aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.cpp28
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.h84
-rw-r--r--contrib/llvm/tools/bugpoint/CrashDebugger.cpp342
-rw-r--r--contrib/llvm/tools/bugpoint/ExecutionDriver.cpp49
-rw-r--r--contrib/llvm/tools/bugpoint/ExtractFunction.cpp39
-rw-r--r--contrib/llvm/tools/bugpoint/FindBugs.cpp8
-rw-r--r--contrib/llvm/tools/bugpoint/Miscompilation.cpp132
-rw-r--r--contrib/llvm/tools/bugpoint/OptimizerDriver.cpp54
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.cpp231
-rw-r--r--contrib/llvm/tools/bugpoint/bugpoint.cpp8
-rw-r--r--contrib/llvm/tools/clang/LICENSE.TXT2
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/BuildSystem.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXString.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Documentation.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h1910
-rw-r--r--contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/APValue.h80
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h645
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h207
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTStructuralEquivalence.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h70
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Attr.h165
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Availability.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def77
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h131
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h74
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CharUnits.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Comment.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentSema.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ComparisonCategories.h243
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DataCollection.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h1016
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h259
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h926
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h302
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h33
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h559
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h574
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h724
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h317
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h117
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/LocInfoType.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Mangle.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NSAPI.h68
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h148
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NonTrivialTypeVisitor.h113
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ODRHash.h15
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h1083
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def40
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ParentMap.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/PrettyDeclStackTrace.h (renamed from contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h)12
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h65
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h102
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h206
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h66
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h590
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h150
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateName.h166
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Type.h655
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h125
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h104
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h1143
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h256
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h72
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h169
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h89
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h63
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h185
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h543
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h173
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h107
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h116
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFG.h291
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/ConstructionContext.h653
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h117
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ABI.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attr.td451
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td283
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrSubjectMatchRules.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attributes.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BitmaskEnum.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def21
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def318
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def3474
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def104
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h13
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Cuda.h21
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DebugInfoOptions.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h548
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td13
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td59
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h84
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td71
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td982
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td85
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Features.def238
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileManager.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h172
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LLVM.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Lambda.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h153
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Linkage.h35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Module.h290
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h66
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenCLOptions.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h96
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h19
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def21
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h145
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h460
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h61
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Stack.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h415
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def61
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Version.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h168
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h125
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Visibility.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/X86Target.def147
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/XRayInstr.h70
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/XRayLists.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/arm_fp16.td131
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td530
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/arm_neon_incl.td316
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitBuilder.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/SwiftCallingConv.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Action.h113
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Compilation.h61
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Distro.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Driver.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Job.h35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Multilib.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td470
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Tool.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h141
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.def3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/Commit.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h19
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h23
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Format/Format.h709
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h372
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h88
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h357
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h23
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Utils.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h13
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/IndexingAction.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h243
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Lexer.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h120
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h224
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h122
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Pragma.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h226
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h414
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h66
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Token.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/Parser.h486
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/RAIIObjectsForParser.h65
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h13
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h19
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h56
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h768
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h485
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h87
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h56
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Initialization.h899
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Lookup.h220
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h110
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Overload.h332
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Ownership.h101
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ParsedAttr.h (renamed from contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h)745
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Scope.h104
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h615
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h1876
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Template.h251
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h148
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TemplateInstCallback.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h137
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Weak.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h1166
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h819
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h273
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/Module.h245
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h106
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td50
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h262
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h260
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h181
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h342
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h36
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h344
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h36
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h353
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h50
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h21
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h194
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h137
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h321
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h322
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h188
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h142
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h (renamed from contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.h)114
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h996
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h91
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h78
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h244
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h89
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h33
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h39
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h150
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h15
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/AllTUsExecution.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h67
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Diagnostic.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h88
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/DiagnosticsYaml.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Execution.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/FixIt.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h137
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/IncludeStyle.h139
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFinder.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h163
-rw-r--r--contrib/llvm/tools/clang/include/clang/module.modulemap6
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp150
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransProtectedScope.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h14
-rw-r--r--contrib/llvm/tools/clang/lib/AST/APValue.cpp79
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp1653
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp3381
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp535
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp97
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Comment.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp248
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentSema.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ComparisonCategories.cpp211
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp266
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp313
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp608
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp204
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp319
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp170
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp1531
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp261
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Mangle.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp350
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NSAPI.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp126
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ODRHash.cpp214
-rw-r--r--contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ParentMap.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp110
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp354
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp269
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp72
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateName.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp860
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp58
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp470
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp628
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp40
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h50
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp179
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp766
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ConstructionContext.cpp217
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp387
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/Dominators.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp163
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ObjCNoReturn.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PostOrderCFGView.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ProgramPoint.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp547
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp194
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Builtins.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Cuda.cpp103
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp183
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Module.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp177
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp309
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h234
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h19
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h46
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp185
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h135
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp104
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h114
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp140
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h49
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h18
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp202
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/X86.h61
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Version.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp363
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Warnings.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h15
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp282
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp67
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp559
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h19
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h39
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp3051
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp394
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h29
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp530
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.h118
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp141
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp66
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp584
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h69
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp568
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp265
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp196
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp508
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp158
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp211
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp215
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h70
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp885
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp230
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp1991
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp275
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h15
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp81
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h33
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp3955
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h517
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp2290
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h165
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h18
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp104
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp1602
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp285
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h24
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGValue.h73
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp55
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp252
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h926
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp996
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h183
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h9
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h23
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp153
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp400
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h3
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp278
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp625
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h12
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Action.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp66
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Distro.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp736
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Multilib.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp198
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp130
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp378
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h32
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp710
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp344
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h24
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Contiki.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp240
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h29
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp655
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.h55
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.cpp350
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.h123
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Lanai.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp129
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp63
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.cpp117
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.h57
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp173
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.h11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Types.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp99
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/Commit.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.h11
-rw-r--r--contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp128
-rw-r--r--contrib/llvm/tools/clang/lib/Format/BreakableToken.h83
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp483
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h160
-rw-r--r--contrib/llvm/tools/clang/lib/Format/Encoding.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Format/Format.cpp754
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatInternal.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.h175
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h12
-rw-r--r--contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h51
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp596
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h12
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h13
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp242
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h23
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h36
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp523
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp205
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp574
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DependencyGraph.cpp41
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp174
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp262
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendTiming.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp94
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp233
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/LayoutOverrideSource.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/HTMLPrint.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp995
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp418
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp122
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp98
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp133
-rw-r--r--contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_builtin_vars.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_device_functions.h1768
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_libdevice_declares.h466
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h95
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h25
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h19
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/ammintrin.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx2intrin.h658
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512bitalgintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h860
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h34
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h660
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h128
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h6515
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512ifmaintrin.h48
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512ifmavlintrin.h116
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512pfintrin.h70
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vbmi2intrin.h130
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vbmiintrin.h66
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vbmivlintrin.h183
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlbitalgintrin.h40
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h977
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h140
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h579
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h5697
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlvbmi2intrin.h364
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlvnniintrin.h237
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vnniintrin.h99
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h40
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avxintrin.h1181
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/bmiintrin.h38
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cetintrin.h22
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cldemoteintrin.h42
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/clwbintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/clzerointrin.h12
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cpuid.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm64
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/emmintrin.h766
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/f16cintrin.h82
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fma4intrin.h70
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fmaintrin.h72
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h16
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/gfniintrin.h112
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/ia32intrin.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/immintrin.h197
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/intrin.h158
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/invpcidintrin.h37
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/lwpintrin.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mm3dnow.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mmintrin.h160
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/module.modulemap20
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/movdirintrin.h63
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mwaitxintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/nmmintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/opencl-c.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pconfigintrin.h50
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pkuintrin.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pmmintrin.h30
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/popcntintrin.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/ptwriteintrin.h51
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/sgxintrin.h70
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/shaintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/smmintrin.h339
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdint.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tmmintrin.h124
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/unwind.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/vaesintrin.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/vpclmulqdqintrin.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/waitpkgintrin.h56
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/wbnoinvdintrin.h38
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/wmmintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/x86intrin.h25
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xmmintrin.h462
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xopintrin.h74
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xtestintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexBody.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp159
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingContext.h15
-rw-r--r--contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp172
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Lexer.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp179
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp486
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp130
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp244
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp141
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp567
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp285
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp344
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp473
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp385
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp316
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp238
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp430
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp101
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp128
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp226
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp322
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp270
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp106
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp (renamed from contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp)162
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp234
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp55
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp579
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp2693
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp2333
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp326
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp1515
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp4363
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp1031
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp591
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp423
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp1587
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp584
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp186
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp456
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp1183
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp305
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp266
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp162
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp3370
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp698
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp229
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp584
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp814
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp730
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp617
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp202
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp233
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp1271
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h713
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h16
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp97
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp1003
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp728
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h70
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp198
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp348
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp101
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/Module.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h22
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationState.h34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp471
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp79
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp152
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp61
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp229
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp318
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp537
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp364
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp140
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp209
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp79
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp223
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp688
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp113
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp2537
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp1244
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp303
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp310
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp72
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp257
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp95
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp1040
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp551
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp224
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp94
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FunctionSummary.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp266
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp303
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp409
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp142
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp455
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp140
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp181
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp272
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/WorkList.cpp254
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp2053
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp174
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/AllTUsExecution.cpp161
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Execution.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Inclusions/CMakeLists.txt12
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp330
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Inclusions/IncludeStyle.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp458
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp196
-rw-r--r--contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp51
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1_main.cpp25
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp86
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1gen_reproducer_main.cpp196
-rw-r--r--contrib/llvm/tools/clang/tools/driver/driver.cpp31
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp306
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp2
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp1083
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangOptionDocEmitter.cpp28
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp2
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp180
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp5
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h1
-rw-r--r--contrib/llvm/tools/llc/llc.cpp96
-rw-r--r--contrib/llvm/tools/lld/COFF/CMakeLists.txt1
-rw-r--r--contrib/llvm/tools/lld/COFF/Chunks.cpp175
-rw-r--r--contrib/llvm/tools/lld/COFF/Chunks.h92
-rw-r--r--contrib/llvm/tools/lld/COFF/Config.h29
-rw-r--r--contrib/llvm/tools/lld/COFF/DLL.cpp2
-rw-r--r--contrib/llvm/tools/lld/COFF/DLL.h5
-rw-r--r--contrib/llvm/tools/lld/COFF/Driver.cpp431
-rw-r--r--contrib/llvm/tools/lld/COFF/Driver.h21
-rw-r--r--contrib/llvm/tools/lld/COFF/DriverUtils.cpp115
-rw-r--r--contrib/llvm/tools/lld/COFF/ICF.cpp96
-rw-r--r--contrib/llvm/tools/lld/COFF/ICF.h (renamed from contrib/llvm/tools/lld/COFF/Strings.h)21
-rw-r--r--contrib/llvm/tools/lld/COFF/InputFiles.cpp146
-rw-r--r--contrib/llvm/tools/lld/COFF/InputFiles.h68
-rw-r--r--contrib/llvm/tools/lld/COFF/LTO.cpp70
-rw-r--r--contrib/llvm/tools/lld/COFF/LTO.h2
-rw-r--r--contrib/llvm/tools/lld/COFF/MapFile.cpp12
-rw-r--r--contrib/llvm/tools/lld/COFF/MarkLive.cpp7
-rw-r--r--contrib/llvm/tools/lld/COFF/MarkLive.h24
-rw-r--r--contrib/llvm/tools/lld/COFF/MinGW.cpp2
-rw-r--r--contrib/llvm/tools/lld/COFF/Options.td29
-rw-r--r--contrib/llvm/tools/lld/COFF/PDB.cpp522
-rw-r--r--contrib/llvm/tools/lld/COFF/PDB.h4
-rw-r--r--contrib/llvm/tools/lld/COFF/Strings.cpp35
-rw-r--r--contrib/llvm/tools/lld/COFF/SymbolTable.cpp96
-rw-r--r--contrib/llvm/tools/lld/COFF/SymbolTable.h6
-rw-r--r--contrib/llvm/tools/lld/COFF/Symbols.cpp8
-rw-r--r--contrib/llvm/tools/lld/COFF/Symbols.h11
-rw-r--r--contrib/llvm/tools/lld/COFF/Writer.cpp825
-rw-r--r--contrib/llvm/tools/lld/COFF/Writer.h16
-rw-r--r--contrib/llvm/tools/lld/Common/Args.cpp18
-rw-r--r--contrib/llvm/tools/lld/Common/CMakeLists.txt1
-rw-r--r--contrib/llvm/tools/lld/Common/ErrorHandler.cpp27
-rw-r--r--contrib/llvm/tools/lld/Common/Strings.cpp77
-rw-r--r--contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp8
-rw-r--r--contrib/llvm/tools/lld/Common/Timer.cpp80
-rw-r--r--contrib/llvm/tools/lld/ELF/AArch64ErrataFix.cpp14
-rw-r--r--contrib/llvm/tools/lld/ELF/AArch64ErrataFix.h1
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/AArch64.cpp57
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/AMDGPU.cpp2
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/ARM.cpp30
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/Hexagon.cpp103
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/Mips.cpp167
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/MipsArchTree.cpp37
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/PPC.cpp7
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp423
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/SPARCV9.cpp12
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/X86.cpp64
-rw-r--r--contrib/llvm/tools/lld/ELF/Arch/X86_64.cpp110
-rw-r--r--contrib/llvm/tools/lld/ELF/CMakeLists.txt4
-rw-r--r--contrib/llvm/tools/lld/ELF/CallGraphSort.cpp249
-rw-r--r--contrib/llvm/tools/lld/ELF/CallGraphSort.h23
-rw-r--r--contrib/llvm/tools/lld/ELF/Config.h54
-rw-r--r--contrib/llvm/tools/lld/ELF/Driver.cpp617
-rw-r--r--contrib/llvm/tools/lld/ELF/Driver.h6
-rw-r--r--contrib/llvm/tools/lld/ELF/DriverUtils.cpp55
-rw-r--r--contrib/llvm/tools/lld/ELF/EhFrame.cpp8
-rw-r--r--contrib/llvm/tools/lld/ELF/Filesystem.cpp2
-rw-r--r--contrib/llvm/tools/lld/ELF/GdbIndex.cpp2
-rw-r--r--contrib/llvm/tools/lld/ELF/GdbIndex.h1
-rw-r--r--contrib/llvm/tools/lld/ELF/ICF.cpp125
-rw-r--r--contrib/llvm/tools/lld/ELF/ICF.h4
-rw-r--r--contrib/llvm/tools/lld/ELF/InputFiles.cpp614
-rw-r--r--contrib/llvm/tools/lld/ELF/InputFiles.h82
-rw-r--r--contrib/llvm/tools/lld/ELF/InputSection.cpp457
-rw-r--r--contrib/llvm/tools/lld/ELF/InputSection.h65
-rw-r--r--contrib/llvm/tools/lld/ELF/LTO.cpp214
-rw-r--r--contrib/llvm/tools/lld/ELF/LTO.h6
-rw-r--r--contrib/llvm/tools/lld/ELF/LinkerScript.cpp389
-rw-r--r--contrib/llvm/tools/lld/ELF/LinkerScript.h53
-rw-r--r--contrib/llvm/tools/lld/ELF/MapFile.cpp213
-rw-r--r--contrib/llvm/tools/lld/ELF/MapFile.h1
-rw-r--r--contrib/llvm/tools/lld/ELF/MarkLive.cpp38
-rw-r--r--contrib/llvm/tools/lld/ELF/MarkLive.h21
-rw-r--r--contrib/llvm/tools/lld/ELF/Options.td524
-rw-r--r--contrib/llvm/tools/lld/ELF/OutputSections.cpp81
-rw-r--r--contrib/llvm/tools/lld/ELF/OutputSections.h14
-rw-r--r--contrib/llvm/tools/lld/ELF/Relocations.cpp823
-rw-r--r--contrib/llvm/tools/lld/ELF/Relocations.h21
-rw-r--r--contrib/llvm/tools/lld/ELF/ScriptLexer.cpp10
-rw-r--r--contrib/llvm/tools/lld/ELF/ScriptParser.cpp291
-rw-r--r--contrib/llvm/tools/lld/ELF/Strings.cpp62
-rw-r--r--contrib/llvm/tools/lld/ELF/Strings.h75
-rw-r--r--contrib/llvm/tools/lld/ELF/SymbolTable.cpp292
-rw-r--r--contrib/llvm/tools/lld/ELF/SymbolTable.h11
-rw-r--r--contrib/llvm/tools/lld/ELF/Symbols.cpp95
-rw-r--r--contrib/llvm/tools/lld/ELF/Symbols.h159
-rw-r--r--contrib/llvm/tools/lld/ELF/SyntheticSections.cpp1535
-rw-r--r--contrib/llvm/tools/lld/ELF/SyntheticSections.h346
-rw-r--r--contrib/llvm/tools/lld/ELF/Target.cpp28
-rw-r--r--contrib/llvm/tools/lld/ELF/Target.h113
-rw-r--r--contrib/llvm/tools/lld/ELF/Thunks.cpp390
-rw-r--r--contrib/llvm/tools/lld/ELF/Thunks.h20
-rw-r--r--contrib/llvm/tools/lld/ELF/Writer.cpp739
-rw-r--r--contrib/llvm/tools/lld/ELF/Writer.h8
-rw-r--r--contrib/llvm/tools/lld/LICENSE.TXT2
-rw-r--r--contrib/llvm/tools/lld/docs/AtomLLD.rst62
-rw-r--r--contrib/llvm/tools/lld/docs/CMakeLists.txt8
-rw-r--r--contrib/llvm/tools/lld/docs/Driver.rst82
-rw-r--r--contrib/llvm/tools/lld/docs/NewLLD.rst309
-rw-r--r--contrib/llvm/tools/lld/docs/README.txt12
-rw-r--r--contrib/llvm/tools/lld/docs/Readers.rst174
-rw-r--r--contrib/llvm/tools/lld/docs/ReleaseNotes.rst43
-rw-r--r--contrib/llvm/tools/lld/docs/WebAssembly.rst36
-rw-r--r--contrib/llvm/tools/lld/docs/_static/favicon.icobin0 -> 1150 bytes
-rw-r--r--contrib/llvm/tools/lld/docs/_templates/indexsidebar.html4
-rw-r--r--contrib/llvm/tools/lld/docs/_templates/layout.html12
-rw-r--r--contrib/llvm/tools/lld/docs/conf.py255
-rw-r--r--contrib/llvm/tools/lld/docs/design.rst421
-rw-r--r--contrib/llvm/tools/lld/docs/development.rst45
-rw-r--r--contrib/llvm/tools/lld/docs/getting_started.rst106
-rw-r--r--contrib/llvm/tools/lld/docs/hello.pngbin0 -> 27616 bytes
-rw-r--r--contrib/llvm/tools/lld/docs/index.rst178
-rw-r--r--contrib/llvm/tools/lld/docs/ld.lld.1577
-rw-r--r--contrib/llvm/tools/lld/docs/llvm-theme/layout.html22
-rw-r--r--contrib/llvm/tools/lld/docs/llvm-theme/static/contents.pngbin0 -> 202 bytes
-rw-r--r--contrib/llvm/tools/lld/docs/llvm-theme/static/llvm.css345
-rw-r--r--contrib/llvm/tools/lld/docs/llvm-theme/static/logo.pngbin0 -> 9865 bytes
-rw-r--r--contrib/llvm/tools/lld/docs/llvm-theme/static/navigation.pngbin0 -> 218 bytes
-rw-r--r--contrib/llvm/tools/lld/docs/llvm-theme/theme.conf4
-rw-r--r--contrib/llvm/tools/lld/docs/make.bat190
-rw-r--r--contrib/llvm/tools/lld/docs/open_projects.rst11
-rw-r--r--contrib/llvm/tools/lld/docs/sphinx_intro.rst127
-rw-r--r--contrib/llvm/tools/lld/docs/windows_support.rst97
-rw-r--r--contrib/llvm/tools/lld/include/lld/Common/Driver.h2
-rw-r--r--contrib/llvm/tools/lld/include/lld/Common/ErrorHandler.h70
-rw-r--r--contrib/llvm/tools/lld/include/lld/Common/Strings.h26
-rw-r--r--contrib/llvm/tools/lld/include/lld/Common/TargetOptionsCommandFlags.h1
-rw-r--r--contrib/llvm/tools/lld/include/lld/Common/Timer.h59
-rw-r--r--contrib/llvm/tools/lld/include/lld/Common/Version.h2
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/DefinedAtom.h44
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/File.h24
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/Instrumentation.h14
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/LinkingContext.h9
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/PassManager.h4
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/Reader.h6
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/Resolver.h6
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/Simple.h2
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/SymbolTable.h22
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/TODO.txt3
-rw-r--r--contrib/llvm/tools/lld/include/lld/Core/Writer.h6
-rw-r--r--contrib/llvm/tools/lld/include/lld/ReaderWriter/MachOLinkingContext.h28
-rw-r--r--contrib/llvm/tools/lld/lib/Core/LinkingContext.cpp4
-rw-r--r--contrib/llvm/tools/lld/lib/Driver/CMakeLists.txt1
-rw-r--r--contrib/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp312
-rw-r--r--contrib/llvm/tools/lld/lib/Driver/DarwinLdOptions.td8
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/FileArchive.cpp6
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp4
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CMakeLists.txt1
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp43
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/MachO/LayoutPass.cpp31
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp14
-rw-r--r--contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp6
-rw-r--r--contrib/llvm/tools/lld/tools/lld/lld.cpp49
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBAddress.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBBroadcaster.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h50
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBData.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBExpressionOptions.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBFrame.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBInstructionList.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBLaunchInfo.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBModule.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h42
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBStream.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBStructuredData.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBSymbol.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBThread.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBValue.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBValueList.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h175
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointID.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointIDList.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointList.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h73
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h73
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointName.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h59
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h64
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h71
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSiteList.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointCallbackContext.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointLocation.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointList.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Address.h202
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h54
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Architecture.h36
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h83
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Communication.h163
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h59
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/DumpRegisterValue.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h104
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Event.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/FileSpecList.h37
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h30
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Mangled.h56
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h219
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Module.h402
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ModuleChild.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h92
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h75
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h58
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h55
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Section.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamBuffer.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeValue.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h73
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/UserSettingsController.h19
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Value.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h74
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h47
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h50
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h81
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionSourceCode.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h24
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h33
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h62
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h22
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h37
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Debug.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Editline.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/File.h81
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Host.h77
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostInfoBase.h53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostProcess.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostThread.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/MainLoop.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/PosixApi.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h350
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/PseudoTerminal.h106
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Socket.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/SocketAddress.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/StringConvert.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/TaskPool.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Terminal.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/XML.h22
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/NativeBreakpoint.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h36
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/NativeRegisterContext.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/NativeThreadProtocol.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/HostInfoPosix.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/PipePosix.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandAlias.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h99
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h85
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h148
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionArgParser.h43
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h265
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompactUnwindInfo.h33
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h114
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h72
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h44
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/DeclVendor.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Declaration.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h45
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h110
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h42
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h65
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h409
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h70
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h123
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h51
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h19
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h38
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h50
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h47
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ABI.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h143
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h395
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContextScope.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Language.h19
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Memory.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/MemoryRegionInfo.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ModuleCache.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/PathMappingList.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Platform.h349
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Process.h934
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ProcessInfo.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ProcessLaunchInfo.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ProcessStructReader.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Queue.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/QueueList.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/RegisterCheckpoint.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/RegisterNumber.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadHistory.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h80
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StackID.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h52
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h136
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Target.h166
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Thread.h138
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadCollection.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h62
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h146
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Args.h (renamed from contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h)321
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Baton.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/CleanUp.h252
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/CompletionRequest.h149
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Connection.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/ConstString.h176
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/DataBuffer.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferHeap.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferLLVM.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/DataEncoder.h102
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/DataExtractor.h356
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Environment.h96
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/FileSpec.h169
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Flags.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/History.h136
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Log.h47
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/RegularExpression.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/SafeMachO.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/SelectHelper.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Status.h80
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Stream.h66
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractorGDBRemote.h (renamed from contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h)10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/StringList.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/StructuredData.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/TildeExpressionResolver.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Timeout.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Timer.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/UUID.h101
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/UserID.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/VMRange.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-defines.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h165
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-forward.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-defines.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h58
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-forward.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-types.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-versioning.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/module.modulemap139
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBAddress.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBBreakpointName.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBDebugger.cpp70
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBEvent.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBFrame.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBHostOS.cpp53
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBInstruction.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBInstructionList.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBLaunchInfo.cpp51
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBModule.cpp63
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBModuleSpec.cpp13
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBPlatform.cpp61
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBProcess.cpp58
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBQueueItem.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBStream.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTarget.cpp96
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBThread.cpp252
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBThreadPlan.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBType.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBValue.cpp43
-rw-r--r--contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp53
-rw-r--r--contrib/llvm/tools/lldb/source/API/SystemInitializerFull.h (renamed from contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h)0
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp133
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp23
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointList.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolver.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp69
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSiteList.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandCompletions.cpp224
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp234
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h52
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp77
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp117
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp205
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h4
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp57
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.cpp39
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp51
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp90
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp117
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp101
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp212
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp132
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.cpp107
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.h25
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.cpp103
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h37
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp245
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp83
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp87
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp72
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Address.cpp103
-rw-r--r--contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Broadcaster.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Communication.cpp23
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Debugger.cpp127
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Disassembler.cpp102
-rw-r--r--contrib/llvm/tools/lldb/source/Core/DumpDataExtractor.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Core/DumpRegisterValue.cpp79
-rw-r--r--contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Event.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Core/FileLineResolver.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Core/FileSpecList.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp104
-rw-r--r--contrib/llvm/tools/lldb/source/Core/IOHandler.cpp173
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Listener.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Mangled.cpp118
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Module.cpp239
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ModuleList.cpp131
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Opcode.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Core/PluginManager.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp77
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Scalar.cpp499
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Section.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Core/SourceManager.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Value.cpp51
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObject.cpp230
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectList.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp27
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp85
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp52
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp376
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/DiagnosticManager.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp74
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp49
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/Materializer.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/REPL.cpp28
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Editline.cpp118
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/File.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Host.cpp42
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp261
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/MainLoop.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/MonitoringProcessLauncher.cpp52
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/NativeBreakpointList.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp97
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/NativeRegisterContext.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/NativeThreadProtocol.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/PseudoTerminal.cpp101
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Socket.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/SoftwareBreakpoint.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp42
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/TaskPool.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Terminal.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/XML.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp23
-rw-r--r--contrib/llvm/tools/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Host/openbsd/Host.cpp13
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp91
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp64
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/HostThreadPosix.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp54
-rw-r--r--contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Args.cpp1500
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandAlias.cpp41
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp413
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp122
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp90
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionArgParser.cpp253
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp28
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormatEntity.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp46
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Options.cpp692
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Property.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp51
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp1217
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp54
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp69
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp69
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h44
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/CMakeLists.txt11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp312
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h60
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h19
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h13
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp204
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h19
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h25
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp62
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h66
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp97
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h81
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp82
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h42
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp142
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.h26
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp164
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h22
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp62
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h105
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp566
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp23
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/CMakeLists.txt11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp406
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h97
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp46
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp119
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp23
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp78
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp198
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp545
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp54
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp207
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp68
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h39
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp560
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp13
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp90
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp37
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp489
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h13
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/CFString.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp58
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/MachException.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp163
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h22
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp54
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp69
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp69
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp134
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h23
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp32
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp59
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp94
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h23
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InstructionUtils.h3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h26
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp25
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp329
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h331
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp57
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp147
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h139
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp59
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp203
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h9
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp322
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp85
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp116
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp140
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp784
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp46
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp206
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.h14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp46
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.h15
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp102
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp124
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp569
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h25
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp291
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp177
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h64
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp911
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp193
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h157
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp1058
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h227
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp205
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h173
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp57
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp300
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h25
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp266
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h70
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp245
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp255
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp146
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h95
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp68
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h69
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp755
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h250
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp272
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h83
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp116
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h26
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp488
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h75
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp1442
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h89
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp149
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp341
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp585
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h45
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp1277
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h65
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp67
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp126
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Block.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp418
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp92
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp95
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp27
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp207
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Function.cpp25
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp22
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp76
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp195
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp59
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp92
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp44
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp117
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Type.cpp49
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp37
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Variable.cpp46
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ABI.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Memory.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ModuleCache.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Target/PathMappingList.cpp101
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Platform.cpp222
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Process.cpp894
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ProcessInfo.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp42
-rw-r--r--contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StackFrame.cpp154
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp138
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StackID.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StopInfo.cpp169
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Target.cpp334
-rw-r--r--contrib/llvm/tools/lldb/source/Target/TargetList.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Thread.cpp204
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadList.cpp162
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanBase.cpp37
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp52
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanPython.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp86
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp93
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp107
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp47
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp32
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp44
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ArchSpec.cpp103
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/Args.cpp726
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/CompletionRequest.cpp60
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ConstString.cpp32
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/DataBufferHeap.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/DataEncoder.cpp78
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/DataExtractor.cpp268
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/Environment.cpp50
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/FastDemangle.cpp126
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/FileSpec.cpp698
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/History.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/JSON.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/Log.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/PPC64_DWARF_Registers.h127
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp43
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/SelectHelper.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/Status.cpp41
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/Stream.cpp70
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp23
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/TildeExpressionResolver.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/UUID.cpp176
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/VASprintf.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/VMRange.cpp10
-rw-r--r--contrib/llvm/tools/lldb/tools/driver/Driver.cpp22
-rw-r--r--contrib/llvm/tools/lldb/tools/driver/Driver.h5
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp58
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp217
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h4
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp339
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h19
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp228
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h4
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp2
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp5
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h1
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp4
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h1
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp4
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp1
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIReadMe.txt8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h4
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/module.modulemap79
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp2
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.cpp33
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.h21
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp5
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp2
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.cpp13
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.cpp166
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.h201
-rw-r--r--contrib/llvm/tools/lli/RemoteJITUtils.h4
-rw-r--r--contrib/llvm/tools/lli/lli.cpp219
-rw-r--r--contrib/llvm/tools/llvm-ar/llvm-ar.cpp296
-rw-r--r--contrib/llvm/tools/llvm-as/llvm-as.cpp51
-rw-r--r--contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp85
-rw-r--r--contrib/llvm/tools/llvm-cov/CodeCoverage.cpp137
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageExporter.h52
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageExporterJson.cpp578
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageExporterJson.h112
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageFilters.cpp12
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageFilters.h33
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageReport.cpp94
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageReport.h15
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h42
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageViewOptions.h16
-rw-r--r--contrib/llvm/tools/llvm-cov/RenderingSupport.h4
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp3
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageView.h64
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp90
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.h4
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageViewText.cpp4
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageViewText.h4
-rw-r--r--contrib/llvm/tools/llvm-cov/TestingSupport.cpp3
-rw-r--r--contrib/llvm/tools/llvm-cov/llvm-cov.cpp22
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/Error.cpp2
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp8
-rw-r--r--contrib/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp6
-rw-r--r--contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp37
-rw-r--r--contrib/llvm/tools/llvm-dis/llvm-dis.cpp50
-rw-r--r--contrib/llvm/tools/llvm-dwarfdump/Statistics.cpp33
-rw-r--r--contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp96
-rw-r--r--contrib/llvm/tools/llvm-extract/llvm-extract.cpp49
-rw-r--r--contrib/llvm/tools/llvm-link/llvm-link.cpp43
-rw-r--r--contrib/llvm/tools/llvm-lto/llvm-lto.cpp33
-rw-r--r--contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp18
-rw-r--r--contrib/llvm/tools/llvm-mc/llvm-mc.cpp261
-rw-r--r--contrib/llvm/tools/llvm-mca/CodeRegion.cpp66
-rw-r--r--contrib/llvm/tools/llvm-mca/CodeRegion.h131
-rw-r--r--contrib/llvm/tools/llvm-mca/Context.cpp63
-rw-r--r--contrib/llvm/tools/llvm-mca/Context.h68
-rw-r--r--contrib/llvm/tools/llvm-mca/DispatchStage.cpp153
-rw-r--r--contrib/llvm/tools/llvm-mca/DispatchStage.h106
-rw-r--r--contrib/llvm/tools/llvm-mca/DispatchStatistics.cpp71
-rw-r--r--contrib/llvm/tools/llvm-mca/DispatchStatistics.h84
-rw-r--r--contrib/llvm/tools/llvm-mca/ExecuteStage.cpp210
-rw-r--r--contrib/llvm/tools/llvm-mca/ExecuteStage.h67
-rw-r--r--contrib/llvm/tools/llvm-mca/FetchStage.cpp46
-rw-r--r--contrib/llvm/tools/llvm-mca/FetchStage.h45
-rw-r--r--contrib/llvm/tools/llvm-mca/HWEventListener.cpp21
-rw-r--r--contrib/llvm/tools/llvm-mca/HWEventListener.h141
-rw-r--r--contrib/llvm/tools/llvm-mca/HardwareUnit.cpp23
-rw-r--r--contrib/llvm/tools/llvm-mca/HardwareUnit.h31
-rw-r--r--contrib/llvm/tools/llvm-mca/InstrBuilder.cpp469
-rw-r--r--contrib/llvm/tools/llvm-mca/InstrBuilder.h85
-rw-r--r--contrib/llvm/tools/llvm-mca/Instruction.cpp177
-rw-r--r--contrib/llvm/tools/llvm-mca/Instruction.h434
-rw-r--r--contrib/llvm/tools/llvm-mca/InstructionInfoView.cpp91
-rw-r--r--contrib/llvm/tools/llvm-mca/InstructionInfoView.h66
-rw-r--r--contrib/llvm/tools/llvm-mca/InstructionTables.cpp70
-rw-r--r--contrib/llvm/tools/llvm-mca/InstructionTables.h43
-rw-r--r--contrib/llvm/tools/llvm-mca/LSUnit.cpp148
-rw-r--r--contrib/llvm/tools/llvm-mca/LSUnit.h147
-rw-r--r--contrib/llvm/tools/llvm-mca/Pipeline.cpp99
-rw-r--r--contrib/llvm/tools/llvm-mca/Pipeline.h79
-rw-r--r--contrib/llvm/tools/llvm-mca/PipelinePrinter.cpp26
-rw-r--r--contrib/llvm/tools/llvm-mca/PipelinePrinter.h52
-rw-r--r--contrib/llvm/tools/llvm-mca/RegisterFile.cpp343
-rw-r--r--contrib/llvm/tools/llvm-mca/RegisterFile.h172
-rw-r--r--contrib/llvm/tools/llvm-mca/RegisterFileStatistics.cpp107
-rw-r--r--contrib/llvm/tools/llvm-mca/RegisterFileStatistics.h67
-rw-r--r--contrib/llvm/tools/llvm-mca/ResourcePressureView.cpp171
-rw-r--r--contrib/llvm/tools/llvm-mca/ResourcePressureView.h109
-rw-r--r--contrib/llvm/tools/llvm-mca/RetireControlUnit.cpp87
-rw-r--r--contrib/llvm/tools/llvm-mca/RetireControlUnit.h98
-rw-r--r--contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.cpp49
-rw-r--r--contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.h60
-rw-r--r--contrib/llvm/tools/llvm-mca/RetireStage.cpp57
-rw-r--r--contrib/llvm/tools/llvm-mca/RetireStage.h48
-rw-r--r--contrib/llvm/tools/llvm-mca/Scheduler.cpp403
-rw-r--r--contrib/llvm/tools/llvm-mca/Scheduler.h515
-rw-r--r--contrib/llvm/tools/llvm-mca/SchedulerStatistics.cpp94
-rw-r--r--contrib/llvm/tools/llvm-mca/SchedulerStatistics.h91
-rw-r--r--contrib/llvm/tools/llvm-mca/SourceMgr.h63
-rw-r--r--contrib/llvm/tools/llvm-mca/Stage.cpp27
-rw-r--r--contrib/llvm/tools/llvm-mca/Stage.h76
-rw-r--r--contrib/llvm/tools/llvm-mca/SummaryView.cpp85
-rw-r--r--contrib/llvm/tools/llvm-mca/SummaryView.h76
-rw-r--r--contrib/llvm/tools/llvm-mca/Support.cpp79
-rw-r--r--contrib/llvm/tools/llvm-mca/Support.h58
-rw-r--r--contrib/llvm/tools/llvm-mca/TimelineView.cpp240
-rw-r--r--contrib/llvm/tools/llvm-mca/TimelineView.h189
-rw-r--r--contrib/llvm/tools/llvm-mca/View.cpp20
-rw-r--r--contrib/llvm/tools/llvm-mca/View.h32
-rw-r--r--contrib/llvm/tools/llvm-mca/llvm-mca.cpp552
-rw-r--r--contrib/llvm/tools/llvm-modextract/llvm-modextract.cpp2
-rw-r--r--contrib/llvm/tools/llvm-nm/llvm-nm.cpp125
-rw-r--r--contrib/llvm/tools/llvm-objcopy/ObjcopyOpts.td99
-rw-r--r--contrib/llvm/tools/llvm-objcopy/Object.cpp1118
-rw-r--r--contrib/llvm/tools/llvm-objcopy/Object.h508
-rw-r--r--contrib/llvm/tools/llvm-objcopy/StripOpts.td49
-rw-r--r--contrib/llvm/tools/llvm-objcopy/llvm-objcopy.cpp679
-rw-r--r--contrib/llvm/tools/llvm-objcopy/llvm-objcopy.h5
-rw-r--r--contrib/llvm/tools/llvm-objdump/COFFDump.cpp4
-rw-r--r--contrib/llvm/tools/llvm-objdump/ELFDump.cpp91
-rw-r--r--contrib/llvm/tools/llvm-objdump/MachODump.cpp407
-rw-r--r--contrib/llvm/tools/llvm-objdump/WasmDump.cpp2
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp1073
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.h7
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/Analyze.cpp2
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/Diff.cpp644
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/Diff.h45
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/DiffPrinter.cpp147
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/DiffPrinter.h172
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp389
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.h4
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp469
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h68
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/InputFile.cpp44
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/InputFile.h11
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp19
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h10
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp25
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp9
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp7
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp95
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp9
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp5
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp3
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp3
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp6
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/StreamUtil.cpp81
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/StreamUtil.h15
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp478
-rw-r--r--contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.h25
-rw-r--r--contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp44
-rw-r--r--contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h13
-rw-r--r--contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp2
-rw-r--r--contrib/llvm/tools/llvm-readobj/COFFDumper.cpp29
-rw-r--r--contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp40
-rw-r--r--contrib/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h245
-rw-r--r--contrib/llvm/tools/llvm-readobj/ELFDumper.cpp734
-rw-r--r--contrib/llvm/tools/llvm-readobj/MachODumper.cpp9
-rw-r--r--contrib/llvm/tools/llvm-readobj/ObjDumper.cpp122
-rw-r--r--contrib/llvm/tools/llvm-readobj/ObjDumper.h13
-rw-r--r--contrib/llvm/tools/llvm-readobj/StackMapPrinter.h49
-rw-r--r--contrib/llvm/tools/llvm-readobj/WasmDumper.cpp40
-rw-r--r--contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp102
-rw-r--r--contrib/llvm/tools/llvm-readobj/llvm-readobj.h1
-rw-r--r--contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp11
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp26
-rw-r--r--contrib/llvm/tools/llvm-xray/func-id-helper.cpp (renamed from contrib/llvm/tools/llvm-xray/func-id-helper.cc)10
-rw-r--r--contrib/llvm/tools/llvm-xray/func-id-helper.h2
-rw-r--r--contrib/llvm/tools/llvm-xray/llvm-xray.cpp (renamed from contrib/llvm/tools/llvm-xray/llvm-xray.cc)2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-account.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-account.cc)145
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-account.h8
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-color-helper.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-color-helper.cc)2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-converter.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-converter.cc)55
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-extract.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-extract.cc)2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-graph-diff.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-graph-diff.cc)2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-graph.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-graph.cc)2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-graph.h2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-registry.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-registry.cc)2
-rw-r--r--contrib/llvm/tools/llvm-xray/xray-stacks.cpp (renamed from contrib/llvm/tools/llvm-xray/xray-stacks.cc)2
-rw-r--r--contrib/llvm/tools/opt/BreakpointPrinter.cpp2
-rw-r--r--contrib/llvm/tools/opt/BreakpointPrinter.h2
-rw-r--r--contrib/llvm/tools/opt/Debugify.cpp357
-rw-r--r--contrib/llvm/tools/opt/Debugify.h75
-rw-r--r--contrib/llvm/tools/opt/NewPMDriver.cpp53
-rw-r--r--contrib/llvm/tools/opt/NewPMDriver.h7
-rw-r--r--contrib/llvm/tools/opt/PassPrinters.cpp2
-rw-r--r--contrib/llvm/tools/opt/PassPrinters.h5
-rw-r--r--contrib/llvm/tools/opt/opt.cpp158
2333 files changed, 178259 insertions, 112505 deletions
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp
index 37bdb7bc96b6..3832e075a693 100644
--- a/contrib/llvm/tools/bugpoint/BugDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/BugDriver.cpp
@@ -55,12 +55,11 @@ cl::opt<std::string> OutputFile("output",
"(for miscompilation detection)"));
}
-/// setNewProgram - If we reduce or update the program somehow, call this method
-/// to update bugdriver with it. This deletes the old module and sets the
-/// specified one as the current program.
-void BugDriver::setNewProgram(Module *M) {
- delete Program;
- Program = M;
+/// If we reduce or update the program somehow, call this method to update
+/// bugdriver with it. This deletes the old module and sets the specified one
+/// as the current program.
+void BugDriver::setNewProgram(std::unique_ptr<Module> M) {
+ Program = std::move(M);
}
/// getPassesString - Turn a list of passes into a string which indicates the
@@ -85,7 +84,6 @@ BugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout,
MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
BugDriver::~BugDriver() {
- delete Program;
if (Interpreter != SafeInterpreter)
delete Interpreter;
delete SafeInterpreter;
@@ -121,6 +119,12 @@ std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename,
return Result;
}
+std::unique_ptr<Module> BugDriver::swapProgramIn(std::unique_ptr<Module> M) {
+ std::unique_ptr<Module> OldProgram = std::move(Program);
+ Program = std::move(M);
+ return OldProgram;
+}
+
// This method takes the specified list of LLVM input files, attempts to load
// them, either as assembly or bitcode, then link them together. It returns
// true on failure (if, for example, an input bitcode file could not be
@@ -131,7 +135,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
assert(!Filenames.empty() && "Must specify at least on input filename!");
// Load the first input file.
- Program = parseInputFile(Filenames[0], Context).release();
+ Program = parseInputFile(Filenames[0], Context);
if (!Program)
return true;
@@ -172,7 +176,7 @@ Error BugDriver::run() {
// miscompilation.
if (!PassesToRun.empty()) {
outs() << "Running selected passes on program to test for crash: ";
- if (runPasses(Program, PassesToRun))
+ if (runPasses(*Program, PassesToRun))
return debugOptimizerCrash();
}
@@ -182,7 +186,7 @@ Error BugDriver::run() {
// Test to see if we have a code generator crash.
outs() << "Running the code generator to test for a crash: ";
- if (Error E = compileProgram(Program)) {
+ if (Error E = compileProgram(*Program)) {
outs() << toString(std::move(E));
return debugCodeGeneratorCrash();
}
@@ -195,7 +199,7 @@ Error BugDriver::run() {
bool CreatedOutput = false;
if (ReferenceOutputFile.empty()) {
outs() << "Generating reference output from raw program: ";
- if (Error E = createReferenceFile(Program)) {
+ if (Error E = createReferenceFile(*Program)) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();
}
@@ -211,7 +215,7 @@ Error BugDriver::run() {
// matches, then we assume there is a miscompilation bug and try to
// diagnose it.
outs() << "*** Checking the code generator...\n";
- Expected<bool> Diff = diffProgram(Program, "", "", false);
+ Expected<bool> Diff = diffProgram(*Program, "", "", false);
if (Error E = Diff.takeError()) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.h b/contrib/llvm/tools/bugpoint/BugDriver.h
index 0e6a9b4f2f38..bc60ae753548 100644
--- a/contrib/llvm/tools/bugpoint/BugDriver.h
+++ b/contrib/llvm/tools/bugpoint/BugDriver.h
@@ -50,7 +50,7 @@ class BugDriver {
LLVMContext &Context;
const char *ToolName; // argv[0] of bugpoint
std::string ReferenceOutputFile; // Name of `good' output file
- Module *Program; // The raw program, linked together
+ std::unique_ptr<Module> Program; // The raw program, linked together
std::vector<std::string> PassesToRun;
AbstractInterpreter *Interpreter; // How to run the program
AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
@@ -128,15 +128,10 @@ public:
///
bool isExecutingJIT();
- Module *getProgram() const { return Program; }
+ Module &getProgram() const { return *Program; }
- /// swapProgramIn - Set the current module to the specified module, returning
- /// the old one.
- Module *swapProgramIn(Module *M) {
- Module *OldProgram = Program;
- Program = M;
- return OldProgram;
- }
+ /// Set the current module to the specified module, returning the old one.
+ std::unique_ptr<Module> swapProgramIn(std::unique_ptr<Module> M);
AbstractInterpreter *switchToSafeInterpreter() {
AbstractInterpreter *Old = Interpreter;
@@ -146,55 +141,47 @@ public:
void switchToInterpreter(AbstractInterpreter *AI) { Interpreter = AI; }
- /// setNewProgram - If we reduce or update the program somehow, call this
- /// method to update bugdriver with it. This deletes the old module and sets
- /// the specified one as the current program.
- void setNewProgram(Module *M);
+ /// If we reduce or update the program somehow, call this method to update
+ /// bugdriver with it. This deletes the old module and sets the specified one
+ /// as the current program.
+ void setNewProgram(std::unique_ptr<Module> M);
/// Try to compile the specified module. This is used for code generation
/// crash testing.
- Error compileProgram(Module *M) const;
+ Error compileProgram(Module &M) const;
- /// executeProgram - This method runs "Program", capturing the output of the
- /// program to a file. A recommended filename may be optionally specified.
- ///
- Expected<std::string> executeProgram(const Module *Program,
+ /// This method runs "Program", capturing the output of the program to a file.
+ /// A recommended filename may be optionally specified.
+ Expected<std::string> executeProgram(const Module &Program,
std::string OutputFilename,
std::string Bitcode,
const std::string &SharedObjects,
AbstractInterpreter *AI) const;
- /// executeProgramSafely - Used to create reference output with the "safe"
- /// backend, if reference output is not provided. If there is a problem with
- /// the code generator (e.g., llc crashes), this will return false and set
- /// Error.
- ///
+ /// Used to create reference output with the "safe" backend, if reference
+ /// output is not provided. If there is a problem with the code generator
+ /// (e.g., llc crashes), this will return false and set Error.
Expected<std::string>
- executeProgramSafely(const Module *Program,
+ executeProgramSafely(const Module &Program,
const std::string &OutputFile) const;
- /// createReferenceFile - calls compileProgram and then records the output
- /// into ReferenceOutputFile. Returns true if reference file created, false
- /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
- /// this function.
- ///
- Error createReferenceFile(Module *M, const std::string &Filename =
+ /// Calls compileProgram and then records the output into ReferenceOutputFile.
+ /// Returns true if reference file created, false otherwise. Note:
+ /// initializeExecutionEnvironment should be called BEFORE this function.
+ Error createReferenceFile(Module &M, const std::string &Filename =
"bugpoint.reference.out-%%%%%%%");
- /// diffProgram - This method executes the specified module and diffs the
- /// output against the file specified by ReferenceOutputFile. If the output
- /// is different, 1 is returned. If there is a problem with the code
- /// generator (e.g., llc crashes), this will return -1 and set Error.
- ///
- Expected<bool> diffProgram(const Module *Program,
+ /// This method executes the specified module and diffs the output against the
+ /// file specified by ReferenceOutputFile. If the output is different, 1 is
+ /// returned. If there is a problem with the code generator (e.g., llc
+ /// crashes), this will return -1 and set Error.
+ Expected<bool> diffProgram(const Module &Program,
const std::string &BitcodeFile = "",
const std::string &SharedObj = "",
bool RemoveBitcode = false) const;
- /// EmitProgressBitcode - This function is used to output M to a file named
- /// "bugpoint-ID.bc".
- ///
- void EmitProgressBitcode(const Module *M, const std::string &ID,
+ /// This function is used to output M to a file named "bugpoint-ID.bc".
+ void EmitProgressBitcode(const Module &M, const std::string &ID,
bool NoFlyer = false) const;
/// This method clones the current Program and deletes the specified
@@ -210,7 +197,7 @@ public:
/// MayModifySemantics argument is true, then the cleanups is allowed to
/// modify how the code behaves.
///
- std::unique_ptr<Module> performFinalCleanups(Module *M,
+ std::unique_ptr<Module> performFinalCleanups(std::unique_ptr<Module> M,
bool MayModifySemantics = false);
/// Given a module, extract up to one loop from it into a new function. This
@@ -243,7 +230,7 @@ public:
/// or failed, unless Quiet is set. ExtraArgs specifies additional arguments
/// to pass to the child bugpoint instance.
///
- bool runPasses(Module *Program, const std::vector<std::string> &PassesToRun,
+ bool runPasses(Module &Program, const std::vector<std::string> &PassesToRun,
std::string &OutputFilename, bool DeleteOutput = false,
bool Quiet = false, unsigned NumExtraArgs = 0,
const char *const *ExtraArgs = nullptr) const;
@@ -252,7 +239,7 @@ public:
/// false indicating whether or not the optimizer crashed on the specified
/// input (true = crashed). Does not produce any output.
///
- bool runPasses(Module *M, const std::vector<std::string> &PassesToRun) const {
+ bool runPasses(Module &M, const std::vector<std::string> &PassesToRun) const {
std::string Filename;
return runPasses(M, PassesToRun, Filename, true);
}
@@ -265,13 +252,12 @@ public:
/// failure.
Error runManyPasses(const std::vector<std::string> &AllPasses);
- /// writeProgramToFile - This writes the current "Program" to the named
- /// bitcode file. If an error occurs, true is returned.
- ///
- bool writeProgramToFile(const std::string &Filename, const Module *M) const;
+ /// This writes the current "Program" to the named bitcode file. If an error
+ /// occurs, true is returned.
+ bool writeProgramToFile(const std::string &Filename, const Module &M) const;
bool writeProgramToFile(const std::string &Filename, int FD,
- const Module *M) const;
- bool writeProgramToFile(int FD, const Module *M) const;
+ const Module &M) const;
+ bool writeProgramToFile(int FD, const Module &M) const;
private:
/// initializeExecutionEnvironment - This method is used to set up the
diff --git a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
index 9097917d5fef..a5b31e1ab321 100644
--- a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
@@ -32,7 +33,6 @@
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
-#include "llvm/Transforms/Utils/Local.h"
#include <set>
using namespace llvm;
@@ -85,16 +85,16 @@ Expected<ReducePassList::TestResult>
ReducePassList::doTest(std::vector<std::string> &Prefix,
std::vector<std::string> &Suffix) {
std::string PrefixOutput;
- Module *OrigProgram = nullptr;
+ std::unique_ptr<Module> OrigProgram;
if (!Prefix.empty()) {
outs() << "Checking to see if these passes crash: "
<< getPassesString(Prefix) << ": ";
if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))
return KeepPrefix;
- OrigProgram = BD.Program;
+ OrigProgram = std::move(BD.Program);
- BD.Program = parseInputFile(PrefixOutput, BD.getContext()).release();
+ BD.Program = parseInputFile(PrefixOutput, BD.getContext());
if (BD.Program == nullptr) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
<< PrefixOutput << "'!\n";
@@ -106,31 +106,27 @@ ReducePassList::doTest(std::vector<std::string> &Prefix,
outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)
<< ": ";
- if (BD.runPasses(BD.getProgram(), Suffix)) {
- delete OrigProgram; // The suffix crashes alone...
- return KeepSuffix;
- }
+ if (BD.runPasses(BD.getProgram(), Suffix))
+ return KeepSuffix; // The suffix crashes alone...
// Nothing failed, restore state...
- if (OrigProgram) {
- delete BD.Program;
- BD.Program = OrigProgram;
- }
+ if (OrigProgram)
+ BD.Program = std::move(OrigProgram);
return NoFailure;
}
+using BugTester = bool (*)(const BugDriver &, Module *);
+
namespace {
-/// ReduceCrashingGlobalVariables - This works by removing the global
-/// variable's initializer and seeing if the program still crashes. If it
-/// does, then we keep that program and try again.
-///
-class ReduceCrashingGlobalVariables : public ListReducer<GlobalVariable *> {
+/// ReduceCrashingGlobalInitializers - This works by removing global variable
+/// initializers and seeing if the program still crashes. If it does, then we
+/// keep that program and try again.
+class ReduceCrashingGlobalInitializers : public ListReducer<GlobalVariable *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
public:
- ReduceCrashingGlobalVariables(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+ ReduceCrashingGlobalInitializers(BugDriver &bd, BugTester testFn)
: BD(bd), TestFn(testFn) {}
Expected<TestResult> doTest(std::vector<GlobalVariable *> &Prefix,
@@ -146,11 +142,11 @@ public:
};
}
-bool ReduceCrashingGlobalVariables::TestGlobalVariables(
+bool ReduceCrashingGlobalInitializers::TestGlobalVariables(
std::vector<GlobalVariable *> &GVs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
std::set<GlobalVariable *> GVSet;
@@ -175,8 +171,8 @@ bool ReduceCrashingGlobalVariables::TestGlobalVariables(
}
// Try running the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use global variable pointers that point into the now-current
// module.
@@ -184,7 +180,6 @@ bool ReduceCrashingGlobalVariables::TestGlobalVariables(
return true;
}
- delete M;
return false;
}
@@ -195,11 +190,10 @@ namespace {
///
class ReduceCrashingFunctions : public ListReducer<Function *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
public:
- ReduceCrashingFunctions(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+ ReduceCrashingFunctions(BugDriver &bd, BugTester testFn)
: BD(bd), TestFn(testFn) {}
Expected<TestResult> doTest(std::vector<Function *> &Prefix,
@@ -241,12 +235,12 @@ static void RemoveFunctionReferences(Module *M, const char *Name) {
bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
// If main isn't present, claim there is no problem.
- if (KeepMain && !is_contained(Funcs, BD.getProgram()->getFunction("main")))
+ if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))
return false;
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
std::set<Function *> Functions;
@@ -305,19 +299,18 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
}
// Finally, remove any null members from any global intrinsic.
- RemoveFunctionReferences(M, "llvm.used");
- RemoveFunctionReferences(M, "llvm.compiler.used");
+ RemoveFunctionReferences(M.get(), "llvm.used");
+ RemoveFunctionReferences(M.get(), "llvm.compiler.used");
}
// Try running the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use function pointers that point into the now-current
// module.
Funcs.assign(Functions.begin(), Functions.end());
return true;
}
- delete M;
return false;
}
@@ -368,11 +361,10 @@ void simpleSimplifyCfg(Function &F, SmallVectorImpl<BasicBlock *> &BBs) {
///
class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
public:
- ReduceCrashingBlocks(BugDriver &BD,
- bool (*testFn)(const BugDriver &, Module *))
+ ReduceCrashingBlocks(BugDriver &BD, BugTester testFn)
: BD(BD), TestFn(testFn) {}
Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
@@ -391,7 +383,7 @@ public:
bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<BasicBlock *, 8> Blocks;
@@ -409,31 +401,32 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
outs() << ": ";
// Loop over and delete any hack up any blocks that are not listed...
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
- for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB)
- if (!Blocks.count(&*BB) && BB->getTerminator()->getNumSuccessors()) {
+ for (Function &F : M->functions()) {
+ for (BasicBlock &BB : F) {
+ if (!Blocks.count(&BB) && BB.getTerminator()->getNumSuccessors()) {
// Loop over all of the successors of this block, deleting any PHI nodes
// that might include it.
- for (succ_iterator SI = succ_begin(&*BB), E = succ_end(&*BB); SI != E;
- ++SI)
- (*SI)->removePredecessor(&*BB);
+ for (BasicBlock *Succ : successors(&BB))
+ Succ->removePredecessor(&BB);
- TerminatorInst *BBTerm = BB->getTerminator();
+ TerminatorInst *BBTerm = BB.getTerminator();
if (BBTerm->isEHPad() || BBTerm->getType()->isTokenTy())
continue;
if (!BBTerm->getType()->isVoidTy())
BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
// Replace the old terminator instruction.
- BB->getInstList().pop_back();
- new UnreachableInst(BB->getContext(), &*BB);
+ BB.getInstList().pop_back();
+ new UnreachableInst(BB.getContext(), &BB);
}
+ }
+ }
// The CFG Simplifier pass may delete one of the basic blocks we are
// interested in. If it does we need to take the block out of the list. Make
// a "persistent mapping" by turning basic blocks into <function, name> pairs.
// This won't work well if blocks are unnamed, but that is just the risk we
- // have to take.
+ // have to take. FIXME: Can we just name the blocks?
std::vector<std::pair<std::string, std::string>> BlockInfo;
for (BasicBlock *BB : Blocks)
@@ -450,31 +443,30 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Verify we didn't break anything
std::vector<std::string> Passes;
Passes.push_back("verify");
- std::unique_ptr<Module> New = BD.runPassesOn(M, Passes);
- delete M;
+ std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
if (!New) {
errs() << "verify failed!\n";
exit(1);
}
- M = New.release();
+ M = std::move(New);
// Try running on the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
- const ValueSymbolTable &GST = M->getValueSymbolTable();
- for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
- Function *F = cast<Function>(GST.lookup(BlockInfo[i].first));
- Value *V = F->getValueSymbolTable()->lookup(BlockInfo[i].second);
+ const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
+ for (const auto &BI : BlockInfo) {
+ Function *F = cast<Function>(GST.lookup(BI.first));
+ Value *V = F->getValueSymbolTable()->lookup(BI.second);
if (V && V->getType() == Type::getLabelTy(V->getContext()))
BBs.push_back(cast<BasicBlock>(V));
}
return true;
}
- delete M; // It didn't crash, try something else.
+ // It didn't crash, try something else.
return false;
}
@@ -486,13 +478,11 @@ namespace {
///
class ReduceCrashingConditionals : public ListReducer<const BasicBlock *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
bool Direction;
public:
- ReduceCrashingConditionals(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *),
- bool Direction)
+ ReduceCrashingConditionals(BugDriver &bd, BugTester testFn, bool Direction)
: BD(bd), TestFn(testFn), Direction(Direction) {}
Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
@@ -512,7 +502,7 @@ bool ReduceCrashingConditionals::TestBlocks(
std::vector<const BasicBlock *> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<const BasicBlock *, 8> Blocks;
@@ -560,22 +550,21 @@ bool ReduceCrashingConditionals::TestBlocks(
// Verify we didn't break anything
std::vector<std::string> Passes;
Passes.push_back("verify");
- std::unique_ptr<Module> New = BD.runPassesOn(M, Passes);
- delete M;
+ std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
if (!New) {
errs() << "verify failed!\n";
exit(1);
}
- M = New.release();
+ M = std::move(New);
// Try running on the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
- const ValueSymbolTable &GST = M->getValueSymbolTable();
+ const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
for (auto &BI : BlockInfo) {
auto *F = cast<Function>(GST.lookup(BI.first));
Value *V = F->getValueSymbolTable()->lookup(BI.second);
@@ -584,7 +573,7 @@ bool ReduceCrashingConditionals::TestBlocks(
}
return true;
}
- delete M; // It didn't crash, try something else.
+ // It didn't crash, try something else.
return false;
}
@@ -594,12 +583,12 @@ namespace {
class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
TargetTransformInfo TTI;
public:
- ReduceSimplifyCFG(BugDriver &bd, bool (*testFn)(const BugDriver &, Module *))
- : BD(bd), TestFn(testFn), TTI(bd.getProgram()->getDataLayout()) {}
+ ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)
+ : BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}
Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
std::vector<const BasicBlock *> &Kept) override {
@@ -617,7 +606,7 @@ public:
bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<const BasicBlock *, 8> Blocks;
@@ -653,22 +642,21 @@ bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Verify we didn't break anything
std::vector<std::string> Passes;
Passes.push_back("verify");
- std::unique_ptr<Module> New = BD.runPassesOn(M, Passes);
- delete M;
+ std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
if (!New) {
errs() << "verify failed!\n";
exit(1);
}
- M = New.release();
+ M = std::move(New);
// Try running on the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
- const ValueSymbolTable &GST = M->getValueSymbolTable();
+ const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
for (auto &BI : BlockInfo) {
auto *F = cast<Function>(GST.lookup(BI.first));
Value *V = F->getValueSymbolTable()->lookup(BI.second);
@@ -677,7 +665,7 @@ bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
}
return true;
}
- delete M; // It didn't crash, try something else.
+ // It didn't crash, try something else.
return false;
}
@@ -687,11 +675,10 @@ namespace {
///
class ReduceCrashingInstructions : public ListReducer<const Instruction *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
public:
- ReduceCrashingInstructions(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+ ReduceCrashingInstructions(BugDriver &bd, BugTester testFn)
: BD(bd), TestFn(testFn) {}
Expected<TestResult> doTest(std::vector<const Instruction *> &Prefix,
@@ -711,7 +698,7 @@ bool ReduceCrashingInstructions::TestInsts(
std::vector<const Instruction *> &Insts) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<Instruction *, 32> Instructions;
@@ -745,8 +732,8 @@ bool ReduceCrashingInstructions::TestInsts(
Passes.run(*M);
// Try running on the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use instruction pointers that point into the now-current
// module, and that they don't include any deleted blocks.
@@ -755,7 +742,7 @@ bool ReduceCrashingInstructions::TestInsts(
Insts.push_back(Inst);
return true;
}
- delete M; // It didn't crash, try something else.
+ // It didn't crash, try something else.
return false;
}
@@ -764,11 +751,10 @@ namespace {
// names to avoid having to convert back and forth every time.
class ReduceCrashingNamedMD : public ListReducer<std::string> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
public:
- ReduceCrashingNamedMD(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+ ReduceCrashingNamedMD(BugDriver &bd, BugTester testFn)
: BD(bd), TestFn(testFn) {}
Expected<TestResult> doTest(std::vector<std::string> &Prefix,
@@ -787,7 +773,7 @@ public:
bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
outs() << "Checking for crash with only these named metadata nodes:";
unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
@@ -821,11 +807,10 @@ bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
Passes.run(*M);
// Try running on the hacked up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
return true;
}
- delete M; // It didn't crash, try something else.
return false;
}
@@ -833,11 +818,10 @@ namespace {
// Reduce the list of operands to named metadata nodes
class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {
BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
+ BugTester TestFn;
public:
- ReduceCrashingNamedMDOps(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+ ReduceCrashingNamedMDOps(BugDriver &bd, BugTester testFn)
: BD(bd), TestFn(testFn) {}
Expected<TestResult> doTest(std::vector<const MDNode *> &Prefix,
@@ -868,11 +852,11 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps(
outs() << " named metadata operands: ";
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// This is a little wasteful. In the future it might be good if we could have
// these dropped during cloning.
- for (auto &NamedMD : BD.getProgram()->named_metadata()) {
+ for (auto &NamedMD : BD.getProgram().named_metadata()) {
// Drop the old one and create a new one
M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
NamedMDNode *NewNamedMDNode =
@@ -888,85 +872,82 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps(
Passes.run(*M);
// Try running on the hacked up program...
- if (TestFn(BD, M)) {
+ if (TestFn(BD, M.get())) {
// Make sure to use instruction pointers that point into the now-current
// module, and that they don't include any deleted blocks.
NamedMDOps.clear();
for (const MDNode *Node : OldMDNodeOps)
NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
return true;
}
- delete M; // It didn't crash, try something else.
+ // It didn't crash, try something else.
return false;
}
-static Error ReduceGlobalInitializers(BugDriver &BD,
- bool (*TestFn)(const BugDriver &,
- Module *)) {
- if (BD.getProgram()->global_begin() != BD.getProgram()->global_end()) {
- // Now try to reduce the number of global variable initializers in the
- // module to something small.
- Module *M = CloneModule(BD.getProgram()).release();
- bool DeletedInit = false;
-
- for (Module::global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I)
- if (I->hasInitializer()) {
- DeleteGlobalInitializer(&*I);
- I->setLinkage(GlobalValue::ExternalLinkage);
- I->setComdat(nullptr);
- DeletedInit = true;
- }
-
- if (!DeletedInit) {
- delete M; // No change made...
- } else {
- // See if the program still causes a crash...
- outs() << "\nChecking to see if we can delete global inits: ";
-
- if (TestFn(BD, M)) { // Still crashes?
- BD.setNewProgram(M);
- outs() << "\n*** Able to remove all global initializers!\n";
- } else { // No longer crashes?
- outs() << " - Removing all global inits hides problem!\n";
- delete M;
-
- std::vector<GlobalVariable *> GVs;
-
- for (Module::global_iterator I = BD.getProgram()->global_begin(),
- E = BD.getProgram()->global_end();
- I != E; ++I)
- if (I->hasInitializer())
- GVs.push_back(&*I);
-
- if (GVs.size() > 1 && !BugpointIsInterrupted) {
- outs() << "\n*** Attempting to reduce the number of global "
- << "variables in the testcase\n";
-
- unsigned OldSize = GVs.size();
- Expected<bool> Result =
- ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs);
- if (Error E = Result.takeError())
- return E;
-
- if (GVs.size() < OldSize)
- BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");
- }
- }
+/// Attempt to eliminate as many global initializers as possible.
+static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
+ Module &OrigM = BD.getProgram();
+ if (OrigM.global_empty())
+ return Error::success();
+
+ // Now try to reduce the number of global variable initializers in the
+ // module to something small.
+ std::unique_ptr<Module> M = CloneModule(OrigM);
+ bool DeletedInit = false;
+
+ for (GlobalVariable &GV : M->globals()) {
+ if (GV.hasInitializer()) {
+ DeleteGlobalInitializer(&GV);
+ GV.setLinkage(GlobalValue::ExternalLinkage);
+ GV.setComdat(nullptr);
+ DeletedInit = true;
}
}
+
+ if (!DeletedInit)
+ return Error::success();
+
+ // See if the program still causes a crash...
+ outs() << "\nChecking to see if we can delete global inits: ";
+
+ if (TestFn(BD, M.get())) { // Still crashes?
+ BD.setNewProgram(std::move(M));
+ outs() << "\n*** Able to remove all global initializers!\n";
+ return Error::success();
+ }
+
+ // No longer crashes.
+ outs() << " - Removing all global inits hides problem!\n";
+
+ std::vector<GlobalVariable *> GVs;
+ for (GlobalVariable &GV : OrigM.globals())
+ if (GV.hasInitializer())
+ GVs.push_back(&GV);
+
+ if (GVs.size() > 1 && !BugpointIsInterrupted) {
+ outs() << "\n*** Attempting to reduce the number of global initializers "
+ << "in the testcase\n";
+
+ unsigned OldSize = GVs.size();
+ Expected<bool> Result =
+ ReduceCrashingGlobalInitializers(BD, TestFn).reduceList(GVs);
+ if (Error E = Result.takeError())
+ return E;
+
+ if (GVs.size() < OldSize)
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");
+ }
return Error::success();
}
-static Error ReduceInsts(BugDriver &BD,
- bool (*TestFn)(const BugDriver &, Module *)) {
+static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
// Attempt to delete instructions using bisection. This should help out nasty
// cases with large basic blocks where the problem is at one end.
if (!BugpointIsInterrupted) {
std::vector<const Instruction *> Insts;
- for (const Function &F : *BD.getProgram())
+ for (const Function &F : BD.getProgram())
for (const BasicBlock &BB : F)
for (const Instruction &I : BB)
if (!isa<TerminatorInst>(&I))
@@ -1001,8 +982,8 @@ static Error ReduceInsts(BugDriver &BD,
// Loop over all of the (non-terminator) instructions remaining in the
// function, attempting to delete them.
unsigned CurInstructionNum = 0;
- for (Module::const_iterator FI = BD.getProgram()->begin(),
- E = BD.getProgram()->end();
+ for (Module::const_iterator FI = BD.getProgram().begin(),
+ E = BD.getProgram().end();
FI != E; ++FI)
if (!FI->isDeclaration())
for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;
@@ -1028,7 +1009,7 @@ static Error ReduceInsts(BugDriver &BD,
if (TestFn(BD, M.get())) {
// Yup, it does, we delete the old module, and continue trying
// to reduce the testcase...
- BD.setNewProgram(M.release());
+ BD.setNewProgram(std::move(M));
InstructionsToSkipBeforeDeleting = CurInstructionNum;
goto TryAgain; // I wish I had a multi-level break here!
}
@@ -1048,8 +1029,7 @@ static Error ReduceInsts(BugDriver &BD,
/// DebugACrash - Given a predicate that determines whether a component crashes
/// on a program, try to destructively reduce the program while still keeping
/// the predicate true.
-static Error DebugACrash(BugDriver &BD,
- bool (*TestFn)(const BugDriver &, Module *)) {
+static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// See if we can get away with nuking some of the global variable initializers
// in the program...
if (!NoGlobalRM)
@@ -1058,7 +1038,7 @@ static Error DebugACrash(BugDriver &BD,
// Now try to reduce the number of functions in the module to something small.
std::vector<Function *> Functions;
- for (Function &F : *BD.getProgram())
+ for (Function &F : BD.getProgram())
if (!F.isDeclaration())
Functions.push_back(&F);
@@ -1080,7 +1060,7 @@ static Error DebugACrash(BugDriver &BD,
// eliminate blocks.
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock *> Blocks;
- for (Function &F : *BD.getProgram())
+ for (Function &F : BD.getProgram())
for (BasicBlock &BB : F)
Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
@@ -1102,7 +1082,7 @@ static Error DebugACrash(BugDriver &BD,
//
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock *> Blocks;
- for (Function &F : *BD.getProgram())
+ for (Function &F : BD.getProgram())
for (BasicBlock &BB : F)
Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
@@ -1115,7 +1095,7 @@ static Error DebugACrash(BugDriver &BD,
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock *> Blocks;
- for (Function &F : *BD.getProgram())
+ for (Function &F : BD.getProgram())
for (BasicBlock &BB : F)
Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
@@ -1137,7 +1117,7 @@ static Error DebugACrash(BugDriver &BD,
std::unique_ptr<Module> M = CloneModule(BD.getProgram());
strip(*M);
if (TestFn(BD, M.get()))
- BD.setNewProgram(M.release());
+ BD.setNewProgram(std::move(M));
};
if (!NoStripDebugInfo && !BugpointIsInterrupted) {
outs() << "\n*** Attempting to strip the debug info: ";
@@ -1154,7 +1134,7 @@ static Error DebugACrash(BugDriver &BD,
// by dropping global named metadata that anchors them
outs() << "\n*** Attempting to remove named metadata: ";
std::vector<std::string> NamedMDNames;
- for (auto &NamedMD : BD.getProgram()->named_metadata())
+ for (auto &NamedMD : BD.getProgram().named_metadata())
NamedMDNames.push_back(NamedMD.getName().str());
Expected<bool> Result =
ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);
@@ -1166,7 +1146,7 @@ static Error DebugACrash(BugDriver &BD,
// Now that we quickly dropped all the named metadata that doesn't
// contribute to the crash, bisect the operands of the remaining ones
std::vector<const MDNode *> NamedMDOps;
- for (auto &NamedMD : BD.getProgram()->named_metadata())
+ for (auto &NamedMD : BD.getProgram().named_metadata())
for (auto op : NamedMD.operands())
NamedMDOps.push_back(op);
Expected<bool> Result =
@@ -1180,15 +1160,13 @@ static Error DebugACrash(BugDriver &BD,
// Try to clean up the testcase by running funcresolve and globaldce...
if (!BugpointIsInterrupted) {
outs() << "\n*** Attempting to perform final cleanups: ";
- Module *M = CloneModule(BD.getProgram()).release();
- M = BD.performFinalCleanups(M, true).release();
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram());
+ M = BD.performFinalCleanups(std::move(M), true);
// Find out if the pass still crashes on the cleaned up program...
- if (TestFn(BD, M)) {
- BD.setNewProgram(M); // Yup, it does, keep the reduced version...
- } else {
- delete M;
- }
+ if (M && TestFn(BD, M.get()))
+ BD.setNewProgram(
+ std::move(M)); // Yup, it does, keep the reduced version...
}
BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");
@@ -1197,7 +1175,7 @@ static Error DebugACrash(BugDriver &BD,
}
static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {
- return BD.runPasses(M, BD.getPassesToRun());
+ return BD.runPasses(*M, BD.getPassesToRun());
}
/// debugOptimizerCrash - This method is called when some pass crashes on input.
@@ -1218,13 +1196,13 @@ Error BugDriver::debugOptimizerCrash(const std::string &ID) {
<< (PassesToRun.size() == 1 ? ": " : "es: ")
<< getPassesString(PassesToRun) << '\n';
- EmitProgressBitcode(Program, ID);
+ EmitProgressBitcode(*Program, ID);
return DebugACrash(*this, TestForOptimizerCrash);
}
static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
- if (Error E = BD.compileProgram(M)) {
+ if (Error E = BD.compileProgram(*M)) {
if (VerboseErrors)
errs() << toString(std::move(E)) << "\n";
else {
diff --git a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
index 7562aa603bbb..773bad69fae0 100644
--- a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
@@ -265,11 +265,9 @@ Error BugDriver::initializeExecutionEnvironment() {
return Error::success();
}
-/// compileProgram - Try to compile the specified module, returning false and
-/// setting Error if an error occurs. This is used for code generation
-/// crash testing.
-///
-Error BugDriver::compileProgram(Module *M) const {
+/// Try to compile the specified module, returning false and setting Error if an
+/// error occurs. This is used for code generation crash testing.
+Error BugDriver::compileProgram(Module &M) const {
// Emit the program to a bitcode file...
auto Temp =
sys::fs::TempFile::create(OutputPrefix + "-test-program-%%%%%%%.bc");
@@ -290,11 +288,10 @@ Error BugDriver::compileProgram(Module *M) const {
return Interpreter->compileProgram(Temp->TmpName, Timeout, MemoryLimit);
}
-/// executeProgram - This method runs "Program", capturing the output of the
-/// program to a file, returning the filename of the file. A recommended
-/// filename may be optionally specified.
-///
-Expected<std::string> BugDriver::executeProgram(const Module *Program,
+/// This method runs "Program", capturing the output of the program to a file,
+/// returning the filename of the file. A recommended filename may be
+/// optionally specified.
+Expected<std::string> BugDriver::executeProgram(const Module &Program,
std::string OutputFile,
std::string BitcodeFile,
const std::string &SharedObj,
@@ -373,11 +370,10 @@ Expected<std::string> BugDriver::executeProgram(const Module *Program,
return OutputFile;
}
-/// executeProgramSafely - Used to create reference output with the "safe"
-/// backend, if reference output is not provided.
-///
+/// Used to create reference output with the "safe" backend, if reference output
+/// is not provided.
Expected<std::string>
-BugDriver::executeProgramSafely(const Module *Program,
+BugDriver::executeProgramSafely(const Module &Program,
const std::string &OutputFile) const {
return executeProgram(Program, OutputFile, "", "", SafeInterpreter);
}
@@ -404,16 +400,14 @@ BugDriver::compileSharedObject(const std::string &BitcodeFile) {
return SharedObjectFile;
}
-/// createReferenceFile - calls compileProgram and then records the output
-/// into ReferenceOutputFile. Returns true if reference file created, false
-/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
-/// this function.
-///
-Error BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
- if (Error E = compileProgram(Program))
+/// Calls compileProgram and then records the output into ReferenceOutputFile.
+/// Returns true if reference file created, false otherwise. Note:
+/// initializeExecutionEnvironment should be called BEFORE this function.
+Error BugDriver::createReferenceFile(Module &M, const std::string &Filename) {
+ if (Error E = compileProgram(*Program))
return E;
- Expected<std::string> Result = executeProgramSafely(Program, Filename);
+ Expected<std::string> Result = executeProgramSafely(*Program, Filename);
if (Error E = Result.takeError()) {
if (Interpreter != SafeInterpreter) {
E = joinErrors(
@@ -432,12 +426,11 @@ Error BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
return Error::success();
}
-/// diffProgram - This method executes the specified module and diffs the
-/// output against the file specified by ReferenceOutputFile. If the output
-/// is different, 1 is returned. If there is a problem with the code
-/// generator (e.g., llc crashes), this will set ErrMsg.
-///
-Expected<bool> BugDriver::diffProgram(const Module *Program,
+/// This method executes the specified module and diffs the output against the
+/// file specified by ReferenceOutputFile. If the output is different, 1 is
+/// returned. If there is a problem with the code generator (e.g., llc
+/// crashes), this will set ErrMsg.
+Expected<bool> BugDriver::diffProgram(const Module &Program,
const std::string &BitcodeFile,
const std::string &SharedObject,
bool RemoveBitcode) const {
diff --git a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
index 431dcedfe203..48f1575c25eb 100644
--- a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
+++ b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
@@ -85,7 +85,7 @@ std::unique_ptr<Module>
BugDriver::deleteInstructionFromProgram(const Instruction *I,
unsigned Simplification) {
// FIXME, use vmap?
- Module *Clone = CloneModule(Program).release();
+ std::unique_ptr<Module> Clone = CloneModule(*Program);
const BasicBlock *PBB = I->getParent();
const Function *PF = PBB->getParent();
@@ -118,8 +118,7 @@ BugDriver::deleteInstructionFromProgram(const Instruction *I,
Passes.push_back("simplifycfg"); // Delete dead control flow
Passes.push_back("verify");
- std::unique_ptr<Module> New = runPassesOn(Clone, Passes);
- delete Clone;
+ std::unique_ptr<Module> New = runPassesOn(Clone.get(), Passes);
if (!New) {
errs() << "Instruction removal failed. Sorry. :( Please report a bug!\n";
exit(1);
@@ -128,7 +127,8 @@ BugDriver::deleteInstructionFromProgram(const Instruction *I,
}
std::unique_ptr<Module>
-BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
+BugDriver::performFinalCleanups(std::unique_ptr<Module> M,
+ bool MayModifySemantics) {
// Make all functions external, so GlobalDCE doesn't delete them...
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
I->setLinkage(GlobalValue::ExternalLinkage);
@@ -141,12 +141,11 @@ BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
else
CleanupPasses.push_back("deadargelim");
- std::unique_ptr<Module> New = runPassesOn(M, CleanupPasses);
+ std::unique_ptr<Module> New = runPassesOn(M.get(), CleanupPasses);
if (!New) {
errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n";
return nullptr;
}
- delete M;
return New;
}
@@ -157,7 +156,7 @@ std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
std::unique_ptr<Module> NewM = runPassesOn(M, LoopExtractPasses);
if (!NewM) {
outs() << "*** Loop extraction failed: ";
- EmitProgressBitcode(M, "loopextraction", true);
+ EmitProgressBitcode(*M, "loopextraction", true);
outs() << "*** Sorry. :( Please report a bug!\n";
return nullptr;
}
@@ -319,15 +318,15 @@ llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
}
ValueToValueMapTy NewVMap;
- std::unique_ptr<Module> New = CloneModule(M, NewVMap);
+ std::unique_ptr<Module> New = CloneModule(*M, NewVMap);
// Remove the Test functions from the Safe module
std::set<Function *> TestFunctions;
for (unsigned i = 0, e = F.size(); i != e; ++i) {
Function *TNOF = cast<Function>(VMap[F[i]]);
- DEBUG(errs() << "Removing function ");
- DEBUG(TNOF->printAsOperand(errs(), false));
- DEBUG(errs() << "\n");
+ LLVM_DEBUG(errs() << "Removing function ");
+ LLVM_DEBUG(TNOF->printAsOperand(errs(), false));
+ LLVM_DEBUG(errs() << "\n");
TestFunctions.insert(cast<Function>(NewVMap[TNOF]));
DeleteFunctionBody(TNOF); // Function is now external in this module!
}
@@ -378,15 +377,21 @@ BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
outs() << "*** Basic Block extraction failed!\n";
errs() << "Error creating temporary file: " << toString(Temp.takeError())
<< "\n";
- EmitProgressBitcode(M, "basicblockextractfail", true);
+ EmitProgressBitcode(*M, "basicblockextractfail", true);
return nullptr;
}
DiscardTemp Discard{*Temp};
+ // Extract all of the blocks except the ones in BBs.
+ SmallVector<BasicBlock *, 32> BlocksToExtract;
+ for (Function &F : *M)
+ for (BasicBlock &BB : F)
+ // Check if this block is going to be extracted.
+ if (std::find(BBs.begin(), BBs.end(), &BB) == BBs.end())
+ BlocksToExtract.push_back(&BB);
+
raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
- for (std::vector<BasicBlock *>::const_iterator I = BBs.begin(), E = BBs.end();
- I != E; ++I) {
- BasicBlock *BB = *I;
+ for (BasicBlock *BB : BBs) {
// If the BB doesn't have a name, give it one so we have something to key
// off of.
if (!BB->hasName())
@@ -396,7 +401,7 @@ BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
OS.flush();
if (OS.has_error()) {
errs() << "Error writing list of blocks to not extract\n";
- EmitProgressBitcode(M, "basicblockextractfail", true);
+ EmitProgressBitcode(*M, "basicblockextractfail", true);
OS.clear_error();
return nullptr;
}
@@ -411,7 +416,7 @@ BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
if (!Ret) {
outs() << "*** Basic Block extraction failed, please report a bug!\n";
- EmitProgressBitcode(M, "basicblockextractfail", true);
+ EmitProgressBitcode(*M, "basicblockextractfail", true);
}
return Ret;
}
diff --git a/contrib/llvm/tools/bugpoint/FindBugs.cpp b/contrib/llvm/tools/bugpoint/FindBugs.cpp
index 40502cbf9495..a695e875b787 100644
--- a/contrib/llvm/tools/bugpoint/FindBugs.cpp
+++ b/contrib/llvm/tools/bugpoint/FindBugs.cpp
@@ -32,7 +32,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
outs() << "\n";
if (ReferenceOutputFile.empty()) {
outs() << "Generating reference output from raw program: \n";
- if (Error E = createReferenceFile(Program))
+ if (Error E = createReferenceFile(*Program))
return E;
}
@@ -53,7 +53,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
}
std::string Filename;
- if (runPasses(Program, PassesToRun, Filename, false)) {
+ if (runPasses(*Program, PassesToRun, Filename, false)) {
outs() << "\n";
outs() << "Optimizer passes caused failure!\n\n";
return debugOptimizerCrash();
@@ -65,7 +65,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
// Step 3: Compile the optimized code.
//
outs() << "Running the code generator to test for a crash: ";
- if (Error E = compileProgram(Program)) {
+ if (Error E = compileProgram(*Program)) {
outs() << "\n*** compileProgram threw an exception: ";
outs() << toString(std::move(E));
return debugCodeGeneratorCrash();
@@ -77,7 +77,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
// output (created above).
//
outs() << "*** Checking if passes caused miscompliation:\n";
- Expected<bool> Diff = diffProgram(Program, Filename, "", false);
+ Expected<bool> Diff = diffProgram(*Program, Filename, "", false);
if (Error E = Diff.takeError()) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();
diff --git a/contrib/llvm/tools/bugpoint/Miscompilation.cpp b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
index 80f4cea23481..375bee7a0d50 100644
--- a/contrib/llvm/tools/bugpoint/Miscompilation.cpp
+++ b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
@@ -152,8 +152,8 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
<< "' passes compile correctly after the '" << getPassesString(Prefix)
<< "' passes: ";
- std::unique_ptr<Module> OriginalInput(
- BD.swapProgramIn(PrefixOutput.release()));
+ std::unique_ptr<Module> OriginalInput =
+ BD.swapProgramIn(std::move(PrefixOutput));
if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false /*delete*/,
true /*quiet*/)) {
errs() << " Error running this sequence of passes"
@@ -179,7 +179,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
// Otherwise, we must not be running the bad pass anymore.
outs() << " yup.\n"; // No miscompilation!
// Restore orig program & free test.
- delete BD.swapProgramIn(OriginalInput.release());
+ BD.setNewProgram(std::move(OriginalInput));
return NoFailure;
}
@@ -230,23 +230,22 @@ static Expected<std::unique_ptr<Module>> testMergedProgram(const BugDriver &BD,
const Module &M2,
bool &Broken) {
// Resulting merge of M1 and M2.
- auto Merged = CloneModule(&M1);
- if (Linker::linkModules(*Merged, CloneModule(&M2)))
+ auto Merged = CloneModule(M1);
+ if (Linker::linkModules(*Merged, CloneModule(M2)))
// TODO: Shouldn't we thread the error up instead of exiting?
exit(1);
// Execute the program.
- Expected<bool> Diff = BD.diffProgram(Merged.get(), "", "", false);
+ Expected<bool> Diff = BD.diffProgram(*Merged, "", "", false);
if (Error E = Diff.takeError())
return std::move(E);
Broken = *Diff;
return std::move(Merged);
}
-/// TestFuncs - split functions in a Module into two groups: those that are
-/// under consideration for miscompilation vs. those that are not, and test
+/// split functions in a Module into two groups: those that are under
+/// consideration for miscompilation vs. those that are not, and test
/// accordingly. Each group of functions becomes a separate Module.
-///
Expected<bool>
ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function *> &Funcs) {
// Test to see if the function is misoptimized if we ONLY run it on the
@@ -266,8 +265,8 @@ ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function *> &Funcs) {
// we can conclude that a function triggers the bug when in fact one
// needs a larger set of original functions to do so.
ValueToValueMapTy VMap;
- Module *Clone = CloneModule(BD.getProgram(), VMap).release();
- Module *Orig = BD.swapProgramIn(Clone);
+ std::unique_ptr<Module> Clone = CloneModule(BD.getProgram(), VMap);
+ std::unique_ptr<Module> Orig = BD.swapProgramIn(std::move(Clone));
std::vector<Function *> FuncsOnClone;
for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
@@ -284,19 +283,18 @@ ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function *> &Funcs) {
Expected<bool> Broken =
TestFn(BD, std::move(ToOptimize), std::move(ToNotOptimize));
- delete BD.swapProgramIn(Orig);
+ BD.setNewProgram(std::move(Orig));
return Broken;
}
-/// DisambiguateGlobalSymbols - Give anonymous global values names.
-///
-static void DisambiguateGlobalSymbols(Module *M) {
- for (Module::global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I)
+/// Give anonymous global values names.
+static void DisambiguateGlobalSymbols(Module &M) {
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;
+ ++I)
if (!I->hasName())
I->setName("anon_global");
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!I->hasName())
I->setName("anon_fn");
}
@@ -317,17 +315,14 @@ ExtractLoops(BugDriver &BD,
ValueToValueMapTy VMap;
std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize.get(),
- MiscompiledFunctions, VMap)
- .release();
+ std::unique_ptr<Module> ToOptimize = SplitFunctionsOutOfModule(
+ ToNotOptimize.get(), MiscompiledFunctions, VMap);
std::unique_ptr<Module> ToOptimizeLoopExtracted =
- BD.extractLoop(ToOptimize);
- if (!ToOptimizeLoopExtracted) {
+ BD.extractLoop(ToOptimize.get());
+ if (!ToOptimizeLoopExtracted)
// If the loop extractor crashed or if there were no extractible loops,
// then this chapter of our odyssey is over with.
- delete ToOptimize;
return MadeChange;
- }
errs() << "Extracted a loop from the breaking portion of the program.\n";
@@ -346,10 +341,9 @@ ExtractLoops(BugDriver &BD,
return false;
// Delete the original and set the new program.
- Module *Old = BD.swapProgramIn(New->release());
+ std::unique_ptr<Module> Old = BD.swapProgramIn(std::move(*New));
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
- delete Old;
if (Failure) {
BD.switchToInterpreter(AI);
@@ -360,25 +354,23 @@ ExtractLoops(BugDriver &BD,
errs() << " Continuing on with un-loop-extracted version.\n";
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
- ToNotOptimize.get());
+ *ToNotOptimize);
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
- ToOptimize);
+ *ToOptimize);
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
- ToOptimizeLoopExtracted.get());
+ *ToOptimizeLoopExtracted);
errs() << "Please submit the " << OutputPrefix
<< "-loop-extract-fail-*.bc files.\n";
- delete ToOptimize;
return MadeChange;
}
- delete ToOptimize;
BD.switchToInterpreter(AI);
outs() << " Testing after loop extraction:\n";
// Clone modules, the tester function will free them.
std::unique_ptr<Module> TOLEBackup =
- CloneModule(ToOptimizeLoopExtracted.get(), VMap);
- std::unique_ptr<Module> TNOBackup = CloneModule(ToNotOptimize.get(), VMap);
+ CloneModule(*ToOptimizeLoopExtracted, VMap);
+ std::unique_ptr<Module> TNOBackup = CloneModule(*ToNotOptimize, VMap);
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
@@ -413,7 +405,7 @@ ExtractLoops(BugDriver &BD,
MiscompiledFunctions.push_back(NewF);
}
- BD.setNewProgram(ToNotOptimize.release());
+ BD.setNewProgram(std::move(ToNotOptimize));
return MadeChange;
}
@@ -444,7 +436,7 @@ ExtractLoops(BugDriver &BD,
MiscompiledFunctions.push_back(NewF);
}
- BD.setNewProgram(ToNotOptimize.release());
+ BD.setNewProgram(std::move(ToNotOptimize));
MadeChange = true;
}
}
@@ -508,8 +500,8 @@ ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) {
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
- Module *Clone = CloneModule(BD.getProgram(), VMap).release();
- Module *Orig = BD.swapProgramIn(Clone);
+ std::unique_ptr<Module> Clone = CloneModule(BD.getProgram(), VMap);
+ std::unique_ptr<Module> Orig = BD.swapProgramIn(std::move(Clone));
std::vector<Function *> FuncsOnClone;
std::vector<BasicBlock *> BBsOnClone;
for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) {
@@ -531,10 +523,10 @@ ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) {
if (std::unique_ptr<Module> New =
BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize.get())) {
Expected<bool> Ret = TestFn(BD, std::move(New), std::move(ToNotOptimize));
- delete BD.swapProgramIn(Orig);
+ BD.setNewProgram(std::move(Orig));
return Ret;
}
- delete BD.swapProgramIn(Orig);
+ BD.setNewProgram(std::move(Orig));
return false;
}
@@ -577,23 +569,19 @@ ExtractBlocks(BugDriver &BD,
}
ValueToValueMapTy VMap;
- Module *ProgClone = CloneModule(BD.getProgram(), VMap).release();
- Module *ToExtract =
- SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap)
- .release();
+ std::unique_ptr<Module> ProgClone = CloneModule(BD.getProgram(), VMap);
+ std::unique_ptr<Module> ToExtract =
+ SplitFunctionsOutOfModule(ProgClone.get(), MiscompiledFunctions, VMap);
std::unique_ptr<Module> Extracted =
- BD.extractMappedBlocksFromModule(Blocks, ToExtract);
+ BD.extractMappedBlocksFromModule(Blocks, ToExtract.get());
if (!Extracted) {
// Weird, extraction should have worked.
errs() << "Nondeterministic problem extracting blocks??\n";
- delete ProgClone;
- delete ToExtract;
return false;
}
// Otherwise, block extraction succeeded. Link the two program fragments back
// together.
- delete ToExtract;
std::vector<std::pair<std::string, FunctionType *>> MisCompFunctions;
for (Module::iterator I = Extracted->begin(), E = Extracted->end(); I != E;
@@ -605,7 +593,7 @@ ExtractBlocks(BugDriver &BD,
exit(1);
// Set the new program and delete the old one.
- BD.setNewProgram(ProgClone);
+ BD.setNewProgram(std::move(ProgClone));
// Update the list of miscompiled functions.
MiscompiledFunctions.clear();
@@ -631,8 +619,8 @@ static Expected<std::vector<Function *>> DebugAMiscompilation(
// miscompiled... first build a list of all of the non-external functions in
// the program.
std::vector<Function *> MiscompiledFunctions;
- Module *Prog = BD.getProgram();
- for (Function &F : *Prog)
+ Module &Prog = BD.getProgram();
+ for (Function &F : Prog)
if (!F.isDeclaration())
MiscompiledFunctions.push_back(&F);
@@ -718,8 +706,8 @@ static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
if (!Optimized) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
- delete BD.swapProgramIn(Test.get());
- BD.EmitProgressBitcode(Test.get(), "pass-error", false);
+ BD.setNewProgram(std::move(Test));
+ BD.EmitProgressBitcode(*Test, "pass-error", false);
if (Error E = BD.debugOptimizerCrash())
return std::move(E);
return false;
@@ -734,7 +722,7 @@ static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
if (auto New = std::move(*Result)) {
outs() << (Broken ? " nope.\n" : " yup.\n");
// Delete the original and set the new program.
- delete BD.swapProgramIn(New.release());
+ BD.setNewProgram(std::move(New));
}
return Broken;
}
@@ -760,7 +748,7 @@ Error BugDriver::debugMiscompilation() {
outs() << "\n*** Found miscompiling pass"
<< (getPassesToRun().size() == 1 ? "" : "es") << ": "
<< getPassesString(getPassesToRun()) << '\n';
- EmitProgressBitcode(Program, "passinput");
+ EmitProgressBitcode(*Program, "passinput");
Expected<std::vector<Function *>> MiscompiledFunctions =
DebugAMiscompilation(*this, TestOptimizer);
@@ -776,11 +764,11 @@ Error BugDriver::debugMiscompilation() {
.release();
outs() << " Non-optimized portion: ";
- EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true);
+ EmitProgressBitcode(*ToNotOptimize, "tonotoptimize", true);
delete ToNotOptimize; // Delete hacked module.
outs() << " Portion that is input to optimizer: ";
- EmitProgressBitcode(ToOptimize, "tooptimize");
+ EmitProgressBitcode(*ToOptimize, "tooptimize");
delete ToOptimize; // Delete hacked module.
return Error::success();
@@ -788,15 +776,15 @@ Error BugDriver::debugMiscompilation() {
/// Get the specified modules ready for code generator testing.
///
-static void CleanupAndPrepareModules(BugDriver &BD,
- std::unique_ptr<Module> &Test,
- Module *Safe) {
+static std::unique_ptr<Module>
+CleanupAndPrepareModules(BugDriver &BD, std::unique_ptr<Module> Test,
+ Module *Safe) {
// Clean up the modules, removing extra cruft that we don't need anymore...
- Test = BD.performFinalCleanups(Test.get());
+ Test = BD.performFinalCleanups(std::move(Test));
// If we are executing the JIT, we have several nasty issues to take care of.
if (!BD.isExecutingJIT())
- return;
+ return Test;
// First, if the main function is in the Safe module, we must add a stub to
// the Test module to call into it. Thus, we create a new function `main'
@@ -942,6 +930,8 @@ static void CleanupAndPrepareModules(BugDriver &BD,
errs() << "Bugpoint has a bug, which corrupted a module!!\n";
abort();
}
+
+ return Test;
}
/// This is the predicate function used to check to see if the "Test" portion of
@@ -951,7 +941,7 @@ static void CleanupAndPrepareModules(BugDriver &BD,
static Expected<bool> TestCodeGenerator(BugDriver &BD,
std::unique_ptr<Module> Test,
std::unique_ptr<Module> Safe) {
- CleanupAndPrepareModules(BD, Test, Safe.get());
+ Test = CleanupAndPrepareModules(BD, std::move(Test), Safe.get());
SmallString<128> TestModuleBC;
int TestModuleFD;
@@ -962,7 +952,7 @@ static Expected<bool> TestCodeGenerator(BugDriver &BD,
<< "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
- if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test.get())) {
+ if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, *Test)) {
errs() << "Error writing bitcode to `" << TestModuleBC.str()
<< "'\nExiting.";
exit(1);
@@ -981,7 +971,7 @@ static Expected<bool> TestCodeGenerator(BugDriver &BD,
exit(1);
}
- if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) {
+ if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, *Safe)) {
errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
exit(1);
}
@@ -1015,7 +1005,7 @@ static Expected<bool> TestCodeGenerator(BugDriver &BD,
Error BugDriver::debugCodeGenerator() {
if ((void *)SafeInterpreter == (void *)Interpreter) {
Expected<std::string> Result =
- executeProgramSafely(Program, "bugpoint.safe.out");
+ executeProgramSafely(*Program, "bugpoint.safe.out");
if (Result) {
outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
<< "the reference diff. This may be due to a\n front-end "
@@ -1028,7 +1018,7 @@ Error BugDriver::debugCodeGenerator() {
return Error::success();
}
- DisambiguateGlobalSymbols(Program);
+ DisambiguateGlobalSymbols(*Program);
Expected<std::vector<Function *>> Funcs =
DebugAMiscompilation(*this, TestCodeGenerator);
@@ -1042,7 +1032,8 @@ Error BugDriver::debugCodeGenerator() {
SplitFunctionsOutOfModule(ToNotCodeGen.get(), *Funcs, VMap);
// Condition the modules
- CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen.get());
+ ToCodeGen =
+ CleanupAndPrepareModules(*this, std::move(ToCodeGen), ToNotCodeGen.get());
SmallString<128> TestModuleBC;
int TestModuleFD;
@@ -1054,7 +1045,7 @@ Error BugDriver::debugCodeGenerator() {
exit(1);
}
- if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen.get())) {
+ if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, *ToCodeGen)) {
errs() << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
exit(1);
}
@@ -1070,8 +1061,7 @@ Error BugDriver::debugCodeGenerator() {
exit(1);
}
- if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD,
- ToNotCodeGen.get())) {
+ if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, *ToNotCodeGen)) {
errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
exit(1);
}
diff --git a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
index ee3f2f0174d2..cbb048db8fe7 100644
--- a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -43,18 +43,14 @@ static cl::opt<bool> PreserveBitcodeUseListOrder(
cl::desc("Preserve use-list order when writing LLVM bitcode."),
cl::init(true), cl::Hidden);
-// ChildOutput - This option captures the name of the child output file that
-// is set up by the parent bugpoint process
-static cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden);
static cl::opt<std::string>
OptCmd("opt-command", cl::init(""),
cl::desc("Path to opt. (default: search path "
"for 'opt'.)"));
-/// writeProgramToFile - This writes the current "Program" to the named bitcode
-/// file. If an error occurs, true is returned.
-///
-static bool writeProgramToFileAux(ToolOutputFile &Out, const Module *M) {
+/// This writes the current "Program" to the named bitcode file. If an error
+/// occurs, true is returned.
+static bool writeProgramToFileAux(ToolOutputFile &Out, const Module &M) {
WriteBitcodeToFile(M, Out.os(), PreserveBitcodeUseListOrder);
Out.os().close();
if (!Out.os().has_error()) {
@@ -65,12 +61,12 @@ static bool writeProgramToFileAux(ToolOutputFile &Out, const Module *M) {
}
bool BugDriver::writeProgramToFile(const std::string &Filename, int FD,
- const Module *M) const {
+ const Module &M) const {
ToolOutputFile Out(Filename, FD);
return writeProgramToFileAux(Out, M);
}
-bool BugDriver::writeProgramToFile(int FD, const Module *M) const {
+bool BugDriver::writeProgramToFile(int FD, const Module &M) const {
raw_fd_ostream OS(FD, /*shouldClose*/ false);
WriteBitcodeToFile(M, OS, PreserveBitcodeUseListOrder);
OS.flush();
@@ -81,7 +77,7 @@ bool BugDriver::writeProgramToFile(int FD, const Module *M) const {
}
bool BugDriver::writeProgramToFile(const std::string &Filename,
- const Module *M) const {
+ const Module &M) const {
std::error_code EC;
ToolOutputFile Out(Filename, EC, sys::fs::F_None);
if (!EC)
@@ -89,10 +85,9 @@ bool BugDriver::writeProgramToFile(const std::string &Filename,
return true;
}
-/// EmitProgressBitcode - This function is used to output the current Program
-/// to a file named "bugpoint-ID.bc".
-///
-void BugDriver::EmitProgressBitcode(const Module *M, const std::string &ID,
+/// This function is used to output the current Program to a file named
+/// "bugpoint-ID.bc".
+void BugDriver::EmitProgressBitcode(const Module &M, const std::string &ID,
bool NoFlyer) const {
// Output the input to the current pass to a bitcode file, emit a message
// telling the user how to reproduce it: opt -foo blah.bc
@@ -132,7 +127,7 @@ static cl::list<std::string> OptArgs("opt-args", cl::Positional,
/// outs() a single line message indicating whether compilation was successful
/// or failed.
///
-bool BugDriver::runPasses(Module *Program,
+bool BugDriver::runPasses(Module &Program,
const std::vector<std::string> &Passes,
std::string &OutputFilename, bool DeleteOutput,
bool Quiet, unsigned NumExtraArgs,
@@ -180,6 +175,10 @@ bool BugDriver::runPasses(Module *Program,
errs() << "Cannot find `opt' in PATH!\n";
return 1;
}
+ if (!sys::fs::exists(tool)) {
+ errs() << "Specified `opt' binary does not exist: " << tool << "\n";
+ return 1;
+ }
std::string Prog;
if (UseValgrind) {
@@ -195,20 +194,20 @@ bool BugDriver::runPasses(Module *Program,
}
// setup the child process' arguments
- SmallVector<const char *, 8> Args;
+ SmallVector<StringRef, 8> Args;
if (UseValgrind) {
Args.push_back("valgrind");
Args.push_back("--error-exitcode=1");
Args.push_back("-q");
- Args.push_back(tool.c_str());
+ Args.push_back(tool);
} else
- Args.push_back(tool.c_str());
+ Args.push_back(tool);
for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
- Args.push_back(OptArgs[i].c_str());
+ Args.push_back(OptArgs[i]);
Args.push_back("-disable-symbolication");
Args.push_back("-o");
- Args.push_back(OutputFilename.c_str());
+ Args.push_back(OutputFilename);
std::vector<std::string> pass_args;
for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
pass_args.push_back(std::string("-load"));
@@ -225,12 +224,11 @@ bool BugDriver::runPasses(Module *Program,
Args.push_back(Temp->TmpName.c_str());
for (unsigned i = 0; i < NumExtraArgs; ++i)
Args.push_back(*ExtraArgs);
- Args.push_back(nullptr);
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs()
- << " " << Args[i];
- errs() << "\n";);
+ LLVM_DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs()
+ << " " << Args[i];
+ errs() << "\n";);
Optional<StringRef> Redirects[3] = {None, None, None};
// Redirect stdout and stderr to nowhere if SilencePasses is given.
@@ -240,8 +238,8 @@ bool BugDriver::runPasses(Module *Program,
}
std::string ErrMsg;
- int result = sys::ExecuteAndWait(Prog, Args.data(), nullptr, Redirects,
- Timeout, MemoryLimit, &ErrMsg);
+ int result = sys::ExecuteAndWait(Prog, Args, None, Redirects, Timeout,
+ MemoryLimit, &ErrMsg);
// If we are supposed to delete the bitcode file or if the passes crashed,
// remove it now. This may fail if the file was never created, but that's ok.
@@ -271,7 +269,7 @@ std::unique_ptr<Module>
BugDriver::runPassesOn(Module *M, const std::vector<std::string> &Passes,
unsigned NumExtraArgs, const char *const *ExtraArgs) {
std::string BitcodeResult;
- if (runPasses(M, Passes, BitcodeResult, false /*delete*/, true /*quiet*/,
+ if (runPasses(*M, Passes, BitcodeResult, false /*delete*/, true /*quiet*/,
NumExtraArgs, ExtraArgs)) {
return nullptr;
}
diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.cpp b/contrib/llvm/tools/bugpoint/ToolRunner.cpp
index 8094dfdd78fa..812e8e3bbae5 100644
--- a/contrib/llvm/tools/bugpoint/ToolRunner.cpp
+++ b/contrib/llvm/tools/bugpoint/ToolRunner.cpp
@@ -53,13 +53,14 @@ cl::opt<std::string>
/// RunProgramWithTimeout - This function provides an alternate interface
/// to the sys::Program::ExecuteAndWait interface.
/// @see sys::Program::ExecuteAndWait
-static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args,
- StringRef StdInFile, StringRef StdOutFile,
- StringRef StdErrFile, unsigned NumSeconds = 0,
+static int RunProgramWithTimeout(StringRef ProgramPath,
+ ArrayRef<StringRef> Args, StringRef StdInFile,
+ StringRef StdOutFile, StringRef StdErrFile,
+ unsigned NumSeconds = 0,
unsigned MemoryLimit = 0,
std::string *ErrMsg = nullptr) {
Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
- return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds,
+ return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds,
MemoryLimit, ErrMsg);
}
@@ -69,24 +70,22 @@ static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args,
/// fails. Remote client is required to return 255 if it failed or program exit
/// code otherwise.
/// @see sys::Program::ExecuteAndWait
-static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
- const char **Args, StringRef StdInFile,
- StringRef StdOutFile,
- StringRef StdErrFile,
- unsigned NumSeconds = 0,
- unsigned MemoryLimit = 0) {
+static int RunProgramRemotelyWithTimeout(
+ StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile,
+ StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0,
+ unsigned MemoryLimit = 0) {
Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
// Run the program remotely with the remote client
- int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr,
- Redirects, NumSeconds, MemoryLimit);
+ int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects,
+ NumSeconds, MemoryLimit);
// Has the remote client fail?
if (255 == ReturnCode) {
std::ostringstream OS;
OS << "\nError running remote client:\n ";
- for (const char **Arg = Args; *Arg; ++Arg)
- OS << " " << *Arg;
+ for (StringRef Arg : Args)
+ OS << " " << Arg.str();
OS << "\n";
// The error message is in the output file, let's print it out from there.
@@ -105,12 +104,12 @@ static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
return ReturnCode;
}
-static Error ProcessFailure(StringRef ProgPath, const char **Args,
+static Error ProcessFailure(StringRef ProgPath, ArrayRef<StringRef> Args,
unsigned Timeout = 0, unsigned MemoryLimit = 0) {
std::ostringstream OS;
OS << "\nError running tool:\n ";
- for (const char **Arg = Args; *Arg; ++Arg)
- OS << " " << *Arg;
+ for (StringRef Arg : Args)
+ OS << " " << Arg.str();
OS << "\n";
// Rerun the compiler, capturing any error messages to print them.
@@ -171,7 +170,7 @@ Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &CCArgs,
const std::vector<std::string> &SharedLibs,
unsigned Timeout, unsigned MemoryLimit) {
- std::vector<const char *> LLIArgs;
+ std::vector<StringRef> LLIArgs;
LLIArgs.push_back(LLIPath.c_str());
LLIArgs.push_back("-force-interpreter=true");
@@ -179,26 +178,25 @@ Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
e = SharedLibs.end();
i != e; ++i) {
LLIArgs.push_back("-load");
- LLIArgs.push_back((*i).c_str());
+ LLIArgs.push_back(*i);
}
// Add any extra LLI args.
for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
- LLIArgs.push_back(ToolArgs[i].c_str());
+ LLIArgs.push_back(ToolArgs[i]);
- LLIArgs.push_back(Bitcode.c_str());
+ LLIArgs.push_back(Bitcode);
// Add optional parameters to the running program from Argv
for (unsigned i = 0, e = Args.size(); i != e; ++i)
- LLIArgs.push_back(Args[i].c_str());
- LLIArgs.push_back(nullptr);
+ LLIArgs.push_back(Args[i]);
outs() << "<lli>";
outs().flush();
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs()
- << " " << LLIArgs[i];
- errs() << "\n";);
- return RunProgramWithTimeout(LLIPath, &LLIArgs[0], InputFile, OutputFile,
+ LLVM_DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs()
+ << " " << LLIArgs[i];
+ errs() << "\n";);
+ return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile,
OutputFile, Timeout, MemoryLimit);
}
@@ -206,7 +204,7 @@ void AbstractInterpreter::anchor() {}
#if defined(LLVM_ON_UNIX)
const char EXESuffix[] = "";
-#elif defined(LLVM_ON_WIN32)
+#elif defined(_WIN32)
const char EXESuffix[] = "exe";
#endif
@@ -215,7 +213,7 @@ const char EXESuffix[] = "exe";
/// itself. This allows us to find another LLVM tool if it is built in the same
/// directory. An empty string is returned on error; note that this function
/// just mainpulates the path and doesn't check for executability.
-/// @brief Find a named executable.
+/// Find a named executable.
static std::string PrependMainExecutablePath(const std::string &ExeName,
const char *Argv0,
void *MainAddr) {
@@ -285,22 +283,20 @@ public:
Error CustomCompiler::compileProgram(const std::string &Bitcode,
unsigned Timeout, unsigned MemoryLimit) {
- std::vector<const char *> ProgramArgs;
+ std::vector<StringRef> ProgramArgs;
ProgramArgs.push_back(CompilerCommand.c_str());
for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
ProgramArgs.push_back(CompilerArgs.at(i).c_str());
- ProgramArgs.push_back(Bitcode.c_str());
- ProgramArgs.push_back(nullptr);
+ ProgramArgs.push_back(Bitcode);
// Add optional parameters to the running program from Argv
for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
ProgramArgs.push_back(CompilerArgs[i].c_str());
- if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], "", "", "",
- Timeout, MemoryLimit))
- return ProcessFailure(CompilerCommand, &ProgramArgs[0], Timeout,
- MemoryLimit);
+ if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout,
+ MemoryLimit))
+ return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit);
return Error::success();
}
@@ -336,19 +332,18 @@ Expected<int> CustomExecutor::ExecuteProgram(
const std::vector<std::string> &SharedLibs, unsigned Timeout,
unsigned MemoryLimit) {
- std::vector<const char *> ProgramArgs;
- ProgramArgs.push_back(ExecutionCommand.c_str());
+ std::vector<StringRef> ProgramArgs;
+ ProgramArgs.push_back(ExecutionCommand);
for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
- ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
- ProgramArgs.push_back(Bitcode.c_str());
- ProgramArgs.push_back(nullptr);
+ ProgramArgs.push_back(ExecutorArgs[i]);
+ ProgramArgs.push_back(Bitcode);
// Add optional parameters to the running program from Argv
for (unsigned i = 0, e = Args.size(); i != e; ++i)
- ProgramArgs.push_back(Args[i].c_str());
+ ProgramArgs.push_back(Args[i]);
- return RunProgramWithTimeout(ExecutionCommand, &ProgramArgs[0], InputFile,
+ return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile,
OutputFile, OutputFile, Timeout, MemoryLimit);
}
@@ -463,31 +458,28 @@ Expected<CC::FileType> LLC::OutputCode(const std::string &Bitcode,
exit(1);
}
OutputAsmFile = UniqueFile.str();
- std::vector<const char *> LLCArgs;
- LLCArgs.push_back(LLCPath.c_str());
+ std::vector<StringRef> LLCArgs;
+ LLCArgs.push_back(LLCPath);
// Add any extra LLC args.
for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
- LLCArgs.push_back(ToolArgs[i].c_str());
+ LLCArgs.push_back(ToolArgs[i]);
LLCArgs.push_back("-o");
- LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file
- LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode
+ LLCArgs.push_back(OutputAsmFile); // Output to the Asm file
+ LLCArgs.push_back(Bitcode); // This is the input bitcode
if (UseIntegratedAssembler)
LLCArgs.push_back("-filetype=obj");
- LLCArgs.push_back(nullptr);
-
outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>");
outs().flush();
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs()
- << " " << LLCArgs[i];
- errs() << "\n";);
- if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], "", "", "", Timeout,
- MemoryLimit))
- return ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit);
+ LLVM_DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs()
+ << " " << LLCArgs[i];
+ errs() << "\n";);
+ if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit))
+ return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit);
return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
}
@@ -581,32 +573,31 @@ Expected<int> JIT::ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &SharedLibs,
unsigned Timeout, unsigned MemoryLimit) {
// Construct a vector of parameters, incorporating those from the command-line
- std::vector<const char *> JITArgs;
+ std::vector<StringRef> JITArgs;
JITArgs.push_back(LLIPath.c_str());
JITArgs.push_back("-force-interpreter=false");
// Add any extra LLI args.
for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
- JITArgs.push_back(ToolArgs[i].c_str());
+ JITArgs.push_back(ToolArgs[i]);
for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
JITArgs.push_back("-load");
- JITArgs.push_back(SharedLibs[i].c_str());
+ JITArgs.push_back(SharedLibs[i]);
}
JITArgs.push_back(Bitcode.c_str());
// Add optional parameters to the running program from Argv
for (unsigned i = 0, e = Args.size(); i != e; ++i)
- JITArgs.push_back(Args[i].c_str());
- JITArgs.push_back(nullptr);
+ JITArgs.push_back(Args[i]);
outs() << "<jit>";
outs().flush();
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs()
- << " " << JITArgs[i];
- errs() << "\n";);
- DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
- return RunProgramWithTimeout(LLIPath, &JITArgs[0], InputFile, OutputFile,
+ LLVM_DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs()
+ << " " << JITArgs[i];
+ errs() << "\n";);
+ LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
+ return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile,
OutputFile, Timeout, MemoryLimit);
}
@@ -630,15 +621,15 @@ AbstractInterpreter::createJIT(const char *Argv0, std::string &Message,
// CC abstraction
//
-static bool IsARMArchitecture(std::vector<const char *> Args) {
- for (std::vector<const char *>::const_iterator I = Args.begin(),
- E = Args.end();
- I != E; ++I) {
- if (StringRef(*I).equals_lower("-arch")) {
- ++I;
- if (I != E && StringRef(*I).startswith_lower("arm"))
- return true;
- }
+static bool IsARMArchitecture(std::vector<StringRef> Args) {
+ for (size_t I = 0; I < Args.size(); ++I) {
+ if (!Args[I].equals_lower("-arch"))
+ continue;
+ ++I;
+ if (I == Args.size())
+ break;
+ if (Args[I].startswith_lower("arm"))
+ return true;
}
return false;
@@ -651,9 +642,9 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
const std::string &OutputFile,
const std::vector<std::string> &ArgsForCC,
unsigned Timeout, unsigned MemoryLimit) {
- std::vector<const char *> CCArgs;
+ std::vector<StringRef> CCArgs;
- CCArgs.push_back(CCPath.c_str());
+ CCArgs.push_back(CCPath);
if (TargetTriple.getArch() == Triple::x86)
CCArgs.push_back("-m32");
@@ -661,7 +652,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
E = ccArgs.end();
I != E; ++I)
- CCArgs.push_back(I->c_str());
+ CCArgs.push_back(*I);
// Specify -x explicitly in case the extension is wonky
if (fileType != ObjectFile) {
@@ -680,7 +671,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
}
}
- CCArgs.push_back(ProgramFile.c_str()); // Specify the input filename.
+ CCArgs.push_back(ProgramFile); // Specify the input filename.
CCArgs.push_back("-x");
CCArgs.push_back("none");
@@ -693,51 +684,50 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
errs() << "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
- CCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
+ CCArgs.push_back(OutputBinary); // Output to the right file...
// Add any arguments intended for CC. We locate them here because this is
// most likely -L and -l options that need to come before other libraries but
// after the source. Other options won't be sensitive to placement on the
// command line, so this should be safe.
for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
- CCArgs.push_back(ArgsForCC[i].c_str());
+ CCArgs.push_back(ArgsForCC[i]);
CCArgs.push_back("-lm"); // Hard-code the math library...
CCArgs.push_back("-O2"); // Optimize the program a bit...
if (TargetTriple.getArch() == Triple::sparc)
CCArgs.push_back("-mcpu=v9");
- CCArgs.push_back(nullptr); // NULL terminator
outs() << "<CC>";
outs().flush();
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
- << " " << CCArgs[i];
- errs() << "\n";);
- if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", ""))
- return ProcessFailure(CCPath, &CCArgs[0]);
+ LLVM_DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
+ << " " << CCArgs[i];
+ errs() << "\n";);
+ if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
+ return ProcessFailure(CCPath, CCArgs);
- std::vector<const char *> ProgramArgs;
+ std::vector<StringRef> ProgramArgs;
// Declared here so that the destructor only runs after
// ProgramArgs is used.
std::string Exec;
if (RemoteClientPath.empty())
- ProgramArgs.push_back(OutputBinary.c_str());
+ ProgramArgs.push_back(OutputBinary);
else {
- ProgramArgs.push_back(RemoteClientPath.c_str());
- ProgramArgs.push_back(RemoteHost.c_str());
+ ProgramArgs.push_back(RemoteClientPath);
+ ProgramArgs.push_back(RemoteHost);
if (!RemoteUser.empty()) {
ProgramArgs.push_back("-l");
- ProgramArgs.push_back(RemoteUser.c_str());
+ ProgramArgs.push_back(RemoteUser);
}
if (!RemotePort.empty()) {
ProgramArgs.push_back("-p");
- ProgramArgs.push_back(RemotePort.c_str());
+ ProgramArgs.push_back(RemotePort);
}
if (!RemoteExtra.empty()) {
- ProgramArgs.push_back(RemoteExtra.c_str());
+ ProgramArgs.push_back(RemoteExtra);
}
// Full path to the binary. We need to cd to the exec directory because
@@ -747,28 +737,28 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
Exec += env_pwd;
Exec += "; ./";
Exec += OutputBinary.c_str();
- ProgramArgs.push_back(Exec.c_str());
+ ProgramArgs.push_back(Exec);
}
// Add optional parameters to the running program from Argv
for (unsigned i = 0, e = Args.size(); i != e; ++i)
- ProgramArgs.push_back(Args[i].c_str());
- ProgramArgs.push_back(nullptr); // NULL terminator
+ ProgramArgs.push_back(Args[i]);
// Now that we have a binary, run it!
outs() << "<program>";
outs().flush();
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs()
- << " " << ProgramArgs[i];
- errs() << "\n";);
+ LLVM_DEBUG(
+ errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs()
+ << " " << ProgramArgs[i];
+ errs() << "\n";);
FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps);
if (RemoteClientPath.empty()) {
- DEBUG(errs() << "<run locally>");
+ LLVM_DEBUG(errs() << "<run locally>");
std::string Error;
- int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0],
+ int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs,
InputFile, OutputFile, OutputFile,
Timeout, MemoryLimit, &Error);
// Treat a signal (usually SIGSEGV) or timeout as part of the program output
@@ -782,7 +772,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
} else {
outs() << "<run remotely>";
outs().flush();
- return RunProgramRemotelyWithTimeout(RemoteClientPath, &ProgramArgs[0],
+ return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs,
InputFile, OutputFile, OutputFile,
Timeout, MemoryLimit);
}
@@ -800,9 +790,9 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
}
OutputFile = UniqueFilename.str();
- std::vector<const char *> CCArgs;
+ std::vector<StringRef> CCArgs;
- CCArgs.push_back(CCPath.c_str());
+ CCArgs.push_back(CCPath);
if (TargetTriple.getArch() == Triple::x86)
CCArgs.push_back("-m32");
@@ -810,7 +800,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
E = ccArgs.end();
I != E; ++I)
- CCArgs.push_back(I->c_str());
+ CCArgs.push_back(*I);
// Compile the C/asm file into a shared object
if (fileType != ObjectFile) {
@@ -818,7 +808,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
}
CCArgs.push_back("-fno-strict-aliasing");
- CCArgs.push_back(InputFile.c_str()); // Specify the input filename.
+ CCArgs.push_back(InputFile); // Specify the input filename.
CCArgs.push_back("-x");
CCArgs.push_back("none");
if (TargetTriple.getArch() == Triple::sparc)
@@ -842,7 +832,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
CCArgs.push_back("-mcpu=v9");
CCArgs.push_back("-o");
- CCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
+ CCArgs.push_back(OutputFile); // Output to the right filename.
CCArgs.push_back("-O2"); // Optimize the program a bit.
// Add any arguments intended for CC. We locate them here because this is
@@ -850,17 +840,16 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
// after the source. Other options won't be sensitive to placement on the
// command line, so this should be safe.
for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
- CCArgs.push_back(ArgsForCC[i].c_str());
- CCArgs.push_back(nullptr); // NULL terminator
+ CCArgs.push_back(ArgsForCC[i]);
outs() << "<CC>";
outs().flush();
- DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
- << " " << CCArgs[i];
- errs() << "\n";);
- if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", ""))
- return ProcessFailure(CCPath, &CCArgs[0]);
+ LLVM_DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
+ << " " << CCArgs[i];
+ errs() << "\n";);
+ if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
+ return ProcessFailure(CCPath, CCArgs);
return Error::success();
}
diff --git a/contrib/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm/tools/bugpoint/bugpoint.cpp
index ec1ca2e54968..f6b7d08455d4 100644
--- a/contrib/llvm/tools/bugpoint/bugpoint.cpp
+++ b/contrib/llvm/tools/bugpoint/bugpoint.cpp
@@ -15,17 +15,18 @@
#include "BugDriver.h"
#include "ToolRunner.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Valgrind.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
@@ -117,9 +118,7 @@ void initializePollyPasses(llvm::PassRegistry &Registry);
int main(int argc, char **argv) {
#ifndef DEBUG_BUGPOINT
- llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
- llvm::PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
#endif
// Initialize passes
@@ -132,6 +131,7 @@ int main(int argc, char **argv) {
initializeAnalysis(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
+ initializeAggressiveInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);
diff --git a/contrib/llvm/tools/clang/LICENSE.TXT b/contrib/llvm/tools/clang/LICENSE.TXT
index b452ca2efd8f..547f6a489382 100644
--- a/contrib/llvm/tools/clang/LICENSE.TXT
+++ b/contrib/llvm/tools/clang/LICENSE.TXT
@@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
-Copyright (c) 2007-2016 University of Illinois at Urbana-Champaign.
+Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
diff --git a/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h b/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h
index 8d323a4e6cae..3cfec388308c 100644
--- a/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h
+++ b/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h
@@ -28,19 +28,19 @@ extern "C" {
*/
/**
- * \brief Return the timestamp for use with Clang's
+ * Return the timestamp for use with Clang's
* \c -fbuild-session-timestamp= option.
*/
CINDEX_LINKAGE unsigned long long clang_getBuildSessionTimestamp(void);
/**
- * \brief Object encapsulating information about overlaying virtual
+ * Object encapsulating information about overlaying virtual
* file/directories over the real file system.
*/
typedef struct CXVirtualFileOverlayImpl *CXVirtualFileOverlay;
/**
- * \brief Create a \c CXVirtualFileOverlay object.
+ * Create a \c CXVirtualFileOverlay object.
* Must be disposed with \c clang_VirtualFileOverlay_dispose().
*
* \param options is reserved, always pass 0.
@@ -49,7 +49,7 @@ CINDEX_LINKAGE CXVirtualFileOverlay
clang_VirtualFileOverlay_create(unsigned options);
/**
- * \brief Map an absolute virtual file path to an absolute real one.
+ * Map an absolute virtual file path to an absolute real one.
* The virtual path must be canonicalized (not contain "."/"..").
* \returns 0 for success, non-zero to indicate an error.
*/
@@ -59,17 +59,17 @@ clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay,
const char *realPath);
/**
- * \brief Set the case sensitivity for the \c CXVirtualFileOverlay object.
+ * Set the case sensitivity for the \c CXVirtualFileOverlay object.
* The \c CXVirtualFileOverlay object is case-sensitive by default, this
* option can be used to override the default.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay,
- int caseSensitive);
+ int caseSensitive);
/**
- * \brief Write out the \c CXVirtualFileOverlay object to a char buffer.
+ * Write out the \c CXVirtualFileOverlay object to a char buffer.
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
@@ -83,7 +83,7 @@ clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options,
unsigned *out_buffer_size);
/**
- * \brief free memory allocated by libclang, such as the buffer returned by
+ * free memory allocated by libclang, such as the buffer returned by
* \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer().
*
* \param buffer memory pointer to free.
@@ -91,17 +91,17 @@ clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options,
CINDEX_LINKAGE void clang_free(void *buffer);
/**
- * \brief Dispose a \c CXVirtualFileOverlay object.
+ * Dispose a \c CXVirtualFileOverlay object.
*/
CINDEX_LINKAGE void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay);
/**
- * \brief Object encapsulating information about a module.map file.
+ * Object encapsulating information about a module.map file.
*/
typedef struct CXModuleMapDescriptorImpl *CXModuleMapDescriptor;
/**
- * \brief Create a \c CXModuleMapDescriptor object.
+ * Create a \c CXModuleMapDescriptor object.
* Must be disposed with \c clang_ModuleMapDescriptor_dispose().
*
* \param options is reserved, always pass 0.
@@ -110,7 +110,7 @@ CINDEX_LINKAGE CXModuleMapDescriptor
clang_ModuleMapDescriptor_create(unsigned options);
/**
- * \brief Sets the framework module name that the module.map describes.
+ * Sets the framework module name that the module.map describes.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
@@ -118,7 +118,7 @@ clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor,
const char *name);
/**
- * \brief Sets the umbrealla header name that the module.map describes.
+ * Sets the umbrealla header name that the module.map describes.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
@@ -126,7 +126,7 @@ clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor,
const char *name);
/**
- * \brief Write out the \c CXModuleMapDescriptor object to a char buffer.
+ * Write out the \c CXModuleMapDescriptor object to a char buffer.
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
@@ -140,7 +140,7 @@ clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor, unsigned options,
unsigned *out_buffer_size);
/**
- * \brief Dispose a \c CXModuleMapDescriptor object.
+ * Dispose a \c CXModuleMapDescriptor object.
*/
CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor);
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
index 29f89e52a6e3..6f483ee28b56 100644
--- a/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
@@ -38,7 +38,7 @@ extern "C" {
typedef void * CXCompilationDatabase;
/**
- * \brief Contains the results of a search in the compilation database
+ * Contains the results of a search in the compilation database
*
* When searching for the compile command for a file, the compilation db can
* return several commands, as the file may have been compiled with
@@ -49,28 +49,28 @@ typedef void * CXCompilationDatabase;
typedef void * CXCompileCommands;
/**
- * \brief Represents the command line invocation to compile a specific file.
+ * Represents the command line invocation to compile a specific file.
*/
typedef void * CXCompileCommand;
/**
- * \brief Error codes for Compilation Database
+ * Error codes for Compilation Database
*/
typedef enum {
/*
- * \brief No error occurred
+ * No error occurred
*/
CXCompilationDatabase_NoError = 0,
/*
- * \brief Database can not be loaded
+ * Database can not be loaded
*/
CXCompilationDatabase_CanNotLoadDatabase = 1
} CXCompilationDatabase_Error;
/**
- * \brief Creates a compilation database from the database found in directory
+ * Creates a compilation database from the database found in directory
* buildDir. For example, CMake can output a compile_commands.json which can
* be used to build the database.
*
@@ -81,13 +81,13 @@ clang_CompilationDatabase_fromDirectory(const char *BuildDir,
CXCompilationDatabase_Error *ErrorCode);
/**
- * \brief Free the given compilation database
+ * Free the given compilation database
*/
CINDEX_LINKAGE void
clang_CompilationDatabase_dispose(CXCompilationDatabase);
/**
- * \brief Find the compile commands used for a file. The compile commands
+ * Find the compile commands used for a file. The compile commands
* must be freed by \c clang_CompileCommands_dispose.
*/
CINDEX_LINKAGE CXCompileCommands
@@ -95,24 +95,24 @@ clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase,
const char *CompleteFileName);
/**
- * \brief Get all the compile commands in the given compilation database.
+ * Get all the compile commands in the given compilation database.
*/
CINDEX_LINKAGE CXCompileCommands
clang_CompilationDatabase_getAllCompileCommands(CXCompilationDatabase);
/**
- * \brief Free the given CompileCommands
+ * Free the given CompileCommands
*/
CINDEX_LINKAGE void clang_CompileCommands_dispose(CXCompileCommands);
/**
- * \brief Get the number of CompileCommand we have for a file
+ * Get the number of CompileCommand we have for a file
*/
CINDEX_LINKAGE unsigned
clang_CompileCommands_getSize(CXCompileCommands);
/**
- * \brief Get the I'th CompileCommand for a file
+ * Get the I'th CompileCommand for a file
*
* Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands)
*/
@@ -120,26 +120,26 @@ CINDEX_LINKAGE CXCompileCommand
clang_CompileCommands_getCommand(CXCompileCommands, unsigned I);
/**
- * \brief Get the working directory where the CompileCommand was executed from
+ * Get the working directory where the CompileCommand was executed from
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getDirectory(CXCompileCommand);
/**
- * \brief Get the filename associated with the CompileCommand.
+ * Get the filename associated with the CompileCommand.
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getFilename(CXCompileCommand);
/**
- * \brief Get the number of arguments in the compiler invocation.
+ * Get the number of arguments in the compiler invocation.
*
*/
CINDEX_LINKAGE unsigned
clang_CompileCommand_getNumArgs(CXCompileCommand);
/**
- * \brief Get the I'th argument value in the compiler invocations
+ * Get the I'th argument value in the compiler invocations
*
* Invariant :
* - argument 0 is the compiler executable
@@ -148,19 +148,19 @@ CINDEX_LINKAGE CXString
clang_CompileCommand_getArg(CXCompileCommand, unsigned I);
/**
- * \brief Get the number of source mappings for the compiler invocation.
+ * Get the number of source mappings for the compiler invocation.
*/
CINDEX_LINKAGE unsigned
clang_CompileCommand_getNumMappedSources(CXCompileCommand);
/**
- * \brief Get the I'th mapped source path for the compiler invocation.
+ * Get the I'th mapped source path for the compiler invocation.
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getMappedSourcePath(CXCompileCommand, unsigned I);
/**
- * \brief Get the I'th mapped source content for the compiler invocation.
+ * Get the I'th mapped source content for the compiler invocation.
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I);
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h b/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h
index aff73b746763..caee48d76832 100644
--- a/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h
+++ b/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h
@@ -21,19 +21,19 @@ extern "C" {
#endif
/**
- * \brief Error codes returned by libclang routines.
+ * Error codes returned by libclang routines.
*
* Zero (\c CXError_Success) is the only error code indicating success. Other
* error codes, including not yet assigned non-zero values, indicate errors.
*/
enum CXErrorCode {
/**
- * \brief No error.
+ * No error.
*/
CXError_Success = 0,
/**
- * \brief A generic error code, no further details are available.
+ * A generic error code, no further details are available.
*
* Errors of this kind can get their own specific error codes in future
* libclang versions.
@@ -41,18 +41,18 @@ enum CXErrorCode {
CXError_Failure = 1,
/**
- * \brief libclang crashed while performing the requested operation.
+ * libclang crashed while performing the requested operation.
*/
CXError_Crashed = 2,
/**
- * \brief The function detected that the arguments violate the function
+ * The function detected that the arguments violate the function
* contract.
*/
CXError_InvalidArguments = 3,
/**
- * \brief An AST deserialization error has occurred.
+ * An AST deserialization error has occurred.
*/
CXError_ASTReadError = 4
};
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXString.h b/contrib/llvm/tools/clang/include/clang-c/CXString.h
index 68ab7bc5244c..76eeda180109 100644
--- a/contrib/llvm/tools/clang/include/clang-c/CXString.h
+++ b/contrib/llvm/tools/clang/include/clang-c/CXString.h
@@ -28,7 +28,7 @@ extern "C" {
*/
/**
- * \brief A character string.
+ * A character string.
*
* The \c CXString type is used to return strings from the interface when
* the ownership of that string might differ from one call to the next.
@@ -46,17 +46,17 @@ typedef struct {
} CXStringSet;
/**
- * \brief Retrieve the character data associated with the given string.
+ * Retrieve the character data associated with the given string.
*/
CINDEX_LINKAGE const char *clang_getCString(CXString string);
/**
- * \brief Free the given string.
+ * Free the given string.
*/
CINDEX_LINKAGE void clang_disposeString(CXString string);
/**
- * \brief Free the given string set.
+ * Free the given string set.
*/
CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set);
diff --git a/contrib/llvm/tools/clang/include/clang-c/Documentation.h b/contrib/llvm/tools/clang/include/clang-c/Documentation.h
index 89373b11457d..58c8af5aa47c 100644
--- a/contrib/llvm/tools/clang/include/clang-c/Documentation.h
+++ b/contrib/llvm/tools/clang/include/clang-c/Documentation.h
@@ -32,7 +32,7 @@ extern "C" {
*/
/**
- * \brief A parsed comment.
+ * A parsed comment.
*/
typedef struct {
const void *ASTNode;
@@ -40,38 +40,38 @@ typedef struct {
} CXComment;
/**
- * \brief Given a cursor that represents a documentable entity (e.g.,
+ * Given a cursor that represents a documentable entity (e.g.,
* declaration), return the associated parsed comment as a
* \c CXComment_FullComment AST node.
*/
CINDEX_LINKAGE CXComment clang_Cursor_getParsedComment(CXCursor C);
/**
- * \brief Describes the type of the comment AST node (\c CXComment). A comment
+ * Describes the type of the comment AST node (\c CXComment). A comment
* node can be considered block content (e. g., paragraph), inline content
* (plain text) or neither (the root AST node).
*/
enum CXCommentKind {
/**
- * \brief Null comment. No AST node is constructed at the requested location
+ * Null comment. No AST node is constructed at the requested location
* because there is no text or a syntax error.
*/
CXComment_Null = 0,
/**
- * \brief Plain text. Inline content.
+ * Plain text. Inline content.
*/
CXComment_Text = 1,
/**
- * \brief A command with word-like arguments that is considered inline content.
+ * A command with word-like arguments that is considered inline content.
*
* For example: \\c command.
*/
CXComment_InlineCommand = 2,
/**
- * \brief HTML start tag with attributes (name-value pairs). Considered
+ * HTML start tag with attributes (name-value pairs). Considered
* inline content.
*
* For example:
@@ -82,7 +82,7 @@ enum CXCommentKind {
CXComment_HTMLStartTag = 3,
/**
- * \brief HTML end tag. Considered inline content.
+ * HTML end tag. Considered inline content.
*
* For example:
* \verbatim
@@ -92,19 +92,19 @@ enum CXCommentKind {
CXComment_HTMLEndTag = 4,
/**
- * \brief A paragraph, contains inline comment. The paragraph itself is
+ * A paragraph, contains inline comment. The paragraph itself is
* block content.
*/
CXComment_Paragraph = 5,
/**
- * \brief A command that has zero or more word-like arguments (number of
+ * A command that has zero or more word-like arguments (number of
* word-like arguments depends on command name) and a paragraph as an
* argument. Block command is block content.
*
* Paragraph argument is also a child of the block command.
*
- * For example: \\brief has 0 word-like arguments and a paragraph argument.
+ * For example: \has 0 word-like arguments and a paragraph argument.
*
* AST nodes of special kinds that parser knows about (e. g., \\param
* command) have their own node kinds.
@@ -112,7 +112,7 @@ enum CXCommentKind {
CXComment_BlockCommand = 6,
/**
- * \brief A \\param or \\arg command that describes the function parameter
+ * A \\param or \\arg command that describes the function parameter
* (name, passing direction, description).
*
* For example: \\param [in] ParamName description.
@@ -120,7 +120,7 @@ enum CXCommentKind {
CXComment_ParamCommand = 7,
/**
- * \brief A \\tparam command that describes a template parameter (name and
+ * A \\tparam command that describes a template parameter (name and
* description).
*
* For example: \\tparam T description.
@@ -128,7 +128,7 @@ enum CXCommentKind {
CXComment_TParamCommand = 8,
/**
- * \brief A verbatim block command (e. g., preformatted code). Verbatim
+ * A verbatim block command (e. g., preformatted code). Verbatim
* block has an opening and a closing command and contains multiple lines of
* text (\c CXComment_VerbatimBlockLine child nodes).
*
@@ -140,67 +140,67 @@ enum CXCommentKind {
CXComment_VerbatimBlockCommand = 9,
/**
- * \brief A line of text that is contained within a
+ * A line of text that is contained within a
* CXComment_VerbatimBlockCommand node.
*/
CXComment_VerbatimBlockLine = 10,
/**
- * \brief A verbatim line command. Verbatim line has an opening command,
+ * A verbatim line command. Verbatim line has an opening command,
* a single line of text (up to the newline after the opening command) and
* has no closing command.
*/
CXComment_VerbatimLine = 11,
/**
- * \brief A full comment attached to a declaration, contains block content.
+ * A full comment attached to a declaration, contains block content.
*/
CXComment_FullComment = 12
};
/**
- * \brief The most appropriate rendering mode for an inline command, chosen on
+ * The most appropriate rendering mode for an inline command, chosen on
* command semantics in Doxygen.
*/
enum CXCommentInlineCommandRenderKind {
/**
- * \brief Command argument should be rendered in a normal font.
+ * Command argument should be rendered in a normal font.
*/
CXCommentInlineCommandRenderKind_Normal,
/**
- * \brief Command argument should be rendered in a bold font.
+ * Command argument should be rendered in a bold font.
*/
CXCommentInlineCommandRenderKind_Bold,
/**
- * \brief Command argument should be rendered in a monospaced font.
+ * Command argument should be rendered in a monospaced font.
*/
CXCommentInlineCommandRenderKind_Monospaced,
/**
- * \brief Command argument should be rendered emphasized (typically italic
+ * Command argument should be rendered emphasized (typically italic
* font).
*/
CXCommentInlineCommandRenderKind_Emphasized
};
/**
- * \brief Describes parameter passing direction for \\param or \\arg command.
+ * Describes parameter passing direction for \\param or \\arg command.
*/
enum CXCommentParamPassDirection {
/**
- * \brief The parameter is an input parameter.
+ * The parameter is an input parameter.
*/
CXCommentParamPassDirection_In,
/**
- * \brief The parameter is an output parameter.
+ * The parameter is an output parameter.
*/
CXCommentParamPassDirection_Out,
/**
- * \brief The parameter is an input and output parameter.
+ * The parameter is an input and output parameter.
*/
CXCommentParamPassDirection_InOut
};
@@ -230,7 +230,7 @@ CINDEX_LINKAGE
CXComment clang_Comment_getChild(CXComment Comment, unsigned ChildIdx);
/**
- * \brief A \c CXComment_Paragraph node is considered whitespace if it contains
+ * A \c CXComment_Paragraph node is considered whitespace if it contains
* only \c CXComment_Text nodes that are empty or whitespace.
*
* Other AST nodes (except \c CXComment_Paragraph and \c CXComment_Text) are
@@ -487,7 +487,7 @@ CXString clang_VerbatimBlockLineComment_getText(CXComment Comment);
CINDEX_LINKAGE CXString clang_VerbatimLineComment_getText(CXComment Comment);
/**
- * \brief Convert an HTML tag AST node to string.
+ * Convert an HTML tag AST node to string.
*
* \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
* node.
@@ -497,13 +497,13 @@ CINDEX_LINKAGE CXString clang_VerbatimLineComment_getText(CXComment Comment);
CINDEX_LINKAGE CXString clang_HTMLTagComment_getAsString(CXComment Comment);
/**
- * \brief Convert a given full parsed comment to an HTML fragment.
+ * Convert a given full parsed comment to an HTML fragment.
*
* Specific details of HTML layout are subject to change. Don't try to parse
* this HTML back into an AST, use other APIs instead.
*
* Currently the following CSS classes are used:
- * \li "para-brief" for \\brief paragraph and equivalent commands;
+ * \li "para-brief" for \paragraph and equivalent commands;
* \li "para-returns" for \\returns paragraph and equivalent commands;
* \li "word-returns" for the "Returns" word in \\returns paragraph.
*
@@ -530,7 +530,7 @@ CINDEX_LINKAGE CXString clang_HTMLTagComment_getAsString(CXComment Comment);
CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment);
/**
- * \brief Convert a given full parsed comment to an XML document.
+ * Convert a given full parsed comment to an XML document.
*
* A Relax NG schema for the XML can be found in comment-xml-schema.rng file
* inside clang source tree.
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h
index 587008a7210b..65dada38b050 100644
--- a/contrib/llvm/tools/clang/include/clang-c/Index.h
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -24,7 +24,7 @@
#include "clang-c/BuildSystem.h"
/**
- * \brief The version constants for the libclang API.
+ * The version constants for the libclang API.
* CINDEX_VERSION_MINOR should increase when there are API additions.
* CINDEX_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
*
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 45
+#define CINDEX_VERSION_MINOR 49
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -75,30 +75,30 @@ extern "C" {
*/
/**
- * \brief An "index" that consists of a set of translation units that would
+ * An "index" that consists of a set of translation units that would
* typically be linked together into an executable or library.
*/
typedef void *CXIndex;
/**
- * \brief An opaque type representing target information for a given translation
+ * An opaque type representing target information for a given translation
* unit.
*/
typedef struct CXTargetInfoImpl *CXTargetInfo;
/**
- * \brief A single translation unit, which resides in an index.
+ * A single translation unit, which resides in an index.
*/
typedef struct CXTranslationUnitImpl *CXTranslationUnit;
/**
- * \brief Opaque pointer representing client data that will be passed through
+ * Opaque pointer representing client data that will be passed through
* to various callbacks and visitors.
*/
typedef void *CXClientData;
/**
- * \brief Provides the contents of a file that has not yet been saved to disk.
+ * Provides the contents of a file that has not yet been saved to disk.
*
* Each CXUnsavedFile instance provides the name of a file on the
* system along with the current contents of that file that have not
@@ -106,66 +106,66 @@ typedef void *CXClientData;
*/
struct CXUnsavedFile {
/**
- * \brief The file whose contents have not yet been saved.
+ * The file whose contents have not yet been saved.
*
* This file must already exist in the file system.
*/
const char *Filename;
/**
- * \brief A buffer containing the unsaved contents of this file.
+ * A buffer containing the unsaved contents of this file.
*/
const char *Contents;
/**
- * \brief The length of the unsaved contents of this buffer.
+ * The length of the unsaved contents of this buffer.
*/
unsigned long Length;
};
/**
- * \brief Describes the availability of a particular entity, which indicates
+ * Describes the availability of a particular entity, which indicates
* whether the use of this entity will result in a warning or error due to
* it being deprecated or unavailable.
*/
enum CXAvailabilityKind {
/**
- * \brief The entity is available.
+ * The entity is available.
*/
CXAvailability_Available,
/**
- * \brief The entity is available, but has been deprecated (and its use is
+ * The entity is available, but has been deprecated (and its use is
* not recommended).
*/
CXAvailability_Deprecated,
/**
- * \brief The entity is not available; any use of it will be an error.
+ * The entity is not available; any use of it will be an error.
*/
CXAvailability_NotAvailable,
/**
- * \brief The entity is available, but not accessible; any use of it will be
+ * The entity is available, but not accessible; any use of it will be
* an error.
*/
CXAvailability_NotAccessible
};
/**
- * \brief Describes a version number of the form major.minor.subminor.
+ * Describes a version number of the form major.minor.subminor.
*/
typedef struct CXVersion {
/**
- * \brief The major version number, e.g., the '10' in '10.7.3'. A negative
+ * The major version number, e.g., the '10' in '10.7.3'. A negative
* value indicates that there is no version number at all.
*/
int Major;
/**
- * \brief The minor version number, e.g., the '7' in '10.7.3'. This value
- * will be negative if no minor version number was provided, e.g., for
+ * The minor version number, e.g., the '7' in '10.7.3'. This value
+ * will be negative if no minor version number was provided, e.g., for
* version '10'.
*/
int Minor;
/**
- * \brief The subminor version number, e.g., the '3' in '10.7.3'. This value
+ * The subminor version number, e.g., the '3' in '10.7.3'. This value
* will be negative if no minor or subminor version number was provided,
* e.g., in version '10' or '10.7'.
*/
@@ -173,60 +173,60 @@ typedef struct CXVersion {
} CXVersion;
/**
- * \brief Describes the exception specification of a cursor.
+ * Describes the exception specification of a cursor.
*
* A negative value indicates that the cursor is not a function declaration.
*/
enum CXCursor_ExceptionSpecificationKind {
/**
- * \brief The cursor has no exception specification.
+ * The cursor has no exception specification.
*/
CXCursor_ExceptionSpecificationKind_None,
/**
- * \brief The cursor has exception specification throw()
+ * The cursor has exception specification throw()
*/
CXCursor_ExceptionSpecificationKind_DynamicNone,
/**
- * \brief The cursor has exception specification throw(T1, T2)
+ * The cursor has exception specification throw(T1, T2)
*/
CXCursor_ExceptionSpecificationKind_Dynamic,
/**
- * \brief The cursor has exception specification throw(...).
+ * The cursor has exception specification throw(...).
*/
CXCursor_ExceptionSpecificationKind_MSAny,
/**
- * \brief The cursor has exception specification basic noexcept.
+ * The cursor has exception specification basic noexcept.
*/
CXCursor_ExceptionSpecificationKind_BasicNoexcept,
/**
- * \brief The cursor has exception specification computed noexcept.
+ * The cursor has exception specification computed noexcept.
*/
CXCursor_ExceptionSpecificationKind_ComputedNoexcept,
/**
- * \brief The exception specification has not yet been evaluated.
+ * The exception specification has not yet been evaluated.
*/
CXCursor_ExceptionSpecificationKind_Unevaluated,
/**
- * \brief The exception specification has not yet been instantiated.
+ * The exception specification has not yet been instantiated.
*/
CXCursor_ExceptionSpecificationKind_Uninstantiated,
/**
- * \brief The exception specification has not been parsed yet.
+ * The exception specification has not been parsed yet.
*/
CXCursor_ExceptionSpecificationKind_Unparsed
};
/**
- * \brief Provides a shared context for creating translation units.
+ * Provides a shared context for creating translation units.
*
* It provides two options:
*
@@ -269,7 +269,7 @@ CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics);
/**
- * \brief Destroy the given index.
+ * Destroy the given index.
*
* The index must not be destroyed until all of the translation units created
* within that index have been destroyed.
@@ -278,12 +278,12 @@ CINDEX_LINKAGE void clang_disposeIndex(CXIndex index);
typedef enum {
/**
- * \brief Used to indicate that no special CXIndex options are needed.
+ * Used to indicate that no special CXIndex options are needed.
*/
CXGlobalOpt_None = 0x0,
/**
- * \brief Used to indicate that threads that libclang creates for indexing
+ * Used to indicate that threads that libclang creates for indexing
* purposes should use background priority.
*
* Affects #clang_indexSourceFile, #clang_indexTranslationUnit,
@@ -292,7 +292,7 @@ typedef enum {
CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1,
/**
- * \brief Used to indicate that threads that libclang creates for editing
+ * Used to indicate that threads that libclang creates for editing
* purposes should use background priority.
*
* Affects #clang_reparseTranslationUnit, #clang_codeCompleteAt,
@@ -301,7 +301,7 @@ typedef enum {
CXGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2,
/**
- * \brief Used to indicate that all threads that libclang creates should use
+ * Used to indicate that all threads that libclang creates should use
* background priority.
*/
CXGlobalOpt_ThreadBackgroundPriorityForAll =
@@ -311,7 +311,7 @@ typedef enum {
} CXGlobalOptFlags;
/**
- * \brief Sets general options associated with a CXIndex.
+ * Sets general options associated with a CXIndex.
*
* For example:
* \code
@@ -326,7 +326,7 @@ typedef enum {
CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options);
/**
- * \brief Gets the general options associated with a CXIndex.
+ * Gets the general options associated with a CXIndex.
*
* \returns A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags that
* are associated with the given CXIndex object.
@@ -334,7 +334,7 @@ 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.
+ * 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
@@ -350,22 +350,22 @@ clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path);
*/
/**
- * \brief A particular source file that is part of a translation unit.
+ * A particular source file that is part of a translation unit.
*/
typedef void *CXFile;
/**
- * \brief Retrieve the complete file and path name of the given file.
+ * Retrieve the complete file and path name of the given file.
*/
CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
/**
- * \brief Retrieve the last modification time of the given file.
+ * Retrieve the last modification time of the given file.
*/
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
- * \brief Uniquely identifies a CXFile, that refers to the same underlying file,
+ * Uniquely identifies a CXFile, that refers to the same underlying file,
* across an indexing session.
*/
typedef struct {
@@ -373,7 +373,7 @@ typedef struct {
} CXFileUniqueID;
/**
- * \brief Retrieve the unique ID for the given \c file.
+ * Retrieve the unique ID for the given \c file.
*
* \param file the file to get the ID for.
* \param outID stores the returned CXFileUniqueID.
@@ -383,15 +383,15 @@ typedef struct {
CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
/**
- * \brief Determine whether the given header is guarded against
+ * Determine whether the given header is guarded against
* multiple inclusions, either with the conventional
* \#ifndef/\#define/\#endif macro guards or with \#pragma once.
*/
-CINDEX_LINKAGE unsigned
+CINDEX_LINKAGE unsigned
clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
/**
- * \brief Retrieve a file handle within the given translation unit.
+ * Retrieve a file handle within the given translation unit.
*
* \param tu the translation unit
*
@@ -404,7 +404,7 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
const char *file_name);
/**
- * \brief Retrieve the buffer associated with the given file.
+ * Retrieve the buffer associated with the given file.
*
* \param tu the translation unit
*
@@ -419,12 +419,19 @@ 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,
+ * Returns non-zero if the \c file1 and \c file2 point to the same file,
* or they are both NULL.
*/
CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
/**
+ * Returns the real path name of \c file.
+ *
+ * An empty string may be returned. Use \c clang_getFileName() in that case.
+ */
+CINDEX_LINKAGE CXString clang_File_tryGetRealPathName(CXFile file);
+
+/**
* @}
*/
@@ -442,7 +449,7 @@ CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
*/
/**
- * \brief Identifies a specific source location within a translation
+ * Identifies a specific source location within a translation
* unit.
*
* Use clang_getExpansionLocation() or clang_getSpellingLocation()
@@ -454,7 +461,7 @@ typedef struct {
} CXSourceLocation;
/**
- * \brief Identifies a half-open character range in the source code.
+ * Identifies a half-open character range in the source code.
*
* Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
* starting and end locations from a source range, respectively.
@@ -466,12 +473,12 @@ typedef struct {
} CXSourceRange;
/**
- * \brief Retrieve a NULL (invalid) source location.
+ * Retrieve a NULL (invalid) source location.
*/
CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(void);
/**
- * \brief Determine whether two source locations, which must refer into
+ * Determine whether two source locations, which must refer into
* the same translation unit, refer to exactly the same point in the source
* code.
*
@@ -482,7 +489,7 @@ CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
CXSourceLocation loc2);
/**
- * \brief Retrieves the source location associated with a given file/line/column
+ * Retrieves the source location associated with a given file/line/column
* in a particular translation unit.
*/
CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
@@ -490,7 +497,7 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
unsigned line,
unsigned column);
/**
- * \brief Retrieves the source location associated with a given character offset
+ * Retrieves the source location associated with a given character offset
* in a particular translation unit.
*/
CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
@@ -498,30 +505,30 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
unsigned offset);
/**
- * \brief Returns non-zero if the given source location is in a system header.
+ * Returns non-zero if the given source location is in a system header.
*/
CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location);
/**
- * \brief Returns non-zero if the given source location is in the main file of
+ * Returns non-zero if the given source location is in the main file of
* the corresponding translation unit.
*/
CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location);
/**
- * \brief Retrieve a NULL (invalid) source range.
+ * Retrieve a NULL (invalid) source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getNullRange(void);
/**
- * \brief Retrieve a source range given the beginning and ending source
+ * Retrieve a source range given the beginning and ending source
* locations.
*/
CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
CXSourceLocation end);
/**
- * \brief Determine whether two ranges are equivalent.
+ * Determine whether two ranges are equivalent.
*
* \returns non-zero if the ranges are the same, zero if they differ.
*/
@@ -529,12 +536,12 @@ CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1,
CXSourceRange range2);
/**
- * \brief Returns non-zero if \p range is null.
+ * Returns non-zero if \p range is null.
*/
CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range);
/**
- * \brief Retrieve the file, line, column, and offset represented by
+ * Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, retrieves the
@@ -562,7 +569,7 @@ CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
unsigned *offset);
/**
- * \brief Retrieve the file, line and column represented by the given source
+ * Retrieve the file, line and column represented by the given source
* location, as specified in a # line directive.
*
* Example: given the following source code in a file somefile.c
@@ -607,7 +614,7 @@ CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
unsigned *column);
/**
- * \brief Legacy API to retrieve the file, line, column, and offset represented
+ * Legacy API to retrieve the file, line, column, and offset represented
* by the given source location.
*
* This interface has been replaced by the newer interface
@@ -621,7 +628,7 @@ CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
unsigned *offset);
/**
- * \brief Retrieve the file, line, column, and offset represented by
+ * Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro instantiation, return where the
@@ -649,7 +656,7 @@ CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location,
unsigned *offset);
/**
- * \brief Retrieve the file, line, column, and offset represented by
+ * Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, return where the macro was
@@ -678,31 +685,31 @@ CINDEX_LINKAGE void clang_getFileLocation(CXSourceLocation location,
unsigned *offset);
/**
- * \brief Retrieve a source location representing the first character within a
+ * Retrieve a source location representing the first character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
/**
- * \brief Retrieve a source location representing the last character within a
+ * Retrieve a source location representing the last character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
/**
- * \brief Identifies an array of ranges.
+ * Identifies an array of ranges.
*/
typedef struct {
- /** \brief The number of ranges in the \c ranges array. */
+ /** The number of ranges in the \c ranges array. */
unsigned count;
/**
- * \brief An array of \c CXSourceRanges.
+ * An array of \c CXSourceRanges.
*/
CXSourceRange *ranges;
} CXSourceRangeList;
/**
- * \brief Retrieve all ranges that were skipped by the preprocessor.
+ * Retrieve all ranges that were skipped by the preprocessor.
*
* The preprocessor will skip lines when they are surrounded by an
* if/ifdef/ifndef directive whose condition does not evaluate to true.
@@ -711,7 +718,7 @@ CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
CXFile file);
/**
- * \brief Retrieve all ranges from all files that were skipped by the
+ * Retrieve all ranges from all files that were skipped by the
* preprocessor.
*
* The preprocessor will skip lines when they are surrounded by an
@@ -720,7 +727,7 @@ CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
CINDEX_LINKAGE CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit tu);
/**
- * \brief Destroy the given \c CXSourceRangeList.
+ * Destroy the given \c CXSourceRangeList.
*/
CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
@@ -735,34 +742,34 @@ CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
*/
/**
- * \brief Describes the severity of a particular diagnostic.
+ * Describes the severity of a particular diagnostic.
*/
enum CXDiagnosticSeverity {
/**
- * \brief A diagnostic that has been suppressed, e.g., by a command-line
+ * A diagnostic that has been suppressed, e.g., by a command-line
* option.
*/
CXDiagnostic_Ignored = 0,
/**
- * \brief This diagnostic is a note that should be attached to the
+ * This diagnostic is a note that should be attached to the
* previous (non-note) diagnostic.
*/
CXDiagnostic_Note = 1,
/**
- * \brief This diagnostic indicates suspicious code that may not be
+ * This diagnostic indicates suspicious code that may not be
* wrong.
*/
CXDiagnostic_Warning = 2,
/**
- * \brief This diagnostic indicates that the code is ill-formed.
+ * This diagnostic indicates that the code is ill-formed.
*/
CXDiagnostic_Error = 3,
/**
- * \brief This diagnostic indicates that the code is ill-formed such
+ * This diagnostic indicates that the code is ill-formed such
* that future parser recovery is unlikely to produce useful
* results.
*/
@@ -770,23 +777,23 @@ enum CXDiagnosticSeverity {
};
/**
- * \brief A single diagnostic, containing the diagnostic's severity,
+ * A single diagnostic, containing the diagnostic's severity,
* location, text, source ranges, and fix-it hints.
*/
typedef void *CXDiagnostic;
/**
- * \brief A group of CXDiagnostics.
+ * A group of CXDiagnostics.
*/
typedef void *CXDiagnosticSet;
-
+
/**
- * \brief Determine the number of diagnostics in a CXDiagnosticSet.
+ * Determine the number of diagnostics in a CXDiagnosticSet.
*/
CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
/**
- * \brief Retrieve a diagnostic associated with the given CXDiagnosticSet.
+ * Retrieve a diagnostic associated with the given CXDiagnosticSet.
*
* \param Diags the CXDiagnosticSet to query.
* \param Index the zero-based diagnostic number to retrieve.
@@ -795,39 +802,39 @@ CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
* via a call to \c clang_disposeDiagnostic().
*/
CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
- unsigned Index);
+ unsigned Index);
/**
- * \brief Describes the kind of error that occurred (if any) in a call to
+ * Describes the kind of error that occurred (if any) in a call to
* \c clang_loadDiagnostics.
*/
enum CXLoadDiag_Error {
/**
- * \brief Indicates that no error occurred.
+ * Indicates that no error occurred.
*/
CXLoadDiag_None = 0,
-
+
/**
- * \brief Indicates that an unknown error occurred while attempting to
+ * Indicates that an unknown error occurred while attempting to
* deserialize diagnostics.
*/
CXLoadDiag_Unknown = 1,
-
+
/**
- * \brief Indicates that the file containing the serialized diagnostics
+ * Indicates that the file containing the serialized diagnostics
* could not be opened.
*/
CXLoadDiag_CannotLoad = 2,
-
+
/**
- * \brief Indicates that the serialized diagnostics file is invalid or
+ * Indicates that the serialized diagnostics file is invalid or
* corrupt.
*/
CXLoadDiag_InvalidFile = 3
};
-
+
/**
- * \brief Deserialize a set of diagnostics from a Clang diagnostics bitcode
+ * Deserialize a set of diagnostics from a Clang diagnostics bitcode
* file.
*
* \param file The name of the file to deserialize.
@@ -844,12 +851,12 @@ CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file,
CXString *errorString);
/**
- * \brief Release a CXDiagnosticSet and all of its contained diagnostics.
+ * Release a CXDiagnosticSet and all of its contained diagnostics.
*/
CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
/**
- * \brief Retrieve the child diagnostics of a CXDiagnostic.
+ * Retrieve the child diagnostics of a CXDiagnostic.
*
* This CXDiagnosticSet does not need to be released by
* clang_disposeDiagnosticSet.
@@ -857,13 +864,13 @@ CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
/**
- * \brief Determine the number of diagnostics produced for the given
+ * Determine the number of diagnostics produced for the given
* translation unit.
*/
CINDEX_LINKAGE unsigned clang_getNumDiagnostics(CXTranslationUnit Unit);
/**
- * \brief Retrieve a diagnostic associated with the given translation unit.
+ * Retrieve a diagnostic associated with the given translation unit.
*
* \param Unit the translation unit to query.
* \param Index the zero-based diagnostic number to retrieve.
@@ -875,28 +882,28 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit,
unsigned Index);
/**
- * \brief Retrieve the complete set of diagnostics associated with a
+ * Retrieve the complete set of diagnostics associated with a
* translation unit.
*
* \param Unit the translation unit to query.
*/
CINDEX_LINKAGE CXDiagnosticSet
- clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
+ clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
/**
- * \brief Destroy a diagnostic.
+ * Destroy a diagnostic.
*/
CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic);
/**
- * \brief Options to control the display of diagnostics.
+ * Options to control the display of diagnostics.
*
* The values in this enum are meant to be combined to customize the
* behavior of \c clang_formatDiagnostic().
*/
enum CXDiagnosticDisplayOptions {
/**
- * \brief Display the source-location information where the
+ * Display the source-location information where the
* diagnostic was located.
*
* When set, diagnostics will be prefixed by the file, line, and
@@ -911,7 +918,7 @@ enum CXDiagnosticDisplayOptions {
CXDiagnostic_DisplaySourceLocation = 0x01,
/**
- * \brief If displaying the source-location information of the
+ * If displaying the source-location information of the
* diagnostic, also include the column number.
*
* This option corresponds to the clang flag \c -fshow-column.
@@ -919,7 +926,7 @@ enum CXDiagnosticDisplayOptions {
CXDiagnostic_DisplayColumn = 0x02,
/**
- * \brief If displaying the source-location information of the
+ * If displaying the source-location information of the
* diagnostic, also include information about source ranges in a
* machine-parsable format.
*
@@ -927,37 +934,37 @@ enum CXDiagnosticDisplayOptions {
* \c -fdiagnostics-print-source-range-info.
*/
CXDiagnostic_DisplaySourceRanges = 0x04,
-
+
/**
- * \brief Display the option name associated with this diagnostic, if any.
+ * Display the option name associated with this diagnostic, if any.
*
* The option name displayed (e.g., -Wconversion) will be placed in brackets
* after the diagnostic text. This option corresponds to the clang flag
* \c -fdiagnostics-show-option.
*/
CXDiagnostic_DisplayOption = 0x08,
-
+
/**
- * \brief Display the category number associated with this diagnostic, if any.
+ * Display the category number associated with this diagnostic, if any.
*
* The category number is displayed within brackets after the diagnostic text.
- * This option corresponds to the clang flag
+ * This option corresponds to the clang flag
* \c -fdiagnostics-show-category=id.
*/
CXDiagnostic_DisplayCategoryId = 0x10,
/**
- * \brief Display the category name associated with this diagnostic, if any.
+ * Display the category name associated with this diagnostic, if any.
*
* The category name is displayed within brackets after the diagnostic text.
- * This option corresponds to the clang flag
+ * This option corresponds to the clang flag
* \c -fdiagnostics-show-category=name.
*/
CXDiagnostic_DisplayCategoryName = 0x20
};
/**
- * \brief Format the given diagnostic in a manner that is suitable for display.
+ * Format the given diagnostic in a manner that is suitable for display.
*
* This routine will format the given diagnostic to a string, rendering
* the diagnostic according to the various options given. The
@@ -975,7 +982,7 @@ CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic,
unsigned Options);
/**
- * \brief Retrieve the set of display options most similar to the
+ * Retrieve the set of display options most similar to the
* default behavior of the clang compiler.
*
* \returns A set of display options suitable for use with \c
@@ -984,13 +991,13 @@ CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic,
CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void);
/**
- * \brief Determine the severity of the given diagnostic.
+ * Determine the severity of the given diagnostic.
*/
CINDEX_LINKAGE enum CXDiagnosticSeverity
clang_getDiagnosticSeverity(CXDiagnostic);
/**
- * \brief Retrieve the source location of the given diagnostic.
+ * Retrieve the source location of the given diagnostic.
*
* This location is where Clang would print the caret ('^') when
* displaying the diagnostic on the command line.
@@ -998,12 +1005,12 @@ clang_getDiagnosticSeverity(CXDiagnostic);
CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
/**
- * \brief Retrieve the text of the given diagnostic.
+ * Retrieve the text of the given diagnostic.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
/**
- * \brief Retrieve the name of the command-line option that enabled this
+ * Retrieve the name of the command-line option that enabled this
* diagnostic.
*
* \param Diag The diagnostic to be queried.
@@ -1012,16 +1019,16 @@ CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
* diagnostic (if any).
*
* \returns A string that contains the command-line option used to enable this
- * warning, such as "-Wconversion" or "-pedantic".
+ * warning, such as "-Wconversion" or "-pedantic".
*/
CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
CXString *Disable);
/**
- * \brief Retrieve the category number for this diagnostic.
+ * Retrieve the category number for this diagnostic.
*
* Diagnostics can be categorized into groups along with other, related
- * diagnostics (e.g., diagnostics under the same warning flag). This routine
+ * diagnostics (e.g., diagnostics under the same warning flag). This routine
* retrieves the category number for the given diagnostic.
*
* \returns The number of the category that contains this diagnostic, or zero
@@ -1030,11 +1037,11 @@ CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic);
/**
- * \brief Retrieve the name of a particular diagnostic category. This
+ * Retrieve the name of a particular diagnostic category. This
* is now deprecated. Use clang_getDiagnosticCategoryText()
* instead.
*
- * \param Category A diagnostic category number, as returned by
+ * \param Category A diagnostic category number, as returned by
* \c clang_getDiagnosticCategory().
*
* \returns The name of the given diagnostic category.
@@ -1043,20 +1050,20 @@ CINDEX_DEPRECATED CINDEX_LINKAGE
CXString clang_getDiagnosticCategoryName(unsigned Category);
/**
- * \brief Retrieve the diagnostic category text for a given diagnostic.
+ * Retrieve the diagnostic category text for a given diagnostic.
*
* \returns The text of the given diagnostic category.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
-
+
/**
- * \brief Determine the number of source ranges associated with the given
+ * Determine the number of source ranges associated with the given
* diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
/**
- * \brief Retrieve a source range associated with the diagnostic.
+ * Retrieve a source range associated with the diagnostic.
*
* A diagnostic's source ranges highlight important elements in the source
* code. On the command line, Clang displays source ranges by
@@ -1072,13 +1079,13 @@ CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
unsigned Range);
/**
- * \brief Determine the number of fix-it hints associated with the
+ * Determine the number of fix-it hints associated with the
* given diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
/**
- * \brief Retrieve the replacement information for a given fix-it.
+ * Retrieve the replacement information for a given fix-it.
*
* Fix-its are described in terms of a source range whose contents
* should be replaced by a string. This approach generalizes over
@@ -1121,13 +1128,13 @@ CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
*/
/**
- * \brief Get the original translation unit source file name.
+ * Get the original translation unit source file name.
*/
CINDEX_LINKAGE CXString
clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
/**
- * \brief Return the CXTranslationUnit for a given source file and the provided
+ * Return the CXTranslationUnit for a given source file and the provided
* command line arguments one would pass to the compiler.
*
* Note: The 'source_filename' argument is optional. If the caller provides a
@@ -1175,7 +1182,7 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
struct CXUnsavedFile *unsaved_files);
/**
- * \brief Same as \c clang_createTranslationUnit2, but returns
+ * Same as \c clang_createTranslationUnit2, but returns
* the \c CXTranslationUnit instead of an error code. In case of an error this
* routine returns a \c NULL \c CXTranslationUnit, without further detailed
* error codes.
@@ -1185,7 +1192,7 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
const char *ast_filename);
/**
- * \brief Create a translation unit from an AST file (\c -emit-ast).
+ * Create a translation unit from an AST file (\c -emit-ast).
*
* \param[out] out_TU A non-NULL pointer to store the created
* \c CXTranslationUnit.
@@ -1198,7 +1205,7 @@ CINDEX_LINKAGE enum CXErrorCode clang_createTranslationUnit2(
CXTranslationUnit *out_TU);
/**
- * \brief Flags that control the creation of translation units.
+ * Flags that control the creation of translation units.
*
* The enumerators in this enumeration type are meant to be bitwise
* ORed together to specify which options should be used when
@@ -1206,13 +1213,13 @@ CINDEX_LINKAGE enum CXErrorCode clang_createTranslationUnit2(
*/
enum CXTranslationUnit_Flags {
/**
- * \brief Used to indicate that no special translation-unit options are
+ * Used to indicate that no special translation-unit options are
* needed.
*/
CXTranslationUnit_None = 0x0,
/**
- * \brief Used to indicate that the parser should construct a "detailed"
+ * Used to indicate that the parser should construct a "detailed"
* preprocessing record, including all macro definitions and instantiations.
*
* Constructing a detailed preprocessing record requires more memory
@@ -1224,7 +1231,7 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
/**
- * \brief Used to indicate that the translation unit is incomplete.
+ * Used to indicate that the translation unit is incomplete.
*
* When a translation unit is considered "incomplete", semantic
* analysis that is typically performed at the end of the
@@ -1235,9 +1242,9 @@ enum CXTranslationUnit_Flags {
* intent of producing a precompiled header.
*/
CXTranslationUnit_Incomplete = 0x02,
-
+
/**
- * \brief Used to indicate that the translation unit should be built with an
+ * Used to indicate that the translation unit should be built with an
* implicit precompiled header for the preamble.
*
* An implicit precompiled header is used as an optimization when a
@@ -1251,9 +1258,9 @@ enum CXTranslationUnit_Flags {
* precompiled header to improve parsing performance.
*/
CXTranslationUnit_PrecompiledPreamble = 0x04,
-
+
/**
- * \brief Used to indicate that the translation unit should cache some
+ * Used to indicate that the translation unit should cache some
* code-completion results with each reparse of the source file.
*
* Caching of code-completion results is a performance optimization that
@@ -1263,7 +1270,7 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_CacheCompletionResults = 0x08,
/**
- * \brief Used to indicate that the translation unit will be serialized with
+ * Used to indicate that the translation unit will be serialized with
* \c clang_saveTranslationUnit.
*
* This option is typically used when parsing a header with the intent of
@@ -1272,7 +1279,7 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_ForSerialization = 0x10,
/**
- * \brief DEPRECATED: Enabled chained precompiled preambles in C++.
+ * DEPRECATED: Enabled chained precompiled preambles in C++.
*
* Note: this is a *temporary* option that is available only while
* we are testing C++ precompiled preamble support. It is deprecated.
@@ -1280,7 +1287,7 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_CXXChainedPCH = 0x20,
/**
- * \brief Used to indicate that function/method bodies should be skipped while
+ * Used to indicate that function/method bodies should be skipped while
* parsing.
*
* This option can be used to search for declarations/definitions while
@@ -1289,14 +1296,14 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_SkipFunctionBodies = 0x40,
/**
- * \brief Used to indicate that brief documentation comments should be
+ * Used to indicate that brief documentation comments should be
* included into the set of code completions returned from this translation
* unit.
*/
CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80,
/**
- * \brief Used to indicate that the precompiled preamble should be created on
+ * Used to indicate that the precompiled preamble should be created on
* the first parse. Otherwise it will be created on the first reparse. This
* trades runtime on the first parse (serializing the preamble takes time) for
* reduced runtime on the second parse (can now reuse the preamble).
@@ -1304,7 +1311,7 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_CreatePreambleOnFirstParse = 0x100,
/**
- * \brief Do not stop processing when fatal errors are encountered.
+ * Do not stop processing when fatal errors are encountered.
*
* When fatal errors are encountered while parsing a translation unit,
* semantic analysis is typically stopped early when compiling code. A common
@@ -1315,27 +1322,35 @@ enum CXTranslationUnit_Flags {
CXTranslationUnit_KeepGoing = 0x200,
/**
- * \brief Sets the preprocessor in a mode for parsing a single file only.
+ * Sets the preprocessor in a mode for parsing a single file only.
*/
- CXTranslationUnit_SingleFileParse = 0x400
+ CXTranslationUnit_SingleFileParse = 0x400,
+
+ /**
+ * Used in combination with CXTranslationUnit_SkipFunctionBodies to
+ * constrain the skipping of function bodies to the preamble.
+ *
+ * The function bodies of the main file are not skipped.
+ */
+ CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800
};
/**
- * \brief Returns the set of flags that is suitable for parsing a translation
+ * Returns the set of flags that is suitable for parsing a translation
* unit that is being edited.
*
* The set of flags returned provide options for \c clang_parseTranslationUnit()
* to indicate that the translation unit is likely to be reparsed many times,
* either explicitly (via \c clang_reparseTranslationUnit()) or implicitly
* (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag
- * set contains an unspecified set of optimizations (e.g., the precompiled
+ * set contains an unspecified set of optimizations (e.g., the precompiled
* preamble) geared toward improving the performance of these routines. The
* set of optimizations enabled may change from one version to the next.
*/
CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
/**
- * \brief Same as \c clang_parseTranslationUnit2, but returns
+ * Same as \c clang_parseTranslationUnit2, but returns
* the \c CXTranslationUnit instead of an error code. In case of an error this
* routine returns a \c NULL \c CXTranslationUnit, without further detailed
* error codes.
@@ -1350,7 +1365,7 @@ clang_parseTranslationUnit(CXIndex CIdx,
unsigned options);
/**
- * \brief Parse the given source file and the translation unit corresponding
+ * Parse the given source file and the translation unit corresponding
* to that file.
*
* This routine is the main entry point for the Clang C API, providing the
@@ -1359,7 +1374,7 @@ clang_parseTranslationUnit(CXIndex CIdx,
* command-line arguments so that the compilation can be configured in the same
* way that the compiler is configured on the command line.
*
- * \param CIdx The index object with which the translation unit will be
+ * \param CIdx The index object with which the translation unit will be
* associated.
*
* \param source_filename The name of the source file to load, or NULL if the
@@ -1368,7 +1383,7 @@ clang_parseTranslationUnit(CXIndex CIdx,
* \param command_line_args The command-line arguments that would be
* passed to the \c clang executable if it were being invoked out-of-process.
* These command-line options will be parsed and will affect how the translation
- * unit is parsed. Note that the following options are ignored: '-c',
+ * unit is parsed. Note that the following options are ignored: '-c',
* '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
*
* \param num_command_line_args The number of command-line arguments in
@@ -1404,7 +1419,7 @@ clang_parseTranslationUnit2(CXIndex CIdx,
CXTranslationUnit *out_TU);
/**
- * \brief Same as clang_parseTranslationUnit2 but requires a full command line
+ * Same as clang_parseTranslationUnit2 but requires a full command line
* for \c command_line_args including argv[0]. This is useful if the standard
* library paths are relative to the binary.
*/
@@ -1415,7 +1430,7 @@ CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv(
unsigned options, CXTranslationUnit *out_TU);
/**
- * \brief Flags that control how translation units are saved.
+ * Flags that control how translation units are saved.
*
* The enumerators in this enumeration type are meant to be bitwise
* ORed together to specify which options should be used when
@@ -1423,13 +1438,13 @@ CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv(
*/
enum CXSaveTranslationUnit_Flags {
/**
- * \brief Used to indicate that no special saving options are needed.
+ * Used to indicate that no special saving options are needed.
*/
CXSaveTranslationUnit_None = 0x0
};
/**
- * \brief Returns the set of flags that is suitable for saving a translation
+ * Returns the set of flags that is suitable for saving a translation
* unit.
*
* The set of flags returned provide options for
@@ -1440,42 +1455,42 @@ enum CXSaveTranslationUnit_Flags {
CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU);
/**
- * \brief Describes the kind of error that occurred (if any) in a call to
+ * Describes the kind of error that occurred (if any) in a call to
* \c clang_saveTranslationUnit().
*/
enum CXSaveError {
/**
- * \brief Indicates that no error occurred while saving a translation unit.
+ * Indicates that no error occurred while saving a translation unit.
*/
CXSaveError_None = 0,
-
+
/**
- * \brief Indicates that an unknown error occurred while attempting to save
+ * Indicates that an unknown error occurred while attempting to save
* the file.
*
- * This error typically indicates that file I/O failed when attempting to
+ * This error typically indicates that file I/O failed when attempting to
* write the file.
*/
CXSaveError_Unknown = 1,
-
+
/**
- * \brief Indicates that errors during translation prevented this attempt
+ * Indicates that errors during translation prevented this attempt
* to save the translation unit.
- *
+ *
* Errors that prevent the translation unit from being saved can be
* extracted using \c clang_getNumDiagnostics() and \c clang_getDiagnostic().
*/
CXSaveError_TranslationErrors = 2,
-
+
/**
- * \brief Indicates that the translation unit to be saved was somehow
+ * Indicates that the translation unit to be saved was somehow
* invalid (e.g., NULL).
*/
CXSaveError_InvalidTU = 3
};
-
+
/**
- * \brief Saves a translation unit into a serialized representation of
+ * Saves a translation unit into a serialized representation of
* that translation unit on disk.
*
* Any translation unit that was parsed without error can be saved
@@ -1494,7 +1509,7 @@ enum CXSaveError {
* CXSaveTranslationUnit_XXX flags.
*
* \returns A value that will match one of the enumerators of the CXSaveError
- * enumeration. Zero (CXSaveError_None) indicates that the translation unit was
+ * enumeration. Zero (CXSaveError_None) indicates that the translation unit was
* saved successfully, while a non-zero value indicates that a problem occurred.
*/
CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
@@ -1502,7 +1517,7 @@ CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
unsigned options);
/**
- * \brief Suspend a translation unit in order to free memory associated with it.
+ * Suspend a translation unit in order to free memory associated with it.
*
* A suspended translation unit uses significantly less memory but on the other
* side does not support any other calls than \c clang_reparseTranslationUnit
@@ -1511,12 +1526,12 @@ CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
CINDEX_LINKAGE unsigned clang_suspendTranslationUnit(CXTranslationUnit);
/**
- * \brief Destroy the specified CXTranslationUnit object.
+ * Destroy the specified CXTranslationUnit object.
*/
CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
/**
- * \brief Flags that control the reparsing of translation units.
+ * Flags that control the reparsing of translation units.
*
* The enumerators in this enumeration type are meant to be bitwise
* ORed together to specify which options should be used when
@@ -1524,41 +1539,41 @@ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
*/
enum CXReparse_Flags {
/**
- * \brief Used to indicate that no special reparsing options are needed.
+ * Used to indicate that no special reparsing options are needed.
*/
CXReparse_None = 0x0
};
-
+
/**
- * \brief Returns the set of flags that is suitable for reparsing a translation
+ * Returns the set of flags that is suitable for reparsing a translation
* unit.
*
* The set of flags returned provide options for
* \c clang_reparseTranslationUnit() by default. The returned flag
* set contains an unspecified set of optimizations geared toward common uses
- * of reparsing. The set of optimizations enabled may change from one version
+ * of reparsing. The set of optimizations enabled may change from one version
* to the next.
*/
CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
/**
- * \brief Reparse the source files that produced this translation unit.
+ * Reparse the source files that produced this translation unit.
*
* This routine can be used to re-parse the source files that originally
* created the given translation unit, for example because those source files
* have changed (either on disk or as passed via \p unsaved_files). The
* source code will be reparsed with the same command-line options as it
- * was originally parsed.
+ * was originally parsed.
*
* Reparsing a translation unit invalidates all cursors and source locations
* that refer into that translation unit. This makes reparsing a translation
* unit semantically equivalent to destroying the translation unit and then
* creating a new translation unit with the same command-line arguments.
- * However, it may be more efficient to reparse a translation
+ * However, it may be more efficient to reparse a translation
* unit using this routine.
*
* \param TU The translation unit whose contents will be re-parsed. The
- * translation unit must originally have been built with
+ * translation unit must originally have been built with
* \c clang_createTranslationUnitFromSourceFile().
*
* \param num_unsaved_files The number of unsaved file entries in \p
@@ -1569,7 +1584,7 @@ CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
* those files. The contents and name of these files (as specified by
* CXUnsavedFile) are copied when necessary, so the client only needs to
* guarantee their validity until the call to this function returns.
- *
+ *
* \param options A bitset of options composed of the flags in CXReparse_Flags.
* The function \c clang_defaultReparseOptions() produces a default set of
* options recommended for most uses, based on the translation unit.
@@ -1586,7 +1601,7 @@ CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,
unsigned options);
/**
- * \brief Categorizes how memory is being used by a translation unit.
+ * Categorizes how memory is being used by a translation unit.
*/
enum CXTUResourceUsageKind {
CXTUResourceUsage_AST = 1,
@@ -1597,8 +1612,8 @@ enum CXTUResourceUsageKind {
CXTUResourceUsage_AST_SideTables = 6,
CXTUResourceUsage_SourceManager_Membuffer_Malloc = 7,
CXTUResourceUsage_SourceManager_Membuffer_MMap = 8,
- CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9,
- CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10,
CXTUResourceUsage_Preprocessor = 11,
CXTUResourceUsage_PreprocessingRecord = 12,
CXTUResourceUsage_SourceManager_DataStructures = 13,
@@ -1612,38 +1627,38 @@ enum CXTUResourceUsageKind {
};
/**
- * \brief Returns the human-readable null-terminated C string that represents
+ * Returns the human-readable null-terminated C string that represents
* the name of the memory category. This string should never be freed.
*/
CINDEX_LINKAGE
const char *clang_getTUResourceUsageName(enum CXTUResourceUsageKind kind);
typedef struct CXTUResourceUsageEntry {
- /* \brief The memory usage category. */
- enum CXTUResourceUsageKind kind;
- /* \brief Amount of resources used.
+ /* The memory usage category. */
+ enum CXTUResourceUsageKind kind;
+ /* Amount of resources used.
The units will depend on the resource kind. */
unsigned long amount;
} CXTUResourceUsageEntry;
/**
- * \brief The memory usage of a CXTranslationUnit, broken into categories.
+ * The memory usage of a CXTranslationUnit, broken into categories.
*/
typedef struct CXTUResourceUsage {
- /* \brief Private data member, used for queries. */
+ /* Private data member, used for queries. */
void *data;
- /* \brief The number of entries in the 'entries' array. */
+ /* The number of entries in the 'entries' array. */
unsigned numEntries;
- /* \brief An array of key-value pairs, representing the breakdown of memory
+ /* An array of key-value pairs, representing the breakdown of memory
usage. */
CXTUResourceUsageEntry *entries;
} CXTUResourceUsage;
/**
- * \brief Return the memory usage of a translation unit. This object
+ * Return the memory usage of a translation unit. This object
* should be released with clang_disposeCXTUResourceUsage().
*/
CINDEX_LINKAGE CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU);
@@ -1651,7 +1666,7 @@ CINDEX_LINKAGE CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU
CINDEX_LINKAGE void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage);
/**
- * \brief Get target information for this translation unit.
+ * Get target information for this translation unit.
*
* The CXTargetInfo object cannot outlive the CXTranslationUnit object.
*/
@@ -1659,13 +1674,13 @@ CINDEX_LINKAGE CXTargetInfo
clang_getTranslationUnitTargetInfo(CXTranslationUnit CTUnit);
/**
- * \brief Destroy the CXTargetInfo object.
+ * Destroy the CXTargetInfo object.
*/
CINDEX_LINKAGE void
clang_TargetInfo_dispose(CXTargetInfo Info);
/**
- * \brief Get the normalized target triple as a string.
+ * Get the normalized target triple as a string.
*
* Returns the empty string in case of any error.
*/
@@ -1673,7 +1688,7 @@ CINDEX_LINKAGE CXString
clang_TargetInfo_getTriple(CXTargetInfo Info);
/**
- * \brief Get the pointer width of the target in bits.
+ * Get the pointer width of the target in bits.
*
* Returns -1 in case of error.
*/
@@ -1685,12 +1700,12 @@ clang_TargetInfo_getPointerWidth(CXTargetInfo Info);
*/
/**
- * \brief Describes the kind of entity that a cursor refers to.
+ * Describes the kind of entity that a cursor refers to.
*/
enum CXCursorKind {
/* Declarations */
/**
- * \brief A declaration whose specific kind is not exposed via this
+ * A declaration whose specific kind is not exposed via this
* interface.
*
* Unexposed declarations have the same operations as any other kind
@@ -1699,84 +1714,84 @@ enum CXCursorKind {
* of the declaration is not reported.
*/
CXCursor_UnexposedDecl = 1,
- /** \brief A C or C++ struct. */
+ /** A C or C++ struct. */
CXCursor_StructDecl = 2,
- /** \brief A C or C++ union. */
+ /** A C or C++ union. */
CXCursor_UnionDecl = 3,
- /** \brief A C++ class. */
+ /** A C++ class. */
CXCursor_ClassDecl = 4,
- /** \brief An enumeration. */
+ /** An enumeration. */
CXCursor_EnumDecl = 5,
/**
- * \brief A field (in C) or non-static data member (in C++) in a
+ * A field (in C) or non-static data member (in C++) in a
* struct, union, or C++ class.
*/
CXCursor_FieldDecl = 6,
- /** \brief An enumerator constant. */
+ /** An enumerator constant. */
CXCursor_EnumConstantDecl = 7,
- /** \brief A function. */
+ /** A function. */
CXCursor_FunctionDecl = 8,
- /** \brief A variable. */
+ /** A variable. */
CXCursor_VarDecl = 9,
- /** \brief A function or method parameter. */
+ /** A function or method parameter. */
CXCursor_ParmDecl = 10,
- /** \brief An Objective-C \@interface. */
+ /** An Objective-C \@interface. */
CXCursor_ObjCInterfaceDecl = 11,
- /** \brief An Objective-C \@interface for a category. */
+ /** An Objective-C \@interface for a category. */
CXCursor_ObjCCategoryDecl = 12,
- /** \brief An Objective-C \@protocol declaration. */
+ /** An Objective-C \@protocol declaration. */
CXCursor_ObjCProtocolDecl = 13,
- /** \brief An Objective-C \@property declaration. */
+ /** An Objective-C \@property declaration. */
CXCursor_ObjCPropertyDecl = 14,
- /** \brief An Objective-C instance variable. */
+ /** An Objective-C instance variable. */
CXCursor_ObjCIvarDecl = 15,
- /** \brief An Objective-C instance method. */
+ /** An Objective-C instance method. */
CXCursor_ObjCInstanceMethodDecl = 16,
- /** \brief An Objective-C class method. */
+ /** An Objective-C class method. */
CXCursor_ObjCClassMethodDecl = 17,
- /** \brief An Objective-C \@implementation. */
+ /** An Objective-C \@implementation. */
CXCursor_ObjCImplementationDecl = 18,
- /** \brief An Objective-C \@implementation for a category. */
+ /** An Objective-C \@implementation for a category. */
CXCursor_ObjCCategoryImplDecl = 19,
- /** \brief A typedef. */
+ /** A typedef. */
CXCursor_TypedefDecl = 20,
- /** \brief A C++ class method. */
+ /** A C++ class method. */
CXCursor_CXXMethod = 21,
- /** \brief A C++ namespace. */
+ /** A C++ namespace. */
CXCursor_Namespace = 22,
- /** \brief A linkage specification, e.g. 'extern "C"'. */
+ /** A linkage specification, e.g. 'extern "C"'. */
CXCursor_LinkageSpec = 23,
- /** \brief A C++ constructor. */
+ /** A C++ constructor. */
CXCursor_Constructor = 24,
- /** \brief A C++ destructor. */
+ /** A C++ destructor. */
CXCursor_Destructor = 25,
- /** \brief A C++ conversion function. */
+ /** A C++ conversion function. */
CXCursor_ConversionFunction = 26,
- /** \brief A C++ template type parameter. */
+ /** A C++ template type parameter. */
CXCursor_TemplateTypeParameter = 27,
- /** \brief A C++ non-type template parameter. */
+ /** A C++ non-type template parameter. */
CXCursor_NonTypeTemplateParameter = 28,
- /** \brief A C++ template template parameter. */
+ /** A C++ template template parameter. */
CXCursor_TemplateTemplateParameter = 29,
- /** \brief A C++ function template. */
+ /** A C++ function template. */
CXCursor_FunctionTemplate = 30,
- /** \brief A C++ class template. */
+ /** A C++ class template. */
CXCursor_ClassTemplate = 31,
- /** \brief A C++ class template partial specialization. */
+ /** A C++ class template partial specialization. */
CXCursor_ClassTemplatePartialSpecialization = 32,
- /** \brief A C++ namespace alias declaration. */
+ /** A C++ namespace alias declaration. */
CXCursor_NamespaceAlias = 33,
- /** \brief A C++ using directive. */
+ /** A C++ using directive. */
CXCursor_UsingDirective = 34,
- /** \brief A C++ using declaration. */
+ /** A C++ using declaration. */
CXCursor_UsingDeclaration = 35,
- /** \brief A C++ alias declaration */
+ /** A C++ alias declaration */
CXCursor_TypeAliasDecl = 36,
- /** \brief An Objective-C \@synthesize definition. */
+ /** An Objective-C \@synthesize definition. */
CXCursor_ObjCSynthesizeDecl = 37,
- /** \brief An Objective-C \@dynamic definition. */
+ /** An Objective-C \@dynamic definition. */
CXCursor_ObjCDynamicDecl = 38,
- /** \brief An access specifier. */
+ /** An access specifier. */
CXCursor_CXXAccessSpecifier = 39,
CXCursor_FirstDecl = CXCursor_UnexposedDecl,
@@ -1788,7 +1803,7 @@ enum CXCursorKind {
CXCursor_ObjCProtocolRef = 41,
CXCursor_ObjCClassRef = 42,
/**
- * \brief A reference to a type declaration.
+ * A reference to a type declaration.
*
* A type reference occurs anywhere where a type is named but not
* declared. For example, given:
@@ -1804,24 +1819,24 @@ enum CXCursorKind {
*/
CXCursor_TypeRef = 43,
CXCursor_CXXBaseSpecifier = 44,
- /**
- * \brief A reference to a class template, function template, template
+ /**
+ * A reference to a class template, function template, template
* template parameter, or class template partial specialization.
*/
CXCursor_TemplateRef = 45,
/**
- * \brief A reference to a namespace or namespace alias.
+ * A reference to a namespace or namespace alias.
*/
CXCursor_NamespaceRef = 46,
/**
- * \brief A reference to a member of a struct, union, or class that occurs in
+ * A reference to a member of a struct, union, or class that occurs in
* some non-expression context, e.g., a designated initializer.
*/
CXCursor_MemberRef = 47,
/**
- * \brief A reference to a labeled statement.
+ * A reference to a labeled statement.
*
- * This cursor kind is used to describe the jump to "start_over" in the
+ * This cursor kind is used to describe the jump to "start_over" in the
* goto statement in the following example:
*
* \code
@@ -1834,9 +1849,9 @@ enum CXCursorKind {
* A label reference cursor refers to a label statement.
*/
CXCursor_LabelRef = 48,
-
+
/**
- * \brief A reference to a set of overloaded functions or function templates
+ * A reference to a set of overloaded functions or function templates
* that has not yet been resolved to a specific function or function template.
*
* An overloaded declaration reference cursor occurs in C++ templates where
@@ -1867,18 +1882,18 @@ enum CXCursorKind {
* argument-dependent lookup (e.g., the "swap" function at the end of the
* example).
*
- * The functions \c clang_getNumOverloadedDecls() and
+ * The functions \c clang_getNumOverloadedDecls() and
* \c clang_getOverloadedDecl() can be used to retrieve the definitions
* referenced by this cursor.
*/
CXCursor_OverloadedDeclRef = 49,
-
+
/**
- * \brief A reference to a variable that occurs in some non-expression
+ * A reference to a variable that occurs in some non-expression
* context, e.g., a C++ lambda capture list.
*/
CXCursor_VariableRef = 50,
-
+
CXCursor_LastRef = CXCursor_VariableRef,
/* Error conditions */
@@ -1893,7 +1908,7 @@ enum CXCursorKind {
CXCursor_FirstExpr = 100,
/**
- * \brief An expression whose specific kind is not exposed via this
+ * An expression whose specific kind is not exposed via this
* interface.
*
* Unexposed expressions have the same operations as any other kind
@@ -1904,103 +1919,103 @@ enum CXCursorKind {
CXCursor_UnexposedExpr = 100,
/**
- * \brief An expression that refers to some value declaration, such
+ * An expression that refers to some value declaration, such
* as a function, variable, or enumerator.
*/
CXCursor_DeclRefExpr = 101,
/**
- * \brief An expression that refers to a member of a struct, union,
+ * An expression that refers to a member of a struct, union,
* class, Objective-C class, etc.
*/
CXCursor_MemberRefExpr = 102,
- /** \brief An expression that calls a function. */
+ /** An expression that calls a function. */
CXCursor_CallExpr = 103,
- /** \brief An expression that sends a message to an Objective-C
+ /** An expression that sends a message to an Objective-C
object or class. */
CXCursor_ObjCMessageExpr = 104,
- /** \brief An expression that represents a block literal. */
+ /** An expression that represents a block literal. */
CXCursor_BlockExpr = 105,
- /** \brief An integer literal.
+ /** An integer literal.
*/
CXCursor_IntegerLiteral = 106,
- /** \brief A floating point number literal.
+ /** A floating point number literal.
*/
CXCursor_FloatingLiteral = 107,
- /** \brief An imaginary number literal.
+ /** An imaginary number literal.
*/
CXCursor_ImaginaryLiteral = 108,
- /** \brief A string literal.
+ /** A string literal.
*/
CXCursor_StringLiteral = 109,
- /** \brief A character literal.
+ /** A character literal.
*/
CXCursor_CharacterLiteral = 110,
- /** \brief A parenthesized expression, e.g. "(1)".
+ /** A parenthesized expression, e.g. "(1)".
*
* This AST node is only formed if full location information is requested.
*/
CXCursor_ParenExpr = 111,
- /** \brief This represents the unary-expression's (except sizeof and
+ /** This represents the unary-expression's (except sizeof and
* alignof).
*/
CXCursor_UnaryOperator = 112,
- /** \brief [C99 6.5.2.1] Array Subscripting.
+ /** [C99 6.5.2.1] Array Subscripting.
*/
CXCursor_ArraySubscriptExpr = 113,
- /** \brief A builtin binary operation expression such as "x + y" or
+ /** A builtin binary operation expression such as "x + y" or
* "x <= y".
*/
CXCursor_BinaryOperator = 114,
- /** \brief Compound assignment such as "+=".
+ /** Compound assignment such as "+=".
*/
CXCursor_CompoundAssignOperator = 115,
- /** \brief The ?: ternary operator.
+ /** The ?: ternary operator.
*/
CXCursor_ConditionalOperator = 116,
- /** \brief An explicit cast in C (C99 6.5.4) or a C-style cast in C++
+ /** An explicit cast in C (C99 6.5.4) or a C-style cast in C++
* (C++ [expr.cast]), which uses the syntax (Type)expr.
*
* For example: (int)f.
*/
CXCursor_CStyleCastExpr = 117,
- /** \brief [C99 6.5.2.5]
+ /** [C99 6.5.2.5]
*/
CXCursor_CompoundLiteralExpr = 118,
- /** \brief Describes an C or C++ initializer list.
+ /** Describes an C or C++ initializer list.
*/
CXCursor_InitListExpr = 119,
- /** \brief The GNU address of label extension, representing &&label.
+ /** The GNU address of label extension, representing &&label.
*/
CXCursor_AddrLabelExpr = 120,
- /** \brief This is the GNU Statement Expression extension: ({int X=4; X;})
+ /** This is the GNU Statement Expression extension: ({int X=4; X;})
*/
CXCursor_StmtExpr = 121,
- /** \brief Represents a C11 generic selection.
+ /** Represents a C11 generic selection.
*/
CXCursor_GenericSelectionExpr = 122,
- /** \brief Implements the GNU __null extension, which is a name for a null
+ /** Implements the GNU __null extension, which is a name for a null
* pointer constant that has integral type (e.g., int or long) and is the same
* size and alignment as a pointer.
*
@@ -2010,23 +2025,23 @@ enum CXCursorKind {
*/
CXCursor_GNUNullExpr = 123,
- /** \brief C++'s static_cast<> expression.
+ /** C++'s static_cast<> expression.
*/
CXCursor_CXXStaticCastExpr = 124,
- /** \brief C++'s dynamic_cast<> expression.
+ /** C++'s dynamic_cast<> expression.
*/
CXCursor_CXXDynamicCastExpr = 125,
- /** \brief C++'s reinterpret_cast<> expression.
+ /** C++'s reinterpret_cast<> expression.
*/
CXCursor_CXXReinterpretCastExpr = 126,
- /** \brief C++'s const_cast<> expression.
+ /** C++'s const_cast<> expression.
*/
CXCursor_CXXConstCastExpr = 127,
- /** \brief Represents an explicit C++ type conversion that uses "functional"
+ /** Represents an explicit C++ type conversion that uses "functional"
* notion (C++ [expr.type.conv]).
*
* Example:
@@ -2036,60 +2051,60 @@ enum CXCursorKind {
*/
CXCursor_CXXFunctionalCastExpr = 128,
- /** \brief A C++ typeid expression (C++ [expr.typeid]).
+ /** A C++ typeid expression (C++ [expr.typeid]).
*/
CXCursor_CXXTypeidExpr = 129,
- /** \brief [C++ 2.13.5] C++ Boolean Literal.
+ /** [C++ 2.13.5] C++ Boolean Literal.
*/
CXCursor_CXXBoolLiteralExpr = 130,
- /** \brief [C++0x 2.14.7] C++ Pointer Literal.
+ /** [C++0x 2.14.7] C++ Pointer Literal.
*/
CXCursor_CXXNullPtrLiteralExpr = 131,
- /** \brief Represents the "this" expression in C++
+ /** Represents the "this" expression in C++
*/
CXCursor_CXXThisExpr = 132,
- /** \brief [C++ 15] C++ Throw Expression.
+ /** [C++ 15] C++ Throw Expression.
*
* This handles 'throw' and 'throw' assignment-expression. When
* assignment-expression isn't present, Op will be null.
*/
CXCursor_CXXThrowExpr = 133,
- /** \brief A new expression for memory allocation and constructor calls, e.g:
+ /** A new expression for memory allocation and constructor calls, e.g:
* "new CXXNewExpr(foo)".
*/
CXCursor_CXXNewExpr = 134,
- /** \brief A delete expression for memory deallocation and destructor calls,
+ /** A delete expression for memory deallocation and destructor calls,
* e.g. "delete[] pArray".
*/
CXCursor_CXXDeleteExpr = 135,
- /** \brief A unary expression. (noexcept, sizeof, or other traits)
+ /** A unary expression. (noexcept, sizeof, or other traits)
*/
CXCursor_UnaryExpr = 136,
- /** \brief An Objective-C string literal i.e. @"foo".
+ /** An Objective-C string literal i.e. @"foo".
*/
CXCursor_ObjCStringLiteral = 137,
- /** \brief An Objective-C \@encode expression.
+ /** An Objective-C \@encode expression.
*/
CXCursor_ObjCEncodeExpr = 138,
- /** \brief An Objective-C \@selector expression.
+ /** An Objective-C \@selector expression.
*/
CXCursor_ObjCSelectorExpr = 139,
- /** \brief An Objective-C \@protocol expression.
+ /** An Objective-C \@protocol expression.
*/
CXCursor_ObjCProtocolExpr = 140,
- /** \brief An Objective-C "bridged" cast expression, which casts between
+ /** An Objective-C "bridged" cast expression, which casts between
* Objective-C pointers and C pointers, transferring ownership in the process.
*
* \code
@@ -2098,7 +2113,7 @@ enum CXCursorKind {
*/
CXCursor_ObjCBridgedCastExpr = 141,
- /** \brief Represents a C++0x pack expansion that produces a sequence of
+ /** Represents a C++0x pack expansion that produces a sequence of
* expressions.
*
* A pack expansion expression contains a pattern (which itself is an
@@ -2113,7 +2128,7 @@ enum CXCursorKind {
*/
CXCursor_PackExpansionExpr = 142,
- /** \brief Represents an expression that computes the length of a parameter
+ /** Represents an expression that computes the length of a parameter
* pack.
*
* \code
@@ -2125,7 +2140,7 @@ enum CXCursorKind {
*/
CXCursor_SizeOfPackExpr = 143,
- /* \brief Represents a C++ lambda expression that produces a local function
+ /* Represents a C++ lambda expression that produces a local function
* object.
*
* \code
@@ -2138,29 +2153,34 @@ enum CXCursorKind {
* \endcode
*/
CXCursor_LambdaExpr = 144,
-
- /** \brief Objective-c Boolean Literal.
+
+ /** Objective-c Boolean Literal.
*/
CXCursor_ObjCBoolLiteralExpr = 145,
- /** \brief Represents the "self" expression in an Objective-C method.
+ /** Represents the "self" expression in an Objective-C method.
*/
CXCursor_ObjCSelfExpr = 146,
- /** \brief OpenMP 4.0 [2.4, Array Section].
+ /** OpenMP 4.0 [2.4, Array Section].
*/
CXCursor_OMPArraySectionExpr = 147,
- /** \brief Represents an @available(...) check.
+ /** Represents an @available(...) check.
*/
CXCursor_ObjCAvailabilityCheckExpr = 148,
- CXCursor_LastExpr = CXCursor_ObjCAvailabilityCheckExpr,
+ /**
+ * Fixed point literal
+ */
+ CXCursor_FixedPointLiteral = 149,
+
+ CXCursor_LastExpr = CXCursor_FixedPointLiteral,
/* Statements */
CXCursor_FirstStmt = 200,
/**
- * \brief A statement whose specific kind is not exposed via this
+ * A statement whose specific kind is not exposed via this
* interface.
*
* Unexposed statements have the same operations as any other kind of
@@ -2169,10 +2189,10 @@ enum CXCursorKind {
* reported.
*/
CXCursor_UnexposedStmt = 200,
-
- /** \brief A labelled statement in a function.
+
+ /** A labelled statement in a function.
*
- * This cursor kind is used to describe the "start_over:" label statement in
+ * This cursor kind is used to describe the "start_over:" label statement in
* the following example:
*
* \code
@@ -2183,329 +2203,329 @@ enum CXCursorKind {
*/
CXCursor_LabelStmt = 201,
- /** \brief A group of statements like { stmt stmt }.
+ /** A group of statements like { stmt stmt }.
*
* This cursor kind is used to describe compound statements, e.g. function
* bodies.
*/
CXCursor_CompoundStmt = 202,
- /** \brief A case statement.
+ /** A case statement.
*/
CXCursor_CaseStmt = 203,
- /** \brief A default statement.
+ /** A default statement.
*/
CXCursor_DefaultStmt = 204,
- /** \brief An if statement
+ /** An if statement
*/
CXCursor_IfStmt = 205,
- /** \brief A switch statement.
+ /** A switch statement.
*/
CXCursor_SwitchStmt = 206,
- /** \brief A while statement.
+ /** A while statement.
*/
CXCursor_WhileStmt = 207,
- /** \brief A do statement.
+ /** A do statement.
*/
CXCursor_DoStmt = 208,
- /** \brief A for statement.
+ /** A for statement.
*/
CXCursor_ForStmt = 209,
- /** \brief A goto statement.
+ /** A goto statement.
*/
CXCursor_GotoStmt = 210,
- /** \brief An indirect goto statement.
+ /** An indirect goto statement.
*/
CXCursor_IndirectGotoStmt = 211,
- /** \brief A continue statement.
+ /** A continue statement.
*/
CXCursor_ContinueStmt = 212,
- /** \brief A break statement.
+ /** A break statement.
*/
CXCursor_BreakStmt = 213,
- /** \brief A return statement.
+ /** A return statement.
*/
CXCursor_ReturnStmt = 214,
- /** \brief A GCC inline assembly statement extension.
+ /** A GCC inline assembly statement extension.
*/
CXCursor_GCCAsmStmt = 215,
CXCursor_AsmStmt = CXCursor_GCCAsmStmt,
- /** \brief Objective-C's overall \@try-\@catch-\@finally statement.
+ /** Objective-C's overall \@try-\@catch-\@finally statement.
*/
CXCursor_ObjCAtTryStmt = 216,
- /** \brief Objective-C's \@catch statement.
+ /** Objective-C's \@catch statement.
*/
CXCursor_ObjCAtCatchStmt = 217,
- /** \brief Objective-C's \@finally statement.
+ /** Objective-C's \@finally statement.
*/
CXCursor_ObjCAtFinallyStmt = 218,
- /** \brief Objective-C's \@throw statement.
+ /** Objective-C's \@throw statement.
*/
CXCursor_ObjCAtThrowStmt = 219,
- /** \brief Objective-C's \@synchronized statement.
+ /** Objective-C's \@synchronized statement.
*/
CXCursor_ObjCAtSynchronizedStmt = 220,
- /** \brief Objective-C's autorelease pool statement.
+ /** Objective-C's autorelease pool statement.
*/
CXCursor_ObjCAutoreleasePoolStmt = 221,
- /** \brief Objective-C's collection statement.
+ /** Objective-C's collection statement.
*/
CXCursor_ObjCForCollectionStmt = 222,
- /** \brief C++'s catch statement.
+ /** C++'s catch statement.
*/
CXCursor_CXXCatchStmt = 223,
- /** \brief C++'s try statement.
+ /** C++'s try statement.
*/
CXCursor_CXXTryStmt = 224,
- /** \brief C++'s for (* : *) statement.
+ /** C++'s for (* : *) statement.
*/
CXCursor_CXXForRangeStmt = 225,
- /** \brief Windows Structured Exception Handling's try statement.
+ /** Windows Structured Exception Handling's try statement.
*/
CXCursor_SEHTryStmt = 226,
- /** \brief Windows Structured Exception Handling's except statement.
+ /** Windows Structured Exception Handling's except statement.
*/
CXCursor_SEHExceptStmt = 227,
- /** \brief Windows Structured Exception Handling's finally statement.
+ /** Windows Structured Exception Handling's finally statement.
*/
CXCursor_SEHFinallyStmt = 228,
- /** \brief A MS inline assembly statement extension.
+ /** A MS inline assembly statement extension.
*/
CXCursor_MSAsmStmt = 229,
- /** \brief The null statement ";": C99 6.8.3p3.
+ /** The null statement ";": C99 6.8.3p3.
*
* This cursor kind is used to describe the null statement.
*/
CXCursor_NullStmt = 230,
- /** \brief Adaptor class for mixing declarations with statements and
+ /** Adaptor class for mixing declarations with statements and
* expressions.
*/
CXCursor_DeclStmt = 231,
- /** \brief OpenMP parallel directive.
+ /** OpenMP parallel directive.
*/
CXCursor_OMPParallelDirective = 232,
- /** \brief OpenMP SIMD directive.
+ /** OpenMP SIMD directive.
*/
CXCursor_OMPSimdDirective = 233,
- /** \brief OpenMP for directive.
+ /** OpenMP for directive.
*/
CXCursor_OMPForDirective = 234,
- /** \brief OpenMP sections directive.
+ /** OpenMP sections directive.
*/
CXCursor_OMPSectionsDirective = 235,
- /** \brief OpenMP section directive.
+ /** OpenMP section directive.
*/
CXCursor_OMPSectionDirective = 236,
- /** \brief OpenMP single directive.
+ /** OpenMP single directive.
*/
CXCursor_OMPSingleDirective = 237,
- /** \brief OpenMP parallel for directive.
+ /** OpenMP parallel for directive.
*/
CXCursor_OMPParallelForDirective = 238,
- /** \brief OpenMP parallel sections directive.
+ /** OpenMP parallel sections directive.
*/
CXCursor_OMPParallelSectionsDirective = 239,
- /** \brief OpenMP task directive.
+ /** OpenMP task directive.
*/
CXCursor_OMPTaskDirective = 240,
- /** \brief OpenMP master directive.
+ /** OpenMP master directive.
*/
CXCursor_OMPMasterDirective = 241,
- /** \brief OpenMP critical directive.
+ /** OpenMP critical directive.
*/
CXCursor_OMPCriticalDirective = 242,
- /** \brief OpenMP taskyield directive.
+ /** OpenMP taskyield directive.
*/
CXCursor_OMPTaskyieldDirective = 243,
- /** \brief OpenMP barrier directive.
+ /** OpenMP barrier directive.
*/
CXCursor_OMPBarrierDirective = 244,
- /** \brief OpenMP taskwait directive.
+ /** OpenMP taskwait directive.
*/
CXCursor_OMPTaskwaitDirective = 245,
- /** \brief OpenMP flush directive.
+ /** OpenMP flush directive.
*/
CXCursor_OMPFlushDirective = 246,
- /** \brief Windows Structured Exception Handling's leave statement.
+ /** Windows Structured Exception Handling's leave statement.
*/
CXCursor_SEHLeaveStmt = 247,
- /** \brief OpenMP ordered directive.
+ /** OpenMP ordered directive.
*/
CXCursor_OMPOrderedDirective = 248,
- /** \brief OpenMP atomic directive.
+ /** OpenMP atomic directive.
*/
CXCursor_OMPAtomicDirective = 249,
- /** \brief OpenMP for SIMD directive.
+ /** OpenMP for SIMD directive.
*/
CXCursor_OMPForSimdDirective = 250,
- /** \brief OpenMP parallel for SIMD directive.
+ /** OpenMP parallel for SIMD directive.
*/
CXCursor_OMPParallelForSimdDirective = 251,
- /** \brief OpenMP target directive.
+ /** OpenMP target directive.
*/
CXCursor_OMPTargetDirective = 252,
- /** \brief OpenMP teams directive.
+ /** OpenMP teams directive.
*/
CXCursor_OMPTeamsDirective = 253,
- /** \brief OpenMP taskgroup directive.
+ /** OpenMP taskgroup directive.
*/
CXCursor_OMPTaskgroupDirective = 254,
- /** \brief OpenMP cancellation point directive.
+ /** OpenMP cancellation point directive.
*/
CXCursor_OMPCancellationPointDirective = 255,
- /** \brief OpenMP cancel directive.
+ /** OpenMP cancel directive.
*/
CXCursor_OMPCancelDirective = 256,
- /** \brief OpenMP target data directive.
+ /** OpenMP target data directive.
*/
CXCursor_OMPTargetDataDirective = 257,
- /** \brief OpenMP taskloop directive.
+ /** OpenMP taskloop directive.
*/
CXCursor_OMPTaskLoopDirective = 258,
- /** \brief OpenMP taskloop simd directive.
+ /** OpenMP taskloop simd directive.
*/
CXCursor_OMPTaskLoopSimdDirective = 259,
- /** \brief OpenMP distribute directive.
+ /** OpenMP distribute directive.
*/
CXCursor_OMPDistributeDirective = 260,
- /** \brief OpenMP target enter data directive.
+ /** OpenMP target enter data directive.
*/
CXCursor_OMPTargetEnterDataDirective = 261,
- /** \brief OpenMP target exit data directive.
+ /** OpenMP target exit data directive.
*/
CXCursor_OMPTargetExitDataDirective = 262,
- /** \brief OpenMP target parallel directive.
+ /** OpenMP target parallel directive.
*/
CXCursor_OMPTargetParallelDirective = 263,
- /** \brief OpenMP target parallel for directive.
+ /** OpenMP target parallel for directive.
*/
CXCursor_OMPTargetParallelForDirective = 264,
- /** \brief OpenMP target update directive.
+ /** OpenMP target update directive.
*/
CXCursor_OMPTargetUpdateDirective = 265,
- /** \brief OpenMP distribute parallel for directive.
+ /** OpenMP distribute parallel for directive.
*/
CXCursor_OMPDistributeParallelForDirective = 266,
- /** \brief OpenMP distribute parallel for simd directive.
+ /** OpenMP distribute parallel for simd directive.
*/
CXCursor_OMPDistributeParallelForSimdDirective = 267,
- /** \brief OpenMP distribute simd directive.
+ /** OpenMP distribute simd directive.
*/
CXCursor_OMPDistributeSimdDirective = 268,
- /** \brief OpenMP target parallel for simd directive.
+ /** OpenMP target parallel for simd directive.
*/
CXCursor_OMPTargetParallelForSimdDirective = 269,
- /** \brief OpenMP target simd directive.
+ /** OpenMP target simd directive.
*/
CXCursor_OMPTargetSimdDirective = 270,
- /** \brief OpenMP teams distribute directive.
+ /** OpenMP teams distribute directive.
*/
CXCursor_OMPTeamsDistributeDirective = 271,
- /** \brief OpenMP teams distribute simd directive.
+ /** OpenMP teams distribute simd directive.
*/
CXCursor_OMPTeamsDistributeSimdDirective = 272,
- /** \brief OpenMP teams distribute parallel for simd directive.
+ /** OpenMP teams distribute parallel for simd directive.
*/
CXCursor_OMPTeamsDistributeParallelForSimdDirective = 273,
- /** \brief OpenMP teams distribute parallel for directive.
+ /** OpenMP teams distribute parallel for directive.
*/
CXCursor_OMPTeamsDistributeParallelForDirective = 274,
- /** \brief OpenMP target teams directive.
+ /** OpenMP target teams directive.
*/
CXCursor_OMPTargetTeamsDirective = 275,
- /** \brief OpenMP target teams distribute directive.
+ /** OpenMP target teams distribute directive.
*/
CXCursor_OMPTargetTeamsDistributeDirective = 276,
- /** \brief OpenMP target teams distribute parallel for directive.
+ /** OpenMP target teams distribute parallel for directive.
*/
CXCursor_OMPTargetTeamsDistributeParallelForDirective = 277,
- /** \brief OpenMP target teams distribute parallel for simd directive.
+ /** OpenMP target teams distribute parallel for simd directive.
*/
CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective = 278,
- /** \brief OpenMP target teams distribute simd directive.
+ /** OpenMP target teams distribute simd directive.
*/
CXCursor_OMPTargetTeamsDistributeSimdDirective = 279,
CXCursor_LastStmt = CXCursor_OMPTargetTeamsDistributeSimdDirective,
/**
- * \brief Cursor that represents the translation unit itself.
+ * Cursor that represents the translation unit itself.
*
* The translation unit cursor exists primarily to act as the root
* cursor for traversing the contents of a translation unit.
@@ -2515,7 +2535,7 @@ enum CXCursorKind {
/* Attributes */
CXCursor_FirstAttr = 400,
/**
- * \brief An attribute whose specific kind is not exposed via this
+ * An attribute whose specific kind is not exposed via this
* interface.
*/
CXCursor_UnexposedAttr = 400,
@@ -2552,29 +2572,29 @@ enum CXCursorKind {
/* Extra Declarations */
/**
- * \brief A module import declaration.
+ * A module import declaration.
*/
CXCursor_ModuleImportDecl = 600,
CXCursor_TypeAliasTemplateDecl = 601,
/**
- * \brief A static_assert or _Static_assert node
+ * A static_assert or _Static_assert node
*/
CXCursor_StaticAssert = 602,
/**
- * \brief a friend declaration.
+ * a friend declaration.
*/
CXCursor_FriendDecl = 603,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
CXCursor_LastExtraDecl = CXCursor_FriendDecl,
/**
- * \brief A code completion overload candidate.
+ * A code completion overload candidate.
*/
CXCursor_OverloadCandidate = 700
};
/**
- * \brief A cursor representing some element in the abstract syntax tree for
+ * A cursor representing some element in the abstract syntax tree for
* a translation unit.
*
* The cursor abstraction unifies the different kinds of entities in a
@@ -2604,12 +2624,12 @@ typedef struct {
*/
/**
- * \brief Retrieve the NULL cursor, which represents no entity.
+ * Retrieve the NULL cursor, which represents no entity.
*/
CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
/**
- * \brief Retrieve the cursor that represents the given translation unit.
+ * Retrieve the cursor that represents the given translation unit.
*
* The translation unit cursor can be used to start traversing the
* various declarations within the given translation unit.
@@ -2617,32 +2637,42 @@ CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
/**
- * \brief Determine whether two cursors are equivalent.
+ * Determine whether two cursors are equivalent.
*/
CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
/**
- * \brief Returns non-zero if \p cursor is null.
+ * Returns non-zero if \p cursor is null.
*/
CINDEX_LINKAGE int clang_Cursor_isNull(CXCursor cursor);
/**
- * \brief Compute a hash value for the given cursor.
+ * Compute a hash value for the given cursor.
*/
CINDEX_LINKAGE unsigned clang_hashCursor(CXCursor);
-
+
/**
- * \brief Retrieve the kind of the given cursor.
+ * Retrieve the kind of the given cursor.
*/
CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
/**
- * \brief Determine whether the given cursor kind represents a declaration.
+ * Determine whether the given cursor kind represents a declaration.
*/
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents a simple
+ * Determine whether the given declaration is invalid.
+ *
+ * A declaration is invalid if it could not be parsed successfully.
+ *
+ * \returns non-zero if the cursor represents a declaration and it is
+ * invalid, otherwise NULL.
+ */
+CINDEX_LINKAGE unsigned clang_isInvalidDeclaration(CXCursor);
+
+/**
+ * Determine whether the given cursor kind represents a simple
* reference.
*
* Note that other kinds of cursors (such as expressions) can also refer to
@@ -2652,90 +2682,90 @@ CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents an expression.
+ * Determine whether the given cursor kind represents an expression.
*/
CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents a statement.
+ * Determine whether the given cursor kind represents a statement.
*/
CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents an attribute.
+ * Determine whether the given cursor kind represents an attribute.
*/
CINDEX_LINKAGE unsigned clang_isAttribute(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor has any attributes.
+ * Determine whether the given cursor has any attributes.
*/
CINDEX_LINKAGE unsigned clang_Cursor_hasAttrs(CXCursor C);
/**
- * \brief Determine whether the given cursor kind represents an invalid
+ * Determine whether the given cursor kind represents an invalid
* cursor.
*/
CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents a translation
+ * Determine whether the given cursor kind represents a translation
* unit.
*/
CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
/***
- * \brief Determine whether the given cursor represents a preprocessing
+ * Determine whether the given cursor represents a preprocessing
* element, such as a preprocessor directive or macro instantiation.
*/
CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind);
-
+
/***
- * \brief Determine whether the given cursor represents a currently
+ * Determine whether the given cursor represents a currently
* unexposed piece of the AST (e.g., CXCursor_UnexposedStmt).
*/
CINDEX_LINKAGE unsigned clang_isUnexposed(enum CXCursorKind);
/**
- * \brief Describe the linkage of the entity referred to by a cursor.
+ * Describe the linkage of the entity referred to by a cursor.
*/
enum CXLinkageKind {
- /** \brief This value indicates that no linkage information is available
+ /** This value indicates that no linkage information is available
* for a provided CXCursor. */
CXLinkage_Invalid,
/**
- * \brief This is the linkage for variables, parameters, and so on that
+ * This is the linkage for variables, parameters, and so on that
* have automatic storage. This covers normal (non-extern) local variables.
*/
CXLinkage_NoLinkage,
- /** \brief This is the linkage for static variables and static functions. */
+ /** This is the linkage for static variables and static functions. */
CXLinkage_Internal,
- /** \brief This is the linkage for entities with external linkage that live
+ /** This is the linkage for entities with external linkage that live
* in C++ anonymous namespaces.*/
CXLinkage_UniqueExternal,
- /** \brief This is the linkage for entities with true, external linkage. */
+ /** This is the linkage for entities with true, external linkage. */
CXLinkage_External
};
/**
- * \brief Determine the linkage of the entity referred to by a given cursor.
+ * Determine the linkage of the entity referred to by a given cursor.
*/
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
enum CXVisibilityKind {
- /** \brief This value indicates that no visibility information is available
+ /** This value indicates that no visibility information is available
* for a provided CXCursor. */
CXVisibility_Invalid,
- /** \brief Symbol not seen by the linker. */
+ /** Symbol not seen by the linker. */
CXVisibility_Hidden,
- /** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
+ /** Symbol seen by the linker but resolves to a symbol inside this object. */
CXVisibility_Protected,
- /** \brief Symbol seen by the linker and acts like a normal symbol. */
+ /** Symbol seen by the linker and acts like a normal symbol. */
CXVisibility_Default
};
/**
- * \brief Describe the visibility of the entity referred to by a cursor.
+ * Describe the visibility of the entity referred to by a cursor.
*
* This returns the default visibility if not explicitly specified by
* a visibility attribute. The default visibility may be changed by
@@ -2748,14 +2778,14 @@ enum CXVisibilityKind {
CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
/**
- * \brief Determine the availability of the entity that this cursor refers to,
+ * Determine the availability of the entity that this cursor refers to,
* taking the current target platform into account.
*
* \param cursor The cursor to query.
*
* \returns The availability of the cursor.
*/
-CINDEX_LINKAGE enum CXAvailabilityKind
+CINDEX_LINKAGE enum CXAvailabilityKind
clang_getCursorAvailability(CXCursor cursor);
/**
@@ -2764,47 +2794,47 @@ clang_getCursorAvailability(CXCursor cursor);
*/
typedef struct CXPlatformAvailability {
/**
- * \brief A string that describes the platform for which this structure
+ * A string that describes the platform for which this structure
* provides availability information.
*
* Possible values are "ios" or "macos".
*/
CXString Platform;
/**
- * \brief The version number in which this entity was introduced.
+ * The version number in which this entity was introduced.
*/
CXVersion Introduced;
/**
- * \brief The version number in which this entity was deprecated (but is
+ * The version number in which this entity was deprecated (but is
* still available).
*/
CXVersion Deprecated;
/**
- * \brief The version number in which this entity was obsoleted, and therefore
+ * The version number in which this entity was obsoleted, and therefore
* is no longer available.
*/
CXVersion Obsoleted;
/**
- * \brief Whether the entity is unconditionally unavailable on this platform.
+ * Whether the entity is unconditionally unavailable on this platform.
*/
int Unavailable;
/**
- * \brief An optional message to provide to a user of this API, e.g., to
+ * An optional message to provide to a user of this API, e.g., to
* suggest replacement APIs.
*/
CXString Message;
} CXPlatformAvailability;
/**
- * \brief Determine the availability of the entity that this cursor refers to
+ * Determine the availability of the entity that this cursor refers to
* on any platforms for which availability information is known.
*
* \param cursor The cursor to query.
*
- * \param always_deprecated If non-NULL, will be set to indicate whether the
+ * \param always_deprecated If non-NULL, will be set to indicate whether the
* entity is deprecated on all platforms.
*
- * \param deprecated_message If non-NULL, will be set to the message text
+ * \param deprecated_message If non-NULL, will be set to the message text
* provided along with the unconditional deprecation of this entity. The client
* is responsible for deallocating this string.
*
@@ -2812,7 +2842,7 @@ typedef struct CXPlatformAvailability {
* entity is unavailable on all platforms.
*
* \param unavailable_message If non-NULL, will be set to the message text
- * provided along with the unconditional unavailability of this entity. The
+ * provided along with the unconditional unavailability of this entity. The
* client is responsible for deallocating this string.
*
* \param availability If non-NULL, an array of CXPlatformAvailability instances
@@ -2820,15 +2850,15 @@ typedef struct CXPlatformAvailability {
* the number of platforms for which availability information is available (as
* returned by this function) or \c availability_size, whichever is smaller.
*
- * \param availability_size The number of elements available in the
+ * \param availability_size The number of elements available in the
* \c availability array.
*
* \returns The number of platforms (N) for which availability information is
* available (which is unrelated to \c availability_size).
*
- * Note that the client is responsible for calling
- * \c clang_disposeCXPlatformAvailability to free each of the
- * platform-availability structures returned. There are
+ * Note that the client is responsible for calling
+ * \c clang_disposeCXPlatformAvailability to free each of the
+ * platform-availability structures returned. There are
* \c min(N, availability_size) such structures.
*/
CINDEX_LINKAGE int
@@ -2841,13 +2871,13 @@ clang_getCursorPlatformAvailability(CXCursor cursor,
int availability_size);
/**
- * \brief Free the memory associated with a \c CXPlatformAvailability structure.
+ * Free the memory associated with a \c CXPlatformAvailability structure.
*/
CINDEX_LINKAGE void
clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability);
-
+
/**
- * \brief Describe the "language" of the entity referred to by a cursor.
+ * Describe the "language" of the entity referred to by a cursor.
*/
enum CXLanguageKind {
CXLanguage_Invalid = 0,
@@ -2857,12 +2887,12 @@ enum CXLanguageKind {
};
/**
- * \brief Determine the "language" of the entity referred to by a given cursor.
+ * Determine the "language" of the entity referred to by a given cursor.
*/
CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
/**
- * \brief Describe the "thread-local storage (TLS) kind" of the declaration
+ * Describe the "thread-local storage (TLS) kind" of the declaration
* referred to by a cursor.
*/
enum CXTLSKind {
@@ -2872,33 +2902,33 @@ enum CXTLSKind {
};
/**
- * \brief Determine the "thread-local storage (TLS) kind" of the declaration
+ * 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.
+ * Returns the translation unit that a cursor originated from.
*/
CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
/**
- * \brief A fast container representing a set of CXCursors.
+ * A fast container representing a set of CXCursors.
*/
typedef struct CXCursorSetImpl *CXCursorSet;
/**
- * \brief Creates an empty CXCursorSet.
+ * Creates an empty CXCursorSet.
*/
CINDEX_LINKAGE CXCursorSet clang_createCXCursorSet(void);
/**
- * \brief Disposes a CXCursorSet and releases its associated memory.
+ * Disposes a CXCursorSet and releases its associated memory.
*/
CINDEX_LINKAGE void clang_disposeCXCursorSet(CXCursorSet cset);
/**
- * \brief Queries a CXCursorSet to see if it contains a specific CXCursor.
+ * Queries a CXCursorSet to see if it contains a specific CXCursor.
*
* \returns non-zero if the set contains the specified cursor.
*/
@@ -2906,7 +2936,7 @@ CINDEX_LINKAGE unsigned clang_CXCursorSet_contains(CXCursorSet cset,
CXCursor cursor);
/**
- * \brief Inserts a CXCursor into a CXCursorSet.
+ * Inserts a CXCursor into a CXCursorSet.
*
* \returns zero if the CXCursor was already in the set, and non-zero otherwise.
*/
@@ -2914,11 +2944,11 @@ CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset,
CXCursor cursor);
/**
- * \brief Determine the semantic parent of the given cursor.
+ * Determine the semantic parent of the given cursor.
*
* The semantic parent of a cursor is the cursor that semantically contains
* the given \p cursor. For many declarations, the lexical and semantic parents
- * are equivalent (the lexical parent is returned by
+ * are equivalent (the lexical parent is returned by
* \c clang_getCursorLexicalParent()). They diverge when declarations or
* definitions are provided out-of-line. For example:
*
@@ -2949,11 +2979,11 @@ CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset,
CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor);
/**
- * \brief Determine the lexical parent of the given cursor.
+ * Determine the lexical parent of the given cursor.
*
* The lexical parent of a cursor is the cursor in which the given \p cursor
* was actually written. For many declarations, the lexical and semantic parents
- * are equivalent (the semantic parent is returned by
+ * are equivalent (the semantic parent is returned by
* \c clang_getCursorSemanticParent()). They diverge when declarations or
* definitions are provided out-of-line. For example:
*
@@ -2985,7 +3015,7 @@ CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor);
CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor);
/**
- * \brief Determine the set of methods that are overridden by the given
+ * Determine the set of methods that are overridden by the given
* method.
*
* In both Objective-C and C++, a method (aka virtual member function,
@@ -3016,33 +3046,33 @@ CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor);
* \param cursor A cursor representing an Objective-C or C++
* method. This routine will compute the set of methods that this
* method overrides.
- *
+ *
* \param overridden A pointer whose pointee will be replaced with a
* pointer to an array of cursors, representing the set of overridden
* methods. If there are no overridden methods, the pointee will be
- * set to NULL. The pointee must be freed via a call to
+ * set to NULL. The pointee must be freed via a call to
* \c clang_disposeOverriddenCursors().
*
* \param num_overridden A pointer to the number of overridden
* functions, will be set to the number of overridden functions in the
* array pointed to by \p overridden.
*/
-CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor,
+CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor,
CXCursor **overridden,
unsigned *num_overridden);
/**
- * \brief Free the set of overridden cursors returned by \c
+ * Free the set of overridden cursors returned by \c
* clang_getOverriddenCursors().
*/
CINDEX_LINKAGE void clang_disposeOverriddenCursors(CXCursor *overridden);
/**
- * \brief Retrieve the file that is included by the given inclusion directive
+ * Retrieve the file that is included by the given inclusion directive
* cursor.
*/
CINDEX_LINKAGE CXFile clang_getIncludedFile(CXCursor cursor);
-
+
/**
* @}
*/
@@ -3059,7 +3089,7 @@ CINDEX_LINKAGE CXFile clang_getIncludedFile(CXCursor cursor);
*/
/**
- * \brief Map a source location to the cursor that describes the entity at that
+ * Map a source location to the cursor that describes the entity at that
* location in the source code.
*
* clang_getCursor() maps an arbitrary source location within a translation
@@ -3076,7 +3106,7 @@ CINDEX_LINKAGE CXFile clang_getIncludedFile(CXCursor cursor);
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
/**
- * \brief Retrieve the physical location of the source constructor referenced
+ * Retrieve the physical location of the source constructor referenced
* by the given cursor.
*
* The location of a declaration is typically the location of the name of that
@@ -3088,7 +3118,7 @@ CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
/**
- * \brief Retrieve the physical extent of the source construct referenced by
+ * Retrieve the physical extent of the source construct referenced by
* the given cursor.
*
* The extent of a cursor starts with the file/line/column pointing at the
@@ -3103,7 +3133,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_TYPES Type information for CXCursors
*
@@ -3111,16 +3141,16 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
*/
/**
- * \brief Describes the kind of type
+ * Describes the kind of type
*/
enum CXTypeKind {
/**
- * \brief Represents an invalid type (e.g., where no type is available).
+ * Represents an invalid type (e.g., where no type is available).
*/
CXType_Invalid = 0,
/**
- * \brief A type whose specific kind is not exposed via this
+ * A type whose specific kind is not exposed via this
* interface.
*/
CXType_Unexposed = 1,
@@ -3157,8 +3187,14 @@ enum CXTypeKind {
CXType_Float128 = 30,
CXType_Half = 31,
CXType_Float16 = 32,
+ CXType_ShortAccum = 33,
+ CXType_Accum = 34,
+ CXType_LongAccum = 35,
+ CXType_UShortAccum = 36,
+ CXType_UAccum = 37,
+ CXType_ULongAccum = 38,
CXType_FirstBuiltin = CXType_Void,
- CXType_LastBuiltin = CXType_Float16,
+ CXType_LastBuiltin = CXType_ULongAccum,
CXType_Complex = 100,
CXType_Pointer = 101,
@@ -3181,7 +3217,7 @@ enum CXTypeKind {
CXType_Auto = 118,
/**
- * \brief Represents a type that was referred to using an elaborated type keyword.
+ * Represents a type that was referred to using an elaborated type keyword.
*
* E.g., struct S, or via a qualified name, e.g., N::M::type, or both.
*/
@@ -3234,7 +3270,7 @@ enum CXTypeKind {
};
/**
- * \brief Describes the calling convention of a function type
+ * Describes the calling convention of a function type
*/
enum CXCallingConv {
CXCallingConv_Default = 0,
@@ -3261,7 +3297,7 @@ enum CXCallingConv {
};
/**
- * \brief The type of an element in the abstract syntax tree.
+ * The type of an element in the abstract syntax tree.
*
*/
typedef struct {
@@ -3270,12 +3306,12 @@ typedef struct {
} CXType;
/**
- * \brief Retrieve the type of a CXCursor (if any).
+ * Retrieve the type of a CXCursor (if any).
*/
CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C);
/**
- * \brief Pretty-print the underlying type using the rules of the
+ * Pretty-print the underlying type using the rules of the
* language of the translation unit from which it came.
*
* If the type is invalid, an empty string is returned.
@@ -3283,7 +3319,7 @@ CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C);
CINDEX_LINKAGE CXString clang_getTypeSpelling(CXType CT);
/**
- * \brief Retrieve the underlying type of a typedef declaration.
+ * Retrieve the underlying type of a typedef declaration.
*
* If the cursor does not reference a typedef declaration, an invalid type is
* returned.
@@ -3291,7 +3327,7 @@ CINDEX_LINKAGE CXString clang_getTypeSpelling(CXType CT);
CINDEX_LINKAGE CXType clang_getTypedefDeclUnderlyingType(CXCursor C);
/**
- * \brief Retrieve the integer type of an enum declaration.
+ * Retrieve the integer type of an enum declaration.
*
* If the cursor does not reference an enum declaration, an invalid type is
* returned.
@@ -3299,7 +3335,7 @@ CINDEX_LINKAGE CXType clang_getTypedefDeclUnderlyingType(CXCursor C);
CINDEX_LINKAGE CXType clang_getEnumDeclIntegerType(CXCursor C);
/**
- * \brief Retrieve the integer value of an enum constant declaration as a signed
+ * Retrieve the integer value of an enum constant declaration as a signed
* long long.
*
* If the cursor does not reference an enum constant declaration, LLONG_MIN is returned.
@@ -3309,7 +3345,7 @@ CINDEX_LINKAGE CXType clang_getEnumDeclIntegerType(CXCursor C);
CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C);
/**
- * \brief Retrieve the integer value of an enum constant declaration as an unsigned
+ * Retrieve the integer value of an enum constant declaration as an unsigned
* long long.
*
* If the cursor does not reference an enum constant declaration, ULLONG_MAX is returned.
@@ -3319,14 +3355,14 @@ CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C);
CINDEX_LINKAGE unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C);
/**
- * \brief Retrieve the bit width of a bit field declaration as an integer.
+ * Retrieve the bit width of a bit field declaration as an integer.
*
* If a cursor that is not a bit field declaration is passed in, -1 is returned.
*/
CINDEX_LINKAGE int clang_getFieldDeclBitWidth(CXCursor C);
/**
- * \brief Retrieve the number of non-variadic arguments associated with a given
+ * Retrieve the number of non-variadic arguments associated with a given
* cursor.
*
* The number of arguments can be determined for calls as well as for
@@ -3335,7 +3371,7 @@ CINDEX_LINKAGE int clang_getFieldDeclBitWidth(CXCursor C);
CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
/**
- * \brief Retrieve the argument cursor of a function or method.
+ * Retrieve the argument cursor of a function or method.
*
* The argument cursor can be determined for calls as well as for declarations
* of functions or methods. For other cursors and for invalid indices, an
@@ -3344,7 +3380,7 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
/**
- * \brief Describes the kind of a template argument.
+ * Describes the kind of a template argument.
*
* See the definition of llvm::clang::TemplateArgument::ArgKind for full
* element descriptions.
@@ -3364,7 +3400,7 @@ enum CXTemplateArgumentKind {
};
/**
- *\brief Returns the number of template args of a function decl representing a
+ *Returns the number of template args of a function decl representing a
* template specialization.
*
* If the argument cursor cannot be converted into a template function
@@ -3382,7 +3418,7 @@ enum CXTemplateArgumentKind {
CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
/**
- * \brief Retrieve the kind of the I'th template argument of the CXCursor C.
+ * Retrieve the kind of the I'th template argument of the CXCursor C.
*
* If the argument CXCursor does not represent a FunctionDecl, an invalid
* template argument kind is returned.
@@ -3401,7 +3437,7 @@ CINDEX_LINKAGE enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(
CXCursor C, unsigned I);
/**
- * \brief Retrieve a CXType representing the type of a TemplateArgument of a
+ * Retrieve a CXType representing the type of a TemplateArgument of a
* function decl representing a template specialization.
*
* If the argument CXCursor does not represent a FunctionDecl whose I'th
@@ -3422,7 +3458,7 @@ CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
unsigned I);
/**
- * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ * Retrieve the value of an Integral TemplateArgument (of a function
* decl representing a template specialization) as a signed long long.
*
* It is undefined to call this function on a CXCursor that does not represent a
@@ -3442,7 +3478,7 @@ CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
unsigned I);
/**
- * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ * Retrieve the value of an Integral TemplateArgument (of a function
* decl representing a template specialization) as an unsigned long long.
*
* It is undefined to call this function on a CXCursor that does not represent a
@@ -3462,7 +3498,7 @@ CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(
CXCursor C, unsigned I);
/**
- * \brief Determine whether two CXTypes represent the same type.
+ * Determine whether two CXTypes represent the same type.
*
* \returns non-zero if the CXTypes represent the same type and
* zero otherwise.
@@ -3470,7 +3506,7 @@ CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(
CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B);
/**
- * \brief Return the canonical type for a CXType.
+ * Return the canonical type for a CXType.
*
* Clang's type system explicitly models typedefs and all the ways
* a specific type can be represented. The canonical type is the underlying
@@ -3480,61 +3516,61 @@ CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B);
CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T);
/**
- * \brief Determine whether a CXType has the "const" qualifier set,
+ * Determine whether a CXType has the "const" qualifier set,
* without looking through typedefs that may have added "const" at a
* different level.
*/
CINDEX_LINKAGE unsigned clang_isConstQualifiedType(CXType T);
/**
- * \brief Determine whether a CXCursor that is a macro, is
+ * Determine whether a CXCursor that is a macro, is
* function like.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isMacroFunctionLike(CXCursor C);
/**
- * \brief Determine whether a CXCursor that is a macro, is a
+ * Determine whether a CXCursor that is a macro, is a
* builtin one.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isMacroBuiltin(CXCursor C);
/**
- * \brief Determine whether a CXCursor that is a function declaration, is an
+ * Determine whether a CXCursor that is a function declaration, is an
* inline declaration.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isFunctionInlined(CXCursor C);
/**
- * \brief Determine whether a CXType has the "volatile" qualifier set,
+ * Determine whether a CXType has the "volatile" qualifier set,
* without looking through typedefs that may have added "volatile" at
* a different level.
*/
CINDEX_LINKAGE unsigned clang_isVolatileQualifiedType(CXType T);
/**
- * \brief Determine whether a CXType has the "restrict" qualifier set,
+ * Determine whether a CXType has the "restrict" qualifier set,
* without looking through typedefs that may have added "restrict" at a
* different level.
*/
CINDEX_LINKAGE unsigned clang_isRestrictQualifiedType(CXType T);
/**
- * \brief Returns the address space of the given type.
+ * Returns the address space of the given type.
*/
CINDEX_LINKAGE unsigned clang_getAddressSpace(CXType T);
/**
- * \brief Returns the typedef name of the given type.
+ * Returns the typedef name of the given type.
*/
CINDEX_LINKAGE CXString clang_getTypedefName(CXType CT);
/**
- * \brief For pointer types, returns the type of the pointee.
+ * For pointer types, returns the type of the pointee.
*/
CINDEX_LINKAGE CXType clang_getPointeeType(CXType T);
/**
- * \brief Return the cursor for the declaration of the given type.
+ * Return the cursor for the declaration of the given type.
*/
CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T);
@@ -3546,36 +3582,37 @@ CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C);
/**
* Returns the Objective-C type encoding for the specified CXType.
*/
-CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type);
+CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type);
/**
- * \brief Retrieve the spelling of a given CXTypeKind.
+ * Retrieve the spelling of a given CXTypeKind.
*/
CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K);
/**
- * \brief Retrieve the calling convention associated with a function type.
+ * Retrieve the calling convention associated with a function type.
*
* If a non-function type is passed in, CXCallingConv_Invalid is returned.
*/
CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
/**
- * \brief Retrieve the return type associated with a function type.
+ * Retrieve the return type associated with a function type.
*
* If a non-function type is passed in, an invalid type is returned.
*/
CINDEX_LINKAGE CXType clang_getResultType(CXType T);
/**
- * \brief Retrieve the exception specification type associated with a function type.
+ * Retrieve the exception specification type associated with a function type.
+ * This is a value of type CXCursor_ExceptionSpecificationKind.
*
* If a non-function type is passed in, an error code of -1 is returned.
*/
CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T);
/**
- * \brief Retrieve the number of non-variadic parameters associated with a
+ * Retrieve the number of non-variadic parameters associated with a
* function type.
*
* If a non-function type is passed in, -1 is returned.
@@ -3583,7 +3620,7 @@ CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T);
CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
/**
- * \brief Retrieve the type of a parameter of a function type.
+ * Retrieve the type of a parameter of a function type.
*
* If a non-function type is passed in or the function does not have enough
* parameters, an invalid type is returned.
@@ -3591,32 +3628,33 @@ CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i);
/**
- * \brief Return 1 if the CXType is a variadic function type, and 0 otherwise.
+ * Return 1 if the CXType is a variadic function type, and 0 otherwise.
*/
CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
/**
- * \brief Retrieve the return type associated with a given cursor.
+ * Retrieve the return type associated with a given cursor.
*
* This only returns a valid type if the cursor refers to a function or method.
*/
CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
/**
- * \brief Retrieve the exception specification type associated with a given cursor.
+ * Retrieve the exception specification type associated with a given cursor.
+ * This is a value of type CXCursor_ExceptionSpecificationKind.
*
* This only returns a valid result if the cursor refers to a function or method.
*/
CINDEX_LINKAGE int clang_getCursorExceptionSpecificationType(CXCursor C);
/**
- * \brief Return 1 if the CXType is a POD (plain old data) type, and 0
+ * Return 1 if the CXType is a POD (plain old data) type, and 0
* otherwise.
*/
CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
/**
- * \brief Return the element type of an array, complex, or vector type.
+ * Return the element type of an array, complex, or vector type.
*
* If a type is passed in that is not an array, complex, or vector type,
* an invalid type is returned.
@@ -3624,7 +3662,7 @@ CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
CINDEX_LINKAGE CXType clang_getElementType(CXType T);
/**
- * \brief Return the number of elements of an array or vector type.
+ * Return the number of elements of an array or vector type.
*
* If a type is passed in that is not an array or vector type,
* -1 is returned.
@@ -3632,28 +3670,28 @@ CINDEX_LINKAGE CXType clang_getElementType(CXType T);
CINDEX_LINKAGE long long clang_getNumElements(CXType T);
/**
- * \brief Return the element type of an array type.
+ * Return the element type of an array type.
*
* If a non-array type is passed in, an invalid type is returned.
*/
CINDEX_LINKAGE CXType clang_getArrayElementType(CXType T);
/**
- * \brief Return the array size of a constant array.
+ * Return the array size of a constant array.
*
* If a non-array type is passed in, -1 is returned.
*/
CINDEX_LINKAGE long long clang_getArraySize(CXType T);
/**
- * \brief Retrieve the type named by the qualified-id.
+ * Retrieve the type named by the qualified-id.
*
* If a non-elaborated type is passed in, an invalid type is returned.
*/
CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T);
/**
- * \brief Determine if a typedef is 'transparent' tag.
+ * Determine if a typedef is 'transparent' tag.
*
* A typedef is considered 'transparent' if it shares a name and spelling
* location with its underlying tag type, as is the case with the NS_ENUM macro.
@@ -3663,7 +3701,7 @@ CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T);
CINDEX_LINKAGE unsigned clang_Type_isTransparentTagTypedef(CXType T);
/**
- * \brief List the possible error codes for \c clang_Type_getSizeOf,
+ * List the possible error codes for \c clang_Type_getSizeOf,
* \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and
* \c clang_Cursor_getOffsetOf.
*
@@ -3672,29 +3710,29 @@ CINDEX_LINKAGE unsigned clang_Type_isTransparentTagTypedef(CXType T);
*/
enum CXTypeLayoutError {
/**
- * \brief Type is of kind CXType_Invalid.
+ * Type is of kind CXType_Invalid.
*/
CXTypeLayoutError_Invalid = -1,
/**
- * \brief The type is an incomplete Type.
+ * The type is an incomplete Type.
*/
CXTypeLayoutError_Incomplete = -2,
/**
- * \brief The type is a dependent Type.
+ * The type is a dependent Type.
*/
CXTypeLayoutError_Dependent = -3,
/**
- * \brief The type is not a constant size type.
+ * The type is not a constant size type.
*/
CXTypeLayoutError_NotConstantSize = -4,
/**
- * \brief The Field name is not valid for this record.
+ * The Field name is not valid for this record.
*/
CXTypeLayoutError_InvalidFieldName = -5
};
/**
- * \brief Return the alignment of a type in bytes as per C++[expr.alignof]
+ * Return the alignment of a type in bytes as per C++[expr.alignof]
* standard.
*
* If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
@@ -3708,14 +3746,14 @@ enum CXTypeLayoutError {
CINDEX_LINKAGE long long clang_Type_getAlignOf(CXType T);
/**
- * \brief Return the class type of an member pointer type.
+ * Return the class type of an member pointer type.
*
* If a non-member-pointer type is passed in, an invalid type is returned.
*/
CINDEX_LINKAGE CXType clang_Type_getClassType(CXType T);
/**
- * \brief Return the size of a type in bytes as per C++[expr.sizeof] standard.
+ * Return the size of a type in bytes as per C++[expr.sizeof] standard.
*
* If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
* If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete
@@ -3726,7 +3764,7 @@ CINDEX_LINKAGE CXType clang_Type_getClassType(CXType T);
CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T);
/**
- * \brief Return the offset of a field named S in a record of type T in bits
+ * Return the offset of a field named S in a record of type T in bits
* as it would be returned by __offsetof__ as per C++11[18.2p4]
*
* If the cursor is not a record field declaration, CXTypeLayoutError_Invalid
@@ -3741,7 +3779,7 @@ CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T);
CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S);
/**
- * \brief Return the offset of the field represented by the Cursor.
+ * Return the offset of the field represented by the Cursor.
*
* If the cursor is not a field declaration, -1 is returned.
* If the cursor semantic parent is not a record field declaration,
@@ -3756,28 +3794,28 @@ CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S);
CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C);
/**
- * \brief Determine whether the given cursor represents an anonymous record
+ * Determine whether the given cursor represents an anonymous record
* declaration.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C);
enum CXRefQualifierKind {
- /** \brief No ref-qualifier was provided. */
+ /** No ref-qualifier was provided. */
CXRefQualifier_None = 0,
- /** \brief An lvalue ref-qualifier was provided (\c &). */
+ /** An lvalue ref-qualifier was provided (\c &). */
CXRefQualifier_LValue,
- /** \brief An rvalue ref-qualifier was provided (\c &&). */
+ /** An rvalue ref-qualifier was provided (\c &&). */
CXRefQualifier_RValue
};
/**
- * \brief Returns the number of template arguments for given template
+ * Returns the number of template arguments for given template
* specialization, or -1 if type \c T is not a template specialization.
*/
CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T);
/**
- * \brief Returns the type template argument of a template class specialization
+ * Returns the type template argument of a template class specialization
* at given index.
*
* This function only returns template type arguments and does not handle
@@ -3786,7 +3824,7 @@ CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T);
CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, unsigned i);
/**
- * \brief Retrieve the ref-qualifier kind of a function or method.
+ * Retrieve the ref-qualifier kind of a function or method.
*
* The ref-qualifier is returned for C++ functions or methods. For other types
* or non-C++ declarations, CXRefQualifier_None is returned.
@@ -3794,19 +3832,19 @@ CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, unsigned i)
CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T);
/**
- * \brief Returns non-zero if the cursor specifies a Record member that is a
+ * Returns non-zero if the cursor specifies a Record member that is a
* bitfield.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isBitField(CXCursor C);
/**
- * \brief Returns 1 if the base class specified by the cursor with kind
+ * Returns 1 if the base class specified by the cursor with kind
* CX_CXXBaseSpecifier is virtual.
*/
CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
-
+
/**
- * \brief Represents the C++ access control level to a base class for a
+ * Represents the C++ access control level to a base class for a
* cursor with kind CX_CXXBaseSpecifier.
*/
enum CX_CXXAccessSpecifier {
@@ -3817,7 +3855,7 @@ enum CX_CXXAccessSpecifier {
};
/**
- * \brief Returns the access control level for the referenced object.
+ * Returns the access control level for the referenced object.
*
* If the cursor refers to a C++ declaration, its access control level within its
* parent scope is returned. Otherwise, if the cursor refers to a base specifier or
@@ -3826,7 +3864,7 @@ enum CX_CXXAccessSpecifier {
CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
/**
- * \brief Represents the storage classes as declared in the source. CX_SC_Invalid
+ * Represents the storage classes as declared in the source. CX_SC_Invalid
* was added for the case that the passed cursor in not a declaration.
*/
enum CX_StorageClass {
@@ -3841,7 +3879,7 @@ enum CX_StorageClass {
};
/**
- * \brief Returns the storage class for a function or variable declaration.
+ * Returns the storage class for a function or variable declaration.
*
* If the passed in Cursor is not a function or variable declaration,
* CX_SC_Invalid is returned else the storage class.
@@ -3849,7 +3887,7 @@ enum CX_StorageClass {
CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor);
/**
- * \brief Determine the number of overloaded declarations referenced by a
+ * Determine the number of overloaded declarations referenced by a
* \c CXCursor_OverloadedDeclRef cursor.
*
* \param cursor The cursor whose overloaded declarations are being queried.
@@ -3860,7 +3898,7 @@ CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor);
CINDEX_LINKAGE unsigned clang_getNumOverloadedDecls(CXCursor cursor);
/**
- * \brief Retrieve a cursor for one of the overloaded declarations referenced
+ * Retrieve a cursor for one of the overloaded declarations referenced
* by a \c CXCursor_OverloadedDeclRef cursor.
*
* \param cursor The cursor whose overloaded declarations are being queried.
@@ -3868,18 +3906,18 @@ CINDEX_LINKAGE unsigned clang_getNumOverloadedDecls(CXCursor cursor);
* \param index The zero-based index into the set of overloaded declarations in
* the cursor.
*
- * \returns A cursor representing the declaration referenced by the given
- * \c cursor at the specified \c index. If the cursor does not have an
+ * \returns A cursor representing the declaration referenced by the given
+ * \c cursor at the specified \c index. If the cursor does not have an
* associated set of overloaded declarations, or if the index is out of bounds,
* returns \c clang_getNullCursor();
*/
-CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
+CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
unsigned index);
-
+
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_ATTRIBUTES Information for attributes
*
@@ -3887,7 +3925,7 @@ CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
*/
/**
- * \brief For cursors representing an iboutletcollection attribute,
+ * For cursors representing an iboutletcollection attribute,
* this function returns the collection element type.
*
*/
@@ -3907,7 +3945,7 @@ CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor);
*/
/**
- * \brief Describes how the traversal of the children of a particular
+ * Describes how the traversal of the children of a particular
* cursor should proceed after visiting a particular child cursor.
*
* A value of this enumeration type should be returned by each
@@ -3915,23 +3953,23 @@ CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor);
*/
enum CXChildVisitResult {
/**
- * \brief Terminates the cursor traversal.
+ * Terminates the cursor traversal.
*/
CXChildVisit_Break,
/**
- * \brief Continues the cursor traversal with the next sibling of
+ * Continues the cursor traversal with the next sibling of
* the cursor just visited, without visiting its children.
*/
CXChildVisit_Continue,
/**
- * \brief Recursively traverse the children of this cursor, using
+ * Recursively traverse the children of this cursor, using
* the same visitor and client data.
*/
CXChildVisit_Recurse
};
/**
- * \brief Visitor invoked for each cursor found by a traversal.
+ * Visitor invoked for each cursor found by a traversal.
*
* This visitor function will be invoked for each cursor found by
* clang_visitCursorChildren(). Its first argument is the cursor being
@@ -3947,7 +3985,7 @@ typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
CXClientData client_data);
/**
- * \brief Visit the children of a particular cursor.
+ * Visit the children of a particular cursor.
*
* This function visits all the direct children of the given cursor,
* invoking the given \p visitor function with the cursors of each
@@ -3974,7 +4012,7 @@ CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
#ifdef __has_feature
# if __has_feature(blocks)
/**
- * \brief Visitor invoked for each cursor found by a traversal.
+ * Visitor invoked for each cursor found by a traversal.
*
* This visitor block will be invoked for each cursor found by
* clang_visitChildrenWithBlock(). Its first argument is the cursor being
@@ -3983,7 +4021,7 @@ CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
* The visitor should return one of the \c CXChildVisitResult values
* to direct clang_visitChildrenWithBlock().
*/
-typedef enum CXChildVisitResult
+typedef enum CXChildVisitResult
(^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);
/**
@@ -4011,7 +4049,7 @@ CINDEX_LINKAGE unsigned clang_visitChildrenWithBlock(CXCursor parent,
*/
/**
- * \brief Retrieve a Unified Symbol Resolution (USR) for the entity referenced
+ * Retrieve a Unified Symbol Resolution (USR) for the entity referenced
* by the given cursor.
*
* A Unified Symbol Resolution (USR) is a string that identifies a particular
@@ -4022,32 +4060,32 @@ CINDEX_LINKAGE unsigned clang_visitChildrenWithBlock(CXCursor parent,
CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor);
/**
- * \brief Construct a USR for a specified Objective-C class.
+ * Construct a USR for a specified Objective-C class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name);
/**
- * \brief Construct a USR for a specified Objective-C category.
+ * Construct a USR for a specified Objective-C category.
*/
CINDEX_LINKAGE CXString
clang_constructUSR_ObjCCategory(const char *class_name,
const char *category_name);
/**
- * \brief Construct a USR for a specified Objective-C protocol.
+ * Construct a USR for a specified Objective-C protocol.
*/
CINDEX_LINKAGE CXString
clang_constructUSR_ObjCProtocol(const char *protocol_name);
/**
- * \brief Construct a USR for a specified Objective-C instance variable and
+ * Construct a USR for a specified Objective-C instance variable and
* the USR for its containing class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name,
CXString classUSR);
/**
- * \brief Construct a USR for a specified Objective-C method and
+ * Construct a USR for a specified Objective-C method and
* the USR for its containing class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name,
@@ -4055,26 +4093,26 @@ CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name,
CXString classUSR);
/**
- * \brief Construct a USR for a specified Objective-C property and the USR
+ * Construct a USR for a specified Objective-C property and the USR
* for its containing class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property,
CXString classUSR);
/**
- * \brief Retrieve a name for the entity referenced by this cursor.
+ * Retrieve a name for the entity referenced by this cursor.
*/
CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
/**
- * \brief Retrieve a range for a piece that forms the cursors spelling name.
+ * Retrieve a range for a piece that forms the cursors spelling name.
* Most of the times there is only one range for the complete spelling but for
* Objective-C methods and Objective-C message expressions, there are multiple
* pieces for each selector identifier.
- *
+ *
* \param pieceIndex the index of the spelling name piece. If this is greater
* than the actual number of pieces, it will return a NULL (invalid) range.
- *
+ *
* \param options Reserved.
*/
CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
@@ -4082,15 +4120,98 @@ CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
unsigned options);
/**
- * \brief Retrieve the display name for the entity referenced by this cursor.
+ * Opaque pointer representing a policy that controls pretty printing
+ * for \c clang_getCursorPrettyPrinted.
+ */
+typedef void *CXPrintingPolicy;
+
+/**
+ * Properties for the printing policy.
+ *
+ * See \c clang::PrintingPolicy for more information.
+ */
+enum CXPrintingPolicyProperty {
+ CXPrintingPolicy_Indentation,
+ CXPrintingPolicy_SuppressSpecifiers,
+ CXPrintingPolicy_SuppressTagKeyword,
+ CXPrintingPolicy_IncludeTagDefinition,
+ CXPrintingPolicy_SuppressScope,
+ CXPrintingPolicy_SuppressUnwrittenScope,
+ CXPrintingPolicy_SuppressInitializers,
+ CXPrintingPolicy_ConstantArraySizeAsWritten,
+ CXPrintingPolicy_AnonymousTagLocations,
+ CXPrintingPolicy_SuppressStrongLifetime,
+ CXPrintingPolicy_SuppressLifetimeQualifiers,
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
+ CXPrintingPolicy_Bool,
+ CXPrintingPolicy_Restrict,
+ CXPrintingPolicy_Alignof,
+ CXPrintingPolicy_UnderscoreAlignof,
+ CXPrintingPolicy_UseVoidForZeroParams,
+ CXPrintingPolicy_TerseOutput,
+ CXPrintingPolicy_PolishForDeclaration,
+ CXPrintingPolicy_Half,
+ CXPrintingPolicy_MSWChar,
+ CXPrintingPolicy_IncludeNewlines,
+ CXPrintingPolicy_MSVCFormatting,
+ CXPrintingPolicy_ConstantsAsWritten,
+ CXPrintingPolicy_SuppressImplicitBase,
+ CXPrintingPolicy_FullyQualifiedName,
+
+ CXPrintingPolicy_LastProperty = CXPrintingPolicy_FullyQualifiedName
+};
+
+/**
+ * Get a property value for the given printing policy.
+ */
+CINDEX_LINKAGE unsigned
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property);
+
+/**
+ * Set a property value for the given printing policy.
+ */
+CINDEX_LINKAGE void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property,
+ unsigned Value);
+
+/**
+ * Retrieve the default policy for the cursor.
+ *
+ * The policy should be released after use with \c
+ * clang_PrintingPolicy_dispose.
+ */
+CINDEX_LINKAGE CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor);
+
+/**
+ * Release a printing policy.
+ */
+CINDEX_LINKAGE void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy);
+
+/**
+ * Pretty print declarations.
+ *
+ * \param Cursor The cursor representing a declaration.
+ *
+ * \param Policy The policy to control the entities being printed. If
+ * NULL, a default policy is used.
+ *
+ * \returns The pretty printed declaration or the empty string for
+ * other cursors.
+ */
+CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor,
+ CXPrintingPolicy Policy);
+
+/**
+ * Retrieve the display name for the entity referenced by this cursor.
*
* The display name contains extra information that helps identify the cursor,
- * such as the parameters of a function or template or the arguments of a
+ * such as the parameters of a function or template or the arguments of a
* class template specialization.
*/
CINDEX_LINKAGE CXString clang_getCursorDisplayName(CXCursor);
-
-/** \brief For a cursor that is a reference, retrieve a cursor representing the
+
+/** For a cursor that is a reference, retrieve a cursor representing the
* entity that it references.
*
* Reference cursors refer to other entities in the AST. For example, an
@@ -4103,7 +4224,7 @@ CINDEX_LINKAGE CXString clang_getCursorDisplayName(CXCursor);
CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor);
/**
- * \brief For a cursor that is either a reference to or a declaration
+ * For a cursor that is either a reference to or a declaration
* of some entity, retrieve a cursor that describes the definition of
* that entity.
*
@@ -4133,13 +4254,13 @@ CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor);
CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor);
/**
- * \brief Determine whether the declaration pointed to by this cursor
+ * Determine whether the declaration pointed to by this cursor
* is also a definition of that entity.
*/
CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
/**
- * \brief Retrieve the canonical cursor corresponding to the given cursor.
+ * Retrieve the canonical cursor corresponding to the given cursor.
*
* In the C family of languages, many kinds of entities can be declared several
* times within a single translation unit. For example, a structure type can
@@ -4153,10 +4274,10 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
* };
* \endcode
*
- * The declarations and the definition of \c X are represented by three
- * different cursors, all of which are declarations of the same underlying
+ * The declarations and the definition of \c X are represented by three
+ * different cursors, all of which are declarations of the same underlying
* entity. One of these cursor is considered the "canonical" cursor, which
- * is effectively the representative for the underlying entity. One can
+ * is effectively the representative for the underlying entity. One can
* determine if two cursors are declarations of the same underlying entity by
* comparing their canonical cursors.
*
@@ -4165,7 +4286,7 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
/**
- * \brief If the cursor points to a selector identifier in an Objective-C
+ * If the cursor points to a selector identifier in an Objective-C
* method or message expression, this returns the selector index.
*
* After getting a cursor with #clang_getCursor, this can be called to
@@ -4178,26 +4299,26 @@ CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
/**
- * \brief Given a cursor pointing to a C++ method call or an Objective-C
+ * Given a cursor pointing to a C++ method call or an Objective-C
* message, returns non-zero if the method/message is "dynamic", meaning:
- *
+ *
* For a C++ method: the call is virtual.
* For an Objective-C message: the receiver is an object instance, not 'super'
* or a specific class.
- *
+ *
* If the method/message is "static" or the cursor does not point to a
* method/message, it will return zero.
*/
CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
/**
- * \brief Given a cursor pointing to an Objective-C message or property
+ * Given a cursor pointing to an Objective-C message or property
* reference, or C++ method call, returns the CXType of the receiver.
*/
CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C);
/**
- * \brief Property attributes for a \c CXCursor_ObjCPropertyDecl.
+ * Property attributes for a \c CXCursor_ObjCPropertyDecl.
*/
typedef enum {
CXObjCPropertyAttr_noattr = 0x00,
@@ -4217,7 +4338,7 @@ typedef enum {
} CXObjCPropertyAttrKind;
/**
- * \brief Given a cursor that represents a property declaration, return the
+ * Given a cursor that represents a property declaration, return the
* associated property attributes. The bits are formed from
* \c CXObjCPropertyAttrKind.
*
@@ -4227,7 +4348,7 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C,
unsigned reserved);
/**
- * \brief 'Qualifiers' written next to the return and parameter types in
+ * 'Qualifiers' written next to the return and parameter types in
* Objective-C method declarations.
*/
typedef enum {
@@ -4241,7 +4362,7 @@ typedef enum {
} CXObjCDeclQualifierKind;
/**
- * \brief Given a cursor that represents an Objective-C method or parameter
+ * Given a cursor that represents an Objective-C method or parameter
* declaration, return the associated Objective-C qualifiers for the return
* type or the parameter respectively. The bits are formed from
* CXObjCDeclQualifierKind.
@@ -4249,19 +4370,19 @@ typedef enum {
CINDEX_LINKAGE unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C);
/**
- * \brief Given a cursor that represents an Objective-C method or property
+ * Given a cursor that represents an Objective-C method or property
* declaration, return non-zero if the declaration was affected by "\@optional".
* Returns zero if the cursor is not such a declaration or it is "\@required".
*/
CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C);
/**
- * \brief Returns non-zero if the given cursor is a variadic function or method.
+ * Returns non-zero if the given cursor is a variadic function or method.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isVariadic(CXCursor C);
/**
- * \brief Returns non-zero if the given cursor points to a symbol marked with
+ * Returns non-zero if the given cursor points to a symbol marked with
* external_source_symbol attribute.
*
* \param language If non-NULL, and the attribute is present, will be set to
@@ -4278,21 +4399,21 @@ CINDEX_LINKAGE unsigned clang_Cursor_isExternalSymbol(CXCursor C,
unsigned *isGenerated);
/**
- * \brief Given a cursor that represents a declaration, return the associated
+ * Given a cursor that represents a declaration, return the associated
* comment's source range. The range may include multiple consecutive comments
* with whitespace in between.
*/
CINDEX_LINKAGE CXSourceRange clang_Cursor_getCommentRange(CXCursor C);
/**
- * \brief Given a cursor that represents a declaration, return the associated
+ * Given a cursor that represents a declaration, return the associated
* comment text, including comment markers.
*/
CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C);
/**
- * \brief Given a cursor that represents a documentable entity (e.g.,
- * declaration), return the associated \\brief paragraph; otherwise return the
+ * Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated \paragraph; otherwise return the
* first paragraph.
*/
CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
@@ -4307,18 +4428,18 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
*/
/**
- * \brief Retrieve the CXString representing the mangled name of the cursor.
+ * Retrieve the CXString representing the mangled name of the cursor.
*/
CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
/**
- * \brief Retrieve the CXStrings representing the mangled symbols of the C++
+ * Retrieve the CXStrings representing the mangled symbols of the C++
* constructor or destructor at the cursor.
*/
CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor);
/**
- * \brief Retrieve the CXStrings representing the mangled symbols of the ObjC
+ * Retrieve the CXStrings representing the mangled symbols of the ObjC
* class interface or implementation at the cursor.
*/
CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor);
@@ -4338,12 +4459,12 @@ CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor);
typedef void *CXModule;
/**
- * \brief Given a CXCursor_ModuleImportDecl cursor, return the associated module.
+ * Given a CXCursor_ModuleImportDecl cursor, return the associated module.
*/
CINDEX_LINKAGE CXModule clang_Cursor_getModule(CXCursor C);
/**
- * \brief Given a CXFile header file, return the module that contains it, if one
+ * Given a CXFile header file, return the module that contains it, if one
* exists.
*/
CINDEX_LINKAGE CXModule clang_getModuleForFile(CXTranslationUnit, CXFile);
@@ -4418,73 +4539,73 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit,
*/
/**
- * \brief Determine if a C++ constructor is a converting constructor.
+ * Determine if a C++ constructor is a converting constructor.
*/
CINDEX_LINKAGE unsigned clang_CXXConstructor_isConvertingConstructor(CXCursor C);
/**
- * \brief Determine if a C++ constructor is a copy constructor.
+ * Determine if a C++ constructor is a copy constructor.
*/
CINDEX_LINKAGE unsigned clang_CXXConstructor_isCopyConstructor(CXCursor C);
/**
- * \brief Determine if a C++ constructor is the default constructor.
+ * Determine if a C++ constructor is the default constructor.
*/
CINDEX_LINKAGE unsigned clang_CXXConstructor_isDefaultConstructor(CXCursor C);
/**
- * \brief Determine if a C++ constructor is a move constructor.
+ * Determine if a C++ constructor is a move constructor.
*/
CINDEX_LINKAGE unsigned clang_CXXConstructor_isMoveConstructor(CXCursor C);
/**
- * \brief Determine if a C++ field is declared 'mutable'.
+ * Determine if a C++ field is declared 'mutable'.
*/
CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C);
/**
- * \brief Determine if a C++ method is declared '= default'.
+ * Determine if a C++ method is declared '= default'.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isDefaulted(CXCursor C);
/**
- * \brief Determine if a C++ member function or member function template is
+ * Determine if a C++ member function or member function template is
* pure virtual.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isPureVirtual(CXCursor C);
/**
- * \brief Determine if a C++ member function or member function template is
+ * Determine if a C++ member function or member function template is
* declared 'static'.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
/**
- * \brief Determine if a C++ member function or member function template is
+ * Determine if a C++ member function or member function template is
* explicitly declared 'virtual' or if it overrides a virtual method from
* one of the base classes.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
/**
- * \brief Determine if a C++ record is abstract, i.e. whether a class or struct
+ * 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.
+ * Determine if an enum declaration refers to a scoped enum.
*/
CINDEX_LINKAGE unsigned clang_EnumDecl_isScoped(CXCursor C);
/**
- * \brief Determine if a C++ member function or member function template is
+ * Determine if a C++ member function or member function template is
* declared 'const'.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C);
/**
- * \brief Given a cursor that represents a template, determine
+ * Given a cursor that represents a template, determine
* the cursor kind of the specializations would be generated by instantiating
* the template.
*
@@ -4501,16 +4622,16 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C);
* \c CXCursor_NoDeclFound.
*/
CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
-
+
/**
- * \brief Given a cursor that may represent a specialization or instantiation
+ * Given a cursor that may represent a specialization or instantiation
* of a template, retrieve the cursor that represents the template that it
* specializes or from which it was instantiated.
*
- * This routine determines the template involved both for explicit
+ * This routine determines the template involved both for explicit
* specializations of templates and for implicit instantiations of the template,
* both of which are referred to as "specializations". For a class template
- * specialization (e.g., \c std::vector<bool>), this routine will return
+ * specialization (e.g., \c std::vector<bool>), this routine will return
* either the primary template (\c std::vector) or, if the specialization was
* instantiated from a class template partial specialization, the class template
* partial specialization. For a class template partial specialization and a
@@ -4518,7 +4639,7 @@ CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
* this routine will return the specialized template.
*
* For members of a class template (e.g., member functions, member classes, or
- * static data members), returns the specialized or instantiated member.
+ * static data members), returns the specialized or instantiated member.
* Although not strictly "templates" in the C++ language, members of class
* templates have the same notions of specializations and instantiations that
* templates do, so this routine treats them similarly.
@@ -4526,23 +4647,23 @@ CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
* \param C A cursor that may be a specialization of a template or a member
* of a template.
*
- * \returns If the given cursor is a specialization or instantiation of a
+ * \returns If the given cursor is a specialization or instantiation of a
* template or a member thereof, the template or member that it specializes or
* from which it was instantiated. Otherwise, returns a NULL cursor.
*/
CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
/**
- * \brief Given a cursor that references something else, return the source range
+ * Given a cursor that references something else, return the source range
* covering that reference.
*
* \param C A cursor pointing to a member reference, a declaration reference, or
* an operator call.
- * \param NameFlags A bitset with three independent flags:
+ * \param NameFlags A bitset with three independent flags:
* CXNameRange_WantQualifier, CXNameRange_WantTemplateArgs, and
* CXNameRange_WantSinglePiece.
- * \param PieceIndex For contiguous names or when passing the flag
- * CXNameRange_WantSinglePiece, only one piece with index 0 is
+ * \param PieceIndex For contiguous names or when passing the flag
+ * CXNameRange_WantSinglePiece, only one piece with index 0 is
* available. When the CXNameRange_WantSinglePiece flag is not passed for a
* non-contiguous names, this index can be used to retrieve the individual
* pieces of the name. See also CXNameRange_WantSinglePiece.
@@ -4551,24 +4672,24 @@ CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
* name, or if the PieceIndex is out-of-range, a null-cursor will be returned.
*/
CINDEX_LINKAGE CXSourceRange clang_getCursorReferenceNameRange(CXCursor C,
- unsigned NameFlags,
+ unsigned NameFlags,
unsigned PieceIndex);
enum CXNameRefFlags {
/**
- * \brief Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the
+ * Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the
* range.
*/
CXNameRange_WantQualifier = 0x1,
-
+
/**
- * \brief Include the explicit template arguments, e.g. \<int> in x.f<int>,
+ * Include the explicit template arguments, e.g. \<int> in x.f<int>,
* in the range.
*/
CXNameRange_WantTemplateArgs = 0x2,
/**
- * \brief If the name is non-contiguous, return the full spanning range.
+ * If the name is non-contiguous, return the full spanning range.
*
* Non-contiguous names occur in Objective-C when a selector with two or more
* parameters is used, or in C++ when using an operator:
@@ -4579,7 +4700,7 @@ enum CXNameRefFlags {
*/
CXNameRange_WantSinglePiece = 0x4
};
-
+
/**
* @}
*/
@@ -4595,37 +4716,37 @@ enum CXNameRefFlags {
*/
/**
- * \brief Describes a kind of token.
+ * Describes a kind of token.
*/
typedef enum CXTokenKind {
/**
- * \brief A token that contains some kind of punctuation.
+ * A token that contains some kind of punctuation.
*/
CXToken_Punctuation,
/**
- * \brief A language keyword.
+ * A language keyword.
*/
CXToken_Keyword,
/**
- * \brief An identifier (that is not a keyword).
+ * An identifier (that is not a keyword).
*/
CXToken_Identifier,
/**
- * \brief A numeric, string, or character literal.
+ * A numeric, string, or character literal.
*/
CXToken_Literal,
/**
- * \brief A comment.
+ * A comment.
*/
CXToken_Comment
} CXTokenKind;
/**
- * \brief Describes a single preprocessing token.
+ * Describes a single preprocessing token.
*/
typedef struct {
unsigned int_data[4];
@@ -4633,12 +4754,26 @@ typedef struct {
} CXToken;
/**
- * \brief Determine the kind of the given token.
+ * Get the raw lexical token starting with the given location.
+ *
+ * \param TU the translation unit whose text is being tokenized.
+ *
+ * \param Location the source location with which the token starts.
+ *
+ * \returns The token starting with the given location or NULL if no such token
+ * exist. The returned pointer must be freed with clang_disposeTokens before the
+ * translation unit is destroyed.
+ */
+CINDEX_LINKAGE CXToken *clang_getToken(CXTranslationUnit TU,
+ CXSourceLocation Location);
+
+/**
+ * Determine the kind of the given token.
*/
CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
/**
- * \brief Determine the spelling of the given token.
+ * Determine the spelling of the given token.
*
* The spelling of a token is the textual representation of that token, e.g.,
* the text of an identifier or keyword.
@@ -4646,18 +4781,18 @@ CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
/**
- * \brief Retrieve the source location of the given token.
+ * Retrieve the source location of the given token.
*/
CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
CXToken);
/**
- * \brief Retrieve a source range that covers the given token.
+ * Retrieve a source range that covers the given token.
*/
CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken);
/**
- * \brief Tokenize the source code described by the given range into raw
+ * Tokenize the source code described by the given range into raw
* lexical tokens.
*
* \param TU the translation unit whose text is being tokenized.
@@ -4677,7 +4812,7 @@ CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
CXToken **Tokens, unsigned *NumTokens);
/**
- * \brief Annotate the given set of tokens by providing cursors for each token
+ * Annotate the given set of tokens by providing cursors for each token
* that can be mapped to a specific entity within the abstract syntax tree.
*
* This token-annotation routine is equivalent to invoking
@@ -4711,7 +4846,7 @@ CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU,
CXCursor *Cursors);
/**
- * \brief Free the given set of tokens.
+ * Free the given set of tokens.
*/
CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU,
CXToken *Tokens, unsigned NumTokens);
@@ -4759,7 +4894,7 @@ CINDEX_LINKAGE void clang_executeOnThread(void (*fn)(void*), void *user_data,
*/
/**
- * \brief A semantic string that describes a code-completion result.
+ * A semantic string that describes a code-completion result.
*
* A semantic string that describes the formatting of a code-completion
* result as a single "template" of text that should be inserted into the
@@ -4774,11 +4909,11 @@ CINDEX_LINKAGE void clang_executeOnThread(void (*fn)(void*), void *user_data,
typedef void *CXCompletionString;
/**
- * \brief A single result of code completion.
+ * A single result of code completion.
*/
typedef struct {
/**
- * \brief The kind of entity that this completion refers to.
+ * The kind of entity that this completion refers to.
*
* The cursor kind will be a macro, keyword, or a declaration (one of the
* *Decl cursor kinds), describing the entity that the completion is
@@ -4790,14 +4925,14 @@ typedef struct {
enum CXCursorKind CursorKind;
/**
- * \brief The code-completion string that describes how to insert this
+ * The code-completion string that describes how to insert this
* code-completion result into the editing buffer.
*/
CXCompletionString CompletionString;
} CXCompletionResult;
/**
- * \brief Describes a single piece of text within a code-completion string.
+ * Describes a single piece of text within a code-completion string.
*
* Each "chunk" within a code-completion string (\c CXCompletionString) is
* either a piece of text with a specific "kind" that describes how that text
@@ -4805,7 +4940,7 @@ typedef struct {
*/
enum CXCompletionChunkKind {
/**
- * \brief A code-completion string that describes "optional" text that
+ * A code-completion string that describes "optional" text that
* could be a part of the template (but is not required).
*
* The Optional chunk is the only kind of chunk that has a code-completion
@@ -4839,7 +4974,7 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_Optional,
/**
- * \brief Text that a user would be expected to type to get this
+ * Text that a user would be expected to type to get this
* code-completion result.
*
* There will be exactly one "typed text" chunk in a semantic string, which
@@ -4850,7 +4985,7 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_TypedText,
/**
- * \brief Text that should be inserted as part of a code-completion result.
+ * Text that should be inserted as part of a code-completion result.
*
* A "text" chunk represents text that is part of the template to be
* inserted into user code should this particular code-completion result
@@ -4858,7 +4993,7 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_Text,
/**
- * \brief Placeholder text that should be replaced by the user.
+ * Placeholder text that should be replaced by the user.
*
* A "placeholder" chunk marks a place where the user should insert text
* into the code-completion template. For example, placeholders might mark
@@ -4869,7 +5004,7 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_Placeholder,
/**
- * \brief Informative text that should be displayed but never inserted as
+ * Informative text that should be displayed but never inserted as
* part of the template.
*
* An "informative" chunk contains annotations that can be displayed to
@@ -4879,7 +5014,7 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_Informative,
/**
- * \brief Text that describes the current parameter when code-completion is
+ * Text that describes the current parameter when code-completion is
* referring to function call, message send, or template specialization.
*
* A "current parameter" chunk occurs when code-completion is providing
@@ -4895,49 +5030,49 @@ enum CXCompletionChunkKind {
* for "int x", indicating that the current argument will initialize that
* parameter. After typing further, to \c add(17, (where the code-completion
* point is after the ","), the code-completion string will contain a
- * "current paremeter" chunk to "int y".
+ * "current parameter" chunk to "int y".
*/
CXCompletionChunk_CurrentParameter,
/**
- * \brief A left parenthesis ('('), used to initiate a function call or
+ * A left parenthesis ('('), used to initiate a function call or
* signal the beginning of a function parameter list.
*/
CXCompletionChunk_LeftParen,
/**
- * \brief A right parenthesis (')'), used to finish a function call or
+ * A right parenthesis (')'), used to finish a function call or
* signal the end of a function parameter list.
*/
CXCompletionChunk_RightParen,
/**
- * \brief A left bracket ('[').
+ * A left bracket ('[').
*/
CXCompletionChunk_LeftBracket,
/**
- * \brief A right bracket (']').
+ * A right bracket (']').
*/
CXCompletionChunk_RightBracket,
/**
- * \brief A left brace ('{').
+ * A left brace ('{').
*/
CXCompletionChunk_LeftBrace,
/**
- * \brief A right brace ('}').
+ * A right brace ('}').
*/
CXCompletionChunk_RightBrace,
/**
- * \brief A left angle bracket ('<').
+ * A left angle bracket ('<').
*/
CXCompletionChunk_LeftAngle,
/**
- * \brief A right angle bracket ('>').
+ * A right angle bracket ('>').
*/
CXCompletionChunk_RightAngle,
/**
- * \brief A comma separator (',').
+ * A comma separator (',').
*/
CXCompletionChunk_Comma,
/**
- * \brief Text that specifies the result type of a given result.
+ * Text that specifies the result type of a given result.
*
* This special kind of informative chunk is not meant to be inserted into
* the text buffer. Rather, it is meant to illustrate the type that an
@@ -4945,15 +5080,15 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_ResultType,
/**
- * \brief A colon (':').
+ * A colon (':').
*/
CXCompletionChunk_Colon,
/**
- * \brief A semicolon (';').
+ * A semicolon (';').
*/
CXCompletionChunk_SemiColon,
/**
- * \brief An '=' sign.
+ * An '=' sign.
*/
CXCompletionChunk_Equal,
/**
@@ -4968,7 +5103,7 @@ enum CXCompletionChunkKind {
};
/**
- * \brief Determine the kind of a particular chunk within a completion string.
+ * Determine the kind of a particular chunk within a completion string.
*
* \param completion_string the completion string to query.
*
@@ -4981,7 +5116,7 @@ clang_getCompletionChunkKind(CXCompletionString completion_string,
unsigned chunk_number);
/**
- * \brief Retrieve the text associated with a particular chunk within a
+ * Retrieve the text associated with a particular chunk within a
* completion string.
*
* \param completion_string the completion string to query.
@@ -4995,7 +5130,7 @@ clang_getCompletionChunkText(CXCompletionString completion_string,
unsigned chunk_number);
/**
- * \brief Retrieve the completion string associated with a particular chunk
+ * Retrieve the completion string associated with a particular chunk
* within a completion string.
*
* \param completion_string the completion string to query.
@@ -5010,15 +5145,15 @@ clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
unsigned chunk_number);
/**
- * \brief Retrieve the number of chunks in the given code-completion string.
+ * Retrieve the number of chunks in the given code-completion string.
*/
CINDEX_LINKAGE unsigned
clang_getNumCompletionChunks(CXCompletionString completion_string);
/**
- * \brief Determine the priority of this code completion.
+ * Determine the priority of this code completion.
*
- * The priority of a code completion indicates how likely it is that this
+ * The priority of a code completion indicates how likely it is that this
* particular completion is the completion that the user will select. The
* priority is selected by various internal heuristics.
*
@@ -5029,20 +5164,20 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
*/
CINDEX_LINKAGE unsigned
clang_getCompletionPriority(CXCompletionString completion_string);
-
+
/**
- * \brief Determine the availability of the entity that this code-completion
+ * Determine the availability of the entity that this code-completion
* string refers to.
*
* \param completion_string The completion string to query.
*
* \returns The availability of the completion string.
*/
-CINDEX_LINKAGE enum CXAvailabilityKind
+CINDEX_LINKAGE enum CXAvailabilityKind
clang_getCompletionAvailability(CXCompletionString completion_string);
/**
- * \brief Retrieve the number of annotations associated with the given
+ * Retrieve the number of annotations associated with the given
* completion string.
*
* \param completion_string the completion string to query.
@@ -5054,7 +5189,7 @@ CINDEX_LINKAGE unsigned
clang_getCompletionNumAnnotations(CXCompletionString completion_string);
/**
- * \brief Retrieve the annotation associated with the given completion string.
+ * Retrieve the annotation associated with the given completion string.
*
* \param completion_string the completion string to query.
*
@@ -5069,9 +5204,9 @@ clang_getCompletionAnnotation(CXCompletionString completion_string,
unsigned annotation_number);
/**
- * \brief Retrieve the parent context of the given completion string.
+ * Retrieve the parent context of the given completion string.
*
- * The parent context of a completion string is the semantic parent of
+ * The parent context of a completion string is the semantic parent of
* the declaration (if any) that the code completion represents. For example,
* a code completion for an Objective-C method would have the method's class
* or protocol as its context.
@@ -5089,14 +5224,14 @@ clang_getCompletionParent(CXCompletionString completion_string,
enum CXCursorKind *kind);
/**
- * \brief Retrieve the brief documentation comment attached to the declaration
+ * Retrieve the brief documentation comment attached to the declaration
* that corresponds to the given completion string.
*/
CINDEX_LINKAGE CXString
clang_getCompletionBriefComment(CXCompletionString completion_string);
/**
- * \brief Retrieve a completion string for an arbitrary declaration or macro
+ * Retrieve a completion string for an arbitrary declaration or macro
* definition cursor.
*
* \param cursor The cursor to query.
@@ -5106,9 +5241,9 @@ clang_getCompletionBriefComment(CXCompletionString completion_string);
*/
CINDEX_LINKAGE CXCompletionString
clang_getCursorCompletionString(CXCursor cursor);
-
+
/**
- * \brief Contains the results of code-completion.
+ * Contains the results of code-completion.
*
* This data structure contains the results of code completion, as
* produced by \c clang_codeCompleteAt(). Its contents must be freed by
@@ -5116,19 +5251,83 @@ clang_getCursorCompletionString(CXCursor cursor);
*/
typedef struct {
/**
- * \brief The code-completion results.
+ * The code-completion results.
*/
CXCompletionResult *Results;
/**
- * \brief The number of code-completion results stored in the
+ * The number of code-completion results stored in the
* \c Results array.
*/
unsigned NumResults;
} CXCodeCompleteResults;
/**
- * \brief Flags that can be passed to \c clang_codeCompleteAt() to
+ * Retrieve the number of fix-its for the given completion index.
+ *
+ * Calling this makes sense only if CXCodeComplete_IncludeCompletionsWithFixIts
+ * option was set.
+ *
+ * \param results The structure keeping all completion results
+ *
+ * \param completion_index The index of the completion
+ *
+ * \return The number of fix-its which must be applied before the completion at
+ * completion_index can be applied
+ */
+CINDEX_LINKAGE unsigned
+clang_getCompletionNumFixIts(CXCodeCompleteResults *results,
+ unsigned completion_index);
+
+/**
+ * Fix-its that *must* be applied before inserting the text for the
+ * corresponding completion.
+ *
+ * By default, clang_codeCompleteAt() only returns completions with empty
+ * fix-its. Extra completions with non-empty fix-its should be explicitly
+ * requested by setting CXCodeComplete_IncludeCompletionsWithFixIts.
+ *
+ * For the clients to be able to compute position of the cursor after applying
+ * fix-its, the following conditions are guaranteed to hold for
+ * replacement_range of the stored fix-its:
+ * - Ranges in the fix-its are guaranteed to never contain the completion
+ * point (or identifier under completion point, if any) inside them, except
+ * at the start or at the end of the range.
+ * - If a fix-it range starts or ends with completion point (or starts or
+ * ends after the identifier under completion point), it will contain at
+ * least one character. It allows to unambiguously recompute completion
+ * point after applying the fix-it.
+ *
+ * The intuition is that provided fix-its change code around the identifier we
+ * complete, but are not allowed to touch the identifier itself or the
+ * completion point. One example of completions with corrections are the ones
+ * replacing '.' with '->' and vice versa:
+ *
+ * std::unique_ptr<std::vector<int>> vec_ptr;
+ * In 'vec_ptr.^', one of the completions is 'push_back', it requires
+ * replacing '.' with '->'.
+ * In 'vec_ptr->^', one of the completions is 'release', it requires
+ * replacing '->' with '.'.
+ *
+ * \param results The structure keeping all completion results
+ *
+ * \param completion_index The index of the completion
+ *
+ * \param fixit_index The index of the fix-it for the completion at
+ * completion_index
+ *
+ * \param replacement_range The fix-it range that must be replaced before the
+ * completion at completion_index can be applied
+ *
+ * \returns The fix-it string that must replace the code at replacement_range
+ * before the completion at completion_index can be applied
+ */
+CINDEX_LINKAGE CXString clang_getCompletionFixIt(
+ CXCodeCompleteResults *results, unsigned completion_index,
+ unsigned fixit_index, CXSourceRange *replacement_range);
+
+/**
+ * Flags that can be passed to \c clang_codeCompleteAt() to
* modify its behavior.
*
* The enumerators in this enumeration can be bitwise-OR'd together to
@@ -5136,163 +5335,176 @@ typedef struct {
*/
enum CXCodeComplete_Flags {
/**
- * \brief Whether to include macros within the set of code
+ * Whether to include macros within the set of code
* completions returned.
*/
CXCodeComplete_IncludeMacros = 0x01,
/**
- * \brief Whether to include code patterns for language constructs
+ * Whether to include code patterns for language constructs
* within the set of code completions, e.g., for loops.
*/
CXCodeComplete_IncludeCodePatterns = 0x02,
/**
- * \brief Whether to include brief documentation within the set of code
+ * Whether to include brief documentation within the set of code
* completions returned.
*/
- CXCodeComplete_IncludeBriefComments = 0x04
+ CXCodeComplete_IncludeBriefComments = 0x04,
+
+ /**
+ * Whether to speed up completion by omitting top- or namespace-level entities
+ * defined in the preamble. There's no guarantee any particular entity is
+ * omitted. This may be useful if the headers are indexed externally.
+ */
+ CXCodeComplete_SkipPreamble = 0x08,
+
+ /**
+ * Whether to include completions with small
+ * fix-its, e.g. change '.' to '->' on member access, etc.
+ */
+ CXCodeComplete_IncludeCompletionsWithFixIts = 0x10
};
/**
- * \brief Bits that represent the context under which completion is occurring.
+ * Bits that represent the context under which completion is occurring.
*
* The enumerators in this enumeration may be bitwise-OR'd together if multiple
* contexts are occurring simultaneously.
*/
enum CXCompletionContext {
/**
- * \brief The context for completions is unexposed, as only Clang results
+ * The context for completions is unexposed, as only Clang results
* should be included. (This is equivalent to having no context bits set.)
*/
CXCompletionContext_Unexposed = 0,
-
+
/**
- * \brief Completions for any possible type should be included in the results.
+ * Completions for any possible type should be included in the results.
*/
CXCompletionContext_AnyType = 1 << 0,
-
+
/**
- * \brief Completions for any possible value (variables, function calls, etc.)
+ * Completions for any possible value (variables, function calls, etc.)
* should be included in the results.
*/
CXCompletionContext_AnyValue = 1 << 1,
/**
- * \brief Completions for values that resolve to an Objective-C object should
+ * Completions for values that resolve to an Objective-C object should
* be included in the results.
*/
CXCompletionContext_ObjCObjectValue = 1 << 2,
/**
- * \brief Completions for values that resolve to an Objective-C selector
+ * Completions for values that resolve to an Objective-C selector
* should be included in the results.
*/
CXCompletionContext_ObjCSelectorValue = 1 << 3,
/**
- * \brief Completions for values that resolve to a C++ class type should be
+ * Completions for values that resolve to a C++ class type should be
* included in the results.
*/
CXCompletionContext_CXXClassTypeValue = 1 << 4,
-
+
/**
- * \brief Completions for fields of the member being accessed using the dot
+ * Completions for fields of the member being accessed using the dot
* operator should be included in the results.
*/
CXCompletionContext_DotMemberAccess = 1 << 5,
/**
- * \brief Completions for fields of the member being accessed using the arrow
+ * Completions for fields of the member being accessed using the arrow
* operator should be included in the results.
*/
CXCompletionContext_ArrowMemberAccess = 1 << 6,
/**
- * \brief Completions for properties of the Objective-C object being accessed
+ * Completions for properties of the Objective-C object being accessed
* using the dot operator should be included in the results.
*/
CXCompletionContext_ObjCPropertyAccess = 1 << 7,
-
+
/**
- * \brief Completions for enum tags should be included in the results.
+ * Completions for enum tags should be included in the results.
*/
CXCompletionContext_EnumTag = 1 << 8,
/**
- * \brief Completions for union tags should be included in the results.
+ * Completions for union tags should be included in the results.
*/
CXCompletionContext_UnionTag = 1 << 9,
/**
- * \brief Completions for struct tags should be included in the results.
+ * Completions for struct tags should be included in the results.
*/
CXCompletionContext_StructTag = 1 << 10,
-
+
/**
- * \brief Completions for C++ class names should be included in the results.
+ * Completions for C++ class names should be included in the results.
*/
CXCompletionContext_ClassTag = 1 << 11,
/**
- * \brief Completions for C++ namespaces and namespace aliases should be
+ * Completions for C++ namespaces and namespace aliases should be
* included in the results.
*/
CXCompletionContext_Namespace = 1 << 12,
/**
- * \brief Completions for C++ nested name specifiers should be included in
+ * Completions for C++ nested name specifiers should be included in
* the results.
*/
CXCompletionContext_NestedNameSpecifier = 1 << 13,
-
+
/**
- * \brief Completions for Objective-C interfaces (classes) should be included
+ * Completions for Objective-C interfaces (classes) should be included
* in the results.
*/
CXCompletionContext_ObjCInterface = 1 << 14,
/**
- * \brief Completions for Objective-C protocols should be included in
+ * Completions for Objective-C protocols should be included in
* the results.
*/
CXCompletionContext_ObjCProtocol = 1 << 15,
/**
- * \brief Completions for Objective-C categories should be included in
+ * Completions for Objective-C categories should be included in
* the results.
*/
CXCompletionContext_ObjCCategory = 1 << 16,
/**
- * \brief Completions for Objective-C instance messages should be included
+ * Completions for Objective-C instance messages should be included
* in the results.
*/
CXCompletionContext_ObjCInstanceMessage = 1 << 17,
/**
- * \brief Completions for Objective-C class messages should be included in
+ * Completions for Objective-C class messages should be included in
* the results.
*/
CXCompletionContext_ObjCClassMessage = 1 << 18,
/**
- * \brief Completions for Objective-C selector names should be included in
+ * Completions for Objective-C selector names should be included in
* the results.
*/
CXCompletionContext_ObjCSelectorName = 1 << 19,
-
+
/**
- * \brief Completions for preprocessor macro names should be included in
+ * Completions for preprocessor macro names should be included in
* the results.
*/
CXCompletionContext_MacroName = 1 << 20,
-
+
/**
- * \brief Natural language completions should be included in the results.
+ * Natural language completions should be included in the results.
*/
CXCompletionContext_NaturalLanguage = 1 << 21,
-
+
/**
- * \brief The current context is unknown, so set all contexts.
+ * The current context is unknown, so set all contexts.
*/
CXCompletionContext_Unknown = ((1 << 22) - 1)
};
-
+
/**
- * \brief Returns a default set of code-completion options that can be
- * passed to\c clang_codeCompleteAt().
+ * Returns a default set of code-completion options that can be
+ * passed to\c clang_codeCompleteAt().
*/
CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
/**
- * \brief Perform code completion at a given location in a translation unit.
+ * Perform code completion at a given location in a translation unit.
*
* This function performs code completion at a particular file, line, and
* column within source code, providing results that suggest potential
@@ -5309,7 +5521,7 @@ CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
* user types punctuation characters or whitespace, at which point the
* code-completion location will coincide with the cursor. For example, if \c p
* is a pointer, code-completion might be triggered after the "-" and then
- * after the ">" in \c p->. When the code-completion location is afer the ">",
+ * after the ">" in \c p->. When the code-completion location is after the ">",
* the completion results will provide, e.g., the members of the struct that
* "p" points to. The client is responsible for placing the cursor at the
* beginning of the token currently being typed, then filtering the results
@@ -5350,7 +5562,7 @@ CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
*
* \param options Extra options that control the behavior of code
* completion, expressed as a bitwise OR of the enumerators of the
- * CXCodeComplete_Flags enumeration. The
+ * CXCodeComplete_Flags enumeration. The
* \c clang_defaultCodeCompleteOptions() function returns a default set
* of code-completion options.
*
@@ -5369,7 +5581,7 @@ CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
unsigned options);
/**
- * \brief Sort the code-completion results in case-insensitive alphabetical
+ * Sort the code-completion results in case-insensitive alphabetical
* order.
*
* \param Results The set of results to sort.
@@ -5378,22 +5590,22 @@ CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
CINDEX_LINKAGE
void clang_sortCodeCompletionResults(CXCompletionResult *Results,
unsigned NumResults);
-
+
/**
- * \brief Free the given set of code-completion results.
+ * Free the given set of code-completion results.
*/
CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
-
+
/**
- * \brief Determine the number of diagnostics produced prior to the
+ * Determine the number of diagnostics produced prior to the
* location where code completion was performed.
*/
CINDEX_LINKAGE
unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
/**
- * \brief Retrieve a diagnostic associated with the given code completion.
+ * Retrieve a diagnostic associated with the given code completion.
*
* \param Results the code completion results to query.
* \param Index the zero-based diagnostic number to retrieve.
@@ -5406,9 +5618,9 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
unsigned Index);
/**
- * \brief Determines what completions are appropriate for the context
+ * Determines what completions are appropriate for the context
* the given code completion.
- *
+ *
* \param Results the code completion results to query
*
* \returns the kinds of completions that are appropriate for use
@@ -5419,7 +5631,7 @@ unsigned long long clang_codeCompleteGetContexts(
CXCodeCompleteResults *Results);
/**
- * \brief Returns the cursor kind for the container for the current code
+ * Returns the cursor kind for the container for the current code
* completion context. The container is only guaranteed to be set for
* contexts where a container exists (i.e. member accesses or Objective-C
* message sends); if there is not a container, this function will return
@@ -5440,7 +5652,7 @@ enum CXCursorKind clang_codeCompleteGetContainerKind(
unsigned *IsIncomplete);
/**
- * \brief Returns the USR for the container for the current code completion
+ * Returns the USR for the container for the current code completion
* context. If there is not a container for the current context, this
* function will return the empty string.
*
@@ -5452,7 +5664,7 @@ CINDEX_LINKAGE
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
/**
- * \brief Returns the currently-entered selector for an Objective-C message
+ * Returns the currently-entered selector for an Objective-C message
* send, formatted like "initWithFoo:bar:". Only guaranteed to return a
* non-empty string for CXCompletionContext_ObjCInstanceMessage and
* CXCompletionContext_ObjCClassMessage.
@@ -5464,7 +5676,7 @@ CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
*/
CINDEX_LINKAGE
CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
-
+
/**
* @}
*/
@@ -5476,21 +5688,21 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
*/
/**
- * \brief Return a version string, suitable for showing to a user, but not
+ * Return a version string, suitable for showing to a user, but not
* intended to be parsed (the format is not guaranteed to be stable).
*/
CINDEX_LINKAGE CXString clang_getClangVersion(void);
/**
- * \brief Enable/disable crash recovery.
+ * Enable/disable crash recovery.
*
* \param isEnabled Flag to indicate if crash recovery is enabled. A non-zero
* value enables crash recovery, while 0 disables it.
*/
CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled);
-
+
/**
- * \brief Visitor invoked for each file in a translation unit
+ * Visitor invoked for each file in a translation unit
* (used with clang_getInclusions()).
*
* This visitor function will be invoked by clang_getInclusions() for each
@@ -5506,7 +5718,7 @@ typedef void (*CXInclusionVisitor)(CXFile included_file,
CXClientData client_data);
/**
- * \brief Visit the set of preprocessor inclusions in a translation unit.
+ * Visit the set of preprocessor inclusions in a translation unit.
* The visitor function is called with the provided data for every included
* file. This does not include headers included by the PCH file (unless one
* is inspecting the inclusions in the PCH file itself).
@@ -5528,55 +5740,55 @@ typedef enum {
} CXEvalResultKind ;
/**
- * \brief Evaluation result of a cursor
+ * Evaluation result of a cursor
*/
typedef void * CXEvalResult;
/**
- * \brief If cursor is a statement declaration tries to evaluate the
+ * If cursor is a statement declaration tries to evaluate the
* statement and if its variable, tries to evaluate its initializer,
* into its corresponding type.
*/
CINDEX_LINKAGE CXEvalResult clang_Cursor_Evaluate(CXCursor C);
/**
- * \brief Returns the kind of the evaluated result.
+ * Returns the kind of the evaluated result.
*/
CINDEX_LINKAGE CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E);
/**
- * \brief Returns the evaluation result as integer if the
+ * Returns the evaluation result as integer if the
* kind is Int.
*/
CINDEX_LINKAGE int clang_EvalResult_getAsInt(CXEvalResult E);
/**
- * \brief Returns the evaluation result as a long long integer if the
+ * Returns the evaluation result as a long long integer if the
* kind is Int. This prevents overflows that may happen if the result is
* returned with clang_EvalResult_getAsInt.
*/
CINDEX_LINKAGE long long clang_EvalResult_getAsLongLong(CXEvalResult E);
/**
- * \brief Returns a non-zero value if the kind is Int and the evaluation
+ * Returns a non-zero value if the kind is Int and the evaluation
* result resulted in an unsigned integer.
*/
CINDEX_LINKAGE unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E);
/**
- * \brief Returns the evaluation result as an unsigned integer if
+ * Returns the evaluation result as an unsigned integer if
* the kind is Int and clang_EvalResult_isUnsignedInt is non-zero.
*/
CINDEX_LINKAGE unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E);
/**
- * \brief Returns the evaluation result as double if the
+ * Returns the evaluation result as double if the
* kind is double.
*/
CINDEX_LINKAGE double clang_EvalResult_getAsDouble(CXEvalResult E);
/**
- * \brief Returns the evaluation result as a constant string if the
+ * Returns the evaluation result as a constant string if the
* kind is other than Int or float. User must not free this pointer,
* instead call clang_EvalResult_dispose on the CXEvalResult returned
* by clang_Cursor_Evaluate.
@@ -5584,7 +5796,7 @@ CINDEX_LINKAGE double clang_EvalResult_getAsDouble(CXEvalResult E);
CINDEX_LINKAGE const char* clang_EvalResult_getAsStr(CXEvalResult E);
/**
- * \brief Disposes the created Eval memory.
+ * Disposes the created Eval memory.
*/
CINDEX_LINKAGE void clang_EvalResult_dispose(CXEvalResult E);
/**
@@ -5597,12 +5809,12 @@ CINDEX_LINKAGE void clang_EvalResult_dispose(CXEvalResult E);
*/
/**
- * \brief A remapping of original source files and their translated files.
+ * A remapping of original source files and their translated files.
*/
typedef void *CXRemapping;
/**
- * \brief Retrieve a remapping.
+ * Retrieve a remapping.
*
* \param path the path that contains metadata about remappings.
*
@@ -5612,7 +5824,7 @@ typedef void *CXRemapping;
CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *path);
/**
- * \brief Retrieve a remapping.
+ * Retrieve a remapping.
*
* \param filePaths pointer to an array of file paths containing remapping info.
*
@@ -5626,13 +5838,13 @@ CXRemapping clang_getRemappingsFromFileList(const char **filePaths,
unsigned numFiles);
/**
- * \brief Determine the number of remappings.
+ * Determine the number of remappings.
*/
CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
/**
- * \brief Get the original and the associated filename from the remapping.
- *
+ * Get the original and the associated filename from the remapping.
+ *
* \param original If non-NULL, will be set to the original filename.
*
* \param transformed If non-NULL, will be set to the filename that the original
@@ -5642,7 +5854,7 @@ CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index,
CXString *original, CXString *transformed);
/**
- * \brief Dispose the remapping.
+ * Dispose the remapping.
*/
CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
@@ -5667,15 +5879,15 @@ typedef struct CXCursorAndRangeVisitor {
typedef enum {
/**
- * \brief Function returned successfully.
+ * Function returned successfully.
*/
CXResult_Success = 0,
/**
- * \brief One of the parameters was invalid for the function.
+ * One of the parameters was invalid for the function.
*/
CXResult_Invalid = 1,
/**
- * \brief The function was terminated by a callback (e.g. it returned
+ * The function was terminated by a callback (e.g. it returned
* CXVisit_Break)
*/
CXResult_VisitBreak = 2
@@ -5683,8 +5895,8 @@ typedef enum {
} CXResult;
/**
- * \brief Find references of a declaration in a specific file.
- *
+ * Find references of a declaration in a specific file.
+ *
* \param cursor pointing to a declaration or a reference of one.
*
* \param file to search for references.
@@ -5700,7 +5912,7 @@ CINDEX_LINKAGE CXResult clang_findReferencesInFile(CXCursor cursor, CXFile file,
CXCursorAndRangeVisitor visitor);
/**
- * \brief Find #import/#include directives in a specific file.
+ * Find #import/#include directives in a specific file.
*
* \param TU translation unit containing the file to query.
*
@@ -5733,29 +5945,29 @@ CXResult clang_findIncludesInFileWithBlock(CXTranslationUnit, CXFile,
#endif
/**
- * \brief The client's data object that is associated with a CXFile.
+ * The client's data object that is associated with a CXFile.
*/
typedef void *CXIdxClientFile;
/**
- * \brief The client's data object that is associated with a semantic entity.
+ * The client's data object that is associated with a semantic entity.
*/
typedef void *CXIdxClientEntity;
/**
- * \brief The client's data object that is associated with a semantic container
+ * The client's data object that is associated with a semantic container
* of entities.
*/
typedef void *CXIdxClientContainer;
/**
- * \brief The client's data object that is associated with an AST file (PCH
+ * The client's data object that is associated with an AST file (PCH
* or module).
*/
typedef void *CXIdxClientASTFile;
/**
- * \brief Source location passed to index callbacks.
+ * Source location passed to index callbacks.
*/
typedef struct {
void *ptr_data[2];
@@ -5763,48 +5975,48 @@ typedef struct {
} CXIdxLoc;
/**
- * \brief Data for ppIncludedFile callback.
+ * Data for ppIncludedFile callback.
*/
typedef struct {
/**
- * \brief Location of '#' in the \#include/\#import directive.
+ * Location of '#' in the \#include/\#import directive.
*/
CXIdxLoc hashLoc;
/**
- * \brief Filename as written in the \#include/\#import directive.
+ * Filename as written in the \#include/\#import directive.
*/
const char *filename;
/**
- * \brief The actual file that the \#include/\#import directive resolved to.
+ * The actual file that the \#include/\#import directive resolved to.
*/
CXFile file;
int isImport;
int isAngled;
/**
- * \brief Non-zero if the directive was automatically turned into a module
+ * Non-zero if the directive was automatically turned into a module
* import.
*/
int isModuleImport;
} CXIdxIncludedFileInfo;
/**
- * \brief Data for IndexerCallbacks#importedASTFile.
+ * Data for IndexerCallbacks#importedASTFile.
*/
typedef struct {
/**
- * \brief Top level AST file containing the imported PCH, module or submodule.
+ * Top level AST file containing the imported PCH, module or submodule.
*/
CXFile file;
/**
- * \brief The imported module or NULL if the AST file is a PCH.
+ * The imported module or NULL if the AST file is a PCH.
*/
CXModule module;
/**
- * \brief Location where the file is imported. Applicable only for modules.
+ * Location where the file is imported. Applicable only for modules.
*/
CXIdxLoc loc;
/**
- * \brief Non-zero if an inclusion directive was automatically turned into
+ * Non-zero if an inclusion directive was automatically turned into
* a module import. Applicable only for modules.
*/
int isImplicit;
@@ -5855,7 +6067,7 @@ typedef enum {
} CXIdxEntityLanguage;
/**
- * \brief Extra C++ template information for an entity. This can apply to:
+ * Extra C++ template information for an entity. This can apply to:
* CXIdxEntity_Function
* CXIdxEntity_CXXClass
* CXIdxEntity_CXXStaticMethod
@@ -5916,7 +6128,7 @@ typedef struct {
CXIdxLoc loc;
const CXIdxContainerInfo *semanticContainer;
/**
- * \brief Generally same as #semanticContainer but can be different in
+ * Generally same as #semanticContainer but can be different in
* cases like out-of-line C++ member functions.
*/
const CXIdxContainerInfo *lexicalContainer;
@@ -5925,7 +6137,7 @@ typedef struct {
int isContainer;
const CXIdxContainerInfo *declAsContainer;
/**
- * \brief Whether the declaration exists in code or was created implicitly
+ * Whether the declaration exists in code or was created implicitly
* by the compiler, e.g. implicit Objective-C methods for properties.
*/
int isImplicit;
@@ -5991,81 +6203,107 @@ typedef struct {
} CXIdxCXXClassDeclInfo;
/**
- * \brief Data for IndexerCallbacks#indexEntityReference.
+ * Data for IndexerCallbacks#indexEntityReference.
+ *
+ * This may be deprecated in a future version as this duplicates
+ * the \c CXSymbolRole_Implicit bit in \c CXSymbolRole.
*/
typedef enum {
/**
- * \brief The entity is referenced directly in user's code.
+ * The entity is referenced directly in user's code.
*/
CXIdxEntityRef_Direct = 1,
/**
- * \brief An implicit reference, e.g. a reference of an Objective-C method
+ * An implicit reference, e.g. a reference of an Objective-C method
* via the dot syntax.
*/
CXIdxEntityRef_Implicit = 2
} CXIdxEntityRefKind;
/**
- * \brief Data for IndexerCallbacks#indexEntityReference.
+ * Roles that are attributed to symbol occurrences.
+ *
+ * Internal: this currently mirrors low 9 bits of clang::index::SymbolRole with
+ * higher bits zeroed. These high bits may be exposed in the future.
+ */
+typedef enum {
+ CXSymbolRole_None = 0,
+ CXSymbolRole_Declaration = 1 << 0,
+ CXSymbolRole_Definition = 1 << 1,
+ CXSymbolRole_Reference = 1 << 2,
+ CXSymbolRole_Read = 1 << 3,
+ CXSymbolRole_Write = 1 << 4,
+ CXSymbolRole_Call = 1 << 5,
+ CXSymbolRole_Dynamic = 1 << 6,
+ CXSymbolRole_AddressOf = 1 << 7,
+ CXSymbolRole_Implicit = 1 << 8
+} CXSymbolRole;
+
+/**
+ * Data for IndexerCallbacks#indexEntityReference.
*/
typedef struct {
CXIdxEntityRefKind kind;
/**
- * \brief Reference cursor.
+ * Reference cursor.
*/
CXCursor cursor;
CXIdxLoc loc;
/**
- * \brief The entity that gets referenced.
+ * The entity that gets referenced.
*/
const CXIdxEntityInfo *referencedEntity;
/**
- * \brief Immediate "parent" of the reference. For example:
- *
+ * Immediate "parent" of the reference. For example:
+ *
* \code
* Foo *var;
* \endcode
- *
+ *
* The parent of reference of type 'Foo' is the variable 'var'.
* For references inside statement bodies of functions/methods,
* the parentEntity will be the function/method.
*/
const CXIdxEntityInfo *parentEntity;
/**
- * \brief Lexical container context of the reference.
+ * Lexical container context of the reference.
*/
const CXIdxContainerInfo *container;
+ /**
+ * Sets of symbol roles of the reference.
+ */
+ CXSymbolRole role;
} CXIdxEntityRefInfo;
/**
- * \brief A group of callbacks used by #clang_indexSourceFile and
+ * A group of callbacks used by #clang_indexSourceFile and
* #clang_indexTranslationUnit.
*/
typedef struct {
/**
- * \brief Called periodically to check whether indexing should be aborted.
+ * Called periodically to check whether indexing should be aborted.
* Should return 0 to continue, and non-zero to abort.
*/
int (*abortQuery)(CXClientData client_data, void *reserved);
/**
- * \brief Called at the end of indexing; passes the complete diagnostic set.
+ * Called at the end of indexing; passes the complete diagnostic set.
*/
void (*diagnostic)(CXClientData client_data,
CXDiagnosticSet, void *reserved);
CXIdxClientFile (*enteredMainFile)(CXClientData client_data,
CXFile mainFile, void *reserved);
-
+
/**
- * \brief Called when a file gets \#included/\#imported.
+ * Called when a file gets \#included/\#imported.
*/
CXIdxClientFile (*ppIncludedFile)(CXClientData client_data,
const CXIdxIncludedFileInfo *);
-
+
/**
- * \brief Called when a AST file (PCH or module) gets imported.
- *
+ * Called when a AST file (PCH or module) gets imported.
+ *
* AST files will not get indexed (there will not be callbacks to index all
* the entities in an AST file). The recommended action is that, if the AST
* file is not already indexed, to initiate a new indexing job specific to
@@ -6075,7 +6313,7 @@ typedef struct {
const CXIdxImportedASTFileInfo *);
/**
- * \brief Called at the beginning of indexing a translation unit.
+ * Called at the beginning of indexing a translation unit.
*/
CXIdxClientContainer (*startedTranslationUnit)(CXClientData client_data,
void *reserved);
@@ -6084,7 +6322,7 @@ typedef struct {
const CXIdxDeclInfo *);
/**
- * \brief Called to index a reference of an entity.
+ * Called to index a reference of an entity.
*/
void (*indexEntityReference)(CXClientData client_data,
const CXIdxEntityRefInfo *);
@@ -6115,39 +6353,39 @@ CINDEX_LINKAGE const CXIdxCXXClassDeclInfo *
clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *);
/**
- * \brief For retrieving a custom CXIdxClientContainer attached to a
+ * For retrieving a custom CXIdxClientContainer attached to a
* container.
*/
CINDEX_LINKAGE CXIdxClientContainer
clang_index_getClientContainer(const CXIdxContainerInfo *);
/**
- * \brief For setting a custom CXIdxClientContainer attached to a
+ * For setting a custom CXIdxClientContainer attached to a
* container.
*/
CINDEX_LINKAGE void
clang_index_setClientContainer(const CXIdxContainerInfo *,CXIdxClientContainer);
/**
- * \brief For retrieving a custom CXIdxClientEntity attached to an entity.
+ * For retrieving a custom CXIdxClientEntity attached to an entity.
*/
CINDEX_LINKAGE CXIdxClientEntity
clang_index_getClientEntity(const CXIdxEntityInfo *);
/**
- * \brief For setting a custom CXIdxClientEntity attached to an entity.
+ * For setting a custom CXIdxClientEntity attached to an entity.
*/
CINDEX_LINKAGE void
clang_index_setClientEntity(const CXIdxEntityInfo *, CXIdxClientEntity);
/**
- * \brief An indexing action/session, to be applied to one or multiple
+ * An indexing action/session, to be applied to one or multiple
* translation units.
*/
typedef void *CXIndexAction;
/**
- * \brief An indexing action/session, to be applied to one or multiple
+ * An indexing action/session, to be applied to one or multiple
* translation units.
*
* \param CIdx The index object with which the index action will be associated.
@@ -6155,7 +6393,7 @@ typedef void *CXIndexAction;
CINDEX_LINKAGE CXIndexAction clang_IndexAction_create(CXIndex CIdx);
/**
- * \brief Destroy the given index action.
+ * Destroy the given index action.
*
* The index action must not be destroyed until all of the translation units
* created within that index action have been destroyed.
@@ -6164,36 +6402,36 @@ CINDEX_LINKAGE void clang_IndexAction_dispose(CXIndexAction);
typedef enum {
/**
- * \brief Used to indicate that no special indexing options are needed.
+ * Used to indicate that no special indexing options are needed.
*/
CXIndexOpt_None = 0x0,
-
+
/**
- * \brief Used to indicate that IndexerCallbacks#indexEntityReference should
+ * Used to indicate that IndexerCallbacks#indexEntityReference should
* be invoked for only one reference of an entity per source file that does
* not also include a declaration/definition of the entity.
*/
CXIndexOpt_SuppressRedundantRefs = 0x1,
/**
- * \brief Function-local symbols should be indexed. If this is not set
+ * Function-local symbols should be indexed. If this is not set
* function-local symbols will be ignored.
*/
CXIndexOpt_IndexFunctionLocalSymbols = 0x2,
/**
- * \brief Implicit function/class template instantiations should be indexed.
+ * Implicit function/class template instantiations should be indexed.
* If this is not set, implicit instantiations will be ignored.
*/
CXIndexOpt_IndexImplicitTemplateInstantiations = 0x4,
/**
- * \brief Suppress all compiler warnings when parsing for indexing.
+ * Suppress all compiler warnings when parsing for indexing.
*/
CXIndexOpt_SuppressWarnings = 0x8,
/**
- * \brief Skip a function/method body that was already parsed during an
+ * Skip a function/method body that was already parsed during an
* indexing session associated with a \c CXIndexAction object.
* Bodies in system headers are always skipped.
*/
@@ -6202,7 +6440,7 @@ typedef enum {
} CXIndexOptFlags;
/**
- * \brief Index the given source file and the translation unit corresponding
+ * Index the given source file and the translation unit corresponding
* to that file via callbacks implemented through #IndexerCallbacks.
*
* \param client_data pointer data supplied by the client, which will
@@ -6240,7 +6478,7 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
unsigned TU_options);
/**
- * \brief Same as clang_indexSourceFile but requires a full command line
+ * Same as clang_indexSourceFile but requires a full command line
* for \c command_line_args including argv[0]. This is useful if the standard
* library paths are relative to the binary.
*/
@@ -6252,18 +6490,18 @@ CINDEX_LINKAGE int clang_indexSourceFileFullArgv(
unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options);
/**
- * \brief Index the given translation unit via callbacks implemented through
+ * Index the given translation unit via callbacks implemented through
* #IndexerCallbacks.
- *
+ *
* The order of callback invocations is not guaranteed to be the same as
* when indexing a source file. The high level order will be:
- *
+ *
* -Preprocessor callbacks invocations
* -Declaration/reference callbacks invocations
* -Diagnostic callback invocations
*
* The parameters are the same as #clang_indexSourceFile.
- *
+ *
* \returns If there is a failure from which there is no recovery, returns
* non-zero, otherwise returns 0.
*/
@@ -6275,7 +6513,7 @@ CINDEX_LINKAGE int clang_indexTranslationUnit(CXIndexAction,
CXTranslationUnit);
/**
- * \brief Retrieve the CXIdxFile, file, line, column, and offset represented by
+ * Retrieve the CXIdxFile, file, line, column, and offset represented by
* the given CXIdxLoc.
*
* If the location refers into a macro expansion, retrieves the
@@ -6290,13 +6528,13 @@ CINDEX_LINKAGE void clang_indexLoc_getFileLocation(CXIdxLoc loc,
unsigned *offset);
/**
- * \brief Retrieve the CXSourceLocation represented by the given CXIdxLoc.
+ * Retrieve the CXSourceLocation represented by the given CXIdxLoc.
*/
CINDEX_LINKAGE
CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc);
/**
- * \brief Visitor invoked for each field found by a traversal.
+ * Visitor invoked for each field found by a traversal.
*
* This visitor function will be invoked for each field found by
* \c clang_Type_visitFields. Its first argument is the cursor being
@@ -6310,7 +6548,7 @@ typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C,
CXClientData client_data);
/**
- * \brief Visit the fields of a particular type.
+ * Visit the fields of a particular type.
*
* This function visits all the direct fields of the given cursor,
* invoking the given \p visitor function with the cursors of each
diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h
index 74081867eebc..30c24f1cdb10 100644
--- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h
+++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h
@@ -22,7 +22,7 @@ namespace clang {
namespace arcmt {
class MigrationPass;
-/// \brief Creates an AST with the provided CompilerInvocation but with these
+/// Creates an AST with the provided CompilerInvocation but with these
/// changes:
/// -if a PCH/PTH is set, the original header is used instead
/// -Automatic Reference Counting mode is enabled
@@ -45,7 +45,7 @@ checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input,
bool emitPremigrationARCErrors = false,
StringRef plistOut = StringRef());
-/// \brief Works similar to checkForManualIssues but instead of checking, it
+/// Works similar to checkForManualIssues but instead of checking, it
/// applies automatic modifications to source files to conform to ARC.
///
/// \returns false if no error is produced, true otherwise.
@@ -55,7 +55,7 @@ applyTransformations(CompilerInvocation &origCI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagClient);
-/// \brief Applies automatic modifications and produces temporary files
+/// Applies automatic modifications and produces temporary files
/// and metadata into the \p outputDir path.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
@@ -72,7 +72,7 @@ bool migrateWithTemporaryFiles(
DiagnosticConsumer *DiagClient, StringRef outputDir,
bool emitPremigrationARCErrors, StringRef plistOut);
-/// \brief Get the set of file remappings from the \p outputDir path that
+/// Get the set of file remappings from the \p outputDir path that
/// migrateWithTemporaryFiles produced.
///
/// \returns false if no error is produced, true otherwise.
@@ -80,7 +80,7 @@ bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
StringRef outputDir,
DiagnosticConsumer *DiagClient);
-/// \brief Get the set of file remappings from a list of files with remapping
+/// Get the set of file remappings from a list of files with remapping
/// info.
///
/// \returns false if no error is produced, true otherwise.
diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h
index 554e0c0c6d02..2571ca75be51 100644
--- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h
+++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h
@@ -55,7 +55,7 @@ public:
bool emitPremigrationARCErrors);
};
-/// \brief Migrates to modern ObjC syntax.
+/// Migrates to modern ObjC syntax.
class ObjCMigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
unsigned ObjCMigAction;
diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h
index 53b88e9eb5e5..731307f24e22 100644
--- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h
+++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h
@@ -41,7 +41,7 @@ class FileRemapper {
public:
FileRemapper();
~FileRemapper();
-
+
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged);
bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/APValue.h b/contrib/llvm/tools/clang/include/clang/AST/APValue.h
index 7c431f3be8c4..d4057c9da5f3 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/APValue.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h
@@ -53,7 +53,58 @@ public:
MemberPointer,
AddrLabelDiff
};
- typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
+
+ class LValueBase {
+ public:
+ typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy;
+
+ LValueBase() : CallIndex(0), Version(0) {}
+
+ template <class T>
+ LValueBase(T P, unsigned I = 0, unsigned V = 0)
+ : Ptr(P), CallIndex(I), Version(V) {}
+
+ template <class T>
+ bool is() const { return Ptr.is<T>(); }
+
+ template <class T>
+ T get() const { return Ptr.get<T>(); }
+
+ template <class T>
+ T dyn_cast() const { return Ptr.dyn_cast<T>(); }
+
+ void *getOpaqueValue() const;
+
+ bool isNull() const;
+
+ explicit operator bool () const;
+
+ PtrTy getPointer() const {
+ return Ptr;
+ }
+
+ unsigned getCallIndex() const {
+ return CallIndex;
+ }
+
+ void setCallIndex(unsigned Index) {
+ CallIndex = Index;
+ }
+
+ unsigned getVersion() const {
+ return Version;
+ }
+
+ bool operator==(const LValueBase &Other) const {
+ return Ptr == Other.Ptr && CallIndex == Other.CallIndex &&
+ Version == Other.Version;
+ }
+
+ private:
+ PtrTy Ptr;
+ unsigned CallIndex, Version;
+ };
+
typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
union LValuePathEntry {
/// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
@@ -135,15 +186,15 @@ public:
}
APValue(const APValue &RHS);
APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
- APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex,
+ APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
bool IsNullPtr = false)
: Kind(Uninitialized) {
- MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr);
+ MakeLValue(); setLValue(B, O, N, IsNullPtr);
}
APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
- bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false)
+ bool OnePastTheEnd, bool IsNullPtr = false)
: Kind(Uninitialized) {
- MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr);
+ MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
}
APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
MakeArray(InitElts, Size);
@@ -168,14 +219,14 @@ public:
MakeUninit();
}
- /// \brief Returns whether the object performed allocations.
+ /// Returns whether the object performed allocations.
///
/// If APValues are constructed via placement new, \c needsCleanup()
/// indicates whether the destructor must be called in order to correctly
/// free all allocated memory.
bool needsCleanup() const;
- /// \brief Swaps the contents of this and the given APValue.
+ /// Swaps the contents of this and the given APValue.
void swap(APValue &RHS);
ValueKind getKind() const { return Kind; }
@@ -255,6 +306,7 @@ public:
bool hasLValuePath() const;
ArrayRef<LValuePathEntry> getLValuePath() const;
unsigned getLValueCallIndex() const;
+ unsigned getLValueVersion() const;
bool isNullPointer() const;
APValue &getVectorElt(unsigned I) {
@@ -376,10 +428,10 @@ public:
((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
}
void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
- unsigned CallIndex, bool IsNullPtr);
+ bool IsNullPtr);
void setLValue(LValueBase B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
- unsigned CallIndex, bool IsNullPtr);
+ bool IsNullPtr);
void setUnion(const FieldDecl *Field, const APValue &Value) {
assert(isUnion() && "Invalid accessor");
((UnionData*)(char*)Data.buffer)->Field = Field;
@@ -451,4 +503,14 @@ private:
} // end namespace clang.
+namespace llvm {
+template<> struct DenseMapInfo<clang::APValue::LValueBase> {
+ static clang::APValue::LValueBase getEmptyKey();
+ static clang::APValue::LValueBase getTombstoneKey();
+ static unsigned getHashValue(const clang::APValue::LValueBase &Base);
+ static bool isEqual(const clang::APValue::LValueBase &LHS,
+ const clang::APValue::LValueBase &RHS);
+};
+}
+
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h
index ad368c86c79c..1167c566a35f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h
@@ -32,7 +32,7 @@ namespace clang {
/// clients that read ASTs. This abstraction layer allows the client to be
/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
class ASTConsumer {
- /// \brief Whether this AST consumer also requires information about
+ /// Whether this AST consumer also requires information about
/// semantic analysis.
bool SemaConsumer;
@@ -53,7 +53,7 @@ public:
/// \returns true to continue parsing, or false to abort parsing.
virtual bool HandleTopLevelDecl(DeclGroupRef D);
- /// \brief This callback is invoked each time an inline (method or friend)
+ /// This callback is invoked each time an inline (method or friend)
/// function definition in a class is completed.
virtual void HandleInlineFunctionDefinition(FunctionDecl *D) {}
@@ -72,22 +72,22 @@ public:
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
- /// \brief This callback is invoked the first time each TagDecl is required to
+ /// This callback is invoked the first time each TagDecl is required to
/// be complete.
virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
- /// \brief Invoked when a function is implicitly instantiated.
+ /// Invoked when a function is implicitly instantiated.
/// Note that at this point point it does not have a body, its body is
/// instantiated at the end of the translation unit and passed to
/// HandleTopLevelDecl.
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
- /// \brief Handle the specified top-level declaration that occurred inside
+ /// Handle the specified top-level declaration that occurred inside
/// and ObjC container.
/// The default implementation ignored them.
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
- /// \brief Handle an ImportDecl that was implicitly created due to an
+ /// Handle an ImportDecl that was implicitly created due to an
/// inclusion directive.
/// The default implementation passes it to HandleTopLevelDecl.
virtual void HandleImplicitImportDecl(ImportDecl *D);
@@ -103,7 +103,7 @@ public:
/// modified by the introduction of an implicit zero initializer.
virtual void CompleteTentativeDefinition(VarDecl *D) {}
- /// \brief Callback invoked when an MSInheritanceAttr has been attached to a
+ /// Callback invoked when an MSInheritanceAttr has been attached to a
/// CXXRecordDecl.
virtual void AssignInheritanceModel(CXXRecordDecl *RD) {}
@@ -111,19 +111,19 @@ public:
// variable has been instantiated.
virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {}
- /// \brief Callback involved at the end of a translation unit to
+ /// Callback involved at the end of a translation unit to
/// notify the consumer that a vtable for the given C++ class is
/// required.
///
/// \param RD The class whose vtable was used.
virtual void HandleVTable(CXXRecordDecl *RD) {}
- /// \brief If the consumer is interested in entities getting modified after
+ /// If the consumer is interested in entities getting modified after
/// their initial creation, it should return a pointer to
/// an ASTMutationListener here.
virtual ASTMutationListener *GetASTMutationListener() { return nullptr; }
- /// \brief If the consumer is interested in entities being deserialized from
+ /// If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
virtual ASTDeserializationListener *GetASTDeserializationListener() {
return nullptr;
@@ -132,7 +132,7 @@ public:
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {}
- /// \brief This callback is called for each function if the Parser was
+ /// This callback is called for each function if the Parser was
/// initialized with \c SkipFunctionBodies set to \c true.
///
/// \return \c true if the function's body should be skipped. The function
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
index a5d080035df0..6eb86183d936 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::ASTContext interface.
+/// Defines the clang::ASTContext interface.
//
//===----------------------------------------------------------------------===//
@@ -18,6 +18,7 @@
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
@@ -144,7 +145,7 @@ struct TypeInfo {
: Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
};
-/// \brief Holds long-lived AST nodes (such as types and decls) that can be
+/// 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> {
friend class NestedNameSpecifier;
@@ -167,6 +168,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<DependentAddressSpaceType>
DependentAddressSpaceTypes;
mutable llvm::FoldingSet<VectorType> VectorTypes;
+ mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes;
mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
FunctionProtoTypes;
@@ -206,13 +208,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
ASTContext&>
SubstTemplateTemplateParmPacks;
- /// \brief The set of nested name specifiers.
+ /// The set of nested name specifiers.
///
/// This set is managed by the NestedNameSpecifier class.
mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr;
- /// \brief A cache mapping from RecordDecls to ASTRecordLayouts.
+ /// A cache mapping from RecordDecls to ASTRecordLayouts.
///
/// This is lazily created. This is intentionally not serialized.
mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>
@@ -220,35 +222,41 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>
ObjCLayouts;
- /// \brief A cache from types to size and alignment information.
+ /// A cache from types to size and alignment information.
using TypeInfoMap = llvm::DenseMap<const Type *, struct TypeInfo>;
mutable TypeInfoMap MemoizedTypeInfo;
- /// \brief A cache mapping from CXXRecordDecls to key functions.
+ /// A cache from types to unadjusted alignment information. Only ARM and
+ /// AArch64 targets need this information, keeping it separate prevents
+ /// imposing overhead on TypeInfo size.
+ using UnadjustedAlignMap = llvm::DenseMap<const Type *, unsigned>;
+ mutable UnadjustedAlignMap MemoizedUnadjustedAlign;
+
+ /// A cache mapping from CXXRecordDecls to key functions.
llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions;
- /// \brief Mapping from ObjCContainers to their ObjCImplementations.
+ /// Mapping from ObjCContainers to their ObjCImplementations.
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
- /// \brief Mapping from ObjCMethod to its duplicate declaration in the same
+ /// Mapping from ObjCMethod to its duplicate declaration in the same
/// interface.
llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls;
- /// \brief Mapping from __block VarDecls to their copy initialization expr.
+ /// Mapping from __block VarDecls to their copy initialization expr.
llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
- /// \brief Mapping from class scope functions specialization to their
+ /// Mapping from class scope functions specialization to their
/// template patterns.
llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
ClassScopeSpecializationPattern;
- /// \brief Mapping from materialized temporaries with static storage duration
+ /// Mapping from materialized temporaries with static storage duration
/// that appear in constant initializers to their evaluated values. These are
/// allocated in a std::map because their address must be stable.
llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
MaterializedTemporaryValues;
- /// \brief Representation of a "canonical" template template parameter that
+ /// Representation of a "canonical" template template parameter that
/// is used in canonical template names.
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
TemplateTemplateParmDecl *Parm;
@@ -270,32 +278,32 @@ class ASTContext : public RefCountedBase<ASTContext> {
TemplateTemplateParmDecl *
getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
- /// \brief The typedef for the __int128_t type.
+ /// The typedef for the __int128_t type.
mutable TypedefDecl *Int128Decl = nullptr;
- /// \brief The typedef for the __uint128_t type.
+ /// The typedef for the __uint128_t type.
mutable TypedefDecl *UInt128Decl = nullptr;
- /// \brief The typedef for the target specific predefined
+ /// The typedef for the target specific predefined
/// __builtin_va_list type.
mutable TypedefDecl *BuiltinVaListDecl = nullptr;
/// The typedef for the predefined \c __builtin_ms_va_list type.
mutable TypedefDecl *BuiltinMSVaListDecl = nullptr;
- /// \brief The typedef for the predefined \c id type.
+ /// The typedef for the predefined \c id type.
mutable TypedefDecl *ObjCIdDecl = nullptr;
- /// \brief The typedef for the predefined \c SEL type.
+ /// The typedef for the predefined \c SEL type.
mutable TypedefDecl *ObjCSelDecl = nullptr;
- /// \brief The typedef for the predefined \c Class type.
+ /// The typedef for the predefined \c Class type.
mutable TypedefDecl *ObjCClassDecl = nullptr;
- /// \brief The typedef for the predefined \c Protocol class in Objective-C.
+ /// The typedef for the predefined \c Protocol class in Objective-C.
mutable ObjCInterfaceDecl *ObjCProtocolClassDecl = nullptr;
- /// \brief The typedef for the predefined 'BOOL' type.
+ /// The typedef for the predefined 'BOOL' type.
mutable TypedefDecl *BOOLDecl = nullptr;
// Typedefs which may be provided defining the structure of Objective-C
@@ -327,53 +335,53 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType ObjCNSStringType;
- /// \brief The typedef declaration for the Objective-C "instancetype" type.
+ /// The typedef declaration for the Objective-C "instancetype" type.
TypedefDecl *ObjCInstanceTypeDecl = nullptr;
- /// \brief The type for the C FILE type.
+ /// The type for the C FILE type.
TypeDecl *FILEDecl = nullptr;
- /// \brief The type for the C jmp_buf type.
+ /// The type for the C jmp_buf type.
TypeDecl *jmp_bufDecl = nullptr;
- /// \brief The type for the C sigjmp_buf type.
+ /// The type for the C sigjmp_buf type.
TypeDecl *sigjmp_bufDecl = nullptr;
- /// \brief The type for the C ucontext_t type.
+ /// The type for the C ucontext_t type.
TypeDecl *ucontext_tDecl = nullptr;
- /// \brief Type for the Block descriptor for Blocks CodeGen.
+ /// 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 = nullptr;
- /// \brief Type for the Block descriptor for Blocks CodeGen.
+ /// 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 = nullptr;
- /// \brief Declaration for the CUDA cudaConfigureCall function.
+ /// Declaration for the CUDA cudaConfigureCall function.
FunctionDecl *cudaConfigureCallDecl = nullptr;
- /// \brief Keeps track of all declaration attributes.
+ /// Keeps track of all declaration attributes.
///
/// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class.
llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
- /// \brief A mapping from non-redeclarable declarations in modules that were
+ /// A mapping from non-redeclarable declarations in modules that were
/// merged with other declarations to the canonical declaration that they were
/// merged into.
llvm::DenseMap<Decl*, Decl*> MergedDecls;
- /// \brief A mapping from a defining declaration to a list of modules (other
+ /// A mapping from a defining declaration to a list of modules (other
/// than the owning module of the declaration) that contain merged
/// definitions of that entity.
llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules;
- /// \brief Initializers for a module, in order. Each Decl will be either
+ /// Initializers for a module, in order. Each Decl will be either
/// something that has a semantic effect on startup (such as a variable with
/// a non-constant initializer), or an ImportDecl (which recursively triggers
/// initialization of another module).
@@ -388,7 +396,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ASTContext &this_() { return *this; }
public:
- /// \brief A type synonym for the TemplateOrInstantiation mapping.
+ /// A type synonym for the TemplateOrInstantiation mapping.
using TemplateOrSpecializationInfo =
llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>;
@@ -398,7 +406,7 @@ private:
friend class ASTWriter;
friend class CXXRecordDecl;
- /// \brief A mapping to contain the template or declaration that
+ /// A mapping to contain the template or declaration that
/// a variable declaration describes or was instantiated from,
/// respectively.
///
@@ -431,7 +439,7 @@ private:
llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>
TemplateOrInstantiation;
- /// \brief Keeps track of the declaration from which a using declaration was
+ /// Keeps track of the declaration from which a using declaration was
/// created during instantiation.
///
/// The source and target declarations are always a UsingDecl, an
@@ -461,7 +469,7 @@ private:
llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
- /// \brief Mapping that stores the methods overridden by a given C++
+ /// Mapping that stores the methods overridden by a given C++
/// member function.
///
/// Since most C++ member functions aren't virtual and therefore
@@ -470,18 +478,18 @@ private:
using CXXMethodVector = llvm::TinyPtrVector<const CXXMethodDecl *>;
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
- /// \brief Mapping from each declaration context to its corresponding
+ /// Mapping from each declaration context to its corresponding
/// mangling numbering context (used for constructs like lambdas which
/// need to be consistently numbered for the mangler).
llvm::DenseMap<const DeclContext *, std::unique_ptr<MangleNumberingContext>>
MangleNumberingContexts;
- /// \brief Side-table of mangling numbers for declarations which rarely
+ /// Side-table of mangling numbers for declarations which rarely
/// need them (like static local vars).
llvm::MapVector<const NamedDecl *, unsigned> MangleNumbers;
llvm::MapVector<const VarDecl *, unsigned> StaticLocalNumbers;
- /// \brief Mapping that stores parameterIndex values for ParmVarDecls when
+ /// Mapping that stores parameterIndex values for ParmVarDecls when
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
using ParameterIndexTable = llvm::DenseMap<const VarDecl *, unsigned>;
ParameterIndexTable ParamIndices;
@@ -494,38 +502,38 @@ private:
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
- /// \brief The associated SourceManager object.
+ /// The associated SourceManager object.
SourceManager &SourceMgr;
- /// \brief The language options used to create the AST associated with
+ /// The language options used to create the AST associated with
/// this ASTContext object.
LangOptions &LangOpts;
- /// \brief Blacklist object that is used by sanitizers to decide which
+ /// Blacklist object that is used by sanitizers to decide which
/// entities should not be instrumented.
std::unique_ptr<SanitizerBlacklist> SanitizerBL;
- /// \brief Function filtering mechanism to determine whether a given function
+ /// Function filtering mechanism to determine whether a given function
/// should be imbued with the XRay "always" or "never" attributes.
std::unique_ptr<XRayFunctionFilter> XRayFilter;
- /// \brief The allocator used to create AST objects.
+ /// The allocator used to create AST objects.
///
/// AST objects are never destructed; rather, all memory associated with the
/// AST objects will be released when the ASTContext itself is destroyed.
mutable llvm::BumpPtrAllocator BumpAlloc;
- /// \brief Allocator for partial diagnostics.
+ /// Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
- /// \brief The current C++ ABI.
+ /// The current C++ ABI.
std::unique_ptr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
- /// \brief The logical -> physical address space map.
+ /// The logical -> physical address space map.
const LangASMap *AddrSpaceMap = nullptr;
- /// \brief Address space map mangling must be used with language specific
+ /// Address space map mangling must be used with language specific
/// address spaces (e.g. OpenCL/CUDA)
bool AddrSpaceMapMangling;
@@ -541,10 +549,10 @@ public:
IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
ASTMutationListener *Listener = nullptr;
- /// \brief Contains parents of a node.
+ /// Contains parents of a node.
using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>;
- /// \brief Maps from a node to its parents. This is used for nodes that have
+ /// 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.
using ParentMapPointers =
@@ -602,7 +610,7 @@ public:
}
};
- /// \brief Returns the parents of the given node.
+ /// Returns the parents of the given node.
///
/// Note that this will lazily compute the parents of all nodes
/// and store them for later retrieval. Thus, the first call is O(n)
@@ -701,10 +709,10 @@ public:
return FullSourceLoc(Loc,SourceMgr);
}
- /// \brief All comments in this translation unit.
+ /// All comments in this translation unit.
RawCommentList Comments;
- /// \brief True if comments are already loaded from ExternalASTSource.
+ /// True if comments are already loaded from ExternalASTSource.
mutable bool CommentsLoaded = false;
class RawCommentAndCacheFlags {
@@ -761,18 +769,18 @@ public:
const Decl *OriginalDecl;
};
- /// \brief Mapping from declarations to comments attached to any
+ /// Mapping from declarations to comments attached to any
/// redeclaration.
///
/// Raw comments are owned by Comments list. This mapping is populated
/// lazily.
mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
- /// \brief Mapping from declarations to parsed comments attached to any
+ /// Mapping from declarations to parsed comments attached to any
/// redeclaration.
mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments;
- /// \brief Return the documentation comment attached to a given declaration,
+ /// Return the documentation comment attached to a given declaration,
/// without looking into cache.
RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
@@ -784,10 +792,10 @@ public:
void addComment(const RawComment &RC) {
assert(LangOpts.RetainCommentsFromSystemHeaders ||
!SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin()));
- Comments.addComment(RC, BumpAlloc);
+ Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc);
}
- /// \brief Return the documentation comment attached to a given declaration.
+ /// Return the documentation comment attached to a given declaration.
/// Returns nullptr if no comment is attached.
///
/// \param OriginalDecl if not nullptr, is set to declaration AST node that
@@ -815,7 +823,7 @@ public:
private:
mutable comments::CommandTraits CommentCommandTraits;
- /// \brief Iterator that visits import declarations.
+ /// Iterator that visits import declarations.
class import_iterator {
ImportDecl *Import = nullptr;
@@ -857,13 +865,13 @@ public:
return CommentCommandTraits;
}
- /// \brief Retrieve the attributes for the given declaration.
+ /// Retrieve the attributes for the given declaration.
AttrVec& getDeclAttrs(const Decl *D);
- /// \brief Erase the attributes corresponding to the given declaration.
+ /// Erase the attributes corresponding to the given declaration.
void eraseDeclAttrs(const Decl *D);
- /// \brief If this variable is an instantiated static data member of a
+ /// If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
// FIXME: Remove ?
@@ -878,7 +886,7 @@ public:
void setClassScopeSpecializationPattern(FunctionDecl *FD,
FunctionDecl *Pattern);
- /// \brief Note that the static data member \p Inst is an instantiation of
+ /// Note that the static data member \p Inst is an instantiation of
/// the static data member template \p Tmpl of a class template.
void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
TemplateSpecializationKind TSK,
@@ -887,12 +895,12 @@ public:
void setTemplateOrSpecializationInfo(VarDecl *Inst,
TemplateOrSpecializationInfo TSI);
- /// \brief If the given using decl \p Inst is an instantiation of a
+ /// If the given using decl \p Inst is an instantiation of a
/// (possibly unresolved) using decl from a template instantiation,
/// return it.
NamedDecl *getInstantiatedFromUsingDecl(NamedDecl *Inst);
- /// \brief Remember that the using decl \p Inst is an instantiation
+ /// Remember that the using decl \p Inst is an instantiation
/// of the using decl \p Pattern of a class template.
void setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern);
@@ -919,12 +927,12 @@ public:
overridden_method_range overridden_methods(const CXXMethodDecl *Method) const;
- /// \brief Note that the given C++ \p Method overrides the given \p
+ /// Note that the given C++ \p Method overrides the given \p
/// Overridden method.
void addOverriddenMethod(const CXXMethodDecl *Method,
const CXXMethodDecl *Overridden);
- /// \brief Return C++ or ObjC overridden methods for the given \p Method.
+ /// Return C++ or ObjC overridden methods for the given \p Method.
///
/// An ObjC method is considered to override any method in the class's
/// base classes, its protocols, or its categories' protocols, that has
@@ -935,7 +943,7 @@ public:
const NamedDecl *Method,
SmallVectorImpl<const NamedDecl *> &Overridden) const;
- /// \brief Notify the AST context that a new import declaration has been
+ /// Notify the AST context that a new import declaration has been
/// parsed or implicitly created within this translation unit.
void addedLocalImportDecl(ImportDecl *Import);
@@ -957,16 +965,16 @@ public:
MergedDecls[D] = Primary;
}
- /// \brief Note that the definition \p ND has been merged into module \p M,
+ /// Note that the definition \p ND has been merged into module \p M,
/// and should be visible whenever \p M is visible.
void mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
bool NotifyListeners = true);
- /// \brief Clean up the merged definition list. Call this if you might have
+ /// Clean up the merged definition list. Call this if you might have
/// added duplicates into the list.
void deduplicateMergedDefinitonsFor(NamedDecl *ND);
- /// \brief Get the additional modules in which the definition \p Def has
+ /// Get the additional modules in which the definition \p Def has
/// been merged.
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) {
auto MergedIt = MergedDefModules.find(Def);
@@ -999,12 +1007,24 @@ public:
CanQualType WCharTy; // [C++ 3.9.1p5].
CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99.
CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions.
+ CanQualType Char8Ty; // [C++20 proposal]
CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
+ CanQualType ShortAccumTy, AccumTy,
+ LongAccumTy; // ISO/IEC JTC1 SC22 WG14 N1169 Extension
+ CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy;
+ CanQualType ShortFractTy, FractTy, LongFractTy;
+ CanQualType UnsignedShortFractTy, UnsignedFractTy, UnsignedLongFractTy;
+ CanQualType SatShortAccumTy, SatAccumTy, SatLongAccumTy;
+ CanQualType SatUnsignedShortAccumTy, SatUnsignedAccumTy,
+ SatUnsignedLongAccumTy;
+ CanQualType SatShortFractTy, SatFractTy, SatLongFractTy;
+ CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy,
+ SatUnsignedLongFractTy;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
@@ -1036,20 +1056,20 @@ public:
ASTContext &operator=(const ASTContext &) = delete;
~ASTContext();
- /// \brief Attach an external AST source to the AST context.
+ /// Attach an external AST source to the AST context.
///
/// The external AST source provides the ability to load parts of
/// the abstract syntax tree as needed from some external storage,
/// e.g., a precompiled header.
void setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source);
- /// \brief Retrieve a pointer to the external AST source associated
+ /// Retrieve a pointer to the external AST source associated
/// with this AST context, if any.
ExternalASTSource *getExternalSource() const {
return ExternalSource.get();
}
- /// \brief Attach an AST mutation listener to the AST context.
+ /// Attach an AST mutation listener to the AST context.
///
/// The AST mutation listener provides the ability to track modifications to
/// the abstract syntax tree entities committed after they were initially
@@ -1058,7 +1078,7 @@ public:
this->Listener = Listener;
}
- /// \brief Retrieve a pointer to the AST mutation listener associated
+ /// Retrieve a pointer to the AST mutation listener associated
/// with this AST context, if any.
ASTMutationListener *getASTMutationListener() const { return Listener; }
@@ -1068,18 +1088,18 @@ public:
BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
const IdentifierInfo *II) const;
- /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
+ /// Create a new implicit TU-level CXXRecordDecl or RecordDecl
/// declaration.
RecordDecl *buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK = TTK_Struct) const;
- /// \brief Create a new implicit TU-level typedef declaration.
+ /// Create a new implicit TU-level typedef declaration.
TypedefDecl *buildImplicitTypedef(QualType T, StringRef Name) const;
- /// \brief Retrieve the declaration for the 128-bit signed integer type.
+ /// Retrieve the declaration for the 128-bit signed integer type.
TypedefDecl *getInt128Decl() const;
- /// \brief Retrieve the declaration for the 128-bit unsigned integer type.
+ /// Retrieve the declaration for the 128-bit unsigned integer type.
TypedefDecl *getUInt128Decl() const;
//===--------------------------------------------------------------------===//
@@ -1087,7 +1107,7 @@ public:
//===--------------------------------------------------------------------===//
private:
- /// \brief Return a type with extended qualifiers.
+ /// Return a type with extended qualifiers.
QualType getExtQualType(const Type *Base, Qualifiers Quals) const;
QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
@@ -1095,7 +1115,7 @@ private:
QualType getPipeType(QualType T, bool ReadOnly) const;
public:
- /// \brief Return the uniqued reference to the type for an address space
+ /// Return the uniqued reference to the type for an address space
/// qualified type with the specified type and address space.
///
/// The resulting type has a union of the qualifiers from T and the address
@@ -1103,29 +1123,29 @@ public:
/// replaced.
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const;
- /// \brief Remove any existing address space on the type and returns the type
+ /// 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.
+ /// Apply Objective-C protocol qualifiers to the given type.
/// \param allowOnPointerType specifies if we can apply protocol
/// qualifiers on ObjCObjectPointerType. It can be set to true when
- /// contructing the canonical type of a Objective-C type parameter.
+ /// constructing the canonical type of a Objective-C type parameter.
QualType applyObjCProtocolQualifiers(QualType type,
ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError,
bool allowOnPointerType = false) const;
- /// \brief Return the uniqued reference to the type for an Objective-C
+ /// Return the uniqued reference to the type for an Objective-C
/// gc-qualified type.
///
- /// The retulting type has a union of the qualifiers from T and the gc
+ /// The resulting type has a union of the qualifiers from T and the gc
/// attribute.
QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const;
- /// \brief Return the uniqued reference to the type for a \c restrict
+ /// Return the uniqued reference to the type for a \c restrict
/// qualified type.
///
/// The resulting type has a union of the qualifiers from \p T and
@@ -1134,7 +1154,7 @@ public:
return T.withFastQualifiers(Qualifiers::Restrict);
}
- /// \brief Return the uniqued reference to the type for a \c volatile
+ /// Return the uniqued reference to the type for a \c volatile
/// qualified type.
///
/// The resulting type has a union of the qualifiers from \p T and
@@ -1143,7 +1163,7 @@ public:
return T.withFastQualifiers(Qualifiers::Volatile);
}
- /// \brief Return the uniqued reference to the type for a \c const
+ /// Return the uniqued reference to the type for a \c const
/// qualified type.
///
/// The resulting type has a union of the qualifiers from \p T and \c const.
@@ -1152,41 +1172,48 @@ public:
/// calling T.withConst().
QualType getConstType(QualType T) const { return T.withConst(); }
- /// \brief Change the ExtInfo on a function type.
+ /// Change the ExtInfo on a function type.
const FunctionType *adjustFunctionType(const FunctionType *Fn,
FunctionType::ExtInfo EInfo);
/// Adjust the given function result type.
CanQualType getCanonicalFunctionResultType(QualType ResultType) const;
- /// \brief Change the result type of a function type once it is deduced.
+ /// Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
- /// \brief Determine whether two function types are the same, ignoring
+ /// Get a function type and produce the equivalent function type with the
+ /// specified exception specification. Type sugar that can be present on a
+ /// declaration of a function with an exception specification is permitted
+ /// and preserved. Other type sugar (for instance, typedefs) is not.
+ QualType getFunctionTypeWithExceptionSpec(
+ QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI);
+
+ /// Determine whether two function types are the same, ignoring
/// exception specifications in cases where they're part of the type.
bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U);
- /// \brief Change the exception specification on a function once it is
+ /// Change the exception specification on a function once it is
/// delay-parsed, instantiated, or computed.
void adjustExceptionSpec(FunctionDecl *FD,
const FunctionProtoType::ExceptionSpecInfo &ESI,
bool AsWritten = false);
- /// \brief Return the uniqued reference to the type for a complex
+ /// Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T) const;
CanQualType getComplexType(CanQualType T) const {
return CanQualType::CreateUnsafe(getComplexType((QualType) T));
}
- /// \brief Return the uniqued reference to the type for a pointer to
+ /// Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType getPointerType(QualType T) const;
CanQualType getPointerType(CanQualType T) const {
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
- /// \brief Return the uniqued reference to a type adjusted from the original
+ /// Return the uniqued reference to a type adjusted from the original
/// type to a new type.
QualType getAdjustedType(QualType Orig, QualType New) const;
CanQualType getAdjustedType(CanQualType Orig, CanQualType New) const {
@@ -1194,7 +1221,7 @@ public:
getAdjustedType((QualType)Orig, (QualType)New));
}
- /// \brief Return the uniqued reference to the decayed version of the given
+ /// Return the uniqued reference to the decayed version of the given
/// type. Can only be called on array and function types which decay to
/// pointer types.
QualType getDecayedType(QualType T) const;
@@ -1202,11 +1229,11 @@ public:
return CanQualType::CreateUnsafe(getDecayedType((QualType) T));
}
- /// \brief Return the uniqued reference to the atomic type for the specified
+ /// Return the uniqued reference to the atomic type for the specified
/// type.
QualType getAtomicType(QualType T) const;
- /// \brief Return the uniqued reference to the type for a block of the
+ /// Return the uniqued reference to the type for a block of the
/// specified type.
QualType getBlockPointerType(QualType T) const;
@@ -1214,10 +1241,10 @@ public:
/// blocks.
QualType getBlockDescriptorType() const;
- /// \brief Return a read_only pipe type for the specified type.
+ /// 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.
+ /// Return a write_only pipe type for the specified type.
QualType getWritePipeType(QualType T) const;
/// Gets the struct used to keep track of the extended descriptor for
@@ -1241,36 +1268,36 @@ 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.
+ /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout
+ /// is set to false in this case. If HasByrefExtendedLayout returns true,
+ /// byref variable has extended lifetime.
bool getByrefLifetime(QualType Ty,
Qualifiers::ObjCLifetime &Lifetime,
bool &HasByrefExtendedLayout) const;
- /// \brief Return the uniqued reference to the type for an lvalue reference
+ /// Return the uniqued reference to the type for an lvalue reference
/// to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true)
const;
- /// \brief Return the uniqued reference to the type for an rvalue reference
+ /// Return the uniqued reference to the type for an rvalue reference
/// to the specified type.
QualType getRValueReferenceType(QualType T) const;
- /// \brief Return the uniqued reference to the type for a member pointer to
+ /// Return the uniqued reference to the type for a member pointer to
/// the specified type in the specified class.
///
/// The class \p Cls is a \c Type because it could be a dependent name.
QualType getMemberPointerType(QualType T, const Type *Cls) const;
- /// \brief Return a non-unique reference to the type for a variable array of
+ /// Return a non-unique reference to the type for a variable array of
/// the specified element type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals,
SourceRange Brackets) const;
- /// \brief Return a non-unique reference to the type for a dependently-sized
+ /// Return a non-unique reference to the type for a dependently-sized
/// array of the specified element type.
///
/// FIXME: We will need these to be uniqued, or at least comparable, at some
@@ -1280,29 +1307,34 @@ public:
unsigned IndexTypeQuals,
SourceRange Brackets) const;
- /// \brief Return a unique reference to the type for an incomplete array of
+ /// Return a unique reference to the type for an incomplete array of
/// the specified element type.
QualType getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals) const;
- /// \brief Return the unique reference to the type for a constant array of
+ /// Return the unique reference to the type for a constant array of
/// the specified element type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals) const;
- /// \brief Returns a vla type where known sizes are replaced with [*].
+ /// Returns a vla type where known sizes are replaced with [*].
QualType getVariableArrayDecayedType(QualType Ty) const;
- /// \brief Return the unique reference to a vector type of the specified
+ /// Return the unique reference to a vector type of the specified
/// element type and size.
///
/// \pre \p VectorType must be a built-in type.
QualType getVectorType(QualType VectorType, unsigned NumElts,
VectorType::VectorKind VecKind) const;
+ /// Return the unique reference to the type for a dependently sized vector of
+ /// the specified element type.
+ QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr,
+ SourceLocation AttrLoc,
+ VectorType::VectorKind VecKind) const;
- /// \brief Return the unique reference to an extended vector type
+ /// Return the unique reference to an extended vector type
/// of the specified element type and size.
///
/// \pre \p VectorType must be a built-in type.
@@ -1321,7 +1353,7 @@ public:
Expr *AddrSpaceExpr,
SourceLocation AttrLoc) const;
- /// \brief Return a K&R style C function type like 'int()'.
+ /// Return a K&R style C function type like 'int()'.
QualType getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info) const;
@@ -1329,20 +1361,22 @@ public:
return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo());
}
- /// \brief Return a normal function type with a typed argument list.
+ /// Return a normal function type with a typed argument list.
QualType getFunctionType(QualType ResultTy, ArrayRef<QualType> Args,
const FunctionProtoType::ExtProtoInfo &EPI) const {
return getFunctionTypeInternal(ResultTy, Args, EPI, false);
}
+ QualType adjustStringLiteralBaseType(QualType StrLTy) const;
+
private:
- /// \brief Return a normal function type with a typed argument list.
+ /// Return a normal function type with a typed argument list.
QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args,
const FunctionProtoType::ExtProtoInfo &EPI,
bool OnlyWantCanonical) const;
public:
- /// \brief Return the unique reference to the type for the specified type
+ /// Return the unique reference to the type for the specified type
/// declaration.
QualType getTypeDeclType(const TypeDecl *Decl,
const TypeDecl *PrevDecl = nullptr) const {
@@ -1358,7 +1392,7 @@ public:
return getTypeDeclTypeSlow(Decl);
}
- /// \brief Return the unique reference to the type for the specified
+ /// Return the unique reference to the type for the specified
/// typedef-name decl.
QualType getTypedefType(const TypedefNameDecl *Decl,
QualType Canon = QualType()) const;
@@ -1404,8 +1438,8 @@ public:
QualType getParenType(QualType NamedType) const;
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
- QualType NamedType) const;
+ NestedNameSpecifier *NNS, QualType NamedType,
+ TagDecl *OwnedTagDecl = nullptr) const;
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
@@ -1455,105 +1489,105 @@ public:
bool QIdProtocolsAdoptObjCObjectProtocols(QualType QT,
ObjCInterfaceDecl *IDecl);
- /// \brief Return a ObjCObjectPointerType type for the given ObjCObjectType.
+ /// Return a ObjCObjectPointerType type for the given ObjCObjectType.
QualType getObjCObjectPointerType(QualType OIT) const;
- /// \brief GCC extension.
+ /// GCC extension.
QualType getTypeOfExprType(Expr *e) const;
QualType getTypeOfType(QualType t) const;
- /// \brief C++11 decltype.
+ /// C++11 decltype.
QualType getDecltypeType(Expr *e, QualType UnderlyingType) const;
- /// \brief Unary type transforms
+ /// Unary type transforms
QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
UnaryTransformType::UTTKind UKind) const;
- /// \brief C++11 deduced auto type.
+ /// C++11 deduced auto type.
QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent) const;
- /// \brief C++11 deduction pattern for 'auto' type.
+ /// C++11 deduction pattern for 'auto' type.
QualType getAutoDeductType() const;
- /// \brief C++11 deduction pattern for 'auto &&' type.
+ /// C++11 deduction pattern for 'auto &&' type.
QualType getAutoRRefDeductType() const;
- /// \brief C++17 deduced class template specialization type.
+ /// C++17 deduced class template specialization type.
QualType getDeducedTemplateSpecializationType(TemplateName Template,
QualType DeducedType,
bool IsDependent) const;
- /// \brief Return the unique reference to the type for the specified TagDecl
+ /// Return the unique reference to the type for the specified TagDecl
/// (struct/union/class/enum) decl.
QualType getTagDeclType(const TagDecl *Decl) const;
- /// \brief Return the unique type for "size_t" (C99 7.17), defined in
+ /// Return the unique type for "size_t" (C99 7.17), defined in
/// <stddef.h>.
///
/// The sizeof operator requires this (C99 6.5.3.4p4).
CanQualType getSizeType() const;
- /// \brief Return the unique signed counterpart of
+ /// Return the unique signed counterpart of
/// the integer type corresponding to size_t.
CanQualType getSignedSizeType() const;
- /// \brief Return the unique type for "intmax_t" (C99 7.18.1.5), defined in
+ /// Return the unique type for "intmax_t" (C99 7.18.1.5), defined in
/// <stdint.h>.
CanQualType getIntMaxType() const;
- /// \brief Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in
+ /// Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in
/// <stdint.h>.
CanQualType getUIntMaxType() const;
- /// \brief Return the unique wchar_t type available in C++ (and available as
+ /// Return the unique wchar_t type available in C++ (and available as
/// __wchar_t as a Microsoft extension).
QualType getWCharType() const { return WCharTy; }
- /// \brief Return the type of wide characters. In C++, this returns the
+ /// Return the type of wide characters. In C++, this returns the
/// unique wchar_t type. In C99, this returns a type compatible with the type
/// defined in <stddef.h> as defined by the target.
QualType getWideCharType() const { return WideCharTy; }
- /// \brief Return the type of "signed wchar_t".
+ /// Return the type of "signed wchar_t".
///
/// Used when in C++, as a GCC extension.
QualType getSignedWCharType() const;
- /// \brief Return the type of "unsigned wchar_t".
+ /// Return the type of "unsigned wchar_t".
///
/// Used when in C++, as a GCC extension.
QualType getUnsignedWCharType() const;
- /// \brief In C99, this returns a type compatible with the type
+ /// In C99, this returns a type compatible with the type
/// defined in <stddef.h> as defined by the target.
QualType getWIntType() const { return WIntTy; }
- /// \brief Return a type compatible with "intptr_t" (C99 7.18.1.4),
+ /// Return a type compatible with "intptr_t" (C99 7.18.1.4),
/// as defined by the target.
QualType getIntPtrType() const;
- /// \brief Return a type compatible with "uintptr_t" (C99 7.18.1.4),
+ /// Return a type compatible with "uintptr_t" (C99 7.18.1.4),
/// as defined by the target.
QualType getUIntPtrType() const;
- /// \brief Return the unique type for "ptrdiff_t" (C99 7.17) defined in
+ /// Return the unique type for "ptrdiff_t" (C99 7.17) defined in
/// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType getPointerDiffType() const;
- /// \brief Return the unique unsigned counterpart of "ptrdiff_t"
+ /// 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
+ /// Return the unique type for "pid_t" defined in
/// <sys/types.h>. We need this to compute the correct type for vfork().
QualType getProcessIDType() const;
- /// \brief Return the C structure type used to represent constant CFStrings.
+ /// Return the C structure type used to represent constant CFStrings.
QualType getCFConstantStringType() const;
- /// \brief Returns the C struct type for objc_super
+ /// Returns the C struct type for objc_super
QualType getObjCSuperType() const;
void setObjCSuperType(QualType ST) { ObjCSuperType = ST; }
@@ -1582,7 +1616,7 @@ public:
ObjCNSStringType = T;
}
- /// \brief Retrieve the type that \c id has been defined to, which may be
+ /// Retrieve the type that \c id has been defined to, which may be
/// different from the built-in \c id if \c id has been typedef'd.
QualType getObjCIdRedefinitionType() const {
if (ObjCIdRedefinitionType.isNull())
@@ -1590,12 +1624,12 @@ public:
return ObjCIdRedefinitionType;
}
- /// \brief Set the user-written type that redefines \c id.
+ /// Set the user-written type that redefines \c id.
void setObjCIdRedefinitionType(QualType RedefType) {
ObjCIdRedefinitionType = RedefType;
}
- /// \brief Retrieve the type that \c Class has been defined to, which may be
+ /// Retrieve the type that \c Class has been defined to, which may be
/// different from the built-in \c Class if \c Class has been typedef'd.
QualType getObjCClassRedefinitionType() const {
if (ObjCClassRedefinitionType.isNull())
@@ -1603,12 +1637,12 @@ public:
return ObjCClassRedefinitionType;
}
- /// \brief Set the user-written type that redefines 'SEL'.
+ /// Set the user-written type that redefines 'SEL'.
void setObjCClassRedefinitionType(QualType RedefType) {
ObjCClassRedefinitionType = RedefType;
}
- /// \brief Retrieve the type that 'SEL' has been defined to, which may be
+ /// Retrieve the type that 'SEL' has been defined to, which may be
/// different from the built-in 'SEL' if 'SEL' has been typedef'd.
QualType getObjCSelRedefinitionType() const {
if (ObjCSelRedefinitionType.isNull())
@@ -1616,7 +1650,7 @@ public:
return ObjCSelRedefinitionType;
}
- /// \brief Set the user-written type that redefines 'SEL'.
+ /// Set the user-written type that redefines 'SEL'.
void setObjCSelRedefinitionType(QualType RedefType) {
ObjCSelRedefinitionType = RedefType;
}
@@ -1676,68 +1710,68 @@ public:
return TypePackElementName;
}
- /// \brief Retrieve the Objective-C "instancetype" type, if already known;
+ /// Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
return getTypeDeclType(getObjCInstanceTypeDecl());
}
- /// \brief Retrieve the typedef declaration corresponding to the Objective-C
+ /// Retrieve the typedef declaration corresponding to the Objective-C
/// "instancetype" type.
TypedefDecl *getObjCInstanceTypeDecl();
- /// \brief Set the type for the C FILE type.
+ /// Set the type for the C FILE type.
void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; }
- /// \brief Retrieve the C FILE type.
+ /// Retrieve the C FILE type.
QualType getFILEType() const {
if (FILEDecl)
return getTypeDeclType(FILEDecl);
return QualType();
}
- /// \brief Set the type for the C jmp_buf type.
+ /// Set the type for the C jmp_buf type.
void setjmp_bufDecl(TypeDecl *jmp_bufDecl) {
this->jmp_bufDecl = jmp_bufDecl;
}
- /// \brief Retrieve the C jmp_buf type.
+ /// Retrieve the C jmp_buf type.
QualType getjmp_bufType() const {
if (jmp_bufDecl)
return getTypeDeclType(jmp_bufDecl);
return QualType();
}
- /// \brief Set the type for the C sigjmp_buf type.
+ /// Set the type for the C sigjmp_buf type.
void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) {
this->sigjmp_bufDecl = sigjmp_bufDecl;
}
- /// \brief Retrieve the C sigjmp_buf type.
+ /// Retrieve the C sigjmp_buf type.
QualType getsigjmp_bufType() const {
if (sigjmp_bufDecl)
return getTypeDeclType(sigjmp_bufDecl);
return QualType();
}
- /// \brief Set the type for the C ucontext_t type.
+ /// Set the type for the C ucontext_t type.
void setucontext_tDecl(TypeDecl *ucontext_tDecl) {
this->ucontext_tDecl = ucontext_tDecl;
}
- /// \brief Retrieve the C ucontext_t type.
+ /// Retrieve the C ucontext_t type.
QualType getucontext_tType() const {
if (ucontext_tDecl)
return getTypeDeclType(ucontext_tDecl);
return QualType();
}
- /// \brief The result type of logical operations, '<', '>', '!=', etc.
+ /// The result type of logical operations, '<', '>', '!=', etc.
QualType getLogicalOperationType() const {
return getLangOpts().CPlusPlus ? BoolTy : IntTy;
}
- /// \brief Emit the Objective-CC type encoding for the given type \p T into
+ /// Emit the Objective-CC type encoding for the given type \p T into
/// \p S.
///
/// If \p Field is specified then record field names are also encoded.
@@ -1745,17 +1779,17 @@ public:
const FieldDecl *Field=nullptr,
QualType *NotEncodedT=nullptr) const;
- /// \brief Emit the Objective-C property type encoding for the given
+ /// Emit the Objective-C property type encoding for the given
/// type \p T into \p S.
void getObjCEncodingForPropertyType(QualType T, std::string &S) const;
void getLegacyIntegralTypeEncoding(QualType &t) const;
- /// \brief Put the string version of the type qualifiers \p QT into \p S.
+ /// Put the string version of the type qualifiers \p QT into \p S.
void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
std::string &S) const;
- /// \brief Emit the encoded type for the function \p Decl into \p S.
+ /// Emit the encoded type for the function \p Decl into \p S.
///
/// This is in the same format as Objective-C method encodings.
///
@@ -1763,12 +1797,12 @@ public:
/// types is incomplete), false otherwise.
std::string getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const;
- /// \brief Emit the encoded type for the method declaration \p Decl into
+ /// Emit the encoded type for the method declaration \p Decl into
/// \p S.
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
bool Extended = false) const;
- /// \brief Return the encoded type for this block declaration.
+ /// Return the encoded type for this block declaration.
std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const;
/// getObjCEncodingForPropertyDecl - Return the encoded type for
@@ -1785,15 +1819,15 @@ public:
const ObjCPropertyDecl *PD,
const Decl *Container) const;
- /// \brief Return the size of type \p T for Objective-C encoding purpose,
+ /// Return the size of type \p T for Objective-C encoding purpose,
/// in characters.
CharUnits getObjCEncodingTypeSize(QualType T) const;
- /// \brief Retrieve the typedef corresponding to the predefined \c id type
+ /// Retrieve the typedef corresponding to the predefined \c id type
/// in Objective-C.
TypedefDecl *getObjCIdDecl() const;
- /// \brief Represents the Objective-CC \c id type.
+ /// Represents the Objective-CC \c id type.
///
/// This is set up lazily, by Sema. \c id is always a (typedef for a)
/// pointer type, a pointer to a struct.
@@ -1801,21 +1835,21 @@ public:
return getTypeDeclType(getObjCIdDecl());
}
- /// \brief Retrieve the typedef corresponding to the predefined 'SEL' type
+ /// Retrieve the typedef corresponding to the predefined 'SEL' type
/// in Objective-C.
TypedefDecl *getObjCSelDecl() const;
- /// \brief Retrieve the type that corresponds to the predefined Objective-C
+ /// Retrieve the type that corresponds to the predefined Objective-C
/// 'SEL' type.
QualType getObjCSelType() const {
return getTypeDeclType(getObjCSelDecl());
}
- /// \brief Retrieve the typedef declaration corresponding to the predefined
+ /// Retrieve the typedef declaration corresponding to the predefined
/// Objective-C 'Class' type.
TypedefDecl *getObjCClassDecl() const;
- /// \brief Represents the Objective-C \c Class type.
+ /// Represents the Objective-C \c Class type.
///
/// This is set up lazily, by Sema. \c Class is always a (typedef for a)
/// pointer type, a pointer to a struct.
@@ -1823,40 +1857,40 @@ public:
return getTypeDeclType(getObjCClassDecl());
}
- /// \brief Retrieve the Objective-C class declaration corresponding to
+ /// Retrieve the Objective-C class declaration corresponding to
/// the predefined \c Protocol class.
ObjCInterfaceDecl *getObjCProtocolDecl() const;
- /// \brief Retrieve declaration of 'BOOL' typedef
+ /// Retrieve declaration of 'BOOL' typedef
TypedefDecl *getBOOLDecl() const {
return BOOLDecl;
}
- /// \brief Save declaration of 'BOOL' typedef
+ /// Save declaration of 'BOOL' typedef
void setBOOLDecl(TypedefDecl *TD) {
BOOLDecl = TD;
}
- /// \brief type of 'BOOL' type.
+ /// type of 'BOOL' type.
QualType getBOOLType() const {
return getTypeDeclType(getBOOLDecl());
}
- /// \brief Retrieve the type of the Objective-C \c Protocol class.
+ /// Retrieve the type of the Objective-C \c Protocol class.
QualType getObjCProtoType() const {
return getObjCInterfaceType(getObjCProtocolDecl());
}
- /// \brief Retrieve the C type declaration corresponding to the predefined
+ /// Retrieve the C type declaration corresponding to the predefined
/// \c __builtin_va_list type.
TypedefDecl *getBuiltinVaListDecl() const;
- /// \brief Retrieve the type of the \c __builtin_va_list type.
+ /// Retrieve the type of the \c __builtin_va_list type.
QualType getBuiltinVaListType() const {
return getTypeDeclType(getBuiltinVaListDecl());
}
- /// \brief Retrieve the C type declaration corresponding to the predefined
+ /// Retrieve the C type declaration corresponding to the predefined
/// \c __va_list_tag type used to help define the \c __builtin_va_list type
/// for some targets.
Decl *getVaListTagDecl() const;
@@ -1870,18 +1904,22 @@ public:
return getTypeDeclType(getBuiltinMSVaListDecl());
}
- /// \brief Return a type with additional \c const, \c volatile, or
+ /// Return whether a declaration to a builtin is allowed to be
+ /// overloaded/redeclared.
+ bool canBuiltinBeRedeclared(const FunctionDecl *) const;
+
+ /// Return a type with additional \c const, \c volatile, or
/// \c restrict qualifiers.
QualType getCVRQualifiedType(QualType T, unsigned CVR) const {
return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
}
- /// \brief Un-split a SplitQualType.
+ /// Un-split a SplitQualType.
QualType getQualifiedType(SplitQualType split) const {
return getQualifiedType(split.Ty, split.Quals);
}
- /// \brief Return a type with additional qualifiers.
+ /// Return a type with additional qualifiers.
QualType getQualifiedType(QualType T, Qualifiers Qs) const {
if (!Qs.hasNonFastQualifiers())
return T.withFastQualifiers(Qs.getFastQualifiers());
@@ -1890,14 +1928,14 @@ public:
return getExtQualType(Ptr, Qc);
}
- /// \brief Return a type with additional qualifiers.
+ /// Return a type with additional qualifiers.
QualType getQualifiedType(const Type *T, Qualifiers Qs) const {
if (!Qs.hasNonFastQualifiers())
return QualType(T, Qs.getFastQualifiers());
return getExtQualType(T, Qs);
}
- /// \brief Return a type with the given lifetime qualifier.
+ /// Return a type with the given lifetime qualifier.
///
/// \pre Neither type.ObjCLifetime() nor \p lifetime may be \c OCL_None.
QualType getLifetimeQualifiedType(QualType type,
@@ -1921,6 +1959,9 @@ public:
return getQualifiedType(type.getUnqualifiedType(), Qs);
}
+ unsigned char getFixedPointScale(QualType Ty) const;
+ unsigned char getFixedPointIBits(QualType Ty) const;
+
DeclarationNameInfo getNameForTemplate(TemplateName Name,
SourceLocation NameLoc) const;
@@ -1954,7 +1995,7 @@ public:
GE_Missing_ucontext
};
- /// \brief Return the type for the specified builtin.
+ /// Return the type for the specified builtin.
///
/// If \p IntegerConstantArgs is non-null, it is filled in with a bitmask of
/// arguments to the builtin that are required to be integer constant
@@ -1962,6 +2003,10 @@ public:
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error,
unsigned *IntegerConstantArgs = nullptr) const;
+ /// Types and expressions required to build C++2a three-way comparisons
+ /// using operator<=>, including the values return by builtin <=> operators.
+ ComparisonCategories CompCategories;
+
private:
CanQualType getFromTargetType(unsigned Type) const;
TypeInfo getTypeInfoImpl(const Type *T) const;
@@ -1971,18 +2016,18 @@ private:
//===--------------------------------------------------------------------===//
public:
- /// \brief Return one of the GCNone, Weak or Strong Objective-C garbage
+ /// Return one of the GCNone, Weak or Strong Objective-C garbage
/// collection attributes.
Qualifiers::GC getObjCGCAttrKind(QualType Ty) const;
- /// \brief Return true if the given vector types are of the same unqualified
+ /// Return true if the given vector types are of the same unqualified
/// type or if they are equivalent to the same GCC vector type.
///
/// \note This ignores whether they are target-specific (AltiVec or Neon)
/// types.
bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
- /// \brief Return true if this is an \c NSObject object with its \c NSObject
+ /// Return true if this is an \c NSObject object with its \c NSObject
/// attribute set.
static bool isObjCNSObjectType(QualType Ty) {
return Ty->isObjCNSObjectType();
@@ -1992,52 +2037,68 @@ public:
// Type Sizing and Analysis
//===--------------------------------------------------------------------===//
- /// \brief Return the APFloat 'semantics' for the specified scalar floating
+ /// Return the APFloat 'semantics' for the specified scalar floating
/// point type.
const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
- /// \brief Get the size and alignment of the specified complete type in bits.
+ /// Get the size and alignment of the specified complete type in bits.
TypeInfo getTypeInfo(const Type *T) const;
TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); }
- /// \brief Get default simd alignment of the specified complete type in bits.
+ /// Get default simd alignment of the specified complete type in bits.
unsigned getOpenMPDefaultSimdAlign(QualType T) const;
- /// \brief Return the size of the specified (complete) type \p T, in bits.
+ /// Return the size of the specified (complete) type \p T, in bits.
uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; }
uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; }
- /// \brief Return the size of the character type, in bits.
+ /// Return the size of the character type, in bits.
uint64_t getCharWidth() const {
return getTypeSize(CharTy);
}
- /// \brief Convert a size in bits to a size in characters.
+ /// Convert a size in bits to a size in characters.
CharUnits toCharUnitsFromBits(int64_t BitSize) const;
- /// \brief Convert a size in characters to a size in bits.
+ /// Convert a size in characters to a size in bits.
int64_t toBits(CharUnits CharSize) const;
- /// \brief Return the size of the specified (complete) type \p T, in
+ /// Return the size of the specified (complete) type \p T, in
/// characters.
CharUnits getTypeSizeInChars(QualType T) const;
CharUnits getTypeSizeInChars(const Type *T) const;
- /// \brief Return the ABI-specified alignment of a (complete) type \p T, in
+ /// Return the ABI-specified alignment of a (complete) type \p T, in
/// bits.
unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }
- /// \brief Return the ABI-specified alignment of a type, in bits, or 0 if
+ /// Return the ABI-specified natural alignment of a (complete) type \p T,
+ /// before alignment adjustments, in bits.
+ ///
+ /// This alignment is curently used only by ARM and AArch64 when passing
+ /// arguments of a composite type.
+ unsigned getTypeUnadjustedAlign(QualType T) const {
+ return getTypeUnadjustedAlign(T.getTypePtr());
+ }
+ unsigned getTypeUnadjustedAlign(const Type *T) const;
+
+ /// Return the ABI-specified alignment of a type, in bits, or 0 if
/// the type is incomplete and we cannot determine the alignment (for
/// example, from alignment attributes).
unsigned getTypeAlignIfKnown(QualType T) const;
- /// \brief Return the ABI-specified alignment of a (complete) type \p T, in
+ /// Return the ABI-specified alignment of a (complete) type \p T, in
/// characters.
CharUnits getTypeAlignInChars(QualType T) const;
CharUnits getTypeAlignInChars(const Type *T) const;
+ /// getTypeUnadjustedAlignInChars - Return the ABI-specified alignment of a type,
+ /// in characters, before alignment adjustments. This method does not work on
+ /// incomplete types.
+ CharUnits getTypeUnadjustedAlignInChars(QualType T) const;
+ CharUnits getTypeUnadjustedAlignInChars(const Type *T) const;
+
// getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the
// type is a record, its data size is returned.
std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const;
@@ -2045,31 +2106,31 @@ public:
std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
- /// \brief Determine if the alignment the type has was required using an
+ /// Determine if the alignment the type has was required using an
/// alignment attribute.
bool isAlignmentRequired(const Type *T) const;
bool isAlignmentRequired(QualType T) const;
- /// \brief Return the "preferred" alignment of the specified type \p T for
+ /// Return the "preferred" alignment of the specified type \p T for
/// the current target, in bits.
///
/// This can be different than the ABI alignment in cases where it is
/// beneficial for performance to overalign a data type.
unsigned getPreferredTypeAlign(const Type *T) const;
- /// \brief Return the default alignment for __attribute__((aligned)) on
+ /// Return the default alignment for __attribute__((aligned)) on
/// this target, to be used if no alignment value is specified.
unsigned getTargetDefaultAlignForAttributeAligned() const;
- /// \brief Return the alignment in bits that should be given to a
+ /// Return the alignment in bits that should be given to a
/// global variable with type \p T.
unsigned getAlignOfGlobalVar(QualType T) const;
- /// \brief Return the alignment in characters that should be given to a
+ /// Return the alignment in characters that should be given to a
/// global variable with type \p T.
CharUnits getAlignOfGlobalVarInChars(QualType T) const;
- /// \brief Return a conservative estimate of the alignment of the specified
+ /// Return a conservative estimate of the alignment of the specified
/// decl \p D.
///
/// \pre \p D must not be a bitfield type, as bitfields do not have a valid
@@ -2081,12 +2142,12 @@ public:
/// pointers and large arrays get extra alignment.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const;
- /// \brief Get or compute information about the layout of the specified
+ /// Get or compute information about the layout of the specified
/// record (struct/union/class) \p D, which indicates its size and field
/// position information.
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
- /// \brief Get or compute information about the layout of the specified
+ /// Get or compute information about the layout of the specified
/// Objective-C interface.
const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D)
const;
@@ -2094,14 +2155,14 @@ public:
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS,
bool Simple = false) const;
- /// \brief Get or compute information about the layout of the specified
+ /// Get or compute information about the layout of the specified
/// Objective-C implementation.
///
/// This may differ from the interface if synthesized ivars are present.
const ASTRecordLayout &
getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const;
- /// \brief Get our current best idea for the key function of the
+ /// Get our current best idea for the key function of the
/// given record decl, or nullptr if there isn't one.
///
/// The key function is, according to the Itanium C++ ABI section 5.2.3:
@@ -2113,7 +2174,7 @@ public:
/// the result of this computation can change.
const CXXMethodDecl *getCurrentKeyFunction(const CXXRecordDecl *RD);
- /// \brief Observe that the given method cannot be a key function.
+ /// Observe that the given method cannot be a key function.
/// Checks the key-function cache for the method's class and clears it
/// if matches the given declaration.
///
@@ -2155,7 +2216,7 @@ public:
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
- /// \brief Return true if the specified type has unique object representations
+ /// Return true if the specified type has unique object representations
/// according to (C++17 [meta.unary.prop]p9)
bool hasUniqueObjectRepresentations(QualType Ty) const;
@@ -2163,7 +2224,7 @@ public:
// Type Operators
//===--------------------------------------------------------------------===//
- /// \brief Return the canonical (structural) type corresponding to the
+ /// Return the canonical (structural) type corresponding to the
/// specified potentially non-canonical type \p T.
///
/// The non-canonical version of a type may have many "decorated" versions of
@@ -2179,14 +2240,14 @@ public:
return T->getCanonicalTypeInternal().getTypePtr();
}
- /// \brief Return the canonical parameter type corresponding to the specific
+ /// Return the canonical parameter type corresponding to the specific
/// potentially non-canonical one.
///
/// Qualifiers are stripped off, functions are turned into function
/// pointers, and arrays decay one level into pointers.
CanQualType getCanonicalParamType(QualType T) const;
- /// \brief Determine whether the given types \p T1 and \p T2 are equivalent.
+ /// Determine whether the given types \p T1 and \p T2 are equivalent.
bool hasSameType(QualType T1, QualType T2) const {
return getCanonicalType(T1) == getCanonicalType(T2);
}
@@ -2194,7 +2255,7 @@ public:
return getCanonicalType(T1) == getCanonicalType(T2);
}
- /// \brief Return this type as a completely-unqualified array type,
+ /// Return this type as a completely-unqualified array type,
/// capturing the qualifiers in \p Quals.
///
/// This will remove the minimal amount of sugaring from the types, similar
@@ -2209,7 +2270,7 @@ public:
/// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
- /// \brief Determine whether the given types are equivalent after
+ /// Determine whether the given types are equivalent after
/// cvr-qualifiers have been removed.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const {
return getCanonicalType(T1).getTypePtr() ==
@@ -2249,9 +2310,22 @@ public:
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
const ObjCMethodDecl *MethodImp);
- bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
+ bool UnwrapSimilarTypes(QualType &T1, QualType &T2);
+ bool UnwrapSimilarArrayTypes(QualType &T1, QualType &T2);
- /// \brief Retrieves the "canonical" nested name specifier for a
+ /// Determine if two types are similar, according to the C++ rules. That is,
+ /// determine if they are the same other than qualifiers on the initial
+ /// sequence of pointer / pointer-to-member / array (and in Clang, object
+ /// pointer) types and their element types.
+ ///
+ /// Clang offers a number of qualifiers in addition to the C++ qualifiers;
+ /// those qualifiers are also ignored in the 'similarity' check.
+ bool hasSimilarType(QualType T1, QualType T2);
+
+ /// Determine if two types are similar, ignoring only CVR qualifiers.
+ bool hasCvrSimilarType(QualType T1, QualType T2);
+
+ /// Retrieves the "canonical" nested name specifier for a
/// given nested name specifier.
///
/// The canonical nested name specifier is a nested name specifier
@@ -2277,11 +2351,11 @@ public:
NestedNameSpecifier *
getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
- /// \brief Retrieves the default calling convention for the current target.
+ /// Retrieves the default calling convention for the current target.
CallingConv getDefaultCallingConvention(bool IsVariadic,
bool IsCXXMethod) const;
- /// \brief Retrieves the "canonical" template name that refers to a
+ /// Retrieves the "canonical" template name that refers to a
/// given template.
///
/// The canonical template name is the simplest expression that can
@@ -2301,11 +2375,11 @@ public:
/// types, values, and templates.
TemplateName getCanonicalTemplateName(TemplateName Name) const;
- /// \brief Determine whether the given template names refer to the same
+ /// Determine whether the given template names refer to the same
/// template.
bool hasSameTemplateName(TemplateName X, TemplateName Y);
- /// \brief Retrieve the "canonical" template argument.
+ /// Retrieve the "canonical" template argument.
///
/// The canonical template argument is the simplest template argument
/// (which may be a type, value, expression, or declaration) that
@@ -2332,33 +2406,33 @@ public:
return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T));
}
- /// \brief Return the innermost element type of an array type.
+ /// Return the innermost element type of an array type.
///
/// For example, will return "int" for int[m][n]
QualType getBaseElementType(const ArrayType *VAT) const;
- /// \brief Return the innermost element type of a type (which needn't
+ /// Return the innermost element type of a type (which needn't
/// actually be an array type).
QualType getBaseElementType(QualType QT) const;
- /// \brief Return number of constant array elements.
+ /// Return number of constant array elements.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
- /// \brief Perform adjustment on the parameter type of a function.
+ /// Perform adjustment on the parameter type of a function.
///
/// This routine adjusts the given parameter type @p T to the actual
/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8],
/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
QualType getAdjustedParameterType(QualType T) const;
- /// \brief Retrieve the parameter type as adjusted for use in the signature
+ /// Retrieve the parameter type as adjusted for use in the signature
/// of a function, decaying array and function types and removing top-level
/// cv-qualifiers.
QualType getSignatureParameterType(QualType T) const;
QualType getExceptionObjectType(QualType T) const;
- /// \brief Return the properly qualified result of decaying the specified
+ /// Return the properly qualified result of decaying the specified
/// array type to a pointer.
///
/// This operation is non-trivial when handling typedefs etc. The canonical
@@ -2368,35 +2442,35 @@ public:
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
QualType getArrayDecayedType(QualType T) const;
- /// \brief Return the type that \p PromotableType will promote to: C99
+ /// Return the type that \p PromotableType will promote to: C99
/// 6.3.1.1p2, assuming that \p PromotableType is a promotable integer type.
QualType getPromotedIntegerType(QualType PromotableType) const;
- /// \brief Recurses in pointer/array types until it finds an Objective-C
+ /// Recurses in pointer/array types until it finds an Objective-C
/// retainable type and returns its ownership.
Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) const;
- /// \brief Whether this is a promotable bitfield reference according
+ /// Whether this is a promotable bitfield reference according
/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
///
/// \returns the type this bit-field will promote to, or NULL if no
/// promotion occurs.
QualType isPromotableBitField(Expr *E) const;
- /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1.
+ /// Return the highest ranked integer type, see C99 6.3.1.8p1.
///
/// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If
/// \p LHS < \p RHS, return -1.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const;
- /// \brief Compare the rank of the two specified floating point types,
+ /// Compare the rank of the two specified floating point types,
/// ignoring the domain of the type (i.e. 'double' == '_Complex double').
///
/// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If
/// \p LHS < \p RHS, return -1.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const;
- /// \brief Return a real floating point or a complex type (based on
+ /// Return a real floating point or a complex type (based on
/// \p typeDomain/\p typeSize).
///
/// \param typeDomain a real floating point or complex type.
@@ -2521,13 +2595,20 @@ public:
// Per C99 6.2.5p6, for every signed integer type, there is a corresponding
// unsigned integer type. This method takes a signed type, and returns the
// corresponding unsigned integer type.
+ // With the introduction of fixed point types in ISO N1169, this method also
+ // accepts fixed point types and returns the corresponding unsigned type for
+ // a given fixed point type.
QualType getCorrespondingUnsignedType(QualType T) const;
+ // Per ISO N1169, this method accepts fixed point types and returns the
+ // corresponding saturated type for a given fixed point type.
+ QualType getCorrespondingSaturatedType(QualType Ty) const;
+
//===--------------------------------------------------------------------===//
// Integer Values
//===--------------------------------------------------------------------===//
- /// \brief Make an APSInt of the appropriate width and signedness for the
+ /// Make an APSInt of the appropriate width and signedness for the
/// given \p Value and integer \p Type.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
// If Type is a signed integer type larger than 64 bits, we need to be sure
@@ -2542,28 +2623,28 @@ public:
bool isSentinelNullExpr(const Expr *E);
- /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or nullptr if
+ /// 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 nullptr if
+ /// Get the implementation of the ObjCCategoryDecl \p D, or nullptr if
/// none exists.
ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
- /// \brief Return true if there is at least one \@implementation in the TU.
+ /// Return true if there is at least one \@implementation in the TU.
bool AnyObjCImplementation() {
return !ObjCImpls.empty();
}
- /// \brief Set the implementation of ObjCInterfaceDecl.
+ /// Set the implementation of ObjCInterfaceDecl.
void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
ObjCImplementationDecl *ImplD);
- /// \brief Set the implementation of ObjCCategoryDecl.
+ /// Set the implementation of ObjCCategoryDecl.
void setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCCategoryImplDecl *ImplD);
- /// \brief Get the duplicate declaration of a ObjCMethod in the same
+ /// Get the duplicate declaration of a ObjCMethod in the same
/// interface, or null if none exists.
const ObjCMethodDecl *
getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const;
@@ -2571,19 +2652,19 @@ public:
void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
const ObjCMethodDecl *Redecl);
- /// \brief Returns the Objective-C interface that \p ND belongs to if it is
+ /// Returns the Objective-C interface that \p ND belongs to if it is
/// an Objective-C method/property/ivar etc. that is part of an interface,
/// otherwise returns null.
const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const;
- /// \brief Set the copy inialization expression of a block var decl.
+ /// 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
+ /// Get the copy initialization expression of the VarDecl \p VD, or
/// nullptr if none exists.
Expr *getBlockVarCopyInits(const VarDecl* VD);
- /// \brief Allocate an uninitialized TypeSourceInfo.
+ /// Allocate an uninitialized TypeSourceInfo.
///
/// The caller should initialize the memory held by TypeSourceInfo using
/// the TypeLoc wrappers.
@@ -2596,14 +2677,14 @@ public:
/// should be calculated based on the type.
TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0) const;
- /// \brief Allocate a TypeSourceInfo where all locations have been
+ /// Allocate a TypeSourceInfo where all locations have been
/// initialized to a given location, which defaults to the empty
/// location.
TypeSourceInfo *
getTrivialTypeSourceInfo(QualType T,
SourceLocation Loc = SourceLocation()) const;
- /// \brief Add a deallocation callback that will be invoked when the
+ /// Add a deallocation callback that will be invoked when the
/// ASTContext is destroyed.
///
/// \param Callback A callback function that will be invoked on destruction.
@@ -2625,7 +2706,7 @@ public:
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const;
GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
- /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
+ /// Determines if the decl can be CodeGen'ed or deserialized from PCH
/// lazily, only when used; this is only relevant for function or file scoped
/// var definitions.
///
@@ -2633,6 +2714,12 @@ public:
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
+ /// Visits all versions of a multiversioned function with the passed
+ /// predicate.
+ void forEachMultiversionedFunctionVersion(
+ const FunctionDecl *FD,
+ llvm::function_ref<void(FunctionDecl *)> Pred) const;
+
const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
@@ -2653,21 +2740,21 @@ public:
void setStaticLocalNumber(const VarDecl *VD, unsigned Number);
unsigned getStaticLocalNumber(const VarDecl *VD) const;
- /// \brief Retrieve the context for computing mangling numbers in the given
+ /// Retrieve the context for computing mangling numbers in the given
/// DeclContext.
MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
std::unique_ptr<MangleNumberingContext> createMangleNumberingContext() const;
- /// \brief Used by ParmVarDecl to store on the side the
+ /// Used by ParmVarDecl to store on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
void setParameterIndex(const ParmVarDecl *D, unsigned index);
- /// \brief Used by ParmVarDecl to retrieve on the side the
+ /// Used by ParmVarDecl to retrieve on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
unsigned getParameterIndex(const ParmVarDecl *D) const;
- /// \brief Get the storage for the constant value of a materialized temporary
+ /// Get the storage for the constant value of a materialized temporary
/// of static storage duration.
APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
bool MayCreate);
@@ -2676,50 +2763,50 @@ public:
// Statistics
//===--------------------------------------------------------------------===//
- /// \brief The number of implicitly-declared default constructors.
+ /// The number of implicitly-declared default constructors.
static unsigned NumImplicitDefaultConstructors;
- /// \brief The number of implicitly-declared default constructors for
+ /// The number of implicitly-declared default constructors for
/// which declarations were built.
static unsigned NumImplicitDefaultConstructorsDeclared;
- /// \brief The number of implicitly-declared copy constructors.
+ /// The number of implicitly-declared copy constructors.
static unsigned NumImplicitCopyConstructors;
- /// \brief The number of implicitly-declared copy constructors for
+ /// The number of implicitly-declared copy constructors for
/// which declarations were built.
static unsigned NumImplicitCopyConstructorsDeclared;
- /// \brief The number of implicitly-declared move constructors.
+ /// The number of implicitly-declared move constructors.
static unsigned NumImplicitMoveConstructors;
- /// \brief The number of implicitly-declared move constructors for
+ /// The number of implicitly-declared move constructors for
/// which declarations were built.
static unsigned NumImplicitMoveConstructorsDeclared;
- /// \brief The number of implicitly-declared copy assignment operators.
+ /// The number of implicitly-declared copy assignment operators.
static unsigned NumImplicitCopyAssignmentOperators;
- /// \brief The number of implicitly-declared copy assignment operators for
+ /// The number of implicitly-declared copy assignment operators for
/// which declarations were built.
static unsigned NumImplicitCopyAssignmentOperatorsDeclared;
- /// \brief The number of implicitly-declared move assignment operators.
+ /// The number of implicitly-declared move assignment operators.
static unsigned NumImplicitMoveAssignmentOperators;
- /// \brief The number of implicitly-declared move assignment operators for
+ /// The number of implicitly-declared move assignment operators for
/// which declarations were built.
static unsigned NumImplicitMoveAssignmentOperatorsDeclared;
- /// \brief The number of implicitly-declared destructors.
+ /// The number of implicitly-declared destructors.
static unsigned NumImplicitDestructors;
- /// \brief The number of implicitly-declared destructors for which
+ /// The number of implicitly-declared destructors for which
/// declarations were built.
static unsigned NumImplicitDestructorsDeclared;
public:
- /// \brief Initialize built-in types.
+ /// Initialize built-in types.
///
/// This routine may only be invoked once for a given ASTContext object.
/// It is normally invoked after ASTContext construction.
@@ -2756,7 +2843,7 @@ public:
QualType T, std::string& S,
bool Extended) const;
- /// \brief Returns true if this is an inline-initialized static data member
+ /// Returns true if this is an inline-initialized static data member
/// which is treated as a definition for MSVC compatibility.
bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const;
@@ -2774,7 +2861,7 @@ public:
Strong
};
- /// \brief Determine whether a definition of this inline variable should
+ /// 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
/// out-of-line declaration of the member, we may promote it from weak to
@@ -2790,7 +2877,7 @@ private:
getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl) const;
- /// \brief A set of deallocations that should be performed when the
+ /// A set of deallocations that should be performed when the
/// ASTContext is destroyed.
// FIXME: We really should have a better mechanism in the ASTContext to
// manage running destructors for types which do variable sized allocation
@@ -2841,13 +2928,13 @@ public:
llvm::StringMap<SectionInfo> SectionInfos;
};
-/// \brief Utility function for constructing a nullary selector.
+/// Utility function for constructing a nullary selector.
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.
+/// Utility function for constructing an unary selector.
inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(1, &II);
@@ -2857,7 +2944,7 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
// operator new and delete aren't allowed inside namespaces.
-/// @brief Placement new for using the ASTContext's allocator.
+/// Placement new for using the ASTContext's allocator.
///
/// This placement form of operator new uses the ASTContext's allocator for
/// obtaining memory.
@@ -2890,7 +2977,7 @@ inline void *operator new(size_t Bytes, const clang::ASTContext &C,
return C.Allocate(Bytes, Alignment);
}
-/// @brief Placement delete companion to the new above.
+/// Placement delete companion to the new above.
///
/// This operator is just a companion to the new above. There is no way of
/// invoking it directly; see the new operator for more details. This operator
@@ -2928,7 +3015,7 @@ inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
return C.Allocate(Bytes, Alignment);
}
-/// @brief Placement delete[] companion to the new[] above.
+/// Placement delete[] companion to the new[] above.
///
/// This operator is just a companion to the new[] above. There is no way of
/// invoking it directly; see the new[] operator for more details. This operator
@@ -2938,7 +3025,7 @@ inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) {
C.Deallocate(Ptr);
}
-/// \brief Create the representation of a LazyGenerationalUpdatePtr.
+/// Create the representation of a LazyGenerationalUpdatePtr.
template <typename Owner, typename T,
void (clang::ExternalASTSource::*Update)(Owner)>
typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h
index 27c85e65f2c1..2534272da3a3 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h
@@ -23,11 +23,11 @@ namespace clang {
NUM_BUILTIN_AST_DIAGNOSTICS
};
} // end namespace diag
-
- /// \brief DiagnosticsEngine argument formatting function for diagnostics that
+
+ /// DiagnosticsEngine argument formatting function for diagnostics that
/// involve AST nodes.
///
- /// This function formats diagnostic arguments for various AST nodes,
+ /// This function formats diagnostic arguments for various AST nodes,
/// including types, declaration names, nested name specifiers, and
/// declaration contexts, into strings that can be printed as part of
/// diagnostics. It is meant to be used as the argument to
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h b/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h
index 003d489c1ca4..038d5c3d3611 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h
@@ -8,7 +8,7 @@
//===--------------------------------------------------------------===//
///
/// \file
-/// \brief Forward declaration of all AST node types.
+/// Forward declaration of all AST node types.
///
//===-------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
index 66b9cd394b9d..2e9a8775a8a2 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
@@ -1,4 +1,4 @@
-//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- C++ -*-===//
+//===- ASTImporter.h - Importing ASTs from other Contexts -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,82 +11,95 @@
// context into another context.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
+#include <utility>
namespace clang {
- class ASTContext;
- class CXXCtorInitializer;
- class CXXBaseSpecifier;
- class Decl;
- class DeclContext;
- class DiagnosticsEngine;
- class Expr;
- class FileManager;
- class IdentifierInfo;
- class NestedNameSpecifier;
- class Stmt;
- class TypeSourceInfo;
-
- /// \brief Imports selected nodes from one AST context into another context,
+
+class ASTContext;
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class Decl;
+class DeclContext;
+class Expr;
+class FileManager;
+class NamedDecl;
+class Stmt;
+class TagDecl;
+class TypeSourceInfo;
+class Attr;
+
+ // \brief Returns with a list of declarations started from the canonical decl
+ // then followed by subsequent decls in the translation unit.
+ // This gives a canonical list for each entry in the redecl chain.
+ // `Decl::redecls()` gives a list of decls which always start from the
+ // previous decl and the next item is actually the previous item in the order
+ // of source locations. Thus, `Decl::redecls()` gives different lists for
+ // the different entries in a given redecl chain.
+ llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D);
+
+ /// Imports selected nodes from one AST context into another context,
/// merging AST nodes where appropriate.
class ASTImporter {
public:
- typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
- typedef llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>
- ImportedCXXBaseSpecifierMap;
+ using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>;
+ using ImportedCXXBaseSpecifierMap =
+ llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>;
private:
- /// \brief The contexts we're importing to and from.
+ /// The contexts we're importing to and from.
ASTContext &ToContext, &FromContext;
-
- /// \brief The file managers we're importing to and from.
+
+ /// The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
- /// \brief Whether to perform a minimal import.
+ /// Whether to perform a minimal import.
bool Minimal;
- /// \brief Whether the last diagnostic came from the "from" context.
- bool LastDiagFromFrom;
-
- /// \brief Mapping from the already-imported types in the "from" context
+ /// Whether the last diagnostic came from the "from" context.
+ bool LastDiagFromFrom = false;
+
+ /// Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
llvm::DenseMap<const Type *, const Type *> ImportedTypes;
-
- /// \brief Mapping from the already-imported declarations in the "from"
+
+ /// Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
llvm::DenseMap<Decl *, Decl *> ImportedDecls;
- /// \brief Mapping from the already-imported statements in the "from"
+ /// Mapping from the already-imported statements in the "from"
/// context to the corresponding statements in the "to" context.
llvm::DenseMap<Stmt *, Stmt *> ImportedStmts;
- /// \brief Mapping from the already-imported FileIDs in the "from" source
+ /// Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
llvm::DenseMap<FileID, FileID> ImportedFileIDs;
- /// \brief Mapping from the already-imported CXXBasesSpecifier in
+ /// Mapping from the already-imported CXXBasesSpecifier in
/// the "from" source manager to the corresponding CXXBasesSpecifier
/// in the "to" source manager.
ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers;
- /// \brief Imported, anonymous tag declarations that are missing their
- /// corresponding typedefs.
- SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
-
- /// \brief Declaration (from, to) pairs that are known not to be equivalent
+ /// Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).
NonEquivalentDeclSet NonEquivalentDecls;
-
+
public:
- /// \brief Create a new AST importer.
+ /// Create a new AST importer.
///
/// \param ToContext The context we'll be importing into.
///
@@ -102,141 +115,150 @@ namespace clang {
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport);
-
+
virtual ~ASTImporter();
-
- /// \brief Whether the importer will perform a minimal import, creating
+
+ /// Whether the importer will perform a minimal import, creating
/// to-be-completed forward declarations when possible.
bool isMinimalImport() const { return Minimal; }
-
- /// \brief Import the given type from the "from" context into the "to"
+
+ /// Import the given type from the "from" context into the "to"
/// context.
///
/// \returns the equivalent type in the "to" context, or a NULL type if
/// an error occurred.
QualType Import(QualType FromT);
- /// \brief Import the given type source information from the
+ /// Import the given type source information from the
/// "from" context into the "to" context.
///
/// \returns the equivalent type source information in the "to"
/// context, or NULL if an error occurred.
TypeSourceInfo *Import(TypeSourceInfo *FromTSI);
- /// \brief Import the given declaration from the "from" context into the
+ /// Import the given attribute from the "from" context into the
+ /// "to" context.
+ ///
+ /// \returns the equivalent attribute in the "to" context.
+ Attr *Import(const Attr *FromAttr);
+
+ /// Import the given declaration from the "from" context into the
/// "to" context.
///
- /// \returns the equivalent declaration in the "to" context, or a NULL type
+ /// \returns the equivalent declaration in the "to" context, or a NULL type
/// if an error occurred.
Decl *Import(Decl *FromD);
+ Decl *Import(const Decl *FromD) {
+ return Import(const_cast<Decl *>(FromD));
+ }
- /// \brief Return the copy of the given declaration in the "to" context if
+ /// Return the copy of the given declaration in the "to" context if
/// it has already been imported from the "from" context. Otherwise return
/// NULL.
Decl *GetAlreadyImportedOrNull(Decl *FromD);
- /// \brief Import the given declaration context from the "from"
+ /// Import the given declaration context from the "from"
/// AST context into the "to" AST context.
///
/// \returns the equivalent declaration context in the "to"
/// context, or a NULL type if an error occurred.
DeclContext *ImportContext(DeclContext *FromDC);
-
- /// \brief Import the given expression from the "from" context into the
+
+ /// Import the given expression from the "from" context into the
/// "to" context.
///
/// \returns the equivalent expression in the "to" context, or NULL if
/// an error occurred.
Expr *Import(Expr *FromE);
- /// \brief Import the given statement from the "from" context into the
+ /// Import the given statement from the "from" context into the
/// "to" context.
///
/// \returns the equivalent statement in the "to" context, or NULL if
/// an error occurred.
Stmt *Import(Stmt *FromS);
- /// \brief Import the given nested-name-specifier from the "from"
+ /// Import the given nested-name-specifier from the "from"
/// context into the "to" context.
///
/// \returns the equivalent nested-name-specifier in the "to"
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
- /// \brief Import the given nested-name-specifier from the "from"
+ /// Import the given nested-name-specifier from the "from"
/// context into the "to" context.
///
/// \returns the equivalent nested-name-specifier in the "to"
/// context.
NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS);
- /// \brief Import the goven template name from the "from" context into the
+ /// Import the goven template name from the "from" context into the
/// "to" context.
TemplateName Import(TemplateName From);
-
- /// \brief Import the given source location from the "from" context into
+
+ /// Import the given source location from the "from" context into
/// the "to" context.
///
/// \returns the equivalent source location in the "to" context, or an
/// invalid source location if an error occurred.
SourceLocation Import(SourceLocation FromLoc);
- /// \brief Import the given source range from the "from" context into
+ /// Import the given source range from the "from" context into
/// the "to" context.
///
/// \returns the equivalent source range in the "to" context, or an
/// invalid source location if an error occurred.
SourceRange Import(SourceRange FromRange);
- /// \brief Import the given declaration name from the "from"
+ /// Import the given declaration name from the "from"
/// context into the "to" context.
///
/// \returns the equivalent declaration name in the "to" context,
/// or an empty declaration name if an error occurred.
DeclarationName Import(DeclarationName FromName);
- /// \brief Import the given identifier from the "from" context
+ /// Import the given identifier from the "from" context
/// into the "to" context.
///
/// \returns the equivalent identifier in the "to" context.
IdentifierInfo *Import(const IdentifierInfo *FromId);
- /// \brief Import the given Objective-C selector from the "from"
+ /// Import the given Objective-C selector from the "from"
/// context into the "to" context.
///
/// \returns the equivalent selector in the "to" context.
Selector Import(Selector FromSel);
- /// \brief Import the given file ID from the "from" context into the
+ /// Import the given file ID from the "from" context into the
/// "to" context.
///
/// \returns the equivalent file ID in the source manager of the "to"
/// context.
FileID Import(FileID);
- /// \brief Import the given C++ constructor initializer from the "from"
+ /// Import the given C++ constructor initializer from the "from"
/// context into the "to" context.
///
/// \returns the equivalent initializer in the "to" context.
CXXCtorInitializer *Import(CXXCtorInitializer *FromInit);
- /// \brief Import the given CXXBaseSpecifier from the "from" context into
+ /// Import the given CXXBaseSpecifier from the "from" context into
/// the "to" context.
///
/// \returns the equivalent CXXBaseSpecifier in the source manager of the
/// "to" context.
CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec);
- /// \brief Import the definition of the given declaration, including all of
+ /// Import the definition of the given declaration, including all of
/// the declarations it contains.
///
- /// This routine is intended to be used
+ /// This routine is intended to be used
void ImportDefinition(Decl *From);
- /// \brief Cope with a name conflict when importing a declaration into the
+ /// Cope with a name conflict when importing a declaration into the
/// given context.
///
- /// This routine is invoked whenever there is a name conflict while
+ /// This routine is invoked whenever there is a name conflict while
/// importing a declaration. The returned name will become the name of the
/// imported declaration. By default, the returned name is the same as the
/// original name, leaving the conflict unresolve such that name lookup
@@ -248,7 +270,7 @@ namespace clang {
/// \param Name the name of the declaration being imported, which conflicts
/// with other declarations.
///
- /// \param DC the declaration context (in the "to" AST context) in which
+ /// \param DC the declaration context (in the "to" AST context) in which
/// the name is being imported.
///
/// \param IDNS the identifier namespace in which the name will be found.
@@ -264,54 +286,55 @@ namespace clang {
unsigned IDNS,
NamedDecl **Decls,
unsigned NumDecls);
-
- /// \brief Retrieve the context that AST nodes are being imported into.
+
+ /// Retrieve the context that AST nodes are being imported into.
ASTContext &getToContext() const { return ToContext; }
-
- /// \brief Retrieve the context that AST nodes are being imported from.
+
+ /// Retrieve the context that AST nodes are being imported from.
ASTContext &getFromContext() const { return FromContext; }
-
- /// \brief Retrieve the file manager that AST nodes are being imported into.
+
+ /// Retrieve the file manager that AST nodes are being imported into.
FileManager &getToFileManager() const { return ToFileManager; }
- /// \brief Retrieve the file manager that AST nodes are being imported from.
+ /// Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
-
- /// \brief Report a diagnostic in the "to" context.
+
+ /// Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
-
- /// \brief Report a diagnostic in the "from" context.
+
+ /// Report a diagnostic in the "from" context.
DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID);
-
- /// \brief Return the set of declarations that we know are not equivalent.
+
+ /// Return the set of declarations that we know are not equivalent.
NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
- /// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl.
+ /// Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl.
/// Mark the Decl as complete, filling it in as much as possible.
///
/// \param D A declaration in the "to" context.
virtual void CompleteDecl(Decl* D);
-
- /// \brief Note that we have imported the "from" declaration by mapping it
- /// to the (potentially-newly-created) "to" declaration.
- ///
+
/// Subclasses can override this function to observe all of the \c From ->
/// \c To declaration mappings as they are imported.
- virtual Decl *Imported(Decl *From, Decl *To);
-
- /// \brief Called by StructuralEquivalenceContext. If a RecordDecl is
+ virtual Decl *Imported(Decl *From, Decl *To) { return To; }
+
+ /// Store and assign the imported declaration to its counterpart.
+ Decl *MapImported(Decl *From, Decl *To);
+
+ /// Called by StructuralEquivalenceContext. If a RecordDecl is
/// being compared to another RecordDecl as part of import, completing the
/// other RecordDecl may trigger importation of the first RecordDecl. This
/// happens especially for anonymous structs. If the original of the second
/// RecordDecl can be found, we can complete it without the need for
/// importation, eliminating this loop.
virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; }
-
- /// \brief Determine whether the given types are structurally
+
+ /// Determine whether the given types are structurally
/// equivalent.
bool IsStructurallyEquivalent(QualType From, QualType To,
bool Complain = true);
};
-}
+
+} // namespace clang
#endif // LLVM_CLANG_AST_ASTIMPORTER_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h b/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h
index 69df2d8c0113..6fedcb8d3801 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file provides some common utility functions for processing
+/// This file provides some common utility functions for processing
/// Lambda related AST Constructs.
///
//===----------------------------------------------------------------------===//
@@ -40,7 +40,7 @@ inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) {
if (!MD) return false;
const CXXRecordDecl *LambdaClass = MD->getParent();
if (LambdaClass && LambdaClass->isGenericLambda())
- return isLambdaCallOperator(MD) &&
+ return isLambdaCallOperator(MD) &&
MD->isFunctionTemplateSpecialization();
return false;
}
@@ -51,11 +51,11 @@ inline bool isLambdaConversionOperator(CXXConversionDecl *C) {
inline bool isLambdaConversionOperator(Decl *D) {
if (!D) return false;
- if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D))
- return isLambdaConversionOperator(Conv);
- if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D))
- if (CXXConversionDecl *Conv =
- dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl()))
+ if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D))
+ return isLambdaConversionOperator(Conv);
+ if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D))
+ if (CXXConversionDecl *Conv =
+ dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl()))
return isLambdaConversionOperator(Conv);
return false;
}
@@ -71,7 +71,7 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
if (isLambdaCallOperator(DC))
return DC->getParent()->getParent();
- else
+ else
return DC->getParent();
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
index 9395d36d87e5..80184e1cc740 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
@@ -41,86 +41,86 @@ namespace clang {
class VarTemplateDecl;
class VarTemplateSpecializationDecl;
-/// \brief An abstract interface that should be implemented by listeners
+/// An abstract interface that should be implemented by listeners
/// that want to be notified when an AST entity gets modified after its
/// initial creation.
class ASTMutationListener {
public:
virtual ~ASTMutationListener();
- /// \brief A new TagDecl definition was completed.
+ /// A new TagDecl definition was completed.
virtual void CompletedTagDefinition(const TagDecl *D) { }
- /// \brief A new declaration with name has been added to a DeclContext.
+ /// A new declaration with name has been added to a DeclContext.
virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
- /// \brief An implicit member was added after the definition was completed.
+ /// An implicit member was added after the definition was completed.
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
- /// \brief A template specialization (or partial one) was added to the
+ /// A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D) {}
- /// \brief A template specialization (or partial one) was added to the
+ /// A template specialization (or partial one) was added to the
/// template declaration.
virtual void
AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
const VarTemplateSpecializationDecl *D) {}
- /// \brief A template specialization (or partial one) was added to the
+ /// A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {}
- /// \brief A function's exception specification has been evaluated or
+ /// A function's exception specification has been evaluated or
/// instantiated.
virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {}
- /// \brief A function's return type has been deduced.
+ /// A function's return type has been deduced.
virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
- /// \brief A virtual destructor's operator delete has been resolved.
+ /// A virtual destructor's operator delete has been resolved.
virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
const FunctionDecl *Delete,
Expr *ThisArg) {}
- /// \brief An implicit member got a definition.
+ /// An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
- /// \brief The instantiation of a templated function or variable was
+ /// 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.
+ /// A templated variable's definition was implicitly instantiated.
virtual void VariableDefinitionInstantiated(const VarDecl *D) {}
- /// \brief A function template's definition was instantiated.
+ /// A function template's definition was instantiated.
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
- /// \brief A default argument was instantiated.
+ /// A default argument was instantiated.
virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {}
- /// \brief A default member initializer was instantiated.
+ /// A default member initializer was instantiated.
virtual void DefaultMemberInitializerInstantiated(const FieldDecl *D) {}
- /// \brief A new objc category class was added for an interface.
+ /// A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
- /// \brief A declaration is marked used which was not previously marked used.
+ /// A declaration is marked used which was not previously marked used.
///
/// \param D the declaration marked used
virtual void DeclarationMarkedUsed(const Decl *D) {}
- /// \brief A declaration is marked as OpenMP threadprivate which was not
+ /// A declaration is marked as OpenMP threadprivate which was not
/// previously marked as threadprivate.
///
/// \param D the declaration marked OpenMP threadprivate.
virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {}
- /// \brief A declaration is marked as OpenMP declaretarget which was not
+ /// A declaration is marked as OpenMP declaretarget which was not
/// previously marked as declaretarget.
///
/// \param D the declaration marked OpenMP declaretarget.
@@ -128,19 +128,19 @@ public:
virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) {}
- /// \brief A definition has been made visible by being redefined locally.
+ /// A definition has been made visible by being redefined locally.
///
/// \param D The definition that was previously not visible.
/// \param M The containing module in which the definition was made visible,
/// if any.
virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {}
-
- /// \brief An attribute was added to a RecordDecl
+
+ /// An attribute was added to a RecordDecl
///
/// \param Attr The attribute that was added to the Record
///
/// \param Record The RecordDecl that got a new attribute
- virtual void AddedAttributeToRecord(const Attr *Attr,
+ virtual void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) {}
// NOTE: If new methods are added they should also be added to
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTStructuralEquivalence.h b/contrib/llvm/tools/clang/include/clang/AST/ASTStructuralEquivalence.h
index 23674c65f332..d32f87d43e04 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTStructuralEquivalence.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTStructuralEquivalence.h
@@ -1,4 +1,4 @@
-//===--- ASTStructuralEquivalence.h - ---------------------------*- C++ -*-===//
+//===- ASTStructuralEquivalence.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include <deque>
+#include <utility>
namespace clang {
@@ -29,6 +30,14 @@ class QualType;
class RecordDecl;
class SourceLocation;
+/// \brief Whether to perform a normal or minimal equivalence check.
+/// In case of `Minimal`, we do not perform a recursive check of decls with
+/// external storage.
+enum class StructuralEquivalenceKind {
+ Default,
+ Minimal,
+};
+
struct StructuralEquivalenceContext {
/// AST contexts for which we are checking structural equivalence.
ASTContext &FromCtx, &ToCtx;
@@ -46,6 +55,8 @@ struct StructuralEquivalenceContext {
/// (which we have already complained about).
llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls;
+ StructuralEquivalenceKind EqKind;
+
/// Whether we're being strict about the spelling of types when
/// unifying two types.
bool StrictTypeSpelling;
@@ -57,27 +68,35 @@ struct StructuralEquivalenceContext {
bool Complain;
/// \c true if the last diagnostic came from ToCtx.
- bool LastDiagFromC2;
+ bool LastDiagFromC2 = false;
StructuralEquivalenceContext(
ASTContext &FromCtx, ASTContext &ToCtx,
llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
+ StructuralEquivalenceKind EqKind,
bool StrictTypeSpelling = false, bool Complain = true,
bool ErrorOnTagTypeMismatch = false)
: FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
- StrictTypeSpelling(StrictTypeSpelling),
- ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain),
- LastDiagFromC2(false) {}
+ EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling),
+ ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {}
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID);
/// Determine whether the two declarations are structurally
/// equivalent.
- bool IsStructurallyEquivalent(Decl *D1, Decl *D2);
+ /// Implementation functions (all static functions in
+ /// ASTStructuralEquivalence.cpp) must never call this function because that
+ /// will wreak havoc the internal state (\c DeclsToCheck and
+ /// \c TentativeEquivalences members) and can cause faulty equivalent results.
+ bool IsEquivalent(Decl *D1, Decl *D2);
/// Determine whether the two types are structurally equivalent.
- bool IsStructurallyEquivalent(QualType T1, QualType T2);
+ /// Implementation functions (all static functions in
+ /// ASTStructuralEquivalence.cpp) must never call this function because that
+ /// will wreak havoc the internal state (\c DeclsToCheck and
+ /// \c TentativeEquivalences members) and can cause faulty equivalent results.
+ bool IsEquivalent(QualType T1, QualType T2);
/// Find the index of the given anonymous struct/union within its
/// context.
@@ -98,6 +117,7 @@ private:
/// \returns true if an error occurred, false otherwise.
bool Finish();
};
+
} // namespace clang
#endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
index 51d60a90a146..9df9793370c4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
@@ -38,62 +38,62 @@ struct PrintingPolicy;
namespace ast_type_traits {
-/// \brief Kind identifier.
+/// Kind identifier.
///
/// It can be constructed from any node kind and allows for runtime type
/// hierarchy checks.
/// Use getFromNodeKind<T>() to construct them.
class ASTNodeKind {
public:
- /// \brief Empty identifier. It matches nothing.
+ /// Empty identifier. It matches nothing.
ASTNodeKind() : KindId(NKI_None) {}
- /// \brief Construct an identifier for T.
+ /// Construct an identifier for T.
template <class T>
static ASTNodeKind getFromNodeKind() {
return ASTNodeKind(KindToKindId<T>::Id);
}
/// \{
- /// \brief Construct an identifier for the dynamic type of the node
+ /// Construct an identifier for the dynamic type of the node
static ASTNodeKind getFromNode(const Decl &D);
static ASTNodeKind getFromNode(const Stmt &S);
static ASTNodeKind getFromNode(const Type &T);
/// \}
- /// \brief Returns \c true if \c this and \c Other represent the same kind.
+ /// Returns \c true if \c this and \c Other represent the same kind.
bool isSame(ASTNodeKind Other) const {
return KindId != NKI_None && KindId == Other.KindId;
}
- /// \brief Returns \c true only for the default \c ASTNodeKind()
+ /// Returns \c true only for the default \c ASTNodeKind()
bool isNone() const { return KindId == NKI_None; }
- /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
+ /// Returns \c true if \c this is a base kind of (or same as) \c Other.
/// \param Distance If non-null, used to return the distance between \c this
/// and \c Other in the class hierarchy.
bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const;
- /// \brief String representation of the kind.
+ /// String representation of the kind.
StringRef asStringRef() const;
- /// \brief Strict weak ordering for ASTNodeKind.
+ /// Strict weak ordering for ASTNodeKind.
bool operator<(const ASTNodeKind &Other) const {
return KindId < Other.KindId;
}
- /// \brief Return the most derived type between \p Kind1 and \p Kind2.
+ /// Return the most derived type between \p Kind1 and \p Kind2.
///
/// Return ASTNodeKind() if they are not related.
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
- /// \brief Return the most derived common ancestor between Kind1 and Kind2.
+ /// Return the most derived common ancestor between Kind1 and Kind2.
///
/// Return ASTNodeKind() if they are not related.
static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
ASTNodeKind Kind2);
- /// \brief Hooks for using ASTNodeKind as a key in a DenseMap.
+ /// Hooks for using ASTNodeKind as a key in a DenseMap.
struct DenseMapInfo {
// ASTNodeKind() is a good empty key because it is represented as a 0.
static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
@@ -115,7 +115,7 @@ public:
}
private:
- /// \brief Kind ids.
+ /// Kind ids.
///
/// Includes all possible base and derived kinds.
enum NodeKindId {
@@ -140,16 +140,16 @@ private:
NKI_NumberOfKinds
};
- /// \brief Use getFromNodeKind<T>() to construct the kind.
+ /// Use getFromNodeKind<T>() to construct the kind.
ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
- /// \brief Returns \c true if \c Base is a base kind of (or same as) \c
+ /// Returns \c true if \c Base is a base kind of (or same as) \c
/// Derived.
/// \param Distance If non-null, used to return the distance between \c Base
/// and \c Derived in the class hierarchy.
static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
- /// \brief Helper meta-function to convert a kind T to its enum value.
+ /// Helper meta-function to convert a kind T to its enum value.
///
/// This struct is specialized below for all known kinds.
template <class T> struct KindToKindId {
@@ -158,11 +158,11 @@ private:
template <class T>
struct KindToKindId<const T> : KindToKindId<T> {};
- /// \brief Per kind info.
+ /// Per kind info.
struct KindInfo {
- /// \brief The id of the parent kind, or None if it has no parent.
+ /// The id of the parent kind, or None if it has no parent.
NodeKindId ParentId;
- /// \brief Name of the kind.
+ /// Name of the kind.
const char *Name;
};
static const KindInfo AllKindInfo[NKI_NumberOfKinds];
@@ -197,7 +197,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
return OS;
}
-/// \brief A dynamically typed AST node container.
+/// A dynamically typed AST node container.
///
/// Stores an AST node in a type safe way. This allows writing code that
/// works with different kinds of AST nodes, despite the fact that they don't
@@ -211,13 +211,13 @@ inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
/// the supported base types.
class DynTypedNode {
public:
- /// \brief Creates a \c DynTypedNode from \c Node.
+ /// Creates a \c DynTypedNode from \c Node.
template <typename T>
static DynTypedNode create(const T &Node) {
return BaseConverter<T>::create(Node);
}
- /// \brief Retrieve the stored node as type \c T.
+ /// Retrieve the stored node as type \c T.
///
/// Returns NULL if the stored node does not have a type that is
/// convertible to \c T.
@@ -234,7 +234,7 @@ public:
return BaseConverter<T>::get(NodeKind, Storage.buffer);
}
- /// \brief Retrieve the stored node as type \c T.
+ /// Retrieve the stored node as type \c T.
///
/// Similar to \c get(), but asserts that the type is what we are expecting.
template <typename T>
@@ -244,7 +244,7 @@ public:
ASTNodeKind getNodeKind() const { return NodeKind; }
- /// \brief Returns a pointer that identifies the stored AST node.
+ /// Returns a pointer that identifies the stored AST node.
///
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
@@ -255,21 +255,21 @@ public:
: nullptr;
}
- /// \brief Prints the node to the given output stream.
+ /// Prints the node to the given output stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
- /// \brief Dumps the node to the given output stream.
+ /// Dumps the node to the given output stream.
void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
- /// \brief For nodes which represent textual entities in the source code,
+ /// For nodes which represent textual entities in the source code,
/// return their SourceRange. For all other nodes, return SourceRange().
SourceRange getSourceRange() const;
/// @{
- /// \brief Imposes an order on \c DynTypedNode.
+ /// Imposes an order on \c DynTypedNode.
///
/// Supports comparison of nodes that support memoization.
- /// FIXME: Implement comparsion for other node types (currently
+ /// FIXME: Implement comparison for other node types (currently
/// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
bool operator<(const DynTypedNode &Other) const {
if (!NodeKind.isSame(Other.NodeKind))
@@ -326,7 +326,7 @@ public:
}
/// @}
- /// \brief Hooks for using DynTypedNode as a key in a DenseMap.
+ /// Hooks for using DynTypedNode as a key in a DenseMap.
struct DenseMapInfo {
static inline DynTypedNode getEmptyKey() {
DynTypedNode Node;
@@ -368,10 +368,10 @@ public:
};
private:
- /// \brief Takes care of converting from and to \c T.
+ /// Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
- /// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
+ /// Converter that uses dyn_cast<T> from a stored BaseT*.
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
@@ -391,7 +391,7 @@ private:
}
};
- /// \brief Converter that stores T* (by pointer).
+ /// Converter that stores T* (by pointer).
template <typename T> struct PtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
@@ -411,7 +411,7 @@ private:
}
};
- /// \brief Converter that stores T (by value).
+ /// Converter that stores T (by value).
template <typename T> struct ValueConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
@@ -432,7 +432,7 @@ private:
ASTNodeKind NodeKind;
- /// \brief Stores the data of the node.
+ /// Stores the data of the node.
///
/// Note that we can store \c Decls, \c Stmts, \c Types,
/// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
index 3693aeccfe14..9bf63bb6e2d7 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
@@ -26,7 +26,7 @@ namespace clang {
class NamedDecl;
-/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator.
+/// An UnresolvedSet-like class which uses the ASTContext's allocator.
class ASTUnresolvedSet {
friend class LazyASTUnresolvedSet;
@@ -89,7 +89,7 @@ public:
const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; }
};
-/// \brief An UnresolvedSet-like class that might not have been loaded from the
+/// An UnresolvedSet-like class that might not have been loaded from the
/// external AST source yet.
class LazyASTUnresolvedSet {
mutable ASTUnresolvedSet Impl;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
index bbe320c28a3b..20922742f687 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Attr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
@@ -23,9 +23,9 @@
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -52,8 +52,10 @@ protected:
unsigned Inherited : 1;
unsigned IsPackExpansion : 1;
unsigned Implicit : 1;
+ // FIXME: These are properties of the attribute kind, not state for this
+ // instance of the attribute.
unsigned IsLateParsed : 1;
- unsigned DuplicatesAllowed : 1;
+ unsigned InheritEvenIfAlreadyPresent : 1;
void *operator new(size_t bytes) noexcept {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
@@ -74,17 +76,17 @@ public:
protected:
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed, bool DuplicatesAllowed)
+ bool IsLateParsed)
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
Inherited(false), IsPackExpansion(false), Implicit(false),
- IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {}
+ IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {}
public:
attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
}
-
+
unsigned getSpellingListIndex() const { return SpellingListIndex; }
const char *getSpelling() const;
@@ -94,7 +96,7 @@ public:
bool isInherited() const { return Inherited; }
- /// \brief Returns true if the attribute has been implicitly created instead
+ /// Returns true if the attribute has been implicitly created instead
/// of explicitly written by the user.
bool isImplicit() const { return Implicit; }
void setImplicit(bool I) { Implicit = I; }
@@ -109,18 +111,13 @@ public:
// Pretty print this attribute.
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
-
- /// \brief By default, attributes cannot be duplicated when being merged;
- /// however, an attribute can override this. Returns true if the attribute
- /// can be duplicated when merging.
- bool duplicatesAllowed() const { return DuplicatesAllowed; }
};
class StmtAttr : public Attr {
protected:
StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed, bool DuplicatesAllowed)
- : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
+ bool IsLateParsed)
+ : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
public:
static bool classof(const Attr *A) {
@@ -132,12 +129,20 @@ public:
class InheritableAttr : public Attr {
protected:
InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed, bool DuplicatesAllowed)
- : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
+ bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
+ : Attr(AK, R, SpellingListIndex, IsLateParsed) {
+ this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
+ }
public:
void setInherited(bool I) { Inherited = I; }
+ /// Should this attribute be inherited from a prior declaration even if it's
+ /// explicitly provided in the current declaration?
+ bool shouldInheritEvenIfAlreadyPresent() const {
+ return InheritEvenIfAlreadyPresent;
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstInheritableAttr &&
@@ -148,9 +153,9 @@ public:
class InheritableParamAttr : public InheritableAttr {
protected:
InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed, bool DuplicatesAllowed)
+ bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
: InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
- DuplicatesAllowed) {}
+ InheritEvenIfAlreadyPresent) {}
public:
// Implement isa/cast/dyncast/etc.
@@ -166,9 +171,9 @@ class ParameterABIAttr : public InheritableParamAttr {
protected:
ParameterABIAttr(attr::Kind AK, SourceRange R,
unsigned SpellingListIndex, bool IsLateParsed,
- bool DuplicatesAllowed)
+ bool InheritEvenIfAlreadyPresent)
: InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
- DuplicatesAllowed) {}
+ InheritEvenIfAlreadyPresent) {}
public:
ParameterABI getABI() const {
@@ -190,6 +195,128 @@ public:
}
};
+/// A single parameter index whose accessors require each use to make explicit
+/// the parameter index encoding needed.
+class ParamIdx {
+ // Idx is exposed only via accessors that specify specific encodings.
+ unsigned Idx : 30;
+ unsigned HasThis : 1;
+ unsigned IsValid : 1;
+
+ void assertComparable(const ParamIdx &I) const {
+ assert(isValid() && I.isValid() &&
+ "ParamIdx must be valid to be compared");
+ // It's possible to compare indices from separate functions, but so far
+ // it's not proven useful. Moreover, it might be confusing because a
+ // comparison on the results of getASTIndex might be inconsistent with a
+ // comparison on the ParamIdx objects themselves.
+ assert(HasThis == I.HasThis &&
+ "ParamIdx must be for the same function to be compared");
+ }
+
+public:
+ /// Construct an invalid parameter index (\c isValid returns false and
+ /// accessors fail an assert).
+ ParamIdx() : Idx(0), HasThis(false), IsValid(false) {}
+
+ /// \param Idx is the parameter index as it is normally specified in
+ /// attributes in the source: one-origin including any C++ implicit this
+ /// parameter.
+ ///
+ /// \param D is the declaration containing the parameters. It is used to
+ /// determine if there is a C++ implicit this parameter.
+ ParamIdx(unsigned Idx, const Decl *D)
+ : Idx(Idx), HasThis(false), IsValid(true) {
+ assert(Idx >= 1 && "Idx must be one-origin");
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ HasThis = FD->isCXXInstanceMember();
+ }
+
+ /// A type into which \c ParamIdx can be serialized.
+ ///
+ /// A static assertion that it's of the correct size follows the \c ParamIdx
+ /// class definition.
+ typedef uint32_t SerialType;
+
+ /// Produce a representation that can later be passed to \c deserialize to
+ /// construct an equivalent \c ParamIdx.
+ SerialType serialize() const {
+ return *reinterpret_cast<const SerialType *>(this);
+ }
+
+ /// Construct from a result from \c serialize.
+ static ParamIdx deserialize(SerialType S) {
+ ParamIdx P(*reinterpret_cast<ParamIdx *>(&S));
+ assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin");
+ return P;
+ }
+
+ /// Is this parameter index valid?
+ bool isValid() const { return IsValid; }
+
+ /// Get the parameter index as it would normally be encoded for attributes at
+ /// the source level of representation: one-origin including any C++ implicit
+ /// this parameter.
+ ///
+ /// This encoding thus makes sense for diagnostics, pretty printing, and
+ /// constructing new attributes from a source-like specification.
+ unsigned getSourceIndex() const {
+ assert(isValid() && "ParamIdx must be valid");
+ return Idx;
+ }
+
+ /// Get the parameter index as it would normally be encoded at the AST level
+ /// of representation: zero-origin not including any C++ implicit this
+ /// parameter.
+ ///
+ /// This is the encoding primarily used in Sema. However, in diagnostics,
+ /// Sema uses \c getSourceIndex instead.
+ unsigned getASTIndex() const {
+ assert(isValid() && "ParamIdx must be valid");
+ assert(Idx >= 1 + HasThis &&
+ "stored index must be base-1 and not specify C++ implicit this");
+ return Idx - 1 - HasThis;
+ }
+
+ /// Get the parameter index as it would normally be encoded at the LLVM level
+ /// of representation: zero-origin including any C++ implicit this parameter.
+ ///
+ /// This is the encoding primarily used in CodeGen.
+ unsigned getLLVMIndex() const {
+ assert(isValid() && "ParamIdx must be valid");
+ assert(Idx >= 1 && "stored index must be base-1");
+ return Idx - 1;
+ }
+
+ bool operator==(const ParamIdx &I) const {
+ assertComparable(I);
+ return Idx == I.Idx;
+ }
+ bool operator!=(const ParamIdx &I) const {
+ assertComparable(I);
+ return Idx != I.Idx;
+ }
+ bool operator<(const ParamIdx &I) const {
+ assertComparable(I);
+ return Idx < I.Idx;
+ }
+ bool operator>(const ParamIdx &I) const {
+ assertComparable(I);
+ return Idx > I.Idx;
+ }
+ bool operator<=(const ParamIdx &I) const {
+ assertComparable(I);
+ return Idx <= I.Idx;
+ }
+ bool operator>=(const ParamIdx &I) const {
+ assertComparable(I);
+ return Idx >= I.Idx;
+ }
+};
+
+static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
+ "ParamIdx does not fit its serialization type");
+
#include "clang/AST/Attrs.inc"
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
index 56807b4590d3..2087ecc0e70c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
@@ -106,7 +106,7 @@ public:
specific_attr_iterator Right) {
assert((Left.Current == nullptr) == (Right.Current == nullptr));
if (Left.Current < Right.Current)
- Left.AdvanceToNext(Right.Current);
+ Left.AdvanceToNext(Right.Current);
else
Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Availability.h b/contrib/llvm/tools/clang/include/clang/AST/Availability.h
index 5ed831378456..28f3c3c01d20 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Availability.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Availability.h
@@ -15,12 +15,12 @@
#define LLVM_CLANG_AST_AVAILABILITY_H
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
namespace clang {
-/// \brief One specifier in an @available expression.
+/// One specifier in an @available expression.
///
/// \code
/// @available(macos 10.10, *)
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h b/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
index fdb7e718fe9e..2b702c76b2fa 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
@@ -24,21 +24,21 @@ namespace clang {
class CXXRecordDecl;
-// BaseSubobject - Uniquely identifies a direct or indirect base class.
+// BaseSubobject - Uniquely identifies a direct or indirect base class.
// Stores both the base class decl and the offset from the most derived class to
// the base class. Used for vtable and VTT generation.
class BaseSubobject {
/// Base - The base class declaration.
const CXXRecordDecl *Base;
-
+
/// BaseOffset - The offset from the most derived class to the base class.
CharUnits BaseOffset;
-
+
public:
BaseSubobject() = default;
BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
: Base(Base), BaseOffset(BaseOffset) {}
-
+
/// getBase - Returns the base class declaration.
const CXXRecordDecl *getBase() const { return Base; }
@@ -74,7 +74,7 @@ template<> struct DenseMapInfo<clang::BaseSubobject> {
Base.getBaseOffset()));
}
- static bool isEqual(const clang::BaseSubobject &LHS,
+ static bool isEqual(const clang::BaseSubobject &LHS,
const clang::BaseSubobject &RHS) {
return LHS == RHS;
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
index e4f5f7db2f73..400efcb1981f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
@@ -72,6 +72,9 @@ UNSIGNED_TYPE(UChar, UnsignedCharTy)
// 'wchar_t' for targets where it's unsigned
SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy))
+// 'char8_t' in C++20 (proposed)
+UNSIGNED_TYPE(Char8, Char8Ty)
+
// 'char16_t' in C++
UNSIGNED_TYPE(Char16, Char16Ty)
@@ -119,6 +122,80 @@ SIGNED_TYPE(LongLong, LongLongTy)
// '__int128_t'
SIGNED_TYPE(Int128, Int128Ty)
+//===- Fixed point types --------------------------------------------------===//
+
+// 'short _Accum'
+SIGNED_TYPE(ShortAccum, ShortAccumTy)
+
+// '_Accum'
+SIGNED_TYPE(Accum, AccumTy)
+
+// 'long _Accum'
+SIGNED_TYPE(LongAccum, LongAccumTy)
+
+// 'unsigned short _Accum'
+UNSIGNED_TYPE(UShortAccum, UnsignedShortAccumTy)
+
+// 'unsigned _Accum'
+UNSIGNED_TYPE(UAccum, UnsignedAccumTy)
+
+// 'unsigned long _Accum'
+UNSIGNED_TYPE(ULongAccum, UnsignedLongAccumTy)
+
+// 'short _Fract'
+SIGNED_TYPE(ShortFract, ShortFractTy)
+
+// '_Fract'
+SIGNED_TYPE(Fract, FractTy)
+
+// 'long _Fract'
+SIGNED_TYPE(LongFract, LongFractTy)
+
+// 'unsigned short _Fract'
+UNSIGNED_TYPE(UShortFract, UnsignedShortFractTy)
+
+// 'unsigned _Fract'
+UNSIGNED_TYPE(UFract, UnsignedFractTy)
+
+// 'unsigned long _Fract'
+UNSIGNED_TYPE(ULongFract, UnsignedLongFractTy)
+
+// '_Sat short _Accum'
+SIGNED_TYPE(SatShortAccum, SatShortAccumTy)
+
+// '_Sat _Accum'
+SIGNED_TYPE(SatAccum, SatAccumTy)
+
+// '_Sat long _Accum'
+SIGNED_TYPE(SatLongAccum, SatLongAccumTy)
+
+// '_Sat unsigned short _Accum'
+UNSIGNED_TYPE(SatUShortAccum, SatUnsignedShortAccumTy)
+
+// '_Sat unsigned _Accum'
+UNSIGNED_TYPE(SatUAccum, SatUnsignedAccumTy)
+
+// '_Sat unsigned long _Accum'
+UNSIGNED_TYPE(SatULongAccum, SatUnsignedLongAccumTy)
+
+// '_Sat short _Fract'
+SIGNED_TYPE(SatShortFract, SatShortFractTy)
+
+// '_Sat _Fract'
+SIGNED_TYPE(SatFract, SatFractTy)
+
+// '_Sat long _Fract'
+SIGNED_TYPE(SatLongFract, SatLongFractTy)
+
+// '_Sat unsigned short _Fract'
+UNSIGNED_TYPE(SatUShortFract, SatUnsignedShortFractTy)
+
+// '_Sat unsigned _Fract'
+UNSIGNED_TYPE(SatUFract, SatUnsignedFractTy)
+
+// '_Sat unsigned long _Fract'
+UNSIGNED_TYPE(SatULongFract, SatUnsignedLongFractTy)
+
//===- Floating point types -----------------------------------------------===//
// 'half' in OpenCL, '__fp16' in ARM NEON.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
index 11fb229f0c09..f5e23f8e8505 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
@@ -34,25 +34,25 @@ namespace clang {
class ASTContext;
class NamedDecl;
-
-/// \brief Represents an element in a path from a derived class to a
-/// base class.
-///
+
+/// Represents an element in a path from a derived class to a
+/// base class.
+///
/// Each step in the path references the link from a
/// derived class to one of its direct base classes, along with a
/// base "number" that identifies which base subobject of the
/// original derived class we are referencing.
struct CXXBasePathElement {
- /// \brief The base specifier that states the link from a derived
+ /// The base specifier that states the link from a derived
/// class to a base class, which will be followed by this base
/// path element.
const CXXBaseSpecifier *Base;
-
- /// \brief The record decl of the class that the base is a base of.
+
+ /// The record decl of the class that the base is a base of.
const CXXRecordDecl *Class;
-
- /// \brief Identifies which base class subobject (of type
- /// \c Base->getType()) this base path element refers to.
+
+ /// Identifies which base class subobject (of type
+ /// \c Base->getType()) this base path element refers to.
///
/// This value is only valid if \c !Base->isVirtual(), because there
/// is no base numbering for the zero or one virtual bases of a
@@ -60,24 +60,24 @@ struct CXXBasePathElement {
int SubobjectNumber;
};
-/// \brief Represents a path from a specific derived class
+/// Represents a path from a specific derived class
/// (which is not represented as part of the path) to a particular
/// (direct or indirect) base class subobject.
///
-/// Individual elements in the path are described by the \c CXXBasePathElement
+/// Individual elements in the path are described by the \c CXXBasePathElement
/// structure, which captures both the link from a derived class to one of its
/// direct bases and identification describing which base class
/// subobject is being used.
class CXXBasePath : public SmallVector<CXXBasePathElement, 4> {
public:
- /// \brief The access along this inheritance path. This is only
+ /// 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 = AS_public;
CXXBasePath() = default;
- /// \brief The set of declarations found inside this base class
+ /// The set of declarations found inside this base class
/// subobject.
DeclContext::lookup_result Decls;
@@ -119,53 +119,58 @@ public:
class CXXBasePaths {
friend class CXXRecordDecl;
- /// \brief The type from which this search originated.
+ /// The type from which this search originated.
CXXRecordDecl *Origin = nullptr;
-
+
/// Paths - The actual set of paths that can be taken from the
/// derived class to the same base class.
std::list<CXXBasePath> Paths;
-
+
/// ClassSubobjects - Records the class subobjects for each class
- /// type that we've seen. The first element in the pair says
+ /// type that we've seen. The first element IsVirtBase says
/// whether we found a path to a virtual base for that class type,
- /// while the element contains the number of non-virtual base
+ /// while NumberOfNonVirtBases contains the number of non-virtual base
/// class subobjects for that class type. The key of the map is
/// the cv-unqualified canonical type of the base class subobject.
- llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
+ struct IsVirtBaseAndNumberNonVirtBases {
+ unsigned IsVirtBase : 1;
+ unsigned NumberOfNonVirtBases : 31;
+ };
+ llvm::SmallDenseMap<QualType, IsVirtBaseAndNumberNonVirtBases, 8>
+ ClassSubobjects;
/// VisitedDependentRecords - Records the dependent records that have been
/// already visited.
- llvm::SmallDenseSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
+
+ /// DetectedVirtual - The base class that is virtual.
+ const RecordType *DetectedVirtual = nullptr;
+
+ /// ScratchPath - A BasePath that is used by Sema::lookupInBases
+ /// to help build the set of paths.
+ CXXBasePath ScratchPath;
+
+ /// 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 = 0;
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
/// ambiguous paths while it is looking for a path from a derived
/// type to a base type.
bool FindAmbiguities;
-
+
/// RecordPaths - Whether Sema::IsDerivedFrom should record paths
/// while it is determining whether there are paths from a derived
/// type to a base type.
bool RecordPaths;
-
+
/// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
/// if it finds a path that goes across a virtual base. The virtual class
/// is also recorded.
bool DetectVirtual;
-
- /// ScratchPath - A BasePath that is used by Sema::lookupInBases
- /// to help build the set of paths.
- CXXBasePath ScratchPath;
- /// DetectedVirtual - The base class that is virtual.
- const RecordType *DetectedVirtual = 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 = 0;
-
void ComputeDeclsFound();
bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
@@ -176,7 +181,7 @@ public:
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,
@@ -188,61 +193,61 @@ public:
paths_iterator end() { return Paths.end(); }
const_paths_iterator begin() const { return Paths.begin(); }
const_paths_iterator end() const { return Paths.end(); }
-
+
CXXBasePath& front() { return Paths.front(); }
const CXXBasePath& front() const { return Paths.front(); }
-
+
using decl_range = llvm::iterator_range<decl_iterator>;
decl_range found_decls();
-
- /// \brief Determine whether the path from the most-derived type to the
+
+ /// Determine whether the path from the most-derived type to the
/// given base type is ambiguous (i.e., it refers to multiple subobjects of
/// the same base type).
bool isAmbiguous(CanQualType BaseType);
-
- /// \brief Whether we are finding multiple paths to detect ambiguities.
+
+ /// Whether we are finding multiple paths to detect ambiguities.
bool isFindingAmbiguities() const { return FindAmbiguities; }
-
- /// \brief Whether we are recording paths.
+
+ /// Whether we are recording paths.
bool isRecordingPaths() const { return RecordPaths; }
-
- /// \brief Specify whether we should be recording paths or not.
+
+ /// Specify whether we should be recording paths or not.
void setRecordingPaths(bool RP) { RecordPaths = RP; }
-
- /// \brief Whether we are detecting virtual bases.
+
+ /// Whether we are detecting virtual bases.
bool isDetectingVirtual() const { return DetectVirtual; }
-
- /// \brief The virtual base discovered on the path (if we are merely
+
+ /// The virtual base discovered on the path (if we are merely
/// detecting virtuals).
const RecordType* getDetectedVirtual() const {
return DetectedVirtual;
}
- /// \brief Retrieve the type from which this base-paths search
+ /// Retrieve the type from which this base-paths search
/// began
CXXRecordDecl *getOrigin() const { return Origin; }
void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
-
- /// \brief Clear the base-paths results.
+
+ /// Clear the base-paths results.
void clear();
-
- /// \brief Swap this data structure's contents with another CXXBasePaths
+
+ /// Swap this data structure's contents with another CXXBasePaths
/// object.
void swap(CXXBasePaths &Other);
};
-/// \brief Uniquely identifies a virtual method within a class
+/// Uniquely identifies a virtual method within a class
/// hierarchy by the method itself and a class subobject number.
struct UniqueVirtualMethod {
- /// \brief The overriding virtual method.
+ /// The overriding virtual method.
CXXMethodDecl *Method = nullptr;
- /// \brief The subobject in which the overriding virtual method
+ /// The subobject in which the overriding virtual method
/// resides.
unsigned Subobject = 0;
- /// \brief The virtual base class subobject of which this overridden
+ /// 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 = nullptr;
@@ -266,7 +271,7 @@ struct UniqueVirtualMethod {
}
};
-/// \brief The set of methods that override a given virtual method in
+/// The set of methods that override a given virtual method in
/// each subobject where it occurs.
///
/// The first part of the pair is the subobject in which the
@@ -310,7 +315,7 @@ public:
void replaceAll(UniqueVirtualMethod Overriding);
};
-/// \brief A mapping from each virtual member function to its set of
+/// A mapping from each virtual member function to its set of
/// final overriders.
///
/// Within a class hierarchy for a given derived class, each virtual
@@ -364,7 +369,7 @@ public:
class CXXFinalOverriderMap
: public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> {};
-/// \brief A set of all the primary bases for a class.
+/// A set of all the primary bases for a class.
class CXXIndirectPrimaryBaseSet
: public llvm::SmallSet<const CXXRecordDecl*, 32> {};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
index 6487613200de..0e738da43ad4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
@@ -44,7 +44,7 @@ class TemplateTypeParmDecl;
// Canonical, qualified type template
//----------------------------------------------------------------------------//
-/// \brief Represents a canonical, potentially-qualified type.
+/// Represents a canonical, potentially-qualified type.
///
/// The CanQual template is a lightweight smart pointer that provides access
/// to the canonical representation of a type, where all typedefs and other
@@ -64,44 +64,44 @@ class TemplateTypeParmDecl;
/// a call to ASTContext::getCanonicalType().
template<typename T = Type>
class CanQual {
- /// \brief The actual, canonical type.
+ /// The actual, canonical type.
QualType Stored;
public:
- /// \brief Constructs a NULL canonical type.
+ /// Constructs a NULL canonical type.
CanQual() = default;
- /// \brief Converting constructor that permits implicit upcasting of
+ /// Converting constructor that permits implicit upcasting of
/// canonical type pointers.
template <typename U>
CanQual(const CanQual<U> &Other,
typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0);
- /// \brief Retrieve the underlying type pointer, which refers to a
+ /// Retrieve the underlying type pointer, which refers to a
/// canonical type.
///
/// 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
+ /// Retrieve the underlying type pointer, which refers to a
/// canonical type, or nullptr.
- const T *getTypePtrOrNull() const {
- return cast_or_null<T>(Stored.getTypePtrOrNull());
+ const T *getTypePtrOrNull() const {
+ return cast_or_null<T>(Stored.getTypePtrOrNull());
}
- /// \brief Implicit conversion to a qualified type.
+ /// Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
- /// \brief Implicit conversion to bool.
+ /// Implicit conversion to bool.
explicit operator bool() const { return !isNull(); }
-
+
bool isNull() const {
return Stored.isNull();
}
SplitQualType split() const { return Stored.split(); }
- /// \brief Retrieve a canonical type pointer with a different static type,
+ /// Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
/// The getAs() function is typically used to try to downcast to a
@@ -122,17 +122,17 @@ public:
template<typename U> CanProxy<U> castAs() const;
- /// \brief Overloaded arrow operator that produces a canonical type
+ /// Overloaded arrow operator that produces a canonical type
/// proxy.
CanProxy<T> operator->() const;
- /// \brief Retrieve all qualifiers.
+ /// Retrieve all qualifiers.
Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
- /// \brief Retrieve the const/volatile/restrict qualifiers.
+ /// Retrieve the const/volatile/restrict qualifiers.
unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
- /// \brief Determines whether this type has any qualifiers
+ /// Determines whether this type has any qualifiers
bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
bool isConstQualified() const {
@@ -147,45 +147,45 @@ public:
return Stored.isLocalRestrictQualified();
}
- /// \brief Determines if this canonical type is furthermore
+ /// Determines if this canonical type is furthermore
/// canonical as a parameter. The parameter-canonicalization
/// process decays arrays to pointers and drops top-level qualifiers.
bool isCanonicalAsParam() const {
return Stored.isCanonicalAsParam();
}
- /// \brief Retrieve the unqualified form of this type.
+ /// Retrieve the unqualified form of this type.
CanQual<T> getUnqualifiedType() const;
- /// \brief Retrieves a version of this type with const applied.
+ /// Retrieves a version of this type with const applied.
/// Note that this does not always yield a canonical type.
QualType withConst() const {
return Stored.withConst();
}
- /// \brief Determines whether this canonical type is more qualified than
+ /// Determines whether this canonical type is more qualified than
/// the @p Other canonical type.
bool isMoreQualifiedThan(CanQual<T> Other) const {
return Stored.isMoreQualifiedThan(Other.Stored);
}
- /// \brief Determines whether this canonical type is at least as qualified as
+ /// Determines whether this canonical type is at least as qualified as
/// the @p Other canonical type.
bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
return Stored.isAtLeastAsQualifiedAs(Other.Stored);
}
- /// \brief If the canonical type is a reference type, returns the type that
+ /// If the canonical type is a reference type, returns the type that
/// it refers to; otherwise, returns the type itself.
CanQual<Type> getNonReferenceType() const;
- /// \brief Retrieve the internal representation of this canonical type.
+ /// Retrieve the internal representation of this canonical type.
void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
- /// \brief Construct a canonical type from its internal representation.
+ /// Construct a canonical type from its internal representation.
static CanQual<T> getFromOpaquePtr(void *Ptr);
- /// \brief Builds a canonical type from a QualType.
+ /// Builds a canonical type from a QualType.
///
/// This routine is inherently unsafe, because it requires the user to
/// ensure that the given type is a canonical type with the correct
@@ -209,7 +209,7 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) {
return x.getAsOpaquePtr() != y.getAsOpaquePtr();
}
-/// \brief Represents a canonical, potentially-qualified type.
+/// Represents a canonical, potentially-qualified type.
using CanQualType = CanQual<Type>;
inline CanQualType Type::getCanonicalTypeUnqualified() const {
@@ -234,7 +234,7 @@ return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
Type Accessor() const { return this->getTypePtr()->Accessor(); }
-/// \brief Base class of all canonical proxy types, which is responsible for
+/// Base class of all canonical proxy types, which is responsible for
/// storing the underlying canonical type and providing basic conversions.
template<typename T>
class CanProxyBase {
@@ -242,10 +242,10 @@ protected:
CanQual<T> Stored;
public:
- /// \brief Retrieve the pointer to the underlying Type
+ /// Retrieve the pointer to the underlying Type
const T *getTypePtr() const { return Stored.getTypePtr(); }
- /// \brief Implicit conversion to the underlying pointer.
+ /// Implicit conversion to the underlying pointer.
///
/// Also provides the ability to use canonical type proxies in a Boolean
// context,e.g.,
@@ -254,7 +254,7 @@ public:
/// @endcode
operator const T*() const { return this->Stored.getTypePtrOrNull(); }
- /// \brief Try to convert the given canonical type to a specific structural
+ /// Try to convert the given canonical type to a specific structural
/// type.
template<typename U> CanProxy<U> getAs() const {
return this->Stored.template getAs<U>();
@@ -313,7 +313,7 @@ public:
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
- /// \brief Retrieve the proxy-adaptor type.
+ /// Retrieve the proxy-adaptor type.
///
/// This arrow operator is used when CanProxyAdaptor has been specialized
/// for the given type T. In that case, we reference members of the
@@ -324,7 +324,7 @@ public:
}
};
-/// \brief Replacable canonical proxy adaptor class that provides the link
+/// Replaceable canonical proxy adaptor class that provides the link
/// between a canonical type and the accessors of the type.
///
/// The CanProxyAdaptor is a replaceable class template that is instantiated
@@ -337,7 +337,7 @@ public:
template<typename T>
struct CanProxyAdaptor : CanProxyBase<T> {};
-/// \brief Canonical proxy type returned when retrieving the members of a
+/// Canonical proxy type returned when retrieving the members of a
/// canonical type or as the result of the @c CanQual<T>::getAs member
/// function.
///
@@ -347,13 +347,13 @@ struct CanProxyAdaptor : CanProxyBase<T> {};
template<typename T>
class CanProxy : public CanProxyAdaptor<T> {
public:
- /// \brief Build a NULL proxy.
+ /// Build a NULL proxy.
CanProxy() = default;
- /// \brief Build a proxy to the given canonical type.
+ /// Build a proxy to the given canonical type.
CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
- /// \brief Implicit conversion to the stored canonical type.
+ /// Implicit conversion to the stored canonical type.
operator CanQual<T>() const { return this->Stored; }
};
@@ -396,7 +396,7 @@ namespace clang {
// Canonical proxy adaptors for canonical type nodes.
//----------------------------------------------------------------------------//
-/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
+/// Iterator adaptor that turns an iterator over canonical QualTypes
/// into an iterator over CanQualTypes.
template <typename InputIterator>
struct CanTypeIterator
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
index ddead6046a14..0aadf06fffc9 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
@@ -61,7 +61,7 @@ namespace clang {
/// fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits fromQuantity(QuantityType Quantity) {
- return CharUnits(Quantity);
+ return CharUnits(Quantity);
}
// Compound assignment.
@@ -87,7 +87,7 @@ namespace clang {
CharUnits operator-- (int) {
return CharUnits(Quantity--);
}
-
+
// Comparison operators.
bool operator== (const CharUnits &Other) const {
return Quantity == Other.Quantity;
@@ -97,21 +97,21 @@ namespace clang {
}
// Relational operators.
- bool operator< (const CharUnits &Other) const {
- return Quantity < Other.Quantity;
+ bool operator< (const CharUnits &Other) const {
+ return Quantity < Other.Quantity;
}
- bool operator<= (const CharUnits &Other) const {
+ bool operator<= (const CharUnits &Other) const {
return Quantity <= Other.Quantity;
}
- bool operator> (const CharUnits &Other) const {
- return Quantity > Other.Quantity;
+ bool operator> (const CharUnits &Other) const {
+ return Quantity > Other.Quantity;
}
- bool operator>= (const CharUnits &Other) const {
- return Quantity >= Other.Quantity;
+ bool operator>= (const CharUnits &Other) const {
+ return Quantity >= Other.Quantity;
}
// Other predicates.
-
+
/// isZero - Test whether the quantity equals zero.
bool isZero() const { return Quantity == 0; }
@@ -172,7 +172,7 @@ namespace clang {
return CharUnits(-Quantity);
}
-
+
// Conversions.
/// getQuantity - Get the raw integer representation of this quantity.
@@ -205,7 +205,7 @@ namespace clang {
}; // class CharUnit
} // namespace clang
-inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
+inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
const clang::CharUnits &CU) {
return CU * Scale;
}
@@ -223,8 +223,8 @@ template<> struct DenseMapInfo<clang::CharUnits> {
static clang::CharUnits getTombstoneKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
-
- return clang::CharUnits::fromQuantity(Quantity);
+
+ return clang::CharUnits::fromQuantity(Quantity);
}
static unsigned getHashValue(const clang::CharUnits &CU) {
@@ -232,7 +232,7 @@ template<> struct DenseMapInfo<clang::CharUnits> {
return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
}
- static bool isEqual(const clang::CharUnits &LHS,
+ static bool isEqual(const clang::CharUnits &LHS,
const clang::CharUnits &RHS) {
return LHS == RHS;
}
@@ -241,7 +241,7 @@ template<> struct DenseMapInfo<clang::CharUnits> {
template <> struct isPodLike<clang::CharUnits> {
static const bool value = true;
};
-
+
} // end namespace llvm
#endif // LLVM_CLANG_AST_CHARUNITS_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Comment.h b/contrib/llvm/tools/clang/include/clang/AST/Comment.h
index 94470cbf305f..f5538dec2a14 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Comment.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Comment.h
@@ -98,7 +98,7 @@ protected:
unsigned RenderKind : 2;
unsigned CommandID : CommandInfo::NumCommandIDBits;
};
- enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
+ enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
CommandInfo::NumCommandIDBits };
class HTMLTagCommentBitfields {
@@ -146,7 +146,7 @@ protected:
/// Contains values from CommandMarkerKind enum.
unsigned CommandMarker : 1;
};
- enum { NumBlockCommandCommentBits = NumCommentBits +
+ enum { NumBlockCommandCommentBits = NumCommentBits +
CommandInfo::NumCommandIDBits + 1 };
class ParamCommandCommentBitfields {
@@ -987,17 +987,17 @@ struct DeclInfo {
/// Declaration the comment is actually attached to (in the source).
/// Should not be NULL.
const Decl *CommentDecl;
-
+
/// CurrentDecl is the declaration with which the FullComment is associated.
///
- /// It can be different from \c CommentDecl. It happens when we we decide
+ /// It can be different from \c CommentDecl. It happens when we decide
/// that the comment originally attached to \c CommentDecl is fine for
/// \c CurrentDecl too (for example, for a redeclaration or an overrider of
/// \c CommentDecl).
///
/// The information in the DeclInfo corresponds to CurrentDecl.
const Decl *CurrentDecl;
-
+
/// Parameters that can be referenced by \\param if \c CommentDecl is something
/// that we consider a "function".
ArrayRef<const ParmVarDecl *> ParamVars;
@@ -1119,21 +1119,21 @@ public:
}
child_iterator child_end() const {
- return reinterpret_cast<child_iterator>(Blocks.end());
+ return reinterpret_cast<child_iterator>(Blocks.end());
}
const Decl *getDecl() const LLVM_READONLY {
return ThisDeclInfo->CommentDecl;
}
-
+
const DeclInfo *getDeclInfo() const LLVM_READONLY {
if (!ThisDeclInfo->IsFilled)
ThisDeclInfo->fill();
return ThisDeclInfo;
}
-
+
ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
-
+
};
} // end namespace comments
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h b/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h
index be5b8eeb80c3..baa22930539e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h
@@ -24,7 +24,7 @@ namespace comments {
///
/// Due to a variety of comment styles, it considers the following as "a brief
/// description", in order of priority:
-/// \li a \\brief or \\short command,
+/// \li a \or \\short command,
/// \li the first paragraph,
/// \li a \\result or \\return or \\returns paragraph.
class BriefParser {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h b/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h
index 289f2fd345af..4fd007872c01 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h
@@ -26,7 +26,7 @@
namespace clang {
namespace comments {
-/// \brief Information about a single command.
+/// Information about a single command.
///
/// When reordering, adding or removing members please update the corresponding
/// TableGen backend.
@@ -57,7 +57,7 @@ struct CommandInfo {
unsigned IsBlockCommand : 1;
/// True if this command is introducing a brief documentation
- /// paragraph (\\brief or an alias).
+ /// paragraph (\or an alias).
unsigned IsBriefCommand : 1;
/// True if this command is \\returns or an alias.
@@ -77,29 +77,29 @@ struct CommandInfo {
/// True if this command is \\deprecated or an alias.
unsigned IsDeprecatedCommand : 1;
- /// \brief True if this is a \\headerfile-like command.
+ /// True if this is a \\headerfile-like command.
unsigned IsHeaderfileCommand : 1;
/// True if we don't want to warn about this command being passed an empty
/// paragraph. Meaningful only for block commands.
unsigned IsEmptyParagraphAllowed : 1;
- /// \brief True if this command is a verbatim-like block command.
+ /// True if this command is a verbatim-like block command.
///
/// A verbatim-like block command eats every character (except line starting
/// decorations) until matching end command is seen or comment end is hit.
unsigned IsVerbatimBlockCommand : 1;
- /// \brief True if this command is an end command for a verbatim-like block.
+ /// True if this command is an end command for a verbatim-like block.
unsigned IsVerbatimBlockEndCommand : 1;
- /// \brief True if this command is a verbatim line command.
+ /// True if this command is a verbatim line command.
///
/// A verbatim-like line command eats everything until a newline is seen or
/// comment end is hit.
unsigned IsVerbatimLineCommand : 1;
- /// \brief True if this command contains a declaration for the entity being
+ /// True if this command contains a declaration for the entity being
/// documented.
///
/// For example:
@@ -107,18 +107,18 @@ struct CommandInfo {
/// \fn void f(int a);
/// \endcode
unsigned IsDeclarationCommand : 1;
-
- /// \brief True if verbatim-like line command is a function declaration.
+
+ /// True if verbatim-like line command is a function declaration.
unsigned IsFunctionDeclarationCommand : 1;
- /// \brief True if block command is further describing a container API; such
+ /// True if block command is further describing a container API; such
/// as \@coclass, \@classdesign, etc.
unsigned IsRecordLikeDetailCommand : 1;
-
- /// \brief True if block command is a container API; such as \@interface.
+
+ /// True if block command is a container API; such as \@interface.
unsigned IsRecordLikeDeclarationCommand : 1;
-
- /// \brief True if this command is unknown. This \c CommandInfo object was
+
+ /// True if this command is unknown. This \c CommandInfo object was
/// created during parsing.
unsigned IsUnknownCommand : 1;
};
@@ -150,7 +150,7 @@ public:
}
const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const;
-
+
const CommandInfo *getCommandInfo(unsigned CommandID) const;
const CommandInfo *registerUnknownCommand(StringRef CommandName);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h b/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h
index 5bb075807be5..3ef5b7c8c998 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h
@@ -52,7 +52,7 @@ enum TokenKind {
};
} // end namespace tok
-/// \brief Comment token.
+/// Comment token.
class Token {
friend class Lexer;
friend class TextTokenRetokenizer;
@@ -72,11 +72,11 @@ class Token {
/// Integer value associated with a token.
///
- /// If the token is a konwn command, contains command ID and TextPtr is
+ /// If the token is a known command, contains command ID and TextPtr is
/// unused (command spelling can be found with CommandTraits). Otherwise,
/// contains the length of the string that starts at TextPtr.
unsigned IntVal;
-
+
public:
SourceLocation getLocation() const LLVM_READONLY { return Loc; }
void setLocation(SourceLocation SL) { Loc = SL; }
@@ -217,7 +217,7 @@ public:
void dump(const Lexer &L, const SourceManager &SM) const;
};
-/// \brief Comment lexer.
+/// Comment lexer.
class Lexer {
private:
Lexer(const Lexer &) = delete;
@@ -228,7 +228,7 @@ private:
llvm::BumpPtrAllocator &Allocator;
DiagnosticsEngine &Diags;
-
+
const CommandTraits &Traits;
const char *const BufferStart;
@@ -281,6 +281,11 @@ private:
/// command, including command marker.
SmallString<16> VerbatimBlockEndCommandName;
+ /// If true, the commands, html tags, etc will be parsed and reported as
+ /// separate tokens inside the comment body. If false, the comment text will
+ /// be parsed into text and newline tokens.
+ bool ParseCommands;
+
/// Given a character reference name (e.g., "lt"), return the character that
/// it stands for (e.g., "<").
StringRef resolveHTMLNamedCharacterReference(StringRef Name) const;
@@ -315,12 +320,11 @@ private:
/// Eat string matching regexp \code \s*\* \endcode.
void skipLineStartingDecorations();
- /// Lex stuff inside comments. CommentEnd should be set correctly.
+ /// Lex comment text, including commands if ParseCommands is set to true.
void lexCommentText(Token &T);
- void setupAndLexVerbatimBlock(Token &T,
- const char *TextBegin,
- char Marker, const CommandInfo *Info);
+ void setupAndLexVerbatimBlock(Token &T, const char *TextBegin, char Marker,
+ const CommandInfo *Info);
void lexVerbatimBlockFirstLine(Token &T);
@@ -343,14 +347,13 @@ private:
public:
Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags,
- const CommandTraits &Traits,
- SourceLocation FileLoc,
- const char *BufferStart, const char *BufferEnd);
+ const CommandTraits &Traits, SourceLocation FileLoc,
+ const char *BufferStart, const char *BufferEnd,
+ bool ParseCommands = true);
void lex(Token &T);
- StringRef getSpelling(const Token &Tok,
- const SourceManager &SourceMgr,
+ StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr,
bool *Invalid = nullptr) const;
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
index 230e52739f24..632eba782b92 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
@@ -55,7 +55,7 @@ class Sema {
/// Contains a valid value if \c DeclInfo->IsFilled is true.
llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
- /// AST node for the \\brief command and its aliases.
+ /// AST node for the \command and its aliases.
const BlockCommandComment *BriefCommand;
/// AST node for the \\headerfile command.
@@ -187,15 +187,15 @@ public:
void checkReturnsCommand(const BlockCommandComment *Command);
/// Emit diagnostics about duplicate block commands that should be
- /// used only once per comment, e.g., \\brief and \\returns.
+ /// used only once per comment, e.g., \and \\returns.
void checkBlockCommandDuplicate(const BlockCommandComment *Command);
void checkDeprecatedCommand(const BlockCommandComment *Comment);
-
+
void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment);
-
+
void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment);
-
+
void checkContainerDecl(const BlockCommandComment *Comment);
/// Resolve parameter names to parameter indexes in function declaration.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ComparisonCategories.h b/contrib/llvm/tools/clang/include/clang/AST/ComparisonCategories.h
new file mode 100644
index 000000000000..23bfd708e7eb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ComparisonCategories.h
@@ -0,0 +1,243 @@
+//===- ComparisonCategories.h - Three Way Comparison Data -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Comparison Category enum and data types, which
+// store the types and expressions needed to support operator<=>
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H
+#define LLVM_CLANG_AST_COMPARISONCATEGORIES_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include <array>
+#include <cassert>
+
+namespace llvm {
+ class StringRef;
+ class APSInt;
+}
+
+namespace clang {
+
+class ASTContext;
+class VarDecl;
+class CXXRecordDecl;
+class Sema;
+class QualType;
+class NamespaceDecl;
+
+/// An enumeration representing the different comparison categories
+/// types.
+///
+/// C++2a [cmp.categories.pre] The types weak_equality, strong_equality,
+/// partial_ordering, weak_ordering, and strong_ordering are collectively
+/// termed the comparison category types.
+enum class ComparisonCategoryType : unsigned char {
+ WeakEquality,
+ StrongEquality,
+ PartialOrdering,
+ WeakOrdering,
+ StrongOrdering,
+ First = WeakEquality,
+ Last = StrongOrdering
+};
+
+/// An enumeration representing the possible results of a three-way
+/// comparison. These values map onto instances of comparison category types
+/// defined in the standard library. e.g. 'std::strong_ordering::less'.
+enum class ComparisonCategoryResult : unsigned char {
+ Equal,
+ Equivalent,
+ Nonequivalent,
+ Nonequal,
+ Less,
+ Greater,
+ Unordered,
+ Last = Unordered
+};
+
+class ComparisonCategoryInfo {
+ friend class ComparisonCategories;
+ friend class Sema;
+
+public:
+ ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD,
+ ComparisonCategoryType Kind)
+ : Ctx(Ctx), Record(RD), Kind(Kind) {}
+
+ struct ValueInfo {
+ ComparisonCategoryResult Kind;
+ VarDecl *VD;
+
+ ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
+ : Kind(Kind), VD(VD) {}
+
+ /// True iff we've successfully evaluated the variable as a constant
+ /// expression and extracted its integer value.
+ bool hasValidIntValue() const;
+
+ /// Get the constant integer value used by this variable to represent
+ /// the comparison category result type.
+ llvm::APSInt getIntValue() const;
+ };
+private:
+ const ASTContext &Ctx;
+
+ /// A map containing the comparison category result decls from the
+ /// standard library. The key is a value of ComparisonCategoryResult.
+ mutable llvm::SmallVector<
+ ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
+ Objects;
+
+ /// Lookup the ValueInfo struct for the specified ValueKind. If the
+ /// VarDecl for the value cannot be found, nullptr is returned.
+ ///
+ /// If the ValueInfo does not have a valid integer value the variable
+ /// is evaluated as a constant expression to determine that value.
+ ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
+
+public:
+ /// The declaration for the comparison category type from the
+ /// standard library.
+ // FIXME: Make this const
+ CXXRecordDecl *Record = nullptr;
+
+ /// The Kind of the comparison category type
+ ComparisonCategoryType Kind;
+
+public:
+ QualType getType() const;
+
+ const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
+ ValueInfo *Info = lookupValueInfo(ValueKind);
+ assert(Info &&
+ "comparison category does not contain the specified result kind");
+ assert(Info->hasValidIntValue() &&
+ "couldn't determine the integer constant for this value");
+ return Info;
+ }
+
+ /// True iff the comparison category is an equality comparison.
+ bool isEquality() const { return !isOrdered(); }
+
+ /// True iff the comparison category is a relational comparison.
+ bool isOrdered() const {
+ using CCK = ComparisonCategoryType;
+ return Kind == CCK::PartialOrdering || Kind == CCK::WeakOrdering ||
+ Kind == CCK::StrongOrdering;
+ }
+
+ /// True iff the comparison is "strong". i.e. it checks equality and
+ /// not equivalence.
+ bool isStrong() const {
+ using CCK = ComparisonCategoryType;
+ return Kind == CCK::StrongEquality || Kind == CCK::StrongOrdering;
+ }
+
+ /// True iff the comparison is not totally ordered.
+ bool isPartial() const {
+ using CCK = ComparisonCategoryType;
+ return Kind == CCK::PartialOrdering;
+ }
+
+ /// Converts the specified result kind into the the correct result kind
+ /// for this category. Specifically it lowers strong equality results to
+ /// weak equivalence if needed.
+ ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const {
+ using CCR = ComparisonCategoryResult;
+ if (!isStrong()) {
+ if (Res == CCR::Equal)
+ return CCR::Equivalent;
+ if (Res == CCR::Nonequal)
+ return CCR::Nonequivalent;
+ }
+ return Res;
+ }
+
+ const ValueInfo *getEqualOrEquiv() const {
+ return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
+ }
+ const ValueInfo *getNonequalOrNonequiv() const {
+ assert(isEquality());
+ return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal));
+ }
+ const ValueInfo *getLess() const {
+ assert(isOrdered());
+ return getValueInfo(ComparisonCategoryResult::Less);
+ }
+ const ValueInfo *getGreater() const {
+ assert(isOrdered());
+ return getValueInfo(ComparisonCategoryResult::Greater);
+ }
+ const ValueInfo *getUnordered() const {
+ assert(isPartial());
+ return getValueInfo(ComparisonCategoryResult::Unordered);
+ }
+};
+
+class ComparisonCategories {
+public:
+ static StringRef getCategoryString(ComparisonCategoryType Kind);
+ static StringRef getResultString(ComparisonCategoryResult Kind);
+
+ /// Return the list of results which are valid for the specified
+ /// comparison category type.
+ static std::vector<ComparisonCategoryResult>
+ getPossibleResultsForType(ComparisonCategoryType Type);
+
+ /// Return the comparison category information for the category
+ /// specified by 'Kind'.
+ const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const {
+ const ComparisonCategoryInfo *Result = lookupInfo(Kind);
+ assert(Result != nullptr &&
+ "information for specified comparison category has not been built");
+ return *Result;
+ }
+
+ /// Return the comparison category information as specified by
+ /// `getCategoryForType(Ty)`. If the information is not already cached,
+ /// the declaration is looked up and a cache entry is created.
+ /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
+ /// possible.
+ const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
+
+public:
+ /// Return the cached comparison category information for the
+ /// specified 'Kind'. If no cache entry is present the comparison category
+ /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
+ /// new cache entry is created and returned
+ const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
+
+ ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
+ const auto &This = *this;
+ return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
+ }
+
+private:
+ const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
+
+private:
+ friend class ASTContext;
+
+ explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
+
+ const ASTContext &Ctx;
+
+ /// A map from the ComparisonCategoryType (represented as 'char') to the
+ /// cached information for the specified category.
+ mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
+ mutable NamespaceDecl *StdNS = nullptr;
+};
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h b/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h
index 229ac2bd0f22..8b2a8345d941 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file declares helper methods for collecting data from AST nodes.
+/// 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:
+/// that the 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
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
index 04a832e552a4..ebdb2890daf5 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -76,14 +76,14 @@ class TypeLoc;
class UnresolvedSetImpl;
class VarTemplateDecl;
-/// \brief A container of type source information.
+/// A container of type source information.
///
/// A client can read the relevant info using TypeLoc wrappers, e.g:
/// @code
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
/// TL.getStartLoc().print(OS, SrcMgr);
/// @endcode
-class TypeSourceInfo {
+class alignas(8) TypeSourceInfo {
// Contains a memory block after the class, used for type source information,
// allocated by ASTContext.
friend class ASTContext;
@@ -93,17 +93,17 @@ class TypeSourceInfo {
TypeSourceInfo(QualType ty) : Ty(ty) {}
public:
- /// \brief Return the type wrapped by this type source info.
+ /// Return the type wrapped by this type source info.
QualType getType() const { return Ty; }
- /// \brief Return the TypeLoc wrapper for the type source info.
+ /// Return the TypeLoc wrapper for the type source info.
TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
-
- /// \brief Override the type stored in this TypeSourceInfo. Use with caution!
+
+ /// Override the type stored in this TypeSourceInfo. Use with caution!
void overrideType(QualType T) { Ty = T; }
};
-/// TranslationUnitDecl - The top declaration context.
+/// The top declaration context.
class TranslationUnitDecl : public Decl, public DeclContext {
ASTContext &Ctx;
@@ -134,7 +134,7 @@ public:
}
};
-/// \brief Represents a `#pragma comment` line. Always a child of
+/// Represents a `#pragma comment` line. Always a child of
/// TranslationUnitDecl.
class PragmaCommentDecl final
: public Decl,
@@ -168,7 +168,7 @@ public:
static bool classofKind(Kind K) { return K == PragmaComment; }
};
-/// \brief Represents a `#pragma detect_mismatch` line. Always a child of
+/// Represents a `#pragma detect_mismatch` line. Always a child of
/// TranslationUnitDecl.
class PragmaDetectMismatchDecl final
: public Decl,
@@ -201,7 +201,7 @@ public:
static bool classofKind(Kind K) { return K == PragmaDetectMismatch; }
};
-/// \brief Declaration context for names declared as extern "C" in C++. This
+/// Declaration context for names declared as extern "C" in C++. This
/// is neither the semantic nor lexical context for such declarations, but is
/// used to check for conflicts with other extern "C" declarations. Example:
///
@@ -240,10 +240,13 @@ public:
}
};
-/// NamedDecl - This represents a decl with a name. Many decls have names such
+/// This represents a decl that may have a name. Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
+///
+/// Note that not every NamedDecl is actually named (e.g., a struct might
+/// be anonymous), and not every name is an identifier.
class NamedDecl : public Decl {
- /// Name - The name of this declaration, which is typically a normal
+ /// 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;
@@ -258,13 +261,15 @@ protected:
: Decl(DK, DC, L), Name(N) {}
public:
- /// getIdentifier - Get the identifier that names this declaration,
- /// if there is one. This will return NULL if this declaration has
- /// no name (e.g., for an unnamed class) or if the name is a special
- /// name (C++ constructor, Objective-C selector, etc.).
+ /// Get the identifier that names this declaration, if there is one.
+ ///
+ /// This will return NULL if this declaration has no name (e.g., for
+ /// an unnamed class) or if the name is a special name (C++ constructor,
+ /// Objective-C selector, etc.).
IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }
- /// getName - Get the name of identifier for this declaration as a StringRef.
+ /// Get the name of identifier for this declaration as a StringRef.
+ ///
/// This requires that the declaration have a name and that it be a simple
/// identifier.
StringRef getName() const {
@@ -272,11 +277,12 @@ public:
return getIdentifier() ? getIdentifier()->getName() : "";
}
- /// getNameAsString - Get a human-readable name for the declaration, even if
- /// it is one of the special kinds of names (C++ constructor, Objective-C
- /// selector, etc). Creating this name requires expensive string
- /// manipulation, so it should be called only when performance doesn't matter.
- /// For simple declarations, getNameAsCString() should suffice.
+ /// Get a human-readable name for the declaration, even if it is one of the
+ /// special kinds of names (C++ constructor, Objective-C selector, etc).
+ ///
+ /// Creating this name requires expensive string manipulation, so it should
+ /// be called only when performance doesn't matter. For simple declarations,
+ /// getNameAsCString() should suffice.
//
// FIXME: This function should be renamed to indicate that it is not just an
// alternate form of getName(), and clients should move as appropriate.
@@ -286,17 +292,19 @@ public:
virtual void printName(raw_ostream &os) const;
- /// getDeclName - Get the actual, stored name of the declaration,
- /// which may be a special name.
+ /// Get the actual, stored name of the declaration, which may be a special
+ /// name.
DeclarationName getDeclName() const { return Name; }
- /// \brief Set the name of this declaration.
+ /// Set the name of this declaration.
void setDeclName(DeclarationName N) { Name = N; }
- /// printQualifiedName - Returns human-readable qualified name for
- /// declaration, like A::B::i, for i being member of namespace A::B.
- /// If declaration is not member of context which can be named (record,
- /// namespace), it will return same result as printName().
+ /// Returns a human-readable qualified name for this declaration, like
+ /// A::B::i, for i being member of namespace A::B.
+ ///
+ /// If the declaration is not a member of context which can be named (record,
+ /// namespace), it will return the same result as printName().
+ ///
/// Creating this name is expensive, so it should be called only when
/// performance doesn't matter.
void printQualifiedName(raw_ostream &OS) const;
@@ -315,25 +323,25 @@ public:
const PrintingPolicy &Policy,
bool Qualified) const;
- /// \brief Determine whether this declaration, if
- /// known to be well-formed within its context, will replace the
- /// declaration OldD if introduced into scope. A declaration will
- /// replace another declaration if, for example, it is a
- /// redeclaration of the same variable or function, but not if it is
- /// a declaration of a different kind (function vs. class) or an
- /// overloaded function.
+ /// Determine whether this declaration, if known to be well-formed within
+ /// its context, will replace the declaration OldD if introduced into scope.
+ ///
+ /// A declaration will replace another declaration if, for example, it is
+ /// a redeclaration of the same variable or function, but not if it is a
+ /// declaration of a different kind (function vs. class) or an overloaded
+ /// function.
///
/// \param IsKnownNewer \c true if this declaration is known to be newer
/// than \p OldD (for instance, if this declaration is newly-created).
bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const;
- /// \brief Determine whether this declaration has linkage.
+ /// Determine whether this declaration has linkage.
bool hasLinkage() const;
using Decl::isModulePrivate;
using Decl::setModulePrivate;
- /// \brief Determine whether this declaration is a C++ class member.
+ /// Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
@@ -346,23 +354,24 @@ public:
return DC->isRecord();
}
- /// \brief Determine whether the given declaration is an instance member of
+ /// Determine whether the given declaration is an instance member of
/// a C++ class.
bool isCXXInstanceMember() const;
- /// \brief Determine what kind of linkage this entity has.
+ /// Determine what kind of linkage this entity has.
+ ///
/// This is not the linkage as defined by the standard or the codegen notion
/// of linkage. It is just an implementation detail that is used to compute
/// those.
Linkage getLinkageInternal() const;
- /// \brief Get the linkage from a semantic point of view. Entities in
+ /// Get the linkage from a semantic point of view. Entities in
/// anonymous namespaces are external (in c++98).
Linkage getFormalLinkage() const {
return clang::getFormalLinkage(getLinkageInternal());
}
- /// \brief True if this decl has external linkage.
+ /// True if this decl has external linkage.
bool hasExternalFormalLinkage() const {
return isExternalFormalLinkage(getLinkageInternal());
}
@@ -377,12 +386,12 @@ public:
return isExternallyVisible() && !getOwningModuleForLinkage();
}
- /// \brief Determines the visibility of this entity.
+ /// Determines the visibility of this entity.
Visibility getVisibility() const {
return getLinkageAndVisibility().getVisibility();
}
- /// \brief Determines the linkage and visibility of this entity.
+ /// Determines the linkage and visibility of this entity.
LinkageInfo getLinkageAndVisibility() const;
/// Kinds of explicit visibility.
@@ -398,16 +407,16 @@ public:
VisibilityForValue
};
- /// \brief If visibility was explicitly specified for this
+ /// If visibility was explicitly specified for this
/// declaration, return that visibility.
Optional<Visibility>
getExplicitVisibility(ExplicitVisibilityKind kind) const;
- /// \brief True if the computed linkage is valid. Used for consistency
+ /// True if the computed linkage is valid. Used for consistency
/// checking. Should always return true.
bool isLinkageValid() const;
- /// \brief True if something has required us to compute the linkage
+ /// True if something has required us to compute the linkage
/// of this declaration.
///
/// Language features which can retroactively change linkage (like a
@@ -417,7 +426,7 @@ public:
return hasCachedLinkage();
}
- /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
+ /// Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.
NamedDecl *getUnderlyingDecl() {
// Fast-path the common case.
@@ -451,7 +460,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
return OS;
}
-/// LabelDecl - Represents the declaration of a label. Labels also have a
+/// Represents the declaration of a label. Labels also have a
/// corresponding LabelStmt, which indicates the position that the label was
/// defined at. For normal labels, the location of the decl is the same as the
/// location of the statement. For GNU local labels (__label__), the decl
@@ -461,7 +470,7 @@ class LabelDecl : public NamedDecl {
StringRef MSAsmName;
bool MSAsmNameResolved = false;
- /// LocStart - For normal labels, this is the same as the main declaration
+ /// For normal labels, this is the same as the main declaration
/// label, i.e., the location of the identifier; for GNU local labels,
/// this is the location of the __label__ keyword.
SourceLocation LocStart;
@@ -479,7 +488,7 @@ public:
SourceLocation IdentL, IdentifierInfo *II,
SourceLocation GnuLabelL);
static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
LabelStmt *getStmt() const { return TheStmt; }
void setStmt(LabelStmt *T) { TheStmt = T; }
@@ -501,20 +510,20 @@ public:
static bool classofKind(Kind K) { return K == Label; }
};
-/// NamespaceDecl - Represent a C++ namespace.
-class NamespaceDecl : public NamedDecl, public DeclContext,
- public Redeclarable<NamespaceDecl>
+/// Represent a C++ namespace.
+class NamespaceDecl : public NamedDecl, public DeclContext,
+ public Redeclarable<NamespaceDecl>
{
- /// LocStart - The starting location of the source range, pointing
+ /// 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.
+ /// The ending location of the source range.
SourceLocation RBraceLoc;
- /// \brief A pointer to either the anonymous namespace that lives just inside
+ /// A pointer to either the anonymous namespace that lives just inside
/// this namespace or to the first namespace in the chain (the latter case
- /// only when this is not the first in the chain), along with a
+ /// only when this is not the first in the chain), along with a
/// boolean value indicating whether this is an inline namespace.
llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline;
@@ -549,7 +558,7 @@ public:
using redeclarable_base::getMostRecentDecl;
using redeclarable_base::isFirstDecl;
- /// \brief Returns true if this is an anonymous namespace declaration.
+ /// Returns true if this is an anonymous namespace declaration.
///
/// For example:
/// \code
@@ -562,28 +571,28 @@ public:
return !getIdentifier();
}
- /// \brief Returns true if this is an inline namespace declaration.
+ /// Returns true if this is an inline namespace declaration.
bool isInline() const {
return AnonOrFirstNamespaceAndInline.getInt();
}
- /// \brief Set whether this is an inline namespace declaration.
+ /// Set whether this is an inline namespace declaration.
void setInline(bool Inline) {
AnonOrFirstNamespaceAndInline.setInt(Inline);
}
- /// \brief Get the original (first) namespace declaration.
+ /// Get the original (first) namespace declaration.
NamespaceDecl *getOriginalNamespace();
- /// \brief Get the original (first) namespace declaration.
+ /// Get the original (first) namespace declaration.
const NamespaceDecl *getOriginalNamespace() const;
- /// \brief Return true if this declaration is an original (first) declaration
+ /// Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
bool isOriginalNamespace() const;
- /// \brief Retrieve the anonymous namespace nested inside this namespace,
+ /// Retrieve the anonymous namespace nested inside this namespace,
/// if any.
NamespaceDecl *getAnonymousNamespace() const {
return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer();
@@ -621,7 +630,7 @@ public:
}
};
-/// ValueDecl - Represent the declaration of a variable (in which case it is
+/// 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 {
@@ -638,7 +647,7 @@ public:
QualType getType() const { return DeclType; }
void setType(QualType newType) { DeclType = newType; }
- /// \brief Determine whether this symbol is weakly-imported,
+ /// Determine whether this symbol is weakly-imported,
/// or declared with the weak or weak-ref attr.
bool isWeak() const;
@@ -647,18 +656,18 @@ public:
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
};
-/// QualifierInfo - A struct with extended info about a syntactic
+/// A struct with extended info about a syntactic
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
NestedNameSpecifierLoc QualifierLoc;
- /// NumTemplParamLists - The number of "outer" template parameter lists.
+ /// The number of "outer" template parameter lists.
/// The count includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
unsigned NumTemplParamLists = 0;
- /// TemplParamLists - A new-allocated array of size NumTemplParamLists,
+ /// 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
@@ -669,13 +678,12 @@ struct QualifierInfo {
QualifierInfo(const QualifierInfo &) = delete;
QualifierInfo& operator=(const QualifierInfo &) = delete;
- /// setTemplateParameterListsInfo - Sets info about "outer" template
- /// parameter lists.
+ /// Sets info about "outer" template parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
};
-/// \brief Represents a ValueDecl that came out of a declarator.
+/// Represents a ValueDecl that came out of a declarator.
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
// A struct representing both a TInfo and a syntactic qualifier,
@@ -686,7 +694,7 @@ class DeclaratorDecl : public ValueDecl {
llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
- /// InnerLocStart - The start of the source range for this declaration,
+ /// The start of the source range for this declaration,
/// ignoring outer template declarations.
SourceLocation InnerLocStart;
@@ -717,13 +725,12 @@ public:
DeclInfo = TI;
}
- /// getInnerLocStart - Return SourceLocation representing start of source
- /// range ignoring outer template declarations.
+ /// Return start of source range ignoring outer template declarations.
SourceLocation getInnerLocStart() const { return InnerLocStart; }
void setInnerLocStart(SourceLocation L) { InnerLocStart = L; }
- /// getOuterLocStart - Return SourceLocation representing start of source
- /// range taking into account any outer template declarations.
+ /// Return start of source range taking into account any outer template
+ /// declarations.
SourceLocation getOuterLocStart() const;
SourceRange getSourceRange() const override LLVM_READONLY;
@@ -732,14 +739,14 @@ public:
return getOuterLocStart();
}
- /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// Retrieve the nested-name-specifier that qualifies the name of this
/// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
: nullptr;
}
- /// \brief Retrieve the nested-name-specifier (with source-location
+ /// Retrieve the nested-name-specifier (with source-location
/// information) that qualifies the name of this declaration, if it was
/// present in the source.
NestedNameSpecifierLoc getQualifierLoc() const {
@@ -770,25 +777,25 @@ public:
}
};
-/// \brief Structure used to store a statement, the constant value to
+/// 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 {
- /// \brief Whether this statement was already evaluated.
+ /// Whether this statement was already evaluated.
bool WasEvaluated : 1;
- /// \brief Whether this statement is being evaluated.
+ /// Whether this statement is being evaluated.
bool IsEvaluating : 1;
- /// \brief Whether we already checked whether this statement was an
+ /// Whether we already checked whether this statement was an
/// integral constant expression.
bool CheckedICE : 1;
- /// \brief Whether we are checking whether this statement is an
+ /// Whether we are checking whether this statement is an
/// integral constant expression.
bool CheckingICE : 1;
- /// \brief Whether this statement is an integral constant expression,
+ /// Whether this statement is an integral constant expression,
/// or in C++11, whether the statement is a constant expression. Only
/// valid if CheckedICE is true.
bool IsICE : 1;
@@ -801,11 +808,10 @@ struct EvaluatedStmt {
};
-/// VarDecl - An instance of this class is created to represent a variable
-/// declaration or definition.
+/// Represents a variable declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
- /// \brief Initialization styles.
+ /// Initialization styles.
enum InitializationStyle {
/// C-style initialization with assignment
CInit,
@@ -817,7 +823,7 @@ public:
ListInit
};
- /// \brief Kinds of thread-local storage.
+ /// Kinds of thread-local storage.
enum TLSKind {
/// Not a TLS variable.
TLS_None,
@@ -829,8 +835,7 @@ public:
TLS_Dynamic
};
- /// getStorageClassSpecifierString - Return the string used to
- /// specify the storage class \p SC.
+ /// 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);
@@ -845,7 +850,7 @@ protected:
// allocated in trailing space when necessary.
using InitType = llvm::PointerUnion<Stmt *, EvaluatedStmt *>;
- /// \brief The initializer for this variable or, for a ParmVarDecl, the
+ /// The initializer for this variable or, for a ParmVarDecl, the
/// C++ default argument.
mutable InitType Init;
@@ -915,41 +920,44 @@ protected:
unsigned : NumVarDeclBits;
// FIXME: We need something similar to CXXRecordDecl::DefinitionData.
- /// \brief Whether this variable is a definition which was demoted due to
+ /// Whether this variable is a definition which was demoted due to
/// module merge.
unsigned IsThisDeclarationADemotedDefinition : 1;
- /// \brief Whether this variable is the exception variable in a C++ catch
+ /// Whether this variable is the exception variable in a C++ catch
/// or an Objective-C @catch statement.
unsigned ExceptionVar : 1;
- /// \brief Whether this local variable could be allocated in the return
+ /// Whether this local variable could be allocated in the return
/// slot of its function, enabling the named return value optimization
/// (NRVO).
unsigned NRVOVariable : 1;
- /// \brief Whether this variable is the for-range-declaration in a C++0x
+ /// Whether this variable is the for-range-declaration in a C++0x
/// for-range statement.
unsigned CXXForRangeDecl : 1;
- /// \brief Whether this variable is an ARC pseudo-__strong
+ /// Whether this variable is the for-in loop declaration in Objective-C.
+ unsigned ObjCForDecl : 1;
+
+ /// Whether this variable is an ARC pseudo-__strong
/// variable; see isARCPseudoStrong() for details.
unsigned ARCPseudoStrong : 1;
- /// \brief Whether this variable is (C++1z) inline.
+ /// Whether this variable is (C++1z) inline.
unsigned IsInline : 1;
- /// \brief Whether this variable has (C++1z) inline explicitly specified.
+ /// Whether this variable has (C++1z) inline explicitly specified.
unsigned IsInlineSpecified : 1;
- /// \brief Whether this variable is (C++0x) constexpr.
+ /// Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
- /// \brief Whether this variable is the implicit variable for a lambda
+ /// Whether this variable is the implicit variable for a lambda
/// init-capture.
unsigned IsInitCapture : 1;
- /// \brief Whether this local extern variable's previous declaration was
+ /// Whether this local extern variable's previous declaration was
/// declared in the same block scope. This controls whether we should merge
/// the type of this declaration with its previous declaration.
unsigned PreviousDeclInSameBlockScope : 1;
@@ -1004,7 +1012,7 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
- /// \brief Returns the storage class as written in the source. For the
+ /// Returns the storage class as written in the source. For the
/// computed linkage of symbol, see getLinkage.
StorageClass getStorageClass() const {
return (StorageClass) VarDeclBits.SClass;
@@ -1020,8 +1028,8 @@ public:
}
TLSKind getTLSKind() const;
- /// hasLocalStorage - Returns true if a variable with function scope
- /// is a non-static local variable.
+ /// Returns true if a variable with function scope is a non-static local
+ /// variable.
bool hasLocalStorage() const {
if (getStorageClass() == SC_None) {
// OpenCL v1.2 s6.5.3: The __constant or constant address space name is
@@ -1044,8 +1052,8 @@ public:
return getStorageClass() >= SC_Auto;
}
- /// isStaticLocal - Returns true if a variable with function scope is a
- /// static local variable.
+ /// Returns true if a variable with function scope is a static local
+ /// variable.
bool isStaticLocal() const {
return (getStorageClass() == SC_Static ||
// C++11 [dcl.stc]p4
@@ -1053,43 +1061,42 @@ public:
&& !isFileVarDecl();
}
- /// \brief Returns true if a variable has extern or __private_extern__
+ /// Returns true if a variable has extern or __private_extern__
/// storage.
bool hasExternalStorage() const {
return getStorageClass() == SC_Extern ||
getStorageClass() == SC_PrivateExtern;
}
- /// \brief Returns true for all variables that do not have local storage.
+ /// Returns true for all variables that do not have local storage.
///
/// This includes all global variables as well as static variables declared
/// within a function.
bool hasGlobalStorage() const { return !hasLocalStorage(); }
- /// \brief Get the storage duration of this variable, per C++ [basic.stc].
+ /// Get the storage duration of this variable, per C++ [basic.stc].
StorageDuration getStorageDuration() const {
return hasLocalStorage() ? SD_Automatic :
getTSCSpec() ? SD_Thread : SD_Static;
}
- /// \brief Compute the language linkage.
+ /// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
- /// \brief Determines whether this variable is a variable with
- /// external, C linkage.
+ /// Determines whether this variable is a variable with external, C linkage.
bool isExternC() const;
- /// \brief Determines whether this variable's context is, or is nested within,
+ /// Determines whether this variable's context is, or is nested within,
/// a C++ extern "C" linkage spec.
bool isInExternCContext() const;
- /// \brief Determines whether this variable's context is, or is nested within,
+ /// Determines whether this variable's context is, or is nested within,
/// a C++ extern "C++" linkage spec.
bool isInExternCXXContext() const;
- /// isLocalVarDecl - Returns true for local variable declarations
- /// other than parameters. Note that this includes static variables
- /// inside of functions. It also includes variables inside blocks.
+ /// Returns true for local variable declarations other than parameters.
+ /// Note that this includes static variables inside of functions. It also
+ /// includes variables inside blocks.
///
/// void foo() { int x; static int y; extern int z; }
bool isLocalVarDecl() const {
@@ -1100,13 +1107,12 @@ public:
return false;
}
- /// \brief Similar to isLocalVarDecl but also includes parameters.
+ /// Similar to isLocalVarDecl but also includes parameters.
bool isLocalVarDeclOrParm() const {
return isLocalVarDecl() || getKind() == Decl::ParmVar;
}
- /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
- /// excludes variables declared in blocks.
+ /// Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var && getKind() != Decl::Decomposition)
return false;
@@ -1114,7 +1120,7 @@ public:
return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
}
- /// \brief Determines whether this is a static data member.
+ /// Determines whether this is a static data member.
///
/// This will only be true in C++, and applies to, e.g., the
/// variable 'x' in:
@@ -1144,7 +1150,7 @@ public:
Definition
};
- /// \brief Check whether this declaration is a definition. If this could be
+ /// Check whether this declaration is a definition. If this could be
/// a tentative definition (in C), don't check whether there's an overriding
/// definition.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const;
@@ -1152,21 +1158,20 @@ public:
return isThisDeclarationADefinition(getASTContext());
}
- /// \brief Check whether this variable is defined in this
- /// translation unit.
+ /// Check whether this variable is defined in this translation unit.
DefinitionKind hasDefinition(ASTContext &) const;
DefinitionKind hasDefinition() const {
return hasDefinition(getASTContext());
}
- /// \brief Get the tentative definition that acts as the real definition in
- /// a TU. Returns null if there is a proper definition available.
+ /// Get the tentative definition that acts as the real definition in a TU.
+ /// Returns null if there is a proper definition available.
VarDecl *getActingDefinition();
const VarDecl *getActingDefinition() const {
return const_cast<VarDecl*>(this)->getActingDefinition();
}
- /// \brief Get the real (not just tentative) definition for this declaration.
+ /// Get the real (not just tentative) definition for this declaration.
VarDecl *getDefinition(ASTContext &);
const VarDecl *getDefinition(ASTContext &C) const {
return const_cast<VarDecl*>(this)->getDefinition(C);
@@ -1178,11 +1183,11 @@ public:
return const_cast<VarDecl*>(this)->getDefinition();
}
- /// \brief Determine whether this is or was instantiated from an out-of-line
+ /// Determine whether this is or was instantiated from an out-of-line
/// definition of a static data member.
bool isOutOfLine() const override;
- /// isFileVarDecl - Returns true for file scoped variable declaration.
+ /// Returns true for file scoped variable declaration.
bool isFileVarDecl() const {
Kind K = getKind();
if (K == ParmVar || K == ImplicitParam)
@@ -1197,14 +1202,14 @@ public:
return false;
}
- /// getAnyInitializer - Get the initializer for this variable, no matter which
+ /// Get the initializer for this variable, no matter which
/// declaration it is attached to.
const Expr *getAnyInitializer() const {
const VarDecl *D;
return getAnyInitializer(D);
}
- /// getAnyInitializer - Get the initializer for this variable, no matter which
+ /// Get the initializer for this variable, no matter which
/// declaration it is attached to. Also get that declaration.
const Expr *getAnyInitializer(const VarDecl *&D) const;
@@ -1214,12 +1219,12 @@ public:
}
Expr *getInit();
- /// \brief Retrieve the address of the initializer expression.
+ /// Retrieve the address of the initializer expression.
Stmt **getInitAddress();
void setInit(Expr *I);
- /// \brief Determine whether this variable's value can be used in a
+ /// Determine whether this variable's value can be used in a
/// constant expression, according to the relevant language standard.
/// This only checks properties of the declaration, and does not check
/// whether the initializer is in fact a constant expression.
@@ -1227,30 +1232,30 @@ public:
EvaluatedStmt *ensureEvaluatedStmt() const;
- /// \brief Attempt to evaluate the value of the initializer attached to this
+ /// Attempt to evaluate the value of the initializer attached to this
/// declaration, and produce notes explaining why it cannot be evaluated or is
/// not a constant expression. Returns a pointer to the value if evaluation
/// succeeded, 0 otherwise.
APValue *evaluateValue() const;
APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
- /// \brief Return the already-evaluated value of this variable's
+ /// Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known. Returns pointer
/// to untyped APValue if the value could not be evaluated.
APValue *getEvaluatedValue() const;
- /// \brief Determines whether it is already known whether the
+ /// Determines whether it is already known whether the
/// initializer is an integral constant expression or not.
bool isInitKnownICE() const;
- /// \brief Determines whether the initializer is an integral constant
+ /// Determines whether the initializer is an integral constant
/// expression, or in C++11, whether the initializer is a constant
/// expression.
///
/// \pre isInitKnownICE()
bool isInitICE() const;
- /// \brief Determine whether the value of the initializer attached to this
+ /// Determine whether the value of the initializer attached to this
/// declaration is an integral constant expression.
bool checkInitIsICE() const;
@@ -1258,7 +1263,7 @@ public:
VarDeclBits.InitStyle = Style;
}
- /// \brief The style of initialization for this declaration.
+ /// The style of initialization for this declaration.
///
/// C-style initialization is "int x = 1;". Call-style initialization is
/// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be
@@ -1272,18 +1277,18 @@ public:
return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
}
- /// \brief Whether the initializer is a direct-initializer (list or call).
+ /// Whether the initializer is a direct-initializer (list or call).
bool isDirectInit() const {
return getInitStyle() != CInit;
}
- /// \brief If this definition should pretend to be a declaration.
+ /// If this definition should pretend to be a declaration.
bool isThisDeclarationADemotedDefinition() const {
return isa<ParmVarDecl>(this) ? false :
NonParmVarDeclBits.IsThisDeclarationADemotedDefinition;
}
- /// \brief This is a definition which should be demoted to a declaration.
+ /// This is a definition which should be demoted to a declaration.
///
/// In some cases (mostly module merging) we can end up with two visible
/// definitions one of which needs to be demoted to a declaration to keep
@@ -1294,7 +1299,7 @@ public:
NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1;
}
- /// \brief Determine whether this variable is the exception variable in a
+ /// Determine whether this variable is the exception variable in a
/// C++ catch statememt or an Objective-C \@catch statement.
bool isExceptionVariable() const {
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar;
@@ -1304,7 +1309,7 @@ public:
NonParmVarDeclBits.ExceptionVar = EV;
}
- /// \brief Determine whether this local variable can be used with the named
+ /// Determine whether this local variable can be used with the named
/// return value optimization (NRVO).
///
/// The named return value optimization (NRVO) works by marking certain
@@ -1322,7 +1327,7 @@ public:
NonParmVarDeclBits.NRVOVariable = NRVO;
}
- /// \brief Determine whether this variable is the for-range-declaration in
+ /// Determine whether this variable is the for-range-declaration in
/// a C++0x for-range statement.
bool isCXXForRangeDecl() const {
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl;
@@ -1332,7 +1337,17 @@ public:
NonParmVarDeclBits.CXXForRangeDecl = FRD;
}
- /// \brief Determine whether this variable is an ARC pseudo-__strong
+ /// Determine whether this variable is a for-loop declaration for a
+ /// for-in statement in Objective-C.
+ bool isObjCForDecl() const {
+ return NonParmVarDeclBits.ObjCForDecl;
+ }
+
+ void setObjCForDecl(bool FRD) {
+ NonParmVarDeclBits.ObjCForDecl = FRD;
+ }
+
+ /// Determine whether this variable is an ARC pseudo-__strong
/// variable. A pseudo-__strong variable has a __strong-qualified
/// type but does not actually retain the object written into it.
/// Generally such variables are also 'const' for safety.
@@ -1392,41 +1407,41 @@ public:
NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
}
- /// \brief Retrieve the variable declaration from which this variable could
+ /// Retrieve the variable declaration from which this variable could
/// be instantiated, if it is an instantiation (rather than a non-template).
VarDecl *getTemplateInstantiationPattern() const;
- /// \brief If this variable is an instantiated static data member of a
+ /// If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
VarDecl *getInstantiatedFromStaticDataMember() const;
- /// \brief If this variable is an instantiation of a variable template or a
+ /// If this variable is an instantiation of a variable template or a
/// static data member of a class template, determine what kind of
/// template specialization or instantiation this is.
TemplateSpecializationKind getTemplateSpecializationKind() const;
- /// \brief If this variable is an instantiation of a variable template or a
+ /// If this variable is an instantiation of a variable template or a
/// static data member of a class template, determine its point of
/// instantiation.
SourceLocation getPointOfInstantiation() const;
- /// \brief If this variable is an instantiation of a static data member of a
+ /// If this variable is an instantiation of a static data member of a
/// class template specialization, retrieves the member specialization
/// information.
MemberSpecializationInfo *getMemberSpecializationInfo() const;
- /// \brief For a static data member that was instantiated from a static
+ /// For a static data member that was instantiated from a static
/// data member of a class template, set the template specialiation kind.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation = SourceLocation());
- /// \brief Specify that this variable is an instantiation of the
+ /// Specify that this variable is an instantiation of the
/// static data member VD.
void setInstantiationOfStaticDataMember(VarDecl *VD,
TemplateSpecializationKind TSK);
- /// \brief Retrieves the variable template that is described by this
+ /// Retrieves the variable template that is described by this
/// variable declaration.
///
/// Every variable template is represented as a VarTemplateDecl and a
@@ -1441,6 +1456,11 @@ public:
void setDescribedVarTemplate(VarTemplateDecl *Template);
+ // Is this variable known to have a definition somewhere in the complete
+ // program? This may be true even if the declaration has internal linkage and
+ // has no definition within this source file.
+ bool isKnownToBeDefined() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
@@ -1509,7 +1529,7 @@ public:
static bool classofKind(Kind K) { return K == ImplicitParam; }
};
-/// ParmVarDecl - Represents a parameter to a function.
+/// Represents a parameter to a function.
class ParmVarDecl : public VarDecl {
public:
enum { MaxFunctionScopeDepth = 255 };
@@ -1598,7 +1618,7 @@ public:
void setDefaultArg(Expr *defarg);
- /// \brief Retrieve the source range that covers the entire default
+ /// Retrieve the source range that covers the entire default
/// argument.
SourceRange getDefaultArgRange() const;
void setUninstantiatedDefaultArg(Expr *arg);
@@ -1607,14 +1627,13 @@ public:
return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
}
- /// hasDefaultArg - Determines whether this parameter has a default argument,
+ /// Determines whether this parameter has a default argument,
/// either parsed or not.
bool hasDefaultArg() const;
- /// hasUnparsedDefaultArg - Determines whether this parameter has a
- /// default argument that has not yet been parsed. This will occur
- /// during the processing of a C++ class whose member functions have
- /// default arguments, e.g.,
+ /// Determines whether this parameter has a default argument that has not
+ /// yet been parsed. This will occur during the processing of a C++ class
+ /// whose member functions have default arguments, e.g.,
/// @code
/// class X {
/// public:
@@ -1629,11 +1648,10 @@ public:
return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
}
- /// setUnparsedDefaultArg - Specify that this parameter has an
- /// unparsed default argument. The argument will be replaced with a
- /// real default argument via setDefaultArg when the class
- /// definition enclosing the function declaration that owns this
- /// default argument is completed.
+ /// Specify that this parameter has an unparsed default argument.
+ /// The argument will be replaced with a real default argument via
+ /// setDefaultArg when the class definition enclosing the function
+ /// declaration that owns this default argument is completed.
void setUnparsedDefaultArg() {
ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
}
@@ -1648,11 +1666,11 @@ public:
QualType getOriginalType() const;
- /// \brief Determine whether this parameter is actually a function
+ /// Determine whether this parameter is actually a function
/// parameter pack.
bool isParameterPack() const;
- /// setOwningFunction - Sets the function declaration that owns this
+ /// Sets the function declaration that owns this
/// ParmVarDecl. Since ParmVarDecls are often created before the
/// FunctionDecls that own them, this routine is required to update
/// the DeclContext appropriately.
@@ -1683,8 +1701,7 @@ private:
unsigned getParameterIndexLarge() const;
};
-/// An instance of this class is created to represent a function declaration or
-/// definition.
+/// Represents 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
@@ -1697,7 +1714,7 @@ private:
class FunctionDecl : public DeclaratorDecl, public DeclContext,
public Redeclarable<FunctionDecl> {
public:
- /// \brief The kind of templated function a FunctionDecl can be.
+ /// The kind of templated function a FunctionDecl can be.
enum TemplatedKind {
TK_NonTemplate,
TK_FunctionTemplate,
@@ -1707,7 +1724,7 @@ public:
};
private:
- /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
+ /// A 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 = nullptr;
@@ -1732,6 +1749,12 @@ private:
unsigned HasWrittenPrototype : 1;
unsigned IsDeleted : 1;
unsigned IsTrivial : 1; // sunk from CXXMethodDecl
+
+ /// This flag indicates whether this function is trivial for the purpose of
+ /// calls. This is meaningful only when this function is a copy/move
+ /// constructor or a destructor.
+ unsigned IsTrivialForCall : 1;
+
unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
unsigned HasImplicitReturnZero : 1;
@@ -1739,10 +1762,10 @@ private:
unsigned IsConstexpr : 1;
unsigned InstantiationIsPending : 1;
- /// \brief Indicates if the function uses __try.
+ /// Indicates if the function uses __try.
unsigned UsesSEHTry : 1;
- /// \brief Indicates if the function was a definition but its body was
+ /// Indicates if the function was a definition but its body was
/// skipped.
unsigned HasSkippedBody : 1;
@@ -1750,6 +1773,10 @@ private:
/// parsing it.
unsigned WillHaveBody : 1;
+ /// Indicates that this function is a multiversioned function using attribute
+ /// 'target'.
+ unsigned IsMultiVersion : 1;
+
protected:
/// [C++17] Only used by CXXDeductionGuideDecl. Declared here to avoid
/// increasing the size of CXXDeductionGuideDecl by the size of an unsigned
@@ -1764,7 +1791,7 @@ private:
unsigned HasODRHash : 1;
unsigned ODRHash;
- /// \brief End part of this FunctionDecl's source range.
+ /// End part of this FunctionDecl's source range.
///
/// We could compute the full range in getSourceRange(). However, when we're
/// dealing with a function definition deserialized from a PCH/AST file,
@@ -1773,7 +1800,7 @@ private:
/// EndRangeLoc.
SourceLocation EndRangeLoc;
- /// \brief The template or declaration that this declaration
+ /// The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
/// For non-templates, this value will be NULL. For function
@@ -1795,7 +1822,7 @@ private:
/// the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;
- /// \brief Specify that this function declaration is actually a function
+ /// Specify that this function declaration is actually a function
/// template specialization.
///
/// \param C the ASTContext.
@@ -1824,7 +1851,7 @@ private:
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation PointOfInstantiation);
- /// \brief Specify that this record is an instantiation of the
+ /// Specify that this record is an instantiation of the
/// member function FD.
void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
TemplateSpecializationKind TSK);
@@ -1842,13 +1869,14 @@ protected:
IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
IsExplicitSpecified(false), IsVirtualAsWritten(false), IsPure(false),
HasInheritedPrototype(false), HasWrittenPrototype(true),
- IsDeleted(false), IsTrivial(false), IsDefaulted(false),
+ IsDeleted(false), IsTrivial(false), IsTrivialForCall(false),
+ IsDefaulted(false),
IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
InstantiationIsPending(false), UsesSEHTry(false), HasSkippedBody(false),
- WillHaveBody(false), IsCopyDeductionCandidate(false), HasODRHash(false),
- ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()),
- DNLoc(NameInfo.getInfo()) {}
+ WillHaveBody(false), IsMultiVersion(false),
+ IsCopyDeductionCandidate(false), HasODRHash(false), ODRHash(0),
+ EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {}
using redeclarable_base = Redeclarable<FunctionDecl>;
@@ -1903,7 +1931,7 @@ public:
bool isConstexprSpecified = false);
static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
@@ -1915,11 +1943,25 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
- /// \brief Returns true if the function has a body (definition). The
- /// function body might be in any of the (re-)declarations of this
- /// function. The variant that accepts a FunctionDecl pointer will
- /// set that function declaration to the actual declaration
- /// containing the body (if there is one).
+ // Function definitions.
+ //
+ // A function declaration may be:
+ // - a non defining declaration,
+ // - a definition. A function may be defined because:
+ // - it has a body, or will have it in the case of late parsing.
+ // - it has an uninstantiated body. The body does not exist because the
+ // function is not used yet, but the declaration is considered a
+ // definition and does not allow other definition of this function.
+ // - it does not have a user specified body, but it does not allow
+ // redefinition, because it is deleted/defaulted or is defined through
+ // some other mechanism (alias, ifunc).
+
+ /// Returns true if the function has a body.
+ ///
+ /// The function body might be in any of the (re-)declarations of this
+ /// function. The variant that accepts a FunctionDecl pointer will set that
+ /// function declaration to the actual declaration containing the body (if
+ /// there is one).
bool hasBody(const FunctionDecl *&Definition) const;
bool hasBody() const override {
@@ -1931,9 +1973,11 @@ public:
/// specific codegen.
bool hasTrivialBody() const;
- /// 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 has a definition that does not need to be
+ /// instantiated.
+ ///
+ /// The variant that accepts a FunctionDecl pointer will set that function
+ /// declaration to the declaration that is a definition (if there is one).
bool isDefined(const FunctionDecl *&Definition) const;
virtual bool isDefined() const {
@@ -1941,7 +1985,7 @@ public:
return isDefined(Definition);
}
- /// \brief Get the definition for this declaration.
+ /// Get the definition for this declaration.
FunctionDecl *getDefinition() {
const FunctionDecl *Definition;
if (isDefined(Definition))
@@ -1975,8 +2019,7 @@ public:
IsLateTemplateParsed || WillHaveBody || hasDefiningAttr();
}
- /// 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.
bool doesThisDeclarationHaveABody() const {
return Body || IsLateTemplateParsed;
}
@@ -2007,6 +2050,9 @@ public:
bool isTrivial() const { return IsTrivial; }
void setTrivial(bool IT) { IsTrivial = IT; }
+ bool isTrivialForCall() const { return IsTrivialForCall; }
+ void setTrivialForCall(bool IT) { IsTrivialForCall = IT; }
+
/// Whether this function is defaulted per C++0x. Only valid for
/// special member functions.
bool isDefaulted() const { return IsDefaulted; }
@@ -2023,7 +2069,7 @@ public:
bool hasImplicitReturnZero() const { return HasImplicitReturnZero; }
void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; }
- /// \brief Whether this function has a prototype, either because one
+ /// Whether this function has a prototype, either because one
/// was explicitly written or because it was "inherited" by merging
/// a declaration without a prototype with a declaration that has a
/// prototype.
@@ -2033,7 +2079,7 @@ public:
bool hasWrittenPrototype() const { return HasWrittenPrototype; }
- /// \brief Whether this function inherited its prototype from a
+ /// Whether this function inherited its prototype from a
/// previous declaration.
bool hasInheritedPrototype() const { return HasInheritedPrototype; }
void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }
@@ -2042,7 +2088,7 @@ public:
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
- /// \brief Whether the instantiation of this function is pending.
+ /// Whether the instantiation of this function is pending.
/// This bit is set when the decision to instantiate this function is made
/// and unset if and when the function body is created. That leaves out
/// cases where instantiation did not happen because the template definition
@@ -2051,11 +2097,11 @@ public:
bool instantiationIsPending() const { return InstantiationIsPending; }
void setInstantiationIsPending(bool IC) { InstantiationIsPending = IC; }
- /// \brief Indicates the function uses __try.
+ /// Indicates the function uses __try.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
- /// \brief Whether this function has been deleted.
+ /// Whether this function has been deleted.
///
/// A function that is "deleted" (via the C++0x "= delete" syntax)
/// acts like a normal function, except that it cannot actually be
@@ -2078,15 +2124,15 @@ public:
bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
void setDeletedAsWritten(bool D = true) { IsDeleted = D; }
- /// \brief Determines whether this function is "main", which is the
+ /// Determines whether this function is "main", which is the
/// entry point into an executable program.
bool isMain() const;
- /// \brief Determines whether this function is a MSVCRT user defined entry
+ /// Determines whether this function is a MSVCRT user defined entry
/// point.
bool isMSVCRTEntryPoint() const;
- /// \brief Determines whether this operator new or delete is one
+ /// Determines whether this operator new or delete is one
/// of the reserved global placement operators:
/// void *operator new(size_t, void *);
/// void *operator new[](size_t, void *);
@@ -2101,7 +2147,7 @@ public:
/// This function must be an allocation or deallocation function.
bool isReservedGlobalPlacementOperator() const;
- /// \brief Determines whether this function is one of the replaceable
+ /// Determines whether this function is one of the replaceable
/// global allocation functions:
/// void *operator new(size_t);
/// void *operator new(size_t, const std::nothrow_t &) noexcept;
@@ -2121,32 +2167,32 @@ public:
/// true through IsAligned.
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
- /// \brief Determine whether this is a destroying operator delete.
+ /// Determine whether this is a destroying operator delete.
bool isDestroyingOperatorDelete() const;
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
- /// \brief Determines whether this function is a function with
+ /// Determines whether this function is a function with
/// external, C linkage.
bool isExternC() const;
- /// \brief Determines whether this function's context is, or is nested within,
+ /// Determines whether this function's context is, or is nested within,
/// a C++ extern "C" linkage spec.
bool isInExternCContext() const;
- /// \brief Determines whether this function's context is, or is nested within,
+ /// Determines whether this function's context is, or is nested within,
/// a C++ extern "C++" linkage spec.
bool isInExternCXXContext() const;
- /// \brief Determines whether this is a global function.
+ /// Determines whether this is a global function.
bool isGlobal() const;
- /// \brief Determines whether this function is known to be 'noreturn', through
+ /// Determines whether this function is known to be 'noreturn', through
/// an attribute on its declaration or its type.
bool isNoReturn() const;
- /// \brief True if the function was a definition but its body was skipped.
+ /// True if the function was a definition but its body was skipped.
bool hasSkippedBody() const { return HasSkippedBody; }
void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
@@ -2154,6 +2200,22 @@ public:
bool willHaveBody() const { return WillHaveBody; }
void setWillHaveBody(bool V = true) { WillHaveBody = V; }
+ /// True if this function is considered a multiversioned function.
+ bool isMultiVersion() const { return getCanonicalDecl()->IsMultiVersion; }
+
+ /// Sets the multiversion state for this declaration and all of its
+ /// redeclarations.
+ void setIsMultiVersion(bool V = true) {
+ getCanonicalDecl()->IsMultiVersion = V;
+ }
+
+ /// True if this function is a multiversioned dispatch function as a part of
+ /// the cpu_specific/cpu_dispatch functionality.
+ bool isCPUDispatchMultiVersion() const;
+ /// True if this function is a multiversioned processor specific function as a
+ /// part of the cpu_specific/cpu_dispatch functionality.
+ bool isCPUSpecificMultiVersion() const;
+
void setPreviousDeclaration(FunctionDecl * PrevDecl);
FunctionDecl *getCanonicalDecl() override;
@@ -2209,34 +2271,34 @@ public:
return getType()->getAs<FunctionType>()->getReturnType();
}
- /// \brief Attempt to compute an informative source range covering the
+ /// Attempt to compute an informative source range covering the
/// function return type. This may omit qualifiers and other information with
/// limited representation in the AST.
SourceRange getReturnTypeSourceRange() const;
- /// \brief Attempt to compute an informative source range covering the
+ /// Attempt to compute an informative source range covering the
/// function exception specification, if any.
SourceRange getExceptionSpecSourceRange() const;
- /// \brief Determine the type of an expression that calls this function.
+ /// Determine the type of an expression that calls this function.
QualType getCallResultType() const {
assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
}
- /// \brief Returns the WarnUnusedResultAttr that is either declared on this
+ /// Returns the WarnUnusedResultAttr that is either declared on this
/// function, or its return type declaration.
const Attr *getUnusedResultAttr() const;
- /// \brief Returns true if this function or its return type has the
+ /// Returns true if this function or its return type has the
/// warn_unused_result attribute.
bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; }
- /// \brief Returns the storage class as written in the source. For the
+ /// Returns the storage class as written in the source. For the
/// computed linkage of symbol, see getLinkage.
StorageClass getStorageClass() const { return StorageClass(SClass); }
- /// \brief Determine whether the "inline" keyword was specified for this
+ /// Determine whether the "inline" keyword was specified for this
/// function.
bool isInlineSpecified() const { return IsInlineSpecified; }
@@ -2251,7 +2313,7 @@ public:
IsInline = true;
}
- /// \brief Determine whether this function should be inlined, because it is
+ /// Determine whether this function should be inlined, because it is
/// either marked "inline" or "constexpr" or is a member function of a class
/// that was defined in the class body.
bool isInlined() const { return IsInline; }
@@ -2262,8 +2324,8 @@ public:
bool doesDeclarationForceExternallyVisibleDefinition() const;
- /// isOverloadedOperator - Whether this function declaration
- /// represents an C++ overloaded operator, e.g., "operator+".
+ /// Whether this function declaration represents an C++ overloaded
+ /// operator, e.g., "operator+".
bool isOverloadedOperator() const {
return getOverloadedOperator() != OO_None;
}
@@ -2272,7 +2334,7 @@ public:
const IdentifierInfo *getLiteralIdentifier() const;
- /// \brief If this function is an instantiation of a member function
+ /// If this function is an instantiation of a member function
/// of a class template specialization, retrieves the function from
/// which it was instantiated.
///
@@ -2295,22 +2357,22 @@ public:
/// declaration returned by getInstantiatedFromMemberFunction().
FunctionDecl *getInstantiatedFromMemberFunction() const;
- /// \brief What kind of templated function this is.
+ /// What kind of templated function this is.
TemplatedKind getTemplatedKind() const;
- /// \brief If this function is an instantiation of a member function of a
+ /// If this function is an instantiation of a member function of a
/// class template specialization, retrieves the member specialization
/// information.
MemberSpecializationInfo *getMemberSpecializationInfo() const;
- /// \brief Specify that this record is an instantiation of the
+ /// Specify that this record is an instantiation of the
/// member function FD.
void setInstantiationOfMemberFunction(FunctionDecl *FD,
TemplateSpecializationKind TSK) {
setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
}
- /// \brief Retrieves the function template that is described by this
+ /// Retrieves the function template that is described by this
/// function declaration.
///
/// Every function template is represented as a FunctionTemplateDecl
@@ -2326,50 +2388,50 @@ public:
void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
- /// \brief Determine whether this function is a function template
+ /// Determine whether this function is a function template
/// specialization.
bool isFunctionTemplateSpecialization() const {
return getPrimaryTemplate() != nullptr;
}
- /// \brief Retrieve the class scope template pattern that this function
+ /// Retrieve the class scope template pattern that this function
/// template specialization is instantiated from.
FunctionDecl *getClassScopeSpecializationPattern() const;
- /// \brief If this function is actually a function template specialization,
+ /// If this function is actually a function template specialization,
/// retrieve information about this function template specialization.
/// Otherwise, returns NULL.
FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;
- /// \brief Determines whether this function is a function template
+ /// Determines whether this function is a function template
/// specialization or a member of a class template specialization that can
/// be implicitly instantiated.
bool isImplicitlyInstantiable() const;
- /// \brief Determines if the given function was instantiated from a
+ /// Determines if the given function was instantiated from a
/// function template.
bool isTemplateInstantiation() const;
- /// \brief Retrieve the function declaration from which this function could
+ /// Retrieve the function declaration from which this function could
/// be instantiated, if it is an instantiation (rather than a non-template
/// or a specialization, for example).
FunctionDecl *getTemplateInstantiationPattern() const;
- /// \brief Retrieve the primary template that this function template
+ /// Retrieve the primary template that this function template
/// specialization either specializes or was instantiated from.
///
/// If this function declaration is not a function template specialization,
/// returns NULL.
FunctionTemplateDecl *getPrimaryTemplate() const;
- /// \brief Retrieve the template arguments used to produce this function
+ /// Retrieve the template arguments used to produce this function
/// template specialization from the primary template.
///
/// If this function declaration is not a function template specialization,
/// returns NULL.
const TemplateArgumentList *getTemplateSpecializationArgs() const;
- /// \brief Retrieve the template argument list as written in the sources,
+ /// Retrieve the template argument list as written in the sources,
/// if any.
///
/// If this function declaration is not a function template specialization
@@ -2379,7 +2441,7 @@ public:
const ASTTemplateArgumentListInfo*
getTemplateSpecializationArgsAsWritten() const;
- /// \brief Specify that this function declaration is actually a function
+ /// Specify that this function declaration is actually a function
/// template specialization.
///
/// \param Template the function template that this function template
@@ -2409,7 +2471,7 @@ public:
PointOfInstantiation);
}
- /// \brief Specifies that this function declaration is actually a
+ /// Specifies that this function declaration is actually a
/// dependent function template specialization.
void setDependentTemplateSpecialization(ASTContext &Context,
const UnresolvedSetImpl &Templates,
@@ -2418,16 +2480,16 @@ public:
DependentFunctionTemplateSpecializationInfo *
getDependentSpecializationInfo() const;
- /// \brief Determine what kind of template instantiation this function
+ /// Determine what kind of template instantiation this function
/// represents.
TemplateSpecializationKind getTemplateSpecializationKind() const;
- /// \brief Determine what kind of template instantiation this function
+ /// Determine what kind of template instantiation this function
/// represents.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation = SourceLocation());
- /// \brief Retrieve the (first) point of instantiation of a function template
+ /// Retrieve the (first) point of instantiation of a function template
/// specialization or a member of a class template specialization.
///
/// \returns the first point of instantiation, if this function was
@@ -2435,20 +2497,24 @@ public:
/// location.
SourceLocation getPointOfInstantiation() const;
- /// \brief Determine whether this is or was instantiated from an out-of-line
+ /// Determine whether this is or was instantiated from an out-of-line
/// definition of a member function.
bool isOutOfLine() const override;
- /// \brief Identify a memory copying or setting function.
+ /// Identify a memory copying or setting function.
/// If the given function is a memory copy or setting function, returns
/// the corresponding Builtin ID. If the function is not a memory function,
/// returns 0.
unsigned getMemoryFunctionKind() const;
- /// \brief Returns ODRHash of the function. This value is calculated and
+ /// Returns ODRHash of the function. This value is calculated and
/// stored on first call, then the stored value returned on the other calls.
unsigned getODRHash();
+ /// Returns cached ODRHash of the function. This must have been previously
+ /// computed and stored.
+ unsigned getODRHash() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
@@ -2462,8 +2528,7 @@ public:
}
};
-/// FieldDecl - An instance of this class is created by Sema::ActOnField to
-/// represent a member of a struct/union/class.
+/// Represents a member of a struct/union/class.
class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
unsigned BitField : 1;
unsigned Mutable : 1;
@@ -2499,7 +2564,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
Expr *BitWidth;
};
- /// \brief Storage for either the bit-width, the in-class initializer, or
+ /// 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
@@ -2533,21 +2598,21 @@ public:
InClassInitStyle InitStyle);
static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- /// getFieldIndex - Returns the index of this field within its record,
+
+ /// Returns the index of this field within its record,
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
unsigned getFieldIndex() const;
- /// isMutable - Determines whether this field is mutable (C++ only).
+ /// Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
- /// \brief Determines whether this field is a bitfield.
+ /// Determines whether this field is a bitfield.
bool isBitField() const { return BitField; }
- /// @brief Determines whether this is an unnamed bitfield.
+ /// Determines whether this is an unnamed bitfield.
bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
- /// isAnonymousStructOrUnion - Determines whether this field is a
+ /// Determines whether this field is a
/// representative for an anonymous struct or union. Such fields are
/// unnamed and are implicitly generated by the implementation to
/// store the data for the anonymous union or struct.
@@ -2564,7 +2629,7 @@ public:
unsigned getBitWidthValue(const ASTContext &Ctx) const;
- /// setBitWidth - Set the bit-field width for this member.
+ /// Set the bit-field width for this member.
// Note: used by some clients (i.e., do not remove it).
void setBitWidth(Expr *Width) {
assert(!hasCapturedVLAType() && !BitField &&
@@ -2578,7 +2643,7 @@ public:
BitField = true;
}
- /// removeBitWidth - Remove the bit-field width from this member.
+ /// 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");
@@ -2586,6 +2651,11 @@ public:
BitField = false;
}
+ /// Is this a zero-length bit-field? Such bit-fields aren't really bit-fields
+ /// at all and instead act as a separator between contiguous runs of other
+ /// bit-fields.
+ bool isZeroLengthBitField(const ASTContext &Ctx) const;
+
/// Get the kind of (C++11) default member initializer that this field has.
InClassInitStyle getInClassInitStyle() const {
InitStorageKind storageKind = InitStorage.getInt();
@@ -2610,8 +2680,7 @@ public:
return static_cast<Expr*>(Ptr);
}
- /// setInClassInitializer - Set the C++11 in-class initializer for this
- /// member.
+ /// Set the C++11 in-class initializer for this member.
void setInClassInitializer(Expr *Init) {
assert(hasInClassInitializer() && !getInClassInitializer());
if (BitField)
@@ -2620,30 +2689,29 @@ public:
InitStorage.setPointer(Init);
}
- /// removeInClassInitializer - Remove the C++11 in-class initializer from this
- /// member.
+ /// Remove the C++11 in-class initializer from this member.
void removeInClassInitializer() {
assert(hasInClassInitializer() && "no initializer to remove");
InitStorage.setPointerAndInt(getBitWidth(), ISK_NoInit);
}
- /// \brief Determine whether this member captures the variable length array
+ /// Determine whether this member captures the variable length array
/// type.
bool hasCapturedVLAType() const {
return InitStorage.getInt() == ISK_CapturedVLAType;
}
- /// \brief Get the captured variable length array type.
+ /// Get the captured variable length array type.
const VariableArrayType *getCapturedVLAType() const {
return hasCapturedVLAType() ? static_cast<const VariableArrayType *>(
InitStorage.getPointer())
: nullptr;
}
- /// \brief Set the captured variable length array type for this field.
+ /// Set the captured variable length array type for this field.
void setCapturedVLAType(const VariableArrayType *VLAType);
- /// getParent - Returns the parent of this field declaration, which
+ /// Returns the parent of this field declaration, which
/// is the struct in which this field is defined.
const RecordDecl *getParent() const {
return cast<RecordDecl>(getDeclContext());
@@ -2664,7 +2732,7 @@ public:
static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
};
-/// EnumConstantDecl - An instance of this object exists for each enum constant
+/// An instance of this object exists for each enum constant
/// that is defined. For example, in "enum X {a,b}", each of a/b are
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
/// TagType for the X EnumDecl.
@@ -2686,7 +2754,7 @@ public:
QualType T, Expr *E,
const llvm::APSInt &V);
static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; }
@@ -2705,9 +2773,8 @@ public:
static bool classofKind(Kind K) { return K == EnumConstant; }
};
-/// IndirectFieldDecl - An instance of this class is created to represent a
-/// field injected from an anonymous union/struct into the parent scope.
-/// IndirectFieldDecl are always implicit.
+/// Represents a field injected from an anonymous union/struct into the parent
+/// scope. These are always implicit.
class IndirectFieldDecl : public ValueDecl,
public Mergeable<IndirectFieldDecl> {
NamedDecl **Chaining;
@@ -2756,17 +2823,17 @@ public:
static bool classofKind(Kind K) { return K == IndirectField; }
};
-/// TypeDecl - Represents a declaration of a type.
+/// Represents a declaration of a type.
class TypeDecl : public NamedDecl {
friend class ASTContext;
- /// TypeForDecl - This indicates the Type object that represents
+ /// 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 = nullptr;
- /// LocStart - The start of the source range for this declaration.
+ /// The start of the source range for this declaration.
SourceLocation LocStart;
void anchor() override;
@@ -2800,13 +2867,16 @@ public:
/// Base class for declarations which introduce a typedef-name.
class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
- using ModedTInfo = std::pair<TypeSourceInfo *, QualType>;
- llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *> MaybeModedTInfo;
+ struct alignas(8) ModedTInfo {
+ TypeSourceInfo *first;
+ QualType second;
+ };
- // 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;
+ /// If int part is 0, we have not computed IsTransparentTag.
+ /// Otherwise, IsTransparentTag is (getInt() >> 1).
+ mutable llvm::PointerIntPair<
+ llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *>, 2>
+ MaybeModedTInfo;
void anchor() override;
@@ -2815,7 +2885,7 @@ protected:
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
- MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {}
+ MaybeModedTInfo(TInfo, 0) {}
using redeclarable_base = Redeclarable<TypedefNameDecl>;
@@ -2842,26 +2912,29 @@ public:
using redeclarable_base::getMostRecentDecl;
using redeclarable_base::isFirstDecl;
- bool isModed() const { return MaybeModedTInfo.is<ModedTInfo*>(); }
+ bool isModed() const {
+ return MaybeModedTInfo.getPointer().is<ModedTInfo *>();
+ }
TypeSourceInfo *getTypeSourceInfo() const {
- return isModed()
- ? MaybeModedTInfo.get<ModedTInfo*>()->first
- : MaybeModedTInfo.get<TypeSourceInfo*>();
+ return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->first
+ : MaybeModedTInfo.getPointer().get<TypeSourceInfo *>();
}
QualType getUnderlyingType() const {
- return isModed()
- ? MaybeModedTInfo.get<ModedTInfo*>()->second
- : MaybeModedTInfo.get<TypeSourceInfo*>()->getType();
+ return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->second
+ : MaybeModedTInfo.getPointer()
+ .get<TypeSourceInfo *>()
+ ->getType();
}
void setTypeSourceInfo(TypeSourceInfo *newType) {
- MaybeModedTInfo = newType;
+ MaybeModedTInfo.setPointer(newType);
}
void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) {
- MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy);
+ MaybeModedTInfo.setPointer(new (getASTContext(), 8)
+ ModedTInfo({unmodedTSI, modedTy}));
}
/// Retrieves the canonical declaration of this typedef-name.
@@ -2878,8 +2951,8 @@ public:
/// Determines if this typedef shares a name and spelling location with its
/// underlying tag type, as is the case with the NS_ENUM macro.
bool isTransparentTag() const {
- if (CacheIsTransparentTag)
- return CacheIsTransparentTag & 0x2;
+ if (MaybeModedTInfo.getInt())
+ return MaybeModedTInfo.getInt() & 0x2;
return isTransparentTagSlow();
}
@@ -2893,7 +2966,7 @@ private:
bool isTransparentTagSlow() const;
};
-/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef'
+/// Represents the declaration of a typedef-name via the 'typedef'
/// type specifier.
class TypedefDecl : public TypedefNameDecl {
TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
@@ -2913,7 +2986,7 @@ public:
static bool classofKind(Kind K) { return K == Typedef; }
};
-/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x
+/// Represents the declaration of a typedef-name via a C++11
/// alias-declaration.
class TypeAliasDecl : public TypedefNameDecl {
/// The template for which this is the pattern, if any.
@@ -2940,7 +3013,7 @@ public:
static bool classofKind(Kind K) { return K == TypeAlias; }
};
-/// TagDecl - Represents the declaration of a struct/union/class/enum.
+/// Represents the declaration of a struct/union/class/enum.
class TagDecl
: public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
public:
@@ -2949,25 +3022,24 @@ public:
private:
// FIXME: This can be packed into the bitfields in Decl.
- /// TagDeclKind - The TagKind enum.
+ /// The TagKind enum.
unsigned TagDeclKind : 3;
- /// IsCompleteDefinition - True if this is a definition ("struct foo
- /// {};"), false if it is a declaration ("struct foo;"). It is not
- /// a definition until the definition has been fully processed.
+ /// True if this is a definition ("struct foo {};"), false if it is a
+ /// declaration ("struct foo;"). It is not considered a definition
+ /// until the definition has been fully processed.
unsigned IsCompleteDefinition : 1;
protected:
- /// IsBeingDefined - True if this is currently being defined.
+ /// True if this is currently being defined.
unsigned IsBeingDefined : 1;
private:
- /// IsEmbeddedInDeclarator - True if this tag declaration is
- /// "embedded" (i.e., defined or declared for the very first time)
- /// in the syntax of a declarator.
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
unsigned IsEmbeddedInDeclarator : 1;
- /// \brief True if this tag is free standing, e.g. "struct foo;".
+ /// True if this tag is free standing, e.g. "struct foo;".
unsigned IsFreeStanding : 1;
protected:
@@ -2975,21 +3047,21 @@ protected:
unsigned NumPositiveBits : 8;
unsigned NumNegativeBits : 8;
- /// IsScoped - True if this tag declaration is a scoped enumeration. Only
+ /// 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,
+ /// If this tag declaration is a scoped enum,
/// then this is true if the scoped enum was declared using the class
/// tag, false if it was declared with the struct tag. No meaning is
/// associated if this tag declaration is not a scoped enum.
unsigned IsScopedUsingClassTag : 1;
- /// IsFixed - True if this is an enumeration with fixed underlying type. Only
+ /// True if this is an enumeration with fixed underlying type. Only
/// possible in C++11, Microsoft extensions, or Objective C mode.
unsigned IsFixed : 1;
- /// \brief Indicates whether it is possible for declarations of this kind
+ /// Indicates whether it is possible for declarations of this kind
/// to have an out-of-date definition.
///
/// This option is only enabled when modules are enabled.
@@ -3006,7 +3078,7 @@ private:
// to be used for the (uncommon) case of out-of-line declarations.
using ExtInfo = QualifierInfo;
- /// \brief If the (out-of-line) tag declaration name
+ /// If the (out-of-line) tag declaration name
/// is qualified, it points to the qualifier info (nns and range);
/// otherwise, if the tag declaration is anonymous and it is part of
/// a typedef or alias, it points to the TypedefNameDecl (used for mangling);
@@ -3050,7 +3122,7 @@ protected:
return getMostRecentDecl();
}
- /// @brief Completes the definition of this tag declaration.
+ /// Completes the definition of this tag declaration.
///
/// This is a helper function for derived classes.
void completeDefinition();
@@ -3072,11 +3144,11 @@ public:
SourceRange getBraceRange() const { return BraceRange; }
void setBraceRange(SourceRange R) { BraceRange = R; }
- /// getInnerLocStart - Return SourceLocation representing start of source
+ /// Return SourceLocation representing start of source
/// range ignoring outer template declarations.
SourceLocation getInnerLocStart() const { return getLocStart(); }
- /// getOuterLocStart - Return SourceLocation representing start of source
+ /// Return SourceLocation representing start of source
/// range taking into account any outer template declarations.
SourceLocation getOuterLocStart() const;
SourceRange getSourceRange() const override LLVM_READONLY;
@@ -3086,25 +3158,24 @@ public:
return const_cast<TagDecl*>(this)->getCanonicalDecl();
}
- /// isThisDeclarationADefinition() - Return true if this declaration
- /// is a completion definition of the type. Provided for consistency.
+ /// Return true if this declaration is a completion definition of the type.
+ /// Provided for consistency.
bool isThisDeclarationADefinition() const {
return isCompleteDefinition();
}
- /// isCompleteDefinition - Return true if this decl has its body
- /// fully specified.
+ /// Return true if this decl has its body fully specified.
bool isCompleteDefinition() const {
return IsCompleteDefinition;
}
- /// \brief Return true if this complete decl is
+ /// Return true if this complete decl is
/// required to be complete for some existing use.
bool isCompleteDefinitionRequired() const {
return IsCompleteDefinitionRequired;
}
- /// isBeingDefined - Return true if this decl is currently being defined.
+ /// Return true if this decl is currently being defined.
bool isBeingDefined() const {
return IsBeingDefined;
}
@@ -3121,19 +3192,19 @@ public:
IsFreeStanding = isFreeStanding;
}
- /// \brief Whether this declaration declares a type that is
+ /// Whether this declaration declares a type that is
/// dependent, i.e., a type that somehow depends on template
/// parameters.
bool isDependentType() const { return isDependentContext(); }
- /// @brief Starts the definition of this tag declaration.
+ /// Starts the definition of this tag declaration.
///
/// This method should be invoked at the beginning of the definition
/// of this tag declaration. It will set the tag type into a state
/// where it is in the process of being defined.
void startDefinition();
- /// getDefinition - Returns the TagDecl that actually defines this
+ /// Returns the TagDecl that actually defines this
/// struct/union/class/enum. When determining whether or not a
/// struct/union/class/enum has a definition, one should use this
/// method as opposed to 'isDefinition'. 'isDefinition' indicates
@@ -3191,14 +3262,14 @@ public:
void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
- /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// Retrieve the nested-name-specifier that qualifies the name of this
/// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
: nullptr;
}
- /// \brief Retrieve the nested-name-specifier (with source-location
+ /// Retrieve the nested-name-specifier (with source-location
/// information) that qualifies the name of this declaration, if it was
/// present in the source.
NestedNameSpecifierLoc getQualifierLoc() const {
@@ -3233,11 +3304,11 @@ public:
}
};
-/// EnumDecl - Represents an enum. In C++11, enums can be forward-declared
+/// 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 {
- /// IntegerType - This represent the integer type that the enum corresponds
+ /// 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.
///
@@ -3253,17 +3324,21 @@ class EnumDecl : public TagDecl {
/// extra pointer when TypeSourceInfo is needed.
llvm::PointerUnion<const Type *, TypeSourceInfo *> IntegerType;
- /// PromotionType - The integer type that values of this type should
+ /// The integer type that values of this type should
/// promote to. In C, enumerators are generally of an integer type
/// directly, but gcc-style large enumerators (and all enumerators
/// in C++) are of the enum type instead.
QualType PromotionType;
- /// \brief If this enumeration is an instantiation of a member enumeration
+ /// If this enumeration is an instantiation of a member enumeration
/// of a class template specialization, this is the member specialization
/// information.
MemberSpecializationInfo *SpecializationInfo = nullptr;
+ /// Store the ODRHash after first calculation.
+ unsigned HasODRHash : 1;
+ unsigned ODRHash;
+
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
bool Scoped, bool ScopedUsingClassTag, bool Fixed)
@@ -3275,6 +3350,8 @@ class EnumDecl : public TagDecl {
IsScoped = Scoped;
IsScopedUsingClassTag = ScopedUsingClassTag;
IsFixed = Fixed;
+ HasODRHash = false;
+ ODRHash = 0;
}
void anchor() override;
@@ -3317,9 +3394,9 @@ public:
bool IsFixed);
static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// completeDefinition - When created, the EnumDecl corresponds to a
+ /// When created, the EnumDecl corresponds to a
/// forward-declared enum. This method is used to mark the
- /// declaration as being defined; it's enumerators have already been
+ /// declaration as being defined; its enumerators have already been
/// added (via DeclContext::addDecl). NewType is the new underlying
/// type of the enumeration type.
void completeDefinition(QualType NewType,
@@ -3327,8 +3404,7 @@ public:
unsigned NumPositiveBits,
unsigned NumNegativeBits);
- // enumerator_iterator - Iterates through the enumerators of this
- // enumeration.
+ // Iterates through the enumerators of this enumeration.
using enumerator_iterator = specific_decl_iterator<EnumConstantDecl>;
using enumerator_range =
llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>;
@@ -3351,14 +3427,13 @@ public:
return enumerator_iterator(E->decls_end());
}
- /// getPromotionType - Return the integer type that enumerators
- /// should promote to.
+ /// Return the integer type that enumerators should promote to.
QualType getPromotionType() const { return PromotionType; }
- /// \brief Set the promotion type.
+ /// Set the promotion type.
void setPromotionType(QualType T) { PromotionType = T; }
- /// getIntegerType - Return the integer type this enum decl corresponds to.
+ /// Return the integer type this enum decl corresponds to.
/// This returns a null QualType for an enum forward definition with no fixed
/// underlying type.
QualType getIntegerType() const {
@@ -3369,23 +3444,23 @@ public:
return IntegerType.get<TypeSourceInfo*>()->getType().getUnqualifiedType();
}
- /// \brief Set the underlying integer type.
+ /// Set the underlying integer type.
void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); }
- /// \brief Set the underlying integer type source info.
+ /// Set the underlying integer type source info.
void setIntegerTypeSourceInfo(TypeSourceInfo *TInfo) { IntegerType = TInfo; }
- /// \brief Return the type source info for the underlying integer type,
+ /// Return the type source info for the underlying integer type,
/// if no type source info exists, return 0.
TypeSourceInfo *getIntegerTypeSourceInfo() const {
return IntegerType.dyn_cast<TypeSourceInfo*>();
}
- /// \brief Retrieve the source range that covers the underlying type if
+ /// Retrieve the source range that covers the underlying type if
/// specified.
SourceRange getIntegerTypeRange() const LLVM_READONLY;
- /// \brief Returns the width in bits required to store all the
+ /// Returns the width in bits required to store all the
/// non-negative enumerators of this enum.
unsigned getNumPositiveBits() const {
return NumPositiveBits;
@@ -3395,7 +3470,7 @@ public:
assert(NumPositiveBits == Num && "can't store this bitcount");
}
- /// \brief Returns the width in bits required to store all the
+ /// Returns the width in bits required to store all the
/// negative enumerators of this enum. These widths include
/// the rightmost leading 1; that is:
///
@@ -3411,25 +3486,29 @@ public:
NumNegativeBits = Num;
}
- /// \brief Returns true if this is a C++11 scoped enumeration.
+ /// Returns true if this is a C++11 scoped enumeration.
bool isScoped() const {
return IsScoped;
}
- /// \brief Returns true if this is a C++11 scoped enumeration.
+ /// Returns true if this is a C++11 scoped enumeration.
bool isScopedUsingClassTag() const {
return IsScopedUsingClassTag;
}
- /// \brief Returns true if this is an Objective-C, C++11, or
+ /// Returns true if this is an Objective-C, C++11, or
/// Microsoft-style enumeration with a fixed underlying type.
bool isFixed() const {
return IsFixed;
}
- /// \brief Returns true if this can be considered a complete type.
+ unsigned getODRHash();
+
+ /// Returns true if this can be considered a complete type.
bool isComplete() const {
- return isCompleteDefinition() || isFixed();
+ // IntegerType is set for fixed type enums and non-fixed but implicitly
+ // int-sized Microsoft enums.
+ return isCompleteDefinition() || IntegerType;
}
/// Returns true if this enum is either annotated with
@@ -3444,33 +3523,33 @@ public:
/// enum_extensibility(open).
bool isClosedNonFlag() const;
- /// \brief Retrieve the enum definition from which this enumeration could
+ /// Retrieve the enum definition from which this enumeration could
/// be instantiated, if it is an instantiation (rather than a non-template).
EnumDecl *getTemplateInstantiationPattern() const;
- /// \brief Returns the enumeration (declared within the template)
+ /// Returns the enumeration (declared within the template)
/// from which this enumeration type was instantiated, or NULL if
/// this enumeration was not instantiated from any template.
EnumDecl *getInstantiatedFromMemberEnum() const;
- /// \brief If this enumeration is a member of a specialization of a
+ /// If this enumeration is a member of a specialization of a
/// templated class, determine what kind of template specialization
/// or instantiation this is.
TemplateSpecializationKind getTemplateSpecializationKind() const;
- /// \brief For an enumeration member that was instantiated from a member
+ /// For an enumeration member that was instantiated from a member
/// enumeration of a templated class, set the template specialiation kind.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation = SourceLocation());
- /// \brief If this enumeration is an instantiation of a member enumeration of
+ /// If this enumeration is an instantiation of a member enumeration of
/// a class template specialization, retrieves the member specialization
/// information.
MemberSpecializationInfo *getMemberSpecializationInfo() const {
return SpecializationInfo;
}
- /// \brief Specify that this enumeration is an instantiation of the
+ /// Specify that this enumeration is an instantiation of the
/// member enumeration ED.
void setInstantiationOfMemberEnum(EnumDecl *ED,
TemplateSpecializationKind TSK) {
@@ -3481,36 +3560,74 @@ public:
static bool classofKind(Kind K) { return K == Enum; }
};
-/// RecordDecl - Represents a struct/union/class. For example:
+/// 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 {
+public:
+ /// Enum that represents the different ways arguments are passed to and
+ /// returned from function calls. This takes into account the target-specific
+ /// and version-specific rules along with the rules determined by the
+ /// language.
+ enum ArgPassingKind : unsigned {
+ /// The argument of this type can be passed directly in registers.
+ APK_CanPassInRegs,
+
+ /// The argument of this type cannot be passed directly in registers.
+ /// Records containing this type as a subobject are not forced to be passed
+ /// indirectly. This value is used only in C++. This value is required by
+ /// C++ because, in uncommon situations, it is possible for a class to have
+ /// only trivial copy/move constructors even when one of its subobjects has
+ /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move
+ /// constructor in the derived class is deleted).
+ APK_CannotPassInRegs,
+
+ /// The argument of this type cannot be passed directly in registers.
+ /// Records containing this type as a subobject are forced to be passed
+ /// indirectly.
+ APK_CanNeverPassInRegs
+ };
+
+private:
friend class DeclContext;
// FIXME: This can be packed into the bitfields in Decl.
- /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
+ /// This is true if this struct ends with a flexible
/// array member (e.g. int X[]) or if this union contains a struct that does.
/// If so, this cannot be contained in arrays or other structs as a member.
- bool HasFlexibleArrayMember : 1;
+ unsigned HasFlexibleArrayMember : 1;
- /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct
- /// or union.
- bool AnonymousStructOrUnion : 1;
+ /// Whether this is the type of an anonymous struct or union.
+ unsigned AnonymousStructOrUnion : 1;
- /// HasObjectMember - This is true if this struct has at least one member
+ /// This is true if this struct has at least one member
/// containing an Objective-C object pointer type.
- bool HasObjectMember : 1;
-
- /// HasVolatileMember - This is true if struct has at least one member of
+ unsigned HasObjectMember : 1;
+
+ /// This is true if struct has at least one member of
/// 'volatile' type.
- bool HasVolatileMember : 1;
+ unsigned HasVolatileMember : 1;
- /// \brief Whether the field declarations of this record have been loaded
+ /// Whether the field declarations of this record have been loaded
/// from external storage. To avoid unnecessary deserialization of
/// methods/nested types we allow deserialization of just the fields
/// when needed.
- mutable bool LoadedFieldsFromExternalStorage : 1;
+ mutable unsigned LoadedFieldsFromExternalStorage : 1;
+
+ /// Basic properties of non-trivial C structs.
+ unsigned NonTrivialToPrimitiveDefaultInitialize : 1;
+ unsigned NonTrivialToPrimitiveCopy : 1;
+ unsigned NonTrivialToPrimitiveDestroy : 1;
+
+ /// Indicates whether this struct is destroyed in the callee.
+ ///
+ /// Please note that MSVC won't merge adjacent bitfields if they don't have
+ /// the same type.
+ unsigned ParamDestroyedInCallee : 1;
+
+ /// Represents the way this type is passed to a function.
+ unsigned ArgPassingRestrictions : 2;
protected:
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
@@ -3541,10 +3658,9 @@ public:
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
- /// isAnonymousStructOrUnion - Whether this is an anonymous struct
- /// or union. To be an anonymous struct or union, it must have been
- /// declared without a name and there must be no objects of this
- /// type declared, e.g.,
+ /// Whether this is an anonymous struct or union. To be an anonymous
+ /// struct or union, it must have been declared without a name and
+ /// there must be no objects of this type declared, e.g.,
/// @code
/// union { int i; float f; };
/// @endcode
@@ -3571,7 +3687,55 @@ public:
LoadedFieldsFromExternalStorage = val;
}
- /// \brief Determines whether this declaration represents the
+ /// Functions to query basic properties of non-trivial C structs.
+ bool isNonTrivialToPrimitiveDefaultInitialize() const {
+ return NonTrivialToPrimitiveDefaultInitialize;
+ }
+
+ void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
+ NonTrivialToPrimitiveDefaultInitialize = V;
+ }
+
+ bool isNonTrivialToPrimitiveCopy() const {
+ return NonTrivialToPrimitiveCopy;
+ }
+
+ void setNonTrivialToPrimitiveCopy(bool V) {
+ NonTrivialToPrimitiveCopy = V;
+ }
+
+ bool isNonTrivialToPrimitiveDestroy() const {
+ return NonTrivialToPrimitiveDestroy;
+ }
+
+ void setNonTrivialToPrimitiveDestroy(bool V) {
+ NonTrivialToPrimitiveDestroy = V;
+ }
+
+ /// Determine whether this class can be passed in registers. In C++ mode,
+ /// it must have at least one trivial, non-deleted copy or move constructor.
+ /// FIXME: This should be set as part of completeDefinition.
+ bool canPassInRegisters() const {
+ return getArgPassingRestrictions() == APK_CanPassInRegs;
+ }
+
+ ArgPassingKind getArgPassingRestrictions() const {
+ return static_cast<ArgPassingKind>(ArgPassingRestrictions);
+ }
+
+ void setArgPassingRestrictions(ArgPassingKind Kind) {
+ ArgPassingRestrictions = static_cast<uint8_t>(Kind);
+ }
+
+ bool isParamDestroyedInCallee() const {
+ return ParamDestroyedInCallee;
+ }
+
+ void setParamDestroyedInCallee(bool V) {
+ ParamDestroyedInCallee = V;
+ }
+
+ /// Determines whether this declaration represents the
/// injected class name.
///
/// The injected class name in C++ is the name of the class that
@@ -3586,19 +3750,19 @@ public:
/// \endcode
bool isInjectedClassName() const;
- /// \brief Determine whether this record is a class describing a lambda
+ /// Determine whether this record is a class describing a lambda
/// function object.
bool isLambda() const;
- /// \brief Determine whether this record is a record for captured variables in
+ /// 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
+ /// Mark the record as a record for captured variables in CapturedStmt
/// construct.
void setCapturedRecord();
- /// getDefinition - Returns the RecordDecl that actually defines
+ /// Returns the RecordDecl that actually defines
/// this struct/union/class. When determining whether or not a
/// struct/union/class is completely defined, one should use this
/// method as opposed to 'isCompleteDefinition'.
@@ -3623,14 +3787,12 @@ public:
return field_iterator(decl_iterator());
}
- // field_empty - Whether there are any fields (non-static data
- // members) in this record.
+ // Whether there are any fields (non-static data members) in this record.
bool field_empty() const {
return field_begin() == field_end();
}
- /// completeDefinition - Notes that the definition of this type is
- /// now complete.
+ /// Note that the definition of this type is now complete.
virtual void completeDefinition();
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -3638,22 +3800,22 @@ public:
return K >= firstRecord && K <= lastRecord;
}
- /// \brief Get whether or not this is an ms_struct which can
+ /// Get whether or not this is an ms_struct which can
/// be turned on with an attribute, pragma, or -mms-bitfields
/// commandline option.
bool isMsStruct(const ASTContext &C) const;
- /// \brief Whether we are allowed to insert extra padding between fields.
+ /// Whether we are allowed to insert extra padding between fields.
/// These padding are added to help AddressSanitizer detect
/// intra-object-overflow bugs.
bool mayInsertExtraPadding(bool EmitRemark = false) const;
/// Finds the first data member which has a name.
/// nullptr is returned if no named data member exists.
- const FieldDecl *findFirstNamedDataMember() const;
+ const FieldDecl *findFirstNamedDataMember() const;
private:
- /// \brief Deserialize just the fields.
+ /// Deserialize just the fields.
void LoadFieldsFromExternalStorage() const;
};
@@ -3673,7 +3835,7 @@ public:
SourceLocation RParenLoc);
static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
SourceLocation getAsmLoc() const { return getLocation(); }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -3689,7 +3851,7 @@ public:
static bool classofKind(Kind K) { return K == FileScopeAsm; }
};
-/// BlockDecl - This represents a block literal declaration, which is like an
+/// Pepresents 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 {
@@ -3739,7 +3901,11 @@ private:
bool BlockMissingReturnType : 1;
bool IsConversionFromLambda : 1;
- /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
+ /// A bit that indicates this block is passed directly to a function as a
+ /// non-escaping parameter.
+ bool DoesNotEscape : 1;
+
+ /// A 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 = nullptr;
@@ -3758,12 +3924,12 @@ protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
: Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false),
CapturesCXXThis(false), BlockMissingReturnType(true),
- IsConversionFromLambda(false) {}
+ IsConversionFromLambda(false), DoesNotEscape(false) {}
public:
- static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
+ static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
SourceLocation getCaretLocation() const { return getLocation(); }
bool isVariadic() const { return IsVariadic; }
@@ -3808,11 +3974,11 @@ public:
void setParams(ArrayRef<ParmVarDecl *> NewParamInfo);
- /// hasCaptures - True if this block (or its nested blocks) captures
+ /// True if this block (or its nested blocks) captures
/// anything of local storage from its enclosing scopes.
bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; }
- /// getNumCaptures - Returns the number of captured variables.
+ /// Returns the number of captured variables.
/// Does not include an entry for 'this'.
unsigned getNumCaptures() const { return NumCaptures; }
@@ -3830,6 +3996,9 @@ public:
bool isConversionFromLambda() const { return IsConversionFromLambda; }
void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; }
+ bool doesNotEscape() const { return DoesNotEscape; }
+ void setDoesNotEscape() { DoesNotEscape = true; }
+
bool capturesVariable(const VarDecl *var) const;
void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
@@ -3840,7 +4009,7 @@ public:
}
Decl *getBlockManglingContextDecl() const {
- return ManglingContextDecl;
+ return ManglingContextDecl;
}
void setBlockMangling(unsigned Number, Decl *Ctx) {
@@ -3861,8 +4030,7 @@ public:
}
};
-/// \brief This represents the body of a CapturedStmt, and serves as its
-/// DeclContext.
+/// Represents the body of a CapturedStmt, and serves as its DeclContext.
class CapturedDecl final
: public Decl,
public DeclContext,
@@ -3873,13 +4041,13 @@ protected:
}
private:
- /// \brief The number of parameters to the outlined function.
+ /// The number of parameters to the outlined function.
unsigned NumParams;
- /// \brief The position of context parameter in list of parameters.
+ /// The position of context parameter in list of parameters.
unsigned ContextParam;
- /// \brief The body of the outlined function.
+ /// The body of the outlined function.
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
explicit CapturedDecl(DeclContext *DC, unsigned NumParams);
@@ -3927,7 +4095,7 @@ public:
return {getParams(), getNumParams()};
}
- /// \brief Retrieve the parameter containing captured variables.
+ /// Retrieve the parameter containing captured variables.
ImplicitParamDecl *getContextParam() const {
assert(ContextParam < NumParams);
return getParam(ContextParam);
@@ -3942,9 +4110,9 @@ public:
using param_iterator = ImplicitParamDecl *const *;
using param_range = llvm::iterator_range<param_iterator>;
- /// \brief Retrieve an iterator pointing to the first parameter decl.
+ /// Retrieve an iterator pointing to the first parameter decl.
param_iterator param_begin() const { return getParams(); }
- /// \brief Retrieve an iterator one past the last parameter decl.
+ /// Retrieve an iterator one past the last parameter decl.
param_iterator param_end() const { return getParams() + NumParams; }
// Implement isa/cast/dyncast/etc.
@@ -3958,7 +4126,7 @@ public:
}
};
-/// \brief Describes a module import declaration, which makes the contents
+/// Describes a module import declaration, which makes the contents
/// of the named module visible in the current translation unit.
///
/// An import declaration imports the named module (or submodule). For example:
@@ -3975,18 +4143,18 @@ class ImportDecl final : public Decl,
friend class ASTReader;
friend TrailingObjects;
- /// \brief The imported module, along with a bit that indicates whether
+ /// The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
- /// name.
+ /// name.
///
/// When the bit is false, we only have a single source location for the
/// end of the import declaration.
llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
-
- /// \brief The next import in the list of imports local to the translation
+
+ /// The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
ImportDecl *NextLocalImport = nullptr;
-
+
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
@@ -3994,27 +4162,27 @@ class ImportDecl final : public Decl,
SourceLocation EndLoc);
ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
-
+
public:
- /// \brief Create a new module import declaration.
- static ImportDecl *Create(ASTContext &C, DeclContext *DC,
+ /// Create a new module import declaration.
+ static ImportDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
-
- /// \brief Create a new module import declaration for an implicitly-generated
+
+ /// Create a new module import declaration for an implicitly-generated
/// import.
- static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
- SourceLocation StartLoc, Module *Imported,
+ static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, Module *Imported,
SourceLocation EndLoc);
-
- /// \brief Create a new, deserialized module import declaration.
- static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+
+ /// Create a new, deserialized module import declaration.
+ static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumLocations);
-
- /// \brief Retrieve the module that was imported by the import declaration.
+
+ /// Retrieve the module that was imported by the import declaration.
Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
-
- /// \brief Retrieves the locations of each of the identifiers that make up
+
+ /// Retrieves the locations of each of the identifiers that make up
/// the complete module name in the import declaration.
///
/// This will return an empty array if the locations of the individual
@@ -4027,7 +4195,7 @@ public:
static bool classofKind(Kind K) { return K == Import; }
};
-/// \brief Represents a C++ Modules TS module export declaration.
+/// Represents a C++ Modules TS module export declaration.
///
/// For example:
/// \code
@@ -4039,7 +4207,7 @@ class ExportDecl final : public Decl, public DeclContext {
private:
friend class ASTDeclReader;
- /// \brief The source location for the right brace (if valid).
+ /// The source location for the right brace (if valid).
SourceLocation RBraceLoc;
ExportDecl(DeclContext *DC, SourceLocation ExportLoc)
@@ -4050,7 +4218,7 @@ public:
static ExportDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation ExportLoc);
static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
SourceLocation getExportLoc() const { return getLocation(); }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
@@ -4077,7 +4245,7 @@ public:
}
};
-/// \brief Represents an empty-declaration.
+/// Represents an empty-declaration.
class EmptyDecl : public Decl {
EmptyDecl(DeclContext *DC, SourceLocation L) : Decl(Empty, DC, L) {}
@@ -4111,7 +4279,7 @@ template<typename decl_type>
void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
// Note: This routine is implemented here because we need both NamedDecl
// and Redeclarable to be defined.
- assert(RedeclLink.NextIsLatest() &&
+ assert(RedeclLink.isFirst() &&
"setPreviousDecl on a decl already in a redeclaration chain");
if (PrevDecl) {
@@ -4119,7 +4287,7 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
// redeclaration, or we can build invalid chains. If the most recent
// redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
First = PrevDecl->getFirstDecl();
- assert(First->RedeclLink.NextIsLatest() && "Expected first");
+ assert(First->RedeclLink.isFirst() && "Expected first");
decl_type *MostRecent = First->getNextRedeclaration();
RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent));
@@ -4142,7 +4310,7 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
// Inline function definitions.
-/// \brief Check if the given decl is complete.
+/// Check if the given decl is complete.
///
/// We use this function to break a cycle between the inline definitions in
/// Type.h and Decl.h.
@@ -4150,7 +4318,7 @@ inline bool IsEnumDeclComplete(EnumDecl *ED) {
return ED->isComplete();
}
-/// \brief Check if the given decl is scoped.
+/// Check if the given decl is scoped.
///
/// We use this function to break a cycle between the inline definitions in
/// Type.h and Decl.h.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
index 15de482a8619..d6b89d971d94 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -19,7 +19,6 @@
#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"
@@ -28,6 +27,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/VersionTuple.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -67,7 +67,7 @@ class TemplateDecl;
class TranslationUnitDecl;
class UsingDirectiveDecl;
-/// \brief Captures the result of checking the availability of a
+/// Captures the result of checking the availability of a
/// declaration.
enum AvailabilityResult {
AR_Available = 0,
@@ -83,9 +83,9 @@ enum AvailabilityResult {
/// (and its subclasses) in its Decl::operator new(). Proper alignment
/// of all subclasses (not requiring more than the alignment of Decl) is
/// asserted in DeclBase.cpp.
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
+class alignas(8) Decl {
public:
- /// \brief Lists the kind of concrete classes of Decl.
+ /// Lists the kind of concrete classes of Decl.
enum Kind {
#define DECL(DERIVED, BASE) DERIVED,
#define ABSTRACT_DECL(DECL)
@@ -96,7 +96,7 @@ public:
#include "clang/AST/DeclNodes.inc"
};
- /// \brief A placeholder type used to construct an empty shell of a
+ /// 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 {};
@@ -231,7 +231,7 @@ public:
};
protected:
- /// \brief The next declaration within the same lexical
+ /// The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end().
///
@@ -288,27 +288,28 @@ private:
/// the implementation rather than explicitly written by the user.
unsigned Implicit : 1;
- /// \brief Whether this declaration was "used", meaning that a definition is
+ /// Whether this declaration was "used", meaning that a definition is
/// required.
unsigned Used : 1;
- /// \brief Whether this declaration was "referenced".
+ /// Whether this declaration was "referenced".
/// The difference with 'Used' is whether the reference appears in a
/// evaluated context or not, e.g. functions used in uninstantiated templates
/// are regarded as "referenced" but not "used".
unsigned Referenced : 1;
- /// \brief Whether this declaration is a top-level declaration (function,
+ /// Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
unsigned TopLevelDeclInObjCContainer : 1;
-
- /// \brief Whether statistic collection is enabled.
+
+ /// Whether statistic collection is enabled.
static bool StatisticsEnabled;
protected:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend class ASTNodeImporter;
friend class ASTReader;
friend class CXXClassMemberWrapper;
friend class LinkageComputer;
@@ -318,17 +319,17 @@ protected:
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
- /// \brief Whether this declaration was loaded from an AST file.
+ /// Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 13;
- /// \brief If 0, we have not computed the linkage of this declaration.
+ /// If 0, we have not computed the linkage of this declaration.
/// Otherwise, it is the linkage + 1.
mutable unsigned CacheValidAndLinkage : 3;
- /// \brief Allocate memory for a deserialized declaration.
+ /// Allocate memory for a deserialized declaration.
///
/// This routine must be used to allocate memory for any declaration that is
/// deserialized from a module file.
@@ -340,7 +341,7 @@ protected:
void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID,
std::size_t Extra = 0);
- /// \brief Allocate memory for a non-deserialized declaration.
+ /// Allocate memory for a non-deserialized declaration.
void *operator new(std::size_t Size, const ASTContext &Ctx,
DeclContext *Parent, std::size_t Extra = 0);
@@ -384,7 +385,7 @@ protected:
virtual ~Decl();
- /// \brief Update a potentially out-of-date declaration.
+ /// Update a potentially out-of-date declaration.
void updateOutOfDate(IdentifierInfo &II) const;
Linkage getCachedLinkage() const {
@@ -400,7 +401,7 @@ protected:
}
public:
- /// \brief Source range that this declaration covers.
+ /// Source range that this declaration covers.
virtual SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocation(), getLocation());
}
@@ -462,7 +463,7 @@ public:
return AccessSpecifier(Access);
}
- /// \brief Retrieve the access specifier for this declaration, even though
+ /// Retrieve the access specifier for this declaration, even though
/// it may not yet have been properly set.
AccessSpecifier getAccessUnsafe() const {
return AccessSpecifier(Access);
@@ -551,7 +552,7 @@ public:
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
- /// \brief Whether *any* (re-)declaration of the entity was used, meaning that
+ /// Whether *any* (re-)declaration of the entity was used, meaning that
/// a definition is required.
///
/// \param CheckUsedAttr When true, also consider the "used" attribute
@@ -559,28 +560,28 @@ public:
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
- /// \brief Set whether the declaration is used, in the sense of odr-use.
+ /// Set whether the declaration is used, in the sense of odr-use.
///
/// This should only be used immediately after creating a declaration.
/// It intentionally doesn't notify any listeners.
void setIsUsed() { getCanonicalDecl()->Used = true; }
- /// \brief Mark the declaration used, in the sense of odr-use.
+ /// Mark the declaration used, in the sense of odr-use.
///
/// This notifies any mutation listeners in addition to setting a bit
/// indicating the declaration is used.
void markUsed(ASTContext &C);
- /// \brief Whether any declaration of this entity was referenced.
+ /// Whether any declaration of this entity was referenced.
bool isReferenced() const;
- /// \brief Whether this declaration was referenced. This should not be relied
+ /// Whether this declaration was referenced. This should not be relied
/// upon for anything other than debugging.
bool isThisDeclarationReferenced() const { return Referenced; }
void setReferenced(bool R = true) { Referenced = R; }
- /// \brief Whether this declaration is a top-level declaration (function,
+ /// Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
bool isTopLevelDeclInObjCContainer() const {
@@ -591,17 +592,17 @@ public:
TopLevelDeclInObjCContainer = V;
}
- /// \brief Looks on this and related declarations for an applicable
+ /// Looks on this and related declarations for an applicable
/// external source symbol attribute.
ExternalSourceSymbolAttr *getExternalSourceSymbolAttr() const;
- /// \brief Whether this declaration was marked as being private to the
+ /// Whether this declaration was marked as being private to the
/// module in which it was defined.
bool isModulePrivate() const {
return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
}
- /// \brief Whether this declaration is exported (by virtue of being lexically
+ /// Whether this declaration is exported (by virtue of being lexically
/// within an ExportDecl or by being a NamespaceDecl).
bool isExported() const;
@@ -613,7 +614,7 @@ public:
const Attr *getDefiningAttr() const;
protected:
- /// \brief Specify that this declaration was marked as being private
+ /// Specify that this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate() {
// The module-private specifier has no effect on unowned declarations.
@@ -623,14 +624,14 @@ protected:
setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate);
}
- /// \brief Set the owning module ID.
+ /// Set the owning module ID.
void setOwningModuleID(unsigned ID) {
assert(isFromASTFile() && "Only works on a deserialized declaration");
*((unsigned*)this - 2) = ID;
}
-
+
public:
- /// \brief Determine the availability of the given declaration.
+ /// Determine the availability of the given declaration.
///
/// This routine will determine the most restrictive availability of
/// the given declaration (e.g., preferring 'unavailable' to
@@ -643,11 +644,16 @@ public:
///
/// \param EnclosingVersion The version to compare with. If empty, assume the
/// deployment target version.
+ ///
+ /// \param RealizedPlatform If non-NULL and the availability result is found
+ /// in an available attribute it will set to the platform which is written in
+ /// the available attribute.
AvailabilityResult
getAvailability(std::string *Message = nullptr,
- VersionTuple EnclosingVersion = VersionTuple()) const;
+ VersionTuple EnclosingVersion = VersionTuple(),
+ StringRef *RealizedPlatform = nullptr) const;
- /// \brief Retrieve the version of the target platform in which this
+ /// Retrieve the version of the target platform in which this
/// declaration was introduced.
///
/// \returns An empty version tuple if this declaration has no 'introduced'
@@ -655,7 +661,7 @@ public:
/// attribute otherwise.
VersionTuple getVersionIntroduced() const;
- /// \brief Determine whether this declaration is marked 'deprecated'.
+ /// Determine whether this declaration is marked 'deprecated'.
///
/// \param Message If non-NULL and the declaration is deprecated,
/// this will be set to the message describing why the declaration
@@ -664,7 +670,7 @@ public:
return getAvailability(Message) == AR_Deprecated;
}
- /// \brief Determine whether this declaration is marked 'unavailable'.
+ /// Determine whether this declaration is marked 'unavailable'.
///
/// \param Message If non-NULL and the declaration is unavailable,
/// this will be set to the message describing why the declaration
@@ -673,7 +679,7 @@ public:
return getAvailability(Message) == AR_Unavailable;
}
- /// \brief Determine whether this is a weak-imported symbol.
+ /// Determine whether this is a weak-imported symbol.
///
/// Weak-imported symbols are typically marked with the
/// 'weak_import' attribute, but may also be marked with an
@@ -681,7 +687,7 @@ public:
/// the introduction of this feature.
bool isWeakImported() const;
- /// \brief Determines whether this symbol can be weak-imported,
+ /// Determines whether this symbol can be weak-imported,
/// e.g., whether it would be well-formed to add the weak_import
/// attribute.
///
@@ -689,11 +695,11 @@ public:
/// declaration cannot be weak-imported because it has a definition.
bool canBeWeakImported(bool &IsDefinition) const;
- /// \brief Determine whether this declaration came from an AST file (such as
+ /// Determine whether this declaration came from an AST file (such as
/// a precompiled header or module) rather than having been parsed.
bool isFromASTFile() const { return FromASTFile; }
- /// \brief Retrieve the global declaration ID associated with this
+ /// Retrieve the global declaration ID associated with this
/// declaration, which specifies where this Decl was loaded from.
unsigned getGlobalID() const {
if (isFromASTFile())
@@ -701,7 +707,7 @@ public:
return 0;
}
- /// \brief Retrieve the global ID of the module that owns this particular
+ /// Retrieve the global ID of the module that owns this particular
/// declaration.
unsigned getOwningModuleID() const {
if (isFromASTFile())
@@ -716,7 +722,7 @@ protected:
bool hasLocalOwningModuleStorage() const;
public:
- /// \brief Get the imported owning module, if this decl is from an imported
+ /// Get the imported owning module, if this decl is from an imported
/// (non-local) module.
Module *getImportedOwningModule() const {
if (!isFromASTFile() || !hasOwningModule())
@@ -725,7 +731,7 @@ public:
return getOwningModuleSlow();
}
- /// \brief Get the local owning module, if known. Returns nullptr if owner is
+ /// Get the local owning module, if known. Returns nullptr if owner is
/// not yet known or declaration is not from a module.
Module *getLocalOwningModule() const {
if (isFromASTFile() || !hasOwningModule())
@@ -759,7 +765,7 @@ public:
/// 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
+ /// 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.
// FIXME: Rename this to make it clearer what it does.
@@ -774,12 +780,12 @@ public:
setModuleOwnershipKind(ModuleOwnershipKind::Visible);
}
- /// \brief Get the kind of module ownership for this declaration.
+ /// Get the kind of module ownership for this declaration.
ModuleOwnershipKind getModuleOwnershipKind() const {
return NextInContextAndBits.getInt();
}
- /// \brief Set whether this declaration is hidden from name lookup.
+ /// Set whether this declaration is hidden from name lookup.
void setModuleOwnershipKind(ModuleOwnershipKind MOK) {
assert(!(getModuleOwnershipKind() == ModuleOwnershipKind::Unowned &&
MOK != ModuleOwnershipKind::Unowned && !isFromASTFile() &&
@@ -848,7 +854,7 @@ public:
return getParentFunctionOrMethod() == nullptr;
}
- /// \brief Returns true if this declaration lexically is inside a function.
+ /// Returns true if this declaration lexically is inside a function.
/// It recognizes non-defining declarations as well as members of local
/// classes:
/// \code
@@ -857,7 +863,7 @@ public:
/// \endcode
bool isLexicallyWithinFunctionOrMethod() const;
- /// \brief If this decl is defined inside a function/method/block it returns
+ /// If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
const DeclContext *getParentFunctionOrMethod() const;
DeclContext *getParentFunctionOrMethod() {
@@ -865,32 +871,32 @@ public:
const_cast<const Decl*>(this)->getParentFunctionOrMethod());
}
- /// \brief Retrieves the "canonical" declaration of the given declaration.
+ /// Retrieves the "canonical" declaration of the given declaration.
virtual Decl *getCanonicalDecl() { return this; }
const Decl *getCanonicalDecl() const {
return const_cast<Decl*>(this)->getCanonicalDecl();
}
- /// \brief Whether this particular Decl is a canonical one.
+ /// Whether this particular Decl is a canonical one.
bool isCanonicalDecl() const { return getCanonicalDecl() == this; }
-
+
protected:
- /// \brief Returns the next redeclaration or itself if this is the only decl.
+ /// Returns the next redeclaration or itself if this is the only decl.
///
/// Decl subclasses that can be redeclared should override this method so that
/// Decl::redecl_iterator can iterate over them.
virtual Decl *getNextRedeclarationImpl() { return this; }
- /// \brief Implementation of getPreviousDecl(), to be overridden by any
+ /// Implementation of getPreviousDecl(), to be overridden by any
/// subclass that has a redeclaration chain.
virtual Decl *getPreviousDeclImpl() { return nullptr; }
- /// \brief Implementation of getMostRecentDecl(), to be overridden by any
+ /// Implementation of getMostRecentDecl(), to be overridden by any
/// subclass that has a redeclaration chain.
virtual Decl *getMostRecentDeclImpl() { return this; }
public:
- /// \brief Iterates through all the redeclarations of the same decl.
+ /// Iterates through all the redeclarations of the same decl.
class redecl_iterator {
/// Current - The current declaration.
Decl *Current = nullptr;
@@ -935,7 +941,7 @@ public:
using redecl_range = llvm::iterator_range<redecl_iterator>;
- /// \brief Returns an iterator range for all the redeclarations of the same
+ /// Returns an iterator range for all the redeclarations of the same
/// decl. It will iterate at least once (when this decl is the only one).
redecl_range redecls() const {
return redecl_range(redecls_begin(), redecls_end());
@@ -947,28 +953,28 @@ public:
redecl_iterator redecls_end() const { return redecl_iterator(); }
- /// \brief Retrieve the previous declaration that declares the same entity
+ /// Retrieve the previous declaration that declares the same entity
/// as this declaration, or NULL if there is no previous declaration.
Decl *getPreviousDecl() { return getPreviousDeclImpl(); }
-
- /// \brief Retrieve the most recent declaration that declares the same entity
+
+ /// Retrieve the most recent declaration that declares the same entity
/// as this declaration, or NULL if there is no previous declaration.
- const Decl *getPreviousDecl() const {
+ const Decl *getPreviousDecl() const {
return const_cast<Decl *>(this)->getPreviousDeclImpl();
}
- /// \brief True if this is the first declaration in its redeclaration chain.
+ /// True if this is the first declaration in its redeclaration chain.
bool isFirstDecl() const {
return getPreviousDecl() == nullptr;
}
- /// \brief Retrieve the most recent declaration that declares the same entity
+ /// Retrieve the most recent declaration that declares the same entity
/// as this declaration (which may be this declaration).
Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); }
- /// \brief Retrieve the most recent declaration that declares the same entity
+ /// Retrieve the most recent declaration that declares the same entity
/// as this declaration (which may be this declaration).
- const Decl *getMostRecentDecl() const {
+ const Decl *getMostRecentDecl() const {
return const_cast<Decl *>(this)->getMostRecentDeclImpl();
}
@@ -977,7 +983,7 @@ public:
/// top-level Stmt* of that body. Otherwise this method returns null.
virtual Stmt* getBody() const { return nullptr; }
- /// \brief Returns true if this \c Decl represents a declaration for a body of
+ /// Returns true if this \c Decl represents a declaration for a body of
/// code, such as a function or method definition.
/// Note that \c hasBody can also return true if any redeclaration of this
/// \c Decl represents a declaration for a body of code.
@@ -1000,24 +1006,24 @@ public:
/// template parameter pack.
bool isTemplateParameterPack() const;
- /// \brief Whether this declaration is a parameter pack.
+ /// Whether this declaration is a parameter pack.
bool isParameterPack() const;
- /// \brief returns true if this declaration is a template
+ /// returns true if this declaration is a template
bool isTemplateDecl() const;
- /// \brief Whether this declaration is a function or function template.
+ /// Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const {
return (DeclKind >= Decl::firstFunction &&
DeclKind <= Decl::lastFunction) ||
DeclKind == FunctionTemplate;
}
- /// \brief If this is a declaration that describes some template, this
+ /// If this is a declaration that describes some template, this
/// method returns that template declaration.
TemplateDecl *getDescribedTemplate() const;
- /// \brief Returns the function itself, or the templated function if this is a
+ /// Returns the function itself, or the templated function if this is a
/// function template.
FunctionDecl *getAsFunction() LLVM_READONLY;
@@ -1025,7 +1031,7 @@ public:
return const_cast<Decl *>(this)->getAsFunction();
}
- /// \brief Changes the namespace of this declaration to reflect that it's
+ /// Changes the namespace of this declaration to reflect that it's
/// a function-local extern declaration.
///
/// These declarations appear in the lexical context of the extern
@@ -1046,14 +1052,14 @@ public:
IdentifierNamespace |= IDNS_Ordinary;
}
- /// \brief Determine whether this is a block-scope declaration with linkage.
+ /// Determine whether this is a block-scope declaration with linkage.
/// This will either be a local variable declaration declared 'extern', or a
/// local function declaration.
bool isLocalExternDecl() {
return IdentifierNamespace & IDNS_LocalExtern;
}
- /// \brief Changes the namespace of this declaration to reflect that it's
+ /// Changes the namespace of this declaration to reflect that it's
/// the object of a friend declaration.
///
/// These declarations appear in the lexical context of the friending
@@ -1095,7 +1101,7 @@ public:
FOK_Undeclared ///< A friend of a previously-undeclared entity.
};
- /// \brief Determines whether this declaration is the object of a
+ /// Determines whether this declaration is the object of a
/// friend declaration and, if so, what kind.
///
/// There is currently no direct way to find the associated FriendDecl.
@@ -1135,7 +1141,7 @@ public:
void dump(raw_ostream &Out, bool Deserialize = false) const;
- /// \brief Looks through the Decl's underlying type to extract a FunctionType
+ /// Looks through the Decl's underlying type to extract a FunctionType
/// when possible. Will return null if the type underlying the Decl does not
/// have a FunctionType.
const FunctionType *getFunctionType(bool BlocksToo = true) const;
@@ -1149,17 +1155,17 @@ protected:
ASTMutationListener *getASTMutationListener() const;
};
-/// \brief Determine whether two declarations declare the same entity.
+/// Determine whether two declarations declare the same entity.
inline bool declaresSameEntity(const Decl *D1, const Decl *D2) {
if (!D1 || !D2)
return false;
-
+
if (D1 == D2)
return true;
-
+
return D1->getCanonicalDecl() == D2->getCanonicalDecl();
}
-
+
/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
/// doing something to a specific decl.
class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
@@ -1176,7 +1182,7 @@ public:
void print(raw_ostream &OS) const override;
};
-/// \brief The results of name lookup within a DeclContext. This is either a
+/// The results of name lookup within a DeclContext. This is either a
/// single result (with no stable storage) or a collection of results (with
/// stable storage provided by the lookup table).
class DeclContextLookupResult {
@@ -1257,36 +1263,36 @@ class DeclContext {
/// DeclKind - This indicates which class this is.
unsigned DeclKind : 8;
- /// \brief Whether this declaration context also has some external
+ /// Whether this declaration context also has some external
/// storage that contains additional declarations that are lexically
/// part of this context.
mutable bool ExternalLexicalStorage : 1;
- /// \brief Whether this declaration context also has some external
+ /// Whether this declaration context also has some external
/// storage that contains additional declarations that are visible
/// in this context.
mutable bool ExternalVisibleStorage : 1;
- /// \brief Whether this declaration context has had external visible
+ /// Whether this declaration context has had external visible
/// storage added since the last lookup. In this case, \c LookupPtr's
/// invariant may not hold and needs to be fixed before we perform
/// another lookup.
mutable bool NeedToReconcileExternalVisibleStorage : 1;
- /// \brief If \c true, this context may have local lexical declarations
+ /// If \c true, this context may have local lexical declarations
/// that are missing from the lookup table.
mutable bool HasLazyLocalLexicalLookups : 1;
- /// \brief If \c true, the external source may have lexical declarations
+ /// If \c true, the external source may have lexical declarations
/// that are missing from the lookup table.
mutable bool HasLazyExternalLexicalLookups : 1;
- /// \brief If \c true, lookups should only return identifier from
+ /// If \c true, lookups should only return identifier from
/// DeclContext scope (for example TranslationUnit). Used in
/// LookupQualifiedName()
mutable bool UseQualifiedLookup : 1;
- /// \brief Pointer to the data structure used to lookup declarations
+ /// Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context). We maintain the invariant that, if the map
/// contains an entry for a DeclarationName (and we haven't lazily
@@ -1309,7 +1315,7 @@ protected:
/// another pointer.
mutable Decl *LastDecl = nullptr;
- /// \brief Build up a chain of declarations.
+ /// Build up a chain of declarations.
///
/// \returns the first/last pair of declarations.
static std::pair<Decl *, Decl *>
@@ -1392,7 +1398,7 @@ public:
}
}
- /// \brief Test whether the context supports looking up names.
+ /// Test whether the context supports looking up names.
bool isLookupContext() const {
return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec &&
DeclKind != Decl::Export;
@@ -1418,7 +1424,7 @@ public:
bool isInlineNamespace() const;
- /// \brief Determines whether this context is dependent on a
+ /// Determines whether this context is dependent on a
/// template parameter.
bool isDependentContext() const;
@@ -1439,28 +1445,28 @@ public:
/// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
- /// \brief Determines whether this context or some of its ancestors is a
+ /// Determines whether this context or some of its ancestors is a
/// linkage specification context that specifies C linkage.
bool isExternCContext() const;
- /// \brief Retrieve the nearest enclosing C linkage specification context.
+ /// Retrieve the nearest enclosing C linkage specification context.
const LinkageSpecDecl *getExternCContext() const;
- /// \brief Determines whether this context or some of its ancestors is a
+ /// Determines whether this context or some of its ancestors is a
/// linkage specification context that specifies C++ linkage.
bool isExternCXXContext() const;
- /// \brief Determine whether this declaration context is equivalent
+ /// Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
- /// \brief Determine whether this declaration context encloses the
+ /// Determine whether this declaration context encloses the
/// declaration context DC.
bool Encloses(const DeclContext *DC) const;
- /// \brief Find the nearest non-closure ancestor of this context,
+ /// Find the nearest non-closure ancestor of this context,
/// i.e. the innermost semantic parent of this context which is not
/// a closure. A context may be its own non-closure ancestor.
Decl *getNonClosureAncestor();
@@ -1487,19 +1493,19 @@ public:
return const_cast<DeclContext *>(this)->getRedeclContext();
}
- /// \brief Retrieve the nearest enclosing namespace context.
+ /// Retrieve the nearest enclosing namespace context.
DeclContext *getEnclosingNamespaceContext();
const DeclContext *getEnclosingNamespaceContext() const {
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
- /// \brief Retrieve the outermost lexically enclosing record context.
+ /// Retrieve the outermost lexically enclosing record context.
RecordDecl *getOuterLexicalRecordContext();
const RecordDecl *getOuterLexicalRecordContext() const {
return const_cast<DeclContext *>(this)->getOuterLexicalRecordContext();
}
- /// \brief Test if this context is part of the enclosing namespace set of
+ /// Test if this context is part of the enclosing namespace set of
/// the context NS, as defined in C++0x [namespace.def]p9. If either context
/// isn't a namespace, this is equivalent to Equals().
///
@@ -1507,11 +1513,11 @@ public:
/// inline, its enclosing namespace, recursively.
bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
- /// \brief Collects all of the declaration contexts that are semantically
+ /// Collects all of the declaration contexts that are semantically
/// connected to this declaration context.
///
/// For declaration contexts that have multiple semantically connected but
- /// syntactically distinct contexts, such as C++ namespaces, this routine
+ /// syntactically distinct contexts, such as C++ namespaces, this routine
/// retrieves the complete set of such declaration contexts in source order.
/// For example, given:
///
@@ -1663,7 +1669,7 @@ public:
}
};
- /// \brief Iterates over a filtered subrange of declarations stored
+ /// Iterates over a filtered subrange of declarations stored
/// in a DeclContext.
///
/// This iterator visits only those declarations that are of type
@@ -1739,7 +1745,7 @@ public:
}
};
- /// @brief Add the declaration D into this context.
+ /// Add the declaration D into this context.
///
/// This routine should be invoked when the declaration D has first
/// been declared, to place D into the context where it was
@@ -1753,7 +1759,7 @@ public:
/// semantic context via makeDeclVisibleInContext.
void addDecl(Decl *D);
- /// @brief Add the declaration D into this context, but suppress
+ /// Add the declaration D into this context, but suppress
/// searches for external declarations with the same name.
///
/// Although analogous in function to addDecl, this removes an
@@ -1763,7 +1769,7 @@ public:
/// See the ASTImporter for use cases.
void addDeclInternal(Decl *D);
- /// @brief Add the declaration D to this context without modifying
+ /// Add the declaration D to this context without modifying
/// any lookup tables.
///
/// This is useful for some operations in dependent contexts where
@@ -1771,12 +1777,16 @@ public:
/// only happens with friends.
void addHiddenDecl(Decl *D);
- /// @brief Removes a declaration from this context.
+ /// Removes a declaration from this context.
void removeDecl(Decl *D);
-
- /// @brief Checks whether a declaration is in this context.
+
+ /// Checks whether a declaration is in this context.
bool containsDecl(Decl *D) const;
+ /// Checks whether a declaration is in this context.
+ /// This also loads the Decls from the external source before the check.
+ bool containsDeclAndLoad(Decl *D) const;
+
using lookup_result = DeclContextLookupResult;
using lookup_iterator = lookup_result::iterator;
@@ -1787,12 +1797,12 @@ public:
/// routine will not look into parent contexts.
lookup_result lookup(DeclarationName Name) const;
- /// \brief Find the declarations with the given name that are visible
+ /// Find the declarations with the given name that are visible
/// within this context; don't attempt to retrieve anything from an
/// external source.
lookup_result noload_lookup(DeclarationName Name);
- /// \brief A simplistic name lookup mechanism that performs name lookup
+ /// A simplistic name lookup mechanism that performs name lookup
/// into this declaration context without consulting the external source.
///
/// This function should almost never be used, because it subverts the
@@ -1804,7 +1814,7 @@ public:
void localUncachedLookup(DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Results);
- /// @brief Makes a declaration visible within this context.
+ /// Makes a declaration visible within this context.
///
/// This routine makes the declaration D visible to name lookup
/// within this context and, if this is a transparent context,
@@ -1827,13 +1837,15 @@ public:
using lookups_range = llvm::iterator_range<all_lookups_iterator>;
lookups_range lookups() const;
- lookups_range noload_lookups() const;
+ // Like lookups(), but avoids loading external declarations.
+ // If PreserveInternalState, avoids building lookup data structures too.
+ lookups_range noload_lookups(bool PreserveInternalState) const;
- /// \brief Iterators over all possible lookups within this context.
+ /// Iterators over all possible lookups within this context.
all_lookups_iterator lookups_begin() const;
all_lookups_iterator lookups_end() const;
- /// \brief Iterators over all possible lookups within this context that are
+ /// Iterators over all possible lookups within this context that are
/// currently loaded; don't attempt to retrieve anything from an external
/// source.
all_lookups_iterator noload_lookups_begin() const;
@@ -1865,7 +1877,7 @@ public:
// Low-level accessors
- /// \brief Mark that there are external lexical declarations that we need
+ /// Mark that there are external lexical declarations that we need
/// to include in our lookup table (and that are not available as external
/// visible lookups). These extra lookup results will be found by walking
/// the lexical declarations of this context. This should be used only if
@@ -1877,28 +1889,28 @@ public:
HasLazyExternalLexicalLookups = true;
}
- /// \brief Retrieve the internal representation of the lookup structure.
+ /// Retrieve the internal representation of the lookup structure.
/// This may omit some names if we are lazily building the structure.
StoredDeclsMap *getLookupPtr() const { return LookupPtr; }
- /// \brief Ensure the lookup structure is fully-built and return it.
+ /// Ensure the lookup structure is fully-built and return it.
StoredDeclsMap *buildLookup();
- /// \brief Whether this DeclContext has external storage containing
+ /// Whether this DeclContext has external storage containing
/// additional declarations that are lexically in this context.
bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
- /// \brief State whether this DeclContext has external storage for
+ /// State whether this DeclContext has external storage for
/// declarations lexically in this context.
void setHasExternalLexicalStorage(bool ES = true) {
ExternalLexicalStorage = ES;
}
- /// \brief Whether this DeclContext has external storage containing
+ /// Whether this DeclContext has external storage containing
/// additional declarations that are visible in this context.
bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
- /// \brief State whether this DeclContext has external storage for
+ /// State whether this DeclContext has external storage for
/// declarations visible in this context.
void setHasExternalVisibleStorage(bool ES = true) {
ExternalVisibleStorage = ES;
@@ -1906,10 +1918,10 @@ public:
NeedToReconcileExternalVisibleStorage = true;
}
- /// \brief Determine whether the given declaration is stored in the list of
+ /// Determine whether the given declaration is stored in the list of
/// declarations lexically within this context.
bool isDeclInLexicalTraversal(const Decl *D) const {
- return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl ||
+ return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl ||
D == LastDecl);
}
@@ -1937,7 +1949,7 @@ private:
void reconcileExternalVisibleStorage() const;
bool LoadLexicalDeclsFromExternalStorage() const;
- /// @brief Makes a declaration visible within this context, but
+ /// Makes a declaration visible within this context, but
/// suppresses searches for external declarations with the same
/// name.
///
@@ -1947,6 +1959,7 @@ private:
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
+ void loadLazyLocalLexicalLookups();
void buildLookupImpl(DeclContext *DCtx, bool Internal);
void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
bool Rediscoverable);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
index 88dc9a655917..4353f66a34e4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the C++ Decl subclasses, other than those for templates
+/// Defines the C++ Decl subclasses, other than those for templates
/// (found in DeclTemplate.h) and friends (in DeclFriend.h).
//
//===----------------------------------------------------------------------===//
@@ -20,6 +20,7 @@
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
@@ -72,7 +73,7 @@ class TemplateDecl;
class TemplateParameterList;
class UsingDecl;
-/// \brief Represents any kind of function declaration, whether it is a
+/// Represents any kind of function declaration, whether it is a
/// concrete function or a function template.
class AnyFunctionDecl {
NamedDecl *Function;
@@ -83,11 +84,11 @@ public:
AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {}
AnyFunctionDecl(FunctionTemplateDecl *FTD);
- /// \brief Implicily converts any function or function template into a
+ /// Implicily converts any function or function template into a
/// named declaration.
operator NamedDecl *() const { return Function; }
- /// \brief Retrieve the underlying function or function template.
+ /// Retrieve the underlying function or function template.
NamedDecl *get() const { return Function; }
static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
@@ -118,7 +119,7 @@ namespace llvm {
namespace clang {
-/// \brief Represents an access specifier followed by colon ':'.
+/// Represents an access specifier followed by colon ':'.
///
/// An objects of this class represents sugar for the syntactic occurrence
/// of an access specifier followed by a colon in the list of member
@@ -129,7 +130,7 @@ 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 {
- /// \brief The location of the ':'.
+ /// The location of the ':'.
SourceLocation ColonLoc;
AccessSpecDecl(AccessSpecifier AS, DeclContext *DC,
@@ -143,16 +144,16 @@ class AccessSpecDecl : public Decl {
virtual void anchor();
public:
- /// \brief The location of the access specifier.
+ /// The location of the access specifier.
SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
- /// \brief Sets the location of the access specifier.
+ /// Sets the location of the access specifier.
void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); }
- /// \brief The location of the colon following the access specifier.
+ /// The location of the colon following the access specifier.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// \brief Sets the location of the colon.
+ /// Sets the location of the colon.
void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; }
SourceRange getSourceRange() const override LLVM_READONLY {
@@ -172,7 +173,7 @@ public:
static bool classofKind(Kind K) { return K == AccessSpec; }
};
-/// \brief Represents a base class of a C++ class.
+/// Represents a base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
/// struct) of a C++ class (or struct). It specifies the type of that
@@ -189,35 +190,35 @@ public:
/// In this code, C will have two CXXBaseSpecifiers, one for "public
/// virtual A" and the other for "protected B".
class CXXBaseSpecifier {
- /// \brief The source code range that covers the full base
+ /// The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
SourceRange Range;
- /// \brief The source location of the ellipsis, if this is a pack
+ /// The source location of the ellipsis, if this is a pack
/// expansion.
SourceLocation EllipsisLoc;
- /// \brief Whether this is a virtual base class or not.
+ /// Whether this is a virtual base class or not.
unsigned Virtual : 1;
- /// \brief Whether this is the base of a class (true) or of a struct (false).
+ /// Whether this is the base of a class (true) or of a struct (false).
///
/// This determines the mapping from the access specifier as written in the
/// source code to the access specifier used for semantic analysis.
unsigned BaseOfClass : 1;
- /// \brief Access specifier as written in the source code (may be AS_none).
+ /// Access specifier as written in the source code (may be AS_none).
///
/// The actual type of data stored here is an AccessSpecifier, but we use
/// "unsigned" here to work around a VC++ bug.
unsigned Access : 2;
- /// \brief Whether the class contains a using declaration
+ /// Whether the class contains a using declaration
/// to inherit the named class's constructors.
unsigned InheritConstructors : 1;
- /// \brief The type of the base class.
+ /// The type of the base class.
///
/// This will be a class or struct (or a typedef of such). The source code
/// range does not include the \c virtual or the access specifier.
@@ -230,40 +231,40 @@ public:
: Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC),
Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) {}
- /// \brief Retrieves the source range that contains the entire base specifier.
+ /// Retrieves the source range that contains the entire base specifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
- /// \brief Get the location at which the base class type was written.
+ /// Get the location at which the base class type was written.
SourceLocation getBaseTypeLoc() const LLVM_READONLY {
return BaseTypeInfo->getTypeLoc().getLocStart();
}
- /// \brief Determines whether the base class is a virtual base class (or not).
+ /// Determines whether the base class is a virtual base class (or not).
bool isVirtual() const { return Virtual; }
- /// \brief Determine whether this base class is a base of a class declared
+ /// Determine whether this base class is a base of a class declared
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; }
- /// \brief Determine whether this base specifier is a pack expansion.
+ /// Determine whether this base specifier is a pack expansion.
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
- /// \brief Determine whether this base class's constructors get inherited.
+ /// Determine whether this base class's constructors get inherited.
bool getInheritConstructors() const { return InheritConstructors; }
- /// \brief Set that this base class's constructors should be inherited.
+ /// Set that this base class's constructors should be inherited.
void setInheritConstructors(bool Inherit = true) {
InheritConstructors = Inherit;
}
- /// \brief For a pack expansion, determine the location of the ellipsis.
+ /// For a pack expansion, determine the location of the ellipsis.
SourceLocation getEllipsisLoc() const {
return EllipsisLoc;
}
- /// \brief Returns the access specifier for this base specifier.
+ /// Returns the access specifier for this base specifier.
///
/// This is the actual base specifier as used for semantic analysis, so
/// the result can never be AS_none. To retrieve the access specifier as
@@ -275,7 +276,7 @@ public:
return (AccessSpecifier)Access;
}
- /// \brief Retrieves the access specifier as written in the source code
+ /// Retrieves the access specifier as written in the source code
/// (which may mean that no access specifier was explicitly written).
///
/// Use getAccessSpecifier() to retrieve the access specifier for use in
@@ -284,18 +285,18 @@ public:
return (AccessSpecifier)Access;
}
- /// \brief Retrieves the type of the base class.
+ /// Retrieves the type of the base class.
///
/// This type will always be an unqualified class type.
QualType getType() const {
return BaseTypeInfo->getType().getUnqualifiedType();
}
- /// \brief Retrieves the type and source location of the base class.
+ /// Retrieves the type and source location of the base class.
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
};
-/// \brief Represents a C++ struct/union/class.
+/// Represents a C++ struct/union/class.
class CXXRecordDecl : public RecordDecl {
friend class ASTDeclReader;
friend class ASTDeclWriter;
@@ -321,16 +322,16 @@ class CXXRecordDecl : public RecordDecl {
};
struct DefinitionData {
- /// \brief True if this class has any user-declared constructors.
+ /// True if this class has any user-declared constructors.
unsigned UserDeclaredConstructor : 1;
- /// \brief The user-declared special members which this class has.
+ /// The user-declared special members which this class has.
unsigned UserDeclaredSpecialMembers : 6;
- /// \brief True when this class is an aggregate.
+ /// True when this class is an aggregate.
unsigned Aggregate : 1;
- /// \brief True when this class is a POD-type.
+ /// True when this class is a POD-type.
unsigned PlainOldData : 1;
/// true when this class is empty for traits purposes,
@@ -339,15 +340,20 @@ class CXXRecordDecl : public RecordDecl {
/// class. Doesn't take union-ness into account.
unsigned Empty : 1;
- /// \brief True when this class is polymorphic, i.e., has at
+ /// True when this class is polymorphic, i.e., has at
/// least one virtual member or derives from a polymorphic class.
unsigned Polymorphic : 1;
- /// \brief True when this class is abstract, i.e., has at least
+ /// True when this class is abstract, i.e., has at least
/// one pure virtual function, (that can come from a base class).
unsigned Abstract : 1;
- /// \brief True when this class has standard layout.
+ /// True when this class is standard-layout, per the applicable
+ /// language rules (including DRs).
+ unsigned IsStandardLayout : 1;
+
+ /// True when this class was standard-layout under the C++11
+ /// definition.
///
/// C++11 [class]p7. A standard-layout class is a class that:
/// * has no non-static data members of type non-standard-layout class (or
@@ -361,57 +367,63 @@ class CXXRecordDecl : public RecordDecl {
/// classes with non-static data members, and
/// * has no base classes of the same type as the first non-static data
/// member.
- unsigned IsStandardLayout : 1;
+ unsigned IsCXX11StandardLayout : 1;
- /// \brief True when there are no non-empty base classes.
- ///
+ /// True when any base class has any declared non-static data
+ /// members or bit-fields.
/// This is a helper bit of state used to implement IsStandardLayout more
/// efficiently.
- unsigned HasNoNonEmptyBases : 1;
+ unsigned HasBasesWithFields : 1;
- /// \brief True when there are private non-static data members.
+ /// True when any base class has any declared non-static data
+ /// members.
+ /// This is a helper bit of state used to implement IsCXX11StandardLayout
+ /// more efficiently.
+ unsigned HasBasesWithNonStaticDataMembers : 1;
+
+ /// True when there are private non-static data members.
unsigned HasPrivateFields : 1;
- /// \brief True when there are protected non-static data members.
+ /// True when there are protected non-static data members.
unsigned HasProtectedFields : 1;
- /// \brief True when there are private non-static data members.
+ /// True when there are private non-static data members.
unsigned HasPublicFields : 1;
- /// \brief True if this class (or any subobject) has mutable fields.
+ /// True if this class (or any subobject) has mutable fields.
unsigned HasMutableFields : 1;
- /// \brief True if this class (or any nested anonymous struct or union)
+ /// True if this class (or any nested anonymous struct or union)
/// has variant members.
unsigned HasVariantMembers : 1;
- /// \brief True if there no non-field members declared by the user.
+ /// True if there no non-field members declared by the user.
unsigned HasOnlyCMembers : 1;
- /// \brief True if any field has an in-class initializer, including those
+ /// True if any field has an in-class initializer, including those
/// within anonymous unions or structs.
unsigned HasInClassInitializer : 1;
- /// \brief True if any field is of reference type, and does not have an
+ /// True if any field is of reference type, and does not have an
/// in-class initializer.
///
/// In this case, value-initialization of this class is illegal in C++98
/// even if the class has a trivial default constructor.
unsigned HasUninitializedReferenceMember : 1;
- /// \brief True if any non-mutable field whose type doesn't have a user-
+ /// True if any non-mutable field whose type doesn't have a user-
/// provided default ctor also doesn't have an in-class initializer.
unsigned HasUninitializedFields : 1;
- /// \brief True if there are any member using-declarations that inherit
+ /// True if there are any member using-declarations that inherit
/// constructors from a base class.
unsigned HasInheritedConstructor : 1;
- /// \brief True if there are any member using-declarations named
+ /// True if there are any member using-declarations named
/// 'operator='.
unsigned HasInheritedAssignment : 1;
- /// \brief These flags are \c true if a defaulted corresponding special
+ /// These flags are \c true if a defaulted corresponding special
/// member can't be fully analyzed without performing overload resolution.
/// @{
unsigned NeedOverloadResolutionForCopyConstructor : 1;
@@ -420,7 +432,7 @@ class CXXRecordDecl : public RecordDecl {
unsigned NeedOverloadResolutionForDestructor : 1;
/// @}
- /// \brief These flags are \c true if an implicit defaulted corresponding
+ /// These flags are \c true if an implicit defaulted corresponding
/// special member would be defined as deleted.
/// @{
unsigned DefaultedCopyConstructorIsDeleted : 1;
@@ -429,7 +441,7 @@ class CXXRecordDecl : public RecordDecl {
unsigned DefaultedDestructorIsDeleted : 1;
/// @}
- /// \brief The trivial special members which this class has, per
+ /// The trivial special members which this class has, per
/// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
/// C++11 [class.dtor]p5, or would have if the member were not suppressed.
///
@@ -437,7 +449,12 @@ class CXXRecordDecl : public RecordDecl {
/// which have been declared but not yet defined.
unsigned HasTrivialSpecialMembers : 6;
- /// \brief The declared special members of this class which are known to be
+ /// These bits keep track of the triviality of special functions for the
+ /// purpose of calls. Only the bits corresponding to SMF_CopyConstructor,
+ /// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
+ unsigned HasTrivialSpecialMembersForCall : 6;
+
+ /// The declared special members of this class which are known to be
/// non-trivial.
///
/// This excludes any user-declared but not user-provided special members
@@ -445,123 +462,123 @@ class CXXRecordDecl : public RecordDecl {
/// members which have not yet been declared.
unsigned DeclaredNonTrivialSpecialMembers : 6;
- /// \brief True when this class has a destructor with no semantic effect.
+ /// These bits keep track of the declared special members that are
+ /// non-trivial for the purpose of calls.
+ /// Only the bits corresponding to SMF_CopyConstructor,
+ /// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
+ unsigned DeclaredNonTrivialSpecialMembersForCall : 6;
+
+ /// True when this class has a destructor with no semantic effect.
unsigned HasIrrelevantDestructor : 1;
- /// \brief True when this class has at least one user-declared constexpr
+ /// True when this class has at least one user-declared constexpr
/// constructor which is neither the copy nor move constructor.
unsigned HasConstexprNonCopyMoveConstructor : 1;
- /// \brief True if this class has a (possibly implicit) defaulted default
+ /// True if this class has a (possibly implicit) defaulted default
/// constructor.
unsigned HasDefaultedDefaultConstructor : 1;
- /// \brief True if this class can be passed in a non-address-preserving
- /// fashion (such as in registers) according to the C++ language rules.
- /// This does not imply anything about how the ABI in use will actually
- /// pass an object of this class.
- unsigned CanPassInRegisters : 1;
-
- /// \brief True if a defaulted default constructor for this class would
+ /// True if a defaulted default constructor for this class would
/// be constexpr.
unsigned DefaultedDefaultConstructorIsConstexpr : 1;
- /// \brief True if this class has a constexpr default constructor.
+ /// True if this class has a constexpr default constructor.
///
/// This is true for either a user-declared constexpr default constructor
/// or an implicitly declared constexpr default constructor.
unsigned HasConstexprDefaultConstructor : 1;
- /// \brief True when this class contains at least one non-static data
+ /// True when this class contains at least one non-static data
/// member or base class of non-literal or volatile type.
unsigned HasNonLiteralTypeFieldsOrBases : 1;
- /// \brief True when visible conversion functions are already computed
+ /// True when visible conversion functions are already computed
/// and are available.
unsigned ComputedVisibleConversions : 1;
- /// \brief Whether we have a C++11 user-provided default constructor (not
+ /// Whether we have a C++11 user-provided default constructor (not
/// explicitly deleted or defaulted).
unsigned UserProvidedDefaultConstructor : 1;
- /// \brief The special members which have been declared for this class,
+ /// The special members which have been declared for this class,
/// either by the user or implicitly.
unsigned DeclaredSpecialMembers : 6;
- /// \brief Whether an implicit copy constructor could have a const-qualified
+ /// Whether an implicit copy constructor could have a const-qualified
/// parameter, for initializing virtual bases and for other subobjects.
unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1;
unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1;
- /// \brief Whether an implicit copy assignment operator would have a
+ /// Whether an implicit copy assignment operator would have a
/// const-qualified parameter.
unsigned ImplicitCopyAssignmentHasConstParam : 1;
- /// \brief Whether any declared copy constructor has a const-qualified
+ /// Whether any declared copy constructor has a const-qualified
/// parameter.
unsigned HasDeclaredCopyConstructorWithConstParam : 1;
- /// \brief Whether any declared copy assignment operator has either a
+ /// Whether any declared copy assignment operator has either a
/// const-qualified reference parameter or a non-reference parameter.
unsigned HasDeclaredCopyAssignmentWithConstParam : 1;
- /// \brief Whether this class describes a C++ lambda.
+ /// Whether this class describes a C++ lambda.
unsigned IsLambda : 1;
- /// \brief Whether we are currently parsing base specifiers.
+ /// Whether we are currently parsing base specifiers.
unsigned IsParsingBaseSpecifiers : 1;
unsigned HasODRHash : 1;
- /// \brief A hash of parts of the class to help in ODR checking.
+ /// A hash of parts of the class to help in ODR checking.
unsigned ODRHash = 0;
- /// \brief The number of base class specifiers in Bases.
+ /// The number of base class specifiers in Bases.
unsigned NumBases = 0;
- /// \brief The number of virtual base class specifiers in VBases.
+ /// The number of virtual base class specifiers in VBases.
unsigned NumVBases = 0;
- /// \brief Base classes of this class.
+ /// Base classes of this class.
///
/// FIXME: This is wasted space for a union.
LazyCXXBaseSpecifiersPtr Bases;
- /// \brief direct and indirect virtual base classes of this class.
+ /// direct and indirect virtual base classes of this class.
LazyCXXBaseSpecifiersPtr VBases;
- /// \brief The conversion functions of this C++ class (but not its
+ /// The conversion functions of this C++ class (but not its
/// inherited conversion functions).
///
/// Each of the entries in this overload set is a CXXConversionDecl.
LazyASTUnresolvedSet Conversions;
- /// \brief The conversion functions of this C++ class and all those
+ /// The conversion functions of this C++ class and all those
/// inherited conversion functions that are visible in this class.
///
/// Each of the entries in this overload set is a CXXConversionDecl or a
/// FunctionTemplateDecl.
LazyASTUnresolvedSet VisibleConversions;
- /// \brief The declaration which defines this record.
+ /// The declaration which defines this record.
CXXRecordDecl *Definition;
- /// \brief The first friend declaration in this class, or null if there
- /// aren't any.
+ /// The first friend declaration in this class, or null if there
+ /// aren't any.
///
/// This is actually currently stored in reverse order.
LazyDeclPtr FirstFriend;
DefinitionData(CXXRecordDecl *D);
- /// \brief Retrieve the set of direct base classes.
+ /// Retrieve the set of direct base classes.
CXXBaseSpecifier *getBases() const {
if (!Bases.isOffset())
return Bases.get(nullptr);
return getBasesSlowCase();
}
- /// \brief Retrieve the set of virtual base classes.
+ /// Retrieve the set of virtual base classes.
CXXBaseSpecifier *getVBases() const {
if (!VBases.isOffset())
return VBases.get(nullptr);
@@ -583,54 +600,54 @@ class CXXRecordDecl : public RecordDecl {
struct DefinitionData *DefinitionData;
- /// \brief Describes a C++ closure type (generated by a lambda expression).
+ /// Describes a C++ closure type (generated by a lambda expression).
struct LambdaDefinitionData : public DefinitionData {
using Capture = LambdaCapture;
- /// \brief Whether this lambda is known to be dependent, even if its
+ /// Whether this lambda is known to be dependent, even if its
/// context isn't dependent.
- ///
+ ///
/// A lambda with a non-dependent context can be dependent if it occurs
/// within the default argument of a function template, because the
/// lambda will have been created with the enclosing context as its
/// declaration context, rather than function. This is an unfortunate
- /// artifact of having to parse the default arguments before.
+ /// artifact of having to parse the default arguments before.
unsigned Dependent : 1;
-
- /// \brief Whether this lambda is a generic lambda.
+
+ /// Whether this lambda is a generic lambda.
unsigned IsGenericLambda : 1;
- /// \brief The Default Capture.
+ /// The Default Capture.
unsigned CaptureDefault : 2;
- /// \brief The number of captures in this lambda is limited 2^NumCaptures.
+ /// The number of captures in this lambda is limited 2^NumCaptures.
unsigned NumCaptures : 15;
- /// \brief The number of explicit captures in this lambda.
+ /// The number of explicit captures in this lambda.
unsigned NumExplicitCaptures : 13;
- /// \brief The number used to indicate this lambda expression for name
+ /// The number used to indicate this lambda expression for name
/// mangling in the Itanium C++ ABI.
unsigned ManglingNumber = 0;
-
- /// \brief The declaration that provides context for this lambda, if the
+
+ /// The declaration that provides context for this lambda, if the
/// actual DeclContext does not suffice. This is used for lambdas that
/// occur within default arguments of function parameters within the class
/// or within a data member initializer.
LazyDeclPtr ContextDecl;
-
- /// \brief The list of captures, both explicit and implicit, for this
+
+ /// The list of captures, both explicit and implicit, for this
/// lambda.
Capture *Captures = nullptr;
- /// \brief The type of the call method.
+ /// 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),
+ 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;
@@ -661,7 +678,7 @@ class CXXRecordDecl : public RecordDecl {
return static_cast<LambdaDefinitionData&>(*DD);
}
- /// \brief The template or declaration that this declaration
+ /// The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
/// For non-templates, this value will be null. For record
@@ -673,11 +690,11 @@ class CXXRecordDecl : public RecordDecl {
llvm::PointerUnion<ClassTemplateDecl *, MemberSpecializationInfo *>
TemplateOrInstantiation;
- /// \brief Called from setBases and addedMember to notify the class that a
+ /// Called from setBases and addedMember to notify the class that a
/// direct or virtual base class or a member of class type has been added.
void addedClassSubobject(CXXRecordDecl *Base);
- /// \brief Notify the class that member has been added.
+ /// Notify the class that member has been added.
///
/// This routine helps maintain information about the class based on which
/// members have been added. It will be invoked by DeclContext::addDecl()
@@ -686,20 +703,26 @@ class CXXRecordDecl : public RecordDecl {
void markedVirtualFunctionPure();
- /// \brief Get the head of our list of friend declarations, possibly
+ /// Get the head of our list of friend declarations, possibly
/// deserializing the friends from an external AST source.
FriendDecl *getFirstFriend() const;
+ /// Determine whether this class has an empty base class subobject of type X
+ /// or of one of the types that might be at offset 0 within X (per the C++
+ /// "standard layout" rules).
+ bool hasSubobjectAtOffsetZeroOfEmptyBaseType(ASTContext &Ctx,
+ const CXXRecordDecl *X);
+
protected:
CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, CXXRecordDecl *PrevDecl);
public:
- /// \brief Iterator that traverses the base classes of a class.
+ /// Iterator that traverses the base classes of a class.
using base_class_iterator = CXXBaseSpecifier *;
- /// \brief Iterator that traverses the base classes of a class.
+ /// Iterator that traverses the base classes of a class.
using base_class_const_iterator = const CXXBaseSpecifier *;
CXXRecordDecl *getCanonicalDecl() override {
@@ -728,6 +751,21 @@ public:
return const_cast<CXXRecordDecl*>(this)->getMostRecentDecl();
}
+ CXXRecordDecl *getMostRecentNonInjectedDecl() {
+ CXXRecordDecl *Recent =
+ static_cast<CXXRecordDecl *>(this)->getMostRecentDecl();
+ while (Recent->isInjectedClassName()) {
+ // FIXME: Does injected class name need to be in the redeclarations chain?
+ assert(Recent->getPreviousDecl());
+ Recent = Recent->getPreviousDecl();
+ }
+ return Recent;
+ }
+
+ const CXXRecordDecl *getMostRecentNonInjectedDecl() const {
+ return const_cast<CXXRecordDecl*>(this)->getMostRecentNonInjectedDecl();
+ }
+
CXXRecordDecl *getDefinition() const {
// We only need an update if we don't already know which
// declaration is the definition.
@@ -752,6 +790,18 @@ public:
return data().Polymorphic || data().NumVBases != 0;
}
+ /// @returns true if class is dynamic or might be dynamic because the
+ /// definition is incomplete of dependent.
+ bool mayBeDynamicClass() const {
+ return !hasDefinition() || isDynamicClass() || hasAnyDependentBases();
+ }
+
+ /// @returns true if class is non dynamic or might be non dynamic because the
+ /// definition is incomplete of dependent.
+ bool mayBeNonDynamicClass() const {
+ return !hasDefinition() || !isDynamicClass() || hasAnyDependentBases();
+ }
+
void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; }
bool isParsingBaseSpecifiers() const {
@@ -760,10 +810,10 @@ public:
unsigned getODRHash() const;
- /// \brief Sets the base classes of this struct or class.
+ /// Sets the base classes of this struct or class.
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
- /// \brief Retrieves the number of base classes of this class.
+ /// Retrieves the number of base classes of this class.
unsigned getNumBases() const { return data().NumBases; }
using base_class_range = llvm::iterator_range<base_class_iterator>;
@@ -784,7 +834,7 @@ public:
return bases_begin() + data().NumBases;
}
- /// \brief Retrieves the number of virtual base classes of this class.
+ /// Retrieves the number of virtual base classes of this class.
unsigned getNumVBases() const { return data().NumVBases; }
base_class_range vbases() {
@@ -801,7 +851,7 @@ public:
return vbases_begin() + data().NumVBases;
}
- /// \brief Determine whether this class has any dependent base classes which
+ /// Determine whether this class has any dependent base classes which
/// are not the current instantiation.
bool hasAnyDependentBases() const;
@@ -816,13 +866,13 @@ public:
return method_range(method_begin(), method_end());
}
- /// \brief Method begin iterator. Iterates in the order the methods
+ /// Method begin iterator. Iterates in the order the methods
/// were declared.
method_iterator method_begin() const {
return method_iterator(decls_begin());
}
- /// \brief Method past-the-end iterator.
+ /// Method past-the-end iterator.
method_iterator method_end() const {
return method_iterator(decls_end());
}
@@ -857,7 +907,7 @@ public:
return data().FirstFriend.isValid();
}
- /// \brief \c true if a defaulted copy constructor for this class would be
+ /// \c true if a defaulted copy constructor for this class would be
/// deleted.
bool defaultedCopyConstructorIsDeleted() const {
assert((!needsOverloadResolutionForCopyConstructor() ||
@@ -866,7 +916,7 @@ public:
return data().DefaultedCopyConstructorIsDeleted;
}
- /// \brief \c true if a defaulted move constructor for this class would be
+ /// \c true if a defaulted move constructor for this class would be
/// deleted.
bool defaultedMoveConstructorIsDeleted() const {
assert((!needsOverloadResolutionForMoveConstructor() ||
@@ -875,7 +925,7 @@ public:
return data().DefaultedMoveConstructorIsDeleted;
}
- /// \brief \c true if a defaulted destructor for this class would be deleted.
+ /// \c true if a defaulted destructor for this class would be deleted.
bool defaultedDestructorIsDeleted() const {
assert((!needsOverloadResolutionForDestructor() ||
(data().DeclaredSpecialMembers & SMF_Destructor)) &&
@@ -883,41 +933,41 @@ public:
return data().DefaultedDestructorIsDeleted;
}
- /// \brief \c true if we know for sure that this class has a single,
+ /// \c true if we know for sure that this class has a single,
/// accessible, unambiguous copy constructor that is not deleted.
bool hasSimpleCopyConstructor() const {
return !hasUserDeclaredCopyConstructor() &&
!data().DefaultedCopyConstructorIsDeleted;
}
- /// \brief \c true if we know for sure that this class has a single,
+ /// \c true if we know for sure that this class has a single,
/// accessible, unambiguous move constructor that is not deleted.
bool hasSimpleMoveConstructor() const {
return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&
!data().DefaultedMoveConstructorIsDeleted;
}
- /// \brief \c true if we know for sure that this class has a single,
+ /// \c true if we know for sure that this class has a single,
/// accessible, unambiguous move assignment operator that is not deleted.
bool hasSimpleMoveAssignment() const {
return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&
!data().DefaultedMoveAssignmentIsDeleted;
}
- /// \brief \c true if we know for sure that this class has an accessible
+ /// \c true if we know for sure that this class has an accessible
/// destructor that is not deleted.
bool hasSimpleDestructor() const {
return !hasUserDeclaredDestructor() &&
!data().DefaultedDestructorIsDeleted;
}
- /// \brief Determine whether this class has any default constructors.
+ /// Determine whether this class has any default constructors.
bool hasDefaultConstructor() const {
return (data().DeclaredSpecialMembers & SMF_DefaultConstructor) ||
needsImplicitDefaultConstructor();
}
- /// \brief Determine if we need to declare a default constructor for
+ /// Determine if we need to declare a default constructor for
/// this class.
///
/// This value is used for lazy creation of default constructors.
@@ -930,33 +980,33 @@ public:
!isLambda();
}
- /// \brief Determine whether this class has any user-declared constructors.
+ /// Determine whether this class has any user-declared constructors.
///
/// When true, a default constructor will not be implicitly declared.
bool hasUserDeclaredConstructor() const {
return data().UserDeclaredConstructor;
}
- /// \brief Whether this class has a user-provided default constructor
+ /// Whether this class has a user-provided default constructor
/// per C++11.
bool hasUserProvidedDefaultConstructor() const {
return data().UserProvidedDefaultConstructor;
}
- /// \brief Determine whether this class has a user-declared copy constructor.
+ /// Determine whether this class has a user-declared copy constructor.
///
/// When false, a copy constructor will be implicitly declared.
bool hasUserDeclaredCopyConstructor() const {
return data().UserDeclaredSpecialMembers & SMF_CopyConstructor;
}
- /// \brief Determine whether this class needs an implicit copy
+ /// Determine whether this class needs an implicit copy
/// constructor to be lazily declared.
bool needsImplicitCopyConstructor() const {
return !(data().DeclaredSpecialMembers & SMF_CopyConstructor);
}
- /// \brief Determine whether we need to eagerly declare a defaulted copy
+ /// Determine whether we need to eagerly declare a defaulted copy
/// constructor for this class.
bool needsOverloadResolutionForCopyConstructor() const {
// C++17 [class.copy.ctor]p6:
@@ -971,7 +1021,7 @@ public:
return data().NeedOverloadResolutionForCopyConstructor;
}
- /// \brief Determine whether an implicit copy constructor for this type
+ /// Determine whether an implicit copy constructor for this type
/// would have a parameter with a const-qualified reference type.
bool implicitCopyConstructorHasConstParam() const {
return data().ImplicitCopyConstructorCanHaveConstParamForNonVBase &&
@@ -979,7 +1029,7 @@ public:
data().ImplicitCopyConstructorCanHaveConstParamForVBase);
}
- /// \brief Determine whether this class has a copy constructor with
+ /// Determine whether this class has a copy constructor with
/// a parameter type which is a reference to a const-qualified type.
bool hasCopyConstructorWithConstParam() const {
return data().HasDeclaredCopyConstructorWithConstParam ||
@@ -987,7 +1037,7 @@ public:
implicitCopyConstructorHasConstParam());
}
- /// \brief Whether this class has a user-declared move constructor or
+ /// Whether this class has a user-declared move constructor or
/// assignment operator.
///
/// When false, a move constructor and assignment operator may be
@@ -997,19 +1047,19 @@ public:
(SMF_MoveConstructor | SMF_MoveAssignment);
}
- /// \brief Determine whether this class has had a move constructor
+ /// Determine whether this class has had a move constructor
/// declared by the user.
bool hasUserDeclaredMoveConstructor() const {
return data().UserDeclaredSpecialMembers & SMF_MoveConstructor;
}
- /// \brief Determine whether this class has a move constructor.
+ /// Determine whether this class has a move constructor.
bool hasMoveConstructor() const {
return (data().DeclaredSpecialMembers & SMF_MoveConstructor) ||
needsImplicitMoveConstructor();
}
- /// \brief Set that we attempted to declare an implicit copy
+ /// Set that we attempted to declare an implicit copy
/// constructor, but overload resolution failed so we deleted it.
void setImplicitCopyConstructorIsDeleted() {
assert((data().DefaultedCopyConstructorIsDeleted ||
@@ -1018,7 +1068,7 @@ public:
data().DefaultedCopyConstructorIsDeleted = true;
}
- /// \brief Set that we attempted to declare an implicit move
+ /// Set that we attempted to declare an implicit move
/// constructor, but overload resolution failed so we deleted it.
void setImplicitMoveConstructorIsDeleted() {
assert((data().DefaultedMoveConstructorIsDeleted ||
@@ -1027,7 +1077,7 @@ public:
data().DefaultedMoveConstructorIsDeleted = true;
}
- /// \brief Set that we attempted to declare an implicit destructor,
+ /// Set that we attempted to declare an implicit destructor,
/// but overload resolution failed so we deleted it.
void setImplicitDestructorIsDeleted() {
assert((data().DefaultedDestructorIsDeleted ||
@@ -1036,7 +1086,7 @@ public:
data().DefaultedDestructorIsDeleted = true;
}
- /// \brief Determine whether this class should get an implicit move
+ /// Determine whether this class should get an implicit move
/// constructor or if any existing special member function inhibits this.
bool needsImplicitMoveConstructor() const {
return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&
@@ -1046,39 +1096,39 @@ public:
!hasUserDeclaredDestructor();
}
- /// \brief Determine whether we need to eagerly declare a defaulted move
+ /// Determine whether we need to eagerly declare a defaulted move
/// constructor for this class.
bool needsOverloadResolutionForMoveConstructor() const {
return data().NeedOverloadResolutionForMoveConstructor;
}
- /// \brief Determine whether this class has a user-declared copy assignment
+ /// Determine whether this class has a user-declared copy assignment
/// operator.
///
- /// When false, a copy assigment operator will be implicitly declared.
+ /// When false, a copy assignment operator will be implicitly declared.
bool hasUserDeclaredCopyAssignment() const {
return data().UserDeclaredSpecialMembers & SMF_CopyAssignment;
}
- /// \brief Determine whether this class needs an implicit copy
+ /// Determine whether this class needs an implicit copy
/// assignment operator to be lazily declared.
bool needsImplicitCopyAssignment() const {
return !(data().DeclaredSpecialMembers & SMF_CopyAssignment);
}
- /// \brief Determine whether we need to eagerly declare a defaulted copy
+ /// Determine whether we need to eagerly declare a defaulted copy
/// assignment operator for this class.
bool needsOverloadResolutionForCopyAssignment() const {
return data().HasMutableFields;
}
- /// \brief Determine whether an implicit copy assignment operator for this
+ /// Determine whether an implicit copy assignment operator for this
/// type would have a parameter with a const-qualified reference type.
bool implicitCopyAssignmentHasConstParam() const {
return data().ImplicitCopyAssignmentHasConstParam;
}
- /// \brief Determine whether this class has a copy assignment operator with
+ /// Determine whether this class has a copy assignment operator with
/// a parameter type which is a reference to a const-qualified type or is not
/// a reference.
bool hasCopyAssignmentWithConstParam() const {
@@ -1087,19 +1137,19 @@ public:
implicitCopyAssignmentHasConstParam());
}
- /// \brief Determine whether this class has had a move assignment
+ /// Determine whether this class has had a move assignment
/// declared by the user.
bool hasUserDeclaredMoveAssignment() const {
return data().UserDeclaredSpecialMembers & SMF_MoveAssignment;
}
- /// \brief Determine whether this class has a move assignment operator.
+ /// Determine whether this class has a move assignment operator.
bool hasMoveAssignment() const {
return (data().DeclaredSpecialMembers & SMF_MoveAssignment) ||
needsImplicitMoveAssignment();
}
- /// \brief Set that we attempted to declare an implicit move assignment
+ /// Set that we attempted to declare an implicit move assignment
/// operator, but overload resolution failed so we deleted it.
void setImplicitMoveAssignmentIsDeleted() {
assert((data().DefaultedMoveAssignmentIsDeleted ||
@@ -1108,7 +1158,7 @@ public:
data().DefaultedMoveAssignmentIsDeleted = true;
}
- /// \brief Determine whether this class should get an implicit move
+ /// Determine whether this class should get an implicit move
/// assignment operator or if any existing special member function inhibits
/// this.
bool needsImplicitMoveAssignment() const {
@@ -1123,54 +1173,54 @@ public:
!isLambda();
}
- /// \brief Determine whether we need to eagerly declare a move assignment
+ /// Determine whether we need to eagerly declare a move assignment
/// operator for this class.
bool needsOverloadResolutionForMoveAssignment() const {
return data().NeedOverloadResolutionForMoveAssignment;
}
- /// \brief Determine whether this class has a user-declared destructor.
+ /// Determine whether this class has a user-declared destructor.
///
/// When false, a destructor will be implicitly declared.
bool hasUserDeclaredDestructor() const {
return data().UserDeclaredSpecialMembers & SMF_Destructor;
}
- /// \brief Determine whether this class needs an implicit destructor to
+ /// Determine whether this class needs an implicit destructor to
/// be lazily declared.
bool needsImplicitDestructor() const {
return !(data().DeclaredSpecialMembers & SMF_Destructor);
}
- /// \brief Determine whether we need to eagerly declare a destructor for this
+ /// Determine whether we need to eagerly declare a destructor for this
/// class.
bool needsOverloadResolutionForDestructor() const {
return data().NeedOverloadResolutionForDestructor;
}
- /// \brief Determine whether this class describes a lambda function object.
+ /// Determine whether this class describes a lambda function object.
bool isLambda() const {
// An update record can't turn a non-lambda into a lambda.
auto *DD = DefinitionData;
return DD && DD->IsLambda;
}
- /// \brief Determine whether this class describes a generic
+ /// Determine whether this class describes a generic
/// lambda function object (i.e. function call operator is
- /// a template).
- bool isGenericLambda() const;
+ /// a template).
+ bool isGenericLambda() const;
- /// \brief Retrieve the lambda call operator of the closure type
+ /// Retrieve the lambda call operator of the closure type
/// if this is a closure type.
- CXXMethodDecl *getLambdaCallOperator() const;
+ CXXMethodDecl *getLambdaCallOperator() const;
- /// \brief Retrieve the lambda static invoker, the address of which
+ /// Retrieve the lambda static invoker, the address of which
/// is returned by the conversion operator, and the body of which
- /// is forwarded to the lambda call operator.
- CXXMethodDecl *getLambdaStaticInvoker() const;
+ /// is forwarded to the lambda call operator.
+ CXXMethodDecl *getLambdaStaticInvoker() const;
- /// \brief Retrieve the generic lambda's template parameter list.
- /// Returns null if the class does not represent a lambda or a generic
+ /// Retrieve the generic lambda's template parameter list.
+ /// Returns null if the class does not represent a lambda or a generic
/// lambda.
TemplateParameterList *getGenericLambdaTemplateParameterList() const;
@@ -1179,7 +1229,7 @@ public:
return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault);
}
- /// \brief For a closure type, retrieve the mapping from captured
+ /// For a closure type, retrieve the mapping from captured
/// variables and \c this to the non-static data members that store the
/// values or references of the captures.
///
@@ -1225,7 +1275,7 @@ public:
/// this class must currently be in the process of being defined.
void removeConversion(const NamedDecl *Old);
- /// \brief Get all conversion functions visible in current class,
+ /// Get all conversion functions visible in current class,
/// including conversion function templates.
llvm::iterator_range<conversion_iterator> getVisibleConversionFunctions();
@@ -1235,12 +1285,12 @@ public:
/// functions (C++ [dcl.init.aggr]p1).
bool isAggregate() const { return data().Aggregate; }
- /// \brief Whether this class has any in-class initializers
+ /// Whether this class has any in-class initializers
/// for non-static data members (including those in anonymous unions or
/// structs).
bool hasInClassInitializer() const { return data().HasInClassInitializer; }
- /// \brief Whether this class or any of its subobjects has any members of
+ /// Whether this class or any of its subobjects has any members of
/// reference type which would make value-initialization ill-formed.
///
/// Per C++03 [dcl.init]p5:
@@ -1253,7 +1303,7 @@ public:
data().HasUninitializedReferenceMember;
}
- /// \brief Whether this class is a POD-type (C++ [class]p4)
+ /// Whether this class is a POD-type (C++ [class]p4)
///
/// For purposes of this function a class is POD if it is an aggregate
/// that has no non-static non-POD data members, no reference data
@@ -1263,11 +1313,11 @@ public:
/// Note that this is the C++ TR1 definition of POD.
bool isPOD() const { return data().PlainOldData; }
- /// \brief True if this class is C-like, without C++-specific features, e.g.
+ /// True if this class is C-like, without C++-specific features, e.g.
/// it contains only public fields, no bases, tag kind is not 'class', etc.
bool isCLike() const;
- /// \brief Determine whether this is an empty class in the sense of
+ /// Determine whether this is an empty class in the sense of
/// (C++11 [meta.unary.prop]).
///
/// The CXXRecordDecl is a class type, but not a union type,
@@ -1278,7 +1328,7 @@ public:
/// \note This does NOT include a check for union-ness.
bool isEmpty() const { return data().Empty; }
- /// \brief Determine whether this class has direct non-static data members.
+ /// Determine whether this class has direct non-static data members.
bool hasDirectFields() const {
auto &D = data();
return D.HasPublicFields || D.HasProtectedFields || D.HasPrivateFields;
@@ -1288,32 +1338,36 @@ public:
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return data().Polymorphic; }
- /// \brief Determine whether this class has a pure virtual function.
+ /// Determine whether this class has a pure virtual function.
///
/// The class is is abstract per (C++ [class.abstract]p2) if it declares
/// a pure virtual function or inherits a pure virtual function that is
/// not overridden.
bool isAbstract() const { return data().Abstract; }
- /// \brief Determine whether this class has standard layout per
- /// (C++ [class]p7)
+ /// Determine whether this class is standard-layout per
+ /// C++ [class]p7.
bool isStandardLayout() const { return data().IsStandardLayout; }
- /// \brief Determine whether this class, or any of its class subobjects,
+ /// Determine whether this class was standard-layout per
+ /// C++11 [class]p7, specifically using the C++11 rules without any DRs.
+ bool isCXX11StandardLayout() const { return data().IsCXX11StandardLayout; }
+
+ /// Determine whether this class, or any of its class subobjects,
/// contains a mutable field.
bool hasMutableFields() const { return data().HasMutableFields; }
- /// \brief Determine whether this class has any variant members.
+ /// Determine whether this class has any variant members.
bool hasVariantMembers() const { return data().HasVariantMembers; }
- /// \brief Determine whether this class has a trivial default constructor
+ /// Determine whether this class has a trivial default constructor
/// (C++11 [class.ctor]p5).
bool hasTrivialDefaultConstructor() const {
return hasDefaultConstructor() &&
(data().HasTrivialSpecialMembers & SMF_DefaultConstructor);
}
- /// \brief Determine whether this class has a non-trivial default constructor
+ /// Determine whether this class has a non-trivial default constructor
/// (C++11 [class.ctor]p5).
bool hasNonTrivialDefaultConstructor() const {
return (data().DeclaredNonTrivialSpecialMembers & SMF_DefaultConstructor) ||
@@ -1321,7 +1375,7 @@ public:
!(data().HasTrivialSpecialMembers & SMF_DefaultConstructor));
}
- /// \brief Determine whether this class has at least one constexpr constructor
+ /// Determine whether this class has at least one constexpr constructor
/// other than the copy or move constructors.
bool hasConstexprNonCopyMoveConstructor() const {
return data().HasConstexprNonCopyMoveConstructor ||
@@ -1329,41 +1383,56 @@ public:
defaultedDefaultConstructorIsConstexpr());
}
- /// \brief Determine whether a defaulted default constructor for this class
+ /// Determine whether a defaulted default constructor for this class
/// would be constexpr.
bool defaultedDefaultConstructorIsConstexpr() const {
return data().DefaultedDefaultConstructorIsConstexpr &&
(!isUnion() || hasInClassInitializer() || !hasVariantMembers());
}
- /// \brief Determine whether this class has a constexpr default constructor.
+ /// Determine whether this class has a constexpr default constructor.
bool hasConstexprDefaultConstructor() const {
return data().HasConstexprDefaultConstructor ||
(needsImplicitDefaultConstructor() &&
defaultedDefaultConstructorIsConstexpr());
}
- /// \brief Determine whether this class has a trivial copy constructor
+ /// Determine whether this class has a trivial copy constructor
/// (C++ [class.copy]p6, C++11 [class.copy]p12)
bool hasTrivialCopyConstructor() const {
return data().HasTrivialSpecialMembers & SMF_CopyConstructor;
}
- /// \brief Determine whether this class has a non-trivial copy constructor
+ bool hasTrivialCopyConstructorForCall() const {
+ return data().HasTrivialSpecialMembersForCall & SMF_CopyConstructor;
+ }
+
+ /// Determine whether this class has a non-trivial copy constructor
/// (C++ [class.copy]p6, C++11 [class.copy]p12)
bool hasNonTrivialCopyConstructor() const {
return data().DeclaredNonTrivialSpecialMembers & SMF_CopyConstructor ||
!hasTrivialCopyConstructor();
}
- /// \brief Determine whether this class has a trivial move constructor
+ bool hasNonTrivialCopyConstructorForCall() const {
+ return (data().DeclaredNonTrivialSpecialMembersForCall &
+ SMF_CopyConstructor) ||
+ !hasTrivialCopyConstructorForCall();
+ }
+
+ /// Determine whether this class has a trivial move constructor
/// (C++11 [class.copy]p12)
bool hasTrivialMoveConstructor() const {
return hasMoveConstructor() &&
(data().HasTrivialSpecialMembers & SMF_MoveConstructor);
}
- /// \brief Determine whether this class has a non-trivial move constructor
+ bool hasTrivialMoveConstructorForCall() const {
+ return hasMoveConstructor() &&
+ (data().HasTrivialSpecialMembersForCall & SMF_MoveConstructor);
+ }
+
+ /// Determine whether this class has a non-trivial move constructor
/// (C++11 [class.copy]p12)
bool hasNonTrivialMoveConstructor() const {
return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveConstructor) ||
@@ -1371,27 +1440,34 @@ public:
!(data().HasTrivialSpecialMembers & SMF_MoveConstructor));
}
- /// \brief Determine whether this class has a trivial copy assignment operator
+ bool hasNonTrivialMoveConstructorForCall() const {
+ return (data().DeclaredNonTrivialSpecialMembersForCall &
+ SMF_MoveConstructor) ||
+ (needsImplicitMoveConstructor() &&
+ !(data().HasTrivialSpecialMembersForCall & SMF_MoveConstructor));
+ }
+
+ /// Determine whether this class has a trivial copy assignment operator
/// (C++ [class.copy]p11, C++11 [class.copy]p25)
bool hasTrivialCopyAssignment() const {
return data().HasTrivialSpecialMembers & SMF_CopyAssignment;
}
- /// \brief Determine whether this class has a non-trivial copy assignment
+ /// Determine whether this class has a non-trivial copy assignment
/// operator (C++ [class.copy]p11, C++11 [class.copy]p25)
bool hasNonTrivialCopyAssignment() const {
return data().DeclaredNonTrivialSpecialMembers & SMF_CopyAssignment ||
!hasTrivialCopyAssignment();
}
- /// \brief Determine whether this class has a trivial move assignment operator
+ /// Determine whether this class has a trivial move assignment operator
/// (C++11 [class.copy]p25)
bool hasTrivialMoveAssignment() const {
return hasMoveAssignment() &&
(data().HasTrivialSpecialMembers & SMF_MoveAssignment);
}
- /// \brief Determine whether this class has a non-trivial move assignment
+ /// Determine whether this class has a non-trivial move assignment
/// operator (C++11 [class.copy]p25)
bool hasNonTrivialMoveAssignment() const {
return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveAssignment) ||
@@ -1399,19 +1475,32 @@ public:
!(data().HasTrivialSpecialMembers & SMF_MoveAssignment));
}
- /// \brief Determine whether this class has a trivial destructor
+ /// Determine whether this class has a trivial destructor
/// (C++ [class.dtor]p3)
bool hasTrivialDestructor() const {
return data().HasTrivialSpecialMembers & SMF_Destructor;
}
- /// \brief Determine whether this class has a non-trivial destructor
+ bool hasTrivialDestructorForCall() const {
+ return data().HasTrivialSpecialMembersForCall & SMF_Destructor;
+ }
+
+ /// Determine whether this class has a non-trivial destructor
/// (C++ [class.dtor]p3)
bool hasNonTrivialDestructor() const {
return !(data().HasTrivialSpecialMembers & SMF_Destructor);
}
- /// \brief Determine whether declaring a const variable with this type is ok
+ bool hasNonTrivialDestructorForCall() const {
+ return !(data().HasTrivialSpecialMembersForCall & SMF_Destructor);
+ }
+
+ void setHasTrivialSpecialMemberForCall() {
+ data().HasTrivialSpecialMembersForCall =
+ (SMF_CopyConstructor | SMF_MoveConstructor | SMF_Destructor);
+ }
+
+ /// Determine whether declaring a const variable with this type is ok
/// per core issue 253.
bool allowConstDefaultInit() const {
return !data().HasUninitializedFields ||
@@ -1419,7 +1508,7 @@ public:
needsImplicitDefaultConstructor());
}
- /// \brief Determine whether this class has a destructor which has no
+ /// Determine whether this class has a destructor which has no
/// semantic effect.
///
/// Any such destructor will be trivial, public, defaulted and not deleted,
@@ -1428,41 +1517,29 @@ public:
return data().HasIrrelevantDestructor;
}
- /// \brief Determine whether this class has at least one trivial, non-deleted
- /// copy or move constructor.
- bool canPassInRegisters() const {
- return data().CanPassInRegisters;
- }
-
- /// \brief Set that we can pass this RecordDecl in registers.
- // FIXME: This should be set as part of completeDefinition.
- void setCanPassInRegisters(bool CanPass) {
- data().CanPassInRegisters = CanPass;
- }
-
- /// \brief Determine whether this class has a non-literal or/ volatile type
+ /// Determine whether this class has a non-literal or/ volatile type
/// non-static data member or base class.
bool hasNonLiteralTypeFieldsOrBases() const {
return data().HasNonLiteralTypeFieldsOrBases;
}
- /// \brief Determine whether this class has a using-declaration that names
+ /// Determine whether this class has a using-declaration that names
/// a user-declared base class constructor.
bool hasInheritedConstructor() const {
return data().HasInheritedConstructor;
}
- /// \brief Determine whether this class has a using-declaration that names
+ /// Determine whether this class has a using-declaration that names
/// a base class assignment operator.
bool hasInheritedAssignment() const {
return data().HasInheritedAssignment;
}
- /// \brief Determine whether this class is considered trivially copyable per
+ /// Determine whether this class is considered trivially copyable per
/// (C++11 [class]p6).
bool isTriviallyCopyable() const;
- /// \brief Determine whether this class is considered trivial.
+ /// Determine whether this class is considered trivial.
///
/// C++11 [class]p6:
/// "A trivial class is a class that has a trivial default constructor and
@@ -1471,7 +1548,7 @@ public:
return isTriviallyCopyable() && hasTrivialDefaultConstructor();
}
- /// \brief Determine whether this class is a literal type.
+ /// Determine whether this class is a literal type.
///
/// C++11 [basic.types]p10:
/// A class type that has all the following properties:
@@ -1497,7 +1574,7 @@ public:
hasTrivialDefaultConstructor());
}
- /// \brief If this record is an instantiation of a member class,
+ /// If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
/// This routine will return non-null for (non-templated) member
@@ -1518,17 +1595,17 @@ public:
/// declaration returned by getInstantiatedFromMemberClass().
CXXRecordDecl *getInstantiatedFromMemberClass() const;
- /// \brief If this class is an instantiation of a member class of a
+ /// If this class is an instantiation of a member class of a
/// class template specialization, retrieves the member specialization
/// information.
MemberSpecializationInfo *getMemberSpecializationInfo() const;
- /// \brief Specify that this record is an instantiation of the
+ /// Specify that this record is an instantiation of the
/// member class \p RD.
void setInstantiationOfMemberClass(CXXRecordDecl *RD,
TemplateSpecializationKind TSK);
- /// \brief Retrieves the class template that is described by this
+ /// Retrieves the class template that is described by this
/// class declaration.
///
/// Every class template is represented as a ClassTemplateDecl and a
@@ -1543,15 +1620,15 @@ public:
void setDescribedClassTemplate(ClassTemplateDecl *Template);
- /// \brief Determine whether this particular class is a specialization or
+ /// Determine whether this particular class is a specialization or
/// instantiation of a class template or member class of a class template,
/// and how it was instantiated or specialized.
TemplateSpecializationKind getTemplateSpecializationKind() const;
- /// \brief Set the kind of specialization or template instantiation this is.
+ /// Set the kind of specialization or template instantiation this is.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
- /// \brief Retrieve the record declaration from which this record could be
+ /// Retrieve the record declaration from which this record could be
/// instantiated. Returns null if this class is not a template instantiation.
const CXXRecordDecl *getTemplateInstantiationPattern() const;
@@ -1560,17 +1637,17 @@ public:
->getTemplateInstantiationPattern());
}
- /// \brief Returns the destructor decl for this class.
+ /// Returns the destructor decl for this class.
CXXDestructorDecl *getDestructor() const;
- /// \brief Returns true if the class destructor, or any implicitly invoked
+ /// Returns true if the class destructor, or any implicitly invoked
/// destructors are marked noreturn.
bool isAnyDestructorNoReturn() const;
- /// \brief If the class is a local class [class.local], returns
+ /// If the class is a local class [class.local], returns
/// the enclosing function declaration.
const FunctionDecl *isLocalClass() const {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
return RD->isLocalClass();
return dyn_cast<FunctionDecl>(getDeclContext());
@@ -1581,11 +1658,11 @@ public:
const_cast<const CXXRecordDecl*>(this)->isLocalClass());
}
- /// \brief Determine whether this dependent class is a current instantiation,
+ /// Determine whether this dependent class is a current instantiation,
/// when viewed from within the given context.
bool isCurrentInstantiation(const DeclContext *CurContext) const;
- /// \brief Determine whether this class is derived from the class \p Base.
+ /// Determine whether this class is derived from the class \p Base.
///
/// This routine only determines whether this class is derived from \p Base,
/// but does not account for factors that may make a Derived -> Base class
@@ -1597,7 +1674,7 @@ public:
/// \returns true if this class is derived from Base, false otherwise.
bool isDerivedFrom(const CXXRecordDecl *Base) const;
- /// \brief Determine whether this class is derived from the type \p Base.
+ /// Determine whether this class is derived from the type \p Base.
///
/// This routine only determines whether this class is derived from \p Base,
/// but does not account for factors that may make a Derived -> Base class
@@ -1615,7 +1692,7 @@ public:
/// tangling input and output in \p Paths
bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
- /// \brief Determine whether this class is virtually derived from
+ /// Determine whether this class is virtually derived from
/// the class \p Base.
///
/// This routine only determines whether this class is virtually
@@ -1630,11 +1707,11 @@ public:
/// false otherwise.
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const;
- /// \brief Determine whether this class is provably not derived from
+ /// Determine whether this class is provably not derived from
/// the type \p Base.
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const;
- /// \brief Function type used by forallBases() as a callback.
+ /// Function type used by forallBases() as a callback.
///
/// \param BaseDefinition the definition of the base class
///
@@ -1642,7 +1719,7 @@ public:
using ForallBasesCallback =
llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>;
- /// \brief Determines if the given callback holds for all the direct
+ /// Determines if the given callback holds for all the direct
/// or indirect base classes of this type.
///
/// The class itself does not count as a base class. This routine
@@ -1658,7 +1735,7 @@ public:
bool forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit = true) const;
- /// \brief Function type used by lookupInBases() to determine whether a
+ /// Function type used by lookupInBases() to determine whether a
/// specific base class subobject matches the lookup criteria.
///
/// \param Specifier the base-class specifier that describes the inheritance
@@ -1672,7 +1749,7 @@ public:
llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path)>;
- /// \brief Look for entities within the base classes of this C++ class,
+ /// Look for entities within the base classes of this C++ class,
/// transitively searching all base class subobjects.
///
/// This routine uses the callback function \p BaseMatches to find base
@@ -1696,7 +1773,7 @@ public:
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths,
bool LookupInDependent = false) const;
- /// \brief Base-class lookup callback that determines whether the given
+ /// Base-class lookup callback that determines whether the given
/// base class specifier refers to a specific class declaration.
///
/// This callback can be used with \c lookupInBases() to determine whether
@@ -1706,7 +1783,7 @@ public:
static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, const CXXRecordDecl *BaseRecord);
- /// \brief Base-class lookup callback that determines whether the
+ /// Base-class lookup callback that determines whether the
/// given base class specifier refers to a specific class
/// declaration and describes virtual derivation.
///
@@ -1719,7 +1796,7 @@ public:
CXXBasePath &Path,
const CXXRecordDecl *BaseRecord);
- /// \brief Base-class lookup callback that determines whether there exists
+ /// Base-class lookup callback that determines whether there exists
/// a tag with the given name.
///
/// This callback can be used with \c lookupInBases() to find tag members
@@ -1727,7 +1804,7 @@ public:
static bool FindTagMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);
- /// \brief Base-class lookup callback that determines whether there exists
+ /// Base-class lookup callback that determines whether there exists
/// a member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
@@ -1735,7 +1812,7 @@ public:
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);
- /// \brief Base-class lookup callback that determines whether there exists
+ /// Base-class lookup callback that determines whether there exists
/// a member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
@@ -1745,7 +1822,7 @@ public:
FindOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);
- /// \brief Base-class lookup callback that determines whether there exists
+ /// Base-class lookup callback that determines whether there exists
/// an OpenMP declare reduction member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
@@ -1753,7 +1830,7 @@ public:
static bool FindOMPReductionMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);
- /// \brief Base-class lookup callback that determines whether there exists
+ /// Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
///
/// This callback can be used with \c lookupInBases() to find members of
@@ -1763,12 +1840,12 @@ public:
CXXBasePath &Path,
DeclarationName Name);
- /// \brief Retrieve the final overriders for each virtual member
+ /// Retrieve the final overriders for each virtual member
/// function in the class hierarchy where this class is the
/// most-derived class in the class hierarchy.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const;
- /// \brief Get the indirect primary bases for this class.
+ /// Get the indirect primary bases for this class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const;
/// Performs an imprecise lookup of a dependent name in this class.
@@ -1784,7 +1861,7 @@ public:
/// GraphViz.
void viewInheritance(ASTContext& Context) const;
- /// \brief Calculates the access of a decl that is reached
+ /// Calculates the access of a decl that is reached
/// along a path.
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess,
AccessSpecifier DeclAccess) {
@@ -1793,14 +1870,16 @@ public:
return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
}
- /// \brief Indicates that the declaration of a defaulted or deleted special
+ /// Indicates that the declaration of a defaulted or deleted special
/// member function is now complete.
void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD);
- /// \brief Indicates that the definition of this class is now complete.
+ void setTrivialForCallFlags(CXXMethodDecl *MD);
+
+ /// Indicates that the definition of this class is now complete.
void completeDefinition() override;
- /// \brief Indicates that the definition of this class is now complete,
+ /// Indicates that the definition of this class is now complete,
/// and provides a final overrider map to help determine
///
/// \param FinalOverriders The final overrider map for this class, which can
@@ -1809,7 +1888,7 @@ public:
/// definition.
void completeDefinition(CXXFinalOverriderMap *FinalOverriders);
- /// \brief Determine whether this class may end up being abstract, even though
+ /// Determine whether this class may end up being abstract, even though
/// it is not yet known to be abstract.
///
/// \returns true if this class is not known to be abstract but has any
@@ -1818,39 +1897,39 @@ public:
/// actually abstract.
bool mayBeAbstract() const;
- /// \brief If this is the closure type of a lambda expression, retrieve the
+ /// If this is the closure type of a lambda expression, retrieve the
/// number to be used for name mangling in the Itanium C++ ABI.
///
- /// Zero indicates that this closure type has internal linkage, so the
+ /// Zero indicates that this closure type has internal linkage, so the
/// mangling number does not matter, while a non-zero value indicates which
/// lambda expression this is in this particular context.
unsigned getLambdaManglingNumber() const {
assert(isLambda() && "Not a lambda closure type!");
return getLambdaData().ManglingNumber;
}
-
- /// \brief Retrieve the declaration that provides additional context for a
+
+ /// Retrieve the declaration that provides additional context for a
/// lambda, when the normal declaration context is not specific enough.
///
- /// Certain contexts (default arguments of in-class function parameters and
+ /// Certain contexts (default arguments of in-class function parameters and
/// the initializers of data members) have separate name mangling rules for
/// lambdas within the Itanium C++ ABI. For these cases, this routine provides
- /// the declaration in which the lambda occurs, e.g., the function parameter
+ /// the declaration in which the lambda occurs, e.g., the function parameter
/// or the non-static data member. Otherwise, it returns NULL to imply that
/// the declaration context suffices.
Decl *getLambdaContextDecl() const;
-
- /// \brief Set the mangling number and context declaration for a lambda
+
+ /// Set the mangling number and context declaration for a lambda
/// class.
void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
getLambdaData().ManglingNumber = ManglingNumber;
getLambdaData().ContextDecl = ContextDecl;
}
- /// \brief Returns the inheritance model used for this record.
+ /// Returns the inheritance model used for this record.
MSInheritanceAttr::Spelling getMSInheritanceModel() const;
- /// \brief Calculate what the inheritance model would be for this class.
+ /// Calculate what the inheritance model would be for this class.
MSInheritanceAttr::Spelling calculateInheritanceModel() const;
/// In the Microsoft C++ ABI, use zero for the field offset of a null data
@@ -1865,11 +1944,11 @@ public:
(hasDefinition() && isPolymorphic());
}
- /// \brief Controls when vtordisps will be emitted if this record is used as a
+ /// Controls when vtordisps will be emitted if this record is used as a
/// virtual base.
MSVtorDispAttr::Mode getMSVtorDispMode() const;
- /// \brief Determine whether this lambda expression was known to be dependent
+ /// Determine whether this lambda expression was known to be dependent
/// at the time it was created, even if its context does not appear to be
/// dependent.
///
@@ -1888,8 +1967,8 @@ public:
return getLambdaData().MethodTyInfo;
}
- // \brief Determine whether this type is an Interface Like type for
- // __interface inheritence purposes.
+ // Determine whether this type is an Interface Like type for
+ // __interface inheritance purposes.
bool isInterfaceLike() const;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1898,7 +1977,7 @@ public:
}
};
-/// \brief Represents a C++ deduction guide declaration.
+/// Represents a C++ deduction guide declaration.
///
/// \code
/// template<typename T> struct A { A(); A(T); };
@@ -1957,7 +2036,7 @@ public:
static bool classofKind(Kind K) { return K == CXXDeductionGuide; }
};
-/// \brief Represents a static or instance method of a struct/union/class.
+/// Represents a static or instance method of a struct/union/class.
///
/// In the terminology of the C++ Standard, these are the (static and
/// non-static) member functions, whether virtual or not.
@@ -2007,8 +2086,7 @@ public:
bool isVolatile() const { return getType()->castAs<FunctionType>()->isVolatile(); }
bool isVirtual() const {
- CXXMethodDecl *CD =
- cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
+ CXXMethodDecl *CD = const_cast<CXXMethodDecl*>(this)->getCanonicalDecl();
// Member function is virtual if it is marked explicitly so, or if it is
// declared in __interface -- then it is automatically pure virtual.
@@ -2031,16 +2109,16 @@ public:
Base, IsAppleKext);
}
- /// \brief Determine whether this is a usual deallocation function
+ /// Determine whether this is a usual deallocation function
/// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
/// delete or delete[] operator with a particular signature.
bool isUsualDeallocationFunction() const;
- /// \brief Determine whether this is a copy-assignment operator, regardless
+ /// Determine whether this is a copy-assignment operator, regardless
/// of whether it was declared implicitly or explicitly.
bool isCopyAssignmentOperator() const;
- /// \brief Determine whether this is a move assignment operator.
+ /// Determine whether this is a move assignment operator.
bool isMoveAssignmentOperator() const;
CXXMethodDecl *getCanonicalDecl() override {
@@ -2093,7 +2171,7 @@ public:
cast<CXXRecordDecl>(FunctionDecl::getParent()));
}
- /// \brief Returns the type of the \c this pointer.
+ /// Returns the type of the \c this pointer.
///
/// Should only be called for instance (i.e., non-static) methods. Note
/// that for the call operator of a lambda closure type, this returns the
@@ -2105,7 +2183,7 @@ public:
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
}
- /// \brief Retrieve the ref-qualifier associated with this method.
+ /// Retrieve the ref-qualifier associated with this method.
///
/// In the following example, \c f() has an lvalue ref-qualifier, \c g()
/// has an rvalue ref-qualifier, and \c h() has no ref-qualifier.
@@ -2122,7 +2200,7 @@ public:
bool hasInlineBody() const;
- /// \brief Determine whether this is a lambda closure type's static member
+ /// Determine whether this is a lambda closure type's static member
/// function that is used for the result of the lambda's conversion to
/// function pointer (for a lambda with no captures).
///
@@ -2131,7 +2209,7 @@ public:
/// or clone the function call operator.
bool isLambdaStaticInvoker() const;
- /// \brief Find the method in \p RD that corresponds to this one.
+ /// Find the method in \p RD that corresponds to this one.
///
/// Find if \p RD or one of the classes it inherits from override this method.
/// If so, return it. \p RD is assumed to be a subclass of the class defining
@@ -2154,7 +2232,7 @@ public:
}
};
-/// \brief Represents a C++ base or member initializer.
+/// Represents a C++ base or member initializer.
///
/// This is part of a constructor initializer that
/// initializes one non-static member variable or one base class. For
@@ -2170,13 +2248,13 @@ public:
/// };
/// \endcode
class CXXCtorInitializer final {
- /// \brief Either the base class name/delegating constructor type (stored as
+ /// Either the base class name/delegating constructor type (stored as
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
/// (IndirectFieldDecl*) being initialized.
llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
Initializee;
- /// \brief The source location for the field name or, for a base initializer
+ /// The source location for the field name or, for a base initializer
/// pack expansion, the location of the ellipsis.
///
/// In the case of a delegating
@@ -2184,25 +2262,25 @@ class CXXCtorInitializer final {
/// Initializee points to the CXXConstructorDecl (to allow loop detection).
SourceLocation MemberOrEllipsisLocation;
- /// \brief The argument used to initialize the base or member, which may
+ /// The argument used to initialize the base or member, which may
/// end up constructing an object (when multiple arguments are involved).
Stmt *Init;
- /// \brief Location of the left paren of the ctor-initializer.
+ /// Location of the left paren of the ctor-initializer.
SourceLocation LParenLoc;
- /// \brief Location of the right paren of the ctor-initializer.
+ /// Location of the right paren of the ctor-initializer.
SourceLocation RParenLoc;
- /// \brief If the initializee is a type, whether that type makes this
+ /// If the initializee is a type, whether that type makes this
/// a delegating initialization.
unsigned IsDelegating : 1;
- /// \brief If the initializer is a base initializer, this keeps track
+ /// If the initializer is a base initializer, this keeps track
/// of whether the base is virtual or not.
unsigned IsVirtual : 1;
- /// \brief Whether or not the initializer is explicitly written
+ /// Whether or not the initializer is explicitly written
/// in the sources.
unsigned IsWritten : 1;
@@ -2211,35 +2289,35 @@ class CXXCtorInitializer final {
unsigned SourceOrder : 13;
public:
- /// \brief Creates a new base-class initializer.
+ /// Creates a new base-class initializer.
explicit
CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual,
SourceLocation L, Expr *Init, SourceLocation R,
SourceLocation EllipsisLoc);
- /// \brief Creates a new member initializer.
+ /// Creates a new member initializer.
explicit
CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
SourceLocation MemberLoc, SourceLocation L, Expr *Init,
SourceLocation R);
- /// \brief Creates a new anonymous field initializer.
+ /// Creates a new anonymous field initializer.
explicit
CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
SourceLocation MemberLoc, SourceLocation L, Expr *Init,
SourceLocation R);
- /// \brief Creates a new delegating initializer.
+ /// Creates a new delegating initializer.
explicit
CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo,
SourceLocation L, Expr *Init, SourceLocation R);
- /// \brief Determine whether this initializer is initializing a base class.
+ /// Determine whether this initializer is initializing a base class.
bool isBaseInitializer() const {
return Initializee.is<TypeSourceInfo*>() && !IsDelegating;
}
- /// \brief Determine whether this initializer is initializing a non-static
+ /// Determine whether this initializer is initializing a non-static
/// data member.
bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); }
@@ -2251,7 +2329,7 @@ public:
return Initializee.is<IndirectFieldDecl*>();
}
- /// \brief Determine whether this initializer is an implicit initializer
+ /// Determine whether this initializer is an implicit initializer
/// generated for a field with an initializer defined on the member
/// declaration.
///
@@ -2261,18 +2339,18 @@ public:
return Init->getStmtClass() == Stmt::CXXDefaultInitExprClass;
}
- /// \brief Determine whether this initializer is creating a delegating
+ /// Determine whether this initializer is creating a delegating
/// constructor.
bool isDelegatingInitializer() const {
return Initializee.is<TypeSourceInfo*>() && IsDelegating;
}
- /// \brief Determine whether this initializer is a pack expansion.
+ /// Determine whether this initializer is a pack expansion.
bool isPackExpansion() const {
return isBaseInitializer() && MemberOrEllipsisLocation.isValid();
}
- // \brief For a pack expansion, returns the location of the ellipsis.
+ // For a pack expansion, returns the location of the ellipsis.
SourceLocation getEllipsisLoc() const {
assert(isPackExpansion() && "Initializer is not a pack expansion");
return MemberOrEllipsisLocation;
@@ -2294,13 +2372,13 @@ public:
return IsVirtual;
}
- /// \brief Returns the declarator information for a base class or delegating
+ /// Returns the declarator information for a base class or delegating
/// initializer.
TypeSourceInfo *getTypeSourceInfo() const {
return Initializee.dyn_cast<TypeSourceInfo *>();
}
- /// \brief If this is a member initializer, returns the declaration of the
+ /// If this is a member initializer, returns the declaration of the
/// non-static data member being initialized. Otherwise, returns null.
FieldDecl *getMember() const {
if (isMemberInitializer())
@@ -2326,23 +2404,23 @@ public:
return MemberOrEllipsisLocation;
}
- /// \brief Determine the source location of the initializer.
+ /// Determine the source location of the initializer.
SourceLocation getSourceLocation() const;
- /// \brief Determine the source range covering the entire initializer.
+ /// Determine the source range covering the entire initializer.
SourceRange getSourceRange() const LLVM_READONLY;
- /// \brief Determine whether this initializer is explicitly written
+ /// Determine whether this initializer is explicitly written
/// in the source code.
bool isWritten() const { return IsWritten; }
- /// \brief Return the source position of the initializer, counting from 0.
+ /// Return the source position of the initializer, counting from 0.
/// If the initializer was implicit, -1 is returned.
int getSourceOrder() const {
return IsWritten ? static_cast<int>(SourceOrder) : -1;
}
- /// \brief Set the source order of this initializer.
+ /// Set the source order of this initializer.
///
/// This can only be called once for each initializer; it cannot be called
/// on an initializer having a positive number of (implicit) array indices.
@@ -2363,8 +2441,8 @@ public:
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- /// \brief Get the initializer.
- Expr *getInit() const { return static_cast<Expr*>(Init); }
+ /// Get the initializer.
+ Expr *getInit() const { return static_cast<Expr *>(Init); }
};
/// Description of a constructor that was inherited from a base class.
@@ -2384,7 +2462,7 @@ public:
CXXConstructorDecl *getConstructor() const { return BaseCtor; }
};
-/// \brief Represents a C++ constructor within a class.
+/// Represents a C++ constructor within a class.
///
/// For example:
///
@@ -2399,12 +2477,12 @@ class CXXConstructorDecl final
private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> {
/// \name Support for base and member initializers.
/// \{
- /// \brief The arguments used to initialize the base or member.
+ /// The arguments used to initialize the base or member.
LazyCXXCtorInitializersPtr CtorInitializers;
unsigned NumCtorInitializers : 31;
/// \}
- /// \brief Whether this constructor declaration is an implicitly-declared
+ /// Whether this constructor declaration is an implicitly-declared
/// inheriting constructor.
unsigned IsInheritingConstructor : 1;
@@ -2439,10 +2517,10 @@ public:
bool isConstexpr,
InheritedConstructor Inherited = InheritedConstructor());
- /// \brief Iterates through the member/base initializer list.
+ /// Iterates through the member/base initializer list.
using init_iterator = CXXCtorInitializer **;
- /// \brief Iterates through the member/base initializer list.
+ /// Iterates through the member/base initializer list.
using init_const_iterator = CXXCtorInitializer *const *;
using init_range = llvm::iterator_range<init_iterator>;
@@ -2453,21 +2531,21 @@ public:
return init_const_range(init_begin(), init_end());
}
- /// \brief Retrieve an iterator to the first initializer.
+ /// Retrieve an iterator to the first initializer.
init_iterator init_begin() {
const auto *ConstThis = this;
return const_cast<init_iterator>(ConstThis->init_begin());
}
- /// \brief Retrieve an iterator to the first initializer.
+ /// Retrieve an iterator to the first initializer.
init_const_iterator init_begin() const;
- /// \brief Retrieve an iterator past the last initializer.
+ /// Retrieve an iterator past the last initializer.
init_iterator init_end() {
return init_begin() + NumCtorInitializers;
}
- /// \brief Retrieve an iterator past the last initializer.
+ /// Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
return init_begin() + NumCtorInitializers;
}
@@ -2490,7 +2568,7 @@ public:
return init_const_reverse_iterator(init_begin());
}
- /// \brief Determine the number of arguments used to initialize the member
+ /// Determine the number of arguments used to initialize the member
/// or base.
unsigned getNumCtorInitializers() const {
return NumCtorInitializers;
@@ -2512,13 +2590,13 @@ public:
return getCanonicalDecl()->isExplicitSpecified();
}
- /// \brief Determine whether this constructor is a delegating constructor.
+ /// Determine whether this constructor is a delegating constructor.
bool isDelegatingConstructor() const {
return (getNumCtorInitializers() == 1) &&
init_begin()[0]->isDelegatingInitializer();
}
- /// \brief When this constructor delegates to another, retrieve the target.
+ /// When this constructor delegates to another, retrieve the target.
CXXConstructorDecl *getTargetConstructor() const;
/// Whether this constructor is a default
@@ -2526,7 +2604,7 @@ public:
/// default-initialize a class of this type.
bool isDefaultConstructor() const;
- /// \brief Whether this constructor is a copy constructor (C++ [class.copy]p2,
+ /// Whether this constructor is a copy constructor (C++ [class.copy]p2,
/// which can be used to copy the class.
///
/// \p TypeQuals will be set to the qualifiers on the
@@ -2549,27 +2627,27 @@ public:
return isCopyConstructor(TypeQuals);
}
- /// \brief Determine whether this constructor is a move constructor
+ /// Determine whether this constructor is a move constructor
/// (C++11 [class.copy]p3), which can be used to move values of the class.
///
/// \param TypeQuals If this constructor is a move constructor, will be set
/// to the type qualifiers on the referent of the first parameter's type.
bool isMoveConstructor(unsigned &TypeQuals) const;
- /// \brief Determine whether this constructor is a move constructor
+ /// Determine whether this constructor is a move constructor
/// (C++11 [class.copy]p3), which can be used to move values of the class.
bool isMoveConstructor() const {
unsigned TypeQuals = 0;
return isMoveConstructor(TypeQuals);
}
- /// \brief Determine whether this is a copy or move constructor.
+ /// Determine whether this is a copy or move constructor.
///
/// \param TypeQuals Will be set to the type qualifiers on the reference
/// parameter, if in fact this is a copy or move constructor.
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const;
- /// \brief Determine whether this a copy or move constructor.
+ /// Determine whether this a copy or move constructor.
bool isCopyOrMoveConstructor() const {
unsigned Quals;
return isCopyOrMoveConstructor(Quals);
@@ -2580,16 +2658,16 @@ public:
/// used for user-defined conversions.
bool isConvertingConstructor(bool AllowExplicit) const;
- /// \brief Determine whether this is a member template specialization that
+ /// Determine whether this is a member template specialization that
/// would copy the object to itself. Such constructors are never used to copy
/// an object.
bool isSpecializationCopyingObject() const;
- /// \brief Determine whether this is an implicit constructor synthesized to
+ /// Determine whether this is an implicit constructor synthesized to
/// model a call to a constructor inherited from a base class.
bool isInheritingConstructor() const { return IsInheritingConstructor; }
- /// \brief Get the constructor that this inheriting constructor is based on.
+ /// Get the constructor that this inheriting constructor is based on.
InheritedConstructor getInheritedConstructor() const {
return IsInheritingConstructor ? *getTrailingObjects<InheritedConstructor>()
: InheritedConstructor();
@@ -2607,7 +2685,7 @@ public:
static bool classofKind(Kind K) { return K == CXXConstructor; }
};
-/// \brief Represents a C++ destructor within a class.
+/// Represents a C++ destructor within a class.
///
/// For example:
///
@@ -2669,7 +2747,7 @@ public:
static bool classofKind(Kind K) { return K == CXXDestructor; }
};
-/// \brief Represents a C++ conversion function within a class.
+/// Represents a C++ conversion function within a class.
///
/// For example:
///
@@ -2713,15 +2791,15 @@ public:
return getCanonicalDecl()->isExplicitSpecified();
}
- /// \brief Returns the type that this conversion function is converting to.
+ /// Returns the type that this conversion function is converting to.
QualType getConversionType() const {
return getType()->getAs<FunctionType>()->getReturnType();
}
- /// \brief Determine whether this conversion function is a conversion from
+ /// Determine whether this conversion function is a conversion from
/// a lambda closure type to a block pointer.
bool isLambdaToBlockPointerConversion() const;
-
+
CXXConversionDecl *getCanonicalDecl() override {
return cast<CXXConversionDecl>(FunctionDecl::getCanonicalDecl());
}
@@ -2734,7 +2812,7 @@ public:
static bool classofKind(Kind K) { return K == CXXConversion; }
};
-/// \brief Represents a linkage specification.
+/// Represents a linkage specification.
///
/// For example:
/// \code
@@ -2744,7 +2822,7 @@ class LinkageSpecDecl : public Decl, public DeclContext {
virtual void anchor();
public:
- /// \brief Represents the language in a linkage specification.
+ /// Represents the language in a linkage specification.
///
/// The values are part of the serialization ABI for
/// ASTs and cannot be changed without altering that ABI. To help
@@ -2756,20 +2834,20 @@ public:
};
private:
- /// \brief The language for this linkage specification.
+ /// The language for this linkage specification.
unsigned Language : 3;
- /// \brief True if this linkage spec has braces.
+ /// 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.
+ /// The source location for the extern keyword.
SourceLocation ExternLoc;
- /// \brief The source location for the right brace (if valid).
+ /// The source location for the right brace (if valid).
SourceLocation RBraceLoc;
LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
@@ -2784,14 +2862,14 @@ public:
SourceLocation LangLoc, LanguageIDs Lang,
bool HasBraces);
static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- /// \brief Return the language specified by this linkage specification.
+
+ /// Return the language specified by this linkage specification.
LanguageIDs getLanguage() const { return LanguageIDs(Language); }
- /// \brief Set the language specified by this linkage specification.
+ /// Set the language specified by this linkage specification.
void setLanguage(LanguageIDs L) { Language = L; }
- /// \brief Determines whether this linkage specification had braces in
+ /// Determines whether this linkage specification had braces in
/// its syntactic form.
bool hasBraces() const {
assert(!RBraceLoc.isValid() || HasBraces);
@@ -2830,7 +2908,7 @@ public:
}
};
-/// \brief Represents C++ using-directive.
+/// Represents C++ using-directive.
///
/// For example:
/// \code
@@ -2841,16 +2919,16 @@ public:
/// artificial names for all using-directives in order to store
/// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
- /// \brief The location of the \c using keyword.
+ /// The location of the \c using keyword.
SourceLocation UsingLoc;
- /// \brief The location of the \c namespace keyword.
+ /// The location of the \c namespace keyword.
SourceLocation NamespaceLoc;
- /// \brief The nested-name-specifier that precedes the namespace.
+ /// The nested-name-specifier that precedes the namespace.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief The namespace nominated by this using-directive.
+ /// The namespace nominated by this using-directive.
NamedDecl *NominatedNamespace;
/// Enclosing context containing both using-directive and nominated
@@ -2867,7 +2945,7 @@ class UsingDirectiveDecl : public NamedDecl {
NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc),
NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) {}
- /// \brief Returns special DeclarationName used by using-directives.
+ /// Returns special DeclarationName used by using-directives.
///
/// This is only used by DeclContext for storing UsingDirectiveDecls in
/// its lookup structure.
@@ -2883,11 +2961,11 @@ public:
// Friend for getUsingDirectiveName.
friend class DeclContext;
- /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// Retrieve the nested-name-specifier that qualifies the
/// name of the namespace, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
@@ -2898,26 +2976,26 @@ public:
return NominatedNamespace;
}
- /// \brief Returns the namespace nominated by this using-directive.
+ /// Returns the namespace nominated by this using-directive.
NamespaceDecl *getNominatedNamespace();
const NamespaceDecl *getNominatedNamespace() const {
return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
}
- /// \brief Returns the common ancestor context of this using-directive and
+ /// Returns the common ancestor context of this using-directive and
/// its nominated namespace.
DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; }
- /// \brief Return the location of the \c using keyword.
+ /// Return the location of the \c using keyword.
SourceLocation getUsingLoc() const { return UsingLoc; }
// FIXME: Could omit 'Key' in name.
- /// \brief Returns the location of the \c namespace keyword.
+ /// Returns the location of the \c namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
- /// \brief Returns the location of this using declaration's identifier.
+ /// Returns the location of this using declaration's identifier.
SourceLocation getIdentLocation() const { return getLocation(); }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2937,7 +3015,7 @@ public:
static bool classofKind(Kind K) { return K == UsingDirective; }
};
-/// \brief Represents a C++ namespace alias.
+/// Represents a C++ namespace alias.
///
/// For example:
///
@@ -2948,18 +3026,18 @@ class NamespaceAliasDecl : public NamedDecl,
public Redeclarable<NamespaceAliasDecl> {
friend class ASTDeclReader;
- /// \brief The location of the \c namespace keyword.
+ /// The location of the \c namespace keyword.
SourceLocation NamespaceLoc;
- /// \brief The location of the namespace's identifier.
+ /// The location of the namespace's identifier.
///
/// This is accessed by TargetNameLoc.
SourceLocation IdentLoc;
- /// \brief The nested-name-specifier that precedes the namespace.
+ /// The nested-name-specifier that precedes the namespace.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief The Decl that this alias points to, either a NamespaceDecl or
+ /// The Decl that this alias points to, either a NamespaceDecl or
/// a NamespaceAliasDecl.
NamedDecl *Namespace;
@@ -3006,26 +3084,26 @@ public:
return getFirstDecl();
}
- /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// Retrieve the nested-name-specifier that qualifies the
/// name of the namespace, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Retrieve the namespace declaration aliased by this directive.
+ /// Retrieve the namespace declaration aliased by this directive.
NamespaceDecl *getNamespace() {
- if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
+ if (auto *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
return AD->getNamespace();
return cast<NamespaceDecl>(Namespace);
}
const NamespaceDecl *getNamespace() const {
- return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
+ return const_cast<NamespaceAliasDecl *>(this)->getNamespace();
}
/// Returns the location of the alias name, i.e. 'foo' in
@@ -3038,7 +3116,7 @@ public:
/// Returns the location of the identifier in the named namespace.
SourceLocation getTargetNameLoc() const { return IdentLoc; }
- /// \brief Retrieve the namespace that this alias refers to, which
+ /// Retrieve the namespace that this alias refers to, which
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *getAliasedNamespace() const { return Namespace; }
@@ -3050,7 +3128,7 @@ public:
static bool classofKind(Kind K) { return K == NamespaceAlias; }
};
-/// \brief Represents a shadow declaration introduced into a scope by a
+/// Represents a shadow declaration introduced into a scope by a
/// (resolved) using declaration.
///
/// For example,
@@ -3069,7 +3147,7 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
/// The referenced declaration.
NamedDecl *Underlying = nullptr;
- /// \brief The using declaration which introduced this decl or the next using
+ /// The using declaration which introduced this decl or the next using
/// shadow declaration contained in the aforementioned using declaration.
NamedDecl *UsingOrNextShadow = nullptr;
@@ -3123,22 +3201,26 @@ public:
return getFirstDecl();
}
- /// \brief Gets the underlying declaration which has been brought into the
+ /// Gets the underlying declaration which has been brought into the
/// local scope.
NamedDecl *getTargetDecl() const { return Underlying; }
- /// \brief Sets the underlying declaration which has been brought into the
+ /// Sets the underlying declaration which has been brought into the
/// local scope.
- void setTargetDecl(NamedDecl* ND) {
+ void setTargetDecl(NamedDecl *ND) {
assert(ND && "Target decl is null!");
Underlying = ND;
- IdentifierNamespace = ND->getIdentifierNamespace();
+ // A UsingShadowDecl is never a friend or local extern declaration, even
+ // if it is a shadow declaration for one.
+ IdentifierNamespace =
+ ND->getIdentifierNamespace() &
+ ~(IDNS_OrdinaryFriend | IDNS_TagFriend | IDNS_LocalExtern);
}
- /// \brief Gets the using declaration to which this declaration is tied.
+ /// Gets the using declaration to which this declaration is tied.
UsingDecl *getUsingDecl() const;
- /// \brief The next using shadow declaration contained in the shadow decl
+ /// The next using shadow declaration contained in the shadow decl
/// chain of the using declaration which introduced this decl.
UsingShadowDecl *getNextUsingShadowDecl() const {
return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow);
@@ -3150,7 +3232,7 @@ public:
}
};
-/// \brief Represents a shadow constructor declaration introduced into a
+/// Represents a shadow constructor declaration introduced into a
/// class by a C++11 using-declaration that names a constructor.
///
/// For example:
@@ -3161,18 +3243,18 @@ public:
/// };
/// \endcode
class ConstructorUsingShadowDecl final : public UsingShadowDecl {
- /// \brief If this constructor using declaration inherted the constructor
+ /// 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 = nullptr;
- /// \brief If this constructor using declaration inherted the constructor
+ /// 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 = nullptr;
- /// \brief \c true if the constructor ultimately named by this using shadow
+ /// \c true if the constructor ultimately named by this using shadow
/// declaration is within a virtual base class subobject of the class that
/// contains this declaration.
unsigned IsVirtual : 1;
@@ -3224,24 +3306,24 @@ public:
}
//@}
- /// \brief Get the inheriting constructor declaration for the direct base
+ /// Get the inheriting constructor declaration for the direct base
/// class from which this using shadow declaration was inherited, if there is
/// one. This can be different for each redeclaration of the same shadow decl.
ConstructorUsingShadowDecl *getNominatedBaseClassShadowDecl() const {
return NominatedBaseClassShadowDecl;
}
- /// \brief Get the inheriting constructor declaration for the base class
+ /// Get the inheriting constructor declaration for the base class
/// for which we don't have an explicit initializer, if there is one.
ConstructorUsingShadowDecl *getConstructedBaseClassShadowDecl() const {
return ConstructedBaseClassShadowDecl;
}
- /// \brief Get the base class that was named in the using declaration. This
+ /// Get the base class that was named in the using declaration. This
/// can be different for each redeclaration of this same shadow decl.
CXXRecordDecl *getNominatedBaseClass() const;
- /// \brief Get the base class whose constructor or constructor shadow
+ /// Get the base class whose constructor or constructor shadow
/// declaration is passed the constructor arguments.
CXXRecordDecl *getConstructedBaseClass() const {
return cast<CXXRecordDecl>((ConstructedBaseClassShadowDecl
@@ -3250,13 +3332,13 @@ public:
->getDeclContext());
}
- /// \brief Returns \c true if the constructed base class is a virtual base
+ /// Returns \c true if the constructed base class is a virtual base
/// class subobject of this declaration's class.
bool constructsVirtualBase() const {
return IsVirtual;
}
- /// \brief Get the constructor or constructor template in the derived class
+ /// Get the constructor or constructor template in the derived class
/// correspnding to this using shadow declaration, if it has been implicitly
/// declared already.
CXXConstructorDecl *getConstructor() const;
@@ -3266,24 +3348,24 @@ public:
static bool classofKind(Kind K) { return K == ConstructorUsingShadow; }
};
-/// \brief Represents a C++ using-declaration.
+/// Represents a C++ using-declaration.
///
/// For example:
/// \code
/// using someNameSpace::someIdentifier;
/// \endcode
class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> {
- /// \brief The source location of the 'using' keyword itself.
+ /// The source location of the 'using' keyword itself.
SourceLocation UsingLocation;
- /// \brief The nested-name-specifier that precedes the name.
+ /// The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief Provides source/type location info for the declaration name
+ /// Provides source/type location info for the declaration name
/// embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
- /// \brief The first shadow declaration of the shadow decl chain associated
+ /// The first shadow declaration of the shadow decl chain associated
/// with this using declaration.
///
/// The bool member of the pair store whether this decl has the \c typename
@@ -3304,17 +3386,17 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- /// \brief Return the source location of the 'using' keyword.
+ /// Return the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
- /// \brief Set the source location of the 'using' keyword.
+ /// Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
- /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ /// Retrieve the nested-name-specifier that qualifies the name.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3323,19 +3405,19 @@ public:
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
- /// \brief Return true if it is a C++03 access declaration (no 'using').
+ /// Return true if it is a C++03 access declaration (no 'using').
bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
- /// \brief Return true if the using declaration has 'typename'.
+ /// Return true if the using declaration has 'typename'.
bool hasTypename() const { return FirstUsingShadow.getInt(); }
- /// \brief Sets whether the using declaration has 'typename'.
+ /// Sets whether the using declaration has 'typename'.
void setTypename(bool TN) { FirstUsingShadow.setInt(TN); }
- /// \brief Iterates through the using shadow declarations associated with
+ /// Iterates through the using shadow declarations associated with
/// this using declaration.
class shadow_iterator {
- /// \brief The current using shadow declaration.
+ /// The current using shadow declaration.
UsingShadowDecl *Current = nullptr;
public:
@@ -3382,7 +3464,7 @@ public:
shadow_iterator shadow_end() const { return shadow_iterator(); }
- /// \brief Return the number of shadowed declarations associated with this
+ /// Return the number of shadowed declarations associated with this
/// using declaration.
unsigned shadow_size() const {
return std::distance(shadow_begin(), shadow_end());
@@ -3480,7 +3562,7 @@ public:
static bool classofKind(Kind K) { return K == UsingPack; }
};
-/// \brief Represents a dependent using declaration which was not marked with
+/// Represents a dependent using declaration which was not marked with
/// \c typename.
///
/// Unlike non-dependent using declarations, these *only* bring through
@@ -3493,16 +3575,16 @@ public:
/// \endcode
class UnresolvedUsingValueDecl : public ValueDecl,
public Mergeable<UnresolvedUsingValueDecl> {
- /// \brief The source location of the 'using' keyword
+ /// The source location of the 'using' keyword
SourceLocation UsingLocation;
- /// \brief If this is a pack expansion, the location of the '...'.
+ /// If this is a pack expansion, the location of the '...'.
SourceLocation EllipsisLoc;
- /// \brief The nested-name-specifier that precedes the name.
+ /// The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief Provides source/type location info for the declaration name
+ /// Provides source/type location info for the declaration name
/// embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
@@ -3522,20 +3604,20 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- /// \brief Returns the source location of the 'using' keyword.
+ /// Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
- /// \brief Set the source location of the 'using' keyword.
+ /// Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
- /// \brief Return true if it is a C++03 access declaration (no 'using').
+ /// Return true if it is a C++03 access declaration (no 'using').
bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
- /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ /// Retrieve the nested-name-specifier that qualifies the name.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3544,12 +3626,12 @@ public:
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
- /// \brief Determine whether this is a pack expansion.
+ /// Determine whether this is a pack expansion.
bool isPackExpansion() const {
return EllipsisLoc.isValid();
}
- /// \brief Get the location of the ellipsis if this is a pack expansion.
+ /// Get the location of the ellipsis if this is a pack expansion.
SourceLocation getEllipsisLoc() const {
return EllipsisLoc;
}
@@ -3576,7 +3658,7 @@ public:
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
};
-/// \brief Represents a dependent using declaration which was marked with
+/// Represents a dependent using declaration which was marked with
/// \c typename.
///
/// \code
@@ -3592,13 +3674,13 @@ class UnresolvedUsingTypenameDecl
public Mergeable<UnresolvedUsingTypenameDecl> {
friend class ASTDeclReader;
- /// \brief The source location of the 'typename' keyword
+ /// The source location of the 'typename' keyword
SourceLocation TypenameLocation;
- /// \brief If this is a pack expansion, the location of the '...'.
+ /// If this is a pack expansion, the location of the '...'.
SourceLocation EllipsisLoc;
- /// \brief The nested-name-specifier that precedes the name.
+ /// The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
@@ -3615,17 +3697,17 @@ class UnresolvedUsingTypenameDecl
void anchor() override;
public:
- /// \brief Returns the source location of the 'using' keyword.
+ /// Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return getLocStart(); }
- /// \brief Returns the source location of the 'typename' keyword.
+ /// Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
- /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ /// Retrieve the nested-name-specifier that qualifies the name.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3634,12 +3716,12 @@ public:
return DeclarationNameInfo(getDeclName(), getLocation());
}
- /// \brief Determine whether this is a pack expansion.
+ /// Determine whether this is a pack expansion.
bool isPackExpansion() const {
return EllipsisLoc.isValid();
}
- /// \brief Get the location of the ellipsis if this is a pack expansion.
+ /// Get the location of the ellipsis if this is a pack expansion.
SourceLocation getEllipsisLoc() const {
return EllipsisLoc;
}
@@ -3665,7 +3747,7 @@ public:
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
};
-/// \brief Represents a C++11 static_assert declaration.
+/// Represents a C++11 static_assert declaration.
class StaticAssertDecl : public Decl {
llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed;
StringLiteral *Message;
@@ -3688,7 +3770,7 @@ public:
Expr *AssertExpr, StringLiteral *Message,
SourceLocation RParenLoc, bool Failed);
static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); }
const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); }
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
index 6545f70f70b5..ccd82d2cf0d2 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
@@ -30,17 +30,17 @@ namespace clang {
class DependentDiagnostic;
-/// \brief An array of decls optimized for the common case of only containing
+/// 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.
+ /// When in vector form, this is what the Data pointer points to.
using DeclsTy = SmallVector<NamedDecl *, 4>;
- /// \brief A collection of declarations, with a flag to indicate if we have
+ /// A collection of declarations, with a flag to indicate if we have
/// further external declarations.
using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>;
- /// \brief The stored data, which will be either a pointer to a NamedDecl,
+ /// 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;
@@ -122,7 +122,7 @@ public:
== Vec.end() && "list still contains decl");
}
- /// \brief Remove any declarations which were imported from an external
+ /// Remove any declarations which were imported from an external
/// AST source.
void removeExternalDecls() {
if (isNull()) {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
index 5d1c6b86fe11..a8de8ed16840 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
@@ -148,13 +148,13 @@ public:
/// Retrieves the source range for the friend declaration.
SourceRange getSourceRange() const override LLVM_READONLY {
if (NamedDecl *ND = getFriendDecl()) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return FD->getSourceRange();
- if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
return FTD->getSourceRange();
- if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
+ if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
return CTD->getSourceRange();
- if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) {
+ if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) {
if (DD->getOuterLocStart() != DD->getInnerLocStart())
return DD->getSourceRange();
}
@@ -254,7 +254,7 @@ inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
FD->NextFriend = data().FirstFriend;
data().FirstFriend = FD;
}
-
+
} // namespace clang
#endif // LLVM_CLANG_AST_DECLFRIEND_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
index 2fff05582563..9627f440d406 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
@@ -54,7 +54,7 @@ public:
++It;
} while (It != End &&
It->first == DeclarationName::getUsingDirectiveName());
-
+
return *this;
}
@@ -86,16 +86,11 @@ inline DeclContext::lookups_range DeclContext::lookups() const {
return lookups_range(all_lookups_iterator(), all_lookups_iterator());
}
-inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
- return lookups().begin();
-}
-
-inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
- return lookups().end();
-}
-
-inline DeclContext::lookups_range DeclContext::noload_lookups() const {
+inline DeclContext::lookups_range
+DeclContext::noload_lookups(bool PreserveInternalState) const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
+ if (!PreserveInternalState)
+ Primary->loadLazyLocalLexicalLookups();
if (StoredDeclsMap *Map = Primary->getLookupPtr())
return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
all_lookups_iterator(Map->end(), Map->end()));
@@ -105,16 +100,6 @@ inline DeclContext::lookups_range DeclContext::noload_lookups() const {
return lookups_range(all_lookups_iterator(), all_lookups_iterator());
}
-inline
-DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const {
- return noload_lookups().begin();
-}
-
-inline
-DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const {
- return noload_lookups().end();
-}
-
} // namespace clang
#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 cef7d935370a..c1cc726e3152 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
@@ -97,7 +97,7 @@ public:
}
};
-/// \brief A list of Objective-C protocols, along with the source
+/// A list of Objective-C protocols, along with the source
/// locations at which they were referenced.
class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
SourceLocation *Locations = nullptr;
@@ -156,10 +156,10 @@ private:
// Method has a definition.
unsigned IsDefined : 1;
- /// \brief Method redeclaration in the same interface.
+ /// Method redeclaration in the same interface.
unsigned IsRedeclaration : 1;
- /// \brief Is redeclared in the same interface.
+ /// Is redeclared in the same interface.
mutable unsigned HasRedeclaration : 1;
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
@@ -170,14 +170,14 @@ private:
/// in, inout, etc.
unsigned objcDeclQualifier : 7;
- /// \brief Indicates whether this method has a related result type.
+ /// Indicates whether this method has a related result type.
unsigned RelatedResultType : 1;
- /// \brief Whether the locations of the selector identifiers are in a
+ /// Whether the locations of the selector identifiers are in a
/// "standard" position, a enum SelectorLocationsKind.
unsigned SelLocsKind : 2;
- /// \brief Whether this method overrides any other in the class hierarchy.
+ /// Whether this method overrides any other in the class hierarchy.
///
/// A method is said to override any method in the class's
/// base classes, its protocols, or its categories' protocols, that has
@@ -186,7 +186,7 @@ private:
/// method in the interface or its categories.
unsigned IsOverriding : 1;
- /// \brief Indicates if the method was a definition but its body was skipped.
+ /// Indicates if the method was a definition but its body was skipped.
unsigned HasSkippedBody : 1;
// Return type of this method.
@@ -195,7 +195,7 @@ private:
// Type source information for the return type.
TypeSourceInfo *ReturnTInfo;
- /// \brief Array of ParmVarDecls for the formal parameters of this method
+ /// Array of ParmVarDecls for the formal parameters of this method
/// and optionally followed by selector locations.
void *ParamsAndSelLocs = nullptr;
unsigned NumParams = 0;
@@ -241,7 +241,7 @@ private:
return getSelLocsKind() != SelLoc_NonStandard;
}
- /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
@@ -250,7 +250,7 @@ private:
return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
}
- /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
ParmVarDecl **getParams() {
return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
@@ -259,7 +259,7 @@ private:
return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
}
- /// \brief Get the number of stored selector identifiers locations.
+ /// Get the number of stored selector identifiers locations.
/// No locations will be stored if HasStandardSelLocs is true.
unsigned getNumStoredSelLocs() const {
if (hasStandardSelLocs())
@@ -271,7 +271,7 @@ private:
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs);
- /// \brief A definition will return its interface declaration.
+ /// A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
ObjCMethodDecl *getNextRedeclarationImpl() override;
@@ -301,18 +301,18 @@ public:
}
void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
- /// \brief Determine whether this method has a result type that is related
+ /// Determine whether this method has a result type that is related
/// to the message receiver's type.
bool hasRelatedResultType() const { return RelatedResultType; }
- /// \brief Note whether this method has a related result type.
+ /// Note whether this method has a related result type.
void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
- /// \brief True if this is a method redeclaration in the same interface.
+ /// True if this is a method redeclaration in the same interface.
bool isRedeclaration() const { return IsRedeclaration; }
void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
- /// \brief Returns the location where the declarator ends. It will be
+ /// Returns the location where the declarator ends. It will be
/// the location of ';' for a method declaration and the location of '{'
/// for a method definition.
SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
@@ -362,7 +362,7 @@ public:
void setReturnType(QualType T) { MethodDeclType = T; }
SourceRange getReturnTypeSourceRange() const;
- /// \brief Determine the type of an expression that sends a message to this
+ /// Determine the type of an expression that sends a message to this
/// function. This replaces the type parameters with the types they would
/// get if the receiver was parameterless (e.g. it may replace the type
/// parameter with 'id').
@@ -407,7 +407,7 @@ public:
NumParams);
}
- /// \brief Sets the method's parameters and selector source locations.
+ /// Sets the method's parameters and selector source locations.
/// If the method is implicit (not coming from source) \p SelLocs is
/// ignored.
void setMethodParams(ASTContext &C,
@@ -462,7 +462,7 @@ public:
bool isDefined() const { return IsDefined; }
void setDefined(bool isDefined) { IsDefined = isDefined; }
- /// \brief Whether this method overrides any other in the class hierarchy.
+ /// Whether this method overrides any other in the class hierarchy.
///
/// A method is said to override any method in the class's
/// base classes, its protocols, or its categories' protocols, that has
@@ -472,7 +472,7 @@ public:
bool isOverriding() const { return IsOverriding; }
void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }
- /// \brief Return overridden methods for the given \p Method.
+ /// Return overridden methods for the given \p Method.
///
/// An ObjC method is considered to override any method in the class's
/// base classes (and base's categories), its protocols, or its categories'
@@ -483,11 +483,11 @@ public:
void getOverriddenMethods(
SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
- /// \brief True if the method was a definition but its body was skipped.
+ /// True if the method was a definition but its body was skipped.
bool hasSkippedBody() const { return HasSkippedBody; }
void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
- /// \brief Returns the property associated with this method's selector.
+ /// Returns the property associated with this method's selector.
///
/// Note that even if this particular method is not marked as a property
/// accessor, it is still possible for it to match a property declared in a
@@ -520,10 +520,10 @@ public:
bool isDesignatedInitializerForTheInterface(
const ObjCMethodDecl **InitMethod = nullptr) const;
- /// \brief Determine whether this method has a body.
+ /// Determine whether this method has a body.
bool hasBody() const override { return Body.isValid(); }
- /// \brief Retrieve the body of this method, if it has one.
+ /// Retrieve the body of this method, if it has one.
Stmt *getBody() const override;
void setLazyBody(uint64_t Offset) { Body = Offset; }
@@ -531,7 +531,7 @@ public:
CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
void setBody(Stmt *B) { Body = B; }
- /// \brief Returns whether this specific method is a definition.
+ /// Returns whether this specific method is a definition.
bool isThisDeclarationADefinition() const { return hasBody(); }
// Implement isa/cast/dyncast/etc.
@@ -587,7 +587,7 @@ class ObjCTypeParamDecl : public TypedefNameDecl {
/// explicitly specified.
SourceLocation ColonLoc;
- ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance, SourceLocation varianceLoc,
unsigned index,
SourceLocation nameLoc, IdentifierInfo *name,
@@ -659,7 +659,7 @@ class ObjCTypeParamList final
unsigned End;
};
- union {
+ union {
/// Location of the left and right angle brackets.
PODSourceRange Brackets;
@@ -737,7 +737,7 @@ enum class ObjCPropertyQueryKind : uint8_t {
OBJC_PR_query_class
};
-/// \brief Represents one property declaration in an Objective-C interface.
+/// Represents one property declaration in an Objective-C interface.
///
/// For example:
/// \code{.mm}
@@ -770,7 +770,7 @@ public:
};
enum {
- /// \brief Number of bits fitting all the property attributes.
+ /// Number of bits fitting all the property attributes.
NumPropertyAttrsBits = 15
};
@@ -1123,7 +1123,7 @@ public:
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.
/// Note, the superclass's properties are not included in the list.
@@ -1163,7 +1163,7 @@ public:
}
};
-/// \brief Represents an ObjC class declaration.
+/// Represents an ObjC class declaration.
///
/// For example:
///
@@ -1195,22 +1195,22 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
mutable const Type *TypeForDecl = nullptr;
-
+
struct DefinitionData {
- /// \brief The definition of this class, for quick access from any
+ /// The definition of this class, for quick access from any
/// declaration.
ObjCInterfaceDecl *Definition = nullptr;
-
+
/// When non-null, this is always an ObjCObjectType.
TypeSourceInfo *SuperClassTInfo = nullptr;
-
+
/// Protocols referenced in the \@interface declaration
ObjCProtocolList ReferencedProtocols;
/// Protocols reference in both the \@interface and class extensions.
ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
- /// \brief List of categories and class extensions defined for this class.
+ /// List of categories and class extensions defined for this class.
///
/// Categories are stored as a linked list in the AST, since the categories
/// and class extensions come long after the initial interface declaration,
@@ -1221,11 +1221,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// extensions and implementation. This list is built lazily.
ObjCIvarDecl *IvarList = nullptr;
- /// \brief Indicates that the contents of this Objective-C class will be
+ /// Indicates that the contents of this Objective-C class will be
/// completed by the external AST source when required.
mutable unsigned ExternallyCompleted : 1;
- /// \brief Indicates that the ivar cache does not yet include ivars
+ /// Indicates that the ivar cache does not yet include ivars
/// declared in the implementation.
mutable unsigned IvarListMissingImplementation : 1;
@@ -1247,11 +1247,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// One of the \c InheritedDesignatedInitializersState enumeratos.
mutable unsigned InheritedDesignatedInitializers : 2;
-
- /// \brief The location of the last location in this declaration, before
- /// the properties/methods. For example, this will be the '>', '}', or
- /// identifier,
- SourceLocation EndLoc;
+
+ /// The location of the last location in this declaration, before
+ /// the properties/methods. For example, this will be the '>', '}', or
+ /// identifier,
+ SourceLocation EndLoc;
DefinitionData()
: ExternallyCompleted(false), IvarListMissingImplementation(true),
@@ -1262,7 +1262,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// The type parameters associated with this class, if any.
ObjCTypeParamList *TypeParamList = nullptr;
- /// \brief Contains a pointer to the data associated with this class,
+ /// Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined.
///
/// The bit indicates when we don't need to check for out-of-date
@@ -1283,9 +1283,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
return *Data.getPointer();
}
- /// \brief Allocate the definition data for this class.
+ /// Allocate the definition data for this class.
void allocateDefinitionData();
-
+
using redeclarable_base = Redeclarable<ObjCInterfaceDecl>;
ObjCInterfaceDecl *getNextRedeclarationImpl() override {
@@ -1334,11 +1334,11 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY {
if (isThisDeclarationADefinition())
return ObjCContainerDecl::getSourceRange();
-
+
return SourceRange(getAtStartLoc(), getLocation());
}
- /// \brief Indicate that this Objective-C class is complete, but that
+ /// Indicate that this Objective-C class is complete, but that
/// the external AST source will be responsible for filling in its contents
/// when a complete class is required.
void setExternallyCompleted();
@@ -1390,7 +1390,7 @@ public:
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return protocol_iterator();
-
+
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -1453,7 +1453,7 @@ public:
if (data().ExternallyCompleted)
LoadExternalDefinition();
- return data().AllReferencedProtocols.empty()
+ return data().AllReferencedProtocols.empty()
? protocol_begin()
: data().AllReferencedProtocols.begin();
}
@@ -1462,11 +1462,11 @@ public:
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return all_protocol_iterator();
-
+
if (data().ExternallyCompleted)
LoadExternalDefinition();
- return data().AllReferencedProtocols.empty()
+ return data().AllReferencedProtocols.empty()
? protocol_end()
: data().AllReferencedProtocols.end();
}
@@ -1476,17 +1476,17 @@ public:
ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
- ivar_iterator ivar_begin() const {
+ ivar_iterator ivar_begin() const {
if (const ObjCInterfaceDecl *Def = getDefinition())
- return ivar_iterator(Def->decls_begin());
-
+ return ivar_iterator(Def->decls_begin());
+
// FIXME: Should make sure no callers ever do this.
return ivar_iterator();
}
- ivar_iterator ivar_end() const {
+ ivar_iterator ivar_end() const {
if (const ObjCInterfaceDecl *Def = getDefinition())
- return ivar_iterator(Def->decls_end());
+ return ivar_iterator(Def->decls_end());
// FIXME: Should make sure no callers ever do this.
return ivar_iterator();
@@ -1544,13 +1544,13 @@ public:
isDesignatedInitializer(Selector Sel,
const ObjCMethodDecl **InitMethod = nullptr) const;
- /// \brief Determine whether this particular declaration of this class is
+ /// Determine whether this particular declaration of this class is
/// actually also a definition.
- bool isThisDeclarationADefinition() const {
+ bool isThisDeclarationADefinition() const {
return getDefinition() == this;
}
-
- /// \brief Determine whether this class has been defined.
+
+ /// Determine whether this class has been defined.
bool hasDefinition() const {
// If the name of this class is out-of-date, bring it up-to-date, which
// might bring in a definition.
@@ -1561,25 +1561,25 @@ public:
return Data.getPointer();
}
-
- /// \brief Retrieve the definition of this class, or NULL if this class
- /// has been forward-declared (with \@class) but not yet defined (with
+
+ /// Retrieve the definition of this class, or NULL if this class
+ /// has been forward-declared (with \@class) but not yet defined (with
/// \@interface).
ObjCInterfaceDecl *getDefinition() {
return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
- /// \brief Retrieve the definition of this class, or NULL if this class
- /// has been forward-declared (with \@class) but not yet defined (with
+ /// Retrieve the definition of this class, or NULL if this class
+ /// has been forward-declared (with \@class) but not yet defined (with
/// \@interface).
const ObjCInterfaceDecl *getDefinition() const {
return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
- /// \brief Starts the definition of this Objective-C class, taking it from
+ /// Starts the definition of this Objective-C class, taking it from
/// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
-
+
/// Retrieve the superclass type.
const ObjCObjectType *getSuperClassType() const {
if (TypeSourceInfo *TInfo = getSuperClassTInfo())
@@ -1593,7 +1593,7 @@ public:
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
-
+
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -1604,11 +1604,11 @@ public:
// does not include any type arguments that apply to the superclass.
ObjCInterfaceDecl *getSuperClass() const;
- void setSuperClass(TypeSourceInfo *superClass) {
+ void setSuperClass(TypeSourceInfo *superClass) {
data().SuperClassTInfo = superClass;
}
- /// \brief Iterator that walks over the list of categories, filtering out
+ /// Iterator that walks over the list of categories, filtering out
/// those that do not meet specific criteria.
///
/// This class template is used for the various permutations of category
@@ -1618,7 +1618,7 @@ public:
ObjCCategoryDecl *Current = nullptr;
void findAcceptableCategory();
-
+
public:
using value_type = ObjCCategoryDecl *;
using reference = value_type;
@@ -1655,13 +1655,13 @@ public:
};
private:
- /// \brief Test whether the given category is visible.
+ /// Test whether the given category is visible.
///
/// Used in the \c visible_categories_iterator.
static bool isVisibleCategory(ObjCCategoryDecl *Cat);
-
+
public:
- /// \brief Iterator that walks over the list of categories and extensions
+ /// Iterator that walks over the list of categories and extensions
/// that are visible, i.e., not hidden in a non-imported submodule.
using visible_categories_iterator =
filtered_category_iterator<isVisibleCategory>;
@@ -1674,30 +1674,30 @@ public:
visible_categories_end());
}
- /// \brief Retrieve an iterator to the beginning of the visible-categories
+ /// Retrieve an iterator to the beginning of the visible-categories
/// list.
visible_categories_iterator visible_categories_begin() const {
return visible_categories_iterator(getCategoryListRaw());
}
- /// \brief Retrieve an iterator to the end of the visible-categories list.
+ /// Retrieve an iterator to the end of the visible-categories list.
visible_categories_iterator visible_categories_end() const {
return visible_categories_iterator();
}
- /// \brief Determine whether the visible-categories list is empty.
+ /// Determine whether the visible-categories list is empty.
bool visible_categories_empty() const {
return visible_categories_begin() == visible_categories_end();
}
private:
- /// \brief Test whether the given category... is a category.
+ /// Test whether the given category... is a category.
///
/// Used in the \c known_categories_iterator.
static bool isKnownCategory(ObjCCategoryDecl *) { return true; }
public:
- /// \brief Iterator that walks over all of the known categories and
+ /// Iterator that walks over all of the known categories and
/// extensions, including those that are hidden.
using known_categories_iterator = filtered_category_iterator<isKnownCategory>;
using known_categories_range =
@@ -1708,30 +1708,30 @@ public:
known_categories_end());
}
- /// \brief Retrieve an iterator to the beginning of the known-categories
+ /// Retrieve an iterator to the beginning of the known-categories
/// list.
known_categories_iterator known_categories_begin() const {
return known_categories_iterator(getCategoryListRaw());
}
- /// \brief Retrieve an iterator to the end of the known-categories list.
+ /// Retrieve an iterator to the end of the known-categories list.
known_categories_iterator known_categories_end() const {
return known_categories_iterator();
}
- /// \brief Determine whether the known-categories list is empty.
+ /// Determine whether the known-categories list is empty.
bool known_categories_empty() const {
return known_categories_begin() == known_categories_end();
}
private:
- /// \brief Test whether the given category is a visible extension.
+ /// Test whether the given category is a visible extension.
///
/// Used in the \c visible_extensions_iterator.
static bool isVisibleExtension(ObjCCategoryDecl *Cat);
public:
- /// \brief Iterator that walks over all of the visible extensions, skipping
+ /// Iterator that walks over all of the visible extensions, skipping
/// any that are known but hidden.
using visible_extensions_iterator =
filtered_category_iterator<isVisibleExtension>;
@@ -1744,34 +1744,34 @@ public:
visible_extensions_end());
}
- /// \brief Retrieve an iterator to the beginning of the visible-extensions
+ /// Retrieve an iterator to the beginning of the visible-extensions
/// list.
visible_extensions_iterator visible_extensions_begin() const {
return visible_extensions_iterator(getCategoryListRaw());
}
- /// \brief Retrieve an iterator to the end of the visible-extensions list.
+ /// Retrieve an iterator to the end of the visible-extensions list.
visible_extensions_iterator visible_extensions_end() const {
return visible_extensions_iterator();
}
- /// \brief Determine whether the visible-extensions list is empty.
+ /// Determine whether the visible-extensions list is empty.
bool visible_extensions_empty() const {
return visible_extensions_begin() == visible_extensions_end();
}
private:
- /// \brief Test whether the given category is an extension.
+ /// Test whether the given category is an extension.
///
/// Used in the \c known_extensions_iterator.
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.
+ /// Iterator that walks over all of the known extensions.
using known_extensions_iterator =
filtered_category_iterator<isKnownExtension>;
using known_extensions_range =
@@ -1782,36 +1782,36 @@ public:
known_extensions_end());
}
- /// \brief Retrieve an iterator to the beginning of the known-extensions
+ /// Retrieve an iterator to the beginning of the known-extensions
/// list.
known_extensions_iterator known_extensions_begin() const {
return known_extensions_iterator(getCategoryListRaw());
}
-
- /// \brief Retrieve an iterator to the end of the known-extensions list.
+
+ /// Retrieve an iterator to the end of the known-extensions list.
known_extensions_iterator known_extensions_end() const {
return known_extensions_iterator();
}
- /// \brief Determine whether the known-extensions list is empty.
+ /// Determine whether the known-extensions list is empty.
bool known_extensions_empty() const {
return known_extensions_begin() == known_extensions_end();
}
- /// \brief Retrieve the raw pointer to the start of the category/extension
+ /// Retrieve the raw pointer to the start of the category/extension
/// list.
ObjCCategoryDecl* getCategoryListRaw() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
-
+
if (data().ExternallyCompleted)
LoadExternalDefinition();
return data().CategoryList;
}
- /// \brief Set the raw pointer to the start of the category/extension
+ /// Set the raw pointer to the start of the category/extension
/// list.
void setCategoryListRaw(ObjCCategoryDecl *category) {
data().CategoryList = category;
@@ -1831,7 +1831,7 @@ public:
while (I != nullptr) {
if (declaresSameEntity(this, I))
return true;
-
+
I = I->getSuperClass();
}
return false;
@@ -1841,7 +1841,7 @@ public:
/// to be incompatible with __weak references. Returns true if it is.
bool isArcWeakrefUnavailable() const;
- /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
+ /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
/// classes must not be auto-synthesized. Returns class decl. if it must not
/// be; 0, otherwise.
const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;
@@ -1854,7 +1854,7 @@ public:
}
ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
-
+
// Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories.
ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
@@ -1874,7 +1874,7 @@ public:
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
- /// \brief Lookup a method in the classes implementation hierarchy.
+ /// Lookup a method in the classes implementation hierarchy.
ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
bool Instance=true) const;
@@ -1882,7 +1882,7 @@ public:
return lookupPrivateMethod(Sel, false);
}
- /// \brief Lookup a setter or getter in the class hierarchy,
+ /// Lookup a setter or getter in the class hierarchy,
/// including in all categories except for category passed
/// as argument.
ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
@@ -1893,14 +1893,14 @@ public:
true /* followsSuper */,
Cat);
}
-
- SourceLocation getEndOfDefinitionLoc() const {
+
+ SourceLocation getEndOfDefinitionLoc() const {
if (!hasDefinition())
return getLocation();
-
- return data().EndLoc;
+
+ return data().EndLoc;
}
-
+
void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
/// Retrieve the starting location of the superclass.
@@ -1909,7 +1909,7 @@ public:
/// isImplicitInterfaceDecl - check that this is an implicitly declared
/// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
/// declaration without an \@interface declaration.
- bool isImplicitInterfaceDecl() const {
+ bool isImplicitInterfaceDecl() const {
return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
}
@@ -1987,8 +1987,8 @@ public:
bool synthesized=false);
static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- /// \brief Return the class interface that this ivar is logically contained
+
+ /// Return the class interface that this ivar is logically contained
/// in; this is either the interface where the ivar was declared, or the
/// interface the ivar is conceptually a part of in the case of synthesized
/// ivars.
@@ -2027,7 +2027,7 @@ private:
unsigned Synthesized : 1;
};
-/// \brief Represents a field declaration created by an \@defs(...).
+/// Represents a field declaration created by an \@defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -2045,13 +2045,13 @@ public:
QualType T, Expr *BW);
static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
};
-/// \brief Represents an Objective-C protocol declaration.
+/// Represents an Objective-C protocol declaration.
///
/// Objective-C protocols declare a pure abstract type (i.e., no instance
/// variables are permitted). Protocols originally drew inspiration from
@@ -2083,14 +2083,14 @@ public:
class ObjCProtocolDecl : public ObjCContainerDecl,
public Redeclarable<ObjCProtocolDecl> {
struct DefinitionData {
- // \brief The declaration that defines this protocol.
+ // The declaration that defines this protocol.
ObjCProtocolDecl *Definition;
- /// \brief Referenced protocols
- ObjCProtocolList ReferencedProtocols;
+ /// Referenced protocols
+ ObjCProtocolList ReferencedProtocols;
};
- /// \brief Contains a pointer to the data associated with this class,
+ /// Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined.
///
/// The bit indicates when we don't need to check for out-of-date
@@ -2107,7 +2107,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
assert(Data.getPointer() && "Objective-C protocol has no definition!");
return *Data.getPointer();
}
-
+
void allocateDefinitionData();
using redeclarable_base = Redeclarable<ObjCProtocolDecl>;
@@ -2152,15 +2152,15 @@ public:
protocol_iterator protocol_begin() const {
if (!hasDefinition())
return protocol_iterator();
-
+
return data().ReferencedProtocols.begin();
}
- protocol_iterator protocol_end() const {
+ protocol_iterator protocol_end() const {
if (!hasDefinition())
return protocol_iterator();
-
- return data().ReferencedProtocols.end();
+
+ return data().ReferencedProtocols.end();
}
using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
@@ -2173,22 +2173,22 @@ public:
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 {
+ unsigned protocol_size() const {
if (!hasDefinition())
return 0;
-
- return data().ReferencedProtocols.size();
+
+ return data().ReferencedProtocols.size();
}
/// setProtocolList - Set the list of protocols that this interface
@@ -2213,7 +2213,7 @@ public:
return lookupMethod(Sel, false/*isInstance*/);
}
- /// \brief Determine whether this protocol has a definition.
+ /// Determine whether this protocol has a definition.
bool hasDefinition() const {
// If the name of this protocol is out-of-date, bring it up-to-date, which
// might bring in a definition.
@@ -2225,23 +2225,23 @@ public:
return Data.getPointer();
}
- /// \brief Retrieve the definition of this protocol, if any.
+ /// Retrieve the definition of this protocol, if any.
ObjCProtocolDecl *getDefinition() {
return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
- /// \brief Retrieve the definition of this protocol, if any.
+ /// Retrieve the definition of this protocol, if any.
const ObjCProtocolDecl *getDefinition() const {
return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
- /// \brief Determine whether this particular declaration is also the
+ /// Determine whether this particular declaration is also the
/// definition.
bool isThisDeclarationADefinition() const {
return getDefinition() == this;
}
-
- /// \brief Starts the definition of this Objective-C protocol.
+
+ /// Starts the definition of this Objective-C protocol.
void startDefinition();
/// Produce a name to be used for protocol's metadata. It comes either via
@@ -2251,10 +2251,10 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY {
if (isThisDeclarationADefinition())
return ObjCContainerDecl::getSourceRange();
-
+
return SourceRange(getAtStartLoc(), getLocation());
}
-
+
using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator;
@@ -2310,13 +2310,13 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory = nullptr;
- /// \brief The location of the category name in this declaration.
+ /// The location of the category name in this declaration.
SourceLocation CategoryNameLoc;
/// class extension may have private ivars.
SourceLocation IvarLBraceLoc;
SourceLocation IvarRBraceLoc;
-
+
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
@@ -2400,7 +2400,7 @@ public:
ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
- /// \brief Retrieve the pointer to the next stored category (or extension),
+ /// Retrieve the pointer to the next stored category (or extension),
/// which may be hidden.
ObjCCategoryDecl *getNextClassCategoryRaw() const {
return NextClassCategory;
@@ -2431,7 +2431,7 @@ public:
SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
-
+
void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
@@ -2576,9 +2576,9 @@ class ObjCImplementationDecl : public ObjCImplDecl {
/// \@implementation may have private ivars.
SourceLocation IvarLBraceLoc;
SourceLocation IvarRBraceLoc;
-
+
/// Support for ivar initialization.
- /// \brief The arguments used to initialize the ivars
+ /// The arguments used to initialize the ivars
LazyCXXCtorInitializersPtr IvarInitializers;
unsigned NumIvarInitializers = 0;
@@ -2594,7 +2594,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
ObjCInterfaceDecl *superDecl,
SourceLocation nameLoc, SourceLocation atStartLoc,
SourceLocation superLoc = SourceLocation(),
- SourceLocation IvarLBraceLoc=SourceLocation(),
+ SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation())
: ObjCImplDecl(ObjCImplementation, DC, classInterface,
classInterface ? classInterface->getIdentifier()
@@ -2616,7 +2616,7 @@ public:
SourceLocation nameLoc,
SourceLocation atStartLoc,
SourceLocation superLoc = SourceLocation(),
- SourceLocation IvarLBraceLoc=SourceLocation(),
+ SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation());
static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2694,13 +2694,13 @@ public:
return getIdentifier()->getName();
}
- /// @brief Get the name of the class associated with this interface.
+ /// Get the name of the class associated with this interface.
//
// FIXME: Move to StringRef API.
std::string getNameAsString() const {
return getName();
}
-
+
/// Produce a name to be used for class's metadata. It comes either via
/// class's objc_runtime_name attribute or class name.
StringRef getObjCRuntimeNameAsString() const;
@@ -2715,7 +2715,7 @@ public:
SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
-
+
using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
@@ -2760,9 +2760,9 @@ public:
SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl* aliasedClass);
- static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
+ static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
-
+
const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
@@ -2785,7 +2785,7 @@ public:
private:
SourceLocation AtLoc; // location of \@synthesize or \@dynamic
- /// \brief For \@synthesize, the location of the ivar, if it was written in
+ /// For \@synthesize, the location of the ivar, if it was written in
/// the source code.
///
/// \code
@@ -2854,7 +2854,7 @@ public:
this->IvarLoc = IvarLoc;
}
- /// \brief For \@synthesize, returns true if an ivar name was explicitly
+ /// For \@synthesize, returns true if an ivar name was explicitly
/// specified.
///
/// \code
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
index 2a329c3732cb..bec3acffc433 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines OpenMP nodes for declarative directives.
+/// This file defines OpenMP nodes for declarative directives.
///
//===----------------------------------------------------------------------===//
@@ -24,7 +24,7 @@
namespace clang {
-/// \brief This represents '#pragma omp threadprivate ...' directive.
+/// This represents '#pragma omp threadprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are threadprivate:
///
/// \code
@@ -89,7 +89,7 @@ public:
static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
};
-/// \brief This represents '#pragma omp declare reduction ...' directive.
+/// This represents '#pragma omp declare reduction ...' directive.
/// For example, in the following, declared reduction 'foo' for types 'int' and
/// 'float':
///
@@ -109,14 +109,14 @@ public:
private:
friend class ASTDeclReader;
- /// \brief Combiner for declare reduction construct.
+ /// Combiner for declare reduction construct.
Expr *Combiner;
- /// \brief Initializer for declare reduction construct.
+ /// 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
+ /// 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.
LazyDeclPtr PrevDeclInScope;
@@ -135,33 +135,33 @@ private:
}
public:
- /// \brief Create declare reduction node.
+ /// Create declare reduction node.
static OMPDeclareReductionDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
- /// \brief Create deserialized declare reduction node.
+ /// Create deserialized declare reduction node.
static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
- /// \brief Get combiner expression of the declare reduction construct.
+ /// Get combiner expression of the declare reduction construct.
Expr *getCombiner() { return Combiner; }
const Expr *getCombiner() const { return Combiner; }
- /// \brief Set combiner expression for the declare reduction construct.
+ /// Set combiner expression for the declare reduction construct.
void setCombiner(Expr *E) { Combiner = E; }
- /// \brief Get initializer expression (if specified) of the declare reduction
+ /// Get initializer expression (if specified) of the declare reduction
/// 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.
+ /// Set initializer expression for the declare reduction construct.
void setInitializer(Expr *E, InitKind IK) {
Initializer = E;
InitializerKind = IK;
}
- /// \brief Get reference to previous declare reduction construct in the same
+ /// Get reference to previous declare reduction construct in the same
/// scope with the same name.
OMPDeclareReductionDecl *getPrevDeclInScope();
const OMPDeclareReductionDecl *getPrevDeclInScope() const;
@@ -189,9 +189,10 @@ class OMPCapturedExprDecl final : public VarDecl {
void anchor() override;
OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
- QualType Type, SourceLocation StartLoc)
- : VarDecl(OMPCapturedExpr, C, DC, StartLoc, SourceLocation(), Id, Type,
- nullptr, SC_None) {
+ QualType Type, TypeSourceInfo *TInfo,
+ SourceLocation StartLoc)
+ : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo,
+ SC_None) {
setImplicit();
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
index 7842d7097174..e0ea7cb8b1b8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the C++ template declaration subclasses.
+/// Defines the C++ template declaration subclasses.
//
//===----------------------------------------------------------------------===//
@@ -56,14 +56,14 @@ class UnresolvedSetImpl;
class VarTemplateDecl;
class VarTemplatePartialSpecializationDecl;
-/// \brief Stores a template parameter of any kind.
+/// Stores a template parameter of any kind.
using TemplateParameter =
llvm::PointerUnion3<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *,
TemplateTemplateParmDecl *>;
NamedDecl *getAsNamedDecl(TemplateParameter P);
-/// \brief Stores a list of template parameters for a TemplateDecl and its
+/// Stores a list of template parameters for a TemplateDecl and its
/// derived classes.
class TemplateParameterList final
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
@@ -110,10 +110,10 @@ public:
SourceLocation RAngleLoc,
Expr *RequiresClause);
- /// \brief Iterates through the template parameters in this list.
+ /// Iterates through the template parameters in this list.
using iterator = NamedDecl **;
- /// \brief Iterates through the template parameters in this list.
+ /// Iterates through the template parameters in this list.
using const_iterator = NamedDecl * const *;
iterator begin() { return getTrailingObjects<NamedDecl *>(); }
@@ -139,32 +139,32 @@ public:
return begin()[Idx];
}
- /// \brief Returns the minimum number of arguments needed to form a
+ /// Returns the minimum number of arguments needed to form a
/// template specialization.
///
/// This may be fewer than the number of template parameters, if some of
/// the parameters have default arguments or if there is a parameter pack.
unsigned getMinRequiredArguments() const;
- /// \brief Get the depth of this template parameter list in the set of
+ /// Get the depth of this template parameter list in the set of
/// template parameter lists.
///
/// The first template parameter list in a declaration will have depth 0,
/// the second template parameter list will have depth 1, etc.
unsigned getDepth() const;
- /// \brief Determine whether this template parameter list contains an
+ /// Determine whether this template parameter list contains an
/// unexpanded parameter pack.
bool containsUnexpandedParameterPack() const {
return ContainsUnexpandedParameterPack;
}
- /// \brief The constraint-expression of the associated requires-clause.
+ /// The constraint-expression of the associated requires-clause.
Expr *getRequiresClause() {
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
}
- /// \brief The constraint-expression of the associated requires-clause.
+ /// The constraint-expression of the associated requires-clause.
const Expr *getRequiresClause() const {
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
}
@@ -182,7 +182,7 @@ public:
using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner;
};
-/// \brief Stores a list of template parameters and the associated
+/// Stores a list of template parameters and the associated
/// requires-clause (if any) for a TemplateDecl and its derived classes.
/// Suitable for creating on the stack.
template <size_t N, bool HasRequiresClause>
@@ -206,13 +206,13 @@ public:
TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {}
};
-/// \brief A template argument list.
+/// A template argument list.
class TemplateArgumentList final
: private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
- /// \brief The template argument list.
+ /// The template argument list.
const TemplateArgument *Arguments;
- /// \brief The number of template arguments in this template
+ /// The number of template arguments in this template
/// argument list.
unsigned NumArguments;
@@ -226,23 +226,23 @@ public:
TemplateArgumentList(const TemplateArgumentList &) = delete;
TemplateArgumentList &operator=(const TemplateArgumentList &) = delete;
- /// \brief Type used to indicate that the template argument list itself is a
+ /// Type used to indicate that the template argument list itself is a
/// stack object. It does not own its template arguments.
enum OnStackType { OnStack };
- /// \brief Create a new template argument list that copies the given set of
+ /// Create a new template argument list that copies the given set of
/// template arguments.
static TemplateArgumentList *CreateCopy(ASTContext &Context,
ArrayRef<TemplateArgument> Args);
- /// \brief Construct a new, temporary template argument list on the stack.
+ /// Construct a new, temporary template argument list on the stack.
///
/// The template argument list does not own the template arguments
/// provided.
explicit TemplateArgumentList(OnStackType, ArrayRef<TemplateArgument> Args)
: Arguments(Args.data()), NumArguments(Args.size()) {}
- /// \brief Produces a shallow copy of the given template argument list.
+ /// Produces a shallow copy of the given template argument list.
///
/// This operation assumes that the input argument list outlives it.
/// This takes the list as a pointer to avoid looking like a copy
@@ -251,25 +251,25 @@ public:
explicit TemplateArgumentList(const TemplateArgumentList *Other)
: Arguments(Other->data()), NumArguments(Other->size()) {}
- /// \brief Retrieve the template argument at a given index.
+ /// Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
assert(Idx < NumArguments && "Invalid template argument index");
return data()[Idx];
}
- /// \brief Retrieve the template argument at a given index.
+ /// Retrieve the template argument at a given index.
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
- /// \brief Produce this as an array ref.
+ /// Produce this as an array ref.
ArrayRef<TemplateArgument> asArray() const {
return llvm::makeArrayRef(data(), size());
}
- /// \brief Retrieve the number of template arguments in this
+ /// Retrieve the number of template arguments in this
/// template argument list.
unsigned size() const { return NumArguments; }
- /// \brief Retrieve a pointer to the template argument list.
+ /// Retrieve a pointer to the template argument list.
const TemplateArgument *data() const { return Arguments; }
};
@@ -299,7 +299,7 @@ class DefaultArgStorage {
static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) {
const DefaultArgStorage &Storage = Parm->getDefaultArgStorage();
- if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>())
+ if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl *>())
Parm = Prev;
assert(!Parm->getDefaultArgStorage()
.ValueOrInherited.template is<ParmDecl *>() &&
@@ -321,9 +321,9 @@ public:
/// default argument is visible.
ArgType get() const {
const DefaultArgStorage *Storage = this;
- if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>())
+ if (const auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl *>())
Storage = &Prev->getDefaultArgStorage();
- if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>())
+ if (const auto *C = Storage->ValueOrInherited.template dyn_cast<Chain *>())
return C->Value;
return Storage->ValueOrInherited.template get<ArgType>();
}
@@ -331,9 +331,9 @@ public:
/// Get the parameter from which we inherit the default argument, if any.
/// This is the parameter on which the default argument was actually written.
const ParmDecl *getInheritedFrom() const {
- if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>())
+ if (const auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>())
return D;
- if (auto *C = ValueOrInherited.template dyn_cast<Chain*>())
+ if (const auto *C = ValueOrInherited.template dyn_cast<Chain *>())
return C->PrevDeclWithDefaultArg;
return nullptr;
}
@@ -365,7 +365,7 @@ public:
// Kinds of Templates
//===----------------------------------------------------------------------===//
-/// \brief Stores the template parameter list and associated constraints for
+/// Stores the template parameter list and associated constraints for
/// \c TemplateDecl objects that track associated constraints.
class ConstrainedTemplateDeclInfo {
friend TemplateDecl;
@@ -391,7 +391,7 @@ protected:
};
-/// \brief The base class of all kinds of template declarations (e.g.,
+/// The base class of all kinds of template declarations (e.g.,
/// class, function, etc.).
///
/// The TemplateDecl class stores the list of template parameters and a
@@ -443,7 +443,7 @@ public:
}
Expr *getAssociatedConstraints() const {
- const TemplateDecl *const C = cast<TemplateDecl>(getCanonicalDecl());
+ const auto *const C = cast<TemplateDecl>(getCanonicalDecl());
const auto *const CTDI =
C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
@@ -466,7 +466,8 @@ public:
protected:
NamedDecl *TemplatedDecl;
- /// \brief The template parameter list and optional requires-clause
+
+ /// The template parameter list and optional requires-clause
/// associated with this declaration; alternatively, a
/// \c ConstrainedTemplateDeclInfo if the associated constraints of the
/// template are being tracked by this particular declaration.
@@ -491,7 +492,7 @@ protected:
}
public:
- /// \brief Initialize the underlying templated declaration and
+ /// Initialize the underlying templated declaration and
/// template parameters.
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
assert(!TemplatedDecl && "TemplatedDecl already set!");
@@ -501,7 +502,7 @@ public:
}
};
-/// \brief Provides information about a function template specialization,
+/// Provides information about a function template specialization,
/// which is a FunctionDecl that has been explicitly specialization or
/// instantiated from a function template.
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
@@ -524,31 +525,31 @@ public:
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation POI);
- /// \brief The function template specialization that this structure
+ /// The function template specialization that this structure
/// describes.
FunctionDecl *Function;
- /// \brief The function template from which this function template
+ /// The function template from which this function template
/// specialization was generated.
///
/// The two bits contain the top 4 values of TemplateSpecializationKind.
llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
- /// \brief The template arguments used to produce the function template
+ /// The template arguments used to produce the function template
/// specialization from the function template.
const TemplateArgumentList *TemplateArguments;
- /// \brief The template arguments as written in the sources, if provided.
+ /// The template arguments as written in the sources, if provided.
const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
- /// \brief The point at which this function template specialization was
+ /// The point at which this function template specialization was
/// first instantiated.
SourceLocation PointOfInstantiation;
- /// \brief Retrieve the template from which this function was specialized.
+ /// Retrieve the template from which this function was specialized.
FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
- /// \brief Determine what kind of template specialization this is.
+ /// Determine what kind of template specialization this is.
TemplateSpecializationKind getTemplateSpecializationKind() const {
return (TemplateSpecializationKind)(Template.getInt() + 1);
}
@@ -557,7 +558,7 @@ public:
return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
}
- /// \brief True if this declaration is an explicit specialization,
+ /// True if this declaration is an explicit specialization,
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
@@ -565,14 +566,14 @@ public:
getTemplateSpecializationKind());
}
- /// \brief Set the template specialization kind.
+ /// Set the template specialization kind.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
assert(TSK != TSK_Undeclared &&
"Cannot encode TSK_Undeclared for a function template specialization");
Template.setInt(TSK - 1);
}
- /// \brief Retrieve the first point of instantiation of this function
+ /// Retrieve the first point of instantiation of this function
/// template specialization.
///
/// The point of instantiation may be an invalid source location if this
@@ -581,7 +582,7 @@ public:
return PointOfInstantiation;
}
- /// \brief Set the (first) point of instantiation of this function template
+ /// Set the (first) point of instantiation of this function template
/// specialization.
void setPointOfInstantiation(SourceLocation POI) {
PointOfInstantiation = POI;
@@ -601,7 +602,7 @@ public:
}
};
-/// \brief Provides information a specialization of a member of a class
+/// Provides information a specialization of a member of a class
/// template, which may be a member function, static data member,
/// member class or member enumeration.
class MemberSpecializationInfo {
@@ -621,11 +622,11 @@ public:
"Cannot encode undeclared template specializations for members");
}
- /// \brief Retrieve the member declaration from which this member was
+ /// Retrieve the member declaration from which this member was
/// instantiated.
NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); }
- /// \brief Determine what kind of template specialization this is.
+ /// Determine what kind of template specialization this is.
TemplateSpecializationKind getTemplateSpecializationKind() const {
return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1);
}
@@ -634,27 +635,27 @@ public:
return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
}
- /// \brief Set the template specialization kind.
+ /// Set the template specialization kind.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
assert(TSK != TSK_Undeclared &&
"Cannot encode undeclared template specializations for members");
MemberAndTSK.setInt(TSK - 1);
}
- /// \brief Retrieve the first point of instantiation of this member.
+ /// Retrieve the first point of instantiation of this member.
/// If the point of instantiation is an invalid location, then this member
/// has not yet been instantiated.
SourceLocation getPointOfInstantiation() const {
return PointOfInstantiation;
}
- /// \brief Set the first point of instantiation.
+ /// Set the first point of instantiation.
void setPointOfInstantiation(SourceLocation POI) {
PointOfInstantiation = POI;
}
};
-/// \brief Provides information about a dependent function-template
+/// Provides information about a dependent function-template
/// specialization declaration.
///
/// Since explicit function template specialization and instantiation
@@ -699,25 +700,25 @@ public:
Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs);
- /// \brief Returns the number of function templates that this might
+ /// Returns the number of function templates that this might
/// be a specialization of.
unsigned getNumTemplates() const { return NumTemplates; }
- /// \brief Returns the i'th template candidate.
+ /// Returns the i'th template candidate.
FunctionTemplateDecl *getTemplate(unsigned I) const {
assert(I < getNumTemplates() && "template index out of range");
return getTrailingObjects<FunctionTemplateDecl *>()[I];
}
- /// \brief Returns the explicit template arguments that were given.
+ /// Returns the explicit template arguments that were given.
const TemplateArgumentLoc *getTemplateArgs() const {
return getTrailingObjects<TemplateArgumentLoc>();
}
- /// \brief Returns the number of explicit template arguments that were given.
+ /// Returns the number of explicit template arguments that were given.
unsigned getNumTemplateArgs() const { return NumArgs; }
- /// \brief Returns the nth template argument.
+ /// Returns the nth template argument.
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
assert(I < getNumTemplateArgs() && "template arg index out of range");
return getTemplateArgs()[I];
@@ -733,8 +734,8 @@ public:
};
/// Declaration of a redeclarable template.
-class RedeclarableTemplateDecl : public TemplateDecl,
- public Redeclarable<RedeclarableTemplateDecl>
+class RedeclarableTemplateDecl : public TemplateDecl,
+ public Redeclarable<RedeclarableTemplateDecl>
{
using redeclarable_base = Redeclarable<RedeclarableTemplateDecl>;
@@ -803,7 +804,7 @@ protected:
struct CommonBase {
CommonBase() : InstantiatedFromMember(nullptr, false) {}
- /// \brief The template from which this was most
+ /// The template from which this was most
/// directly instantiated (or null).
///
/// The boolean value indicates whether this template
@@ -811,7 +812,7 @@ protected:
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember;
- /// \brief If non-null, points to an array of specializations (including
+ /// 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
@@ -819,11 +820,11 @@ protected:
uint32_t *LazySpecializations = nullptr;
};
- /// \brief Pointer to the common data shared by all declarations of this
+ /// Pointer to the common data shared by all declarations of this
/// template.
mutable CommonBase *Common = nullptr;
-
- /// \brief Retrieves the "common" pointer shared by all (re-)declarations of
+
+ /// Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory
/// for the common pointer.
CommonBase *getCommonPtr() const;
@@ -849,7 +850,7 @@ public:
friend class ASTReader;
template <class decl_type> friend class RedeclarableTemplate;
- /// \brief Retrieves the canonical declaration of this template.
+ /// Retrieves the canonical declaration of this template.
RedeclarableTemplateDecl *getCanonicalDecl() override {
return getFirstDecl();
}
@@ -857,7 +858,7 @@ public:
return getFirstDecl();
}
- /// \brief Determines whether this template was a specialization of a
+ /// Determines whether this template was a specialization of a
/// member template.
///
/// In the following example, the function template \c X<int>::f and the
@@ -879,18 +880,18 @@ public:
return getCommonPtr()->InstantiatedFromMember.getInt();
}
- /// \brief Note that this member template is a specialization.
+ /// Note that this member template is a specialization.
void setMemberSpecialization() {
assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
getCommonPtr()->InstantiatedFromMember.setInt(true);
}
- /// \brief Retrieve the member template from which this template was
- /// instantiated, or nullptr if this template was not instantiated from a
+ /// Retrieve the member template from which this template was
+ /// instantiated, or nullptr if this template was not instantiated from a
/// member template.
///
- /// A template is instantiated from a member template when the member
+ /// A template is instantiated from a member template when the member
/// template itself is part of a class template (or member thereof). For
/// example, given
///
@@ -968,14 +969,14 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
protected:
friend class FunctionDecl;
- /// \brief Data that is common to all of the declarations of a given
+ /// Data that is common to all of the declarations of a given
/// function template.
struct Common : CommonBase {
- /// \brief The function template specializations for this function
+ /// The function template specializations for this function
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
- /// \brief The set of "injected" template arguments used within this
+ /// The set of "injected" template arguments used within this
/// function template.
///
/// This pointer refers to the template arguments (there are as
@@ -999,12 +1000,12 @@ protected:
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
- /// \brief Retrieve the set of function template specializations of this
+ /// Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
getSpecializations() const;
- /// \brief Add a specialization of this function template.
+ /// Add a specialization of this function template.
///
/// \param InsertPos Insert position in the FoldingSetVector, must have been
/// retrieved by an earlier call to findSpecialization().
@@ -1015,7 +1016,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- /// \brief Load any lazily-loaded specializations from the external source.
+ /// Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// Get the underlying function declaration of the template.
@@ -1029,7 +1030,7 @@ public:
return getTemplatedDecl()->isThisDeclarationADefinition();
}
- /// \brief Return the specialization with the provided arguments if it exists,
+ /// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos);
@@ -1043,7 +1044,7 @@ public:
RedeclarableTemplateDecl::getCanonicalDecl());
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// Retrieve the previous declaration of this function template, or
/// nullptr if no such declaration exists.
FunctionTemplateDecl *getPreviousDecl() {
return cast_or_null<FunctionTemplateDecl>(
@@ -1083,7 +1084,7 @@ public:
return makeSpecIterator(getSpecializations(), true);
}
- /// \brief Retrieve the "injected" template arguments that correspond to the
+ /// Retrieve the "injected" template arguments that correspond to the
/// template parameters of this function template.
///
/// Although the C++ standard has no notion of the "injected" template
@@ -1092,14 +1093,14 @@ public:
/// template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
- /// \brief Create a function template node.
+ /// Create a function template node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl);
- /// \brief Create an empty function template node.
+ /// Create an empty function template node.
static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
// Implement isa/cast/dyncast support
@@ -1111,7 +1112,7 @@ public:
// Kinds of Template Parameters
//===----------------------------------------------------------------------===//
-/// \brief Defines the position of a template parameter within a template
+/// Defines the position of a template parameter within a template
/// parameter list.
///
/// Because template parameter can be listed
@@ -1144,7 +1145,7 @@ public:
unsigned getIndex() const { return Position; }
};
-/// \brief Declaration of a template type parameter.
+/// Declaration of a template type parameter.
///
/// For example, "T" in
/// \code
@@ -1154,13 +1155,13 @@ 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
+ /// Whether this template type parameter was declaration with
/// the 'typename' keyword.
///
/// If false, it was declared with the 'class' keyword.
bool Typename : 1;
- /// \brief The default template argument, if any.
+ /// The default template argument, if any.
using DefArgStorage =
DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>;
DefArgStorage DefaultArgument;
@@ -1177,10 +1178,10 @@ public:
unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack);
- static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
+ static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
unsigned ID);
- /// \brief Whether this template type parameter was declared with
+ /// Whether this template type parameter was declared with
/// the 'typename' keyword.
///
/// If not, it was declared with the 'class' keyword.
@@ -1188,57 +1189,57 @@ public:
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
- /// \brief Determine whether this template parameter has a default
+ /// Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
- /// \brief Retrieve the default argument, if any.
+ /// Retrieve the default argument, if any.
QualType getDefaultArgument() const {
return DefaultArgument.get()->getType();
}
- /// \brief Retrieves the default argument's source information, if any.
+ /// Retrieves the default argument's source information, if any.
TypeSourceInfo *getDefaultArgumentInfo() const {
return DefaultArgument.get();
}
- /// \brief Retrieves the location of the default argument declaration.
+ /// Retrieves the location of the default argument declaration.
SourceLocation getDefaultArgumentLoc() const;
- /// \brief Determines whether the default argument was inherited
+ /// Determines whether the default argument was inherited
/// from a previous declaration of this template.
bool defaultArgumentWasInherited() const {
return DefaultArgument.isInherited();
}
- /// \brief Set the default argument for this template parameter.
+ /// Set the default argument for this template parameter.
void setDefaultArgument(TypeSourceInfo *DefArg) {
DefaultArgument.set(DefArg);
}
- /// \brief Set that this default argument was inherited from another
+ /// Set that this default argument was inherited from another
/// parameter.
void setInheritedDefaultArgument(const ASTContext &C,
TemplateTypeParmDecl *Prev) {
DefaultArgument.setInherited(C, Prev);
}
- /// \brief Removes the default argument of this template parameter.
+ /// Removes the default argument of this template parameter.
void removeDefaultArgument() {
DefaultArgument.clear();
}
- /// \brief Set whether this template type parameter was declared with
+ /// Set whether this template type parameter was declared with
/// the 'typename' or 'class' keyword.
void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
- /// \brief Retrieve the depth of the template parameter.
+ /// Retrieve the depth of the template parameter.
unsigned getDepth() const;
- /// \brief Retrieve the index of the template parameter.
+ /// Retrieve the index of the template parameter.
unsigned getIndex() const;
- /// \brief Returns whether this is a parameter pack.
+ /// Returns whether this is a parameter pack.
bool isParameterPack() const;
SourceRange getSourceRange() const override LLVM_READONLY;
@@ -1261,7 +1262,7 @@ class NonTypeTemplateParmDecl final
friend class ASTDeclReader;
friend TrailingObjects;
- /// \brief The default template argument, if any, and whether or not
+ /// The default template argument, if any, and whether or not
/// it was inherited.
using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>;
DefArgStorage DefaultArgument;
@@ -1269,15 +1270,15 @@ class NonTypeTemplateParmDecl final
// FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
// down here to save memory.
- /// \brief Whether this non-type template parameter is a parameter pack.
+ /// Whether this non-type template parameter is a parameter pack.
bool ParameterPack;
- /// \brief Whether this non-type template parameter is an "expanded"
+ /// 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 = false;
- /// \brief The number of types in an expanded parameter pack.
+ /// The number of types in an expanded parameter pack.
unsigned NumExpandedTypes = 0;
size_t numTrailingObjects(
@@ -1311,12 +1312,12 @@ public:
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos);
- static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
+ static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
- static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
+ static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
unsigned ID,
unsigned NumExpandedTypes);
-
+
using TemplateParmPosition::getDepth;
using TemplateParmPosition::setDepth;
using TemplateParmPosition::getPosition;
@@ -1327,23 +1328,23 @@ public:
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
- /// \brief Determine whether this template parameter has a default
+ /// Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
- /// \brief Retrieve the default argument, if any.
+ /// Retrieve the default argument, if any.
Expr *getDefaultArgument() const { return DefaultArgument.get(); }
- /// \brief Retrieve the location of the default argument, if any.
+ /// Retrieve the location of the default argument, if any.
SourceLocation getDefaultArgumentLoc() const;
- /// \brief Determines whether the default argument was inherited
+ /// Determines whether the default argument was inherited
/// from a previous declaration of this template.
bool defaultArgumentWasInherited() const {
return DefaultArgument.isInherited();
}
- /// \brief Set the default argument for this template parameter, and
+ /// Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); }
@@ -1352,10 +1353,10 @@ public:
DefaultArgument.setInherited(C, Parm);
}
- /// \brief Removes the default argument of this template parameter.
+ /// Removes the default argument of this template parameter.
void removeDefaultArgument() { DefaultArgument.clear(); }
- /// \brief Whether this parameter is a non-type template parameter pack.
+ /// Whether this parameter is a non-type template parameter pack.
///
/// If the parameter is a parameter pack, the type may be a
/// \c PackExpansionType. In the following example, the \c Dims parameter
@@ -1366,7 +1367,7 @@ public:
/// \endcode
bool isParameterPack() const { return ParameterPack; }
- /// \brief Whether this parameter pack is a pack expansion.
+ /// Whether this parameter pack is a pack expansion.
///
/// A non-type template parameter pack is a pack expansion if its type
/// contains an unexpanded parameter pack. In this case, we will have
@@ -1375,7 +1376,7 @@ public:
return ParameterPack && getType()->getAs<PackExpansionType>();
}
- /// \brief Whether this parameter is a non-type template parameter pack
+ /// Whether this parameter is a non-type template parameter pack
/// that has a known list of different types at different positions.
///
/// A parameter pack is an expanded parameter pack when the original
@@ -1401,14 +1402,14 @@ public:
/// return the expansion types.
bool isExpandedParameterPack() const { return ExpandedParameterPack; }
- /// \brief Retrieves the number of expansion types in an expanded parameter
+ /// Retrieves the number of expansion types in an expanded parameter
/// pack.
unsigned getNumExpansionTypes() const {
assert(ExpandedParameterPack && "Not an expansion parameter pack");
return NumExpandedTypes;
}
- /// \brief Retrieve a particular expansion type within an expanded parameter
+ /// Retrieve a particular expansion type within an expanded parameter
/// pack.
QualType getExpansionType(unsigned I) const {
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
@@ -1417,7 +1418,7 @@ public:
return TypesAndInfos[I].first;
}
- /// \brief Retrieve a particular expansion type source info within an
+ /// Retrieve a particular expansion type source info within an
/// expanded parameter pack.
TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
@@ -1443,20 +1444,20 @@ class TemplateTemplateParmDecl final
protected TemplateParmPosition,
private llvm::TrailingObjects<TemplateTemplateParmDecl,
TemplateParameterList *> {
- /// \brief The default template argument, if any.
+ /// The default template argument, if any.
using DefArgStorage =
DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
DefArgStorage DefaultArgument;
- /// \brief Whether this parameter is a parameter pack.
+ /// Whether this parameter is a parameter pack.
bool ParameterPack;
- /// \brief Whether this template template parameter is an "expanded"
+ /// 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 = false;
- /// \brief The number of parameters in an expanded parameter pack.
+ /// The number of parameters in an expanded parameter pack.
unsigned NumExpandedParams = 0;
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
@@ -1494,14 +1495,14 @@ public:
static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
unsigned ID,
unsigned NumExpansions);
-
+
using TemplateParmPosition::getDepth;
using TemplateParmPosition::setDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::setPosition;
using TemplateParmPosition::getIndex;
- /// \brief Whether this template template parameter is a template
+ /// Whether this template template parameter is a template
/// parameter pack.
///
/// \code
@@ -1509,7 +1510,7 @@ public:
/// \endcode
bool isParameterPack() const { return ParameterPack; }
- /// \brief Whether this parameter pack is a pack expansion.
+ /// Whether this parameter pack is a pack expansion.
///
/// A template template parameter pack is a pack expansion if its template
/// parameter list contains an unexpanded parameter pack.
@@ -1518,7 +1519,7 @@ public:
getTemplateParameters()->containsUnexpandedParameterPack();
}
- /// \brief Whether this parameter is a template template parameter pack that
+ /// Whether this parameter is a template template parameter pack that
/// has a known list of different template parameter lists at different
/// positions.
///
@@ -1538,14 +1539,14 @@ public:
/// parameter pack.
bool isExpandedParameterPack() const { return ExpandedParameterPack; }
- /// \brief Retrieves the number of expansion template parameters in
+ /// Retrieves the number of expansion template parameters in
/// an expanded parameter pack.
unsigned getNumExpansionTemplateParameters() const {
assert(ExpandedParameterPack && "Not an expansion parameter pack");
return NumExpandedParams;
}
- /// \brief Retrieve a particular expansion type within an expanded parameter
+ /// Retrieve a particular expansion type within an expanded parameter
/// pack.
TemplateParameterList *getExpansionTemplateParameters(unsigned I) const {
assert(I < NumExpandedParams && "Out-of-range expansion type index");
@@ -1554,26 +1555,26 @@ public:
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
- /// \brief Determine whether this template parameter has a default
+ /// Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
- /// \brief Retrieve the default argument, if any.
+ /// Retrieve the default argument, if any.
const TemplateArgumentLoc &getDefaultArgument() const {
static const TemplateArgumentLoc None;
return DefaultArgument.isSet() ? *DefaultArgument.get() : None;
}
- /// \brief Retrieve the location of the default argument, if any.
+ /// Retrieve the location of the default argument, if any.
SourceLocation getDefaultArgumentLoc() const;
- /// \brief Determines whether the default argument was inherited
+ /// Determines whether the default argument was inherited
/// from a previous declaration of this template.
bool defaultArgumentWasInherited() const {
return DefaultArgument.isInherited();
}
- /// \brief Set the default argument for this template parameter, and
+ /// Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
void setDefaultArgument(const ASTContext &C,
@@ -1583,7 +1584,7 @@ public:
DefaultArgument.setInherited(C, Prev);
}
- /// \brief Removes the default argument of this template parameter.
+ /// Removes the default argument of this template parameter.
void removeDefaultArgument() { DefaultArgument.clear(); }
SourceRange getSourceRange() const override LLVM_READONLY {
@@ -1598,7 +1599,7 @@ public:
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
};
-/// \brief Represents the builtin template declaration which is used to
+/// 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 {
@@ -1621,13 +1622,13 @@ public:
}
SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange();
+ return {};
}
BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
};
-/// \brief Represents a class template specialization, which refers to
+/// Represents a class template specialization, which refers to
/// a class template with a given set of template arguments.
///
/// Class template specializations represent both explicit
@@ -1642,48 +1643,48 @@ public:
/// \endcode
class ClassTemplateSpecializationDecl
: public CXXRecordDecl, public llvm::FoldingSetNode {
- /// \brief Structure that stores information about a class template
+ /// Structure that stores information about a class template
/// specialization that was instantiated from a class template partial
/// specialization.
struct SpecializedPartialSpecialization {
- /// \brief The class template partial specialization from which this
+ /// The class template partial specialization from which this
/// class template specialization was instantiated.
ClassTemplatePartialSpecializationDecl *PartialSpecialization;
- /// \brief The template argument list deduced for the class template
+ /// The template argument list deduced for the class template
/// partial specialization itself.
const TemplateArgumentList *TemplateArgs;
};
- /// \brief The template that this specialization specializes
+ /// The template that this specialization specializes
llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
SpecializedTemplate;
- /// \brief Further info for explicit template specialization/instantiation.
+ /// Further info for explicit template specialization/instantiation.
struct ExplicitSpecializationInfo {
- /// \brief The type-as-written.
+ /// The type-as-written.
TypeSourceInfo *TypeAsWritten = nullptr;
- /// \brief The location of the extern keyword.
+ /// The location of the extern keyword.
SourceLocation ExternLoc;
- /// \brief The location of the template keyword.
+ /// The location of the template keyword.
SourceLocation TemplateKeywordLoc;
ExplicitSpecializationInfo() = default;
};
- /// \brief Further info for explicit template specialization/instantiation.
+ /// Further info for explicit template specialization/instantiation.
/// Does not apply to implicit specializations.
ExplicitSpecializationInfo *ExplicitInfo = nullptr;
- /// \brief The template arguments used to describe this specialization.
+ /// The template arguments used to describe this specialization.
const TemplateArgumentList *TemplateArgs;
- /// \brief The point where this template was instantiated (if any)
+ /// The point where this template was instantiated (if any)
SourceLocation PointOfInstantiation;
- /// \brief The kind of specialization this declaration refers to.
+ /// The kind of specialization this declaration refers to.
/// Really a value of type TemplateSpecializationKind.
unsigned SpecializationKind : 3;
@@ -1719,26 +1720,20 @@ public:
// it's not clear that we should override that, because the most recent
// declaration as a CXXRecordDecl sometimes is the injected-class-name.
ClassTemplateSpecializationDecl *getMostRecentDecl() {
- CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>(
- this)->getMostRecentDecl();
- while (!isa<ClassTemplateSpecializationDecl>(Recent)) {
- // FIXME: Does injected class name need to be in the redeclarations chain?
- assert(Recent->isInjectedClassName() && Recent->getPreviousDecl());
- Recent = Recent->getPreviousDecl();
- }
- return cast<ClassTemplateSpecializationDecl>(Recent);
+ return cast<ClassTemplateSpecializationDecl>(
+ getMostRecentNonInjectedDecl());
}
- /// \brief Retrieve the template that this specialization specializes.
+ /// Retrieve the template that this specialization specializes.
ClassTemplateDecl *getSpecializedTemplate() const;
- /// \brief Retrieve the template arguments of the class template
+ /// Retrieve the template arguments of the class template
/// specialization.
const TemplateArgumentList &getTemplateArgs() const {
return *TemplateArgs;
}
- /// \brief Determine the kind of specialization that this
+ /// Determine the kind of specialization that this
/// declaration represents.
TemplateSpecializationKind getSpecializationKind() const {
return static_cast<TemplateSpecializationKind>(SpecializationKind);
@@ -1748,7 +1743,7 @@ public:
return getSpecializationKind() == TSK_ExplicitSpecialization;
}
- /// \brief True if this declaration is an explicit specialization,
+ /// True if this declaration is an explicit specialization,
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
@@ -1760,7 +1755,7 @@ public:
SpecializationKind = TSK;
}
- /// \brief Get the point of instantiation (if any), or null if none.
+ /// Get the point of instantiation (if any), or null if none.
SourceLocation getPointOfInstantiation() const {
return PointOfInstantiation;
}
@@ -1770,7 +1765,7 @@ public:
PointOfInstantiation = Loc;
}
- /// \brief If this class template specialization is an instantiation of
+ /// If this class template specialization is an instantiation of
/// a template (rather than an explicit specialization), return the
/// class template or class template partial specialization from which it
/// was instantiated.
@@ -1784,19 +1779,19 @@ public:
return getSpecializedTemplateOrPartial();
}
- /// \brief Retrieve the class template or class template partial
+ /// Retrieve the class template or class template partial
/// specialization which was specialized by this.
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
getSpecializedTemplateOrPartial() const {
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization;
return SpecializedTemplate.get<ClassTemplateDecl*>();
}
- /// \brief Retrieve the set of template arguments that should be used
+ /// Retrieve the set of template arguments that should be used
/// to instantiate members of the class template or class template partial
/// specialization from which this class template specialization was
/// instantiated.
@@ -1808,28 +1803,27 @@ public:
/// deduced template arguments for the class template partial specialization
/// itself.
const TemplateArgumentList &getTemplateInstantiationArgs() const {
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return *PartialSpec->TemplateArgs;
return getTemplateArgs();
}
- /// \brief Note that this class template specialization is actually an
+ /// Note that this class template specialization is actually an
/// instantiation of the given class template partial specialization whose
/// template arguments have been deduced.
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
- SpecializedPartialSpecialization *PS
- = new (getASTContext()) SpecializedPartialSpecialization();
+ auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
PS->PartialSpecialization = PartialSpec;
PS->TemplateArgs = TemplateArgs;
SpecializedTemplate = PS;
}
- /// \brief Note that this class template specialization is an instantiation
+ /// Note that this class template specialization is an instantiation
/// of the given class template.
void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
@@ -1837,7 +1831,7 @@ public:
SpecializedTemplate = TemplDecl;
}
- /// \brief Sets the type of this specialization as it was written by
+ /// Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type.
void setTypeAsWritten(TypeSourceInfo *T) {
if (!ExplicitInfo)
@@ -1845,32 +1839,32 @@ public:
ExplicitInfo->TypeAsWritten = T;
}
- /// \brief Gets the type of this specialization as it was written by
+ /// Gets the type of this specialization as it was written by
/// the user, if it was so written.
TypeSourceInfo *getTypeAsWritten() const {
return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
}
- /// \brief Gets the location of the extern keyword, if present.
+ /// Gets the location of the extern keyword, if present.
SourceLocation getExternLoc() const {
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
}
- /// \brief Sets the location of the extern keyword.
+ /// Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->ExternLoc = Loc;
}
- /// \brief Sets the location of the template keyword.
+ /// Sets the location of the template keyword.
void setTemplateKeywordLoc(SourceLocation Loc) {
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
- /// \brief Gets the location of the template keyword, if present.
+ /// Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
}
@@ -1899,14 +1893,14 @@ public:
class ClassTemplatePartialSpecializationDecl
: public ClassTemplateSpecializationDecl {
- /// \brief The list of template parameters
+ /// The list of template parameters
TemplateParameterList* TemplateParams = nullptr;
- /// \brief The source info for the template arguments as written.
+ /// The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
- /// \brief The class template partial specialization from which this
+ /// The class template partial specialization from which this
/// class template partial specialization was instantiated.
///
/// The boolean value will be true to indicate that this class template
@@ -1963,7 +1957,7 @@ public:
return ArgsAsWritten;
}
- /// \brief Retrieve the member class template partial specialization from
+ /// Retrieve the member class template partial specialization from
/// which this particular class template partial specialization was
/// instantiated.
///
@@ -1984,7 +1978,7 @@ public:
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
- const ClassTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
@@ -1995,12 +1989,11 @@ public:
void setInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *PartialSpec) {
- ClassTemplatePartialSpecializationDecl *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
First->InstantiatedFromMember.setPointer(PartialSpec);
}
- /// \brief Determines whether this class template partial specialization
+ /// Determines whether this class template partial specialization
/// template was a specialization of a member partial specialization.
///
/// In the following example, the member template partial specialization
@@ -2017,15 +2010,14 @@ public:
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}
- /// \brief Note that this member template is a specialization.
+ /// Note that this member template is a specialization.
void setMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
@@ -2052,29 +2044,29 @@ public:
/// Declaration of a class template.
class ClassTemplateDecl : public RedeclarableTemplateDecl {
protected:
- /// \brief Data that is common to all of the declarations of a given
+ /// Data that is common to all of the declarations of a given
/// class template.
struct Common : CommonBase {
- /// \brief The class template specializations for this class
+ /// The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations;
- /// \brief The class template partial specializations for this class
+ /// The class template partial specializations for this class
/// template.
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>
PartialSpecializations;
- /// \brief The injected-class-name type for this class template.
+ /// The injected-class-name type for this class template.
QualType InjectedClassNameType;
Common() = default;
};
- /// \brief Retrieve the set of specializations of this class template.
+ /// Retrieve the set of specializations of this class template.
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
getSpecializations() const;
- /// \brief Retrieve the set of partial specializations of this class
+ /// Retrieve the set of partial specializations of this class
/// template.
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
getPartialSpecializations();
@@ -2100,22 +2092,22 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- /// \brief Load any lazily-loaded specializations from the external source.
+ /// Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
- /// \brief Get the underlying class declarations of the template.
+ /// Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
- /// \brief Returns whether this template declaration defines the primary
+ /// Returns whether this template declaration defines the primary
/// class pattern.
bool isThisDeclarationADefinition() const {
return getTemplatedDecl()->isThisDeclarationADefinition();
}
// FIXME: remove default argument for AssociatedConstraints
- /// \brief Create a class template node.
+ /// Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
@@ -2123,15 +2115,15 @@ public:
NamedDecl *Decl,
Expr *AssociatedConstraints = nullptr);
- /// \brief Create an empty class template node.
+ /// Create an empty class template node.
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// \brief Return the specialization with the provided arguments if it exists,
+ /// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
ClassTemplateSpecializationDecl *
findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
- /// \brief Insert the specified specialization knowing that it is not already
+ /// Insert the specified specialization knowing that it is not already
/// in. InsertPos must be obtained from findSpecialization.
void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
@@ -2144,7 +2136,7 @@ public:
RedeclarableTemplateDecl::getCanonicalDecl());
}
- /// \brief Retrieve the previous declaration of this class template, or
+ /// Retrieve the previous declaration of this class template, or
/// nullptr if no such declaration exists.
ClassTemplateDecl *getPreviousDecl() {
return cast_or_null<ClassTemplateDecl>(
@@ -2169,21 +2161,21 @@ public:
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
- /// \brief Return the partial specialization with the provided arguments if it
+ /// Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point.
ClassTemplatePartialSpecializationDecl *
findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
- /// \brief Insert the specified partial specialization knowing that it is not
+ /// Insert the specified partial specialization knowing that it is not
/// already in. InsertPos must be obtained from findPartialSpecialization.
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
void *InsertPos);
- /// \brief Retrieve the partial specializations as an ordered list.
+ /// Retrieve the partial specializations as an ordered list.
void getPartialSpecializations(
SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
- /// \brief Find a class template partial specialization with the given
+ /// Find a class template partial specialization with the given
/// type T.
///
/// \param T a dependent type that names a specialization of this class
@@ -2193,7 +2185,7 @@ public:
/// 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
+ /// Find a class template partial specialization which was instantiated
/// from the given member partial specialization.
///
/// \param D a member class template partial specialization.
@@ -2205,7 +2197,7 @@ public:
findPartialSpecInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *D);
- /// \brief Retrieve the template specialization type of the
+ /// Retrieve the template specialization type of the
/// injected-class-name for this class template.
///
/// The injected-class-name for a class template \c X is \c
@@ -2241,7 +2233,7 @@ public:
static bool classofKind(Kind K) { return K == ClassTemplate; }
};
-/// \brief Declaration of a friend template.
+/// Declaration of a friend template.
///
/// For example:
/// \code
@@ -2305,7 +2297,7 @@ public:
return Friend.dyn_cast<NamedDecl*>();
}
- /// \brief Retrieves the location of the 'friend' keyword.
+ /// Retrieves the location of the 'friend' keyword.
SourceLocation getFriendLoc() const {
return FriendLoc;
}
@@ -2324,7 +2316,7 @@ public:
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
};
-/// \brief Declaration of an alias template.
+/// Declaration of an alias template.
///
/// For example:
/// \code
@@ -2365,7 +2357,7 @@ public:
RedeclarableTemplateDecl::getCanonicalDecl());
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// Retrieve the previous declaration of this function template, or
/// nullptr if no such declaration exists.
TypeAliasTemplateDecl *getPreviousDecl() {
return cast_or_null<TypeAliasTemplateDecl>(
@@ -2382,14 +2374,14 @@ public:
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
- /// \brief Create a function template node.
+ /// Create a function template node.
static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl);
- /// \brief Create an empty alias template node.
+ /// Create an empty alias template node.
static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
// Implement isa/cast/dyncast support
@@ -2397,7 +2389,7 @@ public:
static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
};
-/// \brief Declaration of a function specialization at template class scope.
+/// Declaration of a function specialization at template class scope.
///
/// This is a non-standard extension needed to support MSVC.
///
@@ -2450,7 +2442,7 @@ public:
static ClassScopeFunctionSpecializationDecl *
CreateDeserialized(ASTContext &Context, unsigned ID);
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2463,7 +2455,7 @@ public:
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
: Function(FTD) {}
-/// \brief Represents a variable template specialization, which refers to
+/// Represents a variable template specialization, which refers to
/// a variable template with a given set of template arguments.
///
/// Variable template specializations represent both explicit
@@ -2479,53 +2471,53 @@ inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
class VarTemplateSpecializationDecl : public VarDecl,
public llvm::FoldingSetNode {
- /// \brief Structure that stores information about a variable template
+ /// Structure that stores information about a variable template
/// specialization that was instantiated from a variable template partial
/// specialization.
struct SpecializedPartialSpecialization {
- /// \brief The variable template partial specialization from which this
+ /// The variable template partial specialization from which this
/// variable template specialization was instantiated.
VarTemplatePartialSpecializationDecl *PartialSpecialization;
- /// \brief The template argument list deduced for the variable template
+ /// The template argument list deduced for the variable template
/// partial specialization itself.
const TemplateArgumentList *TemplateArgs;
};
- /// \brief The template that this specialization specializes.
+ /// The template that this specialization specializes.
llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *>
SpecializedTemplate;
- /// \brief Further info for explicit template specialization/instantiation.
+ /// Further info for explicit template specialization/instantiation.
struct ExplicitSpecializationInfo {
- /// \brief The type-as-written.
+ /// The type-as-written.
TypeSourceInfo *TypeAsWritten = nullptr;
- /// \brief The location of the extern keyword.
+ /// The location of the extern keyword.
SourceLocation ExternLoc;
- /// \brief The location of the template keyword.
+ /// The location of the template keyword.
SourceLocation TemplateKeywordLoc;
ExplicitSpecializationInfo() = default;
};
- /// \brief Further info for explicit template specialization/instantiation.
+ /// Further info for explicit template specialization/instantiation.
/// Does not apply to implicit specializations.
ExplicitSpecializationInfo *ExplicitInfo = nullptr;
- /// \brief The template arguments used to describe this specialization.
+ /// The template arguments used to describe this specialization.
const TemplateArgumentList *TemplateArgs;
TemplateArgumentListInfo TemplateArgsInfo;
- /// \brief The point where this template was instantiated (if any).
+ /// The point where this template was instantiated (if any).
SourceLocation PointOfInstantiation;
- /// \brief The kind of specialization this declaration refers to.
+ /// The kind of specialization this declaration refers to.
/// Really a value of type TemplateSpecializationKind.
unsigned SpecializationKind : 3;
- /// \brief Whether this declaration is a complete definition of the
+ /// 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.
@@ -2562,10 +2554,10 @@ public:
return cast<VarTemplateSpecializationDecl>(Recent);
}
- /// \brief Retrieve the template that this specialization specializes.
+ /// Retrieve the template that this specialization specializes.
VarTemplateDecl *getSpecializedTemplate() const;
- /// \brief Retrieve the template arguments of the variable template
+ /// Retrieve the template arguments of the variable template
/// specialization.
const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
@@ -2576,7 +2568,7 @@ public:
return TemplateArgsInfo;
}
- /// \brief Determine the kind of specialization that this
+ /// Determine the kind of specialization that this
/// declaration represents.
TemplateSpecializationKind getSpecializationKind() const {
return static_cast<TemplateSpecializationKind>(SpecializationKind);
@@ -2586,7 +2578,7 @@ public:
return getSpecializationKind() == TSK_ExplicitSpecialization;
}
- /// \brief True if this declaration is an explicit specialization,
+ /// True if this declaration is an explicit specialization,
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
@@ -2598,7 +2590,7 @@ public:
SpecializationKind = TSK;
}
- /// \brief Get the point of instantiation (if any), or null if none.
+ /// Get the point of instantiation (if any), or null if none.
SourceLocation getPointOfInstantiation() const {
return PointOfInstantiation;
}
@@ -2610,7 +2602,7 @@ public:
void setCompleteDefinition() { IsCompleteDefinition = true; }
- /// \brief If this variable template specialization is an instantiation of
+ /// If this variable template specialization is an instantiation of
/// a template (rather than an explicit specialization), return the
/// variable template or variable template partial specialization from which
/// it was instantiated.
@@ -2623,18 +2615,18 @@ public:
return getSpecializedTemplateOrPartial();
}
- /// \brief Retrieve the variable template or variable template partial
+ /// Retrieve the variable template or variable template partial
/// specialization which was specialized by this.
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
getSpecializedTemplateOrPartial() const {
- if (SpecializedPartialSpecialization *PartialSpec =
+ if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization;
return SpecializedTemplate.get<VarTemplateDecl *>();
}
- /// \brief Retrieve the set of template arguments that should be used
+ /// Retrieve the set of template arguments that should be used
/// to instantiate the initializer of the variable template or variable
/// template partial specialization from which this variable template
/// specialization was instantiated.
@@ -2646,28 +2638,27 @@ public:
/// return deduced template arguments for the variable template partial
/// specialization itself.
const TemplateArgumentList &getTemplateInstantiationArgs() const {
- if (SpecializedPartialSpecialization *PartialSpec =
+ if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return *PartialSpec->TemplateArgs;
return getTemplateArgs();
}
- /// \brief Note that this variable template specialization is actually an
+ /// Note that this variable template specialization is actually an
/// instantiation of the given variable template partial specialization whose
/// template arguments have been deduced.
void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Already set to a variable template partial specialization!");
- SpecializedPartialSpecialization *PS =
- new (getASTContext()) SpecializedPartialSpecialization();
+ auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
PS->PartialSpecialization = PartialSpec;
PS->TemplateArgs = TemplateArgs;
SpecializedTemplate = PS;
}
- /// \brief Note that this variable template specialization is an instantiation
+ /// Note that this variable template specialization is an instantiation
/// of the given variable template.
void setInstantiationOf(VarTemplateDecl *TemplDecl) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
@@ -2675,7 +2666,7 @@ public:
SpecializedTemplate = TemplDecl;
}
- /// \brief Sets the type of this specialization as it was written by
+ /// Sets the type of this specialization as it was written by
/// the user.
void setTypeAsWritten(TypeSourceInfo *T) {
if (!ExplicitInfo)
@@ -2683,32 +2674,32 @@ public:
ExplicitInfo->TypeAsWritten = T;
}
- /// \brief Gets the type of this specialization as it was written by
+ /// Gets the type of this specialization as it was written by
/// the user, if it was so written.
TypeSourceInfo *getTypeAsWritten() const {
return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
}
- /// \brief Gets the location of the extern keyword, if present.
+ /// Gets the location of the extern keyword, if present.
SourceLocation getExternLoc() const {
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
}
- /// \brief Sets the location of the extern keyword.
+ /// Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->ExternLoc = Loc;
}
- /// \brief Sets the location of the template keyword.
+ /// Sets the location of the template keyword.
void setTemplateKeywordLoc(SourceLocation Loc) {
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
- /// \brief Gets the location of the template keyword, if present.
+ /// Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
}
@@ -2735,14 +2726,14 @@ public:
class VarTemplatePartialSpecializationDecl
: public VarTemplateSpecializationDecl {
- /// \brief The list of template parameters
+ /// The list of template parameters
TemplateParameterList *TemplateParams = nullptr;
- /// \brief The source info for the template arguments as written.
+ /// The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
- /// \brief The variable template partial specialization from which this
+ /// The variable template partial specialization from which this
/// variable template partial specialization was instantiated.
///
/// The boolean value will be true to indicate that this variable template
@@ -2794,7 +2785,7 @@ public:
return ArgsAsWritten;
}
- /// \brief Retrieve the member variable template partial specialization from
+ /// Retrieve the member variable template partial specialization from
/// which this particular variable template partial specialization was
/// instantiated.
///
@@ -2815,19 +2806,18 @@ public:
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
- const VarTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
void
setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
- VarTemplatePartialSpecializationDecl *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
First->InstantiatedFromMember.setPointer(PartialSpec);
}
- /// \brief Determines whether this variable template partial specialization
+ /// Determines whether this variable template partial specialization
/// was a specialization of a member partial specialization.
///
/// In the following example, the member template partial specialization
@@ -2844,15 +2834,14 @@ public:
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
/// \endcode
bool isMemberSpecialization() {
- VarTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}
- /// \brief Note that this member template is a specialization.
+ /// Note that this member template is a specialization.
void setMemberSpecialization() {
- VarTemplatePartialSpecializationDecl *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
@@ -2868,14 +2857,14 @@ public:
/// Declaration of a variable template.
class VarTemplateDecl : public RedeclarableTemplateDecl {
protected:
- /// \brief Data that is common to all of the declarations of a given
+ /// Data that is common to all of the declarations of a given
/// variable template.
struct Common : CommonBase {
- /// \brief The variable template specializations for this variable
+ /// The variable template specializations for this variable
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
- /// \brief The variable template partial specializations for this variable
+ /// The variable template partial specializations for this variable
/// template.
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
PartialSpecializations;
@@ -2883,11 +2872,11 @@ protected:
Common() = default;
};
- /// \brief Retrieve the set of specializations of this variable template.
+ /// Retrieve the set of specializations of this variable template.
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
getSpecializations() const;
- /// \brief Retrieve the set of partial specializations of this class
+ /// Retrieve the set of partial specializations of this class
/// template.
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
getPartialSpecializations();
@@ -2907,15 +2896,15 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- /// \brief Load any lazily-loaded specializations from the external source.
+ /// Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
- /// \brief Get the underlying variable declarations of the template.
+ /// Get the underlying variable declarations of the template.
VarDecl *getTemplatedDecl() const {
return static_cast<VarDecl *>(TemplatedDecl);
}
- /// \brief Returns whether this template declaration defines the primary
+ /// Returns whether this template declaration defines the primary
/// variable pattern.
bool isThisDeclarationADefinition() const {
return getTemplatedDecl()->isThisDeclarationADefinition();
@@ -2923,21 +2912,21 @@ public:
VarTemplateDecl *getDefinition();
- /// \brief Create a variable template node.
+ /// Create a variable template node.
static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params,
VarDecl *Decl);
- /// \brief Create an empty variable template node.
+ /// Create an empty variable template node.
static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// \brief Return the specialization with the provided arguments if it exists,
+ /// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
VarTemplateSpecializationDecl *
findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
- /// \brief Insert the specified specialization knowing that it is not already
+ /// Insert the specified specialization knowing that it is not already
/// in. InsertPos must be obtained from findSpecialization.
void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos);
@@ -2948,7 +2937,7 @@ public:
return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
}
- /// \brief Retrieve the previous declaration of this variable template, or
+ /// Retrieve the previous declaration of this variable template, or
/// nullptr if no such declaration exists.
VarTemplateDecl *getPreviousDecl() {
return cast_or_null<VarTemplateDecl>(
@@ -2973,21 +2962,21 @@ public:
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
- /// \brief Return the partial specialization with the provided arguments if it
+ /// Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point.
VarTemplatePartialSpecializationDecl *
findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
- /// \brief Insert the specified partial specialization knowing that it is not
+ /// Insert the specified partial specialization knowing that it is not
/// already in. InsertPos must be obtained from findPartialSpecialization.
void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D,
void *InsertPos);
- /// \brief Retrieve the partial specializations as an ordered list.
+ /// Retrieve the partial specializations as an ordered list.
void getPartialSpecializations(
SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS);
- /// \brief Find a variable template partial specialization which was
+ /// Find a variable template partial specialization which was
/// instantiated
/// from the given member partial specialization.
///
@@ -3021,11 +3010,11 @@ public:
};
inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
- if (auto *PD = P.dyn_cast<TemplateTypeParmDecl*>())
+ if (auto *PD = P.dyn_cast<TemplateTypeParmDecl *>())
return PD;
- if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl*>())
+ if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl *>())
return PD;
- return P.get<TemplateTemplateParmDecl*>();
+ return P.get<TemplateTemplateParmDecl *>();
}
inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
index 3ff274bd6a7a..520a4a10bfe1 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
@@ -30,7 +30,7 @@ namespace declvisitor {
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.
+/// A simple visitor class that helps create declaration visitors.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class Base {
public:
@@ -62,7 +62,7 @@ public:
} // namespace declvisitor
-/// \brief A simple visitor class that helps create declaration visitors.
+/// A simple visitor class that helps create declaration visitors.
///
/// This class does not preserve constness of Decl pointers (see also
/// ConstDeclVisitor).
@@ -70,7 +70,7 @@ 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.
+/// 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>
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
index 467b02c52b0c..856f3ab5720e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
@@ -194,7 +194,7 @@ public:
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
- /// \brief Evaluates true when this declaration name is empty.
+ /// Evaluates true when this declaration name is empty.
bool isEmpty() const {
return !*this;
}
@@ -211,14 +211,14 @@ public:
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
- /// \brief Determines whether the name itself is dependent, e.g., because it
+ /// Determines whether the name itself is dependent, e.g., because it
/// involves a C++ type that is itself dependent.
///
/// Note that this does not capture all of the notions of "dependent name",
- /// because an identifier can be a dependent name if it is used as the
+ /// because an identifier can be a dependent name if it is used as the
/// callee in a call expression with dependent arguments.
bool isDependentName() const;
-
+
/// getNameAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
@@ -541,10 +541,10 @@ public:
LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
}
- /// \brief Determine whether this name involves a template parameter.
+ /// Determine whether this name involves a template parameter.
bool isInstantiationDependent() const;
-
- /// \brief Determine whether this name contains an unexpanded
+
+ /// Determine whether this name contains an unexpanded
/// parameter pack.
bool containsUnexpandedParameterPack() const;
@@ -558,7 +558,7 @@ public:
SourceLocation getBeginLoc() const { return NameLoc; }
/// getEndLoc - Retrieve the location of the last token.
- SourceLocation getEndLoc() const;
+ SourceLocation getEndLoc() const { return getLocEnd(); }
/// getSourceRange - The range of the declaration name.
SourceRange getSourceRange() const LLVM_READONLY {
@@ -570,9 +570,11 @@ public:
}
SourceLocation getLocEnd() const LLVM_READONLY {
- SourceLocation EndLoc = getEndLoc();
+ SourceLocation EndLoc = getEndLocPrivate();
return EndLoc.isValid() ? EndLoc : getLocStart();
}
+private:
+ SourceLocation getEndLocPrivate() const;
};
/// Insertion operator for diagnostics. This allows sending DeclarationName's
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
index a514326c6cb1..c21ef7907b8a 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
@@ -101,9 +101,9 @@ private:
friend class DependentStoredDeclsMap;
DependentDiagnostic(const PartialDiagnostic &PDiag,
- PartialDiagnostic::Storage *Storage)
+ PartialDiagnostic::Storage *Storage)
: Diag(PDiag, Storage) {}
-
+
static DependentDiagnostic *Create(ASTContext &Context,
DeclContext *Parent,
const PartialDiagnostic &PDiag);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
index aad7726f8484..1aec5ae842d4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
@@ -21,10 +21,10 @@
#include "clang/AST/StmtVisitor.h"
namespace clang {
-
+
class ASTContext;
-
-/// \brief Given a potentially-evaluated expression, this visitor visits all
+
+/// Given a potentially-evaluated expression, this visitor visits all
/// of its potentially-evaluated subexpressions, recursively.
template<template <typename> class Ptr, typename ImplClass>
class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> {
@@ -95,7 +95,7 @@ public:
this->Visit(*I);
}
- /// \brief The basis case walks all of the children of the statement or
+ /// The basis case walks all of the children of the statement or
/// expression, assuming they are all potentially evaluated.
void VisitStmt(PTR(Stmt) S) {
for (auto *SubStmt : S->children())
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
index f2770940372f..c18fbf05df68 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -52,10 +52,10 @@ namespace clang {
class TargetInfo;
class ValueDecl;
-/// \brief A simple array of base specifiers.
+/// A simple array of base specifiers.
typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
-/// \brief An adjustment to be made to the temporary created when emitting a
+/// An adjustment to be made to the temporary created when emitting a
/// reference binding, which accesses a particular subobject of that temporary.
struct SubobjectAdjustment {
enum {
@@ -121,7 +121,7 @@ protected:
setType(T);
}
- /// \brief Construct an empty expression.
+ /// Construct an empty expression.
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
public:
@@ -148,7 +148,7 @@ public:
/// @endcode
bool isValueDependent() const { return ExprBits.ValueDependent; }
- /// \brief Set whether this expression is value-dependent or not.
+ /// Set whether this expression is value-dependent or not.
void setValueDependent(bool VD) {
ExprBits.ValueDependent = VD;
}
@@ -166,12 +166,12 @@ public:
/// @endcode
bool isTypeDependent() const { return ExprBits.TypeDependent; }
- /// \brief Set whether this expression is type-dependent or not.
+ /// Set whether this expression is type-dependent or not.
void setTypeDependent(bool TD) {
ExprBits.TypeDependent = TD;
}
- /// \brief Whether this expression is instantiation-dependent, meaning that
+ /// Whether this expression is instantiation-dependent, meaning that
/// it depends in some way on a template parameter, even if neither its type
/// nor (constant) value can change due to the template instantiation.
///
@@ -192,12 +192,12 @@ public:
return ExprBits.InstantiationDependent;
}
- /// \brief Set whether this expression is instantiation-dependent or not.
+ /// Set whether this expression is instantiation-dependent or not.
void setInstantiationDependent(bool ID) {
ExprBits.InstantiationDependent = ID;
}
- /// \brief Whether this expression contains an unexpanded parameter
+ /// Whether this expression contains an unexpanded parameter
/// pack (for C++11 variadic templates).
///
/// Given the following function template:
@@ -215,7 +215,7 @@ public:
return ExprBits.ContainsUnexpandedParameterPack;
}
- /// \brief Set the bit that describes whether this expression
+ /// Set the bit that describes whether this expression
/// contains an unexpanded parameter pack.
void setContainsUnexpandedParameterPack(bool PP = true) {
ExprBits.ContainsUnexpandedParameterPack = PP;
@@ -297,11 +297,11 @@ public:
isModifiableLvalueResult
isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const;
- /// \brief The return type of classify(). Represents the C++11 expression
+ /// The return type of classify(). Represents the C++11 expression
/// taxonomy.
class Classification {
public:
- /// \brief The various classification results. Most of these mean prvalue.
+ /// The various classification results. Most of these mean prvalue.
enum Kinds {
CL_LValue,
CL_XValue,
@@ -316,7 +316,7 @@ public:
CL_ObjCMessageRValue, // ObjC message is an rvalue
CL_PRValue // A prvalue for any other reason, of any other type
};
- /// \brief The results of modification testing.
+ /// The results of modification testing.
enum ModifiableType {
CM_Untested, // testModifiable was false.
CM_Modifiable,
@@ -356,13 +356,13 @@ public:
bool isRValue() const { return Kind >= CL_XValue; }
bool isModifiable() const { return getModifiable() == CM_Modifiable; }
- /// \brief Create a simple, modifiably lvalue
+ /// Create a simple, modifiably lvalue
static Classification makeSimpleLValue() {
return Classification(CL_LValue, CM_Modifiable);
}
};
- /// \brief Classify - Classify this expression according to the C++11
+ /// Classify - Classify this expression according to the C++11
/// expression taxonomy.
///
/// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the
@@ -378,7 +378,7 @@ public:
return ClassifyImpl(Ctx, nullptr);
}
- /// \brief ClassifyModifiable - Classify this expression according to the
+ /// ClassifyModifiable - Classify this expression according to the
/// C++11 expression taxonomy, and see if it is valid on the left side
/// of an assignment.
///
@@ -429,14 +429,14 @@ private:
public:
- /// \brief Returns true if this expression is a gl-value that
+ /// Returns true if this expression is a gl-value that
/// potentially refers to a bit-field.
///
/// In C++, whether a gl-value refers to a bitfield is essentially
/// an aspect of the value-kind type system.
bool refersToBitField() const { return getObjectKind() == OK_BitField; }
- /// \brief If this expression refers to a bit-field, retrieve the
+ /// If this expression refers to a bit-field, retrieve the
/// declaration of that bit-field.
///
/// Note that this returns a non-null pointer in subtly different
@@ -454,26 +454,26 @@ public:
return const_cast<Expr*>(this)->getReferencedDeclOfCallee();
}
- /// \brief If this expression is an l-value for an Objective C
+ /// If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *getObjCProperty() const;
- /// \brief Check if this expression is the ObjC 'self' implicit parameter.
+ /// Check if this expression is the ObjC 'self' implicit parameter.
bool isObjCSelfExpr() const;
- /// \brief Returns whether this expression refers to a vector element.
+ /// Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
- /// \brief Returns whether this expression refers to a global register
+ /// Returns whether this expression refers to a global register
/// variable.
bool refersToGlobalRegisterVar() const;
- /// \brief Returns whether this expression has a placeholder type.
+ /// Returns whether this expression has a placeholder type.
bool hasPlaceholderType() const {
return getType()->isPlaceholderType();
}
- /// \brief Returns whether this expression has a specific placeholder type.
+ /// Returns whether this expression has a specific placeholder type.
bool hasPlaceholderType(BuiltinType::Kind K) const {
assert(BuiltinType::isPlaceholderTypeKind(K));
if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType()))
@@ -539,11 +539,11 @@ public:
/// EvalStatus is a struct with detailed info about an evaluation in progress.
struct EvalStatus {
- /// \brief Whether the evaluated expression has side effects.
+ /// Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
bool HasSideEffects;
- /// \brief Whether the evaluation hit undefined behavior.
+ /// Whether the evaluation hit undefined behavior.
/// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
/// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
bool HasUndefinedBehavior;
@@ -586,7 +586,7 @@ public:
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant
- /// which we we can fold and convert to a boolean condition using
+ /// which we can fold and convert to a boolean condition using
/// any crazy technique that we want to, even if the expression has
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
@@ -625,7 +625,7 @@ public:
bool HasSideEffects(const ASTContext &Ctx,
bool IncludePossibleEffects = true) const;
- /// \brief Determine whether this expression involves a call to any function
+ /// Determine whether this expression involves a call to any function
/// that is not trivial.
bool hasNonTrivialCall(const ASTContext &Ctx) const;
@@ -658,7 +658,14 @@ public:
ArrayRef<const Expr*> Args,
const Expr *This = nullptr) const;
- /// \brief If the current Expr is a pointer, this will try to statically
+ /// Indicates how the constant expression will be used.
+ enum ConstExprUsage { EvaluateForCodeGen, EvaluateForMangling };
+
+ /// Evaluate an expression that is required to be a constant expression.
+ bool EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
+ const ASTContext &Ctx) const;
+
+ /// If the current Expr is a pointer, this will try to statically
/// determine the number of bytes available where the pointer is pointing.
/// Returns true if all of the above holds and we were able to figure out the
/// size, false otherwise.
@@ -668,40 +675,40 @@ public:
bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
unsigned Type) const;
- /// \brief Enumeration used to describe the kind of Null pointer constant
+ /// Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
- /// \brief Expression is not a Null pointer constant.
+ /// Expression is not a Null pointer constant.
NPCK_NotNull = 0,
- /// \brief Expression is a Null pointer constant built from a zero integer
+ /// Expression is a Null pointer constant built from a zero integer
/// expression that is not a simple, possibly parenthesized, zero literal.
/// C++ Core Issue 903 will classify these expressions as "not pointers"
/// once it is adopted.
/// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
NPCK_ZeroExpression,
- /// \brief Expression is a Null pointer constant built from a literal zero.
+ /// Expression is a Null pointer constant built from a literal zero.
NPCK_ZeroLiteral,
- /// \brief Expression is a C++11 nullptr.
+ /// Expression is a C++11 nullptr.
NPCK_CXX11_nullptr,
- /// \brief Expression is a GNU-style __null constant.
+ /// Expression is a GNU-style __null constant.
NPCK_GNUNull
};
- /// \brief Enumeration used to describe how \c isNullPointerConstant()
+ /// Enumeration used to describe how \c isNullPointerConstant()
/// should cope with value-dependent expressions.
enum NullPointerConstantValueDependence {
- /// \brief Specifies that the expression should never be value-dependent.
+ /// Specifies that the expression should never be value-dependent.
NPC_NeverValueDependent = 0,
- /// \brief Specifies that a value-dependent expression of integral or
+ /// Specifies that a value-dependent expression of integral or
/// dependent type should be considered a null pointer constant.
NPC_ValueDependentIsNull,
- /// \brief Specifies that a value-dependent expression should be considered
+ /// Specifies that a value-dependent expression should be considered
/// to never be a null pointer constant.
NPC_ValueDependentIsNotNull
};
@@ -717,10 +724,10 @@ public:
/// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
- /// \brief Returns true if this expression is a bound member function.
+ /// Returns true if this expression is a bound member function.
bool isBoundMemberFunction(ASTContext &Ctx) const;
- /// \brief Given an expression of bound-member type, find the type
+ /// Given an expression of bound-member type, find the type
/// of the member. Returns null if this is an *overloaded* bound
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
@@ -788,7 +795,7 @@ public:
return const_cast<Expr*>(this)->ignoreParenBaseCasts();
}
- /// \brief Determine whether this expression is a default function argument.
+ /// Determine whether this expression is a default function argument.
///
/// Default arguments are implicitly generated in the abstract syntax tree
/// by semantic analysis for function calls, object constructions, etc. in
@@ -797,11 +804,11 @@ public:
/// the expression is a default argument.
bool isDefaultArgument() const;
- /// \brief Determine whether the result of this expression is a
+ /// Determine whether the result of this expression is a
/// temporary object of the given class type.
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
- /// \brief Whether this expression is an implicit reference to 'this' in C++.
+ /// Whether this expression is an implicit reference to 'this' in C++.
bool isImplicitCXXThis() const;
const Expr *IgnoreImpCasts() const LLVM_READONLY {
@@ -824,7 +831,7 @@ public:
static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs);
- /// \brief For an expression of class type or pointer to class type,
+ /// For an expression of class type or pointer to class type,
/// return the most derived class decl the expression is known to refer to.
///
/// If this expression is a cast, this method looks through it to find the
@@ -833,7 +840,7 @@ public:
/// behavior if the object isn't dynamically of the derived type.
const CXXRecordDecl *getBestDynamicClassType() const;
- /// \brief Get the inner expression that determines the best dynamic class.
+ /// Get the inner expression that determines the best dynamic class.
/// If this is a prvalue, we guarantee that it is of the most-derived type
/// for the object itself.
const Expr *getBestDynamicClassTypeExpr() const;
@@ -877,12 +884,13 @@ public:
: Expr(OpaqueValueExprClass, T, VK, OK,
T->isDependentType() ||
(SourceExpr && SourceExpr->isTypeDependent()),
- T->isDependentType() ||
+ T->isDependentType() ||
(SourceExpr && SourceExpr->isValueDependent()),
T->isInstantiationDependentType() ||
(SourceExpr && SourceExpr->isInstantiationDependent()),
false),
SourceExpr(SourceExpr), Loc(Loc) {
+ setIsUnique(false);
}
/// Given an expression which invokes a copy constructor --- i.e. a
@@ -893,7 +901,7 @@ public:
explicit OpaqueValueExpr(EmptyShell Empty)
: Expr(OpaqueValueExprClass, Empty) { }
- /// \brief Retrieve the location of this expression.
+ /// Retrieve the location of this expression.
SourceLocation getLocation() const { return Loc; }
SourceLocation getLocStart() const LLVM_READONLY {
@@ -925,12 +933,20 @@ public:
/// place.
Expr *getSourceExpr() const { return SourceExpr; }
+ void setIsUnique(bool V) {
+ assert((!V || SourceExpr) &&
+ "unique OVEs are expected to have source expressions");
+ OpaqueValueExprBits.IsUnique = V;
+ }
+
+ bool isUnique() const { return OpaqueValueExprBits.IsUnique; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OpaqueValueExprClass;
}
};
-/// \brief A reference to a declared variable, function, enum, etc.
+/// A reference to a declared variable, function, enum, etc.
/// [C99 6.5.1p2]
///
/// This encodes all the information about how a declaration is referenced
@@ -958,13 +974,13 @@ class DeclRefExpr final
private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
NamedDecl *, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
- /// \brief The declaration that we are referencing.
+ /// The declaration that we are referencing.
ValueDecl *D;
- /// \brief The location of the declaration name itself.
+ /// The location of the declaration name itself.
SourceLocation Loc;
- /// \brief Provides source/type location info for the declaration name
+ /// Provides source/type location info for the declaration name
/// embedded in D.
DeclarationNameLoc DNLoc;
@@ -980,7 +996,7 @@ class DeclRefExpr final
return hasTemplateKWAndArgsInfo() ? 1 : 0;
}
- /// \brief Test whether there is a distinct FoundDecl attached to the end of
+ /// Test whether there is a distinct FoundDecl attached to the end of
/// this DRE.
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
@@ -993,11 +1009,11 @@ class DeclRefExpr final
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK);
- /// \brief Construct an empty declaration reference expression.
+ /// Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
- /// \brief Computes the type- and value-dependence flags for this
+ /// Computes the type- and value-dependence flags for this
/// declaration reference expression.
void computeDependence(const ASTContext &C);
@@ -1031,7 +1047,7 @@ public:
NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
- /// \brief Construct an empty declaration reference expression.
+ /// Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(const ASTContext &Context,
bool HasQualifier,
bool HasFoundDecl,
@@ -1051,11 +1067,11 @@ public:
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
- /// \brief Determine whether this declaration reference was preceded by a
+ /// Determine whether this declaration reference was preceded by a
/// C++ nested-name-specifier, e.g., \c N::foo.
bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
- /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!hasQualifier())
@@ -1063,13 +1079,13 @@ public:
return *getTrailingObjects<NestedNameSpecifierLoc>();
}
- /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name. Otherwise, returns NULL.
NestedNameSpecifier *getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
- /// \brief Get the NamedDecl through which this reference occurred.
+ /// Get the NamedDecl through which this reference occurred.
///
/// This Decl may be different from the ValueDecl actually referred to in the
/// presence of using declarations, etc. It always returns non-NULL, and may
@@ -1079,7 +1095,7 @@ public:
return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
- /// \brief Get the NamedDecl through which this reference occurred.
+ /// Get the NamedDecl through which this reference occurred.
/// See non-const variant.
const NamedDecl *getFoundDecl() const {
return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
@@ -1089,36 +1105,36 @@ public:
return DeclRefExprBits.HasTemplateKWAndArgsInfo;
}
- /// \brief Retrieve the location of the template keyword preceding
+ /// Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
- /// \brief Retrieve the location of the left angle bracket starting the
+ /// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
- /// \brief Retrieve the location of the right angle bracket ending the
+ /// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
- /// \brief Determines whether the name in this declaration reference
+ /// Determines whether the name in this declaration reference
/// was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
- /// \brief Determines whether this declaration reference was followed by an
+ /// Determines whether this declaration reference was followed by an
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Copies the template arguments (if present) into the given
+ /// Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
@@ -1126,7 +1142,7 @@ public:
getTrailingObjects<TemplateArgumentLoc>(), List);
}
- /// \brief Retrieve the template arguments provided as part of this
+ /// Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
@@ -1135,7 +1151,7 @@ public:
return getTrailingObjects<TemplateArgumentLoc>();
}
- /// \brief Retrieve the number of template arguments provided as part of this
+ /// Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
@@ -1148,19 +1164,19 @@ public:
return {getTemplateArgs(), getNumTemplateArgs()};
}
- /// \brief Returns true if this expression refers to a function that
+ /// Returns true if this expression refers to a function that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return DeclRefExprBits.HadMultipleCandidates;
}
- /// \brief Sets the flag telling whether this expression refers to
+ /// Sets the flag telling whether this expression refers to
/// a function that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
DeclRefExprBits.HadMultipleCandidates = V;
}
- /// \brief Does this DeclRefExpr refer to an enclosing local or a captured
+ /// Does this DeclRefExpr refer to an enclosing local or a captured
/// variable?
bool refersToEnclosingVariableOrCapture() const {
return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
@@ -1184,17 +1200,18 @@ public:
friend class ASTStmtWriter;
};
-/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
+/// [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr : public Expr {
public:
enum IdentType {
Func,
Function,
- LFunction, // Same as Function, but as wide string.
+ LFunction, // Same as Function, but as wide string.
FuncDName,
FuncSig,
+ LFuncSig, // Same as FuncSig, but as as wide string
PrettyFunction,
- /// \brief The same as PrettyFunction, except that the
+ /// The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
PrettyFunctionNoVirtual
};
@@ -1208,7 +1225,7 @@ public:
PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
StringLiteral *SL);
- /// \brief Construct an empty predefined expression.
+ /// Construct an empty predefined expression.
explicit PredefinedExpr(EmptyShell Empty)
: Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
@@ -1241,7 +1258,7 @@ public:
friend class ASTStmtReader;
};
-/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
+/// Used by IntegerLiteral/FloatingLiteral to store the numeric without
/// leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
@@ -1295,7 +1312,7 @@ public:
class IntegerLiteral : public Expr, public APIntStorage {
SourceLocation Loc;
- /// \brief Construct an empty integer literal.
+ /// Construct an empty integer literal.
explicit IntegerLiteral(EmptyShell Empty)
: Expr(IntegerLiteralClass, Empty) { }
@@ -1305,19 +1322,19 @@ public:
IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
SourceLocation l);
- /// \brief Returns a new integer literal with value 'V' and type 'type'.
+ /// Returns a new integer literal with value 'V' and type 'type'.
/// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
/// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
/// \param V - the value that the returned integer literal contains.
static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l);
- /// \brief Returns a new empty integer literal.
+ /// Returns a new empty integer literal.
static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
- /// \brief Retrieve the location of the literal.
+ /// Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation Location) { Loc = Location; }
@@ -1335,6 +1352,47 @@ public:
}
};
+class FixedPointLiteral : public Expr, public APIntStorage {
+ SourceLocation Loc;
+ unsigned Scale;
+
+ /// \brief Construct an empty integer literal.
+ explicit FixedPointLiteral(EmptyShell Empty)
+ : Expr(FixedPointLiteralClass, Empty) {}
+
+ public:
+ FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
+ SourceLocation l, unsigned Scale);
+
+ // Store the int as is without any bit shifting.
+ static FixedPointLiteral *CreateFromRawInt(const ASTContext &C,
+ const llvm::APInt &V,
+ QualType type, SourceLocation l,
+ unsigned Scale);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ /// \brief Retrieve the location of the literal.
+ SourceLocation getLocation() const { return Loc; }
+
+ void setLocation(SourceLocation Location) { Loc = Location; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == FixedPointLiteralClass;
+ }
+
+ std::string getValueAsString(unsigned Radix) const;
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ const_child_range children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+};
+
class CharacterLiteral : public Expr {
public:
enum CharacterKind {
@@ -1358,7 +1416,7 @@ public:
CharacterLiteralBits.Kind = kind;
}
- /// \brief Construct an empty character literal.
+ /// Construct an empty character literal.
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
SourceLocation getLocation() const { return Loc; }
@@ -1394,7 +1452,7 @@ class FloatingLiteral : public Expr, private APFloatStorage {
FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L);
- /// \brief Construct an empty floating-point literal.
+ /// Construct an empty floating-point literal.
explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);
public:
@@ -1468,7 +1526,7 @@ public:
false, false),
Val(val) {}
- /// \brief Build an empty imaginary literal.
+ /// Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
: Expr(ImaginaryLiteralClass, Empty) { }
@@ -1551,7 +1609,7 @@ public:
return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
}
- /// \brief Construct an empty string literal.
+ /// Construct an empty string literal.
static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs);
StringRef getString() const {
@@ -1590,7 +1648,7 @@ public:
unsigned getLength() const { return Length; }
unsigned getCharByteWidth() const { return CharByteWidth; }
- /// \brief Sets the string data to the given string data.
+ /// Sets the string data to the given string data.
void setString(const ASTContext &C, StringRef Str,
StringKind Kind, bool IsPascal);
@@ -1604,6 +1662,14 @@ public:
bool isUTF32() const { return Kind == UTF32; }
bool isPascal() const { return IsPascal; }
+ bool containsNonAscii() const {
+ StringRef Str = getString();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ if (!isASCII(Str[i]))
+ return true;
+ return false;
+ }
+
bool containsNonAsciiOrNull() const {
StringRef Str = getString();
for (unsigned i = 0, e = Str.size(); i != e; ++i)
@@ -1674,7 +1740,7 @@ public:
val->containsUnexpandedParameterPack()),
L(l), R(r), Val(val) {}
- /// \brief Construct an empty parenthesized expression.
+ /// Construct an empty parenthesized expression.
explicit ParenExpr(EmptyShell Empty)
: Expr(ParenExprClass, Empty) { }
@@ -1685,11 +1751,11 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return L; }
SourceLocation getLocEnd() const LLVM_READONLY { return R; }
- /// \brief Get the location of the left parentheses '('.
+ /// Get the location of the left parentheses '('.
SourceLocation getLParen() const { return L; }
void setLParen(SourceLocation Loc) { L = Loc; }
- /// \brief Get the location of the right parentheses ')'.
+ /// Get the location of the right parentheses ')'.
SourceLocation getRParen() const { return R; }
void setRParen(SourceLocation Loc) { R = Loc; }
@@ -1720,21 +1786,21 @@ public:
private:
unsigned Opc : 5;
+ unsigned CanOverflow : 1;
SourceLocation Loc;
Stmt *Val;
public:
-
- UnaryOperator(Expr *input, Opcode opc, QualType type,
- ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
- : Expr(UnaryOperatorClass, type, VK, OK,
- input->isTypeDependent() || type->isDependentType(),
- input->isValueDependent(),
- (input->isInstantiationDependent() ||
- type->isInstantiationDependentType()),
- input->containsUnexpandedParameterPack()),
- Opc(opc), Loc(l), Val(input) {}
-
- /// \brief Build an empty unary operator.
+ UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation l, bool CanOverflow)
+ : Expr(UnaryOperatorClass, type, VK, OK,
+ input->isTypeDependent() || type->isDependentType(),
+ input->isValueDependent(),
+ (input->isInstantiationDependent() ||
+ type->isInstantiationDependentType()),
+ input->containsUnexpandedParameterPack()),
+ Opc(opc), CanOverflow(CanOverflow), Loc(l), Val(input) {}
+
+ /// Build an empty unary operator.
explicit UnaryOperator(EmptyShell Empty)
: Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
@@ -1748,6 +1814,15 @@ public:
SourceLocation getOperatorLoc() const { return Loc; }
void setOperatorLoc(SourceLocation L) { Loc = L; }
+ /// Returns true if the unary operator can cause an overflow. For instance,
+ /// signed int i = INT_MAX; i++;
+ /// signed char c = CHAR_MAX; c++;
+ /// Due to integer promotions, c++ is promoted to an int before the postfix
+ /// increment, and the result is an int that cannot overflow. However, i++
+ /// can overflow.
+ bool canOverflow() const { return CanOverflow; }
+ void setCanOverflow(bool C) { CanOverflow = C; }
+
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op) {
return Op == UO_PostInc || Op == UO_PostDec;
@@ -1789,11 +1864,11 @@ public:
/// corresponds to, e.g. "sizeof" or "[pre]++"
static StringRef getOpcodeStr(Opcode Op);
- /// \brief Retrieve the unary opcode that corresponds to the given
+ /// Retrieve the unary opcode that corresponds to the given
/// overloaded operator.
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix);
- /// \brief Retrieve the overloaded operator kind that corresponds to
+ /// Retrieve the overloaded operator kind that corresponds to
/// the given unary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
@@ -1821,15 +1896,15 @@ public:
// __builtin_offsetof(type, identifier(.identifier|[expr])*)
class OffsetOfNode {
public:
- /// \brief The kind of offsetof node we have.
+ /// The kind of offsetof node we have.
enum Kind {
- /// \brief An index into an array.
+ /// An index into an array.
Array = 0x00,
- /// \brief A field.
+ /// A field.
Field = 0x01,
- /// \brief A field in a dependent type, known only by its name.
+ /// A field in a dependent type, known only by its name.
Identifier = 0x02,
- /// \brief An implicit indirection through a C++ base class, when the
+ /// An implicit indirection through a C++ base class, when the
/// field found is in a base class.
Base = 0x03
};
@@ -1837,10 +1912,10 @@ public:
private:
enum { MaskBits = 2, Mask = 0x03 };
- /// \brief The source range that covers this part of the designator.
+ /// The source range that covers this part of the designator.
SourceRange Range;
- /// \brief The data describing the designator, which comes in three
+ /// The data describing the designator, which comes in three
/// different forms, depending on the lower two bits.
/// - An unsigned index into the array of Expr*'s stored after this node
/// in memory, for [constant-expression] designators.
@@ -1852,53 +1927,53 @@ private:
uintptr_t Data;
public:
- /// \brief Create an offsetof node that refers to an array element.
+ /// Create an offsetof node that refers to an array element.
OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
SourceLocation RBracketLoc)
: Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {}
- /// \brief Create an offsetof node that refers to a field.
+ /// Create an offsetof node that refers to a field.
OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc)
: Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {}
- /// \brief Create an offsetof node that refers to an identifier.
+ /// Create an offsetof node that refers to an identifier.
OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
SourceLocation NameLoc)
: Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {}
- /// \brief Create an offsetof node that refers into a C++ base class.
+ /// Create an offsetof node that refers into a C++ base class.
explicit OffsetOfNode(const CXXBaseSpecifier *Base)
: Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
- /// \brief Determine what kind of offsetof node this is.
+ /// Determine what kind of offsetof node this is.
Kind getKind() const { return static_cast<Kind>(Data & Mask); }
- /// \brief For an array element node, returns the index into the array
+ /// For an array element node, returns the index into the array
/// of expressions.
unsigned getArrayExprIndex() const {
assert(getKind() == Array);
return Data >> 2;
}
- /// \brief For a field offsetof node, returns the field.
+ /// For a field offsetof node, returns the field.
FieldDecl *getField() const {
assert(getKind() == Field);
return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
}
- /// \brief For a field or identifier offsetof node, returns the name of
+ /// For a field or identifier offsetof node, returns the name of
/// the field.
IdentifierInfo *getFieldName() const;
- /// \brief For a base class node, returns the base specifier.
+ /// For a base class node, returns the base specifier.
CXXBaseSpecifier *getBase() const {
assert(getKind() == Base);
return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
}
- /// \brief Retrieve the source range that covers this offsetof node.
+ /// Retrieve the source range that covers this offsetof node.
///
/// For an array element node, the source range contains the locations of
/// the square brackets. For a field or identifier node, the source range
@@ -1961,7 +2036,7 @@ public:
SourceLocation getOperatorLoc() const { return OperatorLoc; }
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
- /// \brief Return the location of the right parentheses.
+ /// Return the location of the right parentheses.
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation R) { RParenLoc = R; }
@@ -2055,7 +2130,7 @@ public:
QualType resultType, SourceLocation op,
SourceLocation rp);
- /// \brief Construct an empty sizeof/alignof expression.
+ /// Construct an empty sizeof/alignof expression.
explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
: Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
@@ -2138,7 +2213,7 @@ public:
SubExprs[RHS] = rhs;
}
- /// \brief Create an empty array subscript expression.
+ /// Create an empty array subscript expression.
explicit ArraySubscriptExpr(EmptyShell Shell)
: Expr(ArraySubscriptExprClass, Shell) { }
@@ -2160,19 +2235,19 @@ public:
void setRHS(Expr *E) { SubExprs[RHS] = E; }
Expr *getBase() {
- return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
+ return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS();
}
const Expr *getBase() const {
- return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
+ return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS();
}
Expr *getIdx() {
- return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
+ return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS();
}
const Expr *getIdx() const {
- return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
+ return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS();
}
SourceLocation getLocStart() const LLVM_READONLY {
@@ -2243,7 +2318,7 @@ public:
CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
ExprValueKind VK, SourceLocation rparenloc);
- /// \brief Build an empty call expression.
+ /// Build an empty call expression.
CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty);
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
@@ -2255,7 +2330,7 @@ public:
return const_cast<CallExpr*>(this)->getCalleeDecl();
}
- /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
+ /// If the callee is a FunctionDecl, return it. Otherwise return 0.
FunctionDecl *getDirectCallee();
const FunctionDecl *getDirectCallee() const {
return const_cast<CallExpr*>(this)->getDirectCallee();
@@ -2265,7 +2340,7 @@ public:
///
unsigned getNumArgs() const { return NumArgs; }
- /// \brief Retrieve the call arguments.
+ /// Retrieve the call arguments.
Expr **getArgs() {
return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
}
@@ -2333,7 +2408,7 @@ public:
/// of the callee. If not, return 0.
unsigned getBuiltinCallee() const;
- /// \brief Returns \c true if this is a call to a builtin which does not
+ /// Returns \c true if this is a call to a builtin which does not
/// evaluate side-effects within its arguments.
bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const;
@@ -2348,6 +2423,10 @@ public:
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
+ /// Return true if this is a call to __assume() or __builtin_assume() with
+ /// a non-value-dependent constant parameter evaluating as false.
+ bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;
+
bool isCallToStdMove() const {
const FunctionDecl* FD = getDirectCallee();
return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
@@ -2373,11 +2452,11 @@ public:
/// Extra data stored in some MemberExpr objects.
struct MemberExprNameQualifier {
- /// \brief The nested-name-specifier that qualifies the name, including
+ /// The nested-name-specifier that qualifies the name, including
/// source-location information.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief The DeclAccessPair through which the MemberDecl was found due to
+ /// The DeclAccessPair through which the MemberDecl was found due to
/// name qualifiers.
DeclAccessPair FoundDecl;
};
@@ -2410,20 +2489,20 @@ class MemberExpr final
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
- /// \brief True if this member expression used a nested-name-specifier to
+ /// True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f", or found its member via a using
/// declaration. When true, a MemberExprNameQualifier
/// structure is allocated immediately after the MemberExpr.
bool HasQualifierOrFoundDecl : 1;
- /// \brief True if this member expression specified a template keyword
+ /// True if this member expression specified a template keyword
/// and/or a template argument list explicitly, e.g., x->f<int>,
/// x->template f, x->template f<int>.
/// When true, an ASTTemplateKWAndArgsInfo structure and its
/// TemplateArguments (if any) are present.
bool HasTemplateKWAndArgsInfo : 1;
- /// \brief True if this member expression refers to a method that
+ /// True if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool HadMultipleCandidates : 1;
@@ -2476,14 +2555,14 @@ public:
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
- /// \brief Retrieve the member declaration to which this expression refers.
+ /// Retrieve the member declaration to which this expression refers.
///
/// The returned declaration will be a FieldDecl or (in C++) a VarDecl (for
/// static data members), a CXXMethodDecl, or an EnumConstantDecl.
ValueDecl *getMemberDecl() const { return MemberDecl; }
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
- /// \brief Retrieves the declaration found by lookup.
+ /// Retrieves the declaration found by lookup.
DeclAccessPair getFoundDecl() const {
if (!HasQualifierOrFoundDecl)
return DeclAccessPair::make(getMemberDecl(),
@@ -2491,12 +2570,12 @@ public:
return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
}
- /// \brief Determines whether this member expression actually had
+ /// Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
bool hasQualifier() const { return getQualifier() != nullptr; }
- /// \brief If the member name was qualified, retrieves the
+ /// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
@@ -2506,28 +2585,28 @@ public:
return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
}
- /// \brief If the member name was qualified, retrieves the
+ /// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
- /// \brief Retrieve the location of the template keyword preceding
+ /// Retrieve the location of the template keyword preceding
/// the member name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
- /// \brief Retrieve the location of the left angle bracket starting the
+ /// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
- /// \brief Retrieve the location of the right angle bracket ending the
+ /// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
@@ -2537,11 +2616,11 @@ public:
/// Determines whether the member name was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
- /// \brief Determines whether the member name was followed by an
+ /// Determines whether the member name was followed by an
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Copies the template arguments (if present) into the given
+ /// Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
@@ -2549,7 +2628,7 @@ public:
getTrailingObjects<TemplateArgumentLoc>(), List);
}
- /// \brief Retrieve the template arguments provided as part of this
+ /// Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
@@ -2558,7 +2637,7 @@ public:
return getTrailingObjects<TemplateArgumentLoc>();
}
- /// \brief Retrieve the number of template arguments provided as part of this
+ /// Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
@@ -2571,7 +2650,7 @@ public:
return {getTemplateArgs(), getNumTemplateArgs()};
}
- /// \brief Retrieve the member declaration name info.
+ /// Retrieve the member declaration name info.
DeclarationNameInfo getMemberNameInfo() const {
return DeclarationNameInfo(MemberDecl->getDeclName(),
MemberLoc, MemberDNLoc);
@@ -2592,24 +2671,24 @@ public:
SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }
- /// \brief Determine whether the base of this explicit is implicit.
+ /// Determine whether the base of this explicit is implicit.
bool isImplicitAccess() const {
return getBase() && getBase()->isImplicitCXXThis();
}
- /// \brief Returns true if this member expression refers to a method that
+ /// Returns true if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return HadMultipleCandidates;
}
- /// \brief Sets the flag telling whether this expression refers to
+ /// Sets the flag telling whether this expression refers to
/// a method that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
HadMultipleCandidates = V;
}
- /// \brief Returns true if virtual dispatch is performed.
+ /// Returns true if virtual dispatch is performed.
/// If the member access is fully qualified, (i.e. X::f()), virtual
/// dispatching is not performed. In -fapple-kext mode qualified
/// calls to virtual method will still go through the vtable.
@@ -2656,7 +2735,7 @@ public:
init->containsUnexpandedParameterPack()),
LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {}
- /// \brief Construct an empty compound literal.
+ /// Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
: Expr(CompoundLiteralExprClass, Empty) { }
@@ -2708,20 +2787,26 @@ public:
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
+public:
+ using BasePathSizeTy = unsigned int;
+ static_assert(std::numeric_limits<BasePathSizeTy>::max() >= 16384,
+ "[implimits] Direct and indirect base classes [16384].");
+
private:
Stmt *Op;
bool CastConsistency() const;
+ BasePathSizeTy *BasePathSize();
+
const CXXBaseSpecifier * const *path_buffer() const {
return const_cast<CastExpr*>(this)->path_buffer();
}
CXXBaseSpecifier **path_buffer();
- void setBasePathSize(unsigned basePathSize) {
- CastExprBits.BasePathSize = basePathSize;
- assert(CastExprBits.BasePathSize == basePathSize &&
- "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!");
+ void setBasePathSize(BasePathSizeTy basePathSize) {
+ assert(!path_empty() && basePathSize != 0);
+ *(BasePathSize()) = basePathSize;
}
protected:
@@ -2743,26 +2828,34 @@ protected:
(op && op->containsUnexpandedParameterPack()))),
Op(op) {
CastExprBits.Kind = kind;
- setBasePathSize(BasePathSize);
+ CastExprBits.PartOfExplicitCast = false;
+ CastExprBits.BasePathIsEmpty = BasePathSize == 0;
+ if (!path_empty())
+ setBasePathSize(BasePathSize);
assert(CastConsistency());
}
- /// \brief Construct an empty cast.
+ /// Construct an empty cast.
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
: Expr(SC, Empty) {
- setBasePathSize(BasePathSize);
+ CastExprBits.PartOfExplicitCast = false;
+ CastExprBits.BasePathIsEmpty = BasePathSize == 0;
+ if (!path_empty())
+ setBasePathSize(BasePathSize);
}
public:
CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
void setCastKind(CastKind K) { CastExprBits.Kind = K; }
- const char *getCastKindName() const;
+
+ static const char *getCastKindName(CastKind CK);
+ const char *getCastKindName() const { return getCastKindName(getCastKind()); }
Expr *getSubExpr() { return cast<Expr>(Op); }
const Expr *getSubExpr() const { return cast<Expr>(Op); }
void setSubExpr(Expr *E) { Op = E; }
- /// \brief Retrieve the cast subexpression as it was written in the source
+ /// Retrieve the cast subexpression as it was written in the source
/// code, looking through any implicit casts or other intermediate nodes
/// introduced by semantic analysis.
Expr *getSubExprAsWritten();
@@ -2770,10 +2863,18 @@ public:
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
}
+ /// If this cast applies a user-defined conversion, retrieve the conversion
+ /// function that it invokes.
+ NamedDecl *getConversionFunction() const;
+
typedef CXXBaseSpecifier **path_iterator;
typedef const CXXBaseSpecifier * const *path_const_iterator;
- bool path_empty() const { return CastExprBits.BasePathSize == 0; }
- unsigned path_size() const { return CastExprBits.BasePathSize; }
+ bool path_empty() const { return CastExprBits.BasePathIsEmpty; }
+ unsigned path_size() const {
+ if (path_empty())
+ return 0U;
+ return *(const_cast<CastExpr *>(this)->BasePathSize());
+ }
path_iterator path_begin() { return path_buffer(); }
path_iterator path_end() { return path_buffer() + path_size(); }
path_const_iterator path_begin() const { return path_buffer(); }
@@ -2821,14 +2922,19 @@ public:
/// @endcode
class ImplicitCastExpr final
: public CastExpr,
- private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<ImplicitCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
}
- /// \brief Construct an empty implicit cast.
+ /// Construct an empty implicit cast.
explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
: CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
@@ -2839,6 +2945,11 @@ public:
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
}
+ bool isPartOfExplicitCast() const { return CastExprBits.PartOfExplicitCast; }
+ void setIsPartOfExplicitCast(bool PartOfExplicitCast) {
+ CastExprBits.PartOfExplicitCast = PartOfExplicitCast;
+ }
+
static ImplicitCastExpr *Create(const ASTContext &Context, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
@@ -2896,7 +3007,7 @@ protected:
TypeSourceInfo *writtenTy)
: CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
- /// \brief Construct an empty explicit cast.
+ /// Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
: CastExpr(SC, Shell, PathSize) { }
@@ -2921,7 +3032,8 @@ public:
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CStyleCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
@@ -2931,10 +3043,14 @@ class CStyleCastExpr final
: ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
- /// \brief Construct an empty C-style explicit cast.
+ /// Construct an empty C-style explicit cast.
explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
static CStyleCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K,
@@ -2964,7 +3080,7 @@ public:
friend class CastExpr;
};
-/// \brief A builtin binary operation expression such as "x + y" or "x <= y".
+/// A builtin binary operation expression such as "x + y" or "x <= y".
///
/// This expression node kind describes a builtin binary operation,
/// such as "x + y" for integer values "x" and "y". The operands will
@@ -3015,7 +3131,7 @@ public:
"Use CompoundAssignOperator for compound assignments");
}
- /// \brief Construct an empty binary operator.
+ /// Construct an empty binary operator.
explicit BinaryOperator(EmptyShell Empty)
: Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
@@ -3044,11 +3160,11 @@ public:
StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); }
- /// \brief Retrieve the binary opcode that corresponds to the given
+ /// Retrieve the binary opcode that corresponds to the given
/// overloaded operator.
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);
- /// \brief Retrieve the overloaded operator kind that corresponds to
+ /// Retrieve the overloaded operator kind that corresponds to
/// the given binary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
@@ -3078,7 +3194,7 @@ public:
static Opcode negateComparisonOp(Opcode Opc) {
switch (Opc) {
default:
- llvm_unreachable("Not a comparsion operator.");
+ llvm_unreachable("Not a comparison operator.");
case BO_LT: return BO_GE;
case BO_GT: return BO_LE;
case BO_LE: return BO_GT;
@@ -3091,7 +3207,7 @@ public:
static Opcode reverseComparisonOp(Opcode Opc) {
switch (Opc) {
default:
- llvm_unreachable("Not a comparsion operator.");
+ llvm_unreachable("Not a comparison operator.");
case BO_LT: return BO_GT;
case BO_GT: return BO_LT;
case BO_LE: return BO_GE;
@@ -3204,7 +3320,7 @@ public:
"Only should be used for compound assignments");
}
- /// \brief Build an empty compound assignment operator expression.
+ /// Build an empty compound assignment operator expression.
explicit CompoundAssignOperator(EmptyShell Empty)
: BinaryOperator(CompoundAssignOperatorClass, Empty) { }
@@ -3294,7 +3410,7 @@ public:
SubExprs[RHS] = rhs;
}
- /// \brief Build an empty conditional operator.
+ /// Build an empty conditional operator.
explicit ConditionalOperator(EmptyShell Empty)
: AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
@@ -3372,30 +3488,30 @@ public:
assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value");
}
- /// \brief Build an empty conditional operator.
+ /// Build an empty conditional operator.
explicit BinaryConditionalOperator(EmptyShell Empty)
: AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { }
- /// \brief getCommon - Return the common expression, written to the
+ /// getCommon - Return the common expression, written to the
/// left of the condition. The opaque value will be bound to the
/// result of this expression.
Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); }
- /// \brief getOpaqueValue - Return the opaque value placeholder.
+ /// getOpaqueValue - Return the opaque value placeholder.
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
- /// \brief getCond - Return the condition expression; this is defined
+ /// getCond - Return the condition expression; this is defined
/// in terms of the opaque value.
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
- /// \brief getTrueExpr - Return the subexpression which will be
+ /// getTrueExpr - Return the subexpression which will be
/// evaluated if the condition evaluates to true; this is defined
/// in terms of the opaque value.
Expr *getTrueExpr() const {
return cast<Expr>(SubExprs[LHS]);
}
- /// \brief getFalseExpr - Return the subexpression which will be
+ /// getFalseExpr - Return the subexpression which will be
/// evaluated if the condnition evaluates to false; this is
/// defined in terms of the opaque value.
Expr *getFalseExpr() const {
@@ -3451,7 +3567,7 @@ public:
false),
AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
- /// \brief Build an empty address of a label expression.
+ /// Build an empty address of a label expression.
explicit AddrLabelExpr(EmptyShell Empty)
: Expr(AddrLabelExprClass, Empty) { }
@@ -3498,7 +3614,7 @@ public:
T->isDependentType(), false, false, false),
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
- /// \brief Build an empty statement expression.
+ /// Build an empty statement expression.
explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); }
@@ -3544,7 +3660,7 @@ public:
ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type,
SourceLocation BLoc, SourceLocation RP);
- /// \brief Build an empty vector-shuffle expression.
+ /// Build an empty vector-shuffle expression.
explicit ShuffleVectorExpr(EmptyShell Empty)
: Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { }
@@ -3566,7 +3682,7 @@ public:
/// pointers.
unsigned getNumSubExprs() const { return NumExprs; }
- /// \brief Retrieve the array of expressions.
+ /// Retrieve the array of expressions.
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
/// getExpr - Return the Expr at the specified index.
@@ -3684,7 +3800,7 @@ public:
SubExprs[RHS] = rhs;
}
- /// \brief Build an empty __builtin_choose_expr.
+ /// Build an empty __builtin_choose_expr.
explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { }
/// isConditionTrue - Return whether the condition is true (i.e. not
@@ -3751,7 +3867,7 @@ public:
false),
TokenLoc(Loc) { }
- /// \brief Build an empty GNU __null expression.
+ /// Build an empty GNU __null expression.
explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
/// getTokenLocation - The location of the __null token.
@@ -3824,7 +3940,7 @@ public:
}
};
-/// @brief Describes an C or C++ initializer list.
+/// Describes an C or C++ initializer list.
///
/// InitListExpr describes an initializer list, which can be used to
/// initialize objects of different types, including
@@ -3882,7 +3998,7 @@ class InitListExpr : public Expr {
/// - the semantic form, if this is in syntactic form.
llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm;
- /// \brief Either:
+ /// Either:
/// If this initializer list initializes an array with more elements than
/// there are initializers in the list, specifies an expression to be used
/// for value initialization of the rest of the elements.
@@ -3895,16 +4011,16 @@ public:
InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc);
- /// \brief Build an empty initializer list.
+ /// Build an empty initializer list.
explicit InitListExpr(EmptyShell Empty)
: Expr(InitListExprClass, Empty), AltForm(nullptr, true) { }
unsigned getNumInits() const { return InitExprs.size(); }
- /// \brief Retrieve the set of initializers.
+ /// Retrieve the set of initializers.
Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
- /// \brief Retrieve the set of initializers.
+ /// Retrieve the set of initializers.
Expr * const *getInits() const {
return reinterpret_cast<Expr * const *>(InitExprs.data());
}
@@ -3940,10 +4056,10 @@ public:
}
}
- /// \brief Reserve space for some number of initializers.
+ /// Reserve space for some number of initializers.
void reserveInits(const ASTContext &C, unsigned NumInits);
- /// @brief Specify the number of initializers
+ /// Specify the number of initializers
///
/// If there are more than @p NumInits initializers, the remaining
/// initializers will be destroyed. If there are fewer than @p
@@ -3951,7 +4067,7 @@ public:
/// unknown initializers.
void resizeInits(const ASTContext &Context, unsigned NumInits);
- /// @brief Updates the initializer at index @p Init with the new
+ /// Updates the initializer at index @p Init with the new
/// expression @p expr, and returns the old expression at that
/// location.
///
@@ -3960,7 +4076,7 @@ public:
/// accommodate the new entry.
Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr);
- /// \brief If this initializer list initializes an array with more elements
+ /// If this initializer list initializes an array with more elements
/// than there are initializers in the list, specifies an expression to be
/// used for value initialization of the rest of the elements.
Expr *getArrayFiller() {
@@ -3971,11 +4087,11 @@ public:
}
void setArrayFiller(Expr *filler);
- /// \brief Return true if this is an array initializer and its array "filler"
+ /// Return true if this is an array initializer and its array "filler"
/// has been set.
bool hasArrayFiller() const { return getArrayFiller(); }
- /// \brief If this initializes a union, specifies which field in the
+ /// If this initializes a union, specifies which field in the
/// union to initialize.
///
/// Typically, this field is the first named field within the
@@ -4083,7 +4199,7 @@ public:
friend class ASTStmtWriter;
};
-/// @brief Represents a C99 designated initializer expression.
+/// Represents a C99 designated initializer expression.
///
/// A designated initializer expression (C99 6.7.8) contains one or
/// more designators (which can be field designators, array
@@ -4107,7 +4223,7 @@ class DesignatedInitExpr final
: public Expr,
private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> {
public:
- /// \brief Forward declaration of the Designator class.
+ /// Forward declaration of the Designator class.
class Designator;
private:
@@ -4127,7 +4243,7 @@ private:
/// expressions used by array and array-range designators.
unsigned NumSubExprs : 16;
- /// \brief The designators in this designated initialization
+ /// The designators in this designated initialization
/// expression.
Designator *Designators;
@@ -4172,14 +4288,14 @@ public:
unsigned RBracketLoc;
};
- /// @brief Represents a single C99 designator.
+ /// Represents a single C99 designator.
///
/// @todo This class is infuriatingly similar to clang::Designator,
/// but minor differences (storing indices vs. storing pointers)
/// keep us from reusing it. Try harder, later, to rectify these
/// differences.
class Designator {
- /// @brief The kind of designator this describes.
+ /// The kind of designator this describes.
enum {
FieldDesignator,
ArrayDesignator,
@@ -4197,7 +4313,7 @@ public:
public:
Designator() {}
- /// @brief Initializes a field designator.
+ /// Initializes a field designator.
Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
SourceLocation FieldLoc)
: Kind(FieldDesignator) {
@@ -4206,7 +4322,7 @@ public:
Field.FieldLoc = FieldLoc.getRawEncoding();
}
- /// @brief Initializes an array designator.
+ /// Initializes an array designator.
Designator(unsigned Index, SourceLocation LBracketLoc,
SourceLocation RBracketLoc)
: Kind(ArrayDesignator) {
@@ -4216,7 +4332,7 @@ public:
ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
}
- /// @brief Initializes a GNU array-range designator.
+ /// Initializes a GNU array-range designator.
Designator(unsigned Index, SourceLocation LBracketLoc,
SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
: Kind(ArrayRangeDesignator) {
@@ -4302,7 +4418,7 @@ public:
static DesignatedInitExpr *CreateEmpty(const ASTContext &C,
unsigned NumIndexExprs);
- /// @brief Returns the number of designators in this initializer.
+ /// Returns the number of designators in this initializer.
unsigned size() const { return NumDesignators; }
// Iterator access to the designators.
@@ -4326,17 +4442,17 @@ public:
Expr *getArrayRangeStart(const Designator &D) const;
Expr *getArrayRangeEnd(const Designator &D) const;
- /// @brief Retrieve the location of the '=' that precedes the
+ /// Retrieve the location of the '=' that precedes the
/// initializer value itself, if present.
SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }
- /// @brief Determines whether this designated initializer used the
+ /// Determines whether this designated initializer used the
/// deprecated GNU syntax for designated initializers.
bool usesGNUSyntax() const { return GNUSyntax; }
void setGNUSyntax(bool GNU) { GNUSyntax = GNU; }
- /// @brief Retrieve the initializer value.
+ /// Retrieve the initializer value.
Expr *getInit() const {
return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin());
}
@@ -4345,7 +4461,7 @@ public:
*child_begin() = init;
}
- /// \brief Retrieve the total number of subexpressions in this
+ /// Retrieve the total number of subexpressions in this
/// designated initializer expression, including the actual
/// initialized value and any expressions that occur within array
/// and array-range designators.
@@ -4361,7 +4477,7 @@ public:
getTrailingObjects<Stmt *>()[Idx] = E;
}
- /// \brief Replaces the designator at index @p Idx with the series
+ /// Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
void ExpandDesignator(const ASTContext &C, unsigned Idx,
const Designator *First, const Designator *Last);
@@ -4388,7 +4504,7 @@ public:
friend TrailingObjects;
};
-/// \brief Represents a place-holder for an object not to be initialized by
+/// Represents a place-holder for an object not to be initialized by
/// anything.
///
/// This only makes sense when it appears as part of an updater of a
@@ -4471,7 +4587,7 @@ public:
}
};
-/// \brief Represents a loop initializing the elements of an array.
+/// Represents a loop initializing the elements of an array.
///
/// The need to initialize the elements of an array occurs in a number of
/// contexts:
@@ -4539,7 +4655,7 @@ public:
friend class ASTStmtWriter;
};
-/// \brief Represents the index of the current element of an array being
+/// Represents the index of the current element of an array being
/// initialized by an ArrayInitLoopExpr. This can only appear within the
/// subexpression of an ArrayInitLoopExpr.
class ArrayInitIndexExpr : public Expr {
@@ -4569,7 +4685,7 @@ public:
friend class ASTStmtReader;
};
-/// \brief Represents an implicitly-generated value initialization of
+/// Represents an implicitly-generated value initialization of
/// an object of a given type.
///
/// Implicit value initializations occur within semantic initializer
@@ -4583,7 +4699,7 @@ public:
: Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary,
false, false, ty->isInstantiationDependentType(), false) { }
- /// \brief Construct an empty implicit value initialization.
+ /// Construct an empty implicit value initialization.
explicit ImplicitValueInitExpr(EmptyShell Empty)
: Expr(ImplicitValueInitExprClass, Empty) { }
@@ -4612,7 +4728,7 @@ public:
ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
ArrayRef<Expr*> exprs, SourceLocation rparenloc);
- /// \brief Build an empty paren list.
+ /// Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
unsigned getNumExprs() const { return NumExprs; }
@@ -4655,7 +4771,7 @@ public:
friend class ASTStmtWriter;
};
-/// \brief Represents a C11 generic selection.
+/// Represents a C11 generic selection.
///
/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
/// expression, followed by one or more generic associations. Each generic
@@ -4801,7 +4917,7 @@ public:
base->containsUnexpandedParameterPack()),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
- /// \brief Build an empty vector element expression.
+ /// Build an empty vector element expression.
explicit ExtVectorElementExpr(EmptyShell Empty)
: Expr(ExtVectorElementExprClass, Empty) { }
@@ -4859,7 +4975,7 @@ public:
false),
TheBlock(BD) {}
- /// \brief Build an empty block expression.
+ /// Build an empty block expression.
explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }
const BlockDecl *getBlockDecl() const { return TheBlock; }
@@ -5111,7 +5227,7 @@ public:
};
private:
- /// \brief Location of sub-expressions.
+ /// 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 };
@@ -5125,11 +5241,11 @@ public:
AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t,
AtomicOp op, SourceLocation RP);
- /// \brief Determine the number of arguments the specified atomic builtin
+ /// Determine the number of arguments the specified atomic builtin
/// should have.
static unsigned getNumSubExprs(AtomicOp Op);
- /// \brief Build an empty AtomicExpr.
+ /// Build an empty AtomicExpr.
explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { }
Expr *getPtr() const {
@@ -5208,7 +5324,7 @@ public:
return const_child_range(SubExprs, SubExprs + NumSubExprs);
}
- /// \brief Get atomic scope model for the atomic op code.
+ /// 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) {
@@ -5219,7 +5335,7 @@ public:
return AtomicScopeModel::create(Kind);
}
- /// \brief Get atomic scope model.
+ /// Get atomic scope model.
/// \return empty atomic scope model if this atomic expression does not have
/// scope operand.
std::unique_ptr<AtomicScopeModel> getScopeModel() const {
@@ -5249,7 +5365,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == TypoExprClass;
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
index 58054dda31aa..7ab8020dec64 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::Expr interface and subclasses for C++ expressions.
+/// Defines the clang::Expr interface and subclasses for C++ expressions.
//
//===----------------------------------------------------------------------===//
@@ -62,7 +62,7 @@ class TemplateParameterList;
// C++ Expressions.
//===--------------------------------------------------------------------===//
-/// \brief A call to an overloaded operator written using operator
+/// A call to an overloaded operator written using operator
/// syntax.
///
/// Represents a call to an overloaded operator written using operator
@@ -76,7 +76,7 @@ class TemplateParameterList;
/// function templates that were found by name lookup at template
/// definition time.
class CXXOperatorCallExpr : public CallExpr {
- /// \brief The overloaded operator.
+ /// The overloaded operator.
OverloadedOperatorKind Operator;
SourceRange Range;
@@ -101,7 +101,7 @@ public:
explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty)
: CallExpr(C, CXXOperatorCallExprClass, Empty) {}
- /// \brief Returns the kind of overloaded operator that this
+ /// Returns the kind of overloaded operator that this
/// expression refers to.
OverloadedOperatorKind getOperator() const { return Operator; }
@@ -115,10 +115,10 @@ public:
}
bool isAssignmentOp() const { return isAssignmentOp(getOperator()); }
- /// \brief Is this written as an infix binary operator?
+ /// Is this written as an infix binary operator?
bool isInfixBinaryOp() const;
- /// \brief Returns the location of the operator symbol in the expression.
+ /// Returns the location of the operator symbol in the expression.
///
/// When \c getOperator()==OO_Call, this is the location of the right
/// parentheses; when \c getOperator()==OO_Subscript, this is the location
@@ -170,15 +170,15 @@ public:
CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
: CallExpr(C, CXXMemberCallExprClass, Empty) {}
- /// \brief Retrieves the implicit object argument for the member call.
+ /// Retrieves the implicit object argument for the member call.
///
/// For example, in "x.f(5)", this returns the sub-expression "x".
Expr *getImplicitObjectArgument() const;
- /// \brief Retrieves the declaration of the called method.
+ /// Retrieves the declaration of the called method.
CXXMethodDecl *getMethodDecl() const;
- /// \brief Retrieves the CXXRecordDecl for the underlying type of
+ /// Retrieves the CXXRecordDecl for the underlying type of
/// the implicit object argument.
///
/// Note that this is may not be the same declaration as that of the class
@@ -199,7 +199,7 @@ public:
}
};
-/// \brief Represents a call to a CUDA kernel function.
+/// Represents a call to a CUDA kernel function.
class CUDAKernelCallExpr : public CallExpr {
private:
enum { CONFIG, END_PREARG };
@@ -218,7 +218,7 @@ public:
}
CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); }
- /// \brief Sets the kernel configuration expression.
+ /// Sets the kernel configuration expression.
///
/// Note that this method cannot be called if config has already been set to a
/// non-null value.
@@ -237,7 +237,7 @@ public:
}
};
-/// \brief Abstract class common to all of the C++ "named"/"keyword" casts.
+/// Abstract class common to all of the C++ "named"/"keyword" casts.
///
/// This abstract class is inherited by all of the classes
/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
@@ -271,11 +271,11 @@ protected:
public:
const char *getCastName() const;
- /// \brief Retrieve the location of the cast operator keyword, e.g.,
+ /// Retrieve the location of the cast operator keyword, e.g.,
/// \c static_cast.
SourceLocation getOperatorLoc() const { return Loc; }
- /// \brief Retrieve the location of the closing parenthesis.
+ /// Retrieve the location of the closing parenthesis.
SourceLocation getRParenLoc() const { return RParenLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
@@ -295,13 +295,14 @@ public:
}
};
-/// \brief A C++ \c static_cast expression (C++ [expr.static.cast]).
+/// A C++ \c static_cast expression (C++ [expr.static.cast]).
///
/// This expression node represents a C++ static cast, e.g.,
/// \c static_cast<int>(1.0).
class CXXStaticCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXStaticCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -312,6 +313,10 @@ class CXXStaticCastExpr final
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -330,14 +335,15 @@ public:
}
};
-/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
+/// A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
///
/// This expression node represents a dynamic cast, e.g.,
/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time
/// check to determine how to perform the type conversion.
class CXXDynamicCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<
+ CXXDynamicCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -348,6 +354,10 @@ class CXXDynamicCastExpr final
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -369,7 +379,7 @@ public:
}
};
-/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
+/// A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
///
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
@@ -380,6 +390,7 @@ public:
class CXXReinterpretCastExpr final
: public CXXNamedCastExpr,
private llvm::TrailingObjects<CXXReinterpretCastExpr,
+ CastExpr::BasePathSizeTy,
CXXBaseSpecifier *> {
CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
Expr *op, unsigned pathSize,
@@ -392,6 +403,10 @@ class CXXReinterpretCastExpr final
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -410,7 +425,7 @@ public:
}
};
-/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]).
+/// A C++ \c const_cast expression (C++ [expr.const.cast]).
///
/// This expression node represents a const cast, e.g.,
/// \c const_cast<char*>(PtrToConstChar).
@@ -419,7 +434,8 @@ public:
/// value.
class CXXConstCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXConstCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc, SourceRange AngleBrackets)
@@ -429,6 +445,10 @@ class CXXConstCastExpr final
explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -445,7 +465,7 @@ public:
}
};
-/// \brief A call to a literal operator (C++11 [over.literal])
+/// A call to a literal operator (C++11 [over.literal])
/// written as a user-defined literal (C++11 [lit.ext]).
///
/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this
@@ -455,7 +475,7 @@ public:
/// Since literal operators are never found by ADL and can only be declared at
/// namespace scope, a user-defined literal is never dependent.
class UserDefinedLiteral : public CallExpr {
- /// \brief The location of a ud-suffix within the literal.
+ /// The location of a ud-suffix within the literal.
SourceLocation UDSuffixLoc;
public:
@@ -492,11 +512,11 @@ public:
LOK_Character
};
- /// \brief Returns the kind of literal operator invocation
+ /// Returns the kind of literal operator invocation
/// which this expression represents.
LiteralOperatorKind getLiteralOperatorKind() const;
- /// \brief If this is not a raw user-defined literal, get the
+ /// If this is not a raw user-defined literal, get the
/// underlying cooked literal (representing the literal with the suffix
/// removed).
Expr *getCookedLiteral();
@@ -512,13 +532,13 @@ public:
SourceLocation getLocEnd() const { return getRParenLoc(); }
- /// \brief Returns the location of a ud-suffix in the expression.
+ /// Returns the location of a ud-suffix in the expression.
///
/// For a string literal, there may be multiple identical suffixes. This
/// returns the first.
SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; }
- /// \brief Returns the ud-suffix specified for this literal.
+ /// Returns the ud-suffix specified for this literal.
const IdentifierInfo *getUDSuffix() const;
static bool classof(const Stmt *S) {
@@ -526,7 +546,7 @@ public:
}
};
-/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals).
+/// A boolean literal, per ([C++ lex.bool] Boolean literals).
class CXXBoolLiteralExpr : public Expr {
bool Value;
SourceLocation Loc;
@@ -559,7 +579,7 @@ public:
}
};
-/// \brief The null pointer literal (C++11 [lex.nullptr])
+/// The null pointer literal (C++11 [lex.nullptr])
///
/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
class CXXNullPtrLiteralExpr : public Expr {
@@ -589,7 +609,7 @@ public:
}
};
-/// \brief Implicit construction of a std::initializer_list<T> object from an
+/// 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 = nullptr;
@@ -619,6 +639,7 @@ public:
return SubExpr->getLocEnd();
}
+ /// Retrieve the source range of the expression.
SourceRange getSourceRange() const LLVM_READONLY {
return SubExpr->getSourceRange();
}
@@ -677,11 +698,11 @@ public:
bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
- /// \brief Retrieves the type operand of this typeid() expression after
+ /// Retrieves the type operand of this typeid() expression after
/// various required adjustments (removing reference types, cv-qualifiers).
QualType getTypeOperand(ASTContext &Context) const;
- /// \brief Retrieve source information for the type operand.
+ /// Retrieve source information for the type operand.
TypeSourceInfo *getTypeOperandSourceInfo() const {
assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
return Operand.get<TypeSourceInfo *>();
@@ -715,12 +736,12 @@ public:
child_range children() {
if (isTypeOperand())
return child_range(child_iterator(), child_iterator());
- Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ auto **begin = reinterpret_cast<Stmt **>(&Operand);
return child_range(begin, begin + 1);
}
};
-/// \brief A member reference to an MSPropertyDecl.
+/// A member reference to an MSPropertyDecl.
///
/// This expression always has pseudo-object type, and therefore it is
/// typically not encountered in a fully-typechecked expression except
@@ -816,7 +837,7 @@ public:
SubExprs[IDX_EXPR] = Idx;
}
- /// \brief Create an empty array subscript expression.
+ /// Create an empty array subscript expression.
explicit MSPropertySubscriptExpr(EmptyShell Shell)
: Expr(MSPropertySubscriptExprClass, Shell) {}
@@ -884,11 +905,11 @@ public:
bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
- /// \brief Retrieves the type operand of this __uuidof() expression after
+ /// Retrieves the type operand of this __uuidof() expression after
/// various required adjustments (removing reference types, cv-qualifiers).
QualType getTypeOperand(ASTContext &Context) const;
- /// \brief Retrieve source information for the type operand.
+ /// Retrieve source information for the type operand.
TypeSourceInfo *getTypeOperandSourceInfo() const {
assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
return Operand.get<TypeSourceInfo *>();
@@ -925,12 +946,12 @@ public:
child_range children() {
if (isTypeOperand())
return child_range(child_iterator(), child_iterator());
- Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ auto **begin = reinterpret_cast<Stmt **>(&Operand);
return child_range(begin, begin + 1);
}
};
-/// \brief Represents the \c this expression in C++.
+/// Represents the \c this expression in C++.
///
/// This is a pointer to the object on which the current member function is
/// executing (C++ [expr.prim]p3). Example:
@@ -977,7 +998,7 @@ public:
}
};
-/// \brief A C++ throw-expression (C++ [except.throw]).
+/// A C++ throw-expression (C++ [except.throw]).
///
/// This handles 'throw' (for re-throwing the current exception) and
/// 'throw' assignment-expression. When assignment-expression isn't
@@ -988,7 +1009,7 @@ class CXXThrowExpr : public Expr {
Stmt *Op;
SourceLocation ThrowLoc;
- /// \brief Whether the thrown variable (if any) is in scope.
+ /// Whether the thrown variable (if any) is in scope.
unsigned IsThrownVariableInScope : 1;
public:
@@ -1009,7 +1030,7 @@ public:
SourceLocation getThrowLoc() const { return ThrowLoc; }
- /// \brief Determines whether the variable thrown by this expression (if any!)
+ /// Determines whether the variable thrown by this expression (if any!)
/// is within the innermost try block.
///
/// This information is required to determine whether the NRVO can apply to
@@ -1034,16 +1055,16 @@ public:
}
};
-/// \brief A default argument (C++ [dcl.fct.default]).
+/// A default argument (C++ [dcl.fct.default]).
///
/// This wraps up a function call argument that was created from the
/// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr final : public Expr {
- /// \brief The parameter whose default is being used.
+ /// The parameter whose default is being used.
ParmVarDecl *Param;
- /// \brief The location where the default argument expression was used.
+ /// The location where the default argument expression was used.
SourceLocation Loc;
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param)
@@ -1081,7 +1102,7 @@ public:
return getParam()->getDefaultArg();
}
- /// \brief Retrieve the location where this default argument was actually
+ /// Retrieve the location where this default argument was actually
/// used.
SourceLocation getUsedLocation() const { return Loc; }
@@ -1102,7 +1123,7 @@ public:
}
};
-/// \brief A use of a default initializer in a constructor or in aggregate
+/// A use of a default initializer in a constructor or in aggregate
/// initialization.
///
/// This wraps a use of a C++ default initializer (technically,
@@ -1111,10 +1132,10 @@ public:
/// (C++11 [class.base.init]p8) or in aggregate initialization
/// (C++1y [dcl.init.aggr]p7).
class CXXDefaultInitExpr : public Expr {
- /// \brief The field whose default is being used.
+ /// The field whose default is being used.
FieldDecl *Field;
- /// \brief The location where the default initializer expression was used.
+ /// The location where the default initializer expression was used.
SourceLocation Loc;
CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field,
@@ -1133,11 +1154,11 @@ public:
return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType());
}
- /// \brief Get the field whose initializer will be used.
+ /// Get the field whose initializer will be used.
FieldDecl *getField() { return Field; }
const FieldDecl *getField() const { return Field; }
- /// \brief Get the initialization expression that will be used.
+ /// Get the initialization expression that will be used.
const Expr *getExpr() const {
assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
return Field->getInClassInitializer();
@@ -1160,9 +1181,9 @@ public:
}
};
-/// \brief Represents a C++ temporary.
+/// Represents a C++ temporary.
class CXXTemporary {
- /// \brief The destructor that needs to be called.
+ /// The destructor that needs to be called.
const CXXDestructorDecl *Destructor;
explicit CXXTemporary(const CXXDestructorDecl *destructor)
@@ -1179,7 +1200,7 @@ public:
}
};
-/// \brief Represents binding an expression to a temporary.
+/// Represents binding an expression to a temporary.
///
/// This ensures the destructor is called for the temporary. It should only be
/// needed for non-POD, non-trivially destructable class types. For example:
@@ -1235,7 +1256,7 @@ public:
child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
-/// \brief Represents a call to a C++ constructor.
+/// Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {
public:
enum ConstructionKind {
@@ -1273,7 +1294,7 @@ protected:
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange);
- /// \brief Construct an empty C++ construction expression.
+ /// Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), NumArgs(0), Elidable(false),
HadMultipleCandidates(false), ListInitialization(false),
@@ -1282,7 +1303,7 @@ protected:
public:
friend class ASTStmtReader;
- /// \brief Construct an empty C++ construction expression.
+ /// Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
: CXXConstructExpr(CXXConstructExprClass, Empty) {}
@@ -1298,40 +1319,40 @@ public:
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange);
- /// \brief Get the constructor that this expression will (ultimately) call.
+ /// Get the constructor that this expression will (ultimately) call.
CXXConstructorDecl *getConstructor() const { return Constructor; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation Loc) { this->Loc = Loc; }
- /// \brief Whether this construction is elidable.
+ /// Whether this construction is elidable.
bool isElidable() const { return Elidable; }
void setElidable(bool E) { Elidable = E; }
- /// \brief Whether the referred constructor was resolved from
+ /// Whether the referred constructor was resolved from
/// an overloaded set having size greater than 1.
bool hadMultipleCandidates() const { return HadMultipleCandidates; }
void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; }
- /// \brief Whether this constructor call was written as list-initialization.
+ /// Whether this constructor call was written as list-initialization.
bool isListInitialization() const { return ListInitialization; }
void setListInitialization(bool V) { ListInitialization = V; }
- /// \brief Whether this constructor call was written as list-initialization,
+ /// Whether this constructor call was written as list-initialization,
/// but was interpreted as forming a std::initializer_list<T> from the list
/// and passing that as a single constructor argument.
/// See C++11 [over.match.list]p1 bullet 1.
bool isStdInitListInitialization() const { return StdInitListInitialization; }
void setStdInitListInitialization(bool V) { StdInitListInitialization = V; }
- /// \brief Whether this construction first requires
+ /// Whether this construction first requires
/// zero-initialization before the initializer is called.
bool requiresZeroInitialization() const { return ZeroInitialization; }
void setRequiresZeroInitialization(bool ZeroInit) {
ZeroInitialization = ZeroInit;
}
- /// \brief Determine whether this constructor is actually constructing
+ /// Determine whether this constructor is actually constructing
/// a base class (rather than a complete object).
ConstructionKind getConstructionKind() const {
return (ConstructionKind)ConstructKind;
@@ -1361,7 +1382,7 @@ public:
}
unsigned getNumArgs() const { return NumArgs; }
- /// \brief Return the specified argument.
+ /// Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
return cast<Expr>(Args[Arg]);
@@ -1371,7 +1392,7 @@ public:
return cast<Expr>(Args[Arg]);
}
- /// \brief Set the specified argument.
+ /// Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
Args[Arg] = ArgExpr;
@@ -1393,7 +1414,7 @@ public:
}
};
-/// \brief Represents a call to an inherited base class constructor from an
+/// Represents a call to an inherited base class constructor from an
/// inheriting constructor. This call implicitly forwards the arguments from
/// the enclosing context (an inheriting constructor) to the specified inherited
/// base class constructor.
@@ -1414,7 +1435,7 @@ private:
public:
friend class ASTStmtReader;
- /// \brief Construct a C++ inheriting construction expression.
+ /// Construct a C++ inheriting construction expression.
CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T,
CXXConstructorDecl *Ctor, bool ConstructsVirtualBase,
bool InheritedFromVirtualBase)
@@ -1426,15 +1447,15 @@ public:
assert(!T->isDependentType());
}
- /// \brief Construct an empty C++ inheriting construction expression.
+ /// Construct an empty C++ inheriting construction expression.
explicit CXXInheritedCtorInitExpr(EmptyShell Empty)
: Expr(CXXInheritedCtorInitExprClass, Empty),
ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {}
- /// \brief Get the constructor that this expression will call.
+ /// Get the constructor that this expression will call.
CXXConstructorDecl *getConstructor() const { return Constructor; }
- /// \brief Determine whether this constructor is actually constructing
+ /// Determine whether this constructor is actually constructing
/// a base class (rather than a complete object).
bool constructsVBase() const { return ConstructsVirtualBase; }
CXXConstructExpr::ConstructionKind getConstructionKind() const {
@@ -1442,7 +1463,7 @@ public:
: CXXConstructExpr::CK_NonVirtualBase;
}
- /// \brief Determine whether the inherited constructor is inherited from a
+ /// Determine whether the inherited constructor is inherited from a
/// virtual base of the object we construct. If so, we are not responsible
/// for calling the inherited constructor (the complete object constructor
/// does that), and so we don't need to pass any arguments.
@@ -1461,7 +1482,7 @@ public:
}
};
-/// \brief Represents an explicit C++ type conversion that uses "functional"
+/// Represents an explicit C++ type conversion that uses "functional"
/// notation (C++ [expr.type.conv]).
///
/// Example:
@@ -1470,7 +1491,8 @@ public:
/// \endcode
class CXXFunctionalCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<
+ CXXFunctionalCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
SourceLocation LParenLoc;
SourceLocation RParenLoc;
@@ -1485,6 +1507,10 @@ class CXXFunctionalCastExpr final
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -1504,6 +1530,9 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+ /// Determine whether this expression models list-initialization.
+ bool isListInitialization() const { return LParenLoc.isInvalid(); }
+
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
@@ -1512,7 +1541,7 @@ public:
}
};
-/// @brief Represents a C++ functional cast expression that builds a
+/// Represents a C++ functional cast expression that builds a
/// temporary object.
///
/// This expression type represents a C++ "functional" cast
@@ -1556,7 +1585,7 @@ public:
}
};
-/// \brief A C++ lambda expression, which produces a function object
+/// A C++ lambda expression, which produces a function object
/// (of unspecified type) that can be invoked later.
///
/// Example:
@@ -1579,29 +1608,29 @@ public:
/// and which can never occur implicitly.
class LambdaExpr final : public Expr,
private llvm::TrailingObjects<LambdaExpr, Stmt *> {
- /// \brief The source range that covers the lambda introducer ([...]).
+ /// The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
- /// \brief The source location of this lambda's capture-default ('=' or '&').
+ /// The source location of this lambda's capture-default ('=' or '&').
SourceLocation CaptureDefaultLoc;
- /// \brief The number of captures.
+ /// The number of captures.
unsigned NumCaptures : 16;
-
- /// \brief The default capture kind, which is a value of type
+
+ /// The default capture kind, which is a value of type
/// LambdaCaptureDefault.
unsigned CaptureDefault : 2;
- /// \brief Whether this lambda had an explicit parameter list vs. an
+ /// Whether this lambda had an explicit parameter list vs. an
/// implicit (and empty) parameter list.
unsigned ExplicitParams : 1;
- /// \brief Whether this lambda had the result type explicitly specified.
+ /// Whether this lambda had the result type explicitly specified.
unsigned ExplicitResultType : 1;
-
- /// \brief The location of the closing brace ('}') that completes
+
+ /// The location of the closing brace ('}') that completes
/// the lambda.
- ///
+ ///
/// The location of the brace is also available by looking up the
/// function call operator in the lambda class. However, it is
/// stored here to improve the performance of getSourceRange(), and
@@ -1609,7 +1638,7 @@ class LambdaExpr final : public Expr,
/// module file just to determine the source range.
SourceLocation ClosingBrace;
- /// \brief Construct a lambda expression.
+ /// Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
@@ -1617,7 +1646,7 @@ class LambdaExpr final : public Expr,
ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack);
- /// \brief Construct an empty lambda expression.
+ /// Construct an empty lambda expression.
LambdaExpr(EmptyShell Empty, unsigned NumCaptures)
: Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures),
CaptureDefault(LCD_None), ExplicitParams(false),
@@ -1634,7 +1663,7 @@ public:
friend class ASTStmtWriter;
friend TrailingObjects;
- /// \brief Construct a new lambda expression.
+ /// Construct a new lambda expression.
static LambdaExpr *
Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc,
@@ -1642,145 +1671,145 @@ public:
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack);
- /// \brief Construct a new lambda expression that will be deserialized from
+ /// Construct a new lambda expression that will be deserialized from
/// an external source.
static LambdaExpr *CreateDeserialized(const ASTContext &C,
unsigned NumCaptures);
- /// \brief Determine the default capture kind for this lambda.
+ /// Determine the default capture kind for this lambda.
LambdaCaptureDefault getCaptureDefault() const {
return static_cast<LambdaCaptureDefault>(CaptureDefault);
}
- /// \brief Retrieve the location of this lambda's capture-default, if any.
+ /// Retrieve the location of this lambda's capture-default, if any.
SourceLocation getCaptureDefaultLoc() const {
return CaptureDefaultLoc;
}
- /// \brief Determine whether one of this lambda's captures is an init-capture.
+ /// Determine whether one of this lambda's captures is an init-capture.
bool isInitCapture(const LambdaCapture *Capture) const;
- /// \brief An iterator that walks over the captures of the lambda,
+ /// An iterator that walks over the captures of the lambda,
/// both implicit and explicit.
using capture_iterator = const LambdaCapture *;
- /// \brief An iterator over a range of lambda captures.
+ /// An iterator over a range of lambda captures.
using capture_range = llvm::iterator_range<capture_iterator>;
- /// \brief Retrieve this lambda's captures.
+ /// Retrieve this lambda's captures.
capture_range captures() const;
-
- /// \brief Retrieve an iterator pointing to the first lambda capture.
+
+ /// Retrieve an iterator pointing to the first lambda capture.
capture_iterator capture_begin() const;
- /// \brief Retrieve an iterator pointing past the end of the
+ /// Retrieve an iterator pointing past the end of the
/// sequence of lambda captures.
capture_iterator capture_end() const;
- /// \brief Determine the number of captures in this lambda.
+ /// Determine the number of captures in this lambda.
unsigned capture_size() const { return NumCaptures; }
- /// \brief Retrieve this lambda's explicit captures.
+ /// Retrieve this lambda's explicit captures.
capture_range explicit_captures() const;
-
- /// \brief Retrieve an iterator pointing to the first explicit
+
+ /// Retrieve an iterator pointing to the first explicit
/// lambda capture.
capture_iterator explicit_capture_begin() const;
- /// \brief Retrieve an iterator pointing past the end of the sequence of
+ /// Retrieve an iterator pointing past the end of the sequence of
/// explicit lambda captures.
capture_iterator explicit_capture_end() const;
- /// \brief Retrieve this lambda's implicit captures.
+ /// Retrieve this lambda's implicit captures.
capture_range implicit_captures() const;
- /// \brief Retrieve an iterator pointing to the first implicit
+ /// Retrieve an iterator pointing to the first implicit
/// lambda capture.
capture_iterator implicit_capture_begin() const;
- /// \brief Retrieve an iterator pointing past the end of the sequence of
+ /// Retrieve an iterator pointing past the end of the sequence of
/// implicit lambda captures.
capture_iterator implicit_capture_end() const;
- /// \brief Iterator that walks over the capture initialization
+ /// Iterator that walks over the capture initialization
/// arguments.
using capture_init_iterator = Expr **;
- /// \brief Const iterator that walks over the capture initialization
+ /// Const iterator that walks over the capture initialization
/// arguments.
using const_capture_init_iterator = Expr *const *;
- /// \brief Retrieve the initialization expressions for this lambda's captures.
+ /// Retrieve the initialization expressions for this lambda's captures.
llvm::iterator_range<capture_init_iterator> capture_inits() {
return llvm::make_range(capture_init_begin(), capture_init_end());
}
- /// \brief Retrieve the initialization expressions for this lambda's captures.
+ /// Retrieve the initialization expressions for this lambda's captures.
llvm::iterator_range<const_capture_init_iterator> capture_inits() const {
return llvm::make_range(capture_init_begin(), capture_init_end());
}
- /// \brief Retrieve the first initialization argument for this
+ /// Retrieve the first initialization argument for this
/// lambda expression (which initializes the first capture field).
capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
- /// \brief Retrieve the first initialization argument for this
+ /// Retrieve the first initialization argument for this
/// lambda expression (which initializes the first capture field).
const_capture_init_iterator capture_init_begin() const {
return reinterpret_cast<Expr *const *>(getStoredStmts());
}
- /// \brief Retrieve the iterator pointing one past the last
+ /// Retrieve the iterator pointing one past the last
/// initialization argument for this lambda expression.
capture_init_iterator capture_init_end() {
return capture_init_begin() + NumCaptures;
}
- /// \brief Retrieve the iterator pointing one past the last
+ /// Retrieve the iterator pointing one past the last
/// initialization argument for this lambda expression.
const_capture_init_iterator capture_init_end() const {
return capture_init_begin() + NumCaptures;
}
- /// \brief Retrieve the source range covering the lambda introducer,
+ /// Retrieve the source range covering the lambda introducer,
/// which contains the explicit capture list surrounded by square
/// brackets ([...]).
SourceRange getIntroducerRange() const { return IntroducerRange; }
- /// \brief Retrieve the class that corresponds to the lambda.
- ///
+ /// Retrieve the class that corresponds to the lambda.
+ ///
/// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the
/// captures in its fields and provides the various operations permitted
/// on a lambda (copying, calling).
CXXRecordDecl *getLambdaClass() const;
- /// \brief Retrieve the function call operator associated with this
- /// lambda expression.
+ /// Retrieve the function call operator associated with this
+ /// lambda expression.
CXXMethodDecl *getCallOperator() const;
- /// \brief If this is a generic lambda expression, retrieve the template
- /// parameter list associated with it, or else return null.
+ /// If this is a generic lambda expression, retrieve the template
+ /// parameter list associated with it, or else return null.
TemplateParameterList *getTemplateParameterList() const;
- /// \brief Whether this is a generic lambda.
+ /// Whether this is a generic lambda.
bool isGenericLambda() const { return getTemplateParameterList(); }
- /// \brief Retrieve the body of the lambda.
+ /// Retrieve the body of the lambda.
CompoundStmt *getBody() const;
- /// \brief Determine whether the lambda is mutable, meaning that any
+ /// Determine whether the lambda is mutable, meaning that any
/// captures values can be modified.
bool isMutable() const;
- /// \brief Determine whether this lambda has an explicit parameter
+ /// Determine whether this lambda has an explicit parameter
/// list vs. an implicit (empty) parameter list.
bool hasExplicitParameters() const { return ExplicitParams; }
- /// \brief Whether this lambda had its result type explicitly specified.
+ /// Whether this lambda had its result type explicitly specified.
bool hasExplicitResultType() const { return ExplicitResultType; }
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == LambdaExprClass;
}
@@ -1806,7 +1835,7 @@ class CXXScalarValueInitExpr : public Expr {
TypeSourceInfo *TypeInfo;
public:
- /// \brief Create an explicitly-written scalar-value initialization
+ /// Create an explicitly-written scalar-value initialization
/// expression.
CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo,
SourceLocation rParenLoc)
@@ -1837,7 +1866,7 @@ public:
}
};
-/// \brief Represents a new-expression for memory allocation and constructor
+/// Represents a new-expression for memory allocation and constructor
/// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
friend class ASTStmtReader;
@@ -1847,24 +1876,24 @@ class CXXNewExpr : public Expr {
/// expression, and any number of optional placement arguments, in that order.
Stmt **SubExprs = nullptr;
- /// \brief Points to the allocation function used.
+ /// Points to the allocation function used.
FunctionDecl *OperatorNew;
- /// \brief Points to the deallocation function used in case of error. May be
+ /// Points to the deallocation function used in case of error. May be
/// null.
FunctionDecl *OperatorDelete;
- /// \brief The allocated type-source information, as written in the source.
+ /// The allocated type-source information, as written in the source.
TypeSourceInfo *AllocatedTypeInfo;
- /// \brief If the allocated type was expressed as a parenthesized type-id,
+ /// If the allocated type was expressed as a parenthesized type-id,
/// the source range covering the parenthesized type-id.
SourceRange TypeIdParens;
- /// \brief Range of the entire new expression.
+ /// Range of the entire new expression.
SourceRange Range;
- /// \brief Source-range of a paren-delimited initializer.
+ /// Source-range of a paren-delimited initializer.
SourceRange DirectInitRange;
/// Was the usage ::new, i.e. is the global new to be used?
@@ -1922,7 +1951,7 @@ public:
return AllocatedTypeInfo;
}
- /// \brief True if the allocation result needs to be null-checked.
+ /// True if the allocation result needs to be null-checked.
///
/// C++11 [expr.new]p13:
/// If the allocation function returns null, initialization shall
@@ -1973,17 +2002,17 @@ public:
bool isGlobalNew() const { return GlobalNew; }
- /// \brief Whether this new-expression has any initializer at all.
+ /// Whether this new-expression has any initializer at all.
bool hasInitializer() const { return StoredInitializationStyle > 0; }
- /// \brief The kind of initializer this new-expression has.
+ /// The kind of initializer this new-expression has.
InitializationStyle getInitializationStyle() const {
if (StoredInitializationStyle == 0)
return NoInit;
return static_cast<InitializationStyle>(StoredInitializationStyle-1);
}
- /// \brief The initializer of this new-expression.
+ /// The initializer of this new-expression.
Expr *getInitializer() {
return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
}
@@ -1991,7 +2020,7 @@ public:
return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
}
- /// \brief Returns the CXXConstructExpr from this new-expression, or null.
+ /// Returns the CXXConstructExpr from this new-expression, or null.
const CXXConstructExpr *getConstructExpr() const {
return dyn_cast_or_null<CXXConstructExpr>(getInitializer());
}
@@ -2066,7 +2095,7 @@ public:
}
};
-/// \brief Represents a \c delete expression for memory deallocation and
+/// Represents a \c delete expression for memory deallocation and
/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
/// Points to the operator delete overload that is used. Could be a member.
@@ -2125,7 +2154,7 @@ public:
Expr *getArgument() { return cast<Expr>(Argument); }
const Expr *getArgument() const { return cast<Expr>(Argument); }
- /// \brief Retrieve the type being destroyed.
+ /// Retrieve the type being destroyed.
///
/// If the type being destroyed is a dependent type which may or may not
/// be a pointer, return an invalid type.
@@ -2142,13 +2171,13 @@ public:
child_range children() { return child_range(&Argument, &Argument+1); }
};
-/// \brief Stores the type being destroyed by a pseudo-destructor expression.
+/// Stores the type being destroyed by a pseudo-destructor expression.
class PseudoDestructorTypeStorage {
- /// \brief Either the type source information or the name of the type, if
+ /// Either the type source information or the name of the type, if
/// it couldn't be resolved due to type-dependence.
llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;
- /// \brief The starting source location of the pseudo-destructor type.
+ /// The starting source location of the pseudo-destructor type.
SourceLocation Location;
public:
@@ -2170,7 +2199,7 @@ public:
SourceLocation getLocation() const { return Location; }
};
-/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
+/// Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
///
/// A pseudo-destructor is an expression that looks like a member access to a
/// destructor of a scalar type, except that scalar types don't have
@@ -2197,31 +2226,31 @@ public:
class CXXPseudoDestructorExpr : public Expr {
friend class ASTStmtReader;
- /// \brief The base expression (that is being destroyed).
+ /// The base expression (that is being destroyed).
Stmt *Base = nullptr;
- /// \brief Whether the operator was an arrow ('->'); otherwise, it was a
+ /// Whether the operator was an arrow ('->'); otherwise, it was a
/// period ('.').
bool IsArrow : 1;
- /// \brief The location of the '.' or '->' operator.
+ /// The location of the '.' or '->' operator.
SourceLocation OperatorLoc;
- /// \brief The nested-name-specifier that follows the operator, if present.
+ /// The nested-name-specifier that follows the operator, if present.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief The type that precedes the '::' in a qualified pseudo-destructor
+ /// The type that precedes the '::' in a qualified pseudo-destructor
/// expression.
TypeSourceInfo *ScopeType = nullptr;
- /// \brief The location of the '::' in a qualified pseudo-destructor
+ /// The location of the '::' in a qualified pseudo-destructor
/// expression.
SourceLocation ColonColonLoc;
- /// \brief The location of the '~'.
+ /// The location of the '~'.
SourceLocation TildeLoc;
- /// \brief The type being destroyed, or its name if we were unable to
+ /// The type being destroyed, or its name if we were unable to
/// resolve the name.
PseudoDestructorTypeStorage DestroyedType;
@@ -2239,30 +2268,30 @@ public:
Expr *getBase() const { return cast<Expr>(Base); }
- /// \brief Determines whether this member expression actually had
+ /// Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
bool hasQualifier() const { return QualifierLoc.hasQualifier(); }
- /// \brief Retrieves the nested-name-specifier that qualifies the type name,
+ /// Retrieves the nested-name-specifier that qualifies the type name,
/// with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief If the member name was qualified, retrieves the
+ /// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// null.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Determine whether this pseudo-destructor expression was written
+ /// Determine whether this pseudo-destructor expression was written
/// using an '->' (otherwise, it used a '.').
bool isArrow() const { return IsArrow; }
- /// \brief Retrieve the location of the '.' or '->' operator.
+ /// Retrieve the location of the '.' or '->' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- /// \brief Retrieve the scope type in a qualified pseudo-destructor
+ /// Retrieve the scope type in a qualified pseudo-destructor
/// expression.
///
/// Pseudo-destructor expressions can have extra qualification within them
@@ -2273,14 +2302,14 @@ public:
/// destructor expression.
TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }
- /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
+ /// Retrieve the location of the '::' in a qualified pseudo-destructor
/// expression.
SourceLocation getColonColonLoc() const { return ColonColonLoc; }
- /// \brief Retrieve the location of the '~'.
+ /// Retrieve the location of the '~'.
SourceLocation getTildeLoc() const { return TildeLoc; }
- /// \brief Retrieve the source location information for the type
+ /// Retrieve the source location information for the type
/// being destroyed.
///
/// This type-source information is available for non-dependent
@@ -2291,28 +2320,28 @@ public:
return DestroyedType.getTypeSourceInfo();
}
- /// \brief In a dependent pseudo-destructor expression for which we do not
+ /// In a dependent pseudo-destructor expression for which we do not
/// have full type information on the destroyed type, provides the name
/// of the destroyed type.
IdentifierInfo *getDestroyedTypeIdentifier() const {
return DestroyedType.getIdentifier();
}
- /// \brief Retrieve the type being destroyed.
+ /// Retrieve the type being destroyed.
QualType getDestroyedType() const;
- /// \brief Retrieve the starting location of the type being destroyed.
+ /// Retrieve the starting location of the type being destroyed.
SourceLocation getDestroyedTypeLoc() const {
return DestroyedType.getLocation();
}
- /// \brief Set the name of destroyed type for a dependent pseudo-destructor
+ /// Set the name of destroyed type for a dependent pseudo-destructor
/// expression.
void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) {
DestroyedType = PseudoDestructorTypeStorage(II, Loc);
}
- /// \brief Set the destroyed type.
+ /// Set the destroyed type.
void setDestroyedType(TypeSourceInfo *Info) {
DestroyedType = PseudoDestructorTypeStorage(Info);
}
@@ -2328,7 +2357,7 @@ public:
child_range children() { return child_range(&Base, &Base + 1); }
};
-/// \brief A type trait used in the implementation of various C++11 and
+/// A type trait used in the implementation of various C++11 and
/// Library TR1 trait templates.
///
/// \code
@@ -2339,15 +2368,15 @@ public:
class TypeTraitExpr final
: public Expr,
private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> {
- /// \brief The location of the type trait keyword.
+ /// The location of the type trait keyword.
SourceLocation Loc;
-
- /// \brief The location of the closing parenthesis.
+
+ /// The location of the closing parenthesis.
SourceLocation RParenLoc;
-
+
// Note: The TypeSourceInfos for the arguments are allocated after the
// TypeTraitExpr.
-
+
TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
@@ -2364,7 +2393,7 @@ public:
friend class ASTStmtWriter;
friend TrailingObjects;
- /// \brief Create a new type trait expression.
+ /// Create a new type trait expression.
static TypeTraitExpr *Create(const ASTContext &C, QualType T,
SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
@@ -2373,27 +2402,27 @@ public:
static TypeTraitExpr *CreateDeserialized(const ASTContext &C,
unsigned NumArgs);
-
- /// \brief Determine which type trait this expression uses.
+
+ /// Determine which type trait this expression uses.
TypeTrait getTrait() const {
return static_cast<TypeTrait>(TypeTraitExprBits.Kind);
}
- bool getValue() const {
- assert(!isValueDependent());
- return TypeTraitExprBits.Value;
+ bool getValue() const {
+ assert(!isValueDependent());
+ return TypeTraitExprBits.Value;
}
-
- /// \brief Determine the number of arguments to this type trait.
+
+ /// Determine the number of arguments to this type trait.
unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; }
-
- /// \brief Retrieve the Ith argument.
+
+ /// Retrieve the Ith argument.
TypeSourceInfo *getArg(unsigned I) const {
assert(I < getNumArgs() && "Argument out-of-range");
return getArgs()[I];
}
-
- /// \brief Retrieve the argument types.
+
+ /// Retrieve the argument types.
ArrayRef<TypeSourceInfo *> getArgs() const {
return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(),
getNumArgs());
@@ -2405,14 +2434,14 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == TypeTraitExprClass;
}
-
+
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
-/// \brief An Embarcadero array type trait, as used in the implementation of
+/// An Embarcadero array type trait, as used in the implementation of
/// __array_rank and __array_extent.
///
/// Example:
@@ -2421,22 +2450,22 @@ public:
/// __array_extent(int, 1) == 20
/// \endcode
class ArrayTypeTraitExpr : public Expr {
- /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
+ /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
unsigned ATT : 2;
- /// \brief The value of the type trait. Unspecified if dependent.
+ /// The value of the type trait. Unspecified if dependent.
uint64_t Value = 0;
- /// \brief The array dimension being queried, or -1 if not used.
+ /// The array dimension being queried, or -1 if not used.
Expr *Dimension;
- /// \brief The location of the type trait keyword.
+ /// The location of the type trait keyword.
SourceLocation Loc;
- /// \brief The location of the closing paren.
+ /// The location of the closing paren.
SourceLocation RParen;
- /// \brief The type being queried.
+ /// The type being queried.
TypeSourceInfo *QueriedType = nullptr;
virtual void anchor();
@@ -2483,7 +2512,7 @@ public:
}
};
-/// \brief An expression trait intrinsic.
+/// An expression trait intrinsic.
///
/// Example:
/// \code
@@ -2491,19 +2520,19 @@ public:
/// __is_lvalue_expr(1) == false
/// \endcode
class ExpressionTraitExpr : public Expr {
- /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned.
+ /// The trait. A ExpressionTrait enum in MSVC compatible unsigned.
unsigned ET : 31;
- /// \brief The value of the type trait. Unspecified if dependent.
+ /// The value of the type trait. Unspecified if dependent.
unsigned Value : 1;
- /// \brief The location of the type trait keyword.
+ /// The location of the type trait keyword.
SourceLocation Loc;
- /// \brief The location of the closing paren.
+ /// The location of the closing paren.
SourceLocation RParen;
- /// \brief The expression being queried.
+ /// The expression being queried.
Expr* QueriedExpression = nullptr;
public:
@@ -2543,13 +2572,13 @@ public:
}
};
-/// \brief A reference to an overloaded function set, either an
+/// A reference to an overloaded function set, either an
/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
class OverloadExpr : public Expr {
- /// \brief The common name of these declarations.
+ /// The common name of these declarations.
DeclarationNameInfo NameInfo;
- /// \brief The nested-name-specifier that qualifies the name, if any.
+ /// The nested-name-specifier that qualifies the name, if any.
NestedNameSpecifierLoc QualifierLoc;
/// The results. These are undesugared, which is to say, they may
@@ -2561,7 +2590,7 @@ class OverloadExpr : public Expr {
unsigned NumResults = 0;
protected:
- /// \brief Whether the name includes info for explicit template
+ /// Whether the name includes info for explicit template
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo = false;
@@ -2577,11 +2606,11 @@ protected:
OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {}
- /// \brief Return the optional template keyword and arguments info.
+ /// Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *
getTrailingASTTemplateKWAndArgsInfo(); // defined far below.
- /// \brief Return the optional template keyword and arguments info.
+ /// Return the optional template keyword and arguments info.
const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const {
return const_cast<OverloadExpr *>(this)
->getTrailingASTTemplateKWAndArgsInfo();
@@ -2604,7 +2633,7 @@ public:
bool HasFormOfMemberPointer;
};
- /// \brief Finds the overloaded expression in the given expression \p E of
+ /// Finds the overloaded expression in the given expression \p E of
/// OverloadTy.
///
/// \return the expression (which must be there) and true if it has
@@ -2618,7 +2647,7 @@ public:
if (isa<UnaryOperator>(E)) {
assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
E = cast<UnaryOperator>(E)->getSubExpr();
- OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens());
+ auto *Ovl = cast<OverloadExpr>(E->IgnoreParens());
Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
Result.IsAddressOfOperand = true;
@@ -2632,7 +2661,7 @@ public:
return Result;
}
- /// \brief Gets the naming class of this lookup, if any.
+ /// Gets the naming class of this lookup, if any.
CXXRecordDecl *getNamingClass() const;
using decls_iterator = UnresolvedSetImpl::iterator;
@@ -2645,52 +2674,52 @@ public:
return llvm::make_range(decls_begin(), decls_end());
}
- /// \brief Gets the number of declarations in the unresolved set.
+ /// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
- /// \brief Gets the full name info.
+ /// Gets the full name info.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
- /// \brief Gets the name looked up.
+ /// Gets the name looked up.
DeclarationName getName() const { return NameInfo.getName(); }
- /// \brief Gets the location of the name.
+ /// Gets the location of the name.
SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
- /// \brief Fetches the nested-name qualifier, if one was given.
+ /// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Fetches the nested-name qualifier with source-location
+ /// Fetches the nested-name qualifier with source-location
/// information, if one was given.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the location of the template keyword preceding
+ /// Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc;
}
- /// \brief Retrieve the location of the left angle bracket starting the
+ /// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc;
}
- /// \brief Retrieve the location of the right angle bracket ending the
+ /// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc;
}
- /// \brief Determines whether the name was preceded by the template keyword.
+ /// Determines whether the name was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
- /// \brief Determines whether this expression had explicit template arguments.
+ /// Determines whether this expression had explicit template arguments.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
TemplateArgumentLoc const *getTemplateArgs() const {
@@ -2710,7 +2739,7 @@ public:
return {getTemplateArgs(), getNumTemplateArgs()};
}
- /// \brief Copies the template arguments into the given structure.
+ /// Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List);
@@ -2722,7 +2751,7 @@ public:
}
};
-/// \brief A reference to a name which we were able to look up during
+/// A reference to a name which we were able to look up during
/// parsing but could not resolve to a specific declaration.
///
/// This arises in several ways:
@@ -2837,7 +2866,7 @@ public:
}
};
-/// \brief A qualified reference to a name whose declaration cannot
+/// A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that
@@ -2856,14 +2885,14 @@ class DependentScopeDeclRefExpr final
private llvm::TrailingObjects<DependentScopeDeclRefExpr,
ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
- /// \brief The nested-name-specifier that qualifies this unresolved
+ /// The nested-name-specifier that qualifies this unresolved
/// declaration name.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief The name of the entity we will be referencing.
+ /// The name of the entity we will be referencing.
DeclarationNameInfo NameInfo;
- /// \brief Whether the name includes info for explicit template
+ /// Whether the name includes info for explicit template
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo;
@@ -2892,42 +2921,42 @@ public:
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
- /// \brief Retrieve the name that this expression refers to.
+ /// Retrieve the name that this expression refers to.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
- /// \brief Retrieve the name that this expression refers to.
+ /// Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return NameInfo.getName(); }
- /// \brief Retrieve the location of the name within the expression.
+ /// Retrieve the location of the name within the expression.
///
/// For example, in "X<T>::value" this is the location of "value".
SourceLocation getLocation() const { return NameInfo.getLoc(); }
- /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// Retrieve the nested-name-specifier that qualifies the
/// name, with source location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies this
+ /// Retrieve the nested-name-specifier that qualifies this
/// declaration.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Retrieve the location of the template keyword preceding
+ /// Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
- /// \brief Retrieve the location of the left angle bracket starting the
+ /// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
- /// \brief Retrieve the location of the right angle bracket ending the
+ /// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
@@ -2940,7 +2969,7 @@ public:
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Copies the template arguments (if present) into the given
+ /// Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
@@ -3063,7 +3092,7 @@ public:
child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
-/// \brief Describes an explicit type conversion that uses functional
+/// Describes an explicit type conversion that uses functional
/// notion but could not be resolved because one or more arguments are
/// type-dependent.
///
@@ -3090,16 +3119,16 @@ class CXXUnresolvedConstructExpr final
friend class ASTStmtReader;
friend TrailingObjects;
- /// \brief The type being constructed.
+ /// The type being constructed.
TypeSourceInfo *Type = nullptr;
- /// \brief The location of the left parentheses ('(').
+ /// The location of the left parentheses ('(').
SourceLocation LParenLoc;
- /// \brief The location of the right parentheses (')').
+ /// The location of the right parentheses (')').
SourceLocation RParenLoc;
- /// \brief The number of arguments used to construct the type.
+ /// The number of arguments used to construct the type.
unsigned NumArgs;
CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
@@ -3120,20 +3149,20 @@ public:
static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C,
unsigned NumArgs);
- /// \brief Retrieve the type that is being constructed, as specified
+ /// Retrieve the type that is being constructed, as specified
/// in the source code.
QualType getTypeAsWritten() const { return Type->getType(); }
- /// \brief Retrieve the type source information for the type being
+ /// Retrieve the type source information for the type being
/// constructed.
TypeSourceInfo *getTypeSourceInfo() const { return Type; }
- /// \brief Retrieve the location of the left parentheses ('(') that
+ /// Retrieve the location of the left parentheses ('(') that
/// precedes the argument list.
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
- /// \brief Retrieve the location of the right parentheses (')') that
+ /// Retrieve the location of the right parentheses (')') that
/// follows the argument list.
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -3143,7 +3172,7 @@ public:
/// an InitListExpr.
bool isListInitialization() const { return LParenLoc.isInvalid(); }
- /// \brief Retrieve the number of arguments.
+ /// Retrieve the number of arguments.
unsigned arg_size() const { return NumArgs; }
using arg_iterator = Expr **;
@@ -3187,12 +3216,12 @@ public:
// Iterators
child_range children() {
- Stmt **begin = reinterpret_cast<Stmt **>(arg_begin());
+ auto **begin = reinterpret_cast<Stmt **>(arg_begin());
return child_range(begin, begin + NumArgs);
}
};
-/// \brief Represents a C++ member access expression where the actual
+/// Represents a C++ member access expression where the actual
/// member referenced could not be resolved because the base
/// expression or the member name was dependent.
///
@@ -3204,29 +3233,29 @@ class CXXDependentScopeMemberExpr final
private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
- /// \brief The expression for the base pointer or class reference,
+ /// The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. Can be null in implicit accesses.
Stmt *Base;
- /// \brief The type of the base expression. Never null, even for
+ /// The type of the base expression. Never null, even for
/// implicit accesses.
QualType BaseType;
- /// \brief Whether this member expression used the '->' operator or
+ /// Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
- /// \brief Whether this member expression has info for explicit template
+ /// Whether this member expression has info for explicit template
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo : 1;
- /// \brief The location of the '->' or '.' operator.
+ /// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
- /// \brief The nested-name-specifier that precedes the member name, if any.
+ /// The nested-name-specifier that precedes the member name, if any.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief In a qualified member access expression such as t->Base::f, this
+ /// In a qualified member access expression such as t->Base::f, this
/// member stores the resolves of name lookup in the context of the member
/// access expression, to be used at instantiation time.
///
@@ -3235,7 +3264,7 @@ class CXXDependentScopeMemberExpr final
/// the CXXDependentScopeMemberExpr, to save space in the common case.
NamedDecl *FirstQualifierFoundInScope;
- /// \brief The member to which this member expression refers, which
+ /// The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
///
/// FIXME: could also be a template-id
@@ -3277,12 +3306,12 @@ public:
CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
- /// \brief True if this is an implicit access, i.e. one in which the
+ /// True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
/// location of the operator is invalid in this case.
bool isImplicitAccess() const;
- /// \brief Retrieve the base object of this member expressions,
+ /// Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
Expr *getBase() const {
assert(!isImplicitAccess());
@@ -3291,24 +3320,24 @@ public:
QualType getBaseType() const { return BaseType; }
- /// \brief Determine whether this member expression used the '->'
+ /// Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator.
bool isArrow() const { return IsArrow; }
- /// \brief Retrieve the location of the '->' or '.' operator.
+ /// Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// Retrieve the nested-name-specifier that qualifies the member
/// name.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// Retrieve the nested-name-specifier that qualifies the member
/// name, with source location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the first part of the nested-name-specifier that was
+ /// 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.
///
@@ -3323,35 +3352,35 @@ public:
return FirstQualifierFoundInScope;
}
- /// \brief Retrieve the name of the member that this expression
+ /// Retrieve the name of the member that this expression
/// refers to.
const DeclarationNameInfo &getMemberNameInfo() const {
return MemberNameInfo;
}
- /// \brief Retrieve the name of the member that this expression
+ /// Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMember() const { return MemberNameInfo.getName(); }
- // \brief Retrieve the location of the name of the member that this
+ // Retrieve the location of the name of the member that this
// expression refers to.
SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }
- /// \brief Retrieve the location of the template keyword preceding the
+ /// Retrieve the location of the template keyword preceding the
/// member name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
- /// \brief Retrieve the location of the left angle bracket starting the
+ /// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
- /// \brief Retrieve the location of the right angle bracket ending the
+ /// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
@@ -3361,11 +3390,11 @@ public:
/// Determines whether the member name was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
- /// \brief Determines whether this member expression actually had a C++
+ /// Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Copies the template arguments (if present) into the given
+ /// Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
@@ -3373,7 +3402,7 @@ public:
getTrailingObjects<TemplateArgumentLoc>(), List);
}
- /// \brief Retrieve the template arguments provided as part of this
+ /// Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
@@ -3382,7 +3411,7 @@ public:
return getTrailingObjects<TemplateArgumentLoc>();
}
- /// \brief Retrieve the number of template arguments provided as part of this
+ /// Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
@@ -3421,7 +3450,7 @@ public:
}
};
-/// \brief Represents a C++ member access expression for which lookup
+/// Represents a C++ member access expression for which lookup
/// produced a set of overloaded functions.
///
/// The member access may be explicit or implicit:
@@ -3444,24 +3473,24 @@ class UnresolvedMemberExpr final
friend class OverloadExpr;
friend TrailingObjects;
- /// \brief Whether this member expression used the '->' operator or
+ /// Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
- /// \brief Whether the lookup results contain an unresolved using
+ /// Whether the lookup results contain an unresolved using
/// declaration.
bool HasUnresolvedUsing : 1;
- /// \brief The expression for the base pointer or class reference,
+ /// The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
///
/// This can be null if this is an 'unbased' member expression.
Stmt *Base = nullptr;
- /// \brief The type of the base expression; never null.
+ /// The type of the base expression; never null.
QualType BaseType;
- /// \brief The location of the '->' or '.' operator.
+ /// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing,
@@ -3496,13 +3525,13 @@ public:
CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
- /// \brief True if this is an implicit access, i.e., one in which the
+ /// True if this is an implicit access, i.e., one in which the
/// member being accessed was not written in the source.
///
/// The source location of the operator is invalid in this case.
bool isImplicitAccess() const;
- /// \brief Retrieve the base object of this member expressions,
+ /// Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
Expr *getBase() {
assert(!isImplicitAccess());
@@ -3515,33 +3544,33 @@ public:
QualType getBaseType() const { return BaseType; }
- /// \brief Determine whether the lookup results contain an unresolved using
+ /// Determine whether the lookup results contain an unresolved using
/// declaration.
bool hasUnresolvedUsing() const { return HasUnresolvedUsing; }
- /// \brief Determine whether this member expression used the '->'
+ /// Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator.
bool isArrow() const { return IsArrow; }
- /// \brief Retrieve the location of the '->' or '.' operator.
+ /// Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- /// \brief Retrieve the naming class of this lookup.
+ /// Retrieve the naming class of this lookup.
CXXRecordDecl *getNamingClass() const;
- /// \brief Retrieve the full name info for the member that this expression
+ /// Retrieve the full name info for the member that this expression
/// refers to.
const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }
- /// \brief Retrieve the name of the member that this expression
+ /// Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMemberName() const { return getName(); }
- // \brief Retrieve the location of the name of the member that this
+ // Retrieve the location of the name of the member that this
// expression refers to.
SourceLocation getMemberLoc() const { return getNameLoc(); }
- // \brief Return the preferred location (the member name) for the arrow when
+ // Return the preferred location (the member name) for the arrow when
// diagnosing a problem with this expression.
SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); }
@@ -3593,7 +3622,7 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
->getTrailingObjects<TemplateArgumentLoc>();
}
-/// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
+/// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
///
/// The noexcept expression tests whether a given expression might throw. Its
/// result is a boolean constant.
@@ -3632,7 +3661,7 @@ public:
child_range children() { return child_range(&Operand, &Operand + 1); }
};
-/// \brief Represents a C++11 pack expansion that produces a sequence of
+/// Represents a C++11 pack expansion that produces a sequence of
/// expressions.
///
/// A pack expansion expression contains a pattern (which itself is an
@@ -3655,7 +3684,7 @@ class PackExpansionExpr : public Expr {
SourceLocation EllipsisLoc;
- /// \brief The number of expansions that will be produced by this pack
+ /// The number of expansions that will be produced by this pack
/// expansion expression, if known.
///
/// When zero, the number of expansions is not known. Otherwise, this value
@@ -3677,17 +3706,17 @@ public:
PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {}
- /// \brief Retrieve the pattern of the pack expansion.
+ /// Retrieve the pattern of the pack expansion.
Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }
- /// \brief Retrieve the pattern of the pack expansion.
+ /// Retrieve the pattern of the pack expansion.
const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); }
- /// \brief Retrieve the location of the ellipsis that describes this pack
+ /// Retrieve the location of the ellipsis that describes this pack
/// expansion.
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
- /// \brief Determine the number of expansions that will be produced when
+ /// Determine the number of expansions that will be produced when
/// this pack expansion is instantiated, if already known.
Optional<unsigned> getNumExpansions() const {
if (NumExpansions)
@@ -3712,7 +3741,7 @@ public:
}
};
-/// \brief Represents an expression that computes the length of a parameter
+/// Represents an expression that computes the length of a parameter
/// pack.
///
/// \code
@@ -3728,16 +3757,16 @@ class SizeOfPackExpr final
friend class ASTStmtWriter;
friend TrailingObjects;
- /// \brief The location of the \c sizeof keyword.
+ /// The location of the \c sizeof keyword.
SourceLocation OperatorLoc;
- /// \brief The location of the name of the parameter pack.
+ /// The location of the name of the parameter pack.
SourceLocation PackLoc;
- /// \brief The location of the closing parenthesis.
+ /// The location of the closing parenthesis.
SourceLocation RParenLoc;
- /// \brief The length of the parameter pack, if known.
+ /// The length of the parameter pack, if known.
///
/// When this expression is not value-dependent, this is the length of
/// the pack. When the expression was parsed rather than instantiated
@@ -3749,10 +3778,10 @@ class SizeOfPackExpr final
/// and this is the length of that array.
unsigned Length;
- /// \brief The parameter pack.
+ /// The parameter pack.
NamedDecl *Pack = nullptr;
- /// \brief Create an expression that computes the length of
+ /// Create an expression that computes the length of
/// the given parameter pack.
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc, SourceLocation RParenLoc,
@@ -3765,11 +3794,11 @@ class SizeOfPackExpr final
Length(Length ? *Length : PartialArgs.size()), Pack(Pack) {
assert((!Length || PartialArgs.empty()) &&
"have partial args for non-dependent sizeof... expression");
- TemplateArgument *Args = getTrailingObjects<TemplateArgument>();
+ auto *Args = getTrailingObjects<TemplateArgument>();
std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args);
}
- /// \brief Create an empty expression.
+ /// Create an empty expression.
SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs)
: Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {}
@@ -3782,19 +3811,19 @@ public:
static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
unsigned NumPartialArgs);
- /// \brief Determine the location of the 'sizeof' keyword.
+ /// Determine the location of the 'sizeof' keyword.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- /// \brief Determine the location of the parameter pack.
+ /// Determine the location of the parameter pack.
SourceLocation getPackLoc() const { return PackLoc; }
- /// \brief Determine the location of the right parenthesis.
+ /// Determine the location of the right parenthesis.
SourceLocation getRParenLoc() const { return RParenLoc; }
- /// \brief Retrieve the parameter pack.
+ /// Retrieve the parameter pack.
NamedDecl *getPack() const { return Pack; }
- /// \brief Retrieve the length of the parameter pack.
+ /// Retrieve the length of the parameter pack.
///
/// This routine may only be invoked when the expression is not
/// value-dependent.
@@ -3804,7 +3833,7 @@ public:
return Length;
}
- /// \brief Determine whether this represents a partially-substituted sizeof...
+ /// Determine whether this represents a partially-substituted sizeof...
/// expression, such as is produced for:
///
/// template<typename ...Ts> using X = int[sizeof...(Ts)];
@@ -3813,10 +3842,10 @@ public:
return isValueDependent() && Length;
}
- /// \brief Get
+ /// Get
ArrayRef<TemplateArgument> getPartialArguments() const {
assert(isPartiallySubstituted());
- const TemplateArgument *Args = getTrailingObjects<TemplateArgument>();
+ const auto *Args = getTrailingObjects<TemplateArgument>();
return llvm::makeArrayRef(Args, Args + Length);
}
@@ -3833,19 +3862,19 @@ public:
}
};
-/// \brief Represents a reference to a non-type template parameter
+/// 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.
+ /// The replaced parameter.
NonTypeTemplateParmDecl *Param;
- /// \brief The replacement expression.
+ /// The replacement expression.
Stmt *Replacement;
- /// \brief The location of the non-type template parameter reference.
+ /// The location of the non-type template parameter reference.
SourceLocation NameLoc;
explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
@@ -3879,7 +3908,7 @@ public:
child_range children() { return child_range(&Replacement, &Replacement+1); }
};
-/// \brief Represents a reference to a non-type template parameter pack that
+/// Represents a reference to a non-type template parameter pack that
/// has been substituted with a non-template argument pack.
///
/// When a pack expansion in the source code contains multiple parameter packs
@@ -3895,17 +3924,17 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
friend class ASTReader;
friend class ASTStmtReader;
- /// \brief The non-type template parameter pack itself.
+ /// The non-type template parameter pack itself.
NonTypeTemplateParmDecl *Param;
- /// \brief A pointer to the set of template arguments that this
+ /// A pointer to the set of template arguments that this
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
- /// \brief The number of template arguments in \c Arguments.
+ /// The number of template arguments in \c Arguments.
unsigned NumArguments;
- /// \brief The location of the non-type template parameter pack reference.
+ /// The location of the non-type template parameter pack reference.
SourceLocation NameLoc;
explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
@@ -3913,17 +3942,18 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
public:
SubstNonTypeTemplateParmPackExpr(QualType T,
+ ExprValueKind ValueKind,
NonTypeTemplateParmDecl *Param,
SourceLocation NameLoc,
const TemplateArgument &ArgPack);
- /// \brief Retrieve the non-type template parameter pack being substituted.
+ /// Retrieve the non-type template parameter pack being substituted.
NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
- /// \brief Retrieve the location of the parameter pack name.
+ /// Retrieve the location of the parameter pack name.
SourceLocation getParameterPackLocation() const { return NameLoc; }
- /// \brief Retrieve the template argument pack containing the substituted
+ /// Retrieve the template argument pack containing the substituted
/// template arguments.
TemplateArgument getArgumentPack() const;
@@ -3940,7 +3970,7 @@ public:
}
};
-/// \brief Represents a reference to a function parameter pack that has been
+/// Represents a reference to a function parameter pack that has been
/// substituted but not yet expanded.
///
/// When a pack expansion contains multiple parameter packs at different levels,
@@ -3961,13 +3991,13 @@ class FunctionParmPackExpr final
friend class ASTStmtReader;
friend TrailingObjects;
- /// \brief The function parameter pack which was referenced.
+ /// The function parameter pack which was referenced.
ParmVarDecl *ParamPack;
- /// \brief The location of the function parameter pack reference.
+ /// The location of the function parameter pack reference.
SourceLocation NameLoc;
- /// \brief The number of expansions of this pack.
+ /// The number of expansions of this pack.
unsigned NumParameters;
FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
@@ -3982,22 +4012,22 @@ public:
static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context,
unsigned NumParams);
- /// \brief Get the parameter pack which this expression refers to.
+ /// Get the parameter pack which this expression refers to.
ParmVarDecl *getParameterPack() const { return ParamPack; }
- /// \brief Get the location of the parameter pack.
+ /// Get the location of the parameter pack.
SourceLocation getParameterPackLocation() const { return NameLoc; }
- /// \brief Iterators over the parameters which the parameter pack expanded
+ /// Iterators over the parameters which the parameter pack expanded
/// into.
using iterator = ParmVarDecl * const *;
iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); }
iterator end() const { return begin() + NumParameters; }
- /// \brief Get the number of parameters in this parameter pack.
+ /// Get the number of parameters in this parameter pack.
unsigned getNumExpansions() const { return NumParameters; }
- /// \brief Get an expansion of the parameter pack by index.
+ /// Get an expansion of the parameter pack by index.
ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; }
SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
@@ -4012,7 +4042,7 @@ public:
}
};
-/// \brief Represents a prvalue temporary that is written into memory so that
+/// Represents a prvalue temporary that is written into memory so that
/// a reference can bind to it.
///
/// Prvalue expressions are materialized when they need to have an address
@@ -4038,11 +4068,11 @@ private:
friend class ASTStmtWriter;
struct ExtraState {
- /// \brief The temporary-generating expression whose value will be
+ /// The temporary-generating expression whose value will be
/// materialized.
Stmt *Temporary;
- /// \brief The declaration which lifetime-extended this reference, if any.
+ /// The declaration which lifetime-extended this reference, if any.
/// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
const ValueDecl *ExtendingDecl;
@@ -4071,11 +4101,11 @@ public:
: State.get<ExtraState *>()->Temporary;
}
- /// \brief Retrieve the temporary-generating subexpression whose value will
+ /// Retrieve the temporary-generating subexpression whose value will
/// be materialized into a glvalue.
Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); }
- /// \brief Retrieve the storage duration for the materialized temporary.
+ /// Retrieve the storage duration for the materialized temporary.
StorageDuration getStorageDuration() const {
const ValueDecl *ExtendingDecl = getExtendingDecl();
if (!ExtendingDecl)
@@ -4093,7 +4123,7 @@ public:
return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
}
- /// \brief Get the declaration which triggered the lifetime-extension of this
+ /// Get the declaration which triggered the lifetime-extension of this
/// temporary, if any.
const ValueDecl *getExtendingDecl() const {
return State.is<Stmt *>() ? nullptr
@@ -4106,7 +4136,7 @@ public:
return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
}
- /// \brief Determine whether this materialized temporary is bound to an
+ /// Determine whether this materialized temporary is bound to an
/// lvalue reference; otherwise, it's bound to an rvalue reference.
bool isBoundToLvalueReference() const {
return getValueKind() == VK_LValue;
@@ -4134,7 +4164,7 @@ public:
}
};
-/// \brief Represents a folding of a pack over an operator.
+/// Represents a folding of a pack over an operator.
///
/// This expression is always dependent and represents a pack expansion of the
/// forms:
@@ -4203,7 +4233,7 @@ public:
child_range children() { return child_range(SubExprs, SubExprs + 2); }
};
-/// \brief Represents an expression that might suspend coroutine execution;
+/// Represents an expression that might suspend coroutine execution;
/// either a co_await or co_yield expression.
///
/// Evaluation of this expression first evaluates its 'ready' expression. If
@@ -4267,7 +4297,7 @@ public:
return static_cast<Expr*>(SubExprs[SubExpr::Common]);
}
- /// \brief getOpaqueValue - Return the opaque value placeholder.
+ /// getOpaqueValue - Return the opaque value placeholder.
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
Expr *getReadyExpr() const {
@@ -4300,7 +4330,7 @@ public:
}
};
-/// \brief Represents a 'co_await' expression.
+/// Represents a 'co_await' expression.
class CoawaitExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
@@ -4335,7 +4365,7 @@ public:
}
};
-/// \brief Represents a 'co_await' expression while the type of the promise
+/// Represents a 'co_await' expression while the type of the promise
/// is dependent.
class DependentCoawaitExpr : public Expr {
friend class ASTStmtReader;
@@ -4383,7 +4413,7 @@ public:
}
};
-/// \brief Represents a 'co_yield' expression.
+/// Represents a 'co_yield' expression.
class CoyieldExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
index ab2df8a34819..bb0402c27080 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
@@ -25,7 +25,6 @@
#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"
@@ -36,6 +35,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstddef>
@@ -90,16 +90,16 @@ public:
Value(val), Loc(l) {}
explicit ObjCBoolLiteralExpr(EmptyShell Empty)
: Expr(ObjCBoolLiteralExprClass, Empty) {}
-
+
bool getValue() const { return Value; }
void setValue(bool V) { Value = V; }
-
+
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
-
+
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
@@ -124,30 +124,30 @@ public:
ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
SourceRange R)
- : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
- E->isTypeDependent(), E->isValueDependent(),
+ : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
+ E->isTypeDependent(), E->isValueDependent(),
E->isInstantiationDependent(),
- E->containsUnexpandedParameterPack()),
+ E->containsUnexpandedParameterPack()),
SubExpr(E), BoxingMethod(method), Range(R) {}
explicit ObjCBoxedExpr(EmptyShell Empty)
: Expr(ObjCBoxedExprClass, Empty) {}
-
+
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
-
+
ObjCMethodDecl *getBoxingMethod() const {
- return BoxingMethod;
+ return BoxingMethod;
}
-
+
SourceLocation getAtLoc() const { return Range.getBegin(); }
-
+
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY {
return Range;
}
-
+
// Iterators
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
@@ -198,31 +198,31 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- /// \brief Retrieve elements of array of literals.
+ /// Retrieve elements of array of literals.
Expr **getElements() { return getTrailingObjects<Expr *>(); }
- /// \brief Retrieve elements of array of literals.
+ /// Retrieve elements of array of literals.
const Expr * const *getElements() const {
return getTrailingObjects<Expr *>();
}
/// getNumElements - Return number of elements of objective-c array literal.
unsigned getNumElements() const { return NumElements; }
-
+
/// 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]);
+ return getElements()[Index];
}
const Expr *getElement(unsigned Index) const {
assert((Index < NumElements) && "Arg access out of range!");
- return cast<Expr>(getElements()[Index]);
+ return getElements()[Index];
}
-
+
ObjCMethodDecl *getArrayWithObjectsMethod() const {
- return ArrayWithObjectsMethod;
+ return ArrayWithObjectsMethod;
}
-
+
// Iterators
child_range children() {
return child_range(reinterpret_cast<Stmt **>(getElements()),
@@ -234,23 +234,23 @@ public:
}
};
-/// \brief An element in an Objective-C dictionary literal.
+/// An element in an Objective-C dictionary literal.
///
struct ObjCDictionaryElement {
- /// \brief The key for the dictionary element.
+ /// The key for the dictionary element.
Expr *Key;
-
- /// \brief The value of the dictionary element.
+
+ /// The value of the dictionary element.
Expr *Value;
-
- /// \brief The location of the ellipsis, if this is a pack expansion.
+
+ /// The location of the ellipsis, if this is a pack expansion.
SourceLocation EllipsisLoc;
-
- /// \brief The number of elements this pack expansion will expand to, if
+
+ /// The number of elements this pack expansion will expand to, if
/// this is a pack expansion and is known.
Optional<unsigned> NumExpansions;
- /// \brief Determines whether this dictionary element is a pack expansion.
+ /// Determines whether this dictionary element is a pack expansion.
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
};
@@ -264,21 +264,21 @@ template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
namespace clang {
-/// \brief Internal struct for storing Key/value pair.
+/// Internal struct for storing Key/value pair.
struct ObjCDictionaryLiteral_KeyValuePair {
Expr *Key;
Expr *Value;
};
-/// \brief Internal struct to describes an element that is a pack
+/// Internal struct to describes an element that is a pack
/// expansion, used if any of the elements in the dictionary literal
/// are pack expansions.
struct ObjCDictionaryLiteral_ExpansionData {
- /// \brief The location of the ellipsis, if this element is a pack
+ /// The location of the ellipsis, if this element is a pack
/// expansion.
SourceLocation EllipsisLoc;
- /// \brief If non-zero, the number of elements that this pack
+ /// If non-zero, the number of elements that this pack
/// expansion will expand to (+1).
unsigned NumExpansionsPlusOne;
};
@@ -290,10 +290,10 @@ class ObjCDictionaryLiteral final
private llvm::TrailingObjects<ObjCDictionaryLiteral,
ObjCDictionaryLiteral_KeyValuePair,
ObjCDictionaryLiteral_ExpansionData> {
- /// \brief The number of elements in this dictionary literal.
+ /// The number of elements in this dictionary literal.
unsigned NumElements : 31;
- /// \brief Determine whether this dictionary literal has any pack expansions.
+ /// Determine whether this dictionary literal has any pack expansions.
///
/// If the dictionary literal has pack expansions, then there will
/// be an array of pack expansion data following the array of
@@ -308,7 +308,7 @@ class ObjCDictionaryLiteral final
using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair;
using ExpansionData = ObjCDictionaryLiteral_ExpansionData;
- ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
+ ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions,
QualType T, ObjCMethodDecl *method,
SourceRange SR);
@@ -328,16 +328,16 @@ public:
friend TrailingObjects;
static ObjCDictionaryLiteral *Create(const ASTContext &C,
- ArrayRef<ObjCDictionaryElement> VK,
+ ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions,
QualType T, ObjCMethodDecl *method,
SourceRange SR);
-
+
static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
unsigned NumElements,
bool HasPackExpansions);
-
- /// getNumElements - Return number of elements of objective-c dictionary
+
+ /// getNumElements - Return number of elements of objective-c dictionary
/// literal.
unsigned getNumElements() const { return NumElements; }
@@ -354,7 +354,7 @@ public:
}
return Result;
}
-
+
ObjCMethodDecl *getDictWithObjectsMethod() const {
return DictWithObjectsMethod;
}
@@ -394,7 +394,7 @@ public:
EncodedType->getType()->isDependentType(),
EncodedType->getType()->isDependentType(),
EncodedType->getType()->isInstantiationDependentType(),
- EncodedType->getType()->containsUnexpandedParameterPack()),
+ EncodedType->getType()->containsUnexpandedParameterPack()),
EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
@@ -408,8 +408,8 @@ public:
TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
- void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
- EncodedType = EncType;
+ void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
+ EncodedType = EncType;
}
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
@@ -531,9 +531,9 @@ public:
bool arrow = false, bool freeIvar = false)
: Expr(ObjCIvarRefExprClass, t, VK_LValue,
d->isBitField() ? OK_BitField : OK_Ordinary,
- /*TypeDependent=*/false, base->isValueDependent(),
+ /*TypeDependent=*/false, base->isValueDependent(),
base->isInstantiationDependent(),
- base->containsUnexpandedParameterPack()),
+ base->containsUnexpandedParameterPack()),
D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow),
IsFreeIvar(freeIvar) {}
@@ -560,7 +560,7 @@ public:
return isFreeIvar() ? Loc : getBase()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
-
+
SourceLocation getOpLoc() const { return OpLoc; }
void setOpLoc(SourceLocation L) { OpLoc = L; }
@@ -582,7 +582,7 @@ private:
/// the pointer is an ObjCPropertyDecl and Setter is always null.
llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter;
- /// \brief Indicates whether the property reference will result in a message
+ /// Indicates whether the property reference will result in a message
/// to the getter, the setter, or both.
/// This applies to both implicit and explicit property references.
enum MethodRefFlags {
@@ -591,7 +591,7 @@ private:
MethodRef_Setter = 0x2
};
- /// \brief Contains the Setter method pointer and MethodRefFlags bit flags.
+ /// Contains the Setter method pointer and MethodRefFlags bit flags.
llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;
// FIXME: Maybe we should store the property identifier here,
@@ -600,13 +600,13 @@ private:
// transformation is lossy on the first character).
SourceLocation IdLoc;
-
- /// \brief When the receiver in property access is 'super', this is
+
+ /// When the receiver in property access is 'super', this is
/// the location of the 'super' keyword. When it's an interface,
/// this is that interface.
SourceLocation ReceiverLoc;
llvm::PointerUnion3<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;
-
+
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
ExprValueKind VK, ExprObjectKind OK,
@@ -618,7 +618,7 @@ public:
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)
@@ -694,14 +694,14 @@ public:
return getExplicitProperty()->getSetterName();
}
- /// \brief True if the property reference will result in a message to the
+ /// True if the property reference will result in a message to the
/// getter.
/// This applies to both implicit and explicit property references.
bool isMessagingGetter() const {
return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
}
- /// \brief True if the property reference will result in a message to the
+ /// True if the property reference will result in a message to the
/// setter.
/// This applies to both implicit and explicit property references.
bool isMessagingSetter() const {
@@ -716,19 +716,19 @@ public:
setMethodRefFlag(MethodRef_Setter, val);
}
- const Expr *getBase() const {
- return cast<Expr>(Receiver.get<Stmt*>());
+ const Expr *getBase() const {
+ return cast<Expr>(Receiver.get<Stmt*>());
}
- Expr *getBase() {
- return cast<Expr>(Receiver.get<Stmt*>());
+ Expr *getBase() {
+ return cast<Expr>(Receiver.get<Stmt*>());
}
SourceLocation getLocation() const { return IdLoc; }
-
+
SourceLocation getReceiverLocation() const { return ReceiverLoc; }
- QualType getSuperReceiverType() const {
- return QualType(Receiver.get<const Type*>(), 0);
+ QualType getSuperReceiverType() const {
+ return QualType(Receiver.get<const Type*>(), 0);
}
ObjCInterfaceDecl *getClassReceiver() const {
@@ -796,7 +796,7 @@ private:
SetterAndMethodRefFlags.setInt(f);
}
};
-
+
/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
class ObjCSubscriptRefExpr : public Expr {
@@ -808,20 +808,20 @@ class ObjCSubscriptRefExpr : public Expr {
// an objective-c object pointer expression.
enum { BASE, KEY, END_EXPR };
Stmt* SubExprs[END_EXPR];
-
+
ObjCMethodDecl *GetAtIndexMethodDecl;
-
+
// For immutable objects this is null. When ObjCSubscriptRefExpr is to read
// an indexed object this is null too.
ObjCMethodDecl *SetAtIndexMethodDecl;
-
+
public:
ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
ExprValueKind VK, ExprObjectKind OK,
ObjCMethodDecl *getMethod,
ObjCMethodDecl *setMethod, SourceLocation RB)
- : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
- base->isTypeDependent() || key->isTypeDependent(),
+ : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
+ base->isTypeDependent() || key->isTypeDependent(),
base->isValueDependent() || key->isValueDependent(),
(base->isInstantiationDependent() ||
key->isInstantiationDependent()),
@@ -834,7 +834,7 @@ public:
explicit ObjCSubscriptRefExpr(EmptyShell Empty)
: Expr(ObjCSubscriptRefExprClass, Empty) {}
-
+
SourceLocation getRBracket() const { return RBracket; }
void setRBracket(SourceLocation RB) { RBracket = RB; }
@@ -843,25 +843,25 @@ public:
}
SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
-
+
Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
-
+
Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }
-
+
ObjCMethodDecl *getAtIndexMethodDecl() const {
return GetAtIndexMethodDecl;
}
-
+
ObjCMethodDecl *setAtIndexMethodDecl() const {
return SetAtIndexMethodDecl;
}
-
+
bool isArraySubscriptRefExpr() const {
return getKeyExpr()->getType()->isIntegralOrEnumerationType();
}
-
+
child_range children() {
return child_range(SubExprs, SubExprs+END_EXPR);
}
@@ -874,7 +874,7 @@ private:
friend class ASTStmtReader;
};
-/// \brief An expression that sends a message to the given Objective-C
+/// An expression that sends a message to the given Objective-C
/// object or class.
///
/// The following contains two message send expressions:
@@ -903,47 +903,47 @@ private:
class ObjCMessageExpr final
: public Expr,
private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> {
- /// \brief Stores either the selector that this message is sending
+ /// 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 = 0;
enum { NumArgsBitWidth = 16 };
- /// \brief The number of arguments in the message send, not
+ /// The number of arguments in the message send, not
/// including the receiver.
unsigned NumArgs : NumArgsBitWidth;
-
- /// \brief The kind of message send this is, which is one of the
+
+ /// The kind of message send this is, which is one of the
/// ReceiverKind values.
///
/// We pad this out to a byte to avoid excessive masking and shifting.
unsigned Kind : 8;
- /// \brief Whether we have an actual method prototype in \c
+ /// Whether we have an actual method prototype in \c
/// SelectorOrMethod.
///
/// When non-zero, we have a method declaration; otherwise, we just
/// have a selector.
unsigned HasMethod : 1;
- /// \brief Whether this message send is a "delegate init call",
+ /// Whether this message send is a "delegate init call",
/// i.e. a call of an init method on self from within an init method.
unsigned IsDelegateInitCall : 1;
- /// \brief Whether this message send was implicitly generated by
+ /// Whether this message send was implicitly generated by
/// the implementation rather than explicitly written by the user.
unsigned IsImplicit : 1;
- /// \brief Whether the locations of the selector identifiers are in a
+ /// Whether the locations of the selector identifiers are in a
/// "standard" position, a enum SelectorLocationsKind.
unsigned SelLocsKind : 2;
- /// \brief When the message expression is a send to 'super', this is
+ /// When the message expression is a send to 'super', this is
/// the location of the 'super' keyword.
SourceLocation SuperLoc;
- /// \brief The source locations of the open and close square
+ /// The source locations of the open and close square
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
@@ -958,7 +958,7 @@ class ObjCMessageExpr final
SourceLocation SuperLoc,
bool IsInstanceSuper,
QualType SuperType,
- Selector Sel,
+ Selector Sel,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
@@ -968,7 +968,7 @@ class ObjCMessageExpr final
ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
- Selector Sel,
+ Selector Sel,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
@@ -978,7 +978,7 @@ class ObjCMessageExpr final
ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
- Selector Sel,
+ Selector Sel,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
@@ -997,10 +997,10 @@ class ObjCMessageExpr final
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK);
- /// \brief Retrieve the pointer value of the message receiver.
+ /// Retrieve the pointer value of the message receiver.
void *getReceiverPointer() const { return *getTrailingObjects<void *>(); }
- /// \brief Set the pointer value of the message receiver.
+ /// Set the pointer value of the message receiver.
void setReceiverPointer(void *Value) {
*getTrailingObjects<void *>() = Value;
}
@@ -1013,7 +1013,7 @@ class ObjCMessageExpr final
return getSelLocsKind() != SelLoc_NonStandard;
}
- /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
return getTrailingObjects<SourceLocation>();
@@ -1022,7 +1022,7 @@ class ObjCMessageExpr final
return getTrailingObjects<SourceLocation>();
}
- /// \brief Get the number of stored selector identifiers locations.
+ /// Get the number of stored selector identifiers locations.
/// No locations will be stored if HasStandardSelLocs is true.
unsigned getNumStoredSelLocs() const {
if (hasStandardSelLocs())
@@ -1045,22 +1045,22 @@ public:
friend class ASTStmtWriter;
friend TrailingObjects;
- /// \brief The kind of receiver this message is sending to.
+ /// The kind of receiver this message is sending to.
enum ReceiverKind {
- /// \brief The receiver is a class.
+ /// The receiver is a class.
Class = 0,
- /// \brief The receiver is an object instance.
+ /// The receiver is an object instance.
Instance,
- /// \brief The receiver is a superclass.
+ /// The receiver is a superclass.
SuperClass,
- /// \brief The receiver is the instance of the superclass object.
+ /// The receiver is the instance of the superclass object.
SuperInstance
};
- /// \brief Create a message send to super.
+ /// Create a message send to super.
///
/// \param Context The ASTContext in which this expression will be created.
///
@@ -1091,14 +1091,14 @@ public:
SourceLocation SuperLoc,
bool IsInstanceSuper,
QualType SuperType,
- Selector Sel,
+ Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc,
bool isImplicit);
- /// \brief Create a class message send.
+ /// Create a class message send.
///
/// \param Context The ASTContext in which this expression will be created.
///
@@ -1125,14 +1125,14 @@ public:
ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
- Selector Sel,
+ Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc,
bool isImplicit);
- /// \brief Create an instance message send.
+ /// Create an instance message send.
///
/// \param Context The ASTContext in which this expression will be created.
///
@@ -1159,14 +1159,14 @@ public:
ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
- Selector Sel,
+ Selector Sel,
ArrayRef<SourceLocation> SeLocs,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc,
bool isImplicit);
- /// \brief Create an empty Objective-C message expression, to be
+ /// Create an empty Objective-C message expression, to be
/// filled in by subsequent calls.
///
/// \param Context The context in which the message send will be created.
@@ -1177,31 +1177,31 @@ public:
unsigned NumArgs,
unsigned NumStoredSelLocs);
- /// \brief Indicates whether the message send was implicitly
+ /// Indicates whether the message send was implicitly
/// generated by the implementation. If false, it was written explicitly
/// in the source code.
bool isImplicit() const { return IsImplicit; }
- /// \brief Determine the kind of receiver that this message is being
+ /// Determine the kind of receiver that this message is being
/// sent to.
ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
- /// \brief Source range of the receiver.
+ /// Source range of the receiver.
SourceRange getReceiverRange() const;
- /// \brief Determine whether this is an instance message to either a
+ /// Determine whether this is an instance message to either a
/// computed object or to super.
bool isInstanceMessage() const {
return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
}
- /// \brief Determine whether this is an class message to either a
+ /// Determine whether this is an class message to either a
/// specified class or to super.
bool isClassMessage() const {
return getReceiverKind() == Class || getReceiverKind() == SuperClass;
}
- /// \brief Returns the object expression (receiver) for an instance message,
+ /// Returns the object expression (receiver) for an instance message,
/// or null for a message that is not an instance message.
Expr *getInstanceReceiver() {
if (getReceiverKind() == Instance)
@@ -1213,23 +1213,23 @@ public:
return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
}
- /// \brief Turn this message send into an instance message that
+ /// Turn this message send into an instance message that
/// computes the receiver object with the given expression.
- void setInstanceReceiver(Expr *rec) {
+ void setInstanceReceiver(Expr *rec) {
Kind = Instance;
setReceiverPointer(rec);
}
-
- /// \brief Returns the type of a class message send, or NULL if the
+
+ /// Returns the type of a class message send, or NULL if the
/// message is not a class message.
- QualType getClassReceiver() const {
+ QualType getClassReceiver() const {
if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
return TSInfo->getType();
return {};
}
- /// \brief Returns a type-source information of a class message
+ /// Returns a type-source information of a class message
/// send, or nullptr if the message is not a class message.
TypeSourceInfo *getClassReceiverTypeInfo() const {
if (getReceiverKind() == Class)
@@ -1242,16 +1242,16 @@ public:
setReceiverPointer(TSInfo);
}
- /// \brief Retrieve the location of the 'super' keyword for a class
+ /// Retrieve the location of the 'super' keyword for a class
/// or instance message to 'super', otherwise an invalid source location.
- SourceLocation getSuperLoc() const {
+ SourceLocation getSuperLoc() const {
if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
return SuperLoc;
return SourceLocation();
}
- /// \brief Retrieve the receiver type to which this message is being directed.
+ /// Retrieve the receiver type to which this message is being directed.
///
/// This routine cross-cuts all of the different kinds of message
/// sends to determine what the underlying (statically known) type
@@ -1262,7 +1262,7 @@ public:
/// \returns The type of the receiver.
QualType getReceiverType() const;
- /// \brief Retrieve the Objective-C interface to which this message
+ /// Retrieve the Objective-C interface to which this message
/// is being directed, if known.
///
/// This routine cross-cuts all of the different kinds of message
@@ -1274,7 +1274,7 @@ public:
/// \returns The Objective-C interface if known, otherwise nullptr.
ObjCInterfaceDecl *getReceiverInterface() const;
- /// \brief Retrieve the type referred to by 'super'.
+ /// Retrieve the type referred to by 'super'.
///
/// The returned type will either be an ObjCInterfaceType (for an
/// class message to super) or an ObjCObjectPointerType that refers
@@ -1294,26 +1294,26 @@ public:
Selector getSelector() const;
- void setSelector(Selector S) {
+ void setSelector(Selector S) {
HasMethod = false;
SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
}
- const ObjCMethodDecl *getMethodDecl() const {
+ const ObjCMethodDecl *getMethodDecl() const {
if (HasMethod)
return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
return nullptr;
}
- ObjCMethodDecl *getMethodDecl() {
+ ObjCMethodDecl *getMethodDecl() {
if (HasMethod)
return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
return nullptr;
}
- void setMethodDecl(ObjCMethodDecl *MD) {
+ void setMethodDecl(ObjCMethodDecl *MD) {
HasMethod = true;
SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
}
@@ -1323,11 +1323,11 @@ public:
return getSelector().getMethodFamily();
}
- /// \brief Return the number of actual arguments in this message,
+ /// Return the number of actual arguments in this message,
/// not counting the receiver.
unsigned getNumArgs() const { return NumArgs; }
- /// \brief Retrieve the arguments to this message, not including the
+ /// Retrieve the arguments to this message, not including the
/// receiver.
Expr **getArgs() {
return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1);
@@ -1414,16 +1414,16 @@ public:
arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
- arg_iterator arg_end() {
- return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
+ 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_begin() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs());
}
- const_arg_iterator arg_end() const {
- return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
+ const_arg_iterator arg_end() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
}
static bool classof(const Stmt *T) {
@@ -1439,7 +1439,7 @@ class ObjCIsaExpr : public Expr {
/// IsaMemberLoc - This is the location of the 'isa'.
SourceLocation IsaMemberLoc;
-
+
/// OpLoc - This is the location of '.' or '->'
SourceLocation OpLoc;
@@ -1455,7 +1455,7 @@ public:
/*ContainsUnexpandedParameterPack=*/false),
Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
- /// \brief Build an empty expression.
+ /// Build an empty expression.
explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {}
void setBase(Expr *E) { Base = E; }
@@ -1468,18 +1468,18 @@ public:
/// location of 'F'.
SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
-
+
SourceLocation getOpLoc() const { return OpLoc; }
void setOpLoc(SourceLocation L) { OpLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY {
return getBase()->getLocStart();
}
-
+
SourceLocation getBaseLocEnd() const LLVM_READONLY {
return getBase()->getLocEnd();
}
-
+
SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; }
SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
@@ -1546,7 +1546,7 @@ public:
/// copy-restore. If false, the temporary will be zero-initialized.
bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }
- child_range children() { return child_range(&Operand, &Operand+1); }
+ child_range children() { return child_range(&Operand, &Operand+1); }
// Source locations are determined by the subexpression.
SourceLocation getLocStart() const LLVM_READONLY {
@@ -1563,7 +1563,7 @@ public:
}
};
-/// \brief An Objective-C "bridged" cast expression, which casts between
+/// An Objective-C "bridged" cast expression, which casts between
/// Objective-C pointers and C pointers, transferring ownership in the process.
///
/// \code
@@ -1571,7 +1571,8 @@ public:
/// \endcode
class ObjCBridgedCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<
+ ObjCBridgedCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class CastExpr;
@@ -1581,6 +1582,10 @@ class ObjCBridgedCastExpr final
SourceLocation BridgeKeywordLoc;
unsigned Kind : 2;
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
CastKind CK, SourceLocation BridgeKeywordLoc,
@@ -1588,36 +1593,36 @@ public:
: ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
CK, Operand, 0, TSInfo),
LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {}
-
- /// \brief Construct an empty Objective-C bridged cast.
+
+ /// Construct an empty Objective-C bridged cast.
explicit ObjCBridgedCastExpr(EmptyShell Shell)
: ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {}
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Determine which kind of bridge is being performed via this cast.
- ObjCBridgeCastKind getBridgeKind() const {
- return static_cast<ObjCBridgeCastKind>(Kind);
+ /// Determine which kind of bridge is being performed via this cast.
+ ObjCBridgeCastKind getBridgeKind() const {
+ return static_cast<ObjCBridgeCastKind>(Kind);
}
-
- /// \brief Retrieve the kind of bridge being performed as a string.
+
+ /// Retrieve the kind of bridge being performed as a string.
StringRef getBridgeKindName() const;
-
- /// \brief The location of the bridge keyword.
+
+ /// The location of the bridge keyword.
SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
-
+
SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return getSubExpr()->getLocEnd();
}
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCBridgedCastExprClass;
}
};
-/// \brief A runtime availability query.
+/// A runtime availability query.
///
/// There are 2 ways to spell this node:
/// \code
@@ -1650,7 +1655,7 @@ public:
SourceLocation getLocEnd() const { return RParen; }
SourceRange getSourceRange() const { return {AtLoc, RParen}; }
- /// \brief This may be '*', in which case this should fold to true.
+ /// This may be '*', in which case this should fold to true.
bool hasVersion() const { return !VersionToCheck.empty(); }
VersionTuple getVersion() { return VersionToCheck; }
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
index a4ef93ba8b14..2b4b5ec4d0e4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
@@ -17,7 +17,7 @@
#include "clang/AST/Expr.h"
namespace clang {
-/// \brief OpenMP 4.0 [2.4, Array Sections].
+/// OpenMP 4.0 [2.4, Array Sections].
/// To specify an array section in an OpenMP construct, array subscript
/// expressions are extended with the following syntax:
/// \code
@@ -72,33 +72,33 @@ public:
SubExprs[LENGTH] = Length;
}
- /// \brief Create an empty array section expression.
+ /// Create an empty array section expression.
explicit OMPArraySectionExpr(EmptyShell Shell)
: Expr(OMPArraySectionExprClass, Shell) {}
/// An array section can be written only as Base[LowerBound:Length].
- /// \brief Get base of the array section.
+ /// Get base of the array section.
Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
- /// \brief Set base of the array section.
+ /// Set base of the array section.
void setBase(Expr *E) { SubExprs[BASE] = E; }
- /// \brief Return original type of the base expression for array section.
+ /// Return original type of the base expression for array section.
static QualType getBaseOriginalType(const Expr *Base);
- /// \brief Get lower bound of array section.
+ /// Get lower bound of array section.
Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
const Expr *getLowerBound() const {
return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
}
- /// \brief Set lower bound of the array section.
+ /// Set lower bound of the array section.
void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
- /// \brief Get length of array section.
+ /// Get length of array section.
Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
- /// \brief Set length of the array section.
+ /// Set length of the array section.
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
SourceLocation getLocStart() const LLVM_READONLY {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h
index 81492aec6e13..7b01fa8cbced 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h
@@ -37,7 +37,7 @@ namespace clang {
/// 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.
+/// - 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.
@@ -57,7 +57,7 @@ public:
typedef std::map<const DeclContext *, DCOrigin> OriginMap;
typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
private:
- /// One importer exists for each source.
+ /// One importer exists for each source.
ImporterVector Importers;
/// Overrides in case name lookup would return nothing or would return
/// the wrong thing.
@@ -97,7 +97,7 @@ public:
/// 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,
+ /// ExternalASTMergers may need to import from new sources (for example,
/// newly-parsed source files).
///
/// Ensures that Importers does not gain duplicate entries as a result.
@@ -106,7 +106,7 @@ public:
/// 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).
+ /// superseded by a newer version).
///
/// The caller is responsible for ensuring that this doesn't leave
/// DeclContexts that can't be completed.
@@ -163,7 +163,7 @@ private:
template <typename CallbackType>
void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
-public:
+public:
/// Log something if there is a logging callback installed.
llvm::raw_ostream &logs() { return *LogStream; }
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
index be013c5d6b6a..525d4c78b362 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
@@ -19,7 +19,6 @@
#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"
@@ -54,7 +53,7 @@ class Selector;
class Stmt;
class TagDecl;
-/// \brief Abstract interface for external sources of AST nodes.
+/// Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
/// external source, such as a precompiled header. External AST
@@ -68,7 +67,7 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
/// whenever we might have added new redeclarations for existing decls.
uint32_t CurrentGeneration = 0;
- /// \brief Whether this AST source also provides information for
+ /// Whether this AST source also provides information for
/// semantic analysis.
bool SemaSource = false;
@@ -76,7 +75,7 @@ public:
ExternalASTSource() = default;
virtual ~ExternalASTSource();
- /// \brief RAII class for safely pairing a StartedDeserializing call
+ /// RAII class for safely pairing a StartedDeserializing call
/// with FinishedDeserializing.
class Deserializing {
ExternalASTSource *Source;
@@ -92,12 +91,12 @@ public:
}
};
- /// \brief Get the current generation of this AST source. This number
+ /// Get the current generation of this AST source. This number
/// is incremented each time the AST source lazily extends an existing
/// entity.
uint32_t getGeneration() const { return CurrentGeneration; }
- /// \brief Resolve a declaration ID into a declaration, potentially
+ /// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
///
/// This method only needs to be implemented if the AST source ever
@@ -106,7 +105,7 @@ public:
/// The default implementation of this method is a no-op.
virtual Decl *GetExternalDecl(uint32_t ID);
- /// \brief Resolve a selector ID into a selector.
+ /// Resolve a selector ID into a selector.
///
/// This operation only needs to be implemented if the AST source
/// returns non-zero for GetNumKnownSelectors().
@@ -114,13 +113,13 @@ public:
/// The default implementation of this method is a no-op.
virtual Selector GetExternalSelector(uint32_t ID);
- /// \brief Returns the number of selectors known to the external AST
+ /// Returns the number of selectors known to the external AST
/// source.
///
/// The default implementation of this method is a no-op.
virtual uint32_t GetNumExternalSelectors();
- /// \brief Resolve the offset of a statement in the decl stream into
+ /// Resolve the offset of a statement in the decl stream into
/// a statement.
///
/// This operation is meant to be used via a LazyOffsetPtr. It only
@@ -130,22 +129,22 @@ public:
/// The default implementation of this method is a no-op.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
- /// \brief Resolve the offset of a set of C++ constructor initializers in
+ /// Resolve the offset of a set of C++ constructor initializers in
/// the decl stream into an array of initializers.
///
/// The default implementation of this method is a no-op.
virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset);
- /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// Resolve the offset of a set of C++ base specifiers in the decl
/// stream into an array of specifiers.
///
/// The default implementation of this method is a no-op.
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
- /// \brief Update an out-of-date identifier.
+ /// Update an out-of-date identifier.
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {}
- /// \brief Find all declarations with the given name in the given context,
+ /// Find all declarations with the given name in the given context,
/// and add them to the context by calling SetExternalVisibleDeclsForName
/// or SetNoExternalVisibleDeclsForName.
/// \return \c true if any declarations might have been found, \c false if
@@ -155,15 +154,19 @@ public:
virtual bool
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
- /// \brief Ensures that the table of all visible declarations inside this
+ /// Ensures that the table of all visible declarations inside this
/// context is up to date.
///
/// The default implementation of this function is a no-op.
virtual void completeVisibleDeclsMap(const DeclContext *DC);
- /// \brief Retrieve the module that corresponds to the given module ID.
+ /// Retrieve the module that corresponds to the given module ID.
virtual Module *getModule(unsigned ID) { return nullptr; }
+ /// Determine whether D comes from a PCH which was built with a corresponding
+ /// object file.
+ virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; }
+
/// Abstracts clang modules and precompiled header files and holds
/// everything needed to generate debug info for an imported module
/// or PCH.
@@ -196,7 +199,7 @@ public:
virtual ExtKind hasExternalDefinitions(const Decl *D);
- /// \brief Finds all declarations lexically contained within the given
+ /// Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
/// \param IsKindWeWant a predicate function that returns true if the passed
@@ -208,31 +211,31 @@ public:
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Result);
- /// \brief Finds all declarations lexically contained within the given
+ /// Finds all declarations lexically contained within the given
/// DeclContext.
void FindExternalLexicalDecls(const DeclContext *DC,
SmallVectorImpl<Decl *> &Result) {
FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result);
}
- /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
/// a range.
virtual void FindFileRegionDecls(FileID File, unsigned Offset,
unsigned Length,
SmallVectorImpl<Decl *> &Decls);
- /// \brief Gives the external AST source an opportunity to complete
+ /// Gives the external AST source an opportunity to complete
/// the redeclaration chain for a declaration. Called each time we
/// need the most recent declaration of a declaration after the
/// generation count is incremented.
virtual void CompleteRedeclChain(const Decl *D);
- /// \brief Gives the external AST source an opportunity to complete
+ /// Gives the external AST source an opportunity to complete
/// an incomplete type.
virtual void CompleteType(TagDecl *Tag);
- /// \brief Gives the external AST source an opportunity to complete an
+ /// Gives the external AST source an opportunity to complete an
/// incomplete Objective-C class.
///
/// This routine will only be invoked if the "externally completed" bit is
@@ -240,37 +243,37 @@ public:
/// \c ObjCInterfaceDecl::setExternallyCompleted().
virtual void CompleteType(ObjCInterfaceDecl *Class);
- /// \brief Loads comment ranges.
+ /// Loads comment ranges.
virtual void ReadComments();
- /// \brief Notify ExternalASTSource that we started deserialization of
+ /// Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void StartedDeserializing();
- /// \brief Notify ExternalASTSource that we finished the deserialization of
+ /// Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void FinishedDeserializing();
- /// \brief Function that will be invoked when we begin parsing a new
+ /// Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
/// The default implementation of this method is a no-op.
virtual void StartTranslationUnit(ASTConsumer *Consumer);
- /// \brief Print any statistics that have been gathered regarding
+ /// Print any statistics that have been gathered regarding
/// the external AST source.
///
/// The default implementation of this method is a no-op.
virtual void PrintStats();
-
- /// \brief Perform layout on the given record.
+
+ /// Perform layout on the given record.
///
- /// This routine allows the external AST source to provide an specific
+ /// This routine allows the external AST source to provide an specific
/// layout for a record, overriding the layout that would normally be
/// constructed. It is intended for clients who receive specific layout
/// details rather than source code (such as LLDB). The client is expected
@@ -287,13 +290,13 @@ public:
/// expressed in bits. All of the fields must be provided with offsets.
///
/// \param BaseOffsets The offset of each of the direct, non-virtual base
- /// classes. If any bases are not given offsets, the bases will be laid
+ /// classes. If any bases are not given offsets, the bases will be laid
/// out according to the ABI.
///
/// \param VirtualBaseOffsets The offset of each of the virtual base classes
- /// (either direct or not). If any bases are not given offsets, the bases will be laid
+ /// (either direct or not). If any bases are not given offsets, the bases will be laid
/// out according to the ABI.
- ///
+ ///
/// \returns true if the record layout was provided, false otherwise.
virtual bool layoutRecordType(
const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
@@ -304,15 +307,15 @@ public:
//===--------------------------------------------------------------------===//
// Queries for performance analysis.
//===--------------------------------------------------------------------===//
-
+
struct MemoryBufferSizes {
size_t malloc_bytes;
size_t mmap_bytes;
-
+
MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
: malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
-
+
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
MemoryBufferSizes getMemoryBufferSizes() const {
@@ -333,11 +336,11 @@ protected:
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name);
- /// \brief Increment the current generation.
+ /// Increment the current generation.
uint32_t incrementGeneration(ASTContext &C);
};
-/// \brief A lazy pointer to an AST node (of base type T) that resides
+/// A lazy pointer to an AST node (of base type T) that resides
/// within an external AST source.
///
/// The AST node is identified within the external AST source by a
@@ -345,7 +348,7 @@ protected:
/// external AST source itself.
template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
struct LazyOffsetPtr {
- /// \brief Either a pointer to an AST node or the offset within the
+ /// Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found.
///
/// If the low bit is clear, a pointer to the AST node. If the low
@@ -377,20 +380,20 @@ public:
return *this;
}
- /// \brief Whether this pointer is non-NULL.
+ /// Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
explicit operator bool() const { return Ptr != 0; }
- /// \brief Whether this pointer is non-NULL.
+ /// Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
bool isValid() const { return Ptr != 0; }
- /// \brief Whether this pointer is currently stored as an offset.
+ /// Whether this pointer is currently stored as an offset.
bool isOffset() const { return Ptr & 0x01; }
- /// \brief Retrieve the pointer to the AST node that this lazy pointer
+ /// Retrieve the pointer to the AST node that this lazy pointer points to.
///
/// \param Source the external AST source.
///
@@ -405,7 +408,7 @@ public:
}
};
-/// \brief A lazy value (of type T) that is within an AST node of type Owner,
+/// A lazy value (of type T) that is within an AST node of type Owner,
/// where the value might change in later generations of the external AST
/// source.
template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)>
@@ -447,7 +450,7 @@ public:
/// Set the value of this pointer, in the current generation.
void set(T NewValue) {
- if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) {
+ if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) {
LazyVal->LastValue = NewValue;
return;
}
@@ -459,7 +462,7 @@ public:
/// Get the value of this pointer, updating its owner if necessary.
T get(Owner O) {
- if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) {
+ if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) {
if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) {
LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration();
(LazyVal->ExternalSource->*Update)(O);
@@ -471,7 +474,7 @@ public:
/// Get the most recently computed value of this pointer without updating it.
T getNotUpdated() const {
- if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>())
+ if (auto *LazyVal = Value.template dyn_cast<LazyData *>())
return LazyVal->LastValue;
return Value.template get<T>();
}
@@ -506,13 +509,13 @@ struct PointerLikeTypeTraits<
namespace clang {
-/// \brief Represents a lazily-loaded vector of data.
+/// Represents a lazily-loaded vector of data.
///
/// The lazily-loaded vector of data contains data that is partially loaded
-/// from an external source and partially added by local translation. The
+/// from an external source and partially added by local translation. The
/// items loaded from the external source are loaded lazily, when needed for
/// iteration over the complete vector.
-template<typename T, typename Source,
+template<typename T, typename Source,
void (Source::*Loader)(SmallVectorImpl<T>&),
unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
class LazyVector {
@@ -561,20 +564,20 @@ public:
iterator begin(Source *source, bool LocalOnly = false) {
if (LocalOnly)
return iterator(this, 0);
-
+
if (source)
(source->*Loader)(Loaded);
return iterator(this, -(int)Loaded.size());
}
-
+
iterator end() {
return iterator(this, Local.size());
}
-
+
void push_back(const T& LocalValue) {
Local.push_back(LocalValue);
}
-
+
void erase(iterator From, iterator To) {
if (From.isLoaded() && To.isLoaded()) {
Loaded.erase(&*From, &*To);
@@ -590,20 +593,20 @@ public:
}
};
-/// \brief A lazy pointer to a statement.
+/// A lazy pointer to a statement.
using LazyDeclStmtPtr =
LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>;
-/// \brief A lazy pointer to a declaration.
+/// A lazy pointer to a declaration.
using LazyDeclPtr =
LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>;
-/// \brief A lazy pointer to a set of CXXCtorInitializers.
+/// A lazy pointer to a set of CXXCtorInitializers.
using LazyCXXCtorInitializersPtr =
LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
&ExternalASTSource::GetExternalCXXCtorInitializers>;
-/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
+/// A lazy pointer to a set of CXXBaseSpecifiers.
using LazyCXXBaseSpecifiersPtr =
LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
&ExternalASTSource::GetExternalCXXBaseSpecifiers>;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h b/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
index 3b3e4367d56c..7f017994216f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
@@ -57,7 +57,7 @@ public:
GlobalDecl CanonGD;
CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
CanonGD.Value.setInt(Value.getInt());
-
+
return CanonGD;
}
@@ -72,11 +72,11 @@ public:
assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
return static_cast<CXXDtorType>(Value.getInt());
}
-
+
friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
return LHS.Value == RHS.Value;
}
-
+
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
static GlobalDecl getFromOpaquePtr(void *P) {
@@ -84,7 +84,7 @@ public:
GD.Value.setFromOpaqueValue(P);
return GD;
}
-
+
GlobalDecl getWithDecl(const Decl *D) {
GlobalDecl Result(*this);
Result.Value.setPointer(D);
@@ -100,7 +100,7 @@ namespace llvm {
static inline clang::GlobalDecl getEmptyKey() {
return clang::GlobalDecl();
}
-
+
static inline clang::GlobalDecl getTombstoneKey() {
return clang::GlobalDecl::
getFromOpaquePtr(reinterpret_cast<void*>(-1));
@@ -109,13 +109,13 @@ namespace llvm {
static unsigned getHashValue(clang::GlobalDecl GD) {
return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
}
-
- static bool isEqual(clang::GlobalDecl LHS,
+
+ static bool isEqual(clang::GlobalDecl LHS,
clang::GlobalDecl RHS) {
return LHS == RHS;
}
};
-
+
// GlobalDecl isn't *technically* a POD type. However, its copy constructor,
// copy assignment operator, and destructor are all trivial.
template <>
diff --git a/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h b/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h
index 6517d656878e..f246bc423bfb 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the LambdaCapture class.
+/// Defines the LambdaCapture class.
///
//===----------------------------------------------------------------------===//
@@ -21,27 +21,27 @@
namespace clang {
-/// \brief Describes the capture of a variable or of \c this, or of a
+/// Describes the capture of a variable or of \c this, or of a
/// C++1y init-capture.
class LambdaCapture {
enum {
- /// \brief Flag used by the Capture class to indicate that the given
+ /// Flag used by the Capture class to indicate that the given
/// capture was implicit.
Capture_Implicit = 0x01,
- /// \brief Flag used by the Capture class to indicate that the
+ /// Flag used by the Capture class to indicate that the
/// given capture was by-copy.
///
/// This includes the case of a non-reference init-capture.
Capture_ByCopy = 0x02,
- /// \brief Flag used by the Capture class to distinguish between a capture
+ /// Flag used by the Capture class to distinguish between a capture
/// of '*this' and a capture of a VLA type.
Capture_This = 0x04
};
// Decl could represent:
- // - a VarDecl* that represents the variable that was captured or the
+ // - a VarDecl* that represents the variable that was captured or the
// init-capture.
// - or, is a nullptr and Capture_This is set in Bits if this represents a
// capture of '*this' by value or reference.
@@ -56,7 +56,7 @@ class LambdaCapture {
friend class ASTStmtWriter;
public:
- /// \brief Create a new capture of a variable or of \c this.
+ /// Create a new capture of a variable or of \c this.
///
/// \param Loc The source location associated with this capture.
///
@@ -75,29 +75,29 @@ public:
VarDecl *Var = nullptr,
SourceLocation EllipsisLoc = SourceLocation());
- /// \brief Determine the kind of capture.
+ /// Determine the kind of capture.
LambdaCaptureKind getCaptureKind() const;
- /// \brief Determine whether this capture handles the C++ \c this
+ /// Determine whether this capture handles the C++ \c this
/// pointer.
bool capturesThis() const {
return DeclAndBits.getPointer() == nullptr &&
(DeclAndBits.getInt() & Capture_This);
}
- /// \brief Determine whether this capture handles a variable.
+ /// Determine whether this capture handles a variable.
bool capturesVariable() const {
return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
}
- /// \brief Determine whether this captures a variable length array bound
+ /// Determine whether this captures a variable length array bound
/// expression.
bool capturesVLAType() const {
return DeclAndBits.getPointer() == nullptr &&
!(DeclAndBits.getInt() & Capture_This);
}
- /// \brief Retrieve the declaration of the local variable being
+ /// Retrieve the declaration of the local variable being
/// captured.
///
/// This operation is only valid if this capture is a variable capture
@@ -107,17 +107,17 @@ public:
return static_cast<VarDecl *>(DeclAndBits.getPointer());
}
- /// \brief Determine whether this was an implicit capture (not
+ /// Determine whether this was an implicit capture (not
/// written between the square brackets introducing the lambda).
bool isImplicit() const {
return DeclAndBits.getInt() & Capture_Implicit;
}
- /// \brief Determine whether this was an explicit capture (written
+ /// Determine whether this was an explicit capture (written
/// between the square brackets introducing the lambda).
bool isExplicit() const { return !isImplicit(); }
- /// \brief Retrieve the source location of the capture.
+ /// Retrieve the source location of the capture.
///
/// For an explicit capture, this returns the location of the
/// explicit capture in the source. For an implicit capture, this
@@ -125,11 +125,11 @@ public:
/// used.
SourceLocation getLocation() const { return Loc; }
- /// \brief Determine whether this capture is a pack expansion,
+ /// Determine whether this capture is a pack expansion,
/// which captures a function parameter pack.
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
- /// \brief Retrieve the location of the ellipsis for a capture
+ /// Retrieve the location of the ellipsis for a capture
/// that is a pack expansion.
SourceLocation getEllipsisLoc() const {
assert(isPackExpansion() && "No ellipsis location for a non-expansion");
diff --git a/contrib/llvm/tools/clang/include/clang/AST/LocInfoType.h b/contrib/llvm/tools/clang/include/clang/AST/LocInfoType.h
index 7e573bd7bac4..802d9134ebde 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/LocInfoType.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/LocInfoType.h
@@ -20,7 +20,7 @@ namespace clang {
class TypeSourceInfo;
-/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
+/// Holds a QualType and a TypeSourceInfo* that came out of a declarator
/// parsing.
///
/// LocInfoType is a "transient" type, only needed for passing to/from Parser
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
index 7a45d88c23c8..c42fe91b3246 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
@@ -30,6 +30,7 @@ namespace clang {
class CXXDestructorDecl;
class CXXMethodDecl;
class FunctionDecl;
+ struct MethodVFTableLocation;
class NamedDecl;
class ObjCMethodDecl;
class StringLiteral;
@@ -72,7 +73,7 @@ public:
DiagnosticsEngine &getDiags() const { return Diags; }
virtual void startNewFunction() { LocalBlockIds.clear(); }
-
+
unsigned getBlockId(const BlockDecl *BD, bool Local) {
llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
= Local? LocalBlockIds : GlobalBlockIds;
@@ -182,14 +183,14 @@ public:
explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Microsoft) {}
- /// \brief Mangle vftable symbols. Only a subset of the bases along the path
+ /// Mangle vftable symbols. Only a subset of the bases along the path
/// to the vftable are included in the name. It's up to the caller to pick
/// them correctly.
virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) = 0;
- /// \brief Mangle vbtable symbols. Only a subset of the bases along the path
+ /// Mangle vbtable symbols. Only a subset of the bases along the path
/// to the vbtable are included in the name. It's up to the caller to pick
/// them correctly.
virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
@@ -201,7 +202,8 @@ public:
raw_ostream &Out) = 0;
virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- raw_ostream &) = 0;
+ const MethodVFTableLocation &ML,
+ raw_ostream &Out) = 0;
virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
const CXXRecordDecl *DstRD,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h b/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h
index 869221dbf31b..ff2148e3516d 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h
@@ -27,29 +27,29 @@ class TagDecl;
class Type;
class VarDecl;
-/// \brief Keeps track of the mangled names of lambda expressions and block
+/// Keeps track of the mangled names of lambda expressions and block
/// literals within a particular context.
class MangleNumberingContext {
public:
virtual ~MangleNumberingContext() {}
- /// \brief Retrieve the mangling number of a new lambda expression with the
+ /// Retrieve the mangling number of a new lambda expression with the
/// given call operator within this context.
virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0;
- /// \brief Retrieve the mangling number of a new block literal within this
+ /// Retrieve the mangling number of a new block literal within this
/// context.
virtual unsigned getManglingNumber(const BlockDecl *BD) = 0;
/// Static locals are numbered by source order.
virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0;
- /// \brief Retrieve the mangling number of a static local variable within
+ /// Retrieve the mangling number of a static local variable within
/// this context.
virtual unsigned getManglingNumber(const VarDecl *VD,
unsigned MSLocalManglingNumber) = 0;
- /// \brief Retrieve the mangling number of a static local variable within
+ /// Retrieve the mangling number of a static local variable within
/// this context.
virtual unsigned getManglingNumber(const TagDecl *TD,
unsigned MSLocalManglingNumber) = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h b/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h
index 3757116e7c70..bf2afe38cbca 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h
@@ -20,7 +20,7 @@ namespace clang {
class QualType;
class Expr;
-// \brief Provides info and caches identifiers/selectors for NSFoundation API.
+// Provides info and caches identifiers/selectors for NSFoundation API.
class NSAPI {
public:
explicit NSAPI(ASTContext &Ctx);
@@ -53,25 +53,25 @@ public:
IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
- /// \brief The Objective-C NSString selectors.
+ /// The Objective-C NSString selectors.
Selector getNSStringSelector(NSStringMethodKind MK) const;
- /// \brief Return NSStringMethodKind if \param Sel is such a selector.
+ /// Return NSStringMethodKind if \param Sel is such a selector.
Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
- /// \brief Returns true if the expression \param E is a reference of
+ /// Returns true if the expression \param E is a reference of
/// "NSUTF8StringEncoding" enum constant.
bool isNSUTF8StringEncodingConstant(const Expr *E) const {
return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
}
- /// \brief Returns true if the expression \param E is a reference of
+ /// Returns true if the expression \param E is a reference of
/// "NSASCIIStringEncoding" enum constant.
bool isNSASCIIStringEncodingConstant(const Expr *E) const {
return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
}
- /// \brief Enumerates the NSArray/NSMutableArray methods used to generate
+ /// Enumerates the NSArray/NSMutableArray methods used to generate
/// literals and to apply some checks.
enum NSArrayMethodKind {
NSArr_array,
@@ -89,13 +89,13 @@ public:
};
static const unsigned NumNSArrayMethods = 12;
- /// \brief The Objective-C NSArray selectors.
+ /// The Objective-C NSArray selectors.
Selector getNSArraySelector(NSArrayMethodKind MK) const;
- /// \brief Return NSArrayMethodKind if \p Sel is such a selector.
+ /// Return NSArrayMethodKind if \p Sel is such a selector.
Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
- /// \brief Enumerates the NSDictionary/NSMutableDictionary methods used
+ /// Enumerates the NSDictionary/NSMutableDictionary methods used
/// to generate literals and to apply some checks.
enum NSDictionaryMethodKind {
NSDict_dictionary,
@@ -113,14 +113,14 @@ public:
NSMutableDict_setValueForKey
};
static const unsigned NumNSDictionaryMethods = 13;
-
- /// \brief The Objective-C NSDictionary selectors.
+
+ /// The Objective-C NSDictionary selectors.
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
- /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector.
+ /// Return NSDictionaryMethodKind if \p Sel is such a selector.
Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
- /// \brief Enumerates the NSMutableSet/NSOrderedSet methods used
+ /// Enumerates the NSMutableSet/NSOrderedSet methods used
/// to apply some checks.
enum NSSetMethodKind {
NSMutableSet_addObject,
@@ -131,42 +131,42 @@ public:
};
static const unsigned NumNSSetMethods = 5;
- /// \brief The Objective-C NSSet selectors.
+ /// The Objective-C NSSet selectors.
Selector getNSSetSelector(NSSetMethodKind MK) const;
- /// \brief Return NSSetMethodKind if \p Sel is such a selector.
+ /// Return NSSetMethodKind if \p Sel is such a selector.
Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
- /// \brief Returns selector for "objectForKeyedSubscript:".
+ /// Returns selector for "objectForKeyedSubscript:".
Selector getObjectForKeyedSubscriptSelector() const {
return getOrInitSelector(StringRef("objectForKeyedSubscript"),
objectForKeyedSubscriptSel);
}
- /// \brief Returns selector for "objectAtIndexedSubscript:".
+ /// Returns selector for "objectAtIndexedSubscript:".
Selector getObjectAtIndexedSubscriptSelector() const {
return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
objectAtIndexedSubscriptSel);
}
- /// \brief Returns selector for "setObject:forKeyedSubscript".
+ /// Returns selector for "setObject:forKeyedSubscript".
Selector getSetObjectForKeyedSubscriptSelector() const {
StringRef Ids[] = { "setObject", "forKeyedSubscript" };
return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
}
- /// \brief Returns selector for "setObject:atIndexedSubscript".
+ /// Returns selector for "setObject:atIndexedSubscript".
Selector getSetObjectAtIndexedSubscriptSelector() const {
StringRef Ids[] = { "setObject", "atIndexedSubscript" };
return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
}
- /// \brief Returns selector for "isEqual:".
+ /// Returns selector for "isEqual:".
Selector getIsEqualSelector() const {
return getOrInitSelector(StringRef("isEqual"), isEqualSel);
}
- /// \brief Enumerates the NSNumber methods used to generate literals.
+ /// Enumerates the NSNumber methods used to generate literals.
enum NSNumberLiteralMethodKind {
NSNumberWithChar,
NSNumberWithUnsignedChar,
@@ -186,7 +186,7 @@ public:
};
static const unsigned NumNSNumberLiteralMethods = 15;
- /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
+ /// The Objective-C NSNumber selectors used to create NSNumber literals.
/// \param Instance if true it will return the selector for the init* method
/// otherwise it will return the selector for the number* method.
Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
@@ -198,29 +198,29 @@ public:
Sel == getNSNumberLiteralSelector(MK, true);
}
- /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector.
+ /// Return NSNumberLiteralMethodKind if \p Sel is such a selector.
Optional<NSNumberLiteralMethodKind>
getNSNumberLiteralMethodKind(Selector Sel) const;
- /// \brief Determine the appropriate NSNumber factory method kind for a
+ /// Determine the appropriate NSNumber factory method kind for a
/// literal of the given type.
Optional<NSNumberLiteralMethodKind>
getNSNumberFactoryMethodKind(QualType T) const;
- /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
+ /// Returns true if \param T is a typedef of "BOOL" in objective-c.
bool isObjCBOOLType(QualType T) const;
- /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
+ /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
bool isObjCNSIntegerType(QualType T) const;
- /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
+ /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
bool isObjCNSUIntegerType(QualType T) const;
- /// \brief Returns one of NSIntegral typedef names if \param T is a typedef
+ /// Returns one of NSIntegral typedef names if \param T is a typedef
/// of that name in objective-c.
StringRef GetNSIntegralKind(QualType T) const;
- /// \brief Returns \c true if \p Id is currently defined as a macro.
+ /// Returns \c true if \p Id is currently defined as a macro.
bool isMacroDefined(StringRef Id) const;
- /// \brief Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
+ /// Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
NSClassIdKindKind NSClassKind) const;
@@ -236,16 +236,16 @@ private:
mutable Selector NSStringSelectors[NumNSStringMethods];
- /// \brief The selectors for Objective-C NSArray methods.
+ /// The selectors for Objective-C NSArray methods.
mutable Selector NSArraySelectors[NumNSArrayMethods];
- /// \brief The selectors for Objective-C NSDictionary methods.
+ /// The selectors for Objective-C NSDictionary methods.
mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
- /// \brief The selectors for Objective-C NSSet methods.
+ /// The selectors for Objective-C NSSet methods.
mutable Selector NSSetSelectors[NumNSSetMethods];
- /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
+ /// The Objective-C NSNumber selectors used to create NSNumber literals.
mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
index e2cb45c36de6..3a7b45767dac 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -36,7 +36,7 @@ struct PrintingPolicy;
class Type;
class TypeLoc;
-/// \brief Represents a C++ nested name specifier, such as
+/// Represents a C++ nested name specifier, such as
/// "\::std::vector<int>::".
///
/// C++ nested name specifiers are the prefixes to qualified
@@ -44,10 +44,10 @@ class TypeLoc;
/// 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
+/// The last two specifiers can only appear at the start of a
/// nested-namespace-specifier.
class NestedNameSpecifier : public llvm::FoldingSetNode {
- /// \brief Enumeration describing
+ /// Enumeration describing
enum StoredSpecifierKind {
StoredIdentifier = 0,
StoredDecl = 1,
@@ -55,7 +55,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
StoredTypeSpecWithTemplate = 3
};
- /// \brief The nested name specifier that precedes this nested name
+ /// The nested name specifier that precedes this nested name
/// specifier.
///
/// The pointer is the nested-name-specifier that precedes this
@@ -63,7 +63,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// SpecifierKind.
llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
- /// \brief The last component in the nested name specifier, which
+ /// The last component in the nested name specifier, which
/// can be an identifier, a declaration, or a type.
///
/// When the pointer is NULL, this specifier represents the global
@@ -73,42 +73,42 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
void* Specifier = nullptr;
public:
- /// \brief The kind of specifier that completes this nested name
+ /// The kind of specifier that completes this nested name
/// specifier.
enum SpecifierKind {
- /// \brief An identifier, stored as an IdentifierInfo*.
+ /// An identifier, stored as an IdentifierInfo*.
Identifier,
- /// \brief A namespace, stored as a NamespaceDecl*.
+ /// A namespace, stored as a NamespaceDecl*.
Namespace,
- /// \brief A namespace alias, stored as a NamespaceAliasDecl*.
+ /// A namespace alias, stored as a NamespaceAliasDecl*.
NamespaceAlias,
- /// \brief A type, stored as a Type*.
+ /// A type, stored as a Type*.
TypeSpec,
- /// \brief A type that was preceded by the 'template' keyword,
+ /// A type that was preceded by the 'template' keyword,
/// stored as a Type*.
TypeSpecWithTemplate,
- /// \brief The global specifier '::'. There is no stored value.
+ /// The global specifier '::'. There is no stored value.
Global,
- /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
+ /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
/// the class it appeared in.
Super
};
private:
- /// \brief Builds the global specifier.
+ /// Builds the global specifier.
NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {}
- /// \brief Copy constructor used internally to clone nested name
+ /// Copy constructor used internally to clone nested name
/// specifiers.
NestedNameSpecifier(const NestedNameSpecifier &Other) = default;
- /// \brief Either find or insert the given nested name specifier
+ /// Either find or insert the given nested name specifier
/// mockup in the given context.
static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
const NestedNameSpecifier &Mockup);
@@ -116,7 +116,7 @@ private:
public:
NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete;
- /// \brief Builds a specifier combining a prefix and an identifier.
+ /// Builds a specifier combining a prefix and an identifier.
///
/// The prefix must be dependent, since nested name specifiers
/// referencing an identifier are only permitted when the identifier
@@ -125,22 +125,22 @@ public:
NestedNameSpecifier *Prefix,
IdentifierInfo *II);
- /// \brief Builds a nested name specifier that names a namespace.
+ /// Builds a nested name specifier that names a namespace.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
const NamespaceDecl *NS);
- /// \brief Builds a nested name specifier that names a namespace alias.
+ /// Builds a nested name specifier that names a namespace alias.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceAliasDecl *Alias);
- /// \brief Builds a nested name specifier that names a type.
+ /// Builds a nested name specifier that names a type.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
bool Template, const Type *T);
- /// \brief Builds a specifier that consists of just an identifier.
+ /// Builds a specifier that consists of just an identifier.
///
/// The nested-name-specifier is assumed to be dependent, but has no
/// prefix because the prefix is implied by something outside of the
@@ -149,16 +149,16 @@ public:
static NestedNameSpecifier *Create(const ASTContext &Context,
IdentifierInfo *II);
- /// \brief Returns the nested name specifier representing the global
+ /// Returns the nested name specifier representing the global
/// scope.
static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
- /// \brief Returns the nested name specifier representing the __super scope
+ /// Returns the nested name specifier representing the __super scope
/// for the given CXXRecordDecl.
static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context,
CXXRecordDecl *RD);
- /// \brief Return the prefix of this nested name specifier.
+ /// Return the prefix of this nested name specifier.
///
/// The prefix contains all of the parts of the nested name
/// specifier that preced this current specifier. For example, for a
@@ -167,10 +167,10 @@ public:
/// "foo::".
NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
- /// \brief Determine what kind of nested name specifier is stored.
+ /// Determine what kind of nested name specifier is stored.
SpecifierKind getKind() const;
- /// \brief Retrieve the identifier stored in this nested name
+ /// Retrieve the identifier stored in this nested name
/// specifier.
IdentifierInfo *getAsIdentifier() const {
if (Prefix.getInt() == StoredIdentifier)
@@ -179,19 +179,19 @@ public:
return nullptr;
}
- /// \brief Retrieve the namespace stored in this nested name
+ /// Retrieve the namespace stored in this nested name
/// specifier.
NamespaceDecl *getAsNamespace() const;
- /// \brief Retrieve the namespace alias stored in this nested name
+ /// Retrieve the namespace alias stored in this nested name
/// specifier.
NamespaceAliasDecl *getAsNamespaceAlias() const;
- /// \brief Retrieve the record declaration stored in this nested name
+ /// Retrieve the record declaration stored in this nested name
/// specifier.
CXXRecordDecl *getAsRecordDecl() const;
- /// \brief Retrieve the type stored in this nested name specifier.
+ /// Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
if (Prefix.getInt() == StoredTypeSpec ||
Prefix.getInt() == StoredTypeSpecWithTemplate)
@@ -200,19 +200,19 @@ public:
return nullptr;
}
- /// \brief Whether this nested name specifier refers to a dependent
+ /// Whether this nested name specifier refers to a dependent
/// type or not.
bool isDependent() const;
- /// \brief Whether this nested name specifier involves a template
+ /// Whether this nested name specifier involves a template
/// parameter.
bool isInstantiationDependent() const;
- /// \brief Whether this nested-name-specifier contains an unexpanded
+ /// Whether this nested-name-specifier contains an unexpanded
/// parameter pack (for C++11 variadic templates).
bool containsUnexpandedParameterPack() const;
- /// \brief Print this nested name specifier to the given output
+ /// Print this nested name specifier to the given output
/// stream.
void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
@@ -221,53 +221,53 @@ public:
ID.AddPointer(Specifier);
}
- /// \brief Dump the nested name specifier to standard output to aid
+ /// Dump the nested name specifier to standard output to aid
/// in debugging.
void dump(const LangOptions &LO) const;
void dump() const;
};
-/// \brief A C++ nested-name-specifier augmented with source location
+/// A C++ nested-name-specifier augmented with source location
/// information.
class NestedNameSpecifierLoc {
NestedNameSpecifier *Qualifier = nullptr;
void *Data = nullptr;
- /// \brief Determines the data length for the last component in the
+ /// Determines the data length for the last component in the
/// given nested-name-specifier.
static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
- /// \brief Determines the data length for the entire
+ /// Determines the data length for the entire
/// nested-name-specifier.
static unsigned getDataLength(NestedNameSpecifier *Qualifier);
public:
- /// \brief Construct an empty nested-name-specifier.
+ /// Construct an empty nested-name-specifier.
NestedNameSpecifierLoc() = default;
- /// \brief Construct a nested-name-specifier with source location information
+ /// Construct a nested-name-specifier with source location information
/// from
NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
: Qualifier(Qualifier), Data(Data) {}
- /// \brief Evalutes true when this nested-name-specifier location is
+ /// Evaluates true when this nested-name-specifier location is
/// non-empty.
explicit operator bool() const { return Qualifier; }
- /// \brief Evalutes true when this nested-name-specifier location is
+ /// Evaluates true when this nested-name-specifier location is
/// empty.
bool hasQualifier() const { return Qualifier; }
- /// \brief Retrieve the nested-name-specifier to which this instance
+ /// Retrieve the nested-name-specifier to which this instance
/// refers.
NestedNameSpecifier *getNestedNameSpecifier() const {
return Qualifier;
}
- /// \brief Retrieve the opaque pointer that refers to source-location data.
+ /// Retrieve the opaque pointer that refers to source-location data.
void *getOpaqueData() const { return Data; }
- /// \brief Retrieve the source range covering the entirety of this
+ /// Retrieve the source range covering the entirety of this
/// nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
@@ -275,7 +275,7 @@ public:
/// from the initial '::' to the last '::'.
SourceRange getSourceRange() const LLVM_READONLY;
- /// \brief Retrieve the source range covering just the last part of
+ /// Retrieve the source range covering just the last part of
/// this nested-name-specifier, not including the prefix.
///
/// For example, if this instance refers to a nested-name-specifier
@@ -283,31 +283,31 @@ public:
/// from "vector" to the last '::'.
SourceRange getLocalSourceRange() const;
- /// \brief Retrieve the location of the beginning of this
+ /// Retrieve the location of the beginning of this
/// nested-name-specifier.
SourceLocation getBeginLoc() const {
return getSourceRange().getBegin();
}
- /// \brief Retrieve the location of the end of this
+ /// Retrieve the location of the end of this
/// nested-name-specifier.
SourceLocation getEndLoc() const {
return getSourceRange().getEnd();
}
- /// \brief Retrieve the location of the beginning of this
+ /// Retrieve the location of the beginning of this
/// component of the nested-name-specifier.
SourceLocation getLocalBeginLoc() const {
return getLocalSourceRange().getBegin();
}
- /// \brief Retrieve the location of the end of this component of the
+ /// Retrieve the location of the end of this component of the
/// nested-name-specifier.
SourceLocation getLocalEndLoc() const {
return getLocalSourceRange().getEnd();
}
- /// \brief Return the prefix of this nested-name-specifier.
+ /// Return the prefix of this nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the
@@ -320,11 +320,11 @@ public:
return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
}
- /// \brief For a nested-name-specifier that refers to a type,
+ /// For a nested-name-specifier that refers to a type,
/// retrieve the type with source-location information.
TypeLoc getTypeLoc() const;
- /// \brief Determines the data length for the entire
+ /// Determines the data length for the entire
/// nested-name-specifier.
unsigned getDataLength() const { return getDataLength(Qualifier); }
@@ -339,15 +339,15 @@ public:
}
};
-/// \brief Class that aids in the construction of nested-name-specifiers along
+/// Class that aids in the construction of nested-name-specifiers along
/// with source-location information for all of the components of the
/// nested-name-specifier.
class NestedNameSpecifierLocBuilder {
- /// \brief The current representation of the nested-name-specifier we're
+ /// The current representation of the nested-name-specifier we're
/// building.
NestedNameSpecifier *Representation = nullptr;
- /// \brief Buffer used to store source-location information for the
+ /// Buffer used to store source-location information for the
/// nested-name-specifier.
///
/// Note that we explicitly manage the buffer (rather than using a
@@ -355,11 +355,11 @@ class NestedNameSpecifierLocBuilder {
/// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
char *Buffer = nullptr;
- /// \brief The size of the buffer used to store source-location information
+ /// The size of the buffer used to store source-location information
/// for the nested-name-specifier.
unsigned BufferSize = 0;
- /// \brief The capacity of the buffer used to store source-location
+ /// The capacity of the buffer used to store source-location
/// information for the nested-name-specifier.
unsigned BufferCapacity = 0;
@@ -375,10 +375,10 @@ public:
free(Buffer);
}
- /// \brief Retrieve the representation of the nested-name-specifier.
+ /// Retrieve the representation of the nested-name-specifier.
NestedNameSpecifier *getRepresentation() const { return Representation; }
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'type::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -392,7 +392,7 @@ public:
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
SourceLocation ColonColonLoc);
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'identifier::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -406,7 +406,7 @@ public:
void Extend(ASTContext &Context, IdentifierInfo *Identifier,
SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -420,7 +420,7 @@ public:
void Extend(ASTContext &Context, NamespaceDecl *Namespace,
SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace-alias::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -435,11 +435,11 @@ public:
void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
SourceLocation AliasLoc, SourceLocation ColonColonLoc);
- /// \brief Turn this (empty) nested-name-specifier into the global
+ /// Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
-
- /// \brief Turns this (empty) nested-name-specifier into '__super'
+
+ /// Turns this (empty) nested-name-specifier into '__super'
/// nested-name-specifier.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -452,10 +452,10 @@ public:
/// name.
///
/// \param ColonColonLoc The location of the trailing '::'.
- void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+ void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
SourceLocation SuperLoc, SourceLocation ColonColonLoc);
- /// \brief Make a new nested-name-specifier from incomplete source-location
+ /// Make a new nested-name-specifier from incomplete source-location
/// information.
///
/// This routine should be used very, very rarely, in cases where we
@@ -464,23 +464,23 @@ public:
void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
SourceRange R);
- /// \brief Adopt an existing nested-name-specifier (with source-range
+ /// Adopt an existing nested-name-specifier (with source-range
/// information).
void Adopt(NestedNameSpecifierLoc Other);
- /// \brief Retrieve the source range covered by this nested-name-specifier.
+ /// Retrieve the source range covered by this nested-name-specifier.
SourceRange getSourceRange() const LLVM_READONLY {
return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
}
- /// \brief Retrieve a nested-name-specifier with location information,
+ /// Retrieve a nested-name-specifier with location information,
/// copied into the given AST context.
///
/// \param Context The context into which this nested-name-specifier will be
/// copied.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
- /// \brief Retrieve a nested-name-specifier with location
+ /// Retrieve a nested-name-specifier with location
/// information based on the information in this builder.
///
/// This loc will contain references to the builder's internal data and may
@@ -489,14 +489,14 @@ public:
return NestedNameSpecifierLoc(Representation, Buffer);
}
- /// \brief Clear out this builder, and prepare it to build another
+ /// Clear out this builder, and prepare it to build another
/// nested-name-specifier with source-location information.
void Clear() {
Representation = nullptr;
BufferSize = 0;
}
- /// \brief Retrieve the underlying buffer.
+ /// Retrieve the underlying buffer.
///
/// \returns A pair containing a pointer to the buffer of source-location
/// data and the size of the source-location data that resides in that
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NonTrivialTypeVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/NonTrivialTypeVisitor.h
new file mode 100644
index 000000000000..bab373dbb298
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/NonTrivialTypeVisitor.h
@@ -0,0 +1,113 @@
+//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the visitor classes that are used to traverse non-trivial
+// structs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H
+#define LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+template <class Derived, class RetTy = void> struct DestructedTypeVisitor {
+ template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+ return asDerived().visitWithKind(FT.isDestructedType(), FT,
+ std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ RetTy visitWithKind(QualType::DestructionKind DK, QualType FT,
+ Ts &&... Args) {
+ switch (DK) {
+ case QualType::DK_objc_strong_lifetime:
+ return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_nontrivial_c_struct:
+ return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_none:
+ return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_cxx_destructor:
+ return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_objc_weak_lifetime:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+ }
+
+ llvm_unreachable("unknown destruction kind");
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+template <class Derived, class RetTy = void>
+struct DefaultInitializedTypeVisitor {
+ template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+ return asDerived().visitWithKind(
+ FT.isNonTrivialToPrimitiveDefaultInitialize(), FT,
+ std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ RetTy visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK,
+ QualType FT, Ts &&... Args) {
+ switch (PDIK) {
+ case QualType::PDIK_ARCStrong:
+ return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_ARCWeak:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_Struct:
+ return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_Trivial:
+ return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+ }
+
+ llvm_unreachable("unknown default-initialize kind");
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+template <class Derived, bool IsMove, class RetTy = void>
+struct CopiedTypeVisitor {
+ template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+ QualType::PrimitiveCopyKind PCK =
+ IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove()
+ : FT.isNonTrivialToPrimitiveCopy();
+ return asDerived().visitWithKind(PCK, FT, std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+ Ts &&... Args) {
+ asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...);
+
+ switch (PCK) {
+ case QualType::PCK_ARCStrong:
+ return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_ARCWeak:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_Struct:
+ return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_Trivial:
+ return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_VolatileTrivial:
+ return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...);
+ }
+
+ llvm_unreachable("unknown primitive copy kind");
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ODRHash.h b/contrib/llvm/tools/clang/include/clang/AST/ODRHash.h
index ed648bb8afb1..75b361789211 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ODRHash.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ODRHash.h
@@ -37,9 +37,9 @@ class TemplateParameterList;
// Typically, only one Add* call is needed. clear can be called to reuse the
// object.
class ODRHash {
- // Use DenseMaps to convert between Decl and Type pointers and an index value.
- llvm::DenseMap<const Decl*, unsigned> DeclMap;
- llvm::DenseMap<const Type*, unsigned> TypeMap;
+ // Use DenseMaps to convert from DeclarationName and Type pointers
+ // to an index value.
+ llvm::DenseMap<DeclarationName, unsigned> DeclNameMap;
// Save space by processing bools at the end.
llvm::SmallVector<bool, 128> Bools;
@@ -54,8 +54,13 @@ public:
void AddCXXRecordDecl(const CXXRecordDecl *Record);
// Use this for ODR checking functions between modules. This method compares
+ // more information than the AddDecl class. SkipBody will process the
+ // hash as if the function has no body.
+ void AddFunctionDecl(const FunctionDecl *Function, bool SkipBody = false);
+
+ // Use this for ODR checking enums between modules. This method compares
// more information than the AddDecl class.
- void AddFunctionDecl(const FunctionDecl *Function);
+ void AddEnumDecl(const EnumDecl *Enum);
// Process SubDecls of the main Decl. This method calls the DeclVisitor
// while AddDecl does not.
@@ -82,7 +87,7 @@ public:
// Save booleans until the end to lower the size of data to process.
void AddBoolean(bool value);
- static bool isWhitelistedDecl(const Decl* D, const CXXRecordDecl *Record);
+ static bool isWhitelistedDecl(const Decl* D, const DeclContext *Parent);
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
index 1f732f67517a..419dbe52fab6 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief This file defines OpenMP AST classes for clauses.
+/// 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.
//
@@ -47,15 +47,15 @@ class ASTContext;
// AST classes for clauses.
//===----------------------------------------------------------------------===//
-/// \brief This is a basic class for representing single OpenMP clause.
+/// This is a basic class for representing single OpenMP clause.
class OMPClause {
- /// \brief Starting location of the clause (the clause keyword).
+ /// Starting location of the clause (the clause keyword).
SourceLocation StartLoc;
- /// \brief Ending location of the clause.
+ /// Ending location of the clause.
SourceLocation EndLoc;
- /// \brief Kind of the clause.
+ /// Kind of the clause.
OpenMPClauseKind Kind;
protected:
@@ -63,19 +63,19 @@ protected:
: StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {}
public:
- /// \brief Returns the starting location of the clause.
+ /// Returns the starting location of the clause.
SourceLocation getLocStart() const { return StartLoc; }
- /// \brief Returns the ending location of the clause.
+ /// Returns the ending location of the clause.
SourceLocation getLocEnd() const { return EndLoc; }
- /// \brief Sets the starting location of the clause.
+ /// Sets the starting location of the clause.
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
- /// \brief Sets the ending location of the clause.
+ /// Sets the ending location of the clause.
void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
- /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.).
+ /// Returns kind of OpenMP clause (private, shared, reduction, etc.).
OpenMPClauseKind getClauseKind() const { return Kind; }
bool isImplicit() const { return StartLoc.isInvalid(); }
@@ -124,7 +124,7 @@ public:
Stmt *getPreInitStmt() { return PreInit; }
/// Get capture region for the stmt in the clause.
- OpenMPDirectiveKind getCaptureRegion() { return CaptureRegion; }
+ OpenMPDirectiveKind getCaptureRegion() const { return CaptureRegion; }
static OMPClauseWithPreInit *get(OMPClause *C);
static const OMPClauseWithPreInit *get(const OMPClause *C);
@@ -157,20 +157,20 @@ public:
static const OMPClauseWithPostUpdate *get(const OMPClause *C);
};
-/// \brief This represents clauses with the list of variables like 'private',
+/// This represents clauses with the list of variables like 'private',
/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the
/// '#pragma omp ...' directives.
template <class T> class OMPVarListClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Number of variables in the list.
+ /// Number of variables in the list.
unsigned NumVars;
protected:
- /// \brief Build a clause with \a N variables
+ /// Build a clause with \a N variables
///
/// \param K Kind of the clause.
/// \param StartLoc Starting location of the clause (the clause keyword).
@@ -181,13 +181,13 @@ protected:
SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N)
: OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {}
- /// \brief Fetches list of variables associated with this clause.
+ /// Fetches list of variables associated with this clause.
MutableArrayRef<Expr *> getVarRefs() {
return MutableArrayRef<Expr *>(
static_cast<T *>(this)->template getTrailingObjects<Expr *>(), NumVars);
}
- /// \brief Sets the list of variables for this clause.
+ /// Sets the list of variables for this clause.
void setVarRefs(ArrayRef<Expr *> VL) {
assert(VL.size() == NumVars &&
"Number of variables is not the same as the preallocated buffer");
@@ -216,13 +216,13 @@ public:
varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); }
varlist_const_iterator varlist_end() const { return getVarRefs().end(); }
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Fetches list of all variables in the clause.
+ /// Fetches list of all variables in the clause.
ArrayRef<const Expr *> getVarRefs() const {
return llvm::makeArrayRef(
static_cast<const T *>(this)->template getTrailingObjects<Expr *>(),
@@ -230,7 +230,7 @@ public:
}
};
-/// \brief This represents 'if' clause in the '#pragma omp ...' directive.
+/// This represents 'if' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp parallel if(parallel:a > 5)
@@ -240,35 +240,35 @@ public:
class OMPIfClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Condition of the 'if' clause.
+ /// Condition of the 'if' clause.
Stmt *Condition = nullptr;
- /// \brief Location of ':' (if any).
+ /// Location of ':' (if any).
SourceLocation ColonLoc;
- /// \brief Directive name modifier for the clause.
+ /// Directive name modifier for the clause.
OpenMPDirectiveKind NameModifier = OMPD_unknown;
- /// \brief Name modifier location.
+ /// Name modifier location.
SourceLocation NameModifierLoc;
- /// \brief Set condition.
+ /// Set condition.
void setCondition(Expr *Cond) { Condition = Cond; }
- /// \brief Set directive name modifier for the clause.
+ /// Set directive name modifier for the clause.
void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; }
- /// \brief Set location of directive name modifier for the clause.
+ /// Set location of directive name modifier for the clause.
void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; }
- /// \brief Set location of ':'.
+ /// Set location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
- /// \brief Build 'if' clause with condition \a Cond.
+ /// Build 'if' clause with condition \a Cond.
///
/// \param NameModifier [OpenMP 4.1] Directive name modifier of clause.
/// \param Cond Condition of the clause.
@@ -290,27 +290,27 @@ public:
setPreInitStmt(HelperCond, CaptureRegion);
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPIfClause()
: OMPClause(OMPC_if, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return the location of ':'.
+ /// Return the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// \brief Returns condition.
+ /// Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
- /// \brief Return directive name modifier associated with the clause.
+ /// Return directive name modifier associated with the clause.
OpenMPDirectiveKind getNameModifier() const { return NameModifier; }
- /// \brief Return the location of directive name modifier.
+ /// Return the location of directive name modifier.
SourceLocation getNameModifierLoc() const { return NameModifierLoc; }
child_range children() { return child_range(&Condition, &Condition + 1); }
@@ -320,7 +320,7 @@ public:
}
};
-/// \brief This represents 'final' clause in the '#pragma omp ...' directive.
+/// This represents 'final' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp task final(a > 5)
@@ -330,17 +330,17 @@ public:
class OMPFinalClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Condition of the 'if' clause.
+ /// Condition of the 'if' clause.
Stmt *Condition = nullptr;
- /// \brief Set condition.
+ /// Set condition.
void setCondition(Expr *Cond) { Condition = Cond; }
public:
- /// \brief Build 'final' clause with condition \a Cond.
+ /// Build 'final' clause with condition \a Cond.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -351,17 +351,17 @@ public:
: OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc),
Condition(Cond) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPFinalClause()
: OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Returns condition.
+ /// Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
child_range children() { return child_range(&Condition, &Condition + 1); }
@@ -371,7 +371,7 @@ public:
}
};
-/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
+/// This represents 'num_threads' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -382,17 +382,17 @@ public:
class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Condition of the 'num_threads' clause.
+ /// Condition of the 'num_threads' clause.
Stmt *NumThreads = nullptr;
- /// \brief Set condition.
+ /// Set condition.
void setNumThreads(Expr *NThreads) { NumThreads = NThreads; }
public:
- /// \brief Build 'num_threads' clause with condition \a NumThreads.
+ /// Build 'num_threads' clause with condition \a NumThreads.
///
/// \param NumThreads Number of threads for the construct.
/// \param HelperNumThreads Helper Number of threads for the construct.
@@ -411,18 +411,18 @@ public:
setPreInitStmt(HelperNumThreads, CaptureRegion);
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPNumThreadsClause()
: OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Returns number of threads.
+ /// Returns number of threads.
Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); }
child_range children() { return child_range(&NumThreads, &NumThreads + 1); }
@@ -432,7 +432,7 @@ public:
}
};
-/// \brief This represents 'safelen' clause in the '#pragma omp ...'
+/// This represents 'safelen' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -447,17 +447,17 @@ public:
class OMPSafelenClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Safe iteration space distance.
+ /// Safe iteration space distance.
Stmt *Safelen = nullptr;
- /// \brief Set safelen.
+ /// Set safelen.
void setSafelen(Expr *Len) { Safelen = Len; }
public:
- /// \brief Build 'safelen' clause.
+ /// Build 'safelen' clause.
///
/// \param Len Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -467,17 +467,17 @@ public:
: OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc),
Safelen(Len) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPSafelenClause()
: OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return safe iteration space distance.
+ /// Return safe iteration space distance.
Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); }
child_range children() { return child_range(&Safelen, &Safelen + 1); }
@@ -487,7 +487,7 @@ public:
}
};
-/// \brief This represents 'simdlen' clause in the '#pragma omp ...'
+/// This represents 'simdlen' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -501,17 +501,17 @@ public:
class OMPSimdlenClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Safe iteration space distance.
+ /// Safe iteration space distance.
Stmt *Simdlen = nullptr;
- /// \brief Set simdlen.
+ /// Set simdlen.
void setSimdlen(Expr *Len) { Simdlen = Len; }
public:
- /// \brief Build 'simdlen' clause.
+ /// Build 'simdlen' clause.
///
/// \param Len Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -521,17 +521,17 @@ public:
: OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc),
Simdlen(Len) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPSimdlenClause()
: OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return safe iteration space distance.
+ /// Return safe iteration space distance.
Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); }
child_range children() { return child_range(&Simdlen, &Simdlen + 1); }
@@ -541,7 +541,7 @@ public:
}
};
-/// \brief This represents 'collapse' clause in the '#pragma omp ...'
+/// This represents 'collapse' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -555,17 +555,17 @@ public:
class OMPCollapseClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Number of for-loops.
+ /// Number of for-loops.
Stmt *NumForLoops = nullptr;
- /// \brief Set the number of associated for-loops.
+ /// Set the number of associated for-loops.
void setNumForLoops(Expr *Num) { NumForLoops = Num; }
public:
- /// \brief Build 'collapse' clause.
+ /// Build 'collapse' clause.
///
/// \param Num Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -576,17 +576,17 @@ public:
: OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumForLoops(Num) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPCollapseClause()
: OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return the number of associated for-loops.
+ /// 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); }
@@ -596,7 +596,7 @@ public:
}
};
-/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
+/// This represents 'default' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp parallel default(shared)
@@ -606,27 +606,27 @@ public:
class OMPDefaultClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief A kind of the 'default' clause.
+ /// A kind of the 'default' clause.
OpenMPDefaultClauseKind Kind = OMPC_DEFAULT_unknown;
- /// \brief Start location of the kind in source code.
+ /// Start location of the kind in source code.
SourceLocation KindKwLoc;
- /// \brief Set kind of the clauses.
+ /// Set kind of the clauses.
///
/// \param K Argument of clause.
void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; }
- /// \brief Set argument location.
+ /// Set argument location.
///
/// \param KLoc Argument location.
void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
public:
- /// \brief Build 'default' clause with argument \a A ('none' or 'shared').
+ /// Build 'default' clause with argument \a A ('none' or 'shared').
///
/// \param A Argument of the clause ('none' or 'shared').
/// \param ALoc Starting location of the argument.
@@ -639,20 +639,20 @@ public:
: OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc),
Kind(A), KindKwLoc(ALoc) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPDefaultClause()
: OMPClause(OMPC_default, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Returns kind of the clause.
+ /// Returns kind of the clause.
OpenMPDefaultClauseKind getDefaultKind() const { return Kind; }
- /// \brief Returns location of clause kind.
+ /// Returns location of clause kind.
SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
child_range children() {
@@ -664,7 +664,7 @@ public:
}
};
-/// \brief This represents 'proc_bind' clause in the '#pragma omp ...'
+/// This represents 'proc_bind' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -675,27 +675,27 @@ public:
class OMPProcBindClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief A kind of the 'proc_bind' clause.
+ /// A kind of the 'proc_bind' clause.
OpenMPProcBindClauseKind Kind = OMPC_PROC_BIND_unknown;
- /// \brief Start location of the kind in source code.
+ /// Start location of the kind in source code.
SourceLocation KindKwLoc;
- /// \brief Set kind of the clause.
+ /// Set kind of the clause.
///
/// \param K Kind of clause.
void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; }
- /// \brief Set clause kind location.
+ /// Set clause kind location.
///
/// \param KLoc Kind location.
void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
public:
- /// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or
+ /// Build 'proc_bind' clause with argument \a A ('master', 'close' or
/// 'spread').
///
/// \param A Argument of the clause ('master', 'close' or 'spread').
@@ -709,20 +709,20 @@ public:
: OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc),
Kind(A), KindKwLoc(ALoc) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPProcBindClause()
: OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Returns kind of the clause.
+ /// Returns kind of the clause.
OpenMPProcBindClauseKind getProcBindKind() const { return Kind; }
- /// \brief Returns location of clause kind.
+ /// Returns location of clause kind.
SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; }
child_range children() {
@@ -734,7 +734,7 @@ public:
}
};
-/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive.
+/// This represents 'schedule' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp for schedule(static, 3)
@@ -744,58 +744,58 @@ public:
class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief A kind of the 'schedule' clause.
+ /// A kind of the 'schedule' clause.
OpenMPScheduleClauseKind Kind = OMPC_SCHEDULE_unknown;
- /// \brief Modifiers for 'schedule' clause.
+ /// Modifiers for 'schedule' clause.
enum {FIRST, SECOND, NUM_MODIFIERS};
OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS];
- /// \brief Locations of modifiers.
+ /// Locations of modifiers.
SourceLocation ModifiersLoc[NUM_MODIFIERS];
- /// \brief Start location of the schedule ind in source code.
+ /// Start location of the schedule ind in source code.
SourceLocation KindLoc;
- /// \brief Location of ',' (if any).
+ /// Location of ',' (if any).
SourceLocation CommaLoc;
- /// \brief Chunk size.
+ /// Chunk size.
Expr *ChunkSize = nullptr;
- /// \brief Set schedule kind.
+ /// Set schedule kind.
///
/// \param K Schedule kind.
void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
- /// \brief Set the first schedule modifier.
+ /// Set the first schedule modifier.
///
/// \param M Schedule modifier.
void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) {
Modifiers[FIRST] = M;
}
- /// \brief Set the second schedule modifier.
+ /// Set the second schedule modifier.
///
/// \param M Schedule modifier.
void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) {
Modifiers[SECOND] = M;
}
- /// \brief Set location of the first schedule modifier.
+ /// Set location of the first schedule modifier.
void setFirstScheduleModifierLoc(SourceLocation Loc) {
ModifiersLoc[FIRST] = Loc;
}
- /// \brief Set location of the second schedule modifier.
+ /// Set location of the second schedule modifier.
void setSecondScheduleModifierLoc(SourceLocation Loc) {
ModifiersLoc[SECOND] = Loc;
}
- /// \brief Set schedule modifier location.
+ /// Set schedule modifier location.
///
/// \param M Schedule modifier location.
void setScheduleModifer(OpenMPScheduleClauseModifier M) {
@@ -807,28 +807,28 @@ class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit {
}
}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
///
/// \param Loc Location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Set schedule kind start location.
+ /// Set schedule kind start location.
///
/// \param KLoc Schedule kind location.
void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
- /// \brief Set location of ','.
+ /// Set location of ','.
///
/// \param Loc Location of ','.
void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
- /// \brief Set chunk size.
+ /// Set chunk size.
///
/// \param E Chunk size.
void setChunkSize(Expr *E) { ChunkSize = E; }
public:
- /// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size
+ /// Build 'schedule' clause with schedule kind \a Kind and chunk size
/// expression \a ChunkSize.
///
/// \param StartLoc Starting location of the clause.
@@ -859,7 +859,7 @@ public:
ModifiersLoc[SECOND] = M2Loc;
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPScheduleClause()
: OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {
@@ -867,42 +867,42 @@ public:
Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
}
- /// \brief Get kind of the clause.
+ /// Get kind of the clause.
OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
- /// \brief Get the first modifier of the clause.
+ /// Get the first modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const {
return Modifiers[FIRST];
}
- /// \brief Get the second modifier of the clause.
+ /// Get the second modifier of the clause.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const {
return Modifiers[SECOND];
}
- /// \brief Get location of '('.
+ /// Get location of '('.
SourceLocation getLParenLoc() { return LParenLoc; }
- /// \brief Get kind location.
+ /// Get kind location.
SourceLocation getScheduleKindLoc() { return KindLoc; }
- /// \brief Get the first modifier location.
+ /// Get the first modifier location.
SourceLocation getFirstScheduleModifierLoc() const {
return ModifiersLoc[FIRST];
}
- /// \brief Get the second modifier location.
+ /// Get the second modifier location.
SourceLocation getSecondScheduleModifierLoc() const {
return ModifiersLoc[SECOND];
}
- /// \brief Get location of ','.
+ /// Get location of ','.
SourceLocation getCommaLoc() { return CommaLoc; }
- /// \brief Get chunk size.
+ /// Get chunk size.
Expr *getChunkSize() { return ChunkSize; }
- /// \brief Get chunk size.
+ /// Get chunk size.
const Expr *getChunkSize() const { return ChunkSize; }
child_range children() {
@@ -915,50 +915,84 @@ public:
}
};
-/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
+/// This represents 'ordered' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp for ordered (2)
/// \endcode
/// In this example directive '#pragma omp for' has 'ordered' clause with
/// parameter 2.
-class OMPOrderedClause : public OMPClause {
+class OMPOrderedClause final
+ : public OMPClause,
+ private llvm::TrailingObjects<OMPOrderedClause, Expr *> {
friend class OMPClauseReader;
+ friend TrailingObjects;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Number of for-loops.
+ /// Number of for-loops.
Stmt *NumForLoops = nullptr;
- /// \brief Set the number of associated for-loops.
+ /// Real number of loops.
+ unsigned NumberOfLoops = 0;
+
+ /// Build 'ordered' clause.
+ ///
+ /// \param Num Expression, possibly associated with this clause.
+ /// \param NumLoops Number of loops, associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ OMPOrderedClause(Expr *Num, unsigned NumLoops, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumForLoops(Num), NumberOfLoops(NumLoops) {}
+
+ /// Build an empty clause.
+ explicit OMPOrderedClause(unsigned NumLoops)
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
+ NumberOfLoops(NumLoops) {}
+
+ /// Set the number of associated for-loops.
void setNumForLoops(Expr *Num) { NumForLoops = Num; }
public:
- /// \brief Build 'ordered' clause.
+ /// Build 'ordered' clause.
///
/// \param Num Expression, possibly associated with this clause.
+ /// \param NumLoops Number of loops, associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc)
- : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
- NumForLoops(Num) {}
+ static OMPOrderedClause *Create(const ASTContext &C, Expr *Num,
+ unsigned NumLoops, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
- /// \brief Build an empty clause.
- explicit OMPOrderedClause()
- : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
+ /// Build an empty clause.
+ static OMPOrderedClause* CreateEmpty(const ASTContext &C, unsigned NumLoops);
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return the number of associated for-loops.
+ /// Return the number of associated for-loops.
Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
+ /// Set number of iterations for the specified loop.
+ void setLoopNumIterations(unsigned NumLoop, Expr *NumIterations);
+ /// Get number of iterations for all the loops.
+ ArrayRef<Expr *> getLoopNumIterations() const;
+
+ /// Set loop counter for the specified loop.
+ void setLoopCounter(unsigned NumLoop, Expr *Counter);
+ /// Get loops counter for the specified loop.
+ Expr *getLoopCunter(unsigned NumLoop);
+ const Expr *getLoopCunter(unsigned NumLoop) const;
+
child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
static bool classof(const OMPClause *T) {
@@ -966,7 +1000,7 @@ public:
}
};
-/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive.
+/// This represents 'nowait' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp for nowait
@@ -974,14 +1008,14 @@ public:
/// In this example directive '#pragma omp for' has 'nowait' clause.
class OMPNowaitClause : public OMPClause {
public:
- /// \brief Build 'nowait' clause.
+ /// 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.
+ /// Build an empty clause.
OMPNowaitClause()
: OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {}
@@ -994,7 +1028,7 @@ public:
}
};
-/// \brief This represents 'untied' clause in the '#pragma omp ...' directive.
+/// This represents 'untied' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp task untied
@@ -1002,14 +1036,14 @@ public:
/// In this example directive '#pragma omp task' has 'untied' clause.
class OMPUntiedClause : public OMPClause {
public:
- /// \brief Build 'untied' clause.
+ /// 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.
+ /// Build an empty clause.
OMPUntiedClause()
: OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {}
@@ -1022,7 +1056,7 @@ public:
}
};
-/// \brief This represents 'mergeable' clause in the '#pragma omp ...'
+/// This represents 'mergeable' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -1031,14 +1065,14 @@ public:
/// In this example directive '#pragma omp task' has 'mergeable' clause.
class OMPMergeableClause : public OMPClause {
public:
- /// \brief Build 'mergeable' clause.
+ /// 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.
+ /// Build an empty clause.
OMPMergeableClause()
: OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {}
@@ -1051,7 +1085,7 @@ public:
}
};
-/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
+/// This represents 'read' clause in the '#pragma omp atomic' directive.
///
/// \code
/// #pragma omp atomic read
@@ -1059,14 +1093,14 @@ public:
/// In this example directive '#pragma omp atomic' has 'read' clause.
class OMPReadClause : public OMPClause {
public:
- /// \brief Build 'read' clause.
+ /// 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.
+ /// Build an empty clause.
OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {}
child_range children() {
@@ -1078,7 +1112,7 @@ public:
}
};
-/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
+/// This represents 'write' clause in the '#pragma omp atomic' directive.
///
/// \code
/// #pragma omp atomic write
@@ -1086,14 +1120,14 @@ public:
/// In this example directive '#pragma omp atomic' has 'write' clause.
class OMPWriteClause : public OMPClause {
public:
- /// \brief Build 'write' clause.
+ /// 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.
+ /// Build an empty clause.
OMPWriteClause()
: OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {}
@@ -1106,7 +1140,7 @@ public:
}
};
-/// \brief This represents 'update' clause in the '#pragma omp atomic'
+/// This represents 'update' clause in the '#pragma omp atomic'
/// directive.
///
/// \code
@@ -1115,14 +1149,14 @@ public:
/// In this example directive '#pragma omp atomic' has 'update' clause.
class OMPUpdateClause : public OMPClause {
public:
- /// \brief Build 'update' clause.
+ /// 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.
+ /// Build an empty clause.
OMPUpdateClause()
: OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {}
@@ -1135,7 +1169,7 @@ public:
}
};
-/// \brief This represents 'capture' clause in the '#pragma omp atomic'
+/// This represents 'capture' clause in the '#pragma omp atomic'
/// directive.
///
/// \code
@@ -1144,14 +1178,14 @@ public:
/// In this example directive '#pragma omp atomic' has 'capture' clause.
class OMPCaptureClause : public OMPClause {
public:
- /// \brief Build 'capture' clause.
+ /// 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.
+ /// Build an empty clause.
OMPCaptureClause()
: OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {}
@@ -1164,7 +1198,7 @@ public:
}
};
-/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
+/// This represents 'seq_cst' clause in the '#pragma omp atomic'
/// directive.
///
/// \code
@@ -1173,14 +1207,14 @@ public:
/// In this example directive '#pragma omp atomic' has 'seq_cst' clause.
class OMPSeqCstClause : public OMPClause {
public:
- /// \brief Build 'seq_cst' clause.
+ /// 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.
+ /// Build an empty clause.
OMPSeqCstClause()
: OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {}
@@ -1193,7 +1227,7 @@ public:
}
};
-/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
+/// This represents clause 'private' in the '#pragma omp ...' directives.
///
/// \code
/// #pragma omp parallel private(a,b)
@@ -1207,7 +1241,7 @@ class OMPPrivateClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -1218,7 +1252,7 @@ class OMPPrivateClause final
: OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc,
EndLoc, N) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPPrivateClause(unsigned N)
@@ -1226,12 +1260,12 @@ class OMPPrivateClause final
SourceLocation(), SourceLocation(),
N) {}
- /// \brief Sets the list of references to private copies with initializers for
+ /// Sets the list of references to private copies with initializers for
/// new private variables.
/// \param VL List of references.
void setPrivateCopies(ArrayRef<Expr *> VL);
- /// \brief Gets the list of references to private copies with initializers for
+ /// Gets the list of references to private copies with initializers for
/// new private variables.
MutableArrayRef<Expr *> getPrivateCopies() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
@@ -1241,7 +1275,7 @@ class OMPPrivateClause final
}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -1254,7 +1288,7 @@ public:
SourceLocation EndLoc, ArrayRef<Expr *> VL,
ArrayRef<Expr *> PrivateVL);
- /// \brief Creates an empty clause with the place for \a N variables.
+ /// Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -1286,7 +1320,7 @@ public:
}
};
-/// \brief This represents clause 'firstprivate' in the '#pragma omp ...'
+/// This represents clause 'firstprivate' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -1302,7 +1336,7 @@ class OMPFirstprivateClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -1314,7 +1348,7 @@ class OMPFirstprivateClause final
LParenLoc, EndLoc, N),
OMPClauseWithPreInit(this) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPFirstprivateClause(unsigned N)
@@ -1323,12 +1357,12 @@ class OMPFirstprivateClause final
SourceLocation(), N),
OMPClauseWithPreInit(this) {}
- /// \brief Sets the list of references to private copies with initializers for
+ /// Sets the list of references to private copies with initializers for
/// new private variables.
/// \param VL List of references.
void setPrivateCopies(ArrayRef<Expr *> VL);
- /// \brief Gets the list of references to private copies with initializers for
+ /// Gets the list of references to private copies with initializers for
/// new private variables.
MutableArrayRef<Expr *> getPrivateCopies() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
@@ -1337,12 +1371,12 @@ class OMPFirstprivateClause final
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
- /// \brief Sets the list of references to initializer variables for new
+ /// Sets the list of references to initializer variables for new
/// private variables.
/// \param VL List of references.
void setInits(ArrayRef<Expr *> VL);
- /// \brief Gets the list of references to initializer variables for new
+ /// Gets the list of references to initializer variables for new
/// private variables.
MutableArrayRef<Expr *> getInits() {
return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
@@ -1352,7 +1386,7 @@ class OMPFirstprivateClause final
}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -1370,7 +1404,7 @@ public:
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.
+ /// Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -1413,7 +1447,7 @@ public:
}
};
-/// \brief This represents clause 'lastprivate' in the '#pragma omp ...'
+/// This represents clause 'lastprivate' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -1445,7 +1479,7 @@ class OMPLastprivateClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -1457,7 +1491,7 @@ class OMPLastprivateClause final
LParenLoc, EndLoc, N),
OMPClauseWithPostUpdate(this) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPLastprivateClause(unsigned N)
@@ -1466,7 +1500,7 @@ class OMPLastprivateClause final
SourceLocation(), N),
OMPClauseWithPostUpdate(this) {}
- /// \brief Get the list of helper expressions for initialization of private
+ /// Get the list of helper expressions for initialization of private
/// copies for lastprivate variables.
MutableArrayRef<Expr *> getPrivateCopies() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
@@ -1475,13 +1509,13 @@ class OMPLastprivateClause final
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent private variables (for arrays, single
/// array element) in the final assignment statement performed by the
/// lastprivate clause.
void setSourceExprs(ArrayRef<Expr *> SrcExprs);
- /// \brief Get the list of helper source expressions.
+ /// Get the list of helper source expressions.
MutableArrayRef<Expr *> getSourceExprs() {
return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
}
@@ -1489,13 +1523,13 @@ class OMPLastprivateClause final
return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent original variables (for arrays, single
/// array element) in the final assignment statement performed by the
/// lastprivate clause.
void setDestinationExprs(ArrayRef<Expr *> DstExprs);
- /// \brief Get the list of helper destination expressions.
+ /// Get the list of helper destination expressions.
MutableArrayRef<Expr *> getDestinationExprs() {
return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
}
@@ -1503,12 +1537,12 @@ class OMPLastprivateClause final
return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
}
- /// \brief Set list of helper assignment expressions, required for proper
+ /// Set list of helper assignment expressions, required for proper
/// codegen of the clause. These expressions are assignment expressions that
/// assign private copy of the variable to original variable.
void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
- /// \brief Get the list of helper assignment expressions.
+ /// Get the list of helper assignment expressions.
MutableArrayRef<Expr *> getAssignmentOps() {
return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
}
@@ -1517,7 +1551,7 @@ class OMPLastprivateClause final
}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -1547,7 +1581,7 @@ public:
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps,
Stmt *PreInit, Expr *PostUpdate);
- /// \brief Creates an empty clause with the place for \a N variables.
+ /// Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -1559,7 +1593,7 @@ public:
using helper_expr_const_range =
llvm::iterator_range<helper_expr_const_iterator>;
- /// \brief Set list of helper expressions, required for generation of private
+ /// Set list of helper expressions, required for generation of private
/// copies of original lastprivate variables.
void setPrivateCopies(ArrayRef<Expr *> PrivateCopies);
@@ -1612,7 +1646,7 @@ public:
}
};
-/// \brief This represents clause 'shared' in the '#pragma omp ...' directives.
+/// This represents clause 'shared' in the '#pragma omp ...' directives.
///
/// \code
/// #pragma omp parallel shared(a,b)
@@ -1625,7 +1659,7 @@ class OMPSharedClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -1636,7 +1670,7 @@ class OMPSharedClause final
: OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc,
EndLoc, N) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPSharedClause(unsigned N)
@@ -1645,7 +1679,7 @@ class OMPSharedClause final
N) {}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -1656,7 +1690,7 @@ public:
SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL);
- /// \brief Creates an empty clause with \a N variables.
+ /// Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -1672,7 +1706,7 @@ public:
}
};
-/// \brief This represents clause 'reduction' in the '#pragma omp ...'
+/// This represents clause 'reduction' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -1688,16 +1722,16 @@ class OMPReductionClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Location of ':'.
+ /// Location of ':'.
SourceLocation ColonLoc;
- /// \brief Nested name specifier for C++.
+ /// Nested name specifier for C++.
NestedNameSpecifierLoc QualifierLoc;
- /// \brief Name of custom operator.
+ /// Name of custom operator.
DeclarationNameInfo NameInfo;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -1715,7 +1749,7 @@ class OMPReductionClause final
OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc),
QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPReductionClause(unsigned N)
@@ -1724,21 +1758,21 @@ class OMPReductionClause final
N),
OMPClauseWithPostUpdate(this) {}
- /// \brief Sets location of ':' symbol in clause.
+ /// Sets location of ':' symbol in clause.
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
- /// \brief Sets the name info for specified reduction identifier.
+ /// Sets the name info for specified reduction identifier.
void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
- /// \brief Sets the nested name specifier.
+ /// Sets the nested name specifier.
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent private copy of the reduction
/// variable.
void setPrivates(ArrayRef<Expr *> Privates);
- /// \brief Get the list of helper privates.
+ /// Get the list of helper privates.
MutableArrayRef<Expr *> getPrivates() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
@@ -1746,12 +1780,12 @@ class OMPReductionClause final
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent LHS expression in the final
/// reduction expression performed by the reduction clause.
void setLHSExprs(ArrayRef<Expr *> LHSExprs);
- /// \brief Get the list of helper LHS expressions.
+ /// Get the list of helper LHS expressions.
MutableArrayRef<Expr *> getLHSExprs() {
return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
}
@@ -1759,14 +1793,14 @@ class OMPReductionClause final
return llvm::makeArrayRef(getPrivates().end(), varlist_size());
}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent RHS expression in the final
/// reduction expression performed by the reduction clause.
/// Also, variables in these expressions are used for proper initialization of
/// reduction copies.
void setRHSExprs(ArrayRef<Expr *> RHSExprs);
- /// \brief Get the list of helper destination expressions.
+ /// Get the list of helper destination expressions.
MutableArrayRef<Expr *> getRHSExprs() {
return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
}
@@ -1774,13 +1808,13 @@ class OMPReductionClause final
return llvm::makeArrayRef(getLHSExprs().end(), varlist_size());
}
- /// \brief Set list of helper reduction expressions, required for proper
+ /// Set list of helper reduction expressions, required for proper
/// codegen of the clause. These expressions are binary expressions or
/// operator/custom reduction call that calculates new value from source
/// helper expressions to destination helper expressions.
void setReductionOps(ArrayRef<Expr *> ReductionOps);
- /// \brief Get the list of helper reduction expressions.
+ /// Get the list of helper reduction expressions.
MutableArrayRef<Expr *> getReductionOps() {
return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size());
}
@@ -1789,7 +1823,7 @@ class OMPReductionClause final
}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -1829,19 +1863,19 @@ public:
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.
+ /// 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.
+ /// Gets location of ':' symbol in clause.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// \brief Gets the name info for specified reduction identifier.
+ /// Gets the name info for specified reduction identifier.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
- /// \brief Gets the nested name specifier.
+ /// Gets the nested name specifier.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
@@ -2357,7 +2391,7 @@ public:
}
};
-/// \brief This represents clause 'linear' in the '#pragma omp ...'
+/// This represents clause 'linear' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -2373,22 +2407,22 @@ class OMPLinearClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Modifier of 'linear' clause.
+ /// Modifier of 'linear' clause.
OpenMPLinearClauseKind Modifier = OMPC_LINEAR_val;
- /// \brief Location of linear modifier if any.
+ /// Location of linear modifier if any.
SourceLocation ModifierLoc;
- /// \brief Location of ':'.
+ /// Location of ':'.
SourceLocation ColonLoc;
- /// \brief Sets the linear step for clause.
+ /// Sets the linear step for clause.
void setStep(Expr *Step) { *(getFinals().end()) = Step; }
- /// \brief Sets the expression to calculate linear step for clause.
+ /// Sets the expression to calculate linear step for clause.
void setCalcStep(Expr *CalcStep) { *(getFinals().end() + 1) = CalcStep; }
- /// \brief Build 'linear' clause with given number of variables \a NumVars.
+ /// Build 'linear' clause with given number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -2404,7 +2438,7 @@ class OMPLinearClause final
OMPClauseWithPostUpdate(this), Modifier(Modifier),
ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param NumVars Number of variables.
explicit OMPLinearClause(unsigned NumVars)
@@ -2413,7 +2447,7 @@ class OMPLinearClause final
NumVars),
OMPClauseWithPostUpdate(this) {}
- /// \brief Gets the list of initial values for linear variables.
+ /// Gets the list of initial values for linear variables.
///
/// There are NumVars expressions with initial values allocated after the
/// varlist, they are followed by NumVars update expressions (used to update
@@ -2439,7 +2473,7 @@ class OMPLinearClause final
return llvm::makeArrayRef(getPrivates().end(), varlist_size());
}
- /// \brief Sets the list of update expressions for linear variables.
+ /// Sets the list of update expressions for linear variables.
MutableArrayRef<Expr *> getUpdates() {
return MutableArrayRef<Expr *>(getInits().end(), varlist_size());
}
@@ -2447,7 +2481,7 @@ class OMPLinearClause final
return llvm::makeArrayRef(getInits().end(), varlist_size());
}
- /// \brief Sets the list of final update expressions for linear variables.
+ /// Sets the list of final update expressions for linear variables.
MutableArrayRef<Expr *> getFinals() {
return MutableArrayRef<Expr *>(getUpdates().end(), varlist_size());
}
@@ -2455,16 +2489,16 @@ class OMPLinearClause final
return llvm::makeArrayRef(getUpdates().end(), varlist_size());
}
- /// \brief Sets the list of the copies of original linear variables.
+ /// Sets the list of the copies of original linear variables.
/// \param PL List of expressions.
void setPrivates(ArrayRef<Expr *> PL);
- /// \brief Sets the list of the initial values for linear variables.
+ /// Sets the list of the initial values for linear variables.
/// \param IL List of expressions.
void setInits(ArrayRef<Expr *> IL);
public:
- /// \brief Creates clause with a list of variables \a VL and a linear step
+ /// Creates clause with a list of variables \a VL and a linear step
/// \a Step.
///
/// \param C AST Context.
@@ -2490,47 +2524,47 @@ public:
ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep,
Stmt *PreInit, Expr *PostUpdate);
- /// \brief Creates an empty clause with the place for \a NumVars variables.
+ /// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
/// \param NumVars Number of variables.
static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
- /// \brief Set modifier.
+ /// Set modifier.
void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; }
- /// \brief Return modifier.
+ /// Return modifier.
OpenMPLinearClauseKind getModifier() const { return Modifier; }
- /// \brief Set modifier location.
+ /// Set modifier location.
void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
- /// \brief Return modifier location.
+ /// Return modifier location.
SourceLocation getModifierLoc() const { return ModifierLoc; }
- /// \brief Sets the location of ':'.
+ /// Sets the location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
- /// \brief Returns the location of ':'.
+ /// Returns the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// \brief Returns linear step.
+ /// Returns linear step.
Expr *getStep() { return *(getFinals().end()); }
- /// \brief Returns linear step.
+ /// Returns linear step.
const Expr *getStep() const { return *(getFinals().end()); }
- /// \brief Returns expression to calculate linear step.
+ /// Returns expression to calculate linear step.
Expr *getCalcStep() { return *(getFinals().end() + 1); }
- /// \brief Returns expression to calculate linear step.
+ /// Returns expression to calculate linear step.
const Expr *getCalcStep() const { return *(getFinals().end() + 1); }
- /// \brief Sets the list of update expressions for linear variables.
+ /// Sets the list of update expressions for linear variables.
/// \param UL List of expressions.
void setUpdates(ArrayRef<Expr *> UL);
- /// \brief Sets the list of final update expressions for linear variables.
+ /// Sets the list of final update expressions for linear variables.
/// \param FL List of expressions.
void setFinals(ArrayRef<Expr *> FL);
@@ -2596,7 +2630,7 @@ public:
}
};
-/// \brief This represents clause 'aligned' in the '#pragma omp ...'
+/// This represents clause 'aligned' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -2611,13 +2645,13 @@ class OMPAlignedClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Location of ':'.
+ /// Location of ':'.
SourceLocation ColonLoc;
- /// \brief Sets the alignment for clause.
+ /// Sets the alignment for clause.
void setAlignment(Expr *A) { *varlist_end() = A; }
- /// \brief Build 'aligned' clause with given number of variables \a NumVars.
+ /// Build 'aligned' clause with given number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -2631,7 +2665,7 @@ class OMPAlignedClause final
EndLoc, NumVars),
ColonLoc(ColonLoc) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param NumVars Number of variables.
explicit OMPAlignedClause(unsigned NumVars)
@@ -2640,7 +2674,7 @@ class OMPAlignedClause final
NumVars) {}
public:
- /// \brief Creates clause with a list of variables \a VL and alignment \a A.
+ /// Creates clause with a list of variables \a VL and alignment \a A.
///
/// \param C AST Context.
/// \param StartLoc Starting location of the clause.
@@ -2655,22 +2689,22 @@ public:
SourceLocation EndLoc, ArrayRef<Expr *> VL,
Expr *A);
- /// \brief Creates an empty clause with the place for \a NumVars variables.
+ /// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
/// \param NumVars Number of variables.
static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
- /// \brief Sets the location of ':'.
+ /// Sets the location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
- /// \brief Returns the location of ':'.
+ /// Returns the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// \brief Returns alignment.
+ /// Returns alignment.
Expr *getAlignment() { return *varlist_end(); }
- /// \brief Returns alignment.
+ /// Returns alignment.
const Expr *getAlignment() const { return *varlist_end(); }
child_range children() {
@@ -2683,7 +2717,7 @@ public:
}
};
-/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives.
+/// This represents clause 'copyin' in the '#pragma omp ...' directives.
///
/// \code
/// #pragma omp parallel copyin(a,b)
@@ -2710,7 +2744,7 @@ class OMPCopyinClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -2721,7 +2755,7 @@ class OMPCopyinClause final
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc,
EndLoc, N) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPCopyinClause(unsigned N)
@@ -2729,12 +2763,12 @@ class OMPCopyinClause final
SourceLocation(), SourceLocation(),
N) {}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent source expression in the final
/// assignment statement performed by the copyin clause.
void setSourceExprs(ArrayRef<Expr *> SrcExprs);
- /// \brief Get the list of helper source expressions.
+ /// Get the list of helper source expressions.
MutableArrayRef<Expr *> getSourceExprs() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
@@ -2742,12 +2776,12 @@ class OMPCopyinClause final
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent destination expression in the final
/// assignment statement performed by the copyin clause.
void setDestinationExprs(ArrayRef<Expr *> DstExprs);
- /// \brief Get the list of helper destination expressions.
+ /// Get the list of helper destination expressions.
MutableArrayRef<Expr *> getDestinationExprs() {
return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
}
@@ -2755,13 +2789,13 @@ class OMPCopyinClause final
return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
}
- /// \brief Set list of helper assignment expressions, required for proper
+ /// Set list of helper assignment expressions, required for proper
/// codegen of the clause. These expressions are assignment expressions that
/// assign source helper expressions to destination helper expressions
/// correspondingly.
void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
- /// \brief Get the list of helper assignment expressions.
+ /// Get the list of helper assignment expressions.
MutableArrayRef<Expr *> getAssignmentOps() {
return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
}
@@ -2770,7 +2804,7 @@ class OMPCopyinClause final
}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -2796,7 +2830,7 @@ public:
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
- /// \brief Creates an empty clause with \a N variables.
+ /// Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -2847,7 +2881,7 @@ public:
}
};
-/// \brief This represents clause 'copyprivate' in the '#pragma omp ...'
+/// This represents clause 'copyprivate' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -2862,7 +2896,7 @@ class OMPCopyprivateClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -2873,7 +2907,7 @@ class OMPCopyprivateClause final
: OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc,
LParenLoc, EndLoc, N) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPCopyprivateClause(unsigned N)
@@ -2881,12 +2915,12 @@ class OMPCopyprivateClause final
OMPC_copyprivate, SourceLocation(), SourceLocation(),
SourceLocation(), N) {}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent source expression in the final
/// assignment statement performed by the copyprivate clause.
void setSourceExprs(ArrayRef<Expr *> SrcExprs);
- /// \brief Get the list of helper source expressions.
+ /// Get the list of helper source expressions.
MutableArrayRef<Expr *> getSourceExprs() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
@@ -2894,12 +2928,12 @@ class OMPCopyprivateClause final
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
- /// \brief Set list of helper expressions, required for proper codegen of the
+ /// Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent destination expression in the final
/// assignment statement performed by the copyprivate clause.
void setDestinationExprs(ArrayRef<Expr *> DstExprs);
- /// \brief Get the list of helper destination expressions.
+ /// Get the list of helper destination expressions.
MutableArrayRef<Expr *> getDestinationExprs() {
return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
}
@@ -2907,13 +2941,13 @@ class OMPCopyprivateClause final
return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
}
- /// \brief Set list of helper assignment expressions, required for proper
+ /// Set list of helper assignment expressions, required for proper
/// codegen of the clause. These expressions are assignment expressions that
/// assign source helper expressions to destination helper expressions
/// correspondingly.
void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
- /// \brief Get the list of helper assignment expressions.
+ /// Get the list of helper assignment expressions.
MutableArrayRef<Expr *> getAssignmentOps() {
return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
}
@@ -2922,7 +2956,7 @@ class OMPCopyprivateClause final
}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -2947,7 +2981,7 @@ public:
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
- /// \brief Creates an empty clause with \a N variables.
+ /// Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -2998,7 +3032,7 @@ public:
}
};
-/// \brief This represents implicit clause 'flush' for the '#pragma omp flush'
+/// This represents implicit clause 'flush' for the '#pragma omp flush'
/// directive.
/// This clause does not exist by itself, it can be only as a part of 'omp
/// flush' directive. This clause is introduced to keep the original structure
@@ -3016,7 +3050,7 @@ class OMPFlushClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a N.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -3027,7 +3061,7 @@ class OMPFlushClause final
: OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc,
EndLoc, N) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPFlushClause(unsigned N)
@@ -3036,7 +3070,7 @@ class OMPFlushClause final
N) {}
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -3047,7 +3081,7 @@ public:
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL);
- /// \brief Creates an empty clause with \a N variables.
+ /// Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
@@ -3063,7 +3097,7 @@ public:
}
};
-/// \brief This represents implicit clause 'depend' for the '#pragma omp task'
+/// This represents implicit clause 'depend' for the '#pragma omp task'
/// directive.
///
/// \code
@@ -3078,45 +3112,53 @@ class OMPDependClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Dependency type (one of in, out, inout).
+ /// Dependency type (one of in, out, inout).
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
- /// \brief Dependency type location.
+ /// Dependency type location.
SourceLocation DepLoc;
- /// \brief Colon location.
+ /// Colon location.
SourceLocation ColonLoc;
- /// \brief Build clause with number of variables \a N.
+ /// Number of loops, associated with the depend clause.
+ unsigned NumLoops = 0;
+
+ /// 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.
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
+ SourceLocation EndLoc, unsigned N, unsigned NumLoops)
: OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
- EndLoc, N) {}
+ EndLoc, N), NumLoops(NumLoops) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
- explicit OMPDependClause(unsigned N)
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
+ explicit OMPDependClause(unsigned N, unsigned NumLoops)
: OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(),
SourceLocation(), SourceLocation(),
- N) {}
+ N),
+ NumLoops(NumLoops) {}
- /// \brief Set dependency kind.
+ /// Set dependency kind.
void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
- /// \brief Set dependency kind and its location.
+ /// Set dependency kind and its location.
void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; }
- /// \brief Set colon location.
+ /// Set colon location.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -3126,35 +3168,43 @@ public:
/// \param DepLoc Location of the dependency type.
/// \param ColonLoc Colon location.
/// \param VL List of references to the variables.
- static OMPDependClause *
- Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
+ static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VL, unsigned NumLoops);
- /// \brief Creates an empty clause with \a N variables.
+ /// 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);
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
+ static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N,
+ unsigned NumLoops);
- /// \brief Get dependency type.
+ /// Get dependency type.
OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
- /// \brief Get dependency type location.
+ /// Get dependency type location.
SourceLocation getDependencyLoc() const { return DepLoc; }
- /// \brief Get colon location.
+ /// 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 number of loops associated with the clause.
+ unsigned getNumLoops() const { return NumLoops; }
- /// Get the loop counter value.
- Expr *getCounterValue();
+ /// Set the loop data for the depend clauses with 'sink|source' kind of
+ /// dependency.
+ void setLoopData(unsigned NumLoop, Expr *Cnt);
- /// Get the loop counter value.
- const Expr *getCounterValue() const;
+ /// Get the loop data.
+ Expr *getLoopData(unsigned NumLoop);
+ const Expr *getLoopData(unsigned NumLoop) const;
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
@@ -3166,7 +3216,7 @@ public:
}
};
-/// \brief This represents 'device' clause in the '#pragma omp ...'
+/// This represents 'device' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -3177,46 +3227,49 @@ public:
class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Device number.
+ /// Device number.
Stmt *Device = nullptr;
- /// \brief Set the device number.
+ /// Set the device number.
///
/// \param E Device number.
void setDevice(Expr *E) { Device = E; }
public:
- /// \brief Build 'device' clause.
+ /// Build 'device' clause.
///
/// \param E Expression associated with this clause.
+ /// \param CaptureRegion Innermost OpenMP region where expressions in this
+ /// clause must be captured.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- OMPDeviceClause(Expr *E, Stmt *HelperE, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc)
+ OMPDeviceClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
: OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this),
LParenLoc(LParenLoc), Device(E) {
- setPreInitStmt(HelperE);
+ setPreInitStmt(HelperE, CaptureRegion);
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPDeviceClause()
: OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return device number.
+ /// Return device number.
Expr *getDevice() { return cast<Expr>(Device); }
- /// \brief Return device number.
+ /// Return device number.
Expr *getDevice() const { return cast<Expr>(Device); }
child_range children() { return child_range(&Device, &Device + 1); }
@@ -3226,7 +3279,7 @@ public:
}
};
-/// \brief This represents 'threads' clause in the '#pragma omp ...' directive.
+/// This represents 'threads' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp ordered threads
@@ -3234,14 +3287,14 @@ public:
/// In this example directive '#pragma omp ordered' has simple 'threads' clause.
class OMPThreadsClause : public OMPClause {
public:
- /// \brief Build 'threads' clause.
+ /// 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.
+ /// Build an empty clause.
OMPThreadsClause()
: OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {}
@@ -3254,7 +3307,7 @@ public:
}
};
-/// \brief This represents 'simd' clause in the '#pragma omp ...' directive.
+/// This represents 'simd' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp ordered simd
@@ -3262,14 +3315,14 @@ public:
/// In this example directive '#pragma omp ordered' has simple 'simd' clause.
class OMPSIMDClause : public OMPClause {
public:
- /// \brief Build 'simd' clause.
+ /// 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.
+ /// Build an empty clause.
OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {}
child_range children() {
@@ -3281,23 +3334,23 @@ public:
}
};
-/// \brief Struct that defines common infrastructure to handle mappable
+/// Struct that defines common infrastructure to handle mappable
/// expressions used in OpenMP clauses.
class OMPClauseMappableExprCommon {
public:
- // \brief Class that represents a component of a mappable expression. E.g.
- // for an expression S.a, the first component is a declaration reference
- // expression associated with 'S' and the second is a member expression
- // associated with the field declaration 'a'. If the expression is an array
- // subscript it may not have any associated declaration. In that case the
- // associated declaration is set to nullptr.
+ /// Class that represents a component of a mappable expression. E.g.
+ /// for an expression S.a, the first component is a declaration reference
+ /// expression associated with 'S' and the second is a member expression
+ /// associated with the field declaration 'a'. If the expression is an array
+ /// subscript it may not have any associated declaration. In that case the
+ /// associated declaration is set to nullptr.
class MappableComponent {
- // \brief Expression associated with the component.
+ /// 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.
+ /// 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:
@@ -3317,29 +3370,29 @@ public:
}
};
- // \brief List of components of an expression. This first one is the whole
+ // List of components of an expression. This first one is the whole
// expression and the last one is the base expression.
using MappableExprComponentList = SmallVector<MappableComponent, 8>;
using MappableExprComponentListRef = ArrayRef<MappableComponent>;
- // \brief List of all component lists associated to the same base declaration.
+ // 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'.
using MappableExprComponentLists = SmallVector<MappableExprComponentList, 8>;
using MappableExprComponentListsRef = ArrayRef<MappableExprComponentList>;
protected:
- // \brief Return the total number of elements in a list of component lists.
+ // Return the total number of elements in a list of component lists.
static unsigned
getComponentsTotalNumber(MappableExprComponentListsRef ComponentLists);
- // \brief Return the total number of elements in a list of declarations. All
+ // Return the total number of elements in a list of declarations. All
// declarations are expected to be canonical.
static unsigned
- getUniqueDeclarationsTotalNumber(ArrayRef<ValueDecl *> Declarations);
+ getUniqueDeclarationsTotalNumber(ArrayRef<const ValueDecl *> Declarations);
};
-/// \brief This represents clauses with a list of expressions that are mappable.
+/// This represents clauses with a list of expressions that are mappable.
/// Examples of these clauses are 'map' in
/// '#pragma omp target [enter|exit] [data]...' directives, and 'to' and 'from
/// in '#pragma omp target update...' directives.
@@ -3348,17 +3401,17 @@ class OMPMappableExprListClause : public OMPVarListClause<T>,
public OMPClauseMappableExprCommon {
friend class OMPClauseReader;
- /// \brief Number of unique declarations in this clause.
+ /// Number of unique declarations in this clause.
unsigned NumUniqueDeclarations;
- /// \brief Number of component lists in this clause.
+ /// Number of component lists in this clause.
unsigned NumComponentLists;
- /// \brief Total number of components in this clause.
+ /// Total number of components in this clause.
unsigned NumComponents;
protected:
- /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a
+ /// Build a clause for \a NumUniqueDeclarations declarations, \a
/// NumComponentLists total component lists, and \a NumComponents total
/// components.
///
@@ -3380,7 +3433,7 @@ protected:
NumUniqueDeclarations(NumUniqueDeclarations),
NumComponentLists(NumComponentLists), NumComponents(NumComponents) {}
- /// \brief Get the unique declarations that are in the trailing objects of the
+ /// Get the unique declarations that are in the trailing objects of the
/// class.
MutableArrayRef<ValueDecl *> getUniqueDeclsRef() {
return MutableArrayRef<ValueDecl *>(
@@ -3388,7 +3441,7 @@ protected:
NumUniqueDeclarations);
}
- /// \brief Get the unique declarations that are in the trailing objects of the
+ /// Get the unique declarations that are in the trailing objects of the
/// class.
ArrayRef<ValueDecl *> getUniqueDeclsRef() const {
return ArrayRef<ValueDecl *>(
@@ -3397,7 +3450,7 @@ protected:
NumUniqueDeclarations);
}
- /// \brief Set the unique declarations that are in the trailing objects of the
+ /// Set the unique declarations that are in the trailing objects of the
/// class.
void setUniqueDecls(ArrayRef<ValueDecl *> UDs) {
assert(UDs.size() == NumUniqueDeclarations &&
@@ -3405,7 +3458,7 @@ protected:
std::copy(UDs.begin(), UDs.end(), getUniqueDeclsRef().begin());
}
- /// \brief Get the number of lists per declaration that are in the trailing
+ /// Get the number of lists per declaration that are in the trailing
/// objects of the class.
MutableArrayRef<unsigned> getDeclNumListsRef() {
return MutableArrayRef<unsigned>(
@@ -3413,7 +3466,7 @@ protected:
NumUniqueDeclarations);
}
- /// \brief Get the number of lists per declaration that are in the trailing
+ /// Get the number of lists per declaration that are in the trailing
/// objects of the class.
ArrayRef<unsigned> getDeclNumListsRef() const {
return ArrayRef<unsigned>(
@@ -3421,7 +3474,7 @@ protected:
NumUniqueDeclarations);
}
- /// \brief Set the number of lists per declaration that are in the trailing
+ /// Set the number of lists per declaration that are in the trailing
/// objects of the class.
void setDeclNumLists(ArrayRef<unsigned> DNLs) {
assert(DNLs.size() == NumUniqueDeclarations &&
@@ -3429,7 +3482,7 @@ protected:
std::copy(DNLs.begin(), DNLs.end(), getDeclNumListsRef().begin());
}
- /// \brief Get the cumulative component lists sizes that are in the trailing
+ /// Get the cumulative component lists sizes that are in the trailing
/// objects of the class. They are appended after the number of lists.
MutableArrayRef<unsigned> getComponentListSizesRef() {
return MutableArrayRef<unsigned>(
@@ -3438,7 +3491,7 @@ protected:
NumComponentLists);
}
- /// \brief Get the cumulative component lists sizes that are in the trailing
+ /// Get the cumulative component lists sizes that are in the trailing
/// objects of the class. They are appended after the number of lists.
ArrayRef<unsigned> getComponentListSizesRef() const {
return ArrayRef<unsigned>(
@@ -3447,7 +3500,7 @@ protected:
NumComponentLists);
}
- /// \brief Set the cumulative component lists sizes that are in the trailing
+ /// Set the cumulative component lists sizes that are in the trailing
/// objects of the class.
void setComponentListSizes(ArrayRef<unsigned> CLSs) {
assert(CLSs.size() == NumComponentLists &&
@@ -3455,7 +3508,7 @@ protected:
std::copy(CLSs.begin(), CLSs.end(), getComponentListSizesRef().begin());
}
- /// \brief Get the components that are in the trailing objects of the class.
+ /// Get the components that are in the trailing objects of the class.
MutableArrayRef<MappableComponent> getComponentsRef() {
return MutableArrayRef<MappableComponent>(
static_cast<T *>(this)
@@ -3463,7 +3516,7 @@ protected:
NumComponents);
}
- /// \brief Get the components that are in the trailing objects of the class.
+ /// Get the components that are in the trailing objects of the class.
ArrayRef<MappableComponent> getComponentsRef() const {
return ArrayRef<MappableComponent>(
static_cast<const T *>(this)
@@ -3471,7 +3524,7 @@ protected:
NumComponents);
}
- /// \brief Set the components that are in the trailing objects of the class.
+ /// Set the components that are in the trailing objects of the class.
/// This requires the list sizes so that it can also fill the original
/// expressions, which are the first component of each list.
void setComponents(ArrayRef<MappableComponent> Components,
@@ -3483,7 +3536,7 @@ protected:
std::copy(Components.begin(), Components.end(), getComponentsRef().begin());
}
- /// \brief Fill the clause information from the list of declarations and
+ /// Fill the clause information from the list of declarations and
/// associated component lists.
void setClauseInfo(ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists) {
@@ -3560,17 +3613,17 @@ protected:
}
public:
- /// \brief Return the number of unique base declarations in this clause.
+ /// 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.
+ /// 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
+ /// Return the total number of components in all lists derived from the
/// clause.
unsigned getTotalComponentsNum() const { return NumComponents; }
- /// \brief Iterator that browse the components by lists. It also allows
+ /// Iterator that browse the components by lists. It also allows
/// browsing components of a single declaration.
class const_component_lists_iterator
: public llvm::iterator_adaptor_base<
@@ -3600,7 +3653,7 @@ public:
MappableExprComponentListRef::const_iterator End;
public:
- /// \brief Construct an iterator that scans all lists.
+ /// Construct an iterator that scans all lists.
explicit const_component_lists_iterator(
ArrayRef<ValueDecl *> UniqueDecls, ArrayRef<unsigned> DeclsListNum,
ArrayRef<unsigned> CumulativeListSizes,
@@ -3616,7 +3669,7 @@ public:
RemainingLists = *NumListsCur;
}
- /// \brief Construct an iterator that scan lists for a given declaration \a
+ /// Construct an iterator that scan lists for a given declaration \a
/// Declaration.
explicit const_component_lists_iterator(
const ValueDecl *Declaration, ArrayRef<ValueDecl *> UniqueDecls,
@@ -3706,7 +3759,7 @@ public:
using const_component_lists_range =
llvm::iterator_range<const_component_lists_iterator>;
- /// \brief Iterators for all component lists.
+ /// Iterators for all component lists.
const_component_lists_iterator component_lists_begin() const {
return const_component_lists_iterator(
getUniqueDeclsRef(), getDeclNumListsRef(), getComponentListSizesRef(),
@@ -3722,7 +3775,7 @@ public:
return {component_lists_begin(), component_lists_end()};
}
- /// \brief Iterators for component lists associated with the provided
+ /// Iterators for component lists associated with the provided
/// declaration.
const_component_lists_iterator
decl_component_lists_begin(const ValueDecl *VD) const {
@@ -3775,7 +3828,7 @@ public:
}
};
-/// \brief This represents clause 'map' in the '#pragma omp ...'
+/// This represents clause 'map' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -3804,22 +3857,22 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
- /// \brief Map type modifier for the 'map' clause.
+ /// Map type modifier for the 'map' clause.
OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
- /// \brief Map type for the 'map' clause.
+ /// Map type for the 'map' clause.
OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
- /// \brief Is this an implicit map type or not.
+ /// Is this an implicit map type or not.
bool MapTypeIsImplicit = false;
- /// \brief Location of the map type.
+ /// Location of the map type.
SourceLocation MapLoc;
- /// \brief Colon location.
+ /// Colon location.
SourceLocation ColonLoc;
- /// \brief Build a clause for \a NumVars listed expressions, \a
+ /// Build a clause for \a NumVars listed expressions, \a
/// NumUniqueDeclarations declarations, \a NumComponentLists total component
/// lists, and \a NumComponents total expression components.
///
@@ -3846,7 +3899,7 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
MapTypeModifier(MapTypeModifier), MapType(MapType),
MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param NumVars Number of expressions listed in this clause.
/// \param NumUniqueDeclarations Number of unique base declarations in this
@@ -3859,26 +3912,26 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(),
NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {}
- /// \brief Set type modifier for the clause.
+ /// 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.
+ /// Set type for the clause.
///
/// \param T Type for the clause.
void setMapType(OpenMPMapClauseKind T) { MapType = T; }
- /// \brief Set type location.
+ /// Set type location.
///
/// \param TLoc Type location.
void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; }
- /// \brief Set colon location.
+ /// Set colon location.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -3899,7 +3952,7 @@ public:
OpenMPMapClauseKind Type, bool TypeIsImplicit,
SourceLocation TypeLoc);
- /// \brief Creates an empty clause with the place for for \a NumVars original
+ /// Creates an empty clause with the place for \a NumVars original
/// expressions, \a NumUniqueDeclarations declarations, \NumComponentLists
/// lists, and \a NumComponents expression components.
///
@@ -3915,25 +3968,25 @@ public:
unsigned NumComponentLists,
unsigned NumComponents);
- /// \brief Fetches mapping kind for the clause.
+ /// Fetches mapping kind for the clause.
OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; }
- /// \brief Is this an implicit map type?
+ /// Is this an implicit map type?
/// We have to capture 'IsMapTypeImplicit' from the parser for more
/// informative error messages. It helps distinguish map(r) from
/// map(tofrom: r), which is important to print more helpful error
/// messages for some target directives.
bool isImplicitMapType() const LLVM_READONLY { return MapTypeIsImplicit; }
- /// \brief Fetches the map type modifier for the clause.
+ /// Fetches the map type modifier for the clause.
OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY {
return MapTypeModifier;
}
- /// \brief Fetches location of clause mapping kind.
+ /// Fetches location of clause mapping kind.
SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; }
- /// \brief Get colon location.
+ /// Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
child_range children() {
@@ -3947,7 +4000,7 @@ public:
}
};
-/// \brief This represents 'num_teams' clause in the '#pragma omp ...'
+/// This represents 'num_teams' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -3958,19 +4011,19 @@ public:
class OMPNumTeamsClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief NumTeams number.
+ /// NumTeams number.
Stmt *NumTeams = nullptr;
- /// \brief Set the NumTeams number.
+ /// Set the NumTeams number.
///
/// \param E NumTeams number.
void setNumTeams(Expr *E) { NumTeams = E; }
public:
- /// \brief Build 'num_teams' clause.
+ /// Build 'num_teams' clause.
///
/// \param E Expression associated with this clause.
/// \param HelperE Helper Expression associated with this clause.
@@ -3987,21 +4040,21 @@ public:
setPreInitStmt(HelperE, CaptureRegion);
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPNumTeamsClause()
: OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return NumTeams number.
+ /// Return NumTeams number.
Expr *getNumTeams() { return cast<Expr>(NumTeams); }
- /// \brief Return NumTeams number.
+ /// Return NumTeams number.
Expr *getNumTeams() const { return cast<Expr>(NumTeams); }
child_range children() { return child_range(&NumTeams, &NumTeams + 1); }
@@ -4011,7 +4064,7 @@ public:
}
};
-/// \brief This represents 'thread_limit' clause in the '#pragma omp ...'
+/// This represents 'thread_limit' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4022,19 +4075,19 @@ public:
class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief ThreadLimit number.
+ /// ThreadLimit number.
Stmt *ThreadLimit = nullptr;
- /// \brief Set the ThreadLimit number.
+ /// Set the ThreadLimit number.
///
/// \param E ThreadLimit number.
void setThreadLimit(Expr *E) { ThreadLimit = E; }
public:
- /// \brief Build 'thread_limit' clause.
+ /// Build 'thread_limit' clause.
///
/// \param E Expression associated with this clause.
/// \param HelperE Helper Expression associated with this clause.
@@ -4052,21 +4105,21 @@ public:
setPreInitStmt(HelperE, CaptureRegion);
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPThreadLimitClause()
: OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return ThreadLimit number.
+ /// Return ThreadLimit number.
Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); }
- /// \brief Return ThreadLimit number.
+ /// Return ThreadLimit number.
Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); }
child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); }
@@ -4076,7 +4129,7 @@ public:
}
};
-/// \brief This represents 'priority' clause in the '#pragma omp ...'
+/// This represents 'priority' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4087,19 +4140,19 @@ public:
class OMPPriorityClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Priority number.
+ /// Priority number.
Stmt *Priority = nullptr;
- /// \brief Set the Priority number.
+ /// Set the Priority number.
///
/// \param E Priority number.
void setPriority(Expr *E) { Priority = E; }
public:
- /// \brief Build 'priority' clause.
+ /// Build 'priority' clause.
///
/// \param E Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -4110,20 +4163,20 @@ public:
: OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
Priority(E) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPPriorityClause()
: OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return Priority number.
+ /// Return Priority number.
Expr *getPriority() { return cast<Expr>(Priority); }
- /// \brief Return Priority number.
+ /// Return Priority number.
Expr *getPriority() const { return cast<Expr>(Priority); }
child_range children() { return child_range(&Priority, &Priority + 1); }
@@ -4133,7 +4186,7 @@ public:
}
};
-/// \brief This represents 'grainsize' clause in the '#pragma omp ...'
+/// This represents 'grainsize' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4144,17 +4197,17 @@ public:
class OMPGrainsizeClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Safe iteration space distance.
+ /// Safe iteration space distance.
Stmt *Grainsize = nullptr;
- /// \brief Set safelen.
+ /// Set safelen.
void setGrainsize(Expr *Size) { Grainsize = Size; }
public:
- /// \brief Build 'grainsize' clause.
+ /// Build 'grainsize' clause.
///
/// \param Size Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -4164,17 +4217,17 @@ public:
: OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
Grainsize(Size) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPGrainsizeClause()
: OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return safe iteration space distance.
+ /// Return safe iteration space distance.
Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); }
child_range children() { return child_range(&Grainsize, &Grainsize + 1); }
@@ -4184,7 +4237,7 @@ public:
}
};
-/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive.
+/// This represents 'nogroup' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp taskloop nogroup
@@ -4192,14 +4245,14 @@ public:
/// In this example directive '#pragma omp taskloop' has 'nogroup' clause.
class OMPNogroupClause : public OMPClause {
public:
- /// \brief Build 'nogroup' clause.
+ /// 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.
+ /// Build an empty clause.
OMPNogroupClause()
: OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {}
@@ -4212,7 +4265,7 @@ public:
}
};
-/// \brief This represents 'num_tasks' clause in the '#pragma omp ...'
+/// This represents 'num_tasks' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4223,17 +4276,17 @@ public:
class OMPNumTasksClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Safe iteration space distance.
+ /// Safe iteration space distance.
Stmt *NumTasks = nullptr;
- /// \brief Set safelen.
+ /// Set safelen.
void setNumTasks(Expr *Size) { NumTasks = Size; }
public:
- /// \brief Build 'num_tasks' clause.
+ /// Build 'num_tasks' clause.
///
/// \param Size Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -4243,17 +4296,17 @@ public:
: OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumTasks(Size) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPNumTasksClause()
: OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Return safe iteration space distance.
+ /// Return safe iteration space distance.
Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); }
child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
@@ -4263,7 +4316,7 @@ public:
}
};
-/// \brief This represents 'hint' clause in the '#pragma omp ...' directive.
+/// This represents 'hint' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp critical (name) hint(6)
@@ -4273,17 +4326,17 @@ public:
class OMPHintClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Hint expression of the 'hint' clause.
+ /// Hint expression of the 'hint' clause.
Stmt *Hint = nullptr;
- /// \brief Set hint expression.
+ /// Set hint expression.
void setHint(Expr *H) { Hint = H; }
public:
- /// \brief Build 'hint' clause with expression \a Hint.
+ /// Build 'hint' clause with expression \a Hint.
///
/// \param Hint Hint expression.
/// \param StartLoc Starting location of the clause.
@@ -4294,16 +4347,16 @@ public:
: OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc),
Hint(Hint) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
OMPHintClause() : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()) {}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
- /// \brief Returns number of threads.
+ /// Returns number of threads.
Expr *getHint() const { return cast_or_null<Expr>(Hint); }
child_range children() { return child_range(&Hint, &Hint + 1); }
@@ -4313,7 +4366,7 @@ public:
}
};
-/// \brief This represents 'dist_schedule' clause in the '#pragma omp ...'
+/// This represents 'dist_schedule' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4324,48 +4377,48 @@ public:
class OMPDistScheduleClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief A kind of the 'schedule' clause.
+ /// A kind of the 'schedule' clause.
OpenMPDistScheduleClauseKind Kind = OMPC_DIST_SCHEDULE_unknown;
- /// \brief Start location of the schedule kind in source code.
+ /// Start location of the schedule kind in source code.
SourceLocation KindLoc;
- /// \brief Location of ',' (if any).
+ /// Location of ',' (if any).
SourceLocation CommaLoc;
- /// \brief Chunk size.
+ /// Chunk size.
Expr *ChunkSize = nullptr;
- /// \brief Set schedule kind.
+ /// Set schedule kind.
///
/// \param K Schedule kind.
void setDistScheduleKind(OpenMPDistScheduleClauseKind K) { Kind = K; }
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
///
/// \param Loc Location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Set schedule kind start location.
+ /// Set schedule kind start location.
///
/// \param KLoc Schedule kind location.
void setDistScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
- /// \brief Set location of ','.
+ /// Set location of ','.
///
/// \param Loc Location of ','.
void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
- /// \brief Set chunk size.
+ /// Set chunk size.
///
/// \param E Chunk size.
void setChunkSize(Expr *E) { ChunkSize = E; }
public:
- /// \brief Build 'dist_schedule' clause with schedule kind \a Kind and chunk
+ /// Build 'dist_schedule' clause with schedule kind \a Kind and chunk
/// size expression \a ChunkSize.
///
/// \param StartLoc Starting location of the clause.
@@ -4387,27 +4440,27 @@ public:
setPreInitStmt(HelperChunkSize);
}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPDistScheduleClause()
: OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()),
OMPClauseWithPreInit(this) {}
- /// \brief Get kind of the clause.
+ /// Get kind of the clause.
OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; }
- /// \brief Get location of '('.
+ /// Get location of '('.
SourceLocation getLParenLoc() { return LParenLoc; }
- /// \brief Get kind location.
+ /// Get kind location.
SourceLocation getDistScheduleKindLoc() { return KindLoc; }
- /// \brief Get location of ','.
+ /// Get location of ','.
SourceLocation getCommaLoc() { return CommaLoc; }
- /// \brief Get chunk size.
+ /// Get chunk size.
Expr *getChunkSize() { return ChunkSize; }
- /// \brief Get chunk size.
+ /// Get chunk size.
const Expr *getChunkSize() const { return ChunkSize; }
child_range children() {
@@ -4420,7 +4473,7 @@ public:
}
};
-/// \brief This represents 'defaultmap' clause in the '#pragma omp ...' directive.
+/// This represents 'defaultmap' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp target defaultmap(tofrom: scalar)
@@ -4430,50 +4483,50 @@ public:
class OMPDefaultmapClause : public OMPClause {
friend class OMPClauseReader;
- /// \brief Location of '('.
+ /// Location of '('.
SourceLocation LParenLoc;
- /// \brief Modifiers for 'defaultmap' clause.
+ /// Modifiers for 'defaultmap' clause.
OpenMPDefaultmapClauseModifier Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
- /// \brief Locations of modifiers.
+ /// Locations of modifiers.
SourceLocation ModifierLoc;
- /// \brief A kind of the 'defaultmap' clause.
+ /// A kind of the 'defaultmap' clause.
OpenMPDefaultmapClauseKind Kind = OMPC_DEFAULTMAP_unknown;
- /// \brief Start location of the defaultmap kind in source code.
+ /// Start location of the defaultmap kind in source code.
SourceLocation KindLoc;
- /// \brief Set defaultmap kind.
+ /// Set defaultmap kind.
///
/// \param K Defaultmap kind.
void setDefaultmapKind(OpenMPDefaultmapClauseKind K) { Kind = K; }
- /// \brief Set the defaultmap modifier.
+ /// Set the defaultmap modifier.
///
/// \param M Defaultmap modifier.
void setDefaultmapModifier(OpenMPDefaultmapClauseModifier M) {
Modifier = M;
}
- /// \brief Set location of the defaultmap modifier.
+ /// Set location of the defaultmap modifier.
void setDefaultmapModifierLoc(SourceLocation Loc) {
ModifierLoc = Loc;
}
- /// \brief Sets the location of '('.
+ /// Sets the location of '('.
///
/// \param Loc Location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Set defaultmap kind start location.
+ /// Set defaultmap kind start location.
///
/// \param KLoc Defaultmap kind location.
void setDefaultmapKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
public:
- /// \brief Build 'defaultmap' clause with defaultmap kind \a Kind
+ /// Build 'defaultmap' clause with defaultmap kind \a Kind
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -4489,25 +4542,25 @@ public:
: OMPClause(OMPC_defaultmap, StartLoc, EndLoc), LParenLoc(LParenLoc),
Modifier(M), ModifierLoc(MLoc), Kind(Kind), KindLoc(KLoc) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPDefaultmapClause()
: OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()) {}
- /// \brief Get kind of the clause.
+ /// Get kind of the clause.
OpenMPDefaultmapClauseKind getDefaultmapKind() const { return Kind; }
- /// \brief Get the modifier of the clause.
+ /// Get the modifier of the clause.
OpenMPDefaultmapClauseModifier getDefaultmapModifier() const {
return Modifier;
}
- /// \brief Get location of '('.
+ /// Get location of '('.
SourceLocation getLParenLoc() { return LParenLoc; }
- /// \brief Get kind location.
+ /// Get kind location.
SourceLocation getDefaultmapKindLoc() { return KindLoc; }
- /// \brief Get the modifier location.
+ /// Get the modifier location.
SourceLocation getDefaultmapModifierLoc() const {
return ModifierLoc;
}
@@ -4521,7 +4574,7 @@ public:
}
};
-/// \brief This represents clause 'to' in the '#pragma omp ...'
+/// This represents clause 'to' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -4538,7 +4591,7 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a NumVars.
+ /// Build clause with number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
@@ -4555,7 +4608,7 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
NumUniqueDeclarations, NumComponentLists,
NumComponents) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param NumVars Number of expressions listed in this clause.
/// \param NumUniqueDeclarations Number of unique base declarations in this
@@ -4581,7 +4634,7 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
}
public:
- /// \brief Creates clause with a list of variables \a Vars.
+ /// Creates clause with a list of variables \a Vars.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -4595,7 +4648,7 @@ public:
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists);
- /// \brief Creates an empty clause with the place for \a NumVars variables.
+ /// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
/// \param NumVars Number of expressions listed in the clause.
@@ -4619,7 +4672,7 @@ public:
}
};
-/// \brief This represents clause 'from' in the '#pragma omp ...'
+/// This represents clause 'from' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -4637,7 +4690,7 @@ class OMPFromClause final
friend OMPVarListClause;
friend TrailingObjects;
- /// \brief Build clause with number of variables \a NumVars.
+ /// Build clause with number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
@@ -4654,7 +4707,7 @@ class OMPFromClause final
NumVars, NumUniqueDeclarations,
NumComponentLists, NumComponents) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param NumVars Number of expressions listed in this clause.
/// \param NumUniqueDeclarations Number of unique base declarations in this
@@ -4680,7 +4733,7 @@ class OMPFromClause final
}
public:
- /// \brief Creates clause with a list of variables \a Vars.
+ /// Creates clause with a list of variables \a Vars.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
@@ -4694,7 +4747,7 @@ public:
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists);
- /// \brief Creates an empty clause with the place for \a NumVars variables.
+ /// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
/// \param NumVars Number of expressions listed in the clause.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def
index b13cf3b63276..e2d65d84880c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def
@@ -227,87 +227,87 @@ CAST_OPERATION(BlockPointerToObjCPointerCast)
/// to a block pointer. Block-to-block casts are bitcasts.
CAST_OPERATION(AnyPointerToBlockPointerCast)
-/// \brief Converting between two Objective-C object types, which
+/// Converting between two Objective-C object types, which
/// can occur when performing reference binding to an Objective-C
/// object.
CAST_OPERATION(ObjCObjectLValueCast)
-/// \brief A conversion of a floating point real to a floating point
+/// A conversion of a floating point real to a floating point
/// complex of the original type. Injects the value as the real
/// component with a zero imaginary component.
/// float -> _Complex float
CAST_OPERATION(FloatingRealToComplex)
-/// \brief Converts a floating point complex to floating point real
+/// Converts a floating point complex to floating point real
/// of the source's element type. Just discards the imaginary
/// component.
/// _Complex long double -> long double
CAST_OPERATION(FloatingComplexToReal)
-/// \brief Converts a floating point complex to bool by comparing
+/// Converts a floating point complex to bool by comparing
/// against 0+0i.
CAST_OPERATION(FloatingComplexToBoolean)
-/// \brief Converts between different floating point complex types.
+/// Converts between different floating point complex types.
/// _Complex float -> _Complex double
CAST_OPERATION(FloatingComplexCast)
-/// \brief Converts from a floating complex to an integral complex.
+/// Converts from a floating complex to an integral complex.
/// _Complex float -> _Complex int
CAST_OPERATION(FloatingComplexToIntegralComplex)
-/// \brief Converts from an integral real to an integral complex
+/// Converts from an integral real to an integral complex
/// whose element type matches the source. Injects the value as
/// the real component with a zero imaginary component.
/// long -> _Complex long
CAST_OPERATION(IntegralRealToComplex)
-/// \brief Converts an integral complex to an integral real of the
+/// Converts an integral complex to an integral real of the
/// source's element type by discarding the imaginary component.
/// _Complex short -> short
CAST_OPERATION(IntegralComplexToReal)
-/// \brief Converts an integral complex to bool by comparing against
+/// Converts an integral complex to bool by comparing against
/// 0+0i.
CAST_OPERATION(IntegralComplexToBoolean)
-/// \brief Converts between different integral complex types.
+/// Converts between different integral complex types.
/// _Complex char -> _Complex long long
/// _Complex unsigned int -> _Complex signed int
CAST_OPERATION(IntegralComplexCast)
-/// \brief Converts from an integral complex to a floating complex.
+/// Converts from an integral complex to a floating complex.
/// _Complex unsigned -> _Complex float
CAST_OPERATION(IntegralComplexToFloatingComplex)
-/// \brief [ARC] Produces a retainable object pointer so that it may
+/// [ARC] Produces a retainable object pointer so that it may
/// be consumed, e.g. by being passed to a consuming parameter.
/// Calls objc_retain.
CAST_OPERATION(ARCProduceObject)
-/// \brief [ARC] Consumes a retainable object pointer that has just
+/// [ARC] Consumes a retainable object pointer that has just
/// been produced, e.g. as the return value of a retaining call.
/// Enters a cleanup to call objc_release at some indefinite time.
CAST_OPERATION(ARCConsumeObject)
-/// \brief [ARC] Reclaim a retainable object pointer object that may
+/// [ARC] Reclaim a retainable object pointer object that may
/// have been produced and autoreleased as part of a function return
/// sequence.
CAST_OPERATION(ARCReclaimReturnedObject)
-/// \brief [ARC] Causes a value of block type to be copied to the
+/// [ARC] Causes a value of block type to be copied to the
/// heap, if it is not already there. A number of other operations
/// in ARC cause blocks to be copied; this is for cases where that
/// would not otherwise be guaranteed, such as when casting to a
/// non-block pointer type.
CAST_OPERATION(ARCExtendBlockObject)
-/// \brief Converts from _Atomic(T) to T.
+/// Converts from _Atomic(T) to T.
CAST_OPERATION(AtomicToNonAtomic)
-/// \brief Converts from T to _Atomic(T).
+/// Converts from T to _Atomic(T).
CAST_OPERATION(NonAtomicToAtomic)
-/// \brief Causes a block literal to by copied to the heap and then
+/// Causes a block literal to by copied to the heap and then
/// autoreleased.
///
/// This particular cast kind is used for the conversion from a C++11
@@ -391,13 +391,13 @@ BINARY_OPERATION(Comma, ",")
// [C99 6.5.2.4] Postfix increment and decrement
UNARY_OPERATION(PostInc, "++")
UNARY_OPERATION(PostDec, "--")
-// [C99 6.5.3.1] Prefix increment and decrement
+// [C99 6.5.3.1] Prefix increment and decrement
UNARY_OPERATION(PreInc, "++")
UNARY_OPERATION(PreDec, "--")
// [C99 6.5.3.2] Address and indirection
UNARY_OPERATION(AddrOf, "&")
UNARY_OPERATION(Deref, "*")
-// [C99 6.5.3.3] Unary arithmetic
+// [C99 6.5.3.3] Unary arithmetic
UNARY_OPERATION(Plus, "+")
UNARY_OPERATION(Minus, "-")
UNARY_OPERATION(Not, "~")
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
index e3832689d64b..ac512d721e34 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
@@ -16,7 +16,7 @@
#define LLVM_CLANG_AST_OPERATIONKINDS_H
namespace clang {
-
+
/// CastKind - The kind of operation required for a conversion.
enum CastKind {
#define CAST_OPERATION(Name) CK_##Name,
@@ -33,15 +33,15 @@ enum UnaryOperatorKind {
#include "clang/AST/OperationKinds.def"
};
-/// \brief The kind of bridging performed by the Objective-C bridge cast.
+/// The kind of bridging performed by the Objective-C bridge cast.
enum ObjCBridgeCastKind {
- /// \brief Bridging via __bridge, which does nothing but reinterpret
+ /// Bridging via __bridge, which does nothing but reinterpret
/// the bits.
OBC_Bridge,
- /// \brief Bridging via __bridge_transfer, which transfers ownership of an
+ /// Bridging via __bridge_transfer, which transfers ownership of an
/// Objective-C pointer into ARC.
OBC_BridgeTransfer,
- /// \brief Bridging via __bridge_retain, which makes an ARC object available
+ /// Bridging via __bridge_retain, which makes an ARC object available
/// as a +1 C pointer.
OBC_BridgeRetained
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h
index 8945c413d268..c1c76ceaaf69 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h
@@ -24,7 +24,7 @@ public:
ParentMap(Stmt* ASTRoot);
~ParentMap();
- /// \brief Adds and/or updates the parent/child-relations of the complete
+ /// Adds and/or updates the parent/child-relations of the complete
/// stmt tree of S. All children of S including indirect descendants are
/// visited and updated or inserted but not the parents of S.
void addStmt(Stmt* S);
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyDeclStackTrace.h
index ca22e640deb4..8eb519eae26d 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyDeclStackTrace.h
@@ -13,31 +13,31 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H
-#define LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H
+#ifndef LLVM_CLANG_AST_PRETTYDECLSTACKTRACE_H
+#define LLVM_CLANG_AST_PRETTYDECLSTACKTRACE_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/PrettyStackTrace.h"
namespace clang {
+class ASTContext;
class Decl;
-class Sema;
class SourceManager;
/// PrettyDeclStackTraceEntry - If a crash occurs in the parser while
/// parsing something related to a declaration, include that
/// declaration in the stack trace.
class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry {
- Sema &S;
+ ASTContext &Context;
Decl *TheDecl;
SourceLocation Loc;
const char *Message;
public:
- PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc,
+ PrettyDeclStackTraceEntry(ASTContext &Ctx, Decl *D, SourceLocation Loc,
const char *Msg)
- : S(S), TheDecl(D), Loc(Loc), Message(Msg) {}
+ : Context(Ctx), TheDecl(D), Loc(Loc), Message(Msg) {}
void print(raw_ostream &OS) const override;
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
index e831b903cbae..b49f5be1b1e6 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
@@ -36,7 +36,7 @@ public:
/// This type is intended to be small and suitable for passing by value.
/// It is very frequently copied.
struct PrintingPolicy {
- /// \brief Create a default printing policy for the specified language.
+ /// Create a default printing policy for the specified language.
PrintingPolicy(const LangOptions &LO)
: Indentation(2), SuppressSpecifiers(false),
SuppressTagKeyword(LO.CPlusPlus),
@@ -109,7 +109,7 @@ struct PrintingPolicy {
/// Suppress printing parts of scope specifiers that don't need
/// to be written, e.g., for inline or anonymous namespaces.
bool SuppressUnwrittenScope : 1;
-
+
/// Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
@@ -140,15 +140,15 @@ struct PrintingPolicy {
/// char a[9] = "A string";
/// \endcode
bool ConstantArraySizeAsWritten : 1;
-
+
/// 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;
-
+
/// When true, suppress printing of the __strong lifetime qualifier in ARC.
unsigned SuppressStrongLifetime : 1;
-
+
/// When true, suppress printing of lifetime qualifier in ARC.
unsigned SuppressLifetimeQualifiers : 1;
@@ -179,7 +179,7 @@ struct PrintingPolicy {
/// declarations inside namespaces etc. Effectively, this should print
/// only the requested declaration.
unsigned TerseOutput : 1;
-
+
/// When true, do certain refinement needed for producing proper declaration
/// tag; such as, do not print attributes attached to the declaration.
///
diff --git a/contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h b/contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h
index 86d805feeed7..422ed9e4c8fc 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h
@@ -63,7 +63,7 @@
namespace clang {
namespace TypeName {
-/// \brief Get the fully qualified name for a type. This includes full
+/// Get the fully qualified name for a type. This includes full
/// qualification of all template parameters etc.
///
/// \param[in] QT - the type for which the fully qualified name will be
@@ -72,9 +72,10 @@ namespace TypeName {
/// \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,
+ const PrintingPolicy &Policy,
bool WithGlobalNsPrefix = false);
-/// \brief Generates a QualType that can be used to name the same type
+/// 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.
///
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h b/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h
index 2e005ddbd027..8327efc750fd 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h
@@ -41,7 +41,7 @@ public:
RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { }
RawComment(const SourceManager &SourceMgr, SourceRange SR,
- bool Merged, bool ParseAllComments);
+ const CommentOptions &CommentOpts, bool Merged);
CommentKind getKind() const LLVM_READONLY {
return (CommentKind) Kind;
@@ -70,7 +70,6 @@ public:
/// \code /**< stuff */ \endcode
/// \code /*!< stuff */ \endcode
bool isTrailingComment() const LLVM_READONLY {
- assert(isDocumentation());
return IsTrailingComment;
}
@@ -83,8 +82,7 @@ public:
/// Returns true if this comment is not a documentation comment.
bool isOrdinary() const LLVM_READONLY {
- return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)) &&
- !ParseAllComments;
+ return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC));
}
/// Returns true if this comment any kind of a documentation comment.
@@ -92,11 +90,6 @@ public:
return !isInvalid() && !isOrdinary();
}
- /// Returns whether we are parsing all comments.
- bool isParseAllComments() const LLVM_READONLY {
- return ParseAllComments;
- }
-
/// Returns raw comment text with comment markers.
StringRef getRawText(const SourceManager &SourceMgr) const {
if (RawTextValid)
@@ -118,6 +111,30 @@ public:
return extractBriefText(Context);
}
+ /// Returns sanitized comment text, suitable for presentation in editor UIs.
+ /// E.g. will transform:
+ /// // This is a long multiline comment.
+ /// // Parts of it might be indented.
+ /// /* The comments styles might be mixed. */
+ /// into
+ /// "This is a long multiline comment.\n"
+ /// " Parts of it might be indented.\n"
+ /// "The comments styles might be mixed."
+ /// Also removes leading indentation and sanitizes some common cases:
+ /// /* This is a first line.
+ /// * This is a second line. It is indented.
+ /// * This is a third line. */
+ /// and
+ /// /* This is a first line.
+ /// This is a second line. It is indented.
+ /// This is a third line. */
+ /// will both turn into:
+ /// "This is a first line.\n"
+ /// " This is a second line. It is indented.\n"
+ /// "This is a third line."
+ std::string getFormattedText(const SourceManager &SourceMgr,
+ DiagnosticsEngine &Diags) const;
+
/// Parse the comment, assuming it is attached to decl \c D.
comments::FullComment *parse(const ASTContext &Context,
const Preprocessor *PP, const Decl *D) const;
@@ -139,18 +156,12 @@ private:
bool IsTrailingComment : 1;
bool IsAlmostTrailingComment : 1;
- /// When true, ordinary comments starting with "//" and "/*" will be
- /// considered as documentation comments.
- bool ParseAllComments : 1;
-
- /// \brief Constructor for AST deserialization.
+ /// Constructor for AST deserialization.
RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
- bool IsAlmostTrailingComment,
- bool ParseAllComments) :
+ bool IsAlmostTrailingComment) :
Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
IsAttached(false), IsTrailingComment(IsTrailingComment),
- IsAlmostTrailingComment(IsAlmostTrailingComment),
- ParseAllComments(ParseAllComments)
+ IsAlmostTrailingComment(IsAlmostTrailingComment)
{ }
StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
@@ -160,7 +171,7 @@ private:
friend class ASTReader;
};
-/// \brief Compare comments' source locations.
+/// Compare comments' source locations.
template<>
class BeforeThanCompare<RawComment> {
const SourceManager &SM;
@@ -177,13 +188,14 @@ public:
}
};
-/// \brief This class represents all comments included in the translation unit,
+/// This class represents all comments included in the translation unit,
/// sorted in order of appearance in the translation unit.
class RawCommentList {
public:
RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
- void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator);
+ void addComment(const RawComment &RC, const CommentOptions &CommentOpts,
+ llvm::BumpPtrAllocator &Allocator);
ArrayRef<RawComment *> getComments() const {
return Comments;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
index 696d44efa0d9..a546c200ffe0 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
@@ -71,6 +71,10 @@ private:
// Alignment - Alignment of record in characters.
CharUnits Alignment;
+ // UnadjustedAlignment - Maximum of the alignments of the record members in
+ // characters.
+ CharUnits UnadjustedAlignment;
+
/// RequiredAlignment - The required alignment of the object. In the MS-ABI
/// the __declspec(align()) trumps #pramga pack and must always be obeyed.
CharUnits RequiredAlignment;
@@ -111,7 +115,7 @@ private:
/// Only used for MS-ABI.
bool EndsWithZeroSizedObject : 1;
- /// \brief True if this class is zero sized or first base is zero sized or
+ /// True if this class is zero sized or first base is zero sized or
/// has this property. Only used for MS-ABI.
bool LeadsWithZeroSizedBase : 1;
@@ -120,10 +124,10 @@ private:
/// BaseSharingVBPtr - The base we share vbptr with.
const CXXRecordDecl *BaseSharingVBPtr;
-
+
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>;
-
+
/// BaseOffsets - Contains a map from base classes to their offset.
BaseOffsetsMapTy BaseOffsets;
@@ -136,6 +140,7 @@ private:
CXXRecordLayoutInfo *CXXInfo = nullptr;
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+ CharUnits unadjustedAlignment,
CharUnits requiredAlignment, CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets);
@@ -144,6 +149,7 @@ private:
// Constructor for C++ records.
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
+ CharUnits unadjustedAlignment,
CharUnits requiredAlignment,
bool hasOwnVFPtr, bool hasExtendableVFPtr,
CharUnits vbptroffset,
@@ -162,7 +168,7 @@ private:
~ASTRecordLayout() = default;
void Destroy(ASTContext &Ctx);
-
+
public:
ASTRecordLayout(const ASTRecordLayout &) = delete;
ASTRecordLayout &operator=(const ASTRecordLayout &) = delete;
@@ -170,6 +176,10 @@ public:
/// getAlignment - Get the record alignment in characters.
CharUnits getAlignment() const { return Alignment; }
+ /// getUnadjustedAlignment - Get the record alignment in characters, before
+ /// alignment adjustement.
+ CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
+
/// getSize - Get the record size in characters.
CharUnits getSize() const { return Size; }
@@ -259,7 +269,7 @@ public:
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->HasExtendableVFPtr;
}
-
+
/// hasOwnVBPtr - Does this class provide its own virtual-base
/// table pointer, rather than inheriting one from a primary base
/// class?
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
index ba76ea0a0df5..0d2b670507c1 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -83,7 +83,7 @@ namespace clang {
return false; \
} while (false)
-/// \brief A class that does preorder or postorder
+/// 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:
@@ -146,7 +146,7 @@ namespace clang {
/// from which they were produced.
///
/// By default, this visitor preorder traverses the AST. If postorder traversal
-/// is needed, the \c shouldTraversePostOrder method needs to be overriden
+/// is needed, the \c shouldTraversePostOrder method needs to be overridden
/// to return \c true.
template <typename Derived> class RecursiveASTVisitor {
public:
@@ -158,25 +158,25 @@ public:
typedef SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>>
DataRecursionQueue;
- /// \brief Return a reference to the derived class.
+ /// Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived *>(this); }
- /// \brief Return whether this visitor should recurse into
+ /// Return whether this visitor should recurse into
/// template instantiations.
bool shouldVisitTemplateInstantiations() const { return false; }
- /// \brief Return whether this visitor should recurse into the types of
+ /// Return whether this visitor should recurse into the types of
/// TypeLocs.
bool shouldWalkTypesOfTypeLocs() const { return true; }
- /// \brief Return whether this visitor should recurse into implicit
+ /// Return whether this visitor should recurse into implicit
/// code, e.g., implicit constructors and destructors.
bool shouldVisitImplicitCode() const { return false; }
- /// \brief Return whether this visitor should traverse post-order.
+ /// Return whether this visitor should traverse post-order.
bool shouldTraversePostOrder() const { return false; }
- /// \brief Recursively visit a statement or expression, by
+ /// Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
@@ -195,70 +195,70 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool dataTraverseStmtPost(Stmt *S) { return true; }
- /// \brief Recursively visit a type, by dispatching to
+ /// Recursively visit a type, by dispatching to
/// Traverse*Type() based on the argument's getTypeClass() property.
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is a Null type).
bool TraverseType(QualType T);
- /// \brief Recursively visit a type with location, by dispatching to
+ /// Recursively visit a type with location, by dispatching to
/// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is a Null type location).
bool TraverseTypeLoc(TypeLoc TL);
- /// \brief Recursively visit an attribute, by dispatching to
+ /// Recursively visit an attribute, by dispatching to
/// Traverse*Attr() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is a Null type location).
bool TraverseAttr(Attr *At);
- /// \brief Recursively visit a declaration, by dispatching to
+ /// Recursively visit a declaration, by dispatching to
/// Traverse*Decl() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is NULL).
bool TraverseDecl(Decl *D);
- /// \brief Recursively visit a C++ nested-name-specifier.
+ /// Recursively visit a C++ nested-name-specifier.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
- /// \brief Recursively visit a C++ nested-name-specifier with location
+ /// Recursively visit a C++ nested-name-specifier with location
/// information.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
- /// \brief Recursively visit a name with its location information.
+ /// Recursively visit a name with its location information.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
- /// \brief Recursively visit a template name and dispatch to the
+ /// Recursively visit a template name and dispatch to the
/// appropriate method.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseTemplateName(TemplateName Template);
- /// \brief Recursively visit a template argument and dispatch to the
+ /// Recursively visit a template argument and dispatch to the
/// appropriate method for the argument type.
///
/// \returns false if the visitation was terminated early, true otherwise.
// FIXME: migrate callers to TemplateArgumentLoc instead.
bool TraverseTemplateArgument(const TemplateArgument &Arg);
- /// \brief Recursively visit a template argument location and dispatch to the
+ /// Recursively visit a template argument location and dispatch to the
/// appropriate method for the argument type.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
- /// \brief Recursively visit a set of template arguments.
+ /// Recursively visit a set of template arguments.
/// This can be overridden by a subclass, but it's not expected that
/// will be needed -- this visitor always dispatches to another.
///
@@ -267,13 +267,13 @@ public:
bool TraverseTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
- /// \brief Recursively visit a base specifier. This can be overridden by a
+ /// 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
+ /// Recursively visit a constructor initializer. This
/// automatically dispatches to another visitor for the initializer
/// expression, but not for the name of the initializer, so may
/// be overridden for clients that need access to the name.
@@ -281,14 +281,14 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
- /// \brief Recursively visit a lambda capture. \c Init is the expression that
+ /// Recursively visit a lambda capture. \c Init is the expression that
/// will be used to initialize the capture.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
Expr *Init);
- /// \brief Recursively visit the body of a lambda expression.
+ /// Recursively visit the body of a lambda expression.
///
/// This provides a hook for visitors that need more context when visiting
/// \c LE->getBody().
@@ -296,7 +296,7 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
- /// \brief Recursively visit the syntactic or semantic form of an
+ /// Recursively visit the syntactic or semantic form of an
/// initialization list.
///
/// \returns false if the visitation was terminated early, true otherwise.
@@ -305,7 +305,7 @@ public:
// ---- Methods on Attrs ----
- // \brief Visit an attribute.
+ // Visit an attribute.
bool VisitAttr(Attr *A) { return true; }
// Declare Traverse* and empty Visit* for all Attr classes.
@@ -529,7 +529,7 @@ private:
bool TraverseOMPClause(OMPClause *C);
#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
#include "clang/Basic/OpenMPKinds.def"
- /// \brief Process clauses with list of variables.
+ /// Process clauses with list of variables.
template <typename T> bool VisitOMPClauseList(T *Node);
/// Process clauses with pre-initis.
bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node);
@@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
+DEF_TRAVERSE_TYPE(DependentVectorType, {
+ if (T->getSizeExpr())
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ TRY_TO(TraverseType(T->getElementType()));
+})
+
DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
if (T->getSizeExpr())
TRY_TO(TraverseStmt(T->getSizeExpr()));
@@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, {
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
+DEF_TRAVERSE_TYPELOC(DependentVectorType, {
+ if (TL.getTypePtr()->getSizeExpr())
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+})
+
// FIXME: size and attributes
// FIXME: base VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(ExtVectorType, {
@@ -2585,6 +2597,7 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, {})
+DEF_TRAVERSE_STMT(FixedPointLiteral, {})
DEF_TRAVERSE_STMT(CharacterLiteral, {})
DEF_TRAVERSE_STMT(FloatingLiteral, {})
DEF_TRAVERSE_STMT(ImaginaryLiteral, {})
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
index 86b0f356e7b5..c2bd6e6fd136 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
@@ -36,7 +36,7 @@ class Decl;
// DeclLink that may point to one of 3 possible states:
// - the "previous" (temporal) element in the chain
// - the "latest" (temporal) element in the chain
-// - the an "uninitialized-latest" value (when newly-constructed)
+// - the "uninitialized-latest" value (when newly-constructed)
//
// - The first element is also often called the canonical element. Every
// element has a pointer to it so that "getCanonical" can be fast.
@@ -48,10 +48,8 @@ class Decl;
// "most-recent" when referring to temporal order: order of addition
// to the chain.
//
-// - To make matters confusing, the DeclLink type uses the term "next"
-// for its pointer-storage internally (thus functions like
-// NextIsPrevious). It's easiest to just ignore the implementation of
-// DeclLink when making sense of the redeclaration chain.
+// - It's easiest to just ignore the implementation of DeclLink when making
+// sense of the redeclaration chain.
//
// - There's also a "definition" link for several types of
// redeclarable, where only one definition should exist at any given
@@ -82,7 +80,7 @@ class Decl;
// | link +-----+ |
// +-->-------------------------------------------+
-/// \brief Provides common interface for the Decls that can be redeclared.
+/// Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
class Redeclarable {
protected:
@@ -105,66 +103,64 @@ protected:
/// previous declaration.
using NotKnownLatest = llvm::PointerUnion<Previous, UninitializedLatest>;
- mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next;
+ mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Link;
public:
enum PreviousTag { PreviousLink };
enum LatestTag { LatestLink };
DeclLink(LatestTag, const ASTContext &Ctx)
- : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
- DeclLink(PreviousTag, decl_type *D) : Next(NotKnownLatest(Previous(D))) {}
+ : Link(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
+ DeclLink(PreviousTag, decl_type *D) : Link(NotKnownLatest(Previous(D))) {}
- bool NextIsPrevious() const {
- return Next.is<NotKnownLatest>() &&
+ bool isFirst() const {
+ return Link.is<KnownLatest>() ||
// FIXME: 'template' is required on the next line due to an
// apparent clang bug.
- Next.get<NotKnownLatest>().template is<Previous>();
+ Link.get<NotKnownLatest>().template is<UninitializedLatest>();
}
- bool NextIsLatest() const { return !NextIsPrevious(); }
-
- decl_type *getNext(const decl_type *D) const {
- if (Next.is<NotKnownLatest>()) {
- NotKnownLatest NKL = Next.get<NotKnownLatest>();
+ decl_type *getPrevious(const decl_type *D) const {
+ if (Link.is<NotKnownLatest>()) {
+ NotKnownLatest NKL = Link.get<NotKnownLatest>();
if (NKL.is<Previous>())
return static_cast<decl_type*>(NKL.get<Previous>());
// Allocate the generational 'most recent' cache now, if needed.
- Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ Link = KnownLatest(*reinterpret_cast<const ASTContext *>(
NKL.get<UninitializedLatest>()),
const_cast<decl_type *>(D));
}
- return static_cast<decl_type*>(Next.get<KnownLatest>().get(D));
+ return static_cast<decl_type*>(Link.get<KnownLatest>().get(D));
}
void setPrevious(decl_type *D) {
- assert(NextIsPrevious() && "decl became non-canonical unexpectedly");
- Next = Previous(D);
+ assert(!isFirst() && "decl became non-canonical unexpectedly");
+ Link = Previous(D);
}
void setLatest(decl_type *D) {
- assert(NextIsLatest() && "decl became canonical unexpectedly");
- if (Next.is<NotKnownLatest>()) {
- NotKnownLatest NKL = Next.get<NotKnownLatest>();
- Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ assert(isFirst() && "decl became canonical unexpectedly");
+ if (Link.is<NotKnownLatest>()) {
+ NotKnownLatest NKL = Link.get<NotKnownLatest>();
+ Link = KnownLatest(*reinterpret_cast<const ASTContext *>(
NKL.get<UninitializedLatest>()),
D);
} else {
- auto Latest = Next.get<KnownLatest>();
+ auto Latest = Link.get<KnownLatest>();
Latest.set(D);
- Next = Latest;
+ Link = Latest;
}
}
- void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); }
+ void markIncomplete() { Link.get<KnownLatest>().markIncomplete(); }
Decl *getLatestNotUpdated() const {
- assert(NextIsLatest() && "expected a canonical decl");
- if (Next.is<NotKnownLatest>())
+ assert(isFirst() && "expected a canonical decl");
+ if (Link.is<NotKnownLatest>())
return nullptr;
- return Next.get<KnownLatest>().getNotUpdated();
+ return Link.get<KnownLatest>().getNotUpdated();
}
};
@@ -176,10 +172,10 @@ protected:
return DeclLink(DeclLink::LatestLink, Ctx);
}
- /// \brief Points to the next redeclaration in the chain.
+ /// Points to the next redeclaration in the chain.
///
- /// If NextIsPrevious() is true, this is a link to the previous declaration
- /// of this same Decl. If NextIsLatest() is true, this is the first
+ /// If isFirst() is false, this is a link to the previous declaration
+ /// of this same Decl. If isFirst() is true, this is the first
/// declaration and Link points to the latest declaration. For example:
///
/// #1 int f(int x, int y = 1); // <pointer to #3, true>
@@ -192,7 +188,7 @@ protected:
decl_type *First;
decl_type *getNextRedeclaration() const {
- return RedeclLink.getNext(static_cast<const decl_type *>(this));
+ return RedeclLink.getPrevious(static_cast<const decl_type *>(this));
}
public:
@@ -203,10 +199,10 @@ public:
: RedeclLink(LatestDeclLink(Ctx)),
First(static_cast<decl_type *>(this)) {}
- /// \brief Return the previous declaration of this declaration or NULL if this
+ /// Return the previous declaration of this declaration or NULL if this
/// is the first declaration.
decl_type *getPreviousDecl() {
- if (RedeclLink.NextIsPrevious())
+ if (!RedeclLink.isFirst())
return getNextRedeclaration();
return nullptr;
}
@@ -215,32 +211,32 @@ public:
static_cast<const decl_type*>(this))->getPreviousDecl();
}
- /// \brief Return the first declaration of this declaration or itself if this
+ /// Return the first declaration of this declaration or itself if this
/// is the only declaration.
decl_type *getFirstDecl() { return First; }
- /// \brief Return the first declaration of this declaration or itself if this
+ /// Return the first declaration of this declaration or itself if this
/// is the only declaration.
const decl_type *getFirstDecl() const { return First; }
- /// \brief True if this is the first declaration in its redeclaration chain.
- bool isFirstDecl() const { return RedeclLink.NextIsLatest(); }
+ /// True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const { return RedeclLink.isFirst(); }
- /// \brief Returns the most recent (re)declaration of this declaration.
+ /// Returns the most recent (re)declaration of this declaration.
decl_type *getMostRecentDecl() {
return getFirstDecl()->getNextRedeclaration();
}
- /// \brief Returns the most recent (re)declaration of this declaration.
+ /// Returns the most recent (re)declaration of this declaration.
const decl_type *getMostRecentDecl() const {
return getFirstDecl()->getNextRedeclaration();
}
- /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
+ /// Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
void setPreviousDecl(decl_type *PrevDecl);
- /// \brief Iterates through all the redeclarations of the same decl.
+ /// Iterates through all the redeclarations of the same decl.
class redecl_iterator {
/// Current - The current declaration.
decl_type *Current = nullptr;
@@ -294,7 +290,7 @@ public:
using redecl_range = llvm::iterator_range<redecl_iterator>;
- /// \brief Returns an iterator range for all the redeclarations of the same
+ /// Returns an iterator range for all the redeclarations of the same
/// decl. It will iterate at least once (when this decl is the only one).
redecl_range redecls() const {
return redecl_range(redecl_iterator(const_cast<decl_type *>(
@@ -306,11 +302,11 @@ public:
redecl_iterator redecls_end() const { return redecls().end(); }
};
-/// \brief Get the primary declaration for a declaration from an AST file. That
+/// Get the primary declaration for a declaration from an AST file. That
/// will be the first-loaded declaration.
Decl *getPrimaryMergedDecl(Decl *D);
-/// \brief Provides common interface for the Decls that cannot be redeclared,
+/// Provides common interface for the Decls that cannot be redeclared,
/// but can be merged if the same declaration is brought in from multiple
/// modules.
template<typename decl_type>
@@ -318,25 +314,25 @@ class Mergeable {
public:
Mergeable() = default;
- /// \brief Return the first declaration of this declaration or itself if this
+ /// Return the first declaration of this declaration or itself if this
/// is the only declaration.
decl_type *getFirstDecl() {
- decl_type *D = static_cast<decl_type*>(this);
+ auto *D = static_cast<decl_type *>(this);
if (!D->isFromASTFile())
return D;
return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
}
- /// \brief Return the first declaration of this declaration or itself if this
+ /// Return the first declaration of this declaration or itself if this
/// is the only declaration.
const decl_type *getFirstDecl() const {
- const decl_type *D = static_cast<const decl_type*>(this);
+ const auto *D = static_cast<const decl_type *>(this);
if (!D->isFromASTFile())
return D;
return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
}
- /// \brief Returns true if this is the first declaration.
+ /// Returns true if this is the first declaration.
bool isFirstDecl() const { return getFirstDecl() == this; }
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h b/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h
index 6d903f820cd4..6ca2dba47558 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h
@@ -23,32 +23,32 @@ namespace clang {
class Expr;
class ParmVarDecl;
-/// \brief Whether all locations of the selector identifiers are in a
+/// Whether all locations of the selector identifiers are in a
/// "standard" position.
enum SelectorLocationsKind {
- /// \brief Non-standard.
+ /// Non-standard.
SelLoc_NonStandard = 0,
- /// \brief For nullary selectors, immediately before the end:
+ /// For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or immediately before the arguments:
/// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y;
SelLoc_StandardNoSpace = 1,
- /// \brief For nullary selectors, immediately before the end:
+ /// For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or with a space between the arguments:
/// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y;
SelLoc_StandardWithSpace = 2
};
-/// \brief Returns true if all \p SelLocs are in a "standard" location.
+/// Returns true if all \p SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
-/// \brief Get the "standard" location of a selector identifier, e.g:
+/// Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
@@ -60,13 +60,13 @@ SourceLocation getStandardSelectorLoc(unsigned Index,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
-/// \brief Returns true if all \p SelLocs are in a "standard" location.
+/// Returns true if all \p SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<ParmVarDecl *> Args,
SourceLocation EndLoc);
-/// \brief Get the "standard" location of a selector identifier, e.g:
+/// Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
index b27dbfacf6a6..aa0f88b71023 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -92,7 +92,7 @@ protected:
class StmtBitfields {
friend class Stmt;
- /// \brief The statement class.
+ /// The statement class.
unsigned sClass : 8;
};
enum { NumStmtBits = 8 };
@@ -198,11 +198,13 @@ protected:
class CastExprBitfields {
friend class CastExpr;
+ friend class ImplicitCastExpr;
unsigned : NumExprBits;
unsigned Kind : 6;
- unsigned BasePathSize : 32 - 6 - NumExprBits;
+ unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr.
+ unsigned BasePathIsEmpty : 1;
};
class CallExprBitfields {
@@ -237,6 +239,16 @@ protected:
unsigned ResultIndex : 32 - 8 - NumExprBits;
};
+ class OpaqueValueExprBitfields {
+ friend class OpaqueValueExpr;
+
+ unsigned : NumExprBits;
+
+ /// The OVE is a unique semantic reference to its source expressio if this
+ /// bit is set to true.
+ unsigned IsUnique : 1;
+ };
+
class ObjCIndirectCopyRestoreExprBitfields {
friend class ObjCIndirectCopyRestoreExpr;
@@ -259,17 +271,17 @@ protected:
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class TypeTraitExpr;
-
+
unsigned : NumExprBits;
-
- /// \brief The kind of type trait, which is a value of a TypeTrait enumerator.
+
+ /// The kind of type trait, which is a value of a TypeTrait enumerator.
unsigned Kind : 8;
-
- /// \brief If this expression is not value-dependent, this indicates whether
+
+ /// If this expression is not value-dependent, this indicates whether
/// the trait evaluated true or false.
unsigned Value : 1;
- /// \brief The number of arguments to this type trait.
+ /// The number of arguments to this type trait.
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
};
@@ -294,6 +306,7 @@ protected:
CallExprBitfields CallExprBits;
ExprWithCleanupsBitfields ExprWithCleanupsBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
+ OpaqueValueExprBitfields OpaqueValueExprBits;
ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
InitListExprBitfields InitListExprBits;
TypeTraitExprBitfields TypeTraitExprBits;
@@ -319,7 +332,7 @@ public:
void operator delete(void *, void *) noexcept {}
public:
- /// \brief A placeholder type used to construct an empty shell of a
+ /// 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 {};
@@ -358,11 +371,11 @@ protected:
};
private:
- /// \brief Whether statistic collection is enabled.
+ /// Whether statistic collection is enabled.
static bool StatisticsEnabled;
protected:
- /// \brief Construct an empty statement.
+ /// Construct an empty statement.
explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {}
public:
@@ -393,7 +406,7 @@ public:
static void EnableStatistics();
static void PrintStats();
- /// \brief Dumps the specified AST fragment and all subtrees to
+ /// Dumps the specified AST fragment and all subtrees to
/// \c llvm::errs().
void dump() const;
void dump(SourceManager &SM) const;
@@ -421,7 +434,7 @@ public:
return const_cast<Stmt *>(this)->IgnoreImplicit();
}
- /// \brief Skip no-op (attributed, compound) container stmts and skip captured
+ /// 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 {
@@ -444,6 +457,7 @@ public:
using const_child_range = llvm::iterator_range<const_child_iterator>;
child_range children();
+
const_child_range children() const {
auto Children = const_cast<Stmt *>(this)->children();
return const_child_range(Children.begin(), Children.end());
@@ -455,7 +469,7 @@ public:
const_child_iterator child_begin() const { return children().begin(); }
const_child_iterator child_end() const { return children().end(); }
- /// \brief Produce a unique representation of the given statement.
+ /// Produce a unique representation of the given statement.
///
/// \param ID once the profiling operation is complete, will contain
/// the unique representation of the given statement.
@@ -470,7 +484,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
bool Canonical) const;
- /// \brief Calculate a unique representation for a statement that is
+ /// Calculate a unique representation for a statement that is
/// stable across compiler invocations.
///
/// \param ID profile information will be stored in ID.
@@ -492,7 +506,7 @@ public:
DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc)
: Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {}
- /// \brief Build an empty declaration statement.
+ /// Build an empty declaration statement.
explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) {}
/// isSingleDecl - This method returns true if this DeclStmt refers
@@ -532,9 +546,11 @@ public:
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 {
return decl_const_range(decl_begin(), decl_end());
}
+
decl_iterator decl_begin() { return DG.begin(); }
decl_iterator decl_end() { return DG.end(); }
const_decl_iterator decl_begin() const { return DG.begin(); }
@@ -556,7 +572,7 @@ public:
class NullStmt : public Stmt {
SourceLocation SemiLoc;
- /// \brief True if the null statement was preceded by an empty macro, e.g:
+ /// True if the null statement was preceded by an empty macro, e.g:
/// @code
/// #define CALL(x)
/// CALL(0);
@@ -571,7 +587,7 @@ public:
: Stmt(NullStmtClass), SemiLoc(L),
HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
- /// \brief Build an empty null statement.
+ /// Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {}
SourceLocation getSemiLoc() const { return SemiLoc; }
@@ -608,13 +624,13 @@ public:
static CompoundStmt *Create(const ASTContext &C, ArrayRef<Stmt *> Stmts,
SourceLocation LB, SourceLocation RB);
- // \brief Build an empty compound statement with a location.
+ // Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
: Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
}
- // \brief Build an empty compound statement.
+ // Build an empty compound statement.
static CompoundStmt *CreateEmpty(const ASTContext &C, unsigned NumStmts);
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
@@ -627,6 +643,7 @@ public:
body_iterator body_begin() { return getTrailingObjects<Stmt *>(); }
body_iterator body_end() { return body_begin() + size(); }
Stmt *body_front() { return !body_empty() ? body_begin()[0] : nullptr; }
+
Stmt *body_back() {
return !body_empty() ? body_begin()[size() - 1] : nullptr;
}
@@ -646,6 +663,7 @@ public:
const_body_iterator body_begin() const {
return getTrailingObjects<Stmt *>();
}
+
const_body_iterator body_end() const { return body_begin() + size(); }
const Stmt *body_front() const {
@@ -751,7 +769,7 @@ public:
EllipsisLoc = ellipsisLoc;
}
- /// \brief Build an empty switch case statement.
+ /// Build an empty switch case statement.
explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {}
SourceLocation getCaseLoc() const { return KeywordLoc; }
@@ -784,7 +802,7 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY {
// Handle deeply nested case statements with iteration instead of recursion.
const CaseStmt *CS = this;
- while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
+ while (const auto *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
CS = CS2;
return CS->getSubStmt()->getLocEnd();
@@ -807,7 +825,7 @@ public:
DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
- /// \brief Build an empty default statement.
+ /// Build an empty default statement.
explicit DefaultStmt(EmptyShell Empty)
: SwitchCase(DefaultStmtClass, Empty) {}
@@ -832,7 +850,7 @@ public:
};
inline SourceLocation SwitchCase::getLocEnd() const {
- if (const CaseStmt *CS = dyn_cast<CaseStmt>(this))
+ if (const auto *CS = dyn_cast<CaseStmt>(this))
return CS->getLocEnd();
return cast<DefaultStmt>(this)->getLocEnd();
}
@@ -852,7 +870,7 @@ public:
"LabelStmt too big");
}
- // \brief Build an empty label statement.
+ // Build an empty label statement.
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {}
SourceLocation getIdentLoc() const { return IdentLoc; }
@@ -874,7 +892,7 @@ public:
}
};
-/// \brief Represents an attribute applied to a statement.
+/// Represents an attribute applied to a statement.
///
/// Represents an attribute applied to a statement. For example:
/// [[omp::for(...)]] for (...) { ... }
@@ -895,7 +913,7 @@ class AttributedStmt final
}
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
- : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
+ : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
}
@@ -908,7 +926,7 @@ public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
- // \brief Build an empty attributed statement.
+ // Build an empty attributed statement.
static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs);
SourceLocation getAttrLoc() const { return AttrLoc; }
@@ -943,10 +961,10 @@ public:
Stmt *then, SourceLocation EL = SourceLocation(),
Stmt *elsev = nullptr);
- /// \brief Build an empty if/then/else statement
+ /// Build an empty if/then/else statement
explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {}
- /// \brief Retrieve the variable declared in this "if" statement, if any.
+ /// Retrieve the variable declared in this "if" statement, if any.
///
/// In the following example, "x" is the condition variable.
/// \code
@@ -1022,10 +1040,10 @@ class SwitchStmt : public Stmt {
public:
SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond);
- /// \brief Build a empty switch statement.
+ /// Build a empty switch statement.
explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {}
- /// \brief Retrieve the variable declared in this "switch" statement, if any.
+ /// Retrieve the variable declared in this "switch" statement, if any.
///
/// In the following example, "x" is the condition variable.
/// \code
@@ -1056,7 +1074,7 @@ public:
void setBody(Stmt *S) { SubExprs[BODY] = S; }
SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); }
- /// \brief Set the case list for this switch statement.
+ /// Set the case list for this switch statement.
void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); }
SourceLocation getSwitchLoc() const { return SwitchLoc; }
@@ -1108,10 +1126,10 @@ public:
WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
SourceLocation WL);
- /// \brief Build an empty while statement.
+ /// Build an empty while statement.
explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {}
- /// \brief Retrieve the variable declared in this "while" statement, if any.
+ /// Retrieve the variable declared in this "while" statement, if any.
///
/// In the following example, "x" is the condition variable.
/// \code
@@ -1170,7 +1188,7 @@ public:
SubExprs[BODY] = body;
}
- /// \brief Build an empty do-while statement.
+ /// Build an empty do-while statement.
explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {}
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
@@ -1215,12 +1233,12 @@ public:
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP);
- /// \brief Build an empty for statement.
+ /// Build an empty for statement.
explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {}
Stmt *getInit() { return SubExprs[INIT]; }
- /// \brief Retrieve the variable declared in this "for" statement, if any.
+ /// Retrieve the variable declared in this "for" statement, if any.
///
/// In the following example, "y" is the condition variable.
/// \code
@@ -1284,7 +1302,7 @@ public:
GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
: Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
- /// \brief Build an empty goto statement.
+ /// Build an empty goto statement.
explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {}
LabelDecl *getLabel() const { return Label; }
@@ -1320,7 +1338,7 @@ public:
: Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
Target((Stmt*)target) {}
- /// \brief Build an empty indirect goto statement.
+ /// Build an empty indirect goto statement.
explicit IndirectGotoStmt(EmptyShell Empty)
: Stmt(IndirectGotoStmtClass, Empty) {}
@@ -1358,7 +1376,7 @@ class ContinueStmt : public Stmt {
public:
ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
- /// \brief Build an empty continue statement.
+ /// Build an empty continue statement.
explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {}
SourceLocation getContinueLoc() const { return ContinueLoc; }
@@ -1387,7 +1405,7 @@ public:
"BreakStmt too large");
}
- /// \brief Build an empty break statement.
+ /// Build an empty break statement.
explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {}
SourceLocation getBreakLoc() const { return BreakLoc; }
@@ -1426,7 +1444,7 @@ public:
: Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
NRVOCandidate(NRVOCandidate) {}
- /// \brief Build an empty return expression.
+ /// Build an empty return expression.
explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {}
const Expr *getRetValue() const;
@@ -1436,7 +1454,7 @@ public:
SourceLocation getReturnLoc() const { return RetLoc; }
void setReturnLoc(SourceLocation L) { RetLoc = L; }
- /// \brief Retrieve the variable that might be used for the named return
+ /// Retrieve the variable that might be used for the named return
/// value optimization.
///
/// The optimization itself can only be performed if the variable is
@@ -1468,11 +1486,11 @@ protected:
SourceLocation AsmLoc;
- /// \brief True if the assembly statement does not have any input or output
+ /// True if the assembly statement does not have any input or output
/// operands.
bool IsSimple;
- /// \brief If true, treat this inline assembly as having side effects.
+ /// If true, treat this inline assembly as having side effects.
/// This assembly statement should not be optimized, deleted or moved.
bool IsVolatile;
@@ -1489,7 +1507,7 @@ protected:
NumClobbers(numclobbers) {}
public:
- /// \brief Build an empty inline-assembly statement.
+ /// Build an empty inline-assembly statement.
explicit AsmStmt(StmtClass SC, EmptyShell Empty) : Stmt(SC, Empty) {}
SourceLocation getAsmLoc() const { return AsmLoc; }
@@ -1501,8 +1519,8 @@ public:
bool isVolatile() const { return IsVolatile; }
void setVolatile(bool V) { IsVolatile = V; }
- SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocStart() const LLVM_READONLY { return {}; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return {}; }
//===--- Asm String Analysis ---===//
@@ -1538,7 +1556,7 @@ public:
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
StringRef getInputConstraint(unsigned i) const;
-
+
const Expr *getInputExpr(unsigned i) const;
//===--- Other ---===//
@@ -1635,7 +1653,7 @@ public:
StringLiteral *asmstr, unsigned numclobbers,
StringLiteral **clobbers, SourceLocation rparenloc);
- /// \brief Build an empty inline-assembly statement.
+ /// Build an empty inline-assembly statement.
explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {}
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -1675,9 +1693,7 @@ public:
bool isString() const { return MyKind == String; }
bool isOperand() const { return MyKind == Operand; }
- const std::string &getString() const {
- return Str;
- }
+ const std::string &getString() const { return Str; }
unsigned getOperandNo() const {
assert(isOperand());
@@ -1707,15 +1723,13 @@ public:
//===--- Output operands ---===//
- IdentifierInfo *getOutputIdentifier(unsigned i) const {
- return Names[i];
- }
+ IdentifierInfo *getOutputIdentifier(unsigned i) const { return Names[i]; }
StringRef getOutputName(unsigned i) const {
if (IdentifierInfo *II = getOutputIdentifier(i))
return II->getName();
- return StringRef();
+ return {};
}
StringRef getOutputConstraint(unsigned i) const;
@@ -1743,7 +1757,7 @@ public:
if (IdentifierInfo *II = getInputIdentifier(i))
return II->getName();
- return StringRef();
+ return {};
}
StringRef getInputConstraint(unsigned i) const;
@@ -1816,7 +1830,7 @@ public:
ArrayRef<Expr*> exprs, StringRef asmstr,
ArrayRef<StringRef> clobbers, SourceLocation endloc);
- /// \brief Build an empty MS-style inline-assembly statement.
+ /// Build an empty MS-style inline-assembly statement.
explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty) {}
SourceLocation getLBraceLoc() const { return LBraceLoc; }
@@ -1930,7 +1944,7 @@ public:
}
child_range children() {
- return child_range(Children,Children+2);
+ return child_range(Children, Children+2);
}
static bool classof(const Stmt *T) {
@@ -2011,7 +2025,7 @@ public:
SEHFinallyStmt *getFinallyHandler() const;
child_range children() {
- return child_range(Children,Children+2);
+ return child_range(Children, Children+2);
}
static bool classof(const Stmt *T) {
@@ -2027,7 +2041,7 @@ public:
explicit SEHLeaveStmt(SourceLocation LL)
: Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {}
- /// \brief Build an empty __leave statement.
+ /// Build an empty __leave statement.
explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) {}
SourceLocation getLeaveLoc() const { return LeaveLoc; }
@@ -2046,7 +2060,7 @@ public:
}
};
-/// \brief This captures a statement into a function. For example, the following
+/// This captures a statement into a function. For example, the following
/// pragma annotated compound statement can be represented as a CapturedStmt,
/// and this compound statement is the body of an anonymous outlined function.
/// @code
@@ -2057,7 +2071,7 @@ public:
/// @endcode
class CapturedStmt : public Stmt {
public:
- /// \brief The different capture forms: by 'this', by reference, capture for
+ /// The different capture forms: by 'this', by reference, capture for
/// variable-length array type etc.
enum VariableCaptureKind {
VCK_This,
@@ -2066,7 +2080,7 @@ public:
VCK_VLAType,
};
- /// \brief Describes the capture of either a variable, or 'this', or
+ /// Describes the capture of either a variable, or 'this', or
/// variable-length array type.
class Capture {
llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind;
@@ -2075,7 +2089,7 @@ public:
public:
friend class ASTStmtReader;
- /// \brief Create a new capture.
+ /// Create a new capture.
///
/// \param Loc The source location associated with this capture.
///
@@ -2085,52 +2099,52 @@ public:
Capture(SourceLocation Loc, VariableCaptureKind Kind,
VarDecl *Var = nullptr);
- /// \brief Determine the kind of capture.
+ /// Determine the kind of capture.
VariableCaptureKind getCaptureKind() const;
- /// \brief Retrieve the source location at which the variable or 'this' was
+ /// Retrieve the source location at which the variable or 'this' was
/// first used.
SourceLocation getLocation() const { return Loc; }
- /// \brief Determine whether this capture handles the C++ 'this' pointer.
+ /// Determine whether this capture handles the C++ 'this' pointer.
bool capturesThis() const { return getCaptureKind() == VCK_This; }
- /// \brief Determine whether this capture handles a variable (by reference).
+ /// Determine whether this capture handles a variable (by reference).
bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
- /// \brief Determine whether this capture handles a variable by copy.
+ /// Determine whether this capture handles a variable by copy.
bool capturesVariableByCopy() const {
return getCaptureKind() == VCK_ByCopy;
}
- /// \brief Determine whether this capture handles a variable-length array
+ /// Determine whether this capture handles a variable-length array
/// type.
bool capturesVariableArrayType() const {
return getCaptureKind() == VCK_VLAType;
}
- /// \brief Retrieve the declaration of the variable being captured.
+ /// Retrieve the declaration of the variable being captured.
///
/// This operation is only valid if this capture captures a variable.
VarDecl *getCapturedVar() const;
};
private:
- /// \brief The number of variable captured, including 'this'.
+ /// The number of variable captured, including 'this'.
unsigned NumCaptures;
- /// \brief The pointer part is the implicit the outlined function and the
+ /// The pointer part is the implicit the outlined function and the
/// int part is the captured region kind, 'CR_Default' etc.
- llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind;
+ llvm::PointerIntPair<CapturedDecl *, 2, CapturedRegionKind> CapDeclAndKind;
- /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl.
+ /// The record for captured variables, a RecordDecl or CXXRecordDecl.
RecordDecl *TheRecordDecl = nullptr;
- /// \brief Construct a captured statement.
+ /// Construct a captured statement.
CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures,
ArrayRef<Expr *> CaptureInits, CapturedDecl *CD, RecordDecl *RD);
- /// \brief Construct an empty captured statement.
+ /// Construct an empty captured statement.
CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
@@ -2155,36 +2169,36 @@ public:
static CapturedStmt *CreateDeserialized(const ASTContext &Context,
unsigned NumCaptures);
- /// \brief Retrieve the statement being captured.
+ /// Retrieve the statement being captured.
Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; }
const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; }
- /// \brief Retrieve the outlined function declaration.
+ /// Retrieve the outlined function declaration.
CapturedDecl *getCapturedDecl();
const CapturedDecl *getCapturedDecl() const;
- /// \brief Set the outlined function declaration.
+ /// Set the outlined function declaration.
void setCapturedDecl(CapturedDecl *D);
- /// \brief Retrieve the captured region kind.
+ /// Retrieve the captured region kind.
CapturedRegionKind getCapturedRegionKind() const;
- /// \brief Set the captured region kind.
+ /// Set the captured region kind.
void setCapturedRegionKind(CapturedRegionKind Kind);
- /// \brief Retrieve the record declaration for captured variables.
+ /// Retrieve the record declaration for captured variables.
const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
- /// \brief Set the record declaration for captured variables.
+ /// Set the record declaration for captured variables.
void setCapturedRecordDecl(RecordDecl *D) {
assert(D && "null RecordDecl");
TheRecordDecl = D;
}
- /// \brief True if this variable has been captured.
+ /// True if this variable has been captured.
bool capturesVariable(const VarDecl *Var) const;
- /// \brief An iterator that walks over the captures.
+ /// An iterator that walks over the captures.
using capture_iterator = Capture *;
using const_capture_iterator = const Capture *;
using capture_range = llvm::iterator_range<capture_iterator>;
@@ -2197,24 +2211,24 @@ public:
return capture_const_range(capture_begin(), capture_end());
}
- /// \brief Retrieve an iterator pointing to the first capture.
+ /// Retrieve an iterator pointing to the first capture.
capture_iterator capture_begin() { return getStoredCaptures(); }
const_capture_iterator capture_begin() const { return getStoredCaptures(); }
- /// \brief Retrieve an iterator pointing past the end of the sequence of
+ /// Retrieve an iterator pointing past the end of the sequence of
/// captures.
capture_iterator capture_end() const {
return getStoredCaptures() + NumCaptures;
}
- /// \brief Retrieve the number of captures, including 'this'.
+ /// Retrieve the number of captures, including 'this'.
unsigned capture_size() const { return NumCaptures; }
- /// \brief Iterator that walks over the capture initialization arguments.
+ /// Iterator that walks over the capture initialization arguments.
using capture_init_iterator = Expr **;
using capture_init_range = llvm::iterator_range<capture_init_iterator>;
- /// \brief Const iterator that walks over the capture initialization
+ /// Const iterator that walks over the capture initialization
/// arguments.
using const_capture_init_iterator = Expr *const *;
using const_capture_init_range =
@@ -2228,7 +2242,7 @@ public:
return const_capture_init_range(capture_init_begin(), capture_init_end());
}
- /// \brief Retrieve the first initialization argument.
+ /// Retrieve the first initialization argument.
capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
@@ -2237,7 +2251,7 @@ public:
return reinterpret_cast<Expr *const *>(getStoredStmts());
}
- /// \brief Retrieve the iterator pointing one past the last initialization
+ /// Retrieve the iterator pointing one past the last initialization
/// argument.
capture_init_iterator capture_init_end() {
return capture_init_begin() + NumCaptures;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
index 77f81838e5eb..34553741eb38 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
@@ -62,21 +62,22 @@ public:
/// CXXTryStmt - A C++ try block, including all handlers.
///
-class CXXTryStmt : public Stmt {
+class CXXTryStmt final : public Stmt,
+ private llvm::TrailingObjects<CXXTryStmt, Stmt *> {
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+
SourceLocation TryLoc;
unsigned NumHandlers;
+ size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; }
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers);
-
CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
: Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
- Stmt const * const *getStmts() const {
- return reinterpret_cast<Stmt const * const*>(this + 1);
- }
- Stmt **getStmts() {
- return reinterpret_cast<Stmt **>(this + 1);
- }
+ Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); }
+ Stmt **getStmts() { return getTrailingObjects<Stmt *>(); }
public:
static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc,
@@ -115,8 +116,6 @@ public:
child_range children() {
return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
}
-
- friend class ASTStmtReader;
};
/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
@@ -210,7 +209,7 @@ public:
}
};
-/// \brief Representation of a Microsoft __if_exists or __if_not_exists
+/// Representation of a Microsoft __if_exists or __if_not_exists
/// statement with a dependent name.
///
/// The __if_exists statement can be used to include a sequence of statements
@@ -257,25 +256,25 @@ public:
QualifierLoc(QualifierLoc), NameInfo(NameInfo),
SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
- /// \brief Retrieve the location of the __if_exists or __if_not_exists
+ /// Retrieve the location of the __if_exists or __if_not_exists
/// keyword.
SourceLocation getKeywordLoc() const { return KeywordLoc; }
- /// \brief Determine whether this is an __if_exists statement.
+ /// Determine whether this is an __if_exists statement.
bool isIfExists() const { return IsIfExists; }
- /// \brief Determine whether this is an __if_exists statement.
+ /// Determine whether this is an __if_exists statement.
bool isIfNotExists() const { return !IsIfExists; }
- /// \brief Retrieve the nested-name-specifier that qualifies this name, if
+ /// Retrieve the nested-name-specifier that qualifies this name, if
/// any.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- /// \brief Retrieve the name of the entity we're testing for, along with
+ /// Retrieve the name of the entity we're testing for, along with
/// location information
DeclarationNameInfo getNameInfo() const { return NameInfo; }
- /// \brief Retrieve the compound statement that will be included in the
+ /// Retrieve the compound statement that will be included in the
/// program only if the existence of the symbol matches the initial keyword.
CompoundStmt *getSubStmt() const {
return reinterpret_cast<CompoundStmt *>(SubStmt);
@@ -293,7 +292,7 @@ public:
}
};
-/// \brief Represents the body of a coroutine. This wraps the normal function
+/// Represents the body of a coroutine. This wraps the normal function
/// body and holds the additional semantic context required to set up and tear
/// down the coroutine frame.
class CoroutineBodyStmt final
@@ -355,7 +354,7 @@ public:
return getPromiseDecl()->getType()->isDependentType();
}
- /// \brief Retrieve the body of the coroutine as written. This will be either
+ /// Retrieve the body of the coroutine as written. This will be either
/// a CompoundStmt or a TryStmt.
Stmt *getBody() const {
return getStoredStmts()[SubStmt::Body];
@@ -418,7 +417,7 @@ public:
}
};
-/// \brief Represents a 'co_return' statement in the C++ Coroutines TS.
+/// Represents a 'co_return' statement in the C++ Coroutines TS.
///
/// This statament models the initialization of the coroutine promise
/// (encapsulating the eventual notional return value) from an expression
@@ -451,11 +450,11 @@ public:
SourceLocation getKeywordLoc() const { return CoreturnLoc; }
- /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr
+ /// Retrieve the operand of the 'co_return' statement. Will be nullptr
/// if none was specified.
Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
- /// \brief Retrieve the promise call that results from this 'co_return'
+ /// Retrieve the promise call that results from this 'co_return'
/// statement. Will be nullptr if either the coroutine has not yet been
/// finalized or the coroutine has no eventual return type.
Expr *getPromiseCall() const {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
index 33aab08bbb71..806edaa38821 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
@@ -33,14 +33,14 @@ protected:
DeclGroupMode = 0x2,
Flags = 0x3
};
-
+
union {
Stmt **stmt;
Decl **DGI;
};
uintptr_t RawVAPtr = 0;
Decl **DGE;
-
+
StmtIteratorBase(Stmt **s) : stmt(s) {}
StmtIteratorBase(const VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h
index 5260b6985bf5..0b2cc78b65be 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
/// \file
-/// \brief Defines the Objective-C statement AST node classes.
+/// Defines the Objective-C statement AST node classes.
#ifndef LLVM_CLANG_AST_STMTOBJC_H
#define LLVM_CLANG_AST_STMTOBJC_H
@@ -18,7 +18,7 @@
namespace clang {
-/// \brief Represents Objective-C's collection statement.
+/// Represents Objective-C's collection statement.
///
/// This is represented as 'for (element 'in' collection-expression)' stmt.
class ObjCForCollectionStmt : public Stmt {
@@ -70,7 +70,7 @@ public:
}
};
-/// \brief Represents Objective-C's \@catch statement.
+/// Represents Objective-C's \@catch statement.
class ObjCAtCatchStmt : public Stmt {
private:
VarDecl *ExceptionDecl;
@@ -81,7 +81,7 @@ public:
ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
VarDecl *catchVarDecl,
Stmt *atCatchStmt)
- : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl),
+ : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl),
Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { }
explicit ObjCAtCatchStmt(EmptyShell Empty) :
@@ -116,7 +116,7 @@ public:
child_range children() { return child_range(&Body, &Body + 1); }
};
-/// \brief Represents Objective-C's \@finally statement
+/// Represents Objective-C's \@finally statement
class ObjCAtFinallyStmt : public Stmt {
SourceLocation AtFinallyLoc;
Stmt *AtFinallyStmt;
@@ -150,32 +150,32 @@ public:
}
};
-/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement.
+/// Represents Objective-C's \@try ... \@catch ... \@finally statement.
class ObjCAtTryStmt : public Stmt {
private:
// The location of the @ in the \@try.
SourceLocation AtTryLoc;
-
+
// The number of catch blocks in this statement.
unsigned NumCatchStmts : 16;
-
+
// Whether this statement has a \@finally statement.
bool HasFinally : 1;
-
- /// \brief Retrieve the statements that are stored after this \@try statement.
+
+ /// Retrieve the statements that are stored after this \@try statement.
///
/// The order of the statements in memory follows the order in the source,
/// with the \@try body first, followed by the \@catch statements (if any)
/// and, finally, the \@finally (if it exists).
Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); }
- const Stmt* const *getStmts() const {
- return reinterpret_cast<const Stmt * const*> (this + 1);
+ const Stmt* const *getStmts() const {
+ return reinterpret_cast<const Stmt * const*> (this + 1);
}
-
+
ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
Stmt **CatchStmts, unsigned NumCatchStmts,
Stmt *atFinallyStmt);
-
+
explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts,
bool HasFinally)
: Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts),
@@ -188,54 +188,54 @@ public:
Stmt *atFinallyStmt);
static ObjCAtTryStmt *CreateEmpty(const ASTContext &Context,
unsigned NumCatchStmts, bool HasFinally);
-
- /// \brief Retrieve the location of the @ in the \@try.
+
+ /// Retrieve the location of the @ in the \@try.
SourceLocation getAtTryLoc() const { return AtTryLoc; }
void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
- /// \brief Retrieve the \@try body.
+ /// Retrieve the \@try body.
const Stmt *getTryBody() const { return getStmts()[0]; }
Stmt *getTryBody() { return getStmts()[0]; }
void setTryBody(Stmt *S) { getStmts()[0] = S; }
- /// \brief Retrieve the number of \@catch statements in this try-catch-finally
+ /// Retrieve the number of \@catch statements in this try-catch-finally
/// block.
unsigned getNumCatchStmts() const { return NumCatchStmts; }
-
- /// \brief Retrieve a \@catch statement.
+
+ /// Retrieve a \@catch statement.
const ObjCAtCatchStmt *getCatchStmt(unsigned I) const {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
}
-
- /// \brief Retrieve a \@catch statement.
+
+ /// Retrieve a \@catch statement.
ObjCAtCatchStmt *getCatchStmt(unsigned I) {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
}
-
- /// \brief Set a particular catch statement.
+
+ /// Set a particular catch statement.
void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
getStmts()[I + 1] = S;
}
-
- /// \brief Retrieve the \@finally statement, if any.
+
+ /// Retrieve the \@finally statement, if any.
const ObjCAtFinallyStmt *getFinallyStmt() const {
if (!HasFinally)
return nullptr;
-
+
return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
}
ObjCAtFinallyStmt *getFinallyStmt() {
if (!HasFinally)
return nullptr;
-
+
return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
}
- void setFinallyStmt(Stmt *S) {
+ void setFinallyStmt(Stmt *S) {
assert(HasFinally && "@try does not have a @finally slot!");
- getStmts()[1 + NumCatchStmts] = S;
+ getStmts()[1 + NumCatchStmts] = S;
}
SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; }
@@ -251,7 +251,7 @@ public:
}
};
-/// \brief Represents Objective-C's \@synchronized statement.
+/// Represents Objective-C's \@synchronized statement.
///
/// Example:
/// \code
@@ -309,7 +309,7 @@ public:
}
};
-/// \brief Represents Objective-C's \@throw statement.
+/// Represents Objective-C's \@throw statement.
class ObjCAtThrowStmt : public Stmt {
SourceLocation AtThrowLoc;
Stmt *Throw;
@@ -341,7 +341,7 @@ public:
child_range children() { return child_range(&Throw, &Throw+1); }
};
-/// \brief Represents Objective-C's \@autoreleasepool Statement
+/// Represents Objective-C's \@autoreleasepool Statement
class ObjCAutoreleasePoolStmt : public Stmt {
SourceLocation AtLoc;
Stmt *SubStmt;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
index b6fd1a2c28cb..d23375e7606b 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file defines OpenMP AST classes for executable directives and
+/// This file defines OpenMP AST classes for executable directives and
/// clauses.
///
//===----------------------------------------------------------------------===//
@@ -27,28 +27,28 @@ namespace clang {
// AST classes for directives.
//===----------------------------------------------------------------------===//
-/// \brief This is a basic class for representing single OpenMP executable
+/// This is a basic class for representing single OpenMP executable
/// directive.
///
class OMPExecutableDirective : public Stmt {
friend class ASTStmtReader;
- /// \brief Kind of the directive.
+ /// Kind of the directive.
OpenMPDirectiveKind Kind;
- /// \brief Starting location of the directive (directive keyword).
+ /// Starting location of the directive (directive keyword).
SourceLocation StartLoc;
- /// \brief Ending location of the directive.
+ /// Ending location of the directive.
SourceLocation EndLoc;
- /// \brief Numbers of clauses.
+ /// Numbers of clauses.
const unsigned NumClauses;
- /// \brief Number of child expressions/stmts.
+ /// Number of child expressions/stmts.
const unsigned NumChildren;
- /// \brief Offset from this to the start of clauses.
+ /// Offset from this to the start of clauses.
/// There are NumClauses pointers to clauses, they are followed by
/// NumChildren pointers to child stmts/exprs (if the directive type
/// requires an associated stmt, then it has to be the first of them).
const unsigned ClausesOffset;
- /// \brief Get the clauses storage.
+ /// Get the clauses storage.
MutableArrayRef<OMPClause *> getClauses() {
OMPClause **ClauseStorage = reinterpret_cast<OMPClause **>(
reinterpret_cast<char *>(this) + ClausesOffset);
@@ -56,7 +56,7 @@ class OMPExecutableDirective : public Stmt {
}
protected:
- /// \brief Build instance of directive of class \a K.
+ /// Build instance of directive of class \a K.
///
/// \param SC Statement class.
/// \param K Kind of OpenMP directive.
@@ -72,13 +72,13 @@ protected:
NumChildren(NumChildren),
ClausesOffset(llvm::alignTo(sizeof(T), alignof(OMPClause *))) {}
- /// \brief Sets the list of variables for this clause.
+ /// Sets the list of variables for this clause.
///
/// \param Clauses The list of clauses for the directive.
///
void setClauses(ArrayRef<OMPClause *> Clauses);
- /// \brief Set the associated statement for the directive.
+ /// Set the associated statement for the directive.
///
/// /param S Associated statement.
///
@@ -88,7 +88,7 @@ protected:
}
public:
- /// \brief Iterates over a filtered subrange of clauses applied to a
+ /// Iterates over a filtered subrange of clauses applied to a
/// directive.
///
/// This iterator visits only clauses of type SpecificClause.
@@ -164,35 +164,35 @@ public:
return Clauses.begin() != Clauses.end();
}
- /// \brief Returns starting location of directive kind.
+ /// Returns starting location of directive kind.
SourceLocation getLocStart() const { return StartLoc; }
- /// \brief Returns ending location of directive.
+ /// Returns ending location of directive.
SourceLocation getLocEnd() const { return EndLoc; }
- /// \brief Set starting location of directive kind.
+ /// Set starting location of directive kind.
///
/// \param Loc New starting location of directive.
///
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
- /// \brief Set ending location of directive.
+ /// Set ending location of directive.
///
/// \param Loc New ending location of directive.
///
void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
- /// \brief Get number of clauses.
+ /// Get number of clauses.
unsigned getNumClauses() const { return NumClauses; }
- /// \brief Returns specified clause.
+ /// Returns specified clause.
///
/// \param i Number of clause.
///
OMPClause *getClause(unsigned i) const { return clauses()[i]; }
- /// \brief Returns true if directive has associated statement.
+ /// Returns true if directive has associated statement.
bool hasAssociatedStmt() const { return NumChildren > 0; }
- /// \brief Returns statement associated with the directive.
+ /// Returns statement associated with the directive.
const Stmt *getAssociatedStmt() const {
assert(hasAssociatedStmt() && "no associated statement.");
return *child_begin();
@@ -202,7 +202,7 @@ public:
return *child_begin();
}
- /// \brief Returns the captured statement associated with the
+ /// Returns the captured statement associated with the
/// component region within the (combined) directive.
//
// \param RegionKind Component region kind.
@@ -222,6 +222,25 @@ public:
llvm_unreachable("Incorrect RegionKind specified for directive.");
}
+ /// Get innermost captured statement for the construct.
+ CapturedStmt *getInnermostCapturedStmt() {
+ assert(hasAssociatedStmt() && getAssociatedStmt() &&
+ "Must have associated statement.");
+ SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+ getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
+ assert(!CaptureRegions.empty() &&
+ "At least one captured statement must be provided.");
+ auto *CS = cast<CapturedStmt>(getAssociatedStmt());
+ for (unsigned Level = CaptureRegions.size(); Level > 1; --Level)
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ return CS;
+ }
+
+ const CapturedStmt *getInnermostCapturedStmt() const {
+ return const_cast<OMPExecutableDirective *>(this)
+ ->getInnermostCapturedStmt();
+ }
+
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
static bool classof(const Stmt *S) {
@@ -233,7 +252,9 @@ public:
if (!hasAssociatedStmt())
return child_range(child_iterator(), child_iterator());
Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
- return child_range(ChildStorage, ChildStorage + NumChildren);
+ /// Do not mark all the special expression/statements as children, except
+ /// for the associated statement.
+ return child_range(ChildStorage, ChildStorage + 1);
}
ArrayRef<OMPClause *> clauses() { return getClauses(); }
@@ -243,7 +264,7 @@ public:
}
};
-/// \brief This represents '#pragma omp parallel' directive.
+/// This represents '#pragma omp parallel' directive.
///
/// \code
/// #pragma omp parallel private(a,b) reduction(+: c,d)
@@ -254,10 +275,10 @@ public:
///
class OMPParallelDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief true if the construct has inner cancel directive.
+ /// true if the construct has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive (directive keyword).
/// \param EndLoc Ending Location of the directive.
@@ -268,7 +289,7 @@ class OMPParallelDirective : public OMPExecutableDirective {
StartLoc, EndLoc, NumClauses, 1),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -278,11 +299,11 @@ class OMPParallelDirective : public OMPExecutableDirective {
1),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -295,7 +316,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
- /// \brief Creates an empty directive with the place for \a N clauses.
+ /// Creates an empty directive with the place for \a N clauses.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
@@ -303,7 +324,7 @@ public:
static OMPParallelDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -311,15 +332,15 @@ public:
}
};
-/// \brief This is a common base class for loop directives ('omp simd', 'omp
+/// This is a common base class for loop directives ('omp simd', 'omp
/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
///
class OMPLoopDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Number of collapsed loops as specified by 'collapse' clause.
+ /// Number of collapsed loops as specified by 'collapse' clause.
unsigned CollapsedNum;
- /// \brief Offsets to the stored exprs.
+ /// Offsets to the stored exprs.
/// This enumeration contains offsets to all the pointers to children
/// expressions stored in OMPLoopDirective.
/// The first 9 children are necessary for all the loop directives,
@@ -376,21 +397,21 @@ class OMPLoopDirective : public OMPExecutableDirective {
CombinedDistributeEnd = 28,
};
- /// \brief Get the counters storage.
+ /// Get the counters storage.
MutableArrayRef<Expr *> getCounters() {
Expr **Storage = reinterpret_cast<Expr **>(
&(*(std::next(child_begin(), getArraysOffset(getDirectiveKind())))));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
- /// \brief Get the private counters storage.
+ /// Get the private counters storage.
MutableArrayRef<Expr *> getPrivateCounters() {
Expr **Storage = reinterpret_cast<Expr **>(&*std::next(
child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
- /// \brief Get the updates storage.
+ /// Get the updates storage.
MutableArrayRef<Expr *> getInits() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
@@ -398,7 +419,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
- /// \brief Get the updates storage.
+ /// Get the updates storage.
MutableArrayRef<Expr *> getUpdates() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
@@ -406,7 +427,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
- /// \brief Get the final counter updates storage.
+ /// Get the final counter updates storage.
MutableArrayRef<Expr *> getFinals() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
@@ -415,7 +436,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
}
protected:
- /// \brief Build instance of loop directive of class \a Kind.
+ /// Build instance of loop directive of class \a Kind.
///
/// \param SC Statement class.
/// \param Kind Kind of OpenMP directive.
@@ -435,7 +456,7 @@ protected:
NumSpecialChildren),
CollapsedNum(CollapsedNum) {}
- /// \brief Offset to the start of children expression arrays.
+ /// Offset to the start of children expression arrays.
static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
if (isOpenMPLoopBoundSharingDirective(Kind))
return CombinedDistributeEnd;
@@ -445,7 +466,7 @@ protected:
return DefaultEnd;
}
- /// \brief Children number.
+ /// Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
@@ -610,72 +631,72 @@ public:
/// Distribute Loop condition used when composing 'omp distribute'
/// with 'omp for' in a same construct
Expr *Cond;
- /// Update of LowerBound for statically sheduled omp loops for
+ /// Update of LowerBound for statically scheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NLB;
- /// Update of UpperBound for statically sheduled omp loops for
+ /// Update of UpperBound for statically scheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NUB;
};
- /// \brief The expressions built for the OpenMP loop CodeGen for the
+ /// The expressions built for the OpenMP loop CodeGen for the
/// whole collapsed loop nest.
struct HelperExprs {
- /// \brief Loop iteration variable.
+ /// Loop iteration variable.
Expr *IterationVarRef;
- /// \brief Loop last iteration number.
+ /// Loop last iteration number.
Expr *LastIteration;
- /// \brief Loop number of iterations.
+ /// Loop number of iterations.
Expr *NumIterations;
- /// \brief Calculation of last iteration.
+ /// Calculation of last iteration.
Expr *CalcLastIteration;
- /// \brief Loop pre-condition.
+ /// Loop pre-condition.
Expr *PreCond;
- /// \brief Loop condition.
+ /// Loop condition.
Expr *Cond;
- /// \brief Loop iteration variable init.
+ /// Loop iteration variable init.
Expr *Init;
- /// \brief Loop increment.
+ /// Loop increment.
Expr *Inc;
- /// \brief IsLastIteration - local flag variable passed to runtime.
+ /// IsLastIteration - local flag variable passed to runtime.
Expr *IL;
- /// \brief LowerBound - local variable passed to runtime.
+ /// LowerBound - local variable passed to runtime.
Expr *LB;
- /// \brief UpperBound - local variable passed to runtime.
+ /// UpperBound - local variable passed to runtime.
Expr *UB;
- /// \brief Stride - local variable passed to runtime.
+ /// Stride - local variable passed to runtime.
Expr *ST;
- /// \brief EnsureUpperBound -- expression UB = min(UB, NumIterations).
+ /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
Expr *EUB;
- /// \brief Update of LowerBound for statically sheduled 'omp for' loops.
+ /// Update of LowerBound for statically scheduled 'omp for' loops.
Expr *NLB;
- /// \brief Update of UpperBound for statically sheduled 'omp for' loops.
+ /// Update of UpperBound for statically scheduled 'omp for' loops.
Expr *NUB;
- /// \brief PreviousLowerBound - local variable passed to runtime in the
+ /// PreviousLowerBound - local variable passed to runtime in the
/// enclosing schedule or null if that does not apply.
Expr *PrevLB;
- /// \brief PreviousUpperBound - local variable passed to runtime in the
+ /// PreviousUpperBound - local variable passed to runtime in the
/// enclosing schedule or null if that does not apply.
Expr *PrevUB;
- /// \brief DistInc - increment expression for distribute loop when found
+ /// DistInc - increment expression for distribute loop when found
/// combined with a further loop level (e.g. in 'distribute parallel for')
/// expression IV = IV + ST
Expr *DistInc;
- /// \brief PrevEUB - expression similar to EUB but to be used when loop
+ /// PrevEUB - expression similar to EUB but to be used when loop
/// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for'
/// when ensuring that the UB is either the calculated UB by the runtime or
/// the end of the assigned distribute chunk)
/// expression UB = min (UB, PrevUB)
Expr *PrevEUB;
- /// \brief Counters Loop counters.
+ /// Counters Loop counters.
SmallVector<Expr *, 4> Counters;
- /// \brief PrivateCounters Loop counters.
+ /// PrivateCounters Loop counters.
SmallVector<Expr *, 4> PrivateCounters;
- /// \brief Expressions for loop counters inits for CodeGen.
+ /// Expressions for loop counters inits for CodeGen.
SmallVector<Expr *, 4> Inits;
- /// \brief Expressions for loop counters update for CodeGen.
+ /// Expressions for loop counters update for CodeGen.
SmallVector<Expr *, 4> Updates;
- /// \brief Final loop counter values for GodeGen.
+ /// Final loop counter values for GodeGen.
SmallVector<Expr *, 4> Finals;
/// Init statement for all captured expressions.
Stmt *PreInits;
@@ -683,7 +704,7 @@ public:
/// Expressions used when combining OpenMP loop pragmas
DistCombinedHelperExprs DistCombinedFields;
- /// \brief Check if all the expressions are built (does not check the
+ /// Check if all the expressions are built (does not check the
/// worksharing ones).
bool builtAll() {
return IterationVarRef != nullptr && LastIteration != nullptr &&
@@ -691,7 +712,7 @@ public:
Cond != nullptr && Init != nullptr && Inc != nullptr;
}
- /// \brief Initialize all the fields to null.
+ /// Initialize all the fields to null.
/// \param Size Number of elements in the counters/finals/updates arrays.
void clear(unsigned Size) {
IterationVarRef = nullptr;
@@ -736,7 +757,7 @@ public:
}
};
- /// \brief Get number of collapsed loops.
+ /// Get number of collapsed loops.
unsigned getCollapsedNumber() const { return CollapsedNum; }
Expr *getIterationVariable() const {
@@ -903,9 +924,8 @@ public:
}
const Stmt *getBody() const {
// This relies on the loop form is already checked by Sema.
- const Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
- while(const auto *CS = dyn_cast<CapturedStmt>(Body))
- Body = CS->getCapturedStmt();
+ const Stmt *Body =
+ getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
Body = cast<ForStmt>(Body)->getBody();
for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
Body = Body->IgnoreContainers();
@@ -973,7 +993,7 @@ public:
}
};
-/// \brief This represents '#pragma omp simd' directive.
+/// This represents '#pragma omp simd' directive.
///
/// \code
/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
@@ -984,7 +1004,7 @@ public:
///
class OMPSimdDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -996,7 +1016,7 @@ class OMPSimdDirective : public OMPLoopDirective {
: OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
EndLoc, CollapsedNum, NumClauses) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -1007,7 +1027,7 @@ class OMPSimdDirective : public OMPLoopDirective {
NumClauses) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1023,7 +1043,7 @@ public:
Stmt *AssociatedStmt,
const HelperExprs &Exprs);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -1038,7 +1058,7 @@ public:
}
};
-/// \brief This represents '#pragma omp for' directive.
+/// This represents '#pragma omp for' directive.
///
/// \code
/// #pragma omp for private(a,b) reduction(+:c,d)
@@ -1050,10 +1070,10 @@ public:
class OMPForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief true if current directive has inner cancel directive.
+ /// true if current directive has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1066,7 +1086,7 @@ class OMPForDirective : public OMPLoopDirective {
CollapsedNum, NumClauses),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -1076,11 +1096,11 @@ class OMPForDirective : public OMPLoopDirective {
SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1097,7 +1117,7 @@ public:
Stmt *AssociatedStmt, const HelperExprs &Exprs,
bool HasCancel);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -1107,7 +1127,7 @@ public:
static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -1115,7 +1135,7 @@ public:
}
};
-/// \brief This represents '#pragma omp for simd' directive.
+/// This represents '#pragma omp for simd' directive.
///
/// \code
/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
@@ -1126,7 +1146,7 @@ public:
///
class OMPForSimdDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1138,7 +1158,7 @@ class OMPForSimdDirective : public OMPLoopDirective {
: OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
StartLoc, EndLoc, CollapsedNum, NumClauses) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -1149,7 +1169,7 @@ class OMPForSimdDirective : public OMPLoopDirective {
NumClauses) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1164,7 +1184,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -1180,7 +1200,7 @@ public:
}
};
-/// \brief This represents '#pragma omp sections' directive.
+/// This represents '#pragma omp sections' directive.
///
/// \code
/// #pragma omp sections private(a,b) reduction(+:c,d)
@@ -1192,10 +1212,10 @@ public:
class OMPSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief true if current directive has inner cancel directive.
+ /// true if current directive has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1207,7 +1227,7 @@ class OMPSectionsDirective : public OMPExecutableDirective {
StartLoc, EndLoc, NumClauses, 1),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -1217,11 +1237,11 @@ class OMPSectionsDirective : public OMPExecutableDirective {
1),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1234,7 +1254,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -1243,7 +1263,7 @@ public:
static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -1251,7 +1271,7 @@ public:
}
};
-/// \brief This represents '#pragma omp section' directive.
+/// This represents '#pragma omp section' directive.
///
/// \code
/// #pragma omp section
@@ -1260,10 +1280,10 @@ public:
class OMPSectionDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief true if current directive has inner cancel directive.
+ /// true if current directive has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1273,7 +1293,7 @@ class OMPSectionDirective : public OMPExecutableDirective {
StartLoc, EndLoc, 0, 1),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
explicit OMPSectionDirective()
: OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
@@ -1281,7 +1301,7 @@ class OMPSectionDirective : public OMPExecutableDirective {
HasCancel(false) {}
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1294,16 +1314,16 @@ public:
SourceLocation EndLoc,
Stmt *AssociatedStmt, bool HasCancel);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -1311,7 +1331,7 @@ public:
}
};
-/// \brief This represents '#pragma omp single' directive.
+/// This represents '#pragma omp single' directive.
///
/// \code
/// #pragma omp single private(a,b) copyprivate(c,d)
@@ -1321,7 +1341,7 @@ public:
///
class OMPSingleDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1332,7 +1352,7 @@ class OMPSingleDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single,
StartLoc, EndLoc, NumClauses, 1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -1342,7 +1362,7 @@ class OMPSingleDirective : public OMPExecutableDirective {
1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1354,7 +1374,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -1368,7 +1388,7 @@ public:
}
};
-/// \brief This represents '#pragma omp master' directive.
+/// This represents '#pragma omp master' directive.
///
/// \code
/// #pragma omp master
@@ -1376,7 +1396,7 @@ public:
///
class OMPMasterDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1385,14 +1405,14 @@ class OMPMasterDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master,
StartLoc, EndLoc, 0, 1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
explicit OMPMasterDirective()
: OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master,
SourceLocation(), SourceLocation(), 0, 1) {}
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1404,7 +1424,7 @@ public:
SourceLocation EndLoc,
Stmt *AssociatedStmt);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
@@ -1415,7 +1435,7 @@ public:
}
};
-/// \brief This represents '#pragma omp critical' directive.
+/// This represents '#pragma omp critical' directive.
///
/// \code
/// #pragma omp critical
@@ -1423,9 +1443,9 @@ public:
///
class OMPCriticalDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Name of the directive.
+ /// Name of the directive.
DeclarationNameInfo DirName;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
@@ -1438,7 +1458,7 @@ class OMPCriticalDirective : public OMPExecutableDirective {
StartLoc, EndLoc, NumClauses, 1),
DirName(Name) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -1448,14 +1468,14 @@ class OMPCriticalDirective : public OMPExecutableDirective {
1),
DirName() {}
- /// \brief Set name of the directive.
+ /// Set name of the directive.
///
/// \param Name Name of the directive.
///
void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param Name Name of the directive.
@@ -1469,7 +1489,7 @@ public:
SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
@@ -1477,7 +1497,7 @@ public:
static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
- /// \brief Return name of the directive.
+ /// Return name of the directive.
///
DeclarationNameInfo getDirectiveName() const { return DirName; }
@@ -1486,7 +1506,7 @@ public:
}
};
-/// \brief This represents '#pragma omp parallel for' directive.
+/// This represents '#pragma omp parallel for' directive.
///
/// \code
/// #pragma omp parallel for private(a,b) reduction(+:c,d)
@@ -1498,10 +1518,10 @@ public:
class OMPParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief true if current region has inner cancel directive.
+ /// true if current region has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1514,7 +1534,7 @@ class OMPParallelForDirective : public OMPLoopDirective {
StartLoc, EndLoc, CollapsedNum, NumClauses),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -1525,11 +1545,11 @@ class OMPParallelForDirective : public OMPLoopDirective {
NumClauses),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1545,7 +1565,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -1557,7 +1577,7 @@ public:
unsigned CollapsedNum,
EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -1565,7 +1585,7 @@ public:
}
};
-/// \brief This represents '#pragma omp parallel for simd' directive.
+/// This represents '#pragma omp parallel for simd' directive.
///
/// \code
/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
@@ -1577,7 +1597,7 @@ public:
///
class OMPParallelForSimdDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1590,7 +1610,7 @@ class OMPParallelForSimdDirective : public OMPLoopDirective {
OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum,
NumClauses) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -1602,7 +1622,7 @@ class OMPParallelForSimdDirective : public OMPLoopDirective {
SourceLocation(), CollapsedNum, NumClauses) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1617,7 +1637,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -1634,7 +1654,7 @@ public:
}
};
-/// \brief This represents '#pragma omp parallel sections' directive.
+/// This represents '#pragma omp parallel sections' directive.
///
/// \code
/// #pragma omp parallel sections private(a,b) reduction(+:c,d)
@@ -1646,10 +1666,10 @@ public:
class OMPParallelSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief true if current directive has inner cancel directive.
+ /// true if current directive has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1662,7 +1682,7 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
NumClauses, 1),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -1672,11 +1692,11 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
SourceLocation(), NumClauses, 1),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1689,7 +1709,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -1698,7 +1718,7 @@ public:
static OMPParallelSectionsDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -1706,7 +1726,7 @@ public:
}
};
-/// \brief This represents '#pragma omp task' directive.
+/// This represents '#pragma omp task' directive.
///
/// \code
/// #pragma omp task private(a,b) final(d)
@@ -1716,10 +1736,10 @@ public:
///
class OMPTaskDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief true if this directive has inner cancel directive.
+ /// true if this directive has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1731,7 +1751,7 @@ class OMPTaskDirective : public OMPExecutableDirective {
EndLoc, NumClauses, 1),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -1741,11 +1761,11 @@ class OMPTaskDirective : public OMPExecutableDirective {
1),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1759,7 +1779,7 @@ public:
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, bool HasCancel);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -1768,7 +1788,7 @@ public:
static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -1776,7 +1796,7 @@ public:
}
};
-/// \brief This represents '#pragma omp taskyield' directive.
+/// This represents '#pragma omp taskyield' directive.
///
/// \code
/// #pragma omp taskyield
@@ -1784,7 +1804,7 @@ public:
///
class OMPTaskyieldDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1793,14 +1813,14 @@ class OMPTaskyieldDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
StartLoc, EndLoc, 0, 0) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
explicit OMPTaskyieldDirective()
: OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
SourceLocation(), SourceLocation(), 0, 0) {}
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1809,7 +1829,7 @@ public:
static OMPTaskyieldDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
@@ -1820,7 +1840,7 @@ public:
}
};
-/// \brief This represents '#pragma omp barrier' directive.
+/// This represents '#pragma omp barrier' directive.
///
/// \code
/// #pragma omp barrier
@@ -1828,7 +1848,7 @@ public:
///
class OMPBarrierDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1837,14 +1857,14 @@ class OMPBarrierDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier,
StartLoc, EndLoc, 0, 0) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
explicit OMPBarrierDirective()
: OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier,
SourceLocation(), SourceLocation(), 0, 0) {}
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1853,7 +1873,7 @@ public:
static OMPBarrierDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
@@ -1864,7 +1884,7 @@ public:
}
};
-/// \brief This represents '#pragma omp taskwait' directive.
+/// This represents '#pragma omp taskwait' directive.
///
/// \code
/// #pragma omp taskwait
@@ -1872,7 +1892,7 @@ public:
///
class OMPTaskwaitDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -1881,14 +1901,14 @@ class OMPTaskwaitDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait,
StartLoc, EndLoc, 0, 0) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
explicit OMPTaskwaitDirective()
: OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait,
SourceLocation(), SourceLocation(), 0, 0) {}
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -1897,7 +1917,7 @@ public:
static OMPTaskwaitDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
@@ -1977,7 +1997,7 @@ public:
}
};
-/// \brief This represents '#pragma omp flush' directive.
+/// This represents '#pragma omp flush' directive.
///
/// \code
/// #pragma omp flush(a,b)
@@ -1989,7 +2009,7 @@ public:
/// FlushClause.
class OMPFlushDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2000,7 +2020,7 @@ class OMPFlushDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush,
StartLoc, EndLoc, NumClauses, 0) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2010,7 +2030,7 @@ class OMPFlushDirective : public OMPExecutableDirective {
0) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2022,7 +2042,7 @@ public:
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -2036,7 +2056,7 @@ public:
}
};
-/// \brief This represents '#pragma omp ordered' directive.
+/// This represents '#pragma omp ordered' directive.
///
/// \code
/// #pragma omp ordered
@@ -2044,7 +2064,7 @@ public:
///
class OMPOrderedDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2055,7 +2075,7 @@ class OMPOrderedDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
StartLoc, EndLoc, NumClauses, 1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2065,7 +2085,7 @@ class OMPOrderedDirective : public OMPExecutableDirective {
1) {}
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2077,7 +2097,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
@@ -2090,7 +2110,7 @@ public:
}
};
-/// \brief This represents '#pragma omp atomic' directive.
+/// This represents '#pragma omp atomic' directive.
///
/// \code
/// #pragma omp atomic capture
@@ -2099,7 +2119,7 @@ public:
///
class OMPAtomicDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may
+ /// Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms
/// \code
/// x = x binop expr;
@@ -2109,7 +2129,7 @@ class OMPAtomicDirective : public OMPExecutableDirective {
/// second. Required for correct codegen of non-associative operations (like
/// << or >>).
bool IsXLHSInRHSPart;
- /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may
+ /// Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms
/// \code
/// v = x; <update x>;
@@ -2119,7 +2139,7 @@ class OMPAtomicDirective : public OMPExecutableDirective {
/// otherwise.
bool IsPostfixUpdate;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2131,7 +2151,7 @@ class OMPAtomicDirective : public OMPExecutableDirective {
StartLoc, EndLoc, NumClauses, 5),
IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2141,19 +2161,19 @@ class OMPAtomicDirective : public OMPExecutableDirective {
5),
IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
- /// \brief Set 'x' part of the associated expression/statement.
+ /// Set 'x' part of the associated expression/statement.
void setX(Expr *X) { *std::next(child_begin()) = X; }
- /// \brief Set helper expression of the form
+ /// Set helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
void setUpdateExpr(Expr *UE) { *std::next(child_begin(), 2) = UE; }
- /// \brief Set 'v' part of the associated expression/statement.
+ /// Set 'v' part of the associated expression/statement.
void setV(Expr *V) { *std::next(child_begin(), 3) = V; }
- /// \brief Set 'expr' part of the associated expression/statement.
+ /// Set 'expr' part of the associated expression/statement.
void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; }
public:
- /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
+ /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
/// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
/// detailed description of 'x', 'v' and 'expr').
///
@@ -2177,7 +2197,7 @@ public:
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -2186,12 +2206,12 @@ public:
static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
- /// \brief Get 'x' part of the associated expression/statement.
+ /// Get 'x' part of the associated expression/statement.
Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); }
const Expr *getX() const {
return cast_or_null<Expr>(*std::next(child_begin()));
}
- /// \brief Get helper expression of the form
+ /// Get helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *getUpdateExpr() {
@@ -2200,19 +2220,19 @@ public:
const Expr *getUpdateExpr() const {
return cast_or_null<Expr>(*std::next(child_begin(), 2));
}
- /// \brief Return true if helper update expression has form
+ /// Return true if helper update expression has form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
- /// \brief Return true if 'v' expression must be updated to original value of
+ /// Return true if 'v' expression must be updated to original value of
/// 'x', false if 'v' must be updated to the new value of 'x'.
bool isPostfixUpdate() const { return IsPostfixUpdate; }
- /// \brief Get 'v' part of the associated expression/statement.
+ /// Get 'v' part of the associated expression/statement.
Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); }
const Expr *getV() const {
return cast_or_null<Expr>(*std::next(child_begin(), 3));
}
- /// \brief Get 'expr' part of the associated expression/statement.
+ /// Get 'expr' part of the associated expression/statement.
Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 4)); }
const Expr *getExpr() const {
return cast_or_null<Expr>(*std::next(child_begin(), 4));
@@ -2223,7 +2243,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target' directive.
+/// This represents '#pragma omp target' directive.
///
/// \code
/// #pragma omp target if(a)
@@ -2233,7 +2253,7 @@ public:
///
class OMPTargetDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2244,7 +2264,7 @@ class OMPTargetDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
StartLoc, EndLoc, NumClauses, 1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2254,7 +2274,7 @@ class OMPTargetDirective : public OMPExecutableDirective {
1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2266,7 +2286,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -2280,7 +2300,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target data' directive.
+/// This represents '#pragma omp target data' directive.
///
/// \code
/// #pragma omp target data device(0) if(a) map(b[:])
@@ -2291,7 +2311,7 @@ public:
///
class OMPTargetDataDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
@@ -2299,21 +2319,21 @@ class OMPTargetDataDirective : public OMPExecutableDirective {
///
OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
- : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
OMPD_target_data, StartLoc, EndLoc, NumClauses,
1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
explicit OMPTargetDataDirective(unsigned NumClauses)
- : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
OMPD_target_data, SourceLocation(),
SourceLocation(), NumClauses, 1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2325,7 +2345,7 @@ public:
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.
+ /// Creates an empty directive with the place for \a N clauses.
///
/// \param C AST context.
/// \param N The number of clauses.
@@ -2338,7 +2358,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target enter data' directive.
+/// This represents '#pragma omp target enter data' directive.
///
/// \code
/// #pragma omp target enter data device(0) if(a) map(b[:])
@@ -2349,7 +2369,7 @@ public:
///
class OMPTargetEnterDataDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
@@ -2361,7 +2381,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective {
OMPD_target_enter_data, StartLoc, EndLoc,
NumClauses, /*NumChildren=*/1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2372,7 +2392,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective {
/*NumChildren=*/1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2384,7 +2404,7 @@ public:
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.
+ /// Creates an empty directive with the place for \a N clauses.
///
/// \param C AST context.
/// \param N The number of clauses.
@@ -2397,7 +2417,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target exit data' directive.
+/// This represents '#pragma omp target exit data' directive.
///
/// \code
/// #pragma omp target exit data device(0) if(a) map(b[:])
@@ -2408,7 +2428,7 @@ public:
///
class OMPTargetExitDataDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
@@ -2420,7 +2440,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective {
OMPD_target_exit_data, StartLoc, EndLoc,
NumClauses, /*NumChildren=*/1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2431,7 +2451,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective {
/*NumChildren=*/1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2443,7 +2463,7 @@ public:
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.
+ /// Creates an empty directive with the place for \a N clauses.
///
/// \param C AST context.
/// \param N The number of clauses.
@@ -2456,7 +2476,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target parallel' directive.
+/// This represents '#pragma omp target parallel' directive.
///
/// \code
/// #pragma omp target parallel if(a)
@@ -2466,7 +2486,7 @@ public:
///
class OMPTargetParallelDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2478,7 +2498,7 @@ class OMPTargetParallelDirective : public OMPExecutableDirective {
OMPD_target_parallel, StartLoc, EndLoc,
NumClauses, /*NumChildren=*/1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2489,7 +2509,7 @@ class OMPTargetParallelDirective : public OMPExecutableDirective {
/*NumChildren=*/1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2501,7 +2521,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -2515,7 +2535,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target parallel for' directive.
+/// This represents '#pragma omp target parallel for' directive.
///
/// \code
/// #pragma omp target parallel for private(a,b) reduction(+:c,d)
@@ -2527,10 +2547,10 @@ public:
class OMPTargetParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief true if current region has inner cancel directive.
+ /// true if current region has inner cancel directive.
bool HasCancel;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2544,7 +2564,7 @@ class OMPTargetParallelForDirective : public OMPLoopDirective {
CollapsedNum, NumClauses),
HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -2556,11 +2576,11 @@ class OMPTargetParallelForDirective : public OMPLoopDirective {
SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
- /// \brief Set cancel state.
+ /// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2576,7 +2596,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -2588,7 +2608,7 @@ public:
unsigned CollapsedNum,
EmptyShell);
- /// \brief Return true if current directive has inner cancel directive.
+ /// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
@@ -2596,7 +2616,7 @@ public:
}
};
-/// \brief This represents '#pragma omp teams' directive.
+/// This represents '#pragma omp teams' directive.
///
/// \code
/// #pragma omp teams if(a)
@@ -2606,7 +2626,7 @@ public:
///
class OMPTeamsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2617,7 +2637,7 @@ class OMPTeamsDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
StartLoc, EndLoc, NumClauses, 1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2627,7 +2647,7 @@ class OMPTeamsDirective : public OMPExecutableDirective {
1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2640,7 +2660,7 @@ public:
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -2654,7 +2674,7 @@ public:
}
};
-/// \brief This represents '#pragma omp cancellation point' directive.
+/// This represents '#pragma omp cancellation point' directive.
///
/// \code
/// #pragma omp cancellation point for
@@ -2664,7 +2684,7 @@ public:
class OMPCancellationPointDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
OpenMPDirectiveKind CancelRegion;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2674,7 +2694,7 @@ class OMPCancellationPointDirective : public OMPExecutableDirective {
OMPD_cancellation_point, StartLoc, EndLoc, 0, 0),
CancelRegion(OMPD_unknown) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
explicit OMPCancellationPointDirective()
: OMPExecutableDirective(this, OMPCancellationPointDirectiveClass,
@@ -2682,12 +2702,12 @@ class OMPCancellationPointDirective : public OMPExecutableDirective {
SourceLocation(), 0, 0),
CancelRegion(OMPD_unknown) {}
- /// \brief Set cancel region for current cancellation point.
+ /// Set cancel region for current cancellation point.
/// \param CR Cancellation region.
void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2697,14 +2717,14 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C,
EmptyShell);
- /// \brief Get cancellation region for the current cancellation point.
+ /// Get cancellation region for the current cancellation point.
OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
static bool classof(const Stmt *T) {
@@ -2712,7 +2732,7 @@ public:
}
};
-/// \brief This represents '#pragma omp cancel' directive.
+/// This represents '#pragma omp cancel' directive.
///
/// \code
/// #pragma omp cancel for
@@ -2722,7 +2742,7 @@ public:
class OMPCancelDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
OpenMPDirectiveKind CancelRegion;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2734,7 +2754,7 @@ class OMPCancelDirective : public OMPExecutableDirective {
StartLoc, EndLoc, NumClauses, 0),
CancelRegion(OMPD_unknown) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
explicit OMPCancelDirective(unsigned NumClauses)
@@ -2743,12 +2763,12 @@ class OMPCancelDirective : public OMPExecutableDirective {
0),
CancelRegion(OMPD_unknown) {}
- /// \brief Set cancel region for current cancellation point.
+ /// Set cancel region for current cancellation point.
/// \param CR Cancellation region.
void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
public:
- /// \brief Creates directive.
+ /// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2759,7 +2779,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
@@ -2767,7 +2787,7 @@ public:
static OMPCancelDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
- /// \brief Get cancellation region for the current cancellation point.
+ /// Get cancellation region for the current cancellation point.
OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
static bool classof(const Stmt *T) {
@@ -2775,7 +2795,7 @@ public:
}
};
-/// \brief This represents '#pragma omp taskloop' directive.
+/// This represents '#pragma omp taskloop' directive.
///
/// \code
/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
@@ -2786,7 +2806,7 @@ public:
///
class OMPTaskLoopDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2798,7 +2818,7 @@ class OMPTaskLoopDirective : public OMPLoopDirective {
: OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
StartLoc, EndLoc, CollapsedNum, NumClauses) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -2809,7 +2829,7 @@ class OMPTaskLoopDirective : public OMPLoopDirective {
NumClauses) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2824,7 +2844,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -2840,7 +2860,7 @@ public:
}
};
-/// \brief This represents '#pragma omp taskloop simd' directive.
+/// This represents '#pragma omp taskloop simd' directive.
///
/// \code
/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
@@ -2851,7 +2871,7 @@ public:
///
class OMPTaskLoopSimdDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2864,7 +2884,7 @@ class OMPTaskLoopSimdDirective : public OMPLoopDirective {
OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum,
NumClauses) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -2875,7 +2895,7 @@ class OMPTaskLoopSimdDirective : public OMPLoopDirective {
CollapsedNum, NumClauses) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2890,7 +2910,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -2907,7 +2927,7 @@ public:
}
};
-/// \brief This represents '#pragma omp distribute' directive.
+/// This represents '#pragma omp distribute' directive.
///
/// \code
/// #pragma omp distribute private(a,b)
@@ -2918,7 +2938,7 @@ public:
class OMPDistributeDirective : public OMPLoopDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -2931,7 +2951,7 @@ class OMPDistributeDirective : public OMPLoopDirective {
StartLoc, EndLoc, CollapsedNum, NumClauses)
{}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -2943,7 +2963,7 @@ class OMPDistributeDirective : public OMPLoopDirective {
{}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -2958,7 +2978,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -2974,7 +2994,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target update' directive.
+/// This represents '#pragma omp target update' directive.
///
/// \code
/// #pragma omp target update to(a) from(b) device(1)
@@ -2985,7 +3005,7 @@ public:
///
class OMPTargetUpdateDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
@@ -2997,7 +3017,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective {
OMPD_target_update, StartLoc, EndLoc, NumClauses,
1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -3007,7 +3027,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective {
SourceLocation(), NumClauses, 1) {}
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -3019,7 +3039,7 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Creates an empty directive with the place for \a NumClauses
+ /// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
@@ -3033,7 +3053,7 @@ public:
}
};
-/// \brief This represents '#pragma omp distribute parallel for' composite
+/// This represents '#pragma omp distribute parallel for' composite
/// directive.
///
/// \code
@@ -3047,7 +3067,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
/// true if the construct has inner cancel directive.
bool HasCancel = false;
- /// \brief Build directive with the given start and end location.
+ /// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
@@ -3061,7 +3081,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
OMPD_distribute_parallel_for, StartLoc, EndLoc,
CollapsedNum, NumClauses), HasCancel(false) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
@@ -3077,7 +3097,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
void setHasCancel(bool Has) { HasCancel = Has; }
public:
- /// \brief Creates directive with a list of \a Clauses.
+ /// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
@@ -3093,7 +3113,7 @@ public:
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
- /// \brief Creates an empty directive with the place
+ /// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
@@ -3137,7 +3157,7 @@ class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
unsigned CollapsedNum,
unsigned NumClauses)
: OMPLoopDirective(this, OMPDistributeParallelForSimdDirectiveClass,
- OMPD_distribute_parallel_for_simd, StartLoc,
+ OMPD_distribute_parallel_for_simd, StartLoc,
EndLoc, CollapsedNum, NumClauses) {}
/// Build an empty directive.
@@ -3148,7 +3168,7 @@ class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum,
unsigned NumClauses)
: OMPLoopDirective(this, OMPDistributeParallelForSimdDirectiveClass,
- OMPD_distribute_parallel_for_simd,
+ OMPD_distribute_parallel_for_simd,
SourceLocation(), SourceLocation(), CollapsedNum,
NumClauses) {}
@@ -3212,7 +3232,7 @@ class OMPDistributeSimdDirective final : public OMPLoopDirective {
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
- explicit OMPDistributeSimdDirective(unsigned CollapsedNum,
+ explicit OMPDistributeSimdDirective(unsigned CollapsedNum,
unsigned NumClauses)
: OMPLoopDirective(this, OMPDistributeSimdDirectiveClass,
OMPD_distribute_simd, SourceLocation(),
@@ -3349,7 +3369,7 @@ class OMPTargetSimdDirective final : public OMPLoopDirective {
/// \param NumClauses Number of clauses.
///
explicit OMPTargetSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
- : OMPLoopDirective(this, OMPTargetSimdDirectiveClass, OMPD_target_simd,
+ : OMPLoopDirective(this, OMPTargetSimdDirectiveClass, OMPD_target_simd,
SourceLocation(),SourceLocation(), CollapsedNum,
NumClauses) {}
@@ -3405,8 +3425,8 @@ class OMPTeamsDistributeDirective final : public OMPLoopDirective {
///
OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
- : OMPLoopDirective(this, OMPTeamsDistributeDirectiveClass,
- OMPD_teams_distribute, StartLoc, EndLoc,
+ : OMPLoopDirective(this, OMPTeamsDistributeDirectiveClass,
+ OMPD_teams_distribute, StartLoc, EndLoc,
CollapsedNum, NumClauses) {}
/// Build an empty directive.
@@ -3547,7 +3567,7 @@ class OMPTeamsDistributeParallelForSimdDirective final
unsigned CollapsedNum,
unsigned NumClauses)
: OMPLoopDirective(this, OMPTeamsDistributeParallelForSimdDirectiveClass,
- OMPD_teams_distribute_parallel_for_simd, StartLoc,
+ OMPD_teams_distribute_parallel_for_simd, StartLoc,
EndLoc, CollapsedNum, NumClauses) {}
/// Build an empty directive.
@@ -3558,7 +3578,7 @@ class OMPTeamsDistributeParallelForSimdDirective final
explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum,
unsigned NumClauses)
: OMPLoopDirective(this, OMPTeamsDistributeParallelForSimdDirectiveClass,
- OMPD_teams_distribute_parallel_for_simd,
+ OMPD_teams_distribute_parallel_for_simd,
SourceLocation(), SourceLocation(), CollapsedNum,
NumClauses) {}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
index 98fa11327406..30bc257c7e79 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
@@ -195,7 +195,7 @@ template<typename ImplClass, typename RetTy=void, typename... ParamTys>
class ConstStmtVisitor
: public StmtVisitorBase<make_const_ptr, ImplClass, RetTy, ParamTys...> {};
-/// \brief This class implements a simple visitor for OMPClause
+/// This class implements a simple visitor for OMPClause
/// subclasses.
template<class ImplClass, template <typename> class Ptr, typename RetTy>
class OMPClauseVisitorBase {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
index 850250b9c0a2..6898ef4e1b8a 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
@@ -47,12 +47,12 @@ struct PrintingPolicy;
class TypeSourceInfo;
class ValueDecl;
-/// \brief Represents a template argument.
+/// Represents a template argument.
class TemplateArgument {
public:
- /// \brief The kind of template argument we're storing.
+ /// The kind of template argument we're storing.
enum ArgKind {
- /// \brief Represents an empty template argument, e.g., one that has not
+ /// Represents an empty template argument, e.g., one that has not
/// been deduced.
Null = 0,
@@ -92,7 +92,7 @@ public:
};
private:
- /// \brief The kind of template argument we're storing.
+ /// The kind of template argument we're storing.
struct DA {
unsigned Kind;
@@ -138,16 +138,16 @@ private:
};
public:
- /// \brief Construct an empty, invalid template argument.
+ /// Construct an empty, invalid template argument.
constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
- /// \brief Construct a template type argument.
+ /// Construct a template type argument.
TemplateArgument(QualType T, bool isNullPtr = false) {
TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
}
- /// \brief Construct a template argument that refers to a
+ /// Construct a template argument that refers to a
/// declaration, which is either an external declaration or a
/// template declaration.
TemplateArgument(ValueDecl *D, QualType QT) {
@@ -157,18 +157,18 @@ public:
DeclArg.D = D;
}
- /// \brief Construct an integral constant template argument. The memory to
+ /// Construct an integral constant template argument. The memory to
/// store the value is allocated with Ctx.
TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
- /// \brief Construct an integral constant template argument with the same
+ /// Construct an integral constant template argument with the same
/// value as Other but a different type.
TemplateArgument(const TemplateArgument &Other, QualType Type) {
Integer = Other.Integer;
Integer.Type = Type.getAsOpaquePtr();
}
- /// \brief Construct a template argument that is a template.
+ /// Construct a template argument that is a template.
///
/// This form of template argument is generally used for template template
/// parameters. However, the template name could be a dependent template
@@ -182,7 +182,7 @@ public:
TemplateArg.NumExpansions = 0;
}
- /// \brief Construct a template argument that is a template pack expansion.
+ /// Construct a template argument that is a template pack expansion.
///
/// This form of template argument is generally used for template template
/// parameters. However, the template name could be a dependent template
@@ -202,7 +202,7 @@ public:
TemplateArg.NumExpansions = 0;
}
- /// \brief Construct a template argument that is an expression.
+ /// Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
/// lists used for dependent types and for expression; it will not
@@ -212,7 +212,7 @@ public:
TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
}
- /// \brief Construct a template argument that is a template argument pack.
+ /// Construct a template argument that is a template argument pack.
///
/// We assume that storage for the template arguments provided
/// outlives the TemplateArgument itself.
@@ -226,40 +226,40 @@ public:
static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
- /// \brief Create a new template argument pack by copying the given set of
+ /// Create a new template argument pack by copying the given set of
/// template arguments.
static TemplateArgument CreatePackCopy(ASTContext &Context,
ArrayRef<TemplateArgument> Args);
- /// \brief Return the kind of stored template argument.
+ /// Return the kind of stored template argument.
ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
- /// \brief Determine whether this template argument has no value.
+ /// Determine whether this template argument has no value.
bool isNull() const { return getKind() == Null; }
- /// \brief Whether this template argument is dependent on a template
+ /// Whether this template argument is dependent on a template
/// parameter such that its result can change from one instantiation to
/// another.
bool isDependent() const;
- /// \brief Whether this template argument is dependent on a template
+ /// Whether this template argument is dependent on a template
/// parameter.
bool isInstantiationDependent() const;
- /// \brief Whether this template argument contains an unexpanded
+ /// Whether this template argument contains an unexpanded
/// parameter pack.
bool containsUnexpandedParameterPack() const;
- /// \brief Determine whether this template argument is a pack expansion.
+ /// Determine whether this template argument is a pack expansion.
bool isPackExpansion() const;
-
- /// \brief Retrieve the type for a type template argument.
+
+ /// Retrieve the type for a type template argument.
QualType getAsType() const {
assert(getKind() == Type && "Unexpected kind");
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
}
- /// \brief Retrieve the declaration for a declaration non-type
+ /// Retrieve the declaration for a declaration non-type
/// template argument.
ValueDecl *getAsDecl() const {
assert(getKind() == Declaration && "Unexpected kind");
@@ -271,32 +271,32 @@ public:
return QualType::getFromOpaquePtr(DeclArg.QT);
}
- /// \brief Retrieve the type for null non-type template argument.
+ /// Retrieve the type for null non-type template argument.
QualType getNullPtrType() const {
assert(getKind() == NullPtr && "Unexpected kind");
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
}
- /// \brief Retrieve the template name for a template name argument.
+ /// Retrieve the template name for a template name argument.
TemplateName getAsTemplate() const {
assert(getKind() == Template && "Unexpected kind");
return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
- /// \brief Retrieve the template argument as a template name; if the argument
+ /// Retrieve the template argument as a template name; if the argument
/// is a pack expansion, return the pattern as a template name.
TemplateName getAsTemplateOrTemplatePattern() const {
assert((getKind() == Template || getKind() == TemplateExpansion) &&
"Unexpected kind");
-
+
return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
- /// \brief Retrieve the number of expansions that a template template argument
+ /// Retrieve the number of expansions that a template template argument
/// expansion will produce, if known.
Optional<unsigned> getNumTemplateExpansions() const;
-
- /// \brief Retrieve the template argument as an integral value.
+
+ /// Retrieve the template argument as an integral value.
// FIXME: Provide a way to read the integral data without copying the value.
llvm::APSInt getAsIntegral() const {
assert(getKind() == Integral && "Unexpected kind");
@@ -311,7 +311,7 @@ public:
Integer.IsUnsigned);
}
- /// \brief Retrieve the type of the integral value.
+ /// Retrieve the type of the integral value.
QualType getIntegralType() const {
assert(getKind() == Integral && "Unexpected kind");
return QualType::getFromOpaquePtr(Integer.Type);
@@ -322,70 +322,70 @@ public:
Integer.Type = T.getAsOpaquePtr();
}
- /// \brief If this is a non-type template argument, get its type. Otherwise,
+ /// If this is a non-type template argument, get its type. Otherwise,
/// returns a null QualType.
QualType getNonTypeTemplateArgumentType() const;
- /// \brief Retrieve the template argument as an expression.
+ /// Retrieve the template argument as an expression.
Expr *getAsExpr() const {
assert(getKind() == Expression && "Unexpected kind");
return reinterpret_cast<Expr *>(TypeOrValue.V);
}
- /// \brief Iterator that traverses the elements of a template argument pack.
+ /// Iterator that traverses the elements of a template argument pack.
using pack_iterator = const TemplateArgument *;
- /// \brief Iterator referencing the first argument of a template argument
+ /// Iterator referencing the first argument of a template argument
/// pack.
pack_iterator pack_begin() const {
assert(getKind() == Pack);
return Args.Args;
}
- /// \brief Iterator referencing one past the last argument of a template
+ /// Iterator referencing one past the last argument of a template
/// argument pack.
pack_iterator pack_end() const {
assert(getKind() == Pack);
return Args.Args + Args.NumArgs;
}
- /// \brief Iterator range referencing all of the elements of a template
+ /// Iterator range referencing all of the elements of a template
/// argument pack.
ArrayRef<TemplateArgument> pack_elements() const {
return llvm::makeArrayRef(pack_begin(), pack_end());
}
- /// \brief The number of template arguments in the given template argument
+ /// The number of template arguments in the given template argument
/// pack.
unsigned pack_size() const {
assert(getKind() == Pack);
return Args.NumArgs;
}
- /// \brief Return the array of arguments in this template argument pack.
+ /// Return the array of arguments in this template argument pack.
ArrayRef<TemplateArgument> getPackAsArray() const {
assert(getKind() == Pack);
return llvm::makeArrayRef(Args.Args, Args.NumArgs);
}
- /// \brief Determines whether two template arguments are superficially the
+ /// Determines whether two template arguments are superficially the
/// same.
bool structurallyEquals(const TemplateArgument &Other) const;
- /// \brief When the template argument is a pack expansion, returns
+ /// When the template argument is a pack expansion, returns
/// the pattern of the pack expansion.
TemplateArgument getPackExpansionPattern() const;
- /// \brief Print this template argument to the given output stream.
+ /// Print this template argument to the given output stream.
void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
-
- /// \brief Debugging aid that dumps the template argument.
+
+ /// Debugging aid that dumps the template argument.
void dump(raw_ostream &Out) const;
- /// \brief Debugging aid that dumps the template argument to standard error.
+ /// Debugging aid that dumps the template argument to standard error.
void dump() const;
-
- /// \brief Used to insert TemplateArguments into FoldingSets.
+
+ /// Used to insert TemplateArguments into FoldingSets.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
};
@@ -411,9 +411,9 @@ public:
constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {}
TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
-
+
TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
-
+
TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
SourceLocation EllipsisLoc) {
@@ -432,14 +432,14 @@ public:
}
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
- return NestedNameSpecifierLoc(Template.Qualifier,
+ return NestedNameSpecifierLoc(Template.Qualifier,
Template.QualifierLocData);
}
-
+
SourceLocation getTemplateNameLoc() const {
return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
}
-
+
SourceLocation getTemplateEllipsisLoc() const {
return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
}
@@ -465,10 +465,16 @@ public:
TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
: Argument(Argument), LocInfo(E) {
- assert(Argument.getKind() == TemplateArgument::Expression);
+
+ // Permit any kind of template argument that can be represented with an
+ // expression
+ assert(Argument.getKind() == TemplateArgument::NullPtr ||
+ Argument.getKind() == TemplateArgument::Integral ||
+ Argument.getKind() == TemplateArgument::Declaration ||
+ Argument.getKind() == TemplateArgument::Expression);
}
- TemplateArgumentLoc(const TemplateArgument &Argument,
+ TemplateArgumentLoc(const TemplateArgument &Argument,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
SourceLocation EllipsisLoc = SourceLocation())
@@ -477,17 +483,17 @@ public:
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
}
-
- /// \brief - Fetches the primary location of the argument.
+
+ /// - Fetches the primary location of the argument.
SourceLocation getLocation() const {
if (Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion)
return getTemplateNameLoc();
-
+
return getSourceRange().getBegin();
}
- /// \brief - Fetches the full source range of the argument.
+ /// - Fetches the full source range of the argument.
SourceRange getSourceRange() const LLVM_READONLY;
const TemplateArgument &getArgument() const {
@@ -528,13 +534,13 @@ public:
Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateQualifierLoc();
}
-
+
SourceLocation getTemplateNameLoc() const {
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateNameLoc();
- }
-
+ }
+
SourceLocation getTemplateEllipsisLoc() const {
assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateEllipsisLoc();
@@ -588,7 +594,7 @@ public:
}
};
-/// \brief Represents an explicit template argument list in C++, e.g.,
+/// Represents an explicit template argument list in C++, e.g.,
/// the "<int>" in "sort<int>".
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
@@ -602,16 +608,16 @@ private:
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
public:
- /// \brief The source location of the left angle bracket ('<').
+ /// The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
- /// \brief The source location of the right angle bracket ('>').
+ /// The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;
- /// \brief The number of template arguments in TemplateArgs.
+ /// The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;
- /// \brief Retrieve the template arguments
+ /// Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return getTrailingObjects<TemplateArgumentLoc>();
}
@@ -628,7 +634,7 @@ public:
Create(ASTContext &C, const TemplateArgumentListInfo &List);
};
-/// \brief Represents an explicit template argument list in C++, e.g.,
+/// Represents an explicit template argument list in C++, e.g.,
/// the "<int>" in "sort<int>".
///
/// It is intended to be used as a trailing object on AST nodes, and
@@ -636,19 +642,19 @@ public:
/// but expects the containing object to also provide storage for
/// that.
struct alignas(void *) ASTTemplateKWAndArgsInfo {
- /// \brief The source location of the left angle bracket ('<').
+ /// The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
- /// \brief The source location of the right angle bracket ('>').
+ /// The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;
- /// \brief The source location of the template keyword; this is used
+ /// The source location of the template keyword; this is used
/// as part of the representation of qualified identifiers, such as
/// S<T>::template apply<T>. Will be empty if this expression does
/// not have a template keyword.
SourceLocation TemplateKWLoc;
- /// \brief The number of template arguments in TemplateArgs.
+ /// The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;
void initializeFrom(SourceLocation TemplateKWLoc,
@@ -689,7 +695,7 @@ inline const TemplateArgument &
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
-
+
} // namespace clang
#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 fb33cf58d796..d88d58d0a2aa 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
@@ -22,7 +22,7 @@
#include <cassert>
namespace clang {
-
+
class ASTContext;
class DependentTemplateName;
class DiagnosticBuilder;
@@ -38,8 +38,8 @@ class SubstTemplateTemplateParmStorage;
class TemplateArgument;
class TemplateDecl;
class TemplateTemplateParmDecl;
-
-/// \brief Implementation class used to describe either a set of overloaded
+
+/// Implementation class used to describe either a set of overloaded
/// template names or an already-substituted template template parameter pack.
class UncommonTemplateNameStorage {
protected:
@@ -50,10 +50,10 @@ protected:
};
struct BitsTag {
- /// \brief A Kind.
+ /// A Kind.
unsigned Kind : 2;
-
- /// \brief The number of stored templates or template arguments,
+
+ /// The number of stored templates or template arguments,
/// depending on which subclass we have.
unsigned Size : 30;
};
@@ -62,21 +62,21 @@ protected:
struct BitsTag Bits;
void *PointerAlignment;
};
-
+
UncommonTemplateNameStorage(Kind kind, unsigned size) {
Bits.Kind = kind;
Bits.Size = size;
}
-
+
public:
unsigned size() const { return Bits.Size; }
-
+
OverloadedTemplateStorage *getAsOverloadedStorage() {
return Bits.Kind == Overloaded
- ? reinterpret_cast<OverloadedTemplateStorage *>(this)
+ ? reinterpret_cast<OverloadedTemplateStorage *>(this)
: nullptr;
}
-
+
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
return Bits.Kind == SubstTemplateTemplateParm
? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
@@ -89,13 +89,13 @@ public:
: nullptr;
}
};
-
-/// \brief A structure for storing the information associated with an
+
+/// A structure for storing the information associated with an
/// overloaded template name.
class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
- OverloadedTemplateStorage(unsigned size)
+ OverloadedTemplateStorage(unsigned size)
: UncommonTemplateNameStorage(Overloaded, size) {}
NamedDecl **getStorage() {
@@ -112,10 +112,10 @@ public:
iterator end() const { return getStorage() + size(); }
};
-/// \brief A structure for storing an already-substituted template template
+/// A structure for storing an already-substituted template template
/// parameter pack.
///
-/// This kind of template names occurs when the parameter pack has been
+/// This kind of template names occurs when the parameter pack has been
/// provided with a template template argument pack in a context where its
/// enclosing pack expansion could not be fully expanded.
class SubstTemplateTemplateParmPackStorage
@@ -123,32 +123,32 @@ class SubstTemplateTemplateParmPackStorage
{
TemplateTemplateParmDecl *Parameter;
const TemplateArgument *Arguments;
-
+
public:
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
- unsigned Size,
+ unsigned Size,
const TemplateArgument *Arguments)
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
Parameter(Parameter), Arguments(Arguments) {}
-
- /// \brief Retrieve the template template parameter pack being substituted.
+
+ /// Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const {
return Parameter;
}
-
- /// \brief Retrieve the template template argument pack with which this
+
+ /// Retrieve the template template argument pack with which this
/// parameter was substituted.
TemplateArgument getArgumentPack() const;
-
+
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
-
+
static void Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack);
};
-/// \brief Represents a C++ template name within the type system.
+/// Represents a C++ template name within the type system.
///
/// A C++ template name refers to a template within the C++ type
/// system. In most cases, a template name is simply a reference to a
@@ -185,27 +185,27 @@ class TemplateName {
explicit TemplateName(void *Ptr);
public:
- // \brief Kind of name that is actually stored.
+ // Kind of name that is actually stored.
enum NameKind {
- /// \brief A single template declaration.
+ /// A single template declaration.
Template,
- /// \brief A set of overloaded template declarations.
+ /// A set of overloaded template declarations.
OverloadedTemplate,
- /// \brief A qualified template name, where the qualification is kept
+ /// 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
+ /// 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
+ /// 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 parameter pack that has been substituted for
/// a template template argument pack, but has not yet been expanded into
/// individual arguments.
SubstTemplateTemplateParmPack
@@ -219,13 +219,13 @@ public:
explicit TemplateName(QualifiedTemplateName *Qual);
explicit TemplateName(DependentTemplateName *Dep);
- /// \brief Determine whether this template name is NULL.
+ /// Determine whether this template name is NULL.
bool isNull() const;
-
- // \brief Get the kind of name that is actually stored.
+
+ // Get the kind of name that is actually stored.
NameKind getKind() const;
- /// \brief Retrieve the underlying template declaration that
+ /// Retrieve the underlying template declaration that
/// this template name refers to, if known.
///
/// \returns The template declaration that this template name refers
@@ -234,7 +234,7 @@ public:
/// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const;
- /// \brief Retrieve the underlying, overloaded function template
+ /// Retrieve the underlying, overloaded function template
// declarations that this template name refers to, if known.
///
/// \returns The set of overloaded function templates that this template
@@ -243,14 +243,14 @@ public:
/// refers to a single template, returns NULL.
OverloadedTemplateStorage *getAsOverloadedTemplate() const;
- /// \brief Retrieve the substituted template template parameter, if
+ /// Retrieve the substituted template template parameter, if
/// known.
///
/// \returns The storage for the substituted template template parameter,
/// if known. Otherwise, returns NULL.
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;
- /// \brief Retrieve the substituted template template parameter pack, if
+ /// Retrieve the substituted template template parameter pack, if
/// known.
///
/// \returns The storage for the substituted template template parameter pack,
@@ -258,11 +258,11 @@ public:
SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const;
- /// \brief Retrieve the underlying qualified template name
+ /// Retrieve the underlying qualified template name
/// structure, if any.
QualifiedTemplateName *getAsQualifiedTemplateName() const;
- /// \brief Retrieve the underlying dependent template name
+ /// Retrieve the underlying dependent template name
/// structure, if any.
DependentTemplateName *getAsDependentTemplateName() const;
@@ -273,18 +273,18 @@ public:
/// the template, including any default template arguments.
TemplateName getNameToSubstitute() const;
- /// \brief Determines whether this is a dependent template name.
+ /// Determines whether this is a dependent template name.
bool isDependent() const;
- /// \brief Determines whether this is a template name that somehow
+ /// Determines whether this is a template name that somehow
/// depends on a template parameter.
bool isInstantiationDependent() const;
- /// \brief Determines whether this template name contains an
+ /// Determines whether this template name contains an
/// unexpanded parameter pack (for C++0x variadic templates).
bool containsUnexpandedParameterPack() const;
- /// \brief Print the template name.
+ /// Print the template name.
///
/// \param OS the output stream to which the template name will be
/// printed.
@@ -295,10 +295,10 @@ public:
void print(raw_ostream &OS, const PrintingPolicy &Policy,
bool SuppressNNS = false) const;
- /// \brief Debugging aid that dumps the template name.
+ /// Debugging aid that dumps the template name.
void dump(raw_ostream &OS) const;
- /// \brief Debugging aid that dumps the template name to standard
+ /// Debugging aid that dumps the template name to standard
/// error.
void dump() const;
@@ -306,10 +306,10 @@ public:
ID.AddPointer(Storage.getOpaqueValue());
}
- /// \brief Retrieve the template name as a void pointer.
+ /// Retrieve the template name as a void pointer.
void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
- /// \brief Build a template name from a void pointer.
+ /// Build a template name from a void pointer.
static TemplateName getFromVoidPointer(void *Ptr) {
return TemplateName(Ptr);
}
@@ -320,7 +320,7 @@ public:
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
TemplateName N);
-/// \brief A structure for storing the information associated with a
+/// A structure for storing the information associated with a
/// substituted template template parameter.
class SubstTemplateTemplateParmStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
@@ -339,7 +339,7 @@ public:
TemplateName getReplacement() const { return Replacement; }
void Profile(llvm::FoldingSetNodeID &ID);
-
+
static void Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *parameter,
TemplateName replacement);
@@ -352,7 +352,7 @@ inline TemplateName TemplateName::getUnderlying() const {
return *this;
}
-/// \brief Represents a template name that was expressed as a
+/// Represents a template name that was expressed as a
/// qualified name.
///
/// This kind of template name refers to a template name that was
@@ -366,7 +366,7 @@ inline TemplateName TemplateName::getUnderlying() const {
class QualifiedTemplateName : public llvm::FoldingSetNode {
friend class ASTContext;
- /// \brief The nested name specifier that qualifies the template name.
+ /// The nested name specifier that qualifies the template name.
///
/// The bit is used to indicate whether the "template" keyword was
/// present before the template name itself. Note that the
@@ -375,7 +375,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// this name with DependentTemplateName).
llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
- /// \brief The template declaration or set of overloaded function templates
+ /// The template declaration or set of overloaded function templates
/// that this qualified name refers to.
TemplateDecl *Template;
@@ -384,18 +384,18 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
: Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {}
public:
- /// \brief Return the nested name specifier that qualifies this name.
+ /// Return the nested name specifier that qualifies this name.
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
- /// \brief Whether the template name was prefixed by the "template"
+ /// Whether the template name was prefixed by the "template"
/// keyword.
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
- /// \brief The template declaration that this qualified name refers
+ /// The template declaration that this qualified name refers
/// to.
TemplateDecl *getDecl() const { return Template; }
- /// \brief The template declaration to which this qualified name
+ /// The template declaration to which this qualified name
/// refers.
TemplateDecl *getTemplateDecl() const { return Template; }
@@ -411,7 +411,7 @@ public:
}
};
-/// \brief Represents a dependent template name that cannot be
+/// Represents a dependent template name that cannot be
/// resolved prior to template instantiation.
///
/// This kind of template name refers to a dependent template name,
@@ -422,7 +422,7 @@ public:
class DependentTemplateName : public llvm::FoldingSetNode {
friend class ASTContext;
- /// \brief The nested name specifier that qualifies the template
+ /// The nested name specifier that qualifies the template
/// name.
///
/// The bit stored in this qualifier describes whether the \c Name field
@@ -430,20 +430,20 @@ class DependentTemplateName : public llvm::FoldingSetNode {
/// overloaded operator kind (when set).
llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
- /// \brief The dependent template name.
+ /// The dependent template name.
union {
- /// \brief The identifier template name.
+ /// The identifier template name.
///
/// Only valid when the bit on \c Qualifier is clear.
const IdentifierInfo *Identifier;
-
- /// \brief The overloaded operator name.
+
+ /// The overloaded operator name.
///
/// Only valid when the bit on \c Qualifier is set.
OverloadedOperatorKind Operator;
};
- /// \brief The canonical template name to which this dependent
+ /// The canonical template name to which this dependent
/// template name refers.
///
/// The canonical template name for a dependent template name is
@@ -453,50 +453,50 @@ class DependentTemplateName : public llvm::FoldingSetNode {
DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier)
- : Qualifier(Qualifier, false), Identifier(Identifier),
+ : Qualifier(Qualifier, false), Identifier(Identifier),
CanonicalTemplateName(this) {}
DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier,
TemplateName Canon)
- : Qualifier(Qualifier, false), Identifier(Identifier),
+ : Qualifier(Qualifier, false), Identifier(Identifier),
CanonicalTemplateName(Canon) {}
DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator)
- : Qualifier(Qualifier, true), Operator(Operator),
+ : Qualifier(Qualifier, true), Operator(Operator),
CanonicalTemplateName(this) {}
-
+
DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator,
TemplateName Canon)
- : Qualifier(Qualifier, true), Operator(Operator),
+ : Qualifier(Qualifier, true), Operator(Operator),
CanonicalTemplateName(Canon) {}
-
+
public:
- /// \brief Return the nested name specifier that qualifies this name.
+ /// Return the nested name specifier that qualifies this name.
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
- /// \brief Determine whether this template name refers to an identifier.
+ /// Determine whether this template name refers to an identifier.
bool isIdentifier() const { return !Qualifier.getInt(); }
- /// \brief Returns the identifier to which this template name refers.
- const IdentifierInfo *getIdentifier() const {
+ /// Returns the identifier to which this template name refers.
+ const IdentifierInfo *getIdentifier() const {
assert(isIdentifier() && "Template name isn't an identifier?");
return Identifier;
}
-
- /// \brief Determine whether this template name refers to an overloaded
+
+ /// Determine whether this template name refers to an overloaded
/// operator.
bool isOverloadedOperator() const { return Qualifier.getInt(); }
-
- /// \brief Return the overloaded operator to which this template name refers.
- OverloadedOperatorKind getOperator() const {
+
+ /// Return the overloaded operator to which this template name refers.
+ OverloadedOperatorKind getOperator() const {
assert(isOverloadedOperator() &&
"Template name isn't an overloaded operator?");
- return Operator;
+ return Operator;
}
-
+
void Profile(llvm::FoldingSetNodeID &ID) {
if (isIdentifier())
Profile(ID, getQualifier(), getIdentifier());
@@ -523,7 +523,7 @@ public:
namespace llvm {
-/// \brief The clang::TemplateName class is effectively a pointer.
+/// The clang::TemplateName class is effectively a pointer.
template<>
struct PointerLikeTypeTraits<clang::TemplateName> {
static inline void *getAsVoidPointer(clang::TemplateName TN) {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h
index 882878bb7e1e..9a8dd6faff31 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Type.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief C Language Family Type Representation
+/// C Language Family Type Representation
///
/// This file defines the clang::Type interface and subclasses, used to
/// represent types for languages in the C family.
@@ -30,6 +30,7 @@
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/None.h"
@@ -56,6 +57,7 @@ namespace clang {
class ExtQuals;
class QualType;
+class TagDecl;
class Type;
enum {
@@ -445,7 +447,7 @@ public:
}
}
- /// \brief Remove the qualifiers from the given set from this set.
+ /// Remove the qualifiers from the given set from this set.
void removeQualifiers(Qualifiers Q) {
// If the other set doesn't have any non-boolean qualifiers, just
// bit-and the inverse in.
@@ -508,7 +510,7 @@ public:
(!other.hasUnaligned() || hasUnaligned());
}
- /// \brief Determines if these qualifiers compatibly include another set of
+ /// Determines if these qualifiers compatibly include another set of
/// qualifiers from the narrow perspective of Objective-C ARC lifetime.
///
/// One set of Objective-C lifetime qualifiers compatibly includes the other
@@ -528,7 +530,7 @@ public:
return hasConst();
}
- /// \brief Determine whether this set of qualifiers is a strict superset of
+ /// Determine whether this set of qualifiers is a strict superset of
/// another set of qualifiers, not considering qualifier compatibility.
bool isStrictSupersetOf(Qualifiers Other) const;
@@ -554,7 +556,7 @@ public:
return *this;
}
- /// \brief Compute the difference between two qualifier sets.
+ /// Compute the difference between two qualifier sets.
friend Qualifiers operator-(Qualifiers L, Qualifiers R) {
L -= R;
return L;
@@ -667,8 +669,7 @@ class QualType {
const ExtQualsTypeCommonBase *getCommonPtr() const {
assert(!isNull() && "Cannot retrieve a NULL type pointer");
- uintptr_t CommonPtrVal
- = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
+ auto CommonPtrVal = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
}
@@ -720,69 +721,69 @@ public:
return Value.getPointer().isNull();
}
- /// \brief Determine whether this particular QualType instance has the
+ /// Determine whether this particular QualType instance has the
/// "const" qualifier set, without looking through typedefs that may have
/// added "const" at a different level.
bool isLocalConstQualified() const {
return (getLocalFastQualifiers() & Qualifiers::Const);
}
- /// \brief Determine whether this type is const-qualified.
+ /// Determine whether this type is const-qualified.
bool isConstQualified() const;
- /// \brief Determine whether this particular QualType instance has the
+ /// Determine whether this particular QualType instance has the
/// "restrict" qualifier set, without looking through typedefs that may have
/// added "restrict" at a different level.
bool isLocalRestrictQualified() const {
return (getLocalFastQualifiers() & Qualifiers::Restrict);
}
- /// \brief Determine whether this type is restrict-qualified.
+ /// Determine whether this type is restrict-qualified.
bool isRestrictQualified() const;
- /// \brief Determine whether this particular QualType instance has the
+ /// Determine whether this particular QualType instance has the
/// "volatile" qualifier set, without looking through typedefs that may have
/// added "volatile" at a different level.
bool isLocalVolatileQualified() const {
return (getLocalFastQualifiers() & Qualifiers::Volatile);
}
- /// \brief Determine whether this type is volatile-qualified.
+ /// Determine whether this type is volatile-qualified.
bool isVolatileQualified() const;
- /// \brief Determine whether this particular QualType instance has any
+ /// Determine whether this particular QualType instance has any
/// qualifiers, without looking through any typedefs that might add
/// qualifiers at a different level.
bool hasLocalQualifiers() const {
return getLocalFastQualifiers() || hasLocalNonFastQualifiers();
}
- /// \brief Determine whether this type has any qualifiers.
+ /// Determine whether this type has any qualifiers.
bool hasQualifiers() const;
- /// \brief Determine whether this particular QualType instance has any
+ /// Determine whether this particular QualType instance has any
/// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType
/// instance.
bool hasLocalNonFastQualifiers() const {
return Value.getPointer().is<const ExtQuals*>();
}
- /// \brief Retrieve the set of qualifiers local to this particular QualType
+ /// Retrieve the set of qualifiers local to this particular QualType
/// instance, not including any qualifiers acquired through typedefs or
/// other sugar.
Qualifiers getLocalQualifiers() const;
- /// \brief Retrieve the set of qualifiers applied to this type.
+ /// Retrieve the set of qualifiers applied to this type.
Qualifiers getQualifiers() const;
- /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
+ /// Retrieve the set of CVR (const-volatile-restrict) qualifiers
/// local to this particular QualType instance, not including any qualifiers
/// acquired through typedefs or other sugar.
unsigned getLocalCVRQualifiers() const {
return getLocalFastQualifiers();
}
- /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
+ /// Retrieve the set of CVR (const-volatile-restrict) qualifiers
/// applied to this type.
unsigned getCVRQualifiers() const;
@@ -790,7 +791,7 @@ public:
return QualType::isConstant(*this, Ctx);
}
- /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
+ /// Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
bool isPODType(const ASTContext &Context) const;
/// Return true if this is a POD type according to the rules of the C++98
@@ -799,7 +800,8 @@ public:
/// Return true if this is a POD type according to the more relaxed rules
/// of the C++11 standard, regardless of the current compilation's language.
- /// (C++0x [basic.types]p9)
+ /// (C++0x [basic.types]p9). Note that, unlike
+ /// CXXRecordDecl::isCXX11StandardLayout, this takes DRs into account.
bool isCXX11PODType(const ASTContext &Context) const;
/// Return true if this is a trivial type per (C++0x [basic.types]p9)
@@ -808,6 +810,13 @@ public:
/// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isTriviallyCopyableType(const ASTContext &Context) const;
+
+ /// Returns true if it is a class and it might be dynamic.
+ bool mayBeDynamicClass() const;
+
+ /// Returns true if it is not a class or if the class might not be dynamic.
+ bool mayBeNotDynamicClass() const;
+
// Don't promise in the API that anything besides 'const' can be
// easily added.
@@ -879,12 +888,12 @@ public:
QualType getCanonicalType() const;
- /// \brief Return this type with all of the instance-specific qualifiers
+ /// Return this type with all of the instance-specific qualifiers
/// removed, but without removing any qualifiers that may have been applied
/// through typedefs.
QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); }
- /// \brief Retrieve the unqualified variant of the given type,
+ /// Retrieve the unqualified variant of the given type,
/// removing as little sugar as possible.
///
/// This routine looks through various kinds of sugar to find the
@@ -915,17 +924,17 @@ public:
/// ASTContext::getUnqualifiedArrayType.
inline SplitQualType getSplitUnqualifiedType() const;
- /// \brief Determine whether this type is more qualified than the other
+ /// Determine whether this type is more qualified than the other
/// given type, requiring exact equality for non-CVR qualifiers.
bool isMoreQualifiedThan(QualType Other) const;
- /// \brief Determine whether this type is at least as qualified as the other
+ /// Determine whether this type is at least as qualified as the other
/// given type, requiring exact equality for non-CVR qualifiers.
bool isAtLeastAsQualifiedAs(QualType Other) const;
QualType getNonReferenceType() const;
- /// \brief Determine the type of a (typically non-lvalue) expression with the
+ /// Determine the type of a (typically non-lvalue) expression with the
/// specified result type.
///
/// This routine should be used for expressions for which the return type is
@@ -951,7 +960,7 @@ public:
return getSplitDesugaredType(*this);
}
- /// \brief Return the specified type with one level of "sugar" removed from
+ /// Return the specified type with one level of "sugar" removed from
/// the type.
///
/// This routine takes off the first typedef, typeof, etc. If the outer level
@@ -983,7 +992,7 @@ public:
static std::string getAsString(const Type *ty, Qualifiers qs,
const PrintingPolicy &Policy);
- std::string getAsString() const;
+ std::string getAsString() const;
std::string getAsString(const PrintingPolicy &Policy) const;
void print(raw_ostream &OS, const PrintingPolicy &Policy,
@@ -1082,11 +1091,79 @@ public:
// true when Type is objc's weak and weak is enabled but ARC isn't.
bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
+ enum PrimitiveDefaultInitializeKind {
+ /// The type does not fall into any of the following categories. Note that
+ /// this case is zero-valued so that values of this enum can be used as a
+ /// boolean condition for non-triviality.
+ PDIK_Trivial,
+
+ /// The type is an Objective-C retainable pointer type that is qualified
+ /// with the ARC __strong qualifier.
+ PDIK_ARCStrong,
+
+ /// The type is an Objective-C retainable pointer type that is qualified
+ /// with the ARC __weak qualifier.
+ PDIK_ARCWeak,
+
+ /// The type is a struct containing a field whose type is not PCK_Trivial.
+ PDIK_Struct
+ };
+
+ /// Functions to query basic properties of non-trivial C struct types.
+
+ /// Check if this is a non-trivial type that would cause a C struct
+ /// transitively containing this type to be non-trivial to default initialize
+ /// and return the kind.
+ PrimitiveDefaultInitializeKind
+ isNonTrivialToPrimitiveDefaultInitialize() const;
+
+ enum PrimitiveCopyKind {
+ /// The type does not fall into any of the following categories. Note that
+ /// this case is zero-valued so that values of this enum can be used as a
+ /// boolean condition for non-triviality.
+ PCK_Trivial,
+
+ /// The type would be trivial except that it is volatile-qualified. Types
+ /// that fall into one of the other non-trivial cases may additionally be
+ /// volatile-qualified.
+ PCK_VolatileTrivial,
+
+ /// The type is an Objective-C retainable pointer type that is qualified
+ /// with the ARC __strong qualifier.
+ PCK_ARCStrong,
+
+ /// The type is an Objective-C retainable pointer type that is qualified
+ /// with the ARC __weak qualifier.
+ PCK_ARCWeak,
+
+ /// The type is a struct containing a field whose type is neither
+ /// PCK_Trivial nor PCK_VolatileTrivial.
+ /// Note that a C++ struct type does not necessarily match this; C++ copying
+ /// semantics are too complex to express here, in part because they depend
+ /// on the exact constructor or assignment operator that is chosen by
+ /// overload resolution to do the copy.
+ PCK_Struct
+ };
+
+ /// Check if this is a non-trivial type that would cause a C struct
+ /// transitively containing this type to be non-trivial to copy and return the
+ /// kind.
+ PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const;
+
+ /// Check if this is a non-trivial type that would cause a C struct
+ /// transitively containing this type to be non-trivial to destructively
+ /// move and return the kind. Destructive move in this context is a C++-style
+ /// move in which the source object is placed in a valid but unspecified state
+ /// after it is moved, as opposed to a truly destructive move in which the
+ /// source object is placed in an uninitialized state.
+ PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const;
+
enum DestructionKind {
DK_none,
DK_cxx_destructor,
DK_objc_strong_lifetime,
- DK_objc_weak_lifetime
+ DK_objc_weak_lifetime,
+ DK_nontrivial_c_struct
};
/// Returns a nonzero value if objects of this type require
@@ -1204,7 +1281,7 @@ struct PointerLikeTypeTraits<clang::QualType> {
namespace clang {
-/// \brief Base class that is common to both the \c ExtQuals and \c Type
+/// 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 {
@@ -1212,14 +1289,14 @@ class ExtQualsTypeCommonBase {
friend class QualType;
friend class Type;
- /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or
+ /// The "base" type of an extended qualifiers type (\c ExtQuals) or
/// a self-referential pointer (for \c Type).
///
/// This pointer allows an efficient mapping from a QualType to its
/// underlying type pointer.
const Type *const BaseType;
- /// \brief The canonical type of this type. A QualType.
+ /// The canonical type of this type. A QualType.
QualType CanonicalType;
ExtQualsTypeCommonBase(const Type *baseType, QualType canon)
@@ -1300,25 +1377,25 @@ public:
/// This determines whether a member function's "this" object can be an
/// lvalue, rvalue, or neither.
enum RefQualifierKind {
- /// \brief No ref-qualifier was provided.
+ /// No ref-qualifier was provided.
RQ_None = 0,
- /// \brief An lvalue ref-qualifier was provided (\c &).
+ /// An lvalue ref-qualifier was provided (\c &).
RQ_LValue,
- /// \brief An rvalue ref-qualifier was provided (\c &&).
+ /// An rvalue ref-qualifier was provided (\c &&).
RQ_RValue
};
/// Which keyword(s) were used to create an AutoType.
enum class AutoTypeKeyword {
- /// \brief auto
+ /// auto
Auto,
- /// \brief decltype(auto)
+ /// decltype(auto)
DecltypeAuto,
- /// \brief __auto_type (GNU extension)
+ /// __auto_type (GNU extension)
GNUAutoType
};
@@ -1377,21 +1454,21 @@ private:
/// Whether this type is a variably-modified type (C99 6.7.5).
unsigned VariablyModified : 1;
- /// \brief Whether this type contains an unexpanded parameter pack
+ /// Whether this type contains an unexpanded parameter pack
/// (for C++11 variadic templates).
unsigned ContainsUnexpandedParameterPack : 1;
- /// \brief True if the cache (i.e. the bitfields here starting with
+ /// True if the cache (i.e. the bitfields here starting with
/// 'Cache') is valid.
mutable unsigned CacheValid : 1;
- /// \brief Linkage of this type.
+ /// Linkage of this type.
mutable unsigned CachedLinkage : 3;
- /// \brief Whether this type involves and local or unnamed types.
+ /// Whether this type involves and local or unnamed types.
mutable unsigned CachedLocalOrUnnamed : 1;
- /// \brief Whether this type comes from an AST file.
+ /// Whether this type comes from an AST file.
mutable unsigned FromAST : 1;
bool isCacheValid() const {
@@ -1446,7 +1523,7 @@ protected:
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
- unsigned ExtInfo : 11;
+ unsigned ExtInfo : 12;
/// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
@@ -1456,7 +1533,7 @@ protected:
/// cv-qualifier-seq, [...], are part of the function type.
unsigned TypeQuals : 4;
- /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+ /// The ref-qualifier associated with a \c FunctionProtoType.
///
/// This is a value of type \c RefQualifierKind.
unsigned RefQualifier : 2;
@@ -1513,6 +1590,7 @@ protected:
class VectorTypeBitfields {
friend class VectorType;
+ friend class DependentVectorType;
unsigned : NumTypeBits;
@@ -1561,7 +1639,7 @@ protected:
private:
template <class T> friend class TypePropertyCache;
- /// \brief Set whether this type comes from an AST file.
+ /// Set whether this type comes from an AST file.
void setFromAST(bool V = true) const {
TypeBits.FromAST = V;
}
@@ -1612,10 +1690,10 @@ public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); }
- /// \brief Whether this type comes from an AST file.
+ /// Whether this type comes from an AST file.
bool isFromAST() const { return TypeBits.FromAST; }
- /// \brief Whether this type is or contains an unexpanded parameter
+ /// Whether this type is or contains an unexpanded parameter
/// pack, used to support C++0x variadic templates.
///
/// A type that contains a parameter pack shall be expanded by the
@@ -1653,7 +1731,7 @@ public:
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
/// routine will need to determine if the size is actually required.
///
- /// \brief Def If non-null, and the type refers to some kind of declaration
+ /// Def If non-null, and the type refers to some kind of declaration
/// that can be completed (such as a C struct, C++ class, or Objective-C
/// class), will be set to the declaration.
bool isIncompleteType(NamedDecl **Def = nullptr) const;
@@ -1664,7 +1742,7 @@ public:
return !isFunctionType();
}
- /// \brief Determine whether this type is an object type.
+ /// Determine whether this type is an object type.
bool isObjectType() const {
// C++ [basic.types]p8:
// An object type is a (possibly cv-qualified) type that is not a
@@ -1706,9 +1784,13 @@ public:
/// isComplexIntegerType() can be used to test for complex integers.
bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
bool isEnumeralType() const;
+
+ /// Determine whether this type is a scoped enumeration type.
+ bool isScopedEnumeralType() const;
bool isBooleanType() const;
bool isCharType() const;
bool isWideCharType() const;
+ bool isChar8Type() const;
bool isChar16Type() const;
bool isChar32Type() const;
bool isAnyCharacterType() const;
@@ -1728,6 +1810,8 @@ public:
bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int.
bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half)
+ bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661
+ bool isFloat128Type() const;
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
bool isVoidType() const; // C99 6.2.5p19
@@ -1857,7 +1941,7 @@ public:
/// somehow depends on a template parameter (C++ [temp.dep.type]).
bool isDependentType() const { return TypeBits.Dependent; }
- /// \brief Determine whether this type is an instantiation-dependent type,
+ /// Determine whether this type is an instantiation-dependent type,
/// meaning that the type involves a template parameter (even if the
/// definition does not actually depend on the type substituted for that
/// template parameter).
@@ -1865,24 +1949,24 @@ public:
return TypeBits.InstantiationDependent;
}
- /// \brief Determine whether this type is an undeduced type, meaning that
+ /// Determine whether this type is an undeduced type, meaning that
/// it somehow involves a C++11 'auto' type or similar which has not yet been
/// deduced.
bool isUndeducedType() const;
- /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ /// Whether this type is a variably-modified type (C99 6.7.5).
bool isVariablyModifiedType() const { return TypeBits.VariablyModified; }
- /// \brief Whether this type involves a variable-length array type
+ /// Whether this type involves a variable-length array type
/// with a definite size.
bool hasSizedVLAType() const;
- /// \brief Whether this type is or contains a local or unnamed type.
+ /// Whether this type is or contains a local or unnamed type.
bool hasUnnamedOrLocalType() const;
bool isOverloadableType() const;
- /// \brief Determine wither this type is a C++ elaborated-type-specifier.
+ /// Determine wither this type is a C++ elaborated-type-specifier.
bool isElaboratedTypeSpecifier() const;
bool canDecayToPointerType() const;
@@ -1896,19 +1980,19 @@ public:
/// purpose of GC'ability
bool hasObjCPointerRepresentation() const;
- /// \brief Determine whether this type has an integer representation
+ /// Determine whether this type has an integer representation
/// of some sort, e.g., it is an integer type or a vector.
bool hasIntegerRepresentation() const;
- /// \brief Determine whether this type has an signed integer representation
+ /// Determine whether this type has an signed integer representation
/// of some sort, e.g., it is an signed integer type or a vector.
bool hasSignedIntegerRepresentation() const;
- /// \brief Determine whether this type has an unsigned integer representation
+ /// Determine whether this type has an unsigned integer representation
/// of some sort, e.g., it is an unsigned integer type or a vector.
bool hasUnsignedIntegerRepresentation() const;
- /// \brief Determine whether this type has a floating-point representation
+ /// Determine whether this type has a floating-point representation
/// of some sort, e.g., it is a floating-point type or a vector thereof.
bool hasFloatingRepresentation() const;
@@ -1928,18 +2012,21 @@ public:
const ObjCObjectPointerType *getAsObjCQualifiedClassType() const;
const ObjCObjectType *getAsObjCQualifiedInterfaceType() const;
- /// \brief Retrieves the CXXRecordDecl that this type refers to, either
+ /// Retrieves the CXXRecordDecl that this type refers to, either
/// because the type is a RecordType or because it is the injected-class-name
/// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const;
- /// \brief Retrieves the TagDecl that this type refers to, either
+ /// Retrieves the RecordDecl this type refers to.
+ RecordDecl *getAsRecordDecl() const;
+
+ /// Retrieves the TagDecl that this type refers to, either
/// because the type is a TagType or because it is the injected-class-name
/// type of a class template or class template partial specialization.
TagDecl *getAsTagDecl() const;
/// If this is a pointer or reference to a RecordType, return the
- /// CXXRecordDecl that that type refers to.
+ /// CXXRecordDecl that the type refers to.
///
/// If this is not a pointer or reference, or the type being pointed to does
/// not refer to a CXXRecordDecl, returns NULL.
@@ -2037,6 +2124,26 @@ public:
/// enumeration types whose underlying type is a unsigned integer type.
bool isUnsignedIntegerOrEnumerationType() const;
+ /// Return true if this is a fixed point type according to
+ /// ISO/IEC JTC1 SC22 WG14 N1169.
+ bool isFixedPointType() const;
+
+ /// Return true if this is a saturated fixed point type according to
+ /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned.
+ bool isSaturatedFixedPointType() const;
+
+ /// Return true if this is a saturated fixed point type according to
+ /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned.
+ bool isUnsaturatedFixedPointType() const;
+
+ /// Return true if this is a fixed point type that is signed according
+ /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated.
+ bool isSignedFixedPointType() const;
+
+ /// Return true if this is a fixed point type that is unsigned according
+ /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated.
+ bool isUnsignedFixedPointType() const;
+
/// Return true if this is not a variable sized type,
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types.
@@ -2113,16 +2220,16 @@ public:
void dump(llvm::raw_ostream &OS) const;
};
-/// \brief This will check for a TypedefType by removing any existing sugar
+/// This will check for a TypedefType by removing any existing sugar
/// until it reaches a TypedefType or a non-sugared type.
template <> const TypedefType *Type::getAs() const;
-/// \brief This will check for a TemplateSpecializationType by removing any
+/// This will check for a TemplateSpecializationType by removing any
/// existing sugar until it reaches a TemplateSpecializationType or a
/// non-sugared type.
template <> const TemplateSpecializationType *Type::getAs() const;
-/// \brief This will check for an AttributedType by removing any existing sugar
+/// This will check for an AttributedType by removing any existing sugar
/// until it reaches an AttributedType or a non-sugared type.
template <> const AttributedType *Type::getAs() const;
@@ -2152,7 +2259,9 @@ public:
#include "clang/AST/BuiltinTypes.def"
};
-public:
+private:
+ friend class ASTContext; // ASTContext creates these.
+
BuiltinType(Kind K)
: Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
/*InstantiationDependent=*/(K == Dependent),
@@ -2161,6 +2270,7 @@ public:
BuiltinTypeBits.Kind = K;
}
+public:
Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
StringRef getName(const PrintingPolicy &Policy) const;
@@ -2637,13 +2747,13 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- /// \brief Determine the number of bits required to address a member of
+ /// 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,
QualType ElementType,
const llvm::APInt &NumElements);
- /// \brief Determine the maximum number of active bits that an array's size
+ /// Determine the maximum number of active bits that an array's size
/// can require, which limits the maximum size of the array.
static unsigned getMaxSizeBits(const ASTContext &Context);
@@ -2774,7 +2884,7 @@ class DependentSizedArrayType : public ArrayType {
const ASTContext &Context;
- /// \brief An assignment expression that will instantiate to the
+ /// An assignment expression that will instantiate to the
/// size of the array.
///
/// The expression itself might be null, in which case the array
@@ -2819,7 +2929,7 @@ public:
};
/// Represents an extended address space qualifier where the input address space
-/// value is dependent. Non-dependent address spaces are not represented with a
+/// 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:
@@ -2838,7 +2948,7 @@ class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode {
SourceLocation loc;
DependentAddressSpaceType(const ASTContext &Context, QualType PointeeType,
- QualType can, Expr *AddrSpaceExpr,
+ QualType can, Expr *AddrSpaceExpr,
SourceLocation loc);
public:
@@ -2979,6 +3089,51 @@ public:
}
};
+/// Represents a vector type where either the type or size is dependent.
+////
+/// For example:
+/// \code
+/// template<typename T, int Size>
+/// class vector {
+/// typedef T __attribute__((vector_size(Size))) type;
+/// }
+/// \endcode
+class DependentVectorType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
+ const ASTContext &Context;
+ QualType ElementType;
+ Expr *SizeExpr;
+ SourceLocation Loc;
+
+ DependentVectorType(const ASTContext &Context, QualType ElementType,
+ QualType CanonType, Expr *SizeExpr,
+ SourceLocation Loc, VectorType::VectorKind vecKind);
+
+public:
+ Expr *getSizeExpr() const { return SizeExpr; }
+ QualType getElementType() const { return ElementType; }
+ SourceLocation getAttributeLoc() const { return Loc; }
+ VectorType::VectorKind getVectorKind() const {
+ return VectorType::VectorKind(VectorTypeBits.VecKind);
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentVector;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType ElementType, const Expr *SizeExpr,
+ VectorType::VectorKind VecKind);
+};
+
/// ExtVectorType - Extended vector type. This type is created using
/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This
@@ -3081,24 +3236,24 @@ public:
class ExtInfo {
friend class FunctionType;
- // Feel free to rearrange or add bits, but if you go over 11,
+ // Feel free to rearrange or add bits, but if you go over 12,
// you'll need to adjust both the Bits field below and
// Type::FunctionTypeBitfields.
- // | CC |noreturn|produces|nocallersavedregs|regparm|
- // |0 .. 4| 5 | 6 | 7 |8 .. 10|
+ // | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|
+ // |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 |
//
// regparm is either 0 (no regparm attribute) or the regparm value+1.
enum { CallConvMask = 0x1F };
enum { NoReturnMask = 0x20 };
enum { ProducesResultMask = 0x40 };
enum { NoCallerSavedRegsMask = 0x80 };
+ enum { NoCfCheckMask = 0x800 };
enum {
RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask |
- NoCallerSavedRegsMask),
+ NoCallerSavedRegsMask | NoCfCheckMask),
RegParmOffset = 8
}; // Assumed to be the last field
-
uint16_t Bits = CC_C;
ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
@@ -3107,12 +3262,13 @@ public:
// Constructor with no defaults. Use this when you know that you
// have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
- bool producesResult, bool noCallerSavedRegs) {
+ bool producesResult, bool noCallerSavedRegs, bool NoCfCheck) {
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
(producesResult ? ProducesResultMask : 0) |
(noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
- (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0);
+ (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) |
+ (NoCfCheck ? NoCfCheckMask : 0);
}
// Constructor with all defaults. Use when for example creating a
@@ -3126,10 +3282,11 @@ public:
bool getNoReturn() const { return Bits & NoReturnMask; }
bool getProducesResult() const { return Bits & ProducesResultMask; }
bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; }
+ bool getNoCfCheck() const { return Bits & NoCfCheckMask; }
bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; }
unsigned getRegParm() const {
- unsigned RegParm = Bits >> RegParmOffset;
+ unsigned RegParm = (Bits & RegParmMask) >> RegParmOffset;
if (RegParm > 0)
--RegParm;
return RegParm;
@@ -3168,6 +3325,13 @@ public:
return ExtInfo(Bits & ~NoCallerSavedRegsMask);
}
+ ExtInfo withNoCfCheck(bool noCfCheck) const {
+ if (noCfCheck)
+ return ExtInfo(Bits | NoCfCheckMask);
+ else
+ return ExtInfo(Bits & ~NoCfCheckMask);
+ }
+
ExtInfo withRegParm(unsigned RegParm) const {
assert(RegParm < 7 && "Invalid regparm value");
return ExtInfo((Bits & ~RegParmMask) |
@@ -3214,7 +3378,7 @@ public:
bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; }
bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; }
- /// \brief Determine the type of an expression that calls a function of
+ /// Determine the type of an expression that calls a function of
/// this type.
QualType getCallResultType(const ASTContext &Context) const {
return getReturnType().getNonLValueExprType(Context);
@@ -3367,7 +3531,7 @@ public:
/// Explicitly-specified list of exception types.
ArrayRef<QualType> Exceptions;
- /// Noexcept expression, if this is EST_ComputedNoexcept.
+ /// Noexcept expression, if this is a computed noexcept specification.
Expr *NoexceptExpr = nullptr;
/// The function whose exception specification this is, for
@@ -3409,7 +3573,7 @@ public:
private:
friend class ASTContext; // ASTContext creates these.
- /// \brief Determine whether there are any argument types that
+ /// Determine whether there are any argument types that
/// contain an unexpanded parameter pack.
static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray,
unsigned numArgs) {
@@ -3464,26 +3628,41 @@ private:
assert(hasExtParameterInfos());
// Find the end of the exception specification.
- const char *ptr = reinterpret_cast<const char *>(exception_begin());
+ const auto *ptr = reinterpret_cast<const char *>(exception_begin());
ptr += getExceptionSpecSize();
return reinterpret_cast<const ExtParameterInfo *>(ptr);
}
- size_t getExceptionSpecSize() const {
- switch (getExceptionSpecType()) {
- case EST_None: return 0;
- case EST_DynamicNone: return 0;
- case EST_MSAny: return 0;
- case EST_BasicNoexcept: return 0;
- case EST_Unparsed: return 0;
- case EST_Dynamic: return getNumExceptions() * sizeof(QualType);
- case EST_ComputedNoexcept: return sizeof(Expr*);
- case EST_Uninstantiated: return 2 * sizeof(FunctionDecl*);
- case EST_Unevaluated: return sizeof(FunctionDecl*);
+ static size_t getExceptionSpecSize(ExceptionSpecificationType EST,
+ unsigned NumExceptions) {
+ switch (EST) {
+ case EST_None:
+ case EST_DynamicNone:
+ case EST_MSAny:
+ case EST_BasicNoexcept:
+ case EST_Unparsed:
+ return 0;
+
+ case EST_Dynamic:
+ return NumExceptions * sizeof(QualType);
+
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
+ return sizeof(Expr *);
+
+ case EST_Uninstantiated:
+ return 2 * sizeof(FunctionDecl *);
+
+ case EST_Unevaluated:
+ return sizeof(FunctionDecl *);
}
llvm_unreachable("bad exception specification kind");
}
+ size_t getExceptionSpecSize() const {
+ return getExceptionSpecSize(getExceptionSpecType(), getNumExceptions());
+ }
public:
unsigned getNumParams() const { return NumParams; }
@@ -3507,7 +3686,7 @@ public:
EPI.RefQualifier = getRefQualifier();
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
EPI.ExceptionSpec.Exceptions = exceptions();
- } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
+ } else if (isComputedNoexcept(EPI.ExceptionSpec.Type)) {
EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr();
} else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
@@ -3547,39 +3726,19 @@ public:
/// spec.
bool hasInstantiationDependentExceptionSpec() const;
- /// Result type of getNoexceptSpec().
- enum NoexceptResult {
- /// 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; }
QualType getExceptionType(unsigned i) const {
assert(i < NumExceptions && "Invalid exception number!");
return exception_begin()[i];
}
Expr *getNoexceptExpr() const {
- if (getExceptionSpecType() != EST_ComputedNoexcept)
+ if (!isComputedNoexcept(getExceptionSpecType()))
return nullptr;
// NoexceptExpr sits where the arguments end.
return *reinterpret_cast<Expr *const *>(param_type_end());
}
- /// \brief If this function type has an exception specification which hasn't
+ /// If this function type has an exception specification which hasn't
/// been determined yet (either because it has not been evaluated or because
/// it has not been instantiated), this is the function whose exception
/// specification is represented by this type.
@@ -3590,7 +3749,7 @@ public:
return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0];
}
- /// \brief If this function type has an uninstantiated exception
+ /// If this function type has an uninstantiated exception
/// specification, this is the function whose exception specification
/// should be instantiated to find the exception specification for
/// this type.
@@ -3602,14 +3761,14 @@ public:
/// Determine whether this function type has a non-throwing exception
/// specification.
- CanThrowResult canThrow(const ASTContext &Ctx) const;
+ CanThrowResult canThrow() const;
/// Determine whether this function type has a non-throwing exception
/// specification. If this depends on template arguments, returns
/// \c ResultIfDependent.
- bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const {
- return ResultIfDependent ? canThrow(Ctx) != CT_Can
- : canThrow(Ctx) == CT_Cannot;
+ bool isNothrow(bool ResultIfDependent = false) const {
+ return ResultIfDependent ? canThrow() != CT_Can
+ : canThrow() == CT_Cannot;
}
bool isVariadic() const { return Variadic; }
@@ -3719,7 +3878,7 @@ public:
bool Canonical);
};
-/// \brief Represents the dependent type named by a dependently-scoped
+/// Represents the dependent type named by a dependently-scoped
/// typename using declaration, e.g.
/// using typename Base<T>::foo;
///
@@ -3790,16 +3949,16 @@ protected:
public:
Expr *getUnderlyingExpr() const { return TOExpr; }
- /// \brief Remove a single level of sugar.
+ /// Remove a single level of sugar.
QualType desugar() const;
- /// \brief Returns whether this type directly provides sugar.
+ /// Returns whether this type directly provides sugar.
bool isSugared() const;
static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; }
};
-/// \brief Internal representation of canonical, dependent
+/// Internal representation of canonical, dependent
/// `typeof(expr)` types.
///
/// This class is used internally by the ASTContext to manage
@@ -3839,10 +3998,10 @@ class TypeOfType : public Type {
public:
QualType getUnderlyingType() const { return TOType; }
- /// \brief Remove a single level of sugar.
+ /// Remove a single level of sugar.
QualType desugar() const { return getUnderlyingType(); }
- /// \brief Returns whether this type directly provides sugar.
+ /// Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
@@ -3862,16 +4021,16 @@ public:
Expr *getUnderlyingExpr() const { return E; }
QualType getUnderlyingType() const { return UnderlyingType; }
- /// \brief Remove a single level of sugar.
+ /// Remove a single level of sugar.
QualType desugar() const;
- /// \brief Returns whether this type directly provides sugar.
+ /// Returns whether this type directly provides sugar.
bool isSugared() const;
static bool classof(const Type *T) { return T->getTypeClass() == Decltype; }
};
-/// \brief Internal representation of canonical, dependent
+/// Internal representation of canonical, dependent
/// decltype(expr) types.
///
/// This class is used internally by the ASTContext to manage
@@ -3927,7 +4086,7 @@ public:
}
};
-/// \brief Internal representation of canonical, dependent
+/// Internal representation of canonical, dependent
/// __underlying_type(type) types.
///
/// This class is used internally by the ASTContext to manage
@@ -4054,6 +4213,7 @@ public:
// No operand.
attr_noreturn,
+ attr_nocf_check,
attr_cdecl,
attr_fastcall,
attr_stdcall,
@@ -4077,6 +4237,7 @@ public:
attr_null_unspecified,
attr_objc_kindof,
attr_objc_inert_unsafe_unretained,
+ attr_lifetimebound,
};
private:
@@ -4246,7 +4407,7 @@ public:
}
};
-/// \brief Represents the result of substituting a type for a template
+/// Represents the result of substituting a type for a template
/// type parameter.
///
/// Within an instantiated template, all template type parameters have
@@ -4297,7 +4458,7 @@ public:
}
};
-/// \brief Represents the result of substituting a set of types for a template
+/// Represents the result of substituting a set of types for a template
/// type parameter pack.
///
/// When a pack expansion in the source code contains multiple parameter packs
@@ -4312,14 +4473,14 @@ public:
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
friend class ASTContext;
- /// \brief The original type parameter.
+ /// The original type parameter.
const TemplateTypeParmType *Replaced;
- /// \brief A pointer to the set of template arguments that this
+ /// A pointer to the set of template arguments that this
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
- /// \brief The number of template arguments in \c Arguments.
+ /// The number of template arguments in \c Arguments.
unsigned NumArguments;
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
@@ -4349,7 +4510,7 @@ public:
}
};
-/// \brief Common base class for placeholders for types that get replaced by
+/// Common base class for placeholders for types that get replaced by
/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced
/// class template types, and (eventually) constrained type names from the C++
/// Concepts TS.
@@ -4382,7 +4543,7 @@ public:
bool isSugared() const { return !isCanonicalUnqualified(); }
QualType desugar() const { return getCanonicalTypeInternal(); }
- /// \brief Get the type deduced for this placeholder type, or null if it's
+ /// Get the type deduced for this placeholder type, or null if it's
/// either not been deduced or was deduced to a dependent type.
QualType getDeducedType() const {
return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
@@ -4397,7 +4558,7 @@ public:
}
};
-/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
+/// Represents a C++11 auto or C++14 decltype(auto) type.
class AutoType : public DeducedType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
@@ -4433,7 +4594,7 @@ public:
}
};
-/// \brief Represents a C++17 deduced template specialization type.
+/// Represents a C++17 deduced template specialization type.
class DeducedTemplateSpecializationType : public DeducedType,
public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
@@ -4470,7 +4631,7 @@ public:
}
};
-/// \brief Represents a type template specialization; the template
+/// Represents a type template specialization; the template
/// must be a class template, a type alias template, or a template
/// template parameter. A template which cannot be resolved to one of
/// these, e.g. because it is written with a dependent scope
@@ -4490,7 +4651,7 @@ public:
/// TemplateArguments, followed by a QualType representing the
/// non-canonical aliased type when the template is a type alias
/// template.
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
+class alignas(8) TemplateSpecializationType
: public Type,
public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
@@ -4530,7 +4691,7 @@ public:
return isa<InjectedClassNameType>(getCanonicalTypeInternal());
}
- /// \brief Determine if this template specialization type is for a type alias
+ /// Determine if this template specialization type is for a type alias
/// template that has been substituted.
///
/// Nearly every template specialization type whose template is an alias
@@ -4599,7 +4760,7 @@ public:
}
};
-/// \brief Print a template argument list, including the '<' and '>'
+/// Print a template argument list, including the '<' and '>'
/// enclosing the template arguments.
void printTemplateArgumentList(raw_ostream &OS,
ArrayRef<TemplateArgument> Args,
@@ -4682,47 +4843,47 @@ public:
}
};
-/// \brief The kind of a tag type.
+/// The kind of a tag type.
enum TagTypeKind {
- /// \brief The "struct" keyword.
+ /// The "struct" keyword.
TTK_Struct,
- /// \brief The "__interface" keyword.
+ /// The "__interface" keyword.
TTK_Interface,
- /// \brief The "union" keyword.
+ /// The "union" keyword.
TTK_Union,
- /// \brief The "class" keyword.
+ /// The "class" keyword.
TTK_Class,
- /// \brief The "enum" keyword.
+ /// The "enum" keyword.
TTK_Enum
};
-/// \brief The elaboration keyword that precedes a qualified type name or
+/// The elaboration keyword that precedes a qualified type name or
/// introduces an elaborated-type-specifier.
enum ElaboratedTypeKeyword {
- /// \brief The "struct" keyword introduces the elaborated-type-specifier.
+ /// The "struct" keyword introduces the elaborated-type-specifier.
ETK_Struct,
- /// \brief The "__interface" keyword introduces the elaborated-type-specifier.
+ /// The "__interface" keyword introduces the elaborated-type-specifier.
ETK_Interface,
- /// \brief The "union" keyword introduces the elaborated-type-specifier.
+ /// The "union" keyword introduces the elaborated-type-specifier.
ETK_Union,
- /// \brief The "class" keyword introduces the elaborated-type-specifier.
+ /// The "class" keyword introduces the elaborated-type-specifier.
ETK_Class,
- /// \brief The "enum" keyword introduces the elaborated-type-specifier.
+ /// The "enum" keyword introduces the elaborated-type-specifier.
ETK_Enum,
- /// \brief The "typename" keyword precedes the qualified type name, e.g.,
+ /// The "typename" keyword precedes the qualified type name, e.g.,
/// \c typename T::type.
ETK_Typename,
- /// \brief No keyword precedes the qualified type name.
+ /// No keyword precedes the qualified type name.
ETK_None
};
@@ -4773,7 +4934,7 @@ public:
static CannotCastToThisType classof(const Type *);
};
-/// \brief Represents a type that was referred to using an elaborated type
+/// Represents a type that was referred to using an elaborated type
/// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type,
/// or both.
///
@@ -4790,14 +4951,18 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
/// The type that this qualified name refers to.
QualType NamedType;
+ /// The (re)declaration of this tag type owned by this occurrence, or nullptr
+ /// if none.
+ TagDecl *OwnedTagDecl;
+
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
- QualType NamedType, QualType CanonType)
+ QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl)
: TypeWithKeyword(Keyword, Elaborated, CanonType,
NamedType->isDependentType(),
NamedType->isInstantiationDependentType(),
NamedType->isVariablyModifiedType(),
NamedType->containsUnexpandedParameterPack()),
- NNS(NNS), NamedType(NamedType) {
+ NNS(NNS), NamedType(NamedType), OwnedTagDecl(OwnedTagDecl) {
assert(!(Keyword == ETK_None && NNS == nullptr) &&
"ElaboratedType cannot have elaborated type keyword "
"and name qualifier both null.");
@@ -4818,15 +4983,21 @@ public:
/// Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
+ /// Return the (re)declaration of this type owned by this occurrence of this
+ /// type, or nullptr if none.
+ TagDecl *getOwnedTagDecl() const { return OwnedTagDecl; }
+
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getKeyword(), NNS, NamedType);
+ Profile(ID, getKeyword(), NNS, NamedType, OwnedTagDecl);
}
static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, QualType NamedType) {
+ NestedNameSpecifier *NNS, QualType NamedType,
+ TagDecl *OwnedTagDecl) {
ID.AddInteger(Keyword);
ID.AddPointer(NNS);
NamedType.Profile(ID);
+ ID.AddPointer(OwnedTagDecl);
}
static bool classof(const Type *T) {
@@ -4834,7 +5005,7 @@ public:
}
};
-/// \brief Represents a qualified type name for which the type name is
+/// Represents a qualified type name for which the type name is
/// dependent.
///
/// DependentNameType represents a class of dependent types that involve a
@@ -4849,10 +5020,10 @@ public:
class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
- /// \brief The nested name specifier containing the qualifier.
+ /// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
- /// \brief The type that this typename specifier refers to.
+ /// The type that this typename specifier refers to.
const IdentifierInfo *Name;
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
@@ -4898,7 +5069,7 @@ public:
/// Represents a template specialization type whose template cannot be
/// resolved, e.g.
/// A<T>::template B<T>
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
+class alignas(8) DependentTemplateSpecializationType
: public TypeWithKeyword,
public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
@@ -4909,7 +5080,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
/// The identifier of the template.
const IdentifierInfo *Name;
- /// \brief The number of template arguments named in this class template
+ /// The number of template arguments named in this class template
/// specialization.
unsigned NumArgs;
@@ -4931,12 +5102,12 @@ public:
NestedNameSpecifier *getQualifier() const { return NNS; }
const IdentifierInfo *getIdentifier() const { return Name; }
- /// \brief Retrieve the template arguments.
+ /// Retrieve the template arguments.
const TemplateArgument *getArgs() const {
return getArgBuffer();
}
- /// \brief Retrieve the number of template arguments.
+ /// Retrieve the number of template arguments.
unsigned getNumArgs() const { return NumArgs; }
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
@@ -4969,7 +5140,7 @@ public:
}
};
-/// \brief Represents a pack expansion of types.
+/// Represents a pack expansion of types.
///
/// Pack expansions are part of C++11 variadic templates. A pack
/// expansion contains a pattern, which itself contains one or more
@@ -4994,10 +5165,10 @@ public:
class PackExpansionType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
- /// \brief The pattern of the pack expansion.
+ /// The pattern of the pack expansion.
QualType Pattern;
- /// \brief The number of expansions that this pack expansion will
+ /// The number of expansions that this pack expansion will
/// generate when substituted (+1), or indicates that
///
/// This field will only have a non-zero value when some of the parameter
@@ -5015,12 +5186,12 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {}
public:
- /// \brief Retrieve the pattern of this pack expansion, which is the
+ /// Retrieve the pattern of this pack expansion, which is the
/// type that will be repeatedly instantiated when instantiating the
/// pack expansion itself.
QualType getPattern() const { return Pattern; }
- /// \brief Retrieve the number of expansions that this pack expansion will
+ /// Retrieve the number of expansions that this pack expansion will
/// generate, if known.
Optional<unsigned> getNumExpansions() const {
if (NumExpansions)
@@ -5169,7 +5340,7 @@ public:
/// with base C and no protocols.
///
/// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P].
-/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no
+/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no
/// protocol list.
/// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*',
/// and protocol list [P].
@@ -5418,8 +5589,8 @@ public:
inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
QualType baseType = getBaseType();
- while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) {
- if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT))
+ while (const auto *ObjT = baseType->getAs<ObjCObjectType>()) {
+ if (const auto *T = dyn_cast<ObjCInterfaceType>(ObjT))
return T->getDecl();
baseType = ObjT->getBaseType();
@@ -5801,7 +5972,7 @@ inline QualType QualType::getUnqualifiedType() const {
return QualType(getSplitUnqualifiedTypeImpl(*this).Ty, 0);
}
-
+
inline SplitQualType QualType::getSplitUnqualifiedType() const {
if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
return split();
@@ -5841,10 +6012,10 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const {
}
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
- if (const PointerType *PT = t.getAs<PointerType>()) {
- if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>())
+ if (const auto *PT = t.getAs<PointerType>()) {
+ if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>())
return FT->getExtInfo();
- } else if (const FunctionType *FT = t.getAs<FunctionType>())
+ } else if (const auto *FT = t.getAs<FunctionType>())
return FT->getExtInfo();
return FunctionType::ExtInfo();
@@ -5889,7 +6060,7 @@ inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const {
/// analysis, the expression designates the object or function
/// denoted by the reference, and the expression is an lvalue.
inline QualType QualType::getNonReferenceType() const {
- if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>())
+ if (const auto *RefType = (*this)->getAs<ReferenceType>())
return RefType->getPointeeType();
else
return *this;
@@ -5964,7 +6135,7 @@ inline bool Type::isRValueReferenceType() const {
}
inline bool Type::isFunctionPointerType() const {
- if (const PointerType *T = getAs<PointerType>())
+ if (const auto *T = getAs<PointerType>())
return T->getPointeeType()->isFunctionType();
else
return false;
@@ -5975,14 +6146,14 @@ inline bool Type::isMemberPointerType() const {
}
inline bool Type::isMemberFunctionPointerType() const {
- if (const MemberPointerType* T = getAs<MemberPointerType>())
+ if (const auto *T = getAs<MemberPointerType>())
return T->isMemberFunctionPointer();
else
return false;
}
inline bool Type::isMemberDataPointerType() const {
- if (const MemberPointerType* T = getAs<MemberPointerType>())
+ if (const auto *T = getAs<MemberPointerType>())
return T->isMemberDataPointer();
else
return false;
@@ -6054,31 +6225,31 @@ inline bool Type::isAtomicType() const {
}
inline bool Type::isObjCQualifiedIdType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedIdType();
return false;
}
inline bool Type::isObjCQualifiedClassType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedClassType();
return false;
}
inline bool Type::isObjCIdType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCIdType();
return false;
}
inline bool Type::isObjCClassType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCClassType();
return false;
}
inline bool Type::isObjCSelType() const {
- if (const PointerType *OPT = getAs<PointerType>())
+ if (const auto *OPT = getAs<PointerType>())
return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel);
return false;
}
@@ -6141,13 +6312,13 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const {
}
inline bool Type::isPlaceholderType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
return BT->isPlaceholderType();
return false;
}
inline const BuiltinType *Type::getAsPlaceholderType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
if (BT->isPlaceholderType())
return BT;
return nullptr;
@@ -6155,32 +6326,44 @@ inline const BuiltinType *Type::getAsPlaceholderType() const {
inline bool Type::isSpecificPlaceholderType(unsigned K) const {
assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K));
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
return (BT->getKind() == (BuiltinType::Kind) K);
return false;
}
inline bool Type::isNonOverloadPlaceholderType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
return BT->isNonOverloadPlaceholderType();
return false;
}
inline bool Type::isVoidType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Void;
return false;
}
inline bool Type::isHalfType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Half;
// FIXME: Should we allow complex __fp16? Probably not.
return false;
}
+inline bool Type::isFloat16Type() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Float16;
+ return false;
+}
+
+inline bool Type::isFloat128Type() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Float128;
+ return false;
+}
+
inline bool Type::isNullPtrType() const {
- if (const BuiltinType *BT = getAs<BuiltinType>())
+ if (const auto *BT = getAs<BuiltinType>())
return BT->getKind() == BuiltinType::NullPtr;
return false;
}
@@ -6189,7 +6372,7 @@ bool IsEnumDeclComplete(EnumDecl *);
bool IsEnumDeclScoped(EnumDecl *);
inline bool Type::isIntegerType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
@@ -6201,8 +6384,46 @@ inline bool Type::isIntegerType() const {
return false;
}
+inline bool Type::isFixedPointType() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ return BT->getKind() >= BuiltinType::ShortAccum &&
+ BT->getKind() <= BuiltinType::SatULongFract;
+ }
+ return false;
+}
+
+inline bool Type::isSaturatedFixedPointType() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ return BT->getKind() >= BuiltinType::SatShortAccum &&
+ BT->getKind() <= BuiltinType::SatULongFract;
+ }
+ return false;
+}
+
+inline bool Type::isUnsaturatedFixedPointType() const {
+ return isFixedPointType() && !isSaturatedFixedPointType();
+}
+
+inline bool Type::isSignedFixedPointType() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ return ((BT->getKind() >= BuiltinType::ShortAccum &&
+ BT->getKind() <= BuiltinType::LongAccum) ||
+ (BT->getKind() >= BuiltinType::ShortFract &&
+ BT->getKind() <= BuiltinType::LongFract) ||
+ (BT->getKind() >= BuiltinType::SatShortAccum &&
+ BT->getKind() <= BuiltinType::SatLongAccum) ||
+ (BT->getKind() >= BuiltinType::SatShortFract &&
+ BT->getKind() <= BuiltinType::SatLongFract));
+ }
+ return false;
+}
+
+inline bool Type::isUnsignedFixedPointType() const {
+ return isFixedPointType() && !isSignedFixedPointType();
+}
+
inline bool Type::isScalarType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() > BuiltinType::Void &&
BT->getKind() <= BuiltinType::NullPtr;
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
@@ -6217,20 +6438,20 @@ inline bool Type::isScalarType() const {
}
inline bool Type::isIntegralOrEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
// Check for a complete enum type; incomplete enum types are not properly an
// enumeration type in the sense required here.
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return IsEnumDeclComplete(ET->getDecl());
- return false;
+ return false;
}
inline bool Type::isBooleanType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Bool;
return false;
}
@@ -6240,13 +6461,13 @@ inline bool Type::isUndeducedType() const {
return DT && !DT->isDeduced();
}
-/// \brief Determines whether this is a type for which one can define
+/// Determines whether this is a type for which one can define
/// an overloaded operator.
inline bool Type::isOverloadableType() const {
return isDependentType() || isRecordType() || isEnumeralType();
}
-/// \brief Determines whether this type can decay to a pointer type.
+/// Determines whether this type can decay to a pointer type.
inline bool Type::canDecayToPointerType() const {
return isFunctionType() || isArrayType();
}
@@ -6307,7 +6528,7 @@ template <typename T> const T *Type::getAs() const {
"ArrayType cannot be used with getAs!");
// If this is directly a T type, return it.
- if (const T *Ty = dyn_cast<T>(this))
+ if (const auto *Ty = dyn_cast<T>(this))
return Ty;
// If the canonical form of this type isn't the right kind, reject it.
@@ -6323,7 +6544,7 @@ template <typename T> const T *Type::getAsAdjusted() const {
static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!");
// If this is directly a T type, return it.
- if (const T *Ty = dyn_cast<T>(this))
+ if (const auto *Ty = dyn_cast<T>(this))
return Ty;
// If the canonical form of this type isn't the right kind, reject it.
@@ -6353,7 +6574,7 @@ template <typename T> const T *Type::getAsAdjusted() const {
inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
// If this is directly an array type, return it.
- if (const ArrayType *arr = dyn_cast<ArrayType>(this))
+ if (const auto *arr = dyn_cast<ArrayType>(this))
return arr;
// If the canonical form of this type isn't the right kind, reject it.
@@ -6369,14 +6590,14 @@ template <typename T> const T *Type::castAs() const {
static_assert(!TypeIsArrayType<T>::value,
"ArrayType cannot be used with castAs!");
- if (const T *ty = dyn_cast<T>(this)) return ty;
+ if (const auto *ty = dyn_cast<T>(this)) return ty;
assert(isa<T>(CanonicalType));
return cast<T>(getUnqualifiedDesugaredType());
}
inline const ArrayType *Type::castAsArrayTypeUnsafe() const {
assert(isa<ArrayType>(CanonicalType));
- if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr;
+ if (const auto *arr = dyn_cast<ArrayType>(this)) return arr;
return cast<ArrayType>(getUnqualifiedDesugaredType());
}
@@ -6396,6 +6617,12 @@ QualType DecayedType::getPointeeType() const {
return cast<PointerType>(Decayed)->getPointeeType();
}
+// Get the decimal string representation of a fixed point type, represented
+// as a scaled integer.
+void FixedPointValueToString(SmallVectorImpl<char> &Str,
+ const llvm::APSInt &Val,
+ unsigned Scale, unsigned Radix);
+
} // namespace clang
#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 b805160a2780..c69f4aa4abcf 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::TypeLoc interface and its subclasses.
+/// Defines the clang::TypeLoc interface and its subclasses.
//
//===----------------------------------------------------------------------===//
@@ -49,7 +49,7 @@ class UnresolvedUsingTypenameDecl;
class Class##TypeLoc;
#include "clang/AST/TypeLocNodes.def"
-/// \brief Base wrapper for a particular "section" of type source info.
+/// Base wrapper for a particular "section" of type source info.
///
/// A client should use the TypeLoc subclasses through castAs()/getAs()
/// in order to get at the actual information.
@@ -67,7 +67,7 @@ public:
TypeLoc(const Type *ty, void *opaqueData)
: Ty(ty), Data(opaqueData) {}
- /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc
+ /// Convert to the specified TypeLoc type, asserting that this TypeLoc
/// is of the desired type.
///
/// \pre T::isKind(*this)
@@ -80,21 +80,21 @@ public:
return t;
}
- /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if
+ /// Convert to the specified TypeLoc type, returning a null TypeLoc if
/// this TypeLoc is not of the desired type.
template<typename T>
T getAs() const {
if (!T::isKind(*this))
- return T();
+ return {};
T t;
TypeLoc& tl = t;
tl = *this;
return t;
}
- /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if
- /// this TypeLock is not of the desired type. It will consider type
- /// adjustments from a type that wad written as a T to another type that is
+ /// Convert to the specified TypeLoc type, returning a null TypeLoc if
+ /// this TypeLoc is not of the desired type. It will consider type
+ /// adjustments from a type that was written as a T to another type that is
/// still canonically a T (ignores parens, attributes, elaborated types, etc).
template <typename T>
T getAsAdjusted() const;
@@ -118,14 +118,14 @@ public:
bool isNull() const { return !Ty; }
explicit operator bool() const { return Ty; }
- /// \brief Returns the size of type source info data block for the given type.
+ /// Returns the size of type source info data block for the given type.
static unsigned getFullDataSizeForType(QualType Ty);
- /// \brief Returns the alignment of type source info data block for
+ /// Returns the alignment of type source info data block for
/// the given type.
static unsigned getLocalAlignmentForType(QualType Ty);
- /// \brief Get the type for which this source info wrapper provides
+ /// Get the type for which this source info wrapper provides
/// information.
QualType getType() const {
return QualType::getFromOpaquePtr(Ty);
@@ -135,18 +135,18 @@ public:
return QualType::getFromOpaquePtr(Ty).getTypePtr();
}
- /// \brief Get the pointer where source information is stored.
+ /// Get the pointer where source information is stored.
void *getOpaqueData() const {
return Data;
}
- /// \brief Get the begin source location.
+ /// Get the begin source location.
SourceLocation getBeginLoc() const;
- /// \brief Get the end source location.
+ /// Get the end source location.
SourceLocation getEndLoc() const;
- /// \brief Get the full source range.
+ /// Get the full source range.
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getBeginLoc(), getEndLoc());
}
@@ -154,28 +154,28 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
- /// \brief Get the local source range.
+ /// Get the local source range.
SourceRange getLocalSourceRange() const {
return getLocalSourceRangeImpl(*this);
}
- /// \brief Returns the size of the type source info data block.
+ /// Returns the size of the type source info data block.
unsigned getFullDataSize() const {
return getFullDataSizeForType(getType());
}
- /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
+ /// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
TypeLoc getNextTypeLoc() const {
return getNextTypeLocImpl(*this);
}
- /// \brief Skips past any qualifiers, if this is qualified.
+ /// Skips past any qualifiers, if this is qualified.
UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header
TypeLoc IgnoreParens() const;
- /// \brief Find a type with the location of an explicit type qualifier.
+ /// Find a type with the location of an explicit type qualifier.
///
/// The result, if non-null, will be one of:
/// QualifiedTypeLoc
@@ -183,7 +183,7 @@ public:
/// AttributedTypeLoc, for those type attributes that behave as qualifiers
TypeLoc findExplicitQualifierLoc() const;
- /// \brief Initializes this to state that every location in this
+ /// Initializes this to state that every location in this
/// type is the given location.
///
/// This method exists to provide a simple transition for code that
@@ -192,14 +192,14 @@ public:
initializeImpl(Context, *this, Loc);
}
- /// \brief Initializes this by copying its information from another
+ /// Initializes this by copying its information from another
/// TypeLoc of the same type.
void initializeFullCopy(TypeLoc Other) {
assert(getType() == Other.getType());
copy(Other);
}
- /// \brief Initializes this by copying its information from another
+ /// Initializes this by copying its information from another
/// TypeLoc of the same type. The given size must be the full data
/// size.
void initializeFullCopy(TypeLoc Other, unsigned Size) {
@@ -235,13 +235,13 @@ private:
static SourceRange getLocalSourceRangeImpl(TypeLoc TL);
};
-/// \brief Return the TypeLoc for a type source info.
+/// Return the TypeLoc for a type source info.
inline TypeLoc TypeSourceInfo::getTypeLoc() const {
// TODO: is this alignment already sufficient?
return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
}
-/// \brief Wrapper of type source information for a type with
+/// Wrapper of type source information for a type with
/// no direct qualifiers.
class UnqualTypeLoc : public TypeLoc {
public:
@@ -264,7 +264,7 @@ private:
}
};
-/// \brief Wrapper of type source information for a type with
+/// Wrapper of type source information for a type with
/// non-trivial direct qualifiers.
///
/// Currently, we intentionally do not provide source location for
@@ -276,7 +276,7 @@ public:
UnqualTypeLoc getUnqualifiedLoc() const {
unsigned align =
TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0));
- uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data);
+ auto dataInt = reinterpret_cast<uintptr_t>(Data);
dataInt = llvm::alignTo(dataInt, align);
return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt));
}
@@ -295,7 +295,7 @@ public:
return getUnqualifiedLoc();
}
- /// \brief Returns the size of the type source info data block that is
+ /// Returns the size of the type source info data block that is
/// specific to this type.
unsigned getLocalDataSize() const {
// In fact, we don't currently preserve any location information
@@ -303,7 +303,7 @@ public:
return 0;
}
- /// \brief Returns the alignment of the type source info data block that is
+ /// Returns the alignment of the type source info data block that is
/// specific to this type.
unsigned getLocalDataAlignment() const {
// We don't preserve any location information.
@@ -429,7 +429,7 @@ protected:
}
void *getNonLocalData() const {
- uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);
+ auto data = reinterpret_cast<uintptr_t>(Base::Data);
data += asDerived()->getLocalDataSize();
data = llvm::alignTo(data, getNextTypeAlign());
return reinterpret_cast<void*>(data);
@@ -503,7 +503,7 @@ struct TypeSpecLocInfo {
SourceLocation NameLoc;
};
-/// \brief A reasonable base class for TypeLocs that correspond to
+/// A reasonable base class for TypeLocs that correspond to
/// types that are written as a type-specifier.
class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
TypeSpecTypeLoc,
@@ -541,7 +541,7 @@ struct BuiltinLocInfo {
SourceRange BuiltinRange;
};
-/// \brief Wrapper for source info for builtin types.
+/// Wrapper for source info for builtin types.
class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
BuiltinTypeLoc,
BuiltinType,
@@ -661,7 +661,7 @@ public:
}
};
-/// \brief Wrapper for source info for typedefs.
+/// Wrapper for source info for typedefs.
class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TypedefTypeLoc,
TypedefType> {
@@ -671,7 +671,7 @@ public:
}
};
-/// \brief Wrapper for source info for injected class names of class
+/// Wrapper for source info for injected class names of class
/// templates.
class InjectedClassNameTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
@@ -683,7 +683,7 @@ public:
}
};
-/// \brief Wrapper for source info for unresolved typename using decls.
+/// Wrapper for source info for unresolved typename using decls.
class UnresolvedUsingTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
UnresolvedUsingTypeLoc,
@@ -694,7 +694,7 @@ public:
}
};
-/// \brief Wrapper for source info for tag types. Note that this only
+/// Wrapper for source info for tag types. Note that this only
/// records source info for the name itself; a type written 'struct foo'
/// should be represented as an ElaboratedTypeLoc. We currently
/// only do that when C++ is enabled because of the expense of
@@ -705,7 +705,7 @@ class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
public:
TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
- /// \brief True if the tag was defined in this type specifier.
+ /// True if the tag was defined in this type specifier.
bool isDefinition() const {
TagDecl *D = getDecl();
return D->isCompleteDefinition() &&
@@ -713,7 +713,7 @@ public:
}
};
-/// \brief Wrapper for source info for record types.
+/// Wrapper for source info for record types.
class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
RecordTypeLoc,
RecordType> {
@@ -721,7 +721,7 @@ public:
RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
};
-/// \brief Wrapper for source info for enum types.
+/// Wrapper for source info for enum types.
class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
EnumTypeLoc,
EnumType> {
@@ -729,7 +729,7 @@ public:
EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
};
-/// \brief Wrapper for template type parameters.
+/// Wrapper for template type parameters.
class TemplateTypeParmTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TemplateTypeParmTypeLoc,
@@ -828,14 +828,14 @@ public:
}
};
-/// \brief Wrapper for substituted template type parameters.
+/// Wrapper for substituted template type parameters.
class SubstTemplateTypeParmTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
SubstTemplateTypeParmTypeLoc,
SubstTemplateTypeParmType> {
};
- /// \brief Wrapper for substituted template type parameters.
+ /// Wrapper for substituted template type parameters.
class SubstTemplateTypeParmPackTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
SubstTemplateTypeParmPackTypeLoc,
@@ -855,7 +855,7 @@ struct AttributedLocInfo {
SourceLocation AttrLoc;
};
-/// \brief Type source information for an attributed type.
+/// Type source information for an attributed type.
class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
AttributedTypeLoc,
AttributedType,
@@ -992,7 +992,7 @@ class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
return (TypeSourceInfo**)this->getExtraLocalData();
}
- // SourceLocations are stored after the type argument information, one for
+ // SourceLocations are stored after the type argument information, one for
// each Protocol.
SourceLocation *getProtocolLocArray() const {
return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs());
@@ -1114,7 +1114,7 @@ struct ObjCInterfaceLocInfo {
SourceLocation NameEndLoc;
};
-/// \brief Wrapper for source info for ObjC interfaces.
+/// Wrapper for source info for ObjC interfaces.
class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc,
ObjCInterfaceTypeLoc,
ObjCInterfaceType,
@@ -1131,11 +1131,11 @@ public:
void setNameLoc(SourceLocation Loc) {
getLocalData()->NameLoc = Loc;
}
-
+
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameEndLoc());
}
-
+
SourceLocation getNameEndLoc() const {
return getLocalData()->NameEndLoc;
}
@@ -1227,7 +1227,7 @@ public:
}
};
-/// \brief Wrapper for source info for pointers decayed from arrays and
+/// Wrapper for source info for pointers decayed from arrays and
/// functions.
class DecayedTypeLoc : public InheritingConcreteTypeLoc<
AdjustedTypeLoc, DecayedTypeLoc, DecayedType> {
@@ -1267,7 +1267,7 @@ public:
}
};
-/// \brief Wrapper for source info for pointers.
+/// Wrapper for source info for pointers.
class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
PointerType> {
public:
@@ -1280,7 +1280,7 @@ public:
}
};
-/// \brief Wrapper for source info for block pointers.
+/// Wrapper for source info for block pointers.
class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
BlockPointerType> {
public:
@@ -1297,7 +1297,7 @@ struct MemberPointerLocInfo : public PointerLikeLocInfo {
TypeSourceInfo *ClassTInfo;
};
-/// \brief Wrapper for source info for member pointers.
+/// Wrapper for source info for member pointers.
class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
MemberPointerType,
MemberPointerLocInfo> {
@@ -1392,7 +1392,7 @@ struct FunctionLocInfo {
SourceLocation LocalRangeEnd;
};
-/// \brief Wrapper for source info for functions.
+/// Wrapper for source info for functions.
class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
FunctionTypeLoc,
FunctionType,
@@ -1496,7 +1496,7 @@ public:
setExceptionSpecRange(Loc);
}
- /// \brief Returns the size of the type source info data block that is
+ /// Returns the size of the type source info data block that is
/// specific to this type.
unsigned getExtraLocalDataSize() const {
unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0;
@@ -1525,7 +1525,7 @@ struct ArrayLocInfo {
Expr *Size;
};
-/// \brief Wrapper for source info for arrays.
+/// Wrapper for source info for arrays.
class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
ArrayTypeLoc,
ArrayType,
@@ -1670,7 +1670,7 @@ public:
getLocalData()->NameLoc = Loc;
}
- /// \brief - Copy the location information from the given info.
+ /// - Copy the location information from the given info.
void copy(TemplateSpecializationTypeLoc Loc) {
unsigned size = getFullDataSize();
assert(size == Loc.getFullDataSize());
@@ -1766,10 +1766,10 @@ public:
return range;
}
- /// Returns the type before the address space attribute application
- /// area.
+ /// Returns the type before the address space attribute application
+ /// area.
/// int * __attribute__((address_space(11))) *
- /// ^ ^
+ /// ^ ^
QualType getInnerType() const {
return this->getTypePtr()->getPointeeType();
}
@@ -1798,6 +1798,13 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
VectorType> {
};
+// FIXME: size expression and attribute locations (or keyword if we
+// ever fully support altivec syntax).
+class DependentVectorTypeLoc
+ : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DependentVectorTypeLoc,
+ DependentVectorType> {};
+
// FIXME: size expression and attribute locations.
class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
ExtVectorTypeLoc,
@@ -1989,7 +1996,7 @@ public:
struct ElaboratedLocInfo {
SourceLocation ElaboratedKWLoc;
- /// \brief Data associated with the nested-name-specifier location.
+ /// Data associated with the nested-name-specifier location.
void *QualifierData;
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
index 66697fa0d0fa..8638f94bda14 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
@@ -75,6 +75,7 @@ DEPENDENT_TYPE(DependentSizedArray, ArrayType)
DEPENDENT_TYPE(DependentSizedExtVector, Type)
DEPENDENT_TYPE(DependentAddressSpace, Type)
TYPE(Vector, Type)
+DEPENDENT_TYPE(DependentVector, Type)
TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
TYPE(FunctionProto, FunctionType)
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h
index fa64fae8824f..7ea78071f5cf 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h
@@ -1,4 +1,4 @@
-//===-------------- TypeOrdering.h - Total ordering for types -------------===//
+//===-------------- TypeOrdering.h - Total ordering for types ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Allows QualTypes to be sorted and hence used in maps and sets.
+/// Allows QualTypes to be sorted and hence used in maps and sets.
///
/// Defines clang::QualTypeOrdering, a total ordering on clang::QualType,
/// and hence enables QualType values to be sorted and to be used in
@@ -25,7 +25,7 @@
namespace clang {
-/// \brief Function object that provides a total ordering on QualType values.
+/// Function object that provides a total ordering on QualType values.
struct QualTypeOrdering {
bool operator()(QualType T1, QualType T2) const {
return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
@@ -56,20 +56,20 @@ namespace llvm {
};
template<> struct DenseMapInfo<clang::CanQualType> {
- static inline clang::CanQualType getEmptyKey() {
- return clang::CanQualType();
+ static inline clang::CanQualType getEmptyKey() {
+ return clang::CanQualType();
}
-
+
static inline clang::CanQualType getTombstoneKey() {
using clang::CanQualType;
return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
}
-
+
static unsigned getHashValue(clang::CanQualType Val) {
return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
}
-
+
static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
return LHS == RHS;
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h
index 11e5a47f1f29..75fa0ec15ce2 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h
@@ -22,7 +22,7 @@ namespace clang {
return static_cast<ImplClass*>(this)-> \
Visit##CLASS(static_cast<const CLASS*>(T))
-/// \brief An operation on a type.
+/// An operation on a type.
///
/// \tparam ImplClass Class implementing the operation. Must be inherited from
/// TypeVisitor.
@@ -65,7 +65,7 @@ template<typename ImplClass, typename RetTy=void>
class TypeVisitor {
public:
- /// \brief Performs the operation associated with this visitor object.
+ /// Performs the operation associated with this visitor object.
RetTy Visit(const Type *T) {
// Top switch stmt: dispatch to VisitFooType for each FooType.
switch (T->getTypeClass()) {
@@ -83,7 +83,7 @@ public:
}
#include "clang/AST/TypeNodes.def"
- /// \brief Method called if \c ImpClass doesn't provide specific handler
+ /// Method called if \c ImpClass doesn't provide specific handler
/// for some type class.
RetTy VisitType(const Type*) { return RetTy(); }
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
index 614ff9bf2efd..b62e9f138bb6 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
@@ -57,7 +57,7 @@ public:
NamedDecl *operator->() const { return **this; }
};
-/// \brief A set of unresolved declarations.
+/// A set of unresolved declarations.
class UnresolvedSetImpl {
using DeclsTy = SmallVectorImpl<DeclAccessPair>;
@@ -140,13 +140,13 @@ private:
}
};
-/// \brief A set of unresolved declarations.
+/// A set of unresolved declarations.
template <unsigned InlineCapacity> class UnresolvedSet :
public UnresolvedSetImpl {
SmallVector<DeclAccessPair, InlineCapacity> Decls;
};
-
+
} // namespace clang
#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 178139477d00..3a8a6a9c15f0 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
@@ -68,92 +68,92 @@ struct VTTComponent {
: VTableIndex(VTableIndex), VTableBase(VTableBase) {}
};
-/// \brief Class for building VTT layout information.
+/// Class for building VTT layout information.
class VTTBuilder {
ASTContext &Ctx;
- /// \brief The most derived class for which we're building this vtable.
+ /// The most derived class for which we're building this vtable.
const CXXRecordDecl *MostDerivedClass;
using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>;
-
- /// \brief The VTT vtables.
+
+ /// The VTT vtables.
VTTVTablesVectorTy VTTVTables;
-
+
using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>;
-
- /// \brief The VTT components.
+
+ /// The VTT components.
VTTComponentsVectorTy VTTComponents;
-
- /// \brief The AST record layout of the most derived class.
+
+ /// The AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>;
using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>;
- /// \brief The sub-VTT indices for the bases of the most derived class.
+ /// The sub-VTT indices for the bases of the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
- /// \brief The secondary virtual pointer indices of all subobjects of
+ /// The secondary virtual pointer indices of all subobjects of
/// the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
- /// \brief Whether the VTT builder should generate LLVM IR for the VTT.
+ /// Whether the VTT builder should generate LLVM IR for the VTT.
bool GenerateDefinition;
- /// \brief Add a vtable pointer to the VTT currently being built.
+ /// Add a vtable pointer to the VTT currently being built.
void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
const CXXRecordDecl *VTableClass);
-
- /// \brief Lay out the secondary VTTs of the given base subobject.
+
+ /// Lay out the secondary VTTs of the given base subobject.
void LayoutSecondaryVTTs(BaseSubobject Base);
-
- /// \brief Lay out the secondary virtual pointers for the given base
+
+ /// Lay out the secondary virtual pointers for the given base
/// subobject.
///
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
/// or a direct or indirect base of a virtual base.
- void LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ void LayoutSecondaryVirtualPointers(BaseSubobject Base,
bool BaseIsMorallyVirtual,
uint64_t VTableIndex,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy &VBases);
-
- /// \brief Lay out the secondary virtual pointers for the given base
+
+ /// Lay out the secondary virtual pointers for the given base
/// subobject.
- void LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ void LayoutSecondaryVirtualPointers(BaseSubobject Base,
uint64_t VTableIndex);
- /// \brief Lay out the VTTs for the virtual base classes of the given
+ /// Lay out the VTTs for the virtual base classes of the given
/// record declaration.
void LayoutVirtualVTTs(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases);
-
- /// \brief Lay out the VTT for the given subobject, including any
+
+ /// Lay out the VTT for the given subobject, including any
/// secondary VTTs, secondary virtual pointers and virtual VTTs.
void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
-
+
public:
VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
bool GenerateDefinition);
- // \brief Returns a reference to the VTT components.
+ // Returns a reference to the VTT components.
const VTTComponentsVectorTy &getVTTComponents() const {
return VTTComponents;
}
-
- // \brief Returns a reference to the VTT vtables.
+
+ // Returns a reference to the VTT vtables.
const VTTVTablesVectorTy &getVTTVTables() const {
return VTTVTables;
}
-
- /// \brief Returns a reference to the sub-VTT indices.
+
+ /// Returns a reference to the sub-VTT indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
return SubVTTIndicies;
}
-
- /// \brief Returns a reference to the secondary virtual pointer indices.
+
+ /// Returns a reference to the secondary virtual pointer indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &
getSecondaryVirtualPointerIndices() const {
return SecondaryVirtualPointerIndices;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
index b0b71e473516..4a779db01ff8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
@@ -26,7 +26,7 @@
namespace clang {
class CXXRecordDecl;
-/// \brief Represents a single component in a vtable.
+/// Represents a single component in a vtable.
class VTableComponent {
public:
enum Kind {
@@ -36,13 +36,13 @@ public:
CK_RTTI,
CK_FunctionPointer,
- /// \brief A pointer to the complete destructor.
+ /// A pointer to the complete destructor.
CK_CompleteDtorPointer,
- /// \brief A pointer to the deleting destructor.
+ /// A pointer to the deleting destructor.
CK_DeletingDtorPointer,
- /// \brief An entry that is never used.
+ /// An entry that is never used.
///
/// In some cases, a vtable function pointer will end up never being
/// called. Such vtable function pointers are represented as a
@@ -93,11 +93,7 @@ public:
reinterpret_cast<uintptr_t>(MD));
}
- static VTableComponent getFromOpaqueInteger(uint64_t I) {
- return VTableComponent(I);
- }
-
- /// \brief Get the kind of this vtable component.
+ /// Get the kind of this vtable component.
Kind getKind() const {
return (Kind)(Value & 0x7);
}
@@ -226,9 +222,6 @@ private:
return static_cast<uintptr_t>(Value & ~7ULL);
}
- explicit VTableComponent(uint64_t Value)
- : Value(Value) { }
-
/// The kind is stored in the lower 3 bits of the value. For offsets, we
/// make use of the facts that classes can't be larger than 2^55 bytes,
/// so we store the offset in the lower part of the 61 bits that remain.
@@ -255,10 +248,10 @@ private:
OwningArrayRef<VTableComponent> VTableComponents;
- /// \brief Contains thunks needed by vtables, sorted by indices.
+ /// Contains thunks needed by vtables, sorted by indices.
OwningArrayRef<VTableThunkTy> VTableThunks;
- /// \brief Address points for all vtables.
+ /// Address points for all vtables.
AddressPointsMapTy AddressPoints;
public:
@@ -324,7 +317,7 @@ public:
protected:
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
- /// \brief Contains all thunks that a given method decl will need.
+ /// Contains all thunks that a given method decl will need.
ThunksMapTy Thunks;
/// Compute and store all vtable related information (vtable layout, vbase
@@ -355,7 +348,7 @@ public:
class ItaniumVTableContext : public VTableContextBase {
private:
- /// \brief Contains the index (relative to the vtable address point)
+ /// Contains the index (relative to the vtable address point)
/// where the function pointer for a virtual function is stored.
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
MethodVTableIndicesTy MethodVTableIndices;
@@ -368,7 +361,7 @@ private:
typedef std::pair<const CXXRecordDecl *,
const CXXRecordDecl *> ClassPairTy;
- /// \brief vtable offsets for offsets of virtual bases of a class.
+ /// vtable offsets for offsets of virtual bases of a class.
///
/// Contains the vtable offset (relative to the address point) in chars
/// where the offsets for virtual bases of a class are stored.
@@ -393,7 +386,7 @@ public:
const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass);
- /// \brief Locate a virtual function in the vtable.
+ /// Locate a virtual function in the vtable.
///
/// Return the index (relative to the vtable address point) where the
/// function pointer for the given virtual function is stored.
@@ -401,7 +394,7 @@ public:
/// Return the offset in chars (relative to the vtable address point) where
/// the offset of the virtual base that contains the given base is stored,
- /// otherwise, if no virtual base contains the given class, return 0.
+ /// otherwise, if no virtual base contains the given class, return 0.
///
/// Base must be a virtual base class or an unambiguous base.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
@@ -479,41 +472,42 @@ struct VirtualBaseInfo {
VPtrInfoVector VBPtrPaths;
};
+struct MethodVFTableLocation {
+ /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
+ uint64_t VBTableIndex;
+
+ /// If nonnull, holds the last vbase which contains the vfptr that the
+ /// method definition is adjusted to.
+ const CXXRecordDecl *VBase;
+
+ /// This is the offset of the vfptr from the start of the last vbase, or the
+ /// complete type if there are no virtual bases.
+ CharUnits VFPtrOffset;
+
+ /// Method's index in the vftable.
+ uint64_t Index;
+
+ MethodVFTableLocation()
+ : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
+ Index(0) {}
+
+ MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
+ CharUnits VFPtrOffset, uint64_t Index)
+ : VBTableIndex(VBTableIndex), VBase(VBase), VFPtrOffset(VFPtrOffset),
+ Index(Index) {}
+
+ bool operator<(const MethodVFTableLocation &other) const {
+ if (VBTableIndex != other.VBTableIndex) {
+ assert(VBase != other.VBase);
+ return VBTableIndex < other.VBTableIndex;
+ }
+ return std::tie(VFPtrOffset, Index) <
+ std::tie(other.VFPtrOffset, other.Index);
+ }
+};
+
class MicrosoftVTableContext : public VTableContextBase {
public:
- struct MethodVFTableLocation {
- /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
- uint64_t VBTableIndex;
-
- /// If nonnull, holds the last vbase which contains the vfptr that the
- /// method definition is adjusted to.
- const CXXRecordDecl *VBase;
-
- /// This is the offset of the vfptr from the start of the last vbase, or the
- /// complete type if there are no virtual bases.
- CharUnits VFPtrOffset;
-
- /// Method's index in the vftable.
- uint64_t Index;
-
- MethodVFTableLocation()
- : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
- Index(0) {}
-
- MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
- CharUnits VFPtrOffset, uint64_t Index)
- : VBTableIndex(VBTableIndex), VBase(VBase),
- VFPtrOffset(VFPtrOffset), Index(Index) {}
-
- bool operator<(const MethodVFTableLocation &other) const {
- if (VBTableIndex != other.VBTableIndex) {
- assert(VBase != other.VBase);
- return VBTableIndex < other.VBTableIndex;
- }
- return std::tie(VFPtrOffset, Index) <
- std::tie(other.VFPtrOffset, other.Index);
- }
- };
private:
ASTContext &Context;
@@ -522,7 +516,7 @@ private:
MethodVFTableLocationsTy;
MethodVFTableLocationsTy MethodVFTableLocations;
- typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector>
+ typedef llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VPtrInfoVector>>
VFPtrLocationsMapTy;
VFPtrLocationsMapTy VFPtrLocations;
@@ -559,7 +553,7 @@ public:
const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD,
CharUnits VFPtrOffset);
- const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD);
+ MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD);
const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override {
// Complete destructors don't have a slot in a vftable, so no thunks needed.
@@ -569,7 +563,7 @@ public:
return VTableContextBase::getThunkInfo(GD);
}
- /// \brief Returns the index of VBase in the vbtable of Derived.
+ /// Returns the index of VBase in the vbtable of Derived.
/// VBase must be a morally virtual base of Derived.
/// The vbtable is an array of i32 offsets. The first entry is a self entry,
/// and the rest are offsets from the vbptr to virtual bases.
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
index 389af1b6e259..324c02db3fe0 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -50,7 +50,7 @@ namespace clang {
namespace ast_matchers {
-/// \brief A class to allow finding matches over the Clang AST.
+/// A class to allow finding matches over the Clang AST.
///
/// After creation, you can add multiple matchers to the MatchFinder via
/// calls to addMatcher(...).
@@ -68,52 +68,52 @@ namespace ast_matchers {
/// Not intended to be subclassed.
class MatchFinder {
public:
- /// \brief Contains all information for a given match.
+ /// Contains all information for a given match.
///
/// Every time a match is found, the MatchFinder will invoke the registered
/// MatchCallback with a MatchResult containing information about the match.
struct MatchResult {
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
- /// \brief Contains the nodes bound on the current match.
+ /// Contains the nodes bound on the current match.
///
/// This allows user code to easily extract matched AST nodes.
const BoundNodes Nodes;
- /// \brief Utilities for interpreting the matched AST structures.
+ /// Utilities for interpreting the matched AST structures.
/// @{
clang::ASTContext * const Context;
clang::SourceManager * const SourceManager;
/// @}
};
- /// \brief Called when the Match registered for it was successfully found
+ /// Called when the Match registered for it was successfully found
/// in the AST.
class MatchCallback {
public:
virtual ~MatchCallback();
- /// \brief Called on every match by the \c MatchFinder.
+ /// Called on every match by the \c MatchFinder.
virtual void run(const MatchResult &Result) = 0;
- /// \brief Called at the start of each translation unit.
+ /// Called at the start of each translation unit.
///
/// Optionally override to do per translation unit tasks.
virtual void onStartOfTranslationUnit() {}
- /// \brief Called at the end of each translation unit.
+ /// Called at the end of each translation unit.
///
/// Optionally override to do per translation unit tasks.
virtual void onEndOfTranslationUnit() {}
- /// \brief An id used to group the matchers.
+ /// An id used to group the matchers.
///
/// This id is used, for example, for the profiling output.
/// It defaults to "<unknown>".
virtual StringRef getID() const;
};
- /// \brief Called when parsing is finished. Intended for testing only.
+ /// Called when parsing is finished. Intended for testing only.
class ParsingDoneTestCallback {
public:
virtual ~ParsingDoneTestCallback();
@@ -125,11 +125,11 @@ public:
Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
: Records(Records) {}
- /// \brief Per bucket timing information.
+ /// Per bucket timing information.
llvm::StringMap<llvm::TimeRecord> &Records;
};
- /// \brief Enables per-check timers.
+ /// Enables per-check timers.
///
/// It prints a report after match.
llvm::Optional<Profiling> CheckProfiling;
@@ -138,7 +138,7 @@ public:
MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
~MatchFinder();
- /// \brief Adds a matcher to execute when running over the AST.
+ /// Adds a matcher to execute when running over the AST.
///
/// Calls 'Action' with the BoundNodes on every match.
/// Adding more than one 'NodeMatch' allows finding different matches in a
@@ -162,7 +162,7 @@ public:
MatchCallback *Action);
/// @}
- /// \brief Adds a matcher to execute when running over the AST.
+ /// Adds a matcher to execute when running over the AST.
///
/// This is similar to \c addMatcher(), but it uses the dynamic interface. It
/// is more flexible, but the lost type information enables a caller to pass
@@ -173,10 +173,10 @@ public:
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
MatchCallback *Action);
- /// \brief Creates a clang ASTConsumer that finds all matches.
+ /// Creates a clang ASTConsumer that finds all matches.
std::unique_ptr<clang::ASTConsumer> newASTConsumer();
- /// \brief Calls the registered callbacks on all matches on the given \p Node.
+ /// Calls the registered callbacks on all matches on the given \p Node.
///
/// Note that there can be multiple matches on a single node, for
/// example when using decl(forEachDescendant(stmt())).
@@ -189,17 +189,17 @@ public:
ASTContext &Context);
/// @}
- /// \brief Finds all matches in the given AST.
+ /// Finds all matches in the given AST.
void matchAST(ASTContext &Context);
- /// \brief Registers a callback to notify the end of parsing.
+ /// Registers a callback to notify the end of parsing.
///
/// The provided closure is called after parsing is done, before the AST is
/// traversed. Useful for benchmarking.
/// Each call to FindAll(...) will call the closure once.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
- /// \brief For each \c Matcher<> a \c MatchCallback that will be called
+ /// For each \c Matcher<> a \c MatchCallback that will be called
/// when it matches.
struct MatchersByType {
std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
@@ -211,7 +211,7 @@ public:
NestedNameSpecifierLoc;
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
- /// \brief All the callbacks in one container to simplify iteration.
+ /// All the callbacks in one container to simplify iteration.
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
};
@@ -220,11 +220,11 @@ private:
MatchFinderOptions Options;
- /// \brief Called when parsing is done.
+ /// Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
};
-/// \brief Returns the results of matching \p Matcher on \p Node.
+/// Returns the results of matching \p Matcher on \p Node.
///
/// Collects the \c BoundNodes of all callback invocations when matching
/// \p Matcher on \p Node and returns the collected results.
@@ -248,12 +248,12 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
ASTContext &Context);
/// @}
-/// \brief Returns the results of matching \p Matcher on the translation unit of
+/// Returns the results of matching \p Matcher on the translation unit of
/// \p Context and collects the \c BoundNodes of all callback invocations.
template <typename MatcherT>
SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context);
-/// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
+/// Returns the first result of type \c NodeT bound to \p BoundTo.
///
/// Returns \c NULL if there is no match, or if the matching node cannot be
/// casted to \c NodeT.
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
index 64e7e908d51e..51f2ce2af75c 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -92,7 +92,7 @@
namespace clang {
namespace ast_matchers {
-/// \brief Maps string IDs to AST nodes matched by parts of a matcher.
+/// Maps string IDs to AST nodes matched by parts of a matcher.
///
/// The bound nodes are generated by calling \c bind("id") on the node matchers
/// of the nodes we want to access later.
@@ -101,7 +101,7 @@ namespace ast_matchers {
/// callbacks are executed every time a match is found.
class BoundNodes {
public:
- /// \brief Returns the AST node bound to \c ID.
+ /// Returns the AST node bound to \c ID.
///
/// Returns NULL if there was no node bound to \c ID or if there is a node but
/// it cannot be converted to the specified type.
@@ -110,12 +110,12 @@ public:
return MyBoundNodes.getNodeAs<T>(ID);
}
- /// \brief Type of mapping from binding identifiers to bound nodes. This type
+ /// 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
using IDToNodeMap = internal::BoundNodesMap::IDToNodeMap;
- /// \brief Retrieve mapping from binding identifiers to bound nodes.
+ /// Retrieve mapping from binding identifiers to bound nodes.
const IDToNodeMap &getMap() const {
return MyBoundNodes.getMap();
}
@@ -123,14 +123,14 @@ public:
private:
friend class internal::BoundNodesTreeBuilder;
- /// \brief Create BoundNodes from a pre-filled map of bindings.
+ /// Create BoundNodes from a pre-filled map of bindings.
BoundNodes(internal::BoundNodesMap &MyBoundNodes)
: MyBoundNodes(MyBoundNodes) {}
internal::BoundNodesMap MyBoundNodes;
};
-/// \brief If the provided matcher matches a node, binds the node to \c ID.
+/// If the provided matcher matches a node, binds the node to \c ID.
///
/// FIXME: Do we want to support this now that we have bind()?
template <typename T>
@@ -139,7 +139,7 @@ internal::Matcher<T> id(StringRef ID,
return InnerMatcher.bind(ID);
}
-/// \brief Types of matchers for the top-level classes in the AST class
+/// Types of matchers for the top-level classes in the AST class
/// hierarchy.
/// @{
using DeclarationMatcher = internal::Matcher<Decl>;
@@ -151,7 +151,7 @@ using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>;
using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
/// @}
-/// \brief Matches any node.
+/// Matches any node.
///
/// Useful when another matcher requires a child matcher, but there's no
/// additional constraint. This will often be used with an explicit conversion
@@ -167,7 +167,7 @@ using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
/// Usable as: Any Matcher
inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
-/// \brief Matches the top declaration context.
+/// Matches the top declaration context.
///
/// Given
/// \code
@@ -181,7 +181,7 @@ inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
translationUnitDecl;
-/// \brief Matches typedef declarations.
+/// Matches typedef declarations.
///
/// Given
/// \code
@@ -193,7 +193,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl>
typedefDecl;
-/// \brief Matches typedef name declarations.
+/// Matches typedef name declarations.
///
/// Given
/// \code
@@ -205,7 +205,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
typedefNameDecl;
-/// \brief Matches type alias declarations.
+/// Matches type alias declarations.
///
/// Given
/// \code
@@ -217,7 +217,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl>
typeAliasDecl;
-/// \brief Matches type alias template declarations.
+/// Matches type alias template declarations.
///
/// typeAliasTemplateDecl() matches
/// \code
@@ -227,7 +227,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
typeAliasTemplateDecl;
-/// \brief Matches AST nodes that were expanded within the main-file.
+/// Matches AST nodes that were expanded within the main-file.
///
/// Example matches X but not Y
/// (matcher = cxxRecordDecl(isExpansionInMainFile())
@@ -248,7 +248,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
SourceManager.getExpansionLoc(Node.getLocStart()));
}
-/// \brief Matches AST nodes that were expanded within system-header-files.
+/// Matches AST nodes that were expanded within system-header-files.
///
/// Example matches Y but not X
/// (matcher = cxxRecordDecl(isExpansionInSystemHeader())
@@ -272,7 +272,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
return SourceManager.isInSystemHeader(ExpansionLoc);
}
-/// \brief Matches AST nodes that were expanded within files whose name is
+/// Matches AST nodes that were expanded within files whose name is
/// partially matching a given regex.
///
/// Example matches Y but not X
@@ -306,7 +306,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
return RE.match(Filename);
}
-/// \brief Matches declarations.
+/// Matches declarations.
///
/// Examples matches \c X, \c C, and the friend declaration inside \c C;
/// \code
@@ -317,7 +317,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
/// \endcode
extern const internal::VariadicAllOfMatcher<Decl> decl;
-/// \brief Matches a declaration of a linkage specification.
+/// Matches a declaration of a linkage specification.
///
/// Given
/// \code
@@ -328,7 +328,7 @@ extern const internal::VariadicAllOfMatcher<Decl> decl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
linkageSpecDecl;
-/// \brief Matches a declaration of anything that could have a name.
+/// Matches a declaration of anything that could have a name.
///
/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U;
/// \code
@@ -341,7 +341,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
-/// \brief Matches a declaration of label.
+/// Matches a declaration of label.
///
/// Given
/// \code
@@ -352,7 +352,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
/// matches 'FOO:'
extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
-/// \brief Matches a declaration of a namespace.
+/// Matches a declaration of a namespace.
///
/// Given
/// \code
@@ -364,7 +364,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl>
namespaceDecl;
-/// \brief Matches a declaration of a namespace alias.
+/// Matches a declaration of a namespace alias.
///
/// Given
/// \code
@@ -376,7 +376,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
namespaceAliasDecl;
-/// \brief Matches class, struct, and union declarations.
+/// Matches class, struct, and union declarations.
///
/// Example matches \c X, \c Z, \c U, and \c S
/// \code
@@ -387,7 +387,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
-/// \brief Matches C++ class declarations.
+/// Matches C++ class declarations.
///
/// Example matches \c X, \c Z
/// \code
@@ -397,7 +397,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl>
cxxRecordDecl;
-/// \brief Matches C++ class template declarations.
+/// Matches C++ class template declarations.
///
/// Example matches \c Z
/// \code
@@ -406,7 +406,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
classTemplateDecl;
-/// \brief Matches C++ class template specializations.
+/// Matches C++ class template specializations.
///
/// Given
/// \code
@@ -420,7 +420,7 @@ extern const internal::VariadicDynCastAllOfMatcher<
Decl, ClassTemplateSpecializationDecl>
classTemplateSpecializationDecl;
-/// \brief Matches declarator declarations (field, variable, function
+/// Matches declarator declarations (field, variable, function
/// and non-type template parameter declarations).
///
/// Given
@@ -432,7 +432,7 @@ extern const internal::VariadicDynCastAllOfMatcher<
extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
declaratorDecl;
-/// \brief Matches parameter variable declarations.
+/// Matches parameter variable declarations.
///
/// Given
/// \code
@@ -443,7 +443,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl>
parmVarDecl;
-/// \brief Matches C++ access specifier declarations.
+/// Matches C++ access specifier declarations.
///
/// Given
/// \code
@@ -457,7 +457,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
accessSpecDecl;
-/// \brief Matches constructor initializers.
+/// Matches constructor initializers.
///
/// Examples matches \c i(42).
/// \code
@@ -469,7 +469,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
cxxCtorInitializer;
-/// \brief Matches template arguments.
+/// Matches template arguments.
///
/// Given
/// \code
@@ -480,7 +480,7 @@ extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
/// matches 'int' in C<int>.
extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
-/// \brief Matches template name.
+/// Matches template name.
///
/// Given
/// \code
@@ -491,7 +491,7 @@ extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
/// matches 'X' in X<int>.
extern const internal::VariadicAllOfMatcher<TemplateName> templateName;
-/// \brief Matches non-type template parameter declarations.
+/// Matches non-type template parameter declarations.
///
/// Given
/// \code
@@ -503,7 +503,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
NonTypeTemplateParmDecl>
nonTypeTemplateParmDecl;
-/// \brief Matches template type parameter declarations.
+/// Matches template type parameter declarations.
///
/// Given
/// \code
@@ -514,7 +514,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
templateTypeParmDecl;
-/// \brief Matches public C++ declarations.
+/// Matches public C++ declarations.
///
/// Given
/// \code
@@ -530,7 +530,7 @@ AST_MATCHER(Decl, isPublic) {
return Node.getAccess() == AS_public;
}
-/// \brief Matches protected C++ declarations.
+/// Matches protected C++ declarations.
///
/// Given
/// \code
@@ -546,7 +546,7 @@ AST_MATCHER(Decl, isProtected) {
return Node.getAccess() == AS_protected;
}
-/// \brief Matches private C++ declarations.
+/// Matches private C++ declarations.
///
/// Given
/// \code
@@ -562,7 +562,7 @@ AST_MATCHER(Decl, isPrivate) {
return Node.getAccess() == AS_private;
}
-/// \brief Matches non-static data members that are bit-fields.
+/// Matches non-static data members that are bit-fields.
///
/// Given
/// \code
@@ -577,7 +577,7 @@ AST_MATCHER(FieldDecl, isBitField) {
return Node.isBitField();
}
-/// \brief Matches non-static data members that are bit-fields of the specified
+/// Matches non-static data members that are bit-fields of the specified
/// bit width.
///
/// Given
@@ -595,7 +595,7 @@ AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
Node.getBitWidthValue(Finder->getASTContext()) == Width;
}
-/// \brief Matches non-static data members that have an in-class initializer.
+/// Matches non-static data members that have an in-class initializer.
///
/// Given
/// \code
@@ -616,7 +616,13 @@ AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>,
InnerMatcher.matches(*Initializer, Finder, Builder));
}
-/// \brief Matches the specialized template of a specialization declaration.
+/// Determines whether the function is "main", which is the entry point
+/// into an executable program.
+AST_MATCHER(FunctionDecl, isMain) {
+ return Node.isMain();
+}
+
+/// Matches the specialized template of a specialization declaration.
///
/// Given
/// \code
@@ -633,13 +639,13 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
InnerMatcher.matches(*Decl, Finder, Builder));
}
-/// \brief Matches a declaration that has been implicitly added
+/// Matches a declaration that has been implicitly added
/// by the compiler (eg. implicit default/copy constructors).
AST_MATCHER(Decl, isImplicit) {
return Node.isImplicit();
}
-/// \brief Matches classTemplateSpecializations, templateSpecializationType and
+/// Matches classTemplateSpecializations, templateSpecializationType and
/// functionDecl that have at least one TemplateArgument matching the given
/// InnerMatcher.
///
@@ -672,7 +678,7 @@ AST_POLYMORPHIC_MATCHER_P(
Builder);
}
-/// \brief Matches expressions that match InnerMatcher after any implicit AST
+/// Matches expressions that match InnerMatcher after any implicit AST
/// nodes are stripped off.
///
/// Parentheses and explicit casts are not discarded.
@@ -693,12 +699,12 @@ AST_POLYMORPHIC_MATCHER_P(
/// varDecl(hasInitializer(cxxConstructExpr()))
/// \endcode
/// only match the declarations for b and c.
-AST_MATCHER_P(Expr, ignoringImplicit, ast_matchers::internal::Matcher<Expr>,
+AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher<Expr>,
InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder);
}
-/// \brief Matches expressions that match InnerMatcher after any implicit casts
+/// Matches expressions that match InnerMatcher after any implicit casts
/// are stripped off.
///
/// Parentheses and explicit casts are not discarded.
@@ -728,7 +734,7 @@ AST_MATCHER_P(Expr, ignoringImpCasts,
return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder);
}
-/// \brief Matches expressions that match InnerMatcher after parentheses and
+/// Matches expressions that match InnerMatcher after parentheses and
/// casts are stripped off.
///
/// Implicit and non-C Style casts are also discarded.
@@ -749,7 +755,7 @@ AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder);
}
-/// \brief Matches expressions that match InnerMatcher after implicit casts and
+/// Matches expressions that match InnerMatcher after implicit casts and
/// parentheses are stripped off.
///
/// Explicit casts are not discarded.
@@ -775,7 +781,7 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts,
return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder);
}
-/// \brief Matches types that match InnerMatcher after any parens are stripped.
+/// Matches types that match InnerMatcher after any parens are stripped.
///
/// Given
/// \code
@@ -791,7 +797,7 @@ AST_MATCHER_P(QualType, ignoringParens,
return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder);
}
-/// \brief Matches classTemplateSpecializations, templateSpecializationType and
+/// Matches classTemplateSpecializations, templateSpecializationType and
/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
///
/// Given
@@ -800,7 +806,7 @@ AST_MATCHER_P(QualType, ignoringParens,
/// A<bool, int> b;
/// A<int, bool> c;
///
-/// template<typename T> f() {};
+/// template<typename T> void f() {}
/// void func() { f<int>(); };
/// \endcode
/// classTemplateSpecializationDecl(hasTemplateArgument(
@@ -822,7 +828,7 @@ AST_POLYMORPHIC_MATCHER_P2(
return InnerMatcher.matches(List[N], Finder, Builder);
}
-/// \brief Matches if the number of template arguments equals \p N.
+/// Matches if the number of template arguments equals \p N.
///
/// Given
/// \code
@@ -839,7 +845,7 @@ AST_POLYMORPHIC_MATCHER_P(
return internal::getTemplateSpecializationArgs(Node).size() == N;
}
-/// \brief Matches a TemplateArgument that refers to a certain type.
+/// Matches a TemplateArgument that refers to a certain type.
///
/// Given
/// \code
@@ -857,7 +863,7 @@ AST_MATCHER_P(TemplateArgument, refersToType,
return InnerMatcher.matches(Node.getAsType(), Finder, Builder);
}
-/// \brief Matches a TemplateArgument that refers to a certain template.
+/// Matches a TemplateArgument that refers to a certain template.
///
/// Given
/// \code
@@ -875,17 +881,17 @@ AST_MATCHER_P(TemplateArgument, refersToTemplate,
return InnerMatcher.matches(Node.getAsTemplate(), Finder, Builder);
}
-/// \brief Matches a canonical TemplateArgument that refers to a certain
+/// Matches a canonical TemplateArgument that refers to a certain
/// declaration.
///
/// Given
/// \code
-/// template<typename T> struct A {};
-/// struct B { B* next; };
+/// struct B { int next; };
+/// template<int(B::*next_ptr)> struct A {};
/// A<&B::next> a;
/// \endcode
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
-/// refersToDeclaration(fieldDecl(hasName("next"))))
+/// refersToDeclaration(fieldDecl(hasName("next")))))
/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching
/// \c B::next
AST_MATCHER_P(TemplateArgument, refersToDeclaration,
@@ -895,12 +901,12 @@ AST_MATCHER_P(TemplateArgument, refersToDeclaration,
return false;
}
-/// \brief Matches a sugar TemplateArgument that refers to a certain expression.
+/// Matches a sugar TemplateArgument that refers to a certain expression.
///
/// Given
/// \code
-/// template<typename T> struct A {};
-/// struct B { B* next; };
+/// struct B { int next; };
+/// template<int(B::*next_ptr)> struct A {};
/// A<&B::next> a;
/// \endcode
/// templateSpecializationType(hasAnyTemplateArgument(
@@ -913,11 +919,11 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) {
return false;
}
-/// \brief Matches a TemplateArgument that is an integral value.
+/// Matches a TemplateArgument that is an integral value.
///
/// Given
/// \code
-/// template<int T> struct A {};
+/// template<int T> struct C {};
/// C<42> c;
/// \endcode
/// classTemplateSpecializationDecl(
@@ -928,11 +934,11 @@ AST_MATCHER(TemplateArgument, isIntegral) {
return Node.getKind() == TemplateArgument::Integral;
}
-/// \brief Matches a TemplateArgument that referes to an integral type.
+/// Matches a TemplateArgument that referes to an integral type.
///
/// Given
/// \code
-/// template<int T> struct A {};
+/// template<int T> struct C {};
/// C<42> c;
/// \endcode
/// classTemplateSpecializationDecl(
@@ -945,7 +951,7 @@ AST_MATCHER_P(TemplateArgument, refersToIntegralType,
return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder);
}
-/// \brief Matches a TemplateArgument of integral type with a given value.
+/// Matches a TemplateArgument of integral type with a given value.
///
/// Note that 'Value' is a string as the template argument's value is
/// an arbitrary precision integer. 'Value' must be euqal to the canonical
@@ -953,7 +959,7 @@ AST_MATCHER_P(TemplateArgument, refersToIntegralType,
///
/// Given
/// \code
-/// template<int T> struct A {};
+/// template<int T> struct C {};
/// C<42> c;
/// \endcode
/// classTemplateSpecializationDecl(
@@ -966,7 +972,20 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
return Node.getAsIntegral().toString(10) == Value;
}
-/// \brief Matches any value declaration.
+/// Matches an Objective-C autorelease pool statement.
+///
+/// Given
+/// \code
+/// @autoreleasepool {
+/// int x = 0;
+/// }
+/// \endcode
+/// autoreleasePoolStmt(stmt()) matches the declaration of "x"
+/// inside the autorelease pool.
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ ObjCAutoreleasePoolStmt> autoreleasePoolStmt;
+
+/// Matches any value declaration.
///
/// Example matches A, B, C and F
/// \code
@@ -975,7 +994,7 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
-/// \brief Matches C++ constructor declarations.
+/// Matches C++ constructor declarations.
///
/// Example matches Foo::Foo() and Foo::Foo(int)
/// \code
@@ -989,7 +1008,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl>
cxxConstructorDecl;
-/// \brief Matches explicit C++ destructor declarations.
+/// Matches explicit C++ destructor declarations.
///
/// Example matches Foo::~Foo()
/// \code
@@ -1001,7 +1020,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl>
cxxDestructorDecl;
-/// \brief Matches enum declarations.
+/// Matches enum declarations.
///
/// Example matches X
/// \code
@@ -1011,7 +1030,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
-/// \brief Matches enum constants.
+/// Matches enum constants.
///
/// Example matches A, B, C
/// \code
@@ -1022,7 +1041,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
enumConstantDecl;
-/// \brief Matches method declarations.
+/// Matches method declarations.
///
/// Example matches y
/// \code
@@ -1031,7 +1050,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl>
cxxMethodDecl;
-/// \brief Matches conversion operator declarations.
+/// Matches conversion operator declarations.
///
/// Example matches the operator.
/// \code
@@ -1040,7 +1059,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
cxxConversionDecl;
-/// \brief Matches variable declarations.
+/// Matches variable declarations.
///
/// Note: this does not match declarations of member variables, which are
/// "field" declarations in Clang parlance.
@@ -1051,7 +1070,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
-/// \brief Matches field declarations.
+/// Matches field declarations.
///
/// Given
/// \code
@@ -1061,7 +1080,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
/// matches 'm'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
-/// \brief Matches function declarations.
+/// Matches function declarations.
///
/// Example matches f
/// \code
@@ -1070,7 +1089,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl>
functionDecl;
-/// \brief Matches C++ function template declarations.
+/// Matches C++ function template declarations.
///
/// Example matches f
/// \code
@@ -1079,7 +1098,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
functionTemplateDecl;
-/// \brief Matches friend declarations.
+/// Matches friend declarations.
///
/// Given
/// \code
@@ -1089,7 +1108,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
/// matches 'friend void foo()'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
-/// \brief Matches statements.
+/// Matches statements.
///
/// Given
/// \code
@@ -1099,7 +1118,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
/// matches both the compound statement '{ ++a; }' and '++a'.
extern const internal::VariadicAllOfMatcher<Stmt> stmt;
-/// \brief Matches declaration statements.
+/// Matches declaration statements.
///
/// Given
/// \code
@@ -1109,7 +1128,7 @@ extern const internal::VariadicAllOfMatcher<Stmt> stmt;
/// matches 'int a'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
-/// \brief Matches member expressions.
+/// Matches member expressions.
///
/// Given
/// \code
@@ -1122,7 +1141,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
/// matches this->x, x, y.x, a, this->b
extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
-/// \brief Matches call expressions.
+/// Matches call expressions.
///
/// Example matches x.y() and y()
/// \code
@@ -1132,7 +1151,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
-/// \brief Matches lambda expressions.
+/// Matches lambda expressions.
///
/// Example matches [&](){return 5;}
/// \code
@@ -1140,7 +1159,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
-/// \brief Matches member call expressions.
+/// Matches member call expressions.
///
/// Example matches x.y()
/// \code
@@ -1150,7 +1169,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
cxxMemberCallExpr;
-/// \brief Matches ObjectiveC Message invocation expressions.
+/// Matches ObjectiveC Message invocation expressions.
///
/// The innermost message send invokes the "alloc" class method on the
/// NSString class, while the outermost message send invokes the
@@ -1162,7 +1181,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
objcMessageExpr;
-/// \brief Matches Objective-C interface declarations.
+/// Matches Objective-C interface declarations.
///
/// Example matches Foo
/// \code
@@ -1172,7 +1191,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
objcInterfaceDecl;
-/// \brief Matches Objective-C implementation declarations.
+/// Matches Objective-C implementation declarations.
///
/// Example matches Foo
/// \code
@@ -1182,7 +1201,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
objcImplementationDecl;
-/// \brief Matches Objective-C protocol declarations.
+/// Matches Objective-C protocol declarations.
///
/// Example matches FooDelegate
/// \code
@@ -1192,7 +1211,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
objcProtocolDecl;
-/// \brief Matches Objective-C category declarations.
+/// Matches Objective-C category declarations.
///
/// Example matches Foo (Additions)
/// \code
@@ -1202,7 +1221,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
objcCategoryDecl;
-/// \brief Matches Objective-C category definitions.
+/// Matches Objective-C category definitions.
///
/// Example matches Foo (Additions)
/// \code
@@ -1212,7 +1231,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
objcCategoryImplDecl;
-/// \brief Matches Objective-C method declarations.
+/// Matches Objective-C method declarations.
///
/// Example matches both declaration and definition of -[Foo method]
/// \code
@@ -1227,7 +1246,20 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
objcMethodDecl;
-/// \brief Matches Objective-C instance variable declarations.
+/// Matches block declarations.
+///
+/// Example matches the declaration of the nameless block printing an input
+/// integer.
+///
+/// \code
+/// myFunc(^(int p) {
+/// printf("%d", p);
+/// })
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl>
+ blockDecl;
+
+/// Matches Objective-C instance variable declarations.
///
/// Example matches _enabled
/// \code
@@ -1239,7 +1271,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl>
objcIvarDecl;
-/// \brief Matches Objective-C property declarations.
+/// Matches Objective-C property declarations.
///
/// Example matches enabled
/// \code
@@ -1250,7 +1282,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
objcPropertyDecl;
-/// \brief Matches Objective-C \@throw statements.
+/// Matches Objective-C \@throw statements.
///
/// Example matches \@throw
/// \code
@@ -1259,7 +1291,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
objcThrowStmt;
-/// \brief Matches Objective-C @try statements.
+/// Matches Objective-C @try statements.
///
/// Example matches @try
/// \code
@@ -1269,7 +1301,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt>
objcTryStmt;
-/// \brief Matches Objective-C @catch statements.
+/// Matches Objective-C @catch statements.
///
/// Example matches @catch
/// \code
@@ -1279,7 +1311,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
objcCatchStmt;
-/// \brief Matches Objective-C @finally statements.
+/// Matches Objective-C @finally statements.
///
/// Example matches @finally
/// \code
@@ -1289,7 +1321,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
objcFinallyStmt;
-/// \brief Matches expressions that introduce cleanups to be run at the end
+/// Matches expressions that introduce cleanups to be run at the end
/// of the sub-expression's evaluation.
///
/// Example matches std::string()
@@ -1299,7 +1331,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
exprWithCleanups;
-/// \brief Matches init list expressions.
+/// Matches init list expressions.
///
/// Given
/// \code
@@ -1312,7 +1344,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr>
initListExpr;
-/// \brief Matches the syntactic form of init list expressions
+/// Matches the syntactic form of init list expressions
/// (if expression have it).
AST_MATCHER_P(InitListExpr, hasSyntacticForm,
internal::Matcher<Expr>, InnerMatcher) {
@@ -1321,7 +1353,7 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm,
InnerMatcher.matches(*SyntForm, Finder, Builder));
}
-/// \brief Matches C++ initializer list expressions.
+/// Matches C++ initializer list expressions.
///
/// Given
/// \code
@@ -1336,7 +1368,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXStdInitializerListExpr>
cxxStdInitializerListExpr;
-/// \brief Matches implicit initializers of init list expressions.
+/// Matches implicit initializers of init list expressions.
///
/// Given
/// \code
@@ -1347,7 +1379,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
implicitValueInitExpr;
-/// \brief Matches paren list expressions.
+/// Matches paren list expressions.
/// ParenListExprs don't have a predefined type and are used for late parsing.
/// In the final AST, they can be met in template declarations.
///
@@ -1365,7 +1397,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr>
parenListExpr;
-/// \brief Matches substitutions of non-type template parameters.
+/// Matches substitutions of non-type template parameters.
///
/// Given
/// \code
@@ -1379,7 +1411,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
SubstNonTypeTemplateParmExpr>
substNonTypeTemplateParmExpr;
-/// \brief Matches using declarations.
+/// Matches using declarations.
///
/// Given
/// \code
@@ -1390,7 +1422,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
/// matches \code using X::x \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
-/// \brief Matches using namespace declarations.
+/// Matches using namespace declarations.
///
/// Given
/// \code
@@ -1402,7 +1434,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
usingDirectiveDecl;
-/// \brief Matches reference to a name that can be looked up during parsing
+/// Matches reference to a name that can be looked up during parsing
/// but could not be resolved to a specific declaration.
///
/// Given
@@ -1419,7 +1451,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
unresolvedLookupExpr;
-/// \brief Matches unresolved using value declarations.
+/// Matches unresolved using value declarations.
///
/// Given
/// \code
@@ -1434,7 +1466,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
UnresolvedUsingValueDecl>
unresolvedUsingValueDecl;
-/// \brief Matches unresolved using value declarations that involve the
+/// Matches unresolved using value declarations that involve the
/// typename.
///
/// Given
@@ -1453,7 +1485,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
UnresolvedUsingTypenameDecl>
unresolvedUsingTypenameDecl;
-/// \brief Matches parentheses used in expressions.
+/// Matches parentheses used in expressions.
///
/// Example matches (foo() + 1)
/// \code
@@ -1462,7 +1494,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
-/// \brief Matches constructor call expressions (including implicit ones).
+/// Matches constructor call expressions (including implicit ones).
///
/// Example matches string(ptr, n) and ptr within arguments of f
/// (matcher = cxxConstructExpr())
@@ -1475,7 +1507,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr>
cxxConstructExpr;
-/// \brief Matches unresolved constructor call expressions.
+/// Matches unresolved constructor call expressions.
///
/// Example matches T(t) in return statement of f
/// (matcher = cxxUnresolvedConstructExpr())
@@ -1487,7 +1519,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXUnresolvedConstructExpr>
cxxUnresolvedConstructExpr;
-/// \brief Matches implicit and explicit this expressions.
+/// Matches implicit and explicit this expressions.
///
/// Example matches the implicit this expression in "return i".
/// (matcher = cxxThisExpr())
@@ -1500,7 +1532,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr>
cxxThisExpr;
-/// \brief Matches nodes where temporaries are created.
+/// Matches nodes where temporaries are created.
///
/// Example matches FunctionTakesString(GetStringByValue())
/// (matcher = cxxBindTemporaryExpr())
@@ -1511,7 +1543,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
cxxBindTemporaryExpr;
-/// \brief Matches nodes where temporaries are materialized.
+/// Matches nodes where temporaries are materialized.
///
/// Example: Given
/// \code
@@ -1523,17 +1555,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
/// \code
/// T u(f());
/// g(f());
+/// f().func();
/// \endcode
/// but does not match
/// \code
/// f();
-/// f().func();
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
MaterializeTemporaryExpr>
materializeTemporaryExpr;
-/// \brief Matches new expressions.
+/// Matches new expressions.
///
/// Given
/// \code
@@ -1543,7 +1575,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
/// matches 'new X'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
-/// \brief Matches delete expressions.
+/// Matches delete expressions.
///
/// Given
/// \code
@@ -1554,7 +1586,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
cxxDeleteExpr;
-/// \brief Matches array subscript expressions.
+/// Matches array subscript expressions.
///
/// Given
/// \code
@@ -1565,7 +1597,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr>
arraySubscriptExpr;
-/// \brief Matches the value of a default argument at the call site.
+/// Matches the value of a default argument at the call site.
///
/// Example matches the CXXDefaultArgExpr placeholder inserted for the
/// default value of the second parameter in the call expression f(42)
@@ -1577,7 +1609,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
cxxDefaultArgExpr;
-/// \brief Matches overloaded operator calls.
+/// Matches overloaded operator calls.
///
/// Note that if an operator isn't overloaded, it won't match. Instead, use
/// binaryOperator matcher.
@@ -1594,7 +1626,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
cxxOperatorCallExpr;
-/// \brief Matches expressions.
+/// Matches expressions.
///
/// Example matches x()
/// \code
@@ -1602,7 +1634,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
-/// \brief Matches expressions that refer to declarations.
+/// Matches expressions that refer to declarations.
///
/// Example matches x in if (x)
/// \code
@@ -1612,7 +1644,21 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr>
declRefExpr;
-/// \brief Matches if statements.
+/// Matches a reference to an ObjCIvar.
+///
+/// Example: matches "a" in "init" method:
+/// \code
+/// @implementation A {
+/// NSString *a;
+/// }
+/// - (void) init {
+/// a = @"hello";
+/// }
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr>
+ objcIvarRefExpr;
+
+/// Matches if statements.
///
/// Example matches 'if (x) {}'
/// \code
@@ -1620,7 +1666,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
-/// \brief Matches for statements.
+/// Matches for statements.
///
/// Example matches 'for (;;) {}'
/// \code
@@ -1629,7 +1675,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
-/// \brief Matches the increment statement of a for loop.
+/// Matches the increment statement of a for loop.
///
/// Example:
/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
@@ -1644,7 +1690,7 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
InnerMatcher.matches(*Increment, Finder, Builder));
}
-/// \brief Matches the initialization statement of a for loop.
+/// Matches the initialization statement of a for loop.
///
/// Example:
/// forStmt(hasLoopInit(declStmt()))
@@ -1658,7 +1704,7 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder));
}
-/// \brief Matches range-based for statements.
+/// Matches range-based for statements.
///
/// cxxForRangeStmt() matches 'for (auto a : i)'
/// \code
@@ -1668,7 +1714,7 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
cxxForRangeStmt;
-/// \brief Matches the initialization statement of a for loop.
+/// Matches the initialization statement of a for loop.
///
/// Example:
/// forStmt(hasLoopVariable(anything()))
@@ -1682,7 +1728,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>,
return (Var != nullptr && InnerMatcher.matches(*Var, Finder, Builder));
}
-/// \brief Matches the range initialization statement of a for loop.
+/// Matches the range initialization statement of a for loop.
///
/// Example:
/// forStmt(hasRangeInit(anything()))
@@ -1696,7 +1742,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>,
return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder));
}
-/// \brief Matches while statements.
+/// Matches while statements.
///
/// Given
/// \code
@@ -1706,7 +1752,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>,
/// matches 'while (true) {}'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
-/// \brief Matches do statements.
+/// Matches do statements.
///
/// Given
/// \code
@@ -1716,7 +1762,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
/// matches 'do {} while(true)'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
-/// \brief Matches break statements.
+/// Matches break statements.
///
/// Given
/// \code
@@ -1726,7 +1772,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
/// matches 'break'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
-/// \brief Matches continue statements.
+/// Matches continue statements.
///
/// Given
/// \code
@@ -1737,7 +1783,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt>
continueStmt;
-/// \brief Matches return statements.
+/// Matches return statements.
///
/// Given
/// \code
@@ -1747,7 +1793,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt>
/// matches 'return 1'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
-/// \brief Matches goto statements.
+/// Matches goto statements.
///
/// Given
/// \code
@@ -1758,7 +1804,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
/// matches 'goto FOO'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
-/// \brief Matches label statements.
+/// Matches label statements.
///
/// Given
/// \code
@@ -1769,7 +1815,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
/// matches 'FOO:'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
-/// \brief Matches address of label statements (GNU extension).
+/// Matches address of label statements (GNU extension).
///
/// Given
/// \code
@@ -1782,7 +1828,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr>
addrLabelExpr;
-/// \brief Matches switch statements.
+/// Matches switch statements.
///
/// Given
/// \code
@@ -1792,47 +1838,47 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr>
/// matches 'switch(a)'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
-/// \brief Matches case and default statements inside switch statements.
+/// Matches case and default statements inside switch statements.
///
/// Given
/// \code
/// switch(a) { case 42: break; default: break; }
/// \endcode
/// switchCase()
-/// matches 'case 42: break;' and 'default: break;'.
+/// matches 'case 42:' and 'default:'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
-/// \brief Matches case statements inside switch statements.
+/// Matches case statements inside switch statements.
///
/// Given
/// \code
/// switch(a) { case 42: break; default: break; }
/// \endcode
/// caseStmt()
-/// matches 'case 42: break;'.
+/// matches 'case 42:'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
-/// \brief Matches default statements inside switch statements.
+/// Matches default statements inside switch statements.
///
/// Given
/// \code
/// switch(a) { case 42: break; default: break; }
/// \endcode
/// defaultStmt()
-/// matches 'default: break;'.
+/// matches 'default:'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt>
defaultStmt;
-/// \brief Matches compound statements.
+/// Matches compound statements.
///
-/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
+/// Example matches '{}' and '{{}}' in 'for (;;) {{}}'
/// \code
/// for (;;) {{}}
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt>
compoundStmt;
-/// \brief Matches catch statements.
+/// Matches catch statements.
///
/// \code
/// try {} catch(int i) {}
@@ -1842,7 +1888,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt>
cxxCatchStmt;
-/// \brief Matches try statements.
+/// Matches try statements.
///
/// \code
/// try {} catch(int i) {}
@@ -1851,7 +1897,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt>
/// matches 'try {}'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
-/// \brief Matches throw expressions.
+/// Matches throw expressions.
///
/// \code
/// try { throw 5; } catch(int i) {}
@@ -1861,7 +1907,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr>
cxxThrowExpr;
-/// \brief Matches null statements.
+/// Matches null statements.
///
/// \code
/// foo();;
@@ -1870,7 +1916,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr>
/// matches the second ';'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
-/// \brief Matches asm statements.
+/// Matches asm statements.
///
/// \code
/// int i = 100;
@@ -1880,7 +1926,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
/// matches '__asm("mov al, 2")'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
-/// \brief Matches bool literals.
+/// Matches bool literals.
///
/// Example matches true
/// \code
@@ -1889,7 +1935,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr>
cxxBoolLiteral;
-/// \brief Matches string literals (also matches wide string literals).
+/// Matches string literals (also matches wide string literals).
///
/// Example matches "abcd", L"abcd"
/// \code
@@ -1899,7 +1945,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral>
stringLiteral;
-/// \brief Matches character literals (also matches wchar_t).
+/// Matches character literals (also matches wchar_t).
///
/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
/// though.
@@ -1912,14 +1958,14 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
characterLiteral;
-/// \brief Matches integer literals of all sizes / encodings, e.g.
+/// Matches integer literals of all sizes / encodings, e.g.
/// 1, 1L, 0x1 and 1U.
///
/// Does not match character-encoded integers such as L'a'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
integerLiteral;
-/// \brief Matches float literals of all sizes / encodings, e.g.
+/// Matches float literals of all sizes / encodings, e.g.
/// 1.0, 1.0f, 1.0L and 1e10.
///
/// Does not match implicit conversions such as
@@ -1929,13 +1975,13 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral>
floatLiteral;
-/// \brief Matches user defined literal operator call.
+/// Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
userDefinedLiteral;
-/// \brief Matches compound (i.e. non-scalar) literals
+/// Matches compound (i.e. non-scalar) literals
///
/// Example match: {1}, (1, 2)
/// \code
@@ -1945,22 +1991,22 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
compoundLiteralExpr;
-/// \brief Matches nullptr literal.
+/// Matches nullptr literal.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
cxxNullPtrLiteralExpr;
-/// \brief Matches GNU __null expression.
+/// Matches GNU __null expression.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr>
gnuNullExpr;
-/// \brief Matches atomic builtins.
+/// Matches atomic builtins.
/// Example matches __atomic_load_n(ptr, 1)
/// \code
/// void foo() { int *ptr; __atomic_load_n(ptr, 1); }
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
-/// \brief Matches statement expression (GNU extension).
+/// Matches statement expression (GNU extension).
///
/// Example match: ({ int X = 4; X; })
/// \code
@@ -1968,7 +2014,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
-/// \brief Matches binary operator expressions.
+/// Matches binary operator expressions.
///
/// Example matches a || b
/// \code
@@ -1977,7 +2023,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
binaryOperator;
-/// \brief Matches unary operator expressions.
+/// Matches unary operator expressions.
///
/// Example matches !a
/// \code
@@ -1986,7 +2032,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator>
unaryOperator;
-/// \brief Matches conditional operator expressions.
+/// Matches conditional operator expressions.
///
/// Example matches a ? b : c
/// \code
@@ -1995,7 +2041,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
conditionalOperator;
-/// \brief Matches binary conditional operator expressions (GNU extension).
+/// Matches binary conditional operator expressions (GNU extension).
///
/// Example matches a ?: b
/// \code
@@ -2005,7 +2051,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
BinaryConditionalOperator>
binaryConditionalOperator;
-/// \brief Matches opaque value expressions. They are used as helpers
+/// Matches opaque value expressions. They are used as helpers
/// to reference another expressions and can be met
/// in BinaryConditionalOperators, for example.
///
@@ -2016,7 +2062,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
opaqueValueExpr;
-/// \brief Matches a C++ static_assert declaration.
+/// Matches a C++ static_assert declaration.
///
/// Example:
/// staticAssertExpr()
@@ -2032,7 +2078,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
staticAssertDecl;
-/// \brief Matches a reinterpret_cast expression.
+/// Matches a reinterpret_cast expression.
///
/// Either the source expression or the destination type can be matched
/// using has(), but hasDestinationType() is more specific and can be
@@ -2045,7 +2091,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
cxxReinterpretCastExpr;
-/// \brief Matches a C++ static_cast expression.
+/// Matches a C++ static_cast expression.
///
/// \see hasDestinationType
/// \see reinterpretCast
@@ -2061,7 +2107,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr>
cxxStaticCastExpr;
-/// \brief Matches a dynamic_cast expression.
+/// Matches a dynamic_cast expression.
///
/// Example:
/// cxxDynamicCastExpr()
@@ -2076,7 +2122,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr>
cxxDynamicCastExpr;
-/// \brief Matches a const_cast expression.
+/// Matches a const_cast expression.
///
/// Example: Matches const_cast<int*>(&r) in
/// \code
@@ -2087,7 +2133,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr>
cxxConstCastExpr;
-/// \brief Matches a C-style cast expression.
+/// Matches a C-style cast expression.
///
/// Example: Matches (int) 2.2f in
/// \code
@@ -2096,7 +2142,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
cStyleCastExpr;
-/// \brief Matches explicit cast expressions.
+/// Matches explicit cast expressions.
///
/// Matches any cast expression written in user code, whether it be a
/// C-style cast, a functional-style cast, or a keyword cast.
@@ -2120,14 +2166,14 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr>
explicitCastExpr;
-/// \brief Matches the implicit cast nodes of Clang's AST.
+/// 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.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
implicitCastExpr;
-/// \brief Matches any cast nodes of Clang's AST.
+/// Matches any cast nodes of Clang's AST.
///
/// Example: castExpr() matches each of the following:
/// \code
@@ -2142,7 +2188,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
-/// \brief Matches functional cast expressions
+/// Matches functional cast expressions
///
/// Example: Matches Foo(bar);
/// \code
@@ -2153,7 +2199,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
cxxFunctionalCastExpr;
-/// \brief Matches functional cast expressions having N != 1 arguments
+/// Matches functional cast expressions having N != 1 arguments
///
/// Example: Matches Foo(bar, bar)
/// \code
@@ -2162,7 +2208,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
cxxTemporaryObjectExpr;
-/// \brief Matches predefined identifier expressions [C99 6.4.2.2].
+/// Matches predefined identifier expressions [C99 6.4.2.2].
///
/// Example: Matches __func__
/// \code
@@ -2171,7 +2217,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr>
predefinedExpr;
-/// \brief Matches C99 designated initializer expressions [C99 6.7.8].
+/// Matches C99 designated initializer expressions [C99 6.7.8].
///
/// Example: Matches { [2].y = 1.0, [0].x = 1.0 }
/// \code
@@ -2180,7 +2226,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
designatedInitExpr;
-/// \brief Matches designated initializer expressions that contain
+/// Matches designated initializer expressions that contain
/// a specific number of designators.
///
/// Example: Given
@@ -2195,16 +2241,16 @@ AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) {
return Node.size() == N;
}
-/// \brief Matches \c QualTypes in the clang AST.
+/// Matches \c QualTypes in the clang AST.
extern const internal::VariadicAllOfMatcher<QualType> qualType;
-/// \brief Matches \c Types in the clang AST.
+/// Matches \c Types in the clang AST.
extern const internal::VariadicAllOfMatcher<Type> type;
-/// \brief Matches \c TypeLocs in the clang AST.
+/// Matches \c TypeLocs in the clang AST.
extern const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
-/// \brief Matches if any of the given matchers matches.
+/// Matches if any of the given matchers matches.
///
/// Unlike \c anyOf, \c eachOf will generate a match result for each
/// matching submatcher.
@@ -2227,21 +2273,21 @@ extern const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
eachOf;
-/// \brief Matches if any of the given matchers matches.
+/// Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
anyOf;
-/// \brief Matches if all given matchers match.
+/// Matches if all given matchers match.
///
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
allOf;
-/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
+/// Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
///
/// Given
/// \code
@@ -2254,7 +2300,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
UnaryExprOrTypeTraitExpr>
unaryExprOrTypeTraitExpr;
-/// \brief Matches unary expressions that have a specific type of argument.
+/// Matches unary expressions that have a specific type of argument.
///
/// Given
/// \code
@@ -2268,7 +2314,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType,
return InnerMatcher.matches(ArgumentType, Finder, Builder);
}
-/// \brief Matches unary expressions of a certain kind.
+/// Matches unary expressions of a certain kind.
///
/// Given
/// \code
@@ -2281,7 +2327,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
return Node.getKind() == Kind;
}
-/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// Same as unaryExprOrTypeTraitExpr, but only matching
/// alignof.
inline internal::Matcher<Stmt> alignOfExpr(
const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
@@ -2289,7 +2335,7 @@ inline internal::Matcher<Stmt> alignOfExpr(
ofKind(UETT_AlignOf), InnerMatcher)));
}
-/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// Same as unaryExprOrTypeTraitExpr, but only matching
/// sizeof.
inline internal::Matcher<Stmt> sizeOfExpr(
const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
@@ -2297,7 +2343,7 @@ inline internal::Matcher<Stmt> sizeOfExpr(
allOf(ofKind(UETT_SizeOf), InnerMatcher)));
}
-/// \brief Matches NamedDecl nodes that have the specified name.
+/// Matches NamedDecl nodes that have the specified name.
///
/// Supports specifying enclosing namespaces or classes by prefixing the name
/// with '<enclosing>::'.
@@ -2313,12 +2359,10 @@ inline internal::Matcher<Stmt> sizeOfExpr(
/// namespace a { namespace b { class X; } }
/// \endcode
inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
- std::vector<std::string> Names;
- Names.push_back(Name);
- return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names));
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher({Name}));
}
-/// \brief Matches NamedDecl nodes that have any of the specified names.
+/// Matches NamedDecl nodes that have any of the specified names.
///
/// This matcher is only provided as a performance optimization of hasName.
/// \code
@@ -2332,7 +2376,7 @@ extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
internal::hasAnyNameFunc>
hasAnyName;
-/// \brief Matches NamedDecl nodes whose fully qualified names contain
+/// Matches NamedDecl nodes whose fully qualified names contain
/// a substring matched by the given RegExp.
///
/// Supports specifying enclosing namespaces or classes by
@@ -2355,7 +2399,7 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
return RE.match(FullNameString);
}
-/// \brief Matches overloaded operator names.
+/// Matches overloaded operator names.
///
/// Matches overloaded operator names specified in strings without the
/// "operator" prefix: e.g. "<<".
@@ -2383,7 +2427,7 @@ hasOverloadedOperatorName(StringRef Name) {
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
}
-/// \brief Matches C++ classes that are directly or indirectly derived from
+/// Matches C++ classes that are directly or indirectly derived from
/// a class matching \c Base.
///
/// Note that a class is not considered to be derived from itself.
@@ -2409,13 +2453,13 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
return Finder->classIsDerivedFrom(&Node, Base, Builder);
}
-/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
+/// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
assert(!BaseName.empty());
return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
-/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly
+/// Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
internal::Matcher<NamedDecl>, Base, 0) {
@@ -2423,7 +2467,7 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
.matches(Node, Finder, Builder);
}
-/// \brief Overloaded method as shortcut for
+/// Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
BaseName, 1) {
@@ -2431,7 +2475,7 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
-/// \brief Matches the first method of a class or struct that satisfies \c
+/// Matches the first method of a class or struct that satisfies \c
/// InnerMatcher.
///
/// Given:
@@ -2448,7 +2492,7 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
Node.method_end(), Finder, Builder);
}
-/// \brief Matches the generated class of lambda expressions.
+/// Matches the generated class of lambda expressions.
///
/// Given:
/// \code
@@ -2461,7 +2505,7 @@ AST_MATCHER(CXXRecordDecl, isLambda) {
return Node.isLambda();
}
-/// \brief Matches AST nodes that have child AST nodes that match the
+/// Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
/// Example matches X, Y
@@ -2481,7 +2525,7 @@ AST_MATCHER(CXXRecordDecl, isLambda) {
/// has(ignoringParenImpCasts(expr())).
extern const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has;
-/// \brief Matches AST nodes that have descendant AST nodes that match the
+/// Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
///
/// Example matches X, Y, Z
@@ -2499,14 +2543,15 @@ extern const internal::ArgumentAdaptingMatcherFunc<
internal::HasDescendantMatcher>
hasDescendant;
-/// \brief Matches AST nodes that have child AST nodes that match the
+/// Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Example matches X, Y
+/// Example matches X, Y, Y::X, Z::Y, Z::Y::X
/// (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
/// \code
-/// class X {}; // Matches X, because X::X is a class of name X inside X.
-/// class Y { class X {}; };
+/// class X {};
+/// class Y { class X {}; }; // Matches Y, because Y::X is a class of name X
+/// // inside Y.
/// class Z { class Y { class X {}; }; }; // Does not match Z.
/// \endcode
///
@@ -2519,14 +2564,15 @@ extern const internal::ArgumentAdaptingMatcherFunc<
extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
forEach;
-/// \brief Matches AST nodes that have descendant AST nodes that match the
+/// Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
///
-/// Example matches X, A, B, C
+/// Example matches X, A, A::X, B, B::C, B::C::X
/// (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
/// \code
-/// class X {}; // Matches X, because X::X is a class of name X inside X.
-/// class A { class X {}; };
+/// class X {};
+/// class A { class X {}; }; // Matches A, because A::X is a class of name
+/// // X inside A.
/// class B { class C { class X {}; }; };
/// \endcode
///
@@ -2549,7 +2595,7 @@ extern const internal::ArgumentAdaptingMatcherFunc<
internal::ForEachDescendantMatcher>
forEachDescendant;
-/// \brief Matches if the node or any descendant matches.
+/// Matches if the node or any descendant matches.
///
/// Generates results for each match.
///
@@ -2570,7 +2616,7 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
return eachOf(Matcher, forEachDescendant(Matcher));
}
-/// \brief Matches AST nodes that have a parent that matches the provided
+/// Matches AST nodes that have a parent that matches the provided
/// matcher.
///
/// Given
@@ -2586,7 +2632,7 @@ extern const internal::ArgumentAdaptingMatcherFunc<
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
hasParent;
-/// \brief Matches AST nodes that have an ancestor that matches the provided
+/// Matches AST nodes that have an ancestor that matches the provided
/// matcher.
///
/// Given
@@ -2603,7 +2649,7 @@ extern const internal::ArgumentAdaptingMatcherFunc<
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
hasAncestor;
-/// \brief Matches if the provided matcher does not match.
+/// Matches if the provided matcher does not match.
///
/// Example matches Y (matcher = cxxRecordDecl(unless(hasName("X"))))
/// \code
@@ -2614,7 +2660,7 @@ extern const internal::ArgumentAdaptingMatcherFunc<
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
-/// \brief Matches a node if the declaration associated with that node
+/// Matches a node if the declaration associated with that node
/// matches the given matcher.
///
/// The associated declaration is:
@@ -2623,6 +2669,7 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
/// - for MemberExpr, the declaration of the referenced member
/// - for CXXConstructExpr, the declaration of the constructor
/// - for CXXNewExpr, the declaration of the operator new
+/// - for ObjCIvarExpr, the declaration of the ivar
///
/// For type nodes, hasDeclaration will generally match the declaration of the
/// sugared type. Given
@@ -2656,7 +2703,7 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
void(internal::HasDeclarationSupportedTypes)>(InnerMatcher);
}
-/// \brief Matches a \c NamedDecl whose underlying declaration matches the given
+/// Matches a \c NamedDecl whose underlying declaration matches the given
/// matcher.
///
/// Given
@@ -2675,13 +2722,13 @@ AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>,
InnerMatcher.matches(*UnderlyingDecl, Finder, Builder);
}
-/// \brief Matches on the implicit object argument of a member call expression.
+/// Matches on the implicit object argument of a member call expression.
///
/// Example matches y.x()
/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
/// \code
/// class Y { public: void x(); };
-/// void z() { Y y; y.x(); }",
+/// void z() { Y y; y.x(); }
/// \endcode
///
/// FIXME: Overload to allow directly matching types?
@@ -2694,7 +2741,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
}
-/// \brief Matches on the receiver of an ObjectiveC Message expression.
+/// Matches on the receiver of an ObjectiveC Message expression.
///
/// Example
/// matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *")));
@@ -2709,8 +2756,43 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
const QualType TypeDecl = Node.getReceiverType();
return InnerMatcher.matches(TypeDecl, Finder, Builder);
}
-
-/// \brief Matches when BaseName == Selector.getAsString()
+
+/// Returns true when the Objective-C message is sent to an instance.
+///
+/// Example
+/// matcher = objcMessagaeExpr(isInstanceMessage())
+/// matches
+/// \code
+/// NSString *x = @"hello";
+/// [x containsString:@"h"];
+/// \endcode
+/// but not
+/// \code
+/// [NSString stringWithFormat:@"format"];
+/// \endcode
+AST_MATCHER(ObjCMessageExpr, isInstanceMessage) {
+ return Node.isInstanceMessage();
+}
+
+/// Matches if the Objective-C message is sent to an instance,
+/// and the inner matcher matches on that instance.
+///
+/// For example the method call in
+/// \code
+/// NSString *x = @"hello";
+/// [x containsString:@"h"];
+/// \endcode
+/// is matched by
+/// objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
+AST_MATCHER_P(ObjCMessageExpr, hasReceiver, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *ReceiverNode = Node.getInstanceReceiver();
+ return (ReceiverNode != nullptr &&
+ InnerMatcher.matches(*ReceiverNode->IgnoreParenImpCasts(), Finder,
+ Builder));
+}
+
+/// Matches when BaseName == Selector.getAsString()
///
/// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
/// matches the outer message expr in the code below, but NOT the message
@@ -2723,8 +2805,22 @@ AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
return BaseName.compare(Sel.getAsString()) == 0;
}
-
-/// \brief Matches ObjC selectors whose name contains
+
+/// Matches when at least one of the supplied string equals to the
+/// Selector.getAsString()
+///
+/// matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
+/// matches both of the expressions below:
+/// \code
+/// [myObj methodA:argA];
+/// [myObj methodB:argB];
+/// \endcode
+extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>,
+ StringRef,
+ internal::hasAnySelectorFunc>
+ hasAnySelector;
+
+/// Matches ObjC selectors whose name contains
/// a substring matched by the given RegExp.
/// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"));
/// matches the outer message expr in the code below, but NOT the message
@@ -2739,7 +2835,7 @@ AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) {
return RE.match(SelectorString);
}
-/// \brief Matches when the selector is the empty selector
+/// Matches when the selector is the empty selector
///
/// Matches only when the selector of the objCMessageExpr is NULL. This may
/// represent an error condition in the tree!
@@ -2747,7 +2843,7 @@ AST_MATCHER(ObjCMessageExpr, hasNullSelector) {
return Node.getSelector().isNull();
}
-/// \brief Matches when the selector is a Unary Selector
+/// Matches when the selector is a Unary Selector
///
/// matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
/// matches self.bodyView in the code below, but NOT the outer message
@@ -2759,7 +2855,7 @@ AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
return Node.getSelector().isUnarySelector();
}
-/// \brief Matches when the selector is a keyword selector
+/// Matches when the selector is a keyword selector
///
/// objCMessageExpr(hasKeywordSelector()) matches the generated setFrame
/// message expression in
@@ -2775,7 +2871,7 @@ AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
return Node.getSelector().isKeywordSelector();
}
-/// \brief Matches when the selector has the specified number of arguments
+/// Matches when the selector has the specified number of arguments
///
/// matcher = objCMessageExpr(numSelectorArgs(0));
/// matches self.bodyView in the code below
@@ -2789,8 +2885,8 @@ AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
return Node.getSelector().getNumArgs() == N;
}
-
-/// \brief Matches if the call expression's callee expression matches.
+
+/// Matches if the call expression's callee expression matches.
///
/// Given
/// \code
@@ -2813,7 +2909,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
-/// \brief Matches if the call expression's callee's declaration matches the
+/// Matches if the call expression's callee's declaration matches the
/// given matcher.
///
/// Example matches y.x() (matcher = callExpr(callee(
@@ -2827,25 +2923,31 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder);
}
-/// \brief Matches if the expression's or declaration's type matches a type
+/// Matches if the expression's or declaration's type matches a type
/// matcher.
///
/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// and U (matcher = typedefDecl(hasType(asString("int")))
+/// and friend class X (matcher = friendDecl(hasType("X"))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
/// typedef int U;
+/// class Y { friend class X; };
/// \endcode
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
- hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefNameDecl, ValueDecl),
+ hasType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, TypedefNameDecl,
+ ValueDecl),
internal::Matcher<QualType>, InnerMatcher, 0) {
- return InnerMatcher.matches(internal::getUnderlyingType(Node),
- Finder, Builder);
+ QualType QT = internal::getUnderlyingType(Node);
+ if (!QT.isNull())
+ return InnerMatcher.matches(QT, Finder, Builder);
+ return false;
}
-/// \brief Overloaded to match the declaration of the expression's or value
+/// Overloaded to match the declaration of the expression's or value
/// declaration's type.
///
/// In case of a value declaration (for example a variable declaration),
@@ -2856,21 +2958,24 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
///
/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+/// and friend class X (matcher = friendDecl(hasType("X"))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
+/// class Y { friend class X; };
/// \endcode
///
/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
-AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType,
- AST_POLYMORPHIC_SUPPORTED_TYPES(Expr,
- ValueDecl),
- internal::Matcher<Decl>, InnerMatcher, 1) {
- return qualType(hasDeclaration(InnerMatcher))
- .matches(Node.getType(), Finder, Builder);
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl),
+ internal::Matcher<Decl>, InnerMatcher, 1) {
+ QualType QT = internal::getUnderlyingType(Node);
+ if (!QT.isNull())
+ return qualType(hasDeclaration(InnerMatcher)).matches(QT, Finder, Builder);
+ return false;
}
-/// \brief Matches if the type location of the declarator decl's type matches
+/// Matches if the type location of the declarator decl's type matches
/// the inner matcher.
///
/// Given
@@ -2886,7 +2991,7 @@ AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder);
}
-/// \brief Matches if the matched type is represented by the given string.
+/// Matches if the matched type is represented by the given string.
///
/// Given
/// \code
@@ -2899,7 +3004,7 @@ AST_MATCHER_P(QualType, asString, std::string, Name) {
return Name == Node.getAsString();
}
-/// \brief Matches if the matched type is a pointer type and the pointee type
+/// Matches if the matched type is a pointer type and the pointee type
/// matches the specified matcher.
///
/// Example matches y->x()
@@ -2916,14 +3021,14 @@ AST_MATCHER_P(
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
-/// \brief Overloaded to match the pointee type's declaration.
+/// Overloaded to match the pointee type's declaration.
AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
InnerMatcher, 1) {
return pointsTo(qualType(hasDeclaration(InnerMatcher)))
.matches(Node, Finder, Builder);
}
-/// \brief Matches if the matched type matches the unqualified desugared
+/// Matches if the matched type matches the unqualified desugared
/// type of the matched node.
///
/// For example, in:
@@ -2931,7 +3036,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// class A {};
/// using B = A;
/// \endcode
-/// The matcher type(hasUnqualifeidDesugaredType(recordType())) matches
+/// The matcher type(hasUnqualifiedDesugaredType(recordType())) matches
/// both B and A.
AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
InnerMatcher) {
@@ -2939,7 +3044,7 @@ AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
Builder);
}
-/// \brief Matches if the matched type is a reference type and the referenced
+/// Matches if the matched type is a reference type and the referenced
/// type matches the specified matcher.
///
/// Example matches X &x and const X &y
@@ -2958,7 +3063,7 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
-/// \brief Matches QualTypes whose canonical type matches InnerMatcher.
+/// Matches QualTypes whose canonical type matches InnerMatcher.
///
/// Given:
/// \code
@@ -2977,7 +3082,7 @@ AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>,
return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder);
}
-/// \brief Overloaded to match the referenced type's declaration.
+/// Overloaded to match the referenced type's declaration.
AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
InnerMatcher, 1) {
return references(qualType(hasDeclaration(InnerMatcher)))
@@ -2991,7 +3096,7 @@ AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
-/// \brief Matches if the expression's type either matches the specified
+/// Matches if the expression's type either matches the specified
/// matcher, or is a pointer to a type that matches the InnerMatcher.
AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
internal::Matcher<QualType>, InnerMatcher, 0) {
@@ -3000,7 +3105,7 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
.matches(Node, Finder, Builder);
}
-/// \brief Overloaded to match the type's declaration.
+/// Overloaded to match the type's declaration.
AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
internal::Matcher<Decl>, InnerMatcher, 1) {
return onImplicitObjectArgument(
@@ -3008,7 +3113,7 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
.matches(Node, Finder, Builder);
}
-/// \brief Matches a DeclRefExpr that refers to a declaration that matches the
+/// Matches a DeclRefExpr that refers to a declaration that matches the
/// specified matcher.
///
/// Example matches x in if(x)
@@ -3024,7 +3129,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
InnerMatcher.matches(*DeclNode, Finder, Builder));
}
-/// \brief Matches a \c DeclRefExpr that refers to a declaration through a
+/// Matches a \c DeclRefExpr that refers to a declaration through a
/// specific using shadow declaration.
///
/// Given
@@ -3046,7 +3151,7 @@ AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
return false;
}
-/// \brief Matches an \c OverloadExpr if any of the declarations in the set of
+/// Matches an \c OverloadExpr if any of the declarations in the set of
/// overloads matches the given matcher.
///
/// Given
@@ -3067,7 +3172,7 @@ AST_MATCHER_P(OverloadExpr, hasAnyDeclaration, internal::Matcher<Decl>,
Node.decls_end(), Finder, Builder);
}
-/// \brief Matches the Decl of a DeclStmt which has a single declaration.
+/// Matches the Decl of a DeclStmt which has a single declaration.
///
/// Given
/// \code
@@ -3084,7 +3189,7 @@ AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) {
return false;
}
-/// \brief Matches a variable declaration that has an initializer expression
+/// Matches a variable declaration that has an initializer expression
/// that matches the given matcher.
///
/// Example matches x (matcher = varDecl(hasInitializer(callExpr())))
@@ -3100,7 +3205,7 @@ AST_MATCHER_P(
InnerMatcher.matches(*Initializer, Finder, Builder));
}
-/// \brief Matches a variable declaration that has function scope and is a
+/// Matches a variable declaration that has function scope and is a
/// non-static local variable.
///
/// Example matches x (matcher = varDecl(hasLocalStorage())
@@ -3115,7 +3220,7 @@ AST_MATCHER(VarDecl, hasLocalStorage) {
return Node.hasLocalStorage();
}
-/// \brief Matches a variable declaration that does not have local storage.
+/// Matches a variable declaration that does not have local storage.
///
/// Example matches y and z (matcher = varDecl(hasGlobalStorage())
/// \code
@@ -3129,7 +3234,7 @@ AST_MATCHER(VarDecl, hasGlobalStorage) {
return Node.hasGlobalStorage();
}
-/// \brief Matches a variable declaration that has automatic storage duration.
+/// Matches a variable declaration that has automatic storage duration.
///
/// Example matches x, but not y, z, or a.
/// (matcher = varDecl(hasAutomaticStorageDuration())
@@ -3145,7 +3250,7 @@ AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
return Node.getStorageDuration() == SD_Automatic;
}
-/// \brief Matches a variable declaration that has static storage duration.
+/// Matches a variable declaration that has static storage duration.
/// It includes the variable declared at namespace scope and those declared
/// with "static" and "extern" storage class specifiers.
///
@@ -3165,7 +3270,7 @@ AST_MATCHER(VarDecl, hasStaticStorageDuration) {
return Node.getStorageDuration() == SD_Static;
}
-/// \brief Matches a variable declaration that has thread storage duration.
+/// Matches a variable declaration that has thread storage duration.
///
/// Example matches z, but not x, z, or a.
/// (matcher = varDecl(hasThreadStorageDuration())
@@ -3181,7 +3286,7 @@ AST_MATCHER(VarDecl, hasThreadStorageDuration) {
return Node.getStorageDuration() == SD_Thread;
}
-/// \brief Matches a variable declaration that is an exception variable from
+/// Matches a variable declaration that is an exception variable from
/// a C++ catch block, or an Objective-C \@catch statement.
///
/// Example matches x (matcher = varDecl(isExceptionVariable())
@@ -3196,7 +3301,7 @@ AST_MATCHER(VarDecl, isExceptionVariable) {
return Node.isExceptionVariable();
}
-/// \brief Checks that a call expression or a constructor call expression has
+/// Checks that a call expression or a constructor call expression has
/// a specific number of arguments (including absent default arguments).
///
/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
@@ -3212,7 +3317,7 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
return Node.getNumArgs() == N;
}
-/// \brief Matches the n'th argument of a call expression or a constructor
+/// Matches the n'th argument of a call expression or a constructor
/// call expression.
///
/// Example matches y in x(y)
@@ -3230,7 +3335,7 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
}
-/// \brief Matches declaration statements that contain a specific number of
+/// Matches declaration statements that contain a specific number of
/// declarations.
///
/// Example: Given
@@ -3245,7 +3350,7 @@ AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) {
return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N;
}
-/// \brief Matches the n'th declaration of a declaration statement.
+/// Matches the n'th declaration of a declaration statement.
///
/// Note that this does not work for global declarations because the AST
/// breaks up multiple-declaration DeclStmt's into multiple single-declaration
@@ -3274,7 +3379,7 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
return InnerMatcher.matches(**Iterator, Finder, Builder);
}
-/// \brief Matches a C++ catch statement that has a catch-all handler.
+/// Matches a C++ catch statement that has a catch-all handler.
///
/// Given
/// \code
@@ -3291,7 +3396,7 @@ AST_MATCHER(CXXCatchStmt, isCatchAll) {
return Node.getExceptionDecl() == nullptr;
}
-/// \brief Matches a constructor initializer.
+/// Matches a constructor initializer.
///
/// Given
/// \code
@@ -3310,7 +3415,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
Node.init_end(), Finder, Builder);
}
-/// \brief Matches the field declaration of a constructor initializer.
+/// Matches the field declaration of a constructor initializer.
///
/// Given
/// \code
@@ -3330,7 +3435,7 @@ AST_MATCHER_P(CXXCtorInitializer, forField,
InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
}
-/// \brief Matches the initializer expression of a constructor initializer.
+/// Matches the initializer expression of a constructor initializer.
///
/// Given
/// \code
@@ -3350,7 +3455,7 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer,
InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
}
-/// \brief Matches a constructor initializer if it is explicitly written in
+/// Matches a constructor initializer if it is explicitly written in
/// code (as opposed to implicitly added by the compiler).
///
/// Given
@@ -3367,7 +3472,7 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
return Node.isWritten();
}
-/// \brief Matches a constructor initializer if it is initializing a base, as
+/// Matches a constructor initializer if it is initializing a base, as
/// opposed to a member.
///
/// Given
@@ -3387,7 +3492,7 @@ AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
return Node.isBaseInitializer();
}
-/// \brief Matches a constructor initializer if it is initializing a member, as
+/// Matches a constructor initializer if it is initializing a member, as
/// opposed to a base.
///
/// Given
@@ -3407,8 +3512,8 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
return Node.isMemberInitializer();
}
-/// \brief Matches any argument of a call expression or a constructor call
-/// expression.
+/// Matches any argument of a call expression or a constructor call
+/// expression, or an ObjC-message-send expression.
///
/// Given
/// \code
@@ -3418,9 +3523,18 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
/// matches x(1, y, 42)
/// with hasAnyArgument(...)
/// matching y
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// void foo(I *i) { [i f:12]; }
+/// \endcode
+/// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+/// matches [i f:12]
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
- CXXConstructExpr),
+ CXXConstructExpr,
+ ObjCMessageExpr),
internal::Matcher<Expr>, InnerMatcher) {
for (const Expr *Arg : Node.arguments()) {
BoundNodesTreeBuilder Result(*Builder);
@@ -3432,12 +3546,12 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
return false;
}
-/// \brief Matches a constructor call expression which uses list initialization.
+/// Matches a constructor call expression which uses list initialization.
AST_MATCHER(CXXConstructExpr, isListInitialization) {
return Node.isListInitialization();
}
-/// \brief Matches a constructor call expression which requires
+/// Matches a constructor call expression which requires
/// zero initialization.
///
/// Given
@@ -3453,7 +3567,8 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
return Node.requiresZeroInitialization();
}
-/// \brief Matches the n'th parameter of a function declaration.
+/// Matches the n'th parameter of a function or an ObjC method
+/// declaration or a block.
///
/// Given
/// \code
@@ -3463,15 +3578,26 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
/// matches f(int x) {}
/// with hasParameter(...)
/// matching int x
-AST_MATCHER_P2(FunctionDecl, hasParameter,
- unsigned, N, internal::Matcher<ParmVarDecl>,
- InnerMatcher) {
- return (N < Node.getNumParams() &&
- InnerMatcher.matches(
- *Node.getParamDecl(N), Finder, Builder));
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// \endcode
+//
+/// the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+/// matches the declaration of method f with hasParameter
+/// matching y.
+AST_POLYMORPHIC_MATCHER_P2(hasParameter,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ ObjCMethodDecl,
+ BlockDecl),
+ unsigned, N, internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
+ return (N < Node.parameters().size()
+ && InnerMatcher.matches(*Node.parameters()[N], Finder, Builder));
}
-/// \brief Matches all arguments and their respective ParmVarDecl.
+/// Matches all arguments and their respective ParmVarDecl.
///
/// Given
/// \code
@@ -3525,7 +3651,8 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
return Matched;
}
-/// \brief Matches any parameter of a function declaration.
+/// Matches any parameter of a function or an ObjC method declaration or a
+/// block.
///
/// Does not match the 'this' parameter of a method.
///
@@ -3537,13 +3664,35 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
/// matches f(int x, int y, int z) {}
/// with hasAnyParameter(...)
/// matching int y
-AST_MATCHER_P(FunctionDecl, hasAnyParameter,
- internal::Matcher<ParmVarDecl>, InnerMatcher) {
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// \endcode
+//
+/// the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of method f with hasParameter
+/// matching y.
+///
+/// For blocks, given
+/// \code
+/// b = ^(int y) { printf("%d", y) };
+/// \endcode
+///
+/// the matcher blockDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of the block b with hasParameter
+/// matching y.
+AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ ObjCMethodDecl,
+ BlockDecl),
+ internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
Node.param_end(), Finder, Builder);
}
-/// \brief Matches \c FunctionDecls and \c FunctionProtoTypes that have a
+/// Matches \c FunctionDecls and \c FunctionProtoTypes that have a
/// specific parameter count.
///
/// Given
@@ -3555,11 +3704,11 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter,
/// void k(int x, int y, int z, ...);
/// \endcode
/// functionDecl(parameterCountIs(2))
-/// matches void g(int i, int j) {}
+/// matches \c g and \c h
/// functionProtoType(parameterCountIs(2))
-/// matches void h(int i, int j)
+/// matches \c g and \c h
/// functionProtoType(parameterCountIs(3))
-/// matches void k(int x, int y, int z, ...);
+/// matches \c k
AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType),
@@ -3567,7 +3716,23 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
return Node.getNumParams() == N;
}
-/// \brief Matches the return type of a function declaration.
+/// Matches \c FunctionDecls that have a noreturn attribute.
+///
+/// Given
+/// \code
+/// void nope();
+/// [[noreturn]] void a();
+/// __attribute__((noreturn)) void b();
+/// struct c { [[noreturn]] c(); };
+/// \endcode
+/// functionDecl(isNoReturn())
+/// matches all of those except
+/// \code
+/// void nope();
+/// \endcode
+AST_MATCHER(FunctionDecl, isNoReturn) { return Node.isNoReturn(); }
+
+/// Matches the return type of a function declaration.
///
/// Given:
/// \code
@@ -3580,7 +3745,7 @@ AST_MATCHER_P(FunctionDecl, returns,
return InnerMatcher.matches(Node.getReturnType(), Finder, Builder);
}
-/// \brief Matches extern "C" function or variable declarations.
+/// Matches extern "C" function or variable declarations.
///
/// Given:
/// \code
@@ -3600,7 +3765,7 @@ AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
return Node.isExternC();
}
-/// \brief Matches variable/function declarations that have "static" storage
+/// Matches variable/function declarations that have "static" storage
/// class specifier ("static" keyword) written in the source.
///
/// Given:
@@ -3620,7 +3785,7 @@ AST_POLYMORPHIC_MATCHER(isStaticStorageClass,
return Node.getStorageClass() == SC_Static;
}
-/// \brief Matches deleted function declarations.
+/// Matches deleted function declarations.
///
/// Given:
/// \code
@@ -3633,7 +3798,7 @@ AST_MATCHER(FunctionDecl, isDeleted) {
return Node.isDeleted();
}
-/// \brief Matches defaulted function declarations.
+/// Matches defaulted function declarations.
///
/// Given:
/// \code
@@ -3646,7 +3811,7 @@ AST_MATCHER(FunctionDecl, isDefaulted) {
return Node.isDefaulted();
}
-/// \brief Matches functions that have a dynamic exception specification.
+/// Matches functions that have a dynamic exception specification.
///
/// Given:
/// \code
@@ -3669,7 +3834,7 @@ AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec,
return false;
}
-/// \brief Matches functions that have a non-throwing exception specification.
+/// Matches functions that have a non-throwing exception specification.
///
/// Given:
/// \code
@@ -3696,27 +3861,32 @@ AST_POLYMORPHIC_MATCHER(isNoThrow,
if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))
return true;
- return FnTy->isNothrow(Finder->getASTContext());
+ return FnTy->isNothrow();
}
-/// \brief Matches constexpr variable and function declarations.
+/// Matches constexpr variable and function declarations,
+/// and if constexpr.
///
/// Given:
/// \code
/// constexpr int foo = 42;
/// constexpr int bar();
+/// void baz() { if constexpr(1 > 0) {} }
/// \endcode
/// varDecl(isConstexpr())
/// matches the declaration of foo.
/// functionDecl(isConstexpr())
/// matches the declaration of bar.
+/// ifStmt(isConstexpr())
+/// matches the if statement in baz.
AST_POLYMORPHIC_MATCHER(isConstexpr,
AST_POLYMORPHIC_SUPPORTED_TYPES(VarDecl,
- FunctionDecl)) {
+ FunctionDecl,
+ IfStmt)) {
return Node.isConstexpr();
}
-/// \brief Matches the condition expression of an if statement, for loop,
+/// Matches the condition expression of an if statement, for loop,
/// switch statement or conditional operator.
///
/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
@@ -3733,7 +3903,7 @@ AST_POLYMORPHIC_MATCHER_P(
InnerMatcher.matches(*Condition, Finder, Builder));
}
-/// \brief Matches the then-statement of an if statement.
+/// Matches the then-statement of an if statement.
///
/// Examples matches the if statement
/// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true)))))
@@ -3745,7 +3915,7 @@ AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) {
return (Then != nullptr && InnerMatcher.matches(*Then, Finder, Builder));
}
-/// \brief Matches the else-statement of an if statement.
+/// Matches the else-statement of an if statement.
///
/// Examples matches the if statement
/// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true)))))
@@ -3757,7 +3927,7 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder));
}
-/// \brief Matches if a node equals a previously bound node.
+/// Matches if a node equals a previously bound node.
///
/// Matches a node if it equals the node previously bound to \p ID.
///
@@ -3794,7 +3964,7 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
return Builder->removeBindings(Predicate);
}
-/// \brief Matches the condition variable statement in an if statement.
+/// Matches the condition variable statement in an if statement.
///
/// Given
/// \code
@@ -3810,7 +3980,7 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
InnerMatcher.matches(*DeclarationStatement, Finder, Builder);
}
-/// \brief Matches the index expression of an array subscript expression.
+/// Matches the index expression of an array subscript expression.
///
/// Given
/// \code
@@ -3826,7 +3996,7 @@ AST_MATCHER_P(ArraySubscriptExpr, hasIndex,
return false;
}
-/// \brief Matches the base expression of an array subscript expression.
+/// Matches the base expression of an array subscript expression.
///
/// Given
/// \code
@@ -3843,7 +4013,7 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
return false;
}
-/// \brief Matches a 'for', 'while', 'do while' statement or a function
+/// Matches a 'for', 'while', 'do while' statement or a function
/// definition that has a given body.
///
/// Given
@@ -3865,7 +4035,7 @@ AST_POLYMORPHIC_MATCHER_P(hasBody,
InnerMatcher.matches(*Statement, Finder, Builder));
}
-/// \brief Matches compound statements where at least one substatement matches
+/// Matches compound statements where at least one substatement matches
/// a given matcher. Also matches StmtExprs that have CompoundStmt as children.
///
/// Given
@@ -3885,7 +4055,7 @@ AST_POLYMORPHIC_MATCHER_P(hasAnySubstatement,
CS->body_end(), Finder, Builder);
}
-/// \brief Checks that a compound statement contains a specific number of
+/// Checks that a compound statement contains a specific number of
/// child statements.
///
/// Example: Given
@@ -3899,7 +4069,7 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
return Node.size() == N;
}
-/// \brief Matches literals that are equal to the given value of type ValueT.
+/// Matches literals that are equal to the given value of type ValueT.
///
/// Given
/// \code
@@ -3960,7 +4130,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
.matchesNode(Node);
}
-/// \brief Matches the operator Name of operator expressions (binary or
+/// Matches the operator Name of operator expressions (binary or
/// unary).
///
/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
@@ -3974,7 +4144,27 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
return Name == Node.getOpcodeStr(Node.getOpcode());
}
-/// \brief Matches the left hand side of binary operator expressions.
+/// Matches all kinds of assignment operators.
+///
+/// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+/// \code
+/// if (a == b)
+/// a += b;
+/// \endcode
+///
+/// Example 2: matches s1 = s2
+/// (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+/// \code
+/// struct S { S& operator=(const S&); };
+/// void x() { S s1, s2; s1 = s2; })
+/// \endcode
+AST_POLYMORPHIC_MATCHER(isAssignmentOperator,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ CXXOperatorCallExpr)) {
+ return Node.isAssignmentOp();
+}
+
+/// Matches the left hand side of binary operator expressions.
///
/// Example matches a (matcher = binaryOperator(hasLHS()))
/// \code
@@ -3989,7 +4179,7 @@ AST_POLYMORPHIC_MATCHER_P(hasLHS,
InnerMatcher.matches(*LeftHandSide, Finder, Builder));
}
-/// \brief Matches the right hand side of binary operator expressions.
+/// Matches the right hand side of binary operator expressions.
///
/// Example matches b (matcher = binaryOperator(hasRHS()))
/// \code
@@ -4004,14 +4194,14 @@ AST_POLYMORPHIC_MATCHER_P(hasRHS,
InnerMatcher.matches(*RightHandSide, Finder, Builder));
}
-/// \brief Matches if either the left hand side or the right hand side of a
+/// Matches if either the left hand side or the right hand side of a
/// binary operator matches.
inline internal::Matcher<BinaryOperator> hasEitherOperand(
const internal::Matcher<Expr> &InnerMatcher) {
return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher));
}
-/// \brief Matches if the operand of a unary operator matches.
+/// Matches if the operand of a unary operator matches.
///
/// Example matches true (matcher = hasUnaryOperand(
/// cxxBoolLiteral(equals(true))))
@@ -4025,7 +4215,7 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
InnerMatcher.matches(*Operand, Finder, Builder));
}
-/// \brief Matches if the cast's source expression
+/// Matches if the cast's source expression
/// or opaque value's source expression matches the given matcher.
///
/// Example 1: matches "a string"
@@ -4050,7 +4240,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSourceExpression,
InnerMatcher.matches(*SubExpression, Finder, Builder));
}
-/// \brief Matches casts that has a given cast kind.
+/// Matches casts that has a given cast kind.
///
/// Example: matches the implicit cast around \c 0
/// (matcher = castExpr(hasCastKind(CK_NullToPointer)))
@@ -4061,7 +4251,7 @@ AST_MATCHER_P(CastExpr, hasCastKind, CastKind, Kind) {
return Node.getCastKind() == Kind;
}
-/// \brief Matches casts whose destination type matches a given matcher.
+/// Matches casts whose destination type matches a given matcher.
///
/// (Note: Clang's AST refers to other conversions as "casts" too, and calls
/// actual casts "explicit" casts.)
@@ -4071,7 +4261,7 @@ AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
return InnerMatcher.matches(NodeType, Finder, Builder);
}
-/// \brief Matches implicit casts whose destination type matches a given
+/// Matches implicit casts whose destination type matches a given
/// matcher.
///
/// FIXME: Unit test this matcher
@@ -4080,7 +4270,7 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
-/// \brief Matches RecordDecl object that are spelled with "struct."
+/// Matches RecordDecl object that are spelled with "struct."
///
/// Example matches S, but not C or U.
/// \code
@@ -4092,7 +4282,7 @@ AST_MATCHER(RecordDecl, isStruct) {
return Node.isStruct();
}
-/// \brief Matches RecordDecl object that are spelled with "union."
+/// Matches RecordDecl object that are spelled with "union."
///
/// Example matches U, but not C or S.
/// \code
@@ -4104,7 +4294,7 @@ AST_MATCHER(RecordDecl, isUnion) {
return Node.isUnion();
}
-/// \brief Matches RecordDecl object that are spelled with "class."
+/// Matches RecordDecl object that are spelled with "class."
///
/// Example matches C, but not S or U.
/// \code
@@ -4116,7 +4306,7 @@ AST_MATCHER(RecordDecl, isClass) {
return Node.isClass();
}
-/// \brief Matches the true branch expression of a conditional operator.
+/// Matches the true branch expression of a conditional operator.
///
/// Example 1 (conditional ternary operator): matches a
/// \code
@@ -4134,7 +4324,7 @@ AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression,
InnerMatcher.matches(*Expression, Finder, Builder));
}
-/// \brief Matches the false branch expression of a conditional operator
+/// Matches the false branch expression of a conditional operator
/// (binary or ternary).
///
/// Example matches b
@@ -4149,7 +4339,7 @@ AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression,
InnerMatcher.matches(*Expression, Finder, Builder));
}
-/// \brief Matches if a declaration has a body attached.
+/// Matches if a declaration has a body attached.
///
/// Example matches A, va, fa
/// \code
@@ -4176,7 +4366,7 @@ AST_POLYMORPHIC_MATCHER(isDefinition,
return Node.isThisDeclarationADefinition();
}
-/// \brief Matches if a function declaration is variadic.
+/// Matches if a function declaration is variadic.
///
/// Example matches f, but not g or h. The function i will not match, even when
/// compiled in C mode.
@@ -4190,7 +4380,7 @@ AST_MATCHER(FunctionDecl, isVariadic) {
return Node.isVariadic();
}
-/// \brief Matches the class declaration that the given method declaration
+/// Matches the class declaration that the given method declaration
/// belongs to.
///
/// FIXME: Generalize this for other kinds of declarations.
@@ -4214,7 +4404,7 @@ AST_MATCHER_P(CXXMethodDecl, ofClass,
InnerMatcher.matches(*Parent, Finder, Builder));
}
-/// \brief Matches each method overriden by the given method. This matcher may
+/// Matches each method overridden by the given method. This matcher may
/// produce multiple matches.
///
/// Given
@@ -4255,7 +4445,7 @@ AST_MATCHER_P(CXXMethodDecl, forEachOverridden,
return Matched;
}
-/// \brief Matches if the given method declaration is virtual.
+/// Matches if the given method declaration is virtual.
///
/// Given
/// \code
@@ -4269,7 +4459,7 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
-/// \brief Matches if the given method declaration has an explicit "virtual".
+/// Matches if the given method declaration has an explicit "virtual".
///
/// Given
/// \code
@@ -4287,7 +4477,7 @@ AST_MATCHER(CXXMethodDecl, isVirtualAsWritten) {
return Node.isVirtualAsWritten();
}
-/// \brief Matches if the given method or class declaration is final.
+/// Matches if the given method or class declaration is final.
///
/// Given:
/// \code
@@ -4308,7 +4498,7 @@ AST_POLYMORPHIC_MATCHER(isFinal,
return Node.template hasAttr<FinalAttr>();
}
-/// \brief Matches if the given method declaration is pure.
+/// Matches if the given method declaration is pure.
///
/// Given
/// \code
@@ -4322,7 +4512,7 @@ AST_MATCHER(CXXMethodDecl, isPure) {
return Node.isPure();
}
-/// \brief Matches if the given method declaration is const.
+/// Matches if the given method declaration is const.
///
/// Given
/// \code
@@ -4337,7 +4527,7 @@ AST_MATCHER(CXXMethodDecl, isConst) {
return Node.isConst();
}
-/// \brief Matches if the given method declaration declares a copy assignment
+/// Matches if the given method declaration declares a copy assignment
/// operator.
///
/// Given
@@ -4354,7 +4544,7 @@ AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) {
return Node.isCopyAssignmentOperator();
}
-/// \brief Matches if the given method declaration declares a move assignment
+/// Matches if the given method declaration declares a move assignment
/// operator.
///
/// Given
@@ -4371,7 +4561,7 @@ AST_MATCHER(CXXMethodDecl, isMoveAssignmentOperator) {
return Node.isMoveAssignmentOperator();
}
-/// \brief Matches if the given method declaration overrides another method.
+/// Matches if the given method declaration overrides another method.
///
/// Given
/// \code
@@ -4389,7 +4579,7 @@ AST_MATCHER(CXXMethodDecl, isOverride) {
return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>();
}
-/// \brief Matches method declarations that are user-provided.
+/// Matches method declarations that are user-provided.
///
/// Given
/// \code
@@ -4404,7 +4594,7 @@ AST_MATCHER(CXXMethodDecl, isUserProvided) {
return Node.isUserProvided();
}
-/// \brief Matches member expressions that are called with '->' as opposed
+/// Matches member expressions that are called with '->' as opposed
/// to '.'.
///
/// Member calls on the implicit this pointer match as called with '->'.
@@ -4423,7 +4613,7 @@ AST_MATCHER(MemberExpr, isArrow) {
return Node.isArrow();
}
-/// \brief Matches QualType nodes that are of integer type.
+/// Matches QualType nodes that are of integer type.
///
/// Given
/// \code
@@ -4437,7 +4627,7 @@ AST_MATCHER(QualType, isInteger) {
return Node->isIntegerType();
}
-/// \brief Matches QualType nodes that are of unsigned integer type.
+/// Matches QualType nodes that are of unsigned integer type.
///
/// Given
/// \code
@@ -4451,7 +4641,7 @@ AST_MATCHER(QualType, isUnsignedInteger) {
return Node->isUnsignedIntegerType();
}
-/// \brief Matches QualType nodes that are of signed integer type.
+/// Matches QualType nodes that are of signed integer type.
///
/// Given
/// \code
@@ -4465,7 +4655,7 @@ AST_MATCHER(QualType, isSignedInteger) {
return Node->isSignedIntegerType();
}
-/// \brief Matches QualType nodes that are of character type.
+/// Matches QualType nodes that are of character type.
///
/// Given
/// \code
@@ -4479,7 +4669,7 @@ AST_MATCHER(QualType, isAnyCharacter) {
return Node->isAnyCharacterType();
}
-/// \brief Matches QualType nodes that are of any pointer type; this includes
+/// Matches QualType nodes that are of any pointer type; this includes
/// the Objective-C object pointer type, which is different despite being
/// syntactically similar.
///
@@ -4499,7 +4689,7 @@ AST_MATCHER(QualType, isAnyPointer) {
return Node->isAnyPointerType();
}
-/// \brief Matches QualType nodes that are const-qualified, i.e., that
+/// Matches QualType nodes that are const-qualified, i.e., that
/// include "top-level" const.
///
/// Given
@@ -4518,7 +4708,7 @@ AST_MATCHER(QualType, isConstQualified) {
return Node.isConstQualified();
}
-/// \brief Matches QualType nodes that are volatile-qualified, i.e., that
+/// Matches QualType nodes that are volatile-qualified, i.e., that
/// include "top-level" volatile.
///
/// Given
@@ -4537,7 +4727,7 @@ AST_MATCHER(QualType, isVolatileQualified) {
return Node.isVolatileQualified();
}
-/// \brief Matches QualType nodes that have local CV-qualifiers attached to
+/// Matches QualType nodes that have local CV-qualifiers attached to
/// the node, not hidden within a typedef.
///
/// Given
@@ -4554,7 +4744,7 @@ AST_MATCHER(QualType, hasLocalQualifiers) {
return Node.hasLocalQualifiers();
}
-/// \brief Matches a member expression where the member is matched by a
+/// Matches a member expression where the member is matched by a
/// given matcher.
///
/// Given
@@ -4571,7 +4761,7 @@ AST_MATCHER_P(MemberExpr, member,
return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
}
-/// \brief Matches a member expression where the object expression is
+/// Matches a member expression where the object expression is
/// matched by a given matcher.
///
/// Given
@@ -4588,7 +4778,7 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression,
return InnerMatcher.matches(*Node.getBase(), Finder, Builder);
}
-/// \brief Matches any using shadow declaration.
+/// Matches any using shadow declaration.
///
/// Given
/// \code
@@ -4603,7 +4793,7 @@ AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl,
Node.shadow_end(), Finder, Builder);
}
-/// \brief Matches a using shadow declaration where the target declaration is
+/// Matches a using shadow declaration where the target declaration is
/// matched by the given matcher.
///
/// Given
@@ -4620,7 +4810,7 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder);
}
-/// \brief Matches template instantiations of function, class, or static
+/// Matches template instantiations of function, class, or static
/// member variable template instantiations.
///
/// Given
@@ -4631,6 +4821,10 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// \code
/// template <typename T> class X {}; class A {}; template class X<A>;
/// \endcode
+/// or
+/// \code
+/// template <typename T> class X {}; class A {}; extern template class X<A>;
+/// \endcode
/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
/// matches the template instantiation of X<A>.
///
@@ -4648,10 +4842,12 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
Node.getTemplateSpecializationKind() ==
- TSK_ExplicitInstantiationDefinition);
+ TSK_ExplicitInstantiationDefinition ||
+ Node.getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration);
}
-/// \brief Matches declarations that are template instantiations or are inside
+/// Matches declarations that are template instantiations or are inside
/// template instantiations.
///
/// Given
@@ -4668,7 +4864,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
}
-/// \brief Matches statements inside of a template instantiation.
+/// Matches statements inside of a template instantiation.
///
/// Given
/// \code
@@ -4688,7 +4884,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
functionDecl(isTemplateInstantiation())))));
}
-/// \brief Matches explicit template specializations of function, class, or
+/// Matches explicit template specializations of function, class, or
/// static member variable template instantiations.
///
/// Given
@@ -4706,7 +4902,7 @@ AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization,
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
}
-/// \brief Matches \c TypeLocs for which the given inner
+/// Matches \c TypeLocs for which the given inner
/// QualType-matcher matches.
AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
internal::Matcher<QualType>, InnerMatcher, 0) {
@@ -4714,7 +4910,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
new internal::TypeLocTypeMatcher(InnerMatcher));
}
-/// \brief Matches type \c bool.
+/// Matches type \c bool.
///
/// Given
/// \code
@@ -4726,7 +4922,7 @@ AST_MATCHER(Type, booleanType) {
return Node.isBooleanType();
}
-/// \brief Matches type \c void.
+/// Matches type \c void.
///
/// Given
/// \code
@@ -4741,7 +4937,7 @@ AST_MATCHER(Type, voidType) {
template <typename NodeType>
using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>;
-/// \brief Matches builtin Types.
+/// Matches builtin Types.
///
/// Given
/// \code
@@ -4755,7 +4951,7 @@ using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>;
/// matches "int b", "float c" and "bool d"
extern const AstTypeMatcher<BuiltinType> builtinType;
-/// \brief Matches all kinds of arrays.
+/// Matches all kinds of arrays.
///
/// Given
/// \code
@@ -4767,7 +4963,7 @@ extern const AstTypeMatcher<BuiltinType> builtinType;
/// matches "int a[]", "int b[4]" and "int c[a[0]]";
extern const AstTypeMatcher<ArrayType> arrayType;
-/// \brief Matches C99 complex types.
+/// Matches C99 complex types.
///
/// Given
/// \code
@@ -4777,7 +4973,7 @@ extern const AstTypeMatcher<ArrayType> arrayType;
/// matches "_Complex float f"
extern const AstTypeMatcher<ComplexType> complexType;
-/// \brief Matches any real floating-point type (float, double, long double).
+/// Matches any real floating-point type (float, double, long double).
///
/// Given
/// \code
@@ -4790,7 +4986,7 @@ AST_MATCHER(Type, realFloatingPointType) {
return Node.isRealFloatingType();
}
-/// \brief Matches arrays and C99 complex types that have a specific element
+/// Matches arrays and C99 complex types that have a specific element
/// type.
///
/// Given
@@ -4807,7 +5003,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement,
AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
ComplexType));
-/// \brief Matches C arrays with a specified constant size.
+/// Matches C arrays with a specified constant size.
///
/// Given
/// \code
@@ -4821,7 +5017,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement,
/// matches "int a[2]"
extern const AstTypeMatcher<ConstantArrayType> constantArrayType;
-/// \brief Matches nodes that have the specified size.
+/// Matches nodes that have the specified size.
///
/// Given
/// \code
@@ -4843,7 +5039,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSize,
return internal::HasSizeMatcher<NodeType>::hasSize(Node, N);
}
-/// \brief Matches C++ arrays whose size is a value-dependent expression.
+/// Matches C++ arrays whose size is a value-dependent expression.
///
/// Given
/// \code
@@ -4856,7 +5052,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSize,
/// matches "T data[Size]"
extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
-/// \brief Matches C arrays with unspecified size.
+/// Matches C arrays with unspecified size.
///
/// Given
/// \code
@@ -4868,7 +5064,7 @@ extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
/// matches "int a[]" and "int c[]"
extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
-/// \brief Matches C arrays with a specified size that is not an
+/// Matches C arrays with a specified size that is not an
/// integer-constant-expression.
///
/// Given
@@ -4883,7 +5079,7 @@ extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
/// matches "int c[a[0]]"
extern const AstTypeMatcher<VariableArrayType> variableArrayType;
-/// \brief Matches \c VariableArrayType nodes that have a specific size
+/// Matches \c VariableArrayType nodes that have a specific size
/// expression.
///
/// Given
@@ -4900,7 +5096,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr,
return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder);
}
-/// \brief Matches atomic types.
+/// Matches atomic types.
///
/// Given
/// \code
@@ -4910,7 +5106,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr,
/// matches "_Atomic(int) i"
extern const AstTypeMatcher<AtomicType> atomicType;
-/// \brief Matches atomic types with a specific value type.
+/// Matches atomic types with a specific value type.
///
/// Given
/// \code
@@ -4924,7 +5120,7 @@ extern const AstTypeMatcher<AtomicType> atomicType;
AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue,
AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
-/// \brief Matches types nodes representing C++11 auto types.
+/// Matches types nodes representing C++11 auto types.
///
/// Given:
/// \code
@@ -4936,7 +5132,19 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue,
/// matches "auto n" and "auto i"
extern const AstTypeMatcher<AutoType> autoType;
-/// \brief Matches \c AutoType nodes where the deduced type is a specific type.
+/// Matches types nodes representing C++11 decltype(<expr>) types.
+///
+/// Given:
+/// \code
+/// short i = 1;
+/// int j = 42;
+/// decltype(i + j) result = i + j;
+/// \endcode
+/// decltypeType()
+/// matches "decltype(i + j)"
+extern const AstTypeMatcher<DecltypeType> decltypeType;
+
+/// Matches \c AutoType nodes where the deduced type is a specific type.
///
/// Note: There is no \c TypeLoc for the deduced type and thus no
/// \c getDeducedLoc() matcher.
@@ -4953,7 +5161,21 @@ extern const AstTypeMatcher<AutoType> autoType;
AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType));
-/// \brief Matches \c FunctionType nodes.
+/// Matches \c DecltypeType nodes to find out the underlying type.
+///
+/// Given
+/// \code
+/// decltype(1) a = 1;
+/// decltype(2.0) b = 2.0;
+/// \endcode
+/// decltypeType(hasUnderlyingType(isInteger()))
+/// matches "auto a"
+///
+/// Usable as: Matcher<DecltypeType>
+AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(DecltypeType));
+
+/// Matches \c FunctionType nodes.
///
/// Given
/// \code
@@ -4964,7 +5186,7 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
/// matches "int (*f)(int)" and the type of "g".
extern const AstTypeMatcher<FunctionType> functionType;
-/// \brief Matches \c FunctionProtoType nodes.
+/// Matches \c FunctionProtoType nodes.
///
/// Given
/// \code
@@ -4976,7 +5198,7 @@ extern const AstTypeMatcher<FunctionType> functionType;
/// In C mode, "g" is not matched because it does not contain a prototype.
extern const AstTypeMatcher<FunctionProtoType> functionProtoType;
-/// \brief Matches \c ParenType nodes.
+/// Matches \c ParenType nodes.
///
/// Given
/// \code
@@ -4988,7 +5210,7 @@ extern const AstTypeMatcher<FunctionProtoType> functionProtoType;
/// \c array_of_ptrs.
extern const AstTypeMatcher<ParenType> parenType;
-/// \brief Matches \c ParenType nodes where the inner type is a specific type.
+/// Matches \c ParenType nodes where the inner type is a specific type.
///
/// Given
/// \code
@@ -5003,13 +5225,13 @@ extern const AstTypeMatcher<ParenType> parenType;
AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
AST_POLYMORPHIC_SUPPORTED_TYPES(ParenType));
-/// \brief Matches block pointer types, i.e. types syntactically represented as
+/// Matches block pointer types, i.e. types syntactically represented as
/// "void (^)(int)".
///
/// The \c pointee is always required to be a \c FunctionType.
extern const AstTypeMatcher<BlockPointerType> blockPointerType;
-/// \brief Matches member pointer types.
+/// Matches member pointer types.
/// Given
/// \code
/// struct A { int i; }
@@ -5019,7 +5241,7 @@ extern const AstTypeMatcher<BlockPointerType> blockPointerType;
/// matches "A::* ptr"
extern const AstTypeMatcher<MemberPointerType> memberPointerType;
-/// \brief Matches pointer types, but does not match Objective-C object pointer
+/// Matches pointer types, but does not match Objective-C object pointer
/// types.
///
/// Given
@@ -5036,7 +5258,7 @@ extern const AstTypeMatcher<MemberPointerType> memberPointerType;
/// matches "int *a", but does not match "Foo *f".
extern const AstTypeMatcher<PointerType> pointerType;
-/// \brief Matches an Objective-C object pointer type, which is different from
+/// Matches an Objective-C object pointer type, which is different from
/// a pointer type, despite being syntactically similar.
///
/// Given
@@ -5051,7 +5273,7 @@ extern const AstTypeMatcher<PointerType> pointerType;
/// matches "Foo *f", but does not match "int *a".
extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
-/// \brief Matches both lvalue and rvalue reference types.
+/// Matches both lvalue and rvalue reference types.
///
/// Given
/// \code
@@ -5067,7 +5289,7 @@ extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f.
extern const AstTypeMatcher<ReferenceType> referenceType;
-/// \brief Matches lvalue reference types.
+/// Matches lvalue reference types.
///
/// Given:
/// \code
@@ -5084,7 +5306,7 @@ extern const AstTypeMatcher<ReferenceType> referenceType;
/// matched since the type is deduced as int& by reference collapsing rules.
extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
-/// \brief Matches rvalue reference types.
+/// Matches rvalue reference types.
///
/// Given:
/// \code
@@ -5101,7 +5323,7 @@ extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
/// matched as it is deduced to int& by reference collapsing rules.
extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
-/// \brief Narrows PointerType (and similar) matchers to those where the
+/// Narrows PointerType (and similar) matchers to those where the
/// \c pointee matches a given matcher.
///
/// Given
@@ -5120,7 +5342,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(
AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType,
PointerType, ReferenceType));
-/// \brief Matches typedef types.
+/// Matches typedef types.
///
/// Given
/// \code
@@ -5130,7 +5352,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(
/// matches "typedef int X"
extern const AstTypeMatcher<TypedefType> typedefType;
-/// \brief Matches enum types.
+/// Matches enum types.
///
/// Given
/// \code
@@ -5145,7 +5367,7 @@ extern const AstTypeMatcher<TypedefType> typedefType;
/// \c s.
extern const AstTypeMatcher<EnumType> enumType;
-/// \brief Matches template specialization types.
+/// Matches template specialization types.
///
/// Given
/// \code
@@ -5161,7 +5383,7 @@ extern const AstTypeMatcher<EnumType> enumType;
extern const AstTypeMatcher<TemplateSpecializationType>
templateSpecializationType;
-/// \brief Matches types nodes representing unary type transformations.
+/// Matches types nodes representing unary type transformations.
///
/// Given:
/// \code
@@ -5171,7 +5393,7 @@ extern const AstTypeMatcher<TemplateSpecializationType>
/// matches "__underlying_type(T)"
extern const AstTypeMatcher<UnaryTransformType> unaryTransformType;
-/// \brief Matches record types (e.g. structs, classes).
+/// Matches record types (e.g. structs, classes).
///
/// Given
/// \code
@@ -5186,7 +5408,7 @@ extern const AstTypeMatcher<UnaryTransformType> unaryTransformType;
/// and \c s.
extern const AstTypeMatcher<RecordType> recordType;
-/// \brief Matches tag types (record and enum types).
+/// Matches tag types (record and enum types).
///
/// Given
/// \code
@@ -5201,7 +5423,7 @@ extern const AstTypeMatcher<RecordType> recordType;
/// and \c c.
extern const AstTypeMatcher<TagType> tagType;
-/// \brief Matches types specified with an elaborated type keyword or with a
+/// Matches types specified with an elaborated type keyword or with a
/// qualified name.
///
/// Given
@@ -5221,7 +5443,7 @@ extern const AstTypeMatcher<TagType> tagType;
/// \c c and \c d.
extern const AstTypeMatcher<ElaboratedType> elaboratedType;
-/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
+/// Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
/// matches \c InnerMatcher if the qualifier exists.
///
/// Given
@@ -5244,7 +5466,7 @@ AST_MATCHER_P(ElaboratedType, hasQualifier,
return false;
}
-/// \brief Matches ElaboratedTypes whose named type matches \c InnerMatcher.
+/// Matches ElaboratedTypes whose named type matches \c InnerMatcher.
///
/// Given
/// \code
@@ -5264,7 +5486,7 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
}
-/// \brief Matches types that represent the result of substituting a type for a
+/// Matches types that represent the result of substituting a type for a
/// template type parameter.
///
/// Given
@@ -5279,7 +5501,7 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
extern const AstTypeMatcher<SubstTemplateTypeParmType>
substTemplateTypeParmType;
-/// \brief Matches template type parameter substitutions that have a replacement
+/// Matches template type parameter substitutions that have a replacement
/// type that matches the provided matcher.
///
/// Given
@@ -5295,7 +5517,7 @@ AST_TYPE_TRAVERSE_MATCHER(
hasReplacementType, getReplacementType,
AST_POLYMORPHIC_SUPPORTED_TYPES(SubstTemplateTypeParmType));
-/// \brief Matches template type parameter types.
+/// Matches template type parameter types.
///
/// Example matches T, but not int.
/// (matcher = templateTypeParmType())
@@ -5304,7 +5526,7 @@ AST_TYPE_TRAVERSE_MATCHER(
/// \endcode
extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
-/// \brief Matches injected class name types.
+/// Matches injected class name types.
///
/// Example matches S s, but not S<T> s.
/// (matcher = parmVarDecl(hasType(injectedClassNameType())))
@@ -5316,7 +5538,7 @@ extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
/// \endcode
extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType;
-/// \brief Matches decayed type
+/// Matches decayed type
/// Example matches i[] in declaration of f.
/// (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
/// Example matches i[1].
@@ -5328,13 +5550,13 @@ extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType;
/// \endcode
extern const AstTypeMatcher<DecayedType> decayedType;
-/// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher
+/// Matches the decayed type, whos decayed type matches \c InnerMatcher
AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
InnerType) {
return InnerType.matches(Node.getDecayedType(), Finder, Builder);
}
-/// \brief Matches declarations whose declaration context, interpreted as a
+/// Matches declarations whose declaration context, interpreted as a
/// Decl, matches \c InnerMatcher.
///
/// Given
@@ -5354,7 +5576,7 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder);
}
-/// \brief Matches nested name specifiers.
+/// Matches nested name specifiers.
///
/// Given
/// \code
@@ -5370,11 +5592,11 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
extern const internal::VariadicAllOfMatcher<NestedNameSpecifier>
nestedNameSpecifier;
-/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc.
+/// Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc.
extern const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc>
nestedNameSpecifierLoc;
-/// \brief Matches \c NestedNameSpecifierLocs for which the given inner
+/// Matches \c NestedNameSpecifierLocs for which the given inner
/// NestedNameSpecifier-matcher matches.
AST_MATCHER_FUNCTION_P_OVERLOAD(
internal::BindableMatcher<NestedNameSpecifierLoc>, loc,
@@ -5384,7 +5606,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
InnerMatcher));
}
-/// \brief Matches nested name specifiers that specify a type matching the
+/// Matches nested name specifiers that specify a type matching the
/// given \c QualType matcher without qualifiers.
///
/// Given
@@ -5403,7 +5625,7 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder);
}
-/// \brief Matches nested name specifier locs that specify a type matching the
+/// Matches nested name specifier locs that specify a type matching the
/// given \c TypeLoc.
///
/// Given
@@ -5416,10 +5638,11 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
- return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
+ return Node && Node.getNestedNameSpecifier()->getAsType() &&
+ InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
}
-/// \brief Matches on the prefix of a \c NestedNameSpecifier.
+/// Matches on the prefix of a \c NestedNameSpecifier.
///
/// Given
/// \code
@@ -5437,7 +5660,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
return InnerMatcher.matches(*NextNode, Finder, Builder);
}
-/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc.
+/// Matches on the prefix of a \c NestedNameSpecifierLoc.
///
/// Given
/// \code
@@ -5455,7 +5678,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
return InnerMatcher.matches(NextNode, Finder, Builder);
}
-/// \brief Matches nested name specifiers that specify a namespace matching the
+/// Matches nested name specifiers that specify a namespace matching the
/// given namespace matcher.
///
/// Given
@@ -5472,23 +5695,23 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder);
}
-/// \brief Overloads for the \c equalsNode matcher.
+/// Overloads for the \c equalsNode matcher.
/// FIXME: Implement for other node types.
/// @{
-/// \brief Matches if a node equals another node.
+/// Matches if a node equals another node.
///
/// \c Decl has pointer identity in the AST.
AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) {
return &Node == Other;
}
-/// \brief Matches if a node equals another node.
+/// Matches if a node equals another node.
///
/// \c Stmt has pointer identity in the AST.
AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) {
return &Node == Other;
}
-/// \brief Matches if a node equals another node.
+/// Matches if a node equals another node.
///
/// \c Type has pointer identity in the AST.
AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) {
@@ -5497,7 +5720,7 @@ AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) {
/// @}
-/// \brief Matches each case or default statement belonging to the given switch
+/// Matches each case or default statement belonging to the given switch
/// statement. This matcher may produce multiple matches.
///
/// Given
@@ -5529,7 +5752,7 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
return Matched;
}
-/// \brief Matches each constructor initializer in a constructor definition.
+/// Matches each constructor initializer in a constructor definition.
///
/// Given
/// \code
@@ -5554,7 +5777,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
return Matched;
}
-/// \brief Matches constructor declarations that are copy constructors.
+/// Matches constructor declarations that are copy constructors.
///
/// Given
/// \code
@@ -5569,7 +5792,7 @@ AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
return Node.isCopyConstructor();
}
-/// \brief Matches constructor declarations that are move constructors.
+/// Matches constructor declarations that are move constructors.
///
/// Given
/// \code
@@ -5584,7 +5807,7 @@ AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
return Node.isMoveConstructor();
}
-/// \brief Matches constructor declarations that are default constructors.
+/// Matches constructor declarations that are default constructors.
///
/// Given
/// \code
@@ -5599,7 +5822,7 @@ AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
return Node.isDefaultConstructor();
}
-/// \brief Matches constructors that delegate to another constructor.
+/// Matches constructors that delegate to another constructor.
///
/// Given
/// \code
@@ -5616,7 +5839,7 @@ AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) {
return Node.isDelegatingConstructor();
}
-/// \brief Matches constructor and conversion declarations that are marked with
+/// Matches constructor and conversion declarations that are marked with
/// the explicit keyword.
///
/// Given
@@ -5636,7 +5859,7 @@ AST_POLYMORPHIC_MATCHER(isExplicit,
return Node.isExplicit();
}
-/// \brief Matches function and namespace declarations that are marked with
+/// Matches function and namespace declarations that are marked with
/// the inline keyword.
///
/// Given
@@ -5661,7 +5884,7 @@ AST_POLYMORPHIC_MATCHER(isInline,
llvm_unreachable("Not a valid polymorphic type");
}
-/// \brief Matches anonymous namespace declarations.
+/// Matches anonymous namespace declarations.
///
/// Given
/// \code
@@ -5674,7 +5897,7 @@ AST_MATCHER(NamespaceDecl, isAnonymous) {
return Node.isAnonymousNamespace();
}
-/// \brief If the given case statement does not use the GNU case range
+/// If the given case statement does not use the GNU case range
/// extension, matches the constant given in the statement.
///
/// Given
@@ -5691,7 +5914,7 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
}
-/// \brief Matches declaration that has a given attribute.
+/// Matches declaration that has a given attribute.
///
/// Given
/// \code
@@ -5708,7 +5931,7 @@ AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
return false;
}
-/// \brief Matches the return value expression of a return statement
+/// Matches the return value expression of a return statement
///
/// Given
/// \code
@@ -5725,7 +5948,7 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>,
return false;
}
-/// \brief Matches CUDA kernel call expression.
+/// Matches CUDA kernel call expression.
///
/// Example matches,
/// \code
@@ -5734,7 +5957,7 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>,
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
cudaKernelCallExpr;
-/// \brief Matches expressions that resolve to a null pointer constant, such as
+/// Matches expressions that resolve to a null pointer constant, such as
/// GNU's __null, C++11's nullptr, or C's NULL macro.
///
/// Given:
@@ -5755,7 +5978,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
integerLiteral(equals(0), hasParent(expr(hasType(pointerType())))));
}
-/// \brief Matches declaration of the function the statement belongs to
+/// Matches declaration of the function the statement belongs to
///
/// Given:
/// \code
@@ -5793,7 +6016,7 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
return false;
}
-/// \brief Matches a declaration that has external formal linkage.
+/// Matches a declaration that has external formal linkage.
///
/// Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
/// \code
@@ -5817,18 +6040,18 @@ AST_MATCHER(NamedDecl, hasExternalFormalLinkage) {
return Node.hasExternalFormalLinkage();
}
-/// \brief Matches a declaration that has default arguments.
+/// 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();
+AST_MATCHER(ParmVarDecl, hasDefaultArgument) {
+ return Node.hasDefaultArg();
}
-/// \brief Matches array new expressions.
+/// Matches array new expressions.
///
/// Given:
/// \code
@@ -5840,7 +6063,7 @@ AST_MATCHER(CXXNewExpr, isArray) {
return Node.isArray();
}
-/// \brief Matches array new expressions with a given array size.
+/// Matches array new expressions with a given array size.
///
/// Given:
/// \code
@@ -5853,7 +6076,7 @@ AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) {
InnerMatcher.matches(*Node.getArraySize(), Finder, Builder);
}
-/// \brief Matches a class declaration that is defined.
+/// Matches a class declaration that is defined.
///
/// Example matches x (matcher = cxxRecordDecl(hasDefinition()))
/// \code
@@ -5864,6 +6087,30 @@ AST_MATCHER(CXXRecordDecl, hasDefinition) {
return Node.hasDefinition();
}
+/// Matches C++11 scoped enum declaration.
+///
+/// Example matches Y (matcher = enumDecl(isScoped()))
+/// \code
+/// enum X {};
+/// enum class Y {};
+/// \endcode
+AST_MATCHER(EnumDecl, isScoped) {
+ return Node.isScoped();
+}
+
+/// Matches a function declared with a trailing return type.
+///
+/// Example matches Y (matcher = functionDecl(hasTrailingReturn()))
+/// \code
+/// int X() {}
+/// auto Y() -> int {}
+/// \endcode
+AST_MATCHER(FunctionDecl, hasTrailingReturn) {
+ if (const auto *F = Node.getType()->getAs<FunctionProtoType>())
+ return F->hasTrailingReturn();
+ return false;
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 8bd61a76e185..9d9f867d053a 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -38,9 +38,12 @@
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateName.h"
@@ -80,7 +83,7 @@ class BoundNodes;
namespace internal {
-/// \brief Variadic function object.
+/// Variadic function object.
///
/// Most of the functions below that use VariadicFunction could be implemented
/// using plain C++11 variadic functions, but the function object allows us to
@@ -113,19 +116,23 @@ private:
}
};
-/// \brief Unifies obtaining the underlying type of a regular node through
+/// Unifies obtaining the underlying type of a regular node through
/// `getType` and a TypedefNameDecl node through `getUnderlyingType`.
inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); }
inline QualType getUnderlyingType(const ValueDecl &Node) {
return Node.getType();
}
-
inline QualType getUnderlyingType(const TypedefNameDecl &Node) {
return Node.getUnderlyingType();
}
+inline QualType getUnderlyingType(const FriendDecl &Node) {
+ if (const TypeSourceInfo *TSI = Node.getFriendType())
+ return TSI->getType();
+ return QualType();
+}
-/// \brief Unifies obtaining the FunctionProtoType pointer from both
+/// Unifies obtaining the FunctionProtoType pointer from both
/// FunctionProtoType and FunctionDecl nodes..
inline const FunctionProtoType *
getFunctionProtoType(const FunctionProtoType &Node) {
@@ -136,17 +143,17 @@ inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) {
return Node.getType()->getAs<FunctionProtoType>();
}
-/// \brief Internal version of BoundNodes. Holds all the bound nodes.
+/// Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap {
public:
- /// \brief Adds \c Node to the map with key \c ID.
+ /// Adds \c Node to the map with key \c ID.
///
/// The node's base type should be in NodeBaseType or it will be unaccessible.
void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
NodeMap[ID] = DynNode;
}
- /// \brief Returns the AST node bound to \c ID.
+ /// Returns the AST node bound to \c ID.
///
/// Returns NULL if there was no node bound to \c ID or if there is a node but
/// it cannot be converted to the specified type.
@@ -167,12 +174,12 @@ public:
return It->second;
}
- /// \brief Imposes an order on BoundNodesMaps.
+ /// Imposes an order on BoundNodesMaps.
bool operator<(const BoundNodesMap &Other) const {
return NodeMap < Other.NodeMap;
}
- /// \brief A map from IDs to the bound nodes.
+ /// A map from IDs to the bound nodes.
///
/// Note that we're using std::map here, as for memoization:
/// - we need a comparison operator
@@ -183,7 +190,7 @@ public:
return NodeMap;
}
- /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all
+ /// Returns \c true if this \c BoundNodesMap can be compared, i.e. all
/// stored nodes have memoization data.
bool isComparable() const {
for (const auto &IDAndNode : NodeMap) {
@@ -197,25 +204,25 @@ private:
IDToNodeMap NodeMap;
};
-/// \brief Creates BoundNodesTree objects.
+/// Creates BoundNodesTree objects.
///
/// The tree builder is used during the matching process to insert the bound
/// nodes from the Id matcher.
class BoundNodesTreeBuilder {
public:
- /// \brief A visitor interface to visit all BoundNodes results for a
+ /// A visitor interface to visit all BoundNodes results for a
/// BoundNodesTree.
class Visitor {
public:
virtual ~Visitor() = default;
- /// \brief Called multiple times during a single call to VisitMatches(...).
+ /// Called multiple times during a single call to VisitMatches(...).
///
/// 'BoundNodesView' contains the bound nodes for a single match.
virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
};
- /// \brief Add a binding from an id to a node.
+ /// Add a binding from an id to a node.
void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.emplace_back();
@@ -223,10 +230,10 @@ public:
Binding.addNode(Id, DynNode);
}
- /// \brief Adds a branch in the tree.
+ /// Adds a branch in the tree.
void addMatch(const BoundNodesTreeBuilder &Bindings);
- /// \brief Visits all matches that this BoundNodesTree represents.
+ /// Visits all matches that this BoundNodesTree represents.
///
/// The ownership of 'ResultVisitor' remains at the caller.
void visitMatches(Visitor* ResultVisitor);
@@ -238,12 +245,12 @@ public:
return !Bindings.empty();
}
- /// \brief Imposes an order on BoundNodesTreeBuilders.
+ /// Imposes an order on BoundNodesTreeBuilders.
bool operator<(const BoundNodesTreeBuilder &Other) const {
return Bindings < Other.Bindings;
}
- /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared,
+ /// Returns \c true if this \c BoundNodesTreeBuilder can be compared,
/// i.e. all stored node maps have memoization data.
bool isComparable() const {
for (const BoundNodesMap &NodesMap : Bindings) {
@@ -259,7 +266,7 @@ private:
class ASTMatchFinder;
-/// \brief Generic interface for all matchers.
+/// Generic interface for all matchers.
///
/// Used by the implementation of Matcher<T> and DynTypedMatcher.
/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
@@ -269,7 +276,7 @@ class DynMatcherInterface
public:
virtual ~DynMatcherInterface() = default;
- /// \brief Returns true if \p DynNode can be matched.
+ /// Returns true if \p DynNode can be matched.
///
/// May bind \p DynNode to an ID via \p Builder, or recurse into
/// the AST via \p Finder.
@@ -278,7 +285,7 @@ public:
BoundNodesTreeBuilder *Builder) const = 0;
};
-/// \brief Generic interface for matchers on an AST node of type T.
+/// Generic interface for matchers on an AST node of type T.
///
/// Implement this if your matcher may need to inspect the children or
/// descendants of the node or bind matched nodes to names. If you are
@@ -288,7 +295,7 @@ public:
template <typename T>
class MatcherInterface : public DynMatcherInterface {
public:
- /// \brief Returns true if 'Node' can be matched.
+ /// Returns true if 'Node' can be matched.
///
/// May bind 'Node' to an ID via 'Builder', or recurse into
/// the AST via 'Finder'.
@@ -303,12 +310,12 @@ public:
}
};
-/// \brief Interface for matchers that only evaluate properties on a single
+/// Interface for matchers that only evaluate properties on a single
/// node.
template <typename T>
class SingleNodeMatcherInterface : public MatcherInterface<T> {
public:
- /// \brief Returns true if the matcher matches the provided node.
+ /// Returns true if the matcher matches the provided node.
///
/// A subclass must implement this instead of Matches().
virtual bool matchesNode(const T &Node) const = 0;
@@ -324,7 +331,7 @@ private:
template <typename> class Matcher;
-/// \brief Matcher that works on a \c DynTypedNode.
+/// Matcher that works on a \c DynTypedNode.
///
/// It is constructed from a \c Matcher<T> object and redirects most calls to
/// underlying matcher.
@@ -333,26 +340,26 @@ template <typename> class Matcher;
/// return false if it is not convertible.
class DynTypedMatcher {
public:
- /// \brief Takes ownership of the provided implementation pointer.
+ /// Takes ownership of the provided implementation pointer.
template <typename T>
DynTypedMatcher(MatcherInterface<T> *Implementation)
: SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
RestrictKind(SupportedKind), Implementation(Implementation) {}
- /// \brief Construct from a variadic function.
+ /// Construct from a variadic function.
enum VariadicOperator {
- /// \brief Matches nodes for which all provided matchers match.
+ /// Matches nodes for which all provided matchers match.
VO_AllOf,
- /// \brief Matches nodes for which at least one of the provided matchers
+ /// 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 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.
+ /// Matches nodes that do not match the provided matcher.
///
/// Uses the variadic matcher interface, but fails if
/// InnerMatchers.size() != 1.
@@ -364,27 +371,27 @@ public:
ast_type_traits::ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers);
- /// \brief Get a "true" matcher for \p NodeKind.
+ /// Get a "true" matcher for \p NodeKind.
///
/// It only checks that the node is of the right kind.
static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
void setAllowBind(bool AB) { AllowBind = AB; }
- /// \brief Check whether this matcher could ever match a node of kind \p Kind.
+ /// Check whether this matcher could ever match a node of kind \p Kind.
/// \return \c false if this matcher will never match such a node. Otherwise,
/// return \c true.
bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const;
- /// \brief Return a matcher that points to the same implementation, but
+ /// Return a matcher that points to the same implementation, but
/// restricts the node types for \p Kind.
DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
- /// \brief Returns true if the matcher matches the given \c DynNode.
+ /// Returns true if the matcher matches the given \c DynNode.
bool matches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
- /// \brief Same as matches(), but skips the kind check.
+ /// Same as matches(), but skips the kind check.
///
/// It is faster, but the caller must ensure the node is valid for the
/// kind of this matcher.
@@ -392,12 +399,12 @@ public:
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const;
- /// \brief Bind the specified \p ID to the matcher.
+ /// Bind the specified \p ID to the matcher.
/// \return A new matcher with the \p ID bound to it if this matcher supports
/// binding. Otherwise, returns an empty \c Optional<>.
llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const;
- /// \brief Returns a unique \p ID for the matcher.
+ /// Returns a unique \p ID for the matcher.
///
/// Casting a Matcher<T> to Matcher<U> creates a matcher that has the
/// same \c Implementation pointer, but different \c RestrictKind. We need to
@@ -412,7 +419,7 @@ public:
reinterpret_cast<uint64_t>(Implementation.get()));
}
- /// \brief Returns the type this matcher works on.
+ /// Returns the type this matcher works on.
///
/// \c matches() will always return false unless the node passed is of this
/// or a derived type.
@@ -420,7 +427,7 @@ public:
return SupportedKind;
}
- /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
+ /// Returns \c true if the passed \c DynTypedMatcher can be converted
/// to a \c Matcher<T>.
///
/// This method verifies that the underlying matcher in \c Other can process
@@ -430,7 +437,7 @@ public:
}
bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
- /// \brief Construct a \c Matcher<T> interface around the dynamic matcher.
+ /// Construct a \c Matcher<T> interface around the dynamic matcher.
///
/// This method asserts that \c canConvertTo() is \c true. Callers
/// should call \c canConvertTo() first to make sure that \c this is
@@ -440,7 +447,7 @@ public:
return unconditionalConvertTo<T>();
}
- /// \brief Same as \c convertTo(), but does not check that the underlying
+ /// Same as \c convertTo(), but does not check that the underlying
/// matcher can handle a value of T.
///
/// If it is not compatible, then this matcher will never match anything.
@@ -456,7 +463,7 @@ private:
bool AllowBind = false;
ast_type_traits::ASTNodeKind SupportedKind;
- /// \brief A potentially stricter node kind.
+ /// A potentially stricter node kind.
///
/// It allows to perform implicit and dynamic cast of matchers without
/// needing to change \c Implementation.
@@ -464,7 +471,7 @@ private:
IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
};
-/// \brief Wrapper base class for a wrapping matcher.
+/// Wrapper base class for a wrapping matcher.
///
/// This is just a container for a DynTypedMatcher that can be used as a base
/// class for another matcher.
@@ -477,7 +484,7 @@ protected:
const DynTypedMatcher InnerMatcher;
};
-/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
+/// Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
/// required. This establishes an is-a relationship which is reverse
@@ -488,11 +495,11 @@ protected:
template <typename T>
class Matcher {
public:
- /// \brief Takes ownership of the provided implementation pointer.
+ /// Takes ownership of the provided implementation pointer.
explicit Matcher(MatcherInterface<T> *Implementation)
: Implementation(Implementation) {}
- /// \brief Implicitly converts \c Other to a Matcher<T>.
+ /// Implicitly converts \c Other to a Matcher<T>.
///
/// Requires \c T to be derived from \c From.
template <typename From>
@@ -504,7 +511,7 @@ public:
ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
}
- /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
+ /// Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
///
/// The resulting matcher is not strict, i.e. ignores qualifiers.
template <typename TypeT>
@@ -514,7 +521,7 @@ public:
std::is_same<TypeT, Type>::value>::type* = nullptr)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
- /// \brief Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
+ /// Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
/// argument.
/// \c To must be a base class of \c T.
template <typename To>
@@ -523,7 +530,7 @@ public:
return Matcher<To>(Implementation);
}
- /// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
+ /// Forwards the call to the underlying MatcherInterface<T> pointer.
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
@@ -531,18 +538,18 @@ public:
Finder, Builder);
}
- /// \brief Returns an ID that uniquely identifies the matcher.
+ /// Returns an ID that uniquely identifies the matcher.
DynTypedMatcher::MatcherIDType getID() const {
return Implementation.getID();
}
- /// \brief Extract the dynamic matcher.
+ /// Extract the dynamic matcher.
///
/// The returned matcher keeps the same restrictions as \c this and remembers
/// that it is meant to support nodes of type \c T.
operator DynTypedMatcher() const { return Implementation; }
- /// \brief Allows the conversion of a \c Matcher<Type> to a \c
+ /// Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
/// Depending on the constructor argument, the matcher is either strict, i.e.
@@ -583,14 +590,14 @@ private:
DynTypedMatcher Implementation;
}; // class Matcher
-/// \brief A convenient helper for creating a Matcher<T> without specifying
+/// A convenient helper for creating a Matcher<T> without specifying
/// the template type argument.
template <typename T>
inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
return Matcher<T>(Implementation);
}
-/// \brief Specialization of the conversion functions for QualType.
+/// Specialization of the conversion functions for QualType.
///
/// This specialization provides the Matcher<Type>->Matcher<QualType>
/// conversion that the static API does.
@@ -606,7 +613,7 @@ inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
return unconditionalConvertTo<QualType>();
}
-/// \brief Finds the first node in a range that matches the given matcher.
+/// Finds the first node in a range that matches the given matcher.
template <typename MatcherT, typename IteratorT>
bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
IteratorT End, ASTMatchFinder *Finder,
@@ -621,7 +628,7 @@ bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
return false;
}
-/// \brief Finds the first node in a pointer range that matches the given
+/// Finds the first node in a pointer range that matches the given
/// matcher.
template <typename MatcherT, typename IteratorT>
bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
@@ -653,7 +660,7 @@ public:
static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
};
-/// \brief Matches overloaded operators with a specific name.
+/// Matches overloaded operators with a specific name.
///
/// The type argument ArgT is not used by this matcher but is used by
/// PolymorphicMatcherWithParam1 and should be StringRef.
@@ -675,14 +682,14 @@ public:
private:
- /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators
+ /// CXXOperatorCallExpr exist only for calls to overloaded operators
/// so this function returns true if the call is to an operator of the given
/// name.
bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
return getOperatorSpelling(Node.getOperator()) == Name;
}
- /// \brief Returns true only if CXXMethodDecl represents an overloaded
+ /// Returns true only if CXXMethodDecl represents an overloaded
/// operator and has the given operator name.
bool matchesSpecialized(const FunctionDecl &Node) const {
return Node.isOverloadedOperator() &&
@@ -692,7 +699,7 @@ private:
std::string Name;
};
-/// \brief Matches named declarations with a specific name.
+/// Matches named declarations with a specific name.
///
/// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.
class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
@@ -702,13 +709,13 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
bool matchesNode(const NamedDecl &Node) const override;
private:
- /// \brief Unqualified match routine.
+ /// Unqualified match routine.
///
/// It is much faster than the full match, but it only works for unqualified
/// matches.
bool matchesNodeUnqualified(const NamedDecl &Node) const;
- /// \brief Full match routine
+ /// Full match routine
///
/// Fast implementation for the simple case of a named declaration at
/// namespace or RecordDecl scope.
@@ -716,7 +723,7 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
/// matchesNodeFullSlow.
bool matchesNodeFullFast(const NamedDecl &Node) const;
- /// \brief Full match routine
+ /// Full match routine
///
/// It generates the fully qualified name of the declaration (which is
/// expensive) before trying to match.
@@ -727,11 +734,16 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
const std::vector<std::string> Names;
};
-/// \brief Trampoline function to use VariadicFunction<> to construct a
+/// Trampoline function to use VariadicFunction<> to construct a
/// HasNameMatcher.
Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
-/// \brief Matches declarations for QualType and CallExpr.
+/// Trampoline function to use VariadicFunction<> to construct a
+/// hasAnySelector matcher.
+Matcher<ObjCMessageExpr> hasAnySelectorFunc(
+ ArrayRef<const StringRef *> NameRefs);
+
+/// Matches declarations for QualType and CallExpr.
///
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
/// not actually used.
@@ -750,7 +762,7 @@ public:
}
private:
- /// \brief Forwards to matching on the underlying type of the QualType.
+ /// Forwards to matching on the underlying type of the QualType.
bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
if (Node.isNull())
@@ -759,7 +771,7 @@ private:
return matchesSpecialized(*Node, Finder, Builder);
}
- /// \brief Finds the best declaration for a type and returns whether the inner
+ /// 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 {
@@ -833,21 +845,21 @@ private:
return false;
}
- /// \brief Extracts the Decl the DeclRefExpr references and returns whether
+ /// 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.getDecl(), Finder, Builder);
}
- /// \brief Extracts the Decl of the callee of a CallExpr and returns whether
+ /// Extracts the Decl of the callee of a CallExpr and returns whether
/// the inner matcher matches on it.
bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
return matchesDecl(Node.getCalleeDecl(), Finder, Builder);
}
- /// \brief Extracts the Decl of the constructor call and returns whether the
+ /// Extracts the Decl of the constructor call and returns whether the
/// inner matcher matches on it.
bool matchesSpecialized(const CXXConstructExpr &Node,
ASTMatchFinder *Finder,
@@ -855,7 +867,13 @@ private:
return matchesDecl(Node.getConstructor(), Finder, Builder);
}
- /// \brief Extracts the operator new of the new call and returns whether the
+ bool matchesSpecialized(const ObjCIvarRefExpr &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getDecl(), Finder, Builder);
+ }
+
+ /// Extracts the operator new of the new call and returns whether the
/// inner matcher matches on it.
bool matchesSpecialized(const CXXNewExpr &Node,
ASTMatchFinder *Finder,
@@ -863,7 +881,7 @@ private:
return matchesDecl(Node.getOperatorNew(), Finder, Builder);
}
- /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns
+ /// Extracts the \c ValueDecl a \c MemberExpr refers to and returns
/// whether the inner matcher matches on it.
bool matchesSpecialized(const MemberExpr &Node,
ASTMatchFinder *Finder,
@@ -871,7 +889,7 @@ private:
return matchesDecl(Node.getMemberDecl(), Finder, Builder);
}
- /// \brief Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns
+ /// Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns
/// whether the inner matcher matches on it.
bool matchesSpecialized(const AddrLabelExpr &Node,
ASTMatchFinder *Finder,
@@ -879,14 +897,14 @@ private:
return matchesDecl(Node.getLabel(), Finder, Builder);
}
- /// \brief Extracts the declaration of a LabelStmt and returns whether the
+ /// 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
+ /// Returns whether the inner matcher \c Node. Returns false if \c Node
/// is \c NULL.
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
@@ -896,7 +914,7 @@ private:
}
};
-/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST
+/// IsBaseType<T>::value is true if T is a "base" type in the AST
/// node class hierarchies.
template <typename T>
struct IsBaseType {
@@ -913,7 +931,7 @@ struct IsBaseType {
template <typename T>
const bool IsBaseType<T>::value;
-/// \brief Interface that allows matchers to traverse the AST.
+/// Interface that allows matchers to traverse the AST.
/// FIXME: Find a better name.
///
/// This provides three entry methods for each base node type in the AST:
@@ -933,7 +951,7 @@ const bool IsBaseType<T>::value;
/// all nodes, as all nodes have ancestors.
class ASTMatchFinder {
public:
- /// \brief Defines how we descend a level in the AST when we pass
+ /// Defines how we descend a level in the AST when we pass
/// through expressions.
enum TraversalKind {
/// Will traverse any child nodes.
@@ -943,7 +961,7 @@ public:
TK_IgnoreImplicitCastsAndParentheses
};
- /// \brief Defines how bindings are processed on recursive matches.
+ /// Defines how bindings are processed on recursive matches.
enum BindKind {
/// Stop at the first match and only bind the first match.
BK_First,
@@ -952,7 +970,7 @@ public:
BK_All
};
- /// \brief Defines which ancestors are considered for a match.
+ /// Defines which ancestors are considered for a match.
enum AncestorMatchMode {
/// All ancestors.
AMM_All,
@@ -963,7 +981,7 @@ public:
virtual ~ASTMatchFinder() = default;
- /// \brief Returns true if the given class is directly or indirectly derived
+ /// Returns true if the given class is directly or indirectly derived
/// from a base type matching \c base.
///
/// A class is considered to be also derived from itself.
@@ -1039,27 +1057,27 @@ protected:
AncestorMatchMode MatchMode) = 0;
};
-/// \brief A type-list implementation.
+/// A type-list implementation.
///
/// A "linked list" of types, accessible by using the ::head and ::tail
/// typedefs.
template <typename... Ts> struct TypeList {}; // Empty sentinel type list.
template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
- /// \brief The first type on the list.
+ /// The first type on the list.
using head = T1;
- /// \brief A sublist with the tail. ie everything but the head.
+ /// 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.
using tail = TypeList<Ts...>;
};
-/// \brief The empty type list.
+/// The empty type list.
using EmptyTypeList = TypeList<>;
-/// \brief Helper meta-function to determine if some type \c T is present or
+/// Helper meta-function to determine if some type \c T is present or
/// a parent type in the list.
template <typename AnyTypeList, typename T>
struct TypeListContainsSuperOf {
@@ -1072,14 +1090,14 @@ struct TypeListContainsSuperOf<EmptyTypeList, T> {
static const bool value = false;
};
-/// \brief A "type list" that contains all types.
+/// A "type list" that contains all types.
///
/// Useful for matchers like \c anything and \c unless.
using AllNodeBaseTypes =
TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
Type, TypeLoc, CXXCtorInitializer>;
-/// \brief Helper meta-function to extract the argument out of a function of
+/// Helper meta-function to extract the argument out of a function of
/// type void(Arg).
///
/// See AST_POLYMORPHIC_SUPPORTED_TYPES for details.
@@ -1088,21 +1106,21 @@ template <class T> struct ExtractFunctionArgMeta<void(T)> {
using type = T;
};
-/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
+/// Default type lists for ArgumentAdaptingMatcher matchers.
using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
using AdaptativeDefaultToTypes =
TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
QualType>;
-/// \brief All types that are supported by HasDeclarationMatcher above.
+/// All types that are supported by HasDeclarationMatcher above.
using HasDeclarationSupportedTypes =
TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
MemberExpr, QualType, RecordType, TagType,
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
- UnresolvedUsingType>;
+ UnresolvedUsingType, ObjCIvarRefExpr>;
-/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
+/// Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
///
/// The \c ArgumentAdapterT argument specifies how the adaptation is done.
@@ -1145,7 +1163,7 @@ struct ArgumentAdaptingMatcherFunc {
}
};
-/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
+/// A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
/// created from N parameters p1, ..., pN (of type P1, ..., PN) and
/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
/// can be constructed.
@@ -1214,7 +1232,7 @@ private:
const P2 Param2;
};
-/// \brief Matches any instance of the given NodeType.
+/// Matches any instance of the given NodeType.
///
/// This is useful when a matcher syntactically requires a child matcher,
/// but the context doesn't care. See for example: anything().
@@ -1230,7 +1248,7 @@ public:
}
};
-/// \brief A Matcher that allows binding the node it matches to an id.
+/// A Matcher that allows binding the node it matches to an id.
///
/// BindableMatcher provides a \a bind() method that allows binding the
/// matched node to an id if the match was successful.
@@ -1241,7 +1259,7 @@ public:
explicit BindableMatcher(MatcherInterface<T> *Implementation)
: Matcher<T>(Implementation) {}
- /// \brief Returns a matcher that will bind the matched node on a match.
+ /// Returns a matcher that will bind the matched node on a match.
///
/// The returned matcher is equivalent to this matcher, but will
/// bind the matched node on a match.
@@ -1251,7 +1269,7 @@ public:
->template unconditionalConvertTo<T>();
}
- /// \brief Same as Matcher<T>'s conversion operator, but enables binding on
+ /// Same as Matcher<T>'s conversion operator, but enables binding on
/// the returned matcher.
operator DynTypedMatcher() const {
DynTypedMatcher Result = static_cast<const Matcher<T>&>(*this);
@@ -1260,7 +1278,7 @@ public:
}
};
-/// \brief Matches nodes of type T that have child nodes of type ChildT for
+/// Matches nodes of type T that have child nodes of type ChildT for
/// which a specified child matcher matches.
///
/// ChildT must be an AST base type.
@@ -1278,7 +1296,7 @@ public:
}
};
-/// \brief Matches nodes of type T that have child nodes of type ChildT for
+/// Matches nodes of type T that have child nodes of type ChildT for
/// which a specified child matcher matches. ChildT must be an AST base
/// type.
/// As opposed to the HasMatcher, the ForEachMatcher will produce a match
@@ -1301,10 +1319,10 @@ class ForEachMatcher : public WrapperMatcherInterface<T> {
}
};
-/// \brief VariadicOperatorMatcher related types.
+/// VariadicOperatorMatcher related types.
/// @{
-/// \brief Polymorphic matcher object that uses a \c
+/// Polymorphic matcher object that uses a \c
/// DynTypedMatcher::VariadicOperator operator.
///
/// Input matchers can have any type (including other polymorphic matcher
@@ -1333,7 +1351,7 @@ private:
std::tuple<Ps...> Params;
};
-/// \brief Overloaded function object to generate VariadicOperatorMatcher
+/// Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
@@ -1354,7 +1372,7 @@ inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
return Matcher<T>(*this);
}
-/// \brief Creates a Matcher<T> that matches if all inner matchers match.
+/// Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
@@ -1380,7 +1398,7 @@ BindableMatcher<T> makeAllOfComposite(
.template unconditionalConvertTo<T>());
}
-/// \brief Creates a Matcher<T> that matches if
+/// Creates a Matcher<T> that matches if
/// T is dyn_cast'able into InnerT and all inner matchers match.
///
/// Returns BindableMatcher, as matchers that use dyn_cast have
@@ -1393,7 +1411,7 @@ BindableMatcher<T> makeDynCastAllOfComposite(
makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
}
-/// \brief Matches nodes of type T that have at least one descendant node of
+/// Matches nodes of type T that have at least one descendant node of
/// type DescendantT for which the given inner matcher matches.
///
/// DescendantT must be an AST base type.
@@ -1413,7 +1431,7 @@ public:
}
};
-/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT
+/// Matches nodes of type \c T that have a parent node of type \c ParentT
/// for which the given inner matcher matches.
///
/// \c ParentT must be an AST base type.
@@ -1433,7 +1451,7 @@ public:
}
};
-/// \brief Matches nodes of type \c T that have at least one ancestor node of
+/// Matches nodes of type \c T that have at least one ancestor node of
/// type \c AncestorT for which the given inner matcher matches.
///
/// \c AncestorT must be an AST base type.
@@ -1453,7 +1471,7 @@ public:
}
};
-/// \brief Matches nodes of type T that have at least one descendant node of
+/// Matches nodes of type T that have at least one descendant node of
/// type DescendantT for which the given inner matcher matches.
///
/// DescendantT must be an AST base type.
@@ -1476,7 +1494,7 @@ public:
}
};
-/// \brief Matches on nodes that have a getValue() method if getValue() equals
+/// Matches on nodes that have a getValue() method if getValue() equals
/// the value the ValueEqualsMatcher was constructed with.
template <typename T, typename ValueT>
class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
@@ -1498,7 +1516,7 @@ private:
const ValueT ExpectedValue;
};
-/// \brief Template specializations to easily write matchers for floating point
+/// Template specializations to easily write matchers for floating point
/// literals.
template <>
inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
@@ -1524,7 +1542,7 @@ inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
}
-/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
+/// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
/// variadic functor that takes a number of Matcher<TargetT> and returns a
/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
/// given matchers, if SourceT can be dynamically casted into TargetT.
@@ -1544,7 +1562,7 @@ public:
VariadicDynCastAllOfMatcher() {}
};
-/// \brief A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
+/// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
/// nodes that are matched by all of the given matchers.
///
@@ -1562,7 +1580,7 @@ public:
VariadicAllOfMatcher() {}
};
-/// \brief Matches nodes of type \c TLoc for which the inner
+/// Matches nodes of type \c TLoc for which the inner
/// \c Matcher<T> matches.
template <typename TLoc, typename T>
class LocMatcher : public WrapperMatcherInterface<TLoc> {
@@ -1584,7 +1602,7 @@ private:
}
};
-/// \brief Matches \c TypeLocs based on an inner matcher matching a certain
+/// Matches \c TypeLocs based on an inner matcher matching a certain
/// \c QualType.
///
/// Used to implement the \c loc() matcher.
@@ -1602,7 +1620,7 @@ public:
}
};
-/// \brief Matches nodes of type \c T for which the inner matcher matches on a
+/// Matches nodes of type \c T for which the inner matcher matches on a
/// another node of type \c T that can be reached using a given traverse
/// function.
template <typename T>
@@ -1626,7 +1644,7 @@ private:
QualType (T::*TraverseFunction)() const;
};
-/// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the inner
+/// Matches nodes of type \c T in a ..Loc hierarchy, for which the inner
/// matcher matches on a another node of type \c T that can be reached using a
/// given traverse function.
template <typename T>
@@ -1650,7 +1668,7 @@ private:
TypeLoc (T::*TraverseFunction)() const;
};
-/// \brief Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
+/// Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
/// \c OuterT is any type that is supported by \c Getter.
///
/// \code Getter<OuterT>::value() \endcode returns a
@@ -1688,7 +1706,7 @@ private:
const Matcher<InnerTBase> InnerMatcher;
};
-/// \brief A simple memoizer of T(*)() functions.
+/// A simple memoizer of T(*)() functions.
///
/// It will call the passed 'Func' template parameter at most once.
/// Used to support AST_MATCHER_FUNCTION() macro.
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
index 6a48da821a53..3080f86699b5 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -50,7 +50,7 @@
#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
-/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
+/// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// ReturnType object.
#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
@@ -61,7 +61,7 @@
} \
inline ReturnType DefineMatcher##_getInstance()
-/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
+/// AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
/// ... }
/// defines a single-parameter function named DefineMatcher() that returns a
/// ReturnType object.
@@ -81,7 +81,7 @@
typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \
inline ReturnType DefineMatcher(ParamType const &Param)
-/// \brief AST_MATCHER(Type, DefineMatcher) { ... }
+/// AST_MATCHER(Type, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// Matcher<Type> object.
///
@@ -113,7 +113,7 @@
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
-/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
+/// AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that returns a
/// Matcher<Type> object.
///
@@ -159,7 +159,7 @@
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
-/// \brief AST_MATCHER_P2(
+/// AST_MATCHER_P2(
/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
/// defines a two-parameter function named DefineMatcher() that returns a
/// Matcher<Type> object.
@@ -211,7 +211,7 @@
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
-/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
+/// Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
/// macros.
///
/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
@@ -222,7 +222,7 @@
#define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \
void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>)
-/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
+/// AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
@@ -252,7 +252,7 @@
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
-/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
+/// AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
@@ -305,7 +305,7 @@
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
const
-/// \brief AST_POLYMORPHIC_MATCHER_P2(
+/// AST_POLYMORPHIC_MATCHER_P2(
/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
/// defines a two-parameter function named matcher() that is polymorphic in
/// the return type.
@@ -359,11 +359,6 @@
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
const
-/// \brief Creates a variadic matcher for both a specific \c Type as well as
-/// the corresponding \c TypeLoc.
-#define AST_TYPE_MATCHER(NodeType, MatcherName) \
- const ::clang::ast_matchers::internal::VariadicDynCastAllOfMatcher< \
- Type, NodeType> MatcherName
// FIXME: add a matcher for TypeLoc derived classes using its custom casting
// API (no longer dyn_cast) if/when we need such matching
@@ -388,7 +383,7 @@
::clang::ast_matchers::internal::TypeTraverseMatcher, \
ReturnTypesF>::Func MatcherName
-/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
+/// AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
/// the matcher \c MatcherName that can be used to traverse from one \c Type
/// to another.
///
@@ -431,7 +426,7 @@
ReturnTypesF>::Func MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF)
-/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
+/// AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
namespace internal { \
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index 908fa0db622d..ccd9590f4bb4 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Diagnostics class to manage error messages.
+/// Diagnostics class to manage error messages.
///
//===----------------------------------------------------------------------===//
@@ -39,7 +39,7 @@ struct SourceRange {
SourceLocation End;
};
-/// \brief A VariantValue instance annotated with its parser context.
+/// A VariantValue instance annotated with its parser context.
struct ParserValue {
ParserValue() : Text(), Range(), Value() {}
StringRef Text;
@@ -47,16 +47,16 @@ struct ParserValue {
VariantValue Value;
};
-/// \brief Helper class to manage error messages.
+/// Helper class to manage error messages.
class Diagnostics {
public:
- /// \brief Parser context types.
+ /// Parser context types.
enum ContextType {
CT_MatcherArg = 0,
CT_MatcherConstruct = 1
};
- /// \brief All errors from the system.
+ /// All errors from the system.
enum ErrorType {
ET_None = 0,
@@ -80,7 +80,7 @@ public:
ET_ParserOverloadedType = 110
};
- /// \brief Helper stream class.
+ /// Helper stream class.
class ArgStream {
public:
ArgStream(std::vector<std::string> *Out) : Out(Out) {}
@@ -93,7 +93,7 @@ public:
std::vector<std::string> *Out;
};
- /// \brief Class defining a parser context.
+ /// Class defining a parser context.
///
/// Used by the parser to specify (possibly recursive) contexts where the
/// parsing/construction can fail. Any error triggered within a context will
@@ -101,11 +101,11 @@ public:
/// This class should be used as a RAII instance in the stack.
struct Context {
public:
- /// \brief About to call the constructor for a matcher.
+ /// About to call the constructor for a matcher.
enum ConstructMatcherEnum { ConstructMatcher };
Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
SourceRange MatcherRange);
- /// \brief About to recurse into parsing one argument for a matcher.
+ /// About to recurse into parsing one argument for a matcher.
enum MatcherArgEnum { MatcherArg };
Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
SourceRange MatcherRange, unsigned ArgNumber);
@@ -115,7 +115,7 @@ public:
Diagnostics *const Error;
};
- /// \brief Context for overloaded matcher construction.
+ /// Context for overloaded matcher construction.
///
/// This context will take care of merging all errors that happen within it
/// as "candidate" overloads for the same matcher.
@@ -124,7 +124,7 @@ public:
OverloadContext(Diagnostics* Error);
~OverloadContext();
- /// \brief Revert all errors that happened within this context.
+ /// Revert all errors that happened within this context.
void revertErrors();
private:
@@ -132,21 +132,21 @@ public:
unsigned BeginIndex;
};
- /// \brief Add an error to the diagnostics.
+ /// Add an error to the diagnostics.
///
/// All the context information will be kept on the error message.
/// \return a helper class to allow the caller to pass the arguments for the
/// error message, using the << operator.
ArgStream addError(SourceRange Range, ErrorType Error);
- /// \brief Information stored for one frame of the context.
+ /// Information stored for one frame of the context.
struct ContextFrame {
ContextType Type;
SourceRange Range;
std::vector<std::string> Args;
};
- /// \brief Information stored for each error found.
+ /// Information stored for each error found.
struct ErrorContent {
std::vector<ContextFrame> ContextStack;
struct Message {
@@ -158,20 +158,20 @@ public:
};
ArrayRef<ErrorContent> errors() const { return Errors; }
- /// \brief Returns a simple string representation of each error.
+ /// Returns a simple string representation of each error.
///
/// Each error only shows the error message without any context.
void printToStream(llvm::raw_ostream &OS) const;
std::string toString() const;
- /// \brief Returns the full string representation of each error.
+ /// Returns the full string representation of each error.
///
/// Each error message contains the full context.
void printToStreamFull(llvm::raw_ostream &OS) const;
std::string toStringFull() const;
private:
- /// \brief Helper function used by the constructors of ContextFrame.
+ /// Helper function used by the constructors of ContextFrame.
ArgStream pushContextFrame(ContextType Type, SourceRange Range);
std::vector<ContextFrame> ContextStack;
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 e8fcf0a9d6cc..907db69529d2 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Simple matcher expression parser.
+/// Simple matcher expression parser.
///
/// The parser understands matcher expressions of the form:
/// MatcherName(Arg0, Arg1, ..., ArgN)
@@ -52,10 +52,10 @@ namespace dynamic {
class Diagnostics;
-/// \brief Matcher expression parser.
+/// Matcher expression parser.
class Parser {
public:
- /// \brief Interface to connect the parser with the registry and more.
+ /// Interface to connect the parser with the registry and more.
///
/// The parser uses the Sema instance passed into
/// parseMatcherExpression() to handle all matcher tokens. The simplest
@@ -69,7 +69,7 @@ public:
public:
virtual ~Sema();
- /// \brief Process a matcher expression.
+ /// Process a matcher expression.
///
/// All the arguments passed here have already been processed.
///
@@ -92,7 +92,7 @@ public:
ArrayRef<ParserValue> Args,
Diagnostics *Error) = 0;
- /// \brief Look up a matcher by name.
+ /// Look up a matcher by name.
///
/// \param MatcherName The matcher name found by the parser.
///
@@ -101,7 +101,7 @@ public:
virtual llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) = 0;
- /// \brief Compute the list of completion types for \p Context.
+ /// Compute the list of completion types for \p Context.
///
/// Each element of \p Context represents a matcher invocation, going from
/// outermost to innermost. Elements are pairs consisting of a reference to
@@ -112,7 +112,7 @@ public:
virtual std::vector<ArgKind> getAcceptedCompletionTypes(
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
- /// \brief Compute the list of completions that match any of
+ /// Compute the list of completions that match any of
/// \p AcceptedTypes.
///
/// \param AcceptedTypes All types accepted for this completion.
@@ -125,7 +125,7 @@ public:
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes);
};
- /// \brief Sema implementation that uses the matcher registry to process the
+ /// Sema implementation that uses the matcher registry to process the
/// tokens.
class RegistrySema : public Parser::Sema {
public:
@@ -149,7 +149,7 @@ public:
using NamedValueMap = llvm::StringMap<VariantValue>;
- /// \brief Parse a matcher expression.
+ /// Parse a matcher expression.
///
/// \param MatcherCode The matcher expression to parse.
///
@@ -178,7 +178,7 @@ public:
return parseMatcherExpression(MatcherCode, nullptr, Error);
}
- /// \brief Parse an expression.
+ /// Parse an expression.
///
/// Parses any expression supported by this parser. In general, the
/// \c parseMatcherExpression function is a better approach to get a matcher
@@ -202,7 +202,7 @@ public:
return parseExpression(Code, nullptr, Value, Error);
}
- /// \brief Complete an expression at the given offset.
+ /// Complete an expression at the given offset.
///
/// \param S The Sema instance that will help the parser
/// construct the matchers. If null, it uses the default registry.
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 277491250db8..ad8628b4b0d9 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Registry of all known matchers.
+/// Registry of all known matchers.
///
/// The registry provides a generic interface to construct any matcher by name.
//
@@ -49,13 +49,13 @@ struct MatcherCompletion {
return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
}
- /// \brief The text to type to select this matcher.
+ /// The text to type to select this matcher.
std::string TypedText;
- /// \brief The "declaration" of the matcher, with type information.
+ /// The "declaration" of the matcher, with type information.
std::string MatcherDecl;
- /// \brief Value corresponding to the "specificity" of the converted matcher.
+ /// Value corresponding to the "specificity" of the converted matcher.
///
/// Zero specificity indicates that this conversion would produce a trivial
/// matcher that will either always or never match.
@@ -67,13 +67,13 @@ class Registry {
public:
Registry() = delete;
- /// \brief Look up a matcher in the registry by name,
+ /// Look up a matcher in the registry by name,
///
/// \return An opaque value which may be used to refer to the matcher
/// constructor, or Optional<MatcherCtor>() if not found.
static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
- /// \brief Compute the list of completion types for \p Context.
+ /// Compute the list of completion types for \p Context.
///
/// Each element of \p Context represents a matcher invocation, going from
/// outermost to innermost. Elements are pairs consisting of a reference to
@@ -84,7 +84,7 @@ public:
static std::vector<ArgKind> getAcceptedCompletionTypes(
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
- /// \brief Compute the list of completions that match any of
+ /// Compute the list of completions that match any of
/// \p AcceptedTypes.
///
/// \param AcceptedTypes All types accepted for this completion.
@@ -96,7 +96,7 @@ public:
static std::vector<MatcherCompletion>
getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes);
- /// \brief Construct a matcher from the registry.
+ /// Construct a matcher from the registry.
///
/// \param Ctor The matcher constructor to instantiate.
///
@@ -116,7 +116,7 @@ public:
ArrayRef<ParserValue> Args,
Diagnostics *Error);
- /// \brief Construct a matcher from the registry and bind it.
+ /// Construct a matcher from the registry and bind it.
///
/// Similar the \c constructMatcher() above, but it then tries to bind the
/// matcher to the specified \c BindID.
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
index f9efe0f16f43..45ac3cadf685 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Polymorphic value type.
+/// Polymorphic value type.
///
/// Supports all the types required for dynamic Matcher construction.
/// Used by the registry to construct matchers in a generic way.
@@ -28,7 +28,7 @@ namespace clang {
namespace ast_matchers {
namespace dynamic {
-/// \brief Kind identifier.
+/// Kind identifier.
///
/// It supports all types that VariantValue can contain.
class ArgKind {
@@ -40,10 +40,10 @@ class ArgKind {
AK_Unsigned,
AK_String
};
- /// \brief Constructor for non-matcher types.
+ /// Constructor for non-matcher types.
ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
- /// \brief Constructor for matcher types.
+ /// Constructor for matcher types.
ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
: K(AK_Matcher), MatcherKind(MatcherKind) {}
@@ -53,7 +53,7 @@ class ArgKind {
return MatcherKind;
}
- /// \brief Determines if this type can be converted to \p To.
+ /// Determines if this type can be converted to \p To.
///
/// \param To the requested destination type.
///
@@ -67,7 +67,7 @@ class ArgKind {
return K < Other.K;
}
- /// \brief String representation of the type.
+ /// String representation of the type.
std::string asString() const;
private:
@@ -77,7 +77,7 @@ private:
using ast_matchers::internal::DynTypedMatcher;
-/// \brief A variant matcher object.
+/// A variant matcher object.
///
/// The purpose of this object is to abstract simple and polymorphic matchers
/// into a single object type.
@@ -91,7 +91,7 @@ using ast_matchers::internal::DynTypedMatcher;
/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
/// the underlying matcher(s) can unambiguously return a Matcher<T>.
class VariantMatcher {
- /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
+ /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
class MatcherOps {
public:
MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
@@ -99,12 +99,12 @@ class VariantMatcher {
bool canConstructFrom(const DynTypedMatcher &Matcher,
bool &IsExactMatch) const;
- /// \brief Convert \p Matcher the destination type and return it as a new
+ /// Convert \p Matcher the destination type and return it as a new
/// DynTypedMatcher.
virtual DynTypedMatcher
convertMatcher(const DynTypedMatcher &Matcher) const = 0;
- /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
+ /// Constructs a variadic typed matcher from \p InnerMatchers.
/// Will try to convert each inner matcher to the destination type and
/// return llvm::None if it fails to do so.
llvm::Optional<DynTypedMatcher>
@@ -118,7 +118,7 @@ class VariantMatcher {
ast_type_traits::ASTNodeKind NodeKind;
};
- /// \brief Payload interface to be specialized by each matcher type.
+ /// Payload interface to be specialized by each matcher type.
///
/// It follows a similar interface as VariantMatcher itself.
class Payload {
@@ -133,39 +133,39 @@ class VariantMatcher {
};
public:
- /// \brief A null matcher.
+ /// A null matcher.
VariantMatcher();
- /// \brief Clones the provided matcher.
+ /// Clones the provided matcher.
static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
- /// \brief Clones the provided matchers.
+ /// Clones the provided matchers.
///
/// They should be the result of a polymorphic matcher.
static VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
- /// \brief Creates a 'variadic' operator matcher.
+ /// Creates a 'variadic' operator matcher.
///
/// It will bind to the appropriate type on getTypedMatcher<T>().
static VariantMatcher
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
std::vector<VariantMatcher> Args);
- /// \brief Makes the matcher the "null" matcher.
+ /// Makes the matcher the "null" matcher.
void reset();
- /// \brief Whether the matcher is null.
+ /// Whether the matcher is null.
bool isNull() const { return !Value; }
- /// \brief Return a single matcher, if there is no ambiguity.
+ /// Return a single matcher, if there is no ambiguity.
///
/// \returns the matcher, if there is only one matcher. An empty Optional, if
/// the underlying matcher is a polymorphic matcher with more than one
/// representation.
llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
- /// \brief Determines if the contained matcher can be converted to
+ /// Determines if the contained matcher can be converted to
/// \c Matcher<T>.
///
/// For the Single case, it returns true if it can be converted to
@@ -179,7 +179,7 @@ public:
return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
}
- /// \brief Determines if the contained matcher can be converted to \p Kind.
+ /// Determines if the contained matcher can be converted to \p Kind.
///
/// \param Kind the requested destination type.
///
@@ -192,7 +192,7 @@ public:
return false;
}
- /// \brief Return this matcher as a \c Matcher<T>.
+ /// Return this matcher as a \c Matcher<T>.
///
/// Handles the different types (Single, Polymorphic) accordingly.
/// Asserts that \c hasTypedMatcher<T>() is true.
@@ -203,7 +203,7 @@ public:
->template convertTo<T>();
}
- /// \brief String representation of the type of the value.
+ /// String representation of the type of the value.
///
/// If the underlying matcher is a polymorphic one, the string will show all
/// the types.
@@ -234,7 +234,7 @@ struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
}
};
-/// \brief Variant value class.
+/// Variant value class.
///
/// Basically, a tagged union with value type semantics.
/// It is used by the registry as the return value and argument type for the
@@ -256,46 +256,46 @@ public:
~VariantValue();
VariantValue &operator=(const VariantValue &Other);
- /// \brief Specific constructors for each supported type.
+ /// Specific constructors for each supported type.
VariantValue(bool Boolean);
VariantValue(double Double);
VariantValue(unsigned Unsigned);
VariantValue(StringRef String);
VariantValue(const VariantMatcher &Matchers);
- /// \brief Constructs an \c unsigned value (disambiguation from bool).
+ /// Constructs an \c unsigned value (disambiguation from bool).
VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
- /// \brief Returns true iff this is not an empty value.
+ /// Returns true iff this is not an empty value.
explicit operator bool() const { return hasValue(); }
bool hasValue() const { return Type != VT_Nothing; }
- /// \brief Boolean value functions.
+ /// Boolean value functions.
bool isBoolean() const;
bool getBoolean() const;
void setBoolean(bool Boolean);
- /// \brief Double value functions.
+ /// Double value functions.
bool isDouble() const;
double getDouble() const;
void setDouble(double Double);
- /// \brief Unsigned value functions.
+ /// Unsigned value functions.
bool isUnsigned() const;
unsigned getUnsigned() const;
void setUnsigned(unsigned Unsigned);
- /// \brief String value functions.
+ /// String value functions.
bool isString() const;
const std::string &getString() const;
void setString(StringRef String);
- /// \brief Matcher value functions.
+ /// Matcher value functions.
bool isMatcher() const;
const VariantMatcher &getMatcher() const;
void setMatcher(const VariantMatcher &Matcher);
- /// \brief Determines if the contained value can be converted to \p Kind.
+ /// Determines if the contained value can be converted to \p Kind.
///
/// \param Kind the requested destination type.
///
@@ -303,7 +303,7 @@ public:
/// conversion.
bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
- /// \brief Determines if the contained value can be converted to any kind
+ /// Determines if the contained value can be converted to any kind
/// in \p Kinds.
///
/// \param Kinds the requested destination types.
@@ -313,13 +313,13 @@ public:
/// conversions.
bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
- /// \brief String representation of the type of the value.
+ /// String representation of the type of the value.
std::string getTypeAsString() const;
private:
void reset();
- /// \brief All supported value types.
+ /// All supported value types.
enum ValueType {
VT_Nothing,
VT_Boolean,
@@ -329,7 +329,7 @@ private:
VT_Matcher
};
- /// \brief All supported value types.
+ /// All supported value types.
union AllValues {
unsigned Unsigned;
double Double;
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index cc14c7bd33db..49da6815ace9 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -1,4 +1,4 @@
-//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- C++ -*-==//
+//===- CFGReachabilityAnalysis.h - Basic reachability analysis --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,17 +23,19 @@ namespace clang {
class CFG;
class CFGBlock;
-
+
// A class that performs reachability queries for CFGBlocks. Several internal
// checks in this checker require reachability information. The requests all
// tend to have a common destination, so we lazily do a predecessor search
// from the destination node and cache the results to prevent work
// duplication.
class CFGReverseBlockReachabilityAnalysis {
- typedef llvm::BitVector ReachableSet;
- typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
+ using ReachableSet = llvm::BitVector;
+ using ReachableMap = llvm::DenseMap<unsigned, ReachableSet>;
+
ReachableSet analyzed;
ReachableMap reachable;
+
public:
CFGReverseBlockReachabilityAnalysis(const CFG &cfg);
@@ -43,7 +45,7 @@ public:
private:
void mapReachability(const CFGBlock *Dst);
};
-
-}
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_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 5ba42b475c83..5a70989e5087 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
@@ -1,4 +1,4 @@
-//===- Consumed.h ----------------------------------------------*- C++ --*-===//
+//===- Consumed.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,41 +15,53 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <list>
+#include <memory>
+#include <utility>
+#include <vector>
namespace clang {
+
+class AnalysisDeclContext;
+class CXXBindTemporaryExpr;
+class FunctionDecl;
+class PostOrderCFGView;
+class Stmt;
+class VarDecl;
+
namespace consumed {
-
+
+ class ConsumedStmtVisitor;
+
enum ConsumedState {
// No state information for the given variable.
CS_None,
-
+
CS_Unknown,
CS_Unconsumed,
CS_Consumed
};
-
- class ConsumedStmtVisitor;
-
- typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
- typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
- typedef std::list<DelayedDiag> DiagList;
- class ConsumedWarningsHandlerBase {
+ using OptionalNotes = SmallVector<PartialDiagnosticAt, 1>;
+ using DelayedDiag = std::pair<PartialDiagnosticAt, OptionalNotes>;
+ using DiagList = std::list<DelayedDiag>;
+ class ConsumedWarningsHandlerBase {
public:
-
virtual ~ConsumedWarningsHandlerBase();
- /// \brief Emit the warnings and notes left by the analysis.
+ /// Emit the warnings and notes left by the analysis.
virtual void emitDiagnostics() {}
-
- /// \brief Warn that a variable's state doesn't match at the entry and exit
+
+ /// Warn that a variable's state doesn't match at the entry and exit
/// of a loop.
///
/// \param Loc -- The location of the end of the loop.
@@ -58,8 +70,8 @@ namespace consumed {
/// state.
virtual void warnLoopStateMismatch(SourceLocation Loc,
StringRef VariableName) {}
-
- /// \brief Warn about parameter typestate mismatches upon return.
+
+ /// Warn about parameter typestate mismatches upon return.
///
/// \param Loc -- The SourceLocation of the return statement.
///
@@ -72,23 +84,23 @@ namespace consumed {
StringRef VariableName,
StringRef ExpectedState,
StringRef ObservedState) {}
-
+
// FIXME: Add documentation.
virtual void warnParamTypestateMismatch(SourceLocation LOC,
StringRef ExpectedState,
StringRef ObservedState) {}
-
+
// FIXME: This can be removed when the attr propagation fix for templated
// classes lands.
- /// \brief Warn about return typestates set for unconsumable types.
- ///
+ /// Warn about return typestates set for unconsumable types.
+ ///
/// \param Loc -- The location of the attributes.
///
/// \param TypeName -- The name of the unconsumable type.
virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
StringRef TypeName) {}
-
- /// \brief Warn about return typestate mismatches.
+
+ /// Warn about return typestate mismatches.
///
/// \param Loc -- The SourceLocation of the return statement.
///
@@ -101,7 +113,7 @@ namespace consumed {
StringRef ExpectedState,
StringRef ObservedState) {}
- /// \brief Warn about use-while-consumed errors.
+ /// Warn about use-while-consumed errors.
/// \param MethodName -- The name of the method that was incorrectly
/// invoked.
///
@@ -112,7 +124,7 @@ namespace consumed {
StringRef State,
SourceLocation Loc) {}
- /// \brief Warn about use-while-consumed errors.
+ /// Warn about use-while-consumed errors.
/// \param MethodName -- The name of the method that was incorrectly
/// invoked.
///
@@ -129,88 +141,84 @@ namespace consumed {
};
class ConsumedStateMap {
-
- typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType;
- typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>
- TmpMapType;
-
+ using VarMapType = llvm::DenseMap<const VarDecl *, ConsumedState>;
+ using TmpMapType =
+ llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>;
+
protected:
-
- bool Reachable;
- const Stmt *From;
+ bool Reachable = true;
+ const Stmt *From = nullptr;
VarMapType VarMap;
TmpMapType TmpMap;
-
+
public:
- ConsumedStateMap() : Reachable(true), From(nullptr) {}
+ ConsumedStateMap() = default;
ConsumedStateMap(const ConsumedStateMap &Other)
- : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
- TmpMap() {}
-
- /// \brief Warn if any of the parameters being tracked are not in the state
+ : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
+ TmpMap() {}
+
+ /// Warn if any of the parameters being tracked are not in the state
/// they were declared to be in upon return from a function.
void checkParamsForReturnTypestate(SourceLocation BlameLoc,
ConsumedWarningsHandlerBase &WarningsHandler) const;
-
- /// \brief Clear the TmpMap.
+
+ /// Clear the TmpMap.
void clearTemporaries();
-
- /// \brief Get the consumed state of a given variable.
+
+ /// Get the consumed state of a given variable.
ConsumedState getState(const VarDecl *Var) const;
-
- /// \brief Get the consumed state of a given temporary value.
+
+ /// Get the consumed state of a given temporary value.
ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
-
- /// \brief Merge this state map with another map.
+
+ /// Merge this state map with another map.
void intersect(const ConsumedStateMap &Other);
void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
const ConsumedStateMap *LoopBackStates,
ConsumedWarningsHandlerBase &WarningsHandler);
-
- /// \brief Return true if this block is reachable.
+
+ /// Return true if this block is reachable.
bool isReachable() const { return Reachable; }
-
- /// \brief Mark the block as unreachable.
+
+ /// Mark the block as unreachable.
void markUnreachable();
-
- /// \brief Set the source for a decision about the branching of states.
+
+ /// Set the source for a decision about the branching of states.
/// \param Source -- The statement that was the origin of a branching
/// decision.
void setSource(const Stmt *Source) { this->From = Source; }
-
- /// \brief Set the consumed state of a given variable.
+
+ /// Set the consumed state of a given variable.
void setState(const VarDecl *Var, ConsumedState State);
-
- /// \brief Set the consumed state of a given temporary value.
+
+ /// Set the consumed state of a given temporary value.
void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
-
- /// \brief Remove the temporary value from our state map.
+
+ /// Remove the temporary value from our state map.
void remove(const CXXBindTemporaryExpr *Tmp);
-
- /// \brief Tests to see if there is a mismatch in the states stored in two
+
+ /// Tests to see if there is a mismatch in the states stored in two
/// maps.
///
/// \param Other -- The second map to compare against.
bool operator!=(const ConsumedStateMap *Other) const;
};
-
+
class ConsumedBlockInfo {
std::vector<std::unique_ptr<ConsumedStateMap>> StateMapsArray;
std::vector<unsigned int> VisitOrder;
-
+
public:
ConsumedBlockInfo() = default;
ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
: StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
unsigned int VisitOrderCounter = 0;
- for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
- BE = SortedGraph->end(); BI != BE; ++BI) {
- VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++;
- }
+ for (const auto BI : *SortedGraph)
+ VisitOrder[BI->getBlockID()] = VisitOrderCounter++;
}
-
+
bool allBackEdgesVisited(const CFGBlock *CurrBlock,
const CFGBlock *TargetBlock);
@@ -220,7 +228,7 @@ namespace consumed {
std::unique_ptr<ConsumedStateMap> StateMap);
ConsumedStateMap* borrowInfo(const CFGBlock *Block);
-
+
void discardInfo(const CFGBlock *Block);
std::unique_ptr<ConsumedStateMap> getInfo(const CFGBlock *Block);
@@ -231,27 +239,25 @@ namespace consumed {
/// A class that handles the analysis of uniqueness violations.
class ConsumedAnalyzer {
-
ConsumedBlockInfo BlockInfo;
std::unique_ptr<ConsumedStateMap> CurrStates;
ConsumedState ExpectedReturnState;
-
+
void determineExpectedReturnState(AnalysisDeclContext &AC,
const FunctionDecl *D);
bool splitState(const CFGBlock *CurrBlock,
const ConsumedStmtVisitor &Visitor);
-
+
public:
-
ConsumedWarningsHandlerBase &WarningsHandler;
ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
: WarningsHandler(WarningsHandler) {}
ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
-
- /// \brief Check a function's CFG for consumed violations.
+
+ /// Check a function's CFG for consumed violations.
///
/// We traverse the blocks in the CFG, keeping track of the state of each
/// value who's type has uniquness annotations. If methods are invoked in
@@ -259,6 +265,9 @@ namespace consumed {
/// exactly once.
void run(AnalysisDeclContext &AC);
};
-}} // end namespace clang::consumed
-#endif
+} // namespace consumed
+
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
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 6cb161ab37c8..021e98dcd885 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
@@ -1,4 +1,4 @@
-//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==//
+//- Dominators.h - Implementation of dominators tree for Clang CFG -*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -16,29 +16,35 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
+#include "llvm/Support/raw_ostream.h"
// FIXME: There is no good reason for the domtree to require a print method
// which accepts an LLVM Module, so remove this (and the method's argument that
// needs it) when that is fixed.
+
namespace llvm {
+
class Module;
-}
+
+} // namespace llvm
namespace clang {
-class CFGBlock;
-typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode;
+using DomTreeNode = llvm::DomTreeNodeBase<CFGBlock>;
-/// \brief Concrete subclass of DominatorTreeBase for Clang
+/// Concrete subclass of DominatorTreeBase for Clang
/// This class implements the dominators tree functionality given a Clang CFG.
///
class DominatorTree : public ManagedAnalysis {
virtual void anchor();
+
public:
- llvm::DomTreeBase<CFGBlock>* DT;
+ llvm::DomTreeBase<CFGBlock> *DT;
DominatorTree() {
DT = new llvm::DomTreeBase<CFGBlock>();
@@ -48,23 +54,21 @@ public:
llvm::DomTreeBase<CFGBlock>& getBase() { return *DT; }
- /// \brief This method returns the root CFGBlock of the dominators tree.
- ///
- inline CFGBlock *getRoot() const {
+ /// This method returns the root CFGBlock of the dominators tree.
+ CFGBlock *getRoot() const {
return DT->getRoot();
}
- /// \brief This method returns the root DomTreeNode, which is the wrapper
+ /// This method returns the root DomTreeNode, which is the wrapper
/// for CFGBlock.
- inline DomTreeNode *getRootNode() const {
+ DomTreeNode *getRootNode() const {
return DT->getRootNode();
}
- /// \brief This method compares two dominator trees.
+ /// This method compares two dominator trees.
/// The method returns false if the other dominator tree matches this
/// dominator tree, otherwise returns true.
- ///
- inline bool compare(DominatorTree &Other) const {
+ bool compare(DominatorTree &Other) const {
DomTreeNode *R = getRootNode();
DomTreeNode *OtherR = Other.getRootNode();
@@ -77,17 +81,15 @@ public:
return false;
}
- /// \brief This method builds the dominator tree for a given CFG
+ /// This method builds the dominator tree for a given CFG
/// The CFG information is passed via AnalysisDeclContext
- ///
void buildDominatorTree(AnalysisDeclContext &AC) {
cfg = AC.getCFG();
DT->recalculate(*cfg);
}
- /// \brief This method dumps immediate dominators for each block,
+ /// This method dumps immediate dominators for each block,
/// mainly used for debug purposes.
- ///
void dump() {
llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n";
for (CFG::const_iterator I = cfg->begin(),
@@ -102,55 +104,48 @@ public:
}
}
- /// \brief This method tests if one CFGBlock dominates the other.
+ /// This method tests if one CFGBlock dominates the other.
/// The method return true if A dominates B, false otherwise.
/// Note a block always dominates itself.
- ///
- inline bool dominates(const CFGBlock* A, const CFGBlock* B) const {
+ bool dominates(const CFGBlock *A, const CFGBlock *B) const {
return DT->dominates(A, B);
}
- /// \brief This method tests if one CFGBlock properly dominates the other.
+ /// This method tests if one CFGBlock properly dominates the other.
/// The method return true if A properly dominates B, false otherwise.
- ///
- bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const {
+ bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const {
return DT->properlyDominates(A, B);
}
- /// \brief This method finds the nearest common dominator CFG block
+ /// This method finds the nearest common dominator CFG block
/// for CFG block A and B. If there is no such block then return NULL.
- ///
- inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
+ CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
- inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
- const CFGBlock *B) {
+ const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
+ const CFGBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
- /// \brief This method is used to update the dominator
+ /// This method is used to update the dominator
/// tree information when a node's immediate dominator changes.
- ///
- inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
+ void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
DT->changeImmediateDominator(N, NewIDom);
}
- /// \brief This method tests if the given CFGBlock can be reachable from root.
+ /// This method tests if the given CFGBlock can be reachable from root.
/// Returns true if reachable, false otherwise.
- ///
bool isReachableFromEntry(const CFGBlock *A) {
return DT->isReachableFromEntry(A);
}
- /// \brief This method releases the memory held by the dominator tree.
- ///
+ /// This method releases the memory held by the dominator tree.
virtual void releaseMemory() {
DT->releaseMemory();
}
- /// \brief This method converts the dominator tree to human readable form.
- ///
+ /// This method converts the dominator tree to human readable form.
virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
DT->print(OS);
}
@@ -159,23 +154,24 @@ private:
CFG *cfg;
};
-} // end namespace clang
+} // namespace clang
//===-------------------------------------
/// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators.
///
namespace llvm {
+
template <> struct GraphTraits< ::clang::DomTreeNode* > {
- typedef ::clang::DomTreeNode *NodeRef;
- typedef ::clang::DomTreeNode::iterator ChildIteratorType;
+ using NodeRef = ::clang::DomTreeNode *;
+ using ChildIteratorType = ::clang::DomTreeNode::iterator;
static NodeRef getEntryNode(NodeRef N) { return N; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
- typedef llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>
- nodes_iterator;
+ using nodes_iterator =
+ llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>;
static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
return nodes_iterator(df_begin(getEntryNode(N)));
@@ -187,7 +183,7 @@ template <> struct GraphTraits< ::clang::DomTreeNode* > {
};
template <> struct GraphTraits< ::clang::DominatorTree* >
- : public GraphTraits< ::clang::DomTreeNode* > {
+ : public GraphTraits< ::clang::DomTreeNode* > {
static NodeRef getEntryNode(::clang::DominatorTree *DT) {
return DT->getRootNode();
}
@@ -200,6 +196,7 @@ template <> struct GraphTraits< ::clang::DominatorTree* >
return nodes_iterator(df_end(getEntryNode(N)));
}
};
-} // end namespace llvm
-#endif
+} // namespace llvm
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
index 8c531d638cc2..598d341ac829 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
@@ -236,7 +236,7 @@ public:
const char *toString() const;
bool isPrintfKind() const { return IsPrintf; }
-
+
Optional<ConversionSpecifier> getStandardSpecifier() const;
protected:
@@ -256,18 +256,26 @@ public:
private:
const Kind K;
QualType T;
- const char *Name;
- bool Ptr;
+ const char *Name = nullptr;
+ bool Ptr = false;
+
+ /// The TypeKind identifies certain well-known types like size_t and
+ /// ptrdiff_t.
+ enum class TypeKind { DontCare, SizeT, PtrdiffT };
+ TypeKind TK = TypeKind::DontCare;
+
public:
- ArgType(Kind k = UnknownTy, const char *n = nullptr)
- : K(k), Name(n), Ptr(false) {}
- ArgType(QualType t, const char *n = nullptr)
- : K(SpecificTy), T(t), Name(n), Ptr(false) {}
- ArgType(CanQualType t) : K(SpecificTy), T(t), Name(nullptr), Ptr(false) {}
+ ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {}
+ ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {}
+ ArgType(CanQualType T) : K(SpecificTy), T(T) {}
static ArgType Invalid() { return ArgType(InvalidTy); }
bool isValid() const { return K != InvalidTy; }
+ bool isSizeT() const { return TK == TypeKind::SizeT; }
+
+ bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; }
+
/// Create an ArgType which corresponds to the type pointer to A.
static ArgType PtrTo(const ArgType& A) {
assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
@@ -276,6 +284,21 @@ public:
return Res;
}
+ /// Create an ArgType which corresponds to the size_t/ssize_t type.
+ static ArgType makeSizeT(const ArgType &A) {
+ ArgType Res = A;
+ Res.TK = TypeKind::SizeT;
+ return Res;
+ }
+
+ /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t
+ /// type.
+ static ArgType makePtrdiffT(const ArgType &A) {
+ ArgType Res = A;
+ Res.TK = TypeKind::PtrdiffT;
+ return Res;
+ }
+
MatchKind matchesType(ASTContext &C, QualType argTy) const;
QualType getRepresentativeType(ASTContext &C) const;
@@ -510,7 +533,7 @@ public:
return getConversionSpecifier().consumesDataArgument();
}
- /// \brief Returns the builtin type that a data argument
+ /// Returns the builtin type that a data argument
/// paired with this format specifier should have. This method
/// will return null if the format specifier does not have
/// a matching data argument or the matching argument matches
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 6a1222386bae..0cb500fffb95 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
@@ -25,7 +25,7 @@ class CFGBlock;
class Stmt;
class DeclRefExpr;
class SourceManager;
-
+
class LiveVariables : public ManagedAnalysis {
public:
class LivenessValues {
@@ -33,33 +33,36 @@ public:
llvm::ImmutableSet<const Stmt *> liveStmts;
llvm::ImmutableSet<const VarDecl *> liveDecls;
-
+ llvm::ImmutableSet<const BindingDecl *> liveBindings;
+
bool equals(const LivenessValues &V) const;
LivenessValues()
- : liveStmts(nullptr), liveDecls(nullptr) {}
+ : liveStmts(nullptr), liveDecls(nullptr), liveBindings(nullptr) {}
LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts,
- llvm::ImmutableSet<const VarDecl *> LiveDecls)
- : liveStmts(LiveStmts), liveDecls(LiveDecls) {}
+ llvm::ImmutableSet<const VarDecl *> LiveDecls,
+ llvm::ImmutableSet<const BindingDecl *> LiveBindings)
+ : liveStmts(LiveStmts), liveDecls(LiveDecls),
+ liveBindings(LiveBindings) {}
bool isLive(const Stmt *S) const;
bool isLive(const VarDecl *D) const;
-
- friend class LiveVariables;
+
+ friend class LiveVariables;
};
-
+
class Observer {
virtual void anchor();
public:
virtual ~Observer() {}
-
+
/// A callback invoked right before invoking the
/// liveness transfer function on the given statement.
virtual void observeStmt(const Stmt *S,
const CFGBlock *currentBlock,
const LivenessValues& V) {}
-
+
/// Called when the live variables analysis registers
/// that a variable is killed.
virtual void observerKill(const DeclRefExpr *DR) {}
@@ -70,47 +73,47 @@ public:
/// Compute the liveness information for a given CFG.
static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext,
bool killAtAssign);
-
+
/// Return true if a variable is live at the end of a
/// specified block.
bool isLive(const CFGBlock *B, const VarDecl *D);
-
+
/// Returns true if a variable is live at the beginning of the
/// the statement. This query only works if liveness information
/// has been recorded at the statement level (see runOnAllBlocks), and
/// only returns liveness information for block-level expressions.
bool isLive(const Stmt *S, const VarDecl *D);
-
+
/// Returns true the block-level expression "value" is live
/// before the given block-level expression (see runOnAllBlocks).
bool isLive(const Stmt *Loc, const Stmt *StmtVal);
-
+
/// Print to stderr the liveness information associated with
/// each basic block.
void dumpBlockLiveness(const SourceManager& M);
void runOnAllBlocks(Observer &obs);
-
+
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, true);
}
-
+
static const void *getTag();
-
+
private:
LiveVariables(void *impl);
void *impl;
};
-
+
class RelaxedLiveVariables : public LiveVariables {
public:
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, false);
}
-
+
static const void *getTag();
};
-
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
index c0a93528373e..7df3dc66c311 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -1,4 +1,4 @@
-//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-//
+//===- PostOrderCFGView.h - Post order view of CFG blocks -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,22 +14,23 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
-#include <vector>
-//#include <algorithm>
-
-#include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/BitVector.h"
-
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include <utility>
+#include <vector>
namespace clang {
class PostOrderCFGView : public ManagedAnalysis {
virtual void anchor();
+
public:
- /// \brief Implements a set of CFGBlocks using a BitVector.
+ /// Implements a set of CFGBlocks using a BitVector.
///
/// This class contains a minimal interface, primarily dictated by the SetType
/// template parameter of the llvm::po_iterator template, as used with
@@ -37,15 +38,16 @@ public:
/// visit during the analysis.
class CFGBlockSet {
llvm::BitVector VisitedBlockIDs;
+
public:
// po_iterator requires this iterator, but the only interface needed is the
- // value_type typedef.
- struct iterator { typedef const CFGBlock *value_type; };
+ // value_type type.
+ struct iterator { using value_type = const CFGBlock *; };
- CFGBlockSet() {}
+ CFGBlockSet() = default;
CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
- /// \brief Set the bit associated with a particular CFGBlock.
+ /// Set the bit associated with a particular CFGBlock.
/// This is the important method for the SetType template parameter.
std::pair<llvm::NoneType, bool> insert(const CFGBlock *Block) {
// Note that insert() is called by po_iterator, which doesn't check to
@@ -60,7 +62,7 @@ public:
return std::make_pair(None, true);
}
- /// \brief Check if the bit for a CFGBlock has been already set.
+ /// Check if the bit for a CFGBlock has been already set.
/// This method is for tracking visited blocks in the main threadsafety
/// loop. Block must not be null.
bool alreadySet(const CFGBlock *Block) {
@@ -69,33 +71,34 @@ public:
};
private:
- typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator;
- std::vector<const CFGBlock*> Blocks;
+ using po_iterator = llvm::po_iterator<const CFG *, CFGBlockSet, true>;
+ std::vector<const CFGBlock *> Blocks;
- typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy;
+ using BlockOrderTy = llvm::DenseMap<const CFGBlock *, unsigned>;
BlockOrderTy BlockOrder;
public:
- typedef std::vector<const CFGBlock *>::reverse_iterator iterator;
- typedef std::vector<const CFGBlock *>::const_reverse_iterator const_iterator;
+ friend struct BlockOrderCompare;
+
+ using iterator = std::vector<const CFGBlock *>::reverse_iterator;
+ using const_iterator = std::vector<const CFGBlock *>::const_reverse_iterator;
PostOrderCFGView(const CFG *cfg);
iterator begin() { return Blocks.rbegin(); }
- iterator end() { return Blocks.rend(); }
+ iterator end() { return Blocks.rend(); }
const_iterator begin() const { return Blocks.rbegin(); }
const_iterator end() const { return Blocks.rend(); }
bool empty() const { return begin() == end(); }
- struct BlockOrderCompare;
- friend struct BlockOrderCompare;
-
struct BlockOrderCompare {
const PostOrderCFGView &POV;
+
public:
BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
+
bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
};
@@ -109,7 +112,6 @@ public:
static PostOrderCFGView *create(AnalysisDeclContext &analysisContext);
};
-} // end clang namespace
-
-#endif
+} // namespace clang
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h
index 4c523bfc8b56..d79f1b03df7b 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h
@@ -57,7 +57,7 @@ public:
};
/// ScanReachableFromBlock - Mark all blocks reachable from Start.
-/// Returns the total number of blocks that were marked reachable.
+/// Returns the total number of blocks that were marked reachable.
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable);
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 7e403b1f4090..c72db6f2b24b 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -1,4 +1,4 @@
-//===- ThreadSafety.h ------------------------------------------*- C++ --*-===//
+//===- ThreadSafety.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,11 +19,15 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
-#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
+
+class AnalysisDeclContext;
+class FunctionDecl;
+class NamedDecl;
+
namespace threadSafety {
class BeforeSet;
@@ -31,27 +35,44 @@ class BeforeSet;
/// This enum distinguishes between different kinds of operations that may
/// need to be protected by locks. We use this enum in error handling.
enum ProtectedOperationKind {
- POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;)
- POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;)
- POK_FunctionCall, ///< Making a function call (e.g. fool())
- POK_PassByRef, ///< Passing a guarded variable by reference.
- POK_PtPassByRef, ///< Passing a pt-guarded variable by reference.
+ /// Dereferencing a variable (e.g. p in *p = 5;)
+ POK_VarDereference,
+
+ /// Reading or writing a variable (e.g. x in x = 5;)
+ POK_VarAccess,
+
+ /// Making a function call (e.g. fool())
+ POK_FunctionCall,
+
+ /// Passing a guarded variable by reference.
+ POK_PassByRef,
+
+ /// Passing a pt-guarded variable by reference.
+ POK_PtPassByRef
};
/// This enum distinguishes between different kinds of lock actions. For
/// example, it is an error to write a variable protected by shared version of a
/// mutex.
enum LockKind {
- LK_Shared, ///< Shared/reader lock of a mutex.
- LK_Exclusive, ///< Exclusive/writer lock of a mutex.
- LK_Generic ///< Can be either Shared or Exclusive
+ /// Shared/reader lock of a mutex.
+ LK_Shared,
+
+ /// Exclusive/writer lock of a mutex.
+ LK_Exclusive,
+
+ /// Can be either Shared or Exclusive.
+ LK_Generic
};
/// This enum distinguishes between different ways to access (read or write) a
/// variable.
enum AccessKind {
- AK_Read, ///< Reading a variable.
- AK_Written ///< Writing a variable.
+ /// Reading a variable.
+ AK_Read,
+
+ /// Writing a variable.
+ AK_Written
};
/// This enum distinguishes between different situations where we warn due to
@@ -72,8 +93,9 @@ enum LockErrorKind {
/// Handler class for thread safety warnings.
class ThreadSafetyHandler {
public:
- typedef StringRef Name;
- ThreadSafetyHandler() : IssueBetaWarnings(false) { }
+ using Name = StringRef;
+
+ ThreadSafetyHandler() = default;
virtual ~ThreadSafetyHandler();
/// Warn about lock expressions which fail to resolve to lockable objects.
@@ -185,7 +207,6 @@ public:
virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
Name LockName, SourceLocation Loc) {}
-
/// Warn that L1 cannot be acquired before L2.
virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
Name L2Name, SourceLocation Loc) {}
@@ -204,10 +225,10 @@ public:
void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
private:
- bool IssueBetaWarnings;
+ bool IssueBetaWarnings = false;
};
-/// \brief Check a function's CFG for thread-safety violations.
+/// Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
@@ -218,9 +239,11 @@ void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
void threadSafetyCleanup(BeforeSet *Cache);
-/// \brief Helper function that returns a LockKind required for the given level
+/// Helper function that returns a LockKind required for the given level
/// of access.
LockKind getLockKindFromAccessKind(AccessKind AK);
-}} // end namespace clang::threadSafety
-#endif
+} // namespace threadSafety
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_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 414645b7231b..599c164923cb 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===//
+//===- ThreadSafetyCommon.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -22,20 +22,41 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
+#include "clang/AST/Decl.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
#include "clang/Analysis/AnalysisDeclContext.h"
-#include "clang/Basic/OperatorKinds.h"
-#include <memory>
-#include <ostream>
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
#include <sstream>
+#include <string>
+#include <utility>
#include <vector>
-
namespace clang {
-namespace threadSafety {
+class AbstractConditionalOperator;
+class ArraySubscriptExpr;
+class BinaryOperator;
+class CallExpr;
+class CastExpr;
+class CXXDestructorDecl;
+class CXXMemberCallExpr;
+class CXXOperatorCallExpr;
+class CXXThisExpr;
+class DeclRefExpr;
+class DeclStmt;
+class Expr;
+class MemberExpr;
+class Stmt;
+class UnaryOperator;
+
+namespace threadSafety {
// Various helper functions on til::SExpr
namespace sx {
@@ -72,9 +93,7 @@ inline std::string toString(const til::SExpr *E) {
return ss.str();
}
-} // end namespace sx
-
-
+} // namespace sx
// This class defines the interface of a clang CFG Visitor.
// CFGWalker will invoke the following methods.
@@ -123,11 +142,10 @@ class CFGVisitor {
void exitCFG(const CFGBlock *Last) {}
};
-
// Walks the clang CFG, and invokes methods on a given CFGVisitor.
class CFGWalker {
public:
- CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {}
+ CFGWalker() = default;
// Initialize the CFGWalker. This setup only needs to be done once, even
// if there are multiple passes over the CFG.
@@ -186,15 +204,15 @@ public:
// Process statements
for (const auto &BI : *CurrBlock) {
switch (BI.getKind()) {
- case CFGElement::Statement: {
+ case CFGElement::Statement:
V.handleStatement(BI.castAs<CFGStmt>().getStmt());
break;
- }
+
case CFGElement::AutomaticObjectDtor: {
CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
- CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
+ auto *DD = const_cast<CXXDestructorDecl *>(
AD.getDestructorDecl(ACtx->getASTContext()));
- VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
+ auto *VD = const_cast<VarDecl *>(AD.getVarDecl());
V.handleDestructorCall(VD, DD);
break;
}
@@ -242,28 +260,27 @@ public:
const PostOrderCFGView *getSortedGraph() const { return SortedGraph; }
private:
- CFG *CFGraph;
- AnalysisDeclContext *ACtx;
- PostOrderCFGView *SortedGraph;
+ CFG *CFGraph = nullptr;
+ AnalysisDeclContext *ACtx = nullptr;
+ PostOrderCFGView *SortedGraph = nullptr;
};
-
-
-
+// TODO: move this back into ThreadSafety.cpp
+// This is specific to thread safety. It is here because
+// translateAttrExpr needs it, but that should be moved too.
class CapabilityExpr {
- // TODO: move this back into ThreadSafety.cpp
- // This is specific to thread safety. It is here because
- // translateAttrExpr needs it, but that should be moved too.
-
private:
- const til::SExpr* CapExpr; ///< The capability expression.
- bool Negated; ///< True if this is a negative capability
+ /// The capability expression.
+ const til::SExpr* CapExpr;
+
+ /// True if this is a negative capability.
+ bool Negated;
public:
CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
- const til::SExpr* sexpr() const { return CapExpr; }
- bool negative() const { return Negated; }
+ const til::SExpr* sexpr() const { return CapExpr; }
+ bool negative() const { return Negated; }
CapabilityExpr operator!() const {
return CapabilityExpr(CapExpr, !Negated);
@@ -289,9 +306,9 @@ public:
const ValueDecl* valueDecl() const {
if (Negated || CapExpr == nullptr)
return nullptr;
- if (auto *P = dyn_cast<til::Project>(CapExpr))
+ if (const auto *P = dyn_cast<til::Project>(CapExpr))
return P->clangDecl();
- if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
+ if (const auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
return P->clangDecl();
return nullptr;
}
@@ -309,12 +326,10 @@ public:
bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
};
-
-
// Translate clang::Expr to til::SExpr.
class SExprBuilder {
public:
- /// \brief Encapsulates the lexical context of a function call. The lexical
+ /// Encapsulates the lexical context of a function call. The lexical
/// context includes the arguments to the call, including the implicit object
/// argument. When an attribute containing a mutex expression is attached to
/// a method, the expression may refer to formal parameters of the method.
@@ -324,22 +339,29 @@ public:
/// should be evaluated; multiple calling contexts can be chained together
/// by the lock_returned attribute.
struct CallingContext {
- CallingContext *Prev; // The previous context; or 0 if none.
- const NamedDecl *AttrDecl; // The decl to which the attr is attached.
- const Expr *SelfArg; // Implicit object argument -- e.g. 'this'
- unsigned NumArgs; // Number of funArgs
- const Expr *const *FunArgs; // Function arguments
- bool SelfArrow; // is Self referred to with -> or .?
+ // The previous context; or 0 if none.
+ CallingContext *Prev;
+
+ // The decl to which the attr is attached.
+ const NamedDecl *AttrDecl;
+
+ // Implicit object argument -- e.g. 'this'
+ const Expr *SelfArg = nullptr;
+
+ // Number of funArgs
+ unsigned NumArgs = 0;
+
+ // Function arguments
+ const Expr *const *FunArgs = nullptr;
+
+ // is Self referred to with -> or .?
+ bool SelfArrow = false;
CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
- : Prev(P), AttrDecl(D), SelfArg(nullptr),
- NumArgs(0), FunArgs(nullptr), SelfArrow(false)
- {}
+ : Prev(P), AttrDecl(D) {}
};
- SExprBuilder(til::MemRegionRef A)
- : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr),
- CurrentBlockInfo(nullptr) {
+ SExprBuilder(til::MemRegionRef A) : Arena(A) {
// FIXME: we don't always have a self-variable.
SelfVar = new (Arena) til::Variable(nullptr);
SelfVar->setKind(til::Variable::VK_SFun);
@@ -368,6 +390,9 @@ public:
til::SCFG *getCFG() { return Scfg; }
private:
+ // We implement the CFGVisitor API
+ friend class CFGWalker;
+
til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE,
CallingContext *Ctx) ;
til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
@@ -397,31 +422,30 @@ private:
til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
// Map from statements in the clang CFG to SExprs in the til::SCFG.
- typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap;
+ using StatementMap = llvm::DenseMap<const Stmt *, til::SExpr *>;
// Map from clang local variables to indices in a LVarDefinitionMap.
- typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap;
+ using LVarIndexMap = llvm::DenseMap<const ValueDecl *, unsigned>;
// Map from local variable indices to SSA variables (or constants).
- typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair;
- typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap;
+ using NameVarPair = std::pair<const ValueDecl *, til::SExpr *>;
+ using LVarDefinitionMap = CopyOnWriteVector<NameVarPair>;
struct BlockInfo {
LVarDefinitionMap ExitMap;
- bool HasBackEdges;
- unsigned UnprocessedSuccessors; // Successors yet to be processed
- unsigned ProcessedPredecessors; // Predecessors already processed
+ bool HasBackEdges = false;
- BlockInfo()
- : HasBackEdges(false), UnprocessedSuccessors(0),
- ProcessedPredecessors(0) {}
+ // Successors yet to be processed
+ unsigned UnprocessedSuccessors = 0;
+
+ // Predecessors already processed
+ unsigned ProcessedPredecessors = 0;
+
+ BlockInfo() = default;
BlockInfo(BlockInfo &&) = default;
BlockInfo &operator=(BlockInfo &&) = default;
};
- // We implement the CFGVisitor API
- friend class CFGWalker;
-
void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);
void enterCFGBlock(const CFGBlock *B);
bool visitPredecessors() { return true; }
@@ -440,6 +464,7 @@ private:
void insertStmt(const Stmt *S, til::SExpr *E) {
SMap.insert(std::make_pair(S, E));
}
+
til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD);
til::SExpr *addStatement(til::SExpr *E, const Stmt *S,
@@ -459,30 +484,36 @@ private:
static const bool CapabilityExprMode = true;
til::MemRegionRef Arena;
- til::Variable *SelfVar; // Variable to use for 'this'. May be null.
- til::SCFG *Scfg;
- StatementMap SMap; // Map from Stmt to TIL Variables
- LVarIndexMap LVarIdxMap; // Indices of clang local vars.
- std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs.
- std::vector<BlockInfo> BBInfo; // Extra information per BB.
- // Indexed by clang BlockID.
+ // Variable to use for 'this'. May be null.
+ til::Variable *SelfVar = nullptr;
+
+ til::SCFG *Scfg = nullptr;
+
+ // Map from Stmt to TIL Variables
+ StatementMap SMap;
+
+ // Indices of clang local vars.
+ LVarIndexMap LVarIdxMap;
+
+ // Map from clang to til BBs.
+ std::vector<til::BasicBlock *> BlockMap;
+
+ // Extra information per BB. Indexed by clang BlockID.
+ std::vector<BlockInfo> BBInfo;
LVarDefinitionMap CurrentLVarMap;
- std::vector<til::Phi*> CurrentArguments;
- std::vector<til::SExpr*> CurrentInstructions;
- std::vector<til::Phi*> IncompleteArgs;
- til::BasicBlock *CurrentBB;
- BlockInfo *CurrentBlockInfo;
+ std::vector<til::Phi *> CurrentArguments;
+ std::vector<til::SExpr *> CurrentInstructions;
+ std::vector<til::Phi *> IncompleteArgs;
+ til::BasicBlock *CurrentBB = nullptr;
+ BlockInfo *CurrentBlockInfo = nullptr;
};
-
// Dump an SCFG to llvm::errs().
void printSCFG(CFGWalker &Walker);
+} // namespace threadSafety
+} // namespace clang
-} // end namespace threadSafety
-
-} // end namespace clang
-
-#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H
+#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
index bc78021343a4..2508af1af107 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
@@ -29,7 +29,7 @@ public:
};
Opcode kind() const { return Kind; }
- /// \brief Logical implication. Returns true if the LExpr implies RHS, i.e. if
+ /// Logical implication. Returns true if the LExpr implies RHS, i.e. if
/// the LExpr holds, then RHS must hold. For example, (A & B) implies A.
inline bool implies(const LExpr *RHS) const;
@@ -92,7 +92,7 @@ public:
static bool classof(const LExpr *E) { return E->kind() == LExpr::Not; }
};
-/// \brief Logical implication. Returns true if LHS implies RHS, i.e. if LHS
+/// Logical implication. Returns true if LHS implies RHS, i.e. if LHS
/// holds, then RHS must hold. For example, (A & B) implies A.
bool implies(const LExpr *LHS, const LExpr *RHS);
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 0a58d2a80250..810f2052b7a5 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===//
+//===- ThreadSafetyTIL.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -47,20 +47,33 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
-// All clang include dependencies for this file must be put in
-// ThreadSafetyUtil.h.
-#include "ThreadSafetyUtil.h"
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
-#include <stdint.h>
+#include <cstdint>
+#include <iterator>
+#include <string>
#include <utility>
-
namespace clang {
+
+class CallExpr;
+class Expr;
+class Stmt;
+
namespace threadSafety {
namespace til {
+class BasicBlock;
/// Enum for the different distinct classes of SExpr
enum TIL_Opcode {
@@ -100,11 +113,21 @@ enum TIL_BinaryOpcode : unsigned char {
/// Opcode for cast operations.
enum TIL_CastOpcode : unsigned char {
CAST_none = 0,
- CAST_extendNum, // extend precision of numeric type
- CAST_truncNum, // truncate precision of numeric type
- CAST_toFloat, // convert to floating point type
- CAST_toInt, // convert to integer type
- CAST_objToPtr // convert smart pointer to pointer (C++ only)
+
+ // Extend precision of numeric type
+ CAST_extendNum,
+
+ // Truncate precision of numeric type
+ CAST_truncNum,
+
+ // Convert to floating point type
+ CAST_toFloat,
+
+ // Convert to integer type
+ CAST_toInt,
+
+ // Convert smart pointer to pointer (C++ only)
+ CAST_objToPtr
};
const TIL_Opcode COP_Min = COP_Future;
@@ -122,7 +145,6 @@ StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
/// Return the name of a binary opcode.
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
-
/// ValueTypes are data types that can actually be held in registers.
/// All variables and expressions must have a value type.
/// Pointer types are further subdivided into the various heap-allocated
@@ -150,22 +172,22 @@ struct ValueType {
ST_128
};
+ ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
+ : Base(B), Size(Sz), Signed(S), VectSize(VS) {}
+
inline static SizeType getSizeType(unsigned nbytes);
template <class T>
inline static ValueType getValueType();
- ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
- : Base(B), Size(Sz), Signed(S), VectSize(VS)
- { }
+ BaseType Base;
+ SizeType Size;
+ bool Signed;
- BaseType Base;
- SizeType Size;
- bool Signed;
- unsigned char VectSize; // 0 for scalar, otherwise num elements in vector
+ // 0 for scalar, otherwise num elements in vector
+ unsigned char VectSize;
};
-
inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
switch (nbytes) {
case 1: return ST_8;
@@ -177,7 +199,6 @@ inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
}
}
-
template<>
inline ValueType ValueType::getValueType<void>() {
return ValueType(BT_Void, ST_0, false, 0);
@@ -253,13 +274,11 @@ inline ValueType ValueType::getValueType<void*>() {
return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0);
}
-
-class BasicBlock;
-
-
/// Base class for AST nodes in the typed intermediate language.
class SExpr {
public:
+ SExpr() = delete;
+
TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
// Subclasses of SExpr must define the following:
@@ -280,6 +299,9 @@ public:
return ::operator new(S, R);
}
+ /// SExpr objects must be created in an arena.
+ void *operator new(size_t) = delete;
+
/// SExpr objects cannot be deleted.
// This declaration is public to workaround a gcc bug that breaks building
// with REQUIRES_EH=1.
@@ -291,45 +313,33 @@ public:
/// Returns the block, if this is an instruction in a basic block,
/// otherwise returns null.
- BasicBlock* block() const { return Block; }
+ BasicBlock *block() const { return Block; }
/// Set the basic block and instruction ID for this expression.
void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
protected:
- SExpr(TIL_Opcode Op)
- : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
- SExpr(const SExpr &E)
- : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
- Block(nullptr) {}
+ SExpr(TIL_Opcode Op) : Opcode(Op) {}
+ SExpr(const SExpr &E) : Opcode(E.Opcode), Flags(E.Flags) {}
const unsigned char Opcode;
- unsigned char Reserved;
- unsigned short Flags;
- unsigned SExprID;
- BasicBlock* Block;
-
-private:
- SExpr() = delete;
-
- /// SExpr objects must be created in an arena.
- void *operator new(size_t) = delete;
+ unsigned char Reserved = 0;
+ unsigned short Flags = 0;
+ unsigned SExprID = 0;
+ BasicBlock *Block = nullptr;
};
-
// Contains various helper functions for SExprs.
namespace ThreadSafetyTIL {
- inline bool isTrivial(const SExpr *E) {
- unsigned Op = E->opcode();
- return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
- }
+
+inline bool isTrivial(const SExpr *E) {
+ unsigned Op = E->opcode();
+ return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
}
-// Nodes which declare variables
-class Function;
-class SFunction;
-class Let;
+} // namespace ThreadSafetyTIL
+// Nodes which declare variables
/// A named variable, e.g. "x".
///
@@ -345,28 +355,35 @@ class Let;
/// pointer to the original declaration.
class Variable : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
-
enum VariableKind {
- VK_Let, ///< Let-variable
- VK_Fun, ///< Function parameter
- VK_SFun ///< SFunction (self) parameter
+ /// Let-variable
+ VK_Let,
+
+ /// Function parameter
+ VK_Fun,
+
+ /// SFunction (self) parameter
+ VK_SFun
};
Variable(StringRef s, SExpr *D = nullptr)
- : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
+ : SExpr(COP_Variable), Name(s), Definition(D) {
Flags = VK_Let;
}
- Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
+
+ Variable(SExpr *D, const ValueDecl *Cvd = nullptr)
: SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
Definition(D), Cvdecl(Cvd) {
Flags = VK_Let;
}
+
Variable(const Variable &Vd, SExpr *D) // rewrite constructor
: SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
Flags = Vd.kind();
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
+
/// Return the kind of variable (let, function param, or self)
VariableKind kind() const { return static_cast<VariableKind>(Flags); }
@@ -374,7 +391,7 @@ public:
StringRef name() const { return Name; }
/// Return the clang declaration for this variable, if any.
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
/// Return the definition of the variable.
/// For let-vars, this is the setting expression.
@@ -385,7 +402,7 @@ public:
void setName(StringRef S) { Name = S; }
void setKind(VariableKind K) { Flags = K; }
void setDefinition(SExpr *E) { Definition = E; }
- void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
+ void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -399,42 +416,41 @@ public:
}
private:
- friend class Function;
- friend class SFunction;
friend class BasicBlock;
+ friend class Function;
friend class Let;
+ friend class SFunction;
- StringRef Name; // The name of the variable.
- SExpr* Definition; // The TIL type or definition
- const clang::ValueDecl *Cvdecl; // The clang declaration for this variable.
-};
+ // The name of the variable.
+ StringRef Name;
+
+ // The TIL type or definition.
+ SExpr *Definition;
+ // The clang declaration for this variable.
+ const ValueDecl *Cvdecl = nullptr;
+};
/// Placeholder for an expression that has not yet been created.
/// Used to implement lazy copy and rewriting strategies.
class Future : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
-
enum FutureStatus {
FS_pending,
FS_evaluating,
FS_done
};
- Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
-
-private:
+ Future() : SExpr(COP_Future) {}
virtual ~Future() = delete;
-public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
+
// A lazy rewriting strategy should subclass Future and override this method.
virtual SExpr *compute() { return nullptr; }
// Return the result of this future if it exists, otherwise return null.
- SExpr *maybeGetResult() const {
- return Result;
- }
+ SExpr *maybeGetResult() const { return Result; }
// Return the result of this future; forcing it if necessary.
SExpr *result() {
@@ -464,19 +480,18 @@ public:
private:
SExpr* force();
- FutureStatus Status;
- SExpr *Result;
+ FutureStatus Status = FS_pending;
+ SExpr *Result = nullptr;
};
-
/// Placeholder for expressions that cannot be represented in the TIL.
class Undefined : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
-
- Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
+ Undefined(const Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
+
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
return Vs.reduceUndefined(*this);
@@ -488,17 +503,16 @@ public:
}
private:
- const clang::Stmt *Cstmt;
+ const Stmt *Cstmt;
};
-
/// Placeholder for a wildcard that matches any other expression.
class Wildcard : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
-
Wildcard() : SExpr(COP_Wildcard) {}
- Wildcard(const Wildcard &W) : SExpr(W) {}
+ Wildcard(const Wildcard &) = default;
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
return Vs.reduceWildcard(*this);
@@ -510,22 +524,20 @@ public:
}
};
-
template <class T> class LiteralT;
// Base class for literal values.
class Literal : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
+ Literal(const Expr *C)
+ : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C) {}
+ Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT) {}
+ Literal(const Literal &) = default;
- Literal(const clang::Expr *C)
- : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C)
- { }
- Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {}
- Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
// The clang expression for this literal.
- const clang::Expr *clangExpr() const { return Cexpr; }
+ const Expr *clangExpr() const { return Cexpr; }
ValueType valueType() const { return ValType; }
@@ -546,26 +558,23 @@ public:
private:
const ValueType ValType;
- const clang::Expr *Cexpr;
+ const Expr *Cexpr = nullptr;
};
-
// Derived class for literal values, which stores the actual value.
template<class T>
class LiteralT : public Literal {
public:
- LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { }
- LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { }
+ LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) {}
+ LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) {}
- T value() const { return Val;}
+ T value() const { return Val;}
T& value() { return Val; }
private:
T Val;
};
-
-
template <class V>
typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
if (Cexpr)
@@ -622,18 +631,17 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
return Vs.reduceLiteral(*this);
}
-
/// A Literal pointer to an object allocated in memory.
/// At compile time, pointer literals are represented by symbolic names.
class LiteralPtr : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
+ LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
+ LiteralPtr(const LiteralPtr &) = default;
- LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
- LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
// The clang declaration for the value that this pointer points to.
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -646,26 +654,26 @@ public:
}
private:
- const clang::ValueDecl *Cvdecl;
+ const ValueDecl *Cvdecl;
};
-
/// A function -- a.k.a. lambda abstraction.
/// Functions with multiple arguments are created by currying,
/// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
class Function : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
-
Function(Variable *Vd, SExpr *Bd)
: SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Fun);
}
+
Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
: SExpr(F), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Fun);
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
+
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
@@ -700,20 +708,18 @@ private:
SExpr* Body;
};
-
/// A self-applicable function.
/// A self-applicable function can be applied to itself. It's useful for
/// implementing objects and late binding.
class SFunction : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
-
SFunction(Variable *Vd, SExpr *B)
: SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
assert(Vd->Definition == nullptr);
Vd->setKind(Variable::VK_SFun);
Vd->Definition = this;
}
+
SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
: SExpr(F), VarDecl(Vd), Body(B) {
assert(Vd->Definition == nullptr);
@@ -721,6 +727,8 @@ public:
Vd->Definition = this;
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
+
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
@@ -752,16 +760,15 @@ private:
SExpr* Body;
};
-
/// A block of code -- e.g. the body of a function.
class Code : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
-
Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
: SExpr(C), ReturnType(T), Body(B) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
+
SExpr *returnType() { return ReturnType; }
const SExpr *returnType() const { return ReturnType; }
@@ -788,16 +795,15 @@ private:
SExpr* Body;
};
-
/// A typed, writable location in memory
class Field : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
-
Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {}
Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
: SExpr(C), Range(R), Body(B) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
+
SExpr *range() { return Range; }
const SExpr *range() const { return Range; }
@@ -824,7 +830,6 @@ private:
SExpr* Body;
};
-
/// Apply an argument to a function.
/// Note that this does not actually call the function. Functions are curried,
/// so this returns a closure in which the first parameter has been applied.
@@ -832,12 +837,11 @@ private:
/// function.
class Apply : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
-
Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor
- : SExpr(A), Fun(F), Arg(Ar)
- {}
+ : SExpr(A), Fun(F), Arg(Ar) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
SExpr *fun() { return Fun; }
const SExpr *fun() const { return Fun; }
@@ -865,16 +869,15 @@ private:
SExpr* Arg;
};
-
/// Apply a self-argument to a self-applicable function.
class SApply : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
-
SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
: SExpr(A), Sfun(Sf), Arg(Ar) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
+
SExpr *sfun() { return Sfun; }
const SExpr *sfun() const { return Sfun; }
@@ -904,23 +907,23 @@ private:
SExpr* Arg;
};
-
/// Project a named slot from a C++ struct or class.
class Project : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
-
- Project(SExpr *R, const clang::ValueDecl *Cvd)
+ Project(SExpr *R, const ValueDecl *Cvd)
: SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
assert(Cvd && "ValueDecl must not be null");
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
+
SExpr *record() { return Rec; }
const SExpr *record() const { return Rec; }
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
bool isArrow() const { return (Flags & 0x01) != 0; }
+
void setArrow(bool b) {
if (b) Flags |= 0x01;
else Flags &= 0xFFFE;
@@ -954,23 +957,22 @@ public:
private:
SExpr* Rec;
mutable llvm::Optional<std::string> SlotName;
- const clang::ValueDecl *Cvdecl;
+ const ValueDecl *Cvdecl;
};
-
/// Call a function (after all arguments have been applied).
class Call : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
-
- Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
+ Call(SExpr *T, const CallExpr *Ce = nullptr)
: SExpr(COP_Call), Target(T), Cexpr(Ce) {}
Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
+
SExpr *target() { return Target; }
const SExpr *target() const { return Target; }
- const clang::CallExpr *clangCallExpr() const { return Cexpr; }
+ const CallExpr *clangCallExpr() const { return Cexpr; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -985,15 +987,12 @@ public:
private:
SExpr* Target;
- const clang::CallExpr *Cexpr;
+ const CallExpr *Cexpr;
};
-
/// Allocate memory for a new value on the heap or stack.
class Alloc : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
-
enum AllocKind {
AK_Stack,
AK_Heap
@@ -1002,6 +1001,8 @@ public:
Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; }
Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
+
AllocKind kind() const { return static_cast<AllocKind>(Flags); }
SExpr *dataType() { return Dtype; }
@@ -1025,15 +1026,14 @@ private:
SExpr* Dtype;
};
-
/// Load a value from memory.
class Load : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
-
Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
+
SExpr *pointer() { return Ptr; }
const SExpr *pointer() const { return Ptr; }
@@ -1052,16 +1052,15 @@ private:
SExpr* Ptr;
};
-
/// Store a value to memory.
/// The destination is a pointer to a field, the source is the value to store.
class Store : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
-
Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
+
SExpr *destination() { return Dest; } // Address to store to
const SExpr *destination() const { return Dest; }
@@ -1088,16 +1087,15 @@ private:
SExpr* Source;
};
-
/// If p is a reference to an array, then p[i] is a reference to the i'th
/// element of the array.
class ArrayIndex : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
-
ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {}
ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
- : SExpr(E), Array(A), Index(N) {}
+ : SExpr(E), Array(A), Index(N) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
SExpr *array() { return Array; }
const SExpr *array() const { return Array; }
@@ -1125,17 +1123,16 @@ private:
SExpr* Index;
};
-
/// Pointer arithmetic, restricted to arrays only.
/// If p is a reference to an array, then p + n, where n is an integer, is
/// a reference to a subarray.
class ArrayAdd : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
-
ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
- : SExpr(E), Array(A), Index(N) {}
+ : SExpr(E), Array(A), Index(N) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
SExpr *array() { return Array; }
const SExpr *array() const { return Array; }
@@ -1163,18 +1160,18 @@ private:
SExpr* Index;
};
-
/// Simple arithmetic unary operations, e.g. negate and not.
/// These operations have no side-effects.
class UnaryOp : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
-
UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
Flags = Op;
}
+
UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
+
TIL_UnaryOpcode unaryOpcode() const {
return static_cast<TIL_UnaryOpcode>(Flags);
}
@@ -1201,22 +1198,22 @@ private:
SExpr* Expr0;
};
-
/// Simple arithmetic binary operations, e.g. +, -, etc.
/// These operations have no side effects.
class BinaryOp : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
-
BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
: SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
Flags = Op;
}
+
BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
: SExpr(B), Expr0(E0), Expr1(E1) {
Flags = B.Flags;
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
+
TIL_BinaryOpcode binaryOpcode() const {
return static_cast<TIL_BinaryOpcode>(Flags);
}
@@ -1251,17 +1248,16 @@ private:
SExpr* Expr1;
};
-
/// Cast expressions.
/// Cast expressions are essentially unary operations, but we treat them
/// as a distinct AST node because they only change the type of the result.
class Cast : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
-
Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
+
TIL_CastOpcode castOpcode() const {
return static_cast<TIL_CastOpcode>(Flags);
}
@@ -1288,16 +1284,14 @@ private:
SExpr* Expr0;
};
-
class SCFG;
-
/// Phi Node, for code in SSA form.
/// Each Phi node has an array of possible values that it can take,
/// depending on where control flow comes from.
class Phi : public SExpr {
public:
- typedef SimpleArray<SExpr *> ValArray;
+ using ValArray = SimpleArray<SExpr *>;
// In minimal SSA form, all Phi nodes are MultiVal.
// During conversion to SSA, incomplete Phi nodes may be introduced, which
@@ -1308,14 +1302,11 @@ public:
PH_Incomplete // Phi node is incomplete
};
- static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
+ Phi() : SExpr(COP_Phi) {}
+ Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals) {}
+ Phi(const Phi &P, ValArray &&Vs) : SExpr(P), Values(std::move(Vs)) {}
- Phi()
- : SExpr(COP_Phi), Cvdecl(nullptr) {}
- Phi(MemRegionRef A, unsigned Nvals)
- : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr) {}
- Phi(const Phi &P, ValArray &&Vs)
- : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
const ValArray &values() const { return Values; }
ValArray &values() { return Values; }
@@ -1324,19 +1315,18 @@ public:
void setStatus(Status s) { Flags = s; }
/// Return the clang declaration of the variable for this Phi node, if any.
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
/// Set the clang variable associated with this Phi node.
- void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
+ void setClangDecl(const ValueDecl *Cvd) { Cvdecl = Cvd; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
typename V::template Container<typename V::R_SExpr>
Nvs(Vs, Values.size());
- for (auto *Val : Values) {
+ for (const auto *Val : Values)
Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
- }
return Vs.reducePhi(*this, Nvs);
}
@@ -1348,31 +1338,28 @@ public:
private:
ValArray Values;
- const clang::ValueDecl* Cvdecl;
+ const ValueDecl* Cvdecl = nullptr;
};
-
/// Base class for basic block terminators: Branch, Goto, and Return.
class Terminator : public SExpr {
+protected:
+ Terminator(TIL_Opcode Op) : SExpr(Op) {}
+ Terminator(const SExpr &E) : SExpr(E) {}
+
public:
static bool classof(const SExpr *E) {
return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
}
-protected:
- Terminator(TIL_Opcode Op) : SExpr(Op) {}
- Terminator(const SExpr &E) : SExpr(E) {}
-
-public:
/// Return the list of basic blocks that this terminator can branch to.
- ArrayRef<BasicBlock*> successors();
+ ArrayRef<BasicBlock *> successors();
- ArrayRef<BasicBlock*> successors() const {
+ ArrayRef<BasicBlock *> successors() const {
return const_cast<Terminator*>(this)->successors();
}
};
-
/// Jump to another basic block.
/// A goto instruction is essentially a tail-recursive call into another
/// block. In addition to the block pointer, it specifies an index into the
@@ -1380,13 +1367,13 @@ public:
/// of the call.
class Goto : public Terminator {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
-
Goto(BasicBlock *B, unsigned I)
: Terminator(COP_Goto), TargetBlock(B), Index(I) {}
Goto(const Goto &G, BasicBlock *B, unsigned I)
: Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
+
const BasicBlock *targetBlock() const { return TargetBlock; }
BasicBlock *targetBlock() { return TargetBlock; }
@@ -1394,9 +1381,7 @@ public:
unsigned index() const { return Index; }
/// Return the list of basic blocks that this terminator can branch to.
- ArrayRef<BasicBlock*> successors() {
- return TargetBlock;
- }
+ ArrayRef<BasicBlock *> successors() { return TargetBlock; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1415,25 +1400,25 @@ private:
unsigned Index;
};
-
/// A conditional branch to two other blocks.
/// Note that unlike Goto, Branch does not have an index. The target blocks
/// must be child-blocks, and cannot have Phi nodes.
class Branch : public Terminator {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
-
Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
: Terminator(COP_Branch), Condition(C) {
Branches[0] = T;
Branches[1] = E;
}
+
Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
: Terminator(Br), Condition(C) {
Branches[0] = T;
Branches[1] = E;
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
+
const SExpr *condition() const { return Condition; }
SExpr *condition() { return Condition; }
@@ -1463,24 +1448,21 @@ public:
}
private:
- SExpr* Condition;
+ SExpr *Condition;
BasicBlock *Branches[2];
};
-
/// Return from the enclosing function, passing the return value to the caller.
/// Only the exit block should end with a return statement.
class Return : public Terminator {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
-
Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
+
/// Return an empty list.
- ArrayRef<BasicBlock*> successors() {
- return None;
- }
+ ArrayRef<BasicBlock *> successors() { return None; }
SExpr *returnValue() { return Retval; }
const SExpr *returnValue() const { return Retval; }
@@ -1500,7 +1482,6 @@ private:
SExpr* Retval;
};
-
inline ArrayRef<BasicBlock*> Terminator::successors() {
switch (opcode()) {
case COP_Goto: return cast<Goto>(this)->successors();
@@ -1511,7 +1492,6 @@ inline ArrayRef<BasicBlock*> Terminator::successors() {
}
}
-
/// A basic block is part of an SCFG. It can be treated as a function in
/// continuation passing style. A block consists of a sequence of phi nodes,
/// which are "arguments" to the function, followed by a sequence of
@@ -1519,15 +1499,23 @@ inline ArrayRef<BasicBlock*> Terminator::successors() {
/// another basic block in the same SCFG.
class BasicBlock : public SExpr {
public:
- typedef SimpleArray<SExpr*> InstrArray;
- typedef SimpleArray<BasicBlock*> BlockArray;
+ using InstrArray = SimpleArray<SExpr *>;
+ using BlockArray = SimpleArray<BasicBlock *>;
// TopologyNodes are used to overlay tree structures on top of the CFG,
// such as dominator and postdominator trees. Each block is assigned an
// ID in the tree according to a depth-first search. Tree traversals are
// always up, towards the parents.
struct TopologyNode {
- TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
+ int NodeID = 0;
+
+ // Includes this node, so must be > 1.
+ int SizeOfSubTree = 0;
+
+ // Pointer to parent.
+ BasicBlock *Parent = nullptr;
+
+ TopologyNode() = default;
bool isParentOf(const TopologyNode& OtherNode) {
return OtherNode.NodeID > NodeID &&
@@ -1538,22 +1526,17 @@ public:
return OtherNode.NodeID >= NodeID &&
OtherNode.NodeID < NodeID + SizeOfSubTree;
}
-
- int NodeID;
- int SizeOfSubTree; // Includes this node, so must be > 1.
- BasicBlock *Parent; // Pointer to parent.
};
- static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
-
explicit BasicBlock(MemRegionRef A)
- : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
- Visited(0), TermInstr(nullptr) {}
+ : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false) {}
BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
Terminator *T)
- : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
+ : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false),
Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
+
/// Returns the block ID. Every block has a unique ID in the CFG.
int blockID() const { return BlockID; }
@@ -1600,11 +1583,13 @@ public:
Args.reserveCheck(1, Arena);
Args.push_back(V);
}
+
/// Add a new instruction.
void addInstruction(SExpr *V) {
Instrs.reserveCheck(1, Arena);
Instrs.push_back(V);
}
+
// Add a new predecessor, and return the phi-node index for it.
// Will add an argument to all phi-nodes, initialized to nullptr.
unsigned addPredecessor(BasicBlock *Pred);
@@ -1632,11 +1617,11 @@ public:
// Entering the basic block should do any scope initialization.
Vs.enterBasicBlock(*this);
- for (auto *E : Args) {
+ for (const auto *E : Args) {
auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
Nas.push_back(Ne);
}
- for (auto *E : Instrs) {
+ for (const auto *E : Instrs) {
auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
Nis.push_back(Ne);
}
@@ -1657,43 +1642,56 @@ public:
private:
friend class SCFG;
- int renumberInstrs(int id); // assign unique ids to all instructions
- int topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
- int topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
+ // assign unique ids to all instructions
+ int renumberInstrs(int id);
+
+ int topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID);
+ int topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks, int ID);
void computeDominator();
void computePostDominator();
-private:
- MemRegionRef Arena; // The arena used to allocate this block.
- SCFG *CFGPtr; // The CFG that contains this block.
- int BlockID : 31; // unique id for this BB in the containing CFG.
- // IDs are in topological order.
- bool Visited : 1; // Bit to determine if a block has been visited
- // during a traversal.
- BlockArray Predecessors; // Predecessor blocks in the CFG.
- InstrArray Args; // Phi nodes. One argument per predecessor.
- InstrArray Instrs; // Instructions.
- Terminator* TermInstr; // Terminating instruction
-
- TopologyNode DominatorNode; // The dominator tree
- TopologyNode PostDominatorNode; // The post-dominator tree
-};
+ // The arena used to allocate this block.
+ MemRegionRef Arena;
+
+ // The CFG that contains this block.
+ SCFG *CFGPtr = nullptr;
+
+ // Unique ID for this BB in the containing CFG. IDs are in topological order.
+ int BlockID : 31;
+ // Bit to determine if a block has been visited during a traversal.
+ bool Visited : 1;
+
+ // Predecessor blocks in the CFG.
+ BlockArray Predecessors;
+
+ // Phi nodes. One argument per predecessor.
+ InstrArray Args;
+
+ // Instructions.
+ InstrArray Instrs;
+
+ // Terminating instruction.
+ Terminator *TermInstr = nullptr;
+
+ // The dominator tree.
+ TopologyNode DominatorNode;
+
+ // The post-dominator tree.
+ TopologyNode PostDominatorNode;
+};
/// An SCFG is a control-flow graph. It consists of a set of basic blocks,
/// each of which terminates in a branch to another basic block. There is one
/// entry point, and one exit point.
class SCFG : public SExpr {
public:
- typedef SimpleArray<BasicBlock *> BlockArray;
- typedef BlockArray::iterator iterator;
- typedef BlockArray::const_iterator const_iterator;
-
- static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
+ using BlockArray = SimpleArray<BasicBlock *>;
+ using iterator = BlockArray::iterator;
+ using const_iterator = BlockArray::const_iterator;
SCFG(MemRegionRef A, unsigned Nblocks)
- : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
- Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
Entry = new (A) BasicBlock(A);
Exit = new (A) BasicBlock(A);
auto *V = new (A) Phi();
@@ -1702,12 +1700,14 @@ public:
add(Entry);
add(Exit);
}
+
SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
- : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
- Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)) {
// TODO: set entry and exit!
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
+
/// Return true if this CFG is valid.
bool valid() const { return Entry && Exit && Blocks.size() > 0; }
@@ -1756,7 +1756,7 @@ public:
Vs.enterCFG(*this);
typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
- for (auto *B : Blocks) {
+ for (const auto *B : Blocks) {
Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
}
Vs.exitCFG(*this);
@@ -1770,27 +1770,25 @@ public:
}
private:
- void renumberInstrs(); // assign unique ids to all instructions
+ // assign unique ids to all instructions
+ void renumberInstrs();
-private:
MemRegionRef Arena;
- BlockArray Blocks;
- BasicBlock *Entry;
- BasicBlock *Exit;
- unsigned NumInstructions;
- bool Normal;
+ BlockArray Blocks;
+ BasicBlock *Entry = nullptr;
+ BasicBlock *Exit = nullptr;
+ unsigned NumInstructions = 0;
+ bool Normal = false;
};
-
-
/// An identifier, e.g. 'foo' or 'x'.
/// This is a pseduo-term; it will be lowered to a variable or projection.
class Identifier : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
+ Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) {}
+ Identifier(const Identifier &) = default;
- Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { }
- Identifier(const Identifier& I) : SExpr(I), Name(I.Name) { }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
StringRef name() const { return Name; }
@@ -1808,19 +1806,16 @@ private:
StringRef Name;
};
-
/// An if-then-else expression.
/// This is a pseduo-term; it will be lowered to a branch in a CFG.
class IfThenElse : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
-
IfThenElse(SExpr *C, SExpr *T, SExpr *E)
- : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E)
- { }
+ : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) {}
IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
- : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
- { }
+ : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
SExpr *condition() { return Condition; } // Address to store to
const SExpr *condition() const { return Condition; }
@@ -1856,20 +1851,20 @@ private:
SExpr* ElseExpr;
};
-
/// A let-expression, e.g. let x=t; u.
/// This is a pseduo-term; it will be lowered to instructions in a CFG.
class Let : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
-
Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Let);
}
+
Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Let);
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
+
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
@@ -1904,15 +1899,13 @@ private:
SExpr* Body;
};
-
-
const SExpr *getCanonicalVal(const SExpr *E);
SExpr* simplifyToCanonicalVal(SExpr *E);
void simplifyIncompleteArg(til::Phi *Ph);
+} // namespace til
+} // namespace threadSafety
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 705fe910d092..49031010a75b 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===//
+//===- ThreadSafetyTraverse.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,13 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
-#include "ThreadSafetyTIL.h"
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <cstdint>
#include <ostream>
namespace clang {
@@ -26,7 +32,7 @@ namespace til {
// Defines an interface used to traverse SExprs. Traversals have been made as
// generic as possible, and are intended to handle any kind of pass over the
-// AST, e.g. visiters, copying, non-destructive rewriting, destructive
+// AST, e.g. visitors, copying, non-destructive rewriting, destructive
// (in-place) rewriting, hashing, typing, etc.
//
// Traversals implement the functional notion of a "fold" operation on SExprs.
@@ -92,21 +98,27 @@ public:
#undef TIL_OPCODE_DEF
};
-
// Base class for simple reducers that don't much care about the context.
class SimpleReducerBase {
public:
enum TraversalKind {
- TRV_Normal, // ordinary subexpressions
- TRV_Decl, // declarations (e.g. function bodies)
- TRV_Lazy, // expressions that require lazy evaluation
- TRV_Type // type expressions
+ // Ordinary subexpressions.
+ TRV_Normal,
+
+ // Declarations (e.g. function bodies).
+ TRV_Decl,
+
+ // Expressions that require lazy evaluation.
+ TRV_Lazy,
+
+ // Type expressions.
+ TRV_Type
};
// R_Ctx defines a "context" for the traversal, which encodes information
// about where a term appears. This can be used to encoding the
// "current continuation" for CPS transforms, or other information.
- typedef TraversalKind R_Ctx;
+ using R_Ctx = TraversalKind;
// Create context for an ordinary subexpression.
R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
@@ -123,14 +135,13 @@ public:
R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
};
-
// Base class for traversals that rewrite an SExpr to another SExpr.
class CopyReducerBase : public SimpleReducerBase {
public:
// R_SExpr is the result type for a traversal.
// A copy or non-destructive rewrite returns a newly allocated term.
- typedef SExpr *R_SExpr;
- typedef BasicBlock *R_BasicBlock;
+ using R_SExpr = SExpr *;
+ using R_BasicBlock = BasicBlock *;
// Container is a minimal interface used to store results when traversing
// SExprs of variable arity, such as Phi, Goto, and SCFG.
@@ -151,32 +162,31 @@ protected:
MemRegionRef Arena;
};
-
// Base class for visit traversals.
class VisitReducerBase : public SimpleReducerBase {
public:
// A visitor returns a bool, representing success or failure.
- typedef bool R_SExpr;
- typedef bool R_BasicBlock;
+ using R_SExpr = bool;
+ using R_BasicBlock = bool;
// A visitor "container" is a single bool, which accumulates success.
template <class T> class Container {
public:
- Container(VisitReducerBase &S, unsigned N) : Success(true) {}
- void push_back(bool E) { Success = Success && E; }
+ bool Success = true;
- bool Success;
+ Container(VisitReducerBase &S, unsigned N) {}
+
+ void push_back(bool E) { Success = Success && E; }
};
};
-
// Implements a traversal that visits each subexpression, and returns either
// true or false.
template <class Self>
class VisitReducer : public Traversal<Self, VisitReducerBase>,
public VisitReducerBase {
public:
- VisitReducer() {}
+ VisitReducer() = default;
public:
R_SExpr reduceNull() { return true; }
@@ -191,54 +201,70 @@ public:
R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
return Nvd && E0;
}
+
R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
return Nvd && E0;
}
+
R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
+
R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
+
R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
return Bbs.Success;
}
+
R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
Container<R_SExpr> &Is, R_SExpr T) {
return (As.Success && Is.Success && T);
}
+
R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
return As.Success;
}
+
R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
return true;
}
+
R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
return C;
}
+
R_SExpr reduceReturn(Return &O, R_SExpr E) {
return E;
}
@@ -246,9 +272,11 @@ public:
R_SExpr reduceIdentifier(Identifier &Orig) {
return true;
}
+
R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
return C && T && E;
}
+
R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
return Nvd && B;
}
@@ -260,7 +288,7 @@ public:
void enterBasicBlock(BasicBlock &BB) {}
void exitBasicBlock(BasicBlock &BB) {}
- Variable *reduceVariableRef (Variable *Ovd) { return Ovd; }
+ Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
public:
@@ -278,7 +306,6 @@ private:
bool Success;
};
-
// Basic class for comparison operations over expressions.
template <typename Self>
class Comparator {
@@ -298,19 +325,18 @@ public:
}
};
-
class EqualsComparator : public Comparator<EqualsComparator> {
public:
// Result type for the comparison, e.g. bool for simple equality,
// or int for lexigraphic comparison (-1, 0, 1). Must have one value which
// denotes "true".
- typedef bool CType;
+ using CType = bool;
CType trueResult() { return true; }
bool notTrue(CType ct) { return !ct; }
- bool compareIntegers(unsigned i, unsigned j) { return i == j; }
- bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
bool comparePointers(const void* P, const void* Q) { return P == Q; }
bool compare(const SExpr *E1, const SExpr* E2) {
@@ -320,10 +346,10 @@ public:
}
// TODO -- handle alpha-renaming of variables
- void enterScope(const Variable* V1, const Variable* V2) { }
- void leaveScope() { }
+ void enterScope(const Variable *V1, const Variable *V2) {}
+ void leaveScope() {}
- bool compareVariableRefs(const Variable* V1, const Variable* V2) {
+ bool compareVariableRefs(const Variable *V1, const Variable *V2) {
return V1 == V2;
}
@@ -333,23 +359,21 @@ public:
}
};
-
-
class MatchComparator : public Comparator<MatchComparator> {
public:
// Result type for the comparison, e.g. bool for simple equality,
// or int for lexigraphic comparison (-1, 0, 1). Must have one value which
// denotes "true".
- typedef bool CType;
+ using CType = bool;
CType trueResult() { return true; }
bool notTrue(CType ct) { return !ct; }
- bool compareIntegers(unsigned i, unsigned j) { return i == j; }
- bool compareStrings (StringRef s, StringRef r) { return s == r; }
- bool comparePointers(const void* P, const void* Q) { return P == Q; }
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool comparePointers(const void *P, const void *Q) { return P == Q; }
- bool compare(const SExpr *E1, const SExpr* E2) {
+ bool compare(const SExpr *E1, const SExpr *E2) {
// Wildcards match anything.
if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
return true;
@@ -360,8 +384,8 @@ public:
}
// TODO -- handle alpha-renaming of variables
- void enterScope(const Variable* V1, const Variable* V2) { }
- void leaveScope() { }
+ void enterScope(const Variable* V1, const Variable* V2) {}
+ void leaveScope() {}
bool compareVariableRefs(const Variable* V1, const Variable* V2) {
return V1 == V2;
@@ -373,8 +397,6 @@ public:
}
};
-
-
// inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
// return SS.write(R.data(), R.size());
// }
@@ -383,14 +405,18 @@ public:
template <typename Self, typename StreamType>
class PrettyPrinter {
private:
- bool Verbose; // Print out additional information
- bool Cleanup; // Omit redundant decls.
- bool CStyle; // Print exprs in C-like syntax.
+ // Print out additional information.
+ bool Verbose;
+
+ // Omit redundant decls.
+ bool Cleanup;
+
+ // Print exprs in C-like syntax.
+ bool CStyle;
public:
PrettyPrinter(bool V = false, bool C = true, bool CS = true)
- : Verbose(V), Cleanup(C), CStyle(CS)
- {}
+ : Verbose(V), Cleanup(C), CStyle(CS) {}
static void print(const SExpr *E, StreamType &SS) {
Self printer;
@@ -470,7 +496,6 @@ protected:
}
}
-
void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
if (!E) {
self()->printNull(SS);
@@ -531,18 +556,16 @@ protected:
else {
ValueType VT = E->valueType();
switch (VT.Base) {
- case ValueType::BT_Void: {
+ case ValueType::BT_Void:
SS << "void";
return;
- }
- case ValueType::BT_Bool: {
+ case ValueType::BT_Bool:
if (E->as<bool>().value())
SS << "true";
else
SS << "false";
return;
- }
- case ValueType::BT_Int: {
+ case ValueType::BT_Int:
switch (VT.Size) {
case ValueType::ST_8:
if (VT.Signed)
@@ -572,8 +595,7 @@ protected:
break;
}
break;
- }
- case ValueType::BT_Float: {
+ case ValueType::BT_Float:
switch (VT.Size) {
case ValueType::ST_32:
printLiteralT(&E->as<float>(), SS);
@@ -585,22 +607,18 @@ protected:
break;
}
break;
- }
- case ValueType::BT_String: {
+ case ValueType::BT_String:
SS << "\"";
printLiteralT(&E->as<StringRef>(), SS);
SS << "\"";
return;
- }
- case ValueType::BT_Pointer: {
+ case ValueType::BT_Pointer:
SS << "#ptr";
return;
- }
- case ValueType::BT_ValueRef: {
+ case ValueType::BT_ValueRef:
SS << "#vref";
return;
}
- }
}
SS << "#lit";
}
@@ -688,8 +706,8 @@ protected:
void printProject(const Project *E, StreamType &SS) {
if (CStyle) {
// Omit the this->
- if (const SApply *SAP = dyn_cast<SApply>(E->record())) {
- if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) {
+ if (const auto *SAP = dyn_cast<SApply>(E->record())) {
+ if (const auto *V = dyn_cast<Variable>(SAP->sfun())) {
if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
SS << E->slotName();
return;
@@ -704,12 +722,10 @@ protected:
}
}
self()->printSExpr(E->record(), SS, Prec_Postfix);
- if (CStyle && E->isArrow()) {
+ if (CStyle && E->isArrow())
SS << "->";
- }
- else {
+ else
SS << ".";
- }
SS << E->slotName();
}
@@ -780,18 +796,16 @@ protected:
void printSCFG(const SCFG *E, StreamType &SS) {
SS << "CFG {\n";
- for (auto BBI : *E) {
+ for (const auto *BBI : *E)
printBasicBlock(BBI, SS);
- }
SS << "}";
newline(SS);
}
-
void printBBInstr(const SExpr *E, StreamType &SS) {
bool Sub = false;
if (E->opcode() == COP_Variable) {
- auto *V = cast<Variable>(E);
+ const auto *V = cast<Variable>(E);
SS << "let " << V->name() << V->id() << " = ";
E = V->definition();
Sub = true;
@@ -810,10 +824,10 @@ protected:
SS << " BB_" << E->parent()->blockID();
newline(SS);
- for (auto *A : E->arguments())
+ for (const auto *A : E->arguments())
printBBInstr(A, SS);
- for (auto *I : E->instructions())
+ for (const auto *I : E->instructions())
printBBInstr(I, SS);
const SExpr *T = E->terminator();
@@ -831,7 +845,7 @@ protected:
self()->printSExpr(E->values()[0], SS, Prec_MAX);
else {
unsigned i = 0;
- for (auto V : E->values()) {
+ for (const auto *V : E->values()) {
if (i++ > 0)
SS << ", ";
self()->printSExpr(V, SS, Prec_MAX);
@@ -890,13 +904,10 @@ protected:
}
};
+class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> {};
-class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { };
-
-
-
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace til
+} // namespace threadSafety
+} // namespace clang
-#endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index cb80ce5da8d2..16583939d542 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyUtil.h --------------------------------------*- C++ --*-===//
+//===- ThreadSafetyUtil.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,18 +14,23 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
-#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/AlignOf.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
+#include <cstring>
+#include <iterator>
#include <ostream>
-#include <utility>
+#include <string>
#include <vector>
namespace clang {
+
+class Expr;
+
namespace threadSafety {
namespace til {
@@ -41,7 +46,7 @@ private:
};
public:
- MemRegionRef() : Allocator(nullptr) {}
+ MemRegionRef() = default;
MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
void *allocate(size_t Sz) {
@@ -55,12 +60,13 @@ public:
}
private:
- llvm::BumpPtrAllocator *Allocator;
+ llvm::BumpPtrAllocator *Allocator = nullptr;
};
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace til
+} // namespace threadSafety
+
+} // namespace clang
inline void *operator new(size_t Sz,
clang::threadSafety::til::MemRegionRef &R) {
@@ -70,10 +76,7 @@ inline void *operator new(size_t Sz,
namespace clang {
namespace threadSafety {
-std::string getSourceLiteralString(const clang::Expr *CE);
-
-using llvm::StringRef;
-using clang::SourceLocation;
+std::string getSourceLiteralString(const Expr *CE);
namespace til {
@@ -81,11 +84,13 @@ namespace til {
// suitable for use with bump pointer allocation.
template <class T> class SimpleArray {
public:
- SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
+ SimpleArray() = default;
SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
: Data(Dat), Size(Sz), Capacity(Cp) {}
SimpleArray(MemRegionRef A, size_t Cp)
- : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
+ : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Capacity(Cp) {}
+ SimpleArray(const SimpleArray<T> &A) = delete;
+
SimpleArray(SimpleArray<T> &&A)
: Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
A.Data = nullptr;
@@ -123,10 +128,10 @@ public:
reserve(u_max(Size + N, Capacity * 2), A);
}
- typedef T *iterator;
- typedef const T *const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ using iterator = T *;
+ using const_iterator = const T *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
size_t size() const { return Size; }
size_t capacity() const { return Capacity; }
@@ -135,27 +140,30 @@ public:
assert(i < Size && "Array index out of bounds.");
return Data[i];
}
+
const T &operator[](unsigned i) const {
assert(i < Size && "Array index out of bounds.");
return Data[i];
}
+
T &back() {
assert(Size && "No elements in the array.");
return Data[Size - 1];
}
+
const T &back() const {
assert(Size && "No elements in the array.");
return Data[Size - 1];
}
iterator begin() { return Data; }
- iterator end() { return Data + Size; }
+ iterator end() { return Data + Size; }
const_iterator begin() const { return Data; }
- const_iterator end() const { return Data + Size; }
+ const_iterator end() const { return Data + Size; }
const_iterator cbegin() const { return Data; }
- const_iterator cend() const { return Data + Size; }
+ const_iterator cend() const { return Data + Size; }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
@@ -163,6 +171,7 @@ public:
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
+
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
@@ -198,6 +207,7 @@ public:
llvm::iterator_range<reverse_iterator> reverse() {
return llvm::make_range(rbegin(), rend());
}
+
llvm::iterator_range<const_reverse_iterator> reverse() const {
return llvm::make_range(rbegin(), rend());
}
@@ -209,14 +219,12 @@ private:
static const size_t InitialCapacity = 4;
- SimpleArray(const SimpleArray<T> &A) = delete;
-
- T *Data;
- size_t Size;
- size_t Capacity;
+ T *Data = nullptr;
+ size_t Size = 0;
+ size_t Capacity = 0;
};
-} // end namespace til
+} // namespace til
// A copy on write vector.
// The vector can be in one of three states:
@@ -228,20 +236,28 @@ template<typename T>
class CopyOnWriteVector {
class VectorData {
public:
- VectorData() : NumRefs(1) { }
- VectorData(const VectorData &VD) : NumRefs(1), Vect(VD.Vect) { }
-
- unsigned NumRefs;
+ unsigned NumRefs = 1;
std::vector<T> Vect;
- };
- // No copy constructor or copy assignment. Use clone() with move assignment.
- CopyOnWriteVector(const CopyOnWriteVector &V) = delete;
- void operator=(const CopyOnWriteVector &V) = delete;
+ VectorData() = default;
+ VectorData(const VectorData &VD) : Vect(VD.Vect) {}
+ };
public:
- CopyOnWriteVector() : Data(nullptr) {}
+ CopyOnWriteVector() = default;
CopyOnWriteVector(CopyOnWriteVector &&V) : Data(V.Data) { V.Data = nullptr; }
+
+ CopyOnWriteVector &operator=(CopyOnWriteVector &&V) {
+ destroy();
+ Data = V.Data;
+ V.Data = nullptr;
+ return *this;
+ }
+
+ // No copy constructor or copy assignment. Use clone() with move assignment.
+ CopyOnWriteVector(const CopyOnWriteVector &) = delete;
+ CopyOnWriteVector &operator=(const CopyOnWriteVector &) = delete;
+
~CopyOnWriteVector() { destroy(); }
// Returns true if this holds a valid vector.
@@ -283,14 +299,7 @@ public:
// Create a lazy copy of this vector.
CopyOnWriteVector clone() { return CopyOnWriteVector(Data); }
- CopyOnWriteVector &operator=(CopyOnWriteVector &&V) {
- destroy();
- Data = V.Data;
- V.Data = nullptr;
- return *this;
- }
-
- typedef typename std::vector<T>::const_iterator const_iterator;
+ using const_iterator = typename std::vector<T>::const_iterator;
const std::vector<T> &elements() const { return Data->Vect; }
@@ -336,14 +345,14 @@ private:
++Data->NumRefs;
}
- VectorData *Data;
+ VectorData *Data = nullptr;
};
inline std::ostream& operator<<(std::ostream& ss, const StringRef str) {
return ss.write(str.data(), str.size());
}
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace threadSafety
+} // namespace clang
#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h
index 53ff20c23560..79d89e0633fd 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -1,4 +1,4 @@
-//= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==//
+//=- UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
-#include "clang/AST/Stmt.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
@@ -24,6 +24,7 @@ class AnalysisDeclContext;
class CFG;
class DeclContext;
class Expr;
+class Stmt;
class VarDecl;
/// A use of a variable, which might be uninitialized.
@@ -39,10 +40,10 @@ private:
const Expr *User;
/// Is this use uninitialized whenever the function is called?
- bool UninitAfterCall;
+ bool UninitAfterCall = false;
/// Is this use uninitialized whenever the variable declaration is reached?
- bool UninitAfterDecl;
+ bool UninitAfterDecl = false;
/// Does this use always see an uninitialized value?
bool AlwaysUninit;
@@ -53,8 +54,7 @@ private:
public:
UninitUse(const Expr *User, bool AlwaysUninit)
- : User(User), UninitAfterCall(false), UninitAfterDecl(false),
- AlwaysUninit(AlwaysUninit) {}
+ : User(User), AlwaysUninit(AlwaysUninit) {}
void addUninitBranch(Branch B) {
UninitBranches.push_back(B);
@@ -70,14 +70,18 @@ public:
enum Kind {
/// The use might be uninitialized.
Maybe,
+
/// The use is uninitialized whenever a certain branch is taken.
Sometimes,
+
/// The use is uninitialized the first time it is reached after we reach
/// the variable's declaration.
AfterDecl,
+
/// The use is uninitialized the first time it is reached after the function
/// is called.
AfterCall,
+
/// The use is always uninitialized.
Always
};
@@ -90,7 +94,8 @@ public:
!branch_empty() ? Sometimes : Maybe;
}
- typedef SmallVectorImpl<Branch>::const_iterator branch_iterator;
+ using branch_iterator = SmallVectorImpl<Branch>::const_iterator;
+
/// Branches which inevitably result in the variable being used uninitialized.
branch_iterator branch_begin() const { return UninitBranches.begin(); }
branch_iterator branch_end() const { return UninitBranches.end(); }
@@ -99,7 +104,7 @@ public:
class UninitVariablesHandler {
public:
- UninitVariablesHandler() {}
+ UninitVariablesHandler() = default;
virtual ~UninitVariablesHandler();
/// Called when the uninitialized variable is used at the given expression.
@@ -122,5 +127,6 @@ void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
UninitVariablesHandler &handler,
UninitVariablesAnalysisStats &stats);
-}
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h
index 03ff4a9516da..19531d92e645 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -1,4 +1,4 @@
-//=== AnalysisDeclContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
+// AnalysisDeclContext.h - Analysis context for Path Sens analysis -*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -15,37 +15,42 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
#define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
-#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/Analysis/BodyFarm.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CodeInjector.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
+#include <functional>
#include <memory>
namespace clang {
-class Stmt;
+class AnalysisDeclContextManager;
+class ASTContext;
+class BlockDecl;
+class BlockInvocationContext;
class CFGReverseBlockReachabilityAnalysis;
class CFGStmtMap;
-class LiveVariables;
-class ManagedAnalysis;
+class ImplicitParamDecl;
+class LocationContext;
+class LocationContextManager;
class ParentMap;
class PseudoConstantAnalysis;
-class LocationContextManager;
class StackFrameContext;
-class BlockInvocationContext;
-class AnalysisDeclContextManager;
-class LocationContext;
-
-namespace idx { class TranslationUnit; }
+class Stmt;
+class VarDecl;
/// The base class of a hierarchy of objects representing analyses tied
/// to AnalysisDeclContext.
class ManagedAnalysis {
protected:
- ManagedAnalysis() {}
+ ManagedAnalysis() = default;
+
public:
virtual ~ManagedAnalysis();
@@ -61,7 +66,6 @@ public:
// which creates the analysis object given an AnalysisDeclContext.
};
-
/// AnalysisDeclContext contains the context data for the function or method
/// under analysis.
class AnalysisDeclContext {
@@ -75,18 +79,19 @@ class AnalysisDeclContext {
std::unique_ptr<CFGStmtMap> cfgStmtMap;
CFG::BuildOptions cfgBuildOptions;
- CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
+ CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
- bool builtCFG, builtCompleteCFG;
+ bool builtCFG = false;
+ bool builtCompleteCFG = false;
std::unique_ptr<ParentMap> PM;
std::unique_ptr<PseudoConstantAnalysis> PCA;
std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
llvm::BumpPtrAllocator A;
- llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+ llvm::DenseMap<const BlockDecl *,void *> *ReferencedBlockVars = nullptr;
- void *ManagedAnalyses;
+ void *ManagedAnalyses = nullptr;
public:
AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
@@ -106,7 +111,7 @@ public:
AnalysisDeclContextManager *getManager() const {
return Manager;
}
-
+
/// Return the build options used to construct the CFG.
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
@@ -130,22 +135,22 @@ public:
void registerForcedBlockExpression(const Stmt *stmt);
const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
- /// \brief Get the body of the Declaration.
+ /// Get the body of the Declaration.
Stmt *getBody() const;
- /// \brief Get the body of the Declaration.
+ /// Get the body of the Declaration.
/// \param[out] IsAutosynthesized Specifies if the body is auto-generated
/// by the BodyFarm.
Stmt *getBody(bool &IsAutosynthesized) const;
- /// \brief Checks if the body of the Decl is generated by the BodyFarm.
+ /// Checks if the body of the Decl is generated by the BodyFarm.
///
/// Note, the lookup is not free. We are going to call getBody behind
/// the scenes.
/// \sa getBody
bool isBodyAutosynthesized() const;
- /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
+ /// Checks if the body of the Decl is generated by the BodyFarm from a
/// model file.
///
/// Note, the lookup is not free. We are going to call getBody behind
@@ -164,7 +169,7 @@ public:
void dumpCFG(bool ShowColors);
- /// \brief Returns true if we have built a CFG for this analysis context.
+ /// Returns true if we have built a CFG for this analysis context.
/// Note that this doesn't correspond to whether or not a valid CFG exists, it
/// corresponds to whether we *attempted* to build one.
bool isCFGBuilt() const { return builtCFG; }
@@ -172,7 +177,7 @@ public:
ParentMap &getParentMap();
PseudoConstantAnalysis *getPseudoConstantAnalysis();
- typedef const VarDecl * const * referenced_decls_iterator;
+ using referenced_decls_iterator = const VarDecl * const *;
llvm::iterator_range<referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
@@ -185,7 +190,7 @@ public:
const Stmt *S,
const CFGBlock *Blk,
unsigned Idx);
-
+
const BlockInvocationContext *
getBlockInvocationContext(const LocationContext *parent,
const BlockDecl *BD,
@@ -200,12 +205,13 @@ public:
if (!data) {
data = T::create(*this);
}
- return static_cast<T*>(data);
+ return static_cast<T *>(data);
}
/// Returns true if the root namespace of the given declaration is the 'std'
/// C++ namespace.
static bool isInStdNamespace(const Decl *D);
+
private:
ManagedAnalysis *&getAnalysisImpl(const void* tag);
@@ -228,7 +234,7 @@ private:
protected:
LocationContext(ContextKind k, AnalysisDeclContext *ctx,
const LocationContext *parent)
- : Kind(k), Ctx(ctx), Parent(parent) {}
+ : Kind(k), Ctx(ctx), Parent(parent) {}
public:
virtual ~LocationContext();
@@ -258,14 +264,18 @@ public:
return Ctx->getSelfDecl();
}
- const StackFrameContext *getCurrentStackFrame() const;
+ const StackFrameContext *getStackFrame() const;
/// Return true if the current LocationContext has no caller context.
virtual bool inTopFrame() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
- void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
+ void dumpStack(
+ raw_ostream &OS, StringRef Indent = {}, const char *NL = "\n",
+ const char *Sep = "",
+ std::function<void(const LocationContext *)> printMoreInfoPerContext =
+ [](const LocationContext *) {}) const;
void dumpStack() const;
public:
@@ -277,6 +287,8 @@ public:
};
class StackFrameContext : public LocationContext {
+ friend class LocationContextManager;
+
// The callsite where this stack frame is established.
const Stmt *CallSite;
@@ -286,15 +298,14 @@ class StackFrameContext : public LocationContext {
// The index of the callsite in the CFGBlock.
unsigned Index;
- friend class LocationContextManager;
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s, const CFGBlock *blk,
unsigned idx)
- : LocationContext(StackFrame, ctx, parent), CallSite(s),
- Block(blk), Index(idx) {}
+ : LocationContext(StackFrame, ctx, parent), CallSite(s),
+ Block(blk), Index(idx) {}
public:
- ~StackFrameContext() override {}
+ ~StackFrameContext() override = default;
const Stmt *getCallSite() const { return CallSite; }
@@ -321,15 +332,16 @@ public:
};
class ScopeContext : public LocationContext {
+ friend class LocationContextManager;
+
const Stmt *Enter;
- friend class LocationContextManager;
ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s)
- : LocationContext(Scope, ctx, parent), Enter(s) {}
+ : LocationContext(Scope, ctx, parent), Enter(s) {}
public:
- ~ScopeContext() override {}
+ ~ScopeContext() override = default;
void Profile(llvm::FoldingSetNodeID &ID) override;
@@ -344,23 +356,23 @@ public:
};
class BlockInvocationContext : public LocationContext {
+ friend class LocationContextManager;
+
const BlockDecl *BD;
-
+
// FIXME: Come up with a more type-safe way to model context-sensitivity.
const void *ContextData;
- friend class LocationContextManager;
-
BlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
const BlockDecl *bd, const void *contextData)
- : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
+ : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
public:
- ~BlockInvocationContext() override {}
+ ~BlockInvocationContext() override = default;
const BlockDecl *getBlockDecl() const { return BD; }
-
+
const void *getContextData() const { return ContextData; }
void Profile(llvm::FoldingSetNodeID &ID) override;
@@ -379,6 +391,7 @@ public:
class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
+
public:
~LocationContextManager();
@@ -390,7 +403,7 @@ public:
const ScopeContext *getScope(AnalysisDeclContext *ctx,
const LocationContext *parent,
const Stmt *s);
-
+
const BlockInvocationContext *
getBlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
@@ -407,8 +420,8 @@ private:
};
class AnalysisDeclContextManager {
- typedef llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>
- ContextMap;
+ using ContextMap =
+ llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
ContextMap Contexts;
LocationContextManager LocContexts;
@@ -431,10 +444,14 @@ public:
bool addImplicitDtors = false,
bool addInitializers = false,
bool addTemporaryDtors = false,
- bool addLifetime = false, bool addLoopExit = false,
+ bool addLifetime = false,
+ bool addLoopExit = false,
+ bool addScopes = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
bool addCXXNewAllocator = true,
+ bool addRichCXXConstructors = true,
+ bool markElidedCXXConstructors = true,
CodeInjector *injector = nullptr);
AnalysisDeclContext *getContext(const Decl *D);
@@ -446,7 +463,7 @@ public:
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
-
+
/// Return true if faux bodies should be synthesized for well-known
/// functions.
bool synthesizeBodies() const { return SynthesizeBodies; }
@@ -488,5 +505,6 @@ private:
}
};
-} // end clang namespace
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
index cfedb2aa8ed5..bf81d8358a54 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
@@ -15,8 +15,10 @@
#ifndef LLVM_CLANG_ANALYSIS_CFG_H
#define LLVM_CLANG_ANALYSIS_CFG_H
-#include "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Analysis/ConstructionContext.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
@@ -50,16 +52,23 @@ class FieldDecl;
class LangOptions;
class VarDecl;
-/// CFGElement - Represents a top-level expression in a basic block.
+/// Represents a top-level expression in a basic block.
class CFGElement {
public:
enum Kind {
// main kind
- Statement,
Initializer,
+ ScopeBegin,
+ ScopeEnd,
NewAllocator,
LifetimeEnds,
LoopExit,
+ // stmt kind
+ Statement,
+ Constructor,
+ CXXRecordTypedCall,
+ STMT_BEGIN = Statement,
+ STMT_END = CXXRecordTypedCall,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
@@ -84,7 +93,7 @@ protected:
CFGElement() = default;
public:
- /// \brief Convert to the specified CFGElement type, asserting that this
+ /// Convert to the specified CFGElement type, asserting that this
/// CFGElement is of the desired type.
template<typename T>
T castAs() const {
@@ -95,7 +104,7 @@ public:
return t;
}
- /// \brief Convert to the specified CFGElement type, returning None if this
+ /// Convert to the specified CFGElement type, returning None if this
/// CFGElement is not of the desired type.
template<typename T>
Optional<T> getAs() const {
@@ -117,7 +126,9 @@ public:
class CFGStmt : public CFGElement {
public:
- CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
+ explicit CFGStmt(Stmt *S, Kind K = Statement) : CFGElement(K, S) {
+ assert(isKind(*this));
+ }
const Stmt *getStmt() const {
return static_cast<const Stmt *>(Data1.getPointer());
@@ -126,18 +137,89 @@ public:
private:
friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() >= STMT_BEGIN && E.getKind() <= STMT_END;
+ }
+
+protected:
CFGStmt() = default;
+};
+
+/// Represents C++ constructor call. Maintains information necessary to figure
+/// out what memory is being initialized by the constructor expression. For now
+/// this is only used by the analyzer's CFG.
+class CFGConstructor : public CFGStmt {
+public:
+ explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
+ : CFGStmt(CE, Constructor) {
+ assert(C);
+ Data2.setPointer(const_cast<ConstructionContext *>(C));
+ }
+
+ const ConstructionContext *getConstructionContext() const {
+ return static_cast<ConstructionContext *>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+
+ CFGConstructor() = default;
static bool isKind(const CFGElement &E) {
- return E.getKind() == Statement;
+ return E.getKind() == Constructor;
}
};
-/// CFGInitializer - Represents C++ base or member initializer from
-/// constructor's initialization list.
+/// Represents a function call that returns a C++ object by value. This, like
+/// constructor, requires a construction context in order to understand the
+/// storage of the returned object . In C such tracking is not necessary because
+/// no additional effort is required for destroying the object or modeling copy
+/// elision. Like CFGConstructor, this element is for now only used by the
+/// analyzer's CFG.
+class CFGCXXRecordTypedCall : public CFGStmt {
+public:
+ /// Returns true when call expression \p CE needs to be represented
+ /// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
+ static bool isCXXRecordTypedCall(Expr *E) {
+ assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E));
+ // There is no such thing as reference-type expression. If the function
+ // returns a reference, it'll return the respective lvalue or xvalue
+ // instead, and we're only interested in objects.
+ return !E->isGLValue() &&
+ E->getType().getCanonicalType()->getAsCXXRecordDecl();
+ }
+
+ explicit CFGCXXRecordTypedCall(Expr *E, const ConstructionContext *C)
+ : CFGStmt(E, CXXRecordTypedCall) {
+ assert(isCXXRecordTypedCall(E));
+ assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
+ // These are possible in C++17 due to mandatory copy elision.
+ isa<ReturnedValueConstructionContext>(C) ||
+ isa<VariableConstructionContext>(C) ||
+ isa<ConstructorInitializerConstructionContext>(C) ||
+ isa<ArgumentConstructionContext>(C)));
+ Data2.setPointer(const_cast<ConstructionContext *>(C));
+ }
+
+ const ConstructionContext *getConstructionContext() const {
+ return static_cast<ConstructionContext *>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+
+ CFGCXXRecordTypedCall() = default;
+
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() == CXXRecordTypedCall;
+ }
+};
+
+/// Represents C++ base or member initializer from constructor's initialization
+/// list.
class CFGInitializer : public CFGElement {
public:
- CFGInitializer(CXXCtorInitializer *initializer)
+ explicit CFGInitializer(CXXCtorInitializer *initializer)
: CFGElement(Initializer, initializer) {}
CXXCtorInitializer* getInitializer() const {
@@ -154,7 +236,7 @@ private:
}
};
-/// CFGNewAllocator - Represents C++ allocator call.
+/// Represents C++ allocator call.
class CFGNewAllocator : public CFGElement {
public:
explicit CFGNewAllocator(const CXXNewExpr *S)
@@ -223,8 +305,57 @@ private:
}
};
-/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
-/// by compiler on various occasions.
+/// Represents beginning of a scope implicitly generated
+/// by the compiler on encountering a CompoundStmt
+class CFGScopeBegin : public CFGElement {
+public:
+ CFGScopeBegin() {}
+ CFGScopeBegin(const VarDecl *VD, const Stmt *S)
+ : CFGElement(ScopeBegin, VD, S) {}
+
+ // Get statement that triggered a new scope.
+ const Stmt *getTriggerStmt() const {
+ return static_cast<Stmt*>(Data2.getPointer());
+ }
+
+ // Get VD that triggered a new scope.
+ const VarDecl *getVarDecl() const {
+ return static_cast<VarDecl *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ Kind kind = E.getKind();
+ return kind == ScopeBegin;
+ }
+};
+
+/// Represents end of a scope implicitly generated by
+/// the compiler after the last Stmt in a CompoundStmt's body
+class CFGScopeEnd : public CFGElement {
+public:
+ CFGScopeEnd() {}
+ CFGScopeEnd(const VarDecl *VD, const Stmt *S) : CFGElement(ScopeEnd, VD, S) {}
+
+ const VarDecl *getVarDecl() const {
+ return static_cast<VarDecl *>(Data1.getPointer());
+ }
+
+ const Stmt *getTriggerStmt() const {
+ return static_cast<Stmt *>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ Kind kind = E.getKind();
+ return kind == ScopeEnd;
+ }
+};
+
+/// Represents C++ object destructor implicitly generated by compiler on various
+/// occasions.
class CFGImplicitDtor : public CFGElement {
protected:
CFGImplicitDtor() = default;
@@ -247,9 +378,9 @@ private:
}
};
-/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
-/// for automatic object or temporary bound to const reference at the point
-/// of leaving its local scope.
+/// Represents C++ object destructor implicitly generated for automatic object
+/// or temporary bound to const reference at the point of leaving its local
+/// scope.
class CFGAutomaticObjDtor: public CFGImplicitDtor {
public:
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
@@ -274,8 +405,7 @@ private:
}
};
-/// CFGDeleteDtor - Represents C++ object destructor generated
-/// from a call to delete.
+/// Represents C++ object destructor generated from a call to delete.
class CFGDeleteDtor : public CFGImplicitDtor {
public:
CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
@@ -300,8 +430,8 @@ private:
}
};
-/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
-/// base object in destructor.
+/// Represents C++ object destructor implicitly generated for base object in
+/// destructor.
class CFGBaseDtor : public CFGImplicitDtor {
public:
CFGBaseDtor(const CXXBaseSpecifier *base)
@@ -321,8 +451,8 @@ private:
}
};
-/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
-/// member object in destructor.
+/// Represents C++ object destructor implicitly generated for member object in
+/// destructor.
class CFGMemberDtor : public CFGImplicitDtor {
public:
CFGMemberDtor(const FieldDecl *field)
@@ -342,8 +472,8 @@ private:
}
};
-/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
-/// at the end of full expression for temporary object.
+/// Represents C++ object destructor implicitly generated at the end of full
+/// expression for temporary object.
class CFGTemporaryDtor : public CFGImplicitDtor {
public:
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
@@ -363,7 +493,7 @@ private:
}
};
-/// CFGTerminator - Represents CFGBlock terminator statement.
+/// Represents CFGBlock terminator statement.
///
/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
/// in control flow of destructors of temporaries. In this case terminator
@@ -394,7 +524,7 @@ public:
explicit operator bool() const { return getStmt(); }
};
-/// CFGBlock - Represents a single basic block in a source-level CFG.
+/// Represents a single basic block in a source-level CFG.
/// It consists of:
///
/// (1) A set of statements/expressions (which may contain subexpressions).
@@ -462,26 +592,24 @@ class CFGBlock {
bool empty() const { return Impl.empty(); }
};
- /// Stmts - The set of statements in the basic block.
+ /// The set of statements in the basic block.
ElementList Elements;
- /// Label - An (optional) label that prefixes the executable
- /// statements in the block. When this variable is non-NULL, it is
- /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
+ /// 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 = nullptr;
- /// Terminator - The terminator for a basic block that
- /// indicates the type of control-flow that occurs between a block
- /// and its successors.
+ /// The terminator for a basic block that indicates the type of control-flow
+ /// that occurs between a block and its successors.
CFGTerminator Terminator;
- /// LoopTarget - Some blocks are used to represent the "loop edge" to
- /// the start of a loop from within the loop body. This Stmt* will be
- /// refer to the loop statement for such blocks (and be null otherwise).
+ /// 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 = nullptr;
- /// BlockID - A numerical ID assigned to a CFGBlock during construction
- /// of the CFG.
+ /// A numerical ID assigned to a CFGBlock during construction of the CFG.
unsigned BlockID;
public:
@@ -503,7 +631,7 @@ public:
public:
/// Construct an AdjacentBlock with a possibly unreachable block.
AdjacentBlock(CFGBlock *B, bool IsReachable);
-
+
/// Construct an AdjacentBlock with a reachable block and an alternate
/// unreachable block.
AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
@@ -539,13 +667,12 @@ public:
};
private:
- /// Predecessors/Successors - Keep track of the predecessor / successor
- /// CFG blocks.
+ /// Keep track of the predecessor / successor CFG blocks.
using AdjacentBlocks = BumpVector<AdjacentBlock>;
AdjacentBlocks Preds;
AdjacentBlocks Succs;
- /// NoReturn - This bit is set when the basic block contains a function call
+ /// This bit is set when the basic block contains a function call
/// or implicit destructor that is attributed as 'noreturn'. In that case,
/// control cannot technically ever proceed past this block. All such blocks
/// will have a single immediate successor: the exit block. This allows them
@@ -556,7 +683,7 @@ private:
/// storage if the memory usage of CFGBlock becomes an issue.
unsigned HasNoReturnElement : 1;
- /// Parent - The parent CFG that owns this CFGBlock.
+ /// The parent CFG that owns this CFGBlock.
CFG *Parent;
public:
@@ -747,6 +874,17 @@ public:
Elements.push_back(CFGStmt(statement), C);
}
+ void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGConstructor(CE, CC), C);
+ }
+
+ void appendCXXRecordTypedCall(Expr *E,
+ const ConstructionContext *CC,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGCXXRecordTypedCall(E, CC), C);
+ }
+
void appendInitializer(CXXCtorInitializer *initializer,
BumpVectorContext &C) {
Elements.push_back(CFGInitializer(initializer), C);
@@ -757,6 +895,24 @@ public:
Elements.push_back(CFGNewAllocator(NE), C);
}
+ void appendScopeBegin(const VarDecl *VD, const Stmt *S,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGScopeBegin(VD, S), C);
+ }
+
+ void prependScopeBegin(const VarDecl *VD, const Stmt *S,
+ BumpVectorContext &C) {
+ Elements.insert(Elements.rbegin(), 1, CFGScopeBegin(VD, S), C);
+ }
+
+ void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) {
+ Elements.push_back(CFGScopeEnd(VD, S), C);
+ }
+
+ void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) {
+ Elements.insert(Elements.rbegin(), 1, CFGScopeEnd(VD, S), C);
+ }
+
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
Elements.push_back(CFGBaseDtor(BS), C);
}
@@ -810,9 +966,22 @@ public:
*I = CFGLifetimeEnds(VD, S);
return ++I;
}
+
+ // Scope leaving must be performed in reversed order. So insertion is in two
+ // steps. First we prepare space for some number of elements, then we insert
+ // the elements beginning at the last position in prepared space.
+ iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C) {
+ return iterator(
+ Elements.insert(I.base(), Cnt, CFGScopeEnd(nullptr, nullptr), C));
+ }
+ iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S) {
+ *I = CFGScopeEnd(VD, S);
+ return ++I;
+ }
+
};
-/// \brief CFGCallback defines methods that should be called when a logical
+/// CFGCallback defines methods that should be called when a logical
/// operator error is found when building the CFG.
class CFGCallback {
public:
@@ -824,7 +993,7 @@ public:
bool isAlwaysTrue) {}
};
-/// CFG - Represents a source-level, intra-procedural CFG that represents the
+/// Represents a source-level, intra-procedural CFG that represents the
/// control-flow of a Stmt. The Stmt can represent an entire function body,
/// or a single expression. A CFG will always contain one empty block that
/// represents the Exit point of the CFG. A CFG will also contain a designated
@@ -852,9 +1021,12 @@ public:
bool AddLifetime = false;
bool AddLoopExit = false;
bool AddTemporaryDtors = false;
+ bool AddScopes = false;
bool AddStaticInitBranches = false;
bool AddCXXNewAllocator = false;
bool AddCXXDefaultInitExprInCtors = false;
+ bool AddRichCXXConstructors = false;
+ bool MarkElidedCXXConstructors = false;
BuildOptions() = default;
@@ -873,21 +1045,21 @@ public:
}
};
- /// buildCFG - Builds a CFG from an AST.
+ /// Builds a CFG from an AST.
static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
const BuildOptions &BO);
- /// createBlock - Create a new block in the CFG. The CFG owns the block;
- /// the caller should not directly free it.
+ /// Create a new block in the CFG. The CFG owns the block; the caller should
+ /// not directly free it.
CFGBlock *createBlock();
- /// setEntry - Set the entry block of the CFG. This is typically used
- /// only during CFG construction. Most CFG clients expect that the
- /// entry block has no predecessors and contains no statements.
+ /// Set the entry block of the CFG. This is typically used only during CFG
+ /// construction. Most CFG clients expect that the entry block has no
+ /// predecessors and contains no statements.
void setEntry(CFGBlock *B) { Entry = B; }
- /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
- /// This is typically used only during CFG construction.
+ /// Set the block used for indirect goto jumps. This is typically used only
+ /// during CFG construction.
void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
//===--------------------------------------------------------------------===//
@@ -981,8 +1153,8 @@ public:
template <typename CALLBACK>
void VisitBlockStmts(CALLBACK& O) const {
- for (const_iterator I=begin(), E=end(); I != E; ++I)
- for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();
BI != BE; ++BI) {
if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
O(const_cast<Stmt*>(stmt->getStmt()));
@@ -993,13 +1165,12 @@ public:
// CFG Introspection.
//===--------------------------------------------------------------------===//
- /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
- /// start at 0).
+ /// Returns the total number of BlockIDs allocated (which start at 0).
unsigned getNumBlockIDs() const { return NumBlockIDs; }
- /// size - Return the total number of CFGBlocks within the CFG
- /// This is simply a renaming of the getNumBlockIDs(). This is necessary
- /// because the dominator implementation needs such an interface.
+ /// Return the total number of CFGBlocks within the CFG This is simply a
+ /// renaming of the getNumBlockIDs(). This is necessary because the dominator
+ /// implementation needs such an interface.
unsigned size() const { return NumBlockIDs; }
//===--------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h
index 4dfa91df0f42..78e637daf379 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h
@@ -19,20 +19,18 @@
namespace clang {
-class CFG;
-class CFGBlock;
class ParentMap;
class Stmt;
class CFGStmtMap {
ParentMap *PM;
void *M;
-
+
CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
-
+
public:
~CFGStmtMap();
-
+
/// Returns a new CFGMap for the given CFG. It is the caller's
/// responsibility to 'delete' this object when done using it.
static CFGStmtMap *Build(CFG* C, ParentMap *PM);
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
index bdcdfecddc3e..ae0f392ed969 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
@@ -34,7 +34,7 @@ class Decl;
class DeclContext;
class Stmt;
-/// \brief The AST-based call graph.
+/// The AST-based call graph.
///
/// The call graph extends itself with the given declarations by implementing
/// the recursive AST visitor, which constructs the graph by visiting the given
@@ -55,7 +55,7 @@ public:
CallGraph();
~CallGraph();
- /// \brief Populate the call graph with the functions in the given
+ /// Populate the call graph with the functions in the given
/// declaration.
///
/// Recursively walks the declaration to find all the dependent Decls as well.
@@ -63,13 +63,13 @@ public:
TraverseDecl(D);
}
- /// \brief Determine if a declaration should be included in the graph.
+ /// Determine if a declaration should be included in the graph.
static bool includeInGraph(const Decl *D);
- /// \brief Lookup the node for the given declaration.
+ /// Lookup the node for the given declaration.
CallGraphNode *getNode(const Decl *) const;
- /// \brief Lookup the node for the given declaration. If none found, insert
+ /// Lookup the node for the given declaration. If none found, insert
/// one into the graph.
CallGraphNode *getOrInsertNode(Decl *);
@@ -83,7 +83,7 @@ public:
const_iterator begin() const { return FunctionMap.begin(); }
const_iterator end() const { return FunctionMap.end(); }
- /// \brief Get the number of nodes in the graph.
+ /// Get the number of nodes in the graph.
unsigned size() const { return FunctionMap.size(); }
/// \ brief Get the virtual root of the graph, all the functions available
@@ -133,10 +133,10 @@ public:
bool shouldWalkTypesOfTypeLocs() const { return false; }
private:
- /// \brief Add the given declaration to the call graph.
+ /// Add the given declaration to the call graph.
void addNodeForDecl(Decl *D, bool IsGlobal);
- /// \brief Allocate a new node in the graph.
+ /// Allocate a new node in the graph.
CallGraphNode *allocateNewNode(Decl *);
};
@@ -145,10 +145,10 @@ public:
using CallRecord = CallGraphNode *;
private:
- /// \brief The function/method declaration.
+ /// The function/method declaration.
Decl *FD;
- /// \brief The list of functions called from this node.
+ /// The list of functions called from this node.
SmallVector<CallRecord, 5> CalledFunctions;
public:
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h b/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h
index 051b9236658c..915ec58a5144 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h
@@ -161,7 +161,7 @@ public:
/// The result of findClones can be further constrained with the constrainClones
/// method.
///
-/// This class only searches for clones in exectuable source code
+/// This class only searches for clones in executable source code
/// (e.g. function bodies). Other clones (e.g. cloned comments or declarations)
/// are not supported.
class CloneDetector {
@@ -332,7 +332,7 @@ struct FilenamePatternConstraint {
StringRef IgnoredFilesPattern;
std::shared_ptr<llvm::Regex> IgnoredFilesRegex;
- FilenamePatternConstraint(StringRef IgnoredFilesPattern)
+ FilenamePatternConstraint(StringRef IgnoredFilesPattern)
: IgnoredFilesPattern(IgnoredFilesPattern) {
IgnoredFilesRegex = std::make_shared<llvm::Regex>("^(" +
IgnoredFilesPattern.str() + "$)");
@@ -351,7 +351,7 @@ struct FilenamePatternConstraint {
/// Analyzes the pattern of the referenced variables in a statement.
class VariablePattern {
- /// Describes an occurence of a variable reference in a statement.
+ /// Describes an occurrence of a variable reference in a statement.
struct VariableOccurence {
/// The index of the associated VarDecl in the Variables vector.
size_t KindID;
@@ -362,7 +362,7 @@ class VariablePattern {
: KindID(KindID), Mention(Mention) {}
};
- /// All occurences of referenced variables in the order of appearance.
+ /// All occurrences of referenced variables in the order of appearance.
std::vector<VariableOccurence> Occurences;
/// List of referenced variables in the order of appearance.
/// Every item in this list is unique.
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h b/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h
index 413a55b05b07..2c87cde996f2 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::CodeInjector interface which is responsible for
+/// Defines the clang::CodeInjector interface which is responsible for
/// injecting AST of function definitions that may not be available in the
/// original source.
///
@@ -23,7 +23,7 @@ class Stmt;
class FunctionDecl;
class ObjCMethodDecl;
-/// \brief CodeInjector is an interface which is responsible for injecting AST
+/// CodeInjector is an interface which is responsible for injecting AST
/// of function definitions that may not be available in the original source.
///
/// The getBody function will be called each time the static analyzer examines a
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ConstructionContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/ConstructionContext.h
new file mode 100644
index 000000000000..aee67865df25
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/ConstructionContext.h
@@ -0,0 +1,653 @@
+//===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ConstructionContext class and its sub-classes,
+// which represent various different ways of constructing C++ objects
+// with the additional information the users may want to know about
+// the constructor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
+#define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
+
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/AST/ExprCXX.h"
+
+namespace clang {
+
+/// Represents a single point (AST node) in the program that requires attention
+/// during construction of an object. ConstructionContext would be represented
+/// as a list of such items.
+class ConstructionContextItem {
+public:
+ enum ItemKind {
+ VariableKind,
+ NewAllocatorKind,
+ ReturnKind,
+ MaterializationKind,
+ TemporaryDestructorKind,
+ ElidedDestructorKind,
+ ElidableConstructorKind,
+ ArgumentKind,
+ STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
+ STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
+ STATEMENT_KIND_BEGIN = VariableKind,
+ STATEMENT_KIND_END = ArgumentKind,
+ InitializerKind,
+ INITIALIZER_KIND_BEGIN=InitializerKind,
+ INITIALIZER_KIND_END=InitializerKind
+ };
+
+ LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
+ switch (K) {
+ case VariableKind: return "construct into local variable";
+ case NewAllocatorKind: return "construct into new-allocator";
+ case ReturnKind: return "construct into return address";
+ case MaterializationKind: return "materialize temporary";
+ case TemporaryDestructorKind: return "destroy temporary";
+ case ElidedDestructorKind: return "elide destructor";
+ case ElidableConstructorKind: return "elide constructor";
+ case ArgumentKind: return "construct into argument";
+ case InitializerKind: return "construct into member variable";
+ };
+ llvm_unreachable("Unknown ItemKind");
+ }
+
+private:
+ const void *const Data;
+ const ItemKind Kind;
+ const unsigned Index = 0;
+
+ bool hasStatement() const {
+ return Kind >= STATEMENT_KIND_BEGIN &&
+ Kind <= STATEMENT_KIND_END;
+ }
+
+ bool hasIndex() const {
+ return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
+ Kind >= STATEMENT_WITH_INDEX_KIND_END;
+ }
+
+ bool hasInitializer() const {
+ return Kind >= INITIALIZER_KIND_BEGIN &&
+ Kind <= INITIALIZER_KIND_END;
+ }
+
+public:
+ // ConstructionContextItem should be simple enough so that it was easy to
+ // re-construct it from the AST node it captures. For that reason we provide
+ // simple implicit conversions from all sorts of supported AST nodes.
+ ConstructionContextItem(const DeclStmt *DS)
+ : Data(DS), Kind(VariableKind) {}
+
+ ConstructionContextItem(const CXXNewExpr *NE)
+ : Data(NE), Kind(NewAllocatorKind) {}
+
+ ConstructionContextItem(const ReturnStmt *RS)
+ : Data(RS), Kind(ReturnKind) {}
+
+ ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
+ : Data(MTE), Kind(MaterializationKind) {}
+
+ ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
+ bool IsElided = false)
+ : Data(BTE),
+ Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
+
+ ConstructionContextItem(const CXXConstructExpr *CE)
+ : Data(CE), Kind(ElidableConstructorKind) {}
+
+ ConstructionContextItem(const CallExpr *CE, unsigned Index)
+ : Data(CE), Kind(ArgumentKind), Index(Index) {}
+
+ ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
+ : Data(CE), Kind(ArgumentKind), Index(Index) {}
+
+ ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
+ : Data(ME), Kind(ArgumentKind), Index(Index) {}
+
+ // A polymorphic version of the previous calls with dynamic type check.
+ ConstructionContextItem(const Expr *E, unsigned Index)
+ : Data(E), Kind(ArgumentKind), Index(Index) {
+ assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
+ isa<ObjCMessageExpr>(E));
+ }
+
+ ConstructionContextItem(const CXXCtorInitializer *Init)
+ : Data(Init), Kind(InitializerKind), Index(0) {}
+
+ ItemKind getKind() const { return Kind; }
+
+ LLVM_DUMP_METHOD StringRef getKindAsString() const {
+ return getKindAsString(getKind());
+ }
+
+ /// The construction site - the statement that triggered the construction
+ /// for one of its parts. For instance, stack variable declaration statement
+ /// triggers construction of itself or its elements if it's an array,
+ /// new-expression triggers construction of the newly allocated object(s).
+ const Stmt *getStmt() const {
+ assert(hasStatement());
+ return static_cast<const Stmt *>(Data);
+ }
+
+ const Stmt *getStmtOrNull() const {
+ return hasStatement() ? getStmt() : nullptr;
+ }
+
+ /// The construction site is not necessarily a statement. It may also be a
+ /// CXXCtorInitializer, which means that a member variable is being
+ /// constructed during initialization of the object that contains it.
+ const CXXCtorInitializer *getCXXCtorInitializer() const {
+ assert(hasInitializer());
+ return static_cast<const CXXCtorInitializer *>(Data);
+ }
+
+ /// If a single trigger statement triggers multiple constructors, they are
+ /// usually being enumerated. This covers function argument constructors
+ /// triggered by a call-expression and items in an initializer list triggered
+ /// by an init-list-expression.
+ unsigned getIndex() const {
+ // This is a fairly specific request. Let's make sure the user knows
+ // what he's doing.
+ assert(hasIndex());
+ return Index;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(Data);
+ ID.AddInteger(Kind);
+ ID.AddInteger(Index);
+ }
+
+ bool operator==(const ConstructionContextItem &Other) const {
+ // For most kinds the Index comparison is trivially true, but
+ // checking kind separately doesn't seem to be less expensive
+ // than checking Index. Same in operator<().
+ return std::make_tuple(Data, Kind, Index) ==
+ std::make_tuple(Other.Data, Other.Kind, Other.Index);
+ }
+
+ bool operator<(const ConstructionContextItem &Other) const {
+ return std::make_tuple(Data, Kind, Index) <
+ std::make_tuple(Other.Data, Other.Kind, Other.Index);
+ }
+};
+
+/// Construction context can be seen as a linked list of multiple layers.
+/// Sometimes a single trigger is not enough to describe the construction
+/// site. That's what causing us to have a chain of "partial" construction
+/// context layers. Some examples:
+/// - A constructor within in an aggregate initializer list within a variable
+/// would have a construction context of the initializer list with
+/// the parent construction context of a variable.
+/// - A constructor for a temporary that needs to be both destroyed
+/// and materialized into an elidable copy constructor would have a
+/// construction context of a CXXBindTemporaryExpr with the parent
+/// construction context of a MaterializeTemproraryExpr.
+/// Not all of these are currently supported.
+/// Layers are created gradually while traversing the AST, and layers that
+/// represent the outmost AST nodes are built first, while the node that
+/// immediately contains the constructor would be built last and capture the
+/// previous layers as its parents. Construction context captures the last layer
+/// (which has links to the previous layers) and classifies the seemingly
+/// arbitrary chain of layers into one of the possible ways of constructing
+/// an object in C++ for user-friendly experience.
+class ConstructionContextLayer {
+ const ConstructionContextLayer *Parent = nullptr;
+ ConstructionContextItem Item;
+
+ ConstructionContextLayer(ConstructionContextItem Item,
+ const ConstructionContextLayer *Parent)
+ : Parent(Parent), Item(Item) {}
+
+public:
+ static const ConstructionContextLayer *
+ create(BumpVectorContext &C, const ConstructionContextItem &Item,
+ const ConstructionContextLayer *Parent = nullptr);
+
+ const ConstructionContextItem &getItem() const { return Item; }
+ const ConstructionContextLayer *getParent() const { return Parent; }
+ bool isLast() const { return !Parent; }
+
+ /// See if Other is a proper initial segment of this construction context
+ /// in terms of the parent chain - i.e. a few first parents coincide and
+ /// then the other context terminates but our context goes further - i.e.,
+ /// we are providing the same context that the other context provides,
+ /// and a bit more above that.
+ bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
+};
+
+
+/// ConstructionContext's subclasses describe different ways of constructing
+/// an object in C++. The context re-captures the essential parent AST nodes
+/// of the CXXConstructExpr it is assigned to and presents these nodes
+/// through easy-to-understand accessor methods.
+class ConstructionContext {
+public:
+ enum Kind {
+ SimpleVariableKind,
+ CXX17ElidedCopyVariableKind,
+ VARIABLE_BEGIN = SimpleVariableKind,
+ VARIABLE_END = CXX17ElidedCopyVariableKind,
+ SimpleConstructorInitializerKind,
+ CXX17ElidedCopyConstructorInitializerKind,
+ INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
+ INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
+ NewAllocatedObjectKind,
+ SimpleTemporaryObjectKind,
+ ElidedTemporaryObjectKind,
+ TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
+ TEMPORARY_END = ElidedTemporaryObjectKind,
+ SimpleReturnedValueKind,
+ CXX17ElidedCopyReturnedValueKind,
+ RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
+ RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
+ ArgumentKind
+ };
+
+protected:
+ Kind K;
+
+ // Do not make public! These need to only be constructed
+ // via createFromLayers().
+ explicit ConstructionContext(Kind K) : K(K) {}
+
+private:
+ // A helper function for constructing an instance into a bump vector context.
+ template <typename T, typename... ArgTypes>
+ static T *create(BumpVectorContext &C, ArgTypes... Args) {
+ auto *CC = C.getAllocator().Allocate<T>();
+ return new (CC) T(Args...);
+ }
+
+ // A sub-routine of createFromLayers() that deals with temporary objects
+ // that need to be materialized. The BTE argument is for the situation when
+ // the object also needs to be bound for destruction.
+ static const ConstructionContext *createMaterializedTemporaryFromLayers(
+ BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
+ const CXXBindTemporaryExpr *BTE,
+ const ConstructionContextLayer *ParentLayer);
+
+ // A sub-routine of createFromLayers() that deals with temporary objects
+ // that need to be bound for destruction. Automatically finds out if the
+ // object also needs to be materialized and delegates to
+ // createMaterializedTemporaryFromLayers() if necessary.
+ static const ConstructionContext *
+ createBoundTemporaryFromLayers(
+ BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
+ const ConstructionContextLayer *ParentLayer);
+
+public:
+ /// Consume the construction context layer, together with its parent layers,
+ /// and wrap it up into a complete construction context. May return null
+ /// if layers do not form any supported construction context.
+ static const ConstructionContext *
+ createFromLayers(BumpVectorContext &C,
+ const ConstructionContextLayer *TopLayer);
+
+ Kind getKind() const { return K; }
+};
+
+/// An abstract base class for local variable constructors.
+class VariableConstructionContext : public ConstructionContext {
+ const DeclStmt *DS;
+
+protected:
+ VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
+ : ConstructionContext(K), DS(DS) {
+ assert(classof(this));
+ assert(DS);
+ }
+
+public:
+ const DeclStmt *getDeclStmt() const { return DS; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() >= VARIABLE_BEGIN &&
+ CC->getKind() <= VARIABLE_END;
+ }
+};
+
+/// Represents construction into a simple local variable, eg. T var(123);.
+/// If a variable has an initializer, eg. T var = makeT();, then the final
+/// elidable copy-constructor from makeT() into var would also be a simple
+/// variable constructor handled by this class.
+class SimpleVariableConstructionContext : public VariableConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleVariableConstructionContext(const DeclStmt *DS)
+ : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
+ DS) {}
+
+public:
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == SimpleVariableKind;
+ }
+};
+
+/// Represents construction into a simple variable with an initializer syntax,
+/// with a single constructor, eg. T var = makeT();. Such construction context
+/// may only appear in C++17 because previously it was split into a temporary
+/// object constructor and an elidable simple variable copy-constructor and
+/// we were producing separate construction contexts for these constructors.
+/// In C++17 we have a single construction context that combines both.
+/// Note that if the object has trivial destructor, then this code is
+/// indistinguishable from a simple variable constructor on the AST level;
+/// in this case we provide a simple variable construction context.
+class CXX17ElidedCopyVariableConstructionContext
+ : public VariableConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit CXX17ElidedCopyVariableConstructionContext(
+ const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
+ : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
+ assert(BTE);
+ }
+
+public:
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == CXX17ElidedCopyVariableKind;
+ }
+};
+
+// An abstract base class for constructor-initializer-based constructors.
+class ConstructorInitializerConstructionContext : public ConstructionContext {
+ const CXXCtorInitializer *I;
+
+protected:
+ explicit ConstructorInitializerConstructionContext(
+ ConstructionContext::Kind K, const CXXCtorInitializer *I)
+ : ConstructionContext(K), I(I) {
+ assert(classof(this));
+ assert(I);
+ }
+
+public:
+ const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() >= INITIALIZER_BEGIN &&
+ CC->getKind() <= INITIALIZER_END;
+ }
+};
+
+/// Represents construction into a field or a base class within a bigger object
+/// via a constructor initializer, eg. T(): field(123) { ... }.
+class SimpleConstructorInitializerConstructionContext
+ : public ConstructorInitializerConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleConstructorInitializerConstructionContext(
+ const CXXCtorInitializer *I)
+ : ConstructorInitializerConstructionContext(
+ ConstructionContext::SimpleConstructorInitializerKind, I) {}
+
+public:
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == SimpleConstructorInitializerKind;
+ }
+};
+
+/// Represents construction into a field or a base class within a bigger object
+/// via a constructor initializer, with a single constructor, eg.
+/// T(): field(Field(123)) { ... }. Such construction context may only appear
+/// in C++17 because previously it was split into a temporary object constructor
+/// and an elidable simple constructor-initializer copy-constructor and we were
+/// producing separate construction contexts for these constructors. In C++17
+/// we have a single construction context that combines both. Note that if the
+/// object has trivial destructor, then this code is indistinguishable from
+/// a simple constructor-initializer constructor on the AST level; in this case
+/// we provide a simple constructor-initializer construction context.
+class CXX17ElidedCopyConstructorInitializerConstructionContext
+ : public ConstructorInitializerConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
+ const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
+ : ConstructorInitializerConstructionContext(
+ CXX17ElidedCopyConstructorInitializerKind, I),
+ BTE(BTE) {
+ assert(BTE);
+ }
+
+public:
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
+ }
+};
+
+/// Represents immediate initialization of memory allocated by operator new,
+/// eg. new T(123);.
+class NewAllocatedObjectConstructionContext : public ConstructionContext {
+ const CXXNewExpr *NE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
+ : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
+ NE(NE) {
+ assert(NE);
+ }
+
+public:
+ const CXXNewExpr *getCXXNewExpr() const { return NE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == NewAllocatedObjectKind;
+ }
+};
+
+/// Represents a temporary object, eg. T(123), that does not immediately cross
+/// function boundaries "by value"; constructors that construct function
+/// value-type arguments or values that are immediately returned from the
+/// function that returns a value receive separate construction context kinds.
+class TemporaryObjectConstructionContext : public ConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+ const MaterializeTemporaryExpr *MTE;
+
+protected:
+ explicit TemporaryObjectConstructionContext(
+ ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
+ const MaterializeTemporaryExpr *MTE)
+ : ConstructionContext(K), BTE(BTE), MTE(MTE) {
+ // Both BTE and MTE can be null here, all combinations possible.
+ // Even though for now at least one should be non-null, we simply haven't
+ // implemented the other case yet (this would be a temporary in the middle
+ // of nowhere that doesn't have a non-trivial destructor).
+ }
+
+public:
+ /// CXXBindTemporaryExpr here is non-null as long as the temporary has
+ /// a non-trivial destructor.
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
+ return BTE;
+ }
+
+ /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
+ /// used after construction, eg. by binding to a reference (lifetime
+ /// extension), accessing a field, calling a method, or passing it into
+ /// a function (an elidable copy or move constructor would be a common
+ /// example) by reference.
+ const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
+ return MTE;
+ }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
+ }
+};
+
+/// Represents a temporary object that is not constructed for the purpose of
+/// being immediately copied/moved by an elidable copy/move-constructor.
+/// This includes temporary objects "in the middle of nowhere" like T(123) and
+/// lifetime-extended temporaries.
+class SimpleTemporaryObjectConstructionContext
+ : public TemporaryObjectConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleTemporaryObjectConstructionContext(
+ const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
+ : TemporaryObjectConstructionContext(
+ ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
+
+public:
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == SimpleTemporaryObjectKind;
+ }
+};
+
+/// Represents a temporary object that is constructed for the sole purpose
+/// of being immediately copied by an elidable copy/move constructor.
+/// For example, T t = T(123); includes a temporary T(123) that is immediately
+/// copied to variable t. In such cases the elidable copy can (but not
+/// necessarily should) be omitted ("elided") accodring to the rules of the
+/// language; the constructor would then construct variable t directly.
+/// This construction context contains information of the elidable constructor
+/// and its respective construction context.
+class ElidedTemporaryObjectConstructionContext
+ : public TemporaryObjectConstructionContext {
+ const CXXConstructExpr *ElidedCE;
+ const ConstructionContext *ElidedCC;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit ElidedTemporaryObjectConstructionContext(
+ const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
+ const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
+ : TemporaryObjectConstructionContext(
+ ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
+ ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
+ // Elided constructor and its context should be either both specified
+ // or both unspecified. In the former case, the constructor must be
+ // elidable.
+ assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
+ }
+
+public:
+ const CXXConstructExpr *getConstructorAfterElision() const {
+ return ElidedCE;
+ }
+
+ const ConstructionContext *getConstructionContextAfterElision() const {
+ return ElidedCC;
+ }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == ElidedTemporaryObjectKind;
+ }
+};
+
+class ReturnedValueConstructionContext : public ConstructionContext {
+ const ReturnStmt *RS;
+
+protected:
+ explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
+ const ReturnStmt *RS)
+ : ConstructionContext(K), RS(RS) {
+ assert(classof(this));
+ assert(RS);
+ }
+
+public:
+ const ReturnStmt *getReturnStmt() const { return RS; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() >= RETURNED_VALUE_BEGIN &&
+ CC->getKind() <= RETURNED_VALUE_END;
+ }
+};
+
+/// Represents a temporary object that is being immediately returned from a
+/// function by value, eg. return t; or return T(123);. In this case there is
+/// always going to be a constructor at the return site. However, the usual
+/// temporary-related bureaucracy (CXXBindTemporaryExpr,
+/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
+class SimpleReturnedValueConstructionContext
+ : public ReturnedValueConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
+ : ReturnedValueConstructionContext(
+ ConstructionContext::SimpleReturnedValueKind, RS) {}
+
+public:
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == SimpleReturnedValueKind;
+ }
+};
+
+/// Represents a temporary object that is being immediately returned from a
+/// function by value, eg. return t; or return T(123); in C++17.
+/// In C++17 there is not going to be an elidable copy constructor at the
+/// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
+/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
+/// Note that if the object has trivial destructor, then this code is
+/// indistinguishable from a simple returned value constructor on the AST level;
+/// in this case we provide a simple returned value construction context.
+class CXX17ElidedCopyReturnedValueConstructionContext
+ : public ReturnedValueConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit CXX17ElidedCopyReturnedValueConstructionContext(
+ const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
+ : ReturnedValueConstructionContext(
+ ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
+ BTE(BTE) {
+ assert(BTE);
+ }
+
+public:
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
+ }
+};
+
+class ArgumentConstructionContext : public ConstructionContext {
+ const Expr *CE; // The call of which the context is an argument.
+ unsigned Index; // Which argument we're constructing.
+ const CXXBindTemporaryExpr *BTE; // Whether the object needs to be destroyed.
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
+ const CXXBindTemporaryExpr *BTE)
+ : ConstructionContext(ArgumentKind), CE(CE),
+ Index(Index), BTE(BTE) {
+ assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
+ isa<ObjCMessageExpr>(CE));
+ // BTE is optional.
+ }
+
+public:
+ const Expr *getCallLikeExpr() const { return CE; }
+ unsigned getIndex() const { return Index; }
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == ArgumentKind;
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h
index 8b3fcff52d08..9326d1abbac1 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements cocoa naming convention analysis.
+// This file implements cocoa naming convention analysis.
//
//===----------------------------------------------------------------------===//
@@ -20,20 +20,20 @@
namespace clang {
class FunctionDecl;
class QualType;
-
+
namespace ento {
namespace cocoa {
-
+
bool isRefType(QualType RetTy, StringRef Prefix,
StringRef Name = StringRef());
-
+
bool isCocoaObjectRef(QualType T);
}
namespace coreFoundation {
bool isCFObjectRef(QualType T);
-
+
bool followsCreateRule(const FunctionDecl *FD);
}
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
index f9e800a4a412..e304d83615d4 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
@@ -21,7 +21,7 @@ namespace clang {
class ASTContext;
class ObjCMessageExpr;
-
+
class ObjCNoReturn {
/// Cached "raise" selector.
Selector RaiseSel;
@@ -36,7 +36,7 @@ class ObjCNoReturn {
public:
ObjCNoReturn(ASTContext &C);
-
+
/// Return true if the given message expression is known to never
/// return.
bool isImplicitNoReturn(const ObjCMessageExpr *ME);
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
index 2d59dec48a88..25ae93fae6b8 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
@@ -33,7 +33,7 @@ namespace clang {
class AnalysisDeclContext;
class FunctionDecl;
class LocationContext;
-
+
/// ProgramPoints can be "tagged" as representing points specific to a given
/// analysis entity. Tags are abstract annotations, with an associated
/// description and potentially other information.
@@ -41,12 +41,12 @@ class ProgramPointTag {
public:
ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
virtual ~ProgramPointTag();
- virtual StringRef getTagDescription() const = 0;
+ virtual StringRef getTagDescription() const = 0;
protected:
/// Used to implement 'isKind' in subclasses.
const void *getTagKind() { return TagKind; }
-
+
private:
const void *TagKind;
};
@@ -73,8 +73,9 @@ public:
PostStoreKind,
PostConditionKind,
PostLValueKind,
+ PostAllocatorCallKind,
MinPostStmtKind = PostStmtKind,
- MaxPostStmtKind = PostLValueKind,
+ MaxPostStmtKind = PostAllocatorCallKind,
PostInitializerKind,
CallEnterKind,
CallExitBeginKind,
@@ -97,7 +98,7 @@ private:
llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
protected:
- ProgramPoint() {}
+ ProgramPoint() = default;
ProgramPoint(const void *P,
Kind k,
const LocationContext *l,
@@ -110,7 +111,7 @@ protected:
assert(getLocationContext() == l);
assert(getData1() == P);
}
-
+
ProgramPoint(const void *P1,
const void *P2,
Kind k,
@@ -134,7 +135,7 @@ public:
getLocationContext(), tag);
}
- /// \brief Convert to the specified ProgramPoint type, asserting that this
+ /// Convert to the specified ProgramPoint type, asserting that this
/// ProgramPoint is of the desired type.
template<typename T>
T castAs() const {
@@ -145,7 +146,7 @@ public:
return t;
}
- /// \brief Convert to the specified ProgramPoint type, returning None if this
+ /// Convert to the specified ProgramPoint type, returning None if this
/// ProgramPoint is not of the desired type.
template<typename T>
Optional<T> getAs() const {
@@ -166,7 +167,7 @@ public:
return (Kind) x;
}
- /// \brief Is this a program point corresponding to purge/removal of dead
+ /// Is this a program point corresponding to purge/removal of dead
/// symbols and bindings.
bool isPurgeKind() {
Kind K = getKind();
@@ -180,6 +181,10 @@ public:
return L.getPointer();
}
+ const StackFrameContext *getStackFrame() const {
+ return getLocationContext()->getStackFrame();
+ }
+
// For use with DenseMap. This hash is probably slow.
unsigned getHashValue() const {
llvm::FoldingSetNodeID ID;
@@ -218,7 +223,7 @@ class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock *B, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
- : ProgramPoint(B, BlockEntranceKind, L, tag) {
+ : ProgramPoint(B, BlockEntranceKind, L, tag) {
assert(B && "BlockEntrance requires non-null block");
}
@@ -230,10 +235,10 @@ public:
const CFGBlock *B = getBlock();
return B->empty() ? Optional<CFGElement>() : B->front();
}
-
+
private:
friend class ProgramPoint;
- BlockEntrance() {}
+ BlockEntrance() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == BlockEntranceKind;
}
@@ -254,7 +259,7 @@ public:
private:
friend class ProgramPoint;
- BlockExit() {}
+ BlockExit() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == BlockExitKind;
}
@@ -274,7 +279,7 @@ public:
const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
protected:
- StmtPoint() {}
+ StmtPoint() = default;
private:
friend class ProgramPoint;
static bool isKind(const ProgramPoint &Location) {
@@ -294,7 +299,7 @@ public:
private:
friend class ProgramPoint;
- PreStmt() {}
+ PreStmt() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PreStmtKind;
}
@@ -302,7 +307,7 @@ private:
class PostStmt : public StmtPoint {
protected:
- PostStmt() {}
+ PostStmt() = default;
PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, data, k, L, tag) {}
@@ -333,7 +338,7 @@ public:
private:
friend class ProgramPoint;
- PostCondition() {}
+ PostCondition() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostConditionKind;
}
@@ -341,11 +346,11 @@ private:
class LocationCheck : public StmtPoint {
protected:
- LocationCheck() {}
+ LocationCheck() = default;
LocationCheck(const Stmt *S, const LocationContext *L,
ProgramPoint::Kind K, const ProgramPointTag *tag)
: StmtPoint(S, nullptr, K, L, tag) {}
-
+
private:
friend class ProgramPoint;
static bool isKind(const ProgramPoint &location) {
@@ -353,16 +358,16 @@ private:
return k == PreLoadKind || k == PreStoreKind;
}
};
-
+
class PreLoad : public LocationCheck {
public:
PreLoad(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreLoadKind, tag) {}
-
+
private:
friend class ProgramPoint;
- PreLoad() {}
+ PreLoad() = default;
static bool isKind(const ProgramPoint &location) {
return location.getKind() == PreLoadKind;
}
@@ -373,10 +378,10 @@ public:
PreStore(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreStoreKind, tag) {}
-
+
private:
friend class ProgramPoint;
- PreStore() {}
+ PreStore() = default;
static bool isKind(const ProgramPoint &location) {
return location.getKind() == PreStoreKind;
}
@@ -390,17 +395,17 @@ public:
private:
friend class ProgramPoint;
- PostLoad() {}
+ PostLoad() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostLoadKind;
}
};
-/// \brief Represents a program point after a store evaluation.
+/// Represents a program point after a store evaluation.
class PostStore : public PostStmt {
public:
/// Construct the post store point.
- /// \param Loc can be used to store the information about the location
+ /// \param Loc can be used to store the information about the location
/// used in the form it was uttered in the code.
PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
const ProgramPointTag *tag = nullptr)
@@ -409,7 +414,7 @@ public:
setData2(Loc);
}
- /// \brief Returns the information about the location used in the store,
+ /// Returns the information about the location used in the store,
/// how it was uttered in the code.
const void *getLocationValue() const {
return getData2();
@@ -417,7 +422,7 @@ public:
private:
friend class ProgramPoint;
- PostStore() {}
+ PostStore() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostStoreKind;
}
@@ -431,7 +436,7 @@ public:
private:
friend class ProgramPoint;
- PostLValue() {}
+ PostLValue() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostLValueKind;
}
@@ -447,7 +452,7 @@ public:
private:
friend class ProgramPoint;
- PreStmtPurgeDeadSymbols() {}
+ PreStmtPurgeDeadSymbols() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
}
@@ -463,7 +468,7 @@ public:
private:
friend class ProgramPoint;
- PostStmtPurgeDeadSymbols() {}
+ PostStmtPurgeDeadSymbols() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
}
@@ -474,7 +479,7 @@ public:
BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {
assert(B1 && "BlockEdge: source block must be non-null");
- assert(B2 && "BlockEdge: destination block must be non-null");
+ assert(B2 && "BlockEdge: destination block must be non-null");
}
const CFGBlock *getSrc() const {
@@ -487,7 +492,7 @@ public:
private:
friend class ProgramPoint;
- BlockEdge() {}
+ BlockEdge() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == BlockEdgeKind;
}
@@ -495,7 +500,7 @@ private:
class PostInitializer : public ProgramPoint {
public:
- /// \brief Construct a PostInitializer point that represents a location after
+ /// Construct a PostInitializer point that represents a location after
/// CXXCtorInitializer expression evaluation.
///
/// \param I The initializer.
@@ -509,14 +514,14 @@ public:
return static_cast<const CXXCtorInitializer *>(getData1());
}
- /// \brief Returns the location of the field.
+ /// Returns the location of the field.
const void *getLocationValue() const {
return getData2();
}
private:
friend class ProgramPoint;
- PostInitializer() {}
+ PostInitializer() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostInitializerKind;
}
@@ -537,7 +542,7 @@ public:
}
protected:
- ImplicitCallPoint() {}
+ ImplicitCallPoint() = default;
private:
friend class ProgramPoint;
static bool isKind(const ProgramPoint &Location) {
@@ -557,7 +562,7 @@ public:
private:
friend class ProgramPoint;
- PreImplicitCall() {}
+ PreImplicitCall() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PreImplicitCallKind;
}
@@ -574,17 +579,31 @@ public:
private:
friend class ProgramPoint;
- PostImplicitCall() {}
+ PostImplicitCall() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostImplicitCallKind;
}
};
+class PostAllocatorCall : public StmtPoint {
+public:
+ PostAllocatorCall(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *Tag = nullptr)
+ : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
+
+private:
+ friend class ProgramPoint;
+ PostAllocatorCall() = default;
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostAllocatorCallKind;
+ }
+};
+
/// Represents a point when we begin processing an inlined call.
/// CallEnter uses the caller's location context.
class CallEnter : public ProgramPoint {
public:
- CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
+ CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
const LocationContext *callerCtx)
: ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
@@ -605,7 +624,7 @@ public:
private:
friend class ProgramPoint;
- CallEnter() {}
+ CallEnter() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == CallEnterKind;
}
@@ -626,9 +645,13 @@ public:
CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS)
: ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
+ const ReturnStmt *getReturnStmt() const {
+ return static_cast<const ReturnStmt *>(getData1());
+ }
+
private:
friend class ProgramPoint;
- CallExitBegin() {}
+ CallExitBegin() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == CallExitBeginKind;
}
@@ -649,7 +672,7 @@ public:
private:
friend class ProgramPoint;
- CallExitEnd() {}
+ CallExitEnd() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == CallExitEndKind;
}
@@ -672,7 +695,7 @@ public:
private:
friend class ProgramPoint;
- LoopExit() {}
+ LoopExit() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == LoopExitKind;
}
@@ -691,7 +714,7 @@ public:
private:
friend class ProgramPoint;
- EpsilonPoint() {}
+ EpsilonPoint() = default;
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == EpsilonKind;
}
@@ -726,7 +749,7 @@ static bool isEqual(const clang::ProgramPoint &L,
}
};
-
+
template <>
struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
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 5940520855ef..00a7417e20f9 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
@@ -29,7 +29,7 @@
#include <type_traits>
namespace clang {
-
+
class BumpVectorContext {
llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;
@@ -47,15 +47,15 @@ public:
/// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the
/// BumpVectorContext object is destroyed.
BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {}
-
+
~BumpVectorContext() {
if (Alloc.getInt())
delete Alloc.getPointer();
}
-
+
llvm::BumpPtrAllocator &getAllocator() { return *Alloc.getPointer(); }
};
-
+
template<typename T>
class BumpVector {
T *Begin = nullptr;
@@ -67,34 +67,34 @@ public:
explicit BumpVector(BumpVectorContext &C, unsigned N) {
reserve(C, N);
}
-
+
~BumpVector() {
if (std::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
}
-
+
using size_type = size_t;
using difference_type = ptrdiff_t;
using value_type = T;
using iterator = T *;
using const_iterator = const T *;
-
+
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = std::reverse_iterator<iterator>;
-
+
using reference = T &;
using const_reference = const T &;
using pointer = T *;
using const_pointer = const T *;
-
+
// forward iterator creation methods.
iterator begin() { return Begin; }
const_iterator begin() const { return Begin; }
iterator end() { return End; }
const_iterator end() const { return End; }
-
+
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
@@ -102,7 +102,7 @@ public:
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
-
+
bool empty() const { return Begin == End; }
size_type size() const { return End-Begin; }
@@ -114,49 +114,49 @@ public:
assert(Begin + idx < End);
return Begin[idx];
}
-
+
reference front() {
return begin()[0];
}
const_reference front() const {
return begin()[0];
}
-
+
reference back() {
return end()[-1];
}
const_reference back() const {
return end()[-1];
}
-
+
void pop_back() {
--End;
End->~T();
}
-
+
T pop_back_val() {
T Result = back();
pop_back();
return Result;
}
-
+
void clear() {
if (std::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
}
-
+
/// data - Return a pointer to the vector's buffer, even if empty().
pointer data() {
return pointer(Begin);
}
-
+
/// data - Return a pointer to the vector's buffer, even if empty().
const_pointer data() const {
return const_pointer(Begin);
}
-
+
void push_back(const_reference Elt, BumpVectorContext &C) {
if (End < Capacity) {
Retry:
@@ -165,7 +165,7 @@ public:
return;
}
grow(C);
- goto Retry;
+ goto Retry;
}
/// insert - Insert some number of copies of element into a position. Return
@@ -193,18 +193,18 @@ public:
/// capacity - Return the total number of elements in the currently allocated
/// buffer.
- size_t capacity() const { return Capacity - Begin; }
-
+ size_t capacity() const { return Capacity - Begin; }
+
private:
/// grow - double the size of the allocated memory, guaranteeing space for at
/// least one more element or MinSize if specified.
void grow(BumpVectorContext &C, size_type MinSize = 1);
-
+
void construct_range(T *S, T *E, const T &Elt) {
for (; S != E; ++S)
new (S) T(Elt);
}
-
+
void destroy_range(T *S, T *E) {
while (S != E) {
--E;
@@ -220,7 +220,7 @@ private:
}
}
};
-
+
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T>
void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
@@ -232,7 +232,7 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
// Allocate the memory from the BumpPtrAllocator.
T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity);
-
+
// Copy the elements over.
if (Begin != End) {
if (std::is_class<T>::value) {
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ABI.h b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h
index 75e9faf4617e..dc0e49cded63 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/ABI.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Enums/classes describing ABI related information about constructors,
+/// Enums/classes describing ABI related information about constructors,
/// destructors and thunks.
///
//===----------------------------------------------------------------------===//
@@ -21,7 +21,7 @@
namespace clang {
-/// \brief C++ constructor types.
+/// C++ constructor types.
enum CXXCtorType {
Ctor_Complete, ///< Complete object ctor
Ctor_Base, ///< Base object ctor
@@ -30,7 +30,7 @@ enum CXXCtorType {
Ctor_DefaultClosure, ///< Default closure variant of a ctor
};
-/// \brief C++ destructor types.
+/// C++ destructor types.
enum CXXDtorType {
Dtor_Deleting, ///< Deleting dtor
Dtor_Complete, ///< Complete object dtor
@@ -38,29 +38,29 @@ enum CXXDtorType {
Dtor_Comdat ///< The COMDAT used for dtors
};
-/// \brief A return adjustment.
+/// A return adjustment.
struct ReturnAdjustment {
- /// \brief The non-virtual adjustment from the derived object to its
+ /// The non-virtual adjustment from the derived object to its
/// nearest virtual base.
int64_t NonVirtual;
- /// \brief Holds the ABI-specific information about the virtual return
+ /// Holds the ABI-specific information about the virtual return
/// adjustment, if needed.
union VirtualAdjustment {
// Itanium ABI
struct {
- /// \brief The offset (in bytes), relative to the address point
+ /// The offset (in bytes), relative to the address point
/// of the virtual base class offset.
int64_t VBaseOffsetOffset;
} Itanium;
// Microsoft ABI
struct {
- /// \brief The offset (in bytes) of the vbptr, relative to the beginning
+ /// The offset (in bytes) of the vbptr, relative to the beginning
/// of the derived class.
uint32_t VBPtrOffset;
- /// \brief Index of the virtual base in the vbtable.
+ /// Index of the virtual base in the vbtable.
uint32_t VBIndex;
} Microsoft;
@@ -81,12 +81,12 @@ struct ReturnAdjustment {
return memcmp(this, &RHS, sizeof(RHS)) < 0;
}
} Virtual;
-
+
ReturnAdjustment() : NonVirtual(0) {}
-
+
bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
- friend bool operator==(const ReturnAdjustment &LHS,
+ friend bool operator==(const ReturnAdjustment &LHS,
const ReturnAdjustment &RHS) {
return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
}
@@ -103,32 +103,32 @@ struct ReturnAdjustment {
return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
}
};
-
-/// \brief A \c this pointer adjustment.
+
+/// A \c this pointer adjustment.
struct ThisAdjustment {
- /// \brief The non-virtual adjustment from the derived object to its
+ /// The non-virtual adjustment from the derived object to its
/// nearest virtual base.
int64_t NonVirtual;
- /// \brief Holds the ABI-specific information about the virtual this
+ /// Holds the ABI-specific information about the virtual this
/// adjustment, if needed.
union VirtualAdjustment {
// Itanium ABI
struct {
- /// \brief The offset (in bytes), relative to the address point,
+ /// The offset (in bytes), relative to the address point,
/// of the virtual call offset.
int64_t VCallOffsetOffset;
} Itanium;
struct {
- /// \brief The offset of the vtordisp (in bytes), relative to the ECX.
+ /// The offset of the vtordisp (in bytes), relative to the ECX.
int32_t VtordispOffset;
- /// \brief The offset of the vbptr of the derived class (in bytes),
+ /// The offset of the vbptr of the derived class (in bytes),
/// relative to the ECX after vtordisp adjustment.
int32_t VBPtrOffset;
- /// \brief The offset (in bytes) of the vbase offset in the vbtable.
+ /// The offset (in bytes) of the vbase offset in the vbtable.
int32_t VBOffsetOffset;
} Microsoft;
@@ -149,12 +149,12 @@ struct ThisAdjustment {
return memcmp(this, &RHS, sizeof(RHS)) < 0;
}
} Virtual;
-
+
ThisAdjustment() : NonVirtual(0) { }
bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
- friend bool operator==(const ThisAdjustment &LHS,
+ friend bool operator==(const ThisAdjustment &LHS,
const ThisAdjustment &RHS) {
return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
}
@@ -162,28 +162,28 @@ struct ThisAdjustment {
friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
return !(LHS == RHS);
}
-
+
friend bool operator<(const ThisAdjustment &LHS,
const ThisAdjustment &RHS) {
if (LHS.NonVirtual < RHS.NonVirtual)
return true;
-
+
return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
}
};
class CXXMethodDecl;
-/// \brief The \c this pointer adjustment as well as an optional return
+/// The \c this pointer adjustment as well as an optional return
/// adjustment for a thunk.
struct ThunkInfo {
- /// \brief The \c this pointer adjustment.
+ /// The \c this pointer adjustment.
ThisAdjustment This;
-
- /// \brief The return adjustment.
+
+ /// The return adjustment.
ReturnAdjustment Return;
- /// \brief Holds a pointer to the overridden method this thunk is for,
+ /// Holds a pointer to the overridden method this thunk is for,
/// if needed by the ABI to distinguish different thunks with equal
/// adjustments. Otherwise, null.
/// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
@@ -204,7 +204,7 @@ struct ThunkInfo {
bool isEmpty() const {
return This.isEmpty() && Return.isEmpty() && Method == nullptr;
}
-};
+};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
index 6b0090813e9b..217fbd763ff2 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
@@ -1,4 +1,4 @@
-//===--- AddressSpaces.h - Language-specific address spaces -----*- C++ -*-===//
+//===- AddressSpaces.h - Language-specific address spaces -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,25 +6,25 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Provides definitions for the various language-specific address
+/// Provides definitions for the various language-specific address
/// spaces.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H
#define LLVM_CLANG_BASIC_ADDRESSSPACES_H
-#include <assert.h>
+#include <cassert>
namespace clang {
-/// \brief Defines the address space values used by the address space qualifier
+/// Defines the address space values used by the address space qualifier
/// of QualType.
///
enum class LangAS : unsigned {
- // The default value 0 is the value used in QualType for the the situation
+ // The default value 0 is the value used in QualType for the situation
// where there is no address space qualifier.
Default = 0,
@@ -51,7 +51,7 @@ enum class LangAS : unsigned {
/// The type of a lookup table which maps from language-specific address spaces
/// to target-specific ones.
-typedef unsigned LangASMap[(unsigned)LangAS::FirstTargetAddressSpace];
+using LangASMap = unsigned[(unsigned)LangAS::FirstTargetAddressSpace];
/// \return whether \p AS is a target-specific address space rather than a
/// clang AST address space
@@ -71,4 +71,4 @@ inline LangAS getLangASFromTargetAS(unsigned TargetAS) {
} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_ADDRESSSPACES_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h b/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h
index b3496949f39a..9751f4118447 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines a function that returns the minimum OS versions supporting
+/// Defines a function that returns the minimum OS versions supporting
/// C++17's aligned allocation functions.
///
//===----------------------------------------------------------------------===//
@@ -16,24 +16,24 @@
#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"
+#include "llvm/Support/VersionTuple.h"
namespace clang {
-inline VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) {
+inline llvm::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);
+ return llvm::VersionTuple(10U, 13U);
case llvm::Triple::IOS:
case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0.
- return VersionTuple(11U);
+ return llvm::VersionTuple(11U);
case llvm::Triple::WatchOS: // Earliest supporting version is 4.0.0.
- return VersionTuple(4U);
+ return llvm::VersionTuple(4U);
}
llvm_unreachable("Unexpected OS");
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
index 1c83e2d0f8a0..afec2d7e0f2f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Includes all the separate Diagnostic headers & some related helpers.
+/// Includes all the separate Diagnostic headers & some related helpers.
///
//===----------------------------------------------------------------------===//
@@ -34,9 +34,9 @@ class StringSizerHelper {
public:
enum { Size = SizeOfStr };
};
-} // end namespace clang
+} // end namespace clang
#define STR_SIZE(str, fieldTy) clang::StringSizerHelper<sizeof(str)-1, \
- fieldTy>::Size
+ fieldTy>::Size
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
index 59f595e03c34..1f17819dba74 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
@@ -83,6 +83,9 @@ def LocalVar : SubsetSubject<Var,
def NonParmVar : SubsetSubject<Var,
[{S->getKind() != Decl::ParmVar}],
"variables">;
+def NonLocalVar : SubsetSubject<Var,
+ [{!S->hasLocalStorage()}],
+ "variables with non-local storage">;
def NonBitField : SubsetSubject<Field,
[{!S->isBitField()}],
"non-bit-field non-static data members">;
@@ -111,6 +114,9 @@ def SharedVar : SubsetSubject<Var,
def GlobalVar : SubsetSubject<Var,
[{S->hasGlobalStorage()}], "global variables">;
+def InlineFunction : SubsetSubject<Function,
+ [{S->isInlineSpecified()}], "inline functions">;
+
// FIXME: this hack is needed because DeclNodes.td defines the base Decl node
// type to be a class, not a definition. This makes it impossible to create an
// attribute subject which accepts a Decl. Normally, this is not a problem,
@@ -135,6 +141,13 @@ def HasFunctionProto : SubsetSubject<DeclBase,
isa<BlockDecl>(S)}],
"non-K&R-style functions">;
+// A subject that matches the implicit object parameter of a non-static member
+// function. Accepted as a function type attribute on the type of such a
+// member function.
+// FIXME: This does not actually ever match currently.
+def ImplicitObjectParameter : SubsetSubject<Function, [{false}],
+ "implicit object parameters">;
+
// A single argument to an attribute
class Argument<string name, bit optional, bit fake = 0> {
string Name = name;
@@ -162,6 +175,13 @@ class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
class VariadicExprArgument<string name> : Argument<name, 1>;
class VariadicStringArgument<string name> : Argument<name, 1>;
+class VariadicIdentifierArgument<string name> : Argument<name, 1>;
+
+// Like VariadicUnsignedArgument except values are ParamIdx.
+class VariadicParamIdxArgument<string name> : Argument<name, 1>;
+
+// Like VariadicParamIdxArgument but for a single function parameter index.
+class ParamIdxArgument<string name, bit opt = 0> : Argument<name, opt>;
// A version of the form major.minor[.subminor].
class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
@@ -172,7 +192,8 @@ class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
class AlignedArgument<string name, bit opt = 0> : Argument<name, opt>;
// A bool argument with a default value
-class DefaultBoolArgument<string name, bit default> : BoolArgument<name, 1> {
+class DefaultBoolArgument<string name, bit default, bit fake = 0>
+ : BoolArgument<name, 1, fake> {
bit Default = default;
}
@@ -231,9 +252,12 @@ 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">;
+// The Clang spelling implies GNU<name>, CXX11<"clang", name>, and optionally,
+// C2x<"clang", name>. This spelling should be used for any Clang-specific
+// attributes.
+class Clang<string name, bit allowInC = 1> : Spelling<name, "Clang"> {
+ bit AllowInC = allowInC;
+}
class Accessor<string name, list<Spelling> spellings> {
string Name = name;
@@ -291,6 +315,7 @@ def TargetAVR : TargetArch<["avr"]>;
def TargetMips32 : TargetArch<["mips", "mipsel"]>;
def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>;
def TargetMSP430 : TargetArch<["msp430"]>;
+def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
def TargetX86 : TargetArch<["x86"]>;
def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
@@ -438,10 +463,7 @@ class Attr {
// Set to true if all of the attribute's arguments should be parsed in an
// unevaluated context.
bit ParseArgumentsAsUnevaluated = 0;
- // Set to true if this attribute can be duplicated on a subject when merging
- // attributes. By default, attributes are not merged.
- bit DuplicatesAllowedWhileMerging = 0;
- // Set to true if this attribute meaningful when applied to or inherited
+ // Set to true if this attribute meaningful when applied to or inherited
// in a class template definition.
bit MeaningfulToClassTemplateDefinition = 0;
// Set to true if this attribute can be used with '#pragma clang attribute'.
@@ -475,7 +497,16 @@ class TypeAttr : Attr {
class StmtAttr : Attr;
/// An inheritable attribute is inherited by later redeclarations.
-class InheritableAttr : Attr;
+class InheritableAttr : Attr {
+ // Set to true if this attribute can be duplicated on a subject when inheriting
+ // attributes from prior declarations.
+ bit InheritEvenIfAlreadyPresent = 0;
+}
+
+/// Some attributes, like calling conventions, can appear in either the
+/// declaration or the type position. These attributes are morally type
+/// attributes, but have historically been written on declarations.
+class DeclOrTypeAttr : InheritableAttr;
/// A target-specific attribute. This class is meant to be used as a mixin
/// with InheritableAttr or Attr depending on the attribute's needs.
@@ -487,7 +518,7 @@ class TargetSpecificAttr<TargetSpec target> {
// "exists" for a given target. So two target-specific attributes can share
// the same name when they exist in different targets. To support this, a
// Kind can be explicitly specified for a target-specific attribute. This
- // corresponds to the AttributeList::AT_* enum that is generated and it
+ // corresponds to the ParsedAttr::AT_* enum that is generated and it
// should contain a shared value between the attributes.
//
// Target-specific attributes which use this feature should ensure that the
@@ -549,7 +580,6 @@ def Aligned : InheritableAttr {
Keyword<"_Alignas">]>,
Accessor<"isDeclspec",[Declspec<"align">]>];
let Documentation = [Undocumented];
- let DuplicatesAllowedWhileMerging = 1;
}
def AlignValue : Attr {
@@ -560,7 +590,7 @@ 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">
@@ -585,6 +615,12 @@ def AlwaysInline : InheritableAttr {
let Documentation = [Undocumented];
}
+def Artificial : InheritableAttr {
+ let Spellings = [GCC<"artificial">];
+ let Subjects = SubjectList<[InlineFunction], WarnDiag>;
+ let Documentation = [ArtificialDocs];
+}
+
def XRayInstrument : InheritableAttr {
let Spellings = [Clang<"xray_always_instrument">,
Clang<"xray_never_instrument">];
@@ -599,6 +635,12 @@ def XRayInstrument : InheritableAttr {
def XRayLogArgs : InheritableAttr {
let Spellings = [Clang<"xray_log_args">];
let Subjects = SubjectList<[Function, ObjCMethod]>;
+ // This argument is a count not an index, so it has the same encoding (base
+ // 1 including C++ implicit this parameter) at the source and LLVM levels of
+ // representation, so ParamIdxArgument is inappropriate. It is never used
+ // at the AST level of representation, so it never needs to be adjusted not
+ // to include any C++ implicit this parameter. Thus, we just store it and
+ // use it as an unsigned that never needs adjustment.
let Args = [UnsignedArgument<"ArgumentCount">];
let Documentation = [XRayDocs];
}
@@ -661,9 +703,7 @@ def AsmLabel : InheritableAttr {
}
def Availability : InheritableAttr {
- // TODO: does not have a [[]] spelling because it requires custom parsing
- // support.
- let Spellings = [GNU<"availability">];
+ let Spellings = [Clang<"availability">];
let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">,
VersionArgument<"deprecated">, VersionArgument<"obsoleted">,
BoolArgument<"unavailable">, StringArgument<"message">,
@@ -707,7 +747,7 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
.Default(Platform);
} }];
let HasCustomParsing = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Named]>;
let Documentation = [AvailabilityDocs];
}
@@ -740,7 +780,7 @@ def CarriesDependency : InheritableParamAttr {
let Documentation = [CarriesDependencyDocs];
}
-def CDecl : InheritableAttr {
+def CDecl : DeclOrTypeAttr {
let Spellings = [GCC<"cdecl">, Keyword<"__cdecl">, Keyword<"_cdecl">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
@@ -814,6 +854,27 @@ def Constructor : InheritableAttr {
let Documentation = [Undocumented];
}
+def CPUSpecific : InheritableAttr {
+ let Spellings = [Clang<"cpu_specific">];
+ let Args = [VariadicIdentifierArgument<"Cpus">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [CPUSpecificCPUDispatchDocs];
+ let AdditionalMembers = [{
+ unsigned ActiveArgIndex = 0;
+
+ IdentifierInfo *getCurCPUName() const {
+ return *(cpus_begin() + ActiveArgIndex);
+ }
+ }];
+}
+
+def CPUDispatch : InheritableAttr {
+ let Spellings = [Clang<"cpu_dispatch">];
+ let Args = [VariadicIdentifierArgument<"Cpus">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [CPUSpecificCPUDispatchDocs];
+}
+
// CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__),
// and they do not receive a [[]] spelling.
def CUDAConstant : InheritableAttr {
@@ -1008,7 +1069,8 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
def AllocSize : InheritableAttr {
let Spellings = [GCC<"alloc_size">];
let Subjects = SubjectList<[Function]>;
- let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>];
+ let Args = [ParamIdxArgument<"ElemSizeParam">,
+ ParamIdxArgument<"NumElemsParam", /*opt*/ 1>];
let TemplateDependent = 1;
let Documentation = [AllocSizeDocs];
}
@@ -1040,14 +1102,14 @@ def FallThrough : StmtAttr {
let Documentation = [FallthroughDocs];
}
-def FastCall : InheritableAttr {
+def FastCall : DeclOrTypeAttr {
let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
Keyword<"_fastcall">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [FastCallDocs];
}
-def RegCall : InheritableAttr {
+def RegCall : DeclOrTypeAttr {
let Spellings = [GCC<"regcall">, Keyword<"__regcall">];
let Documentation = [RegCallDocs];
}
@@ -1095,7 +1157,7 @@ def Format : InheritableAttr {
def FormatArg : InheritableAttr {
let Spellings = [GCC<"format_arg">];
- let Args = [IntArgument<"FormatIdx">];
+ let Args = [ParamIdxArgument<"FormatIdx">];
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto]>;
let Documentation = [Undocumented];
}
@@ -1156,6 +1218,22 @@ def LayoutVersion : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Documentation = [LayoutVersionDocs];
}
+def LifetimeBound : InheritableAttr {
+ let Spellings = [Clang<"lifetimebound", 0>];
+ let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
+ let Documentation = [LifetimeBoundDocs];
+ let LangOpts = [CPlusPlus];
+}
+
+def TrivialABI : InheritableAttr {
+ // This attribute does not have a C [[]] spelling because it requires the
+ // CPlusPlus language option.
+ let Spellings = [Clang<"trivial_abi", 0>];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let Documentation = [TrivialABIDocs];
+ let LangOpts = [CPlusPlus];
+}
+
def MaxFieldAlignment : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
@@ -1170,7 +1248,7 @@ def MayAlias : InheritableAttr {
let Documentation = [Undocumented];
}
-def MSABI : InheritableAttr {
+def MSABI : DeclOrTypeAttr {
let Spellings = [GCC<"ms_abi">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [MSABIDocs];
@@ -1311,6 +1389,17 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Documentation = [MicroMipsDocs];
}
+def RISCVInterrupt : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [GCC<"interrupt">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [EnumArgument<"Interrupt", "InterruptType",
+ ["user", "supervisor", "machine"],
+ ["user", "supervisor", "machine"],
+ 1>];
+ let ParseKind = "Interrupt";
+ let Documentation = [RISCVInterruptDocs];
+}
+
// This is not a TargetSpecificAttr so that is silently accepted and
// ignored on other targets as encouraged by the OpenCL spec.
//
@@ -1329,28 +1418,28 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> {
// this should be rejected on non-kernels.
def AMDGPUFlatWorkGroupSize : InheritableAttr {
- let Spellings = [Clang<"amdgpu_flat_work_group_size">];
+ let Spellings = [Clang<"amdgpu_flat_work_group_size", 0>];
let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max">];
let Documentation = [AMDGPUFlatWorkGroupSizeDocs];
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUWavesPerEU : InheritableAttr {
- let Spellings = [Clang<"amdgpu_waves_per_eu">];
+ let Spellings = [Clang<"amdgpu_waves_per_eu", 0>];
let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max", 1>];
let Documentation = [AMDGPUWavesPerEUDocs];
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUNumSGPR : InheritableAttr {
- let Spellings = [Clang<"amdgpu_num_sgpr">];
+ let Spellings = [Clang<"amdgpu_num_sgpr", 0>];
let Args = [UnsignedArgument<"NumSGPR">];
let Documentation = [AMDGPUNumSGPRNumVGPRDocs];
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUNumVGPR : InheritableAttr {
- let Spellings = [Clang<"amdgpu_num_vgpr">];
+ let Spellings = [Clang<"amdgpu_num_vgpr", 0>];
let Args = [UnsignedArgument<"NumVGPR">];
let Documentation = [AMDGPUNumSGPRNumVGPRDocs];
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
@@ -1366,18 +1455,18 @@ def NonNull : InheritableParamAttr {
let Spellings = [GCC<"nonnull">];
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
"functions, methods, and parameters">;
- let Args = [VariadicUnsignedArgument<"Args">];
- let AdditionalMembers =
-[{bool isNonNull(unsigned idx) const {
- if (!args_size())
- return true;
- for (const auto &V : args())
- if (V == idx)
+ let Args = [VariadicParamIdxArgument<"Args">];
+ let AdditionalMembers = [{
+ bool isNonNull(unsigned IdxAST) const {
+ if (!args_size())
return true;
- return false;
- } }];
+ return args_end() != std::find_if(
+ args_begin(), args_end(),
+ [=](const ParamIdx &Idx) { return Idx.getASTIndex() == IdxAST; });
+ }
+ }];
// FIXME: We should merge duplicates into a single nonnull attribute.
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Documentation = [NonNullDocs];
}
@@ -1433,7 +1522,7 @@ def AssumeAligned : InheritableAttr {
def AllocAlign : InheritableAttr {
let Spellings = [GCC<"alloc_align">];
let Subjects = SubjectList<[HasFunctionProto]>;
- let Args = [IntArgument<"ParamIndex">];
+ let Args = [ParamIdxArgument<"ParamIndex">];
let Documentation = [AllocAlignDocs];
}
@@ -1455,6 +1544,12 @@ def NotTailCalled : InheritableAttr {
let Documentation = [NotTailCalledDocs];
}
+def NoStackProtector : InheritableAttr {
+ let Spellings = [Clang<"no_stack_protector">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NoStackProtectorDocs];
+}
+
def NoThrow : InheritableAttr {
let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
let Subjects = SubjectList<[Function]>;
@@ -1484,13 +1579,11 @@ def ObjCBridgeMutable : InheritableAttr {
}
def ObjCBridgeRelated : InheritableAttr {
- // TODO: this attribute does not have a [[]] spelling because it requires
- // custom parsing support.
- let Spellings = [GNU<"objc_bridge_related">];
+ let Spellings = [Clang<"objc_bridge_related">];
let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"RelatedClass">,
- IdentifierArgument<"ClassMethod", 1>,
- IdentifierArgument<"InstanceMethod", 1>];
+ IdentifierArgument<"ClassMethod">,
+ IdentifierArgument<"InstanceMethod">];
let HasCustomParsing = 1;
let Documentation = [Undocumented];
}
@@ -1624,7 +1717,7 @@ def Overloadable : Attr {
let Documentation = [OverloadableDocs];
}
-def Override : InheritableAttr {
+def Override : InheritableAttr {
let Spellings = [Keyword<"override">];
let SemaHandler = 0;
let Documentation = [Undocumented];
@@ -1644,7 +1737,8 @@ def Ownership : InheritableAttr {
Returns;
}
}];
- let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">];
+ let Args = [IdentifierArgument<"Module">,
+ VariadicParamIdxArgument<"Args">];
let Subjects = SubjectList<[HasFunctionProto]>;
let Documentation = [Undocumented];
}
@@ -1655,13 +1749,13 @@ def Packed : InheritableAttr {
let Documentation = [Undocumented];
}
-def IntelOclBicc : InheritableAttr {
- let Spellings = [Clang<"intel_ocl_bicc">];
+def IntelOclBicc : DeclOrTypeAttr {
+ let Spellings = [Clang<"intel_ocl_bicc", 0>];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
}
-def Pcs : InheritableAttr {
+def Pcs : DeclOrTypeAttr {
let Spellings = [GCC<"pcs">];
let Args = [EnumArgument<"PCS", "PCSType",
["aapcs", "aapcs-vfp"],
@@ -1691,7 +1785,9 @@ def ReqdWorkGroupSize : InheritableAttr {
}
def RequireConstantInit : InheritableAttr {
- let Spellings = [Clang<"require_constant_initialization">];
+ // This attribute does not have a C [[]] spelling because it requires the
+ // CPlusPlus language option.
+ let Spellings = [Clang<"require_constant_initialization", 0>];
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [RequireConstantInitDocs];
let LangOpts = [CPlusPlus];
@@ -1700,7 +1796,7 @@ def RequireConstantInit : InheritableAttr {
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">,
+ let Args = [UnsignedArgument<"XDim">,
UnsignedArgument<"YDim">,
UnsignedArgument<"ZDim">];
let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -1722,6 +1818,13 @@ def Section : InheritableAttr {
let Documentation = [SectionDocs];
}
+def CodeSeg : InheritableAttr {
+ let Spellings = [Declspec<"code_seg">];
+ let Args = [StringArgument<"Name">];
+ let Subjects = SubjectList<[Function, CXXRecord], ErrorDiag>;
+ let Documentation = [CodeSegDocs];
+}
+
def PragmaClangBSSSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
@@ -1762,13 +1865,13 @@ def Sentinel : InheritableAttr {
let Documentation = [Undocumented];
}
-def StdCall : InheritableAttr {
+def StdCall : DeclOrTypeAttr {
let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [StdCallDocs];
}
-def SwiftCall : InheritableAttr {
+def SwiftCall : DeclOrTypeAttr {
let Spellings = [Clang<"swiftcall">];
// let Subjects = SubjectList<[Function]>;
let Documentation = [SwiftCallDocs];
@@ -1795,38 +1898,38 @@ def Suppress : StmtAttr {
let Documentation = [SuppressDocs];
}
-def SysVABI : InheritableAttr {
+def SysVABI : DeclOrTypeAttr {
let Spellings = [GCC<"sysv_abi">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
}
-def ThisCall : InheritableAttr {
+def ThisCall : DeclOrTypeAttr {
let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">,
Keyword<"_thiscall">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [ThisCallDocs];
}
-def VectorCall : InheritableAttr {
+def VectorCall : DeclOrTypeAttr {
let Spellings = [Clang<"vectorcall">, Keyword<"__vectorcall">,
Keyword<"_vectorcall">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [VectorCallDocs];
}
-def Pascal : InheritableAttr {
+def Pascal : DeclOrTypeAttr {
let Spellings = [Clang<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
}
-def PreserveMost : InheritableAttr {
+def PreserveMost : DeclOrTypeAttr {
let Spellings = [Clang<"preserve_most">];
let Documentation = [PreserveMostDocs];
}
-def PreserveAll : InheritableAttr {
+def PreserveAll : DeclOrTypeAttr {
let Spellings = [Clang<"preserve_all">];
let Documentation = [PreserveAllDocs];
}
@@ -1841,12 +1944,27 @@ def Target : InheritableAttr {
std::vector<std::string> Features;
StringRef Architecture;
bool DuplicateArchitecture = false;
+ bool operator ==(const ParsedTargetAttr &Other) const {
+ return DuplicateArchitecture == Other.DuplicateArchitecture &&
+ Architecture == Other.Architecture && Features == Other.Features;
+ }
};
ParsedTargetAttr parse() const {
return parse(getFeaturesStr());
}
+
+ template<class Compare>
+ ParsedTargetAttr parse(Compare cmp) const {
+ ParsedTargetAttr Attrs = parse();
+ llvm::sort(std::begin(Attrs.Features), std::end(Attrs.Features), cmp);
+ return Attrs;
+ }
+
+ bool isDefaultVersion() const { return getFeaturesStr() == "default"; }
+
static ParsedTargetAttr parse(StringRef Features) {
ParsedTargetAttr Ret;
+ if (Features == "default") return Ret;
SmallVector<StringRef, 1> AttrFeatures;
Features.split(AttrFeatures, ",");
@@ -1862,7 +1980,7 @@ def Target : InheritableAttr {
// overall feature validity for the function with the rest of the
// attributes on the function.
if (Feature.startswith("fpmath=") || Feature.startswith("tune="))
- continue;
+ continue;
// While we're here iterating check for a different target cpu.
if (Feature.startswith("arch=")) {
@@ -1880,6 +1998,13 @@ def Target : InheritableAttr {
}];
}
+def MinVectorWidth : InheritableAttr {
+ let Spellings = [Clang<"min_vector_width">];
+ let Args = [UnsignedArgument<"VectorWidth">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [MinVectorWidthDocs];
+}
+
def TransparentUnion : InheritableAttr {
let Spellings = [GCC<"transparent_union">];
// let Subjects = SubjectList<[Record, TypedefName]>;
@@ -1914,7 +2039,7 @@ def DiagnoseIf : InheritableAttr {
["DT_Error", "DT_Warning"]>,
BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
NamedArgument<"Parent", 0, /*fake*/ 1>];
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let LateParsed = 1;
let AdditionalMembers = [{
bool isError() const { return diagnosticType == DT_Error; }
@@ -1959,6 +2084,7 @@ def Unused : InheritableAttr {
def Used : InheritableAttr {
let Spellings = [GCC<"used">];
+ let Subjects = SubjectList<[NonLocalVar, Function, ObjCMethod]>;
let Documentation = [Undocumented];
}
@@ -2007,7 +2133,10 @@ def TypeVisibility : InheritableAttr {
}
def VecReturn : InheritableAttr {
- let Spellings = [Clang<"vecreturn">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ struct/class/union.
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"vecreturn", 0>];
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -2067,6 +2196,12 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr,
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
}
+def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
+ let Spellings = [GCC<"nocf_check">];
+ let Subjects = SubjectList<[FunctionLike]>;
+ let Documentation = [AnyX86NoCfCheckDocs];
+}
+
def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
let Spellings = [GCC<"force_align_arg_pointer">];
// Technically, this appertains to a FunctionDecl, but the target-specific
@@ -2113,13 +2248,13 @@ def NoSanitizeSpecific : InheritableAttr {
// an updated captability-based name and the older name will only be supported
// under the GNU-style spelling.
def GuardedVar : InheritableAttr {
- let Spellings = [Clang<"guarded_var">];
+ let Spellings = [Clang<"guarded_var", 0>];
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
def PtGuardedVar : InheritableAttr {
- let Spellings = [Clang<"pt_guarded_var">];
+ let Spellings = [Clang<"pt_guarded_var", 0>];
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2132,17 +2267,17 @@ def Lockable : InheritableAttr {
}
def ScopedLockable : InheritableAttr {
- let Spellings = [Clang<"scoped_lockable">];
+ let Spellings = [Clang<"scoped_lockable", 0>];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
}
def Capability : InheritableAttr {
- let Spellings = [Clang<"capability">, Clang<"shared_capability">];
+ let Spellings = [Clang<"capability", 0>, Clang<"shared_capability", 0>];
let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>;
let Args = [StringArgument<"Name">];
let Accessors = [Accessor<"isShared",
- [Clang<"shared_capability">]>];
+ [Clang<"shared_capability", 0>]>];
let Documentation = [Undocumented];
let AdditionalMembers = [{
bool isMutex() const { return getName().equals_lower("mutex"); }
@@ -2151,83 +2286,83 @@ def Capability : InheritableAttr {
}
def AssertCapability : InheritableAttr {
- let Spellings = [Clang<"assert_capability">,
- Clang<"assert_shared_capability">];
+ let Spellings = [Clang<"assert_capability", 0>,
+ Clang<"assert_shared_capability", 0>];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [Clang<"assert_shared_capability">]>];
+ [Clang<"assert_shared_capability", 0>]>];
let Documentation = [AssertCapabilityDocs];
}
def AcquireCapability : InheritableAttr {
- let Spellings = [Clang<"acquire_capability">,
- Clang<"acquire_shared_capability">,
+ let Spellings = [Clang<"acquire_capability", 0>,
+ Clang<"acquire_shared_capability", 0>,
GNU<"exclusive_lock_function">,
GNU<"shared_lock_function">];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [Clang<"acquire_shared_capability">,
+ [Clang<"acquire_shared_capability", 0>,
GNU<"shared_lock_function">]>];
let Documentation = [AcquireCapabilityDocs];
}
def TryAcquireCapability : InheritableAttr {
- let Spellings = [Clang<"try_acquire_capability">,
- Clang<"try_acquire_shared_capability">];
+ let Spellings = [Clang<"try_acquire_capability", 0>,
+ Clang<"try_acquire_shared_capability", 0>];
let Subjects = SubjectList<[Function],
ErrorDiag>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [Clang<"try_acquire_shared_capability">]>];
+ [Clang<"try_acquire_shared_capability", 0>]>];
let Documentation = [TryAcquireCapabilityDocs];
}
def ReleaseCapability : InheritableAttr {
- let Spellings = [Clang<"release_capability">,
- Clang<"release_shared_capability">,
- Clang<"release_generic_capability">,
- Clang<"unlock_function">];
+ let Spellings = [Clang<"release_capability", 0>,
+ Clang<"release_shared_capability", 0>,
+ Clang<"release_generic_capability", 0>,
+ Clang<"unlock_function", 0>];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [Clang<"release_shared_capability">]>,
+ [Clang<"release_shared_capability", 0>]>,
Accessor<"isGeneric",
- [Clang<"release_generic_capability">,
- Clang<"unlock_function">]>];
+ [Clang<"release_generic_capability", 0>,
+ Clang<"unlock_function", 0>]>];
let Documentation = [ReleaseCapabilityDocs];
}
def RequiresCapability : InheritableAttr {
- let Spellings = [Clang<"requires_capability">,
- Clang<"exclusive_locks_required">,
- Clang<"requires_shared_capability">,
- Clang<"shared_locks_required">];
+ let Spellings = [Clang<"requires_capability", 0>,
+ Clang<"exclusive_locks_required", 0>,
+ Clang<"requires_shared_capability", 0>,
+ Clang<"shared_locks_required", 0>];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function]>;
- let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability">,
- Clang<"shared_locks_required">]>];
+ let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability", 0>,
+ Clang<"shared_locks_required", 0>]>];
let Documentation = [Undocumented];
}
@@ -2243,7 +2378,7 @@ def GuardedBy : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2254,7 +2389,7 @@ def PtGuardedBy : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2265,7 +2400,7 @@ def AcquiredAfter : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2276,7 +2411,7 @@ def AcquiredBefore : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2287,7 +2422,7 @@ def AssertExclusiveLock : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@@ -2298,7 +2433,7 @@ def AssertSharedLock : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@@ -2311,7 +2446,7 @@ def ExclusiveTrylockFunction : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@@ -2324,7 +2459,7 @@ def SharedTrylockFunction : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@@ -2345,7 +2480,7 @@ def LocksExcluded : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
+ let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@@ -2353,7 +2488,10 @@ def LocksExcluded : InheritableAttr {
// C/C++ consumed attributes.
def Consumable : InheritableAttr {
- let Spellings = [Clang<"consumable">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ struct/class/union.
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"consumable", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Args = [EnumArgument<"DefaultState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2362,19 +2500,28 @@ def Consumable : InheritableAttr {
}
def ConsumableAutoCast : InheritableAttr {
- let Spellings = [Clang<"consumable_auto_cast_state">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ struct/class/union.
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"consumable_auto_cast_state", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
}
def ConsumableSetOnRead : InheritableAttr {
- let Spellings = [Clang<"consumable_set_state_on_read">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ struct/class/union.
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"consumable_set_state_on_read", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
}
def CallableWhen : InheritableAttr {
- let Spellings = [Clang<"callable_when">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ function (but doesn't require it to be a member function).
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"callable_when", 0>];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [VariadicEnumArgument<"CallableStates", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2383,7 +2530,10 @@ def CallableWhen : InheritableAttr {
}
def ParamTypestate : InheritableAttr {
- let Spellings = [Clang<"param_typestate">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to a parameter whose type is a consumable C++ class.
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"param_typestate", 0>];
let Subjects = SubjectList<[ParmVar]>;
let Args = [EnumArgument<"ParamState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2392,7 +2542,10 @@ def ParamTypestate : InheritableAttr {
}
def ReturnTypestate : InheritableAttr {
- let Spellings = [Clang<"return_typestate">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to a parameter or function return type that is a consumable C++ class.
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"return_typestate", 0>];
let Subjects = SubjectList<[Function, ParmVar]>;
let Args = [EnumArgument<"State", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2401,7 +2554,10 @@ def ReturnTypestate : InheritableAttr {
}
def SetTypestate : InheritableAttr {
- let Spellings = [Clang<"set_typestate">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ function (but doesn't require it to be a member function).
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"set_typestate", 0>];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [EnumArgument<"NewState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2410,7 +2566,10 @@ def SetTypestate : InheritableAttr {
}
def TestTypestate : InheritableAttr {
- let Spellings = [Clang<"test_typestate">];
+ // This attribute does not have a C [[]] spelling because it only appertains
+ // to C++ function (but doesn't require it to be a member function).
+ // FIXME: should this attribute have a CPlusPlus language option?
+ let Spellings = [Clang<"test_typestate", 0>];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [EnumArgument<"TestState", "ConsumedState",
["consumed", "unconsumed"],
@@ -2421,18 +2580,18 @@ def TestTypestate : InheritableAttr {
// Type safety attributes for `void *' pointers and type tags.
def ArgumentWithTypeTag : InheritableAttr {
- let Spellings = [GNU<"argument_with_type_tag">,
- GNU<"pointer_with_type_tag">];
+ let Spellings = [Clang<"argument_with_type_tag">,
+ Clang<"pointer_with_type_tag">];
+ let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
let Args = [IdentifierArgument<"ArgumentKind">,
- UnsignedArgument<"ArgumentIdx">,
- UnsignedArgument<"TypeTagIdx">,
- BoolArgument<"IsPointer">];
- let HasCustomParsing = 1;
+ ParamIdxArgument<"ArgumentIdx">,
+ ParamIdxArgument<"TypeTagIdx">,
+ BoolArgument<"IsPointer", /*opt*/0, /*fake*/1>];
let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs];
}
def TypeTagForDatatype : InheritableAttr {
- let Spellings = [GNU<"type_tag_for_datatype">];
+ let Spellings = [Clang<"type_tag_for_datatype">];
let Args = [IdentifierArgument<"ArgumentKind">,
TypeArgument<"MatchingCType">,
BoolArgument<"LayoutCompatible">,
@@ -2470,6 +2629,16 @@ def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Spellings = [Declspec<"dllimport">, GCC<"dllimport">];
let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>;
let Documentation = [DLLImportDocs];
+
+
+ let AdditionalMembers = [{
+private:
+ bool PropagatedToBaseTemplate = false;
+
+public:
+ void setPropagatedToBaseTemplate() { PropagatedToBaseTemplate = true; }
+ bool wasPropagatedToBaseTemplate() { return PropagatedToBaseTemplate; }
+ }];
}
def SelectAny : InheritableAttr {
@@ -2511,7 +2680,7 @@ def UPtr : TypeAttr {
def MSInheritance : InheritableAttr {
let LangOpts = [MicrosoftExt];
- let Args = [DefaultBoolArgument<"BestCase", 1>];
+ let Args = [DefaultBoolArgument<"BestCase", /*default*/1, /*fake*/1>];
let Spellings = [Keyword<"__single_inheritance">,
Keyword<"__multiple_inheritance">,
Keyword<"__virtual_inheritance">,
@@ -2566,7 +2735,7 @@ def InitSeg : Attr {
let Documentation = [InitSegDocs];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
- OS << '(' << getSection() << ')';
+ OS << " (" << getSection() << ')';
}
}];
}
@@ -2576,7 +2745,7 @@ def LoopHint : Attr {
/// vectorize: vectorizes loop operations if State == Enable.
/// vectorize_width: vectorize loop operations with width 'Value'.
/// interleave: interleave multiple loop iterations if State == Enable.
- /// interleave_count: interleaves 'Value' loop interations.
+ /// interleave_count: interleaves 'Value' loop iterations.
/// unroll: fully unroll loop if State == Enable.
/// unroll_count: unrolls loop 'Value' times.
/// distribute: attempt to distribute loop if State == Enable
@@ -2621,12 +2790,12 @@ def LoopHint : Attr {
if (SpellingIndex == Pragma_nounroll)
return;
else if (SpellingIndex == Pragma_unroll) {
- OS << getValueString(Policy);
+ OS << ' ' << getValueString(Policy);
return;
}
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
- OS << getOptionName(option) << getValueString(Policy);
+ OS << ' ' << getOptionName(option) << getValueString(Policy);
}
// Return a string containing the loop hint argument including the
@@ -2694,6 +2863,14 @@ def OMPCaptureKind : Attr {
let Documentation = [Undocumented];
}
+def OMPReferencedVar : Attr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Args = [ExprArgument<"Ref">];
+ let Documentation = [Undocumented];
+}
+
def OMPDeclareSimdDecl : Attr {
let Spellings = [Pragma<"omp", "declare simd">];
let Subjects = SubjectList<[Function]>;
@@ -2713,37 +2890,37 @@ def OMPDeclareSimdDecl : Attr {
void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
const {
if (getBranchState() != BS_Undefined)
- OS << ConvertBranchStateTyToStr(getBranchState()) << " ";
+ OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
if (auto *E = getSimdlen()) {
- OS << "simdlen(";
+ OS << " simdlen(";
E->printPretty(OS, nullptr, Policy);
- OS << ") ";
+ OS << ")";
}
if (uniforms_size() > 0) {
- OS << "uniform";
+ OS << " uniform";
StringRef Sep = "(";
for (auto *E : uniforms()) {
OS << Sep;
E->printPretty(OS, nullptr, Policy);
Sep = ", ";
}
- OS << ") ";
+ OS << ")";
}
alignments_iterator NI = alignments_begin();
for (auto *E : aligneds()) {
- OS << "aligned(";
+ OS << " aligned(";
E->printPretty(OS, nullptr, Policy);
if (*NI) {
OS << ": ";
(*NI)->printPretty(OS, nullptr, Policy);
}
- OS << ") ";
+ OS << ")";
++NI;
}
steps_iterator I = steps_begin();
modifiers_iterator MI = modifiers_begin();
for (auto *E : linears()) {
- OS << "linear(";
+ OS << " linear(";
if (*MI != OMPC_LINEAR_unknown)
OS << getOpenMPSimpleClauseTypeName(OMPC_linear, *MI) << "(";
E->printPretty(OS, nullptr, Policy);
@@ -2753,7 +2930,7 @@ def OMPDeclareSimdDecl : Attr {
OS << ": ";
(*I)->printPretty(OS, nullptr, Policy);
}
- OS << ") ";
+ OS << ")";
++I;
++MI;
}
@@ -2761,9 +2938,10 @@ def OMPDeclareSimdDecl : Attr {
}];
}
-def OMPDeclareTargetDecl : Attr {
+def OMPDeclareTargetDecl : InheritableAttr {
let Spellings = [Pragma<"omp", "declare target">];
let SemaHandler = 0;
+ let Subjects = SubjectList<[Function, SharedVar]>;
let Documentation = [OMPDeclareTargetDocs];
let Args = [
EnumArgument<"MapType", "MapTypeTy",
@@ -2774,7 +2952,16 @@ def OMPDeclareTargetDecl : Attr {
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
// Use fake syntax because it is for testing and debugging purpose only.
if (getMapType() != MT_To)
- OS << ConvertMapTypeTyToStr(getMapType()) << " ";
+ OS << ' ' << ConvertMapTypeTyToStr(getMapType());
+ }
+ static llvm::Optional<MapTypeTy>
+ isDeclareTargetDeclaration(const ValueDecl *VD) {
+ if (!VD->hasAttrs())
+ return llvm::None;
+ if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+
+ return llvm::None;
}
}];
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
index dc355832b875..bb2993eab4bc 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
@@ -191,6 +191,65 @@ in generation of more efficient code.
}];
}
+def CPUSpecificCPUDispatchDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and
+resolve multiversioned functions. This form of multiversioning provides a
+mechanism for declaring versions across translation units and manually
+specifying the resolved function list. A specified CPU defines a set of minimum
+features that are required for the function to be called. The result of this is
+that future processors execute the most restrictive version of the function the
+new processor can execute.
+
+Function versions are defined with ``cpu_specific``, which takes one or more CPU
+names as a parameter. For example:
+
+.. code-block:: c
+
+ // Declares and defines the ivybridge version of single_cpu.
+ __attribute__((cpu_specific(ivybridge)))
+ void single_cpu(void){}
+
+ // Declares and defines the atom version of single_cpu.
+ __attribute__((cpu_specific(atom)))
+ void single_cpu(void){}
+
+ // Declares and defines both the ivybridge and atom version of multi_cpu.
+ __attribute__((cpu_specific(ivybridge, atom)))
+ void multi_cpu(void){}
+
+A dispatching (or resolving) function can be declared anywhere in a project's
+source code with ``cpu_dispatch``. This attribute takes one or more CPU names
+as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch``
+are not expected to be defined, only declared. If such a marked function has a
+definition, any side effects of the function are ignored; trivial function
+bodies are permissible for ICC compatibility.
+
+.. code-block:: c
+
+ // Creates a resolver for single_cpu above.
+ __attribute__((cpu_dispatch(ivybridge, atom)))
+ void single_cpu(void){}
+
+ // Creates a resolver for multi_cpu, but adds a 3rd version defined in another
+ // translation unit.
+ __attribute__((cpu_dispatch(ivybridge, atom, sandybridge)))
+ void multi_cpu(void){}
+
+Note that it is possible to have a resolving function that dispatches based on
+more or fewer options than are present in the program. Specifying fewer will
+result in the omitted options not being considered during resolution. Specifying
+a version for resolution that isn't defined in the program will result in a
+linking failure.
+
+It is also possible to specify a CPU name of ``generic`` which will be resolved
+if the executing processor doesn't satisfy the features required in the CPU
+name. The behavior of a program executing on a processor that doesn't satisfy
+any option of a multiversioned function is undefined.
+ }];
+}
+
def C11NoReturnDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -273,7 +332,7 @@ def AllocSizeDocs : Documentation {
let Content = [{
The ``alloc_size`` attribute can be placed on functions that return pointers in
order to hint to the compiler how many bytes of memory will be available at the
-returned poiner. ``alloc_size`` takes one or two arguments.
+returned pointer. ``alloc_size`` takes one or two arguments.
- ``alloc_size(N)`` implies that argument number N equals the number of
available bytes at the returned pointer.
@@ -306,12 +365,24 @@ An example of how to use ``alloc_size``
}];
}
+def CodeSegDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``__declspec(code_seg)`` attribute enables the placement of code into separate
+named segments that can be paged or locked in memory individually. This attribute
+is used to control the placement of instantiated templates and compiler-generated
+code. See the documentation for `__declspec(code_seg)`_ on MSDN.
+
+.. _`__declspec(code_seg)`: http://msdn.microsoft.com/en-us/library/dn636922.aspx
+ }];
+}
+
def AllocAlignDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Use ``__attribute__((alloc_align(<alignment>))`` on a function
declaration to specify that the return value of the function (which must be a
-pointer type) is at least as aligned as the value of the indicated parameter. The
+pointer type) is at least as aligned as the value of the indicated parameter. The
parameter is given by its index in the list of formal parameters; the first
parameter has index 1 unless the function is a C++ non-static member function,
in which case the first parameter has index 2 to account for the implicit ``this``
@@ -330,7 +401,7 @@ parameter.
void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3)));
Note that this attribute merely informs the compiler that a function always
-returns a sufficiently aligned pointer. It does not cause the compiler to
+returns a sufficiently aligned pointer. It does not cause the compiler to
emit code to enforce that alignment. The behavior is undefined if the returned
poitner is not sufficiently aligned.
}];
@@ -913,10 +984,10 @@ in the metadata name for that object. The `objc_runtime_name`
attribute allows annotated interfaces or protocols to use the
specified string argument in the object's metadata name instead of the
default name.
-
+
**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute
can only be placed before an @protocol or @interface declaration:
-
+
.. code-block:: objc
__attribute__((objc_runtime_name("MyLocalName")))
@@ -1430,6 +1501,29 @@ as ``-mlong-calls`` and ``-mno-long-calls``.
}];
}
+def RISCVInterruptDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "interrupt (RISCV)";
+ let Content = [{
+Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV
+targets. This attribute may be attached to a function definition and instructs
+the backend to generate appropriate function entry/exit code so that it can be
+used directly as an interrupt service routine.
+
+Permissible values for this parameter are ``user``, ``supervisor``,
+and ``machine``. If there is no parameter, then it defaults to machine.
+
+Repeated interrupt attribute on the same declaration will cause a warning
+to be emitted. In case of repeated declarations, the last one prevails.
+
+Refer to:
+https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html
+https://riscv.org/specifications/privileged-isa/
+The RISC-V Instruction Set Manual Volume II: Privileged Architecture
+Version 1.10.
+ }];
+}
+
def AVRInterruptDocs : Documentation {
let Category = DocCatFunction;
let Heading = "interrupt (AVR)";
@@ -1474,6 +1568,49 @@ for the function.
Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2",
"avx", "xop" and largely correspond to the machine specific options handled by
the front end.
+
+Additionally, this attribute supports function multiversioning for ELF based
+x86/x86-64 targets, which can be used to create multiple implementations of the
+same function that will be resolved at runtime based on the priority of their
+``target`` attribute strings. A function is considered a multiversioned function
+if either two declarations of the function have different ``target`` attribute
+strings, or if it has a ``target`` attribute string of ``default``. For
+example:
+
+ .. code-block:: c++
+
+ __attribute__((target("arch=atom")))
+ void foo() {} // will be called on 'atom' processors.
+ __attribute__((target("default")))
+ void foo() {} // will be called on any other processors.
+
+All multiversioned functions must contain a ``default`` (fallback)
+implementation, otherwise usages of the function are considered invalid.
+Additionally, a function may not become multiversioned after its first use.
+}];
+}
+
+def MinVectorWidthDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the ``__attribute__((min_vector_width(width)))`` attribute. This
+attribute may be attached to a function and informs the backend that this
+function desires vectors of at least this width to be generated. Target-specific
+maximum vector widths still apply. This means even if you ask for something
+larger than the target supports, you will only get what the target supports.
+This attribute is meant to be a hint to control target heuristics that may
+generate narrower vectors than what the target hardware supports.
+
+This is currently used by the X86 target to allow some CPUs that support 512-bit
+vectors to be limited to using 256-bit vectors to avoid frequency penalties.
+This is currently enabled with the ``-prefer-vector-width=256`` command line
+option. The ``min_vector_width`` attribute can be used to prevent the backend
+from trying to split vector operations to match the ``prefer-vector-width``. All
+X86 vector intrinsics from x86intrin.h already set this attribute. Additionally,
+use of any of the X86-specific vector builtins will implicitly set this
+attribute on the calling function. The intent is that explicitly writing vector
+code using the X86 intrinsics will prevent ``prefer-vector-width`` from
+affecting the code.
}];
}
@@ -1785,13 +1922,14 @@ This attribute accepts a single parameter that must be one of the following:
def NoSanitizeDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
-Use the ``no_sanitize`` attribute on a function declaration to specify
-that a particular instrumentation or set of instrumentations should not be
-applied to that function. The attribute takes a list of string literals,
-which have the same meaning as values accepted by the ``-fno-sanitize=``
-flag. For example, ``__attribute__((no_sanitize("address", "thread")))``
-specifies that AddressSanitizer and ThreadSanitizer should not be applied
-to the function.
+Use the ``no_sanitize`` attribute on a function or a global variable
+declaration to specify that a particular instrumentation or set of
+instrumentations should not be applied. The attribute takes a list of
+string literals, which have the same meaning as values accepted by the
+``-fno-sanitize=`` flag. For example,
+``__attribute__((no_sanitize("address", "thread")))`` specifies that
+AddressSanitizer and ThreadSanitizer should not be applied to the
+function or variable.
See :ref:`Controlling Code Generation <controlling-code-generation>` for a
full list of supported sanitizer flags.
@@ -1806,9 +1944,9 @@ def NoSanitizeAddressDocs : Documentation {
let Content = [{
.. _langext-address_sanitizer:
-Use ``__attribute__((no_sanitize_address))`` on a function declaration to
-specify that address safety instrumentation (e.g. AddressSanitizer) should
-not be applied to that function.
+Use ``__attribute__((no_sanitize_address))`` on a function or a global
+variable declaration to specify that address safety instrumentation
+(e.g. AddressSanitizer) should not be applied.
}];
}
@@ -2224,6 +2362,64 @@ It is only supported when using the Microsoft C++ ABI.
}];
}
+def LifetimeBoundDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``lifetimebound`` attribute indicates that a resource owned by
+a function parameter or implicit object parameter
+is retained by the return value of the annotated function
+(or, for a parameter of a constructor, in the value of the constructed object).
+It is only supported in C++.
+
+This attribute provides an experimental implementation of the facility
+described in the C++ committee paper [http://wg21.link/p0936r0](P0936R0),
+and is subject to change as the design of the corresponding functionality
+changes.
+ }];
+}
+
+def TrivialABIDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union.
+It instructs the compiler to pass and return the type using the C ABI for the
+underlying type when the type would otherwise be considered non-trivial for the
+purpose of calls.
+A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example:
+
+ .. code-block:: c++
+
+ // A is trivial for the purposes of calls because `trivial_abi` makes the
+ // user-provided special functions trivial.
+ struct __attribute__((trivial_abi)) A {
+ ~A();
+ A(const A &);
+ A(A &&);
+ int x;
+ };
+
+ // B's destructor and copy/move constructor are considered trivial for the
+ // purpose of calls because A is trivial.
+ struct B {
+ A a;
+ };
+
+If a type is trivial for the purposes of calls, has a non-trivial destructor,
+and is passed as an argument by value, the convention is that the callee will
+destroy the object before returning.
+
+Attribute ``trivial_abi`` has no effect in the following cases:
+
+- The class directly declares a virtual base or virtual methods.
+- The class has a base class that is non-trivial for the purposes of calls.
+- The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes:
+
+ - classes that are non-trivial for the purposes of calls
+ - __weak-qualified types in Objective-C++
+ - arrays of any of the above
+ }];
+}
+
def MSInheritanceDocs : Documentation {
let Category = DocCatType;
let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance";
@@ -2565,7 +2761,7 @@ The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullabl
int fetch_or_zero(int * _Nullable ptr);
-a caller of ``fetch_or_zero`` can provide null.
+a caller of ``fetch_or_zero`` can provide null.
}];
}
@@ -2679,6 +2875,28 @@ The syntax of the declare target directive is as follows:
}];
}
+def NoStackProtectorDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the ``__attribute__((no_stack_protector))`` attribute which disables
+the stack protector on the specified function. This attribute is useful for
+selectively disabling the stack protector on some functions when building with
+``-fstack-protector`` compiler option.
+
+For example, it disables the stack protector for the function ``foo`` but function
+``bar`` will still be built with the stack protector with the ``-fstack-protector``
+option.
+
+.. code-block:: c
+
+ int __attribute__((no_stack_protector))
+ foo (int x); // stack protection will be disabled for foo.
+
+ int bar(int y); // bar can be built with the stack protector.
+
+ }];
+}
+
def NotTailCalledDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -2737,7 +2955,7 @@ 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
+``__declspec(nothrow)`` attribute as an equivalent 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
@@ -2800,7 +3018,7 @@ Use this attribute to indicate that the specified function has no
caller-saved registers. That is, all registers are callee-saved except for
registers used for passing parameters to the function or returning parameters
from the function.
-The compiler saves and restores any modified registers that were not used for
+The compiler saves and restores any modified registers that were not used for
passing or returning arguments to the function.
The user can call functions specified with the 'no_caller_saved_registers'
@@ -2852,6 +3070,23 @@ jumps from i386 arch code).
}];
}
+def AnyX86NoCfCheckDocs : Documentation{
+ let Category = DocCatFunction;
+ let Content = [{
+Jump Oriented Programming attacks rely on tampering with addresses used by
+indirect call / jmp, e.g. redirect control-flow to non-programmer
+intended bytes in the binary.
+X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow
+Enforcement Technology (CET). IBT instruments ENDBR instructions used to
+specify valid targets of indirect call / jmp.
+The ``nocf_check`` attribute has two roles:
+1. Appertains to a function - do not add ENDBR instruction at the beginning of
+the function.
+2. Appertains to a function pointer - do not track the target function of this
+pointer (by adding nocf_check prefix to the indirect-call instruction).
+}];
+}
+
def SwiftCallDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
@@ -3031,7 +3266,7 @@ the ability to distinguish between different versions of the same entity but
with different ABI versions supported. For example, a newer version of a class
could have a different set of data members and thus have a different size. Using
the ``abi_tag`` attribute, it is possible to have different mangled names for
-a global variable of the class type. Therefor, the old code could keep using
+a global variable of the class type. Therefore, the old code could keep using
the old manged name and the new code will use the new mangled name with tags.
}];
}
@@ -3213,3 +3448,13 @@ For more information see
or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_.
}];
}
+
+def ArtificialDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``artificial`` attribute can be applied to an inline function. If such a
+function is inlined, the attribute indicates that debuggers should associate
+the resulting instructions with the call site, rather than with the
+corresponding line within the inlined callee.
+ }];
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h
index 8f7394f59d4d..d82dbb032be9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::attr::Kind enum.
+/// Defines the clang::attr::Kind enum.
///
//===----------------------------------------------------------------------===//
@@ -19,7 +19,7 @@ namespace clang {
namespace attr {
-// \brief A list of all the recognized kinds of attributes.
+// A list of all the recognized kinds of attributes.
enum Kind {
#define ATTR(X) X,
#define ATTR_RANGE(CLASS, FIRST_NAME, LAST_NAME) \
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrSubjectMatchRules.h b/contrib/llvm/tools/clang/include/clang/Basic/AttrSubjectMatchRules.h
index 4c88adf57f17..81aa634dfeb8 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AttrSubjectMatchRules.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrSubjectMatchRules.h
@@ -16,7 +16,7 @@
namespace clang {
namespace attr {
-/// \brief A list of all the recognized kinds of attributes.
+/// A list of all the recognized kinds of attributes.
enum SubjectMatchRule {
#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X,
#include "clang/Basic/AttrSubMatchRulesList.inc"
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
index c651abacd482..3152453694c9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
@@ -32,7 +32,7 @@ enum class AttrSyntax {
Pragma
};
-/// \brief Return the version number associated with the attribute if we
+/// Return the version number associated with the attribute if we
/// recognize and implement the attribute specified by the given information.
int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
const IdentifierInfo *Attr, const TargetInfo &Target,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BitmaskEnum.h b/contrib/llvm/tools/clang/include/clang/Basic/BitmaskEnum.h
new file mode 100644
index 000000000000..12ff3cf207be
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BitmaskEnum.h
@@ -0,0 +1,25 @@
+//===--- BitmaskEnum.h - wrapper of LLVM's bitmask enum facility-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Provides LLVM's BitmaskEnum facility to enumeration types declared in
+/// namespace clang.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_BITMASKENUM_H
+#define LLVM_CLANG_BASIC_BITMASKENUM_H
+
+#include "llvm/ADT/BitmaskEnum.h"
+
+namespace clang {
+ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
index 3d4deb5ed306..9089ce1b659e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -48,8 +48,8 @@
// . -> "...". This may only occur at the end of the function list.
//
// Types may be prefixed with the following modifiers:
-// L -> long (e.g. Li for 'long int')
-// LL -> long long
+// L -> long (e.g. Li for 'long int', Ld for 'long double')
+// LL -> long long (e.g. LLi for 'long long int', LLd for __float128)
// LLL -> __int128_t (e.g. LLLi)
// W -> int64_t
// N -> 'int' size if target is LP64, 'L' otherwise.
@@ -89,9 +89,10 @@
// S:N: -> similar to the s:N: attribute, but the function is like vscanf
// in that it accepts its arguments as a va_list rather than
// through an ellipsis
-// e -> const, but only when -fmath-errno=0
+// e -> const, but only when -fno-math-errno
// j -> returns_twice (like setjmp)
// u -> arguments are not evaluated for their side-effects
+// V:N: -> requires vectors of at least N bits to be legal
// FIXME: gcc has nonnull
#if defined(BUILTIN) && !defined(LIBBUILTIN)
@@ -110,9 +111,11 @@ BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_copysign, "ddd", "ncF")
BUILTIN(__builtin_copysignf, "fff", "ncF")
BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
+BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
+BUILTIN(__builtin_fabsf128, "LLdLLd", "ncF")
BUILTIN(__builtin_fmod , "ddd" , "Fne")
BUILTIN(__builtin_fmodf, "fff" , "Fne")
BUILTIN(__builtin_fmodl, "LdLdLd", "Fne")
@@ -122,9 +125,11 @@ BUILTIN(__builtin_frexpl, "LdLdi*", "Fn")
BUILTIN(__builtin_huge_val, "d", "nc")
BUILTIN(__builtin_huge_valf, "f", "nc")
BUILTIN(__builtin_huge_vall, "Ld", "nc")
+BUILTIN(__builtin_huge_valf128, "LLd", "nc")
BUILTIN(__builtin_inf , "d" , "nc")
BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
+BUILTIN(__builtin_inff128 , "LLd" , "nc")
BUILTIN(__builtin_labs , "LiLi" , "Fnc")
BUILTIN(__builtin_llabs, "LLiLLi", "Fnc")
BUILTIN(__builtin_ldexp , "ddi" , "Fne")
@@ -133,12 +138,14 @@ BUILTIN(__builtin_ldexpl, "LdLdi", "Fne")
BUILTIN(__builtin_modf , "ddd*" , "Fn")
BUILTIN(__builtin_modff, "fff*" , "Fn")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fn")
-BUILTIN(__builtin_nan, "dcC*" , "ncF")
-BUILTIN(__builtin_nanf, "fcC*" , "ncF")
-BUILTIN(__builtin_nanl, "LdcC*", "ncF")
-BUILTIN(__builtin_nans, "dcC*" , "ncF")
-BUILTIN(__builtin_nansf, "fcC*" , "ncF")
-BUILTIN(__builtin_nansl, "LdcC*", "ncF")
+BUILTIN(__builtin_nan, "dcC*" , "FnU")
+BUILTIN(__builtin_nanf, "fcC*" , "FnU")
+BUILTIN(__builtin_nanl, "LdcC*", "FnU")
+BUILTIN(__builtin_nanf128, "LLdcC*", "FnU")
+BUILTIN(__builtin_nans, "dcC*" , "FnU")
+BUILTIN(__builtin_nansf, "fcC*" , "FnU")
+BUILTIN(__builtin_nansl, "LdcC*", "FnU")
+BUILTIN(__builtin_nansf128, "LLdcC*", "FnU")
BUILTIN(__builtin_powi , "ddi" , "Fnc")
BUILTIN(__builtin_powif, "ffi" , "Fnc")
BUILTIN(__builtin_powil, "LdLdi", "Fnc")
@@ -715,6 +722,10 @@ ATOMIC_BUILTIN(__opencl_atomic_fetch_xor, "v.", "t")
ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t")
ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t")
+// GCC does not support these, they are a Clang extension.
+ATOMIC_BUILTIN(__atomic_fetch_min, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t")
+
#undef ATOMIC_BUILTIN
// Non-overloaded atomic builtins.
@@ -734,6 +745,14 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittest, "UcNiC*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittestandcomplement, "UcNi*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittestandreset, "UcNi*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittestandset, "UcNi*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittest64, "UcWiC*Wi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittestandcomplement64, "UcWi*Wi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittestandreset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_bittestandset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
@@ -773,7 +792,16 @@ LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandreset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandreset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandreset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandreset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_interlockedbittestandset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
@@ -796,6 +824,10 @@ LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES)
LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES)
// C99 library functions
+// C99 stdarg.h
+LIBBUILTIN(va_start, "vA.", "fn", "stdarg.h", ALL_LANGUAGES)
+LIBBUILTIN(va_end, "vA", "fn", "stdarg.h", ALL_LANGUAGES)
+LIBBUILTIN(va_copy, "vAA", "fn", "stdarg.h", ALL_LANGUAGES)
// C99 stdlib.h
LIBBUILTIN(abort, "v", "fr", "stdlib.h", ALL_LANGUAGES)
LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h", ALL_LANGUAGES)
@@ -803,6 +835,13 @@ LIBBUILTIN(exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES)
LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES)
LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES)
LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtod, "dcC*c**", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtof, "fcC*c**", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtold, "LdcC*c**", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtol, "LicC*c**i", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtoll, "LLicC*c**i", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtoul, "ULicC*c**i", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(strtoull, "ULLicC*c**i", "f", "stdlib.h", ALL_LANGUAGES)
// C99 string.h
LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(memcmp, "ivC*vC*z", "f", "string.h", ALL_LANGUAGES)
@@ -826,6 +865,7 @@ LIBBUILTIN(memset, "v*v*iz", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES)
// C99 stdio.h
+// FIXME: This list is incomplete.
LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h", ALL_LANGUAGES)
@@ -840,6 +880,10 @@ LIBBUILTIN(sscanf, "icC*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(fopen, "P*cC*cC*", "f", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(fread, "zv*zzP*", "f", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(fwrite, "zvC*zzP*", "f", "stdio.h", ALL_LANGUAGES)
+
// C99 ctype.h
LIBBUILTIN(isalnum, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
LIBBUILTIN(isalpha, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
@@ -912,7 +956,7 @@ LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
// id objc_msgSend(id, SEL, ...)
LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG)
-// long double objc_msgSend_fpret(id self, SEL op, ...)
+// long double objc_msgSend_fpret(id self, SEL op, ...)
LIBBUILTIN(objc_msgSend_fpret, "LdGH.", "f", "objc/message.h", OBJC_LANG)
// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
LIBBUILTIN(objc_msgSend_fp2ret, "XLdGH.", "f", "objc/message.h", OBJC_LANG)
@@ -1361,12 +1405,15 @@ BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
// Clang builtins (not available in GCC).
BUILTIN(__builtin_addressof, "v*v&", "nct")
-BUILTIN(__builtin_operator_new, "v*z", "c")
-BUILTIN(__builtin_operator_delete, "vv*", "n")
+BUILTIN(__builtin_operator_new, "v*z", "tc")
+BUILTIN(__builtin_operator_delete, "vv*", "tn")
BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
+BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
// Safestack builtins
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
+BUILTIN(__builtin___get_unsafe_stack_bottom, "v*", "Fn")
+BUILTIN(__builtin___get_unsafe_stack_top, "v*", "Fn")
BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
// Nontemporal loads/stores builtins
@@ -1381,6 +1428,7 @@ BUILTIN(__builtin_coro_promise, "v*v*IiIb", "n")
BUILTIN(__builtin_coro_size, "z", "n")
BUILTIN(__builtin_coro_frame, "v*", "n")
+BUILTIN(__builtin_coro_noop, "v*", "n")
BUILTIN(__builtin_coro_free, "v*v*", "n")
BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n")
@@ -1443,6 +1491,7 @@ LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG)
// Builtins for XRay
BUILTIN(__xray_customevent, "vcC*z", "")
+BUILTIN(__xray_typedevent, "vzcC*z", "")
// Win64-compatible va_list functions
BUILTIN(__builtin_ms_va_start, "vc*&.", "nt")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
index 963c72ea82e0..fa2bcc4c7ab0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines enum values for all the target-independent builtin
+/// Defines enum values for all the target-independent builtin
/// functions.
///
//===----------------------------------------------------------------------===//
@@ -59,7 +59,7 @@ struct Info {
const char *Features;
};
-/// \brief Holds information about both target-independent and
+/// Holds information about both target-independent and
/// target-specific builtins, allowing easy queries by clients.
///
/// Builtins from an optional auxiliary target are stored in
@@ -72,122 +72,129 @@ class Context {
public:
Context() {}
- /// \brief Perform target-specific initialization
+ /// Perform target-specific initialization
/// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);
- /// \brief Mark the identifiers for all the builtins with their
+ /// Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
- /// \brief Return the identifier name for the specified builtin,
+ /// Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
const char *getName(unsigned ID) const {
return getRecord(ID).Name;
}
- /// \brief Get the type descriptor string for the specified builtin.
+ /// Get the type descriptor string for the specified builtin.
const char *getTypeString(unsigned ID) const {
return getRecord(ID).Type;
}
- /// \brief Return true if this function is a target-specific builtin.
+ /// Return true if this function is a target-specific builtin.
bool isTSBuiltin(unsigned ID) const {
return ID >= Builtin::FirstTSBuiltin;
}
- /// \brief Return true if this function has no side effects.
+ /// Return true if this function has no side effects.
bool isPure(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'U') != nullptr;
}
- /// \brief Return true if this function has no side effects and doesn't
+ /// Return true if this function has no side effects and doesn't
/// read memory.
bool isConst(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'c') != nullptr;
}
- /// \brief Return true if we know this builtin never throws an exception.
+ /// Return true if we know this builtin never throws an exception.
bool isNoThrow(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'n') != nullptr;
}
- /// \brief Return true if we know this builtin never returns.
+ /// Return true if we know this builtin never returns.
bool isNoReturn(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'r') != nullptr;
}
- /// \brief Return true if we know this builtin can return twice.
+ /// Return true if we know this builtin can return twice.
bool isReturnsTwice(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'j') != nullptr;
}
- /// \brief Returns true if this builtin does not perform the side-effects
+ /// Returns true if this builtin does not perform the side-effects
/// of its arguments.
bool isUnevaluated(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'u') != nullptr;
}
- /// \brief Return true if this is a builtin for a libc/libm function,
+ /// Return true if this is a builtin for a libc/libm function,
/// with a "__builtin_" prefix (e.g. __builtin_abs).
bool isLibFunction(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'F') != nullptr;
}
- /// \brief Determines whether this builtin is a predefined libc/libm
+ /// Determines whether this builtin is a predefined libc/libm
/// function, such as "malloc", where we know the signature a
/// priori.
bool isPredefinedLibFunction(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'f') != nullptr;
}
- /// \brief Returns true if this builtin requires appropriate header in other
+ /// Returns true if this builtin requires appropriate header in other
/// compilers. In Clang it will work even without including it, but we can emit
/// a warning about missing header.
bool isHeaderDependentFunction(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'h') != nullptr;
}
- /// \brief Determines whether this builtin is a predefined compiler-rt/libgcc
+ /// Determines whether this builtin is a predefined compiler-rt/libgcc
/// function, such as "__clear_cache", where we know the signature a
/// priori.
bool isPredefinedRuntimeFunction(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'i') != nullptr;
}
- /// \brief Determines whether this builtin has custom typechecking.
+ /// Determines whether this builtin has custom typechecking.
bool hasCustomTypechecking(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 't') != nullptr;
}
- /// \brief Determines whether this builtin has a result or any arguments which
+ /// Determines whether this builtin has a result or any arguments which
/// are pointer types.
bool hasPtrArgsOrResult(unsigned ID) const {
return strchr(getRecord(ID).Type, '*') != nullptr;
}
- /// \brief Completely forget that the given ID was ever considered a builtin,
+ /// Return true if this builtin has a result or any arguments which are
+ /// reference types.
+ bool hasReferenceArgsOrResult(unsigned ID) const {
+ return strchr(getRecord(ID).Type, '&') != nullptr ||
+ strchr(getRecord(ID).Type, 'A') != nullptr;
+ }
+
+ /// Completely forget that the given ID was ever considered a builtin,
/// e.g., because the user provided a conflicting signature.
void forgetBuiltin(unsigned ID, IdentifierTable &Table);
- /// \brief If this is a library function that comes from a specific
+ /// If this is a library function that comes from a specific
/// header, retrieve that header name.
const char *getHeaderName(unsigned ID) const {
return getRecord(ID).HeaderName;
}
- /// \brief Determine whether this builtin is like printf in its
+ /// Determine whether this builtin is like printf in its
/// formatting rules and, if so, set the index to the format string
/// argument and whether this function as a va_list argument.
bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
- /// \brief Determine whether this builtin is like scanf in its
+ /// Determine whether this builtin is like scanf in its
/// formatting rules and, if so, set the index to the format string
/// argument and whether this function as a va_list argument.
bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
- /// \brief Return true if this function has no side effects and doesn't
+ /// Return true if this function has no side effects and doesn't
/// read memory, except for possibly errno.
///
/// Such functions can be const when the MathErrno lang option is disabled.
@@ -199,12 +206,14 @@ public:
return getRecord(ID).Features;
}
- /// \brief Return true if builtin ID belongs to AuxTarget.
+ unsigned getRequiredVectorWidth(unsigned ID) const;
+
+ /// Return true if builtin ID belongs to AuxTarget.
bool isAuxBuiltinID(unsigned ID) const {
return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());
}
- /// Return real buitin ID (i.e. ID it would have furing compilation
+ /// Return real builtin ID (i.e. ID it would have during compilation
/// for AuxTarget).
unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
@@ -212,26 +221,30 @@ public:
/// prefix.
static bool isBuiltinFunc(const char *Name);
+ /// Returns true if this is a builtin that can be redeclared. Returns true
+ /// for non-builtins.
+ bool canBeRedeclared(unsigned ID) const;
+
private:
const Info &getRecord(unsigned ID) const;
- /// \brief Is this builtin supported according to the given language options?
+ /// Is this builtin supported according to the given language options?
bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
const LangOptions &LangOpts);
- /// \brief Helper function for isPrintfLike and isScanfLike.
+ /// Helper function for isPrintfLike and isScanfLike.
bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
const char *Fmt) const;
};
}
-/// \brief Kinds of BuiltinTemplateDecl.
+/// Kinds of BuiltinTemplateDecl.
enum BuiltinTemplateKind : int {
- /// \brief This names the __make_integer_seq BuiltinTemplateDecl.
+ /// This names the __make_integer_seq BuiltinTemplateDecl.
BTK__make_integer_seq,
- /// \brief This names the __type_pack_element BuiltinTemplateDecl.
+ /// This names the __type_pack_element BuiltinTemplateDecl.
BTK__type_pack_element
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
index 55a4f70176d0..b5d971d0bc6e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -18,6 +18,10 @@
# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
#endif
+#if defined(BUILTIN) && !defined(TARGET_HEADER_BUILTIN)
+# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
// In libgcc
BUILTIN(__clear_cache, "vv*v*", "i")
@@ -65,9 +69,40 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+// MSVC
LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
+
+// MSVC intrinsics for volatile but non-acquire/release loads and stores
+LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_load16, "ssCD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_load32, "iiCD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_load64, "LLiLLiCD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_store8, "vcD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_store16, "vsD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_store32, "viD*i", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__iso_volatile_store64, "vLLiD*LLi", "n", ALL_MS_LANGUAGES)
+
+TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+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, "")
#undef BUILTIN
#undef LANGBUILTIN
+#undef TARGET_HEADER_BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
index ec6a0fb91765..4a447eb9f6a8 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -21,9 +21,9 @@
// 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")
+BUILTIN(__builtin_amdgcn_dispatch_ptr, "Uc*4", "nc")
+BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "Uc*4", "nc")
+BUILTIN(__builtin_amdgcn_implicitarg_ptr, "Uc*4", "nc")
BUILTIN(__builtin_amdgcn_workgroup_id_x, "Ui", "nc")
BUILTIN(__builtin_amdgcn_workgroup_id_y, "Ui", "nc")
@@ -93,6 +93,9 @@ BUILTIN(__builtin_amdgcn_ds_bpermute, "iii", "nc")
BUILTIN(__builtin_amdgcn_readfirstlane, "ii", "nc")
BUILTIN(__builtin_amdgcn_readlane, "iii", "nc")
BUILTIN(__builtin_amdgcn_fmed3f, "ffff", "nc")
+BUILTIN(__builtin_amdgcn_ds_faddf, "ff*fIiIiIb", "n")
+BUILTIN(__builtin_amdgcn_ds_fminf, "ff*fIiIiIb", "n")
+BUILTIN(__builtin_amdgcn_ds_fmaxf, "ff*fIiIiIb", "n")
//===----------------------------------------------------------------------===//
// VI+ only builtins.
@@ -118,6 +121,18 @@ TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp")
TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts")
//===----------------------------------------------------------------------===//
+// Deep learning builtins.
+//===----------------------------------------------------------------------===//
+
+TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dl-insts")
+
+//===----------------------------------------------------------------------===//
// Special builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_read_exec, "LUi", "nc")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
index fda50b53589b..f976720d116d 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
@@ -17,28 +17,51 @@
// The builtins below are not autogenerated from iset.py.
// Make sure you do not overwrite these.
-BUILTIN(__builtin_brev_ldd, "LLi*LLi*LLi*i", "")
-BUILTIN(__builtin_brev_ldw, "i*i*i*i", "")
-BUILTIN(__builtin_brev_ldh, "s*s*s*i", "")
-BUILTIN(__builtin_brev_lduh, "Us*Us*Us*i", "")
-BUILTIN(__builtin_brev_ldb, "c*c*c*i", "")
-BUILTIN(__builtin_brev_ldub, "Uc*Uc*Uc*i", "")
+BUILTIN(__builtin_brev_ldd, "v*LLi*CLLi*iC", "")
+BUILTIN(__builtin_brev_ldw, "v*i*Ci*iC", "")
+BUILTIN(__builtin_brev_ldh, "v*s*Cs*iC", "")
+BUILTIN(__builtin_brev_lduh, "v*Us*CUs*iC", "")
+BUILTIN(__builtin_brev_ldb, "v*Sc*CSc*iC", "")
+BUILTIN(__builtin_brev_ldub, "v*Uc*CUc*iC", "")
BUILTIN(__builtin_circ_ldd, "LLi*LLi*LLi*iIi", "")
BUILTIN(__builtin_circ_ldw, "i*i*i*iIi", "")
BUILTIN(__builtin_circ_ldh, "s*s*s*iIi", "")
BUILTIN(__builtin_circ_lduh, "Us*Us*Us*iIi", "")
BUILTIN(__builtin_circ_ldb, "c*c*c*iIi", "")
BUILTIN(__builtin_circ_ldub, "Uc*Uc*Uc*iIi", "")
-BUILTIN(__builtin_brev_std, "LLi*LLi*LLii", "")
-BUILTIN(__builtin_brev_stw, "i*i*ii", "")
-BUILTIN(__builtin_brev_sth, "s*s*ii", "")
-BUILTIN(__builtin_brev_sthhi, "s*s*ii", "")
-BUILTIN(__builtin_brev_stb, "c*c*ii", "")
+BUILTIN(__builtin_brev_std, "LLi*CLLi*LLiiC", "")
+BUILTIN(__builtin_brev_stw, "i*Ci*iiC", "")
+BUILTIN(__builtin_brev_sth, "s*Cs*iiC", "")
+BUILTIN(__builtin_brev_sthhi, "s*Cs*iiC", "")
+BUILTIN(__builtin_brev_stb, "c*Cc*iiC", "")
BUILTIN(__builtin_circ_std, "LLi*LLi*LLiiIi", "")
BUILTIN(__builtin_circ_stw, "i*i*iiIi", "")
BUILTIN(__builtin_circ_sth, "s*s*iiIi", "")
BUILTIN(__builtin_circ_sthhi, "s*s*iiIi", "")
BUILTIN(__builtin_circ_stb, "c*c*iiIi", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrub_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrb_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadruh_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrh_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadri_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrd_pci, "LLiv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrub_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrb_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadruh_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrh_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadri_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrd_pcr, "LLiv*ivC*", "")
+
+BUILTIN(__builtin_HEXAGON_S2_storerb_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerh_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerf_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storeri_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerd_pci, "vv*IiiLLivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerb_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerh_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerf_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storeri_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerd_pcr, "vv*iLLivC*", "")
// The builtins above are not autogenerated from iset.py.
// Make sure you do not overwrite these.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def
index 7800ae69c4c9..241b93a915a9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def
@@ -16,6 +16,7 @@
#define GET_NEON_BUILTINS
#include "clang/Basic/arm_neon.inc"
+#include "clang/Basic/arm_fp16.inc"
#undef GET_NEON_BUILTINS
#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
index 7bab73a3b110..08c60979779b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
@@ -18,6 +18,19 @@
# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
+#pragma push_macro("SM_70")
+#define SM_70 "sm_70|sm_71"
+#pragma push_macro("SM_60")
+#define SM_60 "sm_60|sm_61|sm_62|" SM_70
+
+#pragma push_macro("PTX61")
+#define PTX61 "ptx61"
+#pragma push_macro("PTX60")
+#define PTX60 "ptx60|" PTX61
+
+#pragma push_macro("AND")
+#define AND(a, b) a "," b
+
// Special Registers
BUILTIN(__nvvm_read_ptx_sreg_tid_x, "i", "nc")
@@ -372,7 +385,7 @@ BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "")
BUILTIN(__nvvm_bitcast_d2ll, "LLid", "")
// FNS
-TARGET_BUILTIN(__nvvm_fns, "UiUiUii", "n", "ptx60")
+TARGET_BUILTIN(__nvvm_fns, "UiUiUii", "n", PTX60)
// Sync
@@ -381,9 +394,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")
+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
@@ -396,14 +409,14 @@ 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")
+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", "")
@@ -411,17 +424,17 @@ 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")
+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")
+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")
+TARGET_BUILTIN(__nvvm_match_all_sync_i32p, "UiUiUii*", "", PTX60)
+TARGET_BUILTIN(__nvvm_match_all_sync_i64p, "WiUiWii*", "", PTX60)
// Membar
@@ -462,194 +475,120 @@ BUILTIN(__builtin_ptx_get_image_channel_orderi_, "ii", "")
// - they are used in address space analysis and optimization
// So it does not hurt to expose them as builtins.
//
-BUILTIN(__nvvm_atom_add_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_add_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_add_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_add_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_add_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_add_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_add_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_add_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_add_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_add_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_add_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_add_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_add_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_add_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_add_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_add_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_add_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_add_gen_ll, "LLiLLiD*LLi", "n", "satom")
-BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n")
-BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_add_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_add_gen_ll, "LLiLLiD*LLi", "n", SM_60)
BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n")
-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")
-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")
-
-BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_add_gen_f, "ffD*f", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_add_gen_f, "ffD*f", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_cta_add_gen_d, "ddD*d", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_add_gen_d, "ddD*d", "n", SM_60)
+
BUILTIN(__nvvm_atom_sub_gen_i, "iiD*i", "n")
-BUILTIN(__nvvm_atom_sub_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_sub_s_l, "LiLiD*3Li", "n")
BUILTIN(__nvvm_atom_sub_gen_l, "LiLiD*Li", "n")
-BUILTIN(__nvvm_atom_sub_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_sub_s_ll, "LLiLLiD*3LLi", "n")
BUILTIN(__nvvm_atom_sub_gen_ll, "LLiLLiD*LLi", "n")
-BUILTIN(__nvvm_atom_xchg_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_xchg_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_xchg_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_xchg_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_xchg_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_xchg_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_xchg_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_xchg_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_xchg_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_ll, "LLiLLiD*LLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_ll, "LLiLLiD*LLi", "n", SM_60)
-BUILTIN(__nvvm_atom_max_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_max_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_max_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_max_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_max_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_max_g_ui, "UiUiD*1Ui", "n")
-BUILTIN(__nvvm_atom_max_s_ui, "UiUiD*3Ui", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_max_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_max_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_max_gen_ui, "UiUiD*Ui", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ui, "UiUiD*Ui", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ui, "UiUiD*Ui", "n", "satom")
-BUILTIN(__nvvm_atom_max_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_max_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ui, "UiUiD*Ui", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ui, "UiUiD*Ui", "n", SM_60)
BUILTIN(__nvvm_atom_max_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_max_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_max_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_max_g_ul, "ULiULiD*1ULi", "n")
-BUILTIN(__nvvm_atom_max_s_ul, "ULiULiD*3ULi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_max_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_max_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_max_gen_ul, "ULiULiD*ULi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ul, "ULiULiD*ULi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ul, "ULiULiD*ULi", "n", "satom")
-BUILTIN(__nvvm_atom_max_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_max_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ul, "ULiULiD*ULi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ul, "ULiULiD*ULi", "n", SM_60)
BUILTIN(__nvvm_atom_max_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ll, "LLiLLiD*LLi", "n", "satom")
-BUILTIN(__nvvm_atom_max_g_ull, "ULLiULLiD*1ULLi", "n")
-BUILTIN(__nvvm_atom_max_s_ull, "ULLiULLiD*3ULLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ll, "LLiLLiD*LLi", "n", SM_60)
BUILTIN(__nvvm_atom_max_gen_ull, "ULLiULLiD*ULLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ull, "ULLiULLiD*ULLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ull, "ULLiULLiD*ULLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ull, "ULLiULLiD*ULLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ull, "ULLiULLiD*ULLi", "n", SM_60)
-BUILTIN(__nvvm_atom_min_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_min_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_min_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_min_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_min_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_min_g_ui, "UiUiD*1Ui", "n")
-BUILTIN(__nvvm_atom_min_s_ui, "UiUiD*3Ui", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_min_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_min_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_min_gen_ui, "UiUiD*Ui", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ui, "UiUiD*Ui", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ui, "UiUiD*Ui", "n", "satom")
-BUILTIN(__nvvm_atom_min_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_min_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ui, "UiUiD*Ui", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ui, "UiUiD*Ui", "n", SM_60)
BUILTIN(__nvvm_atom_min_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_min_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_min_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_min_g_ul, "ULiULiD*1ULi", "n")
-BUILTIN(__nvvm_atom_min_s_ul, "ULiULiD*3ULi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_min_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_min_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_min_gen_ul, "ULiULiD*ULi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ul, "ULiULiD*ULi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ul, "ULiULiD*ULi", "n", "satom")
-BUILTIN(__nvvm_atom_min_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_min_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ul, "ULiULiD*ULi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ul, "ULiULiD*ULi", "n", SM_60)
BUILTIN(__nvvm_atom_min_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ll, "LLiLLiD*LLi", "n", "satom")
-BUILTIN(__nvvm_atom_min_g_ull, "ULLiULLiD*1ULLi", "n")
-BUILTIN(__nvvm_atom_min_s_ull, "ULLiULLiD*3ULLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ll, "LLiLLiD*LLi", "n", SM_60)
BUILTIN(__nvvm_atom_min_gen_ull, "ULLiULLiD*ULLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ull, "ULLiULLiD*ULLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ull, "ULLiULLiD*ULLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ull, "ULLiULLiD*ULLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ull, "ULLiULLiD*ULLi", "n", SM_60)
-BUILTIN(__nvvm_atom_inc_g_ui, "UiUiD*1Ui", "n")
-BUILTIN(__nvvm_atom_inc_s_ui, "UiUiD*3Ui", "n")
BUILTIN(__nvvm_atom_inc_gen_ui, "UiUiD*Ui", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_inc_gen_ui, "UiUiD*Ui", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_inc_gen_ui, "UiUiD*Ui", "n", "satom")
-BUILTIN(__nvvm_atom_dec_g_ui, "UiUiD*1Ui", "n")
-BUILTIN(__nvvm_atom_dec_s_ui, "UiUiD*3Ui", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_inc_gen_ui, "UiUiD*Ui", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_inc_gen_ui, "UiUiD*Ui", "n", SM_60)
BUILTIN(__nvvm_atom_dec_gen_ui, "UiUiD*Ui", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_dec_gen_ui, "UiUiD*Ui", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_dec_gen_ui, "UiUiD*Ui", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_dec_gen_ui, "UiUiD*Ui", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_dec_gen_ui, "UiUiD*Ui", "n", SM_60)
-BUILTIN(__nvvm_atom_and_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_and_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_and_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_and_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_and_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_and_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_and_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_and_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_and_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_and_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_and_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_and_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_and_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_and_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_and_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_and_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_and_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_and_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_and_gen_ll, "LLiLLiD*LLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_and_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_and_gen_ll, "LLiLLiD*LLi", "n", SM_60)
-BUILTIN(__nvvm_atom_or_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_or_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_or_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_or_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_or_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_or_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_or_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_or_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_or_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_or_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_or_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_or_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_or_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_or_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_or_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_or_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_or_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_or_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_or_gen_ll, "LLiLLiD*LLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_or_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_or_gen_ll, "LLiLLiD*LLi", "n", SM_60)
-BUILTIN(__nvvm_atom_xor_g_i, "iiD*1i", "n")
-BUILTIN(__nvvm_atom_xor_s_i, "iiD*3i", "n")
BUILTIN(__nvvm_atom_xor_gen_i, "iiD*i", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_i, "iiD*i", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_i, "iiD*i", "n", "satom")
-BUILTIN(__nvvm_atom_xor_g_l, "LiLiD*1Li", "n")
-BUILTIN(__nvvm_atom_xor_s_l, "LiLiD*3Li", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_i, "iiD*i", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_i, "iiD*i", "n", SM_60)
BUILTIN(__nvvm_atom_xor_gen_l, "LiLiD*Li", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_l, "LiLiD*Li", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_l, "LiLiD*Li", "n", "satom")
-BUILTIN(__nvvm_atom_xor_g_ll, "LLiLLiD*1LLi", "n")
-BUILTIN(__nvvm_atom_xor_s_ll, "LLiLLiD*3LLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_l, "LiLiD*Li", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_l, "LiLiD*Li", "n", SM_60)
BUILTIN(__nvvm_atom_xor_gen_ll, "LLiLLiD*LLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_ll, "LLiLLiD*LLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_ll, "LLiLLiD*LLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_ll, "LLiLLiD*LLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_ll, "LLiLLiD*LLi", "n", SM_60)
-BUILTIN(__nvvm_atom_cas_g_i, "iiD*1ii", "n")
-BUILTIN(__nvvm_atom_cas_s_i, "iiD*3ii", "n")
BUILTIN(__nvvm_atom_cas_gen_i, "iiD*ii", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_i, "iiD*ii", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_i, "iiD*ii", "n", "satom")
-BUILTIN(__nvvm_atom_cas_g_l, "LiLiD*1LiLi", "n")
-BUILTIN(__nvvm_atom_cas_s_l, "LiLiD*3LiLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_i, "iiD*ii", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_i, "iiD*ii", "n", SM_60)
BUILTIN(__nvvm_atom_cas_gen_l, "LiLiD*LiLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_l, "LiLiD*LiLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_l, "LiLiD*LiLi", "n", "satom")
-BUILTIN(__nvvm_atom_cas_g_ll, "LLiLLiD*1LLiLLi", "n")
-BUILTIN(__nvvm_atom_cas_s_ll, "LLiLLiD*3LLiLLi", "n")
+TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_l, "LiLiD*LiLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_l, "LiLiD*LiLi", "n", SM_60)
BUILTIN(__nvvm_atom_cas_gen_ll, "LLiLLiD*LLiLLi", "n")
-TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_ll, "LLiLLiD*LLiLLi", "n", "satom")
-TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_ll, "LLiLLiD*LLiLLi", "n", "satom")
+TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60)
+TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60)
// Compiler Error Warn
BUILTIN(__nvvm_compiler_error, "vcC*4", "n")
@@ -692,17 +631,46 @@ 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")
+TARGET_BUILTIN(__hmma_m16n16k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_ld_b, "vi*iC*UiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f16, "vi*iC*UiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f32, "vf*fC*UiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_st_c_f16, "vi*i*UiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_st_c_f32, "vf*f*UiIi", "", AND(SM_70,PTX60))
+
+TARGET_BUILTIN(__hmma_m32n8k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_ld_b, "vi*iC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_ld_c_f16, "vi*iC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_ld_c_f32, "vf*fC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_st_c_f16, "vi*i*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_st_c_f32, "vf*f*UiIi", "", AND(SM_70,PTX61))
+
+TARGET_BUILTIN(__hmma_m8n32k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_ld_b, "vi*iC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_ld_c_f16, "vi*iC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_ld_c_f32, "vf*fC*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_st_c_f16, "vi*i*UiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_st_c_f32, "vf*f*UiIi", "", AND(SM_70,PTX61))
+
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", AND(SM_70,PTX60))
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX60))
+
+TARGET_BUILTIN(__hmma_m32n8k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m32n8k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX61))
+
+TARGET_BUILTIN(__hmma_m8n32k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", AND(SM_70,PTX61))
+TARGET_BUILTIN(__hmma_m8n32k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX61))
#undef BUILTIN
#undef TARGET_BUILTIN
+#pragma pop_macro("AND")
+#pragma pop_macro("SM_60")
+#pragma pop_macro("SM_70")
+#pragma pop_macro("PTX60")
+#pragma pop_macro("PTX61")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
index faa70a48edc3..9be760853d50 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
@@ -58,7 +58,7 @@ BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fIi", "")
BUILTIN(__builtin_altivec_dss, "vUi", "")
BUILTIN(__builtin_altivec_dssall, "v", "")
-BUILTIN(__builtin_altivec_dst, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dst, "vvC*iUi", "")
BUILTIN(__builtin_altivec_dstt, "vvC*iUi", "")
BUILTIN(__builtin_altivec_dstst, "vvC*iUi", "")
BUILTIN(__builtin_altivec_dststt, "vvC*iUi", "")
@@ -423,6 +423,15 @@ BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "")
BUILTIN(__builtin_vsx_xxpermdi, "v.", "t")
BUILTIN(__builtin_vsx_xxsldwi, "v.", "t")
+// Float 128 built-ins
+BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "")
+BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "")
+BUILTIN(__builtin_subf128_round_to_odd, "LLdLLdLLd", "")
+BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "")
+BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "")
+BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "")
+BUILTIN(__builtin_truncf128_round_to_odd, "dLLd", "")
+
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "UiUIi", "")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
index 19318dcebb9e..b3d877dcedf3 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines the WebAssembly-specific builtin function database.
+/// This file defines the WebAssembly-specific builtin function database.
/// Users of this file must define the BUILTIN macro to make use of this
/// information.
///
@@ -16,8 +16,17 @@
// The format of this database matches clang/Basic/Builtins.def.
-// Note that current_memory is not "c" (readnone) because it must be sequenced
-// with respect to grow_memory calls.
+// Query the current memory size, and increase the current memory size.
+// Note that memory.size is not "c" (readnone) because it must be sequenced
+// with respect to memory.grow calls.
+BUILTIN(__builtin_wasm_memory_size, "zIi", "n")
+BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n")
+
+// These are the old names.
+BUILTIN(__builtin_wasm_mem_size, "zIi", "n")
+BUILTIN(__builtin_wasm_mem_grow, "zIiz", "n")
+
+// These are the old old names. They also lack the immediate field.
BUILTIN(__builtin_wasm_current_memory, "z", "n")
BUILTIN(__builtin_wasm_grow_memory, "zz", "n")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
index 9169b7c22920..e98f7d612c3c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
@@ -27,8 +27,6 @@
# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
-// FIXME: Are these nothrow/const?
-
// Miscellaneous builtin for checking x86 cpu features.
// TODO: Make this somewhat generic so that other backends
// can use it?
@@ -38,9 +36,9 @@ BUILTIN(__builtin_cpu_is, "bcC*", "nc")
// Undefined Values
//
-TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "nc", "")
-TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "nc", "")
-TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "nc", "")
+TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "ncV:128:", "")
+TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "ncV:256:", "")
+TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "ncV:512:", "")
// FLAGS
//
@@ -49,33 +47,33 @@ TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "")
// 3DNow!
//
-TARGET_BUILTIN(__builtin_ia32_femms, "v", "", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc", "3dnow")
-TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_femms, "v", "n", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "ncV:64:", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "ncV:64:", "3dnow")
// 3DNow! Extensions (3dnowa).
-TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc", "3dnowa")
-TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc", "3dnowa")
-TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc", "3dnowa")
-TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc", "3dnowa")
-TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc", "3dnowa")
-TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "ncV:64:", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "ncV:64:", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "ncV:64:", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "ncV:64:", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "ncV:64:", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "ncV:64:", "3dnowa")
// MMX
//
@@ -86,1808 +84,1758 @@ TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa")
// argument and our prior approach of using a #define to the current built-in
// doesn't work in the presence of re-declaration of _mm_prefetch for windows.
TARGET_BUILTIN(_mm_prefetch, "vcC*i", "nc", "mmx")
-TARGET_BUILTIN(__builtin_ia32_emms, "v", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "", "mmx")
-TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_emms, "v", "n", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "nV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "nV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "ncV:64:", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "ncV:64:", "mmx")
// MMX2 (MMX+SSE) intrinsics
-TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "ncV:64:", "mmx,sse")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "ncV:64:", "mmx,sse")
// MMX+SSE2
-TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "ncV:64:", "mmx,sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "ncV:64:", "mmx,sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "ncV:64:", "mmx,sse2")
+TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx,sse2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "ncV:64:", "mmx,sse2")
+TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx,sse2")
// MMX+SSSE3
-TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "ncV:64:", "mmx,ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3")
// SSE intrinsics.
-TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "", "sse")
-
-TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "", "sse2")
-
-TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "", "sse")
-
-TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "", "sse2")
-
-TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "", "ssse3")
-TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "", "ssse3")
-
-TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "", "sse")
-TARGET_HEADER_BUILTIN(_mm_setcsr, "vUi", "h","xmmintrin.h", ALL_LANGUAGES, "sse")
-TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "", "sse")
-TARGET_HEADER_BUILTIN(_mm_getcsr, "Ui", "h", "xmmintrin.h", ALL_LANGUAGES, "sse")
-TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_sfence, "v", "", "sse")
-TARGET_HEADER_BUILTIN(_mm_sfence, "v", "h", "xmmintrin.h", ALL_LANGUAGES, "sse")
-TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "", "sse")
-
-TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "", "sse2")
-TARGET_HEADER_BUILTIN(_mm_clflush, "vvC*", "h", "emmintrin.h", ALL_LANGUAGES, "sse2")
-TARGET_BUILTIN(__builtin_ia32_lfence, "v", "", "sse2")
-TARGET_HEADER_BUILTIN(_mm_lfence, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2")
-TARGET_BUILTIN(__builtin_ia32_mfence, "v", "", "sse2")
-TARGET_HEADER_BUILTIN(_mm_mfence, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2")
-TARGET_BUILTIN(__builtin_ia32_pause, "v", "", "")
-TARGET_HEADER_BUILTIN(_mm_pause, "v", "h", "emmintrin.h", ALL_LANGUAGES, "")
-TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "", "sse2")
-
-TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "", "sse3")
-TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "", "sse3")
-
-TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "", "ssse3")
-
-TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "", "sse4.1")
-
-TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "", "sse4.1")
-TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "ncV:128:", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "ncV:128:", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "ncV:128:", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssIi", "ncV:128:", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "ncV:128:", "sse3")
+TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "ncV:128:", "sse3")
+TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "ncV:128:", "sse3")
+TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "ncV:128:", "sse3")
+TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "ncV:128:", "sse3")
+TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "ncV:128:", "sse3")
+TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "ncV:128:", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "ncV:128:", "ssse3")
+
+TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "n", "sse")
+TARGET_HEADER_BUILTIN(_mm_setcsr, "vUi", "nh","xmmintrin.h", ALL_LANGUAGES, "sse")
+TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "n", "sse")
+TARGET_HEADER_BUILTIN(_mm_getcsr, "Ui", "nh", "xmmintrin.h", ALL_LANGUAGES, "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "nV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "nV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "nV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_sfence, "v", "n", "sse")
+TARGET_HEADER_BUILTIN(_mm_sfence, "v", "nh", "xmmintrin.h", ALL_LANGUAGES, "sse")
+TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fIi", "ncV:128:", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "nV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "n", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pshufd, "V4iV4iIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pshuflw, "V8sV8sIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pshufhw, "V8sV8sIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2dIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "n", "sse2")
+TARGET_HEADER_BUILTIN(_mm_clflush, "vvC*", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2")
+TARGET_BUILTIN(__builtin_ia32_lfence, "v", "n", "sse2")
+TARGET_HEADER_BUILTIN(_mm_lfence, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2")
+TARGET_BUILTIN(__builtin_ia32_mfence, "v", "n", "sse2")
+TARGET_HEADER_BUILTIN(_mm_mfence, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2")
+TARGET_BUILTIN(__builtin_ia32_pause, "v", "n", "")
+TARGET_HEADER_BUILTIN(_mm_pause, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "")
+TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslldqi128_byteshift, "V2LLiV2LLiIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrldqi128_byteshift, "V2LLiV2LLiIi", "ncV:128:", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "n", "sse3")
+TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "n", "sse3")
+TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "nV:128:", "sse3")
+
+TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "ncV:128:", "ssse3")
+
+TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "ncV:128:", "sse4.1")
+
+TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v16qi, "cV16cIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16ccIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iiIi", "ncV:128:", "sse4.1")
// SSE 4.2
-TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","", "sse4.2")
-
-TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","", "sse4.2")
-
-TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
+
+TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "nc", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "nc", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "nc", "sse4.2")
// SSE4a
-TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "", "sse4a")
-TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "", "sse4a")
-TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "", "sse4a")
-TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "", "sse4a")
-TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "", "sse4a")
-TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "ncV:128:", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "ncV:128:", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "ncV:128:", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "ncV:128:", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "nV:128:", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "nV:128:", "sse4a")
// AES
-TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "", "aes")
-TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "", "aes")
-TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "", "aes")
-TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "", "aes")
-TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "", "aes")
-TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "ncV:128:", "aes")
+TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "ncV:128:", "aes")
// VAES
-TARGET_BUILTIN(__builtin_ia32_aesenc256, "V4LLiV4LLiV4LLi", "", "vaes")
-TARGET_BUILTIN(__builtin_ia32_aesenc512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes")
-TARGET_BUILTIN(__builtin_ia32_aesenclast256, "V4LLiV4LLiV4LLi", "", "vaes")
-TARGET_BUILTIN(__builtin_ia32_aesenclast512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes")
-TARGET_BUILTIN(__builtin_ia32_aesdec256, "V4LLiV4LLiV4LLi", "", "vaes")
-TARGET_BUILTIN(__builtin_ia32_aesdec512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes")
-TARGET_BUILTIN(__builtin_ia32_aesdeclast256, "V4LLiV4LLiV4LLi", "", "vaes")
-TARGET_BUILTIN(__builtin_ia32_aesdeclast512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes")
+TARGET_BUILTIN(__builtin_ia32_aesenc256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes")
+TARGET_BUILTIN(__builtin_ia32_aesenc512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes")
+TARGET_BUILTIN(__builtin_ia32_aesenclast256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes")
+TARGET_BUILTIN(__builtin_ia32_aesenclast512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes")
+TARGET_BUILTIN(__builtin_ia32_aesdec256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes")
+TARGET_BUILTIN(__builtin_ia32_aesdec512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes")
+TARGET_BUILTIN(__builtin_ia32_aesdeclast256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes")
+TARGET_BUILTIN(__builtin_ia32_aesdeclast512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes")
// GFNI
-TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v16qi, "V16cV16cV16cIc", "", "gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v32qi, "V32cV32cV32cIc", "", "avx,gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v64qi, "V64cV64cV64cIc", "", "avx512bw,gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v16qi, "V16cV16cV16cIc", "", "gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v32qi, "V32cV32cV32cIc", "", "avx,gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v64qi, "V64cV64cV64cIc", "", "avx512bw,gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v16qi, "V16cV16cV16c", "", "gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v32qi, "V32cV32cV32c", "", "avx,gfni")
-TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v64qi, "V64cV64cV64c", "", "avx512bw,gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v16qi, "V16cV16cV16cIc", "ncV:128:", "gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v32qi, "V32cV32cV32cIc", "ncV:256:", "avx,gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v64qi, "V64cV64cV64cIc", "ncV:512:", "avx512bw,gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v16qi, "V16cV16cV16cIc", "ncV:128:", "gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v32qi, "V32cV32cV32cIc", "ncV:256:", "avx,gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v64qi, "V64cV64cV64cIc", "ncV:512:", "avx512bw,gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v16qi, "V16cV16cV16c", "ncV:128:", "gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v32qi, "V32cV32cV32c", "ncV:256:", "avx,gfni")
+TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v64qi, "V64cV64cV64c", "ncV:512:", "avx512bw,gfni")
// CLMUL
-TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "", "pclmul")
+TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "ncV:128:", "pclmul")
// VPCLMULQDQ
-TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4LLiV4LLiV4LLiIc", "", "vpclmulqdq")
-TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8LLiV8LLiV8LLiIc", "", "avx512f,vpclmulqdq")
+TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4LLiV4LLiV4LLiIc", "ncV:256:", "vpclmulqdq")
+TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8LLiV8LLiV8LLiIc", "ncV:512:", "avx512f,vpclmulqdq")
// AVX
-TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "", "avx")
-TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "ncV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "n", "avx")
+TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "n", "avx")
+TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "nV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "nV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "nV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "nV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "nV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "nV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "nV:128:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "nV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "nV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v32qi, "cV32cIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v16hi, "sV16sIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v8si, "iV8iIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v32qi, "V32cV32ccIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v16hi, "V16sV16ssIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v8si, "V8iV8iiIi", "ncV:256:", "avx")
// AVX2
-TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pshufd256, "V8iV8iIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pshuflw256, "V16sV16sIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pshufhw256, "V16sV16sIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslldqi256_byteshift, "V4LLiV4LLiIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrldqi256_byteshift, "V4LLiV4LLiIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permdf256, "V4dV4dIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "ncV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "ncV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "ncV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "ncV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "ncV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "ncV:128:", "avx2")
// GATHER
-TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "", "avx2")
-
-TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "nV:256:", "avx2")
+
+TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "nV:256:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "nV:128:", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "nV:256:", "avx2")
// F16C
-TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "", "f16c")
-TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "", "f16c")
-TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "", "f16c")
-TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "ncV:128:", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "ncV:256:", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "ncV:128:", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "ncV:256:", "f16c")
// RDRAND
-TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "", "rdrnd")
-TARGET_BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "", "rdrnd")
-TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "", "rdrnd")
-
-// FSGSBASE
-TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "n", "rdrnd")
+TARGET_BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "n", "rdrnd")
// FXSR
-TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "", "fxsr")
-TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "n", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "n", "fxsr")
// XSAVE
-TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "", "xsave")
-TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "", "xsave")
-TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "", "xsaveopt")
-TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves")
-TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec")
-TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "n", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "n", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "n", "xsaveopt")
+TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "n", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "n", "xsavec")
+TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "n", "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")
+TARGET_BUILTIN(__builtin_ia32_incsspd, "vUi", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_rdsspd, "UiUi", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_saveprevssp, "v", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_rstorssp, "vv*", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrssd, "vUiv*", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrussd, "vUiv*", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_setssbsy, "v", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_clrssbsy, "vv*", "n", "shstk")
//CLFLUSHOPT
-TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "", "clflushopt")
+TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "n", "clflushopt")
//CLWB
-TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "", "clwb")
+TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "n", "clwb")
+
+//WB[NO]INVD
+TARGET_BUILTIN(__builtin_ia32_wbinvd, "v", "n", "")
+TARGET_BUILTIN(__builtin_ia32_wbnoinvd, "v", "n", "wbnoinvd")
// ADX
-TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx")
-TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "", "")
-TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "", "")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "n", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "n", "")
+TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "n", "")
// RDSEED
-TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "", "rdseed")
-TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "n", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "n", "rdseed")
// BMI
-TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "", "bmi")
+TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "nc", "bmi")
// BMI2
-TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "", "bmi2")
-TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "", "bmi2")
-TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "nc", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "nc", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "nc", "bmi2")
// TBM
-TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "", "tbm")
+TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "nc", "tbm")
// LWP
-TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "", "lwp")
-TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "", "lwp")
-TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "", "lwp")
-TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "", "lwp")
+TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "n", "lwp")
// SHA
-TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "", "sha")
-TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "", "sha")
-TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "", "sha")
-TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "", "sha")
-TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "", "sha")
-TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "", "sha")
-TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "ncV:128:", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "ncV:128:", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "ncV:128:", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "ncV:128:", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "ncV:128:", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "ncV:128:", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "ncV:128:", "sha")
// FMA
-TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "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_vfmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "ncV:128:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "ncV:128:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss3, "V4fV4fV4fV4f", "ncV:128:", "fma")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd3, "V2dV2dV2dV2d", "ncV:128:", "fma")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "ncV:128:", "fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "ncV:128:", "fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "ncV:128:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "ncV:128:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "ncV:256:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "ncV:256:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "ncV:256:", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "ncV:256:", "fma|fma4")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
// XOP
-TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "", "xop")
-
-TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "", "xop")
-TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "", "xop")
-
-TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "", "rtm")
-TARGET_BUILTIN(__builtin_ia32_xend, "v", "", "rtm")
-TARGET_BUILTIN(__builtin_ia32_xabort, "vIc", "", "rtm")
-TARGET_BUILTIN(__builtin_ia32_xtest, "i", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "ncV:128:", "xop")
+
+TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "ncV:256:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "ncV:256:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "ncV:128:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "ncV:256:", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "ncV:256:", "xop")
+
+TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "n", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xend, "v", "n", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xabort, "vIc", "n", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xtest, "i", "n", "rtm")
BUILTIN(__builtin_ia32_rdpmc, "ULLii", "")
BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
BUILTIN(__rdtsc, "ULLi", "")
BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
+
+TARGET_BUILTIN(__builtin_ia32_rdpid, "Ui", "n", "rdpid")
+
// PKU
-TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "", "pku")
-TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "", "pku")
+TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "n", "pku")
+TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "n", "pku")
// AVX-512
-TARGET_BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
-
-TARGET_BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_rcp28sd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_rcp28ss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
-TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
-
-TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "", "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")
-TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fV16fC*V16fUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8ddC*V8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dV8dC*V8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vLLi*V8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vi*V16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_vpdpbusd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusd512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusds128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusds256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusds512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssd512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssds128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssds256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssds512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusds128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusds256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpbusds512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssds128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssds256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_vpdpwssds512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni")
-
-TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "", "avx512pf")
-
-TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_maskz, "V32sV32sV32sV32sUi", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpconflictsi_128_mask, "V4iV4iV4iUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpconflictsi_256_mask, "V8iV8iV8iUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
-TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx512cd")
-TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
-TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
-
-TARGET_BUILTIN(__builtin_ia32_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")
-
-TARGET_BUILTIN(__builtin_ia32_vpopcntb_128, "V16cV16c", "", "avx512vl,avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpopcntw_128, "V8sV8s", "", "avx512vl,avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpopcntb_256, "V32cV32c", "", "avx512vl,avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpopcntw_256, "V16sV16s", "", "avx512vl,avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpopcntb_512, "V64cV64c", "", "avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpopcntw_512, "V32sV32s", "", "avx512bitalg")
-
-TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb128_mask, "UsV16cV16cUs", "", "avx512vl,avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb256_mask, "UiV32cV32cUi", "", "avx512vl,avx512bitalg")
-TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb512_mask, "ULLiV64cV64cULLi", "", "avx512bitalg")
-
-TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_pmulhrsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_addpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_addps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_divpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_divps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_mulpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_mulps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_subpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_subps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_pmaddubsw512_mask, "V32sV64cV64cV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaddwd512_mask, "V16iV32sV32sV16iUs", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_addss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_divss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_mulss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_subss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_maxss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_minss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_addsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_divsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_mulsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_subsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_maxsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_minsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_compresshi128_mask, "V8sV8sV8sUc","","avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compresshi256_mask, "V16sV16sV16sUs","","avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressqi128_mask, "V16cV16cV16cUs","","avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressqi256_mask, "V32cV32cV32cUi","","avx512vl,avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_compressstorehi128_mask, "vV8s*V8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressstorehi256_mask, "vV16s*V16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressstoreqi128_mask, "vV16c*V16cUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressstoreqi256_mask, "vV32c*V32cUi", "", "avx512vl,avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtdq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256_mask, "V4fV4dV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtps2pd128_mask, "V2dV4fV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtps2pd256_mask, "V4dV4fV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtudq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtudq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_expandhi128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandhi256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandqi128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandqi256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2d*V2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4d*V4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLi*V2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLi*V4LLiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_expandloadhi128_mask, "V8sV8sC*V8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandloadhi256_mask, "V16sV16sC*V16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandloadqi128_mask, "V16cV16cC*V16cUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandloadqi256_mask, "V32cV32cC*V32cUi", "", "avx512vl,avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4f*V4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8f*V8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4i*V4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8i*V8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pabsq128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pabsq256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vpermi2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128_mask, "V2dV2dV2LLiV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256_mask, "V4dV4dV4LLiV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varps128_mask, "V4fV4fV4iV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varps256_mask, "V8fV8fV8iV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_mask, "V2dV2LLiV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_maskz, "V2dV2LLiV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_mask, "V4dV4LLiV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_maskz, "V4dV4LLiV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_mask, "V4fV4iV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_maskz, "V4fV4iV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_mask, "V8fV8iV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_maskz, "V8fV8iV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_vpshldd128_mask, "V4iV4iV4iIiV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldd256_mask, "V8iV8iV8iIiV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldd512_mask, "V16iV16iV16iIiV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldq128_mask, "V2LLiV2LLiV2LLiIiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldq256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldw128_mask, "V8sV8sV8sIiV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldw256_mask, "V16sV16sV16sIiV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldw512_mask, "V32sV32sV32sIiV32sUi", "", "avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "", "avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "", "avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_vpshrdd128_mask, "V4iV4iV4iIiV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdd256_mask, "V8iV8iV8iIiV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdd512_mask, "V16iV16iV16iIiV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdq128_mask, "V2LLiV2LLiV2LLiIiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdq256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdw128_mask, "V8sV8sV8sIiV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdw256_mask, "V16sV16sV16sIiV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdw512_mask, "V32sV32sV32sIiV32sUi", "", "avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangesd128_round_mask, "V2dV2dV2dV2dUcIiIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangess128_round_mask, "V4fV4fV4fV4fUcIiIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reducesd_mask, "V2dV2dV2dV2dUcIiIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reducess_mask, "V4fV4fV4fV4fUcIiIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovwb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_prold512_mask, "V16iV16iIiV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prolq512_mask, "V8LLiV8LLiIiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prold128_mask, "V4iV4iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prold256_mask, "V8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prolq128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prolq256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prolvd512_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prolvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prord512_mask, "V16iV16iiV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prorq512_mask, "V8LLiV8LLiiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prolvd128_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prolvd256_mask, "V8iV8iV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prolvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prolvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prord128_mask, "V4iV4iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prord256_mask, "V8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prorq128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prorq256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prorvd512_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prorvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_prorvd128_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prorvd256_mask, "V8iV8iV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prorvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_prorvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psllv16hi, "V16sV16sV16s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv8hi, "V8sV8sV8s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslldi512, "V16iV16ii","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllqi512, "V8LLiV8LLii","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlv32hi, "V32sV32sV32s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrlv16hi, "V16sV16sV16s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv8hi, "V8sV8sV8s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrldi512, "V16iV16ii","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlqi512, "V8LLiV8LLii","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrav32hi, "V32sV32sV32s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrav16hi, "V16sV16sV16s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrav8hi, "V8sV8sV8s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psravq128, "V2LLiV2LLiV2LLi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psravq256, "V4LLiV4LLiV4LLi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8LLiV8LLiC*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa64store512_mask, "vV8LLi*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa32store128_mask, "vV4i*V4iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa32store256_mask, "vV8i*V8iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc","","avx512vl")
-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_vpmadd52huq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varqi512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varqi512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varqi512_maskz, "V64cV64cV64cV64cULLi","","avx512vbmi")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varqi128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varqi256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varqi128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varqi128_maskz, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varqi256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermt2varqi256_maskz, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kunpckdi, "ULLiULLiULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_kunpcksi, "UiUiUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cULLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8LLiIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8LLiIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmps512_maskz, "V16fV16fV16fV16iIiUsIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmsd_mask, "V2dV2dV2dV2LLiIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmsd_maskz, "V2dV2dV2dV2LLiIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmss_mask, "V4fV4fV4fV4iIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_fixupimmss_maskz, "V4fV4fV4fV4iIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_maskz, "V4dV4dV4dV4LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V8dV8d*V8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V16fV16f*V16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2LLiV2LLi*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4LLiV4LLi*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_storedquqi128_mask, "vV16c*V16cUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_storedquqi256_mask, "vV32c*V32cUi","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_storeapd128_mask, "vV2d*V2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storesd128_mask, "vV8d*V8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_storeapd256_mask, "vV4d*V4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storeaps128_mask, "vV4f*V4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storess128_mask, "vV16f*V16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_storeaps256_mask, "vV8f*V8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storedqudi128_mask, "vV2LLi*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storedqudi256_mask, "vV4LLi*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storedqusi128_mask, "vV4i*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storedqusi256_mask, "vV8i*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storeupd128_mask, "vV2d*V2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storeupd256_mask, "vV4d*V4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storeups128_mask, "vV4f*V4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_storeups256_mask, "vV8f*V8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rcp14pd128_mask, "V2dV2dV2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rcp14pd256_mask, "V4dV4dV4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rcp14ps128_mask, "V4fV4fV4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rcp14ps256_mask, "V8fV8fV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vplzcntd_128_mask, "V4iV4iV4iUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vplzcntd_256_mask, "V8iV8iV8iUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vplzcntq_128_mask, "V2LLiV2LLiV2LLiUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vplzcntq_256_mask, "V4LLiV4LLiV4LLiUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermi2vard512_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varpd512_mask, "V8dV8dV8LLiV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varps512_mask, "V16fV16fV16iV16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermi2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_maskz, "V16iV16iV16iV16iUs","","avx512f")
-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_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_scalefps512_mask, "V16fV16fV16fV16fUsIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_scalefsd_round_mask, "V2dV2dV2dV2dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_scalefss_round_mask, "V4fV4fV4fV4fUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psradi512, "V16iV16ii","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psraqi512, "V8LLiV8LLii","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psraq128, "V2LLiV2LLiV2LLi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraq256, "V4LLiV4LLiV2LLi","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraqi128, "V2LLiV2LLii","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraqi256, "V4LLiV4LLii","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslld512, "V16iV16iV4i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllq512, "V8LLiV8LLiV2LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllv16si, "V16iV16iV16i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllv8di, "V8LLiV8LLiV8LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrad512, "V16iV16iV4i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psraq512, "V8LLiV8LLiV2LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrav16si, "V16iV16iV16i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrav8di, "V8LLiV8LLiV8LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrld512, "V16iV16iV4i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlq512, "V8LLiV8LLiV2LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlv16si, "V16iV16iV16i","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlv8di, "V8LLiV8LLiV8LLi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pternlogd512_mask, "V16iV16iV16iV16iIiUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pternlogd512_maskz, "V16iV16iV16iV16iIiUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pternlogq512_mask, "V8LLiV8LLiV8LLiV8LLiIiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pternlogq512_maskz, "V8LLiV8LLiV8LLiV8LLiIiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pternlogd128_mask, "V4iV4iV4iV4iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogd128_maskz, "V4iV4iV4iV4iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogd256_mask, "V8iV8iV8iV8iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogd256_maskz, "V8iV8iV8iV8iIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_mask, "V16fV16fV16fIiV16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_mask, "V8dV8dV8dIiV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_mask, "V16iV16iV16iIiV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_mask, "V8LLiV8LLiV8LLiIiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256_mask, "V8fV8fV8fIiV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256_mask, "V4dV4dV4dIiV4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256_mask, "V8iV8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14pd256_mask, "V4dV4dV4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14ps128_mask, "V4fV4fV4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_rsqrt14ps256_mask, "V8fV8fV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtb2mask512, "ULLiV64c","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2b512, "V64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2w512, "V32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cvtd2mask512, "UsV16i","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2d512, "V16iUs","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2q512, "V8LLiUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtq2mask512, "UcV8LLi","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_cvtb2mask128, "UsV16c","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtb2mask256, "UiV32c","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2b128, "V16cUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2b256, "V32cUi","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2w128, "V8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2w256, "V16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtd2mask128, "UcV4i","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtd2mask256, "UcV8i","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2d128, "V4iUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtmask2d256, "V8iUc","","avx512dq,avx512vl")
-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_pmovsdb512_mask, "V16cV16iV16cUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovsdw512_mask, "V16sV16iV16sUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsdw512mem_mask, "vV16s*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsqb512_mask, "V16cV8LLiV16cUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsqb512mem_mask, "vV16c*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsqd512_mask, "V8iV8LLiV8iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsqd512mem_mask, "vV8i*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsqw512_mask, "V8sV8LLiV8sUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsqw512mem_mask, "vV8s*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsdb128_mask, "V16cV4iV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsdb128mem_mask, "vV16c*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovswb128mem_mask, "vV16c*V8sUc","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovsdb256_mask, "V16cV8iV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsdb256mem_mask, "vV16c*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovswb256mem_mask, "vV16c*V16sUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovsdw128_mask, "V8sV4iV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsdw128mem_mask, "vV8s*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsdw256_mask, "V8sV8iV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsdw256mem_mask, "vV8s*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqb128_mask, "V16cV2LLiV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqb128mem_mask, "vV16c*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqb256_mask, "V16cV4LLiV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqb256mem_mask, "vV16c*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqd128_mask, "V4iV2LLiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqd128mem_mask, "vV4i*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqd256_mask, "V4iV4LLiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqd256mem_mask, "vV4i*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqw128_mask, "V8sV2LLiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqw128mem_mask, "vV8s*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqw256_mask, "V8sV4LLiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsqw256mem_mask, "vV8s*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusdb512_mask, "V16cV16iV16cUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusdb512mem_mask, "vV16c*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovuswb512mem_mask, "vV32c*V32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovusdw512_mask, "V16sV16iV16sUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusdw512mem_mask, "vV16s*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusqb512_mask, "V16cV8LLiV16cUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusqb512mem_mask, "vV16c*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusqd512_mask, "V8iV8LLiV8iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusqd512mem_mask, "vV8i*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusqw512_mask, "V8sV8LLiV8sUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusqw512mem_mask, "vV8s*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovusdb128_mask, "V16cV4iV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusdb128mem_mask, "vV16c*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovuswb128mem_mask, "vV16c*V8sUc","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovusdb256_mask, "V16cV8iV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusdb256mem_mask, "vV16c*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovuswb256mem_mask, "vV16c*V16sUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovusdw128_mask, "V8sV4iV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusdw128mem_mask, "vV8s*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusdw256_mask, "V8sV8iV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusdw256mem_mask, "vV8s*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqb128_mask, "V16cV2LLiV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqb128mem_mask, "vV16c*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqb256_mask, "V16cV4LLiV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqb256mem_mask, "vV16c*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqd128_mask, "V4iV2LLiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqd128mem_mask, "vV4i*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqd256_mask, "V4iV4LLiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqd256mem_mask, "vV4i*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqw128_mask, "V8sV2LLiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqw128mem_mask, "vV8s*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqw256_mask, "V8sV4LLiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovusqw256mem_mask, "vV8s*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovdb512_mask, "V16cV16iV16cUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovdb512mem_mask, "vV16c*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovwb512mem_mask, "vV32c*V32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovdb128_mask, "V16cV4iV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovwb128mem_mask, "vV16c*V8sUc","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovdb128mem_mask, "vV16c*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovdb256_mask, "V16cV8iV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovdb256mem_mask, "vV16c*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovwb256mem_mask, "vV16c*V16sUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovdw128_mask, "V8sV4iV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovdw128mem_mask, "vV8s*V4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovdw256_mask, "V8sV8iV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovdw256mem_mask, "vV8s*V8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqb128_mask, "V16cV2LLiV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqb128mem_mask, "vV16c*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqb256_mask, "V16cV4LLiV16cUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqb256mem_mask, "vV16c*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqd128_mask, "V4iV2LLiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqd128mem_mask, "vV4i*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqd256_mask, "V4iV4LLiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqd256mem_mask, "vV4i*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2diV2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4diV4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fiV4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getmantps256_mask, "V8fV8fiV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_getmantpd512_mask, "V8dV8diV8dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getmantps512_mask, "V16fV16fiV16fUsIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getexppd512_mask, "V8dV8dV8dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_getexpps512_mask, "V16fV16fV16fUsIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddss3_maskz, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask3, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubss3_mask3, "V4fV4fV4fV4fUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_permvarhi512_mask, "V32sV32sV32sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_permvardf512_mask, "V8dV8dV8LLiV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_permvardi512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_permvarsf512_mask, "V16fV16fV16iV16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_permvarsi512_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_permvarqi512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi")
-TARGET_BUILTIN(__builtin_ia32_permvarqi128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvarqi256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvarhi128_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvarhi256_mask, "V16sV16sV16sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvardf256_mask, "V4dV4dV4LLiV4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvardi256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvarsf256_mask, "V8fV8fV8iV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_permvarsi256_mask, "V8iV8iV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fpclasspd128_mask, "UcV2dIiUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fpclasspd256_mask, "UcV4dIiUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fpclassps128_mask, "UcV4fIiUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fpclassps256_mask, "UcV8fIiUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_kandhi, "UsUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kandnhi, "UsUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_korhi, "UsUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kortestchi, "iUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_palignr512_mask, "V64cV64cV64cIiV64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_dbpsadbw128_mask, "V8sV16cV16cIiV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_dbpsadbw256_mask, "V16sV32cV32cIiV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_dbpsadbw512_mask, "V32sV64cV64cIiV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compresshi512_mask, "V32sV32sV32sUi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressqi512_mask, "V64cV64cV64cULLi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandqi512_mask, "V64cV64cV64cULLi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandloaddf512_mask, "V8dV8dC*V8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expandloaddi512_mask, "V8LLiV8LLiC*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expandloadhi512_mask, "V32sV32sC*V32sUi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandloadqi512_mask, "V64cV64cC*V64cULLi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_expandloadsf512_mask, "V16fV16fC*V16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expandloadsi512_mask, "V16iV16iC*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expandsf512_mask, "V16fV16fV16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_expandsi512_mask, "V16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtps2pd512_mask, "V8dV8fV8dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compressstoredf512_mask, "vV8d*V8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compressstoredi512_mask, "vV8LLi*V8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compressstorehi512_mask, "vV32s*V32sUi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressstoreqi512_mask, "vV64c*V64cULLi","","avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_compressstoresf512_mask, "vV16f*V16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_compressstoresi512_mask, "vV16i*V16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtph2ps_mask, "V4fV8sV4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256_mask, "V8fV8sV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vcvtps2ph_mask, "V8sV4fIiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256_mask, "V8sV8fIiV8sUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtw2mask512, "UiV32s","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_cvtw2mask128, "UcV8s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtw2mask256, "UsV16s","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtusi2sd32, "V2dV2dUi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi")
-TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd512, "V8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_sqrtps512, "V16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er")
+
+TARGET_BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_rcp28sd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28ss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er")
+
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "ncV:128:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pabsd512, "V16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pabsq512, "V8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxud512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminsd512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminsq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminud512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminuq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16ffC*V16fUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fV16fC*V16fUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8ddC*V8dUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dV8dC*V8dUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vLLi*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vi*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignd512, "V16iV16iV16iIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "ncV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpbusd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpbusds128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpbusds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpbusds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpwssd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpwssd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpwssd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpwssds128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpwssds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni")
+TARGET_BUILTIN(__builtin_ia32_vpdpwssds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni")
+
+TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "nV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "nV:512:", "avx512pf")
+
+TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "nc", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "ncV:512:", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pabsb512, "V64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw512, "V32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpconflictsi_128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpconflictsi_256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vplzcntd_512, "V16iV16i", "ncV:512:", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vplzcntq_512, "V8LLiV8LLi", "ncV:512:", "avx512cd")
+
+TARGET_BUILTIN(__builtin_ia32_vpopcntd_128, "V4iV4i", "ncV:128:", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntq_128, "V2LLiV2LLi", "ncV:128:", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntd_256, "V8iV8i", "ncV:256:", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntq_256, "V4LLiV4LLi", "ncV:256:", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "ncV:512:", "avx512vpopcntdq")
+TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "ncV:512:", "avx512vpopcntdq")
+
+TARGET_BUILTIN(__builtin_ia32_vpopcntb_128, "V16cV16c", "ncV:128:", "avx512vl,avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpopcntw_128, "V8sV8s", "ncV:128:", "avx512vl,avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpopcntb_256, "V32cV32c", "ncV:256:", "avx512vl,avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpopcntw_256, "V16sV16s", "ncV:256:", "avx512vl,avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpopcntb_512, "V64cV64c", "ncV:512:", "avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpopcntw_512, "V32sV32s", "ncV:512:", "avx512bitalg")
+
+TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb128_mask, "UsV16cV16cUs", "ncV:128:", "avx512vl,avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb256_mask, "UiV32cV32cUi", "ncV:256:", "avx512vl,avx512bitalg")
+TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb512_mask, "ULLiV64cV64cULLi", "ncV:512:", "avx512bitalg")
+
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_addpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_addps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw512, "V32sV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd512, "V16iV32sV32s", "ncV:512:", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_addss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_addsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_compresshi128_mask, "V8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compresshi256_mask, "V16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressqi128_mask, "V16cV16cV16cUs", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressqi256_mask, "V32cV32cV32cUi", "ncV:256:", "avx512vl,avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_compressstorehi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressstorehi256_mask, "vV16s*V16sUs", "nV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressstoreqi128_mask, "vV16c*V16cUs", "nV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressstoreqi256_mask, "vV32c*V32cUi", "nV:256:", "avx512vl,avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_expandhi128_mask, "V8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandhi256_mask, "V16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandqi128_mask, "V16cV16cV16cUs", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandqi256_mask, "V32cV32cV32cUi", "ncV:256:", "avx512vl,avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2dC*V2dUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4dC*V4dUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLiC*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLiC*V4LLiUc", "nV:256:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_expandloadhi128_mask, "V8sV8sC*V8sUc", "nV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandloadhi256_mask, "V16sV16sC*V16sUs", "nV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandloadqi128_mask, "V16cV16cC*V16cUs", "nV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandloadqi256_mask, "V32cV32cC*V32cUi", "nV:256:", "avx512vl,avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4fC*V4fUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8fC*V8fUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4iC*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8iC*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsq128, "V2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsq256, "V4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminuq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminuq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "ncV:256:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "nV:256:", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard512, "V16iV16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128, "V2dV2dV2LLiV2d", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256, "V4dV4dV4LLiV4d", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd512, "V8dV8dV8LLiV8d", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps128, "V4fV4fV4iV4f", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps256, "V8fV8fV8iV8f", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps512, "V16fV16fV16iV16f", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varqi128, "V16cV16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varqi256, "V32cV32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varqi512, "V64cV64cV64cV64c", "ncV:512:", "avx512vbmi")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512, "V32sV32sV32sV32s", "ncV:512:", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpshldd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldd512, "V16iV16iV16iIi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdd512, "V16iV16iV16iIi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangesd128_round_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangess128_round_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducesd_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducess_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "ncV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_prold512, "V16iV16iIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prolq512, "V8LLiV8LLiIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prold128, "V4iV4iIi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prold256, "V8iV8iIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prolq128, "V2LLiV2LLiIi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prolq256, "V4LLiV4LLiIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prolvd512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prolvq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prord512, "V16iV16iIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prorq512, "V8LLiV8LLiIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prolvd128, "V4iV4iV4i", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prolvd256, "V8iV8iV8i", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prolvq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prolvq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prord128, "V4iV4iIi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prord256, "V8iV8iIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prorq128, "V2LLiV2LLiIi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prorq256, "V4LLiV4LLiIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prorvd512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prorvq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_prorvd128, "V4iV4iV4i", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prorvd256, "V8iV8iV8i", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prorvq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_prorvq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pshufhw512, "V32sV32sIi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshuflw512, "V32sV32sIi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psllv16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psllv8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pslldi512, "V16iV16ii", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psllqi512, "V8LLiV8LLii", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrlv32hi, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psrlv16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psrlv8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psrldi512, "V16iV16ii", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrlqi512, "V8LLiV8LLii", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrav32hi, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psrav16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psrav8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psravq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psravq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pslldqi512_byteshift, "V8LLiV8LLiIi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psrldqi512_byteshift, "V8LLiV8LLiIi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8LLiV8LLiC*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_movdqa64store512_mask, "vV8LLi*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_movdqa32store128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa32store256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa64load256_mask, "V4LLiV4LLiC*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa64store128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_movdqa64store256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512ifma")
+TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512ifma")
+TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512ifma,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512ifma,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512ifma,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512ifma,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kunpckdi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kunpcksi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cULLi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8LLiIiUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8LLiIiUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmps512_maskz, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmsd_mask, "V2dV2dV2dV2LLiIiUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmsd_maskz, "V2dV2dV2dV2LLiIiUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmss_mask, "V4fV4fV4fV4iIiUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_fixupimmss_maskz, "V4fV4fV4fV4iIiUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc", "nV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs", "nV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs", "nV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi", "nV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2LLiIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2LLiIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4LLiIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_maskz, "V4dV4dV4dV4LLiIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2LLiV2LLi*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4LLiV4LLi*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cULLi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs", "nV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_storedquqi128_mask, "vV16c*V16cUs", "nV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_storedquqi256_mask, "vV32c*V32cUi", "nV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_storeapd128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storesd128_mask, "vV2d*V2dUc", "nV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeapd256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storeaps128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storess128_mask, "vV4f*V4fUc", "nV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeaps256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storedqudi128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storedqudi256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storedqusi128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storedqusi256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storeupd128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storeupd256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storeups128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_storeups256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rcp14pd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rcp14pd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rcp14ps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rcp14ps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vplzcntd_128, "V4iV4i", "ncV:128:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vplzcntd_256, "V8iV8i", "ncV:256:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vplzcntq_128, "V2LLiV2LLi", "ncV:128:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vplzcntq_256, "V4LLiV4LLi", "ncV:256:", "avx512cd,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermilpd512, "V8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermilps512, "V16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scalefps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scalefsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scalefss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psradi512, "V16iV16ii", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psraqi512, "V8LLiV8LLii", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psraq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psraq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psraqi128, "V2LLiV2LLii", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psraqi256, "V4LLiV4LLii", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pslld512, "V16iV16iV4i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psllq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psllv16si, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psllv8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrad512, "V16iV16iV4i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psraq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrav16si, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrav8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrld512, "V16iV16iV4i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrlq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrlv16si, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psrlv8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pternlogd512_mask, "V16iV16iV16iV16iIiUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pternlogd512_maskz, "V16iV16iV16iV16iIiUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pternlogq512_mask, "V8LLiV8LLiV8LLiV8LLiIiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pternlogq512_maskz, "V8LLiV8LLiV8LLiV8LLiIiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pternlogd128_mask, "V4iV4iV4iV4iIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogd128_maskz, "V4iV4iV4iV4iIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogd256_mask, "V8iV8iV8iV8iIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogd256_maskz, "V8iV8iV8iV8iIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_shuf_f32x4, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_shuf_f64x2, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_shuf_i32x4, "V16iV16iV16iIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_shuf_i64x2, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_shufpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_shufps512, "V16fV16fV16fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256, "V8fV8fV8fIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256, "V4dV4dV4dIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256, "V8iV8iV8iIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14pd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtb2mask512, "ULLiV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2b512, "V64cULLi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2w512, "V32sUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtd2mask512, "UsV16i", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2d512, "V16iUs", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2q512, "V8LLiUc", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtq2mask512, "UcV8LLi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtb2mask128, "UsV16c", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtb2mask256, "UiV32c", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2b128, "V16cUs", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2b256, "V32cUi", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2w128, "V8sUc", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2w256, "V16sUs", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtd2mask128, "UcV4i", "ncV:128:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtd2mask256, "UcV8i", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2d128, "V4iUc", "ncV:128:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2d256, "V8iUc", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2q128, "V2LLiUc", "ncV:128:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtmask2q256, "V4LLiUc", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi", "ncV:128:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovsdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovsdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovswb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovsdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovswb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovsdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqd256_mask, "V4iV4LLiV4iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovsqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovusdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovusdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovusdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovusdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqd256_mask, "V4iV4LLiV4iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovusqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovwb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmovdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovwb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovwb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_extractf32x8_mask, "V8fV16fIiV8fUc", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_extractf64x2_512_mask, "V2dV8dIiV2dUc", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_extracti32x8_mask, "V8iV16iIiV8iUc", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_extracti64x2_512_mask, "V2LLiV8LLiIiV2LLiUc", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_extracti32x4_mask, "V4iV16iIiV4iUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extracti64x4_mask, "V4LLiV8LLiIiV4LLiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extractf64x2_256_mask, "V2dV4dIiV2dUc", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_extracti64x2_256_mask, "V2LLiV4LLiIiV2LLiUc", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_extractf32x4_256_mask, "V4fV8fIiV4fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_extracti32x4_256_mask, "V4iV8iIiV4iUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_insertf32x8, "V16fV16fV8fIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_insertf64x2_512, "V8dV8dV2dIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_inserti32x8, "V16iV16iV8iIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_inserti64x2_512, "V8LLiV8LLiV2LLiIi", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_insertf64x4, "V8dV8dV4dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_inserti64x4, "V8LLiV8LLiV4LLiIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_insertf64x2_256, "V4dV4dV2dIi", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_inserti64x2_256, "V4LLiV4LLiV2LLiIi", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_insertf32x4_256, "V8fV8fV4fIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_inserti32x4_256, "V8iV8iV4iIi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_insertf32x4, "V16fV16fV4fIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_inserti32x4, "V16iV16iV4iIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getmantps256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getmantpd512_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getmantps512_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getexppd512_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_getexpps512_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss3_maskz, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask3, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permdf512, "V8dV8dIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permdi512, "V8LLiV8LLiIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permvarhi512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_permvardf512, "V8dV8dV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permvardi512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permvarsf512, "V16fV16fV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permvarsi512, "V16iV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_permvarqi512, "V64cV64cV64c", "ncV:512:", "avx512vbmi")
+TARGET_BUILTIN(__builtin_ia32_permvarqi128, "V16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_permvarqi256, "V32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_permvarhi128, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_permvarhi256, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_permvardf256, "V4dV4dV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_permvardi256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fpclasspd128_mask, "UcV2dIiUc", "ncV:128:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fpclasspd256_mask, "UcV4dIiUc", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fpclassps128_mask, "UcV4fIiUc", "ncV:128:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fpclassps256_mask, "UcV8fIiUc", "ncV:256:", "avx512dq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc", "ncV:512:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kandhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kandnhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_korhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kortestchi, "iUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_palignr512, "V64cV64cV64cIi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_dbpsadbw128, "V8sV16cV16cIi", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_dbpsadbw256, "V16sV32cV32cIi", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_dbpsadbw512, "V32sV64cV64cIi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compresshi512_mask, "V32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressqi512_mask, "V64cV64cV64cULLi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pshufd512, "V16iV16iIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandqi512_mask, "V64cV64cV64cULLi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandloaddf512_mask, "V8dV8dC*V8dUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi512_mask, "V8LLiV8LLiC*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expandloadhi512_mask, "V32sV32sC*V32sUi", "nV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandloadqi512_mask, "V64cV64cC*V64cULLi", "nV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_expandloadsf512_mask, "V16fV16fC*V16fUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expandsf512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_expandsi512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd512_mask, "V8dV8fV8dUcIi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf512_mask, "vV8d*V8dUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi512_mask, "vV8LLi*V8LLiUc", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compressstorehi512_mask, "vV32s*V32sUi", "nV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressstoreqi512_mask, "vV64c*V64cULLi", "nV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_compressstoresf512_mask, "vV16f*V16fUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi512_mask, "vV16i*V16iUs", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps_mask, "V4fV8sV4fUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256_mask, "V8fV8sV8fUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph_mask, "V8sV4fIiV8sUc", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256_mask, "V8sV8fIiV8sUc", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtw2mask512, "UiV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtw2mask128, "UcV8s", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtw2mask256, "UsV16s", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512vbmi")
+TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "ncV:128:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "ncV:256:", "avx512vbmi,avx512vl")
// generic select intrinsics
-TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "", "")
-TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "", "")
+TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "ncV:128:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "ncV:256:", "avx512bw,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "ncV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "ncV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "ncV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_selectss_128, "V4fUcV4fV4f", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_selectsd_128, "V2dUcV2dV2d", "ncV:128:", "avx512f")
// MONITORX/MWAITX
-TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "", "mwaitx")
-TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx")
+TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "n", "mwaitx")
+TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "n", "mwaitx")
+
+// WAITPKG
+TARGET_BUILTIN(__builtin_ia32_umonitor, "vv*", "n", "waitpkg")
+TARGET_BUILTIN(__builtin_ia32_umwait, "UcUiUiUi", "n", "waitpkg")
+TARGET_BUILTIN(__builtin_ia32_tpause, "UcUiUiUi", "n", "waitpkg")
// CLZERO
-TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "", "clzero")
+TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "n", "clzero")
+
+// CLDEMOTE
+TARGET_BUILTIN(__builtin_ia32_cldemote, "vvC*", "n", "cldemote")
+
+// Direct Move
+TARGET_BUILTIN(__builtin_ia32_directstore_u32, "vUi*Ui", "n", "movdiri")
+TARGET_BUILTIN(__builtin_ia32_movdir64b, "vv*vC*", "n", "movdir64b")
+
+// PTWRITE
+TARGET_BUILTIN(__builtin_ia32_ptwrite32, "vUi", "n", "ptwrite")
+
+// INVPCID
+TARGET_BUILTIN(__builtin_ia32_invpcid, "vUiv*", "nc", "invpcid")
// MSVC
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -1897,14 +1845,14 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES
TARGET_HEADER_BUILTIN(_ReadBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_WriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(__emul, "LLiii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__emul, "LLiii", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(__int2c, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(__ud2, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__int2c, "v", "nhr", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__ud2, "v", "nhr", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsbyte, "UcUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsword, "UsUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
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 fe2c887c7e0f..cc400c0697f9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def
@@ -27,8 +27,8 @@ TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_
TARGET_HEADER_BUILTIN(__mulh, "LLiLLiLLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_mul128, "LLiLLiLLiLLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_mul128, "LLiLLiLLiLLi*", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__faststorefence, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -44,50 +44,62 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh",
TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "")
TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "")
-TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "", "sse4.2")
-TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "", "fxsr")
-TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "", "fxsr")
-TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "", "xsave")
-TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "", "xsave")
-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*", "", "")
-TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "", "rdseed")
-TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "", "bmi")
-TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "", "bmi2")
-TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "", "bmi2")
-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_vcvtsd2si64, "LLiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtsi2sd64, "V2dV2dLLiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi","","avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "n", "sse2")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "ncV:128:", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "nc", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "ncV:256:", "avx")
+TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "n", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "n", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "n", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "n", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "n", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "n", "xsaveopt")
+TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "n", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "n", "xsavec")
+TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "n", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_incsspq, "vULLi", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_rdsspq, "ULLiULLi", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrssq, "vULLiv*", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrussq, "vULLiv*", "n", "shstk")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "n", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "n", "")
+TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "n", "")
+TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "n", "rdrnd")
+TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "n", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "nc", "bmi")
+TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "nc", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "nc", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "nc", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "nc", "tbm")
+TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcULLiUiUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpval64, "vULLiUiUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtsi2sd64, "V2dV2dLLiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi", "ncV:128:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_directstore_u64, "vULi*ULi", "n", "movdiri")
+TARGET_BUILTIN(__builtin_ia32_ptwrite64, "vULLi", "n", "ptwrite")
#undef BUILTIN
#undef TARGET_BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h b/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h
index c4a289b696dd..324e1b1d3d09 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h
@@ -13,9 +13,10 @@
namespace clang {
-/// \brief The different kinds of captured statement.
+/// The different kinds of captured statement.
enum CapturedRegionKind {
CR_Default,
+ CR_ObjCAtFinally,
CR_OpenMP
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
index cc27bbb48e0d..e6c5e90d346c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
@@ -1,4 +1,4 @@
-//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters ------------===//
+//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -180,14 +180,15 @@ LLVM_READONLY inline char toUppercase(char c) {
/// Return true if this is a valid ASCII identifier.
///
-/// Note that this is a very simple check; it does not accept '$' or UCNs as
-/// valid identifier characters.
-LLVM_READONLY inline bool isValidIdentifier(StringRef S) {
- if (S.empty() || !isIdentifierHead(S[0]))
+/// Note that this is a very simple check; it does not accept UCNs as valid
+/// identifier characters.
+LLVM_READONLY inline bool isValidIdentifier(StringRef S,
+ bool AllowDollar = false) {
+ if (S.empty() || !isIdentifierHead(S[0], AllowDollar))
return false;
for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I)
- if (!isIdentifierBody(*I))
+ if (!isIdentifierBody(*I, AllowDollar))
return false;
return true;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h
index 92419f91b741..6cc9cf6b199c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h
@@ -1,4 +1,4 @@
-//===--- CommentOptions.h - Options for parsing comments -----*- C++ -*-===//
+//===- CommentOptions.h - Options for parsing comments ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the clang::CommentOptions interface.
-///
+/// Defines the clang::CommentOptions interface.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_COMMENTOPTIONS_H
@@ -20,20 +20,20 @@
namespace clang {
-/// \brief Options for controlling comment parsing.
+/// Options for controlling comment parsing.
struct CommentOptions {
- typedef std::vector<std::string> BlockCommandNamesTy;
+ using BlockCommandNamesTy = std::vector<std::string>;
- /// \brief Command names to treat as block commands in comments.
+ /// Command names to treat as block commands in comments.
/// Should not include the leading backslash.
BlockCommandNamesTy BlockCommandNames;
- /// \brief Treat ordinary comments as documentation comments.
- bool ParseAllComments;
+ /// Treat ordinary comments as documentation comments.
+ bool ParseAllComments = false;
- CommentOptions() : ParseAllComments(false) { }
+ CommentOptions() = default;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_COMMENTOPTIONS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h b/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h
index 1a0731c37a35..24159e160f3f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h
@@ -22,7 +22,9 @@ enum class CudaVersion {
CUDA_75,
CUDA_80,
CUDA_90,
- LATEST = CUDA_90,
+ CUDA_91,
+ CUDA_92,
+ LATEST = CUDA_92,
};
const char *CudaVersionToString(CudaVersion V);
@@ -44,6 +46,21 @@ enum class CudaArch {
SM_61,
SM_62,
SM_70,
+ SM_72,
+ GFX600,
+ GFX601,
+ GFX700,
+ GFX701,
+ GFX702,
+ GFX703,
+ GFX704,
+ GFX801,
+ GFX802,
+ GFX803,
+ GFX810,
+ GFX900,
+ GFX902,
+ LAST,
};
const char *CudaArchToString(CudaArch A);
@@ -64,6 +81,8 @@ enum class CudaVirtualArch {
COMPUTE_61,
COMPUTE_62,
COMPUTE_70,
+ COMPUTE_72,
+ COMPUTE_AMDGCN,
};
const char *CudaVirtualArchToString(CudaVirtualArch A);
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DebugInfoOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/DebugInfoOptions.h
index e7ff4a662b63..037c813c6114 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DebugInfoOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DebugInfoOptions.h
@@ -28,7 +28,7 @@ enum DebugInfoKind {
/// forward decls for types that could be
/// replaced with forward decls in the source
/// code. For dynamic C++ classes type info
- /// is only emitted int the module that
+ /// is only emitted into the module that
/// contains the classe's vtable.
FullDebugInfo /// Generate complete debug info.
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
index a7458d45618e..d30ac14e02fe 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -1,4 +1,4 @@
-//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
+//===- Diagnostic.h - C Language Family Diagnostic Handling -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the Diagnostic-related interfaces.
-///
+/// Defines the Diagnostic-related interfaces.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H
@@ -22,12 +22,13 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include <algorithm>
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstdint>
+#include <limits>
#include <list>
#include <map>
#include <memory>
@@ -44,15 +45,16 @@ class DiagnosticConsumer;
class IdentifierInfo;
class LangOptions;
class Preprocessor;
+class SourceManager;
class StoredDiagnostic;
namespace tok {
- enum TokenKind : unsigned short;
+enum TokenKind : unsigned short;
-} // end namespace tok
+} // namespace tok
-/// \brief Annotates a diagnostic with some code that should be
+/// Annotates a diagnostic with some code that should be
/// inserted, removed, or replaced to fix the problem.
///
/// This kind of hint should be used when we are certain that the
@@ -63,29 +65,29 @@ namespace tok {
/// compilation.
class FixItHint {
public:
- /// \brief Code that should be replaced to correct the error. Empty for an
+ /// Code that should be replaced to correct the error. Empty for an
/// insertion hint.
CharSourceRange RemoveRange;
- /// \brief Code in the specific range that should be inserted in the insertion
+ /// Code in the specific range that should be inserted in the insertion
/// location.
CharSourceRange InsertFromRange;
- /// \brief The actual code to insert at the insertion location, as a
+ /// The actual code to insert at the insertion location, as a
/// string.
std::string CodeToInsert;
- bool BeforePreviousInsertions;
+ bool BeforePreviousInsertions = false;
- /// \brief Empty code modification hint, indicating that no code
+ /// Empty code modification hint, indicating that no code
/// modification is known.
- FixItHint() : BeforePreviousInsertions(false) { }
+ FixItHint() = default;
bool isNull() const {
return !RemoveRange.isValid();
}
-
- /// \brief Create a code modification hint that inserts the given
+
+ /// Create a code modification hint that inserts the given
/// code string at a specific location.
static FixItHint CreateInsertion(SourceLocation InsertionLoc,
StringRef Code,
@@ -97,8 +99,8 @@ public:
Hint.BeforePreviousInsertions = BeforePreviousInsertions;
return Hint;
}
-
- /// \brief Create a code modification hint that inserts the given
+
+ /// Create a code modification hint that inserts the given
/// code from \p FromRange at a specific location.
static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
CharSourceRange FromRange,
@@ -111,7 +113,7 @@ public:
return Hint;
}
- /// \brief Create a code modification hint that removes the given
+ /// Create a code modification hint that removes the given
/// source range.
static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
FixItHint Hint;
@@ -121,8 +123,8 @@ public:
static FixItHint CreateRemoval(SourceRange RemoveRange) {
return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
}
-
- /// \brief Create a code modification hint that replaces the given
+
+ /// Create a code modification hint that replaces the given
/// source range with the given code string.
static FixItHint CreateReplacement(CharSourceRange RemoveRange,
StringRef Code) {
@@ -131,14 +133,14 @@ public:
Hint.CodeToInsert = Code;
return Hint;
}
-
+
static FixItHint CreateReplacement(SourceRange RemoveRange,
StringRef Code) {
return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
}
};
-/// \brief Concrete class used by the front-end to report problems and issues.
+/// Concrete class used by the front-end to report problems and issues.
///
/// This massages the diagnostics (e.g. handling things like "report warnings
/// as errors" and passes them off to the DiagnosticConsumer for reporting to
@@ -146,7 +148,7 @@ public:
/// SourceManager.
class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
public:
- /// \brief The level of the diagnostic, after it has been through mapping.
+ /// The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored = DiagnosticIDs::Ignored,
Note = DiagnosticIDs::Note,
@@ -157,45 +159,88 @@ public:
};
enum ArgumentKind {
- ak_std_string, ///< std::string
- ak_c_string, ///< const char *
- ak_sint, ///< int
- ak_uint, ///< unsigned
- ak_tokenkind, ///< enum TokenKind : unsigned
- ak_identifierinfo, ///< IdentifierInfo
- ak_qualtype, ///< QualType
- ak_declarationname, ///< DeclarationName
- ak_nameddecl, ///< NamedDecl *
- ak_nestednamespec, ///< NestedNameSpecifier *
- ak_declcontext, ///< DeclContext *
- ak_qualtype_pair, ///< pair<QualType, QualType>
- ak_attr ///< Attr *
+ /// std::string
+ ak_std_string,
+
+ /// const char *
+ ak_c_string,
+
+ /// int
+ ak_sint,
+
+ /// unsigned
+ ak_uint,
+
+ /// enum TokenKind : unsigned
+ ak_tokenkind,
+
+ /// IdentifierInfo
+ ak_identifierinfo,
+
+ /// QualType
+ ak_qualtype,
+
+ /// DeclarationName
+ ak_declarationname,
+
+ /// NamedDecl *
+ ak_nameddecl,
+
+ /// NestedNameSpecifier *
+ ak_nestednamespec,
+
+ /// DeclContext *
+ ak_declcontext,
+
+ /// pair<QualType, QualType>
+ ak_qualtype_pair,
+
+ /// Attr *
+ ak_attr
};
- /// \brief Represents on argument value, which is a union discriminated
+ /// Represents on argument value, which is a union discriminated
/// by ArgumentKind, with a value.
- typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
+ using ArgumentValue = std::pair<ArgumentKind, intptr_t>;
private:
- unsigned char AllExtensionsSilenced; // Used by __extension__
- bool SuppressAfterFatalError; // Suppress diagnostics after a fatal error?
- bool SuppressAllDiagnostics; // Suppress all diagnostics.
- bool ElideType; // Elide common types of templates.
- bool PrintTemplateTree; // Print a tree when comparing templates.
- bool ShowColors; // Color printing is enabled.
- OverloadsShown ShowOverloads; // Which overload candidates to show.
- unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit.
- unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
- // 0 -> no limit.
- unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
- // backtrace stack, 0 -> no limit.
+ // Used by __extension__
+ unsigned char AllExtensionsSilenced = 0;
+
+ // Suppress diagnostics after a fatal error?
+ bool SuppressAfterFatalError = true;
+
+ // Suppress all diagnostics.
+ bool SuppressAllDiagnostics = false;
+
+ // Elide common types of templates.
+ bool ElideType = true;
+
+ // Print a tree when comparing templates.
+ bool PrintTemplateTree = false;
+
+ // Color printing is enabled.
+ bool ShowColors = false;
+
+ // Which overload candidates to show.
+ OverloadsShown ShowOverloads = Ovl_All;
+
+ // Cap of # errors emitted, 0 -> no limit.
+ unsigned ErrorLimit = 0;
+
+ // Cap on depth of template backtrace stack, 0 -> no limit.
+ unsigned TemplateBacktraceLimit = 0;
+
+ // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit.
+ unsigned ConstexprBacktraceLimit = 0;
+
IntrusiveRefCntPtr<DiagnosticIDs> Diags;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
- DiagnosticConsumer *Client;
+ DiagnosticConsumer *Client = nullptr;
std::unique_ptr<DiagnosticConsumer> Owner;
- SourceManager *SourceMgr;
+ SourceManager *SourceMgr = nullptr;
- /// \brief Mapping information for diagnostics.
+ /// Mapping information for diagnostics.
///
/// Mapping info is packed into four bits per diagnostic. The low three
/// bits are the mapping (an instance of diag::Severity), or zero if unset.
@@ -211,25 +256,38 @@ private:
public:
// "Global" configuration state that can actually vary between modules.
- unsigned IgnoreAllWarnings : 1; // Ignore all warnings: -w
- unsigned EnableAllWarnings : 1; // Enable all warnings.
- unsigned WarningsAsErrors : 1; // Treat warnings like errors.
- unsigned ErrorsAsFatal : 1; // Treat errors like fatal errors.
- unsigned SuppressSystemWarnings : 1; // Suppress warnings in system headers.
- diag::Severity ExtBehavior; // Map extensions to warnings or errors?
+
+ // Ignore all warnings: -w
+ unsigned IgnoreAllWarnings : 1;
+
+ // Enable all warnings.
+ unsigned EnableAllWarnings : 1;
+
+ // Treat warnings like errors.
+ unsigned WarningsAsErrors : 1;
+
+ // Treat errors like fatal errors.
+ unsigned ErrorsAsFatal : 1;
+
+ // Suppress warnings in system headers.
+ unsigned SuppressSystemWarnings : 1;
+
+ // Map extensions to warnings or errors?
+ diag::Severity ExtBehavior = diag::Severity::Ignored;
DiagState()
: IgnoreAllWarnings(false), EnableAllWarnings(false),
WarningsAsErrors(false), ErrorsAsFatal(false),
- SuppressSystemWarnings(false), ExtBehavior(diag::Severity::Ignored) {}
+ SuppressSystemWarnings(false) {}
- typedef llvm::DenseMap<unsigned, DiagnosticMapping>::iterator iterator;
- typedef llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator
- const_iterator;
+ using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator;
+ using const_iterator =
+ llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator;
void setMapping(diag::kind Diag, DiagnosticMapping Info) {
DiagMap[Diag] = Info;
}
+
DiagnosticMapping lookupMapping(diag::kind Diag) const {
return DiagMap.lookup(Diag);
}
@@ -240,7 +298,7 @@ private:
const_iterator end() const { return DiagMap.end(); }
};
- /// \brief Keeps and automatically disposes all DiagStates that we create.
+ /// Keeps and automatically disposes all DiagStates that we create.
std::list<DiagState> DiagStates;
/// A mapping from files to the diagnostic states for those files. Lazily
@@ -249,12 +307,16 @@ private:
public:
/// Add an initial diagnostic state.
void appendFirst(DiagState *State);
+
/// Add a new latest state point.
void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State);
+
/// Look up the diagnostic state at a given source location.
DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const;
+
/// Determine whether this map is empty.
bool empty() const { return Files.empty(); }
+
/// Clear out this map.
void clear() {
Files.clear();
@@ -262,13 +324,21 @@ private:
CurDiagStateLoc = SourceLocation();
}
+ /// Produce a debugging dump of the diagnostic state.
+ LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr,
+ StringRef DiagName = StringRef()) const;
+
/// Grab the most-recently-added state point.
DiagState *getCurDiagState() const { return CurDiagState; }
+
/// Get the location at which a diagnostic state was last added.
SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; }
private:
- /// \brief Represents a point in source where the diagnostic state was
+ friend class ASTReader;
+ friend class ASTWriter;
+
+ /// Represents a point in source where the diagnostic state was
/// modified because of a pragma.
///
/// 'Loc' can be null if the point represents the diagnostic state
@@ -276,8 +346,9 @@ private:
struct DiagStatePoint {
DiagState *State;
unsigned Offset;
+
DiagStatePoint(DiagState *State, unsigned Offset)
- : State(State), Offset(Offset) { }
+ : State(State), Offset(Offset) {}
};
/// Description of the diagnostic states and state transitions for a
@@ -287,11 +358,14 @@ private:
/// as looking up the DecomposedIncludedLoc for the FileID in the Files
/// map would give us this, but we cache it here for performance.
File *Parent = nullptr;
+
/// The offset of this file within its parent.
unsigned ParentOffset = 0;
+
/// Whether this file has any local (not imported from an AST file)
/// diagnostic state transitions.
bool HasLocalTransitions = false;
+
/// The points within the file where the state changes. There will always
/// be at least one of these (the state on entry to the file).
llvm::SmallVector<DiagStatePoint, 4> StateTransitions;
@@ -304,21 +378,20 @@ private:
/// The initial diagnostic state.
DiagState *FirstDiagState;
+
/// The current diagnostic state.
DiagState *CurDiagState;
+
/// The location at which the current diagnostic state was established.
SourceLocation CurDiagStateLoc;
/// Get the diagnostic state information for a file.
File *getFile(SourceManager &SrcMgr, FileID ID) const;
-
- friend class ASTReader;
- friend class ASTWriter;
};
DiagStateMap DiagStatesByLoc;
- /// \brief Keeps the DiagState that was active during each diagnostic 'push'
+ /// Keeps the DiagState that was active during each diagnostic 'push'
/// so we can get back at it when we 'pop'.
std::vector<DiagState *> DiagStateOnPushStack;
@@ -328,41 +401,44 @@ private:
void PushDiagStatePoint(DiagState *State, SourceLocation L);
- /// \brief Finds the DiagStatePoint that contains the diagnostic state of
+ /// Finds the DiagStatePoint that contains the diagnostic state of
/// the given source location.
DiagState *GetDiagStateForLoc(SourceLocation Loc) const {
return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc)
: DiagStatesByLoc.getCurDiagState();
}
- /// \brief Sticky flag set to \c true when an error is emitted.
+ /// Sticky flag set to \c true when an error is emitted.
bool ErrorOccurred;
- /// \brief Sticky flag set to \c true when an "uncompilable error" occurs.
+ /// Sticky flag set to \c true when an "uncompilable error" occurs.
/// I.e. an error that was not upgraded from a warning by -Werror.
bool UncompilableErrorOccurred;
- /// \brief Sticky flag set to \c true when a fatal error is emitted.
+ /// Sticky flag set to \c true when a fatal error is emitted.
bool FatalErrorOccurred;
- /// \brief Indicates that an unrecoverable error has occurred.
+ /// Indicates that an unrecoverable error has occurred.
bool UnrecoverableErrorOccurred;
-
- /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
+
+ /// Counts for DiagnosticErrorTrap to check whether an error occurred
/// during a parsing section, e.g. during parsing a function.
unsigned TrapNumErrorsOccurred;
unsigned TrapNumUnrecoverableErrorsOccurred;
- /// \brief The level of the last diagnostic emitted.
+ /// The level of the last diagnostic emitted.
///
/// This is used to emit continuation diagnostics with the same level as the
/// diagnostic that they follow.
DiagnosticIDs::Level LastDiagLevel;
- unsigned NumWarnings; ///< Number of warnings reported
- unsigned NumErrors; ///< Number of errors reported
+ /// Number of warnings reported
+ unsigned NumWarnings;
- /// \brief A function pointer that converts an opaque diagnostic
+ /// Number of errors reported
+ unsigned NumErrors;
+
+ /// A function pointer that converts an opaque diagnostic
/// argument to a strings.
///
/// This takes the modifiers and argument that was present in the diagnostic.
@@ -372,28 +448,29 @@ private:
/// avoid redundancy across arguments.
///
/// This is a hack to avoid a layering violation between libbasic and libsema.
- typedef void (*ArgToStringFnTy)(
+ using ArgToStringFnTy = void (*)(
ArgumentKind Kind, intptr_t Val,
StringRef Modifier, StringRef Argument,
ArrayRef<ArgumentValue> PrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
ArrayRef<intptr_t> QualTypeVals);
- void *ArgToStringCookie;
+
+ void *ArgToStringCookie = nullptr;
ArgToStringFnTy ArgToStringFn;
- /// \brief ID of the "delayed" diagnostic, which is a (typically
+ /// ID of the "delayed" diagnostic, which is a (typically
/// fatal) diagnostic that had to be delayed because it was found
/// while emitting another diagnostic.
unsigned DelayedDiagID;
- /// \brief First string argument for the delayed diagnostic.
+ /// First string argument for the delayed diagnostic.
std::string DelayedDiagArg1;
- /// \brief Second string argument for the delayed diagnostic.
+ /// Second string argument for the delayed diagnostic.
std::string DelayedDiagArg2;
- /// \brief Optional flag value.
+ /// Optional flag value.
///
/// Some flags accept values, for instance: -Wframe-larger-than=<value> and
/// -Rpass=<value>. The content of this string is emitted after the flag name
@@ -402,23 +479,28 @@ private:
public:
explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags,
- DiagnosticOptions *DiagOpts,
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
DiagnosticConsumer *client = nullptr,
bool ShouldOwnClient = true);
DiagnosticsEngine(const DiagnosticsEngine &) = delete;
DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete;
~DiagnosticsEngine();
+ LLVM_DUMP_METHOD void dump() const { DiagStatesByLoc.dump(*SourceMgr); }
+ LLVM_DUMP_METHOD void dump(StringRef DiagName) const {
+ DiagStatesByLoc.dump(*SourceMgr, DiagName);
+ }
+
const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
return Diags;
}
- /// \brief Retrieve the diagnostic options.
+ /// Retrieve the diagnostic options.
DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; }
- typedef llvm::iterator_range<DiagState::const_iterator> diag_mapping_range;
+ using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>;
- /// \brief Get the current set of diagnostic mappings.
+ /// Get the current set of diagnostic mappings.
diag_mapping_range getDiagnosticMappings() const {
const DiagState &DS = *GetCurDiagState();
return diag_mapping_range(DS.begin(), DS.end());
@@ -427,18 +509,20 @@ public:
DiagnosticConsumer *getClient() { return Client; }
const DiagnosticConsumer *getClient() const { return Client; }
- /// \brief Determine whether this \c DiagnosticsEngine object own its client.
+ /// Determine whether this \c DiagnosticsEngine object own its client.
bool ownsClient() const { return Owner != nullptr; }
- /// \brief Return the current diagnostic client along with ownership of that
+ /// Return the current diagnostic client along with ownership of that
/// client.
std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); }
bool hasSourceManager() const { return SourceMgr != nullptr; }
+
SourceManager &getSourceManager() const {
assert(SourceMgr && "SourceManager not set!");
return *SourceMgr;
}
+
void setSourceManager(SourceManager *SrcMgr) {
assert(DiagStatesByLoc.empty() &&
"Leftover diag state from a different SourceManager.");
@@ -450,54 +534,54 @@ public:
// how diagnostics are emitted.
//
- /// \brief Copies the current DiagMappings and pushes the new copy
+ /// Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
void pushMappings(SourceLocation Loc);
- /// \brief Pops the current DiagMappings off the top of the stack,
+ /// Pops the current DiagMappings off the top of the stack,
/// causing the new top of the stack to be the active mappings.
///
/// \returns \c true if the pop happens, \c false if there is only one
/// DiagMapping on the stack.
bool popMappings(SourceLocation Loc);
- /// \brief Set the diagnostic client associated with this diagnostic object.
+ /// Set the diagnostic client associated with this diagnostic object.
///
/// \param ShouldOwnClient true if the diagnostic object should take
/// ownership of \c client.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
- /// \brief Specify a limit for the number of errors we should
+ /// Specify a limit for the number of errors we should
/// emit before giving up.
///
/// Zero disables the limit.
void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
-
- /// \brief Specify the maximum number of template instantiation
+
+ /// Specify the maximum number of template instantiation
/// notes to emit along with a given diagnostic.
void setTemplateBacktraceLimit(unsigned Limit) {
TemplateBacktraceLimit = Limit;
}
- /// \brief Retrieve the maximum number of template instantiation
+ /// Retrieve the maximum number of template instantiation
/// notes to emit along with a given diagnostic.
unsigned getTemplateBacktraceLimit() const {
return TemplateBacktraceLimit;
}
- /// \brief Specify the maximum number of constexpr evaluation
+ /// Specify the maximum number of constexpr evaluation
/// notes to emit along with a given diagnostic.
void setConstexprBacktraceLimit(unsigned Limit) {
ConstexprBacktraceLimit = Limit;
}
- /// \brief Retrieve the maximum number of constexpr evaluation
+ /// Retrieve the maximum number of constexpr evaluation
/// notes to emit along with a given diagnostic.
unsigned getConstexprBacktraceLimit() const {
return ConstexprBacktraceLimit;
}
- /// \brief When set to true, any unmapped warnings are ignored.
+ /// When set to true, any unmapped warnings are ignored.
///
/// If this and WarningsAsErrors are both set, then this one wins.
void setIgnoreAllWarnings(bool Val) {
@@ -507,7 +591,7 @@ public:
return GetCurDiagState()->IgnoreAllWarnings;
}
- /// \brief When set to true, any unmapped ignored warnings are no longer
+ /// When set to true, any unmapped ignored warnings are no longer
/// ignored.
///
/// If this and IgnoreAllWarnings are both set, then that one wins.
@@ -518,7 +602,7 @@ public:
return GetCurDiagState()->EnableAllWarnings;
}
- /// \brief When set to true, any warnings reported are issued as errors.
+ /// When set to true, any warnings reported are issued as errors.
void setWarningsAsErrors(bool Val) {
GetCurDiagState()->WarningsAsErrors = Val;
}
@@ -526,15 +610,15 @@ public:
return GetCurDiagState()->WarningsAsErrors;
}
- /// \brief When set to true, any error reported is made a fatal error.
+ /// When set to true, any error reported is made a fatal error.
void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; }
bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; }
- /// \brief When set to true (the default), suppress further diagnostics after
+ /// When set to true (the default), suppress further diagnostics after
/// a fatal error.
void setSuppressAfterFatalError(bool Val) { SuppressAfterFatalError = Val; }
- /// \brief When set to true mask warnings that come from system headers.
+ /// When set to true mask warnings that come from system headers.
void setSuppressSystemWarnings(bool Val) {
GetCurDiagState()->SuppressSystemWarnings = Val;
}
@@ -542,30 +626,30 @@ public:
return GetCurDiagState()->SuppressSystemWarnings;
}
- /// \brief Suppress all diagnostics, to silence the front end when we
+ /// Suppress all diagnostics, to silence the front end when we
/// know that we don't want any more diagnostics to be passed along to the
/// client
- void setSuppressAllDiagnostics(bool Val = true) {
- SuppressAllDiagnostics = Val;
+ void setSuppressAllDiagnostics(bool Val = true) {
+ SuppressAllDiagnostics = Val;
}
bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
- /// \brief Set type eliding, to skip outputting same types occurring in
+ /// Set type eliding, to skip outputting same types occurring in
/// template types.
void setElideType(bool Val = true) { ElideType = Val; }
bool getElideType() { return ElideType; }
-
- /// \brief Set tree printing, to outputting the template difference in a
+
+ /// Set tree printing, to outputting the template difference in a
/// tree format.
void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
bool getPrintTemplateTree() { return PrintTemplateTree; }
-
- /// \brief Set color printing, so the type diffing will inject color markers
+
+ /// Set color printing, so the type diffing will inject color markers
/// into the output.
void setShowColors(bool Val = false) { ShowColors = Val; }
bool getShowColors() { return ShowColors; }
- /// \brief Specify which overload candidates to show when overload resolution
+ /// Specify which overload candidates to show when overload resolution
/// fails.
///
/// By default, we show all candidates.
@@ -573,8 +657,8 @@ public:
ShowOverloads = Val;
}
OverloadsShown getShowOverloads() const { return ShowOverloads; }
-
- /// \brief Pretend that the last diagnostic issued was ignored, so any
+
+ /// Pretend that the last diagnostic issued was ignored, so any
/// 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.
@@ -586,14 +670,14 @@ public:
LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning;
}
- /// \brief Determine whether the previous diagnostic was ignored. This can
+ /// Determine whether the previous diagnostic was ignored. This can
/// be used by clients that want to determine whether notes attached to a
/// diagnostic will be suppressed.
bool isLastDiagnosticIgnored() const {
return LastDiagLevel == DiagnosticIDs::Ignored;
}
- /// \brief Controls whether otherwise-unmapped extension diagnostics are
+ /// Controls whether otherwise-unmapped extension diagnostics are
/// mapped onto ignore/warning/error.
///
/// This corresponds to the GCC -pedantic and -pedantic-errors option.
@@ -604,7 +688,7 @@ public:
return GetCurDiagState()->ExtBehavior;
}
- /// \brief Counter bumped when an __extension__ block is/ encountered.
+ /// Counter bumped when an __extension__ block is/ encountered.
///
/// When non-zero, all extension diagnostics are entirely silenced, no
/// matter how they are mapped.
@@ -612,7 +696,7 @@ public:
void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
- /// \brief This allows the client to specify that certain warnings are
+ /// This allows the client to specify that certain warnings are
/// ignored.
///
/// Notes can never be mapped, errors can only be mapped to fatal, and
@@ -622,7 +706,7 @@ public:
/// take affect. It can be null if we are setting the latest state.
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc);
- /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to
+ /// Change an entire diagnostic group (e.g. "unknown-pragmas") to
/// have the specified mapping.
///
/// \returns true (and ignores the request) if "Group" was unknown, false
@@ -637,21 +721,21 @@ public:
diag::Severity Map,
SourceLocation Loc = SourceLocation());
- /// \brief Set the warning-as-error flag for the given diagnostic group.
+ /// Set the warning-as-error flag for the given diagnostic group.
///
/// This function always only operates on the current diagnostic state.
///
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
- /// \brief Set the error-as-fatal flag for the given diagnostic group.
+ /// Set the error-as-fatal flag for the given diagnostic group.
///
/// This function always only operates on the current diagnostic state.
///
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
- /// \brief Add the specified mapping to all diagnostics of the specified
+ /// Add the specified mapping to all diagnostics of the specified
/// flavor.
///
/// Mainly to be used by -Wno-everything to disable all warnings but allow
@@ -661,25 +745,25 @@ public:
bool hasErrorOccurred() const { return ErrorOccurred; }
- /// \brief Errors that actually prevent compilation, not those that are
+ /// Errors that actually prevent compilation, not those that are
/// upgraded from a warning by -Werror.
bool hasUncompilableErrorOccurred() const {
return UncompilableErrorOccurred;
}
bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
-
- /// \brief Determine whether any kind of unrecoverable error has occurred.
+
+ /// Determine whether any kind of unrecoverable error has occurred.
bool hasUnrecoverableErrorOccurred() const {
return FatalErrorOccurred || UnrecoverableErrorOccurred;
}
-
+
unsigned getNumWarnings() const { return NumWarnings; }
void setNumWarnings(unsigned NumWarnings) {
this->NumWarnings = NumWarnings;
}
- /// \brief Return an ID for a diagnostic with the specified format string and
+ /// Return an ID for a diagnostic with the specified format string and
/// level.
///
/// If this is the first request for this diagnostic, it is registered and
@@ -693,7 +777,7 @@ public:
StringRef(FormatString, N - 1));
}
- /// \brief Converts a diagnostic argument (as an intptr_t) into the string
+ /// Converts a diagnostic argument (as an intptr_t) into the string
/// that represents it.
void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
StringRef Modifier, StringRef Argument,
@@ -709,21 +793,21 @@ public:
ArgToStringCookie = Cookie;
}
- /// \brief Note that the prior diagnostic was emitted by some other
+ /// Note that the prior diagnostic was emitted by some other
/// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic.
void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) {
LastDiagLevel = Other.LastDiagLevel;
}
- /// \brief Reset the state of the diagnostic object to its initial
+ /// Reset the state of the diagnostic object to its initial
/// configuration.
void Reset();
-
+
//===--------------------------------------------------------------------===//
// DiagnosticsEngine classification and reporting interfaces.
//
- /// \brief Determine whether the diagnostic is known to be ignored.
+ /// Determine whether the diagnostic is known to be ignored.
///
/// This can be used to opportunistically avoid expensive checks when it's
/// known for certain that the diagnostic has been suppressed at the
@@ -736,7 +820,7 @@ public:
diag::Severity::Ignored;
}
- /// \brief Based on the way the client configured the DiagnosticsEngine
+ /// Based on the way the client configured the DiagnosticsEngine
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticConsumer.
///
@@ -750,7 +834,7 @@ public:
return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
}
- /// \brief Issue the message to the client.
+ /// Issue the message to the client.
///
/// This actually returns an instance of DiagnosticBuilder which emits the
/// diagnostics (through @c ProcessDiag) when it is destroyed.
@@ -763,10 +847,12 @@ public:
void Report(const StoredDiagnostic &storedDiag);
- /// \brief Determine whethere there is already a diagnostic in flight.
- bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
+ /// Determine whethere there is already a diagnostic in flight.
+ bool isDiagnosticInFlight() const {
+ return CurDiagID != std::numeric_limits<unsigned>::max();
+ }
- /// \brief Set the "delayed" diagnostic that will be emitted once
+ /// Set the "delayed" diagnostic that will be emitted once
/// the current diagnostic completes.
///
/// If a diagnostic is already in-flight but the front end must
@@ -789,39 +875,40 @@ public:
/// DiagnosticsEngine object itself.
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
StringRef Arg2 = "");
-
- /// \brief Clear out the current diagnostic.
- void Clear() { CurDiagID = ~0U; }
- /// \brief Return the value associated with this diagnostic flag.
+ /// Clear out the current diagnostic.
+ void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); }
+
+ /// Return the value associated with this diagnostic flag.
StringRef getFlagValue() const { return FlagValue; }
private:
- /// \brief Report the delayed diagnostic.
- void ReportDelayed();
-
// This is private state used by DiagnosticBuilder. We put it here instead of
// in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
// object. This implementation choice means that we can only have one
// diagnostic "in flight" at a time, but this seems to be a reasonable
// tradeoff to keep these objects small. Assertions verify that only one
// diagnostic is in flight at a time.
- friend class DiagnosticIDs;
- friend class DiagnosticBuilder;
friend class Diagnostic;
- friend class PartialDiagnostic;
+ friend class DiagnosticBuilder;
friend class DiagnosticErrorTrap;
-
- /// \brief The location of the current diagnostic that is in flight.
+ friend class DiagnosticIDs;
+ friend class PartialDiagnostic;
+
+ /// Report the delayed diagnostic.
+ void ReportDelayed();
+
+ /// The location of the current diagnostic that is in flight.
SourceLocation CurDiagLoc;
- /// \brief The ID of the current diagnostic that is in flight.
+ /// The ID of the current diagnostic that is in flight.
///
- /// This is set to ~0U when there is no diagnostic in flight.
+ /// This is set to std::numeric_limits<unsigned>::max() when there is no
+ /// diagnostic in flight.
unsigned CurDiagID;
enum {
- /// \brief The maximum number of arguments we can hold.
+ /// The maximum number of arguments we can hold.
///
/// We currently only support up to 10 arguments (%0-%9). A single
/// diagnostic with more than that almost certainly has to be simplified
@@ -829,33 +916,33 @@ private:
MaxArguments = 10,
};
- /// \brief The number of entries in Arguments.
+ /// The number of entries in Arguments.
signed char NumDiagArgs;
- /// \brief Specifies whether an argument is in DiagArgumentsStr or
+ /// Specifies whether an argument is in DiagArgumentsStr or
/// in DiagArguments.
///
/// This is an array of ArgumentKind::ArgumentKind enum values, one for each
/// argument.
unsigned char DiagArgumentsKind[MaxArguments];
- /// \brief Holds the values of each string argument for the current
+ /// Holds the values of each string argument for the current
/// diagnostic.
///
/// This is only used when the corresponding ArgumentKind is ak_std_string.
std::string DiagArgumentsStr[MaxArguments];
- /// \brief The values for the various substitution positions.
+ /// The values for the various substitution positions.
///
/// This is used when the argument is not an std::string. The specific
/// value is mangled into an intptr_t and the interpretation depends on
/// exactly what sort of argument kind it is.
intptr_t DiagArgumentsVal[MaxArguments];
- /// \brief The list of ranges added to this diagnostic.
+ /// The list of ranges added to this diagnostic.
SmallVector<CharSourceRange, 8> DiagRanges;
- /// \brief If valid, provides a hint with some code to insert, remove,
+ /// If valid, provides a hint with some code to insert, remove,
/// or modify at a particular position.
SmallVector<FixItHint, 8> DiagFixItHints;
@@ -874,7 +961,7 @@ private:
return Mapping;
}
- /// \brief Used to report a diagnostic that is finally fully formed.
+ /// Used to report a diagnostic that is finally fully formed.
///
/// \returns true if the diagnostic was emitted, false if it was suppressed.
bool ProcessDiag() {
@@ -884,13 +971,16 @@ private:
/// @name Diagnostic Emission
/// @{
protected:
+ friend class ASTReader;
+ friend class ASTWriter;
+
// Sema requires access to the following functions because the current design
// of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to
// access us directly to ensure we minimize the emitted code for the common
// Sema::Diag() patterns.
friend class Sema;
- /// \brief Emit the current diagnostic and clear the diagnostic state.
+ /// Emit the current diagnostic and clear the diagnostic state.
///
/// \param Force Emit the diagnostic regardless of suppression settings.
bool EmitCurrentDiagnostic(bool Force = false);
@@ -900,12 +990,9 @@ protected:
SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; }
/// @}
-
- friend class ASTReader;
- friend class ASTWriter;
};
-/// \brief RAII class that determines when any errors have occurred
+/// RAII class that determines when any errors have occurred
/// between the time the instance was created and the time it was
/// queried.
class DiagnosticErrorTrap {
@@ -915,21 +1002,21 @@ class DiagnosticErrorTrap {
public:
explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
- : Diag(Diag) { reset(); }
+ : Diag(Diag) { reset(); }
- /// \brief Determine whether any errors have occurred since this
+ /// Determine whether any errors have occurred since this
/// object instance was created.
bool hasErrorOccurred() const {
return Diag.TrapNumErrorsOccurred > NumErrors;
}
- /// \brief Determine whether any unrecoverable errors have occurred since this
+ /// Determine whether any unrecoverable errors have occurred since this
/// object instance was created.
bool hasUnrecoverableErrorOccurred() const {
return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
}
- /// \brief Set to initial state of "no errors occurred".
+ /// Set to initial state of "no errors occurred".
void reset() {
NumErrors = Diag.TrapNumErrorsOccurred;
NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
@@ -940,7 +1027,7 @@ public:
// DiagnosticBuilder
//===----------------------------------------------------------------------===//
-/// \brief A little helper class used to produce diagnostics.
+/// A little helper class used to produce diagnostics.
///
/// This is constructed by the DiagnosticsEngine::Report method, and
/// allows insertion of extra information (arguments and source ranges) into
@@ -953,22 +1040,23 @@ public:
/// the common fields to registers, eliminating increments of the NumArgs field,
/// for example.
class DiagnosticBuilder {
+ friend class DiagnosticsEngine;
+ friend class PartialDiagnostic;
+
mutable DiagnosticsEngine *DiagObj = nullptr;
mutable unsigned NumArgs = 0;
- /// \brief Status variable indicating if this diagnostic is still active.
+ /// Status variable indicating if this diagnostic is still active.
///
// NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
// but LLVM is not currently smart enough to eliminate the null check that
// Emit() would end up with if we used that as our status variable.
mutable bool IsActive = false;
- /// \brief Flag indicating that this diagnostic is being emitted via a
+ /// Flag indicating that this diagnostic is being emitted via a
/// call to ForceEmit.
mutable bool IsForceEmit = false;
- friend class DiagnosticsEngine;
-
DiagnosticBuilder() = default;
explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
@@ -978,24 +1066,22 @@ class DiagnosticBuilder {
diagObj->DiagFixItHints.clear();
}
- friend class PartialDiagnostic;
-
protected:
void FlushCounts() {
DiagObj->NumDiagArgs = NumArgs;
}
- /// \brief Clear out the current diagnostic.
+ /// Clear out the current diagnostic.
void Clear() const {
DiagObj = nullptr;
IsActive = false;
IsForceEmit = false;
}
- /// \brief Determine whether this diagnostic is still active.
+ /// Determine whether this diagnostic is still active.
bool isActive() const { return IsActive; }
- /// \brief Force the diagnostic builder to emit the diagnostic now.
+ /// Force the diagnostic builder to emit the diagnostic now.
///
/// Once this function has been called, the DiagnosticBuilder object
/// should not be used again before it is destroyed.
@@ -1019,7 +1105,7 @@ protected:
return Result;
}
-
+
public:
/// Copy constructor. When copied, this "takes" the diagnostic info from the
/// input and neuters it.
@@ -1033,23 +1119,23 @@ public:
DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete;
- /// \brief Emits the diagnostic.
+ /// Emits the diagnostic.
~DiagnosticBuilder() {
Emit();
}
- /// \brief Retrieve an empty diagnostic builder.
+ /// Retrieve an empty diagnostic builder.
static DiagnosticBuilder getEmpty() {
- return DiagnosticBuilder();
+ return {};
}
- /// \brief Forces the diagnostic to be emitted.
+ /// Forces the diagnostic to be emitted.
const DiagnosticBuilder &setForceEmit() const {
IsForceEmit = true;
return *this;
}
- /// \brief Conversion of DiagnosticBuilder to bool always returns \c true.
+ /// Conversion of DiagnosticBuilder to bool always returns \c true.
///
/// This allows is to be used in boolean error contexts (where \c true is
/// used to indicate that an error has occurred), like:
@@ -1089,11 +1175,12 @@ public:
};
struct AddFlagValue {
- explicit AddFlagValue(StringRef V) : Val(V) {}
StringRef Val;
+
+ explicit AddFlagValue(StringRef V) : Val(V) {}
};
-/// \brief Register a value for the flag in the current diagnostic. This
+/// Register a value for the flag in the current diagnostic. This
/// value will be shown as the suffix "=value" after the flag name. It is
/// useful in cases where the diagnostic flag accepts values (e.g.,
/// -Rpass or -Wframe-larger-than).
@@ -1199,14 +1286,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
/// A nullability kind paired with a bit indicating whether it used a
/// context-sensitive keyword.
-typedef std::pair<NullabilityKind, bool> DiagNullabilityKind;
+using DiagNullabilityKind = std::pair<NullabilityKind, bool>;
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
DiagNullabilityKind nullability);
inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
unsigned DiagID) {
- assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
+ assert(CurDiagID == std::numeric_limits<unsigned>::max() &&
+ "Multiple diagnostics in flight at once!");
CurDiagLoc = Loc;
CurDiagID = DiagID;
FlagValue.clear();
@@ -1231,7 +1319,7 @@ class Diagnostic {
public:
explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
- : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
+ : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
const DiagnosticsEngine *getDiags() const { return DiagObj; }
unsigned getID() const { return DiagObj->CurDiagID; }
@@ -1241,7 +1329,7 @@ public:
unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
- /// \brief Return the kind of the specified index.
+ /// Return the kind of the specified index.
///
/// Based on the kind of argument, the accessors below can be used to get
/// the value.
@@ -1252,7 +1340,7 @@ public:
return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
}
- /// \brief Return the provided argument string specified by \p Idx.
+ /// Return the provided argument string specified by \p Idx.
/// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
const std::string &getArgStdStr(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
@@ -1260,7 +1348,7 @@ public:
return DiagObj->DiagArgumentsStr[Idx];
}
- /// \brief Return the specified C string argument.
+ /// Return the specified C string argument.
/// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
const char *getArgCStr(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
@@ -1268,7 +1356,7 @@ public:
return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
}
- /// \brief Return the specified signed integer argument.
+ /// Return the specified signed integer argument.
/// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
int getArgSInt(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
@@ -1276,7 +1364,7 @@ public:
return (int)DiagObj->DiagArgumentsVal[Idx];
}
- /// \brief Return the specified unsigned integer argument.
+ /// Return the specified unsigned integer argument.
/// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
unsigned getArgUInt(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
@@ -1284,7 +1372,7 @@ public:
return (unsigned)DiagObj->DiagArgumentsVal[Idx];
}
- /// \brief Return the specified IdentifierInfo argument.
+ /// Return the specified IdentifierInfo argument.
/// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
@@ -1292,7 +1380,7 @@ public:
return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
}
- /// \brief Return the specified non-string argument in an opaque form.
+ /// Return the specified non-string argument in an opaque form.
/// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
intptr_t getRawArg(unsigned Idx) const {
assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
@@ -1300,7 +1388,7 @@ public:
return DiagObj->DiagArgumentsVal[Idx];
}
- /// \brief Return the number of source ranges associated with this diagnostic.
+ /// Return the number of source ranges associated with this diagnostic.
unsigned getNumRanges() const {
return DiagObj->DiagRanges.size();
}
@@ -1311,7 +1399,7 @@ public:
return DiagObj->DiagRanges[Idx];
}
- /// \brief Return an array reference for this diagnostic's ranges.
+ /// Return an array reference for this diagnostic's ranges.
ArrayRef<CharSourceRange> getRanges() const {
return DiagObj->DiagRanges;
}
@@ -1329,21 +1417,21 @@ public:
return DiagObj->DiagFixItHints;
}
- /// \brief Format this diagnostic into a string, substituting the
+ /// Format this diagnostic into a string, substituting the
/// formal arguments into the %0 slots.
///
/// The result is appended onto the \p OutStr array.
void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
- /// \brief Format the given format-string into the output buffer using the
+ /// Format the given format-string into the output buffer using the
/// arguments stored in this diagnostic.
void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
SmallVectorImpl<char> &OutStr) const;
};
/**
- * \brief Represents a diagnostic in a form that can be retained until its
- * corresponding source manager is destroyed.
+ * Represents a diagnostic in a form that can be retained until its
+ * corresponding source manager is destroyed.
*/
class StoredDiagnostic {
unsigned ID;
@@ -1356,14 +1444,14 @@ class StoredDiagnostic {
public:
StoredDiagnostic() = default;
StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
- StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
+ StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message);
- StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
+ StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message, FullSourceLoc Loc,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Fixits);
- /// \brief Evaluates true when this object stores a diagnostic.
+ /// Evaluates true when this object stores a diagnostic.
explicit operator bool() const { return !Message.empty(); }
unsigned getID() const { return ID; }
@@ -1373,42 +1461,43 @@ public:
void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
- typedef std::vector<CharSourceRange>::const_iterator range_iterator;
+ using range_iterator = std::vector<CharSourceRange>::const_iterator;
+
range_iterator range_begin() const { return Ranges.begin(); }
range_iterator range_end() const { return Ranges.end(); }
unsigned range_size() const { return Ranges.size(); }
-
+
ArrayRef<CharSourceRange> getRanges() const {
return llvm::makeArrayRef(Ranges);
}
- typedef std::vector<FixItHint>::const_iterator fixit_iterator;
+ using fixit_iterator = std::vector<FixItHint>::const_iterator;
+
fixit_iterator fixit_begin() const { return FixIts.begin(); }
fixit_iterator fixit_end() const { return FixIts.end(); }
unsigned fixit_size() const { return FixIts.size(); }
-
+
ArrayRef<FixItHint> getFixIts() const {
return llvm::makeArrayRef(FixIts);
}
};
-/// \brief Abstract interface, implemented by clients of the front-end, which
+/// Abstract interface, implemented by clients of the front-end, which
/// formats and prints fully processed diagnostics.
class DiagnosticConsumer {
protected:
unsigned NumWarnings = 0; ///< Number of warnings reported
unsigned NumErrors = 0; ///< Number of errors reported
-
+
public:
DiagnosticConsumer() = default;
-
virtual ~DiagnosticConsumer();
unsigned getNumErrors() const { return NumErrors; }
unsigned getNumWarnings() const { return NumWarnings; }
virtual void clear() { NumWarnings = NumErrors = 0; }
- /// \brief Callback to inform the diagnostic client that processing
+ /// Callback to inform the diagnostic client that processing
/// of a source file is beginning.
///
/// Note that diagnostics may be emitted outside the processing of a source
@@ -1417,30 +1506,30 @@ public:
/// in between BeginSourceFile() and EndSourceFile().
///
/// \param LangOpts The language options for the source file being processed.
- /// \param PP The preprocessor object being used for the source; this is
+ /// \param PP The preprocessor object being used for the source; this is
/// optional, e.g., it may not be present when processing AST source files.
virtual void BeginSourceFile(const LangOptions &LangOpts,
const Preprocessor *PP = nullptr) {}
- /// \brief Callback to inform the diagnostic client that processing
+ /// Callback to inform the diagnostic client that processing
/// of a source file has ended.
///
/// The diagnostic client should assume that any objects made available via
/// BeginSourceFile() are inaccessible.
virtual void EndSourceFile() {}
- /// \brief Callback to inform the diagnostic client that processing of all
+ /// Callback to inform the diagnostic client that processing of all
/// source files has ended.
virtual void finish() {}
- /// \brief Indicates whether the diagnostics handled by this
+ /// Indicates whether the diagnostics handled by this
/// DiagnosticConsumer should be included in the number of diagnostics
/// reported by DiagnosticsEngine.
///
/// The default implementation returns true.
virtual bool IncludeInDiagnosticCounts() const;
- /// \brief Handle this diagnostic, reporting it to the user or
+ /// Handle this diagnostic, reporting it to the user or
/// capturing it to a log as needed.
///
/// The default implementation just keeps track of the total number of
@@ -1449,7 +1538,7 @@ public:
const Diagnostic &Info);
};
-/// \brief A diagnostic client that ignores all diagnostics.
+/// A diagnostic client that ignores all diagnostics.
class IgnoringDiagConsumer : public DiagnosticConsumer {
virtual void anchor();
@@ -1459,7 +1548,7 @@ class IgnoringDiagConsumer : public DiagnosticConsumer {
}
};
-/// \brief Diagnostic consumer that forwards diagnostics along to an
+/// Diagnostic consumer that forwards diagnostics along to an
/// existing, already-initialized diagnostic consumer.
///
class ForwardingDiagnosticConsumer : public DiagnosticConsumer {
@@ -1467,7 +1556,6 @@ class ForwardingDiagnosticConsumer : public DiagnosticConsumer {
public:
ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {}
-
~ForwardingDiagnosticConsumer() override;
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
@@ -1485,6 +1573,7 @@ struct TemplateDiffTypes {
unsigned PrintFromType : 1;
unsigned ElideType : 1;
unsigned ShowColors : 1;
+
// The printer sets this variable to true if the template diff was used.
unsigned TemplateDiffUsed : 1;
};
@@ -1493,13 +1582,12 @@ struct TemplateDiffTypes {
/// attribute. The character itself will be not be printed.
const char ToggleHighlight = 127;
-
/// ProcessWarningOptions - Initialize the diagnostic client and process the
/// warning options specified on the command line.
void ProcessWarningOptions(DiagnosticsEngine &Diags,
const DiagnosticOptions &Opts,
bool ReportDiags = true);
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
index 52ccf350e651..2a0f1e6385d3 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
@@ -39,6 +39,15 @@ def SFINAE_Suppress : SFINAEResponse;
def SFINAE_Report : SFINAEResponse;
def SFINAE_AccessControl : SFINAEResponse;
+// Textual substitutions which may be performed on the text of diagnostics
+class TextSubstitution<string Text> {
+ string Substitution = Text;
+ // TODO: These are only here to allow substitutions to be declared inline with
+ // diagnostics
+ string Component = "";
+ string CategoryName = "";
+}
+
// Diagnostic Categories. These can be applied to groups or individual
// diagnostics to specify a category.
class DiagCategory<string Name> {
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
index 215580b2e9b6..587254367bee 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -168,7 +168,7 @@ def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
InGroup<DiagGroup<"integer-overflow">>;
-// This is a temporary diagnostic, and shall be removed once our
+// This is a temporary diagnostic, and shall be removed once our
// implementation is complete, and like the preceding constexpr notes belongs
// in Sema.
def note_unimplemented_constexpr_lambda_feature_ast : Note<
@@ -273,6 +273,8 @@ def note_odr_objc_synthesize_ivar_here : Note<
"property is synthesized to ivar %0 here">;
// Importing C++ ASTs
+def note_odr_friend : Note<"friend declared here">;
+def note_odr_missing_friend : Note<"no corresponding friend here">;
def err_odr_different_num_template_parameters : Error<
"template parameter lists have a different number of parameters (%0 vs %1)">;
def note_odr_template_parameter_list : Note<
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td
index ab24582c1180..ebe62e4738f0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td
@@ -83,19 +83,19 @@ def warn_doc_function_method_decl_mismatch : Warning<
"%select{a function|a function|an Objective-C method|an Objective-C method|"
"a pointer to function}2 declaration">,
InGroup<Documentation>, DefaultIgnore;
-
+
def warn_doc_api_container_decl_mismatch : Warning<
"'%select{\\|@}0%select{class|interface|protocol|struct|union}1' "
"command should not be used in a comment attached to a "
"non-%select{class|interface|protocol|struct|union}2 declaration">,
InGroup<Documentation>, DefaultIgnore;
-
+
def warn_doc_container_decl_mismatch : Warning<
"'%select{\\|@}0%select{classdesign|coclass|dependency|helper"
"|helperclass|helps|instancesize|ownership|performance|security|superclass}1' "
"command should not be used in a comment attached to a non-container declaration">,
InGroup<Documentation>, DefaultIgnore;
-
+
def warn_doc_param_duplicate : Warning<
"parameter '%0' is already documented">,
InGroup<Documentation>, DefaultIgnore;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 82ca27b7345e..b98b183c9d6f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -16,7 +16,7 @@ let Component = "Common" in {
// Basic.
def fatal_too_many_errors
- : Error<"too many errors emitted, stopping now">, DefaultFatal;
+ : Error<"too many errors emitted, stopping now">, DefaultFatal;
def note_declared_at : Note<"declared here">;
def note_previous_definition : Note<"previous definition is here">;
@@ -94,11 +94,14 @@ def remark_module_lock_failure : Remark<
"could not acquire lock file for module '%0': %1">, InGroup<ModuleBuild>;
def remark_module_lock_timeout : Remark<
"timed out waiting to acquire lock file for module '%0'">, InGroup<ModuleBuild>;
-def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
+def err_module_shadowed : Error<"import of shadowed module '%0'">, DefaultFatal;
+def err_module_build_shadowed_submodule : Error<
+ "build a shadowed submodule '%0'">, DefaultFatal;
+def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
DefaultFatal;
def err_module_prebuilt : Error<
"error in loading module '%0' from prebuilt module path">, DefaultFatal;
-def note_pragma_entered_here : Note<"#pragma entered here">;
+def note_pragma_entered_here : Note<"#pragma entered here">;
def note_decl_hiding_tag_type : Note<
"%1 %0 is hidden by a non-type declaration of %0 here">;
def err_attribute_not_type_attr : Error<
@@ -112,7 +115,7 @@ let CategoryName = "Nullability Issue" in {
def warn_nullability_duplicate : Warning<
"duplicate nullability specifier %0">,
InGroup<Nullability>;
-
+
def warn_conflicting_nullability_attr_overriding_ret_types : Warning<
"conflicting nullability specifier on return types, %0 "
"conflicts with existing specifier %1">,
@@ -165,6 +168,10 @@ def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">,
InGroup<GccCompat>;
def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">,
InGroup<GccCompat>;
+def err_too_large_for_fixed_point : Error<
+ "this value is too large for this fixed point type">;
+def err_fixed_point_not_enabled : Error<"compile with "
+ "'-ffixed-point' to enable fixed point types">;
// SEH
def err_seh_expected_handler : Error<
@@ -185,6 +192,7 @@ 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 note_valid_options : Note<"valid target CPU values are: %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'">;
@@ -200,6 +208,10 @@ def err_target_unsupported_execute_only : Error<
"execute only is not supported for the %0 sub-architecture">;
def err_opt_not_valid_with_opt : Error<
"option '%0' cannot be specified with '%1'">;
+def err_opt_not_valid_without_opt : Error<
+ "option '%0' cannot be specified without '%1'">;
+def err_opt_not_valid_on_target : Error<
+ "option '%0' cannot be specified on this target">;
// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
@@ -211,7 +223,7 @@ def err_unable_to_rename_temp : Error<
"unable to rename temporary '%0' to output file '%1': '%2'">;
def err_unable_to_make_temp : Error<
"unable to make temporary file: %0">;
-
+
// Modules
def err_module_format_unhandled : Error<
"no handler registered for module format '%0'">, DefaultFatal;
@@ -226,6 +238,10 @@ def note_mt_message : Note<"[rewriter] %0">;
def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">;
def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">;
+// OpenCL C++.
+def err_openclcxx_not_supported : Error<
+ "'%0' is not supported in OpenCL C++">;
+
// OpenMP
def err_omp_more_one_clause : Error<
"directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 69c20ea7806c..7f75f45c6578 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -11,6 +11,8 @@ let Component = "Driver" in {
def err_drv_no_such_file : Error<"no such file or directory: '%0'">;
def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
+def err_drv_unsupported_opt_with_suggestion
+ : Error<"unsupported option '%0', did you mean '%1'?">;
def err_drv_unsupported_opt_for_target : Error<
"unsupported option '%0' for target '%1'">;
def err_drv_unsupported_option_argument : Error<
@@ -22,6 +24,10 @@ def err_drv_unknown_stdin_type_clang_cl : Error<
def err_drv_unknown_language : Error<"language not recognized: '%0'">;
def err_drv_invalid_arch_name : Error<
"invalid arch name '%0'">;
+def err_drv_invalid_riscv_arch_name : Error<
+ "invalid arch name '%0', %1">;
+def err_drv_invalid_riscv_ext_arch_name : Error<
+ "invalid arch name '%0', %1 '%2'">;
def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">;
def err_drv_no_cuda_installation : Error<
"cannot find CUDA installation. Provide its path via --cuda-path, or pass "
@@ -34,7 +40,8 @@ def err_drv_cuda_version_unsupported : Error<
"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_cuda_host_arch : Error<"unsupported architecture '%0' for host compilation.">;
+def err_drv_mix_cuda_hip : Error<"Mixed Cuda and HIP compilation is not supported.">;
def err_drv_invalid_thread_model_for_target : Error<
"invalid thread model '%0' in '%1' for this target">;
def err_drv_invalid_linker_name : Error<
@@ -135,9 +142,14 @@ def err_arch_unsupported_isa
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
+def err_drv_unknown_argument_with_suggestion
+ : Error<"unknown argument '%0', did you mean '%1'?">;
def warn_drv_unknown_argument_clang_cl : Warning<
"unknown argument ignored in clang-cl: '%0'">,
InGroup<UnknownArgument>;
+def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning<
+ "unknown argument ignored in clang-cl '%0' (did you mean '%1'?)">,
+ InGroup<UnknownArgument>;
def warn_drv_ycyu_no_arg_clang_cl : Warning<
"support for '%0' without a filename not implemented yet; flag ignored">,
@@ -181,6 +193,8 @@ def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
def err_drv_unknown_objc_runtime : Error<
"unknown or ill-formed Objective-C runtime '%0'">;
+def err_drv_gnustep_objc_runtime_incompatible_binary : Error<
+ "GNUstep Objective-C runtime version %0 incompatible with target binary format">;
def err_drv_emit_llvm_link : Error<
"-emit-llvm cannot be used when linking">;
def err_drv_optimization_remark_pattern : Error<
@@ -194,7 +208,10 @@ def err_drv_omp_host_target_not_supported : Error<
def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
"The option -fopenmp-targets must be used in conjunction with a -fopenmp option compatible with offloading, please use -fopenmp=libomp or -fopenmp=libiomp5.">;
def warn_drv_omp_offload_target_duplicate : Warning<
- "The OpenMP offloading target '%0' is similar to target '%1' already specified - will be ignored.">,
+ "The OpenMP offloading target '%0' is similar to target '%1' already specified - will be ignored.">,
+ InGroup<OpenMPTarget>;
+def warn_drv_omp_offload_target_missingbcruntime : Warning<
+ "No library '%0' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.">,
InGroup<OpenMPTarget>;
def err_drv_bitcode_unsupported_on_toolchain : Error<
"-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
@@ -209,6 +226,9 @@ def warn_ignored_clang_option : Warning<"the flag '%0' has been deprecated and w
def warn_drv_unsupported_opt_for_target : Warning<
"optimization flag '%0' is not supported for target '%1'">,
InGroup<IgnoredOptimizationArgument>;
+def warn_drv_unsupported_debug_info_opt_for_target : Warning<
+ "debug information option '%0' is not supported for target '%1'">,
+ InGroup<UnsupportedTargetOpt>;
def warn_c_kext : Warning<
"ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
def warn_drv_input_file_unused : Warning<
@@ -251,15 +271,12 @@ def warn_incompatible_sysroot : Warning<"using sysroot for '%0' but targeting '%
InGroup<DiagGroup<"incompatible-sysroot">>;
def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">,
InGroup<DiagGroup<"debug-compression-unavailable">>;
-def warn_drv_enabling_rtti_with_exceptions : Warning<
- "implicitly enabling rtti for exception handling">,
- InGroup<DiagGroup<"rtti-for-exceptions">>;
def warn_drv_disabling_vptr_no_rtti_default : Warning<
"implicitly disabling vptr sanitizer because rtti wasn't enabled">,
InGroup<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>;
+ InGroup<InvalidCommandLineArgument>, DefaultWarnNoWerror;
def note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;
@@ -278,6 +295,9 @@ def err_analyzer_config_multiple_values : Error<
def err_drv_invalid_hvx_length : Error<
"-mhvx-length is not supported without a -mhvx/-mhvx= flag">;
+def warn_drv_vectorize_needs_hvx : Warning<
+ "auto-vectorization requires HVX, use -mhvx to enable it">,
+ InGroup<OptionIgnored>;
def err_drv_modules_validate_once_requires_timestamp : Error<
"option '-fmodules-validate-once-per-build-session' requires "
@@ -322,10 +342,12 @@ 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">,
+def warn_drv_unsupported_pic_with_mabicalls : Warning<
+ "ignoring '%0' option as it cannot be used with "
+ "%select{implicit usage of|}1 -mabicalls and the N64 ABI">,
InGroup<OptionIgnored>;
+def err_drv_unsupported_noabicalls_pic : Error<
+ "position-independent code requires ‘-mabicalls’">;
def err_drv_unsupported_indirect_jump_opt : Error<
"'-mindirect-jump=%0' is unsupported with the '%1' architecture">;
def err_drv_unknown_indirect_jump_opt : Error<
@@ -366,4 +388,8 @@ def warn_drv_experimental_isel_incomplete : Warning<
def warn_drv_experimental_isel_incomplete_opt : Warning<
"-fexperimental-isel support is incomplete for this architecture at the current optimization level">,
InGroup<ExperimentalISel>;
+
+def warn_drv_moutline_unsupported_opt : Warning<
+ "The '%0' architecture does not support -moutline; flag ignored">,
+ InGroup<OptionIgnored>;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h
index 6b4b073736a8..3f7be46c9505 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h
@@ -15,7 +15,7 @@
namespace clang {
-/// \brief Carries a Clang diagnostic in an llvm::Error.
+/// Carries a Clang diagnostic in an llvm::Error.
///
/// Users should emit the stored diagnostic using the DiagnosticsEngine.
class DiagnosticError : public llvm::ErrorInfo<DiagnosticError> {
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index b25181f25658..66287933b7ca 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -36,7 +36,7 @@ def remark_fe_backend_plugin: Remark<"%0">, BackendInfo, InGroup<RemarkBackendPl
def note_fe_backend_plugin: Note<"%0">, BackendInfo;
def warn_fe_override_module : Warning<
- "overriding the module target triple with %0">,
+ "overriding the module target triple with %0">,
InGroup<DiagGroup<"override-module">>;
def remark_fe_backend_optimization_remark : Remark<"%0">, BackendInfo,
@@ -118,6 +118,8 @@ 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 err_fe_invalid_exception_model
+ : Error<"invalid exception model '%0' for target '%1'">;
def warn_fe_serialized_diag_merge_failure : Warning<
"unable to merge a subprocess's serialized diagnostics">,
@@ -188,10 +190,10 @@ def err_module_interface_requires_modules_ts : Error<
def warn_module_config_mismatch : Warning<
"module file %0 cannot be loaded due to a configuration mismatch with the current "
"compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
-def err_module_map_not_found : Error<"module map file '%0' not found">,
+def err_module_map_not_found : Error<"module map file '%0' not found">,
DefaultFatal;
def err_missing_module_name : Error<
- "no module name provided; specify one with -fmodule-name=">,
+ "no module name provided; specify one with -fmodule-name=">,
DefaultFatal;
def err_missing_module : Error<
"no module named '%0' declared in module map file '%1'">, DefaultFatal;
@@ -234,4 +236,9 @@ def err_invalid_vfs_overlay : Error<
def warn_option_invalid_ocl_version : Warning<
"OpenCL version %0 does not support the option '%1'">, InGroup<Deprecated>;
+
+def warn_stdlibcxx_not_found : Warning<
+ "include path for stdlibc++ headers not found; pass '-std=libc++' on the "
+ "command line to use the libc++ standard library instead">,
+ InGroup<DiagGroup<"stdlibcxx-not-found">>;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
index 2d471f1fa5a4..c0128f56a59e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -31,6 +31,10 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">;
def Availability : DiagGroup<"availability">;
def Section : DiagGroup<"section">;
def AutoImport : DiagGroup<"auto-import">;
+def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">;
+def FrameworkIncludePrivateFromPublic :
+ DiagGroup<"framework-include-private-from-public">;
+def FrameworkHdrAtImport : DiagGroup<"atimport-in-framework-header">;
def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">;
def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
@@ -68,6 +72,7 @@ def UnsupportedNan : DiagGroup<"unsupported-nan">;
def UnsupportedAbs : DiagGroup<"unsupported-abs">;
def UnsupportedCB : DiagGroup<"unsupported-cb">;
def UnsupportedGPOpt : DiagGroup<"unsupported-gpopt">;
+def UnsupportedTargetOpt : DiagGroup<"unsupported-target-opt">;
def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
def NullConversion : DiagGroup<"null-conversion">;
def ImplicitConversionFloatingPointToBool :
@@ -116,6 +121,7 @@ def DeprecatedDynamicExceptionSpec
def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
def DeprecatedRegister : DiagGroup<"deprecated-register">;
+def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">;
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
[CXX11CompatDeprecatedWritableStr]>;
// FIXME: Why is DeprecatedImplementations not in this group?
@@ -124,6 +130,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
DeprecatedDynamicExceptionSpec,
DeprecatedIncrementBool,
DeprecatedRegister,
+ DeprecatedThisCapture,
DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
@@ -151,8 +158,10 @@ def Exceptions : DiagGroup<"exceptions">;
def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">;
def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
def ExtraTokens : DiagGroup<"extra-tokens">;
+def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">;
def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
-def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>;
+def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi,
+ CXX11ExtraSemi]>;
def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">;
def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
@@ -196,6 +205,7 @@ def CXX98Compat : DiagGroup<"c++98-compat",
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
CXX98CompatBindToTemporaryCopy,
+ CXX98CompatExtraSemi,
CXXPre14CompatPedantic,
CXXPre17CompatPedantic,
CXXPre2aCompatPedantic]>;
@@ -263,6 +273,11 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
+def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
+def ReturnStackAddress : DiagGroup<"return-stack-address">;
+def Dangling : DiagGroup<"dangling", [DanglingField,
+ DanglingInitializerList,
+ ReturnStackAddress]>;
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
def FlagEnum : DiagGroup<"flag-enum">;
@@ -273,7 +288,7 @@ def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
def GNUIncludeNext : DiagGroup<"gnu-include-next">;
def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
-def IncompatiblePointerTypesDiscardsQualifiers
+def IncompatiblePointerTypesDiscardsQualifiers
: DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
def IncompatibleFunctionPointerTypes
: DiagGroup<"incompatible-function-pointer-types">;
@@ -282,6 +297,8 @@ def IncompatiblePointerTypes
[IncompatiblePointerTypesDiscardsQualifiers,
IncompatibleFunctionPointerTypes]>;
def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
+def IncompleteFrameworkModuleDeclaration
+ : DiagGroup<"incomplete-framework-module-declaration">;
def NonModularIncludeInFrameworkModule
: DiagGroup<"non-modular-include-in-framework-module">;
def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
@@ -347,7 +364,6 @@ 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">;
def OldStyleCast : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
@@ -380,7 +396,11 @@ def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
def Packed : DiagGroup<"packed">;
def Padded : DiagGroup<"padded">;
+
def PessimizingMove : DiagGroup<"pessimizing-move">;
+def ReturnStdMoveInCXX11 : DiagGroup<"return-std-move-in-c++11">;
+def ReturnStdMove : DiagGroup<"return-std-move">;
+
def PointerArith : DiagGroup<"pointer-arith">;
def PoundWarning : DiagGroup<"#warnings">;
def PoundPragmaMessage : DiagGroup<"#pragma-messages">,
@@ -391,13 +411,13 @@ def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
def RedundantMove : DiagGroup<"redundant-move">;
def Register : DiagGroup<"register", [DeprecatedRegister]>;
-def ReturnStackAddress : DiagGroup<"return-stack-address">;
def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy",
[CXX98CompatBindToTemporaryCopy]>;
def SelfAssignmentField : DiagGroup<"self-assign-field">;
-def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>;
+def SelfAssignmentOverloaded : DiagGroup<"self-assign-overloaded">;
+def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentOverloaded, SelfAssignmentField]>;
def SelfMove : DiagGroup<"self-move">;
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
def Sentinel : DiagGroup<"sentinel">;
@@ -426,6 +446,13 @@ def : DiagGroup<"synth">;
def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">;
def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">;
def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">;
+def MemsetTransposedArgs : DiagGroup<"memset-transposed-args">;
+def DynamicClassMemaccess : DiagGroup<"dynamic-class-memaccess">;
+def NonTrivialMemaccess : DiagGroup<"nontrivial-memaccess">;
+def SuspiciousBzero : DiagGroup<"suspicious-bzero">;
+def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess",
+ [SizeofPointerMemaccess, DynamicClassMemaccess,
+ NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>;
def StaticInInline : DiagGroup<"static-in-inline">;
def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
@@ -512,8 +539,13 @@ def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
UninitializedStaticSelfInit]>;
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
+// #pragma optimize is often used to avoid to work around MSVC codegen bugs or
+// to disable inlining. It's not completely clear what alternative to suggest
+// (#pragma clang optimize, noinline) so suggest nothing for now.
+def IgnoredPragmaOptimize : DiagGroup<"ignored-pragma-optimize">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
-def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
+def IgnoredPragmas : DiagGroup<"ignored-pragmas",
+ [IgnoredPragmaIntrinsic, IgnoredPragmaOptimize]>;
def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">;
def PragmaPackSuspiciousInclude : DiagGroup<"pragma-pack-suspicious-include">;
def PragmaPack : DiagGroup<"pragma-pack", [PragmaPackSuspiciousInclude]>;
@@ -715,7 +747,12 @@ def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
[IntToVoidPointerCast]>;
-def Move : DiagGroup<"move", [PessimizingMove, RedundantMove, SelfMove]>;
+def Move : DiagGroup<"move", [
+ PessimizingMove,
+ RedundantMove,
+ ReturnStdMove,
+ SelfMove
+ ]>;
def Extra : DiagGroup<"extra", [
MissingFieldInitializers,
@@ -762,14 +799,14 @@ def Most : DiagGroup<"most", [
UserDefinedWarnings
]>;
-// Thread Safety warnings
+// Thread Safety warnings
def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">;
def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">;
def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">;
def ThreadSafetyReference : DiagGroup<"thread-safety-reference">;
def ThreadSafetyNegative : DiagGroup<"thread-safety-negative">;
def ThreadSafety : DiagGroup<"thread-safety",
- [ThreadSafetyAttributes,
+ [ThreadSafetyAttributes,
ThreadSafetyAnalysis,
ThreadSafetyPrecise,
ThreadSafetyReference]>;
@@ -988,3 +1025,7 @@ def SpirCompat : DiagGroup<"spir-compat">;
// Warning for the experimental-isel options.
def ExperimentalISel : DiagGroup<"experimental-isel">;
+
+// A warning group specifically for warnings related to function
+// multiversioning.
+def FunctionMultiVersioning : DiagGroup<"function-multiversion">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
index b4ea85ba853c..983dcb21cfdf 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the Diagnostic IDs-related interfaces.
+/// Defines the Diagnostic IDs-related interfaces.
///
//===----------------------------------------------------------------------===//
@@ -60,7 +60,7 @@ namespace clang {
class CustomDiagInfo;
- /// \brief All of the diagnostics that can be emitted by the frontend.
+ /// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
// Get typedefs for common diagnostics.
@@ -158,25 +158,25 @@ public:
}
};
-/// \brief Used for handling and querying diagnostic IDs.
+/// Used for handling and querying diagnostic IDs.
///
/// Can be used and shared by multiple Diagnostics for multiple translation units.
class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
- /// \brief The level of the diagnostic, after it has been through mapping.
+ /// The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored, Note, Remark, Warning, Error, Fatal
};
private:
- /// \brief Information for uniquing and looking up custom diags.
+ /// Information for uniquing and looking up custom diags.
diag::CustomDiagInfo *CustomDiagInfo;
public:
DiagnosticIDs();
~DiagnosticIDs();
- /// \brief Return an ID for a diagnostic with the specified format string and
+ /// Return an ID for a diagnostic with the specified format string and
/// level.
///
/// If this is the first request for this diagnostic, it is registered and
@@ -191,31 +191,31 @@ public:
// Diagnostic classification and reporting interfaces.
//
- /// \brief Given a diagnostic ID, return a description of the issue.
+ /// Given a diagnostic ID, return a description of the issue.
StringRef getDescription(unsigned DiagID) const;
- /// \brief Return true if the unmapped diagnostic levelof the specified
+ /// Return true if the unmapped diagnostic levelof the specified
/// diagnostic ID is a Warning or Extension.
///
/// This only works on builtin diagnostics, not custom ones, and is not
/// legal to call on NOTEs.
static bool isBuiltinWarningOrExtension(unsigned DiagID);
- /// \brief Return true if the specified diagnostic is mapped to errors by
+ /// Return true if the specified diagnostic is mapped to errors by
/// default.
static bool isDefaultMappingAsError(unsigned DiagID);
- /// \brief Determine whether the given built-in diagnostic ID is a Note.
+ /// Determine whether the given built-in diagnostic ID is a Note.
static bool isBuiltinNote(unsigned DiagID);
- /// \brief Determine whether the given built-in diagnostic ID is for an
+ /// Determine whether the given built-in diagnostic ID is for an
/// extension of some sort.
static bool isBuiltinExtensionDiag(unsigned DiagID) {
bool ignored;
return isBuiltinExtensionDiag(DiagID, ignored);
}
-
- /// \brief Determine whether the given built-in diagnostic ID is for an
+
+ /// Determine whether the given built-in diagnostic ID is for an
/// extension of some sort, and whether it is enabled by default.
///
/// This also returns EnabledByDefault, which is set to indicate whether the
@@ -223,55 +223,55 @@ public:
/// treated as a warning/error by default.
///
static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
-
- /// \brief Return the lowest-level warning option that enables the specified
+
+ /// Return the lowest-level warning option that enables the specified
/// diagnostic.
///
/// If there is no -Wfoo flag that controls the diagnostic, this returns null.
static StringRef getWarningOptionForDiag(unsigned DiagID);
-
- /// \brief Return the category number that a specified \p DiagID belongs to,
+
+ /// Return the category number that a specified \p DiagID belongs to,
/// or 0 if no category.
static unsigned getCategoryNumberForDiag(unsigned DiagID);
- /// \brief Return the number of diagnostic categories.
+ /// Return the number of diagnostic categories.
static unsigned getNumberOfCategories();
- /// \brief Given a category ID, return the name of the category.
+ /// Given a category ID, return the name of the category.
static StringRef getCategoryNameFromID(unsigned CategoryID);
-
- /// \brief Return true if a given diagnostic falls into an ARC diagnostic
+
+ /// Return true if a given diagnostic falls into an ARC diagnostic
/// category.
static bool isARCDiagnostic(unsigned DiagID);
- /// \brief Enumeration describing how the emission of a diagnostic should
+ /// Enumeration describing how the emission of a diagnostic should
/// be treated when it occurs during C++ template argument deduction.
enum SFINAEResponse {
- /// \brief The diagnostic should not be reported, but it should cause
+ /// The diagnostic should not be reported, but it should cause
/// template argument deduction to fail.
///
- /// The vast majority of errors that occur during template argument
+ /// The vast majority of errors that occur during template argument
/// deduction fall into this category.
SFINAE_SubstitutionFailure,
-
- /// \brief The diagnostic should be suppressed entirely.
+
+ /// The diagnostic should be suppressed entirely.
///
/// Warnings generally fall into this category.
SFINAE_Suppress,
-
- /// \brief The diagnostic should be reported.
+
+ /// The diagnostic should be reported.
///
- /// The diagnostic should be reported. Various fatal errors (e.g.,
+ /// The diagnostic should be reported. Various fatal errors (e.g.,
/// template instantiation depth exceeded) fall into this category.
SFINAE_Report,
-
- /// \brief The diagnostic is an access-control diagnostic, which will be
+
+ /// The diagnostic is an access-control diagnostic, which will be
/// substitution failures in some contexts and reported in others.
SFINAE_AccessControl
};
-
- /// \brief Determines whether the given built-in diagnostic ID is
+
+ /// Determines whether the given built-in diagnostic ID is
/// for an error that is suppressed if it occurs during C++ template
/// argument deduction.
///
@@ -281,32 +281,32 @@ public:
/// are not SFINAE errors.
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
- /// \brief Get the string of all diagnostic flags.
+ /// Get the string of all diagnostic flags.
///
/// \returns A list of all diagnostics flags as they would be written in a
/// command line invocation including their `no-` variants. For example:
/// `{"-Wempty-body", "-Wno-empty-body", ...}`
static std::vector<std::string> getDiagnosticFlags();
- /// \brief Get the set of all diagnostic IDs in the group with the given name.
+ /// Get the set of all diagnostic IDs in the group with the given name.
///
/// \param[out] Diags - On return, the diagnostics in the group.
/// \returns \c true if the given group is unknown, \c false otherwise.
bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
SmallVectorImpl<diag::kind> &Diags) const;
- /// \brief Get the set of all diagnostic IDs.
+ /// Get the set of all diagnostic IDs.
static void getAllDiagnostics(diag::Flavor Flavor,
std::vector<diag::kind> &Diags);
- /// \brief Get the diagnostic option with the closest edit distance to the
+ /// Get the diagnostic option with the closest edit distance to the
/// given group name.
static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group);
private:
- /// \brief Classify the specified diagnostic ID into a Level, consumable by
+ /// Classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
- ///
+ ///
/// The classification is based on the way the client configured the
/// DiagnosticsEngine object.
///
@@ -320,17 +320,17 @@ private:
getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
const DiagnosticsEngine &Diag) const LLVM_READONLY;
- /// \brief Used to report a diagnostic that is finally fully formed.
+ /// Used to report a diagnostic that is finally fully formed.
///
/// \returns \c true if the diagnostic was emitted, \c false if it was
/// suppressed.
bool ProcessDiag(DiagnosticsEngine &Diag) const;
- /// \brief Used to emit a diagnostic that is finally fully formed,
+ /// Used to emit a diagnostic that is finally fully formed,
/// ignoring suppression.
void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const;
- /// \brief Whether the diagnostic may leave the AST in a state where some
+ /// Whether the diagnostic may leave the AST in a state where some
/// invariants can break.
bool isUnrecoverable(unsigned DiagID) const;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
index c391470cb1c8..1c960711bccb 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -53,7 +53,7 @@ def ext_multi_line_line_comment : Extension<"multi-line // comment">,
def ext_line_comment : Extension<
"// comments are not allowed in this language">,
InGroup<Comment>;
-def ext_no_newline_eof : Extension<"no newline at end of file">,
+def ext_no_newline_eof : Extension<"no newline at end of file">,
InGroup<NewlineEOF>;
def warn_no_newline_eof : Warning<"no newline at end of file">,
InGroup<NewlineEOF>, DefaultIgnore;
@@ -294,7 +294,7 @@ def pp_nonportable_path : NonportablePath,
InGroup<DiagGroup<"nonportable-include-path">>;
def pp_nonportable_system_path : NonportablePath, DefaultIgnore,
InGroup<DiagGroup<"nonportable-system-include-path">>;
-
+
def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">,
InGroup<DiagGroup<"pragma-once-outside-header">>;
def pp_pragma_sysheader_in_main_file : Warning<
@@ -353,7 +353,7 @@ def ext_pp_warning_directive : Extension<"#warning is a language extension">;
def ext_pp_extra_tokens_at_eol : ExtWarn<
"extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
-
+
def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
def ext_pp_bad_vaargs_use : Extension<
"__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
@@ -404,6 +404,14 @@ def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
def err_pp_directive_required : Error<
"%0 must be used within a preprocessing directive">;
def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
+def err_pp_through_header_not_found : Error<
+ "'%0' required for precompiled header not found">, DefaultFatal;
+def err_pp_through_header_not_seen : Error<
+ "#include of '%0' not seen while attempting to "
+ "%select{create|use}1 precompiled header">, DefaultFatal;
+def warn_pp_macro_def_mismatch_with_pch : Warning<
+ "definition of macro %0 does not match definition in precompiled header">,
+ InGroup<ClangClPch>;
def err_pp_file_not_found_not_fatal : Error<
"'%0' file not found with <angled> include; use \"quotes\" instead">;
def err_pp_error_opening_file : Error<
@@ -505,17 +513,12 @@ def warn_pragma_message : Warning<"%0">,
def err_pragma_message : Error<"%0">;
def warn_pragma_ignored : Warning<"unknown pragma ignored">,
InGroup<UnknownPragmas>, DefaultIgnore;
-def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
- InGroup<UnknownPragmas>;
def ext_on_off_switch_syntax :
ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">,
InGroup<UnknownPragmas>;
def ext_pragma_syntax_eod :
ExtWarn<"expected end of directive in pragma">,
InGroup<UnknownPragmas>;
-def warn_stdc_fenv_access_not_supported :
- Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
- InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_invalid :
ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
" 'push', or 'pop'">,
@@ -591,7 +594,7 @@ def err_pp_illegal_floating_literal : Error<
def err_pp_line_requires_integer : Error<
"#line directive requires a positive integer argument">;
def ext_pp_line_zero : Extension<
- "#line directive with zero argument is a GNU extension">,
+ "#line directive with zero argument is a GNU extension">,
InGroup<GNUZeroLineDirective>;
def err_pp_line_invalid_filename : Error<
"invalid filename for #line directive">;
@@ -699,6 +702,11 @@ def warn_mmap_mismatched_private_module_name : Warning<
InGroup<PrivateModule>;
def note_mmap_rename_top_level_private_module : Note<
"rename '%0' to ensure it can be found by name">;
+def warn_mmap_incomplete_framework_module_declaration : Warning<
+ "skipping '%0' because module declaration of '%1' lacks the 'framework' qualifier">,
+ InGroup<IncompleteFrameworkModuleDeclaration>;
+def note_mmap_add_framework_keyword : Note<
+ "use 'framework module' to declare module '%0'">;
def err_mmap_duplicate_header_attribute : Error<
"header attribute '%0' specified multiple times">;
@@ -714,13 +722,21 @@ def warn_mmap_redundant_export_as : Warning<
def err_mmap_submodule_export_as : Error<
"only top-level modules can be re-exported as public">;
+def warn_quoted_include_in_framework_header : Warning<
+ "double-quoted include \"%0\" in framework header, "
+ "expected angle-bracketed instead"
+ >, InGroup<FrameworkHdrQuotedInclude>, DefaultIgnore;
+def warn_framework_include_private_from_public : Warning<
+ "public framework header includes private framework header '%0'"
+ >, InGroup<FrameworkIncludePrivateFromPublic>;
+
def warn_auto_module_import : Warning<
"treating #%select{include|import|include_next|__include_macros}0 as an "
"import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
def note_implicit_top_level_module_import_here : Note<
"submodule of top-level module '%0' implicitly imported here">;
def warn_uncovered_module_header : Warning<
- "umbrella header for module '%0' does not include header '%1'">,
+ "umbrella header for module '%0' does not include header '%1'">,
InGroup<IncompleteUmbrella>;
def warn_mmap_umbrella_dir_not_found : Warning<
"umbrella directory '%0' not found">,
@@ -739,7 +755,7 @@ def warn_non_modular_include_in_module : Warning<
"include of non-modular header inside module '%0': '%1'">,
InGroup<NonModularIncludeInModule>, DefaultIgnore;
def warn_module_conflict : Warning<
- "module '%0' conflicts with already-imported module '%1': %2">,
+ "module '%0' conflicts with already-imported module '%1': %2">,
InGroup<ModuleConflict>;
def warn_header_guard : Warning<
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def
index 2467b24fd909..22645654afd8 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def
@@ -61,9 +61,9 @@ DIAGOPT(ShowOptionNames, 1, 0) /// Show the option name for mappable
DIAGOPT(ShowNoteIncludeStack, 1, 0) /// Show include stacks for notes.
VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number,
/// 2 -> Full Name.
-
-ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics:
-
+
+ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics:
+
DIAGOPT(ShowColors, 1, 0) /// Show diagnostics with ANSI color sequences.
ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1,
Ovl_All) /// Overload candidates to show.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
index 3844eb63f0ea..4c5bcb4e8793 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
@@ -1,4 +1,4 @@
-//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===//
+//===- DiagnosticOptions.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,14 +18,17 @@
namespace clang {
-/// \brief Specifies which overload candidates to display when overload
+/// Specifies which overload candidates to display when overload
/// resolution fails.
enum OverloadsShown : unsigned {
- Ovl_All, ///< Show all overloads.
- Ovl_Best ///< Show just the "best" overload candidates.
+ /// Show all overloads.
+ Ovl_All,
+
+ /// Show just the "best" overload candidates.
+ Ovl_Best
};
-/// \brief A bitmask representing the diagnostic levels used by
+/// A bitmask representing the diagnostic levels used by
/// VerifyDiagnosticConsumer.
enum class DiagnosticLevelMask : unsigned {
None = 0,
@@ -57,7 +60,7 @@ inline DiagnosticLevelMask operator&(DiagnosticLevelMask LHS,
raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M);
-/// \brief Options for controlling the compiler diagnostics engine.
+/// Options for controlling the compiler diagnostics engine.
class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
public:
enum TextDiagnosticFormat { Clang, MSVC, Vi };
@@ -86,10 +89,10 @@ protected:
#include "clang/Basic/DiagnosticOptions.def"
public:
- /// \brief The file to log diagnostic output to.
+ /// The file to log diagnostic output to.
std::string DiagnosticLogFile;
-
- /// \brief The file to serialize diagnostics to (non-appending).
+
+ /// The file to serialize diagnostics to (non-appending).
std::string DiagnosticSerializationFile;
/// The list of -W... options used to alter the diagnostic mappings, with the
@@ -119,8 +122,8 @@ public:
}
};
-typedef DiagnosticOptions::TextDiagnosticFormat TextDiagnosticFormat;
+using TextDiagnosticFormat = DiagnosticOptions::TextDiagnosticFormat;
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
index 7936cdd96f80..609dca4f075c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -39,7 +39,7 @@ def ext_empty_translation_unit : Extension<
InGroup<DiagGroup<"empty-translation-unit">>;
def warn_cxx98_compat_top_level_semi : Warning<
"extra ';' outside of a function is incompatible with C++98">,
- InGroup<CXX98CompatPedantic>, DefaultIgnore;
+ InGroup<CXX98CompatExtraSemi>, DefaultIgnore;
def ext_extra_semi : Extension<
"extra ';' %select{"
"outside of a function|"
@@ -86,7 +86,7 @@ def err_enumerator_list_missing_comma : Error<
def err_enumerator_unnamed_no_def : Error<
"unnamed enumeration must be a definition">;
def ext_cxx11_enum_fixed_underlying_type : Extension<
- "enumeration types with a fixed underlying type are a C++11 extension">,
+ "enumeration types with a fixed underlying type are a C++11 extension">,
InGroup<CXX11>;
def ext_c_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
@@ -101,7 +101,7 @@ def ext_alignof_expr : ExtWarn<
"%0 applied to an expression is a GNU extension">, InGroup<GNUAlignofExpression>;
def warn_microsoft_dependent_exists : Warning<
- "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">,
+ "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">,
InGroup<DiagGroup<"microsoft-exists">>;
def warn_microsoft_qualifiers_ignored : Warning<
"qualifiers after comma in declarator list are ignored">,
@@ -134,14 +134,14 @@ def ext_gnu_conditional_expr : Extension<
"use of GNU ?: conditional expression extension, omitting middle operand">, InGroup<GNUConditionalOmittedOperand>;
def ext_gnu_empty_initializer : Extension<
"use of GNU empty initializer extension">, InGroup<GNUEmptyInitializer>;
-def ext_gnu_array_range : Extension<"use of GNU array range extension">,
+def ext_gnu_array_range : Extension<"use of GNU array range extension">,
InGroup<GNUDesignator>;
def ext_gnu_missing_equal_designator : ExtWarn<
- "use of GNU 'missing =' extension in designator">,
+ "use of GNU 'missing =' extension in designator">,
InGroup<GNUDesignator>;
def err_expected_equal_designator : Error<"expected '=' or another designator">;
def ext_gnu_old_style_field_designator : ExtWarn<
- "use of GNU old-style field designator extension">,
+ "use of GNU old-style field designator extension">,
InGroup<GNUDesignator>;
def ext_gnu_case_range : Extension<"use of GNU case range extension">,
InGroup<GNUCaseRange>;
@@ -168,13 +168,16 @@ def err_unexpected_semi : Error<"unexpected ';' before %0">;
def err_expected_fn_body : Error<
"expected function body after function declarator">;
def warn_attribute_on_function_definition : Warning<
- "GCC does not allow %0 attribute in this position on a function definition">,
+ "GCC does not allow %0 attribute in this position on a function definition">,
InGroup<GccCompat>;
def warn_gcc_attribute_location : Warning<
- "GCC does not allow an attribute in this position on a function declaration">,
+ "GCC does not allow an attribute in this position on a function declaration">,
InGroup<GccCompat>;
+def warn_gcc_variable_decl_in_for_loop : Warning<
+ "GCC does not allow variable declarations in for loop initializers before "
+ "C99">, InGroup<GccCompat>;
def warn_attribute_no_decl : Warning<
- "attribute %0 ignored, because it is not attached to a declaration">,
+ "attribute %0 ignored, because it is not attached to a declaration">,
InGroup<IgnoredAttributes>;
def err_ms_attributes_not_enabled : Error<
"'__declspec' attributes are not enabled; use '-fdeclspec' or "
@@ -248,6 +251,11 @@ def err_unexpected_at : Error<"unexpected '@' in program">;
def err_atimport : Error<
"use of '@import' when modules are disabled">;
+def warn_atimport_in_framework_header : Warning<
+ "use of '@import' in framework header is discouraged, "
+ "including this header requires -fmodules">,
+ InGroup<FrameworkHdrAtImport>;
+
def err_invalid_reference_qualifier_application : Error<
"'%0' qualifier may not be applied to a reference">;
def err_illegal_decl_reference_to_reference : Error<
@@ -311,7 +319,7 @@ def warn_cxx98_compat_decltype : Warning<
def err_unexpected_scope_on_base_decltype : Error<
"unexpected namespace scope prior to decltype">;
def err_expected_class_name : Error<"expected class name">;
-def err_expected_class_name_not_template :
+def err_expected_class_name_not_template :
Error<"'typename' is redundant; base classes are implicitly types">;
def err_unspecified_vla_size_with_static : Error<
"'static' may not be used with an unspecified variable length array size">;
@@ -387,7 +395,7 @@ def warn_arc_bridge_cast_nonarc : Warning<
"'%0' casts have no effect when not using ARC">,
InGroup<DiagGroup<"arc-bridge-casts-disallowed-in-nonarc">>;
}
-
+
def err_objc_illegal_visibility_spec : Error<
"illegal visibility specification">;
def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">;
@@ -575,7 +583,7 @@ def err_cxx11_attribute_forbids_arguments : Error<
def err_attribute_requires_arguments : Error<
"parentheses must be omitted if %0 attribute's argument list is empty">;
def err_cxx11_attribute_forbids_ellipsis : Error<
- "attribute '%0' cannot be used as an attribute pack">;
+ "attribute %0 cannot be used as an attribute pack">;
def err_cxx11_attribute_repeated : Error<
"attribute %0 cannot appear multiple times in an attribute specifier">;
def warn_cxx14_compat_using_attribute_ns : Warning<
@@ -633,6 +641,8 @@ def err_template_spec_syntax_non_template : Error<
"<unused>|refers to a variable template|<unused>}1">;
def err_id_after_template_in_nested_name_spec : Error<
"expected template name after 'template' keyword in nested name specifier">;
+def err_unexpected_template_in_unqualified_id : Error<
+ "'template' keyword not permitted here">;
def err_two_right_angle_brackets_need_space : Error<
"a space is required between consecutive right angle brackets (use '> >')">;
def err_right_angle_bracket_equal_needs_space : Error<
@@ -677,7 +687,7 @@ def warn_cxx98_compat_extern_template : Warning<
def warn_static_inline_explicit_inst_ignored : Warning<
"ignoring '%select{static|inline}0' keyword on explicit template "
"instantiation">, InGroup<DiagGroup<"static-inline-explicit-instantiation">>;
-
+
// Constructor template diagnostics.
def err_out_of_line_constructor_template_id : Error<
"out-of-line constructor for %0 cannot have template arguments">;
@@ -693,7 +703,7 @@ def err_expected_type_name_after_typename : Error<
"expected an identifier or template-id after '::'">;
def err_explicit_spec_non_template : Error<
"explicit %select{specialization|instantiation}0 of non-template %1 %2">;
-
+
def err_default_template_template_parameter_not_template : Error<
"default template argument for a template template parameter must be a class "
"template">;
@@ -840,7 +850,7 @@ def err_zero_version : Error<
"version number must have non-zero major, minor, or sub-minor version">;
def err_availability_expected_platform : Error<
"expected a platform name, e.g., 'macos'">;
-
+
// objc_bridge_related attribute
def err_objcbridge_related_expected_related_class : Error<
"expected a related ObjectiveC class name, e.g., 'NSColor'">;
@@ -895,6 +905,12 @@ def warn_pragma_expected_rparen : Warning<
"missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_identifier : Warning<
"expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_string : Warning<
+ "expected string literal in '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_missing_argument : Warning<
+ "missing argument to '#pragma %0'%select{|; expected %2}1">, InGroup<IgnoredPragmas>;
+def warn_pragma_invalid_argument : Warning<
+ "unexpected argument '%0' to '#pragma %1'%select{|; expected %3}2">, InGroup<IgnoredPragmas>;
// '#pragma clang section' related errors
def err_pragma_expected_clang_section_name : Error<
@@ -923,6 +939,8 @@ def warn_pragma_ms_struct : Warning<
def warn_pragma_extra_tokens_at_eol : Warning<
"extra tokens at end of '#pragma %0' - ignored">,
InGroup<IgnoredPragmas>;
+def warn_pragma_expected_comma : Warning<
+ "expected ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_punc : Warning<
"expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_non_wide_string : Warning<
@@ -960,6 +978,10 @@ def warn_pragma_pack_malformed : Warning<
def warn_pragma_intrinsic_builtin : Warning<
"%0 is not a recognized builtin%select{|; consider including <intrin.h> to access non-builtin intrinsics}1">,
InGroup<IgnoredPragmaIntrinsic>;
+// - #pragma optimize
+def warn_pragma_optimize : Warning<
+ "'#pragma optimize' is not supported">,
+ InGroup<IgnoredPragmaOptimize>;
// - #pragma unused
def warn_pragma_unused_expected_var : Warning<
"expected '#pragma unused' argument to be a variable name">,
@@ -972,7 +994,13 @@ def warn_pragma_init_seg_unsupported_target : Warning<
// - #pragma fp_contract
def err_pragma_fp_contract_scope : Error<
"'#pragma fp_contract' can only appear at file scope or at the start of a "
- "compound statement">;
+ "compound statement">;
+// - #pragma stdc unknown
+def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
+ InGroup<UnknownPragmas>;
+def warn_stdc_fenv_access_not_supported :
+ Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
+ InGroup<UnknownPragmas>;
// - #pragma comment
def err_pragma_comment_malformed : Error<
"pragma comment requires parenthesized identifier and optional string">;
@@ -1055,6 +1083,12 @@ def err_opencl_taking_function_address_parser : Error<
def err_opencl_logical_exclusive_or : Error<
"^^ is a reserved operator in OpenCL">;
+// OpenCL C++.
+def err_openclcxx_virtual_function : Error<
+ "virtual functions are not supported in OpenCL C++">;
+def err_openclcxx_reserved : Error<
+ "'%0' is a reserved keyword in OpenCL C++">;
+
// OpenMP support.
def warn_pragma_omp_ignored : Warning<
"unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
@@ -1066,7 +1100,7 @@ def warn_pragma_expected_colon_r_paren : Warning<
def err_omp_unknown_directive : Error<
"expected an OpenMP directive">;
def err_omp_unexpected_directive : Error<
- "unexpected OpenMP directive '#pragma omp %0'">;
+ "unexpected OpenMP directive %select{|'#pragma omp %1'}0">;
def err_omp_expected_punc : Error<
"expected ',' or ')' in '%0' %select{clause|directive}1">;
def err_omp_unexpected_clause : Error<
@@ -1156,6 +1190,9 @@ def err_objc_parameterized_implementation : Error<
def err_objc_type_args_after_protocols : Error<
"protocol qualifiers must precede type arguments">;
+
+def note_meant_to_use_typename : Note<
+ "did you mean to use 'typename'?">;
}
let CategoryName = "Coroutines Issue" in {
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9d17bdaeb7cd..dc192aafe38c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -203,6 +203,8 @@ def ext_imaginary_constant : Extension<
def ext_integer_complex : Extension<
"complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
+def err_invalid_saturation_spec : Error<"'_Sat' specifier is only valid on "
+ "'_Fract' or '_Accum', not '%0'">;
def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
def err_invalid_width_spec : Error<
"'%select{|short|long|long long}0 %1' is invalid">;
@@ -241,7 +243,7 @@ def err_invalid_vector_double_decl_spec : Error <
"(available on POWER7 or later)">;
def err_invalid_vector_long_long_decl_spec : Error <
"use of 'long long' with '__vector bool' requires VSX support (available on "
- "POWER7 or later) or extended Altivec support (available on POWER8 or later) "
+ "POWER7 or later) or extended Altivec support (available on POWER8 or later) "
"to be enabled">;
def err_invalid_vector_long_double_decl_spec : Error<
"cannot use 'long double' with '__vector'">;
@@ -272,6 +274,14 @@ def warn_mips_interrupt_attribute : Warning<
"MIPS 'interrupt' attribute only applies to functions that have "
"%select{no parameters|a 'void' return type}0">,
InGroup<IgnoredAttributes>;
+def warn_riscv_repeated_interrupt_attribute : Warning<
+ "repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>;
+def note_riscv_repeated_interrupt_attribute : Note<
+ "repeated RISC-V 'interrupt' attribute is here">;
+def warn_riscv_interrupt_attribute : Warning<
+ "RISC-V 'interrupt' attribute only applies to functions that have "
+ "%select{no parameters|a 'void' return type}0">,
+ InGroup<IgnoredAttributes>;
def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
def warn_unused_variable : Warning<"unused variable %0">,
@@ -279,7 +289,7 @@ def warn_unused_variable : Warning<"unused variable %0">,
def warn_unused_local_typedef : Warning<
"unused %select{typedef|type alias}0 %1">,
InGroup<UnusedLocalTypedef>, DefaultIgnore;
-def warn_unused_property_backing_ivar :
+def warn_unused_property_backing_ivar :
Warning<"ivar %0 which backs the property is not "
"referenced in this property's accessor">,
InGroup<UnusedPropertyIvar>, DefaultIgnore;
@@ -378,7 +388,7 @@ def err_inline_non_function : Error<
"'inline' can only appear on functions%select{| and non-local variables}0">;
def err_noreturn_non_function : Error<
"'_Noreturn' can only appear on functions">;
-def warn_qual_return_type : Warning<
+def warn_qual_return_type : Warning<
"'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">,
InGroup<IgnoredQualifiers>, DefaultIgnore;
def warn_deprecated_redundant_constexpr_static_def : Warning<
@@ -602,9 +612,12 @@ def warn_redecl_library_builtin : Warning<
"incompatible redeclaration of library function %0">,
InGroup<DiagGroup<"incompatible-library-redeclaration">>;
def err_builtin_definition : Error<"definition of builtin function %0">;
+def err_builtin_redeclare : Error<"cannot redeclare 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_invalid_cpu_specific_dispatch_value : Error<
+"invalid option '%0' for %select{cpu_specific|cpu_dispatch}1">;
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 "
@@ -612,16 +625,23 @@ def err_function_needs_feature
"'%2'">;
def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
InGroup<ImplicitFunctionDeclare>, DefaultError;
+def warn_cstruct_memaccess : Warning<
+ "%select{destination for|source of|first operand of|second operand of}0 this "
+ "%1 call is a pointer to record %2 that is not trivial to "
+ "%select{primitive-default-initialize|primitive-copy}3">,
+ InGroup<NonTrivialMemaccess>;
+def note_nontrivial_field : Note<
+ "field is non-trivial to %select{copy|default-initialize}0">;
def warn_dyn_class_memaccess : Warning<
"%select{destination for|source of|first operand of|second operand of}0 this "
"%1 call is a pointer to %select{|class containing a }2dynamic class %3; "
"vtable pointer will be %select{overwritten|copied|moved|compared}4">,
- InGroup<DiagGroup<"dynamic-class-memaccess">>;
+ InGroup<DynamicClassMemaccess>;
def note_bad_memaccess_silence : Note<
"explicitly cast the pointer to silence this warning">;
def warn_sizeof_pointer_expr_memaccess : Warning<
- "'%0' call operates on objects of type %1 while the size is based on a "
- "different type %2">,
+ "'%0' call operates on objects of type %1 while the size is based on a "
+ "different type %2">,
InGroup<SizeofPointerMemaccess>;
def warn_sizeof_pointer_expr_memaccess_note : Note<
"did you mean to %select{dereference the argument to 'sizeof' (and multiply "
@@ -645,16 +665,28 @@ def note_memsize_comparison_paren : Note<
"did you mean to compare the result of %0 instead?">;
def note_memsize_comparison_cast_silence : Note<
"explicitly cast the argument to size_t to silence this warning">;
-
+def warn_suspicious_sizeof_memset : Warning<
+ "%select{'size' argument to memset is '0'|"
+ "setting buffer to a 'sizeof' expression}0"
+ "; did you mean to transpose the last two arguments?">,
+ InGroup<MemsetTransposedArgs>;
+def note_suspicious_sizeof_memset_silence : Note<
+ "%select{parenthesize the third argument|"
+ "cast the second argument to 'int'}0 to silence">;
+def warn_suspicious_bzero_size : Warning<"'size' argument to bzero is '0'">,
+ InGroup<SuspiciousBzero>;
+def note_suspicious_bzero_size_silence : Note<
+ "parenthesize the second argument to silence">;
+
def warn_strncat_large_size : Warning<
- "the value of the size argument in 'strncat' is too large, might lead to a "
+ "the value of the size argument in 'strncat' is too large, might lead to a "
"buffer overflow">, InGroup<StrncatSize>;
-def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears "
+def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears "
"to be size of the source">, InGroup<StrncatSize>;
def warn_strncat_wrong_size : Warning<
"the value of the size argument to 'strncat' is wrong">, InGroup<StrncatSize>;
def note_strncat_wrong_size : Note<
- "change the argument to be the free space in the destination buffer minus "
+ "change the argument to be the free space in the destination buffer minus "
"the terminating null byte">;
def warn_assume_side_effects : Warning<
@@ -751,7 +783,7 @@ 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<
+def warn_pragma_pack_pop_identifier_and_alignment : Warning<
"specifying both a name and alignment to 'pop' is undefined">;
def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">,
InGroup<IgnoredPragmas>;
@@ -998,15 +1030,15 @@ def note_property_attribute : Note<"property %0 is declared "
"%select{deprecated|unavailable|partial}1 here">;
def err_setter_type_void : Error<"type of setter must be void">;
def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
-def warn_duplicate_method_decl :
- Warning<"multiple declarations of method %0 found and ignored">,
+def warn_duplicate_method_decl :
+ Warning<"multiple declarations of method %0 found and ignored">,
InGroup<MethodDuplicate>, DefaultIgnore;
def warn_objc_cdirective_format_string :
Warning<"using %0 directive in %select{NSString|CFString}1 "
"which is being passed as a formatting argument to the formatting "
"%select{method|CFfunction}2">,
InGroup<ObjCCStringFormat>, DefaultIgnore;
-def err_objc_var_decl_inclass :
+def err_objc_var_decl_inclass :
Error<"cannot declare variable inside @interface or @protocol">;
def err_missing_method_context : Error<
"missing context for method declaration">;
@@ -1031,7 +1063,7 @@ def warn_objc_pointer_masking : Warning<
def warn_objc_pointer_masking_performSelector : Warning<warn_objc_pointer_masking.Text>,
InGroup<ObjCPointerIntrospectPerformSelector>;
def warn_objc_property_default_assign_on_object : Warning<
- "default property attribute 'assign' not appropriate for non-GC object">,
+ "default property attribute 'assign' not appropriate for object">,
InGroup<ObjCPropertyNoAttribute>;
def warn_property_attr_mismatch : Warning<
"property attribute in class extension does not match the primary class">,
@@ -1218,7 +1250,7 @@ def warn_auto_implicit_atomic_property : Warning<
"property is assumed atomic when auto-synthesizing the property">,
InGroup<ImplicitAtomic>, DefaultIgnore;
def warn_unimplemented_selector: Warning<
- "no method with selector %0 is implemented in this translation unit">,
+ "no method with selector %0 is implemented in this translation unit">,
InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method %0 in protocol %1 not implemented">, InGroup<Protocol>;
@@ -1329,7 +1361,7 @@ def err_invalid_member_in_interface : Error<
"nested class }0%1 is not permitted within an interface type">;
def err_invalid_base_in_interface : Error<
"interface type cannot inherit from "
- "%select{'struct|non-public 'interface|'class}0 %1'">;
+ "%select{struct|non-public interface|class}0 %1">;
def err_abstract_type_in_decl : Error<
"%select{return|parameter|variable|field|instance variable|"
@@ -1347,7 +1379,7 @@ def err_capture_default_non_local : Error<
"non-local lambda expression cannot have a capture-default">;
def err_multiple_final_overriders : Error<
- "virtual function %q0 has more than one final overrider in %1">;
+ "virtual function %q0 has more than one final overrider in %1">;
def note_final_overrider : Note<"final overrider of %q0 in %1">;
def err_type_defined_in_type_specifier : Error<
@@ -1389,7 +1421,7 @@ def warn_weak_template_vtable : Warning<
def ext_using_undefined_std : ExtWarn<
"using directive refers to implicitly-defined namespace 'std'">;
-
+
// C++ exception specifications
def err_exception_spec_in_typedef : Error<
"exception specifications are not allowed in %select{typedefs|type aliases}0">;
@@ -1443,7 +1475,7 @@ def ext_ms_using_declaration_inaccessible : ExtWarn<
"to accessible member '%1') is a Microsoft compatibility extension">,
AccessControl, InGroup<MicrosoftUsingDecl>;
def err_access_ctor : Error<
- "calling a %select{private|protected}0 constructor of class %2">,
+ "calling a %select{private|protected}0 constructor of class %2">,
AccessControl;
def ext_rvalue_to_reference_access_ctor : Extension<
"C++98 requires an accessible copy constructor for class %2 when binding "
@@ -1466,7 +1498,7 @@ def err_access_friend_function : Error<
AccessControl;
def err_access_dtor : Error<
- "calling a %select{private|protected}1 destructor of class %0">,
+ "calling a %select{private|protected}1 destructor of class %0">,
AccessControl;
def err_access_dtor_base :
Error<"base class %0 has %select{private|protected}1 destructor">,
@@ -1508,7 +1540,7 @@ def note_access_protected_restricted_object : Note<
def warn_cxx98_compat_sfinae_access_control : Warning<
"substitution failure due to access control is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore, NoSFINAE;
-
+
// C++ name lookup
def err_incomplete_nested_name_spec : Error<
"incomplete type %0 named in nested name specifier">;
@@ -1586,6 +1618,8 @@ def err_not_integral_type_bitfield : Error<
"bit-field %0 has non-integral type %1">;
def err_not_integral_type_anon_bitfield : Error<
"anonymous bit-field has non-integral type %0">;
+def err_anon_bitfield_qualifiers : Error<
+ "anonymous bit-field cannot have qualifiers">;
def err_member_function_initialization : Error<
"initializer on function does not look like a pure-specifier">;
def err_non_virtual_pure : Error<
@@ -1612,13 +1646,16 @@ def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
"overrides of %0 in subclasses are not available in the "
"%select{constructor|destructor}1 of %2">;
+def select_special_member_kind : TextSubstitution<
+ "%select{default constructor|copy constructor|move constructor|"
+ "copy assignment operator|move assignment operator|destructor}0">;
+
def note_member_declared_at : Note<"member is declared here">;
def note_ivar_decl : Note<"instance variable is declared here">;
def note_bitfield_decl : Note<"bit-field is declared here">;
def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
def note_member_synthesized_at : Note<
- "in implicit %select{default constructor|copy constructor|move constructor|"
- "copy assignment operator|move assignment operator|destructor}0 for %1 "
+ "in implicit %sub{select_special_member_kind}0 for %1 "
"first required here">;
def err_missing_default_ctor : Error<
"%select{constructor for %1 must explicitly initialize the|"
@@ -1627,16 +1664,14 @@ def err_missing_default_ctor : Error<
"%select{base class|member}2 %3 %select{which|which|of %1}0 "
"does not have a default constructor">;
def note_due_to_dllexported_class : Note<
- "due to '%0' being dllexported%select{|; try compiling in C++11 mode}1">;
+ "due to %0 being dllexported%select{|; try compiling in C++11 mode}1">;
def err_illegal_union_or_anon_struct_member : Error<
"%select{anonymous struct|union}0 member %1 has a non-trivial "
- "%select{constructor|copy constructor|move constructor|copy assignment "
- "operator|move assignment operator|destructor}2">;
+ "%sub{select_special_member_kind}2">;
def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning<
"%select{anonymous struct|union}0 member %1 with a non-trivial "
- "%select{constructor|copy constructor|move constructor|copy assignment "
- "operator|move assignment operator|destructor}2 is incompatible with C++98">,
+ "%sub{select_special_member_kind}2 is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def note_nontrivial_virtual_dtor : Note<
@@ -1655,8 +1690,7 @@ def note_nontrivial_no_copy : Note<
"%select{base class|field|an object}0 of type %3">;
def note_nontrivial_user_provided : Note<
"because %select{base class of |field of |}0type %1 has a user-provided "
- "%select{default constructor|copy constructor|move constructor|"
- "copy assignment operator|move assignment operator|destructor}2">;
+ "%sub{select_special_member_kind}2">;
def note_nontrivial_in_class_init : Note<
"because field %0 has an initializer">;
def note_nontrivial_param_type : Note<
@@ -1699,6 +1733,8 @@ def warn_overriding_method_missing_noescape : Warning<
"__attribute__((noescape))">, InGroup<MissingNoEscape>;
def note_overridden_marked_noescape : Note<
"parameter of overridden method is annotated with __attribute__((noescape))">;
+def note_cat_conform_to_noescape_prot : Note<
+ "%select{category|class extension}0 conforms to protocol %1 which defines method %2">;
def err_covariant_return_inaccessible_base : Error<
"invalid covariant return for virtual function: %1 is a "
@@ -1723,9 +1759,7 @@ def err_covariant_return_type_class_type_more_qualified : Error<
// C++ implicit special member functions
def note_in_declaration_of_implicit_special_member : Note<
- "while declaring the implicit "
- "%select{default constructor|copy constructor|move constructor|"
- "copy assignment operator|move assignment operator|destructor}1"
+ "while declaring the implicit %sub{select_special_member_kind}1"
" for %0">;
// C++ constructors
@@ -1780,7 +1814,8 @@ def err_destructor_template : Error<
// C++ initialization
def err_init_conversion_failed : Error<
- "cannot initialize %select{a variable|a parameter|return object|an "
+ "cannot initialize %select{a variable|a parameter|return object|"
+ "statement expression result|an "
"exception object|a member subobject|an array element|a new value|a value|a "
"base class|a constructor delegation|a vector element|a block element|a "
"block element|a complex element|a lambda capture|a compound literal "
@@ -1820,10 +1855,6 @@ def err_reference_bind_failed : Error<
"type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
def err_reference_bind_init_list : Error<
"reference to type %0 cannot bind to an initializer list">;
-def warn_temporary_array_to_pointer_decay : Warning<
- "pointer is initialized by a temporary array, which will be destroyed at the "
- "end of the full-expression">,
- InGroup<DiagGroup<"address-of-array-temporary">>;
def err_init_list_bad_dest_type : Error<
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
"list">;
@@ -1915,34 +1946,29 @@ def warn_unsequenced_mod_mod : Warning<
def warn_unsequenced_mod_use : Warning<
"unsequenced modification and access to %0">, InGroup<Unsequenced>;
+def select_initialized_entity_kind : TextSubstitution<
+ "%select{copying variable|copying parameter|"
+ "returning object|initializing statement expression result|"
+ "throwing object|copying member subobject|copying array element|"
+ "allocating object|copying temporary|initializing base subobject|"
+ "initializing vector element|capturing value}0">;
+
def err_temp_copy_no_viable : Error<
- "no viable constructor %select{copying variable|copying parameter|"
- "returning object|throwing object|copying member subobject|copying array "
- "element|allocating object|copying temporary|initializing base subobject|"
- "initializing vector element|capturing value}0 of type %1">;
+ "no viable constructor %sub{select_initialized_entity_kind}0 of type %1">;
def ext_rvalue_to_reference_temp_copy_no_viable : Extension<
- "no viable constructor %select{copying variable|copying parameter|"
- "returning object|throwing object|copying member subobject|copying array "
- "element|allocating object|copying temporary|initializing base subobject|"
- "initializing vector element|capturing value}0 of type %1; C++98 requires a copy "
- "constructor when binding a reference to a temporary">,
+ "no viable constructor %sub{select_initialized_entity_kind}0 of type %1; "
+ "C++98 requires a copy constructor when binding a reference to a temporary">,
InGroup<BindToTemporaryCopy>;
def err_temp_copy_ambiguous : Error<
- "ambiguous constructor call when %select{copying variable|copying "
- "parameter|returning object|throwing object|copying member subobject|copying "
- "array element|allocating object|copying temporary|initializing base subobject|"
- "initializing vector element|capturing value}0 of type %1">;
+ "ambiguous constructor call when %sub{select_initialized_entity_kind}0 "
+ "of type %1">;
def err_temp_copy_deleted : Error<
- "%select{copying variable|copying parameter|returning object|throwing "
- "object|copying member subobject|copying array element|allocating object|"
- "copying temporary|initializing base subobject|initializing vector element|"
- "capturing value}0 of type %1 invokes deleted constructor">;
+ "%sub{select_initialized_entity_kind}0 of type %1 "
+ "invokes deleted constructor">;
def err_temp_copy_incomplete : Error<
"copying a temporary object of incomplete type %0">;
def warn_cxx98_compat_temp_copy : Warning<
- "%select{copying variable|copying parameter|returning object|throwing "
- "object|copying member subobject|copying array element|allocating object|"
- "copying temporary|initializing base subobject|initializing vector element}1 "
+ "%sub{select_initialized_entity_kind}1 "
"of type %2 when binding a reference to a temporary would %select{invoke "
"an inaccessible constructor|find no viable constructor|find ambiguous "
"constructors|invoke a deleted constructor}0 in C++98">,
@@ -1955,7 +1981,7 @@ def note_explicit_ctor_deduction_guide_here : Note<
// C++11 decltype
def err_decltype_in_declarator : Error<
"'decltype' cannot be used to name a declaration">;
-
+
// C++11 auto
def warn_cxx98_compat_auto_type_specifier : Warning<
"'auto' type specifier is incompatible with C++98">,
@@ -2039,10 +2065,6 @@ def err_implied_std_initializer_list_not_found : Error<
"not found; include <initializer_list>">;
def err_malformed_std_initializer_list : Error<
"std::initializer_list must be a class template with a single type parameter">;
-def warn_dangling_std_initializer_list : Warning<
- "array backing the initializer list will be destroyed at the end of "
- "%select{the full-expression|the constructor}0">,
- InGroup<DiagGroup<"dangling-initializer-list">>;
def err_auto_init_list_from_c : Error<
"cannot use __auto_type with initializer list in C">;
def err_auto_bitfield : Error<
@@ -2107,9 +2129,16 @@ def err_deduction_guide_explicit_mismatch : Error<
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
"%select{explicitly instantiated|explicitly specialized}0">;
def err_deduction_guide_template_not_deducible : Error<
- "deduction guide template contains "
- "%select{a template parameter|template parameters}0 that cannot be "
- "deduced">;
+ "deduction guide template contains "
+ "%select{a template parameter|template parameters}0 that cannot be "
+ "deduced">;
+def err_deduction_guide_wrong_access : Error<
+ "deduction guide has different access from the corresponding "
+ "member template">;
+def note_deduction_guide_template_access : Note<
+ "member template declared %0 here">;
+def note_deduction_guide_access : Note<
+ "deduction guide declared %0 by intervening access specifier">;
// C++1y deduced return types
def err_auto_fn_deduction_failure : Error<
@@ -2371,6 +2400,8 @@ def note_non_literal_user_provided_dtor : Note<
"%0 is not literal because it has a user-provided destructor">;
def note_non_literal_nontrivial_dtor : Note<
"%0 is not literal because it has a non-trivial destructor">;
+def note_non_literal_lambda : Note<
+ "lambda closure types are non-literal types before C++17">;
def warn_private_extern : Warning<
"use of __private_extern__ on a declaration may not produce external symbol "
"private to the linkage unit and is deprecated">, InGroup<PrivateExtern>;
@@ -2411,6 +2442,9 @@ def err_template_different_associated_constraints : Error<
def warn_cxx98_compat_unicode_type : Warning<
"'%0' type specifier is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx17_compat_unicode_type : Warning<
+ "'char8_t' type specifier is incompatible with C++ standards before C++20">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
// __make_integer_seq
def err_integer_sequence_negative_length : Error<
@@ -2449,8 +2483,8 @@ 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 %select{unsupported|duplicate}0"
- "%select{| architecture}1 '%2' in the target attribute string">,
+ : Warning<"%select{unsupported|duplicate}0%select{| architecture}1 '%2' in"
+ " the 'target' attribute string; 'target' attribute ignored">,
InGroup<IgnoredAttributes>;
def err_attribute_unsupported
: Error<"%0 attribute is not supported for this target">;
@@ -2554,6 +2588,9 @@ def err_attribute_address_space_too_high : Error<
"address space is larger than the maximum supported (%0)">;
def err_attribute_address_multiple_qualifiers : Error<
"multiple address spaces specified for type">;
+def warn_attribute_address_multiple_identical_qualifiers : Warning<
+ "multiple identical address spaces specified for type">,
+ InGroup<DuplicateDeclSpecifier>;
def err_attribute_address_function_type : Error<
"function type may not be qualified with an address space">;
def err_as_qualified_auto_decl : Error<
@@ -2597,7 +2634,7 @@ def warn_objc_literal_comparison : Warning<
def err_missing_atsign_prefix : Error<
"string literal must be prefixed by '@' ">;
def warn_objc_string_literal_comparison : Warning<
- "direct comparison of a string literal has undefined behavior">,
+ "direct comparison of a string literal has undefined behavior">,
InGroup<ObjCStringComparison>;
def warn_concatenated_nsarray_literal : Warning<
"concatenated NSString literal for an NSArray expression - "
@@ -2647,11 +2684,19 @@ def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
def err_attribute_section_invalid_for_target : Error<
- "argument to 'section' attribute is not valid for this target: %0">;
+ "argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">;
def warn_mismatched_section : Warning<
- "section does not match previous declaration">, InGroup<Section>;
+ "%select{codeseg|section}0 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_mismatched_code_seg_base : Error<
+ "derived class must specify the same code segment as its base classes">;
+def err_mismatched_code_seg_override : Error<
+ "overriding virtual function must specify the same code segment as its overridden function">;
+def err_conflicting_codeseg_attribute : Error<
+ "conflicting code segment specifiers">;
+def warn_duplicate_codeseg_attribute : Warning<
+ "duplicate code segment specifiers">, InGroup<Section>;
def err_anonymous_property: Error<
"anonymous property is not supported">;
@@ -2691,6 +2736,9 @@ def warn_attribute_ignored : Warning<"%0 attribute ignored">,
def warn_attribute_ignored_on_inline :
Warning<"%0 attribute ignored on inline function">,
InGroup<IgnoredAttributes>;
+def warn_nocf_check_attribute_ignored :
+ Warning<"'nocf_check' attribute ignored; use -fcf-protection to enable the attribute">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_after_definition_ignored : Warning<
"attribute %0 after definition is ignored">,
InGroup<IgnoredAttributes>;
@@ -2700,7 +2748,7 @@ def warn_cxx11_gnu_attribute_on_type : Warning<
"attribute %0 ignored, because it cannot be applied to a type">,
InGroup<IgnoredAttributes>;
def warn_unhandled_ms_attribute_ignored : Warning<
- "__declspec attribute %0 is not supported">,
+ "__declspec attribute %0 is not supported">,
InGroup<IgnoredAttributes>;
def err_decl_attribute_invalid_on_stmt : Error<
"%0 attribute cannot be applied to a statement">;
@@ -2804,7 +2852,7 @@ def warn_alias_with_section : Warning<
"%select{alias|ifunc}1 will not be in section '%0' but in the same section as the %select{aliasee|resolver}2">,
InGroup<IgnoredAttributes>;
def err_duplicate_mangled_name : Error<
- "definition with same mangled name as another definition">;
+ "definition with same mangled name '%0' as another definition">;
def err_cyclic_alias : Error<
"%select{alias|ifunc}0 definition is part of a cycle">;
def err_ifunc_resolver_return : Error<
@@ -2829,8 +2877,7 @@ def warn_attribute_wrong_decl_type : Warning<
"|types and namespaces"
"|variables, functions and classes"
"|kernel functions"
- "|non-K&R-style functions"
- "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}1">,
+ "|non-K&R-style functions}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
def warn_type_attribute_wrong_type : Warning<
@@ -2885,6 +2932,9 @@ def err_base_specifier_attribute : Error<
def err_invalid_attribute_on_virtual_function : Error<
"%0 attribute cannot be applied to virtual functions">;
+def ext_cannot_use_trivial_abi : ExtWarn<
+ "'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>;
+
// Availability attribute
def warn_availability_unknown_platform : Warning<
"unknown platform %0 in availability macro">, InGroup<Availability>;
@@ -2904,6 +2954,10 @@ def warn_mismatched_availability_override_unavail : Warning<
"%select{the protocol method it implements|its overridden method}1 is "
"available">,
InGroup<Availability>;
+def warn_availability_on_static_initializer : Warning<
+ "ignoring availability attribute %select{on '+load' method|"
+ "with constructor attribute|with destructor attribute}0">,
+ InGroup<Availability>;
def note_overridden_method : Note<
"overridden method is here">;
def note_protocol_method : Note<
@@ -2949,7 +3003,7 @@ def err_attribute_argument_out_of_range : Error<
"1:can only be 1, since there is one parameter|"
":must be between 1 and %2}2">;
-// Thread Safety Analysis
+// Thread Safety Analysis
def warn_unlock_but_no_lock : Warning<"releasing %0 '%1' that was not held">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_unlock_kind_mismatch : Warning<
@@ -2963,7 +3017,7 @@ def warn_no_unlock : Warning<
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_expecting_locked : Warning<
"expecting %0 '%1' to be held at the end of function">,
- InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
// FIXME: improve the error message about locks not in scope
def warn_lock_some_predecessors : Warning<
"%0 '%1' is not held on every path through here">,
@@ -2978,11 +3032,11 @@ def warn_lock_exclusive_and_shared : Warning<
def note_lock_exclusive_and_shared : Note<
"the other acquisition of %0 '%1' is here">;
def warn_variable_requires_any_lock : Warning<
- "%select{reading|writing}1 variable '%0' requires holding "
+ "%select{reading|writing}1 variable %0 requires holding "
"%select{any mutex|any mutex exclusively}1">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_any_lock : Warning<
- "%select{reading|writing}1 the value pointed to by '%0' requires holding "
+ "%select{reading|writing}1 the value pointed to by %0 requires holding "
"%select{any mutex|any mutex exclusively}1">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_excludes_mutex : Warning<
@@ -3006,25 +3060,25 @@ def warn_acquire_requires_negative_cap : Warning<
// Thread safety warnings on pass by reference
def warn_guarded_pass_by_reference : Warning<
- "passing variable '%1' by reference requires holding %0 "
+ "passing variable %1 by reference requires holding %0 "
"%select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyReference>, DefaultIgnore;
def warn_pt_guarded_pass_by_reference : Warning<
- "passing the value that '%1' points to by reference requires holding %0 "
+ "passing the value that %1 points to by reference requires holding %0 "
"%select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyReference>, DefaultIgnore;
// Imprecise thread safety warnings
def warn_variable_requires_lock : Warning<
- "%select{reading|writing}3 variable '%1' requires holding %0 "
+ "%select{reading|writing}3 variable %1 requires holding %0 "
"%select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_lock : Warning<
- "%select{reading|writing}3 the value pointed to by '%1' requires "
+ "%select{reading|writing}3 the value pointed to by %1 requires "
"holding %0 %select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_requires_lock : Warning<
- "calling function '%1' requires holding %0 %select{'%2'|'%2' exclusively}3">,
+ "calling function %1 requires holding %0 %select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
// Precise thread safety warnings
@@ -3040,13 +3094,13 @@ def warn_fun_requires_lock_precise :
def note_found_mutex_near_match : Note<"found near match '%0'">;
// Verbose thread safety warnings
-def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">,
+def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">,
InGroup<ThreadSafetyVerbose>, DefaultIgnore;
-def note_thread_warning_in_fun : Note<"Thread warning in function '%0'">;
+def note_thread_warning_in_fun : Note<"Thread warning in function %0">;
def note_guarded_by_declared_here : Note<"Guarded_by declared here.">;
-// Dummy warning that will trigger "beta" warnings from the analysis if enabled.
-def warn_thread_safety_beta : Warning<"Thread safety beta warning.">,
+// Dummy warning that will trigger "beta" warnings from the analysis if enabled.
+def warn_thread_safety_beta : Warning<"Thread safety beta warning.">,
InGroup<ThreadSafetyBeta>, DefaultIgnore;
// Consumed warnings
@@ -3090,6 +3144,9 @@ def err_impcast_complex_scalar : Error<
def warn_impcast_float_precision : Warning<
"implicit conversion loses floating-point precision: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_float_result_precision : Warning<
+ "implicit conversion when assigning computation result loses floating-point precision: %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
def warn_impcast_double_promotion : Warning<
"implicit conversion increases floating-point precision: %0 to %1">,
InGroup<DoublePromotion>, DefaultIgnore;
@@ -3115,13 +3172,18 @@ def warn_impcast_bitfield_precision_constant : Warning<
def warn_impcast_literal_float_to_integer : Warning<
"implicit conversion from %0 to %1 changes value from %2 to %3">,
InGroup<LiteralConversion>;
+def warn_impcast_literal_float_to_integer_out_of_range : Warning<
+ "implicit conversion of out of range value from %0 to %1 is undefined">,
+ InGroup<LiteralConversion>;
def warn_impcast_float_integer : Warning<
"implicit conversion turns floating-point number into integer: %0 to %1">,
InGroup<FloatConversion>, DefaultIgnore;
def warn_impcast_float_to_integer : Warning<
- "implicit conversion of out of range value from %0 to %1 changes value "
- "from %2 to %3">,
+ "implicit conversion from %0 to %1 changes value from %2 to %3">,
+ InGroup<FloatOverflowConversion>, DefaultIgnore;
+def warn_impcast_float_to_integer_out_of_range : Warning<
+ "implicit conversion of out of range value from %0 to %1 is undefined">,
InGroup<FloatOverflowConversion>, DefaultIgnore;
def warn_impcast_float_to_integer_zero : Warning<
"implicit conversion from %0 to %1 changes non-zero value from %2 to %3">,
@@ -3294,7 +3356,7 @@ def err_attribute_sentinel_not_zero_or_one : Error<
"'sentinel' parameter 2 not 0 or 1">;
def warn_cleanup_ext : Warning<
"GCC does not allow the 'cleanup' attribute argument to be anything other "
- "than a simple identifier">,
+ "than a simple identifier">,
InGroup<GccCompat>;
def err_attribute_cleanup_arg_not_function : Error<
"'cleanup' argument %select{|%1 |%1 }0is not a %select{||single }0function">;
@@ -3311,6 +3373,9 @@ def err_attribute_not_supported_in_lang : Error<
"%0 attribute is not supported in %select{C|C++|Objective-C}1">;
def err_attribute_not_supported_on_arch
: Error<"%0 attribute is not supported on '%1'">;
+def warn_gcc_ignores_type_attr : Warning<
+ "GCC does not allow the %0 attribute to be written on a type">,
+ InGroup<GccCompat>;
// Clang-Specific Attributes
def warn_attribute_iboutlet : Warning<
@@ -3326,7 +3391,7 @@ def warn_iboutlet_object_type : Warning<
def warn_iboutletcollection_property_assign : Warning<
"IBOutletCollection properties should be copy/strong and not assign">,
InGroup<ObjCInvalidIBOutletProperty>;
-
+
def err_attribute_overloadable_mismatch : Error<
"redeclaration of %0 must %select{not |}1have the 'overloadable' attribute">;
def note_attribute_overloadable_prev_overload : Note<
@@ -3492,27 +3557,29 @@ def err_ovl_deleted_member_call : Error<
def note_ovl_too_many_candidates : Note<
"remaining %0 candidate%s0 omitted; "
"pass -fshow-overloads=all to show them">;
-def note_ovl_candidate : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "is the implicit default constructor|"
- "is the implicit copy constructor|"
- "is the implicit move constructor|"
- "is the implicit copy assignment operator|"
- "is the implicit move assignment operator|"
- "inherited constructor|"
- "inherited constructor }0%2"
- "%select{| has different class%diff{ (expected $ but has $)|}4,5"
- "| has different number of parameters (expected %4 but has %5)"
- "| has type mismatch at %ordinal4 parameter"
- "%diff{ (expected $ but has $)|}5,6"
- "| has different return type%diff{ ($ expected but has $)|}4,5"
+
+def select_ovl_candidate_kind : TextSubstitution<
+ "%select{function|function|constructor|"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "inherited constructor}0%select{| template| %2}1">;
+
+def note_ovl_candidate : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,3"
+ "%select{| has different class%diff{ (expected $ but has $)|}5,6"
+ "| has different number of parameters (expected %5 but has %6)"
+ "| has type mismatch at %ordinal5 parameter"
+ "%diff{ (expected $ but has $)|}6,7"
+ "| has different return type%diff{ ($ expected but has $)|}5,6"
"| has different qualifiers (expected "
"%select{none|const|restrict|const and restrict|volatile|const and volatile"
- "|volatile and restrict|const, volatile, and restrict}4 but found "
+ "|volatile and restrict|const, volatile, and restrict}5 but found "
"%select{none|const|restrict|const and restrict|volatile|const and volatile"
- "|volatile and restrict|const, volatile, and restrict}5)"
- "| has different exception specification}3">;
+ "|volatile and restrict|const, volatile, and restrict}6)"
+ "| has different exception specification}4">;
def note_ovl_candidate_inherited_constructor : Note<
"constructor from base class %0 inherited here">;
@@ -3526,6 +3593,9 @@ def note_ovl_candidate_bad_deduction : Note<
"candidate template ignored: failed template argument deduction">;
def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
"couldn't infer template argument %0">;
+def note_ovl_candidate_incomplete_deduction_pack : Note<"candidate template ignored: "
+ "deduced too few arguments for expanded pack %0; no argument for %ordinal1 "
+ "expanded parameter in deduced argument pack %2">;
def note_ovl_candidate_inconsistent_deduction : Note<
"candidate template ignored: deduced conflicting %select{types|values|"
"templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">;
@@ -3582,233 +3652,99 @@ def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
// Note that we don't treat templates differently for this diagnostic.
def note_ovl_candidate_arity : Note<"candidate "
- "%select{function|function|constructor|function|function|constructor|"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor}0 %select{|template }1"
- "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 "
- "%plural{1:was|:were}4 provided">;
+ "%sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "requires%select{ at least| at most|}3 %4 argument%s4, but %5 "
+ "%plural{1:was|:were}5 provided">;
def note_ovl_candidate_arity_one : Note<"candidate "
- "%select{function|function|constructor|function|function|constructor|"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor}0 %select{|template }1not viable: "
- "%select{requires at least|allows at most single|requires single}2 "
- "argument %3, but %plural{0:no|:%4}4 arguments were provided">;
+ "%sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "%select{requires at least|allows at most single|requires single}3 "
+ "argument %4, but %plural{0:no|:%5}5 arguments were provided">;
def note_ovl_candidate_deleted : Note<
- "candidate %select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 has been "
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 has been "
"%select{explicitly made unavailable|explicitly deleted|"
- "implicitly deleted}2">;
+ "implicitly deleted}3">;
// Giving the index of the bad argument really clutters this message, and
// it's relatively unimportant because 1) it's generally obvious which
// argument(s) are of the given object type and 2) the fix is usually
// to complete the type, which doesn't involve changes to the call line
// anyway. If people complain, we can change it.
-def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 "
- "not viable: cannot convert argument of incomplete type "
- "%diff{$ to $|to parameter type}2,3 for "
- "%select{%ordinal5 argument|object argument}4"
+def note_ovl_candidate_bad_conv_incomplete : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "cannot convert argument of incomplete type "
+ "%diff{$ to $|to parameter type}3,4 for "
+ "%select{%ordinal6 argument|object argument}5"
"%select{|; dereference the argument with *|"
"; take the address of the argument with &|"
"; remove *|"
- "; remove &}6">;
-def note_ovl_candidate_bad_list_argument : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 "
- "not viable: cannot convert initializer list argument to %3">;
-def note_ovl_candidate_bad_overload : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1"
- " not viable: no overload of %3 matching %2 for %ordinal4 argument">;
-def note_ovl_candidate_bad_conv : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1"
- " not viable: no known conversion "
- "%diff{from $ to $|from argument type to parameter type}2,3 for "
- "%select{%ordinal5 argument|object argument}4"
+ "; remove &}7">;
+def note_ovl_candidate_bad_list_argument : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "cannot convert initializer list argument to %4">;
+def note_ovl_candidate_bad_overload : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "no overload of %4 matching %3 for %ordinal5 argument">;
+def note_ovl_candidate_bad_conv : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "no known conversion "
+ "%diff{from $ to $|from argument type to parameter type}3,4 for "
+ "%select{%ordinal6 argument|object argument}5"
"%select{|; dereference the argument with *|"
"; take the address of the argument with &|"
"; remove *|"
- "; remove &}6">;
-def note_ovl_candidate_bad_arc_conv : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1"
- " not viable: cannot implicitly convert argument "
- "%diff{of type $ to $|type to parameter type}2,3 for "
- "%select{%ordinal5 argument|object argument}4 under ARC">;
-def note_ovl_candidate_bad_lvalue : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1"
- " not viable: expects an l-value for "
- "%select{%ordinal3 argument|object argument}2">;
-def note_ovl_candidate_bad_addrspace : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 not viable: "
- "%select{%ordinal6|'this'}5 argument (%2) is in "
- "address space %3, but parameter must be in address space %4">;
-def note_ovl_candidate_bad_gc : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 not viable: "
- "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 "
- "ownership, but parameter has %select{no|__weak|__strong}4 ownership">;
-def note_ovl_candidate_bad_ownership : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 not viable: "
- "%select{%ordinal6|'this'}5 argument (%2) has "
- "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}3 ownership,"
+ "; remove &}7">;
+def note_ovl_candidate_bad_arc_conv : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "cannot implicitly convert argument "
+ "%diff{of type $ to $|type to parameter type}3,4 for "
+ "%select{%ordinal6 argument|object argument}5 under ARC">;
+def note_ovl_candidate_bad_lvalue : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "expects an l-value for "
+ "%select{%ordinal4 argument|object argument}3">;
+def note_ovl_candidate_bad_addrspace : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "address space mismatch in %select{%ordinal6|'this'}5 argument (%3), "
+ "parameter type must be %4">;
+def note_ovl_candidate_bad_gc : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "%select{%ordinal7|'this'}6 argument (%3) has %select{no|__weak|__strong}4 "
+ "ownership, but parameter has %select{no|__weak|__strong}5 ownership">;
+def note_ovl_candidate_bad_ownership : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "%select{%ordinal7|'this'}6 argument (%3) has "
+ "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}4 ownership,"
" but parameter has %select{no|__unsafe_unretained|__strong|__weak|"
- "__autoreleasing}4 ownership">;
-def note_ovl_candidate_bad_cvr_this : Note<"candidate "
- "%select{|function|||function|||||"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)||}0 not viable: "
- "'this' argument has type %2, but method is not marked "
+ "__autoreleasing}5 ownership">;
+def note_ovl_candidate_bad_cvr_this : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "'this' argument has type %3, but method is not marked "
"%select{const|restrict|const or restrict|volatile|const or volatile|"
- "volatile or restrict|const, volatile, or restrict}3">;
-def note_ovl_candidate_bad_cvr : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 not viable: "
- "%ordinal4 argument (%2) would lose "
+ "volatile or restrict|const, volatile, or restrict}4">;
+def note_ovl_candidate_bad_cvr : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "%ordinal5 argument (%3) would lose "
"%select{const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}3 qualifier"
- "%select{||s||s|s|s}3">;
-def note_ovl_candidate_bad_unaligned : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 not viable: "
- "%ordinal4 argument (%2) would lose __unaligned qualifier">;
-def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor }0%1 not viable: "
- "cannot %select{convert from|convert from|bind}2 "
- "%select{base class pointer|superclass|base class object of type}2 %3 to "
- "%select{derived class pointer|subclass|derived class reference}2 %4 for "
- "%ordinal5 argument">;
+ "volatile and restrict|const, volatile, and restrict}4 qualifier"
+ "%select{||s||s|s|s}4">;
+def note_ovl_candidate_bad_unaligned : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "%ordinal5 argument (%3) would lose __unaligned qualifier">;
+def note_ovl_candidate_bad_base_to_derived_conv : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "cannot %select{convert from|convert from|bind}3 "
+ "%select{base class pointer|superclass|base class object of type}3 %4 to "
+ "%select{derived class pointer|subclass|derived class reference}3 %5 for "
+ "%ordinal6 argument">;
def note_ovl_candidate_bad_target : Note<
- "candidate %select{function|function|constructor|"
- "function|function|constructor|"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "constructor (the implicit move constructor)|"
- "function (the implicit copy assignment operator)|"
- "function (the implicit move assignment operator)|"
- "inherited constructor|"
- "inherited constructor}0 not viable: "
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
"call to "
- "%select{__device__|__global__|__host__|__host__ __device__|invalid}1 function from"
- " %select{__device__|__global__|__host__|__host__ __device__|invalid}2 function">;
+ "%select{__device__|__global__|__host__|__host__ __device__|invalid}3 function from"
+ " %select{__device__|__global__|__host__|__host__ __device__|invalid}4 function">;
def note_implicit_member_target_infer_collision : Note<
- "implicit %select{"
- "default constructor|"
- "copy constructor|"
- "move constructor|"
- "copy assignment operator|"
- "move assignment operator|"
- "destructor}0 inferred target collision: call to both "
+ "implicit %sub{select_special_member_kind}0 inferred target collision: call to both "
"%select{__device__|__global__|__host__|__host__ __device__}1 and "
"%select{__device__|__global__|__host__|__host__ __device__}2 members">;
@@ -3850,16 +3786,14 @@ def err_ovl_deleted_oper : Error<
"overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">;
def err_ovl_deleted_special_oper : Error<
"object of type %0 cannot be %select{constructed|copied|moved|assigned|"
- "assigned|destroyed}1 because its %select{default constructor|"
- "copy constructor|move constructor|copy assignment operator|"
- "move assignment operator|destructor}1 is implicitly deleted">;
+ "assigned|destroyed}1 because its %sub{select_special_member_kind}1 is implicitly deleted">;
def err_ovl_no_viable_subscript :
Error<"no viable overloaded operator[] for type %0">;
def err_ovl_no_oper :
Error<"type %0 does not provide a %select{subscript|call}1 operator">;
def err_ovl_unresolvable : Error<
- "reference to overloaded function could not be resolved; "
- "did you mean to call it%select{| with no arguments}0?">;
+ "reference to %select{overloaded|multiversioned}1 function could not be "
+ "resolved; did you mean to call it%select{| with no arguments}0?">;
def err_bound_member_function : Error<
"reference to non-static member function must be called"
"%select{|; did you mean to call it with no arguments?}0">;
@@ -3922,7 +3856,7 @@ def note_template_param_different_kind : Note<
def err_invalid_decl_specifier_in_nontype_parm : Error<
"invalid declaration specifier in template non-type parameter">;
-
+
def err_template_nontype_parm_different_type : Error<
"template non-type parameter has a different type %0 in template "
"%select{|template parameter }1redeclaration">;
@@ -3969,8 +3903,6 @@ def err_template_member_noparams : Error<
"extraneous 'template<>' in declaration of member %0">;
def err_template_tag_noparams : Error<
"extraneous 'template<>' in declaration of %0 %1">;
-def err_template_decl_ref : Error<
- "cannot refer to %select{class|variable}0 template %1 without a template argument list">;
// C++ Template Argument Lists
def err_template_missing_args : Error<
@@ -4138,42 +4070,20 @@ def note_explicit_specialization_declared_here : Note<
"explicit specialization declared here">;
def err_template_spec_decl_function_scope : Error<
"explicit specialization of %0 in function scope">;
-def err_template_spec_decl_class_scope : Error<
- "explicit specialization of %0 in class scope">;
def err_template_spec_decl_friend : Error<
"cannot declare an explicit specialization in a friend">;
-def err_template_spec_decl_out_of_scope_global : Error<
- "%select{class template|class template partial|variable template|"
- "variable template partial|function template|member function|"
- "static data member|member class|member enumeration}0 "
- "specialization of %1 must originally be declared in the global scope">;
-def err_template_spec_decl_out_of_scope : Error<
- "%select{class template|class template partial|variable template|"
- "variable template partial|function template|member "
- "function|static data member|member class|member enumeration}0 "
- "specialization of %1 must originally be declared in namespace %2">;
-def ext_template_spec_decl_out_of_scope : ExtWarn<
- "first declaration of %select{class template|class template partial|"
- "variable template|variable template partial|"
- "function template|member function|static data member|member class|"
- "member enumeration}0 specialization of %1 outside namespace %2 is a "
- "C++11 extension">, InGroup<CXX11>;
-def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning<
- "%select{class template|class template partial|variable template|"
- "variable template partial|function template|member "
- "function|static data member|member class|member enumeration}0 "
- "specialization of %1 outside namespace %2 is incompatible with C++98">,
- InGroup<CXX98Compat>, DefaultIgnore;
def err_template_spec_redecl_out_of_scope : Error<
"%select{class template|class template partial|variable template|"
"variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
- "specialization of %1 not in a namespace enclosing %2">;
+ "specialization of %1 not in %select{a namespace enclosing %2|"
+ "class %2 or an enclosing namespace}3">;
def ext_ms_template_spec_redecl_out_of_scope: ExtWarn<
"%select{class template|class template partial|variable template|"
"variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
- "specialization of %1 outside namespace enclosing %2 "
+ "specialization of %1 not in %select{a namespace enclosing %2|"
+ "class %2 or an enclosing namespace}3 "
"is a Microsoft extension">, InGroup<MicrosoftTemplate>;
def err_template_spec_redecl_global_scope : Error<
"%select{class template|class template partial|variable template|"
@@ -4195,16 +4105,18 @@ def err_template_spec_default_arg : Error<
def err_not_class_template_specialization : Error<
"cannot specialize a %select{dependent template|template template "
"parameter}0">;
-def err_function_specialization_in_class : Error<
- "cannot specialize a function %0 within class scope">;
-def ext_function_specialization_in_class : ExtWarn<
- "explicit specialization of %0 within class scope is a Microsoft extension">,
- InGroup<MicrosoftTemplate>;
def ext_explicit_specialization_storage_class : ExtWarn<
"explicit specialization cannot have a storage class">;
def err_explicit_specialization_inconsistent_storage_class : Error<
"explicit specialization has extraneous, inconsistent storage class "
"'%select{none|extern|static|__private_extern__|auto|register}0'">;
+def err_dependent_function_template_spec_no_match : Error<
+ "no candidate function template was found for dependent"
+ " friend function template specialization">;
+def note_dependent_function_template_spec_discard_reason : Note<
+ "candidate ignored: %select{not a function template"
+ "|not a member of the enclosing namespace;"
+ " did you mean to explicitly qualify the specialization?}0">;
// C++ class template specializations and out-of-line definitions
def err_template_spec_needs_header : Error<
@@ -4246,7 +4158,7 @@ def err_dependent_typed_non_type_arg_in_partial_spec : Error<
def err_partial_spec_args_match_primary_template : Error<
"%select{class|variable}0 template partial specialization does not "
"specialize any template argument; to %select{declare|define}1 the "
- "primary template, remove the template argument list">;
+ "primary template, remove the template argument list">;
def ext_partial_spec_not_more_specialized_than_primary : ExtWarn<
"%select{class|variable}0 template partial specialization is not "
"more specialized than the primary template">, DefaultError,
@@ -4281,7 +4193,7 @@ def err_var_spec_no_template : Error<
def err_var_spec_no_template_but_method : Error<
"no variable template matches specialization; "
"did you mean to use %0 as function template instead?">;
-
+
// C++ Function template specializations
def err_function_template_spec_no_match : Error<
"no function template matches function template specialization %0">;
@@ -4402,12 +4314,12 @@ def err_explicit_instantiation_out_of_scope : Error<
def err_explicit_instantiation_must_be_global : Error<
"explicit instantiation of %0 must occur at global scope">;
def warn_explicit_instantiation_out_of_scope_0x : Warning<
- "explicit instantiation of %0 not in a namespace enclosing %1">,
+ "explicit instantiation of %0 not in a namespace enclosing %1">,
InGroup<CXX11Compat>, DefaultIgnore;
def warn_explicit_instantiation_must_be_global_0x : Warning<
- "explicit instantiation of %0 must occur at global scope">,
+ "explicit instantiation of %0 must occur at global scope">,
InGroup<CXX11Compat>, DefaultIgnore;
-
+
def err_explicit_instantiation_requires_name : Error<
"explicit instantiation declaration requires a name">;
def err_explicit_instantiation_of_typedef : Error<
@@ -4468,7 +4380,7 @@ def err_mismatched_exception_spec_explicit_instantiation : Error<
def ext_mismatched_exception_spec_explicit_instantiation : ExtWarn<
err_mismatched_exception_spec_explicit_instantiation.Text>,
InGroup<MicrosoftExceptionSpec>;
-
+
// C++ typename-specifiers
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
def err_typename_nested_not_found_enable_if : Error<
@@ -4501,6 +4413,8 @@ def note_using_value_decl_missing_typename : Note<
def err_template_kw_refers_to_non_template : Error<
"%0 following the 'template' keyword does not refer to a template">;
+def note_template_kw_refers_to_non_template : Note<
+ "declared as a non-template here">;
def err_template_kw_refers_to_class_template : Error<
"'%0%1' instantiated to a class template, not a function template">;
def note_referenced_class_template : Note<
@@ -4544,7 +4458,7 @@ def note_template_parameter_pack_non_pack : Note<
def note_template_parameter_pack_here : Note<
"previous %select{template type|non-type template|template template}0 "
"parameter%select{| pack}1 declared here">;
-
+
def err_unexpanded_parameter_pack : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
@@ -4562,6 +4476,9 @@ def err_pack_expansion_length_conflict : Error<
def err_pack_expansion_length_conflict_multilevel : Error<
"pack expansion contains parameter pack %0 that has a different "
"length (%1 vs. %2) from outer parameter packs">;
+def err_pack_expansion_length_conflict_partial : Error<
+ "pack expansion contains parameter pack %0 that has a different "
+ "length (at least %1 vs. %2) from outer parameter packs">;
def err_pack_expansion_member_init : Error<
"pack expansion for initialization of member %0">;
@@ -4645,7 +4562,7 @@ def warn_missing_prototype : Warning<
"no previous prototype for function %0">,
InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
def note_declaration_not_a_prototype : Note<
- "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">;
+ "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">;
def warn_strict_prototypes : Warning<
"this %select{function declaration is not|block declaration is not|"
"old-style function definition is not preceded by}0 a prototype">,
@@ -4853,7 +4770,7 @@ def ext_ms_forward_ref_enum : ExtWarn<
def ext_forward_ref_enum_def : Extension<
"redeclaration of already-defined enum %0 is a GNU extension">,
InGroup<GNURedeclaredEnum>;
-
+
def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
def err_duplicate_member : Error<"duplicate member %0">;
def err_misplaced_ivar : Error<
@@ -4872,7 +4789,7 @@ def ext_enumerator_increment_too_large : ExtWarn<
def warn_flag_enum_constant_out_of_range : Warning<
"enumeration value %0 is out of range of flags in enumeration type %1">,
InGroup<FlagEnum>;
-
+
def warn_illegal_constant_array_size : Extension<
"size of static array must be an integer constant expression">;
def err_vm_decl_in_file_scope : Error<
@@ -4977,7 +4894,7 @@ def err_illegal_initializer : Error<
"illegal initializer (only variables can be initialized)">;
def err_illegal_initializer_type : Error<"illegal initializer type %0">;
def ext_init_list_type_narrowing : ExtWarn<
- "type %0 cannot be narrowed to %1 in initializer list">,
+ "type %0 cannot be narrowed to %1 in initializer list">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def ext_init_list_variable_narrowing : ExtWarn<
"non-constant-expression cannot be narrowed from type %0 to %1 in "
@@ -5120,12 +5037,17 @@ def note_protected_by_objc_strong_init : Note<
"jump bypasses initialization of __strong variable">;
def note_protected_by_objc_weak_init : Note<
"jump bypasses initialization of __weak variable">;
+def note_protected_by_non_trivial_c_struct_init : Note<
+ "jump bypasses initialization of variable of non-trivial C struct type">;
def note_enters_block_captures_cxx_obj : Note<
"jump enters lifetime of block which captures a destructible C++ object">;
def note_enters_block_captures_strong : Note<
"jump enters lifetime of block which strongly captures a variable">;
def note_enters_block_captures_weak : Note<
"jump enters lifetime of block which weakly captures a variable">;
+def note_enters_block_captures_non_trivial_c_struct : Note<
+ "jump enters lifetime of block which captures a C struct that is non-trivial "
+ "to destroy">;
def note_exits_cleanup : Note<
"jump exits scope of variable with __attribute__((cleanup))">;
@@ -5166,6 +5088,9 @@ def note_exits_block_captures_strong : Note<
"jump exits lifetime of block which strongly captures a variable">;
def note_exits_block_captures_weak : Note<
"jump exits lifetime of block which weakly captures a variable">;
+def note_exits_block_captures_non_trivial_c_struct : Note<
+ "jump exits lifetime of block which captures a C struct that is non-trivial "
+ "to destroy">;
def err_func_returning_qualified_void : ExtWarn<
"function cannot return qualified void type %0">,
@@ -5307,9 +5232,9 @@ def err_arc_illegal_method_def : Error<
def warn_arc_strong_pointer_objc_pointer : Warning<
"method parameter of type %0 with no explicit ownership">,
InGroup<DiagGroup<"explicit-ownership-type">>, DefaultIgnore;
-
+
} // end "ARC Restrictions" category
-
+
def err_arc_lost_method_convention : Error<
"method was declared as %select{an 'alloc'|a 'copy'|an 'init'|a 'new'}0 "
"method, but its implementation doesn't match because %select{"
@@ -5378,7 +5303,7 @@ def warn_receiver_forward_instance : Warning<
InGroup<ForwardClassReceiver>, DefaultIgnore;
def err_arc_collection_forward : Error<
"collection expression type %0 is a forward declaration">;
-def err_arc_multiple_method_decl : Error<
+def err_arc_multiple_method_decl : Error<
"multiple methods named %0 found with mismatched result, "
"parameter type or attributes">;
def warn_arc_lifetime_result_type : Warning<
@@ -5419,8 +5344,6 @@ def warn_block_capture_autoreleasing : Warning<
"block captures an autoreleasing out-parameter, which may result in "
"use-after-free bugs">,
InGroup<BlockCaptureAutoReleasing>;
-def note_declare_parameter_autoreleasing : Note<
- "declare the parameter __autoreleasing explicitly to suppress this warning">;
def note_declare_parameter_strong : Note<
"declare the parameter __strong or capture a __block __strong variable to "
"keep values alive across autorelease pools">;
@@ -5609,9 +5532,12 @@ def warn_addition_in_bitshift : Warning<
"operator '%0' has lower precedence than '%1'; "
"'%1' will be evaluated first">, InGroup<ShiftOpParentheses>;
-def warn_self_assignment : Warning<
+def warn_self_assignment_builtin : Warning<
"explicitly assigning value of variable of type %0 to itself">,
InGroup<SelfAssignment>, DefaultIgnore;
+def warn_self_assignment_overloaded : Warning<
+ "explicitly assigning value of variable of type %0 to itself">,
+ InGroup<SelfAssignmentOverloaded>, DefaultIgnore;
def warn_self_move : Warning<
"explicitly moving variable of type %0 to itself">,
InGroup<SelfMove>, DefaultIgnore;
@@ -5627,6 +5553,19 @@ def warn_pessimizing_move_on_initialization : Warning<
InGroup<PessimizingMove>, DefaultIgnore;
def note_remove_move : Note<"remove std::move call here">;
+def warn_return_std_move : Warning<
+ "local variable %0 will be copied despite being %select{returned|thrown}1 by name">,
+ InGroup<ReturnStdMove>, DefaultIgnore;
+def note_add_std_move : Note<
+ "call 'std::move' explicitly to avoid copying">;
+def warn_return_std_move_in_cxx11 : Warning<
+ "prior to the resolution of a defect report against ISO C++11, "
+ "local variable %0 would have been copied despite being returned by name, "
+ "due to its not matching the function return type%diff{ ($ vs $)|}1,2">,
+ InGroup<ReturnStdMoveInCXX11>, DefaultIgnore;
+def note_add_std_move_in_cxx11 : Note<
+ "call 'std::move' explicitly to avoid copying on older compilers">;
+
def warn_string_plus_int : Warning<
"adding %0 to a string does not append to the string">,
InGroup<StringPlusInt>;
@@ -5757,7 +5696,7 @@ def warn_namespace_member_extra_qualification : Warning<
"extra qualification on member %0">,
InGroup<DiagGroup<"extra-qualification">>;
def err_member_qualification : Error<
- "non-friend class member %0 cannot have a qualified name">;
+ "non-friend class member %0 cannot have a qualified name">;
def note_member_def_close_match : Note<"member declaration nearly matches">;
def note_member_def_close_const_match : Note<
"member declaration does not match because "
@@ -5805,6 +5744,13 @@ def err_array_init_wide_string_into_char : Error<
"initializing char array with wide string literal">;
def err_array_init_incompat_wide_string_into_wchar : Error<
"initializing wide char array with incompatible wide string literal">;
+def err_array_init_plain_string_into_char8_t : Error<
+ "initializing 'char8_t' array with plain string literal">;
+def note_array_init_plain_string_into_char8_t : Note<
+ "add 'u8' prefix to form a 'char8_t' string literal">;
+def err_array_init_utf8_string_into_char : Error<
+ "initialization of char array with UTF-8 string literal is not permitted "
+ "by '-fchar8_t'">;
def err_array_init_different_type : Error<
"cannot initialize array %diff{of type $ with array of type $|"
"with different type of array}0,1">;
@@ -5856,7 +5802,7 @@ def err_typecheck_invalid_lvalue_addrof_addrof_function : Error<
def err_typecheck_invalid_lvalue_addrof : Error<
"cannot take the address of an rvalue of type %0">;
def ext_typecheck_addrof_temporary : ExtWarn<
- "taking the address of a temporary object of type %0">,
+ "taking the address of a temporary object of type %0">,
InGroup<AddressOfTemporary>, DefaultError;
def err_typecheck_addrof_temporary : Error<
"taking the address of a temporary object of type %0">;
@@ -5889,6 +5835,8 @@ def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
def err_typecheck_invalid_operands : Error<
"invalid operands to binary expression (%0 and %1)">;
+def note_typecheck_invalid_operands_converted : Note<
+ "%select{first|second}0 operand was implicitly converted to type %1">;
def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error<
"logical expression with vector %select{type %1 and non-vector type %2|types"
" %1 and %2}0 is only supported in C++">;
@@ -5902,7 +5850,8 @@ def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension<
def err_typecheck_ordered_comparison_of_pointer_and_zero : Error<
"ordered comparison between pointer and zero (%0 and %1)">;
def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn<
- "ordered comparison of function pointers (%0 and %1)">;
+ "ordered comparison of function pointers (%0 and %1)">,
+ InGroup<DiagGroup<"ordered-compare-function-pointers">>;
def ext_typecheck_comparison_of_fptr_to_void : Extension<
"equality comparison between function pointer and void pointer (%0 and %1)">;
def err_typecheck_comparison_of_fptr_to_void : Error<
@@ -5964,7 +5913,7 @@ def warn_mixed_sign_comparison : Warning<
"comparison of integers of different signs: %0 and %1">,
InGroup<SignCompare>, DefaultIgnore;
def warn_out_of_range_compare : Warning<
- "result of comparison of %select{constant %0|true|false}1 with "
+ "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>,
@@ -6122,7 +6071,7 @@ def err_no_subobject_property_setting : Error<
"expression is not assignable">;
def err_qualified_objc_access : Error<
"%select{property|instance variable}0 access cannot be qualified with '%1'">;
-
+
def ext_freestanding_complex : Extension<
"complex numbers are an extension in a freestanding C99 implementation">;
@@ -6194,9 +6143,9 @@ def err_objc_object_catch : Error<
def err_incomplete_type_objc_at_encode : Error<
"'@encode' of incomplete type %0">;
def warn_objc_circular_container : Warning<
- "adding '%0' to '%1' might cause circular dependency in container">,
+ "adding %0 to %1 might cause circular dependency in container">,
InGroup<DiagGroup<"objc-circular-container">>;
-def note_objc_circular_container_declared_here : Note<"'%0' declared here">;
+def note_objc_circular_container_declared_here : Note<"%0 declared here">;
def warn_objc_unsafe_perform_selector : Warning<
"%0 is incompatible with selectors that return a "
"%select{struct|union|vector}1 type">,
@@ -6268,6 +6217,12 @@ def err_bad_cxx_cast_bitfield : Error<
def err_bad_cxx_cast_qualifiers_away : Error<
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
"functional-style cast}0 from %1 to %2 casts away qualifiers">;
+def ext_bad_cxx_cast_qualifiers_away_incoherent : ExtWarn<
+ "ISO C++ does not allow "
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2 because it casts away qualifiers, "
+ "even though the source and destination types are unrelated">,
+ SFINAEFailure, InGroup<DiagGroup<"cast-qual-unrelated">>;
def err_bad_const_cast_dest : Error<
"%select{const_cast||||C-style cast|functional-style cast}0 to %2, "
"which is not a reference, pointer-to-object, or pointer-to-data-member">;
@@ -6282,13 +6237,13 @@ def warn_cxx98_compat_cast_fn_obj : Warning<
def err_bad_reinterpret_cast_small_int : Error<
"cast from pointer to smaller type %2 loses information">;
def err_bad_cxx_cast_vector_to_scalar_different_size : Error<
- "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
+ "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
"to scalar %2 of different size">;
def err_bad_cxx_cast_scalar_to_vector_different_size : Error<
- "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 "
+ "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 "
"to vector %2 of different size">;
def err_bad_cxx_cast_vector_to_vector_different_size : Error<
- "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
+ "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
"to vector %2 of different size">;
def err_bad_lvalue_to_rvalue_cast : Error<
"cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
@@ -6448,6 +6403,8 @@ def err_bad_memptr_rhs : Error<
def err_bad_memptr_lhs : Error<
"left hand operand to %0 must be a %select{|pointer to }1class "
"compatible with the right hand operand, but is %2">;
+def err_memptr_incomplete : Error<
+ "member pointer has incomplete base type %0">;
def warn_exception_caught_by_earlier_handler : Warning<
"exception of type %0 will be caught by earlier handler">,
InGroup<Exceptions>;
@@ -6508,12 +6465,12 @@ def warn_overaligned_type : Warning<
"type %0 requires %1 bytes of alignment and the default allocator only "
"guarantees %2 bytes">,
InGroup<OveralignedType>, DefaultIgnore;
-def warn_aligned_allocation_unavailable :Warning<
+def err_aligned_allocation_unavailable : Error<
"aligned %select{allocation|deallocation}0 function of type '%1' is only "
- "available on %2 %3 or newer">, InGroup<AlignedAllocationUnavailable>, DefaultError;
+ "available on %2 %3 or newer">;
def note_silence_unligned_allocation_unavailable : Note<
"if you supply your own aligned allocation functions, use "
- "-Wno-aligned-allocation-unavailable to silence this diagnostic">;
+ "-faligned-allocation to silence this diagnostic">;
def err_conditional_void_nonvoid : Error<
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
@@ -6569,6 +6526,8 @@ let CategoryName = "Lambda Issue" in {
"lambda expression in an unevaluated operand">;
def err_lambda_in_constant_expression : Error<
"a lambda expression may not appear inside of a constant expression">;
+ def err_lambda_in_invalid_context : Error<
+ "a lambda expression cannot appear in this context">;
def err_lambda_return_init_list : Error<
"cannot deduce lambda return type from initializer list">;
def err_lambda_capture_default_arg : Error<
@@ -6627,6 +6586,11 @@ let CategoryName = "Lambda Issue" in {
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 warn_deprecated_this_capture : Warning<
+ "implicit capture of 'this' with a capture default of '=' is deprecated">,
+ InGroup<DeprecatedThisCapture>, DefaultIgnore;
+ def note_deprecated_this_capture : Note<
+ "add an explicit capture of 'this' to capture '*this' by reference">;
}
def err_return_in_captured_stmt : Error<
@@ -6681,7 +6645,7 @@ def err_typecheck_nonviable_condition_incomplete : Error<
def err_typecheck_deleted_function : Error<
"conversion function %diff{from $ to $|between types}0,1 "
"invokes a deleted function">;
-
+
def err_expected_class_or_namespace : Error<"%0 is not a class"
"%select{ or namespace|, namespace, or enumeration}1">;
def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here "
@@ -6696,9 +6660,9 @@ def err_not_tag_in_scope : Error<
"no %select{struct|interface|union|class|enum}0 named %1 in %2">;
def err_no_typeid_with_fno_rtti : Error<
- "cannot use typeid with -fno-rtti">;
+ "use of typeid requires -frtti">;
def err_no_dynamic_cast_with_fno_rtti : Error<
- "cannot use dynamic_cast with -fno-rtti">;
+ "use of dynamic_cast requires -frtti">;
def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">;
@@ -7049,11 +7013,11 @@ def err_typecheck_call_too_many_args_at_most_suggest : Error<
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected at most %1, have %2; did you mean %3?">;
-
+
def err_arc_typecheck_convert_incompatible_pointer : Error<
"incompatible pointer types passing retainable parameter of type %0"
"to a CF function expecting %1 type">;
-
+
def err_builtin_fn_use : Error<"builtin functions must be directly called">;
def warn_call_wrong_number_of_arguments : Warning<
@@ -7063,6 +7027,8 @@ def err_atomic_builtin_must_be_pointer : Error<
def err_atomic_builtin_must_be_pointer_intptr : Error<
"address argument to atomic builtin must be a pointer to integer or pointer"
" (%0 invalid)">;
+def err_atomic_builtin_cannot_be_const : Error<
+ "address argument to atomic builtin cannot be const-qualified (%0 invalid)">;
def err_atomic_builtin_must_be_pointer_intfltptr : Error<
"address argument to atomic builtin must be a pointer to integer,"
" floating-point or pointer (%0 invalid)">;
@@ -7087,6 +7053,8 @@ def err_atomic_op_needs_trivial_copy : Error<
def err_atomic_op_needs_atomic_int_or_ptr : Error<
"address argument to atomic operation must be a pointer to %select{|atomic }0"
"integer or pointer (%1 invalid)">;
+def err_atomic_op_needs_int32_or_ptr : Error<
+ "address argument to atomic operation must be a pointer to signed or unsigned 32-bit integer">;
def err_atomic_op_bitwise_needs_atomic_int : Error<
"address argument to bitwise atomic operation must be a pointer to "
"%select{|atomic }0integer (%1 invalid)">;
@@ -7095,6 +7063,9 @@ def warn_atomic_op_has_invalid_memory_order : Warning<
InGroup<DiagGroup<"atomic-memory-ordering">>;
def err_atomic_op_has_invalid_synch_scope : Error<
"synchronization scope argument to atomic operation is invalid">;
+def warn_atomic_op_misaligned : Warning<
+ "misaligned or large atomic operation may incur significant performance penalty">,
+ InGroup<DiagGroup<"atomic-alignment">>;
def err_overflow_builtin_must_be_int : Error<
"operand argument to overflow builtin must be an integer (%0 invalid)">;
@@ -7145,7 +7116,7 @@ def err_va_arg_in_device : Error<
"CUDA device code does not support va_arg">;
def err_alias_not_supported_on_nvptx : Error<"CUDA does not support aliases">;
def err_cuda_unattributed_constexpr_cannot_overload_device : Error<
- "constexpr function '%0' without __host__ or __device__ attributes cannot "
+ "constexpr function %0 without __host__ or __device__ attributes cannot "
"overload __device__ function with same signature. Add a __host__ "
"attribute, or build with -fno-cuda-host-device-constexpr.">;
def note_cuda_conflicting_device_function_declared_here : Note<
@@ -7160,7 +7131,8 @@ def err_shared_var_init : Error<
"initialization is not supported for __shared__ variables.">;
def err_device_static_local_var : Error<
"within a %select{__device__|__global__|__host__|__host__ __device__}0 "
- "function, only __shared__ variables may be marked 'static'">;
+ "function, only __shared__ variables or const variables without device "
+ "memory qualifier may be marked 'static'">;
def err_cuda_vla : Error<
"cannot use variable-length arrays in "
"%select{__device__|__global__|__host__|__host__ __device__}0 functions">;
@@ -7184,6 +7156,10 @@ def err_cannot_pass_objc_interface_to_vararg_format : Error<
"cannot pass object with interface type %1 by value to variadic "
"%select{function|block|method|constructor}2; expected type from format "
"string was %3">;
+def err_cannot_pass_non_trivial_c_struct_to_vararg : Error<
+ "cannot pass non-trivial C object of type %0 by value to variadic "
+ "%select{function|block|method|constructor}1">;
+
def err_cannot_pass_objc_interface_to_vararg : Error<
"cannot pass object with interface type %0 by value through variadic "
@@ -7532,8 +7508,8 @@ def err_reference_to_local_in_enclosing_context : Error<
"%select{%3|block literal|lambda expression|context}2">;
def err_static_data_member_not_allowed_in_local_class : Error<
- "static data member %0 not allowed in local class %1">;
-
+ "static data member %0 not allowed in local class %1">;
+
// C++ derived classes
def err_base_clause_on_union : Error<"unions cannot have base classes">;
def err_base_must_be_class : Error<"base specifier must name a class">;
@@ -7631,6 +7607,11 @@ def err_destroying_operator_delete_not_usual : Error<
"alignment parameter">;
def note_implicit_delete_this_in_destructor_here : Note<
"while checking implicit 'delete this' for virtual destructor">;
+def err_builtin_operator_new_delete_not_usual : Error<
+ "call to '%select{__builtin_operator_new|__builtin_operator_delete}0' "
+ "selects non-usual %select{allocation|deallocation}0 function">;
+def note_non_usual_function_declared_here : Note<
+ "non-usual %0 declared here">;
// C++ literal operators
def err_literal_operator_outside_namespace : Error<
@@ -7713,9 +7694,8 @@ def err_defaulted_special_member_quals : Error<
"an explicitly-defaulted %select{copy|move}0 assignment operator may not "
"have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">;
def err_defaulted_special_member_volatile_param : Error<
- "the parameter for an explicitly-defaulted %select{<<ERROR>>|"
- "copy constructor|move constructor|copy assignment operator|"
- "move assignment operator|<<ERROR>>}0 may not be volatile">;
+ "the parameter for an explicitly-defaulted %sub{select_special_member_kind}0 "
+ "may not be volatile">;
def err_defaulted_special_member_move_const_param : Error<
"the parameter for an explicitly-defaulted move "
"%select{constructor|assignment operator}0 may not be const">;
@@ -7727,17 +7707,13 @@ def err_defaulted_copy_assign_not_ref : Error<
"the parameter for an explicitly-defaulted copy assignment operator must be an "
"lvalue reference type">;
def err_incorrect_defaulted_exception_spec : Error<
- "exception specification of explicitly defaulted %select{default constructor|"
- "copy constructor|move constructor|copy assignment operator|move assignment "
- "operator|destructor}0 does not match the "
- "calculated one">;
+ "exception specification of explicitly defaulted "
+ "%sub{select_special_member_kind}0 does not match the calculated one">;
def err_incorrect_defaulted_constexpr : Error<
- "defaulted definition of %select{default constructor|copy constructor|"
- "move constructor|copy assignment operator|move assignment operator}0 "
+ "defaulted definition of %sub{select_special_member_kind}0 "
"is not constexpr">;
def err_out_of_line_default_deletes : Error<
- "defaulting this %select{default constructor|copy constructor|move "
- "constructor|copy assignment operator|move assignment operator|destructor}0 "
+ "defaulting this %sub{select_special_member_kind}0 "
"would delete it after its first declaration">;
def warn_vbase_moved_multiple_times : Warning<
"defaulted move assignment operator of %0 will move assign virtual base "
@@ -7792,6 +7768,10 @@ def warn_format_argument_needs_cast : Warning<
"%select{values of type|enum values with underlying type}2 '%0' should not "
"be used as format arguments; add an explicit cast to %1 instead">,
InGroup<Format>;
+def warn_format_argument_needs_cast_pedantic : Warning<
+ "%select{values of type|enum values with underlying type}2 '%0' should not "
+ "be used as format arguments; add an explicit cast to %1 instead">,
+ InGroup<FormatPedantic>, DefaultIgnore;
def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">,
InGroup<Format>;
@@ -7874,10 +7854,17 @@ def warn_null_ret : Warning<
"null returned from %select{function|method}0 that requires a non-null return value">,
InGroup<NonNull>;
+def err_lifetimebound_no_object_param : Error<
+ "'lifetimebound' attribute cannot be applied; %select{static |non-}0member "
+ "function has no implicit object parameter">;
+def err_lifetimebound_ctor_dtor : Error<
+ "'lifetimebound' attribute cannot be applied to a "
+ "%select{constructor|destructor}0">;
+
// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr_ref : Warning<
- "%select{address of|reference to}0 stack memory associated with local "
- "variable %1 returned">,
+ "%select{address of|reference to}0 stack memory associated with "
+ "%select{local variable|parameter}2 %1 returned">,
InGroup<ReturnStackAddress>;
def warn_ret_local_temp_addr_ref : Warning<
"returning %select{address of|reference to}0 local temporary object">,
@@ -7887,30 +7874,71 @@ def warn_ret_addr_label : Warning<
InGroup<ReturnStackAddress>;
def err_ret_local_block : Error<
"returning block that lives on the local stack">;
-def note_ref_var_local_bind : Note<
- "binding reference variable %0 here">;
+def note_local_var_initializer : Note<
+ "%select{via initialization of|binding reference}0 variable "
+ "%select{%2 |}1here">;
+def note_init_with_default_member_initalizer : Note<
+ "initializing field %0 with default member initializer">;
// Check for initializing a member variable with the address or a reference to
// a constructor parameter.
def warn_bind_ref_member_to_parameter : Warning<
- "binding reference member %0 to stack allocated parameter %1">,
- InGroup<DanglingField>;
+ "binding reference member %0 to stack allocated "
+ "%select{variable|parameter}2 %1">, InGroup<DanglingField>;
def warn_init_ptr_member_to_parameter_addr : Warning<
- "initializing pointer member %0 with the stack address of parameter %1">,
- InGroup<DanglingField>;
-def warn_bind_ref_member_to_temporary : Warning<
- "binding reference %select{|subobject of }1member %0 to a temporary value">,
- InGroup<DanglingField>;
+ "initializing pointer member %0 with the stack address of "
+ "%select{variable|parameter}2 %1">, InGroup<DanglingField>;
def note_ref_or_ptr_member_declared_here : Note<
"%select{reference|pointer}0 member declared here">;
-def note_ref_subobject_of_member_declared_here : Note<
- "member with reference subobject declared here">;
+
+def err_dangling_member : Error<
+ "%select{reference|backing array for 'std::initializer_list'}2 "
+ "%select{|subobject of }1member %0 "
+ "%select{binds to|is}2 a temporary object "
+ "whose lifetime would be shorter than the lifetime of "
+ "the constructed object">;
+def warn_dangling_member : Warning<
+ "%select{reference|backing array for 'std::initializer_list'}2 "
+ "%select{|subobject of }1member %0 "
+ "%select{binds to|is}2 a temporary object "
+ "whose lifetime is shorter than the lifetime of the constructed object">,
+ InGroup<DanglingField>;
+def note_lifetime_extending_member_declared_here : Note<
+ "%select{%select{reference|'std::initializer_list'}0 member|"
+ "member with %select{reference|'std::initializer_list'}0 subobject}1 "
+ "declared here">;
+def warn_dangling_variable : Warning<
+ "%select{temporary %select{whose address is used as value of|"
+ "%select{|implicitly }2bound to}4 "
+ "%select{%select{|reference }4member of local variable|"
+ "local %select{variable|reference}4}1|"
+ "array backing "
+ "%select{initializer list subobject of local variable|"
+ "local initializer list}1}0 "
+ "%select{%3 |}2will be destroyed at the end of the full-expression">,
+ InGroup<Dangling>;
+def warn_new_dangling_reference : Warning<
+ "temporary bound to reference member of allocated object "
+ "will be destroyed at the end of the full-expression">,
+ InGroup<DanglingField>;
+def warn_new_dangling_initializer_list : Warning<
+ "array backing "
+ "%select{initializer list subobject of the allocated object|"
+ "the allocated initializer list}0 "
+ "will be destroyed at the end of the full-expression">,
+ InGroup<DanglingInitializerList>;
+def warn_unsupported_lifetime_extension : Warning<
+ "sorry, lifetime extension of "
+ "%select{temporary|backing array of initializer list}0 created "
+ "by aggregate initialization using default member initializer "
+ "is not supported; lifetime of %select{temporary|backing array}0 "
+ "will end at the end of the full-expression">, InGroup<Dangling>;
// For non-floating point, expressions of the form x == x or x != x
// should result in a warning, since these always evaluate to a constant.
// Array comparisons have similar warnings
def warn_comparison_always : Warning<
- "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
+ "%select{self-|array }0comparison always evaluates to %select{a constant|%2}1">,
InGroup<TautologicalCompare>;
def warn_comparison_bitwise_always : Warning<
"bitwise comparison always evaluates to %select{false|true}0">,
@@ -7966,7 +7994,7 @@ def err_generic_sel_multi_match : Error<
// Blocks
def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
- " or %select{pick a deployment target that supports them|for OpenCL 2.0 or above}0">;
+ " or %select{pick a deployment target that supports them|for OpenCL 2.0}0">;
def err_block_returning_array_function : Error<
"block cannot return %select{array|function}0 type %1">;
@@ -8203,9 +8231,12 @@ def err_vector_incorrect_num_initializers : Error<
def err_altivec_empty_initializer : Error<"expected initializer">;
def err_invalid_neon_type_code : Error<
- "incompatible constant for this __builtin_neon function">;
+ "incompatible constant for this __builtin_neon function">;
def err_argument_invalid_range : Error<
- "argument should be a value from %0 to %1">;
+ "argument value %0 is outside the valid range [%1, %2]">;
+def warn_argument_invalid_range : Warning<
+ "argument value %0 is outside the valid range [%1, %2]">, DefaultError,
+ InGroup<DiagGroup<"argument-outside-range">>;
def err_argument_not_multiple : Error<
"argument should be a multiple of %0">;
def warn_neon_vector_initializer_non_portable : Warning<
@@ -8222,6 +8253,8 @@ def err_systemz_invalid_tabort_code : Error<
"invalid transaction abort code">;
def err_64_bit_builtin_32_bit_tgt : Error<
"this builtin is only available on 64-bit targets">;
+def err_32_bit_builtin_64_bit_tgt : Error<
+ "this builtin is only available on 32-bit targets">;
def err_builtin_x64_aarch64_only : Error<
"this builtin is only available on x86-64 and aarch64 targets">;
def err_ppc_builtin_only_on_pwr7 : Error<
@@ -8230,7 +8263,15 @@ def err_x86_builtin_invalid_rounding : Error<
"invalid rounding argument">;
def err_x86_builtin_invalid_scale : Error<
"scale argument must be 1, 2, 4, or 8">;
-
+def err_hexagon_builtin_unsupported_cpu : Error<
+ "builtin is not supported on this CPU">;
+def err_hexagon_builtin_requires_hvx : Error<
+ "builtin requires HVX">;
+def err_hexagon_builtin_unsupported_hvx : Error<
+ "builtin is not supported on this version of HVX">;
+
+def err_builtin_target_unsupported : Error<
+ "builtin is not supported on this target">;
def err_builtin_longjmp_unsupported : Error<
"__builtin_longjmp is not supported for the current target">;
def err_builtin_setjmp_unsupported : Error<
@@ -8246,7 +8287,7 @@ def err_constant_integer_arg_type : Error<
def ext_mixed_decls_code : Extension<
"ISO C90 forbids mixing declarations and code">,
InGroup<DiagGroup<"declaration-after-statement">>;
-
+
def err_non_local_variable_decl_in_for : Error<
"declaration of non-local variable in 'for' loop">;
def err_non_variable_decl_in_for : Error<
@@ -8304,13 +8345,17 @@ 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 warn_nsconsumed_attribute_mismatch : Warning<
+def err_nsconsumed_attribute_mismatch : Error<
"overriding method has mismatched ns_consumed attribute on its"
- " parameter">, InGroup<NSConsumedMismatch>;
-def warn_nsreturns_retained_attribute_mismatch : Warning<
+ " parameter">;
+def err_nsreturns_retained_attribute_mismatch : Error<
"overriding method has mismatched ns_returns_%select{not_retained|retained}0"
- " attributes">, InGroup<NSReturnsMismatch>;
-
+ " attributes">;
+def warn_nsconsumed_attribute_mismatch : Warning<
+ err_nsconsumed_attribute_mismatch.Text>, InGroup<NSConsumedMismatch>;
+def warn_nsreturns_retained_attribute_mismatch : Warning<
+ err_nsreturns_retained_attribute_mismatch.Text>, InGroup<NSReturnsMismatch>;
+
def note_getter_unavailable : Note<
"or because setter is declared here, but no getter method %0 is found">;
def err_invalid_protocol_qualifiers : Error<
@@ -8505,7 +8550,7 @@ def err_reference_pipe_type : Error <
"pipes packet types cannot be of reference type">;
def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
def err_opencl_kernel_attr :
- Error<"attribute %0 can only be applied to a kernel function">;
+ Error<"attribute %0 can only be applied to an OpenCL kernel function">;
def err_opencl_return_value_with_address_space : Error<
"return value cannot be qualified with address space">;
def err_opencl_constant_no_init : Error<
@@ -8553,7 +8598,8 @@ def note_opencl_typedef_access_qualifier : Note<
// OpenCL Section 6.8.g
def err_opencl_unknown_type_specifier : Error<
- "OpenCL version %0 does not support the '%1' %select{type qualifier|storage class specifier}2">;
+ "OpenCL %select{C|C++}0 version %1 does not support the '%2' "
+ "%select{type qualifier|storage class specifier}3">;
// OpenCL v2.0 s6.12.5 Blocks restrictions
def err_opencl_block_storage_type : Error<
@@ -8565,7 +8611,7 @@ def err_opencl_extern_block_declaration : Error<
def err_opencl_block_ref_block : Error<
"cannot refer to a block inside block">;
-// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
+// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
def err_opencl_builtin_to_addr_arg_num : Error<
"invalid number of arguments to function: %0">;
def err_opencl_builtin_to_addr_invalid_arg : Error<
@@ -8643,8 +8689,8 @@ def err_omp_pointer_mapped_along_with_derived_section : Error<
"pointer cannot be mapped along with a section derived from itself">;
def err_omp_original_storage_is_shared_and_does_not_contain : Error<
"original storage of expression in data environment is shared but data environment do not fully contain mapped expression storage">;
-def err_omp_same_pointer_derreferenced : Error<
- "same pointer derreferenced in multiple different ways in map clause expressions">;
+def err_omp_same_pointer_dereferenced : Error<
+ "same pointer dereferenced in multiple different ways in map clause expressions">;
def note_omp_task_predetermined_firstprivate_here : Note<
"predetermined as a firstprivate in a task construct here">;
def err_omp_threadprivate_incomplete_type : Error<
@@ -8980,6 +9026,9 @@ 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">;
+def warn_omp_non_trivial_type_mapped : Warning<
+ "Non-trivial type %0 is mapped, only trivial types are guaranteed to be mapped correctly">,
+ InGroup<OpenMPTarget>;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -9080,9 +9129,9 @@ def note_equivalent_internal_linkage_decl : Note<
"declared here%select{ in module '%1'|}0">;
def note_redefinition_modules_same_file : Note<
- "'%0' included multiple times, additional include site in header from module '%1'">;
+ "'%0' included multiple times, additional include site in header from module '%1'">;
def note_redefinition_include_same_file : Note<
- "'%0' included multiple times, additional include site here">;
+ "'%0' included multiple times, additional include site here">;
}
let CategoryName = "Coroutines Issue" in {
@@ -9123,7 +9172,7 @@ def err_coroutine_promise_type_incomplete : Error<
"this function cannot be a coroutine: %0 is an incomplete type">;
def err_coroutine_type_missing_specialization : Error<
"this function cannot be a coroutine: missing definition of "
- "specialization %q0">;
+ "specialization %0">;
def err_coroutine_promise_incompatible_return_functions : Error<
"the coroutine promise type %0 declares both 'return_value' and 'return_void'">;
def err_coroutine_promise_requires_return_function : Error<
@@ -9328,8 +9377,67 @@ def ext_warn_gnu_final : ExtWarn<
InGroup<GccCompat>;
def warn_shadow_field :
- Warning<"non-static data member '%0' of '%1' shadows member inherited from type '%2'">,
+ Warning<"non-static data member %0 of %1 shadows member inherited from "
+ "type %2">,
InGroup<ShadowField>, DefaultIgnore;
def note_shadow_field : Note<"declared here">;
+def err_multiversion_required_in_redecl : Error<
+ "function declaration is missing %select{'target'|'cpu_specific' or "
+ "'cpu_dispatch'}0 attribute in a multiversioned function">;
+def note_multiversioning_caused_here : Note<
+ "function multiversioning caused by this declaration">;
+def err_multiversion_after_used : Error<
+ "function declaration cannot become a multiversioned function after first "
+ "usage">;
+def err_bad_multiversion_option : Error<
+ "function multiversioning doesn't support %select{feature|architecture}0 "
+ "'%1'">;
+def err_multiversion_duplicate : Error<
+ "multiversioned function redeclarations require identical target attributes">;
+def err_multiversion_noproto : Error<
+ "multiversioned function must have a prototype">;
+def err_multiversion_no_other_attrs : Error<
+ "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined"
+ " with other attributes">;
+def err_multiversion_diff : Error<
+ "multiversioned function declaration has a different %select{calling convention"
+ "|return type|constexpr specification|inline specification|storage class|"
+ "linkage}0">;
+def err_multiversion_doesnt_support : Error<
+ "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not "
+ "yet support %select{function templates|virtual functions|"
+ "deduced return types|constructors|destructors|deleted functions|"
+ "defaulted functions|constexpr functions}1">;
+def err_multiversion_not_allowed_on_main : Error<
+ "'main' cannot be a multiversioned function">;
+def err_multiversion_not_supported : Error<
+ "function multiversioning is not supported on the current target">;
+def err_multiversion_types_mixed : Error<
+ "multiversioning attributes cannot be combined">;
+def err_cpu_dispatch_mismatch : Error<
+ "'cpu_dispatch' function redeclared with different CPUs">;
+def err_cpu_specific_multiple_defs : Error<
+ "multiple 'cpu_specific' functions cannot specify the same CPU: %0">;
+def warn_multiversion_duplicate_entries : Warning<
+ "CPU list contains duplicate entries; attribute ignored">,
+ InGroup<FunctionMultiVersioning>;
+def warn_dispatch_body_ignored : Warning<
+ "body of cpu_dispatch function will be ignored">,
+ InGroup<FunctionMultiVersioning>;
+
+// three-way comparison operator diagnostics
+def err_implied_comparison_category_type_not_found : Error<
+ "cannot deduce return type of 'operator<=>' because type '%0' was not found; "
+ "include <compare>">;
+def err_spaceship_argument_narrowing : Error<
+ "argument to 'operator<=>' "
+ "%select{cannot be narrowed from type %1 to %2|"
+ "evaluates to %1, which cannot be narrowed to type %2}0">;
+def err_std_compare_type_not_supported : Error<
+ "standard library implementation of %0 is not supported; "
+ "%select{member '%2' does not have expected form|"
+ "member '%2' is missing|"
+ "the type is not trivially copyable|"
+ "the type does not have the expected form}1">;
} // end of sema component.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index 250b49f2cac4..54237d16f5c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -38,8 +38,8 @@ def err_pch_targetopt_mismatch : Error<
"PCH file was compiled for the %0 '%1' but the current translation "
"unit is being compiled for target '%2'">;
def err_pch_targetopt_feature_mismatch : Error<
- "%select{AST file|current translation unit}0 was compiled with the target "
- "feature'%1' but the %select{current translation unit is|AST file was}0 "
+ "%select{AST file was|current translation unit is}0 compiled with the target "
+ "feature '%1' but the %select{current translation unit is|AST file was}0 "
"not">;
def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "
"PCH file but is currently %select{disabled|enabled}2">;
@@ -49,7 +49,7 @@ def err_pch_diagopt_mismatch : Error<"%0 is currently enabled, but was not in "
"the PCH file">;
def err_pch_modulecache_mismatch : Error<"PCH was compiled with module cache "
"path '%0', but the path is currently '%1'">;
-
+
def err_pch_version_too_old : Error<
"PCH file uses an older PCH format that is no longer supported">;
def err_pch_version_too_new : Error<
@@ -168,11 +168,11 @@ def err_module_odr_violation_mismatch_decl : Error<
"%select{definition in module '%2'|defined here}1 found "
"%select{end of class|public access specifier|private access specifier|"
"protected access specifier|static assert|field|method|type alias|typedef|"
- "data member|friend declaration}3">;
+ "data member|friend declaration|function template}3">;
def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found "
"%select{end of class|public access specifier|private access specifier|"
"protected access specifier|static assert|field|method|type alias|typedef|"
- "data member|friend declaration}1">;
+ "data member|friend declaration|function template}1">;
def err_module_odr_violation_mismatch_decl_diff : Error<
"%q0 has different definitions in different modules; first difference is "
@@ -192,6 +192,8 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"%select{method %5|constructor|destructor}4 "
"is %select{not deleted|deleted}6|"
"%select{method %5|constructor|destructor}4 "
+ "is %select{not defaulted|defaulted}6|"
+ "%select{method %5|constructor|destructor}4 "
"is %select{|pure }6%select{not virtual|virtual}7|"
"%select{method %5|constructor|destructor}4 "
"is %select{not static|static}6|"
@@ -211,6 +213,16 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"with %ordinal6 parameter with%select{out|}7 a default argument|"
"%select{method %5|constructor|destructor}4 "
"with %ordinal6 parameter with a default argument|"
+ "%select{method %5|constructor|destructor}4 "
+ "with %select{no |}6template arguments|"
+ "%select{method %5|constructor|destructor}4 "
+ "with %6 template argument%s6|"
+ "%select{method %5|constructor|destructor}4 "
+ "with %6 for %ordinal7 template argument|"
+ "%select{method %5|constructor|destructor}4 "
+ "with %select{no body|body}6|"
+ "%select{method %5|constructor|destructor}4 "
+ "with body|"
"%select{typedef|type alias}4 name %5|"
"%select{typedef|type alias}4 %5 with underlying type %6|"
"data member with name %4|"
@@ -221,6 +233,18 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"friend %select{class|function}4|"
"friend %4|"
"friend function %4|"
+ "function template %4 with %5 template parameter%s5|"
+ "function template %4 with %ordinal5 template parameter being a "
+ "%select{type|non-type|template}6 template parameter|"
+ "function template %4 with %ordinal5 template parameter "
+ "%select{with no name|named %7}6|"
+ "function template %4 with %ordinal5 template parameter with "
+ "%select{no |}6default argument|"
+ "function template %4 with %ordinal5 template parameter with "
+ "default argument %6|"
+ "function template %4 with %ordinal5 template parameter with one type|"
+ "function template %4 with %ordinal5 template parameter %select{not |}6"
+ "being a template parameter pack|"
"}3">;
def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
@@ -239,6 +263,8 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"%select{method %3|constructor|destructor}2 "
"is %select{not deleted|deleted}4|"
"%select{method %3|constructor|destructor}2 "
+ "is %select{not defaulted|defaulted}4|"
+ "%select{method %3|constructor|destructor}2 "
"is %select{|pure }4%select{not virtual|virtual}5|"
"%select{method %3|constructor|destructor}2 "
"is %select{not static|static}4|"
@@ -258,6 +284,16 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"with %ordinal4 parameter with%select{out|}5 a default argument|"
"%select{method %3|constructor|destructor}2 "
"with %ordinal4 parameter with a different default argument|"
+ "%select{method %3|constructor|destructor}2 "
+ "with %select{no |}4template arguments|"
+ "%select{method %3|constructor|destructor}2 "
+ "with %4 template argument%s4|"
+ "%select{method %3|constructor|destructor}2 "
+ "with %4 for %ordinal5 template argument|"
+ "%select{method %3|constructor|destructor}2 "
+ "with %select{no body|body}4|"
+ "%select{method %3|constructor|destructor}2 "
+ "with different body|"
"%select{typedef|type alias}2 name %3|"
"%select{typedef|type alias}2 %3 with different underlying type %4|"
"data member with name %2|"
@@ -268,6 +304,18 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"friend %select{class|function}2|"
"friend %2|"
"friend function %2|"
+ "function template %2 with %3 template parameter%s3|"
+ "function template %2 with %ordinal3 template paramter being a "
+ "%select{type|non-type|template}4 template parameter|"
+ "function template %2 with %ordinal3 template parameter "
+ "%select{with no name|named %5}4|"
+ "function template %2 with %ordinal3 template parameter with "
+ "%select{no |}4default argument|"
+ "function template %2 with %ordinal3 template parameter with "
+ "default argument %4|"
+ "function template %2 with %ordinal3 template parameter with different type|"
+ "function template %2 with %ordinal3 template parameter %select{not |}4"
+ "being a template parameter pack|"
"}1">;
def err_module_odr_violation_function : Error<
@@ -293,6 +341,33 @@ def note_module_odr_violation_function : Note<"but in '%0' found "
"a different body"
"}1">;
+def err_module_odr_violation_enum : Error<
+ "%q0 has different definitions in different modules; "
+ "%select{definition in module '%2'|defined here}1 "
+ "first difference is "
+ "%select{"
+ "enum that is %select{not scoped|scoped}4|"
+ "enum scoped with keyword %select{struct|class}4|"
+ "enum %select{without|with}4 specified type|"
+ "enum with specified type %4|"
+ "enum with %4 element%s4|"
+ "%ordinal4 element has name %5|"
+ "%ordinal4 element %5 %select{has|does not have}6 an initilizer|"
+ "%ordinal4 element %5 has an initializer|"
+ "}3">;
+
+def note_module_odr_violation_enum : Note<"but in '%0' found "
+ "%select{"
+ "enum that is %select{not scoped|scoped}2|"
+ "enum scoped with keyword %select{struct|class}2|"
+ "enum %select{without|with}2 specified type|"
+ "enum with specified type %2|"
+ "enum with %2 element%s2|"
+ "%ordinal2 element has name %3|"
+ "%ordinal2 element %3 %select{has|does not have}4 an initializer|"
+ "%ordinal2 element %3 has different initializer|"
+ "}1">;
+
def err_module_odr_violation_mismatch_decl_unknown : Error<
"%q0 %select{with definition in module '%2'|defined here}1 has different "
"definitions in different modules; first difference is this "
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h b/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h
index 132b5ba1e5a7..0c2c8e6d860a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the ExceptionSpecificationType enumeration and various
+/// Defines the ExceptionSpecificationType enumeration and various
/// utility functions.
///
//===----------------------------------------------------------------------===//
@@ -17,14 +17,16 @@
namespace clang {
-/// \brief The various types of exception specifications that exist in C++11.
+/// The various types of exception specifications that exist in C++11.
enum ExceptionSpecificationType {
EST_None, ///< no exception specification
EST_DynamicNone, ///< throw()
EST_Dynamic, ///< throw(T1, T2)
EST_MSAny, ///< Microsoft throw(...) extension
EST_BasicNoexcept, ///< noexcept
- EST_ComputedNoexcept, ///< noexcept(expression)
+ EST_DependentNoexcept,///< noexcept(expression), value-dependent
+ EST_NoexceptFalse, ///< noexcept(expression), evals to 'false'
+ EST_NoexceptTrue, ///< noexcept(expression), evals to 'true'
EST_Unevaluated, ///< not evaluated yet, for special member function
EST_Uninstantiated, ///< not instantiated yet
EST_Unparsed ///< not parsed yet
@@ -34,15 +36,20 @@ inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {
return ESpecType >= EST_DynamicNone && ESpecType <= EST_MSAny;
}
+inline bool isComputedNoexcept(ExceptionSpecificationType ESpecType) {
+ return ESpecType >= EST_DependentNoexcept &&
+ ESpecType <= EST_NoexceptTrue;
+}
+
inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) {
- return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept;
+ return ESpecType == EST_BasicNoexcept || isComputedNoexcept(ESpecType);
}
inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType) {
return ESpecType == EST_Unevaluated || ESpecType == EST_Uninstantiated;
}
-/// \brief Possible results from evaluation of a noexcept expression.
+/// Possible results from evaluation of a noexcept expression.
enum CanThrowResult {
CT_Cannot,
CT_Dependent,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h
index 0363a1d2c74c..2983adde1ed6 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines enumerations for expression traits intrinsics.
+/// Defines enumerations for expression traits intrinsics.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Features.def b/contrib/llvm/tools/clang/include/clang/Basic/Features.def
new file mode 100644
index 000000000000..a0e0ce4560ab
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Features.def
@@ -0,0 +1,238 @@
+//===--- Features.def - Features and Extensions 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 features exposed via __has_feature and extensions exposed
+// via __has_extension. Users of this file must either define the FEATURE or
+// EXTENSION macros (or both) to make use of this information. Note that these
+// macros expect the following declarations to be available for the Predicate:
+//
+// const LangOptions &LangOpts;
+// const Preprocessor &PP;
+//
+// The Predicate field dictates the conditions under which the feature or
+// extension will be made available.
+//===----------------------------------------------------------------------===//
+
+#if !defined(FEATURE) && !defined(EXTENSION)
+# error Define either the FEATURE or EXTENSION macro to handle features
+#endif
+
+#ifndef FEATURE
+#define FEATURE(Name, Predicate)
+#endif
+
+#ifndef EXTENSION
+#define EXTENSION(Name, Predicate)
+#endif
+
+FEATURE(address_sanitizer,
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
+FEATURE(hwaddress_sanitizer,
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress))
+FEATURE(assume_nonnull, true)
+FEATURE(attribute_analyzer_noreturn, true)
+FEATURE(attribute_availability, true)
+FEATURE(attribute_availability_with_message, true)
+FEATURE(attribute_availability_app_extension, true)
+FEATURE(attribute_availability_with_version_underscores, true)
+FEATURE(attribute_availability_tvos, true)
+FEATURE(attribute_availability_watchos, true)
+FEATURE(attribute_availability_with_strict, true)
+FEATURE(attribute_availability_with_replacement, true)
+FEATURE(attribute_availability_in_templates, true)
+FEATURE(attribute_cf_returns_not_retained, true)
+FEATURE(attribute_cf_returns_retained, true)
+FEATURE(attribute_cf_returns_on_parameters, true)
+FEATURE(attribute_deprecated_with_message, true)
+FEATURE(attribute_deprecated_with_replacement, true)
+FEATURE(attribute_ext_vector_type, true)
+FEATURE(attribute_ns_returns_not_retained, true)
+FEATURE(attribute_ns_returns_retained, true)
+FEATURE(attribute_ns_consumes_self, true)
+FEATURE(attribute_ns_consumed, true)
+FEATURE(attribute_cf_consumed, true)
+FEATURE(attribute_objc_ivar_unused, true)
+FEATURE(attribute_objc_method_family, true)
+FEATURE(attribute_overloadable, true)
+FEATURE(attribute_unavailable_with_message, true)
+FEATURE(attribute_unused_on_fields, true)
+FEATURE(attribute_diagnose_if_objc, true)
+FEATURE(blocks, LangOpts.Blocks)
+FEATURE(c_thread_safety_attributes, true)
+FEATURE(cxx_exceptions, LangOpts.CXXExceptions)
+FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData)
+FEATURE(enumerator_attributes, true)
+FEATURE(nullability, true)
+FEATURE(nullability_on_arrays, true)
+FEATURE(memory_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Memory))
+FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
+FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
+FEATURE(efficiency_sanitizer,
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
+FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
+// Objective-C features
+FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
+FEATURE(objc_arc, LangOpts.ObjCAutoRefCount)
+FEATURE(objc_arc_fields, true)
+FEATURE(objc_arc_weak, LangOpts.ObjCWeak)
+FEATURE(objc_default_synthesize_properties, LangOpts.ObjC2)
+FEATURE(objc_fixed_enum, LangOpts.ObjC2)
+FEATURE(objc_instancetype, LangOpts.ObjC2)
+FEATURE(objc_kindof, LangOpts.ObjC2)
+FEATURE(objc_modules, LangOpts.ObjC2 &&LangOpts.Modules)
+FEATURE(objc_nonfragile_abi, LangOpts.ObjCRuntime.isNonFragile())
+FEATURE(objc_property_explicit_atomic, true)
+FEATURE(objc_protocol_qualifier_mangling, true)
+FEATURE(objc_weak_class, LangOpts.ObjCRuntime.hasWeakClassImport())
+FEATURE(ownership_holds, true)
+FEATURE(ownership_returns, true)
+FEATURE(ownership_takes, true)
+FEATURE(objc_bool, true)
+FEATURE(objc_subscripting, LangOpts.ObjCRuntime.isNonFragile())
+FEATURE(objc_array_literals, LangOpts.ObjC2)
+FEATURE(objc_dictionary_literals, LangOpts.ObjC2)
+FEATURE(objc_boxed_expressions, LangOpts.ObjC2)
+FEATURE(objc_boxed_nsvalue_expressions, LangOpts.ObjC2)
+FEATURE(arc_cf_code_audited, true)
+FEATURE(objc_bridge_id, true)
+FEATURE(objc_bridge_id_on_typedefs, true)
+FEATURE(objc_generics, LangOpts.ObjC2)
+FEATURE(objc_generics_variance, LangOpts.ObjC2)
+FEATURE(objc_class_property, LangOpts.ObjC2)
+// C11 features
+FEATURE(c_alignas, LangOpts.C11)
+FEATURE(c_alignof, LangOpts.C11)
+FEATURE(c_atomic, LangOpts.C11)
+FEATURE(c_generic_selections, LangOpts.C11)
+FEATURE(c_static_assert, LangOpts.C11)
+FEATURE(c_thread_local, LangOpts.C11 &&PP.getTargetInfo().isTLSSupported())
+// C++11 features
+FEATURE(cxx_access_control_sfinae, LangOpts.CPlusPlus11)
+FEATURE(cxx_alias_templates, LangOpts.CPlusPlus11)
+FEATURE(cxx_alignas, LangOpts.CPlusPlus11)
+FEATURE(cxx_alignof, LangOpts.CPlusPlus11)
+FEATURE(cxx_atomic, LangOpts.CPlusPlus11)
+FEATURE(cxx_attributes, LangOpts.CPlusPlus11)
+FEATURE(cxx_auto_type, LangOpts.CPlusPlus11)
+FEATURE(cxx_constexpr, LangOpts.CPlusPlus11)
+FEATURE(cxx_constexpr_string_builtins, LangOpts.CPlusPlus11)
+FEATURE(cxx_decltype, LangOpts.CPlusPlus11)
+FEATURE(cxx_decltype_incomplete_return_types, LangOpts.CPlusPlus11)
+FEATURE(cxx_default_function_template_args, LangOpts.CPlusPlus11)
+FEATURE(cxx_defaulted_functions, LangOpts.CPlusPlus11)
+FEATURE(cxx_delegating_constructors, LangOpts.CPlusPlus11)
+FEATURE(cxx_deleted_functions, LangOpts.CPlusPlus11)
+FEATURE(cxx_explicit_conversions, LangOpts.CPlusPlus11)
+FEATURE(cxx_generalized_initializers, LangOpts.CPlusPlus11)
+FEATURE(cxx_implicit_moves, LangOpts.CPlusPlus11)
+FEATURE(cxx_inheriting_constructors, LangOpts.CPlusPlus11)
+FEATURE(cxx_inline_namespaces, LangOpts.CPlusPlus11)
+FEATURE(cxx_lambdas, LangOpts.CPlusPlus11)
+FEATURE(cxx_local_type_template_args, LangOpts.CPlusPlus11)
+FEATURE(cxx_nonstatic_member_init, LangOpts.CPlusPlus11)
+FEATURE(cxx_noexcept, LangOpts.CPlusPlus11)
+FEATURE(cxx_nullptr, LangOpts.CPlusPlus11)
+FEATURE(cxx_override_control, LangOpts.CPlusPlus11)
+FEATURE(cxx_range_for, LangOpts.CPlusPlus11)
+FEATURE(cxx_raw_string_literals, LangOpts.CPlusPlus11)
+FEATURE(cxx_reference_qualified_functions, LangOpts.CPlusPlus11)
+FEATURE(cxx_rvalue_references, LangOpts.CPlusPlus11)
+FEATURE(cxx_strong_enums, LangOpts.CPlusPlus11)
+FEATURE(cxx_static_assert, LangOpts.CPlusPlus11)
+FEATURE(cxx_thread_local,
+ LangOpts.CPlusPlus11 &&PP.getTargetInfo().isTLSSupported())
+FEATURE(cxx_trailing_return, LangOpts.CPlusPlus11)
+FEATURE(cxx_unicode_literals, LangOpts.CPlusPlus11)
+FEATURE(cxx_unrestricted_unions, LangOpts.CPlusPlus11)
+FEATURE(cxx_user_literals, LangOpts.CPlusPlus11)
+FEATURE(cxx_variadic_templates, LangOpts.CPlusPlus11)
+// C++14 features
+FEATURE(cxx_aggregate_nsdmi, LangOpts.CPlusPlus14)
+FEATURE(cxx_binary_literals, LangOpts.CPlusPlus14)
+FEATURE(cxx_contextual_conversions, LangOpts.CPlusPlus14)
+FEATURE(cxx_decltype_auto, LangOpts.CPlusPlus14)
+FEATURE(cxx_generic_lambdas, LangOpts.CPlusPlus14)
+FEATURE(cxx_init_captures, LangOpts.CPlusPlus14)
+FEATURE(cxx_relaxed_constexpr, LangOpts.CPlusPlus14)
+FEATURE(cxx_return_type_deduction, LangOpts.CPlusPlus14)
+FEATURE(cxx_variable_templates, LangOpts.CPlusPlus14)
+// NOTE: For features covered by SD-6, it is preferable to provide *only*
+// the SD-6 macro and not a __has_feature check.
+
+// C++ TSes
+// FEATURE(cxx_runtime_arrays, LangOpts.CPlusPlusTSArrays)
+// FEATURE(cxx_concepts, LangOpts.CPlusPlusTSConcepts)
+// FIXME: Should this be __has_feature or __has_extension?
+// FEATURE(raw_invocation_type, LangOpts.CPlusPlus)
+// Type traits
+// N.B. Additional type traits should not be added to the following list.
+// Instead, they should be detected by has_extension.
+FEATURE(has_nothrow_assign, LangOpts.CPlusPlus)
+FEATURE(has_nothrow_copy, LangOpts.CPlusPlus)
+FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus)
+FEATURE(has_trivial_assign, LangOpts.CPlusPlus)
+FEATURE(has_trivial_copy, LangOpts.CPlusPlus)
+FEATURE(has_trivial_constructor, LangOpts.CPlusPlus)
+FEATURE(has_trivial_destructor, LangOpts.CPlusPlus)
+FEATURE(has_virtual_destructor, LangOpts.CPlusPlus)
+FEATURE(is_abstract, LangOpts.CPlusPlus)
+FEATURE(is_base_of, LangOpts.CPlusPlus)
+FEATURE(is_class, LangOpts.CPlusPlus)
+FEATURE(is_constructible, LangOpts.CPlusPlus)
+FEATURE(is_convertible_to, LangOpts.CPlusPlus)
+FEATURE(is_empty, LangOpts.CPlusPlus)
+FEATURE(is_enum, LangOpts.CPlusPlus)
+FEATURE(is_final, LangOpts.CPlusPlus)
+FEATURE(is_literal, LangOpts.CPlusPlus)
+FEATURE(is_standard_layout, LangOpts.CPlusPlus)
+FEATURE(is_pod, LangOpts.CPlusPlus)
+FEATURE(is_polymorphic, LangOpts.CPlusPlus)
+FEATURE(is_sealed, LangOpts.CPlusPlus &&LangOpts.MicrosoftExt)
+FEATURE(is_trivial, LangOpts.CPlusPlus)
+FEATURE(is_trivially_assignable, LangOpts.CPlusPlus)
+FEATURE(is_trivially_constructible, LangOpts.CPlusPlus)
+FEATURE(is_trivially_copyable, LangOpts.CPlusPlus)
+FEATURE(is_union, LangOpts.CPlusPlus)
+FEATURE(modules, LangOpts.Modules)
+FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack))
+FEATURE(shadow_call_stack,
+ LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
+FEATURE(tls, PP.getTargetInfo().isTLSSupported())
+FEATURE(underlying_type, LangOpts.CPlusPlus)
+
+// C11 features supported by other languages as extensions.
+EXTENSION(c_alignas, true)
+EXTENSION(c_alignof, true)
+EXTENSION(c_atomic, true)
+EXTENSION(c_generic_selections, true)
+EXTENSION(c_static_assert, true)
+EXTENSION(c_thread_local, PP.getTargetInfo().isTLSSupported())
+// C++11 features supported by other languages as extensions.
+EXTENSION(cxx_atomic, LangOpts.CPlusPlus)
+EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus)
+EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus)
+EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus)
+EXTENSION(cxx_local_type_template_args, LangOpts.CPlusPlus)
+EXTENSION(cxx_nonstatic_member_init, LangOpts.CPlusPlus)
+EXTENSION(cxx_override_control, LangOpts.CPlusPlus)
+EXTENSION(cxx_range_for, LangOpts.CPlusPlus)
+EXTENSION(cxx_reference_qualified_functions, LangOpts.CPlusPlus)
+EXTENSION(cxx_rvalue_references, LangOpts.CPlusPlus)
+EXTENSION(cxx_variadic_templates, LangOpts.CPlusPlus)
+// C++14 features supported by other languages as extensions.
+EXTENSION(cxx_binary_literals, true)
+EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11)
+EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus)
+// Miscellaneous language extensions
+EXTENSION(overloadable_unmarked, true)
+
+#undef EXTENSION
+#undef FEATURE
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
index b817dd20c301..ab5dfca71639 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::FileManager interface and associated types.
+/// Defines the clang::FileManager interface and associated types.
///
//===----------------------------------------------------------------------===//
@@ -40,7 +40,7 @@ namespace clang {
class FileSystemStatCache;
-/// \brief Cached information about one directory (either on disk or in
+/// Cached information about one directory (either on disk or in
/// the virtual file system).
class DirectoryEntry {
friend class FileManager;
@@ -51,7 +51,7 @@ public:
StringRef getName() const { return Name; }
};
-/// \brief Cached information about one file (either on disk
+/// Cached information about one file (either on disk
/// or in the virtual file system).
///
/// If the 'File' member is valid, then this FileEntry has an open file
@@ -70,7 +70,7 @@ class FileEntry {
bool InPCH;
bool IsValid; // Is this \c FileEntry initialized and valid?
- /// \brief The open file, if it is owned by the \p FileEntry.
+ /// The open file, if it is owned by the \p FileEntry.
mutable std::unique_ptr<vfs::File> File;
public:
@@ -90,12 +90,12 @@ public:
bool isInPCH() const { return InPCH; }
time_t getModificationTime() const { return ModTime; }
- /// \brief Return the directory the file lives in.
+ /// Return the directory the file lives in.
const DirectoryEntry *getDir() const { return Dir; }
bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
- /// \brief Check whether the file is a named pipe (and thus can't be opened by
+ /// Check whether the file is a named pipe (and thus can't be opened by
/// the native FileManager methods).
bool isNamedPipe() const { return IsNamedPipe; }
@@ -106,7 +106,7 @@ public:
struct FileData;
-/// \brief Implements support for file system lookup, file system caching,
+/// Implements support for file system lookup, file system caching,
/// and directory search management.
///
/// This also handles more advanced properties, such as uniquing files based
@@ -117,21 +117,21 @@ class FileManager : public RefCountedBase<FileManager> {
IntrusiveRefCntPtr<vfs::FileSystem> FS;
FileSystemOptions FileSystemOpts;
- /// \brief Cache for existing real directories.
+ /// Cache for existing real directories.
std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
- /// \brief Cache for existing real files.
+ /// Cache for existing real files.
std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
- /// \brief The virtual directories that we have allocated.
+ /// The virtual directories that we have allocated.
///
/// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
/// directories (foo/ and foo/bar/) here.
SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
- /// \brief The virtual files that we have allocated.
+ /// The virtual files that we have allocated.
SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
- /// \brief A cache that maps paths to directory entries (either real or
+ /// A cache that maps paths to directory entries (either real or
/// virtual) we have looked up
///
/// The actual Entries for real directories/files are
@@ -141,19 +141,19 @@ class FileManager : public RefCountedBase<FileManager> {
///
llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
- /// \brief A cache that maps paths to file entries (either real or
+ /// A cache that maps paths to file entries (either real or
/// virtual) we have looked up.
///
/// \see SeenDirEntries
llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
- /// \brief The canonical names of directories.
+ /// The canonical names of directories.
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
- /// \brief Storage for canonical names that we have computed.
+ /// Storage for canonical names that we have computed.
llvm::BumpPtrAllocator CanonicalNameStorage;
- /// \brief Each FileEntry we create is assigned a unique ID #.
+ /// Each FileEntry we create is assigned a unique ID #.
///
unsigned NextFileUID;
@@ -176,7 +176,7 @@ public:
IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr);
~FileManager();
- /// \brief Installs the provided FileSystemStatCache object within
+ /// Installs the provided FileSystemStatCache object within
/// the FileManager.
///
/// Ownership of this object is transferred to the FileManager.
@@ -190,13 +190,13 @@ public:
void addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
bool AtBeginning = false);
- /// \brief Removes the specified FileSystemStatCache object from the manager.
+ /// Removes the specified FileSystemStatCache object from the manager.
void removeStatCache(FileSystemStatCache *statCache);
- /// \brief Removes all FileSystemStatCache objects from the manager.
+ /// Removes all FileSystemStatCache objects from the manager.
void clearStatCaches();
- /// \brief Lookup, cache, and verify the specified directory (real or
+ /// Lookup, cache, and verify the specified directory (real or
/// virtual).
///
/// This returns NULL if the directory doesn't exist.
@@ -206,7 +206,7 @@ public:
const DirectoryEntry *getDirectory(StringRef DirName,
bool CacheFailure = true);
- /// \brief Lookup, cache, and verify the specified file (real or
+ /// Lookup, cache, and verify the specified file (real or
/// virtual).
///
/// This returns NULL if the file doesn't exist.
@@ -218,7 +218,7 @@ public:
const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
bool CacheFailure = true);
- /// \brief Returns the current file system options
+ /// Returns the current file system options
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
@@ -226,22 +226,22 @@ public:
return FS;
}
- /// \brief Retrieve a file entry for a "virtual" file that acts as
+ /// Retrieve a file entry for a "virtual" file that acts as
/// if there were a file with the given name on disk.
///
/// The file itself is not accessed.
const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
time_t ModificationTime);
- /// \brief Open the specified file as a MemoryBuffer, returning a new
+ /// Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
bool ShouldCloseOpenFile = true);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBufferForFile(StringRef Filename);
+ getBufferForFile(StringRef Filename, bool isVolatile = false);
- /// \brief Get the 'stat' information for the given \p Path.
+ /// Get the 'stat' information for the given \p Path.
///
/// If the path is relative, it will be resolved against the WorkingDir of the
/// FileManager's FileSystemOptions.
@@ -250,10 +250,10 @@ public:
bool getNoncachedStatValue(StringRef Path,
vfs::Status &Result);
- /// \brief Remove the real file \p Entry from the cache.
+ /// Remove the real file \p Entry from the cache.
void invalidateCache(const FileEntry *Entry);
- /// \brief If path is not absolute and FileSystemOptions set the working
+ /// If path is not absolute and FileSystemOptions set the working
/// directory, the path is modified to be relative to the given
/// working directory.
/// \returns true if \c path changed.
@@ -264,17 +264,17 @@ public:
/// \returns true if \c Path changed to absolute.
bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
- /// \brief Produce an array mapping from the unique IDs assigned to each
+ /// Produce an array mapping from the unique IDs assigned to each
/// file to the corresponding FileEntry pointer.
void GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
- /// \brief Modifies the size and modification time of a previously created
+ /// Modifies the size and modification time of a previously created
/// FileEntry. Use with caution.
static void modifyFileEntry(FileEntry *File, off_t Size,
time_t ModificationTime);
- /// \brief Retrieve the canonical name for a given directory.
+ /// Retrieve the canonical name for a given directory.
///
/// This is a very expensive operation, despite its results being cached,
/// and should only be used when the physical layout of the file system is
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h
index 38f134631248..8b8b13bb5686 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::FileSystemOptions interface.
+/// Defines the clang::FileSystemOptions interface.
///
//===----------------------------------------------------------------------===//
@@ -19,10 +19,10 @@
namespace clang {
-/// \brief Keeps track of options that affect how file operations are performed.
+/// Keeps track of options that affect how file operations are performed.
class FileSystemOptions {
public:
- /// \brief If set, paths are resolved as if the working directory was
+ /// If set, paths are resolved as if the working directory was
/// set to the value of WorkingDir.
std::string WorkingDir;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h
index 75f986b59bdd..1ec344623a0d 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h
@@ -1,4 +1,4 @@
-//===--- FileSystemStatCache.h - Caching for 'stat' calls -------*- C++ -*-===//
+//===- FileSystemStatCache.h - Caching for 'stat' calls ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the FileSystemStatCache interface.
-///
+/// Defines the FileSystemStatCache interface.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
@@ -17,48 +17,61 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/FileSystem.h"
+#include <cstdint>
+#include <ctime>
#include <memory>
+#include <string>
+#include <utility>
namespace clang {
namespace vfs {
+
class File;
class FileSystem;
-}
+
+} // namespace vfs
// FIXME: should probably replace this with vfs::Status
struct FileData {
std::string Name;
- uint64_t Size;
- time_t ModTime;
+ uint64_t Size = 0;
+ time_t ModTime = 0;
llvm::sys::fs::UniqueID UniqueID;
- bool IsDirectory;
- bool IsNamedPipe;
- bool InPCH;
- bool IsVFSMapped; // FIXME: remove this when files support multiple names
- FileData()
- : Size(0), ModTime(0), IsDirectory(false), IsNamedPipe(false),
- InPCH(false), IsVFSMapped(false) {}
+ bool IsDirectory = false;
+ bool IsNamedPipe = false;
+ bool InPCH = false;
+
+ // FIXME: remove this when files support multiple names
+ bool IsVFSMapped = false;
+
+ FileData() = default;
};
-/// \brief Abstract interface for introducing a FileManager cache for 'stat'
+/// Abstract interface for introducing a FileManager cache for 'stat'
/// system calls, which is used by precompiled and pretokenized headers to
/// improve performance.
class FileSystemStatCache {
virtual void anchor();
+
protected:
std::unique_ptr<FileSystemStatCache> NextStatCache;
public:
- virtual ~FileSystemStatCache() {}
-
+ virtual ~FileSystemStatCache() = default;
+
enum LookupResult {
- CacheExists, ///< We know the file exists and its cached stat data.
- CacheMissing ///< We know that the file doesn't exist.
+ /// We know the file exists and its cached stat data.
+ CacheExists,
+
+ /// We know that the file doesn't exist.
+ CacheMissing
};
- /// \brief Get the 'stat' information for the specified path, using the cache
+ /// Get the 'stat' information for the specified path, using the cache
/// to accelerate it if possible.
///
/// \returns \c true if the path does not exist or \c false if it exists.
@@ -72,16 +85,16 @@ public:
std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache,
vfs::FileSystem &FS);
- /// \brief Sets the next stat call cache in the chain of stat caches.
+ /// Sets the next stat call cache in the chain of stat caches.
/// Takes ownership of the given stat cache.
void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) {
NextStatCache = std::move(Cache);
}
-
- /// \brief Retrieve the next stat call cache in the chain.
+
+ /// Retrieve the next stat call cache in the chain.
FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); }
-
- /// \brief Retrieve the next stat call cache in the chain, transferring
+
+ /// Retrieve the next stat call cache in the chain, transferring
/// ownership of this cache (and, transitively, all of the remaining caches)
/// to the caller.
std::unique_ptr<FileSystemStatCache> takeNextStatCache() {
@@ -107,16 +120,16 @@ protected:
}
};
-/// \brief A stat "cache" that can be used by FileManager to keep
+/// A stat "cache" that can be used by FileManager to keep
/// track of the results of stat() calls that occur throughout the
/// execution of the front end.
class MemorizeStatCalls : public FileSystemStatCache {
public:
- /// \brief The set of stat() calls that have been seen.
+ /// The set of stat() calls that have been seen.
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
- typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
- iterator;
+ using iterator =
+ llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator;
iterator begin() const { return StatCalls.begin(); }
iterator end() const { return StatCalls.end(); }
@@ -126,6 +139,6 @@ public:
vfs::FileSystem &FS) override;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
index 8e3c15afbfcd..c2e9c71b0f0d 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and
+/// Defines the clang::IdentifierInfo, clang::IdentifierTable, and
/// clang::Selector interfaces.
//
//===----------------------------------------------------------------------===//
@@ -39,7 +39,7 @@ class LangOptions;
class MultiKeywordSelector;
class SourceLocation;
-/// \brief A simple pair of identifier info and location.
+/// A simple pair of identifier info and location.
using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
/// One of these records is kept for each identifier that
@@ -63,7 +63,7 @@ class IdentifierInfo {
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
- bool IsFromAST : 1; // True if identifier was loaded (at least
+ bool IsFromAST : 1; // True if identifier was loaded (at least
// partially) from an AST file.
bool ChangedAfterLoad : 1; // True if identifier has changed from the
// definition loaded from an AST file.
@@ -89,7 +89,7 @@ public:
IdentifierInfo(const IdentifierInfo &) = delete;
IdentifierInfo &operator=(const IdentifierInfo &) = delete;
- /// \brief Return true if this is the identifier for the specified string.
+ /// Return true if this is the identifier for the specified string.
///
/// This is intended to be used for string literals only: II->isStr("foo").
template <std::size_t StrLen>
@@ -98,7 +98,13 @@ public:
memcmp(getNameStart(), Str, StrLen-1) == 0;
}
- /// \brief Return the beginning of the actual null-terminated string for this
+ /// Return true if this is the identifier for the specified StringRef.
+ bool isStr(llvm::StringRef Str) const {
+ llvm::StringRef ThisStr(getNameStart(), getLength());
+ return ThisStr == Str;
+ }
+
+ /// Return the beginning of the actual null-terminated string for this
/// identifier.
const char *getNameStart() const {
if (Entry) return Entry->getKeyData();
@@ -112,7 +118,7 @@ public:
return ((const actualtype*) this)->second;
}
- /// \brief Efficiently return the length of this identifier info.
+ /// 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
@@ -126,12 +132,12 @@ public:
return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1;
}
- /// \brief Return the actual identifier string.
+ /// Return the actual identifier string.
StringRef getName() const {
return StringRef(getNameStart(), getLength());
}
- /// \brief Return true if this identifier is \#defined to some other value.
+ /// Return true if this identifier is \#defined to some other value.
/// \note The current definition may be in a module and not currently visible.
bool hasMacroDefinition() const {
return HasMacro;
@@ -147,7 +153,7 @@ public:
RecomputeNeedsHandleIdentifier();
}
}
- /// \brief Returns true if this identifier was \#defined to some value at any
+ /// Returns true if this identifier was \#defined to some value at any
/// moment. In this case there should be an entry for the identifier in the
/// macro history table in Preprocessor.
bool hadMacroDefinition() const {
@@ -159,10 +165,10 @@ public:
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
- /// \brief True if revertTokenIDToIdentifier() was called.
+ /// True if revertTokenIDToIdentifier() was called.
bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
- /// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
+ /// Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
/// compatibility.
///
/// TokenID is normally read-only but there are 2 instances where we revert it
@@ -179,12 +185,12 @@ public:
RevertedTokenID = false;
}
- /// \brief Return the preprocessor keyword ID for this identifier.
+ /// Return the preprocessor keyword ID for this identifier.
///
/// For example, "define" will return tok::pp_define.
tok::PPKeywordKind getPPKeywordID() const;
- /// \brief Return the Objective-C keyword ID for the this identifier.
+ /// Return the Objective-C keyword ID for the this identifier.
///
/// For example, 'class' will return tok::objc_class if ObjC is enabled.
tok::ObjCKeywordKind getObjCKeywordID() const {
@@ -195,19 +201,19 @@ public:
}
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
- /// \brief True if setNotBuiltin() was called.
+ /// True if setNotBuiltin() was called.
bool hasRevertedBuiltin() const {
return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
}
- /// \brief Revert the identifier to a non-builtin identifier. We do this if
+ /// Revert the identifier to a non-builtin identifier. We do this if
/// the name of a known builtin library function is used to declare that
/// function, but an unexpected type is specified.
void revertBuiltin() {
setBuiltinID(0);
}
- /// \brief Return a value indicating whether this is a builtin function.
+ /// Return a value indicating whether this is a builtin function.
///
/// 0 is not-built-in. 1+ are specific builtin functions.
unsigned getBuiltinID() const {
@@ -261,7 +267,7 @@ public:
RecomputeNeedsHandleIdentifier();
}
- /// \brief Return true if this token has been poisoned.
+ /// Return true if this token has been poisoned.
bool isPoisoned() const { return IsPoisoned; }
/// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
@@ -271,10 +277,10 @@ public:
}
bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
- /// \brief Return true if this token is a keyword in the specified language.
+ /// Return true if this token is a keyword in the specified language.
bool isKeyword(const LangOptions &LangOpts) const;
- /// \brief Return true if this token is a C++ keyword in the specified
+ /// Return true if this token is a C++ keyword in the specified
/// language.
bool isCPlusPlusKeyword(const LangOptions &LangOpts) const;
@@ -284,48 +290,48 @@ public:
T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
void setFETokenInfo(void *T) { FETokenInfo = T; }
- /// \brief Return true if the Preprocessor::HandleIdentifier must be called
+ /// Return true if the Preprocessor::HandleIdentifier must be called
/// on a token of this identifier.
///
/// If this returns false, we know that HandleIdentifier will not affect
/// the token.
bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
- /// \brief Return true if the identifier in its current state was loaded
+ /// Return true if the identifier in its current state was loaded
/// from an AST file.
bool isFromAST() const { return IsFromAST; }
void setIsFromAST() { IsFromAST = true; }
- /// \brief Determine whether this identifier has changed since it was loaded
+ /// Determine whether this identifier has changed since it was loaded
/// from an AST file.
bool hasChangedSinceDeserialization() const {
return ChangedAfterLoad;
}
-
- /// \brief Note that this identifier has changed since it was loaded from
+
+ /// Note that this identifier has changed since it was loaded from
/// an AST file.
void setChangedSinceDeserialization() {
ChangedAfterLoad = true;
}
- /// \brief Determine whether the frontend token information for this
+ /// Determine whether the frontend token information for this
/// identifier has changed since it was loaded from an AST file.
bool hasFETokenInfoChangedSinceDeserialization() const {
return FEChangedAfterLoad;
}
-
- /// \brief Note that the frontend token information for this identifier has
+
+ /// Note that the frontend token information for this identifier has
/// changed since it was loaded from an AST file.
void setFETokenInfoChangedSinceDeserialization() {
FEChangedAfterLoad = true;
}
- /// \brief Determine whether the information for this identifier is out of
+ /// Determine whether the information for this identifier is out of
/// date with respect to the external source.
bool isOutOfDate() const { return OutOfDate; }
-
- /// \brief Set whether the information for this identifier is out of
+
+ /// Set whether the information for this identifier is out of
/// date with respect to the external source.
void setOutOfDate(bool OOD) {
OutOfDate = OOD;
@@ -334,11 +340,11 @@ public:
else
RecomputeNeedsHandleIdentifier();
}
-
- /// \brief Determine whether this is the contextual keyword \c import.
+
+ /// Determine whether this is the contextual keyword \c import.
bool isModulesImport() const { return IsModulesImport; }
-
- /// \brief Set whether this identifier is the contextual keyword \c import.
+
+ /// Set whether this identifier is the contextual keyword \c import.
void setModulesImport(bool I) {
IsModulesImport = I;
if (I)
@@ -360,7 +366,7 @@ public:
return getName().startswith("<#") && getName().endswith("#>");
}
- /// \brief Provide less than operator for lexicographical sorting.
+ /// Provide less than operator for lexicographical sorting.
bool operator<(const IdentifierInfo &RHS) const {
return getName() < RHS.getName();
}
@@ -379,7 +385,7 @@ private:
}
};
-/// \brief An RAII object for [un]poisoning an identifier within a scope.
+/// An RAII object for [un]poisoning an identifier within a scope.
///
/// \p II is allowed to be null, in which case objects of this type have
/// no effect.
@@ -400,7 +406,7 @@ public:
}
};
-/// \brief An iterator that walks over all of the known identifiers
+/// An iterator that walks over all of the known identifiers
/// in the lookup table.
///
/// Since this iterator uses an abstract interface via virtual
@@ -413,14 +419,14 @@ public:
class IdentifierIterator {
protected:
IdentifierIterator() = default;
-
+
public:
IdentifierIterator(const IdentifierIterator &) = delete;
IdentifierIterator &operator=(const IdentifierIterator &) = delete;
virtual ~IdentifierIterator();
- /// \brief Retrieve the next string in the identifier table and
+ /// Retrieve the next string in the identifier table and
/// advances the iterator for the following string.
///
/// \returns The next string in the identifier table. If there is
@@ -428,19 +434,19 @@ public:
virtual StringRef Next() = 0;
};
-/// \brief Provides lookups to, and iteration over, IdentiferInfo objects.
+/// Provides lookups to, and iteration over, IdentiferInfo objects.
class IdentifierInfoLookup {
public:
virtual ~IdentifierInfoLookup();
- /// \brief Return the IdentifierInfo for the specified named identifier.
+ /// Return the IdentifierInfo for the specified named identifier.
///
/// Unlike the version in IdentifierTable, this returns a pointer instead
/// of a reference. If the pointer is null then the IdentifierInfo cannot
/// be found.
virtual IdentifierInfo* get(StringRef Name) = 0;
- /// \brief Retrieve an iterator into the set of all identifiers
+ /// Retrieve an iterator into the set of all identifiers
/// known to this identifier lookup source.
///
/// This routine provides access to all of the identifiers known to
@@ -453,7 +459,7 @@ public:
virtual IdentifierIterator *getIdentifiers();
};
-/// \brief Implements an efficient mapping from strings to IdentifierInfo nodes.
+/// Implements an efficient mapping from strings to IdentifierInfo nodes.
///
/// This has no other purpose, but this is an extremely performance-critical
/// piece of the code, as each occurrence of every identifier goes through
@@ -467,26 +473,29 @@ class IdentifierTable {
IdentifierInfoLookup* ExternalLookup;
public:
- /// \brief Create the identifier table, populating it with info about the
+ /// Create the identifier table.
+ explicit IdentifierTable(IdentifierInfoLookup *ExternalLookup = nullptr);
+
+ /// Create the identifier table, populating it with info about the
/// language keywords for the language specified by \p LangOpts.
- IdentifierTable(const LangOptions &LangOpts,
- IdentifierInfoLookup* externalLookup = nullptr);
+ explicit IdentifierTable(const LangOptions &LangOpts,
+ IdentifierInfoLookup *ExternalLookup = nullptr);
- /// \brief Set the external identifier lookup mechanism.
+ /// Set the external identifier lookup mechanism.
void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) {
ExternalLookup = IILookup;
}
- /// \brief Retrieve the external identifier lookup object, if any.
+ /// Retrieve the external identifier lookup object, if any.
IdentifierInfoLookup *getExternalIdentifierLookup() const {
return ExternalLookup;
}
-
+
llvm::BumpPtrAllocator& getAllocator() {
return HashTable.getAllocator();
}
- /// \brief Return the identifier token info for the specified named
+ /// Return the identifier token info for the specified named
/// identifier.
IdentifierInfo &get(StringRef Name) {
auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first;
@@ -519,7 +528,7 @@ public:
return II;
}
- /// \brief Gets an IdentifierInfo for the given name without consulting
+ /// Gets an IdentifierInfo for the given name without consulting
/// external sources.
///
/// This is a version of get() meant for external sources that want to
@@ -554,14 +563,16 @@ public:
iterator end() const { return HashTable.end(); }
unsigned size() const { return HashTable.size(); }
- /// \brief Print some statistics to stderr that indicate how well the
+ /// Print some statistics to stderr that indicate how well the
/// hashing is doing.
void PrintStats() const;
+ /// Populate the identifier table with info about the language keywords
+ /// for the language specified by \p LangOpts.
void AddKeywords(const LangOptions &LangOpts);
};
-/// \brief A family of Objective-C methods.
+/// A family of Objective-C methods.
///
/// These families have no inherent meaning in the language, but are
/// nonetheless central enough in the existing implementations to
@@ -579,7 +590,7 @@ public:
/// explicitly change or remove a method's family. Therefore the
/// method's family should be considered the single source of truth.
enum ObjCMethodFamily {
- /// \brief No particular method family.
+ /// No particular method family.
OMF_None,
// Selectors in these families may have arbitrary arity, may be
@@ -611,10 +622,10 @@ enum ObjCMethodFamily {
/// InvalidObjCMethodFamily.
enum { ObjCMethodFamilyBitWidth = 4 };
-/// \brief An invalid value of ObjCMethodFamily.
+/// An invalid value of ObjCMethodFamily.
enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 };
-/// \brief A family of Objective-C methods.
+/// A family of Objective-C methods.
///
/// These are family of methods whose result type is initially 'id', but
/// but are candidate for the result type to be changed to 'instancetype'.
@@ -633,7 +644,7 @@ enum ObjCStringFormatFamily {
SFF_CFString
};
-/// \brief Smart pointer class that efficiently represents Objective-C method
+/// Smart pointer class that efficiently represents Objective-C method
/// names.
///
/// This class will either point to an IdentifierInfo or a
@@ -676,13 +687,13 @@ class Selector {
MultiKeywordSelector *getMultiKeywordSelector() const {
return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags);
}
-
+
unsigned getIdentifierInfoFlag() const {
return InfoPtr & ArgFlags;
}
static ObjCMethodFamily getMethodFamilyImpl(Selector sel);
-
+
static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel);
public:
@@ -706,7 +717,7 @@ public:
return reinterpret_cast<void*>(InfoPtr);
}
- /// \brief Determine whether this is the empty selector.
+ /// Determine whether this is the empty selector.
bool isNull() const { return InfoPtr == 0; }
// Predicates to identify the selector type.
@@ -719,11 +730,11 @@ public:
}
unsigned getNumArgs() const;
-
- /// \brief Retrieve the identifier at a given position in the selector.
+
+ /// Retrieve the identifier at a given position in the selector.
///
/// Note that the identifier pointer returned may be NULL. Clients that only
- /// care about the text of the identifier string, and not the specific,
+ /// care about the text of the identifier string, and not the specific,
/// uniqued identifier pointer, should use \c getNameForSlot(), which returns
/// an empty string when the identifier pointer would be NULL.
///
@@ -734,8 +745,8 @@ public:
/// \returns the uniqued identifier for this slot, or NULL if this slot has
/// no corresponding identifier.
IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
-
- /// \brief Retrieve the name at a given position in the selector.
+
+ /// Retrieve the name at a given position in the selector.
///
/// \param argIndex The index for which we want to retrieve the name.
/// This index shall be less than \c getNumArgs() unless this is a keyword
@@ -744,23 +755,25 @@ public:
/// \returns the name for this slot, which may be the empty string if no
/// name was supplied.
StringRef getNameForSlot(unsigned argIndex) const;
-
- /// \brief Derive the full selector name (e.g. "foo:bar:") and return
+
+ /// Derive the full selector name (e.g. "foo:bar:") and return
/// it as an std::string.
std::string getAsString() const;
- /// \brief Prints the full selector name (e.g. "foo:bar:").
+ /// Prints the full selector name (e.g. "foo:bar:").
void print(llvm::raw_ostream &OS) const;
- /// \brief Derive the conventional family of this method.
+ void dump() const;
+
+ /// Derive the conventional family of this method.
ObjCMethodFamily getMethodFamily() const {
return getMethodFamilyImpl(*this);
}
-
+
ObjCStringFormatFamily getStringFormatFamily() const {
return getStringFormatFamilyImpl(*this);
}
-
+
static Selector getEmptyMarker() {
return Selector(uintptr_t(-1));
}
@@ -768,11 +781,11 @@ public:
static Selector getTombstoneMarker() {
return Selector(uintptr_t(-2));
}
-
+
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel);
};
-/// \brief This table allows us to fully hide how we implement
+/// This table allows us to fully hide how we implement
/// multi-keyword caching.
class SelectorTable {
// Actually a SelectorTableImpl
@@ -784,7 +797,7 @@ public:
SelectorTable &operator=(const SelectorTable &) = delete;
~SelectorTable();
- /// \brief Can create any sort of selector.
+ /// Can create any sort of selector.
///
/// \p NumArgs indicates whether this is a no argument selector "foo", a
/// single argument selector "foo:" or multi-argument "foo:bar:".
@@ -798,22 +811,25 @@ public:
return Selector(ID, 0);
}
- /// \brief Return the total amount of memory allocated for managing selectors.
+ /// Return the total amount of memory allocated for managing selectors.
size_t getTotalMemory() const;
- /// \brief Return the default setter name for the given identifier.
+ /// Return the default setter name for the given identifier.
///
/// This is "set" + \p Name where the initial character of \p Name
/// has been capitalized.
static SmallString<64> constructSetterName(StringRef Name);
- /// \brief Return the default setter selector for the given identifier.
+ /// Return the default setter selector for the given identifier.
///
/// This is "set" + \p Name where the initial character of \p Name
/// has been capitalized.
static Selector constructSetterSelector(IdentifierTable &Idents,
SelectorTable &SelTable,
const IdentifierInfo *Name);
+
+ /// Return the property name for the given setter selector.
+ static std::string getPropertyNameFromSetterSelector(Selector Sel);
};
/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
@@ -885,7 +901,7 @@ struct PointerLikeTypeTraits<clang::Selector> {
return clang::Selector(reinterpret_cast<uintptr_t>(P));
}
- enum { NumLowBitsAvailable = 0 };
+ enum { NumLowBitsAvailable = 0 };
};
// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
index e60284d1b445..3f833c62c0a8 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Forward-declares and imports various common LLVM datatypes that
+/// Forward-declares and imports various common LLVM datatypes that
/// clang wants to use unqualified.
///
//===----------------------------------------------------------------------===//
@@ -28,6 +28,7 @@ namespace llvm {
// ADT's.
class StringRef;
class Twine;
+ class VersionTuple;
template<typename T> class ArrayRef;
template<typename T> class MutableArrayRef;
template<typename T> class OwningArrayRef;
@@ -58,19 +59,20 @@ namespace clang {
using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
using llvm::cast_or_null;
-
+
// ADT's.
- using llvm::None;
- using llvm::Optional;
- using llvm::StringRef;
- using llvm::Twine;
using llvm::ArrayRef;
using llvm::MutableArrayRef;
+ using llvm::None;
+ using llvm::Optional;
using llvm::OwningArrayRef;
+ using llvm::SaveAndRestore;
using llvm::SmallString;
using llvm::SmallVector;
using llvm::SmallVectorImpl;
- using llvm::SaveAndRestore;
+ using llvm::StringRef;
+ using llvm::Twine;
+ using llvm::VersionTuple;
// Error handling.
using llvm::Expected;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h b/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h
index 1c19f1dcc8b1..675854e67e7a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines several types used to describe C++ lambda expressions
+/// Defines several types used to describe C++ lambda expressions
/// that are shared between the parser and AST.
///
//===----------------------------------------------------------------------===//
@@ -19,14 +19,14 @@
namespace clang {
-/// \brief The default, if any, capture method for a lambda expression.
+/// The default, if any, capture method for a lambda expression.
enum LambdaCaptureDefault {
LCD_None,
LCD_ByCopy,
LCD_ByRef
};
-/// \brief The different capture forms in a lambda introducer
+/// The different capture forms in a lambda introducer
///
/// C++11 allows capture of \c this, or of local variables by copy or
/// by reference. C++1y also allows "init-capture", where the initializer
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
index c6ed256dd6e4..fc38af5b03f6 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
@@ -106,6 +106,7 @@ LANGOPT(LineComment , 1, 0, "'//' comments")
LANGOPT(Bool , 1, 0, "bool, true, and false keywords")
LANGOPT(Half , 1, 0, "half keyword")
LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword")
+LANGOPT(Char8 , 1, 0, "char8_t keyword")
LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword")
BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
@@ -153,6 +154,7 @@ COMPATIBLE_LANGOPT(ModulesTS , 1, 0, "C++ Modules TS")
BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None,
"compiling a module interface")
BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch")
+BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a corresponding object file")
COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses")
BENIGN_LANGOPT(ModulesSearchAll , 1, 1, "searching even non-imported modules to find unresolved references")
COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules")
@@ -188,22 +190,27 @@ ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default
LANGOPT(ShortEnums , 1, 0, "short enum types")
LANGOPT(OpenCL , 1, 0, "OpenCL")
-LANGOPT(OpenCLVersion , 32, 0, "OpenCL version")
+LANGOPT(OpenCLVersion , 32, 0, "OpenCL C version")
+LANGOPT(OpenCLCPlusPlus , 1, 0, "OpenCL C++")
+LANGOPT(OpenCLCPlusPlusVersion , 32, 0, "OpenCL C++ version")
LANGOPT(NativeHalfType , 1, 0, "Native half type support")
LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns")
LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
LANGOPT(CUDA , 1, 0, "CUDA")
+LANGOPT(HIP , 1, 0, "HIP")
LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 or 45)")
LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.")
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
+LANGOPT(OpenMPCUDAMode , 1, 0, "Generate code for OpenMP pragmas in SIMT/SPMD mode")
+LANGOPT(OpenMPHostCXXExceptions , 1, 0, "C++ exceptions handling in the host code.")
LANGOPT(RenderScript , 1, 0, "RenderScript")
LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device")
LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code")
LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__")
-LANGOPT(CUDADeviceFlushDenormalsToZero, 1, 0, "flushing denormals to zero")
LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions")
+LANGOPT(CUDARelocatableDeviceCode, 1, 0, "generate relocatable device code")
LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
@@ -226,7 +233,7 @@ BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and su
BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking")
LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants")
LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
-/// \brief FP_CONTRACT mode (on/off/fast).
+/// FP_CONTRACT mode (on/off/fast).
ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type")
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
@@ -234,11 +241,16 @@ LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime")
LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files")
LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
+LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")
BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing")
LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
+LANGOPT(
+ CompleteMemberPointers, 1, 0,
+ "Require member pointer base types to be complete at the point where the "
+ "type's inheritance model would be determined under the Microsoft ABI")
ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode")
ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility,
@@ -277,10 +289,25 @@ 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.")
+LANGOPT(XRayAlwaysEmitTypedEvents, 1, 0,
+ "controls whether to always emit intrinsic calls to "
+ "__xray_typedevent(...) builtin.")
+
+LANGOPT(ForceEmitVTables, 1, 0, "whether to emit all vtables")
BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0,
"allow editor placeholders in source")
+ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest,
+ "version of Clang that we should attempt to be ABI-compatible "
+ "with")
+
+COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions")
+
+LANGOPT(FixedPoint, 1, 0, "fixed point types")
+LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0,
+ "unsigned fixed point types having one extra padding bit")
+
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
@@ -290,4 +317,3 @@ BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0,
#undef VALUE_LANGOPT
#undef COMPATIBLE_VALUE_LANGOPT
#undef BENIGN_VALUE_LANGOPT
-
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
index f7a43adefad0..a1396f84352f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -1,4 +1,4 @@
-//===--- LangOptions.h - C Language Family Language Options -----*- C++ -*-===//
+//===- LangOptions.h - C Language Family Language Options -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the clang::LangOptions interface.
-///
+/// Defines the clang::LangOptions interface.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H
@@ -20,6 +20,8 @@
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/Visibility.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include <string>
#include <vector>
@@ -43,26 +45,36 @@ protected:
#include "clang/Basic/LangOptions.def"
};
-/// \brief Keeps track of the various options that can be
+/// Keeps track of the various options that can be
/// enabled, which controls the dialect of C or C++ that is accepted.
class LangOptions : public LangOptionsBase {
public:
- typedef clang::Visibility Visibility;
-
+ using Visibility = clang::Visibility;
+
enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
-
+
enum SignedOverflowBehaviorTy {
- SOB_Undefined, // Default C standard behavior.
- SOB_Defined, // -fwrapv
- SOB_Trapping // -ftrapv
+ // Default C standard behavior.
+ SOB_Undefined,
+
+ // -fwrapv
+ SOB_Defined,
+
+ // -ftrapv
+ SOB_Trapping
};
// FIXME: Unify with TUKind.
enum CompilingModuleKind {
- CMK_None, ///< Not compiling a module interface at all.
- CMK_ModuleMap, ///< Compiling a module from a module map.
- CMK_ModuleInterface ///< Compiling a C++ modules TS module interface unit.
+ /// Not compiling a module interface at all.
+ CMK_None,
+
+ /// Compiling a module from a module map.
+ CMK_ModuleMap,
+
+ /// Compiling a C++ modules TS module interface unit.
+ CMK_ModuleInterface
};
enum PragmaMSPointersToMembersKind {
@@ -90,77 +102,117 @@ public:
MSVC2015 = 19
};
+ /// Clang versions with different platform ABI conformance.
+ enum class ClangABI {
+ /// Attempt to be ABI-compatible with code generated by Clang 3.8.x
+ /// (SVN r257626). This causes <1 x long long> to be passed in an
+ /// integer register instead of an SSE register on x64_64.
+ Ver3_8,
+
+ /// Attempt to be ABI-compatible with code generated by Clang 4.0.x
+ /// (SVN r291814). This causes move operations to be ignored when
+ /// determining whether a class type can be passed or returned directly.
+ Ver4,
+
+ /// Attempt to be ABI-compatible with code generated by Clang 6.0.x
+ /// (SVN r321711). This causes determination of whether a type is
+ /// standard-layout to ignore collisions between empty base classes
+ /// and between base classes and member subobjects, which affects
+ /// whether we reuse base class tail padding in some ABIs.
+ Ver6,
+
+ /// Conform to the underlying platform's C and C++ ABIs as closely
+ /// as we can.
+ Latest
+ };
+
enum FPContractModeKind {
- FPC_Off, // Form fused FP ops only where result will not be affected.
- FPC_On, // Form fused FP ops according to FP_CONTRACT rules.
- FPC_Fast // Aggressively fuse FP ops (E.g. FMA).
+ // Form fused FP ops only where result will not be affected.
+ FPC_Off,
+
+ // Form fused FP ops according to FP_CONTRACT rules.
+ FPC_On,
+
+ // Aggressively fuse FP ops (E.g. FMA).
+ FPC_Fast
};
public:
- /// \brief Set of enabled sanitizers.
+ /// Set of enabled sanitizers.
SanitizerSet Sanitize;
- /// \brief Paths to blacklist files specifying which objects
+ /// Paths to blacklist files specifying which objects
/// (files, functions, variables) should not be instrumented.
std::vector<std::string> SanitizerBlacklistFiles;
- /// \brief Paths to the XRay "always instrument" files specifying which
+ /// Paths to the XRay "always instrument" files specifying which
/// objects (files, functions, variables) should be imbued with the XRay
/// "always instrument" attribute.
+ /// WARNING: This is a deprecated field and will go away in the future.
std::vector<std::string> XRayAlwaysInstrumentFiles;
- /// \brief Paths to the XRay "never instrument" files specifying which
+ /// Paths to the XRay "never instrument" files specifying which
/// objects (files, functions, variables) should be imbued with the XRay
/// "never instrument" attribute.
+ /// WARNING: This is a deprecated field and will go away in the future.
std::vector<std::string> XRayNeverInstrumentFiles;
+ /// Paths to the XRay attribute list files, specifying which objects
+ /// (files, functions, variables) should be imbued with the appropriate XRay
+ /// attribute(s).
+ std::vector<std::string> XRayAttrListFiles;
+
clang::ObjCRuntime ObjCRuntime;
std::string ObjCConstantStringClass;
-
- /// \brief The name of the handler function to be called when -ftrapv is
+
+ /// The name of the handler function to be called when -ftrapv is
/// specified.
///
/// If none is specified, abort (GCC-compatible behaviour).
std::string OverflowHandler;
- /// \brief The name of the current module, of which the main source file
+ /// The module currently being compiled as speficied by -fmodule-name.
+ std::string ModuleName;
+
+ /// The name of the current module, of which the main source file
/// is a part. If CompilingModule is set, we are compiling the interface
/// of this module, otherwise we are compiling an implementation file of
- /// it.
+ /// it. This starts as ModuleName in case -fmodule-name is provided and
+ /// changes during compilation to reflect the current module.
std::string CurrentModule;
- /// \brief The names of any features to enable in module 'requires' decls
+ /// The names of any features to enable in module 'requires' decls
/// in addition to the hard-coded list in Module.cpp and the target features.
///
/// This list is sorted.
std::vector<std::string> ModuleFeatures;
- /// \brief Options for parsing comments.
+ /// Options for parsing comments.
CommentOptions CommentOpts;
- /// \brief A list of all -fno-builtin-* function names (e.g., memset).
+ /// A list of all -fno-builtin-* function names (e.g., memset).
std::vector<std::string> NoBuiltinFuncs;
- /// \brief Triples of the OpenMP targets that the host code codegen should
+ /// Triples of the OpenMP targets that the host code codegen should
/// take into account in order to generate accurate offloading descriptors.
std::vector<llvm::Triple> OMPTargetTriples;
- /// \brief Name of the IR file that contains the result of the OpenMP target
+ /// Name of the IR file that contains the result of the OpenMP target
/// host code generation.
std::string OMPHostIRFile;
- /// \brief Indicates whether the front-end is explicitly told that the
+ /// Indicates whether the front-end is explicitly told that the
/// input is a header file (i.e. -x c-header).
- bool IsHeaderFile;
+ bool IsHeaderFile = false;
LangOptions();
// Define accessors/mutators for language options of enumeration type.
-#define LANGOPT(Name, Bits, Default, Description)
+#define LANGOPT(Name, Bits, Default, Description)
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Type get##Name() const { return static_cast<Type>(Name); } \
- void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
+ void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
#include "clang/Basic/LangOptions.def"
/// Are we compiling a module interface (.cppm or module map)?
@@ -176,7 +228,7 @@ public:
bool isSignedOverflowDefined() const {
return getSignedOverflowBehavior() == SOB_Defined;
}
-
+
bool isSubscriptPointerArithmetic() const {
return ObjCRuntime.isSubscriptPointerArithmetic() &&
!ObjCSubscriptingLegacyRuntime;
@@ -186,15 +238,15 @@ public:
return MSCompatibilityVersion >= MajorVersion * 10000000U;
}
- /// \brief Reset all of the options that are not considered when building a
+ /// Reset all of the options that are not considered when building a
/// module.
void resetNonModularOptions();
- /// \brief Is this a libc/libm function that is no longer recognized as a
+ /// Is this a libc/libm function that is no longer recognized as a
/// builtin because a -fno-builtin-* option has been specified?
bool isNoBuiltinFunc(StringRef Name) const;
- /// \brief True if any ObjC types may have non-trivial lifetime qualifiers.
+ /// True if any ObjC types may have non-trivial lifetime qualifiers.
bool allowsNonTrivialObjCLifetimeQualifiers() const {
return ObjCAutoRefCount || ObjCWeak;
}
@@ -202,9 +254,12 @@ public:
bool assumeFunctionsAreConvergent() const {
return (CUDA && CUDAIsDevice) || OpenCL;
}
+
+ /// Return the OpenCL C or C++ version as a VersionTuple.
+ VersionTuple getOpenCLVersionTuple() const;
};
-/// \brief Floating point control options
+/// Floating point control options
class FPOptions {
public:
FPOptions() : fp_contract(LangOptions::FPC_Off) {}
@@ -219,15 +274,19 @@ public:
bool allowFPContractWithinStatement() const {
return fp_contract == LangOptions::FPC_On;
}
+
bool allowFPContractAcrossStatement() const {
return fp_contract == LangOptions::FPC_Fast;
}
+
void setAllowFPContractWithinStatement() {
fp_contract = LangOptions::FPC_On;
}
+
void setAllowFPContractAcrossStatement() {
fp_contract = LangOptions::FPC_Fast;
}
+
void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; }
/// Used to serialize this.
@@ -238,17 +297,19 @@ private:
unsigned fp_contract : 2;
};
-/// \brief Describes the kind of translation unit being processed.
+/// Describes the kind of translation unit being processed.
enum TranslationUnitKind {
- /// \brief The translation unit is a complete translation unit.
+ /// The translation unit is a complete translation unit.
TU_Complete,
- /// \brief The translation unit is a prefix to a translation unit, and is
+
+ /// The translation unit is a prefix to a translation unit, and is
/// not complete.
TU_Prefix,
- /// \brief The translation unit is a module.
+
+ /// The translation unit is a module.
TU_Module
};
-
-} // end namespace clang
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_LANGOPTIONS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h
index 6ec8763f2491..529cfa9f3f8d 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h
@@ -1,4 +1,4 @@
-//===--- Linkage.h - Linkage enumeration and utilities ----------*- C++ -*-===//
+//===- Linkage.h - Linkage enumeration and utilities ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,33 +6,32 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the Linkage enumeration and various utility functions.
-///
+/// Defines the Linkage enumeration and various utility functions.
+//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
#define LLVM_CLANG_BASIC_LINKAGE_H
-#include <assert.h>
-#include <stdint.h>
#include <utility>
namespace clang {
-/// \brief Describes the different kinds of linkage
+/// Describes the different kinds of linkage
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
enum Linkage : unsigned char {
- /// \brief No linkage, which means that the entity is unique and
+ /// No linkage, which means that the entity is unique and
/// can only be referred to from within its scope.
NoLinkage = 0,
- /// \brief Internal linkage, which indicates that the entity can
+ /// Internal linkage, which indicates that the entity can
/// be referred to from within the translation unit (but not other
/// translation units).
InternalLinkage,
- /// \brief External linkage within a unique namespace.
+ /// External linkage within a unique namespace.
///
/// From the language perspective, these entities have external
/// linkage. However, since they reside in an anonymous namespace,
@@ -41,27 +40,27 @@ enum Linkage : unsigned char {
/// point of view.
UniqueExternalLinkage,
- /// \brief No linkage according to the standard, but is visible from other
+ /// No linkage according to the standard, but is visible from other
/// translation units because of types defined in a inline function.
VisibleNoLinkage,
- /// \brief Internal linkage according to the Modules TS, but can be referred
+ /// Internal linkage according to the Modules TS, but can be referred
/// to from other translation units indirectly through inline functions and
/// templates in the module interface.
ModuleInternalLinkage,
- /// \brief Module linkage, which indicates that the entity can be referred
+ /// Module linkage, which indicates that the entity can be referred
/// to from other translation units within the same module, and indirectly
/// from arbitrary other translation units through inline functions and
/// templates in the module interface.
ModuleLinkage,
- /// \brief External linkage, which indicates that the entity can
+ /// External linkage, which indicates that the entity can
/// be referred to from other translation units.
ExternalLinkage
};
-/// \brief Describes the different kinds of language linkage
+/// Describes the different kinds of language linkage
/// (C++ [dcl.link]) that an entity may have.
enum LanguageLinkage {
CLanguageLinkage,
@@ -69,7 +68,7 @@ enum LanguageLinkage {
NoLanguageLinkage
};
-/// \brief A more specific kind of linkage than enum Linkage.
+/// A more specific kind of linkage than enum Linkage.
///
/// This is relevant to CodeGen and AST file reading.
enum GVALinkage {
@@ -105,7 +104,7 @@ inline bool isExternalFormalLinkage(Linkage L) {
return getFormalLinkage(L) == ExternalLinkage;
}
-/// \brief Compute the minimum linkage given two linkages.
+/// Compute the minimum linkage given two linkages.
///
/// The linkage can be interpreted as a pair formed by the formal linkage and
/// a boolean for external visibility. This is just what getFormalLinkage and
@@ -125,6 +124,6 @@ inline Linkage minLinkage(Linkage L1, Linkage L2) {
return L1 < L2 ? L1 : L2;
}
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_BASIC_LINKAGE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h
index 9a9eaa24983c..b2edc972fee2 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::MacroBuilder utility class.
+/// Defines the clang::MacroBuilder utility class.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
index 6631721e3531..02a4ef610b64 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Module.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::Module class, which describes a module in the
+/// Defines the clang::Module class, which describes a module in the
/// source code.
//
//===----------------------------------------------------------------------===//
@@ -44,11 +44,11 @@ class raw_ostream;
} // namespace llvm
namespace clang {
-
+
class LangOptions;
class TargetInfo;
-/// \brief Describes the name of a module.
+/// Describes the name of a module.
using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
/// The signature of a module, which is a hash of the AST content.
@@ -61,76 +61,76 @@ struct ASTFileSignature : std::array<uint32_t, 5> {
}
};
-/// \brief Describes a module or submodule.
+/// Describes a module or submodule.
class Module {
public:
- /// \brief The name of this module.
+ /// The name of this module.
std::string Name;
-
- /// \brief The location of the module definition.
+
+ /// The location of the module definition.
SourceLocation DefinitionLoc;
enum ModuleKind {
- /// \brief This is a module that was defined by a module map and built out
+ /// This is a module that was defined by a module map and built out
/// of header files.
ModuleMapModule,
- /// \brief This is a C++ Modules TS module interface unit.
+ /// This is a C++ Modules TS module interface unit.
ModuleInterfaceUnit,
- /// \brief This is a fragment of the global module within some C++ Modules
+ /// This is a fragment of the global module within some C++ Modules
/// TS module.
GlobalModuleFragment,
};
- /// \brief The kind of this module.
+ /// The kind of this module.
ModuleKind Kind = ModuleMapModule;
- /// \brief The parent of this module. This will be NULL for the top-level
+ /// The parent of this module. This will be NULL for the top-level
/// module.
Module *Parent;
- /// \brief The build directory of this module. This is the directory in
+ /// 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 = nullptr;
- /// \brief The presumed file name for the module map defining this module.
+ /// The presumed file name for the module map defining this module.
/// Only non-empty when building from preprocessed source.
std::string PresumedModuleMapFile;
- /// \brief The umbrella header or directory.
+ /// The umbrella header or directory.
llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
- /// \brief The module signature.
+ /// The module signature.
ASTFileSignature Signature;
- /// \brief The name of the umbrella entry, as written in the module map.
+ /// 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
+ /// 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.
+ /// The submodules of this module, indexed by name.
std::vector<Module *> SubModules;
-
- /// \brief A mapping from the submodule name to the index into the
+
+ /// A mapping from the submodule name to the index into the
/// \c SubModules vector at which that submodule resides.
llvm::StringMap<unsigned> SubModuleIndex;
- /// \brief The AST file if this is a top-level module which has a
+ /// The AST file if this is a top-level module which has a
/// corresponding serialized AST file, or null otherwise.
const FileEntry *ASTFile = nullptr;
- /// \brief The top-level headers associated with this module.
+ /// The top-level headers associated with this module.
llvm::SmallSetVector<const FileEntry *, 2> TopHeaders;
- /// \brief top-level header filenames that aren't resolved to FileEntries yet.
+ /// top-level header filenames that aren't resolved to FileEntries yet.
std::vector<std::string> TopHeaderNames;
- /// \brief Cache of modules visible to lookup in this module.
+ /// Cache of modules visible to lookup in this module.
mutable llvm::DenseSet<const Module*> VisibleModulesCache;
/// The ID used when referencing this module within a VisibleModuleSet.
@@ -146,7 +146,7 @@ public:
};
static const int NumHeaderKinds = HK_Excluded + 1;
- /// \brief Information about a header directive as found in the module map
+ /// Information about a header directive as found in the module map
/// file.
struct Header {
std::string NameAsWritten;
@@ -155,7 +155,7 @@ public:
explicit operator bool() { return Entry; }
};
- /// \brief Information about a directory name as found in the module map
+ /// Information about a directory name as found in the module map
/// file.
struct DirectoryName {
std::string NameAsWritten;
@@ -164,10 +164,10 @@ public:
explicit operator bool() { return Entry; }
};
- /// \brief The headers that are part of this module.
+ /// The headers that are part of this module.
SmallVector<Header, 2> Headers[5];
- /// \brief Stored information about a header directive that was found in the
+ /// Stored information about a header directive that was found in the
/// module map file but has not been resolved to a file.
struct UnresolvedHeaderDirective {
HeaderKind Kind = HK_Normal;
@@ -183,191 +183,202 @@ public:
/// yet attempted to resolve to a file on the file system.
SmallVector<UnresolvedHeaderDirective, 1> UnresolvedHeaders;
- /// \brief Headers that are mentioned in the module map file but could not be
+ /// Headers that are mentioned in the module map file but could not be
/// found on the file system.
SmallVector<UnresolvedHeaderDirective, 1> MissingHeaders;
- /// \brief An individual requirement: a feature name and a flag indicating
+ /// An individual requirement: a feature name and a flag indicating
/// the required state of that feature.
using Requirement = std::pair<std::string, bool>;
- /// \brief The set of language features required to use this module.
+ /// The set of language features required to use this module.
///
/// If any of these requirements are not available, the \c IsAvailable bit
/// will be false to indicate that this (sub)module is not available.
SmallVector<Requirement, 2> Requirements;
- /// \brief Whether this module is missing a feature from \c Requirements.
+ /// A module with the same name that shadows this module.
+ Module *ShadowingModule = nullptr;
+
+ /// Whether this module is missing a feature from \c Requirements.
unsigned IsMissingRequirement : 1;
- /// \brief Whether we tried and failed to load a module file for this module.
+ /// Whether we tried and failed to load a module file for this module.
unsigned HasIncompatibleModuleFile : 1;
- /// \brief Whether this module is available in the current translation unit.
+ /// Whether this module is available in the current translation unit.
///
/// If the module is missing headers or does not meet all requirements then
/// this bit will be 0.
unsigned IsAvailable : 1;
- /// \brief Whether this module was loaded from a module file.
+ /// Whether this module was loaded from a module file.
unsigned IsFromModuleFile : 1;
-
- /// \brief Whether this is a framework module.
+
+ /// Whether this is a framework module.
unsigned IsFramework : 1;
-
- /// \brief Whether this is an explicit submodule.
+
+ /// Whether this is an explicit submodule.
unsigned IsExplicit : 1;
-
- /// \brief Whether this is a "system" module (which assumes that all
+
+ /// Whether this is a "system" module (which assumes that all
/// headers in it are system headers).
unsigned IsSystem : 1;
- /// \brief Whether this is an 'extern "C"' module (which implicitly puts all
+ /// Whether this is an 'extern "C"' module (which implicitly puts all
/// headers in it within an 'extern "C"' block, and allows the module to be
/// imported within such a block).
unsigned IsExternC : 1;
- /// \brief Whether this is an inferred submodule (module * { ... }).
+ /// Whether this is an inferred submodule (module * { ... }).
unsigned IsInferred : 1;
- /// \brief Whether we should infer submodules for this module based on
+ /// Whether we should infer submodules for this module based on
/// the headers.
///
/// Submodules can only be inferred for modules with an umbrella header.
unsigned InferSubmodules : 1;
-
- /// \brief Whether, when inferring submodules, the inferred submodules
+
+ /// Whether, when inferring submodules, the inferred submodules
/// should be explicit.
unsigned InferExplicitSubmodules : 1;
-
- /// \brief Whether, when inferring submodules, the inferr submodules should
+
+ /// Whether, when inferring submodules, the inferr submodules should
/// export all modules they import (e.g., the equivalent of "export *").
unsigned InferExportWildcard : 1;
- /// \brief Whether the set of configuration macros is exhaustive.
+ /// Whether the set of configuration macros is exhaustive.
///
/// When the set of configuration macros is exhaustive, meaning
/// that no identifier not in this list should affect how the module is
/// built.
unsigned ConfigMacrosExhaustive : 1;
- /// \brief Whether files in this module can only include non-modular headers
+ /// Whether files in this module can only include non-modular headers
/// and headers from used modules.
unsigned NoUndeclaredIncludes : 1;
- /// \brief Describes the visibility of the various names within a
+ /// Whether this module came from a "private" module map, found next
+ /// to a regular (public) module map.
+ unsigned ModuleMapIsPrivate : 1;
+
+ /// Describes the visibility of the various names within a
/// particular module.
enum NameVisibilityKind {
- /// \brief All of the names in this module are hidden.
+ /// All of the names in this module are hidden.
Hidden,
- /// \brief All of the names in this module are visible.
+ /// All of the names in this module are visible.
AllVisible
};
- /// \brief The visibility of names within this particular module.
+ /// The visibility of names within this particular module.
NameVisibilityKind NameVisibility;
- /// \brief The location of the inferred submodule.
+ /// The location of the inferred submodule.
SourceLocation InferredSubmoduleLoc;
- /// \brief The set of modules imported by this module, and on which this
+ /// The set of modules imported by this module, and on which this
/// module depends.
llvm::SmallSetVector<Module *, 2> Imports;
-
- /// \brief Describes an exported module.
+
+ /// Describes an exported module.
///
/// The pointer is the module being re-exported, while the bit will be true
/// to indicate that this is a wildcard export.
using ExportDecl = llvm::PointerIntPair<Module *, 1, bool>;
-
- /// \brief The set of export declarations.
+
+ /// The set of export declarations.
SmallVector<ExportDecl, 2> Exports;
-
- /// \brief Describes an exported module that has not yet been resolved
+
+ /// Describes an exported module that has not yet been resolved
/// (perhaps because the module it refers to has not yet been loaded).
struct UnresolvedExportDecl {
- /// \brief The location of the 'export' keyword in the module map file.
+ /// The location of the 'export' keyword in the module map file.
SourceLocation ExportLoc;
-
- /// \brief The name of the module.
+
+ /// The name of the module.
ModuleId Id;
-
- /// \brief Whether this export declaration ends in a wildcard, indicating
+
+ /// Whether this export declaration ends in a wildcard, indicating
/// that all of its submodules should be exported (rather than the named
/// module itself).
bool Wildcard;
};
-
- /// \brief The set of export declarations that have yet to be resolved.
+
+ /// The set of export declarations that have yet to be resolved.
SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;
- /// \brief The directly used modules.
+ /// The directly used modules.
SmallVector<Module *, 2> DirectUses;
- /// \brief The set of use declarations that have yet to be resolved.
+ /// The set of use declarations that have yet to be resolved.
SmallVector<ModuleId, 2> UnresolvedDirectUses;
- /// \brief A library or framework to link against when an entity from this
+ /// A library or framework to link against when an entity from this
/// module is used.
struct LinkLibrary {
LinkLibrary() = default;
LinkLibrary(const std::string &Library, bool IsFramework)
: Library(Library), IsFramework(IsFramework) {}
-
- /// \brief The library to link against.
+
+ /// The library to link against.
///
/// This will typically be a library or framework name, but can also
/// be an absolute path to the library or framework.
std::string Library;
- /// \brief Whether this is a framework rather than a library.
+ /// Whether this is a framework rather than a library.
bool IsFramework = false;
};
- /// \brief The set of libraries or frameworks to link against when
+ /// The set of libraries or frameworks to link against when
/// an entity from this module is used.
llvm::SmallVector<LinkLibrary, 2> LinkLibraries;
- /// \brief The set of "configuration macros", which are macros that
+ /// Autolinking uses the framework name for linking purposes
+ /// when this is false and the export_as name otherwise.
+ bool UseExportAsModuleLinkName = false;
+
+ /// The set of "configuration macros", which are macros that
/// (intentionally) change how this module is built.
std::vector<std::string> ConfigMacros;
- /// \brief An unresolved conflict with another module.
+ /// An unresolved conflict with another module.
struct UnresolvedConflict {
- /// \brief The (unresolved) module id.
+ /// The (unresolved) module id.
ModuleId Id;
- /// \brief The message provided to the user when there is a conflict.
+ /// The message provided to the user when there is a conflict.
std::string Message;
};
- /// \brief The list of conflicts for which the module-id has not yet been
+ /// The list of conflicts for which the module-id has not yet been
/// resolved.
std::vector<UnresolvedConflict> UnresolvedConflicts;
- /// \brief A conflict between two modules.
+ /// A conflict between two modules.
struct Conflict {
- /// \brief The module that this module conflicts with.
+ /// The module that this module conflicts with.
Module *Other;
- /// \brief The message provided to the user when there is a conflict.
+ /// The message provided to the user when there is a conflict.
std::string Message;
};
- /// \brief The list of conflicts.
+ /// The list of conflicts.
std::vector<Conflict> Conflicts;
- /// \brief Construct a new module or submodule.
+ /// Construct a new module or submodule.
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID);
-
+
~Module();
-
- /// \brief Determine whether this module is available for use within the
+
+ /// Determine whether this module is available for use within the
/// current translation unit.
bool isAvailable() const { return IsAvailable; }
- /// \brief Determine whether this module is available for use within the
+ /// Determine whether this module is available for use within the
/// current translation unit.
///
/// \param LangOpts The language options used for the current
@@ -375,33 +386,40 @@ public:
///
/// \param Target The target options used for the current translation unit.
///
- /// \param Req If this module is unavailable, this parameter
- /// will be set to one of the requirements that is not met for use of
- /// this module.
- bool isAvailable(const LangOptions &LangOpts,
+ /// \param Req If this module is unavailable because of a missing requirement,
+ /// this parameter will be set to one of the requirements that is not met for
+ /// use of this module.
+ ///
+ /// \param MissingHeader If this module is unavailable because of a missing
+ /// header, this parameter will be set to one of the missing headers.
+ ///
+ /// \param ShadowingModule If this module is unavailable because it is
+ /// shadowed, this parameter will be set to the shadowing module.
+ bool isAvailable(const LangOptions &LangOpts,
const TargetInfo &Target,
Requirement &Req,
- UnresolvedHeaderDirective &MissingHeader) const;
+ UnresolvedHeaderDirective &MissingHeader,
+ Module *&ShadowingModule) const;
- /// \brief Determine whether this module is a submodule.
+ /// Determine whether this module is a submodule.
bool isSubModule() const { return Parent != nullptr; }
-
- /// \brief Determine whether this module is a submodule of the given other
+
+ /// Determine whether this module is a submodule of the given other
/// module.
bool isSubModuleOf(const Module *Other) const;
-
- /// \brief Determine whether this module is a part of a framework,
+
+ /// Determine whether this module is a part of a framework,
/// either because it is a framework module or because it is a submodule
/// of a framework module.
bool isPartOfFramework() const {
- for (const Module *Mod = this; Mod; Mod = Mod->Parent)
+ for (const Module *Mod = this; Mod; Mod = Mod->Parent)
if (Mod->IsFramework)
return true;
-
+
return false;
}
- /// \brief Determine whether this module is a subframework of another
+ /// Determine whether this module is a subframework of another
/// framework.
bool isSubFramework() const {
return IsFramework && Parent && Parent->isPartOfFramework();
@@ -416,51 +434,51 @@ public:
Parent->SubModules.push_back(this);
}
- /// \brief Retrieve the full name of this module, including the path from
+ /// 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
/// lexically valid as identifiers will be emitted as string literals.
std::string getFullModuleName(bool AllowStringLiterals = false) const;
- /// \brief Whether the full name of this module is equal to joining
+ /// Whether the full name of this module is equal to joining
/// \p nameParts with "."s.
///
/// This is more efficient than getFullModuleName().
bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const;
- /// \brief Retrieve the top-level module for this (sub)module, which may
+ /// Retrieve the top-level module for this (sub)module, which may
/// be this module.
Module *getTopLevelModule() {
return const_cast<Module *>(
const_cast<const Module *>(this)->getTopLevelModule());
}
- /// \brief Retrieve the top-level module for this (sub)module, which may
+ /// Retrieve the top-level module for this (sub)module, which may
/// be this module.
const Module *getTopLevelModule() const;
-
- /// \brief Retrieve the name of the top-level module.
+
+ /// Retrieve the name of the top-level module.
StringRef getTopLevelModuleName() const {
return getTopLevelModule()->Name;
}
- /// \brief The serialized AST file for this module, if one was created.
+ /// The serialized AST file for this module, if one was created.
const FileEntry *getASTFile() const {
return getTopLevelModule()->ASTFile;
}
- /// \brief Set the serialized AST file for the top-level module of this module.
+ /// Set the serialized AST file for the top-level module of this module.
void setASTFile(const FileEntry *File) {
assert((File == nullptr || getASTFile() == nullptr ||
getASTFile() == File) && "file path changed");
getTopLevelModule()->ASTFile = File;
}
- /// \brief Retrieve the directory for which this module serves as the
+ /// Retrieve the directory for which this module serves as the
/// umbrella.
DirectoryName getUmbrellaDir() const;
- /// \brief Retrieve the header that serves as the umbrella header for this
+ /// Retrieve the header that serves as the umbrella header for this
/// module.
Header getUmbrellaHeader() const {
if (auto *E = Umbrella.dyn_cast<const FileEntry *>())
@@ -468,31 +486,31 @@ public:
return Header{};
}
- /// \brief Determine whether this module has an umbrella directory that is
+ /// Determine whether this module has an umbrella directory that is
/// not based on an umbrella header.
bool hasUmbrellaDir() const {
return Umbrella && Umbrella.is<const DirectoryEntry *>();
}
- /// \brief Add a top-level header associated with this module.
+ /// Add a top-level header associated with this module.
void addTopHeader(const FileEntry *File) {
assert(File);
TopHeaders.insert(File);
}
- /// \brief Add a top-level header filename associated with this module.
+ /// Add a top-level header filename associated with this module.
void addTopHeaderFilename(StringRef Filename) {
TopHeaderNames.push_back(Filename);
}
- /// \brief The top-level headers associated with this module.
+ /// The top-level headers associated with this module.
ArrayRef<const FileEntry *> getTopHeaders(FileManager &FileMgr);
- /// \brief Determine whether this module has declared its intention to
+ /// Determine whether this module has declared its intention to
/// directly use another module.
bool directlyUses(const Module *Requested) const;
- /// \brief Add the given feature requirement to the list of features
+ /// Add the given feature requirement to the list of features
/// required by this module.
///
/// \param Feature The feature that is required by this module (and
@@ -510,15 +528,15 @@ public:
const LangOptions &LangOpts,
const TargetInfo &Target);
- /// \brief Mark this module and all of its submodules as unavailable.
+ /// Mark this module and all of its submodules as unavailable.
void markUnavailable(bool MissingRequirement = false);
- /// \brief Find the submodule with the given name.
+ /// Find the submodule with the given name.
///
/// \returns The submodule if found, or NULL otherwise.
Module *findSubmodule(StringRef Name) const;
- /// \brief Determine whether the specified module would be visible to
+ /// Determine whether the specified module would be visible to
/// a lookup at the end of this module.
///
/// FIXME: This may return incorrect results for (submodules of) the
@@ -534,7 +552,7 @@ public:
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();}
submodule_iterator submodule_end() { return SubModules.end(); }
@@ -547,7 +565,7 @@ public:
return llvm::make_range(submodule_begin(), submodule_end());
}
- /// \brief Appends this module's list of exported modules to \p Exported.
+ /// Appends this module's list of exported modules to \p Exported.
///
/// This provides a subset of immediately imported modules (the ones that are
/// directly exported), not the complete set of exported modules.
@@ -557,17 +575,17 @@ public:
return "<module-includes>";
}
- /// \brief Print the module map for this module to the given stream.
+ /// 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.
+
+ /// Dump the contents of this module to the given output stream.
void dump() const;
private:
void buildVisibleModulesCache() const;
};
-/// \brief A set of visible modules.
+/// A set of visible modules.
class VisibleModuleSet {
public:
VisibleModuleSet() = default;
@@ -587,34 +605,34 @@ public:
return *this;
}
- /// \brief Get the current visibility generation. Incremented each time the
+ /// Get the current visibility generation. Incremented each time the
/// set of visible modules changes in any way.
unsigned getGeneration() const { return Generation; }
- /// \brief Determine whether a module is visible.
+ /// Determine whether a module is visible.
bool isVisible(const Module *M) const {
return getImportLoc(M).isValid();
}
- /// \brief Get the location at which the import of a module was triggered.
+ /// Get the location at which the import of a module was triggered.
SourceLocation getImportLoc(const Module *M) const {
return M->getVisibilityID() < ImportLocs.size()
? ImportLocs[M->getVisibilityID()]
: SourceLocation();
}
- /// \brief A callback to call when a module is made visible (directly or
+ /// A callback to call when a module is made visible (directly or
/// indirectly) by a call to \ref setVisible.
using VisibleCallback = llvm::function_ref<void(Module *M)>;
- /// \brief A callback to call when a module conflict is found. \p Path
+ /// 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.
using ConflictCallback =
llvm::function_ref<void(ArrayRef<Module *> Path, Module *Conflict,
StringRef Message)>;
- /// \brief Make a specific module visible.
+ /// Make a specific module visible.
void setVisible(Module *M, SourceLocation Loc,
VisibleCallback Vis = [](Module *) {},
ConflictCallback Cb = [](ArrayRef<Module *>, Module *,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
index 8dc259c7ab66..c307c9643390 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
@@ -1,4 +1,4 @@
-//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===//
+//===- ObjCRuntime.h - Objective-C Runtime Configuration --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,25 +6,28 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines types useful for describing an Objective-C runtime.
-///
+/// Defines types useful for describing an Objective-C runtime.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H
#define LLVM_CLANG_BASIC_OBJCRUNTIME_H
-#include "clang/Basic/VersionTuple.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/VersionTuple.h"
+#include <string>
namespace clang {
-/// \brief The basic abstraction for the target Objective-C runtime.
+/// The basic abstraction for the target Objective-C runtime.
class ObjCRuntime {
public:
- /// \brief The basic Objective-C runtimes that we know about.
+ /// The basic Objective-C runtimes that we know about.
enum Kind {
/// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS
/// X platforms that use the non-fragile ABI; the version is a
@@ -57,15 +60,14 @@ public:
};
private:
- Kind TheKind;
+ Kind TheKind = MacOSX;
VersionTuple Version;
public:
/// A bogus initialization of the runtime.
- ObjCRuntime() : TheKind(MacOSX) {}
-
+ ObjCRuntime() = default;
ObjCRuntime(Kind kind, const VersionTuple &version)
- : TheKind(kind), Version(version) {}
+ : TheKind(kind), Version(version) {}
void set(Kind kind, VersionTuple version) {
TheKind = kind;
@@ -75,7 +77,7 @@ public:
Kind getKind() const { return TheKind; }
const VersionTuple &getVersion() const { return Version; }
- /// \brief Does this runtime follow the set of implied behaviors for a
+ /// Does this runtime follow the set of implied behaviors for a
/// "non-fragile" ABI?
bool isNonFragile() const {
switch (getKind()) {
@@ -113,7 +115,7 @@ public:
return true;
}
- /// \brief Is this runtime basically of the GNU family of runtimes?
+ /// Is this runtime basically of the GNU family of runtimes?
bool isGNUFamily() const {
switch (getKind()) {
case FragileMacOSX:
@@ -129,14 +131,14 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Is this runtime basically of the NeXT family of runtimes?
+ /// Is this runtime basically of the NeXT family of runtimes?
bool isNeXTFamily() const {
// For now, this is just the inverse of isGNUFamily(), but that's
// not inherently true.
return !isGNUFamily();
}
- /// \brief Does this runtime allow ARC at all?
+ /// Does this runtime allow ARC at all?
bool allowsARC() const {
switch (getKind()) {
case FragileMacOSX:
@@ -152,7 +154,7 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Does this runtime natively provide the ARC entrypoints?
+ /// Does this runtime natively provide the ARC entrypoints?
///
/// ARC cannot be directly supported on a platform that does not provide
/// these entrypoints, although it may be supportable via a stub
@@ -171,7 +173,7 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Does this runtime supports optimized setter entrypoints?
+ /// Does this runtime supports optimized setter entrypoints?
bool hasOptimizedSetter() const {
switch (getKind()) {
case MacOSX:
@@ -182,9 +184,8 @@ public:
return true;
case GNUstep:
return getVersion() >= VersionTuple(1, 7);
-
default:
- return false;
+ return false;
}
}
@@ -193,7 +194,7 @@ public:
return hasNativeWeak();
}
- /// \brief Does this runtime natively provide ARC-compliant 'weak'
+ /// Does this runtime natively provide ARC-compliant 'weak'
/// entrypoints?
bool hasNativeWeak() const {
// Right now, this is always equivalent to whether the runtime
@@ -201,14 +202,14 @@ public:
return hasNativeARC();
}
- /// \brief Does this runtime directly support the subscripting methods?
+ /// Does this runtime directly support the subscripting methods?
///
/// This is really a property of the library, not the runtime.
bool hasSubscripting() const {
switch (getKind()) {
case FragileMacOSX: return false;
- case MacOSX: return getVersion() >= VersionTuple(10, 8);
- case iOS: return getVersion() >= VersionTuple(6);
+ case MacOSX: return getVersion() >= VersionTuple(10, 11);
+ case iOS: return getVersion() >= VersionTuple(9);
case WatchOS: return true;
// This is really a lie, because some implementations and versions
@@ -221,12 +222,12 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Does this runtime allow sizeof or alignof on object types?
+ /// Does this runtime allow sizeof or alignof on object types?
bool allowsSizeofAlignof() const {
return isFragile();
}
- /// \brief Does this runtime allow pointer arithmetic on objects?
+ /// Does this runtime allow pointer arithmetic on objects?
///
/// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic()
/// yields true) [].
@@ -245,12 +246,12 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Is subscripting pointer arithmetic?
+ /// Is subscripting pointer arithmetic?
bool isSubscriptPointerArithmetic() const {
return allowsPointerArithmetic();
}
- /// \brief Does this runtime provide an objc_terminate function?
+ /// Does this runtime provide an objc_terminate function?
///
/// This is used in handlers for exceptions during the unwind process;
/// without it, abort() must be used in pure ObjC files.
@@ -267,7 +268,7 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Does this runtime support weakly importing classes?
+ /// Does this runtime support weakly importing classes?
bool hasWeakClassImport() const {
switch (getKind()) {
case MacOSX: return true;
@@ -281,7 +282,7 @@ public:
llvm_unreachable("bad kind");
}
- /// \brief Does this runtime use zero-cost exceptions?
+ /// Does this runtime use zero-cost exceptions?
bool hasUnwindExceptions() const {
switch (getKind()) {
case MacOSX: return true;
@@ -320,7 +321,6 @@ public:
return getVersion() >= VersionTuple(2);
case GNUstep:
return false;
-
default:
return false;
}
@@ -340,7 +340,7 @@ public:
}
}
- /// \brief Try to parse an Objective-C runtime specification from the given
+ /// Try to parse an Objective-C runtime specification from the given
/// string.
///
/// \return true on error.
@@ -360,6 +360,6 @@ public:
raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_OBJCRUNTIME_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
index c3319d2d808b..13cb12e7c581 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
@@ -53,6 +53,9 @@ OPENCLEXT_INTERNAL(cl_khr_icd, 100, ~0U)
OPENCLEXT_INTERNAL(cl_khr_gl_event, 110, ~0U)
OPENCLEXT_INTERNAL(cl_khr_d3d10_sharing, 110, ~0U)
+// EMBEDDED_PROFILE
+OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U)
+
// OpenCL 1.2.
OPENCLEXT_INTERNAL(cl_khr_context_abort, 120, ~0U)
OPENCLEXT_INTERNAL(cl_khr_d3d11_sharing, 120, ~0U)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLOptions.h
index cc850f0b0b24..cc4e9922dca0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLOptions.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::OpenCLOptions class.
+/// Defines the clang::OpenCLOptions class.
///
//===----------------------------------------------------------------------===//
@@ -19,7 +19,7 @@
namespace clang {
-/// \brief OpenCL supported extensions and optional core features
+/// OpenCL supported extensions and optional core features
class OpenCLOptions {
struct Info {
bool Supported; // Is this option supported
@@ -67,7 +67,7 @@ public:
OptMap[Ext].Enabled = V;
}
- /// \brief Enable or disable support for OpenCL extensions
+ /// Enable or disable support for OpenCL extensions
/// \param Ext name of the extension optionally prefixed with
/// '+' or '-'
/// \param V used when \p Ext is not prefixed by '+' or '-'
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
index 6a0bed7ab15f..4ed7053b679b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file defines the list of supported OpenMP directives and
+/// This file defines the list of supported OpenMP directives and
/// clauses.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
index e00333153f9b..c47973e53a8a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines some OpenMP-specific enums and functions.
+/// Defines some OpenMP-specific enums and functions.
///
//===----------------------------------------------------------------------===//
@@ -19,7 +19,7 @@
namespace clang {
-/// \brief OpenMP directives.
+/// OpenMP directives.
enum OpenMPDirectiveKind {
#define OPENMP_DIRECTIVE(Name) \
OMPD_##Name,
@@ -29,7 +29,7 @@ enum OpenMPDirectiveKind {
OMPD_unknown
};
-/// \brief OpenMP clauses.
+/// OpenMP clauses.
enum OpenMPClauseKind {
#define OPENMP_CLAUSE(Name, Class) \
OMPC_##Name,
@@ -39,7 +39,7 @@ enum OpenMPClauseKind {
OMPC_unknown
};
-/// \brief OpenMP attributes for 'default' clause.
+/// OpenMP attributes for 'default' clause.
enum OpenMPDefaultClauseKind {
#define OPENMP_DEFAULT_KIND(Name) \
OMPC_DEFAULT_##Name,
@@ -47,7 +47,7 @@ enum OpenMPDefaultClauseKind {
OMPC_DEFAULT_unknown
};
-/// \brief OpenMP attributes for 'proc_bind' clause.
+/// OpenMP attributes for 'proc_bind' clause.
enum OpenMPProcBindClauseKind {
#define OPENMP_PROC_BIND_KIND(Name) \
OMPC_PROC_BIND_##Name,
@@ -55,7 +55,7 @@ enum OpenMPProcBindClauseKind {
OMPC_PROC_BIND_unknown
};
-/// \brief OpenMP attributes for 'schedule' clause.
+/// OpenMP attributes for 'schedule' clause.
enum OpenMPScheduleClauseKind {
#define OPENMP_SCHEDULE_KIND(Name) \
OMPC_SCHEDULE_##Name,
@@ -63,7 +63,7 @@ enum OpenMPScheduleClauseKind {
OMPC_SCHEDULE_unknown
};
-/// \brief OpenMP modifiers for 'schedule' clause.
+/// OpenMP modifiers for 'schedule' clause.
enum OpenMPScheduleClauseModifier {
OMPC_SCHEDULE_MODIFIER_unknown = OMPC_SCHEDULE_unknown,
#define OPENMP_SCHEDULE_MODIFIER(Name) \
@@ -72,7 +72,7 @@ enum OpenMPScheduleClauseModifier {
OMPC_SCHEDULE_MODIFIER_last
};
-/// \brief OpenMP attributes for 'depend' clause.
+/// OpenMP attributes for 'depend' clause.
enum OpenMPDependClauseKind {
#define OPENMP_DEPEND_KIND(Name) \
OMPC_DEPEND_##Name,
@@ -80,7 +80,7 @@ enum OpenMPDependClauseKind {
OMPC_DEPEND_unknown
};
-/// \brief OpenMP attributes for 'linear' clause.
+/// OpenMP attributes for 'linear' clause.
enum OpenMPLinearClauseKind {
#define OPENMP_LINEAR_KIND(Name) \
OMPC_LINEAR_##Name,
@@ -88,7 +88,7 @@ enum OpenMPLinearClauseKind {
OMPC_LINEAR_unknown
};
-/// \brief OpenMP mapping kind for 'map' clause.
+/// OpenMP mapping kind for 'map' clause.
enum OpenMPMapClauseKind {
#define OPENMP_MAP_KIND(Name) \
OMPC_MAP_##Name,
@@ -96,14 +96,14 @@ enum OpenMPMapClauseKind {
OMPC_MAP_unknown
};
-/// \brief OpenMP attributes for 'dist_schedule' clause.
+/// OpenMP attributes for 'dist_schedule' clause.
enum OpenMPDistScheduleClauseKind {
#define OPENMP_DIST_SCHEDULE_KIND(Name) OMPC_DIST_SCHEDULE_##Name,
#include "clang/Basic/OpenMPKinds.def"
OMPC_DIST_SCHEDULE_unknown
};
-/// \brief OpenMP attributes for 'defaultmap' clause.
+/// OpenMP attributes for 'defaultmap' clause.
enum OpenMPDefaultmapClauseKind {
#define OPENMP_DEFAULTMAP_KIND(Name) \
OMPC_DEFAULTMAP_##Name,
@@ -111,7 +111,7 @@ enum OpenMPDefaultmapClauseKind {
OMPC_DEFAULTMAP_unknown
};
-/// \brief OpenMP modifiers for 'defaultmap' clause.
+/// OpenMP modifiers for 'defaultmap' clause.
enum OpenMPDefaultmapClauseModifier {
OMPC_DEFAULTMAP_MODIFIER_unknown = OMPC_DEFAULTMAP_unknown,
#define OPENMP_DEFAULTMAP_MODIFIER(Name) \
@@ -139,39 +139,39 @@ const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind);
-/// \brief Checks if the specified directive is a directive with an associated
+/// Checks if the specified directive is a directive with an associated
/// loop construct.
/// \param DKind Specified directive.
/// \return true - the directive is a loop-associated directive like 'omp simd'
/// or 'omp for' directive, otherwise - false.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a worksharing directive.
+/// Checks if the specified directive is a worksharing directive.
/// \param DKind Specified directive.
/// \return true - the directive is a worksharing directive like 'omp for',
/// otherwise - false.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a taskloop directive.
+/// Checks if the specified directive is a taskloop directive.
/// \param DKind Specified directive.
/// \return true - the directive is a worksharing directive like 'omp taskloop',
/// otherwise - false.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a parallel-kind directive.
+/// Checks if the specified directive is a parallel-kind directive.
/// \param DKind Specified directive.
/// \return true - the directive is a parallel-like directive like 'omp
/// parallel', otherwise - false.
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a target code offload directive.
+/// Checks if the specified directive is a target code offload directive.
/// \param DKind Specified directive.
/// \return true - the directive is a target code offload directive like
/// 'omp target', 'omp target parallel', 'omp target xxx'
/// otherwise - false.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a target data offload directive.
+/// Checks if the specified directive is a target data offload directive.
/// \param DKind Specified directive.
/// \return true - the directive is a target data offload directive like
/// 'omp target data', 'omp target update', 'omp target enter data',
@@ -193,13 +193,13 @@ bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind);
/// \return true - the directive is a teams-like directive, otherwise - false.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a simd directive.
+/// Checks if the specified directive is a simd directive.
/// \param DKind Specified directive.
/// \return true - the directive is a simd directive like 'omp simd',
/// otherwise - false.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a distribute directive.
+/// Checks if the specified directive is a distribute directive.
/// \param DKind Specified directive.
/// \return true - the directive is a distribute-directive like 'omp
/// distribute',
@@ -214,13 +214,13 @@ bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind);
/// otherwise - false.
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified clause is one of private clauses like
+/// Checks if the specified clause is one of private clauses like
/// 'private', 'firstprivate', 'reduction' etc..
/// \param Kind Clause kind.
/// \return true - the clause is a private clause, otherwise - false.
bool isOpenMPPrivate(OpenMPClauseKind Kind);
-/// \brief Checks if the specified clause is one of threadprivate clauses like
+/// Checks if the specified clause is one of threadprivate clauses like
/// 'threadprivate', 'copyin' or 'copyprivate'.
/// \param Kind Clause kind.
/// \return true - the clause is a threadprivate clause, otherwise - false.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h
index 7120baeef675..3096f835e66b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines an enumeration for C++ overloaded operators.
+/// Defines an enumeration for C++ overloaded operators.
///
//===----------------------------------------------------------------------===//
@@ -17,7 +17,7 @@
namespace clang {
-/// \brief Enumeration specifying the different kinds of C++ overloaded
+/// Enumeration specifying the different kinds of C++ overloaded
/// operators.
enum OverloadedOperatorKind : int {
OO_None, ///< Not an overloaded operator
@@ -27,7 +27,7 @@ enum OverloadedOperatorKind : int {
NUM_OVERLOADED_OPERATORS
};
-/// \brief Retrieve the spelling of the given overloaded operator, without
+/// Retrieve the spelling of the given overloaded operator, without
/// the preceding "operator" keyword.
const char *getOperatorSpelling(OverloadedOperatorKind Operator);
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
index 94978f81e543..4389e3bbd257 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines and computes precedence levels for binary/ternary operators.
+/// Defines and computes precedence levels for binary/ternary operators.
///
//===----------------------------------------------------------------------===//
@@ -44,7 +44,7 @@ namespace prec {
};
}
-/// \brief Return the precedence of the specified binary operator token.
+/// Return the precedence of the specified binary operator token.
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator,
bool CPlusPlus11);
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
index b2f14afe5695..9727af86f649 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
@@ -1,4 +1,4 @@
-//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===//
+//===- PartialDiagnostic.h - Diagnostic "closures" --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,25 +6,32 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Implements a partial diagnostic that can be emitted anwyhere
+/// Implements a partial diagnostic that can be emitted anwyhere
/// in a DiagnosticBuilder stream.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
#define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include <cassert>
+#include <cstdint>
+#include <string>
+#include <type_traits>
+#include <utility>
namespace clang {
+class DeclContext;
+class IdentifierInfo;
+
class PartialDiagnostic {
public:
enum {
@@ -36,10 +43,8 @@ public:
};
struct Storage {
- Storage() : NumDiagArgs(0) { }
-
enum {
- /// \brief The maximum number of arguments we can hold. We
+ /// The maximum number of arguments we can hold. We
/// currently only support up to 10 arguments (%0-%9).
///
/// A single diagnostic with more than that almost certainly has to
@@ -47,33 +52,35 @@ public:
MaxArguments = PartialDiagnostic::MaxArguments
};
- /// \brief The number of entries in Arguments.
- unsigned char NumDiagArgs;
+ /// The number of entries in Arguments.
+ unsigned char NumDiagArgs = 0;
- /// \brief Specifies for each argument whether it is in DiagArgumentsStr
+ /// Specifies for each argument whether it is in DiagArgumentsStr
/// or in DiagArguments.
unsigned char DiagArgumentsKind[MaxArguments];
- /// \brief The values for the various substitution positions.
+ /// The values for the various substitution positions.
///
/// This is used when the argument is not an std::string. The specific value
/// is mangled into an intptr_t and the interpretation depends on exactly
/// what sort of argument kind it is.
intptr_t DiagArgumentsVal[MaxArguments];
- /// \brief The values for the various substitution positions that have
+ /// The values for the various substitution positions that have
/// string arguments.
std::string DiagArgumentsStr[MaxArguments];
- /// \brief The list of ranges added to this diagnostic.
+ /// The list of ranges added to this diagnostic.
SmallVector<CharSourceRange, 8> DiagRanges;
- /// \brief If valid, provides a hint with some code to insert, remove, or
+ /// If valid, provides a hint with some code to insert, remove, or
/// modify at a particular position.
SmallVector<FixItHint, 6> FixItHints;
+
+ Storage() = default;
};
- /// \brief An allocator for Storage objects, which uses a small cache to
+ /// An allocator for Storage objects, which uses a small cache to
/// objects, used to reduce malloc()/free() traffic for partial diagnostics.
class StorageAllocator {
static const unsigned NumCached = 16;
@@ -85,7 +92,7 @@ public:
StorageAllocator();
~StorageAllocator();
- /// \brief Allocate new storage.
+ /// Allocate new storage.
Storage *Allocate() {
if (NumFreeListEntries == 0)
return new Storage;
@@ -97,7 +104,7 @@ public:
return Result;
}
- /// \brief Free the given storage object.
+ /// Free the given storage object.
void Deallocate(Storage *S) {
if (S >= Cached && S <= Cached + NumCached) {
FreeList[NumFreeListEntries++] = S;
@@ -113,16 +120,16 @@ private:
// in the sense that its bits can be safely memcpy'ed and destructed
// in the new location.
- /// \brief The diagnostic ID.
- mutable unsigned DiagID;
+ /// The diagnostic ID.
+ mutable unsigned DiagID = 0;
- /// \brief Storage for args and ranges.
- mutable Storage *DiagStorage;
+ /// Storage for args and ranges.
+ mutable Storage *DiagStorage = nullptr;
- /// \brief Allocator used to allocate storage for this diagnostic.
- StorageAllocator *Allocator;
+ /// Allocator used to allocate storage for this diagnostic.
+ StorageAllocator *Allocator = nullptr;
- /// \brief Retrieve storage for this particular diagnostic.
+ /// Retrieve storage for this particular diagnostic.
Storage *getStorage() const {
if (DiagStorage)
return DiagStorage;
@@ -176,17 +183,16 @@ private:
public:
struct NullDiagnostic {};
- /// \brief Create a null partial diagnostic, which cannot carry a payload,
+
+ /// Create a null partial diagnostic, which cannot carry a payload,
/// and only exists to be swapped with a real partial diagnostic.
- PartialDiagnostic(NullDiagnostic)
- : DiagID(0), DiagStorage(nullptr), Allocator(nullptr) { }
+ PartialDiagnostic(NullDiagnostic) {}
PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
- : DiagID(DiagID), DiagStorage(nullptr), Allocator(&Allocator) { }
+ : DiagID(DiagID), Allocator(&Allocator) {}
PartialDiagnostic(const PartialDiagnostic &Other)
- : DiagID(Other.DiagID), DiagStorage(nullptr), Allocator(Other.Allocator)
- {
+ : DiagID(Other.DiagID), Allocator(Other.Allocator) {
if (Other.DiagStorage) {
DiagStorage = getStorage();
*DiagStorage = *Other.DiagStorage;
@@ -194,22 +200,20 @@ public:
}
PartialDiagnostic(PartialDiagnostic &&Other)
- : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage),
- Allocator(Other.Allocator) {
+ : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage),
+ Allocator(Other.Allocator) {
Other.DiagStorage = nullptr;
}
PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage)
- : DiagID(Other.DiagID), DiagStorage(DiagStorage),
- Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
- {
+ : DiagID(Other.DiagID), DiagStorage(DiagStorage),
+ Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) {
if (Other.DiagStorage)
*this->DiagStorage = *Other.DiagStorage;
}
PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator)
- : DiagID(Other.getID()), DiagStorage(nullptr), Allocator(&Allocator)
- {
+ : DiagID(Other.getID()), Allocator(&Allocator) {
// Copy arguments.
for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
if (Other.getArgKind(I) == DiagnosticsEngine::ak_std_string)
@@ -320,7 +324,7 @@ public:
Diags.Clear();
}
- /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID
+ /// Clear out this partial diagnostic, giving it a new diagnostic ID
/// and removing all of its arguments, ranges, and fix-it hints.
void Reset(unsigned DiagID = 0) {
this->DiagID = DiagID;
@@ -402,7 +406,6 @@ public:
PD.AddFixItHint(Hint);
return PD;
}
-
};
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -411,9 +414,10 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
-/// \brief A partial diagnostic along with the source location where this
+/// A partial diagnostic along with the source location where this
/// diagnostic occurs.
-typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt;
+using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>;
+
+} // namespace clang
-} // end namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h b/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h
index 61de82450cf7..be92bbfde185 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h
@@ -1,4 +1,4 @@
-//===---------- PlistSupport.h - Plist Output Utilities ---------*- C++ -*-===//
+//===- PlistSupport.h - Plist Output Utilities ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,12 +10,20 @@
#ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H
#define LLVM_CLANG_BASIC_PLISTSUPPORT_H
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
namespace markup {
-typedef llvm::DenseMap<FileID, unsigned> FIDMap;
+
+using FIDMap = llvm::DenseMap<FileID, unsigned>;
inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
const SourceManager &SM, SourceLocation L) {
@@ -112,7 +120,8 @@ inline void EmitRange(raw_ostream &o, const SourceManager &SM,
EmitLocation(o, SM, R.getEnd(), FM, indent + 1);
Indent(o, indent) << "</array>\n";
}
-}
-}
-#endif
+} // namespace markup
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_PLISTSUPPORT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h
index 6badae5c0349..e652f52055d6 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the PrettyStackTraceEntry class, which is used to make
+/// Defines the PrettyStackTraceEntry class, which is used to make
/// crashes give more contextual information about what the program was doing
/// when it crashed.
///
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
index 30d5cc8166dc..ae5c75fc5bbd 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
@@ -44,8 +44,12 @@ SANITIZER("address", Address)
// Kernel AddressSanitizer (KASan)
SANITIZER("kernel-address", KernelAddress)
+// Hardware-assisted AddressSanitizer
SANITIZER("hwaddress", HWAddress)
+// Kernel Hardware-assisted AddressSanitizer (KHWASan)
+SANITIZER("kernel-hwaddress", KernelHWAddress)
+
// MemorySanitizer
SANITIZER("memory", Memory)
@@ -100,16 +104,20 @@ SANITIZER("dataflow", DataFlow)
SANITIZER("cfi-cast-strict", CFICastStrict)
SANITIZER("cfi-derived-cast", CFIDerivedCast)
SANITIZER("cfi-icall", CFIICall)
+SANITIZER("cfi-mfcall", CFIMFCall)
SANITIZER("cfi-unrelated-cast", CFIUnrelatedCast)
SANITIZER("cfi-nvcall", CFINVCall)
SANITIZER("cfi-vcall", CFIVCall)
SANITIZER_GROUP("cfi", CFI,
- CFIDerivedCast | CFIICall | CFIUnrelatedCast | CFINVCall |
- CFIVCall)
+ CFIDerivedCast | CFIICall | CFIMFCall | CFIUnrelatedCast |
+ CFINVCall | CFIVCall)
// Safe Stack
SANITIZER("safe-stack", SafeStack)
+// Shadow Call Stack
+SANITIZER("shadow-call-stack", ShadowCallStack)
+
// -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,
@@ -123,9 +131,14 @@ SANITIZER_GROUP("undefined", Undefined,
// -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
+// ImplicitConversionSanitizer
+SANITIZER("implicit-integer-truncation", ImplicitIntegerTruncation)
+SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
+ ImplicitIntegerTruncation)
+
SANITIZER_GROUP("integer", Integer,
- SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
- IntegerDivideByZero)
+ ImplicitIntegerTruncation | IntegerDivideByZero | Shift |
+ SignedIntegerOverflow | UnsignedIntegerOverflow)
SANITIZER("local-bounds", LocalBounds)
SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
index 1b936c7d115c..2ecbde821599 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
@@ -1,4 +1,4 @@
-//===--- Sanitizers.h - C Language Family Language Options ------*- C++ -*-===//
+//===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the clang::SanitizerKind enum.
-///
+/// Defines the clang::SanitizerKind enum.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SANITIZERS_H
@@ -18,10 +18,12 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
-typedef uint64_t SanitizerMask;
+using SanitizerMask = uint64_t;
namespace SanitizerKind {
@@ -43,19 +45,19 @@ enum SanitizerOrdinal : uint64_t {
const SanitizerMask ID##Group = 1ULL << SO_##ID##Group;
#include "clang/Basic/Sanitizers.def"
-}
+} // namespace SanitizerKind
struct SanitizerSet {
- /// \brief Check if a certain (single) sanitizer is enabled.
+ /// Check if a certain (single) sanitizer is enabled.
bool has(SanitizerMask K) const {
assert(llvm::isPowerOf2_64(K));
return Mask & K;
}
- /// \brief Check if one or more sanitizers are enabled.
+ /// Check if one or more sanitizers are enabled.
bool hasOneOf(SanitizerMask K) const { return Mask & K; }
- /// \brief Enable or disable a certain (single) sanitizer.
+ /// Enable or disable a certain (single) sanitizer.
void set(SanitizerMask K, bool Value) {
assert(llvm::isPowerOf2_64(K));
Mask = Value ? (Mask | K) : (Mask & ~K);
@@ -64,10 +66,10 @@ struct SanitizerSet {
/// Disable the sanitizers specified in \p K.
void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
- /// \brief Returns true if at least one sanitizer is enabled.
+ /// Returns true if at least one sanitizer is enabled.
bool empty() const { return Mask == 0; }
- /// \brief Bitmask of enabled sanitizers.
+ /// Bitmask of enabled sanitizers.
SanitizerMask Mask = 0;
};
@@ -82,9 +84,10 @@ SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
/// Return the sanitizers which do not affect preprocessing.
inline SanitizerMask getPPTransparentSanitizers() {
return SanitizerKind::CFI | SanitizerKind::Integer |
- SanitizerKind::Nullability | SanitizerKind::Undefined;
+ SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
+ SanitizerKind::Undefined;
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_SANITIZERS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
index 7418b50f9d83..488a604a452f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
@@ -1,4 +1,4 @@
-//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
+//===- SourceLocation.h - Compact identifier for Source Files ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,38 +6,39 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the clang::SourceLocation class and associated facilities.
-///
+/// Defines the clang::SourceLocation class and associated facilities.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H
#define LLVM_CLANG_BASIC_SOURCELOCATION_H
#include "clang/Basic/LLVM.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
-#include <functional>
+#include <cstdint>
#include <string>
#include <utility>
namespace llvm {
- class MemoryBuffer;
- template <typename T> struct DenseMapInfo;
- template <typename T> struct isPodLike;
-}
+
+template <typename T> struct DenseMapInfo;
+template <typename T> struct isPodLike;
+
+} // namespace llvm
namespace clang {
class SourceManager;
-/// \brief An opaque identifier used by SourceManager which refers to a
+/// An opaque identifier used by SourceManager which refers to a
/// source file (MemoryBuffer) along with its \#include path and \#line data.
///
class FileID {
- /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is
+ /// A mostly-opaque identifier, where 0 is "invalid", >0 is
/// this module, and <-1 is something loaded from another module.
int ID = 0;
@@ -56,20 +57,20 @@ public:
unsigned getHashValue() const { return static_cast<unsigned>(ID); }
private:
- friend class SourceManager;
friend class ASTWriter;
friend class ASTReader;
-
+ friend class SourceManager;
+
static FileID get(int V) {
FileID F;
F.ID = V;
return F;
}
+
int getOpaqueValue() const { return ID; }
};
-
-/// \brief Encodes a location in the source. The SourceManager can decode this
+/// Encodes a location in the source. The SourceManager can decode this
/// to get at the full include stack, line and column information.
///
/// Technically, a source location is simply an offset into the manager's view
@@ -85,10 +86,12 @@ private:
///
/// It is important that this type remains small. It is currently 32 bits wide.
class SourceLocation {
- unsigned ID = 0;
- friend class SourceManager;
friend class ASTReader;
friend class ASTWriter;
+ friend class SourceManager;
+
+ unsigned ID = 0;
+
enum : unsigned {
MacroIDBit = 1U << 31
};
@@ -97,7 +100,7 @@ public:
bool isFileID() const { return (ID & MacroIDBit) == 0; }
bool isMacroID() const { return (ID & MacroIDBit) != 0; }
- /// \brief Return true if this is a valid SourceLocation object.
+ /// Return true if this is a valid SourceLocation object.
///
/// Invalid SourceLocations are often used when events have no corresponding
/// location in the source (e.g. a diagnostic is required for a command line
@@ -106,7 +109,7 @@ public:
bool isInvalid() const { return ID == 0; }
private:
- /// \brief Return the offset into the manager's global input view.
+ /// Return the offset into the manager's global input view.
unsigned getOffset() const {
return ID & ~MacroIDBit;
}
@@ -124,9 +127,9 @@ private:
L.ID = MacroIDBit | ID;
return L;
}
-public:
- /// \brief Return a source location with the specified offset from this
+public:
+ /// Return a source location with the specified offset from this
/// SourceLocation.
SourceLocation getLocWithOffset(int Offset) const {
assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow");
@@ -135,14 +138,14 @@ public:
return L;
}
- /// \brief When a SourceLocation itself cannot be used, this returns
+ /// When a SourceLocation itself cannot be used, this returns
/// an (opaque) 32-bit integer encoding for it.
///
/// This should only be passed to SourceLocation::getFromRawEncoding, it
/// should not be inspected directly.
unsigned getRawEncoding() const { return ID; }
- /// \brief Turn a raw encoding of a SourceLocation object into
+ /// Turn a raw encoding of a SourceLocation object into
/// a real SourceLocation.
///
/// \see getRawEncoding.
@@ -152,7 +155,7 @@ public:
return X;
}
- /// \brief When a SourceLocation itself cannot be used, this returns
+ /// When a SourceLocation itself cannot be used, this returns
/// an (opaque) pointer encoding for it.
///
/// This should only be passed to SourceLocation::getFromPtrEncoding, it
@@ -163,7 +166,7 @@ public:
return (void*)(uintptr_t)getRawEncoding();
}
- /// \brief Turn a pointer encoding of a SourceLocation object back
+ /// Turn a pointer encoding of a SourceLocation object back
/// into a real SourceLocation.
static SourceLocation getFromPtrEncoding(const void *Encoding) {
return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
@@ -191,7 +194,7 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() < RHS.getRawEncoding();
}
-/// \brief A trivial tuple used to represent a source range.
+/// A trivial tuple used to represent a source range.
class SourceRange {
SourceLocation B;
SourceLocation E;
@@ -218,15 +221,15 @@ public:
return B != X.B || E != X.E;
}
};
-
-/// \brief Represents a character-granular source range.
+
+/// Represents a character-granular source range.
///
/// The underlying SourceRange can either specify the starting/ending character
/// of the range, or it can specify the start of the range and the start of the
/// last token of the range (a "token range"). In the token range case, the
/// size of the last token must be measured to determine the actual end of the
/// range.
-class CharSourceRange {
+class CharSourceRange {
SourceRange Range;
bool IsTokenRange = false;
@@ -241,32 +244,34 @@ public:
static CharSourceRange getCharRange(SourceRange R) {
return CharSourceRange(R, false);
}
-
+
static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
return getTokenRange(SourceRange(B, E));
}
+
static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
return getCharRange(SourceRange(B, E));
}
-
- /// \brief Return true if the end of this range specifies the start of
+
+ /// Return true if the end of this range specifies the start of
/// the last token. Return false if the end of this range specifies the last
/// character in the range.
bool isTokenRange() const { return IsTokenRange; }
bool isCharRange() const { return !IsTokenRange; }
-
+
SourceLocation getBegin() const { return Range.getBegin(); }
SourceLocation getEnd() const { return Range.getEnd(); }
SourceRange getAsRange() const { return Range; }
-
+
void setBegin(SourceLocation b) { Range.setBegin(b); }
void setEnd(SourceLocation e) { Range.setEnd(e); }
-
+ void setTokenRange(bool TR) { IsTokenRange = TR; }
+
bool isValid() const { return Range.isValid(); }
bool isInvalid() const { return !isValid(); }
};
-/// \brief Represents an unpacked "presumed" location which can be presented
+/// Represents an unpacked "presumed" location which can be presented
/// to the user.
///
/// A 'presumed' location can be modified by \#line and GNU line marker
@@ -274,23 +279,23 @@ public:
///
/// You can get a PresumedLoc from a SourceLocation with SourceManager.
class PresumedLoc {
- const char *Filename;
+ const char *Filename = nullptr;
unsigned Line, Col;
SourceLocation IncludeLoc;
public:
- PresumedLoc() : Filename(nullptr) {}
+ PresumedLoc() = default;
PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
: Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {}
- /// \brief Return true if this object is invalid or uninitialized.
+ /// Return true if this object is invalid or uninitialized.
///
/// This occurs when created with invalid source locations or when walking
/// off the top of a \#include stack.
bool isInvalid() const { return Filename == nullptr; }
bool isValid() const { return Filename != nullptr; }
- /// \brief Return the presumed filename of this location.
+ /// Return the presumed filename of this location.
///
/// This can be affected by \#line etc.
const char *getFilename() const {
@@ -298,7 +303,7 @@ public:
return Filename;
}
- /// \brief Return the presumed line number of this location.
+ /// Return the presumed line number of this location.
///
/// This can be affected by \#line etc.
unsigned getLine() const {
@@ -306,7 +311,7 @@ public:
return Line;
}
- /// \brief Return the presumed column number of this location.
+ /// Return the presumed column number of this location.
///
/// This cannot be affected by \#line, but is packaged here for convenience.
unsigned getColumn() const {
@@ -314,7 +319,7 @@ public:
return Col;
}
- /// \brief Return the presumed include location of this location.
+ /// Return the presumed include location of this location.
///
/// This can be affected by GNU linemarker directives.
SourceLocation getIncludeLoc() const {
@@ -325,18 +330,18 @@ public:
class FileEntry;
-/// \brief A SourceLocation and its associated SourceManager.
+/// A SourceLocation and its associated SourceManager.
///
/// This is useful for argument passing to functions that expect both objects.
class FullSourceLoc : public SourceLocation {
const SourceManager *SrcMgr = nullptr;
public:
- /// \brief Creates a FullSourceLoc where isValid() returns \c false.
+ /// Creates a FullSourceLoc where isValid() returns \c false.
FullSourceLoc() = default;
explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
- : SourceLocation(Loc), SrcMgr(&SM) {}
+ : SourceLocation(Loc), SrcMgr(&SM) {}
bool hasManager() const {
bool hasSrcMgr = SrcMgr != nullptr;
@@ -355,7 +360,6 @@ public:
FullSourceLoc getExpansionLoc() const;
FullSourceLoc getSpellingLoc() const;
FullSourceLoc getFileLoc() const;
- std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const;
PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
FullSourceLoc getImmediateMacroCallerLoc() const;
@@ -373,15 +377,13 @@ public:
unsigned getLineNumber(bool *Invalid = nullptr) const;
unsigned getColumnNumber(bool *Invalid = nullptr) const;
- std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const;
-
const FileEntry *getFileEntry() const;
- /// \brief Return a StringRef to the source buffer data for the
+ /// Return a StringRef to the source buffer data for the
/// specified FileID.
StringRef getBufferData(bool *Invalid = nullptr) const;
- /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ /// Decompose the specified location into a raw FileID + Offset pair.
///
/// The first element is the FileID, the second is the offset from the
/// start of the buffer of the location.
@@ -389,12 +391,12 @@ public:
bool isInSystemHeader() const;
- /// \brief Determines the order of 2 source locations in the translation unit.
+ /// Determines the order of 2 source locations in the translation unit.
///
/// \returns true if this source location comes before 'Loc', false otherwise.
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
- /// \brief Determines the order of 2 source locations in the translation unit.
+ /// Determines the order of 2 source locations in the translation unit.
///
/// \returns true if this source location comes before 'Loc', false otherwise.
bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
@@ -403,44 +405,43 @@ public:
return isBeforeInTranslationUnitThan((SourceLocation)Loc);
}
- /// \brief Comparison function class, useful for sorting FullSourceLocs.
+ /// Comparison function class, useful for sorting FullSourceLocs.
struct BeforeThanCompare {
bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
return lhs.isBeforeInTranslationUnitThan(rhs);
}
};
- /// \brief Prints information about this FullSourceLoc to stderr.
+ /// Prints information about this FullSourceLoc to stderr.
///
/// This is useful for debugging.
void dump() const;
- friend inline bool
+ friend bool
operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
return LHS.getRawEncoding() == RHS.getRawEncoding() &&
LHS.SrcMgr == RHS.SrcMgr;
}
- friend inline bool
+ friend bool
operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
return !(LHS == RHS);
}
-
};
-
-
-} // end namespace clang
+} // namespace clang
namespace llvm {
+
/// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
/// DenseSets.
template <>
struct DenseMapInfo<clang::FileID> {
- static inline clang::FileID getEmptyKey() {
- return clang::FileID();
+ static clang::FileID getEmptyKey() {
+ return {};
}
- static inline clang::FileID getTombstoneKey() {
+
+ static clang::FileID getTombstoneKey() {
return clang::FileID::getSentinel();
}
@@ -452,7 +453,7 @@ namespace llvm {
return LHS == RHS;
}
};
-
+
template <>
struct isPodLike<clang::SourceLocation> { static const bool value = true; };
template <>
@@ -461,15 +462,17 @@ namespace llvm {
// Teach SmallPtrSet how to handle SourceLocation.
template<>
struct PointerLikeTypeTraits<clang::SourceLocation> {
- static inline void *getAsVoidPointer(clang::SourceLocation L) {
+ enum { NumLowBitsAvailable = 0 };
+
+ static void *getAsVoidPointer(clang::SourceLocation L) {
return L.getPtrEncoding();
}
- static inline clang::SourceLocation getFromVoidPointer(void *P) {
+
+ static clang::SourceLocation getFromVoidPointer(void *P) {
return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P);
}
- enum { NumLowBitsAvailable = 0 };
};
-} // end namespace llvm
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_BASIC_SOURCELOCATION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
index 397ad2e77fb5..af7dbbc13ca7 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the SourceManager interface.
+/// Defines the SourceManager interface.
///
/// There are three different types of locations in a %file: a spelling
/// location, an expansion location, and a presumed location.
@@ -35,6 +35,7 @@
#ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H
#define LLVM_CLANG_BASIC_SOURCEMANAGER_H
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
@@ -60,15 +61,14 @@ namespace clang {
class ASTReader;
class ASTWriter;
-class DiagnosticsEngine;
class LineTableInfo;
class SourceManager;
-/// \brief Public enums and private classes that are part of the
+/// 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,
+ /// Indicates whether a file or directory holds normal user code,
/// system code, or system code which is implicitly 'extern "C"' in C++ mode.
///
/// Entire directories can be tagged with this (this is maintained by
@@ -89,19 +89,19 @@ namespace SrcMgr {
return CK == C_User_ModuleMap || CK == C_System_ModuleMap;
}
- /// \brief One instance of this struct is kept for every file loaded or used.
+ /// One instance of this struct is kept for every file loaded or used.
///
/// This object owns the MemoryBuffer object.
- class LLVM_ALIGNAS(8) ContentCache {
+ class alignas(8) ContentCache {
enum CCFlags {
- /// \brief Whether the buffer is invalid.
+ /// Whether the buffer is invalid.
InvalidFlag = 0x01,
- /// \brief Whether the buffer should not be freed on destruction.
+ /// Whether the buffer should not be freed on destruction.
DoNotFreeFlag = 0x02
};
- /// \brief The actual buffer containing the characters from the input
+ /// The actual buffer containing the characters from the input
/// file.
///
/// This is owned by the ContentCache object. The bits indicate
@@ -109,7 +109,7 @@ namespace SrcMgr {
mutable llvm::PointerIntPair<llvm::MemoryBuffer *, 2> Buffer;
public:
- /// \brief Reference to the file entry representing this ContentCache.
+ /// Reference to the file entry representing this ContentCache.
///
/// This reference does not own the FileEntry object.
///
@@ -117,35 +117,35 @@ namespace SrcMgr {
/// an imaginary text buffer.
const FileEntry *OrigEntry;
- /// \brief References the file which the contents were actually loaded from.
+ /// References the file which the contents were actually loaded from.
///
/// Can be different from 'Entry' if we overridden the contents of one file
/// with the contents of another file.
const FileEntry *ContentsEntry;
- /// \brief A bump pointer allocated array of offsets for each source line.
+ /// A bump pointer allocated array of offsets for each source line.
///
/// This is lazily computed. This is owned by the SourceManager
/// BumpPointerAllocator object.
unsigned *SourceLineCache = nullptr;
- /// \brief The number of lines in this ContentCache.
+ /// The number of lines in this ContentCache.
///
/// This is only valid if SourceLineCache is non-null.
unsigned NumLines = 0;
- /// \brief Indicates whether the buffer itself was provided to override
+ /// Indicates whether the buffer itself was provided to override
/// the actual file contents.
///
/// When true, the original entry may be a virtual file that does not
/// exist.
unsigned BufferOverridden : 1;
- /// \brief True if this content cache was initially created for a source
+ /// True if this content cache was initially created for a source
/// file considered as a system one.
unsigned IsSystemFile : 1;
- /// \brief True if this file may be transient, that is, if it might not
+ /// True if this file may be transient, that is, if it might not
/// exist at some later point in time when this content entry is used,
/// after serialization and deserialization.
unsigned IsTransient : 1;
@@ -155,7 +155,7 @@ namespace SrcMgr {
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
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.
@@ -176,7 +176,7 @@ namespace SrcMgr {
~ContentCache();
- /// \brief Returns the memory buffer for the associated content.
+ /// Returns the memory buffer for the associated content.
///
/// \param Diag Object through which diagnostics will be emitted if the
/// buffer cannot be retrieved.
@@ -190,7 +190,7 @@ namespace SrcMgr {
SourceLocation Loc = SourceLocation(),
bool *Invalid = nullptr) const;
- /// \brief Returns the size of the content encapsulated by this
+ /// Returns the size of the content encapsulated by this
/// ContentCache.
///
/// This can be the size of the source file or the size of an
@@ -198,7 +198,7 @@ namespace SrcMgr {
/// file this size is retrieved from the file's FileEntry.
unsigned getSize() const;
- /// \brief Returns the number of bytes actually mapped for this
+ /// Returns the number of bytes actually mapped for this
/// ContentCache.
///
/// This can be 0 if the MemBuffer was not actually expanded.
@@ -208,20 +208,20 @@ namespace SrcMgr {
/// this content cache. This is used for performance analysis.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;
- /// \brief Get the underlying buffer, returning NULL if the buffer is not
+ /// Get the underlying buffer, returning NULL if the buffer is not
/// yet available.
llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); }
- /// \brief Replace the existing buffer (which will be deleted)
+ /// Replace the existing buffer (which will be deleted)
/// with the given buffer.
void replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree = false);
- /// \brief Determine whether the buffer itself is invalid.
+ /// Determine whether the buffer itself is invalid.
bool isBufferInvalid() const {
return Buffer.getInt() & InvalidFlag;
}
- /// \brief Determine whether the buffer should be freed.
+ /// Determine whether the buffer should be freed.
bool shouldFreeBuffer() const {
return (Buffer.getInt() & DoNotFreeFlag) == 0;
}
@@ -232,7 +232,7 @@ namespace SrcMgr {
static_assert(alignof(ContentCache) >= 8,
"ContentCache must be 8-byte aligned.");
- /// \brief Information about a FileID, basically just the logical file
+ /// Information about a FileID, basically just the logical file
/// that it represents and include stack information.
///
/// Each FileInfo has include stack information, indicating where it came
@@ -246,26 +246,26 @@ namespace SrcMgr {
friend class clang::ASTWriter;
friend class clang::ASTReader;
- /// \brief The location of the \#include that brought in this file.
+ /// The location of the \#include that brought in this file.
///
/// This is an invalid SLOC for the main file (top of the \#include chain).
unsigned IncludeLoc; // Really a SourceLocation
- /// \brief Number of FileIDs (files and macros) that were created during
+ /// Number of FileIDs (files and macros) that were created during
/// preprocessing of this \#include, including this SLocEntry.
///
/// Zero means the preprocessor didn't provide such info for this SLocEntry.
unsigned NumCreatedFIDs : 31;
- /// \brief Whether this FileInfo has any \#line directives.
+ /// Whether this FileInfo has any \#line directives.
unsigned HasLineDirectives : 1;
- /// \brief The content cache and the characteristic of the file.
+ /// The content cache and the characteristic of the file.
llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind>
ContentAndKind;
public:
- /// \brief Return a FileInfo object.
+ /// Return a FileInfo object.
static FileInfo get(SourceLocation IL, const ContentCache *Con,
CharacteristicKind FileCharacter) {
FileInfo X;
@@ -285,28 +285,28 @@ namespace SrcMgr {
return ContentAndKind.getPointer();
}
- /// \brief Return whether this is a system header or not.
+ /// Return whether this is a system header or not.
CharacteristicKind getFileCharacteristic() const {
return ContentAndKind.getInt();
}
- /// \brief Return true if this FileID has \#line directives in it.
+ /// Return true if this FileID has \#line directives in it.
bool hasLineDirectives() const { return HasLineDirectives; }
- /// \brief Set the flag that indicates that this FileID has
+ /// Set the flag that indicates that this FileID has
/// line table entries associated with it.
void setHasLineDirectives() {
HasLineDirectives = true;
}
};
- /// \brief Each ExpansionInfo encodes the expansion location - where
+ /// Each ExpansionInfo encodes the expansion location - where
/// the token was ultimately expanded, and the SpellingLoc - where the actual
/// character data for the token came from.
class ExpansionInfo {
// Really these are all SourceLocations.
- /// \brief Where the spelling for the token can be found.
+ /// Where the spelling for the token can be found.
unsigned SpellingLoc;
/// In a macro expansion, ExpansionLocStart and ExpansionLocEnd
@@ -317,9 +317,13 @@ namespace SrcMgr {
/// invalid location.
unsigned ExpansionLocStart, ExpansionLocEnd;
+ /// Whether the expansion range is a token range.
+ bool ExpansionIsTokenRange;
+
public:
SourceLocation getSpellingLoc() const {
- return SourceLocation::getFromRawEncoding(SpellingLoc);
+ SourceLocation SpellLoc = SourceLocation::getFromRawEncoding(SpellingLoc);
+ return SpellLoc.isInvalid() ? getExpansionLocStart() : SpellLoc;
}
SourceLocation getExpansionLocStart() const {
@@ -332,8 +336,14 @@ namespace SrcMgr {
return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc;
}
- std::pair<SourceLocation,SourceLocation> getExpansionLocRange() const {
- return std::make_pair(getExpansionLocStart(), getExpansionLocEnd());
+ bool isExpansionTokenRange() const {
+ return ExpansionIsTokenRange;
+ }
+
+ CharSourceRange getExpansionLocRange() const {
+ return CharSourceRange(
+ SourceRange(getExpansionLocStart(), getExpansionLocEnd()),
+ isExpansionTokenRange());
}
bool isMacroArgExpansion() const {
@@ -352,22 +362,24 @@ namespace SrcMgr {
getExpansionLocStart() != getExpansionLocEnd();
}
- /// \brief Return a ExpansionInfo for an expansion.
+ /// Return a ExpansionInfo for an expansion.
///
/// Start and End specify the expansion range (where the macro is
/// expanded), and SpellingLoc specifies the spelling location (where
/// the characters from the token come from). All three can refer to
/// normal File SLocs or expansion locations.
static ExpansionInfo create(SourceLocation SpellingLoc,
- SourceLocation Start, SourceLocation End) {
+ SourceLocation Start, SourceLocation End,
+ bool ExpansionIsTokenRange = true) {
ExpansionInfo X;
X.SpellingLoc = SpellingLoc.getRawEncoding();
X.ExpansionLocStart = Start.getRawEncoding();
X.ExpansionLocEnd = End.getRawEncoding();
+ X.ExpansionIsTokenRange = ExpansionIsTokenRange;
return X;
}
- /// \brief Return a special ExpansionInfo for the expansion of
+ /// Return a special ExpansionInfo for the expansion of
/// a macro argument into a function-like macro's body.
///
/// ExpansionLoc specifies the expansion location (where the macro is
@@ -389,13 +401,24 @@ namespace SrcMgr {
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc,
SourceLocation ExpansionLoc) {
// We store an intentionally invalid source location for the end of the
- // expansion range to mark that this is a macro argument ion rather than
- // a normal one.
+ // expansion range to mark that this is a macro argument location rather
+ // than a normal one.
return create(SpellingLoc, ExpansionLoc, SourceLocation());
}
+
+ /// Return a special ExpansionInfo representing a token that ends
+ /// prematurely. This is used to model a '>>' token that has been split
+ /// into '>' tokens and similar cases. Unlike for the other forms of
+ /// expansion, the expansion range in this case is a character range, not
+ /// a token range.
+ static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc,
+ SourceLocation Start,
+ SourceLocation End) {
+ return create(SpellingLoc, Start, End, false);
+ }
};
- /// \brief This is a discriminated union of FileInfo and ExpansionInfo.
+ /// This is a discriminated union of FileInfo and ExpansionInfo.
///
/// SourceManager keeps an array of these objects, and they are uniquely
/// identified by the FileID datatype.
@@ -446,44 +469,44 @@ namespace SrcMgr {
} // namespace SrcMgr
-/// \brief External source of source location entries.
+/// External source of source location entries.
class ExternalSLocEntrySource {
public:
virtual ~ExternalSLocEntrySource();
- /// \brief Read the source location entry with index ID, which will always be
+ /// Read the source location entry with index ID, which will always be
/// less than -1.
///
/// \returns true if an error occurred that prevented the source-location
/// entry from being loaded.
virtual bool ReadSLocEntry(int ID) = 0;
- /// \brief Retrieve the module import location and name for the given ID, if
+ /// Retrieve the module import location and name for the given ID, if
/// in fact it was loaded from a module (rather than, say, a precompiled
/// header).
virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0;
};
-/// \brief Holds the cache used by isBeforeInTranslationUnit.
+/// Holds the cache used by isBeforeInTranslationUnit.
///
/// The cache structure is complex enough to be worth breaking out of
/// SourceManager.
class InBeforeInTUCacheEntry {
- /// \brief The FileID's of the cached query.
+ /// The FileID's of the cached query.
///
/// If these match up with a subsequent query, the result can be reused.
FileID LQueryFID, RQueryFID;
- /// \brief True if LQueryFID was created before RQueryFID.
+ /// True if LQueryFID was created before RQueryFID.
///
/// This is used to compare macro expansion locations.
bool IsLQFIDBeforeRQFID;
- /// \brief The file found in common between the two \#include traces, i.e.,
+ /// The file found in common between the two \#include traces, i.e.,
/// the nearest common ancestor of the \#include tree.
FileID CommonFID;
- /// \brief The offset of the previous query in CommonFID.
+ /// The offset of the previous query in CommonFID.
///
/// Usually, this represents the location of the \#include for QueryFID, but
/// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a
@@ -491,7 +514,7 @@ class InBeforeInTUCacheEntry {
unsigned LCommonOffset, RCommonOffset;
public:
- /// \brief Return true if the currently cached values match up with
+ /// Return true if the currently cached values match up with
/// the specified LHS/RHS query.
///
/// If not, we can't use the cache.
@@ -499,7 +522,7 @@ public:
return LQueryFID == LHS && RQueryFID == RHS;
}
- /// \brief If the cache is valid, compute the result given the
+ /// If the cache is valid, compute the result given the
/// specified offsets in the LHS/RHS FileID's.
bool getCachedResult(unsigned LOffset, unsigned ROffset) const {
// If one of the query files is the common file, use the offset. Otherwise,
@@ -518,7 +541,7 @@ public:
return LOffset < ROffset;
}
- /// \brief Set up a new query.
+ /// Set up a new query.
void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) {
assert(LHS != RHS);
LQueryFID = LHS;
@@ -539,12 +562,12 @@ public:
}
};
-/// \brief The stack used when building modules on demand, which is used
+/// The stack used when building modules on demand, which is used
/// to provide a link between the source managers of the different compiler
/// instances.
using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>;
-/// \brief This class handles loading and caching of source files into memory.
+/// This class handles loading and caching of source files into memory.
///
/// This object owns the MemoryBuffer objects for all of the loaded
/// files and assigns unique FileID's for each unique \#include chain.
@@ -557,14 +580,14 @@ using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>;
/// where the expanded token came from and the expansion location specifies
/// where it was expanded.
class SourceManager : public RefCountedBase<SourceManager> {
- /// \brief DiagnosticsEngine object.
+ /// DiagnosticsEngine object.
DiagnosticsEngine &Diag;
FileManager &FileMgr;
mutable llvm::BumpPtrAllocator ContentCacheAlloc;
- /// \brief Memoized information about all of the files tracked by this
+ /// Memoized information about all of the files tracked by this
/// SourceManager.
///
/// This map allows us to merge ContentCache entries based
@@ -572,29 +595,29 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// non-null, FileEntry pointers.
llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
- /// \brief True if the ContentCache for files that are overridden by other
+ /// True if the ContentCache for files that are overridden by other
/// files, should report the original file name. Defaults to true.
bool OverridenFilesKeepOriginalName = true;
- /// \brief True if non-system source files should be treated as volatile
+ /// True if non-system source files should be treated as volatile
/// (likely to change while trying to use them). Defaults to false.
bool UserFilesAreVolatile;
- /// \brief True if all files read during this compilation should be treated
+ /// 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 = false;
struct OverriddenFilesInfoTy {
- /// \brief Files that have been overridden with the contents from another
+ /// 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.
+ /// Files that were overridden with a memory buffer.
llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
};
- /// \brief Lazily create the object keeping overridden files info, since
+ /// Lazily create the object keeping overridden files info, since
/// it is uncommonly used.
std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo;
@@ -604,77 +627,77 @@ class SourceManager : public RefCountedBase<SourceManager> {
return *OverriddenFilesInfo;
}
- /// \brief Information about various memory buffers that we have read in.
+ /// Information about various memory buffers that we have read in.
///
/// All FileEntry* within the stored ContentCache objects are NULL,
/// as they do not refer to a file.
std::vector<SrcMgr::ContentCache*> MemBufferInfos;
- /// \brief The table of SLocEntries that are local to this module.
+ /// The table of SLocEntries that are local to this module.
///
/// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid
/// expansion.
SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable;
- /// \brief The table of SLocEntries that are loaded from other modules.
+ /// The table of SLocEntries that are loaded from other modules.
///
/// Negative FileIDs are indexes into this table. To get from ID to an index,
/// use (-ID - 2).
mutable SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable;
- /// \brief The starting offset of the next local SLocEntry.
+ /// The starting offset of the next local SLocEntry.
///
/// This is LocalSLocEntryTable.back().Offset + the size of that entry.
unsigned NextLocalOffset;
- /// \brief The starting offset of the latest batch of loaded SLocEntries.
+ /// The starting offset of the latest batch of loaded SLocEntries.
///
/// This is LoadedSLocEntryTable.back().Offset, except that that entry might
/// not have been loaded, so that value would be unknown.
unsigned CurrentLoadedOffset;
- /// \brief The highest possible offset is 2^31-1, so CurrentLoadedOffset
+ /// The highest possible offset is 2^31-1, so CurrentLoadedOffset
/// starts at 2^31.
static const unsigned MaxLoadedOffset = 1U << 31U;
- /// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable
+ /// A bitmap that indicates whether the entries of LoadedSLocEntryTable
/// have already been loaded from the external source.
///
/// Same indexing as LoadedSLocEntryTable.
llvm::BitVector SLocEntryLoaded;
- /// \brief An external source for source location entries.
+ /// An external source for source location entries.
ExternalSLocEntrySource *ExternalSLocEntries = nullptr;
- /// \brief A one-entry cache to speed up getFileID.
+ /// A one-entry cache to speed up getFileID.
///
/// LastFileIDLookup records the last FileID looked up or created, because it
/// is very common to look up many tokens from the same file.
mutable FileID LastFileIDLookup;
- /// \brief Holds information for \#line directives.
+ /// Holds information for \#line directives.
///
/// This is referenced by indices from SLocEntryTable.
LineTableInfo *LineTable = nullptr;
- /// \brief These ivars serve as a cache used in the getLineNumber
+ /// These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
mutable FileID LastLineNoFileIDQuery;
mutable SrcMgr::ContentCache *LastLineNoContentCache;
mutable unsigned LastLineNoFilePos;
mutable unsigned LastLineNoResult;
- /// \brief The file ID for the main source file of the translation unit.
+ /// The file ID for the main source file of the translation unit.
FileID MainFileID;
- /// \brief The file ID for the precompiled preamble there is one.
+ /// The file ID for the precompiled preamble there is one.
FileID PreambleFileID;
// Statistics for -print-stats.
mutable unsigned NumLinearScans = 0;
mutable unsigned NumBinaryProbes = 0;
- /// \brief Associates a FileID with its "included/expanded in" decomposed
+ /// Associates a FileID with its "included/expanded in" decomposed
/// location.
///
/// Used to cache results from and speed-up \c getDecomposedIncludedLoc
@@ -702,14 +725,14 @@ class SourceManager : public RefCountedBase<SourceManager> {
mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery;
- /// \brief Lazily computed map of macro argument chunks to their expanded
+ /// Lazily computed map of macro argument chunks to their expanded
/// source location.
using MacroArgsMap = std::map<unsigned, SourceLocation>;
mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>>
MacroArgsCacheMap;
- /// \brief The stack of modules being built, which is used to detect
+ /// The stack of modules being built, which is used to detect
/// cycles in the module dependency graph as modules are being built, as
/// well as to describe why we're rebuilding a particular module.
///
@@ -735,29 +758,29 @@ public:
FileManager &getFileManager() const { return FileMgr; }
- /// \brief Set true if the SourceManager should report the original file name
+ /// Set true if the SourceManager should report the original file name
/// for contents of files that were overridden by other files. Defaults to
/// true.
void setOverridenFilesKeepOriginalName(bool value) {
OverridenFilesKeepOriginalName = value;
}
- /// \brief True if non-system source files should be treated as volatile
+ /// True if non-system source files should be treated as volatile
/// (likely to change while trying to use them).
bool userFilesAreVolatile() const { return UserFilesAreVolatile; }
- /// \brief Retrieve the module build stack.
+ /// Retrieve the module build stack.
ModuleBuildStack getModuleBuildStack() const {
return StoredModuleBuildStack;
}
- /// \brief Set the module build stack.
+ /// Set the module build stack.
void setModuleBuildStack(ModuleBuildStack stack) {
StoredModuleBuildStack.clear();
StoredModuleBuildStack.append(stack.begin(), stack.end());
}
- /// \brief Push an entry to the module build stack.
+ /// Push an entry to the module build stack.
void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) {
StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc));
}
@@ -766,28 +789,28 @@ public:
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
- /// \brief Returns the FileID of the main source file.
+ /// Returns the FileID of the main source file.
FileID getMainFileID() const { return MainFileID; }
- /// \brief Set the file ID for the main source file.
+ /// Set the file ID for the main source file.
void setMainFileID(FileID FID) {
MainFileID = FID;
}
- /// \brief Set the file ID for the precompiled preamble.
+ /// Set the file ID for the precompiled preamble.
void setPreambleFileID(FileID Preamble) {
assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
PreambleFileID = Preamble;
}
- /// \brief Get the file ID for the precompiled preamble if there is one.
+ /// Get the file ID for the precompiled preamble if there is one.
FileID getPreambleFileID() const { return PreambleFileID; }
//===--------------------------------------------------------------------===//
// Methods to create new FileID's and macro expansions.
//===--------------------------------------------------------------------===//
- /// \brief Create a new FileID that represents the specified file
+ /// Create a new FileID that represents the specified file
/// being \#included from the specified IncludePosition.
///
/// This translates NULL into standard input.
@@ -800,7 +823,7 @@ public:
return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
}
- /// \brief Create a new FileID that represents the specified memory buffer.
+ /// 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.
@@ -815,7 +838,7 @@ public:
enum UnownedTag { Unowned };
- /// \brief Create a new FileID that represents the specified memory buffer.
+ /// 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.
@@ -827,7 +850,7 @@ public:
IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
}
- /// \brief Get the FileID for \p SourceFile if it exists. Otherwise, create a
+ /// Get the FileID for \p SourceFile if it exists. Otherwise, create a
/// new FileID for the \p SourceFile.
FileID getOrCreateFileID(const FileEntry *SourceFile,
SrcMgr::CharacteristicKind FileCharacter) {
@@ -836,7 +859,7 @@ public:
FileCharacter);
}
- /// \brief Return a new SourceLocation that encodes the
+ /// Return a new SourceLocation that encodes the
/// fact that a token from SpellingLoc should actually be referenced from
/// ExpansionLoc, and that it represents the expansion of a macro argument
/// into the function-like macro body.
@@ -844,24 +867,31 @@ public:
SourceLocation ExpansionLoc,
unsigned TokLength);
- /// \brief Return a new SourceLocation that encodes the fact
+ /// Return a new SourceLocation that encodes the fact
/// that a token from SpellingLoc should actually be referenced from
/// ExpansionLoc.
SourceLocation createExpansionLoc(SourceLocation Loc,
SourceLocation ExpansionLocStart,
SourceLocation ExpansionLocEnd,
unsigned TokLength,
+ bool ExpansionIsTokenRange = true,
int LoadedID = 0,
unsigned LoadedOffset = 0);
- /// \brief Retrieve the memory buffer associated with the given file.
+ /// Return a new SourceLocation that encodes that the token starting
+ /// at \p TokenStart ends prematurely at \p TokenEnd.
+ SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc,
+ SourceLocation TokenStart,
+ SourceLocation TokenEnd);
+
+ /// Retrieve the memory buffer associated with the given file.
///
/// \param Invalid If non-NULL, will be set \c true if an error
/// occurs while retrieving the memory buffer.
llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
bool *Invalid = nullptr);
- /// \brief Override the contents of the given source file by providing an
+ /// Override the contents of the given source file by providing an
/// already-allocated buffer.
///
/// \param SourceFile the source file whose contents will be overridden.
@@ -878,7 +908,7 @@ public:
overrideFileContents(SourceFile, Buffer.release(), /*DoNotFree*/ false);
}
- /// \brief Override the given source file with another one.
+ /// Override the given source file with another one.
///
/// \param SourceFile the source file which will be overridden.
///
@@ -887,7 +917,7 @@ public:
void overrideFileContents(const FileEntry *SourceFile,
const FileEntry *NewFile);
- /// \brief Returns true if the file contents have been overridden.
+ /// Returns true if the file contents have been overridden.
bool isFileOverridden(const FileEntry *File) const {
if (OverriddenFilesInfo) {
if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File))
@@ -899,16 +929,16 @@ public:
return false;
}
- /// \brief Disable overridding the contents of a file, previously enabled
+ /// Disable overridding the contents of a file, previously enabled
/// with #overrideFileContents.
///
/// This should be called before parsing has begun.
void disableFileContentsOverride(const FileEntry *File);
- /// \brief Specify that a file is transient.
+ /// Specify that a file is transient.
void setFileIsTransient(const FileEntry *SourceFile);
- /// \brief Specify that all files that are read during this compilation are
+ /// Specify that all files that are read during this compilation are
/// transient.
void setAllFilesAreTransient(bool Transient) {
FilesAreTransient = Transient;
@@ -918,7 +948,7 @@ public:
// FileID manipulation methods.
//===--------------------------------------------------------------------===//
- /// \brief Return the buffer for the specified FileID.
+ /// Return the buffer for the specified FileID.
///
/// If there is an error opening this buffer the first time, this
/// manufactures a temporary buffer and returns a non-empty error string.
@@ -952,7 +982,7 @@ public:
Invalid);
}
- /// \brief Returns the FileEntry record for the provided FileID.
+ /// Returns the FileEntry record for the provided FileID.
const FileEntry *getFileEntryForID(FileID FID) const {
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
@@ -965,7 +995,7 @@ public:
return Content->OrigEntry;
}
- /// \brief Returns the FileEntry record for the provided SLocEntry.
+ /// Returns the FileEntry record for the provided SLocEntry.
const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
{
const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache();
@@ -974,14 +1004,14 @@ public:
return Content->OrigEntry;
}
- /// \brief Return a StringRef to the source buffer data for the
+ /// Return a StringRef to the source buffer data for the
/// specified FileID.
///
/// \param FID The file ID whose contents will be returned.
/// \param Invalid If non-NULL, will be set true if an error occurred.
StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const;
- /// \brief Get the number of FileIDs (files and macros) that were created
+ /// Get the number of FileIDs (files and macros) that were created
/// during preprocessing of \p FID, including it.
unsigned getNumCreatedFIDsForFileID(FileID FID) const {
bool Invalid = false;
@@ -992,7 +1022,7 @@ public:
return Entry.getFile().NumCreatedFIDs;
}
- /// \brief Set the number of FileIDs (files and macros) that were created
+ /// Set the number of FileIDs (files and macros) that were created
/// during preprocessing of \p FID, including it.
void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const {
bool Invalid = false;
@@ -1008,7 +1038,7 @@ public:
// SourceLocation manipulation methods.
//===--------------------------------------------------------------------===//
- /// \brief Return the FileID for a SourceLocation.
+ /// Return the FileID for a SourceLocation.
///
/// This is a very hot method that is used for all SourceManager queries
/// that start with a SourceLocation object. It is responsible for finding
@@ -1024,14 +1054,14 @@ public:
return getFileIDSlow(SLocOffset);
}
- /// \brief Return the filename of the file containing a SourceLocation.
+ /// Return the filename of the file containing a SourceLocation.
StringRef getFilename(SourceLocation SpellingLoc) const {
if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
return F->getName();
return StringRef();
}
- /// \brief Return the source location corresponding to the first byte of
+ /// Return the source location corresponding to the first byte of
/// the specified file.
SourceLocation getLocForStartOfFile(FileID FID) const {
bool Invalid = false;
@@ -1042,20 +1072,20 @@ public:
unsigned FileOffset = Entry.getOffset();
return SourceLocation::getFileLoc(FileOffset);
}
-
- /// \brief Return the source location corresponding to the last byte of the
+
+ /// Return the source location corresponding to the last byte of the
/// specified file.
SourceLocation getLocForEndOfFile(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid || !Entry.isFile())
return SourceLocation();
-
+
unsigned FileOffset = Entry.getOffset();
return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID));
}
- /// \brief Returns the include location if \p FID is a \#include'd file
+ /// Returns the include location if \p FID is a \#include'd file
/// otherwise it returns an invalid location.
SourceLocation getIncludeLoc(FileID FID) const {
bool Invalid = false;
@@ -1066,7 +1096,7 @@ public:
return Entry.getFile().getIncludeLoc();
}
- // \brief Returns the import location if the given source location is
+ // Returns the import location if the given source location is
// located within a module, or an invalid location if the source location
// is within the current translation unit.
std::pair<SourceLocation, StringRef>
@@ -1081,7 +1111,7 @@ public:
return ExternalSLocEntries->getModuleImportLoc(FID.ID);
}
- /// \brief Given a SourceLocation object \p Loc, return the expansion
+ /// Given a SourceLocation object \p Loc, return the expansion
/// location referenced by the ID.
SourceLocation getExpansionLoc(SourceLocation Loc) const {
// Handle the non-mapped case inline, defer to out of line code to handle
@@ -1090,7 +1120,7 @@ public:
return getExpansionLocSlowCase(Loc);
}
- /// \brief Given \p Loc, if it is a macro location return the expansion
+ /// Given \p Loc, if it is a macro location return the expansion
/// location or the spelling location, depending on if it comes from a
/// macro argument or not.
SourceLocation getFileLoc(SourceLocation Loc) const {
@@ -1098,26 +1128,35 @@ public:
return getFileLocSlowCase(Loc);
}
- /// \brief Return the start/end of the expansion information for an
+ /// Return the start/end of the expansion information for an
/// expansion location.
///
/// \pre \p Loc is required to be an expansion location.
- std::pair<SourceLocation,SourceLocation>
- getImmediateExpansionRange(SourceLocation Loc) const;
+ CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const;
- /// \brief Given a SourceLocation object, return the range of
+ /// Given a SourceLocation object, return the range of
/// tokens covered by the expansion in the ultimate file.
- std::pair<SourceLocation,SourceLocation>
- getExpansionRange(SourceLocation Loc) const;
+ CharSourceRange getExpansionRange(SourceLocation Loc) const;
- /// \brief Given a SourceRange object, return the range of
- /// tokens covered by the expansion in the ultimate file.
- SourceRange getExpansionRange(SourceRange Range) const {
- return SourceRange(getExpansionRange(Range.getBegin()).first,
- getExpansionRange(Range.getEnd()).second);
+ /// Given a SourceRange object, return the range of
+ /// tokens or characters covered by the expansion in the ultimate file.
+ CharSourceRange getExpansionRange(SourceRange Range) const {
+ SourceLocation Begin = getExpansionRange(Range.getBegin()).getBegin();
+ CharSourceRange End = getExpansionRange(Range.getEnd());
+ return CharSourceRange(SourceRange(Begin, End.getEnd()),
+ End.isTokenRange());
}
- /// \brief Given a SourceLocation object, return the spelling
+ /// Given a CharSourceRange object, return the range of
+ /// tokens or characters covered by the expansion in the ultimate file.
+ CharSourceRange getExpansionRange(CharSourceRange Range) const {
+ CharSourceRange Expansion = getExpansionRange(Range.getAsRange());
+ if (Expansion.getEnd() == Range.getEnd())
+ Expansion.setTokenRange(Range.isTokenRange());
+ return Expansion;
+ }
+
+ /// Given a SourceLocation object, return the spelling
/// location referenced by the ID.
///
/// This is the place where the characters that make up the lexed token
@@ -1129,7 +1168,7 @@ public:
return getSpellingLocSlowCase(Loc);
}
- /// \brief Given a SourceLocation object, return the spelling location
+ /// Given a SourceLocation object, return the spelling location
/// referenced by the ID.
///
/// This is the first level down towards the place where the characters
@@ -1137,7 +1176,19 @@ public:
/// be used by clients.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;
- /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ /// Form a SourceLocation from a FileID and Offset pair.
+ SourceLocation getComposedLoc(FileID FID, unsigned Offset) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return SourceLocation();
+
+ unsigned GlobalOffset = Entry.getOffset() + Offset;
+ return Entry.isFile() ? SourceLocation::getFileLoc(GlobalOffset)
+ : SourceLocation::getMacroLoc(GlobalOffset);
+ }
+
+ /// Decompose the specified location into a raw FileID + Offset pair.
///
/// The first element is the FileID, the second is the offset from the
/// start of the buffer of the location.
@@ -1150,7 +1201,7 @@ public:
return std::make_pair(FID, Loc.getOffset()-E.getOffset());
}
- /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ /// Decompose the specified location into a raw FileID + Offset pair.
///
/// If the location is an expansion record, walk through it until we find
/// the final location expanded.
@@ -1169,7 +1220,7 @@ public:
return getDecomposedExpansionLocSlowCase(E);
}
- /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ /// Decompose the specified location into a raw FileID + Offset pair.
///
/// If the location is an expansion record, walk through it until we find
/// its spelling record.
@@ -1187,11 +1238,11 @@ public:
return getDecomposedSpellingLocSlowCase(E, Offset);
}
- /// \brief Returns the "included/expanded in" decomposed location of the given
+ /// Returns the "included/expanded in" decomposed location of the given
/// FileID.
std::pair<FileID, unsigned> getDecomposedIncludedLoc(FileID FID) const;
- /// \brief Returns the offset from the start of the file that the
+ /// Returns the offset from the start of the file that the
/// specified SourceLocation represents.
///
/// This is not very meaningful for a macro ID.
@@ -1199,7 +1250,7 @@ public:
return getDecomposedLoc(SpellingLoc).second;
}
- /// \brief Tests whether the given source location represents a macro
+ /// Tests whether the given source location represents a macro
/// argument's expansion into the function-like macro definition.
///
/// \param StartLoc If non-null and function returns true, it is set to the
@@ -1211,14 +1262,14 @@ public:
bool isMacroArgExpansion(SourceLocation Loc,
SourceLocation *StartLoc = nullptr) const;
- /// \brief Tests whether the given source location represents the expansion of
+ /// Tests whether the given source location represents the expansion of
/// a macro body.
///
/// This is equivalent to testing whether the location is part of a macro
/// expansion but not the expansion of an argument to a function-like macro.
bool isMacroBodyExpansion(SourceLocation Loc) const;
- /// \brief Returns true if the given MacroID location points at the beginning
+ /// Returns true if the given MacroID location points at the beginning
/// of the immediate macro expansion.
///
/// \param MacroBegin If non-null and function returns true, it is set to the
@@ -1226,7 +1277,7 @@ public:
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
SourceLocation *MacroBegin = nullptr) const;
- /// \brief Returns true if the given MacroID location points at the character
+ /// Returns true if the given MacroID location points at the character
/// end of the immediate macro expansion.
///
/// \param MacroEnd If non-null and function returns true, it is set to the
@@ -1235,7 +1286,7 @@ public:
isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
SourceLocation *MacroEnd = nullptr) const;
- /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length)
+ /// Returns true if \p Loc is inside the [\p Start, +\p Length)
/// chunk of the source location address space.
///
/// If it's true and \p RelativeOffset is non-null, it will be set to the
@@ -1260,7 +1311,7 @@ public:
return false;
}
- /// \brief Return true if both \p LHS and \p RHS are in the local source
+ /// Return true if both \p LHS and \p RHS are in the local source
/// location address space or the loaded one.
///
/// If it's true and \p RelativeOffset is non-null, it will be set to the
@@ -1284,14 +1335,14 @@ public:
// Queries about the code at a SourceLocation.
//===--------------------------------------------------------------------===//
- /// \brief Return a pointer to the start of the specified location
+ /// Return a pointer to the start of the specified location
/// in the appropriate spelling MemoryBuffer.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
const char *getCharacterData(SourceLocation SL,
bool *Invalid = nullptr) const;
- /// \brief Return the column # for the specified file position.
+ /// Return the column # for the specified file position.
///
/// This is significantly cheaper to compute than the line number. This
/// returns zero if the column number isn't known. This may only be called
@@ -1306,7 +1357,7 @@ public:
unsigned getPresumedColumnNumber(SourceLocation Loc,
bool *Invalid = nullptr) const;
- /// \brief Given a SourceLocation, return the spelling line number
+ /// Given a SourceLocation, return the spelling line number
/// for the position indicated.
///
/// This requires building and caching a table of line offsets for the
@@ -1317,14 +1368,14 @@ public:
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
- /// \brief Return the filename or buffer identifier of the buffer the
+ /// Return the filename or buffer identifier of the buffer the
/// location is in.
///
/// Note that this name does not respect \#line directives. Use
/// getPresumedLoc for normal clients.
StringRef getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const;
- /// \brief Return the file characteristic of the specified source
+ /// Return the file characteristic of the specified source
/// location, indicating whether this is a normal file, a system
/// header, or an "implicit extern C" system header.
///
@@ -1336,7 +1387,7 @@ public:
/// considered to be from a system header.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;
- /// \brief Returns the "presumed" location of a SourceLocation specifies.
+ /// Returns the "presumed" location of a SourceLocation specifies.
///
/// A "presumed location" can be modified by \#line or GNU line marker
/// directives. This provides a view on the data that a user should see
@@ -1352,7 +1403,7 @@ public:
PresumedLoc getPresumedLoc(SourceLocation Loc,
bool UseLineDirectives = true) const;
- /// \brief Returns whether the PresumedLoc for a given SourceLocation is
+ /// Returns whether the PresumedLoc for a given SourceLocation is
/// in the main file.
///
/// This computes the "presumed" location for a SourceLocation, then checks
@@ -1361,7 +1412,7 @@ public:
/// account.
bool isInMainFile(SourceLocation Loc) const;
- /// \brief Returns true if the spelling locations for both SourceLocations
+ /// Returns true if the spelling locations for both SourceLocations
/// are part of the same file buffer.
///
/// This check ignores line marker directives.
@@ -1369,7 +1420,7 @@ public:
return getFileID(Loc1) == getFileID(Loc2);
}
- /// \brief Returns true if the spelling location for the given location
+ /// Returns true if the spelling location for the given location
/// is in the main file buffer.
///
/// This check ignores line marker directives.
@@ -1377,25 +1428,25 @@ public:
return getFileID(Loc) == getMainFileID();
}
- /// \brief Returns if a SourceLocation is in a system header.
+ /// Returns if a SourceLocation is in a system header.
bool isInSystemHeader(SourceLocation Loc) const {
return isSystem(getFileCharacteristic(Loc));
}
- /// \brief Returns if a SourceLocation is in an "extern C" system header.
+ /// Returns if a SourceLocation is in an "extern C" system header.
bool isInExternCSystemHeader(SourceLocation Loc) const {
return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
}
- /// \brief Returns whether \p Loc is expanded from a macro in a system header.
+ /// Returns whether \p Loc is expanded from a macro in a system header.
bool isInSystemMacro(SourceLocation loc) const {
return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc));
}
- /// \brief The size of the SLocEntry that \p FID represents.
+ /// The size of the SLocEntry that \p FID represents.
unsigned getFileIDSize(FileID FID) const;
- /// \brief Given a specific FileID, returns true if \p Loc is inside that
+ /// Given a specific FileID, returns true if \p Loc is inside that
/// FileID chunk and sets relative offset (offset of \p Loc from beginning
/// of FileID) to \p relativeOffset.
bool isInFileID(SourceLocation Loc, FileID FID,
@@ -1414,10 +1465,10 @@ public:
// Line Table Manipulation Routines
//===--------------------------------------------------------------------===//
- /// \brief Return the uniqued ID for the specified filename.
+ /// 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
+ /// Add a line note to the line table for the FileID and offset
/// specified by Loc.
///
/// If FilenameID is -1, it is considered to be unspecified.
@@ -1425,17 +1476,17 @@ public:
bool IsFileEntry, bool IsFileExit,
SrcMgr::CharacteristicKind FileKind);
- /// \brief Determine if the source manager has a line table.
+ /// Determine if the source manager has a line table.
bool hasLineTable() const { return LineTable != nullptr; }
- /// \brief Retrieve the stored line table.
+ /// Retrieve the stored line table.
LineTableInfo &getLineTable();
//===--------------------------------------------------------------------===//
// Queries for performance analysis.
//===--------------------------------------------------------------------===//
- /// \brief Return the total amount of physical memory allocated by the
+ /// Return the total amount of physical memory allocated by the
/// ContentCache allocator.
size_t getContentCacheSize() const {
return ContentCacheAlloc.getTotalMemory();
@@ -1449,11 +1500,11 @@ public:
: malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
- /// \brief Return the amount of memory used by memory buffers, breaking down
+ /// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
MemoryBufferSizes getMemoryBufferSizes() const;
- /// \brief Return the amount of memory used for various side tables and
+ /// Return the amount of memory used for various side tables and
/// data structures in the SourceManager.
size_t getDataStructureSizes() const;
@@ -1461,25 +1512,25 @@ public:
// Other miscellaneous methods.
//===--------------------------------------------------------------------===//
- /// \brief Get the source location for the given file:line:col triplet.
+ /// Get the source location for the given file:line:col triplet.
///
/// If the source file is included multiple times, the source location will
/// be based upon the first inclusion.
SourceLocation translateFileLineCol(const FileEntry *SourceFile,
unsigned Line, unsigned Col) const;
- /// \brief Get the FileID for the given file.
+ /// Get the FileID for the given file.
///
/// If the source file is included multiple times, the FileID will be the
/// first inclusion.
FileID translateFile(const FileEntry *SourceFile) const;
- /// \brief Get the source location in \p FID for the given line:col.
+ /// Get the source location in \p FID for the given line:col.
/// Returns null location if \p FID is not a file SLocEntry.
SourceLocation translateLineCol(FileID FID,
unsigned Line, unsigned Col) const;
- /// \brief If \p Loc points inside a function macro argument, the returned
+ /// If \p Loc points inside a function macro argument, the returned
/// location will be the macro location in which the argument was expanded.
/// If a macro argument is used multiple times, the expanded location will
/// be at the first expansion of the argument.
@@ -1490,12 +1541,12 @@ public:
/// where 'foo' was expanded into.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const;
- /// \brief Determines the order of 2 source locations in the translation unit.
+ /// Determines the order of 2 source locations in the translation unit.
///
/// \returns true if LHS source location comes before RHS, false otherwise.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
- /// \brief Determines whether the two decomposed source location is in the
+ /// Determines whether the two decomposed source location is in the
/// same translation unit. As a byproduct, it also calculates the order
/// of the source locations in case they are in the same TU.
///
@@ -1506,13 +1557,13 @@ public:
isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs,
std::pair<FileID, unsigned> &ROffs) const;
- /// \brief Determines the order of 2 source locations in the "source location
+ /// Determines the order of 2 source locations in the "source location
/// address space".
bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
return isBeforeInSLocAddrSpace(LHS, RHS.getOffset());
}
- /// \brief Determines the order of a source location and a source location
+ /// Determines the order of a source location and a source location
/// offset in the "source location address space".
///
/// Note that we always consider source locations loaded from
@@ -1544,25 +1595,25 @@ public:
return FileInfos.find(File) != FileInfos.end();
}
- /// \brief Print statistics to stderr.
+ /// Print statistics to stderr.
void PrintStats() const;
void dump() const;
- /// \brief Get the number of local SLocEntries we have.
+ /// Get the number of local SLocEntries we have.
unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }
- /// \brief Get a local SLocEntry. This is exposed for indexing.
+ /// Get a local SLocEntry. This is exposed for indexing.
const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index,
bool *Invalid = nullptr) const {
assert(Index < LocalSLocEntryTable.size() && "Invalid index");
return LocalSLocEntryTable[Index];
}
- /// \brief Get the number of loaded SLocEntries we have.
+ /// Get the number of loaded SLocEntries we have.
unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();}
- /// \brief Get a loaded SLocEntry. This is exposed for indexing.
+ /// Get a loaded SLocEntry. This is exposed for indexing.
const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index,
bool *Invalid = nullptr) const {
assert(Index < LoadedSLocEntryTable.size() && "Invalid index");
@@ -1588,7 +1639,7 @@ public:
ExternalSLocEntries = Source;
}
- /// \brief Allocate a number of loaded SLocEntries, which will be actually
+ /// Allocate a number of loaded SLocEntries, which will be actually
/// loaded on demand from the external source.
///
/// NumSLocEntries will be allocated, which occupy a total of TotalSize space
@@ -1597,23 +1648,23 @@ public:
std::pair<int, unsigned>
AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize);
- /// \brief Returns true if \p Loc came from a PCH/Module.
+ /// Returns true if \p Loc came from a PCH/Module.
bool isLoadedSourceLocation(SourceLocation Loc) const {
return Loc.getOffset() >= CurrentLoadedOffset;
}
- /// \brief Returns true if \p Loc did not come from a PCH/Module.
+ /// Returns true if \p Loc did not come from a PCH/Module.
bool isLocalSourceLocation(SourceLocation Loc) const {
return Loc.getOffset() < NextLocalOffset;
}
- /// \brief Returns true if \p FID came from a PCH/Module.
+ /// Returns true if \p FID came from a PCH/Module.
bool isLoadedFileID(FileID FID) const {
assert(FID.ID != -1 && "Using FileID sentinel value");
return FID.ID < 0;
}
- /// \brief Returns true if \p FID did not come from a PCH/Module.
+ /// Returns true if \p FID did not come from a PCH/Module.
bool isLocalFileID(FileID FID) const {
return !isLoadedFileID(FID);
}
@@ -1631,9 +1682,12 @@ public:
// Otherwise, the caller of the macro is located where this macro is
// expanded (while the spelling is part of the macro definition).
- return getImmediateExpansionRange(Loc).first;
+ return getImmediateExpansionRange(Loc).getBegin();
}
+ /// \return Location of the top-level macro caller.
+ SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const;
+
private:
friend class ASTReader;
friend class ASTWriter;
@@ -1643,7 +1697,7 @@ private:
const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const;
- /// \brief Get the entry with the given unwrapped FileID.
+ /// Get the entry with the given unwrapped FileID.
const SrcMgr::SLocEntry &getSLocEntryByID(int ID,
bool *Invalid = nullptr) const {
assert(ID != -1 && "Using FileID sentinel value");
@@ -1664,7 +1718,7 @@ private:
int LoadedID = 0,
unsigned LoadedOffset = 0);
- /// \brief Return true if the specified FileID contains the
+ /// Return true if the specified FileID contains the
/// specified SourceLocation offset. This is a very hot method.
inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const {
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
@@ -1684,15 +1738,15 @@ private:
return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset();
}
- /// \brief Returns the previous in-order FileID or an invalid FileID if there
+ /// Returns the previous in-order FileID or an invalid FileID if there
/// is no previous one.
FileID getPreviousFileID(FileID FID) const;
- /// \brief Returns the next in-order FileID or an invalid FileID if there is
+ /// Returns the next in-order FileID or an invalid FileID if there is
/// no next one.
FileID getNextFileID(FileID FID) const;
- /// \brief Create a new fileID for the specified ContentCache and
+ /// Create a new fileID for the specified ContentCache and
/// include position.
///
/// This works regardless of whether the ContentCache corresponds to a
@@ -1706,7 +1760,7 @@ private:
getOrCreateContentCache(const FileEntry *SourceFile,
bool isSystemFile = false);
- /// \brief Create a new ContentCache for the specified memory buffer.
+ /// Create a new ContentCache for the specified memory buffer.
const SrcMgr::ContentCache *
createMemBufferContentCache(llvm::MemoryBuffer *Buf, bool DoNotFree);
@@ -1731,11 +1785,11 @@ private:
unsigned ExpansionLength) const;
};
-/// \brief Comparison function object.
+/// Comparison function object.
template<typename T>
class BeforeThanCompare;
-/// \brief Compare two source locations.
+/// Compare two source locations.
template<>
class BeforeThanCompare<SourceLocation> {
SourceManager &SM;
@@ -1748,7 +1802,7 @@ public:
}
};
-/// \brief Compare two non-overlapping source ranges.
+/// Compare two non-overlapping source ranges.
template<>
class BeforeThanCompare<SourceRange> {
SourceManager &SM;
@@ -1761,6 +1815,28 @@ public:
}
};
+/// SourceManager and necessary depdencies (e.g. VFS, FileManager) for a single
+/// in-memorty file.
+class SourceManagerForFile {
+public:
+ /// Creates SourceManager and necessary depdencies (e.g. VFS, FileManager).
+ /// The main file in the SourceManager will be \p FileName with \p Content.
+ SourceManagerForFile(StringRef FileName, StringRef Content);
+
+ SourceManager &get() {
+ assert(SourceMgr);
+ return *SourceMgr;
+ }
+
+private:
+ // The order of these fields are important - they should be in the same order
+ // as they are created in `createSourceManagerForFile` so that they can be
+ // deleted in the reverse order as they are created.
+ std::unique_ptr<FileManager> FileMgr;
+ std::unique_ptr<DiagnosticsEngine> Diagnostics;
+ std::unique_ptr<SourceManager> SourceMgr;
+};
+
} // 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 edd910e70412..ddc58ffb6969 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines implementation details of the clang::SourceManager class.
+/// Defines implementation details of the clang::SourceManager class.
//
//===----------------------------------------------------------------------===//
@@ -31,20 +31,20 @@ namespace clang {
//===----------------------------------------------------------------------===//
struct LineEntry {
- /// \brief The offset in this file that the line entry occurs at.
+ /// The offset in this file that the line entry occurs at.
unsigned FileOffset;
- /// \brief The presumed line number of this line entry: \#line 4.
+ /// The presumed line number of this line entry: \#line 4.
unsigned LineNo;
- /// \brief The ID of the filename identified by this line entry:
+ /// The ID of the filename identified by this line entry:
/// \#line 4 "foo.c". This is -1 if not specified.
int FilenameID;
- /// \brief Set the 0 if no flags, 1 if a system header,
+ /// Set the 0 if no flags, 1 if a system header,
SrcMgr::CharacteristicKind FileKind;
- /// \brief The offset of the virtual include stack location,
+ /// The offset of the virtual include stack location,
/// which is manipulated by GNU linemarker directives.
///
/// If this is 0 then there is no virtual \#includer.
@@ -77,9 +77,9 @@ inline bool operator<(unsigned Offset, const LineEntry &E) {
return Offset < E.FileOffset;
}
-/// \brief Used to hold and unique data used to represent \#line information.
+/// Used to hold and unique data used to represent \#line information.
class LineTableInfo {
- /// \brief Map used to assign unique IDs to filenames in \#line directives.
+ /// Map used to assign unique IDs to filenames in \#line directives.
///
/// This allows us to unique the filenames that
/// frequently reoccur and reference them with indices. FilenameIDs holds
@@ -88,7 +88,7 @@ class LineTableInfo {
llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
- /// \brief Map from FileIDs to a list of line entries (sorted by the offset
+ /// 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;
@@ -113,7 +113,7 @@ public:
unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);
- /// \brief Find the line entry nearest to FID that is before it.
+ /// Find the line entry nearest to FID that is before it.
///
/// If there is no line entry before \p Offset in \p FID, returns null.
const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset);
@@ -124,7 +124,7 @@ public:
iterator begin() { return LineEntries.begin(); }
iterator end() { return LineEntries.end(); }
- /// \brief Add a new line entry that has already been encoded into
+ /// Add a new line entry that has already been encoded into
/// the internal representation of the line table.
void AddEntry(FileID FID, const std::vector<LineEntry> &Entries);
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
index 377534baab06..cd8213f6cfd4 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines various enumerations that describe declaration and
+/// Defines various enumerations that describe declaration and
/// type specifiers.
///
//===----------------------------------------------------------------------===//
@@ -21,38 +21,41 @@
#include "llvm/Support/ErrorHandling.h"
namespace clang {
- /// \brief Specifies the width of a type, e.g., short, long, or long long.
+ /// Specifies the width of a type, e.g., short, long, or long long.
enum TypeSpecifierWidth {
TSW_unspecified,
TSW_short,
TSW_long,
TSW_longlong
};
-
- /// \brief Specifies the signedness of a type, e.g., signed or unsigned.
+
+ /// Specifies the signedness of a type, e.g., signed or unsigned.
enum TypeSpecifierSign {
TSS_unspecified,
TSS_signed,
TSS_unsigned
};
-
+
enum TypeSpecifiersPipe {
TSP_unspecified,
TSP_pipe
};
- /// \brief Specifies the kind of type.
+ /// Specifies the kind of type.
enum TypeSpecifierType {
TST_unspecified,
TST_void,
TST_char,
TST_wchar, // C++ wchar_t
+ TST_char8, // C++20 char8_t (proposed)
TST_char16, // C++11 char16_t
TST_char32, // C++11 char32_t
TST_int,
TST_int128,
TST_half, // OpenCL half, ARM NEON __fp16
TST_Float16, // C11 extension ISO/IEC TS 18661-3
+ TST_Accum, // ISO/IEC JTC1 SC22 WG14 N1169 Extension
+ TST_Fract,
TST_float,
TST_double,
TST_float128,
@@ -80,7 +83,7 @@ namespace clang {
TST_error // erroneous type
};
- /// \brief Structure that packs information about the type specifiers that
+ /// Structure that packs information about the type specifiers that
/// were written in a particular type specifier sequence.
struct WrittenBuiltinSpecs {
static_assert(TST_error < 1 << 6, "Type bitfield not wide enough for TST");
@@ -90,7 +93,7 @@ namespace clang {
unsigned ModeAttr : 1;
};
- /// \brief A C++ access specifier (public, private, protected), plus the
+ /// A C++ access specifier (public, private, protected), plus the
/// special value "none" which means different things in different contexts.
enum AccessSpecifier {
AS_public,
@@ -99,24 +102,24 @@ namespace clang {
AS_none
};
- /// \brief The categorization of expression values, currently following the
+ /// The categorization of expression values, currently following the
/// C++11 scheme.
enum ExprValueKind {
- /// \brief An r-value expression (a pr-value in the C++11 taxonomy)
+ /// An r-value expression (a pr-value in the C++11 taxonomy)
/// produces a temporary value.
VK_RValue,
- /// \brief An l-value expression is a reference to an object with
+ /// An l-value expression is a reference to an object with
/// independent storage.
VK_LValue,
- /// \brief An x-value expression is a reference to an object with
+ /// An x-value expression is a reference to an object with
/// independent storage but which can be "moved", i.e.
/// efficiently cannibalized for its resources.
VK_XValue
};
- /// \brief A further classification of the kind of object referenced by an
+ /// A further classification of the kind of object referenced by an
/// l-value or x-value.
enum ExprObjectKind {
/// An ordinary object is located at an address in memory.
@@ -131,14 +134,14 @@ namespace clang {
/// An Objective-C property is a logical field of an Objective-C
/// object which is read and written via Objective-C method calls.
OK_ObjCProperty,
-
+
/// An Objective-C array/dictionary subscripting which reads an
/// object or writes at the subscripted array/dictionary element via
/// Objective-C method calls.
OK_ObjCSubscript
};
- /// \brief Describes the kind of template specialization that a
+ /// Describes the kind of template specialization that a
/// particular template specialization declaration represents.
enum TemplateSpecializationKind {
/// This template specialization was formed from a template-id but
@@ -161,14 +164,14 @@ namespace clang {
TSK_ExplicitInstantiationDefinition
};
- /// \brief Determine whether this template specialization kind refers
+ /// Determine whether this template specialization kind refers
/// to an instantiation of an entity (as opposed to a non-template or
/// an explicit specialization).
inline bool isTemplateInstantiation(TemplateSpecializationKind Kind) {
return Kind != TSK_Undeclared && Kind != TSK_ExplicitSpecialization;
}
- /// \brief True if this template specialization kind is an explicit
+ /// True if this template specialization kind is an explicit
/// specialization, explicit instantiation declaration, or explicit
/// instantiation definition.
inline bool isTemplateExplicitInstantiationOrSpecialization(
@@ -186,7 +189,7 @@ namespace clang {
llvm_unreachable("bad template specialization kind");
}
- /// \brief Thread storage-class-specifier.
+ /// Thread storage-class-specifier.
enum ThreadStorageClassSpecifier {
TSCS_unspecified,
/// GNU __thread.
@@ -199,7 +202,7 @@ namespace clang {
TSCS__Thread_local
};
- /// \brief Storage classes.
+ /// Storage classes.
enum StorageClass {
// These are legal on both functions and variables.
SC_None,
@@ -212,24 +215,24 @@ namespace clang {
SC_Register
};
- /// \brief Checks whether the given storage class is legal for functions.
+ /// Checks whether the given storage class is legal for functions.
inline bool isLegalForFunction(StorageClass SC) {
return SC <= SC_PrivateExtern;
}
- /// \brief Checks whether the given storage class is legal for variables.
+ /// Checks whether the given storage class is legal for variables.
inline bool isLegalForVariable(StorageClass SC) {
return true;
}
- /// \brief In-class initialization styles for non-static data members.
+ /// In-class initialization styles for non-static data members.
enum InClassInitStyle {
ICIS_NoInit, ///< No in-class initializer.
ICIS_CopyInit, ///< Copy initialization.
ICIS_ListInit ///< Direct list-initialization.
};
- /// \brief CallingConv - Specifies the calling convention that a function uses.
+ /// CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
@@ -250,7 +253,7 @@ namespace clang {
CC_PreserveAll, // __attribute__((preserve_all))
};
- /// \brief Checks whether the given calling convention supports variadic
+ /// Checks whether the given calling convention supports variadic
/// calls. Unprototyped calls also use the variadic call rules.
inline bool supportsVariadicCall(CallingConv CC) {
switch (CC) {
@@ -269,7 +272,7 @@ namespace clang {
}
}
- /// \brief The storage duration for an object (per C++ [basic.stc]).
+ /// The storage duration for an object (per C++ [basic.stc]).
enum StorageDuration {
SD_FullExpression, ///< Full-expression storage duration (for temporaries).
SD_Automatic, ///< Automatic storage duration (most local variables).
@@ -291,11 +294,17 @@ namespace clang {
Unspecified
};
+ /// Return true if \p L has a weaker nullability annotation than \p R. The
+ /// ordering is: Unspecified < Nullable < NonNull.
+ inline bool hasWeakerNullability(NullabilityKind L, NullabilityKind R) {
+ return uint8_t(L) > uint8_t(R);
+ }
+
/// Retrieve the spelling of the given nullability kind.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind,
bool isContextSensitive = false);
- /// \brief Kinds of parameter ABI.
+ /// Kinds of parameter ABI.
enum class ParameterABI {
/// This parameter uses ordinary ABI rules for its type.
Ordinary,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Stack.h b/contrib/llvm/tools/clang/include/clang/Basic/Stack.h
new file mode 100644
index 000000000000..15a37c6d5949
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Stack.h
@@ -0,0 +1,27 @@
+//===--- Stack.h - Utilities for dealing with stack space -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Defines utilities for dealing with stack allocation and stack space.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_STACK_H
+#define LLVM_CLANG_BASIC_STACK_H
+
+#include <cstddef>
+
+namespace clang {
+ /// The amount of stack space that Clang would like to be provided with.
+ /// If less than this much is available, we may be unable to reach our
+ /// template instantiation depth limit and other similar limits.
+ constexpr size_t DesiredStackSize = 8 << 20;
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_STACK_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
index 0d21845fbf8b..1517d741cb3c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
@@ -57,6 +57,7 @@ def Expr : Stmt<1>;
def PredefinedExpr : DStmt<Expr>;
def DeclRefExpr : DStmt<Expr>;
def IntegerLiteral : DStmt<Expr>;
+def FixedPointLiteral : DStmt<Expr>;
def FloatingLiteral : DStmt<Expr>;
def ImaginaryLiteral : DStmt<Expr>;
def StringLiteral : DStmt<Expr>;
@@ -186,7 +187,7 @@ def TypoExpr : DStmt<Expr>;
// Microsoft Extensions.
def MSPropertyRefExpr : DStmt<Expr>;
def MSPropertySubscriptExpr : DStmt<Expr>;
-def CXXUuidofExpr : DStmt<Expr>;
+def CXXUuidofExpr : DStmt<Expr>;
def SEHTryStmt : Stmt;
def SEHExceptStmt : Stmt;
def SEHFinallyStmt : Stmt;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h b/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h
index 09ac0052185a..db4461eda013 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides definitions for the atomic synchronization scopes.
+/// Provides definitions for the atomic synchronization scopes.
///
//===----------------------------------------------------------------------===//
@@ -22,7 +22,7 @@
namespace clang {
-/// \brief Defines synch scope values used internally by clang.
+/// 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
@@ -62,36 +62,36 @@ inline llvm::StringRef getAsString(SyncScope S) {
llvm_unreachable("Invalid synch scope");
}
-/// \brief Defines the kind of atomic scope models.
+/// Defines the kind of atomic scope models.
enum class AtomicScopeModelKind { None, OpenCL };
-/// \brief Defines the interface for synch scope model.
+/// Defines the interface for synch scope model.
class AtomicScopeModel {
public:
virtual ~AtomicScopeModel() {}
- /// \brief Maps language specific synch scope values to internal
+ /// 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
+ /// 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
+ /// 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
+ /// 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.
+ /// 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.
+/// Defines the synch scope model for OpenCL.
class AtomicScopeOpenCLModel : public AtomicScopeModel {
public:
/// The enum values match the pre-defined macros
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
index 8f4f5e9a74dd..75a3811007cc 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Enumerates target-specific builtins in their own namespaces within
+/// Enumerates target-specific builtins in their own namespaces within
/// namespace ::clang.
///
//===----------------------------------------------------------------------===//
@@ -31,7 +31,7 @@ namespace clang {
};
}
- /// \brief ARM builtins
+ /// ARM builtins
namespace ARM {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -42,7 +42,7 @@ namespace clang {
};
}
- /// \brief AArch64 builtins
+ /// AArch64 builtins
namespace AArch64 {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
@@ -53,7 +53,7 @@ namespace clang {
};
}
- /// \brief PPC builtins
+ /// PPC builtins
namespace PPC {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -63,7 +63,7 @@ namespace clang {
};
}
- /// \brief NVPTX builtins
+ /// NVPTX builtins
namespace NVPTX {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -73,7 +73,7 @@ namespace clang {
};
}
- /// \brief AMDGPU builtins
+ /// AMDGPU builtins
namespace AMDGPU {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
@@ -83,7 +83,7 @@ namespace clang {
};
}
- /// \brief X86 builtins
+ /// X86 builtins
namespace X86 {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
@@ -97,7 +97,7 @@ namespace clang {
};
}
- /// \brief Flags to identify the types for overloaded Neon builtins.
+ /// Flags to identify the types for overloaded Neon builtins.
///
/// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h.
class NeonTypeFlags {
@@ -140,7 +140,7 @@ namespace clang {
bool isQuad() const { return (Flags & QuadFlag) != 0; }
};
- /// \brief Hexagon builtins
+ /// Hexagon builtins
namespace Hexagon {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -150,7 +150,7 @@ namespace clang {
};
}
- /// \brief Nios2 builtins
+ /// Nios2 builtins
namespace Nios2 {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
@@ -160,7 +160,7 @@ namespace clang {
};
}
- /// \brief MIPS builtins
+ /// MIPS builtins
namespace Mips {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -170,7 +170,7 @@ namespace clang {
};
}
- /// \brief XCore builtins
+ /// XCore builtins
namespace XCore {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -180,7 +180,7 @@ namespace clang {
};
}
- /// \brief Le64 builtins
+ /// Le64 builtins
namespace Le64 {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
@@ -190,7 +190,7 @@ namespace clang {
};
}
- /// \brief SystemZ builtins
+ /// SystemZ builtins
namespace SystemZ {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -200,7 +200,7 @@ namespace clang {
};
}
- /// \brief WebAssembly builtins
+ /// WebAssembly builtins
namespace WebAssembly {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
index 7fb1f826b0f6..455121a98f33 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the TargetCXXABI class, which abstracts details of the
+/// Defines the TargetCXXABI class, which abstracts details of the
/// C++ ABI that we're targeting.
///
//===----------------------------------------------------------------------===//
@@ -20,10 +20,10 @@
namespace clang {
-/// \brief The basic abstraction for the target C++ ABI.
+/// The basic abstraction for the target C++ ABI.
class TargetCXXABI {
public:
- /// \brief The basic C++ ABI kind.
+ /// The basic C++ ABI kind.
enum Kind {
/// The generic Itanium ABI is the standard ABI of most open-source
/// and Unix-like platforms. It is the primary ABI targeted by
@@ -131,7 +131,7 @@ public:
Kind getKind() const { return TheKind; }
- /// \brief Does this ABI generally fall into the Itanium family of ABIs?
+ /// Does this ABI generally fall into the Itanium family of ABIs?
bool isItaniumFamily() const {
switch (getKind()) {
case GenericAArch64:
@@ -150,7 +150,7 @@ public:
llvm_unreachable("bad ABI kind");
}
- /// \brief Is this ABI an MSVC-compatible ABI?
+ /// Is this ABI an MSVC-compatible ABI?
bool isMicrosoft() const {
switch (getKind()) {
case GenericAArch64:
@@ -169,7 +169,7 @@ public:
llvm_unreachable("bad ABI kind");
}
- /// \brief Are member functions differently aligned?
+ /// Are member functions differently aligned?
///
/// Many Itanium-style C++ ABIs require member functions to be aligned, so
/// that a pointer to such a function is guaranteed to have a zero in the
@@ -199,13 +199,6 @@ public:
llvm_unreachable("bad ABI kind");
}
- /// \brief Is the default C++ member function calling convention
- /// the same as the default calling convention?
- bool isMemberFunctionCCDefault() const {
- // Right now, this is always false for Microsoft.
- return !isMicrosoft();
- }
-
/// Are arguments to a call destroyed left to right in the callee?
/// This is a fundamental language change, since it implies that objects
/// passed by value do *not* live to the end of the full expression.
@@ -217,25 +210,25 @@ public:
return isMicrosoft();
}
- /// \brief Does this ABI have different entrypoints for complete-object
+ /// Does this ABI have different entrypoints for complete-object
/// and base-subobject constructors?
bool hasConstructorVariants() const {
return isItaniumFamily();
}
- /// \brief Does this ABI allow virtual bases to be primary base classes?
+ /// Does this ABI allow virtual bases to be primary base classes?
bool hasPrimaryVBases() const {
return isItaniumFamily();
}
- /// \brief Does this ABI use key functions? If so, class data such as the
+ /// Does this ABI use key functions? If so, class data such as the
/// vtable is emitted with strong linkage by the TU containing the key
/// function.
bool hasKeyFunctions() const {
return isItaniumFamily();
}
- /// \brief Can an out-of-line inline function serve as a key function?
+ /// Can an out-of-line inline function serve as a key function?
///
/// This flag is only useful in ABIs where type data (for example,
/// vtables and type_info objects) are emitted only after processing
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
index 6ba58779114f..958b9106bc99 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::TargetInfo interface.
+/// Defines the clang::TargetInfo interface.
///
//===----------------------------------------------------------------------===//
@@ -20,7 +20,6 @@
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
@@ -30,6 +29,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <string>
#include <vector>
@@ -49,7 +49,7 @@ class SourceManager;
namespace Builtin { struct Info; }
-/// \brief Exposes information about the current target.
+/// Exposes information about the current target.
///
class TargetInfo : public RefCountedBase<TargetInfo> {
std::shared_ptr<TargetOptions> TargetOpts;
@@ -61,6 +61,8 @@ protected:
bool TLSSupported;
bool VLASupported;
bool NoAsmVariants; // True if {|} are normal characters.
+ bool HasLegalHalfType; // True if the backend supports operations on the half
+ // LLVM IR type.
bool HasFloat128;
unsigned char PointerWidth, PointerAlign;
unsigned char BoolWidth, BoolAlign;
@@ -72,6 +74,33 @@ protected:
unsigned char LargeArrayMinWidth, LargeArrayAlign;
unsigned char LongWidth, LongAlign;
unsigned char LongLongWidth, LongLongAlign;
+
+ // Fixed point bit widths
+ unsigned char ShortAccumWidth, ShortAccumAlign;
+ unsigned char AccumWidth, AccumAlign;
+ unsigned char LongAccumWidth, LongAccumAlign;
+ unsigned char ShortFractWidth, ShortFractAlign;
+ unsigned char FractWidth, FractAlign;
+ unsigned char LongFractWidth, LongFractAlign;
+
+ // If true, unsigned fixed point types have the same number of fractional bits
+ // as their signed counterparts, forcing the unsigned types to have one extra
+ // bit of padding. Otherwise, unsigned fixed point types have
+ // one more fractional bit than its corresponding signed type. This is false
+ // by default.
+ bool PaddingOnUnsignedFixedPoint;
+
+ // Fixed point integral and fractional bit sizes
+ // Saturated types share the same integral/fractional bits as their
+ // corresponding unsaturated types.
+ // For simplicity, the fractional bits in a _Fract type will be one less the
+ // width of that _Fract type. This leaves all signed _Fract types having no
+ // padding and unsigned _Fract types will only have 1 bit of padding after the
+ // sign if PaddingOnUnsignedFixedPoint is set.
+ unsigned char ShortAccumScale;
+ unsigned char AccumScale;
+ unsigned char LongAccumScale;
+
unsigned char SuitableAlign;
unsigned char DefaultAlignForAttributeAligned;
unsigned char MinGlobalAlign;
@@ -107,7 +136,7 @@ protected:
}
public:
- /// \brief Construct a target for the given options.
+ /// Construct a target for the given options.
///
/// \param Opts - The options to use to initialize the target. The target may
/// modify the options to canonicalize the target feature information to match
@@ -118,7 +147,7 @@ public:
virtual ~TargetInfo();
- /// \brief Retrieve the target options.
+ /// Retrieve the target options.
TargetOptions &getTargetOpts() const {
assert(TargetOpts && "Missing target options");
return *TargetOpts;
@@ -147,7 +176,7 @@ public:
Float128
};
- /// \brief The different kinds of __builtin_va_list types defined by
+ /// The different kinds of __builtin_va_list types defined by
/// the target implementation.
enum BuiltinVaListKind {
/// typedef char* __builtin_va_list;
@@ -193,7 +222,7 @@ protected:
WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType,
ProcessIDType;
- /// \brief Whether Objective-C's built-in boolean type should be signed char.
+ /// Whether Objective-C's built-in boolean type should be signed char.
///
/// Otherwise, when this flag is not set, the normal built-in boolean type is
/// used.
@@ -206,7 +235,7 @@ protected:
/// boundary.
unsigned UseBitFieldTypeAlignment : 1;
- /// \brief Whether zero length bitfields (e.g., int : 0;) force alignment of
+ /// Whether zero length bitfields (e.g., int : 0;) force alignment of
/// the next bitfield.
///
/// If the alignment of the zero length bitfield is greater than the member
@@ -214,14 +243,14 @@ protected:
/// zero-length bitfield.
unsigned UseZeroLengthBitfieldAlignment : 1;
- /// \brief Whether explicit bit field alignment attributes are honored.
+ /// Whether explicit bit field alignment attributes are honored.
unsigned UseExplicitBitFieldAlignment : 1;
/// If non-zero, specifies a fixed alignment value for bitfields that follow
/// zero length bitfield, regardless of the zero length bitfield type.
unsigned ZeroLengthBitfieldBoundary;
- /// \brief Specify if mangling based on address space map should be used or
+ /// Specify if mangling based on address space map should be used or
/// not for language specific address spaces
bool UseAddrSpaceMapMangling;
@@ -283,30 +312,30 @@ public:
}
}
- /// \brief Return the width (in bits) of the specified integer type enum.
+ /// Return the width (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
- /// \brief Return integer type with specified width.
+ /// Return integer type with specified width.
virtual IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
- /// \brief Return the smallest integer type with at least the specified width.
+ /// Return the smallest integer type with at least the specified width.
virtual IntType getLeastIntTypeByWidth(unsigned BitWidth,
bool IsSigned) const;
- /// \brief Return floating point type with specified width.
+ /// Return floating point type with specified width.
RealType getRealTypeByWidth(unsigned BitWidth) const;
- /// \brief Return the alignment (in bits) of the specified integer type enum.
+ /// Return the alignment (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntAlign().
unsigned getTypeAlign(IntType T) const;
- /// \brief Returns true if the type is signed; false otherwise.
+ /// Returns true if the type is signed; false otherwise.
static bool isTypeSigned(IntType T);
- /// \brief Return the width of pointers on this target, for the
+ /// Return the width of pointers on this target, for the
/// specified address space.
uint64_t getPointerWidth(unsigned AddrSpace) const {
return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace);
@@ -315,29 +344,29 @@ public:
return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
}
- /// \brief Return the maximum width of pointers on this target.
+ /// Return the maximum width of pointers on this target.
virtual uint64_t getMaxPointerWidth() const {
return PointerWidth;
}
- /// \brief Get integer value for null pointer.
+ /// Get integer value for null pointer.
/// \param AddrSpace address space of pointee in source language.
virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; }
- /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits.
+ /// Return the size of '_Bool' and C++ 'bool' for this target, in bits.
unsigned getBoolWidth() const { return BoolWidth; }
- /// \brief Return the alignment of '_Bool' and C++ 'bool' for this target.
+ /// Return the alignment of '_Bool' and C++ 'bool' for this target.
unsigned getBoolAlign() const { return BoolAlign; }
unsigned getCharWidth() const { return 8; } // FIXME
unsigned getCharAlign() const { return 8; } // FIXME
- /// \brief Return the size of 'signed short' and 'unsigned short' for this
+ /// Return the size of 'signed short' and 'unsigned short' for this
/// target, in bits.
unsigned getShortWidth() const { return 16; } // FIXME
- /// \brief Return the alignment of 'signed short' and 'unsigned short' for
+ /// Return the alignment of 'signed short' and 'unsigned short' for
/// this target.
unsigned getShortAlign() const { return 16; } // FIXME
@@ -356,19 +385,135 @@ public:
unsigned getLongLongWidth() const { return LongLongWidth; }
unsigned getLongLongAlign() const { return LongLongAlign; }
- /// \brief Determine whether the __int128 type is supported on this target.
+ /// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
+ /// 'unsigned short _Accum' for this target, in bits.
+ unsigned getShortAccumWidth() const { return ShortAccumWidth; }
+ unsigned getShortAccumAlign() const { return ShortAccumAlign; }
+
+ /// getAccumWidth/Align - Return the size of 'signed _Accum' and
+ /// 'unsigned _Accum' for this target, in bits.
+ unsigned getAccumWidth() const { return AccumWidth; }
+ unsigned getAccumAlign() const { return AccumAlign; }
+
+ /// getLongAccumWidth/Align - Return the size of 'signed long _Accum' and
+ /// 'unsigned long _Accum' for this target, in bits.
+ unsigned getLongAccumWidth() const { return LongAccumWidth; }
+ unsigned getLongAccumAlign() const { return LongAccumAlign; }
+
+ /// getShortFractWidth/Align - Return the size of 'signed short _Fract' and
+ /// 'unsigned short _Fract' for this target, in bits.
+ unsigned getShortFractWidth() const { return ShortFractWidth; }
+ unsigned getShortFractAlign() const { return ShortFractAlign; }
+
+ /// getFractWidth/Align - Return the size of 'signed _Fract' and
+ /// 'unsigned _Fract' for this target, in bits.
+ unsigned getFractWidth() const { return FractWidth; }
+ unsigned getFractAlign() const { return FractAlign; }
+
+ /// getLongFractWidth/Align - Return the size of 'signed long _Fract' and
+ /// 'unsigned long _Fract' for this target, in bits.
+ unsigned getLongFractWidth() const { return LongFractWidth; }
+ unsigned getLongFractAlign() const { return LongFractAlign; }
+
+ /// getShortAccumScale/IBits - Return the number of fractional/integral bits
+ /// in a 'signed short _Accum' type.
+ unsigned getShortAccumScale() const { return ShortAccumScale; }
+ unsigned getShortAccumIBits() const {
+ return ShortAccumWidth - ShortAccumScale - 1;
+ }
+
+ /// getAccumScale/IBits - Return the number of fractional/integral bits
+ /// in a 'signed _Accum' type.
+ unsigned getAccumScale() const { return AccumScale; }
+ unsigned getAccumIBits() const { return AccumWidth - AccumScale - 1; }
+
+ /// getLongAccumScale/IBits - Return the number of fractional/integral bits
+ /// in a 'signed long _Accum' type.
+ unsigned getLongAccumScale() const { return LongAccumScale; }
+ unsigned getLongAccumIBits() const {
+ return LongAccumWidth - LongAccumScale - 1;
+ }
+
+ /// getUnsignedShortAccumScale/IBits - Return the number of
+ /// fractional/integral bits in a 'unsigned short _Accum' type.
+ unsigned getUnsignedShortAccumScale() const {
+ return PaddingOnUnsignedFixedPoint ? ShortAccumScale : ShortAccumScale + 1;
+ }
+ unsigned getUnsignedShortAccumIBits() const {
+ return PaddingOnUnsignedFixedPoint
+ ? getShortAccumIBits()
+ : ShortAccumWidth - getUnsignedShortAccumScale();
+ }
+
+ /// getUnsignedAccumScale/IBits - Return the number of fractional/integral
+ /// bits in a 'unsigned _Accum' type.
+ unsigned getUnsignedAccumScale() const {
+ return PaddingOnUnsignedFixedPoint ? AccumScale : AccumScale + 1;
+ }
+ unsigned getUnsignedAccumIBits() const {
+ return PaddingOnUnsignedFixedPoint ? getAccumIBits()
+ : AccumWidth - getUnsignedAccumScale();
+ }
+
+ /// getUnsignedLongAccumScale/IBits - Return the number of fractional/integral
+ /// bits in a 'unsigned long _Accum' type.
+ unsigned getUnsignedLongAccumScale() const {
+ return PaddingOnUnsignedFixedPoint ? LongAccumScale : LongAccumScale + 1;
+ }
+ unsigned getUnsignedLongAccumIBits() const {
+ return PaddingOnUnsignedFixedPoint
+ ? getLongAccumIBits()
+ : LongAccumWidth - getUnsignedLongAccumScale();
+ }
+
+ /// getShortFractScale - Return the number of fractional bits
+ /// in a 'signed short _Fract' type.
+ unsigned getShortFractScale() const { return ShortFractWidth - 1; }
+
+ /// getFractScale - Return the number of fractional bits
+ /// in a 'signed _Fract' type.
+ unsigned getFractScale() const { return FractWidth - 1; }
+
+ /// getLongFractScale - Return the number of fractional bits
+ /// in a 'signed long _Fract' type.
+ unsigned getLongFractScale() const { return LongFractWidth - 1; }
+
+ /// getUnsignedShortFractScale - Return the number of fractional bits
+ /// in a 'unsigned short _Fract' type.
+ unsigned getUnsignedShortFractScale() const {
+ return PaddingOnUnsignedFixedPoint ? getShortFractScale()
+ : getShortFractScale() + 1;
+ }
+
+ /// getUnsignedFractScale - Return the number of fractional bits
+ /// in a 'unsigned _Fract' type.
+ unsigned getUnsignedFractScale() const {
+ return PaddingOnUnsignedFixedPoint ? getFractScale() : getFractScale() + 1;
+ }
+
+ /// getUnsignedLongFractScale - Return the number of fractional bits
+ /// in a 'unsigned long _Fract' type.
+ unsigned getUnsignedLongFractScale() const {
+ return PaddingOnUnsignedFixedPoint ? getLongFractScale()
+ : getLongFractScale() + 1;
+ }
+
+ /// Determine whether the __int128 type is supported on this target.
virtual bool hasInt128Type() const {
- return getPointerWidth(0) >= 64;
+ return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
} // FIXME
- /// \brief Determine whether the __float128 type is supported on this target.
+ /// Determine whether _Float16 is supported on this target.
+ virtual bool hasLegalHalfType() const { return HasLegalHalfType; }
+
+ /// Determine whether the __float128 type is supported on this target.
virtual bool hasFloat128Type() const { return HasFloat128; }
- /// \brief Return the alignment that is suitable for storing any
+ /// Return the alignment that is suitable for storing any
/// object with a fundamental alignment requirement.
unsigned getSuitableAlign() const { return SuitableAlign; }
- /// \brief Return the default alignment for __attribute__((aligned)) on
+ /// Return the default alignment for __attribute__((aligned)) on
/// this target, to be used if no alignment value is specified.
unsigned getDefaultAlignForAttributeAligned() const {
return DefaultAlignForAttributeAligned;
@@ -431,11 +576,11 @@ public:
return *Float128Format;
}
- /// \brief Return true if the 'long double' type should be mangled like
+ /// Return true if the 'long double' type should be mangled like
/// __float128.
virtual bool useFloat128ManglingForLongDouble() const { return false; }
- /// \brief Return the value for the C99 FLT_EVAL_METHOD macro.
+ /// Return the value for the C99 FLT_EVAL_METHOD macro.
virtual unsigned getFloatEvalMethod() const { return 0; }
// getLargeArrayMinWidth/Align - Return the minimum array size that is
@@ -443,16 +588,16 @@ public:
unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
- /// \brief Return the maximum width lock-free atomic operation which will
+ /// Return the maximum width lock-free atomic operation which will
/// ever be supported for the given target
unsigned getMaxAtomicPromoteWidth() const { return MaxAtomicPromoteWidth; }
- /// \brief Return the maximum width lock-free atomic operation which can be
+ /// 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
+ /// 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
+ /// Returns true if the given target supports lock-free atomic
/// operations at the specified width and alignment.
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits,
uint64_t AlignmentInBits) const {
@@ -462,14 +607,14 @@ public:
llvm::isPowerOf2_64(AtomicSizeInBits / getCharWidth()));
}
- /// \brief Return the maximum vector alignment supported for the given target.
+ /// Return the maximum vector alignment supported for the given target.
unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
- /// \brief Return default simd alignment for the given target. Generally, this
+ /// Return default simd alignment for the given target. Generally, this
/// value is type-specific, but this alignment can be used for most of the
/// types for the given target.
unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
- /// \brief Return the size of intmax_t and uintmax_t for this target, in bits.
+ /// Return the size of intmax_t and uintmax_t for this target, in bits.
unsigned getIntMaxTWidth() const {
return getTypeWidth(IntMaxType);
}
@@ -477,7 +622,7 @@ public:
// Return the size of unwind_word for this target.
virtual unsigned getUnwindWordWidth() const { return getPointerWidth(0); }
- /// \brief Return the "preferred" register width on this target.
+ /// Return the "preferred" register width on this target.
virtual unsigned getRegisterWidth() const {
// Currently we assume the register width on the target matches the pointer
// width, we can introduce a new variable for this if/when some target wants
@@ -485,12 +630,12 @@ public:
return PointerWidth;
}
- /// \brief Returns the name of the mcount instrumentation function.
+ /// Returns the name of the mcount instrumentation function.
const char *getMCountName() const {
return MCountName;
}
- /// \brief Check if the Objective-C built-in boolean type should be signed
+ /// Check if the Objective-C built-in boolean type should be signed
/// char.
///
/// Otherwise, if this returns false, the normal built-in boolean type
@@ -502,58 +647,58 @@ public:
UseSignedCharForObjCBool = false;
}
- /// \brief Check whether the alignment of bit-field types is respected
+ /// Check whether the alignment of bit-field types is respected
/// when laying out structures.
bool useBitFieldTypeAlignment() const {
return UseBitFieldTypeAlignment;
}
- /// \brief Check whether zero length bitfields should force alignment of
+ /// Check whether zero length bitfields should force alignment of
/// the next member.
bool useZeroLengthBitfieldAlignment() const {
return UseZeroLengthBitfieldAlignment;
}
- /// \brief Get the fixed alignment value in bits for a member that follows
+ /// Get the fixed alignment value in bits for a member that follows
/// a zero length bitfield.
unsigned getZeroLengthBitfieldBoundary() const {
return ZeroLengthBitfieldBoundary;
}
- /// \brief Check whether explicit bitfield alignment attributes should be
+ /// Check whether explicit bitfield alignment attributes should be
// honored, as in "__attribute__((aligned(2))) int b : 1;".
bool useExplicitBitFieldAlignment() const {
return UseExplicitBitFieldAlignment;
}
- /// \brief Check whether this target support '\#pragma options align=mac68k'.
+ /// Check whether this target support '\#pragma options align=mac68k'.
bool hasAlignMac68kSupport() const {
return HasAlignMac68kSupport;
}
- /// \brief Return the user string for the specified integer type enum.
+ /// Return the user string for the specified integer type enum.
///
/// For example, SignedShort -> "short".
static const char *getTypeName(IntType T);
- /// \brief Return the constant suffix for the specified integer type enum.
+ /// Return the constant suffix for the specified integer type enum.
///
/// For example, SignedLong -> "L".
const char *getTypeConstantSuffix(IntType T) const;
- /// \brief Return the printf format modifier for the specified
+ /// Return the printf format modifier for the specified
/// integer type enum.
///
/// For example, SignedLong -> "l".
static const char *getTypeFormatModifier(IntType T);
- /// \brief Check whether the given real type should use the "fpret" flavor of
+ /// Check whether the given real type should use the "fpret" flavor of
/// Objective-C message passing on this target.
bool useObjCFPRetForRealType(RealType T) const {
return RealTypeUsesObjCFPRet & (1 << T);
}
- /// \brief Check whether _Complex long double should use the "fp2ret" flavor
+ /// Check whether _Complex long double should use the "fp2ret" flavor
/// of Objective-C message passing on this target.
bool useObjCFP2RetForComplexLongDouble() const {
return ComplexLongDoubleUsesFP2Ret;
@@ -567,7 +712,7 @@ public:
return true;
}
- /// \brief Specify if mangling based on address space map should be used or
+ /// Specify if mangling based on address space map should be used or
/// not for language specific address spaces
bool useAddressSpaceMapMangling() const {
return UseAddrSpaceMapMangling;
@@ -575,7 +720,7 @@ public:
///===---- Other target property query methods --------------------------===//
- /// \brief Appends the target-specific \#define values for this
+ /// Appends the target-specific \#define values for this
/// target set to the specified buffer.
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const = 0;
@@ -593,7 +738,7 @@ public:
/// idea to avoid optimizing based on that undef behavior.
virtual bool isCLZForZeroUndef() const { return true; }
- /// \brief Returns the kind of __builtin_va_list type that should be used
+ /// Returns the kind of __builtin_va_list type that should be used
/// with this target.
virtual BuiltinVaListKind getBuiltinVaListKind() const = 0;
@@ -604,28 +749,34 @@ public:
/// Returns true for RenderScript.
bool isRenderScriptTarget() const { return IsRenderScriptTarget; }
- /// \brief Returns whether the passed in string is a valid clobber in an
+ /// Returns whether the passed in string is a valid clobber in an
/// inline asm statement.
///
/// This is used by Sema.
bool isValidClobber(StringRef Name) const;
- /// \brief Returns whether the passed in string is a valid register name
+ /// Returns whether the passed in string is a valid register name
/// according to GCC.
///
/// This is used by Sema for inline asm statements.
- bool isValidGCCRegisterName(StringRef Name) const;
+ virtual bool isValidGCCRegisterName(StringRef Name) const;
- /// \brief Returns the "normalized" GCC register name.
+ /// Returns the "normalized" GCC register name.
///
/// ReturnCannonical true will return the register name without any additions
/// such as "{}" or "%" in it's canonical form, for example:
/// ReturnCanonical = true and Name = "rax", will return "ax".
StringRef getNormalizedGCCRegisterName(StringRef Name,
bool ReturnCanonical = false) const;
-
- virtual StringRef getConstraintRegister(const StringRef &Constraint,
- const StringRef &Expression) const {
+
+ /// Extracts a register from the passed constraint (if it is a
+ /// single-register constraint) and the asm label expression related to a
+ /// variable in the input or output list of an inline asm statement.
+ ///
+ /// This function is used by Sema in order to diagnose conflicts between
+ /// the clobber list and the input/output lists.
+ virtual StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const {
return "";
}
@@ -663,11 +814,11 @@ public:
bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
- /// \brief Return true if this output operand has a matching
+ /// Return true if this output operand has a matching
/// (tied) input operand.
bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; }
- /// \brief Return true if this input operand is a matching
+ /// Return true if this input operand is a matching
/// constraint that ties it to an output operand.
///
/// If this returns true then getTiedOperand will indicate which output
@@ -711,7 +862,7 @@ public:
ImmRange.Max = INT_MAX;
}
- /// \brief Indicate that this is an input operand that is tied to
+ /// Indicate that this is an input operand that is tied to
/// the specified output operand.
///
/// Copy over the various constraint information from the output.
@@ -723,7 +874,7 @@ public:
}
};
- /// \brief Validate register name used for global register variables.
+ /// Validate register name used for global register variables.
///
/// This function returns true if the register passed in RegName can be used
/// for global register variables on this target. In addition, it returns
@@ -777,16 +928,16 @@ public:
return std::string(1, *Constraint);
}
- /// \brief Returns a string of target-specific clobbers, in LLVM format.
+ /// Returns a string of target-specific clobbers, in LLVM format.
virtual const char *getClobbers() const = 0;
- /// \brief Returns true if NaN encoding is IEEE 754-2008.
+ /// Returns true if NaN encoding is IEEE 754-2008.
/// Only MIPS allows a different encoding.
virtual bool isNan2008() const {
return true;
}
- /// \brief Returns the target triple of the primary target.
+ /// Returns the target triple of the primary target.
const llvm::Triple &getTriple() const {
return Triple;
}
@@ -806,7 +957,7 @@ public:
const unsigned RegNum;
};
- /// \brief Does this target support "protected" visibility?
+ /// Does this target support "protected" visibility?
///
/// Any target which dynamic libraries will naturally support
/// something like "default" (meaning that the symbol is visible
@@ -818,7 +969,7 @@ public:
/// either; the entire thing is pretty badly mangled.
virtual bool hasProtectedVisibility() const { return true; }
- /// \brief An optional hook that targets can implement to perform semantic
+ /// An optional hook that targets can implement to perform semantic
/// checking on attribute((section("foo"))) specifiers.
///
/// In this case, "foo" is passed in to be checked. If the section
@@ -833,18 +984,18 @@ public:
return "";
}
- /// \brief Set forced language options.
+ /// Set forced language options.
///
/// Apply changes to the target information with respect to certain
/// language options which change the target configuration and adjust
/// the language based on the target options where applicable.
virtual void adjust(LangOptions &Opts);
- /// \brief Adjust target options based on codegen options.
+ /// Adjust target options based on codegen options.
virtual void adjustTargetOptions(const CodeGenOptions &CGOpts,
TargetOptions &TargetOpts) const {}
- /// \brief Initialize the map with the default set of target features for the
+ /// Initialize the map with the default set of target features for the
/// CPU this should include all legal feature strings on the target.
///
/// \return False on error (invalid features).
@@ -852,41 +1003,44 @@ public:
DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeatureVec) const;
- /// \brief Get the ABI currently in use.
+ /// Get the ABI currently in use.
virtual StringRef getABI() const { return StringRef(); }
- /// \brief Get the C++ ABI currently in use.
+ /// Get the C++ ABI currently in use.
TargetCXXABI getCXXABI() const {
return TheCXXABI;
}
- /// \brief Target the specified CPU.
+ /// Target the specified CPU.
///
/// \return False on error (invalid CPU name).
virtual bool setCPU(const std::string &Name) {
return false;
}
+ /// Fill a SmallVectorImpl with the valid values to setCPU.
+ virtual void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {}
+
/// brief Determine whether this TargetInfo supports the given CPU name.
virtual bool isValidCPUName(StringRef Name) const {
return true;
}
- /// \brief Use the specified ABI.
+ /// Use the specified ABI.
///
/// \return False on error (invalid ABI name).
virtual bool setABI(const std::string &Name) {
return false;
}
- /// \brief Use the specified unit for FP math.
+ /// Use the specified unit for FP math.
///
/// \return False on error (invalid unit name).
virtual bool setFPMath(StringRef Name) {
return false;
}
- /// \brief Enable or disable a specific target feature;
+ /// Enable or disable a specific target feature;
/// the feature name must be valid.
virtual void setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
@@ -894,12 +1048,12 @@ public:
Features[Name] = Enabled;
}
- /// \brief Determine whether this TargetInfo supports the given feature.
+ /// Determine whether this TargetInfo supports the given feature.
virtual bool isValidFeatureName(StringRef Feature) const {
return true;
}
- /// \brief Perform initialization based on the user configured
+ /// Perform initialization based on the user configured
/// set of features (e.g., +sse4).
///
/// The list is guaranteed to have at most one entry per feature.
@@ -915,31 +1069,62 @@ public:
return true;
}
- /// \brief Determine whether the given target has the given feature.
+ /// Determine whether the given target has the given feature.
virtual bool hasFeature(StringRef Feature) const {
return false;
}
- // \brief Validate the contents of the __builtin_cpu_supports(const char*)
+ /// Identify whether this taret supports multiversioning of functions,
+ /// which requires support for cpu_supports and cpu_is functionality.
+ virtual bool supportsMultiVersioning() const { return false; }
+
+ // Validate the contents of the __builtin_cpu_supports(const char*)
// argument.
virtual bool validateCpuSupports(StringRef Name) const { return false; }
- // \brief Validate the contents of the __builtin_cpu_is(const char*)
+ // Return the target-specific priority for features/cpus/vendors so
+ // that they can be properly sorted for checking.
+ virtual unsigned multiVersionSortPriority(StringRef Name) const {
+ return 0;
+ }
+
+ // 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.
+ // Validate a cpu_dispatch/cpu_specific CPU option, which is a different list
+ // from cpu_is, since it checks via features rather than CPUs directly.
+ virtual bool validateCPUSpecificCPUDispatch(StringRef Name) const {
+ return false;
+ }
+
+ // Get the character to be added for mangling purposes for cpu_specific.
+ virtual char CPUSpecificManglingCharacter(StringRef Name) const {
+ llvm_unreachable(
+ "cpu_specific Multiversioning not implemented on this target");
+ }
+
+ // Get a list of the features that make up the CPU option for
+ // cpu_specific/cpu_dispatch so that it can be passed to llvm as optimization
+ // options.
+ virtual void getCPUSpecificCPUDispatchFeatures(
+ StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const {
+ llvm_unreachable(
+ "cpu_specific Multiversioning not implemented on this target");
+ }
+
+ // Returns maximal number of args passed in registers.
unsigned getRegParmMax() const {
assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
return RegParmMax;
}
- /// \brief Whether the target supports thread-local storage.
+ /// Whether the target supports thread-local storage.
bool isTLSSupported() const {
return TLSSupported;
}
- /// \brief Return the maximum alignment (in bits) of a TLS variable
+ /// Return the maximum alignment (in bits) of a TLS variable
///
/// Gets the maximum alignment (in bits) of a TLS variable on this target.
/// Returns zero if there is no such constraint.
@@ -947,17 +1132,18 @@ public:
return MaxTLSAlign;
}
- /// \brief Whether target supports variable-length arrays.
+ /// Whether target supports variable-length arrays.
bool isVLASupported() const { return VLASupported; }
- /// \brief Whether the target supports SEH __try.
+ /// Whether the target supports SEH __try.
bool isSEHTrySupported() const {
return getTriple().isOSWindows() &&
(getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64);
+ getTriple().getArch() == llvm::Triple::x86_64 ||
+ getTriple().getArch() == llvm::Triple::aarch64);
}
- /// \brief Return true if {|} are normal characters in the asm string.
+ /// Return true if {|} are normal characters in the asm string.
///
/// If this returns false (the default), then {abc|xyz} is syntax
/// that says that when compiling for asm variant #0, "abc" should be
@@ -967,7 +1153,7 @@ public:
return NoAsmVariants;
}
- /// \brief Return the register number that __builtin_eh_return_regno would
+ /// Return the register number that __builtin_eh_return_regno would
/// return with the specified argument.
/// This corresponds with TargetLowering's getExceptionPointerRegister
/// and getExceptionSelectorRegister in the backend.
@@ -975,14 +1161,14 @@ public:
return -1;
}
- /// \brief Return the section to use for C++ static initialization functions.
+ /// Return the section to use for C++ static initialization functions.
virtual const char *getStaticInitSectionSpecifier() const {
return nullptr;
}
const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; }
- /// \brief Return an AST address space which can be used opportunistically
+ /// 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.
@@ -990,11 +1176,11 @@ public:
return LangAS::Default;
}
- /// \brief Retrieve the name of the platform as it is used in the
+ /// Retrieve the name of the platform as it is used in the
/// availability attribute.
StringRef getPlatformName() const { return PlatformName; }
- /// \brief Retrieve the minimum desired version of the platform, to
+ /// Retrieve the minimum desired version of the platform, to
/// which the program should be compiled.
VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; }
@@ -1007,7 +1193,7 @@ public:
CCMT_NonMember
};
- /// \brief Gets the default calling convention for the given target and
+ /// Gets the default calling convention for the given target and
/// declaration context.
virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const {
// Not all targets will specify an explicit calling convention that we can
@@ -1022,7 +1208,7 @@ public:
CCCR_Ignore,
};
- /// \brief Determines whether a given calling convention is valid for the
+ /// Determines whether a given calling convention is valid for the
/// target. A calling convention can either be accepted, produce a warning
/// and be substituted with the default calling convention, or (someday)
/// produce an error (such as using thiscall on a non-instance function).
@@ -1035,31 +1221,47 @@ public:
}
}
+ enum CallingConvKind {
+ CCK_Default,
+ CCK_ClangABI4OrPS4,
+ CCK_MicrosoftWin64
+ };
+
+ virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const;
+
/// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
/// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
virtual bool hasSjLjLowering() const {
return false;
}
- /// \brief Whether target allows to overalign ABI-specified preferred alignment
+ /// Check if the target supports CFProtection branch.
+ virtual bool
+ checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const;
+
+ /// Check if the target supports CFProtection branch.
+ virtual bool
+ checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const;
+
+ /// Whether target allows to overalign ABI-specified preferred alignment
virtual bool allowsLargerPreferedTypeAlignment() const { return true; }
- /// \brief Set supported OpenCL extensions and optional core features.
+ /// Set supported OpenCL extensions and optional core features.
virtual void setSupportedOpenCLOpts() {}
- /// \brief Set supported OpenCL extensions as written on command line
+ /// Set supported OpenCL extensions as written on command line
virtual void setOpenCLExtensionOpts() {
for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) {
getTargetOpts().SupportedOpenCLOptions.support(Ext);
}
}
- /// \brief Get supported OpenCL extensions and optional core features.
+ /// Get supported OpenCL extensions and optional core features.
OpenCLOptions &getSupportedOpenCLOpts() {
return getTargetOpts().SupportedOpenCLOptions;
}
- /// \brief Get const supported OpenCL extensions and optional core features.
+ /// Get const supported OpenCL extensions and optional core features.
const OpenCLOptions &getSupportedOpenCLOpts() const {
return getTargetOpts().SupportedOpenCLOptions;
}
@@ -1075,7 +1277,7 @@ public:
OCLTK_Sampler,
};
- /// \brief Get address space for OpenCL type.
+ /// Get address space for OpenCL type.
virtual LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const;
/// \returns Target specific vtbl ptr address space.
@@ -1093,7 +1295,7 @@ public:
return None;
}
- /// \brief Check the target is valid after it is fully initialized.
+ /// Check the target is valid after it is fully initialized.
virtual bool validateTarget(DiagnosticsEngine &Diags) const {
return true;
}
@@ -1113,6 +1315,11 @@ protected:
virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const {
return None;
}
+
+ private:
+ // Assert the values for the fractional and integral bits for each fixed point
+ // type follow the restrictions given in clause 6.2.6.3 of N1169.
+ void CheckFixedPointBits() const;
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
index 60becfb8ee76..31a674287915 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::TargetOptions class.
+/// Defines the clang::TargetOptions class.
///
//===----------------------------------------------------------------------===//
@@ -22,7 +22,7 @@
namespace clang {
-/// \brief Options for controlling the target.
+/// Options for controlling the target.
class TargetOptions {
public:
/// The name of the target triple to compile for.
@@ -47,7 +47,7 @@ public:
/// If given, the version string of the linker in use.
std::string LinkerVersion;
- /// \brief The list of target specific features to enable or disable, as written on the command line.
+ /// The list of target specific features to enable or disable, as written on the command line.
std::vector<std::string> FeaturesAsWritten;
/// The list of target specific features to enable or disable -- this should
@@ -57,9 +57,16 @@ public:
/// Supported OpenCL extensions and optional core features.
OpenCLOptions SupportedOpenCLOptions;
- /// \brief The list of OpenCL extensions to enable or disable, as written on
+ /// The list of OpenCL extensions to enable or disable, as written on
/// the command line.
std::vector<std::string> OpenCLExtensionsAsWritten;
+
+ /// If given, enables support for __int128_t and __uint128_t types.
+ bool ForceEnableInt128 = false;
+
+ /// \brief If enabled, use 32-bit pointers for accessing const/local/shared
+ /// address space.
+ bool NVPTXUseShortPointers = false;
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h
index ac99ad185f33..a0bc362e7a44 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::TemplateNameKind enum.
+/// Defines the clang::TemplateNameKind enum.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_TEMPLATEKINDS_H
@@ -16,7 +16,7 @@
namespace clang {
-/// \brief Specifies the kind of template name that an identifier refers to.
+/// Specifies the kind of template name that an identifier refers to.
/// Be careful when changing this: this enumeration is used in diagnostics.
enum TemplateNameKind {
/// The name does not refer to a template.
@@ -31,7 +31,7 @@ enum TemplateNameKind {
/// The name refers to a variable template whose specialization produces a
/// variable.
TNK_Var_template,
- /// The name refers to a dependent template name:
+ /// The name refers to a dependent template name:
/// \code
/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
/// typedef typename MetaFun::template apply<T1, T2>::type type;
@@ -39,7 +39,7 @@ enum TemplateNameKind {
/// \endcode
///
/// Here, "apply" is a dependent template name within the typename
- /// specifier in the typedef. "apply" is a nested template, and
+ /// specifier in the typedef. "apply" is a nested template, and
/// whether the template name is assumed to refer to a type template or a
/// function template depends on the context in which the template
/// name occurs.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
index 91c13244f9a0..30cb022f1cba 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
@@ -249,8 +249,10 @@ PUNCTUATOR(caretcaret, "^^")
// KEYMS - This is a keyword if Microsoft extensions are enabled
// KEYNOMS18 - This is a keyword that must never be enabled under
// MSVC <= v18.
-// KEYOPENCL - This is a keyword in OpenCL
-// KEYNOOPENCL - This is a keyword that is not supported in OpenCL
+// KEYOPENCLC - This is a keyword in OpenCL C
+// KEYOPENCLCXX - This is a keyword in OpenCL C++
+// KEYNOOPENCL - This is a keyword that is not supported in OpenCL C
+// nor in OpenCL C++.
// KEYALTIVEC - This is a keyword in AltiVec
// KEYZVECTOR - This is a keyword for the System z vector extensions,
// which are heavily based on AltiVec
@@ -260,6 +262,7 @@ PUNCTUATOR(caretcaret, "^^")
// BOOLSUPPORT - This is a keyword if 'bool' is a built-in type
// HALFSUPPORT - This is a keyword if 'half' is a built-in type
// WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type
+// CHAR8SUPPORT - This is a keyword if 'char8_t' is a built-in type
//
KEYWORD(auto , KEYALL)
KEYWORD(break , KEYALL)
@@ -380,9 +383,17 @@ KEYWORD(co_yield , KEYCOROUTINES)
MODULES_KEYWORD(module)
MODULES_KEYWORD(import)
+// C++ char8_t proposal
+KEYWORD(char8_t , CHAR8SUPPORT)
+
// C11 Extension
KEYWORD(_Float16 , KEYALL)
+// ISO/IEC JTC1 SC22 WG14 N1169 Extension
+KEYWORD(_Accum , KEYNOCXX)
+KEYWORD(_Fract , KEYNOCXX)
+KEYWORD(_Sat , KEYNOCXX)
+
// GNU Extensions (in impl-reserved namespace)
KEYWORD(_Decimal32 , KEYALL)
KEYWORD(_Decimal64 , KEYALL)
@@ -414,6 +425,7 @@ KEYWORD(typeof , KEYGNU)
KEYWORD(__FUNCDNAME__ , KEYMS)
KEYWORD(__FUNCSIG__ , KEYMS)
KEYWORD(L__FUNCTION__ , KEYMS)
+KEYWORD(L__FUNCSIG__ , KEYMS)
TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
@@ -463,6 +475,7 @@ TYPE_TRAIT_1(__has_unique_object_representations,
TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
+TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
KEYWORD(__underlying_type , KEYCXX)
// Embarcadero Expression Traits
@@ -520,36 +533,36 @@ KEYWORD(__unaligned , KEYMS)
KEYWORD(__super , KEYMS)
// OpenCL address space qualifiers
-KEYWORD(__global , KEYOPENCL)
-KEYWORD(__local , KEYOPENCL)
-KEYWORD(__constant , KEYOPENCL)
-KEYWORD(__private , KEYOPENCL)
-KEYWORD(__generic , KEYOPENCL)
-ALIAS("global", __global , KEYOPENCL)
-ALIAS("local", __local , KEYOPENCL)
-ALIAS("constant", __constant , KEYOPENCL)
-ALIAS("private", __private , KEYOPENCL)
-ALIAS("generic", __generic , KEYOPENCL)
+KEYWORD(__global , KEYOPENCLC | KEYOPENCLCXX)
+KEYWORD(__local , KEYOPENCLC | KEYOPENCLCXX)
+KEYWORD(__constant , KEYOPENCLC | KEYOPENCLCXX)
+KEYWORD(__private , KEYOPENCLC | KEYOPENCLCXX)
+KEYWORD(__generic , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("global", __global , KEYOPENCLC)
+ALIAS("local", __local , KEYOPENCLC)
+ALIAS("constant", __constant , KEYOPENCLC)
+ALIAS("private", __private , KEYOPENCLC)
+ALIAS("generic", __generic , KEYOPENCLC)
// OpenCL function qualifiers
-KEYWORD(__kernel , KEYOPENCL)
-ALIAS("kernel", __kernel , KEYOPENCL)
+KEYWORD(__kernel , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("kernel", __kernel , KEYOPENCLC | KEYOPENCLCXX)
// OpenCL access qualifiers
-KEYWORD(__read_only , KEYOPENCL)
-KEYWORD(__write_only , KEYOPENCL)
-KEYWORD(__read_write , KEYOPENCL)
-ALIAS("read_only", __read_only , KEYOPENCL)
-ALIAS("write_only", __write_only , KEYOPENCL)
-ALIAS("read_write", __read_write , KEYOPENCL)
+KEYWORD(__read_only , KEYOPENCLC | KEYOPENCLCXX)
+KEYWORD(__write_only , KEYOPENCLC | KEYOPENCLCXX)
+KEYWORD(__read_write , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("read_only", __read_only , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("write_only", __write_only , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("read_write", __read_write , KEYOPENCLC | KEYOPENCLCXX)
// OpenCL builtins
-KEYWORD(__builtin_astype , KEYOPENCL)
-KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
-#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCL)
+KEYWORD(__builtin_astype , KEYOPENCLC)
+KEYWORD(vec_step , KEYOPENCLC | KEYALTIVEC | KEYZVECTOR)
+#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCLC)
#include "clang/Basic/OpenCLImageTypes.def"
// OpenMP Type Traits
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
-KEYWORD(pipe , KEYOPENCL)
+KEYWORD(pipe , KEYOPENCLC)
// Borland Extensions.
KEYWORD(__pascal , KEYALL)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h
index f4ecb3eb306f..fb4b5252b70b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::TokenKind enum and support functions.
+/// Defines the clang::TokenKind enum and support functions.
///
//===----------------------------------------------------------------------===//
@@ -21,14 +21,14 @@ namespace clang {
namespace tok {
-/// \brief Provides a simple uniform namespace for tokens from all C languages.
+/// Provides a simple uniform namespace for tokens from all C languages.
enum TokenKind : unsigned short {
#define TOK(X) X,
#include "clang/Basic/TokenKinds.def"
NUM_TOKENS
};
-/// \brief Provides a namespace for preprocessor keywords which start with a
+/// Provides a namespace for preprocessor keywords which start with a
/// '#' at the beginning of the line.
enum PPKeywordKind {
#define PPKEYWORD(X) pp_##X,
@@ -36,7 +36,7 @@ enum PPKeywordKind {
NUM_PP_KEYWORDS
};
-/// \brief Provides a namespace for Objective-C keywords which start with
+/// Provides a namespace for Objective-C keywords which start with
/// an '@'.
enum ObjCKeywordKind {
#define OBJC1_AT_KEYWORD(X) objc_##X,
@@ -45,18 +45,18 @@ enum ObjCKeywordKind {
NUM_OBJC_KEYWORDS
};
-/// \brief Defines the possible values of an on-off-switch (C99 6.10.6p2).
+/// Defines the possible values of an on-off-switch (C99 6.10.6p2).
enum OnOffSwitch {
OOS_ON, OOS_OFF, OOS_DEFAULT
};
-/// \brief Determines the name of a token as used within the front end.
+/// Determines the name of a token as used within the front end.
///
/// The name of a token will be an internal name (such as "l_square")
/// and should not be used as part of diagnostic messages.
const char *getTokenName(TokenKind Kind) LLVM_READNONE;
-/// \brief Determines the spelling of simple punctuation tokens like
+/// Determines the spelling of simple punctuation tokens like
/// '!' or '%', and returns NULL for literal and annotation tokens.
///
/// This routine only retrieves the "simple" spelling of the token,
@@ -65,16 +65,16 @@ const char *getTokenName(TokenKind Kind) LLVM_READNONE;
/// Preprocessor::getSpelling().
const char *getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE;
-/// \brief Determines the spelling of simple keyword and contextual keyword
+/// Determines the spelling of simple keyword and contextual keyword
/// tokens like 'int' and 'dynamic_cast'. Returns NULL for other token kinds.
const char *getKeywordSpelling(TokenKind Kind) LLVM_READNONE;
-/// \brief Return true if this is a raw identifier or an identifier kind.
+/// Return true if this is a raw identifier or an identifier kind.
inline bool isAnyIdentifier(TokenKind K) {
return (K == tok::identifier) || (K == tok::raw_identifier);
}
-/// \brief Return true if this is a C or C++ string-literal (or
+/// Return true if this is a C or C++ string-literal (or
/// C++11 user-defined-string-literal) token.
inline bool isStringLiteral(TokenKind K) {
return K == tok::string_literal || K == tok::wide_string_literal ||
@@ -82,7 +82,7 @@ inline bool isStringLiteral(TokenKind K) {
K == tok::utf32_string_literal;
}
-/// \brief Return true if this is a "literal" kind, like a numeric
+/// Return true if this is a "literal" kind, like a numeric
/// constant, string, etc.
inline bool isLiteral(TokenKind K) {
return K == tok::numeric_constant || K == tok::char_constant ||
@@ -91,7 +91,7 @@ inline bool isLiteral(TokenKind K) {
isStringLiteral(K) || K == tok::angle_string_literal;
}
-/// \brief Return true if this is any of tok::annot_* kinds.
+/// Return true if this is any of tok::annot_* kinds.
inline bool isAnnotation(TokenKind K) {
#define ANNOTATION(NAME) \
if (K == tok::annot_##NAME) \
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
index 8ecd63f9c3cb..bdb426834a8c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines enumerations for the type traits support.
+/// Defines enumerations for the type traits support.
///
//===----------------------------------------------------------------------===//
@@ -17,7 +17,7 @@
namespace clang {
- /// \brief Names for traits that operate specifically on types.
+ /// Names for traits that operate specifically on types.
enum TypeTrait {
UTT_HasNothrowAssign,
UTT_HasNothrowMoveAssign,
@@ -80,19 +80,20 @@ namespace clang {
BTT_IsAssignable,
BTT_IsNothrowAssignable,
BTT_IsTriviallyAssignable,
- BTT_Last = BTT_IsTriviallyAssignable,
+ BTT_ReferenceBindsToTemporary,
+ BTT_Last = BTT_ReferenceBindsToTemporary,
TT_IsConstructible,
TT_IsNothrowConstructible,
TT_IsTriviallyConstructible
};
- /// \brief Names for the array type traits.
+ /// Names for the array type traits.
enum ArrayTypeTrait {
ATT_ArrayRank,
ATT_ArrayExtent
};
- /// \brief Names for the "expression or type" traits.
+ /// Names for the "expression or type" traits.
enum UnaryExprOrTypeTrait {
UETT_SizeOf,
UETT_AlignOf,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Version.h b/contrib/llvm/tools/clang/include/clang/Basic/Version.h
index 57dcf92c3b28..6d625c6ddb80 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Version.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines version macros and version-related utility functions
+/// Defines version macros and version-related utility functions
/// for Clang.
///
//===----------------------------------------------------------------------===//
@@ -20,40 +20,40 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
- /// \brief Retrieves the repository path (e.g., Subversion path) that
+ /// Retrieves the repository path (e.g., Subversion path) that
/// identifies the particular Clang branch, tag, or trunk from which this
/// Clang was built.
std::string getClangRepositoryPath();
- /// \brief Retrieves the repository path from which LLVM was built.
+ /// Retrieves the repository path from which LLVM was built.
///
/// This supports LLVM residing in a separate repository from clang.
std::string getLLVMRepositoryPath();
- /// \brief Retrieves the repository revision number (or identifer) from which
+ /// Retrieves the repository revision number (or identifier) from which
/// this Clang was built.
std::string getClangRevision();
- /// \brief Retrieves the repository revision number (or identifer) from which
+ /// Retrieves the repository revision number (or identifier) from which
/// LLVM was built.
///
/// If Clang and LLVM are in the same repository, this returns the same
/// string as getClangRevision.
std::string getLLVMRevision();
- /// \brief Retrieves the full repository version that is an amalgamation of
+ /// Retrieves the full repository version that is an amalgamation of
/// the information in getClangRepositoryPath() and getClangRevision().
std::string getClangFullRepositoryVersion();
- /// \brief Retrieves a string representing the complete clang version,
+ /// Retrieves a string representing the complete clang version,
/// which includes the clang version number, the repository version,
/// and the vendor tag.
std::string getClangFullVersion();
- /// \brief Like getClangFullVersion(), but with a custom tool name.
+ /// Like getClangFullVersion(), but with a custom tool name.
std::string getClangToolFullVersion(llvm::StringRef ToolName);
- /// \brief Retrieves a string representing the complete clang version suitable
+ /// Retrieves a string representing the complete clang version suitable
/// for use in the CPP __VERSION__ macro, which includes the clang version
/// number, the repository version, and the vendor tag.
std::string getClangFullCPPVersion();
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h
deleted file mode 100644
index da3b01903ed9..000000000000
--- a/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h
+++ /dev/null
@@ -1,168 +0,0 @@
-//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines the clang::VersionTuple class, which represents a version in
-/// the form major[.minor[.subminor]].
-///
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H
-#define LLVM_CLANG_BASIC_VERSIONTUPLE_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/Optional.h"
-#include <string>
-#include <tuple>
-
-namespace clang {
-
-/// \brief Represents a version number in the form major[.minor[.subminor[.build]]].
-class VersionTuple {
- unsigned Major : 31;
-
- unsigned UsesUnderscores : 1;
-
- unsigned Minor : 31;
- unsigned HasMinor : 1;
-
- unsigned Subminor : 31;
- unsigned HasSubminor : 1;
-
- unsigned Build : 31;
- unsigned HasBuild : 1;
-
-public:
- VersionTuple()
- : Major(0), UsesUnderscores(false), Minor(0), HasMinor(false),
- Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {}
-
- explicit VersionTuple(unsigned Major)
- : Major(Major), UsesUnderscores(false), Minor(0), HasMinor(false),
- Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {}
-
- explicit VersionTuple(unsigned Major, unsigned Minor,
- bool UsesUnderscores = false)
- : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor),
- HasMinor(true), Subminor(0), HasSubminor(false), Build(0),
- HasBuild(false) {}
-
- explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
- bool UsesUnderscores = false)
- : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor),
- HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(0),
- HasBuild(false) {}
-
- explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
- unsigned Build, bool UsesUnderscores = false)
- : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor),
- HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(Build),
- HasBuild(true) {}
-
- /// \brief Determine whether this version information is empty
- /// (e.g., all version components are zero).
- bool empty() const {
- return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
- }
-
- /// \brief Retrieve the major version number.
- unsigned getMajor() const { return Major; }
-
- /// \brief Retrieve the minor version number, if provided.
- Optional<unsigned> getMinor() const {
- if (!HasMinor)
- return None;
- return Minor;
- }
-
- /// \brief Retrieve the subminor version number, if provided.
- Optional<unsigned> getSubminor() const {
- if (!HasSubminor)
- return None;
- return Subminor;
- }
-
- /// \brief Retrieve the build version number, if provided.
- Optional<unsigned> getBuild() const {
- if (!HasBuild)
- return None;
- return Build;
- }
-
- bool usesUnderscores() const {
- return UsesUnderscores;
- }
-
- void UseDotAsSeparator() {
- UsesUnderscores = false;
- }
-
- /// \brief Determine if two version numbers are equivalent. If not
- /// provided, minor and subminor version numbers are considered to be zero.
- friend bool operator==(const VersionTuple& X, const VersionTuple &Y) {
- return X.Major == Y.Major && X.Minor == Y.Minor &&
- X.Subminor == Y.Subminor && X.Build == Y.Build;
- }
-
- /// \brief Determine if two version numbers are not equivalent.
- ///
- /// If not provided, minor and subminor version numbers are considered to be
- /// zero.
- friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
- return !(X == Y);
- }
-
- /// \brief Determine whether one version number precedes another.
- ///
- /// If not provided, minor and subminor version numbers are considered to be
- /// zero.
- friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
- return std::tie(X.Major, X.Minor, X.Subminor, X.Build) <
- std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build);
- }
-
- /// \brief Determine whether one version number follows another.
- ///
- /// If not provided, minor and subminor version numbers are considered to be
- /// zero.
- friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
- return Y < X;
- }
-
- /// \brief Determine whether one version number precedes or is
- /// equivalent to another.
- ///
- /// If not provided, minor and subminor version numbers are considered to be
- /// zero.
- friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
- return !(Y < X);
- }
-
- /// \brief Determine whether one version number follows or is
- /// equivalent to another.
- ///
- /// If not provided, minor and subminor version numbers are considered to be
- /// zero.
- friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
- return !(X < Y);
- }
-
- /// \brief Retrieve a string representation of the version number.
- std::string getAsString() const;
-
- /// \brief Try to parse the given string as a version number.
- /// \returns \c true if the string does not match the regular expression
- /// [0-9]+(\.[0-9]+){0,3}
- bool tryParse(StringRef string);
-};
-
-/// \brief Print a version number.
-raw_ostream& operator<<(raw_ostream &Out, const VersionTuple &V);
-
-} // end namespace clang
-#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
index 245452dd12b5..2480b91123c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
@@ -6,8 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
/// \file
-/// \brief Defines the virtual file system interface vfs::FileSystem.
+/// Defines the virtual file system interface vfs::FileSystem.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
@@ -15,6 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -23,8 +26,6 @@
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
#include <cassert>
#include <cstdint>
#include <ctime>
@@ -39,12 +40,12 @@ namespace llvm {
class MemoryBuffer;
-} // end namespace llvm
+} // namespace llvm
namespace clang {
namespace vfs {
-/// \brief The result of a \p status operation.
+/// The result of a \p status operation.
class Status {
std::string Name;
llvm::sys::fs::UniqueID UID;
@@ -52,14 +53,14 @@ class Status {
uint32_t User;
uint32_t Group;
uint64_t Size;
- llvm::sys::fs::file_type Type;
+ llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::status_error;
llvm::sys::fs::perms Perms;
public:
- bool IsVFSMapped; // FIXME: remove when files support multiple names
+ // FIXME: remove when files support multiple names
+ bool IsVFSMapped = false;
-public:
- Status() : Type(llvm::sys::fs::file_type::status_error) {}
+ Status() = default;
Status(const llvm::sys::fs::file_status &Status);
Status(StringRef Name, llvm::sys::fs::UniqueID UID,
llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
@@ -71,7 +72,7 @@ public:
static Status copyWithNewName(const llvm::sys::fs::file_status &In,
StringRef NewName);
- /// \brief Returns the name that should be used for this file or directory.
+ /// Returns the name that should be used for this file or directory.
StringRef getName() const { return Name; }
/// @name Status interface from llvm::sys::fs
@@ -97,18 +98,18 @@ public:
/// @}
};
-/// \brief Represents an open file.
+/// Represents an open file.
class File {
public:
- /// \brief Destroy the file after closing it (if open).
+ /// Destroy the file after closing it (if open).
/// Sub-classes should generally call close() inside their destructors. We
/// cannot do that from the base class, since close is virtual.
virtual ~File();
- /// \brief Get the status of the file.
+ /// Get the status of the file.
virtual llvm::ErrorOr<Status> status() = 0;
- /// \brief Get the name of the file
+ /// Get the name of the file
virtual llvm::ErrorOr<std::string> getName() {
if (auto Status = status())
return Status->getName().str();
@@ -116,32 +117,32 @@ public:
return Status.getError();
}
- /// \brief Get the contents of the file as a \p MemoryBuffer.
+ /// Get the contents of the file as a \p MemoryBuffer.
virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize = -1,
bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
- /// \brief Closes the file.
+ /// Closes the file.
virtual std::error_code close() = 0;
};
namespace detail {
-/// \brief An interface for virtual file systems to provide an iterator over the
+/// An interface for virtual file systems to provide an iterator over the
/// (non-recursive) contents of a directory.
struct DirIterImpl {
virtual ~DirIterImpl();
- /// \brief Sets \c CurrentEntry to the next entry in the directory on success,
+ /// Sets \c CurrentEntry to the next entry in the directory on success,
/// or returns a system-defined \c error_code.
virtual std::error_code increment() = 0;
Status CurrentEntry;
};
-} // end namespace detail
+} // namespace detail
-/// \brief An input iterator over the entries in a virtual path, similar to
+/// An input iterator over the entries in a virtual path, similar to
/// llvm::sys::fs::directory_iterator.
class directory_iterator {
std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
@@ -154,10 +155,10 @@ public:
Impl.reset(); // Normalize the end iterator to Impl == nullptr.
}
- /// \brief Construct an 'end' iterator.
+ /// Construct an 'end' iterator.
directory_iterator() = default;
- /// \brief Equivalent to operator++, with an error code.
+ /// Equivalent to operator++, with an error code.
directory_iterator &increment(std::error_code &EC) {
assert(Impl && "attempting to increment past end");
EC = Impl->increment();
@@ -181,11 +182,11 @@ public:
class FileSystem;
-/// \brief An input iterator over the recursive contents of a virtual path,
+/// An input iterator over the recursive contents of a virtual path,
/// similar to llvm::sys::fs::recursive_directory_iterator.
class recursive_directory_iterator {
- typedef std::stack<directory_iterator, std::vector<directory_iterator>>
- IterState;
+ using IterState =
+ std::stack<directory_iterator, std::vector<directory_iterator>>;
FileSystem *FS;
std::shared_ptr<IterState> State; // Input iterator semantics on copy.
@@ -193,10 +194,11 @@ class recursive_directory_iterator {
public:
recursive_directory_iterator(FileSystem &FS, const Twine &Path,
std::error_code &EC);
- /// \brief Construct an 'end' iterator.
+
+ /// Construct an 'end' iterator.
recursive_directory_iterator() = default;
- /// \brief Equivalent to operator++, with an error code.
+ /// Equivalent to operator++, with an error code.
recursive_directory_iterator &increment(std::error_code &EC);
const Status &operator*() const { return *State->top(); }
@@ -209,21 +211,22 @@ public:
return !(*this == RHS);
}
- /// \brief Gets the current level. Starting path is at level 0.
+ /// Gets the current level. Starting path is at level 0.
int level() const {
- assert(State->size() && "Cannot get level without any iteration state");
+ assert(!State->empty() && "Cannot get level without any iteration state");
return State->size()-1;
}
};
-/// \brief The virtual file system interface.
+/// The virtual file system interface.
class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
public:
virtual ~FileSystem();
- /// \brief Get the status of the entry at \p Path, if one exists.
+ /// Get the status of the entry at \p Path, if one exists.
virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
- /// \brief Get a \p File object for the file at \p Path, if one exists.
+
+ /// Get a \p File object for the file at \p Path, if one exists.
virtual llvm::ErrorOr<std::unique_ptr<File>>
openFileForRead(const Twine &Path) = 0;
@@ -233,7 +236,7 @@ public:
getBufferForFile(const Twine &Name, int64_t FileSize = -1,
bool RequiresNullTerminator = true, bool IsVolatile = false);
- /// \brief Get a directory_iterator for \p Dir.
+ /// Get a directory_iterator for \p Dir.
/// \note The 'end' iterator is directory_iterator().
virtual directory_iterator dir_begin(const Twine &Dir,
std::error_code &EC) = 0;
@@ -241,9 +244,16 @@ public:
/// Set the working directory. This will affect all following operations on
/// this file system and may propagate down for nested file systems.
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
+
/// Get the working directory of this file system.
virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
+ /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve
+ /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`.
+ /// This returns errc::operation_not_permitted if not implemented by subclass.
+ virtual std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const;
+
/// Check whether a file exists. Provided for convenience.
bool exists(const Twine &Path);
@@ -261,11 +271,11 @@ public:
std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
};
-/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
+/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
/// the operating system.
IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
-/// \brief A file system that allows overlaying one \p AbstractFileSystem on top
+/// A file system that allows overlaying one \p AbstractFileSystem on top
/// of another.
///
/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
@@ -276,14 +286,16 @@ IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
/// that exists in more than one file system, the file in the top-most file
/// system overrides the other(s).
class OverlayFileSystem : public FileSystem {
- typedef SmallVector<IntrusiveRefCntPtr<FileSystem>, 1> FileSystemList;
- /// \brief The stack of file systems, implemented as a list in order of
+ using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
+
+ /// The stack of file systems, implemented as a list in order of
/// their addition.
FileSystemList FSList;
public:
OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
- /// \brief Pushes a file system on top of the stack.
+
+ /// Pushes a file system on top of the stack.
void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
llvm::ErrorOr<Status> status(const Twine &Path) override;
@@ -292,22 +304,27 @@ public:
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override;
+
+ using iterator = FileSystemList::reverse_iterator;
+ using const_iterator = FileSystemList::const_reverse_iterator;
- typedef FileSystemList::reverse_iterator iterator;
-
- /// \brief Get an iterator pointing to the most recently added file system.
+ /// Get an iterator pointing to the most recently added file system.
iterator overlays_begin() { return FSList.rbegin(); }
+ const_iterator overlays_begin() const { return FSList.rbegin(); }
- /// \brief Get an iterator pointing one-past the least recently added file
+ /// Get an iterator pointing one-past the least recently added file
/// system.
iterator overlays_end() { return FSList.rend(); }
+ const_iterator overlays_end() const { return FSList.rend(); }
};
namespace detail {
class InMemoryDirectory;
-} // end namespace detail
+} // namespace detail
/// An in-memory file system.
class InMemoryFileSystem : public FileSystem {
@@ -330,6 +347,7 @@ public:
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.
/// If present, User, Group, Type and Perms apply to the newly-created file
/// or directory.
@@ -344,6 +362,7 @@ public:
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; }
@@ -351,16 +370,26 @@ public:
llvm::ErrorOr<std::unique_ptr<File>>
openFileForRead(const Twine &Path) override;
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
return WorkingDirectory;
}
+ /// Canonicalizes \p Path by combining with the current working
+ /// directory and normalizing the path (e.g. remove dots). If the current
+ /// working directory is not set, this returns errc::operation_not_permitted.
+ ///
+ /// This doesn't resolve symlinks as they are not supported in in-memory file
+ /// system.
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override;
+
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
};
-/// \brief Get a globally unique ID for a virtual file or directory.
+/// Get a globally unique ID for a virtual file or directory.
llvm::sys::fs::UniqueID getNextVirtualUniqueID();
-/// \brief Gets a \p FileSystem for a virtual file system described in YAML
+/// Gets a \p FileSystem for a virtual file system described in YAML
/// format.
IntrusiveRefCntPtr<FileSystem>
getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
@@ -376,7 +405,7 @@ struct YAMLVFSEntry {
std::string RPath;
};
-/// \brief Collect all pairs of <virtual path, real path> entries from the
+/// Collect all pairs of <virtual path, real path> entries from the
/// \p YAMLFilePath. This is used by the module dependency collector to forward
/// the entries into the reproducer output VFS YAML file.
void collectVFSFromYAML(
@@ -419,7 +448,7 @@ public:
void write(llvm::raw_ostream &OS);
};
-} // end namespace vfs
-} // end namespace clang
+} // namespace vfs
+} // namespace clang
#endif // LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h b/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h
index cc839d789e7f..c5ab62436fe0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::Visibility enumeration and various utility
+/// Defines the clang::Visibility enumeration and various utility
/// functions.
///
//===----------------------------------------------------------------------===//
@@ -16,10 +16,12 @@
#define LLVM_CLANG_BASIC_VISIBILITY_H
#include "clang/Basic/Linkage.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
-/// \brief Describes the different kinds of visibility that a declaration
+/// Describes the different kinds of visibility that a declaration
/// may have.
///
/// Visibility determines how a declaration interacts with the dynamic
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def b/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def
index 21550fe2dd55..d2d2540e5005 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def
@@ -12,6 +12,10 @@
//
//===----------------------------------------------------------------------===//
+#ifndef PROC_WITH_FEAT
+#define PROC_WITH_FEAT(ENUM, STRING, IS64BIT, KEYFEATURE) \
+ PROC(ENUM, STRING, IS64BIT)
+#endif
#ifndef PROC
#define PROC(ENUM, STRING, IS64BIT)
@@ -21,6 +25,18 @@
#define PROC_ALIAS(ENUM, ALIAS)
#endif
+#ifndef FEATURE
+#define FEATURE(ENUM)
+#endif
+
+#ifndef CPU_SPECIFIC
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES)
+#endif
+
+#ifndef CPU_SPECIFIC_ALIAS
+#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME)
+#endif
+
#define PROC_64_BIT true
#define PROC_32_BIT false
@@ -77,7 +93,7 @@ PROC(Nocona, "nocona", PROC_64_BIT)
/// \name Core
/// Core microarchitecture based processors.
//@{
-PROC(Core2, "core2", PROC_64_BIT)
+PROC_WITH_FEAT(Core2, "core2", PROC_64_BIT, FEATURE_SSSE3)
/// This enumerator, like Yonah, is a bit odd. It is another
/// codename which GCC no longer accepts as an option to -march, but Clang
@@ -89,67 +105,74 @@ PROC(Penryn, "penryn", PROC_64_BIT)
/// \name Atom
/// Atom processors
//@{
-PROC(Bonnell, "bonnell", PROC_64_BIT)
+PROC_WITH_FEAT(Bonnell, "bonnell", PROC_64_BIT, FEATURE_SSSE3)
PROC_ALIAS(Bonnell, "atom")
-PROC(Silvermont, "silvermont", PROC_64_BIT)
+PROC_WITH_FEAT(Silvermont, "silvermont", PROC_64_BIT, FEATURE_SSE4_2)
PROC_ALIAS(Silvermont, "slm")
PROC(Goldmont, "goldmont", PROC_64_BIT)
+PROC(GoldmontPlus, "goldmont-plus", PROC_64_BIT)
+
+PROC(Tremont, "tremont", PROC_64_BIT)
//@}
/// \name Nehalem
/// Nehalem microarchitecture based processors.
-PROC(Nehalem, "nehalem", PROC_64_BIT)
+PROC_WITH_FEAT(Nehalem, "nehalem", PROC_64_BIT, FEATURE_SSE4_2)
PROC_ALIAS(Nehalem, "corei7")
/// \name Westmere
/// Westmere microarchitecture based processors.
-PROC(Westmere, "westmere", PROC_64_BIT)
+PROC_WITH_FEAT(Westmere, "westmere", PROC_64_BIT, FEATURE_PCLMUL)
/// \name Sandy Bridge
/// Sandy Bridge microarchitecture based processors.
-PROC(SandyBridge, "sandybridge", PROC_64_BIT)
+PROC_WITH_FEAT(SandyBridge, "sandybridge", PROC_64_BIT, FEATURE_AVX)
PROC_ALIAS(SandyBridge, "corei7-avx")
/// \name Ivy Bridge
/// Ivy Bridge microarchitecture based processors.
-PROC(IvyBridge, "ivybridge", PROC_64_BIT)
+PROC_WITH_FEAT(IvyBridge, "ivybridge", PROC_64_BIT, FEATURE_AVX)
PROC_ALIAS(IvyBridge, "core-avx-i")
/// \name Haswell
/// Haswell microarchitecture based processors.
-PROC(Haswell, "haswell", PROC_64_BIT)
+PROC_WITH_FEAT(Haswell, "haswell", PROC_64_BIT, FEATURE_AVX2)
PROC_ALIAS(Haswell, "core-avx2")
/// \name Broadwell
/// Broadwell microarchitecture based processors.
-PROC(Broadwell, "broadwell", PROC_64_BIT)
+PROC_WITH_FEAT(Broadwell, "broadwell", PROC_64_BIT, FEATURE_AVX2)
/// \name Skylake Client
/// Skylake client microarchitecture based processors.
-PROC(SkylakeClient, "skylake", PROC_64_BIT)
+PROC_WITH_FEAT(SkylakeClient, "skylake", PROC_64_BIT, FEATURE_AVX2)
/// \name Skylake Server
/// Skylake server microarchitecture based processors.
-PROC(SkylakeServer, "skylake-avx512", PROC_64_BIT)
+PROC_WITH_FEAT(SkylakeServer, "skylake-avx512", PROC_64_BIT, FEATURE_AVX512F)
PROC_ALIAS(SkylakeServer, "skx")
/// \name Cannonlake Client
/// Cannonlake client microarchitecture based processors.
-PROC(Cannonlake, "cannonlake", PROC_64_BIT)
+PROC_WITH_FEAT(Cannonlake, "cannonlake", PROC_64_BIT, FEATURE_AVX512VBMI)
/// \name Icelake Client
/// Icelake client microarchitecture based processors.
-PROC(Icelake, "icelake", PROC_64_BIT)
+PROC(IcelakeClient, "icelake-client", PROC_64_BIT)
+
+/// \name Icelake Server
+/// Icelake server microarchitecture based processors.
+PROC(IcelakeServer, "icelake-server", PROC_64_BIT)
/// \name Knights Landing
/// Knights Landing processor.
-PROC(KNL, "knl", PROC_64_BIT)
+PROC_WITH_FEAT(KNL, "knl", PROC_64_BIT, FEATURE_AVX512F)
/// \name Knights Mill
/// Knights Mill processor.
-PROC(KNM, "knm", PROC_64_BIT)
+PROC_WITH_FEAT(KNM, "knm", PROC_64_BIT, FEATURE_AVX5124FMAPS)
/// \name Lakemont
/// Lakemont microarchitecture based processors.
@@ -186,30 +209,30 @@ PROC(K8SSE3, "k8-sse3", PROC_64_BIT)
PROC_ALIAS(K8SSE3, "athlon64-sse3")
PROC_ALIAS(K8SSE3, "opteron-sse3")
-PROC(AMDFAM10, "amdfam10", PROC_64_BIT)
+PROC_WITH_FEAT(AMDFAM10, "amdfam10", PROC_64_BIT, FEATURE_SSE4_A)
PROC_ALIAS(AMDFAM10, "barcelona")
//@}
/// \name Bobcat
/// Bobcat architecture processors.
//@{
-PROC(BTVER1, "btver1", PROC_64_BIT)
-PROC(BTVER2, "btver2", PROC_64_BIT)
+PROC_WITH_FEAT(BTVER1, "btver1", PROC_64_BIT, FEATURE_SSE4_A)
+PROC_WITH_FEAT(BTVER2, "btver2", PROC_64_BIT, FEATURE_BMI)
//@}
/// \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)
+PROC_WITH_FEAT(BDVER1, "bdver1", PROC_64_BIT, FEATURE_XOP)
+PROC_WITH_FEAT(BDVER2, "bdver2", PROC_64_BIT, FEATURE_FMA)
+PROC_WITH_FEAT(BDVER3, "bdver3", PROC_64_BIT, FEATURE_FMA)
+PROC_WITH_FEAT(BDVER4, "bdver4", PROC_64_BIT, FEATURE_AVX2)
//@}
/// \name zen
/// Zen architecture processors.
//@{
-PROC(ZNVER1, "znver1", PROC_64_BIT)
+PROC_WITH_FEAT(ZNVER1, "znver1", PROC_64_BIT, FEATURE_AVX2)
//@}
/// This specification is deprecated and will be removed in the future.
@@ -225,8 +248,84 @@ PROC(x86_64, "x86-64", PROC_64_BIT)
PROC(Geode, "geode", PROC_32_BIT)
//@}
-
+// List of CPU Supports features in order. These need to remain in the order
+// required by attribute 'target' checking. Note that not all are supported/
+// prioritized by GCC, so synchronization with GCC's implementation may require
+// changing some existing values.
+FEATURE(FEATURE_CMOV)
+FEATURE(FEATURE_MMX)
+FEATURE(FEATURE_SSE)
+FEATURE(FEATURE_SSE2)
+FEATURE(FEATURE_SSE3)
+FEATURE(FEATURE_SSSE3)
+FEATURE(FEATURE_SSE4_A)
+FEATURE(FEATURE_SSE4_1)
+FEATURE(FEATURE_SSE4_2)
+FEATURE(FEATURE_POPCNT)
+FEATURE(FEATURE_AES)
+FEATURE(FEATURE_PCLMUL)
+FEATURE(FEATURE_AVX)
+FEATURE(FEATURE_BMI)
+FEATURE(FEATURE_FMA4)
+FEATURE(FEATURE_XOP)
+FEATURE(FEATURE_FMA)
+FEATURE(FEATURE_BMI2)
+FEATURE(FEATURE_AVX2)
+FEATURE(FEATURE_AVX512F)
+FEATURE(FEATURE_AVX512VL)
+FEATURE(FEATURE_AVX512BW)
+FEATURE(FEATURE_AVX512DQ)
+FEATURE(FEATURE_AVX512CD)
+FEATURE(FEATURE_AVX512ER)
+FEATURE(FEATURE_AVX512PF)
+FEATURE(FEATURE_AVX512VBMI)
+FEATURE(FEATURE_AVX512IFMA)
+FEATURE(FEATURE_AVX5124VNNIW)
+FEATURE(FEATURE_AVX5124FMAPS)
+FEATURE(FEATURE_AVX512VPOPCNTDQ)
+
+
+// FIXME: When commented out features are supported in LLVM, enable them here.
+CPU_SPECIFIC("generic", 'A', "")
+CPU_SPECIFIC("pentium", 'B', "")
+CPU_SPECIFIC("pentium_pro", 'C', "+cmov")
+CPU_SPECIFIC("pentium_mmx", 'D', "+mmx")
+CPU_SPECIFIC("pentium_ii", 'E', "+cmov,+mmx")
+CPU_SPECIFIC("pentium_iii", 'H', "+cmov,+mmx,+sse")
+CPU_SPECIFIC("pentium_iii_no_xmm_regs", 'H',"+cmov,+sse")
+CPU_SPECIFIC("pentium_4", 'J', "+cmov,+mmx,+sse,+sse2")
+CPU_SPECIFIC("pentium_m", 'K', "+cmov,+mmx,+sse,+sse2")
+CPU_SPECIFIC("pentium_4_sse3", 'L', "+cmov,+mmx,+sse,+sse2,+sse3")
+CPU_SPECIFIC("core_2_duo_ssse3", 'M', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3")
+CPU_SPECIFIC("core_2_duo_sse4_1", 'N', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1")
+CPU_SPECIFIC("atom", 'O', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+movbe")
+CPU_SPECIFIC("atom_sse4_2", 'c', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt")
+CPU_SPECIFIC("core_i7_sse4_2", 'P', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt")
+CPU_SPECIFIC("core_aes_pclmulqdq", 'Q', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt")
+CPU_SPECIFIC("atom_sse4_2_movbe", 'd', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt")
+CPU_SPECIFIC("goldmont", 'i', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt")
+CPU_SPECIFIC("sandybridge", 'R', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+avx")
+CPU_SPECIFIC_ALIAS("core_2nd_gen_avx", "sandybridge")
+CPU_SPECIFIC("ivybridge", 'S', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+f16c,+avx")
+CPU_SPECIFIC_ALIAS("core_3rd_gen_avx", "ivybridge")
+CPU_SPECIFIC("haswell", 'V', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2")
+CPU_SPECIFIC_ALIAS("core_4th_gen_avx", "haswell")
+CPU_SPECIFIC("core_4th_gen_avx_tsx", 'W', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2")
+CPU_SPECIFIC("broadwell", 'X', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx")
+CPU_SPECIFIC_ALIAS("core_5th_gen_avx", "broadwell")
+CPU_SPECIFIC("core_5th_gen_avx_tsx", 'Y', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx")
+CPU_SPECIFIC("knl", 'Z', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512f,+adx,+avx512er,+avx512pf,+avx512cd")
+CPU_SPECIFIC_ALIAS("mic_avx512", "knl")
+CPU_SPECIFIC("skylake", 'b', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx,+mpx")
+CPU_SPECIFIC( "skylake_avx512", 'a', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512dq,+avx512f,+adx,+avx512cd,+avx512bw,+avx512vl,+clwb")
+CPU_SPECIFIC("cannonlake", 'e', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512dq,+avx512f,+adx,+avx512ifma,+avx512cd,+avx512bw,+avx512vl,+avx512vbmi")
+CPU_SPECIFIC("knm", 'j', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512f,+adx,+avx512er,+avx512pf,+avx512cd,+avx5124fmaps,+avx5124vnniw,+avx512vpopcntdq")
+
+#undef CPU_SPECIFIC_ALIAS
+#undef CPU_SPECIFIC
#undef PROC_64_BIT
#undef PROC_32_BIT
+#undef FEATURE
#undef PROC
#undef PROC_ALIAS
+#undef PROC_WITH_FEAT
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/XRayInstr.h b/contrib/llvm/tools/clang/include/clang/Basic/XRayInstr.h
new file mode 100644
index 000000000000..13c3032a5cca
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/XRayInstr.h
@@ -0,0 +1,70 @@
+//===--- XRayInstr.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Defines the clang::XRayInstrKind enum.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_XRAYINSTR_H
+#define LLVM_CLANG_BASIC_XRAYINSTR_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
+
+namespace clang {
+
+using XRayInstrMask = uint32_t;
+
+namespace XRayInstrKind {
+
+// TODO: Auto-generate these as we add more instrumentation kinds.
+enum XRayInstrOrdinal : XRayInstrMask {
+ XRIO_Function,
+ XRIO_Custom,
+ XRIO_Typed,
+ XRIO_Count
+};
+
+constexpr XRayInstrMask None = 0;
+constexpr XRayInstrMask Function = 1U << XRIO_Function;
+constexpr XRayInstrMask Custom = 1U << XRIO_Custom;
+constexpr XRayInstrMask Typed = 1U << XRIO_Typed;
+constexpr XRayInstrMask All = Function | Custom | Typed;
+
+} // namespace XRayInstrKind
+
+struct XRayInstrSet {
+ bool has(XRayInstrMask K) const {
+ assert(llvm::isPowerOf2_32(K));
+ return Mask & K;
+ }
+
+ bool hasOneOf(XRayInstrMask K) const { return Mask & K; }
+
+ void set(XRayInstrMask K, bool Value) {
+ assert(llvm::isPowerOf2_32(K));
+ Mask = Value ? (Mask | K) : (Mask & ~K);
+ }
+
+ void clear(XRayInstrMask K = XRayInstrKind::All) { Mask &= ~K; }
+
+ bool empty() const { return Mask == 0; }
+
+ XRayInstrMask Mask = 0;
+};
+
+XRayInstrMask parseXRayInstrValue(StringRef Value);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_XRAYINSTR_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/XRayLists.h b/contrib/llvm/tools/clang/include/clang/Basic/XRayLists.h
index 8cfea70e280a..244b1d533b7c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/XRayLists.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/XRayLists.h
@@ -26,12 +26,13 @@ namespace clang {
class XRayFunctionFilter {
std::unique_ptr<llvm::SpecialCaseList> AlwaysInstrument;
std::unique_ptr<llvm::SpecialCaseList> NeverInstrument;
+ std::unique_ptr<llvm::SpecialCaseList> AttrList;
SourceManager &SM;
public:
XRayFunctionFilter(ArrayRef<std::string> AlwaysInstrumentPaths,
ArrayRef<std::string> NeverInstrumentPaths,
- SourceManager &SM);
+ ArrayRef<std::string> AttrListPaths, SourceManager &SM);
enum class ImbueAttribute {
NONE,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_fp16.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_fp16.td
new file mode 100644
index 000000000000..bc15a22d84a6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_fp16.td
@@ -0,0 +1,131 @@
+//===--- arm_fp16.td - ARM FP16 compiler interface ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TableGen definitions from which the ARM FP16 header
+// file will be generated.
+//
+//===----------------------------------------------------------------------===//
+
+include "arm_neon_incl.td"
+
+// ARMv8.2-A FP16 intrinsics.
+let ArchGuard = "defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) && defined(__aarch64__)" in {
+
+ // Negate
+ def VNEGSH : SInst<"vneg", "ss", "Sh">;
+
+ // Reciprocal/Sqrt
+ def SCALAR_FRECPSH : IInst<"vrecps", "sss", "Sh">;
+ def FSQRTSH : SInst<"vsqrt", "ss", "Sh">;
+ def SCALAR_FRSQRTSH : IInst<"vrsqrts", "sss", "Sh">;
+
+ // Reciprocal Estimate
+ def SCALAR_FRECPEH : IInst<"vrecpe", "ss", "Sh">;
+
+ // Reciprocal Exponent
+ def SCALAR_FRECPXH : IInst<"vrecpx", "ss", "Sh">;
+
+ // Reciprocal Square Root Estimate
+ def SCALAR_FRSQRTEH : IInst<"vrsqrte", "ss", "Sh">;
+
+ // Rounding
+ def FRINTZ_S64H : SInst<"vrnd", "ss", "Sh">;
+ def FRINTA_S64H : SInst<"vrnda", "ss", "Sh">;
+ def FRINTI_S64H : SInst<"vrndi", "ss", "Sh">;
+ def FRINTM_S64H : SInst<"vrndm", "ss", "Sh">;
+ def FRINTN_S64H : SInst<"vrndn", "ss", "Sh">;
+ def FRINTP_S64H : SInst<"vrndp", "ss", "Sh">;
+ def FRINTX_S64H : SInst<"vrndx", "ss", "Sh">;
+
+ // Conversion
+ def SCALAR_SCVTFSH : SInst<"vcvth_f16", "Ys", "silUsUiUl">;
+ def SCALAR_FCVTZSH : SInst<"vcvt_s16", "$s", "Sh">;
+ def SCALAR_FCVTZSH1 : SInst<"vcvt_s32", "Is", "Sh">;
+ def SCALAR_FCVTZSH2 : SInst<"vcvt_s64", "Ls", "Sh">;
+ def SCALAR_FCVTZUH : SInst<"vcvt_u16", "bs", "Sh">;
+ def SCALAR_FCVTZUH1 : SInst<"vcvt_u32", "Us", "Sh">;
+ def SCALAR_FCVTZUH2 : SInst<"vcvt_u64", "Os", "Sh">;
+ def SCALAR_FCVTASH : SInst<"vcvta_s16", "$s", "Sh">;
+ def SCALAR_FCVTASH1 : SInst<"vcvta_s32", "Is", "Sh">;
+ def SCALAR_FCVTASH2 : SInst<"vcvta_s64", "Ls", "Sh">;
+ def SCALAR_FCVTAUH : SInst<"vcvta_u16", "bs", "Sh">;
+ def SCALAR_FCVTAUH1 : SInst<"vcvta_u32", "Us", "Sh">;
+ def SCALAR_FCVTAUH2 : SInst<"vcvta_u64", "Os", "Sh">;
+ def SCALAR_FCVTMSH : SInst<"vcvtm_s16", "$s", "Sh">;
+ def SCALAR_FCVTMSH1 : SInst<"vcvtm_s32", "Is", "Sh">;
+ def SCALAR_FCVTMSH2 : SInst<"vcvtm_s64", "Ls", "Sh">;
+ def SCALAR_FCVTMUH : SInst<"vcvtm_u16", "bs", "Sh">;
+ def SCALAR_FCVTMUH1 : SInst<"vcvtm_u32", "Us", "Sh">;
+ def SCALAR_FCVTMUH2 : SInst<"vcvtm_u64", "Os", "Sh">;
+ def SCALAR_FCVTNSH : SInst<"vcvtn_s16", "$s", "Sh">;
+ def SCALAR_FCVTNSH1 : SInst<"vcvtn_s32", "Is", "Sh">;
+ def SCALAR_FCVTNSH2 : SInst<"vcvtn_s64", "Ls", "Sh">;
+ def SCALAR_FCVTNUH : SInst<"vcvtn_u16", "bs", "Sh">;
+ def SCALAR_FCVTNUH1 : SInst<"vcvtn_u32", "Us", "Sh">;
+ def SCALAR_FCVTNUH2 : SInst<"vcvtn_u64", "Os", "Sh">;
+ def SCALAR_FCVTPSH : SInst<"vcvtp_s16", "$s", "Sh">;
+ def SCALAR_FCVTPSH1 : SInst<"vcvtp_s32", "Is", "Sh">;
+ def SCALAR_FCVTPSH2 : SInst<"vcvtp_s64", "Ls", "Sh">;
+ def SCALAR_FCVTPUH : SInst<"vcvtp_u16", "bs", "Sh">;
+ def SCALAR_FCVTPUH1 : SInst<"vcvtp_u32", "Us", "Sh">;
+ def SCALAR_FCVTPUH2 : SInst<"vcvtp_u64", "Os", "Sh">;
+ let isVCVT_N = 1 in {
+ def SCALAR_SCVTFSHO : SInst<"vcvth_n_f16", "Ysi", "silUsUiUl">;
+ def SCALAR_FCVTZSHO : SInst<"vcvt_n_s16", "$si", "Sh">;
+ def SCALAR_FCVTZSH1O: SInst<"vcvt_n_s32", "Isi", "Sh">;
+ def SCALAR_FCVTZSH2O: SInst<"vcvt_n_s64", "Lsi", "Sh">;
+ def SCALAR_FCVTZUHO : SInst<"vcvt_n_u16", "bsi", "Sh">;
+ def SCALAR_FCVTZUH1O: SInst<"vcvt_n_u32", "Usi", "Sh">;
+ def SCALAR_FCVTZUH2O: SInst<"vcvt_n_u64", "Osi", "Sh">;
+ }
+ // Comparison
+ def SCALAR_CMEQRH : SInst<"vceq", "bss", "Sh">;
+ def SCALAR_CMEQZH : SInst<"vceqz", "bs", "Sh">;
+ def SCALAR_CMGERH : SInst<"vcge", "bss", "Sh">;
+ def SCALAR_CMGEZH : SInst<"vcgez", "bs", "Sh">;
+ def SCALAR_CMGTRH : SInst<"vcgt", "bss", "Sh">;
+ def SCALAR_CMGTZH : SInst<"vcgtz", "bs", "Sh">;
+ def SCALAR_CMLERH : SInst<"vcle", "bss", "Sh">;
+ def SCALAR_CMLEZH : SInst<"vclez", "bs", "Sh">;
+ def SCALAR_CMLTH : SInst<"vclt", "bss", "Sh">;
+ def SCALAR_CMLTZH : SInst<"vcltz", "bs", "Sh">;
+
+ // Absolute Compare Mask Greater Than Or Equal
+ def SCALAR_FACGEH : IInst<"vcage", "bss", "Sh">;
+ def SCALAR_FACLEH : IInst<"vcale", "bss", "Sh">;
+
+ // Absolute Compare Mask Greater Than
+ def SCALAR_FACGT : IInst<"vcagt", "bss", "Sh">;
+ def SCALAR_FACLT : IInst<"vcalt", "bss", "Sh">;
+
+ // Scalar Absolute Value
+ def SCALAR_ABSH : SInst<"vabs", "ss", "Sh">;
+
+ // Scalar Absolute Difference
+ def SCALAR_ABDH: IInst<"vabd", "sss", "Sh">;
+
+ // Add/Sub
+ def VADDSH : SInst<"vadd", "sss", "Sh">;
+ def VSUBHS : SInst<"vsub", "sss", "Sh">;
+
+ // Max/Min
+ def VMAXHS : SInst<"vmax", "sss", "Sh">;
+ def VMINHS : SInst<"vmin", "sss", "Sh">;
+ def FMAXNMHS : SInst<"vmaxnm", "sss", "Sh">;
+ def FMINNMHS : SInst<"vminnm", "sss", "Sh">;
+
+ // Multiplication/Division
+ def VMULHS : SInst<"vmul", "sss", "Sh">;
+ def MULXHS : SInst<"vmulx", "sss", "Sh">;
+ def FDIVHS : SInst<"vdiv", "sss", "Sh">;
+
+ // Vector fused multiply-add operations
+ def VFMAHS : SInst<"vfma", "ssss", "Sh">;
+ def VFMSHS : SInst<"vfms", "ssss", "Sh">;
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
index d5c16a91a34f..c35336166c39 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
@@ -11,309 +11,8 @@
// file will be generated. See ARM document DUI0348B.
//
//===----------------------------------------------------------------------===//
-//
-// Each intrinsic is a subclass of the Inst class. An intrinsic can either
-// generate a __builtin_* call or it can expand to a set of generic operations.
-//
-// The operations are subclasses of Operation providing a list of DAGs, the
-// last of which is the return value. The available DAG nodes are documented
-// below.
-//
-//===----------------------------------------------------------------------===//
-
-// The base Operation class. All operations must subclass this.
-class Operation<list<dag> ops=[]> {
- list<dag> Ops = ops;
- bit Unavailable = 0;
-}
-// An operation that only contains a single DAG.
-class Op<dag op> : Operation<[op]>;
-// A shorter version of Operation - takes a list of DAGs. The last of these will
-// be the return value.
-class LOp<list<dag> ops> : Operation<ops>;
-
-// These defs and classes are used internally to implement the SetTheory
-// expansion and should be ignored.
-foreach Index = 0-63 in
- def sv##Index;
-class MaskExpand;
-
-//===----------------------------------------------------------------------===//
-// Available operations
-//===----------------------------------------------------------------------===//
-
-// DAG arguments can either be operations (documented below) or variables.
-// Variables are prefixed with '$'. There are variables for each input argument,
-// with the name $pN, where N starts at zero. So the zero'th argument will be
-// $p0, the first $p1 etc.
-
-// op - Binary or unary operator, depending on the number of arguments. The
-// operator itself is just treated as a raw string and is not checked.
-// example: (op "+", $p0, $p1) -> "__p0 + __p1".
-// (op "-", $p0) -> "-__p0"
-def op;
-// call - Invoke another intrinsic. The input types are type checked and
-// disambiguated. If there is no intrinsic defined that takes
-// the given types (or if there is a type ambiguity) an error is
-// generated at tblgen time. The name of the intrinsic is the raw
-// name as given to the Inst class (not mangled).
-// example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)"
-// (assuming $p0 has type int16x8_t).
-def call;
-// cast - Perform a cast to a different type. This gets emitted as a static
-// C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use
-// "bitcast".
-//
-// The syntax is (cast MOD* VAL). The last argument is the value to
-// cast, preceded by a sequence of type modifiers. The target type
-// starts off as the type of VAL, and is modified by MOD in sequence.
-// The available modifiers are:
-// - $X - Take the type of parameter/variable X. For example:
-// (cast $p0, $p1) would cast $p1 to the type of $p0.
-// - "R" - The type of the return type.
-// - A typedef string - A NEON or stdint.h type that is then parsed.
-// for example: (cast "uint32x4_t", $p0).
-// - "U" - Make the type unsigned.
-// - "S" - Make the type signed.
-// - "H" - Halve the number of lanes in the type.
-// - "D" - Double the number of lanes in the type.
-// - "8" - Convert type to an equivalent vector of 8-bit signed
-// integers.
-// example: (cast "R", "U", $p0) -> "(uint32x4_t)__p0" (assuming the return
-// value is of type "int32x4_t".
-// (cast $p0, "D", "8", $p1) -> "(int8x16_t)__p1" (assuming __p0
-// has type float64x1_t or any other vector type of 64 bits).
-// (cast "int32_t", $p2) -> "(int32_t)__p2"
-def cast;
-// bitcast - Same as "cast", except a reinterpret-cast is produced:
-// (bitcast "T", $p0) -> "*(T*)&__p0".
-// The VAL argument is saved to a temporary so it can be used
-// as an l-value.
-def bitcast;
-// dup - Take a scalar argument and create a vector by duplicating it into
-// all lanes. The type of the vector is the base type of the intrinsic.
-// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type
-// is uint32x2_t).
-def dup;
-// splat - Take a vector and a lane index, and return a vector of the same type
-// containing repeated instances of the source vector at the lane index.
-// example: (splat $p0, $p1) ->
-// "__builtin_shufflevector(__p0, __p0, __p1, __p1, __p1, __p1)"
-// (assuming __p0 has four elements).
-def splat;
-// save_temp - Create a temporary (local) variable. The variable takes a name
-// based on the zero'th parameter and can be referenced using
-// using that name in subsequent DAGs in the same
-// operation. The scope of a temp is the operation. If a variable
-// with the given name already exists, an error will be given at
-// tblgen time.
-// example: [(save_temp $var, (call "foo", $p0)),
-// (op "+", $var, $p1)] ->
-// "int32x2_t __var = foo(__p0); return __var + __p1;"
-def save_temp;
-// name_replace - Return the name of the current intrinsic with the first
-// argument replaced by the second argument. Raises an error if
-// the first argument does not exist in the intrinsic name.
-// example: (call (name_replace "_high_", "_"), $p0) (to call the non-high
-// version of this intrinsic).
-def name_replace;
-// literal - Create a literal piece of code. The code is treated as a raw
-// string, and must be given a type. The type is a stdint.h or
-// NEON intrinsic type as given to (cast).
-// example: (literal "int32_t", "0")
-def literal;
-// shuffle - Create a vector shuffle. The syntax is (shuffle ARG0, ARG1, MASK).
-// The MASK argument is a set of elements. The elements are generated
-// from the two special defs "mask0" and "mask1". "mask0" expands to
-// the lane indices in sequence for ARG0, and "mask1" expands to
-// the lane indices in sequence for ARG1. They can be used as-is, e.g.
-//
-// (shuffle $p0, $p1, mask0) -> $p0
-// (shuffle $p0, $p1, mask1) -> $p1
-//
-// or, more usefully, they can be manipulated using the SetTheory
-// operators plus some extra operators defined in the NEON emitter.
-// The operators are described below.
-// example: (shuffle $p0, $p1, (add (highhalf mask0), (highhalf mask1))) ->
-// A concatenation of the high halves of the input vectors.
-def shuffle;
-
-// add, interleave, decimate: These set operators are vanilla SetTheory
-// operators and take their normal definition.
-def add;
-def interleave;
-def decimate;
-// rotl - Rotate set left by a number of elements.
-// example: (rotl mask0, 3) -> [3, 4, 5, 6, 0, 1, 2]
-def rotl;
-// rotl - Rotate set right by a number of elements.
-// example: (rotr mask0, 3) -> [4, 5, 6, 0, 1, 2, 3]
-def rotr;
-// highhalf - Take only the high half of the input.
-// example: (highhalf mask0) -> [4, 5, 6, 7] (assuming mask0 had 8 elements)
-def highhalf;
-// highhalf - Take only the low half of the input.
-// example: (lowhalf mask0) -> [0, 1, 2, 3] (assuming mask0 had 8 elements)
-def lowhalf;
-// rev - Perform a variable-width reversal of the elements. The zero'th argument
-// is a width in bits to reverse. The lanes this maps to is determined
-// based on the element width of the underlying type.
-// example: (rev 32, mask0) -> [3, 2, 1, 0, 7, 6, 5, 4] (if 8-bit elements)
-// example: (rev 32, mask0) -> [1, 0, 3, 2] (if 16-bit elements)
-def rev;
-// mask0 - The initial sequence of lanes for shuffle ARG0
-def mask0 : MaskExpand;
-// mask0 - The initial sequence of lanes for shuffle ARG1
-def mask1 : MaskExpand;
-
-def OP_NONE : Operation;
-def OP_UNAVAILABLE : Operation {
- let Unavailable = 1;
-}
-//===----------------------------------------------------------------------===//
-// Instruction definitions
-//===----------------------------------------------------------------------===//
-
-// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and
-// a sequence of typespecs.
-//
-// The name is the base name of the intrinsic, for example "vget_lane". This is
-// then mangled by the tblgen backend to add type information ("vget_lane_s16").
-//
-// A typespec is a sequence of uppercase characters (modifiers) followed by one
-// lowercase character. A typespec encodes a particular "base type" of the
-// intrinsic.
-//
-// An example typespec is "Qs" - quad-size short - uint16x8_t. The available
-// typespec codes are given below.
-//
-// The string given to an Inst class is a sequence of typespecs. The intrinsic
-// is instantiated for every typespec in the sequence. For example "sdQsQd".
-//
-// The prototype is a string that defines the return type of the intrinsic
-// and the type of each argument. The return type and every argument gets a
-// "modifier" that can change in some way the "base type" of the intrinsic.
-//
-// The modifier 'd' means "default" and does not modify the base type in any
-// way. The available modifiers are given below.
-//
-// Typespecs
-// ---------
-// c: char
-// s: short
-// i: int
-// l: long
-// k: 128-bit long
-// f: float
-// h: half-float
-// d: double
-//
-// Typespec modifiers
-// ------------------
-// S: scalar, only used for function mangling.
-// U: unsigned
-// Q: 128b
-// H: 128b without mangling 'q'
-// P: polynomial
-//
-// Prototype modifiers
-// -------------------
-// prototype: return (arg, arg, ...)
-//
-// v: void
-// t: best-fit integer (int/poly args)
-// x: signed integer (int/float args)
-// u: unsigned integer (int/float args)
-// f: float (int args)
-// F: double (int args)
-// H: half (int args)
-// d: default
-// g: default, ignore 'Q' size modifier.
-// j: default, force 'Q' size modifier.
-// w: double width elements, same num elts
-// n: double width elements, half num elts
-// h: half width elements, double num elts
-// q: half width elements, quad num elts
-// e: half width elements, double num elts, unsigned
-// m: half width elements, same num elts
-// i: constant int
-// l: constant uint64
-// s: scalar of element type
-// z: scalar of half width element type, signed
-// r: scalar of double width element type, signed
-// a: scalar of element type (splat to vector type)
-// b: scalar of unsigned integer/long type (int/float args)
-// $: scalar of signed integer/long type (int/float args)
-// y: scalar of float
-// o: scalar of double
-// k: default elt width, double num elts
-// 2,3,4: array of default vectors
-// B,C,D: array of default elts, force 'Q' size modifier.
-// p: pointer type
-// c: const pointer type
-
-// Every intrinsic subclasses Inst.
-class Inst <string n, string p, string t, Operation o> {
- string Name = n;
- string Prototype = p;
- string Types = t;
- string ArchGuard = "";
-
- Operation Operation = o;
- bit CartesianProductOfTypes = 0;
- bit BigEndianSafe = 0;
- bit isShift = 0;
- bit isScalarShift = 0;
- bit isScalarNarrowShift = 0;
- bit isVCVT_N = 0;
- // For immediate checks: the immediate will be assumed to specify the lane of
- // a Q register. Only used for intrinsics which end up calling polymorphic
- // builtins.
- bit isLaneQ = 0;
-
- // Certain intrinsics have different names than their representative
- // instructions. This field allows us to handle this correctly when we
- // are generating tests.
- string InstName = "";
-
- // Certain intrinsics even though they are not a WOpInst or LOpInst,
- // generate a WOpInst/LOpInst instruction (see below for definition
- // of a WOpInst/LOpInst). For testing purposes we need to know
- // this. Ex: vset_lane which outputs vmov instructions.
- bit isHiddenWInst = 0;
- bit isHiddenLInst = 0;
-}
-
-// The following instruction classes are implemented via builtins.
-// These declarations are used to generate Builtins.def:
-//
-// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8", "p8")
-// IInst: Instruction with generic integer suffix (e.g., "i8")
-// WInst: Instruction with only bit size suffix (e.g., "8")
-class SInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
-class IInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
-class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
-
-// The following instruction classes are implemented via operators
-// instead of builtins. As such these declarations are only used for
-// the purpose of generating tests.
-//
-// SOpInst: Instruction with signed/unsigned suffix (e.g., "s8",
-// "u8", "p8").
-// IOpInst: Instruction with generic integer suffix (e.g., "i8").
-// WOpInst: Instruction with bit size only suffix (e.g., "8").
-// LOpInst: Logical instruction with no bit size suffix.
-// NoTestOpInst: Intrinsic that has no corresponding instruction.
-class SOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
-class IOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
-class WOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
-class LOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
-class NoTestOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
-
-//===----------------------------------------------------------------------===//
-// Operations
-//===----------------------------------------------------------------------===//
+include "arm_neon_incl.td"
def OP_ADD : Op<(op "+", $p0, $p1)>;
def OP_ADDL : Op<(op "+", (call "vmovl", $p0), (call "vmovl", $p1))>;
@@ -500,6 +199,13 @@ def OP_SCALAR_HALF_SET_LNQ : Op<(bitcast "float16x8_t",
(bitcast "int16_t", $p0),
(bitcast "int16x8_t", $p1), $p2))>;
+def OP_DOT_LN
+ : Op<(call "vdot", $p0, $p1,
+ (bitcast $p1, (splat(bitcast "uint32x2_t", $p2), $p3)))>;
+def OP_DOT_LNQ
+ : Op<(call "vdot", $p0, $p1,
+ (bitcast $p1, (splat(bitcast "uint32x4_t", $p2), $p3)))>;
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -632,12 +338,24 @@ def VSLI_N : WInst<"vsli_n", "dddi",
// E.3.14 Loads and stores of a single vector
def VLD1 : WInst<"vld1", "dc",
"QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD1_X2 : WInst<"vld1_x2", "2c",
+ "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+def VLD1_X3 : WInst<"vld1_x3", "3c",
+ "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+def VLD1_X4 : WInst<"vld1_x4", "4c",
+ "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VLD1_LANE : WInst<"vld1_lane", "dcdi",
"QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
def VLD1_DUP : WInst<"vld1_dup", "dc",
"QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
def VST1 : WInst<"vst1", "vpd",
"QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST1_X2 : WInst<"vst1_x2", "vp2",
+ "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+def VST1_X3 : WInst<"vst1_x3", "vp3",
+ "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+def VST1_X4 : WInst<"vst1_x4", "vp4",
+ "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VST1_LANE : WInst<"vst1_lane", "vpdi",
"QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
@@ -646,9 +364,12 @@ def VST1_LANE : WInst<"vst1_lane", "vpdi",
def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD2_DUP : WInst<"vld2_dup", "2c", "UcUsUiUlcsilhfPcPs">;
-def VLD3_DUP : WInst<"vld3_dup", "3c", "UcUsUiUlcsilhfPcPs">;
-def VLD4_DUP : WInst<"vld4_dup", "4c", "UcUsUiUlcsilhfPcPs">;
+def VLD2_DUP : WInst<"vld2_dup", "2c",
+ "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">;
+def VLD3_DUP : WInst<"vld3_dup", "3c",
+ "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">;
+def VLD4_DUP : WInst<"vld4_dup", "4c",
+ "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">;
def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
@@ -698,6 +419,10 @@ def VCOMBINE : NoTestOpInst<"vcombine", "kdd", "csilhfUcUsUiUlPcPs", OP_CONC>;
////////////////////////////////////////////////////////////////////////////////
// E.3.21 Splitting vectors
+// Note that the ARM NEON Reference 2.0 mistakenly document the vget_high_f16()
+// and vget_low_f16() intrinsics as AArch64-only. We (and GCC) support all
+// versions of these intrinsics in both AArch32 and AArch64 architectures. See
+// D45668 for more details.
let InstName = "vmov" in {
def VGET_HIGH : NoTestOpInst<"vget_high", "dk", "csilhfUcUsUiUlPcPs", OP_HI>;
def VGET_LOW : NoTestOpInst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
@@ -832,6 +557,7 @@ def VREINTERPRET
let ArchGuard = "defined(__ARM_FEATURE_FMA)" in {
def VFMA : SInst<"vfma", "dddd", "fQf">;
def VFMS : SOpInst<"vfms", "dddd", "fQf", OP_FMLS>;
+ def FMLA_N_F32 : SOpInst<"vfma_n", "ddds", "fQf", OP_FMLA_N>;
}
////////////////////////////////////////////////////////////////////////////////
@@ -858,18 +584,15 @@ def ST3 : WInst<"vst3", "vp3", "QUlQldQdPlQPl">;
def ST4 : WInst<"vst4", "vp4", "QUlQldQdPlQPl">;
def LD1_X2 : WInst<"vld1_x2", "2c",
- "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
-def LD3_x3 : WInst<"vld1_x3", "3c",
- "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
-def LD4_x4 : WInst<"vld1_x4", "4c",
- "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
-
-def ST1_X2 : WInst<"vst1_x2", "vp2",
- "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
-def ST1_X3 : WInst<"vst1_x3", "vp3",
- "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
-def ST1_X4 : WInst<"vst1_x4", "vp4",
- "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+ "dQdPlQPl">;
+def LD1_X3 : WInst<"vld1_x3", "3c",
+ "dQdPlQPl">;
+def LD1_X4 : WInst<"vld1_x4", "4c",
+ "dQdPlQPl">;
+
+def ST1_X2 : WInst<"vst1_x2", "vp2", "dQdPlQPl">;
+def ST1_X3 : WInst<"vst1_x3", "vp3", "dQdPlQPl">;
+def ST1_X4 : WInst<"vst1_x4", "vp4", "dQdPlQPl">;
def LD1_LANE : WInst<"vld1_lane", "dcdi", "dQdPlQPl">;
def LD2_LANE : WInst<"vld2_lane", "2c2i", "lUlQcQUcQPcQlQUldQdPlQPl">;
@@ -881,12 +604,9 @@ def ST3_LANE : WInst<"vst3_lane", "vp3i", "lUlQcQUcQPcQlQUldQdPlQPl">;
def ST4_LANE : WInst<"vst4_lane", "vp4i", "lUlQcQUcQPcQlQUldQdPlQPl">;
def LD1_DUP : WInst<"vld1_dup", "dc", "dQdPlQPl">;
-def LD2_DUP : WInst<"vld2_dup", "2c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
-def LD3_DUP : WInst<"vld3_dup", "3c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
-def LD4_DUP : WInst<"vld4_dup", "4c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
+def LD2_DUP : WInst<"vld2_dup", "2c", "dQdPlQPl">;
+def LD3_DUP : WInst<"vld3_dup", "3c", "dQdPlQPl">;
+def LD4_DUP : WInst<"vld4_dup", "4c", "dQdPlQPl">;
def VLDRQ : WInst<"vldrq", "sc", "Pk">;
def VSTRQ : WInst<"vstrq", "vps", "Pk">;
@@ -922,8 +642,8 @@ def FMLS : SOpInst<"vfms", "dddd", "dQd", OP_FMLS>;
// MUL, MLA, MLS, FMA, FMS definitions with scalar argument
def VMUL_N_A64 : IOpInst<"vmul_n", "dds", "Qd", OP_MUL_N>;
-def FMLA_N : SOpInst<"vfma_n", "ddds", "fQfQd", OP_FMLA_N>;
-def FMLS_N : SOpInst<"vfms_n", "ddds", "fQfQd", OP_FMLS_N>;
+def FMLA_N : SOpInst<"vfma_n", "ddds", "dQd", OP_FMLA_N>;
+def FMLS_N : SOpInst<"vfms_n", "ddds", "fdQfQd", OP_FMLS_N>;
def MLA_N : SOpInst<"vmla_n", "ddds", "Qd", OP_MLA_N>;
def MLS_N : SOpInst<"vmls_n", "ddds", "Qd", OP_MLS_N>;
@@ -1052,9 +772,9 @@ def RSHRN_HIGH_N : IOpInst<"vrshrn_high_n", "hmdi",
"HsHiHlHUsHUiHUl", OP_NARROW_HI>;
def QRSHRUN_HIGH_N : SOpInst<"vqrshrun_high_n", "hmdi",
"HsHiHl", OP_NARROW_HI>;
-def QSHRN_HIGH_N : SOpInst<"vqshrn_high_n", "hmdi",
+def QSHRN_HIGH_N : SOpInst<"vqshrn_high_n", "hmdi",
"HsHiHlHUsHUiHUl", OP_NARROW_HI>;
-def QRSHRN_HIGH_N : SOpInst<"vqrshrn_high_n", "hmdi",
+def QRSHRN_HIGH_N : SOpInst<"vqrshrn_high_n", "hmdi",
"HsHiHlHUsHUiHUl", OP_NARROW_HI>;
}
@@ -1207,14 +927,14 @@ def VMINV : SInst<"vminv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQd">;
def VADDV : SInst<"vaddv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQdQlQUl">;
def FMAXNMV : SInst<"vmaxnmv", "sd", "fQfQd">;
def FMINNMV : SInst<"vminnmv", "sd", "fQfQd">;
-
+
////////////////////////////////////////////////////////////////////////////////
// Newly added Vector Extract for f64
def VEXT_A64 : WInst<"vext", "dddi", "dQdPlQPl">;
////////////////////////////////////////////////////////////////////////////////
// Crypto
-let ArchGuard = "__ARM_FEATURE_CRYPTO" in {
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)" in {
def AESE : SInst<"vaese", "ddd", "QUc">;
def AESD : SInst<"vaesd", "ddd", "QUc">;
def AESMC : SInst<"vaesmc", "dd", "QUc">;
@@ -1268,6 +988,7 @@ def FRINTP_S32 : SInst<"vrndp", "dd", "fQf">;
def FRINTM_S32 : SInst<"vrndm", "dd", "fQf">;
def FRINTX_S32 : SInst<"vrndx", "dd", "fQf">;
def FRINTZ_S32 : SInst<"vrnd", "dd", "fQf">;
+def FRINTI_S32 : SInst<"vrndi", "dd", "fQf">;
}
let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in {
@@ -1277,7 +998,7 @@ def FRINTP_S64 : SInst<"vrndp", "dd", "dQd">;
def FRINTM_S64 : SInst<"vrndm", "dd", "dQd">;
def FRINTX_S64 : SInst<"vrndx", "dd", "dQd">;
def FRINTZ_S64 : SInst<"vrnd", "dd", "dQd">;
-def FRINTI_S64 : SInst<"vrndi", "dd", "fdQfQd">;
+def FRINTI_S64 : SInst<"vrndi", "dd", "dQd">;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1417,6 +1138,12 @@ def SCALAR_FCVTZU_N_U64 : SInst<"vcvt_n_u64", "bsi", "Sd">;
}
////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Round to Integral
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in {
+def SCALAR_FRINTN_S32 : SInst<"vrndn", "ss", "Sf">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Scalar Reduce Pairwise Addition (Scalar and Floating Point)
def SCALAR_ADDP : SInst<"vpadd", "sd", "SfSHlSHdSHUl">;
@@ -1664,8 +1391,8 @@ def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
}
-// ARMv8.2-A FP16 intrinsics.
-let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in {
+// ARMv8.2-A FP16 vector intrinsics for A32/A64.
+let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in {
// ARMv8.2-A FP16 one-operand vector intrinsics.
@@ -1690,20 +1417,20 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
def VCVTP_U16 : SInst<"vcvtp_u16", "ud", "hQh">;
// Vector rounding
- def FRINTZH : SInst<"vrnd", "dd", "hQh">;
- def FRINTNH : SInst<"vrndn", "dd", "hQh">;
- def FRINTAH : SInst<"vrnda", "dd", "hQh">;
- def FRINTPH : SInst<"vrndp", "dd", "hQh">;
- def FRINTMH : SInst<"vrndm", "dd", "hQh">;
- def FRINTXH : SInst<"vrndx", "dd", "hQh">;
- def FRINTIH : SInst<"vrndi", "dd", "hQh">;
+ let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in {
+ def FRINTZH : SInst<"vrnd", "dd", "hQh">;
+ def FRINTNH : SInst<"vrndn", "dd", "hQh">;
+ def FRINTAH : SInst<"vrnda", "dd", "hQh">;
+ def FRINTPH : SInst<"vrndp", "dd", "hQh">;
+ def FRINTMH : SInst<"vrndm", "dd", "hQh">;
+ def FRINTXH : SInst<"vrndx", "dd", "hQh">;
+ }
// Misc.
def VABSH : SInst<"vabs", "dd", "hQh">;
def VNEGH : SOpInst<"vneg", "dd", "hQh", OP_NEG>;
def VRECPEH : SInst<"vrecpe", "dd", "hQh">;
def FRSQRTEH : SInst<"vrsqrte", "dd", "hQh">;
- def FSQRTH : SInst<"vsqrt", "dd", "hQh">;
// ARMv8.2-A FP16 two-operands vector intrinsics.
@@ -1714,12 +1441,12 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
// Comparison
let InstName = "vacge" in {
- def VCAGEH : SInst<"vcage", "udd", "hQh">;
- def VCALEH : SInst<"vcale", "udd", "hQh">;
+ def VCAGEH : SInst<"vcage", "udd", "hQh">;
+ def VCALEH : SInst<"vcale", "udd", "hQh">;
}
let InstName = "vacgt" in {
def VCAGTH : SInst<"vcagt", "udd", "hQh">;
- def VCALTH : SInst<"vcalt", "udd", "hQh">;
+ def VCALTH : SInst<"vcalt", "udd", "hQh">;
}
def VCEQH : SOpInst<"vceq", "udd", "hQh", OP_EQ>;
def VCGEH : SOpInst<"vcge", "udd", "hQh", OP_GE>;
@@ -1739,23 +1466,20 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
// Max/Min
def VMAXH : SInst<"vmax", "ddd", "hQh">;
def VMINH : SInst<"vmin", "ddd", "hQh">;
- def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">;
- def FMINNMH : SInst<"vminnm", "ddd", "hQh">;
+ let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in {
+ def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">;
+ def FMINNMH : SInst<"vminnm", "ddd", "hQh">;
+ }
// Multiplication/Division
def VMULH : SOpInst<"vmul", "ddd", "hQh", OP_MUL>;
- def MULXH : SInst<"vmulx", "ddd", "hQh">;
- def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>;
// Pairwise addition
- def VPADDH : SInst<"vpadd", "ddd", "hQh">;
+ def VPADDH : SInst<"vpadd", "ddd", "h">;
// Pairwise Max/Min
- def VPMAXH : SInst<"vpmax", "ddd", "hQh">;
- def VPMINH : SInst<"vpmin", "ddd", "hQh">;
- // Pairwise MaxNum/MinNum
- def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">;
- def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">;
+ def VPMAXH : SInst<"vpmax", "ddd", "h">;
+ def VPMINH : SInst<"vpmin", "ddd", "h">;
// Reciprocal/Sqrt
def VRECPSH : SInst<"vrecps", "ddd", "hQh">;
@@ -1769,6 +1493,63 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
// ARMv8.2-A FP16 lane vector intrinsics.
+ // Mul lane
+ def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>;
+ def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>;
+
+ // Data processing intrinsics - section 5
+
+ // Logical operations
+ let isHiddenLInst = 1 in
+ def VBSLH : SInst<"vbsl", "dudd", "hQh">;
+
+ // Transposition operations
+ def VZIPH : WInst<"vzip", "2dd", "hQh">;
+ def VUZPH : WInst<"vuzp", "2dd", "hQh">;
+ def VTRNH : WInst<"vtrn", "2dd", "hQh">;
+
+
+ let ArchGuard = "!defined(__aarch64__)" in {
+ // Set all lanes to same value.
+ // Already implemented prior to ARMv8.2-A.
+ def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>;
+ def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>;
+ def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>;
+ }
+
+ // Vector Extract
+ def VEXTH : WInst<"vext", "dddi", "hQh">;
+
+ // Reverse vector elements
+ def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>;
+}
+
+// ARMv8.2-A FP16 vector intrinsics for A64 only.
+let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in {
+
+ // Vector rounding
+ def FRINTIH : SInst<"vrndi", "dd", "hQh">;
+
+ // Misc.
+ def FSQRTH : SInst<"vsqrt", "dd", "hQh">;
+
+ // Multiplication/Division
+ def MULXH : SInst<"vmulx", "ddd", "hQh">;
+ def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>;
+
+ // Pairwise addition
+ def VPADDH1 : SInst<"vpadd", "ddd", "Qh">;
+
+ // Pairwise Max/Min
+ def VPMAXH1 : SInst<"vpmax", "ddd", "Qh">;
+ def VPMINH1 : SInst<"vpmin", "ddd", "Qh">;
+
+ // Pairwise MaxNum/MinNum
+ def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">;
+ def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">;
+
+ // ARMv8.2-A FP16 lane vector intrinsics.
+
// FMA lane
def VFMA_LANEH : IInst<"vfma_lane", "dddgi", "hQh">;
def VFMA_LANEQH : IInst<"vfma_laneq", "dddji", "hQh">;
@@ -1789,9 +1570,7 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
def SCALAR_FMLS_LANEQH : IOpInst<"vfms_laneq", "sssji", "Sh", OP_FMS_LNQ>;
// Mul lane
- def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>;
def VMUL_LANEQH : IOpInst<"vmul_laneq", "ddji", "hQh", OP_MUL_LN>;
- def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>;
// Scalar floating point multiply (scalar, by element)
def SCALAR_FMUL_LANEH : IOpInst<"vmul_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>;
def SCALAR_FMUL_LANEQH : IOpInst<"vmul_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>;
@@ -1800,11 +1579,9 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
def VMULX_LANEH : IOpInst<"vmulx_lane", "ddgi", "hQh", OP_MULX_LN>;
def VMULX_LANEQH : IOpInst<"vmulx_laneq", "ddji", "hQh", OP_MULX_LN>;
def VMULX_NH : IOpInst<"vmulx_n", "dds", "hQh", OP_MULX_N>;
- // TODO: Scalar floating point multiply extended (scalar, by element)
- // Below ones are commented out because they need vmulx_f16(float16_t, float16_t)
- // which will be implemented later with fp16 scalar intrinsic (arm_fp16.h)
- //def SCALAR_FMULX_LANEH : IOpInst<"vmulx_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>;
- //def SCALAR_FMULX_LANEQH : IOpInst<"vmulx_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>;
+ // Scalar floating point mulx (scalar, by element)
+ def SCALAR_FMULX_LANEH : IInst<"vmulx_lane", "ssdi", "Sh">;
+ def SCALAR_FMULX_LANEQH : IInst<"vmulx_laneq", "ssji", "Sh">;
// ARMv8.2-A FP16 reduction vector intrinsics.
def VMAXVH : SInst<"vmaxv", "sd", "hQh">;
@@ -1812,29 +1589,6 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
def FMAXNMVH : SInst<"vmaxnmv", "sd", "hQh">;
def FMINNMVH : SInst<"vminnmv", "sd", "hQh">;
- // Data processing intrinsics - section 5
-
- // Logical operations
- let isHiddenLInst = 1 in
- def VBSLH : SInst<"vbsl", "dudd", "hQh">;
-
- // Transposition operations
- def VZIPH : WInst<"vzip", "2dd", "hQh">;
- def VUZPH : WInst<"vuzp", "2dd", "hQh">;
- def VTRNH : WInst<"vtrn", "2dd", "hQh">;
-
- // Set all lanes to same value.
- /* Already implemented prior to ARMv8.2-A.
- def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>;
- def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>;
- def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>;*/
-
- // Vector Extract
- def VEXTH : WInst<"vext", "dddi", "hQh">;
-
- // Reverse vector elements
- def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>;
-
// Permutation
def VTRN1H : SOpInst<"vtrn1", "ddd", "hQh", OP_TRN1>;
def VZIP1H : SOpInst<"vzip1", "ddd", "hQh", OP_ZIP1>;
@@ -1846,3 +1600,13 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc
def SCALAR_VDUP_LANEH : IInst<"vdup_lane", "sdi", "Sh">;
def SCALAR_VDUP_LANEQH : IInst<"vdup_laneq", "sji", "Sh">;
}
+
+// v8.2-A dot product instructions.
+let ArchGuard = "defined(__ARM_FEATURE_DOTPROD)" in {
+ def DOT : SInst<"vdot", "dd88", "iQiUiQUi">;
+ def DOT_LANE : SOpInst<"vdot_lane", "dd87i", "iUiQiQUi", OP_DOT_LN>;
+}
+let ArchGuard = "defined(__ARM_FEATURE_DOTPROD) && defined(__aarch64__)" in {
+ // Variants indexing into a 128-bit vector are A64 only.
+ def UDOT_LANEQ : SOpInst<"vdot_laneq", "dd89i", "iUiQiQUi", OP_DOT_LNQ>;
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon_incl.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon_incl.td
new file mode 100644
index 000000000000..5f3aa6fc0221
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon_incl.td
@@ -0,0 +1,316 @@
+//===--- arm_neon_incl.td - ARM NEON compiler interface ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines data structures shared by arm_neon.td and arm_fp16.td.
+// It constains base operation classes, operations, instructions, instruction
+// modifiers, etc.
+//
+//===----------------------------------------------------------------------===//
+//
+// Each intrinsic is a subclass of the Inst class. An intrinsic can either
+// generate a __builtin_* call or it can expand to a set of generic operations.
+//
+// The operations are subclasses of Operation providing a list of DAGs, the
+// last of which is the return value. The available DAG nodes are documented
+// below.
+//
+//===----------------------------------------------------------------------===//
+
+// The base Operation class. All operations must subclass this.
+class Operation<list<dag> ops=[]> {
+ list<dag> Ops = ops;
+ bit Unavailable = 0;
+}
+// An operation that only contains a single DAG.
+class Op<dag op> : Operation<[op]>;
+// A shorter version of Operation - takes a list of DAGs. The last of these will
+// be the return value.
+class LOp<list<dag> ops> : Operation<ops>;
+
+// These defs and classes are used internally to implement the SetTheory
+// expansion and should be ignored.
+foreach Index = 0-63 in
+ def sv##Index;
+class MaskExpand;
+
+//===----------------------------------------------------------------------===//
+// Available operations
+//===----------------------------------------------------------------------===//
+
+// DAG arguments can either be operations (documented below) or variables.
+// Variables are prefixed with '$'. There are variables for each input argument,
+// with the name $pN, where N starts at zero. So the zero'th argument will be
+// $p0, the first $p1 etc.
+
+// op - Binary or unary operator, depending on the number of arguments. The
+// operator itself is just treated as a raw string and is not checked.
+// example: (op "+", $p0, $p1) -> "__p0 + __p1".
+// (op "-", $p0) -> "-__p0"
+def op;
+// call - Invoke another intrinsic. The input types are type checked and
+// disambiguated. If there is no intrinsic defined that takes
+// the given types (or if there is a type ambiguity) an error is
+// generated at tblgen time. The name of the intrinsic is the raw
+// name as given to the Inst class (not mangled).
+// example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)"
+// (assuming $p0 has type int16x8_t).
+def call;
+// cast - Perform a cast to a different type. This gets emitted as a static
+// C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use
+// "bitcast".
+//
+// The syntax is (cast MOD* VAL). The last argument is the value to
+// cast, preceded by a sequence of type modifiers. The target type
+// starts off as the type of VAL, and is modified by MOD in sequence.
+// The available modifiers are:
+// - $X - Take the type of parameter/variable X. For example:
+// (cast $p0, $p1) would cast $p1 to the type of $p0.
+// - "R" - The type of the return type.
+// - A typedef string - A NEON or stdint.h type that is then parsed.
+// for example: (cast "uint32x4_t", $p0).
+// - "U" - Make the type unsigned.
+// - "S" - Make the type signed.
+// - "H" - Halve the number of lanes in the type.
+// - "D" - Double the number of lanes in the type.
+// - "8" - Convert type to an equivalent vector of 8-bit signed
+// integers.
+// example: (cast "R", "U", $p0) -> "(uint32x4_t)__p0" (assuming the return
+// value is of type "int32x4_t".
+// (cast $p0, "D", "8", $p1) -> "(int8x16_t)__p1" (assuming __p0
+// has type float64x1_t or any other vector type of 64 bits).
+// (cast "int32_t", $p2) -> "(int32_t)__p2"
+def cast;
+// bitcast - Same as "cast", except a reinterpret-cast is produced:
+// (bitcast "T", $p0) -> "*(T*)&__p0".
+// The VAL argument is saved to a temporary so it can be used
+// as an l-value.
+def bitcast;
+// dup - Take a scalar argument and create a vector by duplicating it into
+// all lanes. The type of the vector is the base type of the intrinsic.
+// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type
+// is uint32x2_t).
+def dup;
+// splat - Take a vector and a lane index, and return a vector of the same type
+// containing repeated instances of the source vector at the lane index.
+// example: (splat $p0, $p1) ->
+// "__builtin_shufflevector(__p0, __p0, __p1, __p1, __p1, __p1)"
+// (assuming __p0 has four elements).
+def splat;
+// save_temp - Create a temporary (local) variable. The variable takes a name
+// based on the zero'th parameter and can be referenced using
+// using that name in subsequent DAGs in the same
+// operation. The scope of a temp is the operation. If a variable
+// with the given name already exists, an error will be given at
+// tblgen time.
+// example: [(save_temp $var, (call "foo", $p0)),
+// (op "+", $var, $p1)] ->
+// "int32x2_t __var = foo(__p0); return __var + __p1;"
+def save_temp;
+// name_replace - Return the name of the current intrinsic with the first
+// argument replaced by the second argument. Raises an error if
+// the first argument does not exist in the intrinsic name.
+// example: (call (name_replace "_high_", "_"), $p0) (to call the non-high
+// version of this intrinsic).
+def name_replace;
+// literal - Create a literal piece of code. The code is treated as a raw
+// string, and must be given a type. The type is a stdint.h or
+// NEON intrinsic type as given to (cast).
+// example: (literal "int32_t", "0")
+def literal;
+// shuffle - Create a vector shuffle. The syntax is (shuffle ARG0, ARG1, MASK).
+// The MASK argument is a set of elements. The elements are generated
+// from the two special defs "mask0" and "mask1". "mask0" expands to
+// the lane indices in sequence for ARG0, and "mask1" expands to
+// the lane indices in sequence for ARG1. They can be used as-is, e.g.
+//
+// (shuffle $p0, $p1, mask0) -> $p0
+// (shuffle $p0, $p1, mask1) -> $p1
+//
+// or, more usefully, they can be manipulated using the SetTheory
+// operators plus some extra operators defined in the NEON emitter.
+// The operators are described below.
+// example: (shuffle $p0, $p1, (add (highhalf mask0), (highhalf mask1))) ->
+// A concatenation of the high halves of the input vectors.
+def shuffle;
+
+// add, interleave, decimate: These set operators are vanilla SetTheory
+// operators and take their normal definition.
+def add;
+def interleave;
+def decimate;
+// rotl - Rotate set left by a number of elements.
+// example: (rotl mask0, 3) -> [3, 4, 5, 6, 0, 1, 2]
+def rotl;
+// rotl - Rotate set right by a number of elements.
+// example: (rotr mask0, 3) -> [4, 5, 6, 0, 1, 2, 3]
+def rotr;
+// highhalf - Take only the high half of the input.
+// example: (highhalf mask0) -> [4, 5, 6, 7] (assuming mask0 had 8 elements)
+def highhalf;
+// highhalf - Take only the low half of the input.
+// example: (lowhalf mask0) -> [0, 1, 2, 3] (assuming mask0 had 8 elements)
+def lowhalf;
+// rev - Perform a variable-width reversal of the elements. The zero'th argument
+// is a width in bits to reverse. The lanes this maps to is determined
+// based on the element width of the underlying type.
+// example: (rev 32, mask0) -> [3, 2, 1, 0, 7, 6, 5, 4] (if 8-bit elements)
+// example: (rev 32, mask0) -> [1, 0, 3, 2] (if 16-bit elements)
+def rev;
+// mask0 - The initial sequence of lanes for shuffle ARG0
+def mask0 : MaskExpand;
+// mask0 - The initial sequence of lanes for shuffle ARG1
+def mask1 : MaskExpand;
+
+def OP_NONE : Operation;
+def OP_UNAVAILABLE : Operation {
+ let Unavailable = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction definitions
+//===----------------------------------------------------------------------===//
+
+// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and
+// a sequence of typespecs.
+//
+// The name is the base name of the intrinsic, for example "vget_lane". This is
+// then mangled by the tblgen backend to add type information ("vget_lane_s16").
+//
+// A typespec is a sequence of uppercase characters (modifiers) followed by one
+// lowercase character. A typespec encodes a particular "base type" of the
+// intrinsic.
+//
+// An example typespec is "Qs" - quad-size short - uint16x8_t. The available
+// typespec codes are given below.
+//
+// The string given to an Inst class is a sequence of typespecs. The intrinsic
+// is instantiated for every typespec in the sequence. For example "sdQsQd".
+//
+// The prototype is a string that defines the return type of the intrinsic
+// and the type of each argument. The return type and every argument gets a
+// "modifier" that can change in some way the "base type" of the intrinsic.
+//
+// The modifier 'd' means "default" and does not modify the base type in any
+// way. The available modifiers are given below.
+//
+// Typespecs
+// ---------
+// c: char
+// s: short
+// i: int
+// l: long
+// k: 128-bit long
+// f: float
+// h: half-float
+// d: double
+//
+// Typespec modifiers
+// ------------------
+// S: scalar, only used for function mangling.
+// U: unsigned
+// Q: 128b
+// H: 128b without mangling 'q'
+// P: polynomial
+//
+// Prototype modifiers
+// -------------------
+// prototype: return (arg, arg, ...)
+//
+// v: void
+// t: best-fit integer (int/poly args)
+// x: signed integer (int/float args)
+// u: unsigned integer (int/float args)
+// f: float (int args)
+// F: double (int args)
+// H: half (int args)
+// d: default
+// g: default, ignore 'Q' size modifier.
+// j: default, force 'Q' size modifier.
+// w: double width elements, same num elts
+// n: double width elements, half num elts
+// h: half width elements, double num elts
+// q: half width elements, quad num elts
+// e: half width elements, double num elts, unsigned
+// m: half width elements, same num elts
+// i: constant int
+// l: constant uint64
+// s: scalar of element type
+// z: scalar of half width element type, signed
+// r: scalar of double width element type, signed
+// a: scalar of element type (splat to vector type)
+// b: scalar of unsigned integer/long type (int/float args)
+// $: scalar of signed integer/long type (int/float args)
+// y: scalar of float
+// o: scalar of double
+// k: default elt width, double num elts
+// 2,3,4: array of default vectors
+// B,C,D: array of default elts, force 'Q' size modifier.
+// p: pointer type
+// c: const pointer type
+// 7: vector of 8-bit elements, ignore 'Q' size modifier
+// 8: vector of 8-bit elements, same width as default type
+// 9: vector of 8-bit elements, force 'Q' size modifier
+
+// Every intrinsic subclasses Inst.
+class Inst <string n, string p, string t, Operation o> {
+ string Name = n;
+ string Prototype = p;
+ string Types = t;
+ string ArchGuard = "";
+
+ Operation Operation = o;
+ bit CartesianProductOfTypes = 0;
+ bit BigEndianSafe = 0;
+ bit isShift = 0;
+ bit isScalarShift = 0;
+ bit isScalarNarrowShift = 0;
+ bit isVCVT_N = 0;
+ // For immediate checks: the immediate will be assumed to specify the lane of
+ // a Q register. Only used for intrinsics which end up calling polymorphic
+ // builtins.
+ bit isLaneQ = 0;
+
+ // Certain intrinsics have different names than their representative
+ // instructions. This field allows us to handle this correctly when we
+ // are generating tests.
+ string InstName = "";
+
+ // Certain intrinsics even though they are not a WOpInst or LOpInst,
+ // generate a WOpInst/LOpInst instruction (see below for definition
+ // of a WOpInst/LOpInst). For testing purposes we need to know
+ // this. Ex: vset_lane which outputs vmov instructions.
+ bit isHiddenWInst = 0;
+ bit isHiddenLInst = 0;
+}
+
+// The following instruction classes are implemented via builtins.
+// These declarations are used to generate Builtins.def:
+//
+// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8", "p8")
+// IInst: Instruction with generic integer suffix (e.g., "i8")
+// WInst: Instruction with only bit size suffix (e.g., "8")
+class SInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+class IInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+
+// The following instruction classes are implemented via operators
+// instead of builtins. As such these declarations are only used for
+// the purpose of generating tests.
+//
+// SOpInst: Instruction with signed/unsigned suffix (e.g., "s8",
+// "u8", "p8").
+// IOpInst: Instruction with generic integer suffix (e.g., "i8").
+// WOpInst: Instruction with bit size only suffix (e.g., "8").
+// LOpInst: Logical instruction with no bit size suffix.
+// NoTestOpInst: Intrinsic that has no corresponding instruction.
+class SOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class IOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class WOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class LOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class NoTestOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
index bb105cb533a4..3d1221a43b14 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
@@ -49,6 +49,8 @@ namespace clang {
llvm::Expected<llvm::BitcodeModule>
FindThinLTOModule(llvm::MemoryBufferRef MBRef);
+ llvm::BitcodeModule *
+ FindThinLTOModule(llvm::MutableArrayRef<llvm::BitcodeModule> BMs);
}
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
index d1f05124d5e5..cf64e9f3eeff 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -95,6 +95,8 @@ private:
bool SRetAfterThis : 1; // isIndirect()
bool InReg : 1; // isDirect() || isExtend() || isIndirect()
bool CanBeFlattened: 1; // isDirect()
+ bool SignExt : 1; // isExtend()
+ bool SuppressSRet : 1; // isIndirect()
bool canHavePaddingType() const {
return isDirect() || isExtend() || isIndirect() || isExpand();
@@ -110,13 +112,14 @@ private:
}
ABIArgInfo(Kind K)
- : TheKind(K), PaddingInReg(false), InReg(false) {
+ : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) {
}
public:
ABIArgInfo()
: TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
- TheKind(Direct), PaddingInReg(false), InReg(false) {}
+ TheKind(Direct), PaddingInReg(false), InReg(false),
+ SuppressSRet(false) {}
static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
llvm::Type *Padding = nullptr,
@@ -133,15 +136,38 @@ public:
AI.setInReg(true);
return AI;
}
- static ABIArgInfo getExtend(llvm::Type *T = nullptr) {
+
+ static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
+ assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
auto AI = ABIArgInfo(Extend);
AI.setCoerceToType(T);
AI.setPaddingType(nullptr);
AI.setDirectOffset(0);
+ AI.setSignExt(true);
return AI;
}
- static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) {
- auto AI = getExtend(T);
+
+ static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
+ assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
+ auto AI = ABIArgInfo(Extend);
+ AI.setCoerceToType(T);
+ AI.setPaddingType(nullptr);
+ AI.setDirectOffset(0);
+ AI.setSignExt(false);
+ return AI;
+ }
+
+ // ABIArgInfo will record the argument as being extended based on the sign
+ // of its type.
+ static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
+ assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
+ if (Ty->hasSignedIntegerRepresentation())
+ return getSignExtend(Ty, T);
+ return getZeroExtend(Ty, T);
+ }
+
+ static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
+ auto AI = getExtend(Ty, T);
AI.setInReg(true);
return AI;
}
@@ -254,6 +280,15 @@ public:
DirectOffset = Offset;
}
+ bool isSignExt() const {
+ assert(isExtend() && "Invalid kind!");
+ return SignExt;
+ }
+ void setSignExt(bool SExt) {
+ assert(isExtend() && "Invalid kind!");
+ SignExt = SExt;
+ }
+
llvm::Type *getPaddingType() const {
return (canHavePaddingType() ? PaddingType : nullptr);
}
@@ -351,7 +386,7 @@ public:
AllocaFieldIndex = FieldIndex;
}
- /// \brief Return true if this field of an inalloca struct should be returned
+ /// Return true if this field of an inalloca struct should be returned
/// to implement a struct return calling convention.
bool getInAllocaSRet() const {
assert(isInAlloca() && "Invalid kind!");
@@ -373,6 +408,16 @@ public:
CanBeFlattened = Flatten;
}
+ bool getSuppressSRet() const {
+ assert(isIndirect() && "Invalid kind!");
+ return SuppressSRet;
+ }
+
+ void setSuppressSRet(bool Suppress) {
+ assert(isIndirect() && "Invalid kind!");
+ SuppressSRet = Suppress;
+ }
+
void dump() const;
};
@@ -461,7 +506,7 @@ class CGFunctionInfo final
unsigned EffectiveCallingConvention : 8;
/// The clang::CallingConv that this was originally created with.
- unsigned ASTCallingConvention : 7;
+ unsigned ASTCallingConvention : 6;
/// Whether this is an instance method.
unsigned InstanceMethod : 1;
@@ -482,6 +527,9 @@ class CGFunctionInfo final
unsigned HasRegParm : 1;
unsigned RegParm : 3;
+ /// Whether this function has nocf_check attribute.
+ unsigned NoCfCheck : 1;
+
RequiredArgs Required;
/// The struct representing all arguments passed in memory. Only used when
@@ -566,6 +614,9 @@ public:
/// Whether this function no longer saves caller registers.
bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
+ /// Whether this function has nocf_check attribute.
+ bool isNoCfCheck() const { return NoCfCheck; }
+
/// getASTCallingConvention() - Return the AST-specified calling
/// convention.
CallingConv getASTCallingConvention() const {
@@ -591,7 +642,7 @@ public:
FunctionType::ExtInfo getExtInfo() const {
return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
getASTCallingConvention(), isReturnsRetained(),
- isNoCallerSavedRegs());
+ isNoCallerSavedRegs(), isNoCfCheck());
}
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -609,10 +660,10 @@ public:
return getExtParameterInfos()[argIndex];
}
- /// \brief Return true if this function uses inalloca arguments.
+ /// Return true if this function uses inalloca arguments.
bool usesInAlloca() const { return ArgStruct; }
- /// \brief Get the struct type used to represent all the arguments in memory.
+ /// Get the struct type used to represent all the arguments in memory.
llvm::StructType *getArgStruct() const { return ArgStruct; }
CharUnits getArgStructAlignment() const {
return CharUnits::fromQuantity(ArgStructAlign);
@@ -631,6 +682,7 @@ public:
ID.AddBoolean(NoCallerSavedRegs);
ID.AddBoolean(HasRegParm);
ID.AddInteger(RegParm);
+ ID.AddBoolean(NoCfCheck);
ID.AddInteger(Required.getOpaqueData());
ID.AddBoolean(HasExtParameterInfos);
if (HasExtParameterInfos) {
@@ -657,6 +709,7 @@ public:
ID.AddBoolean(info.getNoCallerSavedRegs());
ID.AddBoolean(info.getHasRegParm());
ID.AddInteger(info.getRegParm());
+ ID.AddBoolean(info.getNoCfCheck());
ID.AddInteger(required.getOpaqueData());
ID.AddBoolean(!paramInfos.empty());
if (!paramInfos.empty()) {
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitBuilder.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitBuilder.h
index 113d86d82c10..f2e78adb8ceb 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitBuilder.h
@@ -266,7 +266,7 @@ public:
/// (2) finishing the entire builder.
///
/// This is useful for emitting certain kinds of structure which
- /// contain some sort of summary field, generaly a count, before any
+ /// contain some sort of summary field, generally a count, before any
/// of the data. By emitting a placeholder first, the structure can
/// be emitted eagerly.
PlaceholderPosition addPlaceholder() {
@@ -295,7 +295,7 @@ public:
slot = value;
}
- /// Produce an address which will eventually point to the the next
+ /// Produce an address which will eventually point to the next
/// position to be filled. This is computed with an indexed
/// getelementptr rather than by computing offsets.
///
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/SwiftCallingConv.h b/contrib/llvm/tools/clang/include/clang/CodeGen/SwiftCallingConv.h
index 23db43e6739c..45b3145ed9f1 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/SwiftCallingConv.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/SwiftCallingConv.h
@@ -1,4 +1,4 @@
-//==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==//
+//==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -116,6 +116,12 @@ private:
void splitVectorEntry(unsigned index);
};
+/// Should an aggregate which expands to the given type sequence
+/// be passed/returned indirectly under swiftcall?
+bool shouldPassIndirectly(CodeGenModule &CGM,
+ ArrayRef<llvm::Type*> types,
+ bool asReturnValue);
+
/// Return the maximum voluntary integer size for the current target.
CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM);
@@ -146,9 +152,15 @@ void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize,
llvm::VectorType *vectorTy,
llvm::SmallVectorImpl<llvm::Type*> &types);
-/// Should a C++ record type be passed and returned indirectly?
-bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
- const CXXRecordDecl *record);
+/// Is the given record type required to be passed and returned indirectly
+/// because of language restrictions?
+///
+/// This considers *only* mandatory indirectness due to language restrictions,
+/// such as C++'s non-trivially-copyable types and Objective-C's __weak
+/// references. A record for which this returns true may still be passed
+/// indirectly for other reasons, such as being too large to fit in a
+/// reasonable number of registers.
+bool mustPassRecordIndirectly(CodeGenModule &CGM, const RecordDecl *record);
/// Classify the rules for how to return a particular type.
ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type);
@@ -160,7 +172,7 @@ ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type);
/// private interface for Clang.
void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
-/// Is swifterror lowered to a register by the target ABI.
+/// Is swifterror lowered to a register by the target ABI?
bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);
} // end namespace swiftcall
diff --git a/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h b/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h
index f2a169025009..041f1a8eea59 100644
--- a/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h
+++ b/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h
@@ -62,7 +62,7 @@ private:
int LineNo;
};
-/// \brief This function parses an index file that determines which
+/// This function parses an index file that determines which
/// translation unit contains which definition.
///
/// The index file format is the following:
@@ -75,7 +75,7 @@ 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
+/// This class is used for tools that requires cross translation
/// unit capability.
///
/// This class can load function definitions from external AST files.
@@ -90,7 +90,7 @@ public:
CrossTranslationUnitContext(CompilerInstance &CI);
~CrossTranslationUnitContext();
- /// \brief This function loads a function definition from an external AST
+ /// 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
@@ -110,7 +110,7 @@ public:
getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir,
StringRef IndexName);
- /// \brief This function loads a function definition from an external AST
+ /// This function loads a function definition from an external AST
/// file.
///
/// A function definition with the same declaration will be looked up in the
@@ -126,17 +126,17 @@ public:
StringRef CrossTUDir,
StringRef IndexName);
- /// \brief This function merges a definition from a separate AST Unit into
+ /// 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.
+ /// Get a name to identify a function.
static std::string getLookupName(const NamedDecl *ND);
- /// \brief Emit diagnostics for the user for potential configuration errors.
+ /// Emit diagnostics for the user for potential configuration errors.
void emitCrossTUDiagnostics(const IndexError &IE);
private:
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Action.h b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
index 72456d34a0d9..723fbbed3598 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Action.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
@@ -1,4 +1,4 @@
-//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===//
+//===- Action.h - Abstract compilation steps --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,20 +10,23 @@
#ifndef LLVM_CLANG_DRIVER_ACTION_H
#define LLVM_CLANG_DRIVER_ACTION_H
-#include "clang/Basic/Cuda.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include <string>
namespace llvm {
+namespace opt {
-class StringRef;
+class Arg;
-namespace opt {
- class Arg;
-}
-}
+} // namespace opt
+} // namespace llvm
namespace clang {
namespace driver {
@@ -44,11 +47,11 @@ class ToolChain;
/// actions via MakeAction().
class Action {
public:
- typedef ActionList::size_type size_type;
- typedef ActionList::iterator input_iterator;
- typedef ActionList::const_iterator input_const_iterator;
- typedef llvm::iterator_range<input_iterator> input_range;
- typedef llvm::iterator_range<input_const_iterator> input_const_range;
+ using size_type = ActionList::size_type;
+ using input_iterator = ActionList::iterator;
+ using input_const_iterator = ActionList::const_iterator;
+ using input_range = llvm::iterator_range<input_iterator>;
+ using input_const_range = llvm::iterator_range<input_const_iterator>;
enum ActionClass {
InputClass = 0,
@@ -78,11 +81,14 @@ public:
// to designate the host offloading tool chain.
enum OffloadKind {
OFK_None = 0x00,
+
// The host offloading tool chain.
OFK_Host = 0x01,
+
// The device offloading tool chains - one bit for each programming model.
OFK_Cuda = 0x02,
OFK_OpenMP = 0x04,
+ OFK_HIP = 0x08,
};
static const char *getClassName(ActionClass AC);
@@ -110,8 +116,10 @@ protected:
/// Multiple programming models may be supported simultaneously by the same
/// host.
unsigned ActiveOffloadKindMask = 0u;
+
/// Offloading kind of the device.
OffloadKind OffloadingDeviceKind = OFK_None;
+
/// The Offloading architecture associated with this action.
const char *OffloadingArch = nullptr;
@@ -149,6 +157,7 @@ public:
void setCannotBeCollapsedWithNextDependentAction() {
CanBeCollapsedWithNextDependentAction = false;
}
+
/// Return true if this function can be collapsed with others.
bool isCollapsingWithNextDependentActionLegal() const {
return CanBeCollapsedWithNextDependentAction;
@@ -156,22 +165,26 @@ public:
/// Return a string containing the offload kind of the action.
std::string getOffloadingKindPrefix() const;
+
/// Return a string that can be used as prefix in order to generate unique
/// files for each offloading kind. By default, no prefix is used for
/// non-device kinds, except if \a CreatePrefixForHost is set.
static std::string
GetOffloadingFileNamePrefix(OffloadKind Kind,
- llvm::StringRef NormalizedTriple,
+ StringRef NormalizedTriple,
bool CreatePrefixForHost = false);
+
/// Return a string containing a offload kind name.
static StringRef GetOffloadKindName(OffloadKind Kind);
/// Set the device offload info of this action and propagate it to its
/// dependences.
void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch);
+
/// Append the host offload info of this action and propagate it to its
/// dependences.
void propagateHostOffloadInfo(unsigned OKinds, const char *OArch);
+
/// Set the offload info of this action to be the same as the provided action,
/// and propagate it to its dependences.
void propagateOffloadInfo(const Action *A);
@@ -179,6 +192,7 @@ public:
unsigned getOffloadingHostActiveKinds() const {
return ActiveOffloadKindMask;
}
+
OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; }
const char *getOffloadingArch() const { return OffloadingArch; }
@@ -196,9 +210,10 @@ public:
};
class InputAction : public Action {
- virtual void anchor();
const llvm::opt::Arg &Input;
+ virtual void anchor();
+
public:
InputAction(const llvm::opt::Arg &Input, types::ID Type);
@@ -211,6 +226,7 @@ public:
class BindArchAction : public Action {
virtual void anchor();
+
/// The architecture to bind, or 0 if the default architecture
/// should be bound.
StringRef ArchName;
@@ -236,9 +252,9 @@ public:
/// toolchain, and offload kind to each action.
class DeviceDependences final {
public:
- typedef SmallVector<const ToolChain *, 3> ToolChainList;
- typedef SmallVector<const char *, 3> BoundArchList;
- typedef SmallVector<OffloadKind, 3> OffloadKindList;
+ using ToolChainList = SmallVector<const ToolChain *, 3>;
+ using BoundArchList = SmallVector<const char *, 3>;
+ using OffloadKindList = SmallVector<OffloadKind, 3>;
private:
// Lists that keep the information for each dependency. All the lists are
@@ -248,10 +264,13 @@ public:
/// The dependence actions.
ActionList DeviceActions;
+
/// The offloading toolchains that should be used with the action.
ToolChainList DeviceToolChains;
+
/// The architectures that should be used with this action.
BoundArchList DeviceBoundArchs;
+
/// The offload kind of each dependence.
OffloadKindList DeviceOffloadKinds;
@@ -262,12 +281,12 @@ public:
OffloadKind OKind);
/// Get each of the individual arrays.
- const ActionList &getActions() const { return DeviceActions; };
- const ToolChainList &getToolChains() const { return DeviceToolChains; };
- const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; };
+ const ActionList &getActions() const { return DeviceActions; }
+ const ToolChainList &getToolChains() const { return DeviceToolChains; }
+ const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; }
const OffloadKindList &getOffloadKinds() const {
return DeviceOffloadKinds;
- };
+ }
};
/// Type used to communicate host actions. It associates bound architecture,
@@ -275,10 +294,13 @@ public:
class HostDependence final {
/// The dependence action.
Action &HostAction;
+
/// The offloading toolchain that should be used with the action.
const ToolChain &HostToolChain;
+
/// The architectures that should be used with this action.
const char *HostBoundArch = nullptr;
+
/// The offload kind of each dependence.
unsigned HostOffloadKinds = 0u;
@@ -286,19 +308,20 @@ public:
HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
const unsigned OffloadKinds)
: HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch),
- HostOffloadKinds(OffloadKinds){};
+ HostOffloadKinds(OffloadKinds) {}
+
/// Constructor version that obtains the offload kinds from the device
/// dependencies.
HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
const DeviceDependences &DDeps);
- Action *getAction() const { return &HostAction; };
- const ToolChain *getToolChain() const { return &HostToolChain; };
- const char *getBoundArch() const { return HostBoundArch; };
- unsigned getOffloadKinds() const { return HostOffloadKinds; };
+ Action *getAction() const { return &HostAction; }
+ const ToolChain *getToolChain() const { return &HostToolChain; }
+ const char *getBoundArch() const { return HostBoundArch; }
+ unsigned getOffloadKinds() const { return HostOffloadKinds; }
};
- typedef llvm::function_ref<void(Action *, const ToolChain *, const char *)>
- OffloadActionWorkTy;
+ using OffloadActionWorkTy =
+ llvm::function_ref<void(Action *, const ToolChain *, const char *)>;
private:
/// The host offloading toolchain that should be used with the action.
@@ -349,6 +372,7 @@ public:
class JobAction : public Action {
virtual void anchor();
+
protected:
JobAction(ActionClass Kind, Action *Input, types::ID Type);
JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
@@ -362,6 +386,7 @@ public:
class PreprocessJobAction : public JobAction {
void anchor() override;
+
public:
PreprocessJobAction(Action *Input, types::ID OutputType);
@@ -372,6 +397,7 @@ public:
class PrecompileJobAction : public JobAction {
void anchor() override;
+
public:
PrecompileJobAction(Action *Input, types::ID OutputType);
@@ -382,6 +408,7 @@ public:
class AnalyzeJobAction : public JobAction {
void anchor() override;
+
public:
AnalyzeJobAction(Action *Input, types::ID OutputType);
@@ -392,6 +419,7 @@ public:
class MigrateJobAction : public JobAction {
void anchor() override;
+
public:
MigrateJobAction(Action *Input, types::ID OutputType);
@@ -402,6 +430,7 @@ public:
class CompileJobAction : public JobAction {
void anchor() override;
+
public:
CompileJobAction(Action *Input, types::ID OutputType);
@@ -412,6 +441,7 @@ public:
class BackendJobAction : public JobAction {
void anchor() override;
+
public:
BackendJobAction(Action *Input, types::ID OutputType);
@@ -422,6 +452,7 @@ public:
class AssembleJobAction : public JobAction {
void anchor() override;
+
public:
AssembleJobAction(Action *Input, types::ID OutputType);
@@ -432,6 +463,7 @@ public:
class LinkJobAction : public JobAction {
void anchor() override;
+
public:
LinkJobAction(ActionList &Inputs, types::ID Type);
@@ -442,6 +474,7 @@ public:
class LipoJobAction : public JobAction {
void anchor() override;
+
public:
LipoJobAction(ActionList &Inputs, types::ID Type);
@@ -452,6 +485,7 @@ public:
class DsymutilJobAction : public JobAction {
void anchor() override;
+
public:
DsymutilJobAction(ActionList &Inputs, types::ID Type);
@@ -462,8 +496,10 @@ public:
class VerifyJobAction : public JobAction {
void anchor() override;
+
public:
VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
+
static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass ||
A->getKind() == VerifyPCHJobClass;
@@ -472,8 +508,10 @@ public:
class VerifyDebugInfoJobAction : public VerifyJobAction {
void anchor() override;
+
public:
VerifyDebugInfoJobAction(Action *Input, types::ID Type);
+
static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass;
}
@@ -481,8 +519,10 @@ public:
class VerifyPCHJobAction : public VerifyJobAction {
void anchor() override;
+
public:
VerifyPCHJobAction(Action *Input, types::ID Type);
+
static bool classof(const Action *A) {
return A->getKind() == VerifyPCHJobClass;
}
@@ -507,18 +547,21 @@ public:
/// Type that provides information about the actions that depend on this
/// unbundling action.
struct DependentActionInfo final {
- /// \brief The tool chain of the dependent action.
+ /// The tool chain of the dependent action.
const ToolChain *DependentToolChain = nullptr;
- /// \brief The bound architecture of the dependent action.
+
+ /// The bound architecture of the dependent action.
StringRef DependentBoundArch;
- /// \brief The offload kind of the dependent action.
+
+ /// The offload kind of the dependent action.
const OffloadKind DependentOffloadKind = OFK_None;
+
DependentActionInfo(const ToolChain *DependentToolChain,
StringRef DependentBoundArch,
const OffloadKind DependentOffloadKind)
: DependentToolChain(DependentToolChain),
DependentBoundArch(DependentBoundArch),
- DependentOffloadKind(DependentOffloadKind){};
+ DependentOffloadKind(DependentOffloadKind) {}
};
private:
@@ -546,7 +589,7 @@ public:
}
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_ACTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
index 7dea88b62cc1..672231e70fad 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -36,6 +36,10 @@ def triple_EQ : Joined<["-"], "triple=">, Alias<triple>;
def mfpmath : Separate<["-"], "mfpmath">,
HelpText<"Which unit to use for fp math">;
+def fpadding_on_unsigned_fixed_point : Flag<["-"], "fpadding-on-unsigned-fixed-point">,
+ HelpText<"Force each unsigned fixed point type to have an extra bit of padding to align their scales with those of signed fixed point types">;
+def fno_padding_on_unsigned_fixed_point : Flag<["-"], "fno-padding-on-unsigned-fixed-point">;
+
//===----------------------------------------------------------------------===//
// Analyzer Options
//===----------------------------------------------------------------------===//
@@ -83,16 +87,16 @@ def analyzer_viz_egraph_ubigraph : Flag<["-"], "analyzer-viz-egraph-ubigraph">,
def analyzer_inline_max_stack_depth : Separate<["-"], "analyzer-inline-max-stack-depth">,
HelpText<"Bound on stack depth while inlining (4 by default)">;
-def analyzer_inline_max_stack_depth_EQ : Joined<["-"], "analyzer-inline-max-stack-depth=">,
+def analyzer_inline_max_stack_depth_EQ : Joined<["-"], "analyzer-inline-max-stack-depth=">,
Alias<analyzer_inline_max_stack_depth>;
-
+
def analyzer_inlining_mode : Separate<["-"], "analyzer-inlining-mode">,
HelpText<"Specify the function selection heuristic used during inlining">;
def analyzer_inlining_mode_EQ : Joined<["-"], "analyzer-inlining-mode=">, Alias<analyzer_inlining_mode>;
def analyzer_disable_retry_exhausted : Flag<["-"], "analyzer-disable-retry-exhausted">,
HelpText<"Do not re-analyze paths leading to exhausted nodes with a different strategy (may decrease code coverage)">;
-
+
def analyzer_max_loop : Separate<["-"], "analyzer-max-loop">,
HelpText<"The maximum number of times the analyzer will go through a loop">;
def analyzer_stats : Flag<["-"], "analyzer-stats">,
@@ -275,8 +279,6 @@ def split_stacks : Flag<["-"], "split-stacks">,
HelpText<"Try to use a split stack if possible.">;
def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">,
HelpText<"Do not put zero initialized data in the BSS">;
-def backend_option : Separate<["-"], "backend-option">,
- HelpText<"Additional arguments to forward to LLVM backend (during code gen)">;
def mregparm : Separate<["-"], "mregparm">,
HelpText<"Limit the number of registers available for integer arguments">;
def munwind_tables : Flag<["-"], "munwind-tables">,
@@ -447,6 +449,8 @@ def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level
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 code_completion_with_fixits : Flag<["-"], "code-completion-with-fixits">,
+ HelpText<"Include code completion results which require small fix-its.">;
def disable_free : Flag<["-"], "disable-free">,
HelpText<"Disable freeing of memory on exit">;
def discard_value_names : Flag<["-"], "discard-value-names">,
@@ -533,6 +537,8 @@ def ast_dump : Flag<["-"], "ast-dump">,
HelpText<"Build ASTs and then debug dump them">;
def ast_dump_all : Flag<["-"], "ast-dump-all">,
HelpText<"Build ASTs and then debug dump them, forcing deserialization">;
+def templight_dump : Flag<["-"], "templight-dump">,
+ HelpText<"Dump templight information to stdout">;
def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
HelpText<"Build ASTs and then debug dump their name lookup tables">;
def ast_view : Flag<["-"], "ast-view">,
@@ -561,6 +567,8 @@ def rewrite_macros : Flag<["-"], "rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
def migrate : Flag<["-"], "migrate">,
HelpText<"Migrate source code">;
+def compiler_options_dump : Flag<["-"], "compiler-options-dump">,
+ HelpText<"Dump the compiler configuration options">;
}
def emit_llvm_uselists : Flag<["-"], "emit-llvm-uselists">,
@@ -599,13 +607,14 @@ def fixit_to_temp : Flag<["-"], "fixit-to-temporary">,
def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">,
HelpText<"Override record layouts with those in the given file">;
-def find_pch_source_EQ : Joined<["-"], "find-pch-source=">,
- HelpText<"When building a pch, try to find the input file in include "
- "directories, as if it had been included by the argument passed "
- "to this flag.">;
+def pch_through_header_EQ : Joined<["-"], "pch-through-header=">,
+ HelpText<"Stop PCH generation after including this file. When using a PCH, "
+ "skip tokens until after this file is included.">;
def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">,
HelpText<"Disable inclusion of timestamp in precompiled headers">;
-
+def building_pch_with_obj : Flag<["-"], "building-pch-with-obj">,
+ HelpText<"This compilation is part of building a PCH with corresponding object file.">;
+
def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">,
HelpText<"Aligned allocation/deallocation functions are unavailable">;
@@ -619,6 +628,8 @@ def version : Flag<["-"], "version">,
HelpText<"Print the compiler version">;
def main_file_name : Separate<["-"], "main-file-name">,
HelpText<"Main file name to use for debug info">;
+def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
+ HelpText<"File name to use for split dwarf debug info output">;
}
@@ -628,8 +639,6 @@ def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
HelpText<"Assume all functions with C linkage do not unwind">;
def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">,
HelpText<"Use split dwarf/Fission">;
-def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
- HelpText<"File name to use for split dwarf debug info output">;
def fno_wchar : Flag<["-"], "fno-wchar">,
HelpText<"Disable C++ builtin type wchar_t">;
def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
@@ -645,6 +654,8 @@ def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-defau
HelpText<"disable the default synthesis of Objective-C properties">;
def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
HelpText<"enable extended encoding of block type signature">;
+def function_alignment : Separate<["-"], "function-alignment">,
+ HelpText<"default alignment for functions">;
def pic_level : Separate<["-"], "pic-level">,
HelpText<"Value for __PIC__">;
def pic_is_pie : Flag<["-"], "pic-is-pie">,
@@ -705,8 +716,6 @@ def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-r
HelpText<"Allow Objective-C array and dictionary subscripting in legacy runtime">;
def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">,
HelpText<"Control vtordisp placement on win32 targets">;
-def fno_rtti_data : Flag<["-"], "fno-rtti-data">,
- HelpText<"Control emission of RTTI data">;
def fnative_half_type: Flag<["-"], "fnative-half-type">,
HelpText<"Use the native half type for __fp16 instead of promoting to float">;
def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and-returns">,
@@ -806,7 +815,7 @@ def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">,
HelpText<"Generate code only for an OpenMP target device.">;
def fopenmp_host_ir_file_path : Separate<["-"], "fopenmp-host-ir-file-path">,
HelpText<"Path to the IR file produced by the frontend for the host.">;
-
+
} // let Flags = [CC1Option]
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
index e417f6cbbec6..78667851ca19 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
@@ -61,6 +61,8 @@ def _SLASH_Brepro_ : CLFlag<"Brepro-">,
def _SLASH_C : CLFlag<"C">,
HelpText<"Don't discard comments when preprocessing">, Alias<C>;
def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>;
+def _SLASH_d1PP : CLFlag<"d1PP">,
+ HelpText<"Retain macro definitions in /E mode">, Alias<dD>;
def _SLASH_d1reportAllClassLayout : CLFlag<"d1reportAllClassLayout">,
HelpText<"Dump record layout information">, Alias<fdump_record_layouts>;
def _SLASH_diagnostics_caret : CLFlag<"diagnostics:caret">,
@@ -164,6 +166,9 @@ def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>,
AliasArgs<["no-deprecated-declarations"]>;
def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
Alias<vtordisp_mode_EQ>;
+def _SLASH_X : CLFlag<"X">,
+ HelpText<"Don't add %INCLUDE% to the include search path">,
+ Alias<nostdlibinc>;
def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">,
HelpText<"Enable C++14 sized global deallocation functions">,
Alias<fsized_deallocation>;
@@ -235,6 +240,8 @@ def _SLASH_Fi : CLCompileJoined<"Fi">,
def _SLASH_Fo : CLCompileJoined<"Fo">,
HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">,
MetaVarName<"<file or directory>">;
+def _SLASH_Guard : CLJoined<"guard:">,
+ HelpText<"Enable Control Flow Guard with /guard:cf">;
def _SLASH_GX : CLFlag<"GX">,
HelpText<"Enable exception handling">;
def _SLASH_GX_ : CLFlag<"GX-">,
@@ -324,18 +331,20 @@ def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
def _SLASH_nologo : CLIgnoredFlag<"nologo">;
def _SLASH_Og : CLIgnoredFlag<"Og">;
def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
+def _SLASH_permissive_ : CLIgnoredFlag<"permissive-">;
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
def _SLASH_sdl : CLIgnoredFlag<"sdl">;
def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">;
def _SLASH_utf8 : CLIgnoredFlag<"utf-8">,
HelpText<"Set source and runtime encoding to UTF-8 (default)">;
def _SLASH_w : CLIgnoredJoined<"w">;
+def _SLASH_Zc___cplusplus : CLIgnoredFlag<"Zc:__cplusplus">;
def _SLASH_Zc_auto : CLIgnoredFlag<"Zc:auto">;
def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">;
def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">;
def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">;
-def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">;
def _SLASH_Zc_ternary : CLIgnoredFlag<"Zc:ternary">;
+def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">;
def _SLASH_Zm : CLIgnoredJoined<"Zm">;
def _SLASH_Zo : CLIgnoredFlag<"Zo">;
def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;
@@ -344,6 +353,8 @@ def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;
// Unsupported:
def _SLASH_AI : CLJoined<"AI">;
+def _SLASH_Bt : CLFlag<"Bt">;
+def _SLASH_Bt_plus : CLFlag<"Bt+">;
def _SLASH_clr : CLJoined<"clr">;
def _SLASH_doc : CLJoined<"doc">;
def _SLASH_FA_joined : CLJoined<"FA">;
@@ -364,7 +375,6 @@ def _SLASH_GL_ : CLFlag<"GL-">;
def _SLASH_Gm : CLFlag<"Gm">;
def _SLASH_Gm_ : CLFlag<"Gm-">;
def _SLASH_GT : CLFlag<"GT">;
-def _SLASH_Guard : CLJoined<"guard:">;
def _SLASH_GZ : CLFlag<"GZ">;
def _SLASH_H : CLFlag<"H">;
def _SLASH_homeparams : CLFlag<"homeparams">;
@@ -382,7 +392,6 @@ def _SLASH_u : CLFlag<"u">;
def _SLASH_V : CLFlag<"V">;
def _SLASH_WL : CLFlag<"WL">;
def _SLASH_Wp64 : CLFlag<"Wp64">;
-def _SLASH_X : CLFlag<"X">;
def _SLASH_Yd : CLFlag<"Yd">;
def _SLASH_Yl : CLJoined<"Yl">;
def _SLASH_Za : CLFlag<"Za">;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
index 89c0def6c57a..20eb07f6de8b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
@@ -1,4 +1,4 @@
-//===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===//
+//===- Compilation.h - Compilation Task Data Structure ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,24 +10,36 @@
#ifndef LLVM_CLANG_DRIVER_COMPILATION_H
#define LLVM_CLANG_DRIVER_COMPILATION_H
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <cassert>
+#include <iterator>
#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
namespace llvm {
namespace opt {
- class DerivedArgList;
- class InputArgList;
-}
-}
+
+class DerivedArgList;
+class InputArgList;
+
+} // namespace opt
+} // namespace llvm
namespace clang {
namespace driver {
- class Driver;
- class JobList;
- class ToolChain;
+
+class Driver;
+class ToolChain;
/// Compilation - A set of tasks to perform for a single driver
/// invocation.
@@ -40,7 +52,7 @@ class Compilation {
/// A mask of all the programming models the host has to support in the
/// current compilation.
- unsigned ActiveOffloadMask;
+ unsigned ActiveOffloadMask = 0;
/// Array with the toolchains of offloading host and devices in the order they
/// were requested by the user. We are preserving that order in case the code
@@ -73,6 +85,11 @@ class Compilation {
const ToolChain *TC = nullptr;
StringRef BoundArch;
Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
+
+ TCArgsKey(const ToolChain *TC, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind)
+ : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
+
bool operator<(const TCArgsKey &K) const {
if (TC < K.TC)
return true;
@@ -83,9 +100,6 @@ class Compilation {
return true;
return false;
}
- TCArgsKey(const ToolChain *TC, StringRef BoundArch,
- Action::OffloadKind DeviceOffloadKind)
- : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
};
std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs;
@@ -103,11 +117,14 @@ class Compilation {
std::vector<Optional<StringRef>> Redirects;
/// Whether we're compiling for diagnostic purposes.
- bool ForDiagnostics;
+ bool ForDiagnostics = false;
/// Whether an error during the parsing of the input args.
bool ContainsError;
+ /// Whether to keep temporary files regardless of -save-temps.
+ bool ForceKeepTempFiles = false;
+
public:
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
llvm::opt::InputArgList *Args,
@@ -123,12 +140,12 @@ public:
}
/// Iterator that visits device toolchains of a given kind.
- typedef const std::multimap<Action::OffloadKind,
- const ToolChain *>::const_iterator
- const_offload_toolchains_iterator;
- typedef std::pair<const_offload_toolchains_iterator,
- const_offload_toolchains_iterator>
- const_offload_toolchains_range;
+ using const_offload_toolchains_iterator =
+ const std::multimap<Action::OffloadKind,
+ const ToolChain *>::const_iterator;
+ using const_offload_toolchains_range =
+ std::pair<const_offload_toolchains_iterator,
+ const_offload_toolchains_iterator>;
template <Action::OffloadKind Kind>
const_offload_toolchains_range getOffloadToolChains() const {
@@ -289,7 +306,7 @@ public:
void Redirect(ArrayRef<Optional<StringRef>> Redirects);
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_COMPILATION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Distro.h b/contrib/llvm/tools/clang/include/clang/Driver/Distro.h
index 4ab4e2ae9937..7b34a0925603 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Distro.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Distro.h
@@ -61,6 +61,7 @@ public:
UbuntuZesty,
UbuntuArtful,
UbuntuBionic,
+ UbuntuCosmic,
UnknownDistro
};
@@ -114,7 +115,7 @@ public:
}
bool IsUbuntu() const {
- return DistroVal >= UbuntuHardy && DistroVal <= UbuntuBionic;
+ return DistroVal >= UbuntuHardy && DistroVal <= UbuntuCosmic;
}
bool IsAlpineLinux() const {
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
index 07134309835e..b7b802221180 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
@@ -202,8 +202,8 @@ public:
unsigned CCGenDiagnostics : 1;
private:
- /// Default target triple.
- std::string DefaultTargetTriple;
+ /// Raw target triple.
+ std::string TargetTriple;
/// Name to use when invoking gcc/g++.
std::string CCCGenericGCCName;
@@ -243,7 +243,7 @@ private:
std::list<std::string> TempFiles;
std::list<std::string> ResultFiles;
- /// \brief Cache of all the ToolChains in use by the driver.
+ /// Cache of all the ToolChains in use by the driver.
///
/// This maps from the string representation of a triple to a ToolChain
/// created targeting that triple. The driver owns all the ToolChain objects
@@ -256,7 +256,7 @@ private:
llvm::opt::DerivedArgList *
TranslateInputArgs(const llvm::opt::InputArgList &Args) const;
- // getFinalPhase - Determine which compilation mode we are in and record
+ // getFinalPhase - Determine which compilation mode we are in and record
// which option we used to determine the final phase.
phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
llvm::opt::Arg **FinalPhaseArg = nullptr) const;
@@ -267,7 +267,7 @@ private:
void generatePrefixedToolNames(StringRef Tool, const ToolChain &TC,
SmallVectorImpl<std::string> &Names) const;
- /// \brief Find the appropriate .crash diagonostic file for the child crash
+ /// Find the appropriate .crash diagonostic file for the child crash
/// under this driver and copy it out to a temporary destination with the
/// other reproducer related files (.sh, .cache, etc). If not found, suggest a
/// directory for the user to look at.
@@ -282,7 +282,7 @@ private:
SmallString<128> &CrashDiagDir);
public:
- Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
+ Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
@@ -309,12 +309,14 @@ public:
const std::string &getTitle() { return DriverTitle; }
void setTitle(std::string Value) { DriverTitle = std::move(Value); }
- /// \brief Get the path to the main clang executable.
+ std::string getTargetTriple() const { return TargetTriple; }
+
+ /// Get the path to the main clang executable.
const char *getClangProgramPath() const {
return ClangExecutable.c_str();
}
- /// \brief Get the path to where the clang executable was installed.
+ /// Get the path to where the clang executable was installed.
const char *getInstalledDir() const {
if (!InstalledDir.empty())
return InstalledDir.c_str();
@@ -363,12 +365,12 @@ public:
llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
bool &ContainsError);
- /// BuildInputs - Construct the list of inputs and their types from
+ /// BuildInputs - Construct the list of inputs and their types from
/// the given arguments.
///
/// \param TC - The default host tool chain.
/// \param Args - The input arguments.
- /// \param Inputs - The list to store the resulting compilation
+ /// \param Inputs - The list to store the resulting compilation
/// inputs onto.
void BuildInputs(const ToolChain &TC, llvm::opt::DerivedArgList &Args,
InputList &Inputs) const;
@@ -405,11 +407,19 @@ public:
int ExecuteCompilation(Compilation &C,
SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands);
- /// generateCompilationDiagnostics - Generate diagnostics information
+ /// Contains the files in the compilation diagnostic report generated by
+ /// generateCompilationDiagnostics.
+ struct CompilationDiagnosticReport {
+ llvm::SmallVector<std::string, 4> TemporaryFiles;
+ };
+
+ /// generateCompilationDiagnostics - Generate diagnostics information
/// including preprocessed source file(s).
- ///
- void generateCompilationDiagnostics(Compilation &C,
- const Command &FailingCommand);
+ ///
+ void generateCompilationDiagnostics(
+ Compilation &C, const Command &FailingCommand,
+ StringRef AdditionalInformation = "",
+ CompilationDiagnosticReport *GeneratedReport = nullptr);
/// @}
/// @name Helper Methods
@@ -442,9 +452,9 @@ public:
// FIXME: This should be in CompilationInfo.
std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;
- /// handleAutocompletions - Handle --autocomplete by searching and printing
+ /// HandleAutocompletions - Handle --autocomplete by searching and printing
/// possible flags, descriptions, and its arguments.
- void handleAutocompletions(StringRef PassedFlags) const;
+ void HandleAutocompletions(StringRef PassedFlags) const;
/// HandleImmediateArgs - Handle any arguments which should be
/// treated before building actions or binding tools.
@@ -456,8 +466,10 @@ public:
/// ConstructAction - Construct the appropriate action to do for
/// \p Phase on the \p Input, taking in to account arguments
/// like -fsyntax-only or --analyze.
- Action *ConstructPhaseAction(Compilation &C, const llvm::opt::ArgList &Args,
- phases::ID Phase, Action *Input) const;
+ Action *ConstructPhaseAction(
+ Compilation &C, const llvm::opt::ArgList &Args, phases::ID Phase,
+ Action *Input,
+ Action::OffloadKind TargetDeviceOffloadKind = Action::OFK_None) const;
/// BuildJobsForAction - Construct the jobs to perform for the action \p A and
/// return an InputInfo for the result of running \p A. Will only construct
@@ -481,7 +493,7 @@ public:
/// \param JA - The action of interest.
/// \param BaseInput - The original input file that this action was
/// triggered by.
- /// \param BoundArch - The bound architecture.
+ /// \param BoundArch - The bound architecture.
/// \param AtTopLevel - Whether this is a "top-level" action.
/// \param MultipleArchs - Whether multiple -arch options were supplied.
/// \param NormalizedTriple - The normalized triple of the relevant target.
@@ -490,7 +502,7 @@ public:
bool AtTopLevel, bool MultipleArchs,
StringRef NormalizedTriple) const;
- /// GetTemporaryPath - Return the pathname of a temporary file to use
+ /// GetTemporaryPath - Return the pathname of a temporary file to use
/// as part of compilation; the file will have the given prefix and suffix.
///
/// GCC goes to extra lengths here to be a bit more robust.
@@ -530,7 +542,7 @@ private:
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
- /// \brief Retrieves a ToolChain for a particular \p Target triple.
+ /// Retrieves a ToolChain for a particular \p Target triple.
///
/// Will cache ToolChains for the life of the driver object, and create them
/// on-demand.
@@ -539,7 +551,7 @@ private:
/// @}
- /// \brief Get bitmasks for which option flags to include and exclude based on
+ /// Get bitmasks for which option flags to include and exclude based on
/// the driver mode.
std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks() const;
@@ -572,6 +584,8 @@ public:
/// no extra characters remaining at the end.
static bool GetReleaseVersion(StringRef Str,
MutableArrayRef<unsigned> Digits);
+ /// Compute the default -fmodule-cache-path.
+ static void getDefaultModuleCachePath(SmallVectorImpl<char> &Result);
};
/// \return True if the last defined optimization level is -Ofast.
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
index b74b3b4b35e1..47d9e992ba50 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Job.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
@@ -1,4 +1,4 @@
-//===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===//
+//===- Job.h - Commands to Execute ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,21 +12,22 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Option/Option.h"
#include <memory>
-
-namespace llvm {
- class raw_ostream;
-}
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace driver {
+
class Action;
-class Command;
-class Tool;
class InputInfo;
+class Tool;
// Re-export this as clang::driver::ArgStringList.
using llvm::opt::ArgStringList;
@@ -60,7 +61,7 @@ class Command {
/// Response file name, if this command is set to use one, or nullptr
/// otherwise
- const char *ResponseFile;
+ const char *ResponseFile = nullptr;
/// The input file list in case we need to emit a file list instead of a
/// proper response file
@@ -92,7 +93,7 @@ public:
// FIXME: This really shouldn't be copyable, but is currently copied in some
// error handling in Driver::generateCompilationDiagnostics.
Command(const Command &) = default;
- virtual ~Command() {}
+ virtual ~Command() = default;
virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const;
@@ -115,7 +116,7 @@ public:
InputFileList = std::move(List);
}
- /// \brief Sets the environment to be used by the new process.
+ /// Sets the environment to be used by the new process.
/// \param NewEnvironment An array of environment variables.
/// \remark If the environment remains unset, then the environment
/// from the parent process will be used.
@@ -165,10 +166,10 @@ public:
/// JobList - A sequence of jobs to perform.
class JobList {
public:
- typedef SmallVector<std::unique_ptr<Command>, 4> list_type;
- typedef list_type::size_type size_type;
- typedef llvm::pointee_iterator<list_type::iterator> iterator;
- typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator;
+ using list_type = SmallVector<std::unique_ptr<Command>, 4>;
+ using size_type = list_type::size_type;
+ using iterator = llvm::pointee_iterator<list_type::iterator>;
+ using const_iterator = llvm::pointee_iterator<list_type::const_iterator>;
private:
list_type Jobs;
@@ -193,7 +194,7 @@ public:
const_iterator end() const { return Jobs.end(); }
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_JOB_H
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h b/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h
index 36d2493b1afc..132d981854fc 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h
@@ -1,4 +1,4 @@
-//===--- Multilib.h ---------------------------------------------*- C++ -*-===//
+//===- Multilib.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,10 +11,14 @@
#define LLVM_CLANG_DRIVER_MULTILIB_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Option/Option.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
#include <functional>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
@@ -24,7 +28,7 @@ namespace driver {
/// by a command line flag
class Multilib {
public:
- typedef std::vector<std::string> flags_list;
+ using flags_list = std::vector<std::string>;
private:
std::string GCCSuffix;
@@ -33,40 +37,43 @@ private:
flags_list Flags;
public:
- Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "",
- StringRef IncludeSuffix = "");
+ Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
+ StringRef IncludeSuffix = {});
- /// \brief Get the detected GCC installation path suffix for the multi-arch
+ /// Get the detected GCC installation path suffix for the multi-arch
/// target variant. Always starts with a '/', unless empty
const std::string &gccSuffix() const {
assert(GCCSuffix.empty() ||
(StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
return GCCSuffix;
}
+
/// Set the GCC installation path suffix.
Multilib &gccSuffix(StringRef S);
- /// \brief Get the detected os path suffix for the multi-arch
+ /// Get the detected os path suffix for the multi-arch
/// target variant. Always starts with a '/', unless empty
const std::string &osSuffix() const {
assert(OSSuffix.empty() ||
(StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1));
return OSSuffix;
}
+
/// Set the os path suffix.
Multilib &osSuffix(StringRef S);
- /// \brief Get the include directory suffix. Always starts with a '/', unless
+ /// Get the include directory suffix. Always starts with a '/', unless
/// empty
const std::string &includeSuffix() const {
assert(IncludeSuffix.empty() ||
(StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1));
return IncludeSuffix;
}
+
/// Set the include directory suffix
Multilib &includeSuffix(StringRef S);
- /// \brief Get the flags that indicate or contraindicate this multilib's use
+ /// Get the flags that indicate or contraindicate this multilib's use
/// All elements begin with either '+' or '-'
const flags_list &flags() const { return Flags; }
flags_list &flags() { return Flags; }
@@ -85,7 +92,7 @@ public:
}
LLVM_DUMP_METHOD void dump() const;
- /// \brief print summary of the Multilib
+ /// print summary of the Multilib
void print(raw_ostream &OS) const;
/// Check whether any of the 'against' flags contradict the 'for' flags.
@@ -102,14 +109,12 @@ raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
class MultilibSet {
public:
- typedef std::vector<Multilib> multilib_list;
- typedef multilib_list::iterator iterator;
- typedef multilib_list::const_iterator const_iterator;
-
- typedef std::function<std::vector<std::string>(const Multilib &M)>
- IncludeDirsFunc;
-
- typedef llvm::function_ref<bool(const Multilib &)> FilterCallback;
+ using multilib_list = std::vector<Multilib>;
+ using iterator = multilib_list::iterator;
+ using const_iterator = multilib_list::const_iterator;
+ using IncludeDirsFunc =
+ std::function<std::vector<std::string>(const Multilib &M)>;
+ using FilterCallback = llvm::function_ref<bool(const Multilib &)>;
private:
multilib_list Multilibs;
@@ -117,7 +122,7 @@ private:
IncludeDirsFunc FilePathsCallback;
public:
- MultilibSet() {}
+ MultilibSet() = default;
/// Add an optional Multilib segment
MultilibSet &Maybe(const Multilib &M);
@@ -135,6 +140,7 @@ public:
/// Filter out some subset of the Multilibs using a user defined callback
MultilibSet &FilterOut(FilterCallback F);
+
/// Filter out those Multilibs whose gccSuffix matches the given expression
MultilibSet &FilterOut(const char *Regex);
@@ -144,7 +150,7 @@ public:
/// Union this set of multilibs with another
void combineWith(const MultilibSet &MS);
- /// Remove all of thie multilibs from the set
+ /// Remove all of the multilibs from the set
void clear() { Multilibs.clear(); }
iterator begin() { return Multilibs.begin(); }
@@ -165,12 +171,14 @@ public:
IncludeCallback = std::move(F);
return *this;
}
+
const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; }
MultilibSet &setFilePathsCallback(IncludeDirsFunc F) {
FilePathsCallback = std::move(F);
return *this;
}
+
const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; }
private:
@@ -182,8 +190,8 @@ private:
};
raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
-}
-}
-#endif
+} // namespace driver
+} // namespace clang
+#endif // LLVM_CLANG_DRIVER_MULTILIB_H
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
index 7480f5163d3b..7da45d277490 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -143,14 +143,18 @@ def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
// These are explicitly handled.
def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">,
Group<m_Group>, DocName<"Hexagon">;
+def m_mips_Features_Group : OptionGroup<"<mips features group>">,
+ Group<m_Group>, DocName<"MIPS">;
def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
Group<m_Group>, DocName<"PowerPC">;
def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
Group<m_Group>, DocName<"WebAssembly">;
def m_x86_Features_Group : OptionGroup<"<x86 features group>">,
Group<m_Group>, Flags<[CoreOption]>, DocName<"X86">;
+def m_riscv_Features_Group : OptionGroup<"<riscv features group>">,
+ Group<m_Group>, DocName<"RISCV">;
-def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>,
+def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_mips_Features_Group>,
Flags<[HelpHidden]>;
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>,
@@ -396,7 +400,12 @@ def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["2"]>;
def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>;
def P : Flag<["-"], "P">, Flags<[CC1Option]>, Group<Preprocessor_Group>,
HelpText<"Disable linemarker output in -E mode">;
-def Qn : Flag<["-"], "Qn">, IgnoredGCCCompat;
+def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>,
+ HelpText<"Emit metadata containing compiler name and version">;
+def Qn : Flag<["-"], "Qn">, Flags<[CC1Option]>,
+ HelpText<"Do not emit metadata containing compiler name and version">;
+def : Flag<["-"], "fident">, Group<f_Group>, Alias<Qy>, Flags<[CC1Option]>;
+def : Flag<["-"], "fno-ident">, Group<f_Group>, Alias<Qn>, Flags<[CC1Option]>;
def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>,
HelpText<"Don't emit warning for unused driver arguments">;
def Q : Flag<["-"], "Q">, IgnoredGCCCompat;
@@ -418,9 +427,9 @@ def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>,
MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group<T_Group>,
- MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
+ MetaVarName<"<addr>">, HelpText<"Set starting address of DATA to <addr>">;
def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group<T_Group>,
- MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
+ MetaVarName<"<addr>">, HelpText<"Set starting address of TEXT to <addr>">;
def T : JoinedOrSeparate<["-"], "T">, Group<T_Group>,
MetaVarName<"<script>">, HelpText<"Specify <script> as linker script">;
def U : JoinedOrSeparate<["-"], "U">, Group<Preprocessor_Group>,
@@ -466,7 +475,8 @@ def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">,
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>">;
+ HelpText<"Pass <arg> to the target offloading toolchain identified by <triple>.">,
+ MetaVarName<"<triple> <arg>">;
def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">,
Group<Link_Group>;
@@ -492,6 +502,8 @@ def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">;
def b : JoinedOrSeparate<["-"], "b">, Flags<[Unsupported]>;
+def cfguard : Flag<["-"], "cfguard">, Flags<[CC1Option]>,
+ HelpText<"Emit tables required for Windows Control Flow Guard.">;
def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. This option disables all optimizations. By default optimizations are enabled.">;
def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">, Group<opencl_Group>, Flags<[CC1Option]>,
@@ -511,11 +523,13 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, Flags<[CC
def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">;
def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, Flags<[CC1Option]>,
- HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0">;
+ HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,c++">;
def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow denormals to be flushed to zero.">;
def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Specify that single precision floating-point divide and sqrt used in the program source are correctly rounded.">;
+def cl_uniform_work_group_size : Flag<["-"], "cl-uniform-work-group-size">, Group<opencl_Group>, Flags<[CC1Option]>,
+ HelpText<"OpenCL only. Defines that the global work-size be a multiple of the work-group size specified to clEnqueueNDRangeKernel">;
def client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
@@ -541,8 +555,14 @@ def cuda_host_only : Flag<["--"], "cuda-host-only">,
def cuda_compile_host_device : Flag<["--"], "cuda-compile-host-device">,
HelpText<"Compile CUDA code for both host and device (default). Has no "
"effect on non-CUDA compilations.">;
+def cuda_include_ptx_EQ : Joined<["--"], "cuda-include-ptx=">, Flags<[DriverOption]>,
+ HelpText<"Include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">;
+def no_cuda_include_ptx_EQ : Joined<["--"], "no-cuda-include-ptx=">, Flags<[DriverOption]>,
+ HelpText<"Do not include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">;
def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">, Flags<[DriverOption]>,
HelpText<"CUDA GPU architecture (e.g. sm_35). May be specified more than once.">;
+def hip_link : Flag<["--"], "hip-link">,
+ HelpText<"Link clang-offload-bundler bundles for HIP">;
def no_cuda_gpu_arch_EQ : Joined<["--"], "no-cuda-gpu-arch=">, Flags<[DriverOption]>,
HelpText<"Remove GPU architecture (e.g. sm_35) from the list of GPUs to compile for. "
"'all' resets the list to its default value.">;
@@ -554,6 +574,8 @@ def no_cuda_version_check : Flag<["--"], "no-cuda-version-check">,
def no_cuda_noopt_device_debug : Flag<["--"], "no-cuda-noopt-device-debug">;
def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group<i_Group>,
HelpText<"CUDA installation path">;
+def cuda_path_ignore_env : Flag<["--"], "cuda-path-ignore-env">, Group<i_Group>,
+ HelpText<"Ignore environment variables to detect CUDA installation">;
def ptxas_path_EQ : Joined<["--"], "ptxas-path=">, Group<i_Group>,
HelpText<"Path to ptxas (used for compiling CUDA code)">;
def fcuda_flush_denormals_to_zero : Flag<["-"], "fcuda-flush-denormals-to-zero">,
@@ -562,6 +584,18 @@ def fno_cuda_flush_denormals_to_zero : Flag<["-"], "fno-cuda-flush-denormals-to-
def fcuda_approx_transcendentals : Flag<["-"], "fcuda-approx-transcendentals">,
Flags<[CC1Option]>, HelpText<"Use approximate transcendental functions">;
def fno_cuda_approx_transcendentals : Flag<["-"], "fno-cuda-approx-transcendentals">;
+def fcuda_rdc : Flag<["-"], "fcuda-rdc">, Flags<[CC1Option]>,
+ HelpText<"Generate relocatable device code, also known as separate compilation mode.">;
+def fno_cuda_rdc : Flag<["-"], "fno-cuda-rdc">;
+def fcuda_short_ptr : Flag<["-"], "fcuda-short-ptr">, Flags<[CC1Option]>,
+ HelpText<"Use 32-bit pointers for accessing const/local/shared address spaces.">;
+def fno_cuda_short_ptr : Flag<["-"], "fno-cuda-short-ptr">;
+def hip_device_lib_path_EQ : Joined<["--"], "hip-device-lib-path=">, Group<Link_Group>,
+ HelpText<"HIP device library path">;
+def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group<Link_Group>,
+ HelpText<"HIP device library">;
+def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">,
+ Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
def dA : Flag<["-"], "dA">, Group<d_Group>;
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
@@ -597,6 +631,9 @@ def fno_PIC : Flag<["-"], "fno-PIC">, Group<f_Group>;
def fPIE : Flag<["-"], "fPIE">, Group<f_Group>;
def fno_PIE : Flag<["-"], "fno-PIE">, Group<f_Group>;
def faccess_control : Flag<["-"], "faccess-control">, Group<f_Group>;
+def falign_functions : Flag<["-"], "falign-functions">, Group<f_Group>;
+def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<f_Group>;
+def fno_align_functions: Flag<["-"], "fno-align-functions">, Group<f_Group>;
def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>;
def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use Apple's kernel extensions ABI">;
@@ -693,10 +730,10 @@ def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Use instrumentation data for profile-guided optimization">;
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
- Group<f_Group>, Flags<[CC1Option]>,
+ Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Generate coverage mapping to enable code coverage analysis">;
def fno_coverage_mapping : Flag<["-"], "fno-coverage-mapping">,
- Group<f_Group>, Flags<[DriverOption]>,
+ Group<f_Group>, Flags<[DriverOption, CoreOption]>,
HelpText<"Disable code coverage analysis">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Group<f_Group>, Flags<[DriverOption]>,
@@ -721,12 +758,16 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
def fno_profile_use : Flag<["-"], "fno-profile-use">,
Alias<fno_profile_instr_use>;
-def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
+def faddrsig : Flag<["-"], "faddrsig">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
+ HelpText<"Emit an address-significance table">;
+def fno_addrsig : Flag<["-"], "fno-addrsig">, Group<f_Group>, Flags<[CoreOption]>,
+ HelpText<"Don't emit an address-significance table">;
+def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
HelpText<"Enable the 'blocks' language feature">;
def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group<f_Group>;
def fborland_extensions : Flag<["-"], "fborland-extensions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Accept non-standard constructs supported by the Borland compiler">;
-def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>;
+def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>, Flags<[CoreOption]>;
def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>,
Flags<[DriverOption]>, HelpText<"Load the clang builtins module map file.">;
def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
@@ -747,6 +788,12 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr
def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>;
def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
+def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>,
+ Flags<[CoreOption, CC1Option]>,
+ HelpText<"Require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
+def fno_complete_member_pointers : Flag<["-"], "fno-complete-member-pointers">, Group<f_clang_Group>,
+ Flags<[CoreOption]>,
+ HelpText<"Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>;
def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>;
def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
@@ -755,6 +802,7 @@ def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">
Group<f_Group>;
def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>,
HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">;
+def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>;
def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>,
HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
@@ -786,6 +834,10 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tr
HelpText<"Print a template comparison tree for differing templates">;
def fdeclspec : Flag<["-"], "fdeclspec">, Group<f_clang_Group>,
HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>;
+def fdiscard_value_names : Flag<["-"], "fdiscard-value-names">, Group<f_clang_Group>,
+ HelpText<"Discard value names in LLVM IR">, Flags<[DriverOption]>;
+def fno_discard_value_names : Flag<["-"], "fno-discard-value-names">, Group<f_clang_Group>,
+ HelpText<"Do not discard value names in LLVM IR">, Flags<[DriverOption]>;
def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group<f_Group>,
HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;
def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
@@ -801,7 +853,7 @@ def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1
HelpText<"Emit all declarations, even if unused">;
def femulated_tls : Flag<["-"], "femulated-tls">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use emutls functions to access thread_local variables">;
-def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>;
+def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>, Flags<[CC1Option]>;
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]>,
@@ -835,6 +887,17 @@ def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;
def fjump_tables : Flag<["-"], "fjump-tables">, Group<f_Group>;
def fno_jump_tables : Flag<["-"], "fno-jump-tables">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not use jump tables for lowering switches">;
+def fforce_enable_int128 : Flag<["-"], "fforce-enable-int128">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable support for int128_t type">;
+def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable support for int128_t type">;
+
+def ffixed_point : Flag<["-"], "ffixed-point">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable fixed point types">;
+def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group<f_Group>,
+ HelpText<"Disable fixed point types">;
// Begin sanitizer flags. These should all be core options exposed in all driver
// modes.
@@ -887,6 +950,14 @@ def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable use-after-scope detection in AddressSanitizer">;
+def fsanitize_address_poison_class_member_array_new_cookie
+ : Flag<[ "-" ], "fsanitize-address-poison-class-member-array-new-cookie">,
+ Group<f_clang_Group>,
+ HelpText<"Enable poisoning array cookies when using class member operator new[] in AddressSanitizer">;
+def fno_sanitize_address_poison_class_member_array_new_cookie
+ : Flag<[ "-" ], "fno-sanitize-address-poison-class-member-array-new-cookie">,
+ Group<f_clang_Group>,
+ HelpText<"Disable poisoning array cookies when using class member operator new[] in AddressSanitizer">;
def fsanitize_address_globals_dead_stripping : Flag<["-"], "fsanitize-address-globals-dead-stripping">,
Group<f_clang_Group>,
HelpText<"Enable linker dead stripping of globals in AddressSanitizer">;
@@ -991,6 +1062,13 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
" | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">;
+def fstrict_float_cast_overflow : Flag<["-"],
+ "fstrict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Assume that overflowing float-to-int casts are undefined (default)">;
+def fno_strict_float_cast_overflow : Flag<["-"],
+ "fno-strict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Relax language rules and try to match the behavior of the target's native float-to-int conversion instructions">;
+
def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
@@ -1002,6 +1080,13 @@ def frewrite_imports : Flag<["-"], "frewrite-imports">, Group<f_Group>,
Flags<[CC1Option]>;
def fno_rewrite_imports : Flag<["-"], "fno-rewrite-imports">, Group<f_Group>;
+def fdelete_null_pointer_checks : Flag<["-"],
+ "fdelete-null-pointer-checks">, Group<f_Group>,
+ HelpText<"Treat usage of null pointers as undefined behavior.">;
+def fno_delete_null_pointer_checks : Flag<["-"],
+ "fno-delete-null-pointer-checks">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Do not treat usage of null pointers as undefined behavior.">;
+
def frewrite_map_file : Separate<["-"], "frewrite-map-file">,
Group<f_Group>,
Flags<[ DriverOption, CC1Option ]>;
@@ -1044,6 +1129,11 @@ def finstrument_functions_after_inlining : Flag<["-"], "finstrument-functions-af
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 fcf_protection_EQ : Joined<["-"], "fcf-protection=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
+ HelpText<"Instrument control-flow architecture protection. Options: return, branch, full, none.">, Values<"return,branch,full,none">;
+def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
+ Alias<fcf_protection_EQ>, AliasArgs<["full"]>,
+ HelpText<"Enable cf-protection in 'full' mode">;
def fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>,
Flags<[CC1Option]>,
@@ -1062,11 +1152,19 @@ def fxray_instruction_threshold_ :
def fxray_always_instrument :
JoinedOrSeparate<["-"], "fxray-always-instrument=">,
Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">;
+ HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">;
def fxray_never_instrument :
JoinedOrSeparate<["-"], "fxray-never-instrument=">,
Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">;
+ HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">;
+def fxray_attr_list :
+ JoinedOrSeparate<["-"], "fxray-attr-list=">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Filename defining the list of functions/types for imbuing XRay attributes.">;
+def fxray_modes :
+ JoinedOrSeparate<["-"], "fxray-modes=">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"List of modes to link in by default into XRay instrumented binaries.">;
def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group<f_Group>,
Flags<[CC1Option]>,
@@ -1074,9 +1172,26 @@ def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents
def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group<f_Group>,
Flags<[CC1Option]>;
+def fxray_always_emit_typedevents : Flag<["-"], "fxray-always-emit-typedevents">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Determine whether to always emit __xray_typedevent(...) calls even if the function it appears in is not always instrumented.">;
+def fnoxray_always_emit_typedevents : Flag<["-"], "fno-xray-always-emit-typedevents">, Group<f_Group>,
+ Flags<[CC1Option]>;
+
+def fxray_link_deps : Flag<["-"], "fxray-link-deps">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Tells clang to add the link dependencies for XRay.">;
+def fnoxray_link_deps : Flag<["-"], "fnoxray-link-deps">, Group<f_Group>,
+ Flags<[CC1Option]>;
+
+def fxray_instrumentation_bundle :
+ JoinedOrSeparate<["-"], "fxray-instrumentation-bundle=">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Select which XRay instrumentation points to emit. Options: all, none, function, custom. Default is 'all'.">;
+
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.">;
+ HelpText<"Use separate accesses for consecutive bitfield runs 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.">;
@@ -1101,7 +1216,7 @@ def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">,
def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>;
def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>,
- Flags<[CC1Option]>, HelpText<"Allow merging of constants">;
+ Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">;
def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>;
def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
@@ -1155,6 +1270,8 @@ def fmodules_disable_diagnostic_validation : Flag<["-"], "fmodules-disable-diagn
def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-headers">,
Group<i_Group>, Flags<[CC1Option]>,
HelpText<"Validate the system headers that a module depends on when loading the module">;
+def fno_modules_validate_system_headers : Flag<["-"], "fno-modules-validate-system-headers">,
+ Group<i_Group>, Flags<[DriverOption]>;
def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Enable the 'modules' language feature">;
@@ -1203,11 +1320,11 @@ def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables
def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group<f_Group>,
HelpText<"Don't assume that C++'s global operator new can't alias any pointer">,
Flags<[CC1Option]>;
-def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>;
+def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>, Flags<[CoreOption]>;
def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>;
-def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option]>,
+def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable implicit builtin knowledge of functions">;
-def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option]>,
+def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable implicit builtin knowledge of a specific function">;
def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<f_Group>,
Flags<[CC1Option]>;
@@ -1229,6 +1346,10 @@ def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">,
def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
Flags<[CC1Option]>, Group<f_Group>;
+def fdigraphs : Flag<["-"], "fdigraphs">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:' (default)">;
+def fno_digraphs : Flag<["-"], "fno-digraphs">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disallow alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:'">;
def fno_declspec : Flag<["-"], "fno-declspec">, Group<f_clang_Group>,
HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>;
def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>,
@@ -1283,6 +1404,8 @@ def fno_operator_names : Flag<["-"], "fno-operator-names">, Group<f_Group>,
def fno_pascal_strings : Flag<["-"], "fno-pascal-strings">, Group<f_Group>;
def fno_rtti : Flag<["-"], "fno-rtti">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable generation of rtti information">;
+def fno_rtti_data : Flag<["-"], "fno-rtti-data">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Control emission of RTTI data">;
def fno_short_enums : Flag<["-"], "fno-short-enums">, Group<f_Group>;
def fno_show_column : Flag<["-"], "fno-show-column">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not include column number on diagnostics">;
@@ -1306,6 +1429,8 @@ def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Grou
Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">;
def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Don't use __cxa_atexit for calling destructors">;
+def fno_register_global_dtors_with_atexit : Flag<["-"], "fno-register-global-dtors-with-atexit">, Group<f_Group>,
+ HelpText<"Don't use atexit or __cxa_atexit to register global destructors">;
def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Don't use .init_array instead of .ctors">;
def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group<f_Group>;
@@ -1363,7 +1488,7 @@ def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable ARC-style weak references in Objective-C">;
// Objective-C ABI options.
-def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>,
+def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Specify the target Objective-C runtime kind and version">;
def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group<f_Group>;
@@ -1372,26 +1497,34 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr
def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>;
def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
-def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
+def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
+ HelpText<"Parse OpenMP pragmas and generate parallel code.">;
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
-def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoArgumentUnused]>;
-def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
+def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>,
+ Flags<[NoArgumentUnused, HelpHidden]>;
+def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOption, CC1Option]>,
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 fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">,
+ Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
+def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">,
+ Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">,
+ Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_simd : Flag<["-"], "fopenmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
-def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
- HelpText<"Disable OpenMP code for SIMD-based constructs.">;
+def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
+def fopenmp_cuda_mode : Flag<["-"], "fopenmp-cuda-mode">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fno_openmp_cuda_mode : Flag<["-"], "fno-openmp-cuda-mode">, Group<f_Group>,
+ Flags<[NoArgumentUnused, HelpHidden]>;
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 fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>;
+def fescaping_block_tail_calls : Flag<["-"], "fescaping-block-tail-calls">, Group<f_Group>;
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
def force__flat__namespace : Flag<["-"], "force_flat_namespace">;
def force__load : Separate<["-"], "force_load">;
@@ -1436,6 +1569,10 @@ 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 fchar8__t : Flag<["-"], "fchar8_t">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable C++ builtin type char8_t">;
+def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>,
+ HelpText<"Disable C++ builtin type char8_t">;
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>,
@@ -1548,6 +1685,8 @@ def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">;
def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>;
def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
+def fregister_global_dtors_with_atexit : Flag<["-"], "fregister-global-dtors-with-atexit">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use atexit or __cxa_atexit to register global destructors">;
def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use .init_array instead of .ctors">;
def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>;
@@ -1555,7 +1694,7 @@ def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">;
def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,
- HelpText<"Give inline C++ member functions default visibility by default">,
+ HelpText<"Give inline C++ member functions hidden visibility by default">,
Flags<[CC1Option]>;
def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>,
HelpText<"Give global types 'default' visibility and global functions and "
@@ -1565,6 +1704,11 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Grou
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>,
Flags<[CoreOption]>;
+def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Emits more virtual tables to improve devirtualization">;
+def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-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]>,
@@ -1579,6 +1723,10 @@ def fdata_sections : Flag <["-"], "fdata-sections">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">;
def fno_data_sections : Flag <["-"], "fno-data-sections">, Group<f_Group>,
Flags<[CC1Option]>;
+def fstack_size_section : Flag<["-"], "fstack-size-section">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Emit section containing metadata on function stack sizes">;
+def fno_stack_size_section : Flag<["-"], "fno-stack-size-section">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Don't emit section containing metadata on function stack sizes">;
def funique_section_names : Flag <["-"], "funique-section-names">,
Group<f_Group>, Flags<[CC1Option]>,
@@ -1604,11 +1752,12 @@ def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>,
Flags<[CC1Option]>;
def fsplit_dwarf_inlining: Flag <["-"], "fsplit-dwarf-inlining">, Group<f_Group>,
- Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
+ Flags<[CC1Option]>, HelpText<"Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF">;
def fno_split_dwarf_inlining: Flag<["-"], "fno-split-dwarf-inlining">, Group<f_Group>,
Flags<[CC1Option]>;
def fdebug_prefix_map_EQ
- : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>, Flags<[CC1Option]>,
+ : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>,
+ Flags<[CC1Option,CC1AsOption]>,
HelpText<"remap file source paths in debug info">;
def g_Flag : Flag<["-"], "g">, Group<g_Group>,
HelpText<"Generate source-level debug information">;
@@ -1657,6 +1806,7 @@ def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[Cor
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>, Flags<[CC1Option]>;
+def gno_gnu_pubnames : Flag<["-"], "gno-gnu-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"
@@ -1665,6 +1815,11 @@ def gz : Flag<["-"], "gz">, Group<g_flags_Group>,
HelpText<"DWARF debug sections compression type">;
def gz_EQ : Joined<["-"], "gz=">, Group<g_flags_Group>,
HelpText<"DWARF debug sections compression type">;
+def gembed_source : Flag<["-"], "gembed-source">, Group<g_flags_Group>, Flags<[CC1Option]>,
+ HelpText<"Embed source text in DWARF debug sections">;
+def gno_embed_source : Flag<["-"], "gno-embed-source">, Group<g_flags_Group>,
+ Flags<[DriverOption]>,
+ HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">;
def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>,
HelpText<"Display available options">;
@@ -1715,7 +1870,7 @@ def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group<clang_i_Group>
Flags<[CC1Option]>;
def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Overlay the virtual filesystem described by file over the real file system">;
-def i : Joined<["-"], "i">, Group<i_Group>;
+def imultilib : Separate<["-"], "imultilib">, Group<gfortran_Group>;
def keep__private__externs : Flag<["-"], "keep_private_externs">;
def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>,
Group<Link_Group>;
@@ -1802,6 +1957,10 @@ def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
Group<m_Group>, Alias<mmacosx_version_min_EQ>;
def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">;
+def moutline : Flag<["-"], "moutline">, Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable function outlining (AArch64 only)">;
+def mno_outline : Flag<["-"], "mno-outline">, Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable function outlining (AArch64 only)">;
def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">;
def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Option]>,
@@ -1810,6 +1969,10 @@ def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags
HelpText<"Set the stack alignment">;
def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the stack probe size">;
+def mstack_arg_probe : Flag<["-"], "mstack-arg-probe">, Group<m_Group>,
+ HelpText<"Enable stack probes">;
+def mno_stack_arg_probe : Flag<["-"], "mno-stack-arg-probe">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable stack probes which are enabled by default">;
def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"The thread model to use, e.g. posix, single (posix by default)">, Values<"posix,single">;
def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
@@ -1826,6 +1989,11 @@ 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 mrelax : Flag<["-"], "mrelax">, Group<m_riscv_Features_Group>,
+ HelpText<"Enable linker relaxation">;
+def mno_relax : Flag<["-"], "mno-relax">, Group<m_riscv_Features_Group>,
+ HelpText<"Disable linker relaxation">;
+
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>,
@@ -1842,8 +2010,8 @@ def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
HelpText<"Reserve the r9 register (ARM only)">;
def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
HelpText<"Disallow use of movt/movw pairs (ARM only)">;
-def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>,
- HelpText<"Allow use of CRC instructions (ARM only)">;
+def mcrc : Flag<["-"], "mcrc">, Group<m_Group>,
+ HelpText<"Allow use of CRC instructions (ARM/Mips only)">;
def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>,
HelpText<"Disallow use of CRC instructions (ARM only)">;
def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group<m_arm_Features_Group>,
@@ -1859,11 +2027,17 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
HelpText<"Reserve the x18 register (AArch64 only)">;
+def ffixed_x20 : Flag<["-"], "ffixed-x20">, Group<m_aarch64_Features_Group>,
+ HelpText<"Reserve the x20 register (AArch64 only)">;
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 msign_ext : Flag<["-"], "msign-ext">, Group<m_wasm_Features_Group>;
+def mno_sign_ext : Flag<["-"], "mno-sign-ext">, Group<m_wasm_Features_Group>;
+def mexception_handing : Flag<["-"], "mexception-handling">, Group<m_wasm_Features_Group>;
+def mno_exception_handing : Flag<["-"], "mno-exception-handling">, Group<m_wasm_Features_Group>;
def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">,
Flags<[HelpHidden]>,
@@ -1881,6 +2055,7 @@ def maltivec : Flag<["-"], "maltivec">, Group<m_ppc_Features_Group>;
def mno_altivec : Flag<["-"], "mno-altivec">, Group<m_ppc_Features_Group>;
def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
+def msecure_plt : Flag<["-"], "msecure-plt">, Group<m_ppc_Features_Group>;
def mpower8_vector : Flag<["-"], "mpower8-vector">,
Group<m_ppc_Features_Group>;
def mno_power8_vector : Flag<["-"], "mno-power8-vector">,
@@ -1977,127 +2152,141 @@ def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>
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 mips16 : Flag<["-"], "mips16">, Group<m_Group>;
-def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>;
-def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>;
-def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_Group>;
-def mxgot : Flag<["-"], "mxgot">, Group<m_Group>;
-def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_Group>;
-def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_Group>;
-def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_Group>;
-def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group<m_Group>;
+def mips16 : Flag<["-"], "mips16">, Group<m_mips_Features_Group>;
+def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_mips_Features_Group>;
+def mmicromips : Flag<["-"], "mmicromips">, Group<m_mips_Features_Group>;
+def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_mips_Features_Group>;
+def mxgot : Flag<["-"], "mxgot">, Group<m_mips_Features_Group>;
+def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_mips_Features_Group>;
+def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_mips_Features_Group>;
+def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_mips_Features_Group>;
+def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">,
+ Group<m_mips_Features_Group>;
def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">,
- Group<m_Group>;
-def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group<m_Group>;
+ Group<m_mips_Features_Group>;
+def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">,
+ Group<m_mips_Features_Group>;
def mbranch_likely : Flag<["-"], "mbranch-likely">, Group<m_Group>,
IgnoredGCCCompat;
def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group<m_Group>,
IgnoredGCCCompat;
def mindirect_jump_EQ : Joined<["-"], "mindirect-jump=">,
- Group<m_Group>,
+ Group<m_mips_Features_Group>,
HelpText<"Change indirect jump instructions to inhibit speculation">;
-def mdsp : Flag<["-"], "mdsp">, Group<m_Group>;
-def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_Group>;
-def mdspr2 : Flag<["-"], "mdspr2">, Group<m_Group>;
-def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_Group>;
-def msingle_float : Flag<["-"], "msingle-float">, Group<m_Group>;
-def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_Group>;
-def mmadd4 : Flag<["-"], "mmadd4">, Group<m_Group>,
+def mdsp : Flag<["-"], "mdsp">, Group<m_mips_Features_Group>;
+def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_mips_Features_Group>;
+def mdspr2 : Flag<["-"], "mdspr2">, Group<m_mips_Features_Group>;
+def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_mips_Features_Group>;
+def msingle_float : Flag<["-"], "msingle-float">, Group<m_mips_Features_Group>;
+def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_mips_Features_Group>;
+def mmadd4 : Flag<["-"], "mmadd4">, Group<m_mips_Features_Group>,
HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">;
-def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_Group>,
+def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_mips_Features_Group>,
HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">;
-def mmsa : Flag<["-"], "mmsa">, Group<m_Group>,
+def mmsa : Flag<["-"], "mmsa">, Group<m_mips_Features_Group>,
HelpText<"Enable MSA ASE (MIPS only)">;
-def mno_msa : Flag<["-"], "mno-msa">, Group<m_Group>,
+def mno_msa : Flag<["-"], "mno-msa">, Group<m_mips_Features_Group>,
HelpText<"Disable MSA ASE (MIPS only)">;
-def mmt : Flag<["-"], "mmt">, Group<m_Group>,
+def mmt : Flag<["-"], "mmt">, Group<m_mips_Features_Group>,
HelpText<"Enable MT ASE (MIPS only)">;
-def mno_mt : Flag<["-"], "mno-mt">, Group<m_Group>,
+def mno_mt : Flag<["-"], "mno-mt">, Group<m_mips_Features_Group>,
HelpText<"Disable MT ASE (MIPS only)">;
-def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>,
+def mfp64 : Flag<["-"], "mfp64">, Group<m_mips_Features_Group>,
HelpText<"Use 64-bit floating point registers (MIPS only)">;
-def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>,
+def mfp32 : Flag<["-"], "mfp32">, Group<m_mips_Features_Group>,
HelpText<"Use 32-bit floating point registers (MIPS only)">;
-def mgpopt : Flag<["-"], "mgpopt">, Group<m_Group>,
+def mgpopt : Flag<["-"], "mgpopt">, Group<m_mips_Features_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>,
+def mno_gpopt : Flag<["-"], "mno-gpopt">, Group<m_mips_Features_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>,
+def mlocal_sdata : Flag<["-"], "mlocal-sdata">,
+ Group<m_mips_Features_Group>,
HelpText<"Extend the -G behaviour to object local data (MIPS)">;
-def mno_local_sdata : Flag<["-"], "mno-local-sdata">, Group<m_Group>,
+def mno_local_sdata : Flag<["-"], "mno-local-sdata">,
+ Group<m_mips_Features_Group>,
HelpText<"Do not extend the -G behaviour to object local data (MIPS)">;
-def mextern_sdata : Flag<["-"], "mextern-sdata">, Group<m_Group>,
+def mextern_sdata : Flag<["-"], "mextern-sdata">,
+ Group<m_mips_Features_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>,
+def mno_extern_sdata : Flag<["-"], "mno-extern-sdata">,
+ Group<m_mips_Features_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>,
+def membedded_data : Flag<["-"], "membedded-data">,
+ Group<m_mips_Features_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>,
+def mno_embedded_data : Flag<["-"], "mno-embedded-data">,
+ Group<m_mips_Features_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>,
+def mnan_EQ : Joined<["-"], "mnan=">, Group<m_mips_Features_Group>;
+def mabs_EQ : Joined<["-"], "mabs=">, Group<m_mips_Features_Group>;
+def mabicalls : Flag<["-"], "mabicalls">, Group<m_mips_Features_Group>,
HelpText<"Enable SVR4-style position-independent code (Mips only)">;
-def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_Group>,
+def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_mips_Features_Group>,
HelpText<"Disable SVR4-style position-independent code (Mips only)">;
+def mno_crc : Flag<["-"], "mno-crc">, Group<m_mips_Features_Group>,
+ HelpText<"Disallow use of CRC instructions (Mips only)">;
+def mvirt : Flag<["-"], "mvirt">, Group<m_mips_Features_Group>;
+def mno_virt : Flag<["-"], "mno-virt">, Group<m_mips_Features_Group>;
+def mginv : Flag<["-"], "mginv">, Group<m_mips_Features_Group>;
+def mno_ginv : Flag<["-"], "mno-ginv">, Group<m_mips_Features_Group>;
def mips1 : Flag<["-"], "mips1">,
- Alias<march_EQ>, AliasArgs<["mips1"]>,
+ Alias<march_EQ>, AliasArgs<["mips1"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>;
def mips2 : Flag<["-"], "mips2">,
- Alias<march_EQ>, AliasArgs<["mips2"]>,
+ Alias<march_EQ>, AliasArgs<["mips2"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips2">, Flags<[HelpHidden]>;
def mips3 : Flag<["-"], "mips3">,
- Alias<march_EQ>, AliasArgs<["mips3"]>,
+ Alias<march_EQ>, AliasArgs<["mips3"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips3">, Flags<[HelpHidden]>;
def mips4 : Flag<["-"], "mips4">,
- Alias<march_EQ>, AliasArgs<["mips4"]>,
+ Alias<march_EQ>, AliasArgs<["mips4"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips4">, Flags<[HelpHidden]>;
def mips5 : Flag<["-"], "mips5">,
- Alias<march_EQ>, AliasArgs<["mips5"]>,
+ Alias<march_EQ>, AliasArgs<["mips5"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips5">, Flags<[HelpHidden]>;
def mips32 : Flag<["-"], "mips32">,
- Alias<march_EQ>, AliasArgs<["mips32"]>,
+ Alias<march_EQ>, AliasArgs<["mips32"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>;
def mips32r2 : Flag<["-"], "mips32r2">,
- Alias<march_EQ>, AliasArgs<["mips32r2"]>,
+ Alias<march_EQ>, AliasArgs<["mips32r2"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>;
def mips32r3 : Flag<["-"], "mips32r3">,
- Alias<march_EQ>, AliasArgs<["mips32r3"]>,
+ Alias<march_EQ>, AliasArgs<["mips32r3"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r3">, Flags<[HelpHidden]>;
def mips32r5 : Flag<["-"], "mips32r5">,
- Alias<march_EQ>, AliasArgs<["mips32r5"]>,
+ Alias<march_EQ>, AliasArgs<["mips32r5"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r5">, Flags<[HelpHidden]>;
def mips32r6 : Flag<["-"], "mips32r6">,
- Alias<march_EQ>, AliasArgs<["mips32r6"]>,
+ Alias<march_EQ>, AliasArgs<["mips32r6"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r6">, Flags<[HelpHidden]>;
def mips64 : Flag<["-"], "mips64">,
- Alias<march_EQ>, AliasArgs<["mips64"]>,
+ Alias<march_EQ>, AliasArgs<["mips64"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>;
def mips64r2 : Flag<["-"], "mips64r2">,
- Alias<march_EQ>, AliasArgs<["mips64r2"]>,
+ Alias<march_EQ>, AliasArgs<["mips64r2"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>;
def mips64r3 : Flag<["-"], "mips64r3">,
- Alias<march_EQ>, AliasArgs<["mips64r3"]>,
+ Alias<march_EQ>, AliasArgs<["mips64r3"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r3">, Flags<[HelpHidden]>;
def mips64r5 : Flag<["-"], "mips64r5">,
- Alias<march_EQ>, AliasArgs<["mips64r5"]>,
+ Alias<march_EQ>, AliasArgs<["mips64r5"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r5">, Flags<[HelpHidden]>;
def mips64r6 : Flag<["-"], "mips64r6">,
- Alias<march_EQ>, AliasArgs<["mips64r6"]>,
+ Alias<march_EQ>, AliasArgs<["mips64r6"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r6">, Flags<[HelpHidden]>;
-def mfpxx : Flag<["-"], "mfpxx">, Group<m_Group>,
+def mfpxx : Flag<["-"], "mfpxx">, Group<m_mips_Features_Group>,
HelpText<"Avoid FPU mode dependent operations when used with the O32 ABI">,
Flags<[HelpHidden]>;
-def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_Group>,
+def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_mips_Features_Group>,
HelpText<"Enable odd single-precision floating point registers">,
Flags<[HelpHidden]>;
-def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_Group>,
+def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_mips_Features_Group>,
HelpText<"Disable odd single-precision floating point registers">,
Flags<[HelpHidden]>;
def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
@@ -2110,7 +2299,7 @@ def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Group<m_Group>;
-def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>,
+def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden, CoreOption]>,
HelpText<"Use relative instead of canonical paths">;
def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group<clang_ignored_f_Group>;
def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>;
@@ -2193,7 +2382,7 @@ def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUn
HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags">;
def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>,
Group<Link_Group>;
-def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
+def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[CC1Option, DriverOption]>,
HelpText<"Save intermediate compilation results.">;
def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
@@ -2344,7 +2533,8 @@ def _for_linker_EQ : Joined<["--"], "for-linker=">, Alias<Xlinker>;
def _for_linker : Separate<["--"], "for-linker">, Alias<Xlinker>;
def _force_link_EQ : Joined<["--"], "force-link=">, Alias<u>;
def _force_link : Separate<["--"], "force-link">, Alias<u>;
-def _help_hidden : Flag<["--"], "help-hidden">;
+def _help_hidden : Flag<["--"], "help-hidden">,
+ HelpText<"Display help for hidden options">;
def _imacros_EQ : Joined<["--"], "imacros=">, Alias<imacros>;
def _include_barrier : Flag<["--"], "include-barrier">, Alias<I_>;
def _include_directory_after_EQ : Joined<["--"], "include-directory-after=">, Alias<idirafter>;
@@ -2414,39 +2604,50 @@ def _write_dependencies : Flag<["--"], "write-dependencies">, Alias<MD>;
def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MMD>;
def _ : Joined<["--"], "">, Flags<[Unsupported]>;
-def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
+// Hexagon feature flags.
+def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">,
+ Group<m_hexagon_Features_Group>;
def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
- AliasArgs<["hexagonv5"]>;
+ AliasArgs<["hexagonv5"]>;
def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
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">;
+ 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">;
+def ffixed_r19: Flag<["-"], "ffixed-r19">,
+ HelpText<"Reserve register r19 (Hexagon only)">;
+def mmemops : Flag<["-"], "mmemops">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable generation of memop instructions">;
+def mno_memops : Flag<["-"], "mno-memops">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable generation of memop instructions">;
+def mpackets : Flag<["-"], "mpackets">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable generation of instruction packets">;
+def mno_packets : Flag<["-"], "mno-packets">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable generation of instruction packets">;
+def mnvj : Flag<["-"], "mnvj">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable generation of new-value jumps">;
+def mno_nvj : Flag<["-"], "mno-nvj">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable generation of new-value jumps">;
+def mnvs : Flag<["-"], "mnvs">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable generation of new-value stores">;
+def mno_nvs : Flag<["-"], "mno-nvs">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable generation of new-value stores">;
// X86 feature flags
@@ -2517,10 +2718,14 @@ 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 mcldemote : Flag<["-"], "mcldemote">, Group<m_x86_Features_Group>;
+def mno_cldemote : Flag<["-"], "mno-cldemote">, 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 mwbnoinvd : Flag<["-"], "mwbnoinvd">, Group<m_x86_Features_Group>;
+def mno_wbnoinvd : Flag<["-"], "mno-wbnoinvd">, 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>;
@@ -2535,6 +2740,8 @@ 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 minvpcid : Flag<["-"], "minvpcid">, Group<m_x86_Features_Group>;
+def mno_invpcid : Flag<["-"], "mno-invpcid">, Group<m_x86_Features_Group>;
def mgfni : Flag<["-"], "mgfni">, Group<m_x86_Features_Group>;
def mno_gfni : Flag<["-"], "mno-gfni">, Group<m_x86_Features_Group>;
def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>;
@@ -2543,6 +2750,10 @@ 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 mmovdiri : Flag<["-"], "mmovdiri">, Group<m_x86_Features_Group>;
+def mno_movdiri : Flag<["-"], "mno-movdiri">, Group<m_x86_Features_Group>;
+def mmovdir64b : Flag<["-"], "mmovdir64b">, Group<m_x86_Features_Group>;
+def mno_movdir64b : Flag<["-"], "mno-movdir64b">, 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>;
@@ -2551,12 +2762,18 @@ 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 mpconfig : Flag<["-"], "mpconfig">, Group<m_x86_Features_Group>;
+def mno_pconfig : Flag<["-"], "mno-pconfig">, 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 mptwrite : Flag<["-"], "mptwrite">, Group<m_x86_Features_Group>;
+def mno_ptwrite : Flag<["-"], "mno-ptwrite">, Group<m_x86_Features_Group>;
+def mrdpid : Flag<["-"], "mrdpid">, Group<m_x86_Features_Group>;
+def mno_rdpid : Flag<["-"], "mno-rdpid">, 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>;
@@ -2575,6 +2792,8 @@ def mvaes : Flag<["-"], "mvaes">, Group<m_x86_Features_Group>;
def mno_vaes : Flag<["-"], "mno-vaes">, Group<m_x86_Features_Group>;
def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group<m_x86_Features_Group>;
def mno_vpclmulqdq : Flag<["-"], "mno-vpclmulqdq">, Group<m_x86_Features_Group>;
+def mwaitpkg : Flag<["-"], "mwaitpkg">, Group<m_x86_Features_Group>;
+def mno_waitpkg : Flag<["-"], "mno-waitpkg">, 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>;
@@ -2587,8 +2806,6 @@ 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>;
def mretpoline : Flag<["-"], "mretpoline">, Group<m_x86_Features_Group>;
def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_x86_Features_Group>;
def mretpoline_external_thunk : Flag<["-"], "mretpoline-external-thunk">, Group<m_x86_Features_Group>;
@@ -2628,8 +2845,6 @@ def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<f_Group>;
def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>, Flags<[CoreOption]>;
-defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
-def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_gcc_optimization_f_Group>;
defm align_labels : BooleanFFlag<"align-labels">, Group<clang_ignored_gcc_optimization_f_Group>;
def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group<clang_ignored_gcc_optimization_f_Group>;
defm align_loops : BooleanFFlag<"align-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
@@ -2647,8 +2862,6 @@ defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_op
defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>;
defm default_inline : BooleanFFlag<"default-inline">, Group<clang_ignored_gcc_optimization_f_Group>;
-defm delete_null_pointer_checks : BooleanFFlag<"delete-null-pointer-checks">,
- Group<clang_ignored_gcc_optimization_f_Group>;
defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group<clang_ignored_gcc_optimization_f_Group>;
defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>;
defm friend_injection : BooleanFFlag<"friend-injection">, Group<clang_ignored_f_Group>;
@@ -2658,7 +2871,6 @@ defm gcse_after_reload: BooleanFFlag<"gcse-after-reload">, Group<clang_ignored_g
defm gcse_las: BooleanFFlag<"gcse-las">, Group<clang_ignored_gcc_optimization_f_Group>;
defm gcse_sm: BooleanFFlag<"gcse-sm">, Group<clang_ignored_gcc_optimization_f_Group>;
defm gnu : BooleanFFlag<"gnu">, Group<clang_ignored_f_Group>;
-defm ident : BooleanFFlag<"ident">, Group<clang_ignored_f_Group>;
defm implicit_templates : BooleanFFlag<"implicit-templates">, Group<clang_ignored_f_Group>;
defm implement_inlines : BooleanFFlag<"implement-inlines">, Group<clang_ignored_f_Group>;
defm merge_constants : BooleanFFlag<"merge-constants">, Group<clang_ignored_gcc_optimization_f_Group>;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
index a31ac05afc1b..d144e488b56b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
@@ -30,7 +30,7 @@ class SanitizerArgs {
std::vector<std::string> ExtraDeps;
int CoverageFeatures = 0;
int MsanTrackOrigins = 0;
- bool MsanUseAfterDtor = false;
+ bool MsanUseAfterDtor = true;
bool CfiCrossDso = false;
bool CfiICallGeneralizePointers = false;
int AsanFieldPadding = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Tool.h b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h
index 8f76e17c48ba..b02ac66d3b5c 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Tool.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h
@@ -88,12 +88,12 @@ public:
virtual bool hasIntegratedCPP() const = 0;
virtual bool isLinkJob() const { return false; }
virtual bool isDsymutilJob() const { return false; }
- /// \brief Returns the level of support for response files of this tool,
+ /// Returns the level of support for response files of this tool,
/// whether it accepts arguments to be passed via a file on disk.
ResponseFileSupport getResponseFilesSupport() const {
return ResponseSupport;
}
- /// \brief Returns which encoding the response file should use. This is only
+ /// Returns which encoding the response file should use. This is only
/// relevant on Windows platforms where there are different encodings being
/// accepted for different tools. On UNIX, UTF8 is universal.
///
@@ -108,11 +108,11 @@ public:
llvm::sys::WindowsEncodingMethod getResponseFileEncoding() const {
return ResponseEncoding;
}
- /// \brief Returns which prefix to use when passing the name of a response
+ /// Returns which prefix to use when passing the name of a response
/// file as a parameter to this tool.
const char *getResponseFileFlag() const { return ResponseFlag; }
- /// \brief Does this tool have "good" standardized diagnostics, or should the
+ /// Does this tool have "good" standardized diagnostics, or should the
/// driver add an additional "command failed" diagnostic on failures.
virtual bool hasGoodDiagnostics() const { return false; }
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
index 13f54d3718b4..2f9c2c190e32 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
@@ -1,4 +1,4 @@
-//===--- ToolChain.h - Collections of tools for one platform ----*- C++ -*-===//
+//===- ToolChain.h - Collections of tools for one platform ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,69 +10,84 @@
#ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H
#define LLVM_CLANG_DRIVER_TOOLCHAIN_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Sanitizers.h"
-#include "clang/Basic/VersionTuple.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Types.h"
-#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Target/TargetOptions.h"
+#include <cassert>
#include <memory>
#include <string>
+#include <utility>
namespace llvm {
namespace opt {
- class ArgList;
- class DerivedArgList;
- class InputArgList;
-}
-}
+
+class Arg;
+class ArgList;
+class DerivedArgList;
+
+} // namespace opt
+} // namespace llvm
namespace clang {
+
class ObjCRuntime;
+
namespace vfs {
+
class FileSystem;
-}
+
+} // namespace vfs
namespace driver {
- class Compilation;
- class CudaInstallationDetector;
- class Driver;
- class InputInfo;
- class JobAction;
- class RegisterEffectiveTriple;
- class SanitizerArgs;
- class Tool;
- class XRayArgs;
+
+class Driver;
+class InputInfo;
+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;
+ const char *DriverMode = nullptr;
+
/// True if TargetPrefix is recognized as a registered target name.
- bool TargetIsValid;
+ bool TargetIsValid = false;
- ParsedClangName() : DriverMode(nullptr), TargetIsValid(false) {}
+ ParsedClangName() = default;
ParsedClangName(std::string Suffix, const char *Mode)
- : ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(false) {}
+ : ModeSuffix(Suffix), DriverMode(Mode) {}
ParsedClangName(std::string Target, std::string Suffix, const char *Mode,
bool IsRegistered)
: TargetPrefix(Target), ModeSuffix(Suffix), DriverMode(Mode),
TargetIsValid(IsRegistered) {}
+
+ bool isEmpty() const {
+ return TargetPrefix.empty() && ModeSuffix.empty() && DriverMode == nullptr;
+ }
};
/// ToolChain - Access to tools for a single platform.
class ToolChain {
public:
- typedef SmallVector<std::string, 16> path_list;
+ using path_list = SmallVector<std::string, 16>;
enum CXXStdlibType {
CST_Libcxx,
@@ -85,32 +100,33 @@ public:
};
enum RTTIMode {
- RM_EnabledExplicitly,
- RM_EnabledImplicitly,
- RM_DisabledExplicitly,
- RM_DisabledImplicitly
+ RM_Enabled,
+ RM_Disabled,
};
private:
+ friend class RegisterEffectiveTriple;
+
const Driver &D;
llvm::Triple Triple;
const llvm::opt::ArgList &Args;
+
// We need to initialize CachedRTTIArg before CachedRTTIMode
const llvm::opt::Arg *const CachedRTTIArg;
+
const RTTIMode CachedRTTIMode;
- /// The list of toolchain specific path prefixes to search for
- /// files.
+ /// The list of toolchain specific path prefixes to search for files.
path_list FilePaths;
- /// The list of toolchain specific path prefixes to search for
- /// programs.
+ /// The list of toolchain specific path prefixes to search for programs.
path_list ProgramPaths;
mutable std::unique_ptr<Tool> Clang;
mutable std::unique_ptr<Tool> Assemble;
mutable std::unique_ptr<Tool> Link;
mutable std::unique_ptr<Tool> OffloadBundler;
+
Tool *getClang() const;
Tool *getAssemble() const;
Tool *getLink() const;
@@ -128,8 +144,6 @@ private:
EffectiveTriple = std::move(ET);
}
- friend class RegisterEffectiveTriple;
-
protected:
MultilibSet Multilibs;
@@ -185,7 +199,7 @@ public:
StringRef getPlatform() const { return Triple.getVendorName(); }
StringRef getOS() const { return Triple.getOSName(); }
- /// \brief Provide the default architecture name (as expected by -arch) for
+ /// Provide the default architecture name (as expected by -arch) for
/// this toolchain.
StringRef getDefaultUniversalArchName() const;
@@ -217,7 +231,7 @@ public:
// Returns the RTTIMode for the toolchain with the current arguments.
RTTIMode getRTTIMode() const { return CachedRTTIMode; }
- /// \brief Return any implicit target and/or mode flag for an invocation of
+ /// Return any implicit target and/or mode flag for an invocation of
/// the compiler driver as `ProgName`.
///
/// For example, when called with i686-linux-android-g++, the first element
@@ -231,7 +245,6 @@ public:
/// e.g., argv[0]).
/// \return A structure of type ParsedClangName that contains the executable
/// name parts.
- ///
static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName);
// Tool access.
@@ -272,7 +285,7 @@ public:
/// the linker suffix or name.
std::string GetLinkerPath() const;
- /// \brief Dispatch to the specific toolchain for verbose printing.
+ /// Dispatch to the specific toolchain for verbose printing.
///
/// This is used when handling the verbose option to print detailed,
/// toolchain-specific information useful for understanding the behavior of
@@ -281,7 +294,7 @@ public:
// Platform defaults information
- /// \brief Returns true if the toolchain is targeting a non-native
+ /// Returns true if the toolchain is targeting a non-native
/// architecture.
virtual bool isCrossCompiling() const;
@@ -300,7 +313,7 @@ public:
/// by default.
virtual bool IsIntegratedAssemblerDefault() const { return false; }
- /// \brief Check if the toolchain should use the integrated assembler.
+ /// Check if the toolchain should use the integrated assembler.
virtual bool useIntegratedAs() const;
/// IsMathErrnoDefault - Does this tool chain use -fmath-errno by default.
@@ -318,7 +331,7 @@ public:
/// mixed dispatch method be used?
virtual bool UseObjCMixedDispatch() const { return false; }
- /// \brief Check whether to enable x86 relax relocations by default.
+ /// Check whether to enable x86 relax relocations by default.
virtual bool useRelaxRelocations() const;
/// GetDefaultStackProtectorLevel - Get the default stack protector level for
@@ -328,9 +341,7 @@ public:
}
/// GetDefaultLinker - Get the default linker to use.
- virtual const char *getDefaultLinker() const {
- return "ld";
- }
+ virtual const char *getDefaultLinker() const { return "ld"; }
/// GetDefaultRuntimeLibType - Get the default runtime library variant to use.
virtual RuntimeLibType GetDefaultRuntimeLibType() const {
@@ -355,6 +366,9 @@ public:
// as OpenMP) to find arch-specific libraries.
std::string getArchSpecificLibPath() const;
+ // Returns <OSname> part of above.
+ StringRef getOSLibName() const;
+
/// needsProfileRT - returns true if instrumentation profile is on.
static bool needsProfileRT(const llvm::opt::ArgList &Args);
@@ -362,13 +376,13 @@ public:
/// by default.
virtual bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const;
- /// \brief Test whether this toolchain defaults to PIC.
+ /// Test whether this toolchain defaults to PIC.
virtual bool isPICDefault() const = 0;
- /// \brief Test whether this toolchain defaults to PIE.
+ /// Test whether this toolchain defaults to PIE.
virtual bool isPIEDefault() const = 0;
- /// \brief Tests whether this toolchain forces its default for PIC, PIE or
+ /// Tests whether this toolchain forces its default for PIC, PIE or
/// non-PIC. If this returns true, any PIC related flags should be ignored
/// and instead the results of \c isPICDefault() and \c isPIEDefault() are
/// used exclusively.
@@ -399,14 +413,17 @@ public:
return llvm::DebuggerKind::GDB;
}
+ /// Does this toolchain supports given debug info option or not.
+ virtual bool supportsDebugInfoOption(const llvm::opt::Arg *) const {
+ return true;
+ }
+
/// 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 {
- return false;
- }
+ virtual bool SupportsEmbeddedBitcode() const { return false; }
/// getThreadModel() - Which thread model does this target use?
virtual std::string getThreadModel() const { return "posix"; }
@@ -442,7 +459,7 @@ public:
/// FIXME: this really belongs on some sort of DeploymentTarget abstraction
virtual bool hasBlocksRuntime() const { return true; }
- /// \brief Add the clang cc1 arguments for system include paths.
+ /// Add the clang cc1 arguments for system include paths.
///
/// This routine is responsible for adding the necessary cc1 arguments to
/// include headers from standard system header directories.
@@ -450,12 +467,12 @@ public:
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
- /// \brief Add options that need to be passed to cc1 for this target.
+ /// Add options that need to be passed to cc1 for this target.
virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const;
- /// \brief Add warning options that need to be passed to cc1 for this target.
+ /// Add warning options that need to be passed to cc1 for this target.
virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
// GetRuntimeLibType - Determine the runtime library type to use with the
@@ -497,27 +514,28 @@ public:
/// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags.
virtual bool AddFastMathRuntimeIfAvailable(
const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const;
+
/// addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass
/// a suitable profile runtime library to the linker.
virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- /// \brief Add arguments to use system-specific CUDA includes.
+ /// Add arguments to use system-specific CUDA includes.
virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
- /// \brief Add arguments to use MCU GCC toolchain includes.
+ /// Add arguments to use MCU GCC toolchain includes.
virtual void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
- /// \brief On Windows, returns the MSVC compatibility version.
+ /// On Windows, returns the MSVC compatibility version.
virtual VersionTuple computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const;
- /// \brief Return sanitizers which are available in this toolchain.
+ /// Return sanitizers which are available in this toolchain.
virtual SanitizerMask getSupportedSanitizers() const;
- /// \brief Return sanitizers which are enabled by default.
+ /// Return sanitizers which are enabled by default.
virtual SanitizerMask getDefaultSanitizers() const { return 0; }
};
@@ -534,7 +552,8 @@ public:
~RegisterEffectiveTriple() { TC.setEffectiveTriple(llvm::Triple()); }
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_TOOLCHAIN_H
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.def b/contrib/llvm/tools/clang/include/clang/Driver/Types.def
index 2430b5b924c3..c23f1f13361f 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Types.def
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.def
@@ -46,6 +46,9 @@ TYPE("cl", CL, PP_C, "cl", "u")
TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", "u")
TYPE("cuda", CUDA, PP_CUDA, "cu", "u")
TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", "")
+TYPE("hip-cpp-output", PP_HIP, INVALID, "cui", "u")
+TYPE("hip", HIP, PP_HIP, "cu", "u")
+TYPE("hip", HIP_DEVICE, PP_HIP, "cu", "")
TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u")
TYPE("objective-c", ObjC, PP_ObjC, "m", "u")
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.h b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
index 22a26ae46a0b..5bc6668a0d1d 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Types.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
@@ -77,6 +77,9 @@ namespace types {
/// isCuda - Is this a CUDA input.
bool isCuda(ID Id);
+ /// isHIP - Is this a HIP input.
+ bool isHIP(ID Id);
+
/// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
bool isObjC(ID Id);
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h
index e5b76162de8e..c7ca94529175 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_DRIVER_XRAYARGS_H
#define LLVM_CLANG_DRIVER_XRAYARGS_H
+#include "clang/Basic/XRayInstr.h"
#include "clang/Driver/Types.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -21,16 +22,25 @@ class ToolChain;
class XRayArgs {
std::vector<std::string> AlwaysInstrumentFiles;
std::vector<std::string> NeverInstrumentFiles;
+ std::vector<std::string> AttrListFiles;
std::vector<std::string> ExtraDeps;
+ std::vector<std::string> Modes;
+ XRayInstrSet InstrumentationBundle;
bool XRayInstrument = false;
int InstructionThreshold = 200;
bool XRayAlwaysEmitCustomEvents = false;
+ bool XRayAlwaysEmitTypedEvents = false;
+ bool XRayRT = true;
public:
/// Parses the XRay arguments from an argument list.
XRayArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
+
+ bool needsXRayRt() const { return XRayInstrument && XRayRT; }
+ llvm::ArrayRef<std::string> modeList() const { return Modes; }
+ XRayInstrSet instrumentationBundle() const { return InstrumentationBundle; }
};
} // namespace driver
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
index ac4bb471fe1c..d6eb6cd84f93 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
@@ -1,4 +1,4 @@
-//===----- Commit.h - A unit of edits ---------------------------*- C++ -*-===//
+//===- Commit.h - A unit of edits -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,17 +10,22 @@
#ifndef LLVM_CLANG_EDIT_COMMIT_H
#define LLVM_CLANG_EDIT_COMMIT_H
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/FileOffset.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
namespace clang {
- class LangOptions;
- class PPConditionalDirectiveRecord;
+
+class LangOptions;
+class PPConditionalDirectiveRecord;
+class SourceManager;
namespace edit {
- class EditedSource;
+
+class EditedSource;
class Commit {
public:
@@ -48,32 +53,34 @@ private:
const SourceManager &SourceMgr;
const LangOptions &LangOpts;
const PPConditionalDirectiveRecord *PPRec;
- EditedSource *Editor;
+ EditedSource *Editor = nullptr;
- bool IsCommitable;
+ bool IsCommitable = true;
SmallVector<Edit, 8> CachedEdits;
-
+
llvm::BumpPtrAllocator StrAlloc;
public:
explicit Commit(EditedSource &Editor);
Commit(const SourceManager &SM, const LangOptions &LangOpts,
const PPConditionalDirectiveRecord *PPRec = nullptr)
- : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(nullptr),
- IsCommitable(true) { }
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {}
bool isCommitable() const { return IsCommitable; }
bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
bool beforePreviousInsertions = false);
+
bool insertAfterToken(SourceLocation loc, StringRef text,
bool beforePreviousInsertions = false) {
return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions);
}
+
bool insertBefore(SourceLocation loc, StringRef text) {
return insert(loc, text, /*afterToken=*/false,
/*beforePreviousInsertions=*/true);
}
+
bool insertFromRange(SourceLocation loc, CharSourceRange range,
bool afterToken = false,
bool beforePreviousInsertions = false);
@@ -92,21 +99,26 @@ public:
return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange),
afterToken, beforePreviousInsertions);
}
+
bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) {
return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after);
}
+
bool remove(SourceRange TokenRange) {
return remove(CharSourceRange::getTokenRange(TokenRange));
}
+
bool replace(SourceRange TokenRange, StringRef text) {
return replace(CharSourceRange::getTokenRange(TokenRange), text);
}
+
bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) {
return replaceWithInner(CharSourceRange::getTokenRange(TokenRange),
CharSourceRange::getTokenRange(TokenInnerRange));
}
- typedef SmallVectorImpl<Edit>::const_iterator edit_iterator;
+ using edit_iterator = SmallVectorImpl<Edit>::const_iterator;
+
edit_iterator edit_begin() const { return CachedEdits.begin(); }
edit_iterator edit_end() const { return CachedEdits.end(); }
@@ -136,8 +148,8 @@ private:
SourceLocation *MacroEnd = nullptr) const;
};
-}
+} // namespace edit
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_COMMIT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
index d95a0c2be805..52873c3c3841 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
@@ -1,4 +1,4 @@
-//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===//
+//===- EditedSource.h - Collection of source edits --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,21 +11,27 @@
#define LLVM_CLANG_EDIT_EDITEDSOURCE_H
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/FileOffset.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
#include <map>
#include <tuple>
+#include <utility>
namespace clang {
- class LangOptions;
- class PPConditionalDirectiveRecord;
+
+class LangOptions;
+class PPConditionalDirectiveRecord;
+class SourceManager;
namespace edit {
- class Commit;
- class EditsReceiver;
+
+class Commit;
+class EditsReceiver;
class EditedSource {
const SourceManager &SourceMgr;
@@ -34,17 +40,19 @@ class EditedSource {
struct FileEdit {
StringRef Text;
- unsigned RemoveLen;
+ unsigned RemoveLen = 0;
- FileEdit() : RemoveLen(0) {}
+ FileEdit() = default;
};
- typedef std::map<FileOffset, FileEdit> FileEditsTy;
+ using FileEditsTy = std::map<FileOffset, FileEdit>;
+
FileEditsTy FileEdits;
struct MacroArgUse {
IdentifierInfo *Identifier;
SourceLocation ImmediateExpansionLoc;
+
// Location of argument use inside the top-level macro
SourceLocation UseLoc;
@@ -65,11 +73,11 @@ class EditedSource {
public:
EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
const PPConditionalDirectiveRecord *PPRec = nullptr)
- : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts),
- StrAlloc() { }
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts) {}
const SourceManager &getSourceManager() const { return SourceMgr; }
const LangOptions &getLangOpts() const { return LangOpts; }
+
const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const {
return PPRec;
}
@@ -77,7 +85,7 @@ public:
bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
bool commit(const Commit &commit);
-
+
void applyRewrites(EditsReceiver &receiver, bool adjustRemovals = true);
void clearRewrites();
@@ -103,8 +111,8 @@ private:
void finishedCommit();
};
-}
+} // namespace edit
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_EDITEDSOURCE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h b/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h
index 600ac28ea920..1bebbeb873a7 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h
@@ -1,4 +1,4 @@
-//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===//
+//===- EditedSource.h - Collection of source edits --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,25 +11,24 @@
#define LLVM_CLANG_EDIT_EDITSRECEIVER_H
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
namespace clang {
- class SourceLocation;
- class CharSourceRange;
-
namespace edit {
class EditsReceiver {
public:
- virtual ~EditsReceiver() { }
+ virtual ~EditsReceiver() = default;
virtual void insert(SourceLocation loc, StringRef text) = 0;
virtual void replace(CharSourceRange range, StringRef text) = 0;
- /// \brief By default it calls replace with an empty string.
+
+ /// By default it calls replace with an empty string.
virtual void remove(CharSourceRange range);
};
-}
-
-} // end namespace clang
+} // namespace edit
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_EDITSRECEIVER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h
index 0c1e72b84e51..02c1b96b3331 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h
@@ -1,4 +1,4 @@
-//===----- FileOffset.h - Offset in a file ----------------------*- C++ -*-===//
+//===- FileOffset.h - Offset in a file --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,17 +11,18 @@
#define LLVM_CLANG_EDIT_FILEOFFSET_H
#include "clang/Basic/SourceLocation.h"
+#include <tuple>
namespace clang {
-
namespace edit {
class FileOffset {
FileID FID;
- unsigned Offs;
+ unsigned Offs = 0;
+
public:
- FileOffset() : Offs(0) { }
- FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) { }
+ FileOffset() = default;
+ FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) {}
bool isInvalid() const { return FID.isInvalid(); }
@@ -37,25 +38,29 @@ public:
friend bool operator==(FileOffset LHS, FileOffset RHS) {
return LHS.FID == RHS.FID && LHS.Offs == RHS.Offs;
}
+
friend bool operator!=(FileOffset LHS, FileOffset RHS) {
return !(LHS == RHS);
}
+
friend bool operator<(FileOffset LHS, FileOffset RHS) {
return std::tie(LHS.FID, LHS.Offs) < std::tie(RHS.FID, RHS.Offs);
}
+
friend bool operator>(FileOffset LHS, FileOffset RHS) {
return RHS < LHS;
}
+
friend bool operator>=(FileOffset LHS, FileOffset RHS) {
return !(LHS < RHS);
}
+
friend bool operator<=(FileOffset LHS, FileOffset RHS) {
return !(RHS < LHS);
}
};
-}
-
-} // end namespace clang
+} // namespace edit
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_FILEOFFSET_H
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h b/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h
index 980ed1d3363f..8338d71b3e52 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h
@@ -29,7 +29,7 @@ bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit,
const ParentMap *PMap);
-
+
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit);
diff --git a/contrib/llvm/tools/clang/include/clang/Format/Format.h b/contrib/llvm/tools/clang/include/clang/Format/Format.h
index d27d934f7679..85dda948c11f 100644
--- a/contrib/llvm/tools/clang/include/clang/Format/Format.h
+++ b/contrib/llvm/tools/clang/include/clang/Format/Format.h
@@ -17,7 +17,9 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Inclusions/IncludeStyle.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Regex.h"
#include <system_error>
namespace clang {
@@ -41,27 +43,27 @@ public:
const std::error_category &getParseCategory();
std::error_code make_error_code(ParseError e);
-/// \brief The ``FormatStyle`` is used to configure the formatting to follow
+/// The ``FormatStyle`` is used to configure the formatting to follow
/// specific guidelines.
struct FormatStyle {
- /// \brief The extra indent or outdent of access modifiers, e.g. ``public:``.
+ /// The extra indent or outdent of access modifiers, e.g. ``public:``.
int AccessModifierOffset;
- /// \brief Different styles for aligning after open brackets.
+ /// Different styles for aligning after open brackets.
enum BracketAlignmentStyle {
- /// \brief Align parameters on the open bracket, e.g.:
+ /// Align parameters on the open bracket, e.g.:
/// \code
/// someLongFunction(argument1,
/// argument2);
/// \endcode
BAS_Align,
- /// \brief Don't align, instead use ``ContinuationIndentWidth``, e.g.:
+ /// Don't align, instead use ``ContinuationIndentWidth``, e.g.:
/// \code
/// someLongFunction(argument1,
/// argument2);
/// \endcode
BAS_DontAlign,
- /// \brief Always break after an open bracket, if the parameters don't fit
+ /// Always break after an open bracket, if the parameters don't fit
/// on a single line, e.g.:
/// \code
/// someLongFunction(
@@ -70,13 +72,13 @@ struct FormatStyle {
BAS_AlwaysBreak,
};
- /// \brief If ``true``, horizontally aligns arguments after an open bracket.
+ /// If ``true``, horizontally aligns arguments after an open bracket.
///
/// This applies to round brackets (parentheses), angle brackets and square
/// brackets.
BracketAlignmentStyle AlignAfterOpenBracket;
- /// \brief If ``true``, aligns consecutive assignments.
+ /// If ``true``, aligns consecutive assignments.
///
/// This will align the assignment operators of consecutive lines. This
/// will result in formattings like
@@ -87,7 +89,7 @@ struct FormatStyle {
/// \endcode
bool AlignConsecutiveAssignments;
- /// \brief If ``true``, aligns consecutive declarations.
+ /// If ``true``, aligns consecutive declarations.
///
/// This will align the declaration names of consecutive lines. This
/// will result in formattings like
@@ -98,9 +100,9 @@ struct FormatStyle {
/// \endcode
bool AlignConsecutiveDeclarations;
- /// \brief Different styles for aligning escaped newlines.
+ /// Different styles for aligning escaped newlines.
enum EscapedNewlineAlignmentStyle {
- /// \brief Don't align escaped newlines.
+ /// Don't align escaped newlines.
/// \code
/// #define A \
/// int aaaa; \
@@ -108,7 +110,7 @@ struct FormatStyle {
/// int dddddddddd;
/// \endcode
ENAS_DontAlign,
- /// \brief Align escaped newlines as far left as possible.
+ /// Align escaped newlines as far left as possible.
/// \code
/// true:
/// #define A \
@@ -119,7 +121,7 @@ struct FormatStyle {
/// false:
/// \endcode
ENAS_Left,
- /// \brief Align escaped newlines in the right-most column.
+ /// Align escaped newlines in the right-most column.
/// \code
/// #define A \
/// int aaaa; \
@@ -129,10 +131,10 @@ struct FormatStyle {
ENAS_Right,
};
- /// \brief Options for aligning backslashes in escaped newlines.
+ /// Options for aligning backslashes in escaped newlines.
EscapedNewlineAlignmentStyle AlignEscapedNewlines;
- /// \brief If ``true``, horizontally align operands of binary and ternary
+ /// If ``true``, horizontally align operands of binary and ternary
/// expressions.
///
/// Specifically, this aligns operands of a single expression that needs to be
@@ -143,7 +145,7 @@ struct FormatStyle {
/// \endcode
bool AlignOperands;
- /// \brief If ``true``, aligns trailing comments.
+ /// If ``true``, aligns trailing comments.
/// \code
/// true: false:
/// int a; // My comment a vs. int a; // My comment a
@@ -151,7 +153,7 @@ struct FormatStyle {
/// \endcode
bool AlignTrailingComments;
- /// \brief If the function declaration doesn't fit on a line,
+ /// 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
@@ -168,12 +170,12 @@ struct FormatStyle {
/// \endcode
bool AllowAllParametersOfDeclarationOnNextLine;
- /// \brief Allows contracting simple braced statements to a single line.
+ /// Allows contracting simple braced statements to a single line.
///
/// E.g., this allows ``if (a) { return; }`` to be put on a single line.
bool AllowShortBlocksOnASingleLine;
- /// \brief If ``true``, short case labels will be contracted to a single line.
+ /// If ``true``, short case labels will be contracted to a single line.
/// \code
/// true: false:
/// switch (a) { vs. switch (a) {
@@ -186,12 +188,12 @@ struct FormatStyle {
/// \endcode
bool AllowShortCaseLabelsOnASingleLine;
- /// \brief Different styles for merging short functions containing at most one
+ /// Different styles for merging short functions containing at most one
/// statement.
enum ShortFunctionStyle {
- /// \brief Never merge functions into a single line.
+ /// Never merge functions into a single line.
SFS_None,
- /// \brief Only merge functions defined inside a class. Same as "inline",
+ /// Only merge functions defined inside a class. Same as "inline",
/// except it does not implies "empty": i.e. top level empty functions
/// are not merged either.
/// \code
@@ -205,7 +207,7 @@ struct FormatStyle {
/// }
/// \endcode
SFS_InlineOnly,
- /// \brief Only merge empty functions.
+ /// Only merge empty functions.
/// \code
/// void f() {}
/// void f2() {
@@ -213,7 +215,7 @@ struct FormatStyle {
/// }
/// \endcode
SFS_Empty,
- /// \brief Only merge functions defined inside a class. Implies "empty".
+ /// Only merge functions defined inside a class. Implies "empty".
/// \code
/// class Foo {
/// void f() { foo(); }
@@ -224,7 +226,7 @@ struct FormatStyle {
/// void f() {}
/// \endcode
SFS_Inline,
- /// \brief Merge all functions fitting on a single line.
+ /// Merge all functions fitting on a single line.
/// \code
/// class Foo {
/// void f() { foo(); }
@@ -234,18 +236,18 @@ struct FormatStyle {
SFS_All,
};
- /// \brief Dependent on the value, ``int f() { return 0; }`` can be put on a
+ /// Dependent on the value, ``int f() { return 0; }`` can be put on a
/// single line.
ShortFunctionStyle AllowShortFunctionsOnASingleLine;
- /// \brief If ``true``, ``if (a) return;`` can be put on a single line.
+ /// If ``true``, ``if (a) return;`` can be put on a single line.
bool AllowShortIfStatementsOnASingleLine;
- /// \brief If ``true``, ``while (true) continue;`` can be put on a single
+ /// If ``true``, ``while (true) continue;`` can be put on a single
/// line.
bool AllowShortLoopsOnASingleLine;
- /// \brief Different ways to break after the function definition return type.
+ /// Different ways to break after the function definition return type.
/// This option is **deprecated** and is retained for backwards compatibility.
enum DefinitionReturnTypeBreakingStyle {
/// Break after return type automatically.
@@ -257,7 +259,7 @@ struct FormatStyle {
DRTBS_TopLevel,
};
- /// \brief Different ways to break after the function definition or
+ /// Different ways to break after the function definition or
/// declaration return type.
enum ReturnTypeBreakingStyle {
/// Break after return type automatically.
@@ -328,14 +330,14 @@ struct FormatStyle {
RTBS_TopLevelDefinitions,
};
- /// \brief The function definition return type breaking style to use. This
+ /// The function definition return type breaking style to use. This
/// option is **deprecated** and is retained for backwards compatibility.
DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType;
- /// \brief The function declaration return type breaking style to use.
+ /// The function declaration return type breaking style to use.
ReturnTypeBreakingStyle AlwaysBreakAfterReturnType;
- /// \brief If ``true``, always break before multiline string literals.
+ /// If ``true``, always break before multiline string literals.
///
/// This flag is mean to make cases where there are multiple multiline strings
/// in a file look more consistent. Thus, it will only take effect if wrapping
@@ -349,16 +351,46 @@ struct FormatStyle {
/// \endcode
bool AlwaysBreakBeforeMultilineStrings;
- /// \brief If ``true``, always break after the ``template<...>`` of a template
- /// declaration.
- /// \code
- /// true: false:
- /// template <typename T> vs. template <typename T> class C {};
- /// class C {};
- /// \endcode
- bool AlwaysBreakTemplateDeclarations;
+ /// Different ways to break after the template declaration.
+ enum BreakTemplateDeclarationsStyle {
+ /// Do not force break before declaration.
+ /// ``PenaltyBreakTemplateDeclaration`` is taken into account.
+ /// \code
+ /// template <typename T> T foo() {
+ /// }
+ /// template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ /// int bbbbbbbbbbbbbbbbbbbbb) {
+ /// }
+ /// \endcode
+ BTDS_No,
+ /// Force break after template declaration only when the following
+ /// declaration spans multiple lines.
+ /// \code
+ /// template <typename T> T foo() {
+ /// }
+ /// template <typename T>
+ /// T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ /// int bbbbbbbbbbbbbbbbbbbbb) {
+ /// }
+ /// \endcode
+ BTDS_MultiLine,
+ /// Always break after template declaration.
+ /// \code
+ /// template <typename T>
+ /// T foo() {
+ /// }
+ /// template <typename T>
+ /// T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ /// int bbbbbbbbbbbbbbbbbbbbb) {
+ /// }
+ /// \endcode
+ BTDS_Yes
+ };
+
+ /// The template declaration breaking style to use.
+ BreakTemplateDeclarationsStyle AlwaysBreakTemplateDeclarations;
- /// \brief If ``false``, a function call's arguments will either be all on the
+ /// If ``false``, a function call's arguments will either be all on the
/// same line or will have one line each.
/// \code
/// true:
@@ -376,7 +408,7 @@ struct FormatStyle {
/// \endcode
bool BinPackArguments;
- /// \brief If ``false``, a function declaration's or function definition's
+ /// If ``false``, a function declaration's or function definition's
/// parameters will either all be on the same line or will have one line each.
/// \code
/// true:
@@ -390,7 +422,18 @@ struct FormatStyle {
/// \endcode
bool BinPackParameters;
- /// \brief The style of breaking before or after binary operators.
+ /// The style of wrapping parameters on the same line (bin-packed) or
+ /// on one line each.
+ enum BinPackStyle {
+ /// Automatically determine parameter bin-packing behavior.
+ BPS_Auto,
+ /// Always bin-pack parameters.
+ BPS_Always,
+ /// Never bin-pack parameters.
+ BPS_Never,
+ };
+
+ /// The style of breaking before or after binary operators.
enum BinaryOperatorStyle {
/// Break after operators.
/// \code
@@ -430,10 +473,10 @@ struct FormatStyle {
BOS_All,
};
- /// \brief The way to wrap binary operators.
+ /// The way to wrap binary operators.
BinaryOperatorStyle BreakBeforeBinaryOperators;
- /// \brief Different ways to attach braces to their surrounding context.
+ /// Different ways to attach braces to their surrounding context.
enum BraceBreakingStyle {
/// Always attach braces to surrounding context.
/// \code
@@ -568,10 +611,10 @@ struct FormatStyle {
BS_Custom
};
- /// \brief The brace breaking style to use.
+ /// The brace breaking style to use.
BraceBreakingStyle BreakBeforeBraces;
- /// \brief Precise control over the wrapping of braces.
+ /// Precise control over the wrapping of braces.
/// \code
/// # Should be declared this way:
/// BreakBeforeBraces: Custom
@@ -579,7 +622,7 @@ struct FormatStyle {
/// AfterClass: true
/// \endcode
struct BraceWrappingFlags {
- /// \brief Wrap class definitions.
+ /// Wrap class definitions.
/// \code
/// true:
/// class foo {};
@@ -589,7 +632,7 @@ struct FormatStyle {
/// {};
/// \endcode
bool AfterClass;
- /// \brief Wrap control statements (``if``/``for``/``while``/``switch``/..).
+ /// Wrap control statements (``if``/``for``/``while``/``switch``/..).
/// \code
/// true:
/// if (foo())
@@ -607,7 +650,7 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterControlStatement;
- /// \brief Wrap enum definitions.
+ /// Wrap enum definitions.
/// \code
/// true:
/// enum X : int
@@ -619,7 +662,7 @@ struct FormatStyle {
/// enum X : int { B };
/// \endcode
bool AfterEnum;
- /// \brief Wrap function definitions.
+ /// Wrap function definitions.
/// \code
/// true:
/// void foo()
@@ -635,7 +678,7 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterFunction;
- /// \brief Wrap namespace definitions.
+ /// Wrap namespace definitions.
/// \code
/// true:
/// namespace
@@ -651,9 +694,11 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterNamespace;
- /// \brief Wrap ObjC definitions (``@autoreleasepool``, interfaces, ..).
+ /// Wrap ObjC definitions (interfaces, implementations...).
+ /// \note @autoreleasepool and @synchronized blocks are wrapped
+ /// according to `AfterControlStatement` flag.
bool AfterObjCDeclaration;
- /// \brief Wrap struct definitions.
+ /// Wrap struct definitions.
/// \code
/// true:
/// struct foo
@@ -667,7 +712,7 @@ struct FormatStyle {
/// };
/// \endcode
bool AfterStruct;
- /// \brief Wrap union definitions.
+ /// Wrap union definitions.
/// \code
/// true:
/// union foo
@@ -681,7 +726,7 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterUnion;
- /// \brief Wrap extern blocks.
+ /// Wrap extern blocks.
/// \code
/// true:
/// extern "C"
@@ -695,7 +740,7 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterExternBlock;
- /// \brief Wrap before ``catch``.
+ /// Wrap before ``catch``.
/// \code
/// true:
/// try {
@@ -711,7 +756,7 @@ struct FormatStyle {
/// }
/// \endcode
bool BeforeCatch;
- /// \brief Wrap before ``else``.
+ /// Wrap before ``else``.
/// \code
/// true:
/// if (foo()) {
@@ -725,9 +770,9 @@ struct FormatStyle {
/// }
/// \endcode
bool BeforeElse;
- /// \brief Indent the wrapped braces themselves.
+ /// Indent the wrapped braces themselves.
bool IndentBraces;
- /// \brief If ``false``, empty function body can be put on a single line.
+ /// If ``false``, empty function body can be put on a single line.
/// This option is used only if the opening brace of the function has
/// already been wrapped, i.e. the `AfterFunction` brace wrapping mode is
/// set, and the function could/should not be put on a single line (as per
@@ -739,7 +784,7 @@ struct FormatStyle {
/// \endcode
///
bool SplitEmptyFunction;
- /// \brief If ``false``, empty record (e.g. class, struct or union) body
+ /// If ``false``, empty record (e.g. class, struct or union) body
/// can be put on a single line. This option is used only if the opening
/// brace of the record has already been wrapped, i.e. the `AfterClass`
/// (for classes) brace wrapping mode is set.
@@ -750,7 +795,7 @@ struct FormatStyle {
/// \endcode
///
bool SplitEmptyRecord;
- /// \brief If ``false``, empty namespace body can be put on a single line.
+ /// If ``false``, empty namespace body can be put on a single line.
/// This option is used only if the opening brace of the namespace has
/// already been wrapped, i.e. the `AfterNamespace` brace wrapping mode is
/// set.
@@ -763,7 +808,7 @@ struct FormatStyle {
bool SplitEmptyNamespace;
};
- /// \brief Control of individual brace wrapping cases.
+ /// Control of individual brace wrapping cases.
///
/// If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how
/// each individual brace case should be handled. Otherwise, this is ignored.
@@ -777,7 +822,7 @@ struct FormatStyle {
/// \endcode
BraceWrappingFlags BraceWrapping;
- /// \brief If ``true``, ternary operators will be placed after line breaks.
+ /// If ``true``, ternary operators will be placed after line breaks.
/// \code
/// true:
/// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription
@@ -791,36 +836,36 @@ struct FormatStyle {
/// \endcode
bool BreakBeforeTernaryOperators;
- /// \brief Different ways to break initializers.
+ /// Different ways to break initializers.
enum BreakConstructorInitializersStyle {
/// Break constructor initializers before the colon and after the commas.
/// \code
- /// Constructor()
- /// : initializer1(),
- /// initializer2()
+ /// Constructor()
+ /// : initializer1(),
+ /// initializer2()
/// \endcode
BCIS_BeforeColon,
/// Break constructor initializers before the colon and commas, and align
/// the commas with the colon.
/// \code
- /// Constructor()
- /// : initializer1()
- /// , initializer2()
+ /// Constructor()
+ /// : initializer1()
+ /// , initializer2()
/// \endcode
BCIS_BeforeComma,
/// Break constructor initializers after the colon and commas.
/// \code
- /// Constructor() :
- /// initializer1(),
- /// initializer2()
+ /// Constructor() :
+ /// initializer1(),
+ /// initializer2()
/// \endcode
BCIS_AfterColon
};
- /// \brief The constructor initializers style to use.
+ /// The constructor initializers style to use.
BreakConstructorInitializersStyle BreakConstructorInitializers;
- /// \brief Break after each annotation on a field in Java files.
+ /// Break after each annotation on a field in Java files.
/// \code{.java}
/// true: false:
/// @Partial vs. @Partial @Mock DataLoad loader;
@@ -829,17 +874,17 @@ struct FormatStyle {
/// \endcode
bool BreakAfterJavaFieldAnnotations;
- /// \brief Allow breaking string literals when formatting.
+ /// Allow breaking string literals when formatting.
bool BreakStringLiterals;
- /// \brief The column limit.
+ /// The column limit.
///
/// A column limit of ``0`` means that there is no column limit. In this case,
/// clang-format will respect the input's line breaking decisions within
/// statements unless they contradict other rules.
unsigned ColumnLimit;
- /// \brief A regular expression that describes comments with special meaning,
+ /// A regular expression that describes comments with special meaning,
/// which should not be split into lines or otherwise changed.
/// \code
/// // CommentPragmas: '^ FOOBAR pragma:'
@@ -848,18 +893,39 @@ struct FormatStyle {
/// \endcode
std::string CommentPragmas;
- /// \brief If ``true``, in the class inheritance expression clang-format will
- /// break before ``:`` and ``,`` if there is multiple inheritance.
- /// \code
- /// true: false:
- /// class MyClass vs. class MyClass : public X, public Y {
- /// : public X };
- /// , public Y {
- /// };
- /// \endcode
- bool BreakBeforeInheritanceComma;
+ /// Different ways to break inheritance list.
+ enum BreakInheritanceListStyle {
+ /// Break inheritance list before the colon and after the commas.
+ /// \code
+ /// class Foo
+ /// : Base1,
+ /// Base2
+ /// {};
+ /// \endcode
+ BILS_BeforeColon,
+ /// Break inheritance list before the colon and commas, and align
+ /// the commas with the colon.
+ /// \code
+ /// class Foo
+ /// : Base1
+ /// , Base2
+ /// {};
+ /// \endcode
+ BILS_BeforeComma,
+ /// Break inheritance list after the colon and commas.
+ /// \code
+ /// class Foo :
+ /// Base1,
+ /// Base2
+ /// {};
+ /// \endcode
+ BILS_AfterColon
+ };
+
+ /// The inheritance list style to use.
+ BreakInheritanceListStyle BreakInheritanceList;
- /// \brief If ``true``, consecutive namespace declarations will be on the same
+ /// If ``true``, consecutive namespace declarations will be on the same
/// line. If ``false``, each namespace is declared on a new line.
/// \code
/// true:
@@ -882,7 +948,7 @@ struct FormatStyle {
/// \endcode
bool CompactNamespaces;
- /// \brief If the constructor initializers don't fit on a line, put each
+ /// If the constructor initializers don't fit on a line, put each
/// initializer on its own line.
/// \code
/// true:
@@ -900,11 +966,11 @@ struct FormatStyle {
/// \endcode
bool ConstructorInitializerAllOnOneLineOrOnePerLine;
- /// \brief The number of characters to use for indentation of constructor
- /// initializer lists.
+ /// The number of characters to use for indentation of constructor
+ /// initializer lists as well as inheritance lists.
unsigned ConstructorInitializerIndentWidth;
- /// \brief Indent width for line continuations.
+ /// Indent width for line continuations.
/// \code
/// ContinuationIndentWidth: 2
///
@@ -914,7 +980,7 @@ struct FormatStyle {
/// \endcode
unsigned ContinuationIndentWidth;
- /// \brief If ``true``, format braced lists as best suited for C++11 braced
+ /// If ``true``, format braced lists as best suited for C++11 braced
/// lists.
///
/// Important differences:
@@ -936,17 +1002,17 @@ struct FormatStyle {
/// \endcode
bool Cpp11BracedListStyle;
- /// \brief If ``true``, analyze the formatted file for the most common
+ /// If ``true``, analyze the formatted file for the most common
/// alignment of ``&`` and ``*``.
/// Pointer and reference alignment styles are going to be updated according
/// to the preferences found in the file.
/// ``PointerAlignment`` is then used only as fallback.
bool DerivePointerAlignment;
- /// \brief Disables formatting completely.
+ /// Disables formatting completely.
bool DisableFormat;
- /// \brief If ``true``, clang-format detects whether function calls and
+ /// If ``true``, clang-format detects whether function calls and
/// definitions are formatted with one parameter per line.
///
/// Each call can be bin-packed, one-per-line or inconclusive. If it is
@@ -958,7 +1024,7 @@ struct FormatStyle {
/// not use this in config files, etc. Use at your own risk.
bool ExperimentalAutoDetectBinPacking;
- /// \brief If ``true``, clang-format adds missing namespace end comments and
+ /// If ``true``, clang-format adds missing namespace end comments and
/// fixes invalid existing ones.
/// \code
/// true: false:
@@ -968,7 +1034,7 @@ struct FormatStyle {
/// \endcode
bool FixNamespaceComments;
- /// \brief A vector of macros that should be interpreted as foreach loops
+ /// A vector of macros that should be interpreted as foreach loops
/// instead of as function calls.
///
/// These are expected to be macros of the form:
@@ -985,93 +1051,9 @@ 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.
- std::string Regex;
- /// \brief The priority to assign to this category.
- int Priority;
- bool operator==(const IncludeCategory &Other) const {
- return Regex == Other.Regex && Priority == Other.Priority;
- }
- };
+ tooling::IncludeStyle IncludeStyle;
- /// \brief Regular expressions denoting the different ``#include`` categories
- /// used for ordering ``#includes``.
- ///
- /// These regular expressions are matched against the filename of an include
- /// (including the <> or "") in order. The value belonging to the first
- /// matching regular expression is assigned and ``#includes`` are sorted first
- /// according to increasing category number and then alphabetically within
- /// each category.
- ///
- /// If none of the regular expressions match, INT_MAX is assigned as
- /// category. The main header for a source file automatically gets category 0.
- /// so that it is generally kept at the beginning of the ``#includes``
- /// (http://llvm.org/docs/CodingStandards.html#include-style). However, you
- /// can also assign negative priorities if you have certain headers that
- /// always need to be first.
- ///
- /// To configure this in the .clang-format file, use:
- /// \code{.yaml}
- /// IncludeCategories:
- /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
- /// Priority: 2
- /// - Regex: '^(<|"(gtest|gmock|isl|json)/)'
- /// Priority: 3
- /// - Regex: '.*'
- /// Priority: 1
- /// \endcode
- std::vector<IncludeCategory> IncludeCategories;
-
- /// \brief Specify a regular expression of suffixes that are allowed in the
- /// file-to-main-include mapping.
- ///
- /// When guessing whether a #include is the "main" include (to assign
- /// category 0, see above), use this regex of allowed suffixes to the header
- /// stem. A partial match is done, so that:
- /// - "" means "arbitrary suffix"
- /// - "$" means "no suffix"
- ///
- /// For example, if configured to "(_test)?$", then a header a.h would be seen
- /// as the "main" include in both a.cc and a_test.cc.
- std::string IncludeIsMainRegex;
-
- /// \brief Indent case labels one level from the switch statement.
+ /// Indent case labels one level from the switch statement.
///
/// When ``false``, use the same indentation level as for the switch statement.
/// Switch statement body is always indented one level more than case labels.
@@ -1087,7 +1069,7 @@ struct FormatStyle {
/// \endcode
bool IndentCaseLabels;
- /// \brief Options for indenting preprocessor directives.
+ /// Options for indenting preprocessor directives.
enum PPDirectiveIndentStyle {
/// Does not indent any directives.
/// \code
@@ -1109,10 +1091,10 @@ struct FormatStyle {
PPDIS_AfterHash
};
- /// \brief The preprocessor directive indenting style to use.
+ /// The preprocessor directive indenting style to use.
PPDirectiveIndentStyle IndentPPDirectives;
- /// \brief The number of columns to use for indentation.
+ /// The number of columns to use for indentation.
/// \code
/// IndentWidth: 3
///
@@ -1125,7 +1107,7 @@ struct FormatStyle {
/// \endcode
unsigned IndentWidth;
- /// \brief Indent if a function definition or declaration is wrapped after the
+ /// Indent if a function definition or declaration is wrapped after the
/// type.
/// \code
/// true:
@@ -1138,7 +1120,7 @@ struct FormatStyle {
/// \endcode
bool IndentWrappedFunctionNames;
- /// \brief Quotation styles for JavaScript strings. Does not affect template
+ /// Quotation styles for JavaScript strings. Does not affect template
/// strings.
enum JavaScriptQuoteStyle {
/// Leave string quotes as they are.
@@ -1161,10 +1143,10 @@ struct FormatStyle {
JSQS_Double
};
- /// \brief The JavaScriptQuoteStyle to use for JavaScript strings.
+ /// The JavaScriptQuoteStyle to use for JavaScript strings.
JavaScriptQuoteStyle JavaScriptQuotes;
- /// \brief Whether to wrap JavaScript import/export statements.
+ /// Whether to wrap JavaScript import/export statements.
/// \code{.js}
/// true:
/// import {
@@ -1178,7 +1160,7 @@ struct FormatStyle {
/// \endcode
bool JavaScriptWrapImports;
- /// \brief If true, the empty line at the start of blocks is kept.
+ /// If true, the empty line at the start of blocks is kept.
/// \code
/// true: false:
/// if (foo) { vs. if (foo) {
@@ -1188,7 +1170,7 @@ struct FormatStyle {
/// \endcode
bool KeepEmptyLinesAtTheStartOfBlocks;
- /// \brief Supported languages.
+ /// Supported languages.
///
/// When stored in a configuration file, specifies the language, that the
/// configuration targets. When passed to the ``reformat()`` function, enables
@@ -1215,10 +1197,10 @@ struct FormatStyle {
};
bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; }
- /// \brief Language, this format style is targeted at.
+ /// Language, this format style is targeted at.
LanguageKind Language;
- /// \brief A regular expression matching macros that start a block.
+ /// A regular expression matching macros that start a block.
/// \code
/// # With:
/// MacroBlockBegin: "^NS_MAP_BEGIN|\
@@ -1246,10 +1228,10 @@ struct FormatStyle {
/// \endcode
std::string MacroBlockBegin;
- /// \brief A regular expression matching macros that end a block.
+ /// A regular expression matching macros that end a block.
std::string MacroBlockEnd;
- /// \brief The maximum number of consecutive empty lines to keep.
+ /// The maximum number of consecutive empty lines to keep.
/// \code
/// MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0
/// int f() { int f() {
@@ -1262,7 +1244,7 @@ struct FormatStyle {
/// \endcode
unsigned MaxEmptyLinesToKeep;
- /// \brief Different ways to indent namespace contents.
+ /// Different ways to indent namespace contents.
enum NamespaceIndentationKind {
/// Don't indent in namespaces.
/// \code
@@ -1296,10 +1278,42 @@ struct FormatStyle {
NI_All
};
- /// \brief The indentation used for namespaces.
+ /// The indentation used for namespaces.
NamespaceIndentationKind NamespaceIndentation;
- /// \brief The number of characters to use for indentation of ObjC blocks.
+ /// Controls bin-packing Objective-C protocol conformance list
+ /// items into as few lines as possible when they go over ``ColumnLimit``.
+ ///
+ /// If ``Auto`` (the default), delegates to the value in
+ /// ``BinPackParameters``. If that is ``true``, bin-packs Objective-C
+ /// protocol conformance list items into as few lines as possible
+ /// whenever they go over ``ColumnLimit``.
+ ///
+ /// If ``Always``, always bin-packs Objective-C protocol conformance
+ /// list items into as few lines as possible whenever they go over
+ /// ``ColumnLimit``.
+ ///
+ /// If ``Never``, lays out Objective-C protocol conformance list items
+ /// onto individual lines whenever they go over ``ColumnLimit``.
+ ///
+ /// \code{.objc}
+ /// Always (or Auto, if BinPackParameters=true):
+ /// @interface ccccccccccccc () <
+ /// ccccccccccccc, ccccccccccccc,
+ /// ccccccccccccc, ccccccccccccc> {
+ /// }
+ ///
+ /// Never (or Auto, if BinPackParameters=false):
+ /// @interface ddddddddddddd () <
+ /// ddddddddddddd,
+ /// ddddddddddddd,
+ /// ddddddddddddd,
+ /// ddddddddddddd> {
+ /// }
+ /// \endcode
+ BinPackStyle ObjCBinPackProtocolList;
+
+ /// The number of characters to use for indentation of ObjC blocks.
/// \code{.objc}
/// ObjCBlockIndentWidth: 4
///
@@ -1309,37 +1323,40 @@ struct FormatStyle {
/// \endcode
unsigned ObjCBlockIndentWidth;
- /// \brief Add a space after ``@property`` in Objective-C, i.e. use
+ /// Add a space after ``@property`` in Objective-C, i.e. use
/// ``@property (readonly)`` instead of ``@property(readonly)``.
bool ObjCSpaceAfterProperty;
- /// \brief Add a space in front of an Objective-C protocol list, i.e. use
+ /// Add a space in front of an Objective-C protocol list, i.e. use
/// ``Foo <Protocol>`` instead of ``Foo<Protocol>``.
bool ObjCSpaceBeforeProtocolList;
- /// \brief The penalty for breaking around an assignment operator.
+ /// The penalty for breaking around an assignment operator.
unsigned PenaltyBreakAssignment;
- /// \brief The penalty for breaking a function call after ``call(``.
+ /// The penalty for breaking a function call after ``call(``.
unsigned PenaltyBreakBeforeFirstCallParameter;
- /// \brief The penalty for each line break introduced inside a comment.
+ /// The penalty for each line break introduced inside a comment.
unsigned PenaltyBreakComment;
- /// \brief The penalty for breaking before the first ``<<``.
+ /// The penalty for breaking before the first ``<<``.
unsigned PenaltyBreakFirstLessLess;
- /// \brief The penalty for each line break introduced inside a string literal.
+ /// The penalty for each line break introduced inside a string literal.
unsigned PenaltyBreakString;
- /// \brief The penalty for each character outside of the column limit.
+ /// The penalty for breaking after template declaration.
+ unsigned PenaltyBreakTemplateDeclaration;
+
+ /// The penalty for each character outside of the column limit.
unsigned PenaltyExcessCharacter;
- /// \brief Penalty for putting the return type of a function onto its own
+ /// Penalty for putting the return type of a function onto its own
/// line.
unsigned PenaltyReturnTypeOnItsOwnLine;
- /// \brief The ``&`` and ``*`` alignment style.
+ /// The ``&`` and ``*`` alignment style.
enum PointerAlignmentStyle {
/// Align pointer to the left.
/// \code
@@ -1358,45 +1375,69 @@ struct FormatStyle {
PAS_Middle
};
- /// \brief Pointer and reference alignment style.
+ /// 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.
+ /// The language of this raw string.
LanguageKind Language;
- /// \brief The style name on which this raw string format is based on.
+ /// A list of raw string delimiters that match this language.
+ std::vector<std::string> Delimiters;
+ /// A list of enclosing function names that match this language.
+ std::vector<std::string> EnclosingFunctions;
+ /// The canonical delimiter for this language.
+ std::string CanonicalDelimiter;
+ /// 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 &&
+ return Language == Other.Language && Delimiters == Other.Delimiters &&
+ EnclosingFunctions == Other.EnclosingFunctions &&
+ CanonicalDelimiter == Other.CanonicalDelimiter &&
BasedOnStyle == Other.BasedOnStyle;
}
};
- /// \brief Raw string delimiters denoting that the raw string contents are
- /// code in a particular language and can be reformatted.
+ /// Defines hints for detecting supported languages code blocks in raw
+ /// strings.
+ ///
+ /// A raw string with a matching delimiter or a matching enclosing function
+ /// name will be reformatted assuming the specified language based on the
+ /// style for that language defined in the .clang-format file. If no style has
+ /// been defined in the .clang-format file for the specific language, a
+ /// predefined style given by 'BasedOnStyle' is used. If 'BasedOnStyle' is not
+ /// found, the formatting is based on llvm style. A matching delimiter takes
+ /// precedence over a matching enclosing function name for determining the
+ /// language of the raw string contents.
///
- /// 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.
+ /// If a canonical delimiter is specified, occurrences of other delimiters for
+ /// the same language will be updated to the canonical if possible.
+ ///
+ /// There should be at most one specification per language and each delimiter
+ /// and enclosing function should not occur in multiple specifications.
///
/// To configure this in the .clang-format file, use:
/// \code{.yaml}
/// RawStringFormats:
- /// - Delimiter: 'pb'
- /// Language: TextProto
- /// BasedOnStyle: llvm
- /// - Delimiter: 'proto'
- /// Language: TextProto
- /// BasedOnStyle: google
+ /// - Language: TextProto
+ /// Delimiters:
+ /// - 'pb'
+ /// - 'proto'
+ /// EnclosingFunctions:
+ /// - 'PARSE_TEXT_PROTO'
+ /// BasedOnStyle: google
+ /// - Language: Cpp
+ /// Delimiters:
+ /// - 'cc'
+ /// - 'cpp'
+ /// BasedOnStyle: llvm
+ /// CanonicalDelimiter: 'cc'
/// \endcode
std::vector<RawStringFormat> RawStringFormats;
- /// \brief If ``true``, clang-format will attempt to re-flow comments.
+ /// If ``true``, clang-format will attempt to re-flow comments.
/// \code
/// false:
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
@@ -1410,7 +1451,7 @@ struct FormatStyle {
/// \endcode
bool ReflowComments;
- /// \brief If ``true``, clang-format will sort ``#includes``.
+ /// If ``true``, clang-format will sort ``#includes``.
/// \code
/// false: true:
/// #include "b.h" vs. #include "a.h"
@@ -1418,7 +1459,7 @@ struct FormatStyle {
/// \endcode
bool SortIncludes;
- /// \brief If ``true``, clang-format will sort using declarations.
+ /// 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
@@ -1434,21 +1475,21 @@ struct FormatStyle {
/// \endcode
bool SortUsingDeclarations;
- /// \brief If ``true``, a space is inserted after C style casts.
+ /// If ``true``, a space is inserted after C style casts.
/// \code
/// true: false:
- /// (int)i; vs. (int) i;
+ /// (int) i; vs. (int)i;
/// \endcode
bool SpaceAfterCStyleCast;
- /// \brief If \c true, a space will be inserted after the 'template' keyword.
+ /// If \c true, a space will be inserted after the 'template' keyword.
/// \code
/// true: false:
/// template <int> void foo(); vs. template<int> void foo();
/// \endcode
bool SpaceAfterTemplateKeyword;
- /// \brief If ``false``, spaces will be removed before assignment operators.
+ /// If ``false``, spaces will be removed before assignment operators.
/// \code
/// true: false:
/// int a = 5; vs. int a=5;
@@ -1456,7 +1497,33 @@ struct FormatStyle {
/// \endcode
bool SpaceBeforeAssignmentOperators;
- /// \brief Different ways to put a space before opening parentheses.
+ /// If ``true``, a space will be inserted before a C++11 braced list
+ /// used to initialize an object (after the preceding identifier or type).
+ /// \code
+ /// true: false:
+ /// Foo foo { bar }; vs. Foo foo{ bar };
+ /// Foo {}; Foo{};
+ /// vector<int> { 1, 2, 3 }; vector<int>{ 1, 2, 3 };
+ /// new int[3] { 1, 2, 3 }; new int[3]{ 1, 2, 3 };
+ /// \endcode
+ bool SpaceBeforeCpp11BracedList;
+
+ /// If ``false``, spaces will be removed before constructor initializer
+ /// colon.
+ /// \code
+ /// true: false:
+ /// Foo::Foo() : a(a) {} Foo::Foo(): a(a) {}
+ /// \endcode
+ bool SpaceBeforeCtorInitializerColon;
+
+ /// If ``false``, spaces will be removed before inheritance colon.
+ /// \code
+ /// true: false:
+ /// class Foo : Bar {} vs. class Foo: Bar {}
+ /// \endcode
+ bool SpaceBeforeInheritanceColon;
+
+ /// Different ways to put a space before opening parentheses.
enum SpaceBeforeParensOptions {
/// Never put a space before opening parentheses.
/// \code
@@ -1491,10 +1558,18 @@ struct FormatStyle {
SBPO_Always
};
- /// \brief Defines in which cases to put a space before opening parentheses.
+ /// Defines in which cases to put a space before opening parentheses.
SpaceBeforeParensOptions SpaceBeforeParens;
- /// \brief If ``true``, spaces may be inserted into ``()``.
+ /// If ``false``, spaces will be removed before range-based for loop
+ /// colon.
+ /// \code
+ /// true: false:
+ /// for (auto v : values) {} vs. for(auto v: values) {}
+ /// \endcode
+ bool SpaceBeforeRangeBasedForLoopColon;
+
+ /// If ``true``, spaces may be inserted into ``()``.
/// \code
/// true: false:
/// void f( ) { vs. void f() {
@@ -1506,7 +1581,7 @@ struct FormatStyle {
/// \endcode
bool SpaceInEmptyParentheses;
- /// \brief The number of spaces before trailing line comments
+ /// The number of spaces before trailing line comments
/// (``//`` - comments).
///
/// This does not affect trailing block comments (``/*`` - comments) as
@@ -1522,7 +1597,7 @@ struct FormatStyle {
/// \endcode
unsigned SpacesBeforeTrailingComments;
- /// \brief If ``true``, spaces will be inserted after ``<`` and before ``>``
+ /// If ``true``, spaces will be inserted after ``<`` and before ``>``
/// in template argument lists.
/// \code
/// true: false:
@@ -1531,7 +1606,7 @@ struct FormatStyle {
/// \endcode
bool SpacesInAngles;
- /// \brief If ``true``, spaces are inserted inside container literals (e.g.
+ /// If ``true``, spaces are inserted inside container literals (e.g.
/// ObjC and Javascript array and dict literals).
/// \code{.js}
/// true: false:
@@ -1540,21 +1615,21 @@ struct FormatStyle {
/// \endcode
bool SpacesInContainerLiterals;
- /// \brief If ``true``, spaces may be inserted into C style casts.
+ /// If ``true``, spaces may be inserted into C style casts.
/// \code
/// true: false:
/// x = ( int32 )y vs. x = (int32)y
/// \endcode
bool SpacesInCStyleCastParentheses;
- /// \brief If ``true``, spaces will be inserted after ``(`` and before ``)``.
+ /// If ``true``, spaces will be inserted after ``(`` and before ``)``.
/// \code
/// true: false:
/// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
/// \endcode
bool SpacesInParentheses;
- /// \brief If ``true``, spaces will be inserted after ``[`` and before ``]``.
+ /// If ``true``, spaces will be inserted after ``[`` and before ``]``.
/// Lambdas or unspecified size array declarations will not be affected.
/// \code
/// true: false:
@@ -1563,7 +1638,7 @@ struct FormatStyle {
/// \endcode
bool SpacesInSquareBrackets;
- /// \brief Supported language standards.
+ /// Supported language standards.
enum LanguageStandard {
/// Use C++03-compatible syntax.
LS_Cpp03,
@@ -1574,14 +1649,14 @@ struct FormatStyle {
LS_Auto
};
- /// \brief Format compatible with this standard, e.g. use ``A<A<int> >``
+ /// Format compatible with this standard, e.g. use ``A<A<int> >``
/// instead of ``A<A<int>>`` for ``LS_Cpp03``.
LanguageStandard Standard;
- /// \brief The number of columns used for tab stops.
+ /// The number of columns used for tab stops.
unsigned TabWidth;
- /// \brief Different ways to use tab in formatting.
+ /// Different ways to use tab in formatting.
enum UseTabStyle {
/// Never use tab.
UT_Never,
@@ -1594,7 +1669,7 @@ struct FormatStyle {
UT_Always
};
- /// \brief The way to use tab characters in the resulting file.
+ /// The way to use tab characters in the resulting file.
UseTabStyle UseTab;
bool operator==(const FormatStyle &R) const {
@@ -1630,7 +1705,7 @@ struct FormatStyle {
BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
BreakStringLiterals == R.BreakStringLiterals &&
ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&
- BreakBeforeInheritanceComma == R.BreakBeforeInheritanceComma &&
+ BreakInheritanceList == R.BreakInheritanceList &&
ConstructorInitializerAllOnOneLineOrOnePerLine ==
R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
ConstructorInitializerIndentWidth ==
@@ -1643,8 +1718,8 @@ struct FormatStyle {
R.ExperimentalAutoDetectBinPacking &&
FixNamespaceComments == R.FixNamespaceComments &&
ForEachMacros == R.ForEachMacros &&
- IncludeBlocks == R.IncludeBlocks &&
- IncludeCategories == R.IncludeCategories &&
+ IncludeStyle.IncludeBlocks == R.IncludeStyle.IncludeBlocks &&
+ IncludeStyle.IncludeCategories == R.IncludeStyle.IncludeCategories &&
IndentCaseLabels == R.IndentCaseLabels &&
IndentPPDirectives == R.IndentPPDirectives &&
IndentWidth == R.IndentWidth && Language == R.Language &&
@@ -1657,11 +1732,11 @@ struct FormatStyle {
MacroBlockEnd == R.MacroBlockEnd &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
NamespaceIndentation == R.NamespaceIndentation &&
+ ObjCBinPackProtocolList == R.ObjCBinPackProtocolList &&
ObjCBlockIndentWidth == R.ObjCBlockIndentWidth &&
ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty &&
ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
- PenaltyBreakAssignment ==
- R.PenaltyBreakAssignment &&
+ PenaltyBreakAssignment == R.PenaltyBreakAssignment &&
PenaltyBreakBeforeFirstCallParameter ==
R.PenaltyBreakBeforeFirstCallParameter &&
PenaltyBreakComment == R.PenaltyBreakComment &&
@@ -1669,12 +1744,20 @@ struct FormatStyle {
PenaltyBreakString == R.PenaltyBreakString &&
PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
+ PenaltyBreakTemplateDeclaration ==
+ R.PenaltyBreakTemplateDeclaration &&
PointerAlignment == R.PointerAlignment &&
RawStringFormats == R.RawStringFormats &&
SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&
SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword &&
SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
+ SpaceBeforeCpp11BracedList == R.SpaceBeforeCpp11BracedList &&
+ SpaceBeforeCtorInitializerColon ==
+ R.SpaceBeforeCtorInitializerColon &&
+ SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon &&
SpaceBeforeParens == R.SpaceBeforeParens &&
+ SpaceBeforeRangeBasedForLoopColon ==
+ R.SpaceBeforeRangeBasedForLoopColon &&
SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
SpacesInAngles == R.SpacesInAngles &&
@@ -1685,38 +1768,75 @@ struct FormatStyle {
Standard == R.Standard && TabWidth == R.TabWidth &&
UseTab == R.UseTab;
}
+
+ llvm::Optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const;
+
+ // Stores per-language styles. A FormatStyle instance inside has an empty
+ // StyleSet. A FormatStyle instance returned by the Get method has its
+ // StyleSet set to a copy of the originating StyleSet, effectively keeping the
+ // internal representation of that StyleSet alive.
+ //
+ // The memory management and ownership reminds of a birds nest: chicks
+ // leaving the nest take photos of the nest with them.
+ struct FormatStyleSet {
+ typedef std::map<FormatStyle::LanguageKind, FormatStyle> MapType;
+
+ llvm::Optional<FormatStyle> Get(FormatStyle::LanguageKind Language) const;
+
+ // Adds \p Style to this FormatStyleSet. Style must not have an associated
+ // FormatStyleSet.
+ // Style.Language should be different than LK_None. If this FormatStyleSet
+ // already contains an entry for Style.Language, that gets replaced with the
+ // passed Style.
+ void Add(FormatStyle Style);
+
+ // Clears this FormatStyleSet.
+ void Clear();
+
+ private:
+ std::shared_ptr<MapType> Styles;
+ };
+
+ static FormatStyleSet BuildStyleSetFromConfiguration(
+ const FormatStyle &MainStyle,
+ const std::vector<FormatStyle> &ConfigurationStyles);
+
+private:
+ FormatStyleSet StyleSet;
+
+ friend std::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
};
-/// \brief Returns a format style complying with the LLVM coding standards:
+/// Returns a format style complying with the LLVM coding standards:
/// http://llvm.org/docs/CodingStandards.html.
FormatStyle getLLVMStyle();
-/// \brief Returns a format style complying with one of Google's style guides:
+/// Returns a format style complying with one of Google's style guides:
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml.
/// http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml.
/// https://developers.google.com/protocol-buffers/docs/style.
FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language);
-/// \brief Returns a format style complying with Chromium's style guide:
+/// Returns a format style complying with Chromium's style guide:
/// http://www.chromium.org/developers/coding-style.
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language);
-/// \brief Returns a format style complying with Mozilla's style guide:
+/// Returns a format style complying with Mozilla's style guide:
/// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style.
FormatStyle getMozillaStyle();
-/// \brief Returns a format style complying with Webkit's style guide:
+/// Returns a format style complying with Webkit's style guide:
/// http://www.webkit.org/coding/coding-style.html
FormatStyle getWebKitStyle();
-/// \brief Returns a format style complying with GNU Coding Standards:
+/// Returns a format style complying with GNU Coding Standards:
/// http://www.gnu.org/prep/standards/standards.html
FormatStyle getGNUStyle();
-/// \brief Returns style indicating formatting should be not applied at all.
+/// Returns style indicating formatting should be not applied at all.
FormatStyle getNoStyle();
-/// \brief Gets a predefined style for the specified language by name.
+/// Gets a predefined style for the specified language by name.
///
/// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are
/// compared case-insensitively.
@@ -1725,66 +1845,64 @@ FormatStyle getNoStyle();
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
FormatStyle *Style);
-/// \brief Parse configuration from YAML-formatted text.
+/// Parse configuration from YAML-formatted text.
///
/// Style->Language is used to get the base style, if the ``BasedOnStyle``
/// option is present.
///
+/// The FormatStyleSet of Style is reset.
+///
/// When ``BasedOnStyle`` is not present, options not present in the YAML
/// document, are retained in \p Style.
std::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
-/// \brief Gets configuration in a YAML string.
+/// Gets configuration in a YAML string.
std::string configurationAsText(const FormatStyle &Style);
-/// \brief Returns the replacements necessary to sort all ``#include`` blocks
+/// Returns the replacements necessary to sort all ``#include`` blocks
/// that are affected by ``Ranges``.
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName,
unsigned *Cursor = nullptr);
-/// \brief Returns the replacements corresponding to applying and formatting
+/// Returns the replacements corresponding to applying and formatting
/// \p Replaces on success; otheriwse, return an llvm::Error carrying
/// llvm::StringError.
llvm::Expected<tooling::Replacements>
formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
const FormatStyle &Style);
-/// \brief Returns the replacements corresponding to applying \p Replaces and
+/// Returns the replacements corresponding to applying \p Replaces and
/// cleaning up the code after that on success; otherwise, return an llvm::Error
/// carrying llvm::StringError.
/// This also supports inserting/deleting C++ #include directives:
/// - If a replacement has offset UINT_MAX, length 0, and a replacement text
/// that is an #include directive, this will insert the #include into the
-/// correct block in the \p Code. When searching for points to insert new
-/// header, this ignores #include's after the #include block(s) in the
-/// beginning of a file to avoid inserting headers into code sections where
-/// new #include's should not be added by default. These code sections
-/// include:
-/// - raw string literals (containing #include).
-/// - #if blocks.
-/// - Special #include's among declarations (e.g. functions).
+/// correct block in the \p Code.
/// - If a replacement has offset UINT_MAX, length 1, and a replacement text
/// that is the name of the header to be removed, the header will be removed
/// from \p Code if it exists.
+/// The include manipulation is done via `tooling::HeaderInclude`, see its
+/// documentation for more details on how include insertion points are found and
+/// what edits are produced.
llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
const FormatStyle &Style);
-/// \brief Represents the status of a formatting attempt.
+/// Represents the status of a formatting attempt.
struct FormattingAttemptStatus {
- /// \brief A value of ``false`` means that any of the affected ranges were not
+ /// A value of ``false`` means that any of the affected ranges were not
/// formatted due to a non-recoverable syntax error.
bool FormatComplete = true;
- /// \brief If ``FormatComplete`` is false, ``Line`` records a one-based
+ /// If ``FormatComplete`` is false, ``Line`` records a one-based
/// original line number at which a syntax error might have occurred. This is
/// based on a best-effort analysis and could be imprecise.
unsigned Line = 0;
};
-/// \brief Reformats the given \p Ranges in \p Code.
+/// Reformats the given \p Ranges in \p Code.
///
/// 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
@@ -1800,7 +1918,7 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
StringRef FileName = "<stdin>",
FormattingAttemptStatus *Status = nullptr);
-/// \brief Same as above, except if ``IncompleteFormat`` is non-null, its value
+/// Same as above, except if ``IncompleteFormat`` is non-null, its value
/// will be set to true if any of the affected ranges were not formatted due to
/// a non-recoverable syntax error.
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
@@ -1808,7 +1926,7 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
StringRef FileName,
bool *IncompleteFormat);
-/// \brief Clean up any erroneous/redundant code in the given \p Ranges in \p
+/// Clean up any erroneous/redundant code in the given \p Ranges in \p
/// Code.
///
/// Returns the ``Replacements`` that clean up all \p Ranges in \p Code.
@@ -1816,7 +1934,7 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>");
-/// \brief Fix namespace end comments in the given \p Ranges in \p Code.
+/// Fix namespace end comments in the given \p Ranges in \p Code.
///
/// Returns the ``Replacements`` that fix the namespace comments in all
/// \p Ranges in \p Code.
@@ -1825,7 +1943,7 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>");
-/// \brief Sort consecutive using declarations in the given \p Ranges in
+/// Sort consecutive using declarations in the given \p Ranges in
/// \p Code.
///
/// Returns the ``Replacements`` that sort the using declarations in all
@@ -1835,17 +1953,26 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>");
-/// \brief Returns the ``LangOpts`` that the formatter expects you to set.
+/// Returns the ``LangOpts`` that the formatter expects you to set.
///
/// \param Style determines specific settings for lexing mode.
LangOptions getFormattingLangOpts(const FormatStyle &Style = getLLVMStyle());
-/// \brief Description to be used for help text for a ``llvm::cl`` option for
+/// Description to be used for help text for a ``llvm::cl`` option for
/// specifying format style. The description is closely related to the operation
/// of ``getStyle()``.
extern const char *StyleOptionHelpDescription;
-/// \brief Construct a FormatStyle based on ``StyleName``.
+/// The suggested format style to use by default. This allows tools using
+/// `getStyle` to have a consistent default style.
+/// Different builds can modify the value to the preferred styles.
+extern const char *DefaultFormatStyle;
+
+/// The suggested predefined style to use as the fallback style in `getStyle`.
+/// Different builds can modify the value to the preferred styles.
+extern const char *DefaultFallbackStyle;
+
+/// Construct a FormatStyle based on ``StyleName``.
///
/// ``StyleName`` can take several forms:
/// * "{<key>: <value>, ...}" - Set specic style parameters.
@@ -1874,7 +2001,11 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
StringRef Code = "",
vfs::FileSystem *FS = nullptr);
-// \brief Returns a string representation of ``Language``.
+// Guesses the language from the ``FileName`` and ``Code`` to be formatted.
+// Defaults to FormatStyle::LK_Cpp.
+FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code);
+
+// Returns a string representation of ``Language``.
inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
switch (Language) {
case FormatStyle::LK_Cpp:
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h
index 53975a07ea94..2a13527df135 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h
@@ -34,9 +34,10 @@ class TargetOptions;
std::unique_ptr<ASTConsumer> CreateASTPrinter(std::unique_ptr<raw_ostream> OS,
StringRef FilterString);
-// AST dumper: dumps the raw AST in human-readable form to stderr; this is
-// intended for debugging.
-std::unique_ptr<ASTConsumer> CreateASTDumper(StringRef FilterString,
+// AST dumper: dumps the raw AST in human-readable form to the given output
+// stream, or stdout if OS is nullptr.
+std::unique_ptr<ASTConsumer> CreateASTDumper(std::unique_ptr<raw_ostream> OS,
+ StringRef FilterString,
bool DumpDecls, bool Deserialize,
bool DumpLookups);
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
index 5d04dcd19119..ba145965462f 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
@@ -1,4 +1,4 @@
-//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===//
+//===- ASTUnit.h - ASTUnit utility ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,8 +16,11 @@
#include "clang-c/Index.h"
#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
@@ -26,48 +29,62 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Frontend/PrecompiledPreamble.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.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/StringMap.h"
-#include "llvm/Support/MD5.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <string>
-#include <sys/types.h>
#include <utility>
#include <vector>
namespace llvm {
- class MemoryBuffer;
-}
+
+class MemoryBuffer;
+
+} // namespace llvm
namespace clang {
-class Sema;
+
class ASTContext;
+class ASTDeserializationListener;
+class ASTMutationListener;
class ASTReader;
-class CompilerInvocation;
class CompilerInstance;
+class CompilerInvocation;
class Decl;
-class DiagnosticsEngine;
class FileEntry;
class FileManager;
+class FrontendAction;
class HeaderSearch;
class InputKind;
class MemoryBufferCache;
-class Preprocessor;
-class PreprocessorOptions;
class PCHContainerOperations;
class PCHContainerReader;
+class Preprocessor;
+class PreprocessorOptions;
+class Sema;
class TargetInfo;
-class FrontendAction;
-class ASTDeserializationListener;
namespace vfs {
+
class FileSystem;
-}
-/// \brief Utility class for loading a ASTContext from an AST file.
-///
+} // namespace vfs
+
+/// \brief Enumerates the available scopes for skipping function bodies.
+enum class SkipFunctionBodiesScope { None, Preamble, PreambleAndMainFile };
+
+/// Utility class for loading a ASTContext from an AST file.
class ASTUnit {
public:
struct StandaloneFixIt {
@@ -83,7 +100,7 @@ public:
std::string Message;
std::string Filename;
unsigned LocOffset;
- std::vector<std::pair<unsigned, unsigned> > Ranges;
+ std::vector<std::pair<unsigned, unsigned>> Ranges;
std::vector<StandaloneFixIt> FixIts;
};
@@ -101,18 +118,18 @@ private:
std::shared_ptr<HeaderSearchOptions> HSOpts;
std::shared_ptr<PreprocessorOptions> PPOpts;
IntrusiveRefCntPtr<ASTReader> Reader;
- bool HadModuleLoaderFatalFailure;
+ bool HadModuleLoaderFatalFailure = false;
struct ASTWriterData;
std::unique_ptr<ASTWriterData> WriterData;
FileSystemOptions FileSystemOpts;
- /// \brief The AST consumer that received information about the translation
+ /// The AST consumer that received information about the translation
/// unit as it was parsed or loaded.
std::unique_ptr<ASTConsumer> Consumer;
- /// \brief The semantic analysis object used to type-check the translation
+ /// The semantic analysis object used to type-check the translation
/// unit.
std::unique_ptr<Sema> TheSema;
@@ -126,23 +143,23 @@ private:
// OnlyLocalDecls - when true, walking this AST should only visit declarations
// that come from the AST itself, not from included precompiled headers.
// FIXME: This is temporary; eventually, CIndex will always do this.
- bool OnlyLocalDecls;
+ bool OnlyLocalDecls = false;
- /// \brief Whether to capture any diagnostics produced.
- bool CaptureDiagnostics;
+ /// Whether to capture any diagnostics produced.
+ bool CaptureDiagnostics = false;
- /// \brief Track whether the main file was loaded from an AST or not.
+ /// Track whether the main file was loaded from an AST or not.
bool MainFileIsAST;
- /// \brief What kind of translation unit this AST represents.
- TranslationUnitKind TUKind;
+ /// What kind of translation unit this AST represents.
+ TranslationUnitKind TUKind = TU_Complete;
- /// \brief Whether we should time each operation.
+ /// Whether we should time each operation.
bool WantTiming;
- /// \brief Whether the ASTUnit should delete the remapped buffers.
- bool OwnsRemappedFileBuffers;
-
+ /// Whether the ASTUnit should delete the remapped buffers.
+ bool OwnsRemappedFileBuffers = true;
+
/// Track the top-level decls which appeared in an ASTUnit which was loaded
/// from a source file.
//
@@ -152,36 +169,36 @@ private:
// more scalable search mechanisms.
std::vector<Decl*> TopLevelDecls;
- /// \brief Sorted (by file offset) vector of pairs of file offset/Decl.
- typedef SmallVector<std::pair<unsigned, Decl *>, 64> LocDeclsTy;
- typedef llvm::DenseMap<FileID, LocDeclsTy *> FileDeclsTy;
+ /// Sorted (by file offset) vector of pairs of file offset/Decl.
+ using LocDeclsTy = SmallVector<std::pair<unsigned, Decl *>, 64>;
+ using FileDeclsTy = llvm::DenseMap<FileID, LocDeclsTy *>;
- /// \brief Map from FileID to the file-level declarations that it contains.
+ /// Map from FileID to the file-level declarations that it contains.
/// The files and decls are only local (and non-preamble) ones.
FileDeclsTy FileDecls;
-
+
/// The name of the original source file used to generate this ASTUnit.
std::string OriginalSourceFile;
- /// \brief The set of diagnostics produced when creating the preamble.
+ /// The set of diagnostics produced when creating the preamble.
SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics;
- /// \brief The set of diagnostics produced when creating this
+ /// The set of diagnostics produced when creating this
/// translation unit.
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
- /// \brief The set of diagnostics produced when failing to parse, e.g. due
+ /// The set of diagnostics produced when failing to parse, e.g. due
/// to failure to load the PCH.
SmallVector<StoredDiagnostic, 4> FailedParseDiagnostics;
- /// \brief The number of stored diagnostics that come from the driver
+ /// The number of stored diagnostics that come from the driver
/// itself.
///
/// Diagnostics that come from the driver are retained from one parse to
/// the next.
- unsigned NumStoredDiagnosticsFromDriver;
-
- /// \brief Counter that determines when we want to try building a
+ unsigned NumStoredDiagnosticsFromDriver = 0;
+
+ /// Counter that determines when we want to try building a
/// precompiled preamble.
///
/// If zero, we will never build a precompiled preamble. Otherwise,
@@ -190,48 +207,47 @@ private:
/// we'll attempt to rebuild the precompiled header. This way, if
/// building the precompiled preamble fails, we won't try again for
/// some number of calls.
- unsigned PreambleRebuildCounter;
+ unsigned PreambleRebuildCounter = 0;
- /// \brief Cache pairs "filename - source location"
+ /// Cache pairs "filename - source location"
///
/// Cache contains only source locations from preamble so it is
/// guaranteed that they stay valid when the SourceManager is recreated.
- /// This cache is used when loading preambule to increase performance
+ /// This cache is used when loading preamble to increase performance
/// of that loading. It must be cleared when preamble is recreated.
llvm::StringMap<SourceLocation> PreambleSrcLocCache;
-private:
/// The contents of the preamble.
llvm::Optional<PrecompiledPreamble> Preamble;
- /// \brief When non-NULL, this is the buffer used to store the contents of
+ /// When non-NULL, this is the buffer used to store the contents of
/// the main file when it has been padded for use with the precompiled
/// preamble.
std::unique_ptr<llvm::MemoryBuffer> SavedMainFileBuffer;
- /// \brief The number of warnings that occurred while parsing the preamble.
+ /// The number of warnings that occurred while parsing the preamble.
///
/// This value will be used to restore the state of the \c DiagnosticsEngine
/// object when re-using the precompiled preamble. Note that only the
/// number of warnings matters, since we will not save the preamble
/// when any errors are present.
- unsigned NumWarningsInPreamble;
+ unsigned NumWarningsInPreamble = 0;
- /// \brief A list of the serialization ID numbers for each of the top-level
+ /// A list of the serialization ID numbers for each of the top-level
/// declarations parsed within the precompiled preamble.
std::vector<serialization::DeclID> TopLevelDeclsInPreamble;
-
- /// \brief Whether we should be caching code-completion results.
+
+ /// Whether we should be caching code-completion results.
bool ShouldCacheCodeCompletionResults : 1;
- /// \brief Whether to include brief documentation within the set of code
+ /// Whether to include brief documentation within the set of code
/// completions cached.
bool IncludeBriefCommentsInCodeCompletion : 1;
- /// \brief True if non-system source files should be treated as volatile
+ /// True if non-system source files should be treated as volatile
/// (likely to change while trying to use them).
bool UserFilesAreVolatile : 1;
-
+
static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
ASTUnit &AST, bool CaptureDiagnostics);
@@ -243,14 +259,14 @@ private:
void clearFileLevelDecls();
public:
- /// \brief A cached code-completion result, which may be introduced in one of
+ /// A cached code-completion result, which may be introduced in one of
/// many different contexts.
struct CachedCodeCompletionResult {
- /// \brief The code-completion string corresponding to this completion
+ /// The code-completion string corresponding to this completion
/// result.
CodeCompletionString *Completion;
-
- /// \brief A bitmask that indicates which code-completion contexts should
+
+ /// A bitmask that indicates which code-completion contexts should
/// contain this completion result.
///
/// The bits in the bitmask correspond to the values of
@@ -258,21 +274,21 @@ public:
/// bit, shift 1 by that number of bits. Many completions can occur in
/// several different contexts.
uint64_t ShowInContexts;
-
- /// \brief The priority given to this code-completion result.
+
+ /// The priority given to this code-completion result.
unsigned Priority;
-
- /// \brief The libclang cursor kind corresponding to this code-completion
+
+ /// The libclang cursor kind corresponding to this code-completion
/// result.
CXCursorKind Kind;
-
- /// \brief The availability of this code-completion result.
+
+ /// The availability of this code-completion result.
CXAvailabilityKind Availability;
-
- /// \brief The simplified type class for a non-macro completion result.
+
+ /// The simplified type class for a non-macro completion result.
SimplifiedTypeClass TypeClass;
-
- /// \brief The type of a non-macro completion result, stored as a unique
+
+ /// The type of a non-macro completion result, stored as a unique
/// integer used by the string map of cached completion types.
///
/// This value will be zero if the type is not known, or a unique value
@@ -280,14 +296,14 @@ public:
/// for more information.
unsigned Type;
};
-
- /// \brief Retrieve the mapping from formatted type names to unique type
+
+ /// Retrieve the mapping from formatted type names to unique type
/// identifiers.
- llvm::StringMap<unsigned> &getCachedCompletionTypes() {
- return CachedCompletionTypes;
+ llvm::StringMap<unsigned> &getCachedCompletionTypes() {
+ return CachedCompletionTypes;
}
-
- /// \brief Retrieve the allocator used to cache global code completions.
+
+ /// Retrieve the allocator used to cache global code completions.
std::shared_ptr<GlobalCodeCompletionAllocator>
getCachedCompletionAllocator() {
return CachedCompletionAllocator;
@@ -301,50 +317,50 @@ public:
}
private:
- /// \brief Allocator used to store cached code completions.
+ /// Allocator used to store cached code completions.
std::shared_ptr<GlobalCodeCompletionAllocator> CachedCompletionAllocator;
std::unique_ptr<CodeCompletionTUInfo> CCTUInfo;
- /// \brief The set of cached code-completion results.
+ /// The set of cached code-completion results.
std::vector<CachedCodeCompletionResult> CachedCompletionResults;
-
- /// \brief A mapping from the formatted type name to a unique number for that
+
+ /// A mapping from the formatted type name to a unique number for that
/// type, which is used for type equality comparisons.
llvm::StringMap<unsigned> CachedCompletionTypes;
-
- /// \brief A string hash of the top-level declaration and macro definition
+
+ /// A string hash of the top-level declaration and macro definition
/// names processed the last time that we reparsed the file.
///
- /// This hash value is used to determine when we need to refresh the
+ /// This hash value is used to determine when we need to refresh the
/// global code-completion cache.
- unsigned CompletionCacheTopLevelHashValue;
+ unsigned CompletionCacheTopLevelHashValue = 0;
- /// \brief A string hash of the top-level declaration and macro definition
+ /// A string hash of the top-level declaration and macro definition
/// names processed the last time that we reparsed the precompiled preamble.
///
- /// This hash value is used to determine when we need to refresh the
+ /// This hash value is used to determine when we need to refresh the
/// global code-completion cache after a rebuild of the precompiled preamble.
- unsigned PreambleTopLevelHashValue;
+ unsigned PreambleTopLevelHashValue = 0;
- /// \brief The current hash value for the top-level declaration and macro
+ /// The current hash value for the top-level declaration and macro
/// definition names
- unsigned CurrentTopLevelHashValue;
-
- /// \brief Bit used by CIndex to mark when a translation unit may be in an
+ unsigned CurrentTopLevelHashValue = 0;
+
+ /// Bit used by CIndex to mark when a translation unit may be in an
/// inconsistent state, and is not safe to free.
unsigned UnsafeToFree : 1;
- /// \brief Cache any "global" code-completion results, so that we can avoid
+ /// \brief Enumerator specifying the scope for skipping function bodies.
+ SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
+
+ /// Cache any "global" code-completion results, so that we can avoid
/// recomputing them with each completion.
void CacheCodeCompletionResults();
-
- /// \brief Clear out and deallocate
+
+ /// Clear out and deallocate
void ClearCachedCompletionResults();
-
- ASTUnit(const ASTUnit &) = delete;
- void operator=(const ASTUnit &) = delete;
-
+
explicit ASTUnit(bool MainFileIsAST);
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
@@ -353,16 +369,16 @@ private:
std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- const CompilerInvocation &PreambleInvocationIn,
+ CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
- /// \brief Transfers ownership of the objects (like SourceManager) from
+ /// Transfers ownership of the objects (like SourceManager) from
/// \param CI to this ASTUnit.
void transferASTDataFromCompilerInstance(CompilerInstance &CI);
- /// \brief Allows us to assert that ASTUnit is not being used concurrently,
+ /// Allows us to assert that ASTUnit is not being used concurrently,
/// which is not supported.
///
/// Clients should create instances of the ConcurrencyCheck class whenever
@@ -382,21 +398,23 @@ private:
ConcurrencyState ConcurrencyCheckValue;
public:
+ friend class ConcurrencyCheck;
+
class ConcurrencyCheck {
ASTUnit &Self;
-
+
public:
- explicit ConcurrencyCheck(ASTUnit &Self)
- : Self(Self)
- {
+ explicit ConcurrencyCheck(ASTUnit &Self) : Self(Self) {
Self.ConcurrencyCheckValue.start();
}
+
~ConcurrencyCheck() {
Self.ConcurrencyCheckValue.finish();
}
};
- friend class ConcurrencyCheck;
+ ASTUnit(const ASTUnit &) = delete;
+ ASTUnit &operator=(const ASTUnit &) = delete;
~ASTUnit();
bool isMainFileAST() const { return MainFileIsAST; }
@@ -405,23 +423,33 @@ public:
void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; }
- DiagnosticsEngine &getDiagnostics() { return *Diagnostics; }
-
+ DiagnosticsEngine &getDiagnostics() { return *Diagnostics; }
+
const SourceManager &getSourceManager() const { return *SourceMgr; }
- SourceManager &getSourceManager() { return *SourceMgr; }
+ SourceManager &getSourceManager() { return *SourceMgr; }
const Preprocessor &getPreprocessor() const { return *PP; }
- Preprocessor &getPreprocessor() { return *PP; }
+ Preprocessor &getPreprocessor() { return *PP; }
std::shared_ptr<Preprocessor> getPreprocessorPtr() const { return PP; }
const ASTContext &getASTContext() const { return *Ctx; }
- ASTContext &getASTContext() { return *Ctx; }
+ ASTContext &getASTContext() { return *Ctx; }
void setASTContext(ASTContext *ctx) { Ctx = ctx; }
void setPreprocessor(std::shared_ptr<Preprocessor> pp);
+ /// Enable source-range based diagnostic messages.
+ ///
+ /// If diagnostic messages with source-range information are to be expected
+ /// and AST comes not from file (e.g. after LoadFromCompilerInvocation) this
+ /// function has to be called.
+ /// The function is to be called only once and the AST should be associated
+ /// with the same source file afterwards.
+ void enableSourceFileDiagnostics();
+
bool hasSema() const { return (bool)TheSema; }
- Sema &getSema() const {
+
+ Sema &getSema() const {
assert(TheSema && "ASTUnit does not have a Sema object!");
return *TheSema;
}
@@ -435,14 +463,14 @@ public:
assert(HSOpts && "ASTUnit does not have header search options");
return *HSOpts;
}
-
+
const PreprocessorOptions &getPreprocessorOpts() const {
assert(PPOpts && "ASTUnit does not have preprocessor options");
return *PPOpts;
}
-
+
const FileManager &getFileManager() const { return *FileMgr; }
- FileManager &getFileManager() { return *FileMgr; }
+ FileManager &getFileManager() { return *FileMgr; }
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
@@ -462,10 +490,10 @@ public:
StringRef getMainFileName() const;
- /// \brief If this ASTUnit came from an AST file, returns the filename for it.
+ /// If this ASTUnit came from an AST file, returns the filename for it.
StringRef getASTFileName() const;
- typedef std::vector<Decl *>::iterator top_level_iterator;
+ using top_level_iterator = std::vector<Decl *>::iterator;
top_level_iterator top_level_begin() {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
@@ -491,26 +519,26 @@ public:
return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty();
}
- /// \brief Add a new top-level declaration.
+ /// Add a new top-level declaration.
void addTopLevelDecl(Decl *D) {
TopLevelDecls.push_back(D);
}
- /// \brief Add a new local file-level declaration.
+ /// Add a new local file-level declaration.
void addFileLevelDecl(Decl *D);
- /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
- /// a range.
+ /// a range.
void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
SmallVectorImpl<Decl *> &Decls);
- /// \brief Retrieve a reference to the current top-level name hash value.
+ /// Retrieve a reference to the current top-level name hash value.
///
/// Note: This is used internally by the top-level tracking action
unsigned &getCurrentTopLevelHashValue() { return CurrentTopLevelHashValue; }
- /// \brief Get the source location for the given file:line:col triplet.
+ /// Get the source location for the given file:line:col triplet.
///
/// The difference with SourceManager::getLocation is that this method checks
/// whether the requested location points inside the precompiled preamble
@@ -518,15 +546,15 @@ public:
SourceLocation getLocation(const FileEntry *File,
unsigned Line, unsigned Col) const;
- /// \brief Get the source location for the given file:offset pair.
+ /// Get the source location for the given file:offset pair.
SourceLocation getLocation(const FileEntry *File, unsigned Offset) const;
- /// \brief If \p Loc is a loaded location from the preamble, returns
+ /// 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) const;
- /// \brief If \p Loc is a local location of the main file but inside the
+ /// 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) const;
@@ -547,33 +575,38 @@ public:
return SourceRange(mapLocationToPreamble(R.getBegin()),
mapLocationToPreamble(R.getEnd()));
}
-
+
// Retrieve the diagnostics associated with this AST
- typedef StoredDiagnostic *stored_diag_iterator;
- typedef const StoredDiagnostic *stored_diag_const_iterator;
- stored_diag_const_iterator stored_diag_begin() const {
- return StoredDiagnostics.begin();
+ using stored_diag_iterator = StoredDiagnostic *;
+ using stored_diag_const_iterator = const StoredDiagnostic *;
+
+ stored_diag_const_iterator stored_diag_begin() const {
+ return StoredDiagnostics.begin();
}
- stored_diag_iterator stored_diag_begin() {
- return StoredDiagnostics.begin();
+
+ stored_diag_iterator stored_diag_begin() {
+ return StoredDiagnostics.begin();
}
- stored_diag_const_iterator stored_diag_end() const {
- return StoredDiagnostics.end();
+
+ stored_diag_const_iterator stored_diag_end() const {
+ return StoredDiagnostics.end();
}
- stored_diag_iterator stored_diag_end() {
- return StoredDiagnostics.end();
+
+ stored_diag_iterator stored_diag_end() {
+ return StoredDiagnostics.end();
}
+
unsigned stored_diag_size() const { return StoredDiagnostics.size(); }
stored_diag_iterator stored_diag_afterDriver_begin() {
if (NumStoredDiagnosticsFromDriver > StoredDiagnostics.size())
NumStoredDiagnosticsFromDriver = 0;
- return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver;
+ return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver;
}
- typedef std::vector<CachedCodeCompletionResult>::iterator
- cached_completion_iterator;
-
+ using cached_completion_iterator =
+ std::vector<CachedCodeCompletionResult>::iterator;
+
cached_completion_iterator cached_completion_begin() {
return CachedCompletionResults.begin();
}
@@ -582,47 +615,47 @@ public:
return CachedCompletionResults.end();
}
- unsigned cached_completion_size() const {
- return CachedCompletionResults.size();
+ unsigned cached_completion_size() const {
+ return CachedCompletionResults.size();
}
- /// \brief Returns an iterator range for the local preprocessing entities
+ /// Returns an iterator range for the local preprocessing entities
/// of the local Preprocessor, if this is a parsed source file, or the loaded
/// preprocessing entities of the primary module if this is an AST file.
llvm::iterator_range<PreprocessingRecord::iterator>
getLocalPreprocessingEntities() const;
- /// \brief Type for a function iterating over a number of declarations.
+ /// Type for a function iterating over a number of declarations.
/// \returns true to continue iteration and false to abort.
- typedef bool (*DeclVisitorFn)(void *context, const Decl *D);
+ using DeclVisitorFn = bool (*)(void *context, const Decl *D);
- /// \brief Iterate over local declarations (locally parsed if this is a parsed
+ /// Iterate over local declarations (locally parsed if this is a parsed
/// source file or the loaded declarations of the primary module if this is an
/// AST file).
/// \returns true if the iteration was complete or false if it was aborted.
bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn);
- /// \brief Get the PCH file if one was included.
+ /// Get the PCH file if one was included.
const FileEntry *getPCHFile();
- /// \brief Returns true if the ASTUnit was constructed from a serialized
+ /// Returns true if the ASTUnit was constructed from a serialized
/// module file.
bool isModuleFile() const;
std::unique_ptr<llvm::MemoryBuffer>
getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr);
- /// \brief Determine what kind of translation unit this AST represents.
+ /// Determine what kind of translation unit this AST represents.
TranslationUnitKind getTranslationUnitKind() const { return TUKind; }
- /// \brief Determine the input kind this AST unit represents.
+ /// Determine the input kind this AST unit represents.
InputKind getInputKind() const;
- /// \brief A mapping from a file name to the memory buffer that stores the
+ /// A mapping from a file name to the memory buffer that stores the
/// remapped contents of that file.
- typedef std::pair<std::string, llvm::MemoryBuffer *> RemappedFile;
+ using RemappedFile = std::pair<std::string, llvm::MemoryBuffer *>;
- /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation.
+ /// Create a ASTUnit. Gets ownership of the passed CompilerInvocation.
static std::unique_ptr<ASTUnit>
create(std::shared_ptr<CompilerInvocation> CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool CaptureDiagnostics,
@@ -631,13 +664,15 @@ public:
enum WhatToLoad {
/// Load options and the preprocessor state.
LoadPreprocessorOnly,
+
/// Load the AST, but do not restore Sema state.
LoadASTOnly,
+
/// Load everything, including Sema.
LoadEverything
};
- /// \brief Create a ASTUnit from an AST file.
+ /// Create a ASTUnit from an AST file.
///
/// \param Filename - The AST file to load.
///
@@ -656,7 +691,7 @@ public:
bool UserFilesAreVolatile = false);
private:
- /// \brief Helper function for \c LoadFromCompilerInvocation() and
+ /// Helper function for \c LoadFromCompilerInvocation() and
/// \c LoadFromCommandLine(), which loads an AST from a compiler invocation.
///
/// \param PrecompilePreambleAfterNParses After how many parses the preamble
@@ -676,9 +711,8 @@ private:
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
public:
-
- /// \brief Create an ASTUnit from a source file, via a CompilerInvocation
- /// object, by invoking the optionally provided ASTFrontendAction.
+ /// Create an ASTUnit from a source file, via a CompilerInvocation
+ /// object, by invoking the optionally provided ASTFrontendAction.
///
/// \param CI - The compiler invocation to use; it must have exactly one input
/// source file. The ASTUnit takes ownership of the CompilerInvocation object.
@@ -782,14 +816,16 @@ public:
TranslationUnitKind TUKind = TU_Complete,
bool CacheCodeCompletionResults = false,
bool IncludeBriefCommentsInCodeCompletion = false,
- bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
- bool SingleFileParse = false,
- bool UserFilesAreVolatile = false, bool ForSerialization = false,
+ bool AllowPCHWithCompilerErrors = false,
+ SkipFunctionBodiesScope SkipFunctionBodies =
+ SkipFunctionBodiesScope::None,
+ bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+ bool ForSerialization = false,
llvm::Optional<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
- /// \brief Reparse the source files using the same command-line options that
+ /// Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
///
/// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
@@ -804,12 +840,12 @@ public:
ArrayRef<RemappedFile> RemappedFiles = None,
IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
- /// \brief Free data that will be re-generated on the next parse.
+ /// Free data that will be re-generated on the next parse.
///
/// Preamble-related data is not affected.
void ResetForParse();
- /// \brief Perform code completion at the given file, line, and
+ /// Perform code completion at the given file, line, and
/// column within this translation unit.
///
/// \param File The file in which code completion will occur.
@@ -818,10 +854,10 @@ public:
///
/// \param Column The column at which code completion will occur.
///
- /// \param IncludeMacros Whether to include macros in the code-completion
+ /// \param IncludeMacros Whether to include macros in the code-completion
/// results.
///
- /// \param IncludeCodePatterns Whether to include code patterns (such as a
+ /// \param IncludeCodePatterns Whether to include code patterns (such as a
/// for loop) in the code-completion results.
///
/// \param IncludeBriefComments Whether to include brief documentation within
@@ -839,13 +875,13 @@ public:
SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
- /// \brief Save this translation unit to a file with the given name.
+ /// Save this translation unit to a file with the given name.
///
/// \returns true if there was a file error or false if the save was
/// successful.
bool Save(StringRef File);
- /// \brief Serialize this translation unit with the given output stream.
+ /// Serialize this translation unit with the given output stream.
///
/// \returns True if an error occurred, false otherwise.
bool serialize(raw_ostream &OS);
@@ -853,4 +889,4 @@ public:
} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h
index eb33273c2fb3..04c6077dc35e 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h
@@ -32,7 +32,7 @@ public:
: OwningPrimary(std::move(Primary)), Primary(OwningPrimary.get()),
Secondary(std::move(Secondary)) {}
- /// \brief Construct without taking ownership of \c Primary.
+ /// Construct without taking ownership of \c Primary.
ChainedDiagnosticConsumer(DiagnosticConsumer *Primary,
std::unique_ptr<DiagnosticConsumer> Secondary)
: Primary(Primary), Secondary(std::move(Secondary)) {}
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
index bb91cf5f742b..a7e71f7ac016 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
@@ -38,10 +38,12 @@ CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) o
CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
CODEGENOPT(Backchain , 1, 0) ///< -mbackchain
+CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard
CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files.
CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files.
CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files.
CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors.
+CODEGENOPT(RegisterGlobalDtorsWithAtExit, 1, 1) ///< Use atexit or __cxa_atexit to register global destructors.
CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
///< aliases to base ctors when possible.
CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled.
@@ -61,15 +63,19 @@ CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
+CODEGENOPT(NoEscapingBlockTailCalls, 1, 0) ///< Do not emit tail calls from
+ ///< escaping blocks.
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
///< Decl* various IR entities came from.
///< Only useful when running CodeGen as a
///< subroutine.
+CODEGENOPT(EmitVersionIdentMetadata , 1, 1) ///< Emit compiler version metadata.
CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA.
CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO.
CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata.
-CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled.
-/// \brief Embed Bitcode mode (off/all/bitcode/marker).
+CODEGENOPT(EmulatedTLS , 1, 0) ///< Set by default or -f[no-]emulated-tls.
+CODEGENOPT(ExplicitEmulatedTLS , 1, 0) ///< Set if -f[no-]emulated-tls is used.
+/// Embed Bitcode mode (off/all/bitcode/marker).
ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off)
CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables
///< are required.
@@ -80,13 +86,20 @@ 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(CFProtectionReturn , 1, 0) ///< if -fcf-protection is
+ ///< set to full or return.
+CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
+ ///< set to full or branch.
CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
///< enabled.
+CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled.
///< Set when -fxray-always-emit-customevents is enabled.
CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)
+///< Set when -fxray-always-emit-typedevents is enabled.
+CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0)
+
///< Set the minimum number of instructions in a function to determine selective
///< XRay instrumentation.
VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
@@ -97,7 +110,7 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t
///< be generated.
CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
///< compile step.
-CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the
+CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the
///< compile step.
CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole
///< program vtable opt).
@@ -117,27 +130,32 @@ 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(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
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.
CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero
CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
+
+/// When false, this attempts to generate code as if the result of an
+/// overflowing conversion matches the overflowing behavior of a target's native
+/// float-to-int conversion instructions.
+CODEGENOPT(StrictFloatCastOverflow, 1, 1)
+
+CODEGENOPT(UniformWGSize , 1, 0) ///< -cl-uniform-work-group-size
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
-/// \brief Method of Objective-C dispatch to use.
+/// Method of Objective-C dispatch to use.
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
///< enabled.
-/// A version of Clang that we should attempt to be ABI-compatible with.
-ENUM_CODEGENOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest)
-
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
-/// \brief Choose profile instrumenation kind or no instrumentation.
+/// Choose profile instrumenation kind or no instrumentation.
ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone)
-/// \brief Choose profile kind for PGO use compilation.
+/// Choose profile kind for PGO use compilation.
ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone)
CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
///< enable code coverage analysis.
@@ -154,6 +172,9 @@ CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-
CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection
///< in AddressSanitizer
+CODEGENOPT(SanitizeAddressPoisonClassMemberArrayNewCookie, 1,
+ 0) ///< Enable poisoning operator new[] which is not a replaceable
+ ///< global allocation function in AddressSanitizer
CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping
///< of globals in AddressSanitizer
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
@@ -218,6 +239,7 @@ VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack
///< alignment, if not 0.
VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack
///< probe size, even if 0.
+CODEGENOPT(NoStackArgProbe, 1, 0) ///< Set when -mno-stack-arg-probe is used
CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information
///< in debug info.
@@ -230,7 +252,7 @@ CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
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.
+ ///< of inline stack frames without .dwo files.
CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete
///< template parameter descriptions in
///< forward declarations (versus just
@@ -308,6 +330,16 @@ CODEGENOPT(GnuPubnames, 1, 0)
CODEGENOPT(NoPLT, 1, 0)
+/// Whether to embed source in DWARF debug line section.
+CODEGENOPT(EmbedSource, 1, 0)
+
+/// Whether to emit all vtables
+CODEGENOPT(ForceEmitVTables, 1, 0)
+
+/// Whether to emit an address-significance table into the object file.
+CODEGENOPT(Addrsig, 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 6b8d2b935fdd..a6d061acf0f4 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
@@ -16,6 +16,8 @@
#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/XRayInstr.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Regex.h"
#include "llvm/Target/TargetOptions.h"
#include <map>
@@ -25,7 +27,7 @@
namespace clang {
-/// \brief Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
+/// Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
/// that this large collection of bitfields is a trivial class type.
class CodeGenOptionsBase {
public:
@@ -167,7 +169,7 @@ public:
std::string SplitDwarfFile;
/// The name of the relocation model to use.
- std::string RelocationModel;
+ llvm::Reloc::Model RelocationModel;
/// The thread model to use
std::string ThreadModel;
@@ -176,9 +178,6 @@ public:
/// function instead of to trap instructions.
std::string TrapFuncName;
- /// A list of command-line options to forward to the LLVM backend.
- std::vector<std::string> BackendOptions;
-
/// A list of dependent libraries.
std::vector<std::string> DependentLibraries;
@@ -204,10 +203,12 @@ public:
/// the summary and module symbol table (and not, e.g. any debug metadata).
std::string ThinLinkBitcodeFile;
- /// A list of file names passed with -fcuda-include-gpubinary options to
- /// forward to CUDA runtime back-end for incorporating them into host-side
- /// object file.
- std::vector<std::string> CudaGpuBinaryFileNames;
+ /// Prefix to use for -save-temps output.
+ std::string SaveTempsFilePrefix;
+
+ /// Name of file passed with -fcuda-include-gpubinary option to forward to
+ /// CUDA runtime back-end for incorporating them into host-side object file.
+ std::string CudaGpuBinaryFileName;
/// The name of the file to which the backend should save YAML optimization
/// records.
@@ -248,7 +249,7 @@ public:
/// List of backend command-line options for -fembed-bitcode.
std::vector<uint8_t> CmdArgs;
- /// \brief A list of all -fno-builtin-* function names (e.g., memset).
+ /// A list of all -fno-builtin-* function names (e.g., memset).
std::vector<std::string> NoBuiltinFuncs;
std::vector<std::string> Reciprocals;
@@ -258,6 +259,9 @@ public:
/// registers.
std::string PreferVectorWidth;
+ /// Set of XRay instrumentation kinds to emit.
+ XRayInstrSet XRayInstrumentationBundle;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
@@ -268,7 +272,7 @@ public:
CodeGenOptions();
- /// \brief Is this a libc/libm function that is no longer recognized as a
+ /// Is this a libc/libm function that is no longer recognized as a
/// builtin because a -fno-builtin-* option has been specified?
bool isNoBuiltinFunc(const char *Name) const;
@@ -276,22 +280,22 @@ public:
return NoBuiltinFuncs;
}
- /// \brief Check if Clang profile instrumenation is on.
+ /// Check if Clang profile instrumenation is on.
bool hasProfileClangInstr() const {
return getProfileInstr() == ProfileClangInstr;
}
- /// \brief Check if IR level profile instrumentation is on.
+ /// Check if IR level profile instrumentation is on.
bool hasProfileIRInstr() const {
return getProfileInstr() == ProfileIRInstr;
}
- /// \brief Check if Clang profile use is on.
+ /// Check if Clang profile use is on.
bool hasProfileClangUse() const {
return getProfileUse() == ProfileClangInstr;
}
- /// \brief Check if IR level profile use is on.
+ /// Check if IR level profile use is on.
bool hasProfileIRUse() const {
return getProfileUse() == ProfileIRInstr;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
index f5c1e1a8a67d..7ae98e079264 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
@@ -21,7 +21,7 @@
namespace clang {
-/// \brief A source location that has been parsed on the command line.
+/// A source location that has been parsed on the command line.
struct ParsedSourceLocation {
std::string FileName;
unsigned Line;
@@ -101,7 +101,7 @@ struct ParsedSourceRange {
namespace llvm {
namespace cl {
- /// \brief Command-line option parser that parses source locations.
+ /// Command-line option parser that parses source locations.
///
/// Source locations are of the form filename:line:column.
template<>
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
index 90a9501475b5..818c733982d9 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
@@ -109,59 +109,59 @@ class CompilerInstance : public ModuleLoader {
/// The code completion consumer.
std::unique_ptr<CodeCompleteConsumer> CompletionConsumer;
- /// \brief The semantic analysis object.
+ /// The semantic analysis object.
std::unique_ptr<Sema> TheSema;
- /// \brief The frontend timer group.
+ /// The frontend timer group.
std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup;
- /// \brief The frontend timer.
+ /// The frontend timer.
std::unique_ptr<llvm::Timer> FrontendTimer;
- /// \brief The ASTReader, if one exists.
+ /// The ASTReader, if one exists.
IntrusiveRefCntPtr<ASTReader> ModuleManager;
- /// \brief The module dependency collector for crashdumps
+ /// The module dependency collector for crashdumps
std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector;
- /// \brief The module provider.
+ /// The module provider.
std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations;
- /// \brief The dependency file generator.
+ /// The dependency file generator.
std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator;
std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors;
- /// \brief The set of top-level modules that has already been loaded,
+ /// The set of top-level modules that has already been loaded,
/// along with the module map
llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules;
- /// \brief The set of top-level modules that has already been built on the
+ /// The set of top-level modules that has already been built on the
/// fly as part of this overall compilation action.
std::map<std::string, std::string> BuiltModules;
/// Should we delete the BuiltModules when we're done?
bool DeleteBuiltModules = true;
- /// \brief The location of the module-import keyword for the last module
- /// import.
+ /// The location of the module-import keyword for the last module
+ /// import.
SourceLocation LastModuleImportLoc;
-
- /// \brief The result of the last module import.
+
+ /// The result of the last module import.
///
ModuleLoadResult LastModuleImportResult;
- /// \brief Whether we should (re)build the global module index once we
+ /// Whether we should (re)build the global module index once we
/// have finished with this translation unit.
bool BuildGlobalModuleIndex = false;
- /// \brief We have a full global module index, with all modules.
+ /// We have a full global module index, with all modules.
bool HaveFullGlobalModuleIndex = false;
- /// \brief One or more modules failed to build.
+ /// One or more modules failed to build.
bool ModuleBuildFailed = false;
- /// \brief Holds information about the output file.
+ /// Holds information about the output file.
///
/// If TempFilename is not empty we must rename it to Filename at the end.
/// TempFilename may be empty and Filename non-empty if creating the temporary
@@ -183,6 +183,9 @@ class CompilerInstance : public ModuleLoader {
/// The list of active output files.
std::list<OutputFile> OutputFiles;
+ /// Force an output buffer.
+ std::unique_ptr<llvm::raw_pwrite_stream> OutputStream;
+
CompilerInstance(const CompilerInstance &) = delete;
void operator=(const CompilerInstance &) = delete;
public:
@@ -241,10 +244,10 @@ public:
/// setInvocation - Replace the current invocation.
void setInvocation(std::shared_ptr<CompilerInvocation> Value);
- /// \brief Indicates whether we should (re)build the global module index.
+ /// Indicates whether we should (re)build the global module index.
bool shouldBuildGlobalModuleIndex() const;
-
- /// \brief Set the flag indicating whether we should (re)build the global
+
+ /// Set the flag indicating whether we should (re)build the global
/// module index.
void setBuildGlobalModuleIndex(bool Build) {
BuildGlobalModuleIndex = Build;
@@ -347,7 +350,7 @@ public:
void setDiagnostics(DiagnosticsEngine *Value);
DiagnosticConsumer &getDiagnosticClient() const {
- assert(Diagnostics && Diagnostics->getClient() &&
+ assert(Diagnostics && Diagnostics->getClient() &&
"Compiler instance has no diagnostic client!");
return *Diagnostics->getClient();
}
@@ -387,7 +390,7 @@ public:
return *VirtualFileSystem;
}
- /// \brief Replace the current virtual file system.
+ /// Replace the current virtual file system.
///
/// \note Most clients should use setFileManager, which will implicitly reset
/// the virtual file system to the one contained in the file manager.
@@ -406,13 +409,13 @@ public:
assert(FileMgr && "Compiler instance has no file manager!");
return *FileMgr;
}
-
+
void resetAndLeakFileManager() {
BuryPointer(FileMgr.get());
FileMgr.resetWithoutRelease();
}
- /// \brief Replace the current file manager and virtual file system.
+ /// Replace the current file manager and virtual file system.
void setFileManager(FileManager *Value);
/// }
@@ -426,7 +429,7 @@ public:
assert(SourceMgr && "Compiler instance has no source manager!");
return *SourceMgr;
}
-
+
void resetAndLeakSourceManager() {
BuryPointer(SourceMgr.get());
SourceMgr.resetWithoutRelease();
@@ -466,7 +469,7 @@ public:
assert(Context && "Compiler instance has no AST context!");
return *Context;
}
-
+
void resetAndLeakASTContext() {
BuryPointer(Context.get());
Context.resetWithoutRelease();
@@ -475,10 +478,10 @@ public:
/// setASTContext - Replace the current AST context.
void setASTContext(ASTContext *Value);
- /// \brief Replace the current Sema; the compiler instance takes ownership
+ /// Replace the current Sema; the compiler instance takes ownership
/// of S.
void setSema(Sema *S);
-
+
/// }
/// @name ASTConsumer
/// {
@@ -503,7 +506,7 @@ public:
/// {
bool hasSema() const { return (bool)TheSema; }
- Sema &getSema() const {
+ Sema &getSema() const {
assert(TheSema && "Compiler instance has no Sema object!");
return *TheSema;
}
@@ -610,7 +613,7 @@ public:
/// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
/// unit.
///
- /// \param ShouldOwnClient If Client is non-NULL, specifies whether
+ /// \param ShouldOwnClient If Client is non-NULL, specifies whether
/// the diagnostic object should take ownership of the client.
void createDiagnostics(DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true);
@@ -687,10 +690,10 @@ public:
Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column,
const CodeCompleteOptions &Opts, raw_ostream &OS);
- /// \brief Create the Sema object to be used for parsing.
+ /// Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer);
-
+
/// Create the frontend timer and replace any existing one with it.
void createFrontendTimer();
@@ -773,6 +776,14 @@ public:
/// }
+ void setOutputStream(std::unique_ptr<llvm::raw_pwrite_stream> OutStream) {
+ OutputStream = std::move(OutStream);
+ }
+
+ std::unique_ptr<llvm::raw_pwrite_stream> takeOutputStream() {
+ return std::move(OutputStream);
+ }
+
// Create module manager.
void createModuleManager();
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
index 8c4c932190bc..1d421f09fdcc 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
@@ -1,4 +1,4 @@
-//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===//
+//===- CompilerInvocation.h - Compiler Invocation Helper Data ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
-#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
+#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
+#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
@@ -21,25 +22,29 @@
#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <memory>
#include <string>
namespace llvm {
+
class Triple;
namespace opt {
+
class ArgList;
-}
-}
+
+} // namespace opt
+
+} // namespace llvm
namespace clang {
-class PreprocessorOptions;
+
+class DiagnosticsEngine;
class HeaderSearchOptions;
+class PreprocessorOptions;
class TargetOptions;
-class LangOptions;
-class CompilerInvocation;
-class DiagnosticsEngine;
-/// \brief Fill out Opts based on the options given in Args.
+/// Fill out Opts based on the options given in Args.
///
/// Args must have been created from the OptTable returned by
/// createCC1OptTable().
@@ -52,8 +57,6 @@ bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
bool DefaultShowOpt = true);
class CompilerInvocationBase {
- void operator=(const CompilerInvocationBase &) = delete;
-
public:
/// Options controlling the language variant.
std::shared_ptr<LangOptions> LangOpts;
@@ -71,24 +74,24 @@ public:
std::shared_ptr<PreprocessorOptions> PreprocessorOpts;
CompilerInvocationBase();
- ~CompilerInvocationBase();
-
CompilerInvocationBase(const CompilerInvocationBase &X);
+ CompilerInvocationBase &operator=(const CompilerInvocationBase &) = delete;
+ ~CompilerInvocationBase();
LangOptions *getLangOpts() { return LangOpts.get(); }
const LangOptions *getLangOpts() const { return LangOpts.get(); }
TargetOptions &getTargetOpts() { return *TargetOpts.get(); }
- const TargetOptions &getTargetOpts() const {
- return *TargetOpts.get();
- }
+ const TargetOptions &getTargetOpts() const { return *TargetOpts.get(); }
DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; }
+
const HeaderSearchOptions &getHeaderSearchOpts() const {
return *HeaderSearchOpts;
}
+
std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const {
return HeaderSearchOpts;
}
@@ -96,13 +99,15 @@ public:
std::shared_ptr<PreprocessorOptions> getPreprocessorOptsPtr() {
return PreprocessorOpts;
}
+
PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; }
+
const PreprocessorOptions &getPreprocessorOpts() const {
return *PreprocessorOpts;
}
};
-
-/// \brief Helper class for holding the data necessary to invoke the compiler.
+
+/// Helper class for holding the data necessary to invoke the compiler.
///
/// This class is designed to represent an abstract "invocation" of the
/// compiler, including data such as the include paths, the code generation
@@ -112,7 +117,7 @@ class CompilerInvocation : public CompilerInvocationBase {
AnalyzerOptionsRef AnalyzerOpts;
MigratorOptions MigratorOpts;
-
+
/// Options controlling IRgen and the backend.
CodeGenOptions CodeGenOpts;
@@ -134,7 +139,7 @@ public:
/// @name Utility Methods
/// @{
- /// \brief Create a compiler invocation from a list of input options.
+ /// Create a compiler invocation from a list of input options.
/// \returns true on success.
///
/// \param [out] Res - The resulting invocation.
@@ -146,7 +151,7 @@ public:
const char* const *ArgEnd,
DiagnosticsEngine &Diags);
- /// \brief Get the directory where the compiler headers
+ /// Get the directory where the compiler headers
/// reside, relative to the compiler binary (found by the passed in
/// arguments).
///
@@ -156,7 +161,7 @@ public:
/// executable), for finding the builtin compiler path.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
- /// \brief Set language defaults for the given input language and
+ /// Set language defaults for the given input language and
/// language standard in the given LangOptions object.
///
/// \param Opts - The LangOptions object to set up.
@@ -167,49 +172,44 @@ public:
static void setLangDefaults(LangOptions &Opts, InputKind IK,
const llvm::Triple &T, PreprocessorOptions &PPOpts,
LangStandard::Kind LangStd = LangStandard::lang_unspecified);
-
- /// \brief Retrieve a module hash string that is suitable for uniquely
+
+ /// Retrieve a module hash string that is suitable for uniquely
/// identifying the conditions under which the module was built.
std::string getModuleHash() const;
-
+
/// @}
/// @name Option Subgroups
/// @{
- AnalyzerOptionsRef getAnalyzerOpts() const {
- return AnalyzerOpts;
- }
+ AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; }
MigratorOptions &getMigratorOpts() { return MigratorOpts; }
- const MigratorOptions &getMigratorOpts() const {
- return MigratorOpts;
- }
-
+ const MigratorOptions &getMigratorOpts() const { return MigratorOpts; }
+
CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
- const CodeGenOptions &getCodeGenOpts() const {
- return CodeGenOpts;
- }
+ const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
DependencyOutputOptions &getDependencyOutputOpts() {
return DependencyOutputOpts;
}
+
const DependencyOutputOptions &getDependencyOutputOpts() const {
return DependencyOutputOpts;
}
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+
const FileSystemOptions &getFileSystemOpts() const {
return FileSystemOpts;
}
FrontendOptions &getFrontendOpts() { return FrontendOpts; }
- const FrontendOptions &getFrontendOpts() const {
- return FrontendOpts;
- }
+ const FrontendOptions &getFrontendOpts() const { return FrontendOpts; }
PreprocessorOutputOptions &getPreprocessorOutputOpts() {
return PreprocessorOutputOpts;
}
+
const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
return PreprocessorOutputOpts;
}
@@ -218,8 +218,10 @@ public:
};
namespace vfs {
- class FileSystem;
-}
+
+class FileSystem;
+
+} // namespace vfs
IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
@@ -230,6 +232,6 @@ createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> BaseFS);
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
index 0be36cd9aa6e..f419d2643649 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
@@ -15,6 +15,9 @@
namespace clang {
+/// ShowIncludesDestination - Destination for /showIncludes output.
+enum class ShowIncludesDestination { None, Stdout, Stderr };
+
/// DependencyOutputFormat - Format for the compiler dependency file.
enum class DependencyOutputFormat { Make, NMake };
@@ -28,11 +31,13 @@ public:
/// dependency, which can avoid some 'make'
/// problems.
unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
- unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
+ /// Destination of cl.exe style /showIncludes info.
+ ShowIncludesDestination ShowIncludesDest = ShowIncludesDestination::None;
+
/// The format for the dependency file.
- DependencyOutputFormat OutputFormat;
+ DependencyOutputFormat OutputFormat = DependencyOutputFormat::Make;
/// The file to write dependency output to.
std::string OutputFile;
@@ -53,22 +58,16 @@ public:
/// In /showIncludes mode, pretend the main TU is a header with this name.
std::string ShowIncludesPretendHeader;
- /// \brief The file to write GraphViz-formatted header dependencies to.
+ /// The file to write GraphViz-formatted header dependencies to.
std::string DOTOutputFile;
- /// \brief The directory to copy module dependencies to when collecting them.
+ /// The directory to copy module dependencies to when collecting them.
std::string ModuleDependencyOutputDir;
public:
- DependencyOutputOptions() {
- IncludeSystemHeaders = 0;
- ShowHeaderIncludes = 0;
- UsePhonyTargets = 0;
- AddMissingHeaderDeps = 0;
- PrintShowIncludes = 0;
- IncludeModuleFiles = 0;
- OutputFormat = DependencyOutputFormat::Make;
- }
+ DependencyOutputOptions()
+ : IncludeSystemHeaders(0), ShowHeaderIncludes(0), UsePhonyTargets(0),
+ AddMissingHeaderDeps(0), IncludeModuleFiles(0) {}
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
index e453d7db624c..3bbf37946d0b 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
@@ -1,4 +1,4 @@
-//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===//
+//===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,20 +17,23 @@
#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
namespace clang {
-class DiagnosticOptions;
class LangOptions;
class SourceManager;
-typedef llvm::PointerUnion<const Diagnostic *,
- const StoredDiagnostic *> DiagOrStoredDiag;
-
-/// \brief Class to encapsulate the logic for formatting a diagnostic message.
+using DiagOrStoredDiag =
+ llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
+
+/// Class to encapsulate the logic for formatting a diagnostic message.
///
/// Actual "printing" logic is implemented by subclasses.
///
@@ -46,29 +49,29 @@ class DiagnosticRenderer {
protected:
const LangOptions &LangOpts;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
-
- /// \brief The location of the previous diagnostic if known.
+
+ /// The location of the previous diagnostic if known.
///
/// This will be invalid in cases where there is no (known) previous
/// diagnostic location, or that location itself is invalid or comes from
/// a different source manager than SM.
SourceLocation LastLoc;
-
- /// \brief The location of the last include whose stack was printed if known.
+
+ /// The location of the last include whose stack was printed if known.
///
/// Same restriction as LastLoc essentially, but tracking include stack
/// root locations rather than diagnostic locations.
SourceLocation LastIncludeLoc;
-
- /// \brief The level of the last diagnostic emitted.
+
+ /// The level of the last diagnostic emitted.
///
/// The level of the last diagnostic emitted. Used to detect level changes
/// which change the amount of information displayed.
- DiagnosticsEngine::Level LastLevel;
+ DiagnosticsEngine::Level LastLevel = DiagnosticsEngine::Ignored;
DiagnosticRenderer(const LangOptions &LangOpts,
DiagnosticOptions *DiagOpts);
-
+
virtual ~DiagnosticRenderer();
virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
@@ -97,7 +100,6 @@ protected:
virtual void endDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {}
-
private:
void emitBasicNote(StringRef Message);
void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
@@ -116,7 +118,7 @@ private:
ArrayRef<FixItHint> Hints);
public:
- /// \brief Emit a diagnostic.
+ /// Emit a diagnostic.
///
/// This is the primary entry point for emitting diagnostic messages.
/// It handles formatting and rendering the message as well as any ancillary
@@ -135,14 +137,14 @@ public:
void emitStoredDiagnostic(StoredDiagnostic &Diag);
};
-
+
/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
/// notes. It is up to subclasses to further define the behavior.
class DiagnosticNoteRenderer : public DiagnosticRenderer {
public:
DiagnosticNoteRenderer(const LangOptions &LangOpts,
DiagnosticOptions *DiagOpts)
- : DiagnosticRenderer(LangOpts, DiagOpts) {}
+ : DiagnosticRenderer(LangOpts, DiagOpts) {}
~DiagnosticNoteRenderer() override;
@@ -156,5 +158,7 @@ public:
virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0;
};
-} // end clang namespace
-#endif
+
+} // namespace clang
+
+#endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h
index 7ae6173512a6..2a4077d34391 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the clang::FrontendAction interface and various convenience
+/// Defines the clang::FrontendAction interface and various convenience
/// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction,
/// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction)
/// derived from it.
@@ -48,7 +48,7 @@ protected:
/// @name Implementation Action Interface
/// @{
- /// \brief Create the AST consumer object for this action, if supported.
+ /// Create the AST consumer object for this action, if supported.
///
/// This routine is called as part of BeginSourceFile(), which will
/// fail if the AST consumer cannot be created. This will not be called if the
@@ -64,7 +64,7 @@ protected:
virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) = 0;
- /// \brief Callback before starting processing a single input, giving the
+ /// Callback before starting processing a single input, giving the
/// opportunity to modify the CompilerInvocation or do some other action
/// before BeginSourceFileAction is called.
///
@@ -72,7 +72,7 @@ protected:
/// ExecuteAction() and EndSourceFileAction() will not be called.
virtual bool BeginInvocation(CompilerInstance &CI) { return true; }
- /// \brief Callback at the start of processing a single input.
+ /// Callback at the start of processing a single input.
///
/// \return True on success; on failure ExecutionAction() and
/// EndSourceFileAction() will not be called.
@@ -80,20 +80,20 @@ protected:
return true;
}
- /// \brief Callback to run the program action, using the initialized
+ /// Callback to run the program action, using the initialized
/// compiler instance.
///
/// This is guaranteed to only be called between BeginSourceFileAction()
/// and EndSourceFileAction().
virtual void ExecuteAction() = 0;
- /// \brief Callback at the end of processing a single input.
+ /// Callback at the end of processing a single input.
///
/// This is guaranteed to only be called following a successful call to
/// BeginSourceFileAction (and BeginSourceFile).
virtual void EndSourceFileAction() {}
- /// \brief Callback at the end of processing a single input, to determine
+ /// Callback at the end of processing a single input, to determine
/// if the output files should be erased or not.
///
/// By default it returns true if a compiler error occurred.
@@ -158,39 +158,39 @@ public:
/// @name Supported Modes
/// @{
- /// \brief Is this action invoked on a model file?
+ /// Is this action invoked on a model file?
///
/// Model files are incomplete translation units that relies on type
/// information from another translation unit. Check ParseModelFileAction for
/// details.
virtual bool isModelParsingAction() const { return false; }
- /// \brief Does this action only use the preprocessor?
+ /// Does this action only use the preprocessor?
///
/// If so no AST context will be created and this action will be invalid
/// with AST file inputs.
virtual bool usesPreprocessorOnly() const = 0;
- /// \brief For AST-based actions, the kind of translation unit we're handling.
+ /// For AST-based actions, the kind of translation unit we're handling.
virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
- /// \brief Does this action support use with PCH?
+ /// Does this action support use with PCH?
virtual bool hasPCHSupport() const { return true; }
- /// \brief Does this action support use with AST files?
+ /// Does this action support use with AST files?
virtual bool hasASTFileSupport() const { return true; }
- /// \brief Does this action support use with IR files?
+ /// Does this action support use with IR files?
virtual bool hasIRSupport() const { return false; }
- /// \brief Does this action support use with code completion?
+ /// Does this action support use with code completion?
virtual bool hasCodeCompletionSupport() const { return false; }
/// @}
/// @name Public Action Interface
/// @{
- /// \brief Prepare the action for processing the input file \p Input.
+ /// Prepare the action for processing the input file \p Input.
///
/// This is run after the options and frontend have been initialized,
/// but prior to executing any per-file processing.
@@ -211,20 +211,20 @@ public:
/// be aborted and neither Execute() nor EndSourceFile() should be called.
bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
- /// \brief Set the source manager's main input file, and run the action.
+ /// Set the source manager's main input file, and run the action.
bool Execute();
- /// \brief Perform any per-file post processing, deallocate per-file
+ /// Perform any per-file post processing, deallocate per-file
/// objects, and run statistics and output file cleanup code.
void EndSourceFile();
/// @}
};
-/// \brief Abstract base class to use for AST consumer-based frontend actions.
+/// Abstract base class to use for AST consumer-based frontend actions.
class ASTFrontendAction : public FrontendAction {
protected:
- /// \brief Implement the ExecuteAction interface by running Sema on
+ /// Implement the ExecuteAction interface by running Sema on
/// the already-initialized AST consumer.
///
/// This will also take care of instantiating a code completion consumer if
@@ -242,7 +242,7 @@ public:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override = 0;
- /// \brief Parse the given plugin command line arguments.
+ /// Parse the given plugin command line arguments.
///
/// \param CI - The compiler instance, for use in reporting diagnostics.
/// \return True if the parsing succeeded; otherwise the plugin will be
@@ -257,7 +257,7 @@ public:
AddBeforeMainAction, ///< Execute the action before the main action
AddAfterMainAction ///< Execute the action after the main action
};
- /// \brief Get the action type for this plugin
+ /// Get the action type for this plugin
///
/// \return The action type. If the type is Cmdline then by default the
/// plugin does nothing and what it does is determined by the cc1
@@ -265,10 +265,10 @@ public:
virtual ActionType getActionType() { return Cmdline; }
};
-/// \brief Abstract base class to use for preprocessor-based frontend actions.
+/// Abstract base class to use for preprocessor-based frontend actions.
class PreprocessorFrontendAction : public FrontendAction {
protected:
- /// \brief Provide a default implementation which returns aborts;
+ /// Provide a default implementation which returns aborts;
/// this method should never be called by FrontendAction clients.
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
@@ -277,7 +277,7 @@ public:
bool usesPreprocessorOnly() const override { return true; }
};
-/// \brief A frontend action which simply wraps some other runtime-specified
+/// A frontend action which simply wraps some other runtime-specified
/// frontend action.
///
/// Deriving from this class allows an action to inject custom logic around
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
index fa1529a3d65d..54539a5b3cee 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
@@ -18,7 +18,7 @@ namespace clang {
class Module;
class FileEntry;
-
+
//===----------------------------------------------------------------------===//
// Custom Consumer Actions
//===----------------------------------------------------------------------===//
@@ -35,6 +35,18 @@ public:
bool usesPreprocessorOnly() const override { return false; }
};
+class DumpCompilerOptionsAction : public FrontendAction {
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
+ return nullptr;
+ }
+
+ void ExecuteAction() override;
+
+public:
+ bool usesPreprocessorOnly() const override { return true; }
+};
+
//===----------------------------------------------------------------------===//
// AST Consumer Actions
//===----------------------------------------------------------------------===//
@@ -83,14 +95,14 @@ protected:
bool shouldEraseOutputFiles() override;
public:
- /// \brief Compute the AST consumer arguments that will be used to
+ /// Compute the AST consumer arguments that will be used to
/// create the PCHGenerator instance returned by CreateASTConsumer.
///
/// \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
+ /// 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,
@@ -140,7 +152,7 @@ public:
bool hasCodeCompletionSupport() const override { return true; }
};
-/// \brief Dump information about the given module file, to be used for
+/// Dump information about the given module file, to be used for
/// basic debugging and discovery.
class DumpModuleInfoAction : public ASTFrontendAction {
protected:
@@ -167,8 +179,16 @@ public:
bool hasCodeCompletionSupport() const override { return false; }
};
+class TemplightDumpAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ void ExecuteAction() override;
+};
+
/**
- * \brief Frontend action adaptor that merges ASTs together.
+ * Frontend action adaptor that merges ASTs together.
*
* This action takes an existing AST file and "merges" it into the AST
* context, producing a merged context. This action is an action
@@ -176,10 +196,10 @@ public:
* will consume the merged context.
*/
class ASTMergeAction : public FrontendAction {
- /// \brief The action that the merge action adapts.
+ /// The action that the merge action adapts.
std::unique_ptr<FrontendAction> AdaptedAction;
-
- /// \brief The set of AST files to merge.
+
+ /// The set of AST files to merge.
std::vector<std::string> ASTFiles;
protected:
@@ -213,7 +233,7 @@ protected:
bool usesPreprocessorOnly() const override { return true; }
};
-
+
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
@@ -244,7 +264,7 @@ protected:
bool hasPCHSupport() const override { return true; }
};
-
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
index 5192a3774cc1..668df83274eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -1,4 +1,4 @@
-//===--- FrontendOptions.h --------------------------------------*- C++ -*-===//
+//===- FrontendOptions.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,54 +14,127 @@
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
namespace llvm {
+
class MemoryBuffer;
-}
+
+} // namespace llvm
namespace clang {
-class FileEntry;
namespace frontend {
- enum ActionKind {
- ASTDeclList, ///< Parse ASTs and list Decl nodes.
- ASTDump, ///< Parse ASTs and dump them.
- ASTPrint, ///< Parse ASTs and print them.
- ASTView, ///< Parse ASTs and view them in Graphviz.
- DumpRawTokens, ///< Dump out raw tokens.
- DumpTokens, ///< Dump out preprocessed tokens.
- EmitAssembly, ///< Emit a .s file.
- EmitBC, ///< Emit a .bc file.
- EmitHTML, ///< Translate input source into HTML.
- EmitLLVM, ///< Emit a .ll file.
- EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything.
- EmitCodeGenOnly, ///< Generate machine code, but don't emit anything.
- EmitObj, ///< Emit a .o file.
- FixIt, ///< Parse and apply any fixits to the source.
- GenerateModule, ///< Generate pre-compiled module from a module map.
- GenerateModuleInterface,///< Generate pre-compiled module from a C++ module
- ///< interface file.
- GeneratePCH, ///< Generate pre-compiled header.
- GeneratePTH, ///< Generate pre-tokenized header.
- InitOnly, ///< Only execute frontend initialization.
- ModuleFileInfo, ///< Dump information about a module file.
- VerifyPCH, ///< Load and verify that a PCH file is usable.
- ParseSyntaxOnly, ///< Parse and perform semantic analysis.
- PluginAction, ///< Run a plugin action, \see ActionName.
- PrintDeclContext, ///< Print DeclContext and their Decls.
- PrintPreamble, ///< Print the "preamble" of the input file
- PrintPreprocessedInput, ///< -E mode.
- RewriteMacros, ///< Expand macros but not \#includes.
- RewriteObjC, ///< ObjC->C Rewriter.
- RewriteTest, ///< Rewriter playground
- RunAnalysis, ///< Run one or more source code analyses.
- MigrateSource, ///< Run migrator.
- RunPreprocessorOnly ///< Just lex, no output.
- };
-}
+
+enum ActionKind {
+ /// Parse ASTs and list Decl nodes.
+ ASTDeclList,
+
+ /// Parse ASTs and dump them.
+ ASTDump,
+
+ /// Parse ASTs and print them.
+ ASTPrint,
+
+ /// Parse ASTs and view them in Graphviz.
+ ASTView,
+
+ /// Dump the compiler configuration.
+ DumpCompilerOptions,
+
+ /// Dump out raw tokens.
+ DumpRawTokens,
+
+ /// Dump out preprocessed tokens.
+ DumpTokens,
+
+ /// Emit a .s file.
+ EmitAssembly,
+
+ /// Emit a .bc file.
+ EmitBC,
+
+ /// Translate input source into HTML.
+ EmitHTML,
+
+ /// Emit a .ll file.
+ EmitLLVM,
+
+ /// Generate LLVM IR, but do not emit anything.
+ EmitLLVMOnly,
+
+ /// Generate machine code, but don't emit anything.
+ EmitCodeGenOnly,
+
+ /// Emit a .o file.
+ EmitObj,
+
+ /// Parse and apply any fixits to the source.
+ FixIt,
+
+ /// Generate pre-compiled module from a module map.
+ GenerateModule,
+
+ /// Generate pre-compiled module from a C++ module interface file.
+ GenerateModuleInterface,
+
+ /// Generate pre-compiled header.
+ GeneratePCH,
+
+ /// Generate pre-tokenized header.
+ GeneratePTH,
+
+ /// Only execute frontend initialization.
+ InitOnly,
+
+ /// Dump information about a module file.
+ ModuleFileInfo,
+
+ /// Load and verify that a PCH file is usable.
+ VerifyPCH,
+
+ /// Parse and perform semantic analysis.
+ ParseSyntaxOnly,
+
+ /// Run a plugin action, \see ActionName.
+ PluginAction,
+
+ /// Print DeclContext and their Decls.
+ PrintDeclContext,
+
+ /// Print the "preamble" of the input file
+ PrintPreamble,
+
+ /// -E mode.
+ PrintPreprocessedInput,
+
+ /// Expand macros but not \#includes.
+ RewriteMacros,
+
+ /// ObjC->C Rewriter.
+ RewriteObjC,
+
+ /// Rewriter playground
+ RewriteTest,
+
+ /// Run one or more source code analyses.
+ RunAnalysis,
+
+ /// Dump template instantiations
+ TemplightDump,
+
+ /// Run migrator.
+ MigrateSource,
+
+ /// Just lex, no output.
+ RunPreprocessorOnly
+};
+
+} // namespace frontend
/// The kind of a file that we've been handed as an input.
class InputKind {
@@ -91,6 +164,7 @@ public:
OpenCL,
CUDA,
RenderScript,
+ HIP,
///@}
};
@@ -118,14 +192,15 @@ public:
InputKind getPreprocessed() const {
return InputKind(getLanguage(), getFormat(), true);
}
+
InputKind withFormat(Format F) const {
return InputKind(getLanguage(), F, isPreprocessed());
}
};
-/// \brief An input file for the front end.
+/// An input file for the front end.
class FrontendInputFile {
- /// \brief The file name, or "-" to read from standard input.
+ /// The file name, or "-" to read from standard input.
std::string File;
/// The input, if it comes from a buffer rather than a file. This object
@@ -133,19 +208,19 @@ class FrontendInputFile {
/// that it outlives any users.
llvm::MemoryBuffer *Buffer = nullptr;
- /// \brief The kind of input, e.g., C source, AST file, LLVM IR.
+ /// 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).
+ /// Whether we're dealing with a 'system' input (vs. a 'user' input).
bool IsSystem = false;
public:
- FrontendInputFile() { }
+ FrontendInputFile() = default;
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
- : File(File.str()), Kind(Kind), IsSystem(IsSystem) { }
+ : 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; }
@@ -159,6 +234,7 @@ public:
assert(isFile());
return File;
}
+
llvm::MemoryBuffer *getBuffer() const {
assert(isBuffer());
return Buffer;
@@ -168,43 +244,67 @@ public:
/// FrontendOptions - Options for controlling the behavior of the frontend.
class FrontendOptions {
public:
- unsigned DisableFree : 1; ///< Disable memory freeing on exit.
- unsigned RelocatablePCH : 1; ///< When generating PCH files,
- /// instruct the AST writer to create
- /// relocatable PCH files.
- unsigned ShowHelp : 1; ///< Show the -help text.
- unsigned ShowStats : 1; ///< Show frontend performance
- /// metrics and statistics.
- unsigned ShowTimers : 1; ///< Show timers for individual
- /// actions.
- unsigned ShowVersion : 1; ///< Show the -version text.
- unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are
- /// unfixable errors.
- unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings.
- unsigned FixAndRecompile : 1; ///< Apply fixes and recompile.
- unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files.
- unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the
- /// migrator can fix them
- unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to
- /// speed up parsing in cases you do
- /// not need them (e.g. with code
- /// completion).
- unsigned UseGlobalModuleIndex : 1; ///< Whether we can use the
- ///< global module index if available.
- unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the
- ///< global module index if needed.
- unsigned ASTDumpDecls : 1; ///< Whether we include declaration
- ///< dumps in AST dumps.
- unsigned ASTDumpAll : 1; ///< Whether we deserialize all decls
- ///< when forming AST dumps.
- unsigned ASTDumpLookups : 1; ///< Whether we include lookup table
- ///< dumps in AST dumps.
- unsigned BuildingImplicitModule : 1; ///< Whether we are performing an
- ///< implicit module build.
- unsigned ModulesEmbedAllFiles : 1; ///< Whether we should embed all used
- ///< files into the PCM file.
- unsigned IncludeTimestamps : 1; ///< Whether timestamps should be
- ///< written to the produced PCH file.
+ /// Disable memory freeing on exit.
+ unsigned DisableFree : 1;
+
+ /// When generating PCH files, instruct the AST writer to create relocatable
+ /// PCH files.
+ unsigned RelocatablePCH : 1;
+
+ /// Show the -help text.
+ unsigned ShowHelp : 1;
+
+ /// Show frontend performance metrics and statistics.
+ unsigned ShowStats : 1;
+
+ /// Show timers for individual actions.
+ unsigned ShowTimers : 1;
+
+ /// Show the -version text.
+ unsigned ShowVersion : 1;
+
+ /// Apply fixes even if there are unfixable errors.
+ unsigned FixWhatYouCan : 1;
+
+ /// Apply fixes only for warnings.
+ unsigned FixOnlyWarnings : 1;
+
+ /// Apply fixes and recompile.
+ unsigned FixAndRecompile : 1;
+
+ /// Apply fixes to temporary files.
+ unsigned FixToTemporaries : 1;
+
+ /// Emit ARC errors even if the migrator can fix them.
+ unsigned ARCMTMigrateEmitARCErrors : 1;
+
+ /// Skip over function bodies to speed up parsing in cases you do not need
+ /// them (e.g. with code completion).
+ unsigned SkipFunctionBodies : 1;
+
+ /// Whether we can use the global module index if available.
+ unsigned UseGlobalModuleIndex : 1;
+
+ /// Whether we can generate the global module index if needed.
+ unsigned GenerateGlobalModuleIndex : 1;
+
+ /// Whether we include declaration dumps in AST dumps.
+ unsigned ASTDumpDecls : 1;
+
+ /// Whether we deserialize all decls when forming AST dumps.
+ unsigned ASTDumpAll : 1;
+
+ /// Whether we include lookup table dumps in AST dumps.
+ unsigned ASTDumpLookups : 1;
+
+ /// Whether we are performing an implicit module build.
+ unsigned BuildingImplicitModule : 1;
+
+ /// Whether we should embed all used files into the PCM file.
+ unsigned ModulesEmbedAllFiles : 1;
+
+ /// Whether timestamps should be written to the produced PCH file.
+ unsigned IncludeTimestamps : 1;
CodeCompleteOptions CodeCompleteOpts;
@@ -213,38 +313,53 @@ public:
ARCMT_Check,
ARCMT_Modify,
ARCMT_Migrate
- } ARCMTAction;
+ } ARCMTAction = ARCMT_None;
enum {
ObjCMT_None = 0,
- /// \brief Enable migration to modern ObjC literals.
+
+ /// Enable migration to modern ObjC literals.
ObjCMT_Literals = 0x1,
- /// \brief Enable migration to modern ObjC subscripting.
+
+ /// Enable migration to modern ObjC subscripting.
ObjCMT_Subscripting = 0x2,
- /// \brief Enable migration to modern ObjC readonly property.
+
+ /// Enable migration to modern ObjC readonly property.
ObjCMT_ReadonlyProperty = 0x4,
- /// \brief Enable migration to modern ObjC readwrite property.
+
+ /// Enable migration to modern ObjC readwrite property.
ObjCMT_ReadwriteProperty = 0x8,
- /// \brief Enable migration to modern ObjC property.
+
+ /// Enable migration to modern ObjC property.
ObjCMT_Property = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty),
- /// \brief Enable annotation of ObjCMethods of all kinds.
+
+ /// Enable annotation of ObjCMethods of all kinds.
ObjCMT_Annotation = 0x10,
- /// \brief Enable migration of ObjC methods to 'instancetype'.
+
+ /// Enable migration of ObjC methods to 'instancetype'.
ObjCMT_Instancetype = 0x20,
- /// \brief Enable migration to NS_ENUM/NS_OPTIONS macros.
+
+ /// Enable migration to NS_ENUM/NS_OPTIONS macros.
ObjCMT_NsMacros = 0x40,
- /// \brief Enable migration to add conforming protocols.
+
+ /// Enable migration to add conforming protocols.
ObjCMT_ProtocolConformance = 0x80,
- /// \brief prefer 'atomic' property over 'nonatomic'.
+
+ /// prefer 'atomic' property over 'nonatomic'.
ObjCMT_AtomicProperty = 0x100,
- /// \brief annotate property with NS_RETURNS_INNER_POINTER
+
+ /// annotate property with NS_RETURNS_INNER_POINTER
ObjCMT_ReturnsInnerPointerProperty = 0x200,
- /// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
+
+ /// use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
ObjCMT_NsAtomicIOSOnlyProperty = 0x400,
- /// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
+
+ /// Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
ObjCMT_DesignatedInitializer = 0x800,
- /// \brief Enable converting setter/getter expressions to property-dot syntx.
+
+ /// Enable converting setter/getter expressions to property-dot syntx.
ObjCMT_PropertyDotSyntax = 0x1000,
+
ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty |
ObjCMT_Annotation | ObjCMT_Instancetype |
ObjCMT_NsMacros | ObjCMT_ProtocolConformance |
@@ -253,7 +368,7 @@ public:
ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting |
ObjCMT_MigrateDecls | ObjCMT_PropertyDotSyntax)
};
- unsigned ObjCMTAction;
+ unsigned ObjCMTAction = ObjCMT_None;
std::string ObjCMTWhiteListPath;
std::string MTMigrateDir;
@@ -279,7 +394,7 @@ public:
ParsedSourceLocation CodeCompletionAt;
/// The frontend action to perform.
- frontend::ActionKind ProgramAction;
+ frontend::ActionKind ProgramAction = frontend::ParseSyntaxOnly;
/// The name of the action to run when using a plugin action.
std::string ActionName;
@@ -296,49 +411,43 @@ public:
/// The list of module file extensions.
std::vector<std::shared_ptr<ModuleFileExtension>> ModuleFileExtensions;
- /// \brief The list of module map files to load before processing the input.
+ /// The list of module map files to load before processing the input.
std::vector<std::string> ModuleMapFiles;
- /// \brief The list of additional prebuilt module files to load before
+ /// The list of additional prebuilt module files to load before
/// processing the input.
std::vector<std::string> ModuleFiles;
- /// \brief The list of files to embed into the compiled module file.
+ /// The list of files to embed into the compiled module file.
std::vector<std::string> ModulesEmbedFiles;
- /// \brief The list of AST files to merge.
+ /// The list of AST files to merge.
std::vector<std::string> ASTMergeFiles;
- /// \brief A list of arguments to forward to LLVM's option processing; this
+ /// A list of arguments to forward to LLVM's option processing; this
/// should only be used for debugging and experimental features.
std::vector<std::string> LLVMArgs;
- /// \brief File name of the file that will provide record layouts
+ /// File name of the file that will provide record layouts
/// (in the format produced by -fdump-record-layouts).
std::string OverrideRecordLayoutsFile;
- /// \brief Auxiliary triple for CUDA compilation.
+ /// Auxiliary triple for CUDA compilation.
std::string AuxTriple;
- /// \brief If non-empty, search the pch input file as if it was a header
- /// included by this file.
- std::string FindPchSource;
-
/// Filename to write statistics to.
std::string StatsFile;
public:
- FrontendOptions() :
- DisableFree(false), RelocatablePCH(false), ShowHelp(false),
- ShowStats(false), ShowTimers(false), ShowVersion(false),
- FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false),
- FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
- SkipFunctionBodies(false), UseGlobalModuleIndex(true),
- GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false),
- BuildingImplicitModule(false), ModulesEmbedAllFiles(false),
- IncludeTimestamps(true), ARCMTAction(ARCMT_None),
- ObjCMTAction(ObjCMT_None), ProgramAction(frontend::ParseSyntaxOnly)
- {}
+ FrontendOptions()
+ : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
+ ShowStats(false), ShowTimers(false), ShowVersion(false),
+ FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false),
+ FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
+ SkipFunctionBodies(false), UseGlobalModuleIndex(true),
+ GenerateGlobalModuleIndex(true), ASTDumpDecls(false),
+ ASTDumpLookups(false), BuildingImplicitModule(false),
+ ModulesEmbedAllFiles(false), IncludeTimestamps(true) {}
/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return InputKind::C.
@@ -348,6 +457,6 @@ public:
static InputKind getInputKindForExtension(StringRef Extension);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h
index 9d7ee08d95d4..9a85e89d905d 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h
@@ -1,4 +1,4 @@
-//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===//
+//===- FrontendPluginRegistry.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,6 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// Pluggable Frontend Action Interface
+//
+//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
@@ -16,8 +20,8 @@
namespace clang {
/// The frontend plugin registry.
-typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry;
+using FrontendPluginRegistry = llvm::Registry<PluginASTAction>;
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
index e7a081dc2aa7..1e895d785d15 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
@@ -155,6 +155,9 @@ LANGSTANDARD(opencl12, "cl1.2",
LANGSTANDARD(opencl20, "cl2.0",
OpenCL, "OpenCL 2.0",
LineComment | C99 | Digraphs | HexFloat | OpenCL)
+LANGSTANDARD(openclcpp, "c++",
+ OpenCL, "OpenCL C++ 1.0",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | OpenCL)
LANGSTANDARD_ALIAS_DEPR(opencl10, "CL")
LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1")
@@ -165,6 +168,10 @@ LANGSTANDARD_ALIAS_DEPR(opencl20, "CL2.0")
LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)",
LineComment | CPlusPlus | Digraphs)
+// HIP
+LANGSTANDARD(hip, "hip", HIP, "HIP",
+ LineComment | CPlusPlus | Digraphs)
+
#undef LANGSTANDARD
#undef LANGSTANDARD_ALIAS
#undef LANGSTANDARD_ALIAS_DEPR
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h
index 16d032b7dd72..28e3cf005b30 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h
@@ -1,4 +1,4 @@
-//===--- LayoutOverrideSource.h --Override Record Layouts -----------------===//
+//===--- LayoutOverrideSource.h --Override Record Layouts -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,36 +16,36 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
- /// \brief An external AST source that overrides the layout of
+ /// An external AST source that overrides the layout of
/// a specified set of record types.
///
/// This class is used only for testing the ability of external AST sources
/// to override the layout of record types. Its input is the output format
/// of the command-line argument -fdump-record-layouts.
class LayoutOverrideSource : public ExternalASTSource {
- /// \brief The layout of a given record.
+ /// The layout of a given record.
struct Layout {
- /// \brief The size of the record.
+ /// The size of the record.
uint64_t Size;
-
- /// \brief The alignment of the record.
+
+ /// The alignment of the record.
uint64_t Align;
-
- /// \brief The offsets of the fields, in source order.
+
+ /// The offsets of the fields, in source order.
SmallVector<uint64_t, 8> FieldOffsets;
};
-
- /// \brief The set of layouts that will be overridden.
+
+ /// The set of layouts that will be overridden.
llvm::StringMap<Layout> Layouts;
-
+
public:
- /// \brief Create a new AST source that overrides the layout of some
+ /// Create a new AST source that overrides the layout of some
/// set of record types.
///
/// The file is the result of passing -fdump-record-layouts to a file.
explicit LayoutOverrideSource(StringRef Filename);
-
- /// \brief If this particular record type has an overridden layout,
+
+ /// If this particular record type has an overridden layout,
/// return that layout.
bool
layoutRecordType(const RecordDecl *Record,
@@ -54,8 +54,8 @@ namespace clang {
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
llvm::DenseMap<const CXXRecordDecl *,
CharUnits> &VirtualBaseOffsets) override;
-
- /// \brief Dump the overridden layouts.
+
+ /// Dump the overridden layouts.
void dump();
};
}
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h
index 98adf655fcf1..3286ecf2cdd3 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h
@@ -23,22 +23,22 @@ class LogDiagnosticPrinter : public DiagnosticConsumer {
struct DiagEntry {
/// The primary message line of the diagnostic.
std::string Message;
-
+
/// The source file name, if available.
std::string Filename;
-
+
/// The source file line number, if available.
unsigned Line;
-
+
/// The source file column number, if available.
unsigned Column;
-
+
/// The ID of the diagnostic.
unsigned DiagnosticID;
/// The Option Flag for the diagnostic
std::string WarningOption;
-
+
/// The level of the diagnostic.
DiagnosticsEngine::Level DiagnosticLevel;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h
index d13565c27bc3..214fefb219cd 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h
@@ -17,13 +17,34 @@
#include "clang/Basic/LLVM.h"
#include "clang/Sema/SemaConsumer.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
#include <memory>
#include <vector>
namespace clang {
class MultiplexASTMutationListener;
-class MultiplexASTDeserializationListener;
+
+// This ASTDeserializationListener forwards its notifications to a set of
+// child listeners.
+class MultiplexASTDeserializationListener : public ASTDeserializationListener {
+public:
+ // Does NOT take ownership of the elements in L.
+ MultiplexASTDeserializationListener(
+ const std::vector<ASTDeserializationListener *> &L);
+ void ReaderInitialized(ASTReader *Reader) override;
+ void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override;
+ void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
+ void TypeRead(serialization::TypeIdx Idx, QualType T) override;
+ void DeclRead(serialization::DeclID ID, const Decl *D) override;
+ void SelectorRead(serialization::SelectorID iD, Selector Sel) override;
+ void MacroDefinitionRead(serialization::PreprocessedEntityID,
+ MacroDefinitionRecord *MD) override;
+ void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override;
+
+private:
+ std::vector<ASTDeserializationListener *> Listeners;
+};
// Has a list of ASTConsumers and calls each of them. Owns its children.
class MultiplexConsumer : public SemaConsumer {
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h b/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
index f9a73508d700..7a12ebc862e7 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
@@ -34,12 +34,12 @@ struct PCHBuffer {
llvm::SmallVector<char, 0> Data;
bool IsComplete;
};
-
+
/// This abstract interface provides operations for creating
/// containers for serialized ASTs (precompiled headers and clang
/// modules).
class PCHContainerWriter {
-public:
+public:
virtual ~PCHContainerWriter() = 0;
virtual StringRef getFormat() const = 0;
@@ -58,7 +58,7 @@ public:
/// containers for serialized ASTs (precompiled headers and clang
/// modules).
class PCHContainerReader {
-public:
+public:
virtual ~PCHContainerReader() = 0;
/// Equivalent to the format passed to -fmodule-format=
virtual StringRef getFormat() const = 0;
@@ -102,7 +102,7 @@ public:
}
void registerReader(std::unique_ptr<PCHContainerReader> Reader) {
Readers[Reader->getFormat()] = std::move(Reader);
- }
+ }
const PCHContainerWriter *getWriterOrNull(StringRef Format) {
return Writers[Format].get();
}
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h b/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
index 130fe60704a7..6abdbe3a1e1b 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
@@ -38,7 +38,7 @@ class CompilerInvocation;
class DeclGroupRef;
class PCHContainerOperations;
-/// \brief Runs lexer to compute suggested preamble bounds.
+/// Runs lexer to compute suggested preamble bounds.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
llvm::MemoryBuffer *Buffer,
unsigned MaxLines);
@@ -53,7 +53,7 @@ class PrecompiledPreamble {
struct PreambleFileHash;
public:
- /// \brief Try to build PrecompiledPreamble for \p Invocation. See
+ /// Try to build PrecompiledPreamble for \p Invocation. See
/// BuildPreambleError for possible error codes.
///
/// \param Invocation Original CompilerInvocation with options to compile the
@@ -104,14 +104,22 @@ public:
/// Changes options inside \p CI to use PCH from this preamble. Also remaps
/// 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.
+ /// Requires that CanReuse() is true.
+ /// For in-memory preambles, PrecompiledPreamble instance continues to own the
+ /// MemoryBuffer with the Preamble after this method returns. The caller is
+ /// responsible 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;
+ /// Configure \p CI to use this preamble.
+ /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
+ /// If this preamble does not match the file, it may parse differently.
+ void OverridePreamble(CompilerInvocation &CI,
+ IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ llvm::MemoryBuffer *MainFileBuffer) const;
+
private:
PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
bool PreambleEndsAtStartOfLine,
@@ -222,6 +230,12 @@ private:
}
};
+ /// Helper function to set up PCH for the preamble into \p CI and \p VFS to
+ /// with the specified \p Bounds.
+ void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
+ IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ llvm::MemoryBuffer *MainFileBuffer) const;
+
/// 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.
@@ -275,7 +289,6 @@ enum class BuildPreambleError {
PreambleIsEmpty = 1,
CouldntCreateTempFile,
CouldntCreateTargetInfo,
- CouldntCreateVFSOverlay,
BeginSourceFileFailed,
CouldntEmitPCH
};
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h
index 4c57e9d404f0..dc68c32fb15a 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h
@@ -1,4 +1,4 @@
-//===--- SerializedDiagnosticPrinter.h - Serializer for diagnostics -------===//
+//===--- SerializedDiagnosticPrinter.h - Diagnostics serializer -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -25,11 +25,11 @@ class DiagnosticOptions;
namespace serialized_diags {
-/// \brief Returns a DiagnosticConsumer that serializes diagnostics to
+/// Returns a DiagnosticConsumer that serializes diagnostics to
/// a bitcode file.
///
/// The created DiagnosticConsumer is designed for quick and lightweight
-/// transfer of of diagnostics to the enclosing build system (e.g., an IDE).
+/// transfer of diagnostics to the enclosing build system (e.g., an IDE).
/// This allows wrapper tools for Clang to get diagnostics from Clang
/// (via libclang) without needing to parse Clang's command line output.
///
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
index 07479844d465..595bdf1f4d7a 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
@@ -1,4 +1,4 @@
-//===--- SerializedDiagnosticReader.h - Reads diagnostics -------*- C++ -*-===//
+//===- SerializedDiagnosticReader.h - Reads diagnostics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
-#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
+#ifndef LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H
+#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H
#include "clang/Basic/LLVM.h"
#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorOr.h"
+#include <system_error>
namespace clang {
namespace serialized_diags {
@@ -41,90 +43,97 @@ inline std::error_code make_error_code(SDError E) {
return std::error_code(static_cast<int>(E), SDErrorCategory());
}
-/// \brief A location that is represented in the serialized diagnostics.
+/// A location that is represented in the serialized diagnostics.
struct Location {
unsigned FileID;
unsigned Line;
unsigned Col;
unsigned Offset;
+
Location(unsigned FileID, unsigned Line, unsigned Col, unsigned Offset)
: FileID(FileID), Line(Line), Col(Col), Offset(Offset) {}
};
-/// \brief A base class that handles reading serialized diagnostics from a file.
+/// A base class that handles reading serialized diagnostics from a file.
///
/// Subclasses should override the visit* methods with their logic for handling
/// the various constructs that are found in serialized diagnostics.
class SerializedDiagnosticReader {
public:
- SerializedDiagnosticReader() {}
- virtual ~SerializedDiagnosticReader() {}
+ SerializedDiagnosticReader() = default;
+ virtual ~SerializedDiagnosticReader() = default;
- /// \brief Read the diagnostics in \c File
+ /// Read the diagnostics in \c File
std::error_code readDiagnostics(StringRef File);
private:
enum class Cursor;
- /// \brief Read to the next record or block to process.
+ /// Read to the next record or block to process.
llvm::ErrorOr<Cursor> skipUntilRecordOrBlock(llvm::BitstreamCursor &Stream,
unsigned &BlockOrRecordId);
- /// \brief Read a metadata block from \c Stream.
+ /// Read a metadata block from \c Stream.
std::error_code readMetaBlock(llvm::BitstreamCursor &Stream);
- /// \brief Read a diagnostic block from \c Stream.
+ /// Read a diagnostic block from \c Stream.
std::error_code readDiagnosticBlock(llvm::BitstreamCursor &Stream);
protected:
- /// \brief Visit the start of a diagnostic block.
- virtual std::error_code visitStartOfDiagnostic() {
- return std::error_code();
- }
- /// \brief Visit the end of a diagnostic block.
- virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); }
- /// \brief Visit a category. This associates the category \c ID to a \c Name.
+ /// Visit the start of a diagnostic block.
+ virtual std::error_code visitStartOfDiagnostic() { return {}; }
+
+ /// Visit the end of a diagnostic block.
+ virtual std::error_code visitEndOfDiagnostic() { return {}; }
+
+ /// Visit a category. This associates the category \c ID to a \c Name.
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) {
- return std::error_code();
+ return {};
}
- /// \brief Visit a flag. This associates the flag's \c ID to a \c Name.
+
+ /// Visit a flag. This associates the flag's \c ID to a \c Name.
virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) {
- return std::error_code();
+ return {};
}
- /// \brief Visit a diagnostic.
+
+ /// Visit a diagnostic.
virtual std::error_code
visitDiagnosticRecord(unsigned Severity, const Location &Location,
unsigned Category, unsigned Flag, StringRef Message) {
- return std::error_code();
+ return {};
}
- /// \brief Visit a filename. This associates the file's \c ID to a \c Name.
+
+ /// Visit a filename. This associates the file's \c ID to a \c Name.
virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
unsigned Timestamp,
StringRef Name) {
- return std::error_code();
+ return {};
}
- /// \brief Visit a fixit hint.
+
+ /// Visit a fixit hint.
virtual std::error_code
visitFixitRecord(const Location &Start, const Location &End, StringRef Text) {
- return std::error_code();
+ return {};
}
- /// \brief Visit a source range.
+
+ /// Visit a source range.
virtual std::error_code visitSourceRangeRecord(const Location &Start,
const Location &End) {
- return std::error_code();
- }
- /// \brief Visit the version of the set of diagnostics.
- virtual std::error_code visitVersionRecord(unsigned Version) {
- return std::error_code();
+ return {};
}
+
+ /// Visit the version of the set of diagnostics.
+ virtual std::error_code visitVersionRecord(unsigned Version) { return {}; }
};
-} // end serialized_diags namespace
-} // end clang namespace
+} // namespace serialized_diags
+} // namespace clang
namespace std {
+
template <>
struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {};
-}
-#endif
+} // namespace std
+
+#endif // LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h
index 2032cd3988db..dacbc678b700 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h
@@ -16,11 +16,11 @@ namespace clang {
namespace serialized_diags {
enum BlockIDs {
- /// \brief A top-level block which represents any meta data associated
+ /// A top-level block which represents any meta data associated
/// with the diagostics, including versioning of the format.
BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID,
- /// \brief The this block acts as a container for all the information
+ /// The this block acts as a container for all the information
/// for a specific diagnostic.
BLOCK_DIAG
};
@@ -37,7 +37,7 @@ enum RecordIDs {
RECORD_LAST = RECORD_FIXIT
};
-/// \brief A stable version of DiagnosticIDs::Level.
+/// A stable version of DiagnosticIDs::Level.
///
/// Do not change the order of values in this enum, and please increment the
/// serialized diagnostics version number when you add to it.
@@ -50,7 +50,7 @@ enum Level {
Remark
};
-/// \brief The serialized diagnostics version number.
+/// The serialized diagnostics version number.
enum { VersionNumber = 2 };
} // end serialized_diags namespace
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h
index 1bbfe9fa02e3..9f33b866a1eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h
@@ -20,7 +20,7 @@
namespace clang {
-/// \brief Class to encapsulate the logic for formatting and printing a textual
+/// Class to encapsulate the logic for formatting and printing a textual
/// diagnostic message.
///
/// This class provides an interface for building and emitting a textual
@@ -42,7 +42,7 @@ public:
~TextDiagnostic() override;
- /// \brief Print the diagonstic level to a raw_ostream.
+ /// Print the diagonstic level to a raw_ostream.
///
/// This is a static helper that handles colorizing the level and formatting
/// it into an arbitrary output stream. This is used internally by the
@@ -54,7 +54,7 @@ public:
bool ShowColors,
bool CLFallbackMode = false);
- /// \brief Pretty-print a diagnostic message to a raw_ostream.
+ /// Pretty-print a diagnostic message to a raw_ostream.
///
/// This is a static helper to handle the line wrapping, colorizing, and
/// rendering of a diagnostic message to a particular ostream. It is
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
index 23f168e2232d..2295f9dbf3bf 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -1,4 +1,4 @@
-//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===//
+//===- TextDiagnosticBuffer.h - Buffer Text Diagnostics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,37 +15,41 @@
#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cstddef>
+#include <string>
+#include <utility>
#include <vector>
namespace clang {
-class Preprocessor;
-class SourceManager;
-
class TextDiagnosticBuffer : public DiagnosticConsumer {
public:
- typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
- typedef DiagList::iterator iterator;
- typedef DiagList::const_iterator const_iterator;
+ using DiagList = std::vector<std::pair<SourceLocation, std::string>>;
+ using iterator = DiagList::iterator;
+ using const_iterator = DiagList::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(); }
+ const_iterator err_begin() const { return Errors.begin(); }
+ const_iterator err_end() const { return Errors.end(); }
const_iterator warn_begin() const { return Warnings.begin(); }
- const_iterator warn_end() const { return Warnings.end(); }
+ const_iterator warn_end() const { return Warnings.end(); }
const_iterator remark_begin() const { return Remarks.begin(); }
- const_iterator remark_end() const { return Remarks.end(); }
+ const_iterator remark_end() const { return Remarks.end(); }
const_iterator note_begin() const { return Notes.begin(); }
- const_iterator note_end() const { return Notes.end(); }
+ const_iterator note_end() const { return Notes.end(); }
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override;
@@ -55,6 +59,6 @@ public:
void FlushDiagnostics(DiagnosticsEngine &Diags) const;
};
-} // end namspace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
index 07cee9f8ad8a..3cb4e02edf0d 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -29,7 +29,7 @@ class TextDiagnosticPrinter : public DiagnosticConsumer {
raw_ostream &OS;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
- /// \brief Handle to the currently active text diagnostic emitter.
+ /// Handle to the currently active text diagnostic emitter.
std::unique_ptr<TextDiagnostic> TextDiag;
/// A string to prefix to error messages.
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
index 8ccc31982dab..67912a8dfcdd 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
@@ -1,4 +1,4 @@
-//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
+//===- Utils.h - Misc utilities for the front-end ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,45 +15,49 @@
#define LLVM_CLANG_FRONTEND_UTILS_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/OptSpecifier.h"
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
namespace llvm {
-class raw_fd_ostream;
+
class Triple;
namespace opt {
+
class ArgList;
-}
-}
+
+} // namespace opt
+
+} // namespace llvm
namespace clang {
-class ASTConsumer;
+
class ASTReader;
class CompilerInstance;
class CompilerInvocation;
-class Decl;
class DependencyOutputOptions;
class DiagnosticsEngine;
-class DiagnosticOptions;
class ExternalSemaSource;
-class FileManager;
+class FrontendOptions;
class HeaderSearch;
class HeaderSearchOptions;
-class IdentifierTable;
class LangOptions;
class PCHContainerReader;
class Preprocessor;
class PreprocessorOptions;
class PreprocessorOutputOptions;
-class SourceManager;
-class Stmt;
-class TargetInfo;
-class FrontendOptions;
/// Apply the header search options to get given HeaderSearch object.
void ApplyHeaderSearchOptions(HeaderSearch &HS,
@@ -68,7 +72,7 @@ void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts,
const FrontendOptions &FEOpts);
/// DoPrintPreprocessedInput - Implement -E mode.
-void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS,
+void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
const PreprocessorOutputOptions &Opts);
/// An interface for collecting the dependencies of a compilation. Users should
@@ -78,9 +82,11 @@ void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS,
/// interface.
class DependencyCollector {
public:
+ virtual ~DependencyCollector();
+
virtual void attachToPreprocessor(Preprocessor &PP);
virtual void attachToASTReader(ASTReader &R);
- llvm::ArrayRef<std::string> getDependencies() const { return Dependencies; }
+ ArrayRef<std::string> getDependencies() const { return Dependencies; }
/// Called when a new file is seen. Return true if \p Filename should be added
/// to the list of dependencies.
@@ -88,17 +94,19 @@ public:
/// The default implementation ignores <built-in> and system files.
virtual bool sawDependency(StringRef Filename, bool FromModule,
bool IsSystem, bool IsModuleFile, bool IsMissing);
+
/// Called when the end of the main file is reached.
- virtual void finishedMainFile() { }
+ virtual void finishedMainFile() {}
+
/// Return true if system files should be passed to sawDependency().
virtual bool needSystemDependencies() { return false; }
- virtual ~DependencyCollector();
-public: // implementation detail
+ // implementation detail
/// Add a dependency \p Filename if it has not been seen before and
/// sawDependency() returns true.
void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem,
bool IsModuleFile, bool IsMissing);
+
private:
llvm::StringSet<> Seen;
std::vector<std::string> Dependencies;
@@ -110,10 +118,13 @@ private:
/// loaded.
class DependencyFileGenerator {
void *Impl; // Opaque implementation
+
DependencyFileGenerator(void *Impl);
+
public:
static DependencyFileGenerator *CreateAndAttachToPreprocessor(
Preprocessor &PP, const DependencyOutputOptions &Opts);
+
void AttachToASTReader(ASTReader &R);
};
@@ -124,15 +135,20 @@ class ModuleDependencyCollector : public DependencyCollector {
bool HasErrors = false;
llvm::StringSet<> Seen;
vfs::YAMLVFSWriter VFSWriter;
-
llvm::StringMap<std::string> SymLinkMap;
bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
- std::error_code copyToRoot(StringRef Src, StringRef Dst = "");
+ std::error_code copyToRoot(StringRef Src, StringRef Dst = {});
+
public:
+ ModuleDependencyCollector(std::string DestDir)
+ : DestDir(std::move(DestDir)) {}
+ ~ModuleDependencyCollector() override { writeFileMap(); }
+
StringRef getDest() { return DestDir; }
bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; }
- void addFile(StringRef Filename, StringRef FileDst = "");
+ void addFile(StringRef Filename, StringRef FileDst = {});
+
void addFileMapping(StringRef VPath, StringRef RPath) {
VFSWriter.addFileMapping(VPath, RPath);
}
@@ -142,9 +158,6 @@ public:
void writeFileMap();
bool hasErrors() { return HasErrors; }
- ModuleDependencyCollector(std::string DestDir)
- : DestDir(std::move(DestDir)) {}
- ~ModuleDependencyCollector() { writeFileMap(); }
};
/// AttachDependencyGraphGen - Create a dependency graph generator, and attach
@@ -167,7 +180,7 @@ void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
void AttachHeaderIncludeGen(Preprocessor &PP,
const DependencyOutputOptions &DepOpts,
bool ShowAllHeaders = false,
- StringRef OutputPath = "",
+ StringRef OutputPath = {},
bool ShowDepth = true, bool MSStyle = false);
/// Cache tokens for use with PCH. Note that this requires a seekable stream.
@@ -221,6 +234,12 @@ template <typename T> void BuryPointer(std::unique_ptr<T> Ptr) {
BuryPointer(Ptr.release());
}
-} // end namespace clang
+// Frontend timing utils
+
+/// If the user specifies the -ftime-report argument on an Clang command line
+/// then the value of this boolean will be true, otherwise false.
+extern bool FrontendTimesIsEnabled;
+
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_UTILS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 8d71fb98b0bb..f36970f1eb39 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -11,18 +11,24 @@
#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/STLExtras.h"
-#include <climits>
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <limits>
#include <memory>
+#include <string>
+#include <vector>
namespace clang {
-class DiagnosticsEngine;
-class TextDiagnosticBuffer;
class FileEntry;
+class LangOptions;
+class SourceManager;
+class TextDiagnosticBuffer;
/// VerifyDiagnosticConsumer - Create a diagnostic client which will use
/// markers in the input source to check that all the emitted diagnostics match
@@ -153,7 +159,7 @@ public:
public:
/// Constant representing n or more matches.
- static const unsigned MaxCount = UINT_MAX;
+ static const unsigned MaxCount = std::numeric_limits<unsigned>::max();
SourceLocation DirectiveLoc;
SourceLocation DiagnosticLoc;
@@ -161,7 +167,9 @@ public:
unsigned Min, Max;
bool MatchAnyLine;
- virtual ~Directive() { }
+ Directive(const Directive &) = delete;
+ Directive &operator=(const Directive &) = delete;
+ virtual ~Directive() = default;
// Returns true if directive text is valid.
// Otherwise returns false and populates E.
@@ -173,22 +181,17 @@ public:
protected:
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
- : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
- Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
- assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
- assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
- "DiagnosticLoc is invalid!");
+ : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
+ Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
+ assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
+ assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
+ "DiagnosticLoc is invalid!");
}
-
- private:
- Directive(const Directive &) = delete;
- void operator=(const Directive &) = delete;
};
- typedef std::vector<std::unique_ptr<Directive>> DirectiveList;
+ using DirectiveList = std::vector<std::unique_ptr<Directive>>;
/// ExpectedData - owns directive objects and deletes on destructor.
- ///
struct ExpectedData {
DirectiveList Errors;
DirectiveList Warnings;
@@ -215,14 +218,15 @@ private:
DiagnosticConsumer *PrimaryClient;
std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner;
std::unique_ptr<TextDiagnosticBuffer> Buffer;
- const Preprocessor *CurrentPreprocessor;
- const LangOptions *LangOpts;
- SourceManager *SrcManager;
- unsigned ActiveSourceFiles;
+ const Preprocessor *CurrentPreprocessor = nullptr;
+ const LangOptions *LangOpts = nullptr;
+ SourceManager *SrcManager = nullptr;
+ unsigned ActiveSourceFiles = 0;
DirectiveStatus Status;
ExpectedData ED;
void CheckDiagnostics();
+
void setSourceManager(SourceManager &SM) {
assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");
SrcManager = &SM;
@@ -231,20 +235,24 @@ private:
// These facilities are used for validation in debug builds.
class UnparsedFileStatus {
llvm::PointerIntPair<const FileEntry *, 1, bool> Data;
+
public:
UnparsedFileStatus(const FileEntry *File, bool FoundDirectives)
- : Data(File, FoundDirectives) {}
+ : Data(File, FoundDirectives) {}
+
const FileEntry *getFile() const { return Data.getPointer(); }
bool foundDirectives() const { return Data.getInt(); }
};
- typedef llvm::DenseMap<FileID, const FileEntry *> ParsedFilesMap;
- typedef llvm::DenseMap<FileID, UnparsedFileStatus> UnparsedFilesMap;
+
+ using ParsedFilesMap = llvm::DenseMap<FileID, const FileEntry *>;
+ using UnparsedFilesMap = llvm::DenseMap<FileID, UnparsedFileStatus>;
+
ParsedFilesMap ParsedFiles;
UnparsedFilesMap UnparsedFiles;
public:
/// Create a new verifying diagnostic client, which will issue errors to
- /// the currently-attached diagnostic client when a diagnostic does not match
+ /// the currently-attached diagnostic client when a diagnostic does not match
/// what is expected (as indicated in the source file).
VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
~VerifyDiagnosticConsumer() override;
@@ -265,7 +273,7 @@ public:
IsUnparsedNoDirectives
};
- /// \brief Update lists of parsed and unparsed files.
+ /// Update lists of parsed and unparsed files.
void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS);
bool HandleComment(Preprocessor &PP, SourceRange Comment) override;
@@ -274,6 +282,6 @@ public:
const Diagnostic &Info) override;
};
-} // end namspace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
diff --git a/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h b/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h
index 031ee7df70ae..2e6b7b5076bb 100644
--- a/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h
+++ b/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h
@@ -15,9 +15,18 @@
#ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H
#define LLVM_CLANG_FRONTENDTOOL_UTILS_H
+#include <memory>
+
namespace clang {
class CompilerInstance;
+class FrontendAction;
+
+/// Construct the FrontendAction of a compiler invocation based on the
+/// options specified for the compiler invocation.
+///
+/// \return - The created FrontendAction object
+std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &CI);
/// ExecuteCompilerInvocation - Execute the given actions described by the
/// compiler invocation object in the given compiler instance.
diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h b/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h
index 080f4cb4d097..6e11455661a0 100644
--- a/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h
@@ -1,4 +1,4 @@
-//===--- IndexDataConsumer.h - Abstract index data consumer ---------------===//
+//===--- IndexDataConsumer.h - Abstract index data consumer -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -42,23 +42,18 @@ public:
/// \returns true to continue indexing, or false to abort.
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
- FileID FID, unsigned Offset,
- ASTNodeInfo ASTNode);
+ SourceLocation Loc, ASTNodeInfo ASTNode);
/// \returns true to continue indexing, or false to abort.
virtual bool handleMacroOccurence(const IdentifierInfo *Name,
const MacroInfo *MI, SymbolRoleSet Roles,
- FileID FID, unsigned Offset);
+ SourceLocation Loc);
/// \returns true to continue indexing, or false to abort.
virtual bool handleModuleOccurence(const ImportDecl *ImportD,
- SymbolRoleSet Roles,
- FileID FID, unsigned Offset);
+ SymbolRoleSet Roles, SourceLocation Loc);
virtual void finish() {}
-
-private:
- virtual void _anchor();
};
} // namespace index
diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h b/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h
index 08f2839f37e8..068796141df8 100644
--- a/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h
+++ b/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h
@@ -1,4 +1,4 @@
-//===--- IndexSymbol.h - Types and functions for indexing symbols ---------===//
+//===- IndexSymbol.h - Types and functions for indexing symbols -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,6 +11,7 @@
#define LLVM_CLANG_INDEX_INDEXSYMBOL_H
#include "clang/Basic/LLVM.h"
+#include "clang/Lex/MacroInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/DataTypes.h"
@@ -89,30 +90,35 @@ enum class SymbolProperty : SymbolPropertySet {
static const unsigned SymbolPropertyBitNum = 8;
/// Set of roles that are attributed to symbol occurrences.
+///
+/// Low 9 bits of clang-c/include/Index.h CXSymbolRole mirrors this enum.
enum class SymbolRole : uint32_t {
Declaration = 1 << 0,
- Definition = 1 << 1,
- Reference = 1 << 2,
- Read = 1 << 3,
- Write = 1 << 4,
- Call = 1 << 5,
- Dynamic = 1 << 6,
- AddressOf = 1 << 7,
- Implicit = 1 << 8,
+ Definition = 1 << 1,
+ Reference = 1 << 2,
+ Read = 1 << 3,
+ Write = 1 << 4,
+ Call = 1 << 5,
+ Dynamic = 1 << 6,
+ AddressOf = 1 << 7,
+ Implicit = 1 << 8,
+ // FIXME: this is not mirrored in CXSymbolRole.
+ // Note that macro occurrences aren't currently supported in libclang.
+ Undefinition = 1 << 9, // macro #undef
// Relation roles.
- RelationChildOf = 1 << 9,
- RelationBaseOf = 1 << 10,
- RelationOverrideOf = 1 << 11,
- RelationReceivedBy = 1 << 12,
- RelationCalledBy = 1 << 13,
- RelationExtendedBy = 1 << 14,
- RelationAccessorOf = 1 << 15,
- RelationContainedBy = 1 << 16,
- RelationIBTypeOf = 1 << 17,
- RelationSpecializationOf = 1 << 18,
+ RelationChildOf = 1 << 10,
+ RelationBaseOf = 1 << 11,
+ RelationOverrideOf = 1 << 12,
+ RelationReceivedBy = 1 << 13,
+ RelationCalledBy = 1 << 14,
+ RelationExtendedBy = 1 << 15,
+ RelationAccessorOf = 1 << 16,
+ RelationContainedBy = 1 << 17,
+ RelationIBTypeOf = 1 << 18,
+ RelationSpecializationOf = 1 << 19,
};
-static const unsigned SymbolRoleBitNum = 19;
+static const unsigned SymbolRoleBitNum = 20;
typedef unsigned SymbolRoleSet;
/// Represents a relation to another symbol for a symbol occurrence.
@@ -133,6 +139,8 @@ struct SymbolInfo {
SymbolInfo getSymbolInfo(const Decl *D);
+SymbolInfo getSymbolInfoForMacro(const MacroInfo &MI);
+
bool isFunctionLocalSymbol(const Decl *D);
void applyForEachSymbolRole(SymbolRoleSet Roles,
diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexingAction.h b/contrib/llvm/tools/clang/include/clang/Index/IndexingAction.h
index fb703be4e5f5..0d09c403483d 100644
--- a/contrib/llvm/tools/clang/include/clang/Index/IndexingAction.h
+++ b/contrib/llvm/tools/clang/include/clang/Index/IndexingAction.h
@@ -1,4 +1,4 @@
-//===--- IndexingAction.h - Frontend index action -------------------------===//
+//===--- IndexingAction.h - Frontend index action ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,6 +11,7 @@
#define LLVM_CLANG_INDEX_INDEXINGACTION_H
#include "clang/Basic/LLVM.h"
+#include "clang/Lex/PPCallbacks.h"
#include "llvm/ADT/ArrayRef.h"
#include <memory>
@@ -38,25 +39,35 @@ struct IndexingOptions {
SystemSymbolFilterKind SystemSymbolFilter
= SystemSymbolFilterKind::DeclarationsOnly;
bool IndexFunctionLocals = false;
+ bool IndexImplicitInstantiation = false;
};
+/// Creates a frontend action that indexes all symbols (macros and AST decls).
/// \param WrappedAction another frontend action to wrap over or null.
std::unique_ptr<FrontendAction>
createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
IndexingOptions Opts,
std::unique_ptr<FrontendAction> WrappedAction);
-void indexASTUnit(ASTUnit &Unit,
- std::shared_ptr<IndexDataConsumer> DataConsumer,
+/// Recursively indexes all decls in the AST.
+/// Note that this does not index macros.
+void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
IndexingOptions Opts);
+/// Recursively indexes \p Decls.
+/// Note that this does not index macros.
void indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls,
- std::shared_ptr<IndexDataConsumer> DataConsumer,
- IndexingOptions Opts);
+ IndexDataConsumer &DataConsumer, IndexingOptions Opts);
+/// Creates a PPCallbacks that indexes macros and feeds macros to \p Consumer.
+/// The caller is responsible for calling `Consumer.setPreprocessor()`.
+std::unique_ptr<PPCallbacks> indexMacrosCallback(IndexDataConsumer &Consumer,
+ IndexingOptions Opts);
+
+/// Recursively indexes all top-level decls in the module.
+/// FIXME: make this index macros as well.
void indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,
- std::shared_ptr<IndexDataConsumer> DataConsumer,
- IndexingOptions Opts);
+ IndexDataConsumer &DataConsumer, IndexingOptions Opts);
} // namespace index
} // namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h b/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h
index 8c661bd63cd8..1ece321746a6 100644
--- a/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h
+++ b/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h
@@ -1,4 +1,4 @@
-//===- USRGeneration.h - Routines for USR generation ----------------------===//
+//===- USRGeneration.h - Routines for USR generation ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -25,33 +25,33 @@ static inline StringRef getUSRSpacePrefix() {
return "c:";
}
-/// \brief Generate a USR for a Decl, including the USR prefix.
+/// Generate a USR for a Decl, including the USR prefix.
/// \returns true if the results should be ignored, false otherwise.
bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf);
-/// \brief Generate a USR fragment for an Objective-C class.
+/// Generate a USR fragment for an Objective-C class.
void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
StringRef ExtSymbolDefinedIn = "",
StringRef CategoryContextExtSymbolDefinedIn = "");
-/// \brief Generate a USR fragment for an Objective-C class category.
+/// Generate a USR fragment for an Objective-C class category.
void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS,
StringRef ClsExtSymbolDefinedIn = "",
StringRef CatExtSymbolDefinedIn = "");
-/// \brief Generate a USR fragment for an Objective-C instance variable. The
+/// Generate a USR fragment for an Objective-C instance variable. The
/// complete USR can be created by concatenating the USR for the
/// encompassing class with this USR fragment.
void generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS);
-/// \brief Generate a USR fragment for an Objective-C method.
+/// Generate a USR fragment for an Objective-C method.
void generateUSRForObjCMethod(StringRef Sel, bool IsInstanceMethod,
raw_ostream &OS);
-/// \brief Generate a USR fragment for an Objective-C property.
+/// Generate a USR fragment for an Objective-C property.
void generateUSRForObjCProperty(StringRef Prop, bool isClassProp, raw_ostream &OS);
-/// \brief Generate a USR fragment for an Objective-C protocol.
+/// Generate a USR fragment for an Objective-C protocol.
void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
StringRef ExtSymbolDefinedIn = "");
@@ -62,7 +62,7 @@ void generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
/// Generate a USR fragment for an enum constant.
void generateUSRForEnumConstant(StringRef EnumConstantName, raw_ostream &OS);
-/// \brief Generate a USR for a macro, including the USR prefix.
+/// Generate a USR for a macro, including the USR prefix.
///
/// \returns true on error, false on success.
bool generateUSRForMacro(const MacroDefinitionRecord *MD,
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h b/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h
index 91c3b7811f07..87089fd7d50b 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h
@@ -18,14 +18,14 @@ namespace clang {
class IdentifierInfo;
class MacroInfo;
-
-/// \brief Callback handler that receives notifications when performing code
+
+/// Callback handler that receives notifications when performing code
/// completion within the preprocessor.
class CodeCompletionHandler {
public:
virtual ~CodeCompletionHandler();
-
- /// \brief Callback invoked when performing code completion for a preprocessor
+
+ /// Callback invoked when performing code completion for a preprocessor
/// directive.
///
/// This callback will be invoked when the preprocessor processes a '#' at the
@@ -34,23 +34,23 @@ public:
/// \param InConditional Whether we're inside a preprocessor conditional
/// already.
virtual void CodeCompleteDirective(bool InConditional) { }
-
- /// \brief Callback invoked when performing code completion within a block of
+
+ /// Callback invoked when performing code completion within a block of
/// code that was excluded due to preprocessor conditionals.
virtual void CodeCompleteInConditionalExclusion() { }
-
- /// \brief Callback invoked when performing code completion in a context
+
+ /// Callback invoked when performing code completion in a context
/// where the name of a macro is expected.
///
/// \param IsDefinition Whether this is the definition of a macro, e.g.,
/// in a \#define.
virtual void CodeCompleteMacroName(bool IsDefinition) { }
-
- /// \brief Callback invoked when performing code completion in a preprocessor
+
+ /// Callback invoked when performing code completion in a preprocessor
/// expression, such as the condition of an \#if or \#elif directive.
virtual void CodeCompletePreprocessorExpression() { }
-
- /// \brief Callback invoked when performing code completion inside a
+
+ /// Callback invoked when performing code completion inside a
/// function-like macro argument.
///
/// There will be another callback invocation after the macro arguments are
@@ -60,12 +60,12 @@ public:
MacroInfo *MacroInfo,
unsigned ArgumentIndex) { }
- /// \brief Callback invoked when performing code completion in a part of the
- /// file where we expect natural language, e.g., a comment, string, or
+ /// Callback invoked when performing code completion in a part of the
+ /// file where we expect natural language, e.g., a comment, string, or
/// \#error directive.
virtual void CodeCompleteNaturalLanguage() { }
};
-
+
}
#endif // LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
index dcd58f434fa2..55065b7d8547 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
@@ -24,7 +24,7 @@ class DirectoryEntry;
class FileEntry;
class HeaderSearch;
class Module;
-
+
/// DirectoryLookup - This class represents one entry in the search list that
/// specifies the search order for directories in \#include directives. It
/// represents either a directory, a framework, or a headermap.
@@ -54,14 +54,14 @@ private:
/// LookupType - This indicates whether this DirectoryLookup object is a
/// normal directory, a framework, or a headermap.
unsigned LookupType : 2;
-
- /// \brief Whether this is a header map used when building a framework.
+
+ /// Whether this is a header map used when building a framework.
unsigned IsIndexHeaderMap : 1;
- /// \brief Whether we've performed an exhaustive search for module maps
+ /// Whether we've performed an exhaustive search for module maps
/// within the subdirectories of this directory.
unsigned SearchedAllModuleMaps : 1;
-
+
public:
/// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
/// 'dir'.
@@ -118,11 +118,11 @@ public:
/// isHeaderMap - Return true if this is a header map, not a normal directory.
bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; }
- /// \brief Determine whether we have already searched this entire
+ /// Determine whether we have already searched this entire
/// directory for module maps.
bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; }
- /// \brief Specify whether we have already searched all of the subdirectories
+ /// Specify whether we have already searched all of the subdirectories
/// for module maps.
void setSearchedAllModuleMaps(bool SAMM) {
SearchedAllModuleMaps = SAMM;
@@ -134,16 +134,16 @@ public:
return (SrcMgr::CharacteristicKind)DirCharacteristic;
}
- /// \brief Whether this describes a system header directory.
+ /// Whether this describes a system header directory.
bool isSystemHeaderDirectory() const {
return getDirCharacteristic() != SrcMgr::C_User;
}
- /// \brief Whether this header map is building a framework or not.
- bool isIndexHeaderMap() const {
- return isHeaderMap() && IsIndexHeaderMap;
+ /// Whether this header map is building a framework or not.
+ bool isIndexHeaderMap() const {
+ return isHeaderMap() && IsIndexHeaderMap;
}
-
+
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
///
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h
index adf8e713e99e..d849bbd76188 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h
@@ -19,30 +19,30 @@ namespace clang {
class IdentifierInfo;
class Module;
-/// \brief Abstract interface for external sources of preprocessor
+/// Abstract interface for external sources of preprocessor
/// information.
///
-/// This abstract class allows an external sources (such as the \c ASTReader)
+/// This abstract class allows an external sources (such as the \c ASTReader)
/// to provide additional preprocessing information.
class ExternalPreprocessorSource {
public:
virtual ~ExternalPreprocessorSource();
-
- /// \brief Read the set of macros defined by this external macro source.
+
+ /// Read the set of macros defined by this external macro source.
virtual void ReadDefinedMacros() = 0;
-
- /// \brief Update an out-of-date identifier.
+
+ /// Update an out-of-date identifier.
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
- /// \brief Return the identifier associated with the given ID number.
+ /// Return the identifier associated with the given ID number.
///
/// The ID 0 is associated with the NULL identifier.
virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
- /// \brief Map a module ID to a module.
+ /// Map a module ID to a module.
virtual Module *getModule(unsigned ModuleID) = 0;
};
-
+
}
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
index 6b9dbfcd1e93..6bb0f58f2db9 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
@@ -46,13 +46,13 @@ class Module;
class Preprocessor;
class TargetInfo;
-/// \brief The preprocessor keeps track of this information for each
+/// The preprocessor keeps track of this information for each
/// file that is \#included.
struct HeaderFileInfo {
- /// \brief True if this is a \#import'd or \#pragma once file.
+ /// True if this is a \#import'd or \#pragma once file.
unsigned isImport : 1;
- /// \brief True if this is a \#pragma once file.
+ /// True if this is a \#pragma once file.
unsigned isPragmaOnce : 1;
/// DirInfo - Keep track of whether this is a system header, and if so,
@@ -61,22 +61,22 @@ struct HeaderFileInfo {
/// SrcMgr::CharacteristicKind.
unsigned DirInfo : 3;
- /// \brief Whether this header file info was supplied by an external source,
+ /// Whether this header file info was supplied by an external source,
/// and has not changed since.
unsigned External : 1;
- /// \brief Whether this header is part of a module.
+ /// Whether this header is part of a module.
unsigned isModuleHeader : 1;
- /// \brief Whether this header is part of the module that we are building.
+ /// Whether this header is part of the module that we are building.
unsigned isCompilingModuleHeader : 1;
- /// \brief Whether this structure is considered to already have been
+ /// Whether this structure is considered to already have been
/// "resolved", meaning that it was loaded from the external source.
unsigned Resolved : 1;
-
- /// \brief Whether this is a header inside a framework that is currently
- /// being built.
+
+ /// Whether this is a header inside a framework that is currently
+ /// being built.
///
/// When a framework is being built, the headers have not yet been placed
/// into the appropriate framework subdirectories, and therefore are
@@ -84,13 +84,13 @@ struct HeaderFileInfo {
/// those framework headers.
unsigned IndexHeaderMapHeader : 1;
- /// \brief Whether this file has been looked up as a header.
+ /// Whether this file has been looked up as a header.
unsigned IsValid : 1;
-
- /// \brief The number of times the file has been included already.
+
+ /// The number of times the file has been included already.
unsigned short NumIncludes = 0;
- /// \brief The ID number of the controlling macro.
+ /// 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
@@ -107,43 +107,43 @@ struct HeaderFileInfo {
/// external storage.
const IdentifierInfo *ControllingMacro = nullptr;
- /// \brief If this header came from a framework include, this is the name
+ /// 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),
+ : 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
+ /// Retrieve the controlling macro for this header file, if
/// any.
const IdentifierInfo *
getControllingMacro(ExternalPreprocessorSource *External);
- /// \brief Determine whether this is a non-default header file info, e.g.,
+ /// Determine whether this is a non-default header file info, e.g.,
/// it corresponds to an actual header we've included or tried to include.
bool isNonDefault() const {
- return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
+ return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
ControllingMacroID;
}
};
-/// \brief An external source of header file information, which may supply
+/// An external source of header file information, which may supply
/// information about header files already included.
class ExternalHeaderFileInfoSource {
public:
virtual ~ExternalHeaderFileInfoSource();
-
- /// \brief Retrieve the header file information for the given file entry.
+
+ /// Retrieve the header file information for the given file entry.
///
/// \returns Header file information for the given file entry, with the
- /// \c External bit set. If the file entry is not known, return a
+ /// \c External bit set. If the file entry is not known, return a
/// default-constructed \c HeaderFileInfo.
virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
};
-
-/// \brief Encapsulates the information needed to find the file referenced
+
+/// Encapsulates the information needed to find the file referenced
/// by a \#include or \#include_next, (sub-)framework lookup, etc.
class HeaderSearch {
friend class DirectoryLookup;
@@ -159,7 +159,7 @@ class HeaderSearch {
bool IsUserSpecifiedSystemFramework;
};
- /// \brief Header-search options used to initialize this header search.
+ /// Header-search options used to initialize this header search.
std::shared_ptr<HeaderSearchOptions> HSOpts;
DiagnosticsEngine &Diags;
@@ -176,7 +176,7 @@ class HeaderSearch {
unsigned SystemDirIdx = 0;
bool NoCurDirSearch = false;
- /// \brief \#include prefixes for which the 'system header' property is
+ /// \#include prefixes for which the 'system header' property is
/// overridden.
///
/// For a \#include "x" or \#include \<x> directive, the last string in this
@@ -184,10 +184,10 @@ class HeaderSearch {
/// a system header.
std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes;
- /// \brief The path to the module cache.
+ /// The path to the module cache.
std::string ModuleCachePath;
-
- /// \brief All of the preprocessor-specific data about files that are
+
+ /// All of the preprocessor-specific data about files that are
/// included, indexed by the FileEntry's UID.
mutable std::vector<HeaderFileInfo> FileInfo;
@@ -215,7 +215,7 @@ class HeaderSearch {
};
llvm::StringMap<LookupFileCacheInfo, llvm::BumpPtrAllocator> LookupFileCache;
- /// \brief Collection mapping a framework or subframework
+ /// Collection mapping a framework or subframework
/// name like "Carbon" to the Carbon.framework directory.
llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap;
@@ -230,28 +230,28 @@ class HeaderSearch {
/// headermaps. This vector owns the headermap.
std::vector<std::pair<const FileEntry *, const HeaderMap *>> HeaderMaps;
- /// \brief The mapping between modules and headers.
+ /// The mapping between modules and headers.
mutable ModuleMap ModMap;
-
- /// \brief Describes whether a given directory has a module map in it.
+
+ /// Describes whether a given directory has a module map in it.
llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap;
- /// \brief Set of module map files we've already loaded, and a flag indicating
+ /// Set of module map files we've already loaded, and a flag indicating
/// whether they were valid or not.
llvm::DenseMap<const FileEntry *, bool> LoadedModuleMaps;
- /// \brief Uniqued set of framework names, which is used to track which
+ /// Uniqued set of framework names, which is used to track which
/// headers were included as framework headers.
llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames;
-
- /// \brief Entity used to resolve the identifier IDs of controlling
+
+ /// Entity used to resolve the identifier IDs of controlling
/// macros into IdentifierInfo pointers, and keep the identifire up to date,
/// as needed.
ExternalPreprocessorSource *ExternalLookup = nullptr;
- /// \brief Entity used to look up stored header file information.
+ /// Entity used to look up stored header file information.
ExternalHeaderFileInfoSource *ExternalSource = nullptr;
-
+
// Various statistics we track for performance analysis.
unsigned NumIncluded = 0;
unsigned NumMultiIncludeFileOptzn = 0;
@@ -266,18 +266,20 @@ public:
HeaderSearch &operator=(const HeaderSearch &) = delete;
~HeaderSearch();
- /// \brief Retrieve the header-search options with which this header search
+ /// Retrieve the header-search options with which this header search
/// was initialized.
HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; }
-
+
FileManager &getFileMgr() const { return FileMgr; }
- /// \brief Interface for setting the file search paths.
+ DiagnosticsEngine &getDiags() const { return Diags; }
+
+ /// Interface for setting the file search paths.
void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
unsigned angledDirIdx, unsigned systemDirIdx,
bool noCurDirSearch) {
assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
- "Directory indicies are unordered");
+ "Directory indices are unordered");
SearchDirs = dirs;
AngledDirIdx = angledDirIdx;
SystemDirIdx = systemDirIdx;
@@ -285,7 +287,7 @@ public:
//LookupFileCache.clear();
}
- /// \brief Add an additional search path.
+ /// Add an additional search path.
void AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
SearchDirs.insert(SearchDirs.begin() + idx, dir);
@@ -294,17 +296,17 @@ public:
SystemDirIdx++;
}
- /// \brief Set the list of system header prefixes.
+ /// Set the list of system header prefixes.
void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) {
SystemHeaderPrefixes.assign(P.begin(), P.end());
}
- /// \brief Checks whether the map exists or not.
+ /// Checks whether the map exists or not.
bool HasIncludeAliasMap() const { return (bool)IncludeAliases; }
- /// \brief Map the source include name to the dest include name.
+ /// Map the source include name to the dest include name.
///
- /// The Source should include the angle brackets or quotes, the dest
+ /// The Source should include the angle brackets or quotes, the dest
/// should not. This allows for distinction between <> and "" headers.
void AddIncludeAlias(StringRef Source, StringRef Dest) {
if (!IncludeAliases)
@@ -326,20 +328,20 @@ public:
return {};
}
- /// \brief Set the path to the module cache.
+ /// Set the path to the module cache.
void setModuleCachePath(StringRef CachePath) {
ModuleCachePath = CachePath;
}
-
- /// \brief Retrieve the path to the module cache.
+
+ /// Retrieve the path to the module cache.
StringRef getModuleCachePath() const { return ModuleCachePath; }
- /// \brief Consider modules when including files from this directory.
+ /// Consider modules when including files from this directory.
void setDirectoryHasModuleMap(const DirectoryEntry* Dir) {
DirectoryHasModuleMap[Dir] = true;
}
-
- /// \brief Forget everything we know about headers so far.
+
+ /// Forget everything we know about headers so far.
void ClearFileInfo() {
FileInfo.clear();
}
@@ -351,17 +353,17 @@ public:
ExternalPreprocessorSource *getExternalLookup() const {
return ExternalLookup;
}
-
- /// \brief Set the external source of header information.
+
+ /// Set the external source of header information.
void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
ExternalSource = ES;
}
-
- /// \brief Set the target information for the header search, if not
+
+ /// Set the target information for the header search, if not
/// already known.
void setTarget(const TargetInfo &Target);
-
- /// \brief Given a "foo" or \<foo> reference, look up the indicated file,
+
+ /// Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure.
///
/// \returns If successful, this returns 'UsedDir', the DirectoryLookup member
@@ -399,7 +401,7 @@ public:
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool *IsMapped, bool SkipCache = false, bool BuildSystemModule = false);
- /// \brief Look up a subframework for the specified \#include file.
+ /// Look up a subframework for the specified \#include file.
///
/// For example, if \#include'ing <HIToolbox/HIToolbox.h> from
/// within ".../Carbon.framework/Headers/Carbon.h", check to see if
@@ -410,13 +412,13 @@ public:
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
- /// \brief Look up the specified framework name in our framework cache.
+ /// Look up the specified framework name in our framework cache.
/// \returns The DirectoryEntry it is in if we know, null otherwise.
FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) {
return FrameworkMap[FWName];
}
- /// \brief Mark the specified file as a target of of a \#include,
+ /// Mark the specified file as a target of a \#include,
/// \#include_next, or \#import directive.
///
/// \return false if \#including the file will have no effect or true
@@ -425,13 +427,13 @@ public:
bool isImport, bool ModulesEnabled,
Module *CorrespondingModule);
- /// \brief Return whether the specified file is a normal header,
+ /// Return whether the specified file is a normal header,
/// a system header, or a C++ friendly system header.
SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
}
- /// \brief Mark the specified file as a "once only" file, e.g. due to
+ /// Mark the specified file as a "once only" file, e.g. due to
/// \#pragma once.
void MarkFileIncludeOnce(const FileEntry *File) {
HeaderFileInfo &FI = getFileInfo(File);
@@ -439,24 +441,24 @@ public:
FI.isPragmaOnce = true;
}
- /// \brief Mark the specified file as a system header, e.g. due to
+ /// Mark the specified file as a system header, e.g. due to
/// \#pragma GCC system_header.
void MarkFileSystemHeader(const FileEntry *File) {
getFileInfo(File).DirInfo = SrcMgr::C_System;
}
- /// \brief Mark the specified file as part of a module.
+ /// Mark the specified file as part of a module.
void MarkFileModuleHeader(const FileEntry *File,
ModuleMap::ModuleHeaderRole Role,
bool IsCompiledModuleHeader);
- /// \brief Increment the count for the number of times the specified
+ /// Increment the count for the number of times the specified
/// FileEntry has been entered.
void IncrementIncludeCount(const FileEntry *File) {
++getFileInfo(File).NumIncludes;
}
- /// \brief Mark the specified file as having a controlling macro.
+ /// Mark the specified file as having a controlling macro.
///
/// This is used by the multiple-include optimization to eliminate
/// no-op \#includes.
@@ -465,12 +467,12 @@ public:
getFileInfo(File).ControllingMacro = ControllingMacro;
}
- /// \brief Return true if this is the first time encountering this header.
+ /// Return true if this is the first time encountering this header.
bool FirstTimeLexingFile(const FileEntry *File) {
return getFileInfo(File).NumIncludes == 1;
}
- /// \brief Determine whether this file is intended to be safe from
+ /// Determine whether this file is intended to be safe from
/// multiple inclusions, e.g., it has \#pragma once or a controlling
/// macro.
///
@@ -481,10 +483,10 @@ public:
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
- /// \brief Get filenames for all registered header maps.
+ /// Get filenames for all registered header maps.
void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const;
- /// \brief Retrieve the name of the cached module file that should be used
+ /// 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.
@@ -493,7 +495,7 @@ public:
/// or an empty string if this module does not correspond to any module file.
std::string getCachedModuleFileName(Module *Module);
- /// \brief Retrieve the name of the prebuilt module file that should be used
+ /// 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.
@@ -506,7 +508,7 @@ public:
std::string getPrebuiltModuleFileName(StringRef ModuleName,
bool FileMapOnly = false);
- /// \brief Retrieve the name of the (to-be-)cached module file that should
+ /// 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.
@@ -519,7 +521,7 @@ public:
std::string getCachedModuleFileName(StringRef ModuleName,
StringRef ModuleMapPath);
- /// \brief Lookup a module Search for a module with the given name.
+ /// Lookup a module Search for a module with the given name.
///
/// \param ModuleName The name of the module we're looking for.
///
@@ -527,17 +529,21 @@ public:
/// search directories to produce a module definition. If not, this lookup
/// will only return an already-known module.
///
+ /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps
+ /// in subdirectories.
+ ///
/// \returns The module with the given name.
- Module *lookupModule(StringRef ModuleName, bool AllowSearch = true);
+ Module *lookupModule(StringRef ModuleName, bool AllowSearch = true,
+ bool AllowExtraModuleMapSearch = false);
- /// \brief Try to find a module map file in the given directory, returning
+ /// Try to find a module map file in the given directory, returning
/// \c nullptr if none is found.
const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir,
bool IsFramework);
-
+
void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
- /// \brief Determine whether there is a module map that may map the header
+ /// Determine whether there is a module map that may map the header
/// with the given file name to a (sub)module.
/// Always returns false if modules are disabled.
///
@@ -550,15 +556,15 @@ public:
/// header directories.
bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root,
bool IsSystem);
-
- /// \brief Retrieve the module that corresponds to the given file, if any.
+
+ /// Retrieve the module that corresponds to the given file, if any.
///
/// \param File The header that we wish to map to a module.
/// \param AllowTextual Whether we want to find textual headers too.
ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File,
bool AllowTextual = false) const;
- /// \brief Read the contents of the given module map file.
+ /// Read the contents of the given module map file.
///
/// \param File The module map file.
/// \param IsSystem Whether this file is in a system header directory.
@@ -575,16 +581,16 @@ public:
FileID ID = FileID(), unsigned *Offset = nullptr,
StringRef OriginalModuleMapFile = StringRef());
- /// \brief Collect the set of all known, top-level modules.
+ /// Collect the set of all known, top-level modules.
///
/// \param Modules Will be filled with the set of known, top-level modules.
void collectAllModules(SmallVectorImpl<Module *> &Modules);
- /// \brief Load all known, top-level system modules.
+ /// Load all known, top-level system modules.
void loadTopLevelSystemModules();
private:
- /// \brief Lookup a module with the given module name and search-name.
+ /// Lookup a module with the given module name and search-name.
///
/// \param ModuleName The name of the module we're looking for.
///
@@ -593,10 +599,14 @@ private:
/// but for compatibility with some buggy frameworks, additional attempts
/// may be made to find the module under a related-but-different search-name.
///
+ /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps
+ /// in subdirectories.
+ ///
/// \returns The module named ModuleName.
- Module *lookupModule(StringRef ModuleName, StringRef SearchName);
+ Module *lookupModule(StringRef ModuleName, StringRef SearchName,
+ bool AllowExtraModuleMapSearch = false);
- /// \brief Retrieve a module with the given name, which may be part of the
+ /// Retrieve a module with the given name, which may be part of the
/// given framework.
///
/// \param Name The name of the module to retrieve.
@@ -607,15 +617,15 @@ private:
/// frameworks.
///
/// \returns The module, if found; otherwise, null.
- Module *loadFrameworkModule(StringRef Name,
+ Module *loadFrameworkModule(StringRef Name,
const DirectoryEntry *Dir,
bool IsSystem);
- /// \brief Load all of the module maps within the immediate subdirectories
+ /// Load all of the module maps within the immediate subdirectories
/// of the given search directory.
void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
- /// \brief Find and suggest a usable module for the given file.
+ /// Find and suggest a usable module for the given file.
///
/// \return \c true if the file can be used, \c false if we are not permitted to
/// find this file due to requirements from \p RequestingModule.
@@ -625,7 +635,7 @@ private:
ModuleMap::KnownHeader *SuggestedModule,
bool IsSystemHeaderDir);
- /// \brief Find and suggest a usable module for the given file, which is part of
+ /// Find and suggest a usable module for the given file, which is part of
/// the specified framework.
///
/// \return \c true if the file can be used, \c false if we are not permitted to
@@ -634,7 +644,7 @@ private:
const FileEntry *File, StringRef FrameworkDir, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
- /// \brief Look up the file with the specified name and determine its owning
+ /// Look up the file with the specified name and determine its owning
/// module.
const FileEntry *
getFileAndSuggestModule(StringRef FileName, SourceLocation IncludeLoc,
@@ -643,19 +653,19 @@ private:
ModuleMap::KnownHeader *SuggestedModule);
public:
- /// \brief Retrieve the module map.
+ /// Retrieve the module map.
ModuleMap &getModuleMap() { return ModMap; }
-
- /// \brief Retrieve the module map.
+
+ /// Retrieve the module map.
const ModuleMap &getModuleMap() const { return ModMap; }
-
+
unsigned header_file_size() const { return FileInfo.size(); }
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry,
+ /// Return the HeaderFileInfo structure for the specified FileEntry,
/// in preparation for updating it in some way.
HeaderFileInfo &getFileInfo(const FileEntry *FE);
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry,
+ /// Return the HeaderFileInfo structure for the specified FileEntry,
/// if it has ever been filled in.
/// \param WantExternal Whether the caller wants purely-external header file
/// info (where \p External is true).
@@ -691,10 +701,10 @@ public:
search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
- /// \brief Retrieve a uniqued framework name.
+ /// Retrieve a uniqued framework name.
StringRef getUniqueFrameworkName(StringRef Framework);
-
- /// \brief Suggest a path by which the specified file could be found, for
+
+ /// Suggest a path by which the specified file could be found, for
/// use in diagnostics to suggest a #include.
///
/// \param IsSystem If non-null, filled in to indicate whether the suggested
@@ -702,23 +712,32 @@ public:
std::string suggestPathToFileForDiagnostics(const FileEntry *File,
bool *IsSystem = nullptr);
+ /// Suggest a path by which the specified file could be found, for
+ /// use in diagnostics to suggest a #include.
+ ///
+ /// \param WorkingDir If non-empty, this will be prepended to search directory
+ /// paths that are relative.
+ std::string suggestPathToFileForDiagnostics(llvm::StringRef File,
+ llvm::StringRef WorkingDir,
+ bool *IsSystem = nullptr);
+
void PrintStats();
-
+
size_t getTotalMemory() const;
private:
- /// \brief Describes what happened when we tried to load a module map file.
+ /// Describes what happened when we tried to load a module map file.
enum LoadModuleMapResult {
- /// \brief The module map file had already been loaded.
+ /// The module map file had already been loaded.
LMM_AlreadyLoaded,
- /// \brief The module map file was loaded by this invocation.
+ /// The module map file was loaded by this invocation.
LMM_NewlyLoaded,
- /// \brief There is was directory with the given name.
+ /// There is was directory with the given name.
LMM_NoDirectory,
- /// \brief There was either no module map file or the module map file was
+ /// There was either no module map file or the module map file was
/// invalid.
LMM_InvalidModuleMap
};
@@ -729,7 +748,7 @@ private:
FileID ID = FileID(),
unsigned *Offset = nullptr);
- /// \brief Try to load the module map file in the given directory.
+ /// Try to load the module map file in the given directory.
///
/// \param DirName The name of the directory where we will look for a module
/// map file.
@@ -741,7 +760,7 @@ private:
LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem,
bool IsFramework);
- /// \brief Try to load the module map file in the given directory.
+ /// Try to load the module map file in the given directory.
///
/// \param Dir The directory where we will look for a module map file.
/// \param IsSystem Whether this is a system header directory.
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
index 937ad9863db3..e5b52b30323f 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
@@ -14,7 +14,7 @@
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
-#include <cstdint>
+#include <cstdint>
#include <string>
#include <vector>
#include <map>
@@ -36,7 +36,7 @@ enum IncludeDirGroup {
Angled,
/// Like Angled, but marks header maps used when building frameworks.
- IndexHeaderMap,
+ IndexHeaderMap,
/// Like Angled, but marks system directories.
System,
@@ -70,7 +70,7 @@ public:
std::string Path;
frontend::IncludeDirGroup Group;
unsigned IsFramework : 1;
-
+
/// IgnoreSysRoot - This is false if an absolute path should be treated
/// relative to the sysroot, or true if it should always be the absolute
/// path.
@@ -108,32 +108,32 @@ public:
/// etc.).
std::string ResourceDir;
- /// \brief The directory used for the module cache.
+ /// The directory used for the module cache.
std::string ModuleCachePath;
- /// \brief The directory used for a user build.
+ /// The directory used for a user build.
std::string ModuleUserBuildPath;
- /// \brief The mapping of module names to prebuilt module files.
+ /// 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.
+ /// The directories used to load prebuilt module files.
std::vector<std::string> PrebuiltModulePaths;
/// The module/pch container format.
std::string ModuleFormat;
- /// \brief Whether we should disable the use of the hash string within the
+ /// Whether we should disable the use of the hash string within the
/// module cache.
///
/// Note: Only used for testing!
unsigned DisableModuleHash : 1;
- /// \brief Implicit module maps. This option is enabld by default when
+ /// Implicit module maps. This option is enabld by default when
/// modules is enabled.
unsigned ImplicitModuleMaps : 1;
- /// \brief Set the 'home directory' of a module map file to the current
+ /// Set the 'home directory' of a module map file to the current
/// working directory (or the home directory of the module map file that
/// contained the 'extern module' directive importing this module map file
/// if any) rather than the directory containing the module map file.
@@ -142,7 +142,7 @@ public:
/// file.
unsigned ModuleMapFileHomeIsCwd : 1;
- /// \brief The interval (in seconds) between pruning operations.
+ /// The interval (in seconds) between pruning operations.
///
/// This operation is expensive, because it requires Clang to walk through
/// the directory structure of the module cache, stat()'ing and removing
@@ -151,7 +151,7 @@ public:
/// The default value is large, e.g., the operation runs once a week.
unsigned ModuleCachePruneInterval = 7 * 24 * 60 * 60;
- /// \brief The time (in seconds) after which an unused module file will be
+ /// The time (in seconds) after which an unused module file will be
/// considered unused and will, therefore, be pruned.
///
/// When the module cache is pruned, any module file that has not been
@@ -160,17 +160,17 @@ public:
/// regenerated often.
unsigned ModuleCachePruneAfter = 31 * 24 * 60 * 60;
- /// \brief The time in seconds when the build session started.
+ /// 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 = 0;
- /// \brief The set of macro names that should be ignored for the purposes
+ /// The set of macro names that should be ignored for the purposes
/// of computing the module hash.
llvm::SmallSetVector<llvm::CachedHashString, 16> ModulesIgnoreMacros;
- /// \brief The set of user-provided virtual filesystem overlay files.
+ /// The set of user-provided virtual filesystem overlay files.
std::vector<std::string> VFSOverlayFiles;
/// Include the compiler builtin includes.
@@ -188,12 +188,12 @@ public:
/// Whether header search information should be output as for -v.
unsigned Verbose : 1;
- /// \brief If true, skip verifying input files used by modules if the
+ /// If true, skip verifying input files used by modules if the
/// module was already verified during this build session (see
/// \c BuildSessionTimestamp).
unsigned ModulesValidateOncePerBuildSession : 1;
- /// \brief Whether to validate system input files when a module is loaded.
+ /// Whether to validate system input files when a module is loaded.
unsigned ModulesValidateSystemHeaders : 1;
/// Whether the module includes debug information (-gmodules).
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
index d58849654cb8..624151ef877b 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
@@ -57,10 +57,10 @@ enum ConflictMarkerKind {
/// PreprocessorOptions::PrecompiledPreambleBytes.
/// The preamble includes the BOM, if any.
struct PreambleBounds {
- /// \brief Size of the preamble in bytes.
+ /// Size of the preamble in bytes.
unsigned Size;
- /// \brief Whether the preamble ends at the start of a new line.
+ /// 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.
@@ -263,7 +263,7 @@ public:
return getSourceLocation(BufferPtr);
}
- /// \brief Return the current location in the buffer.
+ /// Return the current location in the buffer.
const char *getBufferLocation() const { return BufferPtr; }
/// Stringify - Convert the specified string into a C string by i) escaping
@@ -322,29 +322,39 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
- /// \brief Relex the token at the specified location.
+ /// Relex the token at the specified location.
/// \returns true if there was a failure, false on success.
static bool getRawToken(SourceLocation Loc, Token &Result,
const SourceManager &SM,
const LangOptions &LangOpts,
bool IgnoreWhiteSpace = false);
- /// \brief Given a location any where in a source buffer, find the location
+ /// Given a location any where in a source buffer, find the location
/// that corresponds to the beginning of the token in which the original
/// source location lands.
static SourceLocation GetBeginningOfToken(SourceLocation Loc,
const SourceManager &SM,
const LangOptions &LangOpts);
+ /// Get the physical length (including trigraphs and escaped newlines) of the
+ /// first \p Characters characters of the token starting at TokStart.
+ static unsigned getTokenPrefixLength(SourceLocation TokStart,
+ unsigned Characters,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
/// AdvanceToTokenCharacter - If the current SourceLocation specifies a
/// location at the start of a token, return a new location that specifies a
/// character within the token. This handles trigraphs and escaped newlines.
static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
- unsigned Character,
+ unsigned Characters,
const SourceManager &SM,
- const LangOptions &LangOpts);
+ const LangOptions &LangOpts) {
+ return TokStart.getLocWithOffset(
+ getTokenPrefixLength(TokStart, Characters, SM, LangOpts));
+ }
- /// \brief Computes the source location just past the end of the
+ /// Computes the source location just past the end of the
/// token at this source location.
///
/// This routine can be used to produce a source location that
@@ -363,7 +373,7 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
- /// \brief Given a token range, produce a corresponding CharSourceRange that
+ /// Given a token range, produce a corresponding CharSourceRange that
/// is not a token range. This allows the source range to be used by
/// components that don't have access to the lexer and thus can't find the
/// end of the range for themselves.
@@ -383,7 +393,7 @@ public:
: Range;
}
- /// \brief Returns true if the given MacroID location points at the first
+ /// Returns true if the given MacroID location points at the first
/// token of the macro expansion.
///
/// \param MacroBegin If non-null and function returns true, it is set to
@@ -393,7 +403,7 @@ public:
const LangOptions &LangOpts,
SourceLocation *MacroBegin = nullptr);
- /// \brief Returns true if the given MacroID location points at the last
+ /// Returns true if the given MacroID location points at the last
/// token of the macro expansion.
///
/// \param MacroEnd If non-null and function returns true, it is set to
@@ -403,7 +413,7 @@ public:
const LangOptions &LangOpts,
SourceLocation *MacroEnd = nullptr);
- /// \brief Accepts a range and returns a character range with file locations.
+ /// Accepts a range and returns a character range with file locations.
///
/// Returns a null range if a part of the range resides inside a macro
/// expansion or the range does not reside on the same FileID.
@@ -433,13 +443,13 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
- /// \brief Returns a string for the source that the range encompasses.
+ /// Returns a string for the source that the range encompasses.
static StringRef getSourceText(CharSourceRange Range,
const SourceManager &SM,
const LangOptions &LangOpts,
bool *Invalid = nullptr);
- /// \brief Retrieve the name of the immediate macro expansion.
+ /// Retrieve the name of the immediate macro expansion.
///
/// This routine starts from a source location, and finds the name of the macro
/// responsible for its immediate expansion. It looks through any intervening
@@ -450,7 +460,7 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
- /// \brief Retrieve the name of the immediate macro expansion.
+ /// Retrieve the name of the immediate macro expansion.
///
/// This routine starts from a source location, and finds the name of the
/// macro responsible for its immediate expansion. It looks through any
@@ -470,7 +480,7 @@ public:
static StringRef getImmediateMacroNameForDiagnostics(
SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts);
- /// \brief Compute the preamble of the given file.
+ /// Compute the preamble of the given file.
///
/// The preamble of a file contains the initial comments, include directives,
/// and other preprocessor directives that occur before the code in this
@@ -496,7 +506,7 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
- /// \brief Checks that the given token is the first token that occurs after
+ /// 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
@@ -507,10 +517,10 @@ public:
const LangOptions &LangOpts,
bool SkipTrailingWhitespaceAndNewLine);
- /// \brief Returns true if the given character could appear in an identifier.
+ /// 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
+ /// Checks whether new line pointed by Str is preceded by escape
/// sequence.
static bool isNewLineEscaped(const char *BufferStart, const char *Str);
@@ -716,7 +726,7 @@ private:
/// invalid.
uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok);
- /// \brief Try to consume a UCN as part of an identifier at the current
+ /// Try to consume a UCN as part of an identifier at the current
/// location.
/// \param CurPtr Initially points to the range of characters in the source
/// buffer containing the '\'. Updated to point past the end of
@@ -730,7 +740,7 @@ private:
bool tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
Token &Result);
- /// \brief Try to consume an identifier character encoded in UTF-8.
+ /// Try to consume an identifier character encoded in UTF-8.
/// \param CurPtr Points to the start of the (potential) UTF-8 code unit
/// sequence. On success, updated to point past the end of it.
/// \return \c true if a UTF-8 sequence mapping to an acceptable identifier
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
index cc9223eb7dbb..3843a5afd2b0 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
@@ -50,7 +50,7 @@ class NumericLiteralParser {
unsigned radix;
- bool saw_exponent, saw_period, saw_ud_suffix;
+ bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix;
SmallString<32> UDSuffixBuf;
@@ -69,11 +69,16 @@ public:
bool isFloat128 : 1; // 1.0q
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
+ bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr
+ bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk
+
+ bool isFixedPointLiteral() const { return saw_fixed_point_suffix; }
+
bool isIntegerLiteral() const {
- return !saw_period && !saw_exponent;
+ return !saw_period && !saw_exponent && !isFixedPointLiteral();
}
bool isFloatingLiteral() const {
- return saw_period || saw_exponent;
+ return (saw_period || saw_exponent) && !isFixedPointLiteral();
}
bool hasUDSuffix() const {
@@ -105,6 +110,12 @@ public:
/// literal exactly, and false otherwise.
llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result);
+ /// GetFixedPointValue - Convert this numeric literal value into a
+ /// scaled integer that represents this value. Returns true if an overflow
+ /// occurred when calculating the integral part of the scaled integer or
+ /// calculating the digit sequence of the exponent.
+ bool GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale);
+
private:
void ParseNumberStartingWithZero(SourceLocation TokLoc);
@@ -112,7 +123,7 @@ private:
static bool isDigitSeparator(char C) { return C == '\''; }
- /// \brief Determine whether the sequence of characters [Start, End) contains
+ /// Determine whether the sequence of characters [Start, End) contains
/// any real digits (not digit separators).
bool containsDigits(const char *Start, const char *End) {
return Start != End && (Start + 1 != End || !isDigitSeparator(Start[0]));
@@ -120,7 +131,7 @@ private:
enum CheckSeparatorKind { CSK_BeforeDigits, CSK_AfterDigits };
- /// \brief Ensure that we don't have a digit separator here.
+ /// Ensure that we don't have a digit separator here.
void checkSeparator(SourceLocation TokLoc, const char *Pos,
CheckSeparatorKind IsAfterDigits);
@@ -197,7 +208,7 @@ class StringLiteralParser {
const LangOptions &Features;
const TargetInfo &Target;
DiagnosticsEngine *Diags;
-
+
unsigned MaxTokenLength;
unsigned SizeBound;
unsigned CharByteWidth;
@@ -219,7 +230,7 @@ public:
ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
init(StringToks);
}
-
+
bool hadError;
bool Pascal;
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
index a202550da3b3..853eee2fd779 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
@@ -27,7 +27,7 @@ namespace clang {
/// MacroArgs - An instance of this class captures information about
/// the formal arguments specified to a function-like macro invocation.
-class MacroArgs final
+class MacroArgs final
: private llvm::TrailingObjects<MacroArgs, Token> {
friend TrailingObjects;
@@ -43,7 +43,7 @@ class MacroArgs final
/// if in strict mode and the C99 varargs macro had only a ... argument, this
/// is false.
bool VarargsElided;
-
+
/// PreExpArgTokens - Pre-expanded tokens for arguments that need them. Empty
/// if not yet computed. This includes the EOF marker at the end of the
/// stream.
@@ -115,7 +115,7 @@ public:
/// 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
+ /// \code
/// #define F(a) a
/// #define V(a, ...) __VA_OPT__(a)
/// F() <-- returns false on this invocation.
@@ -123,7 +123,7 @@ public:
/// 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
@@ -135,8 +135,8 @@ public:
Preprocessor &PP, bool Charify,
SourceLocation ExpansionLocStart,
SourceLocation ExpansionLocEnd);
-
-
+
+
/// deallocate - This should only be called by the Preprocessor when managing
/// its freelist.
MacroArgs *deallocate();
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
index 3029294209ec..0cc1cb92e67e 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes.
+/// Defines the clang::MacroInfo and clang::MacroDirective classes.
//
//===----------------------------------------------------------------------===//
@@ -34,20 +34,20 @@ class Module;
class Preprocessor;
class SourceManager;
-/// \brief Encapsulates the data about a macro definition (e.g. its tokens).
+/// Encapsulates the data about a macro definition (e.g. its tokens).
///
/// There's an instance of this class for every #define.
class MacroInfo {
//===--------------------------------------------------------------------===//
// State set when the macro is defined.
- /// \brief The location the macro is defined.
+ /// The location the macro is defined.
SourceLocation Location;
- /// \brief The location of the last token in the macro.
+ /// The location of the last token in the macro.
SourceLocation EndLocation;
- /// \brief The list of arguments for a function-like macro.
+ /// The list of arguments for a function-like macro.
///
/// ParameterList points to the first of NumParameters pointers.
///
@@ -58,61 +58,61 @@ class MacroInfo {
/// \see ParameterList
unsigned NumParameters = 0;
- /// \brief This is the list of tokens that the macro is defined to.
+ /// This is the list of tokens that the macro is defined to.
SmallVector<Token, 8> ReplacementTokens;
- /// \brief Length in characters of the macro definition.
+ /// Length in characters of the macro definition.
mutable unsigned DefinitionLength;
mutable bool IsDefinitionLengthCached : 1;
- /// \brief True if this macro is function-like, false if it is object-like.
+ /// True if this macro is function-like, false if it is object-like.
bool IsFunctionLike : 1;
- /// \brief True if this macro is of the form "#define X(...)" or
+ /// True if this macro is of the form "#define X(...)" or
/// "#define X(Y,Z,...)".
///
/// The __VA_ARGS__ token should be replaced with the contents of "..." in an
/// invocation.
bool IsC99Varargs : 1;
- /// \brief True if this macro is of the form "#define X(a...)".
+ /// True if this macro is of the form "#define X(a...)".
///
/// The "a" identifier in the replacement list will be replaced with all
/// arguments of the macro starting with the specified one.
bool IsGNUVarargs : 1;
- /// \brief True if this macro requires processing before expansion.
+ /// True if this macro requires processing before expansion.
///
/// This is the case for builtin macros such as __LINE__, so long as they have
/// not been redefined, but not for regular predefined macros from the
/// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID).
bool IsBuiltinMacro : 1;
- /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__"
+ /// Whether this macro contains the sequence ", ## __VA_ARGS__"
bool HasCommaPasting : 1;
//===--------------------------------------------------------------------===//
// State that changes as the macro is used.
- /// \brief True if we have started an expansion of this macro already.
+ /// True if we have started an expansion of this macro already.
///
/// This disables recursive expansion, which would be quite bad for things
/// like \#define A A.
bool IsDisabled : 1;
- /// \brief True if this macro is either defined in the main file and has
+ /// True if this macro is either defined in the main file and has
/// been used, or if it is not defined in the main file.
///
/// This is used to emit -Wunused-macros diagnostics.
bool IsUsed : 1;
- /// \brief True if this macro can be redefined without emitting a warning.
+ /// True if this macro can be redefined without emitting a warning.
bool IsAllowRedefinitionsWithoutWarning : 1;
- /// \brief Must warn if the macro is unused at the end of translation unit.
+ /// Must warn if the macro is unused at the end of translation unit.
bool IsWarnIfUnused : 1;
- /// \brief Whether this macro was used as header guard.
+ /// Whether this macro was used as header guard.
bool UsedForHeaderGuard : 1;
// Only the Preprocessor gets to create and destroy these.
@@ -120,23 +120,23 @@ class MacroInfo {
~MacroInfo() = default;
public:
- /// \brief Return the location that the macro was defined at.
+ /// Return the location that the macro was defined at.
SourceLocation getDefinitionLoc() const { return Location; }
- /// \brief Set the location of the last token in the macro.
+ /// Set the location of the last token in the macro.
void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
- /// \brief Return the location of the last token in the macro.
+ /// Return the location of the last token in the macro.
SourceLocation getDefinitionEndLoc() const { return EndLocation; }
- /// \brief Get length in characters of the macro definition.
+ /// Get length in characters of the macro definition.
unsigned getDefinitionLength(const SourceManager &SM) const {
if (IsDefinitionLengthCached)
return DefinitionLength;
return getDefinitionLengthSlow(SM);
}
- /// \brief Return true if the specified macro definition is equal to
+ /// Return true if the specified macro definition is equal to
/// this macro in spelling, arguments, and whitespace.
///
/// \param Syntactically if true, the macro definitions can be identical even
@@ -146,21 +146,21 @@ public:
bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
bool Syntactically) const;
- /// \brief Set or clear the isBuiltinMacro flag.
+ /// Set or clear the isBuiltinMacro flag.
void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }
- /// \brief Set the value of the IsUsed flag.
+ /// Set the value of the IsUsed flag.
void setIsUsed(bool Val) { IsUsed = Val; }
- /// \brief Set the value of the IsAllowRedefinitionsWithoutWarning flag.
+ /// Set the value of the IsAllowRedefinitionsWithoutWarning flag.
void setIsAllowRedefinitionsWithoutWarning(bool Val) {
IsAllowRedefinitionsWithoutWarning = Val;
}
- /// \brief Set the value of the IsWarnIfUnused flag.
+ /// Set the value of the IsWarnIfUnused flag.
void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; }
- /// \brief Set the specified list of identifiers as the parameter list for
+ /// Set the specified list of identifiers as the parameter list for
/// this macro.
void setParameterList(ArrayRef<IdentifierInfo *> List,
llvm::BumpPtrAllocator &PPAllocator) {
@@ -174,7 +174,7 @@ public:
std::copy(List.begin(), List.end(), ParameterList);
}
- /// Parameters - The list of parameters for a function-like macro. This can
+ /// Parameters - The list of parameters for a function-like macro. This can
/// be empty, for, e.g. "#define X()".
using param_iterator = IdentifierInfo *const *;
bool param_empty() const { return NumParameters == 0; }
@@ -185,7 +185,7 @@ public:
return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters);
}
- /// \brief Return the parameter number of the specified identifier,
+ /// Return the parameter number of the specified identifier,
/// or -1 if the identifier is not a formal parameter identifier.
int getParameterNum(const IdentifierInfo *Arg) const {
for (param_iterator I = param_begin(), E = param_end(); I != E; ++I)
@@ -207,7 +207,7 @@ public:
bool isGNUVarargs() const { return IsGNUVarargs; }
bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }
- /// \brief Return true if this macro requires processing before expansion.
+ /// Return true if this macro requires processing before expansion.
///
/// This is true only for builtin macro, such as \__LINE__, whose values
/// are not given by fixed textual expansions. Regular predefined macros
@@ -218,19 +218,19 @@ public:
bool hasCommaPasting() const { return HasCommaPasting; }
void setHasCommaPasting() { HasCommaPasting = true; }
- /// \brief Return false if this macro is defined in the main file and has
+ /// Return false if this macro is defined in the main file and has
/// not yet been used.
bool isUsed() const { return IsUsed; }
- /// \brief Return true if this macro can be redefined without warning.
+ /// Return true if this macro can be redefined without warning.
bool isAllowRedefinitionsWithoutWarning() const {
return IsAllowRedefinitionsWithoutWarning;
}
- /// \brief Return true if we should emit a warning if the macro is unused.
+ /// Return true if we should emit a warning if the macro is unused.
bool isWarnIfUnused() const { return IsWarnIfUnused; }
- /// \brief Return the number of tokens that this macro expands to.
+ /// Return the number of tokens that this macro expands to.
unsigned getNumTokens() const { return ReplacementTokens.size(); }
const Token &getReplacementToken(unsigned Tok) const {
@@ -245,7 +245,7 @@ public:
bool tokens_empty() const { return ReplacementTokens.empty(); }
ArrayRef<Token> tokens() const { return ReplacementTokens; }
- /// \brief Add the specified token to the replacement text for the macro.
+ /// Add the specified token to the replacement text for the macro.
void AddTokenToBody(const Token &Tok) {
assert(
!IsDefinitionLengthCached &&
@@ -253,7 +253,7 @@ public:
ReplacementTokens.push_back(Tok);
}
- /// \brief Return true if this macro is enabled.
+ /// Return true if this macro is enabled.
///
/// In other words, that we are not currently in an expansion of this macro.
bool isEnabled() const { return !IsDisabled; }
@@ -268,7 +268,7 @@ public:
IsDisabled = true;
}
- /// \brief Determine whether this macro was used for a header guard.
+ /// Determine whether this macro was used for a header guard.
bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; }
void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; }
@@ -281,7 +281,7 @@ private:
unsigned getDefinitionLengthSlow(const SourceManager &SM) const;
};
-/// \brief Encapsulates changes to the "macros namespace" (the location where
+/// Encapsulates changes to the "macros namespace" (the location where
/// the macro name became active, the location where it was undefined, etc.).
///
/// MacroDirectives, associated with an identifier, are used to model the macro
@@ -297,20 +297,20 @@ public:
};
protected:
- /// \brief Previous macro directive for the same identifier, or nullptr.
+ /// Previous macro directive for the same identifier, or nullptr.
MacroDirective *Previous = nullptr;
SourceLocation Loc;
- /// \brief MacroDirective kind.
+ /// MacroDirective kind.
unsigned MDKind : 2;
- /// \brief True if the macro directive was loaded from a PCH file.
+ /// True if the macro directive was loaded from a PCH file.
unsigned IsFromPCH : 1;
// Used by VisibilityMacroDirective ----------------------------------------//
- /// \brief Whether the macro has public visibility (when described in a
+ /// Whether the macro has public visibility (when described in a
/// module).
unsigned IsPublic : 1;
@@ -322,16 +322,16 @@ public:
SourceLocation getLocation() const { return Loc; }
- /// \brief Set previous definition of the macro with the same name.
+ /// Set previous definition of the macro with the same name.
void setPrevious(MacroDirective *Prev) { Previous = Prev; }
- /// \brief Get previous definition of the macro with the same name.
+ /// Get previous definition of the macro with the same name.
const MacroDirective *getPrevious() const { return Previous; }
- /// \brief Get previous definition of the macro with the same name.
+ /// Get previous definition of the macro with the same name.
MacroDirective *getPrevious() { return Previous; }
- /// \brief Return true if the macro directive was loaded from a PCH file.
+ /// Return true if the macro directive was loaded from a PCH file.
bool isFromPCH() const { return IsFromPCH; }
void setIsFromPCH() { IsFromPCH = true; }
@@ -374,7 +374,7 @@ public:
}
};
- /// \brief Traverses the macro directives history and returns the next
+ /// Traverses the macro directives history and returns the next
/// macro definition directive along with info about its undefined location
/// (if there is one) and if it is public or private.
DefInfo getDefinition();
@@ -393,7 +393,7 @@ public:
}
MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }
- /// \brief Find macro definition active in the specified source location. If
+ /// Find macro definition active in the specified source location. If
/// this macro was not defined there, return NULL.
const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const;
@@ -402,7 +402,7 @@ public:
static bool classof(const MacroDirective *) { return true; }
};
-/// \brief A directive for a defined macro or a macro imported from a module.
+/// A directive for a defined macro or a macro imported from a module.
class DefMacroDirective : public MacroDirective {
MacroInfo *Info;
@@ -414,7 +414,7 @@ public:
explicit DefMacroDirective(MacroInfo *MI)
: DefMacroDirective(MI, MI->getDefinitionLoc()) {}
- /// \brief The data for the macro definition.
+ /// The data for the macro definition.
const MacroInfo *getInfo() const { return Info; }
MacroInfo *getInfo() { return Info; }
@@ -425,7 +425,7 @@ public:
static bool classof(const DefMacroDirective *) { return true; }
};
-/// \brief A directive for an undefined macro.
+/// A directive for an undefined macro.
class UndefMacroDirective : public MacroDirective {
public:
explicit UndefMacroDirective(SourceLocation UndefLoc)
@@ -440,7 +440,7 @@ public:
static bool classof(const UndefMacroDirective *) { return true; }
};
-/// \brief A directive for setting the module visibility of a macro.
+/// A directive for setting the module visibility of a macro.
class VisibilityMacroDirective : public MacroDirective {
public:
explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
@@ -448,7 +448,7 @@ public:
IsPublic = Public;
}
- /// \brief Determine whether this macro is part of the public API of its
+ /// Determine whether this macro is part of the public API of its
/// module.
bool isPublic() const { return IsPublic; }
@@ -478,7 +478,7 @@ MacroDirective::DefInfo::getPreviousDefinition() {
return DefDirective->getPrevious()->getDefinition();
}
-/// \brief Represents a macro directive exported by a module.
+/// Represents a macro directive exported by a module.
///
/// There's an instance of this class for every macro #define or #undef that is
/// the final directive for a macro name within a module. These entities also
@@ -557,7 +557,7 @@ public:
unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
};
-/// \brief A description of the current definition of a macro.
+/// A description of the current definition of a macro.
///
/// The definition of a macro comprises a set of (at least one) defining
/// entities, which are either local MacroDirectives or imported ModuleMacros.
@@ -571,12 +571,12 @@ public:
bool IsAmbiguous)
: LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
- /// \brief Determine whether there is a definition of this macro.
+ /// Determine whether there is a definition of this macro.
explicit operator bool() const {
return getLocalDirective() || !ModuleMacros.empty();
}
- /// \brief Get the MacroInfo that should be used for this definition.
+ /// Get the MacroInfo that should be used for this definition.
MacroInfo *getMacroInfo() const {
if (!ModuleMacros.empty())
return ModuleMacros.back()->getMacroInfo();
@@ -585,16 +585,16 @@ public:
return nullptr;
}
- /// \brief \c true if the definition is ambiguous, \c false otherwise.
+ /// \c true if the definition is ambiguous, \c false otherwise.
bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }
- /// \brief Get the latest non-imported, non-\#undef'd macro definition
+ /// Get the latest non-imported, non-\#undef'd macro definition
/// for this macro.
DefMacroDirective *getLocalDirective() const {
return LatestLocalAndAmbiguous.getPointer();
}
- /// \brief Get the active module macros for this macro.
+ /// Get the active module macros for this macro.
ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }
template <typename Fn> void forAllDefinitions(Fn F) const {
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
index 30ea583b71e0..05396dd20597 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the ModuleLoader interface, which is responsible for
+// This file defines the ModuleLoader interface, which is responsible for
// loading named modules.
//
//===----------------------------------------------------------------------===//
@@ -28,11 +28,11 @@ namespace clang {
class GlobalModuleIndex;
class IdentifierInfo;
-/// \brief A sequence of identifier/location pairs used to describe a particular
+/// A sequence of identifier/location pairs used to describe a particular
/// module or submodule, e.g., std.vector.
using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>;
-/// \brief Describes the result of attempting to load a module.
+/// Describes the result of attempting to load a module.
class ModuleLoadResult {
public:
enum LoadResultKind {
@@ -55,18 +55,18 @@ public:
operator Module *() const { return Storage.getPointer(); }
- /// \brief Determines whether the module, which failed to load, was
+ /// Determines whether the module, which failed to load, was
/// actually a submodule that we expected to see (based on implying the
/// submodule from header structure), but didn't materialize in the actual
/// module.
bool isMissingExpected() const { return Storage.getInt() == MissingExpected; }
- /// \brief Determines whether the module failed to load due to a configuration
+ /// Determines whether the module failed to load due to a configuration
/// mismatch with an explicitly-named .pcm file from the command line.
bool isConfigMismatch() const { return Storage.getInt() == ConfigMismatch; }
};
-/// \brief Abstract interface for a module loader.
+/// Abstract interface for a module loader.
///
/// This abstract interface describes a module loader, which is responsible
/// for resolving a module name (e.g., "std") to an actual module file, and
@@ -80,27 +80,27 @@ public:
: BuildingModule(BuildingModule) {}
virtual ~ModuleLoader();
-
- /// \brief Returns true if this instance is building a module.
+
+ /// Returns true if this instance is building a module.
bool buildingModule() const {
return BuildingModule;
}
- /// \brief Flag indicating whether this instance is building a module.
+ /// Flag indicating whether this instance is building a module.
void setBuildingModule(bool BuildingModuleFlag) {
BuildingModule = BuildingModuleFlag;
}
-
- /// \brief Attempt to load the given module.
+
+ /// Attempt to load the given module.
///
- /// This routine attempts to load the module described by the given
+ /// This routine attempts to load the module described by the given
/// parameters.
///
/// \param ImportLoc The location of the 'import' keyword.
///
/// \param Path The identifiers (and their locations) of the module
/// "path", e.g., "std.vector" would be split into "std" and "vector".
- ///
+ ///
/// \param Visibility The visibility provided for the names in the loaded
/// module.
///
@@ -108,7 +108,7 @@ public:
/// implicitly, due to the presence of an inclusion directive. Otherwise,
/// it is being loaded due to an import declaration.
///
- /// \returns If successful, returns the loaded module. Otherwise, returns
+ /// \returns If successful, returns the loaded module. Otherwise, returns
/// NULL to indicate that the module could not be loaded.
virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
ModuleIdPath Path,
@@ -125,12 +125,12 @@ public:
virtual void loadModuleFromSource(SourceLocation Loc, StringRef ModuleName,
StringRef Source) = 0;
- /// \brief Make the given module visible.
+ /// Make the given module visible.
virtual void makeModuleVisible(Module *Mod,
Module::NameVisibilityKind Visibility,
SourceLocation ImportLoc) = 0;
- /// \brief Load, create, or return global module.
+ /// Load, create, or return global module.
/// This function returns an existing global module index, if one
/// had already been loaded or created, or loads one if it
/// exists, or creates one if it doesn't exist.
@@ -177,7 +177,7 @@ public:
return false;
}
};
-
+
} // namespace clang
#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 41ed8e49b6c1..aa519891c1ce 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -41,13 +42,13 @@ class FileManager;
class HeaderSearch;
class SourceManager;
-/// \brief A mechanism to observe the actions of the module map parser as it
+/// A mechanism to observe the actions of the module map parser as it
/// reads module map files.
class ModuleMapCallbacks {
public:
virtual ~ModuleMapCallbacks() = default;
- /// \brief Called when a module map file has been read.
+ /// Called when a module map file has been read.
///
/// \param FileStart A SourceLocation referring to the start of the file's
/// contents.
@@ -56,19 +57,19 @@ public:
virtual void moduleMapFileRead(SourceLocation FileStart,
const FileEntry &File, bool IsSystem) {}
- /// \brief Called when a header is added during module map parsing.
+ /// Called when a header is added during module map parsing.
///
/// \param Filename The header file itself.
virtual void moduleMapAddHeader(StringRef Filename) {}
- /// \brief Called when an umbrella header is added during module map parsing.
+ /// Called when an umbrella header is added during module map parsing.
///
/// \param FileMgr FileManager instance
/// \param Header The umbrella header to collect.
virtual void moduleMapAddUmbrellaHeader(FileManager *FileMgr,
const FileEntry *Header) {}
};
-
+
class ModuleMap {
SourceManager &SourceMgr;
DiagnosticsEngine &Diags;
@@ -77,12 +78,12 @@ class ModuleMap {
HeaderSearch &HeaderInfo;
llvm::SmallVector<std::unique_ptr<ModuleMapCallbacks>, 1> Callbacks;
-
- /// \brief The directory used for Clang-supplied, builtin include headers,
+
+ /// The directory used for Clang-supplied, builtin include headers,
/// such as "stdint.h".
const DirectoryEntry *BuiltinIncludeDir = nullptr;
-
- /// \brief Language options used to parse the module map itself.
+
+ /// Language options used to parse the module map itself.
///
/// These are always simple C language options.
LangOptions MMapLangOpts;
@@ -95,22 +96,37 @@ class ModuleMap {
/// transferred if/when we create an enclosing module.
std::unique_ptr<Module> PendingGlobalModule;
- /// \brief The top-level modules that are known.
+ /// The top-level modules that are known.
llvm::StringMap<Module *> Modules;
- /// \brief The number of modules we have created in total.
+ /// Shadow modules created while building this module map.
+ llvm::SmallVector<Module*, 2> ShadowModules;
+
+ /// The number of modules we have created in total.
unsigned NumCreatedModules = 0;
+ /// In case a module has a export_as entry, it might have a pending link
+ /// name to be determined if that module is imported.
+ llvm::StringMap<llvm::StringSet<>> PendingLinkAsModule;
+
public:
- /// \brief Flags describing the role of a module header.
+ /// Use PendingLinkAsModule information to mark top level link names that
+ /// are going to be replaced by export_as aliases.
+ void resolveLinkAsDependencies(Module *Mod);
+
+ /// Make module to use export_as as the link dependency name if enough
+ /// information is available or add it to a pending list otherwise.
+ void addLinkAsDependency(Module *Mod);
+
+ /// Flags describing the role of a module header.
enum ModuleHeaderRole {
- /// \brief This header is normally included in the module.
+ /// This header is normally included in the module.
NormalHeader = 0x0,
- /// \brief This header is included but private.
+ /// This header is included but private.
PrivateHeader = 0x1,
- /// \brief This header is part of the module (for layering purposes) but
+ /// This header is part of the module (for layering purposes) but
/// should be textually included.
TextualHeader = 0x2,
@@ -128,7 +144,7 @@ public:
/// Convert a header role to a kind.
static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role);
- /// \brief A header that is known to reside within a given module,
+ /// A header that is known to reside within a given module,
/// whether it was included or excluded.
class KnownHeader {
llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
@@ -144,24 +160,24 @@ public:
return A.Storage != B.Storage;
}
- /// \brief Retrieve the module the header is stored in.
+ /// Retrieve the module the header is stored in.
Module *getModule() const { return Storage.getPointer(); }
- /// \brief The role of this header within the module.
+ /// The role of this header within the module.
ModuleHeaderRole getRole() const { return Storage.getInt(); }
- /// \brief Whether this header is available in the module.
+ /// Whether this header is available in the module.
bool isAvailable() const {
return getModule()->isAvailable();
}
- /// \brief Whether this header is accessible from the specified module.
+ /// Whether this header is accessible from the specified module.
bool isAccessibleFrom(Module *M) const {
return !(getRole() & PrivateHeader) ||
(M && M->getTopLevelModule() == getModule()->getTopLevelModule());
}
- // \brief Whether this known header is valid (i.e., it has an
+ // Whether this known header is valid (i.e., it has an
// associated module).
explicit operator bool() const {
return Storage.getPointer() != nullptr;
@@ -176,7 +192,7 @@ private:
using HeadersMap =
llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>;
- /// \brief Mapping from each header to the module that owns the contents of
+ /// Mapping from each header to the module that owns the contents of
/// that header.
HeadersMap Headers;
@@ -187,7 +203,7 @@ private:
mutable llvm::DenseMap<time_t, llvm::TinyPtrVector<Module*>>
LazyHeadersByModTime;
- /// \brief Mapping from directories with umbrella headers to the module
+ /// Mapping from directories with umbrella headers to the module
/// that is generated from the umbrella header.
///
/// This mapping is used to map headers that haven't explicitly been named
@@ -195,18 +211,27 @@ private:
/// header.
llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
- /// \brief The set of attributes that can be attached to a module.
+ /// A generation counter that is used to test whether modules of the
+ /// same name may shadow or are illegal redefinitions.
+ ///
+ /// Modules from earlier scopes may shadow modules from later ones.
+ /// Modules from the same scope may not have the same name.
+ unsigned CurrentModuleScopeID = 0;
+
+ llvm::DenseMap<Module *, unsigned> ModuleScopeIDs;
+
+ /// The set of attributes that can be attached to a module.
struct Attributes {
- /// \brief Whether this is a system module.
+ /// Whether this is a system module.
unsigned IsSystem : 1;
- /// \brief Whether this is an extern "C" module.
+ /// Whether this is an extern "C" module.
unsigned IsExternC : 1;
- /// \brief Whether this is an exhaustive set of configuration macros.
+ /// Whether this is an exhaustive set of configuration macros.
unsigned IsExhaustive : 1;
- /// \brief Whether files in this module can only include non-modular headers
+ /// Whether files in this module can only include non-modular headers
/// and headers from used modules.
unsigned NoUndeclaredIncludes : 1;
@@ -215,26 +240,26 @@ private:
NoUndeclaredIncludes(false) {}
};
- /// \brief A directory for which framework modules can be inferred.
+ /// A directory for which framework modules can be inferred.
struct InferredDirectory {
- /// \brief Whether to infer modules from this directory.
+ /// Whether to infer modules from this directory.
unsigned InferModules : 1;
- /// \brief The attributes to use for inferred modules.
+ /// The attributes to use for inferred modules.
Attributes Attrs;
- /// \brief If \c InferModules is non-zero, the module map file that allowed
+ /// If \c InferModules is non-zero, the module map file that allowed
/// inferred modules. Otherwise, nullptr.
const FileEntry *ModuleMapFile;
- /// \brief The names of modules that cannot be inferred within this
+ /// 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
+ /// A mapping from directories to information about inferring
/// framework modules from within those directories.
llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories;
@@ -244,11 +269,11 @@ private:
llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps;
- /// \brief Describes whether we haved parsed a particular file as a module
+ /// Describes whether we haved parsed a particular file as a module
/// map.
llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap;
- /// \brief Resolve the given export declaration into an actual export
+ /// Resolve the given export declaration into an actual export
/// declaration.
///
/// \param Mod The module in which we're resolving the export declaration.
@@ -260,11 +285,11 @@ private:
///
/// \returns The resolved export declaration, which will have a NULL pointer
/// if the export could not be resolved.
- Module::ExportDecl
+ Module::ExportDecl
resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved,
bool Complain) const;
- /// \brief Resolve the given module id to an actual module.
+ /// Resolve the given module id to an actual module.
///
/// \param Id The module-id to resolve.
///
@@ -278,8 +303,15 @@ private:
Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const;
/// Add an unresolved header to a module.
+ ///
+ /// \param Mod The module in which we're adding the unresolved header
+ /// directive.
+ /// \param Header The unresolved header directive.
+ /// \param NeedsFramework If Mod is not a framework but a missing header would
+ /// be found in case Mod was, set it to true. False otherwise.
void addUnresolvedHeader(Module *Mod,
- Module::UnresolvedHeaderDirective Header);
+ Module::UnresolvedHeaderDirective Header,
+ bool &NeedsFramework);
/// Look up the given header directive to find an actual header file.
///
@@ -287,14 +319,22 @@ private:
/// \param Header The header directive to resolve.
/// \param RelativePathName Filled in with the relative path name from the
/// module to the resolved header.
+ /// \param NeedsFramework If M is not a framework but a missing header would
+ /// be found in case M was, set it to true. False otherwise.
/// \return The resolved file, if any.
const FileEntry *findHeader(Module *M,
const Module::UnresolvedHeaderDirective &Header,
- SmallVectorImpl<char> &RelativePathName);
+ SmallVectorImpl<char> &RelativePathName,
+ bool &NeedsFramework);
/// Resolve the given header directive.
- void resolveHeader(Module *M,
- const Module::UnresolvedHeaderDirective &Header);
+ ///
+ /// \param M The module in which we're resolving the header directive.
+ /// \param Header The header directive to resolve.
+ /// \param NeedsFramework If M is not a framework but a missing header would
+ /// be found in case M was, set it to true. False otherwise.
+ void resolveHeader(Module *M, const Module::UnresolvedHeaderDirective &Header,
+ bool &NeedsFramework);
/// Attempt to resolve the specified header directive as naming a builtin
/// header.
@@ -302,14 +342,14 @@ private:
bool resolveAsBuiltinHeader(Module *M,
const Module::UnresolvedHeaderDirective &Header);
- /// \brief Looks up the modules that \p File corresponds to.
+ /// Looks up the modules that \p File corresponds to.
///
/// If \p File represents a builtin header within Clang's builtin include
/// directory, this also loads all of the module maps to see if it will get
/// associated with a specific module (e.g. in /usr/include).
HeadersMap::iterator findKnownHeader(const FileEntry *File);
- /// \brief Searches for a module whose umbrella directory contains \p File.
+ /// Searches for a module whose umbrella directory contains \p File.
///
/// \param File The header to search for.
///
@@ -318,11 +358,11 @@ private:
KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
- /// \brief Given that \p File is not in the Headers map, look it up within
+ /// Given that \p File is not in the Headers map, look it up within
/// umbrella directories and find or create a module for it.
KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File);
- /// \brief A convenience method to determine if \p File is (possibly nested)
+ /// A convenience method to determine if \p File is (possibly nested)
/// in an umbrella directory.
bool isHeaderInUmbrellaDirs(const FileEntry *File) {
SmallVector<const DirectoryEntry *, 2> IntermediateDirs;
@@ -333,7 +373,7 @@ private:
Attributes Attrs, Module *Parent);
public:
- /// \brief Construct a new module map.
+ /// Construct a new module map.
///
/// \param SourceMgr The source manager used to find module files and headers.
/// This source manager should be shared with the header-search mechanism,
@@ -348,32 +388,32 @@ public:
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo);
- /// \brief Destroy the module map.
+ /// Destroy the module map.
~ModuleMap();
- /// \brief Set the target information.
+ /// Set the target information.
void setTarget(const TargetInfo &Target);
- /// \brief Set the directory that contains Clang-supplied include
+ /// Set the directory that contains Clang-supplied include
/// files, such as our stdarg.h or tgmath.h.
void setBuiltinIncludeDir(const DirectoryEntry *Dir) {
BuiltinIncludeDir = Dir;
}
- /// \brief Get the directory that contains Clang-supplied include files.
+ /// Get the directory that contains Clang-supplied include files.
const DirectoryEntry *getBuiltinDir() const {
return BuiltinIncludeDir;
}
- /// \brief Is this a compiler builtin header?
+ /// Is this a compiler builtin header?
static bool isBuiltinHeader(StringRef FileName);
- /// \brief Add a module map callback.
+ /// Add a module map callback.
void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) {
Callbacks.push_back(std::move(Callback));
}
- /// \brief Retrieve the module that owns the given header file, if any.
+ /// Retrieve the module that owns the given header file, if any.
///
/// \param File The header file that is likely to be included.
///
@@ -387,7 +427,7 @@ public:
KnownHeader findModuleForHeader(const FileEntry *File,
bool AllowTextual = false);
- /// \brief Retrieve all the modules that contain the given header file. This
+ /// Retrieve all the modules that contain the given header file. This
/// may not include umbrella modules, nor information from external sources,
/// if they have not yet been inferred / loaded.
///
@@ -404,7 +444,7 @@ public:
/// Resolve all lazy header directives for the specified module.
void resolveHeaderDirectives(Module *Mod) const;
- /// \brief Reports errors if a module must not include a specific file.
+ /// Reports errors if a module must not include a specific file.
///
/// \param RequestingModule The module including a file.
///
@@ -423,23 +463,23 @@ public:
SourceLocation FilenameLoc, StringRef Filename,
const FileEntry *File);
- /// \brief Determine whether the given header is part of a module
+ /// Determine whether the given header is part of a module
/// marked 'unavailable'.
bool isHeaderInUnavailableModule(const FileEntry *Header) const;
- /// \brief Determine whether the given header is unavailable as part
+ /// Determine whether the given header is unavailable as part
/// of the specified module.
bool isHeaderUnavailableInModule(const FileEntry *Header,
const Module *RequestingModule) const;
- /// \brief Retrieve a module with the given name.
+ /// Retrieve a module with the given name.
///
/// \param Name The name of the module to look up.
///
/// \returns The named module, if known; otherwise, returns null.
Module *findModule(StringRef Name) const;
- /// \brief Retrieve a module with the given name using lexical name lookup,
+ /// Retrieve a module with the given name using lexical name lookup,
/// starting at the given context.
///
/// \param Name The name of the module to look up.
@@ -450,18 +490,18 @@ public:
/// \returns The named module, if known; otherwise, returns null.
Module *lookupModuleUnqualified(StringRef Name, Module *Context) const;
- /// \brief Retrieve a module with the given name within the given context,
+ /// Retrieve a module with the given name within the given context,
/// using direct (qualified) name lookup.
///
/// \param Name The name of the module to look up.
- ///
+ ///
/// \param Context The module for which we will look for a submodule. If
/// null, we will look for a top-level module.
///
/// \returns The named submodule, if known; otherwose, returns null.
Module *lookupModuleQualified(StringRef Name, Module *Context) const;
-
- /// \brief Find a new module or submodule, or create it if it does not already
+
+ /// Find a new module or submodule, or create it if it does not already
/// exist.
///
/// \param Name The name of the module to find or create.
@@ -479,7 +519,7 @@ public:
bool IsFramework,
bool IsExplicit);
- /// \brief Create a 'global module' for a C++ Modules TS module interface
+ /// 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.
@@ -487,7 +527,7 @@ public:
/// 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.
+ /// 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.
///
@@ -497,12 +537,30 @@ public:
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
Module *GlobalModule);
- /// \brief Infer the contents of a framework module map from the given
+ /// Infer the contents of a framework module map from the given
/// framework directory.
Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
bool IsSystem, Module *Parent);
- /// \brief Retrieve the module map file containing the definition of the given
+ /// Create a new top-level module that is shadowed by
+ /// \p ShadowingModule.
+ Module *createShadowedModule(StringRef Name, bool IsFramework,
+ Module *ShadowingModule);
+
+ /// Creates a new declaration scope for module names, allowing
+ /// previously defined modules to shadow definitions from the new scope.
+ ///
+ /// \note Module names from earlier scopes will shadow names from the new
+ /// scope, which is the opposite of how shadowing works for variables.
+ void finishModuleDeclarationScope() { CurrentModuleScopeID += 1; }
+
+ bool mayShadowNewModule(Module *ExistingModule) {
+ assert(!ExistingModule->Parent && "expected top-level module");
+ assert(ModuleScopeIDs.count(ExistingModule) && "unknown module");
+ return ModuleScopeIDs[ExistingModule] < CurrentModuleScopeID;
+ }
+
+ /// Retrieve the module map file containing the definition of the given
/// module.
///
/// \param Module The module whose module map file will be returned, if known.
@@ -511,7 +569,7 @@ public:
/// 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
+ /// Get the module map file that (along with the module name) uniquely
/// identifies this module.
///
/// The particular module that \c Name refers to may depend on how the module
@@ -524,7 +582,7 @@ public:
void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap);
- /// \brief Get any module map files other than getModuleMapFileForUniquing(M)
+ /// Get any module map files other than getModuleMapFileForUniquing(M)
/// that define submodules of a top-level module \p M. This is cheaper than
/// getting the module map file for each submodule individually, since the
/// expected number of results is very small.
@@ -539,7 +597,7 @@ public:
AdditionalModMaps[M].insert(ModuleMap);
}
- /// \brief Resolve all of the unresolved exports in the given module.
+ /// Resolve all of the unresolved exports in the given module.
///
/// \param Mod The module whose exports should be resolved.
///
@@ -549,7 +607,7 @@ public:
/// false otherwise.
bool resolveExports(Module *Mod, bool Complain);
- /// \brief Resolve all of the unresolved uses in the given module.
+ /// Resolve all of the unresolved uses in the given module.
///
/// \param Mod The module whose uses should be resolved.
///
@@ -559,7 +617,7 @@ public:
/// false otherwise.
bool resolveUses(Module *Mod, bool Complain);
- /// \brief Resolve all of the unresolved conflicts in the given module.
+ /// Resolve all of the unresolved conflicts in the given module.
///
/// \param Mod The module whose conflicts should be resolved.
///
@@ -569,25 +627,25 @@ public:
/// false otherwise.
bool resolveConflicts(Module *Mod, bool Complain);
- /// \brief Sets the umbrella header of the given module to the given
+ /// Sets the umbrella header of the given module to the given
/// header.
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
Twine NameAsWritten);
- /// \brief Sets the umbrella directory of the given module to the given
+ /// Sets the umbrella directory of the given module to the given
/// directory.
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
Twine NameAsWritten);
- /// \brief Adds this header to the given module.
+ /// Adds this header to the given module.
/// \param Role The role of the header wrt the module.
void addHeader(Module *Mod, Module::Header Header,
ModuleHeaderRole Role, bool Imported = false);
- /// \brief Marks this header as being excluded from the given module.
+ /// Marks this header as being excluded from the given module.
void excludeHeader(Module *Mod, Module::Header Header);
- /// \brief Parse the given module map file, and record any modules we
+ /// Parse the given module map file, and record any modules we
/// encounter.
///
/// \param File The file to be parsed.
@@ -608,19 +666,19 @@ public:
///
/// \returns true if an error occurred, false otherwise.
bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
- const DirectoryEntry *HomeDir, FileID ID = FileID(),
- unsigned *Offset = nullptr,
+ const DirectoryEntry *HomeDir,
+ FileID ID = FileID(), unsigned *Offset = nullptr,
SourceLocation ExternModuleLoc = SourceLocation());
- /// \brief Dump the contents of the module map, for debugging purposes.
+ /// Dump the contents of the module map, for debugging purposes.
void dump();
-
+
using module_iterator = llvm::StringMap<Module *>::const_iterator;
module_iterator module_begin() const { return Modules.begin(); }
module_iterator module_end() const { return Modules.end(); }
};
-
+
} // 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 3967f8688966..ac0dcc7b51c2 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the MultipleIncludeOpt interface.
+/// Defines the MultipleIncludeOpt interface.
//
//===----------------------------------------------------------------------===//
@@ -20,7 +20,7 @@
namespace clang {
class IdentifierInfo;
-/// \brief Implements the simple state machine that the Lexer class uses to
+/// Implements the simple state machine that the Lexer class uses to
/// detect files subject to the 'multiple-include' optimization.
///
/// The public methods in this class are triggered by various
@@ -113,13 +113,13 @@ public:
/// buffer, this method is called to disable the MIOpt if needed.
void ExpandedMacro() { DidMacroExpansion = true; }
- /// \brief Called when entering a top-level \#ifndef directive (or the
+ /// Called when entering a top-level \#ifndef directive (or the
/// "\#if !defined" equivalent) without any preceding tokens.
///
/// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
/// ensures that this is only called if there are no tokens read before the
/// \#ifndef. The caller is required to do this, because reading the \#if
- /// line obviously reads in in tokens.
+ /// line obviously reads in tokens.
void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc) {
// If the macro is already set, this is after the top-level #endif.
if (TheMacro)
@@ -139,14 +139,14 @@ public:
MacroLoc = Loc;
}
- /// \brief Invoked when a top level conditional (except \#ifndef) is found.
+ /// Invoked when a top level conditional (except \#ifndef) is found.
void EnterTopLevelConditional() {
// If a conditional directive (except #ifndef) is found at the top level,
// there is a chunk of the file not guarded by the controlling macro.
Invalidate();
}
- /// \brief Called when the lexer exits the top-level conditional.
+ /// Called when the lexer exits the top-level conditional.
void ExitTopLevelConditional() {
// If we have a macro, that means the top of the file was ok. Set our state
// back to "not having read any tokens" so we can detect anything after the
@@ -159,7 +159,7 @@ public:
ImmediatelyAfterTopLevelIfndef = false;
}
- /// \brief Once the entire file has been lexed, if there is a controlling
+ /// Once the entire file has been lexed, if there is a controlling
/// macro, return it.
const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
// If we haven't read any tokens after the #endif, return the controlling
@@ -169,7 +169,7 @@ public:
return nullptr;
}
- /// \brief If the ControllingMacro is followed by a macro definition, return
+ /// If the ControllingMacro is followed by a macro definition, return
/// the macro that was defined.
const IdentifierInfo *GetDefinedMacro() const {
return DefinedMacro;
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
index 19bce4dd32e8..45c2d18da6e2 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the PPCallbacks interface.
+/// Defines the PPCallbacks interface.
///
//===----------------------------------------------------------------------===//
@@ -29,7 +29,7 @@ namespace clang {
class MacroDirective;
class MacroArgs;
-/// \brief This interface provides a way to observe the actions of the
+/// This interface provides a way to observe the actions of the
/// preprocessor as it does its thing.
///
/// Clients can define their hooks here to implement preprocessor level tools.
@@ -41,7 +41,7 @@ public:
EnterFile, ExitFile, SystemHeaderPragma, RenameFile
};
- /// \brief Callback invoked whenever a source file is entered or exited.
+ /// Callback invoked whenever a source file is entered or exited.
///
/// \param Loc Indicates the new location.
/// \param PrevFID the file that was exited if \p Reason is ExitFile.
@@ -50,7 +50,7 @@ public:
FileID PrevFID = FileID()) {
}
- /// \brief Callback invoked whenever a source file is skipped as the result
+ /// Callback invoked whenever a source file is skipped as the result
/// of header guard optimization.
///
/// \param SkippedFile The file that is skipped instead of entering \#include
@@ -63,13 +63,13 @@ public:
SrcMgr::CharacteristicKind FileType) {
}
- /// \brief Callback invoked whenever an inclusion directive results in a
+ /// Callback invoked whenever an inclusion directive results in a
/// file-not-found error.
///
- /// \param FileName The name of the file being included, as written in the
+ /// \param FileName The name of the file being included, as written in the
/// source code.
///
- /// \param RecoveryPath If this client indicates that it can recover from
+ /// \param RecoveryPath If this client indicates that it can recover from
/// this missing file, the client should set this as an additional header
/// search patch.
///
@@ -80,17 +80,17 @@ public:
return false;
}
- /// \brief Callback invoked whenever an inclusion directive of
+ /// Callback invoked whenever an inclusion directive of
/// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
/// of whether the inclusion will actually result in an inclusion.
///
- /// \param HashLoc The location of the '#' that starts the inclusion
+ /// \param HashLoc The location of the '#' that starts the inclusion
/// directive.
///
- /// \param IncludeTok The token that indicates the kind of inclusion
+ /// \param IncludeTok The token that indicates the kind of inclusion
/// directive, e.g., 'include' or 'import'.
///
- /// \param FileName The name of the file being included, as written in the
+ /// \param FileName The name of the file being included, as written in the
/// source code.
///
/// \param IsAngled Whether the file name was enclosed in angle brackets;
@@ -99,7 +99,7 @@ public:
/// \param FilenameRange The character range of the quotes or angle brackets
/// for the written file name.
///
- /// \param File The actual file that may be included by this inclusion
+ /// \param File The actual file that may be included by this inclusion
/// directive.
///
/// \param SearchPath Contains the search path which was used to find the file
@@ -117,6 +117,10 @@ public:
/// \param Imported The module, whenever an inclusion directive was
/// automatically turned into a module import or null otherwise.
///
+ /// \param FileType The characteristic kind, indicates whether a file or
+ /// directory holds normal user code, system code, or system code which is
+ /// implicitly 'extern "C"' in C++ mode.
+ ///
virtual void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
@@ -125,10 +129,11 @@ public:
const FileEntry *File,
StringRef SearchPath,
StringRef RelativePath,
- const Module *Imported) {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
}
- /// \brief Callback invoked whenever there was an explicit module-import
+ /// Callback invoked whenever there was an explicit module-import
/// syntax.
///
/// \param ImportLoc The location of import directive token.
@@ -143,54 +148,54 @@ public:
const Module *Imported) {
}
- /// \brief Callback invoked when the end of the main file is reached.
+ /// Callback invoked when the end of the main file is reached.
///
/// No subsequent callbacks will be made.
virtual void EndOfMainFile() {
}
- /// \brief Callback invoked when a \#ident or \#sccs directive is read.
+ /// Callback invoked when a \#ident or \#sccs directive is read.
/// \param Loc The location of the directive.
/// \param str The text of the directive.
///
virtual void Ident(SourceLocation Loc, StringRef str) {
}
- /// \brief Callback invoked when start reading any pragma directive.
+ /// Callback invoked when start reading any pragma directive.
virtual void PragmaDirective(SourceLocation Loc,
PragmaIntroducerKind Introducer) {
}
- /// \brief Callback invoked when a \#pragma comment directive is read.
+ /// Callback invoked when a \#pragma comment directive is read.
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
StringRef Str) {
}
- /// \brief Callback invoked when a \#pragma detect_mismatch directive is
+ /// Callback invoked when a \#pragma detect_mismatch directive is
/// read.
virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
StringRef Value) {
}
- /// \brief Callback invoked when a \#pragma clang __debug directive is read.
+ /// Callback invoked when a \#pragma clang __debug directive is read.
/// \param Loc The location of the debug directive.
/// \param DebugType The identifier following __debug.
virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) {
}
- /// \brief Determines the kind of \#pragma invoking a call to PragmaMessage.
+ /// Determines the kind of \#pragma invoking a call to PragmaMessage.
enum PragmaMessageKind {
- /// \brief \#pragma message has been invoked.
+ /// \#pragma message has been invoked.
PMK_Message,
- /// \brief \#pragma GCC warning has been invoked.
+ /// \#pragma GCC warning has been invoked.
PMK_Warning,
- /// \brief \#pragma GCC error has been invoked.
+ /// \#pragma GCC error has been invoked.
PMK_Error
};
- /// \brief Callback invoked when a \#pragma message directive is read.
+ /// Callback invoked when a \#pragma message directive is read.
/// \param Loc The location of the message directive.
/// \param Namespace The namespace of the message directive.
/// \param Kind The type of the message directive.
@@ -199,62 +204,62 @@ public:
PragmaMessageKind Kind, StringRef Str) {
}
- /// \brief Callback invoked when a \#pragma gcc diagnostic push directive
+ /// Callback invoked when a \#pragma gcc diagnostic push directive
/// is read.
virtual void PragmaDiagnosticPush(SourceLocation Loc,
StringRef Namespace) {
}
- /// \brief Callback invoked when a \#pragma gcc diagnostic pop directive
+ /// Callback invoked when a \#pragma gcc diagnostic pop directive
/// is read.
virtual void PragmaDiagnosticPop(SourceLocation Loc,
StringRef Namespace) {
}
- /// \brief Callback invoked when a \#pragma gcc diagnostic directive is read.
+ /// Callback invoked when a \#pragma gcc diagnostic directive is read.
virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
diag::Severity mapping, StringRef Str) {}
- /// \brief Called when an OpenCL extension is either disabled or
+ /// Called when an OpenCL extension is either disabled or
/// enabled with a pragma.
- virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
+ virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
const IdentifierInfo *Name,
SourceLocation StateLoc, unsigned State) {
}
- /// \brief Callback invoked when a \#pragma warning directive is read.
+ /// Callback invoked when a \#pragma warning directive is read.
virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
ArrayRef<int> Ids) {
}
- /// \brief Callback invoked when a \#pragma warning(push) directive is read.
+ /// Callback invoked when a \#pragma warning(push) directive is read.
virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
}
- /// \brief Callback invoked when a \#pragma warning(pop) directive is read.
+ /// Callback invoked when a \#pragma warning(pop) directive is read.
virtual void PragmaWarningPop(SourceLocation Loc) {
}
- /// \brief Callback invoked when a \#pragma clang assume_nonnull begin directive
+ /// 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
+ /// Callback invoked when a \#pragma clang assume_nonnull end directive
/// is read.
virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {}
- /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
+ /// Called by Preprocessor::HandleMacroExpandedIdentifier when a
/// macro invocation is found.
virtual void MacroExpands(const Token &MacroNameTok,
const MacroDefinition &MD, SourceRange Range,
const MacroArgs *Args) {}
- /// \brief Hook called whenever a macro definition is seen.
+ /// Hook called whenever a macro definition is seen.
virtual void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) {
}
- /// \brief Hook called whenever a macro \#undef is seen.
+ /// Hook called whenever a macro \#undef is seen.
/// \param MacroNameTok The active Token
/// \param MD A MacroDefinition for the named macro.
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
@@ -264,14 +269,14 @@ public:
const MacroDefinition &MD,
const MacroDirective *Undef) {
}
-
- /// \brief Hook called whenever the 'defined' operator is seen.
+
+ /// Hook called whenever the 'defined' operator is seen.
/// \param MD The MacroDirective if the name was a macro, null otherwise.
virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range) {
}
-
- /// \brief Hook called when a source range is skipped.
+
+ /// 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.
/// \param EndifLoc The end location of the 'endif' token, which may precede
@@ -284,7 +289,7 @@ public:
CVK_NotEvaluated, CVK_False, CVK_True
};
- /// \brief Hook called whenever an \#if is seen.
+ /// Hook called whenever an \#if is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param ConditionValue The evaluated value of the condition.
@@ -294,7 +299,7 @@ public:
ConditionValueKind ConditionValue) {
}
- /// \brief Hook called whenever an \#elif is seen.
+ /// Hook called whenever an \#elif is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param ConditionValue The evaluated value of the condition.
@@ -304,7 +309,7 @@ public:
ConditionValueKind ConditionValue, SourceLocation IfLoc) {
}
- /// \brief Hook called whenever an \#ifdef is seen.
+ /// Hook called whenever an \#ifdef is seen.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
@@ -312,7 +317,7 @@ public:
const MacroDefinition &MD) {
}
- /// \brief Hook called whenever an \#ifndef is seen.
+ /// Hook called whenever an \#ifndef is seen.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
@@ -320,20 +325,20 @@ public:
const MacroDefinition &MD) {
}
- /// \brief Hook called whenever an \#else is seen.
+ /// Hook called whenever an \#else is seen.
/// \param Loc the source location of the directive.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
}
- /// \brief Hook called whenever an \#endif is seen.
+ /// Hook called whenever an \#endif is seen.
/// \param Loc the source location of the directive.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
}
};
-/// \brief Simple wrapper class for chaining callbacks.
+/// Simple wrapper class for chaining callbacks.
class PPChainedCallbacks : public PPCallbacks {
virtual void anchor();
std::unique_ptr<PPCallbacks> First, Second;
@@ -367,13 +372,14 @@ public:
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override {
First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
FilenameRange, File, SearchPath, RelativePath,
- Imported);
+ Imported, FileType);
Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
FilenameRange, File, SearchPath, RelativePath,
- Imported);
+ Imported, FileType);
}
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
@@ -499,41 +505,41 @@ public:
Second->SourceRangeSkipped(Range, EndifLoc);
}
- /// \brief Hook called whenever an \#if is seen.
+ /// Hook called whenever an \#if is seen.
void If(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue) override {
First->If(Loc, ConditionRange, ConditionValue);
Second->If(Loc, ConditionRange, ConditionValue);
}
- /// \brief Hook called whenever an \#elif is seen.
+ /// Hook called whenever an \#elif is seen.
void Elif(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
First->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
}
- /// \brief Hook called whenever an \#ifdef is seen.
+ /// Hook called whenever an \#ifdef is seen.
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
First->Ifdef(Loc, MacroNameTok, MD);
Second->Ifdef(Loc, MacroNameTok, MD);
}
- /// \brief Hook called whenever an \#ifndef is seen.
+ /// Hook called whenever an \#ifndef is seen.
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
First->Ifndef(Loc, MacroNameTok, MD);
Second->Ifndef(Loc, MacroNameTok, MD);
}
- /// \brief Hook called whenever an \#else is seen.
+ /// Hook called whenever an \#else is seen.
void Else(SourceLocation Loc, SourceLocation IfLoc) override {
First->Else(Loc, IfLoc);
Second->Else(Loc, IfLoc);
}
- /// \brief Hook called whenever an \#endif is seen.
+ /// Hook called whenever an \#endif is seen.
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
First->Endif(Loc, IfLoc);
Second->Endif(Loc, IfLoc);
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h
index 8c5227561b83..a2ccf1407f79 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -20,12 +20,12 @@
#include <vector>
namespace clang {
-
-/// \brief Records preprocessor conditional directive regions and allows
+
+/// Records preprocessor conditional directive regions and allows
/// querying in which region source locations belong to.
class PPConditionalDirectiveRecord : public PPCallbacks {
SourceManager &SourceMgr;
-
+
SmallVector<SourceLocation, 6> CondDirectiveStack;
class CondDirectiveLoc {
@@ -57,25 +57,25 @@ class PPConditionalDirectiveRecord : public PPCallbacks {
};
typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy;
- /// \brief The locations of conditional directives in source order.
+ /// The locations of conditional directives in source order.
CondDirectiveLocsTy CondDirectiveLocs;
void addCondDirectiveLoc(CondDirectiveLoc DirLoc);
public:
- /// \brief Construct a new preprocessing record.
+ /// Construct a new preprocessing record.
explicit PPConditionalDirectiveRecord(SourceManager &SM);
size_t getTotalMemory() const;
SourceManager &getSourceManager() const { return SourceMgr; }
- /// \brief Returns true if the given range intersects with a conditional
+ /// Returns true if the given range intersects with a conditional
/// directive. if a \#if/\#endif block is fully contained within the range,
/// this function will return false.
bool rangeIntersectsConditionalDirective(SourceRange Range) const;
- /// \brief Returns true if the given locations are in different regions,
+ /// Returns true if the given locations are in different regions,
/// separated by conditional directive blocks.
bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS,
SourceLocation RHS) const {
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
index f122a008e4aa..0b84df1434ae 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
@@ -49,7 +49,7 @@ class PTHLexer : public PreprocessorLexer {
/// ReadToken - Used by PTHLexer to read tokens TokBuf.
void ReadToken(Token &T);
-
+
bool LexEndOfFile(Token &Result);
/// PTHMgr - The PTHManager object that created this PTHLexer.
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
index 090ae2a98236..4d74face5275 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
@@ -26,27 +26,27 @@ class Preprocessor;
class Token;
/**
- * \brief Describes how the pragma was introduced, e.g., with \#pragma,
+ * Describes how the pragma was introduced, e.g., with \#pragma,
* _Pragma, or __pragma.
*/
enum PragmaIntroducerKind {
/**
- * \brief The pragma was introduced via \#pragma.
+ * The pragma was introduced via \#pragma.
*/
PIK_HashPragma,
-
+
/**
- * \brief The pragma was introduced via the C99 _Pragma(string-literal).
+ * The pragma was introduced via the C99 _Pragma(string-literal).
*/
PIK__Pragma,
-
+
/**
- * \brief The pragma was introduced via the Microsoft
+ * The pragma was introduced via the Microsoft
* __pragma(token-string).
*/
PIK___pragma
};
-
+
/// PragmaHandler - Instances of this interface defined to handle the various
/// pragmas that the language front-end uses. Each handler optionally has a
/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
index 5f7a6efcef10..44d79d9b6229 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
@@ -39,11 +39,11 @@ class PreprocessingRecord;
} // namespace clang
-/// \brief Allocates memory within a Clang preprocessing record.
+/// Allocates memory within a Clang preprocessing record.
void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
unsigned alignment = 8) noexcept;
-/// \brief Frees memory allocated in a Clang preprocessing record.
+/// Frees memory allocated in a Clang preprocessing record.
void operator delete(void *ptr, clang::PreprocessingRecord &PR,
unsigned) noexcept;
@@ -55,25 +55,25 @@ class MacroInfo;
class SourceManager;
class Token;
- /// \brief Base class that describes a preprocessed entity, which may be a
+ /// Base class that describes a preprocessed entity, which may be a
/// preprocessor directive or macro expansion.
class PreprocessedEntity {
public:
- /// \brief The kind of preprocessed entity an object describes.
+ /// The kind of preprocessed entity an object describes.
enum EntityKind {
- /// \brief Indicates a problem trying to load the preprocessed entity.
+ /// Indicates a problem trying to load the preprocessed entity.
InvalidKind,
- /// \brief A macro expansion.
+ /// A macro expansion.
MacroExpansionKind,
-
+
/// \defgroup Preprocessing directives
/// @{
-
- /// \brief A macro definition.
+
+ /// A macro definition.
MacroDefinitionKind,
-
- /// \brief An inclusion directive, such as \c \#include, \c
+
+ /// An inclusion directive, such as \c \#include, \c
/// \#import, or \c \#include_next.
InclusionDirectiveKind,
@@ -84,12 +84,12 @@ class Token;
};
private:
- /// \brief The kind of preprocessed entity that this object describes.
+ /// The kind of preprocessed entity that this object describes.
EntityKind Kind;
-
- /// \brief The source range that covers this preprocessed entity.
+
+ /// The source range that covers this preprocessed entity.
SourceRange Range;
-
+
protected:
friend class PreprocessingRecord;
@@ -97,18 +97,18 @@ class Token;
: Kind(Kind), Range(Range) {}
public:
- /// \brief Retrieve the kind of preprocessed entity stored in this object.
+ /// Retrieve the kind of preprocessed entity stored in this object.
EntityKind getKind() const { return Kind; }
-
- /// \brief Retrieve the source range that covers this entire preprocessed
+
+ /// Retrieve the source range that covers this entire preprocessed
/// entity.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- /// \brief Returns true if there was a problem loading the preprocessed
+ /// Returns true if there was a problem loading the preprocessed
/// entity.
bool isInvalid() const { return Kind == InvalidKind; }
- // Only allow allocation of preprocessed entities using the allocator
+ // Only allow allocation of preprocessed entities using the allocator
// in PreprocessingRecord or by doing a placement new.
void *operator new(size_t bytes, PreprocessingRecord &PR,
unsigned alignment = 8) noexcept {
@@ -130,23 +130,23 @@ class Token;
void *operator new(size_t bytes) noexcept;
void operator delete(void *data) noexcept;
};
-
- /// \brief Records the presence of a preprocessor directive.
+
+ /// Records the presence of a preprocessor directive.
class PreprocessingDirective : public PreprocessedEntity {
public:
- PreprocessingDirective(EntityKind Kind, SourceRange Range)
+ PreprocessingDirective(EntityKind Kind, SourceRange Range)
: PreprocessedEntity(Kind, Range) {}
-
+
// Implement isa/cast/dyncast/etc.
- static bool classof(const PreprocessedEntity *PD) {
+ static bool classof(const PreprocessedEntity *PD) {
return PD->getKind() >= FirstPreprocessingDirective &&
PD->getKind() <= LastPreprocessingDirective;
}
};
- /// \brief Record the location of a macro definition.
+ /// Record the location of a macro definition.
class MacroDefinitionRecord : public PreprocessingDirective {
- /// \brief The name of the macro being defined.
+ /// The name of the macro being defined.
const IdentifierInfo *Name;
public:
@@ -154,21 +154,21 @@ class Token;
SourceRange Range)
: PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) {}
- /// \brief Retrieve the name of the macro being defined.
+ /// Retrieve the name of the macro being defined.
const IdentifierInfo *getName() const { return Name; }
- /// \brief Retrieve the location of the macro name in the definition.
+ /// Retrieve the location of the macro name in the definition.
SourceLocation getLocation() const { return getSourceRange().getBegin(); }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const PreprocessedEntity *PE) {
return PE->getKind() == MacroDefinitionKind;
}
};
-
- /// \brief Records the location of a macro expansion.
+
+ /// Records the location of a macro expansion.
class MacroExpansion : public PreprocessedEntity {
- /// \brief The definition of this macro or the name of the macro if it is
+ /// The definition of this macro or the name of the macro if it is
/// a builtin macro.
llvm::PointerUnion<IdentifierInfo *, MacroDefinitionRecord *> NameOrDef;
@@ -181,17 +181,17 @@ class Token;
: PreprocessedEntity(MacroExpansionKind, Range), NameOrDef(Definition) {
}
- /// \brief True if it is a builtin macro.
+ /// True if it is a builtin macro.
bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }
- /// \brief The name of the macro being expanded.
+ /// The name of the macro being expanded.
const IdentifierInfo *getName() const {
if (MacroDefinitionRecord *Def = getDefinition())
return Def->getName();
return NameOrDef.get<IdentifierInfo *>();
}
- /// \brief The definition of the macro being expanded. May return null if
+ /// The definition of the macro being expanded. May return null if
/// this is a builtin macro.
MacroDefinitionRecord *getDefinition() const {
return NameOrDef.dyn_cast<MacroDefinitionRecord *>();
@@ -203,126 +203,131 @@ class Token;
}
};
- /// \brief Record the location of an inclusion directive, such as an
+ /// Record the location of an inclusion directive, such as an
/// \c \#include or \c \#import statement.
class InclusionDirective : public PreprocessingDirective {
public:
- /// \brief The kind of inclusion directives known to the
+ /// The kind of inclusion directives known to the
/// preprocessor.
enum InclusionKind {
- /// \brief An \c \#include directive.
+ /// An \c \#include directive.
Include,
- /// \brief An Objective-C \c \#import directive.
+ /// An Objective-C \c \#import directive.
Import,
- /// \brief A GNU \c \#include_next directive.
+ /// A GNU \c \#include_next directive.
IncludeNext,
- /// \brief A Clang \c \#__include_macros directive.
+ /// A Clang \c \#__include_macros directive.
IncludeMacros
};
private:
- /// \brief The name of the file that was included, as written in
+ /// The name of the file that was included, as written in
/// the source.
StringRef FileName;
- /// \brief Whether the file name was in quotation marks; otherwise, it was
+ /// Whether the file name was in quotation marks; otherwise, it was
/// in angle brackets.
unsigned InQuotes : 1;
- /// \brief The kind of inclusion directive we have.
+ /// The kind of inclusion directive we have.
///
/// This is a value of type InclusionKind.
unsigned Kind : 2;
- /// \brief Whether the inclusion directive was automatically turned into
+ /// Whether the inclusion directive was automatically turned into
/// a module import.
unsigned ImportedModule : 1;
- /// \brief The file that was included.
+ /// The file that was included.
const FileEntry *File;
public:
InclusionDirective(PreprocessingRecord &PPRec,
- InclusionKind Kind, StringRef FileName,
+ InclusionKind Kind, StringRef FileName,
bool InQuotes, bool ImportedModule,
const FileEntry *File, SourceRange Range);
-
- /// \brief Determine what kind of inclusion directive this is.
+
+ /// Determine what kind of inclusion directive this is.
InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }
-
- /// \brief Retrieve the included file name as it was written in the source.
+
+ /// Retrieve the included file name as it was written in the source.
StringRef getFileName() const { return FileName; }
-
- /// \brief Determine whether the included file name was written in quotes;
+
+ /// Determine whether the included file name was written in quotes;
/// otherwise, it was written in angle brackets.
bool wasInQuotes() const { return InQuotes; }
- /// \brief Determine whether the inclusion directive was automatically
+ /// Determine whether the inclusion directive was automatically
/// turned into a module import.
bool importedModule() const { return ImportedModule; }
-
- /// \brief Retrieve the file entry for the actual file that was included
+
+ /// Retrieve the file entry for the actual file that was included
/// by this directive.
const FileEntry *getFile() const { return File; }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const PreprocessedEntity *PE) {
return PE->getKind() == InclusionDirectiveKind;
}
};
-
- /// \brief An abstract class that should be subclassed by any external source
+
+ /// An abstract class that should be subclassed by any external source
/// of preprocessing record entries.
class ExternalPreprocessingRecordSource {
public:
virtual ~ExternalPreprocessingRecordSource();
-
- /// \brief Read a preallocated preprocessed entity from the external source.
+
+ /// Read a preallocated preprocessed entity from the external source.
///
/// \returns null if an error occurred that prevented the preprocessed
/// entity from being loaded.
virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0;
- /// \brief Returns a pair of [Begin, End) indices of preallocated
+ /// Returns a pair of [Begin, End) indices of preallocated
/// preprocessed entities that \p Range encompasses.
virtual std::pair<unsigned, unsigned>
findPreprocessedEntitiesInRange(SourceRange Range) = 0;
- /// \brief Optionally returns true or false if the preallocated preprocessed
+ /// Optionally returns true or false if the preallocated preprocessed
/// entity with index \p Index came from file \p FID.
virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
FileID FID) {
return None;
}
+
+ /// Read a preallocated skipped range from the external source.
+ virtual SourceRange ReadSkippedRange(unsigned Index) = 0;
};
-
- /// \brief A record of the steps taken while preprocessing a source file,
- /// including the various preprocessing directives processed, macros
+
+ /// A record of the steps taken while preprocessing a source file,
+ /// including the various preprocessing directives processed, macros
/// expanded, etc.
class PreprocessingRecord : public PPCallbacks {
SourceManager &SourceMgr;
-
- /// \brief Allocator used to store preprocessing objects.
+
+ /// Allocator used to store preprocessing objects.
llvm::BumpPtrAllocator BumpAlloc;
- /// \brief The set of preprocessed entities in this record, in order they
+ /// The set of preprocessed entities in this record, in order they
/// were seen.
std::vector<PreprocessedEntity *> PreprocessedEntities;
-
- /// \brief The set of preprocessed entities in this record that have been
+
+ /// The set of preprocessed entities in this record that have been
/// loaded from external sources.
///
/// The entries in this vector are loaded lazily from the external source,
/// and are referenced by the iterator using negative indices.
std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
- /// \brief The set of ranges that were skipped by the preprocessor,
+ /// The set of ranges that were skipped by the preprocessor,
std::vector<SourceRange> SkippedRanges;
- /// \brief Global (loaded or local) ID for a preprocessed entity.
+ bool SkippedRangesAllLoaded = true;
+
+ /// Global (loaded or local) ID for a preprocessed entity.
/// Negative values are used to indicate preprocessed entities
/// loaded from the external source while non-negative values are used to
/// indicate preprocessed entities introduced by the current preprocessor.
@@ -346,50 +351,60 @@ class Token;
return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1);
}
- /// \brief Mapping from MacroInfo structures to their definitions.
+ /// Mapping from MacroInfo structures to their definitions.
llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions;
- /// \brief External source of preprocessed entities.
+ /// External source of preprocessed entities.
ExternalPreprocessingRecordSource *ExternalSource = nullptr;
- /// \brief Retrieve the preprocessed entity at the given ID.
+ /// Retrieve the preprocessed entity at the given ID.
PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);
- /// \brief Retrieve the loaded preprocessed entity at the given index.
+ /// Retrieve the loaded preprocessed entity at the given index.
PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index);
-
- /// \brief Determine the number of preprocessed entities that were
+
+ /// Determine the number of preprocessed entities that were
/// loaded (or can be loaded) from an external source.
unsigned getNumLoadedPreprocessedEntities() const {
return LoadedPreprocessedEntities.size();
}
- /// \brief Returns a pair of [Begin, End) indices of local preprocessed
+ /// Returns a pair of [Begin, End) indices of local preprocessed
/// entities that \p Range encompasses.
std::pair<unsigned, unsigned>
findLocalPreprocessedEntitiesInRange(SourceRange Range) const;
unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const;
unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const;
- /// \brief Allocate space for a new set of loaded preprocessed entities.
+ /// Allocate space for a new set of loaded preprocessed entities.
///
/// \returns The index into the set of loaded preprocessed entities, which
/// corresponds to the first newly-allocated entity.
unsigned allocateLoadedEntities(unsigned NumEntities);
- /// \brief Register a new macro definition.
+ /// Allocate space for a new set of loaded preprocessed skipped
+ /// ranges.
+ ///
+ /// \returns The index into the set of loaded preprocessed ranges, which
+ /// corresponds to the first newly-allocated range.
+ unsigned allocateSkippedRanges(unsigned NumRanges);
+
+ /// Ensures that all external skipped ranges have been loaded.
+ void ensureSkippedRangesLoaded();
+
+ /// Register a new macro definition.
void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);
public:
- /// \brief Construct a new preprocessing record.
+ /// Construct a new preprocessing record.
explicit PreprocessingRecord(SourceManager &SM);
- /// \brief Allocate memory in the preprocessing record.
+ /// Allocate memory in the preprocessing record.
void *Allocate(unsigned Size, unsigned Align = 8) {
return BumpAlloc.Allocate(Size, Align);
}
-
- /// \brief Deallocate memory in the preprocessing record.
+
+ /// Deallocate memory in the preprocessing record.
void Deallocate(void *Ptr) {}
size_t getTotalMemory() const;
@@ -436,27 +451,27 @@ class Token;
PreprocessedEntity *operator->() const { return **this; }
};
- /// \brief Begin iterator for all preprocessed entities.
+ /// Begin iterator for all preprocessed entities.
iterator begin() {
return iterator(this, -(int)LoadedPreprocessedEntities.size());
}
- /// \brief End iterator for all preprocessed entities.
+ /// End iterator for all preprocessed entities.
iterator end() {
return iterator(this, PreprocessedEntities.size());
}
- /// \brief Begin iterator for local, non-loaded, preprocessed entities.
+ /// Begin iterator for local, non-loaded, preprocessed entities.
iterator local_begin() {
return iterator(this, 0);
}
- /// \brief End iterator for local, non-loaded, preprocessed entities.
+ /// End iterator for local, non-loaded, preprocessed entities.
iterator local_end() {
return iterator(this, PreprocessedEntities.size());
}
- /// \brief iterator range for the given range of loaded
+ /// iterator range for the given range of loaded
/// preprocessed entities.
llvm::iterator_range<iterator> getIteratorsForLoadedRange(unsigned start,
unsigned count) {
@@ -467,14 +482,14 @@ class Token;
iterator(this, int(end) - LoadedPreprocessedEntities.size()));
}
- /// \brief Returns a range of preprocessed entities that source range \p R
+ /// Returns a range of preprocessed entities that source range \p R
/// encompasses.
///
/// \param R the range to look for preprocessed entities.
llvm::iterator_range<iterator>
getPreprocessedEntitiesInRange(SourceRange R);
- /// \brief Returns true if the preprocessed entity that \p PPEI iterator
+ /// Returns true if the preprocessed entity that \p PPEI iterator
/// points to is coming from the file \p FID.
///
/// Can be used to avoid implicit deserializations of preallocated
@@ -483,26 +498,27 @@ class Token;
/// \see getPreprocessedEntitiesInRange.
bool isEntityInFileID(iterator PPEI, FileID FID);
- /// \brief Add a new preprocessed entity to this record.
+ /// Add a new preprocessed entity to this record.
PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);
- /// \brief Set the external source for preprocessed entities.
+ /// Set the external source for preprocessed entities.
void SetExternalSource(ExternalPreprocessingRecordSource &Source);
- /// \brief Retrieve the external source for preprocessed entities.
+ /// Retrieve the external source for preprocessed entities.
ExternalPreprocessingRecordSource *getExternalSource() const {
return ExternalSource;
}
- /// \brief Retrieve the macro definition that corresponds to the given
+ /// Retrieve the macro definition that corresponds to the given
/// \c MacroInfo.
MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);
- /// \brief Retrieve all ranges that got skipped while preprocessing.
- const std::vector<SourceRange> &getSkippedRanges() const {
+ /// Retrieve all ranges that got skipped while preprocessing.
+ const std::vector<SourceRange> &getSkippedRanges() {
+ ensureSkippedRangesLoaded();
return SkippedRanges;
}
-
+
private:
friend class ASTReader;
friend class ASTWriter;
@@ -516,14 +532,14 @@ class Token;
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange,
const FileEntry *File, StringRef SearchPath,
- StringRef RelativePath,
- const Module *Imported) override;
+ StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override;
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override;
- /// \brief Hook called whenever the 'defined' operator is seen.
+ /// Hook called whenever the 'defined' operator is seen.
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range) override;
@@ -533,7 +549,7 @@ class Token;
void addMacroExpansion(const Token &Id, const MacroInfo *MI,
SourceRange Range);
- /// \brief Cached result of the last \see getPreprocessedEntitiesInRange
+ /// Cached result of the last \see getPreprocessedEntitiesInRange
/// query.
struct {
SourceRange Range;
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
index 485600f12232..e718f5b6bbd0 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the clang::Preprocessor interface.
+/// Defines the clang::Preprocessor interface.
//
//===----------------------------------------------------------------------===//
@@ -83,7 +83,7 @@ class PTHManager;
class ScratchBuffer;
class TargetInfo;
-/// \brief Stores token information for comparing actual tokens with
+/// Stores token information for comparing actual tokens with
/// predefined values. Only handles simple tokens and identifiers.
class TokenValue {
tok::TokenKind Kind;
@@ -106,7 +106,7 @@ public:
}
};
-/// \brief Context in which macro name is used.
+/// Context in which macro name is used.
enum MacroUse {
// other than #define or #undef
MU_Other = 0,
@@ -118,7 +118,7 @@ enum MacroUse {
MU_Undef = 2
};
-/// \brief Engages in a tight little dance with the lexer to efficiently
+/// Engages in a tight little dance with the lexer to efficiently
/// preprocess tokens.
///
/// Lexers know only about tokens within a single source file, and don't
@@ -140,7 +140,7 @@ class Preprocessor {
HeaderSearch &HeaderInfo;
ModuleLoader &TheModuleLoader;
- /// \brief External source of macros.
+ /// External source of macros.
ExternalPreprocessorSource *ExternalSource;
/// An optional PTHManager object used for getting tokens from
@@ -186,7 +186,7 @@ class Preprocessor {
unsigned CounterValue = 0;
enum {
- /// \brief Maximum depth of \#includes.
+ /// Maximum depth of \#includes.
MaxAllowedIncludeStackDepth = 200
};
@@ -210,26 +210,26 @@ class Preprocessor {
class ResetMacroExpansionHelper;
- /// \brief Whether we have already loaded macros from the external source.
+ /// Whether we have already loaded macros from the external source.
mutable bool ReadMacrosFromExternalSource : 1;
- /// \brief True if pragmas are enabled.
+ /// True if pragmas are enabled.
bool PragmasEnabled : 1;
- /// \brief True if the current build action is a preprocessing action.
+ /// True if the current build action is a preprocessing action.
bool PreprocessedOutput : 1;
- /// \brief True if we are currently preprocessing a #if or #elif directive
+ /// True if we are currently preprocessing a #if or #elif directive
bool ParsingIfOrElifDirective;
- /// \brief True if we are pre-expanding macro arguments.
+ /// True if we are pre-expanding macro arguments.
bool InMacroArgPreExpansion;
- /// \brief Mapping/lookup information for all identifiers in
+ /// Mapping/lookup information for all identifiers in
/// the program, including program keywords.
mutable IdentifierTable Identifiers;
- /// \brief This table contains all the selectors in the program.
+ /// This table contains all the selectors in the program.
///
/// Unlike IdentifierTable above, this table *isn't* populated by the
/// preprocessor. It is declared/expanded here because its role/lifetime is
@@ -240,82 +240,82 @@ class Preprocessor {
/// the lifetime of the preprocessor.
SelectorTable Selectors;
- /// \brief Information about builtins.
+ /// Information about builtins.
Builtin::Context BuiltinInfo;
- /// \brief Tracks all of the pragmas that the client registered
+ /// Tracks all of the pragmas that the client registered
/// with this preprocessor.
std::unique_ptr<PragmaNamespace> PragmaHandlers;
- /// \brief Pragma handlers of the original source is stored here during the
+ /// Pragma handlers of the original source is stored here during the
/// parsing of a model file.
std::unique_ptr<PragmaNamespace> PragmaHandlersBackup;
- /// \brief Tracks all of the comment handlers that the client registered
+ /// Tracks all of the comment handlers that the client registered
/// with this preprocessor.
std::vector<CommentHandler *> CommentHandlers;
- /// \brief True if we want to ignore EOF token and continue later on (thus
+ /// True if we want to ignore EOF token and continue later on (thus
/// avoid tearing the Lexer and etc. down).
bool IncrementalProcessing = false;
/// The kind of translation unit we are processing.
TranslationUnitKind TUKind;
- /// \brief The code-completion handler.
+ /// The code-completion handler.
CodeCompletionHandler *CodeComplete = nullptr;
- /// \brief The file that we're performing code-completion for, if any.
+ /// The file that we're performing code-completion for, if any.
const FileEntry *CodeCompletionFile = nullptr;
- /// \brief The offset in file for the code-completion point.
+ /// The offset in file for the code-completion point.
unsigned CodeCompletionOffset = 0;
- /// \brief The location for the code-completion point. This gets instantiated
+ /// The location for the code-completion point. This gets instantiated
/// when the CodeCompletionFile gets \#include'ed for preprocessing.
SourceLocation CodeCompletionLoc;
- /// \brief The start location for the file of the code-completion point.
+ /// The start location for the file of the code-completion point.
///
/// This gets instantiated when the CodeCompletionFile gets \#include'ed
/// for preprocessing.
SourceLocation CodeCompletionFileLoc;
- /// \brief The source location of the \c import contextual keyword we just
+ /// The source location of the \c import contextual keyword we just
/// lexed, if any.
SourceLocation ModuleImportLoc;
- /// \brief The module import path that we're currently processing.
+ /// The module import path that we're currently processing.
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath;
- /// \brief Whether the last token we lexed was an '@'.
+ /// Whether the last token we lexed was an '@'.
bool LastTokenWasAt = false;
- /// \brief Whether the module import expects an identifier next. Otherwise,
+ /// Whether the module import expects an identifier next. Otherwise,
/// it expects a '.' or ';'.
bool ModuleImportExpectsIdentifier = false;
-
- /// \brief The source location of the currently-active
+
+ /// The source location of the currently-active
/// \#pragma clang arc_cf_code_audited begin.
SourceLocation PragmaARCCFCodeAuditedLoc;
- /// \brief The source location of the currently-active
+ /// The source location of the currently-active
/// \#pragma clang assume_nonnull begin.
SourceLocation PragmaAssumeNonNullLoc;
- /// \brief True if we hit the code-completion point.
+ /// True if we hit the code-completion point.
bool CodeCompletionReached = false;
- /// \brief The code completion token containing the information
+ /// The code completion token containing the information
/// on the stem that is to be code completed.
IdentifierInfo *CodeCompletionII = nullptr;
- /// \brief The directory that the main file should be considered to occupy,
+ /// 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 = nullptr;
- /// \brief The number of bytes that we will initially skip when entering the
+ /// The number of bytes that we will initially skip when entering the
/// main file, along with a flag that indicates whether skipping this number
/// of bytes will place the lexer at the start of a line.
///
@@ -386,37 +386,37 @@ private:
State ConditionalStackState = Off;
} PreambleConditionalStack;
- /// \brief The current top of the stack that we're lexing from if
+ /// The current top of the stack that we're lexing from if
/// not expanding a macro and we are lexing directly from source code.
///
/// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
std::unique_ptr<Lexer> CurLexer;
- /// \brief The current top of stack that we're lexing from if
+ /// The current top of stack that we're lexing from if
/// not expanding from a macro and we are lexing from a PTH cache.
///
/// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
std::unique_ptr<PTHLexer> CurPTHLexer;
- /// \brief The current top of the stack what we're lexing from
+ /// The current top of the stack what we're lexing from
/// if not expanding a macro.
///
/// This is an alias for either CurLexer or CurPTHLexer.
PreprocessorLexer *CurPPLexer = nullptr;
- /// \brief Used to find the current FileEntry, if CurLexer is non-null
+ /// 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 = nullptr;
- /// \brief The current macro we are expanding, if we are expanding a macro.
+ /// The current macro we are expanding, if we are expanding a macro.
///
/// One of CurLexer and CurTokenLexer must be null.
std::unique_ptr<TokenLexer> CurTokenLexer;
- /// \brief The kind of lexer we're currently working with.
+ /// The kind of lexer we're currently working with.
enum CurLexerKind {
CLK_Lexer,
CLK_PTHLexer,
@@ -425,11 +425,11 @@ private:
CLK_LexAfterModuleImport
} CurLexerKind = CLK_Lexer;
- /// \brief If the current lexer is for a submodule that is being built, this
+ /// If the current lexer is for a submodule that is being built, this
/// is that submodule.
Module *CurLexerSubmodule = nullptr;
- /// \brief Keeps track of the stack of files currently
+ /// Keeps track of the stack of files currently
/// \#included, and macros currently being expanded from, not counting
/// CurLexer/CurTokenLexer.
struct IncludeStackInfo {
@@ -458,7 +458,7 @@ private:
};
std::vector<IncludeStackInfo> IncludeMacroStack;
- /// \brief Actions invoked when some preprocessor activity is
+ /// Actions invoked when some preprocessor activity is
/// encountered (e.g. a file is \#included, etc).
std::unique_ptr<PPCallbacks> Callbacks;
@@ -617,7 +617,7 @@ private:
struct SubmoduleState;
- /// \brief Information about a submodule that we're currently building.
+ /// Information about a submodule that we're currently building.
struct BuildingSubmoduleInfo {
/// The module that we are building.
Module *M;
@@ -643,7 +643,7 @@ private:
};
SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack;
- /// \brief Information about a submodule's preprocessor state.
+ /// Information about a submodule's preprocessor state.
struct SubmoduleState {
/// The macros for the submodule.
MacroMap Macros;
@@ -674,7 +674,7 @@ private:
llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro *>>
LeafModuleMacros;
- /// \brief Macros that we want to warn because they are not used at the end
+ /// Macros that we want to warn because they are not used at the end
/// of the translation unit.
///
/// We store just their SourceLocations instead of
@@ -686,7 +686,7 @@ private:
using WarnUnusedMacroLocsTy = llvm::SmallPtrSet<SourceLocation, 32>;
WarnUnusedMacroLocsTy WarnUnusedMacroLocs;
- /// \brief A "freelist" of MacroArg objects that can be
+ /// A "freelist" of MacroArg objects that can be
/// reused for quick allocation.
MacroArgs *MacroArgCache = nullptr;
@@ -713,21 +713,27 @@ private:
unsigned NumFastTokenPaste = 0;
unsigned NumSkipped = 0;
- /// \brief The predefined macros that preprocessor should use from the
+ /// The predefined macros that preprocessor should use from the
/// command line etc.
std::string Predefines;
- /// \brief The file ID for the preprocessor predefines.
+ /// The file ID for the preprocessor predefines.
FileID PredefinesFileID;
+ /// The file ID for the PCH through header.
+ FileID PCHThroughHeaderFileID;
+
+ /// Whether tokens are being skipped until the through header is seen.
+ bool SkippingUntilPCHThroughHeader = false;
+
/// \{
- /// \brief Cache of macro expanders to reduce malloc traffic.
+ /// Cache of macro expanders to reduce malloc traffic.
enum { TokenLexerCacheSize = 8 };
unsigned NumCachedTokenLexers;
std::unique_ptr<TokenLexer> TokenLexerCache[TokenLexerCacheSize];
/// \}
- /// \brief Keeps macro expanded tokens for TokenLexers.
+ /// Keeps macro expanded tokens for TokenLexers.
//
/// Works like a stack; a TokenLexer adds the macro expanded tokens that is
/// going to lex in the cache and when it finishes the tokens are removed
@@ -735,7 +741,7 @@ private:
SmallVector<Token, 16> MacroExpandedTokens;
std::vector<std::pair<TokenLexer *, size_t>> MacroExpandingLexersStack;
- /// \brief A record of the macro definitions and expansions that
+ /// A record of the macro definitions and expansions that
/// occurred during preprocessing.
///
/// This is an optional side structure that can be enabled with
@@ -745,18 +751,18 @@ private:
/// Cached tokens state.
using CachedTokensTy = SmallVector<Token, 1>;
- /// \brief Cached tokens are stored here when we do backtracking or
+ /// Cached tokens are stored here when we do backtracking or
/// lookahead. They are "lexed" by the CachingLex() method.
CachedTokensTy CachedTokens;
- /// \brief The position of the cached token that CachingLex() should
+ /// The position of the cached token that CachingLex() should
/// "lex" next.
///
/// If it points beyond the CachedTokens vector, it means that a normal
/// Lex() should be invoked.
CachedTokensTy::size_type CachedLexPos = 0;
- /// \brief Stack of backtrack positions, allowing nested backtracks.
+ /// Stack of backtrack positions, allowing nested backtracks.
///
/// The EnableBacktrackAtThisPos() method pushes a position to
/// indicate where CachedLexPos should be set when the BackTrack() method is
@@ -785,7 +791,7 @@ public:
~Preprocessor();
- /// \brief Initialize the preprocessor using information about the target.
+ /// Initialize the preprocessor using information about the target.
///
/// \param Target is owned by the caller and must remain valid for the
/// lifetime of the preprocessor.
@@ -794,7 +800,7 @@ public:
void Initialize(const TargetInfo &Target,
const TargetInfo *AuxTarget = nullptr);
- /// \brief Initialize the preprocessor to parse a model file
+ /// Initialize the preprocessor to parse a model file
///
/// To parse model files the preprocessor of the original source is reused to
/// preserver the identifier table. However to avoid some duplicate
@@ -802,13 +808,13 @@ public:
/// to parse model files. This method does that cleanup.
void InitializeForModelFile();
- /// \brief Cleanup after model file parsing
+ /// Cleanup after model file parsing
void FinalizeForModelFile();
- /// \brief Retrieve the preprocessor options used to initialize this
+ /// Retrieve the preprocessor options used to initialize this
/// preprocessor.
PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; }
-
+
DiagnosticsEngine &getDiagnostics() const { return *Diags; }
void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; }
@@ -838,19 +844,19 @@ public:
return ExternalSource;
}
- /// \brief Retrieve the module loader associated with this preprocessor.
+ /// Retrieve the module loader associated with this preprocessor.
ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
bool hadModuleLoaderFatalFailure() const {
return TheModuleLoader.HadFatalFailure;
}
- /// \brief True if we are currently preprocessing a #if or #elif directive
- bool isParsingIfOrElifDirective() const {
+ /// True if we are currently preprocessing a #if or #elif directive
+ bool isParsingIfOrElifDirective() const {
return ParsingIfOrElifDirective;
}
- /// \brief Control whether the preprocessor retains comments in output.
+ /// Control whether the preprocessor retains comments in output.
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
this->KeepComments = KeepComments | KeepMacroComments;
this->KeepMacroComments = KeepMacroComments;
@@ -879,32 +885,32 @@ public:
/// false if it is producing tokens to be consumed by Parse and Sema.
bool isPreprocessedOutput() const { return PreprocessedOutput; }
- /// \brief Return true if we are lexing directly from the specified lexer.
+ /// Return true if we are lexing directly from the specified lexer.
bool isCurrentLexer(const PreprocessorLexer *L) const {
return CurPPLexer == L;
}
- /// \brief Return the current lexer being lexed from.
+ /// Return the current lexer being lexed from.
///
/// Note that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
- /// \brief Return the current file lexer being lexed from.
+ /// Return the current file lexer being lexed from.
///
/// Note that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *getCurrentFileLexer() const;
- /// \brief Return the submodule owning the file being lexed. This may not be
+ /// Return the submodule owning the file being lexed. This may not be
/// the current module if we have changed modules since entering the file.
Module *getCurrentLexerSubmodule() const { return CurLexerSubmodule; }
- /// \brief Returns the FileID for the preprocessor predefines.
+ /// Returns the FileID for the preprocessor predefines.
FileID getPredefinesFileID() const { return PredefinesFileID; }
/// \{
- /// \brief Accessors for preprocessor callbacks.
+ /// Accessors for preprocessor callbacks.
///
/// Note that this class takes ownership of any PPCallbacks object given to
/// it.
@@ -925,7 +931,7 @@ public:
(!getLangOpts().Modules || (bool)getMacroDefinition(II));
}
- /// \brief Determine whether II is defined as a macro within the module M,
+ /// Determine whether II is defined as a macro within the module M,
/// if that is a module that we've already preprocessed. Does not check for
/// macros imported into M.
bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M) {
@@ -969,7 +975,7 @@ public:
S.isAmbiguous(*this, II));
}
- /// \brief Given an identifier, return its latest non-imported MacroDirective
+ /// Given an identifier, return its latest non-imported MacroDirective
/// if it is \#define'd and not \#undef'd, or null if it isn't \#define'd.
MacroDirective *getLocalMacroDirective(const IdentifierInfo *II) const {
if (!II->hasMacroDefinition())
@@ -994,14 +1000,14 @@ public:
return nullptr;
}
- /// \brief Given an identifier, return the latest non-imported macro
+ /// Given an identifier, return the latest non-imported macro
/// directive for that identifier.
///
/// One can iterate over all previous macro directives from the most recent
/// one.
MacroDirective *getLocalMacroDirectiveHistory(const IdentifierInfo *II) const;
- /// \brief Add a directive to the macro directive history for this identifier.
+ /// Add a directive to the macro directive history for this identifier.
void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD);
DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI,
SourceLocation Loc) {
@@ -1014,16 +1020,16 @@ public:
return appendDefMacroDirective(II, MI, MI->getDefinitionLoc());
}
- /// \brief Set a MacroDirective that was loaded from a PCH file.
+ /// Set a MacroDirective that was loaded from a PCH file.
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED,
MacroDirective *MD);
- /// \brief Register an exported macro for a module and identifier.
+ /// Register an exported macro for a module and identifier.
ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro,
ArrayRef<ModuleMacro *> Overrides, bool &IsNew);
ModuleMacro *getModuleMacro(Module *Mod, IdentifierInfo *II);
- /// \brief Get the list of leaf (non-overridden) module macros for a name.
+ /// Get the list of leaf (non-overridden) module macros for a name.
ArrayRef<ModuleMacro*> getLeafModuleMacros(const IdentifierInfo *II) const {
if (II->isOutOfDate())
updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II));
@@ -1041,15 +1047,17 @@ public:
macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
macro_iterator macro_end(bool IncludeExternalMacros = true) const;
- llvm::iterator_range<macro_iterator>
+ llvm::iterator_range<macro_iterator>
macros(bool IncludeExternalMacros = true) const {
- return llvm::make_range(macro_begin(IncludeExternalMacros),
- macro_end(IncludeExternalMacros));
+ macro_iterator begin = macro_begin(IncludeExternalMacros);
+ macro_iterator end = macro_end(IncludeExternalMacros);
+ return llvm::make_range(begin, end);
}
+
/// \}
- /// \brief Return the name of the macro defined before \p Loc that has
+ /// Return the name of the macro defined before \p Loc that has
/// spelling \p Tokens. If there are multiple macros with same spelling,
/// return the last one defined.
StringRef getLastMacroWithSpelling(SourceLocation Loc,
@@ -1057,7 +1065,7 @@ public:
const std::string &getPredefines() const { return Predefines; }
- /// \brief Set the predefines for this Preprocessor.
+ /// Set the predefines for this Preprocessor.
///
/// These predefines are automatically injected when parsing the main file.
void setPredefines(const char *P) { Predefines = P; }
@@ -1069,7 +1077,7 @@ public:
return &Identifiers.get(Name);
}
- /// \brief Add the specified pragma handler to this preprocessor.
+ /// Add the specified pragma handler to this preprocessor.
///
/// If \p Namespace is non-null, then it is a token required to exist on the
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
@@ -1078,7 +1086,7 @@ public:
AddPragmaHandler(StringRef(), Handler);
}
- /// \brief Remove the specific pragma handler from this preprocessor.
+ /// Remove the specific pragma handler from this preprocessor.
///
/// If \p Namespace is non-null, then it should be the namespace that
/// \p Handler was added to. It is an error to remove a handler that
@@ -1091,68 +1099,84 @@ public:
/// Install empty handlers for all pragmas (making them ignored).
void IgnorePragmas();
- /// \brief Add the specified comment handler to the preprocessor.
+ /// Add the specified comment handler to the preprocessor.
void addCommentHandler(CommentHandler *Handler);
- /// \brief Remove the specified comment handler.
+ /// Remove the specified comment handler.
///
/// It is an error to remove a handler that has not been registered.
void removeCommentHandler(CommentHandler *Handler);
- /// \brief Set the code completion handler to the given object.
+ /// Set the code completion handler to the given object.
void setCodeCompletionHandler(CodeCompletionHandler &Handler) {
CodeComplete = &Handler;
}
- /// \brief Retrieve the current code-completion handler.
+ /// Retrieve the current code-completion handler.
CodeCompletionHandler *getCodeCompletionHandler() const {
return CodeComplete;
}
- /// \brief Clear out the code completion handler.
+ /// Clear out the code completion handler.
void clearCodeCompletionHandler() {
CodeComplete = nullptr;
}
- /// \brief Hook used by the lexer to invoke the "natural language" code
+ /// Hook used by the lexer to invoke the "natural language" code
/// completion point.
void CodeCompleteNaturalLanguage();
- /// \brief Set the code completion token for filtering purposes.
+ /// Set the code completion token for filtering purposes.
void setCodeCompletionIdentifierInfo(IdentifierInfo *Filter) {
CodeCompletionII = Filter;
}
- /// \brief Get the code completion token for filtering purposes.
+ /// Get the code completion token for filtering purposes.
StringRef getCodeCompletionFilter() {
if (CodeCompletionII)
return CodeCompletionII->getName();
return {};
}
- /// \brief Retrieve the preprocessing record, or NULL if there is no
+ /// Retrieve the preprocessing record, or NULL if there is no
/// preprocessing record.
PreprocessingRecord *getPreprocessingRecord() const { return Record; }
- /// \brief Create a new preprocessing record, which will keep track of
+ /// Create a new preprocessing record, which will keep track of
/// all macro expansions, macro definitions, etc.
void createPreprocessingRecord();
- /// \brief Enter the specified FileID as the main source file,
+ /// Returns true if the FileEntry is the PCH through header.
+ bool isPCHThroughHeader(const FileEntry *File);
+
+ /// True if creating a PCH with a through header.
+ bool creatingPCHWithThroughHeader();
+
+ /// True if using a PCH with a through header.
+ bool usingPCHWithThroughHeader();
+
+ /// Skip tokens until after the #include of the through header.
+ void SkipTokensUntilPCHThroughHeader();
+
+ /// Process directives while skipping until the through header is found.
+ void HandleSkippedThroughHeaderDirective(Token &Result,
+ SourceLocation HashLoc);
+
+ /// Enter the specified FileID as the main source file,
/// which implicitly adds the builtin defines etc.
void EnterMainSourceFile();
- /// \brief Inform the preprocessor callbacks that processing is complete.
+ /// Inform the preprocessor callbacks that processing is complete.
void EndSourceFile();
- /// \brief Add a source file to the top of the include stack and
+ /// Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
///
/// Emits a diagnostic, doesn't enter the file, and returns true on error.
bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
SourceLocation Loc);
- /// \brief Add a Macro to the top of the include stack and start lexing
+ /// Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
///
/// \param Args specifies the tokens input to a function-like macro.
@@ -1161,7 +1185,7 @@ public:
void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro,
MacroArgs *Args);
- /// \brief Add a "macro" context to the top of the include stack,
+ /// Add a "macro" context to the top of the include stack,
/// which will cause the lexer to start returning the specified tokens.
///
/// If \p DisableMacroExpansion is true, tokens lexed from the token stream
@@ -1186,7 +1210,7 @@ public:
EnterTokenStream(Toks.data(), Toks.size(), DisableMacroExpansion, false);
}
- /// \brief Pop the current lexer/macro exp off the top of the lexer stack.
+ /// Pop the current lexer/macro exp off the top of the lexer stack.
///
/// This should only be used in situations where the current state of the
/// top-of-stack lexer is known.
@@ -1207,7 +1231,7 @@ public:
///
void EnableBacktrackAtThisPos();
- /// \brief Disable the last EnableBacktrackAtThisPos call.
+ /// Disable the last EnableBacktrackAtThisPos call.
void CommitBacktrackedTokens();
struct CachedTokensRange {
@@ -1215,28 +1239,28 @@ public:
};
private:
- /// \brief A range of cached tokens that should be erased after lexing
+ /// A range of cached tokens that should be erased after lexing
/// when backtracking requires the erasure of such cached tokens.
Optional<CachedTokensRange> CachedTokenRangeToErase;
public:
- /// \brief Returns the range of cached tokens that were lexed since
+ /// Returns the range of cached tokens that were lexed since
/// EnableBacktrackAtThisPos() was previously called.
CachedTokensRange LastCachedTokenRange();
- /// \brief Erase the range of cached tokens that were lexed since
+ /// Erase the range of cached tokens that were lexed since
/// EnableBacktrackAtThisPos() was previously called.
void EraseCachedTokens(CachedTokensRange TokenRange);
- /// \brief Make Preprocessor re-lex the tokens that were lexed since
+ /// Make Preprocessor re-lex the tokens that were lexed since
/// EnableBacktrackAtThisPos() was previously called.
void Backtrack();
- /// \brief True if EnableBacktrackAtThisPos() was called and
+ /// True if EnableBacktrackAtThisPos() was called and
/// caching of tokens is on.
bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
- /// \brief Lex the next token for this preprocessor.
+ /// Lex the next token for this preprocessor.
void Lex(Token &Result);
void LexAfterModuleImport(Token &Result);
@@ -1247,7 +1271,7 @@ public:
return CurSubmoduleState->VisibleModules.getImportLoc(M);
}
- /// \brief Lex a string literal, which may be the concatenation of multiple
+ /// Lex a string literal, which may be the concatenation of multiple
/// string literals and may even come from macro expansion.
/// \returns true on success, false if a error diagnostic has been generated.
bool LexStringLiteral(Token &Result, std::string &String,
@@ -1260,13 +1284,13 @@ public:
AllowMacroExpansion);
}
- /// \brief Complete the lexing of a string literal where the first token has
+ /// Complete the lexing of a string literal where the first token has
/// already been lexed (see LexStringLiteral).
bool FinishLexStringLiteral(Token &Result, std::string &String,
const char *DiagnosticTag,
bool AllowMacroExpansion);
- /// \brief Lex a token. If it's a comment, keep lexing until we get
+ /// Lex a token. If it's a comment, keep lexing until we get
/// something not a comment.
///
/// This is useful in -E -C mode where comments would foul up preprocessor
@@ -1277,7 +1301,7 @@ public:
while (Result.getKind() == tok::comment);
}
- /// \brief Just like Lex, but disables macro expansion of identifier tokens.
+ /// Just like Lex, but disables macro expansion of identifier tokens.
void LexUnexpandedToken(Token &Result) {
// Disable macro expansion.
bool OldVal = DisableMacroExpansion;
@@ -1289,7 +1313,7 @@ public:
DisableMacroExpansion = OldVal;
}
- /// \brief Like LexNonComment, but this disables macro expansion of
+ /// Like LexNonComment, but this disables macro expansion of
/// identifier tokens.
void LexUnexpandedNonComment(Token &Result) {
do
@@ -1297,7 +1321,7 @@ public:
while (Result.getKind() == tok::comment);
}
- /// \brief Parses a simple integer literal to get its numeric value. Floating
+ /// Parses a simple integer literal to get its numeric value. Floating
/// point literals and user defined literals are rejected. Used primarily to
/// handle pragmas that accept integer arguments.
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value);
@@ -1308,7 +1332,7 @@ public:
MacroExpansionInDirectivesOverride = true;
}
- /// \brief Peeks ahead N tokens and returns that token without consuming any
+ /// Peeks ahead N tokens and returns that token without consuming any
/// tokens.
///
/// LookAhead(0) returns the next token that would be returned by Lex(),
@@ -1322,7 +1346,7 @@ public:
return PeekAhead(N+1);
}
- /// \brief When backtracking is enabled and tokens are cached,
+ /// When backtracking is enabled and tokens are cached,
/// this allows to revert a specific number of tokens.
///
/// Note that the number of tokens being reverted should be up to the last
@@ -1337,7 +1361,7 @@ public:
CachedLexPos -= N;
}
- /// \brief Enters a token in the token stream to be lexed next.
+ /// Enters a token in the token stream to be lexed next.
///
/// If BackTrack() is called afterwards, the token will remain at the
/// insertion point.
@@ -1367,18 +1391,18 @@ public:
return CachedTokens[CachedLexPos-1].getLastLoc();
}
- /// \brief Whether \p Tok is the most recent token (`CachedLexPos - 1`) in
+ /// Whether \p Tok is the most recent token (`CachedLexPos - 1`) in
/// CachedTokens.
bool IsPreviousCachedToken(const Token &Tok) const;
- /// \brief Replace token in `CachedLexPos - 1` in CachedTokens by the tokens
+ /// Replace token in `CachedLexPos - 1` in CachedTokens by the tokens
/// in \p NewToks.
///
/// Useful when a token needs to be split in smaller ones and CachedTokens
/// most recent token must to be updated to reflect that.
void ReplacePreviousCachedToken(ArrayRef<Token> NewToks);
- /// \brief Replace the last token with an annotation token.
+ /// Replace the last token with an annotation token.
///
/// Like AnnotateCachedTokens(), this routine replaces an
/// already-parsed (and resolved) token with an annotation
@@ -1404,19 +1428,19 @@ public:
CachedTokens[CachedLexPos-1] = Tok;
}
- /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/
+ /// Recompute the current lexer kind based on the CurLexer/CurPTHLexer/
/// CurTokenLexer pointers.
void recomputeCurLexerKind();
- /// \brief Returns true if incremental processing is enabled
+ /// Returns true if incremental processing is enabled
bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; }
- /// \brief Enables the incremental processing
+ /// Enables the incremental processing
void enableIncrementalProcessing(bool value = true) {
IncrementalProcessing = value;
}
-
- /// \brief Specify the point at which code-completion will be performed.
+
+ /// Specify the point at which code-completion will be performed.
///
/// \param File the file in which code completion should occur. If
/// this file is included multiple times, code-completion will
@@ -1433,16 +1457,16 @@ public:
bool SetCodeCompletionPoint(const FileEntry *File,
unsigned Line, unsigned Column);
- /// \brief Determine if we are performing code completion.
+ /// Determine if we are performing code completion.
bool isCodeCompletionEnabled() const { return CodeCompletionFile != nullptr; }
- /// \brief Returns the location of the code-completion point.
+ /// Returns the location of the code-completion point.
///
/// Returns an invalid location if code-completion is not enabled or the file
/// containing the code-completion point has not been lexed yet.
SourceLocation getCodeCompletionLoc() const { return CodeCompletionLoc; }
- /// \brief Returns the start location of the file of code-completion point.
+ /// Returns the start location of the file of code-completion point.
///
/// Returns an invalid location if code-completion is not enabled or the file
/// containing the code-completion point has not been lexed yet.
@@ -1450,11 +1474,11 @@ public:
return CodeCompletionFileLoc;
}
- /// \brief Returns true if code-completion is enabled and we have hit the
+ /// Returns true if code-completion is enabled and we have hit the
/// code-completion point.
bool isCodeCompletionReached() const { return CodeCompletionReached; }
- /// \brief Note that we hit the code-completion point.
+ /// Note that we hit the code-completion point.
void setCodeCompletionReached() {
assert(isCodeCompletionEnabled() && "Code-completion not enabled!");
CodeCompletionReached = true;
@@ -1462,7 +1486,7 @@ public:
getDiagnostics().setSuppressAllDiagnostics(true);
}
- /// \brief The location of the currently-active \#pragma clang
+ /// The location of the currently-active \#pragma clang
/// arc_cf_code_audited begin.
///
/// Returns an invalid location if there is no such pragma active.
@@ -1470,13 +1494,13 @@ public:
return PragmaARCCFCodeAuditedLoc;
}
- /// \brief Set the location of the currently-active \#pragma clang
+ /// Set the location of the currently-active \#pragma clang
/// arc_cf_code_audited begin. An invalid location ends the pragma.
void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) {
PragmaARCCFCodeAuditedLoc = Loc;
}
- /// \brief The location of the currently-active \#pragma clang
+ /// The location of the currently-active \#pragma clang
/// assume_nonnull begin.
///
/// Returns an invalid location if there is no such pragma active.
@@ -1484,19 +1508,19 @@ public:
return PragmaAssumeNonNullLoc;
}
- /// \brief Set the location of the currently-active \#pragma clang
+ /// Set the location of the currently-active \#pragma clang
/// assume_nonnull begin. An invalid location ends the pragma.
void setPragmaAssumeNonNullLoc(SourceLocation Loc) {
PragmaAssumeNonNullLoc = Loc;
}
- /// \brief Set the directory in which the main file should be considered
+ /// Set the directory in which the main file should be considered
/// to have been found, if it is not a real file.
void setMainFileDir(const DirectoryEntry *Dir) {
MainFileDir = Dir;
}
- /// \brief Instruct the preprocessor to skip part of the main source file.
+ /// Instruct the preprocessor to skip part of the main source file.
///
/// \param Bytes The number of bytes in the preamble to skip.
///
@@ -1531,7 +1555,7 @@ public:
return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid);
}
- /// \brief Return the 'spelling' of the Tok token.
+ /// 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
@@ -1543,7 +1567,7 @@ public:
return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid);
}
- /// \brief Get the spelling of a token into a preallocated buffer, instead
+ /// 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
@@ -1560,7 +1584,7 @@ public:
return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid);
}
- /// \brief Get the spelling of a token into a SmallVector.
+ /// Get the spelling of a token into a SmallVector.
///
/// Note that the returned StringRef may not point to the
/// supplied buffer if a copy can be avoided.
@@ -1568,14 +1592,14 @@ public:
SmallVectorImpl<char> &Buffer,
bool *Invalid = nullptr) const;
- /// \brief Relex the token at the specified location.
+ /// Relex the token at the specified location.
/// \returns true if there was a failure, false on success.
bool getRawToken(SourceLocation Loc, Token &Result,
bool IgnoreWhiteSpace = false) {
return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace);
}
- /// \brief Given a Token \p Tok that is a numeric constant with length 1,
+ /// Given a Token \p Tok that is a numeric constant with length 1,
/// return the character.
char
getSpellingOfSingleCharacterNumericConstant(const Token &Tok,
@@ -1593,7 +1617,7 @@ public:
return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid);
}
- /// \brief Retrieve the name of the immediate macro expansion.
+ /// Retrieve the name of the immediate macro expansion.
///
/// This routine starts from a source location, and finds the name of the
/// macro responsible for its immediate expansion. It looks through any
@@ -1605,8 +1629,8 @@ public:
return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts());
}
- /// \brief Plop the specified string into a scratch buffer and set the
- /// specified token's location and length to it.
+ /// Plop the specified string into a scratch buffer and set the
+ /// specified token's location and length to it.
///
/// If specified, the source location provides a location of the expansion
/// point of the token.
@@ -1614,7 +1638,12 @@ public:
SourceLocation ExpansionLocStart = SourceLocation(),
SourceLocation ExpansionLocEnd = SourceLocation());
- /// \brief Computes the source location just past the end of the
+ /// Split the first Length characters out of the token starting at TokLoc
+ /// and return a location pointing to the split token. Re-lexing from the
+ /// split token will return the split token rather than the original.
+ SourceLocation SplitToken(SourceLocation TokLoc, unsigned Length);
+
+ /// Computes the source location just past the end of the
/// token at this source location.
///
/// This routine can be used to produce a source location that
@@ -1633,7 +1662,7 @@ public:
return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
}
- /// \brief Returns true if the given MacroID location points at the first
+ /// Returns true if the given MacroID location points at the first
/// token of the macro expansion.
///
/// \param MacroBegin If non-null and function returns true, it is set to
@@ -1644,7 +1673,7 @@ public:
MacroBegin);
}
- /// \brief Returns true if the given MacroID location points at the last
+ /// Returns true if the given MacroID location points at the last
/// token of the macro expansion.
///
/// \param MacroEnd If non-null and function returns true, it is set to
@@ -1654,20 +1683,20 @@ public:
return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
}
- /// \brief Print the token to stderr, used for debugging.
+ /// Print the token to stderr, used for debugging.
void DumpToken(const Token &Tok, bool DumpFlags = false) const;
void DumpLocation(SourceLocation Loc) const;
void DumpMacro(const MacroInfo &MI) const;
void dumpMacroInfo(const IdentifierInfo *II);
- /// \brief Given a location that specifies the start of a
+ /// Given a location that specifies the start of a
/// token, return a new location that specifies a character within the token.
SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
unsigned Char) const {
return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, LangOpts);
}
- /// \brief Increment the counters for the number of token paste operations
+ /// Increment the counters for the number of token paste operations
/// performed.
///
/// If fast was specified, this is a 'fast paste' case we handled.
@@ -1700,13 +1729,13 @@ private:
llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons;
public:
- /// \brief Specifies the reason for poisoning an identifier.
+ /// Specifies the reason for poisoning an identifier.
///
/// If that identifier is accessed while poisoned, then this reason will be
/// used instead of the default "poisoned" diagnostic.
void SetPoisonReason(IdentifierInfo *II, unsigned DiagID);
- /// \brief Display reason for poisoned identifier.
+ /// Display reason for poisoned identifier.
void HandlePoisonedIdentifier(Token & Tok);
void MaybeHandlePoisonedIdentifier(Token & Identifier) {
@@ -1739,8 +1768,8 @@ private:
public:
void PoisonSEHIdentifiers(bool Poison = true); // Borland
- /// \brief Callback invoked when the lexer reads an identifier and has
- /// filled in the tokens IdentifierInfo member.
+ /// Callback invoked when the lexer reads an identifier and has
+ /// filled in the tokens IdentifierInfo member.
///
/// This callback potentially macro expands it or turns it into a named
/// token (like 'for').
@@ -1749,36 +1778,36 @@ public:
/// lex again.
bool HandleIdentifier(Token &Identifier);
- /// \brief Callback invoked when the lexer hits the end of the current file.
+ /// Callback invoked when the lexer hits the end of the current file.
///
/// This either returns the EOF token and returns true, or
/// pops a level off the include stack and returns false, at which point the
/// client should call lex again.
bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
- /// \brief Callback invoked when the current TokenLexer hits the end of its
+ /// Callback invoked when the current TokenLexer hits the end of its
/// token stream.
bool HandleEndOfTokenLexer(Token &Result);
- /// \brief Callback invoked when the lexer sees a # token at the start of a
+ /// Callback invoked when the lexer sees a # token at the start of a
/// line.
///
/// This consumes the directive, modifies the lexer/preprocessor state, and
/// advances the lexer(s) so that the next token read is the correct one.
void HandleDirective(Token &Result);
- /// \brief Ensure that the next token is a tok::eod token.
+ /// Ensure that the next token is a tok::eod token.
///
/// If not, emit a diagnostic and consume up until the eod.
/// If \p EnableMacros is true, then we consider macros that expand to zero
/// tokens as being ok.
void CheckEndOfDirective(const char *Directive, bool EnableMacros = false);
- /// \brief Read and discard all tokens remaining on the current line until
+ /// Read and discard all tokens remaining on the current line until
/// the tok::eod token is found.
void DiscardUntilEndOfDirective();
- /// \brief Returns true if the preprocessor has seen a use of
+ /// Returns true if the preprocessor has seen a use of
/// __DATE__ or __TIME__ in the file so far.
bool SawDateOrTime() const {
return DATELoc != SourceLocation() || TIMELoc != SourceLocation();
@@ -1786,14 +1815,14 @@ public:
unsigned getCounterValue() const { return CounterValue; }
void setCounterValue(unsigned V) { CounterValue = V; }
- /// \brief Retrieves the module that we're currently building, if any.
+ /// Retrieves the module that we're currently building, if any.
Module *getCurrentModule();
-
- /// \brief Allocate a new MacroInfo object with the provided SourceLocation.
+
+ /// Allocate a new MacroInfo object with the provided SourceLocation.
MacroInfo *AllocateMacroInfo(SourceLocation L);
- /// \brief Turn the specified lexer token into a fully checked and spelled
- /// filename, e.g. as an operand of \#include.
+ /// Turn the specified lexer token into a fully checked and spelled
+ /// filename, e.g. as an operand of \#include.
///
/// The caller is expected to provide a buffer that is large enough to hold
/// the spelling of the filename, but is also expected to handle the case
@@ -1803,7 +1832,7 @@ public:
/// in ""'s.
bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename);
- /// \brief Given a "foo" or \<foo> reference, look up the indicated file.
+ /// Given a "foo" or \<foo> reference, look up the indicated file.
///
/// Returns null on failure. \p isAngled indicates whether the file
/// reference is for system \#include's or not (i.e. using <> instead of "").
@@ -1816,18 +1845,18 @@ public:
ModuleMap::KnownHeader *SuggestedModule,
bool *IsMapped, bool SkipCache = false);
- /// \brief Get the DirectoryLookup structure used to find the current
- /// FileEntry, if CurLexer is non-null and if applicable.
+ /// Get the DirectoryLookup structure used to find the current
+ /// FileEntry, if CurLexer is non-null and if applicable.
///
/// This allows us to implement \#include_next and find directory-specific
/// properties.
const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
- /// \brief Return true if we're in the top-level file, not in a \#include.
+ /// Return true if we're in the top-level file, not in a \#include.
bool isInPrimaryFile() const;
- /// \brief Handle cases where the \#include name is expanded
- /// from a macro as multiple tokens, which need to be glued together.
+ /// Handle cases where the \#include name is expanded
+ /// from a macro as multiple tokens, which need to be glued together.
///
/// This occurs for code like:
/// \code
@@ -1842,7 +1871,7 @@ public:
bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
SourceLocation &End);
- /// \brief Lex an on-off-switch (C99 6.10.6p2) and verify that it is
+ /// Lex an on-off-switch (C99 6.10.6p2) and verify that it is
/// followed by EOD. Return true if the token is not a valid on-off-switch.
bool LexOnOffSwitch(tok::OnOffSwitch &OOS);
@@ -1891,7 +1920,7 @@ private:
VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc,
bool isPublic);
- /// \brief Lex and validate a macro name, which occurs after a
+ /// Lex and validate a macro name, which occurs after a
/// \#define or \#undef.
///
/// \param MacroNameTok Token that represents the name defined or undefined.
@@ -1910,7 +1939,7 @@ private:
/// - # (stringization) is followed by a macro parameter
/// \param MacroNameTok - Token that represents the macro name
/// \param ImmediatelyAfterHeaderGuard - Macro follows an #ifdef header guard
- ///
+ ///
/// 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(
@@ -1935,7 +1964,7 @@ private:
bool FoundNonSkipPortion, bool FoundElse,
SourceLocation ElseLoc = SourceLocation());
- /// \brief A fast PTH version of SkipExcludedConditionalBlock.
+ /// A fast PTH version of SkipExcludedConditionalBlock.
void PTHSkipExcludedConditionalBlock();
/// Information about the result for evaluating an expression for a
@@ -1948,17 +1977,17 @@ private:
bool IncludedUndefinedIds;
};
- /// \brief Evaluate an integer constant expression that may occur after a
+ /// Evaluate an integer constant expression that may occur after a
/// \#if or \#elif directive and return a \p DirectiveEvalResult object.
///
/// If the expression is equivalent to "!defined(X)" return X in IfNDefMacro.
DirectiveEvalResult EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
- /// \brief Install the standard preprocessor pragmas:
+ /// Install the standard preprocessor pragmas:
/// \#pragma GCC poison/system_header/dependency and \#pragma once.
void RegisterBuiltinPragmas();
- /// \brief Register builtin macros such as __LINE__ with the identifier table.
+ /// Register builtin macros such as __LINE__ with the identifier table.
void RegisterBuiltinMacros();
/// If an identifier token is read that is to be expanded as a macro, handle
@@ -1966,7 +1995,7 @@ private:
/// otherwise the caller should lex again.
bool HandleMacroExpandedIdentifier(Token &Tok, const MacroDefinition &MD);
- /// \brief Cache macro expanded tokens for TokenLexers.
+ /// Cache macro expanded tokens for TokenLexers.
//
/// Works like a stack; a TokenLexer adds the macro expanded tokens that is
/// going to lex in the cache and when it finishes the tokens are removed
@@ -1986,34 +2015,37 @@ private:
MacroArgs *ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI,
SourceLocation &ExpansionEnd);
- /// \brief If an identifier token is read that is to be expanded
+ /// If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
void ExpandBuiltinMacro(Token &Tok);
- /// \brief Read a \c _Pragma directive, slice it up, process it, then
+ /// Read a \c _Pragma directive, slice it up, process it, then
/// return the first token after the directive.
/// This assumes that the \c _Pragma token has just been read into \p Tok.
void Handle_Pragma(Token &Tok);
- /// \brief Like Handle_Pragma except the pragma text is not enclosed within
+ /// Like Handle_Pragma except the pragma text is not enclosed within
/// a string literal.
void HandleMicrosoft__pragma(Token &Tok);
- /// \brief Add a lexer to the top of the include stack and
+ /// Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
- /// \brief Add a lexer to the top of the include stack and
+ /// Add a lexer to the top of the include stack and
/// start getting tokens from it using the PTH cache.
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
- /// \brief Set the FileID for the preprocessor predefines.
+ /// Set the FileID for the preprocessor predefines.
void setPredefinesFileID(FileID FID) {
assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!");
PredefinesFileID = FID;
}
- /// \brief Returns true if we are lexing from a file and not a
+ /// Set the FileID for the PCH through header.
+ void setPCHThroughHeaderFileID(FileID FID);
+
+ /// Returns true if we are lexing from a file and not a
/// pragma or a macro.
static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
return L ? !L->isPragmaLexer() : P != nullptr;
@@ -2079,12 +2111,12 @@ public:
DiagnosticsEngine &Diags, Module *M);
// Module inclusion testing.
- /// \brief Find the module that owns the source or header file that
+ /// Find the module that owns the source or header file that
/// \p Loc points to. If the location is in a file that was included
/// into a module, or is outside any module, returns nullptr.
Module *getModuleForLocation(SourceLocation Loc);
- /// \brief We want to produce a diagnostic at location IncLoc concerning a
+ /// We want to produce a diagnostic at location IncLoc concerning a
/// missing module import.
///
/// \param IncLoc The location at which the missing import was detected.
@@ -2127,7 +2159,7 @@ public:
}
private:
- /// \brief After processing predefined file, initialize the conditional stack from
+ /// After processing predefined file, initialize the conditional stack from
/// the preamble.
void replayPreambleConditionalStack();
@@ -2164,12 +2196,12 @@ public:
// has inserted some tokens and getCommentRetentionState() is false.
bool HandleComment(Token &Token, SourceRange Comment);
- /// \brief A macro is used, update information about macros that need unused
+ /// A macro is used, update information about macros that need unused
/// warnings.
void markMacroAsUsed(MacroInfo *MI);
};
-/// \brief Abstract base class that describes a handler that will receive
+/// Abstract base class that describes a handler that will receive
/// source ranges for each of the comments encountered in the source file.
class CommentHandler {
public:
@@ -2180,7 +2212,7 @@ public:
virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
};
-/// \brief Registry of pragma handlers added by plugins
+/// Registry of pragma handlers added by plugins
using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>;
} // namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
index ff71d11b4511..b619f192f530 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Defines the PreprocessorLexer interface.
+/// Defines the PreprocessorLexer interface.
//
//===----------------------------------------------------------------------===//
@@ -39,21 +39,21 @@ protected:
/// The SourceManager FileID corresponding to the file being lexed.
const FileID FID;
- /// \brief Number of SLocEntries before lexing the file.
+ /// Number of SLocEntries before lexing the file.
unsigned InitialNumSLocEntries = 0;
//===--------------------------------------------------------------------===//
// Context-specific lexing flags set by the preprocessor.
//===--------------------------------------------------------------------===//
- /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token.
+ /// True when parsing \#XXX; turns '\\n' into a tok::eod token.
bool ParsingPreprocessorDirective = false;
- /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal
+ /// True after \#include; turns \<xx> into a tok::angle_string_literal
/// token.
bool ParsingFilename = false;
- /// \brief True if in raw mode.
+ /// True if in raw mode.
///
/// Raw mode disables interpretation of tokens and is a far faster mode to
/// lex in than non-raw-mode. This flag:
@@ -68,11 +68,11 @@ protected:
/// Note that in raw mode that the PP pointer may be null.
bool LexingRawMode = false;
- /// \brief A state machine that detects the \#ifndef-wrapping a file
+ /// A state machine that detects the \#ifndef-wrapping a file
/// idiom for the multiple-include optimization.
MultipleIncludeOpt MIOpt;
- /// \brief Information about the set of \#if/\#ifdef/\#ifndef blocks
+ /// Information about the set of \#if/\#ifdef/\#ifndef blocks
/// we are currently in.
SmallVector<PPConditionalInfo, 4> ConditionalStack;
@@ -82,7 +82,7 @@ protected:
virtual void IndirectLex(Token& Result) = 0;
- /// \brief Return the source location for the next observable location.
+ /// Return the source location for the next observable location.
virtual SourceLocation getSourceLocation() = 0;
//===--------------------------------------------------------------------===//
@@ -114,7 +114,7 @@ protected:
return false;
}
- /// \brief Return the top of the conditional stack.
+ /// Return the top of the conditional stack.
/// \pre This requires that there be a conditional active.
PPConditionalInfo &peekConditionalLevel() {
assert(!ConditionalStack.empty() && "No conditionals active!");
@@ -130,23 +130,23 @@ public:
//===--------------------------------------------------------------------===//
// Misc. lexing methods.
- /// \brief After the preprocessor has parsed a \#include, lex and
+ /// After the preprocessor has parsed a \#include, lex and
/// (potentially) macro expand the filename.
///
/// If the sequence parsed is not lexically legal, emit a diagnostic and
/// return a result EOD token.
void LexIncludeFilename(Token &Result);
- /// \brief Inform the lexer whether or not we are currently lexing a
+ /// Inform the lexer whether or not we are currently lexing a
/// preprocessor directive.
void setParsingPreprocessorDirective(bool f) {
ParsingPreprocessorDirective = f;
}
- /// \brief Return true if this lexer is in raw mode or not.
+ /// Return true if this lexer is in raw mode or not.
bool isLexingRawMode() const { return LexingRawMode; }
- /// \brief Return the preprocessor object for this lexer.
+ /// Return the preprocessor object for this lexer.
Preprocessor *getPP() const { return PP; }
FileID getFileID() const {
@@ -155,7 +155,7 @@ public:
return FID;
}
- /// \brief Number of SLocEntries before lexing the file.
+ /// Number of SLocEntries before lexing the file.
unsigned getInitialNumSLocEntries() const {
return InitialNumSLocEntries;
}
@@ -164,17 +164,17 @@ public:
/// getFileID(), this only works for lexers with attached preprocessors.
const FileEntry *getFileEntry() const;
- /// \brief Iterator that traverses the current stack of preprocessor
+ /// Iterator that traverses the current stack of preprocessor
/// conditional directives (\#if/\#ifdef/\#ifndef).
using conditional_iterator =
SmallVectorImpl<PPConditionalInfo>::const_iterator;
- conditional_iterator conditional_begin() const {
- return ConditionalStack.begin();
+ conditional_iterator conditional_begin() const {
+ return ConditionalStack.begin();
}
- conditional_iterator conditional_end() const {
- return ConditionalStack.end();
+ conditional_iterator conditional_end() const {
+ return ConditionalStack.end();
}
void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) {
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
index 55fc305dc295..5134aeaa6a29 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
@@ -13,7 +13,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
-#include <memory>
+#include <memory>
#include <set>
#include <string>
#include <utility>
@@ -27,17 +27,17 @@ class MemoryBuffer;
namespace clang {
-/// \brief Enumerate the kinds of standard library that
+/// Enumerate the kinds of standard library that
enum ObjCXXARCStandardLibraryKind {
ARCXX_nolib,
- /// \brief libc++
+ /// libc++
ARCXX_libcxx,
- /// \brief libstdc++
+ /// libstdc++
ARCXX_libstdcxx
};
-
+
/// PreprocessorOptions - This class is used for passing the various options
/// used in preprocessor initialization to InitializePreprocessor().
class PreprocessorOptions {
@@ -46,48 +46,60 @@ public:
std::vector<std::string> Includes;
std::vector<std::string> MacroIncludes;
- /// \brief Initialize the preprocessor with the compiler and target specific
+ /// Initialize the preprocessor with the compiler and target specific
/// predefines.
bool UsePredefines = true;
- /// \brief Whether we should maintain a detailed record of all macro
+ /// Whether we should maintain a detailed record of all macro
/// definitions and expansions.
bool DetailedRecord = false;
+ /// If non-empty, the filename used in an #include directive in the primary
+ /// source file (or command-line preinclude) that is used to implement
+ /// MSVC-style precompiled headers. When creating a PCH, after the #include
+ /// of this header, the PCH generation stops. When using a PCH, tokens are
+ /// skipped until after an #include of this header is seen.
+ std::string PCHThroughHeader;
+
/// The implicit PCH included at the start of the translation unit, or empty.
std::string ImplicitPCHInclude;
- /// \brief Headers that will be converted to chained PCHs in memory.
+ /// Headers that will be converted to chained PCHs in memory.
std::vector<std::string> ChainedIncludes;
- /// \brief When true, disables most of the normal validation performed on
+ /// When true, disables most of the normal validation performed on
/// precompiled headers.
bool DisablePCHValidation = false;
- /// \brief When true, a PCH with compiler errors will not be rejected.
+ /// When true, a PCH with compiler errors will not be rejected.
bool AllowPCHWithCompilerErrors = false;
- /// \brief Dump declarations that are deserialized from PCH, for testing.
+ /// Dump declarations that are deserialized from PCH, for testing.
bool DumpDeserializedPCHDecls = false;
- /// \brief This is a set of names for decls that we do not want to be
+ /// This is a set of names for decls that we do not want to be
/// deserialized, and we emit an error if they are; for testing purposes.
std::set<std::string> DeserializedPCHDeclsToErrorOn;
- /// \brief If non-zero, the implicit PCH include is actually a precompiled
+ /// If non-zero, the implicit PCH include is actually a precompiled
/// preamble that covers this number of bytes in the main source file.
///
/// The boolean indicates whether the preamble ends at the start of a new
/// line.
std::pair<unsigned, bool> PrecompiledPreambleBytes;
- /// \brief True indicates that a preamble is being generated.
+ /// True indicates that a preamble is being generated.
///
/// 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 = false;
+ /// Whether to write comment locations into the PCH when building it.
+ /// Reading the comments from the PCH can be a performance hit even if the
+ /// clients don't use them.
+ bool WriteCommentListToPCH = true;
+
/// The implicit PTH input included at the start of the translation unit, or
/// empty.
std::string ImplicitPTHInclude;
@@ -105,35 +117,35 @@ public:
/// When enabled, the preprocessor will construct editor placeholder tokens.
bool LexEditorPlaceholders = true;
- /// \brief True if the SourceManager should report the original file name for
+ /// 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 = true;
- /// \brief The set of file remappings, which take existing files on
+ /// The set of file remappings, which take existing files on
/// the system (the first part of each pair) and gives them the
/// contents of other files on the system (the second part of each
/// pair).
std::vector<std::pair<std::string, std::string>> RemappedFiles;
- /// \brief The set of file-to-buffer remappings, which take existing files
+ /// The set of file-to-buffer remappings, which take existing files
/// on the system (the first part of each pair) and gives them the contents
/// of the specified memory buffer (the second part of each pair).
std::vector<std::pair<std::string, llvm::MemoryBuffer *>> RemappedFileBuffers;
- /// \brief Whether the compiler instance should retain (i.e., not free)
+ /// Whether the compiler instance should retain (i.e., not free)
/// the buffers associated with remapped files.
///
/// This flag defaults to false; it can be set true only through direct
- /// manipulation of the compiler invocation object, in cases where the
+ /// manipulation of the compiler invocation object, in cases where the
/// compiler invocation and its buffers will be reused.
bool RetainRemappedFileBuffers = false;
-
- /// \brief The Objective-C++ ARC standard library that we should support,
+
+ /// 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 = ARCXX_nolib;
-
- /// \brief Records the set of modules
+
+ /// Records the set of modules
class FailedModulesSet {
llvm::StringSet<> Failed;
@@ -146,8 +158,8 @@ public:
Failed.insert(module);
}
};
-
- /// \brief The set of modules that failed to build.
+
+ /// The set of modules that failed to build.
///
/// This pointer will be shared among all of the compiler instances created
/// to (re)build modules, so that once a module fails to build anywhere,
@@ -173,8 +185,8 @@ public:
RemappedFiles.clear();
RemappedFileBuffers.clear();
}
-
- /// \brief Reset any options that are not considered when building a
+
+ /// Reset any options that are not considered when building a
/// module.
void resetNonModularOptions() {
Includes.clear();
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Token.h b/contrib/llvm/tools/clang/include/clang/Lex/Token.h
index 02a1fef70f2b..85bef728197d 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Token.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Token.h
@@ -73,7 +73,7 @@ public:
enum TokenFlags {
StartOfLine = 0x01, // At start of line or only after whitespace
// (considering the line after macro expansion).
- LeadingSpace = 0x02, // Whitespace exists before this token (considering
+ LeadingSpace = 0x02, // Whitespace exists before this token (considering
// whitespace after macro expansion).
DisableExpand = 0x04, // This identifier may never be macro expanded.
NeedsCleaning = 0x08, // Contained an escaped newline or trigraph.
@@ -102,24 +102,24 @@ public:
return is(K1) || isOneOf(K2, Ks...);
}
- /// \brief Return true if this is a raw identifier (when lexing
+ /// Return true if this is a raw identifier (when lexing
/// in raw mode) or a non-keyword identifier (when lexing in non-raw mode).
bool isAnyIdentifier() const {
return tok::isAnyIdentifier(getKind());
}
- /// \brief Return true if this is a "literal", like a numeric
+ /// Return true if this is a "literal", like a numeric
/// constant, string, etc.
bool isLiteral() const {
return tok::isLiteral(getKind());
}
- /// \brief Return true if this is any of tok::annot_* kind tokens.
+ /// Return true if this is any of tok::annot_* kind tokens.
bool isAnnotation() const {
return tok::isAnnotation(getKind());
}
- /// \brief Return a source location identifier for the specified
+ /// Return a source location identifier for the specified
/// offset in the current file.
SourceLocation getLocation() const {
return SourceLocation::getFromRawEncoding(Loc);
@@ -153,7 +153,7 @@ public:
: getLocation().getLocWithOffset(getLength());
}
- /// \brief SourceRange of the group of tokens that this annotation token
+ /// SourceRange of the group of tokens that this annotation token
/// represents.
SourceRange getAnnotationRange() const {
return SourceRange(getLocation(), getAnnotationEndLoc());
@@ -165,7 +165,7 @@ public:
const char *getName() const { return tok::getTokenName(Kind); }
- /// \brief Reset all flags to cleared.
+ /// Reset all flags to cleared.
void startToken() {
Kind = tok::unknown;
Flags = 0;
@@ -230,22 +230,22 @@ public:
PtrData = val;
}
- /// \brief Set the specified flag.
+ /// Set the specified flag.
void setFlag(TokenFlags Flag) {
Flags |= Flag;
}
- /// \brief Get the specified flag.
+ /// Get the specified flag.
bool getFlag(TokenFlags Flag) const {
return (Flags & Flag) != 0;
}
- /// \brief Unset the specified flag.
+ /// Unset the specified flag.
void clearFlag(TokenFlags Flag) {
Flags &= ~Flag;
}
- /// \brief Return the internal represtation of the flags.
+ /// Return the internal represtation of the flags.
///
/// This is only intended for low-level operations such as writing tokens to
/// disk.
@@ -253,7 +253,7 @@ public:
return Flags;
}
- /// \brief Set a flag to either true or false.
+ /// Set a flag to either true or false.
void setFlagValue(TokenFlags Flag, bool Val) {
if (Val)
setFlag(Flag);
@@ -265,28 +265,28 @@ public:
///
bool isAtStartOfLine() const { return getFlag(StartOfLine); }
- /// \brief Return true if this token has whitespace before it.
+ /// Return true if this token has whitespace before it.
///
bool hasLeadingSpace() const { return getFlag(LeadingSpace); }
- /// \brief Return true if this identifier token should never
+ /// Return true if this identifier token should never
/// be expanded in the future, due to C99 6.10.3.4p2.
bool isExpandDisabled() const { return getFlag(DisableExpand); }
- /// \brief Return true if we have an ObjC keyword identifier.
+ /// Return true if we have an ObjC keyword identifier.
bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const;
- /// \brief Return the ObjC keyword kind.
+ /// Return the ObjC keyword kind.
tok::ObjCKeywordKind getObjCKeywordID() const;
- /// \brief Return true if this token has trigraphs or escaped newlines in it.
+ /// Return true if this token has trigraphs or escaped newlines in it.
bool needsCleaning() const { return getFlag(NeedsCleaning); }
- /// \brief Return true if this token has an empty macro before it.
+ /// Return true if this token has an empty macro before it.
///
bool hasLeadingEmptyMacro() const { return getFlag(LeadingEmptyMacro); }
- /// \brief Return true if this token is a string or character literal which
+ /// Return true if this token is a string or character literal which
/// has a ud-suffix.
bool hasUDSuffix() const { return getFlag(HasUDSuffix); }
@@ -308,21 +308,21 @@ public:
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
};
-/// \brief Information about the conditional stack (\#if directives)
+/// Information about the conditional stack (\#if directives)
/// currently active.
struct PPConditionalInfo {
- /// \brief Location where the conditional started.
+ /// Location where the conditional started.
SourceLocation IfLoc;
- /// \brief True if this was contained in a skipping directive, e.g.,
+ /// True if this was contained in a skipping directive, e.g.,
/// in a "\#if 0" block.
bool WasSkipping;
- /// \brief True if we have emitted tokens already, and now we're in
+ /// True if we have emitted tokens already, and now we're in
/// an \#else block or something. Only useful in Skipping blocks.
bool FoundNonSkip;
- /// \brief True if we've seen a \#else in this block. If so,
+ /// True if we've seen a \#else in this block. If so,
/// \#elif/\#else directives are not allowed.
bool FoundElse;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h
index a2d98b0d473a..60c182b509a4 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h
@@ -58,8 +58,8 @@ namespace clang {
public:
TokenConcatenation(Preprocessor &PP);
- bool AvoidConcat(const Token &PrevPrevTok,
- const Token &PrevTok,
+ bool AvoidConcat(const Token &PrevPrevTok,
+ const Token &PrevTok,
const Token &Tok) const;
private:
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
index b8b0beabf2ba..98935ad9c4fa 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -62,18 +62,18 @@ class TokenLexer {
/// expanded.
SourceLocation ExpandLocStart, ExpandLocEnd;
- /// \brief Source location pointing at the source location entry chunk that
+ /// Source location pointing at the source location entry chunk that
/// was reserved for the current macro expansion.
SourceLocation MacroExpansionStart;
-
- /// \brief The offset of the macro expansion in the
+
+ /// The offset of the macro expansion in the
/// "source location address space".
unsigned MacroStartSLocOffset;
- /// \brief Location of the macro definition.
+ /// Location of the macro definition.
SourceLocation MacroDefStart;
- /// \brief Length of the macro definition.
+ /// Length of the macro definition.
unsigned MacroDefLength;
/// Lexical information about the expansion point of the macro: the identifier
@@ -198,7 +198,7 @@ private:
/// 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
+ /// \param[in] VCtx - contains relevant contextual information about the
/// state of the tokens around and including the __VA_OPT__ token, necessary
/// for stringification.
void stringifyVAOPTContents(SmallVectorImpl<Token> &ReplacementToks,
@@ -216,12 +216,12 @@ private:
/// first token on the next line.
void HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc);
- /// \brief If \p loc is a FileID and points inside the current macro
+ /// If \p loc is a FileID and points inside the current macro
/// definition, returns the appropriate source location pointing at the
/// macro expansion source location entry.
SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const;
- /// \brief Creates SLocEntries and updates the locations of macro argument
+ /// Creates SLocEntries and updates the locations of macro argument
/// tokens to their new expanded locations.
///
/// \param ArgIdSpellLoc the location of the macro argument id inside the
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h
index cebaf15187de..3a7a955953f4 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h
@@ -55,7 +55,7 @@ namespace clang {
/// 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
+ /// occurred 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);
@@ -66,15 +66,15 @@ namespace clang {
~VariadicMacroScopeGuard() { exitScope(); }
};
- /// \brief A class for tracking whether we're inside a VA_OPT during a
+ /// 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__) {}
@@ -86,12 +86,12 @@ namespace clang {
/// 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 {
@@ -107,16 +107,16 @@ namespace clang {
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
+ /// 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 {
@@ -133,11 +133,11 @@ namespace clang {
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");
@@ -169,14 +169,14 @@ namespace clang {
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");
@@ -185,13 +185,13 @@ namespace clang {
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");
@@ -219,7 +219,7 @@ namespace clang {
using VAOptDefinitionContext::isInVAOpt;
using VAOptDefinitionContext::sawClosingParen;
using VAOptDefinitionContext::sawOpeningParen;
-
+
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
index 34c96816ebdf..f6e78ac2ca56 100644
--- a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
+++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
@@ -23,7 +23,7 @@ namespace clang {
class CodeCompleteConsumer;
class Sema;
- /// \brief Parse the entire file specified, notifying the ASTConsumer as
+ /// Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.
///
/// This operation inserts the parsed decls into the translation
@@ -42,7 +42,7 @@ namespace clang {
CodeCompleteConsumer *CompletionConsumer = nullptr,
bool SkipFunctionBodies = false);
- /// \brief Parse the main file known to the preprocessor, producing an
+ /// Parse the main file known to the preprocessor, producing an
/// abstract syntax tree.
void ParseAST(Sema &S, bool PrintStats = false,
bool SkipFunctionBodies = false);
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
index a606d785304a..69bf88a371db 100644
--- a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
+++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_PARSE_PARSER_H
#include "clang/AST/Availability.h"
+#include "clang/Basic/BitmaskEnum.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Basic/Specifiers.h"
@@ -45,7 +46,6 @@ namespace clang {
class ColonProtectionRAIIObject;
class InMessageExpressionRAIIObject;
class PoisonSEHIdentifiersRAIIObject;
- class VersionTuple;
class OMPClause;
class ObjCTypeParamList;
class ObjCTypeParameter;
@@ -121,25 +121,25 @@ class Parser : public CodeCompletionHandler {
/// Objective-C contextual keywords.
mutable IdentifierInfo *Ident_instancetype;
- /// \brief Identifier for "introduced".
+ /// Identifier for "introduced".
IdentifierInfo *Ident_introduced;
- /// \brief Identifier for "deprecated".
+ /// Identifier for "deprecated".
IdentifierInfo *Ident_deprecated;
- /// \brief Identifier for "obsoleted".
+ /// Identifier for "obsoleted".
IdentifierInfo *Ident_obsoleted;
- /// \brief Identifier for "unavailable".
+ /// Identifier for "unavailable".
IdentifierInfo *Ident_unavailable;
-
- /// \brief Identifier for "message".
+
+ /// Identifier for "message".
IdentifierInfo *Ident_message;
- /// \brief Identifier for "strict".
+ /// Identifier for "strict".
IdentifierInfo *Ident_strict;
- /// \brief Identifier for "replacement".
+ /// Identifier for "replacement".
IdentifierInfo *Ident_replacement;
/// Identifiers used by the 'external_source_symbol' attribute.
@@ -179,12 +179,16 @@ class Parser : public CodeCompletionHandler {
std::unique_ptr<PragmaHandler> MSSection;
std::unique_ptr<PragmaHandler> MSRuntimeChecks;
std::unique_ptr<PragmaHandler> MSIntrinsic;
+ std::unique_ptr<PragmaHandler> MSOptimize;
std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler;
std::unique_ptr<PragmaHandler> OptimizeHandler;
std::unique_ptr<PragmaHandler> LoopHintHandler;
std::unique_ptr<PragmaHandler> UnrollHintHandler;
std::unique_ptr<PragmaHandler> NoUnrollHintHandler;
std::unique_ptr<PragmaHandler> FPHandler;
+ std::unique_ptr<PragmaHandler> STDCFENVHandler;
+ std::unique_ptr<PragmaHandler> STDCCXLIMITHandler;
+ std::unique_ptr<PragmaHandler> STDCUnknownHandler;
std::unique_ptr<PragmaHandler> AttributePragmaHandler;
std::unique_ptr<CommentHandler> CommentSemaHandler;
@@ -201,7 +205,7 @@ class Parser : public CodeCompletionHandler {
/// ColonProtectionRAIIObject RAII object.
bool ColonIsSacred;
- /// \brief When true, we are directly inside an Objective-C message
+ /// When true, we are directly inside an Objective-C message
/// send expression.
///
/// This is managed by the \c InMessageExpressionRAIIObject class, and
@@ -211,7 +215,7 @@ class Parser : public CodeCompletionHandler {
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
- /// \brief RAII class that manages the template parameter depth.
+ /// RAII class that manages the template parameter depth.
class TemplateParameterDepthRAII {
unsigned &Depth;
unsigned AddedLevels;
@@ -234,16 +238,100 @@ class Parser : public CodeCompletionHandler {
unsigned getDepth() const { return Depth; }
};
- /// Factory object for creating AttributeList objects.
+ /// Factory object for creating ParsedAttr objects.
AttributeFactory AttrFactory;
- /// \brief Gathers and cleans up TemplateIdAnnotations when parsing of a
+ /// Gathers and cleans up TemplateIdAnnotations when parsing of a
/// top-level declaration is finished.
SmallVector<TemplateIdAnnotation *, 16> TemplateIds;
- /// \brief Identifiers which have been declared within a tentative parse.
+ /// Identifiers which have been declared within a tentative parse.
SmallVector<IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;
+ /// Tracker for '<' tokens that might have been intended to be treated as an
+ /// angle bracket instead of a less-than comparison.
+ ///
+ /// This happens when the user intends to form a template-id, but typoes the
+ /// template-name or forgets a 'template' keyword for a dependent template
+ /// name.
+ ///
+ /// We track these locations from the point where we see a '<' with a
+ /// name-like expression on its left until we see a '>' or '>>' that might
+ /// match it.
+ struct AngleBracketTracker {
+ /// Flags used to rank candidate template names when there is more than one
+ /// '<' in a scope.
+ enum Priority : unsigned short {
+ /// A non-dependent name that is a potential typo for a template name.
+ PotentialTypo = 0x0,
+ /// A dependent name that might instantiate to a template-name.
+ DependentName = 0x2,
+
+ /// A space appears before the '<' token.
+ SpaceBeforeLess = 0x0,
+ /// No space before the '<' token
+ NoSpaceBeforeLess = 0x1,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ DependentName)
+ };
+
+ struct Loc {
+ Expr *TemplateName;
+ SourceLocation LessLoc;
+ AngleBracketTracker::Priority Priority;
+ unsigned short ParenCount, BracketCount, BraceCount;
+
+ bool isActive(Parser &P) const {
+ return P.ParenCount == ParenCount && P.BracketCount == BracketCount &&
+ P.BraceCount == BraceCount;
+ }
+
+ bool isActiveOrNested(Parser &P) const {
+ return isActive(P) || P.ParenCount > ParenCount ||
+ P.BracketCount > BracketCount || P.BraceCount > BraceCount;
+ }
+ };
+
+ SmallVector<Loc, 8> Locs;
+
+ /// Add an expression that might have been intended to be a template name.
+ /// In the case of ambiguity, we arbitrarily select the innermost such
+ /// expression, for example in 'foo < bar < baz', 'bar' is the current
+ /// candidate. No attempt is made to track that 'foo' is also a candidate
+ /// for the case where we see a second suspicious '>' token.
+ void add(Parser &P, Expr *TemplateName, SourceLocation LessLoc,
+ Priority Prio) {
+ if (!Locs.empty() && Locs.back().isActive(P)) {
+ if (Locs.back().Priority <= Prio) {
+ Locs.back().TemplateName = TemplateName;
+ Locs.back().LessLoc = LessLoc;
+ Locs.back().Priority = Prio;
+ }
+ } else {
+ Locs.push_back({TemplateName, LessLoc, Prio,
+ P.ParenCount, P.BracketCount, P.BraceCount});
+ }
+ }
+
+ /// Mark the current potential missing template location as having been
+ /// handled (this happens if we pass a "corresponding" '>' or '>>' token
+ /// or leave a bracket scope).
+ void clear(Parser &P) {
+ while (!Locs.empty() && Locs.back().isActiveOrNested(P))
+ Locs.pop_back();
+ }
+
+ /// Get the current enclosing expression that might hve been intended to be
+ /// a template name.
+ Loc *getCurrent(Parser &P) {
+ if (!Locs.empty() && Locs.back().isActive(P))
+ return &Locs.back();
+ return nullptr;
+ }
+ };
+
+ AngleBracketTracker AngleBrackets;
+
IdentifierInfo *getSEHExceptKeyword();
/// True if we are within an Objective-C container while parsing C-like decls.
@@ -376,15 +464,15 @@ private:
/// isTokenParen - Return true if the cur token is '(' or ')'.
bool isTokenParen() const {
- return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren;
+ return Tok.isOneOf(tok::l_paren, tok::r_paren);
}
/// isTokenBracket - Return true if the cur token is '[' or ']'.
bool isTokenBracket() const {
- return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square;
+ return Tok.isOneOf(tok::l_square, tok::r_square);
}
/// isTokenBrace - Return true if the cur token is '{' or '}'.
bool isTokenBrace() const {
- return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace;
+ return Tok.isOneOf(tok::l_brace, tok::r_brace);
}
/// isTokenStringLiteral - True if this token is a string-literal.
bool isTokenStringLiteral() const {
@@ -396,11 +484,11 @@ private:
isTokenBrace() || Tok.is(tok::code_completion) || Tok.isAnnotation();
}
- /// \brief Returns true if the current token is '=' or is a type of '='.
+ /// Returns true if the current token is '=' or is a type of '='.
/// For typos, give a fixit to '='
bool isTokenEqualOrEqualTypo();
- /// \brief Return the current token to the token stream and make the given
+ /// Return the current token to the token stream and make the given
/// token the current token.
void UnconsumeToken(Token &Consumed) {
Token Next = Tok;
@@ -423,8 +511,10 @@ private:
assert(isTokenParen() && "wrong consume method");
if (Tok.getKind() == tok::l_paren)
++ParenCount;
- else if (ParenCount)
+ else if (ParenCount) {
+ AngleBrackets.clear(*this);
--ParenCount; // Don't let unbalanced )'s drive the count negative.
+ }
PrevTokLocation = Tok.getLocation();
PP.Lex(Tok);
return PrevTokLocation;
@@ -436,8 +526,10 @@ private:
assert(isTokenBracket() && "wrong consume method");
if (Tok.getKind() == tok::l_square)
++BracketCount;
- else if (BracketCount)
+ else if (BracketCount) {
+ AngleBrackets.clear(*this);
--BracketCount; // Don't let unbalanced ]'s drive the count negative.
+ }
PrevTokLocation = Tok.getLocation();
PP.Lex(Tok);
@@ -450,8 +542,10 @@ private:
assert(isTokenBrace() && "wrong consume method");
if (Tok.getKind() == tok::l_brace)
++BraceCount;
- else if (BraceCount)
+ else if (BraceCount) {
+ AngleBrackets.clear(*this);
--BraceCount; // Don't let unbalanced }'s drive the count negative.
+ }
PrevTokLocation = Tok.getLocation();
PP.Lex(Tok);
@@ -470,7 +564,7 @@ private:
return PrevTokLocation;
}
- /// \brief Consume the current code-completion token.
+ /// Consume the current code-completion token.
///
/// This routine can be called to consume the code-completion token and
/// continue processing in special cases where \c cutOffParsing() isn't
@@ -489,7 +583,7 @@ private:
/// \returns the source location of the code-completion token.
SourceLocation handleUnexpectedCodeCompletionToken();
- /// \brief Abruptly cut off parsing; mainly used when we have reached the
+ /// Abruptly cut off parsing; mainly used when we have reached the
/// code-completion point.
void cutOffParsing() {
if (PP.isCodeCompletionEnabled())
@@ -498,7 +592,7 @@ private:
Tok.setKind(tok::eof);
}
- /// \brief Determine if we're at the end of the file or at a transition
+ /// Determine if we're at the end of the file or at a transition
/// between modules.
bool isEofOrEom() {
tok::TokenKind Kind = Tok.getKind();
@@ -506,34 +600,34 @@ 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.
+ /// 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.
+ /// Checks if the \p Kind is a valid operator for fold expressions.
bool isFoldOperator(tok::TokenKind Kind) const;
- /// \brief Initialize all pragma handlers.
+ /// Initialize all pragma handlers.
void initializePragmaHandlers();
- /// \brief Destroy and reset all pragma handlers.
+ /// Destroy and reset all pragma handlers.
void resetPragmaHandlers();
- /// \brief Handle the annotation token produced for #pragma unused(...)
+ /// Handle the annotation token produced for #pragma unused(...)
void HandlePragmaUnused();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma GCC visibility...
void HandlePragmaVisibility();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma pack...
void HandlePragmaPack();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma ms_struct...
void HandlePragmaMSStruct();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma comment...
void HandlePragmaMSComment();
@@ -549,43 +643,43 @@ private:
bool HandlePragmaMSInitSeg(StringRef PragmaName,
SourceLocation PragmaLocation);
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma align...
void HandlePragmaAlign();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma clang __debug dump...
void HandlePragmaDump();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma weak id...
void HandlePragmaWeak();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma weak id = id...
void HandlePragmaWeakAlias();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma redefine_extname...
void HandlePragmaRedefineExtname();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma STDC FP_CONTRACT...
void HandlePragmaFPContract();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma clang fp ...
void HandlePragmaFP();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma OPENCL EXTENSION...
void HandlePragmaOpenCLExtension();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma clang __debug captured
StmtResult HandlePragmaCaptured();
- /// \brief Handle the annotation token produced for
+ /// Handle the annotation token produced for
/// #pragma clang loop and #pragma unroll.
bool HandlePragmaLoopHint(LoopHint &Hint);
@@ -624,13 +718,13 @@ private:
Tok.setAnnotationValue(T.getAsOpaquePtr());
}
- /// \brief Read an already-translated primary expression out of an annotation
+ /// Read an already-translated primary expression out of an annotation
/// token.
static ExprResult getExprAnnotation(const Token &Tok) {
return ExprResult::getFromOpaquePointer(Tok.getAnnotationValue());
}
- /// \brief Set the primary expression corresponding to the given annotation
+ /// Set the primary expression corresponding to the given annotation
/// token.
static void setExprAnnotation(Token &Tok, ExprResult ER) {
Tok.setAnnotationValue(ER.getAsOpaquePointer());
@@ -714,7 +808,7 @@ private:
/// otherwise emits a diagnostic and returns true.
bool TryKeywordIdentFallback(bool DisableKeyword);
- /// \brief Get the TemplateIdAnnotation from the token.
+ /// Get the TemplateIdAnnotation from the token.
TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
/// TentativeParsingAction - An object that is used as a kind of "tentative
@@ -812,14 +906,14 @@ private:
unsigned Diag = diag::err_expected,
StringRef DiagMsg = "");
- /// \brief The parser expects a semicolon and, if present, will consume it.
+ /// The parser expects a semicolon and, if present, will consume it.
///
/// If the next token is not a semicolon, this emits the specified diagnostic,
/// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior
/// to the semicolon, consumes that extra token.
bool ExpectAndConsumeSemi(unsigned DiagID);
- /// \brief The kind of extra semi diagnostic to emit.
+ /// The kind of extra semi diagnostic to emit.
enum ExtraSemiKind {
OutsideFunction = 0,
InsideStruct = 1,
@@ -827,7 +921,7 @@ private:
AfterMemberFunctionDefinition = 3
};
- /// \brief Consume any extra semi-colons until the end of the line.
+ /// Consume any extra semi-colons until the end of the line.
void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified);
/// Return false if the next token is an identifier. An 'expected identifier'
@@ -891,7 +985,7 @@ public:
void ExitScope();
private:
- /// \brief RAII object used to modify the scope flags for the current scope.
+ /// RAII object used to modify the scope flags for the current scope.
class ParseScopeFlags {
Scope *CurScope;
unsigned OldFlags;
@@ -920,10 +1014,10 @@ private:
public:
- /// \brief Control flags for SkipUntil functions.
+ /// Control flags for SkipUntil functions.
enum SkipUntilFlags {
StopAtSemi = 1 << 0, ///< Stop skipping at semicolon
- /// \brief Stop skipping at specified token, but don't skip the token itself
+ /// Stop skipping at specified token, but don't skip the token itself
StopBeforeMatch = 1 << 1,
StopAtCodeCompletion = 1 << 2 ///< Stop at code completion
};
@@ -1045,7 +1139,7 @@ private:
Decl *D;
CachedTokens Toks;
- /// \brief Whether this member function had an associated template
+ /// Whether this member function had an associated template
/// scope. When true, D is a template declaration.
/// otherwise, it is a member function declaration.
bool TemplateScope;
@@ -1091,9 +1185,9 @@ private:
/// Method - The method declaration.
Decl *Method;
- /// \brief Whether this member function had an associated template
+ /// Whether this member function had an associated template
/// scope. When true, D is a template declaration.
- /// othewise, it is a member function declaration.
+ /// otherwise, it is a member function declaration.
bool TemplateScope;
/// DefaultArgs - Contains the parameters of the function and
@@ -1102,8 +1196,8 @@ private:
/// method will be stored so that they can be reintroduced into
/// scope at the appropriate times.
SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
-
- /// \brief The set of tokens that make up an exception-specification that
+
+ /// The set of tokens that make up an exception-specification that
/// has not yet been parsed.
CachedTokens *ExceptionSpecTokens;
};
@@ -1131,11 +1225,11 @@ private:
/// C++ class, its method declarations that contain parts that won't be
/// parsed until after the definition is completed (C++ [class.mem]p2),
/// the method declarations and possibly attached inline definitions
- /// will be stored here with the tokens that will be parsed to create those
+ /// will be stored here with the tokens that will be parsed to create those
/// entities.
typedef SmallVector<LateParsedDeclaration*,2> LateParsedDeclarationsContainer;
- /// \brief Representation of a class that has been parsed, including
+ /// Representation of a class that has been parsed, including
/// any member function declarations or definitions that need to be
/// parsed after the corresponding top-level class is complete.
struct ParsingClass {
@@ -1143,19 +1237,19 @@ private:
: TopLevelClass(TopLevelClass), TemplateScope(false),
IsInterface(IsInterface), TagOrTemplate(TagOrTemplate) { }
- /// \brief Whether this is a "top-level" class, meaning that it is
+ /// Whether this is a "top-level" class, meaning that it is
/// not nested within another class.
bool TopLevelClass : 1;
- /// \brief Whether this class had an associated template
+ /// Whether this class had an associated template
/// scope. When true, TagOrTemplate is a template declaration;
- /// othewise, it is a tag declaration.
+ /// otherwise, it is a tag declaration.
bool TemplateScope : 1;
- /// \brief Whether this class is an __interface.
+ /// Whether this class is an __interface.
bool IsInterface : 1;
- /// \brief The class or class template whose definition we are parsing.
+ /// The class or class template whose definition we are parsing.
Decl *TagOrTemplate;
/// LateParsedDeclarations - Method declarations, inline definitions and
@@ -1164,7 +1258,7 @@ private:
LateParsedDeclarationsContainer LateParsedDeclarations;
};
- /// \brief The stack of classes that is currently being
+ /// The stack of classes that is currently being
/// parsed. Nested and local classes will be pushed onto this stack
/// when they are parsed, and removed afterward.
std::stack<ParsingClass *> ClassStack;
@@ -1174,7 +1268,7 @@ private:
return *ClassStack.top();
}
- /// \brief RAII object used to manage the parsing of a class definition.
+ /// RAII object used to manage the parsing of a class definition.
class ParsingClassDefinition {
Parser &P;
bool Popped;
@@ -1187,7 +1281,7 @@ private:
State(P.PushParsingClass(TagOrTemplate, TopLevelClass, IsInterface)) {
}
- /// \brief Pop this class of the stack.
+ /// Pop this class of the stack.
void Pop() {
assert(!Popped && "Nested class has already been popped");
Popped = true;
@@ -1200,7 +1294,7 @@ private:
}
};
- /// \brief Contains information about any template-specific
+ /// Contains information about any template-specific
/// information that has been parsed prior to parsing declaration
/// specifiers.
struct ParsedTemplateInfo {
@@ -1220,31 +1314,31 @@ private:
ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
LastParameterListWasEmpty(false){ }
- /// \brief The kind of template we are parsing.
+ /// The kind of template we are parsing.
enum {
- /// \brief We are not parsing a template at all.
+ /// We are not parsing a template at all.
NonTemplate = 0,
- /// \brief We are parsing a template declaration.
+ /// We are parsing a template declaration.
Template,
- /// \brief We are parsing an explicit specialization.
+ /// We are parsing an explicit specialization.
ExplicitSpecialization,
- /// \brief We are parsing an explicit instantiation.
+ /// We are parsing an explicit instantiation.
ExplicitInstantiation
} Kind;
- /// \brief The template parameter lists, for template declarations
+ /// The template parameter lists, for template declarations
/// and explicit specializations.
TemplateParameterLists *TemplateParams;
- /// \brief The location of the 'extern' keyword, if any, for an explicit
+ /// The location of the 'extern' keyword, if any, for an explicit
/// instantiation
SourceLocation ExternLoc;
- /// \brief The location of the 'template' keyword, for an explicit
+ /// The location of the 'template' keyword, for an explicit
/// instantiation.
SourceLocation TemplateLoc;
- /// \brief Whether the last template parameter list was empty.
+ /// Whether the last template parameter list was empty.
bool LastParameterListWasEmpty;
SourceRange getSourceRange() const LLVM_READONLY;
@@ -1267,11 +1361,11 @@ private:
};
NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS,
- AttributeList *AccessAttrs,
- ParsingDeclarator &D,
- const ParsedTemplateInfo &TemplateInfo,
- const VirtSpecifiers& VS,
- SourceLocation PureSpecLoc);
+ ParsedAttributes &AccessAttrs,
+ ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo,
+ const VirtSpecifiers &VS,
+ SourceLocation PureSpecLoc);
void ParseCXXNonStaticMemberInitializer(Decl *VarD);
void ParseLexedAttributes(ParsingClass &Class);
void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
@@ -1312,6 +1406,15 @@ private:
SourceRange Range;
};
+ struct ParsedAttributesViewWithRange : ParsedAttributesView {
+ ParsedAttributesViewWithRange() : ParsedAttributesView() {}
+ void clearListOnly() {
+ ParsedAttributesView::clearListOnly();
+ Range = SourceRange();
+ }
+
+ SourceRange Range;
+ };
DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS = nullptr);
@@ -1337,7 +1440,7 @@ private:
// Objective-C External Declarations
void MaybeSkipAttributes(tok::ObjCKeywordKind Kind);
- DeclGroupPtrTy ParseObjCAtDirectives();
+ DeclGroupPtrTy ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs);
DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParsedAttributes &prefixAttrs);
@@ -1475,6 +1578,7 @@ public:
ExprResult ParseConstantExpressionInExprEvalContext(
TypeCastState isTypeCast = NotTypeCast);
ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast);
+ ExprResult ParseCaseExpression(SourceLocation CaseLoc);
ExprResult ParseConstraintExpression();
// Expr that doesn't include commas.
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast);
@@ -1513,6 +1617,14 @@ private:
}
bool diagnoseUnknownTemplateId(ExprResult TemplateName, SourceLocation Less);
+ void checkPotentialAngleBracket(ExprResult &PotentialTemplateName);
+ bool checkPotentialAngleBracketDelimiter(const AngleBracketTracker::Loc &,
+ const Token &OpToken);
+ bool checkPotentialAngleBracketDelimiter(const Token &OpToken) {
+ if (auto *Info = AngleBrackets.getCurrent(*this))
+ return checkPotentialAngleBracketDelimiter(*Info, OpToken);
+ return false;
+ }
ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
ExprResult ParseUnaryExprOrTypeTraitExpression();
@@ -1541,6 +1653,7 @@ private:
/// ParenParseOption - Control what ParseParenExpression will parse.
enum ParenParseOption {
SimpleExpr, // Only parse '(' expression ')'
+ FoldExpr, // Also allow fold-expression <anything>
CompoundStmt, // Also allow '(' compound-statement ')'
CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
CastExpr // Also allow '(' type-name ')' <anything>
@@ -1561,7 +1674,7 @@ private:
ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false);
ExprResult ParseGenericSelectionExpression();
-
+
ExprResult ParseObjCBoolLiteral();
ExprResult ParseFoldExpression(ExprResult LHS, BalancedDelimiterTracker &T);
@@ -1641,7 +1754,8 @@ private:
//===--------------------------------------------------------------------===//
// C++0x 8: Function declaration trailing-return-type
- TypeResult ParseTrailingReturnType(SourceRange &Range);
+ TypeResult ParseTrailingReturnType(SourceRange &Range,
+ bool MayBeFollowedByDirectInit);
//===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
@@ -1722,7 +1836,7 @@ private:
SourceLocation LBracloc, SourceLocation SuperLoc,
ParsedType ReceiverType, Expr *ReceiverExpr);
bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
-
+
//===--------------------------------------------------------------------===//
// C99 6.8: Statements and Blocks.
@@ -1737,11 +1851,11 @@ private:
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
bool AllowOpenMPStandalone = false);
enum AllowedConstructsKind {
- /// \brief Allow any declarations, statements, OpenMP directives.
+ /// Allow any declarations, statements, OpenMP directives.
ACK_Any,
- /// \brief Allow only statements and non-standalone OpenMP directives.
+ /// Allow only statements and non-standalone OpenMP directives.
ACK_StatementsOpenMPNonStandalone,
- /// \brief Allow statements and all executable OpenMP directives
+ /// Allow statements and all executable OpenMP directives
ACK_StatementsOpenMPAnyExecutable
};
StmtResult
@@ -1782,34 +1896,34 @@ private:
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs);
- /// \brief Describes the behavior that should be taken for an __if_exists
+ /// Describes the behavior that should be taken for an __if_exists
/// block.
enum IfExistsBehavior {
- /// \brief Parse the block; this code is always used.
+ /// Parse the block; this code is always used.
IEB_Parse,
- /// \brief Skip the block entirely; this code is never used.
+ /// Skip the block entirely; this code is never used.
IEB_Skip,
- /// \brief Parse the block as a dependent block, which may be used in
+ /// Parse the block as a dependent block, which may be used in
/// some template instantiations but not others.
IEB_Dependent
};
- /// \brief Describes the condition of a Microsoft __if_exists or
+ /// Describes the condition of a Microsoft __if_exists or
/// __if_not_exists block.
struct IfExistsCondition {
- /// \brief The location of the initial keyword.
+ /// The location of the initial keyword.
SourceLocation KeywordLoc;
- /// \brief Whether this is an __if_exists block (rather than an
+ /// Whether this is an __if_exists block (rather than an
/// __if_not_exists block).
bool IsIfExists;
- /// \brief Nested-name-specifier preceding the name.
+ /// Nested-name-specifier preceding the name.
CXXScopeSpec SS;
- /// \brief The name we're looking for.
+ /// The name we're looking for.
UnqualifiedId Name;
- /// \brief The behavior of this __if_exists or __if_not_exists block
+ /// The behavior of this __if_exists or __if_not_exists block
/// should.
IfExistsBehavior Behavior;
};
@@ -1818,7 +1932,8 @@ private:
void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
void ParseMicrosoftIfExistsExternalDeclaration();
void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
- AccessSpecifier& CurAS);
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier &CurAS);
bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
bool &InitExprsOk);
bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
@@ -1942,7 +2057,7 @@ private:
Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
- /// \brief When in code-completion, skip parsing of the function/method body
+ /// When in code-completion, skip parsing of the function/method body
/// unless the body contains the code-completion point.
///
/// \returns true if the function body was skipped.
@@ -1950,7 +2065,7 @@ private:
bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
- AccessSpecifier AS, DeclSpecContext DSC,
+ AccessSpecifier AS, DeclSpecContext DSC,
ParsedAttributesWithRange &Attrs);
DeclSpecContext
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context);
@@ -1990,7 +2105,7 @@ private:
/// specifier or if we're not sure.
bool isKnownToBeTypeSpecifier(const Token &Tok) const;
- /// \brief Return true if we know that we are definitely looking at a
+ /// Return true if we know that we are definitely looking at a
/// decl-specifier, and isn't part of an expression such as a function-style
/// cast. Return false if it's no a decl-specifier, or we're not sure.
bool isKnownToBeDeclarationSpecifier() {
@@ -2018,19 +2133,19 @@ private:
return isDeclarationSpecifier(true);
}
- /// \brief Determine whether this is a C++1z for-range-identifier.
+ /// Determine whether this is a C++1z for-range-identifier.
bool isForRangeIdentifier();
- /// \brief Determine whether we are currently at the start of an Objective-C
+ /// Determine whether we are currently at the start of an Objective-C
/// class message that appears to be missing the open bracket '['.
bool isStartOfObjCClassMessageMissingOpenBracket();
- /// \brief Starting with a scope specifier, identifier, or
+ /// Starting with a scope specifier, identifier, or
/// template-id that refers to the current class, determine whether
/// this is a constructor declarator.
bool isConstructorDeclarator(bool Unqualified, bool DeductionGuide = false);
- /// \brief Specifies the context in which type-id/expression
+ /// Specifies the context in which type-id/expression
/// disambiguation will occur.
enum TentativeCXXTypeIdContext {
TypeIdInParens,
@@ -2053,7 +2168,7 @@ private:
return isTypeIdInParens(isAmbiguous);
}
- /// \brief Checks if the current tokens form type-id or expression.
+ /// Checks if the current tokens form type-id or expression.
/// It is similar to isTypeIdInParens but does not suppose that type-id
/// is in parenthesis.
bool isTypeIdUnambiguously() {
@@ -2078,7 +2193,7 @@ private:
/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
/// a constructor-style initializer, when parsing declaration statements.
/// Returns true for function declarator and false for constructor-style
- /// initializer. Sets 'IsAmbiguous' to true to indicate that this declaration
+ /// initializer. Sets 'IsAmbiguous' to true to indicate that this declaration
/// might be a constructor-style initializer.
/// If during the disambiguation process a parsing error is encountered,
/// the function returns true to let the declaration parsing code handle it.
@@ -2091,7 +2206,7 @@ private:
InitStmtDecl, ///< Disambiguated as a simple-declaration init-statement.
Error ///< Can't be any of the above!
};
- /// \brief Disambiguates between the different kinds of things that can happen
+ /// Disambiguates between the different kinds of things that can happen
/// after 'if (' or 'switch ('. This could be one of two different kinds of
/// declaration (depending on whether there is a ';' later) or an expression.
ConditionOrInitStatement
@@ -2109,7 +2224,7 @@ private:
True, False, Ambiguous, Error
};
- /// \brief Based only on the given token kind, determine whether we know that
+ /// Based only on the given token kind, determine whether we know that
/// we're at the start of an expression or a type-specifier-seq (which may
/// be an expression, in C++).
///
@@ -2137,7 +2252,7 @@ private:
/// a type-specifier other than a cv-qualifier.
bool isCXXDeclarationSpecifierAType();
- /// \brief Determine whether an identifier has been tentatively declared as a
+ /// Determine whether an identifier has been tentatively declared as a
/// non-type. Such tentative declarations should not be found to name a type
/// during a tentative parse, but also should not be annotated as a non-type.
bool isTentativelyDeclared(IdentifierInfo *II);
@@ -2155,7 +2270,8 @@ private:
TPResult TryParsePtrOperatorSeq();
TPResult TryParseOperatorId();
TPResult TryParseInitDeclaratorList();
- TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
+ TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true,
+ bool mayHaveDirectInit = false);
TPResult
TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr,
bool VersusTemplateArg = false);
@@ -2204,16 +2320,25 @@ private:
void stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
DeclSpec &DS, Sema::TagUseKind TUK);
-
+
// FixItLoc = possible correct location for the attributes
- void ProhibitAttributes(ParsedAttributesWithRange &attrs,
+ void ProhibitAttributes(ParsedAttributesWithRange &Attrs,
SourceLocation FixItLoc = SourceLocation()) {
- if (!attrs.Range.isValid()) return;
- DiagnoseProhibitedAttributes(attrs, FixItLoc);
- attrs.clear();
+ if (Attrs.Range.isInvalid())
+ return;
+ DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ Attrs.clear();
+ }
+
+ void ProhibitAttributes(ParsedAttributesViewWithRange &Attrs,
+ SourceLocation FixItLoc = SourceLocation()) {
+ if (Attrs.Range.isInvalid())
+ return;
+ DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ Attrs.clearListOnly();
}
- void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs,
- SourceLocation FixItLoc);
+ void DiagnoseProhibitedAttributes(const SourceRange &Range,
+ SourceLocation FixItLoc);
// Forbid C++11 and C2x attributes that appear on certain syntactic locations
// which standard permits but we don't supported yet, for example, attributes
@@ -2221,16 +2346,16 @@ private:
void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
unsigned DiagID);
- /// \brief Skip C++11 and C2x attributes and return the end location of the
+ /// 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 and C2x attributes that appear in syntactic
+ /// Diagnose and skip C++11 and C2x attributes that appear in syntactic
/// locations where attributes are not allowed.
void DiagnoseAndSkipCXX11Attributes();
- /// \brief Parses syntax-generic attribute arguments for attributes which are
+ /// Parses syntax-generic attribute arguments for attributes which are
/// known to the implementation, and adds them to the given ParsedAttributes
/// list with the given attribute syntax. Returns the number of arguments
/// parsed for the attribute.
@@ -2238,7 +2363,7 @@ private:
ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
void MaybeParseGNUAttributes(Declarator &D,
LateParsedAttrList *LateAttrs = nullptr) {
@@ -2261,19 +2386,16 @@ private:
Declarator *D = nullptr);
void ParseGNUAttributeArgs(IdentifierInfo *AttrName,
SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc,
- IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax,
- Declarator *D);
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax, Declarator *D);
IdentifierLoc *ParseIdentifierLoc();
unsigned
ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
void MaybeParseCXX11Attributes(Declarator &D) {
if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
@@ -2303,7 +2425,7 @@ private:
SourceLocation *EndLoc = nullptr);
void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
SourceLocation *EndLoc = nullptr);
- /// \brief Parses a C++11 (or C2x)-style attribute argument list. Returns true
+ /// 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,
@@ -2339,7 +2461,7 @@ private:
void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
void ParseOpenCLKernelAttributes(ParsedAttributes &attrs);
void ParseOpenCLQualifiers(ParsedAttributes &Attrs);
- /// \brief Parses opencl_unroll_hint attribute if language is OpenCL v2.0
+ /// Parses opencl_unroll_hint attribute if language is OpenCL v2.0
/// or higher.
/// \return false if error happens.
bool MaybeParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
@@ -2347,7 +2469,7 @@ private:
return ParseOpenCLUnrollHintAttribute(Attrs);
return true;
}
- /// \brief Parses opencl_unroll_hint attribute.
+ /// Parses opencl_unroll_hint attribute.
/// \return false if error happens.
bool ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs);
void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs);
@@ -2359,7 +2481,7 @@ private:
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
Optional<AvailabilitySpec> ParseAvailabilitySpec();
ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc);
@@ -2370,7 +2492,7 @@ private:
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
SourceLocation ObjCBridgeRelatedLoc,
@@ -2378,7 +2500,7 @@ private:
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
@@ -2386,15 +2508,13 @@ private:
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
- void ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc,
- IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ void
+ ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc, ParsedAttributes &Attrs,
+ SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax);
void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
@@ -2538,12 +2658,11 @@ private:
struct UsingDeclarator {
SourceLocation TypenameLoc;
CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
UnqualifiedId Name;
SourceLocation EllipsisLoc;
void clear() {
- TypenameLoc = TemplateKWLoc = EllipsisLoc = SourceLocation();
+ TypenameLoc = EllipsisLoc = SourceLocation();
SS.clear();
Name.clear();
}
@@ -2571,7 +2690,7 @@ private:
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS, bool EnteringContext,
- DeclSpecContext DSC,
+ DeclSpecContext DSC,
ParsedAttributesWithRange &Attributes);
void SkipCXXMemberSpecification(SourceLocation StartLoc,
SourceLocation AttrFixitLoc,
@@ -2591,7 +2710,7 @@ private:
void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D,
VirtSpecifiers &VS);
DeclGroupPtrTy ParseCXXClassMemberDeclaration(
- AccessSpecifier AS, AttributeList *Attr,
+ AccessSpecifier AS, ParsedAttributes &Attr,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(
@@ -2628,18 +2747,18 @@ private:
DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
CachedTokens &Toks,
SourceLocation Loc);
- /// \brief Parses declarative OpenMP directives.
+ /// Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
DeclSpec::TST TagType = DeclSpec::TST_unspecified,
Decl *TagDecl = nullptr);
- /// \brief Parse 'omp declare reduction' construct.
+ /// 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.
+ /// Parses simple list of variables.
///
/// \param Kind Kind of the directive.
/// \param Callback Callback function to be called for the list elements.
@@ -2651,7 +2770,7 @@ private:
const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
Callback,
bool AllowScopeSpecifier);
- /// \brief Parses declarative or executable directive.
+ /// Parses declarative or executable directive.
///
/// \param Allowed ACK_Any, if any directives are allowed,
/// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
@@ -2660,7 +2779,7 @@ private:
///
StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(AllowedConstructsKind Allowed);
- /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
+ /// Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
/// \param CKind Kind of current clause.
@@ -2669,33 +2788,45 @@ private:
///
OMPClause *ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause);
- /// \brief Parses clause with a single expression of a kind \a Kind.
+ /// Parses clause with a single expression of a kind \a Kind.
///
/// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
///
- OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind);
- /// \brief Parses simple clause of a kind \a Kind.
+ OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ bool ParseOnly);
+ /// Parses simple clause of a kind \a Kind.
///
/// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
///
- OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind);
- /// \brief Parses clause with a single expression and an additional argument
+ OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly);
+ /// Parses clause with a single expression and an additional argument
/// of a kind \a Kind.
///
/// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
///
- OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind);
- /// \brief Parses clause without any additional arguments.
+ OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
+ bool ParseOnly);
+ /// Parses clause without any additional arguments.
///
/// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
///
- OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind);
- /// \brief Parses clause with the list of variables of a kind \a Kind.
+ OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly = false);
+ /// Parses clause with the list of variables of a kind \a Kind.
///
/// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
///
OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
- OpenMPClauseKind Kind);
+ OpenMPClauseKind Kind, bool ParseOnly);
public:
/// Parses simple expression in parens for single-expression clauses of OpenMP
@@ -2707,6 +2838,7 @@ public:
struct OpenMPVarListDataTy {
Expr *TailExpr = nullptr;
SourceLocation ColonLoc;
+ SourceLocation RLoc;
CXXScopeSpec ReductionIdScopeSpec;
DeclarationNameInfo ReductionId;
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
@@ -2726,7 +2858,7 @@ public:
bool AllowConstructorName,
bool AllowDeductionGuide,
ParsedType ObjectType,
- SourceLocation& TemplateKWLoc,
+ SourceLocation *TemplateKWLoc,
UnqualifiedId &Result);
private:
@@ -2735,20 +2867,17 @@ private:
// C++ 14.1: Template Parameters [temp.param]
Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
- SourceLocation &DeclEnd,
- AccessSpecifier AS = AS_none,
- AttributeList *AccessAttrs = nullptr);
+ SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS = AS_none);
Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
SourceLocation &DeclEnd,
- AccessSpecifier AS,
- AttributeList *AccessAttrs);
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS);
Decl *ParseSingleDeclarationAfterTemplate(
- DeclaratorContext Context,
- const ParsedTemplateInfo &TemplateInfo,
- ParsingDeclRAIIObject &DiagsFromParams,
- SourceLocation &DeclEnd,
- AccessSpecifier AS=AS_none,
- AttributeList *AccessAttrs = nullptr);
+ DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none);
bool ParseTemplateParameters(unsigned Depth,
SmallVectorImpl<NamedDecl *> &TemplateParams,
SourceLocation &LAngleLoc,
@@ -2791,6 +2920,7 @@ private:
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
AccessSpecifier AS = AS_none);
//===--------------------------------------------------------------------===//
@@ -2814,7 +2944,7 @@ private:
//===--------------------------------------------------------------------===//
// C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseTypeTrait();
-
+
//===--------------------------------------------------------------------===//
// Embarcadero: Arary and Expression Traits
ExprResult ParseArrayTypeTrait();
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/include/clang/Parse/RAIIObjectsForParser.h
index acaeb442a21a..ba5e5fe3c8fb 100644
--- a/contrib/llvm/tools/clang/include/clang/Parse/RAIIObjectsForParser.h
+++ b/contrib/llvm/tools/clang/include/clang/Parse/RAIIObjectsForParser.h
@@ -25,7 +25,7 @@ namespace clang {
// TODO: move ParsingClassDefinition here.
// TODO: move TentativeParsingAction here.
- /// \brief A RAII object used to temporarily suppress access-like
+ /// A RAII object used to temporarily suppress access-like
/// checking. Access-like checks are those associated with
/// controlling the use of a declaration, like C++ access control
/// errors and deprecation warnings. They are contextually
@@ -49,7 +49,7 @@ namespace clang {
bool Active;
public:
- /// Begin suppressing access-like checks
+ /// Begin suppressing access-like checks
SuppressAccessChecks(Parser &P, bool activate = true)
: S(P.getActions()), DiagnosticPool(nullptr) {
if (activate) {
@@ -84,7 +84,7 @@ namespace clang {
}
};
- /// \brief RAII object used to inform the actions that we're
+ /// RAII object used to inform the actions that we're
/// currently parsing a declaration. This is active when parsing a
/// variable's initializer, but not when parsing the body of a
/// class or function definition.
@@ -264,7 +264,7 @@ namespace clang {
Diags.DecrementAllExtensionsSilenced();
}
};
-
+
/// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
/// restores it when destroyed. This says that "foo:" should not be
/// considered a possible typo for "foo::" for error recovery purposes.
@@ -276,19 +276,19 @@ namespace clang {
: P(p), OldVal(P.ColonIsSacred) {
P.ColonIsSacred = Value;
}
-
+
/// restore - This can be used to restore the state early, before the dtor
/// is run.
void restore() {
P.ColonIsSacred = OldVal;
}
-
+
~ColonProtectionRAIIObject() {
restore();
}
};
-
- /// \brief RAII object that makes '>' behave either as an operator
+
+ /// RAII object that makes '>' behave either as an operator
/// or as the closing angle bracket for a template argument list.
class GreaterThanIsOperatorScope {
bool &GreaterThanIsOperator;
@@ -298,29 +298,29 @@ namespace clang {
: GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
GreaterThanIsOperator = Val;
}
-
+
~GreaterThanIsOperatorScope() {
GreaterThanIsOperator = OldGreaterThanIsOperator;
}
};
-
+
class InMessageExpressionRAIIObject {
bool &InMessageExpression;
bool OldValue;
-
+
public:
InMessageExpressionRAIIObject(Parser &P, bool Value)
- : InMessageExpression(P.InMessageExpression),
+ : InMessageExpression(P.InMessageExpression),
OldValue(P.InMessageExpression) {
InMessageExpression = Value;
}
-
+
~InMessageExpressionRAIIObject() {
InMessageExpression = OldValue;
}
};
-
- /// \brief RAII object that makes sure paren/bracket/brace count is correct
+
+ /// RAII object that makes sure paren/bracket/brace count is correct
/// after declaration/statement parsing, even when there's a parsing error.
class ParenBraceBracketBalancer {
Parser &P;
@@ -329,8 +329,9 @@ namespace clang {
ParenBraceBracketBalancer(Parser &p)
: P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
BraceCount(p.BraceCount) { }
-
+
~ParenBraceBracketBalancer() {
+ P.AngleBrackets.clear(P);
P.ParenCount = ParenCount;
P.BracketCount = BracketCount;
P.BraceCount = BraceCount;
@@ -361,14 +362,14 @@ namespace clang {
}
};
- /// \brief RAII class that helps handle the parsing of an open/close delimiter
+ /// RAII class that helps handle the parsing of an open/close delimiter
/// pair, such as braces { ... } or parentheses ( ... ).
class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
Parser& P;
tok::TokenKind Kind, Close, FinalToken;
SourceLocation (Parser::*Consumer)();
SourceLocation LOpen, LClose;
-
+
unsigned short &getDepth() {
switch (Kind) {
case tok::l_brace: return P.BraceCount;
@@ -377,12 +378,10 @@ namespace clang {
default: llvm_unreachable("Wrong token kind");
}
}
-
- enum { MaxDepth = 256 };
-
+
bool diagnoseOverflow();
bool diagnoseMissingClose();
-
+
public:
BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
tok::TokenKind FinalToken = tok::semi)
@@ -392,34 +391,34 @@ namespace clang {
switch (Kind) {
default: llvm_unreachable("Unexpected balanced token");
case tok::l_brace:
- Close = tok::r_brace;
+ Close = tok::r_brace;
Consumer = &Parser::ConsumeBrace;
break;
case tok::l_paren:
- Close = tok::r_paren;
+ Close = tok::r_paren;
Consumer = &Parser::ConsumeParen;
break;
-
+
case tok::l_square:
- Close = tok::r_square;
+ Close = tok::r_square;
Consumer = &Parser::ConsumeBracket;
break;
- }
+ }
}
-
+
SourceLocation getOpenLocation() const { return LOpen; }
SourceLocation getCloseLocation() const { return LClose; }
SourceRange getRange() const { return SourceRange(LOpen, LClose); }
-
+
bool consumeOpen() {
if (!P.Tok.is(Kind))
return true;
-
+
if (getDepth() < P.getLangOpts().BracketDepth) {
LOpen = (P.*Consumer)();
return false;
}
-
+
return diagnoseOverflow();
}
@@ -437,13 +436,13 @@ namespace clang {
LClose = (P.*Consumer)();
return false;
}
-
+
return diagnoseMissingClose();
}
void skipToEnd();
};
- /// \brief RAIIObject to destroy the contents of a SmallVector of
+ /// RAIIObject to destroy the contents of a SmallVector of
/// TemplateIdAnnotation pointers and clear the vector.
class DestroyTemplateIdAnnotationsRAIIObj {
SmallVectorImpl<TemplateIdAnnotation *> &Container;
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h
index fbffb38e377d..f798e9fc41eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h
@@ -1,4 +1,4 @@
-//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- C++ -*-===//
+//===- DeltaTree.h - B-Tree for Rewrite Delta tracking ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,8 +14,6 @@
#ifndef LLVM_CLANG_REWRITE_CORE_DELTATREE_H
#define LLVM_CLANG_REWRITE_CORE_DELTATREE_H
-#include "llvm/Support/Compiler.h"
-
namespace clang {
/// DeltaTree - a multiway search tree (BTree) structure with some fancy
@@ -27,12 +25,14 @@ namespace clang {
/// as well, without traversing the whole tree.
class DeltaTree {
void *Root; // "DeltaTreeNode *"
- void operator=(const DeltaTree &) = delete;
+
public:
DeltaTree();
// Note: Currently we only support copying when the RHS is empty.
DeltaTree(const DeltaTree &RHS);
+
+ DeltaTree &operator=(const DeltaTree &) = delete;
~DeltaTree();
/// getDeltaAt - Return the accumulated delta at the specified file offset.
@@ -45,6 +45,7 @@ namespace clang {
/// into the current DeltaTree at offset FileIndex.
void AddDelta(unsigned FileIndex, int Delta);
};
-} // end namespace clang
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_REWRITE_CORE_DELTATREE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h
index 1fd7c7a3f84e..0f1f490d8305 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h
@@ -31,7 +31,8 @@ namespace html {
/// start/end tags are placed at the start/end of each line if the range is
/// multiline.
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
- const char *StartTag, const char *EndTag);
+ const char *StartTag, const char *EndTag,
+ bool IsTokenRange = true);
/// HighlightRange - Highlight a range in the source code with the specified
/// start/end tags. The Start/end of the range must be in the same file.
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h
index d69c69b81e48..c618298f5e82 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h
@@ -1,4 +1,4 @@
-//===--- RewriteBuffer.h - Buffer rewriting interface -----------*- C++ -*-===//
+//===- RewriteBuffer.h - Buffer rewriting interface -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,7 +16,6 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
- class Rewriter;
/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
/// input with modifications get a new RewriteBuffer associated with them. The
@@ -26,12 +25,16 @@ namespace clang {
/// locations after the insertion point have to be mapped.
class RewriteBuffer {
friend class Rewriter;
+
/// Deltas - Keep track of all the deltas in the source code due to insertions
/// and deletions.
DeltaTree Deltas;
+
RewriteRope Buffer;
+
public:
- typedef RewriteRope::const_iterator iterator;
+ using iterator = RewriteRope::const_iterator;
+
iterator begin() const { return Buffer.begin(); }
iterator end() const { return Buffer.end(); }
unsigned size() const { return Buffer.size(); }
@@ -45,7 +48,7 @@ public:
Initialize(Input.begin(), Input.end());
}
- /// \brief Write to \p Stream the result of applying all changes to the
+ /// Write to \p Stream the result of applying all changes to the
/// original buffer.
/// Note that it isn't safe to use this function to overwrite memory mapped
/// files in-place (PR17960). Consider using a higher-level utility such as
@@ -61,7 +64,6 @@ public:
/// InsertText - Insert some text at the specified point, where the offset in
/// the buffer is specified relative to the original SourceBuffer. The
/// text is inserted after the specified location.
- ///
void InsertText(unsigned OrigOffset, StringRef Str,
bool InsertAfter = true);
@@ -87,8 +89,7 @@ public:
void ReplaceText(unsigned OrigOffset, unsigned OrigLength,
StringRef NewStr);
-private: // Methods only usable by Rewriter.
-
+private:
/// getMappedOffset - Given an offset into the original SourceBuffer that this
/// RewriteBuffer is based on, map it into the offset space of the
/// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a
@@ -112,6 +113,6 @@ private: // Methods only usable by Rewriter.
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h
index 50025544854a..2a0e0a4a639b 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h
@@ -1,4 +1,4 @@
-//===--- RewriteRope.h - Rope specialized for rewriter ----------*- C++ -*-===//
+//===- RewriteRope.h - Rope specialized for rewriter ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,13 +16,13 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
-#include <cstring>
#include <iterator>
+#include <utility>
namespace clang {
+
//===--------------------------------------------------------------------===//
// RopeRefCountString Class
//===--------------------------------------------------------------------===//
@@ -58,11 +58,10 @@ namespace clang {
/// different offsets) which is a nice constant time operation.
struct RopePiece {
llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData;
- unsigned StartOffs;
- unsigned EndOffs;
-
- RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {}
+ unsigned StartOffs = 0;
+ unsigned EndOffs = 0;
+ RopePiece() = default;
RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start,
unsigned End)
: StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {}
@@ -88,18 +87,18 @@ namespace clang {
class RopePieceBTreeIterator :
public std::iterator<std::forward_iterator_tag, const char, ptrdiff_t> {
/// CurNode - The current B+Tree node that we are inspecting.
- const void /*RopePieceBTreeLeaf*/ *CurNode;
+ const void /*RopePieceBTreeLeaf*/ *CurNode = nullptr;
+
/// CurPiece - The current RopePiece in the B+Tree node that we're
/// inspecting.
- const RopePiece *CurPiece;
+ const RopePiece *CurPiece = nullptr;
+
/// CurChar - The current byte in the RopePiece we are pointing to.
- unsigned CurChar;
+ unsigned CurChar = 0;
+
public:
- // begin iterator.
+ RopePieceBTreeIterator() = default;
RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N);
- // end iterator
- RopePieceBTreeIterator()
- : CurNode(nullptr), CurPiece(nullptr), CurChar(0) {}
char operator*() const {
return (*CurPiece)[CurChar];
@@ -119,7 +118,8 @@ namespace clang {
MoveToNextPiece();
return *this;
}
- inline RopePieceBTreeIterator operator++(int) { // Postincrement
+
+ RopePieceBTreeIterator operator++(int) { // Postincrement
RopePieceBTreeIterator tmp = *this; ++*this; return tmp;
}
@@ -136,13 +136,15 @@ namespace clang {
class RopePieceBTree {
void /*RopePieceBTreeNode*/ *Root;
- void operator=(const RopePieceBTree &) = delete;
+
public:
RopePieceBTree();
RopePieceBTree(const RopePieceBTree &RHS);
+ RopePieceBTree &operator=(const RopePieceBTree &) = delete;
~RopePieceBTree();
- typedef RopePieceBTreeIterator iterator;
+ using iterator = RopePieceBTreeIterator;
+
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
unsigned size() const;
@@ -168,19 +170,18 @@ class RewriteRope {
/// We allocate space for string data out of a buffer of size AllocChunkSize.
/// This keeps track of how much space is left.
llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer;
- unsigned AllocOffs;
enum { AllocChunkSize = 4080 };
+ unsigned AllocOffs = AllocChunkSize;
public:
- RewriteRope() : AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {}
- RewriteRope(const RewriteRope &RHS)
- : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {
- }
+ RewriteRope() = default;
+ RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {}
+
+ using iterator = RopePieceBTree::iterator;
+ using const_iterator = RopePieceBTree::iterator;
- typedef RopePieceBTree::iterator iterator;
- typedef RopePieceBTree::iterator const_iterator;
iterator begin() const { return Chunks.begin(); }
- iterator end() const { return Chunks.end(); }
+ iterator end() const { return Chunks.end(); }
unsigned size() const { return Chunks.size(); }
void clear() {
@@ -209,6 +210,6 @@ private:
RopePiece MakeRopeString(const char *Start, const char *End);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h
index 800372ea557f..107968a9fb43 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h
@@ -1,4 +1,4 @@
-//===--- Rewriter.h - Code rewriting interface ------------------*- C++ -*-===//
+//===- Rewriter.h - Code rewriting interface --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,52 +15,55 @@
#ifndef LLVM_CLANG_REWRITE_CORE_REWRITER_H
#define LLVM_CLANG_REWRITE_CORE_REWRITER_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Rewrite/Core/RewriteBuffer.h"
-#include <cstring>
+#include "llvm/ADT/StringRef.h"
#include <map>
#include <string>
namespace clang {
- class LangOptions;
- class SourceManager;
+
+class LangOptions;
+class SourceManager;
/// Rewriter - This is the main interface to the rewrite buffers. Its primary
/// job is to dispatch high-level requests to the low-level RewriteBuffers that
/// are involved.
class Rewriter {
- SourceManager *SourceMgr;
- const LangOptions *LangOpts;
+ SourceManager *SourceMgr = nullptr;
+ const LangOptions *LangOpts = nullptr;
std::map<FileID, RewriteBuffer> RewriteBuffers;
+
public:
struct RewriteOptions {
- /// \brief Given a source range, true to include previous inserts at the
+ /// Given a source range, true to include previous inserts at the
/// beginning of the range as part of the range itself (true by default).
- bool IncludeInsertsAtBeginOfRange;
- /// \brief Given a source range, true to include previous inserts at the
+ bool IncludeInsertsAtBeginOfRange = true;
+
+ /// Given a source range, true to include previous inserts at the
/// end of the range as part of the range itself (true by default).
- bool IncludeInsertsAtEndOfRange;
- /// \brief If true and removing some text leaves a blank line
+ bool IncludeInsertsAtEndOfRange = true;
+
+ /// If true and removing some text leaves a blank line
/// also remove the empty line (false by default).
- bool RemoveLineIfEmpty;
+ bool RemoveLineIfEmpty = false;
- RewriteOptions()
- : IncludeInsertsAtBeginOfRange(true),
- IncludeInsertsAtEndOfRange(true),
- RemoveLineIfEmpty(false) { }
+ RewriteOptions() {}
};
- typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator;
- typedef std::map<FileID, RewriteBuffer>::const_iterator const_buffer_iterator;
+ using buffer_iterator = std::map<FileID, RewriteBuffer>::iterator;
+ using const_buffer_iterator = std::map<FileID, RewriteBuffer>::const_iterator;
+ explicit Rewriter() = default;
explicit Rewriter(SourceManager &SM, const LangOptions &LO)
- : SourceMgr(&SM), LangOpts(&LO) {}
- explicit Rewriter() : SourceMgr(nullptr), LangOpts(nullptr) {}
+ : SourceMgr(&SM), LangOpts(&LO) {}
void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
SourceMgr = &SM;
LangOpts = &LO;
}
+
SourceManager &getSourceMgr() const { return *SourceMgr; }
const LangOptions &getLangOpts() const { return *LangOpts; }
@@ -82,7 +85,6 @@ public:
/// in different buffers, this returns an empty string.
///
/// Note that this method is not particularly efficient.
- ///
std::string getRewrittenText(SourceRange Range) const;
/// InsertText - Insert the specified string at the specified location in the
@@ -103,7 +105,7 @@ public:
return InsertText(Loc, Str);
}
- /// \brief Insert the specified string after the token in the
+ /// Insert the specified string after the token in the
/// specified location.
bool InsertTextAfterToken(SourceLocation Loc, StringRef Str);
@@ -120,13 +122,13 @@ public:
bool RemoveText(SourceLocation Start, unsigned Length,
RewriteOptions opts = RewriteOptions());
- /// \brief Remove the specified text region.
+ /// Remove the specified text region.
bool RemoveText(CharSourceRange range,
RewriteOptions opts = RewriteOptions()) {
return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
}
- /// \brief Remove the specified text region.
+ /// Remove the specified text region.
bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) {
return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
}
@@ -149,7 +151,7 @@ public:
/// operation.
bool ReplaceText(SourceRange range, SourceRange replacementRange);
- /// \brief Increase indentation for the lines between the given source range.
+ /// Increase indentation for the lines between the given source range.
/// To determine what the indentation should be, 'parentIndent' is used
/// that should be at a source location with an indentation one degree
/// lower than the given range.
@@ -190,6 +192,6 @@ private:
unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_REWRITER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h
index 0f71e81c313e..ab2c2c8b0adb 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h
@@ -1,4 +1,4 @@
-//===--- TokenRewriter.h - Token-based Rewriter -----------------*- C++ -*-===//
+//===- TokenRewriter.h - Token-based Rewriter -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,13 +17,16 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Token.h"
+#include <cassert>
#include <list>
#include <map>
#include <memory>
namespace clang {
- class LangOptions;
- class ScratchBuffer;
+
+class LangOptions;
+class ScratchBuffer;
+class SourceManager;
class TokenRewriter {
/// TokenList - This is the list of raw tokens that make up this file. Each
@@ -31,7 +34,7 @@ namespace clang {
std::list<Token> TokenList;
/// TokenRefTy - This is the type used to refer to a token in the TokenList.
- typedef std::list<Token>::iterator TokenRefTy;
+ using TokenRefTy = std::list<Token>::iterator;
/// TokenAtLoc - This map indicates which token exists at a specific
/// SourceLocation. Since each token has a unique SourceLocation, this is a
@@ -40,23 +43,24 @@ namespace clang {
std::map<SourceLocation, TokenRefTy> TokenAtLoc;
/// ScratchBuf - This is the buffer that we create scratch tokens from.
- ///
std::unique_ptr<ScratchBuffer> ScratchBuf;
- TokenRewriter(const TokenRewriter &) = delete;
- void operator=(const TokenRewriter &) = delete;
public:
/// TokenRewriter - This creates a TokenRewriter for the file with the
/// specified FileID.
TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO);
+
+ TokenRewriter(const TokenRewriter &) = delete;
+ TokenRewriter &operator=(const TokenRewriter &) = delete;
~TokenRewriter();
- typedef std::list<Token>::const_iterator token_iterator;
+ using token_iterator = std::list<Token>::const_iterator;
+
token_iterator token_begin() const { return TokenList.begin(); }
token_iterator token_end() const { return TokenList.end(); }
-
token_iterator AddTokenBefore(token_iterator I, const char *Val);
+
token_iterator AddTokenAfter(token_iterator I, const char *Val) {
assert(I != token_end() && "Cannot insert after token_end()!");
return AddTokenBefore(++I, Val);
@@ -72,8 +76,6 @@ namespace clang {
TokenRefTy AddToken(const Token &T, TokenRefTy Where);
};
+} // namespace clang
-
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_TOKENREWRITER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h
index 3b1b31e0cdee..7456840bc5c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h
@@ -1,4 +1,4 @@
-//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===//
+//===- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,105 +12,108 @@
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
#define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
+class LangOptions;
class SourceManager;
-class FileEntry;
class FixItOptions {
public:
- FixItOptions() : InPlace(false), FixWhatYouCan(false),
- FixOnlyWarnings(false), Silent(false) { }
-
+ FixItOptions() = default;
virtual ~FixItOptions();
- /// \brief This file is about to be rewritten. Return the name of the file
+ /// This file is about to be rewritten. Return the name of the file
/// that is okay to write to.
///
/// \param fd out parameter for file descriptor. After the call it may be set
/// to an open file descriptor for the returned filename, or it will be -1
/// otherwise.
- ///
virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0;
/// True if files should be updated in place. RewriteFilename is only called
/// if this is false.
- bool InPlace;
+ bool InPlace = false;
- /// \brief Whether to abort fixing a file when not all errors could be fixed.
- bool FixWhatYouCan;
+ /// Whether to abort fixing a file when not all errors could be fixed.
+ bool FixWhatYouCan = false;
- /// \brief Whether to only fix warnings and not errors.
- bool FixOnlyWarnings;
+ /// Whether to only fix warnings and not errors.
+ bool FixOnlyWarnings = false;
- /// \brief If true, only pass the diagnostic to the actual diagnostic consumer
+ /// If true, only pass the diagnostic to the actual diagnostic consumer
/// if it is an error or a fixit was applied as part of the diagnostic.
/// It basically silences warnings without accompanying fixits.
- bool Silent;
+ bool Silent = false;
};
class FixItRewriter : public DiagnosticConsumer {
- /// \brief The diagnostics machinery.
+ /// The diagnostics machinery.
DiagnosticsEngine &Diags;
edit::EditedSource Editor;
- /// \brief The rewriter used to perform the various code
+ /// The rewriter used to perform the various code
/// modifications.
Rewriter Rewrite;
- /// \brief The diagnostic client that performs the actual formatting
+ /// The diagnostic client that performs the actual formatting
/// of error messages.
DiagnosticConsumer *Client;
std::unique_ptr<DiagnosticConsumer> Owner;
- /// \brief Turn an input path into an output path. NULL implies overwriting
+ /// Turn an input path into an output path. NULL implies overwriting
/// the original.
FixItOptions *FixItOpts;
- /// \brief The number of rewriter failures.
- unsigned NumFailures;
+ /// The number of rewriter failures.
+ unsigned NumFailures = 0;
- /// \brief Whether the previous diagnostic was not passed to the consumer.
- bool PrevDiagSilenced;
+ /// Whether the previous diagnostic was not passed to the consumer.
+ bool PrevDiagSilenced = false;
public:
- typedef Rewriter::buffer_iterator iterator;
-
- /// \brief Initialize a new fix-it rewriter.
+ /// Initialize a new fix-it rewriter.
FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const LangOptions &LangOpts, FixItOptions *FixItOpts);
- /// \brief Destroy the fix-it rewriter.
+ /// Destroy the fix-it rewriter.
~FixItRewriter() override;
- /// \brief Check whether there are modifications for a given file.
+ /// Check whether there are modifications for a given file.
bool IsModified(FileID ID) const {
return Rewrite.getRewriteBufferFor(ID) != nullptr;
}
+ using iterator = Rewriter::buffer_iterator;
+
// Iteration over files with changes.
iterator buffer_begin() { return Rewrite.buffer_begin(); }
iterator buffer_end() { return Rewrite.buffer_end(); }
- /// \brief Write a single modified source file.
+ /// Write a single modified source file.
///
/// \returns true if there was an error, false otherwise.
bool WriteFixedFile(FileID ID, raw_ostream &OS);
- /// \brief Write the modified source files.
+ /// Write the modified source files.
///
/// \returns true if there was an error, false otherwise.
bool WriteFixedFiles(
- std::vector<std::pair<std::string, std::string> > *RewrittenFiles=nullptr);
+ std::vector<std::pair<std::string, std::string>> *RewrittenFiles = nullptr);
/// IncludeInDiagnosticCounts - This method (whose default implementation
/// returns true) indicates whether the diagnostics handled by this
@@ -123,10 +126,10 @@ public:
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override;
- /// \brief Emit a diagnostic via the adapted diagnostic client.
+ /// Emit a diagnostic via the adapted diagnostic client.
void Diag(SourceLocation Loc, unsigned DiagID);
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h
index 5f83ac16fedf..40d2f4c22afe 100644
--- a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h
@@ -46,7 +46,7 @@ public:
~FixItAction() override;
};
-/// \brief Emits changes to temporary files and uses them for the original
+/// Emits changes to temporary files and uses them for the original
/// frontend action.
class FixItRecompile : public WrapperFrontendAction {
public:
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
index 64dd2d36bef8..6e8d83974e5b 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -54,34 +54,34 @@ private:
/// \name Statistics
/// @{
- /// \brief Number of function CFGs built and analyzed.
+ /// Number of function CFGs built and analyzed.
unsigned NumFunctionsAnalyzed;
- /// \brief Number of functions for which the CFG could not be successfully
+ /// Number of functions for which the CFG could not be successfully
/// built.
unsigned NumFunctionsWithBadCFGs;
- /// \brief Total number of blocks across all CFGs.
+ /// Total number of blocks across all CFGs.
unsigned NumCFGBlocks;
- /// \brief Largest number of CFG blocks for a single function analyzed.
+ /// Largest number of CFG blocks for a single function analyzed.
unsigned MaxCFGBlocksPerFunction;
- /// \brief Total number of CFGs with variables analyzed for uninitialized
+ /// Total number of CFGs with variables analyzed for uninitialized
/// uses.
unsigned NumUninitAnalysisFunctions;
- /// \brief Total number of variables analyzed for uninitialized uses.
+ /// Total number of variables analyzed for uninitialized uses.
unsigned NumUninitAnalysisVariables;
- /// \brief Max number of variables analyzed for uninitialized uses in a single
+ /// Max number of variables analyzed for uninitialized uses in a single
/// function.
unsigned MaxUninitAnalysisVariablesPerFunction;
- /// \brief Total number of block visits during uninitialized use analysis.
+ /// Total number of block visits during uninitialized use analysis.
unsigned NumUninitAnalysisBlockVisits;
- /// \brief Max number of block visits during uninitialized use analysis of
+ /// Max number of block visits during uninitialized use analysis of
/// a single function.
unsigned MaxUninitAnalysisBlockVisitsPerFunction;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
index 5d280b5608e7..ede3ddf91993 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -1,4 +1,4 @@
-//===---- CodeCompleteConsumer.h - Code Completion Interface ----*- C++ -*-===//
+//===- CodeCompleteConsumer.h - Code Completion Interface -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,107 +10,141 @@
// This file defines the CodeCompleteConsumer class.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#include "clang-c/Index.h"
-#include "clang/AST/CanonicalType.h"
-#include "clang/AST/DeclBase.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <memory>
#include <string>
#include <utility>
namespace clang {
+class ASTContext;
class Decl;
+class DeclContext;
+class FunctionDecl;
+class FunctionTemplateDecl;
+class IdentifierInfo;
+class LangOptions;
+class NamedDecl;
+class NestedNameSpecifier;
+class Preprocessor;
+class RawComment;
+class Sema;
+class UsingShadowDecl;
-/// \brief Default priority values for code-completion results based
+/// Default priority values for code-completion results based
/// on their kind.
enum {
- /// \brief Priority for the next initialization in a constructor initializer
+ /// Priority for the next initialization in a constructor initializer
/// list.
CCP_NextInitializer = 7,
- /// \brief Priority for an enumeration constant inside a switch whose
+
+ /// Priority for an enumeration constant inside a switch whose
/// condition is of the enumeration type.
CCP_EnumInCase = 7,
- /// \brief Priority for a send-to-super completion.
+
+ /// Priority for a send-to-super completion.
CCP_SuperCompletion = 20,
- /// \brief Priority for a declaration that is in the local scope.
+
+ /// Priority for a declaration that is in the local scope.
CCP_LocalDeclaration = 34,
- /// \brief Priority for a member declaration found from the current
+
+ /// Priority for a member declaration found from the current
/// method or member function.
CCP_MemberDeclaration = 35,
- /// \brief Priority for a language keyword (that isn't any of the other
+
+ /// Priority for a language keyword (that isn't any of the other
/// categories).
CCP_Keyword = 40,
- /// \brief Priority for a code pattern.
+
+ /// Priority for a code pattern.
CCP_CodePattern = 40,
- /// \brief Priority for a non-type declaration.
+
+ /// Priority for a non-type declaration.
CCP_Declaration = 50,
- /// \brief Priority for a type.
+
+ /// Priority for a type.
CCP_Type = CCP_Declaration,
- /// \brief Priority for a constant value (e.g., enumerator).
+
+ /// Priority for a constant value (e.g., enumerator).
CCP_Constant = 65,
- /// \brief Priority for a preprocessor macro.
+
+ /// Priority for a preprocessor macro.
CCP_Macro = 70,
- /// \brief Priority for a nested-name-specifier.
+
+ /// Priority for a nested-name-specifier.
CCP_NestedNameSpecifier = 75,
- /// \brief Priority for a result that isn't likely to be what the user wants,
+
+ /// Priority for a result that isn't likely to be what the user wants,
/// but is included for completeness.
CCP_Unlikely = 80,
- /// \brief Priority for the Objective-C "_cmd" implicit parameter.
+ /// Priority for the Objective-C "_cmd" implicit parameter.
CCP_ObjC_cmd = CCP_Unlikely
};
-/// \brief Priority value deltas that are added to code-completion results
+/// Priority value deltas that are added to code-completion results
/// based on the context of the result.
enum {
- /// \brief The result is in a base class.
+ /// The result is in a base class.
CCD_InBaseClass = 2,
- /// \brief The result is a C++ non-static member function whose qualifiers
+
+ /// The result is a C++ non-static member function whose qualifiers
/// exactly match the object type on which the member function can be called.
CCD_ObjectQualifierMatch = -1,
- /// \brief The selector of the given message exactly matches the selector
+
+ /// The selector of the given message exactly matches the selector
/// of the current method, which might imply that some kind of delegation
/// is occurring.
CCD_SelectorMatch = -3,
- /// \brief Adjustment to the "bool" type in Objective-C, where the typedef
+ /// Adjustment to the "bool" type in Objective-C, where the typedef
/// "BOOL" is preferred.
CCD_bool_in_ObjC = 1,
- /// \brief Adjustment for KVC code pattern priorities when it doesn't look
+ /// Adjustment for KVC code pattern priorities when it doesn't look
/// like the
CCD_ProbablyNotObjCCollection = 15,
- /// \brief An Objective-C method being used as a property.
+ /// An Objective-C method being used as a property.
CCD_MethodAsProperty = 2,
- /// \brief An Objective-C block property completed as a setter with a
+ /// An Objective-C block property completed as a setter with a
/// block placeholder.
CCD_BlockPropertySetter = 3
};
-/// \brief Priority value factors by which we will divide or multiply the
+/// Priority value factors by which we will divide or multiply the
/// priority of a code-completion result.
enum {
- /// \brief Divide by this factor when a code-completion result's type exactly
+ /// Divide by this factor when a code-completion result's type exactly
/// matches the type we expect.
CCF_ExactTypeMatch = 4,
- /// \brief Divide by this factor when a code-completion result's type is
+
+ /// Divide by this factor when a code-completion result's type is
/// similar to the type we expect (e.g., both arithmetic types, both
/// Objective-C object pointer types).
CCF_SimilarTypeMatch = 2
};
-/// \brief A simplified classification of types used when determining
+/// A simplified classification of types used when determining
/// "similar" types for code completion.
enum SimplifiedTypeClass {
STC_Arithmetic,
@@ -124,14 +158,14 @@ enum SimplifiedTypeClass {
STC_Void
};
-/// \brief Determine the simplified type class of the given canonical type.
+/// Determine the simplified type class of the given canonical type.
SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
-/// \brief Determine the type that this declaration will have if it is used
+/// Determine the type that this declaration will have if it is used
/// as a type or in an expression.
QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND);
-/// \brief Determine the priority to be given to a macro code completion result
+/// Determine the priority to be given to a macro code completion result
/// with the given name.
///
/// \param MacroName The name of the macro.
@@ -144,190 +178,230 @@ unsigned getMacroUsagePriority(StringRef MacroName,
const LangOptions &LangOpts,
bool PreferredTypeIsPointer = false);
-/// \brief Determine the libclang cursor kind associated with the given
+/// Determine the libclang cursor kind associated with the given
/// declaration.
CXCursorKind getCursorKindForDecl(const Decl *D);
-class FunctionDecl;
-class FunctionType;
-class FunctionTemplateDecl;
-class IdentifierInfo;
-class NamedDecl;
-class NestedNameSpecifier;
-class Sema;
-
-/// \brief The context in which code completion occurred, so that the
+/// The context in which code completion occurred, so that the
/// code-completion consumer can process the results accordingly.
class CodeCompletionContext {
public:
enum Kind {
- /// \brief An unspecified code-completion context.
+ /// An unspecified code-completion context.
CCC_Other,
- /// \brief An unspecified code-completion context where we should also add
+
+ /// An unspecified code-completion context where we should also add
/// macro completions.
CCC_OtherWithMacros,
- /// \brief Code completion occurred within a "top-level" completion context,
+
+ /// Code completion occurred within a "top-level" completion context,
/// e.g., at namespace or global scope.
CCC_TopLevel,
- /// \brief Code completion occurred within an Objective-C interface,
+
+ /// Code completion occurred within an Objective-C interface,
/// protocol, or category interface.
CCC_ObjCInterface,
- /// \brief Code completion occurred within an Objective-C implementation
+
+ /// Code completion occurred within an Objective-C implementation
/// or category implementation.
CCC_ObjCImplementation,
- /// \brief Code completion occurred within the instance variable list of
+
+ /// Code completion occurred within the instance variable list of
/// an Objective-C interface, implementation, or category implementation.
CCC_ObjCIvarList,
- /// \brief Code completion occurred within a class, struct, or union.
+
+ /// Code completion occurred within a class, struct, or union.
CCC_ClassStructUnion,
- /// \brief Code completion occurred where a statement (or declaration) is
+
+ /// Code completion occurred where a statement (or declaration) is
/// expected in a function, method, or block.
CCC_Statement,
- /// \brief Code completion occurred where an expression is expected.
+
+ /// Code completion occurred where an expression is expected.
CCC_Expression,
- /// \brief Code completion occurred where an Objective-C message receiver
+
+ /// Code completion occurred where an Objective-C message receiver
/// is expected.
CCC_ObjCMessageReceiver,
- /// \brief Code completion occurred on the right-hand side of a member
+
+ /// Code completion occurred on the right-hand side of a member
/// access expression using the dot operator.
///
/// The results of this completion are the members of the type being
/// accessed. The type itself is available via
/// \c CodeCompletionContext::getType().
CCC_DotMemberAccess,
- /// \brief Code completion occurred on the right-hand side of a member
+
+ /// Code completion occurred on the right-hand side of a member
/// access expression using the arrow operator.
///
/// The results of this completion are the members of the type being
/// accessed. The type itself is available via
/// \c CodeCompletionContext::getType().
CCC_ArrowMemberAccess,
- /// \brief Code completion occurred on the right-hand side of an Objective-C
+
+ /// Code completion occurred on the right-hand side of an Objective-C
/// property access expression.
///
/// The results of this completion are the members of the type being
/// accessed. The type itself is available via
/// \c CodeCompletionContext::getType().
CCC_ObjCPropertyAccess,
- /// \brief Code completion occurred after the "enum" keyword, to indicate
+
+ /// Code completion occurred after the "enum" keyword, to indicate
/// an enumeration name.
CCC_EnumTag,
- /// \brief Code completion occurred after the "union" keyword, to indicate
+
+ /// Code completion occurred after the "union" keyword, to indicate
/// a union name.
CCC_UnionTag,
- /// \brief Code completion occurred after the "struct" or "class" keyword,
+
+ /// Code completion occurred after the "struct" or "class" keyword,
/// to indicate a struct or class name.
CCC_ClassOrStructTag,
- /// \brief Code completion occurred where a protocol name is expected.
+
+ /// Code completion occurred where a protocol name is expected.
CCC_ObjCProtocolName,
- /// \brief Code completion occurred where a namespace or namespace alias
+
+ /// Code completion occurred where a namespace or namespace alias
/// is expected.
CCC_Namespace,
- /// \brief Code completion occurred where a type name is expected.
+
+ /// Code completion occurred where a type name is expected.
CCC_Type,
- /// \brief Code completion occurred where a new name is expected.
+
+ /// Code completion occurred where a new name is expected.
CCC_Name,
- /// \brief Code completion occurred where a new name is expected and a
+
+ /// Code completion occurred where a new name is expected and a
/// qualified name is permissible.
CCC_PotentiallyQualifiedName,
- /// \brief Code completion occurred where an macro is being defined.
+
+ /// Code completion occurred where an macro is being defined.
CCC_MacroName,
- /// \brief Code completion occurred where a macro name is expected
+
+ /// Code completion occurred where a macro name is expected
/// (without any arguments, in the case of a function-like macro).
CCC_MacroNameUse,
- /// \brief Code completion occurred within a preprocessor expression.
+
+ /// Code completion occurred within a preprocessor expression.
CCC_PreprocessorExpression,
- /// \brief Code completion occurred where a preprocessor directive is
+
+ /// Code completion occurred where a preprocessor directive is
/// expected.
CCC_PreprocessorDirective,
- /// \brief Code completion occurred in a context where natural language is
+
+ /// Code completion occurred in a context where natural language is
/// expected, e.g., a comment or string literal.
///
/// This context usually implies that no completions should be added,
/// unless they come from an appropriate natural-language dictionary.
CCC_NaturalLanguage,
- /// \brief Code completion for a selector, as in an \@selector expression.
+
+ /// Code completion for a selector, as in an \@selector expression.
CCC_SelectorName,
- /// \brief Code completion within a type-qualifier list.
+
+ /// Code completion within a type-qualifier list.
CCC_TypeQualifiers,
- /// \brief Code completion in a parenthesized expression, which means that
+
+ /// Code completion in a parenthesized expression, which means that
/// we may also have types here in C and Objective-C (as well as in C++).
CCC_ParenthesizedExpression,
- /// \brief Code completion where an Objective-C instance message is
+
+ /// Code completion where an Objective-C instance message is
/// expected.
CCC_ObjCInstanceMessage,
- /// \brief Code completion where an Objective-C class message is expected.
+
+ /// Code completion where an Objective-C class message is expected.
CCC_ObjCClassMessage,
- /// \brief Code completion where the name of an Objective-C class is
+
+ /// Code completion where the name of an Objective-C class is
/// expected.
CCC_ObjCInterfaceName,
- /// \brief Code completion where an Objective-C category name is expected.
+
+ /// Code completion where an Objective-C category name is expected.
CCC_ObjCCategoryName,
- /// \brief An unknown context, in which we are recovering from a parsing
+
+ /// An unknown context, in which we are recovering from a parsing
/// error and don't know which completions we should give.
CCC_Recovery
};
+ using VisitedContextSet = llvm::SmallPtrSet<DeclContext *, 8>;
+
private:
- enum Kind Kind;
+ Kind CCKind;
- /// \brief The type that would prefer to see at this point (e.g., the type
+ /// The type that would prefer to see at this point (e.g., the type
/// of an initializer or function parameter).
QualType PreferredType;
- /// \brief The type of the base object in a member access expression.
+ /// The type of the base object in a member access expression.
QualType BaseType;
- /// \brief The identifiers for Objective-C selector parts.
+ /// The identifiers for Objective-C selector parts.
ArrayRef<IdentifierInfo *> SelIdents;
- /// \brief The scope specifier that comes before the completion token e.g.
+ /// The scope specifier that comes before the completion token e.g.
/// "a::b::"
llvm::Optional<CXXScopeSpec> ScopeSpecifier;
+ /// A set of declaration contexts visited by Sema when doing lookup for
+ /// code completion.
+ VisitedContextSet VisitedContexts;
+
public:
- /// \brief Construct a new code-completion context of the given kind.
- CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { }
+ /// Construct a new code-completion context of the given kind.
+ CodeCompletionContext(Kind CCKind) : CCKind(CCKind), SelIdents(None) {}
- /// \brief Construct a new code-completion context of the given kind.
- CodeCompletionContext(enum Kind Kind, QualType T,
+ /// Construct a new code-completion context of the given kind.
+ CodeCompletionContext(Kind CCKind, QualType T,
ArrayRef<IdentifierInfo *> SelIdents = None)
- : Kind(Kind),
- SelIdents(SelIdents) {
- if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess ||
- Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage ||
- Kind == CCC_ObjCInstanceMessage)
+ : CCKind(CCKind), SelIdents(SelIdents) {
+ if (CCKind == CCC_DotMemberAccess || CCKind == CCC_ArrowMemberAccess ||
+ CCKind == CCC_ObjCPropertyAccess || CCKind == CCC_ObjCClassMessage ||
+ CCKind == CCC_ObjCInstanceMessage)
BaseType = T;
else
PreferredType = T;
}
- /// \brief Retrieve the kind of code-completion context.
- enum Kind getKind() const { return Kind; }
+ /// Retrieve the kind of code-completion context.
+ Kind getKind() const { return CCKind; }
- /// \brief Retrieve the type that this expression would prefer to have, e.g.,
+ /// Retrieve the type that this expression would prefer to have, e.g.,
/// if the expression is a variable initializer or a function argument, the
/// type of the corresponding variable or function parameter.
QualType getPreferredType() const { return PreferredType; }
- /// \brief Retrieve the type of the base object in a member-access
+ /// Retrieve the type of the base object in a member-access
/// expression.
QualType getBaseType() const { return BaseType; }
- /// \brief Retrieve the Objective-C selector identifiers.
+ /// Retrieve the Objective-C selector identifiers.
ArrayRef<IdentifierInfo *> getSelIdents() const { return SelIdents; }
- /// \brief Determines whether we want C++ constructors as results within this
+ /// 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.
+ /// 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);
}
+ /// Adds a visited context.
+ void addVisitedContext(DeclContext *Ctx) {
+ VisitedContexts.insert(Ctx);
+ }
+
+ /// Retrieves all visited contexts.
+ const VisitedContextSet &getVisitedContexts() const {
+ return VisitedContexts;
+ }
+
llvm::Optional<const CXXScopeSpec *> getCXXScopeSpecifier() {
if (ScopeSpecifier)
return ScopeSpecifier.getPointer();
@@ -335,7 +409,10 @@ public:
}
};
-/// \brief A "string" used to describe how code completion can
+/// Get string representation of \p Kind, useful for for debugging.
+llvm::StringRef getCompletionKindString(CodeCompletionContext::Kind Kind);
+
+/// A "string" used to describe how code completion can
/// be performed for an entity.
///
/// A code completion string typically shows how a particular entity can be
@@ -344,128 +421,147 @@ public:
/// arguments, etc.
class CodeCompletionString {
public:
- /// \brief The different kinds of "chunks" that can occur within a code
+ /// The different kinds of "chunks" that can occur within a code
/// completion string.
enum ChunkKind {
- /// \brief The piece of text that the user is expected to type to
+ /// The piece of text that the user is expected to type to
/// match the code-completion string, typically a keyword or the name of a
/// declarator or macro.
CK_TypedText,
- /// \brief A piece of text that should be placed in the buffer, e.g.,
+
+ /// A piece of text that should be placed in the buffer, e.g.,
/// parentheses or a comma in a function call.
CK_Text,
- /// \brief A code completion string that is entirely optional. For example,
+
+ /// A code completion string that is entirely optional. For example,
/// an optional code completion string that describes the default arguments
/// in a function call.
CK_Optional,
- /// \brief A string that acts as a placeholder for, e.g., a function
+
+ /// A string that acts as a placeholder for, e.g., a function
/// call argument.
CK_Placeholder,
- /// \brief A piece of text that describes something about the result but
+
+ /// A piece of text that describes something about the result but
/// should not be inserted into the buffer.
CK_Informative,
- /// \brief A piece of text that describes the type of an entity or, for
+ /// A piece of text that describes the type of an entity or, for
/// functions and methods, the return type.
CK_ResultType,
- /// \brief A piece of text that describes the parameter that corresponds
+
+ /// A piece of text that describes the parameter that corresponds
/// to the code-completion location within a function call, message send,
/// macro invocation, etc.
CK_CurrentParameter,
- /// \brief A left parenthesis ('(').
+
+ /// A left parenthesis ('(').
CK_LeftParen,
- /// \brief A right parenthesis (')').
+
+ /// A right parenthesis (')').
CK_RightParen,
- /// \brief A left bracket ('[').
+
+ /// A left bracket ('[').
CK_LeftBracket,
- /// \brief A right bracket (']').
+
+ /// A right bracket (']').
CK_RightBracket,
- /// \brief A left brace ('{').
+
+ /// A left brace ('{').
CK_LeftBrace,
- /// \brief A right brace ('}').
+
+ /// A right brace ('}').
CK_RightBrace,
- /// \brief A left angle bracket ('<').
+
+ /// A left angle bracket ('<').
CK_LeftAngle,
- /// \brief A right angle bracket ('>').
+
+ /// A right angle bracket ('>').
CK_RightAngle,
- /// \brief A comma separator (',').
+
+ /// A comma separator (',').
CK_Comma,
- /// \brief A colon (':').
+
+ /// A colon (':').
CK_Colon,
- /// \brief A semicolon (';').
+
+ /// A semicolon (';').
CK_SemiColon,
- /// \brief An '=' sign.
+
+ /// An '=' sign.
CK_Equal,
- /// \brief Horizontal whitespace (' ').
+
+ /// Horizontal whitespace (' ').
CK_HorizontalSpace,
- /// \brief Vertical whitespace ('\\n' or '\\r\\n', depending on the
+
+ /// Vertical whitespace ('\\n' or '\\r\\n', depending on the
/// platform).
CK_VerticalSpace
};
- /// \brief One piece of the code completion string.
+ /// One piece of the code completion string.
struct Chunk {
- /// \brief The kind of data stored in this piece of the code completion
+ /// The kind of data stored in this piece of the code completion
/// string.
- ChunkKind Kind;
+ ChunkKind Kind = CK_Text;
union {
- /// \brief The text string associated with a CK_Text, CK_Placeholder,
+ /// The text string associated with a CK_Text, CK_Placeholder,
/// CK_Informative, or CK_Comma chunk.
/// The string is owned by the chunk and will be deallocated
/// (with delete[]) when the chunk is destroyed.
const char *Text;
- /// \brief The code completion string associated with a CK_Optional chunk.
+ /// The code completion string associated with a CK_Optional chunk.
/// The optional code completion string is owned by the chunk, and will
/// be deallocated (with delete) when the chunk is destroyed.
CodeCompletionString *Optional;
};
- Chunk() : Kind(CK_Text), Text(nullptr) { }
+ Chunk() : Text(nullptr) {}
explicit Chunk(ChunkKind Kind, const char *Text = "");
- /// \brief Create a new text chunk.
+ /// Create a new text chunk.
static Chunk CreateText(const char *Text);
- /// \brief Create a new optional chunk.
+ /// Create a new optional chunk.
static Chunk CreateOptional(CodeCompletionString *Optional);
- /// \brief Create a new placeholder chunk.
+ /// Create a new placeholder chunk.
static Chunk CreatePlaceholder(const char *Placeholder);
- /// \brief Create a new informative chunk.
+ /// Create a new informative chunk.
static Chunk CreateInformative(const char *Informative);
- /// \brief Create a new result type chunk.
+ /// Create a new result type chunk.
static Chunk CreateResultType(const char *ResultType);
- /// \brief Create a new current-parameter chunk.
+ /// Create a new current-parameter chunk.
static Chunk CreateCurrentParameter(const char *CurrentParameter);
};
private:
- /// \brief The number of chunks stored in this string.
+ friend class CodeCompletionBuilder;
+ friend class CodeCompletionResult;
+
+ /// The number of chunks stored in this string.
unsigned NumChunks : 16;
- /// \brief The number of annotations for this code-completion result.
+ /// The number of annotations for this code-completion result.
unsigned NumAnnotations : 16;
- /// \brief The priority of this code-completion string.
+ /// The priority of this code-completion string.
unsigned Priority : 16;
- /// \brief The availability of this code-completion result.
+ /// The availability of this code-completion result.
unsigned Availability : 2;
-
- /// \brief The name of the parent context.
+
+ /// The name of the parent context.
StringRef ParentName;
- /// \brief A brief documentation comment attached to the declaration of
+ /// A brief documentation comment attached to the declaration of
/// entity being completed by this result.
const char *BriefComment;
-
- CodeCompletionString(const CodeCompletionString &) = delete;
- void operator=(const CodeCompletionString &) = delete;
CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
unsigned Priority, CXAvailabilityKind Availability,
@@ -474,11 +570,12 @@ private:
const char *BriefComment);
~CodeCompletionString() = default;
- friend class CodeCompletionBuilder;
- friend class CodeCompletionResult;
-
public:
- typedef const Chunk *iterator;
+ CodeCompletionString(const CodeCompletionString &) = delete;
+ CodeCompletionString &operator=(const CodeCompletionString &) = delete;
+
+ using iterator = const Chunk *;
+
iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); }
iterator end() const { return begin() + NumChunks; }
bool empty() const { return NumChunks == 0; }
@@ -489,22 +586,22 @@ public:
return begin()[I];
}
- /// \brief Returns the text in the TypedText chunk.
+ /// Returns the text in the TypedText chunk.
const char *getTypedText() const;
- /// \brief Retrieve the priority of this code completion result.
+ /// Retrieve the priority of this code completion result.
unsigned getPriority() const { return Priority; }
- /// \brief Retrieve the availability of this code completion result.
+ /// Retrieve the availability of this code completion result.
unsigned getAvailability() const { return Availability; }
- /// \brief Retrieve the number of annotations for this code completion result.
+ /// Retrieve the number of annotations for this code completion result.
unsigned getAnnotationCount() const;
- /// \brief Retrieve the annotation string specified by \c AnnotationNr.
+ /// Retrieve the annotation string specified by \c AnnotationNr.
const char *getAnnotation(unsigned AnnotationNr) const;
-
- /// \brief Retrieve the name of the parent context.
+
+ /// Retrieve the name of the parent context.
StringRef getParentContextName() const {
return ParentName;
}
@@ -512,20 +609,20 @@ public:
const char *getBriefComment() const {
return BriefComment;
}
-
- /// \brief Retrieve a string representation of the code completion string,
+
+ /// Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
std::string getAsString() const;
};
-/// \brief An allocator used specifically for the purpose of code completion.
+/// An allocator used specifically for the purpose of code completion.
class CodeCompletionAllocator : public llvm::BumpPtrAllocator {
public:
- /// \brief Copy the given string into this allocator.
+ /// Copy the given string into this allocator.
const char *CopyString(const Twine &String);
};
-/// \brief Allocator for a cached set of global code completions.
+/// Allocator for a cached set of global code completions.
class GlobalCodeCompletionAllocator : public CodeCompletionAllocator {};
class CodeCompletionTUInfo {
@@ -540,6 +637,7 @@ public:
std::shared_ptr<GlobalCodeCompletionAllocator> getAllocatorRef() const {
return AllocatorRef;
}
+
CodeCompletionAllocator &getAllocator() const {
assert(AllocatorRef);
return *AllocatorRef;
@@ -548,30 +646,32 @@ public:
StringRef getParentName(const DeclContext *DC);
};
-} // end namespace clang
+} // namespace clang
namespace llvm {
- template <> struct isPodLike<clang::CodeCompletionString::Chunk> {
- static const bool value = true;
- };
-}
+
+template <> struct isPodLike<clang::CodeCompletionString::Chunk> {
+ static const bool value = true;
+};
+
+} // namespace llvm
namespace clang {
-/// \brief A builder class used to construct new code-completion strings.
+/// A builder class used to construct new code-completion strings.
class CodeCompletionBuilder {
public:
- typedef CodeCompletionString::Chunk Chunk;
+ using Chunk = CodeCompletionString::Chunk;
private:
CodeCompletionAllocator &Allocator;
CodeCompletionTUInfo &CCTUInfo;
- unsigned Priority;
- CXAvailabilityKind Availability;
+ unsigned Priority = 0;
+ CXAvailabilityKind Availability = CXAvailability_Available;
StringRef ParentName;
- const char *BriefComment;
-
- /// \brief The chunks stored in this string.
+ const char *BriefComment = nullptr;
+
+ /// The chunks stored in this string.
SmallVector<Chunk, 4> Chunks;
SmallVector<const char *, 2> Annotations;
@@ -579,203 +679,237 @@ private:
public:
CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo)
- : Allocator(Allocator), CCTUInfo(CCTUInfo),
- Priority(0), Availability(CXAvailability_Available),
- BriefComment(nullptr) { }
+ : Allocator(Allocator), CCTUInfo(CCTUInfo) {}
CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
unsigned Priority, CXAvailabilityKind Availability)
- : Allocator(Allocator), CCTUInfo(CCTUInfo),
- Priority(Priority), Availability(Availability),
- BriefComment(nullptr) { }
+ : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(Priority),
+ Availability(Availability) {}
- /// \brief Retrieve the allocator into which the code completion
+ /// Retrieve the allocator into which the code completion
/// strings should be allocated.
CodeCompletionAllocator &getAllocator() const { return Allocator; }
CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
- /// \brief Take the resulting completion string.
+ /// Take the resulting completion string.
///
/// This operation can only be performed once.
CodeCompletionString *TakeString();
- /// \brief Add a new typed-text chunk.
+ /// Add a new typed-text chunk.
void AddTypedTextChunk(const char *Text);
- /// \brief Add a new text chunk.
+ /// Add a new text chunk.
void AddTextChunk(const char *Text);
- /// \brief Add a new optional chunk.
+ /// Add a new optional chunk.
void AddOptionalChunk(CodeCompletionString *Optional);
- /// \brief Add a new placeholder chunk.
+ /// Add a new placeholder chunk.
void AddPlaceholderChunk(const char *Placeholder);
- /// \brief Add a new informative chunk.
+ /// Add a new informative chunk.
void AddInformativeChunk(const char *Text);
- /// \brief Add a new result-type chunk.
+ /// Add a new result-type chunk.
void AddResultTypeChunk(const char *ResultType);
- /// \brief Add a new current-parameter chunk.
+ /// Add a new current-parameter chunk.
void AddCurrentParameterChunk(const char *CurrentParameter);
- /// \brief Add a new chunk.
+ /// Add a new chunk.
void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = "");
void AddAnnotation(const char *A) { Annotations.push_back(A); }
- /// \brief Add the parent context information to this code completion.
+ /// Add the parent context information to this code completion.
void addParentContext(const DeclContext *DC);
const char *getBriefComment() const { return BriefComment; }
void addBriefComment(StringRef Comment);
-
+
StringRef getParentName() const { return ParentName; }
};
-/// \brief Captures a result of code completion.
+/// Captures a result of code completion.
class CodeCompletionResult {
public:
- /// \brief Describes the kind of result generated.
+ /// Describes the kind of result generated.
enum ResultKind {
- RK_Declaration = 0, ///< Refers to a declaration
- RK_Keyword, ///< Refers to a keyword or symbol.
- RK_Macro, ///< Refers to a macro
- RK_Pattern ///< Refers to a precomputed pattern.
+ /// Refers to a declaration.
+ RK_Declaration = 0,
+
+ /// Refers to a keyword or symbol.
+ RK_Keyword,
+
+ /// Refers to a macro.
+ RK_Macro,
+
+ /// Refers to a precomputed pattern.
+ RK_Pattern
};
- /// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are
+ /// When Kind == RK_Declaration or RK_Pattern, the declaration we are
/// referring to. In the latter case, the declaration might be NULL.
- const NamedDecl *Declaration;
+ const NamedDecl *Declaration = nullptr;
union {
- /// \brief When Kind == RK_Keyword, the string representing the keyword
+ /// When Kind == RK_Keyword, the string representing the keyword
/// or symbol's spelling.
const char *Keyword;
- /// \brief When Kind == RK_Pattern, the code-completion string that
+ /// When Kind == RK_Pattern, the code-completion string that
/// describes the completion text to insert.
CodeCompletionString *Pattern;
- /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+ /// When Kind == RK_Macro, the identifier that refers to a macro.
const IdentifierInfo *Macro;
};
- /// \brief The priority of this particular code-completion result.
+ /// The priority of this particular code-completion result.
unsigned Priority;
- /// \brief Specifies which parameter (of a function, Objective-C method,
+ /// Specifies which parameter (of a function, Objective-C method,
/// macro, etc.) we should start with when formatting the result.
- unsigned StartParameter;
+ unsigned StartParameter = 0;
- /// \brief The kind of result stored here.
+ /// The kind of result stored here.
ResultKind Kind;
- /// \brief The cursor kind that describes this result.
+ /// The cursor kind that describes this result.
CXCursorKind CursorKind;
- /// \brief The availability of this result.
- CXAvailabilityKind Availability;
+ /// The availability of this result.
+ CXAvailabilityKind Availability = CXAvailability_Available;
- /// \brief Whether this result is hidden by another name.
+ /// Fix-its that *must* be applied before inserting the text for the
+ /// corresponding completion.
+ ///
+ /// By default, CodeCompletionBuilder only returns completions with empty
+ /// fix-its. Extra completions with non-empty fix-its should be explicitly
+ /// requested by setting CompletionOptions::IncludeFixIts.
+ ///
+ /// For the clients to be able to compute position of the cursor after
+ /// applying fix-its, the following conditions are guaranteed to hold for
+ /// RemoveRange of the stored fix-its:
+ /// - Ranges in the fix-its are guaranteed to never contain the completion
+ /// point (or identifier under completion point, if any) inside them, except
+ /// at the start or at the end of the range.
+ /// - If a fix-it range starts or ends with completion point (or starts or
+ /// ends after the identifier under completion point), it will contain at
+ /// least one character. It allows to unambiguously recompute completion
+ /// point after applying the fix-it.
+ ///
+ /// The intuition is that provided fix-its change code around the identifier
+ /// we complete, but are not allowed to touch the identifier itself or the
+ /// completion point. One example of completions with corrections are the ones
+ /// replacing '.' with '->' and vice versa:
+ ///
+ /// std::unique_ptr<std::vector<int>> vec_ptr;
+ /// In 'vec_ptr.^', one of the completions is 'push_back', it requires
+ /// replacing '.' with '->'.
+ /// In 'vec_ptr->^', one of the completions is 'release', it requires
+ /// replacing '->' with '.'.
+ std::vector<FixItHint> FixIts;
+
+ /// Whether this result is hidden by another name.
bool Hidden : 1;
- /// \brief Whether this result was found via lookup into a base class.
+ /// Whether this result was found via lookup into a base class.
bool QualifierIsInformative : 1;
- /// \brief Whether this declaration is the beginning of a
+ /// Whether this declaration is the beginning of a
/// nested-name-specifier and, therefore, should be followed by '::'.
bool StartsNestedNameSpecifier : 1;
- /// \brief Whether all parameters (of a function, Objective-C
+ /// Whether all parameters (of a function, Objective-C
/// method, etc.) should be considered "informative".
bool AllParametersAreInformative : 1;
- /// \brief Whether we're completing a declaration of the given entity,
+ /// Whether we're completing a declaration of the given entity,
/// rather than a use of that entity.
bool DeclaringEntity : 1;
- /// \brief If the result should have a nested-name-specifier, this is it.
+ /// If the result should have a nested-name-specifier, this is it.
/// When \c QualifierIsInformative, the nested-name-specifier is
/// informative rather than required.
- NestedNameSpecifier *Qualifier;
+ NestedNameSpecifier *Qualifier = nullptr;
- /// \brief Build a result that refers to a declaration.
- CodeCompletionResult(const NamedDecl *Declaration,
- unsigned Priority,
+ /// If this Decl was unshadowed by using declaration, this can store a
+ /// pointer to the UsingShadowDecl which was used in the unshadowing process.
+ /// This information can be used to uprank CodeCompletionResults / which have
+ /// corresponding `using decl::qualified::name;` nearby.
+ const UsingShadowDecl *ShadowDecl = nullptr;
+
+ /// Build a result that refers to a declaration.
+ CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority,
NestedNameSpecifier *Qualifier = nullptr,
bool QualifierIsInformative = false,
- bool Accessible = true)
- : Declaration(Declaration), Priority(Priority),
- StartParameter(0), Kind(RK_Declaration),
- Availability(CXAvailability_Available), Hidden(false),
- QualifierIsInformative(QualifierIsInformative),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(Qualifier) {
+ bool Accessible = true,
+ std::vector<FixItHint> FixIts = std::vector<FixItHint>())
+ : Declaration(Declaration), Priority(Priority), Kind(RK_Declaration),
+ FixIts(std::move(FixIts)), Hidden(false),
+ QualifierIsInformative(QualifierIsInformative),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(Qualifier) {
+ // FIXME: Add assert to check FixIts range requirements.
computeCursorKindAndAvailability(Accessible);
}
- /// \brief Build a result that refers to a keyword or symbol.
+ /// Build a result that refers to a keyword or symbol.
CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
- : Declaration(nullptr), Keyword(Keyword), Priority(Priority),
- StartParameter(0), Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented),
- Availability(CXAvailability_Available), Hidden(false),
- QualifierIsInformative(0), StartsNestedNameSpecifier(false),
- AllParametersAreInformative(false), DeclaringEntity(false),
- Qualifier(nullptr) {}
-
- /// \brief Build a result that refers to a macro.
+ : Keyword(Keyword), Priority(Priority), Kind(RK_Keyword),
+ CursorKind(CXCursor_NotImplemented), Hidden(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false) {}
+
+ /// Build a result that refers to a macro.
CodeCompletionResult(const IdentifierInfo *Macro,
unsigned Priority = CCP_Macro)
- : Declaration(nullptr), Macro(Macro), Priority(Priority), StartParameter(0),
- Kind(RK_Macro), CursorKind(CXCursor_MacroDefinition),
- Availability(CXAvailability_Available), Hidden(false),
- QualifierIsInformative(0), StartsNestedNameSpecifier(false),
- AllParametersAreInformative(false), DeclaringEntity(false),
- Qualifier(nullptr) {}
-
- /// \brief Build a result that refers to a pattern.
+ : Macro(Macro), Priority(Priority), Kind(RK_Macro),
+ CursorKind(CXCursor_MacroDefinition), Hidden(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false) {}
+
+ /// Build a result that refers to a pattern.
CodeCompletionResult(CodeCompletionString *Pattern,
unsigned Priority = CCP_CodePattern,
CXCursorKind CursorKind = CXCursor_NotImplemented,
CXAvailabilityKind Availability = CXAvailability_Available,
const NamedDecl *D = nullptr)
- : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
- Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability),
- Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(nullptr)
- {
- }
+ : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
+ CursorKind(CursorKind), Availability(Availability), Hidden(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false) {}
- /// \brief Build a result that refers to a pattern with an associated
+ /// Build a result that refers to a pattern with an associated
/// declaration.
CodeCompletionResult(CodeCompletionString *Pattern, const NamedDecl *D,
unsigned Priority)
- : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
- Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false),
- QualifierIsInformative(false), StartsNestedNameSpecifier(false),
- AllParametersAreInformative(false), DeclaringEntity(false),
- Qualifier(nullptr) {
+ : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
+ Hidden(false), QualifierIsInformative(false),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false) {
computeCursorKindAndAvailability();
- }
-
- /// \brief Retrieve the declaration stored in this result.
+ }
+
+ /// Retrieve the declaration stored in this result. This might be nullptr if
+ /// Kind is RK_Pattern.
const NamedDecl *getDeclaration() const {
- assert(Kind == RK_Declaration && "Not a declaration result");
+ assert(((Kind == RK_Declaration) || (Kind == RK_Pattern)) &&
+ "Not a declaration or pattern result");
return Declaration;
}
- /// \brief Retrieve the keyword stored in this result.
+ /// Retrieve the keyword stored in this result.
const char *getKeyword() const {
assert(Kind == RK_Keyword && "Not a keyword result");
return Keyword;
}
- /// \brief Create a new code-completion string that describes how to insert
+ /// Create a new code-completion string that describes how to insert
/// this result into a program.
///
/// \param S The semantic analysis that created the result.
@@ -793,8 +927,15 @@ public:
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments);
-
- /// \brief Retrieve the name that should be used to order a result.
+ /// Creates a new code-completion string for the macro result. Similar to the
+ /// above overloads, except this only requires preprocessor information.
+ /// The result kind must be `RK_Macro`.
+ CodeCompletionString *
+ CreateCodeCompletionStringForMacro(Preprocessor &PP,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo);
+
+ /// 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.
@@ -821,80 +962,81 @@ inline bool operator>=(const CodeCompletionResult &X,
return !(X < Y);
}
-
raw_ostream &operator<<(raw_ostream &OS,
const CodeCompletionString &CCS);
-/// \brief Abstract interface for a consumer of code-completion
+/// Abstract interface for a consumer of code-completion
/// information.
class CodeCompleteConsumer {
protected:
const CodeCompleteOptions CodeCompleteOpts;
- /// \brief Whether the output format for the code-completion consumer is
+ /// Whether the output format for the code-completion consumer is
/// binary.
bool OutputIsBinary;
public:
class OverloadCandidate {
public:
- /// \brief Describes the type of overload candidate.
+ /// Describes the type of overload candidate.
enum CandidateKind {
- /// \brief The candidate is a function declaration.
+ /// The candidate is a function declaration.
CK_Function,
- /// \brief The candidate is a function template.
+
+ /// The candidate is a function template.
CK_FunctionTemplate,
- /// \brief The "candidate" is actually a variable, expression, or block
+
+ /// The "candidate" is actually a variable, expression, or block
/// for which we only have a function prototype.
CK_FunctionType
};
private:
- /// \brief The kind of overload candidate.
+ /// The kind of overload candidate.
CandidateKind Kind;
union {
- /// \brief The function overload candidate, available when
+ /// The function overload candidate, available when
/// Kind == CK_Function.
FunctionDecl *Function;
- /// \brief The function template overload candidate, available when
+ /// The function template overload candidate, available when
/// Kind == CK_FunctionTemplate.
FunctionTemplateDecl *FunctionTemplate;
- /// \brief The function type that describes the entity being called,
+ /// The function type that describes the entity being called,
/// when Kind == CK_FunctionType.
const FunctionType *Type;
};
public:
OverloadCandidate(FunctionDecl *Function)
- : Kind(CK_Function), Function(Function) { }
+ : Kind(CK_Function), Function(Function) {}
OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
- : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { }
+ : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) {}
OverloadCandidate(const FunctionType *Type)
- : Kind(CK_FunctionType), Type(Type) { }
+ : Kind(CK_FunctionType), Type(Type) {}
- /// \brief Determine the kind of overload candidate.
+ /// Determine the kind of overload candidate.
CandidateKind getKind() const { return Kind; }
- /// \brief Retrieve the function overload candidate or the templated
+ /// Retrieve the function overload candidate or the templated
/// function declaration for a function template.
FunctionDecl *getFunction() const;
- /// \brief Retrieve the function template overload candidate.
+ /// Retrieve the function template overload candidate.
FunctionTemplateDecl *getFunctionTemplate() const {
assert(getKind() == CK_FunctionTemplate && "Not a function template");
return FunctionTemplate;
}
- /// \brief Retrieve the function type of the entity, regardless of how the
+ /// Retrieve the function type of the entity, regardless of how the
/// function is stored.
const FunctionType *getFunctionType() const;
- /// \brief Create a new code-completion string that describes the function
+ /// Create a new code-completion string that describes the function
/// signature of this overload candidate.
CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
Sema &S,
@@ -905,43 +1047,52 @@ public:
CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
bool OutputIsBinary)
- : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary)
- { }
+ : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary) {}
- /// \brief Whether the code-completion consumer wants to see macros.
+ /// Whether the code-completion consumer wants to see macros.
bool includeMacros() const {
return CodeCompleteOpts.IncludeMacros;
}
- /// \brief Whether the code-completion consumer wants to see code patterns.
+ /// Whether the code-completion consumer wants to see code patterns.
bool includeCodePatterns() const {
return CodeCompleteOpts.IncludeCodePatterns;
}
- /// \brief Whether to include global (top-level) declaration results.
+ /// Whether to include global (top-level) declaration results.
bool includeGlobals() const { return CodeCompleteOpts.IncludeGlobals; }
- /// \brief Whether to include declarations in namespace contexts (including
+ /// 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
+ /// Whether to include brief documentation comments within the set of
/// code completions returned.
bool includeBriefComments() const {
return CodeCompleteOpts.IncludeBriefComments;
}
- /// \brief Determine whether the output of this consumer is binary.
+ /// Whether to include completion items with small fix-its, e.g. change
+ /// '.' to '->' on member access, etc.
+ bool includeFixIts() const { return CodeCompleteOpts.IncludeFixIts; }
+
+ /// Hint whether to load data from the external AST in order to provide
+ /// full results. If false, declarations from the preamble may be omitted.
+ bool loadExternal() const {
+ return CodeCompleteOpts.LoadExternal;
+ }
+
+ /// Determine whether the output of this consumer is binary.
bool isOutputBinary() const { return OutputIsBinary; }
- /// \brief Deregisters and destroys this code-completion consumer.
+ /// Deregisters and destroys this code-completion consumer.
virtual ~CodeCompleteConsumer();
/// \name Code-completion filtering
- /// \brief Check if the result should be filtered out.
+ /// Check if the result should be filtered out.
virtual bool isResultFilteredOut(StringRef Filter,
CodeCompletionResult Results) {
return false;
@@ -949,11 +1100,11 @@ public:
/// \name Code-completion callbacks
//@{
- /// \brief Process the finalized code-completion results.
+ /// Process the finalized code-completion results.
virtual void ProcessCodeCompleteResults(Sema &S,
CodeCompletionContext Context,
CodeCompletionResult *Results,
- unsigned NumResults) { }
+ unsigned NumResults) {}
/// \param S the semantic-analyzer object for which code-completion is being
/// done.
@@ -965,33 +1116,50 @@ public:
/// \param NumCandidates the number of overload candidates
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
- unsigned NumCandidates) { }
+ unsigned NumCandidates) {}
//@}
- /// \brief Retrieve the allocator that will be used to allocate
+ /// Retrieve the allocator that will be used to allocate
/// code completion strings.
virtual CodeCompletionAllocator &getAllocator() = 0;
virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() = 0;
};
-/// \brief A simple code-completion consumer that prints the results it
+/// Get the documentation comment used to produce
+/// CodeCompletionString::BriefComment for RK_Declaration.
+const RawComment *getCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *Decl);
+
+/// Get the documentation comment used to produce
+/// CodeCompletionString::BriefComment for RK_Pattern.
+const RawComment *getPatternCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *Decl);
+
+/// Get the documentation comment used to produce
+/// CodeCompletionString::BriefComment for OverloadCandidate.
+const RawComment *
+getParameterComment(const ASTContext &Ctx,
+ const CodeCompleteConsumer::OverloadCandidate &Result,
+ unsigned ArgIndex);
+
+/// A simple code-completion consumer that prints the results it
/// receives in a simple format.
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
- /// \brief The raw output stream.
+ /// The raw output stream.
raw_ostream &OS;
CodeCompletionTUInfo CCTUInfo;
public:
- /// \brief Create a new printing code-completion consumer that prints its
+ /// Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
PrintingCodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
raw_ostream &OS)
: CodeCompleteConsumer(CodeCompleteOpts, false), OS(OS),
CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
- /// \brief Prints the finalized code-completion results.
+ /// Prints the finalized code-completion results.
void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
CodeCompletionResult *Results,
unsigned NumResults) override;
@@ -1009,6 +1177,6 @@ public:
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
};
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
index 091d8ca60505..1d3bbb4e585d 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
@@ -35,9 +35,18 @@ public:
/// Show brief documentation comments in code completion results.
unsigned IncludeBriefComments : 1;
+ /// Hint whether to load data from the external AST to provide full results.
+ /// If false, namespace-level declarations from the preamble may be omitted.
+ unsigned LoadExternal : 1;
+
+ /// Include results after corrections (small fix-its), e.g. change '.' to '->'
+ /// on member access, etc.
+ unsigned IncludeFixIts : 1;
+
CodeCompleteOptions()
: IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1),
- IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {}
+ IncludeNamespaceLevelDecls(1), IncludeBriefComments(0),
+ LoadExternal(1), IncludeFixIts(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 2e7411337bfc..2e70203c6cc0 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines the classes used to store parsed information about
+/// This file defines the classes used to store parsed information about
/// declaration-specifiers and declarators.
///
/// \verbatim
@@ -29,8 +29,8 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Token.h"
-#include "clang/Sema/AttributeList.h"
#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedAttr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -48,7 +48,7 @@ namespace clang {
class Declarator;
struct TemplateIdAnnotation;
-/// \brief Represents a C++ nested-name-specifier or a global scope specifier.
+/// Represents a C++ nested-name-specifier or a global scope specifier.
///
/// These can be in 3 states:
/// 1) Not present, identified by isEmpty()
@@ -61,7 +61,7 @@ namespace clang {
///
/// The actual scope is described by getScopeRep().
class CXXScopeSpec {
- SourceRange Range;
+ SourceRange Range;
NestedNameSpecifierLocBuilder Builder;
public:
@@ -72,12 +72,12 @@ public:
SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
- /// \brief Retrieve the representation of the nested-name-specifier.
- NestedNameSpecifier *getScopeRep() const {
- return Builder.getRepresentation();
+ /// Retrieve the representation of the nested-name-specifier.
+ NestedNameSpecifier *getScopeRep() const {
+ return Builder.getRepresentation();
}
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'type::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -91,7 +91,7 @@ public:
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
SourceLocation ColonColonLoc);
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'identifier::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -105,7 +105,7 @@ public:
void Extend(ASTContext &Context, IdentifierInfo *Identifier,
SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -119,7 +119,7 @@ public:
void Extend(ASTContext &Context, NamespaceDecl *Namespace,
SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
- /// \brief Extend the current nested-name-specifier by another
+ /// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace-alias::'.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -127,18 +127,18 @@ public:
///
/// \param Alias The namespace alias.
///
- /// \param AliasLoc The location of the namespace alias
+ /// \param AliasLoc The location of the namespace alias
/// name.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
SourceLocation AliasLoc, SourceLocation ColonColonLoc);
- /// \brief Turn this (empty) nested-name-specifier into the global
+ /// Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
-
- /// \brief Turns this (empty) nested-name-specifier into '__super'
+
+ /// Turns this (empty) nested-name-specifier into '__super'
/// nested-name-specifier.
///
/// \param Context The AST context in which this nested-name-specifier
@@ -154,27 +154,27 @@ public:
void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
SourceLocation SuperLoc, SourceLocation ColonColonLoc);
- /// \brief Make a new nested-name-specifier from incomplete source-location
+ /// Make a new nested-name-specifier from incomplete source-location
/// information.
///
/// FIXME: This routine should be used very, very rarely, in cases where we
/// need to synthesize a nested-name-specifier. Most code should instead use
/// \c Adopt() with a proper \c NestedNameSpecifierLoc.
- void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
SourceRange R);
-
- /// \brief Adopt an existing nested-name-specifier (with source-range
+
+ /// Adopt an existing nested-name-specifier (with source-range
/// information).
void Adopt(NestedNameSpecifierLoc Other);
-
- /// \brief Retrieve a nested-name-specifier with location information, copied
+
+ /// Retrieve a nested-name-specifier with location information, copied
/// into the given AST context.
///
/// \param Context The context into which this nested-name-specifier will be
/// copied.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
- /// \brief Retrieve the location of the name in the last qualifier
+ /// Retrieve the location of the name in the last qualifier
/// in this nested name specifier.
///
/// For example, the location of \c bar
@@ -195,15 +195,15 @@ public:
/// A scope specifier is present, and it refers to a real scope.
bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; }
- /// \brief Indicate that this nested-name-specifier is invalid.
- void SetInvalid(SourceRange R) {
+ /// Indicate that this nested-name-specifier is invalid.
+ void SetInvalid(SourceRange R) {
assert(R.isValid() && "Must have a valid source range");
if (Range.getBegin().isInvalid())
Range.setBegin(R.getBegin());
Range.setEnd(R.getEnd());
Builder.Clear();
}
-
+
/// Deprecated. Some call sites intend isNotEmpty() while others intend
/// isValid().
bool isSet() const { return getScopeRep() != nullptr; }
@@ -213,21 +213,21 @@ public:
Builder.Clear();
}
- /// \brief Retrieve the data associated with the source-location information.
+ /// Retrieve the data associated with the source-location information.
char *location_data() const { return Builder.getBuffer().first; }
-
- /// \brief Retrieve the size of the data associated with source-location
+
+ /// Retrieve the size of the data associated with source-location
/// information.
unsigned location_size() const { return Builder.getBuffer().second; }
};
-/// \brief Captures information about "declaration specifiers".
+/// Captures information about "declaration specifiers".
///
/// "Declaration specifiers" encompasses storage-class-specifiers,
/// type-specifiers, type-qualifiers, and function-specifiers.
class DeclSpec {
public:
- /// \brief storage-class-specifier
+ /// storage-class-specifier
/// \note The order of these enumerators is important for diagnostics.
enum SCS {
SCS_unspecified = 0,
@@ -254,7 +254,7 @@ public:
static const TSW TSW_short = clang::TSW_short;
static const TSW TSW_long = clang::TSW_long;
static const TSW TSW_longlong = clang::TSW_longlong;
-
+
enum TSC {
TSC_unspecified,
TSC_imaginary,
@@ -273,6 +273,7 @@ public:
static const TST TST_void = clang::TST_void;
static const TST TST_char = clang::TST_char;
static const TST TST_wchar = clang::TST_wchar;
+ static const TST TST_char8 = clang::TST_char8;
static const TST TST_char16 = clang::TST_char16;
static const TST TST_char32 = clang::TST_char32;
static const TST TST_int = clang::TST_int;
@@ -281,6 +282,8 @@ public:
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_accum = clang::TST_Accum;
+ static const TST TST_fract = clang::TST_Fract;
static const TST TST_float128 = clang::TST_float128;
static const TST TST_bool = clang::TST_bool;
static const TST TST_decimal32 = clang::TST_decimal32;
@@ -326,6 +329,7 @@ public:
PQ_TypeSpecifier = 2,
PQ_TypeQualifier = 4,
PQ_FunctionSpecifier = 8
+ // FIXME: Attributes should be included here.
};
private:
@@ -344,6 +348,7 @@ private:
unsigned TypeAltiVecBool : 1;
unsigned TypeSpecOwned : 1;
unsigned TypeSpecPipe : 1;
+ unsigned TypeSpecSat : 1;
// type-qualifiers
unsigned TypeQualifiers : 5; // Bitwise OR of TQ.
@@ -379,7 +384,7 @@ private:
SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
SourceRange TSWRange;
- SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
+ SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc;
/// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union,
/// typename, then this is the location of the named type (if present);
/// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and
@@ -428,6 +433,7 @@ public:
TypeAltiVecBool(false),
TypeSpecOwned(false),
TypeSpecPipe(false),
+ TypeSpecSat(false),
TypeQualifiers(TQ_unspecified),
FS_inline_specified(false),
FS_forceinline_specified(false),
@@ -481,6 +487,7 @@ public:
bool isTypeSpecOwned() const { return TypeSpecOwned; }
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
bool isTypeSpecPipe() const { return TypeSpecPipe; }
+ bool isTypeSpecSat() const { return TypeSpecSat; }
ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
@@ -507,6 +514,7 @@ public:
SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
SourceLocation getAltiVecLoc() const { return AltiVecLoc; }
+ SourceLocation getTypeSpecSatLoc() const { return TSSatLoc; }
SourceLocation getTypeSpecTypeNameLoc() const {
assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename);
@@ -523,7 +531,7 @@ public:
bool hasTagDefinition() const;
- /// \brief Turn a type-specifier-type into a string like "_Bool" or "union".
+ /// Turn a type-specifier-type into a string like "_Bool" or "union".
static const char *getSpecifierName(DeclSpec::TST T,
const PrintingPolicy &Policy);
static const char *getSpecifierName(DeclSpec::TQ Q);
@@ -544,7 +552,7 @@ public:
SourceLocation getUnalignedSpecLoc() const { return TQ_unalignedLoc; }
SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
- /// \brief Clear out all of the type qualifiers.
+ /// Clear out all of the type qualifiers.
void ClearTypeQualifiers() {
TypeQualifiers = 0;
TQ_constLoc = SourceLocation();
@@ -585,7 +593,7 @@ public:
FS_noreturnLoc = SourceLocation();
}
- /// \brief Return true if any type-specifier has been found.
+ /// Return true if any type-specifier has been found.
bool hasTypeSpecifier() const {
return getTypeSpecType() != DeclSpec::TST_unspecified ||
getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
@@ -593,7 +601,7 @@ public:
getTypeSpecSign() != DeclSpec::TSS_unspecified;
}
- /// \brief Return a bitmask of which flavors of specifiers this
+ /// Return a bitmask of which flavors of specifiers this
/// DeclSpec includes.
unsigned getParsedSpecifiers() const;
@@ -659,6 +667,8 @@ public:
bool SetTypePipe(bool isPipe, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy);
+ bool SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
bool SetTypeSpecError();
void UpdateDeclRep(Decl *Rep) {
assert(isDeclRep((TST) TypeSpecType));
@@ -699,7 +709,7 @@ public:
bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; }
-
+
bool isConstexprSpecified() const { return Constexpr_specified; }
SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
@@ -712,7 +722,7 @@ public:
return Attrs.getPool();
}
- /// \brief Concatenates two attribute lists.
+ /// Concatenates two attribute lists.
///
/// The GCC attribute syntax allows for the following:
///
@@ -729,8 +739,8 @@ public:
/// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
/// \endcode
///
- void addAttributes(AttributeList *AL) {
- Attrs.addAll(AL);
+ void addAttributes(ParsedAttributesView &AL) {
+ Attrs.addAll(AL.begin(), AL.end());
}
bool hasAttributes() const { return !Attrs.empty(); }
@@ -754,13 +764,13 @@ public:
ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; }
void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; }
- /// \brief Checks if this DeclSpec can stand alone, without a Declarator.
+ /// Checks if this DeclSpec can stand alone, without a Declarator.
///
/// Only tag declspecs can stand alone.
bool isMissingDeclaratorOk();
};
-/// \brief Captures information about "declaration specifiers" specific to
+/// Captures information about "declaration specifiers" specific to
/// Objective-C.
class ObjCDeclSpec {
public:
@@ -882,47 +892,47 @@ private:
};
-/// \brief Describes the kind of unqualified-id parsed.
+/// Describes the kind of unqualified-id parsed.
enum class UnqualifiedIdKind {
- /// \brief An identifier.
+ /// An identifier.
IK_Identifier,
- /// \brief An overloaded operator name, e.g., operator+.
+ /// An overloaded operator name, e.g., operator+.
IK_OperatorFunctionId,
- /// \brief A conversion function name, e.g., operator int.
+ /// A conversion function name, e.g., operator int.
IK_ConversionFunctionId,
- /// \brief A user-defined literal name, e.g., operator "" _i.
+ /// A user-defined literal name, e.g., operator "" _i.
IK_LiteralOperatorId,
- /// \brief A constructor name.
+ /// A constructor name.
IK_ConstructorName,
- /// \brief A constructor named via a template-id.
+ /// A constructor named via a template-id.
IK_ConstructorTemplateId,
- /// \brief A destructor name.
+ /// A destructor name.
IK_DestructorName,
- /// \brief A template-id, e.g., f<int>.
+ /// A template-id, e.g., f<int>.
IK_TemplateId,
- /// \brief An implicit 'self' parameter
+ /// An implicit 'self' parameter
IK_ImplicitSelfParam,
- /// \brief A deduction-guide name (a template-name)
+ /// A deduction-guide name (a template-name)
IK_DeductionGuideName
};
-/// \brief Represents a C++ unqualified-id that has been parsed.
+/// Represents a C++ unqualified-id that has been parsed.
class UnqualifiedId {
private:
UnqualifiedId(const UnqualifiedId &Other) = delete;
const UnqualifiedId &operator=(const UnqualifiedId &) = delete;
public:
- /// \brief Describes the kind of unqualified-id parsed.
+ /// Describes the kind of unqualified-id parsed.
UnqualifiedIdKind Kind;
struct OFI {
- /// \brief The kind of overloaded operator.
+ /// The kind of overloaded operator.
OverloadedOperatorKind Operator;
- /// \brief The source locations of the individual tokens that name
- /// the operator, e.g., the "new", "[", and "]" tokens in
- /// operator new [].
+ /// The source locations of the individual tokens that name
+ /// the operator, e.g., the "new", "[", and "]" tokens in
+ /// operator new [].
///
/// Different operators have different numbers of tokens in their name,
/// up to three. Any remaining source locations in this array will be
@@ -930,50 +940,50 @@ public:
unsigned SymbolLocations[3];
};
- /// \brief Anonymous union that holds extra data associated with the
+ /// Anonymous union that holds extra data associated with the
/// parsed unqualified-id.
union {
- /// \brief When Kind == IK_Identifier, the parsed identifier, or when
+ /// When Kind == IK_Identifier, the parsed identifier, or when
/// Kind == IK_UserLiteralId, the identifier suffix.
IdentifierInfo *Identifier;
-
- /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
+
+ /// When Kind == IK_OperatorFunctionId, the overloaded operator
/// that we parsed.
struct OFI OperatorFunctionId;
-
- /// \brief When Kind == IK_ConversionFunctionId, the type that the
+
+ /// When Kind == IK_ConversionFunctionId, the type that the
/// conversion function names.
UnionParsedType ConversionFunctionId;
- /// \brief When Kind == IK_ConstructorName, the class-name of the type
+ /// When Kind == IK_ConstructorName, the class-name of the type
/// whose constructor is being referenced.
UnionParsedType ConstructorName;
-
- /// \brief When Kind == IK_DestructorName, the type referred to by the
+
+ /// When Kind == IK_DestructorName, the type referred to by the
/// class-name.
UnionParsedType DestructorName;
- /// \brief When Kind == IK_DeductionGuideName, the parsed template-name.
+ /// When Kind == IK_DeductionGuideName, the parsed template-name.
UnionParsedTemplateTy TemplateName;
-
- /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId,
+
+ /// When Kind == IK_TemplateId or IK_ConstructorTemplateId,
/// the template-id annotation that contains the template name and
/// template arguments.
TemplateIdAnnotation *TemplateId;
};
-
- /// \brief The location of the first token that describes this unqualified-id,
+
+ /// The location of the first token that describes this unqualified-id,
/// which will be the location of the identifier, "operator" keyword,
/// tilde (for a destructor), or the template name of a template-id.
SourceLocation StartLocation;
-
- /// \brief The location of the last token that describes this unqualified-id.
+
+ /// The location of the last token that describes this unqualified-id.
SourceLocation EndLocation;
UnqualifiedId()
: Kind(UnqualifiedIdKind::IK_Identifier), Identifier(nullptr) {}
- /// \brief Clear out this unqualified-id, setting it to default (invalid)
+ /// Clear out this unqualified-id, setting it to default (invalid)
/// state.
void clear() {
Kind = UnqualifiedIdKind::IK_Identifier;
@@ -981,18 +991,18 @@ public:
StartLocation = SourceLocation();
EndLocation = SourceLocation();
}
-
- /// \brief Determine whether this unqualified-id refers to a valid name.
+
+ /// Determine whether this unqualified-id refers to a valid name.
bool isValid() const { return StartLocation.isValid(); }
- /// \brief Determine whether this unqualified-id refers to an invalid name.
+ /// Determine whether this unqualified-id refers to an invalid name.
bool isInvalid() const { return !isValid(); }
-
- /// \brief Determine what kind of name we have.
+
+ /// Determine what kind of name we have.
UnqualifiedIdKind getKind() const { return Kind; }
- void setKind(UnqualifiedIdKind kind) { Kind = kind; }
-
- /// \brief Specify that this unqualified-id was parsed as an identifier.
+ void setKind(UnqualifiedIdKind kind) { Kind = kind; }
+
+ /// Specify that this unqualified-id was parsed as an identifier.
///
/// \param Id the parsed identifier.
/// \param IdLoc the location of the parsed identifier.
@@ -1001,8 +1011,8 @@ public:
Identifier = const_cast<IdentifierInfo *>(Id);
StartLocation = EndLocation = IdLoc;
}
-
- /// \brief Specify that this unqualified-id was parsed as an
+
+ /// Specify that this unqualified-id was parsed as an
/// operator-function-id.
///
/// \param OperatorLoc the location of the 'operator' keyword.
@@ -1011,11 +1021,11 @@ public:
///
/// \param SymbolLocations the locations of the individual operator symbols
/// in the operator.
- void setOperatorFunctionId(SourceLocation OperatorLoc,
+ void setOperatorFunctionId(SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
SourceLocation SymbolLocations[3]);
-
- /// \brief Specify that this unqualified-id was parsed as a
+
+ /// Specify that this unqualified-id was parsed as a
/// conversion-function-id.
///
/// \param OperatorLoc the location of the 'operator' keyword.
@@ -1023,7 +1033,7 @@ public:
/// \param Ty the type to which this conversion function is converting.
///
/// \param EndLoc the location of the last token that makes up the type name.
- void setConversionFunctionId(SourceLocation OperatorLoc,
+ void setConversionFunctionId(SourceLocation OperatorLoc,
ParsedType Ty,
SourceLocation EndLoc) {
Kind = UnqualifiedIdKind::IK_ConversionFunctionId;
@@ -1032,7 +1042,7 @@ public:
ConversionFunctionId = Ty;
}
- /// \brief Specific that this unqualified-id was parsed as a
+ /// Specific that this unqualified-id was parsed as a
/// literal-operator-id.
///
/// \param Id the parsed identifier.
@@ -1047,15 +1057,15 @@ public:
StartLocation = OpLoc;
EndLocation = IdLoc;
}
-
- /// \brief Specify that this unqualified-id was parsed as a constructor name.
+
+ /// Specify that this unqualified-id was parsed as a constructor name.
///
/// \param ClassType the class type referred to by the constructor name.
///
/// \param ClassNameLoc the location of the class name.
///
/// \param EndLoc the location of the last token that makes up the type name.
- void setConstructorName(ParsedType ClassType,
+ void setConstructorName(ParsedType ClassType,
SourceLocation ClassNameLoc,
SourceLocation EndLoc) {
Kind = UnqualifiedIdKind::IK_ConstructorName;
@@ -1064,7 +1074,7 @@ public:
ConstructorName = ClassType;
}
- /// \brief Specify that this unqualified-id was parsed as a
+ /// Specify that this unqualified-id was parsed as a
/// template-id that names a constructor.
///
/// \param TemplateId the template-id annotation that describes the parsed
@@ -1072,7 +1082,7 @@ public:
/// \p TemplateId and will free it on destruction.
void setConstructorTemplateId(TemplateIdAnnotation *TemplateId);
- /// \brief Specify that this unqualified-id was parsed as a destructor name.
+ /// Specify that this unqualified-id was parsed as a destructor name.
///
/// \param TildeLoc the location of the '~' that introduces the destructor
/// name.
@@ -1086,15 +1096,15 @@ public:
EndLocation = EndLoc;
DestructorName = ClassType;
}
-
- /// \brief Specify that this unqualified-id was parsed as a template-id.
+
+ /// Specify that this unqualified-id was parsed as a template-id.
///
/// \param TemplateId the template-id annotation that describes the parsed
/// template-id. This UnqualifiedId instance will take ownership of the
/// \p TemplateId and will free it on destruction.
void setTemplateId(TemplateIdAnnotation *TemplateId);
- /// \brief Specify that this unqualified-id was parsed as a template-name for
+ /// Specify that this unqualified-id was parsed as a template-name for
/// a deduction-guide.
///
/// \param Template The parsed template-name.
@@ -1105,19 +1115,19 @@ public:
TemplateName = Template;
StartLocation = EndLocation = TemplateLoc;
}
-
- /// \brief Return the source range that covers this unqualified-id.
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(StartLocation, EndLocation);
+
+ /// Return the source range that covers this unqualified-id.
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(StartLocation, EndLocation);
}
SourceLocation getLocStart() const LLVM_READONLY { return StartLocation; }
SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; }
};
-/// \brief A set of tokens that has been cached for later parsing.
+/// A set of tokens that has been cached for later parsing.
typedef SmallVector<Token, 4> CachedTokens;
-/// \brief One instance of this struct is used for each type in a
+/// One instance of this struct is used for each type in a
/// declarator that is parsed.
///
/// This is intended to be a small value object.
@@ -1137,11 +1147,9 @@ struct DeclaratorChunk {
return SourceRange(Loc, EndLoc);
}
- struct TypeInfoCommon {
- AttributeList *AttrList;
- };
+ ParsedAttributesView AttrList;
- struct PointerTypeInfo : TypeInfoCommon {
+ struct PointerTypeInfo {
/// The type qualifiers: const/volatile/restrict/unaligned/atomic.
unsigned TypeQuals : 5;
@@ -1164,7 +1172,7 @@ struct DeclaratorChunk {
}
};
- struct ReferenceTypeInfo : TypeInfoCommon {
+ struct ReferenceTypeInfo {
/// The type qualifier: restrict. [GNU] C++ extension
bool HasRestrict : 1;
/// True if this is an lvalue reference, false if it's an rvalue reference.
@@ -1173,7 +1181,7 @@ struct DeclaratorChunk {
}
};
- struct ArrayTypeInfo : TypeInfoCommon {
+ struct ArrayTypeInfo {
/// The type qualifiers for the array:
/// const/volatile/restrict/__unaligned/_Atomic.
unsigned TypeQuals : 5;
@@ -1224,7 +1232,7 @@ struct DeclaratorChunk {
SourceRange Range;
};
- struct FunctionTypeInfo : TypeInfoCommon {
+ struct FunctionTypeInfo {
/// hasPrototype - This is true if the function had at least one typed
/// parameter. If the function is () or (a,b,c), then it has no prototype,
/// and is treated as a K&R-style function.
@@ -1238,7 +1246,7 @@ struct DeclaratorChunk {
/// Can this declaration be a constructor-style initializer?
unsigned isAmbiguous : 1;
- /// \brief Whether the ref-qualifier (if any) is an lvalue reference.
+ /// Whether the ref-qualifier (if any) is an lvalue reference.
/// Otherwise, it's an rvalue reference.
unsigned RefQualifierIsLValueRef : 1;
@@ -1274,34 +1282,34 @@ struct DeclaratorChunk {
/// number of declarations in the function prototype.
unsigned NumExceptionsOrDecls;
- /// \brief The location of the ref-qualifier, if any.
+ /// The location of the ref-qualifier, if any.
///
/// If this is an invalid location, there is no ref-qualifier.
unsigned RefQualifierLoc;
- /// \brief The location of the const-qualifier, if any.
+ /// The location of the const-qualifier, if any.
///
/// If this is an invalid location, there is no const-qualifier.
unsigned ConstQualifierLoc;
- /// \brief The location of the volatile-qualifier, if any.
+ /// The location of the volatile-qualifier, if any.
///
/// If this is an invalid location, there is no volatile-qualifier.
unsigned VolatileQualifierLoc;
- /// \brief The location of the restrict-qualifier, if any.
+ /// The location of the restrict-qualifier, if any.
///
/// If this is an invalid location, there is no restrict-qualifier.
unsigned RestrictQualifierLoc;
- /// \brief The location of the 'mutable' qualifer in a lambda-declarator, if
+ /// The location of the 'mutable' qualifer in a lambda-declarator, if
/// any.
unsigned MutableLoc;
- /// \brief The beginning location of the exception specification, if any.
+ /// The beginning location of the exception specification, if any.
unsigned ExceptionSpecLocBeg;
- /// \brief The end location of the exception specification, if any.
+ /// The end location of the exception specification, if any.
unsigned ExceptionSpecLocEnd;
/// Params - This is a pointer to a new[]'d array of ParamInfo objects that
@@ -1310,16 +1318,16 @@ struct DeclaratorChunk {
ParamInfo *Params;
union {
- /// \brief Pointer to a new[]'d array of TypeAndRange objects that
+ /// Pointer to a new[]'d array of TypeAndRange objects that
/// contain the types in the function's dynamic exception specification
/// and their locations, if there is one.
TypeAndRange *Exceptions;
- /// \brief Pointer to the expression in the noexcept-specifier of this
+ /// Pointer to the expression in the noexcept-specifier of this
/// function, if it has one.
Expr *NoexceptExpr;
-
- /// \brief Pointer to the cached tokens for an exception-specification
+
+ /// Pointer to the cached tokens for an exception-specification
/// that has not yet been parsed.
CachedTokens *ExceptionSpecTokens;
@@ -1329,11 +1337,11 @@ struct DeclaratorChunk {
NamedDecl **DeclsInPrototype;
};
- /// \brief If HasTrailingReturnType is true, this is the trailing return
+ /// If HasTrailingReturnType is true, this is the trailing return
/// type specified.
UnionParsedType TrailingReturnType;
- /// \brief Reset the parameter list to having zero parameters.
+ /// Reset the parameter list to having zero parameters.
///
/// This is used in various places for error recovery.
void freeParams() {
@@ -1347,8 +1355,7 @@ struct DeclaratorChunk {
}
void destroy() {
- if (DeleteParams)
- delete[] Params;
+ freeParams();
switch (getExceptionSpecType()) {
default:
break;
@@ -1394,66 +1401,66 @@ struct DeclaratorChunk {
return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd());
}
- /// \brief Retrieve the location of the ref-qualifier, if any.
+ /// Retrieve the location of the ref-qualifier, if any.
SourceLocation getRefQualifierLoc() const {
return SourceLocation::getFromRawEncoding(RefQualifierLoc);
}
- /// \brief Retrieve the location of the 'const' qualifier, if any.
+ /// Retrieve the location of the 'const' qualifier, if any.
SourceLocation getConstQualifierLoc() const {
return SourceLocation::getFromRawEncoding(ConstQualifierLoc);
}
- /// \brief Retrieve the location of the 'volatile' qualifier, if any.
+ /// Retrieve the location of the 'volatile' qualifier, if any.
SourceLocation getVolatileQualifierLoc() const {
return SourceLocation::getFromRawEncoding(VolatileQualifierLoc);
}
- /// \brief Retrieve the location of the 'restrict' qualifier, if any.
+ /// Retrieve the location of the 'restrict' qualifier, if any.
SourceLocation getRestrictQualifierLoc() const {
return SourceLocation::getFromRawEncoding(RestrictQualifierLoc);
}
- /// \brief Retrieve the location of the 'mutable' qualifier, if any.
+ /// Retrieve the location of the 'mutable' qualifier, if any.
SourceLocation getMutableLoc() const {
return SourceLocation::getFromRawEncoding(MutableLoc);
}
- /// \brief Determine whether this function declaration contains a
+ /// Determine whether this function declaration contains a
/// ref-qualifier.
bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); }
- /// \brief Determine whether this lambda-declarator contains a 'mutable'
+ /// Determine whether this lambda-declarator contains a 'mutable'
/// qualifier.
bool hasMutableQualifier() const { return getMutableLoc().isValid(); }
- /// \brief Get the type of exception specification this function has.
+ /// Get the type of exception specification this function has.
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
- /// \brief Get the number of dynamic exception specifications.
+ /// Get the number of dynamic exception specifications.
unsigned getNumExceptions() const {
assert(ExceptionSpecType != EST_None);
return NumExceptionsOrDecls;
}
- /// \brief Get the non-parameter decls defined within this function
+ /// Get the non-parameter decls defined within this function
/// prototype. Typically these are tag declarations.
ArrayRef<NamedDecl *> getDeclsInPrototype() const {
assert(ExceptionSpecType == EST_None);
return llvm::makeArrayRef(DeclsInPrototype, NumExceptionsOrDecls);
}
- /// \brief Determine whether this function declarator had a
+ /// Determine whether this function declarator had a
/// trailing-return-type.
bool hasTrailingReturnType() const { return HasTrailingReturnType; }
- /// \brief Get the trailing-return-type for this function declarator.
+ /// Get the trailing-return-type for this function declarator.
ParsedType getTrailingReturnType() const { return TrailingReturnType; }
};
- struct BlockPointerTypeInfo : TypeInfoCommon {
+ struct BlockPointerTypeInfo {
/// For now, sema will catch these as invalid.
/// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic.
unsigned TypeQuals : 5;
@@ -1462,7 +1469,7 @@ struct DeclaratorChunk {
}
};
- struct MemberPointerTypeInfo : TypeInfoCommon {
+ struct MemberPointerTypeInfo {
/// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic.
unsigned TypeQuals : 5;
// CXXScopeSpec has a constructor, so it can't be a direct member.
@@ -1479,15 +1486,14 @@ struct DeclaratorChunk {
}
};
- struct PipeTypeInfo : TypeInfoCommon {
- /// The access writes.
- unsigned AccessWrites : 3;
+ struct PipeTypeInfo {
+ /// The access writes.
+ unsigned AccessWrites : 3;
- void destroy() {}
+ void destroy() {}
};
union {
- TypeInfoCommon Common;
PointerTypeInfo Ptr;
ReferenceTypeInfo Ref;
ArrayTypeInfo Arr;
@@ -1510,17 +1516,12 @@ struct DeclaratorChunk {
}
}
- /// \brief If there are attributes applied to this declaratorchunk, return
+ /// If there are attributes applied to this declaratorchunk, return
/// them.
- const AttributeList *getAttrs() const {
- return Common.AttrList;
- }
+ const ParsedAttributesView &getAttrs() const { return AttrList; }
+ ParsedAttributesView &getAttrs() { return AttrList; }
- AttributeList *&getAttrListRef() {
- return Common.AttrList;
- }
-
- /// \brief Return a DeclaratorChunk for a pointer.
+ /// Return a DeclaratorChunk for a pointer.
static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
SourceLocation ConstQualLoc,
SourceLocation VolatileQualLoc,
@@ -1536,11 +1537,10 @@ struct DeclaratorChunk {
I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding();
I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding();
- I.Ptr.AttrList = nullptr;
return I;
}
- /// \brief Return a DeclaratorChunk for a reference.
+ /// Return a DeclaratorChunk for a reference.
static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
bool lvalue) {
DeclaratorChunk I;
@@ -1548,11 +1548,10 @@ struct DeclaratorChunk {
I.Loc = Loc;
I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
I.Ref.LValueRef = lvalue;
- I.Ref.AttrList = nullptr;
return I;
}
- /// \brief Return a DeclaratorChunk for an array.
+ /// Return a DeclaratorChunk for an array.
static DeclaratorChunk getArray(unsigned TypeQuals,
bool isStatic, bool isStar, Expr *NumElts,
SourceLocation LBLoc, SourceLocation RBLoc) {
@@ -1560,7 +1559,6 @@ struct DeclaratorChunk {
I.Kind = Array;
I.Loc = LBLoc;
I.EndLoc = RBLoc;
- I.Arr.AttrList = nullptr;
I.Arr.TypeQuals = TypeQuals;
I.Arr.hasStatic = isStatic;
I.Arr.isStar = isStar;
@@ -1597,25 +1595,23 @@ struct DeclaratorChunk {
TypeResult TrailingReturnType =
TypeResult());
- /// \brief Return a DeclaratorChunk for a block.
+ /// Return a DeclaratorChunk for a block.
static DeclaratorChunk getBlockPointer(unsigned TypeQuals,
SourceLocation Loc) {
DeclaratorChunk I;
I.Kind = BlockPointer;
I.Loc = Loc;
I.Cls.TypeQuals = TypeQuals;
- I.Cls.AttrList = nullptr;
return I;
}
- /// \brief Return a DeclaratorChunk for a block.
+ /// Return a DeclaratorChunk for a block.
static DeclaratorChunk getPipe(unsigned TypeQuals,
SourceLocation Loc) {
DeclaratorChunk I;
I.Kind = Pipe;
I.Loc = Loc;
I.Cls.TypeQuals = TypeQuals;
- I.Cls.AttrList = nullptr;
return I;
}
@@ -1627,19 +1623,17 @@ struct DeclaratorChunk {
I.Loc = SS.getBeginLoc();
I.EndLoc = Loc;
I.Mem.TypeQuals = TypeQuals;
- I.Mem.AttrList = nullptr;
new (I.Mem.ScopeMem) CXXScopeSpec(SS);
return I;
}
- /// \brief Return a DeclaratorChunk for a paren.
+ /// Return a DeclaratorChunk for a paren.
static DeclaratorChunk getParen(SourceLocation LParenLoc,
SourceLocation RParenLoc) {
DeclaratorChunk I;
I.Kind = Paren;
I.Loc = LParenLoc;
I.EndLoc = RParenLoc;
- I.Common.AttrList = nullptr;
return I;
}
@@ -1700,7 +1694,7 @@ public:
}
};
-/// \brief Described the kind of function definition (if any) provided for
+/// Described the kind of function definition (if any) provided for
/// a function.
enum FunctionDefinitionKind {
FDK_Declaration,
@@ -1731,13 +1725,15 @@ enum class DeclaratorContext {
LambdaExprParameterContext, // Lambda-expression parameter declarator.
ConversionIdContext, // C++ conversion-type-id.
TrailingReturnContext, // C++11 trailing-type-specifier.
- TemplateTypeArgContext, // Template type argument.
+ TrailingReturnVarContext, // C++11 trailing-type-specifier for variable.
+ TemplateArgContext, // Any template argument (in template argument list).
+ TemplateTypeArgContext, // Template type argument (in default argument).
AliasDeclContext, // C++11 alias-declaration.
AliasTemplateContext // C++11 alias-declaration template.
};
-/// \brief Information about one declarator, including the parsed type
+/// Information about one declarator, including the parsed type
/// information and the identifier.
///
/// When the declarator is fully formed, this is turned into the appropriate
@@ -1750,14 +1746,14 @@ enum class DeclaratorContext {
/// Instances of this class should be a transient object that lives on the
/// stack, not objects that are allocated in large quantities on the heap.
class Declarator {
-
+
private:
const DeclSpec &DS;
CXXScopeSpec SS;
UnqualifiedId Name;
SourceRange Range;
- /// \brief Where we are parsing this declarator.
+ /// Where we are parsing this declarator.
DeclaratorContext Context;
/// The C++17 structured binding, if any. This is an alternative to a Name.
@@ -1775,21 +1771,21 @@ private:
/// GroupingParens - Set by Parser::ParseParenDeclarator().
unsigned GroupingParens : 1;
- /// FunctionDefinition - Is this Declarator for a function or member
+ /// FunctionDefinition - Is this Declarator for a function or member
/// definition and, if so, what kind?
///
/// Actually a FunctionDefinitionKind.
unsigned FunctionDefinition : 2;
- /// \brief Is this Declarator a redeclaration?
+ /// Is this Declarator a redeclaration?
unsigned Redeclaration : 1;
- /// \brief true if the declaration is preceded by \c __extension__.
+ /// true if the declaration is preceded by \c __extension__.
unsigned Extension : 1;
/// Indicates whether this is an Objective-C instance variable.
unsigned ObjCIvar : 1;
-
+
/// Indicates whether this is an Objective-C 'weak' property.
unsigned ObjCWeakProperty : 1;
@@ -1799,7 +1795,7 @@ private:
/// Attrs - Attributes.
ParsedAttributes Attrs;
- /// \brief The asm label, if specified.
+ /// The asm label, if specified.
Expr *AsmLabel;
#ifndef _MSC_VER
@@ -1814,14 +1810,14 @@ private:
};
#endif
- /// \brief If this is the second or subsequent declarator in this declaration,
+ /// If this is the second or subsequent declarator in this declaration,
/// the location of the comma before this declarator.
SourceLocation CommaLoc;
- /// \brief If provided, the source location of the ellipsis used to describe
+ /// If provided, the source location of the ellipsis used to describe
/// this declarator as a parameter pack.
SourceLocation EllipsisLoc;
-
+
friend struct DeclaratorChunk;
public:
@@ -1856,13 +1852,13 @@ public:
const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
CXXScopeSpec &getCXXScopeSpec() { return SS; }
- /// \brief Retrieve the name specified by this declarator.
+ /// Retrieve the name specified by this declarator.
UnqualifiedId &getName() { return Name; }
const DecompositionDeclarator &getDecompositionDeclarator() const {
return BindingGroup;
}
-
+
DeclaratorContext getContext() const { return Context; }
bool isPrototypeContext() const {
@@ -1872,7 +1868,7 @@ public:
Context == DeclaratorContext::LambdaExprParameterContext);
}
- /// \brief Get the source range that spans this declarator.
+ /// Get the source range that spans this declarator.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
@@ -1900,7 +1896,7 @@ public:
Range.setEnd(SR.getEnd());
}
- /// \brief Reset the contents of this Declarator.
+ /// Reset the contents of this Declarator.
void clear() {
SS.clear();
Name.clear();
@@ -1948,8 +1944,10 @@ public:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
return true;
}
llvm_unreachable("unknown context kind!");
@@ -1984,8 +1982,10 @@ public:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2024,8 +2024,10 @@ public:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2052,6 +2054,7 @@ public:
case DeclaratorContext::BlockContext:
case DeclaratorContext::ForContext:
case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::TrailingReturnVarContext:
return true;
case DeclaratorContext::ConditionContext:
@@ -2077,6 +2080,7 @@ public:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
return false;
@@ -2103,15 +2107,15 @@ public:
return BindingGroup.isSet();
}
- IdentifierInfo *getIdentifier() const {
+ IdentifierInfo *getIdentifier() const {
if (Name.getKind() == UnqualifiedIdKind::IK_Identifier)
return Name.Identifier;
-
+
return nullptr;
}
SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
- /// \brief Set the name of this declarator to be the given identifier.
+ /// Set the name of this declarator to be the given identifier.
void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
Name.setIdentifier(Id, IdLoc);
}
@@ -2124,23 +2128,33 @@ public:
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
/// EndLoc, which should be the last token of the chunk.
- void AddTypeInfo(const DeclaratorChunk &TI,
- ParsedAttributes &attrs,
+ /// This function takes attrs by R-Value reference because it takes ownership
+ /// of those attributes from the parameter.
+ void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs,
SourceLocation EndLoc) {
DeclTypeInfo.push_back(TI);
- DeclTypeInfo.back().getAttrListRef() = attrs.getList();
+ DeclTypeInfo.back().getAttrs().addAll(attrs.begin(), attrs.end());
getAttributePool().takeAllFrom(attrs.getPool());
if (!EndLoc.isInvalid())
SetRangeEnd(EndLoc);
}
- /// \brief Add a new innermost chunk to this declarator.
+ /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
+ /// EndLoc, which should be the last token of the chunk.
+ void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
+ DeclTypeInfo.push_back(TI);
+
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// Add a new innermost chunk to this declarator.
void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
}
- /// \brief Return the number of types applied to this declarator.
+ /// Return the number of types applied to this declarator.
unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
/// Return the specified TypeInfo from this declarator. TypeInfo #0 is
@@ -2247,15 +2261,15 @@ public:
return const_cast<Declarator*>(this)->getFunctionTypeInfo();
}
- /// \brief Determine whether the declaration that will be produced from
+ /// Determine whether the declaration that will be produced from
/// this declaration will be a function.
- ///
+ ///
/// A declaration can declare a function even if the declarator itself
/// isn't a function declarator, if the type specifier refers to a function
/// type. This routine checks for both cases.
bool isDeclarationOfFunction() const;
- /// \brief Return true if this declaration appears in a context where a
+ /// Return true if this declaration appears in a context where a
/// function declarator would be a function declaration.
bool isFunctionDeclarationContext() const {
if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
@@ -2286,8 +2300,10 @@ public:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2302,8 +2318,8 @@ public:
case DeclaratorContext::MemberContext:
// FIXME: sizeof(...) permits an expression.
- case DeclaratorContext::TypeNameContext:
-
+ case DeclaratorContext::TypeNameContext:
+
case DeclaratorContext::FunctionalCastContext:
case DeclaratorContext::AliasDeclContext:
case DeclaratorContext::AliasTemplateContext:
@@ -2319,20 +2335,22 @@ public:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TemplateTypeArgContext:
return false;
case DeclaratorContext::BlockContext:
case DeclaratorContext::ForContext:
case DeclaratorContext::InitStmtContext:
case DeclaratorContext::ConditionContext:
- case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TemplateArgContext:
return true;
}
llvm_unreachable("unknown context kind!");
}
-
- /// \brief Return true if a function declarator at this position would be a
+
+ /// Return true if a function declarator at this position would be a
/// function declaration.
bool isFunctionDeclaratorAFunctionDeclaration() const {
if (!isFunctionDeclarationContext())
@@ -2345,7 +2363,7 @@ public:
return true;
}
- /// \brief Determine whether a trailing return type was written (at any
+ /// Determine whether a trailing return type was written (at any
/// level) within this declarator.
bool hasTrailingReturnType() const {
for (const auto &Chunk : type_objects())
@@ -2371,29 +2389,25 @@ public:
SetRangeEnd(lastLoc);
}
- const AttributeList *getAttributes() const { return Attrs.getList(); }
- AttributeList *getAttributes() { return Attrs.getList(); }
-
- AttributeList *&getAttrListRef() { return Attrs.getListRef(); }
+ const ParsedAttributes &getAttributes() const { return Attrs; }
+ ParsedAttributes &getAttributes() { return Attrs; }
/// hasAttributes - do we contain any attributes?
bool hasAttributes() const {
- if (getAttributes() || getDeclSpec().hasAttributes()) return true;
+ if (!getAttributes().empty() || getDeclSpec().hasAttributes())
+ return true;
for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i)
- if (getTypeObject(i).getAttrs())
+ if (!getTypeObject(i).getAttrs().empty())
return true;
return false;
}
- /// \brief Return a source range list of C++11 attributes associated
+ /// Return a source range list of C++11 attributes associated
/// with the declarator.
void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) {
- AttributeList *AttrList = Attrs.getList();
- while (AttrList) {
- if (AttrList->isCXX11Attribute())
- Ranges.push_back(AttrList->getRange());
- AttrList = AttrList->getNext();
- }
+ for (const ParsedAttr &AL : Attrs)
+ if (AL.isCXX11Attribute())
+ Ranges.push_back(AL.getRange());
}
void setAsmLabel(Expr *E) { AsmLabel = E; }
@@ -2404,7 +2418,7 @@ public:
void setObjCIvar(bool Val = true) { ObjCIvar = Val; }
bool isObjCIvar() const { return ObjCIvar; }
-
+
void setObjCWeakProperty(bool Val = true) { ObjCWeakProperty = Val; }
bool isObjCWeakProperty() const { return ObjCWeakProperty; }
@@ -2424,16 +2438,16 @@ public:
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
- void setFunctionDefinitionKind(FunctionDefinitionKind Val) {
- FunctionDefinition = Val;
+ void setFunctionDefinitionKind(FunctionDefinitionKind Val) {
+ FunctionDefinition = Val;
}
-
+
bool isFunctionDefinition() const {
return getFunctionDefinitionKind() != FDK_Declaration;
}
-
- FunctionDefinitionKind getFunctionDefinitionKind() const {
- return (FunctionDefinitionKind)FunctionDefinition;
+
+ FunctionDefinitionKind getFunctionDefinitionKind() const {
+ return (FunctionDefinitionKind)FunctionDefinition;
}
/// Returns true if this declares a real member and not a friend.
@@ -2454,7 +2468,7 @@ public:
bool isRedeclaration() const { return Redeclaration; }
};
-/// \brief This little struct is used to capture information about
+/// This little struct is used to capture information about
/// structure field declarators, which is basically just a bitfield size.
struct FieldDeclarator {
Declarator D;
@@ -2464,7 +2478,7 @@ struct FieldDeclarator {
BitfieldSize(nullptr) {}
};
-/// \brief Represents a C++11 virt-specifier-seq.
+/// Represents a C++11 virt-specifier-seq.
class VirtSpecifiers {
public:
enum Specifier {
@@ -2497,7 +2511,7 @@ public:
SourceLocation getFirstLocation() const { return FirstLocation; }
SourceLocation getLastLocation() const { return LastLocation; }
Specifier getLastSpecifier() const { return LastSpecifier; }
-
+
private:
unsigned Specifiers;
Specifier LastSpecifier;
@@ -2514,9 +2528,9 @@ enum class LambdaCaptureInitKind {
ListInit //!< [a{b}]
};
-/// \brief Represents a complete lambda introducer.
+/// Represents a complete lambda introducer.
struct LambdaIntroducer {
- /// \brief An individual capture in a lambda introducer.
+ /// An individual capture in a lambda introducer.
struct LambdaCapture {
LambdaCaptureKind Kind;
SourceLocation Loc;
@@ -2525,12 +2539,16 @@ struct LambdaIntroducer {
LambdaCaptureInitKind InitKind;
ExprResult Init;
ParsedType InitCaptureType;
+ SourceRange ExplicitRange;
+
LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
IdentifierInfo *Id, SourceLocation EllipsisLoc,
LambdaCaptureInitKind InitKind, ExprResult Init,
- ParsedType InitCaptureType)
+ ParsedType InitCaptureType,
+ SourceRange ExplicitRange)
: Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc),
- InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType) {}
+ InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType),
+ ExplicitRange(ExplicitRange) {}
};
SourceRange Range;
@@ -2541,16 +2559,17 @@ struct LambdaIntroducer {
LambdaIntroducer()
: Default(LCD_None) {}
- /// \brief Append a capture in a lambda introducer.
+ /// Append a capture in a lambda introducer.
void addCapture(LambdaCaptureKind Kind,
SourceLocation Loc,
IdentifierInfo* Id,
SourceLocation EllipsisLoc,
LambdaCaptureInitKind InitKind,
- ExprResult Init,
- ParsedType InitCaptureType) {
+ ExprResult Init,
+ ParsedType InitCaptureType,
+ SourceRange ExplicitRange) {
Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
- InitCaptureType));
+ InitCaptureType, ExplicitRange));
}
};
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h
index d65dbf0cd34e..a26b6ff070f6 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h
@@ -1,4 +1,4 @@
-//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- C++ -*-===//
+//===- DelayedDiagnostic.h - Delayed declarator diagnostics -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,9 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief Defines the classes clang::DelayedDiagnostic and
+/// Defines the classes clang::DelayedDiagnostic and
/// clang::AccessedEntity.
///
/// DelayedDiangostic is used to record diagnostics that are being
@@ -16,15 +16,34 @@
/// diagnostics -- notably deprecation and access control -- are suppressed
/// based on semantic properties of the parsed declaration that aren't known
/// until it is fully parsed.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
#define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
namespace clang {
+
+class ObjCInterfaceDecl;
+class ObjCPropertyDecl;
+
namespace sema {
/// A declaration being accessed, together with information about how
@@ -39,16 +58,14 @@ public:
/// The target is the base class.
enum BaseNonce { Base };
- bool isMemberAccess() const { return IsMember; }
-
AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator,
MemberNonce _,
CXXRecordDecl *NamingClass,
DeclAccessPair FoundDecl,
QualType BaseObjectType)
- : Access(FoundDecl.getAccess()), IsMember(true),
- Target(FoundDecl.getDecl()), NamingClass(NamingClass),
- BaseObjectType(BaseObjectType), Diag(0, Allocator) {
+ : Access(FoundDecl.getAccess()), IsMember(true),
+ Target(FoundDecl.getDecl()), NamingClass(NamingClass),
+ BaseObjectType(BaseObjectType), Diag(0, Allocator) {
}
AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator,
@@ -56,11 +73,10 @@ public:
CXXRecordDecl *BaseClass,
CXXRecordDecl *DerivedClass,
AccessSpecifier Access)
- : Access(Access), IsMember(false),
- Target(BaseClass),
- NamingClass(DerivedClass),
- Diag(0, Allocator) {
- }
+ : Access(Access), IsMember(false), Target(BaseClass),
+ NamingClass(DerivedClass), Diag(0, Allocator) {}
+
+ bool isMemberAccess() const { return IsMember; }
bool isQuiet() const { return Diag.getDiagID() == 0; }
@@ -123,7 +139,7 @@ public:
void Destroy();
static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
- SourceLocation Loc,
+ ArrayRef<SourceLocation> Locs,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -131,7 +147,6 @@ public:
StringRef Msg,
bool ObjCPropertyAccess);
-
static DelayedDiagnostic makeAccess(SourceLocation Loc,
const AccessedEntity &Entity) {
DelayedDiagnostic DD;
@@ -179,6 +194,12 @@ public:
return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen);
}
+ ArrayRef<SourceLocation> getAvailabilitySelectorLocs() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return llvm::makeArrayRef(AvailabilityData.SelectorLocs,
+ AvailabilityData.NumSelectorLocs);
+ }
+
AvailabilityResult getAvailabilityResult() const {
assert(Kind == Availability && "Not an availability diagnostic.");
return AvailabilityData.AR;
@@ -216,7 +237,6 @@ public:
}
private:
-
struct AD {
const NamedDecl *ReferringDecl;
const NamedDecl *OffendingDecl;
@@ -224,6 +244,8 @@ private:
const ObjCPropertyDecl *ObjCProperty;
const char *Message;
size_t MessageLen;
+ SourceLocation *SelectorLocs;
+ size_t NumSelectorLocs;
AvailabilityResult AR;
bool ObjCPropertyAccess;
};
@@ -243,25 +265,22 @@ private:
};
};
-/// \brief A collection of diagnostics which were delayed.
+/// A collection of diagnostics which were delayed.
class DelayedDiagnosticPool {
const DelayedDiagnosticPool *Parent;
SmallVector<DelayedDiagnostic, 4> Diagnostics;
- DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete;
- void operator=(const DelayedDiagnosticPool &) = delete;
public:
DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
- ~DelayedDiagnosticPool() {
- for (SmallVectorImpl<DelayedDiagnostic>::iterator
- i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
- i->Destroy();
- }
+
+ DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete;
+ DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &) = delete;
DelayedDiagnosticPool(DelayedDiagnosticPool &&Other)
- : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) {
+ : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) {
Other.Diagnostics.clear();
}
+
DelayedDiagnosticPool &operator=(DelayedDiagnosticPool &&Other) {
Parent = Other.Parent;
Diagnostics = std::move(Other.Diagnostics);
@@ -269,6 +288,12 @@ public:
return *this;
}
+ ~DelayedDiagnosticPool() {
+ for (SmallVectorImpl<DelayedDiagnostic>::iterator
+ i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
+ i->Destroy();
+ }
+
const DelayedDiagnosticPool *getParent() const { return Parent; }
/// Does this pool, or any of its ancestors, contain any diagnostics?
@@ -293,13 +318,14 @@ public:
pool.Diagnostics.clear();
}
- typedef SmallVectorImpl<DelayedDiagnostic>::const_iterator pool_iterator;
+ using pool_iterator = SmallVectorImpl<DelayedDiagnostic>::const_iterator;
+
pool_iterator pool_begin() const { return Diagnostics.begin(); }
pool_iterator pool_end() const { return Diagnostics.end(); }
bool pool_empty() const { return Diagnostics.empty(); }
};
-}
+} // namespace clang
/// Add a diagnostic to the current delay pool.
inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
@@ -307,7 +333,6 @@ inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
CurPool->add(diag);
}
+} // namespace clang
-}
-
-#endif
+#endif // LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
index c5cb7b12b3f1..00f80e27415d 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
@@ -39,15 +39,15 @@ class ValueDecl;
class VarDecl;
struct LateParsedTemplate;
-/// \brief A simple structure that captures a vtable use for the purposes of
+/// A simple structure that captures a vtable use for the purposes of
/// the \c ExternalSemaSource.
struct ExternalVTableUse {
CXXRecordDecl *Record;
SourceLocation Location;
bool DefinitionRequired;
};
-
-/// \brief An abstract interface that should be implemented by
+
+/// An abstract interface that should be implemented by
/// external AST sources that also provide information for semantic
/// analysis.
class ExternalSemaSource : public ExternalASTSource {
@@ -58,15 +58,15 @@ public:
~ExternalSemaSource() override;
- /// \brief Initialize the semantic source with the Sema instance
+ /// Initialize the semantic source with the Sema instance
/// being used to perform semantic analysis on the abstract syntax
/// tree.
virtual void InitializeSema(Sema &S) {}
- /// \brief Inform the semantic consumer that Sema is no longer available.
+ /// Inform the semantic consumer that Sema is no longer available.
virtual void ForgetSema() {}
- /// \brief Load the contents of the global method pool for a given
+ /// Load the contents of the global method pool for a given
/// selector.
virtual void ReadMethodPool(Selector Sel);
@@ -74,12 +74,12 @@ public:
/// selector if necessary.
virtual void updateOutOfDateSelector(Selector Sel);
- /// \brief Load the set of namespaces that are known to the external source,
+ /// Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
virtual void ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces);
- /// \brief Load the set of used but not defined functions or variables with
+ /// Load the set of used but not defined functions or variables with
/// internal linkage, or used but not defined internal functions.
virtual void
ReadUndefinedButUsed(llvm::MapVector<NamedDecl *, SourceLocation> &Undefined);
@@ -87,7 +87,7 @@ public:
virtual void ReadMismatchingDeleteExpressions(llvm::MapVector<
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &);
- /// \brief Do last resort, unqualified lookup on a LookupResult that
+ /// Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
///
/// \param R a LookupResult that is being recovered.
@@ -97,7 +97,7 @@ public:
/// \return true to tell Sema to recover using the LookupResult.
virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; }
- /// \brief Read the set of tentative definitions known to the external Sema
+ /// Read the set of tentative definitions known to the external Sema
/// source.
///
/// The external source should append its own tentative definitions to the
@@ -106,8 +106,8 @@ public:
/// introduce the same declarations repeatedly.
virtual void ReadTentativeDefinitions(
SmallVectorImpl<VarDecl *> &TentativeDefs) {}
-
- /// \brief Read the set of unused file-scope declarations known to the
+
+ /// Read the set of unused file-scope declarations known to the
/// external Sema source.
///
/// The external source should append its own unused, filed-scope to the
@@ -116,8 +116,8 @@ public:
/// introduce the same declarations repeatedly.
virtual void ReadUnusedFileScopedDecls(
SmallVectorImpl<const DeclaratorDecl *> &Decls) {}
-
- /// \brief Read the set of delegating constructors known to the
+
+ /// Read the set of delegating constructors known to the
/// external Sema source.
///
/// The external source should append its own delegating constructors to the
@@ -127,7 +127,7 @@ public:
virtual void ReadDelegatingConstructors(
SmallVectorImpl<CXXConstructorDecl *> &Decls) {}
- /// \brief Read the set of ext_vector type declarations known to the
+ /// Read the set of ext_vector type declarations known to the
/// external Sema source.
///
/// The external source should append its own ext_vector type declarations to
@@ -136,7 +136,7 @@ public:
/// introduce the same declarations repeatedly.
virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {}
- /// \brief Read the set of potentially unused typedefs known to the source.
+ /// Read the set of potentially unused typedefs known to the source.
///
/// The external source should append its own potentially unused local
/// typedefs to the given vector of declarations. Note that this routine may
@@ -145,34 +145,34 @@ public:
virtual void ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}
- /// \brief Read the set of referenced selectors known to the
+ /// Read the set of referenced selectors known to the
/// external Sema source.
///
- /// The external source should append its own referenced selectors to the
- /// given vector of selectors. Note that this routine
- /// may be invoked multiple times; the external source should take care not
+ /// The external source should append its own referenced selectors to the
+ /// given vector of selectors. Note that this routine
+ /// may be invoked multiple times; the external source should take care not
/// to introduce the same selectors repeatedly.
virtual void ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {}
- /// \brief Read the set of weak, undeclared identifiers known to the
+ /// Read the set of weak, undeclared identifiers known to the
/// external Sema source.
///
/// The external source should append its own weak, undeclared identifiers to
- /// the given vector. Note that this routine may be invoked multiple times;
+ /// the given vector. Note that this routine may be invoked multiple times;
/// the external source should take care not to introduce the same identifiers
/// repeatedly.
virtual void ReadWeakUndeclaredIdentifiers(
SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {}
- /// \brief Read the set of used vtables known to the external Sema source.
+ /// Read the set of used vtables known to the external Sema source.
///
/// The external source should append its own used vtables to the given
/// vector. Note that this routine may be invoked multiple times; the external
/// source should take care not to introduce the same vtables repeatedly.
virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {}
- /// \brief Read the set of pending instantiations known to the external
+ /// Read the set of pending instantiations known to the external
/// Sema source.
///
/// The external source should append its own pending instantiations to the
@@ -180,10 +180,10 @@ public:
/// external source should take care not to introduce the same instantiations
/// repeatedly.
virtual void ReadPendingInstantiations(
- SmallVectorImpl<std::pair<ValueDecl *,
+ SmallVectorImpl<std::pair<ValueDecl *,
SourceLocation> > &Pending) {}
- /// \brief Read the set of late parsed template functions for this source.
+ /// Read the set of late parsed template functions for this source.
///
/// The external source should insert its own late parsed template functions
/// into the map. Note that this routine may be invoked multiple times; the
@@ -209,7 +209,7 @@ public:
return TypoCorrection();
}
- /// \brief Produces a diagnostic note if the external source contains a
+ /// Produces a diagnostic note if the external source contains a
/// complete definition for \p T.
///
/// \param Loc the location at which a complete type was required but not
@@ -227,7 +227,7 @@ public:
static bool classof(const ExternalASTSource *Source) {
return Source->SemaSource;
}
-};
+};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h
index 382fe80bea7d..1c46e1d0e3d2 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h
@@ -15,35 +15,38 @@
#ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
#define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
-#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
namespace clang {
-class ASTContext;
class Decl;
-class DeclContext;
class DeclarationName;
-class ExternalPreprocessorSource;
+class DeclContext;
+class IdentifierInfo;
+class LangOptions;
class NamedDecl;
class Preprocessor;
class Scope;
-
+
/// IdentifierResolver - Keeps track of shadowed decls on enclosing
/// scopes. It manages the shadowing chains of declaration names and
/// implements efficient decl lookup based on a declaration name.
class IdentifierResolver {
-
/// IdDeclInfo - Keeps track of information about decls associated
/// to a particular declaration name. IdDeclInfos are lazily
/// constructed and assigned to a declaration name the first time a
/// decl with that declaration name is shadowed in some scope.
class IdDeclInfo {
public:
- typedef SmallVector<NamedDecl*, 2> DeclsTy;
+ using DeclsTy = SmallVector<NamedDecl *, 2>;
- inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
- inline DeclsTy::iterator decls_end() { return Decls.end(); }
+ DeclsTy::iterator decls_begin() { return Decls.begin(); }
+ DeclsTy::iterator decls_end() { return Decls.end(); }
void AddDecl(NamedDecl *D) { Decls.push_back(D); }
@@ -51,40 +54,42 @@ class IdentifierResolver {
/// The decl must already be part of the decl chain.
void RemoveDecl(NamedDecl *D);
- /// \brief Insert the given declaration at the given position in the list.
+ /// Insert the given declaration at the given position in the list.
void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) {
Decls.insert(Pos, D);
}
-
+
private:
DeclsTy Decls;
};
public:
-
/// iterator - Iterate over the decls of a specified declaration name.
/// It will walk or not the parent declaration contexts depending on how
/// it was instantiated.
class iterator {
public:
- typedef NamedDecl * value_type;
- typedef NamedDecl * reference;
- typedef NamedDecl * pointer;
- typedef std::input_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ friend class IdentifierResolver;
+
+ using value_type = NamedDecl *;
+ using reference = NamedDecl *;
+ using pointer = NamedDecl *;
+ using iterator_category = std::input_iterator_tag;
+ using difference_type = std::ptrdiff_t;
/// Ptr - There are 2 forms that 'Ptr' represents:
/// 1) A single NamedDecl. (Ptr & 0x1 == 0)
/// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
/// same declaration context. (Ptr & 0x1 == 0x1)
- uintptr_t Ptr;
- typedef IdDeclInfo::DeclsTy::iterator BaseIter;
+ uintptr_t Ptr = 0;
+ using BaseIter = IdDeclInfo::DeclsTy::iterator;
/// A single NamedDecl. (Ptr & 0x1 == 0)
iterator(NamedDecl *D) {
Ptr = reinterpret_cast<uintptr_t>(D);
assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
}
+
/// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
/// contexts depending on 'LookInParentCtx'.
iterator(BaseIter I) {
@@ -98,11 +103,10 @@ public:
return reinterpret_cast<BaseIter>(Ptr & ~0x1);
}
- friend class IdentifierResolver;
-
void incrementSlowCase();
+
public:
- iterator() : Ptr(0) {}
+ iterator() = default;
NamedDecl *operator*() const {
if (isIterator())
@@ -128,6 +132,9 @@ public:
}
};
+ explicit IdentifierResolver(Preprocessor &PP);
+ ~IdentifierResolver();
+
/// begin - Returns an iterator for decls with the name 'Name'.
iterator begin(DeclarationName Name);
@@ -156,11 +163,11 @@ public:
/// The decl must already be part of the decl chain.
void RemoveDecl(NamedDecl *D);
- /// \brief Insert the given declaration after the given iterator
+ /// Insert the given declaration after the given iterator
/// position.
void InsertDeclAfter(iterator Pos, NamedDecl *D);
- /// \brief Try to add the given declaration to the top level scope, if it
+ /// Try to add the given declaration to the top level scope, if it
/// (or a redeclaration of it) hasn't already been added.
///
/// \param D The externally-produced declaration to add.
@@ -169,20 +176,17 @@ public:
///
/// \returns true if the declaration was added, false otherwise.
bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name);
-
- explicit IdentifierResolver(Preprocessor &PP);
- ~IdentifierResolver();
private:
const LangOptions &LangOpt;
Preprocessor &PP;
-
+
class IdDeclInfoMap;
IdDeclInfoMap *IdDeclInfos;
void updatingIdentifier(IdentifierInfo &II);
void readingIdentifier(IdentifierInfo &II);
-
+
/// FETokenInfo contains a Decl pointer if lower bit == 0.
static inline bool isDeclPtr(void *Ptr) {
return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
@@ -193,11 +197,10 @@ private:
assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
&& "Ptr not a IdDeclInfo* !");
return reinterpret_cast<IdDeclInfo*>(
- reinterpret_cast<uintptr_t>(Ptr) & ~0x1
- );
+ reinterpret_cast<uintptr_t>(Ptr) & ~0x1);
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
index bd07b9ea9aee..8582e971d0b6 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
@@ -1,4 +1,4 @@
-//===--- Initialization.h - Semantic Analysis for Initializers --*- C++ -*-===//
+//===- Initialization.h - Semantic Analysis for Initializers ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,85 +10,115 @@
// This file provides supporting data types for initialization of objects.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_SEMA_INITIALIZATION_H
#define LLVM_CLANG_SEMA_INITIALIZATION_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
-#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include <cassert>
+#include <cstdint>
+#include <string>
namespace clang {
-
+
+class APValue;
class CXXBaseSpecifier;
-class DeclaratorDecl;
-class DeclaratorInfo;
-class FieldDecl;
-class FunctionDecl;
-class ParmVarDecl;
-class Sema;
-class TypeLoc;
-class VarDecl;
+class CXXConstructorDecl;
class ObjCMethodDecl;
-
-/// \brief Describes an entity that is being initialized.
-class InitializedEntity {
+class Sema;
+
+/// Describes an entity that is being initialized.
+class alignas(8) InitializedEntity {
public:
- /// \brief Specifies the kind of entity being initialized.
+ /// Specifies the kind of entity being initialized.
enum EntityKind {
- /// \brief The entity being initialized is a variable.
+ /// The entity being initialized is a variable.
EK_Variable,
- /// \brief The entity being initialized is a function parameter.
+
+ /// The entity being initialized is a function parameter.
EK_Parameter,
- /// \brief The entity being initialized is the result of a function call.
+
+ /// The entity being initialized is the result of a function call.
EK_Result,
- /// \brief The entity being initialized is an exception object that
+
+ /// The entity being initialized is the result of a statement expression.
+ EK_StmtExprResult,
+
+ /// The entity being initialized is an exception object that
/// is being thrown.
EK_Exception,
- /// \brief The entity being initialized is a non-static data member
+
+ /// The entity being initialized is a non-static data member
/// subobject.
EK_Member,
- /// \brief The entity being initialized is an element of an array.
+
+ /// The entity being initialized is an element of an array.
EK_ArrayElement,
- /// \brief The entity being initialized is an object (or array of
+
+ /// The entity being initialized is an object (or array of
/// objects) allocated via new.
EK_New,
- /// \brief The entity being initialized is a temporary object.
+
+ /// The entity being initialized is a temporary object.
EK_Temporary,
- /// \brief The entity being initialized is a base member subobject.
+
+ /// The entity being initialized is a base member subobject.
EK_Base,
- /// \brief The initialization is being done by a delegating constructor.
+
+ /// The initialization is being done by a delegating constructor.
EK_Delegating,
- /// \brief The entity being initialized is an element of a vector.
+
+ /// The entity being initialized is an element of a vector.
/// or vector.
EK_VectorElement,
- /// \brief The entity being initialized is a field of block descriptor for
+
+ /// The entity being initialized is a field of block descriptor for
/// the copied-in c++ object.
EK_BlockElement,
+
/// The entity being initialized is a field of block descriptor for the
/// copied-in lambda object that's used in the lambda to block conversion.
EK_LambdaToBlockConversionBlockElement,
- /// \brief The entity being initialized is the real or imaginary part of a
+
+ /// The entity being initialized is the real or imaginary part of a
/// complex number.
EK_ComplexElement,
- /// \brief The entity being initialized is the field that captures a
+
+ /// The entity being initialized is the field that captures a
/// variable in a lambda.
EK_LambdaCapture,
- /// \brief The entity being initialized is the initializer for a compound
+
+ /// The entity being initialized is the initializer for a compound
/// literal.
EK_CompoundLiteralInit,
- /// \brief The entity being implicitly initialized back to the formal
+
+ /// The entity being implicitly initialized back to the formal
/// result type.
EK_RelatedResult,
- /// \brief The entity being initialized is a function parameter; function
+
+ /// The entity being initialized is a function parameter; function
/// is member of group of audited CF APIs.
EK_Parameter_CF_Audited,
- /// \brief The entity being initialized is a structured binding of a
+
+ /// The entity being initialized is a structured binding of a
/// decomposition declaration.
EK_Binding,
@@ -96,133 +126,132 @@ public:
// enum as an index for its first %select. When modifying this list,
// that diagnostic text needs to be updated as well.
};
-
+
private:
- /// \brief The kind of entity being initialized.
+ /// The kind of entity being initialized.
EntityKind Kind;
- /// \brief If non-NULL, the parent entity in which this
+ /// If non-NULL, the parent entity in which this
/// initialization occurs.
- const InitializedEntity *Parent;
+ const InitializedEntity *Parent = nullptr;
- /// \brief The type of the object or reference being initialized.
+ /// The type of the object or reference being initialized.
QualType Type;
- /// \brief The mangling number for the next reference temporary to be created.
- mutable unsigned ManglingNumber;
+ /// The mangling number for the next reference temporary to be created.
+ mutable unsigned ManglingNumber = 0;
struct LN {
- /// \brief When Kind == EK_Result, EK_Exception, EK_New, the
+ /// When Kind == EK_Result, EK_Exception, EK_New, the
/// location of the 'return', 'throw', or 'new' keyword,
/// respectively. When Kind == EK_Temporary, the location where
/// the temporary is being created.
unsigned Location;
- /// \brief Whether the entity being initialized may end up using the
+ /// Whether the entity being initialized may end up using the
/// named return value optimization (NRVO).
bool NRVO;
};
struct VD {
- /// \brief The VarDecl, FieldDecl, or BindingDecl being initialized.
+ /// The VarDecl, FieldDecl, or BindingDecl being initialized.
ValueDecl *VariableOrMember;
- /// \brief When Kind == EK_Member, whether this is an implicit member
+ /// When Kind == EK_Member, whether this is an implicit member
/// initialization in a copy or move constructor. These can perform array
/// copies.
bool IsImplicitFieldInit;
+
+ /// When Kind == EK_Member, whether this is the initial initialization
+ /// check for a default member initializer.
+ bool IsDefaultMemberInit;
};
struct C {
- /// \brief The name of the variable being captured by an EK_LambdaCapture.
+ /// The name of the variable being captured by an EK_LambdaCapture.
IdentifierInfo *VarID;
- /// \brief The source location at which the capture occurs.
+ /// The source location at which the capture occurs.
unsigned Location;
};
union {
- /// \brief When Kind == EK_Variable, EK_Member or EK_Binding, the variable.
+ /// When Kind == EK_Variable, EK_Member or EK_Binding, the variable.
VD Variable;
-
- /// \brief When Kind == EK_RelatedResult, the ObjectiveC method where
+
+ /// When Kind == EK_RelatedResult, the ObjectiveC method where
/// result type was implicitly changed to accommodate ARC semantics.
ObjCMethodDecl *MethodDecl;
- /// \brief When Kind == EK_Parameter, the ParmVarDecl, with the
+ /// When Kind == EK_Parameter, the ParmVarDecl, with the
/// low bit indicating whether the parameter is "consumed".
uintptr_t Parameter;
-
- /// \brief When Kind == EK_Temporary or EK_CompoundLiteralInit, the type
+
+ /// When Kind == EK_Temporary or EK_CompoundLiteralInit, the type
/// source information for the temporary.
TypeSourceInfo *TypeInfo;
struct LN LocAndNRVO;
-
- /// \brief When Kind == EK_Base, the base specifier that provides the
+
+ /// When Kind == EK_Base, the base specifier that provides the
/// base class. The lower bit specifies whether the base is an inherited
/// virtual base.
uintptr_t Base;
- /// \brief When Kind == EK_ArrayElement, EK_VectorElement, or
+ /// When Kind == EK_ArrayElement, EK_VectorElement, or
/// EK_ComplexElement, the index of the array or vector element being
- /// initialized.
+ /// initialized.
unsigned Index;
struct C Capture;
};
- InitializedEntity() : ManglingNumber(0) {}
+ InitializedEntity() = default;
- /// \brief Create the initialization entity for a variable.
+ /// Create the initialization entity for a variable.
InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
- : Kind(EK), Parent(nullptr), Type(Var->getType()),
- ManglingNumber(0), Variable{Var, false} { }
-
- /// \brief Create the initialization entity for the result of a
+ : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
+
+ /// Create the initialization entity for the result of a
/// function, throwing an object, performing an explicit cast, or
/// initializing a parameter for which there is no declaration.
InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
bool NRVO = false)
- : Kind(Kind), Parent(nullptr), Type(Type), ManglingNumber(0)
- {
+ : Kind(Kind), Type(Type) {
LocAndNRVO.Location = Loc.getRawEncoding();
LocAndNRVO.NRVO = NRVO;
}
-
- /// \brief Create the initialization entity for a member subobject.
+
+ /// Create the initialization entity for a member subobject.
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
- bool Implicit)
- : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
- ManglingNumber(0), Variable{Member, Implicit} {
- }
-
- /// \brief Create the initialization entity for an array element.
- InitializedEntity(ASTContext &Context, unsigned Index,
+ bool Implicit, bool DefaultMemberInit)
+ : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ Variable{Member, Implicit, DefaultMemberInit} {}
+
+ /// Create the initialization entity for an array element.
+ InitializedEntity(ASTContext &Context, unsigned Index,
const InitializedEntity &Parent);
- /// \brief Create the initialization entity for a lambda capture.
+ /// Create the initialization entity for a lambda capture.
InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
- : Kind(EK_LambdaCapture), Parent(nullptr), Type(FieldType),
- ManglingNumber(0)
- {
+ : Kind(EK_LambdaCapture), Type(FieldType) {
Capture.VarID = VarID;
Capture.Location = Loc.getRawEncoding();
}
-
+
public:
- /// \brief Create the initialization entity for a variable.
+ /// Create the initialization entity for a variable.
static InitializedEntity InitializeVariable(VarDecl *Var) {
return InitializedEntity(Var);
}
- /// \brief Create the initialization entity for a parameter.
+ /// Create the initialization entity for a parameter.
static InitializedEntity InitializeParameter(ASTContext &Context,
const ParmVarDecl *Parm) {
return InitializeParameter(Context, Parm, Parm->getType());
}
- /// \brief Create the initialization entity for a parameter, but use
+ /// Create the initialization entity for a parameter, but use
/// another type.
static InitializedEntity InitializeParameter(ASTContext &Context,
const ParmVarDecl *Parm,
@@ -240,7 +269,7 @@ public:
return Entity;
}
- /// \brief Create the initialization entity for a parameter that is
+ /// Create the initialization entity for a parameter that is
/// only known by its type.
static InitializedEntity InitializeParameter(ASTContext &Context,
QualType Type,
@@ -253,12 +282,17 @@ public:
return Entity;
}
- /// \brief Create the initialization entity for the result of a function.
+ /// Create the initialization entity for the result of a function.
static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
QualType Type, bool NRVO) {
return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
}
+ static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc,
+ QualType Type) {
+ return InitializedEntity(EK_StmtExprResult, ReturnLoc, Type);
+ }
+
static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
QualType Type, bool NRVO) {
return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO);
@@ -270,36 +304,36 @@ public:
BlockVarLoc, Type, NRVO);
}
- /// \brief Create the initialization entity for an exception object.
+ /// Create the initialization entity for an exception object.
static InitializedEntity InitializeException(SourceLocation ThrowLoc,
QualType Type, bool NRVO) {
return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO);
}
- /// \brief Create the initialization entity for an object allocated via new.
+ /// Create the initialization entity for an object allocated via new.
static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
return InitializedEntity(EK_New, NewLoc, Type);
}
-
- /// \brief Create the initialization entity for a temporary.
+
+ /// Create the initialization entity for a temporary.
static InitializedEntity InitializeTemporary(QualType Type) {
return InitializeTemporary(nullptr, Type);
}
- /// \brief Create the initialization entity for a temporary.
+ /// Create the initialization entity for a temporary.
static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) {
return InitializeTemporary(TypeInfo, TypeInfo->getType());
}
-
- /// \brief Create the initialization entity for a temporary.
+
+ /// Create the initialization entity for a temporary.
static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo,
QualType Type) {
InitializedEntity Result(EK_Temporary, SourceLocation(), Type);
Result.TypeInfo = TypeInfo;
return Result;
}
-
- /// \brief Create the initialization entity for a related result.
+
+ /// Create the initialization entity for a related result.
static InitializedEntity InitializeRelatedResult(ObjCMethodDecl *MD,
QualType Type) {
InitializedEntity Result(EK_RelatedResult, SourceLocation(), Type);
@@ -307,54 +341,59 @@ public:
return Result;
}
-
- /// \brief Create the initialization entity for a base class subobject.
+ /// Create the initialization entity for a base class subobject.
static InitializedEntity
InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base,
bool IsInheritedVirtualBase,
const InitializedEntity *Parent = nullptr);
- /// \brief Create the initialization entity for a delegated constructor.
+ /// Create the initialization entity for a delegated constructor.
static InitializedEntity InitializeDelegation(QualType Type) {
return InitializedEntity(EK_Delegating, SourceLocation(), Type);
}
-
- /// \brief Create the initialization entity for a member subobject.
+
+ /// Create the initialization entity for a member subobject.
static InitializedEntity
InitializeMember(FieldDecl *Member,
const InitializedEntity *Parent = nullptr,
bool Implicit = false) {
- return InitializedEntity(Member, Parent, Implicit);
+ return InitializedEntity(Member, Parent, Implicit, false);
}
-
- /// \brief Create the initialization entity for a member subobject.
+
+ /// Create the initialization entity for a member subobject.
static InitializedEntity
InitializeMember(IndirectFieldDecl *Member,
const InitializedEntity *Parent = nullptr,
bool Implicit = false) {
- return InitializedEntity(Member->getAnonField(), Parent, Implicit);
+ return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
}
- /// \brief Create the initialization entity for an array element.
- static InitializedEntity InitializeElement(ASTContext &Context,
- unsigned Index,
+ /// Create the initialization entity for a default member initializer.
+ static InitializedEntity
+ InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
+ return InitializedEntity(Member, nullptr, false, true);
+ }
+
+ /// Create the initialization entity for an array element.
+ static InitializedEntity InitializeElement(ASTContext &Context,
+ unsigned Index,
const InitializedEntity &Parent) {
return InitializedEntity(Context, Index, Parent);
}
- /// \brief Create the initialization entity for a structured binding.
+ /// Create the initialization entity for a structured binding.
static InitializedEntity InitializeBinding(VarDecl *Binding) {
return InitializedEntity(Binding, EK_Binding);
}
- /// \brief Create the initialization entity for a lambda capture.
+ /// Create the initialization entity for a lambda capture.
static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID,
QualType FieldType,
SourceLocation Loc) {
return InitializedEntity(VarID, FieldType, Loc);
}
- /// \brief Create the entity for a compound literal initializer.
+ /// Create the entity for a compound literal initializer.
static InitializedEntity InitializeCompoundLiteralInit(TypeSourceInfo *TSI) {
InitializedEntity Result(EK_CompoundLiteralInit, SourceLocation(),
TSI->getType());
@@ -362,38 +401,37 @@ public:
return Result;
}
-
- /// \brief Determine the kind of initialization.
+ /// Determine the kind of initialization.
EntityKind getKind() const { return Kind; }
-
- /// \brief Retrieve the parent of the entity being initialized, when
+
+ /// Retrieve the parent of the entity being initialized, when
/// the initialization itself is occurring within the context of a
/// larger initialization.
const InitializedEntity *getParent() const { return Parent; }
- /// \brief Retrieve type being initialized.
+ /// Retrieve type being initialized.
QualType getType() const { return Type; }
-
- /// \brief Retrieve complete type-source information for the object being
+
+ /// Retrieve complete type-source information for the object being
/// constructed, if known.
TypeSourceInfo *getTypeSourceInfo() const {
if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit)
return TypeInfo;
-
+
return nullptr;
}
-
- /// \brief Retrieve the name of the entity being initialized.
+
+ /// Retrieve the name of the entity being initialized.
DeclarationName getName() const;
- /// \brief Retrieve the variable, parameter, or field being
+ /// Retrieve the variable, parameter, or field being
/// initialized.
ValueDecl *getDecl() const;
-
- /// \brief Retrieve the ObjectiveC method being initialized.
+
+ /// Retrieve the ObjectiveC method being initialized.
ObjCMethodDecl *getMethodDecl() const { return MethodDecl; }
- /// \brief Determine whether this initialization allows the named return
+ /// Determine whether this initialization allows the named return
/// value optimization, which also applies to thrown objects.
bool allowsNRVO() const;
@@ -401,77 +439,87 @@ public:
return (getKind() == EK_Parameter ||
getKind() == EK_Parameter_CF_Audited);
}
- /// \brief Determine whether this initialization consumes the
+
+ /// Determine whether this initialization consumes the
/// parameter.
bool isParameterConsumed() const {
assert(isParameterKind() && "Not a parameter");
return (Parameter & 1);
}
-
- /// \brief Retrieve the base specifier.
+
+ /// Retrieve the base specifier.
const CXXBaseSpecifier *getBaseSpecifier() const {
assert(getKind() == EK_Base && "Not a base specifier");
return reinterpret_cast<const CXXBaseSpecifier *>(Base & ~0x1);
}
- /// \brief Return whether the base is an inherited virtual base.
+ /// Return whether the base is an inherited virtual base.
bool isInheritedVirtualBase() const {
assert(getKind() == EK_Base && "Not a base specifier");
return Base & 0x1;
}
- /// \brief Determine whether this is an array new with an unknown bound.
+ /// Determine whether this is an array new with an unknown bound.
bool isVariableLengthArrayNew() const {
return getKind() == EK_New && dyn_cast_or_null<IncompleteArrayType>(
getType()->getAsArrayTypeUnsafe());
}
- /// \brief Is this the implicit initialization of a member of a class from
+ /// Is this the implicit initialization of a member of a class from
/// a defaulted constructor?
bool isImplicitMemberInitializer() const {
return getKind() == EK_Member && Variable.IsImplicitFieldInit;
}
- /// \brief Determine the location of the 'return' keyword when initializing
+ /// Is this the default member initializer of a member (specified inside
+ /// the class definition)?
+ bool isDefaultMemberInitializer() const {
+ return getKind() == EK_Member && Variable.IsDefaultMemberInit;
+ }
+
+ /// Determine the location of the 'return' keyword when initializing
/// the result of a function call.
SourceLocation getReturnLoc() const {
assert(getKind() == EK_Result && "No 'return' location!");
return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
}
- /// \brief Determine the location of the 'throw' keyword when initializing
+ /// Determine the location of the 'throw' keyword when initializing
/// an exception object.
SourceLocation getThrowLoc() const {
assert(getKind() == EK_Exception && "No 'throw' location!");
return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
}
- /// \brief If this is an array, vector, or complex number element, get the
+ /// If this is an array, vector, or complex number element, get the
/// element's index.
unsigned getElementIndex() const {
assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
getKind() == EK_ComplexElement);
return Index;
}
- /// \brief If this is already the initializer for an array or vector
+
+ /// If this is already the initializer for an array or vector
/// element, sets the element index.
void setElementIndex(unsigned Index) {
assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
getKind() == EK_ComplexElement);
this->Index = Index;
}
- /// \brief For a lambda capture, return the capture's name.
+
+ /// For a lambda capture, return the capture's name.
StringRef getCapturedVarName() const {
assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
return Capture.VarID->getName();
}
- /// \brief Determine the location of the capture when initializing
+
+ /// Determine the location of the capture when initializing
/// field from a captured variable in a lambda.
SourceLocation getCaptureLoc() const {
assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
return SourceLocation::getFromRawEncoding(Capture.Location);
}
-
+
void setParameterCFAudited() {
Kind = EK_Parameter_CF_Audited;
}
@@ -485,52 +533,71 @@ public:
private:
unsigned dumpImpl(raw_ostream &OS) const;
};
-
-/// \brief Describes the kind of initialization being performed, along with
+
+/// Describes the kind of initialization being performed, along with
/// location information for tokens related to the initialization (equal sign,
/// parentheses).
class InitializationKind {
public:
- /// \brief The kind of initialization being performed.
+ /// The kind of initialization being performed.
enum InitKind {
- IK_Direct, ///< Direct initialization
- IK_DirectList, ///< Direct list-initialization
- IK_Copy, ///< Copy initialization
- IK_Default, ///< Default initialization
- IK_Value ///< Value initialization
+ /// Direct initialization
+ IK_Direct,
+
+ /// Direct list-initialization
+ IK_DirectList,
+
+ /// Copy initialization
+ IK_Copy,
+
+ /// Default initialization
+ IK_Default,
+
+ /// Value initialization
+ IK_Value
};
-
+
private:
- /// \brief The context of the initialization.
+ /// The context of the initialization.
enum InitContext {
- IC_Normal, ///< Normal context
- IC_ExplicitConvs, ///< Normal context, but allows explicit conversion funcs
- IC_Implicit, ///< Implicit context (value initialization)
- IC_StaticCast, ///< Static cast context
- IC_CStyleCast, ///< C-style cast context
- IC_FunctionalCast ///< Functional cast context
+ /// Normal context
+ IC_Normal,
+
+ /// Normal context, but allows explicit conversion functionss
+ IC_ExplicitConvs,
+
+ /// Implicit context (value initialization)
+ IC_Implicit,
+
+ /// Static cast context
+ IC_StaticCast,
+
+ /// C-style cast context
+ IC_CStyleCast,
+
+ /// Functional cast context
+ IC_FunctionalCast
};
-
- /// \brief The kind of initialization being performed.
+
+ /// The kind of initialization being performed.
InitKind Kind : 8;
- /// \brief The context of the initialization.
+ /// The context of the initialization.
InitContext Context : 8;
-
- /// \brief The source locations involved in the initialization.
+
+ /// The source locations involved in the initialization.
SourceLocation Locations[3];
-
- InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1,
+
+ InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1,
SourceLocation Loc2, SourceLocation Loc3)
- : Kind(Kind), Context(Context)
- {
+ : Kind(Kind), Context(Context) {
Locations[0] = Loc1;
Locations[1] = Loc2;
Locations[2] = Loc3;
}
-
+
public:
- /// \brief Create a direct initialization.
+ /// Create a direct initialization.
static InitializationKind CreateDirect(SourceLocation InitLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
@@ -539,18 +606,25 @@ public:
}
static InitializationKind CreateDirectList(SourceLocation InitLoc) {
- return InitializationKind(IK_DirectList, IC_Normal,
- InitLoc, InitLoc, InitLoc);
+ return InitializationKind(IK_DirectList, IC_Normal, InitLoc, InitLoc,
+ InitLoc);
}
- /// \brief Create a direct initialization due to a cast that isn't a C-style
+ static InitializationKind CreateDirectList(SourceLocation InitLoc,
+ SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc) {
+ return InitializationKind(IK_DirectList, IC_Normal, InitLoc, LBraceLoc,
+ RBraceLoc);
+ }
+
+ /// Create a direct initialization due to a cast that isn't a C-style
/// or functional cast.
static InitializationKind CreateCast(SourceRange TypeRange) {
return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(),
TypeRange.getBegin(), TypeRange.getEnd());
}
-
- /// \brief Create a direct initialization for a C-style cast.
+
+ /// Create a direct initialization for a C-style cast.
static InitializationKind CreateCStyleCast(SourceLocation StartLoc,
SourceRange TypeRange,
bool InitList) {
@@ -561,7 +635,7 @@ public:
TypeRange.getEnd());
}
- /// \brief Create a direct initialization for a functional cast.
+ /// Create a direct initialization for a functional cast.
static InitializationKind CreateFunctionalCast(SourceRange TypeRange,
bool InitList) {
return InitializationKind(InitList ? IK_DirectList : IK_Direct,
@@ -569,21 +643,21 @@ public:
TypeRange.getBegin(), TypeRange.getEnd());
}
- /// \brief Create a copy initialization.
+ /// Create a copy initialization.
static InitializationKind CreateCopy(SourceLocation InitLoc,
SourceLocation EqualLoc,
bool AllowExplicitConvs = false) {
- return InitializationKind(IK_Copy,
+ return InitializationKind(IK_Copy,
AllowExplicitConvs? IC_ExplicitConvs : IC_Normal,
InitLoc, EqualLoc, EqualLoc);
}
-
- /// \brief Create a default initialization.
+
+ /// Create a default initialization.
static InitializationKind CreateDefault(SourceLocation InitLoc) {
return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc);
}
-
- /// \brief Create a value initialization.
+
+ /// Create a value initialization.
static InitializationKind CreateValue(SourceLocation InitLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc,
@@ -592,55 +666,56 @@ public:
InitLoc, LParenLoc, RParenLoc);
}
- /// \brief Create an initialization from an initializer (which, for direct
+ /// Create an initialization from an initializer (which, for direct
/// initialization from a parenthesized list, will be a ParenListExpr).
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit,
Expr *Init) {
if (!Init) return CreateDefault(Loc);
if (!DirectInit) return CreateCopy(Loc, Init->getLocStart());
- if (isa<InitListExpr>(Init)) return CreateDirectList(Loc);
+ if (isa<InitListExpr>(Init))
+ return CreateDirectList(Loc, Init->getLocStart(), Init->getLocEnd());
return CreateDirect(Loc, Init->getLocStart(), Init->getLocEnd());
}
-
- /// \brief Determine the initialization kind.
+
+ /// Determine the initialization kind.
InitKind getKind() const {
return Kind;
}
-
- /// \brief Determine whether this initialization is an explicit cast.
+
+ /// Determine whether this initialization is an explicit cast.
bool isExplicitCast() const {
return Context >= IC_StaticCast;
}
-
- /// \brief Determine whether this initialization is a C-style cast.
- bool isCStyleOrFunctionalCast() const {
- return Context >= IC_CStyleCast;
+
+ /// Determine whether this initialization is a C-style cast.
+ bool isCStyleOrFunctionalCast() const {
+ return Context >= IC_CStyleCast;
}
- /// \brief Determine whether this is a C-style cast.
+ /// Determine whether this is a C-style cast.
bool isCStyleCast() const {
return Context == IC_CStyleCast;
}
- /// \brief Determine whether this is a functional-style cast.
+ /// Determine whether this is a functional-style cast.
bool isFunctionalCast() const {
return Context == IC_FunctionalCast;
}
- /// \brief Determine whether this initialization is an implicit
+ /// Determine whether this initialization is an implicit
/// value-initialization, e.g., as occurs during aggregate
/// initialization.
bool isImplicitValueInit() const { return Context == IC_Implicit; }
- /// \brief Retrieve the location at which initialization is occurring.
+ /// Retrieve the location at which initialization is occurring.
SourceLocation getLocation() const { return Locations[0]; }
-
- /// \brief Retrieve the source range that covers the initialization.
- SourceRange getRange() const {
+
+ /// Retrieve the source range that covers the initialization.
+ SourceRange getRange() const {
return SourceRange(Locations[0], Locations[2]);
}
-
- /// \brief Retrieve the location of the equal sign for copy initialization
+
+ /// Retrieve the location of the equal sign for copy initialization
/// (if present).
SourceLocation getEqualLoc() const {
assert(Kind == IK_Copy && "Only copy initialization has an '='");
@@ -649,143 +724,188 @@ public:
bool isCopyInit() const { return Kind == IK_Copy; }
- /// \brief Retrieve whether this initialization allows the use of explicit
+ /// Retrieve whether this initialization allows the use of explicit
/// constructors.
bool AllowExplicit() const { return !isCopyInit(); }
- /// \brief Retrieve whether this initialization allows the use of explicit
+ /// Retrieve whether this initialization allows the use of explicit
/// conversion functions when binding a reference. If the reference is the
/// first parameter in a copy or move constructor, such conversions are
/// permitted even though we are performing copy-initialization.
bool allowExplicitConversionFunctionsInRefBinding() const {
return !isCopyInit() || Context == IC_ExplicitConvs;
}
-
- /// \brief Retrieve the source range containing the locations of the open
- /// and closing parentheses for value and direct initializations.
- SourceRange getParenRange() const {
- assert((Kind == IK_Direct || Kind == IK_Value) &&
- "Only direct- and value-initialization have parentheses");
+
+ /// Determine whether this initialization has a source range containing the
+ /// locations of open and closing parentheses or braces.
+ bool hasParenOrBraceRange() const {
+ return Kind == IK_Direct || Kind == IK_Value || Kind == IK_DirectList;
+ }
+
+ /// Retrieve the source range containing the locations of the open
+ /// and closing parentheses or braces for value, direct, and direct list
+ /// initializations.
+ SourceRange getParenOrBraceRange() const {
+ assert(hasParenOrBraceRange() && "Only direct, value, and direct-list "
+ "initialization have parentheses or "
+ "braces");
return SourceRange(Locations[1], Locations[2]);
}
};
-/// \brief Describes the sequence of initializations required to initialize
+/// Describes the sequence of initializations required to initialize
/// a given object or reference with a set of arguments.
class InitializationSequence {
public:
- /// \brief Describes the kind of initialization sequence computed.
+ /// Describes the kind of initialization sequence computed.
enum SequenceKind {
- /// \brief A failed initialization sequence. The failure kind tells what
+ /// A failed initialization sequence. The failure kind tells what
/// happened.
FailedSequence = 0,
- /// \brief A dependent initialization, which could not be
+ /// A dependent initialization, which could not be
/// type-checked due to the presence of dependent types or
/// dependently-typed expressions.
DependentSequence,
- /// \brief A normal sequence.
+ /// A normal sequence.
NormalSequence
};
-
- /// \brief Describes the kind of a particular step in an initialization
+
+ /// Describes the kind of a particular step in an initialization
/// sequence.
enum StepKind {
- /// \brief Resolve the address of an overloaded function to a specific
+ /// Resolve the address of an overloaded function to a specific
/// function declaration.
SK_ResolveAddressOfOverloadedFunction,
- /// \brief Perform a derived-to-base cast, producing an rvalue.
+
+ /// Perform a derived-to-base cast, producing an rvalue.
SK_CastDerivedToBaseRValue,
- /// \brief Perform a derived-to-base cast, producing an xvalue.
+
+ /// Perform a derived-to-base cast, producing an xvalue.
SK_CastDerivedToBaseXValue,
- /// \brief Perform a derived-to-base cast, producing an lvalue.
+
+ /// Perform a derived-to-base cast, producing an lvalue.
SK_CastDerivedToBaseLValue,
- /// \brief Reference binding to an lvalue.
+
+ /// Reference binding to an lvalue.
SK_BindReference,
- /// \brief Reference binding to a temporary.
+
+ /// Reference binding to a temporary.
SK_BindReferenceToTemporary,
- /// \brief An optional copy of a temporary object to another
+
+ /// An optional copy of a temporary object to another
/// temporary object, which is permitted (but not required) by
/// C++98/03 but not C++0x.
SK_ExtraneousCopyToTemporary,
- /// \brief Direct-initialization from a reference-related object in the
+
+ /// Direct-initialization from a reference-related object in the
/// final stage of class copy-initialization.
SK_FinalCopy,
- /// \brief Perform a user-defined conversion, either via a conversion
+
+ /// Perform a user-defined conversion, either via a conversion
/// function or via a constructor.
SK_UserConversion,
- /// \brief Perform a qualification conversion, producing an rvalue.
+
+ /// Perform a qualification conversion, producing an rvalue.
SK_QualificationConversionRValue,
- /// \brief Perform a qualification conversion, producing an xvalue.
+
+ /// Perform a qualification conversion, producing an xvalue.
SK_QualificationConversionXValue,
- /// \brief Perform a qualification conversion, producing an lvalue.
+
+ /// Perform a qualification conversion, producing an lvalue.
SK_QualificationConversionLValue,
- /// \brief Perform a conversion adding _Atomic to a type.
+
+ /// Perform a conversion adding _Atomic to a type.
SK_AtomicConversion,
- /// \brief Perform a load from a glvalue, producing an rvalue.
+
+ /// Perform a load from a glvalue, producing an rvalue.
SK_LValueToRValue,
- /// \brief Perform an implicit conversion sequence.
+
+ /// Perform an implicit conversion sequence.
SK_ConversionSequence,
- /// \brief Perform an implicit conversion sequence without narrowing.
+
+ /// Perform an implicit conversion sequence without narrowing.
SK_ConversionSequenceNoNarrowing,
- /// \brief Perform list-initialization without a constructor.
+
+ /// Perform list-initialization without a constructor.
SK_ListInitialization,
- /// \brief Unwrap the single-element initializer list for a reference.
+
+ /// Unwrap the single-element initializer list for a reference.
SK_UnwrapInitList,
- /// \brief Rewrap the single-element initializer list for a reference.
+
+ /// Rewrap the single-element initializer list for a reference.
SK_RewrapInitList,
- /// \brief Perform initialization via a constructor.
+
+ /// Perform initialization via a constructor.
SK_ConstructorInitialization,
- /// \brief Perform initialization via a constructor, taking arguments from
+
+ /// Perform initialization via a constructor, taking arguments from
/// a single InitListExpr.
SK_ConstructorInitializationFromList,
- /// \brief Zero-initialize the object
+
+ /// Zero-initialize the object
SK_ZeroInitialization,
- /// \brief C assignment
+
+ /// C assignment
SK_CAssignment,
- /// \brief Initialization by string
+
+ /// Initialization by string
SK_StringInit,
- /// \brief An initialization that "converts" an Objective-C object
+
+ /// An initialization that "converts" an Objective-C object
/// (not a point to an object) to another Objective-C object type.
SK_ObjCObjectConversion,
- /// \brief Array indexing for initialization by elementwise copy.
+
+ /// Array indexing for initialization by elementwise copy.
SK_ArrayLoopIndex,
- /// \brief Array initialization by elementwise copy.
+
+ /// Array initialization by elementwise copy.
SK_ArrayLoopInit,
- /// \brief Array initialization (from an array rvalue).
+
+ /// Array initialization (from an array rvalue).
SK_ArrayInit,
- /// \brief Array initialization (from an array rvalue) as a GNU extension.
+
+ /// Array initialization (from an array rvalue) as a GNU extension.
SK_GNUArrayInit,
- /// \brief Array initialization from a parenthesized initializer list.
+
+ /// Array initialization from a parenthesized initializer list.
/// This is a GNU C++ extension.
SK_ParenthesizedArrayInit,
- /// \brief Pass an object by indirect copy-and-restore.
+
+ /// Pass an object by indirect copy-and-restore.
SK_PassByIndirectCopyRestore,
- /// \brief Pass an object by indirect restore.
+
+ /// Pass an object by indirect restore.
SK_PassByIndirectRestore,
- /// \brief Produce an Objective-C object pointer.
+
+ /// Produce an Objective-C object pointer.
SK_ProduceObjCObject,
- /// \brief Construct a std::initializer_list from an initializer list.
+
+ /// Construct a std::initializer_list from an initializer list.
SK_StdInitializerList,
- /// \brief Perform initialization via a constructor taking a single
+
+ /// Perform initialization via a constructor taking a single
/// std::initializer_list argument.
SK_StdInitializerListConstructorCall,
- /// \brief Initialize an OpenCL sampler from an integer.
+
+ /// Initialize an OpenCL sampler from an integer.
SK_OCLSamplerInit,
- /// \brief Initialize queue_t from 0.
+
+ /// Initialize queue_t from 0.
SK_OCLZeroQueue,
- /// \brief Passing zero to a function where OpenCL event_t is expected.
+
+ /// Passing zero to a function where OpenCL event_t is expected.
SK_OCLZeroEvent
};
-
- /// \brief A single step in the initialization sequence.
+
+ /// A single step in the initialization sequence.
class Step {
public:
- /// \brief The kind of conversion or initialization step we are taking.
+ /// The kind of conversion or initialization step we are taking.
StepKind Kind;
-
- // \brief The type that results from this initialization.
+
+ // The type that results from this initialization.
QualType Type;
struct F {
@@ -795,8 +915,8 @@ public:
};
union {
- /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
- /// SK_UserConversion, the function that the expression should be
+ /// When Kind == SK_ResolvedOverloadedFunction or Kind ==
+ /// SK_UserConversion, the function that the expression should be
/// resolved to or the conversion function to call, respectively.
/// When Kind == SK_ConstructorInitialization or SK_ListConstruction,
/// the constructor to be called.
@@ -807,127 +927,167 @@ public:
/// For construct decls, the naming class is the target type.
struct F Function;
- /// \brief When Kind = SK_ConversionSequence, the implicit conversion
+ /// When Kind = SK_ConversionSequence, the implicit conversion
/// sequence.
ImplicitConversionSequence *ICS;
- /// \brief When Kind = SK_RewrapInitList, the syntactic form of the
+ /// When Kind = SK_RewrapInitList, the syntactic form of the
/// wrapping list.
InitListExpr *WrappingSyntacticList;
};
void Destroy();
};
-
+
private:
- /// \brief The kind of initialization sequence computed.
+ /// The kind of initialization sequence computed.
enum SequenceKind SequenceKind;
-
- /// \brief Steps taken by this initialization.
+
+ /// Steps taken by this initialization.
SmallVector<Step, 4> Steps;
-
+
public:
- /// \brief Describes why initialization failed.
+ /// Describes why initialization failed.
enum FailureKind {
- /// \brief Too many initializers provided for a reference.
+ /// Too many initializers provided for a reference.
FK_TooManyInitsForReference,
- /// \brief Reference initialized from a parenthesized initializer list.
+
+ /// Reference initialized from a parenthesized initializer list.
FK_ParenthesizedListInitForReference,
- /// \brief Array must be initialized with an initializer list.
+
+ /// Array must be initialized with an initializer list.
FK_ArrayNeedsInitList,
- /// \brief Array must be initialized with an initializer list or a
+
+ /// Array must be initialized with an initializer list or a
/// string literal.
FK_ArrayNeedsInitListOrStringLiteral,
- /// \brief Array must be initialized with an initializer list or a
+
+ /// Array must be initialized with an initializer list or a
/// wide string literal.
FK_ArrayNeedsInitListOrWideStringLiteral,
- /// \brief Initializing a wide char array with narrow string literal.
+
+ /// Initializing a wide char array with narrow string literal.
FK_NarrowStringIntoWideCharArray,
- /// \brief Initializing char array with wide string literal.
+
+ /// Initializing char array with wide string literal.
FK_WideStringIntoCharArray,
- /// \brief Initializing wide char array with incompatible wide string
+
+ /// Initializing wide char array with incompatible wide string
/// literal.
FK_IncompatWideStringIntoWideChar,
- /// \brief Array type mismatch.
+
+ /// Initializing char8_t array with plain string literal.
+ FK_PlainStringIntoUTF8Char,
+
+ /// Initializing char array with UTF-8 string literal.
+ FK_UTF8StringIntoPlainChar,
+
+ /// Array type mismatch.
FK_ArrayTypeMismatch,
- /// \brief Non-constant array initializer
+
+ /// Non-constant array initializer
FK_NonConstantArrayInit,
- /// \brief Cannot resolve the address of an overloaded function.
+
+ /// Cannot resolve the address of an overloaded function.
FK_AddressOfOverloadFailed,
- /// \brief Overloading due to reference initialization failed.
+
+ /// Overloading due to reference initialization failed.
FK_ReferenceInitOverloadFailed,
- /// \brief Non-const lvalue reference binding to a temporary.
+
+ /// Non-const lvalue reference binding to a temporary.
FK_NonConstLValueReferenceBindingToTemporary,
- /// \brief Non-const lvalue reference binding to a bit-field.
+
+ /// Non-const lvalue reference binding to a bit-field.
FK_NonConstLValueReferenceBindingToBitfield,
- /// \brief Non-const lvalue reference binding to a vector element.
+
+ /// Non-const lvalue reference binding to a vector element.
FK_NonConstLValueReferenceBindingToVectorElement,
- /// \brief Non-const lvalue reference binding to an lvalue of unrelated
+
+ /// Non-const lvalue reference binding to an lvalue of unrelated
/// type.
FK_NonConstLValueReferenceBindingToUnrelated,
- /// \brief Rvalue reference binding to an lvalue.
+
+ /// Rvalue reference binding to an lvalue.
FK_RValueReferenceBindingToLValue,
- /// \brief Reference binding drops qualifiers.
+
+ /// Reference binding drops qualifiers.
FK_ReferenceInitDropsQualifiers,
- /// \brief Reference binding failed.
+
+ /// Reference binding failed.
FK_ReferenceInitFailed,
- /// \brief Implicit conversion failed.
+
+ /// Implicit conversion failed.
FK_ConversionFailed,
- /// \brief Implicit conversion failed.
+
+ /// Implicit conversion failed.
FK_ConversionFromPropertyFailed,
- /// \brief Too many initializers for scalar
+
+ /// Too many initializers for scalar
FK_TooManyInitsForScalar,
- /// \brief Scalar initialized from a parenthesized initializer list.
+
+ /// Scalar initialized from a parenthesized initializer list.
FK_ParenthesizedListInitForScalar,
- /// \brief Reference initialization from an initializer list
+
+ /// Reference initialization from an initializer list
FK_ReferenceBindingToInitList,
- /// \brief Initialization of some unused destination type with an
+
+ /// Initialization of some unused destination type with an
/// initializer list.
FK_InitListBadDestinationType,
- /// \brief Overloading for a user-defined conversion failed.
+
+ /// Overloading for a user-defined conversion failed.
FK_UserConversionOverloadFailed,
- /// \brief Overloading for initialization by constructor failed.
+
+ /// Overloading for initialization by constructor failed.
FK_ConstructorOverloadFailed,
- /// \brief Overloading for list-initialization by constructor failed.
+
+ /// Overloading for list-initialization by constructor failed.
FK_ListConstructorOverloadFailed,
- /// \brief Default-initialization of a 'const' object.
+
+ /// Default-initialization of a 'const' object.
FK_DefaultInitOfConst,
- /// \brief Initialization of an incomplete type.
+
+ /// Initialization of an incomplete type.
FK_Incomplete,
- /// \brief Variable-length array must not have an initializer.
+
+ /// Variable-length array must not have an initializer.
FK_VariableLengthArrayHasInitializer,
- /// \brief List initialization failed at some point.
+
+ /// List initialization failed at some point.
FK_ListInitializationFailed,
- /// \brief Initializer has a placeholder type which cannot be
+
+ /// Initializer has a placeholder type which cannot be
/// resolved by initialization.
FK_PlaceholderType,
- /// \brief Trying to take the address of a function that doesn't support
+
+ /// Trying to take the address of a function that doesn't support
/// having its address taken.
FK_AddressOfUnaddressableFunction,
- /// \brief List-copy-initialization chose an explicit constructor.
+
+ /// List-copy-initialization chose an explicit constructor.
FK_ExplicitConstructor,
};
-
+
private:
- /// \brief The reason why initialization failed.
+ /// The reason why initialization failed.
FailureKind Failure;
- /// \brief The failed result of overload resolution.
+ /// The failed result of overload resolution.
OverloadingResult FailedOverloadResult;
-
- /// \brief The candidate set created when initialization failed.
+
+ /// The candidate set created when initialization failed.
OverloadCandidateSet FailedCandidateSet;
- /// \brief The incomplete type that caused a failure.
+ /// The incomplete type that caused a failure.
QualType FailedIncompleteType;
- /// \brief The fixit that needs to be applied to make this initialization
+ /// The fixit that needs to be applied to make this initialization
/// succeed.
std::string ZeroInitializationFixit;
SourceLocation ZeroInitializationFixitLoc;
public:
- /// \brief Call for initializations are invalid but that would be valid
+ /// Call for initializations are invalid but that would be valid
/// zero initialzations if Fixit was applied.
void SetZeroInitializationFixit(const std::string& Fixit, SourceLocation L) {
ZeroInitializationFixit = Fixit;
@@ -935,17 +1095,16 @@ public:
}
private:
-
- /// \brief Prints a follow-up note that highlights the location of
+ /// Prints a follow-up note that highlights the location of
/// the initialized entity, if it's remote.
void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity);
public:
- /// \brief Try to perform initialization of the given entity, creating a
+ /// Try to perform initialization of the given entity, creating a
/// record of the steps required to perform the initialization.
///
/// The generated initialization sequence will either contain enough
- /// information to diagnose
+ /// information to diagnose
///
/// \param S the semantic analysis object.
///
@@ -960,7 +1119,7 @@ public:
/// narrowing conversions in C++11 onwards.
/// \param TreatUnavailableAsInvalid true if we want to treat unavailable
/// as invalid.
- InitializationSequence(Sema &S,
+ InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args,
@@ -971,8 +1130,8 @@ public:
bool TopLevelOfInitList, bool TreatUnavailableAsInvalid);
~InitializationSequence();
-
- /// \brief Perform the actual initialization of the given entity based on
+
+ /// Perform the actual initialization of the given entity based on
/// the computed initialization sequence.
///
/// \param S the semantic analysis object.
@@ -998,47 +1157,49 @@ public:
const InitializationKind &Kind,
MultiExprArg Args,
QualType *ResultType = nullptr);
-
- /// \brief Diagnose an potentially-invalid initialization sequence.
+
+ /// Diagnose an potentially-invalid initialization sequence.
///
- /// \returns true if the initialization sequence was ill-formed,
+ /// \returns true if the initialization sequence was ill-formed,
/// false otherwise.
- bool Diagnose(Sema &S,
+ bool Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
ArrayRef<Expr *> Args);
-
- /// \brief Determine the kind of initialization sequence computed.
+
+ /// Determine the kind of initialization sequence computed.
enum SequenceKind getKind() const { return SequenceKind; }
-
- /// \brief Set the kind of sequence computed.
+
+ /// Set the kind of sequence computed.
void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
-
- /// \brief Determine whether the initialization sequence is valid.
+
+ /// Determine whether the initialization sequence is valid.
explicit operator bool() const { return !Failed(); }
- /// \brief Determine whether the initialization sequence is invalid.
+ /// Determine whether the initialization sequence is invalid.
bool Failed() const { return SequenceKind == FailedSequence; }
- typedef SmallVectorImpl<Step>::const_iterator step_iterator;
+ using step_iterator = SmallVectorImpl<Step>::const_iterator;
+
step_iterator step_begin() const { return Steps.begin(); }
step_iterator step_end() const { return Steps.end(); }
- typedef llvm::iterator_range<step_iterator> step_range;
+ using step_range = llvm::iterator_range<step_iterator>;
+
step_range steps() const { return {step_begin(), step_end()}; }
- /// \brief Determine whether this initialization is a direct reference
+ /// Determine whether this initialization is a direct reference
/// binding (C++ [dcl.init.ref]).
bool isDirectReferenceBinding() const;
-
- /// \brief Determine whether this initialization failed due to an ambiguity.
+
+ /// Determine whether this initialization failed due to an ambiguity.
bool isAmbiguous() const;
-
- /// \brief Determine whether this initialization is direct call to a
+
+ /// Determine whether this initialization is direct call to a
/// constructor.
bool isConstructorInitialization() const;
- /// \brief Returns whether the last step in this initialization sequence is a
+ /// Returns whether the last step in this initialization sequence is a
/// narrowing conversion, defined by C++0x [dcl.init.list]p7.
///
/// If this function returns true, *isInitializerConstant will be set to
@@ -1049,7 +1210,7 @@ public:
bool *isInitializerConstant,
APValue *ConstantValue) const;
- /// \brief Add a new step in the initialization that resolves the address
+ /// Add a new step in the initialization that resolves the address
/// of an overloaded function to a specific function declaration.
///
/// \param Function the function to which the overloaded function reference
@@ -1058,7 +1219,7 @@ public:
DeclAccessPair Found,
bool HadMultipleCandidates);
- /// \brief Add a new step in the initialization that performs a derived-to-
+ /// Add a new step in the initialization that performs a derived-to-
/// base cast.
///
/// \param BaseType the base type to which we will be casting.
@@ -1067,15 +1228,15 @@ public:
/// rvalue, an xvalue, or an lvalue.
void AddDerivedToBaseCastStep(QualType BaseType,
ExprValueKind Category);
-
- /// \brief Add a new step binding a reference to an object.
+
+ /// Add a new step binding a reference to an object.
///
/// \param BindingTemporary True if we are binding a reference to a temporary
/// object (thereby extending its lifetime); false if we are binding to an
/// lvalue or an lvalue treated as an rvalue.
void AddReferenceBindingStep(QualType T, bool BindingTemporary);
- /// \brief Add a new step that makes an extraneous copy of the input
+ /// Add a new step that makes an extraneous copy of the input
/// to a temporary of the same class type.
///
/// This extraneous copy only occurs during reference binding in
@@ -1087,40 +1248,40 @@ public:
/// \param T The type of the temporary being created.
void AddExtraneousCopyToTemporary(QualType T);
- /// \brief Add a new step that makes a copy of the input to an object of
+ /// Add a new step that makes a copy of the input to an object of
/// the given type, as the final step in class copy-initialization.
void AddFinalCopy(QualType T);
- /// \brief Add a new step invoking a conversion function, which is either
+ /// Add a new step invoking a conversion function, which is either
/// a constructor or a conversion function.
void AddUserConversionStep(FunctionDecl *Function,
DeclAccessPair FoundDecl,
QualType T,
bool HadMultipleCandidates);
- /// \brief Add a new step that performs a qualification conversion to the
+ /// Add a new step that performs a qualification conversion to the
/// given type.
void AddQualificationConversionStep(QualType Ty,
ExprValueKind Category);
- /// \brief Add a new step that performs conversion from non-atomic to atomic
+ /// Add a new step that performs conversion from non-atomic to atomic
/// type.
void AddAtomicConversionStep(QualType Ty);
- /// \brief Add a new step that performs a load of the given type.
+ /// Add a new step that performs a load of the given type.
///
/// Although the term "LValueToRValue" is conventional, this applies to both
/// lvalues and xvalues.
void AddLValueToRValueStep(QualType Ty);
- /// \brief Add a new step that applies an implicit conversion sequence.
+ /// Add a new step that applies an implicit conversion sequence.
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
QualType T, bool TopLevelOfInitList = false);
- /// \brief Add a list-initialization step.
+ /// Add a list-initialization step.
void AddListInitializationStep(QualType T);
- /// \brief Add a constructor-initialization step.
+ /// Add a constructor-initialization step.
///
/// \param FromInitList The constructor call is syntactically an initializer
/// list.
@@ -1131,104 +1292,104 @@ public:
bool HadMultipleCandidates,
bool FromInitList, bool AsInitList);
- /// \brief Add a zero-initialization step.
+ /// Add a zero-initialization step.
void AddZeroInitializationStep(QualType T);
- /// \brief Add a C assignment step.
+ /// Add a C assignment step.
//
// FIXME: It isn't clear whether this should ever be needed;
// ideally, we would handle everything needed in C in the common
// path. However, that isn't the case yet.
void AddCAssignmentStep(QualType T);
- /// \brief Add a string init step.
+ /// Add a string init step.
void AddStringInitStep(QualType T);
- /// \brief Add an Objective-C object conversion step, which is
+ /// Add an Objective-C object conversion step, which is
/// always a no-op.
void AddObjCObjectConversionStep(QualType T);
- /// \brief Add an array initialization loop step.
+ /// Add an array initialization loop step.
void AddArrayInitLoopStep(QualType T, QualType EltTy);
- /// \brief Add an array initialization step.
+ /// Add an array initialization step.
void AddArrayInitStep(QualType T, bool IsGNUExtension);
- /// \brief Add a parenthesized array initialization step.
+ /// Add a parenthesized array initialization step.
void AddParenthesizedArrayInitStep(QualType T);
- /// \brief Add a step to pass an object by indirect copy-restore.
+ /// Add a step to pass an object by indirect copy-restore.
void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy);
- /// \brief Add a step to "produce" an Objective-C object (by
+ /// Add a step to "produce" an Objective-C object (by
/// retaining it).
void AddProduceObjCObjectStep(QualType T);
- /// \brief Add a step to construct a std::initializer_list object from an
+ /// Add a step to construct a std::initializer_list object from an
/// initializer list.
void AddStdInitializerListConstructionStep(QualType T);
- /// \brief Add a step to initialize an OpenCL sampler from an integer
+ /// Add a step to initialize an OpenCL sampler from an integer
/// constant.
void AddOCLSamplerInitStep(QualType T);
- /// \brief Add a step to initialize an OpenCL event_t from a NULL
+ /// Add a step to initialize an OpenCL event_t from a NULL
/// constant.
void AddOCLZeroEventStep(QualType T);
- /// \brief Add a step to initialize an OpenCL queue_t from 0.
+ /// Add a step to initialize an OpenCL queue_t from 0.
void AddOCLZeroQueueStep(QualType T);
- /// \brief Add steps to unwrap a initializer list for a reference around a
+ /// Add steps to unwrap a initializer list for a reference around a
/// single element and rewrap it at the end.
void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
- /// \brief Note that this initialization sequence failed.
+ /// Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;
this->Failure = Failure;
assert((Failure != FK_Incomplete || !FailedIncompleteType.isNull()) &&
"Incomplete type failure requires a type!");
}
-
- /// \brief Note that this initialization sequence failed due to failed
+
+ /// Note that this initialization sequence failed due to failed
/// overload resolution.
void SetOverloadFailure(FailureKind Failure, OverloadingResult Result);
-
- /// \brief Retrieve a reference to the candidate set when overload
+
+ /// Retrieve a reference to the candidate set when overload
/// resolution fails.
OverloadCandidateSet &getFailedCandidateSet() {
return FailedCandidateSet;
}
- /// \brief Get the overloading result, for when the initialization
+ /// Get the overloading result, for when the initialization
/// sequence failed due to a bad overload.
OverloadingResult getFailedOverloadResult() const {
return FailedOverloadResult;
}
- /// \brief Note that this initialization sequence failed due to an
+ /// Note that this initialization sequence failed due to an
/// incomplete type.
void setIncompleteTypeFailure(QualType IncompleteType) {
FailedIncompleteType = IncompleteType;
SetFailed(FK_Incomplete);
}
- /// \brief Determine why initialization failed.
+ /// Determine why initialization failed.
FailureKind getFailureKind() const {
assert(Failed() && "Not an initialization failure!");
return Failure;
}
- /// \brief Dump a representation of this initialization sequence to
+ /// Dump a representation of this initialization sequence to
/// the given stream, for debugging purposes.
void dump(raw_ostream &OS) const;
-
- /// \brief Dump a representation of this initialization sequence to
+
+ /// Dump a representation of this initialization sequence to
/// standard error, for debugging purposes.
void dump() const;
};
-
-} // end namespace clang
+
+} // namespace clang
#endif // LLVM_CLANG_SEMA_INITIALIZATION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
index 546df8842a35..e28b847f4ae5 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
@@ -1,4 +1,4 @@
-//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===//
+//===- Lookup.h - Classes for name lookup -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,14 +15,29 @@
#ifndef LLVM_CLANG_SEMA_LOOKUP_H
#define LLVM_CLANG_SEMA_LOOKUP_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/Sema.h"
-
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <utility>
namespace clang {
-/// @brief Represents the results of name lookup.
+class CXXBasePaths;
+
+/// Represents the results of name lookup.
///
/// An instance of the LookupResult class captures the results of a
/// single name lookup, which can return no result (nothing found),
@@ -32,28 +47,28 @@ namespace clang {
class LookupResult {
public:
enum LookupResultKind {
- /// @brief No entity found met the criteria.
+ /// No entity found met the criteria.
NotFound = 0,
- /// @brief No entity found met the criteria within the current
- /// instantiation,, but there were dependent base classes of the
+ /// No entity found met the criteria within the current
+ /// instantiation,, but there were dependent base classes of the
/// current instantiation that could not be searched.
NotFoundInCurrentInstantiation,
-
- /// @brief Name lookup found a single declaration that met the
+
+ /// Name lookup found a single declaration that met the
/// criteria. getFoundDecl() will return this declaration.
Found,
- /// @brief Name lookup found a set of overloaded functions that
+ /// Name lookup found a set of overloaded functions that
/// met the criteria.
FoundOverloaded,
- /// @brief Name lookup found an unresolvable value declaration
+ /// Name lookup found an unresolvable value declaration
/// and cannot yet complete. This only happens in C++ dependent
/// contexts with dependent using declarations.
FoundUnresolvedValue,
- /// @brief Name lookup results in an ambiguity; use
+ /// Name lookup results in an ambiguity; use
/// getAmbiguityKind to figure out what kind of ambiguity
/// we have.
Ambiguous
@@ -126,25 +141,15 @@ public:
Temporary
};
- typedef UnresolvedSetImpl::iterator iterator;
+ using iterator = UnresolvedSetImpl::iterator;
LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo,
Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
- : ResultKind(NotFound),
- Paths(nullptr),
- NamingClass(nullptr),
- SemaPtr(&SemaRef),
- NameInfo(NameInfo),
- LookupKind(LookupKind),
- IDNS(0),
- Redecl(Redecl != Sema::NotForRedeclaration),
- ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
- HideTags(true),
- Diagnose(Redecl == Sema::NotForRedeclaration),
- AllowHidden(false),
- Shadowed(false)
- {
+ : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
+ Diagnose(Redecl == Sema::NotForRedeclaration) {
configure();
}
@@ -154,20 +159,10 @@ public:
LookupResult(Sema &SemaRef, DeclarationName Name,
SourceLocation NameLoc, Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
- : ResultKind(NotFound),
- Paths(nullptr),
- NamingClass(nullptr),
- SemaPtr(&SemaRef),
- NameInfo(Name, NameLoc),
- LookupKind(LookupKind),
- IDNS(0),
- Redecl(Redecl != Sema::NotForRedeclaration),
- ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
- HideTags(true),
- Diagnose(Redecl == Sema::NotForRedeclaration),
- AllowHidden(false),
- Shadowed(false)
- {
+ : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
+ Diagnose(Redecl == Sema::NotForRedeclaration) {
configure();
}
@@ -175,20 +170,10 @@ public:
/// using the information from another result. Diagnostics are always
/// disabled.
LookupResult(TemporaryToken _, const LookupResult &Other)
- : ResultKind(NotFound),
- Paths(nullptr),
- NamingClass(nullptr),
- SemaPtr(Other.SemaPtr),
- NameInfo(Other.NameInfo),
- LookupKind(Other.LookupKind),
- IDNS(Other.IDNS),
- Redecl(Other.Redecl),
- ExternalRedecl(Other.ExternalRedecl),
- HideTags(Other.HideTags),
- Diagnose(false),
- AllowHidden(Other.AllowHidden),
- Shadowed(false)
- {}
+ : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo),
+ LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl),
+ ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags),
+ AllowHidden(Other.AllowHidden) {}
// FIXME: Remove these deleted methods once the default build includes
// -Wdeprecated.
@@ -213,6 +198,7 @@ public:
Other.Paths = nullptr;
Other.Diagnose = false;
}
+
LookupResult &operator=(LookupResult &&Other) {
ResultKind = std::move(Other.ResultKind);
Ambiguity = std::move(Other.Ambiguity);
@@ -246,7 +232,7 @@ public:
return NameInfo;
}
- /// \brief Sets the name info to look up.
+ /// Sets the name info to look up.
void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
this->NameInfo = NameInfo;
}
@@ -256,7 +242,7 @@ public:
return NameInfo.getName();
}
- /// \brief Sets the name to look up.
+ /// Sets the name to look up.
void setLookupName(DeclarationName Name) {
NameInfo.setName(Name);
}
@@ -282,13 +268,13 @@ public:
Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration;
}
- /// \brief Specify whether hidden declarations are visible, e.g.,
+ /// Specify whether hidden declarations are visible, e.g.,
/// for recovery reasons.
void setAllowHidden(bool AH) {
AllowHidden = AH;
}
- /// \brief Determine whether this lookup is permitted to see hidden
+ /// Determine whether this lookup is permitted to see hidden
/// declarations, such as those in modules that have not yet been imported.
bool isHiddenDeclarationVisible(NamedDecl *ND) const {
return AllowHidden ||
@@ -338,16 +324,16 @@ public:
iterator begin() const { return iterator(Decls.begin()); }
iterator end() const { return iterator(Decls.end()); }
- /// \brief Return true if no decls were found
+ /// Return true if no decls were found
bool empty() const { return Decls.empty(); }
- /// \brief Return the base paths structure that's associated with
+ /// Return the base paths structure that's associated with
/// these results, or null if none is.
CXXBasePaths *getBasePaths() const {
return Paths;
}
- /// \brief Determine whether the given declaration is visible to the
+ /// Determine whether the given declaration is visible to the
/// program.
static bool isVisible(Sema &SemaRef, NamedDecl *D) {
// If this declaration is not hidden, it's visible.
@@ -359,7 +345,7 @@ public:
return isVisibleSlow(SemaRef, D);
}
- /// \brief Retrieve the accepted (re)declaration of the given declaration,
+ /// Retrieve the accepted (re)declaration of the given declaration,
/// if there is one.
NamedDecl *getAcceptableDecl(NamedDecl *D) const {
if (!D->isInIdentifierNamespace(IDNS))
@@ -376,18 +362,18 @@ private:
NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
public:
- /// \brief Returns the identifier namespace mask for this lookup.
+ /// Returns the identifier namespace mask for this lookup.
unsigned getIdentifierNamespace() const {
return IDNS;
}
- /// \brief Returns whether these results arose from performing a
+ /// Returns whether these results arose from performing a
/// lookup into a class.
bool isClassLookup() const {
return NamingClass != nullptr;
}
- /// \brief Returns the 'naming class' for this lookup, i.e. the
+ /// Returns the 'naming class' for this lookup, i.e. the
/// class which was looked into to find these results.
///
/// C++0x [class.access.base]p5:
@@ -407,72 +393,72 @@ public:
return NamingClass;
}
- /// \brief Sets the 'naming class' for this lookup.
+ /// Sets the 'naming class' for this lookup.
void setNamingClass(CXXRecordDecl *Record) {
NamingClass = Record;
}
- /// \brief Returns the base object type associated with this lookup;
+ /// Returns the base object type associated with this lookup;
/// important for [class.protected]. Most lookups do not have an
/// associated base object.
QualType getBaseObjectType() const {
return BaseObjectType;
}
- /// \brief Sets the base object type for this lookup.
+ /// Sets the base object type for this lookup.
void setBaseObjectType(QualType T) {
BaseObjectType = T;
}
- /// \brief Add a declaration to these results with its natural access.
+ /// Add a declaration to these results with its natural access.
/// Does not test the acceptance criteria.
void addDecl(NamedDecl *D) {
addDecl(D, D->getAccess());
}
- /// \brief Add a declaration to these results with the given access.
+ /// Add a declaration to these results with the given access.
/// Does not test the acceptance criteria.
void addDecl(NamedDecl *D, AccessSpecifier AS) {
Decls.addDecl(D, AS);
ResultKind = Found;
}
- /// \brief Add all the declarations from another set of lookup
+ /// Add all the declarations from another set of lookup
/// results.
void addAllDecls(const LookupResult &Other) {
Decls.append(Other.Decls.begin(), Other.Decls.end());
ResultKind = Found;
}
- /// \brief Determine whether no result was found because we could not
+ /// Determine whether no result was found because we could not
/// search into dependent base classes of the current instantiation.
bool wasNotFoundInCurrentInstantiation() const {
return ResultKind == NotFoundInCurrentInstantiation;
}
-
- /// \brief Note that while no result was found in the current instantiation,
+
+ /// Note that while no result was found in the current instantiation,
/// there were dependent base classes that could not be searched.
void setNotFoundInCurrentInstantiation() {
assert(ResultKind == NotFound && Decls.empty());
ResultKind = NotFoundInCurrentInstantiation;
}
- /// \brief Determine whether the lookup result was shadowed by some other
+ /// Determine whether the lookup result was shadowed by some other
/// declaration that lookup ignored.
bool isShadowed() const { return Shadowed; }
- /// \brief Note that we found and ignored a declaration while performing
+ /// Note that we found and ignored a declaration while performing
/// lookup.
void setShadowed() { Shadowed = true; }
- /// \brief Resolves the result kind of the lookup, possibly hiding
+ /// Resolves the result kind of the lookup, possibly hiding
/// decls.
///
/// This should be called in any environment where lookup might
/// generate multiple lookup results.
void resolveKind();
- /// \brief Re-resolves the result kind of the lookup after a set of
+ /// Re-resolves the result kind of the lookup after a set of
/// removals has been performed.
void resolveKindAfterFilter() {
if (Decls.empty()) {
@@ -512,7 +498,7 @@ public:
return dyn_cast<DeclClass>(getFoundDecl());
}
- /// \brief Fetch the unique decl found by this lookup. Asserts
+ /// Fetch the unique decl found by this lookup. Asserts
/// that one was found.
///
/// This is intended for users who have examined the result kind
@@ -529,31 +515,31 @@ public:
return *begin();
}
- /// \brief Asks if the result is a single tag decl.
+ /// Asks if the result is a single tag decl.
bool isSingleTagDecl() const {
return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
}
- /// \brief Make these results show that the name was found in
+ /// Make these results show that the name was found in
/// base classes of different types.
///
/// The given paths object is copied and invalidated.
void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
- /// \brief Make these results show that the name was found in
+ /// Make these results show that the name was found in
/// distinct base classes of the same type.
///
/// The given paths object is copied and invalidated.
void setAmbiguousBaseSubobjects(CXXBasePaths &P);
- /// \brief Make these results show that the name was found in
+ /// Make these results show that the name was found in
/// different contexts and a tag decl was hidden by an ordinary
/// decl in a different context.
void setAmbiguousQualifiedTagHiding() {
setAmbiguous(AmbiguousTagHiding);
}
- /// \brief Clears out any current state.
+ /// Clears out any current state.
void clear() {
ResultKind = NotFound;
Decls.clear();
@@ -563,7 +549,7 @@ public:
Shadowed = false;
}
- /// \brief Clears out any current state and re-initializes for a
+ /// Clears out any current state and re-initializes for a
/// different kind of lookup.
void clear(Sema::LookupNameKind Kind) {
clear();
@@ -571,7 +557,7 @@ public:
configure();
}
- /// \brief Change this lookup's redeclaration kind.
+ /// Change this lookup's redeclaration kind.
void setRedeclarationKind(Sema::RedeclarationKind RK) {
Redecl = (RK != Sema::NotForRedeclaration);
ExternalRedecl = (RK == Sema::ForExternalRedeclaration);
@@ -610,7 +596,7 @@ public:
return NameInfo.getLoc();
}
- /// \brief Get the Sema object that this lookup result is searching
+ /// Get the Sema object that this lookup result is searching
/// with.
Sema &getSema() const { return *SemaPtr; }
@@ -618,15 +604,14 @@ public:
/// filtering out results. The results returned are possibly
/// sugared.
class Filter {
+ friend class LookupResult;
+
LookupResult &Results;
LookupResult::iterator I;
- bool Changed;
- bool CalledDone;
-
- friend class LookupResult;
- Filter(LookupResult &Results)
- : Results(Results), I(Results.begin()), Changed(false), CalledDone(false)
- {}
+ bool Changed = false;
+ bool CalledDone = false;
+
+ Filter(LookupResult &Results) : Results(Results), I(Results.begin()) {}
public:
Filter(Filter &&F)
@@ -634,6 +619,7 @@ public:
CalledDone(F.CalledDone) {
F.CalledDone = true;
}
+
~Filter() {
assert(CalledDone &&
"LookupResult::Filter destroyed without done() call");
@@ -722,11 +708,11 @@ private:
static void deletePaths(CXXBasePaths *);
// Results.
- LookupResultKind ResultKind;
+ LookupResultKind ResultKind = NotFound;
AmbiguityKind Ambiguity; // ill-defined unless ambiguous
UnresolvedSet<8> Decls;
- CXXBasePaths *Paths;
- CXXRecordDecl *NamingClass;
+ CXXBasePaths *Paths = nullptr;
+ CXXRecordDecl *NamingClass = nullptr;
QualType BaseObjectType;
// Parameters.
@@ -734,27 +720,27 @@ private:
DeclarationNameInfo NameInfo;
SourceRange NameContextRange;
Sema::LookupNameKind LookupKind;
- unsigned IDNS; // set by configure()
+ unsigned IDNS = 0; // set by configure()
bool Redecl;
bool ExternalRedecl;
- /// \brief True if tag declarations should be hidden if non-tags
+ /// True if tag declarations should be hidden if non-tags
/// are present
- bool HideTags;
+ bool HideTags = true;
- bool Diagnose;
+ bool Diagnose = false;
- /// \brief True if we should allow hidden declarations to be 'visible'.
- bool AllowHidden;
+ /// True if we should allow hidden declarations to be 'visible'.
+ bool AllowHidden = false;
- /// \brief True if the found declarations were shadowed by some other
+ /// True if the found declarations were shadowed by some other
/// declaration that we skipped. This only happens when \c LookupKind
/// is \c LookupRedeclarationWithLinkage.
- bool Shadowed;
+ bool Shadowed = false;
};
-/// \brief Consumes visible declarations found when searching for
+/// Consumes visible declarations found when searching for
/// all visible names within a given scope or context.
///
/// This abstract class is meant to be subclassed by clients of \c
@@ -762,15 +748,15 @@ private:
/// FoundDecl() function to process declarations as they are found.
class VisibleDeclConsumer {
public:
- /// \brief Destroys the visible declaration consumer.
+ /// Destroys the visible declaration consumer.
virtual ~VisibleDeclConsumer();
- /// \brief Determine whether hidden declarations (from unimported
+ /// Determine whether hidden declarations (from unimported
/// modules) should be given to this consumer. By default, they
/// are not included.
virtual bool includeHiddenDecls() const;
- /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
+ /// Invoked each time \p Sema::LookupVisibleDecls() finds a
/// declaration visible from the current scope or context.
///
/// \param ND the declaration found.
@@ -784,9 +770,15 @@ public:
/// class of the context we searched.
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) = 0;
+
+ /// Callback to inform the client that Sema entered into a new context
+ /// to find a visible declaration.
+ //
+ /// \param Ctx the context which Sema entered.
+ virtual void EnteredContext(DeclContext *Ctx) {}
};
-/// \brief A class for storing results from argument-dependent lookup.
+/// A class for storing results from argument-dependent lookup.
class ADLResult {
private:
/// A map from canonical decls to the 'most recent' decl.
@@ -807,13 +799,13 @@ public:
Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
}
- typedef llvm::mapped_iterator<decltype(Decls)::iterator, select_second>
- iterator;
+ using iterator =
+ llvm::mapped_iterator<decltype(Decls)::iterator, select_second>;
iterator begin() { return iterator(Decls.begin(), select_second()); }
iterator end() { return iterator(Decls.end(), select_second()); }
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_LOOKUP_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h b/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h
index c8b2ee845e59..171435e69bc8 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h
@@ -12,12 +12,12 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Sema/AttributeList.h"
#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedAttr.h"
namespace clang {
-/// \brief Loop optimization hint for loop and unroll pragmas.
+/// Loop optimization hint for loop and unroll pragmas.
struct LoopHint {
// Source range of the directive.
SourceRange Range;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
index 1d681a00552f..86bddebcef69 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -33,7 +33,7 @@ namespace clang {
class VarDecl;
-/// \brief An abstract interface that should be implemented by
+/// An abstract interface that should be implemented by
/// external AST sources that also provide information for semantic
/// analysis.
class MultiplexExternalSemaSource : public ExternalSemaSource {
@@ -42,8 +42,8 @@ private:
SmallVector<ExternalSemaSource *, 2> Sources; // doesn't own them.
public:
-
- ///\brief Constructs a new multiplexing external sema source and appends the
+
+ ///Constructs a new multiplexing external sema source and appends the
/// given element to it.
///
///\param[in] s1 - A non-null (old) ExternalSemaSource.
@@ -53,7 +53,7 @@ public:
~MultiplexExternalSemaSource() override;
- ///\brief Appends new source to the source list.
+ ///Appends new source to the source list.
///
///\param[in] source - An ExternalSemaSource.
///
@@ -63,45 +63,45 @@ public:
// ExternalASTSource.
//===--------------------------------------------------------------------===//
- /// \brief Resolve a declaration ID into a declaration, potentially
+ /// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
Decl *GetExternalDecl(uint32_t ID) override;
- /// \brief Complete the redeclaration chain if it's been extended since the
+ /// Complete the redeclaration chain if it's been extended since the
/// previous generation of the AST source.
void CompleteRedeclChain(const Decl *D) override;
- /// \brief Resolve a selector ID into a selector.
+ /// Resolve a selector ID into a selector.
Selector GetExternalSelector(uint32_t ID) override;
- /// \brief Returns the number of selectors known to the external AST
+ /// Returns the number of selectors known to the external AST
/// source.
uint32_t GetNumExternalSelectors() override;
- /// \brief Resolve the offset of a statement in the decl stream into
+ /// Resolve the offset of a statement in the decl stream into
/// a statement.
Stmt *GetExternalDeclStmt(uint64_t Offset) override;
- /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// Resolve the offset of a set of C++ base specifiers in the decl
/// stream into an array of specifiers.
CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
- /// \brief Resolve a handle to a list of ctor initializers into the list of
+ /// Resolve a handle to a list of ctor initializers into the list of
/// initializers themselves.
CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
ExtKind hasExternalDefinitions(const Decl *D) override;
- /// \brief Find all declarations with the given name in the
+ /// Find all declarations with the given name in the
/// given context.
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;
- /// \brief Ensures that the table of all visible declarations inside this
+ /// Ensures that the table of all visible declarations inside this
/// context is up to date.
void completeVisibleDeclsMap(const DeclContext *DC) override;
- /// \brief Finds all declarations lexically contained within the given
+ /// Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
/// \param IsKindWeWant a predicate function that returns true if the passed
@@ -111,48 +111,52 @@ public:
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Result) override;
- /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
- /// a range.
+ /// a range.
void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
SmallVectorImpl<Decl *> &Decls) override;
- /// \brief Gives the external AST source an opportunity to complete
+ /// Gives the external AST source an opportunity to complete
/// an incomplete type.
void CompleteType(TagDecl *Tag) override;
- /// \brief Gives the external AST source an opportunity to complete an
+ /// Gives the external AST source an opportunity to complete an
/// incomplete Objective-C class.
///
/// This routine will only be invoked if the "externally completed" bit is
- /// set on the ObjCInterfaceDecl via the function
+ /// set on the ObjCInterfaceDecl via the function
/// \c ObjCInterfaceDecl::setExternallyCompleted().
void CompleteType(ObjCInterfaceDecl *Class) override;
- /// \brief Loads comment ranges.
+ /// Loads comment ranges.
void ReadComments() override;
- /// \brief Notify ExternalASTSource that we started deserialization of
+ /// Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
void StartedDeserializing() override;
- /// \brief Notify ExternalASTSource that we finished the deserialization of
+ /// Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
void FinishedDeserializing() override;
- /// \brief Function that will be invoked when we begin parsing a new
+ /// Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
void StartTranslationUnit(ASTConsumer *Consumer) override;
- /// \brief Print any statistics that have been gathered regarding
+ /// Print any statistics that have been gathered regarding
/// the external AST source.
void PrintStats() override;
-
-
- /// \brief Perform layout on the given record.
+
+ /// Retrieve the module that corresponds to the given module ID.
+ Module *getModule(unsigned ID) override;
+
+ bool DeclIsFromPCHWithObjectFile(const Decl *D) override;
+
+ /// Perform layout on the given record.
///
- /// This routine allows the external AST source to provide an specific
+ /// This routine allows the external AST source to provide an specific
/// layout for a record, overriding the layout that would normally be
/// constructed. It is intended for clients who receive specific layout
/// details rather than source code (such as LLDB). The client is expected
@@ -169,13 +173,13 @@ public:
/// expressed in bits. All of the fields must be provided with offsets.
///
/// \param BaseOffsets The offset of each of the direct, non-virtual base
- /// classes. If any bases are not given offsets, the bases will be laid
+ /// classes. If any bases are not given offsets, the bases will be laid
/// out according to the ABI.
///
/// \param VirtualBaseOffsets The offset of each of the virtual base classes
- /// (either direct or not). If any bases are not given offsets, the bases will
+ /// (either direct or not). If any bases are not given offsets, the bases will
/// be laid out according to the ABI.
- ///
+ ///
/// \returns true if the record layout was provided, false otherwise.
bool
layoutRecordType(const RecordDecl *Record,
@@ -193,15 +197,15 @@ public:
// ExternalSemaSource.
//===--------------------------------------------------------------------===//
- /// \brief Initialize the semantic source with the Sema instance
+ /// Initialize the semantic source with the Sema instance
/// being used to perform semantic analysis on the abstract syntax
/// tree.
void InitializeSema(Sema &S) override;
- /// \brief Inform the semantic consumer that Sema is no longer available.
+ /// Inform the semantic consumer that Sema is no longer available.
void ForgetSema() override;
- /// \brief Load the contents of the global method pool for a given
+ /// Load the contents of the global method pool for a given
/// selector.
void ReadMethodPool(Selector Sel) override;
@@ -209,12 +213,12 @@ public:
/// selector if necessary.
void updateOutOfDateSelector(Selector Sel) override;
- /// \brief Load the set of namespaces that are known to the external source,
+ /// Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
void
ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces) override;
- /// \brief Load the set of used but not defined functions or variables with
+ /// Load the set of used but not defined functions or variables with
/// internal linkage, or used but not defined inline functions.
void ReadUndefinedButUsed(
llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) override;
@@ -223,7 +227,7 @@ public:
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
Exprs) override;
- /// \brief Do last resort, unqualified lookup on a LookupResult that
+ /// Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
///
/// \param R a LookupResult that is being recovered.
@@ -233,7 +237,7 @@ public:
/// \return true to tell Sema to recover using the LookupResult.
bool LookupUnqualified(LookupResult &R, Scope *S) override;
- /// \brief Read the set of tentative definitions known to the external Sema
+ /// Read the set of tentative definitions known to the external Sema
/// source.
///
/// The external source should append its own tentative definitions to the
@@ -242,7 +246,7 @@ public:
/// introduce the same declarations repeatedly.
void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs) override;
- /// \brief Read the set of unused file-scope declarations known to the
+ /// Read the set of unused file-scope declarations known to the
/// external Sema source.
///
/// The external source should append its own unused, filed-scope to the
@@ -252,7 +256,7 @@ public:
void ReadUnusedFileScopedDecls(
SmallVectorImpl<const DeclaratorDecl*> &Decls) override;
- /// \brief Read the set of delegating constructors known to the
+ /// Read the set of delegating constructors known to the
/// external Sema source.
///
/// The external source should append its own delegating constructors to the
@@ -262,7 +266,7 @@ public:
void ReadDelegatingConstructors(
SmallVectorImpl<CXXConstructorDecl*> &Decls) override;
- /// \brief Read the set of ext_vector type declarations known to the
+ /// Read the set of ext_vector type declarations known to the
/// external Sema source.
///
/// The external source should append its own ext_vector type declarations to
@@ -271,7 +275,7 @@ public:
/// introduce the same declarations repeatedly.
void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override;
- /// \brief Read the set of potentially unused typedefs known to the source.
+ /// Read the set of potentially unused typedefs known to the source.
///
/// The external source should append its own potentially unused local
/// typedefs to the given vector of declarations. Note that this routine may
@@ -280,34 +284,34 @@ public:
void ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
- /// \brief Read the set of referenced selectors known to the
+ /// Read the set of referenced selectors known to the
/// external Sema source.
///
- /// The external source should append its own referenced selectors to the
- /// given vector of selectors. Note that this routine
- /// may be invoked multiple times; the external source should take care not
+ /// The external source should append its own referenced selectors to the
+ /// given vector of selectors. Note that this routine
+ /// may be invoked multiple times; the external source should take care not
/// to introduce the same selectors repeatedly.
void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector,
SourceLocation> > &Sels) override;
- /// \brief Read the set of weak, undeclared identifiers known to the
+ /// Read the set of weak, undeclared identifiers known to the
/// external Sema source.
///
/// The external source should append its own weak, undeclared identifiers to
- /// the given vector. Note that this routine may be invoked multiple times;
+ /// the given vector. Note that this routine may be invoked multiple times;
/// the external source should take care not to introduce the same identifiers
/// repeatedly.
void ReadWeakUndeclaredIdentifiers(
SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) override;
- /// \brief Read the set of used vtables known to the external Sema source.
+ /// Read the set of used vtables known to the external Sema source.
///
/// The external source should append its own used vtables to the given
/// vector. Note that this routine may be invoked multiple times; the external
/// source should take care not to introduce the same vtables repeatedly.
void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
- /// \brief Read the set of pending instantiations known to the external
+ /// Read the set of pending instantiations known to the external
/// Sema source.
///
/// The external source should append its own pending instantiations to the
@@ -317,7 +321,7 @@ public:
void ReadPendingInstantiations(
SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override;
- /// \brief Read the set of late parsed template functions for this source.
+ /// Read the set of late parsed template functions for this source.
///
/// The external source should insert its own late parsed template functions
/// into the map. Note that this routine may be invoked multiple times; the
@@ -336,7 +340,7 @@ public:
bool EnteringContext,
const ObjCObjectPointerType *OPT) override;
- /// \brief Produces a diagnostic note if one of the attached sources
+ /// Produces a diagnostic note if one of the attached sources
/// contains a complete definition for \p T. Queries the sources in list
/// order until the first one claims that a diagnostic was produced.
///
@@ -352,7 +356,7 @@ public:
// isa/cast/dyn_cast support
static bool classof(const MultiplexExternalSemaSource*) { return true; }
//static bool classof(const ExternalSemaSource*) { return true; }
-};
+};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h
index 80ccd363d272..d0af4d15fb9f 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h
@@ -21,13 +21,13 @@ namespace clang {
class ObjCMethodDecl;
-/// \brief a linked list of methods with the same selector name but different
+/// a linked list of methods with the same selector name but different
/// signatures.
struct ObjCMethodList {
// NOTE: If you add any members to this struct, make sure to serialize them.
- /// \brief If there is more than one decl with this signature.
+ /// If there is more than one decl with this signature.
llvm::PointerIntPair<ObjCMethodDecl *, 1> MethodAndHasMoreThanOneDecl;
- /// \brief The next list object and 2 bits for extra info.
+ /// The next list object and 2 bits for extra info.
llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits;
ObjCMethodList() { }
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
index 05cfe53666ca..6ded010ee8ed 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
@@ -1,4 +1,4 @@
-//===--- Overload.h - C++ Overloading ---------------------------*- C++ -*-===//
+//===- Overload.h - C++ Overloading -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,34 +16,53 @@
#define LLVM_CLANG_SEMA_OVERLOAD_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/Expr.h"
-#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
-#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
namespace clang {
- class ASTContext;
- class CXXConstructorDecl;
- class CXXConversionDecl;
- class FunctionDecl;
- class Sema;
+
+class APValue;
+class ASTContext;
+class Sema;
/// OverloadingResult - Capture the result of performing overload
/// resolution.
enum OverloadingResult {
- OR_Success, ///< Overload resolution succeeded.
- OR_No_Viable_Function, ///< No viable function found.
- OR_Ambiguous, ///< Ambiguous candidates found.
- OR_Deleted ///< Succeeded, but refers to a deleted function.
+ /// Overload resolution succeeded.
+ OR_Success,
+
+ /// No viable function found.
+ OR_No_Viable_Function,
+
+ /// Ambiguous candidates found.
+ OR_Ambiguous,
+
+ /// Succeeded, but refers to a deleted function.
+ OR_Deleted
};
-
+
enum OverloadCandidateDisplayKind {
/// Requests that all candidates be shown. Viable candidates will
/// be printed first.
@@ -55,39 +74,95 @@ namespace clang {
/// ImplicitConversionKind - The kind of implicit conversion used to
/// convert an argument to a parameter's type. The enumerator values
- /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
- /// better conversion kinds have smaller values.
+ /// match with the table titled 'Conversions' in [over.ics.scs] and are listed
+ /// such that better conversion kinds have smaller values.
enum ImplicitConversionKind {
- ICK_Identity = 0, ///< Identity conversion (no conversion)
- ICK_Lvalue_To_Rvalue, ///< Lvalue-to-rvalue conversion (C++ 4.1)
- ICK_Array_To_Pointer, ///< Array-to-pointer conversion (C++ 4.2)
- ICK_Function_To_Pointer, ///< Function-to-pointer (C++ 4.3)
- ICK_Function_Conversion, ///< Function pointer conversion (C++17 4.13)
- ICK_Qualification, ///< Qualification conversions (C++ 4.4)
- ICK_Integral_Promotion, ///< Integral promotions (C++ 4.5)
- ICK_Floating_Promotion, ///< Floating point promotions (C++ 4.6)
- ICK_Complex_Promotion, ///< Complex promotions (Clang extension)
- ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7)
- ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8)
- ICK_Complex_Conversion, ///< Complex conversions (C99 6.3.1.6)
- ICK_Floating_Integral, ///< Floating-integral conversions (C++ 4.9)
- ICK_Pointer_Conversion, ///< Pointer conversions (C++ 4.10)
- ICK_Pointer_Member, ///< Pointer-to-member conversions (C++ 4.11)
- ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12)
- ICK_Compatible_Conversion, ///< Conversions between compatible types in C99
- ICK_Derived_To_Base, ///< Derived-to-base (C++ [over.best.ics])
- ICK_Vector_Conversion, ///< Vector conversions
- ICK_Vector_Splat, ///< A vector splat from an arithmetic type
- ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7)
- ICK_Block_Pointer_Conversion, ///< Block Pointer conversions
- ICK_TransparentUnionConversion, ///< Transparent Union Conversions
- ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion
- ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10)
- ICK_Zero_Queue_Conversion, ///< Zero constant to queue
- ICK_C_Only_Conversion, ///< Conversions allowed in C, but not C++
- ICK_Incompatible_Pointer_Conversion, ///< C-only conversion between pointers
- /// with incompatible types
- ICK_Num_Conversion_Kinds, ///< The number of conversion kinds
+ /// Identity conversion (no conversion)
+ ICK_Identity = 0,
+
+ /// Lvalue-to-rvalue conversion (C++ [conv.lval])
+ ICK_Lvalue_To_Rvalue,
+
+ /// Array-to-pointer conversion (C++ [conv.array])
+ ICK_Array_To_Pointer,
+
+ /// Function-to-pointer (C++ [conv.array])
+ ICK_Function_To_Pointer,
+
+ /// Function pointer conversion (C++17 [conv.fctptr])
+ ICK_Function_Conversion,
+
+ /// Qualification conversions (C++ [conv.qual])
+ ICK_Qualification,
+
+ /// Integral promotions (C++ [conv.prom])
+ ICK_Integral_Promotion,
+
+ /// Floating point promotions (C++ [conv.fpprom])
+ ICK_Floating_Promotion,
+
+ /// Complex promotions (Clang extension)
+ ICK_Complex_Promotion,
+
+ /// Integral conversions (C++ [conv.integral])
+ ICK_Integral_Conversion,
+
+ /// Floating point conversions (C++ [conv.double]
+ ICK_Floating_Conversion,
+
+ /// Complex conversions (C99 6.3.1.6)
+ ICK_Complex_Conversion,
+
+ /// Floating-integral conversions (C++ [conv.fpint])
+ ICK_Floating_Integral,
+
+ /// Pointer conversions (C++ [conv.ptr])
+ ICK_Pointer_Conversion,
+
+ /// Pointer-to-member conversions (C++ [conv.mem])
+ ICK_Pointer_Member,
+
+ /// Boolean conversions (C++ [conv.bool])
+ ICK_Boolean_Conversion,
+
+ /// Conversions between compatible types in C99
+ ICK_Compatible_Conversion,
+
+ /// Derived-to-base (C++ [over.best.ics])
+ ICK_Derived_To_Base,
+
+ /// Vector conversions
+ ICK_Vector_Conversion,
+
+ /// A vector splat from an arithmetic type
+ ICK_Vector_Splat,
+
+ /// Complex-real conversions (C99 6.3.1.7)
+ ICK_Complex_Real,
+
+ /// Block Pointer conversions
+ ICK_Block_Pointer_Conversion,
+
+ /// Transparent Union Conversions
+ ICK_TransparentUnionConversion,
+
+ /// Objective-C ARC writeback conversion
+ ICK_Writeback_Conversion,
+
+ /// Zero constant to event (OpenCL1.2 6.12.10)
+ ICK_Zero_Event_Conversion,
+
+ /// Zero constant to queue
+ ICK_Zero_Queue_Conversion,
+
+ /// Conversions allowed in C, but not C++
+ ICK_C_Only_Conversion,
+
+ /// C-only conversion between pointers with incompatible types
+ ICK_Incompatible_Pointer_Conversion,
+
+ /// The number of conversion kinds
+ ICK_Num_Conversion_Kinds,
};
/// ImplicitConversionRank - The rank of an implicit conversion
@@ -95,16 +170,30 @@ namespace clang {
/// 13.3.3.1.1) and are listed such that better conversion ranks
/// have smaller values.
enum ImplicitConversionRank {
- ICR_Exact_Match = 0, ///< Exact Match
- ICR_Promotion, ///< Promotion
- ICR_Conversion, ///< Conversion
- ICR_OCL_Scalar_Widening, ///< OpenCL Scalar Widening
- ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion
- ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion
- ICR_C_Conversion, ///< Conversion only allowed in the C standard.
- /// (e.g. void* to char*)
- ICR_C_Conversion_Extension ///< Conversion not allowed by the C standard,
- /// but that we accept as an extension anyway.
+ /// Exact Match
+ ICR_Exact_Match = 0,
+
+ /// Promotion
+ ICR_Promotion,
+
+ /// Conversion
+ ICR_Conversion,
+
+ /// OpenCL Scalar Widening
+ ICR_OCL_Scalar_Widening,
+
+ /// Complex <-> Real conversion
+ ICR_Complex_Real_Conversion,
+
+ /// ObjC ARC writeback conversion
+ ICR_Writeback_Conversion,
+
+ /// Conversion only allowed in the C standard (e.g. void* to char*).
+ ICR_C_Conversion,
+
+ /// Conversion not allowed by the C standard, but that we accept as an
+ /// extension anyway.
+ ICR_C_Conversion_Extension
};
ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
@@ -155,15 +244,15 @@ namespace clang {
/// or a function conversion.
ImplicitConversionKind Third : 8;
- /// \brief Whether this is the deprecated conversion of a
+ /// Whether this is the deprecated conversion of a
/// string literal to a pointer to non-const character data
/// (C++ 4.2p2).
unsigned DeprecatedStringLiteralToCharPtr : 1;
- /// \brief Whether the qualification conversion involves a change in the
+ /// Whether the qualification conversion involves a change in the
/// Objective-C lifetime (for automatic reference counting).
unsigned QualificationIncludesObjCLifetime : 1;
-
+
/// IncompatibleObjC - Whether this is an Objective-C conversion
/// that we should warn about (if we actually use it).
unsigned IncompatibleObjC : 1;
@@ -176,24 +265,24 @@ namespace clang {
/// direct binding (C++ [dcl.init.ref]).
unsigned DirectBinding : 1;
- /// \brief Whether this is an lvalue reference binding (otherwise, it's
+ /// Whether this is an lvalue reference binding (otherwise, it's
/// an rvalue reference binding).
unsigned IsLvalueReference : 1;
-
- /// \brief Whether we're binding to a function lvalue.
+
+ /// Whether we're binding to a function lvalue.
unsigned BindsToFunctionLvalue : 1;
-
- /// \brief Whether we're binding to an rvalue.
+
+ /// Whether we're binding to an rvalue.
unsigned BindsToRvalue : 1;
-
- /// \brief Whether this binds an implicit object argument to a
+
+ /// Whether this binds an implicit object argument to a
/// non-static member function without a ref-qualifier.
unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1;
-
- /// \brief Whether this binds a reference to an object with a different
+
+ /// Whether this binds a reference to an object with a different
/// Objective-C lifetime qualifier.
unsigned ObjCLifetimeConversionBinding : 1;
-
+
/// FromType - The type that this conversion is converting
/// from. This is an opaque pointer that can be translated into a
/// QualType.
@@ -213,12 +302,14 @@ namespace clang {
DeclAccessPair FoundCopyConstructor;
void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
- void setToType(unsigned Idx, QualType T) {
+
+ void setToType(unsigned Idx, QualType T) {
assert(Idx < 3 && "To type index is out of range");
- ToTypePtrs[Idx] = T.getAsOpaquePtr();
+ ToTypePtrs[Idx] = T.getAsOpaquePtr();
}
+
void setAllToTypes(QualType T) {
- ToTypePtrs[0] = T.getAsOpaquePtr();
+ ToTypePtrs[0] = T.getAsOpaquePtr();
ToTypePtrs[1] = ToTypePtrs[0];
ToTypePtrs[2] = ToTypePtrs[0];
}
@@ -226,21 +317,23 @@ namespace clang {
QualType getFromType() const {
return QualType::getFromOpaquePtr(FromTypePtr);
}
+
QualType getToType(unsigned Idx) const {
assert(Idx < 3 && "To type index is out of range");
return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
}
void setAsIdentityConversion();
-
+
bool isIdentityConversion() const {
return Second == ICK_Identity && Third == ICK_Identity;
}
-
+
ImplicitConversionRank getRank() const;
- NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted,
- APValue &ConstantValue,
- QualType &ConstantType) const;
+ NarrowingKind
+ getNarrowingKind(ASTContext &Context, const Expr *Converted,
+ APValue &ConstantValue, QualType &ConstantType,
+ bool IgnoreFloatToIntegralConversion = false) const;
bool isPointerConversionToBool() const;
bool isPointerConversionToVoidPointer(ASTContext& Context) const;
void dump() const;
@@ -249,7 +342,7 @@ namespace clang {
/// UserDefinedConversionSequence - Represents a user-defined
/// conversion sequence (C++ 13.3.3.1.2).
struct UserDefinedConversionSequence {
- /// \brief Represents the standard conversion that occurs before
+ /// Represents the standard conversion that occurs before
/// the actual user-defined conversion.
///
/// C++11 13.3.3.1.2p1:
@@ -284,7 +377,7 @@ namespace clang {
/// aggregate initialization from an initializer list.
FunctionDecl* ConversionFunction;
- /// \brief The declaration that we found via name lookup, which might be
+ /// The declaration that we found via name lookup, which might be
/// the same as \c ConversionFunction or it might be a using declaration
/// that refers to \c ConversionFunction.
DeclAccessPair FoundConversionFunction;
@@ -294,7 +387,8 @@ namespace clang {
/// Represents an ambiguous user-defined conversion sequence.
struct AmbiguousConversionSequence {
- typedef SmallVector<std::pair<NamedDecl*, FunctionDecl*>, 4> ConversionSet;
+ using ConversionSet =
+ SmallVector<std::pair<NamedDecl *, FunctionDecl *>, 4>;
void *FromTypePtr;
void *ToTypePtr;
@@ -303,9 +397,11 @@ namespace clang {
QualType getFromType() const {
return QualType::getFromOpaquePtr(FromTypePtr);
}
+
QualType getToType() const {
return QualType::getFromOpaquePtr(ToTypePtr);
}
+
void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
@@ -321,11 +417,13 @@ namespace clang {
conversions().push_back(std::make_pair(Found, D));
}
- typedef ConversionSet::iterator iterator;
+ using iterator = ConversionSet::iterator;
+
iterator begin() { return conversions().begin(); }
iterator end() { return conversions().end(); }
- typedef ConversionSet::const_iterator const_iterator;
+ using const_iterator = ConversionSet::const_iterator;
+
const_iterator begin() const { return conversions().begin(); }
const_iterator end() const { return conversions().end(); }
@@ -362,6 +460,7 @@ namespace clang {
init(K, From->getType(), To);
FromExpr = From;
}
+
void init(FailureKind K, QualType From, QualType To) {
Kind = K;
FromExpr = nullptr;
@@ -376,6 +475,7 @@ namespace clang {
FromExpr = E;
setFromType(E->getType());
}
+
void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); }
void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); }
};
@@ -406,7 +506,7 @@ namespace clang {
/// ConversionKind - The kind of implicit conversion sequence.
unsigned ConversionKind : 30;
- /// \brief Whether the target is really a std::initializer_list, and the
+ /// Whether the target is really a std::initializer_list, and the
/// sequence only represents the worst element conversion.
unsigned StdInitializerListElement : 1;
@@ -442,13 +542,10 @@ namespace clang {
: ConversionKind(Uninitialized), StdInitializerListElement(false) {
Standard.setAsIdentityConversion();
}
- ~ImplicitConversionSequence() {
- destruct();
- }
+
ImplicitConversionSequence(const ImplicitConversionSequence &Other)
- : ConversionKind(Other.ConversionKind),
- StdInitializerListElement(Other.StdInitializerListElement)
- {
+ : ConversionKind(Other.ConversionKind),
+ StdInitializerListElement(Other.StdInitializerListElement) {
switch (ConversionKind) {
case Uninitialized: break;
case StandardConversion: Standard = Other.Standard; break;
@@ -460,18 +557,22 @@ namespace clang {
}
ImplicitConversionSequence &
- operator=(const ImplicitConversionSequence &Other) {
+ operator=(const ImplicitConversionSequence &Other) {
destruct();
new (this) ImplicitConversionSequence(Other);
return *this;
}
-
+
+ ~ImplicitConversionSequence() {
+ destruct();
+ }
+
Kind getKind() const {
assert(isInitialized() && "querying uninitialized conversion");
return Kind(ConversionKind);
}
-
- /// \brief Return a ranking of the implicit conversion sequence
+
+ /// Return a ranking of the implicit conversion sequence
/// kind, where smaller ranks represent better conversion
/// sequences.
///
@@ -480,11 +581,11 @@ namespace clang {
/// per C++ [over.best.ics]p10.
unsigned getKindRank() const {
switch (getKind()) {
- case StandardConversion:
+ case StandardConversion:
return 0;
case UserDefinedConversion:
- case AmbiguousConversion:
+ case AmbiguousConversion:
return 1;
case EllipsisConversion:
@@ -526,6 +627,7 @@ namespace clang {
void setStandard() { setKind(StandardConversion); }
void setEllipsis() { setKind(EllipsisConversion); }
void setUserDefined() { setKind(UserDefinedConversion); }
+
void setAmbiguous() {
if (ConversionKind == AmbiguousConversion) return;
ConversionKind = AmbiguousConversion;
@@ -539,7 +641,7 @@ namespace clang {
Standard.setAllToTypes(T);
}
- /// \brief Whether the target is really a std::initializer_list, and the
+ /// Whether the target is really a std::initializer_list, and the
/// sequence only represents the worst element conversion.
bool isStdInitializerListElement() const {
return StdInitializerListElement;
@@ -613,12 +715,16 @@ namespace clang {
/// This inherited constructor is not viable because it would slice the
/// argument.
ovl_fail_inhctor_slice,
+
+ /// This candidate was not viable because it is a non-default multiversioned
+ /// function.
+ ovl_non_default_multiversion_function,
};
/// A list of implicit conversion sequences for the arguments of an
/// OverloadCandidate.
- typedef llvm::MutableArrayRef<ImplicitConversionSequence>
- ConversionSequenceList;
+ using ConversionSequenceList =
+ llvm::MutableArrayRef<ImplicitConversionSequence>;
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
struct OverloadCandidate {
@@ -669,13 +775,13 @@ namespace clang {
/// Actually an OverloadFailureKind.
unsigned char FailureKind;
- /// \brief The number of call arguments that were explicitly provided,
+ /// The number of call arguments that were explicitly provided,
/// to be used while performing partial ordering of function templates.
unsigned ExplicitCallArguments;
union {
DeductionFailureInfo DeductionFailure;
-
+
/// FinalConversion - For a conversion function (where Function is
/// a CXXConversionDecl), the standard conversion that occurs
/// after the call to the overload candidate to convert the result
@@ -726,16 +832,19 @@ namespace clang {
enum CandidateSetKind {
/// Normal lookup.
CSK_Normal,
+
/// 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.
@@ -755,7 +864,7 @@ namespace clang {
constexpr static unsigned NumInlineBytes =
24 * sizeof(ImplicitConversionSequence);
- unsigned NumInlineBytesUsed;
+ unsigned NumInlineBytesUsed = 0;
llvm::AlignedCharArray<alignof(void *), NumInlineBytes> InlineSpace;
/// If we have space, allocates from inline storage. Otherwise, allocates
@@ -784,36 +893,36 @@ namespace clang {
return reinterpret_cast<T *>(FreeSpaceStart);
}
- OverloadCandidateSet(const OverloadCandidateSet &) = delete;
- void operator=(const OverloadCandidateSet &) = delete;
-
void destroyCandidates();
public:
OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK)
- : Loc(Loc), Kind(CSK), NumInlineBytesUsed(0) {}
+ : Loc(Loc), Kind(CSK) {}
+ OverloadCandidateSet(const OverloadCandidateSet &) = delete;
+ OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
~OverloadCandidateSet() { destroyCandidates(); }
SourceLocation getLocation() const { return Loc; }
CandidateSetKind getKind() const { return Kind; }
- /// \brief Determine when this overload candidate will be new to the
+ /// Determine when this overload candidate will be new to the
/// overload set.
bool isNewCandidate(Decl *F) {
return Functions.insert(F->getCanonicalDecl()).second;
}
- /// \brief Clear out all of the candidates.
+ /// Clear out all of the candidates.
void clear(CandidateSetKind CSK);
- typedef SmallVectorImpl<OverloadCandidate>::iterator iterator;
+ using iterator = SmallVectorImpl<OverloadCandidate>::iterator;
+
iterator begin() { return Candidates.begin(); }
iterator end() { return Candidates.end(); }
size_t size() const { return Candidates.size(); }
bool empty() const { return Candidates.empty(); }
- /// \brief Allocate storage for conversion sequences for NumConversions
+ /// Allocate storage for conversion sequences for NumConversions
/// conversions.
ConversionSequenceList
allocateConversionSequences(unsigned NumConversions) {
@@ -827,7 +936,7 @@ namespace clang {
return ConversionSequenceList(Conversions, NumConversions);
}
- /// \brief Add a new candidate with NumConversions conversion sequence slots
+ /// Add a new candidate with NumConversions conversion sequence slots
/// to the overload set.
OverloadCandidate &addCandidate(unsigned NumConversions = 0,
ConversionSequenceList Conversions = None) {
@@ -865,8 +974,10 @@ namespace clang {
DeclAccessPair FoundDecl;
CXXConstructorDecl *Constructor;
FunctionTemplateDecl *ConstructorTmpl;
+
explicit operator bool() const { return Constructor; }
};
+
// FIXME: Add an AddOverloadCandidate / AddTemplateOverloadCandidate overload
// that takes one of these.
inline ConstructorInfo getConstructorInfo(NamedDecl *ND) {
@@ -884,6 +995,7 @@ namespace clang {
Info.Constructor = dyn_cast<CXXConstructorDecl>(D);
return Info;
}
-} // end namespace clang
+
+} // namespace clang
#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
index 1e35316fd5dd..ae2f178df1ec 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
@@ -1,4 +1,4 @@
-//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===//
+//===- Ownership.h - Parser ownership helpers -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,23 +17,29 @@
#include "clang/AST/Expr.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
//===----------------------------------------------------------------------===//
// OpaquePtr
//===----------------------------------------------------------------------===//
namespace clang {
- class CXXCtorInitializer;
- class CXXBaseSpecifier;
- class Decl;
- class Expr;
- class ParsedTemplateArgument;
- class QualType;
- class Stmt;
- class TemplateName;
- class TemplateParameterList;
-
- /// \brief Wrapper for void* pointer.
+
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class Decl;
+class Expr;
+class ParsedTemplateArgument;
+class QualType;
+class Stmt;
+class TemplateName;
+class TemplateParameterList;
+
+ /// Wrapper for void* pointer.
/// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
/// a pointer.
///
@@ -44,16 +50,17 @@ namespace clang {
template <class PtrTy>
class OpaquePtr {
void *Ptr = nullptr;
+
explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
- typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
+ using Traits = llvm::PointerLikeTypeTraits<PtrTy>;
public:
OpaquePtr(std::nullptr_t = nullptr) {}
static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
- /// \brief Returns plain pointer to the entity pointed by this wrapper.
+ /// Returns plain pointer to the entity pointed by this wrapper.
/// \tparam PointeeT Type of pointed entity.
///
/// It is identical to getPtrAs<PointeeT*>.
@@ -61,7 +68,7 @@ namespace clang {
return get();
}
- /// \brief Returns pointer converted to the specified type.
+ /// Returns pointer converted to the specified type.
/// \tparam PtrT Result pointer type. There must be implicit conversion
/// from PtrTy to PtrT.
///
@@ -103,26 +110,32 @@ namespace clang {
return *this;
}
};
-}
+
+} // namespace clang
namespace llvm {
+
template <class T>
- struct PointerLikeTypeTraits<clang::OpaquePtr<T> > {
+ struct PointerLikeTypeTraits<clang::OpaquePtr<T>> {
+ enum { NumLowBitsAvailable = 0 };
+
static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
// FIXME: Doesn't work? return P.getAs< void >();
return P.getAsOpaquePtr();
}
+
static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
return clang::OpaquePtr<T>::getFromOpaquePtr(P);
}
- enum { NumLowBitsAvailable = 0 };
};
template <class T>
- struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; };
-}
+ struct isPodLike<clang::OpaquePtr<T>> { static const bool value = true; };
+
+} // namespace llvm
namespace clang {
+
// Basic
class DiagnosticBuilder;
@@ -146,8 +159,7 @@ namespace clang {
bool Invalid;
public:
- ActionResult(bool Invalid = false)
- : Val(PtrTy()), Invalid(Invalid) {}
+ ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
ActionResult(PtrTy val) : Val(val), Invalid(false) {}
ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
@@ -178,17 +190,20 @@ namespace clang {
// A pointer whose low bit is 1 if this result is invalid, 0
// otherwise.
uintptr_t PtrWithInvalid;
- typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
+
+ using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
+
public:
ActionResult(bool Invalid = false)
- : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
+ : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) {}
ActionResult(PtrTy V) {
void *VP = PtrTraits::getAsVoidPointer(V);
PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
}
- ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
+
+ ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) {}
// These two overloads prevent void* -> bool conversions.
ActionResult(const void *) = delete;
@@ -202,6 +217,7 @@ namespace clang {
void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
return PtrTraits::getFromVoidPointer(VP);
}
+
template <typename T> T *getAs() { return static_cast<T*>(get()); }
void set(PtrTy V) {
@@ -229,8 +245,8 @@ namespace clang {
/// An opaque type for threading parsed type information through the
/// parser.
- typedef OpaquePtr<QualType> ParsedType;
- typedef UnionOpaquePtr<QualType> UnionParsedType;
+ using ParsedType = OpaquePtr<QualType>;
+ using UnionParsedType = UnionOpaquePtr<QualType>;
// We can re-use the low bit of expression, statement, base, and
// member-initializer pointers for the "invalid" flag of
@@ -248,21 +264,21 @@ namespace clang {
static const bool value = true;
};
- typedef ActionResult<Expr*> ExprResult;
- typedef ActionResult<Stmt*> StmtResult;
- typedef ActionResult<ParsedType> TypeResult;
- typedef ActionResult<CXXBaseSpecifier*> BaseResult;
- typedef ActionResult<CXXCtorInitializer*> MemInitResult;
+ using ExprResult = ActionResult<Expr *>;
+ using StmtResult = ActionResult<Stmt *>;
+ using TypeResult = ActionResult<ParsedType>;
+ using BaseResult = ActionResult<CXXBaseSpecifier *>;
+ using MemInitResult = ActionResult<CXXCtorInitializer *>;
- typedef ActionResult<Decl*> DeclResult;
- typedef OpaquePtr<TemplateName> ParsedTemplateTy;
- typedef UnionOpaquePtr<TemplateName> UnionParsedTemplateTy;
+ using DeclResult = ActionResult<Decl *>;
+ using ParsedTemplateTy = OpaquePtr<TemplateName>;
+ using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
- typedef MutableArrayRef<Expr*> MultiExprArg;
- typedef MutableArrayRef<Stmt*> MultiStmtArg;
- typedef MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr;
- typedef MutableArrayRef<ParsedType> MultiTypeArg;
- typedef MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg;
+ using MultiExprArg = MutableArrayRef<Expr *>;
+ using MultiStmtArg = MutableArrayRef<Stmt *>;
+ using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
+ using MultiTypeArg = MutableArrayRef<ParsedType>;
+ using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
inline ExprResult ExprError() { return ExprResult(true); }
inline StmtResult StmtError() { return StmtResult(true); }
@@ -282,6 +298,7 @@ namespace clang {
assert(!R.isInvalid() && "operation was asserted to never fail!");
return R.get();
}
-}
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_OWNERSHIP_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedAttr.h
index 4e806116c4d9..cfb91af78370 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedAttr.h
@@ -1,4 +1,4 @@
-//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===//
+//======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AttributeList class, which is used to collect
+// This file defines the ParsedAttr class, which is used to collect
// parsed attributes.
//
//===----------------------------------------------------------------------===//
@@ -18,45 +18,54 @@
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/VersionTuple.h"
#include "clang/Sema/Ownership.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/VersionTuple.h"
#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <utility>
namespace clang {
- class ASTContext;
- class IdentifierInfo;
- class Expr;
-/// \brief Represents information about a change in availability for
+class ASTContext;
+class Decl;
+class Expr;
+class IdentifierInfo;
+class LangOptions;
+
+/// Represents information about a change in availability for
/// an entity, which is part of the encoding of the 'availability'
/// attribute.
struct AvailabilityChange {
- /// \brief The location of the keyword indicating the kind of change.
+ /// The location of the keyword indicating the kind of change.
SourceLocation KeywordLoc;
- /// \brief The version number at which the change occurred.
+ /// The version number at which the change occurred.
VersionTuple Version;
- /// \brief The source range covering the version number.
+ /// The source range covering the version number.
SourceRange VersionRange;
- /// \brief Determine whether this availability change is valid.
+ /// Determine whether this availability change is valid.
bool isValid() const { return !Version.empty(); }
};
namespace {
+
enum AvailabilitySlot {
IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
};
-/// Describes the trailing object for Availability attribute in AttributeList.
+/// Describes the trailing object for Availability attribute in ParsedAttr.
struct AvailabilityData {
AvailabilityChange Changes[NumAvailabilitySlots];
SourceLocation StrictLoc;
const Expr *Replacement;
+
AvailabilityData(const AvailabilityChange &Introduced,
const AvailabilityChange &Deprecated,
const AvailabilityChange &Obsoleted,
@@ -67,9 +76,10 @@ struct AvailabilityData {
Changes[ObsoletedSlot] = Obsoleted;
}
};
-}
-/// \brief Wraps an identifier and optional source location for the identifier.
+} // namespace
+
+/// Wraps an identifier and optional source location for the identifier.
struct IdentifierLoc {
SourceLocation Loc;
IdentifierInfo *Ident;
@@ -78,12 +88,12 @@ struct IdentifierLoc {
IdentifierInfo *Ident);
};
-/// \brief A union of the various pointer types that can be passed to an
-/// AttributeList as an argument.
-typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion;
-typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector;
+/// A union of the various pointer types that can be passed to an
+/// ParsedAttr as an argument.
+using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>;
+using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
-/// AttributeList - Represents a syntactic attribute.
+/// ParsedAttr - Represents a syntactic attribute.
///
/// For a GNU attribute, there are four forms of this construct:
///
@@ -92,24 +102,31 @@ typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector;
/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
///
-class AttributeList { // TODO: This should really be called ParsedAttribute
+class ParsedAttr { // TODO: This should really be called ParsedAttribute
public:
/// The style used to specify an attribute.
enum Syntax {
/// __attribute__((...))
AS_GNU,
+
/// [[...]]
AS_CXX11,
+
/// [[...]]
AS_C2x,
+
/// __declspec(...)
AS_Declspec,
+
/// [uuid("...")] class Foo
AS_Microsoft,
+
/// __ptr16, alignas(...), etc.
AS_Keyword,
+
/// #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.
@@ -159,17 +176,11 @@ private:
/// A cached value.
mutable unsigned ProcessingCache : 8;
- /// \brief The location of the 'unavailable' keyword in an
+ /// The location of the 'unavailable' keyword in an
/// availability attribute.
SourceLocation UnavailableLoc;
-
- const Expr *MessageExpr;
-
- /// The next attribute in the current position.
- AttributeList *NextInPosition;
- /// The next attribute allocated in the current Pool.
- AttributeList *NextInPool;
+ const Expr *MessageExpr;
/// Arguments, if any, are stored immediately following the object.
ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
@@ -194,83 +205,43 @@ public:
};
struct PropertyData {
IdentifierInfo *GetterId, *SetterId;
+
PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
- : GetterId(getterId), SetterId(setterId) {}
+ : GetterId(getterId), SetterId(setterId) {}
};
private:
- /// Type tag information is stored immediately following the arguments, if
- /// any, at the end of the object. They are mutually exlusive with
- /// availability slots.
- TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
- return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
- }
-
- const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
- return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
- + NumArgs);
- }
-
- /// The type buffer immediately follows the object and are mutually exclusive
- /// with arguments.
- ParsedType &getTypeBuffer() {
- return *reinterpret_cast<ParsedType *>(this + 1);
- }
-
- const ParsedType &getTypeBuffer() const {
- return *reinterpret_cast<const ParsedType *>(this + 1);
- }
-
- /// The property data immediately follows the object is is mutually exclusive
- /// with arguments.
- PropertyData &getPropertyDataBuffer() {
- assert(IsProperty);
- return *reinterpret_cast<PropertyData*>(this + 1);
- }
-
- const PropertyData &getPropertyDataBuffer() const {
- assert(IsProperty);
- return *reinterpret_cast<const PropertyData*>(this + 1);
- }
-
- AttributeList(const AttributeList &) = delete;
- void operator=(const AttributeList &) = delete;
- void operator delete(void *) = delete;
- ~AttributeList() = delete;
-
- size_t allocated_size() const;
+ friend class AttributeFactory;
+ friend class AttributePool;
/// Constructor for attributes with expression arguments.
- AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ArgsUnion *args, unsigned numArgs,
- Syntax syntaxUsed, SourceLocation ellipsisLoc)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
- SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
- IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
- HasParsedType(false), HasProcessingCache(false),
- NextInPosition(nullptr), NextInPool(nullptr) {
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
+ SourceLocation ellipsisLoc)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
+ SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(false), HasProcessingCache(false) {
if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for availability attributes.
- AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Parm, const AvailabilityChange &introduced,
- const AvailabilityChange &deprecated,
- const AvailabilityChange &obsoleted,
- SourceLocation unavailable,
- const Expr *messageExpr,
- Syntax syntaxUsed, SourceLocation strict,
- const Expr *replacementExpr)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
- Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
- IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
- HasProcessingCache(false), UnavailableLoc(unavailable),
- MessageExpr(messageExpr), NextInPosition(nullptr), NextInPool(nullptr) {
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted, SourceLocation unavailable,
+ const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
+ const Expr *replacementExpr)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(true),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), UnavailableLoc(unavailable),
+ MessageExpr(messageExpr) {
ArgsUnion PVal(Parm);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
new (getAvailabilityData()) AvailabilityData(
@@ -279,34 +250,32 @@ private:
}
/// Constructor for objc_bridge_related attributes.
- AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Parm1,
- IdentifierLoc *Parm2,
- IdentifierLoc *Parm3,
- Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),
- Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
- HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) {
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false) {
ArgsUnion *Args = getArgsBuffer();
Args[0] = Parm1;
Args[1] = Parm2;
Args[2] = Parm3;
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
-
+
/// Constructor for type_tag_for_datatype attribute.
- AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *ArgKind, ParsedType matchingCType,
- bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
- Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
- HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) {
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *ArgKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false) {
ArgsUnion PVal(ArgKind);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
@@ -317,37 +286,73 @@ private:
}
/// Constructor for attributes with a single type argument.
- AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ParsedType typeArg, Syntax syntaxUsed)
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg, Syntax syntaxUsed)
: AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
- Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
- HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr){
+ HasProcessingCache(false) {
new (&getTypeBuffer()) ParsedType(typeArg);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for microsoft __declspec(property) attribute.
- AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *getterId, IdentifierInfo *setterId,
- Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
- Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
- HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) {
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
+ HasProcessingCache(false) {
new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
- friend class AttributePool;
- friend class AttributeFactory;
+ /// Type tag information is stored immediately following the arguments, if
+ /// any, at the end of the object. They are mutually exclusive with
+ /// availability slots.
+ TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
+ return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
+ }
+ const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
+ return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
+ + NumArgs);
+ }
+
+ /// The type buffer immediately follows the object and are mutually exclusive
+ /// with arguments.
+ ParsedType &getTypeBuffer() {
+ return *reinterpret_cast<ParsedType *>(this + 1);
+ }
+ const ParsedType &getTypeBuffer() const {
+ return *reinterpret_cast<const ParsedType *>(this + 1);
+ }
+
+ /// The property data immediately follows the object is is mutually exclusive
+ /// with arguments.
+ PropertyData &getPropertyDataBuffer() {
+ assert(IsProperty);
+ return *reinterpret_cast<PropertyData*>(this + 1);
+ }
+ const PropertyData &getPropertyDataBuffer() const {
+ assert(IsProperty);
+ return *reinterpret_cast<const PropertyData*>(this + 1);
+ }
+
+ size_t allocated_size() const;
public:
- enum Kind {
+ ParsedAttr(const ParsedAttr &) = delete;
+ ParsedAttr &operator=(const ParsedAttr &) = delete;
+ ~ParsedAttr() = delete;
+
+ void operator delete(void *) = delete;
+
+ enum Kind {
#define PARSED_ATTR(NAME) AT_##NAME,
#include "clang/Sema/AttrParsedAttrList.inc"
#undef PARSED_ATTR
@@ -358,11 +363,11 @@ public:
IdentifierInfo *getName() const { return AttrName; }
SourceLocation getLoc() const { return AttrRange.getBegin(); }
SourceRange getRange() const { return AttrRange; }
-
+
bool hasScope() const { return ScopeName; }
IdentifierInfo *getScopeName() const { return ScopeName; }
SourceLocation getScopeLoc() const { return ScopeLoc; }
-
+
bool hasParsedType() const { return HasParsedType; }
/// Is this the Microsoft __declspec(property) attribute?
@@ -377,12 +382,15 @@ public:
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
+
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;
}
@@ -395,10 +403,12 @@ public:
void setInvalid(bool b = true) const { Invalid = b; }
bool hasProcessingCache() const { return HasProcessingCache; }
+
unsigned getProcessingCache() const {
assert(hasProcessingCache());
return ProcessingCache;
}
+
void setProcessingCache(unsigned value) const {
ProcessingCache = value;
HasProcessingCache = true;
@@ -414,9 +424,6 @@ public:
static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
Syntax SyntaxUsed);
- AttributeList *getNext() const { return NextInPosition; }
- void setNext(AttributeList *N) { NextInPosition = N; }
-
/// getNumArgs - Return the number of actual arguments to this attribute.
unsigned getNumArgs() const { return NumArgs; }
@@ -429,6 +436,7 @@ public:
bool isArgExpr(unsigned Arg) const {
return Arg < NumArgs && getArg(Arg).is<Expr*>();
}
+
Expr *getArgAsExpr(unsigned Arg) const {
return getArg(Arg).get<Expr*>();
}
@@ -436,6 +444,7 @@ public:
bool isArgIdent(unsigned Arg) const {
return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
}
+
IdentifierLoc *getArgAsIdent(unsigned Arg) const {
return getArg(Arg).get<IdentifierLoc*>();
}
@@ -464,7 +473,7 @@ public:
assert(getKind() == AT_Availability && "Not an availability attribute");
return UnavailableLoc;
}
-
+
const Expr * getMessageExpr() const {
assert(getKind() == AT_Availability && "Not an availability attribute");
return MessageExpr;
@@ -503,7 +512,7 @@ public:
return getPropertyDataBuffer();
}
- /// \brief Get an index into the attribute spelling list
+ /// Get an index into the attribute spelling list
/// defined in Attr.td. This index is used by an attribute
/// to pretty print itself.
unsigned getAttributeSpellingListIndex() const;
@@ -526,7 +535,7 @@ public:
bool isKnownToGCC() const;
bool isSupportedByPragmaAttribute() const;
- /// \brief If the parsed attribute has a semantic equivalent, and it would
+ /// If the parsed attribute has a semantic equivalent, and it would
/// have a semantic Spelling enumeration (due to having semantically-distinct
/// spelling variations), return the value of that semantic spelling. If the
/// parsed attribute does not have a semantic equivalent, or would not have
@@ -534,6 +543,7 @@ public:
unsigned getSemanticSpelling() const;
};
+class AttributePool;
/// A factory, from which one makes pools, from which one creates
/// individual attributes which are deallocated with the pool.
///
@@ -545,18 +555,17 @@ public:
/// The required allocation size of an availability attribute,
/// which we want to ensure is a multiple of sizeof(void*).
AvailabilityAllocSize =
- sizeof(AttributeList)
- + ((sizeof(AvailabilityData) + sizeof(void*) + sizeof(ArgsUnion) - 1)
- / sizeof(void*) * sizeof(void*)),
- TypeTagForDatatypeAllocSize =
- sizeof(AttributeList)
- + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
- sizeof(ArgsUnion) - 1)
- / sizeof(void*) * sizeof(void*),
+ sizeof(ParsedAttr) +
+ ((sizeof(AvailabilityData) + sizeof(void *) + sizeof(ArgsUnion) - 1) /
+ sizeof(void *) * sizeof(void *)),
+ TypeTagForDatatypeAllocSize = sizeof(ParsedAttr) +
+ (sizeof(ParsedAttr::TypeTagForDatatypeData) +
+ sizeof(void *) + sizeof(ArgsUnion) - 1) /
+ sizeof(void *) * sizeof(void *),
PropertyAllocSize =
- sizeof(AttributeList)
- + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
- / sizeof(void*) * sizeof(void*)
+ sizeof(ParsedAttr) +
+ (sizeof(ParsedAttr::PropertyData) + sizeof(void *) - 1) /
+ sizeof(void *) * sizeof(void *)
};
private:
@@ -567,14 +576,14 @@ private:
/// attribute that needs more than that; on x86-64 you'd need 10
/// expression arguments, and on i386 you'd need 19.
InlineFreeListsCapacity =
- 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
+ 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *)
};
llvm::BumpPtrAllocator Alloc;
/// Free lists. The index is determined by the following formula:
- /// (size - sizeof(AttributeList)) / sizeof(void*)
- SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
+ /// (size - sizeof(ParsedAttr)) / sizeof(void*)
+ SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists;
// The following are the private interface used by AttributePool.
friend class AttributePool;
@@ -582,12 +591,14 @@ private:
/// Allocate an attribute of the given size.
void *allocate(size_t size);
+ void deallocate(ParsedAttr *AL);
+
/// Reclaim all the attributes in the given pool chain, which is
/// non-empty. Note that the current implementation is safe
/// against reclaiming things which were not actually allocated
/// with the allocator, although of course it's important to make
/// sure that their allocator lives at least as long as this one.
- void reclaimPool(AttributeList *head);
+ void reclaimPool(AttributePool &head);
public:
AttributeFactory();
@@ -595,294 +606,297 @@ public:
};
class AttributePool {
+ friend class AttributeFactory;
AttributeFactory &Factory;
- AttributeList *Head;
+ llvm::TinyPtrVector<ParsedAttr *> Attrs;
void *allocate(size_t size) {
return Factory.allocate(size);
}
- AttributeList *add(AttributeList *attr) {
- // We don't care about the order of the pool.
- attr->NextInPool = Head;
- Head = attr;
+ ParsedAttr *add(ParsedAttr *attr) {
+ Attrs.push_back(attr);
return attr;
}
- void takePool(AttributeList *pool);
+ void remove(ParsedAttr *attr) {
+ assert(llvm::is_contained(Attrs, attr) &&
+ "Can't take attribute from a pool that doesn't own it!");
+ Attrs.erase(llvm::find(Attrs, attr));
+ }
+
+ void takePool(AttributePool &pool);
public:
/// Create a new pool for a factory.
- AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
+ AttributePool(AttributeFactory &factory) : Factory(factory) {}
AttributePool(const AttributePool &) = delete;
+ ~AttributePool() { Factory.reclaimPool(*this); }
+
/// Move the given pool's allocations to this pool.
- AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) {
- pool.Head = nullptr;
- }
+ AttributePool(AttributePool &&pool) = default;
AttributeFactory &getFactory() const { return Factory; }
void clear() {
- if (Head) {
- Factory.reclaimPool(Head);
- Head = nullptr;
- }
+ Factory.reclaimPool(*this);
+ Attrs.clear();
}
/// Take the given pool's allocations and add them to this pool.
void takeAllFrom(AttributePool &pool) {
- if (pool.Head) {
- takePool(pool.Head);
- pool.Head = nullptr;
- }
- }
-
- ~AttributePool() {
- if (Head) Factory.reclaimPool(Head);
- }
-
- AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ArgsUnion *args, unsigned numArgs,
- AttributeList::Syntax syntax,
- SourceLocation ellipsisLoc = SourceLocation()) {
- void *memory = allocate(sizeof(AttributeList)
- + numArgs * sizeof(ArgsUnion));
- return add(new (memory) AttributeList(attrName, attrRange,
- scopeName, scopeLoc,
- args, numArgs, syntax,
- ellipsisLoc));
- }
-
- AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param,
- const AvailabilityChange &introduced,
- const AvailabilityChange &deprecated,
- const AvailabilityChange &obsoleted,
- SourceLocation unavailable,
- const Expr *MessageExpr,
- AttributeList::Syntax syntax,
- SourceLocation strict, const Expr *ReplacementExpr) {
+ takePool(pool);
+ pool.Attrs.clear();
+ }
+
+ ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ ParsedAttr::Syntax syntax,
+ SourceLocation ellipsisLoc = SourceLocation()) {
+ void *memory = allocate(sizeof(ParsedAttr) + numArgs * sizeof(ArgsUnion));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ args, numArgs, syntax, ellipsisLoc));
+ }
+
+ ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable, const Expr *MessageExpr,
+ ParsedAttr::Syntax syntax, SourceLocation strict,
+ const Expr *ReplacementExpr) {
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
- return add(new (memory) AttributeList(attrName, attrRange,
- scopeName, scopeLoc,
- Param, introduced, deprecated,
- obsoleted, unavailable, MessageExpr,
- syntax, strict, ReplacementExpr));
- }
-
- AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param1,
- IdentifierLoc *Param2,
- IdentifierLoc *Param3,
- AttributeList::Syntax syntax) {
- size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
+ return add(new (memory) ParsedAttr(
+ attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr));
+ }
+
+ ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param1, IdentifierLoc *Param2,
+ IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
+ size_t size = sizeof(ParsedAttr) + 3 * sizeof(ArgsUnion);
void *memory = allocate(size);
- return add(new (memory) AttributeList(attrName, attrRange,
- scopeName, scopeLoc,
- Param1, Param2, Param3,
- syntax));
- }
-
- AttributeList *createTypeTagForDatatype(
- IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *argumentKind, ParsedType matchingCType,
- bool layoutCompatible, bool mustBeNull,
- AttributeList::Syntax syntax) {
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ Param1, Param2, Param3, syntax));
+ }
+
+ ParsedAttr *
+ createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *argumentKind,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, ParsedAttr::Syntax syntax) {
void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
- return add(new (memory) AttributeList(attrName, attrRange,
- scopeName, scopeLoc,
- argumentKind, matchingCType,
- layoutCompatible, mustBeNull,
- syntax));
- }
-
- AttributeList *createTypeAttribute(
- IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
- void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
- return add(new (memory) AttributeList(attrName, attrRange,
- scopeName, scopeLoc,
- typeArg, syntaxUsed));
- }
-
- AttributeList *createPropertyAttribute(
- IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *getterId, IdentifierInfo *setterId,
- AttributeList::Syntax syntaxUsed) {
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ argumentKind, matchingCType,
+ layoutCompatible, mustBeNull, syntax));
+ }
+
+ ParsedAttr *createTypeAttribute(IdentifierInfo *attrName,
+ SourceRange attrRange,
+ IdentifierInfo *scopeName,
+ SourceLocation scopeLoc, ParsedType typeArg,
+ ParsedAttr::Syntax syntaxUsed) {
+ void *memory = allocate(sizeof(ParsedAttr) + sizeof(void *));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ typeArg, syntaxUsed));
+ }
+
+ ParsedAttr *
+ createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ ParsedAttr::Syntax syntaxUsed) {
void *memory = allocate(AttributeFactory::PropertyAllocSize);
- return add(new (memory) AttributeList(attrName, attrRange,
- scopeName, scopeLoc,
- getterId, setterId,
- syntaxUsed));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ getterId, setterId, syntaxUsed));
}
};
-/// ParsedAttributes - A collection of parsed attributes. Currently
-/// we don't differentiate between the various attribute syntaxes,
-/// which is basically silly.
-///
-/// Right now this is a very lightweight container, but the expectation
-/// is that this will become significantly more serious.
-class ParsedAttributes {
+class ParsedAttributesView {
+ using VecTy = llvm::TinyPtrVector<ParsedAttr *>;
+ using SizeType = decltype(std::declval<VecTy>().size());
+
public:
- ParsedAttributes(AttributeFactory &factory)
- : pool(factory), list(nullptr) {
+ bool empty() const { return AttrList.empty(); }
+ SizeType size() const { return AttrList.size(); }
+ ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; }
+ const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; }
+
+ void addAtStart(ParsedAttr *newAttr) {
+ assert(newAttr);
+ AttrList.insert(AttrList.begin(), newAttr);
+ }
+ void addAtEnd(ParsedAttr *newAttr) {
+ assert(newAttr);
+ AttrList.push_back(newAttr);
}
- ParsedAttributes(const ParsedAttributes &) = delete;
+ void remove(ParsedAttr *ToBeRemoved) {
+ assert(is_contained(AttrList, ToBeRemoved) &&
+ "Cannot remove attribute that isn't in the list");
+ AttrList.erase(llvm::find(AttrList, ToBeRemoved));
+ }
- AttributePool &getPool() const { return pool; }
+ void clearListOnly() { AttrList.clear(); }
- bool empty() const { return list == nullptr; }
+ struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator,
+ std::random_access_iterator_tag,
+ ParsedAttr> {
+ iterator() : iterator_adaptor_base(nullptr) {}
+ iterator(VecTy::iterator I) : iterator_adaptor_base(I) {}
+ reference operator*() { return **I; }
+ friend class ParsedAttributesView;
+ };
+ struct const_iterator
+ : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator,
+ std::random_access_iterator_tag,
+ ParsedAttr> {
+ const_iterator() : iterator_adaptor_base(nullptr) {}
+ const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const { return **I; }
+ friend class ParsedAttributesView;
+ };
- void add(AttributeList *newAttr) {
- assert(newAttr);
- assert(newAttr->getNext() == nullptr);
- newAttr->setNext(list);
- list = newAttr;
+ void addAll(iterator B, iterator E) {
+ AttrList.insert(AttrList.begin(), B.I, E.I);
}
- void addAll(AttributeList *newList) {
- if (!newList) return;
-
- AttributeList *lastInNewList = newList;
- while (AttributeList *next = lastInNewList->getNext())
- lastInNewList = next;
+ void addAll(const_iterator B, const_iterator E) {
+ AttrList.insert(AttrList.begin(), B.I, E.I);
+ }
- lastInNewList->setNext(list);
- list = newList;
+ void addAllAtEnd(iterator B, iterator E) {
+ AttrList.insert(AttrList.end(), B.I, E.I);
}
- void addAllAtEnd(AttributeList *newList) {
- if (!list) {
- list = newList;
- return;
- }
+ void addAllAtEnd(const_iterator B, const_iterator E) {
+ AttrList.insert(AttrList.end(), B.I, E.I);
+ }
- AttributeList *lastInList = list;
- while (AttributeList *next = lastInList->getNext())
- lastInList = next;
+ iterator begin() { return iterator(AttrList.begin()); }
+ const_iterator begin() const { return const_iterator(AttrList.begin()); }
+ iterator end() { return iterator(AttrList.end()); }
+ const_iterator end() const { return const_iterator(AttrList.end()); }
- lastInList->setNext(newList);
+ bool hasAttribute(ParsedAttr::Kind K) const {
+ return llvm::any_of(
+ AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; });
}
- void set(AttributeList *newList) {
- list = newList;
- }
+private:
+ VecTy AttrList;
+};
+
+/// ParsedAttributes - A collection of parsed attributes. Currently
+/// we don't differentiate between the various attribute syntaxes,
+/// which is basically silly.
+///
+/// Right now this is a very lightweight container, but the expectation
+/// is that this will become significantly more serious.
+class ParsedAttributes : public ParsedAttributesView {
+public:
+ ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
+ ParsedAttributes(const ParsedAttributes &) = delete;
+
+ AttributePool &getPool() const { return pool; }
void takeAllFrom(ParsedAttributes &attrs) {
- addAll(attrs.list);
- attrs.list = nullptr;
+ addAll(attrs.begin(), attrs.end());
+ attrs.clearListOnly();
pool.takeAllFrom(attrs.pool);
}
- void clear() { list = nullptr; pool.clear(); }
- AttributeList *getList() const { return list; }
-
- void clearListOnly() { list = nullptr; }
-
- /// Returns a reference to the attribute list. Try not to introduce
- /// dependencies on this method, it may not be long-lived.
- AttributeList *&getListRef() { return list; }
+ void clear() {
+ clearListOnly();
+ pool.clear();
+ }
/// Add attribute with expression arguments.
- AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ArgsUnion *args, unsigned numArgs,
- AttributeList::Syntax syntax,
- SourceLocation ellipsisLoc = SourceLocation()) {
- AttributeList *attr =
- pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
- syntax, ellipsisLoc);
- add(attr);
+ ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ ParsedAttr::Syntax syntax,
+ SourceLocation ellipsisLoc = SourceLocation()) {
+ ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
+ args, numArgs, syntax, ellipsisLoc);
+ addAtStart(attr);
return attr;
}
/// Add availability attribute.
- AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param,
- const AvailabilityChange &introduced,
- const AvailabilityChange &deprecated,
- const AvailabilityChange &obsoleted,
- SourceLocation unavailable,
- const Expr *MessageExpr,
- AttributeList::Syntax syntax,
- SourceLocation strict, const Expr *ReplacementExpr) {
- AttributeList *attr =
- pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
- deprecated, obsoleted, unavailable, MessageExpr, syntax,
- strict, ReplacementExpr);
- add(attr);
+ ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable, const Expr *MessageExpr,
+ ParsedAttr::Syntax syntax, SourceLocation strict,
+ const Expr *ReplacementExpr) {
+ ParsedAttr *attr = pool.create(
+ attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr);
+ addAtStart(attr);
return attr;
}
/// Add objc_bridge_related attribute.
- AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param1,
- IdentifierLoc *Param2,
- IdentifierLoc *Param3,
- AttributeList::Syntax syntax) {
- AttributeList *attr =
- pool.create(attrName, attrRange, scopeName, scopeLoc,
- Param1, Param2, Param3, syntax);
- add(attr);
+ ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param1, IdentifierLoc *Param2,
+ IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
+ ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
+ Param1, Param2, Param3, syntax);
+ addAtStart(attr);
return attr;
}
/// Add type_tag_for_datatype attribute.
- AttributeList *addNewTypeTagForDatatype(
- IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *argumentKind, ParsedType matchingCType,
- bool layoutCompatible, bool mustBeNull,
- AttributeList::Syntax syntax) {
- AttributeList *attr =
- pool.createTypeTagForDatatype(attrName, attrRange,
- scopeName, scopeLoc,
- argumentKind, matchingCType,
- layoutCompatible, mustBeNull, syntax);
- add(attr);
+ ParsedAttr *
+ addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *argumentKind,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, ParsedAttr::Syntax syntax) {
+ ParsedAttr *attr = pool.createTypeTagForDatatype(
+ attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
+ layoutCompatible, mustBeNull, syntax);
+ addAtStart(attr);
return attr;
}
/// Add an attribute with a single type argument.
- AttributeList *
- addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
- AttributeList *attr =
- pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
- typeArg, syntaxUsed);
- add(attr);
+ ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg,
+ ParsedAttr::Syntax syntaxUsed) {
+ ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName,
+ scopeLoc, typeArg, syntaxUsed);
+ addAtStart(attr);
return attr;
}
/// Add microsoft __delspec(property) attribute.
- AttributeList *
+ ParsedAttr *
addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *getterId, IdentifierInfo *setterId,
- AttributeList::Syntax syntaxUsed) {
- AttributeList *attr =
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ ParsedAttr::Syntax syntaxUsed) {
+ ParsedAttr *attr =
pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
getterId, setterId, syntaxUsed);
- add(attr);
+ addAtStart(attr);
return attr;
}
private:
mutable AttributePool pool;
- AttributeList *list;
};
/// These constants match the enumerated choices of
@@ -910,9 +924,8 @@ enum AttributeDeclKind {
ExpectedFunctionVariableOrClass,
ExpectedKernelFunction,
ExpectedFunctionWithProtoType,
- ExpectedForMaybeUnused,
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
index 01a4ab3f37a5..258b2291d260 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
@@ -25,131 +25,131 @@
#include <cstdlib>
#include <new>
-namespace clang {
- /// \brief Represents the parsed form of a C++ template argument.
+namespace clang {
+ /// Represents the parsed form of a C++ template argument.
class ParsedTemplateArgument {
public:
- /// \brief Describes the kind of template argument that was parsed.
+ /// Describes the kind of template argument that was parsed.
enum KindType {
- /// \brief A template type parameter, stored as a type.
+ /// A template type parameter, stored as a type.
Type,
- /// \brief A non-type template parameter, stored as an expression.
+ /// A non-type template parameter, stored as an expression.
NonType,
- /// \brief A template template argument, stored as a template name.
+ /// A template template argument, stored as a template name.
Template
};
- /// \brief Build an empty template argument.
+ /// Build an empty template argument.
///
/// This template argument is invalid.
ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
-
- /// \brief Create a template type argument or non-type template argument.
+
+ /// Create a template type argument or non-type template argument.
///
/// \param Arg the template type argument or non-type template argument.
/// \param Loc the location of the type.
ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
: Kind(Kind), Arg(Arg), Loc(Loc) { }
-
- /// \brief Create a template template argument.
+
+ /// Create a template template argument.
///
/// \param SS the C++ scope specifier that precedes the template name, if
/// any.
///
- /// \param Template the template to which this template template
+ /// \param Template the template to which this template template
/// argument refers.
///
/// \param TemplateLoc the location of the template name.
ParsedTemplateArgument(const CXXScopeSpec &SS,
- ParsedTemplateTy Template,
- SourceLocation TemplateLoc)
+ ParsedTemplateTy Template,
+ SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template),
- Arg(Template.getAsOpaquePtr()),
+ Arg(Template.getAsOpaquePtr()),
SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
-
- /// \brief Determine whether the given template argument is invalid.
+
+ /// Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == nullptr; }
-
- /// \brief Determine what kind of template argument we have.
+
+ /// Determine what kind of template argument we have.
KindType getKind() const { return Kind; }
-
- /// \brief Retrieve the template type argument's type.
+
+ /// Retrieve the template type argument's type.
ParsedType getAsType() const {
assert(Kind == Type && "Not a template type argument");
return ParsedType::getFromOpaquePtr(Arg);
}
-
- /// \brief Retrieve the non-type template argument's expression.
+
+ /// Retrieve the non-type template argument's expression.
Expr *getAsExpr() const {
assert(Kind == NonType && "Not a non-type template argument");
return static_cast<Expr*>(Arg);
}
-
- /// \brief Retrieve the template template argument's template name.
+
+ /// Retrieve the template template argument's template name.
ParsedTemplateTy getAsTemplate() const {
assert(Kind == Template && "Not a template template argument");
return ParsedTemplateTy::getFromOpaquePtr(Arg);
}
-
- /// \brief Retrieve the location of the template argument.
+
+ /// Retrieve the location of the template argument.
SourceLocation getLocation() const { return Loc; }
-
- /// \brief Retrieve the nested-name-specifier that precedes the template
+
+ /// Retrieve the nested-name-specifier that precedes the template
/// name in a template template argument.
const CXXScopeSpec &getScopeSpec() const {
- assert(Kind == Template &&
+ assert(Kind == Template &&
"Only template template arguments can have a scope specifier");
return SS;
}
-
- /// \brief Retrieve the location of the ellipsis that makes a template
+
+ /// Retrieve the location of the ellipsis that makes a template
/// template argument into a pack expansion.
SourceLocation getEllipsisLoc() const {
- assert(Kind == Template &&
+ assert(Kind == Template &&
"Only template template arguments can have an ellipsis");
return EllipsisLoc;
}
-
- /// \brief Retrieve a pack expansion of the given template template
+
+ /// Retrieve a pack expansion of the given template template
/// argument.
///
/// \param EllipsisLoc The location of the ellipsis.
ParsedTemplateArgument getTemplatePackExpansion(
SourceLocation EllipsisLoc) const;
-
+
private:
KindType Kind;
-
- /// \brief The actual template argument representation, which may be
+
+ /// The actual template argument representation, which may be
/// an \c Sema::TypeTy* (for a type), an Expr* (for an
/// expression), or an Sema::TemplateTy (for a template).
void *Arg;
- /// \brief The nested-name-specifier that can accompany a template template
+ /// The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
- /// \brief the location of the template argument.
+ /// the location of the template argument.
SourceLocation Loc;
- /// \brief The ellipsis location that can accompany a template template
+ /// The ellipsis location that can accompany a template template
/// argument (turning it into a template template argument expansion).
SourceLocation EllipsisLoc;
};
-
- /// \brief Information about a template-id annotation
+
+ /// Information about a template-id annotation
/// token.
///
- /// A template-id annotation token contains the template declaration,
- /// template arguments, whether those template arguments were types,
- /// expressions, or template names, and the source locations for important
- /// tokens. All of the information about template arguments is allocated
+ /// A template-id annotation token contains the template declaration,
+ /// template arguments, whether those template arguments were types,
+ /// expressions, or template names, and the source locations for important
+ /// tokens. All of the information about template arguments is allocated
/// directly after this structure.
struct TemplateIdAnnotation final
: private llvm::TrailingObjects<TemplateIdAnnotation,
ParsedTemplateArgument> {
friend TrailingObjects;
- /// \brief The nested-name-specifier that precedes the template name.
+ /// The nested-name-specifier that precedes the template name.
CXXScopeSpec SS;
/// TemplateKWLoc - The location of the template keyword.
@@ -159,37 +159,37 @@ namespace clang {
/// TemplateNameLoc - The location of the template name within the
/// source.
SourceLocation TemplateNameLoc;
-
+
/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
-
+
/// FIXME: Temporarily stores the overloaded operator kind.
OverloadedOperatorKind Operator;
-
+
/// The declaration of the template corresponding to the
/// template-name.
ParsedTemplateTy Template;
-
+
/// The kind of template that Template refers to.
TemplateNameKind Kind;
-
+
/// The location of the '<' before the template argument
/// list.
SourceLocation LAngleLoc;
-
+
/// The location of the '>' after the template argument
/// list.
SourceLocation RAngleLoc;
-
+
/// NumArgs - The number of template arguments.
unsigned NumArgs;
-
- /// \brief Retrieves a pointer to the template arguments
- ParsedTemplateArgument *getTemplateArgs() {
- return getTrailingObjects<ParsedTemplateArgument>();
+
+ /// Retrieves a pointer to the template arguments
+ ParsedTemplateArgument *getTemplateArgs() {
+ return getTrailingObjects<ParsedTemplateArgument>();
}
- /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
+ /// Creates a new TemplateIdAnnotation with NumArgs arguments and
/// appends it to List.
static TemplateIdAnnotation *
Create(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
@@ -199,8 +199,7 @@ namespace clang {
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs,
SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
-
- TemplateIdAnnotation *TemplateId = new (std::malloc(
+ TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name,
OperatorKind, OpaqueTemplateName, TemplateKind,
@@ -214,7 +213,7 @@ namespace clang {
getTemplateArgs(), getTemplateArgs() + NumArgs,
[](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); });
this->~TemplateIdAnnotation();
- free(this);
+ free(this);
}
private:
TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
@@ -240,7 +239,7 @@ namespace clang {
/// Retrieves the range of the given template parameter lists.
SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
- unsigned NumParams);
+ unsigned NumParams);
} // end namespace clang
#endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
index cd58a9910f98..11fa0362124b 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
@@ -1,4 +1,4 @@
-//===--- Scope.h - Scope interface ------------------------------*- C++ -*-===//
+//===- Scope.h - Scope interface --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,101 +14,102 @@
#ifndef LLVM_CLANG_SEMA_SCOPE_H
#define LLVM_CLANG_SEMA_SCOPE_H
-#include "clang/AST/Decl.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include <cassert>
namespace llvm {
class raw_ostream;
-}
+} // namespace llvm
namespace clang {
class Decl;
+class DeclContext;
class UsingDirectiveDecl;
class VarDecl;
/// Scope - A scope is a transient data structure that is used while parsing the
/// program. It assists with resolving identifiers to the appropriate
/// declaration.
-///
class Scope {
public:
/// ScopeFlags - These are bitfields that are or'd together when creating a
/// scope, which defines the sorts of things the scope contains.
enum ScopeFlags {
- /// \brief This indicates that the scope corresponds to a function, which
+ /// This indicates that the scope corresponds to a function, which
/// means that labels are set here.
FnScope = 0x01,
- /// \brief This is a while, do, switch, for, etc that can have break
+ /// This is a while, do, switch, for, etc that can have break
/// statements embedded into it.
BreakScope = 0x02,
- /// \brief This is a while, do, for, which can have continue statements
+ /// This is a while, do, for, which can have continue statements
/// embedded into it.
ContinueScope = 0x04,
- /// \brief This is a scope that can contain a declaration. Some scopes
+ /// This is a scope that can contain a declaration. Some scopes
/// just contain loop constructs but don't contain decls.
DeclScope = 0x08,
- /// \brief The controlling scope in a if/switch/while/for statement.
+ /// The controlling scope in a if/switch/while/for statement.
ControlScope = 0x10,
- /// \brief The scope of a struct/union/class definition.
+ /// The scope of a struct/union/class definition.
ClassScope = 0x20,
- /// \brief This is a scope that corresponds to a block/closure object.
+ /// This is a scope that corresponds to a block/closure object.
/// Blocks serve as top-level scopes for some objects like labels, they
/// also prevent things like break and continue. BlockScopes always have
/// the FnScope and DeclScope flags set as well.
BlockScope = 0x40,
- /// \brief This is a scope that corresponds to the
+ /// This is a scope that corresponds to the
/// template parameters of a C++ template. Template parameter
/// scope starts at the 'template' keyword and ends when the
/// template declaration ends.
TemplateParamScope = 0x80,
- /// \brief This is a scope that corresponds to the
+ /// This is a scope that corresponds to the
/// parameters within a function prototype.
FunctionPrototypeScope = 0x100,
- /// \brief This is a scope that corresponds to the parameters within
+ /// This is a scope that corresponds to the parameters within
/// a function prototype for a function declaration (as opposed to any
/// other kind of function declarator). Always has FunctionPrototypeScope
/// set as well.
FunctionDeclarationScope = 0x200,
- /// \brief This is a scope that corresponds to the Objective-C
+ /// This is a scope that corresponds to the Objective-C
/// \@catch statement.
AtCatchScope = 0x400,
-
- /// \brief This scope corresponds to an Objective-C method body.
+
+ /// This scope corresponds to an Objective-C method body.
/// It always has FnScope and DeclScope set as well.
ObjCMethodScope = 0x800,
- /// \brief This is a scope that corresponds to a switch statement.
+ /// This is a scope that corresponds to a switch statement.
SwitchScope = 0x1000,
- /// \brief This is the scope of a C++ try statement.
+ /// This is the scope of a C++ try statement.
TryScope = 0x2000,
- /// \brief This is the scope for a function-level C++ try or catch scope.
+ /// This is the scope for a function-level C++ try or catch scope.
FnTryCatchScope = 0x4000,
- /// \brief This is the scope of OpenMP executable directive.
+ /// This is the scope of OpenMP executable directive.
OpenMPDirectiveScope = 0x8000,
- /// \brief This is the scope of some OpenMP loop directive.
+ /// This is the scope of some OpenMP loop directive.
OpenMPLoopDirectiveScope = 0x10000,
- /// \brief This is the scope of some OpenMP simd directive.
+ /// This is the scope of some OpenMP simd directive.
/// For example, it is used for 'omp simd', 'omp for simd'.
/// This flag is propagated to children scopes.
OpenMPSimdDirectiveScope = 0x20000,
@@ -131,6 +132,7 @@ public:
/// 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
/// scope.
@@ -144,7 +146,7 @@ private:
/// depth 0.
unsigned short Depth;
- /// \brief Declarations with static linkage are mangled with the number of
+ /// Declarations with static linkage are mangled with the number of
/// scopes seen as a component.
unsigned short MSLastManglingNumber;
@@ -185,7 +187,7 @@ private:
/// popped, these declarations are removed from the IdentifierTable's notion
/// of current declaration. It is up to the current Action implementation to
/// implement these semantics.
- typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy;
+ using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>;
DeclSetTy DeclsInScope;
/// The DeclContext with which this scope is associated. For
@@ -193,10 +195,10 @@ private:
/// entity of a function scope is a function, etc.
DeclContext *Entity;
- typedef SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
+ using UsingDirectivesTy = SmallVector<UsingDirectiveDecl *, 2>;
UsingDirectivesTy UsingDirectives;
- /// \brief Used to determine if errors occurred in this scope.
+ /// Used to determine if errors occurred in this scope.
DiagnosticErrorTrap ErrorTrap;
/// A lattice consisting of undefined, a single NRVO candidate variable in
@@ -207,25 +209,23 @@ private:
public:
Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag)
- : ErrorTrap(Diag) {
+ : ErrorTrap(Diag) {
Init(Parent, ScopeFlags);
}
/// getFlags - Return the flags for this scope.
- ///
unsigned getFlags() const { return Flags; }
+
void setFlags(unsigned F) { setFlags(getParent(), F); }
/// isBlockScope - Return true if this scope correspond to a closure.
bool isBlockScope() const { return Flags & BlockScope; }
/// getParent - Return the scope that this is nested in.
- ///
const Scope *getParent() const { return AnyParent; }
Scope *getParent() { return AnyParent; }
/// getFnParent - Return the closest scope that is a function body.
- ///
const Scope *getFnParent() const { return FnParent; }
Scope *getFnParent() { return FnParent; }
@@ -259,6 +259,9 @@ public:
Scope *getTemplateParamParent() { return TemplateParamParent; }
const Scope *getTemplateParamParent() const { return TemplateParamParent; }
+ /// Returns the depth of this scope. The translation-unit has scope depth 0.
+ unsigned getDepth() const { return Depth; }
+
/// Returns the number of function prototype scopes in this scope
/// chain.
unsigned getFunctionPrototypeDepth() const {
@@ -272,10 +275,12 @@ public:
return PrototypeIndex++;
}
- typedef llvm::iterator_range<DeclSetTy::iterator> decl_range;
+ using decl_range = llvm::iterator_range<DeclSetTy::iterator>;
+
decl_range decls() const {
return decl_range(DeclsInScope.begin(), DeclsInScope.end());
}
+
bool decl_empty() const { return DeclsInScope.empty(); }
void AddDecl(Decl *D) {
@@ -342,7 +347,7 @@ public:
}
return false;
}
-
+
/// isInObjcMethodScope - Return true if this scope is, or is contained in, an
/// Objective-C method body. Note that this method is not constant time.
bool isInObjcMethodScope() const {
@@ -365,7 +370,6 @@ public:
return false;
}
-
/// isTemplateParamScope - Return true if this scope is a C++
/// template parameter scope.
bool isTemplateParamScope() const {
@@ -397,12 +401,12 @@ public:
return false;
}
- /// \brief Determines whether this scope is the OpenMP directive scope
+ /// Determines whether this scope is the OpenMP directive scope
bool isOpenMPDirectiveScope() const {
return (getFlags() & Scope::OpenMPDirectiveScope);
}
- /// \brief Determine whether this scope is some OpenMP loop directive scope
+ /// Determine whether this scope is some OpenMP loop directive scope
/// (for example, 'omp for', 'omp simd').
bool isOpenMPLoopDirectiveScope() const {
if (getFlags() & Scope::OpenMPLoopDirectiveScope) {
@@ -413,34 +417,34 @@ public:
return false;
}
- /// \brief Determine whether this scope is (or is nested into) some OpenMP
+ /// Determine whether this scope is (or is nested into) some OpenMP
/// loop simd directive scope (for example, 'omp simd', 'omp for simd').
bool isOpenMPSimdDirectiveScope() const {
return getFlags() & Scope::OpenMPSimdDirectiveScope;
}
- /// \brief Determine whether this scope is a loop having OpenMP loop
+ /// Determine whether this scope is a loop having OpenMP loop
/// directive attached.
bool isOpenMPLoopScope() const {
const Scope *P = getParent();
return P && P->isOpenMPLoopDirectiveScope();
}
- /// \brief Determine whether this scope is a C++ 'try' block.
+ /// Determine whether this scope is a C++ 'try' block.
bool isTryScope() const { return getFlags() & Scope::TryScope; }
- /// \brief Determine whether this scope is a SEH '__try' block.
+ /// Determine whether this scope is a SEH '__try' block.
bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; }
- /// \brief Determine whether this scope is a SEH '__except' block.
+ /// 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.
+ /// 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.
+ /// Returns if rhs has a higher scope depth than this.
///
/// The caller is responsible for calling this only if one of the two scopes
/// is an ancestor of the other.
@@ -454,8 +458,8 @@ public:
UsingDirectives.push_back(UDir);
}
- typedef llvm::iterator_range<UsingDirectivesTy::iterator>
- using_directives_range;
+ using using_directives_range =
+ llvm::iterator_range<UsingDirectivesTy::iterator>;
using_directives_range using_directives() {
return using_directives_range(UsingDirectives.begin(),
@@ -474,25 +478,23 @@ public:
}
void setNoNRVO() {
- NRVO.setInt(1);
+ NRVO.setInt(true);
NRVO.setPointer(nullptr);
}
void mergeNRVOIntoParent();
/// Init - This is used by the parser to implement scope caching.
- ///
void Init(Scope *parent, unsigned flags);
- /// \brief Sets up the specified scope flags and adjusts the scope state
+ /// Sets up the specified scope flags and adjusts the scope state
/// variables accordingly.
- ///
void AddFlags(unsigned Flags);
void dumpImpl(raw_ostream &OS) const;
void dump() const;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_SCOPE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
index c707a3e8ef07..5925fd6ccead 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -1,4 +1,4 @@
-//===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===//
+//===- ScopeInfo.h - Information about a semantic context -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,48 +18,62 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/CleanupInfo.h"
-#include "clang/Sema/Ownership.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
+#include <cassert>
+#include <utility>
namespace clang {
-class Decl;
class BlockDecl;
class CapturedDecl;
class CXXMethodDecl;
-class FieldDecl;
-class ObjCPropertyDecl;
-class IdentifierInfo;
+class CXXRecordDecl;
class ImplicitParamDecl;
-class LabelDecl;
+class NamedDecl;
+class ObjCIvarRefExpr;
+class ObjCMessageExpr;
+class ObjCPropertyDecl;
+class ObjCPropertyRefExpr;
+class ParmVarDecl;
+class RecordDecl;
class ReturnStmt;
class Scope;
+class Stmt;
class SwitchStmt;
-class TemplateTypeParmDecl;
class TemplateParameterList;
+class TemplateTypeParmDecl;
class VarDecl;
-class ObjCIvarRefExpr;
-class ObjCPropertyRefExpr;
-class ObjCMessageExpr;
namespace sema {
-/// \brief Contains information about the compound statement currently being
+/// Contains information about the compound statement currently being
/// parsed.
class CompoundScopeInfo {
public:
- CompoundScopeInfo()
- : HasEmptyLoopBodies(false) { }
-
- /// \brief Whether this compound stamement contains `for' or `while' loops
+ /// Whether this compound stamement contains `for' or `while' loops
/// with empty bodies.
- bool HasEmptyLoopBodies;
+ bool HasEmptyLoopBodies = false;
+
+ /// Whether this compound statement corresponds to a GNU statement
+ /// expression.
+ bool IsStmtExpr;
+
+ CompoundScopeInfo(bool IsStmtExpr) : IsStmtExpr(IsStmtExpr) {}
void setHasEmptyLoopBodies() {
HasEmptyLoopBodies = true;
@@ -71,13 +85,13 @@ public:
PartialDiagnostic PD;
SourceLocation Loc;
const Stmt *stmt;
-
+
PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
const Stmt *stmt)
- : PD(PD), Loc(Loc), stmt(stmt) {}
+ : PD(PD), Loc(Loc), stmt(stmt) {}
};
-
-/// \brief Retains information about a function, method, or block that is
+
+/// Retains information about a function, method, or block that is
/// currently being parsed.
class FunctionScopeInfo {
protected:
@@ -87,32 +101,31 @@ protected:
SK_Lambda,
SK_CapturedRegion
};
-
+
public:
- /// \brief What kind of scope we are describing.
- ///
+ /// What kind of scope we are describing.
ScopeKind Kind : 3;
- /// \brief Whether this function contains a VLA, \@try, try, C++
+ /// Whether this function contains a VLA, \@try, try, C++
/// initializer, or anything else that can't be jumped past.
bool HasBranchProtectedScope : 1;
- /// \brief Whether this function contains any switches or direct gotos.
+ /// Whether this function contains any switches or direct gotos.
bool HasBranchIntoScope : 1;
- /// \brief Whether this function contains any indirect gotos.
+ /// Whether this function contains any indirect gotos.
bool HasIndirectGoto : 1;
- /// \brief Whether a statement was dropped because it was invalid.
+ /// Whether a statement was dropped because it was invalid.
bool HasDroppedStmt : 1;
- /// \brief True if current scope is for OpenMP declare reduction combiner.
+ /// True if current scope is for OpenMP declare reduction combiner.
bool HasOMPDeclareReductionCombiner : 1;
- /// \brief Whether there is a fallthrough statement in this function.
+ /// Whether there is a fallthrough statement in this function.
bool HasFallthroughStmt : 1;
- /// \brief Whether we make reference to a declaration that could be
+ /// Whether we make reference to a declaration that could be
/// unavailable.
bool HasPotentialAvailabilityViolations : 1;
@@ -123,6 +136,7 @@ public:
/// True when this is a method marked as a designated initializer.
bool ObjCIsDesignatedInit : 1;
+
/// This starts true for a method marked as designated initializer and will
/// be set to false if there is an invocation to a designated initializer of
/// the super class.
@@ -132,15 +146,16 @@ public:
/// initializer within a class that has at least one initializer marked as a
/// designated initializer.
bool ObjCIsSecondaryInit : 1;
+
/// This starts true for a secondary initializer method and will be set to
/// false if there is an invocation of an initializer on 'self'.
bool ObjCWarnForNoInitDelegation : 1;
- /// \brief True only when this function has not already built, or attempted
+ /// True only when this function has not already built, or attempted
/// to build, the initial and final coroutine suspend points
bool NeedsCoroutineSuspends : 1;
- /// \brief An enumeration represeting the kind of the first coroutine statement
+ /// An enumeration represeting the kind of the first coroutine statement
/// in the function. One of co_return, co_await, or co_yield.
unsigned char FirstCoroutineStmtKind : 2;
@@ -157,36 +172,44 @@ public:
/// First SEH '__try' statement in the current function.
SourceLocation FirstSEHTryLoc;
- /// \brief Used to determine if errors occurred in this function or block.
+ /// Used to determine if errors occurred in this function or block.
DiagnosticErrorTrap ErrorTrap;
+ /// A SwitchStmt, along with a flag indicating if its list of case statements
+ /// is incomplete (because we dropped an invalid one while parsing).
+ using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>;
+
/// SwitchStack - This is the current set of active switch statements in the
/// block.
- SmallVector<SwitchStmt*, 8> SwitchStack;
+ SmallVector<SwitchInfo, 8> SwitchStack;
- /// \brief The list of return statements that occur within the function or
+ /// The list of return statements that occur within the function or
/// block, if there is any chance of applying the named return value
/// optimization, or if we need to infer a return type.
SmallVector<ReturnStmt*, 4> Returns;
- /// \brief The promise object for this coroutine, if any.
+ /// The promise object for this coroutine, if any.
VarDecl *CoroutinePromise = nullptr;
- /// \brief The initial and final coroutine suspend points.
+ /// A mapping between the coroutine function parameters that were moved
+ /// to the coroutine frame, and their move statements.
+ llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves;
+
+ /// The initial and final coroutine suspend points.
std::pair<Stmt *, Stmt *> CoroutineSuspends;
- /// \brief The stack of currently active compound stamement scopes in the
+ /// The stack of currently active compound stamement scopes in the
/// function.
SmallVector<CompoundScopeInfo, 4> CompoundScopes;
- /// \brief A list of PartialDiagnostics created but delayed within the
+ /// A list of PartialDiagnostics created but delayed within the
/// current function scope. These diagnostics are vetted for reachability
/// prior to being emitted.
SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
-
- /// \brief A list of parameters which have the nonnull attribute and are
+
+ /// A list of parameters which have the nonnull attribute and are
/// modified in the function.
- llvm::SmallPtrSet<const ParmVarDecl*, 8> ModifiedNonNullParams;
+ llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams;
public:
/// Represents a simple identification of a weak object.
@@ -218,14 +241,14 @@ public:
/// identify the object in memory.
///
/// \sa isExactProfile()
- typedef llvm::PointerIntPair<const NamedDecl *, 1, bool> BaseInfoTy;
+ using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>;
BaseInfoTy Base;
/// The "property" decl, as described in the class documentation.
///
/// Note that this may not actually be an ObjCPropertyDecl, e.g. in the
/// case of "implicit" properties (regular methods accessed via dot syntax).
- const NamedDecl *Property;
+ const NamedDecl *Property = nullptr;
/// Used to find the proper base profile for a given base expression.
static BaseInfoTy getBaseInfo(const Expr *BaseE);
@@ -270,12 +293,14 @@ public:
static inline WeakObjectProfileTy getEmptyKey() {
return WeakObjectProfileTy();
}
+
static inline WeakObjectProfileTy getTombstoneKey() {
return WeakObjectProfileTy::getSentinel();
}
static unsigned getHashValue(const WeakObjectProfileTy &Val) {
- typedef std::pair<BaseInfoTy, const NamedDecl *> Pair;
+ using Pair = std::pair<BaseInfoTy, const NamedDecl *>;
+
return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base,
Val.Property));
}
@@ -295,6 +320,7 @@ public:
/// Part of the implementation of -Wrepeated-use-of-weak.
class WeakUseTy {
llvm::PointerIntPair<const Expr *, 1, bool> Rep;
+
public:
WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {}
@@ -310,14 +336,14 @@ public:
/// Used to collect uses of a particular weak object in a function body.
///
/// Part of the implementation of -Wrepeated-use-of-weak.
- typedef SmallVector<WeakUseTy, 4> WeakUseVector;
+ using WeakUseVector = SmallVector<WeakUseTy, 4>;
/// Used to collect all uses of weak objects in a function body.
///
/// Part of the implementation of -Wrepeated-use-of-weak.
- typedef llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
- WeakObjectProfileTy::DenseMapInfo>
- WeakObjectUseMap;
+ using WeakObjectUseMap =
+ llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
+ WeakObjectProfileTy::DenseMapInfo>;
private:
/// Used to collect all uses of weak objects in this function body.
@@ -329,6 +355,18 @@ protected:
FunctionScopeInfo(const FunctionScopeInfo&) = default;
public:
+ FunctionScopeInfo(DiagnosticsEngine &Diag)
+ : Kind(SK_Function), HasBranchProtectedScope(false),
+ HasBranchIntoScope(false), HasIndirectGoto(false),
+ HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false),
+ HasFallthroughStmt(false), HasPotentialAvailabilityViolations(false),
+ ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false),
+ ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false),
+ ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true),
+ ErrorTrap(Diag) {}
+
+ virtual ~FunctionScopeInfo();
+
/// Record that a weak object was accessed.
///
/// Part of the implementation of -Wrepeated-use-of-weak.
@@ -430,30 +468,137 @@ public:
CoroutineSuspends.second = Final;
}
- FunctionScopeInfo(DiagnosticsEngine &Diag)
- : Kind(SK_Function),
- HasBranchProtectedScope(false),
- HasBranchIntoScope(false),
- HasIndirectGoto(false),
- HasDroppedStmt(false),
- HasOMPDeclareReductionCombiner(false),
- HasFallthroughStmt(false),
- HasPotentialAvailabilityViolations(false),
- ObjCShouldCallSuper(false),
- ObjCIsDesignatedInit(false),
- ObjCWarnForNoDesignatedInitChain(false),
- ObjCIsSecondaryInit(false),
- ObjCWarnForNoInitDelegation(false),
- NeedsCoroutineSuspends(true),
- ErrorTrap(Diag) { }
-
- virtual ~FunctionScopeInfo();
-
- /// \brief Clear out the information in this function scope, making it
+ /// Clear out the information in this function scope, making it
/// suitable for reuse.
void Clear();
};
+class Capture {
+ // There are three categories of capture: capturing 'this', capturing
+ // local variables, and C++1y initialized captures (which can have an
+ // arbitrary initializer, and don't really capture in the traditional
+ // sense at all).
+ //
+ // There are three ways to capture a local variable:
+ // - capture by copy in the C++11 sense,
+ // - capture by reference in the C++11 sense, and
+ // - __block capture.
+ // Lambdas explicitly specify capture by copy or capture by reference.
+ // For blocks, __block capture applies to variables with that annotation,
+ // variables of reference type are captured by reference, and other
+ // variables are captured by copy.
+ enum CaptureKind {
+ Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
+ };
+ enum {
+ IsNestedCapture = 0x1,
+ IsThisCaptured = 0x2
+ };
+
+ /// The variable being captured (if we are not capturing 'this') and whether
+ /// this is a nested capture, and whether we are capturing 'this'
+ llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis;
+
+ /// Expression to initialize a field of the given type, and the kind of
+ /// capture (if this is a capture and not an init-capture). The expression
+ /// is only required if we are capturing ByVal and the variable's type has
+ /// a non-trivial copy constructor.
+ llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
+
+ /// The source location at which the first capture occurred.
+ SourceLocation Loc;
+
+ /// The location of the ellipsis that expands a parameter pack.
+ SourceLocation EllipsisLoc;
+
+ /// The type as it was captured, which is in effect the type of the
+ /// non-static data member that would hold the capture.
+ QualType CaptureType;
+
+ /// Whether an explicit capture has been odr-used in the body of the
+ /// lambda.
+ bool ODRUsed = false;
+
+ /// Whether an explicit capture has been non-odr-used in the body of
+ /// the lambda.
+ bool NonODRUsed = false;
+
+public:
+ Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, Expr *Cpy)
+ : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0),
+ InitExprAndCaptureKind(
+ Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
+ : Cap_ByCopy),
+ Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
+
+ enum IsThisCapture { ThisCapture };
+ Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
+ QualType CaptureType, Expr *Cpy, const bool ByCopy)
+ : VarAndNestedAndThis(
+ nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),
+ InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
+ Loc(Loc), CaptureType(CaptureType) {}
+
+ bool isThisCapture() const {
+ return VarAndNestedAndThis.getInt() & IsThisCaptured;
+ }
+
+ bool isVariableCapture() const {
+ return !isThisCapture() && !isVLATypeCapture();
+ }
+
+ bool isCopyCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
+ }
+
+ bool isReferenceCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByRef;
+ }
+
+ bool isBlockCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_Block;
+ }
+
+ bool isVLATypeCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_VLA;
+ }
+
+ bool isNested() const {
+ return VarAndNestedAndThis.getInt() & IsNestedCapture;
+ }
+
+ bool isODRUsed() const { return ODRUsed; }
+ bool isNonODRUsed() const { return NonODRUsed; }
+ void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
+
+ VarDecl *getVariable() const {
+ assert(isVariableCapture());
+ return VarAndNestedAndThis.getPointer();
+ }
+
+ /// Retrieve the location at which this variable was captured.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// Retrieve the source location of the ellipsis, whose presence
+ /// indicates that the capture is a pack expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// Retrieve the capture type for this capture, which is effectively
+ /// the type of the non-static data member in the lambda/block structure
+ /// that would store this capture.
+ QualType getCaptureType() const {
+ assert(!isThisCapture());
+ return CaptureType;
+ }
+
+ Expr *getInitExpr() const {
+ assert(!isVLATypeCapture() && "no init expression for type capture");
+ return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
+ }
+};
+
class CapturingScopeInfo : public FunctionScopeInfo {
protected:
CapturingScopeInfo(const CapturingScopeInfo&) = default;
@@ -466,152 +611,31 @@ public:
ImplicitCaptureStyle ImpCaptureStyle;
- class Capture {
- // There are three categories of capture: capturing 'this', capturing
- // local variables, and C++1y initialized captures (which can have an
- // arbitrary initializer, and don't really capture in the traditional
- // sense at all).
- //
- // There are three ways to capture a local variable:
- // - capture by copy in the C++11 sense,
- // - capture by reference in the C++11 sense, and
- // - __block capture.
- // Lambdas explicitly specify capture by copy or capture by reference.
- // For blocks, __block capture applies to variables with that annotation,
- // variables of reference type are captured by reference, and other
- // variables are captured by copy.
- enum CaptureKind {
- Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
- };
- enum {
- IsNestedCapture = 0x1,
- IsThisCaptured = 0x2
- };
- /// The variable being captured (if we are not capturing 'this') and whether
- /// this is a nested capture, and whether we are capturing 'this'
- llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis;
- /// Expression to initialize a field of the given type, and the kind of
- /// capture (if this is a capture and not an init-capture). The expression
- /// is only required if we are capturing ByVal and the variable's type has
- /// a non-trivial copy constructor.
- llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
-
- /// \brief The source location at which the first capture occurred.
- SourceLocation Loc;
-
- /// \brief The location of the ellipsis that expands a parameter pack.
- SourceLocation EllipsisLoc;
-
- /// \brief The type as it was captured, which is in effect the type of the
- /// non-static data member that would hold the capture.
- QualType CaptureType;
-
- /// \brief Whether an explicit capture has been odr-used in the body of the
- /// lambda.
- bool ODRUsed;
-
- /// \brief Whether an explicit capture has been non-odr-used in the body of
- /// the lambda.
- bool NonODRUsed;
-
- public:
- Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
- SourceLocation Loc, SourceLocation EllipsisLoc,
- QualType CaptureType, Expr *Cpy)
- : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0),
- InitExprAndCaptureKind(
- Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
- : Cap_ByCopy),
- Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType),
- ODRUsed(false), NonODRUsed(false) {}
-
- enum IsThisCapture { ThisCapture };
- Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
- QualType CaptureType, Expr *Cpy, const bool ByCopy)
- : VarAndNestedAndThis(
- nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),
- InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
- Loc(Loc), EllipsisLoc(), CaptureType(CaptureType), ODRUsed(false),
- NonODRUsed(false) {}
-
- bool isThisCapture() const {
- return VarAndNestedAndThis.getInt() & IsThisCaptured;
- }
- bool isVariableCapture() const {
- return !isThisCapture() && !isVLATypeCapture();
- }
- bool isCopyCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
- }
- bool isReferenceCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_ByRef;
- }
- bool isBlockCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_Block;
- }
- bool isVLATypeCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_VLA;
- }
- bool isNested() const {
- return VarAndNestedAndThis.getInt() & IsNestedCapture;
- }
- bool isODRUsed() const { return ODRUsed; }
- bool isNonODRUsed() const { return NonODRUsed; }
- void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
-
- VarDecl *getVariable() const {
- assert(isVariableCapture());
- return VarAndNestedAndThis.getPointer();
- }
-
- /// \brief Retrieve the location at which this variable was captured.
- SourceLocation getLocation() const { return Loc; }
-
- /// \brief Retrieve the source location of the ellipsis, whose presence
- /// indicates that the capture is a pack expansion.
- SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
-
- /// \brief Retrieve the capture type for this capture, which is effectively
- /// the type of the non-static data member in the lambda/block structure
- /// that would store this capture.
- QualType getCaptureType() const {
- assert(!isThisCapture());
- return CaptureType;
- }
-
- Expr *getInitExpr() const {
- assert(!isVLATypeCapture() && "no init expression for type capture");
- return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
- }
- };
-
CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
- : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0),
- HasImplicitReturnType(false)
- {}
+ : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {}
/// CaptureMap - A map of captured variables to (index+1) into Captures.
llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
/// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
/// zero if 'this' is not captured.
- unsigned CXXThisCaptureIndex;
+ unsigned CXXThisCaptureIndex = 0;
/// Captures - The captures.
SmallVector<Capture, 4> Captures;
- /// \brief - Whether the target type of return statements in this context
+ /// - Whether the target type of return statements in this context
/// is deduced (e.g. a lambda or block with omitted return type).
- bool HasImplicitReturnType;
+ bool HasImplicitReturnType = false;
/// ReturnType - The target type of return statements in this context,
/// or null if unknown.
QualType ReturnType;
void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
- SourceLocation Loc, SourceLocation EllipsisLoc,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
QualType CaptureType, Expr *Cpy) {
- Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
+ Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
EllipsisLoc, CaptureType, Cpy));
CaptureMap[Var] = Captures.size();
}
@@ -629,24 +653,24 @@ public:
void addThisCapture(bool isNested, SourceLocation Loc,
Expr *Cpy, bool ByCopy);
- /// \brief Determine whether the C++ 'this' is captured.
+ /// Determine whether the C++ 'this' is captured.
bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
-
- /// \brief Retrieve the capture of C++ 'this', if it has been captured.
+
+ /// Retrieve the capture of C++ 'this', if it has been captured.
Capture &getCXXThisCapture() {
assert(isCXXThisCaptured() && "this has not been captured");
return Captures[CXXThisCaptureIndex - 1];
}
-
- /// \brief Determine whether the given variable has been captured.
+
+ /// Determine whether the given variable has been captured.
bool isCaptured(VarDecl *Var) const {
return CaptureMap.count(Var);
}
- /// \brief Determine whether the given variable-array type has been captured.
+ /// Determine whether the given variable-array type has been captured.
bool isVLATypeCaptured(const VariableArrayType *VAT) const;
- /// \brief Retrieve the capture of the given variable, if it has been
+ /// Retrieve the capture of the given variable, if it has been
/// captured already.
Capture &getCapture(VarDecl *Var) {
assert(isCaptured(Var) && "Variable has not been captured");
@@ -660,17 +684,17 @@ public:
return Captures[Known->second - 1];
}
- static bool classof(const FunctionScopeInfo *FSI) {
+ static bool classof(const FunctionScopeInfo *FSI) {
return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda
|| FSI->Kind == SK_CapturedRegion;
}
};
-/// \brief Retains information about a block that is currently being parsed.
+/// Retains information about a block that is currently being parsed.
class BlockScopeInfo final : public CapturingScopeInfo {
public:
BlockDecl *TheDecl;
-
+
/// TheScope - This is the scope for the block itself, which contains
/// arguments etc.
Scope *TheScope;
@@ -680,51 +704,56 @@ public:
QualType FunctionType;
BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
- : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
- TheScope(BlockScope)
- {
+ : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
+ TheScope(BlockScope) {
Kind = SK_Block;
}
~BlockScopeInfo() override;
- static bool classof(const FunctionScopeInfo *FSI) {
- return FSI->Kind == SK_Block;
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Block;
}
};
-/// \brief Retains information about a captured region.
+/// Retains information about a captured region.
class CapturedRegionScopeInfo final : public CapturingScopeInfo {
public:
- /// \brief The CapturedDecl for this statement.
+ /// The CapturedDecl for this statement.
CapturedDecl *TheCapturedDecl;
- /// \brief The captured record type.
+
+ /// The captured record type.
RecordDecl *TheRecordDecl;
- /// \brief This is the enclosing scope of the captured region.
+
+ /// This is the enclosing scope of the captured region.
Scope *TheScope;
- /// \brief The implicit parameter for the captured variables.
+
+ /// The implicit parameter for the captured variables.
ImplicitParamDecl *ContextParam;
- /// \brief The kind of captured region.
+
+ /// The kind of captured region.
unsigned short CapRegionKind;
+
unsigned short OpenMPLevel;
CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
RecordDecl *RD, ImplicitParamDecl *Context,
CapturedRegionKind K, unsigned OpenMPLevel)
- : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
- TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
- ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel)
- {
+ : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
+ TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
+ ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) {
Kind = SK_CapturedRegion;
}
~CapturedRegionScopeInfo() override;
- /// \brief A descriptive name for the kind of captured region this is.
+ /// A descriptive name for the kind of captured region this is.
StringRef getRegionName() const {
switch (CapRegionKind) {
case CR_Default:
return "default captured statement";
+ case CR_ObjCAtFinally:
+ return "Objective-C @finally statement";
case CR_OpenMP:
return "OpenMP region";
}
@@ -738,41 +767,41 @@ public:
class LambdaScopeInfo final : public CapturingScopeInfo {
public:
- /// \brief The class that describes the lambda.
- CXXRecordDecl *Lambda;
+ /// The class that describes the lambda.
+ CXXRecordDecl *Lambda = nullptr;
- /// \brief The lambda's compiler-generated \c operator().
- CXXMethodDecl *CallOperator;
+ /// The lambda's compiler-generated \c operator().
+ CXXMethodDecl *CallOperator = nullptr;
- /// \brief Source range covering the lambda introducer [...].
+ /// Source range covering the lambda introducer [...].
SourceRange IntroducerRange;
- /// \brief Source location of the '&' or '=' specifying the default capture
+ /// Source location of the '&' or '=' specifying the default capture
/// type, if any.
SourceLocation CaptureDefaultLoc;
- /// \brief The number of captures in the \c Captures list that are
+ /// The number of captures in the \c Captures list that are
/// explicit captures.
- unsigned NumExplicitCaptures;
+ unsigned NumExplicitCaptures = 0;
- /// \brief Whether this is a mutable lambda.
- bool Mutable;
+ /// Whether this is a mutable lambda.
+ bool Mutable = false;
- /// \brief Whether the (empty) parameter list is explicit.
- bool ExplicitParams;
+ /// Whether the (empty) parameter list is explicit.
+ bool ExplicitParams = false;
- /// \brief Whether any of the capture expressions requires cleanups.
+ /// Whether any of the capture expressions requires cleanups.
CleanupInfo Cleanup;
- /// \brief Whether the lambda contains an unexpanded parameter pack.
- bool ContainsUnexpandedParameterPack;
+ /// Whether the lambda contains an unexpanded parameter pack.
+ bool ContainsUnexpandedParameterPack = false;
- /// \brief If this is a generic lambda, use this as the depth of
+ /// If this is a generic lambda, use this as the depth of
/// each 'auto' parameter, during initial AST construction.
- unsigned AutoTemplateParameterDepth;
+ unsigned AutoTemplateParameterDepth = 0;
- /// \brief Store the list of the auto parameters for a generic lambda.
- /// If this is a generic lambda, store the list of the auto
+ /// Store the list of the auto parameters for a generic lambda.
+ /// If this is a generic lambda, store the list of the auto
/// parameters converted into TemplateTypeParmDecls into a vector
/// that can be used to construct the generic lambda's template
/// parameter list, during initial AST construction.
@@ -781,30 +810,32 @@ public:
/// If this is a generic lambda, and the template parameter
/// list has been created (from the AutoTemplateParams) then
/// store a reference to it (cache it to avoid reconstructing it).
- TemplateParameterList *GLTemplateParameterList;
-
- /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs
+ TemplateParameterList *GLTemplateParameterList = nullptr;
+
+ /// Contains all variable-referring-expressions (i.e. DeclRefExprs
/// or MemberExprs) that refer to local variables in a generic lambda
/// or a lambda in a potentially-evaluated-if-used context.
- ///
- /// Potentially capturable variables of a nested lambda that might need
- /// to be captured by the lambda are housed here.
+ ///
+ /// Potentially capturable variables of a nested lambda that might need
+ /// to be captured by the lambda are housed here.
/// This is specifically useful for generic lambdas or
- /// lambdas within a a potentially evaluated-if-used context.
+ /// lambdas within a potentially evaluated-if-used context.
/// If an enclosing variable is named in an expression of a lambda nested
- /// within a generic lambda, we don't always know know whether the variable
+ /// within a generic lambda, we don't always know know whether the variable
/// will truly be odr-used (i.e. need to be captured) by that nested lambda,
- /// until its instantiation. But we still need to capture it in the
+ /// until its instantiation. But we still need to capture it in the
/// enclosing lambda if all intervening lambdas can capture the variable.
-
llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
- /// \brief Contains all variable-referring-expressions that refer
+ /// Contains all variable-referring-expressions that refer
/// to local variables that are usable as constant expressions and
/// do not involve an odr-use (they may still need to be captured
/// if the enclosing full-expression is instantiation dependent).
llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs;
+ /// A map of explicit capture indices to their introducer source ranges.
+ llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges;
+
/// Contains all of the variables defined in this lambda that shadow variables
/// that were defined in parent contexts. Used to avoid warnings when the
/// shadowed variables are uncaptured by this lambda.
@@ -817,15 +848,11 @@ public:
SourceLocation PotentialThisCaptureLocation;
LambdaScopeInfo(DiagnosticsEngine &Diag)
- : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr),
- CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false),
- ExplicitParams(false), Cleanup{},
- ContainsUnexpandedParameterPack(false), AutoTemplateParameterDepth(0),
- GLTemplateParameterList(nullptr) {
+ : CapturingScopeInfo(Diag, ImpCap_None) {
Kind = SK_Lambda;
}
- /// \brief Note when all explicit captures have been added.
+ /// Note when all explicit captures have been added.
void finishedExplicitCaptures() {
NumExplicitCaptures = Captures.size();
}
@@ -840,11 +867,10 @@ public:
return !AutoTemplateParams.empty() || GLTemplateParameterList;
}
+ /// Add a variable that might potentially be captured by the
+ /// lambda and therefore the enclosing lambdas.
///
- /// \brief Add a variable that might potentially be captured by the
- /// lambda and therefore the enclosing lambdas.
- ///
- /// This is also used by enclosing lambda's to speculatively capture
+ /// This is also used by enclosing lambda's to speculatively capture
/// variables that nested lambda's - depending on their enclosing
/// specialization - might need to capture.
/// Consider:
@@ -853,7 +879,7 @@ public:
/// void foo() {
/// const int x = 10;
/// auto L = [=](auto a) { // capture 'x'
- /// return [=](auto b) {
+ /// return [=](auto b) {
/// f(x, a); // we may or may not need to capture 'x'
/// };
/// };
@@ -862,45 +888,46 @@ public:
assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr));
PotentiallyCapturingExprs.push_back(VarExpr);
}
-
+
void addPotentialThisCapture(SourceLocation Loc) {
PotentialThisCaptureLocation = Loc;
}
- bool hasPotentialThisCapture() const {
- return PotentialThisCaptureLocation.isValid();
+
+ bool hasPotentialThisCapture() const {
+ return PotentialThisCaptureLocation.isValid();
}
- /// \brief Mark a variable's reference in a lambda as non-odr using.
+ /// Mark a variable's reference in a lambda as non-odr using.
///
- /// For generic lambdas, if a variable is named in a potentially evaluated
- /// expression, where the enclosing full expression is dependent then we
+ /// For generic lambdas, if a variable is named in a potentially evaluated
+ /// expression, where the enclosing full expression is dependent then we
/// must capture the variable (given a default capture).
- /// This is accomplished by recording all references to variables
- /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of
+ /// This is accomplished by recording all references to variables
+ /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of
/// PotentialCaptures. All such variables have to be captured by that lambda,
/// except for as described below.
- /// If that variable is usable as a constant expression and is named in a
- /// manner that does not involve its odr-use (e.g. undergoes
+ /// If that variable is usable as a constant expression and is named in a
+ /// manner that does not involve its odr-use (e.g. undergoes
/// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the
/// act of analyzing the enclosing full expression (ActOnFinishFullExpr)
/// if we can determine that the full expression is not instantiation-
- /// dependent, then we can entirely avoid its capture.
+ /// dependent, then we can entirely avoid its capture.
///
/// const int n = 0;
/// [&] (auto x) {
/// (void)+n + x;
/// };
- /// Interestingly, this strategy would involve a capture of n, even though
- /// it's obviously not odr-used here, because the full-expression is
+ /// Interestingly, this strategy would involve a capture of n, even though
+ /// it's obviously not odr-used here, because the full-expression is
/// instantiation-dependent. It could be useful to avoid capturing such
/// variables, even when they are referred to in an instantiation-dependent
/// expression, if we can unambiguously determine that they shall never be
/// odr-used. This would involve removal of the variable-referring-expression
- /// from the array of PotentialCaptures during the lvalue-to-rvalue
+ /// from the array of PotentialCaptures during the lvalue-to-rvalue
/// conversions. But per the working draft N3797, (post-chicago 2013) we must
- /// capture such variables.
+ /// capture such variables.
/// Before anyone is tempted to implement a strategy for not-capturing 'n',
- /// consider the insightful warning in:
+ /// consider the insightful warning in:
/// /cfe-commits/Week-of-Mon-20131104/092596.html
/// "The problem is that the set of captures for a lambda is part of the ABI
/// (since lambda layout can be made visible through inline functions and the
@@ -909,34 +936,33 @@ public:
/// seemingly harmless change elsewhere in Sema could cause us to start or stop
/// building such a node. So we need a rule that anyone can implement and get
/// exactly the same result".
- ///
void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
- assert(isa<DeclRefExpr>(CapturingVarExpr)
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
|| isa<MemberExpr>(CapturingVarExpr));
NonODRUsedCapturingExprs.insert(CapturingVarExpr);
}
bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
- assert(isa<DeclRefExpr>(CapturingVarExpr)
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
|| isa<MemberExpr>(CapturingVarExpr));
return NonODRUsedCapturingExprs.count(CapturingVarExpr);
}
void removePotentialCapture(Expr *E) {
PotentiallyCapturingExprs.erase(
- std::remove(PotentiallyCapturingExprs.begin(),
- PotentiallyCapturingExprs.end(), E),
+ std::remove(PotentiallyCapturingExprs.begin(),
+ PotentiallyCapturingExprs.end(), E),
PotentiallyCapturingExprs.end());
}
void clearPotentialCaptures() {
PotentiallyCapturingExprs.clear();
PotentialThisCaptureLocation = SourceLocation();
}
- unsigned getNumPotentialVariableCaptures() const {
- return PotentiallyCapturingExprs.size();
+ unsigned getNumPotentialVariableCaptures() const {
+ return PotentiallyCapturingExprs.size();
}
- bool hasPotentialCaptures() const {
- return getNumPotentialVariableCaptures() ||
- PotentialThisCaptureLocation.isValid();
+ bool hasPotentialCaptures() const {
+ return getNumPotentialVariableCaptures() ||
+ PotentialThisCaptureLocation.isValid();
}
// When passed the index, returns the VarDecl and Expr associated
@@ -945,7 +971,7 @@ public:
};
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
- : Base(nullptr, false), Property(nullptr) {}
+ : Base(nullptr, false) {}
FunctionScopeInfo::WeakObjectProfileTy
FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
@@ -970,7 +996,8 @@ CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc,
CXXThisCaptureIndex = Captures.size();
}
-} // end namespace sema
-} // end namespace clang
+} // namespace sema
+
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_SCOPEINFO_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
index 055d14f2d0de..b1077c620f8a 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -17,9 +17,11 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Availability.h"
-#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LocInfoType.h"
@@ -30,7 +32,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/ExpressionTraits.h"
-#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/PragmaKinds.h"
@@ -45,12 +46,12 @@
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
@@ -75,7 +76,7 @@ namespace clang {
class ASTReader;
class ASTWriter;
class ArrayType;
- class AttributeList;
+ class ParsedAttr;
class BindingDecl;
class BlockDecl;
class CapturedDecl;
@@ -172,6 +173,7 @@ namespace clang {
class TemplateArgumentList;
class TemplateArgumentLoc;
class TemplateDecl;
+ class TemplateInstantiationCallback;
class TemplateParameterList;
class TemplatePartialOrderingContext;
class TemplateTemplateParmDecl;
@@ -200,6 +202,7 @@ namespace clang {
namespace sema {
class AccessedEntity;
class BlockScopeInfo;
+ class Capture;
class CapturedRegionScopeInfo;
class CapturingScopeInfo;
class CompoundScopeInfo;
@@ -275,10 +278,10 @@ class Sema {
Sema(const Sema &) = delete;
void operator=(const Sema &) = delete;
- ///\brief Source of additional semantic information.
+ ///Source of additional semantic information.
ExternalSemaSource *ExternalSource;
- ///\brief Whether Sema has generated a multiplexer and has to delete it.
+ ///Whether Sema has generated a multiplexer and has to delete it.
bool isMultiplexExternalSource;
static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
@@ -318,16 +321,16 @@ public:
DiagnosticsEngine &Diags;
SourceManager &SourceMgr;
- /// \brief Flag indicating whether or not to collect detailed statistics.
+ /// Flag indicating whether or not to collect detailed statistics.
bool CollectStats;
- /// \brief Code-completion consumer.
+ /// Code-completion consumer.
CodeCompleteConsumer *CodeCompleter;
/// CurContext - This is the current declaration context of parsing.
DeclContext *CurContext;
- /// \brief Generally null except when we temporarily switch decl contexts,
+ /// Generally null except when we temporarily switch decl contexts,
/// like in \see ActOnObjCTemporaryExitContainerContext.
DeclContext *OriginalLexicalContext;
@@ -337,17 +340,17 @@ public:
bool MSStructPragmaOn; // True when \#pragma ms_struct on
- /// \brief Controls member pointer representation format under the MS ABI.
+ /// Controls member pointer representation format under the MS ABI.
LangOptions::PragmaMSPointersToMembersKind
MSPointerToMemberRepresentationMethod;
/// Stack of active SEH __finally scopes. Can be empty.
SmallVector<Scope*, 2> CurrentSEHFinally;
- /// \brief Source location for newly created implicit MSInheritanceAttrs
+ /// Source location for newly created implicit MSInheritanceAttrs
SourceLocation ImplicitMSInheritanceAttrLoc;
- /// \brief pragma clang section kind
+ /// pragma clang section kind
enum PragmaClangSectionKind {
PCSK_Invalid = 0,
PCSK_BSS = 1,
@@ -438,7 +441,7 @@ public:
// FIXME: We should serialize / deserialize these if they occur in a PCH (but
// we shouldn't do so if they're in a module).
- /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft
+ /// Whether to insert vtordisps prior to virtual bases in the Microsoft
/// C++ ABI. Possible values are 0, 1, and 2, which mean:
///
/// 0: Suppress all vtordisps
@@ -487,26 +490,26 @@ public:
/// VisContext - Manages the stack for \#pragma GCC visibility.
void *VisContext; // Really a "PragmaVisStack*"
- /// \brief This represents the stack of attributes that were pushed by
+ /// This represents the stack of attributes that were pushed by
/// \#pragma clang attribute.
struct PragmaAttributeEntry {
SourceLocation Loc;
- AttributeList *Attribute;
+ ParsedAttr *Attribute;
SmallVector<attr::SubjectMatchRule, 4> MatchRules;
bool IsUsed;
};
SmallVector<PragmaAttributeEntry, 2> PragmaAttributeStack;
- /// \brief The declaration that is currently receiving an attribute from the
+ /// The declaration that is currently receiving an attribute from the
/// #pragma attribute stack.
const Decl *PragmaAttributeCurrentTargetDecl;
- /// \brief This represents the last location of a "#pragma clang optimize off"
+ /// This represents the last location of a "#pragma clang optimize off"
/// directive if such a directive has not been closed by an "on" yet. If
/// optimizations are currently "on", this is set to an invalid location.
SourceLocation OptimizeOffPragmaLocation;
- /// \brief Flag indicating if Sema is building a recovery call expression.
+ /// Flag indicating if Sema is building a recovery call expression.
///
/// This flag is used to avoid building recovery call expressions
/// if Sema is already doing so, which would cause infinite recursions.
@@ -520,7 +523,7 @@ public:
/// element type here is ExprWithCleanups::Object.
SmallVector<BlockDecl*, 8> ExprCleanupObjects;
- /// \brief Store a list of either DeclRefExprs or MemberExprs
+ /// Store a list of either DeclRefExprs or MemberExprs
/// that contain a reference to a variable (constant) that may or may not
/// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue
/// and discarded value conversions have been applied to all subexpressions
@@ -528,12 +531,10 @@ public:
/// full expression.
llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
- /// \brief Stack containing information about each of the nested
+ std::unique_ptr<sema::FunctionScopeInfo> PreallocatedFunctionScope;
+
+ /// Stack containing information about each of the nested
/// function, block, and method scopes that are currently active.
- ///
- /// This array is never empty. Clients should ignore the first
- /// element, which is used to cache a single FunctionScopeInfo
- /// that's used to parse every top-level function.
SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
@@ -548,16 +549,16 @@ public:
/// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
std::unique_ptr<CXXFieldCollector> FieldCollector;
- typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType;
+ typedef llvm::SmallSetVector<NamedDecl *, 16> NamedDeclSetType;
- /// \brief Set containing all declared private fields that are not used.
+ /// Set containing all declared private fields that are not used.
NamedDeclSetType UnusedPrivateFields;
- /// \brief Set containing all typedefs that are likely unused.
+ /// Set containing all typedefs that are likely unused.
llvm::SmallSetVector<const TypedefNameDecl *, 4>
UnusedLocalTypedefNameCandidates;
- /// \brief Delete-expressions to be analyzed at the end of translation unit
+ /// Delete-expressions to be analyzed at the end of translation unit
///
/// This list contains class members, and locations of delete-expressions
/// that could not be proven as to whether they mismatch with new-expression
@@ -577,21 +578,21 @@ public:
/// we are currently parsing the initializer.
llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
- /// \brief Look for a locally scoped extern "C" declaration by the given name.
+ /// Look for a locally scoped extern "C" declaration by the given name.
NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
typedef LazyVector<VarDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadTentativeDefinitions, 2, 2>
TentativeDefinitionsType;
- /// \brief All the tentative definitions encountered in the TU.
+ /// All the tentative definitions encountered in the TU.
TentativeDefinitionsType TentativeDefinitions;
typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2>
UnusedFileScopedDeclsType;
- /// \brief The set of file scoped decls seen so far that have not been used
+ /// The set of file scoped decls seen so far that have not been used
/// and must warn if not used. Only contains the first declaration.
UnusedFileScopedDeclsType UnusedFileScopedDecls;
@@ -599,17 +600,17 @@ public:
&ExternalSemaSource::ReadDelegatingConstructors, 2, 2>
DelegatingCtorDeclsType;
- /// \brief All the delegating constructors seen so far in the file, used for
+ /// All the delegating constructors seen so far in the file, used for
/// cycle detection at the end of the TU.
DelegatingCtorDeclsType DelegatingCtorDecls;
- /// \brief All the overriding functions seen during a class definition
+ /// All the overriding functions seen during a class definition
/// that had their exception spec checks delayed, plus the overridden
/// function.
SmallVector<std::pair<const CXXMethodDecl*, const CXXMethodDecl*>, 2>
DelayedExceptionSpecChecks;
- /// \brief All the members seen during a class definition which were both
+ /// All the members seen during a class definition which were both
/// explicitly defaulted and had explicitly-specified exception
/// specifications, along with the function type containing their
/// user-specified exception specification. Those exception specifications
@@ -624,7 +625,7 @@ public:
LateParsedTemplateMapT;
LateParsedTemplateMapT LateParsedTemplateMap;
- /// \brief Callback to the parser to parse templated functions when needed.
+ /// Callback to the parser to parse templated functions when needed.
typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT);
typedef void LateTemplateParserCleanupCB(void *P);
LateTemplateParserCB *LateTemplateParser;
@@ -651,7 +652,7 @@ public:
/// A class which encapsulates the logic for delaying diagnostics
/// during parsing and other processing.
class DelayedDiagnostics {
- /// \brief The current pool of diagnostics into which delayed
+ /// The current pool of diagnostics into which delayed
/// diagnostics should go.
sema::DelayedDiagnosticPool *CurPool;
@@ -734,7 +735,7 @@ public:
}
};
- /// \brief RAII object to handle the state changes required to synthesize
+ /// RAII object to handle the state changes required to synthesize
/// a function body.
class SynthesizedFunctionScope {
Sema &S;
@@ -787,7 +788,7 @@ public:
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers;
- /// \brief Load weak undeclared identifiers from the external source.
+ /// Load weak undeclared identifiers from the external source.
void LoadExternalWeakUndeclaredIdentifiers();
/// WeakTopLevelDecl - Translation-unit scoped declarations generated by
@@ -804,77 +805,81 @@ public:
/// For example, user-defined classes, built-in "id" type, etc.
Scope *TUScope;
- /// \brief The C++ "std" namespace, where the standard library resides.
+ /// The C++ "std" namespace, where the standard library resides.
LazyDeclPtr StdNamespace;
- /// \brief The C++ "std::bad_alloc" class, which is defined by the C++
+ /// The C++ "std::bad_alloc" class, which is defined by the C++
/// standard library.
LazyDeclPtr StdBadAlloc;
- /// \brief The C++ "std::align_val_t" enum class, which is defined by the C++
+ /// The C++ "std::align_val_t" enum class, which is defined by the C++
/// standard library.
LazyDeclPtr StdAlignValT;
- /// \brief The C++ "std::experimental" namespace, where the experimental parts
+ /// The C++ "std::experimental" namespace, where the experimental parts
/// of the standard library resides.
NamespaceDecl *StdExperimentalNamespaceCache;
- /// \brief The C++ "std::initializer_list" template, which is defined in
+ /// The C++ "std::initializer_list" template, which is defined in
/// \<initializer_list>.
ClassTemplateDecl *StdInitializerList;
- /// \brief The C++ "type_info" declaration, which is defined in \<typeinfo>.
+ /// The C++ "std::coroutine_traits" template, which is defined in
+ /// \<coroutine_traits>
+ ClassTemplateDecl *StdCoroutineTraitsCache;
+
+ /// The C++ "type_info" declaration, which is defined in \<typeinfo>.
RecordDecl *CXXTypeInfoDecl;
- /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files.
+ /// The MSVC "_GUID" struct, which is defined in MSVC header files.
RecordDecl *MSVCGuidDecl;
- /// \brief Caches identifiers/selectors for NSFoundation APIs.
+ /// Caches identifiers/selectors for NSFoundation APIs.
std::unique_ptr<NSAPI> NSAPIObj;
- /// \brief The declaration of the Objective-C NSNumber class.
+ /// The declaration of the Objective-C NSNumber class.
ObjCInterfaceDecl *NSNumberDecl;
- /// \brief The declaration of the Objective-C NSValue class.
+ /// The declaration of the Objective-C NSValue class.
ObjCInterfaceDecl *NSValueDecl;
- /// \brief Pointer to NSNumber type (NSNumber *).
+ /// Pointer to NSNumber type (NSNumber *).
QualType NSNumberPointer;
- /// \brief Pointer to NSValue type (NSValue *).
+ /// Pointer to NSValue type (NSValue *).
QualType NSValuePointer;
- /// \brief The Objective-C NSNumber methods used to create NSNumber literals.
+ /// The Objective-C NSNumber methods used to create NSNumber literals.
ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
- /// \brief The declaration of the Objective-C NSString class.
+ /// The declaration of the Objective-C NSString class.
ObjCInterfaceDecl *NSStringDecl;
- /// \brief Pointer to NSString type (NSString *).
+ /// Pointer to NSString type (NSString *).
QualType NSStringPointer;
- /// \brief The declaration of the stringWithUTF8String: method.
+ /// The declaration of the stringWithUTF8String: method.
ObjCMethodDecl *StringWithUTF8StringMethod;
- /// \brief The declaration of the valueWithBytes:objCType: method.
+ /// The declaration of the valueWithBytes:objCType: method.
ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
- /// \brief The declaration of the Objective-C NSArray class.
+ /// The declaration of the Objective-C NSArray class.
ObjCInterfaceDecl *NSArrayDecl;
- /// \brief The declaration of the arrayWithObjects:count: method.
+ /// The declaration of the arrayWithObjects:count: method.
ObjCMethodDecl *ArrayWithObjectsMethod;
- /// \brief The declaration of the Objective-C NSDictionary class.
+ /// The declaration of the Objective-C NSDictionary class.
ObjCInterfaceDecl *NSDictionaryDecl;
- /// \brief The declaration of the dictionaryWithObjects:forKeys:count: method.
+ /// The declaration of the dictionaryWithObjects:forKeys:count: method.
ObjCMethodDecl *DictionaryWithObjectsMethod;
- /// \brief id<NSCopying> type.
+ /// id<NSCopying> type.
QualType QIDNSCopying;
- /// \brief will hold 'respondsToSelector:'
+ /// will hold 'respondsToSelector:'
Selector RespondsToSelectorSel;
/// A flag to remember whether the implicit forms of operator new and delete
@@ -885,43 +890,43 @@ public:
/// references to fields. This is really a
bool AllowAbstractFieldReference;
- /// \brief Describes how the expressions currently being parsed are
+ /// Describes how the expressions currently being parsed are
/// evaluated at run-time, if at all.
enum class ExpressionEvaluationContext {
- /// \brief The current expression and its subexpressions occur within an
+ /// The current expression and its subexpressions occur within an
/// unevaluated operand (C++11 [expr]p7), such as the subexpression of
/// \c sizeof, where the type of the expression may be significant but
/// no code will be generated to evaluate the value of the expression at
/// run time.
Unevaluated,
- /// \brief The current expression occurs within a braced-init-list within
+ /// The current expression occurs within a braced-init-list within
/// an unevaluated operand. This is mostly like a regular unevaluated
/// context, except that we still instantiate constexpr functions that are
/// referenced here so that we can perform narrowing checks correctly.
UnevaluatedList,
- /// \brief The current expression occurs within a discarded statement.
+ /// The current expression occurs within a discarded statement.
/// This behaves largely similarly to an unevaluated operand in preventing
/// definitions from being required, but not in other ways.
DiscardedStatement,
- /// \brief The current expression occurs within an unevaluated
+ /// The current expression occurs within an unevaluated
/// operand that unconditionally permits abstract references to
/// fields, such as a SIZE operator in MS-style inline assembly.
UnevaluatedAbstract,
- /// \brief The current context is "potentially evaluated" in C++11 terms,
+ /// The current context is "potentially evaluated" in C++11 terms,
/// but the expression is evaluated at compile-time (like the values of
/// cases in a switch statement).
ConstantEvaluated,
- /// \brief The current expression is potentially evaluated at run time,
+ /// The current expression is potentially evaluated at run time,
/// which means that code may be generated to evaluate the value of the
/// expression at run time.
PotentiallyEvaluated,
- /// \brief The current expression is potentially evaluated, but any
+ /// The current expression is potentially evaluated, but any
/// declarations referenced inside that expression are only used if
/// in fact the current expression is used.
///
@@ -932,63 +937,69 @@ public:
PotentiallyEvaluatedIfUsed
};
- /// \brief Data structure used to record current or nested
+ /// Data structure used to record current or nested
/// expression evaluation contexts.
struct ExpressionEvaluationContextRecord {
- /// \brief The expression evaluation context.
+ /// The expression evaluation context.
ExpressionEvaluationContext Context;
- /// \brief Whether the enclosing context needed a cleanup.
+ /// Whether the enclosing context needed a cleanup.
CleanupInfo ParentCleanup;
- /// \brief Whether we are in a decltype expression.
+ /// Whether we are in a decltype expression.
bool IsDecltype;
- /// \brief The number of active cleanup objects when we entered
+ /// The number of active cleanup objects when we entered
/// this expression evaluation context.
unsigned NumCleanupObjects;
- /// \brief The number of typos encountered during this expression evaluation
+ /// The number of typos encountered during this expression evaluation
/// context (i.e. the number of TypoExprs created).
unsigned NumTypos;
llvm::SmallPtrSet<Expr*, 2> SavedMaybeODRUseExprs;
- /// \brief The lambdas that are present within this context, if it
+ /// The lambdas that are present within this context, if it
/// is indeed an unevaluated context.
SmallVector<LambdaExpr *, 2> Lambdas;
- /// \brief The declaration that provides context for lambda expressions
+ /// The declaration that provides context for lambda expressions
/// and block literals if the normal declaration context does not
/// suffice, e.g., in a default function argument.
Decl *ManglingContextDecl;
- /// \brief The context information used to mangle lambda expressions
+ /// The context information used to mangle lambda expressions
/// and block literals within this context.
///
/// This mangling information is allocated lazily, since most contexts
/// do not have lambda expressions or block literals.
std::unique_ptr<MangleNumberingContext> MangleNumbering;
- /// \brief If we are processing a decltype type, a set of call expressions
+ /// If we are processing a decltype type, a set of call expressions
/// for which we have deferred checking the completeness of the return type.
SmallVector<CallExpr *, 8> DelayedDecltypeCalls;
- /// \brief If we are processing a decltype type, a set of temporary binding
+ /// If we are processing a decltype type, a set of temporary binding
/// expressions for which we have deferred checking the destructor.
SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
+ /// \brief Describes whether we are in an expression constext which we have
+ /// to handle differently.
+ enum ExpressionKind {
+ EK_Decltype, EK_TemplateArgument, EK_Other
+ } ExprContext;
+
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
unsigned NumCleanupObjects,
CleanupInfo ParentCleanup,
Decl *ManglingContextDecl,
- bool IsDecltype)
- : Context(Context), ParentCleanup(ParentCleanup),
- IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
- NumTypos(0),
- ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
+ ExpressionKind ExprContext)
+ : Context(Context), ParentCleanup(ParentCleanup),
+ NumCleanupObjects(NumCleanupObjects), NumTypos(0),
+ ManglingContextDecl(ManglingContextDecl), MangleNumbering(),
+ ExprContext(ExprContext) {}
- /// \brief Retrieve the mangling numbering context, used to consistently
+ /// Retrieve the mangling numbering context, used to consistently
/// number constructs like lambdas for mangling.
MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);
@@ -1005,7 +1016,7 @@ public:
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
- /// \brief Compute the mangling number context for a lambda expression or
+ /// Compute the mangling number context for a lambda expression or
/// block literal.
///
/// \param DC - The DeclContext containing the lambda expression or
@@ -1054,15 +1065,15 @@ public:
{}
};
- /// \brief A cache of special member function overload resolution results
+ /// A cache of special member function overload resolution results
/// for C++ records.
llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache;
- /// \brief A cache of the flags available in enumerations with the flag_bits
+ /// A cache of the flags available in enumerations with the flag_bits
/// attribute.
mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
- /// \brief The kind of translation unit we are processing.
+ /// The kind of translation unit we are processing.
///
/// When we're processing a complete translation unit, Sema will perform
/// end-of-translation-unit semantic tasks (such as creating
@@ -1073,13 +1084,13 @@ public:
llvm::BumpPtrAllocator BumpAlloc;
- /// \brief The number of SFINAE diagnostics that have been trapped.
+ /// The number of SFINAE diagnostics that have been trapped.
unsigned NumSFINAEErrors;
typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>>
UnparsedDefaultArgInstantiationsMap;
- /// \brief A mapping from parameters with unparsed default arguments to the
+ /// A mapping from parameters with unparsed default arguments to the
/// set of instantiations of each parameter.
///
/// This mapping is a temporary data structure used when parsing
@@ -1161,7 +1172,7 @@ public:
bool isSelfExpr(Expr *RExpr);
bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
- /// \brief Cause the active diagnostic on the DiagosticsEngine to be
+ /// Cause the active diagnostic on the DiagosticsEngine to be
/// emitted. This is closely coupled to the SemaDiagnosticBuilder class and
/// should not be used elsewhere.
void EmitCurrentDiagnostic(unsigned DiagID);
@@ -1186,7 +1197,7 @@ public:
CodeCompleteConsumer *CompletionConsumer = nullptr);
~Sema();
- /// \brief Perform initialization that occurs after the parser has been
+ /// Perform initialization that occurs after the parser has been
/// initialized but before it parses anything.
void Initialize();
@@ -1202,7 +1213,7 @@ public:
ASTMutationListener *getASTMutationListener() const;
ExternalSemaSource* getExternalSource() const { return ExternalSource; }
- ///\brief Registers an external source. If an external source already exists,
+ ///Registers an external source. If an external source already exists,
/// creates a multiplex external source and appends to it.
///
///\param[in] E - A non-null external sema source.
@@ -1211,7 +1222,7 @@ public:
void PrintStats() const;
- /// \brief Helper class that creates diagnostics with optional
+ /// Helper class that creates diagnostics with optional
/// template instantiation stacks.
///
/// This class provides a wrapper around the basic DiagnosticBuilder
@@ -1266,29 +1277,29 @@ public:
}
};
- /// \brief Emit a diagnostic.
+ /// Emit a diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
DiagnosticBuilder DB = Diags.Report(Loc, DiagID);
return SemaDiagnosticBuilder(DB, *this, DiagID);
}
- /// \brief Emit a partial diagnostic.
+ /// Emit a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
- /// \brief Build a partial diagnostic.
+ /// Build a partial diagnostic.
PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
bool findMacroSpelling(SourceLocation &loc, StringRef name);
- /// \brief Get a string to suggest for zero-initialization of a type.
+ /// Get a string to suggest for zero-initialization of a type.
std::string
getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const;
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
- /// \brief Calls \c Lexer::getLocForEndOfToken()
+ /// Calls \c Lexer::getLocForEndOfToken()
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
- /// \brief Retrieve the module loader associated with the preprocessor.
+ /// Retrieve the module loader associated with the preprocessor.
ModuleLoader &getModuleLoader() const;
void emitAndClearUnusedLocalTypedefWarnings();
@@ -1304,7 +1315,7 @@ public:
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
sema::LambdaScopeInfo *PushLambdaScope();
- /// \brief This is used to inform Sema what the current TemplateParameterDepth
+ /// This is used to inform Sema what the current TemplateParameterDepth
/// is during Parsing. Currently it is used to pass on the depth
/// when parsing generic lambda 'auto' parameters.
void RecordParsingTemplateParameterDepth(unsigned Depth);
@@ -1318,35 +1329,23 @@ public:
const BlockExpr *blkExpr = nullptr);
sema::FunctionScopeInfo *getCurFunction() const {
- return FunctionScopes.back();
+ return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
}
- sema::FunctionScopeInfo *getEnclosingFunction() const {
- if (FunctionScopes.empty())
- return nullptr;
+ sema::FunctionScopeInfo *getEnclosingFunction() const;
- for (int e = FunctionScopes.size()-1; e >= 0; --e) {
- if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
- continue;
- return FunctionScopes[e];
- }
- return nullptr;
- }
+ void setFunctionHasBranchIntoScope();
+ void setFunctionHasBranchProtectedScope();
+ void setFunctionHasIndirectGoto();
- template <typename ExprT>
- void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) {
- if (!isUnevaluatedContext())
- getCurFunction()->recordUseOfWeak(E, IsRead);
- }
-
- void PushCompoundScope();
+ void PushCompoundScope(bool IsStmtExpr);
void PopCompoundScope();
sema::CompoundScopeInfo &getCurCompoundScope() const;
bool hasAnyUnrecoverableErrorsInThisFunction() const;
- /// \brief Retrieve the current block, if any.
+ /// Retrieve the current block, if any.
sema::BlockScopeInfo *getCurBlock();
/// Retrieve the current lambda scope info, if any.
@@ -1356,10 +1355,10 @@ public:
sema::LambdaScopeInfo *
getCurLambda(bool IgnoreNonLambdaCapturingScope = false);
- /// \brief Retrieve the current generic lambda info, if any.
+ /// Retrieve the current generic lambda info, if any.
sema::LambdaScopeInfo *getCurGenericLambda();
- /// \brief Retrieve the current captured region, if any.
+ /// Retrieve the current captured region, if any.
sema::CapturedRegionScopeInfo *getCurCapturedRegion();
/// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
@@ -1382,6 +1381,7 @@ public:
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity);
+ QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc);
QualType BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc);
QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
@@ -1389,7 +1389,7 @@ public:
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
- /// \brief Build a function type.
+ /// Build a function type.
///
/// This routine checks the function type according to C++ rules and
/// under the assumption that the result type and parameter types have
@@ -1438,7 +1438,7 @@ public:
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
- /// \brief Package the given type and TSI into a ParsedType.
+ /// Package the given type and TSI into a ParsedType.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
DeclarationNameInfo GetNameForDeclarator(Declarator &D);
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
@@ -1459,6 +1459,7 @@ public:
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc);
+ bool handlerCanCatch(QualType HandlerType, QualType ExceptionType);
bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
const PartialDiagnostic &NestedDiagID,
const PartialDiagnostic &NoteID,
@@ -1475,11 +1476,11 @@ public:
TypeResult ActOnTypeName(Scope *S, Declarator &D);
- /// \brief The parser has parsed the context-sensitive type 'instancetype'
+ /// The parser has parsed the context-sensitive type 'instancetype'
/// in an Objective-C message declaration. Return the appropriate type.
ParsedType ActOnObjCInstanceType(SourceLocation Loc);
- /// \brief Abstract class used to diagnose incomplete types.
+ /// Abstract class used to diagnose incomplete types.
struct TypeDiagnoser {
TypeDiagnoser() {}
@@ -1548,10 +1549,10 @@ private:
VisibleModuleSet VisibleModules;
public:
- /// \brief Get the module owning an entity.
+ /// Get the module owning an entity.
Module *getOwningModule(Decl *Entity) { return Entity->getOwningModule(); }
- /// \brief Make a merged definition of an existing hidden definition \p ND
+ /// Make a merged definition of an existing hidden definition \p ND
/// visible at the specified location.
void makeMergedDefinitionVisible(NamedDecl *ND);
@@ -1649,7 +1650,8 @@ public:
}
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T);
+ const CXXScopeSpec &SS, QualType T,
+ TagDecl *OwnedTagDecl = nullptr);
QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
/// If AsUnevaluated is false, E is treated as though it were an evaluated
@@ -1705,7 +1707,7 @@ public:
SourceLocation NameLoc,
bool IsTemplateTypeArg);
- /// \brief Describes the result of the name lookup and resolution performed
+ /// Describes the result of the name lookup and resolution performed
/// by \c ClassifyName().
enum NameClassificationKind {
NC_Unknown,
@@ -1796,7 +1798,7 @@ public:
}
};
- /// \brief Perform name lookup on the given name, classifying it based on
+ /// Perform name lookup on the given name, classifying it based on
/// the results of name lookup and the following token.
///
/// This routine is used by the parser to resolve identifiers and help direct
@@ -1840,13 +1842,19 @@ public:
/// Determine whether it's plausible that E was intended to be a
/// template-name.
- bool mightBeIntendedToBeTemplateName(ExprResult E) {
+ bool mightBeIntendedToBeTemplateName(ExprResult E, bool &Dependent) {
if (!getLangOpts().CPlusPlus || E.isInvalid())
return false;
+ Dependent = false;
if (auto *DRE = dyn_cast<DeclRefExpr>(E.get()))
return !DRE->hasExplicitTemplateArgs();
if (auto *ME = dyn_cast<MemberExpr>(E.get()))
return !ME->hasExplicitTemplateArgs();
+ Dependent = true;
+ if (auto *DSDRE = dyn_cast<DependentScopeDeclRefExpr>(E.get()))
+ return !DSDRE->hasExplicitTemplateArgs();
+ if (auto *DSME = dyn_cast<CXXDependentScopeMemberExpr>(E.get()))
+ return !DSME->hasExplicitTemplateArgs();
// Any additional cases recognized here should also be handled by
// diagnoseExprIntendedAsTemplateName.
return false;
@@ -1862,8 +1870,8 @@ public:
void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
- DeclarationName Name,
- SourceLocation Loc);
+ DeclarationName Name, SourceLocation Loc,
+ bool IsTemplateId);
void
diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
SourceLocation FallbackLoc,
@@ -1944,6 +1952,7 @@ public:
bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl);
void CheckMain(FunctionDecl *FD, const DeclSpec &D);
void CheckMSVCRTEntryPoint(FunctionDecl *FD);
+ Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition);
Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
@@ -1999,7 +2008,7 @@ public:
return D && isa<ObjCMethodDecl>(D);
}
- /// \brief Determine whether we can delay parsing the body of a function or
+ /// Determine whether we can delay parsing the body of a function or
/// function template until it is used, assuming we don't care about emitting
/// code for that function.
///
@@ -2009,7 +2018,7 @@ public:
/// or has an 'auto' return type in C++14. These cases are essentially bugs.
bool canDelayFunctionBody(const Declarator &D);
- /// \brief Determine whether we can skip parsing the body of a function
+ /// Determine whether we can skip parsing the body of a function
/// definition, assuming we don't care about analyzing its body or emitting
/// code for that function.
///
@@ -2028,11 +2037,11 @@ public:
/// attribute for which parsing is delayed.
void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs);
- /// \brief Diagnose any unused parameters in the given sequence of
+ /// Diagnose any unused parameters in the given sequence of
/// ParmVarDecl pointers.
void DiagnoseUnusedParameters(ArrayRef<ParmVarDecl *> Parameters);
- /// \brief Diagnose whether the size of parameters or return value of a
+ /// Diagnose whether the size of parameters or return value of a
/// function or obj-c method definition is pass-by-value and larger than a
/// specified threshold.
void
@@ -2044,9 +2053,8 @@ public:
SourceLocation AsmLoc,
SourceLocation RParenLoc);
- /// \brief Handle a C++11 empty-declaration and attribute-declaration.
- Decl *ActOnEmptyDeclaration(Scope *S,
- AttributeList *AttrList,
+ /// Handle a C++11 empty-declaration and attribute-declaration.
+ Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList,
SourceLocation SemiLoc);
enum class ModuleDeclKind {
@@ -2061,7 +2069,7 @@ public:
SourceLocation ModuleLoc, ModuleDeclKind MDK,
ModuleIdPath Path);
- /// \brief The parser has processed a module import declaration.
+ /// The parser has processed a module import declaration.
///
/// \param AtLoc The location of the '@' symbol, if any.
///
@@ -2071,17 +2079,17 @@ public:
DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc,
ModuleIdPath Path);
- /// \brief The parser has processed a module import translated from a
+ /// The parser has processed a module import translated from a
/// #include or similar preprocessing directive.
void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
- /// \brief The parsed has entered a submodule.
+ /// The parsed has entered a submodule.
void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
- /// \brief The parser has left a submodule.
+ /// The parser has left a submodule.
void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
- /// \brief Create an implicit import of the given module at the given
+ /// Create an implicit import of the given module at the given
/// source location, for error recovery, if possible.
///
/// This routine is typically used when an entity found by name lookup
@@ -2100,7 +2108,7 @@ public:
PartialSpecialization
};
- /// \brief Diagnose that the specified declaration needs to be visible but
+ /// Diagnose that the specified declaration needs to be visible but
/// isn't, and suggest a module import that would resolve the problem.
void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
MissingImportKind MIK, bool Recover = true);
@@ -2113,23 +2121,23 @@ public:
Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl,
SourceLocation RBraceLoc);
- /// \brief We've found a use of a templated declaration that would trigger an
+ /// We've found a use of a templated declaration that would trigger an
/// implicit instantiation. Check that any relevant explicit specializations
/// and partial specializations are visible, and diagnose if not.
void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
- /// \brief We've found a use of a template specialization that would select a
+ /// We've found a use of a template specialization that would select a
/// partial specialization. Check that the partial specialization is visible,
/// and diagnose if not.
void checkPartialSpecializationVisibility(SourceLocation Loc,
NamedDecl *Spec);
- /// \brief Retrieve a suitable printing policy.
+ /// Retrieve a suitable printing policy for diagnostics.
PrintingPolicy getPrintingPolicy() const {
return getPrintingPolicy(Context, PP);
}
- /// \brief Retrieve a suitable printing policy.
+ /// Retrieve a suitable printing policy for diagnostics.
static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
const Preprocessor &PP);
@@ -2184,7 +2192,7 @@ public:
Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name,
- SourceLocation NameLoc, AttributeList *Attr,
+ SourceLocation NameLoc, const ParsedAttributesView &Attr,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl,
bool &IsDependent, SourceLocation ScopedEnumKWLoc,
@@ -2194,9 +2202,9 @@ public:
Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ const ParsedAttributesView &Attr,
MultiTemplateParamsArg TempParamLists);
TypeResult ActOnDependentTag(Scope *S,
@@ -2218,11 +2226,11 @@ public:
InClassInitStyle InitStyle,
AccessSpecifier AS);
MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
- SourceLocation DeclStart,
- Declarator &D, Expr *BitfieldWidth,
+ SourceLocation DeclStart, Declarator &D,
+ Expr *BitfieldWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS,
- AttributeList *MSPropertyAttr);
+ const ParsedAttr &MSPropertyAttr);
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
@@ -2235,7 +2243,17 @@ public:
bool CheckNontrivialField(FieldDecl *FD);
void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
+
+ enum TrivialABIHandling {
+ /// The triviality of a method unaffected by "trivial_abi".
+ TAH_IgnoreTrivialABI,
+
+ /// The triviality of a method affected by "trivial_abi".
+ TAH_ConsiderTrivialABI
+ };
+
bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ TrivialABIHandling TAH = TAH_IgnoreTrivialABI,
bool Diagnose = false);
CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
void ActOnLastBitfield(SourceLocation DeclStart,
@@ -2245,10 +2263,9 @@ public:
tok::ObjCKeywordKind visibility);
// This is used for both record definitions and ObjC interface declarations.
- void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl,
- ArrayRef<Decl *> Fields,
- SourceLocation LBrac, SourceLocation RBrac,
- AttributeList *AttrList);
+ void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl,
+ ArrayRef<Decl *> Fields, SourceLocation LBrac,
+ SourceLocation RBrac, const ParsedAttributesView &AttrList);
/// ActOnTagStartDefinition - Invoked when we have entered the
/// scope of a tag's definition (e.g., for an enumeration, class,
@@ -2263,7 +2280,7 @@ public:
typedef void *SkippedDefinitionContext;
- /// \brief Invoked when we enter a tag definition that we're skipping.
+ /// Invoked when we enter a tag definition that we're skipping.
SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
Decl *ActOnObjCContainerStartDefinition(Decl *IDecl);
@@ -2285,7 +2302,7 @@ public:
void ActOnObjCContainerFinishDefinition();
- /// \brief Invoked when we must temporarily exit the objective-c container
+ /// Invoked when we must temporarily exit the objective-c container
/// scope for parsing/looking-up C constructs.
///
/// Must be followed by a call to \see ActOnObjCReenterContainerContext
@@ -2303,8 +2320,7 @@ public:
Expr *val);
bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
- QualType EnumUnderlyingTy,
- bool EnumUnderlyingIsImplicit,
+ QualType EnumUnderlyingTy, bool IsFixed,
const EnumDecl *Prev);
/// Determine whether the body of an anonymous enumeration should be skipped.
@@ -2314,12 +2330,11 @@ public:
Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
- AttributeList *Attrs, SourceLocation EqualLoc,
- Expr *Val);
+ const ParsedAttributesView &Attrs,
+ SourceLocation EqualLoc, Expr *Val);
void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
- Decl *EnumDecl,
- ArrayRef<Decl *> Elements,
- Scope *S, AttributeList *Attr);
+ Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S,
+ const ParsedAttributesView &Attr);
DeclContext *getContainingDC(DeclContext *DC);
@@ -2356,7 +2371,7 @@ public:
/// Add this decl to the scope shadowed decl chains.
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
- /// \brief Make the given externally-produced declaration visible at the
+ /// Make the given externally-produced declaration visible at the
/// top level scope.
///
/// \param D The externally-produced declaration to push.
@@ -2383,18 +2398,18 @@ public:
TypeSourceInfo *TInfo);
bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
- /// \brief Describes the kind of merge to perform for availability
+ /// Describes the kind of merge to perform for availability
/// attributes (including "deprecated", "unavailable", and "availability").
enum AvailabilityMergeKind {
- /// \brief Don't merge availability attributes at all.
+ /// Don't merge availability attributes at all.
AMK_None,
- /// \brief Merge availability attributes for a redeclaration, which requires
+ /// Merge availability attributes for a redeclaration, which requires
/// an exact match.
AMK_Redeclaration,
- /// \brief Merge availability attributes for an override, which requires
+ /// Merge availability attributes for an override, which requires
/// an exact match or a weakening of constraints.
AMK_Override,
- /// \brief Merge availability attributes for an implementation of
+ /// Merge availability attributes for an implementation of
/// a protocol requirement.
AMK_ProtocolImplementation,
};
@@ -2432,6 +2447,8 @@ public:
int FirstArg, unsigned AttrSpellingListIndex);
SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
unsigned AttrSpellingListIndex);
+ CodeSegAttr *mergeCodeSegAttr(Decl *D, SourceRange Range, StringRef Name,
+ unsigned AttrSpellingListIndex);
AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
IdentifierInfo *Ident,
unsigned AttrSpellingListIndex);
@@ -2496,7 +2513,7 @@ public:
bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl,
bool ConsiderCudaAttrs = true);
- /// \brief Checks availability of the function depending on the current
+ /// Checks availability of the function depending on the current
/// function context.Inside an unavailable function,unavailability is ignored.
///
/// \returns true if \p FD is unavailable and current context is inside
@@ -2568,6 +2585,11 @@ public:
NamedDecl *FoundDecl,
CXXMethodDecl *Method);
+ /// Check that the lifetime of the initializer (and its subobjects) is
+ /// sufficient for initializing the entity, and perform lifetime extension
+ /// (when permitted) if not.
+ void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);
+
ExprResult PerformContextuallyConvertToBool(Expr *From);
ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
@@ -2584,7 +2606,7 @@ public:
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
APValue &Value, CCEKind CCE);
- /// \brief Abstract base class used to perform a contextual implicit
+ /// Abstract base class used to perform a contextual implicit
/// conversion from an expression to any type passing a filter.
class ContextualImplicitConverter {
public:
@@ -2595,38 +2617,38 @@ public:
bool SuppressConversion = false)
: Suppress(Suppress), SuppressConversion(SuppressConversion) {}
- /// \brief Determine whether the specified type is a valid destination type
+ /// Determine whether the specified type is a valid destination type
/// for this conversion.
virtual bool match(QualType T) = 0;
- /// \brief Emits a diagnostic complaining that the expression does not have
+ /// Emits a diagnostic complaining that the expression does not have
/// integral or enumeration type.
virtual SemaDiagnosticBuilder
diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
- /// \brief Emits a diagnostic when the expression has incomplete class type.
+ /// Emits a diagnostic when the expression has incomplete class type.
virtual SemaDiagnosticBuilder
diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
- /// \brief Emits a diagnostic when the only matching conversion function
+ /// Emits a diagnostic when the only matching conversion function
/// is explicit.
virtual SemaDiagnosticBuilder diagnoseExplicitConv(
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
- /// \brief Emits a note for the explicit conversion function.
+ /// Emits a note for the explicit conversion function.
virtual SemaDiagnosticBuilder
noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
- /// \brief Emits a diagnostic when there are multiple possible conversion
+ /// Emits a diagnostic when there are multiple possible conversion
/// functions.
virtual SemaDiagnosticBuilder
diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
- /// \brief Emits a note for one of the candidate conversions.
+ /// Emits a note for one of the candidate conversions.
virtual SemaDiagnosticBuilder
noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
- /// \brief Emits a diagnostic when we picked a conversion function
+ /// Emits a diagnostic when we picked a conversion function
/// (for cases when we are not allowed to pick a conversion function).
virtual SemaDiagnosticBuilder diagnoseConversion(
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
@@ -2651,7 +2673,7 @@ public:
return diagnoseNotInt(S, Loc, T);
}
- /// \brief Emits a diagnostic complaining that the expression does not have
+ /// Emits a diagnostic complaining that the expression does not have
/// integral or enumeration type.
virtual SemaDiagnosticBuilder
diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
@@ -2986,7 +3008,7 @@ public:
/// the ability to distinguish among them.
//@{
- /// @brief Describes the kind of name lookup to perform.
+ /// Describes the kind of name lookup to perform.
enum LookupNameKind {
/// Ordinary name lookup, which finds ordinary names (functions,
/// variables, typedefs, etc.) in C and most kinds of names
@@ -3028,22 +3050,22 @@ public:
LookupObjCProtocolName,
/// Look up implicit 'self' parameter of an objective-c method.
LookupObjCImplicitSelfParam,
- /// \brief Look up the name of an OpenMP user-defined reduction operation.
+ /// Look up the name of an OpenMP user-defined reduction operation.
LookupOMPReductionName,
- /// \brief Look up any declaration with any name.
+ /// Look up any declaration with any name.
LookupAnyName
};
- /// \brief Specifies whether (or how) name lookup is being performed for a
+ /// Specifies whether (or how) name lookup is being performed for a
/// redeclaration (vs. a reference).
enum RedeclarationKind {
- /// \brief The lookup is a reference to this name that is not for the
+ /// The lookup is a reference to this name that is not for the
/// purpose of redeclaring the name.
NotForRedeclaration = 0,
- /// \brief The lookup results will be used for redeclaration of a name,
+ /// The lookup results will be used for redeclaration of a name,
/// if an entity by that name already exists and is visible.
ForVisibleRedeclaration,
- /// \brief The lookup results will be used for redeclaration of a name
+ /// 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
@@ -3060,23 +3082,23 @@ public:
return ForExternalRedeclaration;
}
- /// \brief The possible outcomes of name lookup for a literal operator.
+ /// The possible outcomes of name lookup for a literal operator.
enum LiteralOperatorLookupResult {
- /// \brief The lookup resulted in an error.
+ /// The lookup resulted in an error.
LOLR_Error,
- /// \brief The lookup found no match but no diagnostic was issued.
+ /// The lookup found no match but no diagnostic was issued.
LOLR_ErrorNoDiagnostic,
- /// \brief The lookup found a single 'cooked' literal operator, which
+ /// The lookup found a single 'cooked' literal operator, which
/// expects a normal literal to be built and passed to it.
LOLR_Cooked,
- /// \brief The lookup found a single 'raw' literal operator, which expects
+ /// The lookup found a single 'raw' literal operator, which expects
/// a string literal containing the spelling of the literal token.
LOLR_Raw,
- /// \brief The lookup found an overload set of literal operator templates,
+ /// The lookup found an overload set of literal operator templates,
/// which expect the characters of the spelling of the literal token to be
/// passed as a non-type template argument pack.
LOLR_Template,
- /// \brief The lookup found an overload set of literal operator templates,
+ /// The lookup found an overload set of literal operator templates,
/// which expect the character type and characters of the spelling of the
/// string literal token to be passed as template arguments.
LOLR_StringTemplate
@@ -3106,25 +3128,25 @@ private:
TypoExprState &operator=(TypoExprState &&other) noexcept;
};
- /// \brief The set of unhandled TypoExprs and their associated state.
+ /// The set of unhandled TypoExprs and their associated state.
llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
- /// \brief Creates a new TypoExpr AST node.
+ /// Creates a new TypoExpr AST node.
TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG,
TypoRecoveryCallback TRC);
- // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.
+ // The set of known/encountered (unique, canonicalized) NamespaceDecls.
//
// The boolean value will be true to indicate that the namespace was loaded
// from an AST/PCH file, or false otherwise.
llvm::MapVector<NamespaceDecl*, bool> KnownNamespaces;
- /// \brief Whether we have already loaded known namespaces from an extenal
+ /// Whether we have already loaded known namespaces from an extenal
/// source.
bool LoadedExternalKnownNamespaces;
- /// \brief Helper for CorrectTypo and CorrectTypoDelayed used to create and
+ /// Helper for CorrectTypo and CorrectTypoDelayed used to create and
/// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
/// should be skipped entirely.
std::unique_ptr<TypoCorrectionConsumer>
@@ -3139,10 +3161,10 @@ private:
public:
const TypoExprState &getTypoExprState(TypoExpr *TE) const;
- /// \brief Clears the state of the given TypoExpr.
+ /// Clears the state of the given TypoExpr.
void clearDelayedTypo(TypoExpr *TE);
- /// \brief Look up a name, looking for a single declaration. Return
+ /// Look up a name, looking for a single declaration. Return
/// null if the results were absent, ambiguous, or overloaded.
///
/// It is preferable to use the elaborated form and explicitly handle
@@ -3199,11 +3221,13 @@ public:
void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
- bool IncludeGlobalScope = true);
+ bool IncludeGlobalScope = true,
+ bool LoadExternal = true);
void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
bool IncludeGlobalScope = true,
- bool IncludeDependentBases = false);
+ bool IncludeDependentBases = false,
+ bool LoadExternal = true);
enum CorrectTypoKind {
CTK_NonError, // CorrectTypo used in a non error recovery situation.
@@ -3230,7 +3254,7 @@ public:
bool EnteringContext = false,
const ObjCObjectPointerType *OPT = nullptr);
- /// \brief Process any TypoExprs in the given Expr and its children,
+ /// Process any TypoExprs in the given Expr and its children,
/// generating diagnostics as appropriate and returning a new Expr if there
/// were typos that were all successfully corrected and ExprError if one or
/// more typos could not be corrected.
@@ -3308,11 +3332,12 @@ public:
// Decl attributes - this routine is the top level dispatcher.
void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
// Helper for delayed processing of attributes.
- void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList);
- void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
- bool IncludeCXX11Attributes = true);
+ void ProcessDeclAttributeDelayed(Decl *D,
+ const ParsedAttributesView &AttrList);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const ParsedAttributesView &AL,
+ bool IncludeCXX11Attributes = true);
bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
- const AttributeList *AttrList);
+ const ParsedAttributesView &AttrList);
void checkUnusedDeclAttributes(Declarator &D);
@@ -3322,13 +3347,13 @@ public:
/// type as valid.
bool isValidPointerAttrType(QualType T, bool RefOkay = false);
- bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
- bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
+ bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
+ bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC,
const FunctionDecl *FD = nullptr);
- bool CheckNoReturnAttr(const AttributeList &attr);
- bool CheckNoCallerSavedRegsAttr(const AttributeList &attr);
- bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
- unsigned ArgNum, StringRef &Str,
+ bool CheckAttrTarget(const ParsedAttr &CurrAttr);
+ bool CheckAttrNoArgs(const ParsedAttr &CurrAttr);
+ bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum,
+ StringRef &Str,
SourceLocation *ArgLocation = nullptr);
bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
@@ -3377,8 +3402,9 @@ public:
bool isContextSensitive,
bool allowArrayTypes);
- /// \brief Stmt attributes - this routine is the top level dispatcher.
- StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
+ /// Stmt attributes - this routine is the top level dispatcher.
+ StmtResult ProcessStmtAttributes(Stmt *Stmt,
+ const ParsedAttributesView &Attrs,
SourceRange Range);
void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
@@ -3520,7 +3546,7 @@ public:
/// warns each time an exact match is found.
void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP);
- /// \brief Add the given method to the list of globally-known methods.
+ /// Add the given method to the list of globally-known methods.
void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
private:
@@ -3535,7 +3561,7 @@ private:
bool instance);
public:
- /// \brief - Returns instance or factory methods in global method pool for
+ /// - Returns instance or factory methods in global method pool for
/// given selector. It checks the desired kind first, if none is found, and
/// parameter checkTheOther is set, it then checks the other kind. If no such
/// method or only one method is found, function returns false; otherwise, it
@@ -3557,14 +3583,14 @@ public:
bool receiverIdOrClass);
private:
- /// \brief - Returns a selector which best matches given argument list or
+ /// - Returns a selector which best matches given argument list or
/// nullptr if none could be found
ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
bool IsInstance,
SmallVectorImpl<ObjCMethodDecl*>& Methods);
- /// \brief Record the typo correction failure and return an empty correction.
+ /// Record the typo correction failure and return an empty correction.
TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
bool RecordFailure = true) {
if (RecordFailure)
@@ -3664,16 +3690,16 @@ public:
StmtResult ActOnNullStmt(SourceLocation SemiLoc,
bool HasLeadingEmptyMacro = false);
- void ActOnStartOfCompoundStmt();
+ void ActOnStartOfCompoundStmt(bool IsStmtExpr);
void ActOnFinishOfCompoundStmt();
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr);
- /// \brief A RAII object to enter scope of a compound statement.
+ /// A RAII object to enter scope of a compound statement.
class CompoundScopeRAII {
public:
- CompoundScopeRAII(Sema &S): S(S) {
- S.ActOnStartOfCompoundStmt();
+ CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
+ S.ActOnStartOfCompoundStmt(IsStmtExpr);
}
~CompoundScopeRAII() {
@@ -3701,9 +3727,10 @@ public:
SourceLocation EndLoc);
void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
StmtResult ActOnForEachLValueExpr(Expr *E);
- StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
- SourceLocation DotDotDotLoc, Expr *RHSVal,
- SourceLocation ColonLoc);
+ ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val);
+ StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS,
+ SourceLocation DotDotDotLoc, ExprResult RHS,
+ SourceLocation ColonLoc);
void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
@@ -3797,10 +3824,22 @@ public:
RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
SourceLocation Loc,
unsigned NumParams);
+
+ enum CopyElisionSemanticsKind {
+ CES_Strict = 0,
+ CES_AllowParameters = 1,
+ CES_AllowDifferentTypes = 2,
+ CES_AllowExceptionVariables = 4,
+ CES_FormerDefault = (CES_AllowParameters),
+ CES_Default = (CES_AllowParameters | CES_AllowDifferentTypes),
+ CES_AsIfByStdMove = (CES_AllowParameters | CES_AllowDifferentTypes |
+ CES_AllowExceptionVariables),
+ };
+
VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
- bool AllowParamOrMoveConstructible);
+ CopyElisionSemanticsKind CESK);
bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
- bool AllowParamOrMoveConstructible);
+ CopyElisionSemanticsKind CESK);
StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
Scope *CurScope);
@@ -3889,7 +3928,7 @@ public:
bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
- /// \brief If it's a file scoped decl that must warn if not used, keep track
+ /// If it's a file scoped decl that must warn if not used, keep track
/// of it.
void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
@@ -3918,7 +3957,7 @@ public:
void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
SourceLocation OpLoc);
- /// \brief Warn if we're implicitly casting from a _Nullable pointer type to a
+ /// Warn if we're implicitly casting from a _Nullable pointer type to a
/// _Nonnull one.
void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
SourceLocation Loc);
@@ -3941,7 +3980,7 @@ public:
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
- void DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
+ void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks = false);
@@ -3949,14 +3988,14 @@ public:
bool makeUnavailableInSystemHeader(SourceLocation loc,
UnavailableAttr::ImplicitReason reason);
- /// \brief Issue any -Wunguarded-availability warnings in \c FD
+ /// Issue any -Wunguarded-availability warnings in \c FD
void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid);
- bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
bool ObjCPropertyAccess = false,
bool AvoidPartialAvailabilityChecks = false);
@@ -3969,13 +4008,15 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
ArrayRef<Expr *> Args);
- void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- Decl *LambdaContextDecl = nullptr,
- bool IsDecltype = false);
+ void PushExpressionEvaluationContext(
+ ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr,
+ ExpressionEvaluationContextRecord::ExpressionKind Type =
+ ExpressionEvaluationContextRecord::EK_Other);
enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
- void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- ReuseLambdaContextDecl_t,
- bool IsDecltype = false);
+ void PushExpressionEvaluationContext(
+ ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+ ExpressionEvaluationContextRecord::ExpressionKind Type =
+ ExpressionEvaluationContextRecord::EK_Other);
void PopExpressionEvaluationContext();
void DiscardCleanupsInEvaluationContext();
@@ -4011,7 +4052,7 @@ public:
TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
};
- /// \brief Try to capture the given variable.
+ /// Try to capture the given variable.
///
/// \param Var The variable to capture.
///
@@ -4050,15 +4091,15 @@ public:
QualType &DeclRefType,
const unsigned *const FunctionScopeIndexToStopAt);
- /// \brief Try to capture the given variable.
+ /// Try to capture the given variable.
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
TryCaptureKind Kind = TryCapture_Implicit,
SourceLocation EllipsisLoc = SourceLocation());
- /// \brief Checks if the variable must be captured.
+ /// Checks if the variable must be captured.
bool NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc);
- /// \brief Given a variable, determine the type that a reference to that
+ /// Given a variable, determine the type that a reference to that
/// variable will have in the given scope.
QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc);
@@ -4069,18 +4110,18 @@ public:
void MarkDeclarationsReferencedInExpr(Expr *E,
bool SkipLocalVariables = false);
- /// \brief Try to recover by turning the given expression into a
+ /// Try to recover by turning the given expression into a
/// call. Returns true if recovery was attempted or an error was
/// emitted; this may also leave the ExprResult invalid.
bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
bool ForceComplain = false,
bool (*IsPlausibleResult)(QualType) = nullptr);
- /// \brief Figure out if an expression could be turned into a call.
+ /// Figure out if an expression could be turned into a call.
bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
UnresolvedSetImpl &NonTemplateOverloads);
- /// \brief Conditionally issue a diagnostic based on the current
+ /// Conditionally issue a diagnostic based on the current
/// evaluation context.
///
/// \param Statement If Statement is non-null, delay reporting the
@@ -4222,6 +4263,7 @@ public:
ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, Expr *Input);
+ bool isQualifiedMemberAccess(Expr *E);
QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
@@ -4354,7 +4396,7 @@ public:
Expr *Op);
CastKind PrepareScalarCast(ExprResult &src, QualType destType);
- /// \brief Build an altivec or OpenCL literal.
+ /// Build an altivec or OpenCL literal.
ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
SourceLocation RParenLoc, Expr *E,
TypeSourceInfo *TInfo);
@@ -4446,19 +4488,19 @@ public:
bool CheckCaseExpression(Expr *E);
- /// \brief Describes the result of an "if-exists" condition check.
+ /// Describes the result of an "if-exists" condition check.
enum IfExistsResult {
- /// \brief The symbol exists.
+ /// The symbol exists.
IER_Exists,
- /// \brief The symbol does not exist.
+ /// The symbol does not exist.
IER_DoesNotExist,
- /// \brief The name is a dependent name, so the results will differ
+ /// The name is a dependent name, so the results will differ
/// from one instantiation to the next.
IER_Dependent,
- /// \brief An error occurred.
+ /// An error occurred.
IER_Error
};
@@ -4520,11 +4562,10 @@ public:
// Act on C++ namespaces
Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
SourceLocation NamespaceLoc,
- SourceLocation IdentLoc,
- IdentifierInfo *Ident,
+ SourceLocation IdentLoc, IdentifierInfo *Ident,
SourceLocation LBrace,
- AttributeList *AttrList,
- UsingDirectiveDecl * &UsingDecl);
+ const ParsedAttributesView &AttrList,
+ UsingDirectiveDecl *&UsingDecl);
void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
NamespaceDecl *getStdNamespace() const;
@@ -4535,27 +4576,41 @@ public:
CXXRecordDecl *getStdBadAlloc() const;
EnumDecl *getStdAlignValT() const;
- /// \brief Tests whether Ty is an instance of std::initializer_list and, if
+private:
+ // A cache representing if we've fully checked the various comparison category
+ // types stored in ASTContext. The bit-index corresponds to the integer value
+ // of a ComparisonCategoryType enumerator.
+ llvm::SmallBitVector FullyCheckedComparisonCategories;
+
+public:
+ /// Lookup the specified comparison category types in the standard
+ /// library, an check the VarDecls possibly returned by the operator<=>
+ /// builtins for that type.
+ ///
+ /// \return The type of the comparison category type corresponding to the
+ /// specified Kind, or a null type if an error occurs
+ QualType CheckComparisonCategoryType(ComparisonCategoryType Kind,
+ SourceLocation Loc);
+
+ /// Tests whether Ty is an instance of std::initializer_list and, if
/// it is and Element is not NULL, assigns the element type to Element.
bool isStdInitializerList(QualType Ty, QualType *Element);
- /// \brief Looks for the std::initializer_list template and instantiates it
+ /// Looks for the std::initializer_list template and instantiates it
/// with Element, or emits an error if it's not found.
///
/// \returns The instantiated template, or null on error.
QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
- /// \brief Determine whether Ctor is an initializer-list constructor, as
+ /// Determine whether Ctor is an initializer-list constructor, as
/// defined in [dcl.init.list]p2.
bool isInitListConstructor(const FunctionDecl *Ctor);
- Decl *ActOnUsingDirective(Scope *CurScope,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
+ Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc, CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *NamespcName,
- AttributeList *AttrList);
+ const ParsedAttributesView &AttrList);
void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
@@ -4586,15 +4641,11 @@ public:
const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc);
- NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
- SourceLocation UsingLoc,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
- DeclarationNameInfo NameInfo,
- SourceLocation EllipsisLoc,
- AttributeList *AttrList,
- bool IsInstantiation);
+ NamedDecl *BuildUsingDeclaration(
+ Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
+ bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
+ const ParsedAttributesView &AttrList, bool IsInstantiation);
NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
ArrayRef<NamedDecl *> Expansions);
@@ -4607,22 +4658,16 @@ public:
findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor,
ConstructorUsingShadowDecl *DerivedShadow);
- Decl *ActOnUsingDeclaration(Scope *CurScope,
- AccessSpecifier AS,
+ Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS,
SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- SourceLocation EllipsisLoc,
- AttributeList *AttrList);
- Decl *ActOnAliasDeclaration(Scope *CurScope,
- AccessSpecifier AS,
+ SourceLocation TypenameLoc, CXXScopeSpec &SS,
+ UnqualifiedId &Name, SourceLocation EllipsisLoc,
+ const ParsedAttributesView &AttrList);
+ Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParams,
- SourceLocation UsingLoc,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- TypeResult Type,
- Decl *DeclFromDeclSpec);
+ SourceLocation UsingLoc, UnqualifiedId &Name,
+ const ParsedAttributesView &AttrList,
+ TypeResult Type, Decl *DeclFromDeclSpec);
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
/// including handling of its default argument expressions.
@@ -4677,7 +4722,7 @@ public:
/// constructed variable.
void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
- /// \brief Helper class that collects exception specifications for
+ /// Helper class that collects exception specifications for
/// implicitly-declared special member functions.
class ImplicitExceptionSpecification {
// Pointer to allow copying
@@ -4704,26 +4749,26 @@ public:
ComputedEST = EST_DynamicNone;
}
- /// \brief Get the computed exception specification type.
+ /// Get the computed exception specification type.
ExceptionSpecificationType getExceptionSpecType() const {
- assert(ComputedEST != EST_ComputedNoexcept &&
+ assert(!isComputedNoexcept(ComputedEST) &&
"noexcept(expr) should not be a possible result");
return ComputedEST;
}
- /// \brief The number of exceptions in the exception specification.
+ /// The number of exceptions in the exception specification.
unsigned size() const { return Exceptions.size(); }
- /// \brief The set of exceptions in the exception specification.
+ /// The set of exceptions in the exception specification.
const QualType *data() const { return Exceptions.data(); }
- /// \brief Integrate another called method into the collected data.
+ /// Integrate another called method into the collected data.
void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
- /// \brief Integrate an invoked expression into the collected data.
+ /// Integrate an invoked expression into the collected data.
void CalledExpr(Expr *E);
- /// \brief Overwrite an EPI's exception specification with this
+ /// Overwrite an EPI's exception specification with this
/// computed exception specification.
FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const {
FunctionProtoType::ExceptionSpecInfo ESI;
@@ -4734,7 +4779,7 @@ public:
/// C++11 [except.spec]p14:
/// The exception-specification is noexcept(false) if the set of
/// potential exceptions of the special member function contains "any"
- ESI.Type = EST_ComputedNoexcept;
+ ESI.Type = EST_NoexceptFalse;
ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(),
tok::kw_false).get();
}
@@ -4742,50 +4787,55 @@ public:
}
};
- /// \brief Determine what sort of exception specification a defaulted
+ /// Determine what sort of exception specification a defaulted
/// copy constructor of a class will have.
ImplicitExceptionSpecification
ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
CXXMethodDecl *MD);
- /// \brief Determine what sort of exception specification a defaulted
+ /// Determine what sort of exception specification a defaulted
/// default constructor of a class will have, and whether the parameter
/// will be const.
ImplicitExceptionSpecification
ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD);
- /// \brief Determine what sort of exception specification a defautled
+ /// Determine what sort of exception specification a defautled
/// copy assignment operator of a class will have, and whether the
/// parameter will be const.
ImplicitExceptionSpecification
ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD);
- /// \brief Determine what sort of exception specification a defaulted move
+ /// Determine what sort of exception specification a defaulted move
/// constructor of a class will have.
ImplicitExceptionSpecification
ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD);
- /// \brief Determine what sort of exception specification a defaulted move
+ /// Determine what sort of exception specification a defaulted move
/// assignment operator of a class will have.
ImplicitExceptionSpecification
ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD);
- /// \brief Determine what sort of exception specification a defaulted
+ /// Determine what sort of exception specification a defaulted
/// destructor of a class will have.
ImplicitExceptionSpecification
ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD);
- /// \brief Determine what sort of exception specification an inheriting
+ /// Determine what sort of exception specification an inheriting
/// constructor of a class will have.
ImplicitExceptionSpecification
ComputeInheritingCtorExceptionSpec(SourceLocation Loc,
CXXConstructorDecl *CD);
- /// \brief Evaluate the implicit exception specification for a defaulted
+ /// Evaluate the implicit exception specification for a defaulted
/// special member function.
void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD);
- /// \brief Check the given exception-specification and update the
+ /// Check the given noexcept-specifier, convert its expression, and compute
+ /// the appropriate ExceptionSpecificationType.
+ ExprResult ActOnNoexceptSpec(SourceLocation NoexceptLoc, Expr *NoexceptExpr,
+ ExceptionSpecificationType &EST);
+
+ /// Check the given exception-specification and update the
/// exception specification information with the results.
void checkExceptionSpecification(bool IsTopLevel,
ExceptionSpecificationType EST,
@@ -4795,11 +4845,11 @@ public:
SmallVectorImpl<QualType> &Exceptions,
FunctionProtoType::ExceptionSpecInfo &ESI);
- /// \brief Determine if we're in a case where we need to (incorrectly) eagerly
+ /// Determine if we're in a case where we need to (incorrectly) eagerly
/// parse an exception specification to work around a libstdc++ bug.
bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D);
- /// \brief Add an exception-specification to the given member function
+ /// Add an exception-specification to the given member function
/// (or member function template). The exception-specification was parsed
/// after the method itself was declared.
void actOnDelayedExceptionSpecification(Decl *Method,
@@ -4811,13 +4861,13 @@ public:
class InheritedConstructorInfo;
- /// \brief Determine if a special member function should have a deleted
+ /// Determine if a special member function should have a deleted
/// definition when it is defaulted.
bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
InheritedConstructorInfo *ICI = nullptr,
bool Diagnose = false);
- /// \brief Declare the implicit default constructor for the given class.
+ /// Declare the implicit default constructor for the given class.
///
/// \param ClassDecl The class declaration into which the implicit
/// default constructor will be added.
@@ -4831,7 +4881,7 @@ public:
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
- /// \brief Declare the implicit destructor for the given class.
+ /// Declare the implicit destructor for the given class.
///
/// \param ClassDecl The class declaration into which the implicit
/// destructor will be added.
@@ -4844,18 +4894,18 @@ public:
void DefineImplicitDestructor(SourceLocation CurrentLocation,
CXXDestructorDecl *Destructor);
- /// \brief Build an exception spec for destructors that don't have one.
+ /// Build an exception spec for destructors that don't have one.
///
/// C++11 says that user-defined destructors with no exception spec get one
/// that looks as if the destructor was implicitly declared.
void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
CXXDestructorDecl *Destructor);
- /// \brief Define the specified inheriting constructor.
+ /// Define the specified inheriting constructor.
void DefineInheritingConstructor(SourceLocation UseLoc,
CXXConstructorDecl *Constructor);
- /// \brief Declare the implicit copy constructor for the given class.
+ /// Declare the implicit copy constructor for the given class.
///
/// \param ClassDecl The class declaration into which the implicit
/// copy constructor will be added.
@@ -4868,7 +4918,7 @@ public:
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
- /// \brief Declare the implicit move constructor for the given class.
+ /// Declare the implicit move constructor for the given class.
///
/// \param ClassDecl The Class declaration into which the implicit
/// move constructor will be added.
@@ -4882,7 +4932,7 @@ public:
void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
- /// \brief Declare the implicit copy assignment operator for the given class.
+ /// Declare the implicit copy assignment operator for the given class.
///
/// \param ClassDecl The class declaration into which the implicit
/// copy assignment operator will be added.
@@ -4890,11 +4940,11 @@ public:
/// \returns The implicitly-declared copy assignment operator.
CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl);
- /// \brief Defines an implicitly-declared copy assignment operator.
+ /// Defines an implicitly-declared copy assignment operator.
void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MethodDecl);
- /// \brief Declare the implicit move assignment operator for the given class.
+ /// Declare the implicit move assignment operator for the given class.
///
/// \param ClassDecl The Class declaration into which the implicit
/// move assignment operator will be added.
@@ -4903,32 +4953,32 @@ public:
/// wasn't declared.
CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl);
- /// \brief Defines an implicitly-declared move assignment operator.
+ /// Defines an implicitly-declared move assignment operator.
void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MethodDecl);
- /// \brief Force the declaration of any implicitly-declared members of this
+ /// Force the declaration of any implicitly-declared members of this
/// class.
void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
- /// \brief Check a completed declaration of an implicit special member.
+ /// Check a completed declaration of an implicit special member.
void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
- /// \brief Determine whether the given function is an implicitly-deleted
+ /// Determine whether the given function is an implicitly-deleted
/// special member function.
bool isImplicitlyDeleted(FunctionDecl *FD);
- /// \brief Check whether 'this' shows up in the type of a static member
+ /// Check whether 'this' shows up in the type of a static member
/// function after the (naturally empty) cv-qualifier-seq would be.
///
/// \returns true if an error occurred.
bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method);
- /// \brief Whether this' shows up in the exception specification of a static
+ /// Whether this' shows up in the exception specification of a static
/// member function.
bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
- /// \brief Check whether 'this' shows up in the attributes of the given
+ /// Check whether 'this' shows up in the attributes of the given
/// static member function.
///
/// \returns true if an error occurred.
@@ -4950,6 +5000,9 @@ public:
SourceLocation NameLoc,
IdentifierInfo &Name);
+ ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext);
ParsedType getDestructorName(SourceLocation TildeLoc,
IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec &SS,
@@ -5010,7 +5063,7 @@ public:
void *TyOrExpr,
SourceLocation RParenLoc);
- /// \brief Handle a C++1z fold-expression: ( expr op ... op expr ).
+ /// Handle a C++1z fold-expression: ( expr op ... op expr ).
ExprResult ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
tok::TokenKind Operator,
SourceLocation EllipsisLoc, Expr *RHS,
@@ -5025,17 +5078,17 @@ public:
//// ActOnCXXThis - Parse 'this' pointer.
ExprResult ActOnCXXThis(SourceLocation loc);
- /// \brief Try to retrieve the type of the 'this' pointer.
+ /// Try to retrieve the type of the 'this' pointer.
///
/// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
QualType getCurrentThisType();
- /// \brief When non-NULL, the C++ 'this' expression is allowed despite the
+ /// When non-NULL, the C++ 'this' expression is allowed despite the
/// current context not being a non-static member function. In such cases,
/// this provides the type used for 'this'.
QualType CXXThisTypeOverride;
- /// \brief RAII object used to temporarily allow the C++ 'this' expression
+ /// RAII object used to temporarily allow the C++ 'this' expression
/// to be used, with the given qualifiers on the current class type.
class CXXThisScopeRAII {
Sema &S;
@@ -5043,7 +5096,7 @@ public:
bool Enabled;
public:
- /// \brief Introduce a new scope where 'this' may be allowed (when enabled),
+ /// Introduce a new scope where 'this' may be allowed (when enabled),
/// using the given declaration (which is either a class template or a
/// class) along with the given qualifiers.
/// along with the qualifiers placed on '*this'.
@@ -5053,7 +5106,7 @@ public:
~CXXThisScopeRAII();
};
- /// \brief Make sure the value of 'this' is actually available in the current
+ /// Make sure the value of 'this' is actually available in the current
/// context, if it is a potentially evaluated context.
///
/// \param Loc The location at which the capture of 'this' occurs.
@@ -5073,7 +5126,7 @@ public:
const unsigned *const FunctionScopeIndexToStopAt = nullptr,
bool ByCopy = false);
- /// \brief Determine whether the given type is the type of *this that is used
+ /// Determine whether the given type is the type of *this that is used
/// outside of the body of a member function for a type that is currently
/// being defined.
bool isThisOutsideMemberFunctionBody(QualType BaseType);
@@ -5103,14 +5156,16 @@ public:
/// or class type construction ("ClassType(x,y,z)")
/// or creation of a value-initialized type ("int()").
ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg Exprs,
- SourceLocation RParenLoc);
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization);
ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
MultiExprArg Exprs,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ bool ListInitialization);
/// ActOnCXXNew - Parsed a C++ 'new' expression.
ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
@@ -5132,11 +5187,29 @@ public:
bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
SourceRange R);
+
+ /// The scope in which to find allocation functions.
+ enum AllocationFunctionScope {
+ /// Only look for allocation functions in the global scope.
+ AFS_Global,
+ /// Only look for allocation functions in the scope of the
+ /// allocated class.
+ AFS_Class,
+ /// Look for allocation functions in both the global scope
+ /// and in the scope of the allocated class.
+ AFS_Both
+ };
+
+ /// Finds the overloads of operator new and delete that are appropriate
+ /// for the allocation.
bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
- bool UseGlobal, QualType AllocType, bool IsArray,
+ AllocationFunctionScope NewScope,
+ AllocationFunctionScope DeleteScope,
+ QualType AllocType, bool IsArray,
bool &PassAlignment, MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
- FunctionDecl *&OperatorDelete);
+ FunctionDecl *&OperatorDelete,
+ bool Diagnose = true);
void DeclareGlobalNewDelete();
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
ArrayRef<QualType> Params);
@@ -5165,7 +5238,7 @@ public:
ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen);
- /// \brief Parsed one of the type trait support pseudo-functions.
+ /// Parsed one of the type trait support pseudo-functions.
ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<ParsedType> Args,
SourceLocation RParenLoc);
@@ -5260,7 +5333,7 @@ public:
bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
- /// \brief The parser has parsed a global nested-name-specifier '::'.
+ /// The parser has parsed a global nested-name-specifier '::'.
///
/// \param CCLoc The location of the '::'.
///
@@ -5270,7 +5343,7 @@ public:
/// \returns true if an error occurred, false otherwise.
bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS);
- /// \brief The parser has parsed a '__super' nested-name-specifier.
+ /// The parser has parsed a '__super' nested-name-specifier.
///
/// \param SuperLoc The location of the '__super' keyword.
///
@@ -5287,23 +5360,23 @@ public:
bool *CanCorrect = nullptr);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
- /// \brief Keeps information about an identifier in a nested-name-spec.
+ /// Keeps information about an identifier in a nested-name-spec.
///
struct NestedNameSpecInfo {
- /// \brief The type of the object, if we're parsing nested-name-specifier in
+ /// The type of the object, if we're parsing nested-name-specifier in
/// a member access expression.
ParsedType ObjectType;
- /// \brief The identifier preceding the '::'.
+ /// The identifier preceding the '::'.
IdentifierInfo *Identifier;
- /// \brief The location of the identifier.
+ /// The location of the identifier.
SourceLocation IdentifierLoc;
- /// \brief The location of the '::'.
+ /// The location of the '::'.
SourceLocation CCLoc;
- /// \brief Creates info object for the most typical case.
+ /// Creates info object for the most typical case.
NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
SourceLocation ColonColonLoc, ParsedType ObjectType = ParsedType())
: ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc),
@@ -5329,7 +5402,7 @@ public:
bool *IsCorrectedToColon = nullptr,
bool OnlyNamespace = false);
- /// \brief The parser has parsed a nested-name-specifier 'identifier::'.
+ /// The parser has parsed a nested-name-specifier 'identifier::'.
///
/// \param S The scope in which this nested-name-specifier occurs.
///
@@ -5372,7 +5445,7 @@ public:
NestedNameSpecInfo &IdInfo,
bool EnteringContext);
- /// \brief The parser has parsed a nested-name-specifier
+ /// The parser has parsed a nested-name-specifier
/// 'template[opt] template-name < template-args >::'.
///
/// \param S The scope in which this nested-name-specifier occurs.
@@ -5406,7 +5479,7 @@ public:
SourceLocation CCLoc,
bool EnteringContext);
- /// \brief Given a C++ nested-name-specifier, produce an annotation value
+ /// Given a C++ nested-name-specifier, produce an annotation value
/// that the parser can use later to reconstruct the given
/// nested-name-specifier.
///
@@ -5416,7 +5489,7 @@ public:
/// nested-name-specifier \p SS.
void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
- /// \brief Given an annotation pointer for a nested-name-specifier, restore
+ /// Given an annotation pointer for a nested-name-specifier, restore
/// the nested-name-specifier structure.
///
/// \param Annotation The annotation pointer, produced by
@@ -5458,13 +5531,13 @@ public:
/// initializer for the declaration 'Dcl'.
void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
- /// \brief Create a new lambda closure type.
+ /// Create a new lambda closure type.
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
bool KnownDependent,
LambdaCaptureDefault CaptureDefault);
- /// \brief Start the definition of a lambda expression.
+ /// Start the definition of a lambda expression.
CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
@@ -5472,7 +5545,7 @@ public:
ArrayRef<ParmVarDecl *> Params,
bool IsConstexprSpecified);
- /// \brief Endow the lambda scope info with the relevant properties.
+ /// Endow the lambda scope info with the relevant properties.
void buildLambdaScope(sema::LambdaScopeInfo *LSI,
CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
@@ -5482,7 +5555,7 @@ public:
bool ExplicitResultType,
bool Mutable);
- /// \brief Perform initialization analysis of the init-capture and perform
+ /// Perform initialization analysis of the init-capture and perform
/// any implicit conversions such as an lvalue-to-rvalue conversion if
/// not being used to initialize a reference.
ParsedType actOnLambdaInitCaptureInitialization(
@@ -5495,7 +5568,7 @@ public:
IdentifierInfo *Id,
bool DirectInit, Expr *&Init);
- /// \brief Create a dummy variable within the declcontext of the lambda's
+ /// Create a dummy variable within the declcontext of the lambda's
/// call operator, for name lookup purposes for a lambda init capture.
///
/// CodeGen handles emission of lambda captures, ignoring these dummy
@@ -5505,17 +5578,17 @@ public:
IdentifierInfo *Id,
unsigned InitStyle, Expr *Init);
- /// \brief Build the implicit field for an init-capture.
+ /// Build the implicit field for an init-capture.
FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
- /// \brief Note that we have finished the explicit captures for the
+ /// Note that we have finished the explicit captures for the
/// given lambda.
void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
- /// \brief Introduce the lambda parameters into scope.
+ /// Introduce the lambda parameters into scope.
void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
- /// \brief Deduce a block or lambda's return type based on the return
+ /// Deduce a block or lambda's return type based on the return
/// statements present in the body.
void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
@@ -5536,13 +5609,15 @@ public:
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope);
- /// \brief Does copying/destroying the captured variable have side effects?
- bool CaptureHasSideEffects(const sema::LambdaScopeInfo::Capture &From);
+ /// Does copying/destroying the captured variable have side effects?
+ bool CaptureHasSideEffects(const sema::Capture &From);
- /// \brief Diagnose if an explicit lambda capture is unused.
- void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture &From);
+ /// Diagnose if an explicit lambda capture is unused. Returns true if a
+ /// diagnostic is emitted.
+ bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+ const sema::Capture &From);
- /// \brief Complete a lambda-expression having processed and attached the
+ /// Complete a lambda-expression having processed and attached the
/// lambda body.
ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
sema::LambdaScopeInfo *LSI);
@@ -5552,7 +5627,7 @@ public:
QualType
getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType);
- /// \brief Define the "body" of the conversion from a lambda object to a
+ /// Define the "body" of the conversion from a lambda object to a
/// function pointer.
///
/// This routine doesn't actually define a sensible body; rather, it fills
@@ -5562,7 +5637,7 @@ public:
void DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLoc, CXXConversionDecl *Conv);
- /// \brief Define the "body" of the conversion from a lambda object to a
+ /// Define the "body" of the conversion from a lambda object to a
/// block pointer.
///
/// This routine doesn't actually define a sensible body; rather, it fills
@@ -5650,14 +5725,14 @@ public:
//===--------------------------------------------------------------------===//
// C++ Classes
//
+ CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS);
bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = nullptr);
bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS);
- bool ActOnAccessSpecifier(AccessSpecifier Access,
- SourceLocation ASLoc,
+ bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
SourceLocation ColonLoc,
- AttributeList *Attrs = nullptr);
+ const ParsedAttributesView &Attrs);
NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
@@ -5731,30 +5806,30 @@ public:
void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
CXXRecordDecl *Record);
- /// \brief The list of classes whose vtables have been used within
+ /// The list of classes whose vtables have been used within
/// this translation unit, and the source locations at which the
/// first use occurred.
typedef std::pair<CXXRecordDecl*, SourceLocation> VTableUse;
- /// \brief The list of vtables that are required but have not yet been
+ /// The list of vtables that are required but have not yet been
/// materialized.
SmallVector<VTableUse, 16> VTableUses;
- /// \brief The set of classes whose vtables have been used within
+ /// The set of classes whose vtables have been used within
/// this translation unit, and a bit that will be true if the vtable is
/// required to be emitted (otherwise, it should be emitted only if needed
/// by code generation).
llvm::DenseMap<CXXRecordDecl *, bool> VTablesUsed;
- /// \brief Load any externally-stored vtable uses.
+ /// Load any externally-stored vtable uses.
void LoadExternalVTableUses();
- /// \brief Note that the vtable for the given class was used at the
+ /// Note that the vtable for the given class was used at the
/// given location.
void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
bool DefinitionRequired = false);
- /// \brief Mark the exception specifications of all virtual member functions
+ /// Mark the exception specifications of all virtual member functions
/// in the given class as needed.
void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
const CXXRecordDecl *RD);
@@ -5764,7 +5839,7 @@ public:
void MarkVirtualMembersReferenced(SourceLocation Loc,
const CXXRecordDecl *RD);
- /// \brief Define all of the vtables that have been used in this
+ /// Define all of the vtables that have been used in this
/// translation unit and reference any virtual members used by those
/// vtables.
///
@@ -5778,10 +5853,11 @@ public:
ArrayRef<CXXCtorInitializer*> MemInits,
bool AnyErrors);
- /// \brief Check class-level dllimport/dllexport attribute. The caller must
+ /// Check class-level dllimport/dllexport attribute. The caller must
/// ensure that referenceDLLExportedClassMethods is called some point later
/// when all outer classes of Class are complete.
void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
+ void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class);
void referenceDLLExportedClassMethods();
@@ -5791,11 +5867,15 @@ public:
SourceLocation BaseLoc);
void CheckCompletedCXXClass(CXXRecordDecl *Record);
- void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- Decl *TagDecl,
- SourceLocation LBrac,
+
+ /// Check that the C++ class annoated with "trivial_abi" satisfies all the
+ /// conditions that are needed for the attribute to have an effect.
+ void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD);
+
+ void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
+ Decl *TagDecl, SourceLocation LBrac,
SourceLocation RBrac,
- AttributeList *AttrList);
+ const ParsedAttributesView &AttrList);
void ActOnFinishCXXMemberDecls();
void ActOnFinishCXXNonNestedClass(Decl *D);
@@ -5989,7 +6069,7 @@ public:
void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
- /// \brief When true, access checking violations are treated as SFINAE
+ /// When true, access checking violations are treated as SFINAE
/// failures rather than hard errors.
bool AccessCheckingSFINAE;
@@ -6032,14 +6112,15 @@ public:
bool hasAnyAcceptableTemplateNames(LookupResult &R,
bool AllowFunctionTemplates = true);
- void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
+ bool LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
QualType ObjectType, bool EnteringContext,
- bool &MemberOfUnknownSpecialization);
+ bool &MemberOfUnknownSpecialization,
+ SourceLocation TemplateKWLoc = SourceLocation());
TemplateNameKind isTemplateName(Scope *S,
CXXScopeSpec &SS,
bool hasTemplateKeyword,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Template,
@@ -6107,7 +6188,7 @@ public:
SourceLocation RAngleLoc,
Expr *RequiresClause);
- /// \brief The context in which we are checking a template parameter list.
+ /// The context in which we are checking a template parameter list.
enum TemplateParamListContext {
TPC_ClassTemplate,
TPC_VarTemplate,
@@ -6128,17 +6209,14 @@ public:
ArrayRef<TemplateParameterList *> ParamLists,
bool IsFriend, bool &IsMemberSpecialization, bool &Invalid);
- DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr,
- TemplateParameterList *TemplateParams,
- AccessSpecifier AS,
- SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc,
- unsigned NumOuterTemplateParamLists,
- TemplateParameterList **OuterTemplateParamLists,
- SkipBodyInfo *SkipBody = nullptr);
+ DeclResult CheckClassTemplate(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
+ const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
+ AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
+ TemplateParameterList **OuterTemplateParamLists,
+ SkipBodyInfo *SkipBody = nullptr);
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
QualType NTTPType,
@@ -6147,6 +6225,8 @@ public:
void translateTemplateArguments(const ASTTemplateArgsPtr &In,
TemplateArgumentListInfo &Out);
+ ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
+
void NoteAllFoundTemplates(TemplateName Name);
QualType CheckTemplateIdType(TemplateName Template,
@@ -6163,7 +6243,7 @@ public:
bool IsCtorOrDtorName = false,
bool IsClassName = false);
- /// \brief Parsed an elaborated-type-specifier that refers to a template-id,
+ /// Parsed an elaborated-type-specifier that refers to a template-id,
/// such as \c class T::template apply<U>.
TypeResult ActOnTagTemplateIdType(TagUseKind TUK,
TypeSpecifierType TagSpec,
@@ -6192,6 +6272,8 @@ public:
SourceLocation TemplateLoc,
const TemplateArgumentListInfo *TemplateArgs);
+ void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
+
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -6205,17 +6287,15 @@ public:
TemplateNameKind ActOnDependentTemplateName(
Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
+ const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
TemplateTy &Template, bool AllowInjectedClassName = false);
- DeclResult
- ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc,
- SourceLocation ModulePrivateLoc,
- TemplateIdAnnotation &TemplateId,
- AttributeList *Attr,
- MultiTemplateParamsArg TemplateParameterLists,
- SkipBodyInfo *SkipBody = nullptr);
+ DeclResult ActOnClassTemplateSpecialization(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId,
+ const ParsedAttributesView &Attr,
+ MultiTemplateParamsArg TemplateParameterLists,
+ SkipBodyInfo *SkipBody = nullptr);
bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
TemplateDecl *PrimaryTemplate,
@@ -6248,30 +6328,19 @@ public:
bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
- DeclResult
- ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc,
- AttributeList *Attr);
+ DeclResult ActOnExplicitInstantiation(
+ Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
+ unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
+ TemplateTy Template, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc, const ParsedAttributesView &Attr);
- DeclResult
- ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- AttributeList *Attr);
+ DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec, SourceLocation KWLoc,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ const ParsedAttributesView &Attr);
DeclResult ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
@@ -6287,18 +6356,18 @@ public:
&Converted,
bool &HasDefaultArg);
- /// \brief Specifies the context in which a particular template
+ /// Specifies the context in which a particular template
/// argument is being checked.
enum CheckTemplateArgumentKind {
- /// \brief The template argument was specified in the code or was
+ /// The template argument was specified in the code or was
/// instantiated with some deduced template arguments.
CTAK_Specified,
- /// \brief The template argument was deduced via template argument
+ /// The template argument was deduced via template argument
/// deduction.
CTAK_Deduced,
- /// \brief The template argument was deduced from an array bound
+ /// The template argument was deduced from an array bound
/// via template argument deduction.
CTAK_DeducedFromArrayBound
};
@@ -6312,7 +6381,7 @@ public:
SmallVectorImpl<TemplateArgument> &Converted,
CheckTemplateArgumentKind CTAK = CTAK_Specified);
- /// \brief Check that the given template arguments can be be provided to
+ /// Check that the given template arguments can be be provided to
/// the given template, converting the arguments along the way.
///
/// \param Template The template to which the template arguments are being
@@ -6354,9 +6423,8 @@ public:
QualType InstantiatedParamType, Expr *Arg,
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK = CTAK_Specified);
- bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- TemplateArgumentLoc &Arg,
- unsigned ArgumentPackIndex);
+ bool CheckTemplateTemplateArgument(TemplateParameterList *Params,
+ TemplateArgumentLoc &Arg);
ExprResult
BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
@@ -6366,10 +6434,10 @@ public:
BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc);
- /// \brief Enumeration describing how template parameter lists are compared
+ /// Enumeration describing how template parameter lists are compared
/// for equality.
enum TemplateParameterListEqualKind {
- /// \brief We are matching the template parameter lists of two templates
+ /// We are matching the template parameter lists of two templates
/// that might be redeclarations.
///
/// \code
@@ -6378,7 +6446,7 @@ public:
/// \endcode
TPL_TemplateMatch,
- /// \brief We are matching the template parameter lists of two template
+ /// We are matching the template parameter lists of two template
/// template parameters as part of matching the template parameter lists
/// of two templates that might be redeclarations.
///
@@ -6388,7 +6456,7 @@ public:
/// \endcode
TPL_TemplateTemplateParmMatch,
- /// \brief We are matching the template parameter lists of a template
+ /// We are matching the template parameter lists of a template
/// template argument against the template parameter lists of a template
/// template parameter.
///
@@ -6409,7 +6477,7 @@ public:
bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
- /// \brief Called when the parser has parsed a C++ typename
+ /// Called when the parser has parsed a C++ typename
/// specifier, e.g., "typename T::type".
///
/// \param S The scope in which this typename type occurs.
@@ -6422,7 +6490,7 @@ public:
const CXXScopeSpec &SS, const IdentifierInfo &II,
SourceLocation IdLoc);
- /// \brief Called when the parser has parsed a C++ typename
+ /// Called when the parser has parsed a C++ typename
/// specifier that ends in a template-id, e.g.,
/// "typename MetaFun::template apply<T1, T2>".
///
@@ -6479,74 +6547,74 @@ public:
/// location. Useful for error recovery.
bool isUnexpandedParameterPackPermitted();
- /// \brief The context in which an unexpanded parameter pack is
+ /// The context in which an unexpanded parameter pack is
/// being diagnosed.
///
/// Note that the values of this enumeration line up with the first
/// argument to the \c err_unexpanded_parameter_pack diagnostic.
enum UnexpandedParameterPackContext {
- /// \brief An arbitrary expression.
+ /// An arbitrary expression.
UPPC_Expression = 0,
- /// \brief The base type of a class type.
+ /// The base type of a class type.
UPPC_BaseType,
- /// \brief The type of an arbitrary declaration.
+ /// The type of an arbitrary declaration.
UPPC_DeclarationType,
- /// \brief The type of a data member.
+ /// The type of a data member.
UPPC_DataMemberType,
- /// \brief The size of a bit-field.
+ /// The size of a bit-field.
UPPC_BitFieldWidth,
- /// \brief The expression in a static assertion.
+ /// The expression in a static assertion.
UPPC_StaticAssertExpression,
- /// \brief The fixed underlying type of an enumeration.
+ /// The fixed underlying type of an enumeration.
UPPC_FixedUnderlyingType,
- /// \brief The enumerator value.
+ /// The enumerator value.
UPPC_EnumeratorValue,
- /// \brief A using declaration.
+ /// A using declaration.
UPPC_UsingDeclaration,
- /// \brief A friend declaration.
+ /// A friend declaration.
UPPC_FriendDeclaration,
- /// \brief A declaration qualifier.
+ /// A declaration qualifier.
UPPC_DeclarationQualifier,
- /// \brief An initializer.
+ /// An initializer.
UPPC_Initializer,
- /// \brief A default argument.
+ /// A default argument.
UPPC_DefaultArgument,
- /// \brief The type of a non-type template parameter.
+ /// The type of a non-type template parameter.
UPPC_NonTypeTemplateParameterType,
- /// \brief The type of an exception.
+ /// The type of an exception.
UPPC_ExceptionType,
- /// \brief Partial specialization.
+ /// Partial specialization.
UPPC_PartialSpecialization,
- /// \brief Microsoft __if_exists.
+ /// Microsoft __if_exists.
UPPC_IfExists,
- /// \brief Microsoft __if_not_exists.
+ /// Microsoft __if_not_exists.
UPPC_IfNotExists,
- /// \brief Lambda expression.
+ /// Lambda expression.
UPPC_Lambda,
- /// \brief Block expression,
+ /// Block expression,
UPPC_Block
};
- /// \brief Diagnose unexpanded parameter packs.
+ /// Diagnose unexpanded parameter packs.
///
/// \param Loc The location at which we should emit the diagnostic.
///
@@ -6560,7 +6628,7 @@ public:
UnexpandedParameterPackContext UPPC,
ArrayRef<UnexpandedParameterPack> Unexpanded);
- /// \brief If the given type contains an unexpanded parameter pack,
+ /// If the given type contains an unexpanded parameter pack,
/// diagnose the error.
///
/// \param Loc The source location where a diagnostc should be emitted.
@@ -6572,7 +6640,7 @@ public:
bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T,
UnexpandedParameterPackContext UPPC);
- /// \brief If the given expression contains an unexpanded parameter
+ /// If the given expression contains an unexpanded parameter
/// pack, diagnose the error.
///
/// \param E The expression that is being checked for unexpanded
@@ -6582,7 +6650,7 @@ public:
bool DiagnoseUnexpandedParameterPack(Expr *E,
UnexpandedParameterPackContext UPPC = UPPC_Expression);
- /// \brief If the given nested-name-specifier contains an unexpanded
+ /// If the given nested-name-specifier contains an unexpanded
/// parameter pack, diagnose the error.
///
/// \param SS The nested-name-specifier that is being checked for
@@ -6592,7 +6660,7 @@ public:
bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
UnexpandedParameterPackContext UPPC);
- /// \brief If the given name contains an unexpanded parameter pack,
+ /// If the given name contains an unexpanded parameter pack,
/// diagnose the error.
///
/// \param NameInfo The name (with source location information) that
@@ -6602,7 +6670,7 @@ public:
bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
UnexpandedParameterPackContext UPPC);
- /// \brief If the given template name contains an unexpanded parameter pack,
+ /// If the given template name contains an unexpanded parameter pack,
/// diagnose the error.
///
/// \param Loc The location of the template name.
@@ -6615,7 +6683,7 @@ public:
TemplateName Template,
UnexpandedParameterPackContext UPPC);
- /// \brief If the given template argument contains an unexpanded parameter
+ /// If the given template argument contains an unexpanded parameter
/// pack, diagnose the error.
///
/// \param Arg The template argument that is being checked for unexpanded
@@ -6625,7 +6693,7 @@ public:
bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
UnexpandedParameterPackContext UPPC);
- /// \brief Collect the set of unexpanded parameter packs within the given
+ /// Collect the set of unexpanded parameter packs within the given
/// template argument.
///
/// \param Arg The template argument that will be traversed to find
@@ -6633,7 +6701,7 @@ public:
void collectUnexpandedParameterPacks(TemplateArgument Arg,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
- /// \brief Collect the set of unexpanded parameter packs within the given
+ /// Collect the set of unexpanded parameter packs within the given
/// template argument.
///
/// \param Arg The template argument that will be traversed to find
@@ -6641,7 +6709,7 @@ public:
void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
- /// \brief Collect the set of unexpanded parameter packs within the given
+ /// Collect the set of unexpanded parameter packs within the given
/// type.
///
/// \param T The type that will be traversed to find
@@ -6649,7 +6717,7 @@ public:
void collectUnexpandedParameterPacks(QualType T,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
- /// \brief Collect the set of unexpanded parameter packs within the given
+ /// Collect the set of unexpanded parameter packs within the given
/// type.
///
/// \param TL The type that will be traversed to find
@@ -6657,7 +6725,7 @@ public:
void collectUnexpandedParameterPacks(TypeLoc TL,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
- /// \brief Collect the set of unexpanded parameter packs within the given
+ /// Collect the set of unexpanded parameter packs within the given
/// nested-name-specifier.
///
/// \param NNS The nested-name-specifier that will be traversed to find
@@ -6665,7 +6733,7 @@ public:
void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
- /// \brief Collect the set of unexpanded parameter packs within the given
+ /// Collect the set of unexpanded parameter packs within the given
/// name.
///
/// \param NameInfo The name that will be traversed to find
@@ -6673,7 +6741,7 @@ public:
void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
- /// \brief Invoked when parsing a template argument followed by an
+ /// Invoked when parsing a template argument followed by an
/// ellipsis, which creates a pack expansion.
///
/// \param Arg The template argument preceding the ellipsis, which
@@ -6683,7 +6751,7 @@ public:
ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc);
- /// \brief Invoked when parsing a type followed by an ellipsis, which
+ /// Invoked when parsing a type followed by an ellipsis, which
/// creates a pack expansion.
///
/// \param Type The type preceding the ellipsis, which will become
@@ -6692,20 +6760,20 @@ public:
/// \param EllipsisLoc The location of the ellipsis.
TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc);
- /// \brief Construct a pack expansion type from the pattern of the pack
+ /// Construct a pack expansion type from the pattern of the pack
/// expansion.
TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions);
- /// \brief Construct a pack expansion type from the pattern of the pack
+ /// Construct a pack expansion type from the pattern of the pack
/// expansion.
QualType CheckPackExpansion(QualType Pattern,
SourceRange PatternRange,
SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions);
- /// \brief Invoked when parsing an expression followed by an ellipsis, which
+ /// Invoked when parsing an expression followed by an ellipsis, which
/// creates a pack expansion.
///
/// \param Pattern The expression preceding the ellipsis, which will become
@@ -6714,7 +6782,7 @@ public:
/// \param EllipsisLoc The location of the ellipsis.
ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
- /// \brief Invoked when parsing an expression followed by an ellipsis, which
+ /// Invoked when parsing an expression followed by an ellipsis, which
/// creates a pack expansion.
///
/// \param Pattern The expression preceding the ellipsis, which will become
@@ -6724,7 +6792,7 @@ public:
ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions);
- /// \brief Determine whether we could expand a pack expansion with the
+ /// Determine whether we could expand a pack expansion with the
/// given set of parameter packs into separate arguments by repeatedly
/// transforming the pattern.
///
@@ -6766,7 +6834,7 @@ public:
bool &RetainExpansion,
Optional<unsigned> &NumExpansions);
- /// \brief Determine the number of arguments in the given pack expansion
+ /// Determine the number of arguments in the given pack expansion
/// type.
///
/// This routine assumes that the number of arguments in the expansion is
@@ -6776,7 +6844,7 @@ public:
Optional<unsigned> getNumArgumentsInExpansion(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs);
- /// \brief Determine whether the given declarator contains any unexpanded
+ /// Determine whether the given declarator contains any unexpanded
/// parameter packs.
///
/// This routine is used by the parser to disambiguate function declarators
@@ -6793,7 +6861,7 @@ public:
/// false otherwise.
bool containsUnexpandedParameterPacks(Declarator &D);
- /// \brief Returns the pattern of the pack expansion for a template argument.
+ /// Returns the pattern of the pack expansion for a template argument.
///
/// \param OrigLoc The template argument to expand.
///
@@ -6825,7 +6893,7 @@ public:
QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType,
bool AdjustExceptionSpec = false);
- /// \brief Describes the result of template argument deduction.
+ /// Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
/// template argument deduction, as returned from
@@ -6835,51 +6903,54 @@ public:
/// list (if successful) or the specific template parameters or
/// deduced arguments that were involved in the failure.
enum TemplateDeductionResult {
- /// \brief Template argument deduction was successful.
+ /// Template argument deduction was successful.
TDK_Success = 0,
- /// \brief The declaration was invalid; do nothing.
+ /// The declaration was invalid; do nothing.
TDK_Invalid,
- /// \brief Template argument deduction exceeded the maximum template
+ /// Template argument deduction exceeded the maximum template
/// instantiation depth (which has already been diagnosed).
TDK_InstantiationDepth,
- /// \brief Template argument deduction did not deduce a value
+ /// Template argument deduction did not deduce a value
/// for every template parameter.
TDK_Incomplete,
- /// \brief Template argument deduction produced inconsistent
+ /// Template argument deduction did not deduce a value for every
+ /// expansion of an expanded template parameter pack.
+ TDK_IncompletePack,
+ /// Template argument deduction produced inconsistent
/// deduced values for the given template parameter.
TDK_Inconsistent,
- /// \brief Template argument deduction failed due to inconsistent
+ /// Template argument deduction failed due to inconsistent
/// cv-qualifiers on a template parameter type that would
/// otherwise be deduced, e.g., we tried to deduce T in "const T"
/// but were given a non-const "X".
TDK_Underqualified,
- /// \brief Substitution of the deduced template argument values
+ /// Substitution of the deduced template argument values
/// resulted in an error.
TDK_SubstitutionFailure,
- /// \brief After substituting deduced template arguments, a dependent
+ /// After substituting deduced template arguments, a dependent
/// parameter type did not match the corresponding argument.
TDK_DeducedMismatch,
- /// \brief After substituting deduced template arguments, an element of
+ /// After substituting deduced template arguments, an element of
/// a dependent parameter type did not match the corresponding element
/// of the corresponding argument (when deducing from an initializer list).
TDK_DeducedMismatchNested,
- /// \brief A non-depnedent component of the parameter did not match the
+ /// A non-depnedent component of the parameter did not match the
/// corresponding component of the argument.
TDK_NonDeducedMismatch,
- /// \brief When performing template argument deduction for a function
+ /// When performing template argument deduction for a function
/// template, there were too many call arguments.
TDK_TooManyArguments,
- /// \brief When performing template argument deduction for a function
+ /// When performing template argument deduction for a function
/// template, there were too few call arguments.
TDK_TooFewArguments,
- /// \brief The explicitly-specified template arguments were not valid
+ /// The explicitly-specified template arguments were not valid
/// template arguments for the given template.
TDK_InvalidExplicitArguments,
- /// \brief Checking non-dependent argument conversions failed.
+ /// Checking non-dependent argument conversions failed.
TDK_NonDependentConversionFailure,
- /// \brief Deduction failed; that's all we know.
+ /// Deduction failed; that's all we know.
TDK_MiscellaneousDeductionFailure,
- /// \brief CUDA Target attributes do not match.
+ /// CUDA Target attributes do not match.
TDK_CUDATargetMismatch
};
@@ -6952,16 +7023,16 @@ public:
sema::TemplateDeductionInfo &Info,
bool IsAddressOfFunction = false);
- /// \brief Substitute Replacement for \p auto in \p TypeWithAuto
+ /// Substitute Replacement for \p auto in \p TypeWithAuto
QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
- /// \brief Substitute Replacement for auto in TypeWithAuto
+ /// Substitute Replacement for auto in TypeWithAuto
TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType Replacement);
- /// \brief Completely replace the \c auto in \p TypeWithAuto by
+ /// Completely replace the \c auto in \p TypeWithAuto by
/// \p Replacement. This does not retain any \c auto type sugar.
QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
- /// \brief Result type of DeduceAutoType.
+ /// Result type of DeduceAutoType.
enum DeduceAutoResult {
DAR_Succeeded,
DAR_Failed,
@@ -6978,7 +7049,7 @@ public:
bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose = true);
- /// \brief Declare implicit deduction guides for a class template if we've
+ /// Declare implicit deduction guides for a class template if we've
/// not already done so.
void DeclareImplicitDeductionGuides(TemplateDecl *Template,
SourceLocation Loc);
@@ -7059,7 +7130,7 @@ public:
/// alone is not sufficient to identify the context). This covers template
/// instantiation and various forms of implicitly-generated functions.
struct CodeSynthesisContext {
- /// \brief The kind of template instantiation we are performing
+ /// The kind of template instantiation we are performing
enum SynthesisKind {
/// We are instantiating a template declaration. The entity is
/// the declaration we're instantiating (e.g., a CXXRecordDecl).
@@ -7107,33 +7178,39 @@ public:
/// We are defining a synthesized function (such as a defaulted special
/// member).
DefiningSynthesizedFunction,
+
+ /// Added for Template instantiation observation.
+ /// Memoization means we are _not_ instantiating a template because
+ /// it is already instantiated (but we entered a context where we
+ /// would have had to if it was not already instantiated).
+ Memoization
} Kind;
- /// \brief Was the enclosing context a non-instantiation SFINAE context?
+ /// Was the enclosing context a non-instantiation SFINAE context?
bool SavedInNonInstantiationSFINAEContext;
- /// \brief The point of instantiation or synthesis within the source code.
+ /// The point of instantiation or synthesis within the source code.
SourceLocation PointOfInstantiation;
- /// \brief The entity that is being synthesized.
+ /// The entity that is being synthesized.
Decl *Entity;
- /// \brief The template (or partial specialization) in which we are
+ /// The template (or partial specialization) in which we are
/// performing the instantiation, for substitutions of prior template
/// arguments.
NamedDecl *Template;
- /// \brief The list of template arguments we are substituting, if they
+ /// The list of template arguments we are substituting, if they
/// are not part of the entity.
const TemplateArgument *TemplateArgs;
// FIXME: Wrap this union around more members, or perhaps store the
// kind-specific members in the RAII object owning the context.
union {
- /// \brief The number of template arguments in TemplateArgs.
+ /// The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;
- /// \brief The special member being declared or defined.
+ /// The special member being declared or defined.
CXXSpecialMember SpecialMember;
};
@@ -7142,11 +7219,11 @@ public:
return {TemplateArgs, NumTemplateArgs};
}
- /// \brief The template deduction info object associated with the
+ /// The template deduction info object associated with the
/// substitution or checking of explicit or deduced template arguments.
sema::TemplateDeductionInfo *DeductionInfo;
- /// \brief The source range that covers the construct that cause
+ /// The source range that covers the construct that cause
/// the instantiation, e.g., the template-id that causes a class
/// template instantiation.
SourceRange InstantiationRange;
@@ -7155,12 +7232,12 @@ public:
: Kind(TemplateInstantiation), Entity(nullptr), Template(nullptr),
TemplateArgs(nullptr), NumTemplateArgs(0), DeductionInfo(nullptr) {}
- /// \brief Determines whether this template is an actual instantiation
+ /// Determines whether this template is an actual instantiation
/// that should be counted toward the maximum instantiation depth.
bool isInstantiationRecord() const;
};
- /// \brief List of active code synthesis contexts.
+ /// List of active code synthesis contexts.
///
/// This vector is treated as a stack. As synthesis of one entity requires
/// synthesis of another, additional contexts are pushed onto the stack.
@@ -7173,32 +7250,32 @@ public:
/// by some template instantiation.
llvm::DenseSet<QualType> InstantiatedNonDependentTypes;
- /// \brief Extra modules inspected when performing a lookup during a template
+ /// Extra modules inspected when performing a lookup during a template
/// instantiation. Computed lazily.
SmallVector<Module*, 16> CodeSynthesisContextLookupModules;
- /// \brief Cache of additional modules that should be used for name lookup
+ /// Cache of additional modules that should be used for name lookup
/// within the current template instantiation. Computed lazily; use
/// getLookupModules() to get a complete set.
llvm::DenseSet<Module*> LookupModulesCache;
- /// \brief Get the set of additional modules that should be checked during
+ /// Get the set of additional modules that should be checked during
/// name lookup. A module and its imports become visible when instanting a
/// template defined within it.
llvm::DenseSet<Module*> &getLookupModules();
- /// \brief Map from the most recent declaration of a namespace to the most
+ /// Map from the most recent declaration of a namespace to the most
/// recent visible declaration of that namespace.
llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache;
- /// \brief Whether we are in a SFINAE context that is not associated with
+ /// Whether we are in a SFINAE context that is not associated with
/// template instantiation.
///
/// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside
/// of a template instantiation or template argument deduction.
bool InNonInstantiationSFINAEContext;
- /// \brief The number of \p CodeSynthesisContexts that are not template
+ /// The number of \p CodeSynthesisContexts that are not template
/// instantiations and, therefore, should not be counted as part of the
/// instantiation depth.
///
@@ -7207,7 +7284,7 @@ public:
// FIXME: Should we have a similar limit for other forms of synthesis?
unsigned NonInstantiationEntries;
- /// \brief The depth of the context stack at the point when the most recent
+ /// The depth of the context stack at the point when the most recent
/// error or warning was produced.
///
/// This value is used to suppress printing of redundant context stacks
@@ -7215,7 +7292,15 @@ public:
// FIXME: Does this belong in Sema? It's tough to implement it anywhere else.
unsigned LastEmittedCodeSynthesisContextDepth = 0;
- /// \brief The current index into pack expansion arguments that will be
+ /// The template instantiation callbacks to trace or track
+ /// instantiations (objects can be chained).
+ ///
+ /// This callbacks is used to print, trace or track template
+ /// instantiations as they are being constructed.
+ std::vector<std::unique_ptr<TemplateInstantiationCallback>>
+ TemplateInstCallbacks;
+
+ /// The current index into pack expansion arguments that will be
/// used for substitution of parameter packs.
///
/// The pack expansion index will be -1 to indicate that parameter packs
@@ -7223,7 +7308,7 @@ public:
/// which argument within the parameter pack will be used for substitution.
int ArgumentPackSubstitutionIndex;
- /// \brief RAII object used to change the argument pack substitution index
+ /// RAII object used to change the argument pack substitution index
/// within a \c Sema object.
///
/// See \c ArgumentPackSubstitutionIndex for more information.
@@ -7244,7 +7329,7 @@ public:
friend class ArgumentPackSubstitutionRAII;
- /// \brief For each declaration that involved template argument deduction, the
+ /// For each declaration that involved template argument deduction, the
/// set of diagnostics that were suppressed during that template argument
/// deduction.
///
@@ -7253,7 +7338,7 @@ public:
SuppressedDiagnosticsMap;
SuppressedDiagnosticsMap SuppressedDiagnostics;
- /// \brief A stack object to be created when performing template
+ /// A stack object to be created when performing template
/// instantiation.
///
/// Construction of an object of type \c InstantiatingTemplate
@@ -7265,7 +7350,7 @@ public:
/// Destruction of this object will pop the named instantiation off
/// the stack.
struct InstantiatingTemplate {
- /// \brief Note that we are instantiating a class template,
+ /// Note that we are instantiating a class template,
/// function template, variable template, alias template,
/// or a member thereof.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -7273,20 +7358,20 @@ public:
SourceRange InstantiationRange = SourceRange());
struct ExceptionSpecification {};
- /// \brief Note that we are instantiating an exception specification
+ /// Note that we are instantiating an exception specification
/// of a function template.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionDecl *Entity, ExceptionSpecification,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are instantiating a default argument in a
+ /// Note that we are instantiating a default argument in a
/// template-id.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateParameter Param, TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are substituting either explicitly-specified or
+ /// Note that we are substituting either explicitly-specified or
/// deduced template arguments during function template argument deduction.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionTemplateDecl *FunctionTemplate,
@@ -7295,7 +7380,7 @@ public:
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are instantiating as part of template
+ /// Note that we are instantiating as part of template
/// argument deduction for a class template declaration.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template,
@@ -7303,7 +7388,7 @@ public:
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are instantiating as part of template
+ /// Note that we are instantiating as part of template
/// argument deduction for a class template partial
/// specialization.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -7312,7 +7397,7 @@ public:
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are instantiating as part of template
+ /// Note that we are instantiating as part of template
/// argument deduction for a variable template partial
/// specialization.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -7321,14 +7406,14 @@ public:
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are instantiating a default argument for a function
+ /// Note that we are instantiating a default argument for a function
/// parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange = SourceRange());
- /// \brief Note that we are substituting prior template arguments into a
+ /// Note that we are substituting prior template arguments into a
/// non-type parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template,
@@ -7336,7 +7421,7 @@ public:
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
- /// \brief Note that we are substituting prior template arguments into a
+ /// Note that we are substituting prior template arguments into a
/// template template parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template,
@@ -7344,7 +7429,7 @@ public:
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
- /// \brief Note that we are checking the default template argument
+ /// Note that we are checking the default template argument
/// against the template parameter for a given template-id.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template,
@@ -7353,16 +7438,16 @@ public:
SourceRange InstantiationRange);
- /// \brief Note that we have finished instantiating this template.
+ /// Note that we have finished instantiating this template.
void Clear();
~InstantiatingTemplate() { Clear(); }
- /// \brief Determines whether we have exceeded the maximum
+ /// Determines whether we have exceeded the maximum
/// recursive template instantiations.
bool isInvalid() const { return Invalid; }
- /// \brief Determine whether we are already instantiating this
+ /// Determine whether we are already instantiating this
/// specialization in some surrounding active instantiation.
bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
@@ -7407,7 +7492,7 @@ public:
void PrintPragmaAttributeInstantiationPoint();
- /// \brief Determines whether we are currently in a context where
+ /// Determines whether we are currently in a context where
/// template argument substitution failures are not considered
/// errors.
///
@@ -7417,7 +7502,7 @@ public:
/// diagnostics that will be suppressed.
Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const;
- /// \brief Determines whether we are currently in a context that
+ /// Determines whether we are currently in a context that
/// is not evaluated as per C++ [expr] p5.
bool isUnevaluatedContext() const {
assert(!ExprEvalContexts.empty() &&
@@ -7425,7 +7510,7 @@ public:
return ExprEvalContexts.back().isUnevaluated();
}
- /// \brief RAII class used to determine whether SFINAE has
+ /// RAII class used to determine whether SFINAE has
/// trapped any errors that occur during template argument
/// deduction.
class SFINAETrap {
@@ -7458,13 +7543,13 @@ public:
PrevLastDiagnosticIgnored);
}
- /// \brief Determine whether any SFINAE errors have been trapped.
+ /// Determine whether any SFINAE errors have been trapped.
bool hasErrorOccurred() const {
return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
}
};
- /// \brief RAII class used to indicate that we are performing provisional
+ /// RAII class used to indicate that we are performing provisional
/// semantic analysis to determine the validity of a construct, so
/// typo-correction and diagnostics in the immediate context (not within
/// implicitly-instantiated templates) should be suppressed.
@@ -7484,30 +7569,30 @@ public:
}
};
- /// \brief The current instantiation scope used to store local
+ /// The current instantiation scope used to store local
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
- /// \brief Tracks whether we are in a context where typo correction is
+ /// Tracks whether we are in a context where typo correction is
/// disabled.
bool DisableTypoCorrection;
- /// \brief The number of typos corrected by CorrectTypo.
+ /// The number of typos corrected by CorrectTypo.
unsigned TyposCorrected;
typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
- /// \brief A cache containing identifiers for which typo correction failed and
+ /// A cache containing identifiers for which typo correction failed and
/// their locations, so that repeated attempts to correct an identifier in a
/// given location are ignored if typo correction already failed for it.
IdentifierSourceLocations TypoCorrectionFailures;
- /// \brief Worker object for performing CFG-based warnings.
+ /// Worker object for performing CFG-based warnings.
sema::AnalysisBasedWarnings AnalysisWarnings;
threadSafety::BeforeSet *ThreadSafetyDeclCache;
- /// \brief An entity for which implicit template instantiation is required.
+ /// An entity for which implicit template instantiation is required.
///
/// The source location associated with the declaration is the first place in
/// the source code where the declaration was "used". It is not necessarily
@@ -7517,10 +7602,14 @@ public:
/// because users will need to know what code triggered the instantiation.
typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
- /// \brief The queue of implicit template instantiations that are required
+ /// The queue of implicit template instantiations that are required
/// but have not yet been performed.
std::deque<PendingImplicitInstantiation> PendingInstantiations;
+ /// Queue of implicit template instantiations that cannot be performed
+ /// eagerly.
+ SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
+
class GlobalEagerInstantiationScope {
public:
GlobalEagerInstantiationScope(Sema &S, bool Enabled)
@@ -7559,7 +7648,7 @@ public:
bool Enabled;
};
- /// \brief The queue of implicit template instantiations that are required
+ /// The queue of implicit template instantiations that are required
/// and must be performed within the current local scope.
///
/// This queue is only used for member functions of local classes in
@@ -7658,7 +7747,7 @@ public:
ExprResult SubstExpr(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs);
- /// \brief Substitute the given template arguments into a list of
+ /// Substitute the given template arguments into a list of
/// expressions, expanding pack expansions if required.
///
/// \param Exprs The list of expressions to substitute into.
@@ -7678,6 +7767,10 @@ public:
StmtResult SubstStmt(Stmt *S,
const MultiLevelTemplateArgumentList &TemplateArgs);
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
Decl *SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -7835,20 +7928,14 @@ public:
SourceLocation rAngleLoc);
void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
- Decl *ActOnStartClassInterface(Scope *S,
- SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- ObjCTypeParamList *typeParamList,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- ArrayRef<ParsedType> SuperTypeArgs,
- SourceRange SuperTypeArgsRange,
- Decl * const *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList);
+ Decl *ActOnStartClassInterface(
+ Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+ SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+ IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
+ Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList);
void ActOnSuperClassOfClassInterface(Scope *S,
SourceLocation AtInterfaceLoc,
@@ -7876,24 +7963,18 @@ public:
const ObjCList<ObjCProtocolDecl> &PList);
Decl *ActOnStartProtocolInterface(
- SourceLocation AtProtoInterfaceLoc,
- IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
- Decl * const *ProtoRefNames, unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList);
-
- Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- ObjCTypeParamList *typeParamList,
- IdentifierInfo *CategoryName,
- SourceLocation CategoryLoc,
- Decl * const *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList);
+ SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
+ SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
+ unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList);
+
+ Decl *ActOnStartCategoryInterface(
+ SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+ SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+ IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+ Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList);
Decl *ActOnStartClassImplementation(
SourceLocation AtClassImplLoc,
@@ -7916,9 +7997,10 @@ public:
ArrayRef<ObjCTypeParamList *> TypeParamLists,
unsigned NumElts);
- DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
- ArrayRef<IdentifierLocPair> IdentList,
- AttributeList *attrList);
+ DeclGroupPtrTy
+ ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+ ArrayRef<IdentifierLocPair> IdentList,
+ const ParsedAttributesView &attrList);
void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
ArrayRef<IdentifierLocPair> ProtocolId,
@@ -8053,22 +8135,21 @@ public:
ObjCDeclSpec DeclSpec;
/// ArgAttrs - Attribute list for this argument.
- AttributeList *ArgAttrs;
+ ParsedAttributesView ArgAttrs;
};
Decl *ActOnMethodDeclaration(
- Scope *S,
- SourceLocation BeginLoc, // location of the + or -.
- SourceLocation EndLoc, // location of the ; or {.
- tok::TokenKind MethodType,
- ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
- ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
- // optional arguments. The number of types/arguments is obtained
- // from the Sel.getNumArgs().
- ObjCArgInfo *ArgInfo,
- DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
- AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind,
- bool isVariadic, bool MethodDefinition);
+ Scope *S,
+ SourceLocation BeginLoc, // location of the + or -.
+ SourceLocation EndLoc, // location of the ; or {.
+ tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
+ // optional arguments. The number of types/arguments is obtained
+ // from the Sel.getNumArgs().
+ ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
+ unsigned CNumArgs, // c-style args
+ const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind,
+ bool isVariadic, bool MethodDefinition);
ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
const ObjCObjectPointerType *OPT,
@@ -8096,14 +8177,14 @@ public:
ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc);
- /// \brief Describes the kind of message expression indicated by a message
+ /// Describes the kind of message expression indicated by a message
/// send that starts with an identifier.
enum ObjCMessageKind {
- /// \brief The message is sent to 'super'.
+ /// The message is sent to 'super'.
ObjCSuperMessage,
- /// \brief The message is an instance message.
+ /// The message is an instance message.
ObjCInstanceMessage,
- /// \brief The message is a class message, and the identifier is a type
+ /// The message is a class message, and the identifier is a type
/// name.
ObjCClassMessage
};
@@ -8212,12 +8293,12 @@ public:
bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
- /// \brief Check whether the given new method is a valid override of the
+ /// Check whether the given new method is a valid override of the
/// given overridden method, and set any properties that should be inherited.
void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
const ObjCMethodDecl *Overridden);
- /// \brief Describes the compatibility of a result type with its method.
+ /// Describes the compatibility of a result type with its method.
enum ResultTypeCompatibilityKind {
RTC_Compatible,
RTC_Incompatible,
@@ -8274,7 +8355,7 @@ public:
LangOptions::PragmaMSPointersToMembersKind Kind,
SourceLocation PragmaLoc);
- /// \brief Called on well formed \#pragma vtordisp().
+ /// Called on well formed \#pragma vtordisp().
void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
SourceLocation PragmaLoc,
MSVtorDispAttr::Mode Value);
@@ -8293,22 +8374,22 @@ public:
int SectionFlags,
SourceLocation PragmaSectionLocation);
- /// \brief Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg.
+ /// Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg.
void ActOnPragmaMSSeg(SourceLocation PragmaLocation,
PragmaMsStackAction Action,
llvm::StringRef StackSlotLabel,
StringLiteral *SegmentName,
llvm::StringRef PragmaName);
- /// \brief Called on well formed \#pragma section().
+ /// Called on well formed \#pragma section().
void ActOnPragmaMSSection(SourceLocation PragmaLocation,
int SectionFlags, StringLiteral *SegmentName);
- /// \brief Called on well-formed \#pragma init_seg().
+ /// Called on well-formed \#pragma init_seg().
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
StringLiteral *SegmentName);
- /// \brief Called on #pragma clang __debug dump II
+ /// Called on #pragma clang __debug dump II
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
/// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
@@ -8384,35 +8465,34 @@ public:
/// the appropriate attribute.
void AddCFAuditedAttribute(Decl *D);
- /// \brief Called on well-formed '\#pragma clang attribute push'.
- void ActOnPragmaAttributePush(AttributeList &Attribute,
- SourceLocation PragmaLoc,
+ /// Called on well-formed '\#pragma clang attribute push'.
+ void ActOnPragmaAttributePush(ParsedAttr &Attribute, SourceLocation PragmaLoc,
attr::ParsedSubjectMatchRuleSet Rules);
- /// \brief Called on well-formed '\#pragma clang attribute pop'.
+ /// Called on well-formed '\#pragma clang attribute pop'.
void ActOnPragmaAttributePop(SourceLocation PragmaLoc);
- /// \brief Adds the attributes that have been specified using the
+ /// Adds the attributes that have been specified using the
/// '\#pragma clang attribute push' directives to the given declaration.
void AddPragmaAttributes(Scope *S, Decl *D);
void DiagnoseUnterminatedPragmaAttribute();
- /// \brief Called on well formed \#pragma clang optimize.
+ /// Called on well formed \#pragma clang optimize.
void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
- /// \brief Get the location for the currently active "\#pragma clang optimize
+ /// Get the location for the currently active "\#pragma clang optimize
/// off". If this location is invalid, then the state of the pragma is "on".
SourceLocation getOptimizeOffPragmaLocation() const {
return OptimizeOffPragmaLocation;
}
- /// \brief Only called on function definitions; if there is a pragma in scope
+ /// Only called on function definitions; if there is a pragma in scope
/// with the effect of a range-based optnone, consider marking the function
/// with attribute optnone.
void AddRangeBasedOptnone(FunctionDecl *FD);
- /// \brief Adds the 'optnone' attribute to the function declaration if there
+ /// Adds the 'optnone' attribute to the function declaration if there
/// are no conflicts; Loc represents the location causing the 'optnone'
/// attribute to be added (usually because of a pragma).
void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
@@ -8473,8 +8553,11 @@ public:
StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E,
bool IsImplicit = false);
StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs);
+ bool buildCoroutineParameterMoves(SourceLocation Loc);
VarDecl *buildCoroutinePromise(SourceLocation Loc);
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
+ ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
+ SourceLocation FuncLoc);
//===--------------------------------------------------------------------===//
// OpenCL extensions.
@@ -8493,36 +8576,36 @@ public:
CurrOpenCLExtension = Ext;
}
- /// \brief Set OpenCL extensions for a type which can only be used when these
+ /// Set OpenCL extensions for a type which can only be used when these
/// OpenCL extensions are enabled. If \p Exts is empty, do nothing.
/// \param Exts A space separated list of OpenCL extensions.
void setOpenCLExtensionForType(QualType T, llvm::StringRef Exts);
- /// \brief Set OpenCL extensions for a declaration which can only be
+ /// Set OpenCL extensions for a declaration which can only be
/// used when these OpenCL extensions are enabled. If \p Exts is empty, do
/// nothing.
/// \param Exts A space separated list of OpenCL extensions.
void setOpenCLExtensionForDecl(Decl *FD, llvm::StringRef Exts);
- /// \brief Set current OpenCL extensions for a type which can only be used
+ /// Set current OpenCL extensions for a type which can only be used
/// when these OpenCL extensions are enabled. If current OpenCL extension is
/// empty, do nothing.
void setCurrentOpenCLExtensionForType(QualType T);
- /// \brief Set current OpenCL extensions for a declaration which
+ /// Set current OpenCL extensions for a declaration which
/// can only be used when these OpenCL extensions are enabled. If current
/// OpenCL extension is empty, do nothing.
void setCurrentOpenCLExtensionForDecl(Decl *FD);
bool isOpenCLDisabledDecl(Decl *FD);
- /// \brief Check if type \p T corresponding to declaration specifier \p DS
+ /// Check if type \p T corresponding to declaration specifier \p DS
/// is disabled due to required OpenCL extensions being disabled. If so,
/// emit diagnostics.
/// \return true if type is disabled.
bool checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType T);
- /// \brief Check if declaration \p D used by expression \p E
+ /// Check if declaration \p D used by expression \p E
/// is disabled due to required OpenCL extensions being disabled. If so,
/// emit diagnostics.
/// \return true if type is disabled.
@@ -8535,7 +8618,7 @@ private:
void *VarDataSharingAttributesStack;
/// Set to true inside '#pragma omp declare target' region.
bool IsInOpenMPDeclareTargetContext = false;
- /// \brief Initialization of data-sharing attributes stack.
+ /// Initialization of data-sharing attributes stack.
void InitDataSharingAttributesStack();
void DestroyDataSharingAttributesStack();
ExprResult
@@ -8570,87 +8653,86 @@ private:
SourceRange SrcRange = SourceRange());
public:
- /// \brief Return true if the provided declaration \a VD should be captured by
+ /// Return true if the provided declaration \a VD should be captured by
/// reference.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
- bool IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level);
+ bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const;
- /// \brief Check if the specified variable is used in one of the private
+ /// Check if the specified variable is used in one of the private
/// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
/// constructs.
- VarDecl *IsOpenMPCapturedDecl(ValueDecl *D);
+ VarDecl *isOpenMPCapturedDecl(ValueDecl *D) const;
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
ExprObjectKind OK, SourceLocation Loc);
- /// \brief Check if the specified variable is used in 'private' clause.
+ /// Check if the specified variable is used in 'private' clause.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
- bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level);
+ bool isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const;
/// 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);
+ void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level);
- /// \brief Check if the specified variable is captured by 'target' directive.
+ /// Check if the specified variable is captured by 'target' directive.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
- bool isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level);
+ bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level) const;
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
Expr *Op);
- /// \brief Called on start of new data sharing attribute block.
+ /// Called on start of new data sharing attribute block.
void StartOpenMPDSABlock(OpenMPDirectiveKind K,
const DeclarationNameInfo &DirName, Scope *CurScope,
SourceLocation Loc);
- /// \brief Start analysis of clauses.
+ /// Start analysis of clauses.
void StartOpenMPClause(OpenMPClauseKind K);
- /// \brief End analysis of clauses.
+ /// End analysis of clauses.
void EndOpenMPClause();
- /// \brief Called on end of data sharing attribute block.
+ /// Called on end of data sharing attribute block.
void EndOpenMPDSABlock(Stmt *CurDirective);
- /// \brief Check if the current region is an OpenMP loop region and if it is,
+ /// Check if the current region is an OpenMP loop region and if it is,
/// mark loop control variable, used in \p Init for loop initialization, as
/// private by default.
/// \param Init First part of the for loop.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init);
// OpenMP directives and clauses.
- /// \brief Called on correct id-expression from the '#pragma omp
+ /// Called on correct id-expression from the '#pragma omp
/// threadprivate'.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
CXXScopeSpec &ScopeSpec,
const DeclarationNameInfo &Id);
- /// \brief Called on well-formed '#pragma omp threadprivate'.
+ /// Called on well-formed '#pragma omp threadprivate'.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
SourceLocation Loc,
ArrayRef<Expr *> VarList);
- /// \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
- OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
- SourceLocation Loc,
- ArrayRef<Expr *> VarList);
- /// \brief Check if the specified type is allowed to be used in 'omp declare
+ /// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
+ OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+ /// Check if the specified type is allowed to be used in 'omp declare
/// reduction' construct.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
TypeResult ParsedType);
- /// \brief Called on start of '#pragma omp declare reduction'.
+ /// Called on start of '#pragma omp declare reduction'.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(
Scope *S, DeclContext *DC, DeclarationName Name,
ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
AccessSpecifier AS, Decl *PrevDeclInScope = nullptr);
- /// \brief Initialize declare reduction construct initializer.
+ /// Initialize declare reduction construct initializer.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D);
- /// \brief Finish current declare reduction construct initializer.
+ /// Finish current declare reduction construct initializer.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner);
- /// \brief Initialize declare reduction construct initializer.
+ /// Initialize declare reduction construct initializer.
/// \return omp_priv variable.
VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D);
- /// \brief Finish current declare reduction construct initializer.
+ /// Finish current declare reduction construct initializer.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
VarDecl *OmpPrivParm);
- /// \brief Called at the end of '#pragma omp declare reduction'.
+ /// Called at the end of '#pragma omp declare reduction'.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(
Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid);
@@ -8682,9 +8764,9 @@ public:
/// Return the number of captured regions created for an OpenMP directive.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
- /// \brief Initialization of captured region for OpenMP region.
+ /// Initialization of captured region for OpenMP region.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
- /// \brief End of OpenMP region.
+ /// End of OpenMP region.
///
/// \param S Statement associated with the current OpenMP region.
/// \param Clauses List of clauses for the current OpenMP region.
@@ -8695,230 +8777,220 @@ public:
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp parallel' after parsing
+ /// Called on well-formed '\#pragma omp parallel' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp simd' after parsing
+ using VarsWithInheritedDSAType =
+ llvm::SmallDenseMap<const ValueDecl *, const Expr *, 4>;
+ /// Called on well-formed '\#pragma omp simd' after parsing
/// of the associated statement.
- StmtResult ActOnOpenMPSimdDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp for' after parsing
+ StmtResult
+ ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp for' after parsing
/// of the associated statement.
- StmtResult ActOnOpenMPForDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp for simd' after parsing
+ StmtResult
+ ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp for simd' after parsing
/// of the associated statement.
- StmtResult ActOnOpenMPForSimdDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp sections' after parsing
+ StmtResult
+ ActOnOpenMPForSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp sections' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp section' after parsing of the
+ /// Called on well-formed '\#pragma omp section' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp single' after parsing of the
+ /// Called on well-formed '\#pragma omp single' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp master' after parsing of the
+ /// Called on well-formed '\#pragma omp master' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp critical' after parsing of the
+ /// Called on well-formed '\#pragma omp critical' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp parallel for' after parsing
+ /// Called on well-formed '\#pragma omp parallel for' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp parallel for simd' after
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp parallel for simd' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp parallel sections' after
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp parallel sections' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp task' after parsing of the
+ /// Called on well-formed '\#pragma omp task' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp taskyield'.
+ /// Called on well-formed '\#pragma omp taskyield'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp barrier'.
+ /// Called on well-formed '\#pragma omp barrier'.
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp taskwait'.
+ /// Called on well-formed '\#pragma omp taskwait'.
StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp taskgroup'.
+ /// Called on well-formed '\#pragma omp taskgroup'.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp flush'.
+ /// Called on well-formed '\#pragma omp flush'.
StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp ordered' after parsing of the
+ /// Called on well-formed '\#pragma omp ordered' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp atomic' after parsing of the
+ /// Called on well-formed '\#pragma omp atomic' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp target' after parsing of the
+ /// Called on well-formed '\#pragma omp target' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp target data' after parsing of
+ /// Called on well-formed '\#pragma omp target data' after parsing of
/// the associated statement.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp target enter data' after
+ /// Called on well-formed '\#pragma omp target enter data' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AStmt);
- /// \brief Called on well-formed '\#pragma omp target exit data' after
+ /// Called on well-formed '\#pragma omp target exit data' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AStmt);
- /// \brief Called on well-formed '\#pragma omp target parallel' after
+ /// Called on well-formed '\#pragma omp target parallel' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp target parallel for' after
+ /// Called on well-formed '\#pragma omp target parallel for' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp teams' after parsing of the
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp teams' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed '\#pragma omp cancellation point'.
+ /// Called on well-formed '\#pragma omp cancellation point'.
StmtResult
ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion);
- /// \brief Called on well-formed '\#pragma omp cancel'.
+ /// Called on well-formed '\#pragma omp cancel'.
StmtResult ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion);
- /// \brief Called on well-formed '\#pragma omp taskloop' after parsing of the
+ /// Called on well-formed '\#pragma omp taskloop' after parsing of the
/// associated statement.
- StmtResult ActOnOpenMPTaskLoopDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp taskloop simd' after parsing of
+ StmtResult
+ ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp taskloop simd' after parsing of
/// the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp distribute' after parsing
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp distribute' after parsing
/// of the associated statement.
- StmtResult ActOnOpenMPDistributeDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp target update'.
+ StmtResult
+ ActOnOpenMPDistributeDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp target update'.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AStmt);
- /// \brief Called on well-formed '\#pragma omp distribute parallel for' after
+ /// Called on well-formed '\#pragma omp distribute parallel for' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp distribute parallel for simd'
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp distribute parallel for simd'
/// after parsing of the associated statement.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp distribute simd' after
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp distribute simd' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp target parallel for simd' after
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp target parallel for simd' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
- /// \brief Called on well-formed '\#pragma omp target simd' after parsing of
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp target simd' after parsing of
/// the associated statement.
- StmtResult ActOnOpenMPTargetSimdDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ StmtResult
+ ActOnOpenMPTargetSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp teams distribute' after parsing of
/// the associated statement.
StmtResult ActOnOpenMPTeamsDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp teams distribute simd' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp teams distribute parallel for simd'
/// after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp teams distribute parallel for'
/// after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp target teams' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
@@ -8929,36 +9001,32 @@ public:
/// of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp target teams distribute parallel for'
/// after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp target teams distribute parallel for
/// simd' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp target teams distribute simd' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Checks correctness of linear modifiers.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
SourceLocation LinLoc);
/// Checks that the specified declaration matches requirements for the linear
/// decls.
- bool CheckOpenMPLinearDecl(ValueDecl *D, SourceLocation ELoc,
+ bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
OpenMPLinearClauseKind LinKind, QualType Type);
- /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of
+ /// Called on well-formed '\#pragma omp declare simd' after parsing of
/// the associated method/function.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(
DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS,
@@ -8971,50 +9039,50 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'if' clause.
+ /// Called on well-formed 'if' clause.
OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation NameModifierLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'final' clause.
+ /// Called on well-formed 'final' clause.
OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'num_threads' clause.
+ /// Called on well-formed 'num_threads' clause.
OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'safelen' clause.
+ /// Called on well-formed 'safelen' clause.
OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'simdlen' clause.
+ /// Called on well-formed 'simdlen' clause.
OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'collapse' clause.
+ /// Called on well-formed 'collapse' clause.
OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'ordered' clause.
+ /// Called on well-formed 'ordered' clause.
OMPClause *
ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc,
SourceLocation LParenLoc = SourceLocation(),
Expr *NumForLoops = nullptr);
- /// \brief Called on well-formed 'grainsize' clause.
+ /// Called on well-formed 'grainsize' clause.
OMPClause *ActOnOpenMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'num_tasks' clause.
+ /// Called on well-formed 'num_tasks' clause.
OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'hint' clause.
+ /// Called on well-formed 'hint' clause.
OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
@@ -9025,13 +9093,13 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'default' clause.
+ /// Called on well-formed 'default' clause.
OMPClause *ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
SourceLocation KindLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'proc_bind' clause.
+ /// Called on well-formed 'proc_bind' clause.
OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
SourceLocation KindLoc,
SourceLocation StartLoc,
@@ -9043,7 +9111,7 @@ public:
SourceLocation StartLoc, SourceLocation LParenLoc,
ArrayRef<SourceLocation> ArgumentsLoc, SourceLocation DelimLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'schedule' clause.
+ /// Called on well-formed 'schedule' clause.
OMPClause *ActOnOpenMPScheduleClause(
OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
@@ -9052,37 +9120,37 @@ public:
OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'nowait' clause.
+ /// Called on well-formed 'nowait' clause.
OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'untied' clause.
+ /// Called on well-formed 'untied' clause.
OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'mergeable' clause.
+ /// Called on well-formed 'mergeable' clause.
OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'read' clause.
+ /// Called on well-formed 'read' clause.
OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'write' clause.
+ /// Called on well-formed 'write' clause.
OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'update' clause.
+ /// Called on well-formed 'update' clause.
OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'capture' clause.
+ /// Called on well-formed 'capture' clause.
OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'seq_cst' clause.
+ /// Called on well-formed 'seq_cst' clause.
OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'threads' clause.
+ /// Called on well-formed 'threads' clause.
OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'simd' clause.
+ /// Called on well-formed 'simd' clause.
OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'nogroup' clause.
+ /// Called on well-formed 'nogroup' clause.
OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc,
SourceLocation EndLoc);
@@ -9095,27 +9163,27 @@ public:
OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation DepLinMapLoc);
- /// \brief Called on well-formed 'private' clause.
+ /// Called on well-formed 'private' clause.
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'firstprivate' clause.
+ /// Called on well-formed 'firstprivate' clause.
OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'lastprivate' clause.
+ /// Called on well-formed 'lastprivate' clause.
OMPClause *ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'shared' clause.
+ /// Called on well-formed 'shared' clause.
OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'reduction' clause.
+ /// Called on well-formed 'reduction' clause.
OMPClause *ActOnOpenMPReductionClause(
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
@@ -9136,80 +9204,80 @@ public:
CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions = llvm::None);
- /// \brief Called on well-formed 'linear' clause.
+ /// Called on well-formed 'linear' clause.
OMPClause *
ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
SourceLocation StartLoc, SourceLocation LParenLoc,
OpenMPLinearClauseKind LinKind, SourceLocation LinLoc,
SourceLocation ColonLoc, SourceLocation EndLoc);
- /// \brief Called on well-formed 'aligned' clause.
+ /// Called on well-formed 'aligned' clause.
OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList,
Expr *Alignment,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'copyin' clause.
+ /// Called on well-formed 'copyin' clause.
OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'copyprivate' clause.
+ /// Called on well-formed 'copyprivate' clause.
OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'flush' pseudo clause.
+ /// Called on well-formed 'flush' pseudo clause.
OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'depend' clause.
+ /// Called on well-formed 'depend' clause.
OMPClause *
ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'device' clause.
+ /// Called on well-formed 'device' clause.
OMPClause *ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'map' clause.
+ /// Called on well-formed 'map' clause.
OMPClause *
ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation MapLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc);
- /// \brief Called on well-formed 'num_teams' clause.
+ /// Called on well-formed 'num_teams' clause.
OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'thread_limit' clause.
+ /// Called on well-formed 'thread_limit' clause.
OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'priority' clause.
+ /// Called on well-formed 'priority' clause.
OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'dist_schedule' clause.
+ /// Called on well-formed 'dist_schedule' clause.
OMPClause *ActOnOpenMPDistScheduleClause(
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc,
SourceLocation CommaLoc, SourceLocation EndLoc);
- /// \brief Called on well-formed 'defaultmap' clause.
+ /// Called on well-formed 'defaultmap' clause.
OMPClause *ActOnOpenMPDefaultmapClause(
OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
SourceLocation KindLoc, SourceLocation EndLoc);
- /// \brief Called on well-formed 'to' clause.
+ /// Called on well-formed 'to' clause.
OMPClause *ActOnOpenMPToClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'from' clause.
+ /// Called on well-formed 'from' clause.
OMPClause *ActOnOpenMPFromClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -9225,18 +9293,25 @@ public:
SourceLocation LParenLoc,
SourceLocation EndLoc);
- /// \brief The kind of conversion being performed.
+ /// The kind of conversion being performed.
enum CheckedConversionKind {
- /// \brief An implicit conversion.
+ /// An implicit conversion.
CCK_ImplicitConversion,
- /// \brief A C-style cast.
+ /// A C-style cast.
CCK_CStyleCast,
- /// \brief A functional-style cast.
+ /// A functional-style cast.
CCK_FunctionalCast,
- /// \brief A cast other than a C-style cast.
- CCK_OtherCast
+ /// A cast other than a C-style cast.
+ CCK_OtherCast,
+ /// A conversion for an operand of a builtin overloaded operator.
+ CCK_ForBuiltinOverloadedOp
};
+ static bool isCast(CheckedConversionKind CCK) {
+ return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
+ CCK == CCK_OtherCast;
+ }
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
/// cast. If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
@@ -9470,7 +9545,7 @@ public:
QualType LHSType, ExprResult &RHS, bool Diagnose = true,
bool DiagnoseCFAudited = false, bool ConvertRHS = true);
- // \brief If the lhs type is a transparent union, check whether we
+ // If the lhs type is a transparent union, check whether we
// can initialize the transparent union with the given expression.
AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType,
ExprResult &RHS);
@@ -9523,8 +9598,8 @@ public:
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc, bool IsCompAssign = false);
QualType CheckCompareOperands( // C99 6.5.8/9
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
- BinaryOperatorKind Opc, bool isRelational);
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc);
QualType CheckBitwiseOperands( // C99 6.5.[10...12]
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc);
@@ -9580,7 +9655,8 @@ public:
bool AllowBothBool, bool AllowBoolConversion);
QualType GetSignedVectorType(QualType V);
QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, bool isRelational);
+ SourceLocation Loc,
+ BinaryOperatorKind Opc);
QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc);
@@ -9617,11 +9693,11 @@ public:
Expr *CastExpr, CastKind &CastKind,
ExprValueKind &VK, CXXCastPath &Path);
- /// \brief Force an expression with unknown-type to an expression of the
+ /// Force an expression with unknown-type to an expression of the
/// given type.
ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
- /// \brief Type-check an expression that's being passed to an
+ /// Type-check an expression that's being passed to an
/// __unknown_anytype parameter.
ExprResult checkUnknownAnyArg(SourceLocation callLoc,
Expr *result, QualType &paramType);
@@ -9633,7 +9709,7 @@ public:
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind);
- /// \brief Prepare `SplattedExpr` for a vector splat operation, adding
+ /// Prepare `SplattedExpr` for a vector splat operation, adding
/// implicit casts if necessary.
ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
@@ -9652,7 +9728,7 @@ public:
enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error };
- /// \brief Checks for invalid conversions and casts between
+ /// Checks for invalid conversions and casts between
/// retainable pointers and other pointer kinds for ARC and Weak.
ARCConversionResult CheckObjCConversion(SourceRange castRange,
QualType castType, Expr *&op,
@@ -9695,18 +9771,18 @@ public:
SourceRange RecRange,
QualType &ReturnType, ExprValueKind &VK);
- /// \brief Determine the result of a message send expression based on
+ /// Determine the result of a message send expression based on
/// the type of the receiver, the method expected to receive the message,
/// and the form of the message send.
QualType getMessageSendResultType(QualType ReceiverType,
ObjCMethodDecl *Method,
bool isClassMessage, bool isSuperMessage);
- /// \brief If the given expression involves a message send to a method
+ /// If the given expression involves a message send to a method
/// with a related result type, emit a note describing what happened.
void EmitRelatedResultTypeNote(const Expr *E);
- /// \brief Given that we had incompatible pointer types in a return
+ /// Given that we had incompatible pointer types in a return
/// statement, check whether we're in a method with a related result
/// type, and if so, emit a note describing what happened.
void EmitRelatedResultTypeNoteForReturn(QualType destType);
@@ -9780,7 +9856,7 @@ public:
/// being used as a boolean condition, warn if it's an assignment.
void DiagnoseAssignmentAsCondition(Expr *E);
- /// \brief Redundant parentheses over an equality comparison can indicate
+ /// Redundant parentheses over an equality comparison can indicate
/// that the user intended an assignment used as condition.
void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
@@ -9799,7 +9875,7 @@ public:
/// in the global scope.
bool CheckObjCDeclScope(Decl *D);
- /// \brief Abstract base class used for diagnosing integer constant
+ /// Abstract base class used for diagnosing integer constant
/// expression violations.
class VerifyICEDiagnoser {
public:
@@ -9995,7 +10071,7 @@ public:
/// will get it wrong. Returns CFT_Host if D is null.
CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D,
bool IgnoreImplicitHDAttr = false);
- CUDAFunctionTarget IdentifyCUDATarget(const AttributeList *Attr);
+ CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs);
/// Gets the CUDA target for the current context.
CUDAFunctionTarget CurrentCUDATarget() {
@@ -10094,6 +10170,16 @@ public:
bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD);
bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD);
+ // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In
+ // case of error emits appropriate diagnostic and invalidates \p Var.
+ //
+ // \details CUDA allows only empty constructors as initializers for global
+ // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all
+ // __shared__ variables whether they are local or not (they all are implicitly
+ // static in CUDA). One exception is that CUDA allows constant initializers
+ // for __constant__ and __device__ variables.
+ void checkAllowedCUDAInitializer(VarDecl *VD);
+
/// Check whether NewFD is a valid overload for CUDA. Emits
/// diagnostics and invalidates NewFD if not.
void checkCUDATargetOverload(FunctionDecl *NewFD,
@@ -10103,48 +10189,48 @@ public:
/// \name Code completion
//@{
- /// \brief Describes the context in which code completion occurs.
+ /// Describes the context in which code completion occurs.
enum ParserCompletionContext {
- /// \brief Code completion occurs at top-level or namespace context.
+ /// Code completion occurs at top-level or namespace context.
PCC_Namespace,
- /// \brief Code completion occurs within a class, struct, or union.
+ /// Code completion occurs within a class, struct, or union.
PCC_Class,
- /// \brief Code completion occurs within an Objective-C interface, protocol,
+ /// Code completion occurs within an Objective-C interface, protocol,
/// or category.
PCC_ObjCInterface,
- /// \brief Code completion occurs within an Objective-C implementation or
+ /// Code completion occurs within an Objective-C implementation or
/// category implementation
PCC_ObjCImplementation,
- /// \brief Code completion occurs within the list of instance variables
+ /// Code completion occurs within the list of instance variables
/// in an Objective-C interface, protocol, category, or implementation.
PCC_ObjCInstanceVariableList,
- /// \brief Code completion occurs following one or more template
+ /// Code completion occurs following one or more template
/// headers.
PCC_Template,
- /// \brief Code completion occurs following one or more template
+ /// Code completion occurs following one or more template
/// headers within a class.
PCC_MemberTemplate,
- /// \brief Code completion occurs within an expression.
+ /// Code completion occurs within an expression.
PCC_Expression,
- /// \brief Code completion occurs within a statement, which may
+ /// Code completion occurs within a statement, which may
/// also be an expression or a declaration.
PCC_Statement,
- /// \brief Code completion occurs at the beginning of the
+ /// Code completion occurs at the beginning of the
/// initialization statement (or expression) in a for loop.
PCC_ForInit,
- /// \brief Code completion occurs within the condition of an if,
+ /// Code completion occurs within the condition of an if,
/// while, switch, or for statement.
PCC_Condition,
- /// \brief Code completion occurs within the body of a function on a
+ /// Code completion occurs within the body of a function on a
/// recovery path, where we do not have a specific handle on our position
/// in the grammar.
PCC_RecoveryInFunction,
- /// \brief Code completion occurs where only a type is permitted.
+ /// Code completion occurs where only a type is permitted.
PCC_Type,
- /// \brief Code completion occurs in a parenthesized expression, which
+ /// Code completion occurs in a parenthesized expression, which
/// might also be a type cast.
PCC_ParenthesizedExpression,
- /// \brief Code completion occurs within a sequence of declaration
+ /// Code completion occurs within a sequence of declaration
/// specifiers within a function, method, or block.
PCC_LocalDeclarationSpecifiers
};
@@ -10159,7 +10245,7 @@ public:
struct CodeCompleteExpressionData;
void CodeCompleteExpression(Scope *S,
const CodeCompleteExpressionData &Data);
- void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+ void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
SourceLocation OpLoc, bool IsArrow,
bool IsBaseExprStatement);
void CodeCompletePostfixExpression(Scope *S, ExprResult LHS);
@@ -10309,6 +10395,9 @@ private:
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall);
@@ -10341,10 +10430,12 @@ private:
ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult);
ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op);
+ ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+ bool IsDelete);
bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
llvm::APSInt &Result);
- bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
- int Low, int High);
+ bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low,
+ int High, bool RangeIsError = true);
bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum,
unsigned Multiple);
bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
@@ -10404,13 +10495,16 @@ private:
const AttrVec *Attrs = nullptr,
const FunctionDecl *FD = nullptr);
- void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS);
+public:
+ void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS);
+
+private:
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
void CheckForIntOverflow(Expr *E);
void CheckUnsequencedOperations(Expr *E);
- /// \brief Perform semantic checks on a completed expression. This will either
+ /// Perform semantic checks on a completed expression. This will either
/// be a full-expression or a default argument expression.
void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(),
bool IsConstexpr = false);
@@ -10423,11 +10517,11 @@ private:
DeclarationName FieldName,
const CXXRecordDecl *RD);
- /// \brief Check if the given expression contains 'break' or 'continue'
+ /// Check if the given expression contains 'break' or 'continue'
/// statement that produces control flow different from GCC.
void CheckBreakContinueBinding(Expr *E);
- /// \brief Check whether receiver is mutable ObjC container which
+ /// Check whether receiver is mutable ObjC container which
/// attempts to add itself into the container
void CheckObjCCircularContainer(ObjCMessageExpr *Message);
@@ -10435,7 +10529,7 @@ private:
void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
bool DeleteWasArrayForm);
public:
- /// \brief Register a magic integral constant to be used as a type tag.
+ /// Register a magic integral constant to be used as a type tag.
void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
uint64_t MagicValue, QualType Type,
bool LayoutCompatible, bool MustBeNull);
@@ -10461,21 +10555,21 @@ public:
typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue;
private:
- /// \brief A map from magic value to type information.
+ /// A map from magic value to type information.
std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>>
TypeTagForDatatypeMagicValues;
- /// \brief Peform checks on a call of a function with argument_with_type_tag
+ /// 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 ArrayRef<const Expr *> ExprArgs,
SourceLocation CallSiteLoc);
- /// \brief Check if we are taking the address of a packed field
+ /// Check if we are taking the address of a packed field
/// as this may be a problem if the pointer value is dereferenced.
void CheckAddressOfPackedMember(Expr *rhs);
- /// \brief The parser's current scope.
+ /// The parser's current scope.
///
/// The parser maintains this state here.
Scope *CurScope;
@@ -10490,7 +10584,7 @@ private:
IdentifierInfo *Ident_NSError = nullptr;
- /// \brief The handler for the FileChanged preprocessor events.
+ /// The handler for the FileChanged preprocessor events.
///
/// Used for diagnostics that implement custom semantic analysis for #include
/// directives, like -Wpragma-pack.
@@ -10513,7 +10607,7 @@ public:
/// Retrieve the identifier "NSError".
IdentifierInfo *getNSErrorIdent();
- /// \brief Retrieve the parser's current scope.
+ /// Retrieve the parser's current scope.
///
/// This routine must only be used when it is certain that semantic analysis
/// and the parser are in precisely the same context, which is not the case
@@ -10544,7 +10638,7 @@ public:
return DC;
}
- /// \brief To be used for checking whether the arguments being passed to
+ /// To be used for checking whether the arguments being passed to
/// function exceeds the number of parameters expected for it.
static bool TooManyArguments(size_t NumParams, size_t NumArgs,
bool PartialOverloading = false) {
@@ -10589,7 +10683,7 @@ private:
}
};
- /// \brief Helper class that collects misaligned member designations and
+ /// Helper class that collects misaligned member designations and
/// their location info for delayed diagnostics.
struct MisalignedMember {
Expr *E;
@@ -10606,28 +10700,28 @@ private:
bool operator==(const MisalignedMember &m) { return this->E == m.E; }
};
- /// \brief Small set of gathered accesses to potentially misaligned members
+ /// Small set of gathered accesses to potentially misaligned members
/// due to the packed attribute.
SmallVector<MisalignedMember, 4> MisalignedMembers;
- /// \brief Adds an expression to the set of gathered misaligned members.
+ /// Adds an expression to the set of gathered misaligned members.
void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
CharUnits Alignment);
public:
- /// \brief Diagnoses the current set of gathered accesses. This typically
+ /// Diagnoses the current set of gathered accesses. This typically
/// happens at full expression level. The set is cleared after emitting the
/// diagnostics.
void DiagnoseMisalignedMembers();
- /// \brief This function checks if the expression is in the sef of potentially
+ /// This function checks if the expression is in the sef of potentially
/// misaligned members and it is converted to some pointer type T with lower
/// or equal alignment requirements. If so it removes it. This is used when
/// we do not want to diagnose such misaligned access (e.g. in conversions to
/// void*).
void DiscardMisalignedMemberAddress(const Type *T, Expr *E);
- /// \brief This function calls Action when it determines that E designates a
+ /// This function calls Action when it determines that E designates a
/// misaligned member due to the packed attribute. This is used to emit
/// local diagnostics like in reference binding.
void RefersToMemberWithReducedAlignment(
@@ -10636,31 +10730,31 @@ public:
Action);
};
-/// \brief RAII object that enters a new expression evaluation context.
+/// RAII object that enters a new expression evaluation context.
class EnterExpressionEvaluationContext {
Sema &Actions;
bool Entered = true;
public:
-
- EnterExpressionEvaluationContext(Sema &Actions,
- Sema::ExpressionEvaluationContext NewContext,
- Decl *LambdaContextDecl = nullptr,
- bool IsDecltype = false,
- bool ShouldEnter = true)
+ EnterExpressionEvaluationContext(
+ Sema &Actions, Sema::ExpressionEvaluationContext NewContext,
+ Decl *LambdaContextDecl = nullptr,
+ Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext =
+ Sema::ExpressionEvaluationContextRecord::EK_Other,
+ bool ShouldEnter = true)
: Actions(Actions), Entered(ShouldEnter) {
if (Entered)
Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
- IsDecltype);
+ ExprContext);
}
- EnterExpressionEvaluationContext(Sema &Actions,
- Sema::ExpressionEvaluationContext NewContext,
- Sema::ReuseLambdaContextDecl_t,
- bool IsDecltype = false)
- : Actions(Actions) {
- Actions.PushExpressionEvaluationContext(NewContext,
- Sema::ReuseLambdaContextDecl,
- IsDecltype);
+ EnterExpressionEvaluationContext(
+ Sema &Actions, Sema::ExpressionEvaluationContext NewContext,
+ Sema::ReuseLambdaContextDecl_t,
+ Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext =
+ Sema::ExpressionEvaluationContextRecord::EK_Other)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(
+ NewContext, Sema::ReuseLambdaContextDecl, ExprContext);
}
enum InitListTag { InitList };
@@ -10674,7 +10768,7 @@ public:
if (ShouldEnter && Actions.isUnevaluatedContext() &&
Actions.getLangOpts().CPlusPlus11) {
Actions.PushExpressionEvaluationContext(
- Sema::ExpressionEvaluationContext::UnevaluatedList, nullptr, false);
+ Sema::ExpressionEvaluationContext::UnevaluatedList);
Entered = true;
}
}
@@ -10689,11 +10783,11 @@ DeductionFailureInfo
MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK,
sema::TemplateDeductionInfo &Info);
-/// \brief Contains a late templated function.
+/// Contains a late templated function.
/// Will be parsed at the end of the translation unit, used by Sema & Parser.
struct LateParsedTemplate {
CachedTokens Toks;
- /// \brief The template function declaration to be late parsed.
+ /// The template function declaration to be late parsed.
Decl *D;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h
index 676646afbd59..a2caf86c3653 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h
@@ -20,7 +20,7 @@
namespace clang {
class Sema;
- /// \brief An abstract interface that should be implemented by
+ /// An abstract interface that should be implemented by
/// clients that read ASTs and then require further semantic
/// analysis of the entities in those ASTs.
class SemaConsumer : public ASTConsumer {
@@ -30,12 +30,12 @@ namespace clang {
ASTConsumer::SemaConsumer = true;
}
- /// \brief Initialize the semantic consumer with the Sema instance
+ /// Initialize the semantic consumer with the Sema instance
/// being used to perform semantic analysis on the abstract syntax
/// tree.
virtual void InitializeSema(Sema &S) {}
- /// \brief Inform the semantic consumer that Sema is no longer available.
+ /// Inform the semantic consumer that Sema is no longer available.
virtual void ForgetSema() {}
// isa/cast/dyn_cast support
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h
index 343ccfb3d630..84dc58754b7b 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h
@@ -1,4 +1,4 @@
-//===--- SemaFixItUtils.h - Sema FixIts -----------------------------------===//
+//===--- SemaFixItUtils.h - Sema FixIts -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
index 4dc215ba21cb..c55e16a27cd3 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
@@ -45,7 +45,7 @@ inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
const VarDecl *DefVD = nullptr;
return !isa<ParmVarDecl>(Var) &&
Var->isUsableInConstantExpressions(Context) &&
- Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
+ Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
}
// Helper function to check whether D's attributes match current CUDA mode.
@@ -60,13 +60,13 @@ inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) {
return isDeviceSideDecl == LangOpts.CUDAIsDevice;
}
-// Directly mark a variable odr-used. Given a choice, prefer to use
-// MarkVariableReferenced since it does additional checks and then
+// Directly mark a variable odr-used. Given a choice, prefer to use
+// MarkVariableReferenced since it does additional checks and then
// calls MarkVarDeclODRUsed.
// If the variable must be captured:
// - if FunctionScopeIndexToStopAt is null, capture it in the CurContext
-// - else capture it in the DeclContext that maps to the
-// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.
+// - else capture it in the DeclContext that maps to the
+// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.
inline void MarkVarDeclODRUsed(VarDecl *Var,
SourceLocation Loc, Sema &SemaRef,
const unsigned *const FunctionScopeIndexToStopAt) {
@@ -81,10 +81,10 @@ inline void MarkVarDeclODRUsed(VarDecl *Var,
old = Loc;
}
QualType CaptureType, DeclRefType;
- SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,
+ SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,
/*EllipsisLoc*/ SourceLocation(),
- /*BuildAndDiagnose*/ true,
- CaptureType, DeclRefType,
+ /*BuildAndDiagnose*/ true,
+ CaptureType, DeclRefType,
FunctionScopeIndexToStopAt);
Var->markUsed(SemaRef.Context);
@@ -101,6 +101,27 @@ inline InheritableAttr *getDLLAttr(Decl *D) {
return nullptr;
}
+/// Retrieve the depth and index of a template parameter.
+inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ const auto *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+/// Retrieve the depth and index of an unexpanded parameter pack.
+inline std::pair<unsigned, unsigned>
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+ if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ return getDepthAndIndex(UPP.first.get<NamedDecl *>());
+}
+
class TypoCorrectionConsumer : public VisibleDeclConsumer {
typedef SmallVector<TypoCorrection, 1> TypoResultList;
typedef llvm::StringMap<TypoResultList> TypoResultsMap;
@@ -139,13 +160,13 @@ public:
return CorrectionResults.empty() && ValidatedCorrections.size() == 1;
}
- /// \brief Return the list of TypoCorrections for the given identifier from
+ /// Return the list of TypoCorrections for the given identifier from
/// the set of corrections that have the closest edit distance, if any.
TypoResultList &operator[](StringRef Name) {
return CorrectionResults.begin()->second[Name];
}
- /// \brief Return the edit distance of the corrections that have the
+ /// Return the edit distance of the corrections that have the
/// closest/best edit distance from the original typop.
unsigned getBestEditDistance(bool Normalized) {
if (CorrectionResults.empty())
@@ -155,28 +176,28 @@ public:
return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
}
- /// \brief Set-up method to add to the consumer the set of namespaces to use
+ /// Set-up method to add to the consumer the set of namespaces to use
/// in performing corrections to nested name specifiers. This method also
/// implicitly adds all of the known classes in the current AST context to the
/// to the consumer for correcting nested name specifiers.
void
addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
- /// \brief Return the next typo correction that passes all internal filters
+ /// Return the next typo correction that passes all internal filters
/// and is deemed valid by the consumer's CorrectionCandidateCallback,
/// starting with the corrections that have the closest edit distance. An
/// empty TypoCorrection is returned once no more viable corrections remain
/// in the consumer.
const TypoCorrection &getNextCorrection();
- /// \brief Get the last correction returned by getNextCorrection().
+ /// Get the last correction returned by getNextCorrection().
const TypoCorrection &getCurrentCorrection() {
return CurrentTCIndex < ValidatedCorrections.size()
? ValidatedCorrections[CurrentTCIndex]
: ValidatedCorrections[0]; // The empty correction.
}
- /// \brief Return the next typo correction like getNextCorrection, but keep
+ /// Return the next typo correction like getNextCorrection, but keep
/// the internal state pointed to the current correction (i.e. the next time
/// getNextCorrection is called, it will return the same correction returned
/// by peekNextcorrection).
@@ -187,27 +208,27 @@ public:
return TC;
}
- /// \brief Reset the consumer's position in the stream of viable corrections
+ /// Reset the consumer's position in the stream of viable corrections
/// (i.e. getNextCorrection() will return each of the previously returned
/// corrections in order before returning any new corrections).
void resetCorrectionStream() {
CurrentTCIndex = 0;
}
- /// \brief Return whether the end of the stream of corrections has been
+ /// Return whether the end of the stream of corrections has been
/// reached.
bool finished() {
return CorrectionResults.empty() &&
CurrentTCIndex >= ValidatedCorrections.size();
}
- /// \brief Save the current position in the correction stream (overwriting any
+ /// Save the current position in the correction stream (overwriting any
/// previously saved position).
void saveCurrentPosition() {
SavedTCIndex = CurrentTCIndex;
}
- /// \brief Restore the saved position in the correction stream.
+ /// Restore the saved position in the correction stream.
void restoreSavedPosition() {
CurrentTCIndex = SavedTCIndex;
}
@@ -241,7 +262,7 @@ private:
std::map<unsigned, SpecifierInfoList> DistanceMap;
- /// \brief Helper for building the list of DeclContexts between the current
+ /// Helper for building the list of DeclContexts between the current
/// context and the top of the translation unit
static DeclContextList buildContextChain(DeclContext *Start);
@@ -252,11 +273,11 @@ private:
NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
CXXScopeSpec *CurScopeSpec);
- /// \brief Add the DeclContext (a namespace or record) to the set, computing
+ /// Add the DeclContext (a namespace or record) to the set, computing
/// the corresponding NestedNameSpecifier and its distance in the process.
void addNameSpecifier(DeclContext *Ctx);
- /// \brief Provides flat iteration over specifiers, sorted by distance.
+ /// Provides flat iteration over specifiers, sorted by distance.
class iterator
: public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
SpecifierInfo> {
@@ -295,21 +316,21 @@ private:
void addName(StringRef Name, NamedDecl *ND,
NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
- /// \brief Find any visible decls for the given typo correction candidate.
+ /// Find any visible decls for the given typo correction candidate.
/// If none are found, it to the set of candidates for which qualified lookups
/// will be performed to find possible nested name specifier changes.
bool resolveCorrection(TypoCorrection &Candidate);
- /// \brief Perform qualified lookups on the queued set of typo correction
+ /// Perform qualified lookups on the queued set of typo correction
/// candidates and add the nested name specifier changes to each candidate if
/// a lookup succeeds (at which point the candidate will be returned to the
/// main pool of potential corrections).
void performQualifiedLookups();
- /// \brief The name written that is a typo in the source.
+ /// The name written that is a typo in the source.
IdentifierInfo *Typo;
- /// \brief The results found that have the smallest edit distance
+ /// The results found that have the smallest edit distance
/// found (so far) with the typo name.
///
/// The pointer value being set to the current DeclContext indicates
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h
index df40b134f0a7..8edb9b5c613d 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h
@@ -8,24 +8,28 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file provides some common utility functions for processing
+/// This file provides some common utility functions for processing
/// Lambdas.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H
#define LLVM_CLANG_SEMA_SEMALAMBDA_H
+
#include "clang/AST/ASTLambda.h"
-#include "clang/Sema/ScopeInfo.h"
+
namespace clang {
+namespace sema {
+class FunctionScopeInfo;
+}
class Sema;
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
-/// enclosing lambda (to the current lambda) that is 'capture-capable' for
+/// Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-capable' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
-/// of the capture-capable lambda's LambdaScopeInfo.
-/// See Implementation for more detailed comments.
+/// of the capture-capable lambda's LambdaScopeInfo.
+/// See Implementation for more detailed comments.
Optional<unsigned> getStackIndexOfNearestEnclosingCaptureCapableLambda(
ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Template.h b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
index 644d55b93f1b..39b08e934be4 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Template.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
@@ -1,29 +1,52 @@
-//===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/
+//===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===//
//
-// This file provides types used in the semantic analysis of C++ templates.
+// This file provides types used in the semantic analysis of C++ templates.
//
-//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
#define LLVM_CLANG_SEMA_TEMPLATE_H
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <utility>
namespace clang {
- /// \brief Data structure that captures multiple levels of template argument
+
+class ASTContext;
+class BindingDecl;
+class CXXMethodDecl;
+class Decl;
+class DeclaratorDecl;
+class DeclContext;
+class EnumDecl;
+class FunctionDecl;
+class NamedDecl;
+class ParmVarDecl;
+class TagDecl;
+class TypedefNameDecl;
+class TypeSourceInfo;
+class VarDecl;
+
+ /// Data structure that captures multiple levels of template argument
/// lists for use in template instantiation.
///
- /// Multiple levels of template arguments occur when instantiating the
+ /// Multiple levels of template arguments occur when instantiating the
/// definitions of member templates. For example:
///
/// \code
@@ -40,47 +63,47 @@ namespace clang {
/// list will contain a template argument list (int) at depth 0 and a
/// template argument list (17) at depth 1.
class MultiLevelTemplateArgumentList {
- /// \brief The template argument list at a certain template depth
- typedef ArrayRef<TemplateArgument> ArgList;
+ /// The template argument list at a certain template depth
+ using ArgList = ArrayRef<TemplateArgument>;
- /// \brief The template argument lists, stored from the innermost template
+ /// The template argument lists, stored from the innermost template
/// argument list (first) to the outermost template argument list (last).
SmallVector<ArgList, 4> TemplateArgumentLists;
- /// \brief The number of outer levels of template arguments that are not
+ /// The number of outer levels of template arguments that are not
/// being substituted.
unsigned NumRetainedOuterLevels = 0;
-
+
public:
- /// \brief Construct an empty set of template argument lists.
- MultiLevelTemplateArgumentList() { }
-
- /// \brief Construct a single-level template argument list.
- explicit
+ /// Construct an empty set of template argument lists.
+ MultiLevelTemplateArgumentList() = default;
+
+ /// Construct a single-level template argument list.
+ explicit
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
addOuterTemplateArguments(&TemplateArgs);
}
-
- /// \brief Determine the number of levels in this template argument
+
+ /// Determine the number of levels in this template argument
/// list.
unsigned getNumLevels() const {
return TemplateArgumentLists.size() + NumRetainedOuterLevels;
}
- /// \brief Determine the number of substituted levels in this template
+ /// Determine the number of substituted levels in this template
/// argument list.
unsigned getNumSubstitutedLevels() const {
return TemplateArgumentLists.size();
}
- /// \brief Retrieve the template argument at a given depth and index.
+ /// Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
return TemplateArgumentLists[getNumLevels() - Depth - 1][Index];
}
-
- /// \brief Determine whether there is a non-NULL template argument at the
+
+ /// Determine whether there is a non-NULL template argument at the
/// given depth and index.
///
/// There must exist a template argument list at the given depth.
@@ -89,14 +112,14 @@ namespace clang {
if (Depth < NumRetainedOuterLevels)
return false;
-
+
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size())
return false;
-
+
return !(*this)(Depth, Index).isNull();
}
-
- /// \brief Clear out a specific template argument.
+
+ /// Clear out a specific template argument.
void setArgument(unsigned Depth, unsigned Index,
TemplateArgument Arg) {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
@@ -105,15 +128,15 @@ namespace clang {
TemplateArgumentLists[getNumLevels() - Depth - 1][Index])
= Arg;
}
-
- /// \brief Add a new outermost level to the multi-level template argument
+
+ /// Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
addOuterTemplateArguments(ArgList(TemplateArgs->data(),
TemplateArgs->size()));
}
- /// \brief Add a new outmost level to the multi-level template argument
+ /// Add a new outmost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(ArgList Args) {
assert(!NumRetainedOuterLevels &&
@@ -121,28 +144,30 @@ namespace clang {
TemplateArgumentLists.push_back(Args);
}
- /// \brief Add an outermost level that we are not substituting. We have no
+ /// Add an outermost level that we are not substituting. We have no
/// arguments at this level, and do not remove it from the depth of inner
/// template parameters that we instantiate.
void addOuterRetainedLevel() {
++NumRetainedOuterLevels;
}
- /// \brief Retrieve the innermost template argument list.
- const ArgList &getInnermost() const {
- return TemplateArgumentLists.front();
+ /// Retrieve the innermost template argument list.
+ const ArgList &getInnermost() const {
+ return TemplateArgumentLists.front();
}
};
-
- /// \brief The context in which partial ordering of function templates occurs.
+
+ /// The context in which partial ordering of function templates occurs.
enum TPOC {
- /// \brief Partial ordering of function templates for a function call.
+ /// Partial ordering of function templates for a function call.
TPOC_Call,
- /// \brief Partial ordering of function templates for a call to a
+
+ /// Partial ordering of function templates for a call to a
/// conversion function.
TPOC_Conversion,
- /// \brief Partial ordering of function templates in other contexts, e.g.,
- /// taking the address of a function template or matching a function
+
+ /// Partial ordering of function templates in other contexts, e.g.,
+ /// taking the address of a function template or matching a function
/// template specialization to a function template.
TPOC_Other
};
@@ -153,47 +178,48 @@ namespace clang {
// making Sema.h declare things as enums).
class TemplatePartialOrderingContext {
TPOC Value;
+
public:
TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
+
operator TPOC() const { return Value; }
};
- /// \brief Captures a template argument whose value has been deduced
+ /// Captures a template argument whose value has been deduced
/// via c++ template argument deduction.
class DeducedTemplateArgument : public TemplateArgument {
- /// \brief For a non-type template argument, whether the value was
+ /// For a non-type template argument, whether the value was
/// deduced from an array bound.
- bool DeducedFromArrayBound;
+ bool DeducedFromArrayBound = false;
public:
- DeducedTemplateArgument()
- : TemplateArgument(), DeducedFromArrayBound(false) { }
+ DeducedTemplateArgument() = default;
DeducedTemplateArgument(const TemplateArgument &Arg,
bool DeducedFromArrayBound = false)
- : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
+ : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {}
- /// \brief Construct an integral non-type template argument that
+ /// Construct an integral non-type template argument that
/// has been deduced, possibly from an array bound.
DeducedTemplateArgument(ASTContext &Ctx,
const llvm::APSInt &Value,
QualType ValueType,
bool DeducedFromArrayBound)
- : TemplateArgument(Ctx, Value, ValueType),
- DeducedFromArrayBound(DeducedFromArrayBound) { }
+ : TemplateArgument(Ctx, Value, ValueType),
+ DeducedFromArrayBound(DeducedFromArrayBound) {}
- /// \brief For a non-type template argument, determine whether the
+ /// For a non-type template argument, determine whether the
/// template argument was deduced from an array bound.
bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
- /// \brief Specify whether the given non-type template argument
+ /// Specify whether the given non-type template argument
/// was deduced from an array bound.
void setDeducedFromArrayBound(bool Deduced) {
DeducedFromArrayBound = Deduced;
}
};
- /// \brief A stack-allocated class that identifies which local
+ /// A stack-allocated class that identifies which local
/// variable declaration instantiations are present in this scope.
///
/// A new instance of this class type will be created whenever we
@@ -201,19 +227,19 @@ namespace clang {
/// set of parameter declarations.
class LocalInstantiationScope {
public:
- /// \brief A set of declarations.
- typedef SmallVector<ParmVarDecl *, 4> DeclArgumentPack;
+ /// A set of declarations.
+ using DeclArgumentPack = SmallVector<ParmVarDecl *, 4>;
private:
- /// \brief Reference to the semantic analysis that is performing
+ /// Reference to the semantic analysis that is performing
/// this template instantiation.
Sema &SemaRef;
- typedef llvm::SmallDenseMap<
- const Decl *, llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>
- LocalDeclsMap;
+ using LocalDeclsMap =
+ llvm::SmallDenseMap<const Decl *,
+ llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
- /// \brief A mapping from local declarations that occur
+ /// A mapping from local declarations that occur
/// within a template to their instantiations.
///
/// This mapping is used during instantiation to keep track of,
@@ -233,67 +259,64 @@ namespace clang {
/// pointer.
LocalDeclsMap LocalDecls;
- /// \brief The set of argument packs we've allocated.
+ /// The set of argument packs we've allocated.
SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
-
- /// \brief The outer scope, which contains local variable
+
+ /// The outer scope, which contains local variable
/// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
- /// \brief Whether we have already exited this scope.
- bool Exited;
+ /// Whether we have already exited this scope.
+ bool Exited = false;
- /// \brief Whether to combine this scope with the outer scope, such that
+ /// Whether to combine this scope with the outer scope, such that
/// lookup will search our outer scope.
bool CombineWithOuterScope;
-
- /// \brief If non-NULL, the template parameter pack that has been
+
+ /// If non-NULL, the template parameter pack that has been
/// partially substituted per C++0x [temp.arg.explicit]p9.
- NamedDecl *PartiallySubstitutedPack;
-
- /// \brief If \c PartiallySubstitutedPack is non-null, the set of
+ NamedDecl *PartiallySubstitutedPack = nullptr;
+
+ /// If \c PartiallySubstitutedPack is non-null, the set of
/// explicitly-specified template arguments in that pack.
- const TemplateArgument *ArgsInPartiallySubstitutedPack;
-
- /// \brief If \c PartiallySubstitutedPack, the number of
- /// explicitly-specified template arguments in
+ const TemplateArgument *ArgsInPartiallySubstitutedPack;
+
+ /// If \c PartiallySubstitutedPack, the number of
+ /// explicitly-specified template arguments in
/// ArgsInPartiallySubstitutedPack.
unsigned NumArgsInPartiallySubstitutedPack;
- // This class is non-copyable
- LocalInstantiationScope(
- const LocalInstantiationScope &) = delete;
- void operator=(const LocalInstantiationScope &) = delete;
-
public:
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
- : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
- Exited(false), CombineWithOuterScope(CombineWithOuterScope),
- PartiallySubstitutedPack(nullptr)
- {
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ CombineWithOuterScope(CombineWithOuterScope) {
SemaRef.CurrentInstantiationScope = this;
}
+ LocalInstantiationScope(const LocalInstantiationScope &) = delete;
+ LocalInstantiationScope &
+ operator=(const LocalInstantiationScope &) = delete;
+
~LocalInstantiationScope() {
Exit();
}
-
+
const Sema &getSema() const { return SemaRef; }
- /// \brief Exit this local instantiation scope early.
+ /// Exit this local instantiation scope early.
void Exit() {
if (Exited)
return;
-
+
for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
delete ArgumentPacks[I];
-
+
SemaRef.CurrentInstantiationScope = Outer;
Exited = true;
}
- /// \brief Clone this scope, and all outer scopes, down to the given
+ /// Clone this scope, and all outer scopes, down to the given
/// outermost scope.
LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
if (this == Outermost) return this;
@@ -333,7 +356,7 @@ namespace clang {
return newScope;
}
- /// \brief deletes the given scope, and all otuer scopes, down to the
+ /// deletes the given scope, and all otuer scopes, down to the
/// given outermost scope.
static void deleteScopes(LocalInstantiationScope *Scope,
LocalInstantiationScope *Outermost) {
@@ -344,7 +367,7 @@ namespace clang {
}
}
- /// \brief Find the instantiation of the declaration D within the current
+ /// Find the instantiation of the declaration D within the current
/// instantiation scope.
///
/// \param D The declaration whose instantiation we are searching for.
@@ -358,9 +381,9 @@ namespace clang {
void InstantiatedLocal(const Decl *D, Decl *Inst);
void InstantiatedLocalPackArg(const Decl *D, ParmVarDecl *Inst);
void MakeInstantiatedLocalArgPack(const Decl *D);
-
- /// \brief Note that the given parameter pack has been partially substituted
- /// via explicit specification of template arguments
+
+ /// Note that the given parameter pack has been partially substituted
+ /// via explicit specification of template arguments
/// (C++0x [temp.arg.explicit]p9).
///
/// \param Pack The parameter pack, which will always be a template
@@ -371,11 +394,11 @@ namespace clang {
///
/// \param NumExplicitArgs The number of explicitly-specified template
/// arguments provided for this parameter pack.
- void SetPartiallySubstitutedPack(NamedDecl *Pack,
+ void SetPartiallySubstitutedPack(NamedDecl *Pack,
const TemplateArgument *ExplicitArgs,
unsigned NumExplicitArgs);
- /// \brief Reset the partially-substituted pack when it is no longer of
+ /// Reset the partially-substituted pack when it is no longer of
/// interest.
void ResetPartiallySubstitutedPack() {
assert(PartiallySubstitutedPack && "No partially-substituted pack");
@@ -384,7 +407,7 @@ namespace clang {
NumArgsInPartiallySubstitutedPack = 0;
}
- /// \brief Retrieve the partially-substitued template parameter pack.
+ /// Retrieve the partially-substitued template parameter pack.
///
/// If there is no partially-substituted parameter pack, returns NULL.
NamedDecl *
@@ -393,23 +416,23 @@ namespace clang {
};
class TemplateDeclInstantiator
- : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
{
Sema &SemaRef;
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
DeclContext *Owner;
const MultiLevelTemplateArgumentList &TemplateArgs;
- Sema::LateInstantiatedAttrVec* LateAttrs;
- LocalInstantiationScope *StartingScope;
+ Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
+ LocalInstantiationScope *StartingScope = nullptr;
- /// \brief A list of out-of-line class template partial
+ /// A list of out-of-line class template partial
/// specializations that will need to be instantiated after the
/// enclosing class's instantiation is complete.
SmallVector<std::pair<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>, 4>
OutOfLinePartialSpecs;
- /// \brief A list of out-of-line variable template partial
+ /// A list of out-of-line variable template partial
/// specializations that will need to be instantiated after the
/// enclosing variable's instantiation is complete.
/// FIXME: Verify that this is needed.
@@ -420,10 +443,9 @@ namespace clang {
public:
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs)
- : SemaRef(SemaRef),
- SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
- Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(nullptr),
- StartingScope(nullptr) {}
+ : SemaRef(SemaRef),
+ SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
+ Owner(Owner), TemplateArgs(TemplateArgs) {}
// Define all the decl visitors using DeclNodes.inc
#define DECL(DERIVED, BASE) \
@@ -476,17 +498,13 @@ namespace clang {
LocalInstantiationScope *getStartingScope() const { return StartingScope; }
- typedef
- SmallVectorImpl<std::pair<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *> >
- ::iterator
- delayed_partial_spec_iterator;
+ using delayed_partial_spec_iterator = SmallVectorImpl<std::pair<
+ ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator;
- typedef SmallVectorImpl<std::pair<
- VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> >::iterator
- delayed_var_partial_spec_iterator;
+ using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair<
+ VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator;
- /// \brief Return an iterator to the beginning of the set of
+ /// Return an iterator to the beginning of the set of
/// "delayed" partial specializations, which must be passed to
/// InstantiateClassTemplatePartialSpecialization once the class
/// definition has been completed.
@@ -498,7 +516,7 @@ namespace clang {
return OutOfLineVarPartialSpecs.begin();
}
- /// \brief Return an iterator to the end of the set of
+ /// Return an iterator to the end of the set of
/// "delayed" partial specializations, which must be passed to
/// InstantiateClassTemplatePartialSpecialization once the class
/// definition has been completed.
@@ -544,7 +562,8 @@ namespace clang {
template<typename T>
Decl *instantiateUnresolvedUsingDecl(T *D,
bool InstantiatingPackElement = false);
- };
-}
+ };
+
+} // namespace clang
#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
index cd9ed6abfaf9..93395b4945d5 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
@@ -1,80 +1,95 @@
-//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/
+//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===/
//
-// This file provides types used with Sema's template argument deduction
+//===----------------------------------------------------------------------===//
+//
+// This file provides types used with Sema's template argument deduction
// routines.
//
-//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
+#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
namespace clang {
+class Decl;
struct DeducedPack;
-class TemplateArgumentList;
class Sema;
namespace sema {
-/// \brief Provides information about an attempted template argument
+/// Provides information about an attempted template argument
/// deduction, whose success or failure was described by a
/// TemplateDeductionResult value.
class TemplateDeductionInfo {
- /// \brief The deduced template argument list.
- ///
- TemplateArgumentList *Deduced;
+ /// The deduced template argument list.
+ TemplateArgumentList *Deduced = nullptr;
- /// \brief The source location at which template argument
+ /// The source location at which template argument
/// deduction is occurring.
SourceLocation Loc;
- /// \brief Have we suppressed an error during deduction?
- bool HasSFINAEDiagnostic;
+ /// Have we suppressed an error during deduction?
+ bool HasSFINAEDiagnostic = false;
- /// \brief The template parameter depth for which we're performing deduction.
+ /// The template parameter depth for which we're performing deduction.
unsigned DeducedDepth;
- /// \brief Warnings (and follow-on notes) that were suppressed due to
+ /// The number of parameters with explicitly-specified template arguments,
+ /// up to and including the partially-specified pack (if any).
+ unsigned ExplicitArgs = 0;
+
+ /// Warnings (and follow-on notes) that were suppressed due to
/// SFINAE while performing template argument deduction.
SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
- TemplateDeductionInfo(const TemplateDeductionInfo &) = delete;
- void operator=(const TemplateDeductionInfo &) = delete;
-
public:
TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0)
- : Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false),
- DeducedDepth(DeducedDepth), CallArgIndex(0) {}
+ : Loc(Loc), DeducedDepth(DeducedDepth) {}
+ TemplateDeductionInfo(const TemplateDeductionInfo &) = delete;
+ TemplateDeductionInfo &operator=(const TemplateDeductionInfo &) = delete;
- /// \brief Returns the location at which template argument is
+ /// Returns the location at which template argument is
/// occurring.
SourceLocation getLocation() const {
return Loc;
}
- /// \brief The depth of template parameters for which deduction is being
+ /// The depth of template parameters for which deduction is being
/// performed.
unsigned getDeducedDepth() const {
return DeducedDepth;
}
- /// \brief Take ownership of the deduced template argument list.
+ /// Get the number of explicitly-specified arguments.
+ unsigned getNumExplicitArgs() const {
+ return ExplicitArgs;
+ }
+
+ /// Take ownership of the deduced template argument list.
TemplateArgumentList *take() {
TemplateArgumentList *Result = Deduced;
Deduced = nullptr;
return Result;
}
- /// \brief Take ownership of the SFINAE diagnostic.
+ /// Take ownership of the SFINAE diagnostic.
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
assert(HasSFINAEDiagnostic);
PD.first = SuppressedDiagnostics.front().first;
@@ -82,7 +97,7 @@ public:
clearSFINAEDiagnostic();
}
- /// \brief Discard any SFINAE diagnostics.
+ /// Discard any SFINAE diagnostics.
void clearSFINAEDiagnostic() {
SuppressedDiagnostics.clear();
HasSFINAEDiagnostic = false;
@@ -94,18 +109,25 @@ public:
return SuppressedDiagnostics.front();
}
- /// \brief Provide a new template argument list that contains the
+ /// Provide an initial template argument list that contains the
+ /// explicitly-specified arguments.
+ void setExplicitArgs(TemplateArgumentList *NewDeduced) {
+ Deduced = NewDeduced;
+ ExplicitArgs = Deduced->size();
+ }
+
+ /// Provide a new template argument list that contains the
/// results of template argument deduction.
void reset(TemplateArgumentList *NewDeduced) {
Deduced = NewDeduced;
}
- /// \brief Is a SFINAE diagnostic available?
+ /// Is a SFINAE diagnostic available?
bool hasSFINAEDiagnostic() const {
return HasSFINAEDiagnostic;
}
- /// \brief Set the diagnostic which caused the SFINAE failure.
+ /// Set the diagnostic which caused the SFINAE failure.
void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
// Only collect the first diagnostic.
if (HasSFINAEDiagnostic)
@@ -115,7 +137,7 @@ public:
HasSFINAEDiagnostic = true;
}
- /// \brief Add a new diagnostic to the set of diagnostics
+ /// Add a new diagnostic to the set of diagnostics
void addSuppressedDiagnostic(SourceLocation Loc,
PartialDiagnostic PD) {
if (HasSFINAEDiagnostic)
@@ -123,19 +145,18 @@ public:
SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
}
- /// \brief Iterator over the set of suppressed diagnostics.
- typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator
- diag_iterator;
+ /// Iterator over the set of suppressed diagnostics.
+ using diag_iterator = SmallVectorImpl<PartialDiagnosticAt>::const_iterator;
- /// \brief Returns an iterator at the beginning of the sequence of suppressed
+ /// Returns an iterator at the beginning of the sequence of suppressed
/// diagnostics.
diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
- /// \brief Returns an iterator at the end of the sequence of suppressed
+ /// Returns an iterator at the end of the sequence of suppressed
/// diagnostics.
diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
- /// \brief The template parameter to which a template argument
+ /// The template parameter to which a template argument
/// deduction failure refers.
///
/// Depending on the result of template argument deduction, this
@@ -144,16 +165,22 @@ public:
/// TDK_Incomplete: this is the first template parameter whose
/// corresponding template argument was not deduced.
///
+ /// TDK_IncompletePack: this is the expanded parameter pack for
+ /// which we deduced too few arguments.
+ ///
/// TDK_Inconsistent: this is the template parameter for which
/// two different template argument values were deduced.
TemplateParameter Param;
- /// \brief The first template argument to which the template
+ /// The first template argument to which the template
/// argument deduction failure refers.
///
/// Depending on the result of the template argument deduction,
/// this template argument may have different meanings:
///
+ /// TDK_IncompletePack: this is the number of arguments we deduced
+ /// for the pack.
+ ///
/// TDK_Inconsistent: this argument is the first value deduced
/// for the corresponding template parameter.
///
@@ -167,7 +194,7 @@ public:
/// of the deduction, directly provided in the source code.
TemplateArgument FirstArg;
- /// \brief The second template argument to which the template
+ /// The second template argument to which the template
/// argument deduction failure refers.
///
/// TDK_Inconsistent: this argument is the second value deduced
@@ -181,20 +208,20 @@ public:
/// FIXME: Finish documenting this.
TemplateArgument SecondArg;
- /// \brief The index of the function argument that caused a deduction
+ /// The index of the function argument that caused a deduction
/// failure.
///
/// TDK_DeducedMismatch: this is the index of the argument that had a
/// different argument type from its substituted parameter type.
- unsigned CallArgIndex;
+ unsigned CallArgIndex = 0;
- /// \brief Information on packs that we're currently expanding.
+ /// Information on packs that we're currently expanding.
///
/// FIXME: This should be kept internal to SemaTemplateDeduction.
SmallVector<DeducedPack *, 8> PendingDeducedPacks;
};
-} // end namespace sema
+} // namespace sema
/// A structure used to record information about a failed
/// template argument deduction, for diagnosis.
@@ -202,41 +229,41 @@ struct DeductionFailureInfo {
/// A Sema::TemplateDeductionResult.
unsigned Result : 8;
- /// \brief Indicates whether a diagnostic is stored in Diagnostic.
+ /// Indicates whether a diagnostic is stored in Diagnostic.
unsigned HasDiagnostic : 1;
- /// \brief Opaque pointer containing additional data about
+ /// Opaque pointer containing additional data about
/// this deduction failure.
void *Data;
- /// \brief A diagnostic indicating why deduction failed.
+ /// A diagnostic indicating why deduction failed.
alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)];
- /// \brief Retrieve the diagnostic which caused this deduction failure,
+ /// Retrieve the diagnostic which caused this deduction failure,
/// if any.
PartialDiagnosticAt *getSFINAEDiagnostic();
- /// \brief Retrieve the template parameter this deduction failure
+ /// Retrieve the template parameter this deduction failure
/// refers to, if any.
TemplateParameter getTemplateParameter();
- /// \brief Retrieve the template argument list associated with this
+ /// Retrieve the template argument list associated with this
/// deduction failure, if any.
TemplateArgumentList *getTemplateArgumentList();
- /// \brief Return the first template argument this deduction failure
+ /// Return the first template argument this deduction failure
/// refers to, if any.
const TemplateArgument *getFirstArg();
- /// \brief Return the second template argument this deduction failure
+ /// Return the second template argument this deduction failure
/// refers to, if any.
const TemplateArgument *getSecondArg();
- /// \brief Return the index of the call argument that this deduction
+ /// Return the index of the call argument that this deduction
/// failure refers to, if any.
llvm::Optional<unsigned> getCallArgIndex();
- /// \brief Free any memory associated with this deduction failure.
+ /// Free any memory associated with this deduction failure.
void Destroy();
};
@@ -248,7 +275,7 @@ struct DeductionFailureInfo {
/// TODO: In the future, we may need to unify/generalize this with
/// OverloadCandidate.
struct TemplateSpecCandidate {
- /// \brief The declaration that was looked up, together with its access.
+ /// The declaration that was looked up, together with its access.
/// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl.
DeclAccessPair FoundDecl;
@@ -276,36 +303,37 @@ struct TemplateSpecCandidate {
class TemplateSpecCandidateSet {
SmallVector<TemplateSpecCandidate, 16> Candidates;
SourceLocation Loc;
+
// Stores whether we're taking the address of these candidates. This helps us
// produce better error messages when dealing with the pass_object_size
// attribute on parameters.
bool ForTakingAddress;
- TemplateSpecCandidateSet(
- const TemplateSpecCandidateSet &) = delete;
- void operator=(const TemplateSpecCandidateSet &) = delete;
-
void destroyCandidates();
public:
TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false)
: Loc(Loc), ForTakingAddress(ForTakingAddress) {}
+ TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete;
+ TemplateSpecCandidateSet &
+ operator=(const TemplateSpecCandidateSet &) = delete;
~TemplateSpecCandidateSet() { destroyCandidates(); }
SourceLocation getLocation() const { return Loc; }
- /// \brief Clear out all of the candidates.
+ /// Clear out all of the candidates.
/// TODO: This may be unnecessary.
void clear();
- typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
+ using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator;
+
iterator begin() { return Candidates.begin(); }
iterator end() { return Candidates.end(); }
size_t size() const { return Candidates.size(); }
bool empty() const { return Candidates.empty(); }
- /// \brief Add a new candidate with NumConversions conversion sequence slots
+ /// Add a new candidate with NumConversions conversion sequence slots
/// to the overload set.
TemplateSpecCandidate &addCandidate() {
Candidates.emplace_back();
@@ -319,6 +347,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateInstCallback.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateInstCallback.h
new file mode 100644
index 000000000000..dc729d52243c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateInstCallback.h
@@ -0,0 +1,83 @@
+//===- TemplateInstCallback.h - Template Instantiation Callback - C++ --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file defines the TemplateInstantiationCallback class, which is the
+// base class for callbacks that will be notified at template instantiations.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TEMPLATE_INST_CALLBACK_H
+#define LLVM_CLANG_TEMPLATE_INST_CALLBACK_H
+
+#include "clang/Sema/Sema.h"
+
+namespace clang {
+
+/// This is a base class for callbacks that will be notified at every
+/// template instantiation.
+class TemplateInstantiationCallback {
+public:
+ virtual ~TemplateInstantiationCallback() = default;
+
+ /// Called before doing AST-parsing.
+ virtual void initialize(const Sema &TheSema) = 0;
+
+ /// Called after AST-parsing is completed.
+ virtual void finalize(const Sema &TheSema) = 0;
+
+ /// Called when instantiation of a template just began.
+ virtual void atTemplateBegin(const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) = 0;
+
+ /// Called when instantiation of a template is just about to end.
+ virtual void atTemplateEnd(const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) = 0;
+};
+
+template <class TemplateInstantiationCallbackPtrs>
+void initialize(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->initialize(TheSema);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void finalize(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->finalize(TheSema);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void atTemplateBegin(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->atTemplateBegin(TheSema, Inst);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void atTemplateEnd(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->atTemplateEnd(TheSema, Inst);
+ }
+}
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
index 5bebe52325c6..d8fe82799845 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
@@ -1,4 +1,4 @@
-//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===//
+//===- TypoCorrection.h - Class for typo correction results -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,18 +15,36 @@
#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include <cstddef>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
-/// @brief Simple class containing the result of Sema::CorrectTypo
+class DeclContext;
+class IdentifierInfo;
+class LangOptions;
+class MemberExpr;
+class NestedNameSpecifier;
+class Sema;
+
+/// Simple class containing the result of Sema::CorrectTypo
class TypoCorrection {
public:
// "Distance" for unusable corrections
- static const unsigned InvalidDistance = ~0U;
+ static const unsigned InvalidDistance = std::numeric_limits<unsigned>::max();
+
// The largest distance still considered valid (larger edit distances are
// mapped to InvalidDistance by getEditDistance).
static const unsigned MaximumDistance = 10000U;
@@ -43,9 +61,7 @@ public:
NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
unsigned QualifierDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(QualifierDistance),
- CallbackDistance(0), ForceSpecifierReplacement(false),
- RequiresImport(false) {
+ CharDistance(CharDistance), QualifierDistance(QualifierDistance) {
if (NameDecl)
CorrectionDecls.push_back(NameDecl);
}
@@ -53,8 +69,7 @@ public:
TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
unsigned CharDistance = 0)
: CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
- ForceSpecifierReplacement(false), RequiresImport(false) {
+ CharDistance(CharDistance) {
if (Name)
CorrectionDecls.push_back(Name);
}
@@ -62,24 +77,22 @@ public:
TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr,
unsigned CharDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
- ForceSpecifierReplacement(false), RequiresImport(false) {}
+ CharDistance(CharDistance) {}
- TypoCorrection()
- : CorrectionNameSpec(nullptr), CharDistance(0), QualifierDistance(0),
- CallbackDistance(0), ForceSpecifierReplacement(false),
- RequiresImport(false) {}
+ TypoCorrection() = default;
- /// \brief Gets the DeclarationName of the typo correction
+ /// Gets the DeclarationName of the typo correction
DeclarationName getCorrection() const { return CorrectionName; }
+
IdentifierInfo *getCorrectionAsIdentifierInfo() const {
return CorrectionName.getAsIdentifierInfo();
}
- /// \brief Gets the NestedNameSpecifier needed to use the typo correction
+ /// Gets the NestedNameSpecifier needed to use the typo correction
NestedNameSpecifier *getCorrectionSpecifier() const {
return CorrectionNameSpec;
}
+
void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
CorrectionNameSpec = NNS;
ForceSpecifierReplacement = (NNS != nullptr);
@@ -110,7 +123,7 @@ public:
return (ED + CharDistanceWeight / 2) / CharDistanceWeight;
}
- /// \brief Gets the "edit distance" of the typo correction from the typo.
+ /// Gets the "edit distance" of the typo correction from the typo.
/// If Normalized is true, scale the distance down by the CharDistanceWeight
/// to return the edit distance in terms of single-character edits.
unsigned getEditDistance(bool Normalized = true) const {
@@ -129,13 +142,13 @@ public:
return Normalized ? NormalizeEditDistance(ED) : ED;
}
- /// \brief Get the correction declaration found by name lookup (before we
+ /// Get the correction declaration found by name lookup (before we
/// looked through using shadow declarations and the like).
NamedDecl *getFoundDecl() const {
return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr;
}
- /// \brief Gets the pointer to the declaration of the typo correction
+ /// Gets the pointer to the declaration of the typo correction
NamedDecl *getCorrectionDecl() const {
auto *D = getFoundDecl();
return D ? D->getUnderlyingDecl() : nullptr;
@@ -145,36 +158,37 @@ public:
return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
}
- /// \brief Clears the list of NamedDecls.
+ /// Clears the list of NamedDecls.
void ClearCorrectionDecls() {
CorrectionDecls.clear();
}
- /// \brief Clears the list of NamedDecls before adding the new one.
+ /// Clears the list of NamedDecls before adding the new one.
void setCorrectionDecl(NamedDecl *CDecl) {
CorrectionDecls.clear();
addCorrectionDecl(CDecl);
}
- /// \brief Clears the list of NamedDecls and adds the given set.
+ /// Clears the list of NamedDecls and adds the given set.
void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) {
CorrectionDecls.clear();
CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end());
}
- /// \brief Add the given NamedDecl to the list of NamedDecls that are the
+ /// Add the given NamedDecl to the list of NamedDecls that are the
/// declarations associated with the DeclarationName of this TypoCorrection
void addCorrectionDecl(NamedDecl *CDecl);
std::string getAsString(const LangOptions &LO) const;
+
std::string getQuoted(const LangOptions &LO) const {
return "'" + getAsString(LO) + "'";
}
- /// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
+ /// Returns whether this TypoCorrection has a non-empty DeclarationName
explicit operator bool() const { return bool(CorrectionName); }
- /// \brief Mark this TypoCorrection as being a keyword.
+ /// Mark this TypoCorrection as being a keyword.
/// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
/// added to the list of the correction's NamedDecl pointers, NULL is added
/// as the only element in the list to mark this TypoCorrection as a keyword.
@@ -214,18 +228,23 @@ public:
return CorrectionRange;
}
- typedef SmallVectorImpl<NamedDecl *>::iterator decl_iterator;
+ using decl_iterator = SmallVectorImpl<NamedDecl *>::iterator;
+
decl_iterator begin() {
return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
}
+
decl_iterator end() { return CorrectionDecls.end(); }
- typedef SmallVectorImpl<NamedDecl *>::const_iterator const_decl_iterator;
+
+ using const_decl_iterator = SmallVectorImpl<NamedDecl *>::const_iterator;
+
const_decl_iterator begin() const {
return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
}
+
const_decl_iterator end() const { return CorrectionDecls.end(); }
- /// \brief Returns whether this typo correction is correcting to a
+ /// Returns whether this typo correction is correcting to a
/// declaration that was declared in a module that has not been imported.
bool requiresImport() const { return RequiresImport; }
void setRequiresImport(bool Req) { RequiresImport = Req; }
@@ -246,19 +265,19 @@ private:
// Results.
DeclarationName CorrectionName;
- NestedNameSpecifier *CorrectionNameSpec;
+ NestedNameSpecifier *CorrectionNameSpec = nullptr;
SmallVector<NamedDecl *, 1> CorrectionDecls;
- unsigned CharDistance;
- unsigned QualifierDistance;
- unsigned CallbackDistance;
+ unsigned CharDistance = 0;
+ unsigned QualifierDistance = 0;
+ unsigned CallbackDistance = 0;
SourceRange CorrectionRange;
- bool ForceSpecifierReplacement;
- bool RequiresImport;
+ bool ForceSpecifierReplacement = false;
+ bool RequiresImport = false;
std::vector<PartialDiagnostic> ExtraDiagnostics;
};
-/// @brief Base class for callback objects used by Sema::CorrectTypo to check
+/// Base class for callback objects used by Sema::CorrectTypo to check
/// the validity of a potential typo correction.
class CorrectionCandidateCallback {
public:
@@ -266,19 +285,15 @@ public:
explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr,
NestedNameSpecifier *TypoNNS = nullptr)
- : WantTypeSpecifiers(true), WantExpressionKeywords(true),
- WantCXXNamedCasts(true), WantFunctionLikeCasts(true),
- WantRemainingKeywords(true), WantObjCSuper(false),
- IsObjCIvarLookup(false), IsAddressOfOperand(false), Typo(Typo),
- TypoNNS(TypoNNS) {}
+ : Typo(Typo), TypoNNS(TypoNNS) {}
- virtual ~CorrectionCandidateCallback() {}
+ virtual ~CorrectionCandidateCallback() = default;
- /// \brief Simple predicate used by the default RankCandidate to
+ /// Simple predicate used by the default RankCandidate to
/// determine whether to return an edit distance of 0 or InvalidDistance.
- /// This can be overrided by validators that only need to determine if a
+ /// This can be overridden by validators that only need to determine if a
/// candidate is viable, without ranking potentially viable candidates.
- /// Only ValidateCandidate or RankCandidate need to be overriden by a
+ /// Only ValidateCandidate or RankCandidate need to be overridden by a
/// callback wishing to check the viability of correction candidates.
/// The default predicate always returns true if the candidate is not a type
/// name or keyword, true for types if WantTypeSpecifiers is true, and true
@@ -286,7 +301,7 @@ public:
/// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true.
virtual bool ValidateCandidate(const TypoCorrection &candidate);
- /// \brief Method used by Sema::CorrectTypo to assign an "edit distance" rank
+ /// Method used by Sema::CorrectTypo to assign an "edit distance" rank
/// to a candidate (where a lower value represents a better candidate), or
/// returning InvalidDistance if the candidate is not at all viable. For
/// validation callbacks that only need to determine if a candidate is viable,
@@ -304,16 +319,16 @@ public:
// Flags for context-dependent keywords. WantFunctionLikeCasts is only
// used/meaningful when WantCXXNamedCasts is false.
// TODO: Expand these to apply to non-keywords or possibly remove them.
- bool WantTypeSpecifiers;
- bool WantExpressionKeywords;
- bool WantCXXNamedCasts;
- bool WantFunctionLikeCasts;
- bool WantRemainingKeywords;
- bool WantObjCSuper;
+ bool WantTypeSpecifiers = true;
+ bool WantExpressionKeywords = true;
+ bool WantCXXNamedCasts = true;
+ bool WantFunctionLikeCasts = true;
+ bool WantRemainingKeywords = true;
+ bool WantObjCSuper = false;
// Temporary hack for the one case where a CorrectTypoContext enum is used
// when looking up results.
- bool IsObjCIvarLookup;
- bool IsAddressOfOperand;
+ bool IsObjCIvarLookup = false;
+ bool IsAddressOfOperand = false;
protected:
bool MatchesTypo(const TypoCorrection &candidate) {
@@ -328,7 +343,7 @@ protected:
NestedNameSpecifier *TypoNNS;
};
-/// @brief Simple template class for restricting typo correction candidates
+/// Simple template class for restricting typo correction candidates
/// to ones having a single Decl* of the given type.
template <class C>
class DeclFilterCCC : public CorrectionCandidateCallback {
@@ -338,7 +353,7 @@ public:
}
};
-// @brief Callback class to limit the allowed keywords and to only accept typo
+// Callback class to limit the allowed keywords and to only accept typo
// corrections that are keywords or whose decls refer to functions (or template
// functions) that accept the given number of arguments.
class FunctionCallFilterCCC : public CorrectionCandidateCallback {
@@ -349,14 +364,14 @@ public:
bool ValidateCandidate(const TypoCorrection &candidate) override;
- private:
+private:
unsigned NumArgs;
bool HasExplicitTemplateArgs;
DeclContext *CurContext;
MemberExpr *MemberFn;
};
-// @brief Callback class that effectively disabled typo correction
+// Callback class that effectively disabled typo correction
class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
public:
NoTypoCorrectionCCC() {
@@ -372,6 +387,6 @@ public:
}
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SEMA_TYPOCORRECTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Weak.h b/contrib/llvm/tools/clang/include/clang/Sema/Weak.h
index 9c7212e0c8ee..115e97bcd2ce 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Weak.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Weak.h
@@ -21,7 +21,7 @@ namespace clang {
class IdentifierInfo;
-/// \brief Captures information about a \#pragma weak directive.
+/// Captures information about a \#pragma weak directive.
class WeakInfo {
IdentifierInfo *alias; // alias (optional)
SourceLocation loc; // for diagnostics
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
index 34a7bb330174..430fc48379fe 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
@@ -31,7 +31,7 @@
namespace clang {
namespace serialization {
- /// \brief AST file major version number supported by this version of
+ /// AST file major version number supported by this version of
/// Clang.
///
/// Whenever the AST file format changes in a way that makes it
@@ -42,9 +42,9 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
- const unsigned VERSION_MAJOR = 6;
+ const unsigned VERSION_MAJOR = 7;
- /// \brief AST file minor version number supported by this version of
+ /// AST file minor version number supported by this version of
/// Clang.
///
/// Whenever the AST format changes in a way that is still
@@ -54,17 +54,17 @@ namespace serialization {
/// should be increased.
const unsigned VERSION_MINOR = 0;
- /// \brief An ID number that refers to an identifier in an AST file.
- ///
+ /// An ID number that refers to an identifier in an AST file.
+ ///
/// The ID numbers of identifiers are consecutive (in order of discovery)
/// and start at 1. 0 is reserved for NULL.
using IdentifierID = uint32_t;
-
- /// \brief An ID number that refers to a declaration in an AST file.
+
+ /// An ID number that refers to a declaration in an AST file.
///
/// The ID numbers of declarations are consecutive (in order of
- /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
- /// At the start of a chain of precompiled headers, declaration ID 1 is
+ /// 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.
using DeclID = uint32_t;
@@ -73,7 +73,7 @@ namespace serialization {
using LocalDeclID = DeclID;
using GlobalDeclID = DeclID;
- /// \brief An ID number that refers to a type in an AST file.
+ /// An ID number that refers to a type in an AST file.
///
/// The ID of a type is partitioned into two parts: the lower
/// three bits are used to store the const/volatile/restrict
@@ -85,7 +85,7 @@ namespace serialization {
/// other types that have serialized representations.
using TypeID = uint32_t;
- /// \brief A type index; the type ID with the qualifier bits removed.
+ /// A type index; the type ID with the qualifier bits removed.
class TypeIdx {
uint32_t Idx = 0;
@@ -98,14 +98,14 @@ namespace serialization {
TypeID asTypeID(unsigned FastQuals) const {
if (Idx == uint32_t(-1))
return TypeID(-1);
-
+
return (Idx << Qualifiers::FastWidth) | FastQuals;
}
static TypeIdx fromTypeID(TypeID ID) {
if (ID == TypeID(-1))
return TypeIdx(-1);
-
+
return TypeIdx(ID >> Qualifiers::FastWidth);
}
};
@@ -124,65 +124,65 @@ namespace serialization {
}
static unsigned getHashValue(QualType T) {
- assert(!T.getLocalFastQualifiers() &&
+ assert(!T.getLocalFastQualifiers() &&
"hash invalid for types with fast quals");
uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
}
};
- /// \brief An ID number that refers to an identifier in an AST file.
+ /// An ID number that refers to an identifier in an AST file.
using IdentID = uint32_t;
- /// \brief The number of predefined identifier IDs.
+ /// 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.
+ /// An ID number that refers to a macro in an AST file.
using MacroID = uint32_t;
- /// \brief A global ID number that refers to a macro in an AST file.
+ /// A global ID number that refers to a macro in an AST file.
using GlobalMacroID = uint32_t;
- /// \brief A local to a module ID number that refers to a macro in an
+ /// A local to a module ID number that refers to a macro in an
/// AST file.
using LocalMacroID = uint32_t;
- /// \brief The number of predefined macro IDs.
+ /// 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.
+ /// An ID number that refers to an ObjC selector in an AST file.
using SelectorID = uint32_t;
- /// \brief The number of predefined selector IDs.
+ /// 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
+
+ /// An ID number that refers to a set of CXXBaseSpecifiers in an
/// AST file.
using CXXBaseSpecifiersID = uint32_t;
- /// \brief An ID number that refers to a list of CXXCtorInitializers in an
+ /// An ID number that refers to a list of CXXCtorInitializers in an
/// AST file.
using CXXCtorInitializersID = uint32_t;
- /// \brief An ID number that refers to an entity in the detailed
+ /// An ID number that refers to an entity in the detailed
/// preprocessing record.
using PreprocessedEntityID = uint32_t;
- /// \brief An ID number that refers to a submodule in a module file.
+ /// An ID number that refers to a submodule in a module file.
using SubmoduleID = uint32_t;
-
- /// \brief The number of predefined submodule IDs.
+
+ /// The number of predefined submodule IDs.
const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
- /// \brief Source range/offset of a preprocessed entity.
+ /// Source range/offset of a preprocessed entity.
struct PPEntityOffset {
- /// \brief Raw source location of beginning of range.
+ /// Raw source location of beginning of range.
unsigned Begin;
- /// \brief Raw source location of end of range.
+ /// Raw source location of end of range.
unsigned End;
- /// \brief Offset in the AST file.
+ /// Offset in the AST file.
uint32_t BitOffset;
PPEntityOffset(SourceRange R, uint32_t BitOffset)
@@ -198,12 +198,31 @@ namespace serialization {
}
};
- /// \brief Source range/offset of a preprocessed entity.
+ /// Source range of a skipped preprocessor region
+ struct PPSkippedRange {
+ /// Raw source location of beginning of range.
+ unsigned Begin;
+ /// Raw source location of end of range.
+ unsigned End;
+
+ PPSkippedRange(SourceRange R)
+ : Begin(R.getBegin().getRawEncoding()),
+ End(R.getEnd().getRawEncoding()) { }
+
+ SourceLocation getBegin() const {
+ return SourceLocation::getFromRawEncoding(Begin);
+ }
+ SourceLocation getEnd() const {
+ return SourceLocation::getFromRawEncoding(End);
+ }
+ };
+
+ /// Source range/offset of a preprocessed entity.
struct DeclOffset {
- /// \brief Raw source location.
+ /// Raw source location.
unsigned Loc = 0;
- /// \brief Offset in the AST file.
+ /// Offset in the AST file.
uint32_t BitOffset = 0;
DeclOffset() = default;
@@ -219,56 +238,56 @@ namespace serialization {
}
};
- /// \brief The number of predefined preprocessed entity IDs.
+ /// The number of predefined preprocessed entity IDs.
const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;
- /// \brief Describes the various kinds of blocks that occur within
+ /// Describes the various kinds of blocks that occur within
/// an AST file.
enum BlockIDs {
- /// \brief The AST block, which acts as a container around the
+ /// The AST block, which acts as a container around the
/// full AST block.
AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
- /// \brief The block containing information about the source
+ /// The block containing information about the source
/// manager.
SOURCE_MANAGER_BLOCK_ID,
- /// \brief The block containing information about the
+ /// The block containing information about the
/// preprocessor.
PREPROCESSOR_BLOCK_ID,
- /// \brief The block containing the definitions of all of the
+ /// The block containing the definitions of all of the
/// types and decls used within the AST file.
DECLTYPES_BLOCK_ID,
- /// \brief The block containing the detailed preprocessing record.
+ /// The block containing the detailed preprocessing record.
PREPROCESSOR_DETAIL_BLOCK_ID,
- /// \brief The block containing the submodule structure.
+ /// The block containing the submodule structure.
SUBMODULE_BLOCK_ID,
- /// \brief The block containing comments.
+ /// The block containing comments.
COMMENTS_BLOCK_ID,
- /// \brief The control block, which contains all of the
+ /// The control block, which contains all of the
/// information that needs to be validated prior to committing
/// to loading the AST file.
CONTROL_BLOCK_ID,
- /// \brief The block of input files, which were used as inputs
+ /// The block of input files, which were used as inputs
/// to create this AST file.
///
/// This block is part of the control block.
INPUT_FILES_BLOCK_ID,
- /// \brief The block of configuration options, used to check that
+ /// The block of configuration options, used to check that
/// a module is being used in a configuration compatible with the
/// configuration in which it was built.
///
/// This block is part of the control block.
OPTIONS_BLOCK_ID,
- /// \brief A block containing a module file extension.
+ /// A block containing a module file extension.
EXTENSION_BLOCK_ID,
/// A block with unhashed content.
@@ -278,47 +297,47 @@ namespace serialization {
UNHASHED_CONTROL_BLOCK_ID,
};
- /// \brief Record types that occur within the control block.
+ /// Record types that occur within the control block.
enum ControlRecordTypes {
- /// \brief AST file metadata, including the AST file version number
+ /// AST file metadata, including the AST file version number
/// and information about the compiler used to build this AST file.
METADATA = 1,
- /// \brief Record code for the list of other AST files imported by
+ /// Record code for the list of other AST files imported by
/// this AST file.
IMPORTS,
- /// \brief Record code for the original file that was used to
+ /// Record code for the original file that was used to
/// generate the AST file, including both its file ID and its
/// name.
ORIGINAL_FILE,
-
- /// \brief The directory that the PCH was originally created in.
+
+ /// The directory that the PCH was originally created in.
ORIGINAL_PCH_DIR,
- /// \brief Record code for file ID of the file or buffer that was used to
+ /// Record code for file ID of the file or buffer that was used to
/// generate the AST file.
ORIGINAL_FILE_ID,
- /// \brief Offsets into the input-files block where input files
+ /// Offsets into the input-files block where input files
/// reside.
INPUT_FILE_OFFSETS,
- /// \brief Record code for the module name.
+ /// Record code for the module name.
MODULE_NAME,
- /// \brief Record code for the module map file that was used to build this
+ /// Record code for the module map file that was used to build this
/// AST file.
MODULE_MAP_FILE,
- /// \brief Record code for the module build directory.
+ /// Record code for the module build directory.
MODULE_DIRECTORY,
};
- /// \brief Record types that occur within the options block inside
+ /// Record types that occur within the options block inside
/// the control block.
enum OptionsRecordTypes {
- /// \brief Record code for the language options table.
+ /// Record code for the language options table.
///
/// The record with this code contains the contents of the
/// LangOptions structure. We serialize the entire contents of
@@ -326,16 +345,16 @@ namespace serialization {
/// actually important to check.
LANGUAGE_OPTIONS = 1,
- /// \brief Record code for the target options table.
+ /// Record code for the target options table.
TARGET_OPTIONS,
- /// \brief Record code for the filesystem options table.
+ /// Record code for the filesystem options table.
FILE_SYSTEM_OPTIONS,
- /// \brief Record code for the headers search options table.
+ /// Record code for the headers search options table.
HEADER_SEARCH_OPTIONS,
- /// \brief Record code for the preprocessor options table.
+ /// Record code for the preprocessor options table.
PREPROCESSOR_OPTIONS,
};
@@ -351,7 +370,7 @@ namespace serialization {
DIAG_PRAGMA_MAPPINGS,
};
- /// \brief Record code for extension blocks.
+ /// Record code for extension blocks.
enum ExtensionBlockRecordTypes {
/// Metadata describing this particular extension.
EXTENSION_METADATA = 1,
@@ -360,16 +379,16 @@ namespace serialization {
FIRST_EXTENSION_RECORD_ID = 4
};
- /// \brief Record types that occur within the input-files block
+ /// Record types that occur within the input-files block
/// inside the control block.
enum InputFileRecordTypes {
- /// \brief An input file.
+ /// An input file.
INPUT_FILE = 1
};
- /// \brief Record types that occur within the AST block itself.
+ /// Record types that occur within the AST block itself.
enum ASTRecordTypes {
- /// \brief Record code for the offsets of each type.
+ /// Record code for the offsets of each type.
///
/// The TYPE_OFFSET constant describes the record that occurs
/// within the AST block. The record itself is an array of offsets that
@@ -383,7 +402,7 @@ namespace serialization {
/// corresponding record within the DECLTYPES_BLOCK_ID block.
TYPE_OFFSET = 1,
- /// \brief Record code for the offsets of each decl.
+ /// Record code for the offsets of each decl.
///
/// The DECL_OFFSET constant describes the record that occurs
/// within the block identified by DECL_OFFSETS_BLOCK_ID within
@@ -395,7 +414,7 @@ namespace serialization {
/// reserved for the translation unit declaration.
DECL_OFFSET = 2,
- /// \brief Record code for the table of offsets of each
+ /// Record code for the table of offsets of each
/// identifier ID.
///
/// The offset table contains offsets into the blob stored in
@@ -403,12 +422,12 @@ namespace serialization {
/// NULL-terminated string that corresponds to that identifier.
IDENTIFIER_OFFSET = 3,
- /// \brief This is so that older clang versions, before the introduction
+ /// This is so that older clang versions, before the introduction
/// of the control block, can read and reject the newer PCH format.
/// *DON'T CHANGE THIS NUMBER*.
METADATA_OLD_FORMAT = 4,
- /// \brief Record code for the identifier table.
+ /// Record code for the identifier table.
///
/// The identifier table is a simple blob that contains
/// NULL-terminated strings for all of the identifiers
@@ -422,7 +441,7 @@ namespace serialization {
/// IDs).
IDENTIFIER_TABLE = 5,
- /// \brief Record code for the array of eagerly deserialized decls.
+ /// Record code for the array of eagerly deserialized decls.
///
/// The AST file contains a list of all of the declarations that should be
/// eagerly deserialized present within the parsed headers, stored as an
@@ -432,7 +451,7 @@ namespace serialization {
/// program (e.g., for code generation).
EAGERLY_DESERIALIZED_DECLS = 6,
- /// \brief Record code for the set of non-builtin, special
+ /// Record code for the set of non-builtin, special
/// types.
///
/// This record contains the type IDs for the various type nodes
@@ -441,31 +460,31 @@ namespace serialization {
/// offsets into this record.
SPECIAL_TYPES = 7,
- /// \brief Record code for the extra statistics we gather while
+ /// Record code for the extra statistics we gather while
/// generating an AST file.
STATISTICS = 8,
- /// \brief Record code for the array of tentative definitions.
+ /// Record code for the array of tentative definitions.
TENTATIVE_DEFINITIONS = 9,
// ID 10 used to be for a list of extern "C" declarations.
- /// \brief Record code for the table of offsets into the
+ /// Record code for the table of offsets into the
/// Objective-C method pool.
SELECTOR_OFFSETS = 11,
- /// \brief Record code for the Objective-C method pool,
+ /// Record code for the Objective-C method pool,
METHOD_POOL = 12,
- /// \brief The value of the next __COUNTER__ to dispense.
+ /// The value of the next __COUNTER__ to dispense.
/// [PP_COUNTER_VALUE, Val]
PP_COUNTER_VALUE = 13,
- /// \brief Record code for the table of offsets into the block
+ /// Record code for the table of offsets into the block
/// of source-location information.
SOURCE_LOCATION_OFFSETS = 14,
- /// \brief Record code for the set of source location entries
+ /// Record code for the set of source location entries
/// that need to be preloaded by the AST reader.
///
/// This set contains the source location entry for the
@@ -473,47 +492,47 @@ namespace serialization {
/// preloaded.
SOURCE_LOCATION_PRELOADS = 15,
- /// \brief Record code for the set of ext_vector type names.
+ /// Record code for the set of ext_vector type names.
EXT_VECTOR_DECLS = 16,
- /// \brief Record code for the array of unused file scoped decls.
+ /// Record code for the array of unused file scoped decls.
UNUSED_FILESCOPED_DECLS = 17,
- /// \brief Record code for the table of offsets to entries in the
+ /// Record code for the table of offsets to entries in the
/// preprocessing record.
PPD_ENTITIES_OFFSETS = 18,
- /// \brief Record code for the array of VTable uses.
+ /// Record code for the array of VTable uses.
VTABLE_USES = 19,
// ID 20 used to be for a list of dynamic classes.
- /// \brief Record code for referenced selector pool.
+ /// Record code for referenced selector pool.
REFERENCED_SELECTOR_POOL = 21,
- /// \brief Record code for an update to the TU's lexically contained
+ /// Record code for an update to the TU's lexically contained
/// declarations.
TU_UPDATE_LEXICAL = 22,
// ID 23 used to be for a list of local redeclarations.
- /// \brief Record code for declarations that Sema keeps references of.
+ /// Record code for declarations that Sema keeps references of.
SEMA_DECL_REFS = 24,
- /// \brief Record code for weak undeclared identifiers.
+ /// Record code for weak undeclared identifiers.
WEAK_UNDECLARED_IDENTIFIERS = 25,
- /// \brief Record code for pending implicit instantiations.
+ /// Record code for pending implicit instantiations.
PENDING_IMPLICIT_INSTANTIATIONS = 26,
// ID 27 used to be for a list of replacement decls.
- /// \brief Record code for an update to a decl context's lookup table.
+ /// Record code for an update to a decl context's lookup table.
///
/// In practice, this should only be used for the TU and namespaces.
UPDATE_VISIBLE = 28,
- /// \brief Record for offsets of DECL_UPDATES records for declarations
+ /// Record for offsets of DECL_UPDATES records for declarations
/// that were modified after being deserialized and need updates.
DECL_UPDATE_OFFSETS = 29,
@@ -524,242 +543,245 @@ namespace serialization {
// ID 32 used to be the code for \#pragma diagnostic mappings.
- /// \brief Record code for special CUDA declarations.
+ /// Record code for special CUDA declarations.
CUDA_SPECIAL_DECL_REFS = 33,
- /// \brief Record code for header search information.
+ /// Record code for header search information.
HEADER_SEARCH_TABLE = 34,
- /// \brief Record code for floating point \#pragma options.
+ /// Record code for floating point \#pragma options.
FP_PRAGMA_OPTIONS = 35,
- /// \brief Record code for enabled OpenCL extensions.
+ /// Record code for enabled OpenCL extensions.
OPENCL_EXTENSIONS = 36,
- /// \brief The list of delegating constructor declarations.
+ /// The list of delegating constructor declarations.
DELEGATING_CTORS = 37,
- /// \brief Record code for the set of known namespaces, which are used
+ /// Record code for the set of known namespaces, which are used
/// for typo correction.
KNOWN_NAMESPACES = 38,
- /// \brief Record code for the remapping information used to relate
+ /// Record code for the remapping information used to relate
/// loaded modules to the various offsets and IDs(e.g., source location
/// offests, declaration and type IDs) that are used in that module to
/// refer to other modules.
MODULE_OFFSET_MAP = 39,
- /// \brief Record code for the source manager line table information,
+ /// Record code for the source manager line table information,
/// which stores information about \#line directives.
SOURCE_MANAGER_LINE_TABLE = 40,
- /// \brief Record code for map of Objective-C class definition IDs to the
+ /// Record code for map of Objective-C class definition IDs to the
/// ObjC categories in a module that are attached to that class.
OBJC_CATEGORIES_MAP = 41,
- /// \brief Record code for a file sorted array of DeclIDs in a module.
+ /// Record code for a file sorted array of DeclIDs in a module.
FILE_SORTED_DECLS = 42,
- /// \brief Record code for an array of all of the (sub)modules that were
+ /// Record code for an array of all of the (sub)modules that were
/// imported by the AST file.
IMPORTED_MODULES = 43,
// ID 44 used to be a table of merged canonical declarations.
// ID 45 used to be a list of declaration IDs of local redeclarations.
- /// \brief Record code for the array of Objective-C categories (including
+ /// Record code for the array of Objective-C categories (including
/// extensions).
///
/// This array can only be interpreted properly using the Objective-C
/// categories map.
OBJC_CATEGORIES = 46,
- /// \brief Record code for the table of offsets of each macro ID.
+ /// Record code for the table of offsets of each macro ID.
///
/// The offset table contains offsets into the blob stored in
/// the preprocessor block. Each offset points to the corresponding
/// macro definition.
MACRO_OFFSET = 47,
- /// \brief A list of "interesting" identifiers. Only used in C++ (where we
+ /// A list of "interesting" identifiers. Only used in C++ (where we
/// don't normally do lookups into the serialized identifier table). These
/// are eagerly deserialized.
INTERESTING_IDENTIFIERS = 48,
- /// \brief Record code for undefined but used functions and variables that
+ /// Record code for undefined but used functions and variables that
/// need a definition in this TU.
UNDEFINED_BUT_USED = 49,
- /// \brief Record code for late parsed template functions.
+ /// Record code for late parsed template functions.
LATE_PARSED_TEMPLATE = 50,
- /// \brief Record code for \#pragma optimize options.
+ /// Record code for \#pragma optimize options.
OPTIMIZE_PRAGMA_OPTIONS = 51,
- /// \brief Record code for potentially unused local typedef names.
+ /// Record code for potentially unused local typedef names.
UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52,
// ID 53 used to be a table of constructor initializer records.
- /// \brief Delete expressions that will be analyzed later.
+ /// Delete expressions that will be analyzed later.
DELETE_EXPRS_TO_ANALYZE = 54,
- /// \brief Record code for \#pragma ms_struct options.
+ /// Record code for \#pragma ms_struct options.
MSSTRUCT_PRAGMA_OPTIONS = 55,
- /// \brief Record code for \#pragma ms_struct options.
+ /// Record code for \#pragma ms_struct options.
POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56,
- /// \brief Number of unmatched #pragma clang cuda_force_host_device begin
+ /// Number of unmatched #pragma clang cuda_force_host_device begin
/// directives we've seen.
CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57,
- /// \brief Record code for types associated with OpenCL extensions.
+ /// Record code for types associated with OpenCL extensions.
OPENCL_EXTENSION_TYPES = 58,
- /// \brief Record code for declarations associated with OpenCL extensions.
+ /// Record code for declarations associated with OpenCL extensions.
OPENCL_EXTENSION_DECLS = 59,
MODULAR_CODEGEN_DECLS = 60,
- /// \brief Record code for \#pragma pack options.
+ /// Record code for \#pragma pack options.
PACK_PRAGMA_OPTIONS = 61,
- /// \brief The stack of open #ifs/#ifdefs recorded in a preamble.
+ /// The stack of open #ifs/#ifdefs recorded in a preamble.
PP_CONDITIONAL_STACK = 62,
+
+ /// A table of skipped ranges within the preprocessing record.
+ PPD_SKIPPED_RANGES = 63
};
- /// \brief Record types used within a source manager block.
+ /// Record types used within a source manager block.
enum SourceManagerRecordTypes {
- /// \brief Describes a source location entry (SLocEntry) for a
+ /// Describes a source location entry (SLocEntry) for a
/// file.
SM_SLOC_FILE_ENTRY = 1,
- /// \brief Describes a source location entry (SLocEntry) for a
+ /// 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
+ /// 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
+ /// 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
+ /// Describes a source location entry (SLocEntry) for a
/// macro expansion.
SM_SLOC_EXPANSION_ENTRY = 5
};
- /// \brief Record types used within a preprocessor block.
+ /// Record types used within a preprocessor block.
enum PreprocessorRecordTypes {
// The macros in the PP section are a PP_MACRO_* instance followed by a
// list of PP_TOKEN instances for each token in the definition.
- /// \brief An object-like macro definition.
+ /// An object-like macro definition.
/// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
PP_MACRO_OBJECT_LIKE = 1,
- /// \brief A function-like macro definition.
+ /// A function-like macro definition.
/// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,
/// IsGNUVarars, NumArgs, ArgIdentInfoID* ]
PP_MACRO_FUNCTION_LIKE = 2,
- /// \brief Describes one token.
+ /// Describes one token.
/// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
PP_TOKEN = 3,
- /// \brief The macro directives history for a particular identifier.
+ /// The macro directives history for a particular identifier.
PP_MACRO_DIRECTIVE_HISTORY = 4,
- /// \brief A macro directive exported by a module.
+ /// A macro directive exported by a module.
/// [PP_MODULE_MACRO, SubmoduleID, MacroID, (Overridden SubmoduleID)*]
PP_MODULE_MACRO = 5,
};
- /// \brief Record types used within a preprocessor detail block.
+ /// Record types used within a preprocessor detail block.
enum PreprocessorDetailRecordTypes {
- /// \brief Describes a macro expansion within the preprocessing record.
+ /// Describes a macro expansion within the preprocessing record.
PPD_MACRO_EXPANSION = 0,
-
- /// \brief Describes a macro definition within the preprocessing record.
+
+ /// Describes a macro definition within the preprocessing record.
PPD_MACRO_DEFINITION = 1,
-
- /// \brief Describes an inclusion directive within the preprocessing
+
+ /// Describes an inclusion directive within the preprocessing
/// record.
PPD_INCLUSION_DIRECTIVE = 2
};
-
- /// \brief Record types used within a submodule description block.
+
+ /// Record types used within a submodule description block.
enum SubmoduleRecordTypes {
- /// \brief Metadata for submodules as a whole.
+ /// Metadata for submodules as a whole.
SUBMODULE_METADATA = 0,
- /// \brief Defines the major attributes of a submodule, including its
+ /// 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,
+ /// 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.
+ /// Specifies a header that falls into this (sub)module.
SUBMODULE_HEADER = 3,
- /// \brief Specifies a top-level header that falls into this (sub)module.
+ /// Specifies a top-level header that falls into this (sub)module.
SUBMODULE_TOPHEADER = 4,
- /// \brief Specifies an umbrella directory.
+ /// Specifies an umbrella directory.
SUBMODULE_UMBRELLA_DIR = 5,
- /// \brief Specifies the submodules that are imported by this
+ /// Specifies the submodules that are imported by this
/// submodule.
SUBMODULE_IMPORTS = 6,
- /// \brief Specifies the submodules that are re-exported from this
+ /// Specifies the submodules that are re-exported from this
/// submodule.
SUBMODULE_EXPORTS = 7,
- /// \brief Specifies a required feature.
+ /// Specifies a required feature.
SUBMODULE_REQUIRES = 8,
- /// \brief Specifies a header that has been explicitly excluded
+ /// Specifies a header that has been explicitly excluded
/// from this submodule.
SUBMODULE_EXCLUDED_HEADER = 9,
- /// \brief Specifies a library or framework to link against.
+ /// Specifies a library or framework to link against.
SUBMODULE_LINK_LIBRARY = 10,
- /// \brief Specifies a configuration macro for this module.
+ /// Specifies a configuration macro for this module.
SUBMODULE_CONFIG_MACRO = 11,
- /// \brief Specifies a conflict with another module.
+ /// Specifies a conflict with another module.
SUBMODULE_CONFLICT = 12,
- /// \brief Specifies a header that is private to this submodule.
+ /// 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
+ /// 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
+ /// 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
+ /// 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
+ /// 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.
+ /// Record types used within a comments block.
enum CommentRecordTypes {
COMMENTS_RAW_COMMENT = 0
};
@@ -771,7 +793,7 @@ namespace serialization {
///
/// @{
- /// \brief Predefined type IDs.
+ /// Predefined type IDs.
///
/// These type IDs correspond to predefined types in the AST
/// context, such as built-in types (int) and special place-holder
@@ -779,496 +801,574 @@ namespace serialization {
/// types are never actually serialized, since they will be built
/// by the AST context when it is created.
enum PredefinedTypeIDs {
- /// \brief The NULL type.
+ /// The NULL type.
PREDEF_TYPE_NULL_ID = 0,
- /// \brief The void type.
+ /// The void type.
PREDEF_TYPE_VOID_ID = 1,
- /// \brief The 'bool' or '_Bool' type.
+ /// The 'bool' or '_Bool' type.
PREDEF_TYPE_BOOL_ID = 2,
- /// \brief The 'char' type, when it is unsigned.
+ /// The 'char' type, when it is unsigned.
PREDEF_TYPE_CHAR_U_ID = 3,
- /// \brief The 'unsigned char' type.
+ /// The 'unsigned char' type.
PREDEF_TYPE_UCHAR_ID = 4,
- /// \brief The 'unsigned short' type.
+ /// The 'unsigned short' type.
PREDEF_TYPE_USHORT_ID = 5,
- /// \brief The 'unsigned int' type.
+ /// The 'unsigned int' type.
PREDEF_TYPE_UINT_ID = 6,
- /// \brief The 'unsigned long' type.
+ /// The 'unsigned long' type.
PREDEF_TYPE_ULONG_ID = 7,
- /// \brief The 'unsigned long long' type.
+ /// The 'unsigned long long' type.
PREDEF_TYPE_ULONGLONG_ID = 8,
- /// \brief The 'char' type, when it is signed.
+ /// The 'char' type, when it is signed.
PREDEF_TYPE_CHAR_S_ID = 9,
- /// \brief The 'signed char' type.
+ /// The 'signed char' type.
PREDEF_TYPE_SCHAR_ID = 10,
- /// \brief The C++ 'wchar_t' type.
+ /// The C++ 'wchar_t' type.
PREDEF_TYPE_WCHAR_ID = 11,
- /// \brief The (signed) 'short' type.
+ /// The (signed) 'short' type.
PREDEF_TYPE_SHORT_ID = 12,
- /// \brief The (signed) 'int' type.
+ /// The (signed) 'int' type.
PREDEF_TYPE_INT_ID = 13,
- /// \brief The (signed) 'long' type.
+ /// The (signed) 'long' type.
PREDEF_TYPE_LONG_ID = 14,
- /// \brief The (signed) 'long long' type.
+ /// The (signed) 'long long' type.
PREDEF_TYPE_LONGLONG_ID = 15,
- /// \brief The 'float' type.
+ /// The 'float' type.
PREDEF_TYPE_FLOAT_ID = 16,
- /// \brief The 'double' type.
+ /// The 'double' type.
PREDEF_TYPE_DOUBLE_ID = 17,
- /// \brief The 'long double' type.
+ /// The 'long double' type.
PREDEF_TYPE_LONGDOUBLE_ID = 18,
- /// \brief The placeholder type for overloaded function sets.
+ /// The placeholder type for overloaded function sets.
PREDEF_TYPE_OVERLOAD_ID = 19,
- /// \brief The placeholder type for dependent types.
+ /// The placeholder type for dependent types.
PREDEF_TYPE_DEPENDENT_ID = 20,
- /// \brief The '__uint128_t' type.
+ /// The '__uint128_t' type.
PREDEF_TYPE_UINT128_ID = 21,
- /// \brief The '__int128_t' type.
+ /// The '__int128_t' type.
PREDEF_TYPE_INT128_ID = 22,
- /// \brief The type of 'nullptr'.
+ /// The type of 'nullptr'.
PREDEF_TYPE_NULLPTR_ID = 23,
- /// \brief The C++ 'char16_t' type.
+ /// The C++ 'char16_t' type.
PREDEF_TYPE_CHAR16_ID = 24,
- /// \brief The C++ 'char32_t' type.
+ /// The C++ 'char32_t' type.
PREDEF_TYPE_CHAR32_ID = 25,
- /// \brief The ObjC 'id' type.
+ /// The ObjC 'id' type.
PREDEF_TYPE_OBJC_ID = 26,
- /// \brief The ObjC 'Class' type.
+ /// The ObjC 'Class' type.
PREDEF_TYPE_OBJC_CLASS = 27,
- /// \brief The ObjC 'SEL' type.
+ /// The ObjC 'SEL' type.
PREDEF_TYPE_OBJC_SEL = 28,
- /// \brief The 'unknown any' placeholder type.
+ /// The 'unknown any' placeholder type.
PREDEF_TYPE_UNKNOWN_ANY = 29,
- /// \brief The placeholder type for bound member functions.
+ /// The placeholder type for bound member functions.
PREDEF_TYPE_BOUND_MEMBER = 30,
- /// \brief The "auto" deduction type.
+ /// The "auto" deduction type.
PREDEF_TYPE_AUTO_DEDUCT = 31,
- /// \brief The "auto &&" deduction type.
+ /// The "auto &&" deduction type.
PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
- /// \brief The OpenCL 'half' / ARM NEON __fp16 type.
+ /// The OpenCL 'half' / ARM NEON __fp16 type.
PREDEF_TYPE_HALF_ID = 33,
- /// \brief ARC's unbridged-cast placeholder type.
+ /// ARC's unbridged-cast placeholder type.
PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
- /// \brief The pseudo-object placeholder type.
+ /// The pseudo-object placeholder type.
PREDEF_TYPE_PSEUDO_OBJECT = 35,
- /// \brief The placeholder type for builtin functions.
+ /// The placeholder type for builtin functions.
PREDEF_TYPE_BUILTIN_FN = 36,
- /// \brief OpenCL event type.
+ /// OpenCL event type.
PREDEF_TYPE_EVENT_ID = 37,
- /// \brief OpenCL clk event type.
+ /// OpenCL clk event type.
PREDEF_TYPE_CLK_EVENT_ID = 38,
- /// \brief OpenCL sampler type.
+ /// OpenCL sampler type.
PREDEF_TYPE_SAMPLER_ID = 39,
- /// \brief OpenCL queue type.
+ /// OpenCL queue type.
PREDEF_TYPE_QUEUE_ID = 40,
- /// \brief OpenCL reserve_id type.
+ /// OpenCL reserve_id type.
PREDEF_TYPE_RESERVE_ID_ID = 41,
- /// \brief The placeholder type for OpenMP array section.
+ /// The placeholder type for OpenMP array section.
PREDEF_TYPE_OMP_ARRAY_SECTION = 42,
- /// \brief The '__float128' type
+ /// The '__float128' type
PREDEF_TYPE_FLOAT128_ID = 43,
- /// \brief The '_Float16' type
+ /// The '_Float16' type
PREDEF_TYPE_FLOAT16_ID = 44,
- /// \brief OpenCL image types with auto numeration
+ /// The C++ 'char8_t' type.
+ PREDEF_TYPE_CHAR8_ID = 45,
+
+ /// \brief The 'short _Accum' type
+ PREDEF_TYPE_SHORT_ACCUM_ID = 46,
+
+ /// \brief The '_Accum' type
+ PREDEF_TYPE_ACCUM_ID = 47,
+
+ /// \brief The 'long _Accum' type
+ PREDEF_TYPE_LONG_ACCUM_ID = 48,
+
+ /// \brief The 'unsigned short _Accum' type
+ PREDEF_TYPE_USHORT_ACCUM_ID = 49,
+
+ /// \brief The 'unsigned _Accum' type
+ PREDEF_TYPE_UACCUM_ID = 50,
+
+ /// \brief The 'unsigned long _Accum' type
+ PREDEF_TYPE_ULONG_ACCUM_ID = 51,
+
+ /// \brief The 'short _Fract' type
+ PREDEF_TYPE_SHORT_FRACT_ID = 52,
+
+ /// \brief The '_Fract' type
+ PREDEF_TYPE_FRACT_ID = 53,
+
+ /// \brief The 'long _Fract' type
+ PREDEF_TYPE_LONG_FRACT_ID = 54,
+
+ /// \brief The 'unsigned short _Fract' type
+ PREDEF_TYPE_USHORT_FRACT_ID = 55,
+
+ /// \brief The 'unsigned _Fract' type
+ PREDEF_TYPE_UFRACT_ID = 56,
+
+ /// \brief The 'unsigned long _Fract' type
+ PREDEF_TYPE_ULONG_FRACT_ID = 57,
+
+ /// \brief The '_Sat short _Accum' type
+ PREDEF_TYPE_SAT_SHORT_ACCUM_ID = 58,
+
+ /// \brief The '_Sat _Accum' type
+ PREDEF_TYPE_SAT_ACCUM_ID = 59,
+
+ /// \brief The '_Sat long _Accum' type
+ PREDEF_TYPE_SAT_LONG_ACCUM_ID = 60,
+
+ /// \brief The '_Sat unsigned short _Accum' type
+ PREDEF_TYPE_SAT_USHORT_ACCUM_ID = 61,
+
+ /// \brief The '_Sat unsigned _Accum' type
+ PREDEF_TYPE_SAT_UACCUM_ID = 62,
+
+ /// \brief The '_Sat unsigned long _Accum' type
+ PREDEF_TYPE_SAT_ULONG_ACCUM_ID = 63,
+
+ /// \brief The '_Sat short _Fract' type
+ PREDEF_TYPE_SAT_SHORT_FRACT_ID = 64,
+
+ /// \brief The '_Sat _Fract' type
+ PREDEF_TYPE_SAT_FRACT_ID = 65,
+
+ /// \brief The '_Sat long _Fract' type
+ PREDEF_TYPE_SAT_LONG_FRACT_ID = 66,
+
+ /// \brief The '_Sat unsigned short _Fract' type
+ PREDEF_TYPE_SAT_USHORT_FRACT_ID = 67,
+
+ /// \brief The '_Sat unsigned _Fract' type
+ PREDEF_TYPE_SAT_UFRACT_ID = 68,
+
+ /// \brief The '_Sat unsigned long _Fract' type
+ PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69,
+
+ /// OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
#include "clang/Basic/OpenCLImageTypes.def"
};
- /// \brief The number of predefined type IDs that are reserved for
+ /// The number of predefined type IDs that are reserved for
/// the PREDEF_TYPE_* constants.
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
- const unsigned NUM_PREDEF_TYPE_IDS = 100;
+ const unsigned NUM_PREDEF_TYPE_IDS = 200;
- /// \brief Record codes for each kind of type.
+ /// Record codes for each kind of type.
///
/// These constants describe the type records that can occur within a
/// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
/// constant describes a record for a specific type class in the
/// AST. Note that DeclCode values share this code space.
enum TypeCode {
- /// \brief An ExtQualType record.
- TYPE_EXT_QUAL = 1,
+ /// An ExtQualType record.
+ TYPE_EXT_QUAL = 1,
- /// \brief A ComplexType record.
- TYPE_COMPLEX = 3,
+ /// A ComplexType record.
+ TYPE_COMPLEX = 3,
- /// \brief A PointerType record.
- TYPE_POINTER = 4,
+ /// A PointerType record.
+ TYPE_POINTER = 4,
- /// \brief A BlockPointerType record.
- TYPE_BLOCK_POINTER = 5,
+ /// A BlockPointerType record.
+ TYPE_BLOCK_POINTER = 5,
- /// \brief An LValueReferenceType record.
- TYPE_LVALUE_REFERENCE = 6,
+ /// An LValueReferenceType record.
+ TYPE_LVALUE_REFERENCE = 6,
- /// \brief An RValueReferenceType record.
- TYPE_RVALUE_REFERENCE = 7,
+ /// An RValueReferenceType record.
+ TYPE_RVALUE_REFERENCE = 7,
- /// \brief A MemberPointerType record.
- TYPE_MEMBER_POINTER = 8,
+ /// A MemberPointerType record.
+ TYPE_MEMBER_POINTER = 8,
- /// \brief A ConstantArrayType record.
- TYPE_CONSTANT_ARRAY = 9,
+ /// A ConstantArrayType record.
+ TYPE_CONSTANT_ARRAY = 9,
- /// \brief An IncompleteArrayType record.
- TYPE_INCOMPLETE_ARRAY = 10,
+ /// An IncompleteArrayType record.
+ TYPE_INCOMPLETE_ARRAY = 10,
- /// \brief A VariableArrayType record.
- TYPE_VARIABLE_ARRAY = 11,
+ /// A VariableArrayType record.
+ TYPE_VARIABLE_ARRAY = 11,
- /// \brief A VectorType record.
- TYPE_VECTOR = 12,
+ /// A VectorType record.
+ TYPE_VECTOR = 12,
- /// \brief An ExtVectorType record.
- TYPE_EXT_VECTOR = 13,
+ /// An ExtVectorType record.
+ TYPE_EXT_VECTOR = 13,
- /// \brief A FunctionNoProtoType record.
- TYPE_FUNCTION_NO_PROTO = 14,
+ /// A FunctionNoProtoType record.
+ TYPE_FUNCTION_NO_PROTO = 14,
- /// \brief A FunctionProtoType record.
- TYPE_FUNCTION_PROTO = 15,
+ /// A FunctionProtoType record.
+ TYPE_FUNCTION_PROTO = 15,
- /// \brief A TypedefType record.
- TYPE_TYPEDEF = 16,
+ /// A TypedefType record.
+ TYPE_TYPEDEF = 16,
- /// \brief A TypeOfExprType record.
- TYPE_TYPEOF_EXPR = 17,
+ /// A TypeOfExprType record.
+ TYPE_TYPEOF_EXPR = 17,
- /// \brief A TypeOfType record.
- TYPE_TYPEOF = 18,
+ /// A TypeOfType record.
+ TYPE_TYPEOF = 18,
- /// \brief A RecordType record.
- TYPE_RECORD = 19,
+ /// A RecordType record.
+ TYPE_RECORD = 19,
- /// \brief An EnumType record.
- TYPE_ENUM = 20,
+ /// An EnumType record.
+ TYPE_ENUM = 20,
- /// \brief An ObjCInterfaceType record.
- TYPE_OBJC_INTERFACE = 21,
+ /// An ObjCInterfaceType record.
+ TYPE_OBJC_INTERFACE = 21,
- /// \brief An ObjCObjectPointerType record.
- TYPE_OBJC_OBJECT_POINTER = 22,
+ /// An ObjCObjectPointerType record.
+ TYPE_OBJC_OBJECT_POINTER = 22,
- /// \brief a DecltypeType record.
- TYPE_DECLTYPE = 23,
+ /// a DecltypeType record.
+ TYPE_DECLTYPE = 23,
- /// \brief An ElaboratedType record.
- TYPE_ELABORATED = 24,
+ /// An ElaboratedType record.
+ TYPE_ELABORATED = 24,
- /// \brief A SubstTemplateTypeParmType record.
+ /// A SubstTemplateTypeParmType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
- /// \brief An UnresolvedUsingType record.
- TYPE_UNRESOLVED_USING = 26,
+ /// An UnresolvedUsingType record.
+ TYPE_UNRESOLVED_USING = 26,
- /// \brief An InjectedClassNameType record.
- TYPE_INJECTED_CLASS_NAME = 27,
+ /// An InjectedClassNameType record.
+ TYPE_INJECTED_CLASS_NAME = 27,
- /// \brief An ObjCObjectType record.
- TYPE_OBJC_OBJECT = 28,
+ /// An ObjCObjectType record.
+ TYPE_OBJC_OBJECT = 28,
- /// \brief An TemplateTypeParmType record.
- TYPE_TEMPLATE_TYPE_PARM = 29,
+ /// An TemplateTypeParmType record.
+ TYPE_TEMPLATE_TYPE_PARM = 29,
- /// \brief An TemplateSpecializationType record.
- TYPE_TEMPLATE_SPECIALIZATION = 30,
+ /// An TemplateSpecializationType record.
+ TYPE_TEMPLATE_SPECIALIZATION = 30,
- /// \brief A DependentNameType record.
- TYPE_DEPENDENT_NAME = 31,
+ /// A DependentNameType record.
+ TYPE_DEPENDENT_NAME = 31,
- /// \brief A DependentTemplateSpecializationType record.
+ /// A DependentTemplateSpecializationType record.
TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
- /// \brief A DependentSizedArrayType record.
- TYPE_DEPENDENT_SIZED_ARRAY = 33,
+ /// A DependentSizedArrayType record.
+ TYPE_DEPENDENT_SIZED_ARRAY = 33,
- /// \brief A ParenType record.
- TYPE_PAREN = 34,
+ /// A ParenType record.
+ TYPE_PAREN = 34,
- /// \brief A PackExpansionType record.
- TYPE_PACK_EXPANSION = 35,
+ /// A PackExpansionType record.
+ TYPE_PACK_EXPANSION = 35,
- /// \brief An AttributedType record.
- TYPE_ATTRIBUTED = 36,
+ /// An AttributedType record.
+ TYPE_ATTRIBUTED = 36,
- /// \brief A SubstTemplateTypeParmPackType record.
+ /// A SubstTemplateTypeParmPackType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
- /// \brief A AutoType record.
- TYPE_AUTO = 38,
+ /// A AutoType record.
+ TYPE_AUTO = 38,
- /// \brief A UnaryTransformType record.
- TYPE_UNARY_TRANSFORM = 39,
+ /// A UnaryTransformType record.
+ TYPE_UNARY_TRANSFORM = 39,
- /// \brief An AtomicType record.
- TYPE_ATOMIC = 40,
+ /// An AtomicType record.
+ TYPE_ATOMIC = 40,
- /// \brief A DecayedType record.
- TYPE_DECAYED = 41,
+ /// A DecayedType record.
+ TYPE_DECAYED = 41,
- /// \brief An AdjustedType record.
- TYPE_ADJUSTED = 42,
+ /// An AdjustedType record.
+ TYPE_ADJUSTED = 42,
- /// \brief A PipeType record.
- TYPE_PIPE = 43,
+ /// A PipeType record.
+ TYPE_PIPE = 43,
- /// \brief An ObjCTypeParamType record.
- TYPE_OBJC_TYPE_PARAM = 44,
+ /// An ObjCTypeParamType record.
+ TYPE_OBJC_TYPE_PARAM = 44,
- /// \brief A DeducedTemplateSpecializationType record.
+ /// A DeducedTemplateSpecializationType record.
TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45,
- /// \brief A DependentSizedExtVectorType record.
+ /// A DependentSizedExtVectorType record.
TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46,
- /// \brief A DependentAddressSpaceType record.
- TYPE_DEPENDENT_ADDRESS_SPACE = 47
+ /// A DependentAddressSpaceType record.
+ TYPE_DEPENDENT_ADDRESS_SPACE = 47,
+
+ /// A dependentSizedVectorType record.
+ TYPE_DEPENDENT_SIZED_VECTOR = 48
};
- /// \brief The type IDs for special types constructed by semantic
+ /// The type IDs for special types constructed by semantic
/// analysis.
///
/// The constants in this enumeration are indices into the
/// SPECIAL_TYPES record.
enum SpecialTypeIDs {
- /// \brief CFConstantString type
+ /// CFConstantString type
SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
- /// \brief C FILE typedef type
+ /// C FILE typedef type
SPECIAL_TYPE_FILE = 1,
- /// \brief C jmp_buf typedef type
+ /// C jmp_buf typedef type
SPECIAL_TYPE_JMP_BUF = 2,
- /// \brief C sigjmp_buf typedef type
+ /// C sigjmp_buf typedef type
SPECIAL_TYPE_SIGJMP_BUF = 3,
- /// \brief Objective-C "id" redefinition type
+ /// Objective-C "id" redefinition type
SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
- /// \brief Objective-C "Class" redefinition type
+ /// Objective-C "Class" redefinition type
SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
- /// \brief Objective-C "SEL" redefinition type
+ /// Objective-C "SEL" redefinition type
SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
- /// \brief C ucontext_t typedef type
+ /// C ucontext_t typedef type
SPECIAL_TYPE_UCONTEXT_T = 7
};
-
- /// \brief The number of special type IDs.
+
+ /// The number of special type IDs.
const unsigned NumSpecialTypeIDs = 8;
- /// \brief Predefined declaration IDs.
+ /// Predefined declaration IDs.
///
/// These declaration IDs correspond to predefined declarations in the AST
/// context, such as the NULL declaration ID. Such declarations are never
- /// actually serialized, since they will be built by the AST context when
+ /// actually serialized, since they will be built by the AST context when
/// it is created.
enum PredefinedDeclIDs {
- /// \brief The NULL declaration.
+ /// The NULL declaration.
PREDEF_DECL_NULL_ID = 0,
- /// \brief The translation unit.
+ /// The translation unit.
PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
- /// \brief The Objective-C 'id' type.
+ /// The Objective-C 'id' type.
PREDEF_DECL_OBJC_ID_ID = 2,
- /// \brief The Objective-C 'SEL' type.
+ /// The Objective-C 'SEL' type.
PREDEF_DECL_OBJC_SEL_ID = 3,
- /// \brief The Objective-C 'Class' type.
+ /// The Objective-C 'Class' type.
PREDEF_DECL_OBJC_CLASS_ID = 4,
- /// \brief The Objective-C 'Protocol' type.
+ /// The Objective-C 'Protocol' type.
PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
- /// \brief The signed 128-bit integer type.
+ /// The signed 128-bit integer type.
PREDEF_DECL_INT_128_ID = 6,
- /// \brief The unsigned 128-bit integer type.
+ /// The unsigned 128-bit integer type.
PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
- /// \brief The internal 'instancetype' typedef.
+ /// The internal 'instancetype' typedef.
PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
- /// \brief The internal '__builtin_va_list' typedef.
+ /// The internal '__builtin_va_list' typedef.
PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
- /// \brief The internal '__va_list_tag' struct, if any.
+ /// The internal '__va_list_tag' struct, if any.
PREDEF_DECL_VA_LIST_TAG = 10,
- /// \brief The internal '__builtin_ms_va_list' typedef.
+ /// The internal '__builtin_ms_va_list' typedef.
PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
- /// \brief The extern "C" context.
+ /// The extern "C" context.
PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12,
- /// \brief The internal '__make_integer_seq' template.
+ /// The internal '__make_integer_seq' template.
PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13,
- /// \brief The internal '__NSConstantString' typedef.
+ /// The internal '__NSConstantString' typedef.
PREDEF_DECL_CF_CONSTANT_STRING_ID = 14,
- /// \brief The internal '__NSConstantString' tag type.
+ /// The internal '__NSConstantString' tag type.
PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 15,
- /// \brief The internal '__type_pack_element' template.
+ /// The internal '__type_pack_element' template.
PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 16,
};
- /// \brief The number of declaration IDs that are predefined.
+ /// The number of declaration IDs that are predefined.
///
/// For more information about predefined declarations, see the
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
const unsigned int NUM_PREDEF_DECL_IDS = 17;
- /// \brief Record of updates for a declaration that was modified after
+ /// Record of updates for a declaration that was modified after
/// being deserialized. This can occur within DECLTYPES_BLOCK_ID.
const unsigned int DECL_UPDATES = 49;
- /// \brief Record code for a list of local redeclarations of a declaration.
+ /// Record code for a list of local redeclarations of a declaration.
/// This can occur within DECLTYPES_BLOCK_ID.
const unsigned int LOCAL_REDECLARATIONS = 50;
-
- /// \brief Record codes for each kind of declaration.
+
+ /// Record codes for each kind of declaration.
///
/// These constants describe the declaration records that can occur within
/// a declarations block (identified by DECLTYPES_BLOCK_ID). Each
/// constant describes a record for a specific declaration class
/// in the AST. Note that TypeCode values share this code space.
enum DeclCode {
- /// \brief A TypedefDecl record.
+ /// A TypedefDecl record.
DECL_TYPEDEF = 51,
- /// \brief A TypeAliasDecl record.
+ /// A TypeAliasDecl record.
DECL_TYPEALIAS,
- /// \brief An EnumDecl record.
+ /// An EnumDecl record.
DECL_ENUM,
- /// \brief A RecordDecl record.
+ /// A RecordDecl record.
DECL_RECORD,
- /// \brief An EnumConstantDecl record.
+ /// An EnumConstantDecl record.
DECL_ENUM_CONSTANT,
- /// \brief A FunctionDecl record.
+ /// A FunctionDecl record.
DECL_FUNCTION,
- /// \brief A ObjCMethodDecl record.
+ /// A ObjCMethodDecl record.
DECL_OBJC_METHOD,
- /// \brief A ObjCInterfaceDecl record.
+ /// A ObjCInterfaceDecl record.
DECL_OBJC_INTERFACE,
- /// \brief A ObjCProtocolDecl record.
+ /// A ObjCProtocolDecl record.
DECL_OBJC_PROTOCOL,
- /// \brief A ObjCIvarDecl record.
+ /// A ObjCIvarDecl record.
DECL_OBJC_IVAR,
- /// \brief A ObjCAtDefsFieldDecl record.
+ /// A ObjCAtDefsFieldDecl record.
DECL_OBJC_AT_DEFS_FIELD,
- /// \brief A ObjCCategoryDecl record.
+ /// A ObjCCategoryDecl record.
DECL_OBJC_CATEGORY,
- /// \brief A ObjCCategoryImplDecl record.
+ /// A ObjCCategoryImplDecl record.
DECL_OBJC_CATEGORY_IMPL,
- /// \brief A ObjCImplementationDecl record.
+ /// A ObjCImplementationDecl record.
DECL_OBJC_IMPLEMENTATION,
- /// \brief A ObjCCompatibleAliasDecl record.
+ /// A ObjCCompatibleAliasDecl record.
DECL_OBJC_COMPATIBLE_ALIAS,
- /// \brief A ObjCPropertyDecl record.
+ /// A ObjCPropertyDecl record.
DECL_OBJC_PROPERTY,
- /// \brief A ObjCPropertyImplDecl record.
+ /// A ObjCPropertyImplDecl record.
DECL_OBJC_PROPERTY_IMPL,
- /// \brief A FieldDecl record.
+ /// A FieldDecl record.
DECL_FIELD,
- /// \brief A MSPropertyDecl record.
+ /// A MSPropertyDecl record.
DECL_MS_PROPERTY,
- /// \brief A VarDecl record.
+ /// A VarDecl record.
DECL_VAR,
- /// \brief An ImplicitParamDecl record.
+ /// An ImplicitParamDecl record.
DECL_IMPLICIT_PARAM,
- /// \brief A ParmVarDecl record.
+ /// A ParmVarDecl record.
DECL_PARM_VAR,
- /// \brief A DecompositionDecl record.
+ /// A DecompositionDecl record.
DECL_DECOMPOSITION,
- /// \brief A BindingDecl record.
+ /// A BindingDecl record.
DECL_BINDING,
- /// \brief A FileScopeAsmDecl record.
+ /// A FileScopeAsmDecl record.
DECL_FILE_SCOPE_ASM,
- /// \brief A BlockDecl record.
+ /// A BlockDecl record.
DECL_BLOCK,
- /// \brief A CapturedDecl record.
+ /// A CapturedDecl record.
DECL_CAPTURED,
- /// \brief A record that stores the set of declarations that are
+ /// A record that stores the set of declarations that are
/// lexically stored within a given DeclContext.
///
/// The record itself is a blob that is an array of declaration IDs,
@@ -1278,7 +1378,7 @@ namespace serialization {
/// DeclContext::decls_begin() and DeclContext::decls_end().
DECL_CONTEXT_LEXICAL,
- /// \brief A record that stores the set of declarations that are
+ /// A record that stores the set of declarations that are
/// visible from a given DeclContext.
///
/// The record itself stores a set of mappings, each of which
@@ -1287,466 +1387,466 @@ namespace serialization {
/// into a DeclContext via DeclContext::lookup.
DECL_CONTEXT_VISIBLE,
- /// \brief A LabelDecl record.
+ /// A LabelDecl record.
DECL_LABEL,
- /// \brief A NamespaceDecl record.
+ /// A NamespaceDecl record.
DECL_NAMESPACE,
- /// \brief A NamespaceAliasDecl record.
+ /// A NamespaceAliasDecl record.
DECL_NAMESPACE_ALIAS,
- /// \brief A UsingDecl record.
+ /// A UsingDecl record.
DECL_USING,
- /// \brief A UsingPackDecl record.
+ /// A UsingPackDecl record.
DECL_USING_PACK,
- /// \brief A UsingShadowDecl record.
+ /// A UsingShadowDecl record.
DECL_USING_SHADOW,
- /// \brief A ConstructorUsingShadowDecl record.
+ /// A ConstructorUsingShadowDecl record.
DECL_CONSTRUCTOR_USING_SHADOW,
- /// \brief A UsingDirecitveDecl record.
+ /// A UsingDirecitveDecl record.
DECL_USING_DIRECTIVE,
- /// \brief An UnresolvedUsingValueDecl record.
+ /// An UnresolvedUsingValueDecl record.
DECL_UNRESOLVED_USING_VALUE,
- /// \brief An UnresolvedUsingTypenameDecl record.
+ /// An UnresolvedUsingTypenameDecl record.
DECL_UNRESOLVED_USING_TYPENAME,
- /// \brief A LinkageSpecDecl record.
+ /// A LinkageSpecDecl record.
DECL_LINKAGE_SPEC,
- /// \brief An ExportDecl record.
+ /// An ExportDecl record.
DECL_EXPORT,
- /// \brief A CXXRecordDecl record.
+ /// A CXXRecordDecl record.
DECL_CXX_RECORD,
- /// \brief A CXXDeductionGuideDecl record.
+ /// A CXXDeductionGuideDecl record.
DECL_CXX_DEDUCTION_GUIDE,
- /// \brief A CXXMethodDecl record.
+ /// A CXXMethodDecl record.
DECL_CXX_METHOD,
- /// \brief A CXXConstructorDecl record.
+ /// A CXXConstructorDecl record.
DECL_CXX_CONSTRUCTOR,
- /// \brief A CXXConstructorDecl record for an inherited constructor.
+ /// A CXXConstructorDecl record for an inherited constructor.
DECL_CXX_INHERITED_CONSTRUCTOR,
- /// \brief A CXXDestructorDecl record.
+ /// A CXXDestructorDecl record.
DECL_CXX_DESTRUCTOR,
- /// \brief A CXXConversionDecl record.
+ /// A CXXConversionDecl record.
DECL_CXX_CONVERSION,
- /// \brief An AccessSpecDecl record.
+ /// An AccessSpecDecl record.
DECL_ACCESS_SPEC,
- /// \brief A FriendDecl record.
+ /// A FriendDecl record.
DECL_FRIEND,
- /// \brief A FriendTemplateDecl record.
+ /// A FriendTemplateDecl record.
DECL_FRIEND_TEMPLATE,
- /// \brief A ClassTemplateDecl record.
+ /// A ClassTemplateDecl record.
DECL_CLASS_TEMPLATE,
- /// \brief A ClassTemplateSpecializationDecl record.
+ /// A ClassTemplateSpecializationDecl record.
DECL_CLASS_TEMPLATE_SPECIALIZATION,
- /// \brief A ClassTemplatePartialSpecializationDecl record.
+ /// A ClassTemplatePartialSpecializationDecl record.
DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
- /// \brief A VarTemplateDecl record.
+ /// A VarTemplateDecl record.
DECL_VAR_TEMPLATE,
- /// \brief A VarTemplateSpecializationDecl record.
+ /// A VarTemplateSpecializationDecl record.
DECL_VAR_TEMPLATE_SPECIALIZATION,
- /// \brief A VarTemplatePartialSpecializationDecl record.
+ /// A VarTemplatePartialSpecializationDecl record.
DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION,
- /// \brief A FunctionTemplateDecl record.
+ /// A FunctionTemplateDecl record.
DECL_FUNCTION_TEMPLATE,
- /// \brief A TemplateTypeParmDecl record.
+ /// A TemplateTypeParmDecl record.
DECL_TEMPLATE_TYPE_PARM,
- /// \brief A NonTypeTemplateParmDecl record.
+ /// A NonTypeTemplateParmDecl record.
DECL_NON_TYPE_TEMPLATE_PARM,
- /// \brief A TemplateTemplateParmDecl record.
+ /// A TemplateTemplateParmDecl record.
DECL_TEMPLATE_TEMPLATE_PARM,
- /// \brief A TypeAliasTemplateDecl record.
+ /// A TypeAliasTemplateDecl record.
DECL_TYPE_ALIAS_TEMPLATE,
- /// \brief A StaticAssertDecl record.
+ /// A StaticAssertDecl record.
DECL_STATIC_ASSERT,
- /// \brief A record containing CXXBaseSpecifiers.
+ /// A record containing CXXBaseSpecifiers.
DECL_CXX_BASE_SPECIFIERS,
- /// \brief A record containing CXXCtorInitializers.
+ /// A record containing CXXCtorInitializers.
DECL_CXX_CTOR_INITIALIZERS,
- /// \brief A IndirectFieldDecl record.
+ /// A IndirectFieldDecl record.
DECL_INDIRECTFIELD,
- /// \brief A NonTypeTemplateParmDecl record that stores an expanded
+ /// 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
+ /// A TemplateTemplateParmDecl record that stores an expanded
/// template template parameter pack.
DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
- /// \brief A ClassScopeFunctionSpecializationDecl record a class scope
+ /// A ClassScopeFunctionSpecializationDecl record a class scope
/// function specialization. (Microsoft extension).
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
- /// \brief An ImportDecl recording a module import.
+ /// An ImportDecl recording a module import.
DECL_IMPORT,
- /// \brief An OMPThreadPrivateDecl record.
+ /// An OMPThreadPrivateDecl record.
DECL_OMP_THREADPRIVATE,
- /// \brief An EmptyDecl record.
+ /// An EmptyDecl record.
DECL_EMPTY,
- /// \brief An ObjCTypeParamDecl record.
+ /// An ObjCTypeParamDecl record.
DECL_OBJC_TYPE_PARAM,
- /// \brief An OMPCapturedExprDecl record.
+ /// An OMPCapturedExprDecl record.
DECL_OMP_CAPTUREDEXPR,
- /// \brief A PragmaCommentDecl record.
+ /// A PragmaCommentDecl record.
DECL_PRAGMA_COMMENT,
- /// \brief A PragmaDetectMismatchDecl record.
+ /// A PragmaDetectMismatchDecl record.
DECL_PRAGMA_DETECT_MISMATCH,
- /// \brief An OMPDeclareReductionDecl record.
+ /// An OMPDeclareReductionDecl record.
DECL_OMP_DECLARE_REDUCTION,
};
- /// \brief Record codes for each kind of statement or expression.
+ /// Record codes for each kind of statement or expression.
///
/// These constants describe the records that describe statements
/// or expressions. These records occur within type and declarations
- /// block, so they begin with record values of 128. Each constant
+ /// block, so they begin with record values of 128. Each constant
/// describes a record for a specific statement or expression class in the
/// AST.
enum StmtCode {
- /// \brief A marker record that indicates that we are at the end
+ /// A marker record that indicates that we are at the end
/// of an expression.
STMT_STOP = 128,
- /// \brief A NULL expression.
+ /// A NULL expression.
STMT_NULL_PTR,
- /// \brief A reference to a previously [de]serialized Stmt record.
+ /// A reference to a previously [de]serialized Stmt record.
STMT_REF_PTR,
- /// \brief A NullStmt record.
+ /// A NullStmt record.
STMT_NULL,
- /// \brief A CompoundStmt record.
+ /// A CompoundStmt record.
STMT_COMPOUND,
- /// \brief A CaseStmt record.
+ /// A CaseStmt record.
STMT_CASE,
- /// \brief A DefaultStmt record.
+ /// A DefaultStmt record.
STMT_DEFAULT,
- /// \brief A LabelStmt record.
+ /// A LabelStmt record.
STMT_LABEL,
- /// \brief An AttributedStmt record.
+ /// An AttributedStmt record.
STMT_ATTRIBUTED,
- /// \brief An IfStmt record.
+ /// An IfStmt record.
STMT_IF,
- /// \brief A SwitchStmt record.
+ /// A SwitchStmt record.
STMT_SWITCH,
- /// \brief A WhileStmt record.
+ /// A WhileStmt record.
STMT_WHILE,
- /// \brief A DoStmt record.
+ /// A DoStmt record.
STMT_DO,
- /// \brief A ForStmt record.
+ /// A ForStmt record.
STMT_FOR,
- /// \brief A GotoStmt record.
+ /// A GotoStmt record.
STMT_GOTO,
- /// \brief An IndirectGotoStmt record.
+ /// An IndirectGotoStmt record.
STMT_INDIRECT_GOTO,
- /// \brief A ContinueStmt record.
+ /// A ContinueStmt record.
STMT_CONTINUE,
- /// \brief A BreakStmt record.
+ /// A BreakStmt record.
STMT_BREAK,
- /// \brief A ReturnStmt record.
+ /// A ReturnStmt record.
STMT_RETURN,
- /// \brief A DeclStmt record.
+ /// A DeclStmt record.
STMT_DECL,
- /// \brief A CapturedStmt record.
+ /// A CapturedStmt record.
STMT_CAPTURED,
- /// \brief A GCC-style AsmStmt record.
+ /// A GCC-style AsmStmt record.
STMT_GCCASM,
- /// \brief A MS-style AsmStmt record.
+ /// A MS-style AsmStmt record.
STMT_MSASM,
- /// \brief A PredefinedExpr record.
+ /// A PredefinedExpr record.
EXPR_PREDEFINED,
- /// \brief A DeclRefExpr record.
+ /// A DeclRefExpr record.
EXPR_DECL_REF,
- /// \brief An IntegerLiteral record.
+ /// An IntegerLiteral record.
EXPR_INTEGER_LITERAL,
- /// \brief A FloatingLiteral record.
+ /// A FloatingLiteral record.
EXPR_FLOATING_LITERAL,
- /// \brief An ImaginaryLiteral record.
+ /// An ImaginaryLiteral record.
EXPR_IMAGINARY_LITERAL,
- /// \brief A StringLiteral record.
+ /// A StringLiteral record.
EXPR_STRING_LITERAL,
- /// \brief A CharacterLiteral record.
+ /// A CharacterLiteral record.
EXPR_CHARACTER_LITERAL,
- /// \brief A ParenExpr record.
+ /// A ParenExpr record.
EXPR_PAREN,
- /// \brief A ParenListExpr record.
+ /// A ParenListExpr record.
EXPR_PAREN_LIST,
- /// \brief A UnaryOperator record.
+ /// A UnaryOperator record.
EXPR_UNARY_OPERATOR,
- /// \brief An OffsetOfExpr record.
+ /// An OffsetOfExpr record.
EXPR_OFFSETOF,
- /// \brief A SizefAlignOfExpr record.
+ /// A SizefAlignOfExpr record.
EXPR_SIZEOF_ALIGN_OF,
- /// \brief An ArraySubscriptExpr record.
+ /// An ArraySubscriptExpr record.
EXPR_ARRAY_SUBSCRIPT,
- /// \brief A CallExpr record.
+ /// A CallExpr record.
EXPR_CALL,
- /// \brief A MemberExpr record.
+ /// A MemberExpr record.
EXPR_MEMBER,
- /// \brief A BinaryOperator record.
+ /// A BinaryOperator record.
EXPR_BINARY_OPERATOR,
- /// \brief A CompoundAssignOperator record.
+ /// A CompoundAssignOperator record.
EXPR_COMPOUND_ASSIGN_OPERATOR,
- /// \brief A ConditionOperator record.
+ /// A ConditionOperator record.
EXPR_CONDITIONAL_OPERATOR,
- /// \brief An ImplicitCastExpr record.
+ /// An ImplicitCastExpr record.
EXPR_IMPLICIT_CAST,
- /// \brief A CStyleCastExpr record.
+ /// A CStyleCastExpr record.
EXPR_CSTYLE_CAST,
- /// \brief A CompoundLiteralExpr record.
+ /// A CompoundLiteralExpr record.
EXPR_COMPOUND_LITERAL,
- /// \brief An ExtVectorElementExpr record.
+ /// An ExtVectorElementExpr record.
EXPR_EXT_VECTOR_ELEMENT,
- /// \brief An InitListExpr record.
+ /// An InitListExpr record.
EXPR_INIT_LIST,
- /// \brief A DesignatedInitExpr record.
+ /// A DesignatedInitExpr record.
EXPR_DESIGNATED_INIT,
- /// \brief A DesignatedInitUpdateExpr record.
+ /// A DesignatedInitUpdateExpr record.
EXPR_DESIGNATED_INIT_UPDATE,
- /// \brief An NoInitExpr record.
+ /// An NoInitExpr record.
EXPR_NO_INIT,
- /// \brief An ArrayInitLoopExpr record.
+ /// An ArrayInitLoopExpr record.
EXPR_ARRAY_INIT_LOOP,
- /// \brief An ArrayInitIndexExpr record.
+ /// An ArrayInitIndexExpr record.
EXPR_ARRAY_INIT_INDEX,
- /// \brief An ImplicitValueInitExpr record.
+ /// An ImplicitValueInitExpr record.
EXPR_IMPLICIT_VALUE_INIT,
- /// \brief A VAArgExpr record.
+ /// A VAArgExpr record.
EXPR_VA_ARG,
- /// \brief An AddrLabelExpr record.
+ /// An AddrLabelExpr record.
EXPR_ADDR_LABEL,
- /// \brief A StmtExpr record.
+ /// A StmtExpr record.
EXPR_STMT,
- /// \brief A ChooseExpr record.
+ /// A ChooseExpr record.
EXPR_CHOOSE,
- /// \brief A GNUNullExpr record.
+ /// A GNUNullExpr record.
EXPR_GNU_NULL,
- /// \brief A ShuffleVectorExpr record.
+ /// A ShuffleVectorExpr record.
EXPR_SHUFFLE_VECTOR,
- /// \brief A ConvertVectorExpr record.
+ /// A ConvertVectorExpr record.
EXPR_CONVERT_VECTOR,
- /// \brief BlockExpr
+ /// BlockExpr
EXPR_BLOCK,
- /// \brief A GenericSelectionExpr record.
+ /// A GenericSelectionExpr record.
EXPR_GENERIC_SELECTION,
- /// \brief A PseudoObjectExpr record.
+ /// A PseudoObjectExpr record.
EXPR_PSEUDO_OBJECT,
- /// \brief An AtomicExpr record.
+ /// An AtomicExpr record.
EXPR_ATOMIC,
// Objective-C
- /// \brief An ObjCStringLiteral record.
+ /// An ObjCStringLiteral record.
EXPR_OBJC_STRING_LITERAL,
EXPR_OBJC_BOXED_EXPRESSION,
EXPR_OBJC_ARRAY_LITERAL,
EXPR_OBJC_DICTIONARY_LITERAL,
-
- /// \brief An ObjCEncodeExpr record.
+
+ /// An ObjCEncodeExpr record.
EXPR_OBJC_ENCODE,
- /// \brief An ObjCSelectorExpr record.
+ /// An ObjCSelectorExpr record.
EXPR_OBJC_SELECTOR_EXPR,
- /// \brief An ObjCProtocolExpr record.
+ /// An ObjCProtocolExpr record.
EXPR_OBJC_PROTOCOL_EXPR,
- /// \brief An ObjCIvarRefExpr record.
+ /// An ObjCIvarRefExpr record.
EXPR_OBJC_IVAR_REF_EXPR,
- /// \brief An ObjCPropertyRefExpr record.
+ /// An ObjCPropertyRefExpr record.
EXPR_OBJC_PROPERTY_REF_EXPR,
- /// \brief An ObjCSubscriptRefExpr record.
+ /// An ObjCSubscriptRefExpr record.
EXPR_OBJC_SUBSCRIPT_REF_EXPR,
- /// \brief UNUSED
+ /// UNUSED
EXPR_OBJC_KVC_REF_EXPR,
- /// \brief An ObjCMessageExpr record.
+ /// An ObjCMessageExpr record.
EXPR_OBJC_MESSAGE_EXPR,
- /// \brief An ObjCIsa Expr record.
+ /// An ObjCIsa Expr record.
EXPR_OBJC_ISA,
- /// \brief An ObjCIndirectCopyRestoreExpr record.
+ /// An ObjCIndirectCopyRestoreExpr record.
EXPR_OBJC_INDIRECT_COPY_RESTORE,
- /// \brief An ObjCForCollectionStmt record.
+ /// An ObjCForCollectionStmt record.
STMT_OBJC_FOR_COLLECTION,
- /// \brief An ObjCAtCatchStmt record.
+ /// An ObjCAtCatchStmt record.
STMT_OBJC_CATCH,
- /// \brief An ObjCAtFinallyStmt record.
+ /// An ObjCAtFinallyStmt record.
STMT_OBJC_FINALLY,
- /// \brief An ObjCAtTryStmt record.
+ /// An ObjCAtTryStmt record.
STMT_OBJC_AT_TRY,
- /// \brief An ObjCAtSynchronizedStmt record.
+ /// An ObjCAtSynchronizedStmt record.
STMT_OBJC_AT_SYNCHRONIZED,
- /// \brief An ObjCAtThrowStmt record.
+ /// An ObjCAtThrowStmt record.
STMT_OBJC_AT_THROW,
- /// \brief An ObjCAutoreleasePoolStmt record.
+ /// An ObjCAutoreleasePoolStmt record.
STMT_OBJC_AUTORELEASE_POOL,
- /// \brief An ObjCBoolLiteralExpr record.
+ /// An ObjCBoolLiteralExpr record.
EXPR_OBJC_BOOL_LITERAL,
- /// \brief An ObjCAvailabilityCheckExpr record.
+ /// An ObjCAvailabilityCheckExpr record.
EXPR_OBJC_AVAILABILITY_CHECK,
// C++
-
- /// \brief A CXXCatchStmt record.
+
+ /// A CXXCatchStmt record.
STMT_CXX_CATCH,
- /// \brief A CXXTryStmt record.
+ /// A CXXTryStmt record.
STMT_CXX_TRY,
- /// \brief A CXXForRangeStmt record.
+ /// A CXXForRangeStmt record.
STMT_CXX_FOR_RANGE,
- /// \brief A CXXOperatorCallExpr record.
+ /// A CXXOperatorCallExpr record.
EXPR_CXX_OPERATOR_CALL,
- /// \brief A CXXMemberCallExpr record.
+ /// A CXXMemberCallExpr record.
EXPR_CXX_MEMBER_CALL,
- /// \brief A CXXConstructExpr record.
+ /// A CXXConstructExpr record.
EXPR_CXX_CONSTRUCT,
- /// \brief A CXXInheritedCtorInitExpr record.
+ /// A CXXInheritedCtorInitExpr record.
EXPR_CXX_INHERITED_CTOR_INIT,
- /// \brief A CXXTemporaryObjectExpr record.
+ /// A CXXTemporaryObjectExpr record.
EXPR_CXX_TEMPORARY_OBJECT,
- /// \brief A CXXStaticCastExpr record.
+ /// A CXXStaticCastExpr record.
EXPR_CXX_STATIC_CAST,
- /// \brief A CXXDynamicCastExpr record.
+ /// A CXXDynamicCastExpr record.
EXPR_CXX_DYNAMIC_CAST,
- /// \brief A CXXReinterpretCastExpr record.
+ /// A CXXReinterpretCastExpr record.
EXPR_CXX_REINTERPRET_CAST,
- /// \brief A CXXConstCastExpr record.
+ /// A CXXConstCastExpr record.
EXPR_CXX_CONST_CAST,
- /// \brief A CXXFunctionalCastExpr record.
+ /// A CXXFunctionalCastExpr record.
EXPR_CXX_FUNCTIONAL_CAST,
- /// \brief A UserDefinedLiteral record.
+ /// A UserDefinedLiteral record.
EXPR_USER_DEFINED_LITERAL,
- /// \brief A CXXStdInitializerListExpr record.
+ /// A CXXStdInitializerListExpr record.
EXPR_CXX_STD_INITIALIZER_LIST,
- /// \brief A CXXBoolLiteralExpr record.
+ /// A CXXBoolLiteralExpr record.
EXPR_CXX_BOOL_LITERAL,
EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
@@ -1762,9 +1862,9 @@ namespace serialization {
EXPR_CXX_NEW, // CXXNewExpr
EXPR_CXX_DELETE, // CXXDeleteExpr
EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
-
+
EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
-
+
EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr
@@ -1778,7 +1878,7 @@ namespace serialization {
EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
EXPR_TYPE_TRAIT, // TypeTraitExpr
EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
-
+
EXPR_PACK_EXPANSION, // PackExpansionExpr
EXPR_SIZEOF_PACK, // SizeOfPackExpr
EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
@@ -1788,7 +1888,7 @@ namespace serialization {
EXPR_CXX_FOLD, // CXXFoldExpr
// CUDA
- EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
+ EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
// OpenCL
EXPR_ASTYPE, // AsTypeExpr
@@ -1865,24 +1965,24 @@ namespace serialization {
EXPR_DEPENDENT_COAWAIT,
};
- /// \brief The kinds of designators that can occur in a
+ /// The kinds of designators that can occur in a
/// DesignatedInitExpr.
enum DesignatorTypes {
- /// \brief Field designator where only the field name is known.
+ /// Field designator where only the field name is known.
DESIG_FIELD_NAME = 0,
- /// \brief Field designator where the field has been resolved to
+ /// Field designator where the field has been resolved to
/// a declaration.
DESIG_FIELD_DECL = 1,
- /// \brief Array designator.
+ /// Array designator.
DESIG_ARRAY = 2,
- /// \brief GNU array range designator.
+ /// GNU array range designator.
DESIG_ARRAY_RANGE = 3
};
- /// \brief The different kinds of data that can occur in a
+ /// The different kinds of data that can occur in a
/// CtorInitializer.
enum CtorInitializerType {
CTOR_INITIALIZER_BASE,
@@ -1891,65 +1991,65 @@ namespace serialization {
CTOR_INITIALIZER_INDIRECT_MEMBER
};
- /// \brief Describes the redeclarations of a declaration.
+ /// Describes the redeclarations of a declaration.
struct LocalRedeclarationsInfo {
// 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) {
return X.FirstID < Y.FirstID;
}
-
+
friend bool operator>(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID > Y.FirstID;
}
-
+
friend bool operator<=(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID <= Y.FirstID;
}
-
+
friend bool operator>=(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID >= Y.FirstID;
}
};
- /// \brief Describes the categories of an Objective-C class.
+ /// Describes the categories of an Objective-C class.
struct ObjCCategoriesInfo {
// 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) {
return X.DefinitionID < Y.DefinitionID;
}
-
+
friend bool operator>(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID > Y.DefinitionID;
}
-
+
friend bool operator<=(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID <= Y.DefinitionID;
}
-
+
friend bool operator>=(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID >= Y.DefinitionID;
}
};
- /// \brief A key used when looking up entities by \ref DeclarationName.
+ /// A key used when looking up entities by \ref DeclarationName.
///
/// Different \ref DeclarationNames are mapped to different keys, but the
/// same key can occasionally represent multiple names (for names that
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h
index c26f3e0b425e..c462a90dde54 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h
@@ -32,28 +32,28 @@ class ASTDeserializationListener {
public:
virtual ~ASTDeserializationListener();
- /// \brief The ASTReader was initialized.
+ /// The ASTReader was initialized.
virtual void ReaderInitialized(ASTReader *Reader) { }
- /// \brief An identifier was deserialized from the AST file.
+ /// An identifier was deserialized from the AST file.
virtual void IdentifierRead(serialization::IdentID ID,
IdentifierInfo *II) { }
- /// \brief A macro was read from the AST file.
+ /// A macro was read from the AST file.
virtual void MacroRead(serialization::MacroID ID, MacroInfo *MI) { }
- /// \brief A type was deserialized from the AST file. The ID here has the
+ /// A type was deserialized from the AST file. The ID here has the
/// qualifier bits already removed, and T is guaranteed to be locally
/// unqualified.
virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { }
- /// \brief A decl was deserialized from the AST file.
+ /// A decl was deserialized from the AST file.
virtual void DeclRead(serialization::DeclID ID, const Decl *D) { }
- /// \brief A selector was read from the AST file.
+ /// A selector was read from the AST file.
virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) {}
- /// \brief A macro definition was read from the AST file.
+ /// A macro definition was read from the AST file.
virtual void MacroDefinitionRead(serialization::PreprocessedEntityID,
MacroDefinitionRecord *MD) {}
- /// \brief A module definition was read from the AST file.
+ /// A module definition was read from the AST file.
virtual void ModuleRead(serialization::SubmoduleID ID, Module *Mod) {}
- /// \brief A module import was read from the AST file.
+ /// A module import was read from the AST file.
virtual void ModuleImportRead(serialization::SubmoduleID ID,
SourceLocation ImportLoc) {}
};
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
index 37920fc143ea..0eecb6f5d65a 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -14,20 +14,20 @@
#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_H
#define LLVM_CLANG_SERIALIZATION_ASTREADER_H
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.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/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"
@@ -61,6 +61,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Timer.h"
+#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
@@ -79,9 +80,6 @@ class ASTContext;
class ASTDeserializationListener;
class ASTReader;
class ASTRecordReader;
-class CXXBaseSpecifier;
-class CXXConstructorDecl;
-class CXXCtorInitializer;
class CXXTemporary;
class Decl;
class DeclaratorDecl;
@@ -102,7 +100,6 @@ class MacroInfo;
class MemoryBufferCache;
class NamedDecl;
class NamespaceDecl;
-class NestedNameSpecifier;
class ObjCCategoryDecl;
class ObjCInterfaceDecl;
class PCHContainerReader;
@@ -120,7 +117,7 @@ class TypeSourceInfo;
class ValueDecl;
class VarDecl;
-/// \brief Abstract interface for callback invocations by the ASTReader.
+/// Abstract interface for callback invocations by the ASTReader.
///
/// While reading an AST file, the ASTReader will call the methods of the
/// listener to pass on specific information. Some of the listener methods can
@@ -130,7 +127,7 @@ class ASTReaderListener {
public:
virtual ~ASTReaderListener();
- /// \brief Receives the full Clang version information.
+ /// Receives the full Clang version information.
///
/// \returns true to indicate that the version is invalid. Subclasses should
/// generally defer to this implementation.
@@ -141,7 +138,7 @@ public:
virtual void ReadModuleName(StringRef ModuleName) {}
virtual void ReadModuleMapFile(StringRef ModuleMapPath) {}
- /// \brief Receives the language options.
+ /// Receives the language options.
///
/// \returns true to indicate the options are invalid or false otherwise.
virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
@@ -150,7 +147,7 @@ public:
return false;
}
- /// \brief Receives the target options.
+ /// Receives the target options.
///
/// \returns true to indicate the target options are invalid, or false
/// otherwise.
@@ -159,7 +156,7 @@ public:
return false;
}
- /// \brief Receives the diagnostic options.
+ /// Receives the diagnostic options.
///
/// \returns true to indicate the diagnostic options are invalid, or false
/// otherwise.
@@ -169,7 +166,7 @@ public:
return false;
}
- /// \brief Receives the file system options.
+ /// Receives the file system options.
///
/// \returns true to indicate the file system options are invalid, or false
/// otherwise.
@@ -178,7 +175,7 @@ public:
return false;
}
- /// \brief Receives the header search options.
+ /// Receives the header search options.
///
/// \returns true to indicate the header search options are invalid, or false
/// otherwise.
@@ -188,7 +185,7 @@ public:
return false;
}
- /// \brief Receives the preprocessor options.
+ /// Receives the preprocessor options.
///
/// \param SuggestedPredefines Can be filled in with the set of predefines
/// that are suggested by the preprocessor options. Typically only used when
@@ -202,7 +199,7 @@ public:
return false;
}
- /// \brief Receives __COUNTER__ value.
+ /// Receives __COUNTER__ value.
virtual void ReadCounter(const serialization::ModuleFile &M,
unsigned Value) {}
@@ -210,15 +207,15 @@ public:
virtual void visitModuleFile(StringRef Filename,
serialization::ModuleKind Kind) {}
- /// \brief Returns true if this \c ASTReaderListener wants to receive the
+ /// 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
+ /// 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
+ /// if \c needsInputFileVisitation returns true, this is called for
/// each non-system input file of the AST File. If
/// \c needsSystemInputFileVisitation is true, then it is called for all
/// system input files as well.
@@ -229,11 +226,11 @@ public:
return true;
}
- /// \brief Returns true if this \c ASTReaderListener wants to receive the
+ /// 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
+ /// If needsImportVisitation returns \c true, this is called for each
/// AST file imported by this AST file.
virtual void visitImport(StringRef Filename) {}
@@ -242,7 +239,7 @@ public:
const ModuleFileExtensionMetadata &Metadata) {}
};
-/// \brief Simple wrapper class for chaining listeners.
+/// Simple wrapper class for chaining listeners.
class ChainedASTReaderListener : public ASTReaderListener {
std::unique_ptr<ASTReaderListener> First;
std::unique_ptr<ASTReaderListener> Second;
@@ -286,7 +283,7 @@ public:
const ModuleFileExtensionMetadata &Metadata) override;
};
-/// \brief ASTReaderListener implementation to validate the information of
+/// ASTReaderListener implementation to validate the information of
/// the PCH file against an initialized Preprocessor.
class PCHValidator : public ASTReaderListener {
Preprocessor &PP;
@@ -294,7 +291,7 @@ class PCHValidator : public ASTReaderListener {
public:
PCHValidator(Preprocessor &PP, ASTReader &Reader)
- : PP(PP), Reader(Reader) {}
+ : PP(PP), Reader(Reader) {}
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool AllowCompatibleDifferences) override;
@@ -313,7 +310,7 @@ private:
void Error(const char *Msg);
};
-/// \brief ASTReaderListenter implementation to set SuggestedPredefines of
+/// ASTReaderListenter implementation to set SuggestedPredefines of
/// ASTReader which is required to use a pch file. This is the replacement
/// of PCHValidator or SimplePCHValidator when using a pch file without
/// validating it.
@@ -321,8 +318,7 @@ class SimpleASTReaderListener : public ASTReaderListener {
Preprocessor &PP;
public:
- SimpleASTReaderListener(Preprocessor &PP)
- : PP(PP) {}
+ SimpleASTReaderListener(Preprocessor &PP) : PP(PP) {}
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
std::string &SuggestedPredefines) override;
@@ -336,14 +332,14 @@ namespace reader {
class ASTIdentifierLookupTrait;
-/// \brief The on-disk hash table(s) used for DeclContext name lookup.
+/// 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
+/// Reads an AST files chain containing the contents of a translation
/// unit.
///
/// The ASTReader class reads bitstreams (produced by the ASTWriter
@@ -364,7 +360,7 @@ class ASTReader
public ExternalSLocEntrySource
{
public:
- /// \brief Types of AST files.
+ /// Types of AST files.
friend class ASTDeclReader;
friend class ASTIdentifierIterator;
friend class ASTRecordReader;
@@ -379,31 +375,31 @@ public:
using RecordData = SmallVector<uint64_t, 64>;
using RecordDataImpl = SmallVectorImpl<uint64_t>;
- /// \brief The result of reading the control block of an AST file, which
+ /// The result of reading the control block of an AST file, which
/// can fail for various reasons.
enum ASTReadResult {
- /// \brief The control block was read successfully. Aside from failures,
+ /// The 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.
+ /// The AST file itself appears corrupted.
Failure,
- /// \brief The AST file was missing.
+ /// The AST file was missing.
Missing,
- /// \brief The AST file is out-of-date relative to its input files,
+ /// 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.
+ /// The AST file was written by a different version of Clang.
VersionMismatch,
- /// \brief The AST file was writtten with a different language/target
+ /// The AST file was writtten with a different language/target
/// configuration.
ConfigurationMismatch,
- /// \brief The AST file has errors.
+ /// The AST file has errors.
HadErrors
};
@@ -415,10 +411,10 @@ public:
using ModuleReverseIterator = ModuleManager::ModuleReverseIterator;
private:
- /// \brief The receiver of some callbacks invoked by ASTReader.
+ /// The receiver of some callbacks invoked by ASTReader.
std::unique_ptr<ASTReaderListener> Listener;
- /// \brief The receiver of deserialization events.
+ /// The receiver of deserialization events.
ASTDeserializationListener *DeserializationListener = nullptr;
bool OwnsDeserializationListener = false;
@@ -428,26 +424,26 @@ private:
const PCHContainerReader &PCHContainerRdr;
DiagnosticsEngine &Diags;
- /// \brief The semantic analysis object that will be processing the
+ /// The semantic analysis object that will be processing the
/// AST files and the translation unit that uses it.
Sema *SemaObj = nullptr;
- /// \brief The preprocessor that will be loading the source file.
+ /// The preprocessor that will be loading the source file.
Preprocessor &PP;
- /// \brief The AST context into which we'll read the AST files.
+ /// The AST context into which we'll read the AST files.
ASTContext *ContextObj = nullptr;
- /// \brief The AST consumer.
+ /// The AST consumer.
ASTConsumer *Consumer = nullptr;
- /// \brief The module manager which manages modules and their dependencies
+ /// The module manager which manages modules and their dependencies
ModuleManager ModuleMgr;
/// The cache that manages memory buffers for PCM files.
MemoryBufferCache &PCMCache;
- /// \brief A dummy identifier resolver used to merge TU-scope declarations in
+ /// A dummy identifier resolver used to merge TU-scope declarations in
/// C, for the cases where we don't have a Sema object to provide a real
/// identifier resolver.
IdentifierResolver DummyIdResolver;
@@ -455,31 +451,31 @@ private:
/// A mapping from extension block names to module file extensions.
llvm::StringMap<std::shared_ptr<ModuleFileExtension>> ModuleFileExtensions;
- /// \brief A timer used to track the time spent deserializing.
+ /// A timer used to track the time spent deserializing.
std::unique_ptr<llvm::Timer> ReadTimer;
- /// \brief The location where the module file will be considered as
+ /// The location where the module file will be considered as
/// imported from. For non-module AST types it should be invalid.
SourceLocation CurrentImportLoc;
- /// \brief The global module index, if loaded.
+ /// The global module index, if loaded.
std::unique_ptr<GlobalModuleIndex> GlobalIndex;
- /// \brief A map of global bit offsets to the module that stores entities
+ /// A map of global bit offsets to the module that stores entities
/// at those bit offsets.
ContinuousRangeMap<uint64_t, ModuleFile*, 4> GlobalBitOffsetsMap;
- /// \brief A map of negated SLocEntryIDs to the modules containing them.
+ /// A map of negated SLocEntryIDs to the modules containing them.
ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocEntryMap;
using GlobalSLocOffsetMapType =
ContinuousRangeMap<unsigned, ModuleFile *, 64>;
- /// \brief A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset)
+ /// A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset)
/// SourceLocation offsets to the modules containing them.
GlobalSLocOffsetMapType GlobalSLocOffsetMap;
- /// \brief Types that have already been loaded from the chain.
+ /// Types that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the type with
/// ID = (I + 1) << FastQual::Width has already been loaded
@@ -488,12 +484,12 @@ private:
using GlobalTypeMapType =
ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>;
- /// \brief Mapping from global type IDs to the module in which the
+ /// Mapping from global type IDs to the module in which the
/// type resides along with the offset that should be added to the
/// global type ID to produce a local ID.
GlobalTypeMapType GlobalTypeMap;
- /// \brief Declarations that have already been loaded from the chain.
+ /// Declarations that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the declaration with ID
/// = I + 1 has already been loaded.
@@ -502,7 +498,7 @@ private:
using GlobalDeclMapType =
ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>;
- /// \brief Mapping from global declaration IDs to the module in which the
+ /// Mapping from global declaration IDs to the module in which the
/// declaration resides.
GlobalDeclMapType GlobalDeclMap;
@@ -511,7 +507,7 @@ private:
using DeclUpdateOffsetsMap =
llvm::DenseMap<serialization::DeclID, FileOffsetsTy>;
- /// \brief Declarations that have modifications residing in a later file
+ /// Declarations that have modifications residing in a later file
/// in the chain.
DeclUpdateOffsetsMap DeclUpdateOffsets;
@@ -527,30 +523,30 @@ private:
: D(D), ID(ID), JustLoaded(JustLoaded) {}
};
- /// \brief Declaration updates for already-loaded declarations that we need
+ /// Declaration updates for already-loaded declarations that we need
/// to apply once we finish processing an import.
llvm::SmallVector<PendingUpdateRecord, 16> PendingUpdateRecords;
enum class PendingFakeDefinitionKind { NotFake, Fake, FakeLoaded };
- /// \brief The DefinitionData pointers that we faked up for class definitions
+ /// The DefinitionData pointers that we faked up for class definitions
/// that we needed but hadn't loaded yet.
llvm::DenseMap<void *, PendingFakeDefinitionKind> PendingFakeDefinitionData;
- /// \brief Exception specification updates that have been loaded but not yet
+ /// Exception specification updates that have been loaded but not yet
/// propagated across the relevant redeclaration chain. The map key is the
/// canonical declaration (used only for deduplication) and the value is a
/// declaration that has an exception specification.
llvm::SmallMapVector<Decl *, FunctionDecl *, 4> PendingExceptionSpecUpdates;
- /// \brief Declarations that have been imported and have typedef names for
+ /// Declarations that have been imported and have typedef names for
/// linkage purposes.
llvm::DenseMap<std::pair<DeclContext *, IdentifierInfo *>, NamedDecl *>
ImportedTypedefNamesForLinkage;
- /// \brief Mergeable declaration contexts that have anonymous declarations
+ /// Mergeable declaration contexts that have anonymous declarations
/// within them, and those anonymous declarations.
- llvm::DenseMap<DeclContext*, llvm::SmallVector<NamedDecl*, 2>>
+ llvm::DenseMap<Decl*, llvm::SmallVector<NamedDecl*, 2>>
AnonymousDeclarationsForMerging;
struct FileDeclsInfo {
@@ -559,24 +555,24 @@ private:
FileDeclsInfo() = default;
FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls)
- : Mod(Mod), Decls(Decls) {}
+ : Mod(Mod), Decls(Decls) {}
};
- /// \brief Map from a FileID to the file-level declarations that it contains.
+ /// Map from a FileID to the file-level declarations that it contains.
llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs;
- /// \brief An array of lexical contents of a declaration context, as a sequence of
+ /// An array of lexical contents of a declaration context, as a sequence of
/// Decl::Kind, DeclID pairs.
using LexicalContents = ArrayRef<llvm::support::unaligned_uint32_t>;
- /// \brief Map from a DeclContext to its lexical contents.
+ /// Map from a DeclContext to its lexical contents.
llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
LexicalDecls;
- /// \brief Map from the TU to its lexical contents from each module file.
+ /// Map from the TU to its lexical contents from each module file.
std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;
- /// \brief Map from a DeclContext to its lookup tables.
+ /// Map from a DeclContext to its lookup tables.
llvm::DenseMap<const DeclContext *,
serialization::reader::DeclContextLookupTable> Lookups;
@@ -590,12 +586,12 @@ private:
};
using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>;
- /// \brief Updates to the visible declarations of declaration contexts that
+ /// Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
PendingVisibleUpdates;
- /// \brief The set of C++ or Objective-C classes that have forward
+ /// The set of C++ or Objective-C classes that have forward
/// declarations that have not yet been linked to their definitions.
llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
@@ -604,24 +600,24 @@ private:
llvm::SmallDenseMap<Decl *, unsigned, 4>,
SmallVector<std::pair<Decl *, uint64_t>, 4>>;
- /// \brief Functions or methods that have bodies that will be attached.
+ /// Functions or methods that have bodies that will be attached.
PendingBodiesMap PendingBodies;
- /// \brief Definitions for which we have added merged definitions but not yet
+ /// Definitions for which we have added merged definitions but not yet
/// performed deduplication.
llvm::SetVector<NamedDecl *> PendingMergedDefinitionsToDeduplicate;
- /// \brief Read the record that describes the lexical contents of a DC.
+ /// 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.
+ /// Read the record that describes the visible contents of a DC.
bool ReadVisibleDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor,
uint64_t Offset, serialization::DeclID ID);
- /// \brief A vector containing identifiers that have already been
+ /// A vector containing identifiers that have already been
/// loaded.
///
/// If the pointer at index I is non-NULL, then it refers to the
@@ -632,12 +628,12 @@ private:
using GlobalIdentifierMapType =
ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4>;
- /// \brief Mapping from global identifier IDs to the module in which the
+ /// Mapping from global identifier IDs to the module in which the
/// identifier resides along with the offset that should be added to the
/// global identifier ID to produce a local ID.
GlobalIdentifierMapType GlobalIdentifierMap;
- /// \brief A vector containing macros that have already been
+ /// A vector containing macros that have already been
/// loaded.
///
/// If the pointer at index I is non-NULL, then it refers to the
@@ -648,7 +644,7 @@ private:
using LoadedMacroInfo =
std::pair<IdentifierInfo *, serialization::SubmoduleID>;
- /// \brief A set of #undef directives that we have loaded; used to
+ /// 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;
@@ -656,59 +652,59 @@ private:
using GlobalMacroMapType =
ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>;
- /// \brief Mapping from global macro IDs to the module in which the
+ /// Mapping from global macro IDs to the module in which the
/// macro resides along with the offset that should be added to the
/// global macro ID to produce a local ID.
GlobalMacroMapType GlobalMacroMap;
- /// \brief A vector containing submodules that have already been loaded.
+ /// A vector containing submodules that have already been loaded.
///
/// This vector is indexed by the Submodule ID (-1). NULL submodule entries
/// indicate that the particular submodule ID has not yet been loaded.
SmallVector<Module *, 2> SubmodulesLoaded;
-
+
using GlobalSubmoduleMapType =
ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4>;
-
- /// \brief Mapping from global submodule IDs to the module file in which the
+
+ /// Mapping from global submodule IDs to the module file in which the
/// submodule resides along with the offset that should be added to the
/// global submodule ID to produce a local ID.
GlobalSubmoduleMapType GlobalSubmoduleMap;
- /// \brief A set of hidden declarations.
+ /// A set of hidden declarations.
using HiddenNames = SmallVector<Decl *, 2>;
using HiddenNamesMapType = llvm::DenseMap<Module *, HiddenNames>;
- /// \brief A mapping from each of the hidden submodules to the deserialized
+ /// 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.
+
+ /// A module import, export, or conflict that hasn't yet been resolved.
struct UnresolvedModuleRef {
- /// \brief The file in which this module resides.
+ /// The file in which this module resides.
ModuleFile *File;
-
- /// \brief The module that is importing or exporting.
+
+ /// The module that is importing or exporting.
Module *Mod;
- /// \brief The kind of module reference.
+ /// The kind of module reference.
enum { Import, Export, Conflict } Kind;
- /// \brief The local ID of the module that is being exported.
+ /// The local ID of the module that is being exported.
unsigned ID;
- /// \brief Whether this is a wildcard export.
+ /// Whether this is a wildcard export.
unsigned IsWildcard : 1;
- /// \brief String data.
+ /// String data.
StringRef String;
};
-
- /// \brief The set of module imports and exports that still need to be
+
+ /// The set of module imports and exports that still need to be
/// resolved.
SmallVector<UnresolvedModuleRef, 2> UnresolvedModuleRefs;
-
- /// \brief A vector containing selectors that have already been loaded.
+
+ /// A vector containing selectors that have already been loaded.
///
/// This vector is indexed by the Selector ID (-1). NULL selector
/// entries indicate that the particular selector ID has not yet
@@ -718,11 +714,11 @@ private:
using GlobalSelectorMapType =
ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4>;
- /// \brief Mapping from global selector IDs to the module in which the
+ /// Mapping from global selector IDs to the module in which the
/// global selector ID to produce a local ID.
GlobalSelectorMapType GlobalSelectorMap;
- /// \brief The generation number of the last time we loaded data from the
+ /// The generation number of the last time we loaded data from the
/// global method pool for this selector.
llvm::DenseMap<Selector, unsigned> SelectorGeneration;
@@ -741,23 +737,30 @@ private:
using PendingMacroIDsMap =
llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2>>;
- /// \brief Mapping from identifiers that have a macro history to the global
+ /// 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;
using GlobalPreprocessedEntityMapType =
ContinuousRangeMap<unsigned, ModuleFile *, 4>;
- /// \brief Mapping from global preprocessing entity IDs to the module in
+ /// Mapping from global preprocessing entity IDs to the module in
/// which the preprocessed entity resides along with the offset that should be
/// added to the global preprocessing entity ID to produce a local ID.
GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap;
+ using GlobalSkippedRangeMapType =
+ ContinuousRangeMap<unsigned, ModuleFile *, 4>;
+
+ /// Mapping from global skipped range base IDs to the module in which
+ /// the skipped ranges reside.
+ GlobalSkippedRangeMapType GlobalSkippedRangeMap;
+
/// \name CodeGen-relevant special data
- /// \brief Fields containing data that is relevant to CodeGen.
+ /// Fields containing data that is relevant to CodeGen.
//@{
- /// \brief The IDs of all declarations that fulfill the criteria of
+ /// The IDs of all declarations that fulfill the criteria of
/// "interesting" decls.
///
/// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks
@@ -765,21 +768,21 @@ private:
/// the consumer eagerly.
SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
- /// \brief The IDs of all tentative definitions stored in the chain.
+ /// The IDs of all tentative definitions stored in the chain.
///
/// Sema keeps track of all tentative definitions in a TU because it has to
/// complete them and pass them on to CodeGen. Thus, tentative definitions in
/// the PCH chain must be eagerly deserialized.
SmallVector<uint64_t, 16> TentativeDefinitions;
- /// \brief The IDs of all CXXRecordDecls stored in the chain whose VTables are
+ /// The IDs of all CXXRecordDecls stored in the chain whose VTables are
/// used.
///
/// CodeGen has to emit VTables for these records, so they have to be eagerly
/// deserialized.
SmallVector<uint64_t, 64> VTableUses;
- /// \brief A snapshot of the pending instantiations in the chain.
+ /// A snapshot of the pending instantiations in the chain.
///
/// This record tracks the instantiations that Sema has to perform at the
/// end of the TU. It consists of a pair of values for every pending
@@ -790,26 +793,26 @@ private:
//@}
/// \name DiagnosticsEngine-relevant special data
- /// \brief Fields containing data that is used for generating diagnostics
+ /// Fields containing data that is used for generating diagnostics
//@{
- /// \brief A snapshot of Sema's unused file-scoped variable tracking, for
+ /// A snapshot of Sema's unused file-scoped variable tracking, for
/// generating warnings.
SmallVector<uint64_t, 16> UnusedFileScopedDecls;
- /// \brief A list of all the delegating constructors we've seen, to diagnose
+ /// A list of all the delegating constructors we've seen, to diagnose
/// cycles.
SmallVector<uint64_t, 4> DelegatingCtorDecls;
- /// \brief Method selectors used in a @selector expression. Used for
+ /// Method selectors used in a @selector expression. Used for
/// implementation of -Wselector.
SmallVector<uint64_t, 64> ReferencedSelectorsData;
- /// \brief A snapshot of Sema's weak undeclared identifier tracking, for
+ /// A snapshot of Sema's weak undeclared identifier tracking, for
/// generating warnings.
SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers;
- /// \brief The IDs of type aliases for ext_vectors that exist in the chain.
+ /// The IDs of type aliases for ext_vectors that exist in the chain.
///
/// Used by Sema for finding sugared names for ext_vectors in diagnostics.
SmallVector<uint64_t, 4> ExtVectorDecls;
@@ -817,48 +820,48 @@ private:
//@}
/// \name Sema-relevant special data
- /// \brief Fields containing data that is used for semantic analysis
+ /// Fields containing data that is used for semantic analysis
//@{
- /// \brief The IDs of all potentially unused typedef names in the chain.
+ /// The IDs of all potentially unused typedef names in the chain.
///
/// Sema tracks these to emit warnings.
SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates;
- /// \brief Our current depth in #pragma cuda force_host_device begin/end
+ /// Our current depth in #pragma cuda force_host_device begin/end
/// macros.
unsigned ForceCUDAHostDeviceDepth = 0;
- /// \brief The IDs of the declarations Sema stores directly.
+ /// The IDs of the declarations Sema stores directly.
///
/// Sema tracks a few important decls, such as namespace std, directly.
SmallVector<uint64_t, 4> SemaDeclRefs;
- /// \brief The IDs of the types ASTContext stores directly.
+ /// The IDs of the types ASTContext stores directly.
///
/// The AST context tracks a few important types, such as va_list, directly.
SmallVector<uint64_t, 16> SpecialTypes;
- /// \brief The IDs of CUDA-specific declarations ASTContext stores directly.
+ /// The IDs of CUDA-specific declarations ASTContext stores directly.
///
/// The AST context tracks a few important decls, currently cudaConfigureCall,
/// directly.
SmallVector<uint64_t, 2> CUDASpecialDeclRefs;
- /// \brief The floating point pragma option settings.
+ /// The floating point pragma option settings.
SmallVector<uint64_t, 1> FPPragmaOptions;
- /// \brief The pragma clang optimize location (if the pragma state is "off").
+ /// The pragma clang optimize location (if the pragma state is "off").
SourceLocation OptimizeOffPragmaLocation;
- /// \brief The PragmaMSStructKind pragma ms_struct state if set, or -1.
+ /// The PragmaMSStructKind pragma ms_struct state if set, or -1.
int PragmaMSStructState = -1;
- /// \brief The PragmaMSPointersToMembersKind pragma pointers_to_members state.
+ /// The PragmaMSPointersToMembersKind pragma pointers_to_members state.
int PragmaMSPointersToMembersState = -1;
SourceLocation PointersToMembersPragmaLocation;
- /// \brief The pragma pack state.
+ /// The pragma pack state.
Optional<unsigned> PragmaPackCurrentValue;
SourceLocation PragmaPackCurrentLocation;
struct PragmaPackStackEntry {
@@ -870,26 +873,26 @@ private:
llvm::SmallVector<PragmaPackStackEntry, 2> PragmaPackStack;
llvm::SmallVector<std::string, 2> PragmaPackStrings;
- /// \brief The OpenCL extension settings.
+ /// The OpenCL extension settings.
OpenCLOptions OpenCLExtensions;
- /// \brief Extensions required by an OpenCL type.
+ /// Extensions required by an OpenCL type.
llvm::DenseMap<const Type *, std::set<std::string>> OpenCLTypeExtMap;
- /// \brief Extensions required by an OpenCL declaration.
+ /// Extensions required by an OpenCL declaration.
llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;
- /// \brief A list of the namespaces we've seen.
+ /// A list of the namespaces we've seen.
SmallVector<uint64_t, 4> KnownNamespaces;
- /// \brief A list of undefined decls with internal linkage followed by the
+ /// A list of undefined decls with internal linkage followed by the
/// SourceLocation of a matching ODR-use.
SmallVector<uint64_t, 8> UndefinedButUsed;
- /// \brief Delete expressions to analyze at the end of translation unit.
+ /// Delete expressions to analyze at the end of translation unit.
SmallVector<uint64_t, 8> DelayedDeleteExprs;
- // \brief A list of late parsed template function data.
+ // A list of late parsed template function data.
SmallVector<uint64_t, 1> LateParsedTemplates;
public:
@@ -898,45 +901,45 @@ public:
SourceLocation ImportLoc;
ImportedSubmodule(serialization::SubmoduleID ID, SourceLocation ImportLoc)
- : ID(ID), ImportLoc(ImportLoc) {}
+ : ID(ID), ImportLoc(ImportLoc) {}
};
private:
- /// \brief A list of modules that were imported by precompiled headers or
+ /// A list of modules that were imported by precompiled headers or
/// any other non-module AST file.
SmallVector<ImportedSubmodule, 2> ImportedModules;
//@}
- /// \brief The system include root to be used when loading the
+ /// The system include root to be used when loading the
/// precompiled header.
std::string isysroot;
- /// \brief Whether to disable the normal validation performed on precompiled
+ /// Whether to disable the normal validation performed on precompiled
/// headers when they are loaded.
bool DisableValidation;
- /// \brief Whether to accept an AST file with compiler errors.
+ /// Whether to accept an AST file with compiler errors.
bool AllowASTWithCompilerErrors;
- /// \brief Whether to accept an AST file that has a different configuration
+ /// Whether to accept an AST file that has a different configuration
/// from the current compiler instance.
bool AllowConfigurationMismatch;
- /// \brief Whether validate system input files.
+ /// Whether validate system input files.
bool ValidateSystemInputs;
- /// \brief Whether we are allowed to use the global module index.
+ /// Whether we are allowed to use the global module index.
bool UseGlobalIndex;
- /// \brief Whether we have tried loading the global module index yet.
+ /// Whether we have tried loading the global module index yet.
bool TriedLoadingGlobalIndex = false;
- ///\brief Whether we are currently processing update records.
+ ///Whether we are currently processing update records.
bool ProcessingUpdateRecords = false;
using SwitchCaseMapTy = llvm::DenseMap<unsigned, SwitchCase *>;
- /// \brief Mapping from switch-case IDs in the chain to switch-case statements
+ /// Mapping from switch-case IDs in the chain to switch-case statements
///
/// Statements usually don't have IDs, but switch cases need them, so that the
/// switch statement can refer to them.
@@ -944,56 +947,56 @@ private:
SwitchCaseMapTy *CurrSwitchCaseStmts;
- /// \brief The number of source location entries de-serialized from
+ /// The number of source location entries de-serialized from
/// the PCH file.
unsigned NumSLocEntriesRead = 0;
- /// \brief The number of source location entries in the chain.
+ /// The number of source location entries in the chain.
unsigned TotalNumSLocEntries = 0;
- /// \brief The number of statements (and expressions) de-serialized
+ /// The number of statements (and expressions) de-serialized
/// from the chain.
unsigned NumStatementsRead = 0;
- /// \brief The total number of statements (and expressions) stored
+ /// The total number of statements (and expressions) stored
/// in the chain.
unsigned TotalNumStatements = 0;
- /// \brief The number of macros de-serialized from the chain.
+ /// The number of macros de-serialized from the chain.
unsigned NumMacrosRead = 0;
- /// \brief The total number of macros stored in the chain.
+ /// The total number of macros stored in the chain.
unsigned TotalNumMacros = 0;
- /// \brief The number of lookups into identifier tables.
+ /// The number of lookups into identifier tables.
unsigned NumIdentifierLookups = 0;
- /// \brief The number of lookups into identifier tables that succeed.
+ /// The number of lookups into identifier tables that succeed.
unsigned NumIdentifierLookupHits = 0;
- /// \brief The number of selectors that have been read.
+ /// The number of selectors that have been read.
unsigned NumSelectorsRead = 0;
- /// \brief The number of method pool entries that have been read.
+ /// The number of method pool entries that have been read.
unsigned NumMethodPoolEntriesRead = 0;
- /// \brief The number of times we have looked up a selector in the method
+ /// The number of times we have looked up a selector in the method
/// pool.
unsigned NumMethodPoolLookups = 0;
- /// \brief The number of times we have looked up a selector in the method
+ /// The number of times we have looked up a selector in the method
/// pool and found something.
unsigned NumMethodPoolHits = 0;
- /// \brief The number of times we have looked up a selector in the method
+ /// The number of times we have looked up a selector in the method
/// pool within a specific module.
unsigned NumMethodPoolTableLookups = 0;
- /// \brief The number of times we have looked up a selector in the method
+ /// The number of times we have looked up a selector in the method
/// pool within a specific module and found something.
unsigned NumMethodPoolTableHits = 0;
- /// \brief The total number of method pool entries in the selector table.
+ /// The total number of method pool entries in the selector table.
unsigned TotalNumMethodPoolEntries = 0;
/// Number of lexical decl contexts read/total.
@@ -1005,16 +1008,16 @@ private:
/// Total size of modules, in bits, currently loaded
uint64_t TotalModulesSizeInBits = 0;
- /// \brief Number of Decl/types that are currently deserializing.
+ /// Number of Decl/types that are currently deserializing.
unsigned NumCurrentElementsDeserializing = 0;
- /// \brief Set true while we are in the process of passing deserialized
+ /// Set true while we are in the process of passing deserialized
/// "interesting" decls to consumer inside FinishedDeserializing().
/// This is used as a guard to avoid recursively repeating the process of
/// passing decls to consumer.
bool PassingDeclsToConsumer = false;
- /// \brief The set of identifiers that were read while the AST reader was
+ /// The set of identifiers that were read while the AST reader was
/// (recursively) loading declarations.
///
/// The declarations on the identifier chain for these identifiers will be
@@ -1022,12 +1025,12 @@ private:
llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4>>
PendingIdentifierInfos;
- /// \brief The set of lookup results that we have faked in order to support
+ /// The set of lookup results that we have faked in order to support
/// merging of partially deserialized decls but that we have not yet removed.
llvm::SmallMapVector<IdentifierInfo *, SmallVector<NamedDecl*, 2>, 16>
PendingFakeLookupResults;
- /// \brief The generation number of each identifier, which keeps track of
+ /// The generation number of each identifier, which keeps track of
/// the last time we loaded information about this identifier.
llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration;
@@ -1045,7 +1048,7 @@ private:
bool hasPendingBody() { return DeclHasPendingBody; }
};
- /// \brief Contains declarations and definitions that could be
+ /// Contains declarations and definitions that could be
/// "interesting" to the ASTConsumer, when we get that AST consumer.
///
/// "Interesting" declarations are those that have data that may
@@ -1053,16 +1056,16 @@ private:
/// Objective-C protocols.
std::deque<InterestingDecl> PotentiallyInterestingDecls;
- /// \brief The list of redeclaration chains that still need to be
+ /// The list of redeclaration chains that still need to be
/// reconstructed, and the local offset to the corresponding list
/// of redeclarations.
SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains;
- /// \brief The list of canonical declarations whose redeclaration chains
+ /// The list of canonical declarations whose redeclaration chains
/// need to be marked as incomplete once we're done deserializing things.
SmallVector<Decl *, 16> PendingIncompleteDeclChains;
- /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has
+ /// The Decl IDs for the Sema/Lexical DeclContext of a Decl that has
/// been loaded but its DeclContext was not set yet.
struct PendingDeclContextInfo {
Decl *D;
@@ -1070,14 +1073,14 @@ private:
serialization::GlobalDeclID LexicalDC;
};
- /// \brief The set of Decls that have been loaded but their DeclContexts are
+ /// The set of Decls that have been loaded but their DeclContexts are
/// not set yet.
///
/// The DeclContexts for these Decls will be set once recursive loading has
/// been completed.
std::deque<PendingDeclContextInfo> PendingDeclContextInfos;
- /// \brief The set of NamedDecls that have been loaded, but are members of a
+ /// The set of NamedDecls that have been loaded, but are members of a
/// context that has been merged into another context where the corresponding
/// declaration is either missing or has not yet been loaded.
///
@@ -1088,64 +1091,68 @@ private:
using DataPointers =
std::pair<CXXRecordDecl *, struct CXXRecordDecl::DefinitionData *>;
- /// \brief Record definitions in which we found an ODR violation.
+ /// Record definitions in which we found an ODR violation.
llvm::SmallDenseMap<CXXRecordDecl *, llvm::SmallVector<DataPointers, 2>, 2>
PendingOdrMergeFailures;
- /// \brief Function definitions in which we found an ODR violation.
+ /// Function definitions in which we found an ODR violation.
llvm::SmallDenseMap<FunctionDecl *, llvm::SmallVector<FunctionDecl *, 2>, 2>
PendingFunctionOdrMergeFailures;
- /// \brief DeclContexts in which we have diagnosed an ODR violation.
+ /// Enum definitions in which we found an ODR violation.
+ llvm::SmallDenseMap<EnumDecl *, llvm::SmallVector<EnumDecl *, 2>, 2>
+ PendingEnumOdrMergeFailures;
+
+ /// DeclContexts in which we have diagnosed an ODR violation.
llvm::SmallPtrSet<DeclContext*, 2> DiagnosedOdrMergeFailures;
- /// \brief The set of Objective-C categories that have been deserialized
+ /// The set of Objective-C categories that have been deserialized
/// since the last time the declaration chains were linked.
llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized;
- /// \brief The set of Objective-C class definitions that have already been
+ /// The set of Objective-C class definitions that have already been
/// loaded, for which we will need to check for categories whenever a new
/// module is loaded.
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
using KeyDeclsMap =
llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2>>;
-
- /// \brief A mapping from canonical declarations to the set of global
+
+ /// A mapping from canonical declarations to the set of global
/// declaration IDs for key declaration that have been merged with that
/// canonical declaration. A key declaration is a formerly-canonical
/// declaration whose module did not import any other key declaration for that
/// entity. These are the IDs that we use as keys when finding redecl chains.
KeyDeclsMap KeyDecls;
-
- /// \brief A mapping from DeclContexts to the semantic DeclContext that we
+
+ /// A mapping from DeclContexts to the semantic DeclContext that we
/// are treating as the definition of the entity. This is used, for instance,
/// when merging implicit instantiations of class templates across modules.
llvm::DenseMap<DeclContext *, DeclContext *> MergedDeclContexts;
- /// \brief A mapping from canonical declarations of enums to their canonical
+ /// A mapping from canonical declarations of enums to their canonical
/// definitions. Only populated when using modules in C++.
llvm::DenseMap<EnumDecl *, EnumDecl *> EnumDefinitions;
- /// \brief When reading a Stmt tree, Stmt operands are placed in this stack.
+ /// When reading a Stmt tree, Stmt operands are placed in this stack.
SmallVector<Stmt *, 16> StmtStack;
- /// \brief What kind of records we are reading.
+ /// What kind of records we are reading.
enum ReadingKind {
Read_None, Read_Decl, Read_Type, Read_Stmt
};
- /// \brief What kind of records we are reading.
+ /// What kind of records we are reading.
ReadingKind ReadingKind = Read_None;
- /// \brief RAII object to change the reading kind.
+ /// RAII object to change the reading kind.
class ReadingKindTracker {
ASTReader &Reader;
enum ReadingKind PrevKind;
public:
ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader)
- : Reader(reader), PrevKind(Reader.ReadingKind) {
+ : Reader(reader), PrevKind(Reader.ReadingKind) {
Reader.ReadingKind = newKind;
}
@@ -1154,14 +1161,14 @@ private:
~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
};
- /// \brief RAII object to mark the start of processing updates.
+ /// RAII object to mark the start of processing updates.
class ProcessingUpdatesRAIIObj {
ASTReader &Reader;
bool PrevState;
public:
ProcessingUpdatesRAIIObj(ASTReader &reader)
- : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) {
+ : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) {
Reader.ProcessingUpdateRecords = true;
}
@@ -1171,7 +1178,7 @@ private:
~ProcessingUpdatesRAIIObj() { Reader.ProcessingUpdateRecords = PrevState; }
};
- /// \brief Suggested contents of the predefines buffer, after this
+ /// Suggested contents of the predefines buffer, after this
/// PCH file has been processed.
///
/// In most cases, this string will be empty, because the predefines
@@ -1183,7 +1190,7 @@ private:
llvm::DenseMap<const Decl *, bool> DefinitionSource;
- /// \brief Reads a statement from the specified cursor.
+ /// Reads a statement from the specified cursor.
Stmt *ReadStmtFromStream(ModuleFile &F);
struct InputFileInfo {
@@ -1195,10 +1202,10 @@ private:
bool TopLevelModuleMap;
};
- /// \brief Reads the stored information about an input file.
+ /// Reads the stored information about an input file.
InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID);
- /// \brief Retrieve the file entry and 'overridden' bit for an input
+ /// Retrieve the file entry and 'overridden' bit for an input
/// file in the given module file.
serialization::InputFile getInputFile(ModuleFile &F, unsigned ID,
bool Complain = true);
@@ -1207,7 +1214,7 @@ public:
void ResolveImportedPath(ModuleFile &M, std::string &Filename);
static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
- /// \brief Returns the first key declaration for the given declaration. This
+ /// Returns the first key declaration for the given declaration. This
/// is one that is formerly-canonical (or still canonical) and whose module
/// did not import any other key declaration of the entity.
Decl *getKeyDeclaration(Decl *D) {
@@ -1224,7 +1231,7 @@ public:
return getKeyDeclaration(const_cast<Decl*>(D));
}
- /// \brief Run a callback on each imported key declaration of \p D.
+ /// Run a callback on each imported key declaration of \p D.
template <typename Fn>
void forEachImportedKeyDecl(const Decl *D, Fn Visit) {
D = D->getCanonicalDecl();
@@ -1237,7 +1244,7 @@ public:
Visit(GetExistingDecl(ID));
}
- /// \brief Get the loaded lookup tables for \p Primary, if any.
+ /// Get the loaded lookup tables for \p Primary, if any.
const serialization::reader::DeclContextLookupTable *
getLoadedLookupTables(DeclContext *Primary) const;
@@ -1250,7 +1257,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,
@@ -1314,8 +1321,7 @@ private:
ModuleFile *F;
uint64_t Offset;
- RecordLocation(ModuleFile *M, uint64_t O)
- : F(M), Offset(O) {}
+ RecordLocation(ModuleFile *M, uint64_t O) : F(M), Offset(O) {}
};
QualType readTypeRecord(unsigned Index);
@@ -1328,7 +1334,7 @@ private:
Decl *ReadDeclRecord(serialization::DeclID ID);
void markIncompleteDeclChain(Decl *Canon);
- /// \brief Returns the most recent declaration of a declaration (which must be
+ /// Returns the most recent declaration of a declaration (which must be
/// of a redeclarable kind) that is either local or has already been loaded
/// merged into its redecl chain.
Decl *getMostRecentExistingDecl(Decl *D);
@@ -1343,12 +1349,12 @@ private:
RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset);
- /// \brief Returns the first preprocessed entity ID that begins or ends after
+ /// Returns the first preprocessed entity ID that begins or ends after
/// \arg Loc.
serialization::PreprocessedEntityID
findPreprocessedEntity(SourceLocation Loc, bool EndsAfter) const;
- /// \brief Find the next module that contains entities and return the ID
+ /// 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
@@ -1358,12 +1364,12 @@ private:
findNextPreprocessedEntity(
GlobalSLocOffsetMapType::const_iterator SLocMapI) const;
- /// \brief Returns (ModuleFile, Local index) pair for \p GlobalIndex of a
+ /// Returns (ModuleFile, Local index) pair for \p GlobalIndex of a
/// preprocessed entity.
std::pair<ModuleFile *, unsigned>
getModulePreprocessedEntity(unsigned GlobalIndex);
- /// \brief Returns (begin, end) pair for the preprocessed entities of a
+ /// Returns (begin, end) pair for the preprocessed entities of a
/// particular module.
llvm::iterator_range<PreprocessingRecord::iterator>
getModulePreprocessedEntities(ModuleFile &Mod) const;
@@ -1416,7 +1422,7 @@ private:
PendingDeclContextInfos.push_back(Info);
}
- /// \brief Produce an error diagnostic and return true.
+ /// Produce an error diagnostic and return true.
///
/// This routine should only be used for fatal errors that have to
/// do with non-routine failures (e.g., corrupted AST file).
@@ -1425,7 +1431,7 @@ private:
StringRef Arg2 = StringRef()) const;
public:
- /// \brief Load the AST file and validate its contents against the given
+ /// Load the AST file and validate its contents against the given
/// Preprocessor.
///
/// \param PP the preprocessor associated with the context in which this
@@ -1480,34 +1486,34 @@ public:
FileManager &getFileManager() const { return FileMgr; }
DiagnosticsEngine &getDiags() const { return Diags; }
- /// \brief Flags that indicate what kind of AST loading failures the client
+ /// Flags that indicate what kind of AST loading failures the client
/// of the AST reader can directly handle.
///
/// When a client states that it can handle a particular kind of failure,
/// the AST reader will not emit errors when producing that kind of failure.
enum LoadFailureCapabilities {
- /// \brief The client can't handle any AST loading failures.
+ /// 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
+ /// 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
+ /// 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
+ /// 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
+ /// The client can handle an AST file that cannot load because it's
/// compiled configuration doesn't match that of the context it was
/// loaded into.
ARR_ConfigurationMismatch = 0x8
};
- /// \brief Load the AST file designated by the given file name.
+ /// Load the AST file designated by the given file name.
///
/// \param FileName The name of the AST file to load.
///
@@ -1528,7 +1534,7 @@ public:
unsigned ClientLoadCapabilities,
SmallVectorImpl<ImportedSubmodule> *Imported = nullptr);
- /// \brief Make the entities in the given module and any of its (non-explicit)
+ /// Make the entities in the given module and any of its (non-explicit)
/// submodules visible to name lookup.
///
/// \param Mod The module whose names should be made visible.
@@ -1541,24 +1547,24 @@ public:
Module::NameVisibilityKind NameVisibility,
SourceLocation ImportLoc);
- /// \brief Make the names within this set of hidden names visible.
+ /// Make the names within this set of hidden names visible.
void makeNamesVisible(const HiddenNames &Names, Module *Owner);
- /// \brief Note that MergedDef is a redefinition of the canonical definition
+ /// Note that MergedDef is a redefinition of the canonical definition
/// Def, so Def should be visible whenever MergedDef is.
void mergeDefinitionVisibility(NamedDecl *Def, NamedDecl *MergedDef);
- /// \brief Take the AST callbacks listener.
+ /// Take the AST callbacks listener.
std::unique_ptr<ASTReaderListener> takeListener() {
return std::move(Listener);
}
- /// \brief Set the AST callbacks listener.
+ /// Set the AST callbacks listener.
void setListener(std::unique_ptr<ASTReaderListener> Listener) {
this->Listener = std::move(Listener);
}
- /// \brief Add an AST callback listener.
+ /// Add an AST callback listener.
///
/// Takes ownership of \p L.
void addListener(std::unique_ptr<ASTReaderListener> L) {
@@ -1593,67 +1599,72 @@ public:
}
};
- /// \brief Set the AST deserialization listener.
+ /// Set the AST deserialization listener.
void setDeserializationListener(ASTDeserializationListener *Listener,
bool TakeOwnership = false);
- /// \brief Determine whether this AST reader has a global index.
+ /// Get the AST deserialization listener.
+ ASTDeserializationListener *getDeserializationListener() {
+ return DeserializationListener;
+ }
+
+ /// Determine whether this AST reader has a global index.
bool hasGlobalIndex() const { return (bool)GlobalIndex; }
- /// \brief Return global module index.
+ /// Return global module index.
GlobalModuleIndex *getGlobalIndex() { return GlobalIndex.get(); }
- /// \brief Reset reader for a reload try.
+ /// Reset reader for a reload try.
void resetForReload() { TriedLoadingGlobalIndex = false; }
- /// \brief Attempts to load the global index.
+ /// Attempts to load the global index.
///
/// \returns true if loading the global index has failed for any reason.
bool loadGlobalIndex();
- /// \brief Determine whether we tried to load the global index, but failed,
+ /// Determine whether we tried to load the global index, but failed,
/// e.g., because it is out-of-date or does not exist.
bool isGlobalIndexUnavailable() const;
-
- /// \brief Initializes the ASTContext
+
+ /// Initializes the ASTContext
void InitializeContext();
- /// \brief Update the state of Sema after loading some additional modules.
+ /// Update the state of Sema after loading some additional modules.
void UpdateSema();
- /// \brief Add in-memory (virtual file) buffer.
+ /// Add in-memory (virtual file) buffer.
void addInMemoryBuffer(StringRef &FileName,
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
ModuleMgr.addInMemoryBuffer(FileName, std::move(Buffer));
}
- /// \brief Finalizes the AST reader's state before writing an AST file to
+ /// Finalizes the AST reader's state before writing an AST file to
/// disk.
///
/// This operation may undo temporary state in the AST that should not be
/// emitted.
void finalizeForWriting();
- /// \brief Retrieve the module manager.
+ /// Retrieve the module manager.
ModuleManager &getModuleManager() { return ModuleMgr; }
- /// \brief Retrieve the preprocessor.
+ /// Retrieve the preprocessor.
Preprocessor &getPreprocessor() const { return PP; }
- /// \brief Retrieve the name of the original source file name for the primary
+ /// Retrieve the name of the original source file name for the primary
/// module file.
StringRef getOriginalSourceFile() {
- return ModuleMgr.getPrimaryModule().OriginalSourceFileName;
+ return ModuleMgr.getPrimaryModule().OriginalSourceFileName;
}
- /// \brief Retrieve the name of the original source file name directly from
+ /// Retrieve the name of the original source file name directly from
/// the AST file, without actually loading the AST file.
static std::string
getOriginalSourceFile(const std::string &ASTFileName, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
DiagnosticsEngine &Diags);
- /// \brief Read the control block for the named AST file.
+ /// Read the control block for the named AST file.
///
/// \returns true if an error occurred, false otherwise.
static bool
@@ -1663,7 +1674,7 @@ public:
ASTReaderListener &Listener,
bool ValidateDiagnosticOptions);
- /// \brief Determine whether the given AST file is acceptable to load into a
+ /// Determine whether the given AST file is acceptable to load into a
/// translation unit with the given language and target options.
static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
@@ -1672,68 +1683,71 @@ public:
const PreprocessorOptions &PPOpts,
StringRef ExistingModuleCachePath);
- /// \brief Returns the suggested contents of the predefines buffer,
+ /// Returns the suggested contents of the predefines buffer,
/// which contains a (typically-empty) subset of the predefines
/// build prior to including the precompiled header.
const std::string &getSuggestedPredefines() { return SuggestedPredefines; }
- /// \brief Read a preallocated preprocessed entity from the external source.
+ /// Read a preallocated preprocessed entity from the external source.
///
/// \returns null if an error occurred that prevented the preprocessed
/// entity from being loaded.
PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) override;
- /// \brief Returns a pair of [Begin, End) indices of preallocated
+ /// Returns a pair of [Begin, End) indices of preallocated
/// preprocessed entities that \p Range encompasses.
std::pair<unsigned, unsigned>
findPreprocessedEntitiesInRange(SourceRange Range) override;
- /// \brief Optionally returns true or false if the preallocated preprocessed
+ /// Optionally returns true or false if the preallocated preprocessed
/// entity with index \p Index came from file \p FID.
Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
FileID FID) override;
- /// \brief Read the header file information for the given file entry.
+ /// Read a preallocated skipped range from the external source.
+ SourceRange ReadSkippedRange(unsigned Index) override;
+
+ /// Read the header file information for the given file entry.
HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override;
void ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag);
- /// \brief Returns the number of source locations found in the chain.
+ /// Returns the number of source locations found in the chain.
unsigned getTotalNumSLocs() const {
return TotalNumSLocEntries;
}
- /// \brief Returns the number of identifiers found in the chain.
+ /// Returns the number of identifiers found in the chain.
unsigned getTotalNumIdentifiers() const {
return static_cast<unsigned>(IdentifiersLoaded.size());
}
- /// \brief Returns the number of macros found in the chain.
+ /// Returns the number of macros found in the chain.
unsigned getTotalNumMacros() const {
return static_cast<unsigned>(MacrosLoaded.size());
}
- /// \brief Returns the number of types found in the chain.
+ /// Returns the number of types found in the chain.
unsigned getTotalNumTypes() const {
return static_cast<unsigned>(TypesLoaded.size());
}
- /// \brief Returns the number of declarations found in the chain.
+ /// Returns the number of declarations found in the chain.
unsigned getTotalNumDecls() const {
return static_cast<unsigned>(DeclsLoaded.size());
}
- /// \brief Returns the number of submodules known.
+ /// Returns the number of submodules known.
unsigned getTotalNumSubmodules() const {
return static_cast<unsigned>(SubmodulesLoaded.size());
}
-
- /// \brief Returns the number of selectors found in the chain.
+
+ /// Returns the number of selectors found in the chain.
unsigned getTotalNumSelectors() const {
return static_cast<unsigned>(SelectorsLoaded.size());
}
- /// \brief Returns the number of preprocessed entities known to the AST
+ /// Returns the number of preprocessed entities known to the AST
/// reader.
unsigned getTotalNumPreprocessedEntities() const {
unsigned Result = 0;
@@ -1742,13 +1756,13 @@ public:
return Result;
}
- /// \brief Reads a TemplateArgumentLocInfo appropriate for the
+ /// Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind.
TemplateArgumentLocInfo
GetTemplateArgumentLocInfo(ModuleFile &F, TemplateArgument::ArgKind Kind,
const RecordData &Record, unsigned &Idx);
- /// \brief Reads a TemplateArgumentLoc.
+ /// Reads a TemplateArgumentLoc.
TemplateArgumentLoc
ReadTemplateArgumentLoc(ModuleFile &F,
const RecordData &Record, unsigned &Idx);
@@ -1757,63 +1771,67 @@ public:
ReadASTTemplateArgumentListInfo(ModuleFile &F,
const RecordData &Record, unsigned &Index);
- /// \brief Reads a declarator info from the given record.
+ /// Reads a declarator info from the given record.
TypeSourceInfo *GetTypeSourceInfo(ModuleFile &F,
const RecordData &Record, unsigned &Idx);
- /// \brief Resolve a type ID into a type, potentially building a new
+ /// Raad the type locations for the given TInfo.
+ void ReadTypeLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx,
+ TypeLoc TL);
+
+ /// Resolve a type ID into a type, potentially building a new
/// type.
QualType GetType(serialization::TypeID ID);
- /// \brief Resolve a local type ID within a given AST file into a type.
+ /// Resolve a local type ID within a given AST file into a type.
QualType getLocalType(ModuleFile &F, unsigned LocalID);
- /// \brief Map a local type ID within a given AST file into a global type ID.
+ /// Map a local type ID within a given AST file into a global type ID.
serialization::TypeID getGlobalTypeID(ModuleFile &F, unsigned LocalID) const;
- /// \brief Read a type from the current position in the given record, which
+ /// Read a type from the current position in the given record, which
/// was read from the given AST file.
QualType readType(ModuleFile &F, const RecordData &Record, unsigned &Idx) {
if (Idx >= Record.size())
- return QualType();
+ return {};
return getLocalType(F, Record[Idx++]);
}
- /// \brief Map from a local declaration ID within a given module to a
+ /// Map from a local declaration ID within a given module to a
/// global declaration ID.
serialization::DeclID getGlobalDeclID(ModuleFile &F,
serialization::LocalDeclID LocalID) const;
- /// \brief Returns true if global DeclID \p ID originated from module \p M.
+ /// Returns true if global DeclID \p ID originated from module \p M.
bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const;
- /// \brief Retrieve the module file that owns the given declaration, or NULL
+ /// Retrieve the module file that owns the given declaration, or NULL
/// if the declaration is not from a module file.
ModuleFile *getOwningModuleFile(const Decl *D);
- /// \brief Get the best name we know for the module that owns the given
+ /// Get the best name we know for the module that owns the given
/// declaration, or an empty string if the declaration is not from a module.
std::string getOwningModuleNameForDiagnostic(const Decl *D);
- /// \brief Returns the source location for the decl \p ID.
+ /// Returns the source location for the decl \p ID.
SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID);
- /// \brief Resolve a declaration ID into a declaration, potentially
+ /// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
Decl *GetDecl(serialization::DeclID ID);
Decl *GetExternalDecl(uint32_t ID) override;
- /// \brief Resolve a declaration ID into a declaration. Return 0 if it's not
+ /// Resolve a declaration ID into a declaration. Return 0 if it's not
/// been loaded yet.
Decl *GetExistingDecl(serialization::DeclID ID);
- /// \brief Reads a declaration with the given local ID in the given module.
+ /// Reads a declaration with the given local ID in the given module.
Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) {
return GetDecl(getGlobalDeclID(F, LocalID));
}
- /// \brief Reads a declaration with the given local ID in the given module.
+ /// Reads a declaration with the given local ID in the given module.
///
/// \returns The requested declaration, casted to the given return type.
template<typename T>
@@ -1821,29 +1839,29 @@ public:
return cast_or_null<T>(GetLocalDecl(F, LocalID));
}
- /// \brief Map a global declaration ID into the declaration ID used to
+ /// Map a global declaration ID into the declaration ID used to
/// refer to this declaration within the given module fule.
///
/// \returns the global ID of the given declaration as known in the given
/// module file.
- serialization::DeclID
+ serialization::DeclID
mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
serialization::DeclID GlobalID);
-
- /// \brief Reads a declaration ID from the given position in a record in the
+
+ /// Reads a declaration ID from the given position in a record in the
/// given module.
///
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
- /// \brief Reads a declaration from the given position in a record in the
+ /// Reads a declaration from the given position in a record in the
/// given module.
Decl *ReadDecl(ModuleFile &F, const RecordData &R, unsigned &I) {
return GetDecl(ReadDeclID(F, R, I));
}
- /// \brief Reads a declaration from the given position in a record in the
+ /// Reads a declaration from the given position in a record in the
/// given module.
///
/// \returns The declaration read from this location, casted to the given
@@ -1853,14 +1871,14 @@ public:
return cast_or_null<T>(GetDecl(ReadDeclID(F, R, I)));
}
- /// \brief If any redeclarations of \p D have been imported since it was
+ /// If any redeclarations of \p D have been imported since it was
/// last checked, this digs out those redeclarations and adds them to the
/// redeclaration chain for \p D.
void CompleteRedeclChain(const Decl *D) override;
CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
- /// \brief Resolve the offset of a statement into a statement.
+ /// Resolve the offset of a statement into a statement.
///
/// This operation will read a new statement from the external
/// source each time it is called, and is meant to be used via a
@@ -1872,13 +1890,13 @@ public:
/// and then leave the cursor pointing into the block.
static bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID);
- /// \brief Finds all the visible declarations with a given name.
+ /// Finds all the visible declarations with a given name.
/// The current implementation of this method just loads the entire
/// lookup table as unmaterialized references.
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;
- /// \brief Read all of the declarations lexically stored in a
+ /// Read all of the declarations lexically stored in a
/// declaration context.
///
/// \param DC The declaration context whose declarations will be
@@ -1896,47 +1914,47 @@ public:
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Decls) override;
- /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
/// a range.
void FindFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
SmallVectorImpl<Decl *> &Decls) override;
- /// \brief Notify ASTReader that we started deserialization of
+ /// Notify ASTReader that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
void StartedDeserializing() override;
- /// \brief Notify ASTReader that we finished the deserialization of
+ /// Notify ASTReader that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
void FinishedDeserializing() override;
- /// \brief Function that will be invoked when we begin parsing a new
+ /// Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
/// This function will provide all of the external definitions to
/// the ASTConsumer.
void StartTranslationUnit(ASTConsumer *Consumer) override;
- /// \brief Print some statistics about AST usage.
+ /// Print some statistics about AST usage.
void PrintStats() override;
- /// \brief Dump information about the AST reader to standard error.
+ /// Dump information about the AST reader to standard error.
void dump();
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
- /// \brief Initialize the semantic source with the Sema instance
+ /// Initialize the semantic source with the Sema instance
/// being used to perform semantic analysis on the abstract syntax
/// tree.
void InitializeSema(Sema &S) override;
- /// \brief Inform the semantic consumer that Sema is no longer available.
+ /// Inform the semantic consumer that Sema is no longer available.
void ForgetSema() override { SemaObj = nullptr; }
- /// \brief Retrieve the IdentifierInfo for the named identifier.
+ /// Retrieve the IdentifierInfo for the named identifier.
///
/// This routine builds a new IdentifierInfo for the given identifier. If any
/// declarations with this name are visible from translation unit scope, their
@@ -1944,11 +1962,11 @@ public:
/// chain of the identifier.
IdentifierInfo *get(StringRef Name) override;
- /// \brief Retrieve an iterator into the set of all identifiers
+ /// Retrieve an iterator into the set of all identifiers
/// in all loaded AST files.
IdentifierIterator *getIdentifiers() override;
- /// \brief Load the contents of the global method pool for a given
+ /// Load the contents of the global method pool for a given
/// selector.
void ReadMethodPool(Selector Sel) override;
@@ -1956,7 +1974,7 @@ public:
/// selector if necessary.
void updateOutOfDateSelector(Selector Sel) override;
- /// \brief Load the set of namespaces that are known to the external source,
+ /// Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
void ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces) override;
@@ -1998,7 +2016,7 @@ public:
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
&LPTMap) override;
- /// \brief Load a selector from disk, registering its ID if it exists.
+ /// Load a selector from disk, registering its ID if it exists.
void LoadSelector(Selector Sel);
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
@@ -2006,10 +2024,10 @@ public:
const SmallVectorImpl<uint32_t> &DeclIDs,
SmallVectorImpl<Decl *> *Decls = nullptr);
- /// \brief Report a diagnostic.
+ /// Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID) const;
- /// \brief Report a diagnostic.
+ /// Report a diagnostic.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const;
IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID);
@@ -2033,47 +2051,49 @@ public:
void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo);
- /// \brief Retrieve the macro with the given ID.
+ /// Retrieve the macro with the given ID.
MacroInfo *getMacro(serialization::MacroID ID);
- /// \brief Retrieve the global macro ID corresponding to the given local
+ /// Retrieve the global macro ID corresponding to the given local
/// ID within the given module file.
serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID);
- /// \brief Read the source location entry with index ID.
+ /// Read the source location entry with index ID.
bool ReadSLocEntry(int ID) override;
- /// \brief Retrieve the module import location and module name for the
+ /// Retrieve the module import location and module name for the
/// given source manager entry ID.
std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override;
- /// \brief Retrieve the global submodule ID given a module and its local ID
+ /// Retrieve the global submodule ID given a module and its local ID
/// number.
- serialization::SubmoduleID
+ serialization::SubmoduleID
getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID);
- /// \brief Retrieve the submodule that corresponds to a global submodule ID.
+ /// Retrieve the submodule that corresponds to a global submodule ID.
///
Module *getSubmodule(serialization::SubmoduleID GlobalID);
- /// \brief Retrieve the module that corresponds to the given module ID.
+ /// Retrieve the module that corresponds to the given module ID.
///
/// Note: overrides method in ExternalASTSource
Module *getModule(unsigned ID) override;
- /// \brief Retrieve the module file with a given local ID within the specified
+ bool DeclIsFromPCHWithObjectFile(const Decl *D) override;
+
+ /// Retrieve the module file with a given local ID within the specified
/// ModuleFile.
ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID);
- /// \brief Get an ID for the given module file.
+ /// Get an ID for the given module file.
unsigned getModuleFileID(ModuleFile *M);
- /// \brief Return a descriptor for the corresponding module.
+ /// Return a descriptor for the corresponding module.
llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
ExtKind hasExternalDefinitions(const Decl *D) override;
- /// \brief Retrieve a selector from the given module with its local ID
+ /// Retrieve a selector from the given module with its local ID
/// number.
Selector getLocalSelector(ModuleFile &M, unsigned LocalID);
@@ -2086,12 +2106,12 @@ public:
return getLocalSelector(M, Record[Idx++]);
}
- /// \brief Retrieve the global selector ID that corresponds to this
+ /// Retrieve the global selector ID that corresponds to this
/// the local selector ID in a given module.
serialization::SelectorID getGlobalSelectorID(ModuleFile &F,
unsigned LocalID) const;
- /// \brief Read a declaration name.
+ /// Read a declaration name.
DeclarationName ReadDeclarationName(ModuleFile &F,
const RecordData &Record, unsigned &Idx);
void ReadDeclarationNameLoc(ModuleFile &F,
@@ -2111,54 +2131,54 @@ public:
const RecordData &Record,
unsigned &Idx);
- /// \brief Read a template name.
+ /// Read a template name.
TemplateName ReadTemplateName(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
- /// \brief Read a template argument.
+ /// Read a template argument.
TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record,
unsigned &Idx,
bool Canonicalize = false);
- /// \brief Read a template parameter list.
+ /// Read a template parameter list.
TemplateParameterList *ReadTemplateParameterList(ModuleFile &F,
const RecordData &Record,
unsigned &Idx);
- /// \brief Read a template argument array.
+ /// Read a template argument array.
void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
ModuleFile &F, const RecordData &Record,
unsigned &Idx, bool Canonicalize = false);
- /// \brief Read a UnresolvedSet structure.
+ /// Read a UnresolvedSet structure.
void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
const RecordData &Record, unsigned &Idx);
- /// \brief Read a C++ base specifier.
+ /// Read a C++ base specifier.
CXXBaseSpecifier ReadCXXBaseSpecifier(ModuleFile &F,
const RecordData &Record,unsigned &Idx);
- /// \brief Read a CXXCtorInitializer array.
+ /// Read a CXXCtorInitializer array.
CXXCtorInitializer **
ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
- /// \brief Read the contents of a CXXCtorInitializer array.
+ /// Read the contents of a CXXCtorInitializer array.
CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
- /// \brief Read a source location from raw form and return it in its
+ /// Read a source location from raw form and return it in its
/// originating module file's source location space.
SourceLocation ReadUntranslatedSourceLocation(uint32_t Raw) const {
return SourceLocation::getFromRawEncoding((Raw >> 1) | (Raw << 31));
}
- /// \brief Read a source location from raw form.
+ /// Read a source location from raw form.
SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, uint32_t Raw) const {
SourceLocation Loc = ReadUntranslatedSourceLocation(Raw);
return TranslateSourceLocation(ModuleFile, Loc);
}
- /// \brief Translate a source location from another module file's source
+ /// Translate a source location from another module file's source
/// location space into ours.
SourceLocation TranslateSourceLocation(ModuleFile &ModuleFile,
SourceLocation Loc) const {
@@ -2171,59 +2191,59 @@ public:
return Loc.getLocWithOffset(Remap);
}
- /// \brief Read a source location.
+ /// Read a source location.
SourceLocation ReadSourceLocation(ModuleFile &ModuleFile,
const RecordDataImpl &Record,
unsigned &Idx) {
return ReadSourceLocation(ModuleFile, Record[Idx++]);
}
- /// \brief Read a source range.
+ /// Read a source range.
SourceRange ReadSourceRange(ModuleFile &F,
const RecordData &Record, unsigned &Idx);
- /// \brief Read an integral value
+ /// Read an integral value
llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx);
- /// \brief Read a signed integral value
+ /// Read a signed integral value
llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
- /// \brief Read a floating-point value
+ /// Read a floating-point value
llvm::APFloat ReadAPFloat(const RecordData &Record,
const llvm::fltSemantics &Sem, unsigned &Idx);
- // \brief Read a string
+ // Read a string
static std::string ReadString(const RecordData &Record, unsigned &Idx);
- // \brief Skip a string
+ // Skip a string
static void SkipString(const RecordData &Record, unsigned &Idx) {
Idx += Record[Idx] + 1;
}
- // \brief Read a path
+ // Read a path
std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);
- // \brief Skip a path
+ // Skip a path
static void SkipPath(const RecordData &Record, unsigned &Idx) {
SkipString(Record, Idx);
}
- /// \brief Read a version tuple.
+ /// Read a version tuple.
static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);
CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
- /// \brief Reads attributes from the current stream position.
+ /// Reads attributes from the current stream position.
void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs);
- /// \brief Reads a statement.
+ /// Reads a statement.
Stmt *ReadStmt(ModuleFile &F);
- /// \brief Reads an expression.
+ /// Reads an expression.
Expr *ReadExpr(ModuleFile &F);
- /// \brief Reads a sub-statement operand during statement reading.
+ /// Reads a sub-statement operand during statement reading.
Stmt *ReadSubStmt() {
assert(ReadingKind == Read_Stmt &&
"Should be called only during statement reading!");
@@ -2233,21 +2253,21 @@ public:
return StmtStack.pop_back_val();
}
- /// \brief Reads a sub-expression operand during statement reading.
+ /// Reads a sub-expression operand during statement reading.
Expr *ReadSubExpr();
- /// \brief Reads a token out of a record.
+ /// Reads a token out of a record.
Token ReadToken(ModuleFile &M, const RecordDataImpl &Record, unsigned &Idx);
- /// \brief Reads the macro record located at the given offset.
+ /// Reads the macro record located at the given offset.
MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset);
- /// \brief Determine the global preprocessed entity ID that corresponds to
+ /// Determine the global preprocessed entity ID that corresponds to
/// the given local ID within the given module.
serialization::PreprocessedEntityID
getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const;
- /// \brief Add a macro to deserialize its macro directive history.
+ /// Add a macro to deserialize its macro directive history.
///
/// \param II The name of the macro.
/// \param M The module file.
@@ -2256,56 +2276,56 @@ public:
void addPendingMacro(IdentifierInfo *II, ModuleFile *M,
uint64_t MacroDirectivesOffset);
- /// \brief Read the set of macros defined by this external macro source.
+ /// Read the set of macros defined by this external macro source.
void ReadDefinedMacros() override;
- /// \brief Update an out-of-date identifier.
+ /// Update an out-of-date identifier.
void updateOutOfDateIdentifier(IdentifierInfo &II) override;
- /// \brief Note that this identifier is up-to-date.
+ /// Note that this identifier is up-to-date.
void markIdentifierUpToDate(IdentifierInfo *II);
- /// \brief Load all external visible decls in the given DeclContext.
+ /// Load all external visible decls in the given DeclContext.
void completeVisibleDeclsMap(const DeclContext *DC) override;
- /// \brief Retrieve the AST context that this AST reader supplements.
+ /// Retrieve the AST context that this AST reader supplements.
ASTContext &getContext() {
assert(ContextObj && "requested AST context when not loading AST");
return *ContextObj;
}
- // \brief Contains the IDs for declarations that were requested before we have
+ // Contains the IDs for declarations that were requested before we have
// access to a Sema object.
SmallVector<uint64_t, 16> PreloadedDeclIDs;
- /// \brief Retrieve the semantic analysis object used to analyze the
+ /// Retrieve the semantic analysis object used to analyze the
/// translation unit in which the precompiled header is being
/// imported.
Sema *getSema() { return SemaObj; }
- /// \brief Get the identifier resolver used for name lookup / updates
+ /// Get the identifier resolver used for name lookup / updates
/// in the translation unit scope. We have one of these even if we don't
/// have a Sema object.
IdentifierResolver &getIdResolver();
- /// \brief Retrieve the identifier table associated with the
+ /// Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &getIdentifierTable();
- /// \brief Record that the given ID maps to the given switch-case
+ /// Record that the given ID maps to the given switch-case
/// statement.
void RecordSwitchCaseID(SwitchCase *SC, unsigned ID);
- /// \brief Retrieve the switch-case statement with the given ID.
+ /// Retrieve the switch-case statement with the given ID.
SwitchCase *getSwitchCaseWithID(unsigned ID);
void ClearSwitchCaseIDs();
- /// \brief Cursors for comments blocks.
+ /// Cursors for comments blocks.
SmallVector<std::pair<llvm::BitstreamCursor,
serialization::ModuleFile *>, 8> CommentsCursors;
- /// \brief Loads comments ranges.
+ /// Loads comments ranges.
void ReadComments() override;
/// Visit all the input files of the given module file.
@@ -2323,7 +2343,7 @@ public:
bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
};
-/// \brief An object for streaming information from a record.
+/// An object for streaming information from a record.
class ASTRecordReader {
using ModuleFile = serialization::ModuleFile;
@@ -2339,56 +2359,56 @@ public:
/// Construct an ASTRecordReader that uses the default encoding scheme.
ASTRecordReader(ASTReader &Reader, ModuleFile &F) : Reader(&Reader), F(&F) {}
- /// \brief Reads a record with id AbbrevID from Cursor, resetting the
+ /// Reads a record with id AbbrevID from Cursor, resetting the
/// internal state.
unsigned readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID);
- /// \brief Is this a module file for a module (rather than a PCH or similar).
+ /// Is this a module file for a module (rather than a PCH or similar).
bool isModule() const { return F->isModule(); }
- /// \brief Retrieve the AST context that this AST reader supplements.
+ /// Retrieve the AST context that this AST reader supplements.
ASTContext &getContext() { return Reader->getContext(); }
- /// \brief The current position in this record.
+ /// The current position in this record.
unsigned getIdx() const { return Idx; }
- /// \brief The length of this record.
+ /// The length of this record.
size_t size() const { return Record.size(); }
- /// \brief An arbitrary index in this record.
+ /// An arbitrary index in this record.
const uint64_t &operator[](size_t N) { return Record[N]; }
- /// \brief The last element in this record.
+ /// 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
+ /// 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.
+ /// Returns the current value in this record, without advancing.
const uint64_t &peekInt() { return Record[Idx]; }
- /// \brief Skips the specified number of values.
+ /// Skips the specified number of values.
void skipInts(unsigned N) { Idx += N; }
- /// \brief Retrieve the global submodule ID its local ID number.
+ /// Retrieve the global submodule ID its local ID number.
serialization::SubmoduleID
getGlobalSubmoduleID(unsigned LocalID) {
return Reader->getGlobalSubmoduleID(*F, LocalID);
}
- /// \brief Retrieve the submodule that corresponds to a global submodule ID.
+ /// Retrieve the submodule that corresponds to a global submodule ID.
Module *getSubmodule(serialization::SubmoduleID GlobalID) {
return Reader->getSubmodule(GlobalID);
}
- /// \brief Read the record that describes the lexical contents of a DC.
+ /// Read the record that describes the lexical contents of a DC.
bool readLexicalDeclContextStorage(uint64_t Offset, DeclContext *DC) {
return Reader->ReadLexicalDeclContextStorage(*F, F->DeclsCursor, Offset,
DC);
}
- /// \brief Read the record that describes the visible contents of a DC.
+ /// Read the record that describes the visible contents of a DC.
bool readVisibleDeclContextStorage(uint64_t Offset,
serialization::DeclID ID) {
return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset,
@@ -2400,24 +2420,24 @@ public:
return Reader->readExceptionSpec(*F, ExceptionStorage, ESI, Record, Idx);
}
- /// \brief Get the global offset corresponding to a local offset.
+ /// Get the global offset corresponding to a local offset.
uint64_t getGlobalBitOffset(uint32_t LocalOffset) {
return Reader->getGlobalBitOffset(*F, LocalOffset);
}
- /// \brief Reads a statement.
+ /// Reads a statement.
Stmt *readStmt() { return Reader->ReadStmt(*F); }
- /// \brief Reads an expression.
+ /// Reads an expression.
Expr *readExpr() { return Reader->ReadExpr(*F); }
- /// \brief Reads a sub-statement operand during statement reading.
+ /// Reads a sub-statement operand during statement reading.
Stmt *readSubStmt() { return Reader->ReadSubStmt(); }
- /// \brief Reads a sub-expression operand during statement reading.
+ /// Reads a sub-expression operand during statement reading.
Expr *readSubExpr() { return Reader->ReadSubExpr(); }
- /// \brief Reads a declaration with the given local ID in the given module.
+ /// Reads a declaration with the given local ID in the given module.
///
/// \returns The requested declaration, casted to the given return type.
template<typename T>
@@ -2425,14 +2445,14 @@ public:
return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
}
- /// \brief Reads a TemplateArgumentLocInfo appropriate for the
+ /// Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind, advancing Idx.
TemplateArgumentLocInfo
getTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
return Reader->GetTemplateArgumentLocInfo(*F, Kind, Record, Idx);
}
- /// \brief Reads a TemplateArgumentLoc, advancing Idx.
+ /// Reads a TemplateArgumentLoc, advancing Idx.
TemplateArgumentLoc
readTemplateArgumentLoc() {
return Reader->ReadTemplateArgumentLoc(*F, Record, Idx);
@@ -2443,35 +2463,40 @@ public:
return Reader->ReadASTTemplateArgumentListInfo(*F, Record, Idx);
}
- /// \brief Reads a declarator info from the given record, advancing Idx.
+ /// Reads a declarator info from the given record, advancing Idx.
TypeSourceInfo *getTypeSourceInfo() {
return Reader->GetTypeSourceInfo(*F, Record, Idx);
}
- /// \brief Map a local type ID within a given AST file to a global type ID.
+ /// Reads the location information for a type.
+ void readTypeLoc(TypeLoc TL) {
+ return Reader->ReadTypeLoc(*F, Record, Idx, TL);
+ }
+
+ /// Map a local type ID within a given AST file to a global type ID.
serialization::TypeID getGlobalTypeID(unsigned LocalID) const {
return Reader->getGlobalTypeID(*F, LocalID);
}
- /// \brief Read a type from the current position in the record.
+ /// Read a type from the current position in the record.
QualType readType() {
return Reader->readType(*F, Record, Idx);
}
- /// \brief Reads a declaration ID from the given position in this record.
+ /// Reads a declaration ID from the given position in this record.
///
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID readDeclID() {
return Reader->ReadDeclID(*F, Record, Idx);
}
- /// \brief Reads a declaration from the given position in a record in the
+ /// Reads a declaration from the given position in a record in the
/// given module, advancing Idx.
Decl *readDecl() {
return Reader->ReadDecl(*F, Record, Idx);
}
- /// \brief Reads a declaration from the given position in the record,
+ /// Reads a declaration from the given position in the record,
/// advancing Idx.
///
/// \returns The declaration read from this location, casted to the given
@@ -2485,12 +2510,12 @@ public:
return Reader->GetIdentifierInfo(*F, Record, Idx);
}
- /// \brief Read a selector from the Record, advancing Idx.
+ /// Read a selector from the Record, advancing Idx.
Selector readSelector() {
return Reader->ReadSelector(*F, Record, Idx);
}
- /// \brief Read a declaration name, advancing Idx.
+ /// Read a declaration name, advancing Idx.
DeclarationName readDeclarationName() {
return Reader->ReadDeclarationName(*F, Record, Idx);
}
@@ -2513,39 +2538,39 @@ public:
return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx);
}
- /// \brief Read a template name, advancing Idx.
+ /// Read a template name, advancing Idx.
TemplateName readTemplateName() {
return Reader->ReadTemplateName(*F, Record, Idx);
}
- /// \brief Read a template argument, advancing Idx.
+ /// Read a template argument, advancing Idx.
TemplateArgument readTemplateArgument(bool Canonicalize = false) {
return Reader->ReadTemplateArgument(*F, Record, Idx, Canonicalize);
}
- /// \brief Read a template parameter list, advancing Idx.
+ /// Read a template parameter list, advancing Idx.
TemplateParameterList *readTemplateParameterList() {
return Reader->ReadTemplateParameterList(*F, Record, Idx);
}
- /// \brief Read a template argument array, advancing Idx.
+ /// Read a template argument array, advancing Idx.
void readTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
bool Canonicalize = false) {
return Reader->ReadTemplateArgumentList(TemplArgs, *F, Record, Idx,
Canonicalize);
}
- /// \brief Read a UnresolvedSet structure, advancing Idx.
+ /// Read a UnresolvedSet structure, advancing Idx.
void readUnresolvedSet(LazyASTUnresolvedSet &Set) {
return Reader->ReadUnresolvedSet(*F, Set, Record, Idx);
}
- /// \brief Read a C++ base specifier, advancing Idx.
+ /// Read a C++ base specifier, advancing Idx.
CXXBaseSpecifier readCXXBaseSpecifier() {
return Reader->ReadCXXBaseSpecifier(*F, Record, Idx);
}
- /// \brief Read a CXXCtorInitializer array, advancing Idx.
+ /// Read a CXXCtorInitializer array, advancing Idx.
CXXCtorInitializer **readCXXCtorInitializers() {
return Reader->ReadCXXCtorInitializers(*F, Record, Idx);
}
@@ -2554,52 +2579,52 @@ public:
return Reader->ReadCXXTemporary(*F, Record, Idx);
}
- /// \brief Read a source location, advancing Idx.
+ /// Read a source location, advancing Idx.
SourceLocation readSourceLocation() {
return Reader->ReadSourceLocation(*F, Record, Idx);
}
- /// \brief Read a source range, advancing Idx.
+ /// Read a source range, advancing Idx.
SourceRange readSourceRange() {
return Reader->ReadSourceRange(*F, Record, Idx);
}
- /// \brief Read an integral value, advancing Idx.
+ /// Read an integral value, advancing Idx.
llvm::APInt readAPInt() {
return Reader->ReadAPInt(Record, Idx);
}
- /// \brief Read a signed integral value, advancing Idx.
+ /// Read a signed integral value, advancing Idx.
llvm::APSInt readAPSInt() {
return Reader->ReadAPSInt(Record, Idx);
}
- /// \brief Read a floating-point value, advancing Idx.
+ /// Read a floating-point value, advancing Idx.
llvm::APFloat readAPFloat(const llvm::fltSemantics &Sem) {
return Reader->ReadAPFloat(Record, Sem,Idx);
}
- /// \brief Read a string, advancing Idx.
+ /// Read a string, advancing Idx.
std::string readString() {
return Reader->ReadString(Record, Idx);
}
- /// \brief Read a path, advancing Idx.
+ /// Read a path, advancing Idx.
std::string readPath() {
return Reader->ReadPath(*F, Record, Idx);
}
- /// \brief Read a version tuple, advancing Idx.
+ /// Read a version tuple, advancing Idx.
VersionTuple readVersionTuple() {
return ASTReader::ReadVersionTuple(Record, Idx);
}
- /// \brief Reads attributes from the current stream position, advancing Idx.
+ /// Reads attributes from the current stream position, advancing Idx.
void readAttributes(AttrVec &Attrs) {
return Reader->ReadAttributes(*this, Attrs);
}
- /// \brief Reads a token out of a record, advancing Idx.
+ /// Reads a token out of a record, advancing Idx.
Token readToken() {
return Reader->ReadToken(*F, Record, Idx);
}
@@ -2608,17 +2633,17 @@ public:
Reader->RecordSwitchCaseID(SC, ID);
}
- /// \brief Retrieve the switch-case statement with the given ID.
+ /// Retrieve the switch-case statement with the given ID.
SwitchCase *getSwitchCaseWithID(unsigned ID) {
return Reader->getSwitchCaseWithID(ID);
}
};
-/// \brief Helper class that saves the current stream position and
+/// Helper class that saves the current stream position and
/// then restores it when destroyed.
struct SavedStreamPosition {
explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor)
- : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {}
+ : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {}
~SavedStreamPosition() {
Cursor.JumpToBit(Offset);
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
index 9437bf7f2c9f..7ff5d65bd7d0 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -93,9 +93,8 @@ class SwitchCase;
class TemplateParameterList;
class Token;
class TypeSourceInfo;
-class VersionTuple;
-/// \brief Writes an AST file containing the contents of a translation unit.
+/// Writes an AST file containing the contents of a translation unit.
///
/// The ASTWriter class produces a bitstream containing the serialized
/// representation of a given abstract syntax tree and its supporting
@@ -114,7 +113,7 @@ public:
using RecordDataRef = ArrayRef<uint64_t>;
private:
- /// \brief Map that provides the ID numbers of each type within the
+ /// Map that provides the ID numbers of each type within the
/// output stream, plus those deserialized from a chained PCH.
///
/// The ID numbers of types are consecutive (in order of discovery)
@@ -126,52 +125,52 @@ private:
using TypeIdxMap = llvm::DenseMap<QualType, serialization::TypeIdx,
serialization::UnsafeQualTypeDenseMapInfo>;
- /// \brief The bitstream writer used to emit this precompiled header.
+ /// The bitstream writer used to emit this precompiled header.
llvm::BitstreamWriter &Stream;
/// The buffer associated with the bitstream.
const SmallVectorImpl<char> &Buffer;
- /// \brief The PCM manager which manages memory buffers for pcm files.
+ /// The PCM manager which manages memory buffers for pcm files.
MemoryBufferCache &PCMCache;
- /// \brief The ASTContext we're writing.
+ /// The ASTContext we're writing.
ASTContext *Context = nullptr;
- /// \brief The preprocessor we're writing.
+ /// The preprocessor we're writing.
Preprocessor *PP = nullptr;
- /// \brief The reader of existing AST files, if we're chaining.
+ /// The reader of existing AST files, if we're chaining.
ASTReader *Chain = nullptr;
- /// \brief The module we're currently writing, if any.
+ /// The module we're currently writing, if any.
Module *WritingModule = nullptr;
- /// \brief The base directory for any relative paths we emit.
+ /// The base directory for any relative paths we emit.
std::string BaseDirectory;
- /// \brief Indicates whether timestamps should be written to the produced
+ /// Indicates whether timestamps should be written to the produced
/// module file. This is the case for files implicitly written to the
/// module cache, where we need the timestamps to determine if the module
/// file is up to date, but not otherwise.
bool IncludeTimestamps;
- /// \brief Indicates when the AST writing is actively performing
+ /// Indicates when the AST writing is actively performing
/// serialization, rather than just queueing updates.
bool WritingAST = false;
- /// \brief Indicates that we are done serializing the collection of decls
+ /// Indicates that we are done serializing the collection of decls
/// and types to emit.
bool DoneWritingDeclsAndTypes = false;
- /// \brief Indicates that the AST contained compiler errors.
+ /// Indicates that the AST contained compiler errors.
bool ASTHasCompilerErrors = false;
- /// \brief Mapping from input file entries to the index into the
+ /// Mapping from input file entries to the index into the
/// offset table where information about that input file is stored.
llvm::DenseMap<const FileEntry *, uint32_t> InputFileIDs;
- /// \brief Stores a declaration or a type to be written to the AST file.
+ /// Stores a declaration or a type to be written to the AST file.
class DeclOrType {
public:
DeclOrType(Decl *D) : Stored(D), IsType(false) {}
@@ -195,16 +194,16 @@ private:
bool IsType;
};
- /// \brief The declarations and types to emit.
+ /// The declarations and types to emit.
std::queue<DeclOrType> DeclTypesToEmit;
- /// \brief The first ID number we can use for our own declarations.
+ /// The first ID number we can use for our own declarations.
serialization::DeclID FirstDeclID = serialization::NUM_PREDEF_DECL_IDS;
- /// \brief The decl ID that will be assigned to the next new decl.
+ /// The decl ID that will be assigned to the next new decl.
serialization::DeclID NextDeclID = FirstDeclID;
- /// \brief Map that provides the ID numbers of each declaration within
+ /// Map that provides the ID numbers of each declaration within
/// the output stream, as well as those deserialized from a chained PCH.
///
/// The ID numbers of declarations are consecutive (in order of
@@ -212,35 +211,35 @@ private:
/// unit, while 0 is reserved for NULL.
llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs;
- /// \brief Offset of each declaration in the bitstream, indexed by
+ /// Offset of each declaration in the bitstream, indexed by
/// the declaration's ID.
std::vector<serialization::DeclOffset> DeclOffsets;
- /// \brief Sorted (by file offset) vector of pairs of file offset/DeclID.
+ /// Sorted (by file offset) vector of pairs of file offset/DeclID.
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
+ /// 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;
};
using FileDeclIDsTy = llvm::DenseMap<FileID, DeclIDInFileInfo *>;
- /// \brief Map from file SLocEntries to info about the file-level declarations
+ /// Map from file SLocEntries to info about the file-level declarations
/// that it contains.
FileDeclIDsTy FileDeclIDs;
void associateDeclWithFile(const Decl *D, serialization::DeclID);
- /// \brief The first ID number we can use for our own types.
+ /// The first ID number we can use for our own types.
serialization::TypeID FirstTypeID = serialization::NUM_PREDEF_TYPE_IDS;
- /// \brief The type ID that will be assigned to the next new type.
+ /// The type ID that will be assigned to the next new type.
serialization::TypeID NextTypeID = FirstTypeID;
- /// \brief Map that provides the ID numbers of each type within the
+ /// Map that provides the ID numbers of each type within the
/// output stream, plus those deserialized from a chained PCH.
///
/// The ID numbers of types are consecutive (in order of discovery)
@@ -251,17 +250,17 @@ private:
/// Keys in the map never have const/volatile qualifiers.
TypeIdxMap TypeIdxs;
- /// \brief Offset of each type in the bitstream, indexed by
+ /// Offset of each type in the bitstream, indexed by
/// the type's ID.
std::vector<uint32_t> TypeOffsets;
- /// \brief The first ID number we can use for our own identifiers.
+ /// The first ID number we can use for our own identifiers.
serialization::IdentID FirstIdentID = serialization::NUM_PREDEF_IDENT_IDS;
- /// \brief The identifier ID that will be assigned to the next new identifier.
+ /// The identifier ID that will be assigned to the next new identifier.
serialization::IdentID NextIdentID = FirstIdentID;
- /// \brief Map that provides the ID numbers of each identifier in
+ /// Map that provides the ID numbers of each identifier in
/// the output stream.
///
/// The ID numbers for identifiers are consecutive (in order of
@@ -269,13 +268,13 @@ private:
/// IdentifierInfo.
llvm::MapVector<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
- /// \brief The first ID number we can use for our own macros.
+ /// The first ID number we can use for our own macros.
serialization::MacroID FirstMacroID = serialization::NUM_PREDEF_MACRO_IDS;
- /// \brief The identifier ID that will be assigned to the next new identifier.
+ /// The identifier ID that will be assigned to the next new identifier.
serialization::MacroID NextMacroID = FirstMacroID;
- /// \brief Map that provides the ID numbers of each macro.
+ /// Map that provides the ID numbers of each macro.
llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs;
struct MacroInfoToEmitData {
@@ -284,7 +283,7 @@ private:
serialization::MacroID ID;
};
- /// \brief The macro infos to emit.
+ /// The macro infos to emit.
std::vector<MacroInfoToEmitData> MacroInfosToEmit;
llvm::DenseMap<const IdentifierInfo *, uint64_t> IdentMacroDirectivesOffsetMap;
@@ -292,46 +291,46 @@ private:
/// @name FlushStmt Caches
/// @{
- /// \brief Set of parent Stmts for the currently serializing sub-stmt.
+ /// Set of parent Stmts for the currently serializing sub-stmt.
llvm::DenseSet<Stmt *> ParentStmts;
- /// \brief Offsets of sub-stmts already serialized. The offset points
+ /// Offsets of sub-stmts already serialized. The offset points
/// just after the stmt record.
llvm::DenseMap<Stmt *, uint64_t> SubStmtEntries;
/// @}
- /// \brief Offsets of each of the identifier IDs into the identifier
+ /// Offsets of each of the identifier IDs into the identifier
/// table.
std::vector<uint32_t> IdentifierOffsets;
- /// \brief The first ID number we can use for our own submodules.
+ /// The first ID number we can use for our own submodules.
serialization::SubmoduleID FirstSubmoduleID =
serialization::NUM_PREDEF_SUBMODULE_IDS;
- /// \brief The submodule ID that will be assigned to the next new submodule.
+ /// The submodule ID that will be assigned to the next new submodule.
serialization::SubmoduleID NextSubmoduleID = FirstSubmoduleID;
- /// \brief The first ID number we can use for our own selectors.
+ /// The first ID number we can use for our own selectors.
serialization::SelectorID FirstSelectorID =
serialization::NUM_PREDEF_SELECTOR_IDS;
- /// \brief The selector ID that will be assigned to the next new selector.
+ /// The selector ID that will be assigned to the next new selector.
serialization::SelectorID NextSelectorID = FirstSelectorID;
- /// \brief Map that provides the ID numbers of each Selector.
+ /// Map that provides the ID numbers of each Selector.
llvm::MapVector<Selector, serialization::SelectorID> SelectorIDs;
- /// \brief Offset of each selector within the method pool/selector
+ /// Offset of each selector within the method pool/selector
/// table, indexed by the Selector ID (-1).
std::vector<uint32_t> SelectorOffsets;
- /// \brief Mapping from macro definitions (as they occur in the preprocessing
+ /// Mapping from macro definitions (as they occur in the preprocessing
/// record) to the macro IDs.
llvm::DenseMap<const MacroDefinitionRecord *,
serialization::PreprocessedEntityID> MacroDefinitions;
- /// \brief Cache of indices of anonymous declarations within their lexical
+ /// Cache of indices of anonymous declarations within their lexical
/// contexts.
llvm::DenseMap<const Decl *, unsigned> AnonymousDeclarationNumbers;
@@ -376,17 +375,17 @@ private:
using UpdateRecord = SmallVector<DeclUpdate, 1>;
using DeclUpdateMap = llvm::MapVector<const Decl *, UpdateRecord>;
- /// \brief Mapping from declarations that came from a chained PCH to the
+ /// Mapping from declarations that came from a chained PCH to the
/// record containing modifications to them.
DeclUpdateMap DeclUpdates;
using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
- /// \brief Map of first declarations from a chained PCH that point to the
+ /// Map of first declarations from a chained PCH that point to the
/// most recent declarations in another PCH.
FirstLatestDeclMap FirstLatestDecls;
- /// \brief Declarations encountered that might be external
+ /// Declarations encountered that might be external
/// definitions.
///
/// We keep track of external definitions and other 'interesting' declarations
@@ -400,7 +399,7 @@ private:
SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
SmallVector<uint64_t, 16> ModularCodegenDecls;
- /// \brief DeclContexts that have received extensions since their serialized
+ /// DeclContexts that have received extensions since their serialized
/// form.
///
/// For namespaces, when we're chaining and encountering a namespace, we check
@@ -409,52 +408,52 @@ private:
/// it.
llvm::SmallSetVector<const DeclContext *, 16> UpdatedDeclContexts;
- /// \brief Keeps track of declarations that we must emit, even though we're
+ /// Keeps track of declarations that we must emit, even though we're
/// not guaranteed to be able to find them by walking the AST starting at the
/// translation unit.
SmallVector<const Decl *, 16> DeclsToEmitEvenIfUnreferenced;
- /// \brief The set of Objective-C class that have categories we
+ /// The set of Objective-C class that have categories we
/// should serialize.
llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories;
-
- /// \brief The set of declarations that may have redeclaration chains that
+
+ /// The set of declarations that may have redeclaration chains that
/// need to be serialized.
llvm::SmallVector<const Decl *, 16> Redeclarations;
- /// \brief A cache of the first local declaration for "interesting"
+ /// A cache of the first local declaration for "interesting"
/// redeclaration chains.
llvm::DenseMap<const Decl *, const Decl *> FirstLocalDeclCache;
-
- /// \brief Mapping from SwitchCase statements to IDs.
+
+ /// Mapping from SwitchCase statements to IDs.
llvm::DenseMap<SwitchCase *, unsigned> SwitchCaseIDs;
- /// \brief The number of statements written to the AST file.
+ /// The number of statements written to the AST file.
unsigned NumStatements = 0;
- /// \brief The number of macros written to the AST file.
+ /// The number of macros written to the AST file.
unsigned NumMacros = 0;
- /// \brief The number of lexical declcontexts written to the AST
+ /// The number of lexical declcontexts written to the AST
/// file.
unsigned NumLexicalDeclContexts = 0;
- /// \brief The number of visible declcontexts written to the AST
+ /// The number of visible declcontexts written to the AST
/// file.
unsigned NumVisibleDeclContexts = 0;
- /// \brief A mapping from each known submodule to its ID number, which will
+ /// A mapping from each known submodule to its ID number, which will
/// be a positive integer.
llvm::DenseMap<Module *, unsigned> SubmoduleIDs;
- /// \brief A list of the module file extension writers.
+ /// A list of the module file extension writers.
std::vector<std::unique_ptr<ModuleFileExtensionWriter>>
ModuleFileExtensionWriters;
- /// \brief Retrieve or create a submodule ID for this module.
+ /// Retrieve or create a submodule ID for this module.
unsigned getSubmoduleID(Module *Mod);
- /// \brief Write the given subexpression to the bitstream.
+ /// Write the given subexpression to the bitstream.
void WriteSubStmt(Stmt *S);
void WriteBlockInfoBlock();
@@ -476,7 +475,7 @@ private:
void WriteHeaderSearch(const HeaderSearch &HS);
void WritePreprocessorDetail(PreprocessingRecord &PPRec);
void WriteSubmodules(Module *WritingModule);
-
+
void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
bool isModule);
@@ -540,7 +539,7 @@ private:
Module *WritingModule);
public:
- /// \brief Create a new precompiled header writer that outputs to
+ /// Create a new precompiled header writer that outputs to
/// the given bitstream.
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
MemoryBufferCache &PCMCache,
@@ -550,12 +549,12 @@ public:
const LangOptions &getLangOpts() const;
- /// \brief Get a timestamp for output into the AST file. The actual timestamp
+ /// Get a timestamp for output into the AST file. The actual timestamp
/// of the specified file may be ignored if we have been instructed to not
/// include timestamps in the output file.
time_t getTimestampForOutput(const FileEntry *E) const;
- /// \brief Write a precompiled header for the given semantic analysis.
+ /// Write a precompiled header for the given semantic analysis.
///
/// \param SemaRef a reference to the semantic analysis object that processed
/// the AST to be written into the precompiled header.
@@ -573,46 +572,46 @@ public:
Module *WritingModule, StringRef isysroot,
bool hasErrors = false);
- /// \brief Emit a token.
+ /// Emit a token.
void AddToken(const Token &Tok, RecordDataImpl &Record);
- /// \brief Emit a source location.
+ /// Emit a source location.
void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record);
- /// \brief Emit a source range.
+ /// Emit a source range.
void AddSourceRange(SourceRange Range, RecordDataImpl &Record);
- /// \brief Emit a reference to an identifier.
+ /// Emit a reference to an identifier.
void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record);
- /// \brief Get the unique number used to refer to the given selector.
+ /// Get the unique number used to refer to the given selector.
serialization::SelectorID getSelectorRef(Selector Sel);
- /// \brief Get the unique number used to refer to the given identifier.
+ /// Get the unique number used to refer to the given identifier.
serialization::IdentID getIdentifierRef(const IdentifierInfo *II);
- /// \brief Get the unique number used to refer to the given macro.
+ /// Get the unique number used to refer to the given macro.
serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name);
- /// \brief Determine the ID of an already-emitted macro.
+ /// Determine the ID of an already-emitted macro.
serialization::MacroID getMacroID(MacroInfo *MI);
uint64_t getMacroDirectivesOffset(const IdentifierInfo *Name);
- /// \brief Emit a reference to a type.
+ /// Emit a reference to a type.
void AddTypeRef(QualType T, RecordDataImpl &Record);
- /// \brief Force a type to be emitted and get its ID.
+ /// Force a type to be emitted and get its ID.
serialization::TypeID GetOrCreateTypeID(QualType T);
- /// \brief Determine the type ID of an already-emitted type.
+ /// Determine the type ID of an already-emitted type.
serialization::TypeID getTypeID(QualType T) const;
- /// \brief Find the first local declaration of a given local redeclarable
+ /// Find the first local declaration of a given local redeclarable
/// decl.
const Decl *getFirstLocalDecl(const Decl *D);
- /// \brief Is this a local declaration (that is, one that will be written to
+ /// Is this a local declaration (that is, one that will be written to
/// our AST file)? This is the case for declarations that are neither imported
/// from another AST file nor predefined.
bool IsLocalDecl(const Decl *D) {
@@ -623,52 +622,52 @@ public:
I->second >= serialization::NUM_PREDEF_DECL_IDS);
};
- /// \brief Emit a reference to a declaration.
+ /// Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
- /// \brief Force a declaration to be emitted and get its ID.
+ /// Force a declaration to be emitted and get its ID.
serialization::DeclID GetDeclRef(const Decl *D);
- /// \brief Determine the declaration ID of an already-emitted
+ /// Determine the declaration ID of an already-emitted
/// declaration.
serialization::DeclID getDeclID(const Decl *D);
unsigned getAnonymousDeclarationNumber(const NamedDecl *D);
- /// \brief Add a string to the given record.
+ /// Add a string to the given record.
void AddString(StringRef Str, RecordDataImpl &Record);
- /// \brief Convert a path from this build process into one that is appropriate
+ /// Convert a path from this build process into one that is appropriate
/// for emission in the module file.
bool PreparePathForOutput(SmallVectorImpl<char> &Path);
- /// \brief Add a path to the given record.
+ /// Add a path to the given record.
void AddPath(StringRef Path, RecordDataImpl &Record);
- /// \brief Emit the current record with the given path as a blob.
+ /// Emit the current record with the given path as a blob.
void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
StringRef Path);
- /// \brief Add a version tuple to the given record
+ /// Add a version tuple to the given record
void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
- /// \brief Retrieve or create a submodule ID for this module, or return 0 if
+ /// Retrieve or create a submodule ID for this module, or return 0 if
/// the submodule is neither local (a submodle of the currently-written module)
/// nor from an imported module.
unsigned getLocalOrImportedSubmoduleID(Module *Mod);
- /// \brief Note that the identifier II occurs at the given offset
+ /// Note that the identifier II occurs at the given offset
/// within the identifier table.
void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset);
- /// \brief Note that the selector Sel occurs at the given offset
+ /// Note that the selector Sel occurs at the given offset
/// within the method pool/selector table.
void SetSelectorOffset(Selector Sel, uint32_t Offset);
- /// \brief Record an ID for the given switch-case statement.
+ /// Record an ID for the given switch-case statement.
unsigned RecordSwitchCaseID(SwitchCase *S);
- /// \brief Retrieve the ID for the given switch-case statement.
+ /// Retrieve the ID for the given switch-case statement.
unsigned getSwitchCaseID(SwitchCase *S);
void ClearSwitchCaseIDs();
@@ -743,21 +742,21 @@ private:
const RecordDecl *Record) override;
};
-/// \brief An object for streaming information to a record.
+/// An object for streaming information to a record.
class ASTRecordWriter {
ASTWriter *Writer;
ASTWriter::RecordDataImpl *Record;
- /// \brief Statements that we've encountered while serializing a
+ /// Statements that we've encountered while serializing a
/// declaration or type.
SmallVector<Stmt *, 16> StmtsToEmit;
- /// \brief Indices of record elements that describe offsets within the
+ /// Indices of record elements that describe offsets within the
/// bitcode. These will be converted to offsets relative to the current
/// record when emitted.
SmallVector<unsigned, 8> OffsetIndices;
- /// \brief Flush all of the statements and expressions that have
+ /// Flush all of the statements and expressions that have
/// been added to the queue via AddStmt().
void FlushStmts();
void FlushSubStmts();
@@ -787,10 +786,10 @@ public:
ASTRecordWriter(const ASTRecordWriter &) = delete;
ASTRecordWriter &operator=(const ASTRecordWriter &) = delete;
- /// \brief Extract the underlying record storage.
+ /// Extract the underlying record storage.
ASTWriter::RecordDataImpl &getRecordData() const { return *Record; }
- /// \brief Minimal vector-like interface.
+ /// Minimal vector-like interface.
/// @{
void push_back(uint64_t N) { Record->push_back(N); }
template<typename InputIterator>
@@ -802,7 +801,7 @@ public:
uint64_t &operator[](size_t N) { return (*Record)[N]; }
/// @}
- /// \brief Emit the record to the stream, followed by its substatements, and
+ /// Emit the record to the stream, followed by its substatements, and
/// return its offset.
// FIXME: Allow record producers to suggest Abbrevs.
uint64_t Emit(unsigned Code, unsigned Abbrev = 0) {
@@ -813,7 +812,7 @@ public:
return Offset;
}
- /// \brief Emit the record to the stream, preceded by its substatements.
+ /// Emit the record to the stream, preceded by its substatements.
uint64_t EmitStmt(unsigned Code, unsigned Abbrev = 0) {
FlushSubStmts();
PrepareToEmit(Writer->Stream.GetCurrentBitNo());
@@ -821,14 +820,14 @@ public:
return Writer->Stream.GetCurrentBitNo();
}
- /// \brief Add a bit offset into the record. This will be converted into an
+ /// Add a bit offset into the record. This will be converted into an
/// offset relative to the current record when emitted.
void AddOffset(uint64_t BitOffset) {
OffsetIndices.push_back(Record->size());
Record->push_back(BitOffset);
}
- /// \brief Add the given statement or expression to the queue of
+ /// Add the given statement or expression to the queue of
/// statements to emit.
///
/// This routine should be used when emitting types and declarations
@@ -839,74 +838,74 @@ public:
StmtsToEmit.push_back(S);
}
- /// \brief Add a definition for the given function to the queue of statements
+ /// Add a definition for the given function to the queue of statements
/// to emit.
void AddFunctionDefinition(const FunctionDecl *FD);
- /// \brief Emit a source location.
+ /// Emit a source location.
void AddSourceLocation(SourceLocation Loc) {
return Writer->AddSourceLocation(Loc, *Record);
}
- /// \brief Emit a source range.
+ /// Emit a source range.
void AddSourceRange(SourceRange Range) {
return Writer->AddSourceRange(Range, *Record);
}
- /// \brief Emit an integral value.
+ /// Emit an integral value.
void AddAPInt(const llvm::APInt &Value);
- /// \brief Emit a signed integral value.
+ /// Emit a signed integral value.
void AddAPSInt(const llvm::APSInt &Value);
- /// \brief Emit a floating-point value.
+ /// Emit a floating-point value.
void AddAPFloat(const llvm::APFloat &Value);
- /// \brief Emit a reference to an identifier.
+ /// Emit a reference to an identifier.
void AddIdentifierRef(const IdentifierInfo *II) {
return Writer->AddIdentifierRef(II, *Record);
}
- /// \brief Emit a Selector (which is a smart pointer reference).
+ /// Emit a Selector (which is a smart pointer reference).
void AddSelectorRef(Selector S);
- /// \brief Emit a CXXTemporary.
+ /// Emit a CXXTemporary.
void AddCXXTemporary(const CXXTemporary *Temp);
- /// \brief Emit a C++ base specifier.
+ /// Emit a C++ base specifier.
void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base);
- /// \brief Emit a set of C++ base specifiers.
+ /// Emit a set of C++ base specifiers.
void AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases);
- /// \brief Emit a reference to a type.
+ /// Emit a reference to a type.
void AddTypeRef(QualType T) {
return Writer->AddTypeRef(T, *Record);
}
- /// \brief Emits a reference to a declarator info.
+ /// Emits a reference to a declarator info.
void AddTypeSourceInfo(TypeSourceInfo *TInfo);
- /// \brief Emits a type with source-location information.
+ /// Emits source location information for a type. Does not emit the type.
void AddTypeLoc(TypeLoc TL);
- /// \brief Emits a template argument location info.
+ /// Emits a template argument location info.
void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
const TemplateArgumentLocInfo &Arg);
- /// \brief Emits a template argument location.
+ /// Emits a template argument location.
void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg);
- /// \brief Emits an AST template argument list info.
+ /// Emits an AST template argument list info.
void AddASTTemplateArgumentListInfo(
const ASTTemplateArgumentListInfo *ASTTemplArgList);
- /// \brief Emit a reference to a declaration.
+ /// Emit a reference to a declaration.
void AddDeclRef(const Decl *D) {
return Writer->AddDeclRef(D, *Record);
}
- /// \brief Emit a declaration name.
+ /// Emit a declaration name.
void AddDeclarationName(DeclarationName Name);
void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
@@ -915,52 +914,52 @@ public:
void AddQualifierInfo(const QualifierInfo &Info);
- /// \brief Emit a nested name specifier.
+ /// Emit a nested name specifier.
void AddNestedNameSpecifier(NestedNameSpecifier *NNS);
- /// \brief Emit a nested name specifier with source-location information.
+ /// Emit a nested name specifier with source-location information.
void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
- /// \brief Emit a template name.
+ /// Emit a template name.
void AddTemplateName(TemplateName Name);
- /// \brief Emit a template argument.
+ /// Emit a template argument.
void AddTemplateArgument(const TemplateArgument &Arg);
- /// \brief Emit a template parameter list.
+ /// Emit a template parameter list.
void AddTemplateParameterList(const TemplateParameterList *TemplateParams);
- /// \brief Emit a template argument list.
+ /// Emit a template argument list.
void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs);
- /// \brief Emit a UnresolvedSet structure.
+ /// Emit a UnresolvedSet structure.
void AddUnresolvedSet(const ASTUnresolvedSet &Set);
- /// \brief Emit a CXXCtorInitializer array.
+ /// Emit a CXXCtorInitializer array.
void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer *> CtorInits);
void AddCXXDefinitionData(const CXXRecordDecl *D);
- /// \brief Emit a string.
+ /// Emit a string.
void AddString(StringRef Str) {
return Writer->AddString(Str, *Record);
}
- /// \brief Emit a path.
+ /// Emit a path.
void AddPath(StringRef Path) {
return Writer->AddPath(Path, *Record);
}
- /// \brief Emit a version tuple.
+ /// Emit a version tuple.
void AddVersionTuple(const VersionTuple &Version) {
return Writer->AddVersionTuple(Version, *Record);
}
- /// \brief Emit a list of attributes.
+ /// Emit a list of attributes.
void AddAttributes(ArrayRef<const Attr*> Attrs);
};
-/// \brief AST and semantic-analysis consumer that generates a
+/// AST and semantic-analysis consumer that generates a
/// precompiled header from the parsed source code.
class PCHGenerator : public SemaConsumer {
const Preprocessor &PP;
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
index 24bfadd0f867..73bf2ed10f04 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
#include <cassert>
@@ -23,7 +24,7 @@
namespace clang {
-/// \brief A map from continuous integer ranges to some value, with a very
+/// A map from continuous integer ranges to some value, with a very
/// specialized interface.
///
/// CRM maps from integer ranges to values. The ranges are continuous, i.e.
@@ -71,14 +72,14 @@ public:
"Must insert keys in order.");
Rep.push_back(Val);
}
-
+
void insertOrReplace(const value_type &Val) {
iterator I = std::lower_bound(Rep.begin(), Rep.end(), Val, Compare());
if (I != Rep.end() && I->first == Val.first) {
I->second = Val.second;
return;
}
-
+
Rep.insert(I, Val);
}
@@ -105,8 +106,8 @@ public:
reference back() { return Rep.back(); }
const_reference back() const { return Rep.back(); }
-
- /// \brief An object that helps properly build a continuous range map
+
+ /// An object that helps properly build a continuous range map
/// from a set of values.
class Builder {
ContinuousRangeMap &Self;
@@ -115,9 +116,9 @@ public:
explicit Builder(ContinuousRangeMap &Self) : Self(Self) {}
Builder(const Builder&) = delete;
Builder &operator=(const Builder&) = delete;
-
+
~Builder() {
- std::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
+ llvm::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
std::unique(Self.Rep.begin(), Self.Rep.end(),
[](const_reference A, const_reference B) {
// FIXME: we should not allow any duplicate keys, but there are a lot of
@@ -127,7 +128,7 @@ public:
return A == B;
});
}
-
+
void insert(const value_type &Val) {
Self.Rep.push_back(Val);
}
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
index 0f14eca0fd86..d47fe9517d76 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
@@ -47,7 +47,7 @@ using llvm::SmallVectorImpl;
using llvm::StringRef;
using serialization::ModuleFile;
-/// \brief A global index for a set of module files, providing information about
+/// A global index for a set of module files, providing information about
/// the identifiers within those module files.
///
/// The global index is an aid for name lookup into modules, offering a central
@@ -59,64 +59,64 @@ using serialization::ModuleFile;
/// imported, and can be queried to determine which modules the current
/// translation could or should load to fix a problem.
class GlobalModuleIndex {
- /// \brief Buffer containing the index file, which is lazily accessed so long
+ /// Buffer containing the index file, which is lazily accessed so long
/// as the global module index is live.
std::unique_ptr<llvm::MemoryBuffer> Buffer;
- /// \brief The hash table.
+ /// The hash table.
///
/// This pointer actually points to a IdentifierIndexTable object,
/// but that type is only accessible within the implementation of
/// GlobalModuleIndex.
void *IdentifierIndex;
- /// \brief Information about a given module file.
+ /// Information about a given module file.
struct ModuleInfo {
ModuleInfo() : File(), Size(), ModTime() { }
- /// \brief The module file, once it has been resolved.
+ /// The module file, once it has been resolved.
ModuleFile *File;
- /// \brief The module file name.
+ /// The module file name.
std::string FileName;
- /// \brief Size of the module file at the time the global index was built.
+ /// Size of the module file at the time the global index was built.
off_t Size;
- /// \brief Modification time of the module file at the time the global
+ /// Modification time of the module file at the time the global
/// index was built.
time_t ModTime;
- /// \brief The module IDs on which this module directly depends.
+ /// The module IDs on which this module directly depends.
/// FIXME: We don't really need a vector here.
llvm::SmallVector<unsigned, 4> Dependencies;
};
- /// \brief A mapping from module IDs to information about each module.
+ /// A mapping from module IDs to information about each module.
///
/// This vector may have gaps, if module files have been removed or have
/// been updated since the index was built. A gap is indicated by an empty
/// file name.
llvm::SmallVector<ModuleInfo, 16> Modules;
- /// \brief Lazily-populated mapping from module files to their
+ /// Lazily-populated mapping from module files to their
/// corresponding index into the \c Modules vector.
llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile;
- /// \brief The set of modules that have not yet been resolved.
+ /// The set of modules that have not yet been resolved.
///
/// The string is just the name of the module itself, which maps to the
/// module ID.
llvm::StringMap<unsigned> UnresolvedModules;
- /// \brief The number of identifier lookups we performed.
+ /// The number of identifier lookups we performed.
unsigned NumIdentifierLookups;
- /// \brief The number of identifier lookup hits, where we recognize the
+ /// The number of identifier lookup hits, where we recognize the
/// identifier.
unsigned NumIdentifierLookupHits;
-
- /// \brief Internal constructor. Use \c readIndex() to read an index.
+
+ /// Internal constructor. Use \c readIndex() to read an index.
explicit GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer,
llvm::BitstreamCursor Cursor);
@@ -126,20 +126,20 @@ class GlobalModuleIndex {
public:
~GlobalModuleIndex();
- /// \brief An error code returned when trying to read an index.
+ /// An error code returned when trying to read an index.
enum ErrorCode {
- /// \brief No error occurred.
+ /// No error occurred.
EC_None,
- /// \brief No index was found.
+ /// No index was found.
EC_NotFound,
- /// \brief Some other process is currently building the index; it is not
+ /// Some other process is currently building the index; it is not
/// available yet.
EC_Building,
- /// \brief There was an unspecified I/O error reading or writing the index.
+ /// There was an unspecified I/O error reading or writing the index.
EC_IOError
};
- /// \brief Read a global index file for the given directory.
+ /// Read a global index file for the given directory.
///
/// \param Path The path to the specific module cache where the module files
/// for the intended configuration reside.
@@ -149,26 +149,26 @@ public:
static std::pair<GlobalModuleIndex *, ErrorCode>
readIndex(StringRef Path);
- /// \brief Returns an iterator for identifiers stored in the index table.
+ /// Returns an iterator for identifiers stored in the index table.
///
/// The caller accepts ownership of the returned object.
IdentifierIterator *createIdentifierIterator() const;
- /// \brief Retrieve the set of modules that have up-to-date indexes.
+ /// Retrieve the set of modules that have up-to-date indexes.
///
/// \param ModuleFiles Will be populated with the set of module files that
/// have been indexed.
void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles);
- /// \brief Retrieve the set of module files on which the given module file
+ /// Retrieve the set of module files on which the given module file
/// directly depends.
void getModuleDependencies(ModuleFile *File,
SmallVectorImpl<ModuleFile *> &Dependencies);
- /// \brief A set of module files in which we found a result.
+ /// A set of module files in which we found a result.
typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet;
-
- /// \brief Look for all of the module files with information about the given
+
+ /// Look for all of the module files with information about the given
/// identifier, e.g., a global function, variable, or type with that name.
///
/// \param Name The identifier to look for.
@@ -179,19 +179,19 @@ public:
/// \returns true if the identifier is known to the index, false otherwise.
bool lookupIdentifier(StringRef Name, HitSet &Hits);
- /// \brief Note that the given module file has been loaded.
+ /// Note that the given module file has been loaded.
///
/// \returns false if the global module index has information about this
/// module file, and true otherwise.
bool loadedModuleFile(ModuleFile *File);
- /// \brief Print statistics to standard error.
+ /// Print statistics to standard error.
void printStats();
- /// \brief Print debugging view to standard error.
+ /// Print debugging view to standard error.
void dump();
- /// \brief Write a global index into the given
+ /// Write a global index into the given
///
/// \param FileMgr The file manager to use to load module files.
/// \param PCHContainerRdr - The PCHContainerOperations to use for loading and
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
index 4e4bf44f3492..d6e78e693109 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
@@ -1,4 +1,4 @@
-//===--- Module.h - Module description --------------------------*- C++ -*-===//
+//===- Module.h - Module description ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,45 +15,52 @@
#ifndef LLVM_CLANG_SERIALIZATION_MODULE_H
#define LLVM_CLANG_SERIALIZATION_MODULE_H
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/ModuleFileExtension.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Endian.h"
+#include <cassert>
+#include <cstdint>
#include <memory>
#include <string>
-
-namespace llvm {
-template <typename Info> class OnDiskChainedHashTable;
-template <typename Info> class OnDiskIterableChainedHashTable;
-}
+#include <vector>
namespace clang {
-class DeclContext;
-class Module;
+class FileEntry;
namespace serialization {
-namespace reader {
- class ASTDeclContextNameLookupTrait;
-}
-
-/// \brief Specifies the kind of module that has been loaded.
+/// Specifies the kind of module that has been loaded.
enum ModuleKind {
- MK_ImplicitModule, ///< File is an implicitly-loaded module.
- MK_ExplicitModule, ///< File is an explicitly-loaded module.
- MK_PCH, ///< File is a PCH file treated as such.
- MK_Preamble, ///< File is a PCH file treated as the preamble.
- MK_MainFile, ///< File is a PCH file treated as the actual main file.
- MK_PrebuiltModule ///< File is from a prebuilt module path.
+ /// File is an implicitly-loaded module.
+ MK_ImplicitModule,
+
+ /// File is an explicitly-loaded module.
+ MK_ExplicitModule,
+
+ /// File is a PCH file treated as such.
+ MK_PCH,
+
+ /// File is a PCH file treated as the preamble.
+ MK_Preamble,
+
+ /// File is a PCH file treated as the actual main file.
+ MK_MainFile,
+
+ /// File is from a prebuilt module path.
+ MK_PrebuiltModule
};
-/// \brief The input file that has been loaded from this AST file, along with
+/// The input file that has been loaded from this AST file, along with
/// bools indicating whether this was an overridden buffer or if it was
/// out-of-date or not-found.
class InputFile {
@@ -65,7 +72,8 @@ class InputFile {
llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val;
public:
- InputFile() {}
+ InputFile() = default;
+
InputFile(const FileEntry *File,
bool isOverridden = false, bool isOutOfDate = false) {
assert(!(isOverridden && isOutOfDate) &&
@@ -90,7 +98,7 @@ public:
bool isNotFound() const { return Val.getInt() == NotFound; }
};
-/// \brief Information about a module that has been loaded by the ASTReader.
+/// Information about a module that has been loaded by the ASTReader.
///
/// Each instance of the Module class corresponds to a single AST file, which
/// may be a precompiled header, precompiled preamble, a module, or an AST file
@@ -105,81 +113,84 @@ public:
// === General information ===
- /// \brief The index of this module in the list of modules.
+ /// The index of this module in the list of modules.
unsigned Index = 0;
- /// \brief The type of this module.
+ /// The type of this module.
ModuleKind Kind;
- /// \brief The file name of the module file.
+ /// The file name of the module file.
std::string FileName;
- /// \brief The name of the module.
+ /// The name of the module.
std::string ModuleName;
- /// \brief The base directory of the module.
+ /// The base directory of the module.
std::string BaseDirectory;
std::string getTimestampFilename() const {
return FileName + ".timestamp";
}
- /// \brief The original source file name that was used to build the
+ /// The original source file name that was used to build the
/// primary AST file, which may have been modified for
/// relocatable-pch support.
std::string OriginalSourceFileName;
- /// \brief The actual original source file name that was used to
+ /// The actual original source file name that was used to
/// build this AST file.
std::string ActualOriginalSourceFileName;
- /// \brief The file ID for the original source file that was used to
+ /// The file ID for the original source file that was used to
/// build this AST file.
FileID OriginalSourceFileID;
- /// \brief The directory that the PCH was originally created in. Used to
+ /// The directory that the PCH was originally created in. Used to
/// allow resolving headers even after headers+PCH was moved to a new path.
std::string OriginalDir;
std::string ModuleMapPath;
- /// \brief Whether this precompiled header is a relocatable PCH file.
+ /// Whether this precompiled header is a relocatable PCH file.
bool RelocatablePCH = false;
- /// \brief Whether timestamps are included in this module file.
+ /// Whether timestamps are included in this module file.
bool HasTimestamps = false;
- /// \brief The file entry for the module file.
+ /// Whether the PCH has a corresponding object file.
+ bool PCHHasObjectFile = false;
+
+ /// The file entry for the module file.
const FileEntry *File = nullptr;
/// The signature of the module file, which may be used instead of the size
/// and modification time to identify this particular file.
ASTFileSignature Signature;
- /// \brief Whether this module has been directly imported by the
+ /// Whether this module has been directly imported by the
/// user.
bool DirectlyImported = false;
- /// \brief The generation of which this module file is a part.
+ /// The generation of which this module file is a part.
unsigned Generation;
-
+
/// The memory buffer that stores the data associated with
/// this AST file, owned by the PCMCache in the ModuleManager.
llvm::MemoryBuffer *Buffer;
- /// \brief The size of this file, in bits.
+ /// The size of this file, in bits.
uint64_t SizeInBits = 0;
- /// \brief The global bit offset (or base) of this module
+ /// The global bit offset (or base) of this module
uint64_t GlobalBitOffset = 0;
- /// \brief The serialized bitstream data for this file.
+ /// The serialized bitstream data for this file.
StringRef Data;
- /// \brief The main bitstream cursor for the main block.
+ /// The main bitstream cursor for the main block.
llvm::BitstreamCursor Stream;
- /// \brief The source location where the module was explicitly or implicitly
+ /// The source location where the module was explicitly or implicitly
/// imported in the local translation unit.
///
/// If module A depends on and imports module B, both modules will have the
@@ -190,10 +201,10 @@ public:
/// made visible, just when the first submodule of that module was imported.
SourceLocation DirectImportLoc;
- /// \brief The source location where this module was first imported.
+ /// The source location where this module was first imported.
SourceLocation ImportLoc;
- /// \brief The first source location in this module.
+ /// The first source location in this module.
SourceLocation FirstLoc;
/// The list of extension readers that are attached to this module
@@ -205,20 +216,21 @@ public:
StringRef ModuleOffsetMap;
// === Input Files ===
- /// \brief The cursor to the start of the input-files block.
+
+ /// The cursor to the start of the input-files block.
llvm::BitstreamCursor InputFilesCursor;
- /// \brief Offsets for all of the input file entries in the AST file.
+ /// Offsets for all of the input file entries in the AST file.
const llvm::support::unaligned_uint64_t *InputFileOffsets = nullptr;
- /// \brief The input files that have been loaded from this AST file.
+ /// The input files that have been loaded from this AST file.
std::vector<InputFile> InputFilesLoaded;
// All user input files reside at the index range [0, NumUserInputFiles), and
// system input files reside at [NumUserInputFiles, InputFilesLoaded.size()).
unsigned NumUserInputFiles = 0;
- /// \brief If non-zero, specifies the time when we last validated input
+ /// If non-zero, specifies the time when we last validated input
/// files. Zero means we never validated them.
///
/// The time is specified in seconds since the start of the Epoch.
@@ -226,153 +238,160 @@ public:
// === Source Locations ===
- /// \brief Cursor used to read source location entries.
+ /// Cursor used to read source location entries.
llvm::BitstreamCursor SLocEntryCursor;
- /// \brief The number of source location entries in this AST file.
+ /// The number of source location entries in this AST file.
unsigned LocalNumSLocEntries = 0;
- /// \brief The base ID in the source manager's view of this module.
+ /// The base ID in the source manager's view of this module.
int SLocEntryBaseID = 0;
- /// \brief The base offset in the source manager's view of this module.
+ /// The base offset in the source manager's view of this module.
unsigned SLocEntryBaseOffset = 0;
- /// \brief Offsets for all of the source location entries in the
+ /// Offsets for all of the source location entries in the
/// AST file.
const uint32_t *SLocEntryOffsets = nullptr;
- /// \brief SLocEntries that we're going to preload.
+ /// SLocEntries that we're going to preload.
SmallVector<uint64_t, 4> PreloadSLocEntries;
- /// \brief Remapping table for source locations in this module.
+ /// Remapping table for source locations in this module.
ContinuousRangeMap<uint32_t, int, 2> SLocRemap;
// === Identifiers ===
- /// \brief The number of identifiers in this AST file.
+ /// The number of identifiers in this AST file.
unsigned LocalNumIdentifiers = 0;
- /// \brief Offsets into the identifier table data.
+ /// Offsets into the identifier table data.
///
/// This array is indexed by the identifier ID (-1), and provides
/// the offset into IdentifierTableData where the string data is
/// stored.
const uint32_t *IdentifierOffsets = nullptr;
- /// \brief Base identifier ID for identifiers local to this module.
+ /// Base identifier ID for identifiers local to this module.
serialization::IdentID BaseIdentifierID = 0;
- /// \brief Remapping table for identifier IDs in this module.
+ /// Remapping table for identifier IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap;
- /// \brief Actual data for the on-disk hash table of identifiers.
+ /// Actual data for the on-disk hash table of identifiers.
///
/// This pointer points into a memory buffer, where the on-disk hash
/// table for identifiers actually lives.
const char *IdentifierTableData = nullptr;
- /// \brief A pointer to an on-disk hash table of opaque type
+ /// A pointer to an on-disk hash table of opaque type
/// IdentifierHashTable.
void *IdentifierLookupTable = nullptr;
- /// \brief Offsets of identifiers that we're going to preload within
+ /// Offsets of identifiers that we're going to preload within
/// IdentifierTableData.
std::vector<unsigned> PreloadIdentifierOffsets;
// === Macros ===
- /// \brief The cursor to the start of the preprocessor block, which stores
+ /// The cursor to the start of the preprocessor block, which stores
/// all of the macro definitions.
llvm::BitstreamCursor MacroCursor;
- /// \brief The number of macros in this AST file.
+ /// The number of macros in this AST file.
unsigned LocalNumMacros = 0;
- /// \brief Offsets of macros in the preprocessor block.
+ /// Offsets of macros in the preprocessor block.
///
/// This array is indexed by the macro ID (-1), and provides
/// the offset into the preprocessor block where macro definitions are
/// stored.
const uint32_t *MacroOffsets = nullptr;
- /// \brief Base macro ID for macros local to this module.
+ /// Base macro ID for macros local to this module.
serialization::MacroID BaseMacroID = 0;
- /// \brief Remapping table for macro IDs in this module.
+ /// Remapping table for macro IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> MacroRemap;
- /// \brief The offset of the start of the set of defined macros.
+ /// The offset of the start of the set of defined macros.
uint64_t MacroStartOffset = 0;
// === Detailed PreprocessingRecord ===
- /// \brief The cursor to the start of the (optional) detailed preprocessing
+ /// The cursor to the start of the (optional) detailed preprocessing
/// record block.
llvm::BitstreamCursor PreprocessorDetailCursor;
- /// \brief The offset of the start of the preprocessor detail cursor.
+ /// The offset of the start of the preprocessor detail cursor.
uint64_t PreprocessorDetailStartOffset = 0;
- /// \brief Base preprocessed entity ID for preprocessed entities local to
+ /// Base preprocessed entity ID for preprocessed entities local to
/// this module.
serialization::PreprocessedEntityID BasePreprocessedEntityID = 0;
- /// \brief Remapping table for preprocessed entity IDs in this module.
+ /// Remapping table for preprocessed entity IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap;
const PPEntityOffset *PreprocessedEntityOffsets = nullptr;
unsigned NumPreprocessedEntities = 0;
+ /// Base ID for preprocessed skipped ranges local to this module.
+ unsigned BasePreprocessedSkippedRangeID = 0;
+
+ const PPSkippedRange *PreprocessedSkippedRangeOffsets = nullptr;
+ unsigned NumPreprocessedSkippedRanges = 0;
+
// === Header search information ===
- /// \brief The number of local HeaderFileInfo structures.
+ /// The number of local HeaderFileInfo structures.
unsigned LocalNumHeaderFileInfos = 0;
- /// \brief Actual data for the on-disk hash table of header file
+ /// Actual data for the on-disk hash table of header file
/// information.
///
/// This pointer points into a memory buffer, where the on-disk hash
/// table for header file information actually lives.
const char *HeaderFileInfoTableData = nullptr;
- /// \brief The on-disk hash table that contains information about each of
+ /// The on-disk hash table that contains information about each of
/// the header files.
void *HeaderFileInfoTable = nullptr;
- // === Submodule information ===
- /// \brief The number of submodules in this module.
+ // === Submodule information ===
+
+ /// The number of submodules in this module.
unsigned LocalNumSubmodules = 0;
-
- /// \brief Base submodule ID for submodules local to this module.
+
+ /// Base submodule ID for submodules local to this module.
serialization::SubmoduleID BaseSubmoduleID = 0;
-
- /// \brief Remapping table for submodule IDs in this module.
+
+ /// Remapping table for submodule IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> SubmoduleRemap;
-
+
// === Selectors ===
- /// \brief The number of selectors new to this file.
+ /// The number of selectors new to this file.
///
/// This is the number of entries in SelectorOffsets.
unsigned LocalNumSelectors = 0;
- /// \brief Offsets into the selector lookup table's data array
+ /// Offsets into the selector lookup table's data array
/// where each selector resides.
const uint32_t *SelectorOffsets = nullptr;
- /// \brief Base selector ID for selectors local to this module.
+ /// Base selector ID for selectors local to this module.
serialization::SelectorID BaseSelectorID = 0;
- /// \brief Remapping table for selector IDs in this module.
+ /// Remapping table for selector IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> SelectorRemap;
- /// \brief A pointer to the character data that comprises the selector table
+ /// A pointer to the character data that comprises the selector table
///
/// The SelectorOffsets table refers into this memory.
const unsigned char *SelectorLookupTableData = nullptr;
- /// \brief A pointer to an on-disk hash table of opaque type
+ /// A pointer to an on-disk hash table of opaque type
/// ASTSelectorLookupTable.
///
/// This hash table provides the IDs of all selectors, and the associated
@@ -386,20 +405,20 @@ public:
/// jump around with these in context.
llvm::BitstreamCursor DeclsCursor;
- /// \brief The number of declarations in this AST file.
+ /// The number of declarations in this AST file.
unsigned LocalNumDecls = 0;
- /// \brief Offset of each declaration within the bitstream, indexed
+ /// Offset of each declaration within the bitstream, indexed
/// by the declaration ID (-1).
const DeclOffset *DeclOffsets = nullptr;
- /// \brief Base declaration ID for declarations local to this module.
+ /// Base declaration ID for declarations local to this module.
serialization::DeclID BaseDeclID = 0;
- /// \brief Remapping table for declaration IDs in this module.
+ /// Remapping table for declaration IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
- /// \brief Mapping from the module files that this module file depends on
+ /// Mapping from the module files that this module file depends on
/// to the base declaration ID for that module as it is understood within this
/// module.
///
@@ -408,64 +427,64 @@ public:
/// as a local ID (for this module file).
llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;
- /// \brief Array of file-level DeclIDs sorted by file.
+ /// Array of file-level DeclIDs sorted by file.
const serialization::DeclID *FileSortedDecls = nullptr;
unsigned NumFileSortedDecls = 0;
- /// \brief Array of category list location information within this
+ /// Array of category list location information within this
/// module file, sorted by the definition ID.
const serialization::ObjCCategoriesInfo *ObjCCategoriesMap = nullptr;
-
- /// \brief The number of redeclaration info entries in ObjCCategoriesMap.
+
+ /// The number of redeclaration info entries in ObjCCategoriesMap.
unsigned LocalNumObjCCategoriesInMap = 0;
-
- /// \brief The Objective-C category lists for categories known to this
+
+ /// The Objective-C category lists for categories known to this
/// module.
SmallVector<uint64_t, 1> ObjCCategories;
// === Types ===
- /// \brief The number of types in this AST file.
+ /// The number of types in this AST file.
unsigned LocalNumTypes = 0;
- /// \brief Offset of each type within the bitstream, indexed by the
+ /// Offset of each type within the bitstream, indexed by the
/// type ID, or the representation of a Type*.
const uint32_t *TypeOffsets = nullptr;
- /// \brief Base type ID for types local to this module as represented in
+ /// Base type ID for types local to this module as represented in
/// the global type ID space.
serialization::TypeID BaseTypeIndex = 0;
- /// \brief Remapping table for type IDs in this module.
+ /// Remapping table for type IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> TypeRemap;
// === Miscellaneous ===
- /// \brief Diagnostic IDs and their mappings that the user changed.
+ /// Diagnostic IDs and their mappings that the user changed.
SmallVector<uint64_t, 8> PragmaDiagMappings;
- /// \brief List of modules which depend on this module
+ /// List of modules which depend on this module
llvm::SetVector<ModuleFile *> ImportedBy;
- /// \brief List of modules which this module depends on
+ /// List of modules which this module depends on
llvm::SetVector<ModuleFile *> Imports;
- /// \brief Determine whether this module was directly imported at
+ /// Determine whether this module was directly imported at
/// any point during translation.
bool isDirectlyImported() const { return DirectlyImported; }
- /// \brief Is this a module file for a module (rather than a PCH or similar).
+ /// Is this a module file for a module (rather than a PCH or similar).
bool isModule() const {
return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule ||
Kind == MK_PrebuiltModule;
}
- /// \brief Dump debugging output for this module.
+ /// Dump debugging output for this module.
void dump();
};
-} // end namespace serialization
+} // namespace serialization
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SERIALIZATION_MODULE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
index f7bdcec598f1..f70218e329af 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
@@ -26,7 +26,7 @@ namespace clang {
class ASTReader;
class ASTWriter;
class Sema;
-
+
namespace serialization {
class ModuleFile;
} // end namespace serialization
@@ -128,7 +128,7 @@ public:
/// Abstract base class that reads a module file extension block from
/// a module file.
///
-/// Subclasses
+/// Subclasses
class ModuleFileExtensionReader {
ModuleFileExtension *Extension;
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
index 147a6910aa29..cfc9a2ef112c 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
@@ -45,45 +45,45 @@ class PCHContainerReader;
namespace serialization {
-/// \brief Manages the set of modules loaded by an AST reader.
+/// Manages the set of modules loaded by an AST reader.
class ModuleManager {
- /// \brief The chain of AST files, in the order in which we started to load
+ /// The chain of AST files, in the order in which we started to load
/// them (this order isn't really useful for anything).
SmallVector<std::unique_ptr<ModuleFile>, 2> Chain;
- /// \brief The chain of non-module PCH files. The first entry is the one named
+ /// The chain of non-module PCH files. The first entry is the one named
/// by the user, the last one is the one that doesn't depend on anything
/// further.
SmallVector<ModuleFile *, 2> PCHChain;
- // \brief The roots of the dependency DAG of AST files. This is used
+ // The roots of the dependency DAG of AST files. This is used
// to implement short-circuiting logic when running DFS over the dependencies.
SmallVector<ModuleFile *, 2> Roots;
- /// \brief All loaded modules, indexed by name.
+ /// All loaded modules, indexed by name.
llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;
- /// \brief FileManager that handles translating between filenames and
+ /// FileManager that handles translating between filenames and
/// FileEntry *.
FileManager &FileMgr;
/// Cache of PCM files.
IntrusiveRefCntPtr<MemoryBufferCache> PCMCache;
- /// \brief Knows how to unwrap module containers.
+ /// Knows how to unwrap module containers.
const PCHContainerReader &PCHContainerRdr;
- /// \brief Preprocessor's HeaderSearchInfo containing the module map.
+ /// Preprocessor's HeaderSearchInfo containing the module map.
const HeaderSearch &HeaderSearchInfo;
- /// \brief A lookup of in-memory (virtual file) buffers
+ /// A lookup of in-memory (virtual file) buffers
llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
InMemoryBuffers;
- /// \brief The visitation order.
+ /// The visitation order.
SmallVector<ModuleFile *, 4> VisitOrder;
-
- /// \brief The list of module files that both we and the global module index
+
+ /// The list of module files that both we and the global module index
/// know about.
///
/// Either the global index or the module manager may have modules that the
@@ -93,13 +93,13 @@ class ModuleManager {
/// known to the global index.
SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex;
- /// \brief The global module index, if one is attached.
+ /// The global module index, if one is attached.
///
/// The global module index will actually be owned by the ASTReader; this is
/// just an non-owning pointer.
GlobalModuleIndex *GlobalIndex = nullptr;
- /// \brief State used by the "visit" operation to avoid malloc traffic in
+ /// State used by the "visit" operation to avoid malloc traffic in
/// calls to visit().
struct VisitState {
explicit VisitState(unsigned N) : VisitNumber(N, 0) {
@@ -110,22 +110,22 @@ class ModuleManager {
delete NextState;
}
- /// \brief The stack used when marking the imports of a particular module
+ /// The stack used when marking the imports of a particular module
/// as not-to-be-visited.
SmallVector<ModuleFile *, 4> Stack;
- /// \brief The visit number of each module file, which indicates when
+ /// The visit number of each module file, which indicates when
/// this module file was last visited.
SmallVector<unsigned, 4> VisitNumber;
- /// \brief The next visit number to use to mark visited module files.
+ /// The next visit number to use to mark visited module files.
unsigned NextVisitNumber = 1;
- /// \brief The next visit state.
+ /// The next visit state.
VisitState *NextState = nullptr;
};
- /// \brief The first visit() state in the chain.
+ /// The first visit() state in the chain.
VisitState *FirstVisitState = nullptr;
VisitState *allocateVisitState();
@@ -145,74 +145,74 @@ public:
const HeaderSearch &HeaderSearchInfo);
~ModuleManager();
- /// \brief Forward iterator to traverse all loaded modules.
+ /// Forward iterator to traverse all loaded modules.
ModuleIterator begin() { return Chain.begin(); }
- /// \brief Forward iterator end-point to traverse all loaded modules
+ /// Forward iterator end-point to traverse all loaded modules
ModuleIterator end() { return Chain.end(); }
-
- /// \brief Const forward iterator to traverse all loaded modules.
+
+ /// 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
+ /// Const forward iterator end-point to traverse all loaded modules
ModuleConstIterator end() const { return Chain.end(); }
-
- /// \brief Reverse iterator to traverse all loaded modules.
+
+ /// Reverse iterator to traverse all loaded modules.
ModuleReverseIterator rbegin() { return Chain.rbegin(); }
- /// \brief Reverse iterator end-point to traverse all loaded modules.
+ /// Reverse iterator end-point to traverse all loaded modules.
ModuleReverseIterator rend() { return Chain.rend(); }
- /// \brief A range covering the PCH and preamble module files loaded.
+ /// A range covering the PCH and preamble module files loaded.
llvm::iterator_range<SmallVectorImpl<ModuleFile *>::const_iterator>
pch_modules() const {
return llvm::make_range(PCHChain.begin(), PCHChain.end());
}
- /// \brief Returns the primary module associated with the manager, that is,
+ /// Returns the primary module associated with the manager, that is,
/// the first module loaded
ModuleFile &getPrimaryModule() { return *Chain[0]; }
-
- /// \brief Returns the primary module associated with the manager, that is,
+
+ /// Returns the primary module associated with the manager, that is,
/// the first module loaded.
ModuleFile &getPrimaryModule() const { return *Chain[0]; }
-
- /// \brief Returns the module associated with the given index
+
+ /// Returns the module associated with the given index
ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; }
-
- /// \brief Returns the module associated with the given file name.
+
+ /// Returns the module associated with the given file name.
ModuleFile *lookupByFileName(StringRef FileName) const;
- /// \brief Returns the module associated with the given module name.
+ /// Returns the module associated with the given module name.
ModuleFile *lookupByModuleName(StringRef ModName) const;
- /// \brief Returns the module associated with the given module file.
+ /// Returns the module associated with the given module file.
ModuleFile *lookup(const FileEntry *File) const;
- /// \brief Returns the in-memory (virtual file) buffer with the given name
+ /// Returns the in-memory (virtual file) buffer with the given name
std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name);
-
- /// \brief Number of modules loaded
+
+ /// Number of modules loaded
unsigned size() const { return Chain.size(); }
- /// \brief The result of attempting to add a new module.
+ /// The result of attempting to add a new module.
enum AddModuleResult {
- /// \brief The module file had already been loaded.
+ /// The module file had already been loaded.
AlreadyLoaded,
- /// \brief The module file was just loaded in response to this call.
+ /// The module file was just loaded in response to this call.
NewlyLoaded,
- /// \brief The module file is missing.
+ /// The module file is missing.
Missing,
- /// \brief The module file is out-of-date.
+ /// The module file is out-of-date.
OutOfDate
};
using ASTFileSignatureReader = ASTFileSignature (*)(StringRef);
- /// \brief Attempts to create a new module and add it to the list of known
+ /// Attempts to create a new module and add it to the list of known
/// modules.
///
/// \param FileName The file name of the module to be loaded.
@@ -255,23 +255,23 @@ public:
ModuleFile *&Module,
std::string &ErrorStr);
- /// \brief Remove the modules starting from First (to the end).
+ /// Remove the modules starting from First (to the end).
void removeModules(ModuleIterator First,
llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
ModuleMap *modMap);
- /// \brief Add an in-memory buffer the list of known buffers
+ /// Add an in-memory buffer the list of known buffers
void addInMemoryBuffer(StringRef FileName,
std::unique_ptr<llvm::MemoryBuffer> Buffer);
- /// \brief Set the global module index.
+ /// Set the global module index.
void setGlobalIndex(GlobalModuleIndex *Index);
- /// \brief Notification from the AST reader that the given module file
+ /// Notification from the AST reader that the given module file
/// has been "accepted", and will not (can not) be unloaded.
void moduleFileAccepted(ModuleFile *MF);
- /// \brief Visit each of the modules.
+ /// Visit each of the modules.
///
/// This routine visits each of the modules, starting with the
/// "root" modules that no other loaded modules depend on, and
@@ -293,7 +293,7 @@ public:
void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr);
- /// \brief Attempt to resolve the given module file name to a file entry.
+ /// Attempt to resolve the given module file name to a file entry.
///
/// \param FileName The name of the module file.
///
@@ -315,7 +315,7 @@ public:
time_t ExpectedModTime,
const FileEntry *&File);
- /// \brief View the graphviz representation of the module graph.
+ /// View the graphviz representation of the module graph.
void viewGraph();
MemoryBufferCache &getPCMCache() const { return *PCMCache; }
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 e510e84e938a..9e53460f6e93 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-include "clang/StaticAnalyzer/Checkers/CheckerBase.td"
+include "CheckerBase.td"
//===----------------------------------------------------------------------===//
// Packages.
@@ -86,7 +86,7 @@ def LLVM : Package<"llvm">;
// The APIModeling package is for checkers that model APIs and don't perform
// any diagnostics. These checkers are always turned on; this package is
-// intended for API modeling that is not controlled by the the target triple.
+// intended for API modeling that is not controlled by the target triple.
def APIModeling : Package<"apiModeling">, Hidden;
def GoogleAPIModeling : Package<"google">, InPackage<APIModeling>;
@@ -218,6 +218,14 @@ def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
} // end "nullability"
+let ParentPackage = APIModeling in {
+
+def TrustNonnullChecker : Checker<"TrustNonnull">,
+ HelpText<"Trust that returns from framework methods annotated with _Nonnull are not null">,
+ DescFile<"TrustNonnullChecker.cpp">;
+
+}
+
//===----------------------------------------------------------------------===//
// Evaluate "builtin" functions.
//===----------------------------------------------------------------------===//
@@ -268,6 +276,10 @@ def ReturnUndefChecker : Checker<"UndefReturn">,
let ParentPackage = Cplusplus in {
+def InnerPointerChecker : Checker<"InnerPointer">,
+ HelpText<"Check for inner pointers of C++ containers used after re/deallocation">,
+ DescFile<"InnerPointerChecker.cpp">;
+
def NewDeleteChecker : Checker<"NewDelete">,
HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
DescFile<"MallocChecker.cpp">;
@@ -306,6 +318,10 @@ def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
"object will be reported">,
DescFile<"MisusedMovedObjectChecker.cpp">;
+def UninitializedObjectChecker: Checker<"UninitializedObject">,
+ HelpText<"Reports uninitialized fields after object construction">,
+ DescFile<"UninitializedObjectChecker.cpp">;
+
} // end: "alpha.cplusplus"
@@ -365,6 +381,15 @@ def PaddingChecker : Checker<"Padding">,
//===----------------------------------------------------------------------===//
let ParentPackage = InsecureAPI in {
+ def bcmp : Checker<"bcmp">,
+ HelpText<"Warn on uses of the 'bcmp' function">,
+ DescFile<"CheckSecuritySyntaxOnly.cpp">;
+ def bcopy : Checker<"bcopy">,
+ HelpText<"Warn on uses of the 'bcopy' function">,
+ DescFile<"CheckSecuritySyntaxOnly.cpp">;
+ def bzero : Checker<"bzero">,
+ HelpText<"Warn on uses of the 'bzero' function">,
+ DescFile<"CheckSecuritySyntaxOnly.cpp">;
def gets : Checker<"gets">,
HelpText<"Warn on uses of the 'gets' function">,
DescFile<"CheckSecuritySyntaxOnly.cpp">;
@@ -414,6 +439,13 @@ def MallocOverflowSecurityChecker : Checker<"MallocOverflow">,
HelpText<"Check for overflows in the arguments to malloc()">,
DescFile<"MallocOverflowSecurityChecker.cpp">;
+// Operating systems specific PROT_READ/PROT_WRITE values is not implemented,
+// the defaults are correct for several common operating systems though,
+// but may need to be overridden via the related analyzer-config flags.
+def MmapWriteExecChecker : Checker<"MmapWriteExec">,
+ HelpText<"Warn on mmap() calls that are both writable and executable">,
+ DescFile<"MmapWriteExecChecker.cpp">;
+
} // end "alpha.security"
//===----------------------------------------------------------------------===//
@@ -536,6 +568,10 @@ def ObjCPropertyChecker : Checker<"ObjCProperty">,
let ParentPackage = Cocoa in {
+def RunLoopAutoreleaseLeakChecker : Checker<"RunLoopAutoreleaseLeak">,
+ HelpText<"Check for leaked memory in autorelease pools that will never be drained">,
+ DescFile<"RunLoopAutoreleaseLeakChecker.cpp">;
+
def ObjCAtSyncChecker : Checker<"AtSync">,
HelpText<"Check for nil pointers used as mutexes for @synchronized">,
DescFile<"ObjCAtSyncChecker.cpp">;
@@ -601,8 +637,18 @@ def ObjCSuperDeallocChecker : Checker<"SuperDealloc">,
HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">,
DescFile<"ObjCSuperDeallocChecker.cpp">;
+def AutoreleaseWriteChecker : Checker<"AutoreleaseWrite">,
+ HelpText<"Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C">,
+ DescFile<"ObjCAutoreleaseWriteChecker.cpp">;
} // end "osx.cocoa"
+let ParentPackage = Performance in {
+
+def GCDAntipattern : Checker<"GCDAntipattern">,
+ HelpText<"Check for performance anti-patterns when using Grand Central Dispatch">,
+ DescFile<"GCDAntipatternChecker.cpp">;
+} // end "optin.performance"
+
let ParentPackage = CocoaAlpha in {
def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">,
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 e5e857e97029..f5a06394b187 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -136,7 +136,7 @@ public:
// by inlining the function
NoRetHard
};
-
+
/// Determines the object kind of a tracked object.
enum ObjKind {
/// Indicates that the tracked object is a CF object. This is
@@ -153,30 +153,30 @@ public:
private:
Kind K;
ObjKind O;
-
+
RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
-
+
public:
Kind getKind() const { return K; }
-
+
ObjKind getObjKind() const { return O; }
-
+
bool isOwned() const {
return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
}
-
+
bool notOwned() const {
return K == NotOwnedSymbol;
}
-
+
bool operator==(const RetEffect &Other) const {
return K == Other.K && O == Other.O;
}
-
+
static RetEffect MakeOwnedWhenTrackedReceiver() {
return RetEffect(OwnedWhenTrackedReceiver, ObjC);
}
-
+
static RetEffect MakeOwned(ObjKind o) {
return RetEffect(OwnedSymbol, o);
}
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 ce50cc582d1e..7586f7e0835b 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -1,4 +1,4 @@
-//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===//
+//===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,18 +19,18 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include <string>
+#include <utility>
#include <vector>
namespace clang {
-class ASTConsumer;
-class DiagnosticsEngine;
-class Preprocessor;
-class LangOptions;
namespace ento {
+
class CheckerBase;
-}
+
+} // namespace ento
/// Analysis - Set of available source code analyses.
enum Analyses {
@@ -76,7 +76,7 @@ enum AnalysisInliningMode {
NumInliningModes
};
-/// \brief Describes the different kinds of C++ member functions which can be
+/// Describes the different kinds of C++ member functions which can be
/// considered for inlining by the analyzer.
///
/// These options are cumulative; enabling one kind of member function will
@@ -100,7 +100,7 @@ enum CXXInlineableMemberKind {
CIMK_Destructors
};
-/// \brief Describes the different modes of inter-procedural analysis.
+/// Describes the different modes of inter-procedural analysis.
enum IPAKind {
IPAK_NotSet = 0,
@@ -123,28 +123,31 @@ enum IPAKind {
class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
- typedef llvm::StringMap<std::string> ConfigTable;
+ using ConfigTable = llvm::StringMap<std::string>;
static std::vector<StringRef>
getRegisteredCheckers(bool IncludeExperimental = false);
- /// \brief Pair of checker name and enable/disable.
- std::vector<std::pair<std::string, bool> > CheckersControlList;
-
- /// \brief A key-value table of use-specified configuration values.
+ /// Pair of checker name and enable/disable.
+ std::vector<std::pair<std::string, bool>> CheckersControlList;
+
+ /// A key-value table of use-specified configuration values.
ConfigTable Config;
- AnalysisStores AnalysisStoreOpt;
- AnalysisConstraints AnalysisConstraintsOpt;
- AnalysisDiagClients AnalysisDiagOpt;
- AnalysisPurgeMode AnalysisPurgeOpt;
-
+ AnalysisStores AnalysisStoreOpt = RegionStoreModel;
+ AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
+ AnalysisDiagClients AnalysisDiagOpt = PD_HTML;
+ AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt;
+
std::string AnalyzeSpecificFunction;
-
- /// \brief The maximum number of times the analyzer visits a block.
+
+ /// Store full compiler invocation for reproducible instructions in the
+ /// generated report.
+ std::string FullCompilerInvocation;
+
+ /// The maximum number of times the analyzer visits a block.
unsigned maxBlockVisitOnPath;
-
-
- /// \brief Disable all analyzer checks.
+
+ /// Disable all analyzer checks.
///
/// This flag allows one to disable analyzer checks on the code processed by
/// the given analysis consumer. Note, the code will get parsed and the
@@ -157,7 +160,7 @@ public:
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
- /// \brief The flag regulates if we should eagerly assume evaluations of
+ /// The flag regulates if we should eagerly assume evaluations of
/// conditionals, thus, bifurcating the path.
///
/// This flag indicates how the engine should handle expressions such as: 'x =
@@ -167,44 +170,58 @@ public:
/// precision until we have a better way to lazily evaluate such logic. The
/// downside is that it eagerly bifurcates paths.
unsigned eagerlyAssumeBinOpBifurcation : 1;
-
+
unsigned TrimGraph : 1;
unsigned visualizeExplodedGraphWithGraphViz : 1;
unsigned visualizeExplodedGraphWithUbiGraph : 1;
unsigned UnoptimizedCFG : 1;
unsigned PrintStats : 1;
-
- /// \brief Do not re-analyze paths leading to exhausted nodes with a different
+
+ /// Do not re-analyze paths leading to exhausted nodes with a different
/// strategy. We get better code coverage when retry is enabled.
unsigned NoRetryExhausted : 1;
-
- /// \brief The inlining stack depth limit.
- unsigned InlineMaxStackDepth;
-
- /// \brief The mode of function selection used during inlining.
- AnalysisInliningMode InliningMode;
+
+ /// The inlining stack depth limit.
+ // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
+ unsigned InlineMaxStackDepth = 5;
+
+ /// The mode of function selection used during inlining.
+ AnalysisInliningMode InliningMode = NoRedundancy;
+
+ enum class ExplorationStrategyKind {
+ DFS,
+ BFS,
+ UnexploredFirst,
+ UnexploredFirstQueue,
+ BFSBlockDFSContents,
+ NotSet
+ };
private:
- /// \brief Describes the kinds for high-level analyzer mode.
+ ExplorationStrategyKind ExplorationStrategy = ExplorationStrategyKind::NotSet;
+
+ /// Describes the kinds for high-level analyzer mode.
enum UserModeKind {
UMK_NotSet = 0,
+
/// Perform shallow but fast analyzes.
UMK_Shallow = 1,
+
/// Perform deep analyzes.
UMK_Deep = 2
};
- /// Controls the high-level analyzer mode, which influences the default
+ /// Controls the high-level analyzer mode, which influences the default
/// settings for some of the lower-level config options (such as IPAMode).
/// \sa getUserMode
- UserModeKind UserMode;
+ UserModeKind UserMode = UMK_NotSet;
/// Controls the mode of inter-procedural analysis.
- IPAKind IPAMode;
+ IPAKind IPAMode = IPAK_NotSet;
/// Controls which C++ member functions will be considered for inlining.
CXXInlineableMemberKind CXXMemberInliningMode;
-
+
/// \sa includeImplicitDtorsInCFG
Optional<bool> IncludeImplicitDtorsInCFG;
@@ -217,9 +234,15 @@ private:
/// \sa IncludeLoopExitInCFG
Optional<bool> IncludeLoopExitInCFG;
+ /// \sa IncludeRichConstructorsInCFG
+ Optional<bool> IncludeRichConstructorsInCFG;
+
/// \sa mayInlineCXXStandardLibrary
Optional<bool> InlineCXXStandardLibrary;
-
+
+ /// \sa includeScopesInCFG
+ Optional<bool> IncludeScopesInCFG;
+
/// \sa mayInlineTemplateFunctions
Optional<bool> InlineTemplateFunctions;
@@ -232,6 +255,9 @@ private:
/// \sa mayInlineCXXSharedPtrDtor
Optional<bool> InlineCXXSharedPtrDtor;
+ /// \sa mayInlineCXXTemporaryDtors
+ Optional<bool> InlineCXXTemporaryDtors;
+
/// \sa mayInlineObjCMethod
Optional<bool> ObjCInliningMode;
@@ -254,15 +280,23 @@ private:
/// \sa shouldSuppressFromCXXStandardLibrary
Optional<bool> SuppressFromCXXStandardLibrary;
+ /// \sa shouldCrosscheckWithZ3
+ Optional<bool> CrosscheckWithZ3;
+
/// \sa reportIssuesInMainSourceFile
Optional<bool> ReportIssuesInMainSourceFile;
/// \sa StableReportFilename
Optional<bool> StableReportFilename;
+ Optional<bool> SerializeStats;
+
/// \sa getGraphTrimInterval
Optional<unsigned> GraphTrimInterval;
+ /// \sa getMaxSymbolComplexity
+ Optional<unsigned> MaxSymbolComplexity;
+
/// \sa getMaxTimesInlineLarge
Optional<unsigned> MaxTimesInlineLarge;
@@ -284,6 +318,22 @@ private:
/// \sa shouldDisplayNotesAsEvents
Optional<bool> DisplayNotesAsEvents;
+ /// \sa shouldAggressivelySimplifyBinaryOperation
+ Optional<bool> AggressiveBinaryOperationSimplification;
+
+ /// \sa getCTUDir
+ Optional<StringRef> CTUDir;
+
+ /// \sa getCTUIndexName
+ Optional<StringRef> CTUIndexName;
+
+ /// \sa naiveCTUEnabled
+ Optional<bool> NaiveCTU;
+
+ /// \sa shouldElideConstructors
+ Optional<bool> ElideConstructors;
+
+
/// A helper function that retrieves option for a given full-qualified
/// checker name.
/// Options for checkers can be specified via 'analyzer-config' command-line
@@ -311,6 +361,15 @@ private:
bool SearchInParents = false);
public:
+ AnalyzerOptions()
+ : DisableAllChecks(false), ShowCheckerHelp(false),
+ ShowEnabledCheckerList(false), AnalyzeAll(false),
+ AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false),
+ eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
+ visualizeExplodedGraphWithGraphViz(false),
+ visualizeExplodedGraphWithUbiGraph(false), UnoptimizedCFG(false),
+ PrintStats(false), NoRetryExhausted(false), CXXMemberInliningMode() {}
+
/// Interprets an option's string value as a boolean. The "true" string is
/// interpreted as true and the "false" string is interpreted as false.
///
@@ -320,7 +379,7 @@ public:
/// specified.
/// @param [in] C The optional checker parameter that can be used to restrict
/// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
+ /// depending on search mode).
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
@@ -338,7 +397,7 @@ public:
/// specified.
/// @param [in] C The optional checker parameter that can be used to restrict
/// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
+ /// depending on search mode).
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
@@ -355,7 +414,7 @@ public:
/// specified.
/// @param [in] C The optional checker parameter that can be used to restrict
/// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
+ /// depending on search mode).
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
@@ -372,7 +431,7 @@ public:
/// specified.
/// @param [in] C The optional checker parameter that can be used to restrict
/// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
+ /// depending on search mode).
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
@@ -381,12 +440,14 @@ public:
const ento::CheckerBase *C = nullptr,
bool SearchInParents = false);
- /// \brief Retrieves and sets the UserMode. This is a high-level option,
+ /// Retrieves and sets the UserMode. This is a high-level option,
/// which is used to set other low-level options. It is not accessible
/// outside of AnalyzerOptions.
UserModeKind getUserMode();
- /// \brief Returns the inter-procedural analysis mode.
+ ExplorationStrategyKind getExplorationStrategy();
+
+ /// Returns the inter-procedural analysis mode.
IPAKind getIPAMode();
/// Returns the option controlling which C++ member functions will be
@@ -428,6 +489,19 @@ public:
/// the values "true" and "false".
bool includeLoopExitInCFG();
+ /// Returns whether or not construction site information should be included
+ /// in the CFG C++ constructor elements.
+ ///
+ /// This is controlled by the 'cfg-rich-constructors' config options,
+ /// which accepts the values "true" and "false".
+ bool includeRichConstructorsInCFG();
+
+ /// Returns whether or not scope information should be included in the CFG.
+ ///
+ /// This is controlled by the 'cfg-scope-info' config option, which accepts
+ /// the values "true" and "false".
+ bool includeScopesInCFG();
+
/// Returns whether or not C++ standard library functions may be considered
/// for inlining.
///
@@ -464,6 +538,17 @@ public:
/// accepts the values "true" and "false".
bool mayInlineCXXSharedPtrDtor();
+ /// Returns true if C++ temporary destructors should be inlined during
+ /// analysis.
+ ///
+ /// If temporary destructors are disabled in the CFG via the
+ /// 'cfg-temporary-dtors' option, temporary destructors would not be
+ /// inlined anyway.
+ ///
+ /// This is controlled by the 'c++-temp-dtor-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXTemporaryDtors();
+
/// Returns whether or not paths that go through null returns should be
/// suppressed.
///
@@ -499,6 +584,13 @@ public:
/// which accepts the values "true" and "false".
bool shouldSuppressFromCXXStandardLibrary();
+ /// Returns whether bug reports should be crosschecked with the Z3
+ /// constraint manager backend.
+ ///
+ /// This is controlled by the 'crosscheck-with-z3' config option,
+ /// which accepts the values "true" and "false".
+ bool shouldCrosscheckWithZ3();
+
/// Returns whether or not the diagnostic report should be always reported
/// in the main source file and not the headers.
///
@@ -512,6 +604,14 @@ public:
/// which accepts the values "true" and "false". Default = false
bool shouldWriteStableReportFilename();
+ /// \return Whether the analyzer should
+ /// serialize statistics to plist output.
+ /// Statistics would be serialized in JSON format inside the main dictionary
+ /// under the \c statistics key.
+ /// Available only if compiled in assert mode or with LLVM statistics
+ /// explicitly enabled.
+ bool shouldSerializeStats();
+
/// Returns whether irrelevant parts of a bug report path should be pruned
/// out of the final output.
///
@@ -546,6 +646,11 @@ public:
/// node reclamation, set the option to "0".
unsigned getGraphTrimInterval();
+ /// Returns the maximum complexity of symbolic constraint (50 by default).
+ ///
+ /// This is controlled by "-analyzer-config max-symbol-complexity" option.
+ unsigned getMaxSymbolComplexity();
+
/// Returns the maximum times a large function could be inlined.
///
/// This is controlled by the 'max-times-inline-large' config option.
@@ -585,36 +690,41 @@ public:
/// to false when unset.
bool shouldDisplayNotesAsEvents();
-public:
- AnalyzerOptions() :
- AnalysisStoreOpt(RegionStoreModel),
- AnalysisConstraintsOpt(RangeConstraintsModel),
- AnalysisDiagOpt(PD_HTML),
- AnalysisPurgeOpt(PurgeStmt),
- DisableAllChecks(0),
- ShowCheckerHelp(0),
- ShowEnabledCheckerList(0),
- AnalyzeAll(0),
- AnalyzerDisplayProgress(0),
- AnalyzeNestedBlocks(0),
- eagerlyAssumeBinOpBifurcation(0),
- TrimGraph(0),
- visualizeExplodedGraphWithGraphViz(0),
- visualizeExplodedGraphWithUbiGraph(0),
- UnoptimizedCFG(0),
- PrintStats(0),
- NoRetryExhausted(0),
- // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
- InlineMaxStackDepth(5),
- InliningMode(NoRedundancy),
- UserMode(UMK_NotSet),
- IPAMode(IPAK_NotSet),
- CXXMemberInliningMode() {}
-
+ /// Returns true if SValBuilder should rearrange comparisons and additive
+ /// operations of symbolic expressions which consist of a sum of a symbol and
+ /// a concrete integer into the format where symbols are on the left-hand
+ /// side and the integer is on the right. This is only done if both symbols
+ /// and both concrete integers are signed, greater than or equal to the
+ /// quarter of the minimum value of the type and less than or equal to the
+ /// quarter of the maximum value of that type.
+ ///
+ /// A + n <OP> B + m becomes A - B <OP> m - n, where A and B symbolic,
+ /// n and m are integers. <OP> is any of '==', '!=', '<', '<=', '>', '>=',
+ /// '+' or '-'. The rearrangement also happens with '-' instead of '+' on
+ // either or both side and also if any or both integers are missing.
+ bool shouldAggressivelySimplifyBinaryOperation();
+
+ /// Returns the directory containing the CTU related files.
+ StringRef getCTUDir();
+
+ /// Returns the name of the file containing the CTU index of functions.
+ StringRef getCTUIndexName();
+
+ /// Returns true when naive cross translation unit analysis is enabled.
+ /// This is an experimental feature to inline functions from another
+ /// translation units.
+ bool naiveCTUEnabled();
+
+ /// Returns true if elidable C++ copy-constructors and move-constructors
+ /// should be actually elided during analysis. Both behaviors are allowed
+ /// by the C++ standard, and the analyzer, like CodeGen, defaults to eliding.
+ /// Starting with C++17 some elisions become mandatory, and in these cases
+ /// the option will be ignored.
+ bool shouldElideConstructors();
};
-
-typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef;
-
-}
-#endif
+using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
+
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
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 cd1355d03b63..9041f4c1afbd 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
@@ -1,4 +1,4 @@
-//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===//
+//===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,78 +15,101 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.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"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator_range.h"
+#include <cassert>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
+class AnalyzerOptions;
class ASTContext;
+class Decl;
class DiagnosticsEngine;
+class LocationContext;
+class SourceManager;
class Stmt;
-class ParentMap;
namespace ento {
-class PathDiagnostic;
-class ExplodedNode;
+class BugType;
+class CheckerBase;
class ExplodedGraph;
-class BugReport;
-class BugReporter;
-class BugReporterContext;
+class ExplodedNode;
class ExprEngine;
-class BugType;
+class MemRegion;
+class SValBuilder;
//===----------------------------------------------------------------------===//
// Interface for individual bug reports.
//===----------------------------------------------------------------------===//
+/// A mapping from diagnostic consumers to the diagnostics they should
+/// consume.
+using DiagnosticForConsumerMapTy =
+ llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>;
+
/// This class provides an interface through which checkers can create
/// individual bug reports.
class BugReport : public llvm::ilist_node<BugReport> {
-public:
+public:
class NodeResolver {
virtual void anchor();
+
public:
- virtual ~NodeResolver() {}
+ virtual ~NodeResolver() = default;
+
virtual const ExplodedNode*
getOriginalNode(const ExplodedNode *N) = 0;
};
- typedef const SourceRange *ranges_iterator;
- typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList;
- typedef VisitorList::iterator visitor_iterator;
- typedef SmallVector<StringRef, 2> ExtraTextList;
- typedef SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> NoteList;
+ using ranges_iterator = const SourceRange *;
+ using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
+ using visitor_iterator = VisitorList::iterator;
+ using ExtraTextList = SmallVector<StringRef, 2>;
+ using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>;
protected:
- friend class BugReporter;
friend class BugReportEquivClass;
+ friend class BugReporter;
BugType& BT;
- const Decl *DeclWithIssue;
+ const Decl *DeclWithIssue = nullptr;
std::string ShortDescription;
std::string Description;
PathDiagnosticLocation Location;
PathDiagnosticLocation UniqueingLocation;
const Decl *UniqueingDecl;
-
- const ExplodedNode *ErrorNode;
+
+ const ExplodedNode *ErrorNode = nullptr;
SmallVector<SourceRange, 4> Ranges;
ExtraTextList ExtraText;
NoteList Notes;
- typedef llvm::DenseSet<SymbolRef> Symbols;
- typedef llvm::DenseSet<const MemRegion *> Regions;
+ using Symbols = llvm::DenseSet<SymbolRef>;
+ using Regions = llvm::DenseSet<const MemRegion *>;
/// A (stack of) a set of symbols that are registered with this
/// report as being "interesting", and thus used to help decide which
@@ -113,20 +136,16 @@ protected:
/// Used for ensuring the visitors are only added once.
llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
- /// Used for clients to tell if the report's configuration has changed
- /// since the last time they checked.
- unsigned ConfigurationChangeToken;
-
/// When set, this flag disables all callstack pruning from a diagnostic
/// path. This is useful for some reports that want maximum fidelty
/// when reporting an issue.
- bool DoNotPrunePath;
+ bool DoNotPrunePath = false;
/// Used to track unique reasons why a bug report might be invalid.
///
/// \sa markInvalid
/// \sa removeInvalidation
- typedef std::pair<const void *, const void *> InvalidationRecord;
+ using InvalidationRecord = std::pair<const void *, const void *>;
/// If non-empty, this bug report is likely a false positive and should not be
/// shown to the user.
@@ -146,20 +165,17 @@ private:
public:
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
- ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+ : BT(bt), Description(desc), ErrorNode(errornode) {}
BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
- Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
+ : BT(bt), ShortDescription(shortDesc), Description(desc),
+ ErrorNode(errornode) {}
BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
- ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+ : BT(bt), Description(desc), Location(l) {}
- /// \brief Create a BugReport with a custom uniqueing location.
+ /// Create a BugReport with a custom uniqueing location.
///
/// The reports that have the same report location, description, bug type, and
/// ranges are uniqued - only one of the equivalent reports will be presented
@@ -168,18 +184,15 @@ public:
/// the allocation site, rather then the location where the bug is reported.
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
- : BT(bt), DeclWithIssue(nullptr), Description(desc),
- UniqueingLocation(LocationToUnique),
- UniqueingDecl(DeclToUnique),
- ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
+ : BT(bt), Description(desc), UniqueingLocation(LocationToUnique),
+ UniqueingDecl(DeclToUnique), ErrorNode(errornode) {}
virtual ~BugReport();
const BugType& getBugType() const { return BT; }
BugType& getBugType() { return BT; }
- /// \brief True when the report has an execution path associated with it.
+ /// True when the report has an execution path associated with it.
///
/// A report is said to be path-sensitive if it was thrown against a
/// particular exploded node in the path-sensitive analysis graph.
@@ -207,21 +220,17 @@ public:
/// Disable all path pruning when generating a PathDiagnostic.
void disablePathPruning() { DoNotPrunePath = true; }
-
+
void markInteresting(SymbolRef sym);
void markInteresting(const MemRegion *R);
void markInteresting(SVal V);
void markInteresting(const LocationContext *LC);
-
+
bool isInteresting(SymbolRef sym);
bool isInteresting(const MemRegion *R);
bool isInteresting(SVal V);
bool isInteresting(const LocationContext *LC);
- unsigned getConfigurationChangeToken() const {
- return ConfigurationChangeToken;
- }
-
/// Returns whether or not this report should be considered valid.
///
/// Invalid reports are those that have been classified as likely false
@@ -243,17 +252,10 @@ public:
Invalidations.insert(std::make_pair(Tag, Data));
}
- /// Reverses the effects of a previous invalidation.
- ///
- /// \sa markInvalid
- void removeInvalidation(const void *Tag, const void *Data) {
- Invalidations.erase(std::make_pair(Tag, Data));
- }
-
/// Return the canonical declaration, be it a method or class, where
/// this issue semantically occurred.
const Decl *getDeclWithIssue() const;
-
+
/// Specifically set the Decl where an issue occurred. This isn't necessary
/// for BugReports that cover a path as it will be automatically inferred.
void setDeclWithIssue(const Decl *declWithIssue) {
@@ -286,9 +288,9 @@ public:
return Notes;
}
- /// \brief This allows for addition of meta data to the diagnostic.
+ /// This allows for addition of meta data to the diagnostic.
///
- /// Currently, only the HTMLDiagnosticClient knows how to display it.
+ /// Currently, only the HTMLDiagnosticClient knows how to display it.
void addExtraText(StringRef S) {
ExtraText.push_back(S);
}
@@ -297,26 +299,26 @@ public:
return ExtraText;
}
- /// \brief Return the "definitive" location of the reported bug.
+ /// Return the "definitive" location of the reported bug.
///
/// While a bug can span an entire path, usually there is a specific
/// location that can be used to identify where the key issue occurred.
/// This location is used by clients rendering diagnostics.
virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
- /// \brief Get the location on which the report should be uniqued.
+ /// Get the location on which the report should be uniqued.
PathDiagnosticLocation getUniqueingLocation() const {
return UniqueingLocation;
}
-
- /// \brief Get the declaration containing the uniqueing location.
+
+ /// Get the declaration containing the uniqueing location.
const Decl *getUniqueingDecl() const {
return UniqueingDecl;
}
const Stmt *getStmt() const;
- /// \brief Add a range to a bug report.
+ /// Add a range to a bug report.
///
/// Ranges are used to highlight regions of interest in the source code.
/// They should be at the same source code line as the BugReport location.
@@ -329,10 +331,10 @@ public:
Ranges.push_back(R);
}
- /// \brief Get the SourceRanges associated with the report.
+ /// Get the SourceRanges associated with the report.
virtual llvm::iterator_range<ranges_iterator> getRanges();
- /// \brief Add custom or predefined bug report visitors to this report.
+ /// Add custom or predefined bug report visitors to this report.
///
/// The visitors should be used when the default trace is not sufficient.
/// For example, they allow constructing a more elaborate trace.
@@ -341,6 +343,9 @@ public:
/// registerVarDeclsLastStore().
void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);
+ /// Remove all visitors attached to this bug report.
+ void clearVisitors();
+
/// Iterators through the custom diagnostic visitors.
visitor_iterator visitor_begin() { return Callbacks.begin(); }
visitor_iterator visitor_end() { return Callbacks.end(); }
@@ -356,10 +361,11 @@ public:
//===----------------------------------------------------------------------===//
class BugReportEquivClass : public llvm::FoldingSetNode {
+ friend class BugReporter;
+
/// List of *owned* BugReport objects.
llvm::ilist<BugReport> Reports;
- friend class BugReporter;
void AddReport(std::unique_ptr<BugReport> R) {
Reports.push_back(R.release());
}
@@ -373,8 +379,8 @@ public:
Reports.front().Profile(ID);
}
- typedef llvm::ilist<BugReport>::iterator iterator;
- typedef llvm::ilist<BugReport>::const_iterator const_iterator;
+ using iterator = llvm::ilist<BugReport>::iterator;
+ using const_iterator = llvm::ilist<BugReport>::const_iterator;
iterator begin() { return Reports.begin(); }
iterator end() { return Reports.end(); }
@@ -390,22 +396,26 @@ public:
class BugReporterData {
public:
virtual ~BugReporterData();
+
virtual DiagnosticsEngine& getDiagnostic() = 0;
virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
- virtual SourceManager& getSourceManager() = 0;
- virtual AnalyzerOptions& getAnalyzerOptions() = 0;
+ virtual SourceManager &getSourceManager() = 0;
+ virtual AnalyzerOptions &getAnalyzerOptions() = 0;
};
/// BugReporter is a utility class for generating PathDiagnostics for analysis.
/// It collects the BugReports and BugTypes and knows how to generate
/// and flush the corresponding diagnostics.
+///
+/// The base class is used for generating path-insensitive
class BugReporter {
public:
enum Kind { BaseBRKind, GRBugReporterKind };
private:
- typedef llvm::ImmutableSet<BugType*> BugTypesTy;
+ using BugTypesTy = llvm::ImmutableSet<BugType *>;
+
BugTypesTy::Factory F;
BugTypesTy BugTypes;
@@ -415,27 +425,28 @@ private:
/// Generate and flush the diagnostics for the given bug report.
void FlushReport(BugReportEquivClass& EQ);
- /// Generate and flush the diagnostics for the given bug report
- /// and PathDiagnosticConsumer.
- void FlushReport(BugReport *exampleReport,
- PathDiagnosticConsumer &PD,
- ArrayRef<BugReport*> BugReports);
+ /// Generate the diagnostics for the given bug report.
+ std::unique_ptr<DiagnosticForConsumerMapTy>
+ generateDiagnosticForConsumerMap(BugReport *exampleReport,
+ ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> bugReports);
/// The set of bug reports tracked by the BugReporter.
llvm::FoldingSet<BugReportEquivClass> EQClasses;
+
/// A vector of BugReports for tracking the allocated pointers and cleanup.
std::vector<BugReportEquivClass *> EQClassesVector;
protected:
- BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
- D(d) {}
+ BugReporter(BugReporterData& d, Kind k)
+ : BugTypes(F.getEmptySet()), kind(k), D(d) {}
public:
- BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind),
- D(d) {}
+ BugReporter(BugReporterData& d)
+ : BugTypes(F.getEmptySet()), kind(BaseBRKind), D(d) {}
virtual ~BugReporter();
- /// \brief Generate and flush diagnostics for all bug reports.
+ /// Generate and flush diagnostics for all bug reports.
void FlushReports();
Kind getKind() const { return kind; }
@@ -448,33 +459,31 @@ public:
return D.getPathDiagnosticConsumers();
}
- /// \brief Iterator over the set of BugTypes tracked by the BugReporter.
- typedef BugTypesTy::iterator iterator;
+ /// Iterator over the set of BugTypes tracked by the BugReporter.
+ using iterator = BugTypesTy::iterator;
iterator begin() { return BugTypes.begin(); }
iterator end() { return BugTypes.end(); }
- /// \brief Iterator over the set of BugReports tracked by the BugReporter.
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
+ /// Iterator over the set of BugReports tracked by the BugReporter.
+ using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
ASTContext &getContext() { return D.getASTContext(); }
- SourceManager& getSourceManager() { return D.getSourceManager(); }
+ SourceManager &getSourceManager() { return D.getSourceManager(); }
- AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+ AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }
- virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
- PathDiagnosticConsumer &PC,
- ArrayRef<BugReport *> &bugReports) {
- return true;
+ virtual std::unique_ptr<DiagnosticForConsumerMapTy>
+ generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> &bugReports) {
+ return {};
}
- bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R);
-
void Register(BugType *BT);
- /// \brief Add the given report to the set of reports tracked by BugReporter.
+ /// Add the given report to the set of reports tracked by BugReporter.
///
/// The reports are usually generated by the checkers. Further, they are
/// folded based on the profile value, which is done to coalesce similar
@@ -494,25 +503,22 @@ public:
private:
llvm::StringMap<BugType *> StrBugTypes;
- /// \brief Returns a BugType that is associated with the given name and
+ /// Returns a BugType that is associated with the given name and
/// category.
BugType *getBugTypeForName(CheckName CheckName, StringRef name,
StringRef category);
};
-// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
+/// GRBugReporter is used for generating path-sensitive reports.
class GRBugReporter : public BugReporter {
ExprEngine& Eng;
+
public:
GRBugReporter(BugReporterData& d, ExprEngine& eng)
- : BugReporter(d, GRBugReporterKind), Eng(eng) {}
+ : BugReporter(d, GRBugReporterKind), Eng(eng) {}
~GRBugReporter() override;
- /// getEngine - Return the analysis engine used to analyze a given
- /// function or method.
- ExprEngine &getEngine() { return Eng; }
-
/// getGraph - Get the exploded graph created by the analysis engine
/// for the analyzed method or function.
ExplodedGraph &getGraph();
@@ -521,16 +527,14 @@ public:
/// engine.
ProgramStateManager &getStateManager();
- /// Generates a path corresponding to one of the given bug reports.
- ///
- /// Which report is used for path generation is not specified. The
- /// bug reporter will try to pick the shortest path, but this is not
- /// guaranteed.
+ /// \p bugReports A set of bug reports within a *single* equivalence class
///
- /// \return True if the report was valid and a path was generated,
- /// false if the reports should be considered invalid.
- bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC,
- ArrayRef<BugReport*> &bugReports) override;
+ /// \return A mapping from consumers to the corresponding diagnostics.
+ /// Iterates through the bug reports within a single equivalence class,
+ /// stops at a first non-invalidated report.
+ std::unique_ptr<DiagnosticForConsumerMapTy>
+ generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> &bugReports) override;
/// classof - Used by isa<>, cast<>, and dyn_cast<>.
static bool classof(const BugReporter* R) {
@@ -538,13 +542,29 @@ public:
}
};
+
+class NodeMapClosure : public BugReport::NodeResolver {
+ InterExplodedGraphMap &M;
+
+public:
+ NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
+
+ const ExplodedNode *getOriginalNode(const ExplodedNode *N) override {
+ return M.lookup(N);
+ }
+};
+
class BugReporterContext {
- virtual void anchor();
GRBugReporter &BR;
+ NodeMapClosure NMC;
+
+ virtual void anchor();
+
public:
- BugReporterContext(GRBugReporter& br) : BR(br) {}
+ BugReporterContext(GRBugReporter &br, InterExplodedGraphMap &Backmap)
+ : BR(br), NMC(Backmap) {}
- virtual ~BugReporterContext() {}
+ virtual ~BugReporterContext() = default;
GRBugReporter& getBugReporter() { return BR; }
@@ -554,7 +574,7 @@ public:
return BR.getStateManager();
}
- SValBuilder& getSValBuilder() {
+ SValBuilder &getSValBuilder() {
return getStateManager().getSValBuilder();
}
@@ -566,11 +586,15 @@ public:
return BR.getSourceManager();
}
- virtual BugReport::NodeResolver& getNodeResolver() = 0;
+ AnalyzerOptions &getAnalyzerOptions() {
+ return BR.getAnalyzerOptions();
+ }
+
+ NodeMapClosure& getNodeResolver() { return NMC; }
};
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index 2043896fd26f..da019f83c214 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -1,4 +1,4 @@
-//===--- BugReporterVisitors.h - Generate PathDiagnostics -------*- C++ -*-===//
+//===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,21 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
namespace clang {
+
+class BinaryOperator;
class CFGBlock;
+class DeclRefExpr;
+class Expr;
+class Stmt;
namespace ento {
@@ -29,13 +39,7 @@ class ExplodedNode;
class MemRegion;
class PathDiagnosticPiece;
-/// \brief BugReporterVisitors are used to add custom diagnostics along a path.
-///
-/// Custom visitors should subclass the BugReporterVisitorImpl class for a
-/// default implementation of the clone() method.
-/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
-/// default implementation of clone() will NOT do the right thing, and you
-/// will have to provide your own implementation.)
+/// BugReporterVisitors are used to add custom diagnostics along a path.
class BugReporterVisitor : public llvm::FoldingSetNode {
public:
BugReporterVisitor() = default;
@@ -43,19 +47,13 @@ public:
BugReporterVisitor(BugReporterVisitor &&) {}
virtual ~BugReporterVisitor();
- /// \brief Returns a copy of this BugReporter.
- ///
- /// Custom BugReporterVisitors should not override this method directly.
- /// Instead, they should inherit from BugReporterVisitorImpl and provide
- /// a protected or public copy constructor.
- ///
- /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
- /// default implementation of clone() will NOT do the right thing, and you
- /// will have to provide your own implementation.)
- virtual std::unique_ptr<BugReporterVisitor> clone() const = 0;
-
- /// \brief Return a diagnostic piece which should be associated with the
+ /// Return a diagnostic piece which should be associated with the
/// given node.
+ /// Note that this function does *not* get run on the very last node
+ /// of the report, as the PathDiagnosticPiece associated with the
+ /// last node should be unique.
+ /// Use {@code getEndPath} to customize the note associated with the report
+ /// end instead.
///
/// The last parameter can be used to register a new visitor with the given
/// BugReport while processing a node.
@@ -63,43 +61,32 @@ public:
VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred,
BugReporterContext &BRC, BugReport &BR) = 0;
- /// \brief Provide custom definition for the final diagnostic piece on the
+ /// Last function called on the visitor, no further calls to VisitNode
+ /// would follow.
+ virtual void finalizeVisitor(BugReporterContext &BRC,
+ const ExplodedNode *EndPathNode,
+ BugReport &BR);
+
+ /// Provide custom definition for the final diagnostic piece on the
/// path - the piece, which is displayed before the path is expanded.
///
- /// If returns NULL the default implementation will be used.
- /// Also note that at most one visitor of a BugReport should generate a
- /// non-NULL end of path diagnostic piece.
- virtual std::unique_ptr<PathDiagnosticPiece>
+ /// NOTE that this function can be implemented on at most one used visitor,
+ /// and otherwise it crahes at runtime.
+ virtual std::shared_ptr<PathDiagnosticPiece>
getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR);
virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
- /// \brief Generates the default final diagnostic piece.
- static std::unique_ptr<PathDiagnosticPiece>
+ /// Generates the default final diagnostic piece.
+ static std::shared_ptr<PathDiagnosticPiece>
getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N,
BugReport &BR);
};
-/// This class provides a convenience implementation for clone() using the
-/// Curiously-Recurring Template Pattern. If you are implementing a custom
-/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public
-/// or protected copy constructor.
-///
-/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
-/// default implementation of clone() will NOT do the right thing, and you
-/// will have to provide your own implementation.)
-template <class DERIVED>
-class BugReporterVisitorImpl : public BugReporterVisitor {
- std::unique_ptr<BugReporterVisitor> clone() const override {
- return llvm::make_unique<DERIVED>(*static_cast<const DERIVED *>(this));
- }
-};
-
-class FindLastStoreBRVisitor final
- : public BugReporterVisitorImpl<FindLastStoreBRVisitor> {
+class FindLastStoreBRVisitor final : public BugReporterVisitor {
const MemRegion *R;
SVal V;
- bool Satisfied;
+ bool Satisfied = false;
/// If the visitor is tracking the value directly responsible for the
/// bug, we are going to employ false positive suppression.
@@ -113,10 +100,7 @@ public:
FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R,
bool InEnableNullFPSuppression)
- : R(R),
- V(V),
- Satisfied(false),
- EnableNullFPSuppression(InEnableNullFPSuppression) {}
+ : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression) {}
void Profile(llvm::FoldingSetNodeID &ID) const override;
@@ -126,22 +110,20 @@ public:
BugReport &BR) override;
};
-class TrackConstraintBRVisitor final
- : public BugReporterVisitorImpl<TrackConstraintBRVisitor> {
+class TrackConstraintBRVisitor final : public BugReporterVisitor {
DefinedSVal Constraint;
bool Assumption;
- bool IsSatisfied;
+ bool IsSatisfied = false;
bool IsZeroCheck;
/// We should start tracking from the last node along the path in which the
/// value is constrained.
- bool IsTrackingTurnedOn;
+ bool IsTrackingTurnedOn = false;
public:
TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
- : Constraint(constraint), Assumption(assumption), IsSatisfied(false),
- IsZeroCheck(!Assumption && Constraint.getAs<Loc>()),
- IsTrackingTurnedOn(false) {}
+ : Constraint(constraint), Assumption(assumption),
+ IsZeroCheck(!Assumption && Constraint.getAs<Loc>()) {}
void Profile(llvm::FoldingSetNodeID &ID) const override;
@@ -157,15 +139,12 @@ public:
private:
/// Checks if the constraint is valid in the current state.
bool isUnderconstrained(const ExplodedNode *N) const;
-
};
/// \class NilReceiverBRVisitor
-/// \brief Prints path notes when a message is sent to a nil receiver.
-class NilReceiverBRVisitor final
- : public BugReporterVisitorImpl<NilReceiverBRVisitor> {
+/// Prints path notes when a message is sent to a nil receiver.
+class NilReceiverBRVisitor final : public BugReporterVisitor {
public:
-
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
ID.AddPointer(&x);
@@ -182,9 +161,7 @@ public:
};
/// Visitor that tries to report interesting diagnostics from conditions.
-class ConditionBRVisitor final
- : public BugReporterVisitorImpl<ConditionBRVisitor> {
-
+class ConditionBRVisitor final : public BugReporterVisitor {
// FIXME: constexpr initialization isn't supported by MSVC2013.
static const char *const GenericTrueMessage;
static const char *const GenericFalseMessage;
@@ -243,11 +220,11 @@ public:
static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece);
};
-/// \brief Suppress reports that might lead to known false positives.
+/// Suppress reports that might lead to known false positives.
///
/// Currently this suppresses reports based on locations of bugs.
class LikelyFalsePositiveSuppressionBRVisitor final
- : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> {
+ : public BugReporterVisitor {
public:
static void *getTag() {
static int Tag = 0;
@@ -265,19 +242,16 @@ public:
return nullptr;
}
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override;
+ void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
+ BugReport &BR) override;
};
-/// \brief When a region containing undefined value or '0' value is passed
+/// When a region containing undefined value or '0' value is passed
/// as an argument in a call, marks the call as interesting.
///
/// As a result, BugReporter will not prune the path through the function even
/// if the region's contents are not modified/accessed by the call.
-class UndefOrNullArgVisitor final
- : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
-
+class UndefOrNullArgVisitor final : public BugReporterVisitor {
/// The interesting memory region this visitor is tracking.
const MemRegion *R;
@@ -296,21 +270,20 @@ public:
BugReport &BR) override;
};
-class SuppressInlineDefensiveChecksVisitor final
- : public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> {
+class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor {
/// The symbolic value for which we are tracking constraints.
/// This value is constrained to null in the end of path.
DefinedSVal V;
/// Track if we found the node where the constraint was first added.
- bool IsSatisfied;
+ bool IsSatisfied = false;
/// Since the visitors can be registered on nodes previous to the last
/// node in the BugReport, but the path traversal always starts with the last
/// node, the visitor invariant (that we start with a node in which V is null)
/// might not hold when node visitation starts. We are going to start tracking
/// from the last node in which the value is null.
- bool IsTrackingTurnedOn;
+ bool IsTrackingTurnedOn = false;
public:
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N);
@@ -327,13 +300,11 @@ public:
BugReport &BR) override;
};
-class CXXSelfAssignmentBRVisitor final
- : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> {
-
- bool Satisfied;
+class CXXSelfAssignmentBRVisitor final : public BugReporterVisitor {
+ bool Satisfied = false;
public:
- CXXSelfAssignmentBRVisitor() : Satisfied(false) {}
+ CXXSelfAssignmentBRVisitor() = default;
void Profile(llvm::FoldingSetNodeID &ID) const override {}
@@ -343,6 +314,44 @@ public:
BugReport &BR) override;
};
+/// The bug visitor prints a diagnostic message at the location where a given
+/// variable was tainted.
+class TaintBugVisitor final : public BugReporterVisitor {
+private:
+ const SVal V;
+
+public:
+ TaintBugVisitor(const SVal V) : V(V) {}
+ void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+};
+
+/// The bug visitor will walk all the nodes in a path and collect all the
+/// constraints. When it reaches the root node, will create a refutation
+/// manager and check if the constraints are satisfiable
+class FalsePositiveRefutationBRVisitor final : public BugReporterVisitor {
+private:
+ /// Holds the constraints in a given path
+ ConstraintRangeTy Constraints;
+
+public:
+ FalsePositiveRefutationBRVisitor();
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
+ BugReport &BR) override;
+};
+
namespace bugreporter {
/// Attempts to add visitors to trace a null or undefined value back to its
@@ -370,10 +379,10 @@ const Stmt *GetDenomExpr(const ExplodedNode *N);
const Stmt *GetRetValExpr(const ExplodedNode *N);
bool isDeclRefExprToReference(const Expr *E);
+} // namespace bugreporter
-} // end namespace clang
-} // end namespace ento
-} // end namespace bugreporter
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index d3163ef3e576..3c1f8f718a3b 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -1,4 +1,4 @@
-//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===//
+//===--- BugType.h - Bug Information Description ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -52,7 +52,7 @@ public:
// FIXME: This is a workaround to ensure that the correct check name is used
// The check names are set after the constructors are run.
// In case the BugType object is initialized in the checker's ctor
- // the Check field will be empty. To circumvent this problem we use
+ // the Check field will be empty. To circumvent this problem we use
// CheckerBase whenever it is possible.
StringRef CheckName =
Checker ? Checker->getCheckName().getName() : Check.getName();
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index f31ab2cd81cd..b0bb12feba20 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -1,4 +1,4 @@
-//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===//
+//===- PathDiagnostic.h - Path-Specific Diagnostic Handling -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,37 +14,49 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
-#include "clang/Analysis/ProgramPoint.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
#include <deque>
#include <iterator>
#include <list>
+#include <map>
+#include <memory>
+#include <set>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
-class ConditionalOperator;
+
class AnalysisDeclContext;
class BinaryOperator;
-class CompoundStmt;
+class CallEnter;
+class CallExitEnd;
+class CallExpr;
+class ConditionalOperator;
class Decl;
+class Expr;
class LocationContext;
class MemberExpr;
-class ParentMap;
class ProgramPoint;
class SourceManager;
-class Stmt;
-class CallExpr;
namespace ento {
class ExplodedNode;
class SymExpr;
-typedef const SymExpr* SymbolRef;
+
+using SymbolRef = const SymExpr *;
//===----------------------------------------------------------------------===//
// High-level interface for handlers of path-sensitive diagnostics.
@@ -58,18 +70,18 @@ public:
public:
PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
- typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
-
- /// \brief A vector of <consumer,file> pairs.
+ using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
+
+ /// A vector of <consumer,file> pairs.
ConsumerFiles files;
-
- /// \brief A precomputed hash tag used for uniquing PDFileEntry objects.
+
+ /// A precomputed hash tag used for uniquing PDFileEntry objects.
const llvm::FoldingSetNodeID NodeID;
- /// \brief Used for profiling in the FoldingSet.
+ /// Used for profiling in the FoldingSet.
void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
};
-
+
class FilesMade {
llvm::BumpPtrAllocator Alloc;
llvm::FoldingSet<PDFileEntry> Set;
@@ -82,14 +94,15 @@ public:
void addDiagnostic(const PathDiagnostic &PD,
StringRef ConsumerName,
StringRef fileName);
-
+
PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
};
private:
virtual void anchor();
+
public:
- PathDiagnosticConsumer() : flushed(false) {}
+ PathDiagnosticConsumer() = default;
virtual ~PathDiagnosticConsumer();
void FlushDiagnostics(FilesMade *FilesMade);
@@ -101,16 +114,26 @@ public:
void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
- enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
+ enum PathGenerationScheme {
+ /// Only runs visitors, no output generated.
+ None,
+
+ /// Used for HTML and text output.
+ Minimal,
+
+ /// Used for plist output, used for "arrows" generation.
+ Extensive,
+ };
+
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
-
+
/// Return true if the PathDiagnosticConsumer supports individual
/// PathDiagnostics that span multiple files.
virtual bool supportsCrossFileDiagnostics() const { return false; }
protected:
- bool flushed;
+ bool flushed = false;
llvm::FoldingSet<PathDiagnostic> Diags;
};
@@ -120,31 +143,28 @@ protected:
class PathDiagnosticRange : public SourceRange {
public:
- bool isPoint;
+ bool isPoint = false;
PathDiagnosticRange(SourceRange R, bool isP = false)
- : SourceRange(R), isPoint(isP) {}
-
- PathDiagnosticRange() : isPoint(false) {}
+ : SourceRange(R), isPoint(isP) {}
+ PathDiagnosticRange() = default;
};
-typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
- LocationOrAnalysisDeclContext;
+using LocationOrAnalysisDeclContext =
+ llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
class PathDiagnosticLocation {
private:
- enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
- const Stmt *S;
- const Decl *D;
- const SourceManager *SM;
+ enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
+
+ const Stmt *S = nullptr;
+ const Decl *D = nullptr;
+ const SourceManager *SM = nullptr;
FullSourceLoc Loc;
PathDiagnosticRange Range;
- PathDiagnosticLocation(SourceLocation L, const SourceManager &sm,
- Kind kind)
- : K(kind), S(nullptr), D(nullptr), SM(&sm),
- Loc(genLocation(L)), Range(genRange()) {
- }
+ PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind)
+ : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
FullSourceLoc genLocation(
SourceLocation L = SourceLocation(),
@@ -155,18 +175,15 @@ private:
public:
/// Create an invalid location.
- PathDiagnosticLocation()
- : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
+ PathDiagnosticLocation() = default;
/// Create a location corresponding to the given statement.
PathDiagnosticLocation(const Stmt *s,
const SourceManager &sm,
LocationOrAnalysisDeclContext lac)
- : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
- S(K == StmtK ? s : nullptr),
- D(nullptr), SM(&sm),
- Loc(genLocation(SourceLocation(), lac)),
- Range(genRange(lac)) {
+ : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
+ S(K == StmtK ? s : nullptr), SM(&sm),
+ Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
assert(K == SingleLocK || S);
assert(K == SingleLocK || Loc.isValid());
assert(K == SingleLocK || Range.isValid());
@@ -174,8 +191,7 @@ public:
/// Create a location corresponding to the given declaration.
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
- : K(DeclK), S(nullptr), D(d), SM(&sm),
- Loc(genLocation()), Range(genRange()) {
+ : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
assert(D);
assert(Loc.isValid());
assert(Range.isValid());
@@ -185,8 +201,7 @@ public:
///
/// This should only be used if there are no more appropriate constructors.
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
- : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
- Range(genRange()) {
+ : SM(&sm), Loc(loc, sm), Range(genRange()) {
assert(Loc.isValid());
assert(Range.isValid());
}
@@ -201,6 +216,15 @@ public:
static PathDiagnosticLocation createBegin(const Decl *D,
const SourceManager &SM);
+ /// Create a location for the beginning of the declaration.
+ /// The third argument is ignored, useful for generic treatment
+ /// of statements and declarations.
+ static PathDiagnosticLocation
+ createBegin(const Decl *D, const SourceManager &SM,
+ const LocationOrAnalysisDeclContext LAC) {
+ return createBegin(D, SM);
+ }
+
/// Create a location for the beginning of the statement.
static PathDiagnosticLocation createBegin(const Stmt *S,
const SourceManager &SM,
@@ -248,7 +272,7 @@ public:
const SourceManager &SM);
/// Create a location corresponding to the given valid ExplodedNode.
- static PathDiagnosticLocation create(const ProgramPoint& P,
+ static PathDiagnosticLocation create(const ProgramPoint &P,
const SourceManager &SMng);
/// Create a location corresponding to the next valid ExplodedNode as end
@@ -281,6 +305,12 @@ public:
}
const Stmt *asStmt() const { assert(isValid()); return S; }
+ const Stmt *getStmtOrNull() const {
+ if (!isValid())
+ return nullptr;
+ return asStmt();
+ }
+
const Decl *asDecl() const { assert(isValid()); return D; }
bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
@@ -292,26 +322,27 @@ public:
void flatten();
const SourceManager& getManager() const { assert(isValid()); return *SM; }
-
+
void Profile(llvm::FoldingSetNodeID &ID) const;
void dump() const;
- /// \brief Given an exploded node, retrieve the statement that should be used
+ /// Given an exploded node, retrieve the statement that should be used
/// for the diagnostic location.
static const Stmt *getStmt(const ExplodedNode *N);
- /// \brief Retrieve the statement corresponding to the successor node.
+ /// Retrieve the statement corresponding to the successor node.
static const Stmt *getNextStmt(const ExplodedNode *N);
};
class PathDiagnosticLocationPair {
private:
PathDiagnosticLocation Start, End;
+
public:
PathDiagnosticLocationPair(const PathDiagnosticLocation &start,
const PathDiagnosticLocation &end)
- : Start(start), End(end) {}
+ : Start(start), End(end) {}
const PathDiagnosticLocation &getStart() const { return Start; }
const PathDiagnosticLocation &getEnd() const { return End; }
@@ -323,7 +354,7 @@ public:
Start.flatten();
End.flatten();
}
-
+
void Profile(llvm::FoldingSetNodeID &ID) const {
Start.Profile(ID);
End.Profile(ID);
@@ -344,10 +375,10 @@ private:
const Kind kind;
const DisplayHint Hint;
- /// \brief In the containing bug report, this piece is the last piece from
+ /// In the containing bug report, this piece is the last piece from
/// the main source file.
- bool LastInMainSourceFile;
-
+ bool LastInMainSourceFile = false;
+
/// A constant string that can be used to tag the PathDiagnosticPiece,
/// typically with the identification of the creator. The actual pointer
/// value is meant to be an identifier; the string itself is useful for
@@ -356,30 +387,28 @@ private:
std::vector<SourceRange> ranges;
- PathDiagnosticPiece() = delete;
- PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete;
- void operator=(const PathDiagnosticPiece &P) = delete;
-
protected:
PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
-
PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
public:
+ PathDiagnosticPiece() = delete;
+ PathDiagnosticPiece(const PathDiagnosticPiece &) = delete;
+ PathDiagnosticPiece &operator=(const PathDiagnosticPiece &) = delete;
virtual ~PathDiagnosticPiece();
StringRef getString() const { return str; }
/// Tag this PathDiagnosticPiece with the given C-string.
void setTag(const char *tag) { Tag = tag; }
-
+
/// Return the opaque tag (if any) on the PathDiagnosticPiece.
const void *getTag() const { return Tag.data(); }
-
+
/// Return the string representation of the tag. This is useful
/// for debugging.
StringRef getTagStr() const { return Tag; }
-
+
/// getDisplayHint - Return a hint indicating where the diagnostic should
/// be displayed by the PathDiagnosticConsumer.
DisplayHint getDisplayHint() const { return Hint; }
@@ -420,8 +449,8 @@ public:
class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> {
void flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const;
-public:
+public:
PathPieces flatten(bool ShouldFlattenMacros) const {
PathPieces Result;
flattenTo(Result, Result, ShouldFlattenMacros);
@@ -434,12 +463,13 @@ public:
class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
private:
PathDiagnosticLocation Pos;
+
public:
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
StringRef s,
PathDiagnosticPiece::Kind k,
bool addPosRange = true)
- : PathDiagnosticPiece(s, k), Pos(pos) {
+ : PathDiagnosticPiece(s, k), Pos(pos) {
assert(Pos.isValid() && Pos.asLocation().isValid() &&
"PathDiagnosticSpotPiece's must have a valid location.");
if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
@@ -456,19 +486,19 @@ public:
}
};
-/// \brief Interface for classes constructing Stack hints.
+/// Interface for classes constructing Stack hints.
///
-/// If a PathDiagnosticEvent occurs in a different frame than the final
+/// If a PathDiagnosticEvent occurs in a different frame than the final
/// diagnostic the hints can be used to summarize the effect of the call.
class StackHintGenerator {
public:
virtual ~StackHintGenerator() = 0;
- /// \brief Construct the Diagnostic message for the given ExplodedNode.
+ /// Construct the Diagnostic message for the given ExplodedNode.
virtual std::string getMessage(const ExplodedNode *N) = 0;
};
-/// \brief Constructs a Stack hint for the given symbol.
+/// Constructs a Stack hint for the given symbol.
///
/// The class knows how to construct the stack hint message based on
/// traversing the CallExpr associated with the call and checking if the given
@@ -481,18 +511,20 @@ private:
public:
StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
- ~StackHintGeneratorForSymbol() override {}
+ ~StackHintGeneratorForSymbol() override = default;
- /// \brief Search the call expression for the symbol Sym and dispatch the
+ /// Search the call expression for the symbol Sym and dispatch the
/// 'getMessageForX()' methods to construct a specific message.
std::string getMessage(const ExplodedNode *N) override;
/// Produces the message of the following form:
/// 'Msg via Nth parameter'
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
+
virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
return Msg;
}
+
virtual std::string getMessageForSymbolNotFound() {
return Msg;
}
@@ -511,9 +543,8 @@ public:
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
StringRef s, bool addPosRange = true,
StackHintGenerator *stackHint = nullptr)
- : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
- CallStackHint(stackHint) {}
-
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
+ CallStackHint(stackHint) {}
~PathDiagnosticEventPiece() override;
/// Mark the diagnostic piece as being potentially prunable. This
@@ -532,35 +563,24 @@ public:
bool hasCallStackHint() { return (bool)CallStackHint; }
- /// Produce the hint for the given node. The node contains
+ /// Produce the hint for the given node. The node contains
/// information about the call for which the diagnostic can be generated.
std::string getCallStackMessage(const ExplodedNode *N) {
if (CallStackHint)
return CallStackHint->getMessage(N);
- return "";
+ return {};
}
void dump() const override;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event;
}
};
class PathDiagnosticCallPiece : public PathDiagnosticPiece {
- PathDiagnosticCallPiece(const Decl *callerD,
- const PathDiagnosticLocation &callReturnPos)
- : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
- NoExit(false), IsCalleeAnAutosynthesizedPropertyAccessor(false),
- callReturn(callReturnPos) {}
-
- PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
- : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
- NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false),
- path(oldPath) {}
-
const Decl *Caller;
- const Decl *Callee;
+ const Decl *Callee = nullptr;
// Flag signifying that this diagnostic has only call enter and no matching
// call exit.
@@ -568,33 +588,37 @@ class PathDiagnosticCallPiece : public PathDiagnosticPiece {
// Flag signifying that the callee function is an Objective-C autosynthesized
// property getter or setter.
- bool IsCalleeAnAutosynthesizedPropertyAccessor;
+ bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
// The custom string, which should appear after the call Return Diagnostic.
// TODO: Should we allow multiple diagnostics?
std::string CallStackMessage;
+ PathDiagnosticCallPiece(const Decl *callerD,
+ const PathDiagnosticLocation &callReturnPos)
+ : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false),
+ callReturn(callReturnPos) {}
+ PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
+ : PathDiagnosticPiece(Call), Caller(caller), NoExit(true),
+ path(oldPath) {}
+
public:
PathDiagnosticLocation callEnter;
PathDiagnosticLocation callEnterWithin;
- PathDiagnosticLocation callReturn;
+ PathDiagnosticLocation callReturn;
PathPieces path;
~PathDiagnosticCallPiece() override;
const Decl *getCaller() const { return Caller; }
-
+
const Decl *getCallee() const { return Callee; }
void setCallee(const CallEnter &CE, const SourceManager &SM);
-
+
bool hasCallStackMessage() { return !CallStackMessage.empty(); }
- void setCallStackMessage(StringRef st) {
- CallStackMessage = st;
- }
+ void setCallStackMessage(StringRef st) { CallStackMessage = st; }
- PathDiagnosticLocation getLocation() const override {
- return callEnter;
- }
+ PathDiagnosticLocation getLocation() const override { return callEnter; }
std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
std::shared_ptr<PathDiagnosticEventPiece>
@@ -604,8 +628,8 @@ public:
void flattenLocations() override {
callEnter.flatten();
callReturn.flatten();
- for (PathPieces::iterator I = path.begin(),
- E = path.end(); I != E; ++I) (*I)->flattenLocations();
+ for (const auto &I : path)
+ I->flattenLocations();
}
static std::shared_ptr<PathDiagnosticCallPiece>
@@ -619,28 +643,29 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Call;
}
};
class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
std::vector<PathDiagnosticLocationPair> LPairs;
+
public:
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
const PathDiagnosticLocation &endPos,
StringRef s)
- : PathDiagnosticPiece(s, ControlFlow) {
- LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
- }
+ : PathDiagnosticPiece(s, ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
const PathDiagnosticLocation &endPos)
- : PathDiagnosticPiece(ControlFlow) {
- LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
- }
+ : PathDiagnosticPiece(ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
- ~PathDiagnosticControlFlowPiece() override;
+ ~PathDiagnosticControlFlowPiece() override;
PathDiagnosticLocation getStartLocation() const {
assert(!LPairs.empty() &&
@@ -668,20 +693,23 @@ public:
return getStartLocation();
}
- typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
+ using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
+
iterator begin() { return LPairs.begin(); }
- iterator end() { return LPairs.end(); }
+ iterator end() { return LPairs.end(); }
void flattenLocations() override {
- for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
+ for (auto &I : *this)
+ I.flatten();
}
- typedef std::vector<PathDiagnosticLocationPair>::const_iterator
- const_iterator;
+ using const_iterator =
+ std::vector<PathDiagnosticLocationPair>::const_iterator;
+
const_iterator begin() const { return LPairs.begin(); }
- const_iterator end() const { return LPairs.end(); }
+ const_iterator end() const { return LPairs.end(); }
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == ControlFlow;
}
@@ -693,21 +721,20 @@ public:
class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
public:
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
- : PathDiagnosticSpotPiece(pos, "", Macro) {}
-
+ : PathDiagnosticSpotPiece(pos, "", Macro) {}
~PathDiagnosticMacroPiece() override;
PathPieces subPieces;
-
+
bool containsEvent() const;
void flattenLocations() override {
PathDiagnosticSpotPiece::flattenLocations();
- for (PathPieces::iterator I = subPieces.begin(),
- E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
+ for (const auto &I : subPieces)
+ I->flattenLocations();
}
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Macro;
}
@@ -721,10 +748,9 @@ public:
PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S,
bool AddPosRange = true)
: PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
-
~PathDiagnosticNotePiece() override;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Note;
}
@@ -733,6 +759,9 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
};
+/// File IDs mapped to sets of line numbers.
+using FilesToLineNumsMap = std::map<unsigned, std::set<unsigned>>;
+
/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
/// each which represent the pieces of the path.
@@ -745,41 +774,44 @@ class PathDiagnostic : public llvm::FoldingSetNode {
std::string Category;
std::deque<std::string> OtherDesc;
- /// \brief Loc The location of the path diagnostic report.
+ /// Loc The location of the path diagnostic report.
PathDiagnosticLocation Loc;
PathPieces pathImpl;
SmallVector<PathPieces *, 3> pathStack;
-
- /// \brief Important bug uniqueing location.
+
+ /// Important bug uniqueing location.
/// The location info is useful to differentiate between bugs.
PathDiagnosticLocation UniqueingLoc;
const Decl *UniqueingDecl;
- PathDiagnostic() = delete;
+ /// Lines executed in the path.
+ std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
+
public:
+ PathDiagnostic() = delete;
PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
StringRef category, PathDiagnosticLocation LocationToUnique,
- const Decl *DeclToUnique);
-
+ const Decl *DeclToUnique,
+ std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
~PathDiagnostic();
-
+
const PathPieces &path;
- /// Return the path currently used by builders for constructing the
+ /// Return the path currently used by builders for constructing the
/// PathDiagnostic.
PathPieces &getActivePath() {
if (pathStack.empty())
return pathImpl;
return *pathStack.back();
}
-
+
/// Return a mutable version of 'path'.
PathPieces &getMutablePieces() {
return pathImpl;
}
-
+
/// Return the unrolled size of the path.
unsigned full_size();
@@ -788,7 +820,7 @@ public:
bool isWithinCall() const { return !pathStack.empty(); }
- void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
+ void setEndOfPath(std::shared_ptr<PathDiagnosticPiece> EndPiece) {
assert(!Loc.isValid() && "End location already set!");
Loc = EndPiece->getLocation();
assert(Loc.isValid() && "Invalid location for end-of-path piece");
@@ -801,21 +833,17 @@ public:
VerboseDesc += S;
}
- void resetPath() {
- pathStack.clear();
- pathImpl.clear();
- Loc = PathDiagnosticLocation();
- }
-
- /// \brief If the last piece of the report point to the header file, resets
+ /// If the last piece of the report point to the header file, resets
/// the location of the report to be the last location in the main source
/// file.
void resetDiagnosticLocationToMainFile();
StringRef getVerboseDescription() const { return VerboseDesc; }
+
StringRef getShortDescription() const {
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
}
+
StringRef getCheckName() const { return CheckName; }
StringRef getBugType() const { return BugType; }
StringRef getCategory() const { return Category; }
@@ -825,30 +853,38 @@ public:
/// where the bug manifests.
const Decl *getDeclWithIssue() const { return DeclWithIssue; }
- typedef std::deque<std::string>::const_iterator meta_iterator;
+ using meta_iterator = std::deque<std::string>::const_iterator;
+
meta_iterator meta_begin() const { return OtherDesc.begin(); }
meta_iterator meta_end() const { return OtherDesc.end(); }
void addMeta(StringRef s) { OtherDesc.push_back(s); }
+ using filesmap_iterator = FilesToLineNumsMap::const_iterator;
+
+ filesmap_iterator executedLines_begin() const {
+ return ExecutedLines->begin();
+ }
+
+ filesmap_iterator executedLines_end() const { return ExecutedLines->end(); }
+
PathDiagnosticLocation getLocation() const {
- assert(Loc.isValid() && "No report location set yet!");
return Loc;
}
- /// \brief Get the location on which the report should be uniqued.
+ /// Get the location on which the report should be uniqued.
PathDiagnosticLocation getUniqueingLoc() const {
return UniqueingLoc;
}
- /// \brief Get the declaration containing the uniqueing location.
+ /// Get the declaration containing the uniqueing location.
const Decl *getUniqueingDecl() const {
return UniqueingDecl;
}
void flattenLocations() {
Loc.flatten();
- for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
- I != E; ++I) (*I)->flattenLocations();
+ for (const auto &I : pathImpl)
+ I->flattenLocations();
}
/// Profiles the diagnostic, independent of the path it references.
@@ -862,10 +898,10 @@ public:
/// Two diagnostics with the same issue along different paths will generate
/// different profiles.
void FullProfile(llvm::FoldingSetNodeID &ID) const;
-};
+};
-} // end GR namespace
+} // namespace ento
-} //end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
index f9477762c758..8484cfe4c956 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
@@ -63,7 +63,7 @@ public:
class EndOfTranslationUnit {
template <typename CHECKER>
static void _checkEndOfTranslationUnit(void *checker,
- const TranslationUnitDecl *TU,
+ const TranslationUnitDecl *TU,
AnalysisManager& mgr,
BugReporter &BR) {
((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
@@ -254,9 +254,9 @@ public:
class EndFunction {
template <typename CHECKER>
- static void _checkEndFunction(void *checker,
+ static void _checkEndFunction(void *checker, const ReturnStmt *RS,
CheckerContext &C) {
- ((const CHECKER *)checker)->checkEndFunction(C);
+ ((const CHECKER *)checker)->checkEndFunction(RS, C);
}
public:
@@ -283,6 +283,22 @@ public:
}
};
+class NewAllocator {
+ template <typename CHECKER>
+ static void _checkNewAllocator(void *checker, const CXXNewExpr *NE,
+ SVal Target, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkNewAllocator(NE, Target, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForNewAllocator(
+ CheckerManager::CheckNewAllocatorFunc(checker,
+ _checkNewAllocator<CHECKER>));
+ }
+};
+
class LiveSymbols {
template <typename CHECKER>
static void _checkLiveSymbols(void *checker, ProgramStateRef state,
@@ -315,7 +331,7 @@ public:
class RegionChanges {
template <typename CHECKER>
- static ProgramStateRef
+ static ProgramStateRef
_checkRegionChanges(void *checker,
ProgramStateRef state,
const InvalidatedSymbols *invalidated,
@@ -354,7 +370,7 @@ class PointerEscape {
Kind);
InvalidatedSymbols RegularEscape;
- for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
E = Escaped.end(); I != E; ++I)
if (!ETraits->hasTrait(*I,
RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
@@ -394,7 +410,7 @@ class ConstPointerEscape {
return State;
InvalidatedSymbols ConstEscape;
- for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
E = Escaped.end(); I != E; ++I)
if (ETraits->hasTrait(*I,
RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
@@ -420,7 +436,7 @@ public:
}
};
-
+
template <typename EVENT>
class Event {
template <typename CHECKER>
@@ -488,7 +504,7 @@ public:
/// Dump checker name to stream.
raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
-/// Tag that can use a checker name as a message provider
+/// Tag that can use a checker name as a message provider
/// (see SimpleProgramPointTag).
class CheckerProgramPointTag : public SimpleProgramPointTag {
public:
@@ -532,7 +548,7 @@ public:
}
};
-/// \brief We dereferenced a location that may be null.
+/// We dereferenced a location that may be null.
struct ImplicitNullDerefEvent {
SVal Location;
bool IsLoad;
@@ -544,7 +560,7 @@ struct ImplicitNullDerefEvent {
bool IsDirectDereference;
};
-/// \brief A helper class which wraps a boolean value set to false by default.
+/// A helper class which wraps a boolean value set to false by default.
///
/// This class should behave exactly like 'bool' except that it doesn't need to
/// be explicitly initialized.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 88cb08a4b647..7c353326be46 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -1,4 +1,4 @@
-//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
+//===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,51 +16,62 @@
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LangOptions.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
-#include <utility>
+#include "llvm/ADT/StringRef.h"
#include <vector>
namespace clang {
- class Decl;
- class Stmt;
- class CallExpr;
+
+class AnalyzerOptions;
+class CallExpr;
+class CXXNewExpr;
+class Decl;
+class LocationContext;
+class Stmt;
+class TranslationUnitDecl;
namespace ento {
- class CheckerBase;
- class CheckerRegistry;
- class ExprEngine;
- class AnalysisManager;
- class BugReporter;
- class CheckerContext;
- class ObjCMethodCall;
- class SVal;
- class ExplodedNode;
- class ExplodedNodeSet;
- class ExplodedGraph;
- class ProgramState;
- class NodeBuilder;
- struct NodeBuilderContext;
- class MemRegion;
- class SymbolReaper;
+
+class AnalysisManager;
+class BugReporter;
+class CallEvent;
+class CheckerBase;
+class CheckerContext;
+class CheckerRegistry;
+class ExplodedGraph;
+class ExplodedNode;
+class ExplodedNodeSet;
+class ExprEngine;
+class MemRegion;
+struct NodeBuilderContext;
+class ObjCMethodCall;
+class RegionAndSymbolInvalidationTraits;
+class SVal;
+class SymbolReaper;
template <typename T> class CheckerFn;
template <typename RET, typename... Ps>
class CheckerFn<RET(Ps...)> {
- typedef RET (*Func)(void *, Ps...);
+ using Func = RET (*)(void *, Ps...);
+
Func Fn;
+
public:
CheckerBase *Checker;
- CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
+
+ CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {}
+
RET operator()(Ps... ps) const {
return Fn(Checker, ps...);
}
};
-/// \brief Describes the different reasons a pointer escapes
+/// Describes the different reasons a pointer escapes
/// during analysis.
enum PointerEscapeKind {
/// A pointer escapes due to binding its value to a location
@@ -75,7 +86,7 @@ enum PointerEscapeKind {
/// argument to a function.
PSK_IndirectEscapeOnCall,
- /// The reason for pointer escape is unknown. For example,
+ /// The reason for pointer escape is unknown. For example,
/// a region containing this pointer is invalidated.
PSK_EscapeOther
};
@@ -85,12 +96,15 @@ enum PointerEscapeKind {
// name strings have a lifetime that keeps them alive at least until the path
// diagnostics have been processed.
class CheckName {
- StringRef Name;
friend class ::clang::ento::CheckerRegistry;
+
+ StringRef Name;
+
explicit CheckName(StringRef Name) : Name(Name) {}
public:
CheckName() = default;
+
StringRef getName() const { return Name; }
};
@@ -121,40 +135,27 @@ public:
const LangOptions &getLangOpts() const { return LangOpts; }
AnalyzerOptions &getAnalyzerOptions() { return AOptions; }
- typedef CheckerBase *CheckerRef;
- typedef const void *CheckerTag;
- typedef CheckerFn<void ()> CheckerDtor;
+ using CheckerRef = CheckerBase *;
+ using CheckerTag = const void *;
+ using CheckerDtor = CheckerFn<void ()>;
//===----------------------------------------------------------------------===//
// registerChecker
//===----------------------------------------------------------------------===//
- /// \brief Used to register checkers.
+ /// Used to register checkers.
+ /// All arguments are automatically passed through to the checker
+ /// constructor.
///
/// \returns a pointer to the checker object.
- template <typename CHECKER>
- CHECKER *registerChecker() {
- CheckerTag tag = getTag<CHECKER>();
- CheckerRef &ref = CheckerTags[tag];
- if (ref)
- return static_cast<CHECKER *>(ref); // already registered.
-
- CHECKER *checker = new CHECKER();
- checker->Name = CurrentCheckName;
- CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
- CHECKER::_register(checker, *this);
- ref = checker;
- return checker;
- }
-
- template <typename CHECKER>
- CHECKER *registerChecker(AnalyzerOptions &AOpts) {
+ template <typename CHECKER, typename... AT>
+ CHECKER *registerChecker(AT... Args) {
CheckerTag tag = getTag<CHECKER>();
CheckerRef &ref = CheckerTags[tag];
if (ref)
return static_cast<CHECKER *>(ref); // already registered.
- CHECKER *checker = new CHECKER(AOpts);
+ CHECKER *checker = new CHECKER(Args...);
checker->Name = CurrentCheckName;
CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
CHECKER::_register(checker, *this);
@@ -166,11 +167,11 @@ public:
// Functions for running checkers for AST traversing..
//===----------------------------------------------------------------------===//
- /// \brief Run checkers handling Decls.
+ /// Run checkers handling Decls.
void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
BugReporter &BR);
- /// \brief Run checkers handling Decls containing a Stmt body.
+ /// Run checkers handling Decls containing a Stmt body.
void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
BugReporter &BR);
@@ -178,7 +179,7 @@ public:
// Functions for running checkers for path-sensitive checking.
//===----------------------------------------------------------------------===//
- /// \brief Run checkers for pre-visiting Stmts.
+ /// Run checkers for pre-visiting Stmts.
///
/// The notification is performed for every explored CFGElement, which does
/// not include the control flow statements such as IfStmt.
@@ -191,7 +192,7 @@ public:
runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
}
- /// \brief Run checkers for post-visiting Stmts.
+ /// Run checkers for post-visiting Stmts.
///
/// The notification is performed for every explored CFGElement, which does
/// not include the control flow statements such as IfStmt.
@@ -205,13 +206,13 @@ public:
runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
}
- /// \brief Run checkers for visiting Stmts.
+ /// Run checkers for visiting Stmts.
void runCheckersForStmt(bool isPreVisit,
ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
const Stmt *S, ExprEngine &Eng,
bool wasInlined = false);
- /// \brief Run checkers for pre-visiting obj-c messages.
+ /// Run checkers for pre-visiting obj-c messages.
void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg,
@@ -219,7 +220,7 @@ public:
runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
}
- /// \brief Run checkers for post-visiting obj-c messages.
+ /// Run checkers for post-visiting obj-c messages.
void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg,
@@ -229,7 +230,7 @@ public:
wasInlined);
}
- /// \brief Run checkers for visiting an obj-c message to nil.
+ /// Run checkers for visiting an obj-c message to nil.
void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg,
@@ -238,21 +239,20 @@ public:
Eng);
}
-
- /// \brief Run checkers for visiting obj-c messages.
+ /// Run checkers for visiting obj-c messages.
void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg, ExprEngine &Eng,
bool wasInlined = false);
- /// \brief Run checkers for pre-visiting obj-c messages.
+ /// Run checkers for pre-visiting obj-c messages.
void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
const CallEvent &Call, ExprEngine &Eng) {
runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
}
- /// \brief Run checkers for post-visiting obj-c messages.
+ /// Run checkers for post-visiting obj-c messages.
void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
const CallEvent &Call, ExprEngine &Eng,
bool wasInlined = false) {
@@ -260,13 +260,13 @@ public:
wasInlined);
}
- /// \brief Run checkers for visiting obj-c messages.
+ /// Run checkers for visiting obj-c messages.
void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const CallEvent &Call, ExprEngine &Eng,
bool wasInlined = false);
- /// \brief Run checkers for load/store of a location.
+ /// Run checkers for load/store of a location.
void runCheckersForLocation(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
SVal location,
@@ -275,35 +275,43 @@ public:
const Stmt *BoundEx,
ExprEngine &Eng);
- /// \brief Run checkers for binding of a value to a location.
+ /// Run checkers for binding of a value to a location.
void runCheckersForBind(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
SVal location, SVal val,
const Stmt *S, ExprEngine &Eng,
const ProgramPoint &PP);
- /// \brief Run checkers for end of analysis.
+ /// Run checkers for end of analysis.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng);
- /// \brief Run checkers on beginning of function.
+ /// Run checkers on beginning of function.
void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
const BlockEdge &L,
ExplodedNode *Pred,
ExprEngine &Eng);
- /// \brief Run checkers on end of function.
+ /// Run checkers on end of function.
void runCheckersForEndFunction(NodeBuilderContext &BC,
ExplodedNodeSet &Dst,
ExplodedNode *Pred,
- ExprEngine &Eng);
+ ExprEngine &Eng,
+ const ReturnStmt *RS);
- /// \brief Run checkers for branch condition.
+ /// Run checkers for branch condition.
void runCheckersForBranchCondition(const Stmt *condition,
ExplodedNodeSet &Dst, ExplodedNode *Pred,
ExprEngine &Eng);
- /// \brief Run checkers for live symbols.
+ /// Run checkers between C++ operator new and constructor calls.
+ void runCheckersForNewAllocator(const CXXNewExpr *NE, SVal Target,
+ ExplodedNodeSet &Dst,
+ ExplodedNode *Pred,
+ ExprEngine &Eng,
+ bool wasInlined = false);
+
+ /// Run checkers for live symbols.
///
/// Allows modifying SymbolReaper object. For example, checkers can explicitly
/// register symbols of interest as live. These symbols will not be marked
@@ -311,7 +319,7 @@ public:
void runCheckersForLiveSymbols(ProgramStateRef state,
SymbolReaper &SymReaper);
- /// \brief Run checkers for dead symbols.
+ /// Run checkers for dead symbols.
///
/// Notifies checkers when symbols become dead. For example, this allows
/// checkers to aggressively clean up/reduce the checker state and produce
@@ -322,7 +330,7 @@ public:
ExprEngine &Eng,
ProgramPoint::Kind K);
- /// \brief Run checkers for region changes.
+ /// Run checkers for region changes.
///
/// This corresponds to the check::RegionChanges callback.
/// \param state The current program state.
@@ -341,45 +349,45 @@ public:
const LocationContext *LCtx,
const CallEvent *Call);
- /// \brief Run checkers when pointers escape.
+ /// Run checkers when pointers escape.
///
/// This notifies the checkers about pointer escape, which occurs whenever
/// the analyzer cannot track the symbol any more. For example, as a
- /// result of assigning a pointer into a global or when it's passed to a
+ /// result of assigning a pointer into a global or when it's passed to a
/// function call the analyzer cannot model.
- ///
+ ///
/// \param State The state at the point of escape.
/// \param Escaped The list of escaped symbols.
- /// \param Call The corresponding CallEvent, if the symbols escape as
+ /// \param Call The corresponding CallEvent, if the symbols escape as
/// parameters to the given call.
/// \param Kind The reason of pointer escape.
- /// \param ITraits Information about invalidation for a particular
+ /// \param ITraits Information about invalidation for a particular
/// region/symbol.
/// \returns Checkers can modify the state by returning a new one.
- ProgramStateRef
+ ProgramStateRef
runCheckersForPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ITraits);
+ RegionAndSymbolInvalidationTraits *ITraits);
- /// \brief Run checkers for handling assumptions on symbolic values.
+ /// Run checkers for handling assumptions on symbolic values.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
SVal Cond, bool Assumption);
- /// \brief Run checkers for evaluating a call.
+ /// Run checkers for evaluating a call.
///
/// Warning: Currently, the CallEvent MUST come from a CallExpr!
void runCheckersForEvalCall(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const CallEvent &CE, ExprEngine &Eng);
-
- /// \brief Run checkers for the entire Translation Unit.
+
+ /// Run checkers for the entire Translation Unit.
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
AnalysisManager &mgr,
BugReporter &BR);
- /// \brief Run checkers for debug-printing a ProgramState.
+ /// Run checkers for debug-printing a ProgramState.
///
/// Unlike most other callbacks, any checker can simply implement the virtual
/// method CheckerBase::printState if it has custom data to print.
@@ -397,10 +405,11 @@ public:
// Functions used by the registration mechanism, checkers should not touch
// these directly.
- typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
- CheckDeclFunc;
+ using CheckDeclFunc =
+ CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>;
+
+ using HandlesDeclFunc = bool (*)(const Decl *D);
- typedef bool (*HandlesDeclFunc)(const Decl *D);
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
void _registerForBody(CheckDeclFunc checkfn);
@@ -409,67 +418,67 @@ public:
// Internal registration functions for path-sensitive checking.
//===----------------------------------------------------------------------===//
- typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
-
- typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
- CheckObjCMessageFunc;
-
- typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
- CheckCallFunc;
-
- typedef CheckerFn<void (const SVal &location, bool isLoad,
- const Stmt *S,
- CheckerContext &)>
- CheckLocationFunc;
-
- typedef CheckerFn<void (const SVal &location, const SVal &val,
- const Stmt *S, CheckerContext &)>
- CheckBindFunc;
-
- typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
- CheckEndAnalysisFunc;
-
- typedef CheckerFn<void (CheckerContext &)>
- CheckBeginFunctionFunc;
-
- typedef CheckerFn<void (CheckerContext &)>
- CheckEndFunctionFunc;
-
- typedef CheckerFn<void (const Stmt *, CheckerContext &)>
- CheckBranchConditionFunc;
-
- typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
- CheckDeadSymbolsFunc;
-
- typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
-
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols *symbols,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx,
- const CallEvent *Call)>
- CheckRegionChangesFunc;
-
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols &Escaped,
- const CallEvent *Call,
- PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ITraits)>
- CheckPointerEscapeFunc;
-
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const SVal &cond, bool assumption)>
- EvalAssumeFunc;
-
- typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
- EvalCallFunc;
-
- typedef CheckerFn<void (const TranslationUnitDecl *,
- AnalysisManager&, BugReporter &)>
- CheckEndOfTranslationUnit;
-
- typedef bool (*HandlesStmtFunc)(const Stmt *D);
+ using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
+
+ using CheckObjCMessageFunc =
+ CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
+
+ using CheckCallFunc =
+ CheckerFn<void (const CallEvent &, CheckerContext &)>;
+
+ using CheckLocationFunc =
+ CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S,
+ CheckerContext &)>;
+
+ using CheckBindFunc =
+ CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,
+ CheckerContext &)>;
+
+ using CheckEndAnalysisFunc =
+ CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
+
+ using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
+
+ using CheckEndFunctionFunc =
+ CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
+
+ using CheckBranchConditionFunc =
+ CheckerFn<void (const Stmt *, CheckerContext &)>;
+
+ using CheckNewAllocatorFunc =
+ CheckerFn<void (const CXXNewExpr *, SVal, CheckerContext &)>;
+
+ using CheckDeadSymbolsFunc =
+ CheckerFn<void (SymbolReaper &, CheckerContext &)>;
+
+ using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
+
+ using CheckRegionChangesFunc =
+ CheckerFn<ProgramStateRef (ProgramStateRef,
+ const InvalidatedSymbols *symbols,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
+ const CallEvent *Call)>;
+
+ using CheckPointerEscapeFunc =
+ CheckerFn<ProgramStateRef (ProgramStateRef,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call, PointerEscapeKind Kind,
+ RegionAndSymbolInvalidationTraits *ITraits)>;
+
+ using EvalAssumeFunc =
+ CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond,
+ bool assumption)>;
+
+ using EvalCallFunc = CheckerFn<bool (const CallExpr *, CheckerContext &)>;
+
+ using CheckEndOfTranslationUnit =
+ CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
+ BugReporter &)>;
+
+ using HandlesStmtFunc = bool (*)(const Stmt *D);
+
void _registerForPreStmt(CheckStmtFunc checkfn,
HandlesStmtFunc isForStmtFn);
void _registerForPostStmt(CheckStmtFunc checkfn,
@@ -489,11 +498,13 @@ public:
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
- void _registerForBeginFunction(CheckEndFunctionFunc checkfn);
+ void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
void _registerForEndFunction(CheckEndFunctionFunc checkfn);
void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
+ void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
+
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
@@ -514,13 +525,13 @@ public:
// Internal registration functions for events.
//===----------------------------------------------------------------------===//
- typedef void *EventTag;
- typedef CheckerFn<void (const void *event)> CheckEventFunc;
+ using EventTag = void *;
+ using CheckEventFunc = CheckerFn<void (const void *event)>;
template <typename EVENT>
void _registerListenerForEvent(CheckEventFunc checkfn) {
EventInfo &info = Events[getTag<EVENT>()];
- info.Checkers.push_back(checkfn);
+ info.Checkers.push_back(checkfn);
}
template <typename EVENT>
@@ -535,8 +546,8 @@ public:
if (I == Events.end())
return;
const EventInfo &info = I->second;
- for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
- info.Checkers[i](&event);
+ for (const auto Checker : info.Checkers)
+ Checker(&event);
}
//===----------------------------------------------------------------------===//
@@ -562,8 +573,8 @@ private:
std::vector<CheckDeclFunc> BodyCheckers;
- typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
- typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
+ using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
+ using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
CachedDeclCheckersMapTy CachedDeclCheckersMap;
struct StmtCheckerInfo {
@@ -573,8 +584,8 @@ private:
};
std::vector<StmtCheckerInfo> StmtCheckers;
- typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
- typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
+ using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
+ using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
CachedStmtCheckersMapTy CachedStmtCheckersMap;
const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
@@ -603,6 +614,8 @@ private:
std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
+ std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
+
std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
@@ -619,16 +632,17 @@ private:
struct EventInfo {
SmallVector<CheckEventFunc, 4> Checkers;
- bool HasDispatcher;
- EventInfo() : HasDispatcher(false) { }
+ bool HasDispatcher = false;
+
+ EventInfo() = default;
};
-
- typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
+
+ using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
EventsTy Events;
};
-} // end ento namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
index e981871ae4e0..2d13bf34cd15 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
@@ -28,7 +28,7 @@ class CheckerOptInfo {
public:
CheckerOptInfo(StringRef name, bool enable)
: Name(name), Enable(enable), Claimed(false) { }
-
+
StringRef getName() const { return Name; }
bool isEnabled() const { return Enable; }
bool isDisabled() const { return !isEnabled(); }
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index 3b26ed3e1a09..d580dda73488 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -1,4 +1,4 @@
-//===--- CheckerRegistry.h - Maintains all available checkers ---*- C++ -*-===//
+//===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,9 @@
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstddef>
#include <vector>
// FIXME: move this information to an HTML file in docs/.
@@ -44,7 +47,7 @@
// The clang_registerCheckers function may add any number of checkers to the
// registry. If any checkers require additional initialization, use the three-
// argument form of CheckerRegistry::addChecker.
-//
+//
// To load a checker plugin, specify the full path to the dynamic library as
// the argument to the -load option in the cc1 frontend. You can then enable
// your custom checker using the -analyzer-checker:
@@ -64,8 +67,9 @@
#endif
namespace clang {
-class DiagnosticsEngine;
+
class AnalyzerOptions;
+class DiagnosticsEngine;
namespace ento {
@@ -81,17 +85,18 @@ class CheckerRegistry {
public:
/// Initialization functions perform any necessary setup for a checker.
/// They should include a call to CheckerManager::registerChecker.
- typedef void (*InitializationFunction)(CheckerManager &);
+ using InitializationFunction = void (*)(CheckerManager &);
+
struct CheckerInfo {
InitializationFunction Initialize;
StringRef FullName;
StringRef Desc;
CheckerInfo(InitializationFunction fn, StringRef name, StringRef desc)
- : Initialize(fn), FullName(name), Desc(desc) {}
+ : Initialize(fn), FullName(name), Desc(desc) {}
};
- typedef std::vector<CheckerInfo> CheckerInfoList;
+ using CheckerInfoList = std::vector<CheckerInfo>;
private:
template <typename T>
@@ -136,7 +141,8 @@ private:
mutable llvm::StringMap<size_t> Packages;
};
-} // end namespace ento
-} // end namespace clang
+} // namespace ento
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
index b3c4f1465594..03997aae79ae 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
@@ -17,7 +17,7 @@ class SourceManager;
class FullSourceLoc;
class LangOptions;
-/// \brief Get an MD5 hash to help identify bugs.
+/// Get an MD5 hash to help identify bugs.
///
/// This function returns a hash that helps identify bugs within a source file.
/// This identification can be utilized to diff diagnostic results on different
@@ -29,7 +29,7 @@ class LangOptions;
/// location. The bugtype and the name of the checker is also part of the hash.
/// The last component is the string representation of the enclosing declaration
/// of the associated location.
-///
+///
/// In case a new hash is introduced, the old one should still be maintained for
/// a while. One should not introduce a new hash for every change, it is
/// possible to introduce experimental hashes that may change in the future.
@@ -41,7 +41,7 @@ llvm::SmallString<32> GetIssueHash(const SourceManager &SM,
llvm::StringRef BugType, const Decl *D,
const LangOptions &LangOpts);
-/// \brief Get the string representation of issue hash. See GetIssueHash() for
+/// Get the string representation of issue hash. See GetIssueHash() for
/// more information.
std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc,
llvm::StringRef CheckerName, llvm::StringRef BugType,
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index ce512fd301ee..2e81aa38c8de 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -1,4 +1,4 @@
-//===--- PathDiagnosticClients.h - Path Diagnostic Clients ------*- C++ -*-===//
+//===--- PathDiagnosticConsumers.h - Path Diagnostic Clients ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
index cc8a9b8ef071..243795e720f6 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
@@ -16,7 +16,7 @@
namespace clang {
namespace ento {
-/// \brief A record of the "type" of an APSInt, used for conversions.
+/// A record of the "type" of an APSInt, used for conversions.
class APSIntType {
uint32_t BitWidth;
bool IsUnsigned;
@@ -31,7 +31,7 @@ public:
uint32_t getBitWidth() const { return BitWidth; }
bool isUnsigned() const { return IsUnsigned; }
- /// \brief Convert a given APSInt, in place, to match this type.
+ /// Convert a given APSInt, in place, to match this type.
///
/// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives
/// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF).
@@ -88,12 +88,12 @@ public:
/// for 'unsigned char' (u8).
RangeTestResultKind testInRange(const llvm::APSInt &Val,
bool AllowMixedSign) const LLVM_READONLY;
-
+
bool operator==(const APSIntType &Other) const {
return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
}
- /// \brief Provide an ordering for finding a common conversion type.
+ /// Provide an ordering for finding a common conversion type.
///
/// Unsigned integers are considered to be better conversion types than
/// signed integers of the same width.
@@ -102,7 +102,7 @@ public:
std::tie(Other.BitWidth, Other.IsUnsigned);
}
};
-
+
} // end ento namespace
} // end clang namespace
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 15b930bc3f1e..85369509efcd 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
@@ -45,12 +45,12 @@ class AnalysisManager : public BugReporterData {
public:
AnalyzerOptions &options;
-
+
AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
const LangOptions &lang,
const PathDiagnosticConsumers &Consumers,
StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr,
+ ConstraintManagerCreator constraintmgr,
CheckerManager *checkerMgr,
AnalyzerOptions &Options,
CodeInjector* injector = nullptr);
@@ -60,7 +60,7 @@ public:
void ClearContexts() {
AnaCtxMgr.clear();
}
-
+
AnalysisDeclContextManager& getAnalysisDeclContextManager() {
return AnaCtxMgr;
}
@@ -126,6 +126,36 @@ public:
AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) {
return AnaCtxMgr.getContext(D);
}
+
+ static bool isInCodeFile(SourceLocation SL, const SourceManager &SM) {
+ if (SM.isInMainFile(SL))
+ return true;
+
+ // Support the "unified sources" compilation method (eg. WebKit) that
+ // involves producing non-header files that include other non-header files.
+ // We should be included directly from a UnifiedSource* file
+ // and we shouldn't be a header - which is a very safe defensive check.
+ SourceLocation IL = SM.getIncludeLoc(SM.getFileID(SL));
+ if (!IL.isValid() || !SM.isInMainFile(IL))
+ return false;
+ // Should rather be "file name starts with", but the current .getFilename
+ // includes the full path.
+ if (SM.getFilename(IL).contains("UnifiedSource")) {
+ // It might be great to reuse FrontendOptions::getInputKindForExtension()
+ // but for now it doesn't discriminate between code and header files.
+ return llvm::StringSwitch<bool>(SM.getFilename(SL).rsplit('.').second)
+ .Cases("c", "m", "mm", "C", "cc", "cp", true)
+ .Cases("cpp", "CPP", "c++", "cxx", "cppm", true)
+ .Default(false);
+ }
+
+ return false;
+ }
+
+ bool isInCodeFile(SourceLocation SL) {
+ const SourceManager &SM = getASTContext().getSourceManager();
+ return isInCodeFile(SL, SM);
+ }
};
} // enAnaCtxMgrspace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 4aa87443e4c2..b72b158194c7 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -1,4 +1,4 @@
-//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*---//
+//==- BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -17,12 +17,26 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
namespace clang {
+
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+
namespace ento {
class CompoundValData : public llvm::FoldingSetNode {
@@ -34,7 +48,8 @@ public:
assert(NonLoc::isCompoundType(t));
}
- typedef llvm::ImmutableList<SVal>::iterator iterator;
+ using iterator = llvm::ImmutableList<SVal>::iterator;
+
iterator begin() const { return L.begin(); }
iterator end() const { return L.end(); }
@@ -47,6 +62,7 @@ public:
class LazyCompoundValData : public llvm::FoldingSetNode {
StoreRef store;
const TypedValueRegion *region;
+
public:
LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
: store(st), region(r) {
@@ -63,16 +79,17 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
};
-class PointerToMemberData: public llvm::FoldingSetNode {
+class PointerToMemberData : public llvm::FoldingSetNode {
const DeclaratorDecl *D;
llvm::ImmutableList<const CXXBaseSpecifier *> L;
public:
PointerToMemberData(const DeclaratorDecl *D,
llvm::ImmutableList<const CXXBaseSpecifier *> L)
- : D(D), L(L) {}
+ : D(D), L(L) {}
+
+ using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;
- typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator;
iterator begin() const { return L.begin(); }
iterator end() const { return L.end(); }
@@ -81,24 +98,25 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, D, L); }
const DeclaratorDecl *getDeclaratorDecl() const {return D;}
+
llvm::ImmutableList<const CXXBaseSpecifier *> getCXXBaseList() const {
return L;
}
};
class BasicValueFactory {
- typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
- APSIntSetTy;
+ using APSIntSetTy =
+ llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt>>;
ASTContext &Ctx;
llvm::BumpPtrAllocator& BPAlloc;
- APSIntSetTy APSIntSet;
- void * PersistentSVals;
- void * PersistentSValPairs;
+ APSIntSetTy APSIntSet;
+ void *PersistentSVals = nullptr;
+ void *PersistentSValPairs = nullptr;
llvm::ImmutableList<SVal>::Factory SValListFactory;
- llvm::ImmutableList<const CXXBaseSpecifier*>::Factory CXXBaseListFactory;
+ llvm::ImmutableList<const CXXBaseSpecifier *>::Factory CXXBaseListFactory;
llvm::FoldingSet<CompoundValData> CompoundValDataSet;
llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
llvm::FoldingSet<PointerToMemberData> PointerToMemberDataSet;
@@ -109,9 +127,8 @@ class BasicValueFactory {
public:
BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
- : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr),
- PersistentSValPairs(nullptr), SValListFactory(Alloc),
- CXXBaseListFactory(Alloc) {}
+ : Ctx(ctx), BPAlloc(Alloc), SValListFactory(Alloc),
+ CXXBaseListFactory(Alloc) {}
~BasicValueFactory();
@@ -138,66 +155,66 @@ public:
return getValue(TargetType.convert(From));
}
-
+
const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
APSIntType TargetType = getAPSIntType(T);
if (TargetType == APSIntType(From))
return From;
-
+
return getValue(TargetType.convert(From));
}
- const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
+ const llvm::APSInt &getIntValue(uint64_t X, bool isUnsigned) {
QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
return getValue(X, T);
}
- inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
+ const llvm::APSInt &getMaxValue(const llvm::APSInt &v) {
return getValue(APSIntType(v).getMaxValue());
}
- inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
+ const llvm::APSInt &getMinValue(const llvm::APSInt &v) {
return getValue(APSIntType(v).getMinValue());
}
- inline const llvm::APSInt& getMaxValue(QualType T) {
+ const llvm::APSInt &getMaxValue(QualType T) {
return getValue(getAPSIntType(T).getMaxValue());
}
- inline const llvm::APSInt& getMinValue(QualType T) {
+ const llvm::APSInt &getMinValue(QualType T) {
return getValue(getAPSIntType(T).getMinValue());
}
- inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
+ const llvm::APSInt &Add1(const llvm::APSInt &V) {
llvm::APSInt X = V;
++X;
return getValue(X);
}
- inline const llvm::APSInt& Sub1(const llvm::APSInt& V) {
+ const llvm::APSInt &Sub1(const llvm::APSInt &V) {
llvm::APSInt X = V;
--X;
return getValue(X);
}
- inline const llvm::APSInt& getZeroWithTypeSize(QualType T) {
+ const llvm::APSInt &getZeroWithTypeSize(QualType T) {
assert(T->isScalarType());
return getValue(0, Ctx.getTypeSize(T), true);
}
- inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
+ const llvm::APSInt &getZeroWithPtrWidth(bool isUnsigned = true) {
return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
}
- inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) {
+ const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) {
return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
}
- inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
- return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
+ const llvm::APSInt &getTruthValue(bool b, QualType T) {
+ return getValue(b ? 1 : 0, Ctx.getIntWidth(T), true);
}
- inline const llvm::APSInt& getTruthValue(bool b) {
+ const llvm::APSInt &getTruthValue(bool b) {
return getTruthValue(b, Ctx.getLogicalOperationType());
}
@@ -229,7 +246,7 @@ public:
return CXXBaseListFactory.add(CBS, L);
}
- const clang::ento::PointerToMemberData *accumCXXBase(
+ const PointerToMemberData *accumCXXBase(
llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
const nonloc::PointerToMember &PTM);
@@ -246,8 +263,8 @@ public:
const SVal* getPersistentSVal(SVal X);
};
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
index 1d779e6cb6ec..5e831095abc7 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
@@ -25,7 +25,7 @@ class StackFrameContext;
namespace ento {
/// \class BlockCounter
-/// \brief An abstract data type used to count the number of times a given
+/// An abstract data type used to count the number of times a given
/// block has been visited along a path analyzed by CoreEngine.
class BlockCounter {
void *Data;
@@ -35,7 +35,7 @@ class BlockCounter {
public:
BlockCounter() : Data(nullptr) {}
- unsigned getNumVisited(const StackFrameContext *CallSite,
+ unsigned getNumVisited(const StackFrameContext *CallSite,
unsigned BlockID) const;
class Factory {
@@ -45,7 +45,7 @@ public:
~Factory();
BlockCounter GetEmptyCounter();
- BlockCounter IncrementCount(BlockCounter BC,
+ BlockCounter IncrementCount(BlockCounter BC,
const StackFrameContext *CallSite,
unsigned BlockID);
};
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 9fec217aca72..9078fb94d282 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
@@ -1,4 +1,4 @@
-//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--//
+//===- CallEvent.h - Wrapper for all function and method calls --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,19 +16,43 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/AnalysisDeclContext.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/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <limits>
#include <utility>
namespace clang {
+
+class LocationContext;
class ProgramPoint;
class ProgramPointTag;
+class StackFrameContext;
namespace ento {
@@ -48,31 +72,31 @@ enum CallEventKind {
};
class CallEvent;
-class CallEventManager;
/// This class represents a description of a function call using the number of
/// arguments and the name of the function.
class CallDescription {
friend CallEvent;
- mutable IdentifierInfo *II;
- mutable bool IsLookupDone;
+
+ mutable IdentifierInfo *II = nullptr;
+ mutable bool IsLookupDone = false;
StringRef FuncName;
unsigned RequiredArgs;
public:
- const static unsigned NoArgRequirement = ~0;
- /// \brief Constructs a CallDescription object.
+ const static unsigned NoArgRequirement = std::numeric_limits<unsigned>::max();
+
+ /// Constructs a CallDescription object.
///
/// @param FuncName The name of the function that will be matched.
///
/// @param RequiredArgs The number of arguments that is expected to match a
- /// call. Omit this parameter to match every occurance of call with a given
+ /// call. Omit this parameter to match every occurrence of call with a given
/// name regardless the number of arguments.
CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement)
- : II(nullptr), IsLookupDone(false), FuncName(FuncName),
- RequiredArgs(RequiredArgs) {}
+ : FuncName(FuncName), RequiredArgs(RequiredArgs) {}
- /// \brief Get the name of the function that this object matches.
+ /// Get the name of the function that this object matches.
StringRef getFunctionName() const { return FuncName; }
};
@@ -94,41 +118,42 @@ public:
}
};
-/// \class RuntimeDefinition
-/// \brief Defines the runtime definition of the called function.
-///
-/// Encapsulates the information we have about which Decl will be used
+/// \class RuntimeDefinition
+/// Defines the runtime definition of the called function.
+///
+/// Encapsulates the information we have about which Decl will be used
/// when the call is executed on the given path. When dealing with dynamic
-/// dispatch, the information is based on DynamicTypeInfo and might not be
+/// dispatch, the information is based on DynamicTypeInfo and might not be
/// precise.
class RuntimeDefinition {
/// The Declaration of the function which could be called at runtime.
/// NULL if not available.
- const Decl *D;
+ const Decl *D = nullptr;
/// The region representing an object (ObjC/C++) on which the method is
/// called. With dynamic dispatch, the method definition depends on the
/// runtime type of this object. NULL when the DynamicTypeInfo is
/// precise.
- const MemRegion *R;
+ const MemRegion *R = nullptr;
public:
- RuntimeDefinition(): D(nullptr), R(nullptr) {}
- RuntimeDefinition(const Decl *InD): D(InD), R(nullptr) {}
+ RuntimeDefinition() = default;
+ RuntimeDefinition(const Decl *InD): D(InD) {}
RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}
+
const Decl *getDecl() { return D; }
-
- /// \brief Check if the definition we have is precise.
- /// If not, it is possible that the call dispatches to another definition at
+
+ /// Check if the definition we have is precise.
+ /// If not, it is possible that the call dispatches to another definition at
/// execution time.
bool mayHaveOtherDefinitions() { return R != nullptr; }
-
- /// When other definitions are possible, returns the region whose runtime type
+
+ /// When other definitions are possible, returns the region whose runtime type
/// determines the method definition.
const MemRegion *getDispatchRegion() { return R; }
};
-/// \brief Represents an abstract call to a function or method along a
+/// Represents an abstract call to a function or method along a
/// particular path.
///
/// CallEvents are created through the factory methods of CallEventManager.
@@ -139,15 +164,13 @@ public:
/// Use the "Data" and "Location" fields instead.
class CallEvent {
public:
- typedef CallEventKind Kind;
+ using Kind = CallEventKind;
private:
ProgramStateRef State;
const LocationContext *LCtx;
llvm::PointerUnion<const Expr *, const Decl *> Origin;
- void operator=(const CallEvent &) = delete;
-
protected:
// This is user data for subclasses.
const void *Data;
@@ -158,9 +181,10 @@ protected:
SourceLocation Location;
private:
- mutable unsigned RefCount;
-
template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo;
+
+ mutable unsigned RefCount = 0;
+
void Retain() const { ++RefCount; }
void Release() const;
@@ -168,72 +192,72 @@ protected:
friend class CallEventManager;
CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx)
- : State(std::move(state)), LCtx(lctx), Origin(E), RefCount(0) {}
+ : State(std::move(state)), LCtx(lctx), Origin(E) {}
CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx)
- : State(std::move(state)), LCtx(lctx), Origin(D), RefCount(0) {}
+ : State(std::move(state)), LCtx(lctx), Origin(D) {}
// DO NOT MAKE PUBLIC
CallEvent(const CallEvent &Original)
- : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
- Data(Original.Data), Location(Original.Location), RefCount(0) {}
+ : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
+ Data(Original.Data), Location(Original.Location) {}
/// Copies this CallEvent, with vtable intact, into a new block of memory.
virtual void cloneTo(void *Dest) const = 0;
- /// \brief Get the value of arbitrary expressions at this point in the path.
+ /// Get the value of arbitrary expressions at this point in the path.
SVal getSVal(const Stmt *S) const {
return getState()->getSVal(S, getLocationContext());
}
+ using ValueList = SmallVectorImpl<SVal>;
- typedef SmallVectorImpl<SVal> ValueList;
-
- /// \brief Used to specify non-argument regions that will be invalidated as a
+ /// Used to specify non-argument regions that will be invalidated as a
/// result of this call.
virtual void getExtraInvalidatedValues(ValueList &Values,
RegionAndSymbolInvalidationTraits *ETraits) const {}
public:
- virtual ~CallEvent() {}
+ CallEvent &operator=(const CallEvent &) = delete;
+ virtual ~CallEvent() = default;
- /// \brief Returns the kind of call this is.
+ /// Returns the kind of call this is.
virtual Kind getKind() const = 0;
- /// \brief Returns the declaration of the function or method that will be
+ /// Returns the declaration of the function or method that will be
/// called. May be null.
virtual const Decl *getDecl() const {
return Origin.dyn_cast<const Decl *>();
}
- /// \brief The state in which the call is being evaluated.
+ /// The state in which the call is being evaluated.
const ProgramStateRef &getState() const {
return State;
}
- /// \brief The context in which the call is being evaluated.
+ /// The context in which the call is being evaluated.
const LocationContext *getLocationContext() const {
return LCtx;
}
- /// \brief Returns the definition of the function or method that will be
+ /// Returns the definition of the function or method that will be
/// called.
virtual RuntimeDefinition getRuntimeDefinition() const = 0;
- /// \brief Returns the expression whose value will be the result of this call.
+ /// Returns the expression whose value will be the result of this call.
/// May be null.
const Expr *getOriginExpr() const {
return Origin.dyn_cast<const Expr *>();
}
- /// \brief Returns the number of arguments (explicit and implicit).
+ /// Returns the number of arguments (explicit and implicit).
///
/// Note that this may be greater than the number of parameters in the
/// callee's declaration, and that it may include arguments not written in
/// the source.
virtual unsigned getNumArgs() const = 0;
- /// \brief Returns true if the callee is known to be from a system header.
+ /// Returns true if the callee is known to be from a system header.
bool isInSystemHeader() const {
const Decl *D = getDecl();
if (!D)
@@ -248,57 +272,57 @@ public:
// Special case for implicitly-declared global operator new/delete.
// These should be considered system functions.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal();
return false;
}
- /// \brief Returns true if the CallEvent is a call to a function that matches
+ /// Returns true if the CallEvent is a call to a function that matches
/// the CallDescription.
///
/// Note that this function is not intended to be used to match Obj-C method
/// calls.
bool isCalled(const CallDescription &CD) const;
- /// \brief Returns a source range for the entire call, suitable for
+ /// Returns a source range for the entire call, suitable for
/// outputting in diagnostics.
virtual SourceRange getSourceRange() const {
return getOriginExpr()->getSourceRange();
}
- /// \brief Returns the value of a given argument at the time of the call.
+ /// Returns the value of a given argument at the time of the call.
virtual SVal getArgSVal(unsigned Index) const;
- /// \brief Returns the expression associated with a given argument.
+ /// Returns the expression associated with a given argument.
/// May be null if this expression does not appear in the source.
virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; }
- /// \brief Returns the source range for errors associated with this argument.
+ /// Returns the source range for errors associated with this argument.
///
/// May be invalid if the argument is not written in the source.
virtual SourceRange getArgSourceRange(unsigned Index) const;
- /// \brief Returns the result type, adjusted for references.
+ /// Returns the result type, adjusted for references.
QualType getResultType() const;
- /// \brief Returns the return value of the call.
+ /// Returns the return value of the call.
///
/// This should only be called if the CallEvent was created using a state in
/// which the return value has already been bound to the origin expression.
SVal getReturnValue() const;
- /// \brief Returns true if the type of any of the non-null arguments satisfies
+ /// Returns true if the type of any of the non-null arguments satisfies
/// the condition.
bool hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const;
- /// \brief Returns true if any of the arguments appear to represent callbacks.
+ /// Returns true if any of the arguments appear to represent callbacks.
bool hasNonZeroCallbackArg() const;
- /// \brief Returns true if any of the arguments is void*.
+ /// Returns true if any of the arguments is void*.
bool hasVoidPointerToNonConstArg() const;
- /// \brief Returns true if any of the arguments are known to escape to long-
+ /// Returns true if any of the arguments are known to escape to long-
/// term storage, even if this method will not modify them.
// NOTE: The exact semantics of this are still being defined!
// We don't really want a list of hardcoded exceptions in the long run,
@@ -307,7 +331,7 @@ public:
return hasNonZeroCallbackArg();
}
- /// \brief Returns true if the callee is an externally-visible function in the
+ /// Returns true if the callee is an externally-visible function in the
/// top-level namespace, such as \c malloc.
///
/// You can use this call to determine that a particular function really is
@@ -325,7 +349,7 @@ public:
// precise callbacks.
bool isGlobalCFunction(StringRef SpecificName = StringRef()) const;
- /// \brief Returns the name of the callee, if its name is a simple identifier.
+ /// Returns the name of the callee, if its name is a simple identifier.
///
/// Note that this will fail for Objective-C methods, blocks, and C++
/// overloaded operators. The former is named by a Selector rather than a
@@ -333,25 +357,25 @@ public:
// FIXME: Move this down to AnyFunctionCall once checkers have more
// precise callbacks.
const IdentifierInfo *getCalleeIdentifier() const {
- const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl());
+ const auto *ND = dyn_cast_or_null<NamedDecl>(getDecl());
if (!ND)
return nullptr;
return ND->getIdentifier();
}
- /// \brief Returns an appropriate ProgramPoint for this call.
+ /// Returns an appropriate ProgramPoint for this call.
ProgramPoint getProgramPoint(bool IsPreVisit = false,
const ProgramPointTag *Tag = nullptr) const;
- /// \brief Returns a new state with all argument regions invalidated.
+ /// Returns a new state with all argument regions invalidated.
///
/// This accepts an alternate state in case some processing has already
/// occurred.
ProgramStateRef invalidateRegions(unsigned BlockCount,
ProgramStateRef Orig = nullptr) const;
- typedef std::pair<Loc, SVal> FrameBindingTy;
- typedef SmallVectorImpl<FrameBindingTy> BindingsTy;
+ using FrameBindingTy = std::pair<Loc, SVal>;
+ using BindingsTy = SmallVectorImpl<FrameBindingTy>;
/// Populates the given SmallVector with the bindings in the callee's stack
/// frame at the start of this call.
@@ -367,20 +391,60 @@ public:
return cloneWithState<CallEvent>(NewState);
}
- /// \brief Returns true if this is a statement is a function or method call
+ /// Returns true if this is a statement is a function or method call
/// of some kind.
static bool isCallStmt(const Stmt *S);
- /// \brief Returns the result type of a function or method declaration.
+ /// Returns the result type of a function or method declaration.
///
/// This will return a null QualType if the result type cannot be determined.
static QualType getDeclaredResultType(const Decl *D);
- /// \brief Returns true if the given decl is known to be variadic.
+ /// Returns true if the given decl is known to be variadic.
///
/// \p D must not be null.
static bool isVariadic(const Decl *D);
+ /// Returns AnalysisDeclContext for the callee stack frame.
+ /// Currently may fail; returns null on failure.
+ AnalysisDeclContext *getCalleeAnalysisDeclContext() const;
+
+ /// Returns the callee stack frame. That stack frame will only be entered
+ /// during analysis if the call is inlined, but it may still be useful
+ /// in intermediate calculations even if the call isn't inlined.
+ /// May fail; returns null on failure.
+ const StackFrameContext *getCalleeStackFrame() const;
+
+ /// Returns memory location for a parameter variable within the callee stack
+ /// frame. May fail; returns null on failure.
+ const VarRegion *getParameterLocation(unsigned Index) const;
+
+ /// Returns true if on the current path, the argument was constructed by
+ /// calling a C++ constructor over it. This is an internal detail of the
+ /// analysis which doesn't necessarily represent the program semantics:
+ /// if we are supposed to construct an argument directly, we may still
+ /// not do that because we don't know how (i.e., construction context is
+ /// unavailable in the CFG or not supported by the analyzer).
+ bool isArgumentConstructedDirectly(unsigned Index) const {
+ // This assumes that the object was not yet removed from the state.
+ return ExprEngine::getObjectUnderConstruction(
+ getState(), {getOriginExpr(), Index}, getCalleeStackFrame()).hasValue();
+ }
+
+ /// Some calls have parameter numbering mismatched from argument numbering.
+ /// This function converts an argument index to the corresponding
+ /// parameter index. Returns None is the argument doesn't correspond
+ /// to any parameter variable.
+ Optional<unsigned> getAdjustedParameterIndex(unsigned ArgumentIndex) const {
+ if (dyn_cast_or_null<CXXOperatorCallExpr>(getOriginExpr()) &&
+ dyn_cast_or_null<CXXMethodDecl>(getDecl())) {
+ // For member operator calls argument 0 on the expression corresponds
+ // to implicit this-parameter on the declaration.
+ return (ArgumentIndex > 0) ? Optional<unsigned>(ArgumentIndex - 1) : None;
+ }
+ return ArgumentIndex;
+ }
+
// Iterator access to formal parameters and their types.
private:
struct GetTypeFn {
@@ -393,10 +457,10 @@ public:
/// Remember that the number of formal parameters may not match the number
/// of arguments for all calls. However, the first parameter will always
/// correspond with the argument value returned by \c getArgSVal(0).
- virtual ArrayRef<ParmVarDecl*> parameters() const = 0;
+ virtual ArrayRef<ParmVarDecl *> parameters() const = 0;
- typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, GetTypeFn>
- param_type_iterator;
+ using param_type_iterator =
+ llvm::mapped_iterator<ArrayRef<ParmVarDecl *>::iterator, GetTypeFn>;
/// Returns an iterator over the types of the call's formal parameters.
///
@@ -416,18 +480,17 @@ public:
void dump() const;
};
-
-/// \brief Represents a call to any sort of function that might have a
+/// Represents a call to any sort of function that might have a
/// FunctionDecl.
class AnyFunctionCall : public CallEvent {
protected:
AnyFunctionCall(const Expr *E, ProgramStateRef St,
const LocationContext *LCtx)
- : CallEvent(E, St, LCtx) {}
+ : CallEvent(E, St, LCtx) {}
AnyFunctionCall(const Decl *D, ProgramStateRef St,
const LocationContext *LCtx)
- : CallEvent(D, St, LCtx) {}
- AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {}
+ : CallEvent(D, St, LCtx) {}
+ AnyFunctionCall(const AnyFunctionCall &Other) = default;
public:
// This function is overridden by subclasses, but they must return
@@ -451,7 +514,7 @@ public:
}
};
-/// \brief Represents a C function or static C++ member function call.
+/// Represents a C function or static C++ member function call.
///
/// Example: \c fun()
class SimpleFunctionCall : public AnyFunctionCall {
@@ -460,9 +523,9 @@ class SimpleFunctionCall : public AnyFunctionCall {
protected:
SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
- : AnyFunctionCall(CE, St, LCtx) {}
- SimpleFunctionCall(const SimpleFunctionCall &Other)
- : AnyFunctionCall(Other) {}
+ : AnyFunctionCall(CE, St, LCtx) {}
+ SimpleFunctionCall(const SimpleFunctionCall &Other) = default;
+
void cloneTo(void *Dest) const override {
new (Dest) SimpleFunctionCall(*this);
}
@@ -487,7 +550,7 @@ public:
}
};
-/// \brief Represents a call to a block.
+/// Represents a call to a block.
///
/// Example: <tt>^{ /* ... */ }()</tt>
class BlockCall : public CallEvent {
@@ -496,9 +559,9 @@ class BlockCall : public CallEvent {
protected:
BlockCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
- : CallEvent(CE, St, LCtx) {}
+ : CallEvent(CE, St, LCtx) {}
+ BlockCall(const BlockCall &Other) = default;
- BlockCall(const BlockCall &Other) : CallEvent(Other) {}
void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); }
void getExtraInvalidatedValues(ValueList &Values,
@@ -515,7 +578,7 @@ public:
return getOriginExpr()->getArg(Index);
}
- /// \brief Returns the region associated with this instance of the block.
+ /// Returns the region associated with this instance of the block.
///
/// This may be NULL if the block's origin is unknown.
const BlockDataRegion *getBlockRegion() const;
@@ -535,7 +598,7 @@ public:
return BD->isConversionFromLambda();
}
- /// \brief For a block converted from a C++ lambda, returns the block
+ /// For a block converted from a C++ lambda, returns the block
/// VarRegion for the variable holding the captured C++ lambda record.
const VarRegion *getRegionStoringCapturedLambda() const {
assert(isConversionFromLambda());
@@ -594,28 +657,26 @@ public:
}
};
-/// \brief Represents a non-static C++ member function call, no matter how
+/// Represents a non-static C++ member function call, no matter how
/// it is written.
class CXXInstanceCall : public AnyFunctionCall {
protected:
- void getExtraInvalidatedValues(ValueList &Values,
- RegionAndSymbolInvalidationTraits *ETraits) const override;
-
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
- : AnyFunctionCall(CE, St, LCtx) {}
+ : AnyFunctionCall(CE, St, LCtx) {}
CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St,
const LocationContext *LCtx)
- : AnyFunctionCall(D, St, LCtx) {}
-
+ : AnyFunctionCall(D, St, LCtx) {}
+ CXXInstanceCall(const CXXInstanceCall &Other) = default;
- CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {}
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
public:
- /// \brief Returns the expression representing the implicit 'this' object.
+ /// Returns the expression representing the implicit 'this' object.
virtual const Expr *getCXXThisExpr() const { return nullptr; }
- /// \brief Returns the value of the implicit 'this' object.
+ /// Returns the value of the implicit 'this' object.
virtual SVal getCXXThisVal() const;
const FunctionDecl *getDecl() const override;
@@ -631,7 +692,7 @@ public:
}
};
-/// \brief Represents a non-static C++ member function call.
+/// Represents a non-static C++ member function call.
///
/// Example: \c obj.fun()
class CXXMemberCall : public CXXInstanceCall {
@@ -640,9 +701,9 @@ class CXXMemberCall : public CXXInstanceCall {
protected:
CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
- : CXXInstanceCall(CE, St, LCtx) {}
+ : CXXInstanceCall(CE, St, LCtx) {}
+ CXXMemberCall(const CXXMemberCall &Other) = default;
- CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); }
public:
@@ -671,7 +732,7 @@ public:
}
};
-/// \brief Represents a C++ overloaded operator call where the operator is
+/// Represents a C++ overloaded operator call where the operator is
/// implemented as a non-static member function.
///
/// Example: <tt>iter + 1</tt>
@@ -681,10 +742,9 @@ class CXXMemberOperatorCall : public CXXInstanceCall {
protected:
CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
- : CXXInstanceCall(CE, St, LCtx) {}
+ : CXXInstanceCall(CE, St, LCtx) {}
+ CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) = default;
- CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
- : CXXInstanceCall(Other) {}
void cloneTo(void *Dest) const override {
new (Dest) CXXMemberOperatorCall(*this);
}
@@ -697,6 +757,7 @@ public:
unsigned getNumArgs() const override {
return getOriginExpr()->getNumArgs() - 1;
}
+
const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index + 1);
}
@@ -710,7 +771,7 @@ public:
}
};
-/// \brief Represents an implicit call to a C++ destructor.
+/// Represents an implicit call to a C++ destructor.
///
/// This can occur at the end of a scope (for automatic objects), at the end
/// of a full-expression (for temporaries), or as part of a delete.
@@ -718,7 +779,7 @@ class CXXDestructorCall : public CXXInstanceCall {
friend class CallEventManager;
protected:
- typedef llvm::PointerIntPair<const MemRegion *, 1, bool> DtorDataTy;
+ using DtorDataTy = llvm::PointerIntPair<const MemRegion *, 1, bool>;
/// Creates an implicit destructor.
///
@@ -730,12 +791,13 @@ protected:
CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
const MemRegion *Target, bool IsBaseDestructor,
ProgramStateRef St, const LocationContext *LCtx)
- : CXXInstanceCall(DD, St, LCtx) {
+ : CXXInstanceCall(DD, St, LCtx) {
Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue();
Location = Trigger->getLocEnd();
}
- CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {}
+ CXXDestructorCall(const CXXDestructorCall &Other) = default;
+
void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);}
public:
@@ -744,7 +806,7 @@ public:
RuntimeDefinition getRuntimeDefinition() const override;
- /// \brief Returns the value of the implicit 'this' object.
+ /// Returns the value of the implicit 'this' object.
SVal getCXXThisVal() const override;
/// Returns true if this is a call to a base class destructor.
@@ -759,7 +821,7 @@ public:
}
};
-/// \brief Represents a call to a C++ constructor.
+/// Represents a call to a C++ constructor.
///
/// Example: \c T(1)
class CXXConstructorCall : public AnyFunctionCall {
@@ -775,11 +837,12 @@ protected:
/// \param LCtx The location context at this point in the program.
CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target,
ProgramStateRef St, const LocationContext *LCtx)
- : AnyFunctionCall(CE, St, LCtx) {
+ : AnyFunctionCall(CE, St, LCtx) {
Data = Target;
}
- CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
+ CXXConstructorCall(const CXXConstructorCall &Other) = default;
+
void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); }
void getExtraInvalidatedValues(ValueList &Values,
@@ -800,7 +863,7 @@ public:
return getOriginExpr()->getArg(Index);
}
- /// \brief Returns the value of the implicit 'this' object.
+ /// Returns the value of the implicit 'this' object.
SVal getCXXThisVal() const;
void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
@@ -813,7 +876,7 @@ public:
}
};
-/// \brief Represents the memory allocation call in a C++ new-expression.
+/// Represents the memory allocation call in a C++ new-expression.
///
/// This is a call to "operator new".
class CXXAllocatorCall : public AnyFunctionCall {
@@ -822,9 +885,9 @@ class CXXAllocatorCall : public AnyFunctionCall {
protected:
CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St,
const LocationContext *LCtx)
- : AnyFunctionCall(E, St, LCtx) {}
+ : AnyFunctionCall(E, St, LCtx) {}
+ CXXAllocatorCall(const CXXAllocatorCall &Other) = default;
- CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {}
void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); }
public:
@@ -854,7 +917,7 @@ public:
}
};
-/// \brief Represents the ways an Objective-C message send can occur.
+/// Represents the ways an Objective-C message send can occur.
//
// Note to maintainers: OCM_Message should always be last, since it does not
// need to fit in the Data field's low bits.
@@ -864,7 +927,7 @@ enum ObjCMessageKind {
OCM_Message
};
-/// \brief Represents any expression that calls an Objective-C method.
+/// Represents any expression that calls an Objective-C method.
///
/// This includes all of the kinds listed in ObjCMessageKind.
class ObjCMethodCall : public CallEvent {
@@ -875,11 +938,12 @@ class ObjCMethodCall : public CallEvent {
protected:
ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St,
const LocationContext *LCtx)
- : CallEvent(Msg, St, LCtx) {
+ : CallEvent(Msg, St, LCtx) {
Data = nullptr;
}
- ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
+ ObjCMethodCall(const ObjCMethodCall &Other) = default;
+
void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); }
void getExtraInvalidatedValues(ValueList &Values,
@@ -893,12 +957,15 @@ public:
virtual const ObjCMessageExpr *getOriginExpr() const {
return cast<ObjCMessageExpr>(CallEvent::getOriginExpr());
}
+
const ObjCMethodDecl *getDecl() const override {
return getOriginExpr()->getMethodDecl();
}
+
unsigned getNumArgs() const override {
return getOriginExpr()->getNumArgs();
}
+
const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index);
}
@@ -906,22 +973,24 @@ public:
bool isInstanceMessage() const {
return getOriginExpr()->isInstanceMessage();
}
+
ObjCMethodFamily getMethodFamily() const {
return getOriginExpr()->getMethodFamily();
}
+
Selector getSelector() const {
return getOriginExpr()->getSelector();
}
SourceRange getSourceRange() const override;
- /// \brief Returns the value of the receiver at the time of this call.
+ /// Returns the value of the receiver at the time of this call.
SVal getReceiverSVal() const;
- /// \brief Return the value of 'self' if available.
+ /// Return the value of 'self' if available.
SVal getSelfSVal() const;
- /// \brief Get the interface for the receiver.
+ /// Get the interface for the receiver.
///
/// This works whether this is an instance message or a class message.
/// However, it currently just uses the static type of the receiver.
@@ -929,7 +998,7 @@ public:
return getOriginExpr()->getReceiverInterface();
}
- /// \brief Checks if the receiver refers to 'self' or 'super'.
+ /// Checks if the receiver refers to 'self' or 'super'.
bool isReceiverSelfOrSuper() const;
/// Returns how the message was written in the source (property access,
@@ -971,8 +1040,7 @@ public:
}
};
-
-/// \brief Manages the lifetime of CallEvent objects.
+/// Manages the lifetime of CallEvent objects.
///
/// CallEventManager provides a way to create arbitrary CallEvents "on the
/// stack" as if they were value objects by keeping a cache of CallEvent-sized
@@ -984,7 +1052,8 @@ class CallEventManager {
llvm::BumpPtrAllocator &Alloc;
SmallVector<void *, 8> Cache;
- typedef SimpleFunctionCall CallEventTemplateTy;
+
+ using CallEventTemplateTy = SimpleFunctionCall;
void reclaim(const void *Memory) {
Cache.push_back(const_cast<void *>(Memory));
@@ -1032,11 +1101,9 @@ class CallEventManager {
public:
CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {}
-
CallEventRef<>
getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State);
-
CallEventRef<>
getSimpleCall(const CallExpr *E, ProgramStateRef State,
const LocationContext *LCtx);
@@ -1067,7 +1134,6 @@ public:
}
};
-
template <typename T>
CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const {
assert(isa<T>(*this) && "Cloning to unrelated type");
@@ -1099,19 +1165,22 @@ inline void CallEvent::Release() const {
this->~CallEvent();
}
-} // end namespace ento
-} // end namespace clang
+} // namespace ento
+
+} // namespace clang
namespace llvm {
- // Support isa<>, cast<>, and dyn_cast<> for CallEventRef.
- template<class T> struct simplify_type< clang::ento::CallEventRef<T> > {
- typedef const T *SimpleType;
- static SimpleType
- getSimplifiedValue(clang::ento::CallEventRef<T> Val) {
- return Val.get();
- }
- };
-}
+// Support isa<>, cast<>, and dyn_cast<> for CallEventRef.
+template<class T> struct simplify_type< clang::ento::CallEventRef<T>> {
+ using SimpleType = const T *;
+
+ static SimpleType
+ getSimplifiedValue(clang::ento::CallEventRef<T> Val) {
+ return Val.get();
+ }
+};
+
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
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 78d38a3d598d..ce2b711a4a1b 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
@@ -51,7 +51,7 @@ namespace ento {
/// be accessible from more than one translation unit.
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
-
+
/// Declares an immutable list of type \p NameTy, suitable for placement into
/// the ProgramState. This is implementing using llvm::ImmutableList.
///
@@ -83,7 +83,7 @@ public:
/// If we are post visiting a call, this flag will be set if the
/// call was inlined. In all other cases it will be false.
const bool wasInlined;
-
+
CheckerContext(NodeBuilder &builder,
ExprEngine &eng,
ExplodedNode *pred,
@@ -110,18 +110,18 @@ public:
StoreManager &getStoreManager() {
return Eng.getStoreManager();
}
-
- /// \brief Returns the previous node in the exploded graph, which includes
+
+ /// Returns the previous node in the exploded graph, which includes
/// the state of the program before the checker ran. Note, checkers should
/// not retain the node in their state since the nodes might get invalidated.
ExplodedNode *getPredecessor() { return Pred; }
const ProgramStateRef &getState() const { return Pred->getState(); }
- /// \brief Check if the checker changed the state of the execution; ex: added
+ /// Check if the checker changed the state of the execution; ex: added
/// a new transition or a bug report.
bool isDifferent() { return Changed; }
- /// \brief Returns the number of times the current block has been visited
+ /// Returns the number of times the current block has been visited
/// along the analyzed path.
unsigned blockCount() const {
return NB.getContext().blockCount();
@@ -149,7 +149,7 @@ public:
BugReporter &getBugReporter() {
return Eng.getBugReporter();
}
-
+
SourceManager &getSourceManager() {
return getBugReporter().getSourceManager();
}
@@ -174,12 +174,12 @@ public:
return Pred->getLocationContext()->getAnalysisDeclContext();
}
- /// \brief Get the blockID.
+ /// Get the blockID.
unsigned getBlockID() const {
return NB.getContext().getBlock()->getBlockID();
}
- /// \brief If the given node corresponds to a PostStore program point,
+ /// If the given node corresponds to a PostStore program point,
/// retrieve the location region as it was uttered in the code.
///
/// This utility can be useful for generating extensive diagnostics, for
@@ -191,19 +191,19 @@ public:
return nullptr;
}
- /// \brief Get the value of arbitrary expressions at this point in the path.
+ /// Get the value of arbitrary expressions at this point in the path.
SVal getSVal(const Stmt *S) const {
- return getState()->getSVal(S, getLocationContext());
+ return Pred->getSVal(S);
}
- /// \brief Returns true if the value of \p E is greater than or equal to \p
+ /// 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
+ /// Generates a new transition in the program state graph
/// (ExplodedGraph). Uses the default CheckerContext predecessor node.
///
/// @param State The state of the generated node. If not specified, the state
@@ -217,7 +217,7 @@ public:
return addTransitionImpl(State ? State : getState(), false, nullptr, Tag);
}
- /// \brief Generates a new transition with the given predecessor.
+ /// Generates a new transition with the given predecessor.
/// Allows checkers to generate a chain of nodes.
///
/// @param State The state of the generated node.
@@ -230,7 +230,7 @@ public:
return addTransitionImpl(State, false, Pred, Tag);
}
- /// \brief Generate a sink node. Generating a sink stops exploration of the
+ /// Generate a sink node. Generating a sink stops exploration of the
/// given path. To create a sink node for the purpose of reporting an error,
/// checkers should use generateErrorNode() instead.
ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
@@ -238,7 +238,7 @@ public:
return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
}
- /// \brief Generate a transition to a node that will be used to report
+ /// Generate a transition to a node that will be used to report
/// an error. This node will be a sink. That is, it will stop exploration of
/// the given path.
///
@@ -251,7 +251,7 @@ public:
(Tag ? Tag : Location.getTag()));
}
- /// \brief Generate a transition to a node that will be used to report
+ /// Generate a transition to a node that will be used to report
/// an error. This node will not be a sink. That is, exploration will
/// continue along this path.
///
@@ -264,23 +264,23 @@ public:
return addTransition(State, (Tag ? Tag : Location.getTag()));
}
- /// \brief Emit the diagnostics report.
+ /// Emit the diagnostics report.
void emitReport(std::unique_ptr<BugReport> R) {
Changed = true;
Eng.getBugReporter().emitReport(std::move(R));
}
- /// \brief Returns the word that should be used to refer to the declaration
+ /// Returns the word that should be used to refer to the declaration
/// in the report.
StringRef getDeclDescription(const Decl *D);
- /// \brief Get the declaration of the called function (path-sensitive).
+ /// Get the declaration of the called function (path-sensitive).
const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
- /// \brief Get the name of the called function (path-sensitive).
+ /// Get the name of the called function (path-sensitive).
StringRef getCalleeName(const FunctionDecl *FunDecl) const;
- /// \brief Get the identifier of the called function (path-sensitive).
+ /// Get the identifier of the called function (path-sensitive).
const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
const FunctionDecl *FunDecl = getCalleeDecl(CE);
if (FunDecl)
@@ -289,13 +289,13 @@ public:
return nullptr;
}
- /// \brief Get the name of the called function (path-sensitive).
+ /// Get the name of the called function (path-sensitive).
StringRef getCalleeName(const CallExpr *CE) const {
const FunctionDecl *FunDecl = getCalleeDecl(CE);
return getCalleeName(FunDecl);
}
- /// \brief Returns true if the callee is an externally-visible function in the
+ /// Returns true if the callee is an externally-visible function in the
/// top-level namespace, such as \c malloc.
///
/// If a name is provided, the function must additionally match the given
@@ -308,7 +308,7 @@ public:
static bool isCLibraryFunction(const FunctionDecl *FD,
StringRef Name = StringRef());
- /// \brief Depending on wither the location corresponds to a macro, return
+ /// Depending on wither the location corresponds to a macro, return
/// either the macro name or the token spelling.
///
/// This could be useful when checkers' logic depends on whether a function
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
index 8dda6367c2e0..7f34a7a5b19d 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -21,6 +21,8 @@ namespace clang {
class Expr;
class VarDecl;
+class QualType;
+class AttributedType;
namespace ento {
@@ -42,6 +44,25 @@ template <class T> bool containsStmt(const Stmt *S) {
std::pair<const clang::VarDecl *, const clang::Expr *>
parseAssignment(const Stmt *S);
+// Do not reorder! The getMostNullable method relies on the order.
+// Optimization: Most pointers expected to be unspecified. When a symbol has an
+// unspecified or nonnull type non of the rules would indicate any problem for
+// that symbol. For this reason only nullable and contradicted nullability are
+// stored for a symbol. When a symbol is already contradicted, it can not be
+// casted back to nullable.
+enum class Nullability : char {
+ Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
+ // not report any nullability related issue for this symbol.
+ // This nullability is propagated aggressively to avoid false
+ // positive results. See the comment on getMostNullable method.
+ Nullable,
+ Unspecified,
+ Nonnull
+};
+
+/// Get nullability annotation for a given type.
+Nullability getNullabilityAnnotation(QualType Type);
+
} // end GR namespace
} // end clang namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index c01600d5c969..d4f8fbaa43df 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -1,4 +1,4 @@
-//== ConstraintManager.h - Constraints on symbolic values.-------*- C++ -*--==//
+//===- ConstraintManager.h - Constraints on symbolic values. ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,28 +14,44 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/SaveAndRestore.h"
+#include <memory>
+#include <utility>
namespace llvm {
+
class APSInt;
-}
+
+} // namespace llvm
namespace clang {
namespace ento {
+class ProgramStateManager;
class SubEngine;
+class SymbolReaper;
class ConditionTruthVal {
Optional<bool> Val;
+
public:
/// Construct a ConditionTruthVal indicating the constraint is constrained
/// to either true or false, depending on the boolean value provided.
ConditionTruthVal(bool constraint) : Val(constraint) {}
/// Construct a ConstraintVal indicating the constraint is underconstrained.
- ConditionTruthVal() {}
+ ConditionTruthVal() = default;
+
+ /// \return Stored value, assuming that the value is known.
+ /// Crashes otherwise.
+ bool getValue() const {
+ return *Val;
+ }
/// Return true if the constraint is perfectly constrained to 'true'.
bool isConstrainedTrue() const {
@@ -61,14 +77,14 @@ public:
class ConstraintManager {
public:
- ConstraintManager() : NotifyAssumeClients(true) {}
-
+ ConstraintManager() = default;
virtual ~ConstraintManager();
+
virtual ProgramStateRef assume(ProgramStateRef state,
DefinedSVal Cond,
bool Assumption) = 0;
- typedef std::pair<ProgramStateRef, ProgramStateRef> ProgramStatePair;
+ using ProgramStatePair = std::pair<ProgramStateRef, ProgramStateRef>;
/// Returns a pair of states (StTrue, StFalse) where the given condition is
/// assumed to be true or false, respectively.
@@ -129,7 +145,7 @@ public:
return ProgramStatePair(StInRange, StOutOfRange);
}
- /// \brief If a symbol is perfectly constrained to a constant, attempt
+ /// If a symbol is perfectly constrained to a constant, attempt
/// to return the concrete value.
///
/// Note that a ConstraintManager is not obligated to return a concretized
@@ -166,7 +182,7 @@ protected:
///
/// Note that this flag allows the ConstraintManager to be re-entrant,
/// but not thread-safe.
- bool NotifyAssumeClients;
+ bool NotifyAssumeClients = true;
/// canReasonAbout - Not all ConstraintManagers can accurately reason about
/// all SVal values. This method returns true if the ConstraintManager can
@@ -187,8 +203,7 @@ CreateRangeConstraintManager(ProgramStateManager &statemgr,
std::unique_ptr<ConstraintManager>
CreateZ3ConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine);
-} // end GR namespace
+} // namespace ento
+} // namespace clang
-} // end clang namespace
-
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
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 7472a7147fca..17369a85bfa3 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
@@ -1,4 +1,4 @@
-//==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
+//===- CoreEngine.h - Path-Sensitive Dataflow Engine ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,21 +15,33 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
-#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
#include <memory>
+#include <utility>
+#include <vector>
namespace clang {
-class ProgramPointTag;
-
+class AnalyzerOptions;
+class CXXBindTemporaryExpr;
+class Expr;
+class LabelDecl;
+
namespace ento {
-class NodeBuilder;
+class FunctionSummariesTy;
+class SubEngine;
//===----------------------------------------------------------------------===//
/// CoreEngine - Implements the core logic of the graph-reachability
@@ -41,23 +53,23 @@ class NodeBuilder;
/// at the statement and block-level. The analyses themselves must implement
/// any transfer function logic and the sub-expression level (if any).
class CoreEngine {
- friend struct NodeBuilderContext;
- friend class NodeBuilder;
- friend class ExprEngine;
friend class CommonNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
+ friend class ExprEngine;
friend class IndirectGotoNodeBuilder;
+ friend class NodeBuilder;
+ friend struct NodeBuilderContext;
friend class SwitchNodeBuilder;
- friend class EndOfFunctionNodeBuilder;
+
public:
- typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
- BlocksExhausted;
-
- typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> >
- BlocksAborted;
+ using BlocksExhausted =
+ std::vector<std::pair<BlockEdge, const ExplodedNode *>>;
-private:
+ using BlocksAborted =
+ std::vector<std::pair<const CFGBlock *, const ExplodedNode *>>;
- SubEngine& SubEng;
+private:
+ SubEngine &SubEng;
/// G - The simulation graph. Each node is a (location,state) pair.
mutable ExplodedGraph G;
@@ -75,7 +87,7 @@ private:
/// The locations where we stopped doing work because we visited a location
/// too many times.
BlocksExhausted blocksExhausted;
-
+
/// The locations where we stopped because the engine aborted analysis,
/// usually because it could not reason about something.
BlocksAborted blocksAborted;
@@ -106,17 +118,17 @@ private:
ExplodedNode *Pred);
private:
- CoreEngine(const CoreEngine &) = delete;
- void operator=(const CoreEngine &) = delete;
-
ExplodedNode *generateCallExitBeginNode(ExplodedNode *N,
const ReturnStmt *RS);
public:
/// Construct a CoreEngine object to analyze the provided CFG.
- CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS)
- : SubEng(subengine), WList(WorkList::makeDFS()),
- BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
+ CoreEngine(SubEngine &subengine,
+ FunctionSummariesTy *FS,
+ AnalyzerOptions &Opts);
+
+ CoreEngine(const CoreEngine &) = delete;
+ CoreEngine &operator=(const CoreEngine &) = delete;
/// getGraph - Returns the exploded graph.
ExplodedGraph &getGraph() { return G; }
@@ -125,10 +137,11 @@ public:
/// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
ProgramStateRef InitState);
+
/// Returns true if there is still simulation state on the worklist.
bool ExecuteWorkListWithInitialState(const LocationContext *L,
unsigned Steps,
- ProgramStateRef InitState,
+ ProgramStateRef InitState,
ExplodedNodeSet &Dst);
/// Dispatch the work list item based on the given location information.
@@ -139,8 +152,8 @@ public:
// Functions for external checking of whether we have unfinished work
bool wasBlockAborted() const { return !blocksAborted.empty(); }
bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
- bool hasWorkRemaining() const { return wasBlocksExhausted() ||
- WList->hasWork() ||
+ bool hasWorkRemaining() const { return wasBlocksExhausted() ||
+ WList->hasWork() ||
wasBlockAborted(); }
/// Inform the CoreEngine that a basic block was aborted because
@@ -148,34 +161,37 @@ public:
void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
blocksAborted.push_back(std::make_pair(block, node));
}
-
+
WorkList *getWorkList() const { return WList.get(); }
BlocksExhausted::const_iterator blocks_exhausted_begin() const {
return blocksExhausted.begin();
}
+
BlocksExhausted::const_iterator blocks_exhausted_end() const {
return blocksExhausted.end();
}
+
BlocksAborted::const_iterator blocks_aborted_begin() const {
return blocksAborted.begin();
}
+
BlocksAborted::const_iterator blocks_aborted_end() const {
return blocksAborted.end();
}
- /// \brief Enqueue the given set of nodes onto the work list.
+ /// Enqueue the given set of nodes onto the work list.
void enqueue(ExplodedNodeSet &Set);
- /// \brief Enqueue nodes that were created as a result of processing
+ /// Enqueue nodes that were created as a result of processing
/// a statement onto the work list.
void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx);
- /// \brief enqueue the nodes corresponding to the end of function onto the
+ /// enqueue the nodes corresponding to the end of function onto the
/// end of path / work list.
void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS);
- /// \brief Enqueue a single node created as a result of statement processing.
+ /// Enqueue a single node created as a result of statement processing.
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
};
@@ -184,23 +200,24 @@ struct NodeBuilderContext {
const CoreEngine &Eng;
const CFGBlock *Block;
const LocationContext *LC;
+
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
- : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); }
+ : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); }
- /// \brief Return the CFGBlock associated with this builder.
+ /// Return the CFGBlock associated with this builder.
const CFGBlock *getBlock() const { return Block; }
- /// \brief Returns the number of times the current basic block has been
+ /// Returns the number of times the current basic block has been
/// visited on the exploded graph path.
unsigned blockCount() const {
return Eng.WList->getBlockCounter().getNumVisited(
- LC->getCurrentStackFrame(),
+ LC->getStackFrame(),
Block->getBlockID());
}
};
/// \class NodeBuilder
-/// \brief This is the simplest builder which generates nodes in the
+/// This is the simplest builder which generates nodes in the
/// ExplodedGraph.
///
/// The main benefit of the builder is that it automatically tracks the
@@ -210,35 +227,35 @@ struct NodeBuilderContext {
/// constructed nodes) but did not have any outgoing transitions added.
class NodeBuilder {
virtual void anchor();
+
protected:
const NodeBuilderContext &C;
/// Specifies if the builder results have been finalized. For example, if it
/// is set to false, autotransitions are yet to be generated.
bool Finalized;
- bool HasGeneratedNodes;
- /// \brief The frontier set - a set of nodes which need to be propagated after
+
+ bool HasGeneratedNodes = false;
+
+ /// The frontier set - a set of nodes which need to be propagated after
/// the builder dies.
ExplodedNodeSet &Frontier;
- /// Checkes if the results are ready.
+ /// Checks if the results are ready.
virtual bool checkResults() {
- if (!Finalized)
- return false;
- return true;
+ return Finalized;
}
bool hasNoSinksInFrontier() {
- for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) {
- if ((*I)->isSink())
+ for (const auto I : Frontier)
+ if (I->isSink())
return false;
- }
return true;
}
/// Allow subclasses to finalize results before result_begin() is executed.
virtual void finalizeResults() {}
-
+
ExplodedNode *generateNodeImpl(const ProgramPoint &PP,
ProgramStateRef State,
ExplodedNode *Pred,
@@ -247,27 +264,27 @@ protected:
public:
NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx, bool F = true)
- : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
+ : C(Ctx), Finalized(F), Frontier(DstSet) {
Frontier.Add(SrcNode);
}
NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx, bool F = true)
- : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
+ : C(Ctx), Finalized(F), Frontier(DstSet) {
Frontier.insert(SrcSet);
assert(hasNoSinksInFrontier());
}
- virtual ~NodeBuilder() {}
+ virtual ~NodeBuilder() = default;
- /// \brief Generates a node in the ExplodedGraph.
+ /// Generates a node in the ExplodedGraph.
ExplodedNode *generateNode(const ProgramPoint &PP,
ProgramStateRef State,
ExplodedNode *Pred) {
return generateNodeImpl(PP, State, Pred, false);
}
- /// \brief Generates a sink in the ExplodedGraph.
+ /// Generates a sink in the ExplodedGraph.
///
/// When a node is marked as sink, the exploration from the node is stopped -
/// the node becomes the last node on the path and certain kinds of bugs are
@@ -284,14 +301,16 @@ public:
return Frontier;
}
- typedef ExplodedNodeSet::iterator iterator;
- /// \brief Iterators through the results frontier.
- inline iterator begin() {
+ using iterator = ExplodedNodeSet::iterator;
+
+ /// Iterators through the results frontier.
+ iterator begin() {
finalizeResults();
assert(checkResults());
return Frontier.begin();
}
- inline iterator end() {
+
+ iterator end() {
finalizeResults();
return Frontier.end();
}
@@ -300,18 +319,20 @@ public:
bool hasGeneratedNodes() { return HasGeneratedNodes; }
void takeNodes(const ExplodedNodeSet &S) {
- for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I )
- Frontier.erase(*I);
+ for (const auto I : S)
+ Frontier.erase(I);
}
+
void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
void addNodes(ExplodedNode *N) { Frontier.Add(N); }
};
/// \class NodeBuilderWithSinks
-/// \brief This node builder keeps track of the generated sink nodes.
+/// This node builder keeps track of the generated sink nodes.
class NodeBuilderWithSinks: public NodeBuilder {
void anchor() override;
+
protected:
SmallVector<ExplodedNode*, 2> sinksGenerated;
ProgramPoint &Location;
@@ -319,7 +340,7 @@ protected:
public:
NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx, ProgramPoint &L)
- : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
+ : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
ExplodedNode *generateNode(ProgramStateRef State,
ExplodedNode *Pred,
@@ -343,20 +364,20 @@ public:
};
/// \class StmtNodeBuilder
-/// \brief This builder class is useful for generating nodes that resulted from
+/// This builder class is useful for generating nodes that resulted from
/// visiting a statement. The main difference from its parent NodeBuilder is
/// that it creates a statement specific ProgramPoint.
class StmtNodeBuilder: public NodeBuilder {
NodeBuilder *EnclosingBldr;
-public:
- /// \brief Constructs a StmtNodeBuilder. If the builder is going to process
+public:
+ /// Constructs a StmtNodeBuilder. If the builder is going to process
/// nodes currently owned by another builder(with larger scope), use
/// Enclosing builder to transfer ownership.
StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx,
NodeBuilder *Enclosing = nullptr)
- : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) {
+ : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) {
if (EnclosingBldr)
EnclosingBldr->takeNodes(SrcNode);
}
@@ -364,11 +385,10 @@ public:
StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx,
NodeBuilder *Enclosing = nullptr)
- : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
+ : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
if (EnclosingBldr)
- for (ExplodedNodeSet::iterator I = SrcSet.begin(),
- E = SrcSet.end(); I != E; ++I )
- EnclosingBldr->takeNodes(*I);
+ for (const auto I : SrcSet)
+ EnclosingBldr->takeNodes(I);
}
~StmtNodeBuilder() override;
@@ -397,22 +417,23 @@ public:
}
};
-/// \brief BranchNodeBuilder is responsible for constructing the nodes
+/// BranchNodeBuilder is responsible for constructing the nodes
/// corresponding to the two branches of the if statement - true and false.
class BranchNodeBuilder: public NodeBuilder {
- void anchor() override;
const CFGBlock *DstT;
const CFGBlock *DstF;
bool InFeasibleTrue;
bool InFeasibleFalse;
+ void anchor() override;
+
public:
BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
const NodeBuilderContext &C,
const CFGBlock *dstT, const CFGBlock *dstF)
- : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
- InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
+ : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
+ InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
// The branch node builder does not generate autotransitions.
// If there are no successors it means that both branches are infeasible.
takeNodes(SrcNode);
@@ -421,8 +442,8 @@ public:
BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
const NodeBuilderContext &C,
const CFGBlock *dstT, const CFGBlock *dstF)
- : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
- InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
+ : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
+ InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
takeNodes(SrcSet);
}
@@ -453,17 +474,18 @@ class IndirectGotoNodeBuilder {
ExplodedNode *Pred;
public:
- IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
+ IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
const Expr *e, const CFGBlock *dispatch, CoreEngine* eng)
- : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
class iterator {
+ friend class IndirectGotoNodeBuilder;
+
CFGBlock::const_succ_iterator I;
- friend class IndirectGotoNodeBuilder;
iterator(CFGBlock::const_succ_iterator i) : I(i) {}
- public:
+ public:
iterator &operator++() { ++I; return *this; }
bool operator!=(const iterator &X) const { return I != X.I; }
@@ -486,7 +508,7 @@ public:
const Expr *getTarget() const { return E; }
ProgramStateRef getState() const { return Pred->State; }
-
+
const LocationContext *getLocationContext() const {
return Pred->getLocationContext();
}
@@ -501,12 +523,13 @@ class SwitchNodeBuilder {
public:
SwitchNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
const Expr *condition, CoreEngine* eng)
- : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
+ : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
class iterator {
+ friend class SwitchNodeBuilder;
+
CFGBlock::const_succ_reverse_iterator I;
- friend class SwitchNodeBuilder;
iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
public:
@@ -539,13 +562,14 @@ public:
const Expr *getCondition() const { return Condition; }
ProgramStateRef getState() const { return Pred->State; }
-
+
const LocationContext *getLocationContext() const {
return Pred->getLocationContext();
}
};
-} // end ento namespace
-} // end clang namespace
+} // namespace ento
+
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
index e13c6410c7be..092e23ce73c8 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
@@ -14,7 +14,7 @@
namespace clang {
namespace ento {
-/// \brief Stores the currently inferred strictest bound on the runtime type
+/// Stores the currently inferred strictest bound on the runtime type
/// of a region in a given state along the analysis path.
class DynamicTypeInfo {
private:
@@ -27,13 +27,13 @@ public:
DynamicTypeInfo(QualType WithType, bool CanBeSub = true)
: T(WithType), CanBeASubClass(CanBeSub) {}
- /// \brief Return false if no dynamic type info is available.
+ /// Return false if no dynamic type info is available.
bool isValid() const { return !T.isNull(); }
- /// \brief Returns the currently inferred upper bound on the runtime type.
+ /// Returns the currently inferred upper bound on the runtime type.
QualType getType() const { return T; }
- /// \brief Returns false if the type information is precise (the type T is
+ /// Returns false if the type information is precise (the type T is
/// the only type in the lattice), true otherwise.
bool canBeASubClass() const { return CanBeASubClass; }
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
index 555191d99709..2f8ead0746ca 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -1,4 +1,4 @@
-//== DynamicTypeMap.h - Dynamic type map ----------------------- -*- C++ -*--=//
+//===- DynamicTypeMap.h - Dynamic type map ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,19 +13,26 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/ImmutableMap.h"
+#include "clang/AST/Type.h"
namespace clang {
namespace ento {
+class MemRegion;
+
/// The GDM component containing the dynamic type info. This is a map from a
/// symbol to its most likely type.
struct DynamicTypeMap {};
-typedef llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>
- DynamicTypeMapImpl;
+
+using DynamicTypeMapImpl =
+ llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>;
+
template <>
struct ProgramStateTrait<DynamicTypeMap>
: public ProgramStatePartialTrait<DynamicTypeMapImpl> {
@@ -35,15 +42,15 @@ struct ProgramStateTrait<DynamicTypeMap>
}
};
-/// \brief Get dynamic type information for a region.
+/// Get dynamic type information for a region.
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
const MemRegion *Reg);
-/// \brief Set dynamic type information of the region; return the new state.
+/// Set dynamic type information of the region; return the new state.
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
DynamicTypeInfo NewTy);
-/// \brief Set dynamic type information of the region; return the new state.
+/// Set dynamic type information of the region; return the new state.
inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
const MemRegion *Reg, QualType NewTy,
bool CanBeSubClassed = true) {
@@ -51,7 +58,10 @@ inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
DynamicTypeInfo(NewTy, CanBeSubClassed));
}
-} // ento
-} // clang
+void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out,
+ const char *NL, const char *Sep);
+
+} // namespace ento
+} // namespace clang
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index c63ed4a013aa..77e35398077c 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
@@ -1,4 +1,4 @@
-//== Environment.h - Map from Stmt* to Locations/Values ---------*- C++ -*--==//
+//===- Environment.h - Map from Stmt* to Locations/Values -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,17 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/ImmutableMap.h"
+#include <utility>
namespace clang {
-class LiveVariables;
+class Stmt;
namespace ento {
-class EnvironmentManager;
class SValBuilder;
class SymbolReaper;
@@ -32,21 +33,21 @@ class SymbolReaper;
/// This allows the environment to manage context-sensitive bindings,
/// which is essentially for modeling recursive function analysis, among
/// other things.
-class EnvironmentEntry : public std::pair<const Stmt*,
+class EnvironmentEntry : public std::pair<const Stmt *,
const StackFrameContext *> {
public:
EnvironmentEntry(const Stmt *s, const LocationContext *L);
const Stmt *getStmt() const { return first; }
const LocationContext *getLocationContext() const { return second; }
-
+
/// Profile an EnvironmentEntry for inclusion in a FoldingSet.
static void Profile(llvm::FoldingSetNodeID &ID,
const EnvironmentEntry &E) {
ID.AddPointer(E.getStmt());
ID.AddPointer(E.getLocationContext());
}
-
+
void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, *this);
}
@@ -57,19 +58,17 @@ class Environment {
private:
friend class EnvironmentManager;
- // Type definitions.
- typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy;
+ using BindingsTy = llvm::ImmutableMap<EnvironmentEntry, SVal>;
- // Data.
BindingsTy ExprBindings;
- Environment(BindingsTy eb)
- : ExprBindings(eb) {}
+ Environment(BindingsTy eb) : ExprBindings(eb) {}
SVal lookupExpr(const EnvironmentEntry &E) const;
public:
- typedef BindingsTy::iterator iterator;
+ using iterator = BindingsTy::iterator;
+
iterator begin() const { return ExprBindings.begin(); }
iterator end() const { return ExprBindings.end(); }
@@ -92,21 +91,19 @@ public:
bool operator==(const Environment& RHS) const {
return ExprBindings == RHS.ExprBindings;
}
-
- void print(raw_ostream &Out, const char *NL, const char *Sep) const;
-
-private:
- void printAux(raw_ostream &Out, bool printLocations,
- const char *NL, const char *Sep) const;
+
+ void print(raw_ostream &Out, const char *NL, const char *Sep,
+ const LocationContext *WithLC = nullptr) const;
};
class EnvironmentManager {
private:
- typedef Environment::BindingsTy::Factory FactoryTy;
+ using FactoryTy = Environment::BindingsTy::Factory;
+
FactoryTy F;
public:
- EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
+ EnvironmentManager(llvm::BumpPtrAllocator &Allocator) : F(Allocator) {}
Environment getInitialEnvironment() {
return Environment(F.getEmptyMap());
@@ -121,8 +118,8 @@ public:
ProgramStateRef state);
};
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_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 dcea5e461d27..4e0c02e6d65b 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
@@ -1,4 +1,4 @@
-//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
+//===- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,17 +19,25 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
-#include "clang/AST/Decl.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
@@ -37,6 +45,10 @@
namespace clang {
class CFG;
+class Decl;
+class Expr;
+class ParentMap;
+class Stmt;
namespace ento {
@@ -52,13 +64,13 @@ class ExplodedGraph;
// successors to it at any time after creating it.
class ExplodedNode : public llvm::FoldingSetNode {
- friend class ExplodedGraph;
- friend class CoreEngine;
- friend class NodeBuilder;
friend class BranchNodeBuilder;
+ friend class CoreEngine;
+ friend class EndOfFunctionNodeBuilder;
+ friend class ExplodedGraph;
friend class IndirectGotoNodeBuilder;
+ friend class NodeBuilder;
friend class SwitchNodeBuilder;
- friend class EndOfFunctionNodeBuilder;
/// Efficiently stores a list of ExplodedNodes, or an optional flag.
///
@@ -75,7 +87,7 @@ class ExplodedNode : public llvm::FoldingSetNode {
// for the nodes in the group.
// This is not a PointerIntPair in order to keep the storage type opaque.
uintptr_t P;
-
+
public:
NodeGroup(bool Flag = false) : P(Flag) {
assert(getFlag() == Flag);
@@ -135,7 +147,7 @@ public:
}
const StackFrameContext *getStackFrame() const {
- return getLocationContext()->getCurrentStackFrame();
+ return getLocation().getStackFrame();
}
const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
@@ -156,6 +168,11 @@ public:
return Location.getAs<T>();
}
+ /// Get the value of an arbitrary expression at this node.
+ SVal getSVal(const Stmt *S) const {
+ return getState()->getSVal(S, getLocationContext());
+ }
+
static void Profile(llvm::FoldingSetNodeID &ID,
const ProgramPoint &Loc,
const ProgramStateRef &state,
@@ -198,10 +215,10 @@ public:
}
// Iterators over successor and predecessor vertices.
- typedef ExplodedNode* const * succ_iterator;
- typedef const ExplodedNode* const * const_succ_iterator;
- typedef ExplodedNode* const * pred_iterator;
- typedef const ExplodedNode* const * const_pred_iterator;
+ using succ_iterator = ExplodedNode * const *;
+ using const_succ_iterator = const ExplodedNode * const *;
+ using pred_iterator = ExplodedNode * const *;
+ using const_pred_iterator = const ExplodedNode * const *;
pred_iterator pred_begin() { return Preds.begin(); }
pred_iterator pred_end() { return Preds.end(); }
@@ -226,29 +243,29 @@ public:
// For debugging.
public:
-
class Auditor {
public:
virtual ~Auditor();
+
virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
};
static void SetAuditor(Auditor* A);
-
+
private:
void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
};
-typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>
- InterExplodedGraphMap;
+using InterExplodedGraphMap =
+ llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>;
class ExplodedGraph {
protected:
friend class CoreEngine;
// Type definitions.
- typedef std::vector<ExplodedNode *> NodeVector;
+ using NodeVector = std::vector<ExplodedNode *>;
/// The roots of the simulation graph. Usually there will be only
/// one, but clients are free to establish multiple subgraphs within a single
@@ -268,25 +285,27 @@ protected:
BumpVectorContext BVC;
/// NumNodes - The number of nodes in the graph.
- unsigned NumNodes;
-
+ unsigned NumNodes = 0;
+
/// A list of recently allocated nodes that can potentially be recycled.
NodeVector ChangedNodes;
-
+
/// A list of nodes that can be reused.
NodeVector FreeNodes;
-
+
/// Determines how often nodes are reclaimed.
///
/// If this is 0, nodes will never be reclaimed.
- unsigned ReclaimNodeInterval;
-
+ unsigned ReclaimNodeInterval = 0;
+
/// Counter to determine when to reclaim nodes.
unsigned ReclaimCounter;
public:
+ ExplodedGraph();
+ ~ExplodedGraph();
- /// \brief Retrieve the node associated with a (Location,State) pair,
+ /// Retrieve the node associated with a (Location,State) pair,
/// where the 'Location' is a ProgramPoint in the CFG. If no node for
/// this pair exists, it is created. IsNew is set to true if
/// the node was freshly created.
@@ -294,7 +313,7 @@ public:
bool IsSink = false,
bool* IsNew = nullptr);
- /// \brief Create a node for a (Location, State) pair,
+ /// Create a node for a (Location, State) pair,
/// but don't store it for deduplication later. This
/// is useful when copying an already completed
/// ExplodedGraph for further processing.
@@ -318,10 +337,6 @@ public:
return V;
}
- ExplodedGraph();
-
- ~ExplodedGraph();
-
unsigned num_roots() const { return Roots.size(); }
unsigned num_eops() const { return EndNodes.size(); }
@@ -331,14 +346,14 @@ public:
void reserve(unsigned NodeCount) { Nodes.reserve(NodeCount); }
// Iterators.
- typedef ExplodedNode NodeTy;
- typedef llvm::FoldingSet<ExplodedNode> AllNodesTy;
- typedef NodeVector::iterator roots_iterator;
- typedef NodeVector::const_iterator const_roots_iterator;
- typedef NodeVector::iterator eop_iterator;
- typedef NodeVector::const_iterator const_eop_iterator;
- typedef AllNodesTy::iterator node_iterator;
- typedef AllNodesTy::const_iterator const_node_iterator;
+ using NodeTy = ExplodedNode;
+ using AllNodesTy = llvm::FoldingSet<ExplodedNode>;
+ using roots_iterator = NodeVector::iterator;
+ using const_roots_iterator = NodeVector::const_iterator;
+ using eop_iterator = NodeVector::iterator;
+ using const_eop_iterator = NodeVector::const_iterator;
+ using node_iterator = AllNodesTy::iterator;
+ using const_node_iterator = AllNodesTy::const_iterator;
node_iterator nodes_begin() { return Nodes.begin(); }
@@ -367,7 +382,7 @@ public:
llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
BumpVectorContext &getNodeAllocator() { return BVC; }
- typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
+ using NodeMap = llvm::DenseMap<const ExplodedNode *, ExplodedNode *>;
/// Creates a trimmed version of the graph that only contains paths leading
/// to the given nodes.
@@ -394,7 +409,7 @@ public:
/// was called.
void reclaimRecentlyAllocatedNodes();
- /// \brief Returns true if nodes for the given expression kind are always
+ /// Returns true if nodes for the given expression kind are always
/// kept around.
static bool isInterestingLValueExpr(const Expr *Ex);
@@ -404,29 +419,30 @@ private:
};
class ExplodedNodeSet {
- typedef llvm::SmallSetVector<ExplodedNode*, 4> ImplTy;
+ using ImplTy = llvm::SmallSetVector<ExplodedNode *, 4>;
ImplTy Impl;
public:
ExplodedNodeSet(ExplodedNode *N) {
- assert (N && !static_cast<ExplodedNode*>(N)->isSink());
+ assert(N && !static_cast<ExplodedNode*>(N)->isSink());
Impl.insert(N);
}
- ExplodedNodeSet() {}
+ ExplodedNodeSet() = default;
- inline void Add(ExplodedNode *N) {
+ void Add(ExplodedNode *N) {
if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
}
- typedef ImplTy::iterator iterator;
- typedef ImplTy::const_iterator const_iterator;
+ using iterator = ImplTy::iterator;
+ using const_iterator = ImplTy::const_iterator;
unsigned size() const { return Impl.size(); }
bool empty() const { return Impl.empty(); }
bool erase(ExplodedNode *N) { return Impl.remove(N); }
void clear() { Impl.clear(); }
+
void insert(const ExplodedNodeSet &S) {
assert(&S != this);
if (empty())
@@ -435,24 +451,25 @@ public:
Impl.insert(S.begin(), S.end());
}
- inline iterator begin() { return Impl.begin(); }
- inline iterator end() { return Impl.end(); }
+ iterator begin() { return Impl.begin(); }
+ iterator end() { return Impl.end(); }
- inline const_iterator begin() const { return Impl.begin(); }
- inline const_iterator end() const { return Impl.end(); }
+ const_iterator begin() const { return Impl.begin(); }
+ const_iterator end() const { return Impl.end(); }
};
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
// GraphTraits
namespace llvm {
+
template<> struct GraphTraits<clang::ento::ExplodedNode*> {
- typedef clang::ento::ExplodedNode *NodeRef;
- typedef clang::ento::ExplodedNode::succ_iterator ChildIteratorType;
- typedef llvm::df_iterator<NodeRef> nodes_iterator;
+ using NodeRef = clang::ento::ExplodedNode *;
+ using ChildIteratorType = clang::ento::ExplodedNode::succ_iterator;
+ using nodes_iterator = llvm::df_iterator<NodeRef>;
static NodeRef getEntryNode(NodeRef N) { return N; }
@@ -466,9 +483,9 @@ namespace llvm {
};
template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
- typedef const clang::ento::ExplodedNode *NodeRef;
- typedef clang::ento::ExplodedNode::const_succ_iterator ChildIteratorType;
- typedef llvm::df_iterator<NodeRef> nodes_iterator;
+ using NodeRef = const clang::ento::ExplodedNode *;
+ using ChildIteratorType = clang::ento::ExplodedNode::const_succ_iterator;
+ using nodes_iterator = llvm::df_iterator<NodeRef>;
static NodeRef getEntryNode(NodeRef N) { return N; }
@@ -481,6 +498,6 @@ namespace llvm {
static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
};
-} // end llvm namespace
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
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 712cd6361e11..06a90fa847a6 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
@@ -1,4 +1,4 @@
-//===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=//
+//===- ExprEngine.h - Path-Sensitive Expression-Level Dataflow --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,32 +18,68 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
+#include "clang/Analysis/CFG.h"
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <cassert>
+#include <utility>
namespace clang {
class AnalysisDeclContextManager;
+class AnalyzerOptions;
+class ASTContext;
+class ConstructionContext;
+class CXXBindTemporaryExpr;
class CXXCatchStmt;
class CXXConstructExpr;
class CXXDeleteExpr;
class CXXNewExpr;
-class CXXTemporaryObjectExpr;
class CXXThisExpr;
+class Decl;
+class DeclStmt;
+class GCCAsmStmt;
+class LambdaExpr;
+class LocationContext;
class MaterializeTemporaryExpr;
+class MSAsmStmt;
+class NamedDecl;
class ObjCAtSynchronizedStmt;
class ObjCForCollectionStmt;
-
+class ObjCIvarRefExpr;
+class ObjCMessageExpr;
+class ReturnStmt;
+class Stmt;
+
+namespace cross_tu {
+
+class CrossTranslationUnitContext;
+
+} // namespace cross_tu
+
namespace ento {
-class AnalysisManager;
+class BasicValueFactory;
class CallEvent;
-class CXXConstructorCall;
+class CheckerManager;
+class ConstraintManager;
+class CXXTempObjectRegion;
+class MemRegion;
+class RegionAndSymbolInvalidationTraits;
+class SymbolManager;
class ExprEngine : public SubEngine {
public:
@@ -51,36 +87,60 @@ public:
enum InliningModes {
/// Follow the default settings for inlining callees.
Inline_Regular = 0,
+
/// Do minimal inlining of callees.
Inline_Minimal = 0x1
};
+ /// Hints for figuring out of a call should be inlined during evalCall().
+ struct EvalCallOptions {
+ /// This call is a constructor or a destructor for which we do not currently
+ /// compute the this-region correctly.
+ bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false;
+
+ /// This call is a constructor or a destructor for a single element within
+ /// an array, a part of array construction or destruction.
+ bool IsArrayCtorOrDtor = false;
+
+ /// This call is a constructor or a destructor of a temporary value.
+ bool IsTemporaryCtorOrDtor = false;
+
+ /// This call is a constructor for a temporary that is lifetime-extended
+ /// by binding it to a reference-type field within an aggregate,
+ /// for example 'A { const C &c; }; A a = { C() };'
+ bool IsTemporaryLifetimeExtendedViaAggregate = false;
+
+ EvalCallOptions() {}
+ };
+
private:
+ cross_tu::CrossTranslationUnitContext &CTU;
+
AnalysisManager &AMgr;
-
+
AnalysisDeclContextManager &AnalysisDeclContexts;
CoreEngine Engine;
/// G - the simulation graph.
- ExplodedGraph& G;
+ ExplodedGraph &G;
/// StateMgr - Object that manages the data for all created states.
ProgramStateManager StateMgr;
/// SymMgr - Object that manages the symbol information.
- SymbolManager& SymMgr;
+ SymbolManager &SymMgr;
/// svalBuilder - SValBuilder object that creates SVals from expressions.
SValBuilder &svalBuilder;
- unsigned int currStmtIdx;
- const NodeBuilderContext *currBldrCtx;
-
+ unsigned int currStmtIdx = 0;
+ const NodeBuilderContext *currBldrCtx = nullptr;
+
/// Helper object to determine if an Objective-C message expression
/// implicitly never returns.
ObjCNoReturn ObjCNoRet;
-
+
/// Whether or not GC is enabled in this analysis.
bool ObjCGCEnabled;
@@ -97,10 +157,9 @@ private:
InliningModes HowToInline;
public:
- ExprEngine(AnalysisManager &mgr, bool gcEnabled,
- SetOfConstDecls *VisitedCalleesIn,
- FunctionSummariesTy *FS,
- InliningModes HowToInlineIn);
+ ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr,
+ bool gcEnabled, SetOfConstDecls *VisitedCalleesIn,
+ FunctionSummariesTy *FS, InliningModes HowToInlineIn);
~ExprEngine() override;
@@ -114,7 +173,7 @@ public:
/// state of the function call. Returns true if there is still simulation
/// state on the worklist.
bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
- ProgramStateRef InitState,
+ ProgramStateRef InitState,
ExplodedNodeSet &Dst) {
return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
}
@@ -130,7 +189,12 @@ public:
SValBuilder &getSValBuilder() { return svalBuilder; }
- BugReporter& getBugReporter() { return BR; }
+ BugReporter &getBugReporter() { return BR; }
+
+ cross_tu::CrossTranslationUnitContext *
+ getCrossTranslationUnitContext() override {
+ return &CTU;
+ }
const NodeBuilderContext &getBuilderContext() {
assert(currBldrCtx);
@@ -150,16 +214,16 @@ public:
/// Visualize a trimmed ExplodedGraph that only contains paths to the given
/// nodes.
- void ViewGraph(ArrayRef<const ExplodedNode*> Nodes);
+ void ViewGraph(ArrayRef<const ExplodedNode *> Nodes);
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
ProgramStateRef getInitialState(const LocationContext *InitLoc) override;
- ExplodedGraph& getGraph() { return G; }
- const ExplodedGraph& getGraph() const { return G; }
+ ExplodedGraph &getGraph() { return G; }
+ const ExplodedGraph &getGraph() const { return G; }
- /// \brief Run the analyzer's garbage collection - remove dead symbols and
+ /// Run the analyzer's garbage collection - remove dead symbols and
/// bindings from the state.
///
/// Checkers can participate in this process with two callbacks:
@@ -194,7 +258,7 @@ public:
void processCFGElement(const CFGElement E, ExplodedNode *Pred,
unsigned StmtIdx, NodeBuilderContext *Ctx) override;
- void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
+ void ProcessStmt(const Stmt *S, ExplodedNode *Pred);
void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred);
@@ -212,17 +276,17 @@ public:
ExplodedNode *Pred, ExplodedNodeSet &Dst);
void ProcessMemberDtor(const CFGMemberDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
- void ProcessTemporaryDtor(const CFGTemporaryDtor D,
+ void ProcessTemporaryDtor(const CFGTemporaryDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// Called by CoreEngine when processing the entrance of a CFGBlock.
void processCFGBlockEntrance(const BlockEdge &L,
NodeBuilderWithSinks &nodeBuilder,
ExplodedNode *Pred) override;
-
+
/// ProcessBranch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- void processBranch(const Stmt *Condition, const Stmt *Term,
+ void processBranch(const Stmt *Condition, const Stmt *Term,
NodeBuilderContext& BuilderCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
@@ -290,7 +354,7 @@ public:
/// processRegionChanges - Called by ProgramStateManager whenever a change is made
/// to the store. Used to update checkers that track region values.
- ProgramStateRef
+ ProgramStateRef
processRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
@@ -299,25 +363,26 @@ public:
const CallEvent *Call) override;
/// printState - Called by ProgramStateManager to print checker-specific data.
- void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) override;
+ void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+ const char *Sep,
+ const LocationContext *LCtx = nullptr) override;
- ProgramStateManager& getStateManager() override { return StateMgr; }
+ ProgramStateManager &getStateManager() override { return StateMgr; }
- StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
+ StoreManager &getStoreManager() { return StateMgr.getStoreManager(); }
- ConstraintManager& getConstraintManager() {
+ ConstraintManager &getConstraintManager() {
return StateMgr.getConstraintManager();
}
// FIXME: Remove when we migrate over to just using SValBuilder.
- BasicValueFactory& getBasicVals() {
+ BasicValueFactory &getBasicVals() {
return StateMgr.getBasicVals();
}
// FIXME: Remove when we migrate over to just using ValueManager.
- SymbolManager& getSymbolManager() { return SymMgr; }
- const SymbolManager& getSymbolManager() const { return SymMgr; }
+ SymbolManager &getSymbolManager() { return SymMgr; }
+ const SymbolManager &getSymbolManager() const { return SymMgr; }
// Functions for external checking of whether we have unfinished work
bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
@@ -345,15 +410,15 @@ public:
ExplodedNodeSet &Dst);
/// VisitBlockExpr - Transfer function logic for BlockExprs.
- void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+ void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitLambdaExpr - Transfer function logic for LambdaExprs.
- void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
+ void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
- void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
+ void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
@@ -363,24 +428,24 @@ public:
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
+ ExplodedNodeSet &Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
- void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
+ void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
+
/// VisitDeclStmt - Transfer function logic for DeclStmts.
- void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
+ void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
- void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
+ void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
+
void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
@@ -389,10 +454,10 @@ public:
ExplodedNodeSet &Dst);
/// VisitMemberExpr - Transfer function for member expressions.
- void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
+ void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
- /// VisitMemberExpr - Transfer function for builtin atomic expressions
+ /// VisitAtomicExpr - Transfer function for builtin atomic expressions
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
@@ -406,26 +471,26 @@ public:
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
- void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
+ void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitReturnStmt - Transfer function logic for return statements.
- void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,
+ void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
-
+
/// VisitOffsetOfExpr - Transfer function for offsetof.
void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
- void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
+ void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Handle ++ and -- (both pre- and post-increment).
@@ -440,7 +505,7 @@ public:
void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
- void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
+ void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
@@ -448,7 +513,8 @@ public:
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
const Stmt *S, bool IsBaseDtor,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ const EvalCallOptions &Options);
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
ExplodedNode *Pred,
@@ -462,16 +528,16 @@ public:
/// Create a C++ temporary object for an rvalue.
void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
- ExplodedNode *Pred,
+ ExplodedNode *Pred,
ExplodedNodeSet &Dst);
-
+
/// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.
- void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
const Expr *Ex);
-
- std::pair<const ProgramPointTag *, const ProgramPointTag*>
+
+ static std::pair<const ProgramPointTag *, const ProgramPointTag *>
geteagerlyAssumeBinOpBifurcationTags();
SVal evalMinus(SVal X) {
@@ -499,7 +565,6 @@ public:
StmtNodeBuilder &Bldr);
public:
-
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
NonLoc L, NonLoc R, QualType T) {
return svalBuilder.evalBinOpNN(state, op, L, R, T);
@@ -515,7 +580,15 @@ public:
SVal LHS, SVal RHS, QualType T) {
return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
}
-
+
+ /// By looking at a certain item that may be potentially part of an object's
+ /// ConstructionContext, retrieve such object's location. A particular
+ /// statement can be transparently passed as \p Item in most cases.
+ static Optional<SVal>
+ getObjectUnderConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC);
+
protected:
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore, VisitDeclStmt, and others.
@@ -539,6 +612,11 @@ protected:
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) override;
+ /// A simple wrapper when you only need to notify checkers of pointer-escape
+ /// of a single value.
+ ProgramStateRef escapeValue(ProgramStateRef State, SVal V,
+ PointerEscapeKind K) const;
+
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
@@ -561,7 +639,13 @@ public:
ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
const ProgramPointTag *tag = nullptr);
- /// \brief Create a new state in which the call return value is binded to the
+ /// Return the CFG element corresponding to the worklist element
+ /// that is currently being processed by ExprEngine.
+ CFGElement getCurrentCFGElement() {
+ return (*currBldrCtx->getBlock())[currStmtIdx];
+ }
+
+ /// Create a new state in which the call return value is binded to the
/// call origin expression.
ProgramStateRef bindReturnValue(const CallEvent &Call,
const LocationContext *LCtx,
@@ -572,9 +656,11 @@ public:
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
const CallEvent &Call);
- /// \brief Default implementation of call evaluation.
+ /// Default implementation of call evaluation.
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
- const CallEvent &Call);
+ const CallEvent &Call,
+ const EvalCallOptions &CallOpts = {});
+
private:
void evalLoadCommon(ExplodedNodeSet &Dst,
const Expr *NodeEx, /* Eventually will be a CFGStmt */
@@ -598,19 +684,33 @@ private:
void examineStackFrames(const Decl *D, const LocationContext *LCtx,
bool &IsRecursive, unsigned &StackDepth);
+ enum CallInlinePolicy {
+ CIP_Allowed,
+ CIP_DisallowedOnce,
+ CIP_DisallowedAlways
+ };
+
+ /// See if a particular call should be inlined, by only looking
+ /// at the call event and the current state of analysis.
+ CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
+ const ExplodedNode *Pred,
+ AnalyzerOptions &Opts,
+ const EvalCallOptions &CallOpts);
+
/// Checks our policies and decides weither the given call should be inlined.
bool shouldInlineCall(const CallEvent &Call, const Decl *D,
- const ExplodedNode *Pred);
+ const ExplodedNode *Pred,
+ const EvalCallOptions &CallOpts = {});
bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
ExplodedNode *Pred, ProgramStateRef State);
- /// \brief Conservatively evaluate call by invalidating regions and binding
+ /// Conservatively evaluate call by invalidating regions and binding
/// a conjured return value.
void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
ExplodedNode *Pred, ProgramStateRef State);
- /// \brief Either inline or process the call conservatively (or both), based
+ /// Either inline or process the call conservatively (or both), based
/// on DynamicDispatchBifurcation data.
void BifurcateCall(const MemRegion *BifurReg,
const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
@@ -634,6 +734,17 @@ private:
const Expr *InitWithAdjustments,
const Expr *Result = nullptr);
+ /// Returns a region representing the first element of a (possibly
+ /// multi-dimensional) array, for the purposes of element construction or
+ /// destruction.
+ ///
+ /// On return, \p Ty will be set to the base type of the array.
+ ///
+ /// If the type is not an array type at all, the original value is returned.
+ /// Otherwise the "IsArray" flag is set.
+ static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
+ QualType &Ty, bool &IsArray);
+
/// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
/// block to find the constructor expression that directly constructed into
/// the storage for this statement. Returns null if the constructor for this
@@ -641,20 +752,62 @@ private:
/// constructing into an existing region.
const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
- /// For a CXXConstructExpr, walk forward in the current CFG block to find the
- /// CFGElement for the DeclStmt or CXXInitCtorInitializer for which is
- /// directly constructed by this constructor. Returns None if the current
- /// constructor expression did not directly construct into an existing
- /// region.
- Optional<CFGElement> findElementDirectlyInitializedByCurrentConstructor();
-
- /// For a given constructor, look forward in the current CFG block to
- /// determine the region into which an object will be constructed by \p CE.
- /// Returns either a field or local variable region if the object will be
- /// directly constructed in an existing region or a temporary object region
- /// if not.
- const MemRegion *getRegionForConstructedObject(const CXXConstructExpr *CE,
- ExplodedNode *Pred);
+ /// Update the program state with all the path-sensitive information
+ /// that's necessary to perform construction of an object with a given
+ /// syntactic construction context. If the construction context is unavailable
+ /// or unusable for any reason, a dummy temporary region is returned, and the
+ /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts.
+ /// Returns the updated program state and the new object's this-region.
+ std::pair<ProgramStateRef, SVal> prepareForObjectConstruction(
+ const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
+ const ConstructionContext *CC, EvalCallOptions &CallOpts);
+
+ /// Store the location of a C++ object corresponding to a statement
+ /// until the statement is actually encountered. For example, if a DeclStmt
+ /// has CXXConstructExpr as its initializer, the object would be considered
+ /// to be "under construction" between CXXConstructExpr and DeclStmt.
+ /// This allows, among other things, to keep bindings to variable's fields
+ /// made within the constructor alive until its declaration actually
+ /// goes into scope.
+ static ProgramStateRef
+ addObjectUnderConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC, SVal V);
+
+ /// Mark the object sa fully constructed, cleaning up the state trait
+ /// that tracks objects under construction.
+ static ProgramStateRef
+ finishObjectConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC);
+
+ /// If the given expression corresponds to a temporary that was used for
+ /// passing into an elidable copy/move constructor and that constructor
+ /// was actually elided, track that we also need to elide the destructor.
+ static ProgramStateRef elideDestructor(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC);
+
+ /// Stop tracking the destructor that corresponds to an elided constructor.
+ static ProgramStateRef
+ cleanupElidedDestructor(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC);
+
+ /// Returns true if the given expression corresponds to a temporary that
+ /// was constructed for passing into an elidable copy/move constructor
+ /// and that constructor was actually elided.
+ static bool isDestructorElided(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC);
+
+ /// Check if all objects under construction have been fully constructed
+ /// for the given context range (including FromLC, not including ToLC).
+ /// This is useful for assertions. Also checks if elided destructors
+ /// were cleaned up.
+ static bool areAllObjectsFullyConstructed(ProgramStateRef State,
+ const LocationContext *FromLC,
+ const LocationContext *ToLC);
};
/// Traits for storing the call processing policy inside GDM.
@@ -668,8 +821,8 @@ struct ProgramStateTrait<ReplayWithoutInlining> :
static void *GDMIndex() { static int index = 0; return &index; }
};
-} // end ento namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
index ce81c98c206b..b70faa10f0b2 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
@@ -1,4 +1,4 @@
-//== FunctionSummary.h - Stores summaries of functions. ------------*- C++ -*-//
+//===- FunctionSummary.h - Stores summaries of functions. -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,15 +18,18 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallBitVector.h"
+#include <cassert>
#include <deque>
+#include <utility>
namespace clang {
-
namespace ento {
-typedef std::deque<Decl*> SetOfDecls;
-typedef llvm::DenseSet<const Decl*> SetOfConstDecls;
+
+using SetOfDecls = std::deque<Decl *>;
+using SetOfConstDecls = llvm::DenseSet<const Decl *>;
class FunctionSummariesTy {
class FunctionSummary {
@@ -47,13 +50,12 @@ class FunctionSummariesTy {
/// The number of times the function has been inlined.
unsigned TimesInlined : 32;
- FunctionSummary() :
- TotalBasicBlocks(0),
- InlineChecked(0),
- TimesInlined(0) {}
+ FunctionSummary()
+ : TotalBasicBlocks(0), InlineChecked(0), MayInline(0),
+ TimesInlined(0) {}
};
- typedef llvm::DenseMap<const Decl *, FunctionSummary> MapTy;
+ using MapTy = llvm::DenseMap<const Decl *, FunctionSummary>;
MapTy Map;
public:
@@ -62,7 +64,8 @@ public:
if (I != Map.end())
return I;
- typedef std::pair<const Decl *, FunctionSummary> KVPair;
+ using KVPair = std::pair<const Decl *, FunctionSummary>;
+
I = Map.insert(KVPair(D, FunctionSummary())).first;
assert(I != Map.end());
return I;
@@ -132,9 +135,9 @@ public:
unsigned getTotalNumBasicBlocks();
unsigned getTotalNumVisitedBasicBlocks();
-
};
-}} // end clang ento namespaces
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
index 3168733e4258..f494c5d6dab8 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
@@ -22,7 +22,7 @@
namespace clang {
namespace ento {
-/// \brief Get the states that result from widening the loop.
+/// Get the states that result from widening the loop.
///
/// Widen the loop by invalidating anything that might be modified
/// by the loop body in any iteration.
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 8ab665623088..3a93aae5a9bc 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
@@ -1,4 +1,4 @@
-//== MemRegion.h - Abstract memory regions for static analysis --*- C++ -*--==//
+//==- MemRegion.h - Abstract memory regions for static analysis -*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
@@ -19,24 +19,39 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
#include <string>
+#include <utility>
namespace clang {
+class AnalysisDeclContext;
+class CXXRecordDecl;
+class Decl;
class LocationContext;
class StackFrameContext;
namespace ento {
class CodeTextRegion;
+class MemRegion;
class MemRegionManager;
class MemSpaceRegion;
class SValBuilder;
@@ -46,7 +61,7 @@ class VarRegion;
/// Represent a region's offset within the top level base region.
class RegionOffset {
/// The base region.
- const MemRegion *R;
+ const MemRegion *R = nullptr;
/// The bit offset within the base region. Can be negative.
int64_t Offset;
@@ -54,9 +69,9 @@ class RegionOffset {
public:
// We're using a const instead of an enumeration due to the size required;
// Visual Studio will only create enumerations of size int, not long long.
- static const int64_t Symbolic = INT64_MAX;
+ static const int64_t Symbolic = std::numeric_limits<int64_t>::max();
- RegionOffset() : R(nullptr) {}
+ RegionOffset() = default;
RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
const MemRegion *getRegion() const { return R; }
@@ -86,6 +101,7 @@ public:
private:
const Kind kind;
+ mutable Optional<RegionOffset> cachedOffset;
protected:
MemRegion(Kind k) : kind(k) {}
@@ -103,43 +119,44 @@ public:
const MemRegion *getBaseRegion() const;
/// Check if the region is a subregion of the given region.
+ /// Each region is a subregion of itself.
virtual bool isSubRegionOf(const MemRegion *R) const;
const MemRegion *StripCasts(bool StripBaseCasts = true) const;
- /// \brief If this is a symbolic region, returns the region. Otherwise,
+ /// If this is a symbolic region, returns the region. Otherwise,
/// goes up the base chain looking for the first symbolic base region.
const SymbolicRegion *getSymbolicBase() const;
bool hasGlobalsOrParametersStorage() const;
bool hasStackStorage() const;
-
+
bool hasStackNonParametersStorage() const;
-
+
bool hasStackParametersStorage() const;
/// Compute the offset within the top level memory object.
RegionOffset getAsOffset() const;
- /// \brief Get a string representation of a region for debug use.
+ /// Get a string representation of a region for debug use.
std::string getString() const;
virtual void dumpToStream(raw_ostream &os) const;
void dump() const;
- /// \brief Returns true if this region can be printed in a user-friendly way.
+ /// Returns true if this region can be printed in a user-friendly way.
virtual bool canPrintPretty() const;
- /// \brief Print the region for use in diagnostics.
+ /// Print the region for use in diagnostics.
virtual void printPretty(raw_ostream &os) const;
- /// \brief Returns true if this region's textual representation can be used
+ /// Returns true if this region's textual representation can be used
/// as part of a larger expression.
virtual bool canPrintPrettyAsExpr() const;
- /// \brief Print the region as expression.
+ /// Print the region as expression.
///
/// When this region represents a subexpression, the method is for printing
/// an expression containing it.
@@ -151,7 +168,6 @@ public:
virtual bool isBoundable() const { return false; }
-
/// Get descriptive name for memory region. The name is obtained from
/// the variable/field declaration retrieved from the memory region.
/// Regions that point to an element of an array are returned as: "arr[0]".
@@ -162,7 +178,6 @@ public:
/// \returns variable name for memory region
std::string getDescriptiveName(bool UseQuotes = true) const;
-
/// Retrieve source range from memory region. The range retrieval
/// is based on the decl obtained from the memory region.
/// For a VarRegion the range of the base region is returned.
@@ -171,7 +186,7 @@ public:
/// The client is responsible for checking if the returned range is valid.
///
/// \returns source range for declaration retrieved from memory region
- clang::SourceRange sourceRange() const;
+ SourceRange sourceRange() const;
};
/// MemSpaceRegion - A memory region that represents a "memory space";
@@ -229,7 +244,7 @@ public:
}
};
-/// \brief The region of the static variables within the current CodeTextRegion
+/// The region of the static variables within the current CodeTextRegion
/// scope.
///
/// Currently, only the static locals are placed there, so we know that these
@@ -238,9 +253,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
friend class MemRegionManager;
const CodeTextRegion *CR;
-
+
StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
- : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
+ : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
assert(cr);
}
@@ -256,14 +271,14 @@ public:
}
};
-/// \brief The region for all the non-static global variables.
+/// The region for all the non-static global variables.
///
/// This class is further split into subclasses for efficient implementation of
/// invalidating a set of related global values as is done in
/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
/// globals, we invalidate the whole parent region).
class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
- virtual void anchor() override;
+ void anchor() override;
protected:
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
@@ -272,7 +287,6 @@ protected:
}
public:
-
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
@@ -280,16 +294,15 @@ public:
}
};
-/// \brief The region containing globals which are defined in system/external
+/// The region containing globals which are defined in system/external
/// headers and are considered modifiable by system calls (ex: errno).
class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
GlobalSystemSpaceRegion(MemRegionManager *mgr)
- : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
+ : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
public:
-
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
@@ -297,7 +310,7 @@ public:
}
};
-/// \brief The region containing globals which are considered not to be modified
+/// The region containing globals which are considered not to be modified
/// or point to data which could be modified as a result of a function call
/// (system or internal). Ex: Const global scalars would be modeled as part of
/// this region. This region also includes most system globals since they have
@@ -306,10 +319,9 @@ class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
GlobalImmutableSpaceRegion(MemRegionManager *mgr)
- : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
+ : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
public:
-
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
@@ -317,17 +329,16 @@ public:
}
};
-/// \brief The region containing globals which can be modified by calls to
+/// The region containing globals which can be modified by calls to
/// "internally" defined functions - (for now just) functions other then system
/// calls.
class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
GlobalInternalSpaceRegion(MemRegionManager *mgr)
- : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
+ : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
public:
-
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
@@ -337,25 +348,25 @@ public:
class HeapSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
-
+
HeapSpaceRegion(MemRegionManager *mgr)
- : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
-public:
+ : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
+public:
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == HeapSpaceRegionKind;
}
};
-
+
class UnknownSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
+
UnknownSpaceRegion(MemRegionManager *mgr)
: MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
public:
-
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
@@ -370,7 +381,7 @@ class StackSpaceRegion : public MemSpaceRegion {
protected:
StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
- : MemSpaceRegion(mgr, k), SFC(sfc) {
+ : MemSpaceRegion(mgr, k), SFC(sfc) {
assert(classof(this));
assert(sfc);
}
@@ -388,10 +399,11 @@ public:
class StackLocalsSpaceRegion : public StackSpaceRegion {
friend class MemRegionManager;
+
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
- : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
-public:
+ : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
+public:
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
@@ -402,10 +414,11 @@ public:
class StackArgumentsSpaceRegion : public StackSpaceRegion {
private:
friend class MemRegionManager;
+
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
- : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
-public:
+ : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
+public:
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
@@ -413,7 +426,6 @@ public:
}
};
-
/// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion.
class SubRegion : public MemRegion {
@@ -421,6 +433,7 @@ class SubRegion : public MemRegion {
protected:
const MemRegion* superRegion;
+
SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) {
assert(classof(this));
assert(sReg);
@@ -454,8 +467,10 @@ public:
class AllocaRegion : public SubRegion {
friend class MemRegionManager;
- unsigned Cnt; // Block counter. Used to distinguish different pieces of
- // memory allocated by alloca at the same call site.
+ // Block counter. Used to distinguish different pieces of memory allocated by
+ // alloca at the same call site.
+ unsigned Cnt;
+
const Expr *Ex;
AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion)
@@ -467,7 +482,6 @@ class AllocaRegion : public SubRegion {
unsigned Cnt, const MemRegion *superRegion);
public:
-
const Expr *getExpr() const { return Ex; }
bool isBoundable() const override { return true; }
@@ -485,7 +499,7 @@ public:
/// TypedRegion - An abstract class representing regions that are typed.
class TypedRegion : public SubRegion {
- virtual void anchor() override;
+ void anchor() override;
protected:
TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) {
@@ -509,7 +523,7 @@ public:
/// TypedValueRegion - An abstract class representing regions having a typed value.
class TypedValueRegion : public TypedRegion {
- virtual void anchor() override;
+ void anchor() override;
protected:
TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {
@@ -541,9 +555,8 @@ public:
}
};
-
class CodeTextRegion : public TypedRegion {
- virtual void anchor() override;
+ void anchor() override;
protected:
CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) {
@@ -566,7 +579,7 @@ class FunctionCodeRegion : public CodeTextRegion {
const NamedDecl *FD;
FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg)
- : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
+ : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
}
@@ -576,7 +589,7 @@ class FunctionCodeRegion : public CodeTextRegion {
public:
QualType getLocationType() const override {
const ASTContext &Ctx = getContext();
- if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
+ if (const auto *D = dyn_cast<FunctionDecl>(FD)) {
return Ctx.getPointerType(D->getType());
}
@@ -585,7 +598,7 @@ public:
// TODO: We might want to return a different type here (ex: id (*ty)(...))
// depending on how it is used.
- return QualType();
+ return {};
}
const NamedDecl *getDecl() const {
@@ -600,8 +613,7 @@ public:
return R->getKind() == FunctionCodeRegionKind;
}
};
-
-
+
/// BlockCodeRegion - A region that represents code texts of blocks (closures).
/// Blocks are represented with two kinds of regions. BlockCodeRegions
/// represent the "code", while BlockDataRegions represent instances of blocks,
@@ -631,7 +643,7 @@ public:
QualType getLocationType() const override {
return locTy;
}
-
+
const BlockDecl *getDecl() const {
return BD;
}
@@ -646,7 +658,7 @@ public:
return R->getKind() == BlockCodeRegionKind;
}
};
-
+
/// BlockDataRegion - A region that represents a block instance.
/// Blocks are represented with two kinds of regions. BlockCodeRegions
/// represent the "code", while BlockDataRegions represent instances of blocks,
@@ -657,15 +669,15 @@ class BlockDataRegion : public TypedRegion {
friend class MemRegionManager;
const BlockCodeRegion *BC;
- const LocationContext *LC; // Can be null */
+ const LocationContext *LC; // Can be null
unsigned BlockCount;
- void *ReferencedVars;
- void *OriginalVars;
+ void *ReferencedVars = nullptr;
+ void *OriginalVars = nullptr;
BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
unsigned count, const MemSpaceRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
- BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) {
+ BlockCount(count) {
assert(bc);
assert(lc);
assert(isa<GlobalImmutableSpaceRegion>(sreg) ||
@@ -679,7 +691,7 @@ class BlockDataRegion : public TypedRegion {
public:
const BlockCodeRegion *getCodeRegion() const { return BC; }
-
+
const BlockDecl *getDecl() const { return BC->getDecl(); }
QualType getLocationType() const override { return BC->getLocationType(); }
@@ -687,14 +699,16 @@ public:
class referenced_vars_iterator {
const MemRegion * const *R;
const MemRegion * const *OriginalR;
+
public:
explicit referenced_vars_iterator(const MemRegion * const *r,
const MemRegion * const *originalR)
- : R(r), OriginalR(originalR) {}
+ : R(r), OriginalR(originalR) {}
const VarRegion *getCapturedRegion() const {
return cast<VarRegion>(*R);
}
+
const VarRegion *getOriginalRegion() const {
return cast<VarRegion>(*OriginalR);
}
@@ -703,10 +717,12 @@ public:
assert((R == nullptr) == (I.R == nullptr));
return I.R == R;
}
+
bool operator!=(const referenced_vars_iterator &I) const {
assert((R == nullptr) == (I.R == nullptr));
return I.R != R;
}
+
referenced_vars_iterator &operator++() {
++R;
++OriginalR;
@@ -717,9 +733,9 @@ public:
/// Return the original region for a captured region, if
/// one exists.
const VarRegion *getOriginalRegion(const VarRegion *VR) const;
-
+
referenced_vars_iterator referenced_vars_begin() const;
- referenced_vars_iterator referenced_vars_end() const;
+ referenced_vars_iterator referenced_vars_end() const;
void dumpToStream(raw_ostream &os) const override;
@@ -728,6 +744,7 @@ public:
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
}
+
private:
void LazyInitializeReferencedVars();
std::pair<const VarRegion *, const VarRegion *>
@@ -754,9 +771,7 @@ class SymbolicRegion : public SubRegion {
}
public:
- SymbolRef getSymbol() const {
- return sym;
- }
+ SymbolRef getSymbol() const { return sym; }
bool isBoundable() const override { return true; }
@@ -779,24 +794,21 @@ public:
class StringRegion : public TypedValueRegion {
friend class MemRegionManager;
- const StringLiteral* Str;
+ const StringLiteral *Str;
StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg)
: TypedValueRegion(sreg, StringRegionKind), Str(str) {
assert(str);
}
- static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- const StringLiteral* Str,
- const MemRegion* superRegion);
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const StringLiteral *Str,
+ const MemRegion *superRegion);
public:
+ const StringLiteral *getStringLiteral() const { return Str; }
- const StringLiteral* getStringLiteral() const { return Str; }
-
- QualType getValueType() const override {
- return Str->getType();
- }
+ QualType getValueType() const override { return Str->getType(); }
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
@@ -812,12 +824,12 @@ public:
return R->getKind() == StringRegionKind;
}
};
-
+
/// The region associated with an ObjCStringLiteral.
class ObjCStringRegion : public TypedValueRegion {
friend class MemRegionManager;
- const ObjCStringLiteral* Str;
+ const ObjCStringLiteral *Str;
ObjCStringRegion(const ObjCStringLiteral *str,
const GlobalInternalSpaceRegion *sreg)
@@ -825,17 +837,14 @@ class ObjCStringRegion : public TypedValueRegion {
assert(str);
}
- static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- const ObjCStringLiteral* Str,
- const MemRegion* superRegion);
-
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const ObjCStringLiteral *Str,
+ const MemRegion *superRegion);
+
public:
-
- const ObjCStringLiteral* getObjCStringLiteral() const { return Str; }
+ const ObjCStringLiteral *getObjCStringLiteral() const { return Str; }
- QualType getValueType() const override {
- return Str->getType();
- }
+ QualType getValueType() const override { return Str->getType(); }
bool isBoundable() const override { return false; }
@@ -869,10 +878,9 @@ class CompoundLiteralRegion : public TypedValueRegion {
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const CompoundLiteralExpr *CL,
const MemRegion* superRegion);
+
public:
- QualType getValueType() const override {
- return CL->getType();
- }
+ QualType getValueType() const override { return CL->getType(); }
bool isBoundable() const override { return !CL->isFileScope(); }
@@ -889,9 +897,9 @@ public:
class DeclRegion : public TypedValueRegion {
protected:
- const Decl *D;
+ const ValueDecl *D;
- DeclRegion(const Decl *d, const MemRegion *sReg, Kind k)
+ DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k)
: TypedValueRegion(sReg, k), D(d) {
assert(classof(this));
assert(d);
@@ -901,7 +909,7 @@ protected:
const MemRegion* superRegion, Kind k);
public:
- const Decl *getDecl() const { return D; }
+ const ValueDecl *getDecl() const { return D; }
void Profile(llvm::FoldingSetNodeID& ID) const override;
static bool classof(const MemRegion* R) {
@@ -943,15 +951,15 @@ public:
void dumpToStream(raw_ostream &os) const override;
- static bool classof(const MemRegion* R) {
- return R->getKind() == VarRegionKind;
- }
-
bool canPrintPrettyAsExpr() const override;
void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == VarRegionKind;
+ }
};
-
+
/// CXXThisRegion - Represents the region for the implicit 'this' parameter
/// in a call to a C++ method. This region doesn't represent the object
/// referred to by 'this', but rather 'this' itself.
@@ -961,7 +969,10 @@ class CXXThisRegion : public TypedValueRegion {
CXXThisRegion(const PointerType *thisPointerTy,
const StackArgumentsSpaceRegion *sReg)
: TypedValueRegion(sReg, CXXThisRegionKind),
- ThisPointerTy(thisPointerTy) {}
+ ThisPointerTy(thisPointerTy) {
+ assert(ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() &&
+ "Invalid region type!");
+ }
static void ProfileRegion(llvm::FoldingSetNodeID &ID,
const PointerType *PT,
@@ -988,7 +999,7 @@ class FieldRegion : public DeclRegion {
friend class MemRegionManager;
FieldRegion(const FieldDecl *fd, const SubRegion* sReg)
- : DeclRegion(fd, sReg, FieldRegionKind) {}
+ : DeclRegion(fd, sReg, FieldRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
const MemRegion* superRegion) {
@@ -1005,16 +1016,16 @@ public:
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
- static bool classof(const MemRegion* R) {
- return R->getKind() == FieldRegionKind;
- }
-
void dumpToStream(raw_ostream &os) const override;
bool canPrintPretty() const override;
void printPretty(raw_ostream &os) const override;
bool canPrintPrettyAsExpr() const override;
void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FieldRegionKind;
+ }
};
class ObjCIvarRegion : public DeclRegion {
@@ -1038,12 +1049,11 @@ public:
return R->getKind() == ObjCIvarRegionKind;
}
};
+
//===----------------------------------------------------------------------===//
// Auxiliary data classes for use with MemRegions.
//===----------------------------------------------------------------------===//
-class ElementRegion;
-
class RegionRawOffset {
friend class ElementRegion;
@@ -1051,7 +1061,7 @@ class RegionRawOffset {
CharUnits Offset;
RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
- : Region(reg), Offset(offset) {}
+ : Region(reg), Offset(offset) {}
public:
// FIXME: Eventually support symbolic offsets.
@@ -1062,7 +1072,7 @@ public:
void dump() const;
};
-/// \brief ElementRegin is used to represent both array elements and casts.
+/// ElementRegin is used to represent both array elements and casts.
class ElementRegion : public TypedValueRegion {
friend class MemRegionManager;
@@ -1070,27 +1080,25 @@ class ElementRegion : public TypedValueRegion {
NonLoc Index;
ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg)
- : TypedValueRegion(sReg, ElementRegionKind),
- ElementType(elementType), Index(Idx) {
+ : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType),
+ Index(Idx) {
assert((!Idx.getAs<nonloc::ConcreteInt>() ||
Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
"The index must be signed");
+ assert(!elementType.isNull() && !elementType->isVoidType() &&
+ "Invalid region type!");
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
SVal Idx, const MemRegion* superRegion);
public:
-
NonLoc getIndex() const { return Index; }
- QualType getValueType() const override {
- return ElementType;
- }
+ QualType getValueType() const override { return ElementType; }
+
+ QualType getElementType() const { return ElementType; }
- QualType getElementType() const {
- return ElementType;
- }
/// Compute the offset within the array. The array might also be a subobject.
RegionRawOffset getAsArrayOffset() const;
@@ -1122,9 +1130,7 @@ class CXXTempObjectRegion : public TypedValueRegion {
public:
const Expr *getExpr() const { return Ex; }
- QualType getValueType() const override {
- return Ex->getType();
- }
+ QualType getValueType() const override { return Ex->getType(); }
void dumpToStream(raw_ostream &os) const override;
@@ -1135,7 +1141,7 @@ public:
}
};
-// CXXBaseObjectRegion represents a base object within a C++ object. It is
+// CXXBaseObjectRegion represents a base object within a C++ object. It is
// identified by the base class declaration and the region of its parent object.
class CXXBaseObjectRegion : public TypedValueRegion {
friend class MemRegionManager;
@@ -1161,18 +1167,18 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
- static bool classof(const MemRegion *region) {
- return region->getKind() == CXXBaseObjectRegionKind;
- }
-
bool canPrintPrettyAsExpr() const override;
void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXBaseObjectRegionKind;
+ }
};
template<typename RegionTy>
const RegionTy* MemRegion::getAs() const {
- if (const RegionTy* RT = dyn_cast<RegionTy>(this))
+ if (const auto *RT = dyn_cast<RegionTy>(this))
return RT;
return nullptr;
@@ -1187,32 +1193,27 @@ class MemRegionManager {
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
- GlobalInternalSpaceRegion *InternalGlobals;
- GlobalSystemSpaceRegion *SystemGlobals;
- GlobalImmutableSpaceRegion *ImmutableGlobals;
+ GlobalInternalSpaceRegion *InternalGlobals = nullptr;
+ GlobalSystemSpaceRegion *SystemGlobals = nullptr;
+ GlobalImmutableSpaceRegion *ImmutableGlobals = nullptr;
-
- llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
+ llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
StackLocalsSpaceRegions;
llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
StackArgumentsSpaceRegions;
llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
StaticsGlobalSpaceRegions;
- HeapSpaceRegion *heap;
- UnknownSpaceRegion *unknown;
- CodeSpaceRegion *code;
+ HeapSpaceRegion *heap = nullptr;
+ UnknownSpaceRegion *unknown = nullptr;
+ CodeSpaceRegion *code = nullptr;
public:
- MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
- : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr),
- ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr),
- code(nullptr) {}
-
+ MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : C(c), A(a) {}
~MemRegionManager();
ASTContext &getContext() { return C; }
-
+
llvm::BumpPtrAllocator &getAllocator() { return A; }
/// getStackLocalsRegion - Retrieve the memory region associated with the
@@ -1250,19 +1251,19 @@ public:
const CompoundLiteralRegion*
getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
const LocationContext *LC);
-
+
/// getCXXThisRegion - Retrieve the [artificial] region associated with the
/// parameter 'this'.
const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC);
- /// \brief Retrieve or create a "symbolic" memory region.
+ /// Retrieve or create a "symbolic" memory region.
const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
- /// \brief Return a unique symbolic region belonging to heap memory space.
+ /// Return a unique symbolic region belonging to heap memory space.
const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
- const StringRegion *getStringRegion(const StringLiteral* Str);
+ const StringRegion *getStringRegion(const StringLiteral *Str);
const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
@@ -1319,7 +1320,7 @@ public:
/// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
/// super region.
const CXXBaseObjectRegion *
- getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
+ getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
const SubRegion *superRegion) {
return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
baseReg->isVirtual());
@@ -1329,7 +1330,7 @@ public:
const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
CanQualType locTy,
AnalysisDeclContext *AC);
-
+
/// getBlockDataRegion - Get the memory region associated with an instance
/// of a block. Unlike many other MemRegions, the LocationContext*
/// argument is allowed to be NULL for cases where we have no known
@@ -1362,7 +1363,7 @@ private:
template <typename REG>
const REG* LazyAllocate(REG*& region);
-
+
template <typename REG, typename ARG>
const REG* LazyAllocate(REG*& region, ARG a);
};
@@ -1381,29 +1382,33 @@ inline ASTContext &MemRegion::getContext() const {
/// Information about invalidation for a particular region/symbol.
class RegionAndSymbolInvalidationTraits {
- typedef unsigned char StorageTypeForKinds;
+ using StorageTypeForKinds = unsigned char;
+
llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
- typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator
- const_region_iterator;
- typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator
- const_symbol_iterator;
+ using const_region_iterator =
+ llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator;
+ using const_symbol_iterator =
+ llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator;
public:
- /// \brief Describes different invalidation traits.
+ /// Describes different invalidation traits.
enum InvalidationKinds {
/// Tells that a region's contents is not changed.
TK_PreserveContents = 0x1,
+
/// Suppress pointer-escaping of a region.
TK_SuppressEscape = 0x2,
+
// Do not invalidate super region.
TK_DoNotInvalidateSuperRegion = 0x4,
+
/// When applied to a MemSpaceRegion, indicates the entire memory space
/// should be invalidated.
TK_EntireMemSpace = 0x8
- // Do not forget to extend StorageTypeForKinds if number of traits exceed
+ // Do not forget to extend StorageTypeForKinds if number of traits exceed
// the number of bits StorageTypeForKinds can store.
};
@@ -1416,8 +1421,7 @@ public:
//===----------------------------------------------------------------------===//
// Pretty-printing regions.
//===----------------------------------------------------------------------===//
-inline raw_ostream &operator<<(raw_ostream &os,
- const clang::ento::MemRegion *R) {
+inline raw_ostream &operator<<(raw_ostream &os, const MemRegion *R) {
R->dumpToStream(os);
return os;
}
@@ -1426,4 +1430,4 @@ inline raw_ostream &operator<<(raw_ostream &os,
} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
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 dd2564b0a3c3..b86301a03470 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
@@ -36,6 +36,7 @@ class ASTContext;
namespace ento {
+class AnalysisManager;
class CallEvent;
class CallEventManager;
@@ -111,6 +112,8 @@ public:
return *stateMgr;
}
+ AnalysisManager &getAnalysisManager() const;
+
/// Return the ConstraintManager.
ConstraintManager &getConstraintManager() const;
@@ -177,20 +180,20 @@ public:
///
/// This returns a new state with the added constraint on \p cond.
/// If no new state is feasible, NULL is returned.
- ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const;
+ LLVM_NODISCARD ProgramStateRef assume(DefinedOrUnknownSVal cond,
+ bool assumption) const;
/// Assumes both "true" and "false" for \p cond, and returns both
/// corresponding states (respectively).
///
/// This is more efficient than calling assume() twice. Note that one (but not
/// both) of the returned states may be NULL.
- std::pair<ProgramStateRef, ProgramStateRef>
+ LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef>
assume(DefinedOrUnknownSVal cond) const;
- ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx,
- DefinedOrUnknownSVal upperBound,
- bool assumption,
- QualType IndexType = QualType()) const;
+ LLVM_NODISCARD ProgramStateRef
+ assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound,
+ bool assumption, QualType IndexType = QualType()) const;
/// Assumes that the value of \p Val is bounded with [\p From; \p To]
/// (if \p assumption is "true") or it is fully out of this range
@@ -198,24 +201,31 @@ public:
///
/// This returns a new state with the added constraint on \p cond.
/// If no new state is feasible, NULL is returned.
- ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool assumption) const;
+ LLVM_NODISCARD ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool assumption) const;
/// Assumes given range both "true" and "false" for \p Val, and returns both
/// corresponding states (respectively).
///
/// This is more efficient than calling assume() twice. Note that one (but not
/// both) of the returned states may be NULL.
- std::pair<ProgramStateRef, ProgramStateRef>
+ LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef>
assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
const llvm::APSInt &To) const;
- /// \brief Check if the given SVal is constrained to zero or is a zero
+ /// Check if the given SVal is not constrained to zero and is not
+ /// a zero constant.
+ ConditionTruthVal isNonNull(SVal V) const;
+
+ /// Check if the given SVal is constrained to zero or is a zero
/// constant.
ConditionTruthVal isNull(SVal V) const;
+ /// \return Whether values \p Lhs and \p Rhs are equal.
+ ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const;
+
/// Utility method for getting regions.
const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
@@ -225,21 +235,34 @@ public:
/// Create a new state by binding the value 'V' to the statement 'S' in the
/// state's environment.
- ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx,
- SVal V, bool Invalidate = true) const;
-
- ProgramStateRef bindLoc(Loc location,
- SVal V,
- const LocationContext *LCtx,
- bool notifyChanges = true) const;
-
- ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const;
-
- ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const;
-
- ProgramStateRef killBinding(Loc LV) const;
-
- /// \brief Returns the state with bindings for the given regions
+ LLVM_NODISCARD ProgramStateRef BindExpr(const Stmt *S,
+ const LocationContext *LCtx, SVal V,
+ bool Invalidate = true) const;
+
+ LLVM_NODISCARD ProgramStateRef bindLoc(Loc location, SVal V,
+ const LocationContext *LCtx,
+ bool notifyChanges = true) const;
+
+ LLVM_NODISCARD ProgramStateRef bindLoc(SVal location, SVal V,
+ const LocationContext *LCtx) const;
+
+ /// Initializes the region of memory represented by \p loc with an initial
+ /// value. Once initialized, all values loaded from any sub-regions of that
+ /// region will be equal to \p V, unless overwritten later by the program.
+ /// This method should not be used on regions that are already initialized.
+ /// If you need to indicate that memory contents have suddenly become unknown
+ /// within a certain region of memory, consider invalidateRegions().
+ LLVM_NODISCARD ProgramStateRef
+ bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const;
+
+ /// Performs C++ zero-initialization procedure on the region of memory
+ /// represented by \p loc.
+ LLVM_NODISCARD ProgramStateRef
+ bindDefaultZero(SVal loc, const LocationContext *LCtx) const;
+
+ LLVM_NODISCARD ProgramStateRef killBinding(Loc LV) const;
+
+ /// Returns the state with bindings for the given regions
/// cleared from the store.
///
/// Optionally invalidates global regions as well.
@@ -257,14 +280,14 @@ public:
/// the call and should be considered directly invalidated.
/// \param ITraits information about special handling for a particular
/// region/symbol.
- ProgramStateRef
+ LLVM_NODISCARD ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
const CallEvent *Call = nullptr,
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
- ProgramStateRef
+ LLVM_NODISCARD ProgramStateRef
invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
@@ -273,8 +296,15 @@ public:
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
- ProgramStateRef enterStackFrame(const CallEvent &Call,
- const StackFrameContext *CalleeCtx) const;
+ LLVM_NODISCARD ProgramStateRef enterStackFrame(
+ const CallEvent &Call, const StackFrameContext *CalleeCtx) const;
+
+ /// Get the lvalue for a base class object reference.
+ Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const;
+
+ /// Get the lvalue for a base class object reference.
+ Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super,
+ bool IsVirtual) const;
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@@ -299,24 +329,24 @@ public:
SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
- /// \brief Return the value bound to the specified location.
+ /// Return the value bound to the specified location.
/// Returns UnknownVal() if none found.
SVal getSVal(Loc LV, QualType T = QualType()) const;
/// Returns the "raw" SVal bound to LV before any value simplfication.
SVal getRawSVal(Loc LV, QualType T= QualType()) const;
- /// \brief Return the value bound to the specified location.
+ /// Return the value bound to the specified location.
/// Returns UnknownVal() if none found.
SVal getSVal(const MemRegion* R, QualType T = QualType()) const;
- /// \brief Return the value bound to the specified location, assuming
+ /// 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
+ /// Visits the symbols reachable from the given SVal using the provided
/// SymbolVisitor.
///
/// This is a convenience API. Consider using ScanReachableSymbols class
@@ -325,12 +355,12 @@ public:
/// \sa ScanReachableSymbols
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
- /// \brief Visits the symbols reachable from the SVals in the given range
+ /// Visits the symbols reachable from the SVals in the given range
/// using the provided SymbolVisitor.
bool scanReachableSymbols(const SVal *I, const SVal *E,
SymbolVisitor &visitor) const;
- /// \brief Visits the symbols reachable from the regions in the given
+ /// Visits the symbols reachable from the regions in the given
/// MemRegions range using the provided SymbolVisitor.
bool scanReachableSymbols(const MemRegion * const *I,
const MemRegion * const *E,
@@ -345,27 +375,29 @@ public:
const MemRegion * const *end) const;
/// Create a new state in which the statement is marked as tainted.
- ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric) const;
+ LLVM_NODISCARD ProgramStateRef
+ addTaint(const Stmt *S, const LocationContext *LCtx,
+ TaintTagType Kind = TaintTagGeneric) const;
/// Create a new state in which the value is marked as tainted.
- ProgramStateRef addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const;
+ LLVM_NODISCARD ProgramStateRef
+ addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const;
/// Create a new state in which the symbol is marked as tainted.
- ProgramStateRef addTaint(SymbolRef S,
+ LLVM_NODISCARD ProgramStateRef addTaint(SymbolRef S,
TaintTagType Kind = TaintTagGeneric) const;
/// Create a new state in which the region symbol is marked as tainted.
- ProgramStateRef addTaint(const MemRegion *R,
- TaintTagType Kind = TaintTagGeneric) const;
+ LLVM_NODISCARD ProgramStateRef
+ addTaint(const MemRegion *R, TaintTagType Kind = TaintTagGeneric) const;
/// Create a new state in a which a sub-region of a given symbol is tainted.
/// This might be necessary when referring to regions that can not have an
/// individual symbol, e.g. if they are represented by the default binding of
/// a LazyCompoundVal.
- ProgramStateRef addPartialTaint(SymbolRef ParentSym,
- const SubRegion *SubRegion,
- TaintTagType Kind = TaintTagGeneric) const;
+ LLVM_NODISCARD ProgramStateRef
+ addPartialTaint(SymbolRef ParentSym, const SubRegion *SubRegion,
+ TaintTagType Kind = TaintTagGeneric) const;
/// Check if the statement is tainted in the current state.
bool isTainted(const Stmt *S, const LocationContext *LCtx,
@@ -380,8 +412,9 @@ public:
void *const* FindGDM(void *K) const;
- template<typename T>
- ProgramStateRef add(typename ProgramStateTrait<T>::key_type K) const;
+ template <typename T>
+ LLVM_NODISCARD ProgramStateRef
+ add(typename ProgramStateTrait<T>::key_type K) const;
template <typename T>
typename ProgramStateTrait<T>::data_type
@@ -399,27 +432,31 @@ public:
template <typename T>
typename ProgramStateTrait<T>::context_type get_context() const;
+ template <typename T>
+ LLVM_NODISCARD ProgramStateRef
+ remove(typename ProgramStateTrait<T>::key_type K) const;
- template<typename T>
- ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K) const;
-
- template<typename T>
- ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::context_type C) const;
template <typename T>
- ProgramStateRef remove() const;
+ LLVM_NODISCARD ProgramStateRef
+ remove(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::context_type C) const;
- template<typename T>
- ProgramStateRef set(typename ProgramStateTrait<T>::data_type D) const;
+ template <typename T> LLVM_NODISCARD ProgramStateRef remove() const;
- template<typename T>
- ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type E) const;
+ template <typename T>
+ LLVM_NODISCARD ProgramStateRef
+ set(typename ProgramStateTrait<T>::data_type D) const;
- template<typename T>
- ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type E,
- typename ProgramStateTrait<T>::context_type C) const;
+ template <typename T>
+ LLVM_NODISCARD ProgramStateRef
+ set(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type E) const;
+
+ template <typename T>
+ LLVM_NODISCARD ProgramStateRef
+ set(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type E,
+ typename ProgramStateTrait<T>::context_type C) const;
template<typename T>
bool contains(typename ProgramStateTrait<T>::key_type key) const {
@@ -428,9 +465,10 @@ public:
}
// Pretty-printing.
- void print(raw_ostream &Out, const char *nl = "\n",
- const char *sep = "") const;
- void printDOT(raw_ostream &Out) const;
+ void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "",
+ const LocationContext *CurrentLC = nullptr) const;
+ void printDOT(raw_ostream &Out,
+ const LocationContext *CurrentLC = nullptr) const;
void printTaint(raw_ostream &Out, const char *nl = "\n",
const char *sep = "") const;
@@ -705,6 +743,22 @@ inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationCont
return this;
}
+inline Loc ProgramState::getLValue(const CXXBaseSpecifier &BaseSpec,
+ const SubRegion *Super) const {
+ const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+ return loc::MemRegionVal(
+ getStateManager().getRegionManager().getCXXBaseObjectRegion(
+ Base, Super, BaseSpec.isVirtual()));
+}
+
+inline Loc ProgramState::getLValue(const CXXRecordDecl *BaseClass,
+ const SubRegion *Super,
+ bool IsVirtual) const {
+ return loc::MemRegionVal(
+ getStateManager().getRegionManager().getCXXBaseObjectRegion(
+ BaseClass, Super, IsVirtual));
+}
+
inline Loc ProgramState::getLValue(const VarDecl *VD,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueVar(VD, LC);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index a04fa9005955..5555b292534c 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -14,33 +14,28 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
- template <typename K, typename D, typename I> class ImmutableMap;
- template <typename K, typename I> class ImmutableSet;
- template <typename T> class ImmutableList;
- template <typename T> class ImmutableListImpl;
-}
+#include <cstdint>
namespace clang {
-
namespace ento {
+
template <typename T> struct ProgramStatePartialTrait;
/// Declares a program state trait for type \p Type called \p Name, and
- /// introduce a typedef named \c NameTy.
+ /// introduce a type named \c NameTy.
/// The macro should not be used inside namespaces, or for traits that must
/// be accessible from more than one translation unit.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
namespace { \
class Name {}; \
- typedef Type Name ## Ty; \
+ using Name ## Ty = Type; \
} \
namespace clang { \
namespace ento { \
@@ -52,28 +47,30 @@ namespace ento {
} \
}
-
// Partial-specialization for ImmutableMap.
-
template <typename Key, typename Data, typename Info>
- struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
- typedef llvm::ImmutableMap<Key,Data,Info> data_type;
- typedef typename data_type::Factory& context_type;
- typedef Key key_type;
- typedef Data value_type;
- typedef const value_type* lookup_type;
-
- static inline data_type MakeData(void *const* p) {
- return p ? data_type((typename data_type::TreeTy*) *p)
+ struct ProgramStatePartialTrait<llvm::ImmutableMap<Key, Data, Info>> {
+ using data_type = llvm::ImmutableMap<Key, Data, Info>;
+ using context_type = typename data_type::Factory &;
+ using key_type = Key;
+ using value_type = Data;
+ using lookup_type = const value_type *;
+
+ static data_type MakeData(void *const *p) {
+ return p ? data_type((typename data_type::TreeTy *) *p)
: data_type(nullptr);
}
- static inline void *MakeVoidPtr(data_type B) {
+
+ static void *MakeVoidPtr(data_type B) {
return B.getRoot();
}
+
static lookup_type Lookup(data_type B, key_type K) {
return B.lookup(K);
}
- static data_type Set(data_type B, key_type K, value_type E,context_type F){
+
+ static data_type Set(data_type B, key_type K, value_type E,
+ context_type F) {
return F.add(B, K, E);
}
@@ -85,8 +82,8 @@ namespace ento {
return B.contains(K);
}
- static inline context_type MakeContext(void *p) {
- return *((typename data_type::Factory*) p);
+ static context_type MakeContext(void *p) {
+ return *((typename data_type::Factory *) p);
}
static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
@@ -94,7 +91,7 @@ namespace ento {
}
static void DeleteContext(void *Ctx) {
- delete (typename data_type::Factory*) Ctx;
+ delete (typename data_type::Factory *) Ctx;
}
};
@@ -107,21 +104,19 @@ namespace ento {
/// can deal with.
#define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
-
// Partial-specialization for ImmutableSet.
-
template <typename Key, typename Info>
- struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
- typedef llvm::ImmutableSet<Key,Info> data_type;
- typedef typename data_type::Factory& context_type;
- typedef Key key_type;
+ struct ProgramStatePartialTrait<llvm::ImmutableSet<Key, Info>> {
+ using data_type = llvm::ImmutableSet<Key, Info>;
+ using context_type = typename data_type::Factory &;
+ using key_type = Key;
- static inline data_type MakeData(void *const* p) {
- return p ? data_type((typename data_type::TreeTy*) *p)
+ static data_type MakeData(void *const *p) {
+ return p ? data_type((typename data_type::TreeTy *) *p)
: data_type(nullptr);
}
- static inline void *MakeVoidPtr(data_type B) {
+ static void *MakeVoidPtr(data_type B) {
return B.getRoot();
}
@@ -137,27 +132,25 @@ namespace ento {
return B.contains(K);
}
- static inline context_type MakeContext(void *p) {
- return *((typename data_type::Factory*) p);
+ static context_type MakeContext(void *p) {
+ return *((typename data_type::Factory *) p);
}
- static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ static void *CreateContext(llvm::BumpPtrAllocator &Alloc) {
return new typename data_type::Factory(Alloc);
}
static void DeleteContext(void *Ctx) {
- delete (typename data_type::Factory*) Ctx;
+ delete (typename data_type::Factory *) Ctx;
}
};
-
// Partial-specialization for ImmutableList.
-
template <typename T>
- struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
- typedef llvm::ImmutableList<T> data_type;
- typedef T key_type;
- typedef typename data_type::Factory& context_type;
+ struct ProgramStatePartialTrait<llvm::ImmutableList<T>> {
+ using data_type = llvm::ImmutableList<T>;
+ using key_type = T;
+ using context_type = typename data_type::Factory &;
static data_type Add(data_type L, key_type K, context_type F) {
return F.add(K, L);
@@ -167,83 +160,84 @@ namespace ento {
return L.contains(K);
}
- static inline data_type MakeData(void *const* p) {
- return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
+ static data_type MakeData(void *const *p) {
+ return p ? data_type((const llvm::ImmutableListImpl<T> *) *p)
: data_type(nullptr);
}
- static inline void *MakeVoidPtr(data_type D) {
+ static void *MakeVoidPtr(data_type D) {
return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
}
- static inline context_type MakeContext(void *p) {
- return *((typename data_type::Factory*) p);
+ static context_type MakeContext(void *p) {
+ return *((typename data_type::Factory *) p);
}
- static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ static void *CreateContext(llvm::BumpPtrAllocator &Alloc) {
return new typename data_type::Factory(Alloc);
}
static void DeleteContext(void *Ctx) {
- delete (typename data_type::Factory*) Ctx;
+ delete (typename data_type::Factory *) Ctx;
}
};
-
// Partial specialization for bool.
template <> struct ProgramStatePartialTrait<bool> {
- typedef bool data_type;
+ using data_type = bool;
- static inline data_type MakeData(void *const* p) {
+ static data_type MakeData(void *const *p) {
return p ? (data_type) (uintptr_t) *p
: data_type();
}
- static inline void *MakeVoidPtr(data_type d) {
- return (void*) (uintptr_t) d;
+
+ static void *MakeVoidPtr(data_type d) {
+ return (void *) (uintptr_t) d;
}
};
// Partial specialization for unsigned.
template <> struct ProgramStatePartialTrait<unsigned> {
- typedef unsigned data_type;
+ using data_type = unsigned;
- static inline data_type MakeData(void *const* p) {
+ static data_type MakeData(void *const *p) {
return p ? (data_type) (uintptr_t) *p
: data_type();
}
- static inline void *MakeVoidPtr(data_type d) {
- return (void*) (uintptr_t) d;
+
+ static void *MakeVoidPtr(data_type d) {
+ return (void *) (uintptr_t) d;
}
};
// Partial specialization for void*.
- template <> struct ProgramStatePartialTrait<void*> {
- typedef void *data_type;
+ template <> struct ProgramStatePartialTrait<void *> {
+ using data_type = void *;
- static inline data_type MakeData(void *const* p) {
+ static data_type MakeData(void *const *p) {
return p ? *p
: data_type();
}
- static inline void *MakeVoidPtr(data_type d) {
+
+ static void *MakeVoidPtr(data_type d) {
return d;
}
};
// Partial specialization for const void *.
template <> struct ProgramStatePartialTrait<const void *> {
- typedef const void *data_type;
+ using data_type = const void *;
- static inline data_type MakeData(void * const *p) {
+ static data_type MakeData(void *const *p) {
return p ? *p : data_type();
}
- static inline void *MakeVoidPtr(data_type d) {
+ static void *MakeVoidPtr(data_type d) {
return const_cast<void *>(d);
}
};
-} // end ento namespace
-
-} // end clang namespace
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
index a4e6062a4f57..d2ba1f7c9529 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
@@ -15,12 +15,126 @@
#define LLVM_CLANG_LIB_STATICANALYZER_CORE_RANGEDCONSTRAINTMANAGER_H
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
namespace clang {
namespace ento {
+/// A Range represents the closed range [from, to]. The caller must
+/// guarantee that from <= to. Note that Range is immutable, so as not
+/// to subvert RangeSet's immutability.
+class Range : public std::pair<const llvm::APSInt *, const llvm::APSInt *> {
+public:
+ Range(const llvm::APSInt &from, const llvm::APSInt &to)
+ : std::pair<const llvm::APSInt *, const llvm::APSInt *>(&from, &to) {
+ assert(from <= to);
+ }
+ bool Includes(const llvm::APSInt &v) const {
+ return *first <= v && v <= *second;
+ }
+ const llvm::APSInt &From() const { return *first; }
+ const llvm::APSInt &To() const { return *second; }
+ const llvm::APSInt *getConcreteValue() const {
+ return &From() == &To() ? &From() : nullptr;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(&From());
+ ID.AddPointer(&To());
+ }
+};
+
+class RangeTrait : public llvm::ImutContainerInfo<Range> {
+public:
+ // When comparing if one Range is less than another, we should compare
+ // the actual APSInt values instead of their pointers. This keeps the order
+ // consistent (instead of comparing by pointer values) and can potentially
+ // be used to speed up some of the operations in RangeSet.
+ static inline bool isLess(key_type_ref lhs, key_type_ref rhs) {
+ return *lhs.first < *rhs.first ||
+ (!(*rhs.first < *lhs.first) && *lhs.second < *rhs.second);
+ }
+};
+
+/// RangeSet contains a set of ranges. If the set is empty, then
+/// there the value of a symbol is overly constrained and there are no
+/// possible values for that symbol.
+class RangeSet {
+ typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet;
+ PrimRangeSet ranges; // no need to make const, since it is an
+ // ImmutableSet - this allows default operator=
+ // to work.
+public:
+ typedef PrimRangeSet::Factory Factory;
+ typedef PrimRangeSet::iterator iterator;
+
+ RangeSet(PrimRangeSet RS) : ranges(RS) {}
+
+ /// Create a new set with all ranges of this set and RS.
+ /// Possible intersections are not checked here.
+ RangeSet addRange(Factory &F, const RangeSet &RS) {
+ PrimRangeSet Ranges(RS.ranges);
+ for (const auto &range : ranges)
+ Ranges = F.add(Ranges, range);
+ return RangeSet(Ranges);
+ }
+
+ iterator begin() const { return ranges.begin(); }
+ iterator end() const { return ranges.end(); }
+
+ bool isEmpty() const { return ranges.isEmpty(); }
+
+ /// Construct a new RangeSet representing '{ [from, to] }'.
+ RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to)
+ : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
+
+ /// Profile - Generates a hash profile of this RangeSet for use
+ /// by FoldingSet.
+ void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); }
+
+ /// getConcreteValue - If a symbol is contrained to equal a specific integer
+ /// constant then this method returns that value. Otherwise, it returns
+ /// NULL.
+ const llvm::APSInt *getConcreteValue() const {
+ return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr;
+ }
+
+private:
+ void IntersectInRange(BasicValueFactory &BV, Factory &F,
+ const llvm::APSInt &Lower, const llvm::APSInt &Upper,
+ PrimRangeSet &newRanges, PrimRangeSet::iterator &i,
+ PrimRangeSet::iterator &e) const;
+
+ const llvm::APSInt &getMinValue() const;
+
+ bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const;
+
+public:
+ RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower,
+ llvm::APSInt Upper) const;
+
+ RangeSet Negate(BasicValueFactory &BV, Factory &F) const;
+
+ void print(raw_ostream &os) const;
+
+ bool operator==(const RangeSet &other) const {
+ return ranges == other.ranges;
+ }
+};
+
+
+class ConstraintRange {};
+using ConstraintRangeTy = llvm::ImmutableMap<SymbolRef, RangeSet>;
+
+template <>
+struct ProgramStateTrait<ConstraintRange>
+ : public ProgramStatePartialTrait<ConstraintRangeTy> {
+ static void *GDMIndex() { static int Index; return &Index; }
+};
+
+
class RangedConstraintManager : public SimpleConstraintManager {
public:
RangedConstraintManager(SubEngine *SE, SValBuilder &SB)
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
new file mode 100644
index 000000000000..19d3d5973e0f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
@@ -0,0 +1,77 @@
+//== SMTConstraintManager.h -------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a SMT generic API, which will be the base class for
+// every SMT solver specific class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h"
+
+namespace clang {
+namespace ento {
+
+class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
+ SMTSolverRef &Solver;
+
+public:
+ SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB,
+ SMTSolverRef &S)
+ : SimpleConstraintManager(SE, SB), Solver(S) {}
+ virtual ~SMTConstraintManager() = default;
+
+ //===------------------------------------------------------------------===//
+ // Implementation for interface from SimpleConstraintManager.
+ //===------------------------------------------------------------------===//
+
+ ProgramStateRef assumeSym(ProgramStateRef state, SymbolRef Sym,
+ bool Assumption) override;
+
+ ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange) override;
+
+ ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym,
+ bool Assumption) override;
+
+ //===------------------------------------------------------------------===//
+ // Implementation for interface from ConstraintManager.
+ //===------------------------------------------------------------------===//
+
+ ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
+
+ const llvm::APSInt *getSymVal(ProgramStateRef State,
+ SymbolRef Sym) const override;
+
+ /// Dumps SMT formula
+ LLVM_DUMP_METHOD void dump() const { Solver->dump(); }
+
+protected:
+ // Check whether a new model is satisfiable, and update the program state.
+ virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym,
+ const SMTExprRef &Exp) = 0;
+
+ /// Given a program state, construct the logical conjunction and add it to
+ /// the solver
+ virtual void addStateConstraints(ProgramStateRef State) const = 0;
+
+ // Generate and check a Z3 model, using the given constraint.
+ ConditionTruthVal checkModel(ProgramStateRef State,
+ const SMTExprRef &Exp) const;
+}; // end class SMTConstraintManager
+
+} // namespace ento
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h
new file mode 100644
index 000000000000..45c9df4ef401
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h
@@ -0,0 +1,31 @@
+//== SMTContext.h -----------------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a SMT generic Context API, which will be the base class
+// for every SMT solver context specific class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H
+
+namespace clang {
+namespace ento {
+
+/// Generic base class for SMT contexts
+class SMTContext {
+public:
+ SMTContext() = default;
+ virtual ~SMTContext() = default;
+};
+
+} // namespace ento
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h
new file mode 100644
index 000000000000..9dedf96cfaf8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h
@@ -0,0 +1,62 @@
+//== SMTExpr.h --------------------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a SMT generic Expr API, which will be the base class
+// for every SMT solver expr specific class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang {
+namespace ento {
+
+/// Generic base class for SMT exprs
+class SMTExpr {
+public:
+ SMTExpr() = default;
+ virtual ~SMTExpr() = default;
+
+ bool operator<(const SMTExpr &Other) const {
+ llvm::FoldingSetNodeID ID1, ID2;
+ Profile(ID1);
+ Other.Profile(ID2);
+ return ID1 < ID2;
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int Tag = 0;
+ ID.AddPointer(&Tag);
+ }
+
+ friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) {
+ return LHS.equal_to(RHS);
+ }
+
+ virtual void print(raw_ostream &OS) const = 0;
+
+ LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
+
+protected:
+ /// Query the SMT solver and returns true if two sorts are equal (same kind
+ /// and bit width). This does not check if the two sorts are the same objects.
+ virtual bool equal_to(SMTExpr const &other) const = 0;
+};
+
+/// Shared pointer for SMTExprs, used by SMTSolver API.
+using SMTExprRef = std::shared_ptr<SMTExpr>;
+
+} // namespace ento
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
new file mode 100644
index 000000000000..a43ca486901b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
@@ -0,0 +1,996 @@
+//== SMTSolver.h ------------------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a SMT generic Solver API, which will be the base class
+// for every SMT solver specific class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H
+
+#include "clang/AST/Expr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+
+namespace clang {
+namespace ento {
+
+/// Generic base class for SMT Solvers
+///
+/// This class is responsible for wrapping all sorts and expression generation,
+/// through the mk* methods. It also provides methods to create SMT expressions
+/// straight from clang's AST, through the from* methods.
+class SMTSolver {
+public:
+ SMTSolver() = default;
+ virtual ~SMTSolver() = default;
+
+ LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
+
+ // Returns an appropriate floating-point sort for the given bitwidth.
+ SMTSortRef getFloatSort(unsigned BitWidth) {
+ switch (BitWidth) {
+ case 16:
+ return getFloat16Sort();
+ case 32:
+ return getFloat32Sort();
+ case 64:
+ return getFloat64Sort();
+ case 128:
+ return getFloat128Sort();
+ default:;
+ }
+ llvm_unreachable("Unsupported floating-point bitwidth!");
+ }
+
+ // Returns an appropriate sort, given a QualType and it's bit width.
+ SMTSortRef mkSort(const QualType &Ty, unsigned BitWidth) {
+ if (Ty->isBooleanType())
+ return getBoolSort();
+
+ if (Ty->isRealFloatingType())
+ return getFloatSort(BitWidth);
+
+ return getBitvectorSort(BitWidth);
+ }
+
+ /// Constructs an SMTExprRef from an unary operator.
+ SMTExprRef fromUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp) {
+ switch (Op) {
+ case UO_Minus:
+ return mkBVNeg(Exp);
+
+ case UO_Not:
+ return mkBVNot(Exp);
+
+ case UO_LNot:
+ return mkNot(Exp);
+
+ default:;
+ }
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Constructs an SMTExprRef from a floating-point unary operator.
+ SMTExprRef fromFloatUnOp(const UnaryOperator::Opcode Op,
+ const SMTExprRef &Exp) {
+ switch (Op) {
+ case UO_Minus:
+ return mkFPNeg(Exp);
+
+ case UO_LNot:
+ return fromUnOp(Op, Exp);
+
+ default:;
+ }
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a n-ary binary operator.
+ SMTExprRef fromNBinOp(const BinaryOperator::Opcode Op,
+ const std::vector<SMTExprRef> &ASTs) {
+ assert(!ASTs.empty());
+
+ if (Op != BO_LAnd && Op != BO_LOr)
+ llvm_unreachable("Unimplemented opcode");
+
+ SMTExprRef res = ASTs.front();
+ for (std::size_t i = 1; i < ASTs.size(); ++i)
+ res = (Op == BO_LAnd) ? mkAnd(res, ASTs[i]) : mkOr(res, ASTs[i]);
+ return res;
+ }
+
+ /// Construct an SMTExprRef from a binary operator.
+ SMTExprRef fromBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op,
+ const SMTExprRef &RHS, bool isSigned) {
+ assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!");
+
+ switch (Op) {
+ // Multiplicative operators
+ case BO_Mul:
+ return mkBVMul(LHS, RHS);
+
+ case BO_Div:
+ return isSigned ? mkBVSDiv(LHS, RHS) : mkBVUDiv(LHS, RHS);
+
+ case BO_Rem:
+ return isSigned ? mkBVSRem(LHS, RHS) : mkBVURem(LHS, RHS);
+
+ // Additive operators
+ case BO_Add:
+ return mkBVAdd(LHS, RHS);
+
+ case BO_Sub:
+ return mkBVSub(LHS, RHS);
+
+ // Bitwise shift operators
+ case BO_Shl:
+ return mkBVShl(LHS, RHS);
+
+ case BO_Shr:
+ return isSigned ? mkBVAshr(LHS, RHS) : mkBVLshr(LHS, RHS);
+
+ // Relational operators
+ case BO_LT:
+ return isSigned ? mkBVSlt(LHS, RHS) : mkBVUlt(LHS, RHS);
+
+ case BO_GT:
+ return isSigned ? mkBVSgt(LHS, RHS) : mkBVUgt(LHS, RHS);
+
+ case BO_LE:
+ return isSigned ? mkBVSle(LHS, RHS) : mkBVUle(LHS, RHS);
+
+ case BO_GE:
+ return isSigned ? mkBVSge(LHS, RHS) : mkBVUge(LHS, RHS);
+
+ // Equality operators
+ case BO_EQ:
+ return mkEqual(LHS, RHS);
+
+ case BO_NE:
+ return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned));
+
+ // Bitwise operators
+ case BO_And:
+ return mkBVAnd(LHS, RHS);
+
+ case BO_Xor:
+ return mkBVXor(LHS, RHS);
+
+ case BO_Or:
+ return mkBVOr(LHS, RHS);
+
+ // Logical operators
+ case BO_LAnd:
+ return mkAnd(LHS, RHS);
+
+ case BO_LOr:
+ return mkOr(LHS, RHS);
+
+ default:;
+ }
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a special floating-point binary operator.
+ SMTExprRef fromFloatSpecialBinOp(const SMTExprRef &LHS,
+ const BinaryOperator::Opcode Op,
+ const llvm::APFloat::fltCategory &RHS) {
+ switch (Op) {
+ // Equality operators
+ case BO_EQ:
+ switch (RHS) {
+ case llvm::APFloat::fcInfinity:
+ return mkFPIsInfinite(LHS);
+
+ case llvm::APFloat::fcNaN:
+ return mkFPIsNaN(LHS);
+
+ case llvm::APFloat::fcNormal:
+ return mkFPIsNormal(LHS);
+
+ case llvm::APFloat::fcZero:
+ return mkFPIsZero(LHS);
+ }
+ break;
+
+ case BO_NE:
+ return fromFloatUnOp(UO_LNot, fromFloatSpecialBinOp(LHS, BO_EQ, RHS));
+
+ default:;
+ }
+
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a floating-point binary operator.
+ SMTExprRef fromFloatBinOp(const SMTExprRef &LHS,
+ const BinaryOperator::Opcode Op,
+ const SMTExprRef &RHS) {
+ assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!");
+
+ switch (Op) {
+ // Multiplicative operators
+ case BO_Mul:
+ return mkFPMul(LHS, RHS);
+
+ case BO_Div:
+ return mkFPDiv(LHS, RHS);
+
+ case BO_Rem:
+ return mkFPRem(LHS, RHS);
+
+ // Additive operators
+ case BO_Add:
+ return mkFPAdd(LHS, RHS);
+
+ case BO_Sub:
+ return mkFPSub(LHS, RHS);
+
+ // Relational operators
+ case BO_LT:
+ return mkFPLt(LHS, RHS);
+
+ case BO_GT:
+ return mkFPGt(LHS, RHS);
+
+ case BO_LE:
+ return mkFPLe(LHS, RHS);
+
+ case BO_GE:
+ return mkFPGe(LHS, RHS);
+
+ // Equality operators
+ case BO_EQ:
+ return mkFPEqual(LHS, RHS);
+
+ case BO_NE:
+ return fromFloatUnOp(UO_LNot, fromFloatBinOp(LHS, BO_EQ, RHS));
+
+ // Logical operators
+ case BO_LAnd:
+ case BO_LOr:
+ return fromBinOp(LHS, Op, RHS, false);
+
+ default:;
+ }
+
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and
+ /// their bit widths.
+ SMTExprRef fromCast(const SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth,
+ QualType FromTy, uint64_t FromBitWidth) {
+ if ((FromTy->isIntegralOrEnumerationType() &&
+ ToTy->isIntegralOrEnumerationType()) ||
+ (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) ||
+ (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) ||
+ (FromTy->isReferenceType() ^ ToTy->isReferenceType())) {
+
+ if (FromTy->isBooleanType()) {
+ assert(ToBitWidth > 0 && "BitWidth must be positive!");
+ return mkIte(Exp, mkBitvector(llvm::APSInt("1"), ToBitWidth),
+ mkBitvector(llvm::APSInt("0"), ToBitWidth));
+ }
+
+ if (ToBitWidth > FromBitWidth)
+ return FromTy->isSignedIntegerOrEnumerationType()
+ ? mkBVSignExt(ToBitWidth - FromBitWidth, Exp)
+ : mkBVZeroExt(ToBitWidth - FromBitWidth, Exp);
+
+ if (ToBitWidth < FromBitWidth)
+ return mkBVExtract(ToBitWidth - 1, 0, Exp);
+
+ // Both are bitvectors with the same width, ignore the type cast
+ return Exp;
+ }
+
+ if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) {
+ if (ToBitWidth != FromBitWidth)
+ return mkFPtoFP(Exp, getFloatSort(ToBitWidth));
+
+ return Exp;
+ }
+
+ if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) {
+ SMTSortRef Sort = getFloatSort(ToBitWidth);
+ return FromTy->isSignedIntegerOrEnumerationType() ? mkFPtoSBV(Exp, Sort)
+ : mkFPtoUBV(Exp, Sort);
+ }
+
+ if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType())
+ return ToTy->isSignedIntegerOrEnumerationType()
+ ? mkSBVtoFP(Exp, ToBitWidth)
+ : mkUBVtoFP(Exp, ToBitWidth);
+
+ llvm_unreachable("Unsupported explicit type cast!");
+ }
+
+ // Callback function for doCast parameter on APSInt type.
+ llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy,
+ uint64_t ToWidth, QualType FromTy,
+ uint64_t FromWidth) {
+ APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType());
+ return TargetType.convert(V);
+ }
+
+ // Generate an SMTExprRef that represents the given symbolic expression.
+ // Sets the hasComparison parameter if the expression has a comparison
+ // operator.
+ // Sets the RetTy parameter to the final return type after promotions and
+ // casts.
+ SMTExprRef getExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy = nullptr,
+ bool *hasComparison = nullptr) {
+ if (hasComparison) {
+ *hasComparison = false;
+ }
+
+ return getSymExpr(Ctx, Sym, RetTy, hasComparison);
+ }
+
+ // Generate an SMTExprRef that compares the expression to zero.
+ SMTExprRef getZeroExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty,
+ bool Assumption) {
+
+ if (Ty->isRealFloatingType()) {
+ llvm::APFloat Zero =
+ llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty));
+ return fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, fromAPFloat(Zero));
+ }
+
+ if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() ||
+ Ty->isBlockPointerType() || Ty->isReferenceType()) {
+
+ // Skip explicit comparison for boolean types
+ bool isSigned = Ty->isSignedIntegerOrEnumerationType();
+ if (Ty->isBooleanType())
+ return Assumption ? fromUnOp(UO_LNot, Exp) : Exp;
+
+ return fromBinOp(Exp, Assumption ? BO_EQ : BO_NE,
+ fromInt("0", Ctx.getTypeSize(Ty)), isSigned);
+ }
+
+ llvm_unreachable("Unsupported type for zero value!");
+ }
+
+ // Recursive implementation to unpack and generate symbolic expression.
+ // Sets the hasComparison and RetTy parameters. See getExpr().
+ SMTExprRef getSymExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy,
+ bool *hasComparison) {
+ if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
+ if (RetTy)
+ *RetTy = Sym->getType();
+
+ return fromData(SD->getSymbolID(), Sym->getType(),
+ Ctx.getTypeSize(Sym->getType()));
+ }
+
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
+ if (RetTy)
+ *RetTy = Sym->getType();
+
+ QualType FromTy;
+ SMTExprRef Exp =
+ getSymExpr(Ctx, SC->getOperand(), &FromTy, hasComparison);
+ // Casting an expression with a comparison invalidates it. Note that this
+ // must occur after the recursive call above.
+ // e.g. (signed char) (x > 0)
+ if (hasComparison)
+ *hasComparison = false;
+ return getCastExpr(Ctx, Exp, FromTy, Sym->getType());
+ }
+
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ SMTExprRef Exp = getSymBinExpr(Ctx, BSE, hasComparison, RetTy);
+ // Set the hasComparison parameter, in post-order traversal order.
+ if (hasComparison)
+ *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode());
+ return Exp;
+ }
+
+ llvm_unreachable("Unsupported SymbolRef type!");
+ }
+
+ // Wrapper to generate SMTExprRef from SymbolCast data.
+ SMTExprRef getCastExpr(ASTContext &Ctx, const SMTExprRef &Exp,
+ QualType FromTy, QualType ToTy) {
+ return fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy,
+ Ctx.getTypeSize(FromTy));
+ }
+
+ // Wrapper to generate SMTExprRef from BinarySymExpr.
+ // Sets the hasComparison and RetTy parameters. See getSMTExprRef().
+ SMTExprRef getSymBinExpr(ASTContext &Ctx, const BinarySymExpr *BSE,
+ bool *hasComparison, QualType *RetTy) {
+ QualType LTy, RTy;
+ BinaryOperator::Opcode Op = BSE->getOpcode();
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
+ SMTExprRef LHS = getSymExpr(Ctx, SIE->getLHS(), &LTy, hasComparison);
+ llvm::APSInt NewRInt;
+ std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS());
+ SMTExprRef RHS = fromAPSInt(NewRInt);
+ return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
+ }
+
+ if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
+ llvm::APSInt NewLInt;
+ std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS());
+ SMTExprRef LHS = fromAPSInt(NewLInt);
+ SMTExprRef RHS = getSymExpr(Ctx, ISE->getRHS(), &RTy, hasComparison);
+ return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
+ }
+
+ if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
+ SMTExprRef LHS = getSymExpr(Ctx, SSM->getLHS(), &LTy, hasComparison);
+ SMTExprRef RHS = getSymExpr(Ctx, SSM->getRHS(), &RTy, hasComparison);
+ return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
+ }
+
+ llvm_unreachable("Unsupported BinarySymExpr type!");
+ }
+
+ // Wrapper to generate SMTExprRef from unpacked binary symbolic expression.
+ // Sets the RetTy parameter. See getSMTExprRef().
+ SMTExprRef getBinExpr(ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy,
+ BinaryOperator::Opcode Op, const SMTExprRef &RHS,
+ QualType RTy, QualType *RetTy) {
+ SMTExprRef NewLHS = LHS;
+ SMTExprRef NewRHS = RHS;
+ doTypeConversion(Ctx, NewLHS, NewRHS, LTy, RTy);
+
+ // Update the return type parameter if the output type has changed.
+ if (RetTy) {
+ // A boolean result can be represented as an integer type in C/C++, but at
+ // this point we only care about the SMT sorts. Set it as a boolean type
+ // to avoid subsequent SMT errors.
+ if (BinaryOperator::isComparisonOp(Op) ||
+ BinaryOperator::isLogicalOp(Op)) {
+ *RetTy = Ctx.BoolTy;
+ } else {
+ *RetTy = LTy;
+ }
+
+ // If the two operands are pointers and the operation is a subtraction,
+ // the result is of type ptrdiff_t, which is signed
+ if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) {
+ *RetTy = Ctx.getPointerDiffType();
+ }
+ }
+
+ return LTy->isRealFloatingType()
+ ? fromFloatBinOp(NewLHS, Op, NewRHS)
+ : fromBinOp(NewLHS, Op, NewRHS,
+ LTy->isSignedIntegerOrEnumerationType());
+ }
+
+ // Wrapper to generate SMTExprRef from a range. If From == To, an equality
+ // will be created instead.
+ SMTExprRef getRangeExpr(ASTContext &Ctx, SymbolRef Sym,
+ const llvm::APSInt &From, const llvm::APSInt &To,
+ bool InRange) {
+ // Convert lower bound
+ QualType FromTy;
+ llvm::APSInt NewFromInt;
+ std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From);
+ SMTExprRef FromExp = fromAPSInt(NewFromInt);
+
+ // Convert symbol
+ QualType SymTy;
+ SMTExprRef Exp = getExpr(Ctx, Sym, &SymTy);
+
+ // Construct single (in)equality
+ if (From == To)
+ return getBinExpr(Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp,
+ FromTy, /*RetTy=*/nullptr);
+
+ QualType ToTy;
+ llvm::APSInt NewToInt;
+ std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To);
+ SMTExprRef ToExp = fromAPSInt(NewToInt);
+ assert(FromTy == ToTy && "Range values have different types!");
+
+ // Construct two (in)equalities, and a logical and/or
+ SMTExprRef LHS = getBinExpr(Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT,
+ FromExp, FromTy, /*RetTy=*/nullptr);
+ SMTExprRef RHS =
+ getBinExpr(Ctx, Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy,
+ /*RetTy=*/nullptr);
+
+ return fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS,
+ SymTy->isSignedIntegerOrEnumerationType());
+ }
+
+ // Recover the QualType of an APSInt.
+ // TODO: Refactor to put elsewhere
+ QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int) {
+ return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned());
+ }
+
+ // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1.
+ std::pair<llvm::APSInt, QualType> fixAPSInt(ASTContext &Ctx,
+ const llvm::APSInt &Int) {
+ llvm::APSInt NewInt;
+
+ // FIXME: This should be a cast from a 1-bit integer type to a boolean type,
+ // but the former is not available in Clang. Instead, extend the APSInt
+ // directly.
+ if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) {
+ NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy));
+ } else
+ NewInt = Int;
+
+ return std::make_pair(NewInt, getAPSIntType(Ctx, NewInt));
+ }
+
+ // Perform implicit type conversion on binary symbolic expressions.
+ // May modify all input parameters.
+ // TODO: Refactor to use built-in conversion functions
+ void doTypeConversion(ASTContext &Ctx, SMTExprRef &LHS, SMTExprRef &RHS,
+ QualType &LTy, QualType &RTy) {
+ assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!");
+
+ // Perform type conversion
+ if ((LTy->isIntegralOrEnumerationType() &&
+ RTy->isIntegralOrEnumerationType()) &&
+ (LTy->isArithmeticType() && RTy->isArithmeticType())) {
+ doIntTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy, RHS,
+ RTy);
+ return;
+ }
+
+ if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) {
+ doFloatTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy,
+ RHS, RTy);
+ return;
+ }
+
+ if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) ||
+ (LTy->isBlockPointerType() || RTy->isBlockPointerType()) ||
+ (LTy->isReferenceType() || RTy->isReferenceType())) {
+ // TODO: Refactor to Sema::FindCompositePointerType(), and
+ // Sema::CheckCompareOperands().
+
+ uint64_t LBitWidth = Ctx.getTypeSize(LTy);
+ uint64_t RBitWidth = Ctx.getTypeSize(RTy);
+
+ // Cast the non-pointer type to the pointer type.
+ // TODO: Be more strict about this.
+ if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) ||
+ (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) ||
+ (LTy->isReferenceType() ^ RTy->isReferenceType())) {
+ if (LTy->isNullPtrType() || LTy->isBlockPointerType() ||
+ LTy->isReferenceType()) {
+ LHS = fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ } else {
+ RHS = fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ }
+ }
+
+ // Cast the void pointer type to the non-void pointer type.
+ // For void types, this assumes that the casted value is equal to the
+ // value of the original pointer, and does not account for alignment
+ // requirements.
+ if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) {
+ assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) &&
+ "Pointer types have different bitwidths!");
+ if (RTy->isVoidPointerType())
+ RTy = LTy;
+ else
+ LTy = RTy;
+ }
+
+ if (LTy == RTy)
+ return;
+ }
+
+ // Fallback: for the solver, assume that these types don't really matter
+ if ((LTy.getCanonicalType() == RTy.getCanonicalType()) ||
+ (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) {
+ LTy = RTy;
+ return;
+ }
+
+ // TODO: Refine behavior for invalid type casts
+ }
+
+ // Perform implicit integer type conversion.
+ // May modify all input parameters.
+ // TODO: Refactor to use Sema::handleIntegerConversion()
+ template <typename T, T (SMTSolver::*doCast)(const T &, QualType, uint64_t,
+ QualType, uint64_t)>
+ void doIntTypeConversion(ASTContext &Ctx, T &LHS, QualType &LTy, T &RHS,
+ QualType &RTy) {
+
+ uint64_t LBitWidth = Ctx.getTypeSize(LTy);
+ uint64_t RBitWidth = Ctx.getTypeSize(RTy);
+
+ assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!");
+ // Always perform integer promotion before checking type equality.
+ // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion
+ if (LTy->isPromotableIntegerType()) {
+ QualType NewTy = Ctx.getPromotedIntegerType(LTy);
+ uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
+ LHS = (this->*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth);
+ LTy = NewTy;
+ LBitWidth = NewBitWidth;
+ }
+ if (RTy->isPromotableIntegerType()) {
+ QualType NewTy = Ctx.getPromotedIntegerType(RTy);
+ uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
+ RHS = (this->*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth);
+ RTy = NewTy;
+ RBitWidth = NewBitWidth;
+ }
+
+ if (LTy == RTy)
+ return;
+
+ // Perform integer type conversion
+ // Note: Safe to skip updating bitwidth because this must terminate
+ bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType();
+ bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType();
+
+ int order = Ctx.getIntegerTypeOrder(LTy, RTy);
+ if (isLSignedTy == isRSignedTy) {
+ // Same signedness; use the higher-ranked type
+ if (order == 1) {
+ RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else {
+ LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ }
+ } else if (order != (isLSignedTy ? 1 : -1)) {
+ // The unsigned type has greater than or equal rank to the
+ // signed type, so use the unsigned type
+ if (isRSignedTy) {
+ RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else {
+ LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ }
+ } else if (LBitWidth != RBitWidth) {
+ // The two types are different widths; if we are here, that
+ // means the signed type is larger than the unsigned type, so
+ // use the signed type.
+ if (isLSignedTy) {
+ RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else {
+ LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ }
+ } else {
+ // The signed type is higher-ranked than the unsigned type,
+ // but isn't actually any bigger (like unsigned int and long
+ // on most 32-bit systems). Use the unsigned type corresponding
+ // to the signed type.
+ QualType NewTy =
+ Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy);
+ RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = NewTy;
+ LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = NewTy;
+ }
+ }
+
+ // Perform implicit floating-point type conversion.
+ // May modify all input parameters.
+ // TODO: Refactor to use Sema::handleFloatConversion()
+ template <typename T, T (SMTSolver::*doCast)(const T &, QualType, uint64_t,
+ QualType, uint64_t)>
+ void doFloatTypeConversion(ASTContext &Ctx, T &LHS, QualType &LTy, T &RHS,
+ QualType &RTy) {
+
+ uint64_t LBitWidth = Ctx.getTypeSize(LTy);
+ uint64_t RBitWidth = Ctx.getTypeSize(RTy);
+
+ // Perform float-point type promotion
+ if (!LTy->isRealFloatingType()) {
+ LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ LBitWidth = RBitWidth;
+ }
+ if (!RTy->isRealFloatingType()) {
+ RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ RBitWidth = LBitWidth;
+ }
+
+ if (LTy == RTy)
+ return;
+
+ // If we have two real floating types, convert the smaller operand to the
+ // bigger result
+ // Note: Safe to skip updating bitwidth because this must terminate
+ int order = Ctx.getFloatingTypeOrder(LTy, RTy);
+ if (order > 0) {
+ RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else if (order == 0) {
+ LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ } else {
+ llvm_unreachable("Unsupported floating-point type cast!");
+ }
+ }
+
+ // Returns a boolean sort.
+ virtual SMTSortRef getBoolSort() = 0;
+
+ // Returns an appropriate bitvector sort for the given bitwidth.
+ virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0;
+
+ // Returns a floating-point sort of width 16
+ virtual SMTSortRef getFloat16Sort() = 0;
+
+ // Returns a floating-point sort of width 32
+ virtual SMTSortRef getFloat32Sort() = 0;
+
+ // Returns a floating-point sort of width 64
+ virtual SMTSortRef getFloat64Sort() = 0;
+
+ // Returns a floating-point sort of width 128
+ virtual SMTSortRef getFloat128Sort() = 0;
+
+ // Returns an appropriate sort for the given AST.
+ virtual SMTSortRef getSort(const SMTExprRef &AST) = 0;
+
+ // Returns a new SMTExprRef from an SMTExpr
+ virtual SMTExprRef newExprRef(const SMTExpr &E) const = 0;
+
+ /// Given a constraint, adds it to the solver
+ virtual void addConstraint(const SMTExprRef &Exp) const = 0;
+
+ /// Creates a bitvector addition operation
+ virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector subtraction operation
+ virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector multiplication operation
+ virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed modulus operation
+ virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned modulus operation
+ virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed division operation
+ virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned division operation
+ virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector logical shift left operation
+ virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector arithmetic shift right operation
+ virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector logical shift right operation
+ virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector negation operation
+ virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector not operation
+ virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector xor operation
+ virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector or operation
+ virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector and operation
+ virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned less-than operation
+ virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed less-than operation
+ virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned greater-than operation
+ virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed greater-than operation
+ virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned less-equal-than operation
+ virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed less-equal-than operation
+ virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned greater-equal-than operation
+ virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed greater-equal-than operation
+ virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean not operation
+ virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0;
+
+ /// Creates a boolean equality operation
+ virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean and operation
+ virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean or operation
+ virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean ite operation
+ virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
+ const SMTExprRef &F) = 0;
+
+ /// Creates a bitvector sign extension operation
+ virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector zero extension operation
+ virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector extract operation
+ virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low,
+ const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector concat operation
+ virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point negation operation
+ virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isInfinite operation
+ virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isNaN operation
+ virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isNormal operation
+ virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isZero operation
+ virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point multiplication operation
+ virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point division operation
+ virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point remainder operation
+ virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point addition operation
+ virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point subtraction operation
+ virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point less-than operation
+ virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point greater-than operation
+ virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point less-than-or-equal operation
+ virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point greater-than-or-equal operation
+ virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point equality operation
+ virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to floating-point
+ /// operation
+ virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to signed
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to unsigned
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from signed bitvector to
+ /// floatint-point operation
+ virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0;
+
+ /// Creates a floating-point conversion from unsigned bitvector to
+ /// floatint-point operation
+ virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0;
+
+ /// Creates a new symbol, given a name and a sort
+ virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0;
+
+ // Returns an appropriate floating-point rounding mode.
+ virtual SMTExprRef getFloatRoundingMode() = 0;
+
+ // If the a model is available, returns the value of a given bitvector symbol
+ virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
+ bool isUnsigned) = 0;
+
+ // If the a model is available, returns the value of a given boolean symbol
+ virtual bool getBoolean(const SMTExprRef &Exp) = 0;
+
+ /// Constructs an SMTExprRef from a boolean.
+ virtual SMTExprRef mkBoolean(const bool b) = 0;
+
+ /// Constructs an SMTExprRef from a finite APFloat.
+ virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0;
+
+ /// Constructs an SMTExprRef from an APSInt and its bit width
+ virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0;
+
+ /// Given an expression, extract the value of this operand in the model.
+ virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0;
+
+ /// Given an expression extract the value of this operand in the model.
+ virtual bool getInterpretation(const SMTExprRef &Exp,
+ llvm::APFloat &Float) = 0;
+
+ /// Construct an SMTExprRef value from a boolean.
+ virtual SMTExprRef fromBoolean(const bool Bool) = 0;
+
+ /// Construct an SMTExprRef value from a finite APFloat.
+ virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0;
+
+ /// Construct an SMTExprRef value from an APSInt.
+ virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0;
+
+ /// Construct an SMTExprRef value from an integer.
+ virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0;
+
+ /// Construct an SMTExprRef from a SymbolData.
+ virtual SMTExprRef fromData(const SymbolID ID, const QualType &Ty,
+ uint64_t BitWidth) = 0;
+
+ /// Check if the constraints are satisfiable
+ virtual ConditionTruthVal check() const = 0;
+
+ /// Push the current solver state
+ virtual void push() = 0;
+
+ /// Pop the previous solver state
+ virtual void pop(unsigned NumStates = 1) = 0;
+
+ /// Reset the solver and remove all constraints.
+ virtual void reset() const = 0;
+
+ virtual void print(raw_ostream &OS) const = 0;
+};
+
+/// Shared pointer for SMTSolvers.
+using SMTSolverRef = std::shared_ptr<SMTSolver>;
+
+/// Convenience method to create and Z3Solver object
+std::unique_ptr<SMTSolver> CreateZ3Solver();
+
+} // namespace ento
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h
new file mode 100644
index 000000000000..41ef573f0c71
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h
@@ -0,0 +1,91 @@
+//== SMTSort.h --------------------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a SMT generic Sort API, which will be the base class
+// for every SMT solver sort specific class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H
+
+#include "clang/Basic/TargetInfo.h"
+
+namespace clang {
+namespace ento {
+
+/// Generic base class for SMT sorts
+class SMTSort {
+public:
+ SMTSort() = default;
+ virtual ~SMTSort() = default;
+
+ /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl().
+ virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); }
+
+ /// Returns true if the sort is a floating-point, calls isFloatSortImpl().
+ virtual bool isFloatSort() const { return isFloatSortImpl(); }
+
+ /// Returns true if the sort is a boolean, calls isBooleanSortImpl().
+ virtual bool isBooleanSort() const { return isBooleanSortImpl(); }
+
+ /// Returns the bitvector size, fails if the sort is not a bitvector
+ /// Calls getBitvectorSortSizeImpl().
+ virtual unsigned getBitvectorSortSize() const {
+ assert(isBitvectorSort() && "Not a bitvector sort!");
+ unsigned Size = getBitvectorSortSizeImpl();
+ assert(Size && "Size is zero!");
+ return Size;
+ };
+
+ /// Returns the floating-point size, fails if the sort is not a floating-point
+ /// Calls getFloatSortSizeImpl().
+ virtual unsigned getFloatSortSize() const {
+ assert(isFloatSort() && "Not a floating-point sort!");
+ unsigned Size = getFloatSortSizeImpl();
+ assert(Size && "Size is zero!");
+ return Size;
+ };
+
+ friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) {
+ return LHS.equal_to(RHS);
+ }
+
+ virtual void print(raw_ostream &OS) const = 0;
+
+ LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
+
+protected:
+ /// Query the SMT solver and returns true if two sorts are equal (same kind
+ /// and bit width). This does not check if the two sorts are the same objects.
+ virtual bool equal_to(SMTSort const &other) const = 0;
+
+ /// Query the SMT solver and checks if a sort is bitvector.
+ virtual bool isBitvectorSortImpl() const = 0;
+
+ /// Query the SMT solver and checks if a sort is floating-point.
+ virtual bool isFloatSortImpl() const = 0;
+
+ /// Query the SMT solver and checks if a sort is boolean.
+ virtual bool isBooleanSortImpl() const = 0;
+
+ /// Query the SMT solver and returns the sort bit width.
+ virtual unsigned getBitvectorSortSizeImpl() const = 0;
+
+ /// Query the SMT solver and returns the sort bit width.
+ virtual unsigned getFloatSortSizeImpl() const = 0;
+};
+
+/// Shared pointer for SMTSorts, used by SMTSolver API.
+using SMTSortRef = std::shared_ptr<SMTSort>;
+
+} // namespace ento
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index d58d0a690c88..865014b22830 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -16,24 +16,46 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/Optional.h"
+#include <cstdint>
namespace clang {
+class BlockDecl;
class CXXBoolLiteralExpr;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class DeclaratorDecl;
+class FunctionDecl;
+class LocationContext;
+class StackFrameContext;
+class Stmt;
namespace ento {
+class ConditionTruthVal;
+class ProgramStateManager;
+class StoreRef;
+
class SValBuilder {
virtual void anchor();
+
protected:
ASTContext &Context;
-
+
/// Manager of APSInt values.
BasicValueFactory BasicVals;
@@ -47,7 +69,7 @@ protected:
/// The scalar type to use for array indices.
const QualType ArrayIndexTy;
-
+
/// The width of the scalar type used for array indices.
const unsigned ArrayIndexWidth;
@@ -62,14 +84,12 @@ public:
public:
SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
ProgramStateManager &stateMgr)
- : Context(context), BasicVals(context, alloc),
- SymMgr(context, BasicVals, alloc),
- MemMgr(context, alloc),
- StateMgr(stateMgr),
- ArrayIndexTy(context.LongLongTy),
- ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
+ : Context(context), BasicVals(context, alloc),
+ SymMgr(context, BasicVals, alloc), MemMgr(context, alloc),
+ StateMgr(stateMgr), ArrayIndexTy(context.LongLongTy),
+ ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
- virtual ~SValBuilder() {}
+ virtual ~SValBuilder() = default;
bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
return haveSameType(Sym1->getType(), Sym2->getType());
@@ -117,14 +137,19 @@ public:
/// that represents the same value, but is hopefully easier to work with
/// than the original SVal.
virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0;
-
+
/// Constructs a symbolic expression for two non-location values.
SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs, QualType resultTy);
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
SVal lhs, SVal rhs, QualType type);
-
+
+ /// \return Whether values in \p lhs and \p rhs are equal at \p state.
+ ConditionTruthVal areEqual(ProgramStateRef state, SVal lhs, SVal rhs);
+
+ SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs);
+
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs,
DefinedOrUnknownSVal rhs);
@@ -132,11 +157,11 @@ public:
const ASTContext &getContext() const { return Context; }
ProgramStateManager &getStateManager() { return StateMgr; }
-
+
QualType getConditionType() const {
return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.IntTy;
}
-
+
QualType getArrayIndexType() const {
return ArrayIndexTy;
}
@@ -173,7 +198,7 @@ public:
/// Make a unique symbol for value of region.
DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region);
- /// \brief Create a new symbol with a unique 'name'.
+ /// Create a new symbol with a unique 'name'.
///
/// We resort to conjured symbols when we cannot construct a derived symbol.
/// The advantage of symbols derived/built from other symbols is that we
@@ -188,12 +213,12 @@ public:
const LocationContext *LCtx,
QualType type,
unsigned count);
-
DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
const LocationContext *LCtx,
QualType type,
unsigned visitCount);
- /// \brief Conjure a symbol representing heap allocated memory region.
+
+ /// Conjure a symbol representing heap allocated memory region.
///
/// Note, the expression should represent a location.
DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E,
@@ -212,7 +237,7 @@ public:
DefinedSVal getMemberPointer(const DeclaratorDecl *DD);
DefinedSVal getFunctionPointer(const FunctionDecl *func);
-
+
DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
const LocationContext *locContext,
unsigned blockCount);
@@ -227,7 +252,7 @@ public:
return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));
}
- NonLoc makeLazyCompoundVal(const StoreRef &store,
+ NonLoc makeLazyCompoundVal(const StoreRef &store,
const TypedValueRegion *region) {
return nonloc::LazyCompoundVal(
BasicVals.getLazyCompoundValData(store, region));
@@ -304,7 +329,7 @@ public:
NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType type);
- /// \brief Create a NonLoc value for cast.
+ /// Create a NonLoc value for cast.
NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy);
nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
@@ -342,6 +367,15 @@ public:
return loc::ConcreteInt(BasicVals.getValue(integer));
}
+ /// Make an SVal that represents the given symbol. This follows the convention
+ /// of representing Loc-type symbols (symbolic pointers and references)
+ /// as Loc values wrapping the symbol rather than as plain symbol values.
+ SVal makeSymbolVal(SymbolRef Sym) {
+ if (Loc::isLocType(Sym->getType()))
+ return makeLoc(Sym);
+ return nonloc::SymbolVal(Sym);
+ }
+
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D,
const StackFrameContext *SFC);
@@ -355,8 +389,8 @@ SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
ASTContext &context,
ProgramStateManager &stateMgr);
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
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 06132587b4aa..1b79bfc3f8cf 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
@@ -1,4 +1,4 @@
-//== SVals.h - Abstract Values for Static Analysis ---------*- C++ -*--==//
+//===- SVals.h - Abstract Values for Static Analysis ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,11 +16,18 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
//==------------------------------------------------------------------------==//
// Base SVal types.
@@ -28,34 +35,40 @@
namespace clang {
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+class FunctionDecl;
+class LabelDecl;
+
namespace ento {
+class BasicValueFactory;
class CompoundValData;
class LazyCompoundValData;
-class PointerToMemberData;
-class ProgramState;
-class BasicValueFactory;
class MemRegion;
-class TypedValueRegion;
-class MemRegionManager;
-class ProgramStateManager;
+class PointerToMemberData;
class SValBuilder;
+class TypedValueRegion;
namespace nonloc {
+
/// Sub-kinds for NonLoc values.
enum Kind {
#define NONLOC_SVAL(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
};
-}
+
+} // namespace nonloc
namespace loc {
+
/// Sub-kinds for Loc values.
enum Kind {
#define LOC_SVAL(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
};
-}
+
+} // namespace loc
/// SVal - This represents a symbolic expression, which can be either
/// an L-value or an R-value.
@@ -71,22 +84,21 @@ public:
enum { BaseBits = 2, BaseMask = 0x3 };
protected:
- const void *Data;
+ const void *Data = nullptr;
/// The lowest 2 bits are a BaseKind (0 -- 3).
/// The higher bits are an unsigned "kind" value.
- unsigned Kind;
+ unsigned Kind = 0;
explicit SVal(const void *d, bool isLoc, unsigned ValKind)
- : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
+ : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
- explicit SVal(BaseKind k, const void *D = nullptr)
- : Data(D), Kind(k) {}
+ explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {}
public:
- explicit SVal() : Data(nullptr), Kind(0) {}
+ explicit SVal() = default;
- /// \brief Convert to the specified SVal type, asserting that this SVal is of
+ /// Convert to the specified SVal type, asserting that this SVal is of
/// the desired type.
template<typename T>
T castAs() const {
@@ -94,7 +106,7 @@ public:
return *static_cast<const T *>(this);
}
- /// \brief Convert to the specified SVal type, returning None if this SVal is
+ /// Convert to the specified SVal type, returning None if this SVal is
/// not of the desired type.
template<typename T>
Optional<T> getAs() const {
@@ -103,38 +115,38 @@ public:
return *static_cast<const T *>(this);
}
- inline unsigned getRawKind() const { return Kind; }
- inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
- inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
+ unsigned getRawKind() const { return Kind; }
+ BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
+ unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
// This method is required for using SVal in a FoldingSetNode. It
// extracts a unique signature for this SVal object.
- inline void Profile(llvm::FoldingSetNodeID& ID) const {
+ void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger((unsigned) getRawKind());
ID.AddPointer(Data);
}
- inline bool operator==(const SVal& R) const {
+ bool operator==(const SVal &R) const {
return getRawKind() == R.getRawKind() && Data == R.Data;
}
- inline bool operator!=(const SVal& R) const {
+ bool operator!=(const SVal &R) const {
return !(*this == R);
}
- inline bool isUnknown() const {
+ bool isUnknown() const {
return getRawKind() == UnknownValKind;
}
- inline bool isUndef() const {
+ bool isUndef() const {
return getRawKind() == UndefinedValKind;
}
- inline bool isUnknownOrUndef() const {
+ bool isUnknownOrUndef() const {
return getRawKind() <= UnknownValKind;
}
- inline bool isValid() const {
+ bool isValid() const {
return getRawKind() > UnknownValKind;
}
@@ -152,7 +164,7 @@ public:
/// Otherwise return 0.
const FunctionDecl *getAsFunctionDecl() const;
- /// \brief If this SVal is a location and wraps a symbol, return that
+ /// If this SVal is a location and wraps a symbol, return that
/// SymbolRef. Otherwise return 0.
///
/// Casts are ignored during lookup.
@@ -163,7 +175,7 @@ public:
/// Get the symbol in the SVal or its base region.
SymbolRef getLocSymbolInBase() const;
- /// \brief If this SVal wraps a symbol return that SymbolRef.
+ /// If this SVal wraps a symbol return that SymbolRef.
/// Otherwise, return 0.
///
/// Casts are ignored during lookup.
@@ -175,7 +187,7 @@ public:
/// return that expression. Otherwise return NULL.
const SymExpr *getAsSymbolicExpression() const;
- const SymExpr* getAsSymExpr() const;
+ const SymExpr *getAsSymExpr() const;
const MemRegion *getAsRegion() const;
@@ -183,14 +195,14 @@ public:
void dump() const;
SymExpr::symbol_iterator symbol_begin() const {
- const SymExpr *SE = getAsSymbolicExpression();
+ const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true);
if (SE)
return SE->symbol_begin();
else
return SymExpr::symbol_iterator();
}
- SymExpr::symbol_iterator symbol_end() const {
+ SymExpr::symbol_iterator symbol_end() const {
return SymExpr::symbol_end();
}
};
@@ -206,70 +218,76 @@ public:
private:
friend class SVal;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == UndefinedValKind;
}
};
class DefinedOrUnknownSVal : public SVal {
-private:
+public:
// We want calling these methods to be a compiler error since they are
// tautologically false.
bool isUndef() const = delete;
bool isValid() const = delete;
-
+
protected:
- DefinedOrUnknownSVal() {}
+ DefinedOrUnknownSVal() = default;
explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
- : SVal(d, isLoc, ValKind) {}
-
- explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
- : SVal(k, D) {}
-
+ : SVal(d, isLoc, ValKind) {}
+ explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {}
+
private:
friend class SVal;
+
static bool isKind(const SVal& V) {
return !V.isUndef();
}
};
-
+
class UnknownVal : public DefinedOrUnknownSVal {
public:
explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
-
+
private:
friend class SVal;
+
static bool isKind(const SVal &V) {
return V.getBaseKind() == UnknownValKind;
}
};
class DefinedSVal : public DefinedOrUnknownSVal {
-private:
+public:
// We want calling these methods to be a compiler error since they are
// tautologically true/false.
bool isUnknown() const = delete;
bool isUnknownOrUndef() const = delete;
bool isValid() const = delete;
+
protected:
- DefinedSVal() {}
+ DefinedSVal() = default;
explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
- : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
+ : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
+
private:
friend class SVal;
+
static bool isKind(const SVal& V) {
return !V.isUnknownOrUndef();
}
};
-
-/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
+/// Represents an SVal that is guaranteed to not be UnknownVal.
class KnownSVal : public SVal {
- KnownSVal() {}
friend class SVal;
+
+ KnownSVal() = default;
+
static bool isKind(const SVal &V) {
return !V.isUnknown();
}
+
public:
KnownSVal(const DefinedSVal &V) : SVal(V) {}
KnownSVal(const UndefinedVal &V) : SVal(V) {}
@@ -277,20 +295,21 @@ public:
class NonLoc : public DefinedSVal {
protected:
- NonLoc() {}
+ NonLoc() = default;
explicit NonLoc(unsigned SubKind, const void *d)
- : DefinedSVal(d, false, SubKind) {}
+ : DefinedSVal(d, false, SubKind) {}
public:
void dumpToStream(raw_ostream &Out) const;
- static inline bool isCompoundType(QualType T) {
+ static bool isCompoundType(QualType T) {
return T->isArrayType() || T->isRecordType() ||
T->isComplexType() || T->isVectorType();
}
private:
friend class SVal;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind;
}
@@ -298,20 +317,21 @@ private:
class Loc : public DefinedSVal {
protected:
- Loc() {}
+ Loc() = default;
explicit Loc(unsigned SubKind, const void *D)
- : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
+ : DefinedSVal(const_cast<void *>(D), true, SubKind) {}
public:
void dumpToStream(raw_ostream &Out) const;
- static inline bool isLocType(QualType T) {
- return T->isAnyPointerType() || T->isBlockPointerType() ||
+ static bool isLocType(QualType T) {
+ return T->isAnyPointerType() || T->isBlockPointerType() ||
T->isReferenceType() || T->isNullPtrType();
}
private:
friend class SVal;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == LocKind;
}
@@ -323,14 +343,17 @@ private:
namespace nonloc {
-/// \brief Represents symbolic expression.
+/// Represents symbolic expression that isn't a location.
class SymbolVal : public NonLoc {
public:
SymbolVal() = delete;
- SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); }
+ SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {
+ assert(sym);
+ assert(!Loc::isLocType(sym->getType()));
+ }
SymbolRef getSymbol() const {
- return (const SymExpr*) Data;
+ return (const SymExpr *) Data;
}
bool isExpression() const {
@@ -339,6 +362,7 @@ public:
private:
friend class SVal;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind &&
V.getSubKind() == SymbolValKind;
@@ -349,13 +373,13 @@ private:
}
};
-/// \brief Value representing integer constant.
+/// Value representing integer constant.
class ConcreteInt : public NonLoc {
public:
explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
- return *static_cast<const llvm::APSInt*>(Data);
+ return *static_cast<const llvm::APSInt *>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
@@ -368,7 +392,9 @@ public:
private:
friend class SVal;
- ConcreteInt() {}
+
+ ConcreteInt() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind &&
V.getSubKind() == ConcreteIntKind;
@@ -392,7 +418,6 @@ class LocAsInteger : public NonLoc {
}
public:
-
Loc getLoc() const {
const std::pair<SVal, uintptr_t> *D =
static_cast<const std::pair<SVal, uintptr_t> *>(Data);
@@ -414,7 +439,9 @@ public:
private:
friend class SVal;
- LocAsInteger() {}
+
+ LocAsInteger() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind &&
V.getSubKind() == LocAsIntegerKind;
@@ -432,16 +459,19 @@ class CompoundVal : public NonLoc {
public:
const CompoundValData* getValue() const {
- return static_cast<const CompoundValData*>(Data);
+ return static_cast<const CompoundValData *>(Data);
}
- typedef llvm::ImmutableList<SVal>::iterator iterator;
+ using iterator = llvm::ImmutableList<SVal>::iterator;
+
iterator begin() const;
iterator end() const;
private:
friend class SVal;
- CompoundVal() {}
+
+ CompoundVal() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
}
@@ -455,30 +485,35 @@ class LazyCompoundVal : public NonLoc {
friend class ento::SValBuilder;
explicit LazyCompoundVal(const LazyCompoundValData *D)
- : NonLoc(LazyCompoundValKind, D) {}
+ : NonLoc(LazyCompoundValKind, D) {}
+
public:
const LazyCompoundValData *getCVData() const {
- return static_cast<const LazyCompoundValData*>(Data);
+ return static_cast<const LazyCompoundValData *>(Data);
}
+
const void *getStore() const;
const TypedValueRegion *getRegion() const;
private:
friend class SVal;
- LazyCompoundVal() {}
+
+ LazyCompoundVal() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind &&
V.getSubKind() == LazyCompoundValKind;
}
+
static bool isKind(const NonLoc& V) {
return V.getSubKind() == LazyCompoundValKind;
}
};
-/// \brief Value representing pointer-to-member.
+/// Value representing pointer-to-member.
///
/// This value is qualified as NonLoc because neither loading nor storing
-/// operations are aplied to it. Instead, the analyzer uses the L-value coming
+/// operations are applied to it. Instead, the analyzer uses the L-value coming
/// from pointer-to-member applied to an object.
/// This SVal is represented by a DeclaratorDecl which can be a member function
/// pointer or a member data pointer and a list of CXXBaseSpecifiers. This list
@@ -488,28 +523,36 @@ class PointerToMember : public NonLoc {
friend class ento::SValBuilder;
public:
- typedef llvm::PointerUnion<const DeclaratorDecl *,
- const PointerToMemberData *> PTMDataType;
+ using PTMDataType =
+ llvm::PointerUnion<const DeclaratorDecl *, const PointerToMemberData *>;
+
const PTMDataType getPTMData() const {
return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data));
}
+
bool isNullMemberPointer() const {
return getPTMData().isNull();
}
+
const DeclaratorDecl *getDecl() const;
+
template<typename AdjustedDecl>
- const AdjustedDecl* getDeclAs() const {
+ const AdjustedDecl *getDeclAs() const {
return dyn_cast_or_null<AdjustedDecl>(getDecl());
}
- typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator;
+
+ using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;
+
iterator begin() const;
iterator end() const;
private:
- explicit PointerToMember(const PTMDataType D)
- : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}
friend class SVal;
- PointerToMember() {}
+
+ PointerToMember() = default;
+ explicit PointerToMember(const PTMDataType D)
+ : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind &&
V.getSubKind() == PointerToMemberKind;
@@ -520,7 +563,7 @@ private:
}
};
-} // end namespace ento::nonloc
+} // namespace nonloc
//==------------------------------------------------------------------------==//
// Subclasses of Loc.
@@ -535,12 +578,14 @@ public:
}
const LabelDecl *getLabel() const {
- return static_cast<const LabelDecl*>(Data);
+ return static_cast<const LabelDecl *>(Data);
}
private:
friend class SVal;
- GotoLabel() {}
+
+ GotoLabel() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
}
@@ -550,19 +595,18 @@ private:
}
};
-
class MemRegionVal : public Loc {
public:
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
assert(r);
}
- /// \brief Get the underlining region.
- const MemRegion* getRegion() const {
- return static_cast<const MemRegion*>(Data);
+ /// Get the underlining region.
+ const MemRegion *getRegion() const {
+ return static_cast<const MemRegion *>(Data);
}
- /// \brief Get the underlining region and strip casts.
+ /// Get the underlining region and strip casts.
const MemRegion* stripCasts(bool StripBaseCasts = true) const;
template <typename REGION>
@@ -570,17 +614,19 @@ public:
return dyn_cast<REGION>(getRegion());
}
- inline bool operator==(const MemRegionVal& R) const {
+ bool operator==(const MemRegionVal &R) const {
return getRegion() == R.getRegion();
}
- inline bool operator!=(const MemRegionVal& R) const {
+ bool operator!=(const MemRegionVal &R) const {
return getRegion() != R.getRegion();
}
private:
friend class SVal;
- MemRegionVal() {}
+
+ MemRegionVal() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == LocKind &&
V.getSubKind() == MemRegionValKind;
@@ -595,8 +641,8 @@ class ConcreteInt : public Loc {
public:
explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
- const llvm::APSInt& getValue() const {
- return *static_cast<const llvm::APSInt*>(Data);
+ const llvm::APSInt &getValue() const {
+ return *static_cast<const llvm::APSInt *>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
@@ -605,7 +651,9 @@ public:
private:
friend class SVal;
- ConcreteInt() {}
+
+ ConcreteInt() = default;
+
static bool isKind(const SVal& V) {
return V.getBaseKind() == LocKind &&
V.getSubKind() == ConcreteIntKind;
@@ -616,11 +664,11 @@ private:
}
};
-} // end ento::loc namespace
+} // namespace loc
-} // end ento namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
namespace llvm {
@@ -629,6 +677,6 @@ template <> struct isPodLike<clang::ento::SVal> {
static const bool value = true;
};
-} // end llvm namespace
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
index 2c9802bbc536..d64b90e2d380 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
@@ -75,6 +75,7 @@ protected:
// Internal implementation.
//===------------------------------------------------------------------===//
+ SValBuilder &getSValBuilder() const { return SVB; }
BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); }
SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); }
@@ -85,8 +86,8 @@ private:
bool Assumption);
};
-} // end GR namespace
+} // end namespace ento
-} // end clang namespace
+} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 25d20a17afaa..fc072a380074 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
@@ -1,4 +1,4 @@
-//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==//
+//===- Store.h - Interface for maps from Locations to Values ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,27 +14,42 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
+#include "clang/AST/Type.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
namespace clang {
-class Stmt;
+class ASTContext;
+class CastExpr;
+class CompoundLiteralExpr;
+class CXXBasePath;
+class Decl;
class Expr;
+class LocationContext;
class ObjCIvarDecl;
-class CXXBasePath;
class StackFrameContext;
namespace ento {
class CallEvent;
-class ProgramState;
class ProgramStateManager;
class ScanReachableSymbols;
+class SymbolReaper;
-typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
+using InvalidatedSymbols = llvm::DenseSet<SymbolRef>;
class StoreManager {
protected:
@@ -48,7 +63,7 @@ protected:
StoreManager(ProgramStateManager &stateMgr);
public:
- virtual ~StoreManager() {}
+ virtual ~StoreManager() = default;
/// Return the value bound to specified location in a given state.
/// \param[in] store The store in which to make the lookup.
@@ -92,9 +107,17 @@ public:
/// by \c val bound to the location given for \c loc.
virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
- virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V);
+ /// Return a store with the specified value bound to all sub-regions of the
+ /// region. The region must not have previous bindings. If you need to
+ /// invalidate existing bindings, consider invalidateRegions().
+ virtual StoreRef BindDefaultInitial(Store store, const MemRegion *R,
+ SVal V) = 0;
+
+ /// Return a store with in which all values within the given region are
+ /// reset to zero. This method is allowed to overwrite previous bindings.
+ virtual StoreRef BindDefaultZero(Store store, const MemRegion *R) = 0;
- /// \brief Create a new store with the specified binding removed.
+ /// Create a new store with the specified binding removed.
/// \param ST the original store, that is the basis for the new store.
/// \param L the location whose binding should be removed.
virtual StoreRef killBinding(Store ST, Loc L) = 0;
@@ -126,7 +149,7 @@ public:
// FIXME: This should soon be eliminated altogether; clients should deal with
// region extents directly.
- virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
+ virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
const MemRegion *region,
QualType EleTy) {
return UnknownVal();
@@ -147,14 +170,14 @@ public:
SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
bool IsVirtual);
- /// \brief Attempts to do a down cast. Used to model BaseToDerived and C++
+ /// Attempts to do a down cast. Used to model BaseToDerived and C++
/// dynamic_cast.
/// The callback may result in the following 3 scenarios:
/// - Successful cast (ex: derived is subclass of base).
/// - Failed cast (ex: derived is definitely not a subclass of base).
/// The distinction of this case from the next one is necessary to model
- /// dynamic_cast.
- /// - We don't know (base is a symbolic region and we don't have
+ /// dynamic_cast.
+ /// - We don't know (base is a symbolic region and we don't have
/// enough info to determine if the cast will succeed at run time).
/// The function returns an SVal representing the derived class; it's
/// valid only if Failed flag is set to false.
@@ -168,11 +191,11 @@ public:
const MemRegion *castRegion(const MemRegion *region, QualType CastToTy);
virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
- SymbolReaper& SymReaper) = 0;
+ SymbolReaper &SymReaper) = 0;
virtual bool includedInBindings(Store store,
const MemRegion *region) const = 0;
-
+
/// If the StoreManager supports it, increment the reference count of
/// the specified Store object.
virtual void incrementReferenceCount(Store store) {}
@@ -182,7 +205,7 @@ public:
/// associated with the object is recycled.
virtual void decrementReferenceCount(Store store) {}
- typedef SmallVector<const MemRegion *, 8> InvalidatedRegions;
+ using InvalidatedRegions = SmallVector<const MemRegion *, 8>;
/// invalidateRegions - Clears out the specified regions from the store,
/// marking their values as unknown. Depending on the store, this may also
@@ -198,7 +221,7 @@ public:
/// globals should get invalidated.
/// \param[in,out] IS A set to fill with any symbols that are no longer
/// accessible. Pass \c NULL if this information will not be used.
- /// \param[in] ITraits Information about invalidation for a particular
+ /// \param[in] ITraits Information about invalidation for a particular
/// region/symbol.
/// \param[in,out] InvalidatedTopLevel A vector to fill with regions
//// explicitly being invalidated. Pass \c NULL if this
@@ -235,6 +258,7 @@ public:
class BindingsHandler {
public:
virtual ~BindingsHandler();
+
virtual bool HandleBinding(StoreManager& SMgr, Store store,
const MemRegion *region, SVal val) = 0;
};
@@ -242,16 +266,16 @@ public:
class FindUniqueBinding :
public BindingsHandler {
SymbolRef Sym;
- const MemRegion* Binding;
- bool First;
+ const MemRegion* Binding = nullptr;
+ bool First = true;
public:
- FindUniqueBinding(SymbolRef sym)
- : Sym(sym), Binding(nullptr), First(true) {}
+ FindUniqueBinding(SymbolRef sym) : Sym(sym) {}
+
+ explicit operator bool() { return First && Binding; }
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal val) override;
- explicit operator bool() { return First && Binding; }
const MemRegion *getRegion() { return Binding; }
};
@@ -266,32 +290,31 @@ protected:
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
- SVal CastRetrievedVal(SVal val, const TypedValueRegion *region,
- QualType castTy, bool performTestOnly = true);
+ SVal CastRetrievedVal(SVal val, const TypedValueRegion *region,
+ QualType castTy);
private:
SVal getLValueFieldOrIvar(const Decl *decl, SVal base);
};
-
inline StoreRef::StoreRef(Store store, StoreManager & smgr)
- : store(store), mgr(smgr) {
+ : store(store), mgr(smgr) {
if (store)
mgr.incrementReferenceCount(store);
}
-inline StoreRef::StoreRef(const StoreRef &sr)
- : store(sr.store), mgr(sr.mgr)
-{
+inline StoreRef::StoreRef(const StoreRef &sr)
+ : store(sr.store), mgr(sr.mgr)
+{
if (store)
mgr.incrementReferenceCount(store);
}
-
+
inline StoreRef::~StoreRef() {
if (store)
mgr.decrementReferenceCount(store);
}
-
+
inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
assert(&newStore.mgr == &mgr);
if (store != newStore.store) {
@@ -308,8 +331,8 @@ CreateRegionStoreManager(ProgramStateManager &StMgr);
std::unique_ptr<StoreManager>
CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr);
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
index 958c8c377ea2..22259a239cf6 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
@@ -1,4 +1,4 @@
-//== StoreRef.h - Smart pointer for store objects ---------------*- C++ -*--==//
+//===- StoreRef.h - Smart pointer for store objects -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,34 +18,37 @@
namespace clang {
namespace ento {
-
+
+class StoreManager;
+
/// Store - This opaque type encapsulates an immutable mapping from
/// locations to values. At a high-level, it represents the symbolic
/// memory model. Different subclasses of StoreManager may choose
/// different types to represent the locations and values.
-typedef const void *Store;
-
-class StoreManager;
-
+using Store = const void *;
+
class StoreRef {
Store store;
StoreManager &mgr;
+
public:
- StoreRef(Store, StoreManager &);
- StoreRef(const StoreRef &);
- StoreRef &operator=(StoreRef const &);
-
+ StoreRef(Store store, StoreManager &smgr);
+ StoreRef(const StoreRef &sr);
+ StoreRef &operator=(StoreRef const &newStore);
+ ~StoreRef();
+
bool operator==(const StoreRef &x) const {
assert(&mgr == &x.mgr);
return x.store == store;
}
+
bool operator!=(const StoreRef &x) const { return !operator==(x); }
-
- ~StoreRef();
-
+
Store getStore() const { return store; }
const StoreManager &getStoreManager() const { return mgr; }
};
-}}
-#endif
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index 8ccd34751bbe..d6aa4feddff2 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -24,8 +24,12 @@ class CFGElement;
class LocationContext;
class Stmt;
+namespace cross_tu {
+class CrossTranslationUnitContext;
+}
+
namespace ento {
-
+
struct NodeBuilderContext;
class AnalysisManager;
class ExplodedNodeSet;
@@ -49,6 +53,9 @@ public:
virtual AnalysisManager &getAnalysisManager() = 0;
+ virtual cross_tu::CrossTranslationUnitContext *
+ getCrossTranslationUnitContext() = 0;
+
virtual ProgramStateManager &getStateManager() = 0;
/// Called by CoreEngine. Used to generate new successor
@@ -126,7 +133,7 @@ public:
/// processRegionChanges - Called by ProgramStateManager whenever a change is
/// made to the store. Used to update checkers that track region values.
- virtual ProgramStateRef
+ virtual ProgramStateRef
processRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
@@ -135,7 +142,7 @@ public:
const CallEvent *Call) = 0;
- inline ProgramStateRef
+ inline ProgramStateRef
processRegionChange(ProgramStateRef state,
const MemRegion* MR,
const LocationContext *LCtx) {
@@ -155,7 +162,8 @@ public:
/// printState - Called by ProgramStateManager to print checker-specific data.
virtual void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) = 0;
+ const char *NL, const char *Sep,
+ const LocationContext *LCtx = nullptr) = 0;
/// Called by CoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
index 52d78b6a3c82..0a75eeb3ea53 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
@@ -21,9 +21,9 @@ namespace ento {
namespace summMgr {
-
+
/* Key kinds:
-
+
- C functions
- C++ functions (name + parameter types)
- ObjC methods:
@@ -34,21 +34,21 @@ namespace summMgr {
- C++ methods
- Class, function name + parameter types + const
*/
-
+
class SummaryKey {
-
+
};
} // end namespace clang::summMgr
-
+
class SummaryManagerImpl {
-
+
};
-
+
template <typename T>
class SummaryManager : SummaryManagerImpl {
-
+
};
} // end GR namespace
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 9780d0144746..69b9858d3feb 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
@@ -1,4 +1,4 @@
-//== SymExpr.h - Management of Symbolic Values ------------------*- C++ -*--==//
+//===- SymExpr.h - Management of Symbolic Values ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,17 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMEXPR_H
#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/raw_ostream.h"
+#include <cassert>
namespace clang {
namespace ento {
class MemRegion;
-/// \brief Symbolic value. These values used to capture symbolic execution of
+/// Symbolic value. These values used to capture symbolic execution of
/// the program.
class SymExpr : public llvm::FoldingSetNode {
virtual void anchor();
@@ -48,8 +49,10 @@ protected:
return !T.isNull() && !T->isVoidType();
}
+ mutable unsigned Complexity = 0;
+
public:
- virtual ~SymExpr() {}
+ virtual ~SymExpr() = default;
Kind getKind() const { return K; }
@@ -60,17 +63,18 @@ public:
virtual QualType getType() const = 0;
virtual void Profile(llvm::FoldingSetNodeID &profile) = 0;
- /// \brief Iterator over symbols that the current symbol depends on.
+ /// Iterator over symbols that the current symbol depends on.
///
/// For SymbolData, it's the symbol itself; for expressions, it's the
/// expression symbol and all the operands in it. Note, SymbolDerived is
/// treated as SymbolData - the iterator will NOT visit the parent region.
class symbol_iterator {
SmallVector<const SymExpr *, 5> itr;
+
void expand();
public:
- symbol_iterator() {}
+ symbol_iterator() = default;
symbol_iterator(const SymExpr *SE);
symbol_iterator &operator++();
@@ -83,9 +87,9 @@ public:
symbol_iterator symbol_begin() const { return symbol_iterator(this); }
static symbol_iterator symbol_end() { return symbol_iterator(); }
- unsigned computeComplexity() const;
+ virtual unsigned computeComplexity() const = 0;
- /// \brief Find the region from which this symbol originates.
+ /// Find the region from which this symbol originates.
///
/// Whenever the symbol was constructed to denote an unknown value of
/// a certain memory region, return this region. This method
@@ -104,26 +108,31 @@ inline raw_ostream &operator<<(raw_ostream &os,
return os;
}
-typedef const SymExpr *SymbolRef;
-typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
+using SymbolRef = const SymExpr *;
+using SymbolRefSmallVectorTy = SmallVector<SymbolRef, 2>;
+using SymbolID = unsigned;
-typedef unsigned SymbolID;
-/// \brief A symbol representing data which can be stored in a memory location
+/// A symbol representing data which can be stored in a memory location
/// (region).
class SymbolData : public SymExpr {
- void anchor() override;
const SymbolID Sym;
+ void anchor() override;
+
protected:
SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {
assert(classof(this));
}
public:
- ~SymbolData() override {}
+ ~SymbolData() override = default;
SymbolID getSymbolID() const { return Sym; }
+ unsigned computeComplexity() const override {
+ return 1;
+ };
+
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
Kind k = SE->getKind();
@@ -134,4 +143,4 @@ public:
} // namespace ento
} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMEXPR_H
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 7d2e5ad8ba91..074551962607 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
@@ -1,4 +1,4 @@
-//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
+//===- SymbolManager.h - Management of Symbolic Values ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,8 +15,8 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
-#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
@@ -26,19 +26,19 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
+#include <cassert>
namespace clang {
- class ASTContext;
- class StackFrameContext;
+
+class ASTContext;
+class Stmt;
namespace ento {
- class BasicValueFactory;
- class SubRegion;
- class TypedValueRegion;
- class VarRegion;
-///\brief A symbol representing the value stored at a MemRegion.
+class BasicValueFactory;
+class StoreManager;
+
+///A symbol representing the value stored at a MemRegion.
class SymbolRegionValue : public SymbolData {
const TypedValueRegion *R;
@@ -66,7 +66,7 @@ public:
QualType getType() const override;
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymbolRegionValueKind;
}
};
@@ -118,7 +118,7 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymbolConjuredKind;
}
};
@@ -157,7 +157,7 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymbolDerivedKind;
}
};
@@ -167,7 +167,7 @@ public:
/// SubRegion::getExtent instead -- the value returned may not be a symbol.
class SymbolExtent : public SymbolData {
const SubRegion *R;
-
+
public:
SymbolExtent(SymbolID sym, const SubRegion *r)
: SymbolData(SymbolExtentKind, sym), R(r) {
@@ -190,7 +190,7 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymbolExtentKind;
}
};
@@ -206,11 +206,12 @@ class SymbolMetadata : public SymbolData {
const LocationContext *LCtx;
unsigned Count;
const void *Tag;
+
public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
const LocationContext *LCtx, unsigned count, const void *tag)
- : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
- Count(count), Tag(tag) {
+ : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
+ Count(count), Tag(tag) {
assert(r);
assert(s);
assert(isValidTypeForSymbol(t));
@@ -245,16 +246,18 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymbolMetadataKind;
}
};
-/// \brief Represents a cast expression.
+/// Represents a cast expression.
class SymbolCast : public SymExpr {
const SymExpr *Operand;
+
/// Type of the operand.
QualType FromTy;
+
/// The type of the result.
QualType ToTy;
@@ -267,6 +270,12 @@ public:
// Otherwise, 'To' should also be a valid type.
}
+ unsigned computeComplexity() const override {
+ if (Complexity == 0)
+ Complexity = 1 + Operand->computeComplexity();
+ return Complexity;
+ }
+
QualType getType() const override { return ToTy; }
const SymExpr *getOperand() const { return Operand; }
@@ -286,12 +295,12 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymbolCastKind;
}
};
-/// \brief Represents a symbolic expression involving a binary operator
+/// Represents a symbolic expression involving a binary operator
class BinarySymExpr : public SymExpr {
BinaryOperator::Opcode Op;
QualType T;
@@ -311,13 +320,13 @@ public:
BinaryOperator::Opcode getOpcode() const { return Op; }
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
Kind k = SE->getKind();
return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
}
};
-/// \brief Represents a symbolic expression like 'x' + 3.
+/// Represents a symbolic expression like 'x' + 3.
class SymIntExpr : public BinarySymExpr {
const SymExpr *LHS;
const llvm::APSInt& RHS;
@@ -334,6 +343,12 @@ public:
const SymExpr *getLHS() const { return LHS; }
const llvm::APSInt &getRHS() const { return RHS; }
+ unsigned computeComplexity() const override {
+ if (Complexity == 0)
+ Complexity = 1 + LHS->computeComplexity();
+ return Complexity;
+ }
+
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const llvm::APSInt& rhs,
QualType t) {
@@ -349,12 +364,12 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymIntExprKind;
}
};
-/// \brief Represents a symbolic expression like 3 - 'x'.
+/// Represents a symbolic expression like 3 - 'x'.
class IntSymExpr : public BinarySymExpr {
const llvm::APSInt& LHS;
const SymExpr *RHS;
@@ -371,6 +386,12 @@ public:
const SymExpr *getRHS() const { return RHS; }
const llvm::APSInt &getLHS() const { return LHS; }
+ unsigned computeComplexity() const override {
+ if (Complexity == 0)
+ Complexity = 1 + RHS->computeComplexity();
+ return Complexity;
+ }
+
static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t) {
@@ -386,12 +407,12 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == IntSymExprKind;
}
};
-/// \brief Represents a symbolic expression like 'x' + 'y'.
+/// Represents a symbolic expression like 'x' + 'y'.
class SymSymExpr : public BinarySymExpr {
const SymExpr *LHS;
const SymExpr *RHS;
@@ -409,6 +430,12 @@ public:
void dumpToStream(raw_ostream &os) const override;
+ unsigned computeComplexity() const override {
+ if (Complexity == 0)
+ Complexity = RHS->computeComplexity() + LHS->computeComplexity();
+ return Complexity;
+ }
+
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
ID.AddInteger((unsigned) SymSymExprKind);
@@ -423,20 +450,22 @@ public:
}
// Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
+ static bool classof(const SymExpr *SE) {
return SE->getKind() == SymSymExprKind;
}
};
class SymbolManager {
- typedef llvm::FoldingSet<SymExpr> DataSetTy;
- typedef llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy*> SymbolDependTy;
+ using DataSetTy = llvm::FoldingSet<SymExpr>;
+ using SymbolDependTy = llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy *>;
DataSetTy DataSet;
+
/// Stores the extra dependencies between symbols: the data should be kept
/// alive as long as the key is live.
SymbolDependTy SymbolDependencies;
- unsigned SymbolCounter;
+
+ unsigned SymbolCounter = 0;
llvm::BumpPtrAllocator& BPAlloc;
BasicValueFactory &BV;
ASTContext &Ctx;
@@ -444,14 +473,12 @@ class SymbolManager {
public:
SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
llvm::BumpPtrAllocator& bpalloc)
- : SymbolDependencies(16), SymbolCounter(0),
- BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
-
+ : SymbolDependencies(16), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
~SymbolManager();
static bool canSymbolicate(QualType T);
- /// \brief Make a unique symbol for MemRegion R according to its kind.
+ /// Make a unique symbol for MemRegion R according to its kind.
const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
const SymbolConjured* conjureSymbol(const Stmt *E,
@@ -472,7 +499,7 @@ public:
const SymbolExtent *getExtentSymbol(const SubRegion *R);
- /// \brief Creates a metadata symbol associated with a specific region.
+ /// Creates a metadata symbol associated with a specific region.
///
/// VisitCount can be used to differentiate regions corresponding to
/// different loop iterations, thus, making the symbol path-dependent.
@@ -504,7 +531,7 @@ public:
return SE->getType();
}
- /// \brief Add artificial symbol dependency.
+ /// Add artificial symbol dependency.
///
/// The dependent symbol should stay alive as long as the primary is alive.
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
@@ -515,23 +542,23 @@ public:
BasicValueFactory &getBasicVals() { return BV; }
};
-/// \brief A class responsible for cleaning up unused symbols.
+/// A class responsible for cleaning up unused symbols.
class SymbolReaper {
enum SymbolStatus {
NotProcessed,
HaveMarkedDependents
};
- typedef llvm::DenseSet<SymbolRef> SymbolSetTy;
- typedef llvm::DenseMap<SymbolRef, SymbolStatus> SymbolMapTy;
- typedef llvm::DenseSet<const MemRegion *> RegionSetTy;
+ using SymbolSetTy = llvm::DenseSet<SymbolRef>;
+ using SymbolMapTy = llvm::DenseMap<SymbolRef, SymbolStatus>;
+ using RegionSetTy = llvm::DenseSet<const MemRegion *>;
SymbolMapTy TheLiving;
SymbolSetTy MetadataInUse;
SymbolSetTy TheDead;
RegionSetTy RegionRoots;
-
+
const StackFrameContext *LCtx;
const Stmt *Loc;
SymbolManager& SymMgr;
@@ -539,17 +566,16 @@ class SymbolReaper {
llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
public:
- /// \brief Construct a reaper object, which removes everything which is not
+ /// Construct a reaper object, which removes everything which is not
/// live before we execute statement s in the given location context.
///
/// If the statement is NULL, everything is this and parent contexts is
/// considered live.
/// If the stack frame context is NULL, everything on stack is considered
/// dead.
- SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
- StoreManager &storeMgr)
- : LCtx(Ctx), Loc(s), SymMgr(symmgr),
- reapedStore(nullptr, storeMgr) {}
+ SymbolReaper(const StackFrameContext *Ctx, const Stmt *s,
+ SymbolManager &symmgr, StoreManager &storeMgr)
+ : LCtx(Ctx), Loc(s), SymMgr(symmgr), reapedStore(nullptr, storeMgr) {}
const LocationContext *getLocationContext() const { return LCtx; }
@@ -558,14 +584,14 @@ public:
bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
- /// \brief Unconditionally marks a symbol as live.
+ /// Unconditionally marks a symbol as live.
///
/// This should never be
/// used by checkers, only by the state infrastructure such as the store and
/// environment. Checkers should instead use metadata symbols and markInUse.
void markLive(SymbolRef sym);
- /// \brief Marks a symbol as important to a checker.
+ /// Marks a symbol as important to a checker.
///
/// For metadata symbols,
/// this will keep the symbol alive as long as its associated region is also
@@ -574,36 +600,38 @@ public:
/// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
void markInUse(SymbolRef sym);
- /// \brief If a symbol is known to be live, marks the symbol as live.
+ /// If a symbol is known to be live, marks the symbol as live.
///
/// Otherwise, if the symbol cannot be proven live, it is marked as dead.
/// Returns true if the symbol is dead, false if live.
bool maybeDead(SymbolRef sym);
- typedef SymbolSetTy::const_iterator dead_iterator;
+ using dead_iterator = SymbolSetTy::const_iterator;
+
dead_iterator dead_begin() const { return TheDead.begin(); }
dead_iterator dead_end() const { return TheDead.end(); }
bool hasDeadSymbols() const {
return !TheDead.empty();
}
-
- typedef RegionSetTy::const_iterator region_iterator;
+
+ using region_iterator = RegionSetTy::const_iterator;
+
region_iterator region_begin() const { return RegionRoots.begin(); }
region_iterator region_end() const { return RegionRoots.end(); }
- /// \brief Returns whether or not a symbol has been confirmed dead.
+ /// Returns whether or not a symbol has been confirmed dead.
///
/// This should only be called once all marking of dead symbols has completed.
/// (For checkers, this means only in the evalDeadSymbols callback.)
bool isDead(SymbolRef sym) const {
return TheDead.count(sym);
}
-
+
void markLive(const MemRegion *region);
void markElementIndicesLive(const MemRegion *region);
-
- /// \brief Set to the value of the symbolic store after
+
+ /// Set to the value of the symbolic store after
/// StoreManager::removeDeadBindings has been called.
void setReapedStore(StoreRef st) { reapedStore = st; }
@@ -621,7 +649,7 @@ public:
SymbolVisitor(const SymbolVisitor &) = default;
SymbolVisitor(SymbolVisitor &&) {}
- /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
+ /// A visitor method invoked by ProgramStateManager::scanReachableSymbols.
///
/// The method returns \c true if symbols should continue be scanned and \c
/// false otherwise.
@@ -629,8 +657,8 @@ public:
virtual bool VisitMemRegion(const MemRegion *region) { return true; }
};
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
index 7b76263f040c..ce19b7131d42 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
@@ -1,4 +1,4 @@
-//== TaintManager.h - Managing taint --------------------------- -*- C++ -*--=//
+//===- TaintManager.h - Managing taint --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,9 +14,9 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
#include "llvm/ADT/ImmutableMap.h"
@@ -29,28 +29,37 @@ namespace ento {
// FIXME: This does not use the nice trait macros because it must be accessible
// from multiple translation units.
struct TaintMap {};
-typedef llvm::ImmutableMap<SymbolRef, TaintTagType> TaintMapImpl;
+
+using TaintMapImpl = llvm::ImmutableMap<SymbolRef, TaintTagType>;
+
template<> struct ProgramStateTrait<TaintMap>
: public ProgramStatePartialTrait<TaintMapImpl> {
- static void *GDMIndex() { static int index = 0; return &index; }
+ static void *GDMIndex() {
+ static int index = 0;
+ return &index;
+ }
};
/// The GDM component mapping derived symbols' parent symbols to their
/// underlying regions. This is used to efficiently check whether a symbol is
/// tainted when it represents a sub-region of a tainted symbol.
struct DerivedSymTaint {};
-typedef llvm::ImmutableMap<SymbolRef, TaintedSubRegions> DerivedSymTaintImpl;
+
+using DerivedSymTaintImpl = llvm::ImmutableMap<SymbolRef, TaintedSubRegions>;
+
template<> struct ProgramStateTrait<DerivedSymTaint>
: public ProgramStatePartialTrait<DerivedSymTaintImpl> {
- static void *GDMIndex() { static int index; return &index; }
+ static void *GDMIndex() {
+ static int index;
+ return &index;
+ }
};
class TaintManager {
-
- TaintManager() {}
+ TaintManager() = default;
};
-}
-}
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
index 0c56e7d8ea69..50c4b8194cff 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
@@ -1,4 +1,4 @@
-//== TaintTag.h - Path-sensitive "State" for tracking values -*- C++ -*--=//
+//===- TaintTag.h - Path-sensitive "State" for tracking values --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,6 +11,7 @@
// of taint.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
@@ -19,9 +20,11 @@ namespace ento {
/// The type of taint, which helps to differentiate between different types of
/// taint.
-typedef unsigned TaintTagType;
+using TaintTagType = unsigned;
+
static const TaintTagType TaintTagGeneric = 0;
-}}
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 4f1a60e67556..07edd35ff944 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -20,7 +20,7 @@
#include <cassert>
namespace clang {
-
+
class CFGBlock;
namespace ento {
@@ -47,13 +47,13 @@ public:
/// Returns the node associated with the worklist unit.
ExplodedNode *getNode() const { return node; }
-
+
/// Returns the block counter map associated with the worklist unit.
BlockCounter getBlockCounter() const { return counter; }
/// Returns the CFGblock associated with the worklist unit.
const CFGBlock *getBlock() const { return block; }
-
+
/// Return the index within the CFGBlock for the worklist unit.
unsigned getIndex() const { return blockIdx; }
};
@@ -80,20 +80,14 @@ public:
void setBlockCounter(BlockCounter C) { CurrentCounter = C; }
BlockCounter getBlockCounter() const { return CurrentCounter; }
- class Visitor {
- public:
- Visitor() {}
- virtual ~Visitor();
- virtual bool visit(const WorkListUnit &U) = 0;
- };
- virtual bool visitItemsInWorkList(Visitor &V) = 0;
-
- static WorkList *makeDFS();
- static WorkList *makeBFS();
- static WorkList *makeBFSBlockDFSContents();
+ static std::unique_ptr<WorkList> makeDFS();
+ static std::unique_ptr<WorkList> makeBFS();
+ static std::unique_ptr<WorkList> makeBFSBlockDFSContents();
+ static std::unique_ptr<WorkList> makeUnexploredFirst();
+ static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
};
-} // end GR namespace
+} // end ento namespace
} // end clang namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
index a9dad6c5e9a2..59fbbc3ca80f 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -17,6 +17,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/LLVM.h"
+#include <functional>
#include <memory>
namespace clang {
@@ -29,10 +30,24 @@ class CompilerInstance;
namespace ento {
class PathDiagnosticConsumer;
class CheckerManager;
+class CheckerRegistry;
class AnalysisASTConsumer : public ASTConsumer {
public:
virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0;
+
+ /// This method allows registering statically linked custom checkers that are
+ /// not a part of the Clang tree. It employs the same mechanism that is used
+ /// by plugins.
+ ///
+ /// Example:
+ ///
+ /// Consumer->AddCheckerRegistrationFn([] (CheckerRegistry& Registry) {
+ /// Registry.addChecker<MyCustomChecker>("example.MyCustomChecker",
+ /// "Description");
+ /// });
+ virtual void
+ AddCheckerRegistrationFn(std::function<void(CheckerRegistry &)> Fn) = 0;
};
/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
index 2985b7c117ef..216a2359efba 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
#include "clang/Basic/LLVM.h"
+#include <functional>
#include <memory>
#include <string>
@@ -21,10 +22,13 @@ namespace clang {
namespace ento {
class CheckerManager;
+ class CheckerRegistry;
- std::unique_ptr<CheckerManager>
- createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
- ArrayRef<std::string> plugins, DiagnosticsEngine &diags);
+ std::unique_ptr<CheckerManager> createCheckerManager(
+ AnalyzerOptions &opts, const LangOptions &langOpts,
+ ArrayRef<std::string> plugins,
+ ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
+ DiagnosticsEngine &diags);
} // end ento namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index e66d48b1be1d..ba37b7f59a02 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -31,7 +31,7 @@ protected:
StringRef InFile) override;
};
-/// \brief Frontend action to parse model files.
+/// Frontend action to parse model files.
///
/// This frontend action is responsible for parsing model files. Model files can
/// not be parsed on their own, they rely on type information that is available
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
index 24f8042587f3..fa00ffd16553 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements clang::ento::ModelConsumer which is an
+/// This file implements clang::ento::ModelConsumer which is an
/// ASTConsumer for model files.
///
//===----------------------------------------------------------------------===//
@@ -25,7 +25,7 @@ class Stmt;
namespace ento {
-/// \brief ASTConsumer to consume model files' AST.
+/// ASTConsumer to consume model files' AST.
///
/// This consumer collects the bodies of function definitions into a StringMap
/// from a model file.
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/AllTUsExecution.h b/contrib/llvm/tools/clang/include/clang/Tooling/AllTUsExecution.h
new file mode 100644
index 000000000000..f199365dc815
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/AllTUsExecution.h
@@ -0,0 +1,76 @@
+//===--- AllTUsExecution.h - Execute actions on all TUs. -*- C++ --------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a tool executor that runs given actions on all TUs in the
+// compilation database. Tool results are deuplicated by the result key.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H
+#define LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H
+
+#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Tooling/Execution.h"
+
+namespace clang {
+namespace tooling {
+
+/// Executes given frontend actions on all files/TUs in the compilation
+/// database.
+class AllTUsToolExecutor : public ToolExecutor {
+public:
+ static const char *ExecutorName;
+
+ /// Init with \p CompilationDatabase.
+ /// This uses \p ThreadCount threads to exececute the actions on all files in
+ /// parallel. If \p ThreadCount is 0, this uses `llvm::hardware_concurrency`.
+ AllTUsToolExecutor(const CompilationDatabase &Compilations,
+ unsigned ThreadCount,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ /// Init with \p CommonOptionsParser. This is expected to be used by
+ /// `createExecutorFromCommandLineArgs` based on commandline options.
+ ///
+ /// The executor takes ownership of \p Options.
+ AllTUsToolExecutor(CommonOptionsParser Options, unsigned ThreadCount,
+ 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;
+
+ ExecutionContext *getExecutionContext() override { return &Context; };
+
+ ToolResults *getToolResults() override { return Results.get(); }
+
+ void mapVirtualFile(StringRef FilePath, StringRef Content) override {
+ OverlayFiles[FilePath] = Content;
+ }
+
+private:
+ // Used to store the parser when the executor is initialized with parser.
+ llvm::Optional<CommonOptionsParser> OptionsParser;
+ const CompilationDatabase &Compilations;
+ std::unique_ptr<ToolResults> Results;
+ ExecutionContext Context;
+ llvm::StringMap<std::string> OverlayFiles;
+ unsigned ThreadCount;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
index 4eb02251a775..94ccf1f34e57 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
@@ -1,4 +1,4 @@
-//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- C++ -*-===//
+//===- ArgumentsAdjusters.h - Command line arguments adjuster ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares typedef ArgumentsAdjuster and functions to create several
+// This file declares type ArgumentsAdjuster and functions to create several
// useful argument adjusters.
// ArgumentsAdjusters modify command line arguments obtained from a compilation
// database before they are used to run a frontend action.
@@ -26,42 +26,42 @@
namespace clang {
namespace tooling {
-/// \brief A sequence of command line arguments.
-typedef std::vector<std::string> CommandLineArguments;
+/// A sequence of command line arguments.
+using CommandLineArguments = std::vector<std::string>;
-/// \brief A prototype of a command line adjuster.
+/// A prototype of a command line adjuster.
///
/// Command line argument adjuster is responsible for command line arguments
/// modification before the arguments are used to run a frontend action.
-typedef std::function<CommandLineArguments(
- const CommandLineArguments &, StringRef Filename)> ArgumentsAdjuster;
+using ArgumentsAdjuster = std::function<CommandLineArguments(
+ const CommandLineArguments &, StringRef Filename)>;
-/// \brief Gets an argument adjuster that converts input command line arguments
+/// Gets an argument adjuster that converts input command line arguments
/// to the "syntax check only" variant.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster();
-/// \brief Gets an argument adjuster which removes output-related command line
+/// Gets an argument adjuster which removes output-related command line
/// arguments.
ArgumentsAdjuster getClangStripOutputAdjuster();
-/// \brief Gets an argument adjuster which removes dependency-file
+/// Gets an argument adjuster which removes dependency-file
/// related command line arguments.
ArgumentsAdjuster getClangStripDependencyFileAdjuster();
enum class ArgumentInsertPosition { BEGIN, END };
-/// \brief Gets an argument adjuster which inserts \p Extra arguments in the
+/// Gets an argument adjuster which inserts \p Extra arguments in the
/// specified position.
ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
ArgumentInsertPosition Pos);
-/// \brief Gets an argument adjuster which inserts an \p Extra argument in the
+/// Gets an argument adjuster which inserts an \p Extra argument in the
/// specified position.
ArgumentsAdjuster getInsertArgumentAdjuster(
const char *Extra,
ArgumentInsertPosition Pos = ArgumentInsertPosition::END);
-/// \brief Gets an argument adjuster which adjusts the arguments in sequence
+/// Gets an argument adjuster which adjusts the arguments in sequence
/// with the \p First adjuster and then with the \p Second one.
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second);
@@ -70,4 +70,3 @@ ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
} // namespace clang
#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
-
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
index 15e8161dd76f..7aaa712f9baf 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
@@ -34,7 +34,7 @@
namespace clang {
namespace tooling {
-/// \brief A parser for options common to all command-line Clang tools.
+/// A parser for options common to all command-line Clang tools.
///
/// Parses a common subset of command-line arguments, locates and loads a
/// compilation commands database and runs a tool with user-specified action. It
@@ -52,7 +52,7 @@ namespace tooling {
///
/// static cl::OptionCategory MyToolCategory("My tool options");
/// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
-/// static cl::extrahelp MoreHelp("\nMore help text...");
+/// static cl::extrahelp MoreHelp("\nMore help text...\n");
/// static cl::opt<bool> YourOwnOption(...);
/// ...
///
@@ -65,7 +65,7 @@ namespace tooling {
/// \endcode
class CommonOptionsParser {
public:
- /// \brief Parses command-line, initializes a compilation database.
+ /// Parses command-line, initializes a compilation database.
///
/// This constructor can change argc and argv contents, e.g. consume
/// command-line options used for creating FixedCompilationDatabase.
@@ -79,7 +79,7 @@ public:
: CommonOptionsParser(argc, argv, Category, llvm::cl::OneOrMore,
Overview) {}
- /// \brief Parses command-line, initializes a compilation database.
+ /// Parses command-line, initializes a compilation database.
///
/// This constructor can change argc and argv contents, e.g. consume
/// command-line options used for creating FixedCompilationDatabase.
@@ -92,7 +92,7 @@ public:
llvm::cl::NumOccurrencesFlag OccurrencesFlag,
const char *Overview = nullptr);
- /// \brief A factory method that is similar to the above constructor, except
+ /// 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,
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
index bc3e67b77de2..37e515fdc09e 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
@@ -1,4 +1,4 @@
-//===--- CompilationDatabase.h - --------------------------------*- C++ -*-===//
+//===- CompilationDatabase.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -34,35 +34,43 @@
#include "llvm/ADT/Twine.h"
#include <memory>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
namespace tooling {
-/// \brief Specifies the working directory and command of a compilation.
+/// Specifies the working directory and command of a compilation.
struct CompileCommand {
- CompileCommand() {}
+ CompileCommand() = default;
CompileCommand(Twine Directory, Twine Filename,
std::vector<std::string> CommandLine, Twine Output)
- : Directory(Directory.str()),
- Filename(Filename.str()),
- CommandLine(std::move(CommandLine)),
- Output(Output.str()){}
+ : Directory(Directory.str()), Filename(Filename.str()),
+ CommandLine(std::move(CommandLine)), Output(Output.str()){}
- /// \brief The working directory the command was executed from.
+ /// The working directory the command was executed from.
std::string Directory;
/// The source file associated with the command.
std::string Filename;
- /// \brief The command line that was executed.
+ /// The command line that was executed.
std::vector<std::string> CommandLine;
/// The output file associated with the command.
std::string Output;
+
+ friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) {
+ return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
+ LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output;
+ }
+
+ friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) {
+ return !(LHS == RHS);
+ }
};
-/// \brief Interface for compilation databases.
+/// Interface for compilation databases.
///
/// A compilation database allows the user to retrieve compile command lines
/// for the files in a project.
@@ -74,7 +82,7 @@ class CompilationDatabase {
public:
virtual ~CompilationDatabase();
- /// \brief Loads a compilation database from a build directory.
+ /// Loads a compilation database from a build directory.
///
/// Looks at the specified 'BuildDirectory' and creates a compilation database
/// that allows to query compile commands for source files in the
@@ -89,21 +97,21 @@ public:
static std::unique_ptr<CompilationDatabase>
loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage);
- /// \brief Tries to detect a compilation database location and load it.
+ /// Tries to detect a compilation database location and load it.
///
/// Looks for a compilation database in all parent paths of file 'SourceFile'
/// by calling loadFromDirectory.
static std::unique_ptr<CompilationDatabase>
autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage);
- /// \brief Tries to detect a compilation database location and load it.
+ /// Tries to detect a compilation database location and load it.
///
/// Looks for a compilation database in directory 'SourceDir' and all
/// its parent paths by calling loadFromDirectory.
static std::unique_ptr<CompilationDatabase>
autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage);
- /// \brief Returns all compile commands in which the specified file was
+ /// Returns all compile commands in which the specified file was
/// compiled.
///
/// This includes compile commands that span multiple source files.
@@ -113,15 +121,15 @@ public:
/// A compilation database representing the project would return both command
/// lines for a.cc and b.cc and only the first command line for t.cc.
virtual std::vector<CompileCommand> getCompileCommands(
- StringRef FilePath) const = 0;
+ StringRef FilePath) const = 0;
- /// \brief Returns the list of all files available in the compilation database.
+ /// Returns the list of all files available in the compilation database.
///
/// 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
+ /// Returns all compile commands for all the files in the compilation
/// database.
///
/// FIXME: Add a layer in Tooling that provides an interface to run a tool
@@ -133,7 +141,7 @@ public:
virtual std::vector<CompileCommand> getAllCompileCommands() const;
};
-/// \brief Interface for compilation database plugins.
+/// Interface for compilation database plugins.
///
/// A compilation database plugin allows the user to register custom compilation
/// databases that are picked up as compilation database if the corresponding
@@ -147,20 +155,20 @@ class CompilationDatabasePlugin {
public:
virtual ~CompilationDatabasePlugin();
- /// \brief Loads a compilation database from a build directory.
+ /// Loads a compilation database from a build directory.
///
/// \see CompilationDatabase::loadFromDirectory().
virtual std::unique_ptr<CompilationDatabase>
loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0;
};
-/// \brief A compilation database that returns a single compile command line.
+/// 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 "--".
+ /// Creates a FixedCompilationDatabase from the arguments after "--".
///
/// Parses the given command line for "--". If "--" is found, the rest of
/// the arguments will make up the command line in the returned
@@ -196,11 +204,11 @@ public:
static std::unique_ptr<FixedCompilationDatabase>
loadFromFile(StringRef Path, std::string &ErrorMsg);
- /// \brief Constructs a compilation data base from a specified directory
+ /// Constructs a compilation data base from a specified directory
/// and command line.
FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
- /// \brief Returns the given compile command.
+ /// Returns the given compile command.
///
/// Will always return a vector with one entry that contains the directory
/// and command line specified at construction with "clang-tool" as argv[0]
@@ -214,7 +222,14 @@ private:
std::vector<CompileCommand> CompileCommands;
};
-} // end namespace tooling
-} // end namespace clang
+/// Returns a wrapped CompilationDatabase that defers to the provided one,
+/// but getCompileCommands() will infer commands for unknown files.
+/// The return value of getAllFiles() or getAllCompileCommands() is unchanged.
+/// See InterpolatingCompilationDatabase.cpp for details on heuristics.
+std::unique_ptr<CompilationDatabase>
+ inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>);
+
+} // namespace tooling
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h
index 7323ec897403..051a08e2a91e 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h
@@ -1,4 +1,4 @@
-//===--- CompilationDatabasePluginRegistry.h - ------------------*- C++ -*-===//
+//===- CompilationDatabasePluginRegistry.h ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,12 +16,10 @@
namespace clang {
namespace tooling {
-class CompilationDatabasePlugin;
+using CompilationDatabasePluginRegistry =
+ llvm::Registry<CompilationDatabasePlugin>;
-typedef llvm::Registry<CompilationDatabasePlugin>
- CompilationDatabasePluginRegistry;
+} // namespace tooling
+} // namespace clang
-} // end namespace tooling
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Diagnostic.h
index b4920d4fe456..ddb40103e211 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Diagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Diagnostic.h
@@ -27,13 +27,13 @@
namespace clang {
namespace tooling {
-/// \brief Represents the diagnostic message with the error message associated
+/// Represents the diagnostic message with the error message associated
/// and the information on the location of the problem.
struct DiagnosticMessage {
DiagnosticMessage(llvm::StringRef Message = "");
- /// \brief Constructs a diagnostic message with anoffset to the diagnostic
- /// within the file where the problem occured.
+ /// Constructs a diagnostic message with anoffset to the diagnostic
+ /// within the file where the problem occurred.
///
/// \param Loc Should be a file location, it is not meaningful for a macro
/// location.
@@ -45,7 +45,7 @@ struct DiagnosticMessage {
unsigned FileOffset;
};
-/// \brief Represents the diagnostic with the level of severity and possible
+/// Represents the diagnostic with the level of severity and possible
/// fixes to be applied.
struct Diagnostic {
enum Level {
@@ -63,22 +63,22 @@ struct Diagnostic {
const SmallVector<DiagnosticMessage, 1> &Notes, Level DiagLevel,
llvm::StringRef BuildDirectory);
- /// \brief Name identifying the Diagnostic.
+ /// Name identifying the Diagnostic.
std::string DiagnosticName;
- /// \brief Message associated to the diagnostic.
+ /// Message associated to the diagnostic.
DiagnosticMessage Message;
- /// \brief Fixes to apply, grouped by file path.
+ /// Fixes to apply, grouped by file path.
llvm::StringMap<Replacements> Fix;
- /// \brief Potential notes about the diagnostic.
+ /// Potential notes about the diagnostic.
SmallVector<DiagnosticMessage, 1> Notes;
- /// \brief Diagnostic level. Can indicate either an error or a warning.
+ /// Diagnostic level. Can indicate either an error or a warning.
Level DiagLevel;
- /// \brief A build directory of the diagnostic source file.
+ /// A build directory of the diagnostic source file.
///
/// It's an absolute path which is `directory` field of the source file in
/// compilation database. If users don't specify the compilation database
@@ -88,7 +88,7 @@ struct Diagnostic {
std::string BuildDirectory;
};
-/// \brief Collection of Diagnostics generated from a single translation unit.
+/// Collection of Diagnostics generated from a single translation unit.
struct TranslationUnitDiagnostics {
/// Name of the main source for the translation unit.
std::string MainSourceFile;
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 3fea9aee604c..ba11ca4a7fee 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
@@ -1,4 +1,4 @@
-//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===//
+//===- Replacement.h - Framework for clang refactoring tools ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,32 +19,35 @@
#ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
#define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
#include <string>
#include <system_error>
+#include <utility>
#include <vector>
namespace clang {
+class FileManager;
class Rewriter;
+class SourceManager;
namespace tooling {
-/// \brief A source range independent of the \c SourceManager.
+/// A source range independent of the \c SourceManager.
class Range {
public:
- Range() : Offset(0), Length(0) {}
+ Range() = default;
Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
- /// \brief Accessors.
+ /// Accessors.
/// @{
unsigned getOffset() const { return Offset; }
unsigned getLength() const { return Length; }
@@ -52,38 +55,38 @@ public:
/// \name Range Predicates
/// @{
- /// \brief Whether this range overlaps with \p RHS or not.
+ /// Whether this range overlaps with \p RHS or not.
bool overlapsWith(Range RHS) const {
return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
}
- /// \brief Whether this range contains \p RHS or not.
+ /// Whether this range contains \p RHS or not.
bool contains(Range RHS) const {
return RHS.Offset >= Offset &&
(RHS.Offset + RHS.Length) <= (Offset + Length);
}
- /// \brief Whether this range equals to \p RHS or not.
+ /// Whether this range equals to \p RHS or not.
bool operator==(const Range &RHS) const {
return Offset == RHS.getOffset() && Length == RHS.getLength();
}
/// @}
private:
- unsigned Offset;
- unsigned Length;
+ unsigned Offset = 0;
+ unsigned Length = 0;
};
-/// \brief A text replacement.
+/// A text replacement.
///
/// Represents a SourceManager independent replacement of a range of text in a
/// specific file.
class Replacement {
public:
- /// \brief Creates an invalid (not applicable) replacement.
+ /// Creates an invalid (not applicable) replacement.
Replacement();
- /// \brief Creates a replacement of the range [Offset, Offset+Length) in
+ /// Creates a replacement of the range [Offset, Offset+Length) in
/// FilePath with ReplacementText.
///
/// \param FilePath A source file accessible via a SourceManager.
@@ -92,28 +95,28 @@ public:
Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
StringRef ReplacementText);
- /// \brief Creates a Replacement of the range [Start, Start+Length) with
+ /// Creates a Replacement of the range [Start, Start+Length) with
/// ReplacementText.
Replacement(const SourceManager &Sources, SourceLocation Start,
unsigned Length, StringRef ReplacementText);
- /// \brief Creates a Replacement of the given range with ReplacementText.
+ /// Creates a Replacement of the given range with ReplacementText.
Replacement(const SourceManager &Sources, const CharSourceRange &Range,
StringRef ReplacementText,
const LangOptions &LangOpts = LangOptions());
- /// \brief Creates a Replacement of the node with ReplacementText.
+ /// Creates a Replacement of the node with ReplacementText.
template <typename Node>
Replacement(const SourceManager &Sources, const Node &NodeToReplace,
StringRef ReplacementText,
const LangOptions &LangOpts = LangOptions());
- /// \brief Returns whether this replacement can be applied to a file.
+ /// Returns whether this replacement can be applied to a file.
///
/// Only replacements that are in a valid file can be applied.
bool isApplicable() const;
- /// \brief Accessors.
+ /// Accessors.
/// @{
StringRef getFilePath() const { return FilePath; }
unsigned getOffset() const { return ReplacementRange.getOffset(); }
@@ -121,10 +124,10 @@ public:
StringRef getReplacementText() const { return ReplacementText; }
/// @}
- /// \brief Applies the replacement on the Rewriter.
+ /// Applies the replacement on the Rewriter.
bool apply(Rewriter &Rewrite) const;
- /// \brief Returns a human readable string representation.
+ /// Returns a human readable string representation.
std::string toString() const;
private:
@@ -147,17 +150,17 @@ enum class replacement_error {
insert_conflict,
};
-/// \brief Carries extra error information in replacement-related llvm::Error,
+/// Carries extra error information in replacement-related llvm::Error,
/// e.g. fail applying replacements and replacements conflict.
class ReplacementError : public llvm::ErrorInfo<ReplacementError> {
public:
ReplacementError(replacement_error Err) : Err(Err) {}
- /// \brief Constructs an error related to an existing replacement.
+ /// Constructs an error related to an existing replacement.
ReplacementError(replacement_error Err, Replacement Existing)
: Err(Err), ExistingReplacement(std::move(Existing)) {}
- /// \brief Constructs an error related to a new replacement and an existing
+ /// Constructs an error related to a new replacement and an existing
/// replacement in a set of replacements.
ReplacementError(replacement_error Err, Replacement New, Replacement Existing)
: Err(Err), NewReplacement(std::move(New)),
@@ -186,35 +189,37 @@ private:
}
replacement_error Err;
+
// A new replacement, which is to expected be added into a set of
// replacements, that is causing problem.
llvm::Optional<Replacement> NewReplacement;
+
// An existing replacement in a replacements set that is causing problem.
llvm::Optional<Replacement> ExistingReplacement;
};
-/// \brief Less-than operator between two Replacements.
+/// Less-than operator between two Replacements.
bool operator<(const Replacement &LHS, const Replacement &RHS);
-/// \brief Equal-to operator between two Replacements.
+/// Equal-to operator between two Replacements.
bool operator==(const Replacement &LHS, const Replacement &RHS);
-/// \brief Maintains a set of replacements that are conflict-free.
+/// Maintains a set of replacements that are conflict-free.
/// Two replacements are considered conflicts if they overlap or have the same
/// offset (i.e. order-dependent).
class Replacements {
- private:
- typedef std::set<Replacement> ReplacementsImpl;
+private:
+ using ReplacementsImpl = std::set<Replacement>;
- public:
- typedef ReplacementsImpl::const_iterator const_iterator;
- typedef ReplacementsImpl::const_reverse_iterator const_reverse_iterator;
+public:
+ using const_iterator = ReplacementsImpl::const_iterator;
+ using const_reverse_iterator = ReplacementsImpl::const_reverse_iterator;
Replacements() = default;
explicit Replacements(const Replacement &R) { Replaces.insert(R); }
- /// \brief Adds a new replacement \p R to the current set of replacements.
+ /// Adds a new replacement \p R to the current set of replacements.
/// \p R must have the same file path as all existing replacements.
/// Returns `success` if the replacement is successfully inserted; otherwise,
/// it returns an llvm::Error, i.e. there is a conflict between R and the
@@ -253,7 +258,7 @@ class Replacements {
/// category of replacements.
llvm::Error add(const Replacement &R);
- /// \brief Merges \p Replaces into the current replacements. \p Replaces
+ /// Merges \p Replaces into the current replacements. \p Replaces
/// refers to code after applying the current replacements.
LLVM_NODISCARD Replacements merge(const Replacements &Replaces) const;
@@ -283,7 +288,6 @@ class Replacements {
return Replaces == RHS.Replaces;
}
-
private:
Replacements(const_iterator Begin, const_iterator End)
: Replaces(Begin, End) {}
@@ -307,7 +311,7 @@ private:
ReplacementsImpl Replaces;
};
-/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
+/// Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
///
/// Replacement applications happen independently of the success of
/// other applications.
@@ -315,7 +319,7 @@ private:
/// \returns true if all replacements apply. false otherwise.
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
-/// \brief Applies all replacements in \p Replaces to \p Code.
+/// Applies all replacements in \p Replaces to \p Code.
///
/// This completely ignores the path stored in each replacement. If all
/// replacements are applied successfully, this returns the code with
@@ -325,14 +329,15 @@ bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
llvm::Expected<std::string> applyAllReplacements(StringRef Code,
const Replacements &Replaces);
-/// \brief Collection of Replacements generated from a single translation unit.
+/// Collection of Replacements generated from a single translation unit.
struct TranslationUnitReplacements {
/// Name of the main source for the translation unit.
std::string MainSourceFile;
+
std::vector<Replacement> Replacements;
};
-/// \brief Calculates the new ranges after \p Replaces are applied. These
+/// Calculates the new ranges after \p Replaces are applied. These
/// include both the original \p Ranges and the affected ranges of \p Replaces
/// in the new code.
///
@@ -344,7 +349,7 @@ std::vector<Range>
calculateRangesAfterReplacements(const Replacements &Replaces,
const std::vector<Range> &Ranges);
-/// \brief If there are multiple <File, Replacements> pairs with the same file
+/// If there are multiple <File, Replacements> pairs with the same file
/// entry, we only keep one pair and discard the rest.
/// If a file does not exist, its corresponding replacements will be ignored.
std::map<std::string, Replacements> groupReplacementsByFile(
@@ -360,7 +365,8 @@ Replacement::Replacement(const SourceManager &Sources,
setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
}
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+
+} // namespace clang
#endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/DiagnosticsYaml.h b/contrib/llvm/tools/clang/include/clang/Tooling/DiagnosticsYaml.h
index 4d6ff063641b..bf0732bf0042 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/DiagnosticsYaml.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/DiagnosticsYaml.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines the structure of a YAML document for serializing
+/// This file defines the structure of a YAML document for serializing
/// diagnostics.
///
//===----------------------------------------------------------------------===//
@@ -27,7 +27,7 @@ namespace llvm {
namespace yaml {
template <> struct MappingTraits<clang::tooling::Diagnostic> {
- /// \brief Helper to (de)serialize a Diagnostic since we don't have direct
+ /// Helper to (de)serialize a Diagnostic since we don't have direct
/// access to its data members.
class NormalizedDiagnostic {
public:
@@ -80,7 +80,7 @@ template <> struct MappingTraits<clang::tooling::Diagnostic> {
}
};
-/// \brief Specialized MappingTraits to describe how a
+/// Specialized MappingTraits to describe how a
/// TranslationUnitDiagnostics is (de)serialized.
template <> struct MappingTraits<clang::tooling::TranslationUnitDiagnostics> {
static void mapping(IO &Io, clang::tooling::TranslationUnitDiagnostics &Doc) {
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h b/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h
index 1a44c4788c49..68aef53cb58f 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h
@@ -32,11 +32,12 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"
+#include "llvm/Support/StringSaver.h"
namespace clang {
namespace tooling {
-/// \brief An abstraction for the result of a tool execution. For example, the
+/// 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
@@ -45,32 +46,41 @@ 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 std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
+ AllKVResults() = 0;
virtual void forEachResult(
llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0;
};
+/// Stores the key-value results in memory. It maintains the lifetime of
+/// the result. Clang tools using this class are expected to generate a small
+/// set of different results, or a large set of duplicated results.
class InMemoryToolResults : public ToolResults {
public:
+ InMemoryToolResults() : Strings(Arena) {}
void addResult(StringRef Key, StringRef Value) override;
- std::vector<std::pair<std::string, std::string>> AllKVResults() override;
+ std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
+ AllKVResults() override;
void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)>
Callback) override;
private:
- std::vector<std::pair<std::string, std::string>> KVResults;
+ llvm::BumpPtrAllocator Arena;
+ llvm::UniqueStringSaver Strings;
+
+ std::vector<std::pair<llvm::StringRef, llvm::StringRef>> KVResults;
};
-/// \brief The context of an execution, including the information about
+/// 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`.
+ /// 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.
+ /// 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.
@@ -88,7 +98,7 @@ private:
ToolResults *Results;
};
-/// \brief Interface for executing clang frontend actions.
+/// 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.
@@ -101,54 +111,54 @@ class ToolExecutor {
public:
virtual ~ToolExecutor() {}
- /// \brief Returns the name of a specific executor.
+ /// Returns the name of a specific executor.
virtual StringRef getExecutorName() const = 0;
- /// \brief Executes each action with a corresponding arguments adjuster.
+ /// 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`.
+ /// 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.
+ /// 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.
+ /// 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.
+ /// 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
+/// 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`.
+ /// 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
+/// 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
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h b/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h
index 882979ef8ff6..11d12f3d30ce 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h
@@ -1,4 +1,4 @@
-//===--- FileMatchTrie.h - --------------------------------------*- C++ -*-===//
+//===- FileMatchTrie.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,22 +16,21 @@
#define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
#include <memory>
-namespace llvm {
-class StringRef;
-}
-
namespace clang {
namespace tooling {
+class FileMatchTrieNode;
+
struct PathComparator {
- virtual ~PathComparator() {}
+ virtual ~PathComparator() = default;
+
virtual bool equivalent(StringRef FileA, StringRef FileB) const = 0;
};
-class FileMatchTrieNode;
-/// \brief A trie to efficiently match against the entries of the compilation
+/// A trie to efficiently match against the entries of the compilation
/// database in order of matching suffix length.
///
/// When a clang tool is supposed to operate on a specific file, we have to
@@ -59,32 +58,32 @@ class FileMatchTrie {
public:
FileMatchTrie();
- /// \brief Construct a new \c FileMatchTrie with the given \c PathComparator.
+ /// Construct a new \c FileMatchTrie with the given \c PathComparator.
///
/// The \c FileMatchTrie takes ownership of 'Comparator'. Used for testing.
FileMatchTrie(PathComparator* Comparator);
~FileMatchTrie();
- /// \brief Insert a new absolute path. Relative paths are ignored.
+ /// Insert a new absolute path. Relative paths are ignored.
void insert(StringRef NewPath);
- /// \brief Finds the corresponding file in this trie.
+ /// Finds the corresponding file in this trie.
///
/// Returns file name stored in this trie that is equivalent to 'FileName'
/// according to 'Comparator', if it can be uniquely identified. If there
- /// are no matches an empty \c StringRef is returned. If there are ambigious
+ /// are no matches an empty \c StringRef is returned. If there are ambiguous
/// matches, an empty \c StringRef is returned and a corresponding message
/// written to 'Error'.
StringRef findEquivalent(StringRef FileName,
raw_ostream &Error) const;
+
private:
FileMatchTrieNode *Root;
std::unique_ptr<PathComparator> Comparator;
};
+} // namespace tooling
+} // namespace clang
-} // end namespace tooling
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/FixIt.h b/contrib/llvm/tools/clang/include/clang/Tooling/FixIt.h
index c1e508849280..b36f378d6361 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/FixIt.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/FixIt.h
@@ -29,35 +29,35 @@ namespace fixit {
namespace internal {
StringRef getText(SourceRange Range, const ASTContext &Context);
-/// \brief Returns the SourceRange of a SourceRange. This identity function is
+/// Returns the SourceRange of a SourceRange. This identity function is
/// used by the following template abstractions.
inline SourceRange getSourceRange(const SourceRange &Range) { return Range; }
-/// \brief Returns the SourceRange of the token at Location \p Loc.
+/// Returns the SourceRange of the token at Location \p Loc.
inline SourceRange getSourceRange(const SourceLocation &Loc) {
return SourceRange(Loc);
}
-/// \brief Returns the SourceRange of an given Node. \p Node is typically a
+/// Returns the SourceRange of an given Node. \p Node is typically a
/// 'Stmt', 'Expr' or a 'Decl'.
template <typename T> SourceRange getSourceRange(const T &Node) {
return Node.getSourceRange();
}
} // end namespace internal
-// \brief Returns a textual representation of \p Node.
+// Returns a textual representation of \p Node.
template <typename T>
StringRef getText(const T &Node, const ASTContext &Context) {
return internal::getText(internal::getSourceRange(Node), Context);
}
-// \brief Returns a FixItHint to remove \p Node.
+// Returns a FixItHint to remove \p Node.
// TODO: Add support for related syntactical elements (i.e. comments, ...).
template <typename T> FixItHint createRemoval(const T &Node) {
return FixItHint::CreateRemoval(internal::getSourceRange(Node));
}
-// \brief Returns a FixItHint to replace \p Destination by \p Source.
+// Returns a FixItHint to replace \p Destination by \p Source.
template <typename D, typename S>
FixItHint createReplacement(const D &Destination, const S &Source,
const ASTContext &Context) {
@@ -65,7 +65,7 @@ FixItHint createReplacement(const D &Destination, const S &Source,
getText(Source, Context));
}
-// \brief Returns a FixItHint to replace \p Destination by \p Source.
+// Returns a FixItHint to replace \p Destination by \p Source.
template <typename D>
FixItHint createReplacement(const D &Destination, StringRef Source) {
return FixItHint::CreateReplacement(internal::getSourceRange(Destination),
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h b/contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
new file mode 100644
index 000000000000..d99a3283168c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -0,0 +1,137 @@
+//===--- HeaderIncludes.h - Insert/Delete #includes for C++ code--*- 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_INCLUSIONS_HEADERINCLUDES_H
+#define LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Inclusions/IncludeStyle.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Regex.h"
+#include <unordered_map>
+
+namespace clang {
+namespace tooling {
+
+/// This class manages priorities of C++ #include categories and calculates
+/// priorities for headers.
+/// FIXME(ioeric): move this class into implementation file when clang-format's
+/// include sorting functions are also moved here.
+class IncludeCategoryManager {
+public:
+ IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName);
+
+ /// Returns the priority of the category which \p IncludeName belongs to.
+ /// If \p CheckMainHeader is true and \p IncludeName is a main header, returns
+ /// 0. Otherwise, returns the priority of the matching category or INT_MAX.
+ /// NOTE: this API is not thread-safe!
+ int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
+
+private:
+ bool isMainHeader(StringRef IncludeName) const;
+
+ const IncludeStyle Style;
+ bool IsMainFile;
+ std::string FileName;
+ // This refers to a substring in FileName.
+ StringRef FileStem;
+ // Regex is not thread-safe.
+ mutable SmallVector<llvm::Regex, 4> CategoryRegexs;
+};
+
+/// Generates replacements for inserting or deleting #include directives in a
+/// file.
+class HeaderIncludes {
+public:
+ HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
+ const IncludeStyle &Style);
+
+ /// Inserts an #include directive of \p Header into the code. If \p IsAngled
+ /// is true, \p Header will be quoted with <> in the directive; otherwise, it
+ /// will be quoted with "".
+ ///
+ /// When searching for points to insert new header, this ignores #include's
+ /// after the #include block(s) in the beginning of a file to avoid inserting
+ /// headers into code sections where new #include's should not be added by
+ /// default. These code sections include:
+ /// - raw string literals (containing #include).
+ /// - #if blocks.
+ /// - Special #include's among declarations (e.g. functions).
+ ///
+ /// Returns a replacement that inserts the new header into a suitable #include
+ /// block of the same category. This respects the order of the existing
+ /// #includes in the block; if the existing #includes are not already sorted,
+ /// this will simply insert the #include in front of the first #include of the
+ /// same category in the code that should be sorted after \p IncludeName. If
+ /// \p IncludeName already exists (with exactly the same spelling), this
+ /// returns None.
+ llvm::Optional<tooling::Replacement> insert(llvm::StringRef Header,
+ bool IsAngled) const;
+
+ /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled
+ /// is true or "" if \p IsAngled is false.
+ /// This doesn't resolve the header file path; it only deletes #includes with
+ /// exactly the same spelling.
+ tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
+
+private:
+ struct Include {
+ Include(StringRef Name, tooling::Range R) : Name(Name), R(R) {}
+
+ // An include header quoted with either <> or "".
+ std::string Name;
+ // The range of the whole line of include directive including any eading
+ // whitespaces and trailing comment.
+ tooling::Range R;
+ };
+
+ void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset);
+
+ std::string FileName;
+ std::string Code;
+
+ // Map from include name (quotation trimmed) to a list of existing includes
+ // (in case there are more than one) with the name in the current file. <x>
+ // and "x" will be treated as the same header when deleting #includes.
+ llvm::StringMap<llvm::SmallVector<Include, 1>> ExistingIncludes;
+
+ /// Map from priorities of #include categories to all #includes in the same
+ /// category. This is used to find #includes of the same category when
+ /// inserting new #includes. #includes in the same categories are sorted in
+ /// in the order they appear in the source file.
+ /// See comment for "FormatStyle::IncludeCategories" for details about include
+ /// priorities.
+ std::unordered_map<int, llvm::SmallVector<const Include *, 8>>
+ IncludesByPriority;
+
+ int FirstIncludeOffset;
+ // All new headers should be inserted after this offset (e.g. after header
+ // guards, file comment).
+ unsigned MinInsertOffset;
+ // Max insertion offset in the original code. For example, we want to avoid
+ // inserting new #includes into the actual code section (e.g. after a
+ // declaration).
+ unsigned MaxInsertOffset;
+ IncludeCategoryManager Categories;
+ // Record the offset of the end of the last include in each category.
+ std::unordered_map<int, int> CategoryEndOffsets;
+
+ // All possible priorities.
+ std::set<int> Priorities;
+
+ // Matches a whole #include directive.
+ llvm::Regex IncludeRegex;
+};
+
+
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
new file mode 100644
index 000000000000..a093dff27728
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -0,0 +1,139 @@
+//===--- IncludeStyle.h - Style of C++ #include directives -------*- 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_INCLUSIONS_INCLUDESTYLE_H
+#define LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
+
+#include "llvm/Support/YAMLTraits.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// Style for sorting and grouping C++ #include directives.
+struct IncludeStyle {
+ /// Styles for sorting multiple ``#include`` blocks.
+ enum IncludeBlocksStyle {
+ /// 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,
+ /// 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,
+ /// 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,
+ };
+
+ /// Dependent on the value, multiple ``#include`` blocks can be sorted
+ /// as one and divided based on category.
+ IncludeBlocksStyle IncludeBlocks;
+
+ /// See documentation of ``IncludeCategories``.
+ struct IncludeCategory {
+ /// The regular expression that this category matches.
+ std::string Regex;
+ /// The priority to assign to this category.
+ int Priority;
+ bool operator==(const IncludeCategory &Other) const {
+ return Regex == Other.Regex && Priority == Other.Priority;
+ }
+ };
+
+ /// Regular expressions denoting the different ``#include`` categories
+ /// used for ordering ``#includes``.
+ ///
+ /// `POSIX extended
+ /// <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_
+ /// regular expressions are supported.
+ ///
+ /// These regular expressions are matched against the filename of an include
+ /// (including the <> or "") in order. The value belonging to the first
+ /// matching regular expression is assigned and ``#includes`` are sorted first
+ /// according to increasing category number and then alphabetically within
+ /// each category.
+ ///
+ /// If none of the regular expressions match, INT_MAX is assigned as
+ /// category. The main header for a source file automatically gets category 0.
+ /// so that it is generally kept at the beginning of the ``#includes``
+ /// (http://llvm.org/docs/CodingStandards.html#include-style). However, you
+ /// can also assign negative priorities if you have certain headers that
+ /// always need to be first.
+ ///
+ /// To configure this in the .clang-format file, use:
+ /// \code{.yaml}
+ /// IncludeCategories:
+ /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ /// Priority: 2
+ /// - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ /// Priority: 3
+ /// - Regex: '<[[:alnum:].]+>'
+ /// Priority: 4
+ /// - Regex: '.*'
+ /// Priority: 1
+ /// \endcode
+ std::vector<IncludeCategory> IncludeCategories;
+
+ /// Specify a regular expression of suffixes that are allowed in the
+ /// file-to-main-include mapping.
+ ///
+ /// When guessing whether a #include is the "main" include (to assign
+ /// category 0, see above), use this regex of allowed suffixes to the header
+ /// stem. A partial match is done, so that:
+ /// - "" means "arbitrary suffix"
+ /// - "$" means "no suffix"
+ ///
+ /// For example, if configured to "(_test)?$", then a header a.h would be seen
+ /// as the "main" include in both a.cc and a_test.cc.
+ std::string IncludeIsMainRegex;
+};
+
+} // namespace tooling
+} // namespace clang
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)
+
+namespace llvm {
+namespace yaml {
+
+template <>
+struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> {
+ static void mapping(IO &IO,
+ clang::tooling::IncludeStyle::IncludeCategory &Category);
+};
+
+template <>
+struct ScalarEnumerationTraits<
+ clang::tooling::IncludeStyle::IncludeBlocksStyle> {
+ static void
+ enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value);
+};
+
+} // namespace yaml
+} // namespace llvm
+
+#endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
index 9a6866240b08..882afc6d9ece 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
@@ -1,4 +1,4 @@
-//===--- JSONCompilationDatabase.h - ----------------------------*- C++ -*-===//
+//===- JSONCompilationDatabase.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/FileMatchTrie.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -25,12 +26,14 @@
#include "llvm/Support/YAMLParser.h"
#include <memory>
#include <string>
+#include <tuple>
+#include <utility>
#include <vector>
namespace clang {
namespace tooling {
-/// \brief A JSON based compilation database.
+/// A JSON based compilation database.
///
/// JSON compilation database files must contain a list of JSON objects which
/// provide the command lines in the attributes 'directory', 'command',
@@ -58,7 +61,7 @@ namespace tooling {
enum class JSONCommandLineSyntax { Windows, Gnu, AutoDetect };
class JSONCompilationDatabase : public CompilationDatabase {
public:
- /// \brief Loads a JSON compilation database from the specified file.
+ /// Loads a JSON compilation database from the specified file.
///
/// Returns NULL and sets ErrorMessage if the database could not be
/// loaded from the given file.
@@ -66,14 +69,14 @@ public:
loadFromFile(StringRef FilePath, std::string &ErrorMessage,
JSONCommandLineSyntax Syntax);
- /// \brief Loads a JSON compilation database from a data buffer.
+ /// Loads a JSON compilation database from a data buffer.
///
/// Returns NULL and sets ErrorMessage if the database could not be loaded.
static std::unique_ptr<JSONCompilationDatabase>
loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage,
JSONCommandLineSyntax Syntax);
- /// \brief Returns all compile commands in which the specified file was
+ /// Returns all compile commands in which the specified file was
/// compiled.
///
/// FIXME: Currently FilePath must be an absolute path inside the
@@ -81,23 +84,23 @@ public:
std::vector<CompileCommand>
getCompileCommands(StringRef FilePath) const override;
- /// \brief Returns the list of all files available in the compilation database.
+ /// Returns the list of all files available in the compilation database.
///
/// These are the 'file' entries of the JSON objects.
std::vector<std::string> getAllFiles() const override;
- /// \brief Returns all compile commands for all the files in the compilation
+ /// Returns all compile commands for all the files in the compilation
/// database.
std::vector<CompileCommand> getAllCompileCommands() const override;
private:
- /// \brief Constructs a JSON compilation database on a memory buffer.
+ /// Constructs a JSON compilation database on a memory buffer.
JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database,
JSONCommandLineSyntax Syntax)
: Database(std::move(Database)), Syntax(Syntax),
YAMLStream(this->Database->getBuffer(), SM) {}
- /// \brief Parses the database file and creates the index.
+ /// Parses the database file and creates the index.
///
/// Returns whether parsing succeeded. Sets ErrorMessage if parsing
/// failed.
@@ -110,12 +113,12 @@ private:
// Otherwise, each entry in the command line vector is a literal
// argument to the compiler.
// The output field may be a nullptr.
- typedef std::tuple<llvm::yaml::ScalarNode *,
- llvm::yaml::ScalarNode *,
- std::vector<llvm::yaml::ScalarNode *>,
- llvm::yaml::ScalarNode *> CompileCommandRef;
+ using CompileCommandRef =
+ std::tuple<llvm::yaml::ScalarNode *, llvm::yaml::ScalarNode *,
+ std::vector<llvm::yaml::ScalarNode *>,
+ llvm::yaml::ScalarNode *>;
- /// \brief Converts the given array of CompileCommandRefs to CompileCommands.
+ /// Converts the given array of CompileCommandRefs to CompileCommands.
void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
std::vector<CompileCommand> &Commands) const;
@@ -134,7 +137,7 @@ private:
llvm::yaml::Stream YAMLStream;
};
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h
index bc95c3b09ec2..64b018ea26c2 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h
@@ -30,7 +30,7 @@ class Rewriter;
namespace tooling {
-/// \brief A tool to run refactorings.
+/// A tool to run refactorings.
///
/// This is a refactoring specific version of \see ClangTool. FrontendActions
/// passed to run() and runAndSave() should add replacements to
@@ -43,17 +43,17 @@ public:
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
- /// \brief Returns the file path to replacements map to which replacements
+ /// Returns the file path to replacements map to which replacements
/// should be added during the run of the tool.
std::map<std::string, Replacements> &getReplacements();
- /// \brief Call run(), apply all generated replacements, and immediately save
+ /// Call run(), apply all generated replacements, and immediately save
/// the results to disk.
///
/// \returns 0 upon success. Non-zero upon failure.
int runAndSave(FrontendActionFactory *ActionFactory);
- /// \brief Apply all stored replacements to the given Rewriter.
+ /// Apply all stored replacements to the given Rewriter.
///
/// FileToReplaces will be deduplicated with `groupReplacementsByFile` before
/// application.
@@ -65,14 +65,14 @@ public:
bool applyAllReplacements(Rewriter &Rewrite);
private:
- /// \brief Write all refactored files to disk.
+ /// Write all refactored files to disk.
int saveRewrittenFiles(Rewriter &Rewrite);
private:
std::map<std::string, Replacements> FileToReplaces;
};
-/// \brief Groups \p Replaces by the file path and applies each group of
+/// Groups \p Replaces by the file path and applies each group of
/// Replacements on the related file in \p Rewriter. In addition to applying
/// given Replacements, this function also formats the changed code.
///
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 8a468a6de84e..bfe042fc53c5 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -24,7 +24,7 @@
namespace clang {
namespace tooling {
-/// \brief An atomic change is used to create and group a set of source edits,
+/// An atomic change is used to create and group a set of source edits,
/// e.g. replacements or header insertions. Edits in an AtomicChange should be
/// related, e.g. replacements for the same type reference and the corresponding
/// header insertion/deletion.
@@ -36,13 +36,13 @@ namespace tooling {
/// bad, i.e. none of its source edits will be applied.
class AtomicChange {
public:
- /// \brief Creates an atomic change around \p KeyPosition with the key being a
+ /// Creates an atomic change around \p KeyPosition with the key being a
/// concatenation of the file name and the offset of \p KeyPosition.
/// \p KeyPosition should be the location of the key syntactical element that
/// is being changed, e.g. the call to a refactored method.
AtomicChange(const SourceManager &SM, SourceLocation KeyPosition);
- /// \brief Creates an atomic change for \p FilePath with a customized key.
+ /// Creates an atomic change for \p FilePath with a customized key.
AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
: Key(Key), FilePath(FilePath) {}
@@ -54,44 +54,44 @@ public:
bool operator==(const AtomicChange &Other) const;
- /// \brief Returns the atomic change as a YAML string.
+ /// Returns the atomic change as a YAML string.
std::string toYAMLString();
- /// \brief Converts a YAML-encoded automic change to AtomicChange.
+ /// Converts a YAML-encoded automic change to AtomicChange.
static AtomicChange convertFromYAML(llvm::StringRef YAMLContent);
- /// \brief Returns the key of this change, which is a concatenation of the
+ /// Returns the key of this change, which is a concatenation of the
/// file name and offset of the key position.
const std::string &getKey() const { return Key; }
- /// \brief Returns the path of the file containing this atomic change.
+ /// Returns the path of the file containing this atomic change.
const std::string &getFilePath() const { return FilePath; }
- /// \brief If this change could not be created successfully, e.g. because of
+ /// If this change could not be created successfully, e.g. because of
/// conflicts among replacements, use this to set an error description.
/// Thereby, places that cannot be fixed automatically can be gathered when
/// applying changes.
void setError(llvm::StringRef Error) { this->Error = Error; }
- /// \brief Returns whether an error has been set on this list.
+ /// Returns whether an error has been set on this list.
bool hasError() const { return !Error.empty(); }
- /// \brief Returns the error message or an empty string if it does not exist.
+ /// Returns the error message or an empty string if it does not exist.
const std::string &getError() const { return Error; }
- /// \brief Adds a replacement that replaces the given Range with
+ /// Adds a replacement that replaces the given Range with
/// ReplacementText.
/// \returns An llvm::Error carrying ReplacementError on error.
llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range,
llvm::StringRef ReplacementText);
- /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
+ /// Adds a replacement that replaces range [Loc, Loc+Length) with
/// \p Text.
/// \returns An llvm::Error carrying ReplacementError on error.
llvm::Error replace(const SourceManager &SM, SourceLocation Loc,
unsigned Length, llvm::StringRef Text);
- /// \brief Adds a replacement that inserts \p Text at \p Loc. If this
+ /// Adds a replacement that inserts \p Text at \p Loc. If this
/// insertion conflicts with an existing insertion (at the same position),
/// this will be inserted before/after the existing insertion depending on
/// \p InsertAfter. Users should use `replace` with `Length=0` instead if they
@@ -102,15 +102,15 @@ public:
llvm::Error insert(const SourceManager &SM, SourceLocation Loc,
llvm::StringRef Text, bool InsertAfter = true);
- /// \brief Adds a header into the file that contains the key position.
+ /// Adds a header into the file that contains the key position.
/// Header can be in angle brackets or double quotation marks. By default
/// (header is not quoted), header will be surrounded with double quotes.
void addHeader(llvm::StringRef Header);
- /// \brief Removes a header from the file that contains the key position.
+ /// Removes a header from the file that contains the key position.
void removeHeader(llvm::StringRef Header);
- /// \brief Returns a const reference to existing replacements.
+ /// Returns a const reference to existing replacements.
const Replacements &getReplacements() const { return Replaces; }
llvm::ArrayRef<std::string> getInsertedHeaders() const {
@@ -158,7 +158,7 @@ struct ApplyChangesSpec {
FormatOption Format = kNone;
};
-/// \brief Applies all AtomicChanges in \p Changes to the \p Code.
+/// 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
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 d96ad78ad876..d2d47ddc2c61 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief A wrapper class around \c RecursiveASTVisitor that visits each
+/// A wrapper class around \c RecursiveASTVisitor that visits each
/// occurrences of a named symbol.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h
index 4130e29d8dea..ce4a91cbbadc 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h
@@ -56,7 +56,7 @@ public:
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.
+ /// to be fulfilled before refactoring can be performed.
virtual bool hasSelectionRequirement() = 0;
/// Traverses each refactoring option used by the rule and invokes the
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
index fe7738e73499..005eb877bf0f 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
@@ -26,8 +26,8 @@ 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.
+ /// Handles an initiation or an invication error. An initiation error typically
+ /// has a \c DiagnosticError payload that describes why initiation failed.
virtual void handleError(llvm::Error Err) = 0;
/// Handles the source replacements that are produced by a refactoring action.
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 734b624d777b..5771a1c2d132 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
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides an action to rename every symbol at a point.
+/// Provides an action to rename every symbol at a point.
///
//===----------------------------------------------------------------------===//
@@ -82,7 +82,7 @@ private:
Expected<AtomicChanges>
createSourceReplacements(RefactoringRuleContext &Context) override;
- // A NamedDecl which indentifies the the symbol being renamed.
+ // A NamedDecl which identifies the symbol being renamed.
const NamedDecl *ND;
// The new qualified name to change the symbol to.
std::string NewQualifiedName;
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
index e69d2908b5d3..42e0a5cb6697 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h
@@ -21,7 +21,7 @@ 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:
+/// methods can contain multiple argument labels:
///
/// \code
/// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y;
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFinder.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFinder.h
index b74a5d7f70af..3622bd0daf85 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFinder.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFinder.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Methods for determining the USR of a symbol at a location in source
+/// Methods for determining the USR of a symbol at a location in source
/// code.
///
//===----------------------------------------------------------------------===//
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 f1c5ae60f875..ebc9790e9cb6 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
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides an action to find all relevant USRs at a point.
+/// Provides an action to find all relevant USRs at a point.
///
//===----------------------------------------------------------------------===//
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 801a8ad9e99c..e1228e9f39f7 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
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides functionality for finding all instances of a USR in a given
+/// Provides functionality for finding all instances of a USR in a given
/// AST.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h b/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h
index 9862951149a3..2137e0035d62 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h
@@ -35,7 +35,7 @@
namespace clang {
namespace tooling {
-/// \brief Base class for RefactoringCallbacks.
+/// Base class for RefactoringCallbacks.
///
/// Collects \c tooling::Replacements while running.
class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback {
@@ -47,7 +47,7 @@ protected:
Replacements Replace;
};
-/// \brief Adaptor between \c ast_matchers::MatchFinder and \c
+/// Adaptor between \c ast_matchers::MatchFinder and \c
/// tooling::RefactoringTool.
///
/// Runs AST matchers and stores the \c tooling::Replacements in a map.
@@ -74,7 +74,7 @@ private:
std::map<std::string, Replacements> &FileToReplaces;
};
-/// \brief Replace the text of the statement bound to \c FromId with the text in
+/// Replace the text of the statement bound to \c FromId with the text in
/// \c ToText.
class ReplaceStmtWithText : public RefactoringCallback {
public:
@@ -86,7 +86,7 @@ private:
std::string ToText;
};
-/// \brief Replace the text of an AST node bound to \c FromId with the result of
+/// Replace the text of an AST node bound to \c FromId with the result of
/// evaluating the template in \c ToTemplate.
///
/// Expressions of the form ${NodeName} in \c ToTemplate will be
@@ -109,7 +109,7 @@ private:
std::vector<TemplateElement> Template;
};
-/// \brief Replace the text of the statement bound to \c FromId with the text of
+/// Replace the text of the statement bound to \c FromId with the text of
/// the statement bound to \c ToId.
class ReplaceStmtWithStmt : public RefactoringCallback {
public:
@@ -121,7 +121,7 @@ private:
std::string ToId;
};
-/// \brief Replace an if-statement bound to \c Id with the outdented text of its
+/// Replace an if-statement bound to \c Id with the outdented text of its
/// body, choosing the consequent or the alternative based on whether
/// \c PickTrueBranch is true.
class ReplaceIfStmtWithItsBody : public RefactoringCallback {
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h b/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h
index 0b1dc4c77423..8e41525a9412 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines the structure of a YAML document for serializing
+/// This file defines the structure of a YAML document for serializing
/// replacements.
///
//===----------------------------------------------------------------------===//
@@ -25,10 +25,10 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement)
namespace llvm {
namespace yaml {
-/// \brief Specialized MappingTraits to describe how a Replacement is
+/// Specialized MappingTraits to describe how a Replacement is
/// (de)serialized.
template <> struct MappingTraits<clang::tooling::Replacement> {
- /// \brief Helper to (de)serialize a Replacement since we don't have direct
+ /// Helper to (de)serialize a Replacement since we don't have direct
/// access to its data members.
struct NormalizedReplacement {
NormalizedReplacement(const IO &)
@@ -59,7 +59,7 @@ template <> struct MappingTraits<clang::tooling::Replacement> {
}
};
-/// \brief Specialized MappingTraits to describe how a
+/// Specialized MappingTraits to describe how a
/// TranslationUnitReplacements is (de)serialized.
template <> struct MappingTraits<clang::tooling::TranslationUnitReplacements> {
static void mapping(IO &Io,
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h b/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h
index f5f32d737a45..572330e4cc22 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h
@@ -20,7 +20,7 @@
namespace clang {
namespace tooling {
-/// \brief A standalone executor that runs FrontendActions on a given set of
+/// 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
@@ -32,15 +32,16 @@ class StandaloneToolExecutor : public ToolExecutor {
public:
static const char *ExecutorName;
- /// \brief Init with \p CompilationDatabase and the paths of all files to be
+ /// Init with \p CompilationDatabase and the paths of all files to be
/// proccessed.
StandaloneToolExecutor(
const CompilationDatabase &Compilations,
llvm::ArrayRef<std::string> SourcePaths,
+ IntrusiveRefCntPtr<vfs::FileSystem> BaseFS = vfs::getRealFileSystem(),
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
- /// \brief Init with \p CommonOptionsParser. This is expected to be used by
+ /// Init with \p CommonOptionsParser. This is expected to be used by
/// `createExecutorFromCommandLineArgs` based on commandline options.
///
/// The executor takes ownership of \p Options.
@@ -58,7 +59,7 @@ public:
std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
Actions) override;
- /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ /// Set a \c DiagnosticConsumer to use during parsing.
void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
Tool.setDiagnosticConsumer(DiagConsumer);
}
@@ -75,7 +76,7 @@ public:
Tool.mapVirtualFile(FilePath, Content);
}
- /// \brief Returns the file manager used in the tool.
+ /// Returns the file manager used in the tool.
///
/// The file manager is shared between all translation units.
FileManager &getFiles() { return Tool.getFiles(); }
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h
index 11ba89546e9e..921689dff86f 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h
@@ -1,4 +1,4 @@
-//===--- ToolExecutorPluginRegistry.h - -------------------------*- C++ -*-===//
+//===- ToolExecutorPluginRegistry.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,9 +16,9 @@
namespace clang {
namespace tooling {
-typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry;
+using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>;
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // 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 e64be07d9ab4..c056894b1a7a 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
@@ -1,4 +1,4 @@
-//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===//
+//===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -31,35 +31,43 @@
#define LLVM_CLANG_TOOLING_TOOLING_H
#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Driver/Util.h"
+#include "clang/Basic/VirtualFileSystem.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"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Option.h"
#include <memory>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
+class CompilerInstance;
+class CompilerInvocation;
+class DiagnosticConsumer;
+class DiagnosticsEngine;
+class SourceManager;
+
namespace driver {
+
class Compilation;
-} // end namespace driver
-class CompilerInvocation;
-class SourceManager;
-class FrontendAction;
+} // namespace driver
namespace tooling {
-/// \brief Interface to process a clang::CompilerInvocation.
+class CompilationDatabase;
+
+/// Interface to process a clang::CompilerInvocation.
///
/// If your tool is based on FrontendAction, you should be deriving from
/// FrontendActionFactory instead.
@@ -67,15 +75,15 @@ class ToolAction {
public:
virtual ~ToolAction();
- /// \brief Perform an action for an invocation.
+ /// Perform an action for an invocation.
virtual bool
- runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation,
+ runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) = 0;
};
-/// \brief Interface to generate clang::FrontendActions.
+/// Interface to generate clang::FrontendActions.
///
/// Having a factory interface allows, for example, a new FrontendAction to be
/// created for each translation unit processed by ClangTool. This class is
@@ -85,19 +93,19 @@ class FrontendActionFactory : public ToolAction {
public:
~FrontendActionFactory() override;
- /// \brief Invokes the compiler with a FrontendAction created by create().
- bool runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation,
+ /// Invokes the compiler with a FrontendAction created by create().
+ bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override;
- /// \brief Returns a new clang::FrontendAction.
+ /// Returns a new clang::FrontendAction.
///
/// The caller takes ownership of the returned action.
- virtual clang::FrontendAction *create() = 0;
+ virtual FrontendAction *create() = 0;
};
-/// \brief Returns a new FrontendActionFactory for a given type.
+/// Returns a new FrontendActionFactory for a given type.
///
/// T must derive from clang::FrontendAction.
///
@@ -107,25 +115,25 @@ public:
template <typename T>
std::unique_ptr<FrontendActionFactory> newFrontendActionFactory();
-/// \brief Callbacks called before and after each source file processed by a
+/// Callbacks called before and after each source file processed by a
/// FrontendAction created by the FrontedActionFactory returned by \c
/// newFrontendActionFactory.
class SourceFileCallbacks {
public:
- virtual ~SourceFileCallbacks() {}
+ virtual ~SourceFileCallbacks() = default;
- /// \brief Called before a source file is processed by a FrontEndAction.
+ /// Called before a source file is processed by a FrontEndAction.
/// \see clang::FrontendAction::BeginSourceFileAction
virtual bool handleBeginSource(CompilerInstance &CI) {
return true;
}
- /// \brief Called after a source file is processed by a FrontendAction.
+ /// Called after a source file is processed by a FrontendAction.
/// \see clang::FrontendAction::EndSourceFileAction
virtual void handleEndSource() {}
};
-/// \brief Returns a new FrontendActionFactory for any type that provides an
+/// Returns a new FrontendActionFactory for any type that provides an
/// implementation of newASTConsumer().
///
/// FactoryT must implement: ASTConsumer *newASTConsumer().
@@ -140,7 +148,7 @@ template <typename FactoryT>
inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr);
-/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
+/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
///
/// \param ToolAction The action to run over the code.
/// \param Code C++ code.
@@ -149,16 +157,16 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
/// clang modules.
///
/// \return - True if 'ToolAction' was successfully executed.
-bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code,
const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
/// The first part of the pair is the filename, the second part the
/// file-content.
-typedef std::vector<std::pair<std::string, std::string>> FileContentMappings;
+using FileContentMappings = std::vector<std::pair<std::string, std::string>>;
-/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
+/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
/// with additional other flags.
///
/// \param ToolAction The action to run over the code.
@@ -172,14 +180,23 @@ typedef std::vector<std::pair<std::string, std::string>> FileContentMappings;
///
/// \return - True if 'ToolAction' was successfully executed.
bool runToolOnCodeWithArgs(
- clang::FrontendAction *ToolAction, const Twine &Code,
+ FrontendAction *ToolAction, const Twine &Code,
const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
const Twine &ToolName = "clang-tool",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(),
const FileContentMappings &VirtualMappedFiles = FileContentMappings());
-/// \brief Builds an AST for 'Code'.
+// Similar to the overload except this takes a VFS.
+bool runToolOnCodeWithArgs(
+ FrontendAction *ToolAction, const Twine &Code,
+ llvm::IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
+ const Twine &ToolName = "clang-tool",
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+/// Builds an AST for 'Code'.
///
/// \param Code C++ code.
/// \param FileName The file name which 'Code' will be mapped as.
@@ -192,7 +209,7 @@ buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
-/// \brief Builds an AST for 'Code' with additional flags.
+/// Builds an AST for 'Code' with additional flags.
///
/// \param Code C++ code.
/// \param Args Additional flags to pass on.
@@ -212,10 +229,10 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
std::make_shared<PCHContainerOperations>(),
ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster());
-/// \brief Utility to run a FrontendAction in a single clang invocation.
+/// Utility to run a FrontendAction in a single clang invocation.
class ToolInvocation {
public:
- /// \brief Create a tool invocation.
+ /// Create a tool invocation.
///
/// \param CommandLine The command line arguments to clang. Note that clang
/// uses its binary name (CommandLine[0]) to locate its builtin headers.
@@ -231,7 +248,7 @@ public:
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
- /// \brief Create a tool invocation.
+ /// Create a tool invocation.
///
/// \param CommandLine The command line arguments to clang.
/// \param Action The action to be executed.
@@ -244,19 +261,19 @@ public:
~ToolInvocation();
- /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ /// Set a \c DiagnosticConsumer to use during parsing.
void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
this->DiagConsumer = DiagConsumer;
}
- /// \brief Map a virtual file to be used while running the tool.
+ /// Map a virtual file to be used while running the tool.
///
/// \param FilePath The path at which the content will be mapped.
/// \param Content A null terminated buffer of the file's content.
// FIXME: remove this when all users have migrated!
void mapVirtualFile(StringRef FilePath, StringRef Content);
- /// \brief Run the clang invocation.
+ /// Run the clang invocation.
///
/// \returns True if there were no errors during execution.
bool run();
@@ -265,8 +282,8 @@ public:
void addFileMappingsTo(SourceManager &SourceManager);
bool runInvocation(const char *BinaryName,
- clang::driver::Compilation *Compilation,
- std::shared_ptr<clang::CompilerInvocation> Invocation,
+ driver::Compilation *Compilation,
+ std::shared_ptr<CompilerInvocation> Invocation,
std::shared_ptr<PCHContainerOperations> PCHContainerOps);
std::vector<std::string> CommandLine;
@@ -276,10 +293,10 @@ public:
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
// Maps <file name> -> <file content>.
llvm::StringMap<StringRef> MappedFileContents;
- DiagnosticConsumer *DiagConsumer;
+ DiagnosticConsumer *DiagConsumer = nullptr;
};
-/// \brief Utility to run a FrontendAction over a set of files.
+/// Utility to run a FrontendAction over a set of files.
///
/// This class is written to be usable for command line utilities.
/// By default the class uses ClangSyntaxOnlyAdjuster to modify
@@ -287,8 +304,8 @@ public:
/// a frontend action. One could install an additional command line
/// arguments adjuster by calling the appendArgumentsAdjuster() method.
class ClangTool {
- public:
- /// \brief Constructs a clang tool to run over a list of files.
+public:
+ /// Constructs a clang tool to run over a list of files.
///
/// \param Compilations The CompilationDatabase which contains the compile
/// command lines for the given source paths.
@@ -296,43 +313,50 @@ class ClangTool {
/// not found in Compilations, it is skipped.
/// \param PCHContainerOps The PCHContainerOperations for loading and creating
/// clang modules.
+ /// \param BaseFS VFS used for all underlying file accesses when running the
+ /// tool.
ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
- std::make_shared<PCHContainerOperations>());
+ std::make_shared<PCHContainerOperations>(),
+ IntrusiveRefCntPtr<vfs::FileSystem> BaseFS =
+ vfs::getRealFileSystem());
~ClangTool();
- /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ /// Set a \c DiagnosticConsumer to use during parsing.
void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
this->DiagConsumer = DiagConsumer;
}
- /// \brief Map a virtual file to be used while running the tool.
+ /// Map a virtual file to be used while running the tool.
///
/// \param FilePath The path at which the content will be mapped.
/// \param Content A null terminated buffer of the file's content.
void mapVirtualFile(StringRef FilePath, StringRef Content);
- /// \brief Append a command line arguments adjuster to the adjuster chain.
+ /// Append a command line arguments adjuster to the adjuster chain.
///
/// \param Adjuster An argument adjuster, which will be run on the output of
/// previous argument adjusters.
void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
- /// \brief Clear the command line arguments adjuster chain.
+ /// Clear the command line arguments adjuster chain.
void clearArgumentsAdjusters();
/// Runs an action over all files specified in the command line.
///
/// \param Action Tool action.
+ ///
+ /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but
+ /// some files are skipped due to missing compile commands.
int run(ToolAction *Action);
- /// \brief Create an AST for each file specified in the command line and
+ /// Create an AST for each file specified in the command line and
/// append them to ASTs.
int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
- /// \brief Returns the file manager used in the tool.
+ /// Returns the file manager used in the tool.
///
/// The file manager is shared between all translation units.
FileManager &getFiles() { return *Files; }
@@ -347,20 +371,22 @@ private:
llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
llvm::IntrusiveRefCntPtr<FileManager> Files;
+
// Contains a list of pairs (<file name>, <file content>).
- std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
+ std::vector<std::pair<StringRef, StringRef>> MappedFileContents;
+
llvm::StringSet<> SeenWorkingDirectories;
ArgumentsAdjuster ArgsAdjuster;
- DiagnosticConsumer *DiagConsumer;
+ DiagnosticConsumer *DiagConsumer = nullptr;
};
template <typename T>
std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
class SimpleFrontendActionFactory : public FrontendActionFactory {
public:
- clang::FrontendAction *create() override { return new T; }
+ FrontendAction *create() override { return new T; }
};
return std::unique_ptr<FrontendActionFactory>(
@@ -374,36 +400,37 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
public:
explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
SourceFileCallbacks *Callbacks)
- : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
- clang::FrontendAction *create() override {
+ FrontendAction *create() override {
return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
}
private:
- class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
+ class ConsumerFactoryAdaptor : public ASTFrontendAction {
public:
ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
SourceFileCallbacks *Callbacks)
- : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
- std::unique_ptr<clang::ASTConsumer>
- CreateASTConsumer(clang::CompilerInstance &, StringRef) override {
+ std::unique_ptr<ASTConsumer>
+ CreateASTConsumer(CompilerInstance &, StringRef) override {
return ConsumerFactory->newASTConsumer();
}
protected:
bool BeginSourceFileAction(CompilerInstance &CI) override {
- if (!clang::ASTFrontendAction::BeginSourceFileAction(CI))
+ if (!ASTFrontendAction::BeginSourceFileAction(CI))
return false;
if (Callbacks)
return Callbacks->handleBeginSource(CI);
return true;
}
+
void EndSourceFileAction() override {
if (Callbacks)
Callbacks->handleEndSource();
- clang::ASTFrontendAction::EndSourceFileAction();
+ ASTFrontendAction::EndSourceFileAction();
}
private:
@@ -418,7 +445,7 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks));
}
-/// \brief Returns the absolute path of \c File, by prepending it with
+/// Returns the absolute path of \c File, by prepending it with
/// the current directory if \c File is not absolute.
///
/// Otherwise returns \c File.
@@ -432,7 +459,7 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
/// \param File Either an absolute or relative path.
std::string getAbsolutePath(StringRef File);
-/// \brief Changes CommandLine to contain implicit flags that would have been
+/// Changes CommandLine to contain implicit flags that would have been
/// defined had the compiler driver been invoked through the path InvokedAs.
///
/// For example, when called with \c InvokedAs set to `i686-linux-android-g++`,
@@ -455,12 +482,12 @@ std::string getAbsolutePath(StringRef File);
void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
StringRef InvokedAs);
-/// \brief Creates a \c CompilerInvocation.
-clang::CompilerInvocation *newInvocation(
- clang::DiagnosticsEngine *Diagnostics,
- const llvm::opt::ArgStringList &CC1Args);
+/// Creates a \c CompilerInvocation.
+CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
+ const llvm::opt::ArgStringList &CC1Args);
+
+} // namespace tooling
-} // end namespace tooling
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_TOOLING_TOOLING_H
diff --git a/contrib/llvm/tools/clang/include/clang/module.modulemap b/contrib/llvm/tools/clang/include/clang/module.modulemap
index 4097ad2dc716..8d525c5ffbac 100644
--- a/contrib/llvm/tools/clang/include/clang/module.modulemap
+++ b/contrib/llvm/tools/clang/include/clang/module.modulemap
@@ -42,6 +42,7 @@ module Clang_Basic {
textual header "Basic/BuiltinsX86_64.def"
textual header "Basic/BuiltinsXCore.def"
textual header "Basic/DiagnosticOptions.def"
+ textual header "Basic/Features.def"
textual header "Basic/LangOptions.def"
textual header "Basic/OpenCLExtensions.def"
textual header "Basic/OpenCLImageTypes.def"
@@ -153,3 +154,8 @@ module Clang_ToolingCore {
requires cplusplus
umbrella "Tooling/Core" module * { export * }
}
+
+module Clang_ToolingInclusions {
+ requires cplusplus
+ umbrella "Tooling/Inclusions" module * { export * }
+}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
index cf7cddefc03d..3c7b593be6d4 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
@@ -226,7 +226,7 @@ static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
new DiagnosticsEngine(DiagID, diagOpts, &printer,
/*ShouldOwnClient=*/false));
Diags->setSourceManager(&PP.getSourceManager());
-
+
printer.BeginSourceFile(PP.getLangOpts(), &PP);
arcDiags.reportDiagnostics(*Diags);
printer.EndSourceFile();
@@ -305,7 +305,7 @@ bool arcmt::checkForManualIssues(
// After parsing of source files ended, we want to reuse the
// diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticConsumer requires that
+ // We call BeginSourceFile because DiagnosticConsumer requires that
// diagnostics with source range information are emitted only in between
// BeginSourceFile() and EndSourceFile().
DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
@@ -503,7 +503,7 @@ public:
} // end anonymous namespace.
-/// \brief Anchor for VTable.
+/// Anchor for VTable.
MigrationProcess::RewriteListener::~RewriteListener() { }
MigrationProcess::MigrationProcess(
@@ -572,7 +572,7 @@ bool MigrationProcess::applyTransform(TransformFn trans,
// After parsing of source files ended, we want to reuse the
// diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticConsumer requires that
+ // We call BeginSourceFile because DiagnosticConsumer requires that
// diagnostics with source range information are emitted only in between
// BeginSourceFile() and EndSourceFile().
DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
index 4dedac88f982..ccc8c9ee30ff 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -67,7 +67,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
llvm::MemoryBuffer::getFile(infoFile);
if (!fileBuf)
return report("Error opening file: " + infoFile, Diag);
-
+
SmallVector<StringRef, 64> lines;
fileBuf.get()->getBuffer().split(lines, "\n");
@@ -78,7 +78,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
return report("Invalid file data: '" + lines[idx+1] + "' not a number",
Diag);
StringRef toFilename = lines[idx+2];
-
+
const FileEntry *origFE = FileMgr->getFile(fromFilename);
if (!origFE) {
if (ignoreIfFilesChanged)
@@ -152,7 +152,7 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
newOut.write(mem->getBufferStart(), mem->getBufferSize());
newOut.close();
-
+
const FileEntry *newE = FileMgr->getFile(tempPath);
remap(origFE, newE);
infoOut << newE->getName() << '\n';
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h b/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h
index 4f153b1ad2f4..1a261c1e31aa 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h
@@ -25,7 +25,7 @@ namespace arcmt {
class CapturedDiagList {
typedef std::list<StoredDiagnostic> ListTy;
ListTy List;
-
+
public:
void push_back(const StoredDiagnostic &diag) { List.push_back(diag); }
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
index fcc67da1f774..7e9bc6a5bdc6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -46,7 +46,7 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
CF_BRIDGING_ENABLE,
CF_BRIDGING_MAY_INCLUDE
};
-
+
void migrateDecl(Decl *D);
void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
void migrateProtocolConformance(ASTContext &Ctx,
@@ -63,26 +63,26 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
ObjCMethodDecl *OM,
ObjCInstanceTypeFamily OIT_Family = OIT_None);
-
+
void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
const FunctionDecl *FuncDecl, bool ResultAnnotated);
void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
-
+
void AnnotateImplicitBridging(ASTContext &Ctx);
-
+
CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
const FunctionDecl *FuncDecl);
-
+
void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
-
+
void migrateAddMethodAnnotation(ASTContext &Ctx,
const ObjCMethodDecl *MethodDecl);
void inferDesignatedInitializers(ASTContext &Ctx,
const ObjCImplementationDecl *ImplD);
-
+
bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
public:
@@ -225,8 +225,8 @@ namespace {
isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
}
-
- /// \brief - Rewrite message expression for Objective-C setter and getters into
+
+ /// - Rewrite message expression for Objective-C setter and getters into
/// property-dot syntax.
bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,
Preprocessor &PP,
@@ -239,17 +239,17 @@ namespace {
if (const Expr *Receiver = Msg->getInstanceReceiver())
if (Receiver->getType()->isObjCBuiltinType())
return false;
-
+
const ObjCMethodDecl *Method = Msg->getMethodDecl();
if (!Method)
return false;
if (!Method->isPropertyAccessor())
return false;
-
+
const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
if (!Prop)
return false;
-
+
SourceRange MsgRange = Msg->getSourceRange();
bool ReceiverIsSuper =
(Msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
@@ -276,7 +276,7 @@ namespace {
PropertyDotString = ".";
PropertyDotString += Prop->getName();
commit.replace(SpaceRange, PropertyDotString);
-
+
// remove '[' ']'
commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
@@ -465,7 +465,7 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
PropertyString += "(nonatomic";
LParenAdded = true;
}
-
+
std::string PropertyNameString = Getter->getNameAsString();
StringRef PropertyName(PropertyNameString);
if (LengthOfPrefix > 0) {
@@ -480,8 +480,8 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
// Property with no setter may be suggested as a 'readonly' property.
if (!Setter)
append_attr(PropertyString, "readonly", LParenAdded);
-
-
+
+
// Short circuit 'delegate' properties that contain the name "delegate" or
// "dataSource", or have exact name "target" to have 'assign' attribute.
if (PropertyName.equals("target") ||
@@ -542,7 +542,7 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
}
SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
Selector GetterSelector = Getter->getSelector();
-
+
SourceLocation EndGetterSelectorLoc =
StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
@@ -572,7 +572,7 @@ void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
ObjCContainerDecl *D) {
if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
return;
-
+
for (auto *Method : D->methods()) {
if (Method->isDeprecated())
continue;
@@ -587,7 +587,7 @@ void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
}
if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
return;
-
+
for (auto *Prop : D->instance_properties()) {
if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
!Prop->isDeprecated())
@@ -628,7 +628,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
else
return false;
}
-
+
// At this point, all required properties in this protocol conform to those
// declared in the class.
// Check that class implements the required methods of the protocol too.
@@ -666,7 +666,7 @@ static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
std::string ClassString;
SourceLocation EndLoc =
IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
-
+
if (Protocols.empty()) {
ClassString = '<';
for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
@@ -686,7 +686,7 @@ static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
EndLoc = *PL;
}
-
+
commit.insertAfterToken(EndLoc, ClassString);
return true;
}
@@ -717,7 +717,7 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
ClassString += NSIntegerName;
}
ClassString += ", ";
-
+
ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ')';
SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
@@ -731,7 +731,7 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
}
else
return false;
-
+
SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
NS.getASTContext(), /*IsDecl*/true);
@@ -763,13 +763,13 @@ static void rewriteToNSMacroDecl(ASTContext &Ctx,
QualType DesignatedEnumType = EnumDcl->getIntegerType();
assert(!DesignatedEnumType.isNull()
&& "rewriteToNSMacroDecl - underlying enum type is null");
-
+
PrintingPolicy Policy(Ctx.getPrintingPolicy());
std::string TypeString = DesignatedEnumType.getAsString(Policy);
std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";
ClassString += TypeString;
ClassString += ", ";
-
+
ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ") ";
SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
@@ -781,7 +781,7 @@ static void rewriteToNSMacroDecl(ASTContext &Ctx,
SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd();
-
+
commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
}
@@ -801,7 +801,7 @@ static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
if (BO->isShiftOp() || BO->isBitwiseOp())
return true;
-
+
uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
if (PowerOfTwo && EnumVal) {
if (!llvm::isPowerOf2_64(EnumVal))
@@ -826,7 +826,7 @@ static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
}
-void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
+void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
const ObjCImplementationDecl *ImpDecl) {
const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
@@ -836,11 +836,11 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
-
+
for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls)
if (!ExplicitProtocols.count(ProtDecl))
PotentialImplicitProtocols.push_back(ProtDecl);
-
+
if (PotentialImplicitProtocols.empty())
return;
@@ -852,10 +852,10 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
PotentialImplicitProtocols[i]))
ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
-
+
if (ConformingProtocols.empty())
return;
-
+
// Further reduce number of conforming protocols. If protocol P1 is in the list
// protocol P2 (P2<P1>), No need to include P1.
llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
@@ -885,7 +885,7 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
const TypedefDecl *TypedefDcl) {
-
+
QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
if (NSAPIObj->isObjCNSIntegerType(qt))
NSIntegerTypedefed = TypedefDcl;
@@ -919,10 +919,10 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
}
if (TypedefDcl->isDeprecated())
return false;
-
+
QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
-
+
if (NSIntegerName.empty()) {
// Also check for typedef enum {...} TD;
if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
@@ -938,7 +938,7 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
}
return false;
}
-
+
// We may still use NS_OPTIONS based on what we find in the enumertor list.
bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
@@ -1000,7 +1000,7 @@ void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
ObjCMethodDecl *OM) {
ObjCInstanceTypeFamily OIT_Family =
Selector::getInstTypeMethodFamily(OM->getSelector());
-
+
std::string ClassName;
switch (OIT_Family) {
case OIT_None:
@@ -1025,7 +1025,7 @@ void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
}
if (!OM->getReturnType()->isObjCIdType())
return;
-
+
ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
if (!IDecl) {
if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
@@ -1065,7 +1065,7 @@ static bool TypeIsInnerPointer(QualType T) {
return true;
}
-/// \brief Check whether the two versions match.
+/// Check whether the two versions match.
static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
return (X == Y);
}
@@ -1080,7 +1080,7 @@ static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
if (!AA1)
return true;
const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
-
+
VersionTuple Introduced1 = AA1->getIntroduced();
VersionTuple Deprecated1 = AA1->getDeprecated();
VersionTuple Obsoleted1 = AA1->getObsoleted();
@@ -1101,7 +1101,7 @@ static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
bool match = false;
for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
- // Matching attribute kind only. Except for Availabilty attributes,
+ // Matching attribute kind only. Except for Availability attributes,
// we are not getting into details of the attributes. For all practical purposes
// this is sufficient.
if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
@@ -1159,14 +1159,14 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
QualType GRT = Method->getReturnType();
if (GRT->isVoidType())
return false;
-
+
Selector GetterSelector = Method->getSelector();
ObjCInstanceTypeFamily OIT_Family =
Selector::getInstTypeMethodFamily(GetterSelector);
-
+
if (OIT_Family != OIT_None)
return false;
-
+
IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
Selector SetterSelector =
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
@@ -1199,7 +1199,7 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
}
}
}
-
+
if (SetterMethod) {
if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
return false;
@@ -1207,7 +1207,7 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
if (SetterMethod->isDeprecated() ||
!AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
return false;
-
+
// Is this a valid setter, matching the target getter?
QualType SRT = SetterMethod->getReturnType();
if (!SRT->isVoidType())
@@ -1255,7 +1255,7 @@ void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
if (!TypeIsInnerPointer(RT) ||
!NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
return;
-
+
edit::Commit commit(*Editor);
commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER");
Editor->commit(commit);
@@ -1277,7 +1277,7 @@ void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
ObjCContainerDecl *CDecl) {
if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl))
return;
-
+
// migrate methods which can have instancetype as their result type.
for (auto *Method : CDecl->methods()) {
if (Method->isDeprecated())
@@ -1294,7 +1294,7 @@ void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
OM->getReturnType() == Ctx.getObjCInstanceType() ||
!OM->getReturnType()->isObjCIdType())
return;
-
+
// Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
// NSYYYNamE with matching names be at least 3 characters long.
ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
@@ -1306,17 +1306,17 @@ void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
}
if (!IDecl)
return;
-
+
std::string StringClassName = IDecl->getName();
StringRef LoweredClassName(StringClassName);
std::string StringLoweredClassName = LoweredClassName.lower();
LoweredClassName = StringLoweredClassName;
-
+
IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
// Handle method with no name at its first selector slot; e.g. + (id):(int)x.
if (!MethodIdName)
return;
-
+
std::string MethodName = MethodIdName->getName();
if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
StringRef STRefMethodName(MethodName);
@@ -1353,10 +1353,10 @@ void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
static bool IsVoidStarType(QualType Ty) {
if (!Ty->isPointerType())
return false;
-
+
while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
Ty = TD->getDecl()->getUnderlyingType();
-
+
// Is the type void*?
const PointerType* PT = Ty->getAs<PointerType>();
if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
@@ -1418,14 +1418,14 @@ void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
if (Decl->isDeprecated())
return;
-
+
if (Decl->hasAttr<CFAuditedTransferAttr>()) {
assert(CFFunctionIBCandidates.empty() &&
"Cannot have audited functions/methods inside user "
"provided CF_IMPLICIT_BRIDGING_ENABLE");
return;
}
-
+
// Finction must be annotated first.
if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
@@ -1469,7 +1469,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
AnnotationString = " NS_RETURNS_RETAINED";
}
-
+
if (AnnotationString) {
edit::Commit commit(*Editor);
commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
@@ -1503,18 +1503,18 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
const FunctionDecl *FuncDecl) {
if (FuncDecl->hasBody())
return CF_BRIDGING_NONE;
-
+
CallEffects CE = CallEffects::getEffect(FuncDecl);
bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
-
+
// Trivial case of when function is annotated and has no argument.
if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
return CF_BRIDGING_NONE;
-
+
bool ReturnCFAudited = false;
if (!FuncIsReturnAnnotated) {
RetEffect Ret = CE.getReturnValue();
@@ -1524,7 +1524,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
else if (!AuditedType(FuncDecl->getReturnType()))
return CF_BRIDGING_NONE;
}
-
+
// At this point result type is audited for potential inclusion.
// Now, how about argument types.
ArrayRef<ArgEffect> AEArgs = CE.getArgs();
@@ -1550,7 +1550,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
}
if (ReturnCFAudited || ArgCFAudited)
return CF_BRIDGING_ENABLE;
-
+
return CF_BRIDGING_MAY_INCLUDE;
}
@@ -1558,7 +1558,7 @@ void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
ObjCContainerDecl *CDecl) {
if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
return;
-
+
// migrate methods which can have instancetype as their result type.
for (const auto *Method : CDecl->methods())
migrateCFAnnotation(Ctx, Method);
@@ -1588,14 +1588,14 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
case clang::OMF_init:
case clang::OMF_mutableCopy:
break;
-
+
default:
if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
AnnotationString = " NS_RETURNS_RETAINED";
break;
}
}
-
+
if (AnnotationString) {
edit::Commit commit(*Editor);
commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString);
@@ -1622,7 +1622,7 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
const ObjCMethodDecl *MethodDecl) {
if (MethodDecl->hasBody() || MethodDecl->isImplicit())
return;
-
+
CallEffects CE = CallEffects::getEffect(MethodDecl);
bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
@@ -1639,12 +1639,12 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF");
Editor->commit(commit);
}
-
+
// Trivial case of when function is annotated and has no argument.
if (MethodIsReturnAnnotated &&
(MethodDecl->param_begin() == MethodDecl->param_end()))
return;
-
+
if (!MethodIsReturnAnnotated) {
RetEffect Ret = CE.getReturnValue();
if ((Ret.getObjKind() == RetEffect::CF ||
@@ -1655,7 +1655,7 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
} else if (!AuditedType(MethodDecl->getReturnType()))
return;
}
-
+
// At this point result type is either annotated or audited.
// Now, how about argument types.
ArrayRef<ArgEffect> AEArgs = CE.getArgs();
@@ -1811,7 +1811,7 @@ private:
OS.write_escaped(Text) << "\",\n";
}
};
-
+
void insert(SourceLocation Loc, StringRef Text) override {
EntryWriter Writer(SourceMgr, OS);
Writer.writeLoc(Loc);
@@ -1835,7 +1835,7 @@ private:
} // end anonymous namespace
void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
-
+
TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
@@ -1846,7 +1846,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
AnnotateImplicitBridging(Ctx);
}
-
+
if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
if (canModify(CDecl))
migrateObjCContainerDecl(Ctx, CDecl);
@@ -1911,7 +1911,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
canModify(FD))
migrateCFAnnotation(Ctx, FD);
}
-
+
if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
bool CanModify = canModify(CDecl);
// migrate methods which can have instancetype as their result type.
@@ -1934,7 +1934,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
AnnotateImplicitBridging(Ctx);
}
-
+
if (IsOutputFile) {
std::error_code EC;
llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
index 9a51690c0ce7..9e4cb3f4cd83 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
@@ -81,7 +81,7 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath,
for (ArrayRef<StoredDiagnostic>::iterator
DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) {
-
+
const StoredDiagnostic &D = *DI;
if (D.getLevel() == DiagnosticsEngine::Ignored)
@@ -107,8 +107,7 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath,
o << " <key>ranges</key>\n";
o << " <array>\n";
for (auto &R : D.getRanges()) {
- CharSourceRange ExpansionRange(SM.getExpansionRange(R.getAsRange()),
- R.isTokenRange());
+ CharSourceRange ExpansionRange = SM.getExpansionRange(R);
EmitRange(o, SM, Lexer::getAsCharRange(ExpansionRange, SM, LangOpts),
FM, 4);
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp
index 80bfd22d6258..d2b4de4891c3 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp
@@ -65,7 +65,7 @@ public:
}
}
}
-
+
return true;
}
};
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
index a8a99fa712a3..2d35655d186f 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -80,7 +80,7 @@ public:
Body = body;
TraverseStmt(body);
}
-
+
~AutoreleasePoolRewriter() {
SmallVector<VarDecl *, 8> VarsToHandle;
@@ -174,7 +174,7 @@ public:
PoolVarInfo &info = PoolVars[VD];
info.Dcl = DclS;
collectRefs(VD, S, info.Refs);
- // Does this statement follow the pattern:
+ // Does this statement follow the pattern:
// NSAutoreleasePool * pool = [NSAutoreleasePool new];
if (isPoolCreation(VD->getInit())) {
Scopes.push_back(PoolScope());
@@ -188,7 +188,7 @@ public:
} else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(child)) {
if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(bop->getLHS())) {
if (VarDecl *VD = dyn_cast<VarDecl>(dref->getDecl())) {
- // Does this statement follow the pattern:
+ // Does this statement follow the pattern:
// pool = [NSAutoreleasePool new];
if (isNSAutoreleasePool(VD->getType()) &&
isPoolCreation(bop->getRHS())) {
@@ -311,7 +311,7 @@ private:
scope.IsFollowedBySimpleReturnStmt = true;
++SI; // the return will be included in scope, don't check it.
}
-
+
for (; SI != SE; ++SI) {
nameUsedOutsideScope = !NameReferenceChecker(Pass.Ctx, scope,
referenceLoc,
@@ -415,7 +415,7 @@ private:
IdentifierInfo *PoolII;
Selector DrainSel;
-
+
struct PoolVarInfo {
DeclStmt *Dcl;
ExprSet Refs;
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
index fac6a84c45e5..85bdabb50461 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
@@ -43,11 +43,11 @@ class RootBlockObjCVarRewriter :
class BlockVarChecker : public RecursiveASTVisitor<BlockVarChecker> {
VarDecl *Var;
-
+
typedef RecursiveASTVisitor<BlockVarChecker> base;
public:
BlockVarChecker(VarDecl *var) : Var(var) { }
-
+
bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) {
if (DeclRefExpr *
ref = dyn_cast<DeclRefExpr>(castE->getSubExpr())) {
@@ -77,7 +77,7 @@ public:
bool VisitBlockDecl(BlockDecl *block) {
SmallVector<VarDecl *, 4> BlockVars;
-
+
for (const auto &I : block->captures()) {
VarDecl *var = I.getVariable();
if (I.isByRef() &&
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index d45d5d60b78a..0327b0def1e6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -73,7 +73,7 @@ static bool isEmptyARCMTMacroStatement(NullStmt *S,
namespace {
-/// \brief Returns true if the statement became empty due to previous
+/// Returns true if the statement became empty due to previous
/// transformations.
class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
ASTContext &Ctx;
@@ -208,7 +208,7 @@ static void cleanupDeallocOrFinalize(MigrationPass &pass) {
for (auto *MD : I->instance_methods()) {
if (!MD->hasBody())
continue;
-
+
if (MD->getMethodFamily() == OMF_dealloc) {
DeallocM = MD;
} else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp
index 2ae6b78a4634..fb45cd92c1f6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp
@@ -23,7 +23,7 @@ using namespace trans;
namespace {
-/// \brief Collects all the places where GC attributes __strong/__weak occur.
+/// Collects all the places where GC attributes __strong/__weak occur.
class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
MigrationContext &MigrateCtx;
bool FullyMigratable;
@@ -48,7 +48,7 @@ public:
return true;
SaveAndRestore<bool> Save(FullyMigratable, isMigratable(D));
-
+
if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) {
lookForAttribute(PropD, PropD->getTypeSourceInfo());
AllProps.push_back(PropD);
@@ -92,7 +92,7 @@ public:
ASTContext &Ctx = MigrateCtx.Pass.Ctx;
SourceManager &SM = Ctx.getSourceManager();
if (Loc.isMacroID())
- Loc = SM.getImmediateExpansionRange(Loc).first;
+ Loc = SM.getImmediateExpansionRange(Loc).getBegin();
SmallString<32> Buf;
bool Invalid = false;
StringRef Spell = Lexer::getSpelling(
@@ -107,7 +107,7 @@ public:
Kind = MigrationContext::GCAttrOccurrence::Weak;
else
return false;
-
+
MigrateCtx.AttrSet.insert(RawLoc);
MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence());
MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back();
@@ -164,7 +164,7 @@ public:
for (auto I : D->redecls())
if (!isInMainFile(I->getLocation()))
return false;
-
+
return true;
}
@@ -287,7 +287,8 @@ static void checkAllAtProps(MigrationContext &MigrateCtx,
SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
if (Loc.isMacroID())
Loc = MigrateCtx.Pass.Ctx.getSourceManager()
- .getImmediateExpansionRange(Loc).first;
+ .getImmediateExpansionRange(Loc)
+ .getBegin();
TA.remove(Loc);
TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
index 389b03666bf7..912f77aeb789 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
@@ -47,7 +47,7 @@ class PropertiesRewriter {
MigrationContext &MigrateCtx;
MigrationPass &Pass;
ObjCImplementationDecl *CurImplD;
-
+
enum PropActionKind {
PropAction_None,
PropAction_RetainReplacedWithStrong,
@@ -118,7 +118,7 @@ public:
AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
if (findAtLoc == AtProps.end())
continue;
-
+
PropsTy &props = findAtLoc->second;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
if (I->PropD == propD) {
@@ -137,7 +137,7 @@ public:
continue;
if (hasIvarWithExplicitARCOwnership(props))
continue;
-
+
Transaction Trans(Pass.TA);
rewriteProperty(props, atLoc);
}
@@ -170,7 +170,7 @@ private:
void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
-
+
if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
ObjCPropertyDecl::OBJC_PR_strong |
@@ -215,7 +215,7 @@ private:
void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
/*AllowOnUnknownClass=*/Pass.isGCMigration());
- const char *toWhich =
+ const char *toWhich =
(Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
(canUseWeak ? "weak" : "unsafe_unretained");
@@ -227,7 +227,7 @@ private:
if (isUserDeclared(I->IvarD)) {
if (I->IvarD &&
I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
- const char *toWhich =
+ const char *toWhich =
(Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
(canUseWeak ? "__weak " : "__unsafe_unretained ");
Pass.TA.insert(I->IvarD->getLocation(), toWhich);
@@ -327,10 +327,10 @@ private:
}
}
- return false;
+ return false;
}
- // \brief Returns true if all declarations in the @property have GC __weak.
+ // Returns true if all declarations in the @property have GC __weak.
bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
if (!Pass.isGCMigration())
return false;
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProtectedScope.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProtectedScope.cpp
index 0fcbcbedfe04..1bb4c1f4e449 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProtectedScope.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProtectedScope.cpp
@@ -46,7 +46,7 @@ struct CaseInfo {
St_CannotFix,
St_Fixed
} State;
-
+
CaseInfo() : SC(nullptr), State(St_Unchecked) {}
CaseInfo(SwitchCase *S, SourceRange Range)
: SC(S), Range(Range), State(St_Unchecked) {}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index 389f3655aa52..c411044ecde3 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -158,7 +158,7 @@ public:
}
private:
- /// \brief Checks for idioms where an unused -autorelease is common.
+ /// Checks for idioms where an unused -autorelease is common.
///
/// Returns true for this idiom which is common in property
/// setters:
@@ -251,7 +251,7 @@ private:
while (OuterS && (isa<ParenExpr>(OuterS) ||
isa<CastExpr>(OuterS) ||
isa<ExprWithCleanups>(OuterS)));
-
+
if (!OuterS)
return std::make_pair(prevStmt, nextStmt);
@@ -309,7 +309,7 @@ private:
return nullptr;
}
- /// \brief Check if the retain/release is due to a GCD/XPC macro that are
+ /// Check if the retain/release is due to a GCD/XPC macro that are
/// defined as:
///
/// #define dispatch_retain(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); (void)[_o retain]; })
@@ -419,7 +419,7 @@ private:
bool isRemovable(Expr *E) const {
return Removables.count(E);
}
-
+
bool tryRemoving(Expr *E) const {
if (isRemovable(E)) {
Pass.TA.removeStmt(E);
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 7ca49558a7f0..66167d37ac95 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -97,7 +97,7 @@ public:
if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
return true;
-
+
bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
bool castRetainable = castType->isObjCIndirectLifetimeType();
if (exprRetainable == castRetainable) return true;
@@ -153,7 +153,7 @@ private:
// Do not migrate to couple of bridge transfer casts which
// cancel each other out. Leave it unchanged so error gets user
// attention instead.
- if (FD->getName() == "CFRetain" &&
+ if (FD->getName() == "CFRetain" &&
FD->getNumParams() == 1 &&
FD->getParent()->isTranslationUnit() &&
FD->isExternallyVisible()) {
@@ -283,13 +283,12 @@ private:
SourceManager &SM = Pass.Ctx.getSourceManager();
SourceLocation Loc = E->getExprLoc();
assert(Loc.isMacroID());
- SourceLocation MacroBegin, MacroEnd;
- std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
+ CharSourceRange MacroRange = SM.getImmediateExpansionRange(Loc);
SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
- Outer = SourceRange(MacroBegin, MacroEnd);
+ Outer = MacroRange.getAsRange();
Inner = SourceRange(InnerBegin, InnerEnd);
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index 76ce0ec90db3..220102ec49ce 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -56,7 +56,7 @@ public:
bool BackedBySynthesizeSetter = false;
for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
- P = SynthesizedProperties.begin(),
+ P = SynthesizedProperties.begin(),
E = SynthesizedProperties.end(); P != E; ++P) {
ObjCPropertyDecl *PropDecl = P->first;
if (PropDecl->getSetterName() == ME->getSelector()) {
@@ -66,11 +66,11 @@ public:
}
if (!BackedBySynthesizeSetter)
return true;
-
+
// Remove the setter message if RHS is null
Transaction Trans(TA);
Expr *RHS = ME->getArg(0);
- bool RHSIsNull =
+ bool RHSIsNull =
RHS->isNullPointerConstant(Ctx,
Expr::NPC_ValueDependentIsNull);
if (RHSIsNull && isRemovable(ME))
@@ -119,10 +119,10 @@ public:
ObjCPropertyDecl *PD = PID->getPropertyDecl();
ObjCMethodDecl *setterM = PD->getSetterMethodDecl();
if (!(setterM && setterM->isDefined())) {
- ObjCPropertyDecl::PropertyAttributeKind AttrKind =
+ ObjCPropertyDecl::PropertyAttributeKind AttrKind =
PD->getPropertyAttributes();
- if (AttrKind &
- (ObjCPropertyDecl::OBJC_PR_retain |
+ if (AttrKind &
+ (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy |
ObjCPropertyDecl::OBJC_PR_strong))
SynthesizedProperties[PD] = PID;
@@ -173,7 +173,7 @@ private:
return false;
bool IvarBacksPropertySynthesis = false;
for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
- P = SynthesizedProperties.begin(),
+ P = SynthesizedProperties.begin(),
E = SynthesizedProperties.end(); P != E; ++P) {
ObjCPropertyImplDecl *PropImpDecl = P->second;
if (PropImpDecl && PropImpDecl->getPropertyIvarDecl() == IVDecl) {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
index 4f3fb5845925..3f79cc441e85 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
@@ -19,7 +19,7 @@ using namespace arcmt;
namespace {
-/// \brief Collects transformations and merges them before applying them with
+/// Collects transformations and merges them before applying them with
/// with applyRewrites(). E.g. if the same source range
/// is requested to be removed twice, only one rewriter remove will be invoked.
/// Rewrites happen in "transactions"; if one rewrite in the transaction cannot
@@ -61,7 +61,7 @@ class TransformActionsImpl {
Range_ExtendsEnd
};
- /// \brief A range to remove. It is a character range.
+ /// A range to remove. It is a character range.
struct CharRange {
FullSourceLoc Begin, End;
@@ -76,7 +76,7 @@ class TransformActionsImpl {
End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
}
assert(Begin.isValid() && End.isValid());
- }
+ }
RangeComparison compareWith(const CharRange &RHS) const {
if (End.isBeforeInTranslationUnitThan(RHS.Begin))
@@ -94,7 +94,7 @@ class TransformActionsImpl {
else
return Range_ExtendsEnd;
}
-
+
static RangeComparison compare(SourceRange LHS, SourceRange RHS,
SourceManager &SrcMgr, Preprocessor &PP) {
return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP)
@@ -107,7 +107,7 @@ class TransformActionsImpl {
typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
InsertsMap;
InsertsMap Inserts;
- /// \brief A list of ranges to remove. They are always sorted and they never
+ /// A list of ranges to remove. They are always sorted and they never
/// intersect with each other.
std::list<CharRange> Removals;
@@ -115,7 +115,7 @@ class TransformActionsImpl {
std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges;
- /// \brief Keeps text passed to transformation methods.
+ /// Keeps text passed to transformation methods.
llvm::StringMap<bool> UniqueText;
public:
@@ -167,12 +167,12 @@ private:
void addRemoval(CharSourceRange range);
void addInsertion(SourceLocation loc, StringRef text);
- /// \brief Stores text passed to the transformation methods to keep the string
+ /// Stores text passed to the transformation methods to keep the string
/// "alive". Since the vast majority of text will be the same, we also unique
/// the strings using a StringMap.
StringRef getUniqueText(StringRef text);
- /// \brief Computes the source location just past the end of the token at
+ /// Computes the source location just past the end of the token at
/// the given source location. If the location points at a macro, the whole
/// macro expansion is skipped.
static SourceLocation getLocForEndOfToken(SourceLocation loc,
@@ -485,7 +485,7 @@ void TransformActionsImpl::commitReplaceText(SourceLocation loc,
SourceLocation afterText = loc.getLocWithOffset(text.size());
addRemoval(CharSourceRange::getCharRange(loc, afterText));
- commitInsert(loc, replacementText);
+ commitInsert(loc, replacementText);
}
void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
@@ -577,21 +577,25 @@ void TransformActionsImpl::applyRewrites(
}
}
-/// \brief Stores text passed to the transformation methods to keep the string
+/// Stores text passed to the transformation methods to keep the string
/// "alive". Since the vast majority of text will be the same, we also unique
/// the strings using a StringMap.
StringRef TransformActionsImpl::getUniqueText(StringRef text) {
return UniqueText.insert(std::make_pair(text, false)).first->first();
}
-/// \brief Computes the source location just past the end of the token at
+/// Computes the source location just past the end of the token at
/// the given source location. If the location points at a macro, the whole
/// macro expansion is skipped.
SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
SourceManager &SM,
Preprocessor &PP) {
- if (loc.isMacroID())
- loc = SM.getExpansionRange(loc).second;
+ if (loc.isMacroID()) {
+ CharSourceRange Exp = SM.getExpansionRange(loc);
+ if (Exp.isCharRange())
+ return Exp.getEnd();
+ loc = Exp.getEnd();
+ }
return PP.getLocForEndOfToken(loc);
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
index cb96a547fbac..4a7af2858879 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
@@ -111,7 +111,7 @@ bool trans::isPlusOne(const Expr *E) {
return implCE && implCE->getCastKind() == CK_ARCConsumeObject;
}
-/// \brief 'Loc' is the end of a statement range. This returns the location
+/// 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
@@ -123,7 +123,7 @@ SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
return SemiLoc.getLocWithOffset(1);
}
-/// \brief \arg Loc is the end of a statement range. This returns the location
+/// \arg Loc is the end of a statement range. This returns the location
/// of the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
@@ -203,7 +203,7 @@ bool trans::isGlobalVar(Expr *E) {
return isGlobalVar(condOp->getTrueExpr()) &&
isGlobalVar(condOp->getFalseExpr());
- return false;
+ return false;
}
StringRef trans::getNilString(MigrationPass &Pass) {
@@ -240,9 +240,9 @@ class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
public:
RemovablesCollector(ExprSet &removables)
: Removables(removables) { }
-
+
bool shouldWalkTypesOfTypeLocs() const { return false; }
-
+
bool TraverseStmtExpr(StmtExpr *E) {
CompoundStmt *S = E->getSubStmt();
for (CompoundStmt::body_iterator
@@ -253,40 +253,40 @@ public:
}
return true;
}
-
+
bool VisitCompoundStmt(CompoundStmt *S) {
for (auto *I : S->body())
mark(I);
return true;
}
-
+
bool VisitIfStmt(IfStmt *S) {
mark(S->getThen());
mark(S->getElse());
return true;
}
-
+
bool VisitWhileStmt(WhileStmt *S) {
mark(S->getBody());
return true;
}
-
+
bool VisitDoStmt(DoStmt *S) {
mark(S->getBody());
return true;
}
-
+
bool VisitForStmt(ForStmt *S) {
mark(S->getInit());
mark(S->getInc());
mark(S->getBody());
return true;
}
-
+
private:
void mark(Stmt *S) {
if (!S) return;
-
+
while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
S = Label->getSubStmt();
S = S->IgnoreImplicit();
@@ -408,12 +408,12 @@ bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
return false;
lexer.LexFromRawLexer(tok);
if (tok.isNot(tok::l_paren)) return false;
-
+
Token BeforeTok = tok;
Token AfterTok;
AfterTok.startToken();
SourceLocation AttrLoc;
-
+
lexer.LexFromRawLexer(tok);
if (tok.is(tok::r_paren))
return false;
@@ -454,7 +454,7 @@ bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
return true;
}
-
+
return false;
}
@@ -493,7 +493,7 @@ bool MigrationContext::addPropertyAttribute(StringRef attr,
Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
return true;
}
-
+
lexer.LexFromRawLexer(tok);
if (tok.is(tok::r_paren)) {
Pass.TA.insert(tok.getLocation(), attr);
@@ -520,7 +520,7 @@ static void GCRewriteFinalize(MigrationPass &pass) {
DeclContext *DC = Ctx.getTranslationUnitDecl();
Selector FinalizeSel =
Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
-
+
typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
impl_iterator;
for (impl_iterator I = impl_iterator(DC->decls_begin()),
@@ -528,11 +528,11 @@ static void GCRewriteFinalize(MigrationPass &pass) {
for (const auto *MD : I->instance_methods()) {
if (!MD->hasBody())
continue;
-
+
if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
const ObjCMethodDecl *FinalizeM = MD;
Transaction Trans(TA);
- TA.insert(FinalizeM->getSourceRange().getBegin(),
+ TA.insert(FinalizeM->getSourceRange().getBegin(),
"#if !__has_feature(objc_arc)\n");
CharSourceRange::getTokenRange(FinalizeM->getSourceRange());
const SourceManager &SM = pass.Ctx.getSourceManager();
@@ -540,10 +540,10 @@ static void GCRewriteFinalize(MigrationPass &pass) {
bool Invalid;
std::string str = "\n#endif\n";
str += Lexer::getSourceText(
- CharSourceRange::getTokenRange(FinalizeM->getSourceRange()),
+ CharSourceRange::getTokenRange(FinalizeM->getSourceRange()),
SM, LangOpts, &Invalid);
TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str);
-
+
break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
index 7e3dd34e7607..bafe9fc52a27 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
@@ -89,7 +89,7 @@ public:
SourceLocation Loc;
QualType ModifiedType;
Decl *Dcl;
- /// \brief true if the attribute is owned, e.g. it is in a body and not just
+ /// true if the attribute is owned, e.g. it is in a body and not just
/// in an interface.
bool FullyMigratable;
};
@@ -97,13 +97,13 @@ public:
llvm::DenseSet<unsigned> AttrSet;
llvm::DenseSet<unsigned> RemovedAttrSet;
- /// \brief Set of raw '@' locations for 'assign' properties group that contain
+ /// Set of raw '@' locations for 'assign' properties group that contain
/// GC __weak.
llvm::DenseSet<unsigned> AtPropsWeak;
explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
~MigrationContext();
-
+
typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
traverser_iterator traversers_begin() { return Traversers.begin(); }
traverser_iterator traversers_end() { return Traversers.end(); }
@@ -156,21 +156,21 @@ public:
// Helpers.
//===----------------------------------------------------------------------===//
-/// \brief Determine whether we can add weak to the given type.
+/// Determine whether we can add weak to the given type.
bool canApplyWeak(ASTContext &Ctx, QualType type,
bool AllowOnUnknownClass = false);
bool isPlusOneAssign(const BinaryOperator *E);
bool isPlusOne(const Expr *E);
-/// \brief 'Loc' is the end of a statement range. This returns the location
+/// 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,
bool IsDecl = false);
-/// \brief 'Loc' is the end of a statement range. This returns the location
+/// 'Loc' is the end of a statement range. This returns the location
/// of the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
@@ -179,7 +179,7 @@ SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,
bool hasSideEffects(Expr *E, ASTContext &Ctx);
bool isGlobalVar(Expr *E);
-/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
+/// Returns "nil" or "0" if 'nil' macro is not actually defined.
StringRef getNilString(MigrationPass &Pass);
template <typename BODY_TRANS>
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp
index 488ad3373ca3..c45b52a65a4d 100644
--- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp
@@ -23,14 +23,57 @@ using namespace clang;
namespace {
struct LVBase {
- llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
+ APValue::LValueBase Base;
CharUnits Offset;
unsigned PathLength;
- unsigned CallIndex;
- bool IsNullPtr;
+ bool IsNullPtr : 1;
+ bool IsOnePastTheEnd : 1;
};
}
+void *APValue::LValueBase::getOpaqueValue() const {
+ return Ptr.getOpaqueValue();
+}
+
+bool APValue::LValueBase::isNull() const {
+ return Ptr.isNull();
+}
+
+APValue::LValueBase::operator bool () const {
+ return static_cast<bool>(Ptr);
+}
+
+clang::APValue::LValueBase
+llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
+ return clang::APValue::LValueBase(
+ DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(),
+ DenseMapInfo<unsigned>::getEmptyKey(),
+ DenseMapInfo<unsigned>::getEmptyKey());
+}
+
+clang::APValue::LValueBase
+llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
+ return clang::APValue::LValueBase(
+ DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(),
+ DenseMapInfo<unsigned>::getTombstoneKey(),
+ DenseMapInfo<unsigned>::getTombstoneKey());
+}
+
+unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue(
+ const clang::APValue::LValueBase &Base) {
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Base.getOpaqueValue());
+ ID.AddInteger(Base.getCallIndex());
+ ID.AddInteger(Base.getVersion());
+ return ID.ComputeHash();
+}
+
+bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual(
+ const clang::APValue::LValueBase &LHS,
+ const clang::APValue::LValueBase &RHS) {
+ return LHS == RHS;
+}
+
struct APValue::LV : LVBase {
static const unsigned InlinePathSpace =
(DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
@@ -150,11 +193,10 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
MakeLValue();
if (RHS.hasLValuePath())
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
- RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(),
- RHS.isNullPointer());
+ RHS.isLValueOnePastTheEnd(), RHS.isNullPointer());
else
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
- RHS.getLValueCallIndex(), RHS.isNullPointer());
+ RHS.isNullPointer());
break;
case Array:
MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
@@ -552,12 +594,12 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
const APValue::LValueBase APValue::getLValueBase() const {
assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer();
+ return ((const LV*)(const void*)Data.buffer)->Base;
}
bool APValue::isLValueOnePastTheEnd() const {
assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt();
+ return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd;
}
CharUnits &APValue::getLValueOffset() {
@@ -578,7 +620,12 @@ ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
unsigned APValue::getLValueCallIndex() const {
assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const char*)Data.buffer)->CallIndex;
+ return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex();
+}
+
+unsigned APValue::getLValueVersion() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const char*)Data.buffer)->Base.getVersion();
}
bool APValue::isNullPointer() const {
@@ -587,26 +634,24 @@ bool APValue::isNullPointer() const {
}
void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
- unsigned CallIndex, bool IsNullPtr) {
+ bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
- LVal.BaseAndIsOnePastTheEnd.setPointer(B);
- LVal.BaseAndIsOnePastTheEnd.setInt(false);
+ LVal.Base = B;
+ LVal.IsOnePastTheEnd = false;
LVal.Offset = O;
- LVal.CallIndex = CallIndex;
LVal.resizePath((unsigned)-1);
LVal.IsNullPtr = IsNullPtr;
}
void APValue::setLValue(LValueBase B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
- unsigned CallIndex, bool IsNullPtr) {
+ bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
- LVal.BaseAndIsOnePastTheEnd.setPointer(B);
- LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
+ LVal.Base = B;
+ LVal.IsOnePastTheEnd = IsOnePastTheEnd;
LVal.Offset = O;
- LVal.CallIndex = CallIndex;
LVal.resizePath(Path.size());
memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
LVal.IsNullPtr = IsNullPtr;
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index c73ae9efe170..c085f52cae31 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -47,6 +47,7 @@
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
@@ -130,35 +131,34 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
return nullptr;
// User can not attach documentation to implicit instantiations.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return nullptr;
}
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->isStaticDataMember() &&
VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return nullptr;
}
- if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
+ if (const auto *CRD = dyn_cast<CXXRecordDecl>(D)) {
if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return nullptr;
}
- if (const ClassTemplateSpecializationDecl *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
TemplateSpecializationKind TSK = CTSD->getSpecializationKind();
if (TSK == TSK_ImplicitInstantiation ||
TSK == TSK_Undeclared)
return nullptr;
}
- if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ if (const auto *ED = dyn_cast<EnumDecl>(D)) {
if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return nullptr;
}
- if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ if (const auto *TD = dyn_cast<TagDecl>(D)) {
// When tag declaration (but not definition!) is part of the
// decl-specifier-seq of some other declaration, it doesn't get comment
if (TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition())
@@ -201,7 +201,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
// declared via a macro. Try using declaration's starting location as
// the "declaration location".
DeclLoc = D->getLocStart();
- } else if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ } else if (const auto *TD = dyn_cast<TagDecl>(D)) {
// If location of the tag decl is inside a macro, but the spelling of
// the tag name comes from a macro argument, it looks like a special
// macro like NS_ENUM is being used to define the tag decl. In that
@@ -226,8 +226,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
// for is usually among the last two comments we parsed -- check them
// first.
RawComment CommentAtDeclLoc(
- SourceMgr, SourceRange(DeclLoc), false,
- LangOpts.CommentOpts.ParseAllComments);
+ SourceMgr, SourceRange(DeclLoc), LangOpts.CommentOpts, false);
BeforeThanCompare<RawComment> Compare(SourceMgr);
ArrayRef<RawComment *>::iterator MaybeBeforeDecl = RawComments.end() - 1;
bool Found = Compare(*MaybeBeforeDecl, &CommentAtDeclLoc);
@@ -253,7 +252,8 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
// First check whether we have a trailing comment.
if (Comment != RawComments.end() &&
- (*Comment)->isDocumentation() && (*Comment)->isTrailingComment() &&
+ ((*Comment)->isDocumentation() || LangOpts.CommentOpts.ParseAllComments)
+ && (*Comment)->isTrailingComment() &&
(isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D) ||
isa<ObjCMethodDecl>(D) || isa<ObjCPropertyDecl>(D))) {
std::pair<FileID, unsigned> CommentBeginDecomp
@@ -275,7 +275,9 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
--Comment;
// Check that we actually have a non-member Doxygen comment.
- if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment())
+ if (!((*Comment)->isDocumentation() ||
+ LangOpts.CommentOpts.ParseAllComments) ||
+ (*Comment)->isTrailingComment())
return nullptr;
// Decompose the end of the comment.
@@ -310,7 +312,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
/// refer to the actual template.
/// If we have an implicit instantiation, adjust 'D' to refer to template.
static const Decl *adjustDeclToTemplate(const Decl *D) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Is this function declaration part of a function template?
if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
return FTD;
@@ -330,7 +332,7 @@ static const Decl *adjustDeclToTemplate(const Decl *D) {
return D;
}
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
// Static data member is instantiated from a member definition of a class
// template?
if (VD->isStaticDataMember())
@@ -339,15 +341,14 @@ static const Decl *adjustDeclToTemplate(const Decl *D) {
return D;
}
- if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
+ if (const auto *CRD = dyn_cast<CXXRecordDecl>(D)) {
// Is this class declaration part of a class template?
if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate())
return CTD;
// Class is an implicit instantiation of a class template or partial
// specialization?
- if (const ClassTemplateSpecializationDecl *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(CRD)) {
+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CRD)) {
if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation)
return D;
llvm::PointerUnion<ClassTemplateDecl *,
@@ -366,7 +367,7 @@ static const Decl *adjustDeclToTemplate(const Decl *D) {
return D;
}
- if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ if (const auto *ED = dyn_cast<EnumDecl>(D)) {
// Enum is instantiated from a member definition of a class template?
if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum())
return MemberDecl;
@@ -428,7 +429,7 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(
}
// If we found a comment, it should be a documentation comment.
- assert(!RC || RC->isDocumentation());
+ assert(!RC || RC->isDocumentation() || LangOpts.CommentOpts.ParseAllComments);
if (OriginalDecl)
*OriginalDecl = OriginalDeclForRC;
@@ -451,7 +452,7 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(
static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod,
SmallVectorImpl<const NamedDecl *> &Redeclared) {
const DeclContext *DC = ObjCMethod->getDeclContext();
- if (const ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(DC)) {
+ if (const auto *IMD = dyn_cast<ObjCImplDecl>(DC)) {
const ObjCInterfaceDecl *ID = IMD->getClassInterface();
if (!ID)
return;
@@ -467,7 +468,7 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod,
comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC,
const Decl *D) const {
- comments::DeclInfo *ThisDeclInfo = new (*this) comments::DeclInfo;
+ auto *ThisDeclInfo = new (*this) comments::DeclInfo;
ThisDeclInfo->CommentDecl = D;
ThisDeclInfo->IsFilled = false;
ThisDeclInfo->fill();
@@ -491,11 +492,11 @@ comments::FullComment *ASTContext::getCommentForDecl(
if (D->isInvalidDecl())
return nullptr;
D = adjustDeclToTemplate(D);
-
+
const Decl *Canonical = D->getCanonicalDecl();
llvm::DenseMap<const Decl *, comments::FullComment *>::iterator Pos =
ParsedComments.find(Canonical);
-
+
if (Pos != ParsedComments.end()) {
if (Canonical != D) {
comments::FullComment *FC = Pos->second;
@@ -504,14 +505,14 @@ comments::FullComment *ASTContext::getCommentForDecl(
}
return Pos->second;
}
-
+
const Decl *OriginalDecl;
-
+
const RawComment *RC = getRawCommentForAnyRedecl(D, &OriginalDecl);
if (!RC) {
if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
SmallVector<const NamedDecl*, 8> Overridden;
- const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D);
+ const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
if (OMD && OMD->isPropertyAccessor())
if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
if (comments::FullComment *FC = getCommentForDecl(PDecl, PP))
@@ -523,28 +524,28 @@ comments::FullComment *ASTContext::getCommentForDecl(
if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP))
return cloneFullComment(FC, D);
}
- else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ else if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
// Attach any tag type's documentation to its typedef if latter
// does not have one of its own.
QualType QT = TD->getUnderlyingType();
- if (const TagType *TT = QT->getAs<TagType>())
+ if (const auto *TT = QT->getAs<TagType>())
if (const Decl *TD = TT->getDecl())
if (comments::FullComment *FC = getCommentForDecl(TD, PP))
return cloneFullComment(FC, D);
}
- else if (const ObjCInterfaceDecl *IC = dyn_cast<ObjCInterfaceDecl>(D)) {
+ else if (const auto *IC = dyn_cast<ObjCInterfaceDecl>(D)) {
while (IC->getSuperClass()) {
IC = IC->getSuperClass();
if (comments::FullComment *FC = getCommentForDecl(IC, PP))
return cloneFullComment(FC, D);
}
}
- else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
+ else if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) {
if (const ObjCInterfaceDecl *IC = CD->getClassInterface())
if (comments::FullComment *FC = getCommentForDecl(IC, PP))
return cloneFullComment(FC, D);
}
- else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (!(RD = RD->getDefinition()))
return nullptr;
// Check non-virtual bases.
@@ -557,7 +558,7 @@ comments::FullComment *ASTContext::getCommentForDecl(
if (const CXXRecordDecl *NonVirtualBase = Ty->getAsCXXRecordDecl()) {
if (!(NonVirtualBase= NonVirtualBase->getDefinition()))
continue;
-
+
if (comments::FullComment *FC = getCommentForDecl((NonVirtualBase), PP))
return cloneFullComment(FC, D);
}
@@ -579,7 +580,7 @@ comments::FullComment *ASTContext::getCommentForDecl(
}
return nullptr;
}
-
+
// If the RawComment was attached to other redeclaration of this Decl, we
// should parse the comment in context of that other Decl. This is important
// because comments can contain references to parameter names which can be
@@ -592,8 +593,8 @@ comments::FullComment *ASTContext::getCommentForDecl(
return FC;
}
-void
-ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
+void
+ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *Parm) {
ID.AddInteger(Parm->getDepth());
ID.AddInteger(Parm->getPosition());
@@ -601,16 +602,16 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
TemplateParameterList *Params = Parm->getTemplateParameters();
ID.AddInteger(Params->size());
- for (TemplateParameterList::const_iterator P = Params->begin(),
+ for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
ID.AddInteger(0);
ID.AddBoolean(TTP->isParameterPack());
continue;
}
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
ID.AddInteger(1);
ID.AddBoolean(NTTP->isParameterPack());
ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr());
@@ -621,12 +622,12 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
QualType T = NTTP->getExpansionType(I);
ID.AddPointer(T.getCanonicalType().getAsOpaquePtr());
}
- } else
+ } else
ID.AddBoolean(false);
continue;
}
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+
+ auto *TTP = cast<TemplateTemplateParmDecl>(*P);
ID.AddInteger(2);
Profile(ID, TTP);
}
@@ -643,24 +644,23 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
= CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
if (Canonical)
return Canonical->getParam();
-
+
// Build a canonical template parameter list.
TemplateParameterList *Params = TTP->getTemplateParameters();
SmallVector<NamedDecl *, 4> CanonParams;
CanonParams.reserve(Params->size());
- for (TemplateParameterList::const_iterator P = Params->begin(),
+ for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P))
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P))
CanonParams.push_back(
- TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(),
+ TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
SourceLocation(),
TTP->getDepth(),
TTP->getIndex(), nullptr, false,
TTP->isParameterPack()));
- else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
QualType T = getCanonicalType(NTTP->getType());
TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T);
NonTypeTemplateParmDecl *Param;
@@ -672,7 +672,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
ExpandedTInfos.push_back(
getTrivialTypeSourceInfo(ExpandedTypes.back()));
}
-
+
Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
SourceLocation(),
@@ -704,9 +704,9 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
Expr *const CanonRequiresClause = nullptr;
TemplateTemplateParmDecl *CanonTTP
- = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
+ = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(), TTP->getDepth(),
- TTP->getPosition(),
+ TTP->getPosition(),
TTP->isParameterPack(),
nullptr,
TemplateParameterList::Create(*this, SourceLocation(),
@@ -788,10 +788,12 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
- LangOpts.XRayNeverInstrumentFiles, SM)),
+ LangOpts.XRayNeverInstrumentFiles,
+ LangOpts.XRayAttrListFiles, SM)),
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM),
- CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) {
+ CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
+ CompCategories(this_()), LastSDM(nullptr, 0) {
TUDecl = TranslationUnitDecl::Create(*this);
}
@@ -812,16 +814,16 @@ ASTContext::~ASTContext() {
const ASTRecordLayout*>::iterator
I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; )
// Increment in loop to prevent using deallocated memory.
- if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
+ if (auto *R = const_cast<ASTRecordLayout *>((I++)->second))
R->Destroy(*this);
for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
// Increment in loop to prevent using deallocated memory.
- if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
+ if (auto *R = const_cast<ASTRecordLayout *>((I++)->second))
R->Destroy(*this);
}
-
+
for (llvm::DenseMap<const Decl*, AttrVec*>::iterator A = DeclAttrs.begin(),
AEnd = DeclAttrs.end();
A != AEnd; ++A)
@@ -966,7 +968,7 @@ void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) {
void ASTContext::addModuleInitializer(Module *M, Decl *D) {
// One special case: if we add a module initializer that imports another
// module, and that module's only initializer is an ImportDecl, simplify.
- if (auto *ID = dyn_cast<ImportDecl>(D)) {
+ if (const auto *ID = dyn_cast<ImportDecl>(D)) {
auto It = ModuleInitializers.find(ID->getImportedModule());
// Maybe the ImportDecl does nothing at all. (Common case.)
@@ -997,9 +999,9 @@ void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) {
IDs.begin(), IDs.end());
}
-ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) {
+ArrayRef<Decl *> ASTContext::getModuleInitializers(Module *M) {
auto It = ModuleInitializers.find(M);
- if (It == ModuleInitializers.end())
+ if (It == ModuleInitializers.end())
return None;
auto *Inits = It->second;
@@ -1079,7 +1081,7 @@ TypedefDecl *ASTContext::getUInt128Decl() const {
}
void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
- BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K);
+ auto *Ty = new (*this, TypeAlignment) BuiltinType(K);
R = CanQualType::CreateUnsafe(QualType(Ty, 0));
Types.push_back(Ty);
}
@@ -1096,7 +1098,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
ABI.reset(createCXXABI(Target));
AddrSpaceMap = getAddressSpaceMap(Target, LangOpts);
AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts);
-
+
// C99 6.2.5p19.
InitBuiltinType(VoidTy, BuiltinType::Void);
@@ -1132,6 +1134,32 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// C11 extension ISO/IEC TS 18661-3
InitBuiltinType(Float16Ty, BuiltinType::Float16);
+ // ISO/IEC JTC1 SC22 WG14 N1169 Extension
+ InitBuiltinType(ShortAccumTy, BuiltinType::ShortAccum);
+ InitBuiltinType(AccumTy, BuiltinType::Accum);
+ InitBuiltinType(LongAccumTy, BuiltinType::LongAccum);
+ InitBuiltinType(UnsignedShortAccumTy, BuiltinType::UShortAccum);
+ InitBuiltinType(UnsignedAccumTy, BuiltinType::UAccum);
+ InitBuiltinType(UnsignedLongAccumTy, BuiltinType::ULongAccum);
+ InitBuiltinType(ShortFractTy, BuiltinType::ShortFract);
+ InitBuiltinType(FractTy, BuiltinType::Fract);
+ InitBuiltinType(LongFractTy, BuiltinType::LongFract);
+ InitBuiltinType(UnsignedShortFractTy, BuiltinType::UShortFract);
+ InitBuiltinType(UnsignedFractTy, BuiltinType::UFract);
+ InitBuiltinType(UnsignedLongFractTy, BuiltinType::ULongFract);
+ InitBuiltinType(SatShortAccumTy, BuiltinType::SatShortAccum);
+ InitBuiltinType(SatAccumTy, BuiltinType::SatAccum);
+ InitBuiltinType(SatLongAccumTy, BuiltinType::SatLongAccum);
+ InitBuiltinType(SatUnsignedShortAccumTy, BuiltinType::SatUShortAccum);
+ InitBuiltinType(SatUnsignedAccumTy, BuiltinType::SatUAccum);
+ InitBuiltinType(SatUnsignedLongAccumTy, BuiltinType::SatULongAccum);
+ InitBuiltinType(SatShortFractTy, BuiltinType::SatShortFract);
+ InitBuiltinType(SatFractTy, BuiltinType::SatFract);
+ InitBuiltinType(SatLongFractTy, BuiltinType::SatLongFract);
+ InitBuiltinType(SatUnsignedShortFractTy, BuiltinType::SatUShortFract);
+ InitBuiltinType(SatUnsignedFractTy, BuiltinType::SatUFract);
+ InitBuiltinType(SatUnsignedLongFractTy, BuiltinType::SatULongFract);
+
// GNU extension, 128-bit integers.
InitBuiltinType(Int128Ty, BuiltinType::Int128);
InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128);
@@ -1150,6 +1178,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
WIntTy = getFromTargetType(Target.getWIntType());
+ // C++20 (proposed)
+ InitBuiltinType(Char8Ty, BuiltinType::Char8);
+
if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++
InitBuiltinType(Char16Ty, BuiltinType::Char16);
else // C99
@@ -1211,13 +1242,13 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(OCLQueueTy, BuiltinType::OCLQueue);
InitBuiltinType(OCLReserveIDTy, BuiltinType::OCLReserveID);
}
-
+
// Builtin type for __objc_yes and __objc_no
ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
SignedCharTy : BoolTy);
-
+
ObjCConstantStringType = QualType();
-
+
ObjCSuperType = QualType();
// void * type
@@ -1250,11 +1281,11 @@ AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
void *Mem = Allocate(sizeof(AttrVec));
Result = new (Mem) AttrVec;
}
-
+
return *Result;
}
-/// \brief Erase the attributes corresponding to the given declaration.
+/// Erase the attributes corresponding to the given declaration.
void ASTContext::eraseDeclAttrs(const Decl *D) {
llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D);
if (Pos != DeclAttrs.end()) {
@@ -1276,7 +1307,7 @@ ASTContext::getTemplateOrSpecializationInfo(const VarDecl *Var) {
llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>::iterator Pos =
TemplateOrInstantiation.find(Var);
if (Pos == TemplateOrInstantiation.end())
- return TemplateOrSpecializationInfo();
+ return {};
return Pos->second;
}
@@ -1330,11 +1361,11 @@ void
ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) {
assert((isa<UsingDecl>(Pattern) ||
isa<UnresolvedUsingValueDecl>(Pattern) ||
- isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
+ isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
"pattern decl is not a using decl");
assert((isa<UsingDecl>(Inst) ||
isa<UnresolvedUsingValueDecl>(Inst) ||
- isa<UnresolvedUsingTypenameDecl>(Inst)) &&
+ isa<UnresolvedUsingTypenameDecl>(Inst)) &&
"instantiation did not produce a using decl");
assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
InstantiatedFromUsingDecl[Inst] = Pattern;
@@ -1401,7 +1432,7 @@ ASTContext::overridden_methods(const CXXMethodDecl *Method) const {
return overridden_method_range(Pos->second.begin(), Pos->second.end());
}
-void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
+void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
const CXXMethodDecl *Overridden) {
assert(Method->isCanonicalDecl() && Overridden->isCanonicalDecl());
OverriddenMethods[Method].push_back(Overridden);
@@ -1412,13 +1443,13 @@ void ASTContext::getOverriddenMethods(
SmallVectorImpl<const NamedDecl *> &Overridden) const {
assert(D);
- if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
Overridden.append(overridden_methods_begin(CXXMethod),
overridden_methods_end(CXXMethod));
return;
}
- const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
+ const auto *Method = dyn_cast<ObjCMethodDecl>(D);
if (!Method)
return;
@@ -1435,7 +1466,7 @@ void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
LastLocalImport = Import;
return;
}
-
+
LastLocalImport->NextLocalImport = Import;
LastLocalImport = Import;
}
@@ -1447,7 +1478,7 @@ void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
/// scalar floating point type.
const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
- const BuiltinType *BT = T->getAs<BuiltinType>();
+ const auto *BT = T->getAs<BuiltinType>();
assert(BT && "Not a floating point type!");
switch (BT->getKind()) {
default: llvm_unreachable("Not a floating point type!");
@@ -1482,7 +1513,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
}
}
else if (isa<FieldDecl>(D))
- UseAlignAttrOnly =
+ UseAlignAttrOnly =
D->hasAttr<PackedAttr>() ||
cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>();
@@ -1490,9 +1521,9 @@ 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)) {
+ } else if (const auto *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
- if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
+ if (const auto *RT = T->getAs<ReferenceType>()) {
if (ForAlignof)
T = RT->getPointeeType();
else
@@ -1517,7 +1548,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
if (BaseT.getQualifiers().hasUnaligned())
Align = Target->getCharWidth();
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasGlobalStorage() && !ForAlignof)
Align = std::max(Align, getTargetInfo().getMinGlobalAlign());
}
@@ -1528,7 +1559,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
// a max-field-alignment constraint (#pragma pack). So calculate
// the actual alignment of the field within the struct, and then
// (as we're expected to) constrain that by the alignment of the type.
- if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) {
+ if (const auto *Field = dyn_cast<FieldDecl>(VD)) {
const RecordDecl *Parent = Field->getParent();
// We can only produce a sensible answer if the record is valid.
if (!Parent->isInvalidDecl()) {
@@ -1567,7 +1598,7 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
// of a base-class subobject. We decide whether that's possible
// during class layout, so here we can just trust the layout results.
if (getLangOpts().CPlusPlus) {
- if (const RecordType *RT = T->getAs<RecordType>()) {
+ if (const auto *RT = T->getAs<RecordType>()) {
const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl());
sizeAndAlign.first = layout.getDataSize();
}
@@ -1598,7 +1629,7 @@ static getConstantArrayInfoInChars(const ASTContext &Context,
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(T))
return getConstantArrayInfoInChars(*this, CAT);
TypeInfo Info = getTypeInfo(T);
return std::make_pair(toCharUnitsFromBits(Info.Width),
@@ -1620,7 +1651,7 @@ bool ASTContext::isAlignmentRequired(QualType T) const {
unsigned ASTContext::getTypeAlignIfKnown(QualType T) const {
// An alignment on a typedef overrides anything else.
- if (auto *TT = T->getAs<TypedefType>())
+ if (const auto *TT = T->getAs<TypedefType>())
if (unsigned Align = TT->getDecl()->getMaxAlignment())
return Align;
@@ -1631,12 +1662,12 @@ unsigned ASTContext::getTypeAlignIfKnown(QualType T) const {
// If we had an array type, its element type might be a typedef
// type with an alignment attribute.
- if (auto *TT = T->getAs<TypedefType>())
+ if (const auto *TT = T->getAs<TypedefType>())
if (unsigned Align = TT->getDecl()->getMaxAlignment())
return Align;
// Otherwise, see if the declaration of the type had an attribute.
- if (auto *TT = T->getAs<TagType>())
+ if (const auto *TT = T->getAs<TagType>())
return TT->getDecl()->getMaxAlignment();
return 0;
@@ -1690,7 +1721,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
case Type::ConstantArray: {
- const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
+ const auto *CAT = cast<ConstantArrayType>(T);
TypeInfo EltInfo = getTypeInfo(CAT->getElementType());
uint64_t Size = CAT->getSize().getZExtValue();
@@ -1705,7 +1736,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::ExtVector:
case Type::Vector: {
- const VectorType *VT = cast<VectorType>(T);
+ const auto *VT = cast<VectorType>(T);
TypeInfo EltInfo = getTypeInfo(VT->getElementType());
Width = EltInfo.Width * VT->getNumElements();
Align = Width;
@@ -1738,6 +1769,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::SChar:
+ case BuiltinType::Char8:
Width = Target->getCharWidth();
Align = Target->getCharAlign();
break;
@@ -1779,6 +1811,48 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = 128;
Align = 128; // int128_t is 128-bit aligned on all targets.
break;
+ case BuiltinType::ShortAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatUShortAccum:
+ Width = Target->getShortAccumWidth();
+ Align = Target->getShortAccumAlign();
+ break;
+ case BuiltinType::Accum:
+ case BuiltinType::UAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatUAccum:
+ Width = Target->getAccumWidth();
+ Align = Target->getAccumAlign();
+ break;
+ case BuiltinType::LongAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatULongAccum:
+ Width = Target->getLongAccumWidth();
+ Align = Target->getLongAccumAlign();
+ break;
+ case BuiltinType::ShortFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatUShortFract:
+ Width = Target->getShortFractWidth();
+ Align = Target->getShortFractAlign();
+ break;
+ case BuiltinType::Fract:
+ case BuiltinType::UFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatUFract:
+ Width = Target->getFractWidth();
+ Align = Target->getFractAlign();
+ break;
+ case BuiltinType::LongFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatULongFract:
+ Width = Target->getLongFractWidth();
+ Align = Target->getLongFractAlign();
+ break;
case BuiltinType::Float16:
case BuiltinType::Half:
Width = Target->getHalfWidth();
@@ -1807,7 +1881,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
- Width = Target->getPointerWidth(0);
+ Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
case BuiltinType::OCLSampler:
@@ -1848,7 +1922,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = Target->getPointerAlign(AS);
break;
case Type::MemberPointer: {
- const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ const auto *MPT = cast<MemberPointerType>(T);
CXXABI::MemberPointerInfo MPI = ABI->getMemberPointerInfo(MPT);
Width = MPI.Width;
Align = MPI.Align;
@@ -1868,7 +1942,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Decayed:
return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr());
case Type::ObjCInterface: {
- const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
+ const auto *ObjCI = cast<ObjCInterfaceType>(T);
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
@@ -1876,7 +1950,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::Record:
case Type::Enum: {
- const TagType *TT = cast<TagType>(T);
+ const auto *TT = cast<TagType>(T);
if (TT->getDecl()->isInvalidDecl()) {
Width = 8;
@@ -1884,7 +1958,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
}
- if (const EnumType *ET = dyn_cast<EnumType>(TT)) {
+ if (const auto *ET = dyn_cast<EnumType>(TT)) {
const EnumDecl *ED = ET->getDecl();
TypeInfo Info =
getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
@@ -1895,7 +1969,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
return Info;
}
- const RecordType *RT = cast<RecordType>(TT);
+ const auto *RT = cast<RecordType>(TT);
const RecordDecl *RD = RT->getDecl();
const ASTRecordLayout &Layout = getASTRecordLayout(RD);
Width = toBits(Layout.getSize());
@@ -1910,7 +1984,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Auto:
case Type::DeducedTemplateSpecialization: {
- const DeducedType *A = cast<DeducedType>(T);
+ const auto *A = cast<DeducedType>(T);
assert(!A->getDeducedType().isNull() &&
"cannot request the size of an undeduced or dependent auto type");
return getTypeInfo(A->getDeducedType().getTypePtr());
@@ -1952,10 +2026,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Info.Width;
Align = Info.Align;
- // If the size of the type doesn't exceed the platform's max
- // atomic promotion width, make the size and alignment more
- // favorable to atomic operations:
- if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth()) {
+ if (!Width) {
+ // An otherwise zero-sized type should still generate an
+ // atomic operation.
+ Width = Target->getCharWidth();
+ assert(Align);
+ } else if (Width <= Target->getMaxAtomicPromoteWidth()) {
+ // If the size of the type doesn't exceed the platform's max
+ // atomic promotion width, make the size and alignment more
+ // favorable to atomic operations:
+
// Round the size up to a power of 2.
if (!llvm::isPowerOf2_64(Width))
Width = llvm::NextPowerOf2(Width);
@@ -1976,6 +2056,27 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
return TypeInfo(Width, Align, AlignIsRequired);
}
+unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const {
+ UnadjustedAlignMap::iterator I = MemoizedUnadjustedAlign.find(T);
+ if (I != MemoizedUnadjustedAlign.end())
+ return I->second;
+
+ unsigned UnadjustedAlign;
+ if (const auto *RT = T->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &Layout = getASTRecordLayout(RD);
+ UnadjustedAlign = toBits(Layout.getUnadjustedAlignment());
+ } else if (const auto *ObjCI = T->getAs<ObjCInterfaceType>()) {
+ const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
+ UnadjustedAlign = toBits(Layout.getUnadjustedAlignment());
+ } else {
+ UnadjustedAlign = getTypeAlign(T);
+ }
+
+ MemoizedUnadjustedAlign[T] = UnadjustedAlign;
+ return UnadjustedAlign;
+}
+
unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const {
unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign();
// Target ppc64 with QPX: simd default alignment for pointer to double is 32.
@@ -2006,7 +2107,7 @@ CharUnits ASTContext::getTypeSizeInChars(const Type *T) const {
return getTypeInfoInChars(T).first;
}
-/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
+/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
/// characters. This method does not work on incomplete types.
CharUnits ASTContext::getTypeAlignInChars(QualType T) const {
return toCharUnitsFromBits(getTypeAlign(T));
@@ -2015,6 +2116,16 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const {
return toCharUnitsFromBits(getTypeAlign(T));
}
+/// getTypeUnadjustedAlignInChars - Return the ABI-specified alignment of a
+/// type, in characters, before alignment adustments. This method does
+/// not work on incomplete types.
+CharUnits ASTContext::getTypeUnadjustedAlignInChars(QualType T) const {
+ return toCharUnitsFromBits(getTypeUnadjustedAlign(T));
+}
+CharUnits ASTContext::getTypeUnadjustedAlignInChars(const Type *T) const {
+ return toCharUnitsFromBits(getTypeUnadjustedAlign(T));
+}
+
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
/// type for the current target in bits. This can be different than the ABI
/// alignment in cases where it is beneficial for performance to overalign
@@ -2033,9 +2144,9 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
return ABIAlign;
// Double and long long should be naturally aligned if possible.
- if (const ComplexType *CT = T->getAs<ComplexType>())
+ if (const auto *CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
- if (const EnumType *ET = T->getAs<EnumType>())
+ if (const auto *ET = T->getAs<EnumType>())
T = ET->getDecl()->getIntegerType().getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
@@ -2091,8 +2202,8 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
for (const auto *I : OI->ivars())
Ivars.push_back(I);
} else {
- ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
- for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
+ auto *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+ for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
Iv= Iv->getNextIvar())
Ivars.push_back(Iv);
}
@@ -2102,13 +2213,13 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
/// those inherited by it.
void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
- if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ if (const auto *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
// We can use protocol_iterator here instead of
- // all_referenced_protocol_iterator since we are walking all categories.
+ // all_referenced_protocol_iterator since we are walking all categories.
for (auto *Proto : OI->all_referenced_protocols()) {
CollectInheritedProtocols(Proto, Protocols);
}
-
+
// Categories of this Interface.
for (const auto *Cat : OI->visible_categories())
CollectInheritedProtocols(Cat, Protocols);
@@ -2118,11 +2229,11 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
CollectInheritedProtocols(SD, Protocols);
SD = SD->getSuperClass();
}
- } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
for (auto *Proto : OC->protocols()) {
CollectInheritedProtocols(Proto, Protocols);
}
- } else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ } else if (const auto *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
// Insert the protocol.
if (!Protocols.insert(
const_cast<ObjCProtocolDecl *>(OP->getCanonicalDecl())).second)
@@ -2184,7 +2295,7 @@ structHasUniqueObjectRepresentations(const ASTContext &Context,
}
}
- std::sort(
+ llvm::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()) <
@@ -2264,7 +2375,7 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const {
return true;
if (Ty->isMemberPointerType()) {
- const MemberPointerType *MPT = Ty->getAs<MemberPointerType>();
+ const auto *MPT = Ty->getAs<MemberPointerType>();
return !ABI->getMemberPointerInfo(MPT).HasPadding;
}
@@ -2299,11 +2410,11 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const {
}
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
- unsigned count = 0;
+ unsigned count = 0;
// Count ivars declared in class extension.
for (const auto *Ext : OI->known_extensions())
count += Ext->ivar_size();
-
+
// Count ivar defined in this class's implementation. This
// includes synthesized ivars.
if (ObjCImplementationDecl *ImplDecl = OI->getImplementation())
@@ -2330,7 +2441,7 @@ bool ASTContext::isSentinelNullExpr(const Expr *E) {
return false;
}
-/// \brief Get the implementation of ObjCInterfaceDecl, or nullptr if none
+/// Get the implementation of ObjCInterfaceDecl, or nullptr if none
/// exists.
ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
@@ -2340,7 +2451,7 @@ ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D)
return nullptr;
}
-/// \brief Get the implementation of ObjCCategoryDecl, or nullptr if none
+/// Get the implementation of ObjCCategoryDecl, or nullptr if none
/// exists.
ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
@@ -2350,14 +2461,14 @@ ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
return nullptr;
}
-/// \brief Set the implementation of ObjCInterfaceDecl.
+/// Set the implementation of ObjCInterfaceDecl.
void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD,
ObjCImplementationDecl *ImplD) {
assert(IFaceD && ImplD && "Passed null params");
ObjCImpls[IFaceD] = ImplD;
}
-/// \brief Set the implementation of ObjCCategoryDecl.
+/// Set the implementation of ObjCCategoryDecl.
void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCCategoryImplDecl *ImplD) {
assert(CatD && ImplD && "Passed null params");
@@ -2377,34 +2488,31 @@ void ASTContext::setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
const ObjCInterfaceDecl *ASTContext::getObjContainingInterface(
const NamedDecl *ND) const {
- if (const ObjCInterfaceDecl *ID =
- dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
+ if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
return ID;
- if (const ObjCCategoryDecl *CD =
- dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
+ if (const auto *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
return CD->getClassInterface();
- if (const ObjCImplDecl *IMD =
- dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
+ if (const auto *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
return IMD->getClassInterface();
return nullptr;
}
-/// \brief Get the copy initialization expression of VarDecl, or nullptr if
+/// Get the copy initialization expression of VarDecl, or nullptr if
/// none exists.
Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
assert(VD && "Passed null params");
- assert(VD->hasAttr<BlocksAttr>() &&
+ assert(VD->hasAttr<BlocksAttr>() &&
"getBlockVarCopyInits - not __block var");
llvm::DenseMap<const VarDecl*, Expr*>::iterator
I = BlockVarCopyInits.find(VD);
- return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : nullptr;
+ return (I != BlockVarCopyInits.end()) ? I->second : nullptr;
}
-/// \brief Set the copy inialization expression of a block var decl.
+/// Set the copy inialization expression of a block var decl.
void ASTContext::setBlockVarCopyInits(VarDecl*VD, Expr* Init) {
assert(VD && Init && "Passed null params");
- assert(VD->hasAttr<BlocksAttr>() &&
+ assert(VD->hasAttr<BlocksAttr>() &&
"setBlockVarCopyInits - not __block var");
BlockVarCopyInits[VD] = Init;
}
@@ -2417,7 +2525,7 @@ TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T,
assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
"incorrect data size provided to CreateTypeSourceInfo!");
- TypeSourceInfo *TInfo =
+ auto *TInfo =
(TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8);
new (TInfo) TypeSourceInfo(T);
return TInfo;
@@ -2470,7 +2578,7 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const {
(void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos);
}
- ExtQuals *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals);
+ auto *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals);
ExtQualNodes.InsertNode(eq, insertPos);
return QualType(eq, fastQuals);
}
@@ -2522,7 +2630,7 @@ QualType ASTContext::getObjCGCQualType(QualType T,
if (CanT.getObjCGCAttr() == GCAttr)
return T;
- if (const PointerType *ptr = T->getAs<PointerType>()) {
+ if (const auto *ptr = T->getAs<PointerType>()) {
QualType Pointee = ptr->getPointeeType();
if (Pointee->isAnyPointerType()) {
QualType ResultType = getObjCGCQualType(Pointee, GCAttr);
@@ -2550,10 +2658,10 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
return T;
QualType Result;
- if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) {
+ if (const auto *FNPT = dyn_cast<FunctionNoProtoType>(T)) {
Result = getFunctionNoProtoType(FNPT->getReturnType(), Info);
} else {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ const auto *FPT = cast<FunctionProtoType>(T);
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExtInfo = Info;
Result = getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI);
@@ -2566,7 +2674,7 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD,
QualType ResultType) {
FD = FD->getMostRecentDecl();
while (true) {
- const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>();
+ const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
FD->setType(getFunctionType(ResultType, FPT->getParamTypes(), EPI));
if (FunctionDecl *Next = FD->getPreviousDecl())
@@ -2582,26 +2690,24 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD,
/// specified exception specification. Type sugar that can be present on a
/// declaration of a function with an exception specification is permitted
/// and preserved. Other type sugar (for instance, typedefs) is not.
-static QualType getFunctionTypeWithExceptionSpec(
- ASTContext &Context, QualType Orig,
- const FunctionProtoType::ExceptionSpecInfo &ESI) {
+QualType ASTContext::getFunctionTypeWithExceptionSpec(
+ QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) {
// Might have some parens.
- if (auto *PT = dyn_cast<ParenType>(Orig))
- return Context.getParenType(
- getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI));
+ if (const auto *PT = dyn_cast<ParenType>(Orig))
+ return getParenType(
+ getFunctionTypeWithExceptionSpec(PT->getInnerType(), ESI));
// Might have a calling-convention attribute.
- if (auto *AT = dyn_cast<AttributedType>(Orig))
- return Context.getAttributedType(
+ if (const auto *AT = dyn_cast<AttributedType>(Orig))
+ return getAttributedType(
AT->getAttrKind(),
- getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI),
- getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(),
- ESI));
+ getFunctionTypeWithExceptionSpec(AT->getModifiedType(), ESI),
+ getFunctionTypeWithExceptionSpec(AT->getEquivalentType(), ESI));
// Anything else must be a function type. Rebuild it with the new exception
// specification.
- const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig);
- return Context.getFunctionType(
+ const auto *Proto = cast<FunctionProtoType>(Orig);
+ return getFunctionType(
Proto->getReturnType(), Proto->getParamTypes(),
Proto->getExtProtoInfo().withExceptionSpec(ESI));
}
@@ -2610,8 +2716,8 @@ bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T,
QualType U) {
return hasSameType(T, U) ||
(getLangOpts().CPlusPlus17 &&
- hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None),
- getFunctionTypeWithExceptionSpec(*this, U, EST_None)));
+ hasSameType(getFunctionTypeWithExceptionSpec(T, EST_None),
+ getFunctionTypeWithExceptionSpec(U, EST_None)));
}
void ASTContext::adjustExceptionSpec(
@@ -2619,7 +2725,7 @@ void ASTContext::adjustExceptionSpec(
bool AsWritten) {
// Update the type.
QualType Updated =
- getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI);
+ getFunctionTypeWithExceptionSpec(FD->getType(), ESI);
FD->setType(Updated);
if (!AsWritten)
@@ -2630,7 +2736,7 @@ void ASTContext::adjustExceptionSpec(
// If the type and the type-as-written differ, we may need to update
// the type-as-written too.
if (TSInfo->getType() != FD->getType())
- Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI);
+ Updated = getFunctionTypeWithExceptionSpec(TSInfo->getType(), ESI);
// FIXME: When we get proper type location information for exceptions,
// we'll also have to rebuild the TypeSourceInfo. For now, we just patch
@@ -2664,7 +2770,7 @@ QualType ASTContext::getComplexType(QualType T) const {
ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical);
+ auto *New = new (*this, TypeAlignment) ComplexType(T, Canonical);
Types.push_back(New);
ComplexTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -2692,7 +2798,7 @@ QualType ASTContext::getPointerType(QualType T) const {
PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical);
+ auto *New = new (*this, TypeAlignment) PointerType(T, Canonical);
Types.push_back(New);
PointerTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -2783,8 +2889,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const {
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- BlockPointerType *New
- = new (*this, TypeAlignment) BlockPointerType(T, Canonical);
+ auto *New = new (*this, TypeAlignment) BlockPointerType(T, Canonical);
Types.push_back(New);
BlockPointerTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -2794,9 +2899,9 @@ QualType ASTContext::getBlockPointerType(QualType T) const {
/// lvalue reference to the specified type.
QualType
ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
- assert(getCanonicalType(T) != OverloadTy &&
+ assert(getCanonicalType(T) != OverloadTy &&
"Unresolved overloaded function type");
-
+
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
@@ -2807,7 +2912,7 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
- const ReferenceType *InnerRef = T->getAs<ReferenceType>();
+ const auto *InnerRef = T->getAs<ReferenceType>();
// If the referencee type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
@@ -2822,9 +2927,8 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- LValueReferenceType *New
- = new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
- SpelledAsLValue);
+ auto *New = new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
+ SpelledAsLValue);
Types.push_back(New);
LValueReferenceTypes.InsertNode(New, InsertPos);
@@ -2844,7 +2948,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
- const ReferenceType *InnerRef = T->getAs<ReferenceType>();
+ const auto *InnerRef = T->getAs<ReferenceType>();
// If the referencee type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
@@ -2859,8 +2963,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- RValueReferenceType *New
- = new (*this, TypeAlignment) RValueReferenceType(T, Canonical);
+ auto *New = new (*this, TypeAlignment) RValueReferenceType(T, Canonical);
Types.push_back(New);
RValueReferenceTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -2890,8 +2993,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- MemberPointerType *New
- = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical);
+ auto *New = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical);
Types.push_back(New);
MemberPointerTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -2935,7 +3037,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- ConstantArrayType *New = new(*this,TypeAlignment)
+ auto *New = new (*this,TypeAlignment)
ConstantArrayType(EltTy, Canon, ArySize, ASM, IndexTypeQuals);
ConstantArrayTypes.InsertNode(New, InsertPos);
Types.push_back(New);
@@ -2964,6 +3066,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::Builtin:
case Type::Complex:
case Type::Vector:
+ case Type::DependentVector:
case Type::ExtVector:
case Type::DependentSizedExtVector:
case Type::DependentAddressSpace:
@@ -3007,7 +3110,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
break;
case Type::LValueReference: {
- const LValueReferenceType *lv = cast<LValueReferenceType>(ty);
+ const auto *lv = cast<LValueReferenceType>(ty);
result = getLValueReferenceType(
getVariableArrayDecayedType(lv->getPointeeType()),
lv->isSpelledAsLValue());
@@ -3015,20 +3118,20 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
}
case Type::RValueReference: {
- const RValueReferenceType *lv = cast<RValueReferenceType>(ty);
+ const auto *lv = cast<RValueReferenceType>(ty);
result = getRValueReferenceType(
getVariableArrayDecayedType(lv->getPointeeType()));
break;
}
case Type::Atomic: {
- const AtomicType *at = cast<AtomicType>(ty);
+ const auto *at = cast<AtomicType>(ty);
result = getAtomicType(getVariableArrayDecayedType(at->getValueType()));
break;
}
case Type::ConstantArray: {
- const ConstantArrayType *cat = cast<ConstantArrayType>(ty);
+ const auto *cat = cast<ConstantArrayType>(ty);
result = getConstantArrayType(
getVariableArrayDecayedType(cat->getElementType()),
cat->getSize(),
@@ -3038,7 +3141,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
}
case Type::DependentSizedArray: {
- const DependentSizedArrayType *dat = cast<DependentSizedArrayType>(ty);
+ const auto *dat = cast<DependentSizedArrayType>(ty);
result = getDependentSizedArrayType(
getVariableArrayDecayedType(dat->getElementType()),
dat->getSizeExpr(),
@@ -3050,7 +3153,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
// Turn incomplete types into [*] types.
case Type::IncompleteArray: {
- const IncompleteArrayType *iat = cast<IncompleteArrayType>(ty);
+ const auto *iat = cast<IncompleteArrayType>(ty);
result = getVariableArrayType(
getVariableArrayDecayedType(iat->getElementType()),
/*size*/ nullptr,
@@ -3062,7 +3165,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
// Turn VLA types into [*] types.
case Type::VariableArray: {
- const VariableArrayType *vat = cast<VariableArrayType>(ty);
+ const auto *vat = cast<VariableArrayType>(ty);
result = getVariableArrayType(
getVariableArrayDecayedType(vat->getElementType()),
/*size*/ nullptr,
@@ -3087,7 +3190,7 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
// Since we don't unique expressions, it isn't possible to unique VLA's
// that have an expression provided for their size.
QualType Canon;
-
+
// Be sure to pull qualifiers off the element type.
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
SplitQualType canonSplit = getCanonicalType(EltTy).split();
@@ -3095,8 +3198,8 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
IndexTypeQuals, Brackets);
Canon = getQualifiedType(Canon, canonSplit.Quals);
}
-
- VariableArrayType *New = new(*this, TypeAlignment)
+
+ auto *New = new (*this, TypeAlignment)
VariableArrayType(EltTy, Canon, NumElts, ASM, IndexTypeQuals, Brackets);
VariableArrayTypes.push_back(New);
@@ -3112,7 +3215,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
ArrayType::ArraySizeModifier ASM,
unsigned elementTypeQuals,
SourceRange brackets) const {
- assert((!numElements || numElements->isTypeDependent() ||
+ assert((!numElements || numElements->isTypeDependent() ||
numElements->isValueDependent()) &&
"Size must be type- or value-dependent!");
@@ -3121,7 +3224,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
// initializer. We do no canonicalization here at all, which is okay
// because they can't be used in most locations.
if (!numElements) {
- DependentSizedArrayType *newType
+ auto *newType
= new (*this, TypeAlignment)
DependentSizedArrayType(*this, elementType, QualType(),
numElements, ASM, elementTypeQuals,
@@ -3167,7 +3270,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
// Otherwise, we need to build a type which follows the spelling
// of the element type.
- DependentSizedArrayType *sugaredType
+ auto *sugaredType
= new (*this, TypeAlignment)
DependentSizedArrayType(*this, elementType, canon, numElements,
ASM, elementTypeQuals, brackets);
@@ -3203,7 +3306,7 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType,
assert(!existing && "Shouldn't be in the map!"); (void) existing;
}
- IncompleteArrayType *newType = new (*this, TypeAlignment)
+ auto *newType = new (*this, TypeAlignment)
IncompleteArrayType(elementType, canon, ASM, elementTypeQuals);
IncompleteArrayTypes.InsertNode(newType, insertPos);
@@ -3235,13 +3338,52 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- VectorType *New = new (*this, TypeAlignment)
+ auto *New = new (*this, TypeAlignment)
VectorType(vecType, NumElts, Canonical, VecKind);
VectorTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
}
+QualType
+ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr,
+ SourceLocation AttrLoc,
+ VectorType::VectorKind VecKind) const {
+ llvm::FoldingSetNodeID ID;
+ DependentVectorType::Profile(ID, *this, getCanonicalType(VecType), SizeExpr,
+ VecKind);
+ void *InsertPos = nullptr;
+ DependentVectorType *Canon =
+ DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
+ DependentVectorType *New;
+
+ if (Canon) {
+ New = new (*this, TypeAlignment) DependentVectorType(
+ *this, VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind);
+ } else {
+ QualType CanonVecTy = getCanonicalType(VecType);
+ if (CanonVecTy == VecType) {
+ New = new (*this, TypeAlignment) DependentVectorType(
+ *this, VecType, QualType(), SizeExpr, AttrLoc, VecKind);
+
+ DependentVectorType *CanonCheck =
+ DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CanonCheck &&
+ "Dependent-sized vector_size canonical type broken");
+ (void)CanonCheck;
+ DependentVectorTypes.InsertNode(New, InsertPos);
+ } else {
+ QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
+ SourceLocation());
+ New = new (*this, TypeAlignment) DependentVectorType(
+ *this, VecType, Canon, SizeExpr, AttrLoc, VecKind);
+ }
+ }
+
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
/// getExtVectorType - Return the unique reference to an extended vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType
@@ -3266,7 +3408,7 @@ ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const {
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- ExtVectorType *New = new (*this, TypeAlignment)
+ auto *New = new (*this, TypeAlignment)
ExtVectorType(vecType, NumElts, Canonical);
VectorTypes.InsertNode(New, InsertPos);
Types.push_back(New);
@@ -3306,7 +3448,7 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType,
} else {
QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
SourceLocation());
- New = new (*this, TypeAlignment)
+ New = new (*this, TypeAlignment)
DependentSizedExtVectorType(*this, vecType, Canon, SizeExpr, AttrLoc);
}
}
@@ -3315,10 +3457,10 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType,
return QualType(New, 0);
}
-QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
- Expr *AddrSpaceExpr,
+QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
+ Expr *AddrSpaceExpr,
SourceLocation AttrLoc) const {
- assert(AddrSpaceExpr->isInstantiationDependent());
+ assert(AddrSpaceExpr->isInstantiationDependent());
QualType canonPointeeType = getCanonicalType(PointeeType);
@@ -3332,25 +3474,25 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
if (!canonTy) {
canonTy = new (*this, TypeAlignment)
- DependentAddressSpaceType(*this, canonPointeeType,
+ DependentAddressSpaceType(*this, canonPointeeType,
QualType(), AddrSpaceExpr, AttrLoc);
DependentAddressSpaceTypes.InsertNode(canonTy, insertPos);
Types.push_back(canonTy);
}
-
+
if (canonPointeeType == PointeeType &&
canonTy->getAddrSpaceExpr() == AddrSpaceExpr)
- return QualType(canonTy, 0);
+ return QualType(canonTy, 0);
- DependentAddressSpaceType *sugaredType
+ auto *sugaredType
= new (*this, TypeAlignment)
- DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0),
+ DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0),
AddrSpaceExpr, AttrLoc);
Types.push_back(sugaredType);
- return QualType(sugaredType, 0);
+ return QualType(sugaredType, 0);
}
-/// \brief Determine whether \p T is canonical as the result type of a function.
+/// Determine whether \p T is canonical as the result type of a function.
static bool isCanonicalResultType(QualType T) {
return T.isCanonical() &&
(T.getObjCLifetime() == Qualifiers::OCL_None ||
@@ -3382,7 +3524,7 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy,
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- FunctionNoProtoType *New = new (*this, TypeAlignment)
+ auto *New = new (*this, TypeAlignment)
FunctionNoProtoType(ResultTy, Canonical, Info);
Types.push_back(New);
FunctionNoProtoTypes.InsertNode(New, InsertPos);
@@ -3416,6 +3558,11 @@ static bool isCanonicalExceptionSpecification(
if (ESI.Type == EST_BasicNoexcept)
return true;
+ // A noexcept(expr) specification is (possibly) canonical if expr is
+ // value-dependent.
+ if (ESI.Type == EST_DependentNoexcept)
+ return true;
+
// A dynamic exception specification is canonical if it only contains pack
// expansions (so we can't tell whether it's non-throwing) and all its
// contained types are canonical.
@@ -3430,11 +3577,6 @@ static bool isCanonicalExceptionSpecification(
return AnyPackExpansions;
}
- // A noexcept(expr) specification is (possibly) canonical if expr is
- // value-dependent.
- if (ESI.Type == EST_ComputedNoexcept)
- return ESI.NoexceptExpr && ESI.NoexceptExpr->isValueDependent();
-
return false;
}
@@ -3462,7 +3604,7 @@ QualType ASTContext::getFunctionTypeInternal(
// noexcept expression, or we're just looking for a canonical type.
// Otherwise, we're going to need to create a type
// sugar node to hold the concrete expression.
- if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept ||
+ if (OnlyWantCanonical || !isComputedNoexcept(EPI.ExceptionSpec.Type) ||
EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr())
return Existing;
@@ -3509,7 +3651,7 @@ QualType ASTContext::getFunctionTypeInternal(
// We don't know yet. It shouldn't matter what we pick here; no-one
// should ever look at this.
LLVM_FALLTHROUGH;
- case EST_None: case EST_MSAny:
+ case EST_None: case EST_MSAny: case EST_NoexceptFalse:
CanonicalEPI.ExceptionSpec.Type = EST_None;
break;
@@ -3531,24 +3673,12 @@ QualType ASTContext::getFunctionTypeInternal(
break;
}
- case EST_DynamicNone: case EST_BasicNoexcept:
+ case EST_DynamicNone: case EST_BasicNoexcept: case EST_NoexceptTrue:
CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept;
break;
- case EST_ComputedNoexcept:
- llvm::APSInt Value(1);
- auto *E = CanonicalEPI.ExceptionSpec.NoexceptExpr;
- if (!E || !E->isIntegerConstantExpr(Value, *this, nullptr,
- /*IsEvaluated*/false)) {
- // This noexcept specification is invalid.
- // FIXME: Should this be able to happen?
- CanonicalEPI.ExceptionSpec.Type = EST_None;
- break;
- }
-
- CanonicalEPI.ExceptionSpec.Type =
- Value.getBoolValue() ? EST_BasicNoexcept : EST_None;
- break;
+ case EST_DependentNoexcept:
+ llvm_unreachable("dependent noexcept is already canonical");
}
} else {
CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
@@ -3573,18 +3703,10 @@ QualType ASTContext::getFunctionTypeInternal(
// Instead of the exception types, there could be a noexcept
// expression, or information used to resolve the exception
// specification.
- size_t Size = sizeof(FunctionProtoType) +
- NumArgs * sizeof(QualType);
-
- if (EPI.ExceptionSpec.Type == EST_Dynamic) {
- Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType);
- } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
- Size += sizeof(Expr*);
- } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
- Size += 2 * sizeof(FunctionDecl*);
- } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
- Size += sizeof(FunctionDecl*);
- }
+ size_t Size =
+ sizeof(FunctionProtoType) + NumArgs * sizeof(QualType) +
+ FunctionProtoType::getExceptionSpecSize(
+ EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size());
// Put the ExtParameterInfos last. If all were equal, it would make
// more sense to put these before the exception specification, because
@@ -3596,7 +3718,7 @@ QualType ASTContext::getFunctionTypeInternal(
Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo);
}
- FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
+ auto *FTP = (FunctionProtoType *) Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI);
Types.push_back(FTP);
@@ -3624,12 +3746,18 @@ QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const {
assert(!NewIP && "Shouldn't be in the map!");
(void)NewIP;
}
- PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly);
+ auto *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly);
Types.push_back(New);
PipeTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
+QualType ASTContext::adjustStringLiteralBaseType(QualType Ty) const {
+ // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
+ return LangOpts.OpenCL ? getAddrSpaceQualType(Ty, LangAS::opencl_constant)
+ : Ty;
+}
+
QualType ASTContext::getReadPipeType(QualType T) const {
return getPipeType(T, true);
}
@@ -3641,7 +3769,7 @@ QualType ASTContext::getWritePipeType(QualType T) const {
#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ const auto *RD = cast<CXXRecordDecl>(D);
if (isa<ClassTemplatePartialSpecializationDecl>(RD))
return true;
if (RD->getDescribedClassTemplate() &&
@@ -3677,21 +3805,20 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
assert(Decl && "Passed null for Decl param");
assert(!Decl->TypeForDecl && "TypeForDecl present in slow case");
- if (const TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Decl))
+ if (const auto *Typedef = dyn_cast<TypedefNameDecl>(Decl))
return getTypedefType(Typedef);
assert(!isa<TemplateTypeParmDecl>(Decl) &&
"Template type parameter types are always available.");
- if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) {
+ if (const auto *Record = dyn_cast<RecordDecl>(Decl)) {
assert(Record->isFirstDecl() && "struct/union has previous declaration");
assert(!NeedsInjectedClassNameType(Record));
return getRecordType(Record);
- } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
+ } else if (const auto *Enum = dyn_cast<EnumDecl>(Decl)) {
assert(Enum->isFirstDecl() && "enum has previous declaration");
return getEnumType(Enum);
- } else if (const UnresolvedUsingTypenameDecl *Using =
- dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
+ } else if (const auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using);
Decl->TypeForDecl = newType;
Types.push_back(newType);
@@ -3710,7 +3837,7 @@ ASTContext::getTypedefType(const TypedefNameDecl *Decl,
if (Canonical.isNull())
Canonical = getCanonicalType(Decl->getUnderlyingType());
- TypedefType *newType = new(*this, TypeAlignment)
+ auto *newType = new (*this, TypeAlignment)
TypedefType(Type::Typedef, Decl, Canonical);
Decl->TypeForDecl = newType;
Types.push_back(newType);
@@ -3722,9 +3849,9 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const {
if (const RecordDecl *PrevDecl = Decl->getPreviousDecl())
if (PrevDecl->TypeForDecl)
- return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+ return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
- RecordType *newType = new (*this, TypeAlignment) RecordType(Decl);
+ auto *newType = new (*this, TypeAlignment) RecordType(Decl);
Decl->TypeForDecl = newType;
Types.push_back(newType);
return QualType(newType, 0);
@@ -3735,9 +3862,9 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
if (const EnumDecl *PrevDecl = Decl->getPreviousDecl())
if (PrevDecl->TypeForDecl)
- return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+ return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
- EnumType *newType = new (*this, TypeAlignment) EnumType(Decl);
+ auto *newType = new (*this, TypeAlignment) EnumType(Decl);
Decl->TypeForDecl = newType;
Types.push_back(newType);
return QualType(newType, 0);
@@ -3763,7 +3890,7 @@ QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
return QualType(type, 0);
}
-/// \brief Retrieve a substitution-result type.
+/// Retrieve a substitution-result type.
QualType
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
QualType Replacement) const {
@@ -3786,7 +3913,7 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
return QualType(SubstParm, 0);
}
-/// \brief Retrieve a
+/// Retrieve a
QualType ASTContext::getSubstTemplateTypeParmPackType(
const TemplateTypeParmType *Parm,
const TemplateArgument &ArgPack) {
@@ -3796,14 +3923,14 @@ QualType ASTContext::getSubstTemplateTypeParmPackType(
assert(P.getAsType().isCanonical() && "Pack contains non-canonical type");
}
#endif
-
+
llvm::FoldingSetNodeID ID;
SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack);
void *InsertPos = nullptr;
if (SubstTemplateTypeParmPackType *SubstParm
= SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(SubstParm, 0);
-
+
QualType Canon;
if (!Parm->isCanonicalUnqualified()) {
Canon = getCanonicalType(QualType(Parm, 0));
@@ -3812,15 +3939,15 @@ QualType ASTContext::getSubstTemplateTypeParmPackType(
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
}
- SubstTemplateTypeParmPackType *SubstParm
+ auto *SubstParm
= new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon,
ArgPack);
Types.push_back(SubstParm);
SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos);
- return QualType(SubstParm, 0);
+ return QualType(SubstParm, 0);
}
-/// \brief Retrieve the template type parameter type for a template
+/// Retrieve the template type parameter type for a template
/// parameter or parameter pack with the given depth, index, and (optionally)
/// name.
QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
@@ -3839,7 +3966,7 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack);
TypeParm = new (*this, TypeAlignment) TemplateTypeParmType(TTPDecl, Canon);
- TemplateTypeParmType *TypeCheck
+ TemplateTypeParmType *TypeCheck
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!TypeCheck && "Template type parameter canonical type broken");
(void)TypeCheck;
@@ -3858,7 +3985,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo &Args,
QualType Underlying) const {
- assert(!Name.getAsDependentTemplateName() &&
+ assert(!Name.getAsDependentTemplateName() &&
"No dependent template names here!");
QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
@@ -3878,7 +4005,7 @@ QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgumentListInfo &Args,
QualType Underlying) const {
- assert(!Template.getAsDependentTemplateName() &&
+ assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
SmallVector<TemplateArgument, 4> ArgVec;
@@ -3894,7 +4021,7 @@ static bool hasAnyPackExpansions(ArrayRef<TemplateArgument> Args) {
for (const TemplateArgument &Arg : Args)
if (Arg.isPackExpansion())
return true;
-
+
return true;
}
#endif
@@ -3903,13 +4030,13 @@ QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
ArrayRef<TemplateArgument> Args,
QualType Underlying) const {
- assert(!Template.getAsDependentTemplateName() &&
+ assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Template = TemplateName(QTN->getTemplateDecl());
-
- bool IsTypeAlias =
+
+ bool IsTypeAlias =
Template.getAsTemplateDecl() &&
isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
QualType CanonType;
@@ -3931,7 +4058,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
sizeof(TemplateArgument) * Args.size() +
(IsTypeAlias? sizeof(QualType) : 0),
TypeAlignment);
- TemplateSpecializationType *Spec
+ auto *Spec
= new (Mem) TemplateSpecializationType(Template, Args, CanonType,
IsTypeAlias ? Underlying : QualType());
@@ -3941,13 +4068,13 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
QualType ASTContext::getCanonicalTemplateSpecializationType(
TemplateName Template, ArrayRef<TemplateArgument> Args) const {
- assert(!Template.getAsDependentTemplateName() &&
+ assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Template = TemplateName(QTN->getTemplateDecl());
-
+
// Build the canonical template specialization type.
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
SmallVector<TemplateArgument, 4> CanonArgs;
@@ -3983,12 +4110,12 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
return QualType(Spec, 0);
}
-QualType
-ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
- QualType NamedType) const {
+QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ QualType NamedType,
+ TagDecl *OwnedTagDecl) const {
llvm::FoldingSetNodeID ID;
- ElaboratedType::Profile(ID, Keyword, NNS, NamedType);
+ ElaboratedType::Profile(ID, Keyword, NNS, NamedType, OwnedTagDecl);
void *InsertPos = nullptr;
ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -4003,7 +4130,8 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
(void)CheckT;
}
- T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon);
+ T = new (*this, TypeAlignment)
+ ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl);
Types.push_back(T);
ElaboratedTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -4077,7 +4205,7 @@ ASTContext::getDependentTemplateSpecializationType(
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
ArrayRef<TemplateArgument> Args) const {
- assert((!NNS || NNS->isDependent()) &&
+ assert((!NNS || NNS->isDependent()) &&
"nested-name-specifier must be dependent");
llvm::FoldingSetNodeID ID;
@@ -4126,7 +4254,7 @@ ASTContext::getDependentTemplateSpecializationType(
TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
TemplateArgument Arg;
- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
QualType ArgType = getTypeDeclType(TTP);
if (TTP->isParameterPack())
ArgType = getPackExpansionType(ArgType, None);
@@ -4212,7 +4340,7 @@ static bool areSortedAndUniqued(ArrayRef<ObjCProtocolDecl *> Protocols) {
if (Protocols[0]->getCanonicalDecl() != Protocols[0])
return false;
-
+
for (unsigned i = 1; i != Protocols.size(); ++i)
if (CmpProtocolNames(&Protocols[i - 1], &Protocols[i]) >= 0 ||
Protocols[i]->getCanonicalDecl() != Protocols[i])
@@ -4265,7 +4393,7 @@ QualType ASTContext::getObjCObjectType(
// type.
ArrayRef<QualType> effectiveTypeArgs = typeArgs;
if (effectiveTypeArgs.empty()) {
- if (auto baseObject = baseType->getAs<ObjCObjectType>())
+ if (const auto *baseObject = baseType->getAs<ObjCObjectType>())
effectiveTypeArgs = baseObject->getTypeArgs();
}
@@ -4313,7 +4441,7 @@ QualType ASTContext::getObjCObjectType(
size += typeArgs.size() * sizeof(QualType);
size += protocols.size() * sizeof(ObjCProtocolDecl *);
void *mem = Allocate(size, TypeAlignment);
- ObjCObjectTypeImpl *T =
+ auto *T =
new (mem) ObjCObjectTypeImpl(canonical, baseType, typeArgs, protocols,
isKindOf);
@@ -4331,15 +4459,14 @@ ASTContext::applyObjCProtocolQualifiers(QualType type,
bool allowOnPointerType) const {
hasError = false;
- if (const ObjCTypeParamType *objT =
- dyn_cast<ObjCTypeParamType>(type.getTypePtr())) {
+ if (const auto *objT = dyn_cast<ObjCTypeParamType>(type.getTypePtr())) {
return getObjCTypeParamType(objT->getDecl(), protocols);
}
// Apply protocol qualifiers to ObjCObjectPointerType.
if (allowOnPointerType) {
- if (const ObjCObjectPointerType *objPtr =
- dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) {
+ if (const auto *objPtr =
+ dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) {
const ObjCObjectType *objT = objPtr->getObjectType();
// Merge protocol lists and construct ObjCObjectType.
SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
@@ -4357,7 +4484,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type,
}
// Apply protocol qualifiers to ObjCObjectType.
- if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
+ if (const auto *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
// FIXME: Check for protocols to which the class type is already
// known to conform.
@@ -4379,7 +4506,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type,
// id<protocol-list>
if (type->isObjCIdType()) {
- const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ const auto *objPtr = type->castAs<ObjCObjectPointerType>();
type = getObjCObjectType(ObjCBuiltinIdTy, {}, protocols,
objPtr->isKindOfType());
return getObjCObjectPointerType(type);
@@ -4387,7 +4514,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type,
// Class<protocol-list>
if (type->isObjCClassType()) {
- const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ const auto *objPtr = type->castAs<ObjCObjectPointerType>();
type = getObjCObjectType(ObjCBuiltinClassTy, {}, protocols,
objPtr->isKindOfType());
return getObjCObjectPointerType(type);
@@ -4424,8 +4551,7 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
unsigned size = sizeof(ObjCTypeParamType);
size += protocols.size() * sizeof(ObjCProtocolDecl *);
void *mem = Allocate(size, TypeAlignment);
- ObjCTypeParamType *newType = new (mem)
- ObjCTypeParamType(Decl, Canonical, protocols);
+ auto *newType = new (mem) ObjCTypeParamType(Decl, Canonical, protocols);
Types.push_back(newType);
ObjCTypeParamTypes.InsertNode(newType, InsertPos);
@@ -4439,8 +4565,8 @@ bool ASTContext::ObjCObjectAdoptsQTypeProtocols(QualType QT,
ObjCInterfaceDecl *IC) {
if (!QT->isObjCQualifiedIdType())
return false;
-
- if (const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>()) {
+
+ if (const auto *OPT = QT->getAs<ObjCObjectPointerType>()) {
// If both the right and left sides have qualifiers.
for (auto *Proto : OPT->quals()) {
if (!IC->ClassImplementsProtocol(Proto, false))
@@ -4458,7 +4584,7 @@ bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT,
ObjCInterfaceDecl *IDecl) {
if (!QT->isObjCQualifiedIdType())
return false;
- const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>();
+ const auto *OPT = QT->getAs<ObjCObjectPointerType>();
if (!OPT)
return false;
if (!IDecl->hasDefinition())
@@ -4467,7 +4593,7 @@ bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT,
CollectInheritedProtocols(IDecl, InheritedProtocols);
if (InheritedProtocols.empty())
return false;
- // Check that if every protocol in list of id<plist> conforms to a protcol
+ // Check that if every protocol in list of id<plist> conforms to a protocol
// of IDecl's, then bridge casting is ok.
bool Conforms = false;
for (auto *Proto : OPT->quals()) {
@@ -4483,7 +4609,7 @@ bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT,
}
if (Conforms)
return true;
-
+
for (auto *PI : InheritedProtocols) {
// If both the right and left sides have qualifiers.
bool Adopts = false;
@@ -4520,7 +4646,7 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const {
// No match.
void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment);
- ObjCObjectPointerType *QType =
+ auto *QType =
new (Mem) ObjCObjectPointerType(Canonical, ObjectT);
Types.push_back(QType);
@@ -4544,9 +4670,9 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
// Prefer the definition, if there is one.
if (const ObjCInterfaceDecl *Def = Decl->getDefinition())
Decl = Def;
-
+
void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
- ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
+ auto *T = new (Mem) ObjCInterfaceType(Decl);
Decl->TypeForDecl = T;
Types.push_back(T);
return QualType(T, 0);
@@ -4593,12 +4719,12 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const {
/// on canonical types (which are always unique).
QualType ASTContext::getTypeOfType(QualType tofType) const {
QualType Canonical = getCanonicalType(tofType);
- TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical);
+ auto *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical);
Types.push_back(tot);
return QualType(tot, 0);
}
-/// \brief Unlike many "get<Type>" functions, we don't unique DecltypeType
+/// Unlike many "get<Type>" functions, we don't unique DecltypeType
/// nodes. This would never be helpful, since each such type has its own
/// expression, and would not give a significant memory saving, since there
/// is an Expr tree under each such type.
@@ -4683,9 +4809,8 @@ QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
- AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
- Keyword,
- IsDependent);
+ auto *AT = new (*this, TypeAlignment)
+ AutoType(DeducedType, Keyword, IsDependent);
Types.push_back(AT);
if (InsertPos)
AutoTypes.InsertNode(AT, InsertPos);
@@ -4706,7 +4831,7 @@ QualType ASTContext::getDeducedTemplateSpecializationType(
DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(DTST, 0);
- DeducedTemplateSpecializationType *DTST = new (*this, TypeAlignment)
+ auto *DTST = new (*this, TypeAlignment)
DeducedTemplateSpecializationType(Template, DeducedType, IsDependent);
Types.push_back(DTST);
if (InsertPos)
@@ -4736,7 +4861,7 @@ QualType ASTContext::getAtomicType(QualType T) const {
AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical);
+ auto *New = new (*this, TypeAlignment) AtomicType(T, Canonical);
Types.push_back(New);
AtomicTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -4776,7 +4901,7 @@ CanQualType ASTContext::getSizeType() const {
return getFromTargetType(Target->getSizeType());
}
-/// Return the unique signed counterpart of the integer type
+/// Return the unique signed counterpart of the integer type
/// corresponding to size_t.
CanQualType ASTContext::getSignedSizeType() const {
return getFromTargetType(Target->getSignedSizeType());
@@ -4820,14 +4945,14 @@ QualType ASTContext::getPointerDiffType() const {
return getFromTargetType(Target->getPtrDiffType(0));
}
-/// \brief Return the unique unsigned counterpart of "ptrdiff_t"
+/// 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
+/// 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 {
return getFromTargetType(Target->getProcessIDType());
@@ -4863,8 +4988,8 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
// the unqualified desugared type and then drops it on the floor.
// We then have to strip that sugar back off with
// getUnqualifiedDesugaredType(), which is silly.
- const ArrayType *AT =
- dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType());
+ const auto *AT =
+ dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType());
// If we don't have an array, just use the results in splitType.
if (!AT) {
@@ -4888,16 +5013,16 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
// build the type back up.
quals.addConsistentQualifiers(splitType.Quals);
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
return getConstantArrayType(unqualElementType, CAT->getSize(),
CAT->getSizeModifier(), 0);
}
- if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
+ if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT)) {
return getIncompleteArrayType(unqualElementType, IAT->getSizeModifier(), 0);
}
- if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) {
+ if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) {
return getVariableArrayType(unqualElementType,
VAT->getSizeExpr(),
VAT->getSizeModifier(),
@@ -4905,54 +5030,120 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
VAT->getBracketsRange());
}
- const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT);
+ const auto *DSAT = cast<DependentSizedArrayType>(AT);
return getDependentSizedArrayType(unqualElementType, DSAT->getSizeExpr(),
DSAT->getSizeModifier(), 0,
SourceRange());
}
-/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that
-/// may be similar (C++ 4.4), replaces T1 and T2 with the type that
-/// they point to and return true. If T1 and T2 aren't pointer types
-/// or pointer-to-member types, or if they are not similar at this
-/// level, returns false and leaves T1 and T2 unchanged. Top-level
-/// qualifiers on T1 and T2 are ignored. This function will typically
-/// be called in a loop that successively "unwraps" pointer and
-/// pointer-to-member types to compare them at each level.
-bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
- const PointerType *T1PtrType = T1->getAs<PointerType>(),
- *T2PtrType = T2->getAs<PointerType>();
+/// Attempt to unwrap two types that may both be array types with the same bound
+/// (or both be array types of unknown bound) for the purpose of comparing the
+/// cv-decomposition of two types per C++ [conv.qual].
+bool ASTContext::UnwrapSimilarArrayTypes(QualType &T1, QualType &T2) {
+ bool UnwrappedAny = false;
+ while (true) {
+ auto *AT1 = getAsArrayType(T1);
+ if (!AT1) return UnwrappedAny;
+
+ auto *AT2 = getAsArrayType(T2);
+ if (!AT2) return UnwrappedAny;
+
+ // If we don't have two array types with the same constant bound nor two
+ // incomplete array types, we've unwrapped everything we can.
+ if (auto *CAT1 = dyn_cast<ConstantArrayType>(AT1)) {
+ auto *CAT2 = dyn_cast<ConstantArrayType>(AT2);
+ if (!CAT2 || CAT1->getSize() != CAT2->getSize())
+ return UnwrappedAny;
+ } else if (!isa<IncompleteArrayType>(AT1) ||
+ !isa<IncompleteArrayType>(AT2)) {
+ return UnwrappedAny;
+ }
+
+ T1 = AT1->getElementType();
+ T2 = AT2->getElementType();
+ UnwrappedAny = true;
+ }
+}
+
+/// Attempt to unwrap two types that may be similar (C++ [conv.qual]).
+///
+/// If T1 and T2 are both pointer types of the same kind, or both array types
+/// with the same bound, unwraps layers from T1 and T2 until a pointer type is
+/// unwrapped. Top-level qualifiers on T1 and T2 are ignored.
+///
+/// This function will typically be called in a loop that successively
+/// "unwraps" pointer and pointer-to-member types to compare them at each
+/// level.
+///
+/// \return \c true if a pointer type was unwrapped, \c false if we reached a
+/// pair of types that can't be unwrapped further.
+bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) {
+ UnwrapSimilarArrayTypes(T1, T2);
+
+ const auto *T1PtrType = T1->getAs<PointerType>();
+ const auto *T2PtrType = T2->getAs<PointerType>();
if (T1PtrType && T2PtrType) {
T1 = T1PtrType->getPointeeType();
T2 = T2PtrType->getPointeeType();
return true;
}
-
- const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
- *T2MPType = T2->getAs<MemberPointerType>();
- if (T1MPType && T2MPType &&
- hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+
+ const auto *T1MPType = T1->getAs<MemberPointerType>();
+ const auto *T2MPType = T2->getAs<MemberPointerType>();
+ if (T1MPType && T2MPType &&
+ hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
QualType(T2MPType->getClass(), 0))) {
T1 = T1MPType->getPointeeType();
T2 = T2MPType->getPointeeType();
return true;
}
-
+
if (getLangOpts().ObjC1) {
- const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(),
- *T2OPType = T2->getAs<ObjCObjectPointerType>();
+ const auto *T1OPType = T1->getAs<ObjCObjectPointerType>();
+ const auto *T2OPType = T2->getAs<ObjCObjectPointerType>();
if (T1OPType && T2OPType) {
T1 = T1OPType->getPointeeType();
T2 = T2OPType->getPointeeType();
return true;
}
}
-
+
// FIXME: Block pointers, too?
-
+
return false;
}
+bool ASTContext::hasSimilarType(QualType T1, QualType T2) {
+ while (true) {
+ Qualifiers Quals;
+ T1 = getUnqualifiedArrayType(T1, Quals);
+ T2 = getUnqualifiedArrayType(T2, Quals);
+ if (hasSameType(T1, T2))
+ return true;
+ if (!UnwrapSimilarTypes(T1, T2))
+ return false;
+ }
+}
+
+bool ASTContext::hasCvrSimilarType(QualType T1, QualType T2) {
+ while (true) {
+ Qualifiers Quals1, Quals2;
+ T1 = getUnqualifiedArrayType(T1, Quals1);
+ T2 = getUnqualifiedArrayType(T2, Quals2);
+
+ Quals1.removeCVRQualifiers();
+ Quals2.removeCVRQualifiers();
+ if (Quals1 != Quals2)
+ return false;
+
+ if (hasSameType(T1, T2))
+ return true;
+
+ if (!UnwrapSimilarTypes(T1, T2))
+ return false;
+ }
+}
+
DeclarationNameInfo
ASTContext::getNameForTemplate(TemplateName Name,
SourceLocation NameLoc) const {
@@ -5008,10 +5199,9 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
case TemplateName::QualifiedTemplate:
case TemplateName::Template: {
TemplateDecl *Template = Name.getAsTemplateDecl();
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Template))
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template))
Template = getCanonicalTemplateTemplateParmDecl(TTP);
-
+
// The canonical template name is the canonical template declaration.
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
}
@@ -5061,7 +5251,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
return Arg;
case TemplateArgument::Declaration: {
- ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
+ auto *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
return TemplateArgument(D, Arg.getParamTypeForDecl());
}
@@ -5086,9 +5276,8 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
case TemplateArgument::Pack: {
if (Arg.pack_size() == 0)
return Arg;
-
- TemplateArgument *CanonArgs
- = new (*this) TemplateArgument[Arg.pack_size()];
+
+ auto *CanonArgs = new (*this) TemplateArgument[Arg.pack_size()];
unsigned Idx = 0;
for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
AEnd = Arg.pack_end();
@@ -5131,7 +5320,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
QualType T = getCanonicalType(QualType(NNS->getAsType(), 0));
-
+
// If we have some kind of dependent-named type (e.g., "typename T::type"),
// break it apart into its prefix and identifier, then reconsititute those
// as the canonical nested-name-specifier. This is required to canonicalize
@@ -5139,8 +5328,8 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
// types, e.g.,
// typedef typename T::type T1;
// typedef typename T1::type T2;
- if (const DependentNameType *DNT = T->getAs<DependentNameType>())
- return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
+ if (const auto *DNT = T->getAs<DependentNameType>())
+ return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
// Otherwise, just canonicalize the type, and force it to be a TypeSpec.
@@ -5163,7 +5352,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
// Handle the non-qualified case efficiently.
if (!T.hasLocalQualifiers()) {
// Handle the common positive case fast.
- if (const ArrayType *AT = dyn_cast<ArrayType>(T))
+ if (const auto *AT = dyn_cast<ArrayType>(T))
return AT;
}
@@ -5183,7 +5372,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
Qualifiers qs = split.Quals;
// If we have a simple case, just return now.
- const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty);
+ const auto *ATy = dyn_cast<ArrayType>(split.Ty);
if (!ATy || qs.empty())
return ATy;
@@ -5191,17 +5380,16 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
// qualifiers into the array element type and return a new array type.
QualType NewEltTy = getQualifiedType(ATy->getElementType(), qs);
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(ATy))
return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
CAT->getSizeModifier(),
CAT->getIndexTypeCVRQualifiers()));
- if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
+ if (const auto *IAT = dyn_cast<IncompleteArrayType>(ATy))
return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
IAT->getSizeModifier(),
IAT->getIndexTypeCVRQualifiers()));
- if (const DependentSizedArrayType *DSAT
- = dyn_cast<DependentSizedArrayType>(ATy))
+ if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(ATy))
return cast<ArrayType>(
getDependentSizedArrayType(NewEltTy,
DSAT->getSizeExpr(),
@@ -5209,7 +5397,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
DSAT->getIndexTypeCVRQualifiers(),
DSAT->getBracketsRange()));
- const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
+ const auto *VAT = cast<VariableArrayType>(ATy);
return cast<ArrayType>(getVariableArrayType(NewEltTy,
VAT->getSizeExpr(),
VAT->getSizeModifier(),
@@ -5303,7 +5491,7 @@ ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const {
/// getFloatingRank - Return a relative rank for floating point types.
/// This routine will assert if passed a built-in type that isn't a float.
static FloatingRank getFloatingRank(QualType T) {
- if (const ComplexType *CT = T->getAs<ComplexType>())
+ if (const auto *CT = T->getAs<ComplexType>())
return getFloatingRank(CT->getElementType());
assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type");
@@ -5396,14 +5584,20 @@ unsigned ASTContext::getIntegerRank(const Type *T) const {
}
}
-/// \brief Whether this is a promotable bitfield reference according
+/// Whether this is a promotable bitfield reference according
/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
///
/// \returns the type this bit-field will promote to, or NULL if no
/// promotion occurs.
QualType ASTContext::isPromotableBitField(Expr *E) const {
if (E->isTypeDependent() || E->isValueDependent())
- return QualType();
+ return {};
+
+ // C++ [conv.prom]p5:
+ // If the bit-field has an enumerated type, it is treated as any other
+ // value of that type for promotion purposes.
+ if (getLangOpts().CPlusPlus && E->getType()->isEnumeralType())
+ return {};
// FIXME: We should not do this unless E->refersToBitField() is true. This
// matters in C where getSourceBitField() will find bit-fields for various
@@ -5411,7 +5605,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
FieldDecl *Field = E->getSourceBitField(); // FIXME: conditional bit-fields?
if (!Field)
- return QualType();
+ return {};
QualType FT = Field->getType();
@@ -5431,18 +5625,20 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
//
// FIXME: C does not permit promotion of a 'long : 3' bitfield to int.
// We perform that promotion here to match GCC and C++.
+ // FIXME: C does not permit promotion of an enum bit-field whose rank is
+ // greater than that of 'int'. We perform that promotion to match GCC.
if (BitWidth < IntSize)
return IntTy;
if (BitWidth == IntSize)
return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy;
- // Types bigger than int are not subject to promotions, and therefore act
+ // Bit-fields wider than int are not subject to promotions, and therefore act
// like the base type. GCC has some weird bugs in this area that we
// deliberately do not follow (GCC follows a pre-standard resolution to
// C's DR315 which treats bit-width as being part of the type, and this leaks
// into their semantics in some cases).
- return QualType();
+ return {};
}
/// getPromotedIntegerType - Returns the type that Promotable will
@@ -5451,10 +5647,10 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
assert(!Promotable.isNull());
assert(Promotable->isPromotableIntegerType());
- if (const EnumType *ET = Promotable->getAs<EnumType>())
+ if (const auto *ET = Promotable->getAs<EnumType>())
return ET->getDecl()->getPromotionType();
- if (const BuiltinType *BT = Promotable->getAs<BuiltinType>()) {
+ if (const auto *BT = Promotable->getAs<BuiltinType>()) {
// C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t
// (3.9.1) can be converted to a prvalue of the first of the following
// types that can represent all the values of its underlying type:
@@ -5463,6 +5659,7 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
// FIXME: Is there some better way to compute this?
if (BT->getKind() == BuiltinType::WChar_S ||
BT->getKind() == BuiltinType::WChar_U ||
+ BT->getKind() == BuiltinType::Char8 ||
BT->getKind() == BuiltinType::Char16 ||
BT->getKind() == BuiltinType::Char32) {
bool FromIsSigned = BT->getKind() == BuiltinType::WChar_S;
@@ -5489,7 +5686,7 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
}
-/// \brief Recurses in pointer/array types until it finds an objc retainable
+/// Recurses in pointer/array types until it finds an objc retainable
/// type and returns its ownership.
Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
while (!T.isNull()) {
@@ -5497,9 +5694,9 @@ Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
return T.getObjCLifetime();
if (T->isArrayType())
T = getBaseElementType(T);
- else if (const PointerType *PT = T->getAs<PointerType>())
+ else if (const auto *PT = T->getAs<PointerType>())
T = PT->getPointeeType();
- else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ else if (const auto *RT = T->getAs<ReferenceType>())
T = RT->getPointeeType();
else
break;
@@ -5524,9 +5721,9 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const {
const Type *RHSC = getCanonicalType(RHS).getTypePtr();
// Unwrap enums to their underlying type.
- if (const EnumType *ET = dyn_cast<EnumType>(LHSC))
+ if (const auto *ET = dyn_cast<EnumType>(LHSC))
LHSC = getIntegerTypeForEnum(ET);
- if (const EnumType *ET = dyn_cast<EnumType>(RHSC))
+ if (const auto *ET = dyn_cast<EnumType>(RHSC))
RHSC = getIntegerTypeForEnum(ET);
if (LHSC == RHSC) return 0;
@@ -5633,10 +5830,10 @@ QualType ASTContext::getObjCSuperType() const {
}
void ASTContext::setCFConstantStringType(QualType T) {
- const TypedefType *TD = T->getAs<TypedefType>();
+ const auto *TD = T->getAs<TypedefType>();
assert(TD && "Invalid CFConstantStringType");
CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl());
- auto TagType =
+ const auto *TagType =
CFConstantStringTypeDecl->getUnderlyingType()->getAs<RecordType>();
assert(TagType && "Invalid CFConstantStringType");
CFConstantStringTagDecl = TagType->getDecl();
@@ -5717,7 +5914,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
}
TargetInfo::OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const {
- auto BT = dyn_cast<BuiltinType>(T);
+ const auto *BT = dyn_cast<BuiltinType>(T);
if (!BT) {
if (isa<PipeType>(T))
@@ -5764,30 +5961,34 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) {
const Expr *copyExpr = getBlockVarCopyInits(D);
if (!copyExpr && record->hasTrivialDestructor()) return false;
-
+
return true;
}
-
+
+ // The block needs copy/destroy helpers if Ty is non-trivial to destructively
+ // move or destroy.
+ if (Ty.isNonTrivialToPrimitiveDestructiveMove() || Ty.isDestructedType())
+ return true;
+
if (!Ty->isObjCRetainableType()) return false;
-
+
Qualifiers qs = Ty.getQualifiers();
-
+
// If we have lifetime, that dominates.
if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
switch (lifetime) {
case Qualifiers::OCL_None: llvm_unreachable("impossible");
-
+
// These are just bits as far as the runtime is concerned.
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
return false;
-
- // Tell the runtime that this is ARC __weak, called by the
- // byref routines.
+
+ // These cases should have been taken care of when checking the type's
+ // non-triviality.
case Qualifiers::OCL_Weak:
- // ARC __strong __block variables need to be retained.
case Qualifiers::OCL_Strong:
- return true;
+ llvm_unreachable("impossible");
}
llvm_unreachable("fell out of lifetime switch!");
}
@@ -5801,7 +6002,7 @@ bool ASTContext::getByrefLifetime(QualType Ty,
if (!getLangOpts().ObjC1 ||
getLangOpts().getGC() != LangOptions::NonGC)
return false;
-
+
HasByrefExtendedLayout = false;
if (Ty->isRecordType()) {
HasByrefExtendedLayout = true;
@@ -5827,7 +6028,7 @@ TypedefDecl *ASTContext::getObjCInstanceTypeDecl() {
// This returns true if a type has been typedefed to BOOL:
// typedef <type> BOOL;
static bool isTypeTypedefedAsBOOL(QualType T) {
- if (const TypedefType *TT = dyn_cast<TypedefType>(T))
+ if (const auto *TT = dyn_cast<TypedefType>(T))
if (IdentifierInfo *II = TT->getDecl()->getIdentifier())
return II->isStr("BOOL");
@@ -5839,7 +6040,7 @@ static bool isTypeTypedefedAsBOOL(QualType T) {
CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
if (!type->isIncompleteArrayType() && type->isIncompleteType())
return CharUnits::Zero();
-
+
CharUnits sz = getTypeSizeInChars(type);
// Make all integer and enum types at least as large as an int
@@ -5879,8 +6080,7 @@ ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const {
return InlineVariableDefinitionKind::WeakUnknown;
}
-static inline
-std::string charUnitsToString(const CharUnits &CU) {
+static std::string charUnitsToString(const CharUnits &CU) {
return llvm::itostr(CU.getQuantity());
}
@@ -5916,13 +6116,13 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
S += charUnitsToString(ParmOffset);
// Block pointer and offset.
S += "@?0";
-
+
// Argument types.
ParmOffset = PtrSize;
for (auto PVDecl : Decl->parameters()) {
- QualType PType = PVDecl->getOriginalType();
- if (const ArrayType *AT =
- dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+ QualType PType = PVDecl->getOriginalType();
+ if (const auto *AT =
+ dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
// Use array's original type only if it has known number of
// elements.
if (!isa<ConstantArrayType>(AT))
@@ -5953,8 +6153,8 @@ ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const {
CharUnits sz = getObjCEncodingTypeSize(PType);
if (sz.isZero())
continue;
-
- assert(sz.isPositive() &&
+
+ assert(sz.isPositive() &&
"getObjCEncodingForFunctionDecl - Incomplete param type");
ParmOffset += sz;
}
@@ -5964,8 +6164,8 @@ ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const {
// Argument types.
for (auto PVDecl : Decl->parameters()) {
QualType PType = PVDecl->getOriginalType();
- if (const ArrayType *AT =
- dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+ if (const auto *AT =
+ dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
// Use array's original type only if it has known number of
// elements.
if (!isa<ConstantArrayType>(AT))
@@ -5976,12 +6176,12 @@ ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const {
S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
-
+
return S;
}
/// getObjCEncodingForMethodParameter - Return the encoded type for a single
-/// method parameter or return type. If Extended, include class names and
+/// method parameter or return type. If Extended, include class names and
/// block object types.
void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
QualType T, std::string& S,
@@ -5991,9 +6191,9 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
// Encode parameter type.
getObjCEncodingForTypeImpl(T, S, true, true, nullptr,
true /*OutermostType*/,
- false /*EncodingProperty*/,
- false /*StructField*/,
- Extended /*EncodeBlockParameters*/,
+ false /*EncodingProperty*/,
+ false /*StructField*/,
+ Extended /*EncodeBlockParameters*/,
Extended /*EncodeClassNames*/);
}
@@ -6019,8 +6219,8 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
CharUnits sz = getObjCEncodingTypeSize(PType);
if (sz.isZero())
continue;
-
- assert(sz.isPositive() &&
+
+ assert(sz.isPositive() &&
"getObjCEncodingForMethodDecl - Incomplete param type");
ParmOffset += sz;
}
@@ -6034,20 +6234,20 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
E = Decl->sel_param_end(); PI != E; ++PI) {
const ParmVarDecl *PVDecl = *PI;
QualType PType = PVDecl->getOriginalType();
- if (const ArrayType *AT =
- dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+ if (const auto *AT =
+ dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
// Use array's original type only if it has known number of
// elements.
if (!isa<ConstantArrayType>(AT))
PType = PVDecl->getType();
} else if (PType->isFunctionType())
PType = PVDecl->getType();
- getObjCEncodingForMethodParameter(PVDecl->getObjCDeclQualifier(),
+ getObjCEncodingForMethodParameter(PVDecl->getObjCDeclQualifier(),
PType, S, Extended);
S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
-
+
return S;
}
@@ -6057,13 +6257,12 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl(
const Decl *Container) const {
if (!Container)
return nullptr;
- if (const ObjCCategoryImplDecl *CID =
- dyn_cast<ObjCCategoryImplDecl>(Container)) {
+ if (const auto *CID = dyn_cast<ObjCCategoryImplDecl>(Container)) {
for (auto *PID : CID->property_impls())
if (PID->getPropertyDecl() == PD)
return PID;
} else {
- const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container);
+ const auto *OID = cast<ObjCImplementationDecl>(Container);
for (auto *PID : OID->property_impls())
if (PID->getPropertyDecl() == PD)
return PID;
@@ -6170,7 +6369,7 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
/// 'i' or 'I' instead if encoding a struct field, or a pointer!
void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const {
if (isa<TypedefType>(PointeeTy.getTypePtr())) {
- if (const BuiltinType *BT = PointeeTy->getAs<BuiltinType>()) {
+ if (const auto *BT = PointeeTy->getAs<BuiltinType>()) {
if (BT->getKind() == BuiltinType::ULong && getIntWidth(PointeeTy) == 32)
PointeeTy = UnsignedIntTy;
else
@@ -6207,6 +6406,7 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
switch (kind) {
case BuiltinType::Void: return 'v';
case BuiltinType::Bool: return 'B';
+ case BuiltinType::Char8:
case BuiltinType::Char_U:
case BuiltinType::UChar: return 'C';
case BuiltinType::Char16:
@@ -6235,6 +6435,30 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Half:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
// FIXME: potentially need @encodes for these!
return ' ';
@@ -6264,13 +6488,13 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
EnumDecl *Enum = ET->getDecl();
-
+
// The encoding of an non-fixed enum type is always 'i', regardless of size.
if (!Enum->isFixed())
return 'i';
-
+
// The encoding of a fixed enum type matches its fixed underlying type.
- const BuiltinType *BT = Enum->getIntegerType()->castAs<BuiltinType>();
+ const auto *BT = Enum->getIntegerType()->castAs<BuiltinType>();
return getObjCEncodingForPrimitiveKind(C, BT->getKind());
}
@@ -6307,10 +6531,10 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
S += llvm::utostr(Offset);
- if (const EnumType *ET = T->getAs<EnumType>())
+ if (const auto *ET = T->getAs<EnumType>())
S += ObjCEncodingForEnumType(Ctx, ET);
else {
- const BuiltinType *BT = T->castAs<BuiltinType>();
+ const auto *BT = T->castAs<BuiltinType>();
S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind());
}
}
@@ -6335,21 +6559,21 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::Enum:
if (FD && FD->isBitField())
return EncodeBitField(this, S, T, FD);
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CT))
+ if (const auto *BT = dyn_cast<BuiltinType>(CT))
S += getObjCEncodingForPrimitiveKind(this, BT->getKind());
else
S += ObjCEncodingForEnumType(this, cast<EnumType>(CT));
return;
case Type::Complex: {
- const ComplexType *CT = T->castAs<ComplexType>();
+ const auto *CT = T->castAs<ComplexType>();
S += 'j';
getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr);
return;
}
case Type::Atomic: {
- const AtomicType *AT = T->castAs<AtomicType>();
+ const auto *AT = T->castAs<AtomicType>();
S += 'A';
getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr);
return;
@@ -6361,7 +6585,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::RValueReference: {
QualType PointeeTy;
if (isa<PointerType>(CT)) {
- const PointerType *PT = T->castAs<PointerType>();
+ const auto *PT = T->castAs<PointerType>();
if (PT->isObjCSelType()) {
S += ':';
return;
@@ -6405,7 +6629,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S += '*';
return;
}
- } else if (const RecordType *RTy = PointeeTy->getAs<RecordType>()) {
+ } else if (const auto *RTy = PointeeTy->getAs<RecordType>()) {
// GCC binary compat: Need to convert "struct objc_class *" to "#".
if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_class")) {
S += '#';
@@ -6430,7 +6654,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray: {
- const ArrayType *AT = cast<ArrayType>(CT);
+ const auto *AT = cast<ArrayType>(CT);
if (isa<IncompleteArrayType>(AT) && !StructField) {
// Incomplete arrays are encoded as a pointer to the array element.
@@ -6441,7 +6665,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
} else {
S += '[';
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
S += llvm::utostr(CAT->getSize().getZExtValue());
else {
//Variable length arrays are encoded as a regular array with 0 elements.
@@ -6470,8 +6694,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
// Anonymous structures print as '?'
if (const IdentifierInfo *II = RDecl->getIdentifier()) {
S += II->getName();
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
+ if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
llvm::raw_string_ostream OS(S);
printTemplateArgumentList(OS, TemplateArgs.asArray(),
@@ -6513,11 +6736,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
case Type::BlockPointer: {
- const BlockPointerType *BT = T->castAs<BlockPointerType>();
+ const auto *BT = T->castAs<BlockPointerType>();
S += "@?"; // Unlike a pointer-to-function, which is "^?".
if (EncodeBlockParameters) {
- const FunctionType *FT = BT->getPointeeType()->castAs<FunctionType>();
-
+ const auto *FT = BT->getPointeeType()->castAs<FunctionType>();
+
S += '<';
// Block return type
getObjCEncodingForTypeImpl(
@@ -6528,7 +6751,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
// Block self
S += "@?";
// Block parameters
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
+ if (const auto *FPT = dyn_cast<FunctionProtoType>(FT)) {
for (const auto &I : FPT->param_types())
getObjCEncodingForTypeImpl(
I, S, ExpandPointedToStructures, ExpandStructures, FD,
@@ -6552,10 +6775,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S += "{objc_class=}";
return;
}
- // TODO: Double check to make sure this intentially falls through.
+ // TODO: Double check to make sure this intentionally falls through.
LLVM_FALLTHROUGH;
}
-
+
case Type::ObjCInterface: {
// Ignore protocol qualifiers when mangling at this level.
// @encode(class_name)
@@ -6567,7 +6790,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
SmallVector<const ObjCIvarDecl*, 32> Ivars;
DeepCollectObjCIvars(OI, true, Ivars);
for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
- const FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+ const FieldDecl *Field = Ivars[i];
if (Field->isBitField())
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
else
@@ -6582,7 +6805,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
case Type::ObjCObjectPointer: {
- const ObjCObjectPointerType *OPT = T->castAs<ObjCObjectPointerType>();
+ const auto *OPT = T->castAs<ObjCObjectPointerType>();
if (OPT->isObjCIdType()) {
S += '@';
return;
@@ -6591,7 +6814,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
// FIXME: Consider if we need to output qualifiers for 'Class<p>'.
// Since this is a binary compatibility issue, need to consult with runtime
- // folks. Fortunately, this is a *very* obsure construct.
+ // folks. Fortunately, this is a *very* obscure construct.
S += '#';
return;
}
@@ -6628,7 +6851,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
SmallVector<const ObjCIvarDecl*, 32> Ivars;
DeepCollectObjCIvars(OI, true, Ivars);
for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
- if (cast<FieldDecl>(Ivars[i]) == FD) {
+ if (Ivars[i] == FD) {
S += '{';
S += OI->getObjCRuntimeNameAsString();
S += '}';
@@ -6645,7 +6868,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
S += '@';
- if (OPT->getInterfaceDecl() &&
+ if (OPT->getInterfaceDecl() &&
(FD || EncodingProperty || EncodeClassNames)) {
S += '"';
S += OPT->getInterfaceDecl()->getObjCRuntimeNameAsString();
@@ -6670,7 +6893,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (NotEncodedT)
*NotEncodedT = T;
return;
-
+
// We could see an undeduced auto type here during error recovery.
// Just ignore it.
case Type::Auto:
@@ -6702,7 +6925,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
if (!RDecl->getDefinition() || RDecl->getDefinition()->isInvalidDecl())
return;
- CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl);
+ const auto *CXXRec = dyn_cast<CXXRecordDecl>(RDecl);
std::multimap<uint64_t, NamedDecl *> FieldOrBaseOffsets;
const ASTRecordLayout &layout = getASTRecordLayout(RDecl);
@@ -6718,7 +6941,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
}
}
}
-
+
unsigned i = 0;
for (auto *Field : RDecl->fields()) {
uint64_t offs = layout.getFieldOffset(i);
@@ -6779,7 +7002,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
#ifndef NDEBUG
assert(CurOffs <= CurLayObj->first);
if (CurOffs < CurLayObj->first) {
- uint64_t padding = CurLayObj->first - CurOffs;
+ uint64_t padding = CurLayObj->first - CurOffs;
// FIXME: There doesn't seem to be a way to indicate in the encoding that
// packing/alignment of members is different that normal, in which case
// the encoding will be out-of-sync with the real layout.
@@ -6795,7 +7018,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
if (!dcl)
break; // reached end of structure.
- if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) {
+ if (auto *base = dyn_cast<CXXRecordDecl>(dcl)) {
// We expand the bases without their virtual bases since those are going
// in the initial structure. Note that this differs from gcc which
// expands virtual bases each time one is encountered in the hierarchy,
@@ -6807,7 +7030,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
#endif
} else {
- FieldDecl *field = cast<FieldDecl>(dcl);
+ const auto *field = cast<FieldDecl>(dcl);
if (FD) {
S += '"';
S += field->getNameAsString();
@@ -6879,15 +7102,15 @@ TypedefDecl *ASTContext::getObjCClassDecl() const {
ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
if (!ObjCProtocolClassDecl) {
- ObjCProtocolClassDecl
- = ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
+ ObjCProtocolClassDecl
+ = ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
&Idents.get("Protocol"),
/*typeParamList=*/nullptr,
/*PrevDecl=*/nullptr,
- SourceLocation(), true);
+ SourceLocation(), true);
}
-
+
return ObjCProtocolClassDecl;
}
@@ -7250,6 +7473,10 @@ TypedefDecl *ASTContext::getBuiltinMSVaListDecl() const {
return BuiltinMSVaListDecl;
}
+bool ASTContext::canBuiltinBeRedeclared(const FunctionDecl *FD) const {
+ return BuiltinInfo.canBeRedeclared(FD->getBuiltinID());
+}
+
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
assert(ObjCConstantStringType.isNull() &&
"'NSConstantString' type already set!");
@@ -7257,7 +7484,7 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
ObjCConstantStringType = getObjCInterfaceType(Decl);
}
-/// \brief Retrieve the template name that corresponds to a non-empty
+/// Retrieve the template name that corresponds to a non-empty
/// lookup.
TemplateName
ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
@@ -7267,12 +7494,13 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
void *memory = Allocate(sizeof(OverloadedTemplateStorage) +
size * sizeof(FunctionTemplateDecl*));
- OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
+ auto *OT = new (memory) OverloadedTemplateStorage(size);
NamedDecl **Storage = OT->getStorage();
for (UnresolvedSetIterator I = Begin; I != End; ++I) {
NamedDecl *D = *I;
assert(isa<FunctionTemplateDecl>(D) ||
+ isa<UnresolvedUsingValueDecl>(D) ||
(isa<UsingShadowDecl>(D) &&
isa<FunctionTemplateDecl>(D->getUnderlyingDecl())));
*Storage++ = D;
@@ -7281,14 +7509,14 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
return TemplateName(OT);
}
-/// \brief Retrieve the template name that represents a qualified
+/// Retrieve the template name that represents a qualified
/// template name such as \c std::vector.
TemplateName
ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
TemplateDecl *Template) const {
assert(NNS && "Missing nested-name-specifier in qualified template name");
-
+
// FIXME: Canonicalization?
llvm::FoldingSetNodeID ID;
QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
@@ -7305,7 +7533,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
return TemplateName(QTN);
}
-/// \brief Retrieve the template name that represents a dependent
+/// Retrieve the template name that represents a dependent
/// template name such as \c MetaFun::template apply.
TemplateName
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
@@ -7341,24 +7569,24 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
return TemplateName(QTN);
}
-/// \brief Retrieve the template name that represents a dependent
+/// Retrieve the template name that represents a dependent
/// template name such as \c MetaFun::template operator+.
-TemplateName
+TemplateName
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) const {
assert((!NNS || NNS->isDependent()) &&
"Nested name specifier must be dependent");
-
+
llvm::FoldingSetNodeID ID;
DependentTemplateName::Profile(ID, NNS, Operator);
void *InsertPos = nullptr;
DependentTemplateName *QTN
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
-
+
if (QTN)
return TemplateName(QTN);
-
+
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
if (CanonNNS == NNS) {
QTN = new (*this, alignof(DependentTemplateName))
@@ -7373,12 +7601,12 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
assert(!CheckQTN && "Dependent template name canonicalization broken");
(void)CheckQTN;
}
-
+
DependentTemplateNames.InsertNode(QTN, InsertPos);
return TemplateName(QTN);
}
-TemplateName
+TemplateName
ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
TemplateName replacement) const {
llvm::FoldingSetNodeID ID;
@@ -7387,7 +7615,7 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
void *insertPos = nullptr;
SubstTemplateTemplateParmStorage *subst
= SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);
-
+
if (!subst) {
subst = new (*this) SubstTemplateTemplateParmStorage(param, replacement);
SubstTemplateTemplateParms.InsertNode(subst, insertPos);
@@ -7396,19 +7624,19 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
return TemplateName(subst);
}
-TemplateName
+TemplateName
ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
const TemplateArgument &ArgPack) const {
- ASTContext &Self = const_cast<ASTContext &>(*this);
+ auto &Self = const_cast<ASTContext &>(*this);
llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack);
void *InsertPos = nullptr;
SubstTemplateTemplateParmPackStorage *Subst
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
-
+
if (!Subst) {
- Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param,
+ Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param,
ArgPack.pack_size(),
ArgPack.pack_begin());
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
@@ -7422,7 +7650,7 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
/// is actually a value of type @c TargetInfo::IntType.
CanQualType ASTContext::getFromTargetType(unsigned Type) const {
switch (Type) {
- case TargetInfo::NoInt: return CanQualType();
+ case TargetInfo::NoInt: return {};
case TargetInfo::SignedChar: return SignedCharTy;
case TargetInfo::UnsignedChar: return UnsignedCharTy;
case TargetInfo::SignedShort: return ShortTy;
@@ -7465,7 +7693,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const {
// pointer.
#ifndef NDEBUG
QualType CT = Ty->getCanonicalTypeInternal();
- while (const ArrayType *AT = dyn_cast<ArrayType>(CT))
+ while (const auto *AT = dyn_cast<ArrayType>(CT))
CT = AT->getElementType();
assert(CT->isAnyPointerType() || CT->isBlockPointerType());
#endif
@@ -7496,8 +7724,8 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
// Treat Neon vector types and most AltiVec vector types as if they are the
// equivalent GCC vector types.
- const VectorType *First = FirstVec->getAs<VectorType>();
- const VectorType *Second = SecondVec->getAs<VectorType>();
+ const auto *First = FirstVec->getAs<VectorType>();
+ const auto *Second = SecondVec->getAs<VectorType>();
if (First->getNumElements() == Second->getNumElements() &&
hasSameType(First->getElementType(), Second->getElementType()) &&
First->getVectorKind() != VectorType::AltiVecPixel &&
@@ -7528,12 +7756,12 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
/// ObjCQualifiedClassTypesAreCompatible - compare Class<pr,...> and
/// Class<pr1, ...>.
-bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
+bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
QualType rhs) {
- const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
- const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ const auto *lhsQID = lhs->getAs<ObjCObjectPointerType>();
+ const auto *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
assert((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
-
+
for (auto *lhsProto : lhsQID->quals()) {
bool match = false;
for (auto *rhsProto : rhsOPT->quals()) {
@@ -7561,7 +7789,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return true;
if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
- const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ const auto *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
if (!rhsOPT) return false;
@@ -7638,7 +7866,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
if (!match)
return false;
}
-
+
// Static class's protocols, or its super class or category protocols
// must be found, direct or indirect in rhs's qualifier list or it is a mismatch.
if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
@@ -7700,12 +7928,12 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
QualType(RHSOPT,0),
false));
}
-
+
if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass()) {
return finish(ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0)));
}
-
+
// If we have 2 user-defined types, fall into that path.
if (LHS->getInterface() && RHS->getInterface()) {
return finish(canAssignObjCInterfaces(LHS, RHS));
@@ -7715,7 +7943,7 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
}
/// canAssignObjCInterfacesInBlockPointer - This routine is specifically written
-/// for providing type-safety for objective-c pointers used to pass/return
+/// for providing type-safety for objective-c pointers used to pass/return
/// arguments in block literals. When passed as arguments, passing 'A*' where
/// 'id' is expected is not OK. Passing 'Sub *" where 'Super *" is expected is
/// not OK. For the return type, the opposite is not OK.
@@ -7744,17 +7972,17 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType())
return true;
-
+
if (LHSOPT->isObjCBuiltinType()) {
return finish(RHSOPT->isObjCBuiltinType() ||
RHSOPT->isObjCQualifiedIdType());
}
-
+
if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
return finish(ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false));
-
+
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
if (LHS && RHS) { // We have 2 user-defined types.
@@ -7782,13 +8010,13 @@ static int compareObjCProtocolsByName(ObjCProtocolDecl * const *lhs,
/// the given common base.
/// It is used to build composite qualifier list of the composite type of
/// the conditional expression involving two objective-c pointer objects.
-static
+static
void getIntersectionOfProtocols(ASTContext &Context,
const ObjCInterfaceDecl *CommonBase,
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT,
SmallVectorImpl<ObjCProtocolDecl *> &IntersectionSet) {
-
+
const ObjCObjectType* LHS = LHSOPT->getObjectType();
const ObjCObjectType* RHS = RHSOPT->getObjectType();
assert(LHS->getInterface() && "LHS must have an interface base");
@@ -7847,14 +8075,14 @@ void getIntersectionOfProtocols(ASTContext &Context,
static bool canAssignObjCObjectTypes(ASTContext &ctx, QualType lhs,
QualType rhs) {
// Common case: two object pointers.
- const ObjCObjectPointerType *lhsOPT = lhs->getAs<ObjCObjectPointerType>();
- const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ const auto *lhsOPT = lhs->getAs<ObjCObjectPointerType>();
+ const auto *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
if (lhsOPT && rhsOPT)
return ctx.canAssignObjCInterfaces(lhsOPT, rhsOPT);
// Two block pointers.
- const BlockPointerType *lhsBlock = lhs->getAs<BlockPointerType>();
- const BlockPointerType *rhsBlock = rhs->getAs<BlockPointerType>();
+ const auto *lhsBlock = lhs->getAs<BlockPointerType>();
+ const auto *rhsBlock = rhs->getAs<BlockPointerType>();
if (lhsBlock && rhsBlock)
return ctx.typesAreBlockPointerCompatible(lhs, rhs);
@@ -7914,7 +8142,7 @@ QualType ASTContext::areCommonBaseCompatible(
const ObjCInterfaceDecl* RDecl = RHS->getInterface();
if (!LDecl || !RDecl)
- return QualType();
+ return {};
// When either LHS or RHS is a kindof type, we should return a kindof type.
// For example, for common base of kindof(ASub1) and kindof(ASub2), we return
@@ -7939,7 +8167,7 @@ QualType ASTContext::areCommonBaseCompatible(
if (!sameObjCTypeArgs(*this, LHS->getInterface(),
LHS->getTypeArgs(), RHS->getTypeArgs(),
/*stripKindOf=*/true))
- return QualType();
+ return {};
} else if (LHS->isSpecialized() != RHS->isSpecialized()) {
// If only one has type arguments, the result will not have type
// arguments.
@@ -7990,7 +8218,7 @@ QualType ASTContext::areCommonBaseCompatible(
if (!sameObjCTypeArgs(*this, LHS->getInterface(),
LHS->getTypeArgs(), RHS->getTypeArgs(),
/*stripKindOf=*/true))
- return QualType();
+ return {};
} else if (LHS->isSpecialized() != RHS->isSpecialized()) {
// If only one has type arguments, the result will not have type
// arguments.
@@ -8025,7 +8253,7 @@ QualType ASTContext::areCommonBaseCompatible(
RHS = RHSSuperType->castAs<ObjCObjectType>();
}
- return QualType();
+ return {};
}
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
@@ -8057,7 +8285,7 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
// If there is no protocols associated with RHS, it is not a match.
if (SuperClassInheritedProtocols.empty())
return false;
-
+
for (const auto *LHSProto : LHS->quals()) {
bool SuperImplementsProtocol = false;
for (auto *SuperClassProto : SuperClassInheritedProtocols)
@@ -8092,8 +8320,8 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
// get the "pointed to" types
- const ObjCObjectPointerType *LHSOPT = LHS->getAs<ObjCObjectPointerType>();
- const ObjCObjectPointerType *RHSOPT = RHS->getAs<ObjCObjectPointerType>();
+ const auto *LHSOPT = LHS->getAs<ObjCObjectPointerType>();
+ const auto *RHSOPT = RHS->getAs<ObjCObjectPointerType>();
if (!LHSOPT || !RHSOPT)
return false;
@@ -8146,7 +8374,7 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType,
}
}
- return QualType();
+ return {};
}
/// mergeFunctionParameterTypes - merge two types which appear as function
@@ -8170,13 +8398,13 @@ QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs,
return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified);
}
-QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
+QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
bool OfBlockPointer,
bool Unqualified) {
- const FunctionType *lbase = lhs->getAs<FunctionType>();
- const FunctionType *rbase = rhs->getAs<FunctionType>();
- const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
- const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(rbase);
+ const auto *lbase = lhs->getAs<FunctionType>();
+ const auto *rbase = rhs->getAs<FunctionType>();
+ const auto *lproto = dyn_cast<FunctionProtoType>(lbase);
+ const auto *rproto = dyn_cast<FunctionProtoType>(rbase);
bool allLTypes = true;
bool allRTypes = true;
@@ -8193,8 +8421,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
else
retType = mergeTypes(lbase->getReturnType(), rbase->getReturnType(), false,
Unqualified);
- if (retType.isNull()) return QualType();
-
+ if (retType.isNull())
+ return {};
+
if (Unqualified)
retType = retType.getUnqualifiedType();
@@ -8204,7 +8433,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
LRetType = LRetType.getUnqualifiedType();
RRetType = RRetType.getUnqualifiedType();
}
-
+
if (getCanonicalType(retType) != LRetType)
allLTypes = false;
if (getCanonicalType(retType) != RRetType)
@@ -8219,18 +8448,20 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
// Compatible functions must have compatible calling conventions
if (lbaseInfo.getCC() != rbaseInfo.getCC())
- return QualType();
+ return {};
// Regparm is part of the calling convention.
if (lbaseInfo.getHasRegParm() != rbaseInfo.getHasRegParm())
- return QualType();
+ return {};
if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm())
- return QualType();
+ return {};
if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
- return QualType();
+ return {};
if (lbaseInfo.getNoCallerSavedRegs() != rbaseInfo.getNoCallerSavedRegs())
- return QualType();
+ return {};
+ if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck())
+ return {};
// FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
@@ -8247,20 +8478,20 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
"C++ shouldn't be here");
// Compatible functions must have the same number of parameters
if (lproto->getNumParams() != rproto->getNumParams())
- return QualType();
+ return {};
// Variadic and non-variadic functions aren't compatible
if (lproto->isVariadic() != rproto->isVariadic())
- return QualType();
+ return {};
if (lproto->getTypeQuals() != rproto->getTypeQuals())
- return QualType();
+ return {};
SmallVector<FunctionProtoType::ExtParameterInfo, 4> newParamInfos;
bool canUseLeft, canUseRight;
if (!mergeExtParameterInfo(lproto, rproto, canUseLeft, canUseRight,
newParamInfos))
- return QualType();
+ return {};
if (!canUseLeft)
allLTypes = false;
@@ -8275,7 +8506,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
QualType paramType = mergeFunctionParameterTypes(
lParamType, rParamType, OfBlockPointer, Unqualified);
if (paramType.isNull())
- return QualType();
+ return {};
if (Unqualified)
paramType = paramType.getUnqualifiedType();
@@ -8291,7 +8522,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (getCanonicalType(paramType) != getCanonicalType(rParamType))
allRTypes = false;
}
-
+
if (allLTypes) return lhs;
if (allRTypes) return rhs;
@@ -8308,7 +8539,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
const FunctionProtoType *proto = lproto ? lproto : rproto;
if (proto) {
assert(!proto->hasExceptionSpec() && "C++ shouldn't be here");
- if (proto->isVariadic()) return QualType();
+ if (proto->isVariadic())
+ return {};
// Check that the types are compatible with the types that
// would result from default argument promotions (C99 6.7.5.3p15).
// The only types actually affected are promotable integer
@@ -8319,15 +8551,15 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
// Look at the converted type of enum types, since that is the type used
// to pass enum values.
- if (const EnumType *Enum = paramTy->getAs<EnumType>()) {
+ if (const auto *Enum = paramTy->getAs<EnumType>()) {
paramTy = Enum->getDecl()->getIntegerType();
if (paramTy.isNull())
- return QualType();
+ return {};
}
if (paramTy->isPromotableIntegerType() ||
getCanonicalType(paramTy).getUnqualifiedType() == FloatTy)
- return QualType();
+ return {};
}
if (allLTypes) return lhs;
@@ -8351,7 +8583,8 @@ static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET,
// Compatibility is based on the underlying type, not the promotion
// type.
QualType underlyingType = ET->getDecl()->getIntegerType();
- if (underlyingType.isNull()) return QualType();
+ if (underlyingType.isNull())
+ return {};
if (Context.hasSameType(underlyingType, other))
return other;
@@ -8361,10 +8594,10 @@ static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET,
Context.getTypeSize(underlyingType) == Context.getTypeSize(other))
return other;
- return QualType();
+ return {};
}
-QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
+QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
bool OfBlockPointer,
bool Unqualified, bool BlockReturnType) {
// C++ [expr]: If an expression initially has the type "reference to T", the
@@ -8379,7 +8612,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
LHS = LHS.getUnqualifiedType();
RHS = RHS.getUnqualifiedType();
}
-
+
QualType LHSCan = getCanonicalType(LHS),
RHSCan = getCanonicalType(RHS);
@@ -8397,7 +8630,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
LQuals.getAddressSpace() != RQuals.getAddressSpace() ||
LQuals.getObjCLifetime() != RQuals.getObjCLifetime() ||
LQuals.hasUnaligned() != RQuals.hasUnaligned())
- return QualType();
+ return {};
// Exactly one GC qualifier difference is allowed: __strong is
// okay if the other type has no GC qualifier but is an Objective
@@ -8409,7 +8642,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
- return QualType();
+ return {};
if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) {
return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong));
@@ -8417,7 +8650,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) {
return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS);
}
- return QualType();
+ return {};
}
// Okay, qualifiers are equal.
@@ -8448,7 +8681,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
if (LHSClass != RHSClass) {
// Note that we only have special rules for turning block enum
// returns into block int returns, not vice-versa.
- if (const EnumType* ETy = LHS->getAs<EnumType>()) {
+ if (const auto *ETy = LHS->getAs<EnumType>()) {
return mergeEnumWithInteger(*this, ETy, RHS, false);
}
if (const EnumType* ETy = RHS->getAs<EnumType>()) {
@@ -8461,8 +8694,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
if (RHS->isObjCIdType() && LHS->isBlockPointerType())
return RHS;
}
-
- return QualType();
+
+ return {};
}
// The canonical type classes match.
@@ -8498,9 +8731,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
LHSPointee = LHSPointee.getUnqualifiedType();
RHSPointee = RHSPointee.getUnqualifiedType();
}
- QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false,
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false,
Unqualified);
- if (ResultType.isNull()) return QualType();
+ if (ResultType.isNull())
+ return {};
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType))
@@ -8522,7 +8756,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// Blocks can't be an expression in a ternary operator (OpenCL v2.0
// 6.12.5) thus the following check is asymmetric.
if (!LHSPteeQual.isAddressSpaceSupersetOf(RHSPteeQual))
- return QualType();
+ return {};
LHSPteeQual.removeAddressSpace();
RHSPteeQual.removeAddressSpace();
LHSPointee =
@@ -8532,7 +8766,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
}
QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
Unqualified);
- if (ResultType.isNull()) return QualType();
+ if (ResultType.isNull())
+ return {};
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType))
@@ -8548,9 +8783,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
LHSValue = LHSValue.getUnqualifiedType();
RHSValue = RHSValue.getUnqualifiedType();
}
- QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
+ QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
Unqualified);
- if (ResultType.isNull()) return QualType();
+ if (ResultType.isNull())
+ return {};
if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
return LHS;
if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
@@ -8562,7 +8798,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
const ConstantArrayType* LCAT = getAsConstantArrayType(LHS);
const ConstantArrayType* RCAT = getAsConstantArrayType(RHS);
if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize())
- return QualType();
+ return {};
QualType LHSElem = getAsArrayType(LHS)->getElementType();
QualType RHSElem = getAsArrayType(RHS)->getElementType();
@@ -8570,9 +8806,42 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
LHSElem = LHSElem.getUnqualifiedType();
RHSElem = RHSElem.getUnqualifiedType();
}
-
+
QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
- if (ResultType.isNull()) return QualType();
+ if (ResultType.isNull())
+ return {};
+
+ const VariableArrayType* LVAT = getAsVariableArrayType(LHS);
+ const VariableArrayType* RVAT = getAsVariableArrayType(RHS);
+
+ // If either side is a variable array, and both are complete, check whether
+ // the current dimension is definite.
+ if (LVAT || RVAT) {
+ auto SizeFetch = [this](const VariableArrayType* VAT,
+ const ConstantArrayType* CAT)
+ -> std::pair<bool,llvm::APInt> {
+ if (VAT) {
+ llvm::APSInt TheInt;
+ Expr *E = VAT->getSizeExpr();
+ if (E && E->isIntegerConstantExpr(TheInt, *this))
+ return std::make_pair(true, TheInt);
+ else
+ return std::make_pair(false, TheInt);
+ } else if (CAT) {
+ return std::make_pair(true, CAT->getSize());
+ } else {
+ return std::make_pair(false, llvm::APInt());
+ }
+ };
+
+ bool HaveLSize, HaveRSize;
+ llvm::APInt LSize, RSize;
+ std::tie(HaveLSize, LSize) = SizeFetch(LVAT, LCAT);
+ std::tie(HaveRSize, RSize) = SizeFetch(RVAT, RCAT);
+ if (HaveLSize && HaveRSize && !llvm::APInt::isSameValue(LSize, RSize))
+ return {}; // Definite, but unequal, array dimension
+ }
+
if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
return LHS;
if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
@@ -8581,8 +8850,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
ArrayType::ArraySizeModifier(), 0);
if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(),
ArrayType::ArraySizeModifier(), 0);
- const VariableArrayType* LVAT = getAsVariableArrayType(LHS);
- const VariableArrayType* RVAT = getAsVariableArrayType(RHS);
if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
return LHS;
if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
@@ -8608,29 +8875,29 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified);
case Type::Record:
case Type::Enum:
- return QualType();
+ return {};
case Type::Builtin:
// Only exactly equal builtin types are compatible, which is tested above.
- return QualType();
+ return {};
case Type::Complex:
// Distinct complex types are incompatible.
- return QualType();
+ return {};
case Type::Vector:
// FIXME: The merged type should be an ExtVector!
if (areCompatVectorTypes(LHSCan->getAs<VectorType>(),
RHSCan->getAs<VectorType>()))
return LHS;
- return QualType();
+ return {};
case Type::ObjCObject: {
// Check if the types are assignment compatible.
// FIXME: This should be type compatibility, e.g. whether
// "LHS x; RHS x;" at global scope is legal.
- const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>();
- const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>();
+ const auto *LHSIface = LHS->getAs<ObjCObjectType>();
+ const auto *RHSIface = RHS->getAs<ObjCObjectType>();
if (canAssignObjCInterfaces(LHSIface, RHSIface))
return LHS;
- return QualType();
+ return {};
}
case Type::ObjCObjectPointer:
if (OfBlockPointer) {
@@ -8639,17 +8906,17 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
RHS->getAs<ObjCObjectPointerType>(),
BlockReturnType))
return LHS;
- return QualType();
+ return {};
}
if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(),
RHS->getAs<ObjCObjectPointerType>()))
return LHS;
- return QualType();
+ return {};
case Type::Pipe:
assert(LHS != RHS &&
"Equivalent pipe types should have already been handled!");
- return QualType();
+ return {};
}
llvm_unreachable("Invalid Type::Class!");
@@ -8717,20 +8984,20 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
return LHS;
if (RHSCan->isFunctionType()) {
if (!LHSCan->isFunctionType())
- return QualType();
+ return {};
QualType OldReturnType =
cast<FunctionType>(RHSCan.getTypePtr())->getReturnType();
QualType NewReturnType =
cast<FunctionType>(LHSCan.getTypePtr())->getReturnType();
- QualType ResReturnType =
+ QualType ResReturnType =
mergeObjCGCQualifiers(NewReturnType, OldReturnType);
if (ResReturnType.isNull())
- return QualType();
+ return {};
if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) {
// id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo();
// In either case, use OldReturnType to build the new function type.
- const FunctionType *F = LHS->getAs<FunctionType>();
- if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) {
+ const auto *F = LHS->getAs<FunctionType>();
+ if (const auto *FPT = cast<FunctionProtoType>(F)) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExtInfo = getFunctionExtInfo(LHS);
QualType ResultType =
@@ -8738,9 +9005,9 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
return ResultType;
}
}
- return QualType();
+ return {};
}
-
+
// If the qualifiers are different, the types can still be merged.
Qualifiers LQuals = LHSCan.getLocalQualifiers();
Qualifiers RQuals = RHSCan.getLocalQualifiers();
@@ -8748,8 +9015,8 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
// If any of these qualifiers are different, we have a type mismatch.
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
LQuals.getAddressSpace() != RQuals.getAddressSpace())
- return QualType();
-
+ return {};
+
// Exactly one GC qualifier difference is allowed: __strong is
// okay if the other type has no GC qualifier but is an Objective
// C object pointer (i.e. implicitly strong by default). We fix
@@ -8758,17 +9025,17 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
-
+
if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
- return QualType();
-
+ return {};
+
if (GC_L == Qualifiers::Strong)
return LHS;
if (GC_R == Qualifiers::Strong)
return RHS;
- return QualType();
+ return {};
}
-
+
if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) {
QualType LHSBaseQT = LHS->getAs<ObjCObjectPointerType>()->getPointeeType();
QualType RHSBaseQT = RHS->getAs<ObjCObjectPointerType>()->getPointeeType();
@@ -8778,7 +9045,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
if (ResQT == RHSBaseQT)
return RHS;
}
- return QualType();
+ return {};
}
//===----------------------------------------------------------------------===//
@@ -8786,7 +9053,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
//===----------------------------------------------------------------------===//
unsigned ASTContext::getIntWidth(QualType T) const {
- if (const EnumType *ET = T->getAs<EnumType>())
+ if (const auto *ET = T->getAs<EnumType>())
T = ET->getDecl()->getIntegerType();
if (T->isBooleanType())
return 1;
@@ -8795,19 +9062,20 @@ unsigned ASTContext::getIntWidth(QualType T) const {
}
QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
- assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
-
+ assert((T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) &&
+ "Unexpected type");
+
// Turn <4 x signed int> -> <4 x unsigned int>
- if (const VectorType *VTy = T->getAs<VectorType>())
+ if (const auto *VTy = T->getAs<VectorType>())
return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
VTy->getNumElements(), VTy->getVectorKind());
// For enums, we return the unsigned version of the base type.
- if (const EnumType *ETy = T->getAs<EnumType>())
+ if (const auto *ETy = T->getAs<EnumType>())
T = ETy->getDecl()->getIntegerType();
-
- const BuiltinType *BTy = T->getAs<BuiltinType>();
- assert(BTy && "Unexpected signed integer type");
+
+ const auto *BTy = T->getAs<BuiltinType>();
+ assert(BTy && "Unexpected signed integer or fixed point type");
switch (BTy->getKind()) {
case BuiltinType::Char_S:
case BuiltinType::SChar:
@@ -8822,8 +9090,33 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
return UnsignedLongLongTy;
case BuiltinType::Int128:
return UnsignedInt128Ty;
+
+ case BuiltinType::ShortAccum:
+ return UnsignedShortAccumTy;
+ case BuiltinType::Accum:
+ return UnsignedAccumTy;
+ case BuiltinType::LongAccum:
+ return UnsignedLongAccumTy;
+ case BuiltinType::SatShortAccum:
+ return SatUnsignedShortAccumTy;
+ case BuiltinType::SatAccum:
+ return SatUnsignedAccumTy;
+ case BuiltinType::SatLongAccum:
+ return SatUnsignedLongAccumTy;
+ case BuiltinType::ShortFract:
+ return UnsignedShortFractTy;
+ case BuiltinType::Fract:
+ return UnsignedFractTy;
+ case BuiltinType::LongFract:
+ return UnsignedLongFractTy;
+ case BuiltinType::SatShortFract:
+ return SatUnsignedShortFractTy;
+ case BuiltinType::SatFract:
+ return SatUnsignedFractTy;
+ case BuiltinType::SatLongFract:
+ return SatUnsignedLongFractTy;
default:
- llvm_unreachable("Unexpected signed integer type");
+ llvm_unreachable("Unexpected signed integer or fixed point type");
}
}
@@ -8852,7 +9145,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
int HowLong = 0;
bool Signed = false, Unsigned = false;
RequiresICE = false;
-
+
// Read the prefixed modifiers first.
bool Done = false;
#ifndef NDEBUG
@@ -8931,10 +9224,12 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
Type = Context.FloatTy;
break;
case 'd':
- assert(HowLong < 2 && !Signed && !Unsigned &&
+ assert(HowLong < 3 && !Signed && !Unsigned &&
"Bad modifiers used with 'd'!");
- if (HowLong)
+ if (HowLong == 1)
Type = Context.LongDoubleTy;
+ else if (HowLong == 2)
+ Type = Context.Float128Ty;
else
Type = Context.DoubleTy;
break;
@@ -9014,10 +9309,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
assert(End != Str && "Missing vector size");
Str = End;
- QualType ElementType = DecodeTypeFromStr(Str, Context, Error,
+ QualType ElementType = DecodeTypeFromStr(Str, Context, Error,
RequiresICE, false);
assert(!RequiresICE && "Can't require vector ICE");
-
+
// TODO: No way to make AltiVec vectors in builtins yet.
Type = Context.getVectorType(ElementType, NumElements,
VectorType::GenericVector);
@@ -9025,16 +9320,16 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
}
case 'E': {
char *End;
-
+
unsigned NumElements = strtoul(Str, &End, 10);
assert(End != Str && "Missing vector size");
-
+
Str = End;
-
+
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE,
false);
Type = Context.getExtVectorType(ElementType, NumElements);
- break;
+ break;
}
case 'X': {
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE,
@@ -9042,7 +9337,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
assert(!RequiresICE && "Can't require complex ICE");
Type = Context.getComplexType(ElementType);
break;
- }
+ }
case 'Y':
Type = Context.getPointerDiffType();
break;
@@ -9050,7 +9345,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
Type = Context.getFILEType();
if (Type.isNull()) {
Error = ASTContext::GE_Missing_stdio;
- return QualType();
+ return {};
}
break;
case 'J':
@@ -9061,7 +9356,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
if (Type.isNull()) {
Error = ASTContext::GE_Missing_setjmp;
- return QualType();
+ return {};
}
break;
case 'K':
@@ -9070,7 +9365,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
if (Type.isNull()) {
Error = ASTContext::GE_Missing_ucontext;
- return QualType();
+ return {};
}
break;
case 'p':
@@ -9112,9 +9407,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
break;
}
}
-
+
assert((!RequiresICE || Type->isIntegralOrEnumerationType()) &&
- "Integer constant 'I' type must be an integer");
+ "Integer constant 'I' type must be an integer");
return Type;
}
@@ -9132,20 +9427,20 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error,
RequiresICE, true);
if (Error != GE_None)
- return QualType();
-
+ return {};
+
assert(!RequiresICE && "Result of intrinsic cannot be required to be an ICE");
-
+
while (TypeStr[0] && TypeStr[0] != '.') {
QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true);
if (Error != GE_None)
- return QualType();
+ return {};
// If this argument is required to be an IntegerConstantExpression and the
// caller cares, fill in the bitmask we return.
if (RequiresICE && IntegerConstantArgs)
*IntegerConstantArgs |= 1 << ArgTypes.size();
-
+
// Do array -> pointer decay. The builtin should use the decayed type.
if (Ty->isArrayType())
Ty = getArrayDecayedType(Ty);
@@ -9154,7 +9449,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
}
if (Id == Builtin::BI__GetExceptionInfo)
- return QualType();
+ return {};
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
@@ -9185,7 +9480,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
// 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 (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
if (!MD->isUserProvided())
return GVA_DiscardableODR;
@@ -9375,7 +9670,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
}
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (!VD->isFileVarDecl())
return false;
// Global named register variables (GNU extension) are never emitted.
@@ -9384,14 +9679,13 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (VD->getDescribedVarTemplate() ||
isa<VarTemplatePartialSpecializationDecl>(VD))
return false;
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// We never need to emit an uninstantiated function template.
if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
return false;
} else if (isa<PragmaCommentDecl>(D))
return true;
- else if (isa<OMPThreadPrivateDecl>(D) ||
- D->hasAttr<OMPDeclareTargetDeclAttr>())
+ else if (isa<OMPThreadPrivateDecl>(D))
return true;
else if (isa<PragmaDetectMismatchDecl>(D))
return true;
@@ -9404,6 +9698,29 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
else
return false;
+ if (D->isFromASTFile() && !LangOpts.BuildingPCHWithObjectFile) {
+ assert(getExternalSource() && "It's from an AST file; must have a source.");
+ // On Windows, PCH files are built together with an object file. If this
+ // declaration comes from such a PCH and DeclMustBeEmitted would return
+ // true, it would have returned true and the decl would have been emitted
+ // into that object file, so it doesn't need to be emitted here.
+ // Note that decls are still emitted if they're referenced, as usual;
+ // DeclMustBeEmitted is used to decide whether a decl must be emitted even
+ // if it's not referenced.
+ //
+ // Explicit template instantiation definitions are tricky. If there was an
+ // explicit template instantiation decl in the PCH before, it will look like
+ // the definition comes from there, even if that was just the declaration.
+ // (Explicit instantiation defs of variable templates always get emitted.)
+ bool IsExpInstDef =
+ isa<FunctionDecl>(D) &&
+ cast<FunctionDecl>(D)->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+
+ if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef)
+ return false;
+ }
+
// If this is a member of a class template, we do not need to emit it.
if (D->getDeclContext()->isDependentContext())
return false;
@@ -9416,7 +9733,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
return true;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Forward declarations aren't required.
if (!FD->doesThisDeclarationHaveABody())
return FD->doesDeclarationForceExternallyVisibleDefinition();
@@ -9424,11 +9741,11 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// Constructors and destructors are required.
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
return true;
-
+
// The key function for a class is required. This rule only comes
// into play when inline functions can be key functions, though.
if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
const CXXRecordDecl *RD = MD->getParent();
if (MD->isOutOfLine() && RD->isDynamicClass()) {
const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD);
@@ -9445,8 +9762,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// Implicit template instantiations can also be deferred in C++.
return !isDiscardableGVALinkage(Linkage);
}
-
- const VarDecl *VD = cast<VarDecl>(D);
+
+ const auto *VD = cast<VarDecl>(D);
assert(VD->isFileVarDecl() && "Expected file scoped var");
if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly &&
@@ -9474,15 +9791,37 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// Likewise, variables with tuple-like bindings are required if their
// bindings have side-effects.
- if (auto *DD = dyn_cast<DecompositionDecl>(VD))
- for (auto *BD : DD->bindings())
- if (auto *BindingVD = BD->getHoldingVar())
+ if (const auto *DD = dyn_cast<DecompositionDecl>(VD))
+ for (const auto *BD : DD->bindings())
+ if (const auto *BindingVD = BD->getHoldingVar())
if (DeclMustBeEmitted(BindingVD))
return true;
+ // If the decl is marked as `declare target`, it should be emitted.
+ if (const llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ return *Res != OMPDeclareTargetDeclAttr::MT_Link;
+
return false;
}
+void ASTContext::forEachMultiversionedFunctionVersion(
+ const FunctionDecl *FD,
+ llvm::function_ref<void(FunctionDecl *)> Pred) const {
+ assert(FD->isMultiVersion() && "Only valid for multiversioned functions");
+ llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls;
+ FD = FD->getCanonicalDecl();
+ for (auto *CurDecl :
+ FD->getDeclContext()->getRedeclContext()->lookup(FD->getDeclName())) {
+ FunctionDecl *CurFD = CurDecl->getAsFunction()->getCanonicalDecl();
+ if (CurFD && hasSameType(CurFD->getType(), FD->getType()) &&
+ std::end(SeenDecls) == llvm::find(SeenDecls, CurFD)) {
+ SeenDecls.insert(CurFD);
+ Pred(CurFD);
+ }
+ }
+}
+
CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
bool IsCXXMethod) const {
// Pass through to the C++ ABI object
@@ -9595,7 +9934,7 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const {
case TargetInfo::Float128:
return Float128Ty;
case TargetInfo::NoFloat:
- return QualType();
+ return {};
}
llvm_unreachable("Unhandled TargetInfo::RealType value");
@@ -9673,7 +10012,7 @@ void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const {
ParameterIndexTable::const_iterator I = ParamIndices.find(D);
- assert(I != ParamIndices.end() &&
+ assert(I != ParamIndices.end() &&
"ParmIndices lacks entry set by ParmVarDecl");
return I->second;
}
@@ -9739,7 +10078,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
}
/// @}
- /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their
+ /// A \c RecursiveASTVisitor that builds a map from nodes to their
/// parents as defined by the \c RecursiveASTVisitor.
///
/// Note that the relationship described here is purely in terms of AST
@@ -9749,7 +10088,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> {
public:
- /// \brief Builds and returns the translation unit's parent map.
+ /// Builds and returns the translation unit's parent map.
///
/// The caller takes ownership of the returned \c ParentMap.
static std::pair<ASTContext::ParentMapPointers *,
@@ -9874,7 +10213,8 @@ static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
if (I == Map.end()) {
return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
}
- if (auto *V = I->second.template dyn_cast<ASTContext::ParentVector *>()) {
+ if (const auto *V =
+ I->second.template dyn_cast<ASTContext::ParentVector *>()) {
return llvm::makeArrayRef(*V);
}
return getSingleDynTypedNodeFromParentMap(I->second);
@@ -9906,10 +10246,10 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
return false;
if (!hasSameType(MethodDecl->getReturnType(), MethodImpl->getReturnType()))
return false;
-
+
if (MethodDecl->param_size() != MethodImpl->param_size())
return false;
-
+
for (ObjCMethodDecl::param_const_iterator IM = MethodImpl->param_begin(),
IF = MethodDecl->param_begin(), EM = MethodImpl->param_end(),
EF = MethodDecl->param_end();
@@ -9942,6 +10282,42 @@ unsigned ASTContext::getTargetAddressSpace(LangAS AS) const {
return (*AddrSpaceMap)[(unsigned)AS];
}
+QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const {
+ assert(Ty->isFixedPointType());
+
+ if (Ty->isSaturatedFixedPointType()) return Ty;
+
+ const auto &BT = Ty->getAs<BuiltinType>();
+ switch (BT->getKind()) {
+ default:
+ llvm_unreachable("Not a fixed point type!");
+ case BuiltinType::ShortAccum:
+ return SatShortAccumTy;
+ case BuiltinType::Accum:
+ return SatAccumTy;
+ case BuiltinType::LongAccum:
+ return SatLongAccumTy;
+ case BuiltinType::UShortAccum:
+ return SatUnsignedShortAccumTy;
+ case BuiltinType::UAccum:
+ return SatUnsignedAccumTy;
+ case BuiltinType::ULongAccum:
+ return SatUnsignedLongAccumTy;
+ case BuiltinType::ShortFract:
+ return SatShortFractTy;
+ case BuiltinType::Fract:
+ return SatFractTy;
+ case BuiltinType::LongFract:
+ return SatLongFractTy;
+ case BuiltinType::UShortFract:
+ return SatUnsignedShortFractTy;
+ case BuiltinType::UFract:
+ return SatUnsignedFractTy;
+ case BuiltinType::ULongFract:
+ return SatUnsignedLongFractTy;
+ }
+}
+
// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
// doesn't include ASTContext.h
template
@@ -9950,3 +10326,92 @@ clang::LazyGenerationalUpdatePtr<
clang::LazyGenerationalUpdatePtr<
const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue(
const clang::ASTContext &Ctx, Decl *Value);
+
+unsigned char ASTContext::getFixedPointScale(QualType Ty) const {
+ assert(Ty->isFixedPointType());
+
+ const auto *BT = Ty->getAs<BuiltinType>();
+ const TargetInfo &Target = getTargetInfo();
+ switch (BT->getKind()) {
+ default:
+ llvm_unreachable("Not a fixed point type!");
+ case BuiltinType::ShortAccum:
+ case BuiltinType::SatShortAccum:
+ return Target.getShortAccumScale();
+ case BuiltinType::Accum:
+ case BuiltinType::SatAccum:
+ return Target.getAccumScale();
+ case BuiltinType::LongAccum:
+ case BuiltinType::SatLongAccum:
+ return Target.getLongAccumScale();
+ case BuiltinType::UShortAccum:
+ case BuiltinType::SatUShortAccum:
+ return Target.getUnsignedShortAccumScale();
+ case BuiltinType::UAccum:
+ case BuiltinType::SatUAccum:
+ return Target.getUnsignedAccumScale();
+ case BuiltinType::ULongAccum:
+ case BuiltinType::SatULongAccum:
+ return Target.getUnsignedLongAccumScale();
+ case BuiltinType::ShortFract:
+ case BuiltinType::SatShortFract:
+ return Target.getShortFractScale();
+ case BuiltinType::Fract:
+ case BuiltinType::SatFract:
+ return Target.getFractScale();
+ case BuiltinType::LongFract:
+ case BuiltinType::SatLongFract:
+ return Target.getLongFractScale();
+ case BuiltinType::UShortFract:
+ case BuiltinType::SatUShortFract:
+ return Target.getUnsignedShortFractScale();
+ case BuiltinType::UFract:
+ case BuiltinType::SatUFract:
+ return Target.getUnsignedFractScale();
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatULongFract:
+ return Target.getUnsignedLongFractScale();
+ }
+}
+
+unsigned char ASTContext::getFixedPointIBits(QualType Ty) const {
+ assert(Ty->isFixedPointType());
+
+ const auto *BT = Ty->getAs<BuiltinType>();
+ const TargetInfo &Target = getTargetInfo();
+ switch (BT->getKind()) {
+ default:
+ llvm_unreachable("Not a fixed point type!");
+ case BuiltinType::ShortAccum:
+ case BuiltinType::SatShortAccum:
+ return Target.getShortAccumIBits();
+ case BuiltinType::Accum:
+ case BuiltinType::SatAccum:
+ return Target.getAccumIBits();
+ case BuiltinType::LongAccum:
+ case BuiltinType::SatLongAccum:
+ return Target.getLongAccumIBits();
+ case BuiltinType::UShortAccum:
+ case BuiltinType::SatUShortAccum:
+ return Target.getUnsignedShortAccumIBits();
+ case BuiltinType::UAccum:
+ case BuiltinType::SatUAccum:
+ return Target.getUnsignedAccumIBits();
+ case BuiltinType::ULongAccum:
+ case BuiltinType::SatULongAccum:
+ return Target.getUnsignedLongAccumIBits();
+ case BuiltinType::ShortFract:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::SatFract:
+ case BuiltinType::LongFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatULongFract:
+ return 0;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
index b43c28deb362..50d2d2999e51 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
@@ -200,7 +200,7 @@ break; \
return QC.apply(Context, QT);
}
-/// \brief Convert the given type to a string suitable for printing as part of
+/// Convert the given type to a string suitable for printing as part of
/// a diagnostic.
///
/// There are four main criteria when determining whether we should have an
@@ -254,7 +254,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
// and the desugared comparison string.
std::string CompareCanS =
CompareCanTy.getAsString(Context.getPrintingPolicy());
-
+
if (CompareCanS == CanS)
continue; // No new info from canonical type
@@ -327,11 +327,11 @@ void clang::FormatASTNodeDiagnosticArgument(
void *Cookie,
ArrayRef<intptr_t> QualTypeVals) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
-
+
size_t OldEnd = Output.size();
llvm::raw_svector_ostream OS(Output);
bool NeedQuotes = true;
-
+
switch (Kind) {
default: llvm_unreachable("unknown ArgumentKind");
case DiagnosticsEngine::ak_qualtype_pair: {
@@ -365,7 +365,7 @@ void clang::FormatASTNodeDiagnosticArgument(
case DiagnosticsEngine::ak_qualtype: {
assert(Modifier.empty() && Argument.empty() &&
"Invalid modifier for QualType argument");
-
+
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals);
NeedQuotes = false;
@@ -2040,7 +2040,7 @@ public:
/// is successful.
static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
QualType ToType, bool PrintTree,
- bool PrintFromType, bool ElideType,
+ bool PrintFromType, bool ElideType,
bool ShowColors, raw_ostream &OS) {
if (PrintTree)
PrintFromType = true;
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
index 92be6d95e898..8a653ecebae3 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
@@ -521,10 +521,12 @@ namespace {
// Exprs
void VisitExpr(const Expr *Node);
void VisitCastExpr(const CastExpr *Node);
+ void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
void VisitDeclRefExpr(const DeclRefExpr *Node);
void VisitPredefinedExpr(const PredefinedExpr *Node);
void VisitCharacterLiteral(const CharacterLiteral *Node);
void VisitIntegerLiteral(const IntegerLiteral *Node);
+ void VisitFixedPointLiteral(const FixedPointLiteral *Node);
void VisitFloatingLiteral(const FloatingLiteral *Node);
void VisitStringLiteral(const StringLiteral *Str);
void VisitInitListExpr(const InitListExpr *ILE);
@@ -539,6 +541,7 @@ namespace {
void VisitAddrLabelExpr(const AddrLabelExpr *Node);
void VisitBlockExpr(const BlockExpr *Node);
void VisitOpaqueValueExpr(const OpaqueValueExpr *Node);
+ void VisitGenericSelectionExpr(const GenericSelectionExpr *E);
// C++
void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
@@ -808,11 +811,10 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
- for (auto I = Deserialize ? Primary->lookups_begin()
- : Primary->noload_lookups_begin(),
- E = Deserialize ? Primary->lookups_end()
- : Primary->noload_lookups_end();
- I != E; ++I) {
+ auto Range = Deserialize
+ ? Primary->lookups()
+ : Primary->noload_lookups(/*PreserveInternalState=*/true);
+ for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
DeclarationName Name = I.getLookupName();
DeclContextLookupResult R = *I;
@@ -1602,7 +1604,7 @@ void ASTDumper::VisitClassTemplatePartialSpecializationDecl(
void ASTDumper::VisitClassScopeFunctionSpecializationDecl(
const ClassScopeFunctionSpecializationDecl *D) {
- dumpDeclRef(D->getSpecialization());
+ dumpDecl(D->getSpecialization());
if (D->hasExplicitTemplateArgs())
dumpTemplateArgumentListInfo(D->templateArgs());
}
@@ -1946,10 +1948,15 @@ void ASTDumper::dumpStmt(const Stmt *S) {
return;
}
+ // Some statements have custom mechanisms for dumping their children.
if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
VisitDeclStmt(DS);
return;
}
+ if (const GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(S)) {
+ VisitGenericSelectionExpr(GSE);
+ return;
+ }
ConstStmtVisitor<ASTDumper>::Visit(S);
@@ -1959,7 +1966,7 @@ void ASTDumper::dumpStmt(const Stmt *S) {
}
void ASTDumper::VisitStmt(const Stmt *Node) {
- {
+ {
ColorScope Color(*this, StmtColor);
OS << Node->getStmtClassName();
}
@@ -2113,6 +2120,12 @@ void ASTDumper::VisitCastExpr(const CastExpr *Node) {
OS << ">";
}
+void ASTDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
+ VisitCastExpr(Node);
+ if (Node->isPartOfExplicitCast())
+ OS << " part_of_explicit_cast";
+}
+
void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
VisitExpr(Node);
@@ -2172,6 +2185,13 @@ void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
OS << " " << Node->getValue().toString(10, isSigned);
}
+void ASTDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
+ VisitExpr(Node);
+
+ ColorScope Color(*this, ValueColor);
+ OS << " " << Node->getValueAsString(/*Radix=*/10);
+}
+
void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
VisitExpr(Node);
ColorScope Color(*this, ValueColor);
@@ -2211,6 +2231,8 @@ void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
VisitExpr(Node);
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
<< " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
+ if (!Node->canOverflow())
+ OS << " cannot overflow";
}
void ASTDumper::VisitUnaryExprOrTypeTraitExpr(
@@ -2272,6 +2294,32 @@ void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
dumpStmt(Source);
}
+void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
+ VisitExpr(E);
+ if (E->isResultDependent())
+ OS << " result_dependent";
+ dumpStmt(E->getControllingExpr());
+ dumpTypeAsChild(E->getControllingExpr()->getType()); // FIXME: remove
+
+ for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) {
+ dumpChild([=] {
+ if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) {
+ OS << "case ";
+ dumpType(TSI->getType());
+ } else {
+ OS << "default";
+ }
+
+ if (!E->isResultDependent() && E->getResultIndex() == I)
+ OS << " selected";
+
+ if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I))
+ dumpTypeAsChild(TSI->getType());
+ dumpStmt(E->getAssocExpr(I));
+ });
+ }
+}
+
// GNU extensions.
void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 0d1d9807549f..b360b3910636 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -1,4 +1,4 @@
-//===--- ASTImporter.cpp - Importing ASTs from other Contexts ---*- C++ -*-===//
+//===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,29 +11,165 @@
// context into another context.
//
//===----------------------------------------------------------------------===//
+
#include "clang/AST/ASTImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTStructuralEquivalence.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/DeclFriend.h"
+#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/LambdaCapture.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/StmtVisitor.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <deque>
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
namespace clang {
+
+ template <class T>
+ SmallVector<Decl*, 2>
+ getCanonicalForwardRedeclChain(Redeclarable<T>* D) {
+ SmallVector<Decl*, 2> Redecls;
+ for (auto *R : D->getFirstDecl()->redecls()) {
+ if (R != D->getFirstDecl())
+ Redecls.push_back(R);
+ }
+ Redecls.push_back(D->getFirstDecl());
+ std::reverse(Redecls.begin(), Redecls.end());
+ return Redecls;
+ }
+
+ SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) {
+ // Currently only FunctionDecl is supported
+ auto FD = cast<FunctionDecl>(D);
+ return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
+ }
+
+ void updateFlags(const Decl *From, Decl *To) {
+ // Check if some flags or attrs are new in 'From' and copy into 'To'.
+ // FIXME: Other flags or attrs?
+ if (From->isUsed(false) && !To->isUsed(false))
+ To->setIsUsed();
+ }
+
class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
public DeclVisitor<ASTNodeImporter, Decl *>,
public StmtVisitor<ASTNodeImporter, Stmt *> {
ASTImporter &Importer;
+ // Wrapper for an overload set.
+ template <typename ToDeclT> struct CallOverloadedCreateFun {
+ template <typename... Args>
+ auto operator()(Args &&... args)
+ -> decltype(ToDeclT::Create(std::forward<Args>(args)...)) {
+ return ToDeclT::Create(std::forward<Args>(args)...);
+ }
+ };
+
+ // Always use these functions to create a Decl during import. There are
+ // certain tasks which must be done after the Decl was created, e.g. we
+ // must immediately register that as an imported Decl. The parameter `ToD`
+ // will be set to the newly created Decl or if had been imported before
+ // then to the already imported Decl. Returns a bool value set to true if
+ // the `FromD` had been imported before.
+ template <typename ToDeclT, typename FromDeclT, typename... Args>
+ LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD,
+ Args &&... args) {
+ // There may be several overloads of ToDeclT::Create. We must make sure
+ // to call the one which would be chosen by the arguments, thus we use a
+ // wrapper for the overload set.
+ CallOverloadedCreateFun<ToDeclT> OC;
+ return GetImportedOrCreateSpecialDecl(ToD, OC, FromD,
+ std::forward<Args>(args)...);
+ }
+ // Use this overload if a special Type is needed to be created. E.g if we
+ // want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl`
+ // then:
+ // TypedefNameDecl *ToTypedef;
+ // GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...);
+ template <typename NewDeclT, typename ToDeclT, typename FromDeclT,
+ typename... Args>
+ LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD,
+ Args &&... args) {
+ CallOverloadedCreateFun<NewDeclT> OC;
+ return GetImportedOrCreateSpecialDecl(ToD, OC, FromD,
+ std::forward<Args>(args)...);
+ }
+ // Use this version if a special create function must be
+ // used, e.g. CXXRecordDecl::CreateLambda .
+ template <typename ToDeclT, typename CreateFunT, typename FromDeclT,
+ typename... Args>
+ LLVM_NODISCARD bool
+ GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun,
+ FromDeclT *FromD, Args &&... args) {
+ ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD));
+ if (ToD)
+ return true; // Already imported.
+ ToD = CreateFun(std::forward<Args>(args)...);
+ InitializeImportedDecl(FromD, ToD);
+ return false; // A new Decl is created.
+ }
+
+ void InitializeImportedDecl(Decl *FromD, Decl *ToD) {
+ Importer.MapImported(FromD, ToD);
+ ToD->IdentifierNamespace = FromD->IdentifierNamespace;
+ if (FromD->hasAttrs())
+ for (const Attr *FromAttr : FromD->getAttrs())
+ ToD->addAttr(Importer.Import(FromAttr));
+ if (FromD->isUsed())
+ ToD->setIsUsed();
+ if (FromD->isImplicit())
+ ToD->setImplicit();
+ }
+
public:
- explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { }
-
+ explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}
+
using TypeVisitor<ASTNodeImporter, QualType>::Visit;
using DeclVisitor<ASTNodeImporter, Decl *>::Visit;
using StmtVisitor<ASTNodeImporter, Stmt *>::Visit;
@@ -52,7 +188,7 @@ namespace clang {
QualType VisitConstantArrayType(const ConstantArrayType *T);
QualType VisitIncompleteArrayType(const IncompleteArrayType *T);
QualType VisitVariableArrayType(const VariableArrayType *T);
- // FIXME: DependentSizedArrayType
+ QualType VisitDependentSizedArrayType(const DependentSizedArrayType *T);
// FIXME: DependentSizedExtVectorType
QualType VisitVectorType(const VectorType *T);
QualType VisitExtVectorType(const ExtVectorType *T);
@@ -76,37 +212,43 @@ namespace clang {
QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
QualType VisitElaboratedType(const ElaboratedType *T);
- // FIXME: DependentNameType
+ QualType VisitDependentNameType(const DependentNameType *T);
QualType VisitPackExpansionType(const PackExpansionType *T);
- // FIXME: DependentTemplateSpecializationType
+ QualType VisitDependentTemplateSpecializationType(
+ const DependentTemplateSpecializationType *T);
QualType VisitObjCInterfaceType(const ObjCInterfaceType *T);
QualType VisitObjCObjectType(const ObjCObjectType *T);
QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
-
- // Importing declarations
- bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
- DeclContext *&LexicalDC, DeclarationName &Name,
+
+ // Importing declarations
+ bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
+ DeclContext *&LexicalDC, DeclarationName &Name,
NamedDecl *&ToD, SourceLocation &Loc);
void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+ void ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);
bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
- typedef DesignatedInitExpr::Designator Designator;
+ using Designator = DesignatedInitExpr::Designator;
+
Designator ImportDesignator(const Designator &D);
-
- /// \brief What we should import from the definition.
- enum ImportDefinitionKind {
- /// \brief Import the default subset of the definition, which might be
+ Optional<LambdaCapture> ImportLambdaCapture(const LambdaCapture &From);
+
+ /// What we should import from the definition.
+ enum ImportDefinitionKind {
+ /// Import the default subset of the definition, which might be
/// nothing (if minimal import is set) or might be everything (if minimal
/// import is not set).
IDK_Default,
- /// \brief Import everything.
+
+ /// Import everything.
IDK_Everything,
- /// \brief Import only the bare bones needed to establish a valid
+
+ /// Import only the bare bones needed to establish a valid
/// DeclContext.
IDK_Basic
};
@@ -116,7 +258,7 @@ namespace clang {
(IDK == IDK_Default && !Importer.isMinimalImport());
}
- bool ImportDefinition(RecordDecl *From, RecordDecl *To,
+ bool ImportDefinition(RecordDecl *From, RecordDecl *To,
ImportDefinitionKind Kind = IDK_Default);
bool ImportDefinition(VarDecl *From, VarDecl *To,
ImportDefinitionKind Kind = IDK_Default);
@@ -127,16 +269,33 @@ namespace clang {
bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To,
ImportDefinitionKind Kind = IDK_Default);
TemplateParameterList *ImportTemplateParameterList(
- TemplateParameterList *Params);
+ TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc(
const TemplateArgumentLoc &TALoc);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
- SmallVectorImpl<TemplateArgument> &ToArgs);
+ SmallVectorImpl<TemplateArgument> &ToArgs);
+
template <typename InContainerTy>
bool ImportTemplateArgumentListInfo(const InContainerTy &Container,
TemplateArgumentListInfo &ToTAInfo);
+
+ template<typename InContainerTy>
+ bool ImportTemplateArgumentListInfo(SourceLocation FromLAngleLoc,
+ SourceLocation FromRAngleLoc,
+ const InContainerTy &Container,
+ TemplateArgumentListInfo &Result);
+
+ using TemplateArgsTy = SmallVector<TemplateArgument, 8>;
+ using OptionalTemplateArgsTy = Optional<TemplateArgsTy>;
+ std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy>
+ ImportFunctionTemplateWithTemplateArgsFromSpecialization(
+ FunctionDecl *FromFD);
+
+ bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
+
+ bool IsStructuralMatch(Decl *From, Decl *To, bool Complain);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
bool Complain = true);
bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
@@ -145,6 +304,7 @@ namespace clang {
bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC);
bool IsStructuralMatch(FunctionTemplateDecl *From,
FunctionTemplateDecl *To);
+ bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
@@ -185,7 +345,6 @@ namespace clang {
Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-
ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
@@ -282,29 +441,38 @@ namespace clang {
Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
Expr *VisitPackExpansionExpr(PackExpansionExpr *E);
+ Expr *VisitSizeOfPackExpr(SizeOfPackExpr *E);
Expr *VisitCXXNewExpr(CXXNewExpr *CE);
Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ Expr *VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ Expr *VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *CE);
+ Expr *VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
+ Expr *VisitUnresolvedMemberExpr(UnresolvedMemberExpr *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 *VisitLambdaExpr(LambdaExpr *LE);
Expr *VisitInitListExpr(InitListExpr *E);
+ Expr *VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
+ Expr *VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E);
Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
Expr *VisitTypeTraitExpr(TypeTraitExpr *E);
-
+ Expr *VisitCXXTypeidExpr(CXXTypeidExpr *E);
template<typename IIter, typename OIter>
void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) {
- typedef typename std::remove_reference<decltype(*Obegin)>::type ItemT;
+ using ItemT = typename std::remove_reference<decltype(*Obegin)>::type;
+
ASTImporter &ImporterRef = Importer;
std::transform(Ibegin, Iend, Obegin,
[&ImporterRef](ItemT From) -> ItemT {
@@ -314,13 +482,13 @@ namespace clang {
template<typename IIter, typename OIter>
bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
- typedef typename std::remove_reference<decltype(**Obegin)>::type ItemT;
+ using ItemT = typename std::remove_reference<decltype(**Obegin)>::type;
+
ASTImporter &ImporterRef = Importer;
bool Failed = false;
std::transform(Ibegin, Iend, Obegin,
[&ImporterRef, &Failed](ItemT *From) -> ItemT * {
- ItemT *To = cast_or_null<ItemT>(
- ImporterRef.Import(From));
+ auto *To = cast_or_null<ItemT>(ImporterRef.Import(From));
if (!To && From)
Failed = true;
return To;
@@ -342,9 +510,58 @@ namespace clang {
// Importing overrides.
void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);
+
+ FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD);
};
+
+template <typename InContainerTy>
+bool ASTNodeImporter::ImportTemplateArgumentListInfo(
+ SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
+ const InContainerTy &Container, TemplateArgumentListInfo &Result) {
+ TemplateArgumentListInfo ToTAInfo(Importer.Import(FromLAngleLoc),
+ Importer.Import(FromRAngleLoc));
+ if (ImportTemplateArgumentListInfo(Container, ToTAInfo))
+ return true;
+ Result = ToTAInfo;
+ return false;
}
+template <>
+bool ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>(
+ const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) {
+ return ImportTemplateArgumentListInfo(
+ From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result);
+}
+
+template <>
+bool ASTNodeImporter::ImportTemplateArgumentListInfo<
+ ASTTemplateArgumentListInfo>(const ASTTemplateArgumentListInfo &From,
+ TemplateArgumentListInfo &Result) {
+ return ImportTemplateArgumentListInfo(From.LAngleLoc, From.RAngleLoc,
+ From.arguments(), Result);
+}
+
+std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy>
+ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
+ FunctionDecl *FromFD) {
+ assert(FromFD->getTemplatedKind() ==
+ FunctionDecl::TK_FunctionTemplateSpecialization);
+ auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
+ auto *Template = cast_or_null<FunctionTemplateDecl>(
+ Importer.Import(FTSInfo->getTemplate()));
+
+ // Import template arguments.
+ auto TemplArgs = FTSInfo->TemplateArguments->asArray();
+ TemplateArgsTy ToTemplArgs;
+ if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),
+ ToTemplArgs)) // Error during import.
+ return std::make_tuple(Template, OptionalTemplateArgsTy());
+
+ return std::make_tuple(Template, ToTemplArgs);
+}
+
+} // namespace clang
+
//----------------------------------------------------------------------------
// Import Types
//----------------------------------------------------------------------------
@@ -354,13 +571,13 @@ using namespace clang;
QualType ASTNodeImporter::VisitType(const Type *T) {
Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
<< T->getTypeClassName();
- return QualType();
+ return {};
}
QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
QualType UnderlyingType = Importer.Import(T->getValueType());
if(UnderlyingType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getAtomicType(UnderlyingType);
}
@@ -383,21 +600,21 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
// context supports ObjC.
case BuiltinType::Char_U:
- // The context we're importing from has an unsigned 'char'. If we're
- // importing into a context with a signed 'char', translate to
+ // The context we're importing from has an unsigned 'char'. If we're
+ // importing into a context with a signed 'char', translate to
// 'unsigned char' instead.
if (Importer.getToContext().getLangOpts().CharIsSigned)
return Importer.getToContext().UnsignedCharTy;
-
+
return Importer.getToContext().CharTy;
case BuiltinType::Char_S:
- // The context we're importing from has an unsigned 'char'. If we're
- // importing into a context with a signed 'char', translate to
+ // The context we're importing from has an unsigned 'char'. If we're
+ // importing into a context with a signed 'char', translate to
// 'unsigned char' instead.
if (!Importer.getToContext().getLangOpts().CharIsSigned)
return Importer.getToContext().SignedCharTy;
-
+
return Importer.getToContext().CharTy;
case BuiltinType::WChar_S:
@@ -413,7 +630,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
QualType OrigT = Importer.Import(T->getOriginalType());
if (OrigT.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getDecayedType(OrigT);
}
@@ -421,16 +638,16 @@ QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
-
+ return {};
+
return Importer.getToContext().getComplexType(ToElementType);
}
QualType ASTNodeImporter::VisitPointerType(const PointerType *T) {
QualType ToPointeeType = Importer.Import(T->getPointeeType());
if (ToPointeeType.isNull())
- return QualType();
-
+ return {};
+
return Importer.getToContext().getPointerType(ToPointeeType);
}
@@ -438,8 +655,8 @@ QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
// FIXME: Check for blocks support in "to" context.
QualType ToPointeeType = Importer.Import(T->getPointeeType());
if (ToPointeeType.isNull())
- return QualType();
-
+ return {};
+
return Importer.getToContext().getBlockPointerType(ToPointeeType);
}
@@ -448,8 +665,8 @@ ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
// FIXME: Check for C++ support in "to" context.
QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
if (ToPointeeType.isNull())
- return QualType();
-
+ return {};
+
return Importer.getToContext().getLValueReferenceType(ToPointeeType);
}
@@ -458,28 +675,28 @@ ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
// FIXME: Check for C++0x support in "to" context.
QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
if (ToPointeeType.isNull())
- return QualType();
-
- return Importer.getToContext().getRValueReferenceType(ToPointeeType);
+ return {};
+
+ return Importer.getToContext().getRValueReferenceType(ToPointeeType);
}
QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
// FIXME: Check for C++ support in "to" context.
QualType ToPointeeType = Importer.Import(T->getPointeeType());
if (ToPointeeType.isNull())
- return QualType();
-
+ return {};
+
QualType ClassType = Importer.Import(QualType(T->getClass(), 0));
- return Importer.getToContext().getMemberPointerType(ToPointeeType,
+ return Importer.getToContext().getMemberPointerType(ToPointeeType,
ClassType.getTypePtr());
}
QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getConstantArrayType(ToElementType,
+ return {};
+
+ return Importer.getToContext().getConstantArrayType(ToElementType,
T->getSize(),
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
@@ -489,9 +706,9 @@ QualType
ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getIncompleteArrayType(ToElementType,
+ return {};
+
+ return Importer.getToContext().getIncompleteArrayType(ToElementType,
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
@@ -499,12 +716,12 @@ ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
+ return {};
Expr *Size = Importer.Import(T->getSizeExpr());
if (!Size)
- return QualType();
-
+ return {};
+
SourceRange Brackets = Importer.Import(T->getBracketsRange());
return Importer.getToContext().getVariableArrayType(ToElementType, Size,
T->getSizeModifier(),
@@ -512,12 +729,30 @@ QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
Brackets);
}
+QualType ASTNodeImporter::VisitDependentSizedArrayType(
+ const DependentSizedArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return {};
+
+ // SizeExpr may be null if size is not specified directly.
+ // For example, 'int a[]'.
+ Expr *Size = Importer.Import(T->getSizeExpr());
+ if (!Size && T->getSizeExpr())
+ return {};
+
+ SourceRange Brackets = Importer.Import(T->getBracketsRange());
+ return Importer.getToContext().getDependentSizedArrayType(
+ ToElementType, Size, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(),
+ Brackets);
+}
+
QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getVectorType(ToElementType,
+ return {};
+
+ return Importer.getToContext().getVectorType(ToElementType,
T->getNumElements(),
T->getVectorKind());
}
@@ -525,19 +760,19 @@ QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getExtVectorType(ToElementType,
+ return {};
+
+ return Importer.getToContext().getExtVectorType(ToElementType,
T->getNumElements());
}
QualType
ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
- // FIXME: What happens if we're importing a function without a prototype
+ // FIXME: What happens if we're importing a function without a prototype
// into C++? Should we make it variadic?
QualType ToResultType = Importer.Import(T->getReturnType());
if (ToResultType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getFunctionNoProtoType(ToResultType,
T->getExtInfo());
@@ -546,23 +781,23 @@ ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
QualType ToResultType = Importer.Import(T->getReturnType());
if (ToResultType.isNull())
- return QualType();
-
+ return {};
+
// Import argument types
SmallVector<QualType, 4> ArgTypes;
for (const auto &A : T->param_types()) {
QualType ArgType = Importer.Import(A);
if (ArgType.isNull())
- return QualType();
+ return {};
ArgTypes.push_back(ArgType);
}
-
+
// Import exception types
SmallVector<QualType, 4> ExceptionTypes;
for (const auto &E : T->exceptions()) {
QualType ExceptionType = Importer.Import(E);
if (ExceptionType.isNull())
- return QualType();
+ return {};
ExceptionTypes.push_back(ExceptionType);
}
@@ -588,16 +823,16 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
QualType ASTNodeImporter::VisitUnresolvedUsingType(
const UnresolvedUsingType *T) {
- UnresolvedUsingTypenameDecl *ToD = cast_or_null<UnresolvedUsingTypenameDecl>(
- Importer.Import(T->getDecl()));
+ const auto *ToD =
+ cast_or_null<UnresolvedUsingTypenameDecl>(Importer.Import(T->getDecl()));
if (!ToD)
- return QualType();
+ return {};
- UnresolvedUsingTypenameDecl *ToPrevD =
+ auto *ToPrevD =
cast_or_null<UnresolvedUsingTypenameDecl>(
Importer.Import(T->getDecl()->getPreviousDecl()));
if (!ToPrevD && T->getDecl()->getPreviousDecl())
- return QualType();
+ return {};
return Importer.getToContext().getTypeDeclType(ToD, ToPrevD);
}
@@ -605,33 +840,33 @@ QualType ASTNodeImporter::VisitUnresolvedUsingType(
QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
QualType ToInnerType = Importer.Import(T->getInnerType());
if (ToInnerType.isNull())
- return QualType();
-
+ return {};
+
return Importer.getToContext().getParenType(ToInnerType);
}
QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
- TypedefNameDecl *ToDecl
- = dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl()));
+ auto *ToDecl =
+ dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl()));
if (!ToDecl)
- return QualType();
-
+ return {};
+
return Importer.getToContext().getTypeDeclType(ToDecl);
}
QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
if (!ToExpr)
- return QualType();
-
+ return {};
+
return Importer.getToContext().getTypeOfExprType(ToExpr);
}
QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
if (ToUnderlyingType.isNull())
- return QualType();
-
+ return {};
+
return Importer.getToContext().getTypeOfType(ToUnderlyingType);
}
@@ -639,11 +874,11 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
// FIXME: Make sure that the "to" context supports C++0x!
Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
if (!ToExpr)
- return QualType();
-
+ return {};
+
QualType UnderlyingType = Importer.Import(T->getUnderlyingType());
if (UnderlyingType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType);
}
@@ -652,7 +887,7 @@ QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
QualType ToBaseType = Importer.Import(T->getBaseType());
QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
if (ToBaseType.isNull() || ToUnderlyingType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getUnaryTransformType(ToBaseType,
ToUnderlyingType,
@@ -666,22 +901,22 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
if (!FromDeduced.isNull()) {
ToDeduced = Importer.Import(FromDeduced);
if (ToDeduced.isNull())
- return QualType();
+ return {};
}
-
+
return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(),
/*IsDependent*/false);
}
QualType ASTNodeImporter::VisitInjectedClassNameType(
const InjectedClassNameType *T) {
- CXXRecordDecl *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl()));
+ auto *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl()));
if (!D)
- return QualType();
+ return {};
QualType InjType = Importer.Import(T->getInjectedSpecializationType());
if (InjType.isNull())
- return QualType();
+ return {};
// FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading
// See comments in InjectedClassNameType definition for details
@@ -696,19 +931,17 @@ QualType ASTNodeImporter::VisitInjectedClassNameType(
}
QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
- RecordDecl *ToDecl
- = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));
+ auto *ToDecl = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));
if (!ToDecl)
- return QualType();
+ return {};
return Importer.getToContext().getTagDeclType(ToDecl);
}
QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
- EnumDecl *ToDecl
- = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl()));
+ auto *ToDecl = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl()));
if (!ToDecl)
- return QualType();
+ return {};
return Importer.getToContext().getTagDeclType(ToDecl);
}
@@ -722,25 +955,24 @@ QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
if (!FromModifiedType.isNull()) {
ToModifiedType = Importer.Import(FromModifiedType);
if (ToModifiedType.isNull())
- return QualType();
+ return {};
}
if (!FromEquivalentType.isNull()) {
ToEquivalentType = Importer.Import(FromEquivalentType);
if (ToEquivalentType.isNull())
- return QualType();
+ return {};
}
return Importer.getToContext().getAttributedType(T->getAttrKind(),
ToModifiedType, ToEquivalentType);
}
-
QualType ASTNodeImporter::VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
- TemplateTypeParmDecl *ParmDecl =
+ auto *ParmDecl =
cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl()));
if (!ParmDecl && T->getDecl())
- return QualType();
+ return {};
return Importer.getToContext().getTemplateTypeParmType(
T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl);
@@ -748,15 +980,15 @@ QualType ASTNodeImporter::VisitTemplateTypeParmType(
QualType ASTNodeImporter::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T) {
- const TemplateTypeParmType *Replaced =
+ const auto *Replaced =
cast_or_null<TemplateTypeParmType>(Importer.Import(
QualType(T->getReplacedParameter(), 0)).getTypePtr());
if (!Replaced)
- return QualType();
+ return {};
QualType Replacement = Importer.Import(T->getReplacementType());
if (Replacement.isNull())
- return QualType();
+ return {};
Replacement = Replacement.getCanonicalType();
return Importer.getToContext().getSubstTemplateTypeParmType(
@@ -767,21 +999,21 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
TemplateName ToTemplate = Importer.Import(T->getTemplateName());
if (ToTemplate.isNull())
- return QualType();
-
+ return {};
+
SmallVector<TemplateArgument, 2> ToTemplateArgs;
if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs))
- return QualType();
-
+ return {};
+
QualType ToCanonType;
if (!QualType(T, 0).isCanonical()) {
- QualType FromCanonType
+ QualType FromCanonType
= Importer.getFromContext().getCanonicalType(QualType(T, 0));
ToCanonType =Importer.Import(FromCanonType);
if (ToCanonType.isNull())
- return QualType();
+ return {};
}
- return Importer.getToContext().getTemplateSpecializationType(ToTemplate,
+ return Importer.getToContext().getTemplateSpecializationType(ToTemplate,
ToTemplateArgs,
ToCanonType);
}
@@ -792,31 +1024,75 @@ QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
if (T->getQualifier()) {
ToQualifier = Importer.Import(T->getQualifier());
if (!ToQualifier)
- return QualType();
+ return {};
}
QualType ToNamedType = Importer.Import(T->getNamedType());
if (ToNamedType.isNull())
- return QualType();
+ return {};
+
+ TagDecl *OwnedTagDecl =
+ cast_or_null<TagDecl>(Importer.Import(T->getOwnedTagDecl()));
+ if (!OwnedTagDecl && T->getOwnedTagDecl())
+ return {};
return Importer.getToContext().getElaboratedType(T->getKeyword(),
- ToQualifier, ToNamedType);
+ ToQualifier, ToNamedType,
+ OwnedTagDecl);
}
QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
QualType Pattern = Importer.Import(T->getPattern());
if (Pattern.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getPackExpansionType(Pattern,
T->getNumExpansions());
}
+QualType ASTNodeImporter::VisitDependentTemplateSpecializationType(
+ const DependentTemplateSpecializationType *T) {
+ NestedNameSpecifier *Qualifier = Importer.Import(T->getQualifier());
+ if (!Qualifier && T->getQualifier())
+ return {};
+
+ IdentifierInfo *Name = Importer.Import(T->getIdentifier());
+ if (!Name && T->getIdentifier())
+ return {};
+
+ SmallVector<TemplateArgument, 2> ToPack;
+ ToPack.reserve(T->getNumArgs());
+ if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToPack))
+ return {};
+
+ return Importer.getToContext().getDependentTemplateSpecializationType(
+ T->getKeyword(), Qualifier, Name, ToPack);
+}
+
+QualType ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
+ NestedNameSpecifier *NNS = Importer.Import(T->getQualifier());
+ if (!NNS && T->getQualifier())
+ return QualType();
+
+ IdentifierInfo *Name = Importer.Import(T->getIdentifier());
+ if (!Name && T->getIdentifier())
+ return QualType();
+
+ QualType Canon = (T == T->getCanonicalTypeInternal().getTypePtr())
+ ? QualType()
+ : Importer.Import(T->getCanonicalTypeInternal());
+ if (!Canon.isNull())
+ Canon = Canon.getCanonicalType();
+
+ return Importer.getToContext().getDependentNameType(T->getKeyword(), NNS,
+ Name, Canon);
+}
+
QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
- ObjCInterfaceDecl *Class
- = dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
+ auto *Class =
+ dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
if (!Class)
- return QualType();
+ return {};
return Importer.getToContext().getObjCInterfaceType(Class);
}
@@ -824,23 +1100,22 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
QualType ToBaseType = Importer.Import(T->getBaseType());
if (ToBaseType.isNull())
- return QualType();
+ return {};
SmallVector<QualType, 4> TypeArgs;
for (auto TypeArg : T->getTypeArgsAsWritten()) {
QualType ImportedTypeArg = Importer.Import(TypeArg);
if (ImportedTypeArg.isNull())
- return QualType();
+ return {};
TypeArgs.push_back(ImportedTypeArg);
}
SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (auto *P : T->quals()) {
- ObjCProtocolDecl *Protocol
- = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P));
+ auto *Protocol = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P));
if (!Protocol)
- return QualType();
+ return {};
Protocols.push_back(Protocol);
}
@@ -853,7 +1128,7 @@ QualType
ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
QualType ToPointeeType = Importer.Import(T->getPointeeType());
if (ToPointeeType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getObjCObjectPointerType(ToPointeeType);
}
@@ -861,28 +1136,46 @@ ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
//----------------------------------------------------------------------------
// Import Declarations
//----------------------------------------------------------------------------
-bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
- DeclContext *&LexicalDC,
- DeclarationName &Name,
+bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
+ DeclContext *&LexicalDC,
+ DeclarationName &Name,
NamedDecl *&ToD,
SourceLocation &Loc) {
+ // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop.
+ // example: int struct_in_proto(struct data_t{int a;int b;} *d);
+ DeclContext *OrigDC = D->getDeclContext();
+ FunctionDecl *FunDecl;
+ if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) &&
+ FunDecl->hasBody()) {
+ SourceRange RecR = D->getSourceRange();
+ SourceRange BodyR = FunDecl->getBody()->getSourceRange();
+ // If RecordDecl is not in Body (it is a param), we bail out.
+ if (RecR.isValid() && BodyR.isValid() &&
+ (RecR.getBegin() < BodyR.getBegin() ||
+ BodyR.getEnd() < RecR.getEnd())) {
+ Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
+ << D->getDeclKindName();
+ return true;
+ }
+ }
+
// Import the context of this declaration.
- DC = Importer.ImportContext(D->getDeclContext());
+ DC = Importer.ImportContext(OrigDC);
if (!DC)
return true;
-
+
LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
return true;
}
-
+
// Import the name of this declaration.
Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
return true;
-
+
// Import the location of this declaration.
Loc = Importer.Import(D->getLocation());
ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
@@ -892,15 +1185,15 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
if (!FromD)
return;
-
+
if (!ToD) {
ToD = Importer.Import(FromD);
if (!ToD)
return;
}
-
- if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) {
- if (RecordDecl *ToRecord = cast_or_null<RecordDecl>(ToD)) {
+
+ if (auto *FromRecord = dyn_cast<RecordDecl>(FromD)) {
+ if (auto *ToRecord = cast_or_null<RecordDecl>(ToD)) {
if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) {
ImportDefinition(FromRecord, ToRecord);
}
@@ -908,8 +1201,8 @@ void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
return;
}
- if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) {
- if (EnumDecl *ToEnum = cast_or_null<EnumDecl>(ToD)) {
+ if (auto *FromEnum = dyn_cast<EnumDecl>(FromD)) {
+ if (auto *ToEnum = cast_or_null<EnumDecl>(ToD)) {
if (FromEnum->getDefinition() && !ToEnum->getDefinition()) {
ImportDefinition(FromEnum, ToEnum);
}
@@ -953,30 +1246,53 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
llvm_unreachable("Unknown name kind.");
}
-void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
+void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
if (Importer.isMinimalImport() && !ForceImport) {
Importer.ImportContext(FromDC);
return;
}
-
+
for (auto *From : FromDC->decls())
Importer.Import(From);
}
-bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
+void ASTNodeImporter::ImportImplicitMethods(
+ const CXXRecordDecl *From, CXXRecordDecl *To) {
+ assert(From->isCompleteDefinition() && To->getDefinition() == To &&
+ "Import implicit methods to or from non-definition");
+
+ for (CXXMethodDecl *FromM : From->methods())
+ if (FromM->isImplicit())
+ Importer.Import(FromM);
+}
+
+static void setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To,
+ ASTImporter &Importer) {
+ if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) {
+ auto *ToTypedef =
+ cast_or_null<TypedefNameDecl>(Importer.Import(FromTypedef));
+ assert (ToTypedef && "Failed to import typedef of an anonymous structure");
+
+ To->setTypedefNameForAnonDecl(ToTypedef);
+ }
+}
+
+bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
ImportDefinitionKind Kind) {
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything)
ImportDeclContext(From, /*ForceImport=*/true);
-
+
return false;
}
-
+
To->startDefinition();
-
+
+ setTypedefNameForAnonDecl(From, To, Importer);
+
// Add base classes.
- if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(To)) {
- CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From);
+ if (auto *ToCXX = dyn_cast<CXXRecordDecl>(To)) {
+ auto *FromCXX = cast<CXXRecordDecl>(From);
struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();
@@ -988,7 +1304,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
ToData.Polymorphic = FromData.Polymorphic;
ToData.Abstract = FromData.Abstract;
ToData.IsStandardLayout = FromData.IsStandardLayout;
- ToData.HasNoNonEmptyBases = FromData.HasNoNonEmptyBases;
+ ToData.IsCXX11StandardLayout = FromData.IsCXX11StandardLayout;
+ ToData.HasBasesWithFields = FromData.HasBasesWithFields;
+ ToData.HasBasesWithNonStaticDataMembers =
+ FromData.HasBasesWithNonStaticDataMembers;
ToData.HasPrivateFields = FromData.HasPrivateFields;
ToData.HasProtectedFields = FromData.HasProtectedFields;
ToData.HasPublicFields = FromData.HasPublicFields;
@@ -1022,7 +1341,6 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
= FromData.HasConstexprNonCopyMoveConstructor;
ToData.HasDefaultedDefaultConstructor
= FromData.HasDefaultedDefaultConstructor;
- ToData.CanPassInRegisters = FromData.CanPassInRegisters;
ToData.DefaultedDefaultConstructorIsConstexpr
= FromData.DefaultedDefaultConstructorIsConstexpr;
ToData.HasConstexprDefaultConstructor
@@ -1043,7 +1361,6 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
= FromData.HasDeclaredCopyConstructorWithConstParam;
ToData.HasDeclaredCopyAssignmentWithConstParam
= FromData.HasDeclaredCopyAssignmentWithConstParam;
- ToData.IsLambda = FromData.IsLambda;
SmallVector<CXXBaseSpecifier *, 4> Bases;
for (const auto &Base1 : FromCXX->bases()) {
@@ -1057,9 +1374,9 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
// Ensure that we have a definition for the base.
ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl());
-
+
Bases.push_back(
- new (Importer.getToContext())
+ new (Importer.getToContext())
CXXBaseSpecifier(Importer.Import(Base1.getSourceRange()),
Base1.isVirtual(),
Base1.isBaseOfClass(),
@@ -1070,10 +1387,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
if (!Bases.empty())
ToCXX->setBases(Bases.data(), Bases.size());
}
-
+
if (shouldForceImportDeclContext(Kind))
ImportDeclContext(From, /*ForceImport=*/true);
-
+
To->completeDefinition();
return false;
}
@@ -1093,27 +1410,29 @@ bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To,
return false;
}
-bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
+bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
ImportDefinitionKind Kind) {
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything)
ImportDeclContext(From, /*ForceImport=*/true);
return false;
}
-
+
To->startDefinition();
+ setTypedefNameForAnonDecl(From, To, Importer);
+
QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From));
if (T.isNull())
return true;
-
+
QualType ToPromotionType = Importer.Import(From->getPromotionType());
if (ToPromotionType.isNull())
return true;
if (shouldForceImportDeclContext(Kind))
ImportDeclContext(From, /*ForceImport=*/true);
-
+
// FIXME: we might need to merge the number of positive or negative bits
// if the enumerator lists don't match.
To->completeDefinition(T, ToPromotionType,
@@ -1127,7 +1446,7 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
SmallVector<NamedDecl *, 4> ToParams(Params->size());
if (ImportContainerChecked(*Params, ToParams))
return nullptr;
-
+
Expr *ToRequiresClause;
if (Expr *const R = Params->getRequiresClause()) {
ToRequiresClause = Importer.Import(R);
@@ -1145,55 +1464,55 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
ToRequiresClause);
}
-TemplateArgument
+TemplateArgument
ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
switch (From.getKind()) {
case TemplateArgument::Null:
return TemplateArgument();
-
+
case TemplateArgument::Type: {
QualType ToType = Importer.Import(From.getAsType());
if (ToType.isNull())
- return TemplateArgument();
+ return {};
return TemplateArgument(ToType);
}
-
+
case TemplateArgument::Integral: {
QualType ToType = Importer.Import(From.getIntegralType());
if (ToType.isNull())
- return TemplateArgument();
+ return {};
return TemplateArgument(From, ToType);
}
case TemplateArgument::Declaration: {
- ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl()));
+ auto *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl()));
QualType ToType = Importer.Import(From.getParamTypeForDecl());
if (!To || ToType.isNull())
- return TemplateArgument();
+ return {};
return TemplateArgument(To, ToType);
}
case TemplateArgument::NullPtr: {
QualType ToType = Importer.Import(From.getNullPtrType());
if (ToType.isNull())
- return TemplateArgument();
+ return {};
return TemplateArgument(ToType, /*isNullPtr*/true);
}
case TemplateArgument::Template: {
TemplateName ToTemplate = Importer.Import(From.getAsTemplate());
if (ToTemplate.isNull())
- return TemplateArgument();
-
+ return {};
+
return TemplateArgument(ToTemplate);
}
case TemplateArgument::TemplateExpansion: {
- TemplateName ToTemplate
+ TemplateName ToTemplate
= Importer.Import(From.getAsTemplateOrTemplatePattern());
if (ToTemplate.isNull())
- return TemplateArgument();
-
+ return {};
+
return TemplateArgument(ToTemplate, From.getNumTemplateExpansions());
}
@@ -1201,18 +1520,18 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
return TemplateArgument(ToExpr);
return TemplateArgument();
-
+
case TemplateArgument::Pack: {
SmallVector<TemplateArgument, 2> ToPack;
ToPack.reserve(From.pack_size());
if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack))
- return TemplateArgument();
+ return {};
return TemplateArgument(
llvm::makeArrayRef(ToPack).copy(Importer.getToContext()));
}
}
-
+
llvm_unreachable("Invalid template argument kind");
}
@@ -1247,13 +1566,16 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
TemplateArgument To = ImportTemplateArgument(FromArgs[I]);
if (To.isNull() && !FromArgs[I].isNull())
return true;
-
+
ToArgs.push_back(To);
}
-
+
return false;
}
+// We cannot use Optional<> pattern here and below because
+// TemplateArgumentListInfo's operator new is declared as deleted so it cannot
+// be stored in Optional.
template <typename InContainerTy>
bool ASTNodeImporter::ImportTemplateArgumentListInfo(
const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
@@ -1266,13 +1588,27 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo(
return false;
}
-bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
+static StructuralEquivalenceKind
+getStructuralEquivalenceKind(const ASTImporter &Importer) {
+ return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal
+ : StructuralEquivalenceKind::Default;
+}
+
+bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) {
+ StructuralEquivalenceContext Ctx(
+ Importer.getFromContext(), Importer.getToContext(),
+ Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
+ false, Complain);
+ return Ctx.IsEquivalent(From, To);
+}
+
+bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
RecordDecl *ToRecord, bool Complain) {
// Eliminate a potential failure point where we attempt to re-import
// something we're trying to import while completing ToRecord.
Decl *ToOrigin = Importer.GetOriginalDecl(ToRecord);
if (ToOrigin) {
- RecordDecl *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin);
+ auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin);
if (ToOriginRecord)
ToRecord = ToOriginRecord;
}
@@ -1280,36 +1616,46 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
ToRecord->getASTContext(),
Importer.getNonEquivalentDecls(),
+ getStructuralEquivalenceKind(Importer),
false, Complain);
- return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
+ return Ctx.IsEquivalent(FromRecord, ToRecord);
}
bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
bool Complain) {
StructuralEquivalenceContext Ctx(
Importer.getFromContext(), Importer.getToContext(),
- Importer.getNonEquivalentDecls(), false, Complain);
- return Ctx.IsStructurallyEquivalent(FromVar, ToVar);
+ Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
+ false, Complain);
+ return Ctx.IsEquivalent(FromVar, ToVar);
}
bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
- StructuralEquivalenceContext Ctx(Importer.getFromContext(),
- Importer.getToContext(),
- Importer.getNonEquivalentDecls());
- return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
+ StructuralEquivalenceContext Ctx(
+ Importer.getFromContext(), Importer.getToContext(),
+ Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer));
+ return Ctx.IsEquivalent(FromEnum, ToEnum);
}
bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
FunctionTemplateDecl *To) {
StructuralEquivalenceContext Ctx(
Importer.getFromContext(), Importer.getToContext(),
- Importer.getNonEquivalentDecls(), false, false);
- return Ctx.IsStructurallyEquivalent(From, To);
+ Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
+ false, false);
+ return Ctx.IsEquivalent(From, To);
+}
+
+bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) {
+ StructuralEquivalenceContext Ctx(
+ Importer.getFromContext(), Importer.getToContext(),
+ Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
+ false, false);
+ return Ctx.IsEquivalent(From, To);
}
bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
- EnumConstantDecl *ToEC)
-{
+ EnumConstantDecl *ToEC) {
const llvm::APSInt &FromVal = FromEC->getInitVal();
const llvm::APSInt &ToVal = ToEC->getInitVal();
@@ -1322,16 +1668,18 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From,
ClassTemplateDecl *To) {
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
Importer.getToContext(),
- Importer.getNonEquivalentDecls());
- return Ctx.IsStructurallyEquivalent(From, To);
+ Importer.getNonEquivalentDecls(),
+ getStructuralEquivalenceKind(Importer));
+ return Ctx.IsEquivalent(From, To);
}
bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
VarTemplateDecl *To) {
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
Importer.getToContext(),
- Importer.getNonEquivalentDecls());
- return Ctx.IsStructurallyEquivalent(From, To);
+ Importer.getNonEquivalentDecls(),
+ getStructuralEquivalenceKind(Importer));
+ return Ctx.IsEquivalent(From, To);
}
Decl *ASTNodeImporter::VisitDecl(Decl *D) {
@@ -1356,24 +1704,25 @@ Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
- EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc);
+ EmptyDecl *ToD;
+ if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc))
+ return ToD;
+
ToD->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToD);
LexicalDC->addDeclInternal(ToD);
return ToD;
}
Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
- TranslationUnitDecl *ToD =
+ TranslationUnitDecl *ToD =
Importer.getToContext().getTranslationUnitDecl();
-
- Importer.Imported(D, ToD);
-
+
+ Importer.MapImported(D, ToD);
+
return ToD;
}
Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
-
SourceLocation Loc = Importer.Import(D->getLocation());
SourceLocation ColonLoc = Importer.Import(D->getColonLoc());
@@ -1382,19 +1731,17 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
if (!DC)
return nullptr;
- AccessSpecDecl *accessSpecDecl
- = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(),
- DC, Loc, ColonLoc);
-
- if (!accessSpecDecl)
- return nullptr;
+ AccessSpecDecl *ToD;
+ if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(),
+ DC, Loc, ColonLoc))
+ return ToD;
// Lexical DeclContext and Semantic DeclContext
// is always the same for the accessSpec.
- accessSpecDecl->setLexicalDeclContext(DC);
- DC->addDeclInternal(accessSpecDecl);
+ ToD->setLexicalDeclContext(DC);
+ DC->addDeclInternal(ToD);
- return accessSpecDecl;
+ return ToD;
}
Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
@@ -1412,17 +1759,18 @@ Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
return nullptr;
StringLiteral *FromMsg = D->getMessage();
- StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
+ auto *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
if (!ToMsg && FromMsg)
return nullptr;
- StaticAssertDecl *ToD = StaticAssertDecl::Create(
- Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
- Importer.Import(D->getRParenLoc()), D->isFailed());
+ StaticAssertDecl *ToD;
+ if (GetImportedOrCreateDecl(
+ ToD, D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
+ Importer.Import(D->getRParenLoc()), D->isFailed()))
+ return ToD;
ToD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToD);
- Importer.Imported(D, ToD);
return ToD;
}
@@ -1442,7 +1790,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// This is an anonymous namespace. Adopt an existing anonymous
// namespace if we can.
// FIXME: Not testable.
- if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(DC))
+ if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
MergeWithNamespace = TU->getAnonymousNamespace();
else
MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace();
@@ -1450,50 +1798,50 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace))
continue;
-
- if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(FoundDecls[I])) {
+
+ if (auto *FoundNS = dyn_cast<NamespaceDecl>(FoundDecl)) {
MergeWithNamespace = FoundNS;
ConflictingDecls.clear();
break;
}
-
- ConflictingDecls.push_back(FoundDecls[I]);
+
+ ConflictingDecls.push_back(FoundDecl);
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
}
}
-
+
// Create the "to" namespace, if needed.
NamespaceDecl *ToNamespace = MergeWithNamespace;
if (!ToNamespace) {
- ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC,
- D->isInline(),
- Importer.Import(D->getLocStart()),
- Loc, Name.getAsIdentifierInfo(),
- /*PrevDecl=*/nullptr);
+ if (GetImportedOrCreateDecl(
+ ToNamespace, D, Importer.getToContext(), DC, D->isInline(),
+ Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(),
+ /*PrevDecl=*/nullptr))
+ return ToNamespace;
ToNamespace->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToNamespace);
-
+
// If this is an anonymous namespace, register it as the anonymous
// namespace within its context.
if (!Name) {
- if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(DC))
+ if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
TU->setAnonymousNamespace(ToNamespace);
else
cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace);
}
}
- Importer.Imported(D, ToNamespace);
-
+ Importer.MapImported(D, ToNamespace);
+
ImportDeclContext(D);
-
+
return ToNamespace;
}
@@ -1510,8 +1858,8 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
// NOTE: No conflict resolution is done for namespace aliases now.
- NamespaceDecl *TargetDecl = cast_or_null<NamespaceDecl>(
- Importer.Import(D->getNamespace()));
+ auto *TargetDecl = cast_or_null<NamespaceDecl>(
+ Importer.Import(D->getNamespace()));
if (!TargetDecl)
return nullptr;
@@ -1523,13 +1871,15 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
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);
+ NamespaceAliasDecl *ToD;
+ if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC,
+ Importer.Import(D->getNamespaceLoc()),
+ Importer.Import(D->getAliasLoc()), ToII, ToQLoc,
+ Importer.Import(D->getTargetNameLoc()),
+ TargetDecl))
+ return ToD;
ToD->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToD);
LexicalDC->addDeclInternal(ToD);
return ToD;
@@ -1554,22 +1904,21 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
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))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (TypedefNameDecl *FoundTypedef =
- dyn_cast<TypedefNameDecl>(FoundDecls[I])) {
+ if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(),
FoundTypedef->getUnderlyingType()))
- return Importer.Imported(D, FoundTypedef);
+ return Importer.MapImported(D, FoundTypedef);
}
- ConflictingDecls.push_back(FoundDecls[I]);
+ ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
return nullptr;
@@ -1584,22 +1933,25 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
// Create the new typedef node.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
SourceLocation StartL = Importer.Import(D->getLocStart());
+
TypedefNameDecl *ToTypedef;
- if (IsAlias)
- ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC,
- StartL, Loc,
- Name.getAsIdentifierInfo(),
- TInfo);
- else
- ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC,
- StartL, Loc,
- Name.getAsIdentifierInfo(),
- TInfo);
+ if (IsAlias) {
+ if (GetImportedOrCreateDecl<TypeAliasDecl>(
+ ToTypedef, D, Importer.getToContext(), DC, StartL, Loc,
+ Name.getAsIdentifierInfo(), TInfo))
+ return ToTypedef;
+ } else if (GetImportedOrCreateDecl<TypedefDecl>(
+ ToTypedef, D, Importer.getToContext(), DC, StartL, Loc,
+ Name.getAsIdentifierInfo(), TInfo))
+ return ToTypedef;
ToTypedef->setAccess(D->getAccess());
ToTypedef->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToTypedef);
- LexicalDC->addDeclInternal(ToTypedef);
+
+ // Templated declarations should not appear in DeclContext.
+ TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr;
+ if (!FromAlias || !FromAlias->getDescribedAliasTemplate())
+ LexicalDC->addDeclInternal(ToTypedef);
return ToTypedef;
}
@@ -1617,11 +1969,11 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ NamedDecl *FoundD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
return nullptr;
- if (ToD)
- return ToD;
+ if (FoundD)
+ return FoundD;
// 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
@@ -1631,13 +1983,12 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
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))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (auto *FoundAlias =
- dyn_cast<TypeAliasTemplateDecl>(FoundDecls[I]))
- return Importer.Imported(D, FoundAlias);
- ConflictingDecls.push_back(FoundDecls[I]);
+ if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl))
+ return Importer.MapImported(D, FoundAlias);
+ ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
@@ -1654,19 +2005,22 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
if (!Params)
return nullptr;
- NamedDecl *TemplDecl = cast_or_null<NamedDecl>(
+ auto *TemplDecl = cast_or_null<TypeAliasDecl>(
Importer.Import(D->getTemplatedDecl()));
if (!TemplDecl)
return nullptr;
- TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create(
- Importer.getToContext(), DC, Loc, Name, Params, TemplDecl);
+ TypeAliasTemplateDecl *ToAlias;
+ if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc,
+ Name, Params, TemplDecl))
+ return ToAlias;
+
+ TemplDecl->setDescribedAliasTemplate(ToAlias);
ToAlias->setAccess(D->getAccess());
ToAlias->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToAlias);
LexicalDC->addDeclInternal(ToAlias);
- return ToD;
+ return ToAlias;
}
Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
@@ -1682,17 +2036,18 @@ Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
assert(LexicalDC->isFunctionOrMethod());
- LabelDecl *ToLabel = D->isGnuLocal()
- ? LabelDecl::Create(Importer.getToContext(),
- DC, Importer.Import(D->getLocation()),
- Name.getAsIdentifierInfo(),
- Importer.Import(D->getLocStart()))
- : LabelDecl::Create(Importer.getToContext(),
- DC, Importer.Import(D->getLocation()),
- Name.getAsIdentifierInfo());
- Importer.Imported(D, ToLabel);
-
- LabelStmt *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt()));
+ LabelDecl *ToLabel;
+ if (D->isGnuLocal()
+ ? GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC,
+ Importer.Import(D->getLocation()),
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getLocStart()))
+ : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC,
+ Importer.Import(D->getLocation()),
+ Name.getAsIdentifierInfo()))
+ return ToLabel;
+
+ auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt()));
if (!Label)
return nullptr;
@@ -1721,48 +2076,49 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
IDNS = Decl::IDNS_Ordinary;
} else if (Importer.getToContext().getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Ordinary;
-
+
// We may already have an enum of the same name; try to find and match it.
if (!DC->isFunctionOrMethod() && SearchName) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
-
- Decl *Found = FoundDecls[I];
- if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
- if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
+
+ Decl *Found = FoundDecl;
+ if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
+ if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
Found = Tag->getDecl();
}
-
- if (EnumDecl *FoundEnum = dyn_cast<EnumDecl>(Found)) {
+
+ if (auto *FoundEnum = dyn_cast<EnumDecl>(Found)) {
if (IsStructuralMatch(D, FoundEnum))
- return Importer.Imported(D, FoundEnum);
+ return Importer.MapImported(D, FoundEnum);
}
-
- ConflictingDecls.push_back(FoundDecls[I]);
+
+ ConflictingDecls.push_back(FoundDecl);
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
}
}
-
+
// Create the enum declaration.
- EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getLocStart()),
- Loc, Name.getAsIdentifierInfo(), nullptr,
- D->isScoped(), D->isScopedUsingClassTag(),
- D->isFixed());
+ EnumDecl *D2;
+ if (GetImportedOrCreateDecl(
+ D2, D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()),
+ Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(),
+ D->isScopedUsingClassTag(), D->isFixed()))
+ return D2;
+
// Import the qualifier, if any.
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, D2);
LexicalDC->addDeclInternal(D2);
// Import the integer type.
@@ -1770,7 +2126,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
if (ToIntegerType.isNull())
return nullptr;
D2->setIntegerType(ToIntegerType);
-
+
// Import the definition
if (D->isCompleteDefinition() && ImportDefinition(D, D2))
return nullptr;
@@ -1783,14 +2139,20 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
// but this particular declaration is not that definition, import the
// definition and map to that.
TagDecl *Definition = D->getDefinition();
- if (Definition && Definition != D) {
+ if (Definition && Definition != D &&
+ // In contrast to a normal CXXRecordDecl, the implicit
+ // CXXRecordDecl of ClassTemplateSpecializationDecl is its redeclaration.
+ // The definition of the implicit CXXRecordDecl in this case is the
+ // ClassTemplateSpecializationDecl itself. Thus, we start with an extra
+ // condition in order to be able to import the implict Decl.
+ !D->isImplicit()) {
Decl *ImportedDef = Importer.Import(Definition);
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
-
+
// Import the major distinguishing characteristics of this record.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -1824,30 +2186,27 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
D->getASTContext().getExternalSource()->CompleteType(D);
}
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
-
- Decl *Found = FoundDecls[I];
- if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
- if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
+
+ Decl *Found = FoundDecl;
+ if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
+ if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
Found = Tag->getDecl();
}
-
- if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
- if (D->isAnonymousStructOrUnion() &&
- FoundRecord->isAnonymousStructOrUnion()) {
- // If both anonymous structs/unions are in a record context, make sure
- // they occur in the same location in the context records.
- if (Optional<unsigned> Index1 =
- StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
- D)) {
- if (Optional<unsigned> Index2 = StructuralEquivalenceContext::
- findUntaggedStructOrUnionIndex(FoundRecord)) {
- if (*Index1 != *Index2)
- continue;
- }
- }
+
+ if (D->getDescribedTemplate()) {
+ if (auto *Template = dyn_cast<ClassTemplateDecl>(Found))
+ Found = Template->getTemplatedDecl();
+ else
+ continue;
+ }
+
+ if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) {
+ if (!SearchName) {
+ if (!IsStructuralMatch(D, FoundRecord, false))
+ continue;
}
PrevDecl = FoundRecord;
@@ -1861,96 +2220,134 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// function.
- // FIXME: For C++, we should also merge methods here.
- return Importer.Imported(D, FoundDef);
+ // FIXME: Structural equivalence check should check for same
+ // user-defined methods.
+ Importer.MapImported(D, FoundDef);
+ if (const auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
+ auto *FoundCXX = dyn_cast<CXXRecordDecl>(FoundDef);
+ assert(FoundCXX && "Record type mismatch");
+
+ if (D->isCompleteDefinition() && !Importer.isMinimalImport())
+ // FoundDef may not have every implicit method that D has
+ // because implicit methods are created only if they are used.
+ ImportImplicitMethods(DCXX, FoundCXX);
+ }
+ return FoundDef;
}
} else if (!D->isCompleteDefinition()) {
// We have a forward declaration of this type, so adopt that forward
// declaration rather than building a new one.
-
+
// If one or both can be completed from external storage then try one
// last time to complete and compare them before doing this.
-
+
if (FoundRecord->hasExternalLexicalStorage() &&
!FoundRecord->isCompleteDefinition())
FoundRecord->getASTContext().getExternalSource()->CompleteType(FoundRecord);
if (D->hasExternalLexicalStorage())
D->getASTContext().getExternalSource()->CompleteType(D);
-
+
if (FoundRecord->isCompleteDefinition() &&
D->isCompleteDefinition() &&
!IsStructuralMatch(D, FoundRecord))
continue;
-
+
AdoptDecl = FoundRecord;
continue;
} else if (!SearchName) {
continue;
}
}
-
- ConflictingDecls.push_back(FoundDecls[I]);
+
+ ConflictingDecls.push_back(FoundDecl);
}
-
+
if (!ConflictingDecls.empty() && SearchName) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
}
}
-
+
// Create the record declaration.
RecordDecl *D2 = AdoptDecl;
SourceLocation StartLoc = Importer.Import(D->getLocStart());
if (!D2) {
CXXRecordDecl *D2CXX = nullptr;
- if (CXXRecordDecl *DCXX = llvm::dyn_cast<CXXRecordDecl>(D)) {
+ if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
if (DCXX->isLambda()) {
TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo());
- D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(),
- DC, TInfo, Loc,
- DCXX->isDependentLambda(),
- DCXX->isGenericLambda(),
- DCXX->getLambdaCaptureDefault());
+ if (GetImportedOrCreateSpecialDecl(
+ D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(),
+ DC, TInfo, Loc, DCXX->isDependentLambda(),
+ DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault()))
+ return D2CXX;
Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl());
if (DCXX->getLambdaContextDecl() && !CDecl)
return nullptr;
D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl);
- } else if (DCXX->isInjectedClassName()) {
- // We have to be careful to do a similar dance to the one in
- // Sema::ActOnStartCXXMemberDeclarations
- CXXRecordDecl *const PrevDecl = nullptr;
- const bool DelayTypeCreation = true;
- D2CXX = CXXRecordDecl::Create(
- Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,
- Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation);
- Importer.getToContext().getTypeDeclType(
- D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC));
+ } else if (DCXX->isInjectedClassName()) {
+ // We have to be careful to do a similar dance to the one in
+ // Sema::ActOnStartCXXMemberDeclarations
+ CXXRecordDecl *const PrevDecl = nullptr;
+ const bool DelayTypeCreation = true;
+ if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
+ D->getTagKind(), DC, StartLoc, Loc,
+ Name.getAsIdentifierInfo(), PrevDecl,
+ DelayTypeCreation))
+ return D2CXX;
+ Importer.getToContext().getTypeDeclType(
+ D2CXX, dyn_cast<CXXRecordDecl>(DC));
} else {
- D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
- D->getTagKind(),
- DC, StartLoc, Loc,
- Name.getAsIdentifierInfo());
+ if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
+ D->getTagKind(), DC, StartLoc, Loc,
+ Name.getAsIdentifierInfo(),
+ cast_or_null<CXXRecordDecl>(PrevDecl)))
+ return D2CXX;
}
+
D2 = D2CXX;
D2->setAccess(D->getAccess());
-
- Importer.Imported(D, D2);
+ D2->setLexicalDeclContext(LexicalDC);
+ if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit())
+ LexicalDC->addDeclInternal(D2);
if (ClassTemplateDecl *FromDescribed =
DCXX->getDescribedClassTemplate()) {
- ClassTemplateDecl *ToDescribed = cast_or_null<ClassTemplateDecl>(
- Importer.Import(FromDescribed));
+ auto *ToDescribed = cast_or_null<ClassTemplateDecl>(
+ Importer.Import(FromDescribed));
if (!ToDescribed)
return nullptr;
D2CXX->setDescribedClassTemplate(ToDescribed);
-
+ if (!DCXX->isInjectedClassName()) {
+ // In a record describing a template the type should be an
+ // InjectedClassNameType (see Sema::CheckClassTemplate). Update the
+ // previously set type to the correct value here (ToDescribed is not
+ // available at record create).
+ // FIXME: The previous type is cleared but not removed from
+ // ASTContext's internal storage.
+ CXXRecordDecl *Injected = nullptr;
+ for (NamedDecl *Found : D2CXX->noload_lookup(Name)) {
+ auto *Record = dyn_cast<CXXRecordDecl>(Found);
+ if (Record && Record->isInjectedClassName()) {
+ Injected = Record;
+ break;
+ }
+ }
+ D2CXX->setTypeForDecl(nullptr);
+ Importer.getToContext().getInjectedClassNameType(D2CXX,
+ ToDescribed->getInjectedClassNameSpecialization());
+ if (Injected) {
+ Injected->setTypeForDecl(nullptr);
+ Importer.getToContext().getTypeDeclType(Injected, D2CXX);
+ }
+ }
} else if (MemberSpecializationInfo *MemberInfo =
DCXX->getMemberSpecializationInfo()) {
TemplateSpecializationKind SK =
MemberInfo->getTemplateSpecializationKind();
CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass();
- CXXRecordDecl *ToInst =
+ auto *ToInst =
cast_or_null<CXXRecordDecl>(Importer.Import(FromInst));
if (FromInst && !ToInst)
return nullptr;
@@ -1958,24 +2355,21 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation(
Importer.Import(MemberInfo->getPointOfInstantiation()));
}
-
} else {
- D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
- DC, StartLoc, Loc, Name.getAsIdentifierInfo());
+ if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(),
+ D->getTagKind(), DC, StartLoc, Loc,
+ Name.getAsIdentifierInfo(), PrevDecl))
+ return D2;
+ D2->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(D2);
}
-
+
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
if (D->isAnonymousStructOrUnion())
D2->setAnonymousStructOrUnion(true);
- if (PrevDecl) {
- // FIXME: do this for all Redeclarables, not just RecordDecls.
- D2->setPreviousDecl(PrevDecl);
- }
}
-
- Importer.Imported(D, D2);
+
+ Importer.MapImported(D, D2);
if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default))
return nullptr;
@@ -1998,51 +2392,152 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
if (T.isNull())
return nullptr;
- // Determine whether there are any other declarations with the same name and
+ // Determine whether there are any other declarations with the same name and
// in the same context.
if (!LexicalDC->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))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (EnumConstantDecl *FoundEnumConstant
- = dyn_cast<EnumConstantDecl>(FoundDecls[I])) {
+ if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) {
if (IsStructuralMatch(D, FoundEnumConstant))
- return Importer.Imported(D, FoundEnumConstant);
+ return Importer.MapImported(D, FoundEnumConstant);
}
- ConflictingDecls.push_back(FoundDecls[I]);
+ ConflictingDecls.push_back(FoundDecl);
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
return nullptr;
}
}
-
+
Expr *Init = Importer.Import(D->getInitExpr());
if (D->getInitExpr() && !Init)
return nullptr;
- EnumConstantDecl *ToEnumerator
- = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc,
- Name.getAsIdentifierInfo(), T,
- Init, D->getInitVal());
+ EnumConstantDecl *ToEnumerator;
+ if (GetImportedOrCreateDecl(
+ ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc,
+ Name.getAsIdentifierInfo(), T, Init, D->getInitVal()))
+ return ToEnumerator;
+
ToEnumerator->setAccess(D->getAccess());
ToEnumerator->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToEnumerator);
LexicalDC->addDeclInternal(ToEnumerator);
return ToEnumerator;
}
+bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD,
+ FunctionDecl *ToFD) {
+ switch (FromFD->getTemplatedKind()) {
+ case FunctionDecl::TK_NonTemplate:
+ case FunctionDecl::TK_FunctionTemplate:
+ return false;
+
+ case FunctionDecl::TK_MemberSpecialization: {
+ auto *InstFD = cast_or_null<FunctionDecl>(
+ Importer.Import(FromFD->getInstantiatedFromMemberFunction()));
+ if (!InstFD)
+ return true;
+
+ TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();
+ SourceLocation POI = Importer.Import(
+ FromFD->getMemberSpecializationInfo()->getPointOfInstantiation());
+ ToFD->setInstantiationOfMemberFunction(InstFD, TSK);
+ ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+ return false;
+ }
+
+ case FunctionDecl::TK_FunctionTemplateSpecialization: {
+ FunctionTemplateDecl* Template;
+ OptionalTemplateArgsTy ToTemplArgs;
+ std::tie(Template, ToTemplArgs) =
+ ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
+ if (!Template || !ToTemplArgs)
+ return true;
+
+ TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy(
+ Importer.getToContext(), *ToTemplArgs);
+
+ auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
+ TemplateArgumentListInfo ToTAInfo;
+ const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;
+ if (FromTAArgsAsWritten)
+ if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo))
+ return true;
+
+ SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation());
+
+ TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();
+ ToFD->setFunctionTemplateSpecialization(
+ Template, ToTAList, /* InsertPos= */ nullptr,
+ TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI);
+ return false;
+ }
+
+ case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
+ auto *FromInfo = FromFD->getDependentSpecializationInfo();
+ UnresolvedSet<8> TemplDecls;
+ unsigned NumTemplates = FromInfo->getNumTemplates();
+ for (unsigned I = 0; I < NumTemplates; I++) {
+ if (auto *ToFTD = cast_or_null<FunctionTemplateDecl>(
+ Importer.Import(FromInfo->getTemplate(I))))
+ TemplDecls.addDecl(ToFTD);
+ else
+ return true;
+ }
+
+ // Import TemplateArgumentListInfo.
+ TemplateArgumentListInfo ToTAInfo;
+ if (ImportTemplateArgumentListInfo(
+ FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(),
+ llvm::makeArrayRef(FromInfo->getTemplateArgs(),
+ FromInfo->getNumTemplateArgs()),
+ ToTAInfo))
+ return true;
+
+ ToFD->setDependentTemplateSpecialization(Importer.getToContext(),
+ TemplDecls, ToTAInfo);
+ return false;
+ }
+ }
+ llvm_unreachable("All cases should be covered!");
+}
+
+FunctionDecl *
+ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) {
+ FunctionTemplateDecl* Template;
+ OptionalTemplateArgsTy ToTemplArgs;
+ std::tie(Template, ToTemplArgs) =
+ ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
+ if (!Template || !ToTemplArgs)
+ return nullptr;
+
+ void *InsertPos = nullptr;
+ auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos);
+ return FoundSpec;
+}
+
Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
+
+ SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D);
+ auto RedeclIt = Redecls.begin();
+ // Import the first part of the decl chain. I.e. import all previous
+ // declarations starting from the canonical decl.
+ for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt)
+ if (!Importer.Import(*RedeclIt))
+ return nullptr;
+ assert(*RedeclIt == D);
+
// Import the major distinguishing characteristics of this function.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -2053,33 +2548,54 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (ToD)
return ToD;
- const FunctionDecl *FoundWithoutBody = nullptr;
-
+ const FunctionDecl *FoundByLookup = nullptr;
+ FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate();
+
+ // If this is a function template specialization, then try to find the same
+ // existing specialization in the "to" context. The localUncachedLookup
+ // below will not find any specialization, but would find the primary
+ // template; thus, we have to skip normal lookup in case of specializations.
+ // FIXME handle member function templates (TK_MemberSpecialization) similarly?
+ if (D->getTemplatedKind() ==
+ FunctionDecl::TK_FunctionTemplateSpecialization) {
+ if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) {
+ if (D->doesThisDeclarationHaveABody() &&
+ FoundFunction->hasBody())
+ return Importer.Imported(D, FoundFunction);
+ FoundByLookup = FoundFunction;
+ }
+ }
// 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()) {
+ else if (!LexicalDC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
- unsigned IDNS = Decl::IDNS_Ordinary;
+ unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) {
+ // If template was found, look at the templated function.
+ if (FromFT) {
+ if (auto *Template = dyn_cast<FunctionTemplateDecl>(FoundDecl))
+ FoundDecl = Template->getTemplatedDecl();
+ else
+ continue;
+ }
+
+ if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) {
if (FoundFunction->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
- 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;
+ if (IsStructuralMatch(D, FoundFunction)) {
+ const FunctionDecl *Definition = nullptr;
+ if (D->doesThisDeclarationHaveABody() &&
+ FoundFunction->hasBody(Definition)) {
+ return Importer.MapImported(
+ D, const_cast<FunctionDecl *>(Definition));
}
- return Importer.Imported(D, FoundFunction);
+ FoundByLookup = FoundFunction;
+ break;
}
// FIXME: Check for overloading more carefully, e.g., by boosting
@@ -2092,22 +2608,22 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Complain about inconsistent function types.
Importer.ToDiag(Loc, diag::err_odr_function_type_inconsistent)
<< Name << D->getType() << FoundFunction->getType();
- Importer.ToDiag(FoundFunction->getLocation(),
+ Importer.ToDiag(FoundFunction->getLocation(),
diag::note_odr_value_here)
<< FoundFunction->getType();
}
}
- ConflictingDecls.push_back(FoundDecls[I]);
+ ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
return nullptr;
- }
+ }
}
DeclarationNameInfo NameInfo(Name, Loc);
@@ -2117,8 +2633,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
QualType FromTy = D->getType();
bool usedDifferentExceptionSpec = false;
- if (const FunctionProtoType *
- FromFPT = D->getType()->getAs<FunctionProtoType>()) {
+ if (const auto *FromFPT = D->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
// FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the
// FunctionDecl that we are importing the FunctionProtoType for.
@@ -2142,75 +2657,66 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Import the function parameters.
SmallVector<ParmVarDecl *, 8> Parameters;
for (auto P : D->parameters()) {
- ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P));
+ auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P));
if (!ToP)
return nullptr;
Parameters.push_back(ToP);
}
-
- // Create the imported function.
+
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ if (D->getTypeSourceInfo() && !TInfo)
+ return nullptr;
+
+ // Create the imported function.
FunctionDecl *ToFunction = nullptr;
SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart());
- if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
- ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
- cast<CXXRecordDecl>(DC),
- InnerLocStart,
- NameInfo, T, TInfo,
- FromConstructor->isExplicit(),
- D->isInlineSpecified(),
- D->isImplicit(),
- D->isConstexpr());
+ if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (GetImportedOrCreateDecl<CXXConstructorDecl>(
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(),
+ D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
+ return ToFunction;
if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
SmallVector<CXXCtorInitializer *, 4> CtorInitializers;
- for (CXXCtorInitializer *I : FromConstructor->inits()) {
- CXXCtorInitializer *ToI =
- cast_or_null<CXXCtorInitializer>(Importer.Import(I));
+ for (auto *I : FromConstructor->inits()) {
+ auto *ToI = cast_or_null<CXXCtorInitializer>(Importer.Import(I));
if (!ToI && I)
return nullptr;
CtorInitializers.push_back(ToI);
}
- CXXCtorInitializer **Memory =
+ auto **Memory =
new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
- CXXConstructorDecl *ToCtor = llvm::cast<CXXConstructorDecl>(ToFunction);
+ auto *ToCtor = cast<CXXConstructorDecl>(ToFunction);
ToCtor->setCtorInitializers(Memory);
ToCtor->setNumCtorInitializers(NumInitializers);
}
} else if (isa<CXXDestructorDecl>(D)) {
- ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
- cast<CXXRecordDecl>(DC),
- InnerLocStart,
- NameInfo, T, TInfo,
- D->isInlineSpecified(),
- D->isImplicit());
- } else if (CXXConversionDecl *FromConversion
- = dyn_cast<CXXConversionDecl>(D)) {
- ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
- cast<CXXRecordDecl>(DC),
- InnerLocStart,
- NameInfo, T, TInfo,
- D->isInlineSpecified(),
- FromConversion->isExplicit(),
- D->isConstexpr(),
- Importer.Import(D->getLocEnd()));
- } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- ToFunction = CXXMethodDecl::Create(Importer.getToContext(),
- cast<CXXRecordDecl>(DC),
- InnerLocStart,
- NameInfo, T, TInfo,
- Method->getStorageClass(),
- Method->isInlineSpecified(),
- D->isConstexpr(),
- Importer.Import(D->getLocEnd()));
+ if (GetImportedOrCreateDecl<CXXDestructorDecl>(
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
+ D->isImplicit()))
+ return ToFunction;
+ } else if (CXXConversionDecl *FromConversion =
+ dyn_cast<CXXConversionDecl>(D)) {
+ if (GetImportedOrCreateDecl<CXXConversionDecl>(
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
+ FromConversion->isExplicit(), D->isConstexpr(), SourceLocation()))
+ return ToFunction;
+ } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (GetImportedOrCreateDecl<CXXMethodDecl>(
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(),
+ Method->isInlineSpecified(), D->isConstexpr(), SourceLocation()))
+ return ToFunction;
} else {
- ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
- InnerLocStart,
- NameInfo, T, TInfo, D->getStorageClass(),
- D->isInlineSpecified(),
- D->hasWrittenPrototype(),
- D->isConstexpr());
+ if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC,
+ InnerLocStart, NameInfo, T, TInfo,
+ D->getStorageClass(), D->isInlineSpecified(),
+ D->hasWrittenPrototype(), D->isConstexpr()))
+ return ToFunction;
}
// Import the qualifier, if any.
@@ -2220,21 +2726,31 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
ToFunction->setTrivial(D->isTrivial());
ToFunction->setPure(D->isPure());
- Importer.Imported(D, ToFunction);
+ ToFunction->setRangeEnd(Importer.Import(D->getLocEnd()));
// Set the parameters.
- for (unsigned I = 0, N = Parameters.size(); I != N; ++I) {
- Parameters[I]->setOwningFunction(ToFunction);
- ToFunction->addDeclInternal(Parameters[I]);
+ for (auto *Param : Parameters) {
+ Param->setOwningFunction(ToFunction);
+ ToFunction->addDeclInternal(Param);
}
ToFunction->setParams(Parameters);
- if (FoundWithoutBody) {
+ if (FoundByLookup) {
auto *Recent = const_cast<FunctionDecl *>(
- FoundWithoutBody->getMostRecentDecl());
+ FoundByLookup->getMostRecentDecl());
ToFunction->setPreviousDecl(Recent);
}
+ // We need to complete creation of FunctionProtoTypeLoc manually with setting
+ // params it refers to.
+ if (TInfo) {
+ if (auto ProtoLoc =
+ TInfo->getTypeLoc().IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
+ for (unsigned I = 0, N = Parameters.size(); I != N; ++I)
+ ProtoLoc.setParam(I, Parameters[I]);
+ }
+ }
+
if (usedDifferentExceptionSpec) {
// Update FunctionProtoType::ExtProtoInfo.
QualType T = Importer.Import(D->getType());
@@ -2243,17 +2759,47 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction->setType(T);
}
- // Import the body, if any.
- if (Stmt *FromBody = D->getBody()) {
- if (Stmt *ToBody = Importer.Import(FromBody)) {
- ToFunction->setBody(ToBody);
+ // Import the describing template function, if any.
+ if (FromFT)
+ if (!Importer.Import(FromFT))
+ return nullptr;
+
+ if (D->doesThisDeclarationHaveABody()) {
+ if (Stmt *FromBody = D->getBody()) {
+ if (Stmt *ToBody = Importer.Import(FromBody)) {
+ ToFunction->setBody(ToBody);
+ }
}
}
// FIXME: Other bits to merge?
- // Add this function to the lexical context.
- LexicalDC->addDeclInternal(ToFunction);
+ // If it is a template, import all related things.
+ if (ImportTemplateInformation(D, ToFunction))
+ return nullptr;
+
+ bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend);
+
+ // TODO Can we generalize this approach to other AST nodes as well?
+ if (D->getDeclContext()->containsDeclAndLoad(D))
+ DC->addDeclInternal(ToFunction);
+ if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D))
+ LexicalDC->addDeclInternal(ToFunction);
+
+ // Friend declaration's lexical context is the befriending class, but the
+ // semantic context is the enclosing scope of the befriending class.
+ // We want the friend functions to be found in the semantic context by lookup.
+ // FIXME should we handle this generically in VisitFriendDecl?
+ // In Other cases when LexicalDC != DC we don't want it to be added,
+ // e.g out-of-class definitions like void B::f() {} .
+ if (LexicalDC != DC && IsFriend) {
+ DC->makeDeclVisibleInContext(ToFunction);
+ }
+
+ // Import the rest of the chain. I.e. import all subsequent declarations.
+ for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt)
+ if (!Importer.Import(*RedeclIt))
+ return nullptr;
if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);
@@ -2278,7 +2824,7 @@ Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
}
static unsigned getFieldIndex(Decl *F) {
- RecordDecl *Owner = dyn_cast<RecordDecl>(F->getDeclContext());
+ auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext());
if (!Owner)
return 0;
@@ -2305,18 +2851,18 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
if (ToD)
return ToD;
- // Determine whether we've already imported this field.
+ // Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) {
+ for (auto *FoundDecl : FoundDecls) {
+ if (auto *FoundField = dyn_cast<FieldDecl>(FoundDecl)) {
// For anonymous fields, match up by index.
if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
continue;
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType())) {
- Importer.Imported(D, FoundField);
+ Importer.MapImported(D, FoundField);
return FoundField;
}
@@ -2338,11 +2884,13 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
if (!BitWidth && D->getBitWidth())
return nullptr;
- FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getInnerLocStart()),
- Loc, Name.getAsIdentifierInfo(),
- T, TInfo, BitWidth, D->isMutable(),
- D->getInClassInitStyle());
+ FieldDecl *ToField;
+ if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC,
+ Importer.Import(D->getInnerLocStart()), Loc,
+ Name.getAsIdentifierInfo(), T, TInfo, BitWidth,
+ D->isMutable(), D->getInClassInitStyle()))
+ return ToField;
+
ToField->setAccess(D->getAccess());
ToField->setLexicalDeclContext(LexicalDC);
if (Expr *FromInitializer = D->getInClassInitializer()) {
@@ -2353,7 +2901,6 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
return nullptr;
}
ToField->setImplicit(D->isImplicit());
- Importer.Imported(D, ToField);
LexicalDC->addDeclInternal(ToField);
return ToField;
}
@@ -2369,12 +2916,11 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
if (ToD)
return ToD;
- // Determine whether we've already imported this field.
+ // Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (IndirectFieldDecl *FoundField
- = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
+ if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
// For anonymous indirect fields, match up by index.
if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
continue;
@@ -2382,7 +2928,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType(),
!Name.isEmpty())) {
- Importer.Imported(D, FoundField);
+ Importer.MapImported(D, FoundField);
return FoundField;
}
@@ -2403,8 +2949,8 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
if (T.isNull())
return nullptr;
- NamedDecl **NamedChain =
- new (Importer.getToContext())NamedDecl*[D->getChainingSize()];
+ auto **NamedChain =
+ new (Importer.getToContext()) NamedDecl*[D->getChainingSize()];
unsigned i = 0;
for (auto *PI : D->chain()) {
@@ -2414,16 +2960,18 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
NamedChain[i++] = cast<NamedDecl>(D);
}
- IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create(
- Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T,
- {NamedChain, D->getChainingSize()});
+ llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()};
+ IndirectFieldDecl *ToIndirectField;
+ if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC,
+ Loc, Name.getAsIdentifierInfo(), T, CH))
+ // FIXME here we leak `NamedChain` which is allocated before
+ return ToIndirectField;
- for (const auto *Attr : D->attrs())
- ToIndirectField->addAttr(Attr->clone(Importer.getToContext()));
+ for (const auto *A : D->attrs())
+ ToIndirectField->addAttr(Importer.Import(A));
ToIndirectField->setAccess(D->getAccess());
ToIndirectField->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToIndirectField);
LexicalDC->addDeclInternal(ToIndirectField);
return ToIndirectField;
}
@@ -2440,37 +2988,38 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
// FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
auto *RD = cast<CXXRecordDecl>(DC);
FriendDecl *ImportedFriend = RD->getFirstFriend();
- StructuralEquivalenceContext Context(
- Importer.getFromContext(), Importer.getToContext(),
- Importer.getNonEquivalentDecls(), false, false);
while (ImportedFriend) {
if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
- if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
- ImportedFriend->getFriendDecl()))
- return Importer.Imported(D, ImportedFriend);
+ if (IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(),
+ /*Complain=*/false))
+ return Importer.MapImported(D, ImportedFriend);
} else if (D->getFriendType() && ImportedFriend->getFriendType()) {
if (Importer.IsStructurallyEquivalent(
D->getFriendType()->getType(),
ImportedFriend->getFriendType()->getType(), true))
- return Importer.Imported(D, ImportedFriend);
+ return Importer.MapImported(D, ImportedFriend);
}
ImportedFriend = ImportedFriend->getNextFriend();
}
// Not found. Create it.
FriendDecl::FriendUnion ToFU;
- if (NamedDecl *FriendD = D->getFriendDecl())
- ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD));
- else
+ if (NamedDecl *FriendD = D->getFriendDecl()) {
+ auto *ToFriendD = cast_or_null<NamedDecl>(Importer.Import(FriendD));
+ if (ToFriendD && FriendD->getFriendObjectKind() != Decl::FOK_None &&
+ !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator)))
+ ToFriendD->setObjectOfFriendDecl(false);
+
+ ToFU = ToFriendD;
+ } else // The friend is a type, not a decl.
ToFU = Importer.Import(D->getFriendType());
if (!ToFU)
return nullptr;
SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
- TemplateParameterList **FromTPLists =
- D->getTrailingObjects<TemplateParameterList *>();
+ auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>();
for (unsigned I = 0; I < D->NumTPLists; I++) {
TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
if (!List)
@@ -2478,13 +3027,11 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
ToTPLists[I] = List;
}
- FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getLocation()),
- ToFU, Importer.Import(D->getFriendLoc()),
- ToTPLists);
-
- Importer.Imported(D, FrD);
- RD->pushFriendDecl(FrD);
+ FriendDecl *FrD;
+ if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC,
+ Importer.Import(D->getLocation()), ToFU,
+ Importer.Import(D->getFriendLoc()), ToTPLists))
+ return FrD;
FrD->setAccess(D->getAccess());
FrD->setLexicalDeclContext(LexicalDC);
@@ -2506,11 +3053,11 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Determine whether we've already imported this ivar
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) {
+ for (auto *FoundDecl : FoundDecls) {
+ if (auto *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundIvar->getType())) {
- Importer.Imported(D, FoundIvar);
+ Importer.MapImported(D, FoundIvar);
return FoundIvar;
}
@@ -2532,17 +3079,17 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
if (!BitWidth && D->getBitWidth())
return nullptr;
- ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(),
- cast<ObjCContainerDecl>(DC),
- Importer.Import(D->getInnerLocStart()),
- Loc, Name.getAsIdentifierInfo(),
- T, TInfo, D->getAccessControl(),
- BitWidth, D->getSynthesize());
+ ObjCIvarDecl *ToIvar;
+ if (GetImportedOrCreateDecl(
+ ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC),
+ Importer.Import(D->getInnerLocStart()), Loc,
+ Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth,
+ D->getSynthesize()))
+ return ToIvar;
+
ToIvar->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToIvar);
LexicalDC->addDeclInternal(ToIvar);
return ToIvar;
-
}
Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
@@ -2564,11 +3111,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
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))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) {
+ if (auto *FoundVar = dyn_cast<VarDecl>(FoundDecl)) {
// We have found a variable that we may need to merge with. Check it.
if (FoundVar->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
@@ -2606,18 +3153,19 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
<< FoundVar->getType();
}
}
-
- ConflictingDecls.push_back(FoundDecls[I]);
+
+ ConflictingDecls.push_back(FoundDecl);
}
if (MergeWithVar) {
- // An equivalent variable with external linkage has been found. Link
+ // An equivalent variable with external linkage has been found. Link
// the two declarations, then merge them.
- Importer.Imported(D, MergeWithVar);
-
+ Importer.MapImported(D, MergeWithVar);
+ updateFlags(D, MergeWithVar);
+
if (VarDecl *DDef = D->getDefinition()) {
if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) {
- Importer.ToDiag(ExistingDef->getLocation(),
+ Importer.ToDiag(ExistingDef->getLocation(),
diag::err_odr_variable_multiple_def)
<< Name;
Importer.FromDiag(DDef->getLocation(), diag::note_odr_defined_here);
@@ -2631,19 +3179,19 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
}
}
}
-
+
return MergeWithVar;
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
return nullptr;
}
}
-
+
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -2651,20 +3199,20 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
// Create the imported variable.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getInnerLocStart()),
- Loc, Name.getAsIdentifierInfo(),
- T, TInfo,
- D->getStorageClass());
+ VarDecl *ToVar;
+ if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC,
+ Importer.Import(D->getInnerLocStart()), Loc,
+ Name.getAsIdentifierInfo(), T, TInfo,
+ D->getStorageClass()))
+ return ToVar;
+
ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToVar);
- LexicalDC->addDeclInternal(ToVar);
- if (!D->isFileVarDecl() &&
- D->isUsed())
- ToVar->setIsUsed();
+ // Templated declarations should never appear in the enclosing DeclContext.
+ if (!D->getDescribedVarTemplate())
+ LexicalDC->addDeclInternal(ToVar);
// Merge the initializer.
if (ImportDefinition(D, ToVar))
@@ -2680,7 +3228,7 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
// Parameters are created in the translation unit's context, then moved
// into the function declaration's context afterward.
DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
-
+
// Import the name of this declaration.
DeclarationName Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
@@ -2688,24 +3236,26 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
-
+
// Import the parameter's type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
return nullptr;
// Create the imported parameter.
- auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc,
- Name.getAsIdentifierInfo(), T,
- D->getParameterKind());
- return Importer.Imported(D, ToParm);
+ ImplicitParamDecl *ToParm = nullptr;
+ if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo(), T,
+ D->getParameterKind()))
+ return ToParm;
+ return ToParm;
}
Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
// Parameters are created in the translation unit's context, then moved
// into the function declaration's context afterward.
DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
-
+
// Import the name of this declaration.
DeclarationName Name = Importer.Import(D->getDeclName());
if (D->getDeclName() && !Name)
@@ -2713,7 +3263,7 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
-
+
// Import the parameter's type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -2721,11 +3271,13 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
// Create the imported parameter.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getInnerLocStart()),
- Loc, Name.getAsIdentifierInfo(),
- T, TInfo, D->getStorageClass(),
- /*DefaultArg*/ nullptr);
+ ParmVarDecl *ToParm;
+ if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
+ Importer.Import(D->getInnerLocStart()), Loc,
+ Name.getAsIdentifierInfo(), T, TInfo,
+ D->getStorageClass(),
+ /*DefaultArg*/ nullptr))
+ return ToParm;
// Set the default argument.
ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
@@ -2747,10 +3299,15 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
if (FromDefArg && !ToDefArg)
return nullptr;
- if (D->isUsed())
- ToParm->setIsUsed();
+ if (D->isObjCMethodParameter()) {
+ ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex());
+ ToParm->setObjCDeclQualifier(D->getObjCDeclQualifier());
+ } else {
+ ToParm->setScopeInfo(D->getFunctionScopeDepth(),
+ D->getFunctionScopeIndex());
+ }
- return Importer.Imported(D, ToParm);
+ return ToParm;
}
Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
@@ -2766,8 +3323,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) {
+ for (auto *FoundDecl : FoundDecls) {
+ if (auto *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecl)) {
if (FoundMethod->isInstanceMethod() != D->isInstanceMethod())
continue;
@@ -2777,7 +3334,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Importer.ToDiag(Loc, diag::err_odr_objc_method_result_type_inconsistent)
<< D->isInstanceMethod() << Name << D->getReturnType()
<< FoundMethod->getReturnType();
- Importer.ToDiag(FoundMethod->getLocation(),
+ Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
return nullptr;
@@ -2788,7 +3345,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Importer.ToDiag(Loc, diag::err_odr_objc_method_num_params_inconsistent)
<< D->isInstanceMethod() << Name
<< D->param_size() << FoundMethod->param_size();
- Importer.ToDiag(FoundMethod->getLocation(),
+ Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
return nullptr;
@@ -2815,14 +3372,14 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
if (D->isVariadic() != FoundMethod->isVariadic()) {
Importer.ToDiag(Loc, diag::err_odr_objc_method_variadic_inconsistent)
<< D->isInstanceMethod() << Name;
- Importer.ToDiag(FoundMethod->getLocation(),
+ Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
return nullptr;
}
// FIXME: Any other bits we need to merge?
- return Importer.Imported(D, FoundMethod);
+ return Importer.MapImported(D, FoundMethod);
}
}
@@ -2833,11 +3390,14 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo());
- ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create(
- Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()),
- Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(),
- D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
- D->getImplementationControl(), D->hasRelatedResultType());
+ ObjCMethodDecl *ToMethod;
+ if (GetImportedOrCreateDecl(
+ ToMethod, D, Importer.getToContext(), Loc,
+ Importer.Import(D->getLocEnd()), Name.getObjCSelector(), ResultTy,
+ ReturnTInfo, DC, D->isInstanceMethod(), D->isVariadic(),
+ D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
+ D->getImplementationControl(), D->hasRelatedResultType()))
+ return ToMethod;
// FIXME: When we decide to merge method definitions, we'll need to
// deal with implicit parameters.
@@ -2845,24 +3405,27 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
// Import the parameters
SmallVector<ParmVarDecl *, 5> ToParams;
for (auto *FromP : D->parameters()) {
- ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP));
+ auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP));
if (!ToP)
return nullptr;
ToParams.push_back(ToP);
}
-
+
// Set the parameters.
- for (unsigned I = 0, N = ToParams.size(); I != N; ++I) {
- ToParams[I]->setOwningFunction(ToMethod);
- ToMethod->addDeclInternal(ToParams[I]);
+ for (auto *ToParam : ToParams) {
+ ToParam->setOwningFunction(ToMethod);
+ ToMethod->addDeclInternal(ToParam);
}
+
SmallVector<SourceLocation, 12> SelLocs;
D->getSelectorLocs(SelLocs);
- ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
+ for (auto &Loc : SelLocs)
+ Loc = Importer.Import(Loc);
+
+ ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
ToMethod->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToMethod);
LexicalDC->addDeclInternal(ToMethod);
return ToMethod;
}
@@ -2882,16 +3445,14 @@ Decl *ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
if (!BoundInfo)
return nullptr;
- ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create(
- Importer.getToContext(), DC,
- D->getVariance(),
- Importer.Import(D->getVarianceLoc()),
- D->getIndex(),
- Importer.Import(D->getLocation()),
- Name.getAsIdentifierInfo(),
- Importer.Import(D->getColonLoc()),
- BoundInfo);
- Importer.Imported(D, Result);
+ ObjCTypeParamDecl *Result;
+ if (GetImportedOrCreateDecl(
+ Result, D, Importer.getToContext(), DC, D->getVariance(),
+ Importer.Import(D->getVarianceLoc()), D->getIndex(),
+ Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(),
+ Importer.Import(D->getColonLoc()), BoundInfo))
+ return Result;
+
Result->setLexicalDeclContext(LexicalDC);
return Result;
}
@@ -2907,8 +3468,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
if (ToD)
return ToD;
- ObjCInterfaceDecl *ToInterface
- = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
+ auto *ToInterface =
+ cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
if (!ToInterface)
return nullptr;
@@ -2917,23 +3478,23 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
= ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
ObjCCategoryDecl *ToCategory = MergeWithCategory;
if (!ToCategory) {
- ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getAtStartLoc()),
- Loc,
- Importer.Import(D->getCategoryNameLoc()),
- Name.getAsIdentifierInfo(),
- ToInterface,
- /*TypeParamList=*/nullptr,
- Importer.Import(D->getIvarLBraceLoc()),
- Importer.Import(D->getIvarRBraceLoc()));
+
+ if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC,
+ Importer.Import(D->getAtStartLoc()), Loc,
+ Importer.Import(D->getCategoryNameLoc()),
+ Name.getAsIdentifierInfo(), ToInterface,
+ /*TypeParamList=*/nullptr,
+ Importer.Import(D->getIvarLBraceLoc()),
+ Importer.Import(D->getIvarRBraceLoc())))
+ return ToCategory;
+
ToCategory->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToCategory);
- Importer.Imported(D, ToCategory);
// Import the type parameter list after calling Imported, to avoid
// loops when bringing in their DeclContext.
ToCategory->setTypeParamList(ImportObjCTypeParamList(
D->getTypeParamList()));
-
+
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
SmallVector<SourceLocation, 4> ProtocolLocs;
@@ -2943,40 +3504,39 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
FromProtoEnd = D->protocol_end();
FromProto != FromProtoEnd;
++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ auto *ToProto =
+ cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
if (!ToProto)
return nullptr;
Protocols.push_back(ToProto);
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
}
-
+
// FIXME: If we're merging, make sure that the protocol list is the same.
ToCategory->setProtocolList(Protocols.data(), Protocols.size(),
ProtocolLocs.data(), Importer.getToContext());
-
} else {
- Importer.Imported(D, ToCategory);
+ Importer.MapImported(D, ToCategory);
}
-
+
// Import all of the members of this category.
ImportDeclContext(D);
-
+
// If we have an implementation, import it as well.
if (D->getImplementation()) {
- ObjCCategoryImplDecl *Impl
- = cast_or_null<ObjCCategoryImplDecl>(
+ auto *Impl =
+ cast_or_null<ObjCCategoryImplDecl>(
Importer.Import(D->getImplementation()));
if (!Impl)
return nullptr;
ToCategory->setImplementation(Impl);
}
-
+
return ToCategory;
}
-bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
+bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
ObjCProtocolDecl *To,
ImportDefinitionKind Kind) {
if (To->getDefinition()) {
@@ -2987,24 +3547,23 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
// Start the protocol definition
To->startDefinition();
-
+
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
SmallVector<SourceLocation, 4> ProtocolLocs;
- ObjCProtocolDecl::protocol_loc_iterator
+ ObjCProtocolDecl::protocol_loc_iterator
FromProtoLoc = From->protocol_loc_begin();
for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(),
FromProtoEnd = From->protocol_end();
FromProto != FromProtoEnd;
++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
if (!ToProto)
return true;
Protocols.push_back(ToProto);
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
}
-
+
// FIXME: If we're merging, make sure that the protocol list is the same.
To->setProtocolList(Protocols.data(), Protocols.size(),
ProtocolLocs.data(), Importer.getToContext());
@@ -3017,7 +3576,7 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
}
Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
- // If this protocol has a definition in the translation unit we're coming
+ // If this protocol has a definition in the translation unit we're coming
// from, but this particular declaration is not that definition, import the
// definition and map to that.
ObjCProtocolDecl *Definition = D->getDefinition();
@@ -3026,7 +3585,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
// Import the major distinguishing characteristics of a protocol.
@@ -3042,25 +3601,26 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
ObjCProtocolDecl *MergeWithProtocol = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
continue;
-
- if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecls[I])))
+
+ if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecl)))
break;
}
-
+
ObjCProtocolDecl *ToProto = MergeWithProtocol;
if (!ToProto) {
- ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
- Name.getAsIdentifierInfo(), Loc,
- Importer.Import(D->getAtStartLoc()),
- /*PrevDecl=*/nullptr);
+ if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC,
+ Name.getAsIdentifierInfo(), Loc,
+ Importer.Import(D->getAtStartLoc()),
+ /*PrevDecl=*/nullptr))
+ return ToProto;
ToProto->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToProto);
}
-
- Importer.Imported(D, ToProto);
+
+ Importer.MapImported(D, ToProto);
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto))
return nullptr;
@@ -3076,14 +3636,11 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
SourceLocation LangLoc = Importer.Import(D->getLocation());
bool HasBraces = D->hasBraces();
-
- LinkageSpecDecl *ToLinkageSpec =
- LinkageSpecDecl::Create(Importer.getToContext(),
- DC,
- ExternLoc,
- LangLoc,
- D->getLanguage(),
- HasBraces);
+
+ LinkageSpecDecl *ToLinkageSpec;
+ if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC,
+ ExternLoc, LangLoc, D->getLanguage(), HasBraces))
+ return ToLinkageSpec;
if (HasBraces) {
SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc());
@@ -3093,8 +3650,6 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
ToLinkageSpec->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToLinkageSpec);
- Importer.Imported(D, ToLinkageSpec);
-
return ToLinkageSpec;
}
@@ -3112,26 +3667,28 @@ Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
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());
+ UsingDecl *ToUsing;
+ if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
+ Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getQualifierLoc()), NameInfo,
+ D->hasTypename()))
+ return ToUsing;
+
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)))
+ if (auto *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)))
+ for (auto *FromShadow : D->shadows()) {
+ if (auto *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
@@ -3151,27 +3708,28 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
if (ToD)
return ToD;
- UsingDecl *ToUsing = dyn_cast_or_null<UsingDecl>(
- Importer.Import(D->getUsingDecl()));
+ auto *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()));
+ auto *ToTarget = dyn_cast_or_null<NamedDecl>(
+ Importer.Import(D->getTargetDecl()));
if (!ToTarget)
return nullptr;
- UsingShadowDecl *ToShadow = UsingShadowDecl::Create(
- Importer.getToContext(), DC, Loc, ToUsing, ToTarget);
+ UsingShadowDecl *ToShadow;
+ if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc,
+ ToUsing, ToTarget))
+ return ToShadow;
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)))
+ if (auto *ToPattern =
+ dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern)))
Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow,
ToPattern);
else
@@ -3185,7 +3743,6 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
return ToShadow;
}
-
Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -3200,19 +3757,22 @@ Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
if (!ToComAncestor)
return nullptr;
- NamespaceDecl *ToNominated = cast_or_null<NamespaceDecl>(
- Importer.Import(D->getNominatedNamespace()));
+ auto *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);
+ UsingDirectiveDecl *ToUsingDir;
+ if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC,
+ Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getNamespaceKeyLocation()),
+ Importer.Import(D->getQualifierLoc()),
+ Importer.Import(D->getIdentLocation()),
+ ToNominated, ToComAncestor))
+ return ToUsingDir;
+
ToUsingDir->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToUsingDir);
- Importer.Imported(D, ToUsingDir);
return ToUsingDir;
}
@@ -3231,12 +3791,13 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl(
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()));
+ UnresolvedUsingValueDecl *ToUsingValue;
+ if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC,
+ Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getQualifierLoc()), NameInfo,
+ Importer.Import(D->getEllipsisLoc())))
+ return ToUsingValue;
- Importer.Imported(D, ToUsingValue);
ToUsingValue->setAccess(D->getAccess());
ToUsingValue->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToUsingValue);
@@ -3255,13 +3816,14 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
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()));
+ UnresolvedUsingTypenameDecl *ToUsing;
+ if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
+ Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getTypenameLoc()),
+ Importer.Import(D->getQualifierLoc()), Loc, Name,
+ Importer.Import(D->getEllipsisLoc())))
+ return ToUsing;
- Importer.Imported(D, ToUsing);
ToUsing->setAccess(D->getAccess());
ToUsing->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToUsing);
@@ -3269,8 +3831,7 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
return ToUsing;
}
-
-bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
+bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
ObjCInterfaceDecl *To,
ImportDefinitionKind Kind) {
if (To->getDefinition()) {
@@ -3281,36 +3842,36 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
if (!FromSuper)
return true;
}
-
- ObjCInterfaceDecl *ToSuper = To->getSuperClass();
+
+ ObjCInterfaceDecl *ToSuper = To->getSuperClass();
if ((bool)FromSuper != (bool)ToSuper ||
(FromSuper && !declaresSameEntity(FromSuper, ToSuper))) {
- Importer.ToDiag(To->getLocation(),
+ Importer.ToDiag(To->getLocation(),
diag::err_odr_objc_superclass_inconsistent)
<< To->getDeclName();
if (ToSuper)
Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass)
<< To->getSuperClass()->getDeclName();
else
- Importer.ToDiag(To->getLocation(),
+ Importer.ToDiag(To->getLocation(),
diag::note_odr_objc_missing_superclass);
if (From->getSuperClass())
- Importer.FromDiag(From->getSuperClassLoc(),
+ Importer.FromDiag(From->getSuperClassLoc(),
diag::note_odr_objc_superclass)
<< From->getSuperClass()->getDeclName();
else
- Importer.FromDiag(From->getLocation(),
- diag::note_odr_objc_missing_superclass);
+ Importer.FromDiag(From->getLocation(),
+ diag::note_odr_objc_missing_superclass);
}
-
+
if (shouldForceImportDeclContext(Kind))
ImportDeclContext(From);
return false;
}
-
+
// Start the definition.
To->startDefinition();
-
+
// If this class has a superclass, import it.
if (From->getSuperClass()) {
TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo());
@@ -3319,41 +3880,40 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
To->setSuperClass(SuperTInfo);
}
-
+
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
SmallVector<SourceLocation, 4> ProtocolLocs;
- ObjCInterfaceDecl::protocol_loc_iterator
+ ObjCInterfaceDecl::protocol_loc_iterator
FromProtoLoc = From->protocol_loc_begin();
-
+
for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(),
FromProtoEnd = From->protocol_end();
FromProto != FromProtoEnd;
++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
if (!ToProto)
return true;
Protocols.push_back(ToProto);
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
}
-
+
// FIXME: If we're merging, make sure that the protocol list is the same.
To->setProtocolList(Protocols.data(), Protocols.size(),
ProtocolLocs.data(), Importer.getToContext());
-
+
// Import categories. When the categories themselves are imported, they'll
// hook themselves into this interface.
for (auto *Cat : From->known_categories())
Importer.Import(Cat);
-
+
// If we have an @implementation, import it as well.
if (From->getImplementation()) {
- ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
- Importer.Import(From->getImplementation()));
+ auto *Impl = cast_or_null<ObjCImplementationDecl>(
+ Importer.Import(From->getImplementation()));
if (!Impl)
return true;
-
+
To->setImplementation(Impl);
}
@@ -3371,8 +3931,8 @@ ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) {
SmallVector<ObjCTypeParamDecl *, 4> toTypeParams;
for (auto fromTypeParam : *list) {
- auto toTypeParam = cast_or_null<ObjCTypeParamDecl>(
- Importer.Import(fromTypeParam));
+ auto *toTypeParam = cast_or_null<ObjCTypeParamDecl>(
+ Importer.Import(fromTypeParam));
if (!toTypeParam)
return nullptr;
@@ -3395,7 +3955,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
// Import the major distinguishing characteristics of an @interface.
@@ -3412,32 +3972,32 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
ObjCInterfaceDecl *MergeWithIface = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
-
- if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecls[I])))
+
+ if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecl)))
break;
}
-
+
// Create an interface declaration, if one does not already exist.
ObjCInterfaceDecl *ToIface = MergeWithIface;
if (!ToIface) {
- ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getAtStartLoc()),
- Name.getAsIdentifierInfo(),
- /*TypeParamList=*/nullptr,
- /*PrevDecl=*/nullptr, Loc,
- D->isImplicitInterfaceDecl());
+ if (GetImportedOrCreateDecl(
+ ToIface, D, Importer.getToContext(), DC,
+ Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(),
+ /*TypeParamList=*/nullptr,
+ /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()))
+ return ToIface;
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
}
- Importer.Imported(D, ToIface);
+ Importer.MapImported(D, ToIface);
// Import the type parameter list after calling Imported, to avoid
// loops when bringing in their DeclContext.
ToIface->setTypeParamList(ImportObjCTypeParamList(
D->getTypeParamListAsWritten()));
-
+
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
return nullptr;
@@ -3445,8 +4005,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
}
Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
- ObjCCategoryDecl *Category = cast_or_null<ObjCCategoryDecl>(
- Importer.Import(D->getCategoryDecl()));
+ auto *Category = cast_or_null<ObjCCategoryDecl>(
+ Importer.Import(D->getCategoryDecl()));
if (!Category)
return nullptr;
@@ -3457,13 +4017,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
return nullptr;
SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc());
- ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getIdentifier()),
- Category->getClassInterface(),
- Importer.Import(D->getLocation()),
- Importer.Import(D->getAtStartLoc()),
- CategoryNameLoc);
-
+ if (GetImportedOrCreateDecl(
+ ToImpl, D, Importer.getToContext(), DC,
+ Importer.Import(D->getIdentifier()), Category->getClassInterface(),
+ Importer.Import(D->getLocation()),
+ Importer.Import(D->getAtStartLoc()), CategoryNameLoc))
+ return ToImpl;
+
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
@@ -3472,20 +4032,20 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
ToImpl->setLexicalDeclContext(LexicalDC);
}
-
+
LexicalDC->addDeclInternal(ToImpl);
Category->setImplementation(ToImpl);
}
-
- Importer.Imported(D, ToImpl);
+
+ Importer.MapImported(D, ToImpl);
ImportDeclContext(D);
return ToImpl;
}
Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
// Find the corresponding interface.
- ObjCInterfaceDecl *Iface = cast_or_null<ObjCInterfaceDecl>(
- Importer.Import(D->getClassInterface()));
+ auto *Iface = cast_or_null<ObjCInterfaceDecl>(
+ Importer.Import(D->getClassInterface()));
if (!Iface)
return nullptr;
@@ -3502,15 +4062,15 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
if (!Impl) {
// We haven't imported an implementation yet. Create a new @implementation
// now.
- Impl = ObjCImplementationDecl::Create(Importer.getToContext(),
- Importer.ImportContext(D->getDeclContext()),
- Iface, Super,
- Importer.Import(D->getLocation()),
- Importer.Import(D->getAtStartLoc()),
- Importer.Import(D->getSuperClassLoc()),
- Importer.Import(D->getIvarLBraceLoc()),
- Importer.Import(D->getIvarRBraceLoc()));
-
+ if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(),
+ Importer.ImportContext(D->getDeclContext()),
+ Iface, Super, Importer.Import(D->getLocation()),
+ Importer.Import(D->getAtStartLoc()),
+ Importer.Import(D->getSuperClassLoc()),
+ Importer.Import(D->getIvarLBraceLoc()),
+ Importer.Import(D->getIvarRBraceLoc())))
+ return Impl;
+
if (D->getDeclContext() != D->getLexicalDeclContext()) {
DeclContext *LexicalDC
= Importer.ImportContext(D->getLexicalDeclContext());
@@ -3518,12 +4078,12 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
return nullptr;
Impl->setLexicalDeclContext(LexicalDC);
}
-
+
// Associate the implementation with the class it implements.
Iface->setImplementation(Impl);
- Importer.Imported(D, Iface->getImplementation());
+ Importer.MapImported(D, Iface->getImplementation());
} else {
- Importer.Imported(D, Iface->getImplementation());
+ Importer.MapImported(D, Iface->getImplementation());
// Verify that the existing @implementation has the same superclass.
if ((Super && !Impl->getSuperClass()) ||
@@ -3553,7 +4113,7 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
return nullptr;
}
}
-
+
// Import all of the members of this @implementation.
ImportDeclContext(D);
@@ -3574,9 +4134,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
// Check whether we have already imported this property.
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (ObjCPropertyDecl *FoundProp
- = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) {
+ for (auto *FoundDecl : FoundDecls) {
+ if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) {
// Check property types.
if (!Importer.IsStructurallyEquivalent(D->getType(),
FoundProp->getType())) {
@@ -3590,7 +4149,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
// FIXME: Check property attributes, getters, setters, etc.?
// Consider these properties to be equivalent.
- Importer.Imported(D, FoundProp);
+ Importer.MapImported(D, FoundProp);
return FoundProp;
}
}
@@ -3601,15 +4160,14 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
return nullptr;
// Create the new property.
- ObjCPropertyDecl *ToProperty
- = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc,
- Name.getAsIdentifierInfo(),
- Importer.Import(D->getAtLoc()),
- Importer.Import(D->getLParenLoc()),
- Importer.Import(D->getType()),
- TSI,
- D->getPropertyImplementation());
- Importer.Imported(D, ToProperty);
+ ObjCPropertyDecl *ToProperty;
+ if (GetImportedOrCreateDecl(
+ ToProperty, D, Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()),
+ Importer.Import(D->getLParenLoc()), Importer.Import(D->getType()),
+ TSI, D->getPropertyImplementation()))
+ return ToProperty;
+
ToProperty->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToProperty);
@@ -3630,8 +4188,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
}
Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
- ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>(
- Importer.Import(D->getPropertyDecl()));
+ auto *Property = cast_or_null<ObjCPropertyDecl>(
+ Importer.Import(D->getPropertyDecl()));
if (!Property)
return nullptr;
@@ -3647,7 +4205,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
return nullptr;
}
- ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC);
+ auto *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC);
if (!InImpl)
return nullptr;
@@ -3663,25 +4221,24 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
ObjCPropertyImplDecl *ToImpl
= InImpl->FindPropertyImplDecl(Property->getIdentifier(),
Property->getQueryKind());
- if (!ToImpl) {
- ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getLocStart()),
- Importer.Import(D->getLocation()),
- Property,
- D->getPropertyImplementation(),
- Ivar,
- Importer.Import(D->getPropertyIvarDeclLoc()));
+ if (!ToImpl) {
+ if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC,
+ Importer.Import(D->getLocStart()),
+ Importer.Import(D->getLocation()), Property,
+ D->getPropertyImplementation(), Ivar,
+ Importer.Import(D->getPropertyIvarDeclLoc())))
+ return ToImpl;
+
ToImpl->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToImpl);
LexicalDC->addDeclInternal(ToImpl);
} else {
// Check that we have the same kind of property implementation (@synthesize
// vs. @dynamic).
if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) {
- Importer.ToDiag(ToImpl->getLocation(),
+ Importer.ToDiag(ToImpl->getLocation(),
diag::err_odr_objc_property_impl_kind_inconsistent)
- << Property->getDeclName()
- << (ToImpl->getPropertyImplementation()
+ << Property->getDeclName()
+ << (ToImpl->getPropertyImplementation()
== ObjCPropertyImplDecl::Dynamic);
Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_property_impl_kind)
@@ -3689,25 +4246,25 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
<< (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
return nullptr;
}
-
- // For @synthesize, check that we have the same
+
+ // For @synthesize, check that we have the same
if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize &&
Ivar != ToImpl->getPropertyIvarDecl()) {
- Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(),
+ Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(),
diag::err_odr_objc_synthesize_ivar_inconsistent)
<< Property->getDeclName()
<< ToImpl->getPropertyIvarDecl()->getDeclName()
<< Ivar->getDeclName();
- Importer.FromDiag(D->getPropertyIvarDeclLoc(),
+ Importer.FromDiag(D->getPropertyIvarDeclLoc(),
diag::note_odr_objc_synthesize_ivar_here)
<< D->getPropertyIvarDecl()->getDeclName();
return nullptr;
}
-
+
// Merge the existing implementation with the new implementation.
- Importer.Imported(D, ToImpl);
+ Importer.MapImported(D, ToImpl);
}
-
+
return ToImpl;
}
@@ -3715,17 +4272,16 @@ Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
// For template arguments, we adopt the translation unit as our declaration
// context. This context will be fixed when the actual template declaration
// is created.
-
+
// FIXME: Import default argument.
- return TemplateTypeParmDecl::Create(Importer.getToContext(),
- Importer.getToContext().getTranslationUnitDecl(),
- Importer.Import(D->getLocStart()),
- Importer.Import(D->getLocation()),
- D->getDepth(),
- D->getIndex(),
- Importer.Import(D->getIdentifier()),
- D->wasDeclaredWithTypename(),
- D->isParameterPack());
+ TemplateTypeParmDecl *ToD = nullptr;
+ (void)GetImportedOrCreateDecl(
+ ToD, D, Importer.getToContext(),
+ Importer.getToContext().getTranslationUnitDecl(),
+ Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()),
+ D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()),
+ D->wasDeclaredWithTypename(), D->isParameterPack());
+ return ToD;
}
Decl *
@@ -3749,13 +4305,15 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
return nullptr;
// FIXME: Import default argument.
-
- return NonTypeTemplateParmDecl::Create(Importer.getToContext(),
- Importer.getToContext().getTranslationUnitDecl(),
- Importer.Import(D->getInnerLocStart()),
- Loc, D->getDepth(), D->getPosition(),
- Name.getAsIdentifierInfo(),
- T, D->isParameterPack(), TInfo);
+
+ NonTypeTemplateParmDecl *ToD = nullptr;
+ (void)GetImportedOrCreateDecl(
+ ToD, D, Importer.getToContext(),
+ Importer.getToContext().getTranslationUnitDecl(),
+ Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(),
+ D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(),
+ TInfo);
+ return ToD;
}
Decl *
@@ -3767,7 +4325,7 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
-
+
// Import template parameters.
TemplateParameterList *TemplateParams
= ImportTemplateParameterList(D->getTemplateParameters());
@@ -3775,30 +4333,42 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
return nullptr;
// FIXME: Import default argument.
-
- return TemplateTemplateParmDecl::Create(Importer.getToContext(),
- Importer.getToContext().getTranslationUnitDecl(),
- Loc, D->getDepth(), D->getPosition(),
- D->isParameterPack(),
- Name.getAsIdentifierInfo(),
- TemplateParams);
+
+ TemplateTemplateParmDecl *ToD = nullptr;
+ (void)GetImportedOrCreateDecl(
+ ToD, D, Importer.getToContext(),
+ Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(),
+ D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(),
+ TemplateParams);
+ return ToD;
+}
+
+// Returns the definition for a (forward) declaration of a ClassTemplateDecl, if
+// it has any definition in the redecl chain.
+static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) {
+ CXXRecordDecl *ToTemplatedDef = D->getTemplatedDecl()->getDefinition();
+ if (!ToTemplatedDef)
+ return nullptr;
+ ClassTemplateDecl *TemplateWithDef =
+ ToTemplatedDef->getDescribedClassTemplate();
+ return TemplateWithDef;
}
Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// If this record has a definition in the translation unit we're coming from,
// but this particular declaration is not that definition, import the
// definition and map to that.
- CXXRecordDecl *Definition
- = cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition());
+ auto *Definition =
+ cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition());
if (Definition && Definition != D->getTemplatedDecl()) {
Decl *ImportedDef
= Importer.Import(Definition->getDescribedClassTemplate());
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
-
+
// Import the major distinguishing characteristics of this class template.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -3814,72 +4384,76 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
-
- Decl *Found = FoundDecls[I];
- if (ClassTemplateDecl *FoundTemplate
- = dyn_cast<ClassTemplateDecl>(Found)) {
+
+ Decl *Found = FoundDecl;
+ if (auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) {
+
+ // The class to be imported is a definition.
+ if (D->isThisDeclarationADefinition()) {
+ // Lookup will find the fwd decl only if that is more recent than the
+ // definition. So, try to get the definition if that is available in
+ // the redecl chain.
+ ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate);
+ if (!TemplateWithDef)
+ continue;
+ FoundTemplate = TemplateWithDef; // Continue with the definition.
+ }
+
if (IsStructuralMatch(D, FoundTemplate)) {
// The class templates structurally match; call it the same template.
- // FIXME: We may be filling in a forward declaration here. Handle
- // this case!
- Importer.Imported(D->getTemplatedDecl(),
- FoundTemplate->getTemplatedDecl());
- return Importer.Imported(D, FoundTemplate);
- }
+
+ Importer.MapImported(D->getTemplatedDecl(),
+ FoundTemplate->getTemplatedDecl());
+ return Importer.MapImported(D, FoundTemplate);
+ }
}
-
- ConflictingDecls.push_back(FoundDecls[I]);
+
+ ConflictingDecls.push_back(FoundDecl);
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
- ConflictingDecls.data(),
+ ConflictingDecls.data(),
ConflictingDecls.size());
}
-
+
if (!Name)
return nullptr;
}
- CXXRecordDecl *DTemplated = D->getTemplatedDecl();
-
+ CXXRecordDecl *FromTemplated = D->getTemplatedDecl();
+
// Create the declaration that is being templated.
- CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>(
- Importer.Import(DTemplated));
- if (!D2Templated)
+ auto *ToTemplated = cast_or_null<CXXRecordDecl>(
+ Importer.Import(FromTemplated));
+ if (!ToTemplated)
return nullptr;
- // Resolve possible cyclic import.
- if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D))
- return AlreadyImported;
-
// Create the class template declaration itself.
- TemplateParameterList *TemplateParams
- = ImportTemplateParameterList(D->getTemplateParameters());
+ TemplateParameterList *TemplateParams =
+ ImportTemplateParameterList(D->getTemplateParameters());
if (!TemplateParams)
return nullptr;
- ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC,
- Loc, Name, TemplateParams,
- D2Templated);
- D2Templated->setDescribedClassTemplate(D2);
-
+ ClassTemplateDecl *D2;
+ if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name,
+ TemplateParams, ToTemplated))
+ return D2;
+
+ ToTemplated->setDescribedClassTemplate(D2);
+
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(D2);
-
- // Note the relationship between the class templates.
- Importer.Imported(D, D2);
- Importer.Imported(DTemplated, D2Templated);
- if (DTemplated->isCompleteDefinition() &&
- !D2Templated->isCompleteDefinition()) {
+ if (FromTemplated->isCompleteDefinition() &&
+ !ToTemplated->isCompleteDefinition()) {
// FIXME: Import definition!
}
-
+
return D2;
}
@@ -3894,11 +4468,11 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
- ClassTemplateDecl *ClassTemplate
- = cast_or_null<ClassTemplateDecl>(Importer.Import(
+ auto *ClassTemplate =
+ cast_or_null<ClassTemplateDecl>(Importer.Import(
D->getSpecializedTemplate()));
if (!ClassTemplate)
return nullptr;
@@ -3914,14 +4488,14 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
if (!LexicalDC)
return nullptr;
}
-
+
// Import the location of this declaration.
SourceLocation StartLoc = Importer.Import(D->getLocStart());
SourceLocation IdLoc = Importer.Import(D->getLocation());
// Import template arguments.
SmallVector<TemplateArgument, 2> TemplateArgs;
- if (ImportTemplateArguments(D->getTemplateArgs().data(),
+ if (ImportTemplateArguments(D->getTemplateArgs().data(),
D->getTemplateArgs().size(),
TemplateArgs))
return nullptr;
@@ -3933,31 +4507,26 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
if (D2) {
// We already have a class template specialization with these template
// arguments.
-
+
// FIXME: Check for specialization vs. instantiation errors.
-
+
if (RecordDecl *FoundDef = D2->getDefinition()) {
if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// function.
- return Importer.Imported(D, FoundDef);
+ return Importer.MapImported(D, FoundDef);
}
}
} else {
// Create a new specialization.
- if (ClassTemplatePartialSpecializationDecl *PartialSpec =
- dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
-
+ if (auto *PartialSpec =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
// Import TemplateArgumentListInfo
TemplateArgumentListInfo ToTAInfo;
- auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
- for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) {
- if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I]))
- ToTAInfo.addArgument(*ToLoc);
- else
- return nullptr;
- }
+ const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
+ if (ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo))
+ return nullptr;
QualType CanonInjType = Importer.Import(
PartialSpec->getInjectedSpecializationType());
@@ -3970,31 +4539,28 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
if (!ToTPList && PartialSpec->getTemplateParameters())
return nullptr;
- D2 = ClassTemplatePartialSpecializationDecl::Create(
- Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc,
- ToTPList, ClassTemplate,
- llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
- ToTAInfo, CanonInjType, nullptr);
+ if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>(
+ D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc,
+ IdLoc, ToTPList, ClassTemplate,
+ llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
+ ToTAInfo, CanonInjType, nullptr))
+ return D2;
} else {
- D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(),
- D->getTagKind(), DC,
- StartLoc, IdLoc,
- ClassTemplate,
- TemplateArgs,
- /*PrevDecl=*/nullptr);
+ if (GetImportedOrCreateDecl(
+ D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc,
+ IdLoc, ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr))
+ return D2;
}
D2->setSpecializationKind(D->getSpecializationKind());
// Add this specialization to the class template.
ClassTemplate->AddSpecialization(D2, InsertPos);
-
+
// Import the qualifier, if any.
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
- Importer.Imported(D, D2);
-
if (auto *TSI = D->getTypeAsWritten()) {
TypeSourceInfo *TInfo = Importer.Import(TSI);
if (!TInfo)
@@ -4012,11 +4578,14 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind());
- // Add the specialization to this context.
+ // Set the context of this specialization/instantiation.
D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+
+ // Add to the DC only if it was an explicit specialization/instantiation.
+ if (D2->isExplicitInstantiationOrSpecialization()) {
+ LexicalDC->addDeclInternal(D2);
+ }
}
- Importer.Imported(D, D2);
if (D->isCompleteDefinition() && ImportDefinition(D, D2))
return nullptr;
@@ -4028,14 +4597,14 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
// from,
// but this particular declaration is not that definition, import the
// definition and map to that.
- VarDecl *Definition =
+ auto *Definition =
cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition());
if (Definition && Definition != D->getTemplatedDecl()) {
Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate());
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
// Import the major distinguishing characteristics of this variable template.
@@ -4054,21 +4623,21 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
- Decl *Found = FoundDecls[I];
- if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
+ Decl *Found = FoundDecl;
+ if (auto *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
if (IsStructuralMatch(D, FoundTemplate)) {
// The variable templates structurally match; call it the same template.
- Importer.Imported(D->getTemplatedDecl(),
- FoundTemplate->getTemplatedDecl());
- return Importer.Imported(D, FoundTemplate);
+ Importer.MapImported(D->getTemplatedDecl(),
+ FoundTemplate->getTemplatedDecl());
+ return Importer.MapImported(D, FoundTemplate);
}
}
- ConflictingDecls.push_back(FoundDecls[I]);
+ ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
@@ -4088,21 +4657,8 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
return nullptr;
// Create the declaration that is being templated.
- SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
- SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
- TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo());
- VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc,
- IdLoc, Name.getAsIdentifierInfo(), T,
- TInfo, DTemplated->getStorageClass());
- D2Templated->setAccess(DTemplated->getAccess());
- D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
- D2Templated->setLexicalDeclContext(LexicalDC);
-
- // Importer.Imported(DTemplated, D2Templated);
- // LexicalDC->addDeclInternal(D2Templated);
-
- // Merge the initializer.
- if (ImportDefinition(DTemplated, D2Templated))
+ auto *ToTemplated = dyn_cast_or_null<VarDecl>(Importer.Import(DTemplated));
+ if (!ToTemplated)
return nullptr;
// Create the variable template declaration itself.
@@ -4111,24 +4667,23 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
if (!TemplateParams)
return nullptr;
- VarTemplateDecl *D2 = VarTemplateDecl::Create(
- Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated);
- D2Templated->setDescribedVarTemplate(D2);
+ VarTemplateDecl *ToVarTD;
+ if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc,
+ Name, TemplateParams, ToTemplated))
+ return ToVarTD;
- D2->setAccess(D->getAccess());
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+ ToTemplated->setDescribedVarTemplate(ToVarTD);
- // Note the relationship between the variable templates.
- Importer.Imported(D, D2);
- Importer.Imported(DTemplated, D2Templated);
+ ToVarTD->setAccess(D->getAccess());
+ ToVarTD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToVarTD);
if (DTemplated->isThisDeclarationADefinition() &&
- !D2Templated->isThisDeclarationADefinition()) {
+ !ToTemplated->isThisDeclarationADefinition()) {
// FIXME: Import definition!
}
- return D2;
+ return ToVarTD;
}
Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
@@ -4142,10 +4697,10 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
if (!ImportedDef)
return nullptr;
- return Importer.Imported(D, ImportedDef);
+ return Importer.MapImported(D, ImportedDef);
}
- VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>(
+ auto *VarTemplate = cast_or_null<VarTemplateDecl>(
Importer.Import(D->getSpecializedTemplate()));
if (!VarTemplate)
return nullptr;
@@ -4188,23 +4743,68 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// variable.
- return Importer.Imported(D, FoundDef);
+ return Importer.MapImported(D, FoundDef);
}
}
} else {
-
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
return nullptr;
+
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ if (D->getTypeSourceInfo() && !TInfo)
+ return nullptr;
+
+ TemplateArgumentListInfo ToTAInfo;
+ if (ImportTemplateArgumentListInfo(D->getTemplateArgsInfo(), ToTAInfo))
+ return nullptr;
+ using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
// Create a new specialization.
- D2 = VarTemplateSpecializationDecl::Create(
- Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
- D->getStorageClass(), TemplateArgs);
+ if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) {
+ // Import TemplateArgumentListInfo
+ TemplateArgumentListInfo ArgInfos;
+ const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten();
+ // NOTE: FromTAArgsAsWritten and template parameter list are non-null.
+ if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos))
+ return nullptr;
+
+ TemplateParameterList *ToTPList = ImportTemplateParameterList(
+ FromPartial->getTemplateParameters());
+ if (!ToTPList)
+ return nullptr;
+
+ PartVarSpecDecl *ToPartial;
+ if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
+ StartLoc, IdLoc, ToTPList, VarTemplate, T,
+ TInfo, D->getStorageClass(), TemplateArgs,
+ ArgInfos))
+ return ToPartial;
+
+ auto *FromInst = FromPartial->getInstantiatedFromMember();
+ auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst));
+ if (FromInst && !ToInst)
+ return nullptr;
+
+ ToPartial->setInstantiatedFromMember(ToInst);
+ if (FromPartial->isMemberSpecialization())
+ ToPartial->setMemberSpecialization();
+
+ D2 = ToPartial;
+ } else { // Full specialization
+ if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, StartLoc,
+ IdLoc, VarTemplate, T, TInfo,
+ D->getStorageClass(), TemplateArgs))
+ return D2;
+ }
+
+ SourceLocation POI = D->getPointOfInstantiation();
+ if (POI.isValid())
+ D2->setPointOfInstantiation(Importer.Import(POI));
+
D2->setSpecializationKind(D->getSpecializationKind());
- D2->setTemplateArgsInfo(D->getTemplateArgsInfo());
+ D2->setTemplateArgsInfo(ToTAInfo);
// Add this specialization to the class template.
VarTemplate->AddSpecialization(D2, InsertPos);
@@ -4212,13 +4812,22 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
// Import the qualifier, if any.
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ if (D->isConstexpr())
+ D2->setConstexpr(true);
+
// Add the specialization to this context.
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(D2);
+
+ D2->setAccess(D->getAccess());
}
- Importer.Imported(D, D2);
- if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2))
+ // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if
+ // declaration has initializer. Should this be fixed in the AST?.. Anyway,
+ // we have to check the declaration for initializer - otherwise, it won't be
+ // imported.
+ if ((D->isThisDeclarationADefinition() || D->hasInit()) &&
+ ImportDefinition(D, D2))
return nullptr;
return D2;
@@ -4242,16 +4851,15 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
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))
+ for (auto *FoundDecl : FoundDecls) {
+ if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (FunctionTemplateDecl *FoundFunction =
- dyn_cast<FunctionTemplateDecl>(FoundDecls[I])) {
+ if (auto *FoundFunction = dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
if (FoundFunction->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
if (IsStructuralMatch(D, FoundFunction)) {
- Importer.Imported(D, FoundFunction);
+ Importer.MapImported(D, FoundFunction);
// FIXME: Actually try to merge the body and other attributes.
return FoundFunction;
}
@@ -4265,18 +4873,19 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (!Params)
return nullptr;
- FunctionDecl *TemplatedFD =
+ auto *TemplatedFD =
cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl()));
if (!TemplatedFD)
return nullptr;
- FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create(
- Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD);
+ FunctionTemplateDecl *ToFunc;
+ if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name,
+ Params, TemplatedFD))
+ return ToFunc;
TemplatedFD->setDescribedFunctionTemplate(ToFunc);
ToFunc->setAccess(D->getAccess());
ToFunc->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToFunc);
LexicalDC->addDeclInternal(ToFunc);
return ToFunc;
@@ -4301,12 +4910,11 @@ DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) {
NumDecls);
}
- Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
- Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
- << S->getStmtClassName();
- return nullptr;
- }
-
+Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return nullptr;
+}
Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
SmallVector<IdentifierInfo *, 4> Names;
@@ -4329,8 +4937,8 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
SmallVector<StringLiteral *, 4> Clobbers;
for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) {
- StringLiteral *Clobber = cast_or_null<StringLiteral>(
- Importer.Import(S->getClobberStringLiteral(I)));
+ auto *Clobber = cast_or_null<StringLiteral>(
+ Importer.Import(S->getClobberStringLiteral(I)));
if (!Clobber)
return nullptr;
Clobbers.push_back(Clobber);
@@ -4338,16 +4946,16 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
SmallVector<StringLiteral *, 4> Constraints;
for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
- StringLiteral *Output = cast_or_null<StringLiteral>(
- Importer.Import(S->getOutputConstraintLiteral(I)));
+ auto *Output = cast_or_null<StringLiteral>(
+ Importer.Import(S->getOutputConstraintLiteral(I)));
if (!Output)
return nullptr;
Constraints.push_back(Output);
}
for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
- StringLiteral *Input = cast_or_null<StringLiteral>(
- Importer.Import(S->getInputConstraintLiteral(I)));
+ auto *Input = cast_or_null<StringLiteral>(
+ Importer.Import(S->getInputConstraintLiteral(I)));
if (!Input)
return nullptr;
Constraints.push_back(Input);
@@ -4360,8 +4968,8 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
return nullptr;
- StringLiteral *AsmStr = cast_or_null<StringLiteral>(
- Importer.Import(S->getAsmString()));
+ auto *AsmStr = cast_or_null<StringLiteral>(
+ Importer.Import(S->getAsmString()));
if (!AsmStr)
return nullptr;
@@ -4383,7 +4991,7 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup());
- for (Decl *ToD : ToDG) {
+ for (auto *ToD : ToDG) {
if (!ToD)
return nullptr;
}
@@ -4399,7 +5007,7 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
}
Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
- llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
+ SmallVector<Stmt *, 8> ToStmts(S->size());
if (ImportContainerChecked(S->body(), ToStmts))
return nullptr;
@@ -4423,7 +5031,7 @@ Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc());
SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc());
SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
- CaseStmt *ToStmt = new (Importer.getToContext())
+ auto *ToStmt = new (Importer.getToContext())
CaseStmt(ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc);
ToStmt->setSubStmt(ToSubStmt);
return ToStmt;
@@ -4441,8 +5049,7 @@ Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc());
- LabelDecl *ToLabelDecl =
- cast_or_null<LabelDecl>(Importer.Import(S->getDecl()));
+ auto *ToLabelDecl = cast_or_null<LabelDecl>(Importer.Import(S->getDecl()));
if (!ToLabelDecl && S->getDecl())
return nullptr;
Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
@@ -4456,15 +5063,8 @@ Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc());
ArrayRef<const Attr*> FromAttrs(S->getAttrs());
SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
- ASTContext &_ToContext = Importer.getToContext();
- std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(),
- [&_ToContext](const Attr *A) -> const Attr * {
- return A->clone(_ToContext);
- });
- for (const Attr *ToA : ToAttrs) {
- if (!ToA)
- return nullptr;
- }
+ if (ImportContainerChecked(FromAttrs, ToAttrs))
+ return nullptr;
Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
if (!ToSubStmt && S->getSubStmt())
return nullptr;
@@ -4516,7 +5116,7 @@ Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
Expr *ToCondition = Importer.Import(S->getCond());
if (!ToCondition && S->getCond())
return nullptr;
- SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt(
+ auto *ToStmt = new (Importer.getToContext()) SwitchStmt(
Importer.getToContext(), ToInit,
ToConditionVariable, ToCondition);
Stmt *ToBody = Importer.Import(S->getBody());
@@ -4528,7 +5128,7 @@ Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
SwitchCase *LastChainedSwitchCase = nullptr;
for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr;
SC = SC->getNextSwitchCase()) {
- SwitchCase *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC));
+ auto *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC));
if (!ToSC)
return nullptr;
if (LastChainedSwitchCase)
@@ -4645,8 +5245,8 @@ Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
Expr *ToRetExpr = Importer.Import(S->getRetValue());
if (!ToRetExpr && S->getRetValue())
return nullptr;
- VarDecl *NRVOCandidate = const_cast<VarDecl*>(S->getNRVOCandidate());
- VarDecl *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate));
+ auto *NRVOCandidate = const_cast<VarDecl *>(S->getNRVOCandidate());
+ auto *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate));
if (!ToNRVOCandidate && NRVOCandidate)
return nullptr;
return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr,
@@ -4688,15 +5288,15 @@ Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
}
Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
- DeclStmt *ToRange =
+ auto *ToRange =
dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt()));
if (!ToRange && S->getRangeStmt())
return nullptr;
- DeclStmt *ToBegin =
+ auto *ToBegin =
dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginStmt()));
if (!ToBegin && S->getBeginStmt())
return nullptr;
- DeclStmt *ToEnd =
+ auto *ToEnd =
dyn_cast_or_null<DeclStmt>(Importer.Import(S->getEndStmt()));
if (!ToEnd && S->getEndStmt())
return nullptr;
@@ -4706,7 +5306,7 @@ Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
Expr *ToInc = Importer.Import(S->getInc());
if (!ToInc && S->getInc())
return nullptr;
- DeclStmt *ToLoopVar =
+ auto *ToLoopVar =
dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt()));
if (!ToLoopVar && S->getLoopVarStmt())
return nullptr;
@@ -4851,7 +5451,6 @@ Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI());
}
-
Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -4866,8 +5465,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
if (T.isNull())
return nullptr;
- StringLiteral *SL = cast_or_null<StringLiteral>(
- Importer.Import(E->getFunctionName()));
+ auto *SL = cast_or_null<StringLiteral>(Importer.Import(E->getFunctionName()));
if (!SL && E->getFunctionName())
return nullptr;
@@ -4876,7 +5474,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
}
Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
- ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
+ auto *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
if (!ToD)
return nullptr;
@@ -4886,25 +5484,20 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
if (!FoundD)
return nullptr;
}
-
+
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
-
TemplateArgumentListInfo ToTAInfo;
TemplateArgumentListInfo *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
- for (const auto &FromLoc : E->template_arguments()) {
- if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc))
- ToTAInfo.addArgument(*ToTALoc);
- else
- return nullptr;
- }
+ if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ return nullptr;
ResInfo = &ToTAInfo;
}
- DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
+ DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
Importer.Import(E->getQualifierLoc()),
Importer.Import(E->getTemplateKeywordLoc()),
ToD,
@@ -4947,14 +5540,14 @@ ASTNodeImporter::ImportDesignator(const Designator &D) {
Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) {
- Expr *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit()));
+ auto *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit()));
if (!Init)
return nullptr;
SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1);
// List elements from the second, the first is Init itself
for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) {
- if (Expr *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I))))
+ if (auto *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I))))
IndexExprs[I - 1] = Arg;
else
return nullptr;
@@ -4966,7 +5559,7 @@ Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) {
return ImportDesignator(D);
});
- for (const Designator &D : DIE->designators())
+ for (const auto &D : DIE->designators())
if (D.isFieldDesignator() && !D.getFieldName())
return nullptr;
@@ -4990,7 +5583,7 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
if (T.isNull())
return nullptr;
- return IntegerLiteral::Create(Importer.getToContext(),
+ return IntegerLiteral::Create(Importer.getToContext(),
E->getValue(), T,
Importer.Import(E->getLocation()));
}
@@ -5067,7 +5660,7 @@ Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
if (T.isNull())
return nullptr;
- LabelDecl *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel()));
+ auto *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel()));
if (!ToLabel)
return nullptr;
@@ -5081,7 +5674,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
if (!SubExpr)
return nullptr;
- return new (Importer.getToContext())
+ return new (Importer.getToContext())
ParenExpr(Importer.Import(E->getLParen()),
Importer.Import(E->getRParen()),
SubExpr);
@@ -5102,8 +5695,8 @@ Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
if (T.isNull())
return nullptr;
- CompoundStmt *ToSubStmt = cast_or_null<CompoundStmt>(
- Importer.Import(E->getSubStmt()));
+ auto *ToSubStmt = cast_or_null<CompoundStmt>(
+ Importer.Import(E->getSubStmt()));
if (!ToSubStmt && E->getSubStmt())
return nullptr;
@@ -5120,16 +5713,15 @@ Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
if (!SubExpr)
return nullptr;
- return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(),
- T, E->getValueKind(),
- E->getObjectKind(),
- Importer.Import(E->getOperatorLoc()));
+ return new (Importer.getToContext()) UnaryOperator(
+ SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(),
+ Importer.Import(E->getOperatorLoc()), E->canOverflow());
}
-Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(
- UnaryExprOrTypeTraitExpr *E) {
+Expr *
+ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
QualType ResultType = Importer.Import(E->getType());
-
+
if (E->isArgumentType()) {
TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo());
if (!TInfo)
@@ -5140,7 +5732,7 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(
Importer.Import(E->getOperatorLoc()),
Importer.Import(E->getRParenLoc()));
}
-
+
Expr *SubExpr = Importer.Import(E->getArgumentExpr());
if (!SubExpr)
return nullptr;
@@ -5208,8 +5800,8 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
if (!Cond)
return nullptr;
- OpaqueValueExpr *OpaqueValue = cast_or_null<OpaqueValueExpr>(
- Importer.Import(E->getOpaqueValue()));
+ auto *OpaqueValue = cast_or_null<OpaqueValueExpr>(
+ Importer.Import(E->getOpaqueValue()));
if (!OpaqueValue)
return nullptr;
@@ -5312,7 +5904,7 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
if (!RHS)
return nullptr;
- return new (Importer.getToContext())
+ return new (Importer.getToContext())
CompoundAssignOperator(LHS, RHS, E->getOpcode(),
T, E->getValueKind(),
E->getObjectKind(),
@@ -5367,7 +5959,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
switch (E->getStmtClass()) {
case Stmt::CStyleCastExprClass: {
- CStyleCastExpr *CCE = cast<CStyleCastExpr>(E);
+ auto *CCE = cast<CStyleCastExpr>(E);
return CStyleCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
SubExpr, &BasePath, TInfo,
@@ -5376,7 +5968,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
}
case Stmt::CXXFunctionalCastExprClass: {
- CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E);
+ auto *FCE = cast<CXXFunctionalCastExpr>(E);
return CXXFunctionalCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), TInfo,
E->getCastKind(), SubExpr, &BasePath,
@@ -5385,7 +5977,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
}
case Stmt::ObjCBridgedCastExprClass: {
- ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E);
+ auto *OCE = cast<ObjCBridgedCastExpr>(E);
return new (Importer.getToContext()) ObjCBridgedCastExpr(
Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
@@ -5395,7 +5987,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
break; // just fall through
}
- CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E);
+ auto *Named = cast<CXXNamedCastExpr>(E);
SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()),
RParenLoc = Importer.Import(Named->getRParenLoc());
SourceRange Brackets = Importer.Import(Named->getAngleBrackets());
@@ -5453,7 +6045,7 @@ Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
break;
}
case OffsetOfNode::Field: {
- FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
+ auto *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
if (!FD)
return nullptr;
Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD,
@@ -5524,8 +6116,7 @@ Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
}
Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
- ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
- Importer.Import(E->getParam()));
+ auto *Param = cast_or_null<ParmVarDecl>(Importer.Import(E->getParam()));
if (!Param)
return nullptr;
@@ -5567,6 +6158,10 @@ Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
if (T.isNull())
return nullptr;
+ TypeSourceInfo *TInfo = Importer.Import(CE->getTypeSourceInfo());
+ if (!TInfo)
+ return nullptr;
+
SmallVector<Expr *, 8> Args(CE->getNumArgs());
if (ImportContainerChecked(CE->arguments(), Args))
return nullptr;
@@ -5576,18 +6171,11 @@ Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
if (!Ctor)
return nullptr;
- return CXXTemporaryObjectExpr::Create(
- Importer.getToContext(), T,
- Importer.Import(CE->getLocStart()),
- Ctor,
- CE->isElidable(),
- Args,
- CE->hadMultipleCandidates(),
- CE->isListInitialization(),
- CE->isStdInitListInitialization(),
- CE->requiresZeroInitialization(),
- CE->getConstructionKind(),
- Importer.Import(CE->getParenOrBraceRange()));
+ return new (Importer.getToContext()) CXXTemporaryObjectExpr(
+ Importer.getToContext(), Ctor, T, TInfo, Args,
+ Importer.Import(CE->getParenOrBraceRange()), CE->hadMultipleCandidates(),
+ CE->isListInitialization(), CE->isStdInitListInitialization(),
+ CE->requiresZeroInitialization());
}
Expr *
@@ -5600,7 +6188,7 @@ ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
if (!TempE)
return nullptr;
- ValueDecl *ExtendedBy = cast_or_null<ValueDecl>(
+ auto *ExtendedBy = cast_or_null<ValueDecl>(
Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
if (!ExtendedBy && E->getExtendingDecl())
return nullptr;
@@ -5627,6 +6215,30 @@ Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
E->getNumExpansions());
}
+Expr *ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ auto *Pack = cast_or_null<NamedDecl>(Importer.Import(E->getPack()));
+ if (!Pack)
+ return nullptr;
+
+ Optional<unsigned> Length;
+
+ if (!E->isValueDependent())
+ Length = E->getPackLength();
+
+ SmallVector<TemplateArgument, 8> PartialArguments;
+ if (E->isPartiallySubstituted()) {
+ if (ImportTemplateArguments(E->getPartialArguments().data(),
+ E->getPartialArguments().size(),
+ PartialArguments))
+ return nullptr;
+ }
+
+ return SizeOfPackExpr::Create(
+ Importer.getToContext(), Importer.Import(E->getOperatorLoc()), Pack,
+ Importer.Import(E->getPackLoc()), Importer.Import(E->getRParenLoc()),
+ Length, PartialArguments);
+}
+
Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
QualType T = Importer.Import(CE->getType());
if (T.isNull())
@@ -5636,12 +6248,12 @@ Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
return nullptr;
- FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>(
+ auto *OperatorNewDecl = cast_or_null<FunctionDecl>(
Importer.Import(CE->getOperatorNew()));
if (!OperatorNewDecl && CE->getOperatorNew())
return nullptr;
- FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
Importer.Import(CE->getOperatorDelete()));
if (!OperatorDeleteDecl && CE->getOperatorDelete())
return nullptr;
@@ -5676,7 +6288,7 @@ Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
if (T.isNull())
return nullptr;
- FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
Importer.Import(E->getOperatorDelete()));
if (!OperatorDeleteDecl && E->getOperatorDelete())
return nullptr;
@@ -5700,7 +6312,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
if (T.isNull())
return nullptr;
- CXXConstructorDecl *ToCCD =
+ auto *ToCCD =
dyn_cast_or_null<CXXConstructorDecl>(Importer.Import(E->getConstructor()));
if (!ToCCD)
return nullptr;
@@ -5742,11 +6354,11 @@ Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
-
+
Expr *ToFn = Importer.Import(E->getCallee());
if (!ToFn)
return nullptr;
-
+
SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
@@ -5760,7 +6372,7 @@ Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
-
+
return new (Importer.getToContext())
CXXThisExpr(Importer.Import(E->getLocation()), T, E->isImplicit());
}
@@ -5769,7 +6381,7 @@ Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
-
+
return new (Importer.getToContext())
CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation()));
}
@@ -5784,13 +6396,17 @@ Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
if (!ToBase && E->getBase())
return nullptr;
- ValueDecl *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl()));
+ auto *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl()));
if (!ToMember && E->getMemberDecl())
return nullptr;
- DeclAccessPair ToFoundDecl = DeclAccessPair::make(
- dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())),
- E->getFoundDecl().getAccess());
+ auto *ToDecl =
+ dyn_cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl()));
+ if (!ToDecl && E->getFoundDecl().getDecl())
+ return nullptr;
+
+ DeclAccessPair ToFoundDecl =
+ DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess());
DeclarationNameInfo ToMemberNameInfo(
Importer.Import(E->getMemberNameInfo().getName()),
@@ -5812,7 +6428,6 @@ Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr(
CXXPseudoDestructorExpr *E) {
-
Expr *BaseE = Importer.Import(E->getBase());
if (!BaseE)
return nullptr;
@@ -5856,11 +6471,10 @@ Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
if (BaseType.isNull())
return nullptr;
- TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
- Importer.Import(E->getRAngleLoc()));
- TemplateArgumentListInfo *ResInfo = nullptr;
+ TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
+ E->template_arguments(), ToTAInfo))
return nullptr;
ResInfo = &ToTAInfo;
}
@@ -5884,6 +6498,127 @@ Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo);
}
+Expr *
+ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+ DeclarationName Name = Importer.Import(E->getDeclName());
+ if (!E->getDeclName().isEmpty() && Name.isEmpty())
+ return nullptr;
+
+ DeclarationNameInfo NameInfo(Name, Importer.Import(E->getExprLoc()));
+ ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+ 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;
+ }
+
+ return DependentScopeDeclRefExpr::Create(
+ Importer.getToContext(), Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo);
+}
+
+Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *CE) {
+ unsigned NumArgs = CE->arg_size();
+
+ SmallVector<Expr *, 8> ToArgs(NumArgs);
+ if (ImportArrayChecked(CE->arg_begin(), CE->arg_end(), ToArgs.begin()))
+ return nullptr;
+
+ return CXXUnresolvedConstructExpr::Create(
+ Importer.getToContext(), Importer.Import(CE->getTypeSourceInfo()),
+ Importer.Import(CE->getLParenLoc()), llvm::makeArrayRef(ToArgs),
+ Importer.Import(CE->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+ auto *NamingClass =
+ cast_or_null<CXXRecordDecl>(Importer.Import(E->getNamingClass()));
+ if (E->getNamingClass() && !NamingClass)
+ return nullptr;
+
+ DeclarationName Name = Importer.Import(E->getName());
+ if (E->getName() && !Name)
+ return nullptr;
+
+ DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc()));
+ // Import additional name location/type info.
+ ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+ UnresolvedSet<8> ToDecls;
+ for (auto *D : E->decls()) {
+ if (auto *To = cast_or_null<NamedDecl>(Importer.Import(D)))
+ ToDecls.addDecl(To);
+ else
+ return nullptr;
+ }
+
+ TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;
+ if (E->hasExplicitTemplateArgs()) {
+ if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
+ E->template_arguments(), ToTAInfo))
+ return nullptr;
+ ResInfo = &ToTAInfo;
+ }
+
+ if (ResInfo || E->getTemplateKeywordLoc().isValid())
+ return UnresolvedLookupExpr::Create(
+ Importer.getToContext(), NamingClass,
+ Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()), NameInfo, E->requiresADL(),
+ ResInfo, ToDecls.begin(), ToDecls.end());
+
+ return UnresolvedLookupExpr::Create(
+ Importer.getToContext(), NamingClass,
+ Importer.Import(E->getQualifierLoc()), NameInfo, E->requiresADL(),
+ E->isOverloaded(), ToDecls.begin(), ToDecls.end());
+}
+
+Expr *ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+ DeclarationName Name = Importer.Import(E->getName());
+ if (!E->getName().isEmpty() && Name.isEmpty())
+ return nullptr;
+ DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc()));
+ // Import additional name location/type info.
+ ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+ QualType BaseType = Importer.Import(E->getType());
+ if (!E->getType().isNull() && BaseType.isNull())
+ return nullptr;
+
+ UnresolvedSet<8> ToDecls;
+ for (Decl *D : E->decls()) {
+ if (NamedDecl *To = cast_or_null<NamedDecl>(Importer.Import(D)))
+ ToDecls.addDecl(To);
+ else
+ return nullptr;
+ }
+
+ TemplateArgumentListInfo ToTAInfo;
+ TemplateArgumentListInfo *ResInfo = nullptr;
+ if (E->hasExplicitTemplateArgs()) {
+ if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ return nullptr;
+ ResInfo = &ToTAInfo;
+ }
+
+ Expr *BaseE = E->isImplicitAccess() ? nullptr : Importer.Import(E->getBase());
+ if (!BaseE && !E->isImplicitAccess() && E->getBase()) {
+ return nullptr;
+ }
+
+ return UnresolvedMemberExpr::Create(
+ Importer.getToContext(), E->hasUnresolvedUsing(), BaseE, BaseType,
+ E->isArrow(), Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo,
+ ToDecls.begin(), ToDecls.end());
+}
+
Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5894,35 +6629,100 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
return nullptr;
unsigned NumArgs = E->getNumArgs();
+ SmallVector<Expr *, 2> ToArgs(NumArgs);
+ if (ImportContainerChecked(E->arguments(), ToArgs))
+ return nullptr;
- llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
-
- for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) {
- Expr *FromArg = E->getArg(ai);
- Expr *ToArg = Importer.Import(FromArg);
- if (!ToArg)
- return nullptr;
- ToArgs[ai] = ToArg;
- }
-
- Expr **ToArgs_Copied = new (Importer.getToContext())
- Expr*[NumArgs];
+ auto **ToArgs_Copied = new (Importer.getToContext()) Expr*[NumArgs];
for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai)
ToArgs_Copied[ai] = ToArgs[ai];
+ if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
+ return new (Importer.getToContext()) CXXOperatorCallExpr(
+ Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, T,
+ OCE->getValueKind(), Importer.Import(OCE->getRParenLoc()),
+ OCE->getFPFeatures());
+ }
+
return new (Importer.getToContext())
- CallExpr(Importer.getToContext(), ToCallee,
+ CallExpr(Importer.getToContext(), ToCallee,
llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(),
Importer.Import(E->getRParenLoc()));
}
+Optional<LambdaCapture>
+ASTNodeImporter::ImportLambdaCapture(const LambdaCapture &From) {
+ VarDecl *Var = nullptr;
+ if (From.capturesVariable()) {
+ Var = cast_or_null<VarDecl>(Importer.Import(From.getCapturedVar()));
+ if (!Var)
+ return None;
+ }
+
+ return LambdaCapture(Importer.Import(From.getLocation()), From.isImplicit(),
+ From.getCaptureKind(), Var,
+ From.isPackExpansion()
+ ? Importer.Import(From.getEllipsisLoc())
+ : SourceLocation());
+}
+
+Expr *ASTNodeImporter::VisitLambdaExpr(LambdaExpr *LE) {
+ CXXRecordDecl *FromClass = LE->getLambdaClass();
+ auto *ToClass = dyn_cast_or_null<CXXRecordDecl>(Importer.Import(FromClass));
+ if (!ToClass)
+ return nullptr;
+
+ // NOTE: lambda classes are created with BeingDefined flag set up.
+ // It means that ImportDefinition doesn't work for them and we should fill it
+ // manually.
+ if (ToClass->isBeingDefined()) {
+ for (auto FromField : FromClass->fields()) {
+ auto *ToField = cast_or_null<FieldDecl>(Importer.Import(FromField));
+ if (!ToField)
+ return nullptr;
+ }
+ }
+
+ auto *ToCallOp = dyn_cast_or_null<CXXMethodDecl>(
+ Importer.Import(LE->getCallOperator()));
+ if (!ToCallOp)
+ return nullptr;
+
+ ToClass->completeDefinition();
+
+ unsigned NumCaptures = LE->capture_size();
+ SmallVector<LambdaCapture, 8> Captures;
+ Captures.reserve(NumCaptures);
+ for (const auto &FromCapture : LE->captures()) {
+ if (auto ToCapture = ImportLambdaCapture(FromCapture))
+ Captures.push_back(*ToCapture);
+ else
+ return nullptr;
+ }
+
+ SmallVector<Expr *, 8> InitCaptures(NumCaptures);
+ if (ImportContainerChecked(LE->capture_inits(), InitCaptures))
+ return nullptr;
+
+ return LambdaExpr::Create(Importer.getToContext(), ToClass,
+ Importer.Import(LE->getIntroducerRange()),
+ LE->getCaptureDefault(),
+ Importer.Import(LE->getCaptureDefaultLoc()),
+ Captures,
+ LE->hasExplicitParameters(),
+ LE->hasExplicitResultType(),
+ InitCaptures,
+ Importer.Import(LE->getLocEnd()),
+ LE->containsUnexpandedParameterPack());
+}
+
Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
QualType T = Importer.Import(ILE->getType());
if (T.isNull())
return nullptr;
- llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
+ SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
if (ImportContainerChecked(ILE->inits(), Exprs))
return nullptr;
@@ -5940,15 +6740,14 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
}
if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) {
- FieldDecl *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD));
+ auto *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD));
if (!ToFD)
return nullptr;
To->setInitializedFieldInUnion(ToFD);
}
if (InitListExpr *SyntForm = ILE->getSyntacticForm()) {
- InitListExpr *ToSyntForm = cast_or_null<InitListExpr>(
- Importer.Import(SyntForm));
+ auto *ToSyntForm = cast_or_null<InitListExpr>(Importer.Import(SyntForm));
if (!ToSyntForm)
return nullptr;
To->setSyntacticForm(ToSyntForm);
@@ -5961,6 +6760,35 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
return To;
}
+Expr *ASTNodeImporter::VisitCXXStdInitializerListExpr(
+ CXXStdInitializerListExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *SE = Importer.Import(E->getSubExpr());
+ if (!SE)
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXStdInitializerListExpr(T, SE);
+}
+
+Expr *ASTNodeImporter::VisitCXXInheritedCtorInitExpr(
+ CXXInheritedCtorInitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ auto *Ctor = cast_or_null<CXXConstructorDecl>(Importer.Import(
+ E->getConstructor()));
+ if (!Ctor)
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXInheritedCtorInitExpr(
+ Importer.Import(E->getLocation()), T, Ctor,
+ E->constructsVBase(), E->inheritedFromVBase());
+}
+
Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
QualType ToType = Importer.Import(E->getType());
if (ToType.isNull())
@@ -5986,8 +6814,7 @@ Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
}
Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
- FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>(
- Importer.Import(DIE->getField()));
+ auto *ToField = dyn_cast_or_null<FieldDecl>(Importer.Import(DIE->getField()));
if (!ToField && DIE->getField())
return nullptr;
@@ -6011,32 +6838,31 @@ Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
SourceLocation ToOperatorLoc = Importer.Import(E->getOperatorLoc());
SourceLocation ToRParenLoc = Importer.Import(E->getRParenLoc());
SourceRange ToAngleBrackets = Importer.Import(E->getAngleBrackets());
-
+
if (isa<CXXStaticCastExpr>(E)) {
return CXXStaticCastExpr::Create(
- Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
+ Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
} else if (isa<CXXDynamicCastExpr>(E)) {
return CXXDynamicCastExpr::Create(
- Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
+ Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
} else if (isa<CXXReinterpretCastExpr>(E)) {
return CXXReinterpretCastExpr::Create(
- Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
+ Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
} else {
return nullptr;
}
}
-
Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- NonTypeTemplateParmDecl *Param = cast_or_null<NonTypeTemplateParmDecl>(
+ auto *Param = cast_or_null<NonTypeTemplateParmDecl>(
Importer.Import(E->getParameter()));
if (!Param)
return nullptr;
@@ -6070,6 +6896,28 @@ Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), ToValue);
}
+Expr *ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
+ return nullptr;
+
+ if (E->isTypeOperand()) {
+ TypeSourceInfo *TSI = Importer.Import(E->getTypeOperandSourceInfo());
+ if (!TSI)
+ return nullptr;
+
+ return new (Importer.getToContext())
+ CXXTypeidExpr(ToType, TSI, Importer.Import(E->getSourceRange()));
+ }
+
+ Expr *Op = Importer.Import(E->getExprOperand());
+ if (!Op)
+ return nullptr;
+
+ return new (Importer.getToContext())
+ CXXTypeidExpr(ToType, Op, Importer.Import(E->getSourceRange()));
+}
+
void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
@@ -6081,37 +6929,36 @@ void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport)
- : ToContext(ToContext), FromContext(FromContext),
- ToFileManager(ToFileManager), FromFileManager(FromFileManager),
- Minimal(MinimalImport), LastDiagFromFrom(false)
-{
+ : ToContext(ToContext), FromContext(FromContext),
+ ToFileManager(ToFileManager), FromFileManager(FromFileManager),
+ Minimal(MinimalImport) {
ImportedDecls[FromContext.getTranslationUnitDecl()]
= ToContext.getTranslationUnitDecl();
}
-ASTImporter::~ASTImporter() { }
+ASTImporter::~ASTImporter() = default;
QualType ASTImporter::Import(QualType FromT) {
if (FromT.isNull())
- return QualType();
+ return {};
const Type *fromTy = FromT.getTypePtr();
-
- // Check whether we've already imported this type.
+
+ // Check whether we've already imported this type.
llvm::DenseMap<const Type *, const Type *>::iterator Pos
= ImportedTypes.find(fromTy);
if (Pos != ImportedTypes.end())
return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers());
-
+
// Import the type
ASTNodeImporter Importer(*this);
QualType ToT = Importer.Visit(fromTy);
if (ToT.isNull())
return ToT;
-
+
// Record the imported type.
ImportedTypes[fromTy] = ToT.getTypePtr();
-
+
return ToContext.getQualifiedType(ToT, FromT.getLocalQualifiers());
}
@@ -6125,14 +6972,21 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
if (T.isNull())
return nullptr;
- return ToContext.getTrivialTypeSourceInfo(T,
+ return ToContext.getTrivialTypeSourceInfo(T,
Import(FromTSI->getTypeLoc().getLocStart()));
}
+Attr *ASTImporter::Import(const Attr *FromAttr) {
+ Attr *ToAttr = FromAttr->clone(ToContext);
+ ToAttr->setRange(Import(FromAttr->getRange()));
+ return ToAttr;
+}
+
Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
if (Pos != ImportedDecls.end()) {
Decl *ToD = Pos->second;
+ // FIXME: move this call to ImportDeclParts().
ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD);
return ToD;
} else {
@@ -6146,44 +7000,22 @@ Decl *ASTImporter::Import(Decl *FromD) {
ASTNodeImporter Importer(*this);
- // Check whether we've already imported this declaration.
- llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
- if (Pos != ImportedDecls.end()) {
- Decl *ToD = Pos->second;
- Importer.ImportDefinitionIfNeeded(FromD, ToD);
+ // Check whether we've already imported this declaration.
+ Decl *ToD = GetAlreadyImportedOrNull(FromD);
+ if (ToD) {
+ // If FromD has some updated flags after last import, apply it
+ updateFlags(FromD, ToD);
return ToD;
}
-
- // Import the type
- Decl *ToD = Importer.Visit(FromD);
+
+ // Import the type.
+ ToD = Importer.Visit(FromD);
if (!ToD)
return nullptr;
- // Record the imported declaration.
- ImportedDecls[FromD] = ToD;
-
- if (TagDecl *FromTag = dyn_cast<TagDecl>(FromD)) {
- // Keep track of anonymous tags that have an associated typedef.
- if (FromTag->getTypedefNameForAnonDecl())
- AnonTagsWithPendingTypedefs.push_back(FromTag);
- } else if (TypedefNameDecl *FromTypedef = dyn_cast<TypedefNameDecl>(FromD)) {
- // When we've finished transforming a typedef, see whether it was the
- // typedef for an anonymous tag.
- for (SmallVectorImpl<TagDecl *>::iterator
- FromTag = AnonTagsWithPendingTypedefs.begin(),
- FromTagEnd = AnonTagsWithPendingTypedefs.end();
- FromTag != FromTagEnd; ++FromTag) {
- if ((*FromTag)->getTypedefNameForAnonDecl() == FromTypedef) {
- if (TagDecl *ToTag = cast_or_null<TagDecl>(Import(*FromTag))) {
- // We found the typedef for an anonymous tag; link them.
- ToTag->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(ToD));
- AnonTagsWithPendingTypedefs.erase(FromTag);
- break;
- }
- }
- }
- }
-
+ // Notify subclasses.
+ Imported(FromD, ToD);
+
return ToD;
}
@@ -6191,14 +7023,14 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
if (!FromDC)
return FromDC;
- DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
+ auto *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
if (!ToDC)
return nullptr;
- // When we're using a record/enum/Objective-C class/protocol as a context, we
+ // When we're using a record/enum/Objective-C class/protocol as a context, we
// need it to have a definition.
- if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
- RecordDecl *FromRecord = cast<RecordDecl>(FromDC);
+ if (auto *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
+ auto *FromRecord = cast<RecordDecl>(FromDC);
if (ToRecord->isCompleteDefinition()) {
// Do nothing.
} else if (FromRecord->isCompleteDefinition()) {
@@ -6207,8 +7039,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
} else {
CompleteDecl(ToRecord);
}
- } else if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
- EnumDecl *FromEnum = cast<EnumDecl>(FromDC);
+ } else if (auto *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
+ auto *FromEnum = cast<EnumDecl>(FromDC);
if (ToEnum->isCompleteDefinition()) {
// Do nothing.
} else if (FromEnum->isCompleteDefinition()) {
@@ -6216,9 +7048,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
ASTNodeImporter::IDK_Basic);
} else {
CompleteDecl(ToEnum);
- }
- } else if (ObjCInterfaceDecl *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) {
- ObjCInterfaceDecl *FromClass = cast<ObjCInterfaceDecl>(FromDC);
+ }
+ } else if (auto *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) {
+ auto *FromClass = cast<ObjCInterfaceDecl>(FromDC);
if (ToClass->getDefinition()) {
// Do nothing.
} else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) {
@@ -6227,8 +7059,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
} else {
CompleteDecl(ToClass);
}
- } else if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) {
- ObjCProtocolDecl *FromProto = cast<ObjCProtocolDecl>(FromDC);
+ } else if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) {
+ auto *FromProto = cast<ObjCProtocolDecl>(FromDC);
if (ToProto->getDefinition()) {
// Do nothing.
} else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) {
@@ -6236,9 +7068,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
ASTNodeImporter::IDK_Basic);
} else {
CompleteDecl(ToProto);
- }
+ }
}
-
+
return ToDC;
}
@@ -6253,11 +7085,11 @@ Stmt *ASTImporter::Import(Stmt *FromS) {
if (!FromS)
return nullptr;
- // Check whether we've already imported this declaration.
+ // Check whether we've already imported this declaration.
llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
if (Pos != ImportedStmts.end())
return Pos->second;
-
+
// Import the type
ASTNodeImporter Importer(*this);
Stmt *ToS = Importer.Visit(FromS);
@@ -6283,14 +7115,14 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
return nullptr;
case NestedNameSpecifier::Namespace:
- if (NamespaceDecl *NS =
- cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
+ if (auto *NS =
+ cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
return NestedNameSpecifier::Create(ToContext, prefix, NS);
}
return nullptr;
case NestedNameSpecifier::NamespaceAlias:
- if (NamespaceAliasDecl *NSAD =
+ if (auto *NSAD =
cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
return NestedNameSpecifier::Create(ToContext, prefix, NSAD);
}
@@ -6300,7 +7132,7 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
return NestedNameSpecifier::GlobalSpecifier(ToContext);
case NestedNameSpecifier::Super:
- if (CXXRecordDecl *RD =
+ if (auto *RD =
cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
return NestedNameSpecifier::SuperSpecifier(ToContext, RD);
}
@@ -6310,9 +7142,9 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
case NestedNameSpecifier::TypeSpecWithTemplate: {
QualType T = Import(QualType(FromNNS->getAsType(), 0u));
if (!T.isNull()) {
- bool bTemplate = FromNNS->getKind() ==
+ bool bTemplate = FromNNS->getKind() ==
NestedNameSpecifier::TypeSpecWithTemplate;
- return NestedNameSpecifier::Create(ToContext, prefix,
+ return NestedNameSpecifier::Create(ToContext, prefix,
bTemplate, T.getTypePtr());
}
}
@@ -6396,110 +7228,103 @@ NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
TemplateName ASTImporter::Import(TemplateName From) {
switch (From.getKind()) {
case TemplateName::Template:
- if (TemplateDecl *ToTemplate
- = cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl())))
+ if (auto *ToTemplate =
+ cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl())))
return TemplateName(ToTemplate);
-
- return TemplateName();
-
+
+ return {};
+
case TemplateName::OverloadedTemplate: {
OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate();
UnresolvedSet<2> ToTemplates;
- for (OverloadedTemplateStorage::iterator I = FromStorage->begin(),
- E = FromStorage->end();
- I != E; ++I) {
- if (NamedDecl *To = cast_or_null<NamedDecl>(Import(*I)))
+ for (auto *I : *FromStorage) {
+ if (auto *To = cast_or_null<NamedDecl>(Import(I)))
ToTemplates.addDecl(To);
else
- return TemplateName();
+ return {};
}
- return ToContext.getOverloadedTemplateName(ToTemplates.begin(),
+ return ToContext.getOverloadedTemplateName(ToTemplates.begin(),
ToTemplates.end());
}
-
+
case TemplateName::QualifiedTemplate: {
QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName();
NestedNameSpecifier *Qualifier = Import(QTN->getQualifier());
if (!Qualifier)
- return TemplateName();
-
- if (TemplateDecl *ToTemplate
- = cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl())))
- return ToContext.getQualifiedTemplateName(Qualifier,
- QTN->hasTemplateKeyword(),
+ return {};
+
+ if (auto *ToTemplate =
+ cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl())))
+ return ToContext.getQualifiedTemplateName(Qualifier,
+ QTN->hasTemplateKeyword(),
ToTemplate);
-
- return TemplateName();
+
+ return {};
}
-
+
case TemplateName::DependentTemplate: {
DependentTemplateName *DTN = From.getAsDependentTemplateName();
NestedNameSpecifier *Qualifier = Import(DTN->getQualifier());
if (!Qualifier)
- return TemplateName();
-
+ return {};
+
if (DTN->isIdentifier()) {
- return ToContext.getDependentTemplateName(Qualifier,
+ return ToContext.getDependentTemplateName(Qualifier,
Import(DTN->getIdentifier()));
}
-
+
return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator());
}
case TemplateName::SubstTemplateTemplateParm: {
SubstTemplateTemplateParmStorage *subst
= From.getAsSubstTemplateTemplateParm();
- TemplateTemplateParmDecl *param
- = cast_or_null<TemplateTemplateParmDecl>(Import(subst->getParameter()));
+ auto *param =
+ cast_or_null<TemplateTemplateParmDecl>(Import(subst->getParameter()));
if (!param)
- return TemplateName();
+ return {};
TemplateName replacement = Import(subst->getReplacement());
- if (replacement.isNull()) return TemplateName();
-
+ if (replacement.isNull())
+ return {};
+
return ToContext.getSubstTemplateTemplateParm(param, replacement);
}
-
+
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack
= From.getAsSubstTemplateTemplateParmPack();
- TemplateTemplateParmDecl *Param
- = cast_or_null<TemplateTemplateParmDecl>(
- Import(SubstPack->getParameterPack()));
+ auto *Param =
+ cast_or_null<TemplateTemplateParmDecl>(
+ Import(SubstPack->getParameterPack()));
if (!Param)
- return TemplateName();
-
+ return {};
+
ASTNodeImporter Importer(*this);
- TemplateArgument ArgPack
+ TemplateArgument ArgPack
= Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
if (ArgPack.isNull())
- return TemplateName();
-
+ return {};
+
return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
}
-
+
llvm_unreachable("Invalid template name kind");
}
SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
if (FromLoc.isInvalid())
- return SourceLocation();
+ return {};
SourceManager &FromSM = FromContext.getSourceManager();
-
- // For now, map everything down to its file location, so that we
- // don't have to import macro expansions.
- // FIXME: Import macro expansions!
- FromLoc = FromSM.getFileLoc(FromLoc);
+
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
- SourceManager &ToSM = ToContext.getSourceManager();
FileID ToFileID = Import(Decomposed.first);
if (ToFileID.isInvalid())
- return SourceLocation();
- SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID)
- .getLocWithOffset(Decomposed.second);
- return ret;
+ return {};
+ SourceManager &ToSM = ToContext.getSourceManager();
+ return ToSM.getComposedLoc(ToFileID, Decomposed.second);
}
SourceRange ASTImporter::Import(SourceRange FromRange) {
@@ -6507,44 +7332,58 @@ SourceRange ASTImporter::Import(SourceRange FromRange) {
}
FileID ASTImporter::Import(FileID FromID) {
- llvm::DenseMap<FileID, FileID>::iterator Pos
- = ImportedFileIDs.find(FromID);
+ llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID);
if (Pos != ImportedFileIDs.end())
return Pos->second;
-
+
SourceManager &FromSM = FromContext.getSourceManager();
SourceManager &ToSM = ToContext.getSourceManager();
const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID);
- assert(FromSLoc.isFile() && "Cannot handle macro expansions yet");
-
- // Include location of this file.
- SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
-
- // Map the FileID for to the "to" source manager.
+
+ // Map the FromID to the "to" source manager.
FileID ToID;
- const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
- if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
- // FIXME: We probably want to use getVirtualFile(), so we don't hit the
- // disk again
- // FIXME: We definitely want to re-use the existing MemoryBuffer, rather
- // than mmap the files several times.
- const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName());
- if (!Entry)
- return FileID();
- ToID = ToSM.createFileID(Entry, ToIncludeLoc,
- FromSLoc.getFile().getFileCharacteristic());
+ if (FromSLoc.isExpansion()) {
+ const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion();
+ SourceLocation ToSpLoc = Import(FromEx.getSpellingLoc());
+ SourceLocation ToExLocS = Import(FromEx.getExpansionLocStart());
+ unsigned TokenLen = FromSM.getFileIDSize(FromID);
+ SourceLocation MLoc;
+ if (FromEx.isMacroArgExpansion()) {
+ MLoc = ToSM.createMacroArgExpansionLoc(ToSpLoc, ToExLocS, TokenLen);
+ } else {
+ SourceLocation ToExLocE = Import(FromEx.getExpansionLocEnd());
+ MLoc = ToSM.createExpansionLoc(ToSpLoc, ToExLocS, ToExLocE, TokenLen,
+ FromEx.isExpansionTokenRange());
+ }
+ ToID = ToSM.getFileID(MLoc);
} else {
- // FIXME: We want to re-use the existing MemoryBuffer!
- const llvm::MemoryBuffer *
- FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
- std::unique_ptr<llvm::MemoryBuffer> ToBuf
- = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
- FromBuf->getBufferIdentifier());
- ToID = ToSM.createFileID(std::move(ToBuf),
- FromSLoc.getFile().getFileCharacteristic());
- }
-
-
+ // Include location of this file.
+ SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
+
+ const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
+ if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
+ // FIXME: We probably want to use getVirtualFile(), so we don't hit the
+ // disk again
+ // FIXME: We definitely want to re-use the existing MemoryBuffer, rather
+ // than mmap the files several times.
+ const FileEntry *Entry =
+ ToFileManager.getFile(Cache->OrigEntry->getName());
+ if (!Entry)
+ return {};
+ ToID = ToSM.createFileID(Entry, ToIncludeLoc,
+ FromSLoc.getFile().getFileCharacteristic());
+ } else {
+ // FIXME: We want to re-use the existing MemoryBuffer!
+ const llvm::MemoryBuffer *FromBuf =
+ Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
+ std::unique_ptr<llvm::MemoryBuffer> ToBuf =
+ llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
+ FromBuf->getBufferIdentifier());
+ ToID = ToSM.createFileID(std::move(ToBuf),
+ FromSLoc.getFile().getFileCharacteristic());
+ }
+ }
+
ImportedFileIDs[FromID] = ToID;
return ToID;
}
@@ -6565,8 +7404,7 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
From->isPackExpansion() ? Import(From->getEllipsisLoc())
: SourceLocation());
} else if (From->isMemberInitializer()) {
- FieldDecl *ToField =
- llvm::cast_or_null<FieldDecl>(Import(From->getMember()));
+ auto *ToField = cast_or_null<FieldDecl>(Import(From->getMember()));
if (!ToField && From->getMember())
return nullptr;
@@ -6574,7 +7412,7 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
ToContext, ToField, Import(From->getMemberLocation()),
Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()));
} else if (From->isIndirectMemberInitializer()) {
- IndirectFieldDecl *ToIField = llvm::cast_or_null<IndirectFieldDecl>(
+ auto *ToIField = cast_or_null<IndirectFieldDecl>(
Import(From->getIndirectMember()));
if (!ToIField && From->getIndirectMember())
return nullptr;
@@ -6595,7 +7433,6 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
}
}
-
CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
if (Pos != ImportedCXXBaseSpecifiers.end())
@@ -6615,27 +7452,27 @@ void ASTImporter::ImportDefinition(Decl *From) {
Decl *To = Import(From);
if (!To)
return;
-
- if (DeclContext *FromDC = cast<DeclContext>(From)) {
+
+ if (auto *FromDC = cast<DeclContext>(From)) {
ASTNodeImporter Importer(*this);
-
- if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(To)) {
+
+ if (auto *ToRecord = dyn_cast<RecordDecl>(To)) {
if (!ToRecord->getDefinition()) {
- Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord,
+ Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord,
ASTNodeImporter::IDK_Everything);
return;
- }
+ }
}
- if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) {
+ if (auto *ToEnum = dyn_cast<EnumDecl>(To)) {
if (!ToEnum->getDefinition()) {
- Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum,
+ Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum,
ASTNodeImporter::IDK_Everything);
return;
- }
+ }
}
-
- if (ObjCInterfaceDecl *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
+
+ if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
if (!ToIFace->getDefinition()) {
Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace,
ASTNodeImporter::IDK_Everything);
@@ -6643,21 +7480,21 @@ void ASTImporter::ImportDefinition(Decl *From) {
}
}
- if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
+ if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
if (!ToProto->getDefinition()) {
Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto,
ASTNodeImporter::IDK_Everything);
return;
}
}
-
+
Importer.ImportDeclContext(FromDC, true);
}
}
DeclarationName ASTImporter::Import(DeclarationName FromName) {
if (!FromName)
- return DeclarationName();
+ return {};
switch (FromName.getNameKind()) {
case DeclarationName::Identifier:
@@ -6671,7 +7508,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) {
case DeclarationName::CXXConstructorName: {
QualType T = Import(FromName.getCXXNameType());
if (T.isNull())
- return DeclarationName();
+ return {};
return ToContext.DeclarationNames.getCXXConstructorName(
ToContext.getCanonicalType(T));
@@ -6680,24 +7517,24 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) {
case DeclarationName::CXXDestructorName: {
QualType T = Import(FromName.getCXXNameType());
if (T.isNull())
- return DeclarationName();
+ return {};
return ToContext.DeclarationNames.getCXXDestructorName(
ToContext.getCanonicalType(T));
}
case DeclarationName::CXXDeductionGuideName: {
- TemplateDecl *Template = cast_or_null<TemplateDecl>(
+ auto *Template = cast_or_null<TemplateDecl>(
Import(FromName.getCXXDeductionGuideTemplate()));
if (!Template)
- return DeclarationName();
+ return {};
return ToContext.DeclarationNames.getCXXDeductionGuideName(Template);
}
case DeclarationName::CXXConversionFunctionName: {
QualType T = Import(FromName.getCXXNameType());
if (T.isNull())
- return DeclarationName();
+ return {};
return ToContext.DeclarationNames.getCXXConversionFunctionName(
ToContext.getCanonicalType(T));
@@ -6733,7 +7570,7 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
Selector ASTImporter::Import(Selector FromSel) {
if (FromSel.isNull())
- return Selector();
+ return {};
SmallVector<IdentifierInfo *, 4> Idents;
Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0)));
@@ -6767,36 +7604,31 @@ DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
}
void ASTImporter::CompleteDecl (Decl *D) {
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+ if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
if (!ID->getDefinition())
ID->startDefinition();
}
- else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+ else if (auto *PD = dyn_cast<ObjCProtocolDecl>(D)) {
if (!PD->getDefinition())
PD->startDefinition();
}
- else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ else if (auto *TD = dyn_cast<TagDecl>(D)) {
if (!TD->getDefinition() && !TD->isBeingDefined()) {
TD->startDefinition();
TD->setCompleteDefinition(true);
}
}
else {
- assert (0 && "CompleteDecl called on a Decl that can't be completed");
+ assert(0 && "CompleteDecl called on a Decl that can't be completed");
}
}
-Decl *ASTImporter::Imported(Decl *From, Decl *To) {
- if (From->hasAttrs()) {
- for (Attr *FromAttr : From->getAttrs())
- To->addAttr(FromAttr->clone(To->getASTContext()));
- }
- if (From->isUsed()) {
- To->setIsUsed();
- }
- if (From->isImplicit()) {
- To->setImplicit();
- }
+Decl *ASTImporter::MapImported(Decl *From, Decl *To) {
+ llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(From);
+ assert((Pos == ImportedDecls.end() || Pos->second == To) &&
+ "Try to import an already imported Decl");
+ if (Pos != ImportedDecls.end())
+ return Pos->second;
ImportedDecls[From] = To;
return To;
}
@@ -6809,6 +7641,7 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To,
return true;
StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls,
- false, Complain);
- return Ctx.IsStructurallyEquivalent(From, To);
+ getStructuralEquivalenceKind(*this), false,
+ Complain);
+ return Ctx.IsEquivalent(From, To);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp
index 0df8e5653f3b..df3c2be9a2e2 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1,4 +1,4 @@
-//===--- ASTStructuralEquivalence.cpp - -------------------------*- C++ -*-===//
+//===- ASTStructuralEquivalence.cpp ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,20 +10,87 @@
// This file implement StructuralEquivalenceContext class and helper functions
// for layout matching.
//
+// The structural equivalence check could have been implemented as a parallel
+// BFS on a pair of graphs. That must have been the original approach at the
+// beginning.
+// Let's consider this simple BFS algorithm from the `s` source:
+// ```
+// void bfs(Graph G, int s)
+// {
+// Queue<Integer> queue = new Queue<Integer>();
+// marked[s] = true; // Mark the source
+// queue.enqueue(s); // and put it on the queue.
+// while (!q.isEmpty()) {
+// int v = queue.dequeue(); // Remove next vertex from the queue.
+// for (int w : G.adj(v))
+// if (!marked[w]) // For every unmarked adjacent vertex,
+// {
+// marked[w] = true;
+// queue.enqueue(w);
+// }
+// }
+// }
+// ```
+// Indeed, it has it's queue, which holds pairs of nodes, one from each graph,
+// this is the `DeclsToCheck` and it's pair is in `TentativeEquivalences`.
+// `TentativeEquivalences` also plays the role of the marking (`marked`)
+// functionality above, we use it to check whether we've already seen a pair of
+// nodes.
+//
+// We put in the elements into the queue only in the toplevel decl check
+// function:
+// ```
+// static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+// Decl *D1, Decl *D2);
+// ```
+// The `while` loop where we iterate over the children is implemented in
+// `Finish()`. And `Finish` is called only from the two **member** functions
+// which check the equivalency of two Decls or two Types. ASTImporter (and
+// other clients) call only these functions.
+//
+// The `static` implementation functions are called from `Finish`, these push
+// the children nodes to the queue via `static bool
+// IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1,
+// Decl *D2)`. So far so good, this is almost like the BFS. However, if we
+// let a static implementation function to call `Finish` via another **member**
+// function that means we end up with two nested while loops each of them
+// working on the same queue. This is wrong and nobody can reason about it's
+// doing. Thus, static implementation functions must not call the **member**
+// functions.
+//
+// So, now `TentativeEquivalences` plays two roles. It is used to store the
+// second half of the decls which we want to compare, plus it plays a role in
+// closing the recursion. On a long term, we could refactor structural
+// equivalency to be more alike to the traditional BFS.
+//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
-#include "clang/AST/ASTImporter.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/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeVisitor.h"
-#include "clang/Basic/SourceManager.h"
-
-namespace {
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <utility>
using namespace clang;
@@ -37,7 +104,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
/// Determine structural equivalence of two expressions.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- Expr *E1, Expr *E2) {
+ const Expr *E1, const Expr *E2) {
if (!E1 || !E2)
return E1 == E2;
@@ -144,6 +211,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
IsStructurallyEquivalent(Context, TS1->getReplacement(),
TS2->getReplacement());
}
+
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage
*P1 = N1.getAsSubstTemplateTemplateParmPack(),
@@ -169,10 +237,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
case TemplateArgument::Type:
- return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType());
+ return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
case TemplateArgument::Integral:
- if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(),
+ if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
Arg2.getIntegralType()))
return false;
@@ -180,7 +248,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Arg2.getAsIntegral());
case TemplateArgument::Declaration:
- return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl());
+ return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
case TemplateArgument::NullPtr:
return true; // FIXME: Is this correct?
@@ -235,6 +303,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (T1.isNull() || T2.isNull())
return T1.isNull() && T2.isNull();
+ QualType OrigT1 = T1;
+ QualType OrigT2 = T2;
+
if (!Context.StrictTypeSpelling) {
// We aren't being strict about token-to-token equivalence of types,
// so map down to the canonical type.
@@ -298,8 +369,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::LValueReference:
case Type::RValueReference: {
- const ReferenceType *Ref1 = cast<ReferenceType>(T1);
- const ReferenceType *Ref2 = cast<ReferenceType>(T2);
+ const auto *Ref1 = cast<ReferenceType>(T1);
+ const auto *Ref2 = cast<ReferenceType>(T2);
if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
return false;
if (Ref1->isInnerRef() != Ref2->isInnerRef())
@@ -311,8 +382,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::MemberPointer: {
- const MemberPointerType *MemPtr1 = cast<MemberPointerType>(T1);
- const MemberPointerType *MemPtr2 = cast<MemberPointerType>(T2);
+ const auto *MemPtr1 = cast<MemberPointerType>(T1);
+ const auto *MemPtr2 = cast<MemberPointerType>(T2);
if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
MemPtr2->getPointeeType()))
return false;
@@ -323,8 +394,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::ConstantArray: {
- const ConstantArrayType *Array1 = cast<ConstantArrayType>(T1);
- const ConstantArrayType *Array2 = cast<ConstantArrayType>(T2);
+ const auto *Array1 = cast<ConstantArrayType>(T1);
+ const auto *Array2 = cast<ConstantArrayType>(T2);
if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
return false;
@@ -340,8 +411,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
case Type::VariableArray: {
- const VariableArrayType *Array1 = cast<VariableArrayType>(T1);
- const VariableArrayType *Array2 = cast<VariableArrayType>(T2);
+ const auto *Array1 = cast<VariableArrayType>(T1);
+ const auto *Array2 = cast<VariableArrayType>(T2);
if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
Array2->getSizeExpr()))
return false;
@@ -353,8 +424,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::DependentSizedArray: {
- const DependentSizedArrayType *Array1 = cast<DependentSizedArrayType>(T1);
- const DependentSizedArrayType *Array2 = cast<DependentSizedArrayType>(T2);
+ const auto *Array1 = cast<DependentSizedArrayType>(T1);
+ const auto *Array2 = cast<DependentSizedArrayType>(T2);
if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
Array2->getSizeExpr()))
return false;
@@ -366,10 +437,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::DependentAddressSpace: {
- const DependentAddressSpaceType *DepAddressSpace1 =
- cast<DependentAddressSpaceType>(T1);
- const DependentAddressSpaceType *DepAddressSpace2 =
- cast<DependentAddressSpaceType>(T2);
+ const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
+ const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
DepAddressSpace2->getAddrSpaceExpr()))
return false;
@@ -381,10 +450,22 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::DependentSizedExtVector: {
- const DependentSizedExtVectorType *Vec1 =
- cast<DependentSizedExtVectorType>(T1);
- const DependentSizedExtVectorType *Vec2 =
- cast<DependentSizedExtVectorType>(T2);
+ const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
+ const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
+ if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
+ Vec2->getSizeExpr()))
+ return false;
+ if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
+ Vec2->getElementType()))
+ return false;
+ break;
+ }
+
+ case Type::DependentVector: {
+ const auto *Vec1 = cast<DependentVectorType>(T1);
+ const auto *Vec2 = cast<DependentVectorType>(T2);
+ if (Vec1->getVectorKind() != Vec2->getVectorKind())
+ return false;
if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
Vec2->getSizeExpr()))
return false;
@@ -396,8 +477,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::Vector:
case Type::ExtVector: {
- const VectorType *Vec1 = cast<VectorType>(T1);
- const VectorType *Vec2 = cast<VectorType>(T2);
+ const auto *Vec1 = cast<VectorType>(T1);
+ const auto *Vec2 = cast<VectorType>(T2);
if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
Vec2->getElementType()))
return false;
@@ -409,8 +490,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::FunctionProto: {
- const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1);
- const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2);
+ const auto *Proto1 = cast<FunctionProtoType>(T1);
+ const auto *Proto2 = cast<FunctionProtoType>(T2);
+
if (Proto1->getNumParams() != Proto2->getNumParams())
return false;
for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
@@ -420,31 +502,41 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
if (Proto1->isVariadic() != Proto2->isVariadic())
return false;
- if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType())
+
+ if (Proto1->getTypeQuals() != Proto2->getTypeQuals())
+ return false;
+
+ // Check exceptions, this information is lost in canonical type.
+ const auto *OrigProto1 =
+ cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
+ const auto *OrigProto2 =
+ cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
+ auto Spec1 = OrigProto1->getExceptionSpecType();
+ auto Spec2 = OrigProto2->getExceptionSpecType();
+
+ if (Spec1 != Spec2)
return false;
- if (Proto1->getExceptionSpecType() == EST_Dynamic) {
- if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
+ if (Spec1 == EST_Dynamic) {
+ if (OrigProto1->getNumExceptions() != OrigProto2->getNumExceptions())
return false;
- for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
- Proto2->getExceptionType(I)))
+ for (unsigned I = 0, N = OrigProto1->getNumExceptions(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context, OrigProto1->getExceptionType(I),
+ OrigProto2->getExceptionType(I)))
return false;
}
- } else if (Proto1->getExceptionSpecType() == EST_ComputedNoexcept) {
- if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
- Proto2->getNoexceptExpr()))
+ } else if (isComputedNoexcept(Spec1)) {
+ if (!IsStructurallyEquivalent(Context, OrigProto1->getNoexceptExpr(),
+ OrigProto2->getNoexceptExpr()))
return false;
}
- if (Proto1->getTypeQuals() != Proto2->getTypeQuals())
- return false;
// Fall through to check the bits common with FunctionNoProtoType.
LLVM_FALLTHROUGH;
}
case Type::FunctionNoProto: {
- const FunctionType *Function1 = cast<FunctionType>(T1);
- const FunctionType *Function2 = cast<FunctionType>(T2);
+ const auto *Function1 = cast<FunctionType>(T1);
+ const auto *Function2 = cast<FunctionType>(T2);
if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
Function2->getReturnType()))
return false;
@@ -458,7 +550,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
cast<UnresolvedUsingType>(T1)->getDecl(),
cast<UnresolvedUsingType>(T2)->getDecl()))
return false;
-
break;
case Type::Attributed:
@@ -501,7 +592,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::UnaryTransform:
if (!IsStructurallyEquivalent(
Context, cast<UnaryTransformType>(T1)->getUnderlyingType(),
- cast<UnaryTransformType>(T1)->getUnderlyingType()))
+ cast<UnaryTransformType>(T2)->getUnderlyingType()))
return false;
break;
@@ -519,8 +610,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
case Type::DeducedTemplateSpecialization: {
- auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
- auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
+ const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
+ const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(),
DT2->getTemplateName()))
return false;
@@ -538,8 +629,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
case Type::TemplateTypeParm: {
- const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1);
- const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2);
+ const auto *Parm1 = cast<TemplateTypeParmType>(T1);
+ const auto *Parm2 = cast<TemplateTypeParmType>(T2);
if (Parm1->getDepth() != Parm2->getDepth())
return false;
if (Parm1->getIndex() != Parm2->getIndex())
@@ -552,10 +643,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::SubstTemplateTypeParm: {
- const SubstTemplateTypeParmType *Subst1 =
- cast<SubstTemplateTypeParmType>(T1);
- const SubstTemplateTypeParmType *Subst2 =
- cast<SubstTemplateTypeParmType>(T2);
+ const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
+ const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
if (!IsStructurallyEquivalent(Context,
QualType(Subst1->getReplacedParameter(), 0),
QualType(Subst2->getReplacedParameter(), 0)))
@@ -567,10 +656,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::SubstTemplateTypeParmPack: {
- const SubstTemplateTypeParmPackType *Subst1 =
- cast<SubstTemplateTypeParmPackType>(T1);
- const SubstTemplateTypeParmPackType *Subst2 =
- cast<SubstTemplateTypeParmPackType>(T2);
+ const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
+ const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
if (!IsStructurallyEquivalent(Context,
QualType(Subst1->getReplacedParameter(), 0),
QualType(Subst2->getReplacedParameter(), 0)))
@@ -580,11 +667,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
}
+
case Type::TemplateSpecialization: {
- const TemplateSpecializationType *Spec1 =
- cast<TemplateSpecializationType>(T1);
- const TemplateSpecializationType *Spec2 =
- cast<TemplateSpecializationType>(T2);
+ const auto *Spec1 = cast<TemplateSpecializationType>(T1);
+ const auto *Spec2 = cast<TemplateSpecializationType>(T2);
if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
Spec2->getTemplateName()))
return false;
@@ -599,8 +685,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::Elaborated: {
- const ElaboratedType *Elab1 = cast<ElaboratedType>(T1);
- const ElaboratedType *Elab2 = cast<ElaboratedType>(T2);
+ const auto *Elab1 = cast<ElaboratedType>(T1);
+ const auto *Elab2 = cast<ElaboratedType>(T2);
// CHECKME: what if a keyword is ETK_None or ETK_typename ?
if (Elab1->getKeyword() != Elab2->getKeyword())
return false;
@@ -614,8 +700,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::InjectedClassName: {
- const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1);
- const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2);
+ const auto *Inj1 = cast<InjectedClassNameType>(T1);
+ const auto *Inj2 = cast<InjectedClassNameType>(T2);
if (!IsStructurallyEquivalent(Context,
Inj1->getInjectedSpecializationType(),
Inj2->getInjectedSpecializationType()))
@@ -624,8 +710,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::DependentName: {
- const DependentNameType *Typename1 = cast<DependentNameType>(T1);
- const DependentNameType *Typename2 = cast<DependentNameType>(T2);
+ const auto *Typename1 = cast<DependentNameType>(T1);
+ const auto *Typename2 = cast<DependentNameType>(T2);
if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(),
Typename2->getQualifier()))
return false;
@@ -637,10 +723,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::DependentTemplateSpecialization: {
- const DependentTemplateSpecializationType *Spec1 =
- cast<DependentTemplateSpecializationType>(T1);
- const DependentTemplateSpecializationType *Spec2 =
- cast<DependentTemplateSpecializationType>(T2);
+ const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
+ const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(),
Spec2->getQualifier()))
return false;
@@ -665,8 +749,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
case Type::ObjCInterface: {
- const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1);
- const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2);
+ const auto *Iface1 = cast<ObjCInterfaceType>(T1);
+ const auto *Iface2 = cast<ObjCInterfaceType>(T2);
if (!IsStructurallyEquivalent(Context, Iface1->getDecl(),
Iface2->getDecl()))
return false;
@@ -674,8 +758,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::ObjCTypeParam: {
- const ObjCTypeParamType *Obj1 = cast<ObjCTypeParamType>(T1);
- const ObjCTypeParamType *Obj2 = cast<ObjCTypeParamType>(T2);
+ const auto *Obj1 = cast<ObjCTypeParamType>(T1);
+ const auto *Obj2 = cast<ObjCTypeParamType>(T2);
if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), Obj2->getDecl()))
return false;
@@ -688,9 +772,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
break;
}
+
case Type::ObjCObject: {
- const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1);
- const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2);
+ const auto *Obj1 = cast<ObjCObjectType>(T1);
+ const auto *Obj2 = cast<ObjCObjectType>(T2);
if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(),
Obj2->getBaseType()))
return false;
@@ -705,28 +790,25 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
case Type::ObjCObjectPointer: {
- const ObjCObjectPointerType *Ptr1 = cast<ObjCObjectPointerType>(T1);
- const ObjCObjectPointerType *Ptr2 = cast<ObjCObjectPointerType>(T2);
+ const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
+ const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(),
Ptr2->getPointeeType()))
return false;
break;
}
- case Type::Atomic: {
+ case Type::Atomic:
if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(),
cast<AtomicType>(T2)->getValueType()))
return false;
break;
- }
- case Type::Pipe: {
+ case Type::Pipe:
if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(),
cast<PipeType>(T2)->getElementType()))
return false;
break;
- }
-
} // end switch
return true;
@@ -735,7 +817,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
/// Determine structural equivalence of two fields.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
FieldDecl *Field1, FieldDecl *Field2) {
- RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
+ const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
// For anonymous structs/unions, match up the anonymous struct/union type
// declarations directly, so that we don't go off searching for anonymous
@@ -829,6 +911,56 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
}
+/// Determine structural equivalence of two methodss.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ CXXMethodDecl *Method1,
+ CXXMethodDecl *Method2) {
+ bool PropertiesEqual =
+ Method1->getDeclKind() == Method2->getDeclKind() &&
+ Method1->getRefQualifier() == Method2->getRefQualifier() &&
+ Method1->getAccess() == Method2->getAccess() &&
+ Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
+ Method1->isStatic() == Method2->isStatic() &&
+ Method1->isConst() == Method2->isConst() &&
+ Method1->isVolatile() == Method2->isVolatile() &&
+ Method1->isVirtual() == Method2->isVirtual() &&
+ Method1->isPure() == Method2->isPure() &&
+ Method1->isDefaulted() == Method2->isDefaulted() &&
+ Method1->isDeleted() == Method2->isDeleted();
+ if (!PropertiesEqual)
+ return false;
+ // FIXME: Check for 'final'.
+
+ if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
+ auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
+ if (Constructor1->isExplicit() != Constructor2->isExplicit())
+ return false;
+ }
+
+ if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
+ auto *Conversion2 = cast<CXXConversionDecl>(Method2);
+ if (Conversion1->isExplicit() != Conversion2->isExplicit())
+ return false;
+ if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
+ Conversion2->getConversionType()))
+ return false;
+ }
+
+ const IdentifierInfo *Name1 = Method1->getIdentifier();
+ const IdentifierInfo *Name2 = Method2->getIdentifier();
+ if (!::IsStructurallyEquivalent(Name1, Name2)) {
+ return false;
+ // TODO: Names do not match, add warning like at check for FieldDecl.
+ }
+
+ // Check the prototypes.
+ if (!::IsStructurallyEquivalent(Context,
+ Method1->getType(), Method2->getType()))
+ return false;
+
+ return true;
+}
+
/// Determine structural equivalence of two records.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
RecordDecl *D1, RecordDecl *D2) {
@@ -845,7 +977,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
}
- if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) {
+ if (!D1->getDeclName() && !D2->getDeclName()) {
// If both anonymous structs/unions are in a record context, make sure
// they occur in the same location in the context records.
if (Optional<unsigned> Index1 =
@@ -861,10 +993,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
// If both declarations are class template specializations, we know
// the ODR applies, so check the template and template arguments.
- ClassTemplateSpecializationDecl *Spec1 =
- dyn_cast<ClassTemplateSpecializationDecl>(D1);
- ClassTemplateSpecializationDecl *Spec2 =
- dyn_cast<ClassTemplateSpecializationDecl>(D2);
+ const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
+ const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
if (Spec1 && Spec2) {
// Check that the specialized templates are the same.
if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
@@ -892,8 +1022,17 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!D1 || !D2)
return true;
- if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
- if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
+ // If any of the records has external storage and we do a minimal check (or
+ // AST import) we assmue they are equivalent. (If we didn't have this
+ // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
+ // another AST import which in turn would call the structural equivalency
+ // check again and finally we'd have an improper result.)
+ if (Context.EqKind == StructuralEquivalenceKind::Minimal)
+ if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
+ return true;
+
+ if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
+ if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
if (D1CXX->hasExternalLexicalStorage() &&
!D1CXX->isCompleteDefinition()) {
D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
@@ -944,6 +1083,44 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
}
}
+
+ // Check the friends for consistency.
+ CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
+ Friend2End = D2CXX->friend_end();
+ for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
+ Friend1End = D1CXX->friend_end();
+ Friend1 != Friend1End; ++Friend1, ++Friend2) {
+ if (Friend2 == Friend2End) {
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(),
+ diag::warn_odr_tag_type_inconsistent)
+ << Context.ToCtx.getTypeDeclType(D2CXX);
+ Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
+ }
+ return false;
+ }
+
+ if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) {
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.ToCtx.getTypeDeclType(D2CXX);
+ Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
+ Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
+ }
+ return false;
+ }
+ }
+
+ if (Friend2 != Friend2End) {
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.ToCtx.getTypeDeclType(D2);
+ Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
+ Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
+ }
+ return false;
+ }
} else if (D1CXX->getNumBases() > 0) {
if (Context.Complain) {
Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
@@ -1081,11 +1258,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
}
- if (!Context.IsStructurallyEquivalent(Params1->getParam(I),
- Params2->getParam(I))) {
-
+ if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
+ Params2->getParam(I)))
return false;
- }
}
return true;
@@ -1121,7 +1296,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
// Check types.
- if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) {
+ if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
if (Context.Complain) {
Context.Diag2(D2->getLocation(),
diag::err_odr_non_type_parameter_type_inconsistent)
@@ -1153,17 +1328,64 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
D2->getTemplateParameters());
}
+static bool IsTemplateDeclCommonStructurallyEquivalent(
+ StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2) {
+ if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
+ return false;
+ if (!D1->getIdentifier()) // Special name
+ if (D1->getNameAsString() != D2->getNameAsString())
+ return false;
+ return IsStructurallyEquivalent(Ctx, D1->getTemplateParameters(),
+ D2->getTemplateParameters());
+}
+
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
ClassTemplateDecl *D1,
ClassTemplateDecl *D2) {
// Check template parameters.
- if (!IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
- D2->getTemplateParameters()))
+ if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
+ return false;
+
+ // Check the templated declaration.
+ return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
+ D2->getTemplatedDecl());
+}
+
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ FunctionTemplateDecl *D1,
+ FunctionTemplateDecl *D2) {
+ // Check template parameters.
+ if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
return false;
// Check the templated declaration.
- return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(),
- D2->getTemplatedDecl());
+ return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
+ D2->getTemplatedDecl()->getType());
+}
+
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ FriendDecl *D1, FriendDecl *D2) {
+ if ((D1->getFriendType() && D2->getFriendDecl()) ||
+ (D1->getFriendDecl() && D2->getFriendType())) {
+ return false;
+ }
+ if (D1->getFriendType() && D2->getFriendType())
+ return IsStructurallyEquivalent(Context,
+ D1->getFriendType()->getType(),
+ D2->getFriendType()->getType());
+ if (D1->getFriendDecl() && D2->getFriendDecl())
+ return IsStructurallyEquivalent(Context, D1->getFriendDecl(),
+ D2->getFriendDecl());
+ return false;
+}
+
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ FunctionDecl *D1, FunctionDecl *D2) {
+ // FIXME: Consider checking for function attributes as well.
+ if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
+ return false;
+
+ return true;
}
/// Determine structural equivalence of two declarations.
@@ -1187,9 +1409,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.DeclsToCheck.push_back(D1->getCanonicalDecl());
return true;
}
-} // namespace
-
-namespace clang {
DiagnosticBuilder StructuralEquivalenceContext::Diag1(SourceLocation Loc,
unsigned DiagID) {
@@ -1214,7 +1433,7 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
ASTContext &Context = Anon->getASTContext();
QualType AnonTy = Context.getRecordType(Anon);
- RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
+ const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
if (!Owner)
return None;
@@ -1234,6 +1453,10 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
// If the field looks like this:
// struct { ... } A;
QualType FieldType = F->getType();
+ // In case of nested structs.
+ while (const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
+ FieldType = ElabType->getNamedType();
+
if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
const RecordDecl *RecDecl = RecType->getDecl();
if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
@@ -1248,16 +1471,26 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
return Index;
}
-bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1,
- Decl *D2) {
+bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) {
+
+ // Ensure that the implementation functions (all static functions in this TU)
+ // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
+ // because that will wreak havoc the internal state (DeclsToCheck and
+ // TentativeEquivalences members) and can cause faulty behaviour. For
+ // instance, some leaf declarations can be stated and cached as inequivalent
+ // as a side effect of one inequivalent element in the DeclsToCheck list.
+ assert(DeclsToCheck.empty());
+ assert(TentativeEquivalences.empty());
+
if (!::IsStructurallyEquivalent(*this, D1, D2))
return false;
return !Finish();
}
-bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1,
- QualType T2) {
+bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
+ assert(DeclsToCheck.empty());
+ assert(TentativeEquivalences.empty());
if (!::IsStructurallyEquivalent(*this, T1, T2))
return false;
@@ -1277,8 +1510,8 @@ bool StructuralEquivalenceContext::Finish() {
// FIXME: Switch on all declaration kinds. For now, we're just going to
// check the obvious ones.
- if (RecordDecl *Record1 = dyn_cast<RecordDecl>(D1)) {
- if (RecordDecl *Record2 = dyn_cast<RecordDecl>(D2)) {
+ if (auto *Record1 = dyn_cast<RecordDecl>(D1)) {
+ if (auto *Record2 = dyn_cast<RecordDecl>(D2)) {
// Check for equivalent structure names.
IdentifierInfo *Name1 = Record1->getIdentifier();
if (!Name1 && Record1->getTypedefNameForAnonDecl())
@@ -1293,8 +1526,8 @@ bool StructuralEquivalenceContext::Finish() {
// Record/non-record mismatch.
Equivalent = false;
}
- } else if (EnumDecl *Enum1 = dyn_cast<EnumDecl>(D1)) {
- if (EnumDecl *Enum2 = dyn_cast<EnumDecl>(D2)) {
+ } else if (auto *Enum1 = dyn_cast<EnumDecl>(D1)) {
+ if (auto *Enum2 = dyn_cast<EnumDecl>(D2)) {
// Check for equivalent enum names.
IdentifierInfo *Name1 = Enum1->getIdentifier();
if (!Name1 && Enum1->getTypedefNameForAnonDecl())
@@ -1309,8 +1542,8 @@ bool StructuralEquivalenceContext::Finish() {
// Enum/non-enum mismatch
Equivalent = false;
}
- } else if (TypedefNameDecl *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) {
- if (TypedefNameDecl *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) {
+ } else if (const auto *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) {
+ if (const auto *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) {
if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(),
Typedef2->getIdentifier()) ||
!::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(),
@@ -1320,46 +1553,75 @@ bool StructuralEquivalenceContext::Finish() {
// Typedef/non-typedef mismatch.
Equivalent = false;
}
- } else if (ClassTemplateDecl *ClassTemplate1 =
- dyn_cast<ClassTemplateDecl>(D1)) {
- if (ClassTemplateDecl *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) {
- if (!::IsStructurallyEquivalent(ClassTemplate1->getIdentifier(),
- ClassTemplate2->getIdentifier()) ||
- !::IsStructurallyEquivalent(*this, ClassTemplate1, ClassTemplate2))
+ } else if (auto *ClassTemplate1 = dyn_cast<ClassTemplateDecl>(D1)) {
+ if (auto *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, ClassTemplate1,
+ ClassTemplate2))
+ Equivalent = false;
+ } else {
+ // Class template/non-class-template mismatch.
+ Equivalent = false;
+ }
+ } else if (auto *FunctionTemplate1 = dyn_cast<FunctionTemplateDecl>(D1)) {
+ if (auto *FunctionTemplate2 = dyn_cast<FunctionTemplateDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, FunctionTemplate1,
+ FunctionTemplate2))
Equivalent = false;
} else {
// Class template/non-class-template mismatch.
Equivalent = false;
}
- } else if (TemplateTypeParmDecl *TTP1 =
- dyn_cast<TemplateTypeParmDecl>(D1)) {
- if (TemplateTypeParmDecl *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) {
+ } else if (auto *TTP1 = dyn_cast<TemplateTypeParmDecl>(D1)) {
+ if (auto *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) {
if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
Equivalent = false;
} else {
// Kind mismatch.
Equivalent = false;
}
- } else if (NonTypeTemplateParmDecl *NTTP1 =
- dyn_cast<NonTypeTemplateParmDecl>(D1)) {
- if (NonTypeTemplateParmDecl *NTTP2 =
- dyn_cast<NonTypeTemplateParmDecl>(D2)) {
+ } else if (auto *NTTP1 = dyn_cast<NonTypeTemplateParmDecl>(D1)) {
+ if (auto *NTTP2 = dyn_cast<NonTypeTemplateParmDecl>(D2)) {
if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2))
Equivalent = false;
} else {
// Kind mismatch.
Equivalent = false;
}
- } else if (TemplateTemplateParmDecl *TTP1 =
- dyn_cast<TemplateTemplateParmDecl>(D1)) {
- if (TemplateTemplateParmDecl *TTP2 =
- dyn_cast<TemplateTemplateParmDecl>(D2)) {
+ } else if (auto *TTP1 = dyn_cast<TemplateTemplateParmDecl>(D1)) {
+ if (auto *TTP2 = dyn_cast<TemplateTemplateParmDecl>(D2)) {
if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
Equivalent = false;
} else {
// Kind mismatch.
Equivalent = false;
}
+ } else if (auto *MD1 = dyn_cast<CXXMethodDecl>(D1)) {
+ if (auto *MD2 = dyn_cast<CXXMethodDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, MD1, MD2))
+ Equivalent = false;
+ } else {
+ // Kind mismatch.
+ Equivalent = false;
+ }
+ } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) {
+ if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(FD1->getIdentifier(),
+ FD2->getIdentifier()))
+ Equivalent = false;
+ if (!::IsStructurallyEquivalent(*this, FD1, FD2))
+ Equivalent = false;
+ } else {
+ // Kind mismatch.
+ Equivalent = false;
+ }
+ } else if (FriendDecl *FrD1 = dyn_cast<FriendDecl>(D1)) {
+ if (FriendDecl *FrD2 = dyn_cast<FriendDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, FrD1, FrD2))
+ Equivalent = false;
+ } else {
+ // Kind mismatch.
+ Equivalent = false;
+ }
}
if (!Equivalent) {
@@ -1374,4 +1636,3 @@ bool StructuralEquivalenceContext::Finish() {
return false;
}
-} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
index 24e96ba38015..a0b22b6a85e0 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
@@ -34,13 +34,13 @@
using namespace clang;
-/// \brief Computes the set of declarations referenced by these base
+/// Computes the set of declarations referenced by these base
/// paths.
void CXXBasePaths::ComputeDeclsFound() {
assert(NumDeclsFound == 0 && !DeclsFound &&
"Already computed the set of declarations");
- llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8>> Decls;
+ llvm::SmallSetVector<NamedDecl *, 8> Decls;
for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path)
Decls.insert(Path->Decls.front());
@@ -63,8 +63,8 @@ CXXBasePaths::decl_range CXXBasePaths::found_decls() {
/// an unqualified, canonical class type.
bool CXXBasePaths::isAmbiguous(CanQualType BaseType) {
BaseType = BaseType.getUnqualifiedType();
- std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
- return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
+ IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType];
+ return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
}
/// clear - Clear out all prior path information.
@@ -76,7 +76,7 @@ void CXXBasePaths::clear() {
DetectedVirtual = nullptr;
}
-/// @brief Swaps the contents of this CXXBasePaths structure with the
+/// Swaps the contents of this CXXBasePaths structure with the
/// contents of Other.
void CXXBasePaths::swap(CXXBasePaths &Other) {
std::swap(Origin, Other.Origin);
@@ -99,7 +99,7 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
CXXBasePaths &Paths) const {
if (getCanonicalDecl() == Base->getCanonicalDecl())
return false;
-
+
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
@@ -120,7 +120,7 @@ bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
if (getCanonicalDecl() == Base->getCanonicalDecl())
return false;
-
+
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
@@ -165,7 +165,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
continue;
}
- CXXRecordDecl *Base =
+ CXXRecordDecl *Base =
cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
if (!Base ||
(Base->isDependentContext() &&
@@ -174,7 +174,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
AllMatches = false;
continue;
}
-
+
Queue.push_back(Base);
if (!BaseMatches(Base)) {
if (AllowShortCircuit) return false;
@@ -209,29 +209,29 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
// C++ [temp.dep]p3:
// In the definition of a class template or a member of a class template,
// if a base class of the class template depends on a template-parameter,
- // the base class scope is not examined during unqualified name lookup
- // either at the point of definition of the class template or member or
+ // the base class scope is not examined during unqualified name lookup
+ // either at the point of definition of the class template or member or
// during an instantiation of the class tem- plate or member.
if (!LookupInDependent && BaseType->isDependentType())
continue;
-
+
// Determine whether we need to visit this base class at all,
// updating the count of subobjects appropriately.
- std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
+ IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
bool VisitBase = true;
bool SetVirtual = false;
if (BaseSpec.isVirtual()) {
- VisitBase = !Subobjects.first;
- Subobjects.first = true;
+ VisitBase = !Subobjects.IsVirtBase;
+ Subobjects.IsVirtBase = true;
if (isDetectingVirtual() && DetectedVirtual == nullptr) {
// If this is the first virtual we find, remember it. If it turns out
// there is no base path here, we'll reset it later.
DetectedVirtual = BaseType->getAs<RecordType>();
SetVirtual = true;
}
- } else
- ++Subobjects.second;
-
+ } else {
+ ++Subobjects.NumberOfNonVirtBases;
+ }
if (isRecordingPaths()) {
// Add this base specifier to the current path.
CXXBasePathElement Element;
@@ -240,7 +240,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
if (BaseSpec.isVirtual())
Element.SubobjectNumber = 0;
else
- Element.SubobjectNumber = Subobjects.second;
+ Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases;
ScratchPath.push_back(Element);
// Calculate the "top-down" access to this base class.
@@ -261,13 +261,13 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
if (IsFirstStep)
ScratchPath.Access = BaseSpec.getAccessSpecifier();
else
- ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere,
+ ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere,
BaseSpec.getAccessSpecifier());
}
-
+
// Track whether there's a path involving this specific base.
bool FoundPathThroughBase = false;
-
+
if (BaseMatches(&BaseSpec, ScratchPath)) {
// We've found a path that terminates at this base.
FoundPath = FoundPathThroughBase = true;
@@ -313,15 +313,15 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
// a sub-object A if A is a base class sub-object of B. Any
// declarations that are so hidden are eliminated from
// consideration.
-
- // There is a path to a base class that meets the criteria. If we're
+
+ // There is a path to a base class that meets the criteria. If we're
// not collecting paths or finding ambiguities, we're done.
FoundPath = FoundPathThroughBase = true;
if (!isFindingAmbiguities())
return FoundPath;
}
}
-
+
// Pop this base specifier off the current path (if we're
// collecting paths).
if (isRecordingPaths()) {
@@ -336,7 +336,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
// Reset the scratch path access.
ScratchPath.Access = AccessToHere;
-
+
return FoundPath;
}
@@ -352,7 +352,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
// we're done.
if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
return true;
-
+
// C++ [class.member.lookup]p6:
// When virtual base classes are used, a hidden declaration can be
// reached along a path through the sub-object lattice that does
@@ -396,7 +396,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
return true;
}
-bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
+bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
const CXXRecordDecl *BaseRecord) {
assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
@@ -405,7 +405,7 @@ bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
->getCanonicalDecl() == BaseRecord;
}
-bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
+bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
const CXXRecordDecl *BaseRecord) {
assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
@@ -415,7 +415,7 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
->getCanonicalDecl() == BaseRecord;
}
-bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
+bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
DeclarationName Name) {
RecordDecl *BaseRecord =
@@ -490,12 +490,12 @@ bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier,
}
bool CXXRecordDecl::
-FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
+FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
-
+
for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
@@ -504,7 +504,7 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag))
return true;
}
-
+
return false;
}
@@ -538,20 +538,20 @@ std::vector<const NamedDecl *> CXXRecordDecl::lookupDependentName(
return Results;
}
-void OverridingMethods::add(unsigned OverriddenSubobject,
+void OverridingMethods::add(unsigned OverriddenSubobject,
UniqueVirtualMethod Overriding) {
SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides
= Overrides[OverriddenSubobject];
- if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
+ if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
Overriding) == SubobjectOverrides.end())
SubobjectOverrides.push_back(Overriding);
}
void OverridingMethods::add(const OverridingMethods &Other) {
for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) {
- for (overriding_const_iterator M = I->second.begin(),
+ for (overriding_const_iterator M = I->second.begin(),
MEnd = I->second.end();
- M != MEnd;
+ M != MEnd;
++M)
add(I->first, *M);
}
@@ -567,11 +567,11 @@ void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) {
namespace {
class FinalOverriderCollector {
- /// \brief The number of subobjects of a given class type that
+ /// 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.
+ /// Overriders for each virtual base subobject.
llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
CXXFinalOverriderMap FinalOverriders;
@@ -586,7 +586,7 @@ public:
} // namespace
-void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
+void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
bool VirtualBase,
const CXXRecordDecl *InVirtualSubobject,
CXXFinalOverriderMap &Overriders) {
@@ -633,12 +633,11 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// Merge the overriders from this base class into our own set of
// overriders.
- for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
+ for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
OMEnd = BaseOverriders->end();
OM != OMEnd;
++OM) {
- const CXXMethodDecl *CanonOM
- = cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
+ const CXXMethodDecl *CanonOM = OM->first->getCanonicalDecl();
Overriders[CanonOM].add(OM->second);
}
}
@@ -649,7 +648,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
if (!M->isVirtual())
continue;
- CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
+ CXXMethodDecl *CanonM = M->getCanonicalDecl();
using OverriddenMethodsRange =
llvm::iterator_range<CXXMethodDecl::method_iterator>;
OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods();
@@ -657,7 +656,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
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.
+ // functions for which we are tracking overridders.
// C++ [class.virtual]p2:
// For convenience we say that any virtual function overrides itself.
@@ -712,12 +711,12 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
FinalOverriderCollector::~FinalOverriderCollector() {
for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
- VO != VOEnd;
+ VO != VOEnd;
++VO)
delete VO->second;
}
-void
+void
CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
FinalOverriderCollector Collector;
Collector.Collect(this, false, nullptr, FinalOverriders);
@@ -755,7 +754,7 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
}
}
-static void
+static void
AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
CXXIndirectPrimaryBaseSet& Bases) {
// If the record has a virtual primary base class, add it to our set.
@@ -778,7 +777,7 @@ AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
}
-void
+void
CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const {
ASTContext &Context = getASTContext();
diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp
index dfa2a1665d40..0d759e226c42 100644
--- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp
@@ -205,7 +205,7 @@ void DeclInfo::fill() {
return;
}
CurrentDecl = CommentDecl;
-
+
Decl::Kind K = CommentDecl->getKind();
switch (K) {
default:
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp
index eecea8fc11df..5ec7586a475d 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp
@@ -122,8 +122,8 @@ std::string BriefParser::Parse() {
if (Tok.is(tok::newline)) {
ConsumeToken();
// We found a paragraph end. This ends the brief description if
- // \\brief command or its equivalent was explicitly used.
- // Stop scanning text because an explicit \\brief paragraph is the
+ // \command or its equivalent was explicitly used.
+ // Stop scanning text because an explicit \paragraph is the
// preffered one.
if (InBrief)
break;
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
index 65d0f56f09ab..8d401ff5c7ea 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
@@ -274,7 +274,7 @@ const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) {
}
llvm_unreachable("buffer end hit before '*/' was seen");
}
-
+
} // end anonymous namespace
void Lexer::formTokenWithChars(Token &Result, const char *TokEnd,
@@ -294,6 +294,39 @@ void Lexer::lexCommentText(Token &T) {
assert(CommentState == LCS_InsideBCPLComment ||
CommentState == LCS_InsideCComment);
+ // Handles lexing non-command text, i.e. text and newline.
+ auto HandleNonCommandToken = [&]() -> void {
+ assert(State == LS_Normal);
+
+ const char *TokenPtr = BufferPtr;
+ assert(TokenPtr < CommentEnd);
+ switch (*TokenPtr) {
+ case '\n':
+ case '\r':
+ TokenPtr = skipNewline(TokenPtr, CommentEnd);
+ formTokenWithChars(T, TokenPtr, tok::newline);
+
+ if (CommentState == LCS_InsideCComment)
+ skipLineStartingDecorations();
+ return;
+
+ default: {
+ StringRef TokStartSymbols = ParseCommands ? "\n\r\\@&<" : "\n\r";
+ size_t End = StringRef(TokenPtr, CommentEnd - TokenPtr)
+ .find_first_of(TokStartSymbols);
+ if (End != StringRef::npos)
+ TokenPtr += End;
+ else
+ TokenPtr = CommentEnd;
+ formTextToken(T, TokenPtr);
+ return;
+ }
+ }
+ };
+
+ if (!ParseCommands)
+ return HandleNonCommandToken();
+
switch (State) {
case LS_Normal:
break;
@@ -315,136 +348,116 @@ void Lexer::lexCommentText(Token &T) {
}
assert(State == LS_Normal);
-
const char *TokenPtr = BufferPtr;
assert(TokenPtr < CommentEnd);
- while (TokenPtr != CommentEnd) {
- switch(*TokenPtr) {
- case '\\':
- case '@': {
- // Commands that start with a backslash and commands that start with
- // 'at' have equivalent semantics. But we keep information about the
- // exact syntax in AST for comments.
- tok::TokenKind CommandKind =
- (*TokenPtr == '@') ? tok::at_command : tok::backslash_command;
+ switch(*TokenPtr) {
+ case '\\':
+ case '@': {
+ // Commands that start with a backslash and commands that start with
+ // 'at' have equivalent semantics. But we keep information about the
+ // exact syntax in AST for comments.
+ tok::TokenKind CommandKind =
+ (*TokenPtr == '@') ? tok::at_command : tok::backslash_command;
+ TokenPtr++;
+ if (TokenPtr == CommentEnd) {
+ formTextToken(T, TokenPtr);
+ return;
+ }
+ char C = *TokenPtr;
+ switch (C) {
+ default:
+ break;
+
+ case '\\': case '@': case '&': case '$':
+ case '#': case '<': case '>': case '%':
+ case '\"': case '.': case ':':
+ // This is one of \\ \@ \& \$ etc escape sequences.
TokenPtr++;
- if (TokenPtr == CommentEnd) {
- formTextToken(T, TokenPtr);
- return;
- }
- char C = *TokenPtr;
- switch (C) {
- default:
- break;
-
- case '\\': case '@': case '&': case '$':
- case '#': case '<': case '>': case '%':
- case '\"': case '.': case ':':
- // This is one of \\ \@ \& \$ etc escape sequences.
+ if (C == ':' && TokenPtr != CommentEnd && *TokenPtr == ':') {
+ // This is the \:: escape sequence.
TokenPtr++;
- if (C == ':' && TokenPtr != CommentEnd && *TokenPtr == ':') {
- // This is the \:: escape sequence.
- TokenPtr++;
- }
- StringRef UnescapedText(BufferPtr + 1, TokenPtr - (BufferPtr + 1));
- formTokenWithChars(T, TokenPtr, tok::text);
- T.setText(UnescapedText);
- return;
}
+ StringRef UnescapedText(BufferPtr + 1, TokenPtr - (BufferPtr + 1));
+ formTokenWithChars(T, TokenPtr, tok::text);
+ T.setText(UnescapedText);
+ return;
+ }
- // Don't make zero-length commands.
- if (!isCommandNameStartCharacter(*TokenPtr)) {
- formTextToken(T, TokenPtr);
- return;
- }
+ // Don't make zero-length commands.
+ if (!isCommandNameStartCharacter(*TokenPtr)) {
+ formTextToken(T, TokenPtr);
+ return;
+ }
- TokenPtr = skipCommandName(TokenPtr, CommentEnd);
- unsigned Length = TokenPtr - (BufferPtr + 1);
-
- // Hardcoded support for lexing LaTeX formula commands
- // \f$ \f[ \f] \f{ \f} as a single command.
- if (Length == 1 && TokenPtr[-1] == 'f' && TokenPtr != CommentEnd) {
- C = *TokenPtr;
- if (C == '$' || C == '[' || C == ']' || C == '{' || C == '}') {
- TokenPtr++;
- Length++;
- }
- }
+ TokenPtr = skipCommandName(TokenPtr, CommentEnd);
+ unsigned Length = TokenPtr - (BufferPtr + 1);
- StringRef CommandName(BufferPtr + 1, Length);
-
- const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName);
- if (!Info) {
- if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) {
- StringRef CorrectedName = Info->Name;
- SourceLocation Loc = getSourceLocation(BufferPtr);
- SourceLocation EndLoc = getSourceLocation(TokenPtr);
- SourceRange FullRange = SourceRange(Loc, EndLoc);
- SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc);
- Diag(Loc, diag::warn_correct_comment_command_name)
- << FullRange << CommandName << CorrectedName
- << FixItHint::CreateReplacement(CommandRange, CorrectedName);
- } else {
- formTokenWithChars(T, TokenPtr, tok::unknown_command);
- T.setUnknownCommandName(CommandName);
- Diag(T.getLocation(), diag::warn_unknown_comment_command_name)
- << SourceRange(T.getLocation(), T.getEndLocation());
- return;
- }
- }
- if (Info->IsVerbatimBlockCommand) {
- setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info);
- return;
- }
- if (Info->IsVerbatimLineCommand) {
- setupAndLexVerbatimLine(T, TokenPtr, Info);
- return;
+ // Hardcoded support for lexing LaTeX formula commands
+ // \f$ \f[ \f] \f{ \f} as a single command.
+ if (Length == 1 && TokenPtr[-1] == 'f' && TokenPtr != CommentEnd) {
+ C = *TokenPtr;
+ if (C == '$' || C == '[' || C == ']' || C == '{' || C == '}') {
+ TokenPtr++;
+ Length++;
}
- formTokenWithChars(T, TokenPtr, CommandKind);
- T.setCommandID(Info->getID());
- return;
}
- case '&':
- lexHTMLCharacterReference(T);
- return;
-
- case '<': {
- TokenPtr++;
- if (TokenPtr == CommentEnd) {
- formTextToken(T, TokenPtr);
+ StringRef CommandName(BufferPtr + 1, Length);
+
+ const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName);
+ if (!Info) {
+ if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) {
+ StringRef CorrectedName = Info->Name;
+ SourceLocation Loc = getSourceLocation(BufferPtr);
+ SourceLocation EndLoc = getSourceLocation(TokenPtr);
+ SourceRange FullRange = SourceRange(Loc, EndLoc);
+ SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc);
+ Diag(Loc, diag::warn_correct_comment_command_name)
+ << FullRange << CommandName << CorrectedName
+ << FixItHint::CreateReplacement(CommandRange, CorrectedName);
+ } else {
+ formTokenWithChars(T, TokenPtr, tok::unknown_command);
+ T.setUnknownCommandName(CommandName);
+ Diag(T.getLocation(), diag::warn_unknown_comment_command_name)
+ << SourceRange(T.getLocation(), T.getEndLocation());
return;
}
- const char C = *TokenPtr;
- if (isHTMLIdentifierStartingCharacter(C))
- setupAndLexHTMLStartTag(T);
- else if (C == '/')
- setupAndLexHTMLEndTag(T);
- else
- formTextToken(T, TokenPtr);
+ }
+ if (Info->IsVerbatimBlockCommand) {
+ setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info);
return;
}
-
- case '\n':
- case '\r':
- TokenPtr = skipNewline(TokenPtr, CommentEnd);
- formTokenWithChars(T, TokenPtr, tok::newline);
-
- if (CommentState == LCS_InsideCComment)
- skipLineStartingDecorations();
+ if (Info->IsVerbatimLineCommand) {
+ setupAndLexVerbatimLine(T, TokenPtr, Info);
return;
+ }
+ formTokenWithChars(T, TokenPtr, CommandKind);
+ T.setCommandID(Info->getID());
+ return;
+ }
- default: {
- size_t End = StringRef(TokenPtr, CommentEnd - TokenPtr).
- find_first_of("\n\r\\@&<");
- if (End != StringRef::npos)
- TokenPtr += End;
- else
- TokenPtr = CommentEnd;
+ case '&':
+ lexHTMLCharacterReference(T);
+ return;
+
+ case '<': {
+ TokenPtr++;
+ if (TokenPtr == CommentEnd) {
formTextToken(T, TokenPtr);
return;
}
+ const char C = *TokenPtr;
+ if (isHTMLIdentifierStartingCharacter(C))
+ setupAndLexHTMLStartTag(T);
+ else if (C == '/')
+ setupAndLexHTMLEndTag(T);
+ else
+ formTextToken(T, TokenPtr);
+ return;
}
+
+ default:
+ return HandleNonCommandToken();
}
}
@@ -727,14 +740,13 @@ void Lexer::lexHTMLEndTag(Token &T) {
}
Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags,
- const CommandTraits &Traits,
- SourceLocation FileLoc,
- const char *BufferStart, const char *BufferEnd):
- Allocator(Allocator), Diags(Diags), Traits(Traits),
- BufferStart(BufferStart), BufferEnd(BufferEnd),
- FileLoc(FileLoc), BufferPtr(BufferStart),
- CommentState(LCS_BeforeComment), State(LS_Normal) {
-}
+ const CommandTraits &Traits, SourceLocation FileLoc,
+ const char *BufferStart, const char *BufferEnd,
+ bool ParseCommands)
+ : Allocator(Allocator), Diags(Diags), Traits(Traits),
+ BufferStart(BufferStart), BufferEnd(BufferEnd), FileLoc(FileLoc),
+ BufferPtr(BufferStart), CommentState(LCS_BeforeComment), State(LS_Normal),
+ ParseCommands(ParseCommands) {}
void Lexer::lex(Token &T) {
again:
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
index 6c2019e1a72b..4bc98bf10765 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
@@ -215,7 +215,7 @@ void Sema::checkContainerDecl(const BlockCommandComment *Comment) {
<< Comment->getSourceRange();
}
-/// \brief Turn a string into the corresponding PassDirection or -1 if it's not
+/// Turn a string into the corresponding PassDirection or -1 if it's not
/// valid.
static int getParamPassDirection(StringRef Arg) {
return llvm::StringSwitch<int>(Arg)
diff --git a/contrib/llvm/tools/clang/lib/AST/ComparisonCategories.cpp b/contrib/llvm/tools/clang/lib/AST/ComparisonCategories.cpp
new file mode 100644
index 000000000000..87f51facc59b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ComparisonCategories.cpp
@@ -0,0 +1,211 @@
+//===- ComparisonCategories.cpp - Three Way Comparison Data -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Comparison Category enum and data types, which
+// store the types and expressions needed to support operator<=>
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ComparisonCategories.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang;
+
+bool ComparisonCategoryInfo::ValueInfo::hasValidIntValue() const {
+ assert(VD && "must have var decl");
+ if (!VD->checkInitIsICE())
+ return false;
+
+ // Before we attempt to get the value of the first field, ensure that we
+ // actually have one (and only one) field.
+ auto *Record = VD->getType()->getAsCXXRecordDecl();
+ if (std::distance(Record->field_begin(), Record->field_end()) != 1 ||
+ !Record->field_begin()->getType()->isIntegralOrEnumerationType())
+ return false;
+
+ return true;
+}
+
+/// Attempt to determine the integer value used to represent the comparison
+/// category result by evaluating the initializer for the specified VarDecl as
+/// a constant expression and retreiving the value of the class's first
+/// (and only) field.
+///
+/// Note: The STL types are expected to have the form:
+/// struct X { T value; };
+/// where T is an integral or enumeration type.
+llvm::APSInt ComparisonCategoryInfo::ValueInfo::getIntValue() const {
+ assert(hasValidIntValue() && "must have a valid value");
+ return VD->evaluateValue()->getStructField(0).getInt();
+}
+
+ComparisonCategoryInfo::ValueInfo *ComparisonCategoryInfo::lookupValueInfo(
+ ComparisonCategoryResult ValueKind) const {
+ // Check if we already have a cache entry for this value.
+ auto It = llvm::find_if(
+ Objects, [&](ValueInfo const &Info) { return Info.Kind == ValueKind; });
+ if (It != Objects.end())
+ return &(*It);
+
+ // We don't have a cached result. Lookup the variable declaration and create
+ // a new entry representing it.
+ DeclContextLookupResult Lookup = Record->getCanonicalDecl()->lookup(
+ &Ctx.Idents.get(ComparisonCategories::getResultString(ValueKind)));
+ if (Lookup.size() != 1 || !isa<VarDecl>(Lookup.front()))
+ return nullptr;
+ Objects.emplace_back(ValueKind, cast<VarDecl>(Lookup.front()));
+ return &Objects.back();
+}
+
+static const NamespaceDecl *lookupStdNamespace(const ASTContext &Ctx,
+ NamespaceDecl *&StdNS) {
+ if (!StdNS) {
+ DeclContextLookupResult Lookup =
+ Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std"));
+ if (Lookup.size() == 1)
+ StdNS = dyn_cast<NamespaceDecl>(Lookup.front());
+ }
+ return StdNS;
+}
+
+static CXXRecordDecl *lookupCXXRecordDecl(const ASTContext &Ctx,
+ const NamespaceDecl *StdNS,
+ ComparisonCategoryType Kind) {
+ StringRef Name = ComparisonCategories::getCategoryString(Kind);
+ DeclContextLookupResult Lookup = StdNS->lookup(&Ctx.Idents.get(Name));
+ if (Lookup.size() == 1)
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Lookup.front()))
+ return RD;
+ return nullptr;
+}
+
+const ComparisonCategoryInfo *
+ComparisonCategories::lookupInfo(ComparisonCategoryType Kind) const {
+ auto It = Data.find(static_cast<char>(Kind));
+ if (It != Data.end())
+ return &It->second;
+
+ if (const NamespaceDecl *NS = lookupStdNamespace(Ctx, StdNS))
+ if (CXXRecordDecl *RD = lookupCXXRecordDecl(Ctx, NS, Kind))
+ return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second;
+
+ return nullptr;
+}
+
+const ComparisonCategoryInfo *
+ComparisonCategories::lookupInfoForType(QualType Ty) const {
+ assert(!Ty.isNull() && "type must be non-null");
+ using CCT = ComparisonCategoryType;
+ auto *RD = Ty->getAsCXXRecordDecl();
+ if (!RD)
+ return nullptr;
+
+ // Check to see if we have information for the specified type cached.
+ const auto *CanonRD = RD->getCanonicalDecl();
+ for (auto &KV : Data) {
+ const ComparisonCategoryInfo &Info = KV.second;
+ if (CanonRD == Info.Record->getCanonicalDecl())
+ return &Info;
+ }
+
+ if (!RD->getEnclosingNamespaceContext()->isStdNamespace())
+ return nullptr;
+
+ // If not, check to see if the decl names a type in namespace std with a name
+ // matching one of the comparison category types.
+ for (unsigned I = static_cast<unsigned>(CCT::First),
+ End = static_cast<unsigned>(CCT::Last);
+ I <= End; ++I) {
+ CCT Kind = static_cast<CCT>(I);
+
+ // We've found the comparison category type. Build a new cache entry for
+ // it.
+ if (getCategoryString(Kind) == RD->getName())
+ return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second;
+ }
+
+ // We've found nothing. This isn't a comparison category type.
+ return nullptr;
+}
+
+const ComparisonCategoryInfo &ComparisonCategories::getInfoForType(QualType Ty) const {
+ const ComparisonCategoryInfo *Info = lookupInfoForType(Ty);
+ assert(Info && "info for comparison category not found");
+ return *Info;
+}
+
+QualType ComparisonCategoryInfo::getType() const {
+ assert(Record);
+ return QualType(Record->getTypeForDecl(), 0);
+}
+
+StringRef ComparisonCategories::getCategoryString(ComparisonCategoryType Kind) {
+ using CCKT = ComparisonCategoryType;
+ switch (Kind) {
+ case CCKT::WeakEquality:
+ return "weak_equality";
+ case CCKT::StrongEquality:
+ return "strong_equality";
+ case CCKT::PartialOrdering:
+ return "partial_ordering";
+ case CCKT::WeakOrdering:
+ return "weak_ordering";
+ case CCKT::StrongOrdering:
+ return "strong_ordering";
+ }
+ llvm_unreachable("unhandled cases in switch");
+}
+
+StringRef ComparisonCategories::getResultString(ComparisonCategoryResult Kind) {
+ using CCVT = ComparisonCategoryResult;
+ switch (Kind) {
+ case CCVT::Equal:
+ return "equal";
+ case CCVT::Nonequal:
+ return "nonequal";
+ case CCVT::Equivalent:
+ return "equivalent";
+ case CCVT::Nonequivalent:
+ return "nonequivalent";
+ case CCVT::Less:
+ return "less";
+ case CCVT::Greater:
+ return "greater";
+ case CCVT::Unordered:
+ return "unordered";
+ }
+ llvm_unreachable("unhandled case in switch");
+}
+
+std::vector<ComparisonCategoryResult>
+ComparisonCategories::getPossibleResultsForType(ComparisonCategoryType Type) {
+ using CCT = ComparisonCategoryType;
+ using CCR = ComparisonCategoryResult;
+ std::vector<CCR> Values;
+ Values.reserve(6);
+ Values.push_back(CCR::Equivalent);
+ bool IsStrong = (Type == CCT::StrongEquality || Type == CCT::StrongOrdering);
+ if (IsStrong)
+ Values.push_back(CCR::Equal);
+ if (Type == CCT::StrongOrdering || Type == CCT::WeakOrdering ||
+ Type == CCT::PartialOrdering) {
+ Values.push_back(CCR::Less);
+ Values.push_back(CCR::Greater);
+ } else {
+ Values.push_back(CCR::Nonequivalent);
+ if (IsStrong)
+ Values.push_back(CCR::Nonequal);
+ }
+ if (Type == CCT::PartialOrdering)
+ Values.push_back(CCR::Unordered);
+ return Values;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index 918466236bff..8030dd0c2f41 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -27,6 +27,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
@@ -76,6 +77,24 @@ Decl *clang::getPrimaryMergedDecl(Decl *D) {
return D->getASTContext().getPrimaryMergedDecl(D);
}
+void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
+ SourceLocation Loc = this->Loc;
+ if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+ if (Loc.isValid()) {
+ Loc.print(OS, Context.getSourceManager());
+ OS << ": ";
+ }
+ OS << Message;
+
+ if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
+ OS << " '";
+ ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
+ OS << "'";
+ }
+
+ OS << '\n';
+}
+
// Defined here so that it can be inlined into its direct callers.
bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
@@ -224,7 +243,7 @@ LinkageInfo LinkageComputer::getLVForType(const Type &T,
return getTypeLinkageAndVisibility(&T);
}
-/// \brief Get the most restrictive linkage for the types in the given
+/// 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.
LinkageInfo LinkageComputer::getLVForTemplateParameterList(
@@ -291,7 +310,7 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
return Ret;
}
-/// \brief Get the most restrictive linkage for the types and
+/// Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
///
/// Note that we don't take an LVComputationKind because we always
@@ -312,12 +331,12 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
LV.merge(getLVForType(*Arg.getAsType(), computation));
continue;
- case TemplateArgument::Declaration:
- if (const auto *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) {
- assert(!usesTypeVisibility(ND));
- LV.merge(getLVForDecl(ND, computation));
- }
+ case TemplateArgument::Declaration: {
+ const NamedDecl *ND = Arg.getAsDecl();
+ assert(!usesTypeVisibility(ND));
+ LV.merge(getLVForDecl(ND, computation));
continue;
+ }
case TemplateArgument::NullPtr:
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
@@ -614,7 +633,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// equivalent in C99)
// The C++ modules TS adds "non-exported" to this list.
if (Context.getLangOpts().CPlusPlus &&
- Var->getType().isConstQualified() &&
+ Var->getType().isConstQualified() &&
!Var->getType().isVolatileQualified() &&
!Var->isInline() &&
!isExportedFromModuleIntefaceUnit(Var)) {
@@ -1030,7 +1049,7 @@ bool NamedDecl::isLinkageValid() const {
ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
StringRef name = getName();
if (name.empty()) return SFF_None;
-
+
if (name.front() == 'C')
if (name == "CFStringCreateWithFormat" ||
name == "CFStringCreateWithFormatAndArguments" ||
@@ -1073,9 +1092,18 @@ getExplicitVisibilityAux(const NamedDecl *ND,
// If there wasn't explicit visibility there, and this is a
// specialization of a class template, check for visibility
// on the pattern.
- if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND))
- return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
- kind);
+ if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ // Walk all the template decl till this point to see if there are
+ // explicit visibility attributes.
+ const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
+ while (TD != nullptr) {
+ auto Vis = getVisibilityOf(TD, kind);
+ if (Vis != None)
+ return Vis;
+ TD = TD->getPreviousDecl();
+ }
+ return None;
+ }
// Use the most recent declaration.
if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
@@ -1310,7 +1338,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
return getExternalLinkageFor(D);
-
+
case Decl::CXXRecord: {
const auto *Record = cast<CXXRecordDecl>(D);
if (Record->isLambda()) {
@@ -1320,25 +1348,25 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
}
// This lambda has its linkage/visibility determined:
- // - either by the outermost lambda if that lambda has no mangling
- // number.
+ // - either by the outermost lambda if that lambda has no mangling
+ // number.
// - or by the parent of the outer most lambda
- // This prevents infinite recursion in settings such as nested lambdas
- // used in NSDMI's, for e.g.
+ // This prevents infinite recursion in settings such as nested lambdas
+ // used in NSDMI's, for e.g.
// struct L {
// int t{};
- // int t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
+ // int t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
// };
- const CXXRecordDecl *OuterMostLambda =
+ const CXXRecordDecl *OuterMostLambda =
getOutermostEnclosingLambda(Record);
if (!OuterMostLambda->getLambdaManglingNumber())
return getInternalLinkageFor(D);
-
+
return getLVForClosure(
OuterMostLambda->getDeclContext()->getRedeclContext(),
OuterMostLambda->getLambdaContextDecl(), computation);
}
-
+
break;
}
}
@@ -1346,7 +1374,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
// Handle linkage for namespace-scope names.
if (D->getDeclContext()->getRedeclContext()->isFileContext())
return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);
-
+
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
// class or enumeration of class scope, or an unnamed class or
@@ -1497,9 +1525,10 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
using ContextsTy = SmallVector<const DeclContext *, 8>;
ContextsTy Contexts;
- // Collect contexts.
- while (Ctx && isa<NamedDecl>(Ctx)) {
- Contexts.push_back(Ctx);
+ // Collect named contexts.
+ while (Ctx) {
+ if (isa<NamedDecl>(Ctx))
+ Contexts.push_back(Ctx);
Ctx = Ctx->getParent();
}
@@ -1689,7 +1718,7 @@ NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
bool NamedDecl::isCXXInstanceMember() const {
if (!isCXXClassMember())
return false;
-
+
const NamedDecl *D = this;
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -1909,7 +1938,7 @@ VarDecl::TLSKind VarDecl::getTLSKind() const {
SourceRange VarDecl::getSourceRange() const {
if (const Expr *Init = getInit()) {
SourceLocation InitEnd = Init->getLocEnd();
- // If Init is implicit, ignore its source range and fallback on
+ // If Init is implicit, ignore its source range and fallback on
// DeclaratorDecl::getSourceRange() to handle postfix elements.
if (InitEnd.isValid() && InitEnd != getLocation())
return SourceRange(getOuterLocStart(), InitEnd);
@@ -2145,11 +2174,11 @@ bool VarDecl::isOutOfLine() const {
return false;
// If this static data member was instantiated from a static data member of
- // a class template, check whether that static data member was defined
+ // a class template, check whether that static data member was defined
// out-of-line.
if (VarDecl *VD = getInstantiatedFromStaticDataMember())
return VD->isOutOfLine();
-
+
return false;
}
@@ -2403,6 +2432,23 @@ void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
getASTContext().setTemplateOrSpecializationInfo(this, Template);
}
+bool VarDecl::isKnownToBeDefined() const {
+ const auto &LangOpts = getASTContext().getLangOpts();
+ // In CUDA mode without relocatable device code, variables of form 'extern
+ // __shared__ Foo foo[]' are pointers to the base of the GPU core's shared
+ // memory pool. These are never undefined variables, even if they appear
+ // inside of an anon namespace or static function.
+ //
+ // With CUDA relocatable device code enabled, these variables don't get
+ // special handling; they're treated like regular extern variables.
+ if (LangOpts.CUDA && !LangOpts.CUDARelocatableDeviceCode &&
+ hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
+ isa<IncompleteArrayType>(getType()))
+ return true;
+
+ return hasDefinition();
+}
+
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
if (isStaticDataMember())
// FIXME: Remove ?
@@ -2827,6 +2873,14 @@ bool FunctionDecl::isNoReturn() const {
return false;
}
+bool FunctionDecl::isCPUDispatchMultiVersion() const {
+ return isMultiVersion() && hasAttr<CPUDispatchAttr>();
+}
+
+bool FunctionDecl::isCPUSpecificMultiVersion() const {
+ return isMultiVersion() && hasAttr<CPUSpecificAttr>();
+}
+
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
redeclarable_base::setPreviousDecl(PrevDecl);
@@ -2837,14 +2891,14 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
FunTmpl->setPreviousDecl(PrevFunTmpl);
}
-
+
if (PrevDecl && PrevDecl->IsInline)
IsInline = true;
}
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
-/// \brief Returns a value indicating whether this function
+/// Returns a value indicating whether this function
/// corresponds to a builtin function.
///
/// The function corresponds to a built-in function if it is
@@ -2901,6 +2955,13 @@ unsigned FunctionDecl::getBuiltinID() const {
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return 0;
+ // CUDA does not have device-side standard library. printf and malloc are the
+ // only special cases that are supported by device-side runtime.
+ if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() &&
+ !hasAttr<CUDAHostAttr>() &&
+ !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
+ return 0;
+
return BuiltinID;
}
@@ -2939,7 +3000,7 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
return NumRequiredArgs;
}
-/// \brief The combination of the extern and inline keywords under MSVC forces
+/// The combination of the extern and inline keywords under MSVC forces
/// the function to be required.
///
/// Note: This function assumes that we will only get called when isInlined()
@@ -2982,13 +3043,13 @@ static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
if (Redecl->isImplicit())
return false;
- if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
+ if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
return true; // Not an inline definition
return false;
}
-/// \brief For a function declaration in C or C++, determine whether this
+/// For a function declaration in C or C++, determine whether this
/// declaration causes the definition to be externally visible.
///
/// For instance, this determines if adding the current declaration to the set
@@ -3027,7 +3088,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
if (!Prev->isInlineSpecified() ||
Prev->getStorageClass() != SC_Extern)
return false;
- } else if (Prev->isInlineSpecified() &&
+ } else if (Prev->isInlineSpecified() &&
Prev->getStorageClass() != SC_Extern) {
return false;
}
@@ -3039,8 +3100,8 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
return false;
// C99 6.7.4p6:
- // [...] If all of the file scope declarations for a function in a
- // translation unit include the inline function specifier without extern,
+ // [...] If all of the file scope declarations for a function in a
+ // translation unit include the inline function specifier without extern,
// then the definition in that translation unit is an inline definition.
if (isInlineSpecified() && getStorageClass() != SC_Extern)
return false;
@@ -3088,12 +3149,9 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
const Attr *FunctionDecl::getUnusedResultAttr() const {
QualType RetType = getReturnType();
- if (RetType->isRecordType()) {
- if (const auto *Ret =
- dyn_cast_or_null<RecordDecl>(RetType->getAsTagDecl())) {
- if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>())
- return R;
- }
+ if (const auto *Ret = RetType->getAsRecordDecl()) {
+ if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>())
+ return R;
} else if (const auto *ET = RetType->getAs<EnumType>()) {
if (const EnumDecl *ED = ET->getDecl()) {
if (const auto *R = ED->getAttr<WarnUnusedResultAttr>())
@@ -3103,7 +3161,7 @@ const Attr *FunctionDecl::getUnusedResultAttr() const {
return getAttr<WarnUnusedResultAttr>();
}
-/// \brief For an inline function definition in C, or for a gnu_inline function
+/// For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
/// Inline function definitions are always available for inlining optimizations.
@@ -3116,16 +3174,16 @@ const Attr *FunctionDecl::getUnusedResultAttr() const {
/// inline definition becomes externally visible (C99 6.7.4p6).
///
/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
-/// definition, we use the GNU semantics for inline, which are nearly the
-/// opposite of C99 semantics. In particular, "inline" by itself will create
-/// an externally visible symbol, but "extern inline" will not create an
+/// definition, we use the GNU semantics for inline, which are nearly the
+/// opposite of C99 semantics. In particular, "inline" by itself will create
+/// an externally visible symbol, but "extern inline" will not create an
/// externally visible symbol.
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
assert((doesThisDeclarationHaveABody() || willHaveBody()) &&
"Must be a function definition");
assert(isInlined() && "Function must be inline");
ASTContext &Context = getASTContext();
-
+
if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
// Note: If you change the logic here, please change
// doesDeclarationForceExternallyVisibleDefinition as well.
@@ -3135,15 +3193,15 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
// externally visible.
if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
return true;
-
+
// If any declaration is 'inline' but not 'extern', then this definition
// is externally visible.
for (auto Redecl : redecls()) {
- if (Redecl->isInlineSpecified() &&
+ if (Redecl->isInlineSpecified() &&
Redecl->getStorageClass() != SC_Extern)
return true;
- }
-
+ }
+
return false;
}
@@ -3152,17 +3210,17 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
"should not use C inline rules in C++");
// C99 6.7.4p6:
- // [...] If all of the file scope declarations for a function in a
- // translation unit include the inline function specifier without extern,
+ // [...] If all of the file scope declarations for a function in a
+ // translation unit include the inline function specifier without extern,
// then the definition in that translation unit is an inline definition.
for (auto Redecl : redecls()) {
if (RedeclForcesDefC99(Redecl))
return true;
}
-
+
// C99 6.7.4p6:
- // An inline definition does not provide an external definition for the
- // function, and does not forbid an external definition in another
+ // An inline definition does not provide an external definition for the
+ // function, and does not forbid an external definition in another
// translation unit.
return false;
}
@@ -3212,13 +3270,13 @@ MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>();
}
-void
+void
FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
FunctionDecl *FD,
TemplateSpecializationKind TSK) {
- assert(TemplateOrSpecialization.isNull() &&
+ assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
- MemberSpecializationInfo *Info
+ MemberSpecializationInfo *Info
= new (C) MemberSpecializationInfo(FD, TSK);
TemplateOrSpecialization = Info;
}
@@ -3235,12 +3293,12 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
// If the function is invalid, it can't be implicitly instantiated.
if (isInvalidDecl())
return false;
-
+
switch (getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitInstantiationDefinition:
return false;
-
+
case TSK_ImplicitInstantiation:
return true;
@@ -3259,12 +3317,12 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
bool HasPattern = false;
if (PatternDecl)
HasPattern = PatternDecl->hasBody(PatternDecl);
-
+
// C++0x [temp.explicit]p9:
// Except for inline functions, other explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
- // to which they refer.
- if (!HasPattern || !PatternDecl)
+ // to which they refer.
+ if (!HasPattern || !PatternDecl)
return true;
return PatternDecl->isInlined();
@@ -3274,7 +3332,7 @@ bool FunctionDecl::isTemplateInstantiation() const {
switch (getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
- return false;
+ return false;
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
@@ -3282,7 +3340,7 @@ bool FunctionDecl::isTemplateInstantiation() const {
}
llvm_unreachable("All TSK values handled.");
}
-
+
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
// Handle class scope explicit specialization special case.
if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
@@ -3291,13 +3349,13 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
return nullptr;
}
- // If this is a generic lambda call operator specialization, its
+ // If this is a generic lambda call operator specialization, its
// instantiation pattern is always its primary template's pattern
- // even if its primary template was instantiated from another
+ // even if its primary template was instantiated from another
// member template (which happens with nested generic lambdas).
- // Since a lambda's call operator's body is transformed eagerly,
- // we don't have to go hunting for a prototype definition template
- // (i.e. instantiated-from-member-template) to use as an instantiation
+ // Since a lambda's call operator's body is transformed eagerly,
+ // we don't have to go hunting for a prototype definition template
+ // (i.e. instantiated-from-member-template) to use as an instantiation
// pattern.
if (isGenericLambdaCallOperatorSpecialization(
@@ -3316,7 +3374,7 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
}
return getDefinitionOrSelf(Primary->getTemplatedDecl());
- }
+ }
if (auto *MFD = getInstantiatedFromMemberFunction())
return getDefinitionOrSelf(MFD);
@@ -3371,7 +3429,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
TemplateSpecializationKind TSK,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation PointOfInstantiation) {
- assert(TSK != TSK_Undeclared &&
+ assert(TSK != TSK_Undeclared &&
"Must specify the type of function template specialization");
FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
@@ -3439,7 +3497,7 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
if (MSInfo)
return MSInfo->getTemplateSpecializationKind();
-
+
return TSK_Undeclared;
}
@@ -3479,22 +3537,22 @@ SourceLocation FunctionDecl::getPointOfInstantiation() const {
else if (MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
return MSInfo->getPointOfInstantiation();
-
+
return SourceLocation();
}
bool FunctionDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
-
- // If this function was instantiated from a member function of a
+
+ // If this function was instantiated from a member function of a
// class template, check whether that member function was defined out-of-line.
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
const FunctionDecl *Definition;
if (FD->hasBody(Definition))
return Definition->isOutOfLine();
}
-
+
// If this function was instantiated from a function template,
// check whether that function template was defined out-of-line.
if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
@@ -3502,7 +3560,7 @@ bool FunctionDecl::isOutOfLine() const {
if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
return Definition->isOutOfLine();
}
-
+
return false;
}
@@ -3515,7 +3573,7 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
if (!FnInfo)
return 0;
-
+
// Builtin handling.
switch (getBuiltinID()) {
case Builtin::BI__builtin_memset:
@@ -3605,16 +3663,19 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
return 0;
}
+unsigned FunctionDecl::getODRHash() const {
+ assert(HasODRHash);
+ return ODRHash;
+}
+
unsigned FunctionDecl::getODRHash() {
if (HasODRHash)
return ODRHash;
- if (FunctionDecl *Definition = getDefinition()) {
- if (Definition != this) {
- HasODRHash = true;
- ODRHash = Definition->getODRHash();
- return ODRHash;
- }
+ if (auto *FT = getInstantiatedFromMemberFunction()) {
+ HasODRHash = true;
+ ODRHash = FT->getODRHash();
+ return ODRHash;
}
class ODRHash Hash;
@@ -3658,6 +3719,11 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
}
+bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
+ return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
+ getBitWidthValue(Ctx) == 0;
+}
+
unsigned FieldDecl::getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical != this)
@@ -3904,6 +3970,17 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
}
+unsigned EnumDecl::getODRHash() {
+ if (HasODRHash)
+ return ODRHash;
+
+ class ODRHash Hash;
+ Hash.AddEnumDecl(this);
+ HasODRHash = true;
+ ODRHash = Hash.CalculateHash();
+ return ODRHash;
+}
+
//===----------------------------------------------------------------------===//
// RecordDecl Implementation
//===----------------------------------------------------------------------===//
@@ -3915,7 +3992,10 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
: TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc),
HasFlexibleArrayMember(false), AnonymousStructOrUnion(false),
HasObjectMember(false), HasVolatileMember(false),
- LoadedFieldsFromExternalStorage(false) {
+ LoadedFieldsFromExternalStorage(false),
+ NonTrivialToPrimitiveDefaultInitialize(false),
+ NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
+ ParamDestroyedInCallee(false), ArgPassingRestrictions(APK_CanPassInRegs) {
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
@@ -4365,9 +4445,7 @@ bool TypedefNameDecl::isTransparentTagSlow() const {
};
bool isTransparent = determineIsTransparent();
- CacheIsTransparentTag = 1;
- if (isTransparent)
- CacheIsTransparentTag |= 0x2;
+ MaybeModedTInfo.setInt((isTransparent << 1) | 1);
return isTransparent;
}
@@ -4433,7 +4511,7 @@ EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
// ImportDecl Implementation
//===----------------------------------------------------------------------===//
-/// \brief Retrieve the number of module identifiers needed to name the given
+/// Retrieve the number of module identifiers needed to name the given
/// module.
static unsigned getNumModuleIdentifiers(Module *Mod) {
unsigned Result = 1;
@@ -4444,7 +4522,7 @@ static unsigned getNumModuleIdentifiers(Module *Mod) {
return Result;
}
-ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
+ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs)
: Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true) {
@@ -4454,7 +4532,7 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
StoredLocs);
}
-ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
+ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported, SourceLocation EndLoc)
: 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 d427c79c44ab..700ddd389ddd 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -34,7 +34,6 @@
#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"
@@ -42,6 +41,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -101,7 +101,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
// padding at the start if required.
size_t ExtraAlign =
llvm::OffsetToAlignment(sizeof(Module *), alignof(Decl));
- char *Buffer = reinterpret_cast<char *>(
+ auto *Buffer = reinterpret_cast<char *>(
::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
Buffer += ExtraAlign;
auto *ParentModule =
@@ -139,14 +139,14 @@ void Decl::setInvalidDecl(bool Invalid) {
if (!isa<ParmVarDecl>(this)) {
// Defensive maneuver for ill-formed code: we're likely not to make it to
// a point where we set the access specifier, so default it to "public"
- // to avoid triggering asserts elsewhere in the front end.
+ // to avoid triggering asserts elsewhere in the front end.
setAccess(AS_public);
}
// Marking a DecompositionDecl as invalid implies all the child BindingDecl's
// are invalid too.
- if (DecompositionDecl *DD = dyn_cast<DecompositionDecl>(this)) {
- for (BindingDecl *Binding : DD->bindings()) {
+ if (auto *DD = dyn_cast<DecompositionDecl>(this)) {
+ for (auto *Binding : DD->bindings()) {
Binding->setInvalidDecl();
}
}
@@ -199,28 +199,26 @@ void Decl::add(Kind k) {
}
bool Decl::isTemplateParameterPack() const {
- if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(this))
return TTP->isParameterPack();
- if (const NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(this))
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(this))
return NTTP->isParameterPack();
- if (const TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(this))
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(this))
return TTP->isParameterPack();
return false;
}
bool Decl::isParameterPack() const {
- if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(this))
+ if (const auto *Parm = dyn_cast<ParmVarDecl>(this))
return Parm->isParameterPack();
-
+
return isTemplateParameterPack();
}
FunctionDecl *Decl::getAsFunction() {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
+ if (auto *FD = dyn_cast<FunctionDecl>(this))
return FD;
- if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(this))
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
return FTD->getTemplatedDecl();
return nullptr;
}
@@ -255,7 +253,7 @@ bool Decl::isTemplated() const {
const DeclContext *Decl::getParentFunctionOrMethod() const {
for (const DeclContext *DC = getDeclContext();
- DC && !DC->isTranslationUnit() && !DC->isNamespace();
+ DC && !DC->isTranslationUnit() && !DC->isNamespace();
DC = DC->getParent())
if (DC->isFunctionOrMethod())
return DC;
@@ -279,7 +277,7 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const {
OS << Message;
- if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) {
+ if (const auto *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) {
OS << " '";
DN->printQualifiedName(OS);
OS << '\'';
@@ -327,7 +325,7 @@ void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
if (SemaDC == LexicalDC) {
DeclCtx = SemaDC;
} else {
- Decl::MultipleDC *MDC = new (Ctx) Decl::MultipleDC();
+ auto *MDC = new (Ctx) Decl::MultipleDC();
MDC->SemanticDC = SemaDC;
MDC->LexicalDC = LexicalDC;
DeclCtx = MDC;
@@ -348,7 +346,7 @@ bool Decl::isLexicallyWithinFunctionOrMethod() const {
bool Decl::isInAnonymousNamespace() const {
for (const DeclContext *DC = getDeclContext(); DC; DC = DC->getParent()) {
- if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
+ if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
if (ND->isAnonymousNamespace())
return true;
}
@@ -361,7 +359,7 @@ bool Decl::isInStdNamespace() const {
}
TranslationUnitDecl *Decl::getTranslationUnitDecl() {
- if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
+ if (auto *TUD = dyn_cast<TranslationUnitDecl>(this))
return TUD;
DeclContext *DC = getDeclContext();
@@ -421,16 +419,16 @@ void Decl::markUsed(ASTContext &C) {
setIsUsed();
}
-bool Decl::isReferenced() const {
+bool Decl::isReferenced() const {
if (Referenced)
return true;
// Check redeclarations.
- for (auto I : redecls())
+ for (const auto *I : redecls())
if (I->Referenced)
return true;
- return false;
+ return false;
}
bool Decl::isExported() const {
@@ -451,11 +449,11 @@ bool Decl::isExported() const {
ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const {
const Decl *Definition = nullptr;
- if (auto ID = dyn_cast<ObjCInterfaceDecl>(this)) {
+ if (auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
Definition = ID->getDefinition();
- } else if (auto PD = dyn_cast<ObjCProtocolDecl>(this)) {
+ } else if (auto *PD = dyn_cast<ObjCProtocolDecl>(this)) {
Definition = PD->getDefinition();
- } else if (auto TD = dyn_cast<TagDecl>(this)) {
+ } else if (auto *TD = dyn_cast<TagDecl>(this)) {
Definition = TD->getDefinition();
}
if (!Definition)
@@ -475,9 +473,9 @@ bool Decl::hasDefiningAttr() const {
}
const Attr *Decl::getDefiningAttr() const {
- if (AliasAttr *AA = getAttr<AliasAttr>())
+ if (auto *AA = getAttr<AliasAttr>())
return AA;
- if (IFuncAttr *IFA = getAttr<IFuncAttr>())
+ if (auto *IFA = getAttr<IFuncAttr>())
return IFA;
return nullptr;
}
@@ -495,7 +493,7 @@ static StringRef getRealizedPlatform(const AvailabilityAttr *A,
return RealizedPlatform;
}
-/// \brief Determine the availability of the given declaration based on
+/// Determine the availability of the given declaration based on
/// the target platform.
///
/// When it returns an availability result other than \c AR_Available,
@@ -532,13 +530,13 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
HintMessage = " - ";
HintMessage += A->getMessage();
}
-
+
// Make sure that this declaration has not been marked 'unavailable'.
if (A->getUnavailable()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
- Out << "not available on " << PrettyPlatformName
+ Out << "not available on " << PrettyPlatformName
<< HintMessage;
}
@@ -546,14 +544,13 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
}
// Make sure that this declaration has already been introduced.
- if (!A->getIntroduced().empty() &&
+ if (!A->getIntroduced().empty() &&
EnclosingVersion < A->getIntroduced()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTI(A->getIntroduced());
- VTI.UseDotAsSeparator();
- Out << "introduced in " << PrettyPlatformName << ' '
+ Out << "introduced in " << PrettyPlatformName << ' '
<< VTI << HintMessage;
}
@@ -566,11 +563,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTO(A->getObsoleted());
- VTO.UseDotAsSeparator();
- Out << "obsoleted in " << PrettyPlatformName << ' '
+ Out << "obsoleted in " << PrettyPlatformName << ' '
<< VTO << HintMessage;
}
-
+
return AR_Unavailable;
}
@@ -580,11 +576,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTD(A->getDeprecated());
- VTD.UseDotAsSeparator();
Out << "first deprecated in " << PrettyPlatformName << ' '
<< VTD << HintMessage;
}
-
+
return AR_Deprecated;
}
@@ -592,9 +587,11 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
}
AvailabilityResult Decl::getAvailability(std::string *Message,
- VersionTuple EnclosingVersion) const {
+ VersionTuple EnclosingVersion,
+ StringRef *RealizedPlatform) const {
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
- return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion);
+ return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion,
+ RealizedPlatform);
AvailabilityResult Result = AR_Available;
std::string ResultMessage;
@@ -621,8 +618,11 @@ AvailabilityResult Decl::getAvailability(std::string *Message,
AvailabilityResult AR = CheckAvailability(getASTContext(), Availability,
Message, EnclosingVersion);
- if (AR == AR_Unavailable)
+ if (AR == AR_Unavailable) {
+ if (RealizedPlatform)
+ *RealizedPlatform = Availability->getPlatform()->getName();
return AR_Unavailable;
+ }
if (AR > Result) {
Result = AR;
@@ -649,14 +649,14 @@ VersionTuple Decl::getVersionIntroduced() const {
return Availability->getIntroduced();
}
}
- return VersionTuple();
+ return {};
}
bool Decl::canBeWeakImported(bool &IsDefinition) const {
IsDefinition = false;
// Variables, if they aren't definitions.
- if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
+ if (const auto *Var = dyn_cast<VarDecl>(this)) {
if (Var->isThisDeclarationADefinition()) {
IsDefinition = true;
return false;
@@ -664,7 +664,7 @@ bool Decl::canBeWeakImported(bool &IsDefinition) const {
return true;
// Functions, if they aren't definitions.
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
+ } else if (const auto *FD = dyn_cast<FunctionDecl>(this)) {
if (FD->hasBody()) {
IsDefinition = true;
return false;
@@ -847,14 +847,14 @@ Decl *Decl::castFromDeclContext (const DeclContext *D) {
#define DECL(NAME, BASE)
#define DECL_CONTEXT(NAME) \
case Decl::NAME: \
- return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D));
+ return static_cast<NAME##Decl *>(const_cast<DeclContext *>(D));
#define DECL_CONTEXT_BASE(NAME)
#include "clang/AST/DeclNodes.inc"
default:
#define DECL(NAME, BASE)
#define DECL_CONTEXT_BASE(NAME) \
if (DK >= first##NAME && DK <= last##NAME) \
- return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D));
+ return static_cast<NAME##Decl *>(const_cast<DeclContext *>(D));
#include "clang/AST/DeclNodes.inc"
llvm_unreachable("a decl that inherits DeclContext isn't handled");
}
@@ -866,14 +866,14 @@ DeclContext *Decl::castToDeclContext(const Decl *D) {
#define DECL(NAME, BASE)
#define DECL_CONTEXT(NAME) \
case Decl::NAME: \
- return static_cast<NAME##Decl*>(const_cast<Decl*>(D));
+ return static_cast<NAME##Decl *>(const_cast<Decl *>(D));
#define DECL_CONTEXT_BASE(NAME)
#include "clang/AST/DeclNodes.inc"
default:
#define DECL(NAME, BASE)
#define DECL_CONTEXT_BASE(NAME) \
if (DK >= first##NAME && DK <= last##NAME) \
- return static_cast<NAME##Decl*>(const_cast<Decl*>(D));
+ return static_cast<NAME##Decl *>(const_cast<Decl *>(D));
#include "clang/AST/DeclNodes.inc"
llvm_unreachable("a decl that inherits DeclContext isn't handled");
}
@@ -882,17 +882,17 @@ DeclContext *Decl::castToDeclContext(const Decl *D) {
SourceLocation Decl::getBodyRBrace() const {
// Special handling of FunctionDecl to avoid de-serializing the body from PCH.
// FunctionDecl stores EndRangeLoc for this purpose.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(this)) {
const FunctionDecl *Definition;
if (FD->hasBody(Definition))
return Definition->getSourceRange().getEnd();
- return SourceLocation();
+ return {};
}
if (Stmt *Body = getBody())
return Body->getSourceRange().getEnd();
- return SourceLocation();
+ return {};
}
bool Decl::AccessDeclContextSanity() const {
@@ -932,9 +932,9 @@ static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }
const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
QualType Ty;
- if (const ValueDecl *D = dyn_cast<ValueDecl>(this))
+ if (const auto *D = dyn_cast<ValueDecl>(this))
Ty = D->getType();
- else if (const TypedefNameDecl *D = dyn_cast<TypedefNameDecl>(this))
+ else if (const auto *D = dyn_cast<TypedefNameDecl>(this))
Ty = D->getUnderlyingType();
else
return nullptr;
@@ -951,22 +951,21 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
/// code context that is not a closure (a lambda, block, etc.).
template <class T> static Decl *getNonClosureContext(T *D) {
if (getKind(D) == Decl::CXXMethod) {
- CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
+ auto *MD = cast<CXXMethodDecl>(D);
if (MD->getOverloadedOperator() == OO_Call &&
MD->getParent()->isLambda())
return getNonClosureContext(MD->getParent()->getParent());
return MD;
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ } else if (auto *FD = dyn_cast<FunctionDecl>(D))
return FD;
- } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ else if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD;
- } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ else if (auto *BD = dyn_cast<BlockDecl>(D))
return getNonClosureContext(BD->getParent());
- } else if (CapturedDecl *CD = dyn_cast<CapturedDecl>(D)) {
+ else if (auto *CD = dyn_cast<CapturedDecl>(D))
return getNonClosureContext(CD->getParent());
- } else {
+ else
return nullptr;
- }
}
Decl *Decl::getNonClosureContext() {
@@ -1001,7 +1000,7 @@ bool DeclContext::classof(const Decl *D) {
DeclContext::~DeclContext() = default;
-/// \brief Find the parent context of this context that will be
+/// Find the parent context of this context that will be
/// used for unqualified name lookup.
///
/// Generally, the parent lookup context is the semantic context. However, for
@@ -1013,7 +1012,7 @@ DeclContext *DeclContext::getLookupParent() {
if (getParent()->getRedeclContext()->isFileContext() &&
getLexicalParent()->getRedeclContext()->isRecord())
return getLexicalParent();
-
+
return getParent();
}
@@ -1026,7 +1025,7 @@ bool DeclContext::isStdNamespace() const {
if (!isNamespace())
return false;
- const NamespaceDecl *ND = cast<NamespaceDecl>(this);
+ const auto *ND = cast<NamespaceDecl>(this);
if (ND->isInline()) {
return ND->getParent()->isStdNamespace();
}
@@ -1045,15 +1044,15 @@ bool DeclContext::isDependentContext() const {
if (isa<ClassTemplatePartialSpecializationDecl>(this))
return true;
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) {
+ if (const auto *Record = dyn_cast<CXXRecordDecl>(this)) {
if (Record->getDescribedClassTemplate())
return true;
-
+
if (Record->isDependentLambda())
return true;
}
-
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
+
+ if (const auto *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getDescribedFunctionTemplate())
return true;
@@ -1132,21 +1131,21 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::Namespace:
// The original namespace is our primary context.
- return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
+ return static_cast<NamespaceDecl *>(this)->getOriginalNamespace();
case Decl::ObjCMethod:
return this;
case Decl::ObjCInterface:
- if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition())
+ if (auto *Def = cast<ObjCInterfaceDecl>(this)->getDefinition())
return Def;
return this;
-
+
case Decl::ObjCProtocol:
- if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(this)->getDefinition())
+ if (auto *Def = cast<ObjCProtocolDecl>(this)->getDefinition())
return Def;
return this;
-
+
case Decl::ObjCCategory:
return this;
@@ -1158,12 +1157,12 @@ DeclContext *DeclContext::getPrimaryContext() {
if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) {
// If this is a tag type that has a definition or is currently
// being defined, that definition is our primary context.
- TagDecl *Tag = cast<TagDecl>(this);
+ auto *Tag = cast<TagDecl>(this);
if (TagDecl *Def = Tag->getDefinition())
return Def;
- if (const TagType *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) {
+ if (const auto *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) {
// Note, TagType::getDecl returns the (partial) definition one exists.
TagDecl *PossiblePartialDef = TagTy->getDecl();
if (PossiblePartialDef->isBeingDefined())
@@ -1181,34 +1180,33 @@ DeclContext *DeclContext::getPrimaryContext() {
}
}
-void
+void
DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
Contexts.clear();
-
+
if (DeclKind != Decl::Namespace) {
Contexts.push_back(this);
return;
}
-
- NamespaceDecl *Self = static_cast<NamespaceDecl *>(this);
+
+ auto *Self = static_cast<NamespaceDecl *>(this);
for (NamespaceDecl *N = Self->getMostRecentDecl(); N;
N = N->getPreviousDecl())
Contexts.push_back(N);
-
+
std::reverse(Contexts.begin(), Contexts.end());
}
std::pair<Decl *, Decl *>
-DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
+DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls,
bool FieldsAlreadyLoaded) {
// Build up a chain of declarations via the Decl::NextInContextAndBits field.
Decl *FirstNewDecl = nullptr;
Decl *PrevDecl = nullptr;
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- if (FieldsAlreadyLoaded && isa<FieldDecl>(Decls[I]))
+ for (auto *D : Decls) {
+ if (FieldsAlreadyLoaded && isa<FieldDecl>(D))
continue;
- Decl *D = Decls[I];
if (PrevDecl)
PrevDecl->NextInContextAndBits.setPointer(D);
else
@@ -1220,7 +1218,7 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
return std::make_pair(FirstNewDecl, PrevDecl);
}
-/// \brief We have just acquired external visible storage, and we already have
+/// We have just acquired external visible storage, and we already have
/// built a lookup map. For every name in the map, pull in the new names from
/// the external storage.
void DeclContext::reconcileExternalVisibleStorage() const {
@@ -1231,7 +1229,7 @@ void DeclContext::reconcileExternalVisibleStorage() const {
Lookup.second.setHasExternalDecls();
}
-/// \brief Load the declarations within this lexical storage from an
+/// Load the declarations within this lexical storage from an
/// external source.
/// \return \c true if any declarations were added.
bool
@@ -1253,9 +1251,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// We may have already loaded just the fields of this record, in which case
// we need to ignore them.
bool FieldsAlreadyLoaded = false;
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
+ if (const auto *RD = dyn_cast<RecordDecl>(this))
FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage;
-
+
// Splice the newly-read declarations into the beginning of the list
// of declarations.
Decl *ExternalFirst, *ExternalLast;
@@ -1320,12 +1318,11 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
}
} else {
// Convert the array to a StoredDeclsList.
- for (ArrayRef<NamedDecl*>::iterator
- I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+ for (auto *D : Decls) {
if (List.isNull())
- List.setOnlyValue(*I);
+ List.setOnlyValue(D);
else
- List.AddSubsequentDecl(*I);
+ List.AddSubsequentDecl(D);
}
}
@@ -1350,6 +1347,38 @@ bool DeclContext::containsDecl(Decl *D) const {
(D->NextInContextAndBits.getPointer() || D == LastDecl));
}
+bool DeclContext::containsDeclAndLoad(Decl *D) const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage();
+ return containsDecl(D);
+}
+
+/// shouldBeHidden - Determine whether a declaration which was declared
+/// within its semantic context should be invisible to qualified name lookup.
+static bool shouldBeHidden(NamedDecl *D) {
+ // Skip unnamed declarations.
+ if (!D->getDeclName())
+ return true;
+
+ // Skip entities that can't be found by name lookup into a particular
+ // context.
+ if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
+ D->isTemplateParameter())
+ return true;
+
+ // Skip template specializations.
+ // FIXME: This feels like a hack. Should DeclarationName support
+ // template-ids, or is there a better way to keep specializations
+ // from being visible?
+ if (isa<ClassTemplateSpecializationDecl>(D))
+ return true;
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isFunctionTemplateSpecialization())
+ return true;
+
+ return false;
+}
+
void DeclContext::removeDecl(Decl *D) {
assert(D->getLexicalDeclContext() == this &&
"decl being removed from non-lexical context");
@@ -1372,16 +1401,22 @@ void DeclContext::removeDecl(Decl *D) {
}
}
}
-
+
// Mark that D is no longer in the decl chain.
D->NextInContextAndBits.setPointer(nullptr);
// Remove D from the lookup table if necessary.
if (isa<NamedDecl>(D)) {
- NamedDecl *ND = cast<NamedDecl>(D);
+ auto *ND = cast<NamedDecl>(D);
+
+ // Do not try to remove the declaration if that is invisible to qualified
+ // lookup. E.g. template specializations are skipped.
+ if (shouldBeHidden(ND))
+ return;
// Remove only decls that have a name
- if (!ND->getDeclName()) return;
+ if (!ND->getDeclName())
+ return;
auto *DC = D->getDeclContext();
do {
@@ -1411,13 +1446,13 @@ void DeclContext::addHiddenDecl(Decl *D) {
// Notify a C++ record declaration that we've added a member, so it can
// update its class-specific state.
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
+ if (auto *Record = dyn_cast<CXXRecordDecl>(this))
Record->addedMember(D);
// If this is a newly-created (not de-serialized) import declaration, wire
// it in to the list of local import declarations.
if (!D->isFromASTFile()) {
- if (ImportDecl *Import = dyn_cast<ImportDecl>(D))
+ if (auto *Import = dyn_cast<ImportDecl>(D))
D->getASTContext().addedLocalImportDecl(Import);
}
}
@@ -1425,7 +1460,7 @@ void DeclContext::addHiddenDecl(Decl *D) {
void DeclContext::addDecl(Decl *D) {
addHiddenDecl(D);
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (auto *ND = dyn_cast<NamedDecl>(D))
ND->getDeclContext()->getPrimaryContext()->
makeDeclVisibleInContextWithFlags(ND, false, true);
}
@@ -1433,37 +1468,11 @@ void DeclContext::addDecl(Decl *D) {
void DeclContext::addDeclInternal(Decl *D) {
addHiddenDecl(D);
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (auto *ND = dyn_cast<NamedDecl>(D))
ND->getDeclContext()->getPrimaryContext()->
makeDeclVisibleInContextWithFlags(ND, true, true);
}
-/// shouldBeHidden - Determine whether a declaration which was declared
-/// within its semantic context should be invisible to qualified name lookup.
-static bool shouldBeHidden(NamedDecl *D) {
- // Skip unnamed declarations.
- if (!D->getDeclName())
- return true;
-
- // Skip entities that can't be found by name lookup into a particular
- // context.
- if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
- D->isTemplateParameter())
- return true;
-
- // Skip template specializations.
- // FIXME: This feels like a hack. Should DeclarationName support
- // template-ids, or is there a better way to keep specializations
- // from being visible?
- if (isa<ClassTemplateSpecializationDecl>(D))
- return true;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- if (FD->isFunctionTemplateSpecialization())
- return true;
-
- return false;
-}
-
/// buildLookup - Build the lookup data structure with all of the
/// declarations in this DeclContext (and any other contexts linked
/// to it or transparent contexts nested within it) and return it.
@@ -1505,7 +1514,7 @@ StoredDeclsMap *DeclContext::buildLookup() {
/// DeclContext, a DeclContext linked to it, or a transparent context
/// nested within it.
void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
- for (Decl *D : DCtx->noload_decls()) {
+ for (auto *D : DCtx->noload_decls()) {
// Insert this declaration into the lookup structure, but only if
// it's semantically within its decl context. Any other decls which
// should be found in this context are added eagerly.
@@ -1514,7 +1523,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
// FindExternalVisibleDeclsByName if needed. Exception: if we're not
// in C++, we do not track external visible decls for the TU, so in
// that case we need to collect them all here.
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (auto *ND = dyn_cast<NamedDecl>(D))
if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND) &&
(!ND->isFromASTFile() ||
(isTranslationUnit() &&
@@ -1524,7 +1533,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
// If this declaration is itself a transparent declaration context
// or inline namespace, add the members of this declaration of that
// context (recursively).
- if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))
+ if (auto *InnerCtx = dyn_cast<DeclContext>(D))
if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
buildLookupImpl(InnerCtx, Internal);
}
@@ -1577,7 +1586,7 @@ DeclContext::lookup(DeclarationName Name) const {
}
}
- return lookup_result();
+ return {};
}
StoredDeclsMap *Map = LookupPtr;
@@ -1585,11 +1594,11 @@ DeclContext::lookup(DeclarationName Name) const {
Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
- return lookup_result();
+ return {};
StoredDeclsMap::iterator I = Map->find(Name);
if (I == Map->end())
- return lookup_result();
+ return {};
return I->second.getLookupResult();
}
@@ -1603,30 +1612,33 @@ DeclContext::noload_lookup(DeclarationName Name) {
if (PrimaryContext != this)
return PrimaryContext->noload_lookup(Name);
- // If we have any lazy lexical declarations not in our lookup map, add them
- // now. Don't import any external declarations, not even if we know we have
- // some missing from the external visible lookups.
- if (HasLazyLocalLexicalLookups) {
- SmallVector<DeclContext *, 2> Contexts;
- collectAllContexts(Contexts);
- for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl(Contexts[I], hasExternalVisibleStorage());
- HasLazyLocalLexicalLookups = false;
- }
-
+ loadLazyLocalLexicalLookups();
StoredDeclsMap *Map = LookupPtr;
if (!Map)
- return lookup_result();
+ return {};
StoredDeclsMap::iterator I = Map->find(Name);
return I != Map->end() ? I->second.getLookupResult()
: lookup_result();
}
+// If we have any lazy lexical declarations not in our lookup map, add them
+// now. Don't import any external declarations, not even if we know we have
+// some missing from the external visible lookups.
+void DeclContext::loadLazyLocalLexicalLookups() {
+ if (HasLazyLocalLexicalLookups) {
+ SmallVector<DeclContext *, 2> Contexts;
+ collectAllContexts(Contexts);
+ for (auto *Context : Contexts)
+ buildLookupImpl(Context, hasExternalVisibleStorage());
+ HasLazyLocalLexicalLookups = false;
+ }
+}
+
void DeclContext::localUncachedLookup(DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Results) {
Results.clear();
-
+
// If there's no external storage, just perform a normal lookup and copy
// the results.
if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) {
@@ -1649,12 +1661,12 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
}
}
- // Slow case: grovel through the declarations in our chain looking for
+ // Slow case: grovel through the declarations in our chain looking for
// matches.
// FIXME: If we have lazy external declarations, this will not find them!
// FIXME: Should we CollectAllContexts and walk them all here?
for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (auto *ND = dyn_cast<NamedDecl>(D))
if (ND->getDeclName() == Name)
Results.push_back(ND);
}
@@ -1696,7 +1708,7 @@ bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
if (O->Equals(this))
return true;
- const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(O);
+ const auto *NS = dyn_cast<NamespaceDecl>(O);
if (!NS || !NS->isInline())
break;
O = NS->getParent();
@@ -1755,7 +1767,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
getParent()->getPrimaryContext()->
makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
- Decl *DCAsDecl = cast<Decl>(this);
+ auto *DCAsDecl = cast<Decl>(this);
// Notify that a decl was made visible unless we are a Tag being defined.
if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
@@ -1873,16 +1885,15 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
if (!Parent->LookupPtr)
Parent->CreateStoredDeclsMap(C);
- DependentStoredDeclsMap *Map =
- static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr);
+ auto *Map = static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr);
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
PartialDiagnostic::Storage *DiagStorage = nullptr;
if (PDiag.hasStorage())
DiagStorage = new (C) PartialDiagnostic::Storage;
-
- DependentDiagnostic *DD = new (C) DependentDiagnostic(PDiag, DiagStorage);
+
+ auto *DD = new (C) DependentDiagnostic(PDiag, DiagStorage);
// TODO: Maybe we shouldn't reverse the order during insertion.
DD->NextDiagnostic = Map->FirstDiagnostic;
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index 41f2449a9d6a..51e8e14f804a 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -74,7 +74,8 @@ void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
: UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0),
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
- Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
+ Abstract(false), IsStandardLayout(true), IsCXX11StandardLayout(true),
+ HasBasesWithFields(false), HasBasesWithNonStaticDataMembers(false),
HasPrivateFields(false), HasProtectedFields(false),
HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false),
HasOnlyCMembers(true), HasInClassInitializer(false),
@@ -88,10 +89,11 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
DefaultedMoveConstructorIsDeleted(false),
DefaultedMoveAssignmentIsDeleted(false),
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
- DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
+ HasTrivialSpecialMembersForCall(SMF_All),
+ DeclaredNonTrivialSpecialMembers(0),
+ DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),
HasConstexprNonCopyMoveConstructor(false),
HasDefaultedDefaultConstructor(false),
- CanPassInRegisters(true),
DefaultedDefaultConstructorIsConstexpr(true),
HasConstexprDefaultConstructor(false),
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
@@ -124,8 +126,8 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
SourceLocation IdLoc, IdentifierInfo *Id,
CXXRecordDecl *PrevDecl,
bool DelayTypeCreation) {
- CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc,
- IdLoc, Id, PrevDecl);
+ auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
+ PrevDecl);
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
// FIXME: DelayTypeCreation seems like such a hack
@@ -139,9 +141,8 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
bool Dependent, bool IsGeneric,
LambdaCaptureDefault CaptureDefault) {
- CXXRecordDecl *R =
- new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
- nullptr, nullptr);
+ auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
+ nullptr, nullptr);
R->IsBeingDefined = true;
R->DefinitionData =
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
@@ -154,13 +155,32 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
CXXRecordDecl *
CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
- CXXRecordDecl *R = new (C, ID) CXXRecordDecl(
+ auto *R = new (C, ID) CXXRecordDecl(
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
R->MayHaveOutOfDateDef = false;
return R;
}
+/// Determine whether a class has a repeated base class. This is intended for
+/// use when determining if a class is standard-layout, so makes no attempt to
+/// handle virtual bases.
+static bool hasRepeatedBaseClass(const CXXRecordDecl *StartRD) {
+ llvm::SmallPtrSet<const CXXRecordDecl*, 8> SeenBaseTypes;
+ SmallVector<const CXXRecordDecl*, 8> WorkList = {StartRD};
+ while (!WorkList.empty()) {
+ const CXXRecordDecl *RD = WorkList.pop_back_val();
+ for (const CXXBaseSpecifier &BaseSpec : RD->bases()) {
+ if (const CXXRecordDecl *B = BaseSpec.getType()->getAsCXXRecordDecl()) {
+ if (!SeenBaseTypes.insert(B).second)
+ return true;
+ WorkList.push_back(B);
+ }
+ }
+ }
+ return false;
+}
+
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
@@ -183,7 +203,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// The set of seen virtual base types.
llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
-
+
// The virtual bases of this class.
SmallVector<const CXXBaseSpecifier *, 8> VBases;
@@ -197,50 +217,67 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// Skip dependent types; we can't do any checking on them now.
if (BaseType->isDependentType())
continue;
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+ auto *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- if (!BaseClassDecl->isEmpty()) {
- if (!data().Empty) {
- // C++0x [class]p7:
- // A standard-layout class is a class that:
- // [...]
- // -- either has no non-static data members in the most derived
- // class and at most one base class with non-static data members,
- // or has no base classes with non-static data members, and
- // If this is the second non-empty base, then neither of these two
- // clauses can be true.
+ // C++2a [class]p7:
+ // A standard-layout class is a class that:
+ // [...]
+ // -- has all non-static data members and bit-fields in the class and
+ // its base classes first declared in the same class
+ if (BaseClassDecl->data().HasBasesWithFields ||
+ !BaseClassDecl->field_empty()) {
+ if (data().HasBasesWithFields)
+ // Two bases have members or bit-fields: not standard-layout.
data().IsStandardLayout = false;
- }
+ data().HasBasesWithFields = true;
+ }
+
+ // C++11 [class]p7:
+ // A standard-layout class is a class that:
+ // -- [...] has [...] at most one base class with non-static data
+ // members
+ if (BaseClassDecl->data().HasBasesWithNonStaticDataMembers ||
+ BaseClassDecl->hasDirectFields()) {
+ if (data().HasBasesWithNonStaticDataMembers)
+ data().IsCXX11StandardLayout = false;
+ data().HasBasesWithNonStaticDataMembers = true;
+ }
+ if (!BaseClassDecl->isEmpty()) {
// C++14 [meta.unary.prop]p4:
// T is a class type [...] with [...] no base class B for which
// is_empty<B>::value is false.
data().Empty = false;
- data().HasNoNonEmptyBases = false;
}
-
+
// C++1z [dcl.init.agg]p1:
// An aggregate is a class with [...] no private or protected base classes
if (Base->getAccessSpecifier() != AS_public)
data().Aggregate = false;
// C++ [class.virtual]p1:
- // A class that declares or inherits a virtual function is called a
+ // A class that declares or inherits a virtual function is called a
// polymorphic class.
- if (BaseClassDecl->isPolymorphic())
+ if (BaseClassDecl->isPolymorphic()) {
data().Polymorphic = true;
+ // An aggregate is a class with [...] no virtual functions.
+ data().Aggregate = false;
+ }
+
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has no non-standard-layout base classes
if (!BaseClassDecl->isStandardLayout())
data().IsStandardLayout = false;
+ if (!BaseClassDecl->isCXX11StandardLayout())
+ data().IsCXX11StandardLayout = false;
// Record if this base is the first non-literal field or base.
if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType(C))
data().HasNonLiteralTypeFieldsOrBases = true;
-
+
// Now go through all virtual bases of this base and add them.
for (const auto &VBase : BaseClassDecl->vbases()) {
// Add this base if it's not already in the list.
@@ -281,11 +318,13 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// operator for a class X] is trivial [...] if:
// -- class X has [...] no virtual base classes
data().HasTrivialSpecialMembers &= SMF_Destructor;
+ data().HasTrivialSpecialMembersForCall &= SMF_Destructor;
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has [...] no virtual base classes
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor [...]
@@ -314,6 +353,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// subobject is trivial, and
if (!BaseClassDecl->hasTrivialCopyConstructor())
data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
+
+ if (!BaseClassDecl->hasTrivialCopyConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;
+
// If the base class doesn't have a simple move constructor, we'll eagerly
// declare it and perform overload resolution to determine which function
// it actually calls. If it does have a simple move constructor, this
@@ -321,6 +364,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (!BaseClassDecl->hasTrivialMoveConstructor())
data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
+ if (!BaseClassDecl->hasTrivialMoveConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;
+
// C++0x [class.copy]p27:
// A copy/move assignment operator for class X is trivial if [...]
// [...]
@@ -357,6 +403,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (!BaseClassDecl->hasTrivialDestructor())
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
+ if (!BaseClassDecl->hasTrivialDestructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
+
if (!BaseClassDecl->hasIrrelevantDestructor())
data().HasIrrelevantDestructor = false;
@@ -372,10 +421,14 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// has an Objective-C object member.
if (BaseClassDecl->hasObjectMember())
setHasObjectMember(true);
-
+
if (BaseClassDecl->hasVolatileMember())
setHasVolatileMember(true);
+ if (BaseClassDecl->getArgPassingRestrictions() ==
+ RecordDecl::APK_CanNeverPassInRegs)
+ setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+
// Keep track of the presence of mutable fields.
if (BaseClassDecl->hasMutableFields()) {
data().HasMutableFields = true;
@@ -390,7 +443,17 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
addedClassSubobject(BaseClassDecl);
}
-
+
+ // C++2a [class]p7:
+ // A class S is a standard-layout class if it:
+ // -- has at most one base class subobject of any given type
+ //
+ // Note that we only need to check this for classes with more than one base
+ // class. If there's only one base class, and it's standard layout, then
+ // we know there are no repeated base classes.
+ if (data().IsStandardLayout && NumBases > 1 && hasRepeatedBaseClass(this))
+ data().IsStandardLayout = false;
+
if (VBases.empty()) {
data().IsParsingBaseSpecifiers = false;
return;
@@ -485,11 +548,86 @@ bool CXXRecordDecl::isTriviallyCopyable() const {
}
void CXXRecordDecl::markedVirtualFunctionPure() {
- // C++ [class.abstract]p2:
+ // C++ [class.abstract]p2:
// A class is abstract if it has at least one pure virtual function.
data().Abstract = true;
}
+bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
+ ASTContext &Ctx, const CXXRecordDecl *XFirst) {
+ if (!getNumBases())
+ return false;
+
+ llvm::SmallPtrSet<const CXXRecordDecl*, 8> Bases;
+ llvm::SmallPtrSet<const CXXRecordDecl*, 8> M;
+ SmallVector<const CXXRecordDecl*, 8> WorkList;
+
+ // Visit a type that we have determined is an element of M(S).
+ auto Visit = [&](const CXXRecordDecl *RD) -> bool {
+ RD = RD->getCanonicalDecl();
+
+ // C++2a [class]p8:
+ // A class S is a standard-layout class if it [...] has no element of the
+ // set M(S) of types as a base class.
+ //
+ // If we find a subobject of an empty type, it might also be a base class,
+ // so we'll need to walk the base classes to check.
+ if (!RD->data().HasBasesWithFields) {
+ // Walk the bases the first time, stopping if we find the type. Build a
+ // set of them so we don't need to walk them again.
+ if (Bases.empty()) {
+ bool RDIsBase = !forallBases([&](const CXXRecordDecl *Base) -> bool {
+ Base = Base->getCanonicalDecl();
+ if (RD == Base)
+ return false;
+ Bases.insert(Base);
+ return true;
+ });
+ if (RDIsBase)
+ return true;
+ } else {
+ if (Bases.count(RD))
+ return true;
+ }
+ }
+
+ if (M.insert(RD).second)
+ WorkList.push_back(RD);
+ return false;
+ };
+
+ if (Visit(XFirst))
+ return true;
+
+ while (!WorkList.empty()) {
+ const CXXRecordDecl *X = WorkList.pop_back_val();
+
+ // FIXME: We don't check the bases of X. That matches the standard, but
+ // that sure looks like a wording bug.
+
+ // -- If X is a non-union class type with a non-static data member
+ // [recurse to] the first non-static data member of X
+ // -- If X is a union type, [recurse to union members]
+ for (auto *FD : X->fields()) {
+ // FIXME: Should we really care about the type of the first non-static
+ // data member of a non-union if there are preceding unnamed bit-fields?
+ if (FD->isUnnamedBitfield())
+ continue;
+
+ // -- If X is n array type, [visit the element type]
+ QualType T = Ctx.getBaseElementType(FD->getType());
+ if (auto *RD = T->getAsCXXRecordDecl())
+ if (Visit(RD))
+ return true;
+
+ if (!X->isUnion())
+ break;
+ }
+ }
+
+ return false;
+}
+
void CXXRecordDecl::addedMember(Decl *D) {
if (!D->isImplicit() &&
!isa<FieldDecl>(D) &&
@@ -501,8 +639,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
// Ignore friends and invalid declarations.
if (D->getFriendObjectKind() || D->isInvalidDecl())
return;
-
- FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+
+ auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (FunTmpl)
D = FunTmpl->getTemplatedDecl();
@@ -510,27 +648,26 @@ void CXXRecordDecl::addedMember(Decl *D) {
Decl *DUnderlying = D;
if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) {
DUnderlying = ND->getUnderlyingDecl();
- if (FunctionTemplateDecl *UnderlyingFunTmpl =
- dyn_cast<FunctionTemplateDecl>(DUnderlying))
+ if (auto *UnderlyingFunTmpl = dyn_cast<FunctionTemplateDecl>(DUnderlying))
DUnderlying = UnderlyingFunTmpl->getTemplatedDecl();
}
-
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isVirtual()) {
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class with [...] no virtual functions.
data().Aggregate = false;
-
+
// C++ [class]p4:
// A POD-struct is an aggregate class...
data().PlainOldData = false;
-
+
// C++14 [meta.unary.prop]p4:
// T is a class type [...] with [...] no virtual member functions...
data().Empty = false;
// C++ [class.virtual]p1:
- // A class that declares or inherits a virtual function is called a
+ // A class that declares or inherits a virtual function is called a
// polymorphic class.
data().Polymorphic = true;
@@ -539,11 +676,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
// assignment operator for a class X] is trivial [...] if:
// -- class X has no virtual functions [...]
data().HasTrivialSpecialMembers &= SMF_Destructor;
+ data().HasTrivialSpecialMembersForCall &= SMF_Destructor;
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has no virtual functions
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
}
}
@@ -557,7 +696,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
unsigned SMKind = 0;
// Handle constructors.
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
if (!Constructor->isImplicit()) {
// Note that we have a user-declared constructor.
data().UserDeclaredConstructor = true;
@@ -599,8 +738,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Handle constructors, including those inherited from base classes.
- if (CXXConstructorDecl *Constructor =
- dyn_cast<CXXConstructorDecl>(DUnderlying)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(DUnderlying)) {
// Record if we see any constexpr constructors which are neither copy
// nor move constructors.
// C++1z [basic.types]p10:
@@ -612,7 +750,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Handle destructors.
- if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) {
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
SMKind |= SMF_Destructor;
if (DD->isUserProvided())
@@ -623,17 +761,19 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++11 [class.dtor]p5:
// A destructor is trivial if [...] the destructor is not virtual.
- if (DD->isVirtual())
+ if (DD->isVirtual()) {
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
+ data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
+ }
}
// Handle member functions.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isCopyAssignmentOperator()) {
SMKind |= SMF_CopyAssignment;
- const ReferenceType *ParamTy =
- Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
+ const auto *ParamTy =
+ Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
if (!ParamTy || ParamTy->getPointeeType().isConstQualified())
data().HasDeclaredCopyAssignmentWithConstParam = true;
}
@@ -642,7 +782,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
SMKind |= SMF_MoveAssignment;
// Keep the list of conversion functions up-to-date.
- if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
+ if (auto *Conversion = dyn_cast<CXXConversionDecl>(D)) {
// FIXME: We use the 'unsafe' accessor for the access specifier here,
// because Sema may not have set it yet. That's really just a misdesign
// in Sema. However, LLDB *will* have set the access specifier correctly,
@@ -670,16 +810,30 @@ void CXXRecordDecl::addedMember(Decl *D) {
// If this is the first declaration of a special member, we no longer have
// an implicit trivial special member.
data().HasTrivialSpecialMembers &=
- data().DeclaredSpecialMembers | ~SMKind;
+ data().DeclaredSpecialMembers | ~SMKind;
+ data().HasTrivialSpecialMembersForCall &=
+ data().DeclaredSpecialMembers | ~SMKind;
if (!Method->isImplicit() && !Method->isUserProvided()) {
// This method is user-declared but not user-provided. We can't work out
// whether it's trivial yet (not until we get to the end of the class).
// We'll handle this method in finishedDefaultedOrDeletedMember.
- } else if (Method->isTrivial())
+ } else if (Method->isTrivial()) {
data().HasTrivialSpecialMembers |= SMKind;
- else
+ data().HasTrivialSpecialMembersForCall |= SMKind;
+ } else if (Method->isTrivialForCall()) {
+ data().HasTrivialSpecialMembersForCall |= SMKind;
+ data().DeclaredNonTrivialSpecialMembers |= SMKind;
+ } else {
data().DeclaredNonTrivialSpecialMembers |= SMKind;
+ // If this is a user-provided function, do not set
+ // DeclaredNonTrivialSpecialMembersForCall here since we don't know
+ // yet whether the method would be considered non-trivial for the
+ // purpose of calls (attribute "trivial_abi" can be dropped from the
+ // class later, which can change the special method's triviality).
+ if (!Method->isUserProvided())
+ data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
+ }
// Note when we have declared a declared special member, and suppress the
// implicit declaration of this special member.
@@ -707,24 +861,54 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Handle non-static data members.
- if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
+ if (const auto *Field = dyn_cast<FieldDecl>(D)) {
+ ASTContext &Context = getASTContext();
+
+ // C++2a [class]p7:
+ // A standard-layout class is a class that:
+ // [...]
+ // -- has all non-static data members and bit-fields in the class and
+ // its base classes first declared in the same class
+ if (data().HasBasesWithFields)
+ data().IsStandardLayout = false;
+
// C++ [class.bit]p2:
- // A declaration for a bit-field that omits the identifier declares an
- // unnamed bit-field. Unnamed bit-fields are not members and cannot be
+ // A declaration for a bit-field that omits the identifier declares an
+ // unnamed bit-field. Unnamed bit-fields are not members and cannot be
// initialized.
- if (Field->isUnnamedBitfield())
+ if (Field->isUnnamedBitfield()) {
+ // C++ [meta.unary.prop]p4: [LWG2358]
+ // T is a class type [...] with [...] no unnamed bit-fields of non-zero
+ // length
+ if (data().Empty && !Field->isZeroLengthBitField(Context) &&
+ Context.getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver6)
+ data().Empty = false;
return;
-
+ }
+
+ // C++11 [class]p7:
+ // A standard-layout class is a class that:
+ // -- either has no non-static data members in the most derived class
+ // [...] or has no base classes with non-static data members
+ if (data().HasBasesWithNonStaticDataMembers)
+ data().IsCXX11StandardLayout = false;
+
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...] no
// private or protected non-static data members (clause 11).
//
- // A POD must be an aggregate.
+ // A POD must be an aggregate.
if (D->getAccess() == AS_private || D->getAccess() == AS_protected) {
data().Aggregate = false;
data().PlainOldData = false;
}
+ // Track whether this is the first field. We use this when checking
+ // whether the class is standard-layout below.
+ bool IsFirstField = !data().HasPrivateFields &&
+ !data().HasProtectedFields && !data().HasPublicFields;
+
// C++0x [class]p7:
// A standard-layout class is a class that:
// [...]
@@ -736,8 +920,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
case AS_none: llvm_unreachable("Invalid access specifier");
};
if ((data().HasPrivateFields + data().HasProtectedFields +
- data().HasPublicFields) > 1)
+ data().HasPublicFields) > 1) {
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
+ }
// Keep track of the presence of mutable fields.
if (Field->isMutable()) {
@@ -752,13 +938,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().HasVariantMembers = true;
// C++0x [class]p9:
- // A POD struct is a class that is both a trivial class and a
- // standard-layout class, and has no non-static data members of type
+ // A POD struct is a class that is both a trivial class and a
+ // standard-layout class, and has no non-static data members of type
// non-POD struct, non-POD union (or array of such types).
//
// Automatic Reference Counting: the presence of a member of Objective-C pointer type
// that does not explicitly have no lifetime makes the class a non-POD.
- ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
if (T.hasNonTrivialObjCLifetime()) {
@@ -772,13 +957,24 @@ void CXXRecordDecl::addedMember(Decl *D) {
struct DefinitionData &Data = data();
Data.PlainOldData = false;
Data.HasTrivialSpecialMembers = 0;
+
+ // __strong or __weak fields do not make special functions non-trivial
+ // for the purpose of calls.
+ Qualifiers::ObjCLifetime LT = T.getQualifiers().getObjCLifetime();
+ if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)
+ data().HasTrivialSpecialMembersForCall = 0;
+
+ // Structs with __weak fields should never be passed directly.
+ if (LT == Qualifiers::OCL_Weak)
+ setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+
Data.HasIrrelevantDestructor = false;
} else if (!Context.getLangOpts().ObjCAutoRefCount) {
setHasObjectMember(true);
}
} else if (!T.isCXX98PODType(Context))
data().PlainOldData = false;
-
+
if (T->isReferenceType()) {
if (!Field->hasInClassInitializer())
data().HasUninitializedReferenceMember = true;
@@ -787,6 +983,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// A standard-layout class is a class that:
// -- has no non-static data members of type [...] reference,
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
// C++1z [class.copy.ctor]p10:
// A defaulted copy constructor for a class X is defined as deleted if X has:
@@ -838,8 +1035,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (T->isReferenceType())
data().DefaultedMoveAssignmentIsDeleted = true;
- if (const RecordType *RecordTy = T->getAs<RecordType>()) {
- CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (const auto *RecordTy = T->getAs<RecordType>()) {
+ auto *FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
if (FieldRec->getDefinition()) {
addedClassSubobject(FieldRec);
@@ -899,12 +1096,19 @@ void CXXRecordDecl::addedMember(Decl *D) {
// member is trivial;
if (!FieldRec->hasTrivialCopyConstructor())
data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
+
+ if (!FieldRec->hasTrivialCopyConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;
+
// If the field doesn't have a simple move constructor, we'll eagerly
// declare the move constructor for this class and we'll decide whether
// it's trivial then.
if (!FieldRec->hasTrivialMoveConstructor())
data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
+ if (!FieldRec->hasTrivialMoveConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;
+
// C++0x [class.copy]p27:
// A copy/move assignment operator for class X is trivial if [...]
// [...]
@@ -921,12 +1125,17 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (!FieldRec->hasTrivialDestructor())
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
+ if (!FieldRec->hasTrivialDestructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
if (!FieldRec->hasIrrelevantDestructor())
data().HasIrrelevantDestructor = false;
if (FieldRec->hasObjectMember())
setHasObjectMember(true);
if (FieldRec->hasVolatileMember())
setHasVolatileMember(true);
+ if (FieldRec->getArgPassingRestrictions() ==
+ RecordDecl::APK_CanNeverPassInRegs)
+ setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
// C++0x [class]p7:
// A standard-layout class is a class that:
@@ -934,31 +1143,32 @@ void CXXRecordDecl::addedMember(Decl *D) {
// class (or array of such types) [...]
if (!FieldRec->isStandardLayout())
data().IsStandardLayout = false;
+ if (!FieldRec->isCXX11StandardLayout())
+ data().IsCXX11StandardLayout = false;
- // C++0x [class]p7:
+ // C++2a [class]p7:
// A standard-layout class is a class that:
// [...]
+ // -- has no element of the set M(S) of types as a base class.
+ if (data().IsStandardLayout && (isUnion() || IsFirstField) &&
+ hasSubobjectAtOffsetZeroOfEmptyBaseType(Context, FieldRec))
+ data().IsStandardLayout = false;
+
+ // C++11 [class]p7:
+ // A standard-layout class is a class that:
// -- has no base classes of the same type as the first non-static
- // data member.
- // We don't want to expend bits in the state of the record decl
- // tracking whether this is the first non-static data member so we
- // cheat a bit and use some of the existing state: the empty bit.
- // Virtual bases and virtual methods make a class non-empty, but they
- // also make it non-standard-layout so we needn't check here.
- // A non-empty base class may leave the class standard-layout, but not
- // if we have arrived here, and have at least one non-static data
- // member. If IsStandardLayout remains true, then the first non-static
- // data member must come through here with Empty still true, and Empty
- // will subsequently be set to false below.
- if (data().IsStandardLayout && data().Empty) {
+ // data member
+ if (data().IsCXX11StandardLayout && IsFirstField) {
+ // FIXME: We should check all base classes here, not just direct
+ // base classes.
for (const auto &BI : bases()) {
if (Context.hasSameUnqualifiedType(BI.getType(), T)) {
- data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
break;
}
}
}
-
+
// Keep track of the presence of mutable fields.
if (FieldRec->hasMutableFields()) {
data().HasMutableFields = true;
@@ -1021,31 +1231,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().DefaultedMoveAssignmentIsDeleted = true;
}
- // C++0x [class]p7:
- // A standard-layout class is a class that:
- // [...]
- // -- either has no non-static data members in the most derived
- // class and at most one base class with non-static data members,
- // or has no base classes with non-static data members, and
- // At this point we know that we have a non-static data member, so the last
- // clause holds.
- if (!data().HasNoNonEmptyBases)
- data().IsStandardLayout = false;
-
// C++14 [meta.unary.prop]p4:
- // T is a class type [...] with [...] no non-static data members other
- // than bit-fields of length 0...
- if (data().Empty) {
- if (!Field->isBitField() ||
- (!Field->getBitWidth()->isTypeDependent() &&
- !Field->getBitWidth()->isValueDependent() &&
- Field->getBitWidthValue(Context) != 0))
- data().Empty = false;
- }
+ // T is a class type [...] with [...] no non-static data members
+ data().Empty = false;
}
-
+
// Handle using declarations of conversion functions.
- if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D)) {
+ if (auto *Shadow = dyn_cast<UsingShadowDecl>(D)) {
if (Shadow->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName) {
ASTContext &Ctx = getASTContext();
@@ -1053,7 +1245,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
}
- if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
+ if (const auto *Using = dyn_cast<UsingDecl>(D)) {
if (Using->getDeclName().getNameKind() ==
DeclarationName::CXXConstructorName) {
data().HasInheritedConstructor = true;
@@ -1073,7 +1265,7 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
// The kind of special member this declaration is, if any.
unsigned SMKind = 0;
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
if (Constructor->isDefaultConstructor()) {
SMKind |= SMF_DefaultConstructor;
if (Constructor->isConstexpr())
@@ -1103,6 +1295,23 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
data().DeclaredNonTrivialSpecialMembers |= SMKind;
}
+void CXXRecordDecl::setTrivialForCallFlags(CXXMethodDecl *D) {
+ unsigned SMKind = 0;
+
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (Constructor->isCopyConstructor())
+ SMKind = SMF_CopyConstructor;
+ else if (Constructor->isMoveConstructor())
+ SMKind = SMF_MoveConstructor;
+ } else if (isa<CXXDestructorDecl>(D))
+ SMKind = SMF_Destructor;
+
+ if (D->isTrivialForCall())
+ data().HasTrivialSpecialMembersForCall |= SMKind;
+ else
+ data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
+}
+
bool CXXRecordDecl::isCLike() const {
if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
!TemplateOrInstantiation.isNull())
@@ -1112,42 +1321,40 @@ bool CXXRecordDecl::isCLike() const {
return isPOD() && data().HasOnlyCMembers;
}
-
-bool CXXRecordDecl::isGenericLambda() const {
+
+bool CXXRecordDecl::isGenericLambda() const {
if (!isLambda()) return false;
return getLambdaData().IsGenericLambda;
}
CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
if (!isLambda()) return nullptr;
- DeclarationName Name =
+ DeclarationName Name =
getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
DeclContext::lookup_result Calls = lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
- assert(Calls.size() == 1 && "More than one lambda call operator!");
-
+ assert(Calls.size() == 1 && "More than one lambda call operator!");
+
NamedDecl *CallOp = Calls.front();
- if (FunctionTemplateDecl *CallOpTmpl =
- dyn_cast<FunctionTemplateDecl>(CallOp))
+ if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());
-
+
return cast<CXXMethodDecl>(CallOp);
}
CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
if (!isLambda()) return nullptr;
- DeclarationName Name =
+ DeclarationName Name =
&getASTContext().Idents.get(getLambdaStaticInvokerName());
DeclContext::lookup_result Invoker = lookup(Name);
if (Invoker.empty()) return nullptr;
- assert(Invoker.size() == 1 && "More than one static invoker operator!");
+ assert(Invoker.size() == 1 && "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
- if (FunctionTemplateDecl *InvokerTemplate =
- dyn_cast<FunctionTemplateDecl>(InvokerFun))
+ if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());
-
- return cast<CXXMethodDecl>(InvokerFun);
+
+ return cast<CXXMethodDecl>(InvokerFun);
}
void CXXRecordDecl::getCaptureFields(
@@ -1168,10 +1375,10 @@ void CXXRecordDecl::getCaptureFields(
assert(Field == field_end());
}
-TemplateParameterList *
+TemplateParameterList *
CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
if (!isLambda()) return nullptr;
- CXXMethodDecl *CallOp = getLambdaCallOperator();
+ CXXMethodDecl *CallOp = getLambdaCallOperator();
if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())
return Tmpl->getTemplateParameters();
return nullptr;
@@ -1257,7 +1464,7 @@ static void CollectVisibleConversions(ASTContext &Context,
= CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier());
bool BaseInVirtual = InVirtual || I.isVirtual();
- CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
+ auto *Base = cast<CXXRecordDecl>(RT->getDecl());
CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
*HiddenTypes, Output, VOutput, HiddenVBaseCs);
}
@@ -1274,7 +1481,7 @@ static void CollectVisibleConversions(ASTContext &Context,
// found. These will be added to the output as long as they don't
// appear in the hidden-conversions set.
UnresolvedSet<8> VBaseCs;
-
+
// The set of conversions in virtual bases that we've determined to
// be hidden.
llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs;
@@ -1365,13 +1572,13 @@ MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
}
-void
+void
CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
TemplateSpecializationKind TSK) {
- assert(TemplateOrInstantiation.isNull() &&
+ assert(TemplateOrInstantiation.isNull() &&
"Previous template or instantiation?");
assert(!isa<ClassTemplatePartialSpecializationDecl>(this));
- TemplateOrInstantiation
+ TemplateOrInstantiation
= new (getASTContext()) MemberSpecializationInfo(RD, TSK);
}
@@ -1384,29 +1591,27 @@ void CXXRecordDecl::setDescribedClassTemplate(ClassTemplateDecl *Template) {
}
TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
- if (const ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(this))
+ if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this))
return Spec->getSpecializationKind();
-
+
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
return MSInfo->getTemplateSpecializationKind();
-
+
return TSK_Undeclared;
}
-void
+void
CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
+ if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
return;
}
-
+
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
return;
}
-
+
llvm_unreachable("Not a class template or member class specialization");
}
@@ -1566,17 +1771,17 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
getFinalOverriders(MyFinalOverriders);
FinalOverriders = &MyFinalOverriders;
}
-
+
bool Done = false;
- for (CXXFinalOverriderMap::iterator M = FinalOverriders->begin(),
+ for (CXXFinalOverriderMap::iterator M = FinalOverriders->begin(),
MEnd = FinalOverriders->end();
M != MEnd && !Done; ++M) {
- for (OverridingMethods::iterator SO = M->second.begin(),
+ for (OverridingMethods::iterator SO = M->second.begin(),
SOEnd = M->second.end();
SO != SOEnd && !Done; ++SO) {
- assert(SO->second.size() > 0 &&
- "All virtual functions have overridding virtual functions");
-
+ assert(SO->second.size() > 0 &&
+ "All virtual functions have overriding virtual functions");
+
// C++ [class.abstract]p4:
// A class is abstract if it contains or inherits at least one
// pure virtual function for which the final overrider is pure
@@ -1589,7 +1794,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
}
}
}
-
+
// Set access bits correctly on the directly-declared conversions.
for (conversion_iterator I = conversion_begin(), E = conversion_end();
I != E; ++I)
@@ -1600,14 +1805,14 @@ bool CXXRecordDecl::mayBeAbstract() const {
if (data().Abstract || isInvalidDecl() || !data().Polymorphic ||
isDependentContext())
return false;
-
+
for (const auto &B : bases()) {
- CXXRecordDecl *BaseDecl
- = cast<CXXRecordDecl>(B.getType()->getAs<RecordType>()->getDecl());
+ const auto *BaseDecl =
+ cast<CXXRecordDecl>(B.getType()->getAs<RecordType>()->getDecl());
if (BaseDecl->isAbstract())
return true;
}
-
+
return false;
}
@@ -1670,7 +1875,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
}
for (auto *ND : RD->lookup(getDeclName())) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND);
+ auto *MD = dyn_cast<CXXMethodDecl>(ND);
if (!MD)
continue;
if (recursivelyOverrides(MD, this))
@@ -1683,7 +1888,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
const RecordType *RT = I.getType()->getAs<RecordType>();
if (!RT)
continue;
- const CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
+ const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base);
if (T)
return T;
@@ -1758,8 +1963,8 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
if (BestDynamicDecl->hasAttr<FinalAttr>())
return DevirtualizedMethod;
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (VD->getType()->isRecordType())
// This is a record decl. We know the type and can devirtualize it.
return DevirtualizedMethod;
@@ -1770,9 +1975,10 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
// We can devirtualize calls on an object accessed by a class member access
// expression, since by C++11 [basic.life]p6 we know that it can't refer to
// a derived class object constructed in the same location.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
- return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr;
+ if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
+ const ValueDecl *VD = ME->getMemberDecl();
+ return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr;
+ }
// Likewise for calls on an object accessed by a (non-reference) pointer to
// member access.
@@ -1800,7 +2006,7 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
return false;
// C++ [basic.stc.dynamic.deallocation]p2:
- // If a class T has a member deallocation function named operator delete
+ // If a class T has a member deallocation function named operator delete
// with exactly one parameter, then that function is a usual (non-placement)
// deallocation function. [...]
if (getNumParams() == 1)
@@ -1816,8 +2022,8 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
++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
+ // [...] If class T does not declare such an operator delete but does
+ // declare a member deallocation function named operator delete with
// exactly two parameters, the second of which has type std::size_t (18.1),
// then this function is a usual deallocation function.
//
@@ -1842,35 +2048,35 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// usual deallocation functions.
if (Context.getLangOpts().AlignedAllocation)
return true;
-
- // This function is a usual deallocation function if there are no
+
+ // This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
I != E; ++I) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
+ if (const auto *FD = dyn_cast<FunctionDecl>(*I))
if (FD->getNumParams() == 1)
return false;
}
-
+
return true;
}
bool CXXMethodDecl::isCopyAssignmentOperator() const {
// C++0x [class.copy]p17:
- // A user-declared copy assignment operator X::operator= is a non-static
- // non-template member function of class X with exactly one parameter of
+ // A user-declared copy assignment operator X::operator= is a non-static
+ // non-template member function of class X with exactly one parameter of
// type X, X&, const X&, volatile X& or const volatile X&.
if (/*operator=*/getOverloadedOperator() != OO_Equal ||
- /*non-static*/ isStatic() ||
+ /*non-static*/ isStatic() ||
/*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() ||
getNumParams() != 1)
return false;
-
+
QualType ParamType = getParamDecl(0)->getType();
- if (const LValueReferenceType *Ref = ParamType->getAs<LValueReferenceType>())
+ if (const auto *Ref = ParamType->getAs<LValueReferenceType>())
ParamType = Ref->getPointeeType();
-
+
ASTContext &Context = getASTContext();
QualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(getParent()));
@@ -1945,7 +2151,7 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
}
bool CXXMethodDecl::hasInlineBody() const {
- // If this function is a template instantiation, look at the template from
+ // If this function is a template instantiation, look at the template from
// which it was instantiated.
const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
if (!CheckFn)
@@ -1997,7 +2203,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
TypeSourceInfo *TInfo,
- SourceLocation L, Expr *Init,
+ SourceLocation L, Expr *Init,
SourceLocation R)
: Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R),
IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {}
@@ -2006,7 +2212,7 @@ TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
else
- return TypeLoc();
+ return {};
}
const Type *CXXCtorInitializer::getBaseClass() const {
@@ -2019,14 +2225,14 @@ const Type *CXXCtorInitializer::getBaseClass() const {
SourceLocation CXXCtorInitializer::getSourceLocation() const {
if (isInClassMemberInitializer())
return getAnyMember()->getLocation();
-
+
if (isAnyMemberInitializer())
return getMemberLocation();
- if (TypeSourceInfo *TSInfo = Initializee.get<TypeSourceInfo*>())
+ if (const auto *TSInfo = Initializee.get<TypeSourceInfo *>())
return TSInfo->getTypeLoc().getLocalSourceRange().getBegin();
-
- return SourceLocation();
+
+ return {};
}
SourceRange CXXCtorInitializer::getSourceRange() const {
@@ -2034,7 +2240,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
FieldDecl *D = getAnyMember();
if (Expr *I = D->getInClassInitializer())
return I->getSourceRange();
- return SourceRange();
+ return {};
}
return SourceRange(getSourceLocation(), getRParenLoc());
@@ -2078,7 +2284,7 @@ CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
assert(isDelegatingConstructor() && "Not a delegating constructor!");
Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
- if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E))
+ if (const auto *Construct = dyn_cast<CXXConstructExpr>(E))
return Construct->getConstructor();
return nullptr;
@@ -2103,7 +2309,7 @@ bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const {
getParamDecl(0)->getType()->isRValueReferenceType();
}
-/// \brief Determine whether this is a copy or move constructor.
+/// Determine whether this is a copy or move constructor.
bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
// C++ [class.copy]p2:
// A non-template constructor for class X is a copy constructor
@@ -2112,37 +2318,37 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
// or else all other parameters have default arguments (8.3.6).
// C++0x [class.copy]p3:
// A non-template constructor for class X is a move constructor if its
- // first parameter is of type X&&, const X&&, volatile X&&, or
- // const volatile X&&, and either there are no other parameters or else
+ // first parameter is of type X&&, const X&&, volatile X&&, or
+ // const volatile X&&, and either there are no other parameters or else
// all other parameters have default arguments.
if ((getNumParams() < 1) ||
(getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
(getPrimaryTemplate() != nullptr) ||
(getDescribedFunctionTemplate() != nullptr))
return false;
-
+
const ParmVarDecl *Param = getParamDecl(0);
-
- // Do we have a reference type?
- const ReferenceType *ParamRefType = Param->getType()->getAs<ReferenceType>();
+
+ // Do we have a reference type?
+ const auto *ParamRefType = Param->getType()->getAs<ReferenceType>();
if (!ParamRefType)
return false;
-
+
// Is it a reference to our class type?
ASTContext &Context = getASTContext();
-
+
CanQualType PointeeType
= Context.getCanonicalType(ParamRefType->getPointeeType());
- CanQualType ClassTy
+ CanQualType ClassTy
= Context.getCanonicalType(Context.getTagDeclType(getParent()));
if (PointeeType.getUnqualifiedType() != ClassTy)
return false;
-
+
// FIXME: other qualifiers?
-
+
// We have a copy or move constructor.
TypeQuals = PointeeType.getCVRQualifiers();
- return true;
+ return true;
}
bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
@@ -2173,14 +2379,14 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
ASTContext &Context = getASTContext();
CanQualType ParamType = Context.getCanonicalType(Param->getType());
-
- // Is it the same as our our class type?
- CanQualType ClassTy
+
+ // Is it the same as our class type?
+ CanQualType ClassTy
= Context.getCanonicalType(Context.getTagDeclType(getParent()));
if (ParamType.getUnqualifiedType() != ClassTy)
return false;
-
- return true;
+
+ return true;
}
void CXXDestructorDecl::anchor() {}
@@ -2271,7 +2477,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentLoc,
NamedDecl *Used,
DeclContext *CommonAncestor) {
- if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used))
+ if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Used))
Used = NS->getOriginalNamespace();
return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
IdentLoc, Used, CommonAncestor);
@@ -2286,8 +2492,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C,
}
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
- if (NamespaceAliasDecl *NA =
- dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
+ if (auto *NA = dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
return NA->getNamespace();
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
@@ -2367,7 +2572,7 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentLoc,
NamedDecl *Namespace) {
// FIXME: Preserve the aliased namespace as written.
- if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
+ if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
QualifierLoc, IdentLoc, Namespace);
@@ -2387,10 +2592,9 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target)
: NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
- redeclarable_base(C), Underlying(Target),
- UsingOrNextShadow(cast<NamedDecl>(Using)) {
+ redeclarable_base(C), UsingOrNextShadow(cast<NamedDecl>(Using)) {
if (Target)
- IdentifierNamespace = Target->getIdentifierNamespace();
+ setTargetDecl(Target);
setImplicit();
}
@@ -2405,8 +2609,8 @@ UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
UsingDecl *UsingShadowDecl::getUsingDecl() const {
const UsingShadowDecl *Shadow = this;
- while (const UsingShadowDecl *NextShadow =
- dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
+ while (const auto *NextShadow =
+ dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
Shadow = NextShadow;
return cast<UsingDecl>(Shadow->UsingOrNextShadow);
}
@@ -2625,7 +2829,7 @@ DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
void DecompositionDecl::printName(llvm::raw_ostream &os) const {
os << '[';
bool Comma = false;
- for (auto *B : bindings()) {
+ for (const auto *B : bindings()) {
if (Comma)
os << ", ";
B->printName(os);
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
index 461bf36858b7..08fbed361579 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
@@ -39,7 +39,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
ArrayRef<TemplateParameterList *> FriendTypeTPLists) {
#ifndef NDEBUG
if (Friend.is<NamedDecl *>()) {
- NamedDecl *D = Friend.get<NamedDecl*>();
+ const auto *D = Friend.get<NamedDecl*>();
assert(isa<FunctionDecl>(D) ||
isa<CXXRecordDecl>(D) ||
isa<FunctionTemplateDecl>(D) ||
@@ -57,8 +57,8 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
std::size_t Extra =
FriendDecl::additionalSizeToAlloc<TemplateParameterList *>(
FriendTypeTPLists.size());
- FriendDecl *FD = new (C, DC, Extra) FriendDecl(DC, L, Friend, FriendL,
- FriendTypeTPLists);
+ auto *FD = new (C, DC, Extra) FriendDecl(DC, L, Friend, FriendL,
+ FriendTypeTPLists);
cast<CXXRecordDecl>(DC)->pushFriendDecl(FD);
return FD;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
index f95d5def47ac..01fd10429fc1 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -51,7 +51,7 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
memcpy(List, InList, sizeof(void*)*Elts);
}
-void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
+void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx) {
if (Elts == 0)
return;
@@ -74,7 +74,7 @@ ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
lookup_result R = lookup(Id);
for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end();
Ivar != IvarEnd; ++Ivar) {
- if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
+ if (auto *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
return ivar;
}
return nullptr;
@@ -86,7 +86,7 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
bool AllowHidden) const {
// If this context is a hidden protocol definition, don't find any
// methods there.
- if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
+ if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
if (Def->isHidden() && !AllowHidden)
return nullptr;
@@ -102,14 +102,14 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
lookup_result R = lookup(Sel);
for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
- ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+ auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
if (MD && MD->isInstanceMethod() == isInstance)
return MD;
}
return nullptr;
}
-/// \brief This routine returns 'true' if a user declared setter method was
+/// This routine returns 'true' if a user declared setter method was
/// found in the class, its protocols, its super classes or categories.
/// It also returns 'true' if one of its categories has declared a 'readwrite'
/// property. This is because, user must provide a setter method for the
@@ -120,12 +120,12 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
lookup_result R = lookup(Sel);
for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
- ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+ auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
if (MD && MD->isInstanceMethod() && !MD->isImplicit())
return true;
}
- if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
+ if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
// Also look into categories, including class extensions, looking
// for a user declared instance method.
for (const auto *Cat : ID->visible_categories()) {
@@ -145,7 +145,7 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
break;
}
}
-
+
// Also look into protocols, for a user declared instance method.
for (const auto *Proto : ID->all_referenced_protocols())
if (Proto->HasUserDeclaredSetterMethod(Property))
@@ -159,7 +159,7 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
OSC = OSC->getSuperClass();
}
}
- if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(this))
+ if (const auto *PD = dyn_cast<ObjCProtocolDecl>(this))
for (const auto *PI : PD->protocols())
if (PI->HasUserDeclaredSetterMethod(Property))
return true;
@@ -172,7 +172,7 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
ObjCPropertyQueryKind queryKind) {
// If this context is a hidden protocol definition, don't find any
// property.
- if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
+ if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
if (Def->isHidden())
return nullptr;
@@ -192,7 +192,7 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
ObjCPropertyDecl *classProp = nullptr;
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I)
- if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) {
+ if (auto *PD = dyn_cast<ObjCPropertyDecl>(*I)) {
// If queryKind is unknown, we return the instance property if one
// exists; otherwise we return the class property.
if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
@@ -230,12 +230,12 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
const IdentifierInfo *PropertyId,
ObjCPropertyQueryKind QueryKind) const {
// Don't find properties within hidden protocol definitions.
- if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
+ if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
if (Def->isHidden())
return nullptr;
}
-
+
// Search the extensions of a class first; they override what's in
// the class itself.
if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {
@@ -254,7 +254,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
default:
break;
case Decl::ObjCProtocol: {
- const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this);
+ const auto *PID = cast<ObjCProtocolDecl>(this);
for (const auto *I : PID->protocols())
if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
QueryKind))
@@ -262,7 +262,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
break;
}
case Decl::ObjCInterface: {
- const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
+ const auto *OID = cast<ObjCInterfaceDecl>(this);
// Look through categories (but not extensions; they were handled above).
for (const auto *Cat : OID->visible_categories()) {
if (!Cat->IsClassExtension())
@@ -283,7 +283,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
break;
}
case Decl::ObjCCategory: {
- const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this);
+ const auto *OCD = cast<ObjCCategoryDecl>(this);
// Look through protocols.
if (!OCD->IsClassExtension())
for (const auto *I : OCD->protocols())
@@ -310,7 +310,8 @@ ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
// Otherwise, look at previous declarations to determine whether any
// of them has a type parameter list, skipping over those
// declarations that do not.
- for (auto decl = getMostRecentDecl(); decl; decl = decl->getPreviousDecl()) {
+ for (const ObjCInterfaceDecl *decl = getMostRecentDecl(); decl;
+ decl = decl->getPreviousDecl()) {
if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten())
return written;
}
@@ -323,7 +324,7 @@ void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) {
if (!TPL)
return;
// Set the declaration context of each of the type parameters.
- for (auto typeParam : *TypeParamList)
+ for (auto *typeParam : *TypeParamList)
typeParam->setDeclContext(this);
}
@@ -331,7 +332,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
-
+
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -350,7 +351,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
return superTInfo->getTypeLoc().getLocStart();
-
+
return SourceLocation();
}
@@ -428,16 +429,16 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
if (data().ExternallyCompleted)
LoadExternalDefinition();
- if (data().AllReferencedProtocols.empty() &&
+ if (data().AllReferencedProtocols.empty() &&
data().ReferencedProtocols.empty()) {
data().AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
-
+
// Check for duplicate protocol in class's protocol list.
// This is O(n*m). But it is extremely rare and number of protocols in
// class or its extension are very few.
- SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
+ SmallVector<ObjCProtocolDecl *, 8> ProtocolRefs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
@@ -445,7 +446,7 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
protocolExists = true;
break;
- }
+ }
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
@@ -604,7 +605,7 @@ void ObjCInterfaceDecl::startDefinition() {
allocateDefinitionData();
// Update all of the declarations with a pointer to the definition.
- for (auto RD : redecls()) {
+ for (auto *RD : redecls()) {
if (RD != this)
RD->Data = Data;
}
@@ -632,7 +633,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
return I;
}
}
-
+
ClassDecl = ClassDecl->getSuperClass();
}
return nullptr;
@@ -672,7 +673,7 @@ ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) {
/// the class, its categories, and its super classes (using a linear search).
/// When argument category "C" is specified, any implicit method found
/// in this category is ignored.
-ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
+ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
bool isInstance,
bool shallowCategoryLookup,
bool followSuper,
@@ -692,7 +693,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
// 1. Look through primary class.
if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
return MethodDecl;
-
+
// 2. Didn't find one yet - now look through categories.
for (const auto *Cat : ClassDecl->visible_categories())
if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
@@ -703,21 +704,20 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
for (const auto *I : ClassDecl->protocols())
if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
return MethodDecl;
-
+
// 4. Didn't find one yet - now look through categories' protocols
if (!shallowCategoryLookup)
for (const auto *Cat : ClassDecl->visible_categories()) {
// Didn't find one yet - look through protocols.
const ObjCList<ObjCProtocolDecl> &Protocols =
Cat->getReferencedProtocols();
- for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end(); I != E; ++I)
- if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ for (auto *Protocol : Protocols)
+ if ((MethodDecl = Protocol->lookupMethod(Sel, isInstance)))
if (C != Cat || !MethodDecl->isImplicit())
return MethodDecl;
}
-
-
+
+
if (!followSuper)
return nullptr;
@@ -742,7 +742,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
ObjCMethodDecl *Method = nullptr;
if (ObjCImplementationDecl *ImpDecl = getImplementation())
- Method = Instance ? ImpDecl->getInstanceMethod(Sel)
+ Method = Instance ? ImpDecl->getInstanceMethod(Sel)
: ImpDecl->getClassMethod(Sel);
// Look through local category implementations associated with the class.
@@ -854,7 +854,7 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C,
setParamsAndSelLocs(C, Params, SelLocs);
}
-/// \brief A definition will return its interface declaration.
+/// A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
@@ -865,27 +865,25 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
if (Redecl)
return Redecl;
- Decl *CtxD = cast<Decl>(getDeclContext());
+ auto *CtxD = cast<Decl>(getDeclContext());
if (!CtxD->isInvalidDecl()) {
- if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
+ if (auto *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
if (!ImplD->isInvalidDecl())
Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
- } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
+ } else if (auto *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
if (!ImplD->isInvalidDecl())
Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
- } else if (ObjCImplementationDecl *ImplD =
- dyn_cast<ObjCImplementationDecl>(CtxD)) {
+ } else if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
if (!IFD->isInvalidDecl())
Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
- } else if (ObjCCategoryImplDecl *CImplD =
- dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
+ } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
if (!CatD->isInvalidDecl())
Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
@@ -908,15 +906,14 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
}
ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
- Decl *CtxD = cast<Decl>(getDeclContext());
+ auto *CtxD = cast<Decl>(getDeclContext());
- if (ObjCImplementationDecl *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
+ if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
isInstanceMethod()))
return MD;
- } else if (ObjCCategoryImplDecl *CImplD =
- dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
+ } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
isInstanceMethod()))
@@ -941,7 +938,7 @@ SourceLocation ObjCMethodDecl::getLocEnd() const {
}
ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
- ObjCMethodFamily family = static_cast<ObjCMethodFamily>(Family);
+ auto family = static_cast<ObjCMethodFamily>(Family);
if (family != static_cast<unsigned>(InvalidObjCMethodFamily))
return family;
@@ -993,12 +990,12 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
if (!isInstanceMethod())
family = OMF_None;
break;
-
+
case OMF_initialize:
if (isInstanceMethod() || !getReturnType()->isVoidType())
family = OMF_None;
break;
-
+
case OMF_performSelector:
if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
family = OMF_None;
@@ -1024,7 +1021,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
}
}
break;
-
+
}
// Cache the result.
@@ -1099,11 +1096,11 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
}
ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
+ if (auto *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
return ID;
- if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
+ if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
return CD->getClassInterface();
- if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
+ if (auto *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
return IMD->getClassInterface();
if (isa<ObjCProtocolDecl>(getDeclContext()))
return nullptr;
@@ -1138,11 +1135,10 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
if (!Container)
return;
- // In categories look for overriden methods from protocols. A method from
- // category is not "overriden" since it is considered as the "same" method
+ // In categories look for overridden methods from protocols. A method from
+ // category is not "overridden" since it is considered as the "same" method
// (same USR) as the one from the interface.
- if (const ObjCCategoryDecl *
- Category = dyn_cast<ObjCCategoryDecl>(Container)) {
+ if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
// Check whether we have a matching method at this category but only if we
// are at the super class level.
if (MovedToSuper)
@@ -1174,13 +1170,12 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
return;
}
- if (const ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
+ if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
for (const auto *P : Protocol->protocols())
CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
}
- if (const ObjCInterfaceDecl *
- Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
+ if (const auto *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
for (const auto *P : Interface->protocols())
CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
@@ -1204,12 +1199,12 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
SmallVectorImpl<const ObjCMethodDecl *> &overridden) {
assert(Method->isOverriding());
- if (const ObjCProtocolDecl *
- ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
+ if (const auto *ProtD =
+ dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
CollectOverriddenMethods(ProtD, Method, overridden);
- } else if (const ObjCImplDecl *
- IMD = dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
+ } else if (const auto *IMD =
+ dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
const ObjCInterfaceDecl *ID = IMD->getClassInterface();
if (!ID)
return;
@@ -1221,8 +1216,8 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
Method = IFaceMeth;
CollectOverriddenMethods(ID, Method, overridden);
- } else if (const ObjCCategoryDecl *
- CatD = dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
+ } else if (const auto *CatD =
+ dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
const ObjCInterfaceDecl *ID = CatD->getClassInterface();
if (!ID)
return;
@@ -1265,7 +1260,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
return nullptr;
if (isPropertyAccessor()) {
- const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
+ const auto *Container = cast<ObjCContainerDecl>(getParent());
bool IsGetter = (NumArgs == 0);
bool IsInstance = isInstanceMethod();
@@ -1328,11 +1323,9 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
OverridesTy Overrides;
getOverriddenMethods(Overrides);
- for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
- I != E; ++I) {
- if (const ObjCPropertyDecl *Prop = (*I)->findPropertyDecl(false))
+ for (const auto *Override : Overrides)
+ if (const ObjCPropertyDecl *Prop = Override->findPropertyDecl(false))
return Prop;
- }
return nullptr;
}
@@ -1422,7 +1415,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc,
bool isInternal){
- ObjCInterfaceDecl *Result = new (C, DC)
+ auto *Result = new (C, DC)
ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
isInternal);
Result->Data.setInt(!C.getLangOpts().Modules);
@@ -1432,12 +1425,9 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
unsigned ID) {
- ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr,
- SourceLocation(),
- nullptr,
- nullptr,
- SourceLocation(),
- nullptr, false);
+ auto *Result = new (C, ID)
+ ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr,
+ SourceLocation(), nullptr, false);
Result->Data.setInt(!C.getLangOpts().Modules);
return Result;
}
@@ -1451,11 +1441,11 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
redeclarable_base(C) {
setPreviousDecl(PrevDecl);
-
+
// Copy the 'data' pointer over.
if (PrevDecl)
Data = PrevDecl->Data;
-
+
setImplicit(IsInternal);
setTypeParamList(typeParamList);
@@ -1469,9 +1459,9 @@ void ObjCInterfaceDecl::LoadExternalDefinition() const {
}
void ObjCInterfaceDecl::setExternallyCompleted() {
- assert(getASTContext().getExternalSource() &&
+ assert(getASTContext().getExternalSource() &&
"Class can't be externally completed without an external source");
- assert(hasDefinition() &&
+ assert(hasDefinition() &&
"Forward declarations can't be externally completed");
data().ExternallyCompleted = true;
}
@@ -1495,7 +1485,7 @@ bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
StringRef
ObjCInterfaceDecl::getObjCRuntimeNameAsString() const {
- if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
+ if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
return ObjCRTName->getMetadataName();
return getName();
@@ -1506,7 +1496,7 @@ ObjCImplementationDecl::getObjCRuntimeNameAsString() const {
if (ObjCInterfaceDecl *ID =
const_cast<ObjCImplementationDecl*>(this)->getClassInterface())
return ID->getObjCRuntimeNameAsString();
-
+
return getName();
}
@@ -1514,11 +1504,11 @@ ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
if (const ObjCInterfaceDecl *Def = getDefinition()) {
if (data().ExternallyCompleted)
LoadExternalDefinition();
-
+
return getASTContext().getObjCImplementation(
const_cast<ObjCInterfaceDecl*>(Def));
}
-
+
// FIXME: Should make sure no callers ever do this.
return nullptr;
}
@@ -1586,7 +1576,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
// cached and complete!
if (!data().IvarListMissingImplementation)
return data().IvarList;
-
+
if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
data().IvarListMissingImplementation = false;
if (!ImplDecl->ivar_empty()) {
@@ -1603,7 +1593,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
curIvar->setNextIvar(IV);
curIvar = IV;
}
-
+
if (!layout.empty()) {
// Order synthesized ivars by their size.
std::stable_sort(layout.begin(), layout.end());
@@ -1669,7 +1659,7 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
bool RHSIsQualifiedID) {
if (!hasDefinition())
return false;
-
+
ObjCInterfaceDecl *IDecl = this;
// 1st, look up the class.
for (auto *PI : IDecl->protocols()){
@@ -1731,9 +1721,9 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
"Invalid ivar decl context!");
// Once a new ivar is created in any of class/class-extension/implementation
// decl contexts, the previously built IvarList must be rebuilt.
- ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
+ auto *ID = dyn_cast<ObjCInterfaceDecl>(DC);
if (!ID) {
- if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC))
+ if (auto *IM = dyn_cast<ObjCImplementationDecl>(DC))
ID = IM->getClassInterface();
else
ID = cast<ObjCCategoryDecl>(DC)->getClassInterface();
@@ -1752,7 +1742,7 @@ ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
}
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
- const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext());
+ const auto *DC = cast<ObjCContainerDecl>(getDeclContext());
switch (DC->getKind()) {
default:
@@ -1762,7 +1752,7 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
// Ivars can only appear in class extension categories.
case ObjCCategory: {
- const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
+ const auto *CD = cast<ObjCCategoryDecl>(DC);
assert(CD->IsClassExtension() && "invalid container for ivar!");
return CD->getClassInterface();
}
@@ -1822,7 +1812,7 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation nameLoc,
SourceLocation atStartLoc,
ObjCProtocolDecl *PrevDecl) {
- ObjCProtocolDecl *Result =
+ auto *Result =
new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl);
Result->Data.setInt(!C.getLangOpts().Modules);
return Result;
@@ -1879,9 +1869,9 @@ void ObjCProtocolDecl::allocateDefinitionData() {
void ObjCProtocolDecl::startDefinition() {
allocateDefinitionData();
-
+
// Update all of the declarations with a pointer to the definition.
- for (auto RD : redecls())
+ for (auto *RD : redecls())
RD->Data = this->Data;
}
@@ -1923,7 +1913,7 @@ void ObjCProtocolDecl::collectInheritedProtocolProperties(
StringRef
ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
- if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
+ if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
return ObjCRTName->getMetadataName();
return getName();
@@ -1936,7 +1926,7 @@ ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
void ObjCCategoryDecl::anchor() {}
ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
- SourceLocation ClassNameLoc,
+ SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
@@ -1957,7 +1947,7 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc) {
- ObjCCategoryDecl *CatDecl =
+ auto *CatDecl =
new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
IDecl, typeParamList, IvarLBraceLoc,
IvarRBraceLoc);
@@ -1995,11 +1985,10 @@ void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
if (!TPL)
return;
// Set the declaration context of each of the type parameters.
- for (auto typeParam : *TypeParamList)
+ for (auto *typeParam : *TypeParamList)
typeParam->setDeclContext(this);
}
-
//===----------------------------------------------------------------------===//
// ObjCCategoryImplDecl
//===----------------------------------------------------------------------===//
@@ -2019,7 +2008,7 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
atStartLoc, CategoryNameLoc);
}
-ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
+ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
SourceLocation(), SourceLocation(),
@@ -2044,13 +2033,11 @@ void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
ASTContext &Ctx = getASTContext();
- if (ObjCImplementationDecl *ImplD
- = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
+ if (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
if (IFace)
Ctx.setObjCImplementation(IFace, ImplD);
- } else if (ObjCCategoryImplDecl *ImplD =
- dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
+ } else if (auto *ImplD = dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
Ctx.setObjCImplementation(CD, ImplD);
}
@@ -2139,8 +2126,7 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
unsigned numInitializers) {
if (numInitializers > 0) {
NumIvarInitializers = numInitializers;
- CXXCtorInitializer **ivarInitializers =
- new (C) CXXCtorInitializer*[NumIvarInitializers];
+ auto **ivarInitializers = new (C) CXXCtorInitializer*[NumIvarInitializers];
memcpy(ivarInitializers, initializers,
numInitializers * sizeof(CXXCtorInitializer*));
IvarInitializers = ivarInitializers;
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp
index 95e44acca032..f5c3599ef6c6 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements OMPThreadPrivateDecl, OMPCapturedExprDecl
+/// This file implements OMPThreadPrivateDecl, OMPCapturedExprDecl
/// classes.
///
//===----------------------------------------------------------------------===//
@@ -92,13 +92,14 @@ void OMPCapturedExprDecl::anchor() {}
OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id, QualType T,
SourceLocation StartLoc) {
- return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T, StartLoc);
+ return new (C, DC) OMPCapturedExprDecl(
+ C, DC, Id, T, C.getTrivialTypeSourceInfo(T), StartLoc);
}
OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID)
- OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), SourceLocation());
+ return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType(),
+ /*TInfo=*/nullptr, SourceLocation());
}
SourceRange OMPCapturedExprDecl::getSourceRange() const {
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index b792c5920a55..55485611054c 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -44,7 +44,7 @@ namespace {
///
/// \param Quals The Objective-C declaration qualifiers.
/// \param T The type to print.
- void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
+ void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
QualType T);
void PrintObjCTypeParams(ObjCTypeParamList *Params);
@@ -128,9 +128,7 @@ static QualType GetBaseType(QualType T) {
// FIXME: This should be on the Type class!
QualType BaseType = T;
while (!BaseType->isSpecifierType()) {
- if (isa<TypedefType>(BaseType))
- break;
- else if (const PointerType* PTy = BaseType->getAs<PointerType>())
+ if (const PointerType *PTy = BaseType->getAs<PointerType>())
BaseType = PTy->getPointeeType();
else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
BaseType = BPy->getPointeeType();
@@ -144,8 +142,11 @@ static QualType GetBaseType(QualType T) {
BaseType = RTy->getPointeeType();
else if (const AutoType *ATy = BaseType->getAs<AutoType>())
BaseType = ATy->getDeducedType();
+ else if (const ParenType *PTy = BaseType->getAs<ParenType>())
+ BaseType = PTy->desugar();
else
- llvm_unreachable("Unknown declarator!");
+ // This must be a syntax error.
+ break;
}
return BaseType;
}
@@ -195,7 +196,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
const DeclContext *DC = this;
while (!DC->isTranslationUnit())
DC = DC->getParent();
-
+
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
@@ -214,6 +215,8 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) {
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
for (auto *A : Attrs) {
+ if (A->isInherited() || A->isImplicit())
+ continue;
switch (A->getKind()) {
#define ATTR(X)
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
@@ -372,21 +375,23 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
!isa<ClassTemplateSpecializationDecl>(DC))
continue;
- // The next bits of code handles stuff like "struct {int x;} a,b"; we're
+ // The next bits of code handle stuff like "struct {int x;} a,b"; we're
// forced to merge the declarations because there's no other way to
- // refer to the struct in question. This limited merging is safe without
- // a bunch of other checks because it only merges declarations directly
- // referring to the tag, not typedefs.
+ // refer to the struct in question. When that struct is named instead, we
+ // also need to merge to avoid splitting off a stand-alone struct
+ // declaration that produces the warning ext_no_declarators in some
+ // contexts.
+ //
+ // This limited merging is safe without a bunch of other checks because it
+ // only merges declarations directly referring to the tag, not typedefs.
//
// Check whether the current declaration should be grouped with a previous
- // unnamed struct.
+ // non-free-standing tag declaration.
QualType CurDeclType = getDeclType(*D);
if (!Decls.empty() && !CurDeclType.isNull()) {
QualType BaseType = GetBaseType(CurDeclType);
- if (!BaseType.isNull() && isa<ElaboratedType>(BaseType))
- BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
- if (!BaseType.isNull() && isa<TagType>(BaseType) &&
- cast<TagType>(BaseType)->getDecl() == Decls[0]) {
+ if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) &&
+ cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) {
Decls.push_back(*D);
continue;
}
@@ -396,9 +401,9 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (!Decls.empty())
ProcessDeclGroup(Decls);
- // If the current declaration is an unnamed tag type, save it
+ // If the current declaration is not a free standing declaration, save it
// so we can merge it with the subsequent declaration(s) using it.
- if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
+ if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) {
Decls.push_back(*D);
continue;
}
@@ -477,7 +482,7 @@ void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
if (!Policy.SuppressSpecifiers) {
Out << "typedef ";
-
+
if (D->isModulePrivate())
Out << "__module_private__ ";
}
@@ -495,14 +500,17 @@ void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
Out << "__module_private__ ";
- Out << "enum ";
+ Out << "enum";
if (D->isScoped()) {
if (D->isScopedUsingClassTag())
- Out << "class ";
+ Out << " class";
else
- Out << "struct ";
+ Out << " struct";
}
- Out << *D;
+
+ prettyPrintAttributes(D);
+
+ Out << ' ' << *D;
if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11)
Out << " : " << D->getIntegerType().stream(Policy);
@@ -512,7 +520,6 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
VisitDeclContext(D);
Indent() << "}";
}
- prettyPrintAttributes(D);
}
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
@@ -634,7 +641,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
Proto += ")";
-
+
if (FT) {
if (FT->isConst())
Proto += " const";
@@ -659,7 +666,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto += " throw(";
if (FT->getExceptionSpecType() == EST_MSAny)
Proto += "...";
- else
+ else
for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
if (I)
Proto += ", ";
@@ -669,7 +676,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto += ")";
} else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
Proto += " noexcept";
- if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
+ if (isComputedNoexcept(FT->getExceptionSpecType())) {
Proto += "(";
llvm::raw_string_ostream EOut(Proto);
FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
@@ -1084,6 +1091,10 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
printTemplateParameters(FD->getTemplateParameterList(I));
}
VisitRedeclarableTemplateDecl(D);
+ // Declare target attribute is special one, natural spelling for the pragma
+ // assumes "ending" construct so print it here.
+ if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
+ Out << "#pragma omp end declare target\n";
// Never print "instantiations" for deduction guides (they don't really
// have them).
@@ -1134,8 +1145,8 @@ void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
// Objective-C declarations
//----------------------------------------------------------------------------
-void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
- Decl::ObjCDeclQualifier Quals,
+void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
+ Decl::ObjCDeclQualifier Quals,
QualType T) {
Out << '(';
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
@@ -1154,7 +1165,7 @@ void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
if (auto nullability = AttributedType::stripOuterNullability(T))
Out << getNullabilitySpelling(*nullability, true) << ' ';
}
-
+
Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
Out << ')';
}
@@ -1209,7 +1220,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (lastPos != 0)
Out << " ";
Out << name.substr(lastPos, pos - lastPos) << ':';
- PrintObjCMethodType(OMD->getASTContext(),
+ PrintObjCMethodType(OMD->getASTContext(),
PI->getObjCDeclQualifier(),
PI->getType());
Out << *PI;
@@ -1221,7 +1232,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isVariadic())
Out << ", ...";
-
+
prettyPrintAttributes(OMD);
if (OMD->getBody() && !Policy.TerseOutput) {
@@ -1241,7 +1252,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
Out << "@implementation " << I << " : " << *SID;
else
Out << "@implementation " << I;
-
+
if (OID->ivar_size() > 0) {
Out << "{\n";
eolnOut = true;
@@ -1283,7 +1294,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
if (auto TypeParams = OID->getTypeParamListAsWritten()) {
PrintObjCTypeParams(TypeParams);
}
-
+
if (SID)
Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
@@ -1362,7 +1373,7 @@ void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
Indentation -= Policy.Indentation;
Out << "}\n";
}
-
+
VisitDeclContext(PID, false);
Out << "@end";
@@ -1441,7 +1452,7 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
Out << (first ? ' ' : ',') << "atomic";
first = false;
}
-
+
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_nullability) {
if (auto nullability = AttributedType::stripOuterNullability(T)) {
@@ -1526,7 +1537,7 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
E = D->varlist_end();
I != E; ++I) {
Out << (I == D->varlist_begin() ? '(' : ',');
- NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
+ NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();
ND->printQualifiedName(Out);
}
Out << ")";
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
index a7949b310cef..848427e7f9d9 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -56,11 +57,11 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
begin()[Idx] = P;
if (!P->isTemplateParameterPack()) {
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
if (NTTP->getType()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
- if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
@@ -116,13 +117,11 @@ unsigned TemplateParameterList::getMinRequiredArguments() const {
unsigned TemplateParameterList::getDepth() const {
if (size() == 0)
return 0;
-
+
const NamedDecl *FirstParm = getParam(0);
- if (const TemplateTypeParmDecl *TTP
- = dyn_cast<TemplateTypeParmDecl>(FirstParm))
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(FirstParm))
return TTP->getDepth();
- else if (const NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
+ else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
return NTTP->getDepth();
else
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
@@ -133,7 +132,7 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
for (NamedDecl *P : *Params) {
P->setDeclContext(Owner);
- if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
}
}
@@ -258,7 +257,7 @@ FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
RedeclarableTemplateDecl::CommonBase *
FunctionTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -318,8 +317,8 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
}
- ConstrainedTemplateDeclInfo *const CTDI = new (C) ConstrainedTemplateDeclInfo;
- ClassTemplateDecl *const New =
+ auto *const CTDI = new (C) ConstrainedTemplateDeclInfo;
+ auto *const New =
new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl);
New->setAssociatedConstraints(AssociatedConstraints);
return New;
@@ -339,17 +338,17 @@ llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
ClassTemplateDecl::getSpecializations() const {
LoadLazySpecializations();
return getCommonPtr()->Specializations;
-}
+}
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
ClassTemplateDecl::getPartialSpecializations() {
LoadLazySpecializations();
return getCommonPtr()->PartialSpecializations;
-}
+}
RedeclarableTemplateDecl::CommonBase *
ClassTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -428,11 +427,11 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
return CommonPtr->InjectedClassNameType;
// C++0x [temp.dep.type]p2:
- // The template argument list of a primary template is a template argument
+ // The template argument list of a primary template is a template argument
// list in which the nth template argument has the value of the nth template
- // parameter of the class template. If the nth template parameter is a
- // template parameter pack (14.5.3), the nth template argument is a pack
- // expansion (14.5.3) whose pattern is the name of the template parameter
+ // parameter of the class template. If the nth template parameter is a
+ // template parameter pack (14.5.3), the nth template argument is a pack
+ // expansion (14.5.3) whose pattern is the name of the template parameter
// pack.
ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
@@ -453,8 +452,8 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation KeyLoc, SourceLocation NameLoc,
unsigned D, unsigned P, IdentifierInfo *Id,
bool Typename, bool ParameterPack) {
- TemplateTypeParmDecl *TTPDecl =
- new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
+ auto *TTPDecl =
+ new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
TTPDecl->setTypeForDecl(TTPType.getTypePtr());
return TTPDecl;
@@ -709,7 +708,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
ClassTemplateSpecializationDecl *PrevDecl) {
- ClassTemplateSpecializationDecl *Result =
+ auto *Result =
new (Context, DC) ClassTemplateSpecializationDecl(
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, PrevDecl);
@@ -722,7 +721,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- ClassTemplateSpecializationDecl *Result =
+ auto *Result =
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
Result->MayHaveOutOfDateDef = false;
return Result;
@@ -732,7 +731,7 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
+ const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
@@ -744,8 +743,8 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic(
ClassTemplateDecl *
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
return SpecializedTemplate.get<ClassTemplateDecl*>();
}
@@ -770,7 +769,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
// uses ExplicitInfo to record the TypeAsWritten, but the source
// locations should be retrieved from the instantiation pattern.
using CTPSDecl = ClassTemplatePartialSpecializationDecl;
- CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
+ auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this));
CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
assert(inst_from != nullptr);
return inst_from->getSourceRange();
@@ -782,9 +781,9 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
inst_from = getInstantiatedFrom();
if (inst_from.isNull())
return getSpecializedTemplate()->getSourceRange();
- if (ClassTemplateDecl *ctd = inst_from.dyn_cast<ClassTemplateDecl*>())
+ if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>())
return ctd->getSourceRange();
- return inst_from.get<ClassTemplatePartialSpecializationDecl*>()
+ return inst_from.get<ClassTemplatePartialSpecializationDecl *>()
->getSourceRange();
}
}
@@ -826,7 +825,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,
const ASTTemplateArgumentListInfo *ASTArgInfos =
ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
- ClassTemplatePartialSpecializationDecl *Result = new (Context, DC)
+ auto *Result = new (Context, DC)
ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc,
Params, SpecializedTemplate, Args,
ASTArgInfos, PrevDecl);
@@ -840,8 +839,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,
ClassTemplatePartialSpecializationDecl *
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- ClassTemplatePartialSpecializationDecl *Result =
- new (C, ID) ClassTemplatePartialSpecializationDecl(C);
+ auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
Result->MayHaveOutOfDateDef = false;
return Result;
}
@@ -887,7 +885,7 @@ TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
RedeclarableTemplateDecl::CommonBase *
TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -950,7 +948,7 @@ VarTemplateDecl::getPartialSpecializations() {
RedeclarableTemplateDecl::CommonBase *
VarTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -1048,7 +1046,7 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
+ const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
@@ -1059,7 +1057,7 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
}
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
- if (SpecializedPartialSpecialization *PartialSpec =
+ if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
return SpecializedTemplate.get<VarTemplateDecl *>();
@@ -1104,7 +1102,7 @@ VarTemplatePartialSpecializationDecl::Create(
const ASTTemplateArgumentListInfo *ASTArgInfos
= ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
- VarTemplatePartialSpecializationDecl *Result =
+ auto *Result =
new (Context, DC) VarTemplatePartialSpecializationDecl(
Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
S, Args, ASTArgInfos);
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
index 31bae93c3cb5..9866d92f61eb 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
@@ -114,14 +114,14 @@ static int compareInt(unsigned A, unsigned B) {
int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
if (LHS.getNameKind() != RHS.getNameKind())
return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
-
+
switch (LHS.getNameKind()) {
case DeclarationName::Identifier: {
IdentifierInfo *LII = LHS.getAsIdentifierInfo();
IdentifierInfo *RII = RHS.getAsIdentifierInfo();
if (!LII) return RII ? -1 : 0;
if (!RII) return 1;
-
+
return LII->getName().compare(RII->getName());
}
@@ -148,7 +148,7 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
return compareInt(LN, RN);
}
-
+
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
@@ -171,7 +171,7 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::CXXLiteralOperatorName:
return LHS.getCXXLiteralIdentifier()->getName().compare(
RHS.getCXXLiteralIdentifier()->getName());
-
+
case DeclarationName::CXXUsingDirective:
return 0;
}
@@ -565,7 +565,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
if (CXXLiteralOperatorIdName *Name =
LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
return DeclarationName (Name);
-
+
CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
@@ -636,13 +636,13 @@ bool DeclarationNameInfo::isInstantiationDependent() const {
case DeclarationName::CXXUsingDirective:
case DeclarationName::CXXDeductionGuideName:
return false;
-
+
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
return TInfo->getType()->isInstantiationDependentType();
-
+
return Name.getCXXNameType()->isInstantiationDependentType();
}
llvm_unreachable("All name kinds handled.");
@@ -689,7 +689,7 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const {
llvm_unreachable("Unexpected declaration name kind");
}
-SourceLocation DeclarationNameInfo::getEndLoc() const {
+SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
case DeclarationName::CXXDeductionGuideName:
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index 7ddab9356b54..7556c76c38bd 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -108,7 +108,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
}
}
} else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
- if (BO->isPtrMemOp()) {
+ if (BO->getOpcode() == BO_PtrMemD) {
assert(BO->getRHS()->isRValue());
E = BO->getLHS();
const MemberPointerType *MPT =
@@ -137,9 +137,9 @@ bool Expr::isKnownToHaveBooleanValue() const {
// If this value has _Bool type, it is obvious 0/1.
if (E->getType()->isBooleanType()) return true;
- // If this is a non-scalar-integer type, we don't care enough to try.
+ // If this is a non-scalar-integer type, we don't care enough to try.
if (!E->getType()->isIntegralOrEnumerationType()) return false;
-
+
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
switch (UO->getOpcode()) {
case UO_Plus:
@@ -150,12 +150,12 @@ bool Expr::isKnownToHaveBooleanValue() const {
return false;
}
}
-
+
// Only look through implicit casts. If the user writes
// '(int) (a && b)' treat it as an arbitrary int.
if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
return CE->getSubExpr()->isKnownToHaveBooleanValue();
-
+
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
default: return false;
@@ -168,24 +168,24 @@ bool Expr::isKnownToHaveBooleanValue() const {
case BO_LAnd: // AND operator.
case BO_LOr: // Logical OR operator.
return true;
-
+
case BO_And: // Bitwise AND operator.
case BO_Xor: // Bitwise XOR operator.
case BO_Or: // Bitwise OR operator.
// Handle things like (x==2)|(y==12).
return BO->getLHS()->isKnownToHaveBooleanValue() &&
BO->getRHS()->isKnownToHaveBooleanValue();
-
+
case BO_Comma:
case BO_Assign:
return BO->getRHS()->isKnownToHaveBooleanValue();
}
}
-
+
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E))
return CO->getTrueExpr()->isKnownToHaveBooleanValue() &&
CO->getFalseExpr()->isKnownToHaveBooleanValue();
-
+
return false;
}
@@ -230,7 +230,7 @@ SourceLocation Expr::getExprLoc() const {
// Primary Expressions.
//===----------------------------------------------------------------------===//
-/// \brief Compute the type-, value-, and instantiation-dependence of a
+/// Compute the type-, value-, and instantiation-dependence of a
/// declaration reference
/// based on the declaration being referenced.
static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
@@ -259,9 +259,9 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
} else if (T->isInstantiationDependentType()) {
InstantiationDependent = true;
}
-
+
// (TD) - a conversion-function-id that specifies a dependent type
- if (D->getDeclName().getNameKind()
+ if (D->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName) {
QualType T = D->getDeclName().getCXXNameType();
if (T->isDependentType()) {
@@ -270,18 +270,18 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
InstantiationDependent = true;
return;
}
-
+
if (T->isInstantiationDependentType())
InstantiationDependent = true;
}
-
+
// (VD) - the name of a non-type template parameter,
if (isa<NonTypeTemplateParmDecl>(D)) {
ValueDependent = true;
InstantiationDependent = true;
return;
}
-
+
// (VD) - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent.
// (VD) - a constant with literal type and is initialized with an
@@ -302,10 +302,10 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
}
}
- // (VD) - FIXME: Missing from the standard:
- // - a member function or a static data member of the current
+ // (VD) - FIXME: Missing from the standard:
+ // - a member function or a static data member of the current
// instantiation
- if (Var->isStaticDataMember() &&
+ if (Var->isStaticDataMember() &&
Var->getDeclContext()->isDependentContext()) {
ValueDependent = true;
InstantiationDependent = true;
@@ -313,12 +313,12 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
if (TInfo->getType()->isIncompleteArrayType())
TypeDependent = true;
}
-
+
return;
}
-
- // (VD) - FIXME: Missing from the standard:
- // - a member function or a static data member of the current
+
+ // (VD) - FIXME: Missing from the standard:
+ // - a member function or a static data member of the current
// instantiation
if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
ValueDependent = true;
@@ -484,6 +484,8 @@ StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
return "__PRETTY_FUNCTION__";
case FuncSig:
return "__FUNCSIG__";
+ case LFuncSig:
+ return "L__FUNCSIG__";
case PrettyFunctionNoVirtual:
break;
}
@@ -536,7 +538,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
return Out.str();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
- if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
+ if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual &&
+ IT != FuncSig && IT != LFuncSig)
return FD->getNameAsString();
SmallString<256> Name;
@@ -561,7 +564,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
- if (IT == FuncSig) {
+ if (IT == FuncSig || IT == LFuncSig) {
switch (AFT->getCallConv()) {
case CC_C: POut << "__cdecl "; break;
case CC_X86StdCall: POut << "__stdcall "; break;
@@ -586,7 +589,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
if (FT->isVariadic()) {
if (FD->getNumParams()) POut << ", ";
POut << "...";
- } else if ((IT == FuncSig || !Context.getLangOpts().CPlusPlus) &&
+ } else if ((IT == FuncSig || IT == LFuncSig ||
+ !Context.getLangOpts().CPlusPlus) &&
!Decl->getNumParams()) {
POut << "void";
}
@@ -621,7 +625,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
llvm::raw_string_ostream TOut(TemplateParams);
for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend();
I != E; ++I) {
- const TemplateParameterList *Params
+ const TemplateParameterList *Params
= (*I)->getSpecializedTemplate()->getTemplateParameters();
const TemplateArgumentList &Args = (*I)->getTemplateArgs();
assert(Params->size() == Args.size());
@@ -634,10 +638,10 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
}
}
- FunctionTemplateSpecializationInfo *FSI
+ FunctionTemplateSpecializationInfo *FSI
= FD->getTemplateSpecializationInfo();
if (FSI && !FSI->isExplicitSpecialization()) {
- const TemplateParameterList* Params
+ const TemplateParameterList* Params
= FSI->getTemplate()->getTemplateParameters();
const TemplateArgumentList* Args = FSI->TemplateArguments;
assert(Params->size() == Args->size());
@@ -755,6 +759,36 @@ IntegerLiteral::Create(const ASTContext &C, EmptyShell Empty) {
return new (C) IntegerLiteral(Empty);
}
+FixedPointLiteral::FixedPointLiteral(const ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l,
+ unsigned Scale)
+ : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ Loc(l), Scale(Scale) {
+ assert(type->isFixedPointType() && "Illegal type in FixedPointLiteral");
+ assert(V.getBitWidth() == C.getTypeInfo(type).Width &&
+ "Fixed point type is not the correct size for constant.");
+ setValue(C, V);
+}
+
+FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C,
+ const llvm::APInt &V,
+ QualType type,
+ SourceLocation l,
+ unsigned Scale) {
+ return new (C) FixedPointLiteral(C, V, type, l, Scale);
+}
+
+std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
+ // Currently the longest decimal number that can be printed is the max for an
+ // unsigned long _Accum: 4294967295.99999999976716935634613037109375
+ // which is 43 characters.
+ SmallString<64> S;
+ FixedPointValueToString(
+ S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale, Radix);
+ return S.str();
+}
+
FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
@@ -881,7 +915,8 @@ StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C,
void *Mem =
C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
alignof(StringLiteral));
- StringLiteral *SL = new (Mem) StringLiteral(QualType());
+ StringLiteral *SL =
+ new (Mem) StringLiteral(C.adjustStringLiteralBaseType(QualType()));
SL->CharByteWidth = 0;
SL->Length = 0;
SL->NumConcatenated = NumStrs;
@@ -907,7 +942,7 @@ void StringLiteral::outputString(raw_ostream &OS) const {
// Convert UTF-16 surrogate pairs back to codepoints before rendering.
// Leave invalid surrogates alone; we'll use \x for those.
- if (getKind() == UTF16 && I != N - 1 && Char >= 0xd800 &&
+ if (getKind() == UTF16 && I != N - 1 && Char >= 0xd800 &&
Char <= 0xdbff) {
uint32_t Trail = getCodeUnit(I + 1);
if (Trail >= 0xdc00 && Trail <= 0xdfff) {
@@ -990,7 +1025,7 @@ void StringLiteral::setString(const ASTContext &C, StringRef Str,
// code unit size and endianness for the type of string.
this->Kind = Kind;
this->IsPascal = IsPascal;
-
+
CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind);
assert((Str.size()%CharByteWidth == 0)
&& "size of data must be multiple of CharByteWidth");
@@ -1057,7 +1092,7 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
while (1) {
assert(TokNo < getNumConcatenated() && "Invalid byte number!");
SourceLocation StrTokLoc = getStrTokenLoc(TokNo);
-
+
// Get the spelling of the string so that we can get the data that makes up
// the string literal, not the identifier for the macro it is potentially
// expanded through.
@@ -1077,17 +1112,17 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
}
const char *StrData = Buffer.data()+LocInfo.second;
-
+
// Create a lexer starting at the beginning of this token.
Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), Features,
Buffer.begin(), StrData, Buffer.end());
Token TheTok;
TheLexer.LexFromRawLexer(TheTok);
-
+
// Use the StringLiteralParser to compute the length of the string in bytes.
StringLiteralParser SLP(TheTok, SM, Features, Target);
unsigned TokNumBytes = SLP.GetStringLength();
-
+
// If the byte is in this token, return the location of the byte.
if (ByteNo < TokNumBytes ||
(ByteNo == TokNumBytes && TokNo == getNumConcatenated() - 1)) {
@@ -1223,12 +1258,12 @@ Decl *CallExpr::getCalleeDecl() {
Decl *Expr::getReferencedDeclOfCallee() {
Expr *CEE = IgnoreParenImpCasts();
-
+
while (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
CEE = NTTP->getReplacement()->IgnoreParenCasts();
}
-
+
// If we're calling a dereference, look at the pointer instead.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
if (BO->isPtrMemOp())
@@ -1344,7 +1379,7 @@ SourceLocation CallExpr::getLocEnd() const {
OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
SourceLocation OperatorLoc,
- TypeSourceInfo *tsi,
+ TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs,
SourceLocation RParenLoc) {
@@ -1367,17 +1402,17 @@ OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
SourceLocation RParenLoc)
: Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false,
+ /*TypeDependent=*/false,
/*ValueDependent=*/tsi->getType()->isDependentType(),
tsi->getType()->isInstantiationDependentType(),
tsi->getType()->containsUnexpandedParameterPack()),
- OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
+ OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
NumComps(comps.size()), NumExprs(exprs.size())
{
for (unsigned i = 0; i != comps.size(); ++i) {
setComponent(i, comps[i]);
}
-
+
for (unsigned i = 0; i != exprs.size(); ++i) {
if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
ExprBits.ValueDependent = true;
@@ -1392,7 +1427,7 @@ IdentifierInfo *OffsetOfNode::getFieldName() const {
assert(getKind() == Field || getKind() == Identifier);
if (getKind() == Field)
return getField()->getIdentifier();
-
+
return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask);
}
@@ -1462,11 +1497,11 @@ MemberExpr *MemberExpr::Create(
E->setValueDependent(true);
E->setTypeDependent(true);
E->setInstantiationDependent(true);
- }
- else if (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
+ }
+ else if (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
E->setInstantiationDependent(true);
-
+
E->HasQualifierOrFoundDecl = true;
MemberExprNameQualifier *NQ =
@@ -1547,9 +1582,9 @@ bool CastExpr::CastConsistency() const {
// Otherwise, we should only have block and ObjC pointer casts
// here if they stay within the type kind.
if (!getType()->isPointerType()) {
- assert(getType()->isObjCObjectPointerType() ==
+ assert(getType()->isObjCObjectPointerType() ==
getSubExpr()->getType()->isObjCObjectPointerType());
- assert(getType()->isBlockPointerType() ==
+ assert(getType()->isBlockPointerType() ==
getSubExpr()->getType()->isBlockPointerType());
}
goto CheckNoBasePath;
@@ -1633,8 +1668,8 @@ bool CastExpr::CastConsistency() const {
return true;
}
-const char *CastExpr::getCastKindName() const {
- switch (getCastKind()) {
+const char *CastExpr::getCastKindName(CastKind CK) {
+ switch (CK) {
#define CAST_OPERATION(Name) case CK_##Name: return #Name;
#include "clang/AST/OperationKinds.def"
}
@@ -1642,23 +1677,22 @@ const char *CastExpr::getCastKindName() const {
}
namespace {
- Expr *skipImplicitTemporary(Expr *expr) {
+ const Expr *skipImplicitTemporary(const Expr *E) {
// Skip through reference binding to temporary.
- if (MaterializeTemporaryExpr *Materialize
- = dyn_cast<MaterializeTemporaryExpr>(expr))
- expr = Materialize->GetTemporaryExpr();
+ if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = Materialize->GetTemporaryExpr();
// Skip any temporary bindings; they're implicit.
- if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr))
- expr = Binder->getSubExpr();
+ if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = Binder->getSubExpr();
- return expr;
+ return E;
}
}
Expr *CastExpr::getSubExprAsWritten() {
- Expr *SubExpr = nullptr;
- CastExpr *E = this;
+ const Expr *SubExpr = nullptr;
+ const CastExpr *E = this;
do {
SubExpr = skipImplicitTemporary(E->getSubExpr());
@@ -1671,15 +1705,48 @@ Expr *CastExpr::getSubExprAsWritten() {
assert((isa<CXXMemberCallExpr>(SubExpr) ||
isa<BlockExpr>(SubExpr)) &&
"Unexpected SubExpr for CK_UserDefinedConversion.");
- if (isa<CXXMemberCallExpr>(SubExpr))
- SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
+ if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SubExpr))
+ SubExpr = MCE->getImplicitObjectArgument();
}
-
+
// If the subexpression we're left with is an implicit cast, look
// through that, too.
- } while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
-
- return SubExpr;
+ } while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
+
+ return const_cast<Expr*>(SubExpr);
+}
+
+NamedDecl *CastExpr::getConversionFunction() const {
+ const Expr *SubExpr = nullptr;
+
+ for (const CastExpr *E = this; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) {
+ SubExpr = skipImplicitTemporary(E->getSubExpr());
+
+ if (E->getCastKind() == CK_ConstructorConversion)
+ return cast<CXXConstructExpr>(SubExpr)->getConstructor();
+
+ if (E->getCastKind() == CK_UserDefinedConversion) {
+ if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SubExpr))
+ return MCE->getMethodDecl();
+ }
+ }
+
+ return nullptr;
+}
+
+CastExpr::BasePathSizeTy *CastExpr::BasePathSize() {
+ assert(!path_empty());
+ switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return static_cast<Type *>(this) \
+ ->getTrailingObjects<CastExpr::BasePathSizeTy>();
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+ default:
+ llvm_unreachable("non-cast expressions not possible here");
+ }
}
CXXBaseSpecifier **CastExpr::path_buffer() {
@@ -1720,7 +1787,9 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
const CXXCastPath *BasePath,
ExprValueKind VK) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
ImplicitCastExpr *E =
new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
if (PathSize)
@@ -1731,7 +1800,9 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
}
@@ -1742,7 +1813,9 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
TypeSourceInfo *WrittenTy,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
CStyleCastExpr *E =
new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R);
if (PathSize)
@@ -1753,7 +1826,9 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
}
@@ -1881,7 +1956,7 @@ InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
if (initExprs[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
}
-
+
InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end());
}
@@ -1971,12 +2046,12 @@ SourceLocation InitListExpr::getLocStart() const {
if (Beg.isInvalid()) {
// Find the first non-null initializer.
for (InitExprsTy::const_iterator I = InitExprs.begin(),
- E = InitExprs.end();
+ E = InitExprs.end();
I != E; ++I) {
if (Stmt *S = *I) {
Beg = S->getLocStart();
break;
- }
+ }
}
}
return Beg;
@@ -2027,7 +2102,7 @@ Stmt *BlockExpr::getBody() {
/// be warned about if the result is unused. If so, fill in Loc and Ranges
/// with location to warn on and the source range[s] to report with the
/// warning.
-bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
+bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
SourceRange &R1, SourceRange &R2,
ASTContext &Ctx) const {
// Don't warn if the expr is type dependent. The type could end up
@@ -2049,6 +2124,10 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
+ case CoawaitExprClass:
+ case CoyieldExprClass:
+ return cast<CoroutineSuspendExpr>(this)->getResumeExpr()->
+ isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case ChooseExprClass:
return cast<ChooseExpr>(this)->getChosenSubExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
@@ -2380,7 +2459,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case DeclRefExprClass: {
const Decl *D = cast<DeclRefExpr>(E)->getDecl();
-
+
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasGlobalStorage())
return true;
@@ -2470,7 +2549,7 @@ Expr *Expr::IgnoreParenCasts() {
E = P->getSubExpr();
continue;
}
- if (MaterializeTemporaryExpr *Materialize
+ if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
@@ -2479,7 +2558,7 @@ Expr *Expr::IgnoreParenCasts() {
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
- }
+ }
return E;
}
}
@@ -2518,7 +2597,7 @@ Expr *Expr::IgnoreParenLValueCasts() {
E = P->getSubExpr();
continue;
}
- } else if (MaterializeTemporaryExpr *Materialize
+ } else if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
@@ -2557,7 +2636,7 @@ Expr *Expr::IgnoreParenImpCasts() {
E = P->getSubExpr();
continue;
}
- if (MaterializeTemporaryExpr *Materialize
+ if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
@@ -2612,7 +2691,7 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
E = NTTP->getReplacement();
continue;
}
-
+
return E;
}
}
@@ -2624,11 +2703,11 @@ bool Expr::isDefaultArgument() const {
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExprAsWritten();
-
+
return isa<CXXDefaultArgExpr>(E);
}
-/// \brief Skip over any no-op casts and any temporary-binding
+/// Skip over any no-op casts and any temporary-binding
/// expressions.
static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
@@ -2700,43 +2779,43 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const {
bool Expr::isImplicitCXXThis() const {
const Expr *E = this;
-
+
// Strip away parentheses and casts we don't care about.
while (true) {
if (const ParenExpr *Paren = dyn_cast<ParenExpr>(E)) {
E = Paren->getSubExpr();
continue;
}
-
+
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp ||
ICE->getCastKind() == CK_LValueToRValue ||
- ICE->getCastKind() == CK_DerivedToBase ||
+ ICE->getCastKind() == CK_DerivedToBase ||
ICE->getCastKind() == CK_UncheckedDerivedToBase) {
E = ICE->getSubExpr();
continue;
}
}
-
+
if (const UnaryOperator* UnOp = dyn_cast<UnaryOperator>(E)) {
if (UnOp->getOpcode() == UO_Extension) {
E = UnOp->getSubExpr();
continue;
}
}
-
+
if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = M->GetTemporaryExpr();
continue;
}
-
+
break;
}
-
+
if (const CXXThisExpr *This = dyn_cast<CXXThisExpr>(E))
return This->isImplicit();
-
+
return false;
}
@@ -2917,8 +2996,20 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
return false;
}
+bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const {
+ const FunctionDecl* FD = getDirectCallee();
+ if (!FD || (FD->getBuiltinID() != Builtin::BI__assume &&
+ FD->getBuiltinID() != Builtin::BI__builtin_assume))
+ return false;
+
+ const Expr* Arg = getArg(0);
+ bool ArgVal;
+ return !Arg->isValueDependent() &&
+ Arg->EvaluateAsBooleanCondition(ArgVal, Ctx) && !ArgVal;
+}
+
namespace {
- /// \brief Look for any side effects within a Stmt.
+ /// Look for any side effects within a Stmt.
class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> {
typedef ConstEvaluatedExprVisitor<SideEffectFinder> Inherited;
const bool IncludePossibleEffects;
@@ -2974,6 +3065,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ObjCIvarRefExprClass:
case PredefinedExprClass:
case IntegerLiteralClass:
+ case FixedPointLiteralClass:
case FloatingLiteralClass:
case ImaginaryLiteralClass:
case StringLiteralClass:
@@ -3214,17 +3306,17 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
}
namespace {
- /// \brief Look for a call to a non-trivial function within an expression.
+ /// Look for a call to a non-trivial function within an expression.
class NonTrivialCallFinder : public ConstEvaluatedExprVisitor<NonTrivialCallFinder>
{
typedef ConstEvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
bool NonTrivial;
-
+
public:
explicit NonTrivialCallFinder(const ASTContext &Context)
: Inherited(Context), NonTrivial(false) { }
-
+
bool hasNonTrivialCall() const { return NonTrivial; }
void VisitCallExpr(const CallExpr *E) {
@@ -3236,7 +3328,7 @@ namespace {
return;
}
}
-
+
NonTrivial = true;
}
@@ -3246,7 +3338,7 @@ namespace {
Inherited::VisitStmt(E);
return;
}
-
+
NonTrivial = true;
}
@@ -3255,7 +3347,7 @@ namespace {
Inherited::VisitStmt(E);
return;
}
-
+
NonTrivial = true;
}
};
@@ -3264,10 +3356,10 @@ namespace {
bool Expr::hasNonTrivialCall(const ASTContext &Ctx) const {
NonTrivialCallFinder Finder(Ctx);
Finder.Visit(this);
- return Finder.hasNonTrivialCall();
+ return Finder.hasNonTrivialCall();
}
-/// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null
+/// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null
/// pointer constant or not, as well as the specific kind of constant detected.
/// Null pointer constants can be integer constant expressions with the
/// value zero, casts of zero to void*, nullptr (C++0X), or __null
@@ -3285,7 +3377,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return NPCK_ZeroExpression;
else
return NPCK_NotNull;
-
+
case NPC_ValueDependentIsNotNull:
return NPCK_NotNull;
}
@@ -3341,7 +3433,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
} else if (isa<GNUNullExpr>(this)) {
// The GNU __null extension is always a null pointer constant.
return NPCK_GNUNull;
- } else if (const MaterializeTemporaryExpr *M
+ } else if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(this)) {
return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) {
@@ -3362,7 +3454,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return ILE->getInit(0)->isNullPointerConstant(Ctx, NPC);
}
// This expression must be an integer type.
- if (!getType()->isIntegerType() ||
+ if (!getType()->isIntegerType() ||
(Ctx.getLangOpts().CPlusPlus && getType()->isEnumeralType()))
return NPCK_NotNull;
@@ -3390,7 +3482,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return NPCK_ZeroExpression;
}
-/// \brief If this expression is an l-value for an Objective C
+/// If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *Expr::getObjCProperty() const {
const Expr *E = this;
@@ -3446,10 +3538,11 @@ FieldDecl *Expr::getSourceBitField() {
if (Field->isBitField())
return Field;
- if (ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E))
- if (FieldDecl *Ivar = dyn_cast<FieldDecl>(IvarRef->getDecl()))
- if (Ivar->isBitField())
- return Ivar;
+ if (ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
+ FieldDecl *Ivar = IvarRef->getDecl();
+ if (Ivar->isBitField())
+ return Ivar;
+ }
if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl()))
@@ -3479,7 +3572,7 @@ FieldDecl *Expr::getSourceBitField() {
bool Expr::refersToVectorElement() const {
// FIXME: Why do we not just look at the ObjectKind here?
const Expr *E = this->IgnoreParens();
-
+
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getValueKind() != VK_RValue &&
ICE->getCastKind() == CK_NoOp)
@@ -3487,7 +3580,7 @@ bool Expr::refersToVectorElement() const {
else
break;
}
-
+
if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E))
return ASE->getBase()->getType()->isVectorType();
@@ -3582,7 +3675,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args,
QualType Type, SourceLocation BLoc,
- SourceLocation RP)
+ SourceLocation RP)
: Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary,
Type->isDependentType(), Type->isDependentType(),
Type->isInstantiationDependentType(),
@@ -3721,11 +3814,11 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
End->isTypeDependent() || End->isValueDependent()) {
ExprBits.TypeDependent = ExprBits.ValueDependent = true;
ExprBits.InstantiationDependent = true;
- } else if (Start->isInstantiationDependent() ||
+ } else if (Start->isInstantiationDependent() ||
End->isInstantiationDependent()) {
ExprBits.InstantiationDependent = true;
}
-
+
// Propagate unexpanded parameter packs.
if (Start->containsUnexpandedParameterPack() ||
End->containsUnexpandedParameterPack())
@@ -3813,7 +3906,7 @@ Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const {
return getSubExpr(D.ArrayOrRange.Index + 2);
}
-/// \brief Replaces the designator at index @p Idx with the series
+/// Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
void DesignatedInitExpr::ExpandDesignator(const ASTContext &C, unsigned Idx,
const Designator *First,
@@ -4034,6 +4127,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__atomic_or_fetch:
case AO__atomic_xor_fetch:
case AO__atomic_nand_fetch:
+ case AO__atomic_fetch_min:
+ case AO__atomic_fetch_max:
return 3;
case AO__opencl_atomic_store:
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index a0d611381123..93d68ec8e0b2 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -120,7 +120,7 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
if (Array) {
if (arraySize->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
-
+
if (arraySize->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -169,8 +169,8 @@ void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray,
}
bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const {
- return getOperatorNew()->getType()->castAs<FunctionProtoType>()->isNothrow(
- Ctx) &&
+ return getOperatorNew()->getType()->castAs<FunctionProtoType>()
+ ->isNothrow() &&
!getOperatorNew()->isReservedGlobalPlacementOperator();
}
@@ -181,7 +181,7 @@ QualType CXXDeleteExpr::getDestroyedType() const {
// 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)) {
+ while (const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
if (ICE->getCastKind() == CK_DerivedToBase ||
ICE->getCastKind() == CK_UncheckedDerivedToBase ||
ICE->getCastKind() == CK_NoOp) {
@@ -210,8 +210,8 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
- SourceLocation ColonColonLoc, SourceLocation TildeLoc,
+ NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc, SourceLocation TildeLoc,
PseudoDestructorTypeStorage DestroyedType)
: Expr(CXXPseudoDestructorExprClass,
Context.BoundMemberTy,
@@ -230,10 +230,10 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
->isInstantiationDependentType())),
// ContainsUnexpandedParameterPack
(Base->containsUnexpandedParameterPack() ||
- (QualifierLoc &&
+ (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()
->containsUnexpandedParameterPack()) ||
- (ScopeType &&
+ (ScopeType &&
ScopeType->getType()->containsUnexpandedParameterPack()) ||
(DestroyedType.getTypeSourceInfo() &&
DestroyedType.getTypeSourceInfo()->getType()
@@ -246,7 +246,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
QualType CXXPseudoDestructorExpr::getDestroyedType() const {
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
return TInfo->getType();
-
+
return QualType();
}
@@ -290,7 +290,7 @@ UnresolvedLookupExpr::CreateEmpty(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
- UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
+ auto *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
@@ -300,7 +300,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin,
+ UnresolvedSetIterator Begin,
UnresolvedSetIterator End,
bool KnownDependent,
bool KnownInstantiationDependent,
@@ -393,13 +393,13 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
true, true,
(NameInfo.isInstantiationDependent() ||
- (QualifierLoc &&
+ (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
(NameInfo.containsUnexpandedParameterPack() ||
- (QualifierLoc &&
+ (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()
->containsUnexpandedParameterPack()))),
- QualifierLoc(QualifierLoc), NameInfo(NameInfo),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo),
HasTemplateKWAndArgsInfo(Args != nullptr || TemplateKWLoc.isValid())
{
if (Args) {
@@ -442,8 +442,8 @@ DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size);
- DependentScopeDeclRefExpr *E
- = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
+ auto *E =
+ new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
SourceLocation(),
DeclarationNameInfo(), nullptr);
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
@@ -504,9 +504,9 @@ SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
Expr *CXXMemberCallExpr::getImplicitObjectArgument() const {
const Expr *Callee = getCallee()->IgnoreParens();
- if (const MemberExpr *MemExpr = dyn_cast<MemberExpr>(Callee))
+ if (const auto *MemExpr = dyn_cast<MemberExpr>(Callee))
return MemExpr->getBase();
- if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(Callee))
+ if (const auto *BO = dyn_cast<BinaryOperator>(Callee))
if (BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI)
return BO->getLHS();
@@ -515,8 +515,7 @@ Expr *CXXMemberCallExpr::getImplicitObjectArgument() const {
}
CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const {
- if (const MemberExpr *MemExpr =
- dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
+ if (const auto *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
return cast<CXXMethodDecl>(MemExpr->getMemberDecl());
// FIXME: Will eventually need to cope with member pointers.
@@ -556,14 +555,16 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
CastKind K, Expr *Op,
const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy,
- SourceLocation L,
+ SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
- CXXStaticCastExpr *E =
- new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
- RParenLoc, AngleBrackets);
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
+ auto *E =
+ new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc, AngleBrackets);
if (PathSize)
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
E->getTrailingObjects<CXXBaseSpecifier *>());
@@ -572,7 +573,9 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
}
@@ -581,14 +584,16 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
CastKind K, Expr *Op,
const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy,
- SourceLocation L,
+ SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
- CXXDynamicCastExpr *E =
- new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
- RParenLoc, AngleBrackets);
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
+ auto *E =
+ new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc, AngleBrackets);
if (PathSize)
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
E->getTrailingObjects<CXXBaseSpecifier *>());
@@ -597,7 +602,9 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
}
@@ -614,7 +621,7 @@ bool CXXDynamicCastExpr::isAlwaysNull() const
QualType SrcType = getSubExpr()->getType();
QualType DestType = getType();
- if (const PointerType *SrcPTy = SrcType->getAs<PointerType>()) {
+ if (const auto *SrcPTy = SrcType->getAs<PointerType>()) {
SrcType = SrcPTy->getPointeeType();
DestType = DestType->castAs<PointerType>()->getPointeeType();
}
@@ -622,14 +629,14 @@ bool CXXDynamicCastExpr::isAlwaysNull() const
if (DestType->isVoidType())
return false;
- const CXXRecordDecl *SrcRD =
- cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
+ const auto *SrcRD =
+ cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
if (!SrcRD->hasAttr<FinalAttr>())
return false;
- const CXXRecordDecl *DestRD =
- cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
+ const auto *DestRD =
+ cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
return !DestRD->isDerivedFrom(SrcRD);
}
@@ -638,14 +645,16 @@ CXXReinterpretCastExpr *
CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
ExprValueKind VK, CastKind K, Expr *Op,
const CXXCastPath *BasePath,
- TypeSourceInfo *WrittenTy, SourceLocation L,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
- CXXReinterpretCastExpr *E =
- new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
- RParenLoc, AngleBrackets);
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
+ auto *E =
+ new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc, AngleBrackets);
if (PathSize)
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
E->getTrailingObjects<CXXBaseSpecifier *>());
@@ -654,14 +663,16 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
CXXReinterpretCastExpr *
CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
}
CXXConstCastExpr *CXXConstCastExpr::Create(const ASTContext &C, QualType T,
ExprValueKind VK, Expr *Op,
TypeSourceInfo *WrittenTy,
- SourceLocation L,
+ SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc, AngleBrackets);
@@ -677,9 +688,11 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
const CXXCastPath *BasePath,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
- CXXFunctionalCastExpr *E =
- new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
+ auto *E =
+ new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
if (PathSize)
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
E->getTrailingObjects<CXXBaseSpecifier *>());
@@ -688,7 +701,9 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
CXXFunctionalCastExpr *
CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
}
@@ -830,7 +845,7 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind) {
if (NumArgs) {
this->Args = new (C) Stmt*[Args.size()];
-
+
for (unsigned i = 0; i != Args.size(); ++i) {
assert(Args[i] && "NULL argument in CXXConstructExpr");
@@ -840,7 +855,7 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
ExprBits.InstantiationDependent = true;
if (Args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
-
+
this->Args[i] = Args[i];
}
}
@@ -853,7 +868,7 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
unsigned Bits = 0;
if (Implicit)
Bits |= Capture_Implicit;
-
+
switch (Kind) {
case LCK_StarThis:
Bits |= Capture_ByCopy;
@@ -902,9 +917,9 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
CXXRecordDecl *Class = getLambdaClass();
CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
-
+
// FIXME: Propagate "has unexpanded parameter pack" bit.
-
+
// Copy captures.
const ASTContext &Context = Class->getASTContext();
Data.NumCaptures = NumCaptures;
@@ -915,15 +930,15 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
if (Captures[I].isExplicit())
++Data.NumExplicitCaptures;
-
+
*ToCapture++ = Captures[I];
}
-
+
// Copy initialization expressions for the non-static data members.
Stmt **Stored = getStoredStmts();
for (unsigned I = 0, N = CaptureInits.size(); I != N; ++I)
*Stored++ = CaptureInits[I];
-
+
// Copy the body of the lambda.
*Stored++ = getCallOperator()->getBody();
}
@@ -1002,7 +1017,7 @@ CXXRecordDecl *LambdaExpr::getLambdaClass() const {
CXXMethodDecl *LambdaExpr::getCallOperator() const {
CXXRecordDecl *Record = getLambdaClass();
- return Record->getLambdaCallOperator();
+ return Record->getLambdaCallOperator();
}
TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
@@ -1079,7 +1094,7 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
true, true, Type->getType()->containsUnexpandedParameterPack()),
Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc),
NumArgs(Args.size()) {
- Expr **StoredArgs = getTrailingObjects<Expr *>();
+ auto **StoredArgs = getTrailingObjects<Expr *>();
for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -1176,12 +1191,12 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
- CXXDependentScopeMemberExpr *E
- = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
- false, SourceLocation(),
- NestedNameSpecifierLoc(),
- SourceLocation(), nullptr,
- DeclarationNameInfo(), nullptr);
+ auto *E =
+ new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
+ false, SourceLocation(),
+ NestedNameSpecifierLoc(),
+ SourceLocation(), nullptr,
+ DeclarationNameInfo(), nullptr);
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
@@ -1189,7 +1204,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
bool CXXDependentScopeMemberExpr::isImplicitAccess() const {
if (!Base)
return true;
-
+
return cast<Expr>(Base)->isImplicitCXXThis();
}
@@ -1219,7 +1234,7 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin,
+ UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
: OverloadExpr(
UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc,
@@ -1242,7 +1257,7 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C,
bool UnresolvedMemberExpr::isImplicitAccess() const {
if (!Base)
return true;
-
+
return cast<Expr>(Base)->isImplicitCXXThis();
}
@@ -1274,7 +1289,7 @@ UnresolvedMemberExpr::CreateEmpty(const ASTContext &C,
HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
- UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
+ auto *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
@@ -1297,15 +1312,15 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
else {
QualType BaseType = getBaseType().getNonReferenceType();
if (isArrow()) {
- const PointerType *PT = BaseType->getAs<PointerType>();
+ const auto *PT = BaseType->getAs<PointerType>();
assert(PT && "base of arrow member access is not pointer");
BaseType = PT->getPointeeType();
}
-
+
Record = BaseType->getAsCXXRecordDecl();
assert(Record && "base of member expression does not name record");
}
-
+
return Record;
}
@@ -1329,11 +1344,12 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
}
SubstNonTypeTemplateParmPackExpr::
-SubstNonTypeTemplateParmPackExpr(QualType T,
+SubstNonTypeTemplateParmPackExpr(QualType T,
+ ExprValueKind ValueKind,
NonTypeTemplateParmDecl *Param,
SourceLocation NameLoc,
const TemplateArgument &ArgPack)
- : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary,
+ : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary,
true, true, true, true),
Param(Param), Arguments(ArgPack.pack_begin()),
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {}
@@ -1378,7 +1394,7 @@ void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy,
// We may need to allocate extra storage for the mangling number and the
// extended-by ValueDecl.
if (!State.is<ExtraState *>()) {
- auto ES = new (ExtendedBy->getASTContext()) ExtraState;
+ auto *ES = new (ExtendedBy->getASTContext()) ExtraState;
ES->Temporary = State.get<Stmt *>();
State = ES;
}
@@ -1402,7 +1418,7 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
TypeTraitExprBits.Value = Value;
TypeTraitExprBits.NumArgs = Args.size();
- TypeSourceInfo **ToArgs = getTrailingObjects<TypeSourceInfo *>();
+ auto **ToArgs = getTrailingObjects<TypeSourceInfo *>();
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (Args[I]->getType()->isDependentType())
@@ -1411,13 +1427,13 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
setInstantiationDependent(true);
if (Args[I]->getType()->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack(true);
-
+
ToArgs[I] = Args[I];
}
}
TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
- SourceLocation Loc,
+ SourceLocation Loc,
TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
index 3bb2b4eb5fc1..e50dd9c79d11 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -1,4 +1,4 @@
-//===--- ExprClassification.cpp - Expression AST Node Implementation ------===//
+//===- ExprClassification.cpp - Expression AST Node Implementation --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,9 +19,10 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "llvm/Support/ErrorHandling.h"
+
using namespace clang;
-typedef Expr::Classification Cl;
+using Cl = Expr::Classification;
static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E);
static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D);
@@ -160,6 +161,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ShuffleVectorExprClass:
case Expr::ConvertVectorExprClass:
case Expr::IntegerLiteralClass:
+ case Expr::FixedPointLiteralClass:
case Expr::CharacterLiteralClass:
case Expr::AddrLabelExprClass:
case Expr::CXXDeleteExprClass:
@@ -343,19 +345,19 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
case Expr::CXXUnresolvedConstructExprClass:
- return ClassifyUnnamed(Ctx,
+ return ClassifyUnnamed(Ctx,
cast<CXXUnresolvedConstructExpr>(E)->getTypeAsWritten());
-
+
case Expr::BinaryConditionalOperatorClass: {
if (!Lang.CPlusPlus) return Cl::CL_PRValue;
- const BinaryConditionalOperator *co = cast<BinaryConditionalOperator>(E);
+ const auto *co = cast<BinaryConditionalOperator>(E);
return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
}
case Expr::ConditionalOperatorClass: {
// Once again, only C++ is interesting.
if (!Lang.CPlusPlus) return Cl::CL_PRValue;
- const ConditionalOperator *co = cast<ConditionalOperator>(E);
+ const auto *co = cast<ConditionalOperator>(E);
return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
}
@@ -368,7 +370,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind;
}
return Cl::CL_PRValue;
-
+
// Some C++ expressions are always class temporaries.
case Expr::CXXConstructExprClass:
case Expr::CXXInheritedCtorInitExprClass:
@@ -385,7 +387,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::StmtExprClass: {
const CompoundStmt *S = cast<StmtExpr>(E)->getSubStmt();
- if (const Expr *LastExpr = dyn_cast_or_null<Expr>(S->body_back()))
+ if (const auto *LastExpr = dyn_cast_or_null<Expr>(S->body_back()))
return ClassifyUnnamed(Ctx, LastExpr->getType());
return Cl::CL_PRValue;
}
@@ -398,7 +400,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::MaterializeTemporaryExprClass:
return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference()
- ? Cl::CL_LValue
+ ? Cl::CL_LValue
: Cl::CL_XValue;
case Expr::InitListExprClass:
@@ -434,8 +436,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
return Cl::CL_MemberFunction;
bool islvalue;
- if (const NonTypeTemplateParmDecl *NTTParm =
- dyn_cast<NonTypeTemplateParmDecl>(D))
+ if (const auto *NTTParm = dyn_cast<NonTypeTemplateParmDecl>(D))
islvalue = NTTParm->getType()->isReferenceType();
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
@@ -461,7 +462,7 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) {
// otherwise.
if (T->isLValueReferenceType())
return Cl::CL_LValue;
- const RValueReferenceType *RV = T->getAs<RValueReferenceType>();
+ const auto *RV = T->getAs<RValueReferenceType>();
if (!RV) // Could still be a class temporary, though.
return ClassifyTemporary(T);
@@ -491,7 +492,7 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
// C++ [expr.ref]p3: E1->E2 is converted to the equivalent form (*(E1)).E2.
// C++ [expr.ref]p4: If E2 is declared to have type "reference to T", then
// E1.E2 is an lvalue.
- if (ValueDecl *Value = dyn_cast<ValueDecl>(Member))
+ if (const auto *Value = dyn_cast<ValueDecl>(Member))
if (Value->getType()->isReferenceType())
return Cl::CL_LValue;
@@ -517,7 +518,7 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
// -- If it refers to a static member function [...], then E1.E2 is an
// lvalue; [...]
// -- Otherwise [...] E1.E2 is a prvalue.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member))
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(Member))
return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction;
// -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue.
@@ -545,7 +546,7 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
if (E->getOpcode() == BO_PtrMemD)
return (E->getType()->isFunctionType() ||
E->hasPlaceholderType(BuiltinType::BoundMember))
- ? Cl::CL_MemberFunction
+ ? Cl::CL_MemberFunction
: ClassifyInternal(Ctx, E->getLHS());
// C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
@@ -553,7 +554,7 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
if (E->getOpcode() == BO_PtrMemI)
return (E->getType()->isFunctionType() ||
E->hasPlaceholderType(BuiltinType::BoundMember))
- ? Cl::CL_MemberFunction
+ ? Cl::CL_MemberFunction
: Cl::CL_LValue;
// All other binary operations are prvalues.
@@ -599,8 +600,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
if (Kind == Cl::CL_PRValue) {
// For the sake of better diagnostics, we want to specifically recognize
// use of the GCC cast-as-lvalue extension.
- if (const ExplicitCastExpr *CE =
- dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) {
+ if (const auto *CE = dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) {
if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) {
Loc = CE->getExprLoc();
return Cl::CM_LValueCast;
@@ -617,7 +617,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
// Assignment to a property in ObjC is an implicit setter access. But a
// setter might not exist.
- if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ if (const auto *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
if (Expr->isImplicitProperty() &&
Expr->getImplicitPropertySetter() == nullptr)
return Cl::CM_NoSetterProperty;
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index 57bf2fca4eb7..25817b475c32 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -48,6 +48,8 @@
#include <cstring>
#include <functional>
+#define DEBUG_TYPE "exprconstant"
+
using namespace clang;
using llvm::APSInt;
using llvm::APFloat;
@@ -139,7 +141,11 @@ namespace {
E = E->IgnoreParens();
// If we're doing a variable assignment from e.g. malloc(N), there will
- // probably be a cast of some kind. Ignore it.
+ // probably be a cast of some kind. In exotic cases, we might also see a
+ // top-level ExprWithCleanups. Ignore them either way.
+ if (const auto *EC = dyn_cast<ExprWithCleanups>(E))
+ E = EC->getSubExpr()->IgnoreParens();
+
if (const auto *Cast = dyn_cast<CastExpr>(E))
E = Cast->getSubExpr()->IgnoreParens();
@@ -446,8 +452,8 @@ namespace {
// Note that we intentionally use std::map here so that references to
// values are stable.
- typedef std::map<const void*, APValue> MapTy;
- typedef MapTy::const_iterator temp_iterator;
+ typedef std::pair<const void *, unsigned> MapKeyTy;
+ typedef std::map<MapKeyTy, APValue> MapTy;
/// Temporaries - Temporary lvalues materialized within this stack frame.
MapTy Temporaries;
@@ -457,6 +463,20 @@ namespace {
/// Index - The call index of this call.
unsigned Index;
+ /// The stack of integers for tracking version numbers for temporaries.
+ SmallVector<unsigned, 2> TempVersionStack = {1};
+ unsigned CurTempVersion = TempVersionStack.back();
+
+ unsigned getTempVersion() const { return TempVersionStack.back(); }
+
+ void pushTempVersion() {
+ TempVersionStack.push_back(++CurTempVersion);
+ }
+
+ void popTempVersion() {
+ TempVersionStack.pop_back();
+ }
+
// FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact
// on the overall stack usage of deeply-recursing constexpr evaluataions.
// (We should cache this map rather than recomputing it repeatedly.)
@@ -473,10 +493,36 @@ namespace {
APValue *Arguments);
~CallStackFrame();
- APValue *getTemporary(const void *Key) {
- MapTy::iterator I = Temporaries.find(Key);
- return I == Temporaries.end() ? nullptr : &I->second;
+ // Return the temporary for Key whose version number is Version.
+ APValue *getTemporary(const void *Key, unsigned Version) {
+ MapKeyTy KV(Key, Version);
+ auto LB = Temporaries.lower_bound(KV);
+ if (LB != Temporaries.end() && LB->first == KV)
+ return &LB->second;
+ // Pair (Key,Version) wasn't found in the map. Check that no elements
+ // in the map have 'Key' as their key.
+ assert((LB == Temporaries.end() || LB->first.first != Key) &&
+ (LB == Temporaries.begin() || std::prev(LB)->first.first != Key) &&
+ "Element with key 'Key' found in map");
+ return nullptr;
+ }
+
+ // Return the current temporary for Key in the map.
+ APValue *getCurrentTemporary(const void *Key) {
+ auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX));
+ if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key)
+ return &std::prev(UB)->second;
+ return nullptr;
+ }
+
+ // Return the version number of the current temporary for Key.
+ unsigned getCurrentTemporaryVersion(const void *Key) const {
+ auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX));
+ if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key)
+ return std::prev(UB)->first.second;
+ return 0;
}
+
APValue &createTemporary(const void *Key, bool IsLifetimeExtended);
};
@@ -526,7 +572,7 @@ namespace {
// FIXME: Force the precision of the source value down so we don't
// print digits which are usually useless (we don't really care here if
// we truncate a digit by accident in edge cases). Ideally,
- // APFloat::toString would automatically print the shortest
+ // APFloat::toString would automatically print the shortest
// representation which rounds to the correct value, but it's a bit
// tricky to implement.
unsigned precision =
@@ -606,7 +652,8 @@ namespace {
/// 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;
+ typedef std::pair<APValue::LValueBase, std::pair<unsigned, unsigned>>
+ EvaluatingObject;
/// EvaluatingConstructors - Set of objects that are currently being
/// constructed.
@@ -625,8 +672,10 @@ namespace {
}
};
- bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex) {
- return EvaluatingConstructors.count(EvaluatingObject(Decl, CallIndex));
+ bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex,
+ unsigned Version) {
+ return EvaluatingConstructors.count(
+ EvaluatingObject(Decl, {CallIndex, Version}));
}
/// The current array initialization index, if we're performing array
@@ -637,11 +686,11 @@ namespace {
/// notes attached to it will also be stored, otherwise they will not be.
bool HasActiveDiagnostic;
- /// \brief Have we emitted a diagnostic explaining why we couldn't constant
+ /// Have we emitted a diagnostic explaining why we couldn't constant
/// fold (not just why it's not strictly a constant expression)?
bool HasFoldFailureDiagnostic;
- /// \brief Whether or not we're currently speculatively evaluating.
+ /// Whether or not we're currently speculatively evaluating.
bool IsSpeculativelyEvaluating;
enum EvaluationMode {
@@ -722,7 +771,7 @@ namespace {
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
EvaluatingDeclValue = &Value;
- EvaluatingConstructors.insert({Base, 0});
+ EvaluatingConstructors.insert({Base, {0, 0}});
}
const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); }
@@ -777,7 +826,7 @@ namespace {
private:
OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId,
unsigned ExtraNotes, bool IsCCEDiag) {
-
+
if (EvalStatus.Diag) {
// If we have a prior diagnostic, it will be noting that the expression
// isn't a constant expression. This diagnostic is more important,
@@ -831,7 +880,7 @@ namespace {
unsigned ExtraNotes = 0) {
return Diag(Loc, DiagId, ExtraNotes, false);
}
-
+
OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId
= diag::note_invalid_subexpr_in_const_expr,
unsigned ExtraNotes = 0) {
@@ -1086,11 +1135,16 @@ namespace {
unsigned OldStackSize;
public:
ScopeRAII(EvalInfo &Info)
- : Info(Info), OldStackSize(Info.CleanupStack.size()) {}
+ : Info(Info), OldStackSize(Info.CleanupStack.size()) {
+ // Push a new temporary version. This is needed to distinguish between
+ // temporaries created in different iterations of a loop.
+ Info.CurrentCall->pushTempVersion();
+ }
~ScopeRAII() {
// Body moved to a static method to encourage the compiler to inline away
// instances of this class.
cleanup(Info, OldStackSize);
+ Info.CurrentCall->popTempVersion();
}
private:
static void cleanup(EvalInfo &Info, unsigned OldStackSize) {
@@ -1170,7 +1224,8 @@ CallStackFrame::~CallStackFrame() {
APValue &CallStackFrame::createTemporary(const void *Key,
bool IsLifetimeExtended) {
- APValue &Result = Temporaries[Key];
+ unsigned Version = Info.CurrentCall->getTempVersion();
+ APValue &Result = Temporaries[MapKeyTy(Key, Version)];
assert(Result.isUninit() && "temporary created multiple times");
Info.CleanupStack.push_back(Cleanup(&Result, IsLifetimeExtended));
return Result;
@@ -1262,27 +1317,27 @@ namespace {
struct LValue {
APValue::LValueBase Base;
CharUnits Offset;
- unsigned InvalidBase : 1;
- unsigned CallIndex : 31;
SubobjectDesignator Designator;
- bool IsNullPtr;
+ bool IsNullPtr : 1;
+ bool InvalidBase : 1;
const APValue::LValueBase getLValueBase() const { return Base; }
CharUnits &getLValueOffset() { return Offset; }
const CharUnits &getLValueOffset() const { return Offset; }
- unsigned getLValueCallIndex() const { return CallIndex; }
SubobjectDesignator &getLValueDesignator() { return Designator; }
const SubobjectDesignator &getLValueDesignator() const { return Designator;}
bool isNullPointer() const { return IsNullPtr;}
+ unsigned getLValueCallIndex() const { return Base.getCallIndex(); }
+ unsigned getLValueVersion() const { return Base.getVersion(); }
+
void moveInto(APValue &V) const {
if (Designator.Invalid)
- V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex,
- IsNullPtr);
+ V = APValue(Base, Offset, APValue::NoLValuePath(), IsNullPtr);
else {
assert(!InvalidBase && "APValues can't handle invalid LValue bases");
V = APValue(Base, Offset, Designator.Entries,
- Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
+ Designator.IsOnePastTheEnd, IsNullPtr);
}
}
void setFrom(ASTContext &Ctx, const APValue &V) {
@@ -1290,12 +1345,11 @@ namespace {
Base = V.getLValueBase();
Offset = V.getLValueOffset();
InvalidBase = false;
- CallIndex = V.getLValueCallIndex();
Designator = SubobjectDesignator(Ctx, V);
IsNullPtr = V.isNullPointer();
}
- void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) {
+ void set(APValue::LValueBase B, bool BInvalid = false) {
#ifndef NDEBUG
// We only allow a few types of invalid bases. Enforce that here.
if (BInvalid) {
@@ -1308,7 +1362,6 @@ namespace {
Base = B;
Offset = CharUnits::fromQuantity(0);
InvalidBase = BInvalid;
- CallIndex = I;
Designator = SubobjectDesignator(getType(B));
IsNullPtr = false;
}
@@ -1317,13 +1370,12 @@ namespace {
Base = (Expr *)nullptr;
Offset = CharUnits::fromQuantity(TargetVal);
InvalidBase = false;
- CallIndex = 0;
Designator = SubobjectDesignator(PointerTy->getPointeeType());
IsNullPtr = true;
}
void setInvalid(APValue::LValueBase B, unsigned I = 0) {
- set(B, I, true);
+ set(B, true);
}
// Check that this LValue is not based on a null pointer. If it is, produce
@@ -1525,6 +1577,15 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result);
// Misc utilities
//===----------------------------------------------------------------------===//
+/// A helper function to create a temporary and set an LValue.
+template <class KeyTy>
+static APValue &createTemporary(const KeyTy *Key, bool IsLifetimeExtended,
+ LValue &LV, CallStackFrame &Frame) {
+ LV.set({Key, Frame.Info.CurrentCall->Index,
+ Frame.Info.CurrentCall->getTempVersion()});
+ return Frame.createTemporary(Key, IsLifetimeExtended);
+}
+
/// Negate an APSInt in place, converting it to a signed form if necessary, and
/// preserving its value (by extending by up to one bit as needed).
static void negateAsSigned(APSInt &Int) {
@@ -1659,7 +1720,8 @@ static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
/// value for an address or reference constant expression. Return true if we
/// can fold this expression, whether or not it's a constant expression.
static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
- QualType Type, const LValue &LVal) {
+ QualType Type, const LValue &LVal,
+ Expr::ConstExprUsage Usage) {
bool IsReferenceType = Type->isReferenceType();
APValue::LValueBase Base = LVal.getLValueBase();
@@ -1692,7 +1754,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
return false;
// A dllimport variable never acts like a constant.
- if (Var->hasAttr<DLLImportAttr>())
+ if (Usage == Expr::EvaluateForCodeGen && Var->hasAttr<DLLImportAttr>())
return false;
}
if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) {
@@ -1706,7 +1768,8 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
// The C language has no notion of ODR; furthermore, it has no notion of
// dynamic initialization. This means that we are permitted to
// perform initialization with the address of the thunk.
- if (Info.getLangOpts().CPlusPlus && FD->hasAttr<DLLImportAttr>())
+ if (Info.getLangOpts().CPlusPlus && Usage == Expr::EvaluateForCodeGen &&
+ FD->hasAttr<DLLImportAttr>())
return false;
}
}
@@ -1739,12 +1802,14 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
static bool CheckMemberPointerConstantExpression(EvalInfo &Info,
SourceLocation Loc,
QualType Type,
- const APValue &Value) {
+ const APValue &Value,
+ Expr::ConstExprUsage Usage) {
const ValueDecl *Member = Value.getMemberPointerDecl();
const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member);
if (!FD)
return true;
- return FD->isVirtual() || !FD->hasAttr<DLLImportAttr>();
+ return Usage == Expr::EvaluateForMangling || FD->isVirtual() ||
+ !FD->hasAttr<DLLImportAttr>();
}
/// Check that this core constant expression is of literal type, and if not,
@@ -1782,8 +1847,10 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
/// Check that this core constant expression value is a valid value for a
/// constant expression. If not, report an appropriate diagnostic. Does not
/// check that the expression is of literal type.
-static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
- QualType Type, const APValue &Value) {
+static bool
+CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, QualType Type,
+ const APValue &Value,
+ Expr::ConstExprUsage Usage = Expr::EvaluateForCodeGen) {
if (Value.isUninit()) {
Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
<< true << Type;
@@ -1802,28 +1869,28 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
QualType EltTy = Type->castAsArrayTypeUnsafe()->getElementType();
for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) {
if (!CheckConstantExpression(Info, DiagLoc, EltTy,
- Value.getArrayInitializedElt(I)))
+ Value.getArrayInitializedElt(I), Usage))
return false;
}
if (!Value.hasArrayFiller())
return true;
- return CheckConstantExpression(Info, DiagLoc, EltTy,
- Value.getArrayFiller());
+ return CheckConstantExpression(Info, DiagLoc, EltTy, Value.getArrayFiller(),
+ Usage);
}
if (Value.isUnion() && Value.getUnionField()) {
return CheckConstantExpression(Info, DiagLoc,
Value.getUnionField()->getType(),
- Value.getUnionValue());
+ Value.getUnionValue(), Usage);
}
if (Value.isStruct()) {
RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
unsigned BaseIndex = 0;
- for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(),
- End = CD->bases_end(); I != End; ++I, ++BaseIndex) {
- if (!CheckConstantExpression(Info, DiagLoc, I->getType(),
- Value.getStructBase(BaseIndex)))
+ for (const CXXBaseSpecifier &BS : CD->bases()) {
+ if (!CheckConstantExpression(Info, DiagLoc, BS.getType(),
+ Value.getStructBase(BaseIndex), Usage))
return false;
+ ++BaseIndex;
}
}
for (const auto *I : RD->fields()) {
@@ -1831,7 +1898,8 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
continue;
if (!CheckConstantExpression(Info, DiagLoc, I->getType(),
- Value.getStructField(I->getFieldIndex())))
+ Value.getStructField(I->getFieldIndex()),
+ Usage))
return false;
}
}
@@ -1839,11 +1907,11 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
if (Value.isLValue()) {
LValue LVal;
LVal.setFrom(Info.Ctx, Value);
- return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal);
+ return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal, Usage);
}
if (Value.isMemberPointer())
- return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value);
+ return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, Usage);
// Everything else is fine.
return true;
@@ -1854,7 +1922,7 @@ static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
}
static bool IsLiteralLValue(const LValue &Value) {
- if (Value.CallIndex)
+ if (Value.getLValueCallIndex())
return false;
const Expr *E = Value.Base.dyn_cast<const Expr*>();
return E && !isa<MaterializeTemporaryExpr>(E);
@@ -2181,6 +2249,8 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
case BO_GE: Result = LHS >= RHS; return true;
case BO_EQ: Result = LHS == RHS; return true;
case BO_NE: Result = LHS != RHS; return true;
+ case BO_Cmp:
+ llvm_unreachable("BO_Cmp should be handled elsewhere");
}
}
@@ -2404,7 +2474,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
/// \param Result Filled in with a pointer to the value of the variable.
static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
const VarDecl *VD, CallStackFrame *Frame,
- APValue *&Result) {
+ APValue *&Result, const LValue *LVal) {
// If this is a parameter to an active constexpr function call, perform
// argument substitution.
@@ -2423,7 +2493,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// If this is a local variable, dig out its value.
if (Frame) {
- Result = Frame->getTemporary(VD);
+ Result = LVal ? Frame->getTemporary(VD, LVal->getLValueVersion())
+ : Frame->getCurrentTemporary(VD);
if (!Result) {
// Assume variables referenced within a lambda's call operator that were
// not declared within the call operator are captures and during checking
@@ -2652,10 +2723,13 @@ struct CompleteObject {
APValue *Value;
/// The type of the complete object.
QualType Type;
+ bool LifetimeStartedInEvaluation;
CompleteObject() : Value(nullptr) {}
- CompleteObject(APValue *Value, QualType Type)
- : Value(Value), Type(Type) {
+ CompleteObject(APValue *Value, QualType Type,
+ bool LifetimeStartedInEvaluation)
+ : Value(Value), Type(Type),
+ LifetimeStartedInEvaluation(LifetimeStartedInEvaluation) {
assert(Value && "missing value for complete object");
}
@@ -2685,6 +2759,8 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
APValue *O = Obj.Value;
QualType ObjType = Obj.Type;
const FieldDecl *LastField = nullptr;
+ const bool MayReadMutableMembers =
+ Obj.LifetimeStartedInEvaluation && Info.getLangOpts().CPlusPlus14;
// Walk the designator's path to find the subobject.
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
@@ -2700,7 +2776,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
// cannot perform this read. (This only happens when performing a trivial
// copy or assignment.)
if (ObjType->isRecordType() && handler.AccessKind == AK_Read &&
- diagnoseUnreadableFields(Info, E, ObjType))
+ !MayReadMutableMembers && diagnoseUnreadableFields(Info, E, ObjType))
return handler.failed();
if (!handler.found(*O, ObjType))
@@ -2780,7 +2856,11 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
: O->getComplexFloatReal(), ObjType);
}
} else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
- if (Field->isMutable() && handler.AccessKind == AK_Read) {
+ // In C++14 onwards, it is permitted to read a mutable member whose
+ // lifetime began within the evaluation.
+ // FIXME: Should we also allow this in C++11?
+ if (Field->isMutable() && handler.AccessKind == AK_Read &&
+ !MayReadMutableMembers) {
Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1)
<< Field;
Info.Note(Field->getLocation(), diag::note_declared_at);
@@ -3000,8 +3080,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
CallStackFrame *Frame = nullptr;
- if (LVal.CallIndex) {
- Frame = Info.getCallFrame(LVal.CallIndex);
+ if (LVal.getLValueCallIndex()) {
+ Frame = Info.getCallFrame(LVal.getLValueCallIndex());
if (!Frame) {
Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1)
<< AK << LVal.Base.is<const ValueDecl*>();
@@ -3026,6 +3106,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// Compute value storage location and type of base object.
APValue *BaseVal = nullptr;
QualType BaseType = getType(LVal.Base);
+ bool LifetimeStartedInEvaluation = Frame;
if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) {
// In C++98, const, non-volatile integers initialized with ICEs are ICEs.
@@ -3113,7 +3194,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
}
- if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal))
+ if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal, &LVal))
return CompleteObject();
} else {
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
@@ -3137,7 +3218,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// int &&r = 1;
// int x = ++r;
// constexpr int k = r;
- // Therefore we use the C++1y rules in C++11 too.
+ // Therefore we use the C++14 rules in C++11 too.
const ValueDecl *VD = Info.EvaluatingDecl.dyn_cast<const ValueDecl*>();
const ValueDecl *ED = MTE->getExtendingDecl();
if (!(BaseType.isConstQualified() &&
@@ -3150,12 +3231,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false);
assert(BaseVal && "got reference to unevaluated temporary");
+ LifetimeStartedInEvaluation = true;
} else {
Info.FFDiag(E);
return CompleteObject();
}
} else {
- BaseVal = Frame->getTemporary(Base);
+ BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion());
assert(BaseVal && "missing value for temporary");
}
@@ -3175,12 +3257,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// During the construction of an object, it is not yet 'const'.
// FIXME: This doesn't do quite the right thing for const subobjects of the
// object under construction.
- if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) {
+ if (Info.isEvaluatingConstructor(LVal.getLValueBase(),
+ LVal.getLValueCallIndex(),
+ LVal.getLValueVersion())) {
BaseType = Info.Ctx.getCanonicalType(BaseType);
BaseType.removeLocalConst();
+ LifetimeStartedInEvaluation = true;
}
- // In C++1y, we can't safely access any mutable state when we might be
+ // In C++14, we can't safely access any mutable state when we might be
// evaluating after an unmodeled side effect.
//
// FIXME: Not all local state is mutable. Allow local constant subobjects
@@ -3190,10 +3275,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
(AK != AK_Read && Info.IsSpeculativelyEvaluating))
return CompleteObject();
- return CompleteObject(BaseVal, BaseType);
+ return CompleteObject(BaseVal, BaseType, LifetimeStartedInEvaluation);
}
-/// \brief Perform an lvalue-to-rvalue conversion on the given glvalue. This
+/// Perform an lvalue-to-rvalue conversion on the given glvalue. This
/// can also be used for 'lvalue-to-lvalue' conversions for looking up the
/// glvalue referred to by an entity of reference type.
///
@@ -3212,7 +3297,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
// Check for special cases where there is no existing APValue to look at.
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
- if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) {
+ if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) {
if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) {
// In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the
// initializer until now for such expressions. Such an expression can't be
@@ -3224,14 +3309,14 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
APValue Lit;
if (!Evaluate(Lit, Info, CLE->getInitializer()))
return false;
- CompleteObject LitObj(&Lit, Base->getType());
+ CompleteObject LitObj(&Lit, Base->getType(), false);
return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal);
} else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) {
// We represent a string literal array as an lvalue pointing at the
// corresponding expression, rather than building an array of chars.
// FIXME: Support ObjCEncodeExpr, MakeStringConstant
APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);
- CompleteObject StrObj(&Str, Base->getType());
+ CompleteObject StrObj(&Str, Base->getType(), false);
return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal);
}
}
@@ -3255,11 +3340,6 @@ static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal,
return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val);
}
-static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) {
- return T->isSignedIntegerType() &&
- Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy);
-}
-
namespace {
struct CompoundAssignSubobjectHandler {
EvalInfo &Info;
@@ -3381,7 +3461,7 @@ static bool handleCompoundAssignment(
namespace {
struct IncDecSubobjectHandler {
EvalInfo &Info;
- const Expr *E;
+ const UnaryOperator *E;
AccessKinds AccessKind;
APValue *Old;
@@ -3453,16 +3533,14 @@ struct IncDecSubobjectHandler {
if (AccessKind == AK_Increment) {
++Value;
- if (!WasNegative && Value.isNegative() &&
- isOverflowingIntegerType(Info.Ctx, SubobjType)) {
+ if (!WasNegative && Value.isNegative() && E->canOverflow()) {
APSInt ActualValue(Value, /*IsUnsigned*/true);
return HandleOverflow(Info, E, ActualValue, SubobjType);
}
} else {
--Value;
- if (WasNegative && !Value.isNegative() &&
- isOverflowingIntegerType(Info.Ctx, SubobjType)) {
+ if (WasNegative && !Value.isNegative() && E->canOverflow()) {
unsigned BitWidth = Value.getBitWidth();
APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false);
ActualValue.setBit(BitWidth);
@@ -3523,7 +3601,7 @@ static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal,
AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement;
CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType);
- IncDecSubobjectHandler Handler = { Info, E, AK, Old };
+ IncDecSubobjectHandler Handler = {Info, cast<UnaryOperator>(E), AK, Old};
return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler);
}
@@ -3715,8 +3793,7 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
return true;
LValue Result;
- Result.set(VD, Info.CurrentCall->Index);
- APValue &Val = Info.CurrentCall->createTemporary(VD, true);
+ APValue &Val = createTemporary(VD, true, Result, *Info.CurrentCall);
const Expr *InitE = VD->getInit();
if (!InitE) {
@@ -3764,7 +3841,7 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
}
namespace {
-/// \brief A location where the result (returned value) of evaluating a
+/// A location where the result (returned value) of evaluating a
/// statement should be stored.
struct StmtResult {
/// The APValue that should be filled in with the returned value.
@@ -3772,6 +3849,19 @@ struct StmtResult {
/// The location containing the result, if any (used to support RVO).
const LValue *Slot;
};
+
+struct TempVersionRAII {
+ CallStackFrame &Frame;
+
+ TempVersionRAII(CallStackFrame &Frame) : Frame(Frame) {
+ Frame.pushTempVersion();
+ }
+
+ ~TempVersionRAII() {
+ Frame.popTempVersion();
+ }
+};
+
}
static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
@@ -4196,13 +4286,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
if (Info.getLangOpts().CPlusPlus11) {
const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
-
+
// If this function is not constexpr because it is an inherited
// non-constexpr constructor, diagnose that directly.
auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
if (CD && CD->isInheritingConstructor()) {
auto *Inherited = CD->getInheritedConstructor().getConstructor();
- if (!Inherited->isConstexpr())
+ if (!Inherited->isConstexpr())
DiagDecl = CD = Inherited;
}
@@ -4298,9 +4388,15 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
This->moveInto(Result);
return true;
} else if (MD && isLambdaCallOperator(MD)) {
- // We're in a lambda; determine the lambda capture field maps.
- MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
- Frame.LambdaThisCaptureField);
+ // We're in a lambda; determine the lambda capture field maps unless we're
+ // just constexpr checking a lambda's call operator. constexpr checking is
+ // done before the captures have been added to the closure object (unless
+ // we're inferring constexpr-ness), so we don't have access to them in this
+ // case. But since we don't need the captures to constexpr check, we can
+ // just ignore them.
+ if (!Info.checkingPotentialConstantExpression())
+ MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
+ Frame.LambdaThisCaptureField);
}
StmtResult Ret = {Result, ResultSlot};
@@ -4329,7 +4425,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
}
EvalInfo::EvaluatingConstructorRAII EvalObj(
- Info, {This.getLValueBase(), This.CallIndex});
+ Info, {This.getLValueBase(),
+ {This.getLValueCallIndex(), This.getLValueVersion()}});
CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues);
// FIXME: Creating an APValue just to hold a nonexistent return value is
@@ -4384,6 +4481,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
#endif
for (const auto *I : Definition->inits()) {
LValue Subobject = This;
+ LValue SubobjectParent = This;
APValue *Value = &Result;
// Determine the subobject to initialize.
@@ -4414,7 +4512,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
} else if (IndirectFieldDecl *IFD = I->getIndirectMember()) {
// Walk the indirect field decl's chain to find the object to initialize,
// and make sure we've initialized every step along it.
- for (auto *C : IFD->chain()) {
+ auto IndirectFieldChain = IFD->chain();
+ for (auto *C : IndirectFieldChain) {
FD = cast<FieldDecl>(C);
CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent());
// Switch the union field if it differs. This happens if we had
@@ -4430,6 +4529,10 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
*Value = APValue(APValue::UninitStruct(), CD->getNumBases(),
std::distance(CD->field_begin(), CD->field_end()));
}
+ // Store Subobject as its parent before updating it for the last element
+ // in the chain.
+ if (C == IndirectFieldChain.back())
+ SubobjectParent = Subobject;
if (!HandleLValueMember(Info, I->getInit(), Subobject, FD))
return false;
if (CD->isUnion())
@@ -4441,10 +4544,16 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
llvm_unreachable("unknown base initializer kind");
}
+ // Need to override This for implicit field initializers as in this case
+ // This refers to innermost anonymous struct/union containing initializer,
+ // not to currently constructed class.
+ const Expr *Init = I->getInit();
+ ThisOverrideRAII ThisOverride(*Info.CurrentCall, &SubobjectParent,
+ isa<CXXDefaultInitExpr>(Init));
FullExpressionRAII InitScope(Info);
- if (!EvaluateInPlace(*Value, Info, Subobject, I->getInit()) ||
- (FD && FD->isBitField() && !truncateBitfieldValue(Info, I->getInit(),
- *Value, FD))) {
+ if (!EvaluateInPlace(*Value, Info, Subobject, Init) ||
+ (FD && FD->isBitField() &&
+ !truncateBitfieldValue(Info, Init, *Value, FD))) {
// If we're checking for a potential constant expression, evaluate all
// initializers even if some of them fail.
if (!Info.noteFailure())
@@ -4578,9 +4687,12 @@ public:
{ return StmtVisitorTy::Visit(E->getResultExpr()); }
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
{ return StmtVisitorTy::Visit(E->getReplacement()); }
- bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
- { return StmtVisitorTy::Visit(E->getExpr()); }
+ bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
+ TempVersionRAII RAII(*Info.CurrentCall);
+ return StmtVisitorTy::Visit(E->getExpr());
+ }
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
+ TempVersionRAII RAII(*Info.CurrentCall);
// The initializer may not have been parsed yet, or might be erroneous.
if (!E->getExpr())
return Error(E);
@@ -4658,7 +4770,7 @@ public:
}
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
- if (APValue *Value = Info.CurrentCall->getTemporary(E))
+ if (APValue *Value = Info.CurrentCall->getCurrentTemporary(E))
return DerivedSuccess(*Value, E);
const Expr *Source = E->getSourceExpr();
@@ -4741,7 +4853,7 @@ public:
return false;
This = &ThisVal;
Args = Args.slice(1);
- } else if (MD && MD->isLambdaStaticInvoker()) {
+ } else if (MD && MD->isLambdaStaticInvoker()) {
// Map the static invoker for the lambda back to the call operator.
// Conveniently, we don't have to slice out the 'this' argument (as is
// being done for the non-static case), since a static member function
@@ -4776,7 +4888,7 @@ public:
FD = LambdaCallOp;
}
-
+
} else
return Error(E);
@@ -4836,7 +4948,7 @@ public:
assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() ==
FD->getParent()->getCanonicalDecl() && "record / field mismatch");
- CompleteObject Obj(&Val, BaseTy);
+ CompleteObject Obj(&Val, BaseTy, true);
SubobjectDesignator Designator(BaseTy);
Designator.addDeclUnchecked(FD);
@@ -4956,7 +5068,7 @@ public:
}
};
-}
+} // namespace
//===----------------------------------------------------------------------===//
// Common base class for lvalue and temporary evaluation.
@@ -5178,10 +5290,17 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
// to within 'E' actually represents a lambda-capture that maps to a
// data-member/field within the closure object, and if so, evaluate to the
// field or what the field refers to.
- if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee)) {
+ if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee) &&
+ isa<DeclRefExpr>(E) &&
+ cast<DeclRefExpr>(E)->refersToEnclosingVariableOrCapture()) {
+ // We don't always have a complete capture-map when checking or inferring if
+ // the function call operator meets the requirements of a constexpr function
+ // - but we don't need to evaluate the captures to determine constexprness
+ // (dcl.constexpr C++17).
+ if (Info.checkingPotentialConstantExpression())
+ return false;
+
if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
- if (Info.checkingPotentialConstantExpression())
- return false;
// Start with 'Result' referring to the complete closure object...
Result = *Info.CurrentCall->This;
// ... then update it to refer to the field of the closure object
@@ -5216,14 +5335,15 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
if (!VD->getType()->isReferenceType()) {
if (Frame) {
- Result.set(VD, Frame->Index);
+ Result.set({VD, Frame->Index,
+ Info.CurrentCall->getCurrentTemporaryVersion(VD)});
return true;
}
return Success(VD);
}
APValue *V;
- if (!evaluateVarDeclInit(Info, E, VD, Frame, V))
+ if (!evaluateVarDeclInit(Info, E, VD, Frame, V, nullptr))
return false;
if (V->isUninit()) {
if (!Info.checkingPotentialConstantExpression())
@@ -5255,9 +5375,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
*Value = APValue();
Result.set(E);
} else {
- Value = &Info.CurrentCall->
- createTemporary(E, E->getStorageDuration() == SD_Automatic);
- Result.set(E, Info.CurrentCall->Index);
+ Value = &createTemporary(E, E->getStorageDuration() == SD_Automatic, Result,
+ *Info.CurrentCall);
}
QualType Type = Inner->getType();
@@ -5441,7 +5560,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
// Pointer Evaluation
//===----------------------------------------------------------------------===//
-/// \brief Attempts to compute the number of bytes available at the pointer
+/// Attempts to compute the number of bytes available at the pointer
/// returned by a function with the alloc_size attribute. Returns true if we
/// were successful. Places an unsigned number into `Result`.
///
@@ -5452,9 +5571,8 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
llvm::APInt &Result) {
const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call);
- // alloc_size args are 1-indexed, 0 means not present.
- assert(AllocSize && AllocSize->getElemSizeParam() != 0);
- unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1;
+ assert(AllocSize && AllocSize->getElemSizeParam().isValid());
+ unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex();
unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
if (Call->getNumArgs() <= SizeArgNo)
return false;
@@ -5472,14 +5590,13 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem))
return false;
- if (!AllocSize->getNumElemsParam()) {
+ if (!AllocSize->getNumElemsParam().isValid()) {
Result = std::move(SizeOfElem);
return true;
}
APSInt NumberOfElems;
- // Argument numbers start at 1
- unsigned NumArgNo = AllocSize->getNumElemsParam() - 1;
+ unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex();
if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems))
return false;
@@ -5492,7 +5609,7 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
return true;
}
-/// \brief Convenience function. LVal's base must be a call to an alloc_size
+/// Convenience function. LVal's base must be a call to an alloc_size
/// function.
static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
const LValue &LVal,
@@ -5504,7 +5621,7 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
return getBytesReturnedByAllocSizeCall(Ctx, CE, Result);
}
-/// \brief Attempts to evaluate the given LValueBase as the result of a call to
+/// Attempts to evaluate the given LValueBase as the result of a call to
/// a function with the alloc_size attribute. If it was possible to do so, this
/// function will return true, make Result's Base point to said function call,
/// and mark Result's Base as invalid.
@@ -5615,7 +5732,7 @@ public:
// Update 'Result' to refer to the data member/field of the closure object
// that represents the '*this' capture.
if (!HandleLValueMember(Info, E, Result,
- Info.CurrentCall->LambdaThisCaptureField))
+ Info.CurrentCall->LambdaThisCaptureField))
return false;
// If we captured '*this' by reference, replace the field with its referent.
if (Info.CurrentCall->LambdaThisCaptureField->getType()
@@ -5670,8 +5787,8 @@ bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
return evaluateLValue(E->getSubExpr(), Result);
}
-bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
- const Expr* SubExpr = E->getSubExpr();
+bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
+ const Expr *SubExpr = E->getSubExpr();
switch (E->getCastKind()) {
default:
@@ -5688,7 +5805,11 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
// permitted in constant expressions in C++11. Bitcasts from cv void* are
// also static_casts, but we disallow them as a resolution to DR1312.
if (!E->getType()->isVoidPointerType()) {
- Result.Designator.setInvalid();
+ // If we changed anything other than cvr-qualifiers, we can't use this
+ // value for constant folding. FIXME: Qualification conversions should
+ // always be CK_NoOp, but we get this wrong in C.
+ if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType()))
+ Result.Designator.setInvalid();
if (SubExpr->getType()->isVoidPointerType())
CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 3 << SubExpr->getType();
@@ -5736,7 +5857,6 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
Result.Base = (Expr*)nullptr;
Result.InvalidBase = false;
Result.Offset = CharUnits::fromQuantity(N);
- Result.CallIndex = 0;
Result.Designator.setInvalid();
Result.IsNullPtr = false;
return true;
@@ -5752,9 +5872,9 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
if (!evaluateLValue(SubExpr, Result))
return false;
} else {
- Result.set(SubExpr, Info.CurrentCall->Index);
- if (!EvaluateInPlace(Info.CurrentCall->createTemporary(SubExpr, false),
- Info, Result, SubExpr))
+ APValue &Value = createTemporary(SubExpr, false, Result,
+ *Info.CurrentCall);
+ if (!EvaluateInPlace(Value, Info, Result, SubExpr))
return false;
}
// The result is a pointer to the first element of the array.
@@ -6125,6 +6245,8 @@ namespace {
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T);
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
+
+ bool VisitBinCmp(const BinaryOperator *E);
};
}
@@ -6461,7 +6583,7 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) {
if (ClosureClass->isInvalidDecl()) return false;
if (Info.checkingPotentialConstantExpression()) return true;
-
+
const size_t NumFields =
std::distance(ClosureClass->field_begin(), ClosureClass->field_end());
@@ -6480,7 +6602,7 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) {
assert(CaptureInitIt != E->capture_init_end());
// Get the initializer for this field
Expr *const CurFieldInit = *CaptureInitIt++;
-
+
// If there is no initializer, either this is a VLA or an error has
// occurred.
if (!CurFieldInit)
@@ -6520,9 +6642,8 @@ public:
/// Visit an expression which constructs the value of this temporary.
bool VisitConstructExpr(const Expr *E) {
- Result.set(E, Info.CurrentCall->Index);
- return EvaluateInPlace(Info.CurrentCall->createTemporary(E, false),
- Info, Result, E);
+ APValue &Value = createTemporary(E, false, Result, *Info.CurrentCall);
+ return EvaluateInPlace(Value, Info, Result, E);
}
bool VisitCastExpr(const CastExpr *E) {
@@ -6681,18 +6802,18 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// The number of initializers can be less than the number of
// vector elements. For OpenCL, this can be due to nested vector
- // initialization. For GCC compatibility, missing trailing elements
+ // initialization. For GCC compatibility, missing trailing elements
// should be initialized with zeroes.
unsigned CountInits = 0, CountElts = 0;
while (CountElts < NumElements) {
// Handle nested vector initialization.
- if (CountInits < NumInits
+ if (CountInits < NumInits
&& E->getInit(CountInits)->getType()->isVectorType()) {
APValue v;
if (!EvaluateVector(E->getInit(CountInits), v, Info))
return Error(E);
unsigned vlen = v.getVectorLength();
- for (unsigned j = 0; j < vlen; j++)
+ for (unsigned j = 0; j < vlen; j++)
Elements.push_back(v.getVectorElt(j));
CountElts += vlen;
} else if (EltTy->isIntegerType()) {
@@ -6795,6 +6916,22 @@ static bool EvaluateArray(const Expr *E, const LValue &This,
return ArrayExprEvaluator(Info, This, Result).Visit(E);
}
+// Return true iff the given array filler may depend on the element index.
+static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) {
+ // For now, just whitelist non-class value-initialization and initialization
+ // lists comprised of them.
+ if (isa<ImplicitValueInitExpr>(FillerExpr))
+ return false;
+ if (const InitListExpr *ILE = dyn_cast<InitListExpr>(FillerExpr)) {
+ for (unsigned I = 0, E = ILE->getNumInits(); I != E; ++I) {
+ if (MaybeElementDependentArrayFiller(ILE->getInit(I)))
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType());
if (!CAT)
@@ -6824,10 +6961,13 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr;
// If the initializer might depend on the array index, run it for each
- // array element. For now, just whitelist non-class value-initialization.
- if (NumEltsToInit != NumElts && !isa<ImplicitValueInitExpr>(FillerExpr))
+ // array element.
+ if (NumEltsToInit != NumElts && MaybeElementDependentArrayFiller(FillerExpr))
NumEltsToInit = NumElts;
+ LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: "
+ << NumEltsToInit << ".\n");
+
Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts);
// If the array was previously zero-initialized, preserve the
@@ -6947,11 +7087,11 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
namespace {
class IntExprEvaluator
- : public ExprEvaluatorBase<IntExprEvaluator> {
+ : public ExprEvaluatorBase<IntExprEvaluator> {
APValue &Result;
public:
IntExprEvaluator(EvalInfo &info, APValue &result)
- : ExprEvaluatorBaseTy(info), Result(result) {}
+ : ExprEvaluatorBaseTy(info), Result(result) {}
bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) {
assert(E->getType()->isIntegralOrEnumerationType() &&
@@ -6968,7 +7108,7 @@ public:
}
bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) {
- assert(E->getType()->isIntegralOrEnumerationType() &&
+ assert(E->getType()->isIntegralOrEnumerationType() &&
"Invalid evaluation result.");
assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
"Invalid evaluation result.");
@@ -6982,7 +7122,7 @@ public:
}
bool Success(uint64_t Value, const Expr *E, APValue &Result) {
- assert(E->getType()->isIntegralOrEnumerationType() &&
+ assert(E->getType()->isIntegralOrEnumerationType() &&
"Invalid evaluation result.");
Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
return true;
@@ -7058,7 +7198,7 @@ public:
}
return Success(Info.ArrayInitIndex, E);
}
-
+
// Note, GNU defines __null as an integer, not a pointer.
bool VisitGNUNullExpr(const GNUNullExpr *E) {
return ZeroInitialization(E);
@@ -7084,6 +7224,73 @@ public:
// FIXME: Missing: array subscript of vector, member of vector
};
+
+class FixedPointExprEvaluator
+ : public ExprEvaluatorBase<FixedPointExprEvaluator> {
+ APValue &Result;
+
+ public:
+ FixedPointExprEvaluator(EvalInfo &info, APValue &result)
+ : ExprEvaluatorBaseTy(info), Result(result) {}
+
+ bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) {
+ assert(E->getType()->isFixedPointType() && "Invalid evaluation result.");
+ assert(SI.isSigned() == E->getType()->isSignedFixedPointType() &&
+ "Invalid evaluation result.");
+ assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+ "Invalid evaluation result.");
+ Result = APValue(SI);
+ return true;
+ }
+ bool Success(const llvm::APSInt &SI, const Expr *E) {
+ return Success(SI, E, Result);
+ }
+
+ bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) {
+ assert(E->getType()->isFixedPointType() && "Invalid evaluation result.");
+ assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+ "Invalid evaluation result.");
+ Result = APValue(APSInt(I));
+ Result.getInt().setIsUnsigned(E->getType()->isUnsignedFixedPointType());
+ return true;
+ }
+ bool Success(const llvm::APInt &I, const Expr *E) {
+ return Success(I, E, Result);
+ }
+
+ bool Success(uint64_t Value, const Expr *E, APValue &Result) {
+ assert(E->getType()->isFixedPointType() && "Invalid evaluation result.");
+ Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
+ return true;
+ }
+ bool Success(uint64_t Value, const Expr *E) {
+ return Success(Value, E, Result);
+ }
+
+ bool Success(CharUnits Size, const Expr *E) {
+ return Success(Size.getQuantity(), E);
+ }
+
+ bool Success(const APValue &V, const Expr *E) {
+ if (V.isLValue() || V.isAddrLabelDiff()) {
+ Result = V;
+ return true;
+ }
+ return Success(V.getInt(), E);
+ }
+
+ bool ZeroInitialization(const Expr *E) { return Success(0, E); }
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ bool VisitFixedPointLiteral(const FixedPointLiteral *E) {
+ return Success(E->getValue(), E);
+ }
+
+ bool VisitUnaryOperator(const UnaryOperator *E);
+};
} // end anonymous namespace
/// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and
@@ -7141,30 +7348,43 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
return false;
}
+/// Values returned by __builtin_classify_type, chosen to match the values
+/// produced by GCC's builtin.
+enum class GCCTypeClass {
+ None = -1,
+ Void = 0,
+ Integer = 1,
+ // GCC reserves 2 for character types, but instead classifies them as
+ // integers.
+ Enum = 3,
+ Bool = 4,
+ Pointer = 5,
+ // GCC reserves 6 for references, but appears to never use it (because
+ // expressions never have reference type, presumably).
+ PointerToDataMember = 7,
+ RealFloat = 8,
+ Complex = 9,
+ // GCC reserves 10 for functions, but does not use it since GCC version 6 due
+ // to decay to pointer. (Prior to version 6 it was only used in C++ mode).
+ // GCC claims to reserve 11 for pointers to member functions, but *actually*
+ // uses 12 for that purpose, same as for a class or struct. Maybe it
+ // internally implements a pointer to member as a struct? Who knows.
+ PointerToMemberFunction = 12, // Not a bug, see above.
+ ClassOrStruct = 12,
+ Union = 13,
+ // GCC reserves 14 for arrays, but does not use it since GCC version 6 due to
+ // decay to pointer. (Prior to version 6 it was only used in C++ mode).
+ // GCC reserves 15 for strings, but actually uses 5 (pointer) for string
+ // literals.
+};
+
/// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
/// as GCC.
-static int EvaluateBuiltinClassifyType(const CallExpr *E,
- const LangOptions &LangOpts) {
- // The following enum mimics the values returned by GCC.
- // FIXME: Does GCC differ between lvalue and rvalue references here?
- enum gcc_type_class {
- no_type_class = -1,
- void_type_class, integer_type_class, char_type_class,
- enumeral_type_class, boolean_type_class,
- pointer_type_class, reference_type_class, offset_type_class,
- real_type_class, complex_type_class,
- function_type_class, method_type_class,
- record_type_class, union_type_class,
- array_type_class, string_type_class,
- lang_type_class
- };
-
- // If no argument was supplied, default to "no_type_class". This isn't
- // ideal, however it is what gcc does.
- if (E->getNumArgs() == 0)
- return no_type_class;
+static GCCTypeClass
+EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
+ assert(!T->isDependentType() && "unexpected dependent type");
- QualType CanTy = E->getArg(0)->getType().getCanonicalType();
+ QualType CanTy = T.getCanonicalType();
const BuiltinType *BT = dyn_cast<BuiltinType>(CanTy);
switch (CanTy->getTypeClass()) {
@@ -7173,36 +7393,55 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E,
#define NON_CANONICAL_TYPE(ID, BASE) case Type::ID:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(ID, BASE) case Type::ID:
#include "clang/AST/TypeNodes.def"
- llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ case Type::Auto:
+ case Type::DeducedTemplateSpecialization:
+ llvm_unreachable("unexpected non-canonical or dependent type");
case Type::Builtin:
switch (BT->getKind()) {
#define BUILTIN_TYPE(ID, SINGLETON_ID)
-#define SIGNED_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return integer_type_class;
-#define FLOATING_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return real_type_class;
-#define PLACEHOLDER_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: break;
+#define SIGNED_TYPE(ID, SINGLETON_ID) \
+ case BuiltinType::ID: return GCCTypeClass::Integer;
+#define FLOATING_TYPE(ID, SINGLETON_ID) \
+ case BuiltinType::ID: return GCCTypeClass::RealFloat;
+#define PLACEHOLDER_TYPE(ID, SINGLETON_ID) \
+ case BuiltinType::ID: break;
#include "clang/AST/BuiltinTypes.def"
case BuiltinType::Void:
- return void_type_class;
+ return GCCTypeClass::Void;
case BuiltinType::Bool:
- return boolean_type_class;
+ return GCCTypeClass::Bool;
- case BuiltinType::Char_U: // gcc doesn't appear to use char_type_class
+ case BuiltinType::Char_U:
case BuiltinType::UChar:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char8:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
case BuiltinType::UShort:
case BuiltinType::UInt:
case BuiltinType::ULong:
case BuiltinType::ULongLong:
case BuiltinType::UInt128:
- return integer_type_class;
+ return GCCTypeClass::Integer;
+
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
+ return GCCTypeClass::None;
case BuiltinType::NullPtr:
- return pointer_type_class;
- case BuiltinType::WChar_U:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
@@ -7214,74 +7453,73 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E,
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
+ return GCCTypeClass::None;
+
case BuiltinType::Dependent:
- llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ llvm_unreachable("unexpected dependent type");
};
- break;
+ llvm_unreachable("unexpected placeholder type");
case Type::Enum:
- return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class;
- break;
+ return LangOpts.CPlusPlus ? GCCTypeClass::Enum : GCCTypeClass::Integer;
case Type::Pointer:
- return pointer_type_class;
- break;
+ case Type::ConstantArray:
+ case Type::VariableArray:
+ case Type::IncompleteArray:
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ return GCCTypeClass::Pointer;
case Type::MemberPointer:
- if (CanTy->isMemberDataPointerType())
- return offset_type_class;
- else {
- // We expect member pointers to be either data or function pointers,
- // nothing else.
- assert(CanTy->isMemberFunctionPointerType());
- return method_type_class;
- }
+ return CanTy->isMemberDataPointerType()
+ ? GCCTypeClass::PointerToDataMember
+ : GCCTypeClass::PointerToMemberFunction;
case Type::Complex:
- return complex_type_class;
-
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- return LangOpts.CPlusPlus ? function_type_class : pointer_type_class;
+ return GCCTypeClass::Complex;
case Type::Record:
- if (const RecordType *RT = CanTy->getAs<RecordType>()) {
- switch (RT->getDecl()->getTagKind()) {
- case TagTypeKind::TTK_Struct:
- case TagTypeKind::TTK_Class:
- case TagTypeKind::TTK_Interface:
- return record_type_class;
-
- case TagTypeKind::TTK_Enum:
- return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class;
-
- case TagTypeKind::TTK_Union:
- return union_type_class;
- }
- }
- llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ return CanTy->isUnionType() ? GCCTypeClass::Union
+ : GCCTypeClass::ClassOrStruct;
- case Type::ConstantArray:
- case Type::VariableArray:
- case Type::IncompleteArray:
- return LangOpts.CPlusPlus ? array_type_class : pointer_type_class;
+ case Type::Atomic:
+ // GCC classifies _Atomic T the same as T.
+ return EvaluateBuiltinClassifyType(
+ CanTy->castAs<AtomicType>()->getValueType(), LangOpts);
case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
case Type::Vector:
case Type::ExtVector:
- case Type::Auto:
- case Type::DeducedTemplateSpecialization:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::Pipe:
- case Type::Atomic:
- llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ // GCC classifies vectors as None. We follow its lead and classify all
+ // other types that don't fit into the regular classification the same way.
+ return GCCTypeClass::None;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ llvm_unreachable("invalid type for expression");
}
- llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ llvm_unreachable("unexpected type class");
+}
+
+/// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
+/// as GCC.
+static GCCTypeClass
+EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) {
+ // If no argument was supplied, default to None. This isn't
+ // ideal, however it is what gcc does.
+ if (E->getNumArgs() == 0)
+ return GCCTypeClass::None;
+
+ // FIXME: Bizarrely, GCC treats a call with more than one argument as not
+ // being an ICE, but still folds it to a constant using the type of the first
+ // argument.
+ return EvaluateBuiltinClassifyType(E->getArg(0)->getType(), LangOpts);
}
/// EvaluateBuiltinConstantPForLValue - Determine the result of
@@ -7600,7 +7838,7 @@ static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc,
return true;
}
-/// \brief Tries to evaluate the __builtin_object_size for @p E. If successful,
+/// Tries to evaluate the __builtin_object_size for @p E. If successful,
/// returns true and stores the result in @p Size.
///
/// If @p WasError is non-null, this will report whether the failure to evaluate
@@ -7705,7 +7943,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
}
case Builtin::BI__builtin_classify_type:
- return Success(EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E);
+ return Success((int)EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E);
// FIXME: BI__builtin_clrsb
// FIXME: BI__builtin_clrsbl
@@ -7921,14 +8159,24 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
BuiltinOp != Builtin::BIwmemcmp &&
BuiltinOp != Builtin::BI__builtin_memcmp &&
BuiltinOp != Builtin::BI__builtin_wmemcmp);
+ bool IsWide = BuiltinOp == Builtin::BIwcscmp ||
+ BuiltinOp == Builtin::BIwcsncmp ||
+ BuiltinOp == Builtin::BIwmemcmp ||
+ BuiltinOp == Builtin::BI__builtin_wcscmp ||
+ BuiltinOp == Builtin::BI__builtin_wcsncmp ||
+ BuiltinOp == Builtin::BI__builtin_wmemcmp;
for (; MaxLength; --MaxLength) {
APValue Char1, Char2;
if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) ||
!handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) ||
!Char1.isInt() || !Char2.isInt())
return false;
- if (Char1.getInt() != Char2.getInt())
- return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);
+ if (Char1.getInt() != Char2.getInt()) {
+ if (IsWide) // wmemcmp compares with wchar_t signedness.
+ return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);
+ // memcmp always compares unsigned chars.
+ return Success(Char1.getInt().ult(Char2.getInt()) ? -1 : 1, E);
+ }
if (StopAtNull && !Char1.getInt())
return Success(0, E);
assert(!(StopAtNull && !Char2.getInt()));
@@ -7987,6 +8235,125 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *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);
+ case Builtin::BI__builtin_add_overflow:
+ case Builtin::BI__builtin_sub_overflow:
+ case Builtin::BI__builtin_mul_overflow:
+ case Builtin::BI__builtin_sadd_overflow:
+ case Builtin::BI__builtin_uadd_overflow:
+ case Builtin::BI__builtin_uaddl_overflow:
+ case Builtin::BI__builtin_uaddll_overflow:
+ case Builtin::BI__builtin_usub_overflow:
+ case Builtin::BI__builtin_usubl_overflow:
+ case Builtin::BI__builtin_usubll_overflow:
+ case Builtin::BI__builtin_umul_overflow:
+ case Builtin::BI__builtin_umull_overflow:
+ case Builtin::BI__builtin_umulll_overflow:
+ case Builtin::BI__builtin_saddl_overflow:
+ case Builtin::BI__builtin_saddll_overflow:
+ case Builtin::BI__builtin_ssub_overflow:
+ case Builtin::BI__builtin_ssubl_overflow:
+ case Builtin::BI__builtin_ssubll_overflow:
+ case Builtin::BI__builtin_smul_overflow:
+ case Builtin::BI__builtin_smull_overflow:
+ case Builtin::BI__builtin_smulll_overflow: {
+ LValue ResultLValue;
+ APSInt LHS, RHS;
+
+ QualType ResultType = E->getArg(2)->getType()->getPointeeType();
+ if (!EvaluateInteger(E->getArg(0), LHS, Info) ||
+ !EvaluateInteger(E->getArg(1), RHS, Info) ||
+ !EvaluatePointer(E->getArg(2), ResultLValue, Info))
+ return false;
+
+ APSInt Result;
+ bool DidOverflow = false;
+
+ // If the types don't have to match, enlarge all 3 to the largest of them.
+ if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
+ BuiltinOp == Builtin::BI__builtin_sub_overflow ||
+ BuiltinOp == Builtin::BI__builtin_mul_overflow) {
+ bool IsSigned = LHS.isSigned() || RHS.isSigned() ||
+ ResultType->isSignedIntegerOrEnumerationType();
+ bool AllSigned = LHS.isSigned() && RHS.isSigned() &&
+ ResultType->isSignedIntegerOrEnumerationType();
+ uint64_t LHSSize = LHS.getBitWidth();
+ uint64_t RHSSize = RHS.getBitWidth();
+ uint64_t ResultSize = Info.Ctx.getTypeSize(ResultType);
+ uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);
+
+ // Add an additional bit if the signedness isn't uniformly agreed to. We
+ // could do this ONLY if there is a signed and an unsigned that both have
+ // MaxBits, but the code to check that is pretty nasty. The issue will be
+ // caught in the shrink-to-result later anyway.
+ if (IsSigned && !AllSigned)
+ ++MaxBits;
+
+ LHS = APSInt(IsSigned ? LHS.sextOrSelf(MaxBits) : LHS.zextOrSelf(MaxBits),
+ !IsSigned);
+ RHS = APSInt(IsSigned ? RHS.sextOrSelf(MaxBits) : RHS.zextOrSelf(MaxBits),
+ !IsSigned);
+ Result = APSInt(MaxBits, !IsSigned);
+ }
+
+ // Find largest int.
+ switch (BuiltinOp) {
+ default:
+ llvm_unreachable("Invalid value for BuiltinOp");
+ case Builtin::BI__builtin_add_overflow:
+ case Builtin::BI__builtin_sadd_overflow:
+ case Builtin::BI__builtin_saddl_overflow:
+ case Builtin::BI__builtin_saddll_overflow:
+ case Builtin::BI__builtin_uadd_overflow:
+ case Builtin::BI__builtin_uaddl_overflow:
+ case Builtin::BI__builtin_uaddll_overflow:
+ Result = LHS.isSigned() ? LHS.sadd_ov(RHS, DidOverflow)
+ : LHS.uadd_ov(RHS, DidOverflow);
+ break;
+ case Builtin::BI__builtin_sub_overflow:
+ case Builtin::BI__builtin_ssub_overflow:
+ case Builtin::BI__builtin_ssubl_overflow:
+ case Builtin::BI__builtin_ssubll_overflow:
+ case Builtin::BI__builtin_usub_overflow:
+ case Builtin::BI__builtin_usubl_overflow:
+ case Builtin::BI__builtin_usubll_overflow:
+ Result = LHS.isSigned() ? LHS.ssub_ov(RHS, DidOverflow)
+ : LHS.usub_ov(RHS, DidOverflow);
+ break;
+ case Builtin::BI__builtin_mul_overflow:
+ case Builtin::BI__builtin_smul_overflow:
+ case Builtin::BI__builtin_smull_overflow:
+ case Builtin::BI__builtin_smulll_overflow:
+ case Builtin::BI__builtin_umul_overflow:
+ case Builtin::BI__builtin_umull_overflow:
+ case Builtin::BI__builtin_umulll_overflow:
+ Result = LHS.isSigned() ? LHS.smul_ov(RHS, DidOverflow)
+ : LHS.umul_ov(RHS, DidOverflow);
+ break;
+ }
+
+ // In the case where multiple sizes are allowed, truncate and see if
+ // the values are the same.
+ if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
+ BuiltinOp == Builtin::BI__builtin_sub_overflow ||
+ BuiltinOp == Builtin::BI__builtin_mul_overflow) {
+ // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,
+ // since it will give us the behavior of a TruncOrSelf in the case where
+ // its parameter <= its size. We previously set Result to be at least the
+ // type-size of the result, so getTypeSize(ResultType) <= Result.BitWidth
+ // will work exactly like TruncOrSelf.
+ APSInt Temp = Result.extOrTrunc(Info.Ctx.getTypeSize(ResultType));
+ Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());
+
+ if (!APSInt::isSameValue(Temp, Result))
+ DidOverflow = true;
+ Result = Temp;
+ }
+
+ APValue APV{Result};
+ if (!handleAssignment(Info, E, ResultLValue, ResultType, APV))
+ return false;
+ return Success(DidOverflow, E);
+ }
}
}
@@ -8007,10 +8374,11 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
}
return IsGlobalLValue(A.getLValueBase()) ||
- A.getLValueCallIndex() == B.getLValueCallIndex();
+ (A.getLValueCallIndex() == B.getLValueCallIndex() &&
+ A.getLValueVersion() == B.getLValueVersion());
}
-/// \brief Determine whether this is a pointer past the end of the complete
+/// Determine whether this is a pointer past the end of the complete
/// object referred to by the lvalue.
static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx,
const LValue &LV) {
@@ -8039,7 +8407,7 @@ static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx,
namespace {
-/// \brief Data recursive integer evaluator of certain binary operators.
+/// Data recursive integer evaluator of certain binary operators.
///
/// We use a data recursive algorithm for binary operators so that we are able
/// to handle extreme cases of chained binary operators without causing stack
@@ -8084,15 +8452,13 @@ public:
DataRecursiveIntBinOpEvaluator(IntExprEvaluator &IntEval, APValue &Result)
: IntEval(IntEval), Info(IntEval.getEvalInfo()), FinalResult(Result) { }
- /// \brief True if \param E is a binary operator that we are going to handle
+ /// True if \param E is a binary operator that we are going to handle
/// data recursively.
/// We handle binary operators that are comma, logical, or that have operands
/// with integral or enumeration type.
static bool shouldEnqueue(const BinaryOperator *E) {
- return E->getOpcode() == BO_Comma ||
- E->isLogicalOp() ||
- (E->isRValue() &&
- E->getType()->isIntegralOrEnumerationType() &&
+ return E->getOpcode() == BO_Comma || E->isLogicalOp() ||
+ (E->isRValue() && E->getType()->isIntegralOrEnumerationType() &&
E->getLHS()->getType()->isIntegralOrEnumerationType() &&
E->getRHS()->getType()->isIntegralOrEnumerationType());
}
@@ -8127,7 +8493,7 @@ private:
return Info.CCEDiag(E, D);
}
- // \brief Returns true if visiting the RHS is necessary, false otherwise.
+ // Returns true if visiting the RHS is necessary, false otherwise.
bool VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E,
bool &SuppressRHSDiags);
@@ -8219,12 +8585,12 @@ bool DataRecursiveIntBinOpEvaluator::
Result = RHSResult.Val;
return true;
}
-
+
if (E->isLogicalOp()) {
bool lhsResult, rhsResult;
bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult);
bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult);
-
+
if (LHSIsOK) {
if (RHSIsOK) {
if (E->getOpcode() == BO_LOr)
@@ -8240,26 +8606,26 @@ bool DataRecursiveIntBinOpEvaluator::
return Success(rhsResult, E, Result);
}
}
-
+
return false;
}
-
+
assert(E->getLHS()->getType()->isIntegralOrEnumerationType() &&
E->getRHS()->getType()->isIntegralOrEnumerationType());
-
+
if (LHSResult.Failed || RHSResult.Failed)
return false;
-
+
const APValue &LHSVal = LHSResult.Val;
const APValue &RHSVal = RHSResult.Val;
-
+
// Handle cases like (unsigned long)&a + 4.
if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) {
Result = LHSVal;
addOrSubLValueAsInteger(Result, RHSVal.getInt(), E->getOpcode() == BO_Sub);
return true;
}
-
+
// Handle cases like 4 + (unsigned long)&a
if (E->getOpcode() == BO_Add &&
RHSVal.isLValue() && LHSVal.isInt()) {
@@ -8267,7 +8633,7 @@ bool DataRecursiveIntBinOpEvaluator::
addOrSubLValueAsInteger(Result, LHSVal.getInt(), /*IsSub*/false);
return true;
}
-
+
if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue()) {
// Handle (intptr_t)&&A - (intptr_t)&&B.
if (!LHSVal.getLValueOffset().isZero() ||
@@ -8306,7 +8672,7 @@ bool DataRecursiveIntBinOpEvaluator::
void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
Job &job = Queue.back();
-
+
switch (job.Kind) {
case Job::AnyExprKind: {
if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(job.E)) {
@@ -8316,12 +8682,12 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
return;
}
}
-
+
EvaluateExpr(job.E, Result);
Queue.pop_back();
return;
}
-
+
case Job::BinOpKind: {
const BinaryOperator *Bop = cast<BinaryOperator>(job.E);
bool SuppressRHSDiags = false;
@@ -8336,7 +8702,7 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
enqueue(Bop->getRHS());
return;
}
-
+
case Job::BinOpVisitedLHSKind: {
const BinaryOperator *Bop = cast<BinaryOperator>(job.E);
EvalResult RHS;
@@ -8346,7 +8712,7 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
return;
}
}
-
+
llvm_unreachable("Invalid Job::Kind!");
}
@@ -8371,19 +8737,47 @@ public:
};
}
-bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- // We don't call noteFailure immediately because the assignment happens after
- // we evaluate LHS and RHS.
- if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
- return Error(E);
+template <class SuccessCB, class AfterCB>
+static bool
+EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
+ SuccessCB &&Success, AfterCB &&DoAfter) {
+ assert(E->isComparisonOp() && "expected comparison operator");
+ assert((E->getOpcode() == BO_Cmp ||
+ E->getType()->isIntegralOrEnumerationType()) &&
+ "unsupported binary expression evaluation");
+ auto Error = [&](const Expr *E) {
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ return false;
+ };
- DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp());
- if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E))
- return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E);
+ using CCR = ComparisonCategoryResult;
+ bool IsRelational = E->isRelationalOp();
+ bool IsEquality = E->isEqualityOp();
+ if (E->getOpcode() == BO_Cmp) {
+ const ComparisonCategoryInfo &CmpInfo =
+ Info.Ctx.CompCategories.getInfoForType(E->getType());
+ IsRelational = CmpInfo.isOrdered();
+ IsEquality = CmpInfo.isEquality();
+ }
QualType LHSTy = E->getLHS()->getType();
QualType RHSTy = E->getRHS()->getType();
+ if (LHSTy->isIntegralOrEnumerationType() &&
+ RHSTy->isIntegralOrEnumerationType()) {
+ APSInt LHS, RHS;
+ bool LHSOK = EvaluateInteger(E->getLHS(), LHS, Info);
+ if (!LHSOK && !Info.noteFailure())
+ return false;
+ if (!EvaluateInteger(E->getRHS(), RHS, Info) || !LHSOK)
+ return false;
+ if (LHS < RHS)
+ return Success(CCR::Less, E);
+ if (LHS > RHS)
+ return Success(CCR::Greater, E);
+ return Success(CCR::Equal, E);
+ }
+
if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {
ComplexValue LHS, RHS;
bool LHSOK;
@@ -8416,30 +8810,13 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
LHS.getComplexFloatReal().compare(RHS.getComplexFloatReal());
APFloat::cmpResult CR_i =
LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag());
-
- if (E->getOpcode() == BO_EQ)
- return Success((CR_r == APFloat::cmpEqual &&
- CR_i == APFloat::cmpEqual), E);
- else {
- assert(E->getOpcode() == BO_NE &&
- "Invalid complex comparison.");
- return Success(((CR_r == APFloat::cmpGreaterThan ||
- CR_r == APFloat::cmpLessThan ||
- CR_r == APFloat::cmpUnordered) ||
- (CR_i == APFloat::cmpGreaterThan ||
- CR_i == APFloat::cmpLessThan ||
- CR_i == APFloat::cmpUnordered)), E);
- }
+ bool IsEqual = CR_r == APFloat::cmpEqual && CR_i == APFloat::cmpEqual;
+ return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E);
} else {
- if (E->getOpcode() == BO_EQ)
- return Success((LHS.getComplexIntReal() == RHS.getComplexIntReal() &&
- LHS.getComplexIntImag() == RHS.getComplexIntImag()), E);
- else {
- assert(E->getOpcode() == BO_NE &&
- "Invalid compex comparison.");
- return Success((LHS.getComplexIntReal() != RHS.getComplexIntReal() ||
- LHS.getComplexIntImag() != RHS.getComplexIntImag()), E);
- }
+ assert(IsEquality && "invalid complex comparison");
+ bool IsEqual = LHS.getComplexIntReal() == RHS.getComplexIntReal() &&
+ LHS.getComplexIntImag() == RHS.getComplexIntImag();
+ return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E);
}
}
@@ -8454,243 +8831,161 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK)
return false;
- APFloat::cmpResult CR = LHS.compare(RHS);
-
- switch (E->getOpcode()) {
- default:
- llvm_unreachable("Invalid binary operator!");
- case BO_LT:
- return Success(CR == APFloat::cmpLessThan, E);
- case BO_GT:
- return Success(CR == APFloat::cmpGreaterThan, E);
- case BO_LE:
- return Success(CR == APFloat::cmpLessThan || CR == APFloat::cmpEqual, E);
- case BO_GE:
- return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpEqual,
- E);
- case BO_EQ:
- return Success(CR == APFloat::cmpEqual, E);
- case BO_NE:
- return Success(CR == APFloat::cmpGreaterThan
- || CR == APFloat::cmpLessThan
- || CR == APFloat::cmpUnordered, E);
- }
+ assert(E->isComparisonOp() && "Invalid binary operator!");
+ auto GetCmpRes = [&]() {
+ switch (LHS.compare(RHS)) {
+ case APFloat::cmpEqual:
+ return CCR::Equal;
+ case APFloat::cmpLessThan:
+ return CCR::Less;
+ case APFloat::cmpGreaterThan:
+ return CCR::Greater;
+ case APFloat::cmpUnordered:
+ return CCR::Unordered;
+ }
+ llvm_unreachable("Unrecognised APFloat::cmpResult enum");
+ };
+ return Success(GetCmpRes(), E);
}
if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
- if (E->getOpcode() == BO_Sub || E->isComparisonOp()) {
- LValue LHSValue, RHSValue;
-
- bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info);
- if (!LHSOK && !Info.noteFailure())
- return false;
-
- if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
- return false;
+ LValue LHSValue, RHSValue;
- // Reject differing bases from the normal codepath; we special-case
- // comparisons to null.
- if (!HasSameBase(LHSValue, RHSValue)) {
- if (E->getOpcode() == BO_Sub) {
- // Handle &&A - &&B.
- if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero())
- return Error(E);
- const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>();
- const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr*>();
- if (!LHSExpr || !RHSExpr)
- return Error(E);
- const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr);
- const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr);
- if (!LHSAddrExpr || !RHSAddrExpr)
- return Error(E);
- // Make sure both labels come from the same function.
- if (LHSAddrExpr->getLabel()->getDeclContext() !=
- RHSAddrExpr->getLabel()->getDeclContext())
- return Error(E);
- return Success(APValue(LHSAddrExpr, RHSAddrExpr), E);
- }
- // Inequalities and subtractions between unrelated pointers have
- // unspecified or undefined behavior.
- if (!E->isEqualityOp())
- return Error(E);
- // A constant address may compare equal to the address of a symbol.
- // The one exception is that address of an object cannot compare equal
- // to a null pointer constant.
- if ((!LHSValue.Base && !LHSValue.Offset.isZero()) ||
- (!RHSValue.Base && !RHSValue.Offset.isZero()))
- return Error(E);
- // It's implementation-defined whether distinct literals will have
- // distinct addresses. In clang, the result of such a comparison is
- // unspecified, so it is not a constant expression. However, we do know
- // that the address of a literal will be non-null.
- if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) &&
- LHSValue.Base && RHSValue.Base)
- return Error(E);
- // We can't tell whether weak symbols will end up pointing to the same
- // object.
- if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))
- return Error(E);
- // We can't compare the address of the start of one object with the
- // past-the-end address of another object, per C++ DR1652.
- if ((LHSValue.Base && LHSValue.Offset.isZero() &&
- isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) ||
- (RHSValue.Base && RHSValue.Offset.isZero() &&
- isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue)))
- return Error(E);
- // We can't tell whether an object is at the same address as another
- // zero sized object.
- if ((RHSValue.Base && isZeroSized(LHSValue)) ||
- (LHSValue.Base && isZeroSized(RHSValue)))
- return Error(E);
- // Pointers with different bases cannot represent the same object.
- return Success(E->getOpcode() == BO_NE, E);
- }
-
- const CharUnits &LHSOffset = LHSValue.getLValueOffset();
- const CharUnits &RHSOffset = RHSValue.getLValueOffset();
-
- SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
- SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
-
- if (E->getOpcode() == BO_Sub) {
- // C++11 [expr.add]p6:
- // Unless both pointers point to elements of the same array object, or
- // one past the last element of the array object, the behavior is
- // undefined.
- if (!LHSDesignator.Invalid && !RHSDesignator.Invalid &&
- !AreElementsOfSameArray(getType(LHSValue.Base),
- LHSDesignator, RHSDesignator))
- CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array);
-
- QualType Type = E->getLHS()->getType();
- QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
-
- CharUnits ElementSize;
- if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize))
- return false;
-
- // As an extension, a type may have zero size (empty struct or union in
- // C, array of zero length). Pointer subtraction in such cases has
- // undefined behavior, so is not constant.
- if (ElementSize.isZero()) {
- Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size)
- << ElementType;
- return false;
- }
+ bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info);
+ if (!LHSOK && !Info.noteFailure())
+ return false;
- // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime,
- // and produce incorrect results when it overflows. Such behavior
- // appears to be non-conforming, but is common, so perhaps we should
- // assume the standard intended for such cases to be undefined behavior
- // and check for them.
-
- // Compute (LHSOffset - RHSOffset) / Size carefully, checking for
- // overflow in the final conversion to ptrdiff_t.
- APSInt LHS(
- llvm::APInt(65, (int64_t)LHSOffset.getQuantity(), true), false);
- APSInt RHS(
- llvm::APInt(65, (int64_t)RHSOffset.getQuantity(), true), false);
- APSInt ElemSize(
- llvm::APInt(65, (int64_t)ElementSize.getQuantity(), true), false);
- APSInt TrueResult = (LHS - RHS) / ElemSize;
- APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType()));
-
- if (Result.extend(65) != TrueResult &&
- !HandleOverflow(Info, E, TrueResult, E->getType()))
- return false;
- return Success(Result, E);
- }
+ if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
+ return false;
- // C++11 [expr.rel]p3:
- // Pointers to void (after pointer conversions) can be compared, with a
- // result defined as follows: If both pointers represent the same
- // address or are both the null pointer value, the result is true if the
- // operator is <= or >= and false otherwise; otherwise the result is
- // unspecified.
- // We interpret this as applying to pointers to *cv* void.
- if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset &&
- E->isRelationalOp())
- CCEDiag(E, diag::note_constexpr_void_comparison);
-
- // C++11 [expr.rel]p2:
- // - If two pointers point to non-static data members of the same object,
- // or to subobjects or array elements fo such members, recursively, the
- // pointer to the later declared member compares greater provided the
- // two members have the same access control and provided their class is
- // not a union.
- // [...]
- // - Otherwise pointer comparisons are unspecified.
- if (!LHSDesignator.Invalid && !RHSDesignator.Invalid &&
- E->isRelationalOp()) {
- bool WasArrayIndex;
- unsigned Mismatch =
- FindDesignatorMismatch(getType(LHSValue.Base), LHSDesignator,
- RHSDesignator, WasArrayIndex);
- // At the point where the designators diverge, the comparison has a
- // specified value if:
- // - we are comparing array indices
- // - we are comparing fields of a union, or fields with the same access
- // Otherwise, the result is unspecified and thus the comparison is not a
- // constant expression.
- if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() &&
- Mismatch < RHSDesignator.Entries.size()) {
- const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]);
- const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]);
- if (!LF && !RF)
- CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes);
- else if (!LF)
- CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field)
+ // Reject differing bases from the normal codepath; we special-case
+ // comparisons to null.
+ if (!HasSameBase(LHSValue, RHSValue)) {
+ // Inequalities and subtractions between unrelated pointers have
+ // unspecified or undefined behavior.
+ if (!IsEquality)
+ return Error(E);
+ // A constant address may compare equal to the address of a symbol.
+ // The one exception is that address of an object cannot compare equal
+ // to a null pointer constant.
+ if ((!LHSValue.Base && !LHSValue.Offset.isZero()) ||
+ (!RHSValue.Base && !RHSValue.Offset.isZero()))
+ return Error(E);
+ // It's implementation-defined whether distinct literals will have
+ // distinct addresses. In clang, the result of such a comparison is
+ // unspecified, so it is not a constant expression. However, we do know
+ // that the address of a literal will be non-null.
+ if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) &&
+ LHSValue.Base && RHSValue.Base)
+ return Error(E);
+ // We can't tell whether weak symbols will end up pointing to the same
+ // object.
+ if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))
+ return Error(E);
+ // We can't compare the address of the start of one object with the
+ // past-the-end address of another object, per C++ DR1652.
+ if ((LHSValue.Base && LHSValue.Offset.isZero() &&
+ isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) ||
+ (RHSValue.Base && RHSValue.Offset.isZero() &&
+ isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue)))
+ return Error(E);
+ // We can't tell whether an object is at the same address as another
+ // zero sized object.
+ if ((RHSValue.Base && isZeroSized(LHSValue)) ||
+ (LHSValue.Base && isZeroSized(RHSValue)))
+ return Error(E);
+ return Success(CCR::Nonequal, E);
+ }
+
+ const CharUnits &LHSOffset = LHSValue.getLValueOffset();
+ const CharUnits &RHSOffset = RHSValue.getLValueOffset();
+
+ SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
+ SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
+
+ // C++11 [expr.rel]p3:
+ // Pointers to void (after pointer conversions) can be compared, with a
+ // result defined as follows: If both pointers represent the same
+ // address or are both the null pointer value, the result is true if the
+ // operator is <= or >= and false otherwise; otherwise the result is
+ // unspecified.
+ // We interpret this as applying to pointers to *cv* void.
+ if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational)
+ Info.CCEDiag(E, diag::note_constexpr_void_comparison);
+
+ // C++11 [expr.rel]p2:
+ // - If two pointers point to non-static data members of the same object,
+ // or to subobjects or array elements fo such members, recursively, the
+ // pointer to the later declared member compares greater provided the
+ // two members have the same access control and provided their class is
+ // not a union.
+ // [...]
+ // - Otherwise pointer comparisons are unspecified.
+ if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
+ bool WasArrayIndex;
+ unsigned Mismatch = FindDesignatorMismatch(
+ getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex);
+ // At the point where the designators diverge, the comparison has a
+ // specified value if:
+ // - we are comparing array indices
+ // - we are comparing fields of a union, or fields with the same access
+ // Otherwise, the result is unspecified and thus the comparison is not a
+ // constant expression.
+ if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() &&
+ Mismatch < RHSDesignator.Entries.size()) {
+ const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]);
+ const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]);
+ if (!LF && !RF)
+ Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes);
+ else if (!LF)
+ Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field)
<< getAsBaseClass(LHSDesignator.Entries[Mismatch])
<< RF->getParent() << RF;
- else if (!RF)
- CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field)
+ else if (!RF)
+ Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field)
<< getAsBaseClass(RHSDesignator.Entries[Mismatch])
<< LF->getParent() << LF;
- else if (!LF->getParent()->isUnion() &&
- LF->getAccess() != RF->getAccess())
- CCEDiag(E, diag::note_constexpr_pointer_comparison_differing_access)
+ else if (!LF->getParent()->isUnion() &&
+ LF->getAccess() != RF->getAccess())
+ Info.CCEDiag(E,
+ diag::note_constexpr_pointer_comparison_differing_access)
<< LF << LF->getAccess() << RF << RF->getAccess()
<< LF->getParent();
- }
- }
-
- // The comparison here must be unsigned, and performed with the same
- // width as the pointer.
- unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy);
- uint64_t CompareLHS = LHSOffset.getQuantity();
- uint64_t CompareRHS = RHSOffset.getQuantity();
- assert(PtrSize <= 64 && "Unexpected pointer width");
- uint64_t Mask = ~0ULL >> (64 - PtrSize);
- CompareLHS &= Mask;
- CompareRHS &= Mask;
-
- // If there is a base and this is a relational operator, we can only
- // compare pointers within the object in question; otherwise, the result
- // depends on where the object is located in memory.
- if (!LHSValue.Base.isNull() && E->isRelationalOp()) {
- QualType BaseTy = getType(LHSValue.Base);
- if (BaseTy->isIncompleteType())
- return Error(E);
- CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
- uint64_t OffsetLimit = Size.getQuantity();
- if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit)
- return Error(E);
}
+ }
- switch (E->getOpcode()) {
- default: llvm_unreachable("missing comparison operator");
- case BO_LT: return Success(CompareLHS < CompareRHS, E);
- case BO_GT: return Success(CompareLHS > CompareRHS, E);
- case BO_LE: return Success(CompareLHS <= CompareRHS, E);
- case BO_GE: return Success(CompareLHS >= CompareRHS, E);
- case BO_EQ: return Success(CompareLHS == CompareRHS, E);
- case BO_NE: return Success(CompareLHS != CompareRHS, E);
- }
+ // The comparison here must be unsigned, and performed with the same
+ // width as the pointer.
+ unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy);
+ uint64_t CompareLHS = LHSOffset.getQuantity();
+ uint64_t CompareRHS = RHSOffset.getQuantity();
+ assert(PtrSize <= 64 && "Unexpected pointer width");
+ uint64_t Mask = ~0ULL >> (64 - PtrSize);
+ CompareLHS &= Mask;
+ CompareRHS &= Mask;
+
+ // If there is a base and this is a relational operator, we can only
+ // compare pointers within the object in question; otherwise, the result
+ // depends on where the object is located in memory.
+ if (!LHSValue.Base.isNull() && IsRelational) {
+ QualType BaseTy = getType(LHSValue.Base);
+ if (BaseTy->isIncompleteType())
+ return Error(E);
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
+ uint64_t OffsetLimit = Size.getQuantity();
+ if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit)
+ return Error(E);
}
+
+ if (CompareLHS < CompareRHS)
+ return Success(CCR::Less, E);
+ if (CompareLHS > CompareRHS)
+ return Success(CCR::Greater, E);
+ return Success(CCR::Equal, E);
}
if (LHSTy->isMemberPointerType()) {
- assert(E->isEqualityOp() && "unexpected member pointer operation");
+ assert(IsEquality && "unexpected member pointer operation");
assert(RHSTy->isMemberPointerType() && "invalid comparison");
MemberPtr LHSValue, RHSValue;
@@ -8707,24 +9002,24 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// null, they compare unequal.
if (!LHSValue.getDecl() || !RHSValue.getDecl()) {
bool Equal = !LHSValue.getDecl() && !RHSValue.getDecl();
- return Success(E->getOpcode() == BO_EQ ? Equal : !Equal, E);
+ return Success(Equal ? CCR::Equal : CCR::Nonequal, E);
}
// Otherwise if either is a pointer to a virtual member function, the
// result is unspecified.
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LHSValue.getDecl()))
if (MD->isVirtual())
- CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
+ Info.CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(RHSValue.getDecl()))
if (MD->isVirtual())
- CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
+ Info.CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
// Otherwise they compare equal if and only if they would refer to the
// same member of the same most derived object or the same subobject if
// they were dereferenced with a hypothetical object of the associated
// class type.
bool Equal = LHSValue == RHSValue;
- return Success(E->getOpcode() == BO_EQ ? Equal : !Equal, E);
+ return Success(Equal ? CCR::Equal : CCR::Nonequal, E);
}
if (LHSTy->isNullPtrType()) {
@@ -8733,14 +9028,163 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t
// are compared, the result is true of the operator is <=, >= or ==, and
// false otherwise.
- BinaryOperator::Opcode Opcode = E->getOpcode();
- return Success(Opcode == BO_EQ || Opcode == BO_LE || Opcode == BO_GE, E);
+ return Success(CCR::Equal, E);
}
- assert((!LHSTy->isIntegralOrEnumerationType() ||
- !RHSTy->isIntegralOrEnumerationType()) &&
+ return DoAfter();
+}
+
+bool RecordExprEvaluator::VisitBinCmp(const BinaryOperator *E) {
+ if (!CheckLiteralType(Info, E))
+ return false;
+
+ auto OnSuccess = [&](ComparisonCategoryResult ResKind,
+ const BinaryOperator *E) {
+ // Evaluation succeeded. Lookup the information for the comparison category
+ // type and fetch the VarDecl for the result.
+ const ComparisonCategoryInfo &CmpInfo =
+ Info.Ctx.CompCategories.getInfoForType(E->getType());
+ const VarDecl *VD =
+ CmpInfo.getValueInfo(CmpInfo.makeWeakResult(ResKind))->VD;
+ // Check and evaluate the result as a constant expression.
+ LValue LV;
+ LV.set(VD);
+ if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result))
+ return false;
+ return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result);
+ };
+ return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() {
+ return ExprEvaluatorBaseTy::VisitBinCmp(E);
+ });
+}
+
+bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ // We don't call noteFailure immediately because the assignment happens after
+ // we evaluate LHS and RHS.
+ if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
+ return Error(E);
+
+ DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp());
+ if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E))
+ return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E);
+
+ assert((!E->getLHS()->getType()->isIntegralOrEnumerationType() ||
+ !E->getRHS()->getType()->isIntegralOrEnumerationType()) &&
"DataRecursiveIntBinOpEvaluator should have handled integral types");
- // We can't continue from here for non-integral types.
+
+ if (E->isComparisonOp()) {
+ // Evaluate builtin binary comparisons by evaluating them as C++2a three-way
+ // comparisons and then translating the result.
+ auto OnSuccess = [&](ComparisonCategoryResult ResKind,
+ const BinaryOperator *E) {
+ using CCR = ComparisonCategoryResult;
+ bool IsEqual = ResKind == CCR::Equal,
+ IsLess = ResKind == CCR::Less,
+ IsGreater = ResKind == CCR::Greater;
+ auto Op = E->getOpcode();
+ switch (Op) {
+ default:
+ llvm_unreachable("unsupported binary operator");
+ case BO_EQ:
+ case BO_NE:
+ return Success(IsEqual == (Op == BO_EQ), E);
+ case BO_LT: return Success(IsLess, E);
+ case BO_GT: return Success(IsGreater, E);
+ case BO_LE: return Success(IsEqual || IsLess, E);
+ case BO_GE: return Success(IsEqual || IsGreater, E);
+ }
+ };
+ return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() {
+ return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
+ });
+ }
+
+ QualType LHSTy = E->getLHS()->getType();
+ QualType RHSTy = E->getRHS()->getType();
+
+ if (LHSTy->isPointerType() && RHSTy->isPointerType() &&
+ E->getOpcode() == BO_Sub) {
+ LValue LHSValue, RHSValue;
+
+ bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info);
+ if (!LHSOK && !Info.noteFailure())
+ return false;
+
+ if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
+ return false;
+
+ // Reject differing bases from the normal codepath; we special-case
+ // comparisons to null.
+ if (!HasSameBase(LHSValue, RHSValue)) {
+ // Handle &&A - &&B.
+ if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero())
+ return Error(E);
+ const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr *>();
+ const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr *>();
+ if (!LHSExpr || !RHSExpr)
+ return Error(E);
+ const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr);
+ const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr);
+ if (!LHSAddrExpr || !RHSAddrExpr)
+ return Error(E);
+ // Make sure both labels come from the same function.
+ if (LHSAddrExpr->getLabel()->getDeclContext() !=
+ RHSAddrExpr->getLabel()->getDeclContext())
+ return Error(E);
+ return Success(APValue(LHSAddrExpr, RHSAddrExpr), E);
+ }
+ const CharUnits &LHSOffset = LHSValue.getLValueOffset();
+ const CharUnits &RHSOffset = RHSValue.getLValueOffset();
+
+ SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
+ SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
+
+ // C++11 [expr.add]p6:
+ // Unless both pointers point to elements of the same array object, or
+ // one past the last element of the array object, the behavior is
+ // undefined.
+ if (!LHSDesignator.Invalid && !RHSDesignator.Invalid &&
+ !AreElementsOfSameArray(getType(LHSValue.Base), LHSDesignator,
+ RHSDesignator))
+ Info.CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array);
+
+ QualType Type = E->getLHS()->getType();
+ QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
+
+ CharUnits ElementSize;
+ if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize))
+ return false;
+
+ // As an extension, a type may have zero size (empty struct or union in
+ // C, array of zero length). Pointer subtraction in such cases has
+ // undefined behavior, so is not constant.
+ if (ElementSize.isZero()) {
+ Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size)
+ << ElementType;
+ return false;
+ }
+
+ // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime,
+ // and produce incorrect results when it overflows. Such behavior
+ // appears to be non-conforming, but is common, so perhaps we should
+ // assume the standard intended for such cases to be undefined behavior
+ // and check for them.
+
+ // Compute (LHSOffset - RHSOffset) / Size carefully, checking for
+ // overflow in the final conversion to ptrdiff_t.
+ APSInt LHS(llvm::APInt(65, (int64_t)LHSOffset.getQuantity(), true), false);
+ APSInt RHS(llvm::APInt(65, (int64_t)RHSOffset.getQuantity(), true), false);
+ APSInt ElemSize(llvm::APInt(65, (int64_t)ElementSize.getQuantity(), true),
+ false);
+ APSInt TrueResult = (LHS - RHS) / ElemSize;
+ APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType()));
+
+ if (Result.extend(65) != TrueResult &&
+ !HandleOverflow(Info, E, TrueResult, E->getType()))
+ return false;
+ return Success(Result, E);
+ }
+
return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
}
@@ -8855,7 +9299,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
const RecordType *BaseRT = CurrentType->getAs<RecordType>();
if (!BaseRT)
return Error(OOE);
-
+
// Add the offset to the base.
Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
break;
@@ -8883,7 +9327,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (!Result.isInt()) return Error(E);
const APSInt &Value = Result.getInt();
- if (Value.isSigned() && Value.isMinSignedValue() &&
+ if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() &&
!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
E->getType()))
return false;
@@ -9088,6 +9532,37 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
return Success(E->getValue(), E);
}
+bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
+ switch (E->getOpcode()) {
+ default:
+ // Invalid unary operators
+ return Error(E);
+ case UO_Plus:
+ // The result is just the value.
+ return Visit(E->getSubExpr());
+ case UO_Minus: {
+ if (!Visit(E->getSubExpr())) return false;
+ if (!Result.isInt()) return Error(E);
+ const APSInt &Value = Result.getInt();
+ if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) {
+ SmallString<64> S;
+ FixedPointValueToString(S, Value,
+ Info.Ctx.getTypeInfo(E->getType()).Width,
+ /*Radix=*/10);
+ Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType();
+ if (Info.noteUndefinedBehavior()) return false;
+ }
+ return Success(-Value, E);
+ }
+ case UO_LNot: {
+ bool bres;
+ if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info))
+ return false;
+ return Success(!bres, E);
+ }
+ }
+}
+
//===----------------------------------------------------------------------===//
// Float Evaluation
//===----------------------------------------------------------------------===//
@@ -9175,9 +9650,11 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_huge_val:
case Builtin::BI__builtin_huge_valf:
case Builtin::BI__builtin_huge_vall:
+ case Builtin::BI__builtin_huge_valf128:
case Builtin::BI__builtin_inf:
case Builtin::BI__builtin_inff:
- case Builtin::BI__builtin_infl: {
+ case Builtin::BI__builtin_infl:
+ case Builtin::BI__builtin_inff128: {
const llvm::fltSemantics &Sem =
Info.Ctx.getFloatTypeSemantics(E->getType());
Result = llvm::APFloat::getInf(Sem);
@@ -9187,6 +9664,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_nans:
case Builtin::BI__builtin_nansf:
case Builtin::BI__builtin_nansl:
+ case Builtin::BI__builtin_nansf128:
if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
true, Result))
return Error(E);
@@ -9195,6 +9673,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_nan:
case Builtin::BI__builtin_nanf:
case Builtin::BI__builtin_nanl:
+ case Builtin::BI__builtin_nanf128:
// If this is __builtin_nan() turn this into a nan, otherwise we
// can't constant fold it.
if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
@@ -9205,6 +9684,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_fabs:
case Builtin::BI__builtin_fabsf:
case Builtin::BI__builtin_fabsl:
+ case Builtin::BI__builtin_fabsf128:
if (!EvaluateFloat(E->getArg(0), Result, Info))
return false;
@@ -9218,7 +9698,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_copysign:
case Builtin::BI__builtin_copysignf:
- case Builtin::BI__builtin_copysignl: {
+ case Builtin::BI__builtin_copysignl:
+ case Builtin::BI__builtin_copysignf128: {
APFloat RHS(0.);
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
!EvaluateFloat(E->getArg(1), RHS, Info))
@@ -9933,6 +10414,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
if (!EvaluateComplex(E, C, Info))
return false;
C.moveInto(Result);
+ } else if (T->isFixedPointType()) {
+ if (!FixedPointExprEvaluator(Info, Result).Visit(E)) return false;
} else if (T->isMemberPointerType()) {
MemberPtr P;
if (!EvaluateMemberPointer(E, P, Info))
@@ -9941,15 +10424,13 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
return true;
} else if (T->isArrayType()) {
LValue LV;
- LV.set(E, Info.CurrentCall->Index);
- APValue &Value = Info.CurrentCall->createTemporary(E, false);
+ APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall);
if (!EvaluateArray(E, LV, Value, Info))
return false;
Result = Value;
} else if (T->isRecordType()) {
LValue LV;
- LV.set(E, Info.CurrentCall->Index);
- APValue &Value = Info.CurrentCall->createTemporary(E, false);
+ APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall);
if (!EvaluateRecord(E, LV, Value, Info))
return false;
Result = Value;
@@ -9963,8 +10444,7 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
QualType Unqual = T.getAtomicUnqualifiedType();
if (Unqual->isArrayType() || Unqual->isRecordType()) {
LValue LV;
- LV.set(E, Info.CurrentCall->Index);
- APValue &Value = Info.CurrentCall->createTemporary(E, false);
+ APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall);
if (!EvaluateAtomic(E, &LV, Value, Info))
return false;
} else {
@@ -10051,7 +10531,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
IsConst = false;
return true;
}
-
+
// FIXME: Evaluating values of large array and record types can cause
// performance problems. Only do so in C++11 for now.
if (Exp->isRValue() && (Exp->getType()->isArrayType() ||
@@ -10073,7 +10553,7 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
bool IsConst;
if (FastEvaluateAsRValue(this, Result, Ctx, IsConst))
return IsConst;
-
+
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
return ::EvaluateAsRValue(Info, this, Result.Val);
}
@@ -10125,13 +10605,25 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
LValue LV;
if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects ||
!CheckLValueConstantExpression(Info, getExprLoc(),
- Ctx.getLValueReferenceType(getType()), LV))
+ Ctx.getLValueReferenceType(getType()), LV,
+ Expr::EvaluateForCodeGen))
return false;
LV.moveInto(Result.Val);
return true;
}
+bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
+ const ASTContext &Ctx) const {
+ EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression;
+ EvalInfo Info(Ctx, Result, EM);
+ if (!::Evaluate(Result.Val, Info, this))
+ return false;
+
+ return CheckConstantExpression(Info, getExprLoc(), getType(), Result.Val,
+ Usage);
+}
+
bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
const VarDecl *VD,
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
@@ -10372,6 +10864,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::GenericSelectionExprClass:
return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx);
case Expr::IntegerLiteralClass:
+ case Expr::FixedPointLiteralClass:
case Expr::CharacterLiteralClass:
case Expr::ObjCBoolLiteralExprClass:
case Expr::CXXBoolLiteralExprClass:
@@ -10394,7 +10887,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::DeclRefExprClass: {
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
return NoDiag();
- const ValueDecl *D = dyn_cast<ValueDecl>(cast<DeclRefExpr>(E)->getDecl());
+ const ValueDecl *D = cast<DeclRefExpr>(E)->getDecl();
if (Ctx.getLangOpts().CPlusPlus &&
D && IsConstNonVolatile(D->getType())) {
// Parameter variables are never constants. Without this check,
@@ -10480,7 +10973,6 @@ 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.
@@ -10502,7 +10994,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case BO_And:
case BO_Xor:
case BO_Or:
- case BO_Comma: {
+ case BO_Comma:
+ case BO_Cmp: {
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
if (Exp->getOpcode() == BO_Div ||
@@ -10649,7 +11142,7 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,
const Expr *E,
llvm::APSInt *Value,
SourceLocation *Loc) {
- if (!E->getType()->isIntegralOrEnumerationType()) {
+ if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
if (Loc) *Loc = E->getExprLoc();
return false;
}
@@ -10786,7 +11279,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
// is a temporary being used as the 'this' pointer.
LValue This;
ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy);
- This.set(&VIE, Info.CurrentCall->Index);
+ This.set({&VIE, Info.CurrentCall->Index});
ArrayRef<const Expr*> Args;
diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp
index 6b75c51c6420..ae28c588ca31 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExternalASTMerger.h"
using namespace clang;
@@ -153,7 +154,7 @@ public:
ToContainer->setMustBuildLookupTable();
assert(Parent.CanComplete(ToContainer));
}
- return ASTImporter::Imported(From, To);
+ return To;
}
ASTImporter &GetReverse() { return Reverse; }
};
@@ -228,7 +229,7 @@ void ExternalASTMerger::CompleteType(TagDecl *Tag) {
SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
if (!SourceTag->getDefinition())
return false;
- Forward.Imported(SourceTag, Tag);
+ Forward.MapImported(SourceTag, Tag);
Forward.ImportDefinition(SourceTag);
Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
return true;
@@ -247,7 +248,7 @@ void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
SourceInterface);
if (!SourceInterface->getDefinition())
return false;
- Forward.Imported(SourceInterface, Interface);
+ Forward.MapImported(SourceInterface, Interface);
Forward.ImportDefinition(SourceInterface);
return true;
});
@@ -303,7 +304,7 @@ void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
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)));
+ Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
}
ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
@@ -351,6 +352,27 @@ void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
}
}
+template <typename DeclTy>
+static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
+ for (auto *Spec : D->specializations())
+ if (!Importer->Import(Spec))
+ return true;
+ return false;
+}
+
+/// Imports specializations from template declarations that can be specialized.
+static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) {
+ if (!isa<TemplateDecl>(D))
+ return false;
+ if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
+ return importSpecializations(FunctionTD, Importer);
+ else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
+ return importSpecializations(ClassTD, Importer);
+ else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D))
+ return importSpecializations(VarTD, Importer);
+ return false;
+}
+
bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
llvm::SmallVector<NamedDecl *, 1> Decls;
@@ -376,9 +398,18 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
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);
+ Decl *LookupRes = C.first.get();
+ ASTImporter *Importer = C.second;
+ NamedDecl *ND = cast_or_null<NamedDecl>(Importer->Import(LookupRes));
+ assert(ND);
+ // If we don't import specialization, they are not available via lookup
+ // because the lookup result is imported TemplateDecl and it does not
+ // reference its specializations until they are imported explicitly.
+ bool IsSpecImportFailed =
+ importSpecializationsIfNeeded(LookupRes, Importer);
+ assert(!IsSpecImportFailed);
+ (void)IsSpecImportFailed;
+ Decls.push_back(ND);
}
SetExternalVisibleDeclsForName(DC, Name, Decls);
return true;
diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
index 198ba9d4fbdb..40829c2e249d 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file provides the default implementation of the ExternalASTSource
+// This file provides the default implementation of the ExternalASTSource
// interface, which enables construction of AST nodes from some external
// source.
//
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
index d6bc16b6350f..64580edf004b 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/iterator.h"
using namespace clang;
@@ -50,12 +51,64 @@ static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
return nullptr;
}
-/// \brief Keeps track of the mangled names of lambda expressions and block
+/// The name of a decomposition declaration.
+struct DecompositionDeclName {
+ using BindingArray = ArrayRef<const BindingDecl*>;
+
+ /// Representative example of a set of bindings with these names.
+ BindingArray Bindings;
+
+ /// Iterators over the sequence of identifiers in the name.
+ struct Iterator
+ : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator,
+ std::random_access_iterator_tag,
+ const IdentifierInfo *> {
+ Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {}
+ const IdentifierInfo *operator*() const {
+ return (*this->I)->getIdentifier();
+ }
+ };
+ Iterator begin() const { return Iterator(Bindings.begin()); }
+ Iterator end() const { return Iterator(Bindings.end()); }
+};
+}
+
+namespace llvm {
+template<>
+struct DenseMapInfo<DecompositionDeclName> {
+ using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>;
+ using IdentInfo = llvm::DenseMapInfo<const IdentifierInfo*>;
+ static DecompositionDeclName getEmptyKey() {
+ return {ArrayInfo::getEmptyKey()};
+ }
+ static DecompositionDeclName getTombstoneKey() {
+ return {ArrayInfo::getTombstoneKey()};
+ }
+ static unsigned getHashValue(DecompositionDeclName Key) {
+ assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey()));
+ return llvm::hash_combine_range(Key.begin(), Key.end());
+ }
+ static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) {
+ if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey()))
+ return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey());
+ if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey()))
+ return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey());
+ return LHS.Bindings.size() == RHS.Bindings.size() &&
+ std::equal(LHS.begin(), LHS.end(), RHS.begin());
+ }
+};
+}
+
+namespace {
+
+/// Keeps track of the mangled names of lambda expressions and block
/// literals within a particular context.
class ItaniumNumberingContext : public MangleNumberingContext {
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
+ llvm::DenseMap<DecompositionDeclName, unsigned>
+ DecompsitionDeclManglingNumbers;
public:
unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
@@ -82,9 +135,15 @@ public:
/// Variable decls are numbered by identifier.
unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
+ if (auto *DD = dyn_cast<DecompositionDecl>(VD)) {
+ DecompositionDeclName Name{DD->bindings()};
+ return ++DecompsitionDeclManglingNumbers[Name];
+ }
+
const IdentifierInfo *Identifier = VD->getIdentifier();
if (!Identifier) {
- // VarDecl without an identifier represents an anonymous union declaration.
+ // VarDecl without an identifier represents an anonymous union
+ // declaration.
Identifier = findAnonymousUnionVarDeclName(*VD);
}
return ++VarManglingNumbers[Identifier];
@@ -131,7 +190,7 @@ public:
return false;
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- CharUnits PointerSize =
+ CharUnits PointerSize =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
return Layout.getNonVirtualSize() == PointerSize;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index 3c7e26d41370..2dc04f2f3d86 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -46,10 +46,10 @@ namespace {
/// Retrieve the declaration context that should be used when mangling the given
/// declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
- // The ABI assumes that lambda closure types that occur within
+ // The ABI assumes that lambda closure types that occur within
// default arguments live in the context of the function. However, due to
// the way in which Clang parses and creates function declarations, this is
- // not the case: the lambda closure type ends up living in the context
+ // not the case: the lambda closure type ends up living in the context
// where the function itself resides, because the function declaration itself
// had not yet been created. Fix the context here.
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -65,7 +65,7 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
= dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
return ContextParam->getDeclContext();
}
-
+
const DeclContext *DC = D->getDeclContext();
if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC)) {
return getEffectiveDeclContext(cast<Decl>(DC));
@@ -323,7 +323,7 @@ class CXXNameMangler {
AdditionalAbiTags->end());
}
- std::sort(TagList.begin(), TagList.end());
+ llvm::sort(TagList.begin(), TagList.end());
TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end());
writeSortedUniqueAbiTags(Out, TagList);
@@ -339,7 +339,7 @@ class CXXNameMangler {
}
const AbiTagList &getSortedUniqueUsedAbiTags() {
- std::sort(UsedAbiTags.begin(), UsedAbiTags.end());
+ llvm::sort(UsedAbiTags.begin(), UsedAbiTags.end());
UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()),
UsedAbiTags.end());
return UsedAbiTags;
@@ -441,7 +441,7 @@ public:
void mangleName(const NamedDecl *ND);
void mangleType(QualType T);
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
-
+
private:
bool mangleSubstitution(const NamedDecl *ND);
@@ -539,7 +539,9 @@ private:
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
const FunctionDecl *FD = nullptr);
void mangleNeonVectorType(const VectorType *T);
+ void mangleNeonVectorType(const DependentVectorType *T);
void mangleAArch64NeonVectorType(const VectorType *T);
+ void mangleAArch64NeonVectorType(const DependentVectorType *T);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
void mangleMemberExprBase(const Expr *base, bool isArrow);
@@ -590,6 +592,18 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (FD->isMain())
return false;
+ // The Windows ABI expects that we would never mangle "typical"
+ // user-defined entry points regardless of visibility or freestanding-ness.
+ //
+ // N.B. This is distinct from asking about "main". "main" has a lot of
+ // special rules associated with it in the standard while these
+ // user-defined entry points are outside of the purview of the standard.
+ // For example, there can be only one definition for "main" in a standards
+ // compliant program; however nothing forbids the existence of wmain and
+ // WinMain in the same translation unit.
+ if (FD->isMSVCRTEntryPoint())
+ return false;
+
// C++ functions and those whose names are not a simple identifier need
// mangling.
if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage)
@@ -772,7 +786,7 @@ static bool isStd(const NamespaceDecl *NS) {
if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
->isTranslationUnit())
return false;
-
+
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
return II && II->isStr("std");
}
@@ -984,7 +998,7 @@ void CXXNameMangler::mangleUnscopedTemplateName(
// ::= <substitution>
if (TemplateDecl *TD = Template.getAsTemplateDecl())
return mangleUnscopedTemplateName(TD, AdditionalAbiTags);
-
+
if (mangleSubstitution(Template))
return;
@@ -1086,7 +1100,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
if (const auto *TST = type->getAs<TemplateSpecializationType>()) {
if (!mangleSubstitution(QualType(TST, 0))) {
mangleTemplatePrefix(TST->getTemplateName());
-
+
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
@@ -1324,8 +1338,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// We must have an anonymous union or struct declaration.
- const RecordDecl *RD =
- cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());
+ const RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
// Itanium C++ ABI 5.1.2:
//
@@ -1359,7 +1372,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// safety, just handle all ObjC containers here.
if (isa<ObjCContainerDecl>(ND))
break;
-
+
// We must have an anonymous struct.
const TagDecl *TD = cast<TagDecl>(ND);
if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
@@ -1376,7 +1389,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
// <unnamed-type-name> ::= <closure-type-name>
- //
+ //
// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
// <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'.
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
@@ -1502,9 +1515,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
const DeclContext *DC,
const AbiTagList *AdditionalAbiTags,
bool NoFunction) {
- // <nested-name>
+ // <nested-name>
// ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
// <template-args> E
Out << 'N';
@@ -1517,7 +1530,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
mangleQualifiers(MethodQuals);
mangleRefQualifier(Method->getRefQualifier());
}
-
+
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
@@ -1548,7 +1561,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
const AbiTagList *AdditionalAbiTags) {
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
// := Z <function encoding> E s [<discriminator>]
- // <local-name> := Z <function encoding> E d [ <parameter number> ]
+ // <local-name> := Z <function encoding> E d [ <parameter number> ]
// _ <entity name>
// <discriminator> := _ <non-negative number>
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
@@ -1578,9 +1591,9 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
// be a bug that is fixed in trunk.
if (RD) {
- // The parameter number is omitted for the last parameter, 0 for the
- // second-to-last parameter, 1 for the third-to-last parameter, etc. The
- // <entity name> will of course contain a <closure-type-name>: Its
+ // The parameter number is omitted for the last parameter, 0 for the
+ // second-to-last parameter, 1 for the third-to-last parameter, etc. The
+ // <entity name> will of course contain a <closure-type-name>: Its
// numbering will be local to the particular argument in which it appears
// -- other default arguments do not affect its encoding.
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
@@ -1597,7 +1610,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
}
}
}
-
+
// Mangle the name relative to the closest enclosing function.
// equality ok because RD derived from ND above
if (D == RD) {
@@ -1686,8 +1699,8 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
}
void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
- // If the context of a closure type is an initializer for a class member
- // (static or nonstatic), it is encoded in a qualified name with a final
+ // If the context of a closure type is an initializer for a class member
+ // (static or nonstatic), it is encoded in a qualified name with a final
// <prefix> of the form:
//
// <data-member-prefix> := <member source-name> M
@@ -1717,9 +1730,9 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
Lambda->getLambdaStaticInvoker());
Out << "E";
-
- // The number is omitted for the first closure type with a given
- // <lambda-sig> in a given context; it is n-2 for the nth closure type
+
+ // The number is omitted for the first closure type with a given
+ // <lambda-sig> in a given context; it is n-2 for the nth closure type
// (in lexical order) with that same <lambda-sig> and context.
//
// The AST keeps track of the number for us.
@@ -1727,7 +1740,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
assert(Number > 0 && "Lambda should be mangled as an unnamed class");
if (Number > 1)
mangleNumber(Number - 2);
- Out << '_';
+ Out << '_';
}
void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
@@ -1782,10 +1795,10 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
assert(!isLocalContainerContext(DC));
- const NamedDecl *ND = cast<NamedDecl>(DC);
+ const NamedDecl *ND = cast<NamedDecl>(DC);
if (mangleSubstitution(ND))
return;
-
+
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
@@ -1931,6 +1944,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::VariableArray:
case Type::DependentSizedArray:
case Type::DependentAddressSpace:
+ case Type::DependentVector:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -2272,19 +2286,19 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
switch (Quals.getObjCLifetime()) {
case Qualifiers::OCL_None:
break;
-
+
case Qualifiers::OCL_Weak:
// Do nothing as we already handled this case above.
break;
-
+
case Qualifiers::OCL_Strong:
mangleVendorQualifier("__strong");
break;
-
+
case Qualifiers::OCL_Autoreleasing:
mangleVendorQualifier("__autoreleasing");
break;
-
+
case Qualifiers::OCL_ExplicitNone:
// The __unsafe_unretained qualifier is *not* mangled, so that
// __unsafe_unretained types in ARC produce the same manglings as the
@@ -2315,11 +2329,11 @@ void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
switch (RefQualifier) {
case RQ_None:
break;
-
+
case RQ_LValue:
Out << 'R';
break;
-
+
case RQ_RValue:
Out << 'O';
break;
@@ -2330,7 +2344,8 @@ void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodName(MD, Out);
}
-static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty) {
+static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty,
+ ASTContext &Ctx) {
if (Quals)
return true;
if (Ty->isSpecificBuiltinType(BuiltinType::ObjCSel))
@@ -2339,21 +2354,25 @@ static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty) {
return true;
if (Ty->isBuiltinType())
return false;
-
+ // Through to Clang 6.0, we accidentally treated undeduced auto types as
+ // substitution candidates.
+ if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver6 &&
+ isa<AutoType>(Ty))
+ return false;
return true;
}
void CXXNameMangler::mangleType(QualType T) {
// If our type is instantiation-dependent but not dependent, we mangle
- // it as it was written in the source, removing any top-level sugar.
+ // it as it was written in the source, removing any top-level sugar.
// Otherwise, use the canonical type.
//
- // FIXME: This is an approximation of the instantiation-dependent name
+ // FIXME: This is an approximation of the instantiation-dependent name
// mangling rules, since we should really be using the type as written and
// augmented via semantic analysis (i.e., with implicit conversions and
- // default template arguments) for any instantiation-dependent type.
+ // default template arguments) for any instantiation-dependent type.
// Unfortunately, that requires several changes to our AST:
- // - Instantiation-dependent TemplateSpecializationTypes will need to be
+ // - Instantiation-dependent TemplateSpecializationTypes will need to be
// uniqued, so that we can handle substitutions properly
// - Default template arguments will need to be represented in the
// TemplateSpecializationType, since they need to be mangled even though
@@ -2383,16 +2402,16 @@ void CXXNameMangler::mangleType(QualType T) {
do {
// Don't desugar through template specialization types that aren't
// type aliases. We need to mangle the template arguments as written.
- if (const TemplateSpecializationType *TST
+ if (const TemplateSpecializationType *TST
= dyn_cast<TemplateSpecializationType>(T))
if (!TST->isTypeAlias())
break;
- QualType Desugared
+ QualType Desugared
= T.getSingleStepDesugaredType(Context.getASTContext());
if (Desugared == T)
break;
-
+
T = Desugared;
} while (true);
}
@@ -2400,7 +2419,8 @@ void CXXNameMangler::mangleType(QualType T) {
Qualifiers quals = split.Quals;
const Type *ty = split.Ty;
- bool isSubstitutable = isTypeSubstitutable(quals, ty);
+ bool isSubstitutable =
+ isTypeSubstitutable(quals, ty, Context.getASTContext());
if (isSubstitutable && mangleSubstitution(T))
return;
@@ -2415,7 +2435,7 @@ void CXXNameMangler::mangleType(QualType T) {
}
if (quals || ty->isDependentAddressSpaceType()) {
- if (const DependentAddressSpaceType *DAST =
+ if (const DependentAddressSpaceType *DAST =
dyn_cast<DependentAddressSpaceType>(ty)) {
SplitQualType splitDAST = DAST->getPointeeType().split();
mangleQualifiers(splitDAST.Quals, DAST);
@@ -2520,6 +2540,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::WChar_U:
Out << 'w';
break;
+ case BuiltinType::Char8:
+ Out << "Du";
+ break;
case BuiltinType::Char16:
Out << "Ds";
break;
@@ -2544,6 +2567,31 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::Float16:
Out << "DF16_";
break;
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
+ llvm_unreachable("Fixed point types are disabled for c++");
case BuiltinType::Half:
Out << "Dh";
break;
@@ -2689,12 +2737,12 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
// e.g. "const" in "int (A::*)() const".
- mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));
+ mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals()));
// Mangle instantiation-dependent exception-specification, if present,
// per cxx-abi-dev proposal on 2016-10-11.
if (T->hasInstantiationDependentExceptionSpec()) {
- if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
+ if (isComputedNoexcept(T->getExceptionSpecType())) {
Out << "DO";
mangleExpression(T->getNoexceptExpr());
Out << "E";
@@ -2705,7 +2753,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
mangleType(ExceptTy);
Out << "E";
}
- } else if (T->isNothrow(getASTContext())) {
+ } else if (T->isNothrow()) {
Out << "Do";
}
@@ -2851,7 +2899,7 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) {
QualType PointeeType = T->getPointeeType();
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
mangleType(FPT);
-
+
// Itanium C++ ABI 5.1.8:
//
// The type of a non-static member function is considered to be different,
@@ -2859,8 +2907,8 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) {
// static member function whose type appears similar. The types of two
// non-static member functions are considered to be different, for the
// purposes of substitution, if the functions are members of different
- // classes. In other words, for the purposes of substitution, the class of
- // which the function is a member is considered part of the type of
+ // classes. In other words, for the purposes of substitution, the class of
+ // which the function is a member is considered part of the type of
// function.
// Given that we already substitute member function pointers as a
@@ -2967,6 +3015,14 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
Out << BaseName << EltName;
}
+void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this dependent neon vector type yet");
+ Diags.Report(T->getAttributeLoc(), DiagID);
+}
+
static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) {
switch (EltType->getKind()) {
case BuiltinType::SChar:
@@ -3034,6 +3090,13 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str();
Out << TypeName.length() << TypeName;
}
+void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this dependent neon vector type yet");
+ Diags.Report(T->getAttributeLoc(), DiagID);
+}
// GNU extension: vector types
// <type> ::= <vector-type>
@@ -3064,6 +3127,32 @@ void CXXNameMangler::mangleType(const VectorType *T) {
else
mangleType(T->getElementType());
}
+
+void CXXNameMangler::mangleType(const DependentVectorType *T) {
+ if ((T->getVectorKind() == VectorType::NeonVector ||
+ T->getVectorKind() == VectorType::NeonPolyVector)) {
+ llvm::Triple Target = getASTContext().getTargetInfo().getTriple();
+ llvm::Triple::ArchType Arch =
+ getASTContext().getTargetInfo().getTriple().getArch();
+ if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) &&
+ !Target.isOSDarwin())
+ mangleAArch64NeonVectorType(T);
+ else
+ mangleNeonVectorType(T);
+ return;
+ }
+
+ Out << "Dv";
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ if (T->getVectorKind() == VectorType::AltiVecPixel)
+ Out << 'p';
+ else if (T->getVectorKind() == VectorType::AltiVecBool)
+ Out << 'b';
+ else
+ mangleType(T->getElementType());
+}
+
void CXXNameMangler::mangleType(const ExtVectorType *T) {
mangleType(static_cast<const VectorType*>(T));
}
@@ -3136,9 +3225,9 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
} else {
if (mangleSubstitution(QualType(T, 0)))
return;
-
+
mangleTemplatePrefix(T->getTemplateName());
-
+
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
@@ -3194,7 +3283,7 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
- mangleTemplateArgs(T->getArgs(), T->getNumArgs());
+ mangleTemplateArgs(T->getArgs(), T->getNumArgs());
Out << 'E';
}
@@ -3239,7 +3328,7 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
// mangle it as the underlying type since they are equivalent.
if (T->isDependentType()) {
Out << 'U';
-
+
switch (T->getUTTKind()) {
case UnaryTransformType::EnumUnderlyingType:
Out << "3eut";
@@ -3251,14 +3340,13 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
}
void CXXNameMangler::mangleType(const AutoType *T) {
- QualType D = T->getDeducedType();
- // <builtin-type> ::= Da # dependent auto
- if (D.isNull()) {
- assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType &&
- "shouldn't need to mangle __auto_type!");
- Out << (T->isDecltypeAuto() ? "Dc" : "Da");
- } else
- mangleType(D);
+ assert(T->getDeducedType().isNull() &&
+ "Deduced AutoType shouldn't be handled here!");
+ assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType &&
+ "shouldn't need to mangle __auto_type!");
+ // <builtin-type> ::= Da # auto
+ // ::= Dc # decltype(auto)
+ Out << (T->isDecltypeAuto() ? "Dc" : "Da");
}
void CXXNameMangler::mangleType(const DeducedTemplateSpecializationType *T) {
@@ -3410,7 +3498,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// ::= L <mangled-name> E # external name
// ::= fpT # 'this' expression
QualType ImplicitlyConvertedToType;
-
+
recurse:
switch (E->getStmtClass()) {
case Expr::NoStmtClass:
@@ -3471,6 +3559,7 @@ recurse:
case Expr::AsTypeExprClass:
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
+ case Expr::FixedPointLiteralClass:
{
if (!NullOut) {
// As bad as this diagnostic is, it's better than crashing.
@@ -3772,24 +3861,24 @@ recurse:
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
-
+
if (!SAE->isInstantiationDependent()) {
// Itanium C++ ABI:
- // If the operand of a sizeof or alignof operator is not
- // instantiation-dependent it is encoded as an integer literal
+ // If the operand of a sizeof or alignof operator is not
+ // instantiation-dependent it is encoded as an integer literal
// reflecting the result of the operator.
//
- // If the result of the operator is implicitly converted to a known
- // integer type, that type is used for the literal; otherwise, the type
+ // If the result of the operator is implicitly converted to a known
+ // integer type, that type is used for the literal; otherwise, the type
// of std::size_t or std::ptrdiff_t is used.
- QualType T = (ImplicitlyConvertedToType.isNull() ||
+ QualType T = (ImplicitlyConvertedToType.isNull() ||
!ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
: ImplicitlyConvertedToType;
llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());
mangleIntegerLiteral(T, V);
break;
}
-
+
switch(SAE->getKind()) {
case UETT_SizeOf:
Out << 's';
@@ -3905,16 +3994,16 @@ recurse:
E = cast<ImplicitCastExpr>(E)->getSubExpr();
goto recurse;
}
-
+
case Expr::ObjCBridgedCastExprClass: {
- // Mangle ownership casts as a vendor extended operator __bridge,
+ // Mangle ownership casts as a vendor extended operator __bridge,
// __bridge_transfer, or __bridge_retain.
StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
Out << "v1U" << Kind.size() << Kind;
}
// Fall through to mangle the cast itself.
LLVM_FALLTHROUGH;
-
+
case Expr::CStyleCastExprClass:
mangleCastExpression(E, "cv");
break;
@@ -4054,7 +4143,7 @@ recurse:
Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
-
+
case Expr::CXXBoolLiteralExprClass:
Out << "Lb";
Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
@@ -4109,12 +4198,12 @@ recurse:
Out << "LDnE";
break;
}
-
+
case Expr::PackExpansionExprClass:
Out << "sp";
mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
break;
-
+
case Expr::SizeOfPackExprClass: {
auto *SPE = cast<SizeOfPackExpr>(E);
if (SPE->isPartiallySubstituted()) {
@@ -4341,11 +4430,11 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
// ::= J <template-arg>* E # argument pack
if (!A.isInstantiationDependent() || A.isDependent())
A = Context.getASTContext().getCanonicalTemplateArgument(A);
-
+
switch (A.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Cannot mangle NULL template argument");
-
+
case TemplateArgument::Type:
mangleType(A.getAsType());
break;
@@ -4372,7 +4461,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
break;
}
}
-
+
Out << 'X';
mangleExpression(E);
Out << 'E';
@@ -4489,7 +4578,7 @@ bool CXXNameMangler::mangleSubstitution(QualType T) {
bool CXXNameMangler::mangleSubstitution(TemplateName Template) {
if (TemplateDecl *TD = Template.getAsTemplateDecl())
return mangleSubstitution(TD);
-
+
Template = Context.getASTContext().getCanonicalTemplateName(Template);
return mangleSubstitution(
reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
@@ -4654,7 +4743,7 @@ void CXXNameMangler::addSubstitution(QualType T) {
void CXXNameMangler::addSubstitution(TemplateName Template) {
if (TemplateDecl *TD = Template.getAsTemplateDecl())
return addSubstitution(TD);
-
+
Template = Context.getASTContext().getCanonicalTemplateName(Template);
addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
}
@@ -4776,14 +4865,14 @@ void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
// # base is the nominal target function of thunk
// # first call-offset is 'this' adjustment
// # second call-offset is result adjustment
-
+
assert(!isa<CXXDestructorDecl>(MD) &&
"Use mangleCXXDtor for destructor decls!");
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZT";
if (!Thunk.Return.isEmpty())
Mangler.getStream() << 'c';
-
+
// Mangle the 'this' pointer adjustment.
Mangler.mangleCallOffset(Thunk.This.NonVirtual,
Thunk.This.Virtual.Itanium.VCallOffsetOffset);
@@ -4805,7 +4894,7 @@ void ItaniumMangleContextImpl::mangleCXXDtorThunk(
Mangler.getStream() << "_ZT";
// Mangle the 'this' pointer adjustment.
- Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
+ Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
ThisAdjustment.Virtual.Itanium.VCallOffsetOffset);
Mangler.mangleFunctionEncoding(DD);
diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
index 56a2500274a7..b0e5146e8194 100644
--- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
@@ -44,7 +44,7 @@ static void mangleFunctionBlock(MangleContext &Context,
if (discriminator == 0)
Out << "__" << Outer << "_block_invoke";
else
- Out << "__" << Outer << "_block_invoke_" << discriminator+1;
+ Out << "__" << Outer << "_block_invoke_" << discriminator+1;
}
void MangleContext::anchor() { }
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
index b19491f31304..3b417c135285 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -25,7 +25,7 @@ using namespace clang;
namespace {
-/// \brief Numbers things which need to correspond across multiple TUs.
+/// Numbers things which need to correspond across multiple TUs.
/// Typically these are things like static locals, lambdas, or blocks.
class MicrosoftNumberingContext : public MangleNumberingContext {
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
@@ -106,7 +106,7 @@ public:
void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) override {
TD = TD->getCanonicalDecl();
- DD = cast<TypedefNameDecl>(DD->getCanonicalDecl());
+ DD = DD->getCanonicalDecl();
TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
if (!I)
I = DD;
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index b4e7a82eb000..40281481f1d1 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -76,7 +76,7 @@ getLambdaDefaultArgumentDeclContext(const Decl *D) {
return nullptr;
}
-/// \brief Retrieve the declaration context that should be used when mangling
+/// Retrieve the declaration context that should be used when mangling
/// the given declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
// The ABI assumes that lambda closure types that occur within
@@ -135,7 +135,8 @@ public:
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- raw_ostream &) override;
+ const MethodVFTableLocation &ML,
+ raw_ostream &Out) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
@@ -290,16 +291,15 @@ public:
raw_ostream &getStream() const { return Out; }
- void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
+ void mangle(const NamedDecl *D, StringRef Prefix = "?");
void mangleName(const NamedDecl *ND);
void mangleFunctionEncoding(const FunctionDecl *FD, bool ShouldMangle);
void mangleVariableEncoding(const VarDecl *VD);
void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD);
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
const CXXMethodDecl *MD);
- void mangleVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML);
+ void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ const MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
void mangleTagTypeKind(TagTypeKind TK);
void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName,
@@ -337,6 +337,8 @@ private:
void mangleArgumentType(QualType T, SourceRange Range);
void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA);
+ bool isArtificialTagType(QualType T) const;
+
// Declare manglers for every type class.
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT)
@@ -362,6 +364,10 @@ private:
const TemplateArgumentList &TemplateArgs);
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
const NamedDecl *Parm);
+
+ void mangleObjCProtocol(const ObjCProtocolDecl *PD);
+ void mangleObjCLifetime(const QualType T, Qualifiers Quals,
+ SourceRange Range);
};
}
@@ -439,7 +445,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
- else
+ else if (!isa<ObjCInterfaceDecl>(D))
llvm_unreachable("Tried to mangle unexpected NamedDecl!");
}
@@ -603,7 +609,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
if (MD->isVirtual()) {
MicrosoftVTableContext *VTContext =
cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
- const MicrosoftVTableContext::MethodVFTableLocation &ML =
+ MethodVFTableLocation ML =
VTContext->getMethodVFTableLocation(GlobalDecl(MD));
mangleVirtualMemPtrThunk(MD, ML);
NVOffset = ML.VFPtrOffset.getQuantity();
@@ -640,8 +646,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
}
void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+ const CXXMethodDecl *MD, const MethodVFTableLocation &ML) {
// Get the vftable offset.
CharUnits PointerWidth = getASTContext().toCharUnitsFromBits(
getASTContext().getTargetInfo().getPointerWidth(0));
@@ -755,7 +760,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// type [ -> template-parameters]
// \-> namespace[s]
// What we do is we create a new mangler, mangle the same type (without
- // a namespace suffix) to a string using the extra mangler and then use
+ // a namespace suffix) to a string using the extra mangler and then use
// the mangled type name as a key to check the mangling of different types
// for aliasing.
@@ -881,11 +886,13 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// associate typedef mangled in if they have one.
Name += "<unnamed-type-";
Name += TND->getName();
- } else if (auto *ED = dyn_cast<EnumDecl>(TD)) {
- auto EnumeratorI = ED->enumerator_begin();
- assert(EnumeratorI != ED->enumerator_end());
+ } else if (isa<EnumDecl>(TD) &&
+ cast<EnumDecl>(TD)->enumerator_begin() !=
+ cast<EnumDecl>(TD)->enumerator_end()) {
+ // Anonymous non-empty enums mangle in the first enumerator.
+ auto *ED = cast<EnumDecl>(TD);
Name += "<unnamed-enum-";
- Name += EnumeratorI->getName();
+ Name += ED->enumerator_begin()->getName();
} else {
// Otherwise, number the types using a $S prefix.
Name += "<unnamed-type-$S";
@@ -1006,7 +1013,7 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
if (const auto *ND = dyn_cast<NamedDecl>(MC))
mangleUnqualifiedName(ND);
// MS ABI and Itanium manglings are in inverted scopes. In the case of a
- // RecordDecl, mangle the entire scope hierachy at this point rather than
+ // RecordDecl, mangle the entire scope hierarchy at this point rather than
// just the unqualified name to get the ordering correct.
if (const auto *RD = dyn_cast<RecordDecl>(DC))
mangleName(RD);
@@ -1364,15 +1371,16 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
break;
}
case TemplateArgument::Declaration: {
- const NamedDecl *ND = cast<NamedDecl>(TA.getAsDecl());
+ const NamedDecl *ND = TA.getAsDecl();
if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) {
- mangleMemberDataPointer(
- cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentDecl(),
- cast<ValueDecl>(ND));
+ mangleMemberDataPointer(cast<CXXRecordDecl>(ND->getDeclContext())
+ ->getMostRecentNonInjectedDecl(),
+ cast<ValueDecl>(ND));
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
if (MD && MD->isInstance()) {
- mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD);
+ mangleMemberFunctionPointer(
+ MD->getParent()->getMostRecentNonInjectedDecl(), MD);
} else {
Out << "$1?";
mangleName(FD);
@@ -1456,6 +1464,47 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
}
}
+void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) {
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+
+ Stream << "?$";
+ Extra.mangleSourceName("Protocol");
+ Extra.mangleArtificalTagType(TTK_Struct, PD->getName());
+
+ mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+}
+
+void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
+ Qualifiers Quals,
+ SourceRange Range) {
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+
+ Stream << "?$";
+ switch (Quals.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ break;
+ case Qualifiers::OCL_Autoreleasing:
+ Extra.mangleSourceName("Autoreleasing");
+ break;
+ case Qualifiers::OCL_Strong:
+ Extra.mangleSourceName("Strong");
+ break;
+ case Qualifiers::OCL_Weak:
+ Extra.mangleSourceName("Weak");
+ break;
+ }
+ Extra.manglePointerCVQualifiers(Quals);
+ Extra.manglePointerExtQualifiers(Quals, Type);
+ Extra.mangleType(Type, Range);
+
+ mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+}
+
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
bool IsMember) {
// <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
@@ -1558,12 +1607,11 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
QualType PointeeType) {
- bool HasRestrict = Quals.hasRestrict();
if (PointersAre64Bit &&
(PointeeType.isNull() || !PointeeType->isFunctionType()))
Out << 'E';
- if (HasRestrict)
+ if (Quals.hasRestrict())
Out << 'I';
if (Quals.hasUnaligned() ||
@@ -1684,6 +1732,8 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
switch (QMM) {
case QMM_Drop:
+ if (Quals.hasObjCLifetime())
+ Quals = Quals.withoutObjCLifetime();
break;
case QMM_Mangle:
if (const FunctionType *FT = dyn_cast<FunctionType>(T)) {
@@ -1702,7 +1752,9 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
case QMM_Result:
// Presence of __unaligned qualifier shouldn't affect mangling here.
Quals.removeUnaligned();
- if ((!IsPointer && Quals) || isa<TagType>(T)) {
+ if (Quals.hasObjCLifetime())
+ Quals = Quals.withoutObjCLifetime();
+ if ((!IsPointer && Quals) || isa<TagType>(T) || isArtificialTagType(T)) {
Out << '?';
mangleQualifiers(Quals, false);
}
@@ -1832,16 +1884,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
llvm_unreachable("placeholder types shouldn't get to name mangling");
case BuiltinType::ObjCId:
- Out << "PA";
- mangleArtificalTagType(TTK_Struct, "objc_object");
+ mangleArtificalTagType(TTK_Struct, ".objc_object");
break;
case BuiltinType::ObjCClass:
- Out << "PA";
- mangleArtificalTagType(TTK_Struct, "objc_class");
+ mangleArtificalTagType(TTK_Struct, ".objc_class");
break;
case BuiltinType::ObjCSel:
- Out << "PA";
- mangleArtificalTagType(TTK_Struct, "objc_selector");
+ mangleArtificalTagType(TTK_Struct, ".objc_selector");
break;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -1875,8 +1924,39 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
break;
case BuiltinType::Float16:
- case BuiltinType::Float128:
- case BuiltinType::Half: {
+ mangleArtificalTagType(TTK_Struct, "_Float16", {"__clang"});
+ break;
+
+ case BuiltinType::Half:
+ mangleArtificalTagType(TTK_Struct, "_Half", {"__clang"});
+ break;
+
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
+ case BuiltinType::Char8:
+ case BuiltinType::Float128: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this built-in %0 type yet");
@@ -2140,6 +2220,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
case CC_Swift: Out << 'S'; break;
+ case CC_PreserveMost: Out << 'U'; break;
case CC_X86RegCall: Out << 'w'; break;
}
}
@@ -2202,8 +2283,11 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
mangleTagTypeKind(TD->getTagKind());
mangleName(TD);
}
+
+// If you add a call to this, consider updating isArtificialTagType() too.
void MicrosoftCXXNameMangler::mangleArtificalTagType(
- TagTypeKind TK, StringRef UnqualifiedName, ArrayRef<StringRef> NestedNames) {
+ TagTypeKind TK, StringRef UnqualifiedName,
+ ArrayRef<StringRef> NestedNames) {
// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
mangleTagTypeKind(TK);
@@ -2290,8 +2374,8 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
// <type> ::= <pointer-to-member-type>
// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
// <class name> <type>
-void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, Qualifiers Quals,
- SourceRange Range) {
+void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
+ Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
@@ -2337,10 +2421,16 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
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();
+ switch (Quals.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ break;
+ case Qualifiers::OCL_Autoreleasing:
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ return mangleObjCLifetime(PointeeType, Quals, Range);
+ }
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
@@ -2384,6 +2474,26 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
+// Returns true for types that mangleArtificalTagType() gets called for with
+// TTK_Union, TTK_Struct, TTK_Class and where compatibility with MSVC's
+// mangling matters.
+// (It doesn't matter for Objective-C types and the like that cl.exe doesn't
+// support.)
+bool MicrosoftCXXNameMangler::isArtificialTagType(QualType T) const {
+ const Type *ty = T.getTypePtr();
+ switch (ty->getTypeClass()) {
+ default:
+ return false;
+
+ case Type::Vector: {
+ // For ABI compatibility only __m64, __m128(id), and __m256(id) matter,
+ // but since mangleType(VectorType*) always calls mangleArtificalTagType()
+ // just always return true (the other vector types are clang-only).
+ return true;
+ }
+ }
+}
+
void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
SourceRange Range) {
const BuiltinType *ET = T->getElementType()->getAs<BuiltinType>();
@@ -2430,6 +2540,16 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
Qualifiers Quals, SourceRange Range) {
mangleType(static_cast<const VectorType *>(T), Quals, Range);
}
+
+void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T,
+ Qualifiers, SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this dependent-sized vector type yet");
+ Diags.Report(Range.getBegin(), DiagID) << Range;
+}
+
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -2450,16 +2570,41 @@ void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T,
void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
SourceRange) {
- // ObjC interfaces have structs underlying them.
+ // ObjC interfaces are mangled as if they were structs with a name that is
+ // not a valid C/C++ identifier
mangleTagTypeKind(TTK_Struct);
- mangleName(T->getDecl());
+ mangle(T->getDecl(), ".objc_cls_");
}
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, QMM_Drop);
+ if (T->qual_empty())
+ return mangleType(T->getBaseType(), Range, QMM_Drop);
+
+ ArgBackRefMap OuterArgsContext;
+ BackRefVec OuterTemplateContext;
+
+ TypeBackReferences.swap(OuterArgsContext);
+ NameBackReferences.swap(OuterTemplateContext);
+
+ mangleTagTypeKind(TTK_Struct);
+
+ Out << "?$";
+ if (T->isObjCId())
+ mangleSourceName(".objc_object");
+ else if (T->isObjCClass())
+ mangleSourceName(".objc_class");
+ else
+ mangleSourceName((".objc_cls_" + T->getInterface()->getName()).str());
+
+ for (const auto &Q : T->quals())
+ mangleObjCProtocol(Q);
+ Out << '@';
+
+ Out << '@';
+
+ TypeBackReferences.swap(OuterArgsContext);
+ NameBackReferences.swap(OuterTemplateContext);
}
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
@@ -2700,17 +2845,12 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
}
}
-void
-MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- raw_ostream &Out) {
- MicrosoftVTableContext *VTContext =
- cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
- const MicrosoftVTableContext::MethodVFTableLocation &ML =
- VTContext->getMethodVFTableLocation(GlobalDecl(MD));
-
+void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(
+ const CXXMethodDecl *MD, const MethodVFTableLocation &ML,
+ raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?";
+ Mangler.getStream() << '?';
Mangler.mangleVirtualMemPtrThunk(MD, ML);
}
@@ -2719,7 +2859,7 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?";
+ Mangler.getStream() << '?';
Mangler.mangleName(MD);
mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO);
if (!Thunk.Return.isEmpty())
@@ -2740,7 +2880,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
assert(Type == Dtor_Deleting);
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
- Mangler.getStream() << "\01??_E";
+ Mangler.getStream() << "??_E";
Mangler.mangleName(DD->getParent());
mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
@@ -2756,9 +2896,9 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable(
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
if (Derived->hasAttr<DLLImportAttr>())
- Mangler.getStream() << "\01??_S";
+ Mangler.getStream() << "??_S";
else
- Mangler.getStream() << "\01??_7";
+ Mangler.getStream() << "??_7";
Mangler.mangleName(Derived);
Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
for (const CXXRecordDecl *RD : BasePath)
@@ -2775,7 +2915,7 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable(
// is always '7' for vbtables.
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_8";
+ Mangler.getStream() << "??_8";
Mangler.mangleName(Derived);
Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const.
for (const CXXRecordDecl *RD : BasePath)
@@ -2786,7 +2926,7 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable(
void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R0";
+ Mangler.getStream() << "??_R0";
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
Mangler.getStream() << "@8";
}
@@ -2802,7 +2942,7 @@ void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap(
const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_K";
+ Mangler.getStream() << "??_K";
Mangler.mangleName(SrcRD);
Mangler.getStream() << "$C";
Mangler.mangleName(DstRD);
@@ -2848,7 +2988,7 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableType(
msvc_hashing_ostream MHO(Stream);
mangleCXXRTTI(T, MHO);
}
- Mangler.getStream() << RTTIMangling.substr(1);
+ Mangler.getStream() << RTTIMangling;
// VS2015 CTP6 omits the copy-constructor in the mangled name. This name is,
// in fact, superfluous but I'm not sure the change was made consciously.
@@ -2860,7 +3000,7 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableType(
msvc_hashing_ostream MHO(Stream);
mangleCXXCtor(CD, CT, MHO);
}
- Mangler.getStream() << CopyCtorMangling.substr(1);
+ Mangler.getStream() << CopyCtorMangling;
Mangler.getStream() << Size;
if (VBPtrOffset == -1) {
@@ -2879,7 +3019,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R1";
+ Mangler.getStream() << "??_R1";
Mangler.mangleNumber(NVOffset);
Mangler.mangleNumber(VBPtrOffset);
Mangler.mangleNumber(VBTableOffset);
@@ -2892,7 +3032,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
const CXXRecordDecl *Derived, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R2";
+ Mangler.getStream() << "??_R2";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
@@ -2901,7 +3041,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor(
const CXXRecordDecl *Derived, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R3";
+ Mangler.getStream() << "??_R3";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
@@ -2917,16 +3057,16 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
llvm::raw_svector_ostream Stream(VFTableMangling);
mangleCXXVFTable(Derived, BasePath, Stream);
- if (VFTableMangling.startswith("\01??@")) {
+ if (VFTableMangling.startswith("??@")) {
assert(VFTableMangling.endswith("@"));
Out << VFTableMangling << "??_R4@";
return;
}
- assert(VFTableMangling.startswith("\01??_7") ||
- VFTableMangling.startswith("\01??_S"));
+ assert(VFTableMangling.startswith("??_7") ||
+ VFTableMangling.startswith("??_S"));
- Out << "\01??_R4" << StringRef(VFTableMangling).drop_front(5);
+ Out << "??_R4" << StringRef(VFTableMangling).drop_front(4);
}
void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
@@ -2937,7 +3077,7 @@ void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
// so the numbering here doesn't have to be the same across TUs.
//
// <mangled-name> ::= ?filt$ <filter-number> @0
- Mangler.getStream() << "\01?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
+ Mangler.getStream() << "?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
Mangler.mangleName(EnclosingDecl);
}
@@ -2949,7 +3089,7 @@ void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
// so the numbering here doesn't have to be the same across TUs.
//
// <mangled-name> ::= ?fin$ <filter-number> @0
- Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
+ Mangler.getStream() << "?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
Mangler.mangleName(EnclosingDecl);
}
@@ -2982,7 +3122,7 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?$RT" << ManglingNumber << '@';
+ Mangler.getStream() << "?$RT" << ManglingNumber << '@';
Mangler.mangle(VD, "");
}
@@ -2991,7 +3131,7 @@ void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?$TSS" << GuardNum << '@';
+ Mangler.getStream() << "?$TSS" << GuardNum << '@';
Mangler.mangleNestedName(VD);
Mangler.getStream() << "@4HA";
}
@@ -3013,9 +3153,9 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
bool Visible = VD->isExternallyVisible();
if (Visible) {
- Mangler.getStream() << (VD->getTLSKind() ? "\01??__J" : "\01??_B");
+ Mangler.getStream() << (VD->getTLSKind() ? "??__J" : "??_B");
} else {
- Mangler.getStream() << "\01?$S1@";
+ Mangler.getStream() << "?$S1@";
}
unsigned ScopeDepth = 0;
if (Visible && !getNextDiscriminator(VD, ScopeDepth))
@@ -3035,7 +3175,7 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??__" << CharCode;
+ Mangler.getStream() << "??__" << CharCode;
Mangler.mangleName(D);
if (D->isStaticDataMember()) {
Mangler.mangleVariableEncoding(D);
@@ -3061,14 +3201,14 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
raw_ostream &Out) {
- // <char-type> ::= 0 # char
- // ::= 1 # wchar_t
- // ::= ??? # char16_t/char32_t will need a mangling too...
+ // <char-type> ::= 0 # char, char16_t, char32_t
+ // # (little endian char data in mangling)
+ // ::= 1 # wchar_t (big endian char data in mangling)
//
// <literal-length> ::= <non-negative integer> # the length of the literal
//
// <encoded-crc> ::= <hex digit>+ @ # crc of the literal including
- // # null-terminator
+ // # trailing null bytes
//
// <encoded-string> ::= <simple character> # uninteresting character
// ::= '?$' <hex digit> <hex digit> # these two nibbles
@@ -3081,7 +3221,19 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
// <literal> ::= '??_C@_' <char-type> <literal-length> <encoded-crc>
// <encoded-string> '@'
MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "\01??_C@_";
+ Mangler.getStream() << "??_C@_";
+
+ // The actual string length might be different from that of the string literal
+ // in cases like:
+ // char foo[3] = "foobar";
+ // char bar[42] = "foobar";
+ // Where it is truncated or zero-padded to fit the array. This is the length
+ // used for mangling, and any trailing null-bytes also need to be mangled.
+ unsigned StringLength = getASTContext()
+ .getAsConstantArrayType(SL->getType())
+ ->getSize()
+ .getZExtValue();
+ unsigned StringByteLength = StringLength * SL->getCharByteWidth();
// <char-type>: The "kind" of string literal is encoded into the mangled name.
if (SL->isWide())
@@ -3090,14 +3242,13 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
Mangler.getStream() << '0';
// <literal-length>: The next part of the mangled name consists of the length
- // of the string.
- // The StringLiteral does not consider the NUL terminator byte(s) but the
- // mangling does.
- // N.B. The length is in terms of bytes, not characters.
- Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth());
+ // of the string in bytes.
+ Mangler.mangleNumber(StringByteLength);
auto GetLittleEndianByte = [&SL](unsigned Index) {
unsigned CharByteWidth = SL->getCharByteWidth();
+ if (Index / CharByteWidth >= SL->getLength())
+ return static_cast<char>(0);
uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
unsigned OffsetInCodeUnit = Index % CharByteWidth;
return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff);
@@ -3105,6 +3256,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
auto GetBigEndianByte = [&SL](unsigned Index) {
unsigned CharByteWidth = SL->getCharByteWidth();
+ if (Index / CharByteWidth >= SL->getLength())
+ return static_cast<char>(0);
uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth);
return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff);
@@ -3112,21 +3265,15 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
// CRC all the bytes of the StringLiteral.
llvm::JamCRC JC;
- for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I)
+ for (unsigned I = 0, E = StringByteLength; I != E; ++I)
JC.update(GetLittleEndianByte(I));
- // The NUL terminator byte(s) were not present earlier,
- // we need to manually process those bytes into the CRC.
- for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth();
- ++NullTerminator)
- JC.update('\x00');
-
// <encoded-crc>: The CRC is encoded utilizing the standard number mangling
// scheme.
Mangler.mangleNumber(JC.getCRC());
- // <encoded-string>: The mangled name also contains the first 32 _characters_
- // (including null-terminator bytes) of the StringLiteral.
+ // <encoded-string>: The mangled name also contains the first 32 bytes
+ // (including null-terminator bytes) of the encoded StringLiteral.
// Each character is encoded by splitting them into bytes and then encoding
// the constituent bytes.
auto MangleByte = [&Mangler](char Byte) {
@@ -3155,20 +3302,15 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
}
};
- // Enforce our 32 character max.
- unsigned NumCharsToMangle = std::min(32U, SL->getLength());
- for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E;
- ++I)
+ // Enforce our 32 bytes max, except wchar_t which gets 32 chars instead.
+ unsigned MaxBytesToMangle = SL->isWide() ? 64U : 32U;
+ unsigned NumBytesToMangle = std::min(MaxBytesToMangle, StringByteLength);
+ for (unsigned I = 0; I != NumBytesToMangle; ++I) {
if (SL->isWide())
MangleByte(GetBigEndianByte(I));
else
MangleByte(GetLittleEndianByte(I));
-
- // Encode the NUL terminator if there is room.
- if (NumCharsToMangle < 32)
- for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth();
- ++NullTerminator)
- MangleByte(0);
+ }
Mangler.getStream() << '@';
}
diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
index 8adaef1fb640..94ad87b6e337 100644
--- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
@@ -432,14 +432,39 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
return NSAPI::NSNumberWithDouble;
case BuiltinType::Bool:
return NSAPI::NSNumberWithBool;
-
+
case BuiltinType::Void:
case BuiltinType::WChar_U:
case BuiltinType::WChar_S:
+ case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Int128:
case BuiltinType::LongDouble:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
case BuiltinType::UInt128:
case BuiltinType::Float16:
case BuiltinType::Float128:
@@ -466,19 +491,19 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::OMPArraySection:
break;
}
-
+
return None;
}
-/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
+/// Returns true if \param T is a typedef of "BOOL" in objective-c.
bool NSAPI::isObjCBOOLType(QualType T) const {
return isObjCTypedef(T, "BOOL", BOOLId);
}
-/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
+/// Returns true if \param T is a typedef of "NSInteger" in objective-c.
bool NSAPI::isObjCNSIntegerType(QualType T) const {
return isObjCTypedef(T, "NSInteger", NSIntegerId);
}
-/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
+/// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
bool NSAPI::isObjCNSUIntegerType(QualType T) const {
return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
}
@@ -486,7 +511,7 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const {
StringRef NSAPI::GetNSIntegralKind(QualType T) const {
if (!Ctx.getLangOpts().ObjC1 || T.isNull())
return StringRef();
-
+
while (const TypedefType *TDT = T->getAs<TypedefType>()) {
StringRef NSIntegralResust =
llvm::StringSwitch<StringRef>(
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
index 889f8308a93c..a514d57b6b6b 100644
--- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -85,7 +85,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *
NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
+ NestedNameSpecifier *Prefix,
NamespaceAliasDecl *Alias) {
assert(Alias && "Namespace alias cannot be NULL");
assert((!Prefix ||
@@ -164,7 +164,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
llvm_unreachable("Invalid NNS Kind!");
}
-/// \brief Retrieve the namespace stored in this nested name specifier.
+/// Retrieve the namespace stored in this nested name specifier.
NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
@@ -172,7 +172,7 @@ NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
return nullptr;
}
-/// \brief Retrieve the namespace alias stored in this nested name specifier.
+/// Retrieve the namespace alias stored in this nested name specifier.
NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
@@ -180,7 +180,7 @@ NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
return nullptr;
}
-/// \brief Retrieve the record declaration stored in this nested name specifier.
+/// Retrieve the record declaration stored in this nested name specifier.
CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
switch (Prefix.getInt()) {
case StoredIdentifier:
@@ -197,7 +197,7 @@ CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
llvm_unreachable("Invalid NNS Kind!");
}
-/// \brief Whether this nested name specifier refers to a dependent
+/// Whether this nested name specifier refers to a dependent
/// type or not.
bool NestedNameSpecifier::isDependent() const {
switch (getKind()) {
@@ -227,14 +227,14 @@ bool NestedNameSpecifier::isDependent() const {
llvm_unreachable("Invalid NNS Kind!");
}
-/// \brief Whether this nested name specifier refers to a dependent
+/// Whether this nested name specifier refers to a dependent
/// type or not.
bool NestedNameSpecifier::isInstantiationDependent() const {
switch (getKind()) {
case Identifier:
// Identifier specifiers always represent dependent types
return true;
-
+
case Namespace:
case NamespaceAlias:
case Global:
@@ -268,7 +268,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
llvm_unreachable("Invalid NNS Kind!");
}
-/// \brief Print this nested name specifier to the given output
+/// Print this nested name specifier to the given output
/// stream.
void
NestedNameSpecifier::print(raw_ostream &OS,
@@ -284,7 +284,7 @@ NestedNameSpecifier::print(raw_ostream &OS,
case Namespace:
if (getAsNamespace()->isAnonymousNamespace())
return;
-
+
OS << getAsNamespace()->getName();
break;
@@ -348,7 +348,7 @@ LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const {
print(llvm::errs(), PrintingPolicy(LO));
}
-unsigned
+unsigned
NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
assert(Qualifier && "Expected a non-NULL qualifier");
@@ -379,7 +379,7 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
return Length;
}
-unsigned
+unsigned
NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
unsigned Length = 0;
for (; Qualifier; Qualifier = Qualifier->getPrefix())
@@ -387,15 +387,15 @@ NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
return Length;
}
-/// \brief Load a (possibly unaligned) source location from a given address
+/// 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
+
+/// Load a (possibly unaligned) pointer from a given address and
/// offset.
static void *LoadPointer(void *Data, unsigned Offset) {
void *Result;
@@ -406,19 +406,19 @@ static void *LoadPointer(void *Data, unsigned Offset) {
SourceRange NestedNameSpecifierLoc::getSourceRange() const {
if (!Qualifier)
return SourceRange();
-
+
NestedNameSpecifierLoc First = *this;
while (NestedNameSpecifierLoc Prefix = First.getPrefix())
First = Prefix;
-
- return SourceRange(First.getLocalSourceRange().getBegin(),
+
+ return SourceRange(First.getLocalSourceRange().getBegin(),
getLocalSourceRange().getEnd());
}
SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
if (!Qualifier)
return SourceRange();
-
+
unsigned Offset = getDataLength(Qualifier->getPrefix());
switch (Qualifier->getKind()) {
case NestedNameSpecifier::Global:
@@ -466,7 +466,7 @@ static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
unsigned NewCapacity = std::max(
(unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
(unsigned)(BufferSize + (End - Start)));
- char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
+ char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
if (BufferCapacity) {
memcpy(NewBuffer, Buffer, BufferSize);
free(Buffer);
@@ -478,8 +478,8 @@ static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
memcpy(Buffer + BufferSize, Start, End - Start);
BufferSize += End-Start;
}
-
-/// \brief Save a source location to the given buffer.
+
+/// Save a source location to the given buffer.
static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
unsigned &BufferSize, unsigned &BufferCapacity) {
unsigned Raw = Loc.getRawEncoding();
@@ -487,8 +487,8 @@ static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
Buffer, BufferSize, BufferCapacity);
}
-
-/// \brief Save a pointer to the given buffer.
+
+/// Save a pointer to the given buffer.
static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
unsigned &BufferCapacity) {
Append(reinterpret_cast<char *>(&Ptr),
@@ -497,18 +497,18 @@ static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
}
NestedNameSpecifierLocBuilder::
-NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
+NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
: Representation(Other.Representation) {
if (!Other.Buffer)
return;
-
+
if (Other.BufferCapacity == 0) {
// Shallow copy is okay.
Buffer = Other.Buffer;
BufferSize = Other.BufferSize;
return;
}
-
+
// Deep copy
Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
BufferCapacity);
@@ -518,72 +518,72 @@ NestedNameSpecifierLocBuilder &
NestedNameSpecifierLocBuilder::
operator=(const NestedNameSpecifierLocBuilder &Other) {
Representation = Other.Representation;
-
+
if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
// Re-use our storage.
BufferSize = Other.BufferSize;
memcpy(Buffer, Other.Buffer, BufferSize);
return *this;
}
-
+
// Free our storage, if we have any.
if (BufferCapacity) {
free(Buffer);
BufferCapacity = 0;
}
-
+
if (!Other.Buffer) {
// Empty.
Buffer = nullptr;
BufferSize = 0;
return *this;
}
-
+
if (Other.BufferCapacity == 0) {
// Shallow copy is okay.
Buffer = Other.Buffer;
BufferSize = Other.BufferSize;
return *this;
}
-
+
// Deep copy.
Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
BufferCapacity);
return *this;
}
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
- SourceLocation TemplateKWLoc,
- TypeLoc TL,
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
+ SourceLocation TemplateKWLoc,
+ TypeLoc TL,
SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
- TemplateKWLoc.isValid(),
+ Representation = NestedNameSpecifier::Create(Context, Representation,
+ TemplateKWLoc.isValid(),
TL.getTypePtr());
-
+
// Push source-location info into the buffer.
SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc,
+ SourceLocation IdentifierLoc,
SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
+ Representation = NestedNameSpecifier::Create(Context, Representation,
Identifier);
-
+
// Push source-location info into the buffer.
SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
NamespaceDecl *Namespace,
- SourceLocation NamespaceLoc,
+ SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
+ Representation = NestedNameSpecifier::Create(Context, Representation,
Namespace);
-
+
// Push source-location info into the buffer.
SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
@@ -591,20 +591,20 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
NamespaceAliasDecl *Alias,
- SourceLocation AliasLoc,
+ SourceLocation AliasLoc,
SourceLocation ColonColonLoc) {
Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
-
+
// Push source-location info into the buffer.
SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
+void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
SourceLocation ColonColonLoc) {
assert(!Representation && "Already have a nested-name-specifier!?");
Representation = NestedNameSpecifier::GlobalSpecifier(Context);
-
+
// Push source-location info into the buffer.
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
@@ -620,12 +620,12 @@ void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
- NestedNameSpecifier *Qualifier,
+void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
SourceRange R) {
Representation = Qualifier;
-
- // Construct bogus (but well-formed) source information for the
+
+ // Construct bogus (but well-formed) source information for the
// nested-name-specifier.
BufferSize = 0;
SmallVector<NestedNameSpecifier *, 4> Stack;
@@ -639,24 +639,24 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
case NestedNameSpecifier::NamespaceAlias:
SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
break;
-
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
TypeSourceInfo *TSInfo
= Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
R.getBegin());
- SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
+ SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
BufferCapacity);
break;
}
-
+
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Super:
break;
}
-
+
// Save the location of the '::'.
- SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
+ SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
Buffer, BufferSize, BufferCapacity);
}
}
@@ -670,8 +670,8 @@ void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
BufferSize = 0;
return;
}
-
- // Rather than copying the data (which is wasteful), "adopt" the
+
+ // Rather than copying the data (which is wasteful), "adopt" the
// pointer (which points into the ASTContext) but set the capacity to zero to
// indicate that we don't own it.
Representation = Other.getNestedNameSpecifier();
@@ -680,16 +680,16 @@ void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
BufferCapacity = 0;
}
-NestedNameSpecifierLoc
+NestedNameSpecifierLoc
NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
if (!Representation)
return NestedNameSpecifierLoc();
-
+
// If we adopted our data pointer from elsewhere in the AST context, there's
// no need to copy the memory.
if (BufferCapacity == 0)
return NestedNameSpecifierLoc(Representation, Buffer);
-
+
// FIXME: After copying the source-location information, should we free
// our (temporary) buffer and adopt the ASTContext-allocated memory?
// Doing so would optimize repeated calls to getWithLocInContext().
diff --git a/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp b/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp
index 38e8d34135f9..e710d3780337 100644
--- a/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp
@@ -33,6 +33,15 @@ void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
}
void ODRHash::AddDeclarationName(DeclarationName Name) {
+ // Index all DeclarationName and use index numbers to refer to them.
+ auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
+ ID.AddInteger(Result.first->second);
+ if (!Result.second) {
+ // If found in map, the the DeclarationName has previously been processed.
+ return;
+ }
+
+ // First time processing each DeclarationName, also process its details.
AddBoolean(Name.isEmpty());
if (Name.isEmpty())
return;
@@ -139,6 +148,8 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
AddQualType(TA.getAsType());
break;
case TemplateArgument::Declaration:
+ AddDecl(TA.getAsDecl());
+ break;
case TemplateArgument::NullPtr:
case TemplateArgument::Integral:
break;
@@ -168,8 +179,7 @@ void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
}
void ODRHash::clear() {
- DeclMap.clear();
- TypeMap.clear();
+ DeclNameMap.clear();
Bools.clear();
ID.clear();
}
@@ -307,26 +317,14 @@ public:
}
void VisitFunctionDecl(const FunctionDecl *D) {
- ID.AddInteger(D->getStorageClass());
- Hash.AddBoolean(D->isInlineSpecified());
- Hash.AddBoolean(D->isVirtualAsWritten());
- Hash.AddBoolean(D->isPure());
- Hash.AddBoolean(D->isDeletedAsWritten());
-
- ID.AddInteger(D->param_size());
-
- for (auto *Param : D->parameters()) {
- Hash.AddSubDecl(Param);
- }
-
- AddQualType(D->getReturnType());
+ // Handled by the ODRHash for FunctionDecl
+ ID.AddInteger(D->getODRHash());
Inherited::VisitFunctionDecl(D);
}
void VisitCXXMethodDecl(const CXXMethodDecl *D) {
- Hash.AddBoolean(D->isConst());
- Hash.AddBoolean(D->isVolatile());
+ // Handled by the ODRHash for FunctionDecl
Inherited::VisitCXXMethodDecl(D);
}
@@ -363,6 +361,7 @@ public:
if (hasDefaultArgument) {
AddTemplateArgument(D->getDefaultArgument());
}
+ Hash.AddBoolean(D->isParameterPack());
Inherited::VisitTemplateTypeParmDecl(D);
}
@@ -375,6 +374,7 @@ public:
if (hasDefaultArgument) {
AddStmt(D->getDefaultArgument());
}
+ Hash.AddBoolean(D->isParameterPack());
Inherited::VisitNonTypeTemplateParmDecl(D);
}
@@ -387,15 +387,37 @@ public:
if (hasDefaultArgument) {
AddTemplateArgument(D->getDefaultArgument().getArgument());
}
+ Hash.AddBoolean(D->isParameterPack());
Inherited::VisitTemplateTemplateParmDecl(D);
}
+
+ void VisitTemplateDecl(const TemplateDecl *D) {
+ Hash.AddTemplateParameterList(D->getTemplateParameters());
+
+ Inherited::VisitTemplateDecl(D);
+ }
+
+ void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) {
+ Hash.AddBoolean(D->isMemberSpecialization());
+ Inherited::VisitRedeclarableTemplateDecl(D);
+ }
+
+ void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
+ AddDecl(D->getTemplatedDecl());
+ Inherited::VisitFunctionTemplateDecl(D);
+ }
+
+ void VisitEnumConstantDecl(const EnumConstantDecl *D) {
+ AddStmt(D->getInitExpr());
+ Inherited::VisitEnumConstantDecl(D);
+ }
};
} // namespace
// Only allow a small portion of Decl's to be processed. Remove this once
// all Decl's can be handled.
-bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
+bool ODRHash::isWhitelistedDecl(const Decl *D, const DeclContext *Parent) {
if (D->isImplicit()) return false;
if (D->getDeclContext() != Parent) return false;
@@ -406,8 +428,10 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXMethod:
+ case Decl::EnumConstant: // Only found in EnumDecl's.
case Decl::Field:
case Decl::Friend:
+ case Decl::FunctionTemplate:
case Decl::StaticAssert:
case Decl::TypeAlias:
case Decl::Typedef:
@@ -418,7 +442,6 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
void ODRHash::AddSubDecl(const Decl *D) {
assert(D && "Expecting non-null pointer.");
- AddDecl(D);
ODRDeclVisitor(ID, *this).Visit(D);
}
@@ -440,9 +463,13 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
// Filter out sub-Decls which will not be processed in order to get an
// accurate count of Decl's.
llvm::SmallVector<const Decl *, 16> Decls;
- for (const Decl *SubDecl : Record->decls()) {
+ for (Decl *SubDecl : Record->decls()) {
if (isWhitelistedDecl(SubDecl, Record)) {
Decls.push_back(SubDecl);
+ if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) {
+ // Compute/Preload ODRHash into FunctionDecl.
+ Function->getODRHash();
+ }
}
}
@@ -466,30 +493,48 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
}
}
-void ODRHash::AddFunctionDecl(const FunctionDecl *Function) {
+void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
+ bool SkipBody) {
assert(Function && "Expecting non-null pointer.");
- // Skip hashing these kinds of function.
- if (Function->isImplicit()) return;
- if (Function->isDefaulted()) return;
- if (Function->isDeleted()) return;
- if (!Function->hasBody()) return;
- if (!Function->getBody()) return;
-
- // TODO: Fix hashing for class methods.
- if (isa<CXXMethodDecl>(Function)) return;
- // And friend functions.
- if (Function->getFriendObjectKind()) return;
-
// Skip functions that are specializations or in specialization context.
const DeclContext *DC = Function;
while (DC) {
if (isa<ClassTemplateSpecializationDecl>(DC)) return;
- if (auto *F = dyn_cast<FunctionDecl>(DC))
- if (F->isFunctionTemplateSpecialization()) return;
+ if (auto *F = dyn_cast<FunctionDecl>(DC)) {
+ if (F->isFunctionTemplateSpecialization()) {
+ if (!isa<CXXMethodDecl>(DC)) return;
+ if (DC->getLexicalParent()->isFileContext()) return;
+ // Inline method specializations are the only supported
+ // specialization for now.
+ }
+ }
DC = DC->getParent();
}
+ ID.AddInteger(Function->getDeclKind());
+
+ const auto *SpecializationArgs = Function->getTemplateSpecializationArgs();
+ AddBoolean(SpecializationArgs);
+ if (SpecializationArgs) {
+ ID.AddInteger(SpecializationArgs->size());
+ for (const TemplateArgument &TA : SpecializationArgs->asArray()) {
+ AddTemplateArgument(TA);
+ }
+ }
+
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
+ AddBoolean(Method->isConst());
+ AddBoolean(Method->isVolatile());
+ }
+
+ ID.AddInteger(Function->getStorageClass());
+ AddBoolean(Function->isInlineSpecified());
+ AddBoolean(Function->isVirtualAsWritten());
+ AddBoolean(Function->isPure());
+ AddBoolean(Function->isDeletedAsWritten());
+ AddBoolean(Function->isExplicitlyDefaulted());
+
AddDecl(Function);
AddQualType(Function->getReturnType());
@@ -498,25 +543,62 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function) {
for (auto Param : Function->parameters())
AddSubDecl(Param);
- AddStmt(Function->getBody());
+ if (SkipBody) {
+ AddBoolean(false);
+ return;
+ }
+
+ const bool HasBody = Function->isThisDeclarationADefinition() &&
+ !Function->isDefaulted() && !Function->isDeleted() &&
+ !Function->isLateTemplateParsed();
+ AddBoolean(HasBody);
+ if (HasBody) {
+ auto *Body = Function->getBody();
+ AddBoolean(Body);
+ if (Body)
+ AddStmt(Body);
+ }
+}
+
+void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
+ assert(Enum);
+ AddDeclarationName(Enum->getDeclName());
+
+ AddBoolean(Enum->isScoped());
+ if (Enum->isScoped())
+ AddBoolean(Enum->isScopedUsingClassTag());
+
+ if (Enum->getIntegerTypeSourceInfo())
+ AddQualType(Enum->getIntegerType());
+
+ // Filter out sub-Decls which will not be processed in order to get an
+ // accurate count of Decl's.
+ llvm::SmallVector<const Decl *, 16> Decls;
+ for (Decl *SubDecl : Enum->decls()) {
+ if (isWhitelistedDecl(SubDecl, Enum)) {
+ assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl");
+ Decls.push_back(SubDecl);
+ }
+ }
+
+ ID.AddInteger(Decls.size());
+ for (auto SubDecl : Decls) {
+ AddSubDecl(SubDecl);
+ }
+
}
void ODRHash::AddDecl(const Decl *D) {
assert(D && "Expecting non-null pointer.");
D = D->getCanonicalDecl();
- auto Result = DeclMap.insert(std::make_pair(D, DeclMap.size()));
- ID.AddInteger(Result.first->second);
- // On first encounter of a Decl pointer, process it. Every time afterwards,
- // only the index value is needed.
- if (!Result.second) {
- return;
- }
-
- ID.AddInteger(D->getKind());
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
AddDeclarationName(ND->getDeclName());
+ return;
}
+
+ ID.AddInteger(D->getKind());
+ // TODO: Handle non-NamedDecl here.
}
namespace {
@@ -644,13 +726,41 @@ public:
VisitFunctionType(T);
}
+ void VisitPointerType(const PointerType *T) {
+ AddQualType(T->getPointeeType());
+ VisitType(T);
+ }
+
+ void VisitReferenceType(const ReferenceType *T) {
+ AddQualType(T->getPointeeTypeAsWritten());
+ VisitType(T);
+ }
+
+ void VisitLValueReferenceType(const LValueReferenceType *T) {
+ VisitReferenceType(T);
+ }
+
+ void VisitRValueReferenceType(const RValueReferenceType *T) {
+ VisitReferenceType(T);
+ }
+
void VisitTypedefType(const TypedefType *T) {
AddDecl(T->getDecl());
QualType UnderlyingType = T->getDecl()->getUnderlyingType();
VisitQualifiers(UnderlyingType.getQualifiers());
- while (const TypedefType *Underlying =
- dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
- UnderlyingType = Underlying->getDecl()->getUnderlyingType();
+ while (true) {
+ if (const TypedefType *Underlying =
+ dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
+ UnderlyingType = Underlying->getDecl()->getUnderlyingType();
+ continue;
+ }
+ if (const ElaboratedType *Underlying =
+ dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) {
+ UnderlyingType = Underlying->getNamedType();
+ continue;
+ }
+
+ break;
}
AddType(UnderlyingType.getTypePtr());
VisitType(T);
@@ -712,14 +822,6 @@ public:
void ODRHash::AddType(const Type *T) {
assert(T && "Expecting non-null pointer.");
- auto Result = TypeMap.insert(std::make_pair(T, TypeMap.size()));
- ID.AddInteger(Result.first->second);
- // On first encounter of a Type pointer, process it. Every time afterwards,
- // only the index value is needed.
- if (!Result.second) {
- return;
- }
-
ODRTypeVisitor(ID, *this).Visit(T);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
index 4feac0cfd041..0b8aa883e180 100644
--- a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
@@ -181,6 +181,57 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
return nullptr;
}
+OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num,
+ unsigned NumLoops,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
+ auto *Clause =
+ new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc);
+ for (unsigned I = 0; I < NumLoops; ++I) {
+ Clause->setLoopNumIterations(I, nullptr);
+ Clause->setLoopCounter(I, nullptr);
+ }
+ return Clause;
+}
+
+OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
+ auto *Clause = new (Mem) OMPOrderedClause(NumLoops);
+ for (unsigned I = 0; I < NumLoops; ++I) {
+ Clause->setLoopNumIterations(I, nullptr);
+ Clause->setLoopCounter(I, nullptr);
+ }
+ return Clause;
+}
+
+void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop,
+ Expr *NumIterations) {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ getTrailingObjects<Expr *>()[NumLoop] = NumIterations;
+}
+
+ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const {
+ return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumberOfLoops);
+}
+
+void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop] = Counter;
+}
+
+Expr *OMPOrderedClause::getLoopCunter(unsigned NumLoop) {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
+}
+
+const Expr *OMPOrderedClause::getLoopCunter(unsigned NumLoop) const {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
+}
+
void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
@@ -653,44 +704,58 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
return new (Mem) OMPFlushClause(N);
}
-OMPDependClause *OMPDependClause::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
- OMPDependClause *Clause =
- new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
+OMPDependClause *
+OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops));
+ OMPDependClause *Clause = new (Mem)
+ OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
Clause->setVarRefs(VL);
Clause->setDependencyKind(DepKind);
Clause->setDependencyLoc(DepLoc);
Clause->setColonLoc(ColonLoc);
- Clause->setCounterValue(nullptr);
+ for (unsigned I = 0 ; I < NumLoops; ++I)
+ Clause->setLoopData(I, nullptr);
return Clause;
}
-OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1));
- return new (Mem) OMPDependClause(N);
+OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops));
+ return new (Mem) OMPDependClause(N, NumLoops);
}
-void OMPDependClause::setCounterValue(Expr *V) {
- assert(getDependencyKind() == OMPC_DEPEND_sink ||
- getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
- *getVarRefs().end() = V;
+void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
+ assert((getDependencyKind() == OMPC_DEPEND_sink ||
+ getDependencyKind() == OMPC_DEPEND_source) &&
+ NumLoop < NumLoops &&
+ "Expected sink or source depend + loop index must be less number of "
+ "loops.");
+ auto It = std::next(getVarRefs().end(), NumLoop);
+ *It = Cnt;
}
-const Expr *OMPDependClause::getCounterValue() const {
- auto *V = *getVarRefs().end();
- assert(getDependencyKind() == OMPC_DEPEND_sink ||
- getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
- return V;
+Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
+ assert((getDependencyKind() == OMPC_DEPEND_sink ||
+ getDependencyKind() == OMPC_DEPEND_source) &&
+ NumLoop < NumLoops &&
+ "Expected sink or source depend + loop index must be less number of "
+ "loops.");
+ auto It = std::next(getVarRefs().end(), NumLoop);
+ return *It;
}
-Expr *OMPDependClause::getCounterValue() {
- auto *V = *getVarRefs().end();
- assert(getDependencyKind() == OMPC_DEPEND_sink ||
- getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
- return V;
+const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
+ assert((getDependencyKind() == OMPC_DEPEND_sink ||
+ getDependencyKind() == OMPC_DEPEND_source) &&
+ NumLoop < NumLoops &&
+ "Expected sink or source depend + loop index must be less number of "
+ "loops.");
+ auto It = std::next(getVarRefs().end(), NumLoop);
+ return *It;
}
unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
@@ -702,10 +767,10 @@ unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
}
unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber(
- ArrayRef<ValueDecl *> Declarations) {
+ ArrayRef<const ValueDecl *> Declarations) {
unsigned TotalNum = 0u;
llvm::SmallPtrSet<const ValueDecl *, 8> Cache;
- for (auto *D : Declarations) {
+ for (const ValueDecl *D : Declarations) {
const ValueDecl *VD = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
if (Cache.count(VD))
continue;
diff --git a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
index d8882c9030b2..af2a480dc23f 100644
--- a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "llvm/ADT/DenseMap.h"
using namespace clang;
@@ -136,7 +137,7 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
}
while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
- return S;
+ return S;
}
Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
@@ -193,6 +194,8 @@ bool ParentMap::isConsumedExpr(Expr* E) const {
return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
case Stmt::SwitchStmtClass:
return DirectChild == cast<SwitchStmt>(P)->getCond();
+ case Stmt::ObjCForCollectionStmtClass:
+ return DirectChild == cast<ObjCForCollectionStmt>(P)->getCollection();
case Stmt::ReturnStmtClass:
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp b/contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp
index 86c0eff9f78c..8b605ef295a0 100644
--- a/contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp
@@ -22,7 +22,7 @@ namespace clang {
namespace TypeName {
-/// \brief Create a NestedNameSpecifier for Namesp and its enclosing
+/// Create a NestedNameSpecifier for Namesp and its enclosing
/// scopes.
///
/// \param[in] Ctx - the AST Context to be used.
@@ -35,7 +35,7 @@ static NestedNameSpecifier *createNestedNameSpecifier(
const NamespaceDecl *Namesp,
bool WithGlobalNsPrefix);
-/// \brief Create a NestedNameSpecifier for TagDecl and its enclosing
+/// Create a NestedNameSpecifier for TagDecl and its enclosing
/// scopes.
///
/// \param[in] Ctx - the AST Context to be used.
@@ -210,7 +210,7 @@ static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
}
-/// \brief Return a fully qualified version of this name specifier.
+/// Return a fully qualified version of this name specifier.
static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
const ASTContext &Ctx, NestedNameSpecifier *Scope,
bool WithGlobalNsPrefix) {
@@ -262,7 +262,7 @@ static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
llvm_unreachable("bad NNS kind");
}
-/// \brief Create a nested name specifier for the declaring context of
+/// Create a nested name specifier for the declaring context of
/// the type.
static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
const ASTContext &Ctx, const Decl *Decl,
@@ -314,7 +314,7 @@ static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
return nullptr;
}
-/// \brief Create a nested name specifier for the declaring context of
+/// Create a nested name specifier for the declaring context of
/// the type.
static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
const ASTContext &Ctx, const Type *TypePtr,
@@ -366,7 +366,7 @@ NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
TD->getTypeForDecl());
}
-/// \brief Return the fully qualified type, including fully-qualified
+/// Return the fully qualified type, including fully-qualified
/// versions of any template parameters.
QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
bool WithGlobalNsPrefix) {
@@ -408,7 +408,7 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
// Get the qualifiers.
Qualifiers Quals = QT.getQualifiers();
- QT = dyn_cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
+ QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
// Add back the qualifiers.
QT = Ctx.getQualifiedType(QT, Quals);
@@ -452,12 +452,8 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
std::string getFullyQualifiedName(QualType QT,
const ASTContext &Ctx,
+ const PrintingPolicy &Policy,
bool WithGlobalNsPrefix) {
- PrintingPolicy Policy(Ctx.getPrintingPolicy());
- Policy.SuppressScope = false;
- Policy.AnonymousTagLocations = false;
- Policy.PolishForDeclaration = true;
- Policy.SuppressUnwrittenScope = true;
QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
return FQQT.getAsString(Policy);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp
index 881a7d9c61be..95da9ed6d238 100644
--- a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp
@@ -80,7 +80,7 @@ bool commentsStartOnSameColumn(const SourceManager &SM, const RawComment &R1,
}
} // unnamed namespace
-/// \brief Determines whether there is only whitespace in `Buffer` between `P`
+/// Determines whether there is only whitespace in `Buffer` between `P`
/// and the previous line.
/// \param Buffer The buffer to search in.
/// \param P The offset from the beginning of `Buffer` to start from.
@@ -107,10 +107,10 @@ static bool isOrdinaryKind(RawComment::CommentKind K) {
}
RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR,
- bool Merged, bool ParseAllComments) :
+ const CommentOptions &CommentOpts, bool Merged) :
Range(SR), RawTextValid(false), BriefTextValid(false),
- IsAttached(false), IsTrailingComment(false), IsAlmostTrailingComment(false),
- ParseAllComments(ParseAllComments) {
+ IsAttached(false), IsTrailingComment(false),
+ IsAlmostTrailingComment(false) {
// Extract raw comment text, if possible.
if (SR.getBegin() == SR.getEnd() || getRawText(SourceMgr).empty()) {
Kind = RCK_Invalid;
@@ -118,10 +118,11 @@ RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR,
}
// Guess comment kind.
- std::pair<CommentKind, bool> K = getCommentKind(RawText, ParseAllComments);
+ std::pair<CommentKind, bool> K =
+ getCommentKind(RawText, CommentOpts.ParseAllComments);
// Guess whether an ordinary comment is trailing.
- if (ParseAllComments && isOrdinaryKind(K.first)) {
+ if (CommentOpts.ParseAllComments && isOrdinaryKind(K.first)) {
FileID BeginFileID;
unsigned BeginOffset;
std::tie(BeginFileID, BeginOffset) =
@@ -270,6 +271,7 @@ static bool onlyWhitespaceBetween(SourceManager &SM,
}
void RawCommentList::addComment(const RawComment &RC,
+ const CommentOptions &CommentOpts,
llvm::BumpPtrAllocator &Allocator) {
if (RC.isInvalid())
return;
@@ -284,7 +286,7 @@ void RawCommentList::addComment(const RawComment &RC,
}
// Ordinary comments are not interesting for us.
- if (RC.isOrdinary())
+ if (RC.isOrdinary() && !CommentOpts.ParseAllComments)
return;
// If this is the first Doxygen comment, save it (because there isn't
@@ -317,8 +319,7 @@ void RawCommentList::addComment(const RawComment &RC,
onlyWhitespaceBetween(SourceMgr, C1.getLocEnd(), C2.getLocStart(),
/*MaxNewlinesAllowed=*/1)) {
SourceRange MergedRange(C1.getLocStart(), C2.getLocEnd());
- *Comments.back() = RawComment(SourceMgr, MergedRange, true,
- RC.isParseAllComments());
+ *Comments.back() = RawComment(SourceMgr, MergedRange, CommentOpts, true);
} else {
Comments.push_back(new (Allocator) RawComment(RC));
}
@@ -334,3 +335,94 @@ void RawCommentList::addDeserializedComments(ArrayRef<RawComment *> Deserialized
BeforeThanCompare<RawComment>(SourceMgr));
std::swap(Comments, MergedComments);
}
+
+std::string RawComment::getFormattedText(const SourceManager &SourceMgr,
+ DiagnosticsEngine &Diags) const {
+ llvm::StringRef CommentText = getRawText(SourceMgr);
+ if (CommentText.empty())
+ return "";
+
+ llvm::BumpPtrAllocator Allocator;
+ // We do not parse any commands, so CommentOptions are ignored by
+ // comments::Lexer. Therefore, we just use default-constructed options.
+ CommentOptions DefOpts;
+ comments::CommandTraits EmptyTraits(Allocator, DefOpts);
+ comments::Lexer L(Allocator, Diags, EmptyTraits, getSourceRange().getBegin(),
+ CommentText.begin(), CommentText.end(),
+ /*ParseCommands=*/false);
+
+ std::string Result;
+ // A column number of the first non-whitespace token in the comment text.
+ // We skip whitespace up to this column, but keep the whitespace after this
+ // column. IndentColumn is calculated when lexing the first line and reused
+ // for the rest of lines.
+ unsigned IndentColumn = 0;
+
+ // Processes one line of the comment and adds it to the result.
+ // Handles skipping the indent at the start of the line.
+ // Returns false when eof is reached and true otherwise.
+ auto LexLine = [&](bool IsFirstLine) -> bool {
+ comments::Token Tok;
+ // Lex the first token on the line. We handle it separately, because we to
+ // fix up its indentation.
+ L.lex(Tok);
+ if (Tok.is(comments::tok::eof))
+ return false;
+ if (Tok.is(comments::tok::newline)) {
+ Result += "\n";
+ return true;
+ }
+ llvm::StringRef TokText = L.getSpelling(Tok, SourceMgr);
+ bool LocInvalid = false;
+ unsigned TokColumn =
+ SourceMgr.getSpellingColumnNumber(Tok.getLocation(), &LocInvalid);
+ assert(!LocInvalid && "getFormattedText for invalid location");
+
+ // Amount of leading whitespace in TokText.
+ size_t WhitespaceLen = TokText.find_first_not_of(" \t");
+ if (WhitespaceLen == StringRef::npos)
+ WhitespaceLen = TokText.size();
+ // Remember the amount of whitespace we skipped in the first line to remove
+ // indent up to that column in the following lines.
+ if (IsFirstLine)
+ IndentColumn = TokColumn + WhitespaceLen;
+
+ // Amount of leading whitespace we actually want to skip.
+ // For the first line we skip all the whitespace.
+ // For the rest of the lines, we skip whitespace up to IndentColumn.
+ unsigned SkipLen =
+ IsFirstLine
+ ? WhitespaceLen
+ : std::min<size_t>(
+ WhitespaceLen,
+ std::max<int>(static_cast<int>(IndentColumn) - TokColumn, 0));
+ llvm::StringRef Trimmed = TokText.drop_front(SkipLen);
+ Result += Trimmed;
+ // Lex all tokens in the rest of the line.
+ for (L.lex(Tok); Tok.isNot(comments::tok::eof); L.lex(Tok)) {
+ if (Tok.is(comments::tok::newline)) {
+ Result += "\n";
+ return true;
+ }
+ Result += L.getSpelling(Tok, SourceMgr);
+ }
+ // We've reached the end of file token.
+ return false;
+ };
+
+ auto DropTrailingNewLines = [](std::string &Str) {
+ while (Str.back() == '\n')
+ Str.pop_back();
+ };
+
+ // Proces first line separately to remember indent for the following lines.
+ if (!LexLine(/*IsFirstLine=*/true)) {
+ DropTrailingNewLines(Result);
+ return Result;
+ }
+ // Process the rest of the lines.
+ while (LexLine(/*IsFirstLine=*/false))
+ ;
+ DropTrailingNewLines(Result);
+ return Result;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
index 37fe029f53bd..9db23d50d0af 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
@@ -30,10 +30,12 @@ void ASTRecordLayout::Destroy(ASTContext &Ctx) {
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
CharUnits alignment,
+ CharUnits unadjustedAlignment,
CharUnits requiredAlignment,
CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
+ UnadjustedAlignment(unadjustedAlignment),
RequiredAlignment(requiredAlignment) {
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
}
@@ -41,6 +43,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
// Constructor for C++ records.
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
+ CharUnits unadjustedAlignment,
CharUnits requiredAlignment,
bool hasOwnVFPtr, bool hasExtendableVFPtr,
CharUnits vbptroffset,
@@ -57,6 +60,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
+ UnadjustedAlignment(unadjustedAlignment),
RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
{
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
@@ -87,5 +91,5 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
"Primary base must be at offset 0!");
}
}
-#endif
+#endif
}
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index de38bc9b64dd..6f71d5b83e62 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -54,25 +54,25 @@ struct BaseSubobjectInfo {
const BaseSubobjectInfo *Derived;
};
-/// \brief Externally provided layout. Typically used when the AST source, such
+/// Externally provided layout. Typically used when the AST source, such
/// as DWARF, lacks all the information that was available at compile time, such
/// as alignment attributes on fields and pragmas in effect.
struct ExternalLayout {
ExternalLayout() : Size(0), Align(0) {}
- /// \brief Overall record size in bits.
+ /// Overall record size in bits.
uint64_t Size;
- /// \brief Overall record alignment in bits.
+ /// Overall record alignment in bits.
uint64_t Align;
- /// \brief Record field offsets in bits.
+ /// Record field offsets in bits.
llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
- /// \brief Direct, non-virtual base offsets.
+ /// Direct, non-virtual base offsets.
llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
- /// \brief Virtual base offsets.
+ /// Virtual base offsets.
llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
/// Get the offset of the given field. The external source must provide
@@ -105,7 +105,7 @@ struct ExternalLayout {
class EmptySubobjectMap {
const ASTContext &Context;
uint64_t CharWidth;
-
+
/// Class - The class whose empty entries we're keeping track of.
const CXXRecordDecl *Class;
@@ -113,35 +113,35 @@ class EmptySubobjectMap {
typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
EmptyClassOffsetsMapTy EmptyClassOffsets;
-
+
/// MaxEmptyClassOffset - The highest offset known to contain an empty
/// base subobject.
CharUnits MaxEmptyClassOffset;
-
+
/// ComputeEmptySubobjectSizes - Compute the size of the largest base or
/// member subobject that is empty.
void ComputeEmptySubobjectSizes();
-
+
void AddSubobjectAtOffset(const CXXRecordDecl *RD, CharUnits Offset);
-
+
void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
CharUnits Offset, bool PlacingEmptyBase);
-
- void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
+
+ void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
CharUnits Offset);
void UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset);
-
+
/// AnyEmptySubobjectsBeyondOffset - Returns whether there are any empty
/// subobjects beyond the given offset.
bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset) const {
return Offset <= MaxEmptyClassOffset;
}
- CharUnits
+ CharUnits
getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const {
uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
- assert(FieldOffset % CharWidth == 0 &&
+ assert(FieldOffset % CharWidth == 0 &&
"Field offset not at char boundary!");
return Context.toCharUnitsFromBits(FieldOffset);
@@ -154,7 +154,7 @@ protected:
bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
CharUnits Offset);
- bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
CharUnits Offset) const;
bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
@@ -228,7 +228,7 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
}
bool
-EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
CharUnits Offset) const {
// We only need to check empty bases.
if (!RD->isEmpty())
@@ -245,8 +245,8 @@ EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
// There is already an empty class of the same type at this offset.
return false;
}
-
-void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
+
+void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
CharUnits Offset) {
// We only care about empty bases.
if (!RD->isEmpty())
@@ -257,9 +257,9 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
ClassVectorTy &Classes = EmptyClassOffsets[Offset];
if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
return;
-
+
Classes.push_back(RD);
-
+
// Update the empty class offset.
if (Offset > MaxEmptyClassOffset)
MaxEmptyClassOffset = Offset;
@@ -296,10 +296,10 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
return false;
}
}
-
+
// Traverse all member variables.
unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
+ for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
if (I->isBitField())
continue;
@@ -312,15 +312,15 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
return true;
}
-void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
+void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
CharUnits Offset,
bool PlacingEmptyBase) {
if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
// We know that the only empty subobjects that can conflict with empty
// subobject of non-empty bases, are empty bases that can be placed at
- // offset zero. Because of this, we only need to keep track of empty base
+ // offset zero. Because of this, we only need to keep track of empty base
// subobjects with offsets less than the size of the largest empty
- // subobject for our class.
+ // subobject for our class.
return;
}
@@ -338,7 +338,7 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
if (Info->PrimaryVirtualBaseInfo) {
BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
-
+
if (Info == PrimaryVirtualBaseInfo->Derived)
UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
PlacingEmptyBase);
@@ -346,7 +346,7 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
// Traverse all member variables.
unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
+ for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
if (I->isBitField())
continue;
@@ -373,7 +373,7 @@ bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
}
bool
-EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
CharUnits Offset) const {
// We don't have to keep looking past the maximum offset that's known to
@@ -383,7 +383,7 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
if (!CanPlaceSubobjectAtOffset(RD, Offset))
return false;
-
+
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
// Traverse all non-virtual bases.
@@ -408,7 +408,7 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
return false;
}
}
-
+
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
@@ -417,7 +417,7 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
continue;
CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
-
+
if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
return false;
}
@@ -432,7 +432,7 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
// contain an empty class.
if (!AnyEmptySubobjectsBeyondOffset(Offset))
return true;
-
+
QualType T = FD->getType();
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
@@ -454,7 +454,7 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
// contain an empty class.
if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
return true;
-
+
if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
return false;
@@ -466,23 +466,23 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
}
bool
-EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
+EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
CharUnits Offset) {
if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
return false;
-
+
// We are able to place the member variable at this offset.
// Make sure to update the empty base subobject map.
UpdateEmptyFieldSubobjects(FD, Offset);
return true;
}
-void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
+void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
CharUnits Offset) {
// We know that the only empty subobjects that can conflict with empty
// field subobjects are subobjects of empty bases that can be placed at offset
- // zero. Because of this, we only need to keep track of empty field
+ // zero. Because of this, we only need to keep track of empty field
// subobjects with offsets less than the size of the largest empty
// subobject for our class.
if (Offset >= SizeOfLargestEmptySubobject)
@@ -512,7 +512,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
}
}
-
+
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
@@ -525,7 +525,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
UpdateEmptyFieldSubobjects(*I, FieldOffset);
}
}
-
+
void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
CharUnits Offset) {
QualType T = FD->getType();
@@ -543,13 +543,13 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
+
uint64_t NumElements = Context.getConstantArrayElementCount(AT);
CharUnits ElementOffset = Offset;
-
+
for (uint64_t I = 0; I != NumElements; ++I) {
// We know that the only empty subobjects that can conflict with empty
- // field subobjects are subobjects of empty bases that can be placed at
+ // field subobjects are subobjects of empty bases that can be placed at
// offset zero. Because of this, we only need to keep track of empty field
// subobjects with offsets less than the size of the largest empty
// subobject for our class.
@@ -579,26 +579,29 @@ protected:
/// Alignment - The current alignment of the record layout.
CharUnits Alignment;
- /// \brief The alignment if attribute packed is not used.
+ /// The alignment if attribute packed is not used.
CharUnits UnpackedAlignment;
+ /// \brief The maximum of the alignments of top-level members.
+ CharUnits UnadjustedAlignment;
+
SmallVector<uint64_t, 16> FieldOffsets;
- /// \brief Whether the external AST source has provided a layout for this
+ /// Whether the external AST source has provided a layout for this
/// record.
unsigned UseExternalLayout : 1;
- /// \brief Whether we need to infer alignment, even when we have an
+ /// Whether we need to infer alignment, even when we have an
/// externally-provided layout.
unsigned InferAlignment : 1;
-
+
/// Packed - Whether the record is packed or not.
unsigned Packed : 1;
unsigned IsUnion : 1;
unsigned IsMac68kAlign : 1;
-
+
unsigned IsMsStruct : 1;
/// UnfilledBitsInLastUnit - If the last field laid out was a bitfield,
@@ -632,7 +635,7 @@ 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.
+ /// the flag of field offset changing due to packed attribute.
bool HasPackedField;
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
@@ -662,6 +665,7 @@ protected:
EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
+ UnadjustedAlignment(CharUnits::One()),
UseExternalLayout(false), InferAlignment(false), Packed(false),
IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
@@ -687,14 +691,14 @@ protected:
/// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects.
llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
-
+
typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
BaseSubobjectInfoMapTy;
/// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases
/// of the class we're laying out to their base subobject info.
BaseSubobjectInfoMapTy VirtualBaseInfo;
-
+
/// NonVirtualBaseInfo - Map from all the direct non-virtual bases of the
/// class we're laying out to their base subobject info.
BaseSubobjectInfoMapTy NonVirtualBaseInfo;
@@ -705,7 +709,7 @@ protected:
/// ComputeBaseSubobjectInfo - Compute the base subobject information for a
/// single class and all of its base classes.
- BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
bool IsVirtual,
BaseSubobjectInfo *Derived);
@@ -749,23 +753,23 @@ protected:
UpdateAlignment(NewAlignment, NewAlignment);
}
- /// \brief Retrieve the externally-supplied field offset for the given
+ /// Retrieve the externally-supplied field offset for the given
/// field.
///
/// \param Field The field whose offset is being queried.
/// \param ComputedOffset The offset that we've computed for this field.
- uint64_t updateExternalFieldOffset(const FieldDecl *Field,
+ uint64_t updateExternalFieldOffset(const FieldDecl *Field,
uint64_t ComputedOffset);
-
+
void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
uint64_t UnpackedOffset, unsigned UnpackedAlign,
bool isPacked, const FieldDecl *D);
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
- CharUnits getSize() const {
+ CharUnits getSize() const {
assert(Size % Context.getCharWidth() == 0);
- return Context.toCharUnitsFromBits(Size);
+ return Context.toCharUnitsFromBits(Size);
}
uint64_t getSizeInBits() const { return Size; }
@@ -774,9 +778,9 @@ protected:
CharUnits getAligment() const { return Alignment; }
- CharUnits getDataSize() const {
+ CharUnits getDataSize() const {
assert(DataSize % Context.getCharWidth() == 0);
- return Context.toCharUnitsFromBits(DataSize);
+ return Context.toCharUnitsFromBits(DataSize);
}
uint64_t getDataSizeInBits() const { return DataSize; }
@@ -867,7 +871,7 @@ void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) {
BaseSubobjectInfo *Info;
-
+
if (IsVirtual) {
// Check if we already have info about this virtual base.
BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
@@ -882,7 +886,7 @@ BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
} else {
Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
}
-
+
Info->Class = RD;
Info->IsVirtual = IsVirtual;
Info->Derived = nullptr;
@@ -898,10 +902,10 @@ BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
// This base does have a primary virtual base.
PrimaryVirtualBase = Layout.getPrimaryBase();
assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
-
+
// Now check if we have base subobject info about this primary base.
PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
-
+
if (PrimaryVirtualBaseInfo) {
if (PrimaryVirtualBaseInfo->Derived) {
// We did have info about this primary base, and it turns out that it
@@ -925,19 +929,19 @@ BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
}
-
+
if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
// Traversing the bases must have created the base info for our primary
// virtual base.
PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
assert(PrimaryVirtualBaseInfo &&
"Did not create a primary virtual base!");
-
+
// Claim the primary virtual base as our primary virtual base.
Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
PrimaryVirtualBaseInfo->Derived = Info;
}
-
+
return Info;
}
@@ -967,7 +971,7 @@ void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign) {
- CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
+ CharUnits BaseAlign = Packed ? CharUnits::One() : UnpackedBaseAlign;
// The maximum field alignment overrides base align.
if (!MaxFieldAlignment.isZero()) {
@@ -990,7 +994,7 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
// Compute base subobject info.
ComputeBaseSubobjectInfo(RD);
-
+
// If we have a primary base class, lay it out.
if (PrimaryBase) {
if (PrimaryBaseIsVirtual) {
@@ -1008,9 +1012,9 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
LayoutVirtualBase(PrimaryBaseInfo);
} else {
- BaseSubobjectInfo *PrimaryBaseInfo =
+ BaseSubobjectInfo *PrimaryBaseInfo =
NonVirtualBaseInfo.lookup(PrimaryBase);
- assert(PrimaryBaseInfo &&
+ assert(PrimaryBaseInfo &&
"Did not find base info for non-virtual primary base!");
LayoutNonVirtualBase(PrimaryBaseInfo);
@@ -1020,9 +1024,9 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
// primary base, add it in now.
} else if (RD->isDynamicClass()) {
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
- CharUnits PtrWidth =
+ CharUnits PtrWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- CharUnits PtrAlign =
+ CharUnits PtrAlign =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
EnsureVTablePointerAlignment(PtrAlign);
HasOwnVFPtr = true;
@@ -1070,14 +1074,14 @@ void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
// This base isn't interesting, it has no virtual bases.
if (!Info->Class->getNumVBases())
return;
-
+
// First, check if we have a virtual primary base to add offsets for.
if (Info->PrimaryVirtualBaseInfo) {
- assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
+ assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
"Primary virtual base is not virtual!");
if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
// Add the offset.
- assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
+ assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
"primary vbase offset already exists!");
VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
ASTRecordLayout::VBaseInfo(Offset, false)));
@@ -1147,13 +1151,13 @@ void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
const BaseSubobjectInfo *Base) {
assert(!Base->Derived && "Trying to lay out a primary virtual base!");
-
+
// Layout the base.
CharUnits Offset = LayoutBase(Base);
// Add its base class offset.
assert(!VBases.count(Base->Class) && "vbase offset already exists!");
- VBases.insert(std::make_pair(Base->Class,
+ VBases.insert(std::make_pair(Base->Class,
ASTRecordLayout::VBaseInfo(Offset, false)));
AddPrimaryVirtualBaseOffsets(Base, Offset);
@@ -1163,9 +1167,9 @@ CharUnits
ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class);
-
+
CharUnits Offset;
-
+
// Query the external layout to see if it provides an offset.
bool HasExternalLayout = false;
if (UseExternalLayout) {
@@ -1174,10 +1178,17 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
else
HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
}
-
+
+ // Clang <= 6 incorrectly applied the 'packed' attribute to base classes.
+ // Per GCC's documentation, it only applies to non-static data members.
CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment();
- CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
-
+ CharUnits BaseAlign =
+ (Packed && ((Context.getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver6) ||
+ Context.getTargetInfo().getTriple().isPS4()))
+ ? CharUnits::One()
+ : UnpackedBaseAlign;
+
// If we have an empty base class, try to place it at offset 0.
if (Base->Class->isEmpty() &&
(!HasExternalLayout || Offset == CharUnits::Zero()) &&
@@ -1213,7 +1224,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
InferAlignment = false;
}
}
-
+
if (!Base->Class->isEmpty()) {
// Update the data size.
setDataSize(Offset + Layout.getNonVirtualSize());
@@ -1234,7 +1245,7 @@ void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
IsMsStruct = RD->isMsStruct(Context);
}
- Packed = D->hasAttr<PackedAttr>();
+ Packed = D->hasAttr<PackedAttr>();
// Honor the default struct packing maximum alignment flag.
if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {
@@ -1256,7 +1267,7 @@ void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (unsigned MaxAlign = D->getMaxAlignment())
UpdateAlignment(Context.toCharUnitsFromBits(MaxAlign));
}
-
+
// If there is an external AST source, ask it for the various offsets.
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
if (ExternalASTSource *Source = Context.getExternalSource()) {
@@ -1410,7 +1421,7 @@ void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
FieldOffset = 0;
} else {
- // The bitfield is allocated starting at the next offset aligned
+ // The bitfield is allocated starting at the next offset aligned
// appropriately for T', with length n bits.
FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.toBits(TypeAlign));
@@ -1504,9 +1515,10 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
FieldAlign = TypeSize;
// If the previous field was not a bitfield, or was a bitfield
- // with a different storage unit size, we're done with that
- // storage unit.
- if (LastBitfieldTypeSize != TypeSize) {
+ // with a different storage unit size, or if this field doesn't fit into
+ // the current storage unit, we're done with that storage unit.
+ if (LastBitfieldTypeSize != TypeSize ||
+ UnfilledBitsInLastUnit < FieldSize) {
// Also, ignore zero-length bitfields after non-bitfields.
if (!LastBitfieldTypeSize && !FieldSize)
FieldAlign = 1;
@@ -1601,7 +1613,7 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool AllowPadding = MaxFieldAlignment.isZero();
// Compute the real offset.
- if (FieldSize == 0 ||
+ if (FieldSize == 0 ||
(AllowPadding &&
(FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
@@ -1699,7 +1711,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
setSize(std::max(getSizeInBits(), getDataSizeInBits()));
// Remember max struct/class alignment.
- UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
+ UnadjustedAlignment =
+ std::max(UnadjustedAlignment, Context.toCharUnitsFromBits(FieldAlign));
+ UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
Context.toCharUnitsFromBits(UnpackedFieldAlign));
}
@@ -1717,7 +1731,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
LastBitfieldTypeSize = 0;
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
- CharUnits FieldOffset =
+ CharUnits FieldOffset =
IsUnion ? CharUnits::Zero() : getDataSize();
CharUnits FieldSize;
CharUnits FieldAlign;
@@ -1732,12 +1746,12 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
FieldAlign = Context.getTypeAlignInChars(ATy->getElementType());
} else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
unsigned AS = Context.getTargetAddressSpace(RT->getPointeeType());
- FieldSize =
+ FieldSize =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS));
- FieldAlign =
+ FieldAlign =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(AS));
} else {
- std::pair<CharUnits, CharUnits> FieldInfo =
+ std::pair<CharUnits, CharUnits> FieldInfo =
Context.getTypeInfoInChars(D->getType());
FieldSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
@@ -1745,7 +1759,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
if (IsMsStruct) {
// If MS bitfield layout is required, figure out what type is being
// laid out and align the field to the width of that type.
-
+
// Resolve all typedefs down to their base type and round up the field
// alignment if necessary.
QualType T = Context.getBaseElementType(D->getType());
@@ -1791,7 +1805,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
if (FieldPacked)
FieldAlign = CharUnits::One();
- CharUnits MaxAlignmentInChars =
+ CharUnits MaxAlignmentInChars =
Context.toCharUnitsFromBits(D->getMaxAlignment());
FieldAlign = std::max(FieldAlign, MaxAlignmentInChars);
UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
@@ -1809,12 +1823,12 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
if (UseExternalLayout) {
FieldOffset = Context.toCharUnitsFromBits(
updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
-
+
if (!IsUnion && EmptySubobjects) {
// Record the fact that we're placing a field at this offset.
bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
(void)Allowed;
- assert(Allowed && "Externally-placed field cannot be placed here");
+ assert(Allowed && "Externally-placed field cannot be placed here");
}
} else {
if (!IsUnion && EmptySubobjects) {
@@ -1825,12 +1839,12 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
}
}
}
-
+
// Place this field at the current location.
FieldOffsets.push_back(Context.toBits(FieldOffset));
if (!UseExternalLayout)
- CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
+ CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
Context.toBits(UnpackedFieldOffset),
Context.toBits(UnpackedFieldAlign), FieldPacked, D);
@@ -1854,6 +1868,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
setSize(std::max(getSizeInBits(), getDataSizeInBits()));
// Remember max struct/class alignment.
+ UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
UpdateAlignment(FieldAlign, UnpackedFieldAlign);
}
@@ -1951,12 +1966,12 @@ ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
Alignment = CharUnits::One();
InferAlignment = false;
}
-
+
// Use the externally-supplied field offset.
return ExternalFieldOffset;
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// field padding diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -1982,7 +1997,7 @@ void ItaniumRecordLayoutBuilder::CheckFieldPadding(
// be done by clients of the AST, such as codegen.
if (D->getLocation().isInvalid())
return;
-
+
unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
// Warn if padding was introduced to the struct/class.
@@ -2133,7 +2148,7 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
// mode; fortunately, that is true because we want to assign
// consistently semantics to the type-traits intrinsics (or at
// least as many of them as possible).
- return RD->isTrivial() && RD->isStandardLayout();
+ return RD->isTrivial() && RD->isCXX11StandardLayout();
}
llvm_unreachable("bad tail-padding use kind");
@@ -2247,9 +2262,9 @@ private:
public:
void layout(const RecordDecl *RD);
void cxxLayout(const CXXRecordDecl *RD);
- /// \brief Initializes size and alignment and honors some flags.
+ /// Initializes size and alignment and honors some flags.
void initializeLayout(const RecordDecl *RD);
- /// \brief Initialized C++ layout, compute alignment and virtual alignment and
+ /// Initialized C++ layout, compute alignment and virtual alignment and
/// existence of vfptrs and vbptrs. Alignment is needed before the vfptr is
/// laid out.
void initializeCXXLayout(const CXXRecordDecl *RD);
@@ -2260,93 +2275,93 @@ public:
const ASTRecordLayout *&PreviousBaseLayout);
void injectVFPtr(const CXXRecordDecl *RD);
void injectVBPtr(const CXXRecordDecl *RD);
- /// \brief Lays out the fields of the record. Also rounds size up to
+ /// Lays out the fields of the record. Also rounds size up to
/// alignment.
void layoutFields(const RecordDecl *RD);
void layoutField(const FieldDecl *FD);
void layoutBitField(const FieldDecl *FD);
- /// \brief Lays out a single zero-width bit-field in the record and handles
+ /// Lays out a single zero-width bit-field in the record and handles
/// special cases associated with zero-width bit-fields.
void layoutZeroWidthBitField(const FieldDecl *FD);
void layoutVirtualBases(const CXXRecordDecl *RD);
void finalizeLayout(const RecordDecl *RD);
- /// \brief Gets the size and alignment of a base taking pragma pack and
+ /// Gets the size and alignment of a base taking pragma pack and
/// __declspec(align) into account.
ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout);
- /// \brief Gets the size and alignment of a field taking pragma pack and
+ /// Gets the size and alignment of a field taking pragma pack and
/// __declspec(align) into account. It also updates RequiredAlignment as a
/// side effect because it is most convenient to do so here.
ElementInfo getAdjustedElementInfo(const FieldDecl *FD);
- /// \brief Places a field at an offset in CharUnits.
+ /// Places a field at an offset in CharUnits.
void placeFieldAtOffset(CharUnits FieldOffset) {
FieldOffsets.push_back(Context.toBits(FieldOffset));
}
- /// \brief Places a bitfield at a bit offset.
+ /// Places a bitfield at a bit offset.
void placeFieldAtBitOffset(uint64_t FieldOffset) {
FieldOffsets.push_back(FieldOffset);
}
- /// \brief Compute the set of virtual bases for which vtordisps are required.
+ /// Compute the set of virtual bases for which vtordisps are required.
void computeVtorDispSet(
llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
const CXXRecordDecl *RD) const;
const ASTContext &Context;
- /// \brief The size of the record being laid out.
+ /// The size of the record being laid out.
CharUnits Size;
- /// \brief The non-virtual size of the record layout.
+ /// The non-virtual size of the record layout.
CharUnits NonVirtualSize;
- /// \brief The data size of the record layout.
+ /// The data size of the record layout.
CharUnits DataSize;
- /// \brief The current alignment of the record layout.
+ /// The current alignment of the record layout.
CharUnits Alignment;
- /// \brief The maximum allowed field alignment. This is set by #pragma pack.
+ /// The maximum allowed field alignment. This is set by #pragma pack.
CharUnits MaxFieldAlignment;
- /// \brief The alignment that this record must obey. This is imposed by
+ /// The alignment that this record must obey. This is imposed by
/// __declspec(align()) on the record itself or one of its fields or bases.
CharUnits RequiredAlignment;
- /// \brief The size of the allocation of the currently active bitfield.
+ /// The size of the allocation of the currently active bitfield.
/// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield
/// is true.
CharUnits CurrentBitfieldSize;
- /// \brief Offset to the virtual base table pointer (if one exists).
+ /// Offset to the virtual base table pointer (if one exists).
CharUnits VBPtrOffset;
- /// \brief Minimum record size possible.
+ /// Minimum record size possible.
CharUnits MinEmptyStructSize;
- /// \brief The size and alignment info of a pointer.
+ /// The size and alignment info of a pointer.
ElementInfo PointerInfo;
- /// \brief The primary base class (if one exists).
+ /// The primary base class (if one exists).
const CXXRecordDecl *PrimaryBase;
- /// \brief The class we share our vb-pointer with.
+ /// The class we share our vb-pointer with.
const CXXRecordDecl *SharedVBPtrBase;
- /// \brief The collection of field offsets.
+ /// The collection of field offsets.
SmallVector<uint64_t, 16> FieldOffsets;
- /// \brief Base classes and their offsets in the record.
+ /// Base classes and their offsets in the record.
BaseOffsetsMapTy Bases;
- /// \brief virtual base classes and their offsets in the record.
+ /// virtual base classes and their offsets in the record.
ASTRecordLayout::VBaseOffsetsMapTy VBases;
- /// \brief The number of remaining bits in our last bitfield allocation.
+ /// The number of remaining bits in our last bitfield allocation.
/// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is
/// true.
unsigned RemainingBitsInField;
bool IsUnion : 1;
- /// \brief True if the last field laid out was a bitfield and was not 0
+ /// True if the last field laid out was a bitfield and was not 0
/// width.
bool LastFieldIsNonZeroWidthBitfield : 1;
- /// \brief True if the class has its own vftable pointer.
+ /// True if the class has its own vftable pointer.
bool HasOwnVFPtr : 1;
- /// \brief True if the class has a vbtable pointer.
+ /// True if the class has a vbtable pointer.
bool HasVBPtr : 1;
- /// \brief True if the last sub-object within the type is zero sized or the
+ /// True if the last sub-object within the type is zero sized or the
/// object itself is zero sized. This *does not* count members that are not
/// records. Only used for MS-ABI.
bool EndsWithZeroSizedObject : 1;
- /// \brief True if this class is zero sized or first base is zero sized or
+ /// True if this class is zero sized or first base is zero sized or
/// has this property. Only used for MS-ABI.
bool LeadsWithZeroSizedBase : 1;
- /// \brief True if the external AST source provided a layout for this record.
+ /// True if the external AST source provided a layout for this record.
bool UseExternalLayout : 1;
- /// \brief The layout provided by the external AST source. Only active if
+ /// The layout provided by the external AST source. Only active if
/// UseExternalLayout is true.
ExternalLayout External;
};
@@ -2437,7 +2452,9 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
auto RoundingAlignment = Alignment;
if (!MaxFieldAlignment.isZero())
RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
- NonVirtualSize = Size = Size.alignTo(RoundingAlignment);
+ if (!UseExternalLayout)
+ Size = Size.alignTo(RoundingAlignment);
+ NonVirtualSize = Size;
RequiredAlignment = std::max(
RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
layoutVirtualBases(RD);
@@ -2611,8 +2628,8 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
}
if (!FoundBase) {
- if (MDCUsesEBO && BaseDecl->isEmpty() &&
- BaseLayout.getNonVirtualSize() == CharUnits::Zero()) {
+ if (MDCUsesEBO && BaseDecl->isEmpty()) {
+ assert(BaseLayout.getNonVirtualSize() == CharUnits::Zero());
BaseOffset = CharUnits::Zero();
} else {
// Otherwise, lay the base out at the end of the MDC.
@@ -2638,21 +2655,16 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
LastFieldIsNonZeroWidthBitfield = false;
ElementInfo Info = getAdjustedElementInfo(FD);
Alignment = std::max(Alignment, Info.Alignment);
- if (IsUnion) {
- placeFieldAtOffset(CharUnits::Zero());
- Size = std::max(Size, Info.Size);
- } else {
- CharUnits FieldOffset;
- if (UseExternalLayout) {
- FieldOffset =
- Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
- assert(FieldOffset >= Size && "field offset already allocated");
- } else {
- FieldOffset = Size.alignTo(Info.Alignment);
- }
- placeFieldAtOffset(FieldOffset);
- Size = FieldOffset + Info.Size;
- }
+ CharUnits FieldOffset;
+ if (UseExternalLayout)
+ FieldOffset =
+ Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
+ else if (IsUnion)
+ FieldOffset = CharUnits::Zero();
+ else
+ FieldOffset = Size.alignTo(Info.Alignment);
+ placeFieldAtOffset(FieldOffset);
+ Size = std::max(Size, FieldOffset + Info.Size);
}
void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
@@ -2669,7 +2681,7 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
// Check to see if this bitfield fits into an existing allocation. Note:
// MSVC refuses to pack bitfields of formal types with different sizes
// into the same allocation.
- if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&
+ if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);
RemainingBitsInField -= Width;
@@ -2677,7 +2689,14 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
}
LastFieldIsNonZeroWidthBitfield = true;
CurrentBitfieldSize = Info.Size;
- if (IsUnion) {
+ if (UseExternalLayout) {
+ auto FieldBitOffset = External.getExternalFieldOffset(FD);
+ placeFieldAtBitOffset(FieldBitOffset);
+ auto NewSize = Context.toCharUnitsFromBits(
+ llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth()));
+ Size = std::max(Size, NewSize);
+ Alignment = std::max(Alignment, Info.Alignment);
+ } else if (IsUnion) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
// TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
@@ -2953,7 +2972,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
if (D->hasExternalLexicalStorage() && !D->getDefinition())
getExternalSource()->CompleteType(const_cast<RecordDecl*>(D));
-
+
D = D->getDefinition();
assert(D && "Cannot get layout of forward declarations!");
assert(!D->isInvalidDecl() && "Cannot get layout of invalid decl!");
@@ -2972,7 +2991,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
Builder.cxxLayout(RD);
NewEntry = new (*this) ASTRecordLayout(
- *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
+ *this, Builder.Size, Builder.Alignment, Builder.Alignment,
+ Builder.RequiredAlignment,
Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(),
@@ -2982,7 +3002,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
} else {
Builder.layout(D);
NewEntry = new (*this) ASTRecordLayout(
- *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
+ *this, Builder.Size, Builder.Alignment, Builder.Alignment,
+ Builder.RequiredAlignment,
Builder.Size, Builder.FieldOffsets);
}
} else {
@@ -3003,7 +3024,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
CharUnits NonVirtualSize =
skipTailPadding ? DataSize : Builder.NonVirtualSize;
NewEntry = new (*this) ASTRecordLayout(
- *this, Builder.getSize(), Builder.Alignment,
+ *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
/*RequiredAlignment : used by MS-ABI)*/
Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets,
@@ -3016,7 +3037,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
Builder.Layout(D);
NewEntry = new (*this) ASTRecordLayout(
- *this, Builder.getSize(), Builder.Alignment,
+ *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
/*RequiredAlignment : used by MS-ABI)*/
Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
}
@@ -3037,7 +3058,7 @@ const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD)
return nullptr;
assert(RD->getDefinition() && "Cannot get key function for forward decl!");
- RD = cast<CXXRecordDecl>(RD->getDefinition());
+ RD = RD->getDefinition();
// Beware:
// 1) computing the key function might trigger deserialization, which might
@@ -3170,6 +3191,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
const ASTRecordLayout *NewEntry =
new (*this) ASTRecordLayout(*this, Builder.getSize(),
Builder.Alignment,
+ Builder.UnadjustedAlignment,
/*RequiredAlignment : used by MS-ABI)*/
Builder.Alignment,
Builder.getDataSize(),
@@ -3199,7 +3221,7 @@ static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset,
BufferOS << Begin << '-' << (Begin + Width - 1);
}
}
-
+
OS << llvm::right_justify(Buffer, 10) << " | ";
OS.indent(IndentLevel * 2);
}
@@ -3307,7 +3329,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
// Dump virtual bases.
if (CXXRD && IncludeVirtualBases) {
- const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps =
+ const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps =
Layout.getVBaseOffsetsMap();
for (const CXXBaseSpecifier &Base : CXXRD->vbases()) {
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index 982fd458493f..a041006c905e 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -11,14 +11,15 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Stmt.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
#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"
@@ -55,7 +56,7 @@ static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
if (Initialized)
return StmtClassInfo[E];
- // Intialize the table on the first use.
+ // Initialize the table on the first use.
Initialized = true;
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
@@ -127,7 +128,7 @@ Stmt *Stmt::IgnoreImplicit() {
return s;
}
-/// \brief Skip no-op (attributed, compound) container stmts and skip captured
+/// Skip no-op (attributed, compound) container stmts and skip captured
/// stmt at the top, if \a IgnoreCaptured is true.
Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
Stmt *S = this;
@@ -147,18 +148,18 @@ Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
return S;
}
-/// \brief Strip off all label-like statements.
+/// Strip off all label-like statements.
///
/// This will strip off label statements, case statements, attributed
/// statements and default statements recursively.
const Stmt *Stmt::stripLabelLikeStatements() const {
const Stmt *S = this;
while (true) {
- if (const LabelStmt *LS = dyn_cast<LabelStmt>(S))
+ if (const auto *LS = dyn_cast<LabelStmt>(S))
S = LS->getSubStmt();
- else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
+ else if (const auto *SC = dyn_cast<SwitchCase>(S))
S = SC->getSubStmt();
- else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S))
+ else if (const auto *AS = dyn_cast<AttributedStmt>(S))
S = AS->getSubStmt();
else
return S;
@@ -173,14 +174,14 @@ namespace {
// These silly little functions have to be static inline to suppress
// unused warnings, and they have to be defined to suppress other
// warnings.
- static inline good is_good(good) { return good(); }
+ static good is_good(good) { return good(); }
typedef Stmt::child_range children_t();
template <class T> good implements_children(children_t T::*) {
return good();
}
LLVM_ATTRIBUTE_UNUSED
- static inline bad implements_children(children_t Stmt::*) {
+ static bad implements_children(children_t Stmt::*) {
return bad();
}
@@ -189,7 +190,7 @@ namespace {
return good();
}
LLVM_ATTRIBUTE_UNUSED
- static inline bad implements_getLocStart(getLocStart_t Stmt::*) {
+ static bad implements_getLocStart(getLocStart_t Stmt::*) {
return bad();
}
@@ -198,7 +199,7 @@ namespace {
return good();
}
LLVM_ATTRIBUTE_UNUSED
- static inline bad implements_getLocEnd(getLocEnd_t Stmt::*) {
+ static bad implements_getLocEnd(getLocEnd_t Stmt::*) {
return bad();
}
@@ -351,49 +352,49 @@ AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
}
std::string AsmStmt::generateAsmString(const ASTContext &C) const {
- if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
return gccAsmStmt->generateAsmString(C);
- if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
return msAsmStmt->generateAsmString(C);
llvm_unreachable("unknown asm statement kind!");
}
StringRef AsmStmt::getOutputConstraint(unsigned i) const {
- if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
return gccAsmStmt->getOutputConstraint(i);
- if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
return msAsmStmt->getOutputConstraint(i);
llvm_unreachable("unknown asm statement kind!");
}
const Expr *AsmStmt::getOutputExpr(unsigned i) const {
- if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
return gccAsmStmt->getOutputExpr(i);
- if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
return msAsmStmt->getOutputExpr(i);
llvm_unreachable("unknown asm statement kind!");
}
StringRef AsmStmt::getInputConstraint(unsigned i) const {
- if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
return gccAsmStmt->getInputConstraint(i);
- if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
return msAsmStmt->getInputConstraint(i);
llvm_unreachable("unknown asm statement kind!");
}
const Expr *AsmStmt::getInputExpr(unsigned i) const {
- if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
return gccAsmStmt->getInputExpr(i);
- if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
return msAsmStmt->getInputExpr(i);
llvm_unreachable("unknown asm statement kind!");
}
StringRef AsmStmt::getClobber(unsigned i) const {
- if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
return gccAsmStmt->getClobber(i);
- if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
return msAsmStmt->getClobber(i);
llvm_unreachable("unknown asm statement kind!");
}
@@ -681,14 +682,14 @@ std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const {
AnalyzeAsmString(Pieces, C, DiagOffs);
std::string AsmString;
- for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
- if (Pieces[i].isString())
- AsmString += Pieces[i].getString();
- else if (Pieces[i].getModifier() == '\0')
- AsmString += '$' + llvm::utostr(Pieces[i].getOperandNo());
+ for (const auto &Piece : Pieces) {
+ if (Piece.isString())
+ AsmString += Piece.getString();
+ else if (Piece.getModifier() == '\0')
+ AsmString += '$' + llvm::utostr(Piece.getOperandNo());
else
- AsmString += "${" + llvm::utostr(Pieces[i].getOperandNo()) + ':' +
- Pieces[i].getModifier() + '}';
+ AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' +
+ Piece.getModifier() + '}';
}
return AsmString;
}
@@ -804,7 +805,7 @@ VarDecl *IfStmt::getConditionVariable() const {
if (!SubExprs[VAR])
return nullptr;
- DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ auto *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
}
@@ -839,7 +840,7 @@ VarDecl *ForStmt::getConditionVariable() const {
if (!SubExprs[CONDVAR])
return nullptr;
- DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
+ auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
return cast<VarDecl>(DS->getSingleDecl());
}
@@ -867,7 +868,7 @@ VarDecl *SwitchStmt::getConditionVariable() const {
if (!SubExprs[VAR])
return nullptr;
- DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ auto *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
}
@@ -901,7 +902,7 @@ VarDecl *WhileStmt::getConditionVariable() const {
if (!SubExprs[VAR])
return nullptr;
- DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ auto *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
}
@@ -918,8 +919,7 @@ void WhileStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
// IndirectGotoStmt
LabelDecl *IndirectGotoStmt::getConstantTarget() {
- if (AddrLabelExpr *E =
- dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
+ if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
return E->getLabel();
return nullptr;
}
@@ -1105,18 +1105,18 @@ const CapturedDecl *CapturedStmt::getCapturedDecl() const {
return CapDeclAndKind.getPointer();
}
-/// \brief Set the outlined function declaration.
+/// Set the outlined function declaration.
void CapturedStmt::setCapturedDecl(CapturedDecl *D) {
assert(D && "null CapturedDecl");
CapDeclAndKind.setPointer(D);
}
-/// \brief Retrieve the captured region kind.
+/// Retrieve the captured region kind.
CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
return CapDeclAndKind.getInt();
}
-/// \brief Set the captured region kind.
+/// Set the captured region kind.
void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
CapDeclAndKind.setInt(Kind);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp
index 666f5dcc9d97..bf2d6a16fb5f 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp
@@ -25,18 +25,14 @@ QualType CXXCatchStmt::getCaughtType() const {
CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, ArrayRef<Stmt *> handlers) {
- std::size_t Size = sizeof(CXXTryStmt);
- Size += ((handlers.size() + 1) * sizeof(Stmt *));
-
+ const size_t Size = totalSizeToAlloc<Stmt *>(handlers.size() + 1);
void *Mem = C.Allocate(Size, alignof(CXXTryStmt));
return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
}
CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
unsigned numHandlers) {
- std::size_t Size = sizeof(CXXTryStmt);
- Size += ((numHandlers + 1) * sizeof(Stmt *));
-
+ const size_t Size = totalSizeToAlloc<Stmt *>(numHandlers + 1);
void *Mem = C.Allocate(Size, alignof(CXXTryStmt));
return new (Mem) CXXTryStmt(Empty, numHandlers);
}
@@ -44,7 +40,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
ArrayRef<Stmt *> handlers)
: Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) {
- Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
+ Stmt **Stmts = getStmts();
Stmts[0] = tryBlock;
std::copy(handlers.begin(), handlers.end(), Stmts + 1);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
index 87bf5aaaa585..1258af7a2d37 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
@@ -1222,9 +1222,9 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create(
alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) *
+ sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd));
- OMPTargetParallelForSimdDirective *Dir =
+ OMPTargetParallelForSimdDirective *Dir =
new (Mem) OMPTargetParallelForSimdDirective(StartLoc, EndLoc,
CollapsedNum, Clauses.size());
Dir->setClauses(Clauses);
@@ -1262,20 +1262,20 @@ OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C,
alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) *
+ sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd));
return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses);
}
OMPTargetSimdDirective *
-OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs) {
unsigned Size =
llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) *
+ sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_target_simd));
OMPTargetSimdDirective *Dir = new (Mem)
OMPTargetSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
@@ -1303,7 +1303,7 @@ OMPTargetSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned Size =
llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) *
+ sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_target_simd));
return new (Mem) OMPTargetSimdDirective(CollapsedNum, NumClauses);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
index d7e668a83280..cbf26c036058 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -1,4 +1,4 @@
-//===--- StmtPrinter.cpp - Printing implementation for Stmt ASTs ----------===//
+//===- StmtPrinter.cpp - Printing implementation for Stmt ASTs ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,30 +14,60 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.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/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TypeTraits.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.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/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+
using namespace clang;
//===----------------------------------------------------------------------===//
// StmtPrinter Visitor
//===----------------------------------------------------------------------===//
-namespace {
+namespace {
+
class StmtPrinter : public StmtVisitor<StmtPrinter> {
raw_ostream &OS;
unsigned IndentLevel;
- clang::PrinterHelper* Helper;
+ PrinterHelper* Helper;
PrintingPolicy Policy;
const ASTContext *Context;
@@ -100,9 +130,11 @@ namespace {
void VisitStmt(Stmt *Node) LLVM_ATTRIBUTE_UNUSED {
Indent() << "<<unknown stmt type>>\n";
}
+
void VisitExpr(Expr *Node) LLVM_ATTRIBUTE_UNUSED {
OS << "<<unknown expr type>>";
}
+
void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
#define ABSTRACT_STMT(CLASS)
@@ -110,7 +142,8 @@ namespace {
void Visit##CLASS(CLASS *Node);
#include "clang/AST/StmtNodes.inc"
};
-}
+
+} // namespace
//===----------------------------------------------------------------------===//
// Stmt printing methods.
@@ -131,7 +164,7 @@ void StmtPrinter::PrintRawDecl(Decl *D) {
}
void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) {
- SmallVector<Decl*, 2> Decls(S->decls());
+ SmallVector<Decl *, 2> Decls(S->decls());
Decl::printGroup(Decls.data(), Decls.size(), OS, Policy, IndentLevel);
}
@@ -189,7 +222,7 @@ void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
PrintExpr(If->getCond());
OS << ')';
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(If->getThen())) {
+ if (auto *CS = dyn_cast<CompoundStmt>(If->getThen())) {
OS << ' ';
PrintRawCompoundStmt(CS);
OS << (If->getElse() ? ' ' : '\n');
@@ -202,11 +235,11 @@ void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
if (Stmt *Else = If->getElse()) {
OS << "else";
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Else)) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
OS << ' ';
PrintRawCompoundStmt(CS);
OS << '\n';
- } else if (IfStmt *ElseIf = dyn_cast<IfStmt>(Else)) {
+ } else if (auto *ElseIf = dyn_cast<IfStmt>(Else)) {
OS << ' ';
PrintRawIfStmt(ElseIf);
} else {
@@ -230,7 +263,7 @@ void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
OS << ")";
// Pretty print compoundstmt bodies (very common).
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
OS << " ";
PrintRawCompoundStmt(CS);
OS << "\n";
@@ -252,7 +285,7 @@ void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
void StmtPrinter::VisitDoStmt(DoStmt *Node) {
Indent() << "do ";
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
PrintRawCompoundStmt(CS);
OS << " ";
} else {
@@ -269,7 +302,7 @@ void StmtPrinter::VisitDoStmt(DoStmt *Node) {
void StmtPrinter::VisitForStmt(ForStmt *Node) {
Indent() << "for (";
if (Node->getInit()) {
- if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getInit()))
+ if (auto *DS = dyn_cast<DeclStmt>(Node->getInit()))
PrintRawDeclStmt(DS);
else
PrintExpr(cast<Expr>(Node->getInit()));
@@ -286,7 +319,7 @@ void StmtPrinter::VisitForStmt(ForStmt *Node) {
}
OS << ") ";
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
PrintRawCompoundStmt(CS);
OS << "\n";
} else {
@@ -297,7 +330,7 @@ void StmtPrinter::VisitForStmt(ForStmt *Node) {
void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
Indent() << "for (";
- if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getElement()))
+ if (auto *DS = dyn_cast<DeclStmt>(Node->getElement()))
PrintRawDeclStmt(DS);
else
PrintExpr(cast<Expr>(Node->getElement()));
@@ -305,7 +338,7 @@ void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
PrintExpr(Node->getCollection());
OS << ") ";
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
PrintRawCompoundStmt(CS);
OS << "\n";
} else {
@@ -333,13 +366,13 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
OS << "__if_exists (";
else
OS << "__if_not_exists (";
-
+
if (NestedNameSpecifier *Qualifier
= Node->getQualifierLoc().getNestedNameSpecifier())
Qualifier->print(OS, Policy);
-
+
OS << Node->getNameInfo() << ") ";
-
+
PrintRawCompoundStmt(Node->getSubStmt());
}
@@ -365,7 +398,6 @@ void StmtPrinter::VisitBreakStmt(BreakStmt *Node) {
if (Policy.IncludeNewlines) OS << "\n";
}
-
void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
Indent() << "return";
if (Node->getRetValue()) {
@@ -376,7 +408,6 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
if (Policy.IncludeNewlines) OS << "\n";
}
-
void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
Indent() << "asm ";
@@ -458,7 +489,7 @@ void StmtPrinter::VisitCapturedStmt(CapturedStmt *Node) {
void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
Indent() << "@try";
- if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
+ if (auto *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
PrintRawCompoundStmt(TS);
OS << "\n";
}
@@ -471,14 +502,13 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
PrintRawDecl(DS);
}
OS << ")";
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) {
+ if (auto *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) {
PrintRawCompoundStmt(CS);
OS << "\n";
}
}
- if (ObjCAtFinallyStmt *FS = static_cast<ObjCAtFinallyStmt *>(
- Node->getFinallyStmt())) {
+ if (auto *FS = static_cast<ObjCAtFinallyStmt *>(Node->getFinallyStmt())) {
Indent() << "@finally";
PrintRawCompoundStmt(dyn_cast<CompoundStmt>(FS->getFinallyBody()));
OS << "\n";
@@ -596,20 +626,26 @@ void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) {
//===----------------------------------------------------------------------===//
namespace {
+
class OMPClausePrinter : public OMPClauseVisitor<OMPClausePrinter> {
raw_ostream &OS;
const PrintingPolicy &Policy;
- /// \brief Process clauses with list of variables.
+
+ /// Process clauses with list of variables.
template <typename T>
void VisitOMPClauseList(T *Node, char StartSym);
+
public:
OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
- : OS(OS), Policy(Policy) { }
+ : OS(OS), Policy(Policy) {}
+
#define OPENMP_CLAUSE(Name, Class) \
void Visit##Class(Class *S);
#include "clang/Basic/OpenMPKinds.def"
};
+} // namespace
+
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
if (Node->getNameModifier() != OMPD_unknown)
@@ -776,7 +812,7 @@ void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
I != E; ++I) {
assert(*I && "Expected non-null Stmt");
OS << (I == Node->varlist_begin() ? StartSym : ',');
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) {
if (isa<OMPCapturedExprDecl>(DRE->getDecl()))
DRE->printPretty(OS, nullptr, Policy, 0);
else
@@ -954,7 +990,7 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
OS << "map(";
if (Node->getMapType() != OMPC_MAP_unknown) {
if (Node->getMapTypeModifier() != OMPC_MAP_unknown) {
- OS << getOpenMPSimpleClauseTypeName(OMPC_map,
+ OS << getOpenMPSimpleClauseTypeName(OMPC_map,
Node->getMapTypeModifier());
OS << ',';
}
@@ -1017,7 +1053,6 @@ void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
OS << ")";
}
}
-}
//===----------------------------------------------------------------------===//
// OpenMP directives printing methods
@@ -1027,43 +1062,38 @@ 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();
- I != E; ++I)
- if (*I && !(*I)->isImplicit()) {
- Printer.Visit(*I);
+ for (auto *Clause : Clauses)
+ if (Clause && !Clause->isImplicit()) {
OS << ' ';
+ Printer.Visit(Clause);
}
OS << "\n";
- if (S->hasAssociatedStmt() && S->getAssociatedStmt() && !ForceNoStmt) {
- assert(isa<CapturedStmt>(S->getAssociatedStmt()) &&
- "Expected captured statement!");
- Stmt *CS = cast<CapturedStmt>(S->getAssociatedStmt())->getCapturedStmt();
- PrintStmt(CS);
- }
+ if (!ForceNoStmt && S->hasAssociatedStmt())
+ PrintStmt(S->getInnermostCapturedStmt()->getCapturedStmt());
}
void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) {
- Indent() << "#pragma omp parallel ";
+ Indent() << "#pragma omp parallel";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPSimdDirective(OMPSimdDirective *Node) {
- Indent() << "#pragma omp simd ";
+ Indent() << "#pragma omp simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
- Indent() << "#pragma omp for ";
+ Indent() << "#pragma omp for";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPForSimdDirective(OMPForSimdDirective *Node) {
- Indent() << "#pragma omp for simd ";
+ Indent() << "#pragma omp for simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) {
- Indent() << "#pragma omp sections ";
+ Indent() << "#pragma omp sections";
PrintOMPExecutableDirective(Node);
}
@@ -1073,7 +1103,7 @@ void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) {
}
void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) {
- Indent() << "#pragma omp single ";
+ Indent() << "#pragma omp single";
PrintOMPExecutableDirective(Node);
}
@@ -1089,29 +1119,28 @@ void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) {
Node->getDirectiveName().printName(OS);
OS << ")";
}
- OS << " ";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) {
- Indent() << "#pragma omp parallel for ";
+ Indent() << "#pragma omp parallel for";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPParallelForSimdDirective(
OMPParallelForSimdDirective *Node) {
- Indent() << "#pragma omp parallel for simd ";
+ Indent() << "#pragma omp parallel for simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *Node) {
- Indent() << "#pragma omp parallel sections ";
+ Indent() << "#pragma omp parallel sections";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
- Indent() << "#pragma omp task ";
+ Indent() << "#pragma omp task";
PrintOMPExecutableDirective(Node);
}
@@ -1131,61 +1160,61 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
}
void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) {
- Indent() << "#pragma omp taskgroup ";
+ Indent() << "#pragma omp taskgroup";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
- Indent() << "#pragma omp flush ";
+ Indent() << "#pragma omp flush";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
- Indent() << "#pragma omp ordered ";
- PrintOMPExecutableDirective(Node);
+ Indent() << "#pragma omp ordered";
+ PrintOMPExecutableDirective(Node, Node->hasClausesOfKind<OMPDependClause>());
}
void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) {
- Indent() << "#pragma omp atomic ";
+ Indent() << "#pragma omp atomic";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) {
- Indent() << "#pragma omp target ";
+ Indent() << "#pragma omp target";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) {
- Indent() << "#pragma omp target data ";
+ Indent() << "#pragma omp target data";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetEnterDataDirective(
OMPTargetEnterDataDirective *Node) {
- Indent() << "#pragma omp target enter data ";
+ Indent() << "#pragma omp target enter data";
PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
}
void StmtPrinter::VisitOMPTargetExitDataDirective(
OMPTargetExitDataDirective *Node) {
- Indent() << "#pragma omp target exit data ";
+ Indent() << "#pragma omp target exit data";
PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
}
void StmtPrinter::VisitOMPTargetParallelDirective(
OMPTargetParallelDirective *Node) {
- Indent() << "#pragma omp target parallel ";
+ Indent() << "#pragma omp target parallel";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetParallelForDirective(
OMPTargetParallelForDirective *Node) {
- Indent() << "#pragma omp target parallel for ";
+ Indent() << "#pragma omp target parallel for";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
- Indent() << "#pragma omp teams ";
+ Indent() << "#pragma omp teams";
PrintOMPExecutableDirective(Node);
}
@@ -1198,111 +1227,111 @@ void StmtPrinter::VisitOMPCancellationPointDirective(
void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
Indent() << "#pragma omp cancel "
- << getOpenMPDirectiveName(Node->getCancelRegion()) << " ";
+ << getOpenMPDirectiveName(Node->getCancelRegion());
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *Node) {
- Indent() << "#pragma omp taskloop ";
+ Indent() << "#pragma omp taskloop";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTaskLoopSimdDirective(
OMPTaskLoopSimdDirective *Node) {
- Indent() << "#pragma omp taskloop simd ";
+ Indent() << "#pragma omp taskloop simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) {
- Indent() << "#pragma omp distribute ";
+ Indent() << "#pragma omp distribute";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetUpdateDirective(
OMPTargetUpdateDirective *Node) {
- Indent() << "#pragma omp target update ";
+ Indent() << "#pragma omp target update";
PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
}
void StmtPrinter::VisitOMPDistributeParallelForDirective(
OMPDistributeParallelForDirective *Node) {
- Indent() << "#pragma omp distribute parallel for ";
+ Indent() << "#pragma omp distribute parallel for";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPDistributeParallelForSimdDirective(
OMPDistributeParallelForSimdDirective *Node) {
- Indent() << "#pragma omp distribute parallel for simd ";
+ Indent() << "#pragma omp distribute parallel for simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPDistributeSimdDirective(
OMPDistributeSimdDirective *Node) {
- Indent() << "#pragma omp distribute simd ";
+ Indent() << "#pragma omp distribute simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetParallelForSimdDirective(
OMPTargetParallelForSimdDirective *Node) {
- Indent() << "#pragma omp target parallel for simd ";
+ Indent() << "#pragma omp target parallel for simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) {
- Indent() << "#pragma omp target simd ";
+ Indent() << "#pragma omp target simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTeamsDistributeDirective(
OMPTeamsDistributeDirective *Node) {
- Indent() << "#pragma omp teams distribute ";
+ Indent() << "#pragma omp teams distribute";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTeamsDistributeSimdDirective(
OMPTeamsDistributeSimdDirective *Node) {
- Indent() << "#pragma omp teams distribute simd ";
+ Indent() << "#pragma omp teams distribute simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective(
OMPTeamsDistributeParallelForSimdDirective *Node) {
- Indent() << "#pragma omp teams distribute parallel for simd ";
+ Indent() << "#pragma omp teams distribute parallel for simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective(
OMPTeamsDistributeParallelForDirective *Node) {
- Indent() << "#pragma omp teams distribute parallel for ";
+ Indent() << "#pragma omp teams distribute parallel for";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) {
- Indent() << "#pragma omp target teams ";
+ Indent() << "#pragma omp target teams";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetTeamsDistributeDirective(
OMPTargetTeamsDistributeDirective *Node) {
- Indent() << "#pragma omp target teams distribute ";
+ Indent() << "#pragma omp target teams distribute";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective(
OMPTargetTeamsDistributeParallelForDirective *Node) {
- Indent() << "#pragma omp target teams distribute parallel for ";
+ Indent() << "#pragma omp target teams distribute parallel for";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
OMPTargetTeamsDistributeParallelForSimdDirective *Node) {
- Indent() << "#pragma omp target teams distribute parallel for simd ";
+ Indent() << "#pragma omp target teams distribute parallel for simd";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
OMPTargetTeamsDistributeSimdDirective *Node) {
- Indent() << "#pragma omp target teams distribute simd ";
+ Indent() << "#pragma omp target teams distribute simd";
PrintOMPExecutableDirective(Node);
}
@@ -1311,7 +1340,7 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
//===----------------------------------------------------------------------===//
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
- if (auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
+ if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
return;
}
@@ -1347,8 +1376,7 @@ void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
static bool isImplicitSelf(const Expr *E) {
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (const ImplicitParamDecl *PD =
- dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
+ if (const auto *PD = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf &&
DRE->getLocStart().isInvalid())
return true;
@@ -1378,14 +1406,17 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
OS << Node->getClassReceiver()->getName() << ".";
}
- if (Node->isImplicitProperty())
- Node->getImplicitPropertyGetter()->getSelector().print(OS);
- else
+ if (Node->isImplicitProperty()) {
+ if (const auto *Getter = Node->getImplicitPropertyGetter())
+ Getter->getSelector().print(OS);
+ else
+ OS << SelectorTable::getPropertyNameFromSetterSelector(
+ Node->getImplicitPropertySetter()->getSelector());
+ } else
OS << Node->getExplicitProperty()->getName();
}
void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
-
PrintExpr(Node->getBaseExpr());
OS << "[";
PrintExpr(Node->getKeyExpr());
@@ -1498,6 +1529,28 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
}
}
+void StmtPrinter::VisitFixedPointLiteral(FixedPointLiteral *Node) {
+ if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
+ return;
+ OS << Node->getValueAsString(/*Radix=*/10);
+
+ switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
+ default: llvm_unreachable("Unexpected type for fixed point literal!");
+ case BuiltinType::ShortFract: OS << "hr"; break;
+ case BuiltinType::ShortAccum: OS << "hk"; break;
+ case BuiltinType::UShortFract: OS << "uhr"; break;
+ case BuiltinType::UShortAccum: OS << "uhk"; break;
+ case BuiltinType::Fract: OS << "r"; break;
+ case BuiltinType::Accum: OS << "k"; break;
+ case BuiltinType::UFract: OS << "ur"; break;
+ case BuiltinType::UAccum: OS << "uk"; break;
+ case BuiltinType::LongFract: OS << "lr"; break;
+ case BuiltinType::LongAccum: OS << "lk"; break;
+ case BuiltinType::ULongFract: OS << "ulr"; break;
+ case BuiltinType::ULongAccum: OS << "ulk"; break;
+ }
+}
+
static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
bool PrintSuffix) {
SmallString<16> Str;
@@ -1535,11 +1588,13 @@ void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
Str->outputString(OS);
}
+
void StmtPrinter::VisitParenExpr(ParenExpr *Node) {
OS << "(";
PrintExpr(Node->getSubExpr());
OS << ")";
}
+
void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
if (!Node->isPostfix()) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
@@ -1590,12 +1645,12 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
IdentifierInfo *Id = ON.getFieldName();
if (!Id)
continue;
-
+
if (PrintedSomething)
OS << ".";
else
PrintedSomething = true;
- OS << Id->getName();
+ OS << Id->getName();
}
OS << ")";
}
@@ -1695,7 +1750,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
if (!Policy.SuppressImplicitBase || !isImplicitThis(Node->getBase())) {
PrintExpr(Node->getBase());
- MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
+ auto *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
FieldDecl *ParentDecl =
ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl())
: nullptr;
@@ -1704,7 +1759,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
OS << (Node->isArrow() ? "->" : ".");
}
- if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
+ if (auto *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
if (FD->isAnonymousStructOrUnion())
return;
@@ -1716,6 +1771,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
if (Node->hasExplicitTemplateArgs())
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
+
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->isa" : ".isa");
@@ -1726,32 +1782,38 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
OS << ".";
OS << Node->getAccessor().getName();
}
+
void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
OS << '(';
Node->getTypeAsWritten().print(OS, Policy);
OS << ')';
PrintExpr(Node->getSubExpr());
}
+
void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
OS << '(';
Node->getType().print(OS, Policy);
OS << ')';
PrintExpr(Node->getInitializer());
}
+
void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
// No need to print anything, simply forward to the subexpression.
PrintExpr(Node->getSubExpr());
}
+
void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
PrintExpr(Node->getLHS());
OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
PrintExpr(Node->getRHS());
}
+
void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
PrintExpr(Node->getLHS());
OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
PrintExpr(Node->getRHS());
}
+
void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) {
PrintExpr(Node->getCond());
OS << " ? ";
@@ -1768,6 +1830,7 @@ StmtPrinter::VisitBinaryConditionalOperator(BinaryConditionalOperator *Node) {
OS << " ?: ";
PrintExpr(Node->getFalseExpr());
}
+
void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) {
OS << "&&" << Node->getLabel()->getName();
}
@@ -2100,7 +2163,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
OS << cast<StringLiteral>(Node->getArg(0)->IgnoreImpCasts())->getString();
break;
case UserDefinedLiteral::LOK_Template: {
- DeclRefExpr *DRE = cast<DeclRefExpr>(Node->getCallee()->IgnoreImpCasts());
+ const auto *DRE = cast<DeclRefExpr>(Node->getCallee()->IgnoreImpCasts());
const TemplateArgumentList *Args =
cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs();
assert(Args);
@@ -2121,13 +2184,13 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
}
case UserDefinedLiteral::LOK_Integer: {
// Print integer literal without suffix.
- IntegerLiteral *Int = cast<IntegerLiteral>(Node->getCookedLiteral());
+ const auto *Int = cast<IntegerLiteral>(Node->getCookedLiteral());
OS << Int->getValue().toString(10, /*isSigned*/false);
break;
}
case UserDefinedLiteral::LOK_Floating: {
// Print floating literal without suffix.
- FloatingLiteral *Float = cast<FloatingLiteral>(Node->getCookedLiteral());
+ auto *Float = cast<FloatingLiteral>(Node->getCookedLiteral());
PrintFloatingLiteral(OS, Float, /*PrintSuffix=*/false);
break;
}
@@ -2240,9 +2303,11 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
case LCK_This:
OS << "this";
break;
+
case LCK_StarThis:
OS << "*this";
break;
+
case LCK_ByRef:
if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C))
OS << '&';
@@ -2252,6 +2317,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
case LCK_ByCopy:
OS << C->getCapturedVar()->getName();
break;
+
case LCK_VLAType:
llvm_unreachable("VLA type in explicit captures.");
}
@@ -2265,7 +2331,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
OS << " (";
CXXMethodDecl *Method = Node->getCallOperator();
NeedComma = false;
- for (auto P : Method->parameters()) {
+ for (const auto *P : Method->parameters()) {
if (NeedComma) {
OS << ", ";
} else {
@@ -2284,8 +2350,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
if (Node->isMutable())
OS << " mutable";
- const FunctionProtoType *Proto
- = Method->getType()->getAs<FunctionProtoType>();
+ auto *Proto = Method->getType()->getAs<FunctionProtoType>();
Proto->printExceptionSpecification(OS, Policy);
// FIXME: Attributes
@@ -2569,13 +2634,11 @@ void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) {
PrintExpr(S->getOperand());
}
-
void StmtPrinter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) {
OS << "co_await ";
PrintExpr(S->getOperand());
}
-
void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) {
OS << "co_yield ";
PrintExpr(S->getOperand());
@@ -2609,7 +2672,7 @@ void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
if (I > 0)
OS << ", ";
-
+
ObjCDictionaryElement Element = E->getKeyValueElement(I);
Visit(Element.Key);
OS << " : ";
@@ -2708,7 +2771,7 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
(*AI)->getType().print(OS, Policy, ParamStr);
}
- const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
+ const auto *FT = cast<FunctionProtoType>(AFT);
if (FT->isVariadic()) {
if (!BD->param_empty()) OS << ", ";
OS << "...";
@@ -2718,7 +2781,7 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
OS << "{ }";
}
-void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
+void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
PrintExpr(Node->getSourceExpr());
}
@@ -2755,4 +2818,4 @@ void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper,
//===----------------------------------------------------------------------===//
// Implement virtual destructor.
-PrinterHelper::~PrinterHelper() {}
+PrinterHelper::~PrinterHelper() = default;
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
index 00ef0da18bbb..15653c4fd838 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -38,37 +38,39 @@ namespace {
void VisitStmt(const Stmt *S);
+ virtual void HandleStmtClass(Stmt::StmtClass SC) = 0;
+
#define STMT(Node, Base) void Visit##Node(const Node *S);
#include "clang/AST/StmtNodes.inc"
- /// \brief Visit a declaration that is referenced within an expression
+ /// Visit a declaration that is referenced within an expression
/// or statement.
virtual void VisitDecl(const Decl *D) = 0;
- /// \brief Visit a type that is referenced within an expression or
+ /// Visit a type that is referenced within an expression or
/// statement.
virtual void VisitType(QualType T) = 0;
- /// \brief Visit a name that occurs within an expression or statement.
- virtual void VisitName(DeclarationName Name) = 0;
+ /// Visit a name that occurs within an expression or statement.
+ virtual void VisitName(DeclarationName Name, bool TreatAsDecl = false) = 0;
- /// \brief Visit identifiers that are not in Decl's or Type's.
+ /// Visit identifiers that are not in Decl's or Type's.
virtual void VisitIdentifierInfo(IdentifierInfo *II) = 0;
- /// \brief Visit a nested-name-specifier that occurs within an expression
+ /// Visit a nested-name-specifier that occurs within an expression
/// or statement.
virtual void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) = 0;
- /// \brief Visit a template name that occurs within an expression or
+ /// Visit a template name that occurs within an expression or
/// statement.
virtual void VisitTemplateName(TemplateName Name) = 0;
- /// \brief Visit template arguments that occur within an expression or
+ /// Visit template arguments that occur within an expression or
/// statement.
void VisitTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs);
- /// \brief Visit a single template argument.
+ /// Visit a single template argument.
void VisitTemplateArgument(const TemplateArgument &Arg);
};
@@ -80,6 +82,10 @@ namespace {
const ASTContext &Context, bool Canonical)
: StmtProfiler(ID, Canonical), Context(Context) {}
private:
+ void HandleStmtClass(Stmt::StmtClass SC) override {
+ ID.AddInteger(SC);
+ }
+
void VisitDecl(const Decl *D) override {
ID.AddInteger(D ? D->getKind() : 0);
@@ -134,7 +140,7 @@ namespace {
ID.AddPointer(T.getAsOpaquePtr());
}
- void VisitName(DeclarationName Name) override {
+ void VisitName(DeclarationName Name, bool /*TreatAsDecl*/) override {
ID.AddPointer(Name.getAsOpaquePtr());
}
@@ -163,11 +169,26 @@ namespace {
: StmtProfiler(ID, false), Hash(Hash) {}
private:
+ void HandleStmtClass(Stmt::StmtClass SC) override {
+ if (SC == Stmt::UnresolvedLookupExprClass) {
+ // Pretend that the name looked up is a Decl due to how templates
+ // handle some Decl lookups.
+ ID.AddInteger(Stmt::DeclRefExprClass);
+ } else {
+ ID.AddInteger(SC);
+ }
+ }
+
void VisitType(QualType T) override {
Hash.AddQualType(T);
}
- void VisitName(DeclarationName Name) override {
+ void VisitName(DeclarationName Name, bool TreatAsDecl) override {
+ if (TreatAsDecl) {
+ // A Decl can be null, so each Decl is preceded by a boolean to
+ // store its nullness. Add a boolean here to match.
+ ID.AddBoolean(true);
+ }
Hash.AddDeclarationName(Name);
}
void VisitIdentifierInfo(IdentifierInfo *II) override {
@@ -196,7 +217,9 @@ namespace {
void StmtProfiler::VisitStmt(const Stmt *S) {
assert(S && "Requires non-null Stmt pointer");
- ID.AddInteger(S->getStmtClass());
+
+ HandleStmtClass(S->getStmtClass());
+
for (const Stmt *SubStmt : S->children()) {
if (SubStmt)
Visit(SubStmt);
@@ -382,7 +405,7 @@ StmtProfiler::VisitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt *S) {
namespace {
class OMPClauseProfiler : public ConstOMPClauseVisitor<OMPClauseProfiler> {
StmtProfiler *Profiler;
- /// \brief Process clauses with list of variables.
+ /// Process clauses with list of variables.
template <typename T>
void VisitOMPClauseList(T *Node);
@@ -966,8 +989,11 @@ void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
if (!Canonical)
VisitNestedNameSpecifier(S->getQualifier());
VisitDecl(S->getDecl());
- if (!Canonical)
- VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+ if (!Canonical) {
+ ID.AddBoolean(S->hasExplicitTemplateArgs());
+ if (S->hasExplicitTemplateArgs())
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+ }
}
void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
@@ -981,6 +1007,12 @@ void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind());
}
+void StmtProfiler::VisitFixedPointLiteral(const FixedPointLiteral *S) {
+ VisitExpr(S);
+ S->getValue().Profile(ID);
+ ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind());
+}
+
void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) {
VisitExpr(S);
ID.AddInteger(S->getKind());
@@ -1245,25 +1277,24 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_Arrow:
case OO_Call:
case OO_Conditional:
- case OO_Coawait:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Invalid operator call kind");
-
+
case OO_Plus:
if (S->getNumArgs() == 1) {
UnaryOp = UO_Plus;
return Stmt::UnaryOperatorClass;
}
-
+
BinaryOp = BO_Add;
return Stmt::BinaryOperatorClass;
-
+
case OO_Minus:
if (S->getNumArgs() == 1) {
UnaryOp = UO_Minus;
return Stmt::UnaryOperatorClass;
}
-
+
BinaryOp = BO_Sub;
return Stmt::BinaryOperatorClass;
@@ -1272,14 +1303,14 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
UnaryOp = UO_Deref;
return Stmt::UnaryOperatorClass;
}
-
+
BinaryOp = BO_Mul;
return Stmt::BinaryOperatorClass;
case OO_Slash:
BinaryOp = BO_Div;
return Stmt::BinaryOperatorClass;
-
+
case OO_Percent:
BinaryOp = BO_Rem;
return Stmt::BinaryOperatorClass;
@@ -1293,10 +1324,10 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
UnaryOp = UO_AddrOf;
return Stmt::UnaryOperatorClass;
}
-
+
BinaryOp = BO_And;
return Stmt::BinaryOperatorClass;
-
+
case OO_Pipe:
BinaryOp = BO_Or;
return Stmt::BinaryOperatorClass;
@@ -1320,7 +1351,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_Greater:
BinaryOp = BO_GT;
return Stmt::BinaryOperatorClass;
-
+
case OO_PlusEqual:
BinaryOp = BO_AddAssign;
return Stmt::CompoundAssignOperatorClass;
@@ -1344,19 +1375,19 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_CaretEqual:
BinaryOp = BO_XorAssign;
return Stmt::CompoundAssignOperatorClass;
-
+
case OO_AmpEqual:
BinaryOp = BO_AndAssign;
return Stmt::CompoundAssignOperatorClass;
-
+
case OO_PipeEqual:
BinaryOp = BO_OrAssign;
return Stmt::CompoundAssignOperatorClass;
-
+
case OO_LessLess:
BinaryOp = BO_Shl;
return Stmt::BinaryOperatorClass;
-
+
case OO_GreaterGreater:
BinaryOp = BO_Shr;
return Stmt::BinaryOperatorClass;
@@ -1364,7 +1395,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_LessLessEqual:
BinaryOp = BO_ShlAssign;
return Stmt::CompoundAssignOperatorClass;
-
+
case OO_GreaterGreaterEqual:
BinaryOp = BO_ShrAssign;
return Stmt::CompoundAssignOperatorClass;
@@ -1372,15 +1403,15 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_EqualEqual:
BinaryOp = BO_EQ;
return Stmt::BinaryOperatorClass;
-
+
case OO_ExclaimEqual:
BinaryOp = BO_NE;
return Stmt::BinaryOperatorClass;
-
+
case OO_LessEqual:
BinaryOp = BO_LE;
return Stmt::BinaryOperatorClass;
-
+
case OO_GreaterEqual:
BinaryOp = BO_GE;
return Stmt::BinaryOperatorClass;
@@ -1388,17 +1419,17 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_Spaceship:
// FIXME: Update this once we support <=> expressions.
llvm_unreachable("<=> expressions not supported yet");
-
+
case OO_AmpAmp:
BinaryOp = BO_LAnd;
return Stmt::BinaryOperatorClass;
-
+
case OO_PipePipe:
BinaryOp = BO_LOr;
return Stmt::BinaryOperatorClass;
case OO_PlusPlus:
- UnaryOp = S->getNumArgs() == 1? UO_PreInc
+ UnaryOp = S->getNumArgs() == 1? UO_PreInc
: UO_PostInc;
return Stmt::UnaryOperatorClass;
@@ -1414,11 +1445,15 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_ArrowStar:
BinaryOp = BO_PtrMemI;
return Stmt::BinaryOperatorClass;
-
+
case OO_Subscript:
return Stmt::ArraySubscriptExprClass;
+
+ case OO_Coawait:
+ UnaryOp = UO_Coawait;
+ return Stmt::UnaryOperatorClass;
}
-
+
llvm_unreachable("Invalid overloaded operator expression");
}
@@ -1450,7 +1485,7 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
Visit(S->getArg(I));
if (SC == Stmt::UnaryOperatorClass)
ID.AddInteger(UnaryOp);
- else if (SC == Stmt::BinaryOperatorClass ||
+ else if (SC == Stmt::BinaryOperatorClass ||
SC == Stmt::CompoundAssignOperatorClass)
ID.AddInteger(BinaryOp);
else
@@ -1659,7 +1694,7 @@ StmtProfiler::VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) {
void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) {
VisitExpr(S);
VisitNestedNameSpecifier(S->getQualifier());
- VisitName(S->getName());
+ VisitName(S->getName(), /*TreatAsDecl*/ true);
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
@@ -1811,7 +1846,7 @@ void StmtProfiler::VisitCoyieldExpr(const CoyieldExpr *S) {
}
void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
- VisitExpr(E);
+ VisitExpr(E);
}
void StmtProfiler::VisitTypoExpr(const TypoExpr *E) {
@@ -1930,7 +1965,7 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
case TemplateArgument::TemplateExpansion:
VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
-
+
case TemplateArgument::Declaration:
VisitDecl(Arg.getAsDecl());
break;
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index e81c11a77825..a78927d229b9 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -43,7 +43,7 @@
using namespace clang;
-/// \brief Print a template integral argument value.
+/// Print a template integral argument value.
///
/// \param TemplArg the TemplateArgument instance to print.
///
@@ -157,16 +157,16 @@ bool TemplateArgument::isInstantiationDependent() const {
switch (getKind()) {
case Null:
llvm_unreachable("Should not have a NULL template argument");
-
+
case Type:
return getAsType()->isInstantiationDependentType();
-
+
case Template:
return getAsTemplate().isInstantiationDependent();
-
+
case TemplateExpansion:
return true;
-
+
case Declaration:
if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
return DC->isDependentContext();
@@ -174,14 +174,14 @@ bool TemplateArgument::isInstantiationDependent() const {
case NullPtr:
return false;
-
+
case Integral:
// Never dependent
return false;
-
+
case Expression:
return getAsExpr()->isInstantiationDependent();
-
+
case Pack:
for (const auto &P : pack_elements())
if (P.isInstantiationDependent())
@@ -197,17 +197,17 @@ bool TemplateArgument::isPackExpansion() const {
case Null:
case Declaration:
case Integral:
- case Pack:
+ case Pack:
case Template:
case NullPtr:
return false;
-
+
case TemplateExpansion:
return true;
-
+
case Type:
return isa<PackExpansionType>(getAsType());
-
+
case Expression:
return isa<PackExpansionExpr>(getAsExpr());
}
@@ -233,7 +233,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
if (getAsTemplate().containsUnexpandedParameterPack())
return true;
break;
-
+
case Expression:
if (getAsExpr()->containsUnexpandedParameterPack())
return true;
@@ -254,8 +254,8 @@ Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
assert(getKind() == TemplateExpansion);
if (TemplateArg.NumExpansions)
return TemplateArg.NumExpansions - 1;
-
- return None;
+
+ return None;
}
QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
@@ -319,7 +319,7 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
}
break;
}
-
+
case Integral:
getAsIntegral().Profile(ID);
getIntegralType().Profile(ID);
@@ -342,7 +342,7 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
switch (getKind()) {
case Null:
case Type:
- case Expression:
+ case Expression:
case Template:
case TemplateExpansion:
case NullPtr:
@@ -368,14 +368,14 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
TemplateArgument TemplateArgument::getPackExpansionPattern() const {
assert(isPackExpansion());
-
+
switch (getKind()) {
case Type:
return getAsType()->getAs<PackExpansionType>()->getPattern();
-
+
case Expression:
return cast<PackExpansionExpr>(getAsExpr())->getPattern();
-
+
case TemplateExpansion:
return TemplateArgument(getAsTemplateOrTemplatePattern());
@@ -391,22 +391,22 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-void TemplateArgument::print(const PrintingPolicy &Policy,
+void TemplateArgument::print(const PrintingPolicy &Policy,
raw_ostream &Out) const {
switch (getKind()) {
case Null:
Out << "(no value)";
break;
-
+
case Type: {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressStrongLifetime = true;
getAsType().print(Out, SubPolicy);
break;
}
-
+
case Declaration: {
- NamedDecl *ND = cast<NamedDecl>(getAsDecl());
+ NamedDecl *ND = getAsDecl();
Out << '&';
if (ND->getDeclName()) {
// FIXME: distinguish between pointer and reference args?
@@ -429,15 +429,15 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
getAsTemplateOrTemplatePattern().print(Out, Policy);
Out << "...";
break;
-
+
case Integral:
printIntegral(*this, Out, Policy);
break;
-
+
case Expression:
getAsExpr()->printPretty(Out, nullptr, Policy);
break;
-
+
case Pack:
Out << "<";
bool First = true;
@@ -446,11 +446,11 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
First = false;
else
Out << ", ";
-
+
P.print(Policy, Out);
}
Out << ">";
- break;
+ break;
}
}
@@ -486,13 +486,13 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
case TemplateArgument::Template:
if (getTemplateQualifierLoc())
- return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
+ return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
getTemplateNameLoc());
return SourceRange(getTemplateNameLoc());
case TemplateArgument::TemplateExpansion:
if (getTemplateQualifierLoc())
- return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
+ return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
getTemplateEllipsisLoc());
return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
@@ -514,19 +514,19 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
// This is bad, but not as bad as crashing because of argument
// count mismatches.
return DB << "(null template argument)";
-
+
case TemplateArgument::Type:
return DB << Arg.getAsType();
-
+
case TemplateArgument::Declaration:
return DB << Arg.getAsDecl();
case TemplateArgument::NullPtr:
return DB << "nullptr";
-
+
case TemplateArgument::Integral:
return DB << Arg.getAsIntegral().toString(10);
-
+
case TemplateArgument::Template:
return DB << Arg.getAsTemplate();
@@ -545,7 +545,7 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
return DB << OS.str();
}
-
+
case TemplateArgument::Pack: {
// FIXME: We're guessing at LangOptions!
SmallString<32> Str;
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
index bd04fd8366b3..0a7a6bc3c6a7 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
@@ -31,7 +31,7 @@
using namespace clang;
-TemplateArgument
+TemplateArgument
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
}
@@ -40,7 +40,7 @@ void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Parameter, Replacement);
}
-void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
+void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *parameter,
TemplateName replacement) {
ID.AddPointer(parameter);
@@ -52,7 +52,7 @@ void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
Profile(ID, Context, Parameter, getArgumentPack());
}
-void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
+void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack) {
@@ -180,13 +180,18 @@ bool TemplateName::isInstantiationDependent() const {
if (QTN->getQualifier()->isInstantiationDependent())
return true;
}
-
+
return isDependent();
}
bool TemplateName::containsUnexpandedParameterPack() const {
+ if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+ if (QTN->getQualifier()->containsUnexpandedParameterPack())
+ return true;
+ }
+
if (TemplateDecl *Template = getAsTemplateDecl()) {
- if (TemplateTemplateParmDecl *TTP
+ if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Template))
return TTP->isParameterPack();
@@ -194,7 +199,7 @@ bool TemplateName::containsUnexpandedParameterPack() const {
}
if (DependentTemplateName *DTN = getAsDependentTemplateName())
- return DTN->getQualifier() &&
+ return DTN->getQualifier() &&
DTN->getQualifier()->containsUnexpandedParameterPack();
return getAsSubstTemplateTemplateParmPack() != nullptr;
@@ -215,7 +220,7 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
if (!SuppressNNS && DTN->getQualifier())
DTN->getQualifier()->print(OS, Policy);
OS << "template ";
-
+
if (DTN->isIdentifier())
OS << DTN->getIdentifier()->getName();
else
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
index 38f2a16fa16f..f79a59712a41 100644
--- a/contrib/llvm/tools/clang/lib/AST/Type.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -29,6 +29,7 @@
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
@@ -87,6 +88,16 @@ const IdentifierInfo* QualType::getBaseTypeIdentifier() const {
return nullptr;
}
+bool QualType::mayBeDynamicClass() const {
+ const auto *ClassDecl = getTypePtr()->getPointeeCXXRecordDecl();
+ return ClassDecl && ClassDecl->mayBeDynamicClass();
+}
+
+bool QualType::mayBeNotDynamicClass() const {
+ const auto *ClassDecl = getTypePtr()->getPointeeCXXRecordDecl();
+ return !ClassDecl || ClassDecl->mayBeNonDynamicClass();
+}
+
bool QualType::isConstant(QualType T, const ASTContext &Ctx) {
if (T.isConstQualified())
return true;
@@ -127,14 +138,14 @@ unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context,
SizeExtended.getBitWidth()) * 2);
llvm::APSInt TotalSize(llvm::APInt(SizeExtended.getBitWidth(), ElementSize));
- TotalSize *= SizeExtended;
+ TotalSize *= SizeExtended;
return TotalSize.getActiveBits();
}
unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) {
unsigned Bits = Context.getTypeSize(Context.getSizeType());
-
+
// Limit the number of bits in size_t so that maximal bit size fits 64 bit
// integer (see PR8256). We can do this as currently there is no hardware
// that supports full 64-bit virtual space.
@@ -144,7 +155,7 @@ unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) {
return Bits;
}
-DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context,
+DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context,
QualType et, QualType can,
Expr *e, ArraySizeModifier sm,
unsigned tq,
@@ -166,11 +177,32 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
E->Profile(ID, Context, true);
}
+DependentVectorType::DependentVectorType(
+ const ASTContext &Context, QualType ElementType, QualType CanonType,
+ Expr *SizeExpr, SourceLocation Loc, VectorType::VectorKind VecKind)
+ : Type(DependentVector, CanonType, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ ElementType->isVariablyModifiedType(),
+ ElementType->containsUnexpandedParameterPack() ||
+ (SizeExpr && SizeExpr->containsUnexpandedParameterPack())),
+ Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) {
+ VectorTypeBits.VecKind = VecKind;
+}
+
+void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context,
+ QualType ElementType, const Expr *SizeExpr,
+ VectorType::VectorKind VecKind) {
+ ID.AddPointer(ElementType.getAsOpaquePtr());
+ ID.AddInteger(VecKind);
+ SizeExpr->Profile(ID, Context, true);
+}
+
DependentSizedExtVectorType::DependentSizedExtVectorType(const
ASTContext &Context,
QualType ElementType,
- QualType can,
- Expr *SizeExpr,
+ QualType can,
+ Expr *SizeExpr,
SourceLocation loc)
: Type(DependentSizedExtVector, can, /*Dependent=*/true,
/*InstantiationDependent=*/true,
@@ -217,7 +249,7 @@ VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
: Type(tc, canonType, vecType->isDependentType(),
vecType->isInstantiationDependentType(),
vecType->isVariablyModifiedType(),
- vecType->containsUnexpandedParameterPack()),
+ vecType->containsUnexpandedParameterPack()),
ElementType(vecType) {
VectorTypeBits.VecKind = vecKind;
VectorTypeBits.NumElements = nElements;
@@ -228,7 +260,7 @@ VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
/// This method should never be used when type qualifiers are meaningful.
const Type *Type::getArrayElementTypeNoTypeQual() const {
// If this is directly an array type, return it.
- if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
+ if (const auto *ATy = dyn_cast<ArrayType>(this))
return ATy->getElementType().getTypePtr();
// If the canonical form of this type isn't the right kind, reject it.
@@ -264,7 +296,7 @@ QualType Type::getLocallyUnqualifiedSingleStepDesugaredType() const {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *ty = cast<Class##Type>(this); \
+ const auto *ty = cast<Class##Type>(this); \
if (!ty->isSugared()) return QualType(ty, 0); \
return ty->desugar(); \
}
@@ -283,7 +315,7 @@ SplitQualType QualType::getSplitDesugaredType(QualType T) {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ const auto *Ty = cast<Class##Type>(CurTy); \
if (!Ty->isSugared()) \
return SplitQualType(Ty, Qs); \
Cur = Ty->desugar(); \
@@ -312,7 +344,7 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *ty = cast<Class##Type>(split.Ty); \
+ const auto *ty = cast<Class##Type>(split.Ty); \
if (!ty->isSugared()) goto done; \
next = ty->desugar(); \
break; \
@@ -335,23 +367,23 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) {
QualType QualType::IgnoreParens(QualType T) {
// FIXME: this seems inherently un-qualifiers-safe.
- while (const ParenType *PT = T->getAs<ParenType>())
+ while (const auto *PT = T->getAs<ParenType>())
T = PT->getInnerType();
return T;
}
-/// \brief This will check for a T (which should be a Type which can act as
+/// This will check for a T (which should be a Type which can act as
/// sugar, such as a TypedefType) by removing any existing sugar until it
/// reaches a T or a non-sugared type.
template<typename T> static const T *getAsSugar(const Type *Cur) {
while (true) {
- if (const T *Sugar = dyn_cast<T>(Cur))
+ if (const auto *Sugar = dyn_cast<T>(Cur))
return Sugar;
switch (Cur->getTypeClass()) {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *Ty = cast<Class##Type>(Cur); \
+ const auto *Ty = cast<Class##Type>(Cur); \
if (!Ty->isSugared()) return 0; \
Cur = Ty->desugar().getTypePtr(); \
break; \
@@ -384,7 +416,7 @@ const Type *Type::getUnqualifiedDesugaredType() const {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Class: { \
- const Class##Type *Ty = cast<Class##Type>(Cur); \
+ const auto *Ty = cast<Class##Type>(Cur); \
if (!Ty->isSugared()) return Cur; \
Cur = Ty->desugar().getTypePtr(); \
break; \
@@ -395,28 +427,31 @@ const Type *Type::getUnqualifiedDesugaredType() const {
}
bool Type::isClassType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isClass();
return false;
}
bool Type::isStructureType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isStruct();
return false;
}
+
bool Type::isObjCBoxableRecordType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->hasAttr<ObjCBoxableAttr>();
return false;
}
+
bool Type::isInterfaceType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isInterface();
return false;
}
+
bool Type::isStructureOrClassType() const {
- if (const RecordType *RT = getAs<RecordType>()) {
+ if (const auto *RT = getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
return RD->isStruct() || RD->isClass() || RD->isInterface();
}
@@ -424,19 +459,19 @@ bool Type::isStructureOrClassType() const {
}
bool Type::isVoidPointerType() const {
- if (const PointerType *PT = getAs<PointerType>())
+ if (const auto *PT = getAs<PointerType>())
return PT->getPointeeType()->isVoidType();
return false;
}
bool Type::isUnionType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isUnion();
return false;
}
bool Type::isComplexType() const {
- if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+ if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
}
@@ -446,38 +481,44 @@ bool Type::isComplexIntegerType() const {
return getAsComplexIntegerType();
}
+bool Type::isScopedEnumeralType() const {
+ if (const auto *ET = getAs<EnumType>())
+ return ET->getDecl()->isScoped();
+ return false;
+}
+
const ComplexType *Type::getAsComplexIntegerType() const {
- if (const ComplexType *Complex = getAs<ComplexType>())
+ if (const auto *Complex = getAs<ComplexType>())
if (Complex->getElementType()->isIntegerType())
return Complex;
return nullptr;
}
QualType Type::getPointeeType() const {
- if (const PointerType *PT = getAs<PointerType>())
+ if (const auto *PT = getAs<PointerType>())
return PT->getPointeeType();
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->getPointeeType();
- if (const BlockPointerType *BPT = getAs<BlockPointerType>())
+ if (const auto *BPT = getAs<BlockPointerType>())
return BPT->getPointeeType();
- if (const ReferenceType *RT = getAs<ReferenceType>())
+ if (const auto *RT = getAs<ReferenceType>())
return RT->getPointeeType();
- if (const MemberPointerType *MPT = getAs<MemberPointerType>())
+ if (const auto *MPT = getAs<MemberPointerType>())
return MPT->getPointeeType();
- if (const DecayedType *DT = getAs<DecayedType>())
+ if (const auto *DT = getAs<DecayedType>())
return DT->getPointeeType();
- return QualType();
+ return {};
}
const RecordType *Type::getAsStructureType() const {
// If this is directly a structure type, return it.
- if (const RecordType *RT = dyn_cast<RecordType>(this)) {
+ if (const auto *RT = dyn_cast<RecordType>(this)) {
if (RT->getDecl()->isStruct())
return RT;
}
// If the canonical form of this type isn't the right kind, reject it.
- if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
+ if (const auto *RT = dyn_cast<RecordType>(CanonicalType)) {
if (!RT->getDecl()->isStruct())
return nullptr;
@@ -490,13 +531,13 @@ const RecordType *Type::getAsStructureType() const {
const RecordType *Type::getAsUnionType() const {
// If this is directly a union type, return it.
- if (const RecordType *RT = dyn_cast<RecordType>(this)) {
+ if (const auto *RT = dyn_cast<RecordType>(this)) {
if (RT->getDecl()->isUnion())
return RT;
}
// If the canonical form of this type isn't the right kind, reject it.
- if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
+ if (const auto *RT = dyn_cast<RecordType>(CanonicalType)) {
if (!RT->getDecl()->isUnion())
return nullptr;
@@ -512,7 +553,7 @@ bool Type::isObjCIdOrObjectKindOfType(const ASTContext &ctx,
const ObjCObjectType *&bound) const {
bound = nullptr;
- const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>();
+ const auto *OPT = getAs<ObjCObjectPointerType>();
if (!OPT)
return false;
@@ -535,7 +576,7 @@ bool Type::isObjCIdOrObjectKindOfType(const ASTContext &ctx,
}
bool Type::isObjCClassOrClassKindOfType() const {
- const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>();
+ const auto *OPT = getAs<ObjCObjectPointerType>();
if (!OPT)
return false;
@@ -560,7 +601,7 @@ bool Type::isObjCClassOrClassKindOfType() const {
bool Type::isObjCInertUnsafeUnretainedType() const {
const Type *cur = this;
while (true) {
- if (auto attributed = dyn_cast<AttributedType>(cur)) {
+ if (const auto attributed = dyn_cast<AttributedType>(cur)) {
if (attributed->getAttrKind() ==
AttributedType::attr_objc_inert_unsafe_unretained)
return true;
@@ -588,9 +629,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf)
- : Type(ObjCObject, Canonical, Base->isDependentType(),
- Base->isInstantiationDependentType(),
- Base->isVariablyModifiedType(),
+ : Type(ObjCObject, Canonical, Base->isDependentType(),
+ Base->isInstantiationDependentType(),
+ Base->isVariablyModifiedType(),
Base->containsUnexpandedParameterPack()),
BaseType(Base) {
ObjCObjectTypeBits.IsKindOf = isKindOf;
@@ -616,13 +657,13 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
initialize(protocols);
}
-bool ObjCObjectType::isSpecialized() const {
+bool ObjCObjectType::isSpecialized() const {
// If we have type arguments written here, the type is specialized.
if (ObjCObjectTypeBits.NumTypeArgs > 0)
return true;
// Otherwise, check whether the base type is specialized.
- if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ if (const auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
return false;
@@ -640,7 +681,7 @@ ArrayRef<QualType> ObjCObjectType::getTypeArgs() const {
return getTypeArgsAsWritten();
// Look at the base type, which might have type arguments.
- if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ if (const auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
return {};
@@ -657,7 +698,7 @@ bool ObjCObjectType::isKindOfType() const {
return true;
// Look at the base type, which might have type arguments.
- if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ if (const auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
return false;
@@ -677,10 +718,8 @@ QualType ObjCObjectType::stripObjCKindOfTypeAndQuals(
// Recursively strip __kindof.
SplitQualType splitBaseType = getBaseType().split();
QualType baseType(splitBaseType.Ty, 0);
- if (const ObjCObjectType *baseObj
- = splitBaseType.Ty->getAs<ObjCObjectType>()) {
+ if (const auto *baseObj = splitBaseType.Ty->getAs<ObjCObjectType>())
baseType = baseObj->stripObjCKindOfTypeAndQuals(ctx);
- }
return ctx.getObjCObjectType(ctx.getQualifiedType(baseType,
splitBaseType.Quals),
@@ -705,7 +744,7 @@ namespace {
/// Visitor used by simpleTransform() to perform the transformation.
template<typename F>
-struct SimpleTransformVisitor
+struct SimpleTransformVisitor
: public TypeVisitor<SimpleTransformVisitor<F>, QualType> {
ASTContext &Ctx;
F &&TheFunc;
@@ -730,10 +769,10 @@ public:
TRIVIAL_TYPE_CLASS(Builtin)
- QualType VisitComplexType(const ComplexType *T) {
+ QualType VisitComplexType(const ComplexType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -744,7 +783,7 @@ public:
QualType VisitPointerType(const PointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
@@ -755,7 +794,7 @@ public:
QualType VisitBlockPointerType(const BlockPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
@@ -766,9 +805,9 @@ public:
QualType VisitLValueReferenceType(const LValueReferenceType *T) {
QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
if (pointeeType.isNull())
- return QualType();
+ return {};
- if (pointeeType.getAsOpaquePtr()
+ if (pointeeType.getAsOpaquePtr()
== T->getPointeeTypeAsWritten().getAsOpaquePtr())
return QualType(T, 0);
@@ -778,9 +817,9 @@ public:
QualType VisitRValueReferenceType(const RValueReferenceType *T) {
QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
if (pointeeType.isNull())
- return QualType();
+ return {};
- if (pointeeType.getAsOpaquePtr()
+ if (pointeeType.getAsOpaquePtr()
== T->getPointeeTypeAsWritten().getAsOpaquePtr())
return QualType(T, 0);
@@ -790,18 +829,18 @@ public:
QualType VisitMemberPointerType(const MemberPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getMemberPointerType(pointeeType, T->getClass());
+ return Ctx.getMemberPointerType(pointeeType, T->getClass());
}
QualType VisitConstantArrayType(const ConstantArrayType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -814,7 +853,7 @@ public:
QualType VisitVariableArrayType(const VariableArrayType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -828,7 +867,7 @@ public:
QualType VisitIncompleteArrayType(const IncompleteArrayType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -837,22 +876,22 @@ public:
T->getIndexTypeCVRQualifiers());
}
- QualType VisitVectorType(const VectorType *T) {
+ QualType VisitVectorType(const VectorType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getVectorType(elementType, T->getNumElements(),
+ return Ctx.getVectorType(elementType, T->getNumElements(),
T->getVectorKind());
}
- QualType VisitExtVectorType(const ExtVectorType *T) {
+ QualType VisitExtVectorType(const ExtVectorType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -860,10 +899,10 @@ public:
return Ctx.getExtVectorType(elementType, T->getNumElements());
}
- QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
+ QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
QualType returnType = recurse(T->getReturnType());
if (returnType.isNull())
- return QualType();
+ return {};
if (returnType.getAsOpaquePtr() == T->getReturnType().getAsOpaquePtr())
return QualType(T, 0);
@@ -871,10 +910,10 @@ public:
return Ctx.getFunctionNoProtoType(returnType, T->getExtInfo());
}
- QualType VisitFunctionProtoType(const FunctionProtoType *T) {
+ QualType VisitFunctionProtoType(const FunctionProtoType *T) {
QualType returnType = recurse(T->getReturnType());
if (returnType.isNull())
- return QualType();
+ return {};
// Transform parameter types.
SmallVector<QualType, 4> paramTypes;
@@ -882,7 +921,7 @@ public:
for (auto paramType : T->getParamTypes()) {
QualType newParamType = recurse(paramType);
if (newParamType.isNull())
- return QualType();
+ return {};
if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr())
paramChanged = true;
@@ -898,10 +937,9 @@ public:
for (auto exceptionType : info.ExceptionSpec.Exceptions) {
QualType newExceptionType = recurse(exceptionType);
if (newExceptionType.isNull())
- return QualType();
-
- if (newExceptionType.getAsOpaquePtr()
- != exceptionType.getAsOpaquePtr())
+ return {};
+
+ if (newExceptionType.getAsOpaquePtr() != exceptionType.getAsOpaquePtr())
exceptionChanged = true;
exceptionTypes.push_back(newExceptionType);
@@ -920,10 +958,10 @@ public:
return Ctx.getFunctionType(returnType, paramTypes, info);
}
- QualType VisitParenType(const ParenType *T) {
+ QualType VisitParenType(const ParenType *T) {
QualType innerType = recurse(T->getInnerType());
if (innerType.isNull())
- return QualType();
+ return {};
if (innerType.getAsOpaquePtr() == T->getInnerType().getAsOpaquePtr())
return QualType(T, 0);
@@ -934,29 +972,29 @@ public:
TRIVIAL_TYPE_CLASS(Typedef)
TRIVIAL_TYPE_CLASS(ObjCTypeParam)
- QualType VisitAdjustedType(const AdjustedType *T) {
+ QualType VisitAdjustedType(const AdjustedType *T) {
QualType originalType = recurse(T->getOriginalType());
if (originalType.isNull())
- return QualType();
+ return {};
QualType adjustedType = recurse(T->getAdjustedType());
if (adjustedType.isNull())
- return QualType();
+ return {};
- if (originalType.getAsOpaquePtr()
+ if (originalType.getAsOpaquePtr()
== T->getOriginalType().getAsOpaquePtr() &&
adjustedType.getAsOpaquePtr() == T->getAdjustedType().getAsOpaquePtr())
return QualType(T, 0);
return Ctx.getAdjustedType(originalType, adjustedType);
}
-
- QualType VisitDecayedType(const DecayedType *T) {
+
+ QualType VisitDecayedType(const DecayedType *T) {
QualType originalType = recurse(T->getOriginalType());
if (originalType.isNull())
- return QualType();
+ return {};
- if (originalType.getAsOpaquePtr()
+ if (originalType.getAsOpaquePtr()
== T->getOriginalType().getAsOpaquePtr())
return QualType(T, 0);
@@ -973,31 +1011,31 @@ public:
// FIXME: Non-trivial to implement, but important for C++
TRIVIAL_TYPE_CLASS(Elaborated)
- QualType VisitAttributedType(const AttributedType *T) {
+ QualType VisitAttributedType(const AttributedType *T) {
QualType modifiedType = recurse(T->getModifiedType());
if (modifiedType.isNull())
- return QualType();
+ return {};
QualType equivalentType = recurse(T->getEquivalentType());
if (equivalentType.isNull())
- return QualType();
+ return {};
- if (modifiedType.getAsOpaquePtr()
+ if (modifiedType.getAsOpaquePtr()
== T->getModifiedType().getAsOpaquePtr() &&
- equivalentType.getAsOpaquePtr()
+ equivalentType.getAsOpaquePtr()
== T->getEquivalentType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getAttributedType(T->getAttrKind(), modifiedType,
+ return Ctx.getAttributedType(T->getAttrKind(), modifiedType,
equivalentType);
}
QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
QualType replacementType = recurse(T->getReplacementType());
if (replacementType.isNull())
- return QualType();
+ return {};
- if (replacementType.getAsOpaquePtr()
+ if (replacementType.getAsOpaquePtr()
== T->getReplacementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -1014,9 +1052,9 @@ public:
QualType deducedType = recurse(T->getDeducedType());
if (deducedType.isNull())
- return QualType();
+ return {};
- if (deducedType.getAsOpaquePtr()
+ if (deducedType.getAsOpaquePtr()
== T->getDeducedType().getAsOpaquePtr())
return QualType(T, 0);
@@ -1030,7 +1068,7 @@ public:
QualType VisitObjCObjectType(const ObjCObjectType *T) {
QualType baseType = recurse(T->getBaseType());
if (baseType.isNull())
- return QualType();
+ return {};
// Transform type arguments.
bool typeArgChanged = false;
@@ -1038,7 +1076,7 @@ public:
for (auto typeArg : T->getTypeArgsAsWritten()) {
QualType newTypeArg = recurse(typeArg);
if (newTypeArg.isNull())
- return QualType();
+ return {};
if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr())
typeArgChanged = true;
@@ -1050,7 +1088,7 @@ public:
!typeArgChanged)
return QualType(T, 0);
- return Ctx.getObjCObjectType(baseType, typeArgs,
+ return Ctx.getObjCObjectType(baseType, typeArgs,
llvm::makeArrayRef(T->qual_begin(),
T->getNumProtocols()),
T->isKindOfTypeAsWritten());
@@ -1061,9 +1099,9 @@ public:
QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
- if (pointeeType.getAsOpaquePtr()
+ if (pointeeType.getAsOpaquePtr()
== T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
@@ -1073,9 +1111,9 @@ public:
QualType VisitAtomicType(const AtomicType *T) {
QualType valueType = recurse(T->getValueType());
if (valueType.isNull())
- return QualType();
+ return {};
- if (valueType.getAsOpaquePtr()
+ if (valueType.getAsOpaquePtr()
== T->getValueType().getAsOpaquePtr())
return QualType(T, 0);
@@ -1123,57 +1161,56 @@ QualType QualType::substObjCTypeArgs(
// Replace an Objective-C type parameter reference with the corresponding
// type argument.
if (const auto *OTPTy = dyn_cast<ObjCTypeParamType>(splitType.Ty)) {
- if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(OTPTy->getDecl())) {
- // If we have type arguments, use them.
- if (!typeArgs.empty()) {
- QualType argType = typeArgs[typeParam->getIndex()];
- if (OTPTy->qual_empty())
- return ctx.getQualifiedType(argType, splitType.Quals);
-
- // Apply protocol lists if exists.
- bool hasError;
- SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
- protocolsVec.append(OTPTy->qual_begin(),
- OTPTy->qual_end());
- ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec;
- QualType resultTy = ctx.applyObjCProtocolQualifiers(argType,
- protocolsToApply, hasError, true/*allowOnPointerType*/);
-
- return ctx.getQualifiedType(resultTy, splitType.Quals);
- }
+ ObjCTypeParamDecl *typeParam = OTPTy->getDecl();
+ // If we have type arguments, use them.
+ if (!typeArgs.empty()) {
+ QualType argType = typeArgs[typeParam->getIndex()];
+ if (OTPTy->qual_empty())
+ return ctx.getQualifiedType(argType, splitType.Quals);
+
+ // Apply protocol lists if exists.
+ bool hasError;
+ SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
+ protocolsVec.append(OTPTy->qual_begin(),
+ OTPTy->qual_end());
+ ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec;
+ QualType resultTy = ctx.applyObjCProtocolQualifiers(argType,
+ protocolsToApply, hasError, true/*allowOnPointerType*/);
+
+ return ctx.getQualifiedType(resultTy, splitType.Quals);
+ }
- switch (context) {
- case ObjCSubstitutionContext::Ordinary:
- case ObjCSubstitutionContext::Parameter:
- case ObjCSubstitutionContext::Superclass:
- // Substitute the bound.
+ switch (context) {
+ case ObjCSubstitutionContext::Ordinary:
+ case ObjCSubstitutionContext::Parameter:
+ case ObjCSubstitutionContext::Superclass:
+ // Substitute the bound.
+ return ctx.getQualifiedType(typeParam->getUnderlyingType(),
+ splitType.Quals);
+
+ case ObjCSubstitutionContext::Result:
+ case ObjCSubstitutionContext::Property: {
+ // Substitute the __kindof form of the underlying type.
+ const auto *objPtr = typeParam->getUnderlyingType()
+ ->castAs<ObjCObjectPointerType>();
+
+ // __kindof types, id, and Class don't need an additional
+ // __kindof.
+ if (objPtr->isKindOfType() || objPtr->isObjCIdOrClassType())
return ctx.getQualifiedType(typeParam->getUnderlyingType(),
splitType.Quals);
- case ObjCSubstitutionContext::Result:
- case ObjCSubstitutionContext::Property: {
- // Substitute the __kindof form of the underlying type.
- const auto *objPtr = typeParam->getUnderlyingType()
- ->castAs<ObjCObjectPointerType>();
-
- // __kindof types, id, and Class don't need an additional
- // __kindof.
- if (objPtr->isKindOfType() || objPtr->isObjCIdOrClassType())
- return ctx.getQualifiedType(typeParam->getUnderlyingType(),
- splitType.Quals);
-
- // Add __kindof.
- const auto *obj = objPtr->getObjectType();
- QualType resultTy = ctx.getObjCObjectType(obj->getBaseType(),
- obj->getTypeArgsAsWritten(),
- obj->getProtocols(),
- /*isKindOf=*/true);
-
- // Rebuild object pointer type.
- resultTy = ctx.getObjCObjectPointerType(resultTy);
- return ctx.getQualifiedType(resultTy, splitType.Quals);
- }
- }
+ // Add __kindof.
+ const auto *obj = objPtr->getObjectType();
+ QualType resultTy = ctx.getObjCObjectType(obj->getBaseType(),
+ obj->getTypeArgsAsWritten(),
+ obj->getProtocols(),
+ /*isKindOf=*/true);
+
+ // Rebuild object pointer type.
+ resultTy = ctx.getObjCObjectPointerType(resultTy);
+ return ctx.getQualifiedType(resultTy, splitType.Quals);
+ }
}
}
@@ -1185,7 +1222,7 @@ QualType QualType::substObjCTypeArgs(
typeArgs,
ObjCSubstitutionContext::Result);
if (returnType.isNull())
- return QualType();
+ return {};
// Handle non-prototyped functions, which only substitute into the result
// type.
@@ -1210,7 +1247,7 @@ QualType QualType::substObjCTypeArgs(
typeArgs,
ObjCSubstitutionContext::Parameter);
if (newParamType.isNull())
- return QualType();
+ return {};
if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr())
paramChanged = true;
@@ -1229,7 +1266,7 @@ QualType QualType::substObjCTypeArgs(
typeArgs,
ObjCSubstitutionContext::Ordinary);
if (newExceptionType.isNull())
- return QualType();
+ return {};
if (newExceptionType.getAsOpaquePtr()
!= exceptionType.getAsOpaquePtr())
@@ -1263,7 +1300,7 @@ QualType QualType::substObjCTypeArgs(
ctx, typeArgs,
ObjCSubstitutionContext::Ordinary);
if (newTypeArg.isNull())
- return QualType();
+ return {};
if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr()) {
// If we're substituting based on an unspecialized context type,
@@ -1336,7 +1373,7 @@ QualType QualType::stripObjCKindOfType(const ASTContext &constCtx) const {
}
QualType QualType::getAtomicUnqualifiedType() const {
- if (auto AT = getTypePtr()->getAs<AtomicType>())
+ if (const auto AT = getTypePtr()->getAs<AtomicType>())
return AT->getValueType().getUnqualifiedType();
return getUnqualifiedType();
}
@@ -1344,12 +1381,12 @@ QualType QualType::getAtomicUnqualifiedType() const {
Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
const DeclContext *dc) const {
// Look through method scopes.
- if (auto method = dyn_cast<ObjCMethodDecl>(dc))
+ if (const auto method = dyn_cast<ObjCMethodDecl>(dc))
dc = method->getDeclContext();
// Find the class or category in which the type we're substituting
// was declared.
- const ObjCInterfaceDecl *dcClassDecl = dyn_cast<ObjCInterfaceDecl>(dc);
+ const auto *dcClassDecl = dyn_cast<ObjCInterfaceDecl>(dc);
const ObjCCategoryDecl *dcCategoryDecl = nullptr;
ObjCTypeParamList *dcTypeParams = nullptr;
if (dcClassDecl) {
@@ -1526,7 +1563,7 @@ const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCObjectType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to
// return and these cannot be Address-space qualified.
- if (const ObjCObjectType *T = getAs<ObjCObjectType>())
+ if (const auto *T = getAs<ObjCObjectType>())
if (T->getNumProtocols() && T->getInterface())
return T;
return nullptr;
@@ -1539,7 +1576,7 @@ bool Type::isObjCQualifiedInterfaceType() const {
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (const auto *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->isObjCQualifiedIdType())
return OPT;
}
@@ -1549,7 +1586,7 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const {
// There is no sugar for ObjCQualifiedClassType's, just return the canonical
// type pointer if it is the right class.
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (const auto *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->isObjCQualifiedClassType())
return OPT;
}
@@ -1557,7 +1594,7 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const {
}
const ObjCObjectType *Type::getAsObjCInterfaceType() const {
- if (const ObjCObjectType *OT = getAs<ObjCObjectType>()) {
+ if (const auto *OT = getAs<ObjCObjectType>()) {
if (OT->getInterface())
return OT;
}
@@ -1565,7 +1602,7 @@ const ObjCObjectType *Type::getAsObjCInterfaceType() const {
}
const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (const auto *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->getInterfaceType())
return OPT;
}
@@ -1574,14 +1611,14 @@ const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const {
QualType PointeeType;
- if (const PointerType *PT = getAs<PointerType>())
+ if (const auto *PT = getAs<PointerType>())
PointeeType = PT->getPointeeType();
- else if (const ReferenceType *RT = getAs<ReferenceType>())
+ else if (const auto *RT = getAs<ReferenceType>())
PointeeType = RT->getPointeeType();
else
return nullptr;
- if (const RecordType *RT = PointeeType->getAs<RecordType>())
+ if (const auto *RT = PointeeType->getAs<RecordType>())
return dyn_cast<CXXRecordDecl>(RT->getDecl());
return nullptr;
@@ -1591,9 +1628,13 @@ CXXRecordDecl *Type::getAsCXXRecordDecl() const {
return dyn_cast_or_null<CXXRecordDecl>(getAsTagDecl());
}
+RecordDecl *Type::getAsRecordDecl() const {
+ return dyn_cast_or_null<RecordDecl>(getAsTagDecl());
+}
+
TagDecl *Type::getAsTagDecl() const {
if (const auto *TT = getAs<TagType>())
- return cast<TagDecl>(TT->getDecl());
+ return TT->getDecl();
if (const auto *Injected = getAs<InjectedClassNameType>())
return Injected->getDecl();
@@ -1694,18 +1735,18 @@ bool Type::hasAutoForTrailingReturnType() const {
}
bool Type::hasIntegerRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
else
return isIntegerType();
}
-/// \brief Determine whether this type is an integral type.
+/// Determine whether this type is an integral type.
///
-/// This routine determines whether the given type is an integral type per
+/// This routine determines whether the given type is an integral type per
/// C++ [basic.fundamental]p7. Although the C standard does not define the
/// term "integral type", it has a similar term "integer type", and in C++
-/// the two terms are equivalent. However, C's "integer type" includes
+/// the two terms are equivalent. However, C's "integer type" includes
/// enumeration types, while C++'s "integer type" does not. The \c ASTContext
/// parameter is used to determine whether we should be following the C or
/// C++ rules when determining whether this type is an integral/integer type.
@@ -1714,26 +1755,26 @@ bool Type::hasIntegerRepresentation() const {
/// type", use this routine.
///
/// For cases where C permits "an integer type" and C++ permits "an integral
-/// or enumeration type", use \c isIntegralOrEnumerationType() instead.
+/// or enumeration type", use \c isIntegralOrEnumerationType() instead.
///
/// \param Ctx The context in which this type occurs.
///
/// \returns true if the type is considered an integral type, false otherwise.
bool Type::isIntegralType(const ASTContext &Ctx) const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
// Complete enum types are integral in C.
if (!Ctx.getLangOpts().CPlusPlus)
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete();
return false;
}
bool Type::isIntegralOrUnscopedEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
@@ -1741,14 +1782,14 @@ bool Type::isIntegralOrUnscopedEnumerationType() const {
// enumeration type in the sense required here.
// C++0x: However, if the underlying type of the enum is fixed, it is
// considered complete.
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return false;
}
bool Type::isCharType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char_U ||
BT->getKind() == BuiltinType::UChar ||
BT->getKind() == BuiltinType::Char_S ||
@@ -1757,34 +1798,41 @@ bool Type::isCharType() const {
}
bool Type::isWideCharType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::WChar_S ||
BT->getKind() == BuiltinType::WChar_U;
return false;
}
-bool Type::isChar16Type() const {
+bool Type::isChar8Type() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Char8;
+ return false;
+}
+
+bool Type::isChar16Type() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char16;
return false;
}
bool Type::isChar32Type() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char32;
return false;
}
-/// \brief Determine whether this type is any of the built-in character
+/// Determine whether this type is any of the built-in character
/// types.
bool Type::isAnyCharacterType() const {
- const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
+ const auto *BT = dyn_cast<BuiltinType>(CanonicalType);
if (!BT) return false;
switch (BT->getKind()) {
default: return false;
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::WChar_U:
+ case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Char_S:
@@ -1798,7 +1846,7 @@ bool Type::isAnyCharacterType() const {
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
/// an enum decl which has a signed representation
bool Type::isSignedIntegerType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::Int128;
}
@@ -1814,21 +1862,21 @@ bool Type::isSignedIntegerType() const {
}
bool Type::isSignedIntegerOrEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::Int128;
}
-
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
if (ET->getDecl()->isComplete())
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
}
-
+
return false;
}
bool Type::hasSignedIntegerRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerOrEnumerationType();
else
return isSignedIntegerOrEnumerationType();
@@ -1838,12 +1886,12 @@ bool Type::hasSignedIntegerRepresentation() const {
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
/// decl which has an unsigned representation
bool Type::isUnsignedIntegerType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::UInt128;
}
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
// Incomplete enum types are not treated as integer types.
// FIXME: In C++, enum types are never integer types.
if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped())
@@ -1854,62 +1902,62 @@ bool Type::isUnsignedIntegerType() const {
}
bool Type::isUnsignedIntegerOrEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::UInt128;
}
-
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
if (ET->getDecl()->isComplete())
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
}
-
+
return false;
}
bool Type::hasUnsignedIntegerRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerOrEnumerationType();
else
return isUnsignedIntegerOrEnumerationType();
}
bool Type::isFloatingType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Half &&
BT->getKind() <= BuiltinType::Float128;
- if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+ if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
}
bool Type::hasFloatingRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isFloatingType();
else
return isFloatingType();
}
bool Type::isRealFloatingType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->isFloatingPoint();
return false;
}
bool Type::isRealType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Float128;
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return false;
}
bool Type::isArithmeticType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Float128;
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
//
@@ -1924,7 +1972,7 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
assert(isScalarType());
const Type *T = CanonicalType.getTypePtr();
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(T)) {
if (BT->getKind() == BuiltinType::Bool) return STK_Bool;
if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer;
if (BT->isInteger()) return STK_Integral;
@@ -1941,7 +1989,7 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
} else if (isa<EnumType>(T)) {
assert(cast<EnumType>(T)->getDecl()->isComplete());
return STK_Integral;
- } else if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
+ } else if (const auto *CT = dyn_cast<ComplexType>(T)) {
if (CT->getElementType()->isRealFloatingType())
return STK_FloatingComplex;
return STK_IntegralComplex;
@@ -1950,7 +1998,7 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
llvm_unreachable("unknown scalar type");
}
-/// \brief Determines whether the type is a C++ aggregate type or C
+/// Determines whether the type is a C++ aggregate type or C
/// aggregate or union type.
///
/// An aggregate type is an array or a class type (struct, union, or
@@ -1960,8 +2008,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
/// subsumes the notion of C aggregates (C99 6.2.5p21) because it also
/// includes union types.
bool Type::isAggregateType() const {
- if (const RecordType *Record = dyn_cast<RecordType>(CanonicalType)) {
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(Record->getDecl()))
+ if (const auto *Record = dyn_cast<RecordType>(CanonicalType)) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(Record->getDecl()))
return ClassDecl->isAggregate();
return true;
@@ -1997,12 +2045,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
EnumDecl *EnumD = cast<EnumType>(CanonicalType)->getDecl();
if (Def)
*Def = EnumD;
-
- // An enumeration with fixed underlying type is complete (C++0x 7.2p3).
- if (EnumD->isFixed())
- return false;
-
- return !EnumD->isCompleteDefinition();
+ return !EnumD->isComplete();
}
case Record: {
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
@@ -2038,7 +2081,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
return false;
// The inheritance attribute might only be present on the most recent
// CXXRecordDecl, use that one.
- RD = RD->getMostRecentDecl();
+ RD = RD->getMostRecentNonInjectedDecl();
// Nothing interesting to do if the inheritance attribute is already set.
if (RD->hasAttr<MSInheritanceAttr>())
return false;
@@ -2072,16 +2115,16 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
// are PODs according to the standard.
if (isNull())
return false;
-
+
if ((*this)->isIncompleteArrayType())
return Context.getBaseElementType(*this).isCXX98PODType(Context);
-
+
if ((*this)->isIncompleteType())
return false;
if (hasNonTrivialObjCLifetime())
return false;
-
+
QualType CanonicalType = getTypePtr()->CanonicalType;
switch (CanonicalType->getTypeClass()) {
// Everything not explicitly mentioned is not POD.
@@ -2090,7 +2133,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
case Type::ConstantArray:
// IncompleteArray is handled above.
return Context.getBaseElementType(*this).isCXX98PODType(Context);
-
+
case Type::ObjCObjectPointer:
case Type::BlockPointer:
case Type::Builtin:
@@ -2105,8 +2148,8 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
return true;
case Type::Record:
- if (CXXRecordDecl *ClassDecl
- = dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
return ClassDecl->isPOD();
// C struct/union is POD.
@@ -2120,33 +2163,32 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
// are PODs according to the standard.
if (isNull())
return false;
-
+
if ((*this)->isArrayType())
return Context.getBaseElementType(*this).isTrivialType(Context);
-
+
// Return false for incomplete types after skipping any incomplete array
// types which are expressly allowed by the standard and thus our API.
if ((*this)->isIncompleteType())
return false;
-
+
if (hasNonTrivialObjCLifetime())
return false;
-
+
QualType CanonicalType = getTypePtr()->CanonicalType;
if (CanonicalType->isDependentType())
return false;
-
+
// C++0x [basic.types]p9:
// Scalar types, trivial class types, arrays of such types, and
// cv-qualified versions of these types are collectively called trivial
// types.
-
+
// As an extension, Clang treats vector types as Scalar types.
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
return true;
- if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *RT = CanonicalType->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p6:
// A trivial class is a class that has a default constructor,
// has no non-trivial default constructors, and is trivially
@@ -2155,10 +2197,10 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
!ClassDecl->hasNonTrivialDefaultConstructor() &&
ClassDecl->isTriviallyCopyable();
}
-
+
return true;
}
-
+
// No other types can match.
return false;
}
@@ -2183,14 +2225,13 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const {
// which are expressly allowed by the standard and thus our API.
if (CanonicalType->isIncompleteType())
return false;
-
+
// As an extension, Clang treats vector types as Scalar types.
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
return true;
- if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *RT = CanonicalType->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
if (!ClassDecl->isTriviallyCopyable()) return false;
}
@@ -2207,6 +2248,45 @@ bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const {
getObjCLifetime() != Qualifiers::OCL_Weak;
}
+QualType::PrimitiveDefaultInitializeKind
+QualType::isNonTrivialToPrimitiveDefaultInitialize() const {
+ if (const auto *RT =
+ getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize())
+ return PDIK_Struct;
+
+ switch (getQualifiers().getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
+ return PDIK_ARCStrong;
+ case Qualifiers::OCL_Weak:
+ return PDIK_ARCWeak;
+ default:
+ return PDIK_Trivial;
+ }
+}
+
+QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const {
+ if (const auto *RT =
+ getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (RT->getDecl()->isNonTrivialToPrimitiveCopy())
+ return PCK_Struct;
+
+ Qualifiers Qs = getQualifiers();
+ switch (Qs.getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
+ return PCK_ARCStrong;
+ case Qualifiers::OCL_Weak:
+ return PCK_ARCWeak;
+ default:
+ return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;
+ }
+}
+
+QualType::PrimitiveCopyKind
+QualType::isNonTrivialToPrimitiveDestructiveMove() const {
+ return isNonTrivialToPrimitiveCopy();
+}
+
bool Type::isLiteralType(const ASTContext &Ctx) const {
if (isDependentType())
return false;
@@ -2243,7 +2323,7 @@ bool Type::isLiteralType(const ASTContext &Ctx) const {
if (BaseTy->isReferenceType())
return true;
// -- a class type that has all of the following properties:
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+ if (const auto *RT = BaseTy->getAs<RecordType>()) {
// -- a trivial destructor,
// -- every constructor call and full-expression in the
// brace-or-equal-initializers for non-static data members (if any)
@@ -2254,15 +2334,14 @@ bool Type::isLiteralType(const ASTContext &Ctx) const {
// -- all non-static data members and base classes of literal types
//
// We resolve DR1361 by ignoring the second bullet.
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
return ClassDecl->isLiteral();
return true;
}
// We treat _Atomic T as a literal type if T is a literal type.
- if (const AtomicType *AT = BaseTy->getAs<AtomicType>())
+ if (const auto *AT = BaseTy->getAs<AtomicType>())
return AT->getValueType()->isLiteralType(Ctx);
// If this type hasn't been deduced yet, then conservatively assume that
@@ -2291,9 +2370,8 @@ bool Type::isStandardLayoutType() const {
// As an extension, Clang treats vector types as Scalar types.
if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *RT = BaseTy->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
if (!ClassDecl->isStandardLayout())
return false;
@@ -2331,9 +2409,8 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
// As an extension, Clang treats vector types as Scalar types.
if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *RT = BaseTy->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class [...]
if (!ClassDecl->isTrivial()) return false;
@@ -2361,8 +2438,8 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
}
bool Type::isAlignValT() const {
- if (auto *ET = getAs<EnumType>()) {
- auto *II = ET->getDecl()->getIdentifier();
+ if (const auto *ET = getAs<EnumType>()) {
+ IdentifierInfo *II = ET->getDecl()->getIdentifier();
if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace())
return true;
}
@@ -2370,8 +2447,8 @@ bool Type::isAlignValT() const {
}
bool Type::isStdByteType() const {
- if (auto *ET = getAs<EnumType>()) {
- auto *II = ET->getDecl()->getIdentifier();
+ if (const auto *ET = getAs<EnumType>()) {
+ IdentifierInfo *II = ET->getDecl()->getIdentifier();
if (II && II->isStr("byte") && ET->getDecl()->isInStdNamespace())
return true;
}
@@ -2379,7 +2456,7 @@ bool Type::isStdByteType() const {
}
bool Type::isPromotableIntegerType() const {
- if (const BuiltinType *BT = getAs<BuiltinType>())
+ if (const auto *BT = getAs<BuiltinType>())
switch (BT->getKind()) {
case BuiltinType::Bool:
case BuiltinType::Char_S:
@@ -2390,6 +2467,7 @@ bool Type::isPromotableIntegerType() const {
case BuiltinType::UShort:
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
+ case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
return true;
@@ -2399,14 +2477,14 @@ bool Type::isPromotableIntegerType() const {
// Enumerated types are promotable to their compatible integer types
// (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2).
- if (const EnumType *ET = getAs<EnumType>()){
+ if (const auto *ET = getAs<EnumType>()){
if (this->isDependentType() || ET->getDecl()->getPromotionType().isNull()
|| ET->getDecl()->isScoped())
return false;
-
+
return true;
}
-
+
return false;
}
@@ -2457,7 +2535,7 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
case TST_union: return TTK_Union;
case TST_enum: return TTK_Enum;
}
-
+
llvm_unreachable("Type specifier is not a tag type kind.");
}
@@ -2506,7 +2584,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
- case ETK_None: return "";
+ case ETK_None: return {};
case ETK_Typename: return "typename";
case ETK_Class: return "class";
case ETK_Struct: return "struct";
@@ -2554,12 +2632,12 @@ DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
bool Type::isElaboratedTypeSpecifier() const {
ElaboratedTypeKeyword Keyword;
- if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this))
+ if (const auto *Elab = dyn_cast<ElaboratedType>(this))
Keyword = Elab->getKeyword();
- else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this))
+ else if (const auto *DepName = dyn_cast<DependentNameType>(this))
Keyword = DepName->getKeyword();
- else if (const DependentTemplateSpecializationType *DepTST =
- dyn_cast<DependentTemplateSpecializationType>(this))
+ else if (const auto *DepTST =
+ dyn_cast<DependentTemplateSpecializationType>(this))
Keyword = DepTST->getKeyword();
else
return false;
@@ -2573,7 +2651,7 @@ const char *Type::getTypeClassName() const {
#define TYPE(Derived, Base) case Derived: return #Derived;
#include "clang/AST/TypeNodes.def"
}
-
+
llvm_unreachable("Invalid type class.");
}
@@ -2619,6 +2697,54 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "double";
case LongDouble:
return "long double";
+ case ShortAccum:
+ return "short _Accum";
+ case Accum:
+ return "_Accum";
+ case LongAccum:
+ return "long _Accum";
+ case UShortAccum:
+ return "unsigned short _Accum";
+ case UAccum:
+ return "unsigned _Accum";
+ case ULongAccum:
+ return "unsigned long _Accum";
+ case BuiltinType::ShortFract:
+ return "short _Fract";
+ case BuiltinType::Fract:
+ return "_Fract";
+ case BuiltinType::LongFract:
+ return "long _Fract";
+ case BuiltinType::UShortFract:
+ return "unsigned short _Fract";
+ case BuiltinType::UFract:
+ return "unsigned _Fract";
+ case BuiltinType::ULongFract:
+ return "unsigned long _Fract";
+ case BuiltinType::SatShortAccum:
+ return "_Sat short _Accum";
+ case BuiltinType::SatAccum:
+ return "_Sat _Accum";
+ case BuiltinType::SatLongAccum:
+ return "_Sat long _Accum";
+ case BuiltinType::SatUShortAccum:
+ return "_Sat unsigned short _Accum";
+ case BuiltinType::SatUAccum:
+ return "_Sat unsigned _Accum";
+ case BuiltinType::SatULongAccum:
+ return "_Sat unsigned long _Accum";
+ case BuiltinType::SatShortFract:
+ return "_Sat short _Fract";
+ case BuiltinType::SatFract:
+ return "_Sat _Fract";
+ case BuiltinType::SatLongFract:
+ return "_Sat long _Fract";
+ case BuiltinType::SatUShortFract:
+ return "_Sat unsigned short _Fract";
+ case BuiltinType::SatUFract:
+ return "_Sat unsigned _Fract";
+ case BuiltinType::SatULongFract:
+ return "_Sat unsigned long _Fract";
case Float16:
return "_Float16";
case Float128:
@@ -2626,6 +2752,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
case WChar_S:
case WChar_U:
return Policy.MSWChar ? "__wchar_t" : "wchar_t";
+ case Char8:
+ return "char8_t";
case Char16:
return "char16_t";
case Char32:
@@ -2674,18 +2802,18 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
}
QualType QualType::getNonLValueExprType(const ASTContext &Context) const {
- if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>())
+ if (const auto *RefType = getTypePtr()->getAs<ReferenceType>())
return RefType->getPointeeType();
-
+
// C++0x [basic.lval]:
- // Class prvalues can have cv-qualified types; non-class prvalues always
+ // Class prvalues can have cv-qualified types; non-class prvalues always
// have cv-unqualified types.
//
// See also C99 6.3.2.1p2.
if (!Context.getLangOpts().CPlusPlus ||
(!getTypePtr()->isDependentType() && !getTypePtr()->isRecordType()))
return getUnqualifiedType();
-
+
return *this;
}
@@ -2732,7 +2860,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
FunctionTypeBits.RefQualifier = epi.RefQualifier;
// Fill in the trailing argument array.
- QualType *argSlot = reinterpret_cast<QualType*>(this+1);
+ auto *argSlot = reinterpret_cast<QualType *>(this+1);
for (unsigned i = 0; i != NumParams; ++i) {
if (params[i]->isDependentType())
setDependent();
@@ -2761,24 +2889,25 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
exnSlot[I++] = ExceptionType;
}
- } else if (getExceptionSpecType() == EST_ComputedNoexcept) {
+ } else if (isComputedNoexcept(getExceptionSpecType())) {
+ assert(epi.ExceptionSpec.NoexceptExpr && "computed noexcept with no expr");
+ assert((getExceptionSpecType() == EST_DependentNoexcept) ==
+ epi.ExceptionSpec.NoexceptExpr->isValueDependent());
+
// Store the noexcept expression and context.
- Expr **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
+ auto **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
*noexSlot = epi.ExceptionSpec.NoexceptExpr;
- if (epi.ExceptionSpec.NoexceptExpr) {
- if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
- epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
- setInstantiationDependent();
+ if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
+ epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
+ setInstantiationDependent();
- if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
- setContainsUnexpandedParameterPack();
- }
+ if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
} else if (getExceptionSpecType() == EST_Uninstantiated) {
// Store the function decl from which we will resolve our
// exception specification.
- FunctionDecl **slot =
- reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
slot[0] = epi.ExceptionSpec.SourceDecl;
slot[1] = epi.ExceptionSpec.SourceTemplate;
// This exception specification doesn't make the type dependent, because
@@ -2786,8 +2915,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
} else if (getExceptionSpecType() == EST_Unevaluated) {
// Store the function decl from which we will resolve our
// exception specification.
- FunctionDecl **slot =
- reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
slot[0] = epi.ExceptionSpec.SourceDecl;
}
@@ -2795,7 +2923,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
// then it's a dependent type. This only happens in C++17 onwards.
if (isCanonicalUnqualified()) {
if (getExceptionSpecType() == EST_Dynamic ||
- getExceptionSpecType() == EST_ComputedNoexcept) {
+ getExceptionSpecType() == EST_DependentNoexcept) {
assert(hasDependentExceptionSpec() && "type should not be canonical");
setDependent();
}
@@ -2805,7 +2933,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
}
if (epi.ExtParameterInfos) {
- ExtParameterInfo *extParamInfos =
+ auto *extParamInfos =
const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer());
for (unsigned i = 0; i != NumParams; ++i)
extParamInfos[i] = epi.ExtParameterInfos[i];
@@ -2833,59 +2961,43 @@ bool FunctionProtoType::hasInstantiationDependentExceptionSpec() const {
return false;
}
-FunctionProtoType::NoexceptResult
-FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
- ExceptionSpecificationType est = getExceptionSpecType();
- if (est == EST_BasicNoexcept)
- return NR_Nothrow;
-
- if (est != EST_ComputedNoexcept)
- return NR_NoNoexcept;
-
- Expr *noexceptExpr = getNoexceptExpr();
- if (!noexceptExpr)
- return NR_BadNoexcept;
- if (noexceptExpr->isValueDependent())
- return NR_Dependent;
-
- llvm::APSInt value;
- bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, nullptr,
- /*evaluated*/false);
- (void)isICE;
- assert(isICE && "AST should not contain bad noexcept expressions.");
+CanThrowResult FunctionProtoType::canThrow() const {
+ switch (getExceptionSpecType()) {
+ case EST_Unparsed:
+ case EST_Unevaluated:
+ case EST_Uninstantiated:
+ llvm_unreachable("should not call this with unresolved exception specs");
- return value.getBoolValue() ? NR_Nothrow : NR_Throw;
-}
-
-CanThrowResult FunctionProtoType::canThrow(const ASTContext &Ctx) const {
- ExceptionSpecificationType EST = getExceptionSpecType();
- assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
- if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
+ case EST_DynamicNone:
+ case EST_BasicNoexcept:
+ case EST_NoexceptTrue:
return CT_Cannot;
- if (EST == EST_Dynamic) {
+ case EST_None:
+ case EST_MSAny:
+ case EST_NoexceptFalse:
+ return CT_Can;
+
+ case EST_Dynamic:
// A dynamic exception specification is throwing unless every exception
// type is an (unexpanded) pack expansion type.
for (unsigned I = 0, N = NumExceptions; I != N; ++I)
if (!getExceptionType(I)->getAs<PackExpansionType>())
return CT_Can;
return CT_Dependent;
- }
-
- if (EST != EST_ComputedNoexcept)
- return CT_Can;
- NoexceptResult NR = getNoexceptSpec(Ctx);
- if (NR == NR_Dependent)
+ case EST_DependentNoexcept:
return CT_Dependent;
- return NR == NR_Nothrow ? CT_Cannot : CT_Can;
+ }
+
+ llvm_unreachable("unexpected exception specification kind");
}
bool FunctionProtoType::isTemplateVariadic() const {
for (unsigned ArgIdx = getNumParams(); ArgIdx; --ArgIdx)
if (isa<PackExpansionType>(getParamType(ArgIdx - 1)))
return true;
-
+
return false;
}
@@ -2897,7 +3009,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
// Note that valid type pointers are never ambiguous with anything else.
//
// The encoding grammar begins:
- // type type* bool int bool
+ // type type* bool int bool
// If that final bool is true, then there is a section for the EH spec:
// bool type*
// This is followed by an optional "consumed argument" section of the
@@ -2905,7 +3017,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
// bool*
// Finally, we have the ext info and trailing return type flag:
// int bool
- //
+ //
// There is no ambiguity between the consumed arguments and an empty EH
// spec because of the leading 'bool' which unambiguously indicates
// whether the following bool is the EH spec or part of the arguments.
@@ -2928,8 +3040,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
if (epi.ExceptionSpec.Type == EST_Dynamic) {
for (QualType Ex : epi.ExceptionSpec.Exceptions)
ID.AddPointer(Ex.getAsOpaquePtr());
- } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&
- epi.ExceptionSpec.NoexceptExpr) {
+ } else if (isComputedNoexcept(epi.ExceptionSpec.Type)) {
epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, Canonical);
} else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||
epi.ExceptionSpec.Type == EST_Unevaluated) {
@@ -2967,7 +3078,7 @@ bool TypeOfExprType::isSugared() const {
QualType TypeOfExprType::desugar() const {
if (isSugared())
return getUnderlyingExpr()->getType();
-
+
return QualType(this, 0);
}
@@ -2991,7 +3102,7 @@ bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
QualType DecltypeType::desugar() const {
if (isSugared())
return getUnderlyingType();
-
+
return QualType(this, 0);
}
@@ -3048,7 +3159,7 @@ bool RecordType::hasConstFields() const {
if (FieldTy.isConstQualified())
return true;
FieldTy = FieldTy.getCanonicalType();
- if (const RecordType *FieldRecTy = FieldTy->getAs<RecordType>())
+ if (const auto *FieldRecTy = FieldTy->getAs<RecordType>())
if (FieldRecTy->hasConstFields())
return true;
}
@@ -3067,6 +3178,7 @@ bool AttributedType::isQualifier() const {
case AttributedType::attr_nonnull:
case AttributedType::attr_nullable:
case AttributedType::attr_null_unspecified:
+ case AttributedType::attr_lifetimebound:
return true;
// These aren't qualifiers; they rewrite the modified type to be a
@@ -3097,6 +3209,7 @@ bool AttributedType::isQualifier() const {
case AttributedType::attr_uptr:
case AttributedType::attr_objc_kindof:
case AttributedType::attr_ns_returns_retained:
+ case AttributedType::attr_nocf_check:
return false;
}
llvm_unreachable("bad attributed type kind");
@@ -3134,6 +3247,8 @@ bool AttributedType::isCallingConv() const {
case attr_nullable:
case attr_null_unspecified:
case attr_objc_kindof:
+ case attr_nocf_check:
+ case attr_lifetimebound:
return false;
case attr_pcs:
@@ -3165,7 +3280,7 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
}
SubstTemplateTypeParmPackType::
-SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
+SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
const TemplateArgument &ArgPack)
: Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
@@ -3222,15 +3337,14 @@ TemplateSpecializationType(TemplateName T,
false,
T.containsUnexpandedParameterPack()),
Template(T), NumArgs(Args.size()), TypeAlias(!AliasedType.isNull()) {
- assert(!T.getAsDependentTemplateName() &&
+ assert(!T.getAsDependentTemplateName() &&
"Use DependentTemplateSpecializationType for dependent template-name");
assert((T.getKind() == TemplateName::Template ||
T.getKind() == TemplateName::SubstTemplateTemplateParm ||
T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
"Unexpected template name for TemplateSpecializationType");
- TemplateArgument *TemplateArgs
- = reinterpret_cast<TemplateArgument *>(this + 1);
+ auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);
for (const TemplateArgument &Arg : Args) {
// Update instantiation-dependent and variably-modified bits.
// If the canonical type exists and is non-dependent, the template
@@ -3252,7 +3366,7 @@ TemplateSpecializationType(TemplateName T,
// Store the aliased type if this is a type alias template specialization.
if (TypeAlias) {
- TemplateArgument *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
+ auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
*reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType;
}
}
@@ -3320,7 +3434,7 @@ void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) {
namespace {
-/// \brief The cached properties of a type.
+/// The cached properties of a type.
class CachedProperties {
Linkage L;
bool local;
@@ -3438,7 +3552,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
}
// C++ [basic.link]p8:
- // - it is a compound type (3.9.2) other than a class or enumeration,
+ // - it is a compound type (3.9.2) other than a class or enumeration,
// compounded exclusively from types that have linkage; or
case Type::Complex:
return Cache::get(cast<ComplexType>(T)->getElementType());
@@ -3450,7 +3564,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
case Type::RValueReference:
return Cache::get(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
- const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ const auto *MPT = cast<MemberPointerType>(T);
return merge(Cache::get(MPT->getClass()),
Cache::get(MPT->getPointeeType()));
}
@@ -3464,7 +3578,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
case Type::FunctionNoProto:
return Cache::get(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ const auto *FPT = cast<FunctionProtoType>(T);
CachedProperties result = Cache::get(FPT->getReturnType());
for (const auto &ai : FPT->param_types())
result = merge(result, Cache::get(ai));
@@ -3487,7 +3601,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
llvm_unreachable("unhandled type class");
}
-/// \brief Determine the linkage of this type.
+/// Determine the linkage of this type.
Linkage Type::getLinkage() const {
Cache::ensure(this);
return TypeBits.getLinkage();
@@ -3534,7 +3648,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
case Type::RValueReference:
return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
- const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ const auto *MPT = cast<MemberPointerType>(T);
LinkageInfo LV = computeTypeLinkageInfo(MPT->getClass());
LV.merge(computeTypeLinkageInfo(MPT->getPointeeType()));
return LV;
@@ -3549,7 +3663,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
case Type::FunctionNoProto:
return computeTypeLinkageInfo(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ const auto *FPT = cast<FunctionProtoType>(T);
LinkageInfo LV = computeTypeLinkageInfo(FPT->getReturnType());
for (const auto &ai : FPT->param_types())
LV.merge(computeTypeLinkageInfo(ai));
@@ -3608,14 +3722,14 @@ Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const
QualType desugared = type.getSingleStepDesugaredType(context);
if (desugared.getTypePtr() == type.getTypePtr())
return None;
-
+
type = desugared;
} while (true);
}
bool Type::canHaveNullability(bool ResultIfUnknown) const {
QualType type = getCanonicalTypeInternal();
-
+
switch (type->getTypeClass()) {
// We'll only see canonical types here.
#define NON_CANONICAL_TYPE(Class, Parent) \
@@ -3702,6 +3816,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
+ case Type::DependentVector:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -3744,7 +3859,7 @@ Optional<NullabilityKind> AttributedType::stripOuterNullability(QualType &T) {
}
bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
- const ObjCObjectPointerType *objcPtr = getAs<ObjCObjectPointerType>();
+ const auto *objcPtr = getAs<ObjCObjectPointerType>();
if (!objcPtr)
return false;
@@ -3789,11 +3904,10 @@ bool Type::isObjCARCImplicitlyUnretainedType() const {
const Type *canon = getCanonicalTypeInternal().getTypePtr();
// Walk down to the base type. We don't care about qualifiers for this.
- while (const ArrayType *array = dyn_cast<ArrayType>(canon))
+ while (const auto *array = dyn_cast<ArrayType>(canon))
canon = array->getElementType().getTypePtr();
- if (const ObjCObjectPointerType *opt
- = dyn_cast<ObjCObjectPointerType>(canon)) {
+ if (const auto *opt = dyn_cast<ObjCObjectPointerType>(canon)) {
// Class and Class<Protocol> don't require retention.
if (opt->getObjectType()->isObjCClass())
return true;
@@ -3805,7 +3919,7 @@ bool Type::isObjCARCImplicitlyUnretainedType() const {
bool Type::isObjCNSObjectType() const {
const Type *cur = this;
while (true) {
- if (const TypedefType *typedefType = dyn_cast<TypedefType>(cur))
+ if (const auto *typedefType = dyn_cast<TypedefType>(cur))
return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
// Single-step desugar until we run out of sugar.
@@ -3816,7 +3930,7 @@ bool Type::isObjCNSObjectType() const {
}
bool Type::isObjCIndependentClassType() const {
- if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ if (const auto *typedefType = dyn_cast<TypedefType>(this))
return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
return false;
}
@@ -3830,11 +3944,11 @@ bool Type::isObjCRetainableType() const {
bool Type::isObjCIndirectLifetimeType() const {
if (isObjCLifetimeType())
return true;
- if (const PointerType *OPT = getAs<PointerType>())
+ if (const auto *OPT = getAs<PointerType>())
return OPT->getPointeeType()->isObjCIndirectLifetimeType();
- if (const ReferenceType *Ref = getAs<ReferenceType>())
+ if (const auto *Ref = getAs<ReferenceType>())
return Ref->getPointeeType()->isObjCIndirectLifetimeType();
- if (const MemberPointerType *MemPtr = getAs<MemberPointerType>())
+ if (const auto *MemPtr = getAs<MemberPointerType>())
return MemPtr->getPointeeType()->isObjCIndirectLifetimeType();
return false;
}
@@ -3848,18 +3962,18 @@ bool Type::isObjCLifetimeType() const {
return type->isObjCRetainableType();
}
-/// \brief Determine whether the given type T is a "bridgable" Objective-C type,
-/// which is either an Objective-C object pointer type or an
+/// Determine whether the given type T is a "bridgable" Objective-C type,
+/// which is either an Objective-C object pointer type or an
bool Type::isObjCARCBridgableType() const {
return isObjCObjectPointerType() || isBlockPointerType();
}
-/// \brief Determine whether the given type T is a "bridgeable" C type.
+/// Determine whether the given type T is a "bridgeable" C type.
bool Type::isCARCBridgableType() const {
- const PointerType *Pointer = getAs<PointerType>();
+ const auto *Pointer = getAs<PointerType>();
if (!Pointer)
return false;
-
+
QualType Pointee = Pointer->getPointeeType();
return Pointee->isVoidType() || Pointee->isRecordType();
}
@@ -3867,12 +3981,12 @@ bool Type::isCARCBridgableType() const {
bool Type::hasSizedVLAType() const {
if (!isVariablyModifiedType()) return false;
- if (const PointerType *ptr = getAs<PointerType>())
+ if (const auto *ptr = getAs<PointerType>())
return ptr->getPointeeType()->hasSizedVLAType();
- if (const ReferenceType *ref = getAs<ReferenceType>())
+ if (const auto *ref = getAs<ReferenceType>())
return ref->getPointeeType()->hasSizedVLAType();
if (const ArrayType *arr = getAsArrayTypeUnsafe()) {
- if (isa<VariableArrayType>(arr) &&
+ if (isa<VariableArrayType>(arr) &&
cast<VariableArrayType>(arr)->getSizeExpr())
return true;
@@ -3895,16 +4009,40 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
return DK_objc_weak_lifetime;
}
- /// Currently, the only destruction kind we recognize is C++ objects
- /// with non-trivial destructors.
- const CXXRecordDecl *record =
- type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
- if (record && record->hasDefinition() && !record->hasTrivialDestructor())
- return DK_cxx_destructor;
+ if (const auto *RT =
+ type->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ /// Check if this is a C++ object with a non-trivial destructor.
+ if (CXXRD->hasDefinition() && !CXXRD->hasTrivialDestructor())
+ return DK_cxx_destructor;
+ } else {
+ /// Check if this is a C struct that is non-trivial to destroy or an array
+ /// that contains such a struct.
+ if (RD->isNonTrivialToPrimitiveDestroy())
+ return DK_nontrivial_c_struct;
+ }
+ }
return DK_none;
}
CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
- return getClass()->getAsCXXRecordDecl()->getMostRecentDecl();
+ return getClass()->getAsCXXRecordDecl()->getMostRecentNonInjectedDecl();
+}
+
+void clang::FixedPointValueToString(SmallVectorImpl<char> &Str,
+ const llvm::APSInt &Val, unsigned Scale,
+ unsigned Radix) {
+ llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale);
+ llvm::APSInt IntPart = Val / ScaleVal;
+ llvm::APSInt FractPart = Val % ScaleVal;
+ llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix);
+
+ IntPart.toString(Str, Radix);
+ Str.push_back('.');
+ do {
+ (FractPart * RadixInt / ScaleVal).toString(Str, Radix);
+ FractPart = (FractPart * RadixInt) % ScaleVal;
+ } while (FractPart.getExtValue());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
index 0ac50b31acec..e4fd6f106e33 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
@@ -68,7 +68,7 @@ public:
} // namespace
-/// \brief Returns the alignment of the type source info data block.
+/// Returns the alignment of the type source info data block.
unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
if (Ty.isNull()) return 1;
return TypeAligner().Visit(TypeLoc(Ty, nullptr));
@@ -88,7 +88,7 @@ public:
} // namespace
-/// \brief Returns the size of the type source info data block.
+/// Returns the size of the type source info data block.
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
unsigned Total = 0;
TypeLoc TyLoc(Ty, nullptr);
@@ -118,16 +118,16 @@ public:
} // namespace
-/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
+/// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
return NextLoc().Visit(TL);
}
-/// \brief Initializes a type location, and all of its children
+/// Initializes a type location, and all of its children
/// recursively, as if the entire tree had been written in the
/// given location.
-void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
+void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
SourceLocation Loc) {
while (true) {
switch (TL.getTypeLocClass()) {
@@ -254,7 +254,7 @@ SourceLocation TypeLoc::getEndLoc() const {
case RValueReference:
case PackExpansion:
if (!Last)
- Last = Cur;
+ Last = Cur;
break;
case Qualified:
case Elaborated:
@@ -281,7 +281,7 @@ struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
} // namespace
-/// \brief Determines if the given type loc corresponds to a
+/// Determines if the given type loc corresponds to a
/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
/// the type hierarchy, this is made somewhat complicated.
///
@@ -317,6 +317,8 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::Char_U:
case BuiltinType::Char_S:
return TST_char;
+ case BuiltinType::Char8:
+ return TST_char8;
case BuiltinType::Char16:
return TST_char16;
case BuiltinType::Char32:
@@ -342,9 +344,33 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::LongDouble:
case BuiltinType::Float16:
case BuiltinType::Float128:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
llvm_unreachable("Builtin type needs extra local data!");
// Fall through, if the impossible happens.
-
+
case BuiltinType::NullPtr:
case BuiltinType::Overload:
case BuiltinType::Dependent:
@@ -420,13 +446,13 @@ void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
setProtocolLoc(i, Loc);
}
-void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
+void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
setTypeArgsLAngleLoc(Loc);
setTypeArgsRAngleLoc(Loc);
for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
- setTypeArgTInfo(i,
+ setTypeArgTInfo(i,
Context.getTrivialTypeSourceInfo(
getTypePtr()->getTypeArgsAsWritten()[i], Loc));
}
@@ -453,7 +479,7 @@ void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context,
Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc));
}
-void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
+void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setElaboratedKeywordLoc(Loc);
NestedNameSpecifierLocBuilder Builder;
@@ -461,7 +487,7 @@ void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
setQualifierLoc(Builder.getWithLocInContext(Context));
}
-void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
+void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setElaboratedKeywordLoc(Loc);
NestedNameSpecifierLocBuilder Builder;
@@ -490,14 +516,14 @@ DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
getArgInfos(), Loc);
}
-void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
+void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
unsigned NumArgs,
const TemplateArgument *Args,
TemplateArgumentLocInfo *ArgInfos,
SourceLocation Loc) {
for (unsigned i = 0, e = NumArgs; i != e; ++i) {
switch (Args[i].getKind()) {
- case TemplateArgument::Null:
+ case TemplateArgument::Null:
llvm_unreachable("Impossible TemplateArgument");
case TemplateArgument::Integral:
@@ -509,10 +535,10 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
case TemplateArgument::Expression:
ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
break;
-
+
case TemplateArgument::Type:
ArgInfos[i] = TemplateArgumentLocInfo(
- Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
+ Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
Loc));
break;
diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
index c28ada7dcb8b..e032c312aa12 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -1,4 +1,4 @@
-//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
+//===- TypePrinter.cpp - Pretty-Print Clang Types -------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,32 +14,52 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/ASTContext.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/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+
using namespace clang;
namespace {
- /// \brief RAII object that enables printing of the ARC __strong lifetime
+
+ /// RAII object that enables printing of the ARC __strong lifetime
/// qualifier.
class IncludeStrongLifetimeRAII {
PrintingPolicy &Policy;
bool Old;
-
+
public:
- explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
- : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
+ explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
+ : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
if (!Policy.SuppressLifetimeQualifiers)
Policy.SuppressStrongLifetime = false;
}
-
+
~IncludeStrongLifetimeRAII() {
Policy.SuppressStrongLifetime = Old;
}
@@ -48,13 +68,13 @@ namespace {
class ParamPolicyRAII {
PrintingPolicy &Policy;
bool Old;
-
+
public:
- explicit ParamPolicyRAII(PrintingPolicy &Policy)
- : Policy(Policy), Old(Policy.SuppressSpecifiers) {
+ explicit ParamPolicyRAII(PrintingPolicy &Policy)
+ : Policy(Policy), Old(Policy.SuppressSpecifiers) {
Policy.SuppressSpecifiers = false;
}
-
+
~ParamPolicyRAII() {
Policy.SuppressSpecifiers = Old;
}
@@ -64,7 +84,7 @@ namespace {
PrintingPolicy &Policy;
bool SuppressTagKeyword;
bool SuppressScope;
-
+
public:
explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
SuppressTagKeyword = Policy.SuppressTagKeyword;
@@ -72,23 +92,22 @@ namespace {
Policy.SuppressTagKeyword = true;
Policy.SuppressScope = true;
}
-
+
~ElaboratedTypePolicyRAII() {
Policy.SuppressTagKeyword = SuppressTagKeyword;
Policy.SuppressScope = SuppressScope;
}
};
-
+
class TypePrinter {
PrintingPolicy Policy;
unsigned Indentation;
- bool HasEmptyPlaceHolder;
- bool InsideCCAttribute;
+ bool HasEmptyPlaceHolder = false;
+ bool InsideCCAttribute = false;
public:
explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0)
- : Policy(Policy), Indentation(Indentation),
- HasEmptyPlaceHolder(false), InsideCCAttribute(false) { }
+ : Policy(Policy), Indentation(Indentation) {}
void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
StringRef PlaceHolder);
@@ -111,7 +130,8 @@ namespace {
void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
#include "clang/AST/TypeNodes.def"
};
-}
+
+} // namespace
static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals,
bool HasRestrictKeyword) {
@@ -169,12 +189,11 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
bool CanPrefixQualifiers = false;
NeedARCStrongQualifier = false;
Type::TypeClass TC = T->getTypeClass();
- if (const AutoType *AT = dyn_cast<AutoType>(T))
+ if (const auto *AT = dyn_cast<AutoType>(T))
TC = AT->desugar()->getTypeClass();
- if (const SubstTemplateTypeParmType *Subst
- = dyn_cast<SubstTemplateTypeParmType>(T))
+ if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T))
TC = Subst->getReplacementType()->getTypeClass();
-
+
switch (TC) {
case Type::Auto:
case Type::Builtin:
@@ -202,19 +221,19 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::Pipe:
CanPrefixQualifiers = true;
break;
-
+
case Type::ObjCObjectPointer:
CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
break;
-
+
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
NeedARCStrongQualifier = true;
LLVM_FALLTHROUGH;
-
+
case Type::Adjusted:
case Type::Decayed:
case Type::Pointer:
@@ -223,6 +242,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::RValueReference:
case Type::MemberPointer:
case Type::DependentAddressSpace:
+ case Type::DependentVector:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -245,14 +265,13 @@ void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
// If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
// at this level.
Qualifiers Quals = Split.Quals;
- if (const SubstTemplateTypeParmType *Subst =
- dyn_cast<SubstTemplateTypeParmType>(Split.Ty))
+ if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Split.Ty))
Quals -= QualType(Subst, 0).getQualifiers();
printBefore(Split.Ty, Quals, OS);
}
-/// \brief Prints the part of the type string before an identifier, e.g. for
+/// Prints the part of the type string before an identifier, e.g. for
/// "int foo[10]" it prints "int ".
void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
if (Policy.SuppressSpecifiers && T->isSpecifierType())
@@ -305,7 +324,7 @@ void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
printAfter(split.Ty, split.Quals, OS);
}
-/// \brief Prints the part of the type string after an identifier, e.g. for
+/// Prints the part of the type string after an identifier, e.g. for
/// "int foo[10]" it prints "[10]".
void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {
switch (T->getTypeClass()) {
@@ -321,12 +340,14 @@ void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {
OS << T->getName(Policy);
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) { }
+
+void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) {}
void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {
OS << "_Complex ";
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
}
@@ -341,6 +362,7 @@ void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {
OS << '(';
OS << '*';
}
+
void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
@@ -357,58 +379,73 @@ void TypePrinter::printBlockPointerBefore(const BlockPointerType *T,
printBefore(T->getPointeeType(), OS);
OS << '^';
}
+
void TypePrinter::printBlockPointerAfter(const BlockPointerType *T,
raw_ostream &OS) {
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printAfter(T->getPointeeType(), OS);
}
+// When printing a reference, the referenced type might also be a reference.
+// If so, we want to skip that before printing the inner type.
+static QualType skipTopLevelReferences(QualType T) {
+ if (auto *Ref = T->getAs<ReferenceType>())
+ return skipTopLevelReferences(Ref->getPointeeTypeAsWritten());
+ return T;
+}
+
void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
- printBefore(T->getPointeeTypeAsWritten(), OS);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
+ printBefore(Inner, OS);
// Handle things like 'int (&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << '(';
OS << '&';
}
+
void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
// Handle things like 'int (&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << ')';
- printAfter(T->getPointeeTypeAsWritten(), OS);
+ printAfter(Inner, OS);
}
void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
- printBefore(T->getPointeeTypeAsWritten(), OS);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
+ printBefore(Inner, OS);
// Handle things like 'int (&&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << '(';
OS << "&&";
}
+
void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
// Handle things like 'int (&&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << ')';
- printAfter(T->getPointeeTypeAsWritten(), OS);
+ printAfter(Inner, OS);
}
-void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
- raw_ostream &OS) {
+void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getPointeeType(), OS);
@@ -423,8 +460,9 @@ void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
OS << "::*";
}
-void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
- raw_ostream &OS) {
+
+void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
// Handle things like 'int (Cls::*A)[4];' correctly.
@@ -434,13 +472,14 @@ void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
printAfter(T->getPointeeType(), OS);
}
-void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
+void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
-void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
+
+void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
@@ -456,25 +495,27 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
printAfter(T->getElementType(), OS);
}
-void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
+void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
-void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
+
+void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
raw_ostream &OS) {
OS << "[]";
printAfter(T->getElementType(), OS);
}
-void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
+void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
-void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
+
+void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
@@ -499,6 +540,7 @@ void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {
// invisible.
printBefore(T->getAdjustedType(), OS);
}
+
void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {
printAfter(T->getAdjustedType(), OS);
}
@@ -507,19 +549,21 @@ void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
// Print as though it's a pointer.
printAdjustedBefore(T, OS);
}
+
void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
printAdjustedAfter(T, OS);
}
void TypePrinter::printDependentSizedArrayBefore(
- const DependentSizedArrayType *T,
+ const DependentSizedArrayType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printDependentSizedArrayAfter(
- const DependentSizedArrayType *T,
+ const DependentSizedArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getSizeExpr())
@@ -532,6 +576,7 @@ 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(";
@@ -542,21 +587,22 @@ void TypePrinter::printDependentAddressSpaceAfter(
}
void TypePrinter::printDependentSizedExtVectorBefore(
- const DependentSizedExtVectorType *T,
- raw_ostream &OS) {
+ const DependentSizedExtVectorType *T,
+ raw_ostream &OS) {
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printDependentSizedExtVectorAfter(
- const DependentSizedExtVectorType *T,
- raw_ostream &OS) {
+ const DependentSizedExtVectorType *T,
+ raw_ostream &OS) {
OS << " __attribute__((ext_vector_type(";
if (T->getSizeExpr())
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
- OS << ")))";
+ OS << ")))";
printAfter(T->getElementType(), OS);
}
-void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
+void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
switch (T->getVectorKind()) {
case VectorType::AltiVecPixel:
OS << "__vector __pixel ";
@@ -586,32 +632,81 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
<< T->getNumElements()
<< " * sizeof(";
print(T->getElementType(), OS, StringRef());
- OS << ")))) ";
+ OS << ")))) ";
printBefore(T->getElementType(), OS);
break;
}
}
}
+
void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
-}
+}
+
+void TypePrinter::printDependentVectorBefore(
+ const DependentVectorType *T, raw_ostream &OS) {
+ switch (T->getVectorKind()) {
+ case VectorType::AltiVecPixel:
+ OS << "__vector __pixel ";
+ break;
+ case VectorType::AltiVecBool:
+ OS << "__vector __bool ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::AltiVecVector:
+ OS << "__vector ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::NeonVector:
+ OS << "__attribute__((neon_vector_type(";
+ if (T->getSizeExpr())
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
+ OS << "))) ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::NeonPolyVector:
+ OS << "__attribute__((neon_polyvector_type(";
+ if (T->getSizeExpr())
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
+ OS << "))) ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::GenericVector: {
+ // FIXME: We prefer to print the size directly here, but have no way
+ // to get the size of the type.
+ OS << "__attribute__((__vector_size__(";
+ if (T->getSizeExpr())
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
+ OS << " * sizeof(";
+ print(T->getElementType(), OS, StringRef());
+ OS << ")))) ";
+ printBefore(T->getElementType(), OS);
+ break;
+ }
+ }
+}
+
+void TypePrinter::printDependentVectorAfter(
+ const DependentVectorType *T, raw_ostream &OS) {
+ printAfter(T->getElementType(), OS);
+}
void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
- raw_ostream &OS) {
+ raw_ostream &OS) {
printBefore(T->getElementType(), OS);
}
-void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
+
+void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
OS << " __attribute__((ext_vector_type(";
OS << T->getNumElements();
OS << ")))";
}
-void
-FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
+void
+FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
const PrintingPolicy &Policy)
const {
-
if (hasDynamicExceptionSpec()) {
OS << " throw(";
if (getExceptionSpecType() == EST_MSAny)
@@ -620,13 +715,15 @@ FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
if (I)
OS << ", ";
-
+
OS << getExceptionType(I).stream(Policy);
}
OS << ')';
} else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
OS << " noexcept";
- if (getExceptionSpecType() == EST_ComputedNoexcept) {
+ // FIXME:Is it useful to print out the expression for a non-dependent
+ // noexcept specification?
+ if (isComputedNoexcept(getExceptionSpecType())) {
OS << '(';
if (getNoexceptExpr())
getNoexceptExpr()->printPretty(OS, nullptr, Policy);
@@ -635,7 +732,7 @@ FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
}
}
-void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
+void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
raw_ostream &OS) {
if (T->hasTrailingReturn()) {
OS << "auto ";
@@ -650,7 +747,7 @@ void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
}
}
-llvm::StringRef clang::getParameterABISpelling(ParameterABI ABI) {
+StringRef clang::getParameterABISpelling(ParameterABI ABI) {
switch (ABI) {
case ParameterABI::Ordinary:
llvm_unreachable("asking for spelling of ordinary parameter ABI");
@@ -664,8 +761,8 @@ llvm::StringRef clang::getParameterABISpelling(ParameterABI ABI) {
llvm_unreachable("bad parameter ABI kind");
}
-void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
- raw_ostream &OS) {
+void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
+ raw_ostream &OS) {
// If needed for precedence reasons, wrap the inner part in grouping parens.
if (!HasEmptyPlaceHolder)
OS << ')';
@@ -688,7 +785,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
print(T->getParamType(i), OS, StringRef());
}
}
-
+
if (T->isVariadic()) {
if (T->getNumParams())
OS << ", ";
@@ -697,7 +794,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
// Do not emit int() if we have a proto, emit 'int(void)'.
OS << "void";
}
-
+
OS << ')';
FunctionType::ExtInfo Info = T->getExtInfo();
@@ -801,23 +898,26 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
<< Info.getRegParm() << ")))";
if (Info.getNoCallerSavedRegs())
OS << " __attribute__((no_caller_saved_registers))";
+ if (Info.getNoCfCheck())
+ OS << " __attribute__((nocf_check))";
}
-void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
- raw_ostream &OS) {
+void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
+ raw_ostream &OS) {
// If needed for precedence reasons, wrap the inner part in grouping parens.
SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
printBefore(T->getReturnType(), OS);
if (!PrevPHIsEmpty.get())
OS << '(';
}
-void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
+
+void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
raw_ostream &OS) {
// If needed for precedence reasons, wrap the inner part in grouping parens.
if (!HasEmptyPlaceHolder)
OS << ')';
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
-
+
OS << "()";
printFunctionAfter(T->getExtInfo(), OS);
printAfter(T->getReturnType(), OS);
@@ -840,13 +940,15 @@ void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
raw_ostream &OS) {
printTypeSpec(T->getDecl(), OS);
}
+
void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
-void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
+void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
printTypeSpec(T->getDecl(), OS);
}
-void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) { }
+
+void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
raw_ostream &OS) {
@@ -855,25 +957,28 @@ void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
-void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
+void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
OS << "typeof(";
print(T->getUnderlyingType(), OS, StringRef());
OS << ')';
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) { }
-void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
+void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
+
+void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
OS << "decltype(";
if (T->getUnderlyingExpr())
T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
OS << ')';
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) { }
+
+void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {}
void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
raw_ostream &OS) {
@@ -890,6 +995,7 @@ void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
printBefore(T->getBaseType(), OS);
}
+
void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
@@ -902,7 +1008,7 @@ void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
printAfter(T->getBaseType(), OS);
}
-void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
+void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
// If the type has been deduced, do not print 'auto'.
if (!T->getDeducedType().isNull()) {
printBefore(T->getDeducedType(), OS);
@@ -915,7 +1021,8 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
spaceBeforePlaceHolder(OS);
}
}
-void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
+
+void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
// If the type has been deduced, do not print 'auto'.
if (!T->getDeducedType().isNull())
printAfter(T->getDeducedType(), OS);
@@ -932,6 +1039,7 @@ void TypePrinter::printDeducedTemplateSpecializationBefore(
spaceBeforePlaceHolder(OS);
}
}
+
void TypePrinter::printDeducedTemplateSpecializationAfter(
const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
// If the type has been deduced, print the deduced type.
@@ -947,7 +1055,8 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
OS << ')';
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
+
+void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {}
void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
@@ -961,30 +1070,29 @@ void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {
-}
+void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
+
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return;
if (DC->isFunctionOrMethod()) return;
AppendScope(DC->getParent(), OS);
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
- if (Policy.SuppressUnwrittenScope &&
+ if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
+ if (Policy.SuppressUnwrittenScope &&
(NS->isAnonymousNamespace() || NS->isInline()))
return;
if (NS->getIdentifier())
OS << NS->getName() << "::";
else
OS << "(anonymous namespace)::";
- } else if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+ } else if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
IncludeStrongLifetimeRAII Strong(Policy);
OS << Spec->getIdentifier()->getName();
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
OS << "::";
- } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+ } else if (const auto *Tag = dyn_cast<TagDecl>(DC)) {
if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
OS << Typedef->getIdentifier()->getName() << "::";
else if (Tag->getIdentifier())
@@ -1035,7 +1143,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
} else {
OS << "anonymous";
}
-
+
if (Policy.AnonymousTagLocations) {
// Suppress the redundant tag keyword if we just printed one.
// We don't have to worry about ElaboratedTypes here because you can't
@@ -1057,8 +1165,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
// If this is a class template specialization, print the template
// arguments.
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
ArrayRef<TemplateArgument> Args;
if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
const TemplateSpecializationType *TST =
@@ -1078,88 +1185,109 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
printTag(T->getDecl(), OS);
}
-void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) { }
-void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
+void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}
+
+void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
printTag(T->getDecl(), OS);
}
-void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) { }
-void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
- raw_ostream &OS) {
+void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
+
+void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
+ raw_ostream &OS) {
if (IdentifierInfo *Id = T->getIdentifier())
OS << Id->getName();
else
OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
- raw_ostream &OS) { }
+
+void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
+ raw_ostream &OS) {}
void TypePrinter::printSubstTemplateTypeParmBefore(
- const SubstTemplateTypeParmType *T,
- raw_ostream &OS) {
+ const SubstTemplateTypeParmType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
printBefore(T->getReplacementType(), OS);
}
+
void TypePrinter::printSubstTemplateTypeParmAfter(
- const SubstTemplateTypeParmType *T,
- raw_ostream &OS) {
+ const SubstTemplateTypeParmType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
printAfter(T->getReplacementType(), OS);
}
void TypePrinter::printSubstTemplateTypeParmPackBefore(
- const SubstTemplateTypeParmPackType *T,
- raw_ostream &OS) {
+ const SubstTemplateTypeParmPackType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
printTemplateTypeParmBefore(T->getReplacedParameter(), OS);
}
+
void TypePrinter::printSubstTemplateTypeParmPackAfter(
- const SubstTemplateTypeParmPackType *T,
- raw_ostream &OS) {
+ const SubstTemplateTypeParmPackType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
}
void TypePrinter::printTemplateSpecializationBefore(
- const TemplateSpecializationType *T,
- raw_ostream &OS) {
+ const TemplateSpecializationType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
T->getTemplateName().print(OS, Policy);
printTemplateArgumentList(OS, T->template_arguments(), Policy);
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printTemplateSpecializationAfter(
- const TemplateSpecializationType *T,
- raw_ostream &OS) { }
+ const TemplateSpecializationType *T,
+ raw_ostream &OS) {}
void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
raw_ostream &OS) {
printTemplateSpecializationBefore(T->getInjectedTST(), OS);
}
+
void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
raw_ostream &OS) {
+ if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) {
+ TagDecl *OwnedTagDecl = T->getOwnedTagDecl();
+ assert(OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() &&
+ "OwnedTagDecl expected to be a declaration for the type");
+ PrintingPolicy SubPolicy = Policy;
+ SubPolicy.IncludeTagDefinition = false;
+ OwnedTagDecl->print(OS, SubPolicy, Indentation);
+ spaceBeforePlaceHolder(OS);
+ return;
+ }
+
// The tag definition will take care of these.
if (!Policy.IncludeTagDefinition)
{
OS << TypeWithKeyword::getKeywordName(T->getKeyword());
if (T->getKeyword() != ETK_None)
OS << " ";
- NestedNameSpecifier* Qualifier = T->getQualifier();
+ NestedNameSpecifier *Qualifier = T->getQualifier();
if (Qualifier)
Qualifier->print(OS, Policy);
}
-
+
ElaboratedTypePolicyRAII PolicyRAII(Policy);
printBefore(T->getNamedType(), OS);
}
+
void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
raw_ostream &OS) {
+ if (Policy.IncludeTagDefinition && T->getOwnedTagDecl())
+ return;
ElaboratedTypePolicyRAII PolicyRAII(Policy);
printAfter(T->getNamedType(), OS);
}
@@ -1171,6 +1299,7 @@ void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
} else
printBefore(T->getInnerType(), OS);
}
+
void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
OS << ')';
@@ -1180,21 +1309,22 @@ void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
}
void TypePrinter::printDependentNameBefore(const DependentNameType *T,
- raw_ostream &OS) {
+ raw_ostream &OS) {
OS << TypeWithKeyword::getKeywordName(T->getKeyword());
if (T->getKeyword() != ETK_None)
OS << " ";
-
+
T->getQualifier()->print(OS, Policy);
-
+
OS << T->getIdentifier()->getName();
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printDependentNameAfter(const DependentNameType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
void TypePrinter::printDependentTemplateSpecializationBefore(
- const DependentTemplateSpecializationType *T, raw_ostream &OS) {
+ const DependentTemplateSpecializationType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
OS << TypeWithKeyword::getKeywordName(T->getKeyword());
@@ -1209,13 +1339,14 @@ void TypePrinter::printDependentTemplateSpecializationBefore(
}
void TypePrinter::printDependentTemplateSpecializationAfter(
- const DependentTemplateSpecializationType *T, raw_ostream &OS) { }
+ const DependentTemplateSpecializationType *T, raw_ostream &OS) {}
-void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
+void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
raw_ostream &OS) {
printBefore(T->getPattern(), OS);
}
-void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
+
+void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
raw_ostream &OS) {
printAfter(T->getPattern(), OS);
OS << "...";
@@ -1312,9 +1443,27 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
return;
}
+ if (T->getAttrKind() == AttributedType::attr_lifetimebound) {
+ OS << " [[clang::lifetimebound]]";
+ return;
+ }
+
OS << " __attribute__((";
switch (T->getAttrKind()) {
- default: llvm_unreachable("This attribute should have been handled already");
+ case AttributedType::attr_lifetimebound:
+ case AttributedType::attr_nonnull:
+ case AttributedType::attr_nullable:
+ case AttributedType::attr_null_unspecified:
+ case AttributedType::attr_objc_gc:
+ case AttributedType::attr_objc_inert_unsafe_unretained:
+ case AttributedType::attr_objc_kindof:
+ case AttributedType::attr_objc_ownership:
+ case AttributedType::attr_ptr32:
+ case AttributedType::attr_ptr64:
+ case AttributedType::attr_sptr:
+ case AttributedType::attr_uptr:
+ llvm_unreachable("This attribute should have been handled already");
+
case AttributedType::attr_address_space:
OS << "address_space(";
// FIXME: printing the raw LangAS value is wrong. This should probably
@@ -1323,9 +1472,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << ')';
break;
- case AttributedType::attr_vector_size: {
+ case AttributedType::attr_vector_size:
OS << "__vector_size__(";
- if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
+ if (const auto *vector = T->getEquivalentType()->getAs<VectorType>()) {
OS << vector->getNumElements();
OS << " * sizeof(";
print(vector->getElementType(), OS, StringRef());
@@ -1333,7 +1482,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
}
OS << ')';
break;
- }
case AttributedType::attr_neon_vector_type:
case AttributedType::attr_neon_polyvector_type: {
@@ -1341,7 +1489,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << "neon_vector_type(";
else
OS << "neon_polyvector_type(";
- const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
+ const auto *vector = T->getEquivalentType()->getAs<VectorType>();
OS << vector->getNumElements();
OS << ')';
break;
@@ -1359,36 +1507,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
break;
}
- case AttributedType::attr_objc_gc: {
- OS << "objc_gc(";
-
- QualType tmp = T->getEquivalentType();
- while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
- QualType next = tmp->getPointeeType();
- if (next == tmp) break;
- tmp = next;
- }
-
- if (tmp.isObjCGCWeak())
- OS << "weak";
- else
- OS << "strong";
- OS << ')';
- break;
- }
-
- case AttributedType::attr_objc_ownership:
- OS << "objc_ownership(";
- switch (T->getEquivalentType().getObjCLifetime()) {
- case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
- case Qualifiers::OCL_ExplicitNone: OS << "none"; break;
- case Qualifiers::OCL_Strong: OS << "strong"; break;
- case Qualifiers::OCL_Weak: OS << "weak"; break;
- case Qualifiers::OCL_Autoreleasing: OS << "autoreleasing"; break;
- }
- OS << ')';
- break;
-
case AttributedType::attr_ns_returns_retained:
OS << "ns_returns_retained";
break;
@@ -1396,7 +1514,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
// FIXME: When Sema learns to form this AttributedType, avoid printing the
// attribute again in printFunctionProtoAfter.
case AttributedType::attr_noreturn: OS << "noreturn"; break;
-
+ case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
case AttributedType::attr_cdecl: OS << "cdecl"; break;
case AttributedType::attr_fastcall: OS << "fastcall"; break;
case AttributedType::attr_stdcall: OS << "stdcall"; break;
@@ -1418,10 +1536,12 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << ')';
break;
}
+
case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
case AttributedType::attr_preserve_most:
OS << "preserve_most";
break;
+
case AttributedType::attr_preserve_all:
OS << "preserve_all";
break;
@@ -1429,13 +1549,14 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << "))";
}
-void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
- raw_ostream &OS) {
+void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
+ raw_ostream &OS) {
OS << T->getDecl()->getName();
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
- raw_ostream &OS) { }
+
+void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
+ raw_ostream &OS) {}
void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
raw_ostream &OS) {
@@ -1457,7 +1578,7 @@ void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
}
void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
raw_ostream &OS) {
@@ -1499,6 +1620,7 @@ void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
raw_ostream &OS) {
if (T->qual_empty() && T->isUnspecializedAsWritten() &&
@@ -1506,7 +1628,7 @@ void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
return printAfter(T->getBaseType(), OS);
}
-void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
+void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
raw_ostream &OS) {
printBefore(T->getPointeeType(), OS);
@@ -1519,8 +1641,8 @@ void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
}
}
-void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
- raw_ostream &OS) { }
+void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
+ raw_ostream &OS) {}
static
const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
@@ -1698,11 +1820,11 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
switch (lifetime) {
case Qualifiers::OCL_None: llvm_unreachable("none but true");
case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
- case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Strong:
if (!Policy.SuppressStrongLifetime)
- OS << "__strong";
+ OS << "__strong";
break;
-
+
case Qualifiers::OCL_Weak: OS << "__weak"; break;
case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
index b946f10105f4..a3f3dbdfb4f9 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
@@ -32,11 +32,11 @@ using namespace clang;
VTTBuilder::VTTBuilder(ASTContext &Ctx,
const CXXRecordDecl *MostDerivedClass,
bool GenerateDefinition)
- : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
+ : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
GenerateDefinition(GenerateDefinition) {
// Lay out this VTT.
- LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+ LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
/*BaseIsVirtual=*/false);
}
@@ -69,22 +69,22 @@ void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
- CharUnits BaseOffset = Base.getBaseOffset() +
+ CharUnits BaseOffset = Base.getBaseOffset() +
Layout.getBaseClassOffset(BaseDecl);
-
+
// Layout the VTT for this base.
LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
}
}
void
-VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
+VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
bool BaseIsMorallyVirtual,
uint64_t VTableIndex,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy &VBases) {
const CXXRecordDecl *RD = Base.getBase();
-
+
// We're not interested in bases that don't have virtual bases, and not
// morally virtual bases.
if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
@@ -96,14 +96,14 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
// Itanium C++ ABI 2.6.2:
// Secondary virtual pointers are present for all bases with either
- // virtual bases or virtual function declarations overridden along a
+ // virtual bases or virtual function declarations overridden along a
// virtual path.
//
// If the base class is not dynamic, we don't want to add it, nor any
// of its base classes.
if (!BaseDecl->isDynamicClass())
continue;
-
+
bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
bool BaseDeclIsNonVirtualPrimaryBase = false;
CharUnits BaseOffset;
@@ -111,15 +111,15 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
// Ignore virtual bases that we've already visited.
if (!VBases.insert(BaseDecl).second)
continue;
-
+
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
BaseDeclIsMorallyVirtual = true;
} else {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
-
- BaseOffset = Base.getBaseOffset() +
+
+ BaseOffset = Base.getBaseOffset() +
Layout.getBaseClassOffset(BaseDecl);
-
+
if (!Layout.isPrimaryBaseVirtual() &&
Layout.getPrimaryBase() == BaseDecl)
BaseDeclIsNonVirtualPrimaryBase = true;
@@ -133,19 +133,19 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
if (!BaseDeclIsNonVirtualPrimaryBase &&
(BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
// Add the vtable pointer.
- AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex,
+ AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex,
VTableClass);
}
// And lay out the secondary virtual pointers for the base class.
LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
- BaseDeclIsMorallyVirtual, VTableIndex,
+ BaseDeclIsMorallyVirtual, VTableIndex,
VTableClass, VBases);
}
}
-void
-VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
+void
+VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
uint64_t VTableIndex) {
VisitedVirtualBasesSetTy VBases;
LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
@@ -155,21 +155,21 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases) {
for (const auto &I : RD->bases()) {
- const CXXRecordDecl *BaseDecl =
+ const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
-
+
// Check if this is a virtual base.
if (I.isVirtual()) {
// Check if we've seen this base before.
if (!VBases.insert(BaseDecl).second)
continue;
-
- CharUnits BaseOffset =
+
+ CharUnits BaseOffset =
MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
-
+
LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
}
-
+
// We only need to layout virtual VTTs for this base if it actually has
// virtual bases.
if (BaseDecl->getNumVBases())
@@ -181,7 +181,7 @@ void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
const CXXRecordDecl *RD = Base.getBase();
// Itanium C++ ABI 2.6.2:
- // An array of virtual table addresses, called the VTT, is declared for
+ // An array of virtual table addresses, called the VTT, is declared for
// each class type that has indirect or direct virtual base classes.
if (RD->getNumVBases() == 0)
return;
@@ -201,10 +201,10 @@ void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
// Add the secondary VTTs.
LayoutSecondaryVTTs(Base);
-
+
// Add the secondary virtual pointers.
LayoutSecondaryVirtualPointers(Base, VTableIndex);
-
+
// If this is the primary VTT, we want to lay out virtual VTTs as well.
if (IsPrimaryVTT) {
VisitedVirtualBasesSetTy VBases;
diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
index 347c516ef6a5..dfc5774ab498 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
@@ -35,14 +35,14 @@ namespace {
struct BaseOffset {
/// DerivedClass - The derived class.
const CXXRecordDecl *DerivedClass;
-
+
/// VirtualBase - If the path from the derived class to the base class
/// involves virtual base classes, this holds the declaration of the last
/// virtual base in this path (i.e. closest to the base class).
const CXXRecordDecl *VirtualBase;
/// NonVirtualOffset - The offset from the derived class to the base class.
- /// (Or the offset from the virtual base class to the base class, if the
+ /// (Or the offset from the virtual base class to the base class, if the
/// path from the derived class to the base class involves a virtual base
/// class.
CharUnits NonVirtualOffset;
@@ -51,7 +51,7 @@ struct BaseOffset {
NonVirtualOffset(CharUnits::Zero()) { }
BaseOffset(const CXXRecordDecl *DerivedClass,
const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
- : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
+ : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
NonVirtualOffset(NonVirtualOffset) { }
bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; }
@@ -81,19 +81,19 @@ private:
/// MostDerivedClass - The most derived class for which the final overriders
/// are stored.
const CXXRecordDecl *MostDerivedClass;
-
- /// MostDerivedClassOffset - If we're building final overriders for a
+
+ /// MostDerivedClassOffset - If we're building final overriders for a
/// construction vtable, this holds the offset from the layout class to the
/// most derived class.
const CharUnits MostDerivedClassOffset;
- /// LayoutClass - The class we're using for layout information. Will be
+ /// LayoutClass - The class we're using for layout information. Will be
/// different than the most derived class if the final overriders are for a
- /// construction vtable.
- const CXXRecordDecl *LayoutClass;
+ /// construction vtable.
+ const CXXRecordDecl *LayoutClass;
ASTContext &Context;
-
+
/// MostDerivedClassLayout - the AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
@@ -103,19 +103,19 @@ private:
typedef llvm::DenseMap<MethodBaseOffsetPairTy,
OverriderInfo> OverridersMapTy;
-
- /// OverridersMap - The final overriders for all virtual member functions of
+
+ /// OverridersMap - The final overriders for all virtual member functions of
/// all the base subobjects of the most derived class.
OverridersMapTy OverridersMap;
-
+
/// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
/// as a record decl and a subobject number) and its offsets in the most
/// derived class as well as the layout class.
- typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
+ typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
CharUnits> SubobjectOffsetMapTy;
typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
-
+
/// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
/// given base.
void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
@@ -125,40 +125,40 @@ private:
SubobjectCountMapTy &SubobjectCounts);
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
-
+
/// dump - dump the final overriders for a base subobject, and all its direct
/// and indirect base subobjects.
void dump(raw_ostream &Out, BaseSubobject Base,
VisitedVirtualBasesSetTy& VisitedVirtualBases);
-
+
public:
FinalOverriders(const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
const CXXRecordDecl *LayoutClass);
/// getOverrider - Get the final overrider for the given method declaration in
- /// the subobject with the given base offset.
- OverriderInfo getOverrider(const CXXMethodDecl *MD,
+ /// the subobject with the given base offset.
+ OverriderInfo getOverrider(const CXXMethodDecl *MD,
CharUnits BaseOffset) const {
- assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
+ assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
"Did not find overrider!");
-
+
return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
}
-
+
/// dump - dump the final overriders.
void dump() {
VisitedVirtualBasesSetTy VisitedVirtualBases;
- dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+ dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
VisitedVirtualBases);
}
-
+
};
FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
const CXXRecordDecl *LayoutClass)
- : MostDerivedClass(MostDerivedClass),
+ : MostDerivedClass(MostDerivedClass),
MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
Context(MostDerivedClass->getASTContext()),
MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
@@ -167,10 +167,10 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
SubobjectOffsetMapTy SubobjectOffsets;
SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
SubobjectCountMapTy SubobjectCounts;
- ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+ ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
/*IsVirtual=*/false,
- MostDerivedClassOffset,
- SubobjectOffsets, SubobjectLayoutClassOffsets,
+ MostDerivedClassOffset,
+ SubobjectOffsets, SubobjectLayoutClassOffsets,
SubobjectCounts);
// Get the final overriders.
@@ -183,10 +183,10 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
for (const auto &M : Methods) {
unsigned SubobjectNumber = M.first;
- assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
+ assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
SubobjectNumber)) &&
"Did not find subobject offset!");
-
+
CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
SubobjectNumber)];
@@ -198,12 +198,12 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
std::make_pair(OverriderRD, Method.Subobject))
&& "Did not find subobject offset!");
CharUnits OverriderOffset =
- SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
+ SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
Method.Subobject)];
OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
assert(!Overrider.Method && "Overrider should not exist yet!");
-
+
Overrider.Offset = OverriderOffset;
Overrider.Method = Method.Method;
Overrider.VirtualBase = Method.InVirtualSubobject;
@@ -235,11 +235,11 @@ static BaseOffset ComputeBaseOffset(const ASTContext &Context,
break;
}
}
-
+
// Now compute the non-virtual offset.
for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
const CXXBasePathElement &Element = Path[I];
-
+
// Check the base class offset.
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
@@ -247,12 +247,12 @@ static BaseOffset ComputeBaseOffset(const ASTContext &Context,
NonVirtualOffset += Layout.getBaseClassOffset(Base);
}
-
+
// FIXME: This should probably use CharUnits or something. Maybe we should
- // even change the base offsets in ASTRecordLayout to be specified in
+ // even change the base offsets in ASTRecordLayout to be specified in
// CharUnits.
return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
-
+
}
static BaseOffset ComputeBaseOffset(const ASTContext &Context,
@@ -268,67 +268,67 @@ static BaseOffset ComputeBaseOffset(const ASTContext &Context,
}
static BaseOffset
-ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
+ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
const CXXMethodDecl *DerivedMD,
const CXXMethodDecl *BaseMD) {
const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
-
+
// Canonicalize the return types.
CanQualType CanDerivedReturnType =
Context.getCanonicalType(DerivedFT->getReturnType());
CanQualType CanBaseReturnType =
Context.getCanonicalType(BaseFT->getReturnType());
- assert(CanDerivedReturnType->getTypeClass() ==
- CanBaseReturnType->getTypeClass() &&
+ assert(CanDerivedReturnType->getTypeClass() ==
+ CanBaseReturnType->getTypeClass() &&
"Types must have same type class!");
-
+
if (CanDerivedReturnType == CanBaseReturnType) {
// No adjustment needed.
return BaseOffset();
}
-
+
if (isa<ReferenceType>(CanDerivedReturnType)) {
- CanDerivedReturnType =
+ CanDerivedReturnType =
CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
- CanBaseReturnType =
+ CanBaseReturnType =
CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
} else if (isa<PointerType>(CanDerivedReturnType)) {
- CanDerivedReturnType =
+ CanDerivedReturnType =
CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
- CanBaseReturnType =
+ CanBaseReturnType =
CanBaseReturnType->getAs<PointerType>()->getPointeeType();
} else {
llvm_unreachable("Unexpected return type!");
}
-
+
// We need to compare unqualified types here; consider
// const T *Base::foo();
// T *Derived::foo();
- if (CanDerivedReturnType.getUnqualifiedType() ==
+ if (CanDerivedReturnType.getUnqualifiedType() ==
CanBaseReturnType.getUnqualifiedType()) {
// No adjustment needed.
return BaseOffset();
}
-
- const CXXRecordDecl *DerivedRD =
+
+ const CXXRecordDecl *DerivedRD =
cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
-
- const CXXRecordDecl *BaseRD =
+
+ const CXXRecordDecl *BaseRD =
cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
return ComputeBaseOffset(Context, BaseRD, DerivedRD);
}
-void
+void
FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
CharUnits OffsetInLayoutClass,
SubobjectOffsetMapTy &SubobjectOffsets,
SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
SubobjectCountMapTy &SubobjectCounts) {
const CXXRecordDecl *RD = Base.getBase();
-
+
unsigned SubobjectNumber = 0;
if (!IsVirtual)
SubobjectNumber = ++SubobjectCounts[RD];
@@ -336,13 +336,13 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
// Set up the subobject to offset mapping.
assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
&& "Subobject offset already exists!");
- assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
+ assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
&& "Subobject offset already exists!");
SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset();
SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
OffsetInLayoutClass;
-
+
// Traverse our bases.
for (const auto &B : RD->bases()) {
const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
@@ -358,19 +358,19 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
Context.getASTRecordLayout(LayoutClass);
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
- BaseOffsetInLayoutClass =
+ BaseOffsetInLayoutClass =
LayoutClassLayout.getVBaseClassOffset(BaseDecl);
} else {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
CharUnits Offset = Layout.getBaseClassOffset(BaseDecl);
-
+
BaseOffset = Base.getBaseOffset() + Offset;
BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
}
- ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset),
- B.isVirtual(), BaseOffsetInLayoutClass,
- SubobjectOffsets, SubobjectLayoutClassOffsets,
+ ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset),
+ B.isVirtual(), BaseOffsetInLayoutClass,
+ SubobjectOffsets, SubobjectLayoutClassOffsets,
SubobjectCounts);
}
}
@@ -382,7 +382,7 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
for (const auto &B : RD->bases()) {
const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
-
+
// Ignore bases that don't have any virtual member functions.
if (!BaseDecl->isPolymorphic())
continue;
@@ -393,7 +393,7 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
// We've visited this base before.
continue;
}
-
+
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
} else {
BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
@@ -431,19 +431,19 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
Offset.VirtualBase->printQualifiedName(Out);
Out << " vbase, ";
}
-
+
Out << Offset.NonVirtualOffset.getQuantity() << " nv]";
}
-
+
Out << "\n";
- }
+ }
}
/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
struct VCallOffsetMap {
-
+
typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
-
+
/// Offsets - Keeps track of methods and their offsets.
// FIXME: This should be a real map and not a vector.
SmallVector<MethodAndOffsetPairTy, 16> Offsets;
@@ -458,11 +458,11 @@ public:
/// add was successful, or false if there was already a member function with
/// the same signature in the map.
bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset);
-
+
/// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
/// vtable address point) for the given virtual member function.
CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD);
-
+
// empty - Return whether the offset map is empty or not.
bool empty() const { return Offsets.empty(); }
};
@@ -489,13 +489,13 @@ bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
const CXXMethodDecl *RHS) {
assert(LHS->isVirtual() && "LHS must be virtual!");
assert(RHS->isVirtual() && "LHS must be virtual!");
-
+
// A destructor can share a vcall offset with another destructor.
if (isa<CXXDestructorDecl>(LHS))
return isa<CXXDestructorDecl>(RHS);
// FIXME: We need to check more things here.
-
+
// The methods must have the same name.
DeclarationName LHSName = LHS->getDeclName();
DeclarationName RHSName = RHS->getDeclName();
@@ -506,14 +506,14 @@ bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
return HasSameVirtualSignature(LHS, RHS);
}
-bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
+bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
CharUnits OffsetOffset) {
// Check if we can reuse an offset.
for (const auto &OffsetPair : Offsets) {
if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
return false;
}
-
+
// Add the offset.
Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
return true;
@@ -525,36 +525,36 @@ CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
return OffsetPair.second;
}
-
+
llvm_unreachable("Should always find a vcall offset offset!");
}
/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
class VCallAndVBaseOffsetBuilder {
public:
- typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
VBaseOffsetOffsetsMapTy;
private:
/// MostDerivedClass - The most derived class for which we're building vcall
/// and vbase offsets.
const CXXRecordDecl *MostDerivedClass;
-
- /// LayoutClass - The class we're using for layout information. Will be
+
+ /// LayoutClass - The class we're using for layout information. Will be
/// different than the most derived class if we're building a construction
/// vtable.
const CXXRecordDecl *LayoutClass;
-
+
/// Context - The ASTContext which we will use for layout information.
ASTContext &Context;
/// Components - vcall and vbase offset components
typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy;
VTableComponentVectorTy Components;
-
+
/// VisitedVirtualBases - Visited virtual bases.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
-
+
/// VCallOffsets - Keeps track of vcall offsets.
VCallOffsetMap VCallOffsets;
@@ -562,7 +562,7 @@ private:
/// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
/// relative to the address point.
VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
-
+
/// FinalOverriders - The final overriders of the most derived class.
/// (Can be null when we're not building a vtable of the most derived class).
const FinalOverriders *Overriders;
@@ -571,48 +571,48 @@ private:
/// given base subobject.
void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
CharUnits RealBaseOffset);
-
+
/// AddVCallOffsets - Add vcall offsets for the given base subobject.
void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset);
-
+
/// AddVBaseOffsets - Add vbase offsets for the given class.
- void AddVBaseOffsets(const CXXRecordDecl *Base,
+ void AddVBaseOffsets(const CXXRecordDecl *Base,
CharUnits OffsetInLayoutClass);
-
+
/// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
/// chars, relative to the vtable address point.
CharUnits getCurrentOffsetOffset() const;
-
+
public:
VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
const CXXRecordDecl *LayoutClass,
const FinalOverriders *Overriders,
BaseSubobject Base, bool BaseIsVirtual,
CharUnits OffsetInLayoutClass)
- : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
+ : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
-
+
// Add vcall and vbase offsets.
AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
}
-
+
/// Methods for iterating over the components.
typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
const_iterator components_begin() const { return Components.rbegin(); }
const_iterator components_end() const { return Components.rend(); }
-
+
const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
return VBaseOffsetOffsets;
}
};
-
-void
+
+void
VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
bool BaseIsVirtual,
CharUnits RealBaseOffset) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
-
+
// Itanium C++ ABI 2.5.2:
// ..in classes sharing a virtual table with a primary base class, the vcall
// and vbase offsets added by the derived class all come before the vcall
@@ -626,16 +626,16 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
CharUnits PrimaryBaseOffset;
-
+
// Get the base offset of the primary base.
if (PrimaryBaseIsVirtual) {
assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
"Primary vbase should have a zero offset!");
-
+
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
-
- PrimaryBaseOffset =
+
+ PrimaryBaseOffset =
MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
} else {
assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
@@ -657,19 +657,19 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
}
CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
- // OffsetIndex is the index of this vcall or vbase offset, relative to the
+ // OffsetIndex is the index of this vcall or vbase offset, relative to the
// vtable address point. (We subtract 3 to account for the information just
// above the address point, the RTTI info, the offset to top, and the
// vcall offset itself).
int64_t OffsetIndex = -(int64_t)(3 + Components.size());
-
- CharUnits PointerWidth =
+
+ CharUnits PointerWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
CharUnits OffsetOffset = PointerWidth * OffsetIndex;
return OffsetOffset;
}
-void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
+void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
CharUnits VBaseOffset) {
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -687,7 +687,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
VBaseOffset);
}
-
+
// Add the vcall offsets.
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
@@ -695,7 +695,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
MD = MD->getCanonicalDecl();
CharUnits OffsetOffset = getCurrentOffsetOffset();
-
+
// Don't add a vcall offset if we already have one for this member function
// signature.
if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
@@ -705,20 +705,20 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
if (Overriders) {
// Get the final overrider.
- FinalOverriders::OverriderInfo Overrider =
+ FinalOverriders::OverriderInfo Overrider =
Overriders->getOverrider(MD, Base.getBaseOffset());
-
- /// The vcall offset is the offset from the virtual base to the object
+
+ /// The vcall offset is the offset from the virtual base to the object
/// where the function was overridden.
Offset = Overrider.Offset - VBaseOffset;
}
-
+
Components.push_back(
VTableComponent::MakeVCallOffset(Offset));
}
// And iterate over all non-virtual bases (ignoring the primary base).
- for (const auto &B : RD->bases()) {
+ for (const auto &B : RD->bases()) {
if (B.isVirtual())
continue;
@@ -727,18 +727,18 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
continue;
// Get the base offset of this base.
- CharUnits BaseOffset = Base.getBaseOffset() +
+ CharUnits BaseOffset = Base.getBaseOffset() +
Layout.getBaseClassOffset(BaseDecl);
-
- AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
+
+ AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
VBaseOffset);
}
}
-void
+void
VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
CharUnits OffsetInLayoutClass) {
- const ASTRecordLayout &LayoutClassLayout =
+ const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
// Add vbase offsets.
@@ -747,7 +747,7 @@ VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
// Check if this is a virtual base that we haven't visited before.
if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
- CharUnits Offset =
+ CharUnits Offset =
LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
// Add the vbase offset offset.
@@ -770,12 +770,12 @@ VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
/// ItaniumVTableBuilder - Class for building vtable layout information.
class ItaniumVTableBuilder {
public:
- /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
+ /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
/// primary bases.
- typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
+ typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
PrimaryBasesSetVectorTy;
-
- typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
VBaseOffsetOffsetsMapTy;
typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy;
@@ -785,7 +785,7 @@ public:
private:
/// VTables - Global vtable information.
ItaniumVTableContext &VTables;
-
+
/// MostDerivedClass - The most derived class for which we're building this
/// vtable.
const CXXRecordDecl *MostDerivedClass;
@@ -793,19 +793,19 @@ private:
/// MostDerivedClassOffset - If we're building a construction vtable, this
/// holds the offset from the layout class to the most derived class.
const CharUnits MostDerivedClassOffset;
-
- /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
+
+ /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
/// base. (This only makes sense when building a construction vtable).
bool MostDerivedClassIsVirtual;
-
- /// LayoutClass - The class we're using for layout information. Will be
+
+ /// LayoutClass - The class we're using for layout information. Will be
/// different than the most derived class if we're building a construction
/// vtable.
const CXXRecordDecl *LayoutClass;
-
+
/// Context - The ASTContext which we will use for layout information.
ASTContext &Context;
-
+
/// FinalOverriders - The final overriders of the most derived class.
const FinalOverriders Overriders;
@@ -828,29 +828,29 @@ private:
struct MethodInfo {
/// BaseOffset - The base offset of this method.
const CharUnits BaseOffset;
-
+
/// BaseOffsetInLayoutClass - The base offset in the layout class of this
/// method.
const CharUnits BaseOffsetInLayoutClass;
-
+
/// VTableIndex - The index in the vtable that this method has.
/// (For destructors, this is the index of the complete destructor).
const uint64_t VTableIndex;
-
- MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
+
+ MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
uint64_t VTableIndex)
- : BaseOffset(BaseOffset),
+ : BaseOffset(BaseOffset),
BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
VTableIndex(VTableIndex) { }
-
- MethodInfo()
- : BaseOffset(CharUnits::Zero()),
- BaseOffsetInLayoutClass(CharUnits::Zero()),
+
+ MethodInfo()
+ : BaseOffset(CharUnits::Zero()),
+ BaseOffsetInLayoutClass(CharUnits::Zero()),
VTableIndex(0) { }
};
-
+
typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
-
+
/// MethodInfoMap - The information for all methods in the vtable we're
/// currently building.
MethodInfoMapTy MethodInfoMap;
@@ -860,25 +860,25 @@ private:
MethodVTableIndicesTy MethodVTableIndices;
typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
-
- /// VTableThunks - The thunks by vtable index in the vtable currently being
+
+ /// VTableThunks - The thunks by vtable index in the vtable currently being
/// built.
VTableThunksMapTy VTableThunks;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
-
+
/// Thunks - A map that contains all the thunks needed for all methods in the
/// most derived class for which the vtable is currently being built.
ThunksMapTy Thunks;
-
+
/// AddThunk - Add a thunk for the given method.
void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
-
+
/// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
/// part of the vtable we're currently building.
void ComputeThisAdjustments();
-
+
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
/// PrimaryVirtualBases - All known virtual bases who are a primary base of
@@ -888,7 +888,7 @@ private:
/// ComputeReturnAdjustment - Compute the return adjustment given a return
/// adjustment base offset.
ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
-
+
/// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
/// the 'this' pointer from the base subobject to the derived subobject.
BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
@@ -897,8 +897,8 @@ private:
/// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
/// given virtual member function, its offset in the layout class and its
/// final overrider.
- ThisAdjustment
- ComputeThisAdjustment(const CXXMethodDecl *MD,
+ ThisAdjustment
+ ComputeThisAdjustment(const CXXMethodDecl *MD,
CharUnits BaseOffsetInLayoutClass,
FinalOverriders::OverriderInfo Overrider);
@@ -907,7 +907,7 @@ private:
void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
/// IsOverriderUsed - Returns whether the overrider will ever be used in this
- /// part of the vtable.
+ /// part of the vtable.
///
/// Itanium C++ ABI 2.5.2:
///
@@ -921,16 +921,16 @@ private:
/// adjustment is required and no thunk is generated. However, inside D
/// objects, A is no longer a primary base of C, so if we allowed calls to
/// C::f() to use the copy of A's vtable in the C subobject, we would need
- /// to adjust this from C* to B::A*, which would require a third-party
- /// thunk. Since we require that a call to C::f() first convert to A*,
- /// C-in-D's copy of A's vtable is never referenced, so this is not
+ /// to adjust this from C* to B::A*, which would require a third-party
+ /// thunk. Since we require that a call to C::f() first convert to A*,
+ /// C-in-D's copy of A's vtable is never referenced, so this is not
/// necessary.
bool IsOverriderUsed(const CXXMethodDecl *Overrider,
CharUnits BaseOffsetInLayoutClass,
const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
CharUnits FirstBaseOffsetInLayoutClass) const;
-
+
/// AddMethods - Add the methods of this base subobject and all its
/// primary bases to the vtable components vector.
void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
@@ -949,12 +949,12 @@ private:
/// or a direct or indirect base of a virtual base.
///
/// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
- /// in the layout class.
+ /// in the layout class.
void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
bool BaseIsMorallyVirtual,
bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass);
-
+
/// LayoutSecondaryVTables - Layout the secondary vtables for the given base
/// subobject.
///
@@ -965,18 +965,18 @@ private:
/// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
/// class hierarchy.
- void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
CharUnits OffsetInLayoutClass,
VisitedVirtualBasesSetTy &VBases);
/// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
/// given base (excluding any primary bases).
- void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
+ void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases);
/// isBuildingConstructionVTable - Return whether this vtable builder is
/// building a construction vtable.
- bool isBuildingConstructorVTable() const {
+ bool isBuildingConstructorVTable() const {
return MostDerivedClass != LayoutClass;
}
@@ -1055,16 +1055,16 @@ public:
void ItaniumVTableBuilder::AddThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk) {
- assert(!isBuildingConstructorVTable() &&
+ assert(!isBuildingConstructorVTable() &&
"Can't add thunks for construction vtable");
SmallVectorImpl<ThunkInfo> &ThunksVector = Thunks[MD];
// Check if we have this thunk already.
- if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
+ if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
ThunksVector.end())
return;
-
+
ThunksVector.push_back(Thunk);
}
@@ -1107,18 +1107,18 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
// Ignore adjustments for unused function pointers.
uint64_t VTableIndex = MethodInfo.VTableIndex;
- if (Components[VTableIndex].getKind() ==
+ if (Components[VTableIndex].getKind() ==
VTableComponent::CK_UnusedFunctionPointer)
continue;
-
+
// Get the final overrider for this method.
FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(MD, MethodInfo.BaseOffset);
-
+
// Check if we need an adjustment at all.
if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
// When a return thunk is needed by a derived class that overrides a
- // virtual base, gcc uses a virtual 'this' adjustment as well.
+ // virtual base, gcc uses a virtual 'this' adjustment as well.
// While the thunk itself might be needed by vtables in subclasses or
// in construction vtables, there doesn't seem to be a reason for using
// the thunk in this vtable. Still, we do so to match gcc.
@@ -1143,7 +1143,7 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
/// Clear the method info map.
MethodInfoMap.clear();
-
+
if (isBuildingConstructorVTable()) {
// We don't need to store thunk information for construction vtables.
return;
@@ -1153,7 +1153,7 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
const VTableComponent &Component = Components[TI.first];
const ThunkInfo &Thunk = TI.second;
const CXXMethodDecl *MD;
-
+
switch (Component.getKind()) {
default:
llvm_unreachable("Unexpected vtable component kind!");
@@ -1176,7 +1176,7 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
ReturnAdjustment
ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
ReturnAdjustment Adjustment;
-
+
if (!Offset.isEmpty()) {
if (Offset.VirtualBase) {
// Get the virtual base offset offset.
@@ -1193,7 +1193,7 @@ ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
}
-
+
return Adjustment;
}
@@ -1201,7 +1201,7 @@ BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
BaseSubobject Base, BaseSubobject Derived) const {
const CXXRecordDecl *BaseRD = Base.getBase();
const CXXRecordDecl *DerivedRD = Derived.getBase();
-
+
CXXBasePaths Paths(/*FindAmbiguities=*/true,
/*RecordPaths=*/true, /*DetectVirtual=*/true);
@@ -1214,32 +1214,32 @@ BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
-
+
if (Offset.VirtualBase) {
// If we have a virtual base class, the non-virtual offset is relative
// to the virtual base class offset.
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
-
- /// Get the virtual base offset, relative to the most derived class
+
+ /// Get the virtual base offset, relative to the most derived class
/// layout.
- OffsetToBaseSubobject +=
+ OffsetToBaseSubobject +=
LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
} else {
- // Otherwise, the non-virtual offset is relative to the derived class
+ // Otherwise, the non-virtual offset is relative to the derived class
// offset.
OffsetToBaseSubobject += Derived.getBaseOffset();
}
-
+
// Check if this path gives us the right base subobject.
if (OffsetToBaseSubobject == Base.getBaseOffset()) {
// Since we're going from the base class _to_ the derived class, we'll
// invert the non-virtual offset here.
Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
return Offset;
- }
+ }
}
-
+
return BaseOffset();
}
@@ -1249,13 +1249,13 @@ ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
// Ignore adjustments for pure virtual member functions.
if (Overrider.Method->isPure())
return ThisAdjustment();
-
- BaseSubobject OverriddenBaseSubobject(MD->getParent(),
+
+ BaseSubobject OverriddenBaseSubobject(MD->getParent(),
BaseOffsetInLayoutClass);
-
+
BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
Overrider.Offset);
-
+
// Compute the adjustment offset.
BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
OverriderBaseSubobject);
@@ -1263,7 +1263,7 @@ ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
return ThisAdjustment();
ThisAdjustment Adjustment;
-
+
if (Offset.VirtualBase) {
// Get the vcall offset map for this virtual base.
VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
@@ -1278,24 +1278,24 @@ ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
/*BaseIsVirtual=*/true,
/*OffsetInLayoutClass=*/
CharUnits::Zero());
-
+
VCallOffsets = Builder.getVCallOffsets();
}
-
+
Adjustment.Virtual.Itanium.VCallOffsetOffset =
VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
}
// Set the non-virtual part of the adjustment.
Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
-
+
return Adjustment;
}
void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
ReturnAdjustment ReturnAdjustment) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- assert(ReturnAdjustment.isEmpty() &&
+ assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
// Add both the complete destructor and the deleting destructor.
@@ -1312,7 +1312,7 @@ void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
}
/// OverridesIndirectMethodInBase - Return whether the given member function
-/// overrides any methods in the set of given bases.
+/// overrides any methods in the set of given bases.
/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
/// For example, if we have:
///
@@ -1320,7 +1320,7 @@ void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
/// struct B : A { virtual void f(); }
/// struct C : B { virtual void f(); }
///
-/// OverridesIndirectMethodInBase will return true if given C::f as the method
+/// OverridesIndirectMethodInBase will return true if given C::f as the method
/// and { A } as the set of bases.
static bool OverridesIndirectMethodInBases(
const CXXMethodDecl *MD,
@@ -1333,7 +1333,7 @@ static bool OverridesIndirectMethodInBases(
if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
return true;
}
-
+
return false;
}
@@ -1347,9 +1347,9 @@ bool ItaniumVTableBuilder::IsOverriderUsed(
return true;
// We know now that Base (or a direct or indirect base of it) is a primary
- // base in part of the class hierarchy, but not a primary base in the most
+ // base in part of the class hierarchy, but not a primary base in the most
// derived class.
-
+
// If the overrider is the first base in the primary base chain, we know
// that the overrider will be used.
if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
@@ -1365,10 +1365,10 @@ bool ItaniumVTableBuilder::IsOverriderUsed(
while (true) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
+
if (!PrimaryBase)
break;
-
+
if (Layout.isPrimaryBaseVirtual()) {
assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
"Primary base should always be at offset 0!");
@@ -1387,13 +1387,13 @@ bool ItaniumVTableBuilder::IsOverriderUsed(
assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
"Primary base should always be at offset 0!");
}
-
+
if (!PrimaryBases.insert(PrimaryBase))
llvm_unreachable("Found a duplicate primary base!");
RD = PrimaryBase;
}
-
+
// If the final overrider is an override of one of the primary bases,
// then we know that it will be used.
return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
@@ -1446,13 +1446,13 @@ void ItaniumVTableBuilder::AddMethods(
if (Layout.isPrimaryBaseVirtual()) {
assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
"Primary vbase should have a zero offset!");
-
+
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
-
- PrimaryBaseOffset =
+
+ PrimaryBaseOffset =
MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
-
+
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
@@ -1467,9 +1467,9 @@ void ItaniumVTableBuilder::AddMethods(
}
AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
- PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
+ PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
FirstBaseOffsetInLayoutClass, PrimaryBases);
-
+
if (!PrimaryBases.insert(PrimaryBase))
llvm_unreachable("Found a duplicate primary base!");
}
@@ -1486,31 +1486,31 @@ void ItaniumVTableBuilder::AddMethods(
MD = MD->getCanonicalDecl();
// Get the final overrider.
- FinalOverriders::OverriderInfo Overrider =
+ FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(MD, Base.getBaseOffset());
// Check if this virtual member function overrides a method in a primary
// base. If this is the case, and the return type doesn't require adjustment
// then we can just use the member function from the primary base.
- if (const CXXMethodDecl *OverriddenMD =
+ if (const CXXMethodDecl *OverriddenMD =
FindNearestOverriddenMethod(MD, PrimaryBases)) {
- if (ComputeReturnAdjustmentBaseOffset(Context, MD,
+ if (ComputeReturnAdjustmentBaseOffset(Context, MD,
OverriddenMD).isEmpty()) {
// Replace the method info of the overridden method with our own
// method.
- assert(MethodInfoMap.count(OverriddenMD) &&
+ assert(MethodInfoMap.count(OverriddenMD) &&
"Did not find the overridden method!");
MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
-
+
MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
OverriddenMethodInfo.VTableIndex);
assert(!MethodInfoMap.count(MD) &&
"Should not have method info for this method yet!");
-
+
MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
MethodInfoMap.erase(OverriddenMD);
-
+
// If the overridden method exists in a virtual base class or a direct
// or indirect base class of a virtual base class, we need to emit a
// thunk if we ever have a class hierarchy where the base class is not
@@ -1529,11 +1529,11 @@ void ItaniumVTableBuilder::AddMethods(
// the final overrider.
BaseOffset ReturnAdjustmentOffset =
ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
- ReturnAdjustment ReturnAdjustment =
+ ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);
// This is a virtual thunk for the most derived class, add it.
- AddThunk(Overrider.Method,
+ AddThunk(Overrider.Method,
ThunkInfo(ThisAdjustment, ReturnAdjustment));
}
}
@@ -1577,7 +1577,7 @@ void ItaniumVTableBuilder::AddMethods(
// Check if this overrider is going to be used.
const CXXMethodDecl *OverriderMD = Overrider.Method;
if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
- FirstBaseInPrimaryBaseChain,
+ FirstBaseInPrimaryBaseChain,
FirstBaseOffsetInLayoutClass)) {
Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
continue;
@@ -1587,13 +1587,13 @@ void ItaniumVTableBuilder::AddMethods(
// We don't want to do this for pure virtual member functions.
BaseOffset ReturnAdjustmentOffset;
if (!OverriderMD->isPure()) {
- ReturnAdjustmentOffset =
+ ReturnAdjustmentOffset =
ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
}
- ReturnAdjustment ReturnAdjustment =
+ ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);
-
+
AddMethod(Overrider.Method, ReturnAdjustment);
}
}
@@ -1604,14 +1604,14 @@ void ItaniumVTableBuilder::LayoutVTable() {
/*BaseIsMorallyVirtual=*/false,
MostDerivedClassIsVirtual,
MostDerivedClassOffset);
-
+
VisitedVirtualBasesSetTy VBases;
-
+
// Determine the primary virtual bases.
- DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
+ DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
VBases);
VBases.clear();
-
+
LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
// -fapple-kext adds an extra entry at end of vtbl.
@@ -1630,14 +1630,14 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
// Add vcall and vbase offsets for this vtable.
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
- Base, BaseIsVirtualInLayoutClass,
+ Base, BaseIsVirtualInLayoutClass,
OffsetInLayoutClass);
Components.append(Builder.components_begin(), Builder.components_end());
-
+
// Check if we need to add these vcall offsets.
if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
-
+
if (VCallOffsets.empty())
VCallOffsets = Builder.getVCallOffsets();
}
@@ -1659,7 +1659,7 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
// Now go through all virtual member functions and add them.
PrimaryBasesSetVectorTy PrimaryBases;
AddMethods(Base, OffsetInLayoutClass,
- Base.getBase(), OffsetInLayoutClass,
+ Base.getBase(), OffsetInLayoutClass,
PrimaryBases);
const CXXRecordDecl *RD = Base.getBase();
@@ -1692,10 +1692,10 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
+
if (!PrimaryBase)
break;
-
+
if (Layout.isPrimaryBaseVirtual()) {
// Check if this virtual primary base is a primary base in the layout
// class. If it's not, we don't want to add it.
@@ -1721,19 +1721,19 @@ ItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
bool BaseIsMorallyVirtual,
CharUnits OffsetInLayoutClass) {
// Itanium C++ ABI 2.5.2:
- // Following the primary virtual table of a derived class are secondary
+ // Following the primary virtual table of a derived class are secondary
// virtual tables for each of its proper base classes, except any primary
// base(s) with which it shares its primary virtual table.
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
+
for (const auto &B : RD->bases()) {
// Ignore virtual bases, we'll emit them later.
if (B.isVirtual())
continue;
-
+
const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
// Ignore bases that don't have a vtable.
@@ -1753,11 +1753,11 @@ ItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
// Get the base offset of this base.
CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
-
- CharUnits BaseOffsetInLayoutClass =
+
+ CharUnits BaseOffsetInLayoutClass =
OffsetInLayoutClass + RelativeBaseOffset;
-
- // Don't emit a secondary vtable for a primary base. We might however want
+
+ // Don't emit a secondary vtable for a primary base. We might however want
// to emit secondary vtables for other bases of this base.
if (BaseDecl == PrimaryBase) {
LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
@@ -1778,7 +1778,7 @@ void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
const CXXRecordDecl *RD, CharUnits OffsetInLayoutClass,
VisitedVirtualBasesSetTy &VBases) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
+
// Check if this base has a primary base.
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
@@ -1794,13 +1794,13 @@ void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
CharUnits PrimaryBaseOffsetInLayoutClass =
LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
-
- // We know that the base is not a primary base in the layout class if
+
+ // We know that the base is not a primary base in the layout class if
// the base offsets are different.
if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
IsPrimaryVirtualBase = false;
}
-
+
if (IsPrimaryVirtualBase)
PrimaryVirtualBases.insert(PrimaryBase);
}
@@ -1811,18 +1811,18 @@ void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
CharUnits BaseOffsetInLayoutClass;
-
+
if (B.isVirtual()) {
if (!VBases.insert(BaseDecl).second)
continue;
-
+
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
- BaseOffsetInLayoutClass =
+ BaseOffsetInLayoutClass =
LayoutClassLayout.getVBaseClassOffset(BaseDecl);
} else {
- BaseOffsetInLayoutClass =
+ BaseOffsetInLayoutClass =
OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
}
@@ -1846,12 +1846,12 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
VBases.insert(BaseDecl).second) {
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
- CharUnits BaseOffset =
+ CharUnits BaseOffset =
MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
-
+
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
- CharUnits BaseOffsetInLayoutClass =
+ CharUnits BaseOffsetInLayoutClass =
LayoutClassLayout.getVBaseClassOffset(BaseDecl);
LayoutPrimaryAndSecondaryVTables(
@@ -1860,7 +1860,7 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
/*BaseIsVirtualInLayoutClass=*/true,
BaseOffsetInLayoutClass);
}
-
+
// We only need to check the base for virtual base vtables if it actually
// has virtual bases.
if (BaseDecl->getNumVBases())
@@ -1897,7 +1897,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
AddressPointsByIndex.insert(std::make_pair(Index, Base));
}
-
+
for (unsigned I = 0, E = Components.size(); I != E; ++I) {
uint64_t Index = I;
@@ -1910,7 +1910,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
case VTableComponent::CK_VCallOffset:
Out << "vcall_offset ("
- << Component.getVCallOffset().getQuantity()
+ << Component.getVCallOffset().getQuantity()
<< ")";
break;
@@ -1925,17 +1925,17 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
<< Component.getOffsetToTop().getQuantity()
<< ")";
break;
-
+
case VTableComponent::CK_RTTI:
Component.getRTTIDecl()->printQualifiedName(Out);
Out << " RTTI";
break;
-
+
case VTableComponent::CK_FunctionPointer: {
const CXXMethodDecl *MD = Component.getFunctionDecl();
- std::string Str =
- PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
MD);
Out << Str;
if (MD->isPure())
@@ -1950,7 +1950,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
if (!Thunk.Return.isEmpty()) {
Out << "\n [return adjustment: ";
Out << Thunk.Return.NonVirtual << " non-virtual";
-
+
if (Thunk.Return.Virtual.Itanium.VBaseOffsetOffset) {
Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
Out << " vbase offset offset";
@@ -1963,26 +1963,26 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
if (!Thunk.This.isEmpty()) {
Out << "\n [this adjustment: ";
Out << Thunk.This.NonVirtual << " non-virtual";
-
+
if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
Out << " vcall offset offset";
}
Out << ']';
- }
+ }
}
break;
}
- case VTableComponent::CK_CompleteDtorPointer:
+ case VTableComponent::CK_CompleteDtorPointer:
case VTableComponent::CK_DeletingDtorPointer: {
- bool IsComplete =
+ bool IsComplete =
Component.getKind() == VTableComponent::CK_CompleteDtorPointer;
-
+
const CXXDestructorDecl *DD = Component.getDestructorDecl();
-
+
DD->printQualifiedName(Out);
if (IsComplete)
Out << "() [complete]";
@@ -1998,15 +1998,15 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
if (!Thunk.This.isEmpty()) {
Out << "\n [this adjustment: ";
Out << Thunk.This.NonVirtual << " non-virtual";
-
+
if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
Out << " vcall offset offset";
}
-
+
Out << ']';
- }
- }
+ }
+ }
break;
}
@@ -2014,8 +2014,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
case VTableComponent::CK_UnusedFunctionPointer: {
const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
- std::string Str =
- PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
MD);
Out << "[unused] " << Str;
if (MD->isPure())
@@ -2025,14 +2025,14 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}
Out << '\n';
-
+
// Dump the next address point.
uint64_t NextIndex = Index + 1;
if (AddressPointsByIndex.count(NextIndex)) {
if (AddressPointsByIndex.count(NextIndex) == 1) {
- const BaseSubobject &Base =
+ const BaseSubobject &Base =
AddressPointsByIndex.find(NextIndex)->second;
-
+
Out << " -- (";
Base.getBase()->printQualifiedName(Out);
Out << ", " << Base.getBaseOffset().getQuantity();
@@ -2040,7 +2040,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
} else {
CharUnits BaseOffset =
AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
-
+
// We store the class names in a set to get a stable order.
std::set<std::string> ClassNames;
for (const auto &I :
@@ -2060,10 +2060,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}
Out << '\n';
-
+
if (isBuildingConstructorVTable())
return;
-
+
if (MostDerivedClass->getNumVBases()) {
// We store the virtual base class names and their offsets in a map to get
// a stable order.
@@ -2074,7 +2074,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
CharUnits OffsetOffset = I.second;
ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
}
-
+
Out << "Virtual base offset offsets for '";
MostDerivedClass->printQualifiedName(Out);
Out << "' (";
@@ -2086,17 +2086,17 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
Out << "\n";
}
-
+
if (!Thunks.empty()) {
// We store the method names in a map to get a stable order.
std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
for (const auto &I : Thunks) {
const CXXMethodDecl *MD = I.first;
- std::string MethodName =
+ std::string MethodName =
PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
MD);
-
+
MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
}
@@ -2105,20 +2105,20 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
const CXXMethodDecl *MD = I.second;
ThunkInfoVectorTy ThunksVector = Thunks[MD];
- std::sort(ThunksVector.begin(), ThunksVector.end(),
- [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ llvm::sort(ThunksVector.begin(), ThunksVector.end(),
+ [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
assert(LHS.Method == nullptr && RHS.Method == nullptr);
return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
});
Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
-
+
for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
const ThunkInfo &Thunk = ThunksVector[I];
Out << llvm::format("%4d | ", I);
-
+
// If this function pointer has a return pointer adjustment, dump it.
if (!Thunk.Return.isEmpty()) {
Out << "return adjustment: " << Thunk.Return.NonVirtual;
@@ -2136,16 +2136,16 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
if (!Thunk.This.isEmpty()) {
Out << "this adjustment: ";
Out << Thunk.This.NonVirtual << " non-virtual";
-
+
if (Thunk.This.Virtual.Itanium.VCallOffsetOffset) {
Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
Out << " vcall offset offset";
}
}
-
+
Out << '\n';
}
-
+
Out << '\n';
}
}
@@ -2206,9 +2206,9 @@ VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices,
else
this->VTableIndices = OwningArrayRef<size_t>(VTableIndices);
- std::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
- [](const VTableLayout::VTableThunkTy &LHS,
- const VTableLayout::VTableThunkTy &RHS) {
+ llvm::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
+ [](const VTableLayout::VTableThunkTy &LHS,
+ const VTableLayout::VTableThunkTy &RHS) {
assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
"Different thunks should have unique indices!");
return LHS.first < RHS.first;
@@ -2223,10 +2223,11 @@ ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
ItaniumVTableContext::~ItaniumVTableContext() {}
uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) {
+ GD = GD.getCanonicalDecl();
MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
if (I != MethodVTableIndices.end())
return I->second;
-
+
const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
computeVTableRelatedInformation(RD);
@@ -2240,8 +2241,8 @@ CharUnits
ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase) {
ClassPairTy ClassPair(RD, VBase);
-
- VirtualBaseClassOffsetOffsetsMapTy::iterator I =
+
+ VirtualBaseClassOffsetOffsetsMapTy::iterator I =
VirtualBaseClassOffsetOffsets.find(ClassPair);
if (I != VirtualBaseClassOffsetOffsets.end())
return I->second;
@@ -2257,10 +2258,10 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
}
-
+
I = VirtualBaseClassOffsetOffsets.find(ClassPair);
assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
-
+
return I->second;
}
@@ -2297,10 +2298,10 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
// the rest of the vtable related information.
if (!RD->getNumVBases())
return;
-
+
const CXXRecordDecl *VBase =
RD->vbases_begin()->getType()->getAsCXXRecordDecl();
-
+
if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
return;
@@ -2367,8 +2368,6 @@ namespace {
class VFTableBuilder {
public:
- typedef MicrosoftVTableContext::MethodVFTableLocation MethodVFTableLocation;
-
typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
MethodVFTableLocationsTy;
@@ -2398,7 +2397,7 @@ private:
MethodVFTableLocationsTy MethodVFTableLocations;
- /// \brief Does this class have an RTTI component?
+ /// Does this class have an RTTI component?
bool HasRTTIComponent = false;
/// MethodInfo - Contains information about a method in a vtable.
@@ -2505,6 +2504,8 @@ private:
for (const auto &I : MethodInfoMap) {
const CXXMethodDecl *MD = I.first;
const MethodInfo &MI = I.second;
+ assert(MD == MD->getCanonicalDecl());
+
// Skip the methods that the MostDerivedClass didn't override
// and the entries shadowed by return adjusting thunks.
if (MD->getParent() != MostDerivedClass || MI.Shadowed)
@@ -2997,7 +2998,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
}
// In case we need a return adjustment, we'll add a new slot for
- // the overrider. Mark the overriden method as shadowed by the new slot.
+ // the overrider. Mark the overridden method as shadowed by the new slot.
OverriddenMethodInfo.Shadowed = true;
// Force a special name mangling for a return-adjusting thunk
@@ -3344,8 +3345,8 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
PathsSorted.reserve(Paths.size());
for (auto& P : Paths)
PathsSorted.push_back(*P);
- std::sort(PathsSorted.begin(), PathsSorted.end(),
- [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
+ llvm::sort(PathsSorted.begin(), PathsSorted.end(),
+ [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
return LHS.MangledPath < RHS.MangledPath;
});
bool Changed = false;
@@ -3544,6 +3545,18 @@ static void computeFullPathsForVFTables(ASTContext &Context,
}
}
+static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout,
+ const MethodVFTableLocation &LHS,
+ const MethodVFTableLocation &RHS) {
+ CharUnits L = LHS.VFPtrOffset;
+ CharUnits R = RHS.VFPtrOffset;
+ if (LHS.VBase)
+ L += Layout.getVBaseClassOffset(LHS.VBase);
+ if (RHS.VBase)
+ R += Layout.getVBaseClassOffset(RHS.VBase);
+ return L < R;
+}
+
void MicrosoftVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
assert(RD->isDynamicClass());
@@ -3555,14 +3568,14 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
{
- VPtrInfoVector VFPtrs;
- computeVTablePaths(/*ForVBTables=*/false, RD, VFPtrs);
- computeFullPathsForVFTables(Context, RD, VFPtrs);
+ auto VFPtrs = llvm::make_unique<VPtrInfoVector>();
+ computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
+ computeFullPathsForVFTables(Context, RD, *VFPtrs);
VFPtrLocations[RD] = std::move(VFPtrs);
}
MethodVFTableLocationsTy NewMethodLocations;
- for (const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) {
+ for (const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
VFTableBuilder Builder(*this, RD, *VFPtr);
VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
@@ -3574,12 +3587,15 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
EmptyAddressPointsMap);
Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
for (const auto &Loc : Builder.vtable_locations()) {
- GlobalDecl GD = Loc.first;
- MethodVFTableLocation NewLoc = Loc.second;
- auto M = NewMethodLocations.find(GD);
- if (M == NewMethodLocations.end() || NewLoc < M->second)
- NewMethodLocations[GD] = NewLoc;
+ auto Insert = NewMethodLocations.insert(Loc);
+ if (!Insert.second) {
+ const MethodVFTableLocation &NewLoc = Loc.second;
+ MethodVFTableLocation &OldLoc = Insert.first->second;
+ if (vfptrIsEarlierInMDC(Layout, NewLoc, OldLoc))
+ OldLoc = NewLoc;
+ }
}
}
@@ -3704,7 +3720,7 @@ MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) {
computeVTableRelatedInformation(RD);
assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations");
- return VFPtrLocations[RD];
+ return *VFPtrLocations[RD];
}
const VTableLayout &
@@ -3717,13 +3733,15 @@ MicrosoftVTableContext::getVFTableLayout(const CXXRecordDecl *RD,
return *VFTableLayouts[id];
}
-const MicrosoftVTableContext::MethodVFTableLocation &
+MethodVFTableLocation
MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
assert(cast<CXXMethodDecl>(GD.getDecl())->isVirtual() &&
"Only use this method for virtual methods or dtors");
if (isa<CXXDestructorDecl>(GD.getDecl()))
assert(GD.getDtorType() == Dtor_Deleting);
+ GD = GD.getCanonicalDecl();
+
MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
if (I != MethodVFTableLocations.end())
return I->second;
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 02aee4b46ddd..63f8395b8277 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -145,17 +145,22 @@ public:
ScopedIncrement ScopedDepth(&CurrentDepth);
return (DeclNode == nullptr) || traverse(*DeclNode);
}
- bool TraverseStmt(Stmt *StmtNode) {
+ bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
+ // If we need to keep track of the depth, we can't perform data recursion.
+ if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX))
+ Queue = nullptr;
+
ScopedIncrement ScopedDepth(&CurrentDepth);
- const Stmt *StmtToTraverse = StmtNode;
- if (Traversal ==
- ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
- const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode);
- if (ExprNode) {
+ Stmt *StmtToTraverse = StmtNode;
+ if (Traversal == ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
+ if (Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode))
StmtToTraverse = ExprNode->IgnoreParenImpCasts();
- }
}
- return (StmtToTraverse == nullptr) || traverse(*StmtToTraverse);
+ if (!StmtToTraverse)
+ return true;
+ if (!match(*StmtToTraverse))
+ return false;
+ return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
}
// We assume that the QualType and the contained type are on the same
// hierarchy level. Thus, we try to match either of them.
@@ -378,7 +383,7 @@ public:
}
bool TraverseDecl(Decl *DeclNode);
- bool TraverseStmt(Stmt *StmtNode);
+ bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
bool TraverseType(QualType TypeNode);
bool TraverseTypeLoc(TypeLoc TypeNode);
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
@@ -506,7 +511,7 @@ private:
TimeBucketRegion() : Bucket(nullptr) {}
~TimeBucketRegion() { setBucket(nullptr); }
- /// \brief Start timing for \p NewBucket.
+ /// Start timing for \p NewBucket.
///
/// If there was a bucket already set, it will finish the timing for that
/// other bucket.
@@ -529,7 +534,7 @@ private:
llvm::TimeRecord *Bucket;
};
- /// \brief Runs all the \p Matchers on \p Node.
+ /// Runs all the \p Matchers on \p Node.
///
/// Used by \c matchDispatch() below.
template <typename T, typename MC>
@@ -585,7 +590,7 @@ private:
}
/// @{
- /// \brief Overloads to pair the different node types to their matchers.
+ /// Overloads to pair the different node types to their matchers.
void matchDispatch(const Decl *Node) {
return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
}
@@ -747,14 +752,14 @@ private:
return false;
}
- /// \brief Bucket to record map.
+ /// Bucket to record map.
///
/// Used to get the appropriate bucket for each matcher.
llvm::StringMap<llvm::TimeRecord> TimeByBucket;
const MatchFinder::MatchersByType *Matchers;
- /// \brief Filtered list of matcher indices for each matcher kind.
+ /// Filtered list of matcher indices for each matcher kind.
///
/// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
/// kind (and derived kinds) so it is a waste to try every matcher on every
@@ -841,12 +846,12 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
}
-bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) {
+bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
if (!StmtNode) {
return true;
}
match(*StmtNode);
- return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode);
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
}
bool MatchASTVisitor::TraverseType(QualType TypeNode) {
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 0bcdd8e32804..9cea2f5efc5b 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -38,6 +38,16 @@
namespace clang {
namespace ast_matchers {
+
+AST_MATCHER_P(ObjCMessageExpr, hasAnySelectorMatcher, std::vector<std::string>,
+ Matches) {
+ std::string SelString = Node.getSelector().getAsString();
+ for (const std::string &S : Matches)
+ if (S == SelString)
+ return true;
+ return false;
+}
+
namespace internal {
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
@@ -108,7 +118,7 @@ private:
const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
};
-/// \brief A matcher that always returns true.
+/// A matcher that always returns true.
///
/// We only ever need one instance of this matcher, so we create a global one
/// and reuse it to reduce the overhead of the matcher and increase the chance
@@ -315,12 +325,22 @@ bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
return false;
}
-Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) {
+inline static
+std::vector<std::string> vectorFromRefs(ArrayRef<const StringRef *> NameRefs) {
std::vector<std::string> Names;
for (auto *Name : NameRefs)
Names.emplace_back(*Name);
- return internal::Matcher<NamedDecl>(
- new internal::HasNameMatcher(std::move(Names)));
+ return Names;
+}
+
+Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) {
+ std::vector<std::string> Names = vectorFromRefs(NameRefs);
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names));
+}
+
+Matcher<ObjCMessageExpr> hasAnySelectorFunc(
+ ArrayRef<const StringRef *> NameRefs) {
+ return hasAnySelectorMatcher(vectorFromRefs(NameRefs));
}
HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
@@ -393,7 +413,8 @@ public:
/// Return true if there are still any patterns left.
bool consumeNameSuffix(StringRef NodeName, bool CanSkip) {
for (size_t I = 0; I < Patterns.size();) {
- if (internal::consumeNameSuffix(Patterns[I].P, NodeName) ||
+ if (::clang::ast_matchers::internal::consumeNameSuffix(Patterns[I].P,
+ NodeName) ||
CanSkip) {
++I;
} else {
@@ -527,6 +548,8 @@ bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
} // end namespace internal
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAutoreleasePoolStmt>
+ autoreleasePoolStmt;
const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
translationUnitDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
@@ -605,6 +628,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
objcCategoryImplDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
objcMethodDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl>
+ blockDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> objcIvarDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
objcPropertyDecl;
@@ -654,6 +679,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
cxxOperatorCallExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr> objcIvarRefExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
@@ -739,6 +765,9 @@ const internal::VariadicOperatorMatcherFunc<
const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
internal::hasAnyNameFunc>
hasAnyName = {};
+const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, StringRef,
+ internal::hasAnySelectorFunc>
+ hasAnySelector = {};
const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {};
const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
hasDescendant = {};
@@ -772,6 +801,7 @@ const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
const AstTypeMatcher<VariableArrayType> variableArrayType;
const AstTypeMatcher<AtomicType> atomicType;
const AstTypeMatcher<AutoType> autoType;
+const AstTypeMatcher<DecltypeType> decltypeType;
const AstTypeMatcher<FunctionType> functionType;
const AstTypeMatcher<FunctionProtoType> functionProtoType;
const AstTypeMatcher<ParenType> parenType;
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
index af90e2c7eca1..c6c89351afd3 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Functions templates and classes to wrap matcher construct functions.
+/// Functions templates and classes to wrap matcher construct functions.
///
/// A collection of template function and classes that provide a generic
/// marshalling layer on top of matcher construct functions.
@@ -47,7 +47,7 @@ namespace ast_matchers {
namespace dynamic {
namespace internal {
-/// \brief Helper template class to just from argument type to the right is/get
+/// Helper template class to just from argument type to the right is/get
/// functions in VariantValue.
/// Used to verify and extract the matcher arguments below.
template <class T> struct ArgTypeTraits;
@@ -166,7 +166,7 @@ public:
}
};
-/// \brief Matcher descriptor interface.
+/// Matcher descriptor interface.
///
/// Provides a \c create() method that constructs the matcher from the provided
/// arguments, and various other methods for type introspection.
@@ -222,7 +222,7 @@ inline bool isRetKindConvertibleTo(
return false;
}
-/// \brief Simple callback implementation. Marshaller and function are provided.
+/// Simple callback implementation. Marshaller and function are provided.
///
/// This class wraps a function of arbitrary signature and a marshaller
/// function into a MatcherDescriptor.
@@ -279,7 +279,7 @@ private:
const std::vector<ArgKind> ArgKinds;
};
-/// \brief Helper methods to extract and merge all possible typed matchers
+/// Helper methods to extract and merge all possible typed matchers
/// out of the polymorphic object.
template <class PolyMatcher>
static void mergePolyMatchers(const PolyMatcher &Poly,
@@ -293,7 +293,7 @@ static void mergePolyMatchers(const PolyMatcher &Poly,
mergePolyMatchers(Poly, Out, typename TypeList::tail());
}
-/// \brief Convert the return values of the functions into a VariantMatcher.
+/// Convert the return values of the functions into a VariantMatcher.
///
/// There are 2 cases right now: The return value is a Matcher<T> or is a
/// polymorphic matcher. For the former, we just construct the VariantMatcher.
@@ -347,7 +347,7 @@ struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T>> {
}
};
-/// \brief Variadic marshaller function.
+/// Variadic marshaller function.
template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
VariantMatcher
@@ -383,7 +383,7 @@ variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange,
return Out;
}
-/// \brief Matcher descriptor for variadic functions.
+/// Matcher descriptor for variadic functions.
///
/// This class simply wraps a VariadicFunction with the right signature to export
/// it as a MatcherDescriptor.
@@ -436,7 +436,7 @@ private:
const ArgKind ArgsKind;
};
-/// \brief Return CK_Trivial when appropriate for VariadicDynCastAllOfMatchers.
+/// Return CK_Trivial when appropriate for VariadicDynCastAllOfMatchers.
class DynCastAllOfMatcherDescriptor : public VariadicFuncMatcherDescriptor {
public:
template <typename BaseT, typename DerivedT>
@@ -470,7 +470,7 @@ private:
const ast_type_traits::ASTNodeKind DerivedKind;
};
-/// \brief Helper macros to check the arguments on all marshaller functions.
+/// Helper macros to check the arguments on all marshaller functions.
#define CHECK_ARG_COUNT(count) \
if (Args.size() != count) { \
Error->addError(NameRange, Error->ET_RegistryWrongArgCount) \
@@ -486,7 +486,7 @@ private:
return VariantMatcher(); \
}
-/// \brief 0-arg marshaller function.
+/// 0-arg marshaller function.
template <typename ReturnType>
static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName,
SourceRange NameRange,
@@ -497,7 +497,7 @@ static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName,
return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)());
}
-/// \brief 1-arg marshaller function.
+/// 1-arg marshaller function.
template <typename ReturnType, typename ArgType1>
static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName,
SourceRange NameRange,
@@ -510,7 +510,7 @@ static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName,
ArgTypeTraits<ArgType1>::get(Args[0].Value)));
}
-/// \brief 2-arg marshaller function.
+/// 2-arg marshaller function.
template <typename ReturnType, typename ArgType1, typename ArgType2>
static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName,
SourceRange NameRange,
@@ -528,7 +528,7 @@ static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName,
#undef CHECK_ARG_COUNT
#undef CHECK_ARG_TYPE
-/// \brief Helper class used to collect all the possible overloads of an
+/// Helper class used to collect all the possible overloads of an
/// argument adaptative matcher function.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename FromTypes, typename ToTypes>
@@ -544,10 +544,10 @@ private:
using AdaptativeFunc = ast_matchers::internal::ArgumentAdaptingMatcherFunc<
ArgumentAdapterT, FromTypes, ToTypes>;
- /// \brief End case for the recursion
+ /// End case for the recursion
static void collect(ast_matchers::internal::EmptyTypeList) {}
- /// \brief Recursive case. Get the overload for the head of the list, and
+ /// Recursive case. Get the overload for the head of the list, and
/// recurse to the tail.
template <typename FromTypeList>
inline void collect(FromTypeList);
@@ -556,7 +556,7 @@ private:
std::vector<std::unique_ptr<MatcherDescriptor>> &Out;
};
-/// \brief MatcherDescriptor that wraps multiple "overloads" of the same
+/// MatcherDescriptor that wraps multiple "overloads" of the same
/// matcher.
///
/// It will try every overload and generate appropriate errors for when none or
@@ -635,7 +635,7 @@ private:
std::vector<std::unique_ptr<MatcherDescriptor>> Overloads;
};
-/// \brief Variadic operator marshaller function.
+/// Variadic operator marshaller function.
class VariadicOperatorMatcherDescriptor : public MatcherDescriptor {
public:
using VarOp = DynTypedMatcher::VariadicOperator;
@@ -701,7 +701,7 @@ private:
/// Helper functions to select the appropriate marshaller functions.
/// They detect the number of arguments, arguments types and return type.
-/// \brief 0-arg overload
+/// 0-arg overload
template <typename ReturnType>
std::unique_ptr<MatcherDescriptor>
makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) {
@@ -712,7 +712,7 @@ makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) {
MatcherName, RetTypes, None);
}
-/// \brief 1-arg overload
+/// 1-arg overload
template <typename ReturnType, typename ArgType1>
std::unique_ptr<MatcherDescriptor>
makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), StringRef MatcherName) {
@@ -724,7 +724,7 @@ makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), StringRef MatcherName) {
reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AK);
}
-/// \brief 2-arg overload
+/// 2-arg overload
template <typename ReturnType, typename ArgType1, typename ArgType2>
std::unique_ptr<MatcherDescriptor>
makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2),
@@ -738,7 +738,7 @@ makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2),
reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs);
}
-/// \brief Variadic overload.
+/// Variadic overload.
template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
@@ -747,7 +747,7 @@ std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
return llvm::make_unique<VariadicFuncMatcherDescriptor>(VarFunc, MatcherName);
}
-/// \brief Overload for VariadicDynCastAllOfMatchers.
+/// Overload for VariadicDynCastAllOfMatchers.
///
/// Not strictly necessary, but DynCastAllOfMatcherDescriptor gives us better
/// completion results for that type of matcher.
@@ -759,7 +759,7 @@ std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
return llvm::make_unique<DynCastAllOfMatcherDescriptor>(VarFunc, MatcherName);
}
-/// \brief Argument adaptative overload.
+/// Argument adaptative overload.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename FromTypes, typename ToTypes>
std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
@@ -782,7 +782,7 @@ inline void AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes,
collect(typename FromTypeList::tail());
}
-/// \brief Variadic operator overload.
+/// Variadic operator overload.
template <unsigned MinCount, unsigned MaxCount>
std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
ast_matchers::internal::VariadicOperatorMatcherFunc<MinCount, MaxCount>
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
index 89e1a2695860..da8df907ba7f 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Recursive parser implementation for the matcher expression grammar.
+/// Recursive parser implementation for the matcher expression grammar.
///
//===----------------------------------------------------------------------===//
@@ -34,9 +34,9 @@ namespace clang {
namespace ast_matchers {
namespace dynamic {
-/// \brief Simple structure to hold information for one token from the parser.
+/// Simple structure to hold information for one token from the parser.
struct Parser::TokenInfo {
- /// \brief Different possible tokens.
+ /// Different possible tokens.
enum TokenKind {
TK_Eof,
TK_OpenParen,
@@ -50,7 +50,7 @@ struct Parser::TokenInfo {
TK_CodeCompletion
};
- /// \brief Some known identifiers.
+ /// Some known identifiers.
static const char* const ID_Bind;
TokenInfo() = default;
@@ -63,7 +63,7 @@ struct Parser::TokenInfo {
const char* const Parser::TokenInfo::ID_Bind = "bind";
-/// \brief Simple tokenizer for the parser.
+/// Simple tokenizer for the parser.
class Parser::CodeTokenizer {
public:
explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
@@ -78,10 +78,10 @@ public:
NextToken = getNextToken();
}
- /// \brief Returns but doesn't consume the next token.
+ /// Returns but doesn't consume the next token.
const TokenInfo &peekNextToken() const { return NextToken; }
- /// \brief Consumes and returns the next token.
+ /// Consumes and returns the next token.
TokenInfo consumeNextToken() {
TokenInfo ThisToken = NextToken;
NextToken = getNextToken();
@@ -185,7 +185,7 @@ private:
return Result;
}
- /// \brief Consume an unsigned and float literal.
+ /// Consume an unsigned and float literal.
void consumeNumberLiteral(TokenInfo *Result) {
bool isFloatingLiteral = false;
unsigned Length = 1;
@@ -238,7 +238,7 @@ private:
Result->Kind = TokenInfo::TK_Error;
}
- /// \brief Consume a string literal.
+ /// Consume a string literal.
///
/// \c Code must be positioned at the start of the literal (the opening
/// quote). Consumed until it finds the same closing quote character.
@@ -272,7 +272,7 @@ private:
Result->Kind = TokenInfo::TK_Error;
}
- /// \brief Consume all leading whitespace from \c Code.
+ /// Consume all leading whitespace from \c Code.
void consumeWhitespace() {
while (!Code.empty() && isWhitespace(Code[0])) {
if (Code[0] == '\n') {
@@ -326,7 +326,7 @@ struct Parser::ScopedContextEntry {
}
};
-/// \brief Parse expressions that start with an identifier.
+/// Parse expressions that start with an identifier.
///
/// This function can parse named values and matchers.
/// In case of failure it will try to determine the user's intent to give
@@ -359,7 +359,7 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
return parseMatcherExpressionImpl(NameToken, Value);
}
-/// \brief Parse and validate a matcher expression.
+/// Parse and validate a matcher expression.
/// \return \c true on success, in which case \c Value has the matcher parsed.
/// If the input is malformed, or some argument has an error, it
/// returns \c false.
@@ -524,7 +524,7 @@ void Parser::addExpressionCompletions() {
}
}
-/// \brief Parse an <Expresssion>
+/// Parse an <Expression>
bool Parser::parseExpressionImpl(VariantValue *Value) {
switch (Tokenizer->nextTokenKind()) {
case TokenInfo::TK_Literal:
@@ -619,8 +619,8 @@ Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
P.parseExpressionImpl(&Dummy);
// Sort by specificity, then by name.
- std::sort(P.Completions.begin(), P.Completions.end(),
- [](const MatcherCompletion &A, const MatcherCompletion &B) {
+ llvm::sort(P.Completions.begin(), P.Completions.end(),
+ [](const MatcherCompletion &A, const MatcherCompletion &B) {
if (A.Specificity != B.Specificity)
return A.Specificity > B.Specificity;
return A.TypedText < B.TypedText;
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 2b7bb7a2120d..4d2d76f6a75b 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Registry map populated at static initialization time.
+/// Registry map populated at static initialization time.
//
//===----------------------------------------------------------------------===//
@@ -90,7 +90,7 @@ void RegistryMaps::registerMatcher(
REGISTER_MATCHER_OVERLOAD(name); \
} while (false)
-/// \brief Generate a registry map with all the known matchers.
+/// Generate a registry map with all the known matchers.
RegistryMaps::RegistryMaps() {
// TODO: Here is the list of the missing matchers, grouped by reason.
//
@@ -134,8 +134,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(atomicExpr);
REGISTER_MATCHER(atomicType);
REGISTER_MATCHER(autoType);
+ REGISTER_MATCHER(autoreleasePoolStmt)
REGISTER_MATCHER(binaryOperator);
REGISTER_MATCHER(binaryConditionalOperator);
+ REGISTER_MATCHER(blockDecl);
REGISTER_MATCHER(blockPointerType);
REGISTER_MATCHER(booleanType);
REGISTER_MATCHER(breakStmt);
@@ -186,6 +188,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(decayedType);
REGISTER_MATCHER(decl);
REGISTER_MATCHER(declaratorDecl);
+ REGISTER_MATCHER(decltypeType);
REGISTER_MATCHER(declCountIs);
REGISTER_MATCHER(declRefExpr);
REGISTER_MATCHER(declStmt);
@@ -281,11 +284,13 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasParent);
REGISTER_MATCHER(hasQualifier);
REGISTER_MATCHER(hasRangeInit);
+ REGISTER_MATCHER(hasReceiver);
REGISTER_MATCHER(hasReceiverType);
REGISTER_MATCHER(hasReplacementType);
REGISTER_MATCHER(hasReturnValue);
REGISTER_MATCHER(hasRHS);
REGISTER_MATCHER(hasSelector);
+ REGISTER_MATCHER(hasAnySelector);
REGISTER_MATCHER(hasSingleDecl);
REGISTER_MATCHER(hasSize);
REGISTER_MATCHER(hasSizeExpr);
@@ -296,6 +301,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasTemplateArgument);
REGISTER_MATCHER(hasThen);
REGISTER_MATCHER(hasThreadStorageDuration);
+ REGISTER_MATCHER(hasTrailingReturn);
REGISTER_MATCHER(hasTrueExpression);
REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
@@ -321,6 +327,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isAnyPointer);
REGISTER_MATCHER(isArray);
REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isAssignmentOperator);
REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isBitField);
REGISTER_MATCHER(isCatchAll);
@@ -344,6 +351,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isImplicit);
REGISTER_MATCHER(isExpansionInFileMatching);
REGISTER_MATCHER(isExpansionInMainFile);
+ REGISTER_MATCHER(isInstanceMessage);
REGISTER_MATCHER(isInstantiated);
REGISTER_MATCHER(isExpansionInSystemHeader);
REGISTER_MATCHER(isInteger);
@@ -351,15 +359,18 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isInTemplateInstantiation);
REGISTER_MATCHER(isLambda);
REGISTER_MATCHER(isListInitialization);
+ REGISTER_MATCHER(isMain);
REGISTER_MATCHER(isMemberInitializer);
REGISTER_MATCHER(isMoveAssignmentOperator);
REGISTER_MATCHER(isMoveConstructor);
+ REGISTER_MATCHER(isNoReturn);
REGISTER_MATCHER(isNoThrow);
REGISTER_MATCHER(isOverride);
REGISTER_MATCHER(isPrivate);
REGISTER_MATCHER(isProtected);
REGISTER_MATCHER(isPublic);
REGISTER_MATCHER(isPure);
+ REGISTER_MATCHER(isScoped);
REGISTER_MATCHER(isSignedInteger);
REGISTER_MATCHER(isStaticStorageClass);
REGISTER_MATCHER(isStruct);
@@ -399,6 +410,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(objcImplementationDecl);
REGISTER_MATCHER(objcInterfaceDecl);
REGISTER_MATCHER(objcIvarDecl);
+ REGISTER_MATCHER(objcIvarRefExpr);
REGISTER_MATCHER(objcMessageExpr);
REGISTER_MATCHER(objcMethodDecl);
REGISTER_MATCHER(objcObjectPointerType);
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 57858d00acb4..06d95eaa7563 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Polymorphic value type.
+/// Polymorphic value type.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
index 181edff0a03f..9557f68452ff 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -1,4 +1,4 @@
-//== AnalysisDeclContext.cpp - Analysis context for Path Sens analysis -*- C++ -*-//
+//===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,67 +7,72 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines AnalysisDeclContext, a class that manages the analysis context
-// data for path sensitive analysis.
+// This file defines AnalysisDeclContext, a class that manages the analysis
+// context data for path sensitive analysis.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/AST/ASTContext.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/LambdaCapture.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#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"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
using namespace clang;
-typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap;
+using ManagedAnalysisMap = llvm::DenseMap<const void *, ManagedAnalysis *>;
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *d,
const CFG::BuildOptions &buildOptions)
- : Manager(Mgr),
- D(d),
- cfgBuildOptions(buildOptions),
- forcedBlkExprs(nullptr),
- builtCFG(false),
- builtCompleteCFG(false),
- ReferencedBlockVars(nullptr),
- ManagedAnalyses(nullptr)
-{
+ : Manager(Mgr), D(d), cfgBuildOptions(buildOptions) {
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *d)
-: Manager(Mgr),
- D(d),
- forcedBlkExprs(nullptr),
- builtCFG(false),
- builtCompleteCFG(false),
- ReferencedBlockVars(nullptr),
- ManagedAnalyses(nullptr)
-{
+ : Manager(Mgr), D(d) {
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
AnalysisDeclContextManager::AnalysisDeclContextManager(
ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
bool addInitializers, bool addTemporaryDtors, bool addLifetime,
- bool addLoopExit, bool synthesizeBodies, bool addStaticInitBranch,
- bool addCXXNewAllocator, CodeInjector *injector)
+ bool addLoopExit, bool addScopes, bool synthesizeBodies,
+ bool addStaticInitBranch, bool addCXXNewAllocator,
+ bool addRichCXXConstructors, bool markElidedCXXConstructors,
+ CodeInjector *injector)
: Injector(injector), FunctionBodyFarm(ASTCtx, injector),
SynthesizeBodies(synthesizeBodies) {
cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
@@ -76,15 +81,18 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(
cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
cfgBuildOptions.AddLifetime = addLifetime;
cfgBuildOptions.AddLoopExit = addLoopExit;
+ cfgBuildOptions.AddScopes = addScopes;
cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
+ cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
+ cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
}
void AnalysisDeclContextManager::clear() { Contexts.clear(); }
Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
IsAutosynthesized = false;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
Stmt *Body = FD->getBody();
if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
Body = CoroBody->getBody();
@@ -97,7 +105,7 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
}
return Body;
}
- else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
Stmt *Body = MD->getBody();
if (Manager && Manager->synthesizeBodies()) {
Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD);
@@ -107,10 +115,9 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
}
}
return Body;
- } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getBody();
- else if (const FunctionTemplateDecl *FunTmpl
- = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
return FunTmpl->getTemplatedDecl()->getBody();
llvm_unreachable("unknown code decl");
@@ -139,15 +146,15 @@ static bool isSelfDecl(const VarDecl *VD) {
}
const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getSelfDecl();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ if (const auto *BD = dyn_cast<BlockDecl>(D)) {
// See if 'self' was captured by the block.
for (const auto &I : BD->captures()) {
const VarDecl *VD = I.getVariable();
if (isSelfDecl(VD))
return dyn_cast<ImplicitParamDecl>(VD);
- }
+ }
}
auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
@@ -158,7 +165,7 @@ const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
if (!parent->isLambda())
return nullptr;
- for (const LambdaCapture &LC : parent->captures()) {
+ for (const auto &LC : parent->captures()) {
if (!LC.capturesVariable())
continue;
@@ -174,7 +181,7 @@ void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
if (!forcedBlkExprs)
forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
// Default construct an entry for 'stmt'.
- if (const Expr *e = dyn_cast<Expr>(stmt))
+ if (const auto *e = dyn_cast<Expr>(stmt))
stmt = e->IgnoreParens();
(void) (*forcedBlkExprs)[stmt];
}
@@ -182,9 +189,9 @@ void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
const CFGBlock *
AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
assert(forcedBlkExprs);
- if (const Expr *e = dyn_cast<Expr>(stmt))
+ if (const auto *e = dyn_cast<Expr>(stmt))
stmt = e->IgnoreParens();
- CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
+ CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
forcedBlkExprs->find(stmt);
assert(itr != forcedBlkExprs->end());
return itr->second;
@@ -244,7 +251,7 @@ CFG *AnalysisDeclContext::getUnoptimizedCFG() {
CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
if (cfgStmtMap)
return cfgStmtMap.get();
-
+
if (CFG *c = getCFG()) {
cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
return cfgStmtMap.get();
@@ -256,7 +263,7 @@ CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
if (CFA)
return CFA.get();
-
+
if (CFG *c = getCFG()) {
CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
return CFA.get();
@@ -266,13 +273,13 @@ CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnaly
}
void AnalysisDeclContext::dumpCFG(bool ShowColors) {
- getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
+ getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
}
ParentMap &AnalysisDeclContext::getParentMap() {
if (!PM) {
PM.reset(new ParentMap(getBody()));
- if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
+ if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
for (const auto *I : C->inits()) {
PM->addStmt(I->getInit());
}
@@ -292,7 +299,7 @@ PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() {
}
AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
// that has the body.
FD->hasBody(FD);
@@ -315,7 +322,7 @@ AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
const BlockInvocationContext *
AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
- const clang::BlockDecl *BD,
+ const BlockDecl *BD,
const void *ContextData) {
return getLocationContextManager().getBlockInvocationContext(this, parent,
BD, ContextData);
@@ -323,7 +330,7 @@ AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+ const auto *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND)
return false;
@@ -336,10 +343,10 @@ bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
return ND->isStdNamespace();
}
-LocationContextManager & AnalysisDeclContext::getLocationContextManager() {
+LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
assert(Manager &&
"Cannot create LocationContexts without an AnalysisDeclContextManager!");
- return Manager->getLocationContextManager();
+ return Manager->getLocationContextManager();
}
//===----------------------------------------------------------------------===//
@@ -399,7 +406,7 @@ LocationContextManager::getStackFrame(AnalysisDeclContext *ctx,
llvm::FoldingSetNodeID ID;
StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
void *InsertPos;
- StackFrameContext *L =
+ auto *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
L = new StackFrameContext(ctx, parent, s, blk, idx);
@@ -423,7 +430,7 @@ LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
llvm::FoldingSetNodeID ID;
BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData);
void *InsertPos;
- BlockInvocationContext *L =
+ auto *L =
cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
InsertPos));
if (!L) {
@@ -437,10 +444,10 @@ LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
// LocationContext methods.
//===----------------------------------------------------------------------===//
-const StackFrameContext *LocationContext::getCurrentStackFrame() const {
+const StackFrameContext *LocationContext::getStackFrame() const {
const LocationContext *LC = this;
while (LC) {
- if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
+ if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
return SFC;
LC = LC->getParent();
}
@@ -448,7 +455,7 @@ const StackFrameContext *LocationContext::getCurrentStackFrame() const {
}
bool LocationContext::inTopFrame() const {
- return getCurrentStackFrame()->inTopFrame();
+ return getStackFrame()->inTopFrame();
}
bool LocationContext::isParentOf(const LocationContext *LC) const {
@@ -463,28 +470,53 @@ bool LocationContext::isParentOf(const LocationContext *LC) const {
return false;
}
-void LocationContext::dumpStack(raw_ostream &OS, StringRef Indent) const {
+static void printLocation(raw_ostream &OS, const SourceManager &SM,
+ SourceLocation SLoc) {
+ if (SLoc.isFileID() && SM.isInMainFile(SLoc))
+ OS << "line " << SM.getExpansionLineNumber(SLoc);
+ else
+ SLoc.print(OS, SM);
+}
+
+void LocationContext::dumpStack(
+ raw_ostream &OS, StringRef Indent, const char *NL, const char *Sep,
+ std::function<void(const LocationContext *)> printMoreInfoPerContext) const {
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
PrintingPolicy PP(Ctx.getLangOpts());
PP.TerseOutput = 1;
+ const SourceManager &SM =
+ getAnalysisDeclContext()->getASTContext().getSourceManager();
+
unsigned Frame = 0;
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
switch (LCtx->getKind()) {
case StackFrame:
- OS << Indent << '#' << Frame++ << ' ';
- cast<StackFrameContext>(LCtx)->getDecl()->print(OS, PP);
- OS << '\n';
+ OS << Indent << '#' << Frame << ' ';
+ ++Frame;
+ if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
+ OS << "Calling " << D->getQualifiedNameAsString();
+ else
+ OS << "Calling anonymous code";
+ if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
+ OS << " at ";
+ printLocation(OS, SM, S->getLocStart());
+ }
break;
case Scope:
- OS << Indent << " (scope)\n";
+ OS << "Entering scope";
break;
case Block:
- OS << Indent << " (block context: "
- << cast<BlockInvocationContext>(LCtx)->getContextData()
- << ")\n";
+ OS << "Invoking block";
+ if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
+ OS << " defined at ";
+ printLocation(OS, SM, D->getLocStart());
+ }
break;
}
+ OS << NL;
+
+ printMoreInfoPerContext(LCtx);
}
}
@@ -497,25 +529,27 @@ LLVM_DUMP_METHOD void LocationContext::dumpStack() const {
//===----------------------------------------------------------------------===//
namespace {
+
class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
- BumpVector<const VarDecl*> &BEVals;
+ BumpVector<const VarDecl *> &BEVals;
BumpVectorContext &BC;
- llvm::SmallPtrSet<const VarDecl*, 4> Visited;
- llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
+ llvm::SmallPtrSet<const VarDecl *, 4> Visited;
+ llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
+
public:
FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
BumpVectorContext &bc)
- : BEVals(bevals), BC(bc) {}
+ : BEVals(bevals), BC(bc) {}
void VisitStmt(Stmt *S) {
- for (Stmt *Child : S->children())
+ for (auto *Child : S->children())
if (Child)
Visit(Child);
}
void VisitDeclRefExpr(DeclRefExpr *DR) {
// Non-local variables are also directly modified.
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
if (!VD->hasLocalStorage()) {
if (Visited.insert(VD).second)
BEVals.push_back(VD, BC);
@@ -528,20 +562,21 @@ public:
IgnoredContexts.insert(BR->getBlockDecl());
Visit(BR->getBlockDecl()->getBody());
}
-
+
void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
- for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
+ for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
et = PE->semantics_end(); it != et; ++it) {
Expr *Semantic = *it;
- if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
Semantic = OVE->getSourceExpr();
Visit(Semantic);
}
}
};
-} // end anonymous namespace
-typedef BumpVector<const VarDecl*> DeclVec;
+} // namespace
+
+using DeclVec = BumpVector<const VarDecl *>;
static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
void *&Vec,
@@ -587,7 +622,7 @@ ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
// Cleanup.
//===----------------------------------------------------------------------===//
-ManagedAnalysis::~ManagedAnalysis() {}
+ManagedAnalysis::~ManagedAnalysis() = default;
AnalysisDeclContext::~AnalysisDeclContext() {
delete forcedBlkExprs;
@@ -600,7 +635,7 @@ AnalysisDeclContext::~AnalysisDeclContext() {
}
}
-LocationContext::~LocationContext() {}
+LocationContext::~LocationContext() = default;
LocationContextManager::~LocationContextManager() {
clear();
@@ -613,7 +648,5 @@ void LocationContextManager::clear() {
++I;
delete LC;
}
-
Contexts.clear();
}
-
diff --git a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp b/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
index 89ca8484819d..ac8fcdc912a0 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
@@ -50,33 +50,33 @@ namespace {
class ASTMaker {
public:
ASTMaker(ASTContext &C) : C(C) {}
-
+
/// Create a new BinaryOperator representing a simple assignment.
BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
-
+
/// Create a new BinaryOperator representing a comparison.
BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
BinaryOperator::Opcode Op);
-
+
/// Create a new compound stmt using the provided statements.
CompoundStmt *makeCompound(ArrayRef<Stmt*>);
-
+
/// Create a new DeclRefExpr for the referenced variable.
DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
bool RefersToEnclosingVariableOrCapture = false);
-
+
/// Create a new UnaryOperator representing a dereference.
UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
-
+
/// Create an implicit cast for an integer conversion.
Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
-
+
/// Create an implicit cast to a builtin boolean type.
ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
-
+
/// 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 *
@@ -92,10 +92,10 @@ public:
/// Create an Objective-C ivar reference.
ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
-
+
/// 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);
@@ -149,7 +149,8 @@ DeclRefExpr *ASTMaker::makeDeclRefExpr(
UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
- VK_LValue, OK_Ordinary, SourceLocation());
+ VK_LValue, OK_Ordinary, SourceLocation(),
+ /*CanOverflow*/ false);
}
ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
@@ -253,21 +254,24 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
QualType Ty = Callback->getType();
DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
- CastKind CK;
+ Expr *SubExpr;
if (Ty->isRValueReferenceType()) {
- CK = CK_LValueToRValue;
- } else {
- assert(Ty->isLValueReferenceType());
- CK = CK_FunctionToPointerDecay;
+ SubExpr = M.makeImplicitCast(
+ Call, Ty.getNonReferenceType(), CK_LValueToRValue);
+ } else if (Ty->isLValueReferenceType() &&
+ Call->getType()->isFunctionType()) {
Ty = C.getPointerType(Ty.getNonReferenceType());
+ SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
+ } else if (Ty->isLValueReferenceType()
+ && Call->getType()->isPointerType()
+ && Call->getType()->getPointeeType()->isFunctionType()){
+ SubExpr = Call;
+ } else {
+ llvm_unreachable("Unexpected state");
}
return new (C)
- CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK),
- /*args=*/CallArgs,
- /*QualType=*/C.VoidTy,
- /*ExprValueType=*/VK_RValue,
- /*SourceLocation=*/SourceLocation());
+ CallExpr(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, SourceLocation());
}
static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
@@ -313,7 +317,7 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
/// }
/// \endcode
static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
- DEBUG(llvm::dbgs() << "Generating body for call_once\n");
+ LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n");
// We need at least two parameters.
if (D->param_size() < 2)
@@ -338,12 +342,12 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
// 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());
+ auto *FlagRecordDecl = FlagType->getAsRecordDecl();
if (!FlagRecordDecl) {
- DEBUG(llvm::dbgs() << "Flag field is not a record: "
- << "unknown std::call_once implementation, "
- << "ignoring the call.\n");
+ LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
+ << "unknown std::call_once implementation, "
+ << "ignoring the call.\n");
return nullptr;
}
@@ -358,16 +362,17 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
}
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.");
+ LLVM_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.");
+ LLVM_DEBUG(llvm::dbgs()
+ << "Not supported: synthesizing body for functors when "
+ << "body farming std::call_once, ignoring the call.");
return nullptr;
}
@@ -394,9 +399,9 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
// 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");
+ LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
+ << "params passed to std::call_once, "
+ << "ignoring the call\n");
return nullptr;
}
@@ -405,6 +410,16 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
// reference.
for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
+ if (PDecl &&
+ CallbackFunctionType->getParamType(ParamIdx - 2)
+ .getNonReferenceType()
+ .getCanonicalType() !=
+ PDecl->getType().getNonReferenceType().getCanonicalType()) {
+ LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
+ << "params passed to std::call_once, "
+ << "ignoring the call\n");
+ return nullptr;
+ }
Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
QualType PTy = PDecl->getType().getNonReferenceType();
@@ -441,7 +456,8 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
/* opc=*/ UO_LNot,
/* QualType=*/ C.IntTy,
/* ExprValueKind=*/ VK_RValue,
- /* ExprObjectKind=*/ OK_Ordinary, SourceLocation());
+ /* ExprObjectKind=*/ OK_Ordinary, SourceLocation(),
+ /* CanOverflow*/ false);
// Create assignment.
BinaryOperator *FlagAssignment = M.makeAssignment(
@@ -490,9 +506,9 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
// block();
// }
// }
-
+
ASTMaker M(C);
-
+
// (1) Create the call.
CallExpr *CE = new (C) CallExpr(
/*ASTContext=*/C,
@@ -505,7 +521,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
// (2) Create the assignment to the predicate.
Expr *DoneValue =
new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy,
- VK_RValue, OK_Ordinary, SourceLocation());
+ VK_RValue, OK_Ordinary, SourceLocation(),
+ /*CanOverflow*/false);
BinaryOperator *B =
M.makeAssignment(
@@ -515,11 +532,11 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
PredicateTy),
M.makeIntegralCast(DoneValue, PredicateTy),
PredicateTy);
-
+
// (3) Create the compound statement.
Stmt *Stmts[] = { B, CE };
CompoundStmt *CS = M.makeCompound(Stmts);
-
+
// (4) Create the 'if' condition.
ImplicitCastExpr *LValToRval =
M.makeLvalueToRvalue(
@@ -559,7 +576,7 @@ static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
// void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
// block();
// }
- //
+ //
ASTMaker M(C);
DeclRefExpr *DR = M.makeDeclRefExpr(PV);
ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
@@ -595,16 +612,16 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
const ParmVarDecl *NewValue = D->getParamDecl(1);
QualType NewValueTy = NewValue->getType();
-
+
assert(OldValueTy == NewValueTy);
-
+
const ParmVarDecl *TheValue = D->getParamDecl(2);
QualType TheValueTy = TheValue->getType();
const PointerType *PT = TheValueTy->getAs<PointerType>();
if (!PT)
return nullptr;
QualType PointeeTy = PT->getPointeeType();
-
+
ASTMaker M(C);
// Construct the comparison.
Expr *Comparison =
@@ -626,29 +643,29 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
PointeeTy),
M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
NewValueTy);
-
+
Expr *BoolVal = M.makeObjCBool(true);
Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
: M.makeIntegralCast(BoolVal, ResultTy);
Stmts[1] = M.makeReturn(RetVal);
CompoundStmt *Body = M.makeCompound(Stmts);
-
+
// Construct the else clause.
BoolVal = M.makeObjCBool(false);
RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
: M.makeIntegralCast(BoolVal, ResultTy);
Stmt *Else = M.makeReturn(RetVal);
-
+
/// Construct the If.
Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
Comparison, Body, SourceLocation(), Else);
- return If;
+ return If;
}
Stmt *BodyFarm::getBody(const FunctionDecl *D) {
D = D->getCanonicalDecl();
-
+
Optional<Stmt *> &Val = Bodies[D];
if (Val.hasValue())
return Val.getValue();
@@ -675,7 +692,7 @@ Stmt *BodyFarm::getBody(const FunctionDecl *D) {
.Case("dispatch_once", create_dispatch_once)
.Default(nullptr);
}
-
+
if (FF) { Val = FF(C, D); }
else if (Injector) { Val = Injector->getBody(D); }
return Val.getValue();
@@ -813,4 +830,3 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
return Val.getValue();
}
-
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
index 714b85d3a9ff..97829de7ace3 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -29,6 +29,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h"
@@ -144,7 +145,7 @@ static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) {
namespace {
class CFGBuilder;
-
+
/// The CFG builder uses a recursive algorithm to build the CFG. When
/// we process an expression, sometimes we know that we must add the
/// subexpressions as block-level expressions. For example:
@@ -233,6 +234,13 @@ public:
assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
return &Scope->Vars[VarIter - 1];
}
+
+ const VarDecl *getFirstVarInScope() const {
+ assert(Scope && "Dereferencing invalid iterator is not allowed");
+ assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
+ return Scope->Vars[0];
+ }
+
VarDecl *operator*() const {
return *this->operator->();
}
@@ -266,11 +274,12 @@ public:
int distance(const_iterator L);
const_iterator shared_parent(const_iterator L);
+ bool pointsToFirstDeclaredVar() { return VarIter == 1; }
};
private:
BumpVectorContext ctx;
-
+
/// Automatic variables in order of declaration.
AutomaticVarsTy Vars;
@@ -357,7 +366,7 @@ class TryResult {
public:
TryResult() = default;
TryResult(bool b) : X(b ? 1 : 0) {}
-
+
bool isTrue() const { return X == 1; }
bool isFalse() const { return X == 0; }
bool isKnown() const { return X >= 0; }
@@ -472,13 +481,22 @@ class CFGBuilder {
using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
LabelSetTy AddressTakenLabels;
+ // Information about the currently visited C++ object construction site.
+ // This is set in the construction trigger and read when the constructor
+ // or a function that returns an object by value is being visited.
+ llvm::DenseMap<Expr *, const ConstructionContextLayer *>
+ ConstructionContextMap;
+
+ using DeclsWithEndedScopeSetTy = llvm::SmallSetVector<VarDecl *, 16>;
+ DeclsWithEndedScopeSetTy DeclsWithEndedScope;
+
bool badCFG = false;
const CFG::BuildOptions &BuildOpts;
-
+
// State to track for building switch statements.
bool switchExclusivelyCovered = false;
Expr::EvalResult *switchCond = nullptr;
-
+
CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;
const Stmt *lastLookup = nullptr;
@@ -491,13 +509,14 @@ public:
explicit CFGBuilder(ASTContext *astContext,
const CFG::BuildOptions &buildOpts)
: Context(astContext), cfg(new CFG()), // crew a new CFG
- BuildOpts(buildOpts) {}
+ ConstructionContextMap(), BuildOpts(buildOpts) {}
+
// buildCFG - Used by external clients to construct the CFG.
std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement);
bool alwaysAdd(const Stmt *stmt);
-
+
private:
// Visitors to walk an AST and construct the CFG.
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
@@ -541,6 +560,8 @@ private:
Stmt *Term,
CFGBlock *TrueBlock,
CFGBlock *FalseBlock);
+ CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
+ AddStmtChoice asc);
CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
@@ -548,6 +569,7 @@ private:
CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
+ CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
CFGBlock *VisitReturnStmt(ReturnStmt *R);
CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
@@ -566,6 +588,12 @@ private:
CFGBlock *VisitChildren(Stmt *S);
CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
+ void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,
+ const Stmt *S) {
+ if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
+ appendScopeBegin(B, VD, S);
+ }
+
/// When creating the CFG for temporary destructors, we want to mirror the
/// branch structure of the corresponding constructor calls.
/// Thus, while visiting a statement for temporary destructors, we keep a
@@ -643,6 +671,43 @@ private:
return Block;
}
+ // Remember to apply the construction context based on the current \p Layer
+ // when constructing the CFG element for \p CE.
+ void consumeConstructionContext(const ConstructionContextLayer *Layer,
+ Expr *E);
+
+ // Scan \p Child statement to find constructors in it, while keeping in mind
+ // that its parent statement is providing a partial construction context
+ // described by \p Layer. If a constructor is found, it would be assigned
+ // the context based on the layer. If an additional construction context layer
+ // is found, the function recurses into that.
+ void findConstructionContexts(const ConstructionContextLayer *Layer,
+ Stmt *Child);
+
+ // Scan all arguments of a call expression for a construction context.
+ // These sorts of call expressions don't have a common superclass,
+ // hence strict duck-typing.
+ template <typename CallLikeExpr,
+ typename = typename std::enable_if<
+ std::is_same<CallLikeExpr, CallExpr>::value ||
+ std::is_same<CallLikeExpr, CXXConstructExpr>::value ||
+ std::is_same<CallLikeExpr, ObjCMessageExpr>::value>>
+ void findConstructionContextsForArguments(CallLikeExpr *E) {
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+ Expr *Arg = E->getArg(i);
+ if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue())
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(),
+ ConstructionContextItem(E, i)),
+ Arg);
+ }
+ }
+
+ // Unset the construction context after consuming it. This is done immediately
+ // after adding the CFGConstructor or CFGCXXRecordTypedCall element, so
+ // there's no need to do this manually in every Visit... function.
+ void cleanupConstructionContext(Expr *E);
+
void autoCreateBlock() { if (!Block) Block = createBlock(); }
CFGBlock *createBlock(bool add_successor = true);
CFGBlock *createNoReturnBlock();
@@ -660,6 +725,11 @@ private:
void addAutomaticObjHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E, Stmt *S);
void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
+ void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
+ Stmt *S);
+
+ void getDeclsWithEndedScope(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt *S);
// Local scopes creation.
LocalScope* createOrReuseLocalScope(LocalScope* Scope);
@@ -671,6 +741,19 @@ private:
void addLocalScopeAndDtors(Stmt *S);
+ const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {
+ if (!BuildOpts.AddRichCXXConstructors)
+ return nullptr;
+
+ const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);
+ if (!Layer)
+ return nullptr;
+
+ cleanupConstructionContext(E);
+ return ConstructionContext::createFromLayers(cfg->getBumpVectorContext(),
+ Layer);
+ }
+
// Interface to CFGBlock - adding CFGElements.
void appendStmt(CFGBlock *B, const Stmt *S) {
@@ -682,6 +765,31 @@ private:
B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
}
+ void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
+ if (const ConstructionContext *CC =
+ retrieveAndCleanupConstructionContext(CE)) {
+ B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
+ return;
+ }
+
+ // No valid construction context found. Fall back to statement.
+ B->appendStmt(CE, cfg->getBumpVectorContext());
+ }
+
+ void appendCall(CFGBlock *B, CallExpr *CE) {
+ if (alwaysAdd(CE) && cachedEntry)
+ cachedEntry->second = B;
+
+ if (const ConstructionContext *CC =
+ retrieveAndCleanupConstructionContext(CE)) {
+ B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext());
+ return;
+ }
+
+ // No valid construction context found. Fall back to statement.
+ B->appendStmt(CE, cfg->getBumpVectorContext());
+ }
+
void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
B->appendInitializer(I, cfg->getBumpVectorContext());
}
@@ -698,6 +806,20 @@ private:
B->appendMemberDtor(FD, cfg->getBumpVectorContext());
}
+ void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {
+ if (alwaysAdd(ME) && cachedEntry)
+ cachedEntry->second = B;
+
+ if (const ConstructionContext *CC =
+ retrieveAndCleanupConstructionContext(ME)) {
+ B->appendCXXRecordTypedCall(ME, CC, cfg->getBumpVectorContext());
+ return;
+ }
+
+ B->appendStmt(const_cast<ObjCMessageExpr *>(ME),
+ cfg->getBumpVectorContext());
+ }
+
void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
}
@@ -725,6 +847,11 @@ private:
LocalScope::const_iterator B,
LocalScope::const_iterator E);
+ const VarDecl *
+ prependAutomaticObjScopeEndWithTerminator(CFGBlock *Blk,
+ LocalScope::const_iterator B,
+ LocalScope::const_iterator E);
+
void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
cfg->getBumpVectorContext());
@@ -737,7 +864,27 @@ private:
cfg->getBumpVectorContext());
}
- /// \brief Find a relational comparison with an expression evaluating to a
+ void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->appendScopeBegin(VD, S, cfg->getBumpVectorContext());
+ }
+
+ void prependScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->prependScopeBegin(VD, S, cfg->getBumpVectorContext());
+ }
+
+ void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());
+ }
+
+ void prependScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->prependScopeEnd(VD, S, cfg->getBumpVectorContext());
+ }
+
+ /// Find a relational comparison with an expression evaluating to a
/// boolean and a constant other than 0 and 1.
/// e.g. if ((x < y) == 10)
TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {
@@ -850,7 +997,7 @@ private:
}
}
- /// \brief Find a pair of comparison expressions with or without parentheses
+ /// Find a pair of comparison expressions with or without parentheses
/// with a shared variable and constants and a logical operator between them
/// that always evaluates to either true or false.
/// e.g. if (x != 3 || x != 4)
@@ -953,7 +1100,7 @@ private:
bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
if (!BuildOpts.PruneTriviallyFalseEdges)
return false;
- return !S->isTypeDependent() &&
+ return !S->isTypeDependent() &&
!S->isValueDependent() &&
S->EvaluateAsRValue(outResult, *Context);
}
@@ -1006,7 +1153,7 @@ private:
return evaluateAsBooleanConditionNoCache(S);
}
- /// \brief Evaluate as boolean \param E without using the cache.
+ /// Evaluate as boolean \param E without using the cache.
TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
if (Bop->isLogicalOp()) {
@@ -1069,18 +1216,18 @@ inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
bool shouldAdd = BuildOpts.alwaysAdd(stmt);
-
+
if (!BuildOpts.forcedBlkExprs)
return shouldAdd;
- if (lastLookup == stmt) {
+ if (lastLookup == stmt) {
if (cachedEntry) {
assert(cachedEntry->first == stmt);
return true;
}
return shouldAdd;
}
-
+
lastLookup = stmt;
// Perform the lookup!
@@ -1101,7 +1248,7 @@ bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
cachedEntry = &*itr;
return true;
}
-
+
// FIXME: Add support for dependent-sized array types in C++?
// Does it even make sense to build a CFG for an uninstantiated template?
static const VariableArrayType *FindVA(const Type *t) {
@@ -1116,6 +1263,129 @@ static const VariableArrayType *FindVA(const Type *t) {
return nullptr;
}
+void CFGBuilder::consumeConstructionContext(
+ const ConstructionContextLayer *Layer, Expr *E) {
+ assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
+ isa<ObjCMessageExpr>(E)) && "Expression cannot construct an object!");
+ if (const ConstructionContextLayer *PreviouslyStoredLayer =
+ ConstructionContextMap.lookup(E)) {
+ (void)PreviouslyStoredLayer;
+ // We might have visited this child when we were finding construction
+ // contexts within its parents.
+ assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
+ "Already within a different construction context!");
+ } else {
+ ConstructionContextMap[E] = Layer;
+ }
+}
+
+void CFGBuilder::findConstructionContexts(
+ const ConstructionContextLayer *Layer, Stmt *Child) {
+ if (!BuildOpts.AddRichCXXConstructors)
+ return;
+
+ if (!Child)
+ return;
+
+ auto withExtraLayer = [this, Layer](const ConstructionContextItem &Item) {
+ return ConstructionContextLayer::create(cfg->getBumpVectorContext(), Item,
+ Layer);
+ };
+
+ switch(Child->getStmtClass()) {
+ case Stmt::CXXConstructExprClass:
+ case Stmt::CXXTemporaryObjectExprClass: {
+ // Support pre-C++17 copy elision AST.
+ auto *CE = cast<CXXConstructExpr>(Child);
+ if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
+ findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
+ }
+
+ consumeConstructionContext(Layer, CE);
+ break;
+ }
+ // FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr.
+ // FIXME: An isa<> would look much better but this whole switch is a
+ // workaround for an internal compiler error in MSVC 2015 (see r326021).
+ case Stmt::CallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
+ case Stmt::UserDefinedLiteralClass:
+ case Stmt::ObjCMessageExprClass: {
+ auto *E = cast<Expr>(Child);
+ if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(E))
+ consumeConstructionContext(Layer, E);
+ break;
+ }
+ case Stmt::ExprWithCleanupsClass: {
+ auto *Cleanups = cast<ExprWithCleanups>(Child);
+ findConstructionContexts(Layer, Cleanups->getSubExpr());
+ break;
+ }
+ case Stmt::CXXFunctionalCastExprClass: {
+ auto *Cast = cast<CXXFunctionalCastExpr>(Child);
+ findConstructionContexts(Layer, Cast->getSubExpr());
+ break;
+ }
+ case Stmt::ImplicitCastExprClass: {
+ auto *Cast = cast<ImplicitCastExpr>(Child);
+ // Should we support other implicit cast kinds?
+ switch (Cast->getCastKind()) {
+ case CK_NoOp:
+ case CK_ConstructorConversion:
+ findConstructionContexts(Layer, Cast->getSubExpr());
+ default:
+ break;
+ }
+ break;
+ }
+ case Stmt::CXXBindTemporaryExprClass: {
+ auto *BTE = cast<CXXBindTemporaryExpr>(Child);
+ findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
+ break;
+ }
+ case Stmt::MaterializeTemporaryExprClass: {
+ // Normally we don't want to search in MaterializeTemporaryExpr because
+ // it indicates the beginning of a temporary object construction context,
+ // so it shouldn't be found in the middle. However, if it is the beginning
+ // of an elidable copy or move construction context, we need to include it.
+ if (Layer->getItem().getKind() ==
+ ConstructionContextItem::ElidableConstructorKind) {
+ auto *MTE = cast<MaterializeTemporaryExpr>(Child);
+ findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
+ }
+ break;
+ }
+ case Stmt::ConditionalOperatorClass: {
+ auto *CO = cast<ConditionalOperator>(Child);
+ if (Layer->getItem().getKind() !=
+ ConstructionContextItem::MaterializationKind) {
+ // If the object returned by the conditional operator is not going to be a
+ // temporary object that needs to be immediately materialized, then
+ // it must be C++17 with its mandatory copy elision. Do not yet promise
+ // to support this case.
+ assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
+ Context->getLangOpts().CPlusPlus17);
+ break;
+ }
+ findConstructionContexts(Layer, CO->getLHS());
+ findConstructionContexts(Layer, CO->getRHS());
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void CFGBuilder::cleanupConstructionContext(Expr *E) {
+ assert(BuildOpts.AddRichCXXConstructors &&
+ "We should not be managing construction contexts!");
+ assert(ConstructionContextMap.count(E) &&
+ "Cannot exit construction context without the context!");
+ ConstructionContextMap.erase(E);
+}
+
+
/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an
/// arbitrary statement. Examples include a single expression or a function
/// body (compound statement). The ownership of the returned CFG is
@@ -1176,6 +1446,9 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
JT.scopePosition);
prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
JT.scopePosition);
+ const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
+ B, I->scopePosition, JT.scopePosition);
+ appendScopeBegin(JT.block, VD, G);
addSuccessor(B, JT.block);
}
@@ -1189,13 +1462,17 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
// If there is no target block that contains label, then we are looking
// at an incomplete AST. Handle this by not registering a successor.
if (LI == LabelMap.end()) continue;
-
+
addSuccessor(B, LI->second.block);
}
// Create an empty entry block that has no predecessors.
cfg->setEntry(createBlock());
+ if (BuildOpts.AddRichCXXConstructors)
+ assert(ConstructionContextMap.empty() &&
+ "Not all construction contexts were cleaned up!");
+
return std::move(cfg);
}
@@ -1243,6 +1520,10 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
appendInitializer(Block, I);
if (Init) {
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), I),
+ Init);
+
if (HasTemporaries) {
// For expression with temporaries go directly to subexpression to omit
// generating destructors for the second time.
@@ -1267,21 +1548,20 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
return Block;
}
-/// \brief Retrieve the type of the temporary object whose lifetime was
+/// Retrieve the type of the temporary object whose lifetime was
/// extended by a local reference with the given initializer.
-static QualType getReferenceInitTemporaryType(ASTContext &Context,
- const Expr *Init,
+static QualType getReferenceInitTemporaryType(const Expr *Init,
bool *FoundMTE = nullptr) {
while (true) {
// Skip parentheses.
Init = Init->IgnoreParens();
-
+
// Skip through cleanups.
if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) {
Init = EWC->getSubExpr();
continue;
}
-
+
// Skip through the temporary-materialization expression.
if (const MaterializeTemporaryExpr *MTE
= dyn_cast<MaterializeTemporaryExpr>(Init)) {
@@ -1290,26 +1570,17 @@ static QualType getReferenceInitTemporaryType(ASTContext &Context,
*FoundMTE = true;
continue;
}
-
- // Skip derived-to-base and no-op casts.
- if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
- if ((CE->getCastKind() == CK_DerivedToBase ||
- CE->getCastKind() == CK_UncheckedDerivedToBase ||
- CE->getCastKind() == CK_NoOp) &&
- Init->getType()->isRecordType()) {
- Init = CE->getSubExpr();
- continue;
- }
- }
-
- // Skip member accesses into rvalues.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
- if (!ME->isArrow() && ME->getBase()->isRValue()) {
- Init = ME->getBase();
- continue;
- }
+
+ // Skip sub-object accesses into rvalues.
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ const Expr *SkippedInit =
+ Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+ if (SkippedInit != Init) {
+ Init = SkippedInit;
+ continue;
}
-
+
break;
}
@@ -1325,9 +1596,34 @@ void CFGBuilder::addLoopExit(const Stmt *LoopStmt){
appendLoopExit(Block, LoopStmt);
}
+void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt *S) {
+ if (!BuildOpts.AddScopes)
+ return;
+
+ if (B == E)
+ return;
+
+ // To go from B to E, one first goes up the scopes from B to P
+ // then sideways in one scope from P to P' and then down
+ // the scopes from P' to E.
+ // The lifetime of all objects between B and P end.
+ LocalScope::const_iterator P = B.shared_parent(E);
+ int Dist = B.distance(P);
+ if (Dist <= 0)
+ return;
+
+ for (LocalScope::const_iterator I = B; I != P; ++I)
+ if (I.pointsToFirstDeclaredVar())
+ DeclsWithEndedScope.insert(*I);
+}
+
void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E,
Stmt *S) {
+ getDeclsWithEndedScope(B, E, S);
+ if (BuildOpts.AddScopes)
+ addScopesEnd(B, E, S);
if (BuildOpts.AddImplicitDtors)
addAutomaticObjDtors(B, E, S);
if (BuildOpts.AddLifetime)
@@ -1379,6 +1675,23 @@ void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
appendLifetimeEnds(Block, *I, S);
}
+/// Add to current block markers for ending scopes.
+void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt *S) {
+ // If implicit destructors are enabled, we'll add scope ends in
+ // addAutomaticObjDtors.
+ if (BuildOpts.AddImplicitDtors)
+ return;
+
+ autoCreateBlock();
+
+ for (auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend();
+ I != E; ++I)
+ appendScopeEnd(Block, *I, S);
+
+ return;
+}
+
/// addAutomaticObjDtors - Add to current block automatic objects destructors
/// for objects in range of local scope positions. Use S as trigger statement
/// for destructors.
@@ -1402,12 +1715,21 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(),
E = Decls.rend();
I != E; ++I) {
+ if (hasTrivialDestructor(*I)) {
+ // If AddScopes is enabled and *I is a first variable in a scope, add a
+ // ScopeEnd marker in a Block.
+ if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) {
+ autoCreateBlock();
+ appendScopeEnd(Block, *I, S);
+ }
+ continue;
+ }
// If this destructor is marked as a no-return destructor, we need to
// create a new block for the destructor which does not have as a successor
// anything built thus far: control won't flow out of this block.
QualType Ty = (*I)->getType();
if (Ty->isReferenceType()) {
- Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit());
+ Ty = getReferenceInitTemporaryType((*I)->getInit());
}
Ty = Context->getBaseElementType(Ty);
@@ -1416,6 +1738,9 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
else
autoCreateBlock();
+ // Add ScopeEnd just after automatic obj destructor.
+ if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I))
+ appendScopeEnd(Block, *I, S);
appendAutomaticObjDtor(Block, *I, S);
}
}
@@ -1476,9 +1801,10 @@ LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
}
/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
-/// that should create implicit scope (e.g. if/else substatements).
+/// that should create implicit scope (e.g. if/else substatements).
void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
- if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
+ if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
+ !BuildOpts.AddScopes)
return;
LocalScope *Scope = nullptr;
@@ -1503,7 +1829,8 @@ void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
/// reuse Scope if not NULL.
LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
LocalScope* Scope) {
- if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
+ if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
+ !BuildOpts.AddScopes)
return Scope;
for (auto *DI : DS->decls())
@@ -1515,7 +1842,7 @@ LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) {
// Check for const references bound to temporary. Set type to pointee.
QualType QT = VD->getType();
- if (QT.getTypePtr()->isReferenceType()) {
+ if (QT->isReferenceType()) {
// Attempt to determine whether this declaration lifetime-extends a
// temporary.
//
@@ -1525,12 +1852,16 @@ bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) {
// MaterializeTemporaryExpr instead.
const Expr *Init = VD->getInit();
- if (!Init)
+ if (!Init) {
+ // Probably an exception catch-by-reference variable.
+ // FIXME: It doesn't really mean that the object has a trivial destructor.
+ // Also are there other cases?
return true;
+ }
- // Lifetime-extending a temporary.
+ // Lifetime-extending a temporary?
bool FoundMTE = false;
- QT = getReferenceInitTemporaryType(*Context, Init, &FoundMTE);
+ QT = getReferenceInitTemporaryType(Init, &FoundMTE);
if (!FoundMTE)
return true;
}
@@ -1555,7 +1886,8 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
LocalScope* Scope) {
assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
"AddImplicitDtors and AddLifetime cannot be used at the same time");
- if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
+ if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
+ !BuildOpts.AddScopes)
return Scope;
// Check if variable is local.
@@ -1568,7 +1900,7 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
}
if (BuildOpts.AddImplicitDtors) {
- if (!hasTrivialDestructor(VD)) {
+ if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
// Add the variable to scope
Scope = createOrReuseLocalScope(Scope);
Scope->addVar(VD);
@@ -1628,6 +1960,26 @@ void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
InsertPos = Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminator());
}
+/// prependAutomaticObjScopeEndWithTerminator - Prepend scope end CFGElements for
+/// variables with automatic storage duration to CFGBlock's elements vector.
+/// Elements will be prepended to physical beginning of the vector which
+/// happens to be logical end. Use blocks terminator as statement that specifies
+/// where scope ends.
+const VarDecl *
+CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
+ CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
+ if (!BuildOpts.AddScopes)
+ return nullptr;
+ BumpVectorContext &C = cfg->getBumpVectorContext();
+ CFGBlock::iterator InsertPos =
+ Blk->beginScopeEndInsert(Blk->end(), 1, C);
+ LocalScope::const_iterator PlaceToInsert = B;
+ for (LocalScope::const_iterator I = B; I != E; ++I)
+ PlaceToInsert = I;
+ Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminator());
+ return *PlaceToInsert;
+}
+
/// 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).
@@ -1756,6 +2108,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::LambdaExprClass:
return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
+ case Stmt::MaterializeTemporaryExprClass:
+ return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
+ asc);
+
case Stmt::MemberExprClass:
return VisitMemberExpr(cast<MemberExpr>(S), asc);
@@ -1780,6 +2136,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::ObjCForCollectionStmtClass:
return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
+ case Stmt::ObjCMessageExprClass:
+ return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
+
case Stmt::OpaqueValueExprClass:
return Block;
@@ -2045,7 +2404,7 @@ static bool CanThrow(Expr *E, ASTContext &Ctx) {
if (FT) {
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) &&
- Proto->isNothrow(Ctx))
+ Proto->isNothrow())
return false;
}
return true;
@@ -2062,6 +2421,8 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
if (!boundType.isNull()) calleeType = boundType;
}
+ findConstructionContextsForArguments(C);
+
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
@@ -2078,7 +2439,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
bool OmitArguments = false;
if (FunctionDecl *FD = C->getDirectCallee()) {
- if (FD->isNoReturn())
+ if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context))
NoReturn = true;
if (FD->hasAttr<NoThrowAttr>())
AddEHEdge = false;
@@ -2098,7 +2459,10 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
}
if (!NoReturn && !AddEHEdge) {
- return VisitStmt(C, asc.withAlwaysAdd(true));
+ autoCreateBlock();
+ appendCall(Block, C);
+
+ return VisitChildren(C);
}
if (Block) {
@@ -2112,7 +2476,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
else
Block = createBlock();
- appendStmt(Block, C);
+ appendCall(Block, C);
if (AddEHEdge) {
// Add exceptional edges.
@@ -2243,7 +2607,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
// At least one of this or the above will be run.
return addStmt(BCO->getCommon());
}
-
+
return addStmt(condExpr);
}
@@ -2252,7 +2616,7 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
// CFG entirely.
if (isa<LabelDecl>(*DS->decl_begin()))
return Block;
-
+
// This case also handles static_asserts.
if (DS->isSingleDecl())
return VisitDeclSubExpr(DS);
@@ -2326,7 +2690,11 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
autoCreateBlock();
appendStmt(Block, DS);
-
+
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),
+ Init);
+
// Keep track of the last non-null block, as 'Block' can be nulled out
// if the initializer expression is something like a 'while' in a
// statement-expression.
@@ -2353,6 +2721,8 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
LastBlock = newBlock;
}
+ maybeAddScopeBeginForVarDecl(Block, VD, DS);
+
// Remove variable from local scope.
if (ScopePos && VD == *ScopePos)
++ScopePos;
@@ -2517,6 +2887,10 @@ CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) {
addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), R);
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), R),
+ R->getRetValue());
+
// If the one of the destructors does not return, we already have the Exit
// block as a successor.
if (!Block->hasNoReturnElement())
@@ -2691,7 +3065,7 @@ CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {
}
return LastBlock;
}
-
+
CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
// Goto is a control-flow statement. Thus we stop processing the current
// block and create a new one.
@@ -2805,7 +3179,7 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
else if (badCFG)
return nullptr;
}
-
+
// Because of short-circuit evaluation, the condition of the loop can span
// multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
// evaluate the condition.
@@ -2813,6 +3187,7 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
do {
Expr *C = F->getCond();
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
// Specially handle logical operators, which have a slightly
// more optimal CFG representation.
@@ -2843,9 +3218,15 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
if (VarDecl *VD = F->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
- appendStmt(Block, F->getConditionVariableDeclStmt());
+ const DeclStmt *DS = F->getConditionVariableDeclStmt();
+ assert(DS->isSingleDecl());
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),
+ Init);
+ appendStmt(Block, DS);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
+ maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
}
}
@@ -2865,13 +3246,15 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
// Link up the loop-back block to the entry condition block.
addSuccessor(TransitionBlock, EntryConditionBlock);
-
+
// The condition block is the implicit successor for any code above the loop.
Succ = EntryConditionBlock;
// If the loop contains initialization, create a new block for those
// statements. This block can also contain statements that precede the loop.
if (Stmt *I = F->getInit()) {
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+ ScopePos = LoopBeginScopePos;
Block = createBlock();
return addStmt(I);
}
@@ -2883,6 +3266,16 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
return EntryConditionBlock;
}
+CFGBlock *
+CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
+ AddStmtChoice asc) {
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),
+ MTE->getTemporary());
+
+ return VisitStmt(MTE, asc);
+}
+
CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
if (asc.alwaysAdd(*this, M)) {
autoCreateBlock();
@@ -2973,7 +3366,7 @@ CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
CFGBlock *LoopBackBlock = nullptr;
Succ = LoopBackBlock = createBlock();
LoopBackBlock->setLoopTarget(S);
-
+
BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
ContinueJumpTarget = JumpTarget(Succ, ScopePos);
@@ -3040,7 +3433,7 @@ CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
// Add the PseudoObject as the last thing.
appendStmt(Block, E);
- CFGBlock *lastBlock = Block;
+ CFGBlock *lastBlock = Block;
// Before that, evaluate all of the semantics in order. In
// CFG-land, that means appending them in reverse order.
@@ -3155,9 +3548,16 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
if (VarDecl *VD = W->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
- appendStmt(Block, W->getConditionVariableDeclStmt());
+ const DeclStmt *DS = W->getConditionVariableDeclStmt();
+ assert(DS->isSingleDecl());
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(),
+ const_cast<DeclStmt *>(DS)),
+ Init);
+ appendStmt(Block, DS);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
+ maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
}
}
@@ -3212,6 +3612,16 @@ CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
return VisitStmt(S, AddStmtChoice::AlwaysAdd);
}
+CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
+ AddStmtChoice asc) {
+ findConstructionContextsForArguments(ME);
+
+ autoCreateBlock();
+ appendObjCMessage(Block, ME);
+
+ return VisitChildren(ME);
+}
+
CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
// If we were in the middle of a block we stop processing that block.
if (badCFG)
@@ -3366,7 +3776,7 @@ CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
// VLA types have expressions that must be evaluated.
CFGBlock *lastBlock = Block;
-
+
if (E->isArgumentType()) {
for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());
VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))
@@ -3483,6 +3893,7 @@ CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
autoCreateBlock();
appendStmt(Block, Terminator->getConditionVariableDeclStmt());
LastBlock = addStmt(Init);
+ maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
}
}
@@ -3494,7 +3905,7 @@ CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
return LastBlock;
}
-
+
static bool shouldAddCase(bool &switchExclusivelyCovered,
const Expr::EvalResult *switchCond,
const CaseStmt *CS,
@@ -3509,7 +3920,7 @@ static bool shouldAddCase(bool &switchExclusivelyCovered,
// Evaluate the LHS of the case value.
const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx);
const llvm::APSInt &condInt = switchCond->Val.getInt();
-
+
if (condInt == lhsInt) {
addCase = true;
switchExclusivelyCovered = true;
@@ -3528,7 +3939,7 @@ static bool shouldAddCase(bool &switchExclusivelyCovered,
else
addCase = true;
}
- return addCase;
+ return addCase;
}
CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
@@ -3700,7 +4111,7 @@ CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
CFGBlock *CatchBlock = Block;
if (!CatchBlock)
CatchBlock = createBlock();
-
+
// CXXCatchStmt is more than just a label. They have semantic meaning
// as well, as they implicitly "initialize" the catch variable. Add
// it to the CFG as a CFGElement so that the control-flow of these
@@ -3863,6 +4274,10 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
autoCreateBlock();
appendStmt(Block, E);
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), E),
+ E->getSubExpr());
+
// We do not want to propagate the AlwaysAdd property.
asc = asc.withAlwaysAdd(false);
}
@@ -3871,8 +4286,13 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
AddStmtChoice asc) {
+ // If the constructor takes objects as arguments by value, we need to properly
+ // construct these objects. Construction contexts we find here aren't for the
+ // constructor C, they're for its arguments only.
+ findConstructionContextsForArguments(C);
+
autoCreateBlock();
- appendStmt(Block, C);
+ appendConstructor(Block, C);
return VisitChildren(C);
}
@@ -3882,15 +4302,23 @@ CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
autoCreateBlock();
appendStmt(Block, NE);
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), NE),
+ const_cast<CXXConstructExpr *>(NE->getConstructExpr()));
+
if (NE->getInitializer())
Block = Visit(NE->getInitializer());
+
if (BuildOpts.AddCXXNewAllocator)
appendNewAllocator(Block, NE);
+
if (NE->isArray())
Block = Visit(NE->getArraySize());
+
for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(),
E = NE->placement_arg_end(); I != E; ++I)
Block = Visit(*I);
+
return Block;
}
@@ -3925,7 +4353,7 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
AddStmtChoice asc) {
autoCreateBlock();
- appendStmt(Block, C);
+ appendConstructor(Block, C);
return VisitChildren(C);
}
@@ -4027,9 +4455,11 @@ tryAgain:
auto *LE = cast<LambdaExpr>(E);
CFGBlock *B = Block;
for (Expr *Init : LE->capture_inits()) {
- if (CFGBlock *R = VisitForTemporaryDtors(
- Init, /*BindToTemporary=*/false, Context))
- B = R;
+ if (Init) {
+ if (CFGBlock *R = VisitForTemporaryDtors(
+ Init, /*BindToTemporary=*/false, Context))
+ B = R;
+ }
}
return B;
}
@@ -4210,11 +4640,15 @@ std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement,
const CXXDestructorDecl *
CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
switch (getKind()) {
- case CFGElement::Statement:
case CFGElement::Initializer:
case CFGElement::NewAllocator:
case CFGElement::LoopExit:
case CFGElement::LifetimeEnds:
+ case CFGElement::Statement:
+ case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
llvm_unreachable("getDestructorDecl should only be used with "
"ImplicitDtors");
case CFGElement::AutomaticObjectDtor: {
@@ -4227,7 +4661,7 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
// temporary in an initializer expression.
if (ty->isReferenceType()) {
if (const Expr *Init = var->getInit()) {
- ty = getReferenceInitTemporaryType(astContext, Init);
+ ty = getReferenceInitTemporaryType(Init);
}
}
@@ -4237,7 +4671,7 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
const RecordType *recordType = ty->getAs<RecordType>();
const CXXRecordDecl *classDecl =
cast<CXXRecordDecl>(recordType->getDecl());
- return classDecl->getDestructor();
+ return classDecl->getDestructor();
}
case CFGElement::DeleteDtor: {
const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
@@ -4335,7 +4769,7 @@ public:
for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
unsigned j = 1;
for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
- BI != BEnd; ++BI, ++j ) {
+ BI != BEnd; ++BI, ++j ) {
if (Optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
const Stmt *stmt= SE->getStmt();
std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
@@ -4343,8 +4777,8 @@ public:
switch (stmt->getStmtClass()) {
case Stmt::DeclStmtClass:
- DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
- break;
+ DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
+ break;
case Stmt::IfStmtClass: {
const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
if (var)
@@ -4544,6 +4978,106 @@ public:
} // namespace
+static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper,
+ const CXXCtorInitializer *I) {
+ if (I->isBaseInitializer())
+ OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
+ else if (I->isDelegatingInitializer())
+ OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName();
+ else
+ OS << I->getAnyMember()->getName();
+ OS << "(";
+ if (Expr *IE = I->getInit())
+ IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
+ OS << ")";
+
+ if (I->isBaseInitializer())
+ OS << " (Base initializer)";
+ else if (I->isDelegatingInitializer())
+ OS << " (Delegating initializer)";
+ else
+ OS << " (Member initializer)";
+}
+
+static void print_construction_context(raw_ostream &OS,
+ StmtPrinterHelper &Helper,
+ const ConstructionContext *CC) {
+ SmallVector<const Stmt *, 3> Stmts;
+ switch (CC->getKind()) {
+ case ConstructionContext::SimpleConstructorInitializerKind: {
+ OS << ", ";
+ const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
+ print_initializer(OS, Helper, SICC->getCXXCtorInitializer());
+ return;
+ }
+ case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: {
+ OS << ", ";
+ const auto *CICC =
+ cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
+ print_initializer(OS, Helper, CICC->getCXXCtorInitializer());
+ Stmts.push_back(CICC->getCXXBindTemporaryExpr());
+ break;
+ }
+ case ConstructionContext::SimpleVariableKind: {
+ const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
+ Stmts.push_back(SDSCC->getDeclStmt());
+ break;
+ }
+ case ConstructionContext::CXX17ElidedCopyVariableKind: {
+ const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
+ Stmts.push_back(CDSCC->getDeclStmt());
+ Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
+ break;
+ }
+ case ConstructionContext::NewAllocatedObjectKind: {
+ const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
+ Stmts.push_back(NECC->getCXXNewExpr());
+ break;
+ }
+ case ConstructionContext::SimpleReturnedValueKind: {
+ const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
+ Stmts.push_back(RSCC->getReturnStmt());
+ break;
+ }
+ case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
+ const auto *RSCC =
+ cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
+ Stmts.push_back(RSCC->getReturnStmt());
+ Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
+ break;
+ }
+ case ConstructionContext::SimpleTemporaryObjectKind: {
+ const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
+ Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
+ Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
+ break;
+ }
+ case ConstructionContext::ElidedTemporaryObjectKind: {
+ const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
+ Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
+ Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
+ Stmts.push_back(TOCC->getConstructorAfterElision());
+ break;
+ }
+ case ConstructionContext::ArgumentKind: {
+ const auto *ACC = cast<ArgumentConstructionContext>(CC);
+ if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
+ OS << ", ";
+ Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
+ }
+ OS << ", ";
+ Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
+ OS << "+" << ACC->getIndex();
+ return;
+ }
+ }
+ for (auto I: Stmts)
+ if (I) {
+ OS << ", ";
+ Helper.handledStmt(const_cast<Stmt *>(I), OS);
+ }
+}
+
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CFGElement &E) {
if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
@@ -4573,16 +5107,23 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
}
S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
- if (isa<CXXOperatorCallExpr>(S)) {
+ if (auto VTC = E.getAs<CFGCXXRecordTypedCall>()) {
+ if (isa<CXXOperatorCallExpr>(S))
+ OS << " (OperatorCall)";
+ OS << " (CXXRecordTypedCall";
+ print_construction_context(OS, Helper, VTC->getConstructionContext());
+ OS << ")";
+ } else if (isa<CXXOperatorCallExpr>(S)) {
OS << " (OperatorCall)";
- }
- else if (isa<CXXBindTemporaryExpr>(S)) {
+ } else if (isa<CXXBindTemporaryExpr>(S)) {
OS << " (BindTemporary)";
- }
- else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {
- OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")";
- }
- else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {
+ } else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {
+ OS << " (CXXConstructExpr";
+ if (Optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) {
+ print_construction_context(OS, Helper, CE->getConstructionContext());
+ }
+ OS << ", " << CCE->getType().getAsString() << ")";
+ } else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {
OS << " (" << CE->getStmtClassName() << ", "
<< CE->getCastKindName()
<< ", " << CE->getType().getAsString()
@@ -4593,32 +5134,19 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
if (isa<Expr>(S))
OS << '\n';
} else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) {
- const CXXCtorInitializer *I = IE->getInitializer();
- if (I->isBaseInitializer())
- OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
- else if (I->isDelegatingInitializer())
- OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName();
- else OS << I->getAnyMember()->getName();
-
- OS << "(";
- if (Expr *IE = I->getInit())
- IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
- OS << ")";
-
- if (I->isBaseInitializer())
- OS << " (Base initializer)\n";
- else if (I->isDelegatingInitializer())
- OS << " (Delegating initializer)\n";
- else OS << " (Member initializer)\n";
+ print_initializer(OS, Helper, IE->getInitializer());
+ OS << '\n';
} else if (Optional<CFGAutomaticObjDtor> DE =
E.getAs<CFGAutomaticObjDtor>()) {
const VarDecl *VD = DE->getVarDecl();
Helper.handleDecl(VD, OS);
- const Type* T = VD->getType().getTypePtr();
- if (const ReferenceType* RT = T->getAs<ReferenceType>())
- T = RT->getPointeeType().getTypePtr();
- T = T->getBaseElementTypeUnsafe();
+ ASTContext &ACtx = VD->getASTContext();
+ QualType T = VD->getType();
+ if (T->isReferenceType())
+ T = getReferenceInitTemporaryType(VD->getInit(), nullptr);
+ if (const ArrayType *AT = ACtx.getAsArrayType(T))
+ T = ACtx.getBaseElementType(AT);
OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
OS << " (Implicit destructor)\n";
@@ -4630,6 +5158,16 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
} else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) {
const Stmt *LoopStmt = LE->getLoopStmt();
OS << LoopStmt->getStmtClassName() << " (LoopExit)\n";
+ } else if (Optional<CFGScopeBegin> SB = E.getAs<CFGScopeBegin>()) {
+ OS << "CFGScopeBegin(";
+ if (const VarDecl *VD = SB->getVarDecl())
+ OS << VD->getQualifiedNameAsString();
+ OS << ")\n";
+ } else if (Optional<CFGScopeEnd> SE = E.getAs<CFGScopeEnd>()) {
+ OS << "CFGScopeEnd(";
+ if (const VarDecl *VD = SE->getVarDecl())
+ OS << VD->getQualifiedNameAsString();
+ OS << ")\n";
} else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
OS << "CFGNewAllocator(";
if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
@@ -4671,7 +5209,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
// Print the header.
if (ShowColors)
OS.changeColor(raw_ostream::YELLOW, true);
-
+
OS << "\n [B" << B.getBlockID();
if (&B == &cfg->getEntry())
@@ -4684,7 +5222,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
OS << " (NORETURN)]\n";
else
OS << "]\n";
-
+
if (ShowColors)
OS.resetColor();
@@ -4755,7 +5293,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
TPrinter.print(B.getTerminator());
OS << '\n';
-
+
if (ShowColors)
OS.resetColor();
}
@@ -4774,7 +5312,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
if (ShowColors)
OS.changeColor(Color);
-
+
for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
I != E; ++I, ++i) {
if (i % 10 == 8)
@@ -4791,7 +5329,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
if (!Reachable)
OS << "(Unreachable)";
}
-
+
if (ShowColors)
OS.resetColor();
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
index 4ae135f1ea77..cdad5b57aee8 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -1,4 +1,4 @@
-//==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==//
+//===- CFGReachabilityAnalysis.cpp - Basic reachability analysis ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,26 +13,27 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallVector.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
using namespace clang;
-CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg)
- : analyzed(cfg.getNumBlockIDs(), false) {}
+CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(
+ const CFG &cfg)
+ : analyzed(cfg.getNumBlockIDs(), false) {}
bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
const CFGBlock *Dst) {
-
const unsigned DstBlockID = Dst->getBlockID();
-
+
// If we haven't analyzed the destination node, run the analysis now
if (!analyzed[DstBlockID]) {
mapReachability(Dst);
analyzed[DstBlockID] = true;
}
-
+
// Return the cached result
return reachable[DstBlockID][Src->getBlockID()];
}
@@ -42,10 +43,10 @@ bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
SmallVector<const CFGBlock *, 11> worklist;
llvm::BitVector visited(analyzed.size());
-
+
ReachableSet &DstReachability = reachable[Dst->getBlockID()];
DstReachability.resize(analyzed.size(), false);
-
+
// Start searching from the destination node, since we commonly will perform
// multiple queries relating to a destination node.
worklist.push_back(Dst);
@@ -57,7 +58,7 @@ void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
if (visited[block->getBlockID()])
continue;
visited[block->getBlockID()] = true;
-
+
// Update reachability information for this node -> Dst
if (!firstRun) {
// Don't insert Dst -> Dst unless it was a predecessor of itself
@@ -65,9 +66,9 @@ void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
}
else
firstRun = false;
-
+
// Add the predecessors to the worklist.
- for (CFGBlock::const_pred_iterator i = block->pred_begin(),
+ for (CFGBlock::const_pred_iterator i = block->pred_begin(),
e = block->pred_end(); i != e; ++i) {
if (*i)
worklist.push_back(*i);
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp
index 19b80191f7a7..3eed0d52f848 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp
@@ -24,7 +24,7 @@ static SMap *AsMap(void *m) { return (SMap*) m; }
CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
-CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
+CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
SMap *SM = AsMap(M);
Stmt *X = S;
@@ -53,17 +53,17 @@ static void Accumulate(SMap &SM, CFGBlock *B) {
Optional<CFGStmt> CS = CE.getAs<CFGStmt>();
if (!CS)
continue;
-
+
CFGBlock *&Entry = SM[CS->getStmt()];
// If 'Entry' is already initialized (e.g., a terminator was already),
// skip.
if (Entry)
continue;
-
+
Entry = B;
-
+
}
-
+
// Look at the label of the block.
if (Stmt *Label = B->getLabel())
SM[Label] = B;
@@ -82,7 +82,7 @@ CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
SMap *SM = new SMap();
// Walk all blocks, accumulating the block-level expressions, labels,
- // and terminators.
+ // and terminators.
for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
Accumulate(*SM, *I);
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp b/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
index fb6d7e87a9a3..bac00680ffda 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
@@ -84,7 +84,7 @@ public:
void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
Selector Sel = ME->getSelector();
-
+
// Find the callee definition within the same translation unit.
Decl *D = nullptr;
if (ME->isInstanceMessage())
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp b/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp
index 098803f9a417..8912b3b76751 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp
@@ -381,7 +381,7 @@ void RecursiveCloneTypeIIHashConstraint::constrain(
for (unsigned i = 0; i < StmtsByHash.size() - 1; ++i) {
const auto Current = StmtsByHash[i];
- // It's likely that we just found an sequence of StmtSequences that
+ // It's likely that we just found a sequence of StmtSequences that
// represent a CloneGroup, so we create a new group and start checking and
// adding the StmtSequences in this sequence.
CloneDetector::CloneGroup NewGroup;
@@ -534,14 +534,14 @@ void VariablePattern::addVariableOccurence(const VarDecl *VarDecl,
// First check if we already reference this variable
for (size_t KindIndex = 0; KindIndex < Variables.size(); ++KindIndex) {
if (Variables[KindIndex] == VarDecl) {
- // If yes, add a new occurence that points to the existing entry in
+ // If yes, add a new occurrence that points to the existing entry in
// the Variables vector.
Occurences.emplace_back(KindIndex, Mention);
return;
}
}
// If this variable wasn't already referenced, add it to the list of
- // referenced variables and add a occurence that points to this new entry.
+ // referenced variables and add a occurrence that points to this new entry.
Occurences.emplace_back(Variables.size(), Mention);
Variables.push_back(VarDecl);
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
index 4d57623e2161..b2d416c171a1 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements cocoa naming convention analysis.
+// This file implements cocoa naming convention analysis.
//
//===----------------------------------------------------------------------===//
@@ -34,15 +34,15 @@ bool cocoa::isRefType(QualType RetTy, StringRef Prefix,
return false;
RetTy = TD->getDecl()->getUnderlyingType();
}
-
+
if (Name.empty())
return false;
-
+
// Is the type void*?
const PointerType* PT = RetTy->getAs<PointerType>();
if (!(PT->getPointeeType().getUnqualifiedType()->isVoidType()))
return false;
-
+
// Does the name start with the prefix?
return Name.startswith(Prefix);
}
@@ -66,32 +66,32 @@ bool coreFoundation::isCFObjectRef(QualType T) {
bool cocoa::isCocoaObjectRef(QualType Ty) {
if (!Ty->isObjCObjectPointerType())
return false;
-
+
const ObjCObjectPointerType *PT = Ty->getAs<ObjCObjectPointerType>();
-
+
// Can be true for objects with the 'NSObject' attribute.
if (!PT)
return true;
-
+
// We assume that id<..>, id, Class, and Class<..> all represent tracked
// objects.
if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
PT->isObjCClassType() || PT->isObjCQualifiedClassType())
return true;
-
+
// Does the interface subclass NSObject?
// FIXME: We can memoize here if this gets too expensive.
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
-
+
// Assume that anything declared with a forward declaration and no
// @interface subclasses NSObject.
if (!ID->hasDefinition())
return true;
-
+
for ( ; ID ; ID = ID->getSuperClass())
if (ID->getIdentifier()->getName() == "NSObject")
return true;
-
+
return false;
}
@@ -101,11 +101,11 @@ bool coreFoundation::followsCreateRule(const FunctionDecl *fn) {
const IdentifierInfo *ident = fn->getIdentifier();
if (!ident) return false;
StringRef functionName = ident->getName();
-
+
StringRef::iterator it = functionName.begin();
StringRef::iterator start = it;
StringRef::iterator endI = functionName.end();
-
+
while (true) {
// Scan for the start of 'create' or 'copy'.
for ( ; it != endI ; ++it) {
@@ -124,7 +124,7 @@ bool coreFoundation::followsCreateRule(const FunctionDecl *fn) {
// Did we hit the end of the string? If so, we didn't find a match.
if (it == endI)
return false;
-
+
// Scan for *lowercase* 'reate' or 'opy', followed by no lowercase
// character.
StringRef suffix = functionName.substr(it - start);
@@ -137,10 +137,10 @@ bool coreFoundation::followsCreateRule(const FunctionDecl *fn) {
// Keep scanning.
continue;
}
-
+
if (it == endI || !isLowercase(*it))
return true;
-
+
// If we matched a lowercase character, it isn't the end of the
// word. Keep scanning.
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ConstructionContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/ConstructionContext.cpp
new file mode 100644
index 000000000000..8169d4a93a6d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/ConstructionContext.cpp
@@ -0,0 +1,217 @@
+//===- ConstructionContext.cpp - CFG constructor information --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ConstructionContext class and its sub-classes,
+// which represent various different ways of constructing C++ objects
+// with the additional information the users may want to know about
+// the constructor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/ConstructionContext.h"
+#include "clang/AST/ExprObjC.h"
+
+using namespace clang;
+
+const ConstructionContextLayer *
+ConstructionContextLayer::create(BumpVectorContext &C,
+ const ConstructionContextItem &Item,
+ const ConstructionContextLayer *Parent) {
+ ConstructionContextLayer *CC =
+ C.getAllocator().Allocate<ConstructionContextLayer>();
+ return new (CC) ConstructionContextLayer(Item, Parent);
+}
+
+bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
+ const ConstructionContextLayer *Other) const {
+ const ConstructionContextLayer *Self = this;
+ while (true) {
+ if (!Other)
+ return Self;
+ if (!Self || !(Self->Item == Other->Item))
+ return false;
+ Self = Self->getParent();
+ Other = Other->getParent();
+ }
+ llvm_unreachable("The above loop can only be terminated via return!");
+}
+
+const ConstructionContext *
+ConstructionContext::createMaterializedTemporaryFromLayers(
+ BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
+ const CXXBindTemporaryExpr *BTE,
+ const ConstructionContextLayer *ParentLayer) {
+ assert(MTE);
+
+ // If the object requires destruction and is not lifetime-extended,
+ // then it must have a BTE within its MTE, otherwise it shouldn't.
+ // FIXME: This should be an assertion.
+ if (!BTE && !(MTE->getType().getCanonicalType()->getAsCXXRecordDecl()
+ ->hasTrivialDestructor() ||
+ MTE->getStorageDuration() != SD_FullExpression)) {
+ return nullptr;
+ }
+
+ // If the temporary is lifetime-extended, don't save the BTE,
+ // because we don't need a temporary destructor, but an automatic
+ // destructor.
+ if (MTE->getStorageDuration() != SD_FullExpression) {
+ BTE = nullptr;
+ }
+
+ // Handle pre-C++17 copy and move elision.
+ const CXXConstructExpr *ElidedCE = nullptr;
+ const ConstructionContext *ElidedCC = nullptr;
+ if (ParentLayer) {
+ const ConstructionContextItem &ElidedItem = ParentLayer->getItem();
+ assert(ElidedItem.getKind() ==
+ ConstructionContextItem::ElidableConstructorKind);
+ ElidedCE = cast<CXXConstructExpr>(ElidedItem.getStmt());
+ assert(ElidedCE->isElidable());
+ // We're creating a construction context that might have already
+ // been created elsewhere. Maybe we should unique our construction
+ // contexts. That's what we often do, but in this case it's unlikely
+ // to bring any benefits.
+ ElidedCC = createFromLayers(C, ParentLayer->getParent());
+ if (!ElidedCC) {
+ // We may fail to create the elided construction context.
+ // In this case, skip copy elision entirely.
+ return create<SimpleTemporaryObjectConstructionContext>(C, BTE, MTE);
+ }
+ return create<ElidedTemporaryObjectConstructionContext>(
+ C, BTE, MTE, ElidedCE, ElidedCC);
+ }
+
+ // This is a normal temporary.
+ assert(!ParentLayer);
+ return create<SimpleTemporaryObjectConstructionContext>(C, BTE, MTE);
+}
+
+const ConstructionContext *ConstructionContext::createBoundTemporaryFromLayers(
+ BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
+ const ConstructionContextLayer *ParentLayer) {
+ if (!ParentLayer) {
+ // A temporary object that doesn't require materialization.
+ // In particular, it shouldn't require copy elision, because
+ // copy/move constructors take a reference, which requires
+ // materialization to obtain the glvalue.
+ return create<SimpleTemporaryObjectConstructionContext>(C, BTE,
+ /*MTE=*/nullptr);
+ }
+
+ const ConstructionContextItem &ParentItem = ParentLayer->getItem();
+ switch (ParentItem.getKind()) {
+ case ConstructionContextItem::VariableKind: {
+ const auto *DS = cast<DeclStmt>(ParentItem.getStmt());
+ assert(!cast<VarDecl>(DS->getSingleDecl())->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor());
+ return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
+ }
+ case ConstructionContextItem::NewAllocatorKind: {
+ llvm_unreachable("This context does not accept a bound temporary!");
+ }
+ case ConstructionContextItem::ReturnKind: {
+ assert(ParentLayer->isLast());
+ const auto *RS = cast<ReturnStmt>(ParentItem.getStmt());
+ assert(!RS->getRetValue()->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor());
+ return create<CXX17ElidedCopyReturnedValueConstructionContext>(C, RS,
+ BTE);
+ }
+
+ case ConstructionContextItem::MaterializationKind: {
+ // No assert. We may have an elidable copy on the grandparent layer.
+ const auto *MTE = cast<MaterializeTemporaryExpr>(ParentItem.getStmt());
+ return createMaterializedTemporaryFromLayers(C, MTE, BTE,
+ ParentLayer->getParent());
+ }
+ case ConstructionContextItem::TemporaryDestructorKind: {
+ llvm_unreachable("Duplicate CXXBindTemporaryExpr in the AST!");
+ }
+ case ConstructionContextItem::ElidedDestructorKind: {
+ llvm_unreachable("Elided destructor items are not produced by the CFG!");
+ }
+ case ConstructionContextItem::ElidableConstructorKind: {
+ llvm_unreachable("Materialization is necessary to put temporary into a "
+ "copy or move constructor!");
+ }
+ case ConstructionContextItem::ArgumentKind: {
+ assert(ParentLayer->isLast());
+ const auto *E = cast<Expr>(ParentItem.getStmt());
+ assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
+ isa<ObjCMessageExpr>(E));
+ return create<ArgumentConstructionContext>(C, E, ParentItem.getIndex(),
+ BTE);
+ }
+ case ConstructionContextItem::InitializerKind: {
+ assert(ParentLayer->isLast());
+ const auto *I = ParentItem.getCXXCtorInitializer();
+ assert(!I->getAnyMember()->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor());
+ return create<CXX17ElidedCopyConstructorInitializerConstructionContext>(
+ C, I, BTE);
+ }
+ } // switch (ParentItem.getKind())
+
+ llvm_unreachable("Unexpected construction context with destructor!");
+}
+
+const ConstructionContext *ConstructionContext::createFromLayers(
+ BumpVectorContext &C, const ConstructionContextLayer *TopLayer) {
+ // Before this point all we've had was a stockpile of arbitrary layers.
+ // Now validate that it is shaped as one of the finite amount of expected
+ // patterns.
+ const ConstructionContextItem &TopItem = TopLayer->getItem();
+ switch (TopItem.getKind()) {
+ case ConstructionContextItem::VariableKind: {
+ assert(TopLayer->isLast());
+ const auto *DS = cast<DeclStmt>(TopItem.getStmt());
+ return create<SimpleVariableConstructionContext>(C, DS);
+ }
+ case ConstructionContextItem::NewAllocatorKind: {
+ assert(TopLayer->isLast());
+ const auto *NE = cast<CXXNewExpr>(TopItem.getStmt());
+ return create<NewAllocatedObjectConstructionContext>(C, NE);
+ }
+ case ConstructionContextItem::ReturnKind: {
+ assert(TopLayer->isLast());
+ const auto *RS = cast<ReturnStmt>(TopItem.getStmt());
+ return create<SimpleReturnedValueConstructionContext>(C, RS);
+ }
+ case ConstructionContextItem::MaterializationKind: {
+ const auto *MTE = cast<MaterializeTemporaryExpr>(TopItem.getStmt());
+ return createMaterializedTemporaryFromLayers(C, MTE, /*BTE=*/nullptr,
+ TopLayer->getParent());
+ }
+ case ConstructionContextItem::TemporaryDestructorKind: {
+ const auto *BTE = cast<CXXBindTemporaryExpr>(TopItem.getStmt());
+ assert(BTE->getType().getCanonicalType()->getAsCXXRecordDecl()
+ ->hasNonTrivialDestructor());
+ return createBoundTemporaryFromLayers(C, BTE, TopLayer->getParent());
+ }
+ case ConstructionContextItem::ElidedDestructorKind: {
+ llvm_unreachable("Elided destructor items are not produced by the CFG!");
+ }
+ case ConstructionContextItem::ElidableConstructorKind: {
+ llvm_unreachable("The argument needs to be materialized first!");
+ }
+ case ConstructionContextItem::InitializerKind: {
+ assert(TopLayer->isLast());
+ const CXXCtorInitializer *I = TopItem.getCXXCtorInitializer();
+ return create<SimpleConstructorInitializerConstructionContext>(C, I);
+ }
+ case ConstructionContextItem::ArgumentKind: {
+ assert(TopLayer->isLast());
+ const auto *E = cast<Expr>(TopItem.getStmt());
+ return create<ArgumentConstructionContext>(C, E, TopItem.getIndex(),
+ /*BTE=*/nullptr);
+ }
+ } // switch (TopItem.getKind())
+ llvm_unreachable("Unexpected construction context!");
+}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
index 96edad0c3019..bc81a71b3d91 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
@@ -1,4 +1,4 @@
-//===- Consumed.cpp --------------------------------------------*- C++ --*-===//
+//===- Consumed.cpp -------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,26 +13,34 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/Consumed.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
#include <memory>
+#include <utility>
// TODO: Adjust states of args to constructors in the same way that arguments to
// function calls are handled.
// TODO: Use information from tests in for- and while-loop conditional.
-// TODO: Add notes about the actual and expected state for
+// TODO: Add notes about the actual and expected state for
// TODO: Correctly identify unreachable blocks when chaining boolean operators.
// TODO: Adjust the parser and AttributesList class to support lists of
// identifiers.
@@ -49,7 +57,7 @@ using namespace clang;
using namespace consumed;
// Key method definition
-ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {}
+ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() = default;
static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
// Find the source location of the first statement in the block, if the block
@@ -63,7 +71,7 @@ static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
if (Block->succ_size() == 1 && *Block->succ_begin())
return getFirstStmtLoc(*Block->succ_begin());
- return SourceLocation();
+ return {};
}
static SourceLocation getLastStmtLoc(const CFGBlock *Block) {
@@ -109,7 +117,6 @@ static ConsumedState invertConsumedUnconsumed(ConsumedState State) {
static bool isCallableInState(const CallableWhenAttr *CWAttr,
ConsumedState State) {
-
for (const auto &S : CWAttr->callableStates()) {
ConsumedState MappedAttrState = CS_None;
@@ -117,31 +124,30 @@ static bool isCallableInState(const CallableWhenAttr *CWAttr,
case CallableWhenAttr::Unknown:
MappedAttrState = CS_Unknown;
break;
-
+
case CallableWhenAttr::Unconsumed:
MappedAttrState = CS_Unconsumed;
break;
-
+
case CallableWhenAttr::Consumed:
MappedAttrState = CS_Consumed;
break;
}
-
+
if (MappedAttrState == State)
return true;
}
-
+
return false;
}
-
static bool isConsumableType(const QualType &QT) {
if (QT->isPointerType() || QT->isReferenceType())
return false;
-
+
if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
return RD->hasAttr<ConsumableAttr>();
-
+
return false;
}
@@ -161,7 +167,6 @@ static bool isSetOnReadPtrType(const QualType &QT) {
return false;
}
-
static bool isKnownState(ConsumedState State) {
switch (State) {
case CS_Unconsumed:
@@ -245,13 +250,13 @@ static StringRef stateToString(ConsumedState State) {
switch (State) {
case consumed::CS_None:
return "none";
-
+
case consumed::CS_Unknown:
return "unknown";
-
+
case consumed::CS_Unconsumed:
return "unconsumed";
-
+
case consumed::CS_Consumed:
return "consumed";
}
@@ -270,11 +275,13 @@ static ConsumedState testsFor(const FunctionDecl *FunDecl) {
}
namespace {
+
struct VarTestResult {
const VarDecl *Var;
ConsumedState TestsFor;
};
-} // end anonymous::VarTestResult
+
+} // namespace
namespace clang {
namespace consumed {
@@ -292,7 +299,7 @@ class PropagationInfo {
IT_BinTest,
IT_Var,
IT_Tmp
- } InfoType;
+ } InfoType = IT_None;
struct BinTestTy {
const BinaryOperator *Source;
@@ -300,7 +307,7 @@ class PropagationInfo {
VarTestResult LTest;
VarTestResult RTest;
};
-
+
union {
ConsumedState State;
VarTestResult VarTest;
@@ -308,35 +315,31 @@ class PropagationInfo {
const CXXBindTemporaryExpr *Tmp;
BinTestTy BinTest;
};
-
+
public:
- PropagationInfo() : InfoType(IT_None) {}
-
+ PropagationInfo() = default;
PropagationInfo(const VarTestResult &VarTest)
- : InfoType(IT_VarTest), VarTest(VarTest) {}
-
+ : InfoType(IT_VarTest), VarTest(VarTest) {}
+
PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
- : InfoType(IT_VarTest) {
-
+ : InfoType(IT_VarTest) {
VarTest.Var = Var;
VarTest.TestsFor = TestsFor;
}
-
+
PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
const VarTestResult &LTest, const VarTestResult &RTest)
- : InfoType(IT_BinTest) {
-
+ : InfoType(IT_BinTest) {
BinTest.Source = Source;
BinTest.EOp = EOp;
BinTest.LTest = LTest;
BinTest.RTest = RTest;
}
-
+
PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
const VarDecl *LVar, ConsumedState LTestsFor,
const VarDecl *RVar, ConsumedState RTestsFor)
- : InfoType(IT_BinTest) {
-
+ : InfoType(IT_BinTest) {
BinTest.Source = Source;
BinTest.EOp = EOp;
BinTest.LTest.Var = LVar;
@@ -344,47 +347,46 @@ public:
BinTest.RTest.Var = RVar;
BinTest.RTest.TestsFor = RTestsFor;
}
-
+
PropagationInfo(ConsumedState State)
- : InfoType(IT_State), State(State) {}
-
+ : InfoType(IT_State), State(State) {}
PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
PropagationInfo(const CXXBindTemporaryExpr *Tmp)
- : InfoType(IT_Tmp), Tmp(Tmp) {}
-
- const ConsumedState & getState() const {
+ : InfoType(IT_Tmp), Tmp(Tmp) {}
+
+ const ConsumedState &getState() const {
assert(InfoType == IT_State);
return State;
}
-
- const VarTestResult & getVarTest() const {
+
+ const VarTestResult &getVarTest() const {
assert(InfoType == IT_VarTest);
return VarTest;
}
-
- const VarTestResult & getLTest() const {
+
+ const VarTestResult &getLTest() const {
assert(InfoType == IT_BinTest);
return BinTest.LTest;
}
-
- const VarTestResult & getRTest() const {
+
+ const VarTestResult &getRTest() const {
assert(InfoType == IT_BinTest);
return BinTest.RTest;
}
-
- const VarDecl * getVar() const {
+
+ const VarDecl *getVar() const {
assert(InfoType == IT_Var);
return Var;
}
-
- const CXXBindTemporaryExpr * getTmp() const {
+
+ const CXXBindTemporaryExpr *getTmp() const {
assert(InfoType == IT_Tmp);
return Tmp;
}
-
+
ConsumedState getAsState(const ConsumedStateMap *StateMap) const {
assert(isVar() || isTmp() || isState());
-
+
if (isVar())
return StateMap->getState(Var);
else if (isTmp())
@@ -394,86 +396,92 @@ public:
else
return CS_None;
}
-
+
EffectiveOp testEffectiveOp() const {
assert(InfoType == IT_BinTest);
return BinTest.EOp;
}
-
+
const BinaryOperator * testSourceNode() const {
assert(InfoType == IT_BinTest);
return BinTest.Source;
}
-
- inline bool isValid() const { return InfoType != IT_None; }
- inline bool isState() const { return InfoType == IT_State; }
- inline bool isVarTest() const { return InfoType == IT_VarTest; }
- inline bool isBinTest() const { return InfoType == IT_BinTest; }
- inline bool isVar() const { return InfoType == IT_Var; }
- inline bool isTmp() const { return InfoType == IT_Tmp; }
-
+
+ bool isValid() const { return InfoType != IT_None; }
+ bool isState() const { return InfoType == IT_State; }
+ bool isVarTest() const { return InfoType == IT_VarTest; }
+ bool isBinTest() const { return InfoType == IT_BinTest; }
+ bool isVar() const { return InfoType == IT_Var; }
+ bool isTmp() const { return InfoType == IT_Tmp; }
+
bool isTest() const {
return InfoType == IT_VarTest || InfoType == IT_BinTest;
}
-
+
bool isPointerToValue() const {
return InfoType == IT_Var || InfoType == IT_Tmp;
}
-
+
PropagationInfo invertTest() const {
assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
-
+
if (InfoType == IT_VarTest) {
return PropagationInfo(VarTest.Var,
invertConsumedUnconsumed(VarTest.TestsFor));
-
+
} else if (InfoType == IT_BinTest) {
return PropagationInfo(BinTest.Source,
BinTest.EOp == EO_And ? EO_Or : EO_And,
BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
} else {
- return PropagationInfo();
+ return {};
}
}
};
-static inline void
+} // namespace consumed
+} // namespace clang
+
+static void
setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
ConsumedState State) {
-
assert(PInfo.isVar() || PInfo.isTmp());
-
+
if (PInfo.isVar())
StateMap->setState(PInfo.getVar(), State);
else
StateMap->setState(PInfo.getTmp(), State);
}
+namespace clang {
+namespace consumed {
+
class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
-
- typedef llvm::DenseMap<const Stmt *, PropagationInfo> MapType;
- typedef std::pair<const Stmt *, PropagationInfo> PairType;
- typedef MapType::iterator InfoEntry;
- typedef MapType::const_iterator ConstInfoEntry;
-
+ using MapType = llvm::DenseMap<const Stmt *, PropagationInfo>;
+ using PairType= std::pair<const Stmt *, PropagationInfo>;
+ using InfoEntry = MapType::iterator;
+ using ConstInfoEntry = MapType::const_iterator;
+
AnalysisDeclContext &AC;
ConsumedAnalyzer &Analyzer;
ConsumedStateMap *StateMap;
MapType PropagationMap;
InfoEntry findInfo(const Expr *E) {
- if (auto Cleanups = dyn_cast<ExprWithCleanups>(E))
+ if (const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
if (!Cleanups->cleanupsHaveSideEffects())
E = Cleanups->getSubExpr();
return PropagationMap.find(E->IgnoreParens());
}
+
ConstInfoEntry findInfo(const Expr *E) const {
- if (auto Cleanups = dyn_cast<ExprWithCleanups>(E))
+ if (const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
if (!Cleanups->cleanupsHaveSideEffects())
E = Cleanups->getSubExpr();
return PropagationMap.find(E->IgnoreParens());
}
+
void insertInfo(const Expr *E, const PropagationInfo &PI) {
PropagationMap.insert(PairType(E->IgnoreParens(), PI));
}
@@ -490,7 +498,7 @@ public:
SourceLocation BlameLoc);
bool handleCall(const CallExpr *Call, const Expr *ObjArg,
const FunctionDecl *FunD);
-
+
void VisitBinaryOperator(const BinaryOperator *BinOp);
void VisitCallExpr(const CallExpr *Call);
void VisitCastExpr(const CastExpr *Cast);
@@ -510,21 +518,23 @@ public:
ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
ConsumedStateMap *StateMap)
: AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
-
+
PropagationInfo getInfo(const Expr *StmtNode) const {
ConstInfoEntry Entry = findInfo(StmtNode);
-
+
if (Entry != PropagationMap.end())
return Entry->second;
else
- return PropagationInfo();
+ return {};
}
-
+
void reset(ConsumedStateMap *NewStateMap) {
StateMap = NewStateMap;
}
};
+} // namespace consumed
+} // namespace clang
void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
InfoEntry Entry = findInfo(From);
@@ -532,7 +542,6 @@ void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
insertInfo(To, Entry->second);
}
-
// Create a new state for To, which is initialized to the state of From.
// If NS is not CS_None, sets the state of From to NS.
void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
@@ -548,7 +557,6 @@ void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
}
}
-
// Get the ConsumedState for From
ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
InfoEntry Entry = findInfo(From);
@@ -559,7 +567,6 @@ ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
return CS_None;
}
-
// If we already have info for To then update it, otherwise create a new entry.
void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
InfoEntry Entry = findInfo(To);
@@ -572,8 +579,6 @@ void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
}
}
-
-
void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
const FunctionDecl *FunDecl,
SourceLocation BlameLoc) {
@@ -592,7 +597,6 @@ void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
Analyzer.WarningsHandler.warnUseInInvalidState(
FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
stateToString(VarState), BlameLoc);
-
} else {
ConsumedState TmpState = PInfo.getAsState(StateMap);
@@ -604,7 +608,6 @@ void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
}
}
-
// Factors out common behavior for function, method, and operator calls.
// Check parameters and set parameter state if necessary.
// Returns true if the state of ObjArg is set, or false otherwise.
@@ -681,7 +684,6 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
return false;
}
-
void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
const FunctionDecl *Fun) {
QualType RetType = Fun->getCallResultType();
@@ -694,32 +696,29 @@ void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
ReturnState = mapReturnTypestateAttrState(RTA);
else
ReturnState = mapConsumableAttrState(RetType);
-
+
PropagationMap.insert(PairType(Call, PropagationInfo(ReturnState)));
}
}
-
void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
switch (BinOp->getOpcode()) {
case BO_LAnd:
case BO_LOr : {
InfoEntry LEntry = findInfo(BinOp->getLHS()),
REntry = findInfo(BinOp->getRHS());
-
+
VarTestResult LTest, RTest;
-
+
if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
LTest = LEntry->second.getVarTest();
-
} else {
LTest.Var = nullptr;
LTest.TestsFor = CS_None;
}
-
+
if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
RTest = REntry->second.getVarTest();
-
} else {
RTest.Var = nullptr;
RTest.TestsFor = CS_None;
@@ -728,15 +727,14 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
if (!(LTest.Var == nullptr && RTest.Var == nullptr))
PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
-
break;
}
-
+
case BO_PtrMemD:
case BO_PtrMemI:
forwardInfo(BinOp->getLHS(), BinOp);
break;
-
+
default:
break;
}
@@ -764,9 +762,9 @@ void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
const CXXBindTemporaryExpr *Temp) {
-
+
InfoEntry Entry = findInfo(Temp->getSubExpr());
-
+
if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
StateMap->setState(Temp, Entry->second.getAsState(StateMap));
PropagationMap.insert(PairType(Temp, PropagationInfo(Temp)));
@@ -778,13 +776,13 @@ void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
ASTContext &CurrContext = AC.getASTContext();
QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
-
+
if (!isConsumableType(ThisType))
return;
-
+
// FIXME: What should happen if someone annotates the move constructor?
if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
- // TODO: Adjust state of args appropriately.
+ // TODO: Adjust state of args appropriately.
ConsumedState RetState = mapReturnTypestateAttrState(RTA);
PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
} else if (Constructor->isDefaultConstructor()) {
@@ -805,7 +803,6 @@ void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
}
}
-
void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
const CXXMemberCallExpr *Call) {
CXXMethodDecl* MD = Call->getMethodDecl();
@@ -816,12 +813,9 @@ void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
propagateReturnType(Call, MD);
}
-
void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
const CXXOperatorCallExpr *Call) {
-
- const FunctionDecl *FunDecl =
- dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
+ const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
if (!FunDecl) return;
if (Call->getOperator() == OO_Equal) {
@@ -831,7 +825,7 @@ void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
return;
}
- if (const CXXMemberCallExpr *MCall = dyn_cast<CXXMemberCallExpr>(Call))
+ if (const auto *MCall = dyn_cast<CXXMemberCallExpr>(Call))
handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
else
handleCall(Call, Call->getArg(0), FunDecl);
@@ -840,24 +834,23 @@ void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
}
void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
+ if (const auto *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
if (StateMap->getState(Var) != consumed::CS_None)
PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
}
void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
- for (const auto *DI : DeclS->decls())
+ for (const auto *DI : DeclS->decls())
if (isa<VarDecl>(DI))
VisitVarDecl(cast<VarDecl>(DI));
-
+
if (DeclS->isSingleDecl())
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
+ if (const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
}
void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *Temp) {
-
forwardInfo(Temp->GetTemporaryExpr(), Temp);
}
@@ -865,42 +858,41 @@ void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
forwardInfo(MExpr->getBase(), MExpr);
}
-
void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
QualType ParamType = Param->getType();
ConsumedState ParamState = consumed::CS_None;
-
+
if (const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
- ParamState = mapParamTypestateAttrState(PTA);
+ ParamState = mapParamTypestateAttrState(PTA);
else if (isConsumableType(ParamType))
- ParamState = mapConsumableAttrState(ParamType);
+ ParamState = mapConsumableAttrState(ParamType);
else if (isRValueRef(ParamType) &&
isConsumableType(ParamType->getPointeeType()))
- ParamState = mapConsumableAttrState(ParamType->getPointeeType());
+ ParamState = mapConsumableAttrState(ParamType->getPointeeType());
else if (ParamType->isReferenceType() &&
isConsumableType(ParamType->getPointeeType()))
ParamState = consumed::CS_Unknown;
-
+
if (ParamState != CS_None)
StateMap->setState(Param, ParamState);
}
void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
-
+
if (ExpectedState != CS_None) {
InfoEntry Entry = findInfo(Ret->getRetValue());
-
+
if (Entry != PropagationMap.end()) {
ConsumedState RetState = Entry->second.getAsState(StateMap);
-
+
if (RetState != ExpectedState)
Analyzer.WarningsHandler.warnReturnTypestateMismatch(
Ret->getReturnLoc(), stateToString(ExpectedState),
stateToString(RetState));
}
}
-
+
StateMap->checkParamsForReturnTypestate(Ret->getLocStart(),
Analyzer.WarningsHandler);
}
@@ -908,17 +900,17 @@ void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
InfoEntry Entry = findInfo(UOp->getSubExpr());
if (Entry == PropagationMap.end()) return;
-
+
switch (UOp->getOpcode()) {
case UO_AddrOf:
PropagationMap.insert(PairType(UOp, Entry->second));
break;
-
+
case UO_LNot:
if (Entry->second.isTest())
PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
break;
-
+
default:
break;
}
@@ -932,7 +924,7 @@ void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
if (VIT != PropagationMap.end()) {
PropagationInfo PInfo = VIT->second;
ConsumedState St = PInfo.getAsState(StateMap);
-
+
if (St != consumed::CS_None) {
StateMap->setState(Var, St);
return;
@@ -943,23 +935,17 @@ void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
StateMap->setState(Var, consumed::CS_Unknown);
}
}
-}} // end clang::consumed::ConsumedStmtVisitor
-
-namespace clang {
-namespace consumed {
static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test,
ConsumedStateMap *ThenStates,
ConsumedStateMap *ElseStates) {
ConsumedState VarState = ThenStates->getState(Test.Var);
-
+
if (VarState == CS_Unknown) {
ThenStates->setState(Test.Var, Test.TestsFor);
ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
-
} else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
ThenStates->markUnreachable();
-
} else if (VarState == Test.TestsFor) {
ElseStates->markUnreachable();
}
@@ -970,36 +956,30 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
ConsumedStateMap *ElseStates) {
const VarTestResult &LTest = PInfo.getLTest(),
&RTest = PInfo.getRTest();
-
+
ConsumedState LState = LTest.Var ? ThenStates->getState(LTest.Var) : CS_None,
RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;
-
+
if (LTest.Var) {
if (PInfo.testEffectiveOp() == EO_And) {
if (LState == CS_Unknown) {
ThenStates->setState(LTest.Var, LTest.TestsFor);
-
} else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
ThenStates->markUnreachable();
-
} else if (LState == LTest.TestsFor && isKnownState(RState)) {
if (RState == RTest.TestsFor)
ElseStates->markUnreachable();
else
ThenStates->markUnreachable();
}
-
} else {
if (LState == CS_Unknown) {
ElseStates->setState(LTest.Var,
invertConsumedUnconsumed(LTest.TestsFor));
-
} else if (LState == LTest.TestsFor) {
ElseStates->markUnreachable();
-
} else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
isKnownState(RState)) {
-
if (RState == RTest.TestsFor)
ElseStates->markUnreachable();
else
@@ -1007,14 +987,13 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
}
}
}
-
+
if (RTest.Var) {
if (PInfo.testEffectiveOp() == EO_And) {
if (RState == CS_Unknown)
ThenStates->setState(RTest.Var, RTest.TestsFor);
else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
ThenStates->markUnreachable();
-
} else {
if (RState == CS_Unknown)
ElseStates->setState(RTest.Var,
@@ -1027,10 +1006,9 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
const CFGBlock *TargetBlock) {
-
assert(CurrBlock && "Block pointer must not be NULL");
assert(TargetBlock && "TargetBlock pointer must not be NULL");
-
+
unsigned int CurrBlockOrder = VisitOrder[CurrBlock->getBlockID()];
for (CFGBlock::const_pred_iterator PI = TargetBlock->pred_begin(),
PE = TargetBlock->pred_end(); PI != PE; ++PI) {
@@ -1043,7 +1021,6 @@ bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
void ConsumedBlockInfo::addInfo(
const CFGBlock *Block, ConsumedStateMap *StateMap,
std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
-
assert(Block && "Block pointer must not be NULL");
auto &Entry = StateMapsArray[Block->getBlockID()];
@@ -1058,7 +1035,6 @@ void ConsumedBlockInfo::addInfo(
void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
std::unique_ptr<ConsumedStateMap> StateMap) {
-
assert(Block && "Block pointer must not be NULL");
auto &Entry = StateMapsArray[Block->getBlockID()];
@@ -1093,7 +1069,7 @@ ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
bool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {
assert(From && "From block must not be NULL");
assert(To && "From block must not be NULL");
-
+
return VisitOrder[From->getBlockID()] > VisitOrder[To->getBlockID()];
}
@@ -1104,7 +1080,7 @@ bool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
// edge.
if (Block->pred_size() < 2)
return false;
-
+
unsigned int BlockVisitOrder = VisitOrder[Block->getBlockID()];
for (CFGBlock::const_pred_iterator PI = Block->pred_begin(),
PE = Block->pred_end(); PI != PE; ++PI) {
@@ -1116,16 +1092,16 @@ bool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
ConsumedWarningsHandlerBase &WarningsHandler) const {
-
+
for (const auto &DM : VarMap) {
if (isa<ParmVarDecl>(DM.first)) {
- const ParmVarDecl *Param = cast<ParmVarDecl>(DM.first);
+ const auto *Param = cast<ParmVarDecl>(DM.first);
const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
-
+
if (!RTA)
continue;
-
- ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);
+
+ ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);
if (DM.second != ExpectedState)
WarningsHandler.warnParamReturnTypestateMismatch(BlameLoc,
Param->getNameAsString(), stateToString(ExpectedState),
@@ -1140,20 +1116,20 @@ void ConsumedStateMap::clearTemporaries() {
ConsumedState ConsumedStateMap::getState(const VarDecl *Var) const {
VarMapType::const_iterator Entry = VarMap.find(Var);
-
+
if (Entry != VarMap.end())
return Entry->second;
-
+
return CS_None;
}
ConsumedState
ConsumedStateMap::getState(const CXXBindTemporaryExpr *Tmp) const {
TmpMapType::const_iterator Entry = TmpMap.find(Tmp);
-
+
if (Entry != TmpMap.end())
return Entry->second;
-
+
return CS_None;
}
@@ -1167,10 +1143,10 @@ void ConsumedStateMap::intersect(const ConsumedStateMap &Other) {
for (const auto &DM : Other.VarMap) {
LocalState = this->getState(DM.first);
-
+
if (LocalState == CS_None)
continue;
-
+
if (LocalState != DM.second)
VarMap[DM.first] = CS_Unknown;
}
@@ -1179,16 +1155,16 @@ void ConsumedStateMap::intersect(const ConsumedStateMap &Other) {
void ConsumedStateMap::intersectAtLoopHead(const CFGBlock *LoopHead,
const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates,
ConsumedWarningsHandlerBase &WarningsHandler) {
-
+
ConsumedState LocalState;
SourceLocation BlameLoc = getLastStmtLoc(LoopBack);
-
- for (const auto &DM : LoopBackStates->VarMap) {
+
+ for (const auto &DM : LoopBackStates->VarMap) {
LocalState = this->getState(DM.first);
-
+
if (LocalState == CS_None)
continue;
-
+
if (LocalState != DM.second) {
VarMap[DM.first] = CS_Unknown;
WarningsHandler.warnLoopStateMismatch(BlameLoc,
@@ -1219,14 +1195,14 @@ void ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) {
bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
for (const auto &DM : Other->VarMap)
if (this->getState(DM.first) != DM.second)
- return true;
+ return true;
return false;
}
void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
const FunctionDecl *D) {
QualType ReturnType;
- if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
ASTContext &CurrContext = AC.getASTContext();
ReturnType = Constructor->getThisType(CurrContext)->getPointeeType();
} else
@@ -1256,63 +1232,56 @@ void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
const ConsumedStmtVisitor &Visitor) {
-
std::unique_ptr<ConsumedStateMap> FalseStates(
new ConsumedStateMap(*CurrStates));
PropagationInfo PInfo;
-
- if (const IfStmt *IfNode =
- dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
-
+
+ if (const auto *IfNode =
+ dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
const Expr *Cond = IfNode->getCond();
-
+
PInfo = Visitor.getInfo(Cond);
if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
-
+
if (PInfo.isVarTest()) {
CurrStates->setSource(Cond);
FalseStates->setSource(Cond);
splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates.get(),
FalseStates.get());
-
} else if (PInfo.isBinTest()) {
CurrStates->setSource(PInfo.testSourceNode());
FalseStates->setSource(PInfo.testSourceNode());
splitVarStateForIfBinOp(PInfo, CurrStates.get(), FalseStates.get());
-
} else {
return false;
}
-
- } else if (const BinaryOperator *BinOp =
- dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
-
+ } else if (const auto *BinOp =
+ dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
PInfo = Visitor.getInfo(BinOp->getLHS());
if (!PInfo.isVarTest()) {
if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
PInfo = Visitor.getInfo(BinOp->getRHS());
-
+
if (!PInfo.isVarTest())
return false;
-
} else {
return false;
}
}
-
+
CurrStates->setSource(BinOp);
FalseStates->setSource(BinOp);
-
+
const VarTestResult &Test = PInfo.getVarTest();
ConsumedState VarState = CurrStates->getState(Test.Var);
-
+
if (BinOp->getOpcode() == BO_LAnd) {
if (VarState == CS_Unknown)
CurrStates->setState(Test.Var, Test.TestsFor);
else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
CurrStates->markUnreachable();
-
+
} else if (BinOp->getOpcode() == BO_LOr) {
if (VarState == CS_Unknown)
FalseStates->setState(Test.Var,
@@ -1320,13 +1289,12 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
else if (VarState == Test.TestsFor)
FalseStates->markUnreachable();
}
-
} else {
return false;
}
-
+
CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
-
+
if (*SI)
BlockInfo.addInfo(*SI, std::move(CurrStates));
else
@@ -1339,10 +1307,10 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
}
void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
- const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
+ const auto *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
if (!D)
return;
-
+
CFG *CFGraph = AC.getCFG();
if (!CFGraph)
return;
@@ -1351,7 +1319,7 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
// AC.getCFG()->viewCFG(LangOptions());
-
+
BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
CurrStates = llvm::make_unique<ConsumedStateMap>();
@@ -1360,15 +1328,14 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
// Add all trackable parameters to the state map.
for (const auto *PI : D->parameters())
Visitor.VisitParmVarDecl(PI);
-
+
// Visit all of the function's basic blocks.
for (const auto *CurrBlock : *SortedGraph) {
if (!CurrStates)
CurrStates = BlockInfo.getInfo(CurrBlock);
-
+
if (!CurrStates) {
continue;
-
} else if (!CurrStates->isReachable()) {
CurrStates = nullptr;
continue;
@@ -1382,34 +1349,34 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
case CFGElement::Statement:
Visitor.Visit(B.castAs<CFGStmt>().getStmt());
break;
-
+
case CFGElement::TemporaryDtor: {
const CFGTemporaryDtor &DTor = B.castAs<CFGTemporaryDtor>();
const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
-
+
Visitor.checkCallability(PropagationInfo(BTE),
DTor.getDestructorDecl(AC.getASTContext()),
BTE->getExprLoc());
CurrStates->remove(BTE);
break;
}
-
+
case CFGElement::AutomaticObjectDtor: {
const CFGAutomaticObjDtor &DTor = B.castAs<CFGAutomaticObjDtor>();
SourceLocation Loc = DTor.getTriggerStmt()->getLocEnd();
const VarDecl *Var = DTor.getVarDecl();
-
+
Visitor.checkCallability(PropagationInfo(Var),
DTor.getDestructorDecl(AC.getASTContext()),
Loc);
break;
}
-
+
default:
break;
}
}
-
+
// TODO: Handle other forms of branching with precision, including while-
// and for-loops. (Deferred)
if (!splitState(CurrBlock, Visitor)) {
@@ -1423,7 +1390,6 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
-
if (*SI == nullptr) continue;
if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
@@ -1440,16 +1406,15 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
CurrStates = nullptr;
}
}
-
+
if (CurrBlock == &AC.getCFG()->getExit() &&
D->getCallResultType()->isVoidType())
CurrStates->checkParamsForReturnTypestate(D->getLocation(),
WarningsHandler);
} // End of block iterator.
-
+
// Delete the last existing state map.
CurrStates = nullptr;
WarningsHandler.emitDiagnostics();
}
-}} // end namespace clang::consumed
diff --git a/contrib/llvm/tools/clang/lib/Analysis/Dominators.cpp b/contrib/llvm/tools/clang/lib/Analysis/Dominators.cpp
index 0e02c6d7174a..1b7dd8c804e1 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/Dominators.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/Dominators.cpp
@@ -1,4 +1,4 @@
-//=- Dominators.cpp - Implementation of dominators tree for Clang CFG C++ -*-=//
+//===- Dominators.cpp - Implementation of dominators tree for Clang CFG ---===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,4 +11,4 @@
using namespace clang;
-void DominatorTree::anchor() { }
+void DominatorTree::anchor() {}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
index c62e537e92dd..f37e4affae3f 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
@@ -407,7 +407,7 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
case WIntTy: {
- QualType PromoArg =
+ QualType PromoArg =
argTy->isPromotableIntegerType()
? C.getPromotedIntegerType(argTy) : argTy;
@@ -623,7 +623,7 @@ const char *ConversionSpecifier::toString() const {
Optional<ConversionSpecifier>
ConversionSpecifier::getStandardSpecifier() const {
ConversionSpecifier::Kind NewKind;
-
+
switch (getKind()) {
default:
return None;
@@ -672,7 +672,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
switch (LM.getKind()) {
case LengthModifier::None:
return true;
-
+
// Handle most integer flags
case LengthModifier::AsShort:
if (Target.getTriple().isOSMSVCRT()) {
@@ -712,7 +712,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
default:
return false;
}
-
+
// Handle 'l' flag
case LengthModifier::AsLong: // or AsWideChar
switch (CS.getKind()) {
@@ -745,7 +745,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
default:
return false;
}
-
+
case LengthModifier::AsLongDouble:
switch (CS.getKind()) {
case ConversionSpecifier::aArg:
diff --git a/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h b/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h
index 17fd2f6aefb8..a63140b366cd 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h
+++ b/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h
@@ -23,7 +23,7 @@ public:
};
namespace analyze_format_string {
-
+
OptionalAmount ParseAmount(const char *&Beg, const char *E);
OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
unsigned &argIndex);
@@ -31,12 +31,12 @@ OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
OptionalAmount ParsePositionAmount(FormatStringHandler &H,
const char *Start, const char *&Beg,
const char *E, PositionContext p);
-
+
bool ParseFieldWidth(FormatStringHandler &H,
FormatSpecifier &CS,
const char *Start, const char *&Beg, const char *E,
unsigned *argIndex);
-
+
bool ParseArgPosition(FormatStringHandler &H,
FormatSpecifier &CS, const char *Start,
const char *&Beg, const char *E);
@@ -62,7 +62,7 @@ public:
SpecifierResult(const char *start,
const T &fs)
: FS(fs), Start(start), Stop(false) {}
-
+
const char *getStart() const { return Start; }
bool shouldStop() const { return Stop; }
bool hasValue() const { return Start != nullptr; }
@@ -72,7 +72,7 @@ public:
}
const T &getValue() { return FS; }
};
-
+
} // end analyze_format_string namespace
} // end clang namespace
diff --git a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
index 4752c2b020ae..05bc1a5d102c 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
@@ -39,7 +39,7 @@ public:
: enqueuedBlocks(cfg.getNumBlockIDs()),
POV(Ctx.getAnalysis<PostOrderCFGView>()),
worklist(POV->getComparator()) {}
-
+
void enqueueBlock(const CFGBlock *block);
void enqueuePredecessors(const CFGBlock *block);
@@ -73,16 +73,17 @@ const CFGBlock *DataflowWorklist::dequeue() {
namespace {
class LiveVariablesImpl {
-public:
+public:
AnalysisDeclContext &analysisContext;
llvm::ImmutableSet<const Stmt *>::Factory SSetFact;
llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
+ llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;
llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
const bool killAtAssign;
-
+
LiveVariables::LivenessValues
merge(LiveVariables::LivenessValues valsA,
LiveVariables::LivenessValues valsB);
@@ -97,6 +98,7 @@ public:
: analysisContext(ac),
SSetFact(false), // Do not canonicalize ImmutableSets by default.
DSetFact(false), // This is a *major* performance win.
+ BSetFact(false),
killAtAssign(KillAtAssign) {}
};
}
@@ -114,6 +116,12 @@ bool LiveVariables::LivenessValues::isLive(const Stmt *S) const {
}
bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {
+ if (const auto *DD = dyn_cast<DecompositionDecl>(D)) {
+ bool alive = false;
+ for (const BindingDecl *BD : DD->bindings())
+ alive |= liveBindings.contains(BD);
+ return alive;
+ }
return liveDecls.contains(D);
}
@@ -122,7 +130,7 @@ namespace {
SET mergeSets(SET A, SET B) {
if (A.isEmpty())
return B;
-
+
for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
A = A.add(*it);
}
@@ -134,25 +142,30 @@ void LiveVariables::Observer::anchor() { }
LiveVariables::LivenessValues
LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
- LiveVariables::LivenessValues valsB) {
-
+ LiveVariables::LivenessValues valsB) {
+
llvm::ImmutableSetRef<const Stmt *>
SSetRefA(valsA.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()),
SSetRefB(valsB.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory());
-
-
+
+
llvm::ImmutableSetRef<const VarDecl *>
DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
-
+
+ llvm::ImmutableSetRef<const BindingDecl *>
+ BSetRefA(valsA.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),
+ BSetRefB(valsB.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());
SSetRefA = mergeSets(SSetRefA, SSetRefB);
DSetRefA = mergeSets(DSetRefA, DSetRefB);
-
+ BSetRefA = mergeSets(BSetRefA, BSetRefB);
+
// asImmutableSet() canonicalizes the tree, allowing us to do an easy
// comparison afterwards.
return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
- DSetRefA.asImmutableSet());
+ DSetRefA.asImmutableSet(),
+ BSetRefA.asImmutableSet());
}
bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {
@@ -198,7 +211,7 @@ public:
void VisitBinaryOperator(BinaryOperator *BO);
void VisitBlockExpr(BlockExpr *BE);
- void VisitDeclRefExpr(DeclRefExpr *DR);
+ void VisitDeclRefExpr(DeclRefExpr *DR);
void VisitDeclStmt(DeclStmt *DS);
void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
@@ -213,7 +226,7 @@ static const VariableArrayType *FindVA(QualType Ty) {
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
if (VAT->getSizeExpr())
return VAT;
-
+
ty = VT->getElementType().getTypePtr();
}
@@ -223,7 +236,7 @@ static const VariableArrayType *FindVA(QualType Ty) {
static const Stmt *LookThroughStmt(const Stmt *S) {
while (S) {
if (const Expr *Ex = dyn_cast<Expr>(S))
- S = Ex->IgnoreParens();
+ S = Ex->IgnoreParens();
if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) {
S = EWC->getSubExpr();
continue;
@@ -246,15 +259,15 @@ static void AddLiveStmt(llvm::ImmutableSet<const Stmt *> &Set,
void TransferFunctions::Visit(Stmt *S) {
if (observer)
observer->observeStmt(S, currentBlock, val);
-
+
StmtVisitor<TransferFunctions>::Visit(S);
-
+
if (isa<Expr>(S)) {
val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
}
// Mark all children expressions live.
-
+
switch (S->getStmtClass()) {
default:
break;
@@ -322,28 +335,37 @@ void TransferFunctions::Visit(Stmt *S) {
}
}
+static bool writeShouldKill(const VarDecl *VD) {
+ return VD && !VD->getType()->isReferenceType() &&
+ !isAlwaysAlive(VD);
+}
+
void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
if (B->isAssignmentOp()) {
if (!LV.killAtAssign)
return;
-
+
// Assigning to a variable?
Expr *LHS = B->getLHS()->IgnoreParens();
-
- if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS))
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- // Assignments to references don't kill the ref's address
- if (VD->getType()->isReferenceType())
- return;
-
- if (!isAlwaysAlive(VD)) {
- // The variable is now dead.
+
+ if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
+ const Decl* D = DR->getDecl();
+ bool Killed = false;
+
+ if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
+ Killed = !BD->getType()->isReferenceType();
+ if (Killed)
+ val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ Killed = writeShouldKill(VD);
+ if (Killed)
val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
- }
- if (observer)
- observer->observerKill(DR);
}
+
+ if (Killed && observer)
+ observer->observerKill(DR);
+ }
}
}
@@ -357,17 +379,27 @@ void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
}
void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
- if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
- if (!isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
- val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
+ const Decl* D = DR->getDecl();
+ bool InAssignment = LV.inAssignment[DR];
+ if (const auto *BD = dyn_cast<BindingDecl>(D)) {
+ if (!InAssignment)
+ val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (!InAssignment && !isAlwaysAlive(VD))
+ val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
+ }
}
void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
- for (const auto *DI : DS->decls())
- if (const auto *VD = dyn_cast<VarDecl>(DI)) {
+ for (const auto *DI : DS->decls()) {
+ if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
+ for (const auto *BD : DD->bindings())
+ val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
+ } else if (const auto *VD = dyn_cast<VarDecl>(DI)) {
if (!isAlwaysAlive(VD))
val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
}
+ }
}
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
@@ -382,7 +414,7 @@ void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
VD = cast<VarDecl>(DR->getDecl());
}
-
+
if (VD) {
val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
if (observer && DR)
@@ -412,22 +444,24 @@ void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
// since a ++/-- acts as both a kill and a "use".
if (!observer)
return;
-
+
switch (UO->getOpcode()) {
default:
return;
case UO_PostInc:
- case UO_PostDec:
+ case UO_PostDec:
case UO_PreInc:
case UO_PreDec:
break;
}
-
- if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens()))
- if (isa<VarDecl>(DR->getDecl())) {
+
+ if (auto *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
+ const Decl *D = DR->getDecl();
+ if (isa<VarDecl>(D) || isa<BindingDecl>(D)) {
// Treat ++/-- as a kill.
observer->observerKill(DR);
}
+ }
}
LiveVariables::LivenessValues
@@ -436,11 +470,11 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block,
LiveVariables::Observer *obs) {
TransferFunctions TF(*this, val, obs, block);
-
+
// Visit the terminator (if any).
if (const Stmt *term = block->getTerminator())
TF.Visit(const_cast<Stmt*>(term));
-
+
// Apply the transfer function for all Stmts in the block.
for (CFGBlock::const_reverse_iterator it = block->rbegin(),
ei = block->rend(); it != ei; ++it) {
@@ -454,7 +488,7 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block,
if (!elem.getAs<CFGStmt>())
continue;
-
+
const Stmt *S = elem.castAs<CFGStmt>().getStmt();
TF.Visit(const_cast<Stmt*>(S));
stmtsToLiveness[S] = val;
@@ -465,10 +499,10 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block,
void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {
const CFG *cfg = getImpl(impl).analysisContext.getCFG();
for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)
- getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
+ getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
}
-LiveVariables::LiveVariables(void *im) : impl(im) {}
+LiveVariables::LiveVariables(void *im) : impl(im) {}
LiveVariables::~LiveVariables() {
delete (LiveVariablesImpl*) impl;
@@ -499,7 +533,7 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
const CFGBlock *block = *it;
worklist.enqueueBlock(block);
-
+
// FIXME: Scan for DeclRefExprs using in the LHS of an assignment.
// We need to do this because we lack context in the reverse analysis
// to determine if a DeclRefExpr appears in such a context, and thus
@@ -508,10 +542,10 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
for (CFGBlock::const_iterator bi = block->begin(), be = block->end();
bi != be; ++bi) {
if (Optional<CFGStmt> cs = bi->getAs<CFGStmt>()) {
- if (const BinaryOperator *BO =
- dyn_cast<BinaryOperator>(cs->getStmt())) {
+ const Stmt* stmt = cs->getStmt();
+ if (const auto *BO = dyn_cast<BinaryOperator>(stmt)) {
if (BO->getOpcode() == BO_Assign) {
- if (const DeclRefExpr *DR =
+ if (const auto *DR =
dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
LV->inAssignment[DR] = 1;
}
@@ -520,35 +554,35 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
}
}
}
-
+
while (const CFGBlock *block = worklist.dequeue()) {
// Determine if the block's end value has changed. If not, we
// have nothing left to do for this block.
LivenessValues &prevVal = LV->blocksEndToLiveness[block];
-
+
// Merge the values of all successor blocks.
LivenessValues val;
for (CFGBlock::const_succ_iterator it = block->succ_begin(),
ei = block->succ_end(); it != ei; ++it) {
- if (const CFGBlock *succ = *it) {
+ if (const CFGBlock *succ = *it) {
val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
}
}
-
+
if (!everAnalyzedBlock[block->getBlockID()])
everAnalyzedBlock[block->getBlockID()] = true;
else if (prevVal.equals(val))
continue;
prevVal = val;
-
+
// Update the dataflow value for the start of this block.
LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
-
+
// Enqueue the value to the predecessors.
worklist.enqueuePredecessors(block);
}
-
+
return new LiveVariables(LV);
}
@@ -561,9 +595,9 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
it != ei; ++it) {
- vec.push_back(it->first);
+ vec.push_back(it->first);
}
- std::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
+ llvm::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
return A->getBlockID() < B->getBlockID();
});
@@ -573,17 +607,18 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
it = vec.begin(), ei = vec.end(); it != ei; ++it) {
llvm::errs() << "\n[ B" << (*it)->getBlockID()
<< " (live variables at block exit) ]\n";
-
+
LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];
declVec.clear();
-
+
for (llvm::ImmutableSet<const VarDecl *>::iterator si =
vals.liveDecls.begin(),
se = vals.liveDecls.end(); si != se; ++si) {
- declVec.push_back(*si);
+ declVec.push_back(*si);
}
- std::sort(declVec.begin(), declVec.end(), [](const Decl *A, const Decl *B) {
+ llvm::sort(declVec.begin(), declVec.end(),
+ [](const Decl *A, const Decl *B) {
return A->getLocStart() < B->getLocStart();
});
@@ -595,7 +630,7 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
llvm::errs() << ">\n";
}
}
- llvm::errs() << "\n";
+ llvm::errs() << "\n";
}
const void *LiveVariables::getTag() { static int x; return &x; }
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ObjCNoReturn.cpp b/contrib/llvm/tools/clang/lib/Analysis/ObjCNoReturn.cpp
index 52d844bf9dd8..f27568c0c322 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ObjCNoReturn.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ObjCNoReturn.cpp
@@ -32,13 +32,13 @@ ObjCNoReturn::ObjCNoReturn(ASTContext &C)
{
// Generate selectors.
SmallVector<IdentifierInfo*, 3> II;
-
+
// raise:format:
II.push_back(&C.Idents.get("raise"));
II.push_back(&C.Idents.get("format"));
NSExceptionInstanceRaiseSelectors[0] =
C.Selectors.getSelector(II.size(), &II[0]);
-
+
// raise:format:arguments:
II.push_back(&C.Idents.get("arguments"));
NSExceptionInstanceRaiseSelectors[1] =
@@ -48,7 +48,7 @@ ObjCNoReturn::ObjCNoReturn(ASTContext &C)
bool ObjCNoReturn::isImplicitNoReturn(const ObjCMessageExpr *ME) {
Selector S = ME->getSelector();
-
+
if (ME->isInstanceMessage()) {
// Check for the "raise" message.
return S == RaiseSel;
@@ -62,6 +62,6 @@ bool ObjCNoReturn::isImplicitNoReturn(const ObjCMessageExpr *ME) {
}
}
}
-
+
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PostOrderCFGView.cpp b/contrib/llvm/tools/clang/lib/Analysis/PostOrderCFGView.cpp
index 5a3c8182a140..d5d0bafe664c 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/PostOrderCFGView.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/PostOrderCFGView.cpp
@@ -1,4 +1,4 @@
-//===- PostOrderCFGView.cpp - Post order view of CFG blocks -------*- C++ --*-//
+//===- PostOrderCFGView.cpp - Post order view of CFG blocks ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,19 +12,21 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
using namespace clang;
-void PostOrderCFGView::anchor() { }
+void PostOrderCFGView::anchor() {}
PostOrderCFGView::PostOrderCFGView(const CFG *cfg) {
Blocks.reserve(cfg->getNumBlockIDs());
CFGBlockSet BSet(cfg);
-
+
for (po_iterator I = po_iterator::begin(cfg, BSet),
E = po_iterator::end(cfg, BSet); I != E; ++I) {
BlockOrder[*I] = Blocks.size() + 1;
- Blocks.push_back(*I);
+ Blocks.push_back(*I);
}
}
@@ -41,9 +43,8 @@ bool PostOrderCFGView::BlockOrderCompare::operator()(const CFGBlock *b1,
const CFGBlock *b2) const {
PostOrderCFGView::BlockOrderTy::const_iterator b1It = POV.BlockOrder.find(b1);
PostOrderCFGView::BlockOrderTy::const_iterator b2It = POV.BlockOrder.find(b2);
-
+
unsigned b1V = (b1It == POV.BlockOrder.end()) ? 0 : b1It->second;
unsigned b2V = (b2It == POV.BlockOrder.end()) ? 0 : b2It->second;
return b1V > b2V;
}
-
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
index dfaed26564e6..dcb15c5e3758 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Analysis/Analyses/OSLog.h"
#include "FormatStringParsing.h"
#include "clang/Basic/TargetInfo.h"
@@ -119,36 +120,56 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
return true;
}
- const char *OSLogVisibilityFlagsStart = nullptr,
- *OSLogVisibilityFlagsEnd = nullptr;
if (*I == '{') {
- OSLogVisibilityFlagsStart = I++;
- // Find the end of the modifier.
- while (I != E && *I != '}') {
- I++;
- }
- if (I == E) {
- if (Warn)
- H.HandleIncompleteSpecifier(Start, E - Start);
- return true;
- }
- assert(*I == '}');
- OSLogVisibilityFlagsEnd = I++;
-
- // Just see if 'private' or 'public' is the first word. os_log itself will
- // do any further parsing.
- const char *P = OSLogVisibilityFlagsStart + 1;
- while (P < OSLogVisibilityFlagsEnd && isspace(*P))
- P++;
- const char *WordStart = P;
- while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_'))
- P++;
- const char *WordEnd = P;
- StringRef Word(WordStart, WordEnd - WordStart);
- if (Word == "private") {
- FS.setIsPrivate(WordStart);
- } else if (Word == "public") {
- FS.setIsPublic(WordStart);
+ ++I;
+ unsigned char PrivacyFlags = 0;
+ StringRef MatchedStr;
+
+ do {
+ StringRef Str(I, E - I);
+ std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";
+ llvm::Regex R(Match);
+ SmallVector<StringRef, 2> Matches;
+
+ if (R.match(Str, &Matches)) {
+ MatchedStr = Matches[1];
+ I += Matches[0].size();
+
+ // Set the privacy flag if the privacy annotation in the
+ // comma-delimited segment is at least as strict as the privacy
+ // annotations in previous comma-delimited segments.
+ if (MatchedStr.equals("private"))
+ PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
+ else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
+ PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
+ } else {
+ size_t CommaOrBracePos =
+ Str.find_if([](char c) { return c == ',' || c == '}'; });
+
+ if (CommaOrBracePos == StringRef::npos) {
+ // Neither a comma nor the closing brace was found.
+ if (Warn)
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ I += CommaOrBracePos + 1;
+ }
+ // Continue until the closing brace is found.
+ } while (*(I - 1) == ',');
+
+ // Set the privacy flag.
+ switch (PrivacyFlags) {
+ case 0:
+ break;
+ case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
+ FS.setIsPrivate(MatchedStr.data());
+ break;
+ case clang::analyze_os_log::OSLogBufferItem::IsPublic:
+ FS.setIsPublic(MatchedStr.data());
+ break;
+ default:
+ llvm_unreachable("Unexpected privacy flag value");
}
}
@@ -327,7 +348,7 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
if (Target.getTriple().isOSMSVCRT())
k = ConversionSpecifier::ZArg;
}
-
+
// Check to see if we used the Objective-C modifier flags with
// a conversion specifier other than '@'.
if (k != ConversionSpecifier::ObjCObjArg &&
@@ -395,9 +416,9 @@ bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
const char *E,
const LangOptions &LO,
const TargetInfo &Target) {
-
+
unsigned argIndex = 0;
-
+
// Keep looking for a %s format specifier until we have exhausted the string.
FormatStringHandler H;
while (I != E) {
@@ -466,13 +487,14 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
case LengthModifier::AsIntMax:
return ArgType(Ctx.getIntMaxType(), "intmax_t");
case LengthModifier::AsSizeT:
- return ArgType(Ctx.getSignedSizeType(), "ssize_t");
+ return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
case LengthModifier::AsInt3264:
return Ctx.getTargetInfo().getTriple().isArch64Bit()
? ArgType(Ctx.LongLongTy, "__int64")
: ArgType(Ctx.IntTy, "__int32");
case LengthModifier::AsPtrDiff:
- return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
+ return ArgType::makePtrdiffT(
+ ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
case LengthModifier::AsWide:
@@ -499,13 +521,14 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
case LengthModifier::AsIntMax:
return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
case LengthModifier::AsSizeT:
- return ArgType(Ctx.getSizeType(), "size_t");
+ return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
case LengthModifier::AsInt3264:
return Ctx.getTargetInfo().getTriple().isArch64Bit()
? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
: ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
case LengthModifier::AsPtrDiff:
- return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t");
+ return ArgType::makePtrdiffT(
+ ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
case LengthModifier::AsWide:
@@ -647,6 +670,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::Bool:
case BuiltinType::WChar_U:
case BuiltinType::WChar_S:
+ case BuiltinType::Char8: // FIXME: Treat like 'char'?
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::UInt128:
@@ -654,6 +678,30 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::Half:
case BuiltinType::Float16:
case BuiltinType::Float128:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
// Various types which are non-trivial to correct.
return false;
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ProgramPoint.cpp b/contrib/llvm/tools/clang/lib/Analysis/ProgramPoint.cpp
index 26b59bb71de2..d9833659d7b3 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ProgramPoint.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ProgramPoint.cpp
@@ -43,7 +43,7 @@ ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
}
}
-SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
+SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
StringRef Msg)
: Desc((MsgProvider + " : " + Msg).str()) {}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
index 7e72795a47f6..ed26a94f3d60 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
@@ -66,6 +66,21 @@ static bool isBuiltinUnreachable(const Stmt *S) {
return false;
}
+static bool isBuiltinAssumeFalse(const CFGBlock *B, const Stmt *S,
+ ASTContext &C) {
+ if (B->empty()) {
+ // Happens if S is B's terminator and B contains nothing else
+ // (e.g. a CFGBlock containing only a goto).
+ return false;
+ }
+ if (Optional<CFGStmt> CS = B->back().getAs<CFGStmt>()) {
+ if (const auto *CE = dyn_cast<CallExpr>(CS->getStmt())) {
+ return CE->getCallee()->IgnoreCasts() == S && CE->isBuiltinAssumeFalse(C);
+ }
+ }
+ return false;
+}
+
static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {
// Look to see if the current control flow ends with a 'return', and see if
// 'S' is a substatement. The 'return' may not be the last element in the
@@ -186,7 +201,7 @@ static bool isConfigurationValue(const Stmt *S,
// Special case looking for the sigil '()' around an integer literal.
if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))
if (!PE->getLocStart().isMacroID())
- return isConfigurationValue(PE->getSubExpr(), PP, SilenceableCondVal,
+ return isConfigurationValue(PE->getSubExpr(), PP, SilenceableCondVal,
IncludeIntegers, true);
if (const Expr *Ex = dyn_cast<Expr>(S))
@@ -295,19 +310,19 @@ static unsigned scanFromBlock(const CFGBlock *Start,
Preprocessor *PP,
bool IncludeSometimesUnreachableEdges) {
unsigned count = 0;
-
+
// Prep work queue
SmallVector<const CFGBlock*, 32> WL;
-
+
// The entry block may have already been marked reachable
// by the caller.
if (!Reachable[Start->getBlockID()]) {
++count;
Reachable[Start->getBlockID()] = true;
}
-
+
WL.push_back(Start);
-
+
// Find the reachable blocks from 'Start'.
while (!WL.empty()) {
const CFGBlock *item = WL.pop_back_val();
@@ -322,7 +337,7 @@ static unsigned scanFromBlock(const CFGBlock *Start,
if (!IncludeSometimesUnreachableEdges)
TreatAllSuccessorsAsReachable = false;
- for (CFGBlock::const_succ_iterator I = item->succ_begin(),
+ for (CFGBlock::const_succ_iterator I = item->succ_begin(),
E = item->succ_end(); I != E; ++I) {
const CFGBlock *B = *I;
if (!B) do {
@@ -372,6 +387,7 @@ namespace {
llvm::BitVector &Reachable;
SmallVector<const CFGBlock *, 10> WorkList;
Preprocessor &PP;
+ ASTContext &C;
typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
DeferredLocsTy;
@@ -379,10 +395,10 @@ namespace {
DeferredLocsTy DeferredLocs;
public:
- DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP)
+ DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP, ASTContext &C)
: Visited(reachable.size()),
Reachable(reachable),
- PP(PP) {}
+ PP(PP), C(C) {}
void enqueue(const CFGBlock *block);
unsigned scanBackwards(const CFGBlock *Start,
@@ -600,7 +616,8 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
if (isa<BreakStmt>(S)) {
UK = reachable_code::UK_Break;
- } else if (isTrivialDoWhile(B, S) || isBuiltinUnreachable(S)) {
+ } else if (isTrivialDoWhile(B, S) || isBuiltinUnreachable(S) ||
+ isBuiltinAssumeFalse(B, S, C)) {
return;
}
else if (isDeadReturn(B, S)) {
@@ -627,7 +644,7 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
Loc, SourceRange(), SourceRange(Loc, Loc), R2);
return;
}
-
+
// Check if the dead block has a predecessor whose branch has
// a configuration value that *could* be modified to
// silence the warning.
@@ -673,7 +690,7 @@ void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable);
if (numReachable == cfg->getNumBlockIDs())
return;
-
+
// If there aren't explicit EH edges, we should include the 'try' dispatch
// blocks as roots.
if (!AC.getCFGBuildOptions().AddEHEdges) {
@@ -686,16 +703,16 @@ void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
}
// There are some unreachable blocks. We need to find the root blocks that
- // contain code that should be considered unreachable.
+ // contain code that should be considered unreachable.
for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
const CFGBlock *block = *I;
// A block may have been marked reachable during this loop.
if (reachable[block->getBlockID()])
continue;
-
- DeadCodeScan DS(reachable, PP);
+
+ DeadCodeScan DS(reachable, PP, AC.getASTContext());
numReachable += DS.scanBackwards(block, CB);
-
+
if (numReachable == cfg->getNumBlockIDs())
return;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
index 8398a4b82d5a..a9af0cdfdacd 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
@@ -41,7 +41,7 @@ static bool ParseScanList(FormatStringHandler &H,
H.HandleIncompleteScanList(start, I);
return true;
}
-
+
// Special case: ']' is the first character.
if (*I == ']') {
if (++I == E) {
@@ -65,7 +65,7 @@ static bool ParseScanList(FormatStringHandler &H,
H.HandleIncompleteScanList(start, I - 1);
return true;
}
- }
+ }
CS.setEndScanList(I);
return false;
@@ -98,17 +98,17 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
break;
}
}
-
+
// No format specifier found?
if (!Start)
return false;
-
+
if (I == E) {
// No more characters left?
H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
-
+
ScanfSpecifier FS;
if (ParseArgPosition(H, FS, Start, I, E))
return true;
@@ -118,7 +118,7 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
-
+
// Look for '*' flag if it is present.
if (*I == '*') {
FS.setSuppressAssignment(I);
@@ -127,7 +127,7 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
return true;
}
}
-
+
// Look for the field width (if any). Unlike printf, this is either
// a fixed integer or isn't present.
const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
@@ -141,20 +141,20 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
return true;
}
}
-
+
// Look for the length modifier.
if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
// No more characters left?
H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
-
+
// Detect spurious null characters, which are likely errors.
if (*I == '\0') {
H.HandleNullChar(I);
return true;
}
-
+
// Finally, look for the conversion specifier.
const char *conversionPosition = I++;
ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
@@ -207,7 +207,7 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
&& !FS.usesPositionalArg())
FS.setArgIndex(argIndex++);
-
+
// FIXME: '%' and '*' doesn't make sense. Issue a warning.
// FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
@@ -537,9 +537,9 @@ bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
const char *E,
const LangOptions &LO,
const TargetInfo &Target) {
-
+
unsigned argIndex = 0;
-
+
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
index 6a9c9a04c55d..03cc234dce5c 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafety.cpp ----------------------------------------*- C++ --*-===//
+//===- ThreadSafety.cpp ---------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,41 +17,59 @@
#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
-#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableMap.h"
-#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <ostream>
-#include <sstream>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <type_traits>
#include <utility>
#include <vector>
+
using namespace clang;
using namespace threadSafety;
// Key method definition
-ThreadSafetyHandler::~ThreadSafetyHandler() {}
+ThreadSafetyHandler::~ThreadSafetyHandler() = default;
namespace {
+
class TILPrinter :
- public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
+ public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
+} // namespace
/// Issue a warning about an invalid lock expression
static void warnInvalidLock(ThreadSafetyHandler &Handler,
@@ -66,11 +84,13 @@ static void warnInvalidLock(ThreadSafetyHandler &Handler,
Handler.handleInvalidLockExp(Kind, Loc);
}
-/// \brief A set of CapabilityInfo objects, which are compiled from the
+namespace {
+
+/// A set of CapabilityInfo objects, which are compiled from the
/// requires attributes on a function.
class CapExprSet : public SmallVector<CapabilityExpr, 4> {
public:
- /// \brief Push M onto list, but discard duplicates.
+ /// Push M onto list, but discard duplicates.
void push_back_nodup(const CapabilityExpr &CapE) {
iterator It = std::find_if(begin(), end(),
[=](const CapabilityExpr &CapE2) {
@@ -84,33 +104,37 @@ public:
class FactManager;
class FactSet;
-/// \brief This is a helper class that stores a fact that is known at a
+/// This is a helper class that stores a fact that is known at a
/// particular point in program execution. Currently, a fact is a capability,
/// along with additional information, such as where it was acquired, whether
/// it is exclusive or shared, etc.
///
-/// FIXME: this analysis does not currently support either re-entrant
-/// locking or lock "upgrading" and "downgrading" between exclusive and
-/// shared.
+/// FIXME: this analysis does not currently support re-entrant locking.
class FactEntry : public CapabilityExpr {
private:
- LockKind LKind; ///< exclusive or shared
- SourceLocation AcquireLoc; ///< where it was acquired.
- bool Asserted; ///< true if the lock was asserted
- bool Declared; ///< true if the lock was declared
+ /// Exclusive or shared.
+ LockKind LKind;
+
+ /// Where it was acquired.
+ SourceLocation AcquireLoc;
+
+ /// True if the lock was asserted.
+ bool Asserted;
+
+ /// True if the lock was declared.
+ bool Declared;
public:
FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
bool Asrt, bool Declrd = false)
: CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt),
Declared(Declrd) {}
+ virtual ~FactEntry() = default;
- virtual ~FactEntry() {}
-
- LockKind kind() const { return LKind; }
- SourceLocation loc() const { return AcquireLoc; }
- bool asserted() const { return Asserted; }
- bool declared() const { return Declared; }
+ LockKind kind() const { return LKind; }
+ SourceLocation loc() const { return AcquireLoc; }
+ bool asserted() const { return Asserted; }
+ bool declared() const { return Declared; }
void setDeclared(bool D) { Declared = D; }
@@ -129,10 +153,9 @@ public:
}
};
+using FactID = unsigned short;
-typedef unsigned short FactID;
-
-/// \brief FactManager manages the memory for all facts that are created during
+/// FactManager manages the memory for all facts that are created during
/// the analysis of a single routine.
class FactManager {
private:
@@ -148,8 +171,7 @@ public:
FactEntry &operator[](FactID F) { return *Facts[F]; }
};
-
-/// \brief A FactSet is the set of facts that are known to be true at a
+/// A FactSet is the set of facts that are known to be true at a
/// particular program point. FactSets must be small, because they are
/// frequently copied, and are thus implemented as a set of indices into a
/// table maintained by a FactManager. A typical FactSet only holds 1 or 2
@@ -158,25 +180,25 @@ public:
/// may involve partial pattern matches, rather than exact matches.
class FactSet {
private:
- typedef SmallVector<FactID, 4> FactVec;
+ using FactVec = SmallVector<FactID, 4>;
FactVec FactIDs;
public:
- typedef FactVec::iterator iterator;
- typedef FactVec::const_iterator const_iterator;
+ using iterator = FactVec::iterator;
+ using const_iterator = FactVec::const_iterator;
- iterator begin() { return FactIDs.begin(); }
+ iterator begin() { return FactIDs.begin(); }
const_iterator begin() const { return FactIDs.begin(); }
- iterator end() { return FactIDs.end(); }
+ iterator end() { return FactIDs.end(); }
const_iterator end() const { return FactIDs.end(); }
bool isEmpty() const { return FactIDs.size() == 0; }
// Return true if the set contains only negative facts
bool isEmpty(FactManager &FactMan) const {
- for (FactID FID : *this) {
+ for (const auto FID : *this) {
if (!FactMan[FID].negative())
return false;
}
@@ -247,28 +269,30 @@ public:
};
class ThreadSafetyAnalyzer;
+
} // namespace
namespace clang {
namespace threadSafety {
+
class BeforeSet {
private:
- typedef SmallVector<const ValueDecl*, 4> BeforeVect;
+ using BeforeVect = SmallVector<const ValueDecl *, 4>;
struct BeforeInfo {
- BeforeInfo() : Visited(0) {}
- BeforeInfo(BeforeInfo &&) = default;
-
BeforeVect Vect;
- int Visited;
+ int Visited = 0;
+
+ BeforeInfo() = default;
+ BeforeInfo(BeforeInfo &&) = default;
};
- typedef llvm::DenseMap<const ValueDecl *, std::unique_ptr<BeforeInfo>>
- BeforeMap;
- typedef llvm::DenseMap<const ValueDecl*, bool> CycleMap;
+ using BeforeMap =
+ llvm::DenseMap<const ValueDecl *, std::unique_ptr<BeforeInfo>>;
+ using CycleMap = llvm::DenseMap<const ValueDecl *, bool>;
public:
- BeforeSet() { }
+ BeforeSet() = default;
BeforeInfo* insertAttrExprs(const ValueDecl* Vd,
ThreadSafetyAnalyzer& Analyzer);
@@ -283,15 +307,18 @@ public:
private:
BeforeMap BMap;
- CycleMap CycMap;
+ CycleMap CycMap;
};
-} // end namespace threadSafety
-} // end namespace clang
+
+} // namespace threadSafety
+} // namespace clang
namespace {
-typedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;
+
class LocalVariableMap;
+using LocalVarContext = llvm::ImmutableMap<const NamedDecl *, unsigned>;
+
/// A side (entry or exit) of a CFG node.
enum CFGBlockSide { CBS_Entry, CBS_Exit };
@@ -299,33 +326,46 @@ enum CFGBlockSide { CBS_Entry, CBS_Exit };
/// maintained for each block in the CFG. See LocalVariableMap for more
/// information about the contexts.
struct CFGBlockInfo {
- FactSet EntrySet; // Lockset held at entry to block
- FactSet ExitSet; // Lockset held at exit from block
- LocalVarContext EntryContext; // Context held at entry to block
- LocalVarContext ExitContext; // Context held at exit from block
- SourceLocation EntryLoc; // Location of first statement in block
- SourceLocation ExitLoc; // Location of last statement in block.
- unsigned EntryIndex; // Used to replay contexts later
- bool Reachable; // Is this block reachable?
+ // Lockset held at entry to block
+ FactSet EntrySet;
+
+ // Lockset held at exit from block
+ FactSet ExitSet;
+
+ // Context held at entry to block
+ LocalVarContext EntryContext;
+
+ // Context held at exit from block
+ LocalVarContext ExitContext;
+
+ // Location of first statement in block
+ SourceLocation EntryLoc;
+
+ // Location of last statement in block.
+ SourceLocation ExitLoc;
+
+ // Used to replay contexts later
+ unsigned EntryIndex;
+
+ // Is this block reachable?
+ bool Reachable = false;
const FactSet &getSet(CFGBlockSide Side) const {
return Side == CBS_Entry ? EntrySet : ExitSet;
}
+
SourceLocation getLocation(CFGBlockSide Side) const {
return Side == CBS_Entry ? EntryLoc : ExitLoc;
}
private:
CFGBlockInfo(LocalVarContext EmptyCtx)
- : EntryContext(EmptyCtx), ExitContext(EmptyCtx), Reachable(false)
- { }
+ : EntryContext(EmptyCtx), ExitContext(EmptyCtx) {}
public:
static CFGBlockInfo getEmptyBlockInfo(LocalVariableMap &M);
};
-
-
// A LocalVariableMap maintains a map from local variables to their currently
// valid definitions. It provides SSA-like functionality when traversing the
// CFG. Like SSA, each definition or assignment to a variable is assigned a
@@ -341,7 +381,7 @@ public:
// that Context to look up the definitions of variables.
class LocalVariableMap {
public:
- typedef LocalVarContext Context;
+ using Context = LocalVarContext;
/// A VarDefinition consists of an expression, representing the value of the
/// variable, along with the context in which that expression should be
@@ -351,30 +391,35 @@ public:
public:
friend class LocalVariableMap;
- const NamedDecl *Dec; // The original declaration for this variable.
- const Expr *Exp; // The expression for this variable, OR
- unsigned Ref; // Reference to another VarDefinition
- Context Ctx; // The map with which Exp should be interpreted.
+ // The original declaration for this variable.
+ const NamedDecl *Dec;
+
+ // The expression for this variable, OR
+ const Expr *Exp = nullptr;
+
+ // Reference to another VarDefinition
+ unsigned Ref = 0;
+
+ // The map with which Exp should be interpreted.
+ Context Ctx;
bool isReference() { return !Exp; }
private:
// Create ordinary variable definition
VarDefinition(const NamedDecl *D, const Expr *E, Context C)
- : Dec(D), Exp(E), Ref(0), Ctx(C)
- { }
+ : Dec(D), Exp(E), Ctx(C) {}
// Create reference to previous definition
VarDefinition(const NamedDecl *D, unsigned R, Context C)
- : Dec(D), Exp(nullptr), Ref(R), Ctx(C)
- { }
+ : Dec(D), Ref(R), Ctx(C) {}
};
private:
Context::Factory ContextFactory;
std::vector<VarDefinition> VarDefinitions;
std::vector<unsigned> CtxIndices;
- std::vector<std::pair<Stmt*, Context> > SavedContexts;
+ std::vector<std::pair<Stmt *, Context>> SavedContexts;
public:
LocalVariableMap() {
@@ -471,12 +516,14 @@ public:
std::vector<CFGBlockInfo> &BlockInfo);
protected:
+ friend class VarMapBuilder;
+
// Get the current context index
unsigned getContextIndex() { return SavedContexts.size()-1; }
// Save the current context for later replay
void saveContext(Stmt *S, Context C) {
- SavedContexts.push_back(std::make_pair(S,C));
+ SavedContexts.push_back(std::make_pair(S, C));
}
// Adds a new definition to the given context, and returns a new context.
@@ -533,16 +580,16 @@ protected:
Context intersectContexts(Context C1, Context C2);
Context createReferenceContext(Context C);
void intersectBackEdge(Context C1, Context C2);
-
- friend class VarMapBuilder;
};
+} // namespace
// This has to be defined after LocalVariableMap.
CFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(LocalVariableMap &M) {
return CFGBlockInfo(M.getEmptyContext());
}
+namespace {
/// Visitor which builds a LocalVariableMap
class VarMapBuilder : public StmtVisitor<VarMapBuilder> {
@@ -551,12 +598,13 @@ public:
LocalVariableMap::Context Ctx;
VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
- : VMap(VM), Ctx(C) {}
+ : VMap(VM), Ctx(C) {}
void VisitDeclStmt(DeclStmt *S);
void VisitBinaryOperator(BinaryOperator *BO);
};
+} // namespace
// Add new local variables to the variable map
void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
@@ -586,8 +634,8 @@ void VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
// Update the variable map and current context.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
- ValueDecl *VDec = DRE->getDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
+ const ValueDecl *VDec = DRE->getDecl();
if (Ctx.lookup(VDec)) {
if (BO->getOpcode() == BO_Assign)
Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx);
@@ -599,7 +647,6 @@ void VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
}
}
-
// Computes the intersection of two contexts. The intersection is the
// set of variables which have the same definition in both contexts;
// variables with different definitions are discarded.
@@ -642,7 +689,6 @@ void LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
}
}
-
// Traverse the CFG in topological order, so all predecessors of a block
// (excluding back-edges) are visited before the block itself. At
// each point in the code, we calculate a Context, which holds the set of
@@ -680,7 +726,6 @@ void LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
// while (b) { x -> x2, y -> y1 | [1st:] x2=x1; [2nd:] x2=NULL; }
// x = x+1; { x -> x3, y -> y1 | x3 = x2 + 1, ... }
// ... { y -> y1 | x3 = 2, x2 = 1, ... }
-//
void LocalVariableMap::traverseCFG(CFG *CFGraph,
const PostOrderCFGView *SortedGraph,
std::vector<CFGBlockInfo> &BlockInfo) {
@@ -731,12 +776,11 @@ void LocalVariableMap::traverseCFG(CFG *CFGraph,
// Visit all the statements in the basic block.
VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext);
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
- switch (BI->getKind()) {
+ for (const auto &BI : *CurrBlock) {
+ switch (BI.getKind()) {
case CFGElement::Statement: {
- CFGStmt CS = BI->castAs<CFGStmt>();
- VMapBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
+ CFGStmt CS = BI.castAs<CFGStmt>();
+ VMapBuilder.Visit(const_cast<Stmt *>(CS.getStmt()));
break;
}
default:
@@ -790,10 +834,9 @@ static void findBlockLocations(CFG *CFGraph,
if (CurrBlockInfo->ExitLoc.isValid()) {
// This block contains at least one statement. Find the source location
// of the first statement in the block.
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
+ for (const auto &BI : *CurrBlock) {
// FIXME: Handle other CFGElement kinds.
- if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
+ if (Optional<CFGStmt> CS = BI.getAs<CFGStmt>()) {
CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
break;
}
@@ -808,9 +851,12 @@ static void findBlockLocations(CFG *CFGraph,
}
}
+namespace {
+
class LockableFactEntry : public FactEntry {
private:
- bool Managed; ///< managed by ScopedLockable object
+ /// managed by ScopedLockable object
+ bool Managed;
public:
LockableFactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
@@ -857,7 +903,7 @@ public:
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const override {
- for (const til::SExpr *UnderlyingMutex : UnderlyingMutexes) {
+ for (const auto *UnderlyingMutex : UnderlyingMutexes) {
if (FSet.findLock(FactMan, CapabilityExpr(UnderlyingMutex, false))) {
// If this scoped lock manages another mutex, and if the underlying
// mutex is still held, then warn about the underlying mutex.
@@ -872,7 +918,7 @@ public:
bool FullyRemove, ThreadSafetyHandler &Handler,
StringRef DiagKind) const override {
assert(!Cp.negative() && "Managing object cannot be negative.");
- for (const til::SExpr *UnderlyingMutex : UnderlyingMutexes) {
+ for (const auto *UnderlyingMutex : UnderlyingMutexes) {
CapabilityExpr UnderCp(UnderlyingMutex, false);
auto UnderEntry = llvm::make_unique<LockableFactEntry>(
!UnderCp, LK_Exclusive, UnlockLoc);
@@ -900,7 +946,7 @@ public:
}
};
-/// \brief Class which implements the core thread safety analysis routines.
+/// Class which implements the core thread safety analysis routines.
class ThreadSafetyAnalyzer {
friend class BuildLockset;
friend class threadSafety::BeforeSet;
@@ -909,17 +955,17 @@ class ThreadSafetyAnalyzer {
threadSafety::til::MemRegionRef Arena;
threadSafety::SExprBuilder SxBuilder;
- ThreadSafetyHandler &Handler;
- const CXXMethodDecl *CurrentMethod;
- LocalVariableMap LocalVarMap;
- FactManager FactMan;
+ ThreadSafetyHandler &Handler;
+ const CXXMethodDecl *CurrentMethod;
+ LocalVariableMap LocalVarMap;
+ FactManager FactMan;
std::vector<CFGBlockInfo> BlockInfo;
- BeforeSet* GlobalBeforeSet;
+ BeforeSet *GlobalBeforeSet;
public:
ThreadSafetyAnalyzer(ThreadSafetyHandler &H, BeforeSet* Bset)
- : Arena(&Bpa), SxBuilder(Arena), Handler(H), GlobalBeforeSet(Bset) {}
+ : Arena(&Bpa), SxBuilder(Arena), Handler(H), GlobalBeforeSet(Bset) {}
bool inCurrentScope(const CapabilityExpr &CapE);
@@ -959,6 +1005,7 @@ public:
void runAnalysis(AnalysisDeclContext &AC);
};
+
} // namespace
/// Process acquired_before and acquired_after attributes on Vd.
@@ -975,10 +1022,10 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
Info = InfoPtr.get();
}
- for (Attr* At : Vd->attrs()) {
+ for (const auto *At : Vd->attrs()) {
switch (At->getKind()) {
case attr::AcquiredBefore: {
- auto *A = cast<AcquiredBeforeAttr>(At);
+ const auto *A = cast<AcquiredBeforeAttr>(At);
// Read exprs from the attribute, and add them to BeforeVect.
for (const auto *Arg : A->args()) {
@@ -986,7 +1033,7 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
if (const ValueDecl *Cpvd = Cp.valueDecl()) {
Info->Vect.push_back(Cpvd);
- auto It = BMap.find(Cpvd);
+ const auto It = BMap.find(Cpvd);
if (It == BMap.end())
insertAttrExprs(Cpvd, Analyzer);
}
@@ -994,7 +1041,7 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
break;
}
case attr::AcquiredAfter: {
- auto *A = cast<AcquiredAfterAttr>(At);
+ const auto *A = cast<AcquiredAfterAttr>(At);
// Read exprs from the attribute, and add them to BeforeVect.
for (const auto *Arg : A->args()) {
@@ -1055,7 +1102,7 @@ void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
InfoVect.push_back(Info);
Info->Visited = 1;
- for (auto *Vdb : Info->Vect) {
+ for (const auto *Vdb : Info->Vect) {
// Exclude mutexes in our immediate before set.
if (FSet.containsMutexDecl(Analyzer.FactMan, Vdb)) {
StringRef L1 = StartVd->getName();
@@ -1077,13 +1124,11 @@ void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
traverse(StartVd);
- for (auto* Info : InfoVect)
+ for (auto *Info : InfoVect)
Info->Visited = 0;
}
-
-
-/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs.
+/// Gets the value decl pointer from DeclRefExprs or MemberExprs.
static const ValueDecl *getValueDecl(const Expr *Exp) {
if (const auto *CE = dyn_cast<ImplicitCastExpr>(Exp))
return getValueDecl(CE->getSubExpr());
@@ -1098,10 +1143,11 @@ static const ValueDecl *getValueDecl(const Expr *Exp) {
}
namespace {
+
template <typename Ty>
class has_arg_iterator_range {
- 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->args()) * = nullptr);
@@ -1112,6 +1158,7 @@ class has_arg_iterator_range {
public:
static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
};
+
} // namespace
static StringRef ClassifyDiagnostic(const CapabilityAttr *A) {
@@ -1163,20 +1210,18 @@ ClassifyDiagnostic(const AttrTy *A) {
return "mutex";
}
-
-inline bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
+bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
if (!CurrentMethod)
return false;
- if (auto *P = dyn_cast_or_null<til::Project>(CapE.sexpr())) {
- auto *VD = P->clangDecl();
+ if (const auto *P = dyn_cast_or_null<til::Project>(CapE.sexpr())) {
+ const auto *VD = P->clangDecl();
if (VD)
return VD->getDeclContext() == CurrentMethod->getDeclContext();
}
return false;
}
-
-/// \brief Add a new lock to the lockset, warning if the lock is already there.
+/// Add a new lock to the lockset, warning if the lock is already there.
/// \param ReqAttr -- true if this is part of an initial Requires attribute.
void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
std::unique_ptr<FactEntry> Entry,
@@ -1214,8 +1259,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
}
}
-
-/// \brief Remove a lock from the lockset, warning if the lock is not there.
+/// Remove a lock from the lockset, warning if the lock is not there.
/// \param UnlockLoc The source location of the unlock (only used in error msg)
void ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const CapabilityExpr &Cp,
SourceLocation UnlockLoc,
@@ -1241,8 +1285,7 @@ void ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const CapabilityExpr &Cp,
DiagKind);
}
-
-/// \brief Extract the list of mutexIDs from the attribute on an expression,
+/// Extract the list of mutexIDs from the attribute on an expression,
/// and push them onto Mtxs, discarding any duplicates.
template <typename AttrType>
void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
@@ -1273,8 +1316,7 @@ void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
}
}
-
-/// \brief Extract the list of mutexIDs from a trylock attribute. If the
+/// Extract the list of mutexIDs from a trylock attribute. If the
/// trylock applies to the given edge, then push them onto Mtxs, discarding
/// any duplicates.
template <class AttrType>
@@ -1285,9 +1327,9 @@ void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
Expr *BrE, bool Neg) {
// Find out which branch has the lock
bool branch = false;
- if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE))
+ if (const auto *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE))
branch = BLE->getValue();
- else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE))
+ else if (const auto *ILE = dyn_cast_or_null<IntegerLiteral>(BrE))
branch = ILE->getValue().getBoolValue();
int branchnum = branch ? 0 : 1;
@@ -1307,19 +1349,17 @@ static bool getStaticBooleanValue(Expr *E, bool &TCond) {
if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
TCond = false;
return true;
- } else if (CXXBoolLiteralExpr *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
+ } else if (const auto *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
TCond = BLE->getValue();
return true;
- } else if (IntegerLiteral *ILE = dyn_cast<IntegerLiteral>(E)) {
+ } else if (const auto *ILE = dyn_cast<IntegerLiteral>(E)) {
TCond = ILE->getValue().getBoolValue();
return true;
- } else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
+ } else if (auto *CE = dyn_cast<ImplicitCastExpr>(E))
return getStaticBooleanValue(CE->getSubExpr(), TCond);
- }
return false;
}
-
// If Cond can be traced back to a function call, return the call expression.
// The negate variable should be called with false, and will be set to true
// if the function call is negated, e.g. if (!mu.tryLock(...))
@@ -1329,30 +1369,26 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
if (!Cond)
return nullptr;
- if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
+ if (const auto *CallExp = dyn_cast<CallExpr>(Cond))
return CallExp;
- }
- else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) {
+ else if (const auto *PE = dyn_cast<ParenExpr>(Cond))
return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
- }
- else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
+ else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
- }
- else if (const ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(Cond)) {
+ else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Cond))
return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
- }
- else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Cond)) {
+ else if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
return getTrylockCallExpr(E, C, Negate);
}
- else if (const UnaryOperator *UOP = dyn_cast<UnaryOperator>(Cond)) {
+ else if (const auto *UOP = dyn_cast<UnaryOperator>(Cond)) {
if (UOP->getOpcode() == UO_LNot) {
Negate = !Negate;
return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
}
return nullptr;
}
- else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
+ else if (const auto *BOP = dyn_cast<BinaryOperator>(Cond)) {
if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
if (BOP->getOpcode() == BO_NE)
Negate = !Negate;
@@ -1373,16 +1409,14 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
// LHS must have been evaluated in a different block.
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
}
- if (BOP->getOpcode() == BO_LOr) {
+ if (BOP->getOpcode() == BO_LOr)
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
- }
return nullptr;
}
return nullptr;
}
-
-/// \brief Find the lockset that holds on the edge between PredBlock
+/// Find the lockset that holds on the edge between PredBlock
/// and CurrBlock. The edge set is the exit set of PredBlock (passed
/// as the ExitSet parameter) plus any trylocks, which are conditionally held.
void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
@@ -1400,12 +1434,11 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
StringRef CapDiagKind = "mutex";
- CallExpr *Exp =
- const_cast<CallExpr*>(getTrylockCallExpr(Cond, LVarCtx, Negate));
+ auto *Exp = const_cast<CallExpr *>(getTrylockCallExpr(Cond, LVarCtx, Negate));
if (!Exp)
return;
- NamedDecl *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
+ auto *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
if(!FunDecl || !FunDecl->hasAttrs())
return;
@@ -1413,19 +1446,25 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
CapExprSet SharedLocksToAdd;
// If the condition is a call to a Trylock function, then grab the attributes
- for (auto *Attr : FunDecl->attrs()) {
+ for (const auto *Attr : FunDecl->attrs()) {
switch (Attr->getKind()) {
+ case attr::TryAcquireCapability: {
+ auto *A = cast<TryAcquireCapabilityAttr>(Attr);
+ getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
+ Exp, FunDecl, PredBlock, CurrBlock, A->getSuccessValue(),
+ Negate);
+ CapDiagKind = ClassifyDiagnostic(A);
+ break;
+ };
case attr::ExclusiveTrylockFunction: {
- ExclusiveTrylockFunctionAttr *A =
- cast<ExclusiveTrylockFunctionAttr>(Attr);
+ const auto *A = cast<ExclusiveTrylockFunctionAttr>(Attr);
getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
PredBlock, CurrBlock, A->getSuccessValue(), Negate);
CapDiagKind = ClassifyDiagnostic(A);
break;
}
case attr::SharedTrylockFunction: {
- SharedTrylockFunctionAttr *A =
- cast<SharedTrylockFunctionAttr>(Attr);
+ const auto *A = cast<SharedTrylockFunctionAttr>(Attr);
getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl,
PredBlock, CurrBlock, A->getSuccessValue(), Negate);
CapDiagKind = ClassifyDiagnostic(A);
@@ -1449,7 +1488,8 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
}
namespace {
-/// \brief We use this class to visit different types of expressions in
+
+/// We use this class to visit different types of expressions in
/// CFGBlocks, and build up the lockset.
/// An expression may cause us to add or remove locks from the lockset, or else
/// output error messages related to missing locks.
@@ -1478,12 +1518,8 @@ class BuildLockset : public StmtVisitor<BuildLockset> {
public:
BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
- : StmtVisitor<BuildLockset>(),
- Analyzer(Anlzr),
- FSet(Info.EntrySet),
- LVarCtx(Info.EntryContext),
- CtxIndex(Info.EntryIndex)
- {}
+ : StmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
+ LVarCtx(Info.EntryContext), CtxIndex(Info.EntryIndex) {}
void VisitUnaryOperator(UnaryOperator *UO);
void VisitBinaryOperator(BinaryOperator *BO);
@@ -1492,9 +1528,10 @@ public:
void VisitCXXConstructExpr(CXXConstructExpr *Exp);
void VisitDeclStmt(DeclStmt *S);
};
+
} // namespace
-/// \brief Warn if the LSet does not contain a lock sufficient to protect access
+/// Warn if the LSet does not contain a lock sufficient to protect access
/// of at least the passed in AccessKind.
void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
AccessKind AK, Expr *MutexExp,
@@ -1558,7 +1595,7 @@ void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
}
}
-/// \brief Warn if the LSet contains the given lock.
+/// Warn if the LSet contains the given lock.
void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
Expr *MutexExp, StringRef DiagKind) {
CapabilityExpr Cp = Analyzer->SxBuilder.translateAttrExpr(MutexExp, D, Exp);
@@ -1576,7 +1613,7 @@ void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
}
}
-/// \brief Checks guarded_by and pt_guarded_by attributes.
+/// Checks guarded_by and pt_guarded_by attributes.
/// Whenever we identify an access (read or write) to a DeclRefExpr that is
/// marked with guarded_by, we must ensure the appropriate mutexes are held.
/// Similarly, we check if the access is to an expression that dereferences
@@ -1600,19 +1637,19 @@ void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
break;
}
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Exp)) {
+ if (const auto *UO = dyn_cast<UnaryOperator>(Exp)) {
// For dereferences
- if (UO->getOpcode() == clang::UO_Deref)
+ if (UO->getOpcode() == UO_Deref)
checkPtAccess(UO->getSubExpr(), AK, POK);
return;
}
- if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
+ if (const auto *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
checkPtAccess(AE->getLHS(), AK, POK);
return;
}
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
+ if (const auto *ME = dyn_cast<MemberExpr>(Exp)) {
if (ME->isArrow())
checkPtAccess(ME->getBase(), AK, POK);
else
@@ -1632,17 +1669,16 @@ void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
ClassifyDiagnostic(I), Loc);
}
-
-/// \brief Checks pt_guarded_by and pt_guarded_var attributes.
+/// Checks pt_guarded_by and pt_guarded_var attributes.
/// POK is the same operationKind that was passed to checkAccess.
void BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK,
ProtectedOperationKind POK) {
while (true) {
- if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
+ if (const auto *PE = dyn_cast<ParenExpr>(Exp)) {
Exp = PE->getSubExpr();
continue;
}
- if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
+ if (const auto *CE = dyn_cast<CastExpr>(Exp)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay) {
// If it's an actual array, and not a pointer, then it's elements
// are protected by GUARDED_BY, not PT_GUARDED_BY;
@@ -1672,7 +1708,7 @@ void BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK,
ClassifyDiagnostic(I), Exp->getExprLoc());
}
-/// \brief Process a function call, method call, constructor call,
+/// Process a function call, method call, constructor call,
/// or destructor call. This involves looking at the attributes on the
/// corresponding function/method/constructor/destructor, issuing warnings,
/// and updating the locksets accordingly.
@@ -1689,23 +1725,22 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
CapExprSet ScopedExclusiveReqs, ScopedSharedReqs;
StringRef CapDiagKind = "mutex";
- // Figure out if we're calling the constructor of scoped lockable class
+ // Figure out if we're constructing an object of scoped lockable class
bool isScopedVar = false;
if (VD) {
- if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
+ if (const auto *CD = dyn_cast<const CXXConstructorDecl>(D)) {
const CXXRecordDecl* PD = CD->getParent();
if (PD && PD->hasAttr<ScopedLockableAttr>())
isScopedVar = true;
}
}
- for(Attr *Atconst : D->attrs()) {
- Attr* At = const_cast<Attr*>(Atconst);
+ for(const Attr *At : D->attrs()) {
switch (At->getKind()) {
// When we encounter a lock function, we need to add the lock to our
// lockset.
case attr::AcquireCapability: {
- auto *A = cast<AcquireCapabilityAttr>(At);
+ const auto *A = cast<AcquireCapabilityAttr>(At);
Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd
: ExclusiveLocksToAdd,
A, Exp, D, VD);
@@ -1718,7 +1753,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
// a warning if it is already there, and will not generate a warning
// if it is not removed.
case attr::AssertExclusiveLock: {
- AssertExclusiveLockAttr *A = cast<AssertExclusiveLockAttr>(At);
+ const auto *A = cast<AssertExclusiveLockAttr>(At);
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
@@ -1730,7 +1765,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
break;
}
case attr::AssertSharedLock: {
- AssertSharedLockAttr *A = cast<AssertSharedLockAttr>(At);
+ const auto *A = cast<AssertSharedLockAttr>(At);
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
@@ -1743,7 +1778,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
}
case attr::AssertCapability: {
- AssertCapabilityAttr *A = cast<AssertCapabilityAttr>(At);
+ const auto *A = cast<AssertCapabilityAttr>(At);
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
for (const auto &AssertLock : AssertLocks)
@@ -1759,7 +1794,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
// When we encounter an unlock function, we need to remove unlocked
// mutexes from the lockset, and flag a warning if they are not there.
case attr::ReleaseCapability: {
- auto *A = cast<ReleaseCapabilityAttr>(At);
+ const auto *A = cast<ReleaseCapabilityAttr>(At);
if (A->isGeneric())
Analyzer->getMutexIDs(GenericLocksToRemove, A, Exp, D, VD);
else if (A->isShared())
@@ -1772,7 +1807,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
}
case attr::RequiresCapability: {
- RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
+ const auto *A = cast<RequiresCapabilityAttr>(At);
for (auto *Arg : A->args()) {
warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
POK_FunctionCall, ClassifyDiagnostic(A),
@@ -1788,7 +1823,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
}
case attr::LocksExcluded: {
- LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);
+ const auto *A = cast<LocksExcludedAttr>(At);
for (auto *Arg : A->args())
warnIfMutexHeld(D, Exp, Arg, ClassifyDiagnostic(A));
break;
@@ -1800,6 +1835,16 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
}
}
+ // Remove locks first to allow lock upgrading/downgrading.
+ // FIXME -- should only fully remove if the attribute refers to 'this'.
+ bool Dtor = isa<CXXDestructorDecl>(D);
+ for (const auto &M : ExclusiveLocksToRemove)
+ Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive, CapDiagKind);
+ for (const auto &M : SharedLocksToRemove)
+ Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared, CapDiagKind);
+ for (const auto &M : GenericLocksToRemove)
+ Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
+
// Add locks.
for (const auto &M : ExclusiveLocksToAdd)
Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>(
@@ -1826,31 +1871,19 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
Scp, MLoc, ExclusiveLocksToAdd, SharedLocksToAdd),
CapDiagKind);
}
-
- // Remove locks.
- // FIXME -- should only fully remove if the attribute refers to 'this'.
- bool Dtor = isa<CXXDestructorDecl>(D);
- for (const auto &M : ExclusiveLocksToRemove)
- Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive, CapDiagKind);
- for (const auto &M : SharedLocksToRemove)
- Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared, CapDiagKind);
- for (const auto &M : GenericLocksToRemove)
- Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
}
-
-/// \brief For unary operations which read and write a variable, we need to
+/// For unary operations which read and write a variable, we need to
/// check whether we hold any required mutexes. Reads are checked in
/// VisitCastExpr.
void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
switch (UO->getOpcode()) {
- case clang::UO_PostDec:
- case clang::UO_PostInc:
- case clang::UO_PreDec:
- case clang::UO_PreInc: {
+ case UO_PostDec:
+ case UO_PostInc:
+ case UO_PreDec:
+ case UO_PreInc:
checkAccess(UO->getSubExpr(), AK_Written);
break;
- }
default:
break;
}
@@ -1869,7 +1902,6 @@ void BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
checkAccess(BO->getLHS(), AK_Written);
}
-
/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
/// need to ensure we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
@@ -1879,23 +1911,21 @@ void BuildLockset::VisitCastExpr(CastExpr *CE) {
checkAccess(CE->getSubExpr(), AK_Read);
}
-
void BuildLockset::VisitCallExpr(CallExpr *Exp) {
bool ExamineArgs = true;
bool OperatorFun = false;
- if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
- MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee());
+ if (const auto *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
+ const auto *ME = dyn_cast<MemberExpr>(CE->getCallee());
// ME can be null when calling a method pointer
- CXXMethodDecl *MD = CE->getMethodDecl();
+ const CXXMethodDecl *MD = CE->getMethodDecl();
if (ME && MD) {
if (ME->isArrow()) {
- if (MD->isConst()) {
+ if (MD->isConst())
checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
- } else { // FIXME -- should be AK_Written
+ else // FIXME -- should be AK_Written
checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
- }
} else {
if (MD->isConst())
checkAccess(CE->getImplicitObjectArgument(), AK_Read);
@@ -1903,7 +1933,7 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
checkAccess(CE->getImplicitObjectArgument(), AK_Read);
}
}
- } else if (CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
+ } else if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
OperatorFun = true;
auto OEop = OE->getOperator();
@@ -1938,13 +1968,11 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
if (ExamineArgs) {
if (FunctionDecl *FD = Exp->getDirectCallee()) {
-
// NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
// only turns off checking within the body of a function, but we also
// use it to turn off checking in arguments to the function. This
// could result in some false negatives, but the alternative is to
// create yet another attribute.
- //
if (!FD->hasAttr<NoThreadSafetyAnalysisAttr>()) {
unsigned Fn = FD->getNumParams();
unsigned Cn = Exp->getNumArgs();
@@ -1976,7 +2004,7 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
}
}
- NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
+ auto *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
if(!D || !D->hasAttrs())
return;
handleCall(Exp, D);
@@ -1991,30 +2019,74 @@ void BuildLockset::VisitCXXConstructExpr(CXXConstructExpr *Exp) {
// FIXME -- only handles constructors in DeclStmt below.
}
+static CXXConstructorDecl *
+findConstructorForByValueReturn(const CXXRecordDecl *RD) {
+ // Prefer a move constructor over a copy constructor. If there's more than
+ // one copy constructor or more than one move constructor, we arbitrarily
+ // pick the first declared such constructor rather than trying to guess which
+ // one is more appropriate.
+ CXXConstructorDecl *CopyCtor = nullptr;
+ for (auto *Ctor : RD->ctors()) {
+ if (Ctor->isDeleted())
+ continue;
+ if (Ctor->isMoveConstructor())
+ return Ctor;
+ if (!CopyCtor && Ctor->isCopyConstructor())
+ CopyCtor = Ctor;
+ }
+ return CopyCtor;
+}
+
+static Expr *buildFakeCtorCall(CXXConstructorDecl *CD, ArrayRef<Expr *> Args,
+ SourceLocation Loc) {
+ ASTContext &Ctx = CD->getASTContext();
+ return CXXConstructExpr::Create(Ctx, Ctx.getRecordType(CD->getParent()), Loc,
+ CD, true, Args, false, false, false, false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange(Loc, Loc));
+}
+
void BuildLockset::VisitDeclStmt(DeclStmt *S) {
// adjust the context
LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
for (auto *D : S->getDeclGroup()) {
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
+ if (auto *VD = dyn_cast_or_null<VarDecl>(D)) {
Expr *E = VD->getInit();
+ if (!E)
+ continue;
+ E = E->IgnoreParens();
+
// handle constructors that involve temporaries
- if (ExprWithCleanups *EWC = dyn_cast_or_null<ExprWithCleanups>(E))
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(E))
E = EWC->getSubExpr();
+ if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = BTE->getSubExpr();
- if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) {
- NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
+ if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
+ const auto *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
if (!CtorD || !CtorD->hasAttrs())
- return;
- handleCall(CE, CtorD, VD);
+ continue;
+ handleCall(E, CtorD, VD);
+ } else if (isa<CallExpr>(E) && E->isRValue()) {
+ // If the object is initialized by a function call that returns a
+ // scoped lockable by value, use the attributes on the copy or move
+ // constructor to figure out what effect that should have on the
+ // lockset.
+ // FIXME: Is this really the best way to handle this situation?
+ auto *RD = E->getType()->getAsCXXRecordDecl();
+ if (!RD || !RD->hasAttr<ScopedLockableAttr>())
+ continue;
+ CXXConstructorDecl *CtorD = findConstructorForByValueReturn(RD);
+ if (!CtorD || !CtorD->hasAttrs())
+ continue;
+ handleCall(buildFakeCtorCall(CtorD, {E}, E->getLocStart()), CtorD, VD);
}
}
}
}
-
-
-/// \brief Compute the intersection of two locksets and issue warnings for any
+/// Compute the intersection of two locksets and issue warnings for any
/// locks in the symmetric difference.
///
/// This function is used at a merge point in the CFG when comparing the lockset
@@ -2076,7 +2148,6 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
}
}
-
// Return true if block B never continues to its successors.
static bool neverReturns(const CFGBlock *B) {
if (B->hasNoReturnElement())
@@ -2092,8 +2163,7 @@ static bool neverReturns(const CFGBlock *B) {
return false;
}
-
-/// \brief Check a function's CFG for thread-safety violations.
+/// Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
@@ -2110,7 +2180,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
CFG *CFGraph = walker.getGraph();
const NamedDecl *D = walker.getDecl();
- const FunctionDecl *CurrentFunction = dyn_cast<FunctionDecl>(D);
+ const auto *CurrentFunction = dyn_cast<FunctionDecl>(D);
CurrentMethod = dyn_cast<CXXMethodDecl>(D);
if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
@@ -2184,10 +2254,13 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
A, nullptr, D);
CapDiagKind = ClassifyDiagnostic(A);
} else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
- // Don't try to check trylock functions for now
+ // Don't try to check trylock functions for now.
return;
} else if (isa<SharedTrylockFunctionAttr>(Attr)) {
- // Don't try to check trylock functions for now
+ // Don't try to check trylock functions for now.
+ return;
+ } else if (isa<TryAcquireCapabilityAttr>(Attr)) {
+ // Don't try to check trylock functions for now.
return;
}
}
@@ -2229,7 +2302,6 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
SmallVector<CFGBlock *, 8> SpecialBlocks;
for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
PE = CurrBlock->pred_end(); PI != PE; ++PI) {
-
// if *PI -> CurrBlock is a back edge
if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI))
continue;
@@ -2306,24 +2378,23 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
BuildLockset LocksetBuilder(this, *CurrBlockInfo);
// Visit all the statements in the basic block.
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
- switch (BI->getKind()) {
+ for (const auto &BI : *CurrBlock) {
+ switch (BI.getKind()) {
case CFGElement::Statement: {
- CFGStmt CS = BI->castAs<CFGStmt>();
- LocksetBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
+ CFGStmt CS = BI.castAs<CFGStmt>();
+ LocksetBuilder.Visit(const_cast<Stmt *>(CS.getStmt()));
break;
}
// Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
case CFGElement::AutomaticObjectDtor: {
- CFGAutomaticObjDtor AD = BI->castAs<CFGAutomaticObjDtor>();
- CXXDestructorDecl *DD = const_cast<CXXDestructorDecl *>(
+ CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
+ auto *DD = const_cast<CXXDestructorDecl *>(
AD.getDestructorDecl(AC.getASTContext()));
if (!DD->hasAttrs())
break;
// Create a dummy expression,
- VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
+ auto *VD = const_cast<VarDecl *>(AD.getVarDecl());
DeclRefExpr DRE(VD, false, VD->getType().getNonReferenceType(),
VK_LValue, AD.getTriggerStmt()->getLocEnd());
LocksetBuilder.handleCall(&DRE, DD);
@@ -2341,7 +2412,6 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
// Lockset held at the beginning of FirstLoopBlock in the EntryLockSets map.
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
-
// if CurrBlock -> *SI is *not* a back edge
if (*SI == nullptr || !VisitedBlocks.alreadySet(*SI))
continue;
@@ -2389,8 +2459,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
Handler.leaveFunction(CurrentFunction);
}
-
-/// \brief Check a function's CFG for thread-safety violations.
+/// Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
@@ -2406,7 +2475,7 @@ void threadSafety::runThreadSafetyAnalysis(AnalysisDeclContext &AC,
void threadSafety::threadSafetyCleanup(BeforeSet *Cache) { delete Cache; }
-/// \brief Helper function that returns a LockKind required for the given level
+/// Helper function that returns a LockKind required for the given level
/// of access.
LockKind threadSafety::getLockKindFromAccessKind(AccessKind AK) {
switch (AK) {
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 99284f07b45b..fced17ff9197 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafetyCommon.cpp -----------------------------------*- C++ -*-===//
+//===- ThreadSafetyCommon.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,24 +13,32 @@
#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
-#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
-#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include <algorithm>
+#include <cassert>
+#include <string>
+#include <utility>
using namespace clang;
using namespace threadSafety;
// From ThreadSafetyUtil.h
-std::string threadSafety::getSourceLiteralString(const clang::Expr *CE) {
+std::string threadSafety::getSourceLiteralString(const Expr *CE) {
switch (CE->getStmtClass()) {
case Stmt::IntegerLiteralClass:
return cast<IntegerLiteral>(CE)->getValue().toString(10, true);
@@ -59,7 +67,7 @@ static bool isIncompletePhi(const til::SExpr *E) {
return false;
}
-typedef SExprBuilder::CallingContext CallingContext;
+using CallingContext = SExprBuilder::CallingContext;
til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
auto It = SMap.find(S);
@@ -74,11 +82,11 @@ til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
}
static bool isCalleeArrow(const Expr *E) {
- const MemberExpr *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
+ const auto *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
return ME ? ME->isArrow() : false;
}
-/// \brief Translate a clang expression in an attribute to a til::SExpr.
+/// Translate a clang expression in an attribute to a til::SExpr.
/// Constructs the context from D, DeclExp, and SelfDecl.
///
/// \param AttrExp The expression to translate.
@@ -97,20 +105,18 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
// Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
// for formal parameters when we call buildMutexID later.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
+ if (const auto *ME = dyn_cast<MemberExpr>(DeclExp)) {
Ctx.SelfArg = ME->getBase();
Ctx.SelfArrow = ME->isArrow();
- } else if (const CXXMemberCallExpr *CE =
- dyn_cast<CXXMemberCallExpr>(DeclExp)) {
+ } else if (const auto *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) {
Ctx.SelfArg = CE->getImplicitObjectArgument();
Ctx.SelfArrow = isCalleeArrow(CE->getCallee());
Ctx.NumArgs = CE->getNumArgs();
Ctx.FunArgs = CE->getArgs();
- } else if (const CallExpr *CE = dyn_cast<CallExpr>(DeclExp)) {
+ } else if (const auto *CE = dyn_cast<CallExpr>(DeclExp)) {
Ctx.NumArgs = CE->getNumArgs();
Ctx.FunArgs = CE->getArgs();
- } else if (const CXXConstructExpr *CE =
- dyn_cast<CXXConstructExpr>(DeclExp)) {
+ } else if (const auto *CE = dyn_cast<CXXConstructExpr>(DeclExp)) {
Ctx.SelfArg = nullptr; // Will be set below
Ctx.NumArgs = CE->getNumArgs();
Ctx.FunArgs = CE->getArgs();
@@ -140,14 +146,14 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
return translateAttrExpr(AttrExp, &Ctx);
}
-/// \brief Translate a clang expression in an attribute to a til::SExpr.
+/// Translate a clang expression in an attribute to a til::SExpr.
// This assumes a CallingContext has already been created.
CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
CallingContext *Ctx) {
if (!AttrExp)
return CapabilityExpr(nullptr, false);
- if (auto* SLit = dyn_cast<StringLiteral>(AttrExp)) {
+ if (const auto* SLit = dyn_cast<StringLiteral>(AttrExp)) {
if (SLit->getString() == StringRef("*"))
// The "*" expr is a universal lock, which essentially turns off
// checks until it is removed from the lockset.
@@ -158,13 +164,13 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
}
bool Neg = false;
- if (auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
+ if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
if (OE->getOperator() == OO_Exclaim) {
Neg = true;
AttrExp = OE->getArg(0);
}
}
- else if (auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
+ else if (const auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
if (UO->getOpcode() == UO_LNot) {
Neg = true;
AttrExp = UO->getSubExpr();
@@ -179,7 +185,7 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
return CapabilityExpr(nullptr, false);
// Hack to deal with smart pointers -- strip off top-level pointer casts.
- if (auto *CE = dyn_cast_or_null<til::Cast>(E)) {
+ if (const auto *CE = dyn_cast_or_null<til::Cast>(E)) {
if (CE->castOpcode() == til::CAST_objToPtr)
return CapabilityExpr(CE->expr(), Neg);
}
@@ -254,7 +260,7 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
default:
break;
}
- if (const CastExpr *CE = dyn_cast<CastExpr>(S))
+ if (const auto *CE = dyn_cast<CastExpr>(S))
return translateCastExpr(CE, Ctx);
return new (Arena) til::Undefined(S);
@@ -262,11 +268,11 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
CallingContext *Ctx) {
- const ValueDecl *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
+ const auto *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
// Function parameters require substitution and/or renaming.
- if (const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
- const FunctionDecl *FD =
+ if (const auto *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
+ const auto *FD =
cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
unsigned I = PV->getFunctionScopeIndex();
@@ -294,13 +300,13 @@ til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
}
static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
- if (auto *V = dyn_cast<til::Variable>(E))
+ if (const auto *V = dyn_cast<til::Variable>(E))
return V->clangDecl();
- if (auto *Ph = dyn_cast<til::Phi>(E))
+ if (const auto *Ph = dyn_cast<til::Phi>(E))
return Ph->clangDecl();
- if (auto *P = dyn_cast<til::Project>(E))
+ if (const auto *P = dyn_cast<til::Project>(E))
return P->clangDecl();
- if (auto *L = dyn_cast<til::LiteralPtr>(E))
+ if (const auto *L = dyn_cast<til::LiteralPtr>(E))
return L->clangDecl();
return nullptr;
}
@@ -309,7 +315,7 @@ static bool hasCppPointerType(const til::SExpr *E) {
auto *VD = getValueDeclFromSExpr(E);
if (VD && VD->getType()->isPointerType())
return true;
- if (auto *C = dyn_cast<til::Cast>(E))
+ if (const auto *C = dyn_cast<til::Cast>(E))
return C->castOpcode() == til::CAST_objToPtr;
return false;
@@ -333,9 +339,8 @@ til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
til::SExpr *BE = translate(ME->getBase(), Ctx);
til::SExpr *E = new (Arena) til::SApply(BE);
- const ValueDecl *D =
- cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
- if (auto *VD = dyn_cast<CXXMethodDecl>(D))
+ const auto *D = cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
+ if (const auto *VD = dyn_cast<CXXMethodDecl>(D))
D = getFirstVirtualDecl(VD);
til::Project *P = new (Arena) til::Project(E, D);
@@ -356,7 +361,7 @@ til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
LRCallCtx.SelfArg = SelfE;
LRCallCtx.NumArgs = CE->getNumArgs();
LRCallCtx.FunArgs = CE->getArgs();
- return const_cast<til::SExpr*>(
+ return const_cast<til::SExpr *>(
translateAttrExpr(At->getArg(), &LRCallCtx).sexpr());
}
}
@@ -407,10 +412,10 @@ til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
case UO_PreDec:
return new (Arena) til::Undefined(UO);
- case UO_AddrOf: {
+ case UO_AddrOf:
if (CapabilityExprMode) {
// interpret &Graph::mu_ as an existential.
- if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) {
if (DRE->getDecl()->isCXXInstanceMember()) {
// This is a pointer-to-member expression, e.g. &MyClass::mu_.
// We interpret this syntax specially, as a wildcard.
@@ -421,7 +426,6 @@ til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
}
// otherwise, & is a no-op
return translate(UO->getSubExpr(), Ctx);
- }
// We treat these as no-ops
case UO_Deref:
@@ -470,7 +474,7 @@ til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op,
const ValueDecl *VD = nullptr;
til::SExpr *CV = nullptr;
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
VD = DRE->getDecl();
CV = lookupVarDecl(VD);
}
@@ -533,10 +537,10 @@ til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
CallingContext *Ctx) {
- clang::CastKind K = CE->getCastKind();
+ CastKind K = CE->getCastKind();
switch (K) {
case CK_LValueToRValue: {
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
til::SExpr *E0 = lookupVarDecl(DRE->getDecl());
if (E0)
return E0;
@@ -584,16 +588,15 @@ SExprBuilder::translateAbstractConditionalOperator(
til::SExpr *
SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
DeclGroupRef DGrp = S->getDeclGroup();
- for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
+ for (auto I : DGrp) {
+ if (auto *VD = dyn_cast_or_null<VarDecl>(I)) {
Expr *E = VD->getInit();
til::SExpr* SE = translate(E, Ctx);
// Add local variables with trivial type to the variable map
QualType T = VD->getType();
- if (T.isTrivialType(VD->getASTContext())) {
+ if (T.isTrivialType(VD->getASTContext()))
return addVarDecl(VD, SE);
- }
else {
// TODO: add alloca
}
@@ -632,7 +635,7 @@ til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
if (!E)
return;
- if (til::Variable *V = dyn_cast<til::Variable>(E)) {
+ if (auto *V = dyn_cast<til::Variable>(E)) {
if (!V->clangDecl())
V->setClangDecl(VD);
}
@@ -672,7 +675,7 @@ void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
if (CurrE->block() == CurrentBB) {
// We already have a Phi node in the current block,
// so just add the new variable to the Phi node.
- til::Phi *Ph = dyn_cast<til::Phi>(CurrE);
+ auto *Ph = dyn_cast<til::Phi>(CurrE);
assert(Ph && "Expecting Phi node.");
if (E)
Ph->values()[ArgIndex] = E;
@@ -690,9 +693,8 @@ void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
Ph->setClangDecl(CurrentLVarMap[i].first);
// If E is from a back-edge, or either E or CurrE are incomplete, then
// mark this node as incomplete; we may need to remove it later.
- if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) {
+ if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE))
Ph->setStatus(til::Phi::PH_Incomplete);
- }
// Add Phi node to current block, and update CurrentLVarMap[i]
CurrentArguments.push_back(Ph);
@@ -721,7 +723,7 @@ void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {
unsigned MSz = Map.size();
unsigned Sz = std::min(ESz, MSz);
- for (unsigned i=0; i<Sz; ++i) {
+ for (unsigned i = 0; i < Sz; ++i) {
if (CurrentLVarMap[i].first != Map[i].first) {
// We've reached the end of variables in common.
CurrentLVarMap.makeWritable();
@@ -758,9 +760,8 @@ void SExprBuilder::mergeEntryMapBackEdge() {
unsigned Sz = CurrentLVarMap.size();
unsigned NPreds = CurrentBB->numPredecessors();
- for (unsigned i=0; i < Sz; ++i) {
+ for (unsigned i = 0; i < Sz; ++i)
makePhiNodeVar(i, NPreds, nullptr);
- }
}
// Update the phi nodes that were initially created for a back edge
@@ -772,7 +773,7 @@ void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) {
assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());
for (til::SExpr *PE : BB->arguments()) {
- til::Phi *Ph = dyn_cast_or_null<til::Phi>(PE);
+ auto *Ph = dyn_cast_or_null<til::Phi>(PE);
assert(Ph && "Expecting Phi Node.");
assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge.");
@@ -816,7 +817,7 @@ void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,
}
void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
- // Intialize TIL basic block and add it to the CFG.
+ // Initialize TIL basic block and add it to the CFG.
CurrentBB = lookupBlock(B);
CurrentBB->reservePredecessors(B->pred_size());
Scfg->add(CurrentBB);
@@ -891,7 +892,7 @@ void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr;
++It;
til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr;
- // FIXME: make sure these arent' critical edges.
+ // FIXME: make sure these aren't critical edges.
auto *Tm = new (Arena) til::Branch(C, BB1, BB2);
CurrentBB->setTerminator(Tm);
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
index cd7cdc69ab73..798bbfb29d7b 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafetyTIL.cpp -------------------------------------*- C++ --*-===//
+//===- ThreadSafetyTIL.cpp ------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
+
using namespace clang;
using namespace threadSafety;
using namespace til;
@@ -19,7 +23,7 @@ StringRef til::getUnaryOpcodeString(TIL_UnaryOpcode Op) {
case UOP_BitNot: return "~";
case UOP_LogicNot: return "!";
}
- return "";
+ return {};
}
StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
@@ -42,10 +46,9 @@ StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
case BOP_LogicAnd: return "&&";
case BOP_LogicOr: return "||";
}
- return "";
+ return {};
}
-
SExpr* Future::force() {
Status = FS_evaluating;
Result = compute();
@@ -53,13 +56,12 @@ SExpr* Future::force() {
return Result;
}
-
unsigned BasicBlock::addPredecessor(BasicBlock *Pred) {
unsigned Idx = Predecessors.size();
Predecessors.reserveCheck(1, Arena);
Predecessors.push_back(Pred);
- for (SExpr *E : Args) {
- if (Phi* Ph = dyn_cast<Phi>(E)) {
+ for (auto *E : Args) {
+ if (auto *Ph = dyn_cast<Phi>(E)) {
Ph->values().reserveCheck(1, Arena);
Ph->values().push_back(nullptr);
}
@@ -67,28 +69,26 @@ unsigned BasicBlock::addPredecessor(BasicBlock *Pred) {
return Idx;
}
-
void BasicBlock::reservePredecessors(unsigned NumPreds) {
Predecessors.reserve(NumPreds, Arena);
- for (SExpr *E : Args) {
- if (Phi* Ph = dyn_cast<Phi>(E)) {
+ for (auto *E : Args) {
+ if (auto *Ph = dyn_cast<Phi>(E)) {
Ph->values().reserve(NumPreds, Arena);
}
}
}
-
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
const SExpr *til::getCanonicalVal(const SExpr *E) {
while (true) {
- if (auto *V = dyn_cast<Variable>(E)) {
+ if (const auto *V = dyn_cast<Variable>(E)) {
if (V->kind() == Variable::VK_Let) {
E = V->definition();
continue;
}
}
- if (const Phi *Ph = dyn_cast<Phi>(E)) {
+ if (const auto *Ph = dyn_cast<Phi>(E)) {
if (Ph->status() == Phi::PH_SingleVal) {
E = Ph->values()[0];
continue;
@@ -99,7 +99,6 @@ const SExpr *til::getCanonicalVal(const SExpr *E) {
return E;
}
-
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
// The non-const version will simplify incomplete Phi nodes.
@@ -129,7 +128,6 @@ SExpr *til::simplifyToCanonicalVal(SExpr *E) {
}
}
-
// Trace the arguments of an incomplete Phi node to see if they have the same
// canonical definition. If so, mark the Phi node as redundant.
// getCanonicalVal() will recursively call simplifyIncompletePhi().
@@ -140,7 +138,7 @@ void til::simplifyIncompleteArg(til::Phi *Ph) {
Ph->setStatus(Phi::PH_MultiVal);
SExpr *E0 = simplifyToCanonicalVal(Ph->values()[0]);
- for (unsigned i=1, n=Ph->values().size(); i<n; ++i) {
+ for (unsigned i = 1, n = Ph->values().size(); i < n; ++i) {
SExpr *Ei = simplifyToCanonicalVal(Ph->values()[i]);
if (Ei == Ph)
continue; // Recursive reference to itself. Don't count.
@@ -151,7 +149,6 @@ void til::simplifyIncompleteArg(til::Phi *Ph) {
Ph->setStatus(Phi::PH_SingleVal);
}
-
// Renumbers the arguments and instructions to have unique, sequential IDs.
int BasicBlock::renumberInstrs(int ID) {
for (auto *Arg : Args)
@@ -166,7 +163,7 @@ int BasicBlock::renumberInstrs(int ID) {
// Each block will be written into the Blocks array in order, and its BlockID
// will be set to the index in the array. Sorting should start from the entry
// block, and ID should be the total number of blocks.
-int BasicBlock::topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID) {
+int BasicBlock::topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID) {
if (Visited) return ID;
Visited = true;
for (auto *Block : successors())
@@ -258,7 +255,6 @@ void BasicBlock::computePostDominator() {
PostDominatorNode.SizeOfSubTree = 1;
}
-
// Renumber instructions in all blocks
void SCFG::renumberInstrs() {
int InstrID = 0;
@@ -266,7 +262,6 @@ void SCFG::renumberInstrs() {
InstrID = Block->renumberInstrs(InstrID);
}
-
static inline void computeNodeSize(BasicBlock *B,
BasicBlock::TopologyNode BasicBlock::*TN) {
BasicBlock::TopologyNode *N = &(B->*TN);
@@ -287,7 +282,6 @@ static inline void computeNodeID(BasicBlock *B,
}
}
-
// Normalizes a CFG. Normalization has a few major components:
// 1) Removing unreachable blocks.
// 2) Computing dominators and post-dominators
diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
index 5f11d8a2a36b..31c88a109565 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
@@ -1,4 +1,4 @@
-//==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==//
+//===- UninitializedValues.cpp - Find Uninitialized Values ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,23 +11,31 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/Analyses/UninitializedValues.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/Analyses/UninitializedValues.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PackedVector.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include <utility>
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cassert>
using namespace clang;
@@ -48,21 +56,24 @@ static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
//====------------------------------------------------------------------------//
namespace {
+
class DeclToIndex {
llvm::DenseMap<const VarDecl *, unsigned> map;
+
public:
- DeclToIndex() {}
-
+ DeclToIndex() = default;
+
/// Compute the actual mapping from declarations to bits.
void computeMap(const DeclContext &dc);
-
+
/// Return the number of declarations in the map.
unsigned size() const { return map.size(); }
-
+
/// Returns the bit vector index for a given declaration.
Optional<unsigned> getValueIndex(const VarDecl *d) const;
};
-}
+
+} // namespace
void DeclToIndex::computeMap(const DeclContext &dc) {
unsigned count = 0;
@@ -96,25 +107,28 @@ enum Value { Unknown = 0x0, /* 00 */
static bool isUninitialized(const Value v) {
return v >= Uninitialized;
}
+
static bool isAlwaysUninit(const Value v) {
return v == Uninitialized;
}
namespace {
-typedef llvm::PackedVector<Value, 2, llvm::SmallBitVector> ValueVector;
+using ValueVector = llvm::PackedVector<Value, 2, llvm::SmallBitVector>;
class CFGBlockValues {
const CFG &cfg;
SmallVector<ValueVector, 8> vals;
ValueVector scratch;
DeclToIndex declToIndex;
+
public:
CFGBlockValues(const CFG &cfg);
unsigned getNumEntries() const { return declToIndex.size(); }
-
- void computeSetOfDeclarations(const DeclContext &dc);
+
+ void computeSetOfDeclarations(const DeclContext &dc);
+
ValueVector &getValueVector(const CFGBlock *block) {
return vals[block->getBlockID()];
}
@@ -122,13 +136,13 @@ public:
void setAllScratchValues(Value V);
void mergeIntoScratch(ValueVector const &source, bool isFirst);
bool updateValueVectorWithScratch(const CFGBlock *block);
-
+
bool hasNoDeclarations() const {
return declToIndex.size() == 0;
}
void resetScratch();
-
+
ValueVector::reference operator[](const VarDecl *vd);
Value getValue(const CFGBlock *block, const CFGBlock *dstBlock,
@@ -137,8 +151,9 @@ public:
assert(idx.hasValue());
return getValueVector(block)[idx.getValue()];
}
-};
-} // end anonymous namespace
+};
+
+} // namespace
CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {}
@@ -150,17 +165,16 @@ void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
if (!n)
return;
vals.resize(n);
- for (unsigned i = 0; i < n; ++i)
- vals[i].resize(decls);
+ for (auto &val : vals)
+ val.resize(decls);
}
#if DEBUG_LOGGING
static void printVector(const CFGBlock *block, ValueVector &bv,
unsigned num) {
llvm::errs() << block->getBlockID() << " :";
- for (unsigned i = 0; i < bv.size(); ++i) {
- llvm::errs() << ' ' << bv[i];
- }
+ for (const auto &i : bv)
+ llvm::errs() << ' ' << i;
llvm::errs() << " : " << num << '\n';
}
#endif
@@ -204,28 +218,31 @@ ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
//====------------------------------------------------------------------------//
namespace {
+
class DataflowWorklist {
PostOrderCFGView::iterator PO_I, PO_E;
SmallVector<const CFGBlock *, 20> worklist;
llvm::BitVector enqueuedBlocks;
+
public:
DataflowWorklist(const CFG &cfg, PostOrderCFGView &view)
- : PO_I(view.begin()), PO_E(view.end()),
- enqueuedBlocks(cfg.getNumBlockIDs(), true) {
- // Treat the first block as already analyzed.
- if (PO_I != PO_E) {
- assert(*PO_I == &cfg.getEntry());
- enqueuedBlocks[(*PO_I)->getBlockID()] = false;
- ++PO_I;
- }
- }
-
+ : PO_I(view.begin()), PO_E(view.end()),
+ enqueuedBlocks(cfg.getNumBlockIDs(), true) {
+ // Treat the first block as already analyzed.
+ if (PO_I != PO_E) {
+ assert(*PO_I == &cfg.getEntry());
+ enqueuedBlocks[(*PO_I)->getBlockID()] = false;
+ ++PO_I;
+ }
+ }
+
void enqueueSuccessors(const CFGBlock *block);
const CFGBlock *dequeue();
};
-}
-void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
+} // namespace
+
+void DataflowWorklist::enqueueSuccessors(const CFGBlock *block) {
for (CFGBlock::const_succ_iterator I = block->succ_begin(),
E = block->succ_end(); I != E; ++I) {
const CFGBlock *Successor = *I;
@@ -250,9 +267,8 @@ const CFGBlock *DataflowWorklist::dequeue() {
B = *PO_I;
++PO_I;
}
- else {
+ else
return nullptr;
- }
assert(enqueuedBlocks[B->getBlockID()] == true);
enqueuedBlocks[B->getBlockID()] = false;
@@ -264,9 +280,11 @@ const CFGBlock *DataflowWorklist::dequeue() {
//====------------------------------------------------------------------------//
namespace {
+
class FindVarResult {
const VarDecl *vd;
const DeclRefExpr *dr;
+
public:
FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {}
@@ -274,10 +292,12 @@ public:
const VarDecl *getDecl() const { return vd; }
};
+} // namespace
+
static const Expr *stripCasts(ASTContext &C, const Expr *Ex) {
while (Ex) {
Ex = Ex->IgnoreParenNoopCasts(C);
- if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+ if (const auto *CE = dyn_cast<CastExpr>(Ex)) {
if (CE->getCastKind() == CK_LValueBitCast) {
Ex = CE->getSubExpr();
continue;
@@ -291,15 +311,17 @@ static const Expr *stripCasts(ASTContext &C, const Expr *Ex) {
/// If E is an expression comprising a reference to a single variable, find that
/// variable.
static FindVarResult findVar(const Expr *E, const DeclContext *DC) {
- if (const DeclRefExpr *DRE =
- dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
- if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (const auto *DRE =
+ dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (isTrackedVar(VD, DC))
return FindVarResult(VD, DRE);
return FindVarResult(nullptr, nullptr);
}
-/// \brief Classify each DeclRefExpr as an initialization or a use. Any
+namespace {
+
+/// Classify each DeclRefExpr as an initialization or a use. Any
/// DeclRefExpr which isn't explicitly classified will be assumed to have
/// escaped the analysis and will be treated as an initialization.
class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
@@ -313,7 +335,7 @@ public:
private:
const DeclContext *DC;
- llvm::DenseMap<const DeclRefExpr*, Class> Classification;
+ llvm::DenseMap<const DeclRefExpr *, Class> Classification;
bool isTrackedVar(const VarDecl *VD) const {
return ::isTrackedVar(VD, DC);
@@ -338,21 +360,22 @@ public:
if (I != Classification.end())
return I->second;
- const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
if (!VD || !isTrackedVar(VD))
return Ignore;
return Init;
}
};
-}
+
+} // namespace
static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
if (VD->getType()->isRecordType())
return nullptr;
if (Expr *Init = VD->getInit()) {
- const DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
+ const auto *DRE =
+ dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
if (DRE && DRE->getDecl() == VD)
return DRE;
}
@@ -362,32 +385,31 @@ static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
void ClassifyRefs::classify(const Expr *E, Class C) {
// The result of a ?: could also be an lvalue.
E = E->IgnoreParens();
- if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
classify(CO->getTrueExpr(), C);
classify(CO->getFalseExpr(), C);
return;
}
- if (const BinaryConditionalOperator *BCO =
- dyn_cast<BinaryConditionalOperator>(E)) {
+ if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
classify(BCO->getFalseExpr(), C);
return;
}
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) {
classify(OVE->getSourceExpr(), C);
return;
}
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (VarDecl *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
if (!VD->isStaticDataMember())
classify(ME->getBase(), C);
}
return;
}
- if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
case BO_PtrMemD:
case BO_PtrMemI:
@@ -408,7 +430,7 @@ void ClassifyRefs::classify(const Expr *E, Class C) {
void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
for (auto *DI : DS->decls()) {
- VarDecl *VD = dyn_cast<VarDecl>(DI);
+ auto *VD = dyn_cast<VarDecl>(DI);
if (VD && isTrackedVar(VD))
if (const DeclRefExpr *DRE = getSelfInitExpr(VD))
Classification[DRE] = SelfInit;
@@ -457,7 +479,7 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
classify((*I), Ignore);
} else if (isPointerToConst((*I)->getType())) {
const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
- const UnaryOperator *UO = dyn_cast<UnaryOperator>(Ex);
+ const auto *UO = dyn_cast<UnaryOperator>(Ex);
if (UO && UO->getOpcode() == UO_AddrOf)
Ex = UO->getSubExpr();
classify(Ex, Ignore);
@@ -468,7 +490,7 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
if (CE->getCastKind() == CK_LValueToRValue)
classify(CE->getSubExpr(), Use);
- else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) {
+ else if (const auto *CSE = dyn_cast<CStyleCastExpr>(CE)) {
if (CSE->getType()->isVoidType()) {
// Squelch any detected load of an uninitialized value if
// we cast it to void.
@@ -483,6 +505,7 @@ void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
//====------------------------------------------------------------------------//
namespace {
+
class TransferFunctions : public StmtVisitor<TransferFunctions> {
CFGBlockValues &vals;
const CFG &cfg;
@@ -497,9 +520,9 @@ public:
const CFGBlock *block, AnalysisDeclContext &ac,
const ClassifyRefs &classification,
UninitVariablesHandler &handler)
- : vals(vals), cfg(cfg), block(block), ac(ac),
- classification(classification), objCNoRet(ac.getASTContext()),
- handler(handler) {}
+ : vals(vals), cfg(cfg), block(block), ac(ac),
+ classification(classification), objCNoRet(ac.getASTContext()),
+ handler(handler) {}
void reportUse(const Expr *ex, const VarDecl *vd);
@@ -591,7 +614,7 @@ public:
const CFGBlock *Pred = *I;
if (!Pred)
continue;
-
+
Value AtPredExit = vals.getValue(Pred, B, vd);
if (AtPredExit == Initialized)
// This block initializes the variable.
@@ -627,8 +650,7 @@ public:
// Scan the frontier, looking for blocks where the variable was
// uninitialized.
- for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
- const CFGBlock *Block = *BI;
+ for (const auto *Block : cfg) {
unsigned BlockID = Block->getBlockID();
const Stmt *Term = Block->getTerminator();
if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() &&
@@ -668,7 +690,8 @@ public:
return Use;
}
};
-}
+
+} // namespace
void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
Value v = vals[vd];
@@ -678,8 +701,8 @@ void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
// This represents an initialization of the 'element' value.
- if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) {
- const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) {
+ const auto *VD = cast<VarDecl>(DS->getSingleDecl());
if (isTrackedVar(VD))
vals[VD] = Initialized;
}
@@ -748,7 +771,7 @@ void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) {
void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
for (auto *DI : DS->decls()) {
- VarDecl *VD = dyn_cast<VarDecl>(DI);
+ auto *VD = dyn_cast<VarDecl>(DI);
if (VD && isTrackedVar(VD)) {
if (getSelfInitExpr(VD)) {
// If the initializer consists solely of a reference to itself, we
@@ -815,34 +838,32 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
}
// Apply the transfer function.
TransferFunctions tf(vals, cfg, block, ac, classification, handler);
- for (CFGBlock::const_iterator I = block->begin(), E = block->end();
- I != E; ++I) {
- if (Optional<CFGStmt> cs = I->getAs<CFGStmt>())
- tf.Visit(const_cast<Stmt*>(cs->getStmt()));
+ for (const auto &I : *block) {
+ if (Optional<CFGStmt> cs = I.getAs<CFGStmt>())
+ tf.Visit(const_cast<Stmt *>(cs->getStmt()));
}
return vals.updateValueVectorWithScratch(block);
}
+namespace {
+
/// PruneBlocksHandler is a special UninitVariablesHandler that is used
/// to detect when a CFGBlock has any *potential* use of an uninitialized
/// variable. It is mainly used to prune out work during the final
/// reporting pass.
-namespace {
struct PruneBlocksHandler : public UninitVariablesHandler {
- PruneBlocksHandler(unsigned numBlocks)
- : hadUse(numBlocks, false), hadAnyUse(false),
- currentBlock(0) {}
-
- ~PruneBlocksHandler() override {}
-
/// Records if a CFGBlock had a potential use of an uninitialized variable.
llvm::BitVector hadUse;
/// Records if any CFGBlock had a potential use of an uninitialized variable.
- bool hadAnyUse;
+ bool hadAnyUse = false;
/// The current block to scribble use information.
- unsigned currentBlock;
+ unsigned currentBlock = 0;
+
+ PruneBlocksHandler(unsigned numBlocks) : hadUse(numBlocks, false) {}
+
+ ~PruneBlocksHandler() override = default;
void handleUseOfUninitVariable(const VarDecl *vd,
const UninitUse &use) override {
@@ -858,7 +879,8 @@ struct PruneBlocksHandler : public UninitVariablesHandler {
hadAnyUse = true;
}
};
-}
+
+} // namespace
void clang::runUninitializedVariablesAnalysis(
const DeclContext &dc,
@@ -881,7 +903,7 @@ void clang::runUninitializedVariablesAnalysis(
const CFGBlock &entry = cfg.getEntry();
ValueVector &vec = vals.getValueVector(&entry);
const unsigned n = vals.getNumEntries();
- for (unsigned j = 0; j < n ; ++j) {
+ for (unsigned j = 0; j < n; ++j) {
vec[j] = Uninitialized;
}
@@ -901,7 +923,7 @@ void clang::runUninitializedVariablesAnalysis(
classification, wasAnalyzed, PBH);
++stats.NumBlockVisits;
if (changed || !previouslyVisited[block->getBlockID()])
- worklist.enqueueSuccessors(block);
+ worklist.enqueueSuccessors(block);
previouslyVisited[block->getBlockID()] = true;
}
@@ -909,13 +931,11 @@ void clang::runUninitializedVariablesAnalysis(
return;
// Run through the blocks one more time, and report uninitialized variables.
- for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
- const CFGBlock *block = *BI;
+ for (const auto *block : cfg)
if (PBH.hadUse[block->getBlockID()]) {
runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
++stats.NumBlockVisits;
}
- }
}
-UninitVariablesHandler::~UninitVariablesHandler() {}
+UninitVariablesHandler::~UninitVariablesHandler() = default;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
index ed7f87c9b95c..a3210ba09068 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
@@ -107,6 +107,22 @@ void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) {
Table.get(getRecord(ID).Name).setBuiltinID(0);
}
+unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const {
+ const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V');
+ if (!WidthPos)
+ return 0;
+
+ ++WidthPos;
+ assert(*WidthPos == ':' &&
+ "Vector width specifier must be followed by a ':'");
+ ++WidthPos;
+
+ char *EndPos;
+ unsigned Width = ::strtol(WidthPos, &EndPos, 10);
+ assert(*EndPos == ':' && "Vector width specific must end with a ':'");
+ return Width;
+}
+
bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
bool &HasVAListArg, const char *Fmt) const {
assert(Fmt && "Not passed a format string");
@@ -139,3 +155,10 @@ bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
bool &HasVAListArg) {
return isLike(ID, FormatIdx, HasVAListArg, "sS");
}
+
+bool Builtin::Context::canBeRedeclared(unsigned ID) const {
+ return ID == Builtin::NotBuiltin ||
+ ID == Builtin::BI__va_start ||
+ (!hasReferenceArgsOrResult(ID) &&
+ !hasCustomTypechecking(ID));
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp b/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
index 58b99a3b58cb..dc7e61c02b24 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
@@ -18,12 +18,18 @@ const char *CudaVersionToString(CudaVersion V) {
return "8.0";
case CudaVersion::CUDA_90:
return "9.0";
+ case CudaVersion::CUDA_91:
+ return "9.1";
+ case CudaVersion::CUDA_92:
+ return "9.2";
}
llvm_unreachable("invalid enum");
}
const char *CudaArchToString(CudaArch A) {
switch (A) {
+ case CudaArch::LAST:
+ break;
case CudaArch::UNKNOWN:
return "unknown";
case CudaArch::SM_20:
@@ -52,6 +58,34 @@ const char *CudaArchToString(CudaArch A) {
return "sm_62";
case CudaArch::SM_70:
return "sm_70";
+ case CudaArch::SM_72:
+ return "sm_72";
+ case CudaArch::GFX600: // tahiti
+ return "gfx600";
+ case CudaArch::GFX601: // pitcairn, verde, oland,hainan
+ return "gfx601";
+ case CudaArch::GFX700: // kaveri
+ return "gfx700";
+ case CudaArch::GFX701: // hawaii
+ return "gfx701";
+ case CudaArch::GFX702: // 290,290x,R390,R390x
+ return "gfx702";
+ case CudaArch::GFX703: // kabini mullins
+ return "gfx703";
+ case CudaArch::GFX704: // bonaire
+ return "gfx704";
+ case CudaArch::GFX801: // carrizo
+ return "gfx801";
+ case CudaArch::GFX802: // tonga,iceland
+ return "gfx802";
+ case CudaArch::GFX803: // fiji,polaris10
+ return "gfx803";
+ case CudaArch::GFX810: // stoney
+ return "gfx810";
+ case CudaArch::GFX900: // vega, instinct
+ return "gfx900";
+ case CudaArch::GFX902: // TBA
+ return "gfx902";
}
llvm_unreachable("invalid enum");
}
@@ -71,6 +105,20 @@ CudaArch StringToCudaArch(llvm::StringRef S) {
.Case("sm_61", CudaArch::SM_61)
.Case("sm_62", CudaArch::SM_62)
.Case("sm_70", CudaArch::SM_70)
+ .Case("sm_72", CudaArch::SM_72)
+ .Case("gfx600", CudaArch::GFX600)
+ .Case("gfx601", CudaArch::GFX601)
+ .Case("gfx700", CudaArch::GFX700)
+ .Case("gfx701", CudaArch::GFX701)
+ .Case("gfx702", CudaArch::GFX702)
+ .Case("gfx703", CudaArch::GFX703)
+ .Case("gfx704", CudaArch::GFX704)
+ .Case("gfx801", CudaArch::GFX801)
+ .Case("gfx802", CudaArch::GFX802)
+ .Case("gfx803", CudaArch::GFX803)
+ .Case("gfx810", CudaArch::GFX810)
+ .Case("gfx900", CudaArch::GFX900)
+ .Case("gfx902", CudaArch::GFX902)
.Default(CudaArch::UNKNOWN);
}
@@ -102,6 +150,10 @@ const char *CudaVirtualArchToString(CudaVirtualArch A) {
return "compute_62";
case CudaVirtualArch::COMPUTE_70:
return "compute_70";
+ case CudaVirtualArch::COMPUTE_72:
+ return "compute_72";
+ case CudaVirtualArch::COMPUTE_AMDGCN:
+ return "compute_amdgcn";
}
llvm_unreachable("invalid enum");
}
@@ -120,11 +172,15 @@ CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
.Case("compute_61", CudaVirtualArch::COMPUTE_61)
.Case("compute_62", CudaVirtualArch::COMPUTE_62)
.Case("compute_70", CudaVirtualArch::COMPUTE_70)
+ .Case("compute_72", CudaVirtualArch::COMPUTE_72)
+ .Case("compute_amdgcn", CudaVirtualArch::COMPUTE_AMDGCN)
.Default(CudaVirtualArch::UNKNOWN);
}
CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
switch (A) {
+ case CudaArch::LAST:
+ break;
case CudaArch::UNKNOWN:
return CudaVirtualArch::UNKNOWN;
case CudaArch::SM_20:
@@ -152,12 +208,30 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
return CudaVirtualArch::COMPUTE_62;
case CudaArch::SM_70:
return CudaVirtualArch::COMPUTE_70;
+ case CudaArch::SM_72:
+ return CudaVirtualArch::COMPUTE_72;
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ return CudaVirtualArch::COMPUTE_AMDGCN;
}
llvm_unreachable("invalid enum");
}
CudaVersion MinVersionForCudaArch(CudaArch A) {
switch (A) {
+ case CudaArch::LAST:
+ break;
case CudaArch::UNKNOWN:
return CudaVersion::UNKNOWN;
case CudaArch::SM_20:
@@ -176,6 +250,22 @@ CudaVersion MinVersionForCudaArch(CudaArch A) {
return CudaVersion::CUDA_80;
case CudaArch::SM_70:
return CudaVersion::CUDA_90;
+ case CudaArch::SM_72:
+ return CudaVersion::CUDA_91;
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ return CudaVersion::CUDA_70;
}
llvm_unreachable("invalid enum");
}
@@ -186,6 +276,19 @@ CudaVersion MaxVersionForCudaArch(CudaArch A) {
return CudaVersion::UNKNOWN;
case CudaArch::SM_20:
case CudaArch::SM_21:
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
return CudaVersion::CUDA_80;
default:
return CudaVersion::LATEST;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
index 26baa838f8c6..f1ebd9d38b9e 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -1,4 +1,4 @@
-//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
+//===- Diagnostic.cpp - C Language Family Diagnostic Handling -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,15 +14,30 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/DiagnosticError.h"
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Locale.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
using namespace clang;
@@ -57,27 +72,13 @@ static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
Output.append(Str.begin(), Str.end());
}
-DiagnosticsEngine::DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> diags,
- DiagnosticOptions *DiagOpts,
- DiagnosticConsumer *client,
- bool ShouldOwnClient)
- : Diags(std::move(diags)), DiagOpts(DiagOpts), Client(nullptr),
- SourceMgr(nullptr) {
+DiagnosticsEngine::DiagnosticsEngine(
+ IntrusiveRefCntPtr<DiagnosticIDs> diags,
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, DiagnosticConsumer *client,
+ bool ShouldOwnClient)
+ : Diags(std::move(diags)), DiagOpts(std::move(DiagOpts)) {
setClient(client, ShouldOwnClient);
ArgToStringFn = DummyArgToStringFn;
- ArgToStringCookie = nullptr;
-
- AllExtensionsSilenced = 0;
- SuppressAfterFatalError = true;
- SuppressAllDiagnostics = false;
- ElideType = true;
- PrintTemplateTree = false;
- ShowColors = false;
- ShowOverloads = Ovl_All;
-
- ErrorLimit = 0;
- TemplateBacktraceLimit = 0;
- ConstexprBacktraceLimit = 0;
Reset();
}
@@ -115,13 +116,13 @@ void DiagnosticsEngine::Reset() {
UncompilableErrorOccurred = false;
FatalErrorOccurred = false;
UnrecoverableErrorOccurred = false;
-
+
NumWarnings = 0;
NumErrors = 0;
TrapNumErrorsOccurred = 0;
TrapNumUnrecoverableErrorsOccurred = 0;
-
- CurDiagID = ~0U;
+
+ CurDiagID = std::numeric_limits<unsigned>::max();
LastDiagLevel = DiagnosticIDs::Ignored;
DelayedDiagID = 0;
@@ -152,8 +153,7 @@ void DiagnosticsEngine::ReportDelayed() {
Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
}
-void DiagnosticsEngine::DiagStateMap::appendFirst(
- DiagState *State) {
+void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
assert(Files.empty() && "not first");
FirstDiagState = CurDiagState = State;
CurDiagStateLoc = SourceLocation();
@@ -236,6 +236,96 @@ DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
return &F;
}
+void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
+ StringRef DiagName) const {
+ llvm::errs() << "diagnostic state at ";
+ CurDiagStateLoc.dump(SrcMgr);
+ llvm::errs() << ": " << CurDiagState << "\n";
+
+ for (auto &F : Files) {
+ FileID ID = F.first;
+ File &File = F.second;
+
+ bool PrintedOuterHeading = false;
+ auto PrintOuterHeading = [&] {
+ if (PrintedOuterHeading) return;
+ PrintedOuterHeading = true;
+
+ llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue()
+ << ">: " << SrcMgr.getBuffer(ID)->getBufferIdentifier();
+ if (F.second.Parent) {
+ std::pair<FileID, unsigned> Decomp =
+ SrcMgr.getDecomposedIncludedLoc(ID);
+ assert(File.ParentOffset == Decomp.second);
+ llvm::errs() << " parent " << File.Parent << " <FileID "
+ << Decomp.first.getHashValue() << "> ";
+ SrcMgr.getLocForStartOfFile(Decomp.first)
+ .getLocWithOffset(Decomp.second)
+ .dump(SrcMgr);
+ }
+ if (File.HasLocalTransitions)
+ llvm::errs() << " has_local_transitions";
+ llvm::errs() << "\n";
+ };
+
+ if (DiagName.empty())
+ PrintOuterHeading();
+
+ for (DiagStatePoint &Transition : File.StateTransitions) {
+ bool PrintedInnerHeading = false;
+ auto PrintInnerHeading = [&] {
+ if (PrintedInnerHeading) return;
+ PrintedInnerHeading = true;
+
+ PrintOuterHeading();
+ llvm::errs() << " ";
+ SrcMgr.getLocForStartOfFile(ID)
+ .getLocWithOffset(Transition.Offset)
+ .dump(SrcMgr);
+ llvm::errs() << ": state " << Transition.State << ":\n";
+ };
+
+ if (DiagName.empty())
+ PrintInnerHeading();
+
+ for (auto &Mapping : *Transition.State) {
+ StringRef Option =
+ DiagnosticIDs::getWarningOptionForDiag(Mapping.first);
+ if (!DiagName.empty() && DiagName != Option)
+ continue;
+
+ PrintInnerHeading();
+ llvm::errs() << " ";
+ if (Option.empty())
+ llvm::errs() << "<unknown " << Mapping.first << ">";
+ else
+ llvm::errs() << Option;
+ llvm::errs() << ": ";
+
+ switch (Mapping.second.getSeverity()) {
+ case diag::Severity::Ignored: llvm::errs() << "ignored"; break;
+ case diag::Severity::Remark: llvm::errs() << "remark"; break;
+ case diag::Severity::Warning: llvm::errs() << "warning"; break;
+ case diag::Severity::Error: llvm::errs() << "error"; break;
+ case diag::Severity::Fatal: llvm::errs() << "fatal"; break;
+ }
+
+ if (!Mapping.second.isUser())
+ llvm::errs() << " default";
+ if (Mapping.second.isPragma())
+ llvm::errs() << " pragma";
+ if (Mapping.second.hasNoWarningAsError())
+ llvm::errs() << " no-error";
+ if (Mapping.second.hasNoErrorAsFatal())
+ llvm::errs() << " no-fatal";
+ if (Mapping.second.wasUpgradedFromWarning())
+ llvm::errs() << " overruled";
+ llvm::errs() << "\n";
+ }
+ }
+ }
+}
+
void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
SourceLocation Loc) {
assert(Loc.isValid() && "Adding invalid loc point");
@@ -373,7 +463,8 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
}
void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
- assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
+ assert(CurDiagID == std::numeric_limits<unsigned>::max() &&
+ "Multiple diagnostics in flight at once!");
CurDiagLoc = storedDiag.getLocation();
CurDiagID = storedDiag.getID();
@@ -394,7 +485,7 @@ void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
++NumWarnings;
}
- CurDiagID = ~0U;
+ CurDiagID = std::numeric_limits<unsigned>::max();
}
bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
@@ -429,8 +520,7 @@ bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
return Emitted;
}
-
-DiagnosticConsumer::~DiagnosticConsumer() {}
+DiagnosticConsumer::~DiagnosticConsumer() = default;
void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) {
@@ -447,7 +537,7 @@ void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
template <std::size_t StrLen>
static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
const char (&Str)[StrLen]) {
- return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
+ return StrLen-1 == ModifierLen && memcmp(Modifier, Str, StrLen-1) == 0;
}
/// ScanForward - Scans forward, looking for the given character, skipping
@@ -527,7 +617,6 @@ static void HandleOrdinalModifier(unsigned ValNo,
Out << ValNo << llvm::getOrdinalSuffix(ValNo);
}
-
/// PluralNumber - Parse an unsigned integer and advance Start.
static unsigned PluralNumber(const char *&Start, const char *End) {
// Programming 101: Parse a decimal number :-)
@@ -563,7 +652,7 @@ static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
if (*Start == ':')
return true;
- while (1) {
+ while (true) {
char C = *Start;
if (C == '%') {
// Modulo expression
@@ -628,7 +717,7 @@ static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
const char *Argument, unsigned ArgumentLen,
SmallVectorImpl<char> &OutStr) {
const char *ArgumentEnd = Argument + ArgumentLen;
- while (1) {
+ while (true) {
assert(Argument < ArgumentEnd && "Plural expression didn't match.");
const char *ExprEnd = Argument;
while (*ExprEnd != ':') {
@@ -648,7 +737,7 @@ static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
}
}
-/// \brief Returns the friendly description for a token kind that will appear
+/// Returns the friendly description for a token kind that will appear
/// without quotes in diagnostic messages. These strings may be translatable in
/// future.
static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) {
@@ -670,7 +759,7 @@ FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
return;
}
- StringRef Diag =
+ StringRef Diag =
getDiags()->getDiagnosticIDs()->getDescription(getID());
FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
@@ -679,7 +768,6 @@ FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
void Diagnostic::
FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
SmallVectorImpl<char> &OutStr) const {
-
// When the diagnostic string is only "%0", the entire string is being given
// by an outside source. Remove unprintable characters from this string
// and skip all the other string processing.
@@ -792,7 +880,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
continue;
}
}
-
+
switch (Kind) {
// ---- STRINGS ----
case DiagnosticsEngine::ak_std_string: {
@@ -899,7 +987,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
FormattedArgs,
OutStr, QualTypeVals);
break;
- case DiagnosticsEngine::ak_qualtype_pair:
+ case DiagnosticsEngine::ak_qualtype_pair: {
// Create a struct with all the info needed for printing.
TemplateDiffTypes TDT;
TDT.FromType = getRawArg(ArgNo);
@@ -967,7 +1055,8 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
break;
}
-
+ }
+
// Remember this argument info for subsequent formatting operations. Turn
// std::strings into a null terminated string to make it be the same case as
// all the other ones.
@@ -978,7 +1067,6 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
else
FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
(intptr_t)getArgStdStr(ArgNo).c_str()));
-
}
// Append the type tree to the end of the diagnostics.
@@ -987,12 +1075,11 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message)
- : ID(ID), Level(Level), Loc(), Message(Message) { }
+ : ID(ID), Level(Level), Message(Message) {}
-StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
+StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info)
- : ID(Info.getID()), Level(Level)
-{
+ : ID(Info.getID()), Level(Level) {
assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
"Valid source location without setting a source manager for diagnostic");
if (Info.getLocation().isValid())
@@ -1008,8 +1095,8 @@ StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message, FullSourceLoc Loc,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixIts)
- : ID(ID), Level(Level), Loc(Loc), Message(Message),
- Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
+ : ID(ID), Level(Level), Loc(Loc), Message(Message),
+ Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
{
}
@@ -1019,9 +1106,9 @@ StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
/// reported by DiagnosticsEngine.
bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
-void IgnoringDiagConsumer::anchor() { }
+void IgnoringDiagConsumer::anchor() {}
-ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() {}
+ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() = default;
void ForwardingDiagnosticConsumer::HandleDiagnostic(
DiagnosticsEngine::Level DiagLevel,
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index c4c425d9eb1d..8f2c3d06a504 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -340,7 +340,7 @@ bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
getBuiltinDiagClass(DiagID) != CLASS_ERROR;
}
-/// \brief Determine whether the given built-in diagnostic ID is a
+/// Determine whether the given built-in diagnostic ID is a
/// Note.
bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
return DiagID < diag::DIAG_UPPER_LIMIT &&
@@ -412,7 +412,7 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
}
-/// \brief Based on the way the client configured the Diagnostic
+/// Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
///
@@ -470,7 +470,7 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
Result = diag::Severity::Error;
}
- // If -Wfatal-errors is enabled, map errors to fatal unless explicity
+ // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
// disabled.
if (Result == diag::Severity::Error) {
if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
@@ -685,7 +685,7 @@ bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
++Diag.NumErrors;
}
- // If we've emitted a lot of errors, emit a fatal error instead of it to
+ // If we've emitted a lot of errors, emit a fatal error instead of it to
// stop a flood of bogus errors.
if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
DiagLevel == DiagnosticIDs::Error) {
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
index 93c2196ca979..ebd9bb45f380 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
@@ -1,4 +1,4 @@
-//===--- DiagnosticOptions.cpp - C Language Family Diagnostic Handling ----===//
+//===- DiagnosticOptions.cpp - C Language Family Diagnostic Handling ------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,6 +13,7 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "llvm/Support/raw_ostream.h"
+#include <type_traits>
namespace clang {
@@ -21,4 +22,4 @@ raw_ostream &operator<<(raw_ostream &Out, DiagnosticLevelMask M) {
return Out << static_cast<UT>(M);
}
-} // end namespace clang
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
index a3e226d6cc96..d339b972ae8e 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -71,7 +71,7 @@ void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
StatCache = std::move(statCache);
return;
}
-
+
FileSystemStatCache *LastCache = StatCache.get();
while (LastCache->getNextStatCache())
LastCache = LastCache->getNextStatCache();
@@ -82,18 +82,18 @@ void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
void FileManager::removeStatCache(FileSystemStatCache *statCache) {
if (!statCache)
return;
-
+
if (StatCache.get() == statCache) {
// This is the first stat cache.
StatCache = StatCache->takeNextStatCache();
return;
}
-
+
// Find the stat cache in the list.
FileSystemStatCache *PrevCache = StatCache.get();
while (PrevCache && PrevCache->getNextStatCache() != statCache)
PrevCache = PrevCache->getNextStatCache();
-
+
assert(PrevCache && "Stat cache not found for removal");
PrevCache->setNextStatCache(statCache->takeNextStatCache());
}
@@ -102,7 +102,7 @@ void FileManager::clearStatCaches() {
StatCache.reset();
}
-/// \brief Retrieve the directory that the given file name resides in.
+/// Retrieve the directory that the given file name resides in.
/// Filename can point to either a real file or a virtual file.
static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
StringRef Filename,
@@ -157,7 +157,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
DirName != llvm::sys::path::root_path(DirName) &&
llvm::sys::path::is_separator(DirName.back()))
DirName = DirName.substr(0, DirName.size()-1);
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
// Fixing a problem with "clang C:test.c" on Windows.
// Stat("C:") does not recognize "C:" as a valid directory
std::string DirNameStr;
@@ -247,7 +247,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
return nullptr;
}
-
+
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
@@ -394,7 +394,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
StringRef pathRef(path.data(), path.size());
- if (FileSystemOpts.WorkingDir.empty()
+ if (FileSystemOpts.WorkingDir.empty()
|| llvm::sys::path::is_absolute(pathRef))
return false;
@@ -450,13 +450,13 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
}
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
-FileManager::getBufferForFile(StringRef Filename) {
+FileManager::getBufferForFile(StringRef Filename, bool isVolatile) {
if (FileSystemOpts.WorkingDir.empty())
- return FS->getBufferForFile(Filename);
+ return FS->getBufferForFile(Filename, -1, true, isVolatile);
SmallString<128> FilePath(Filename);
FixupRelativePath(FilePath);
- return FS->getBufferForFile(FilePath.c_str());
+ return FS->getBufferForFile(FilePath.c_str(), -1, true, isVolatile);
}
/// getStatValue - Get the 'stat' information for the specified path,
@@ -505,14 +505,14 @@ void FileManager::GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
UIDToFiles.clear();
UIDToFiles.resize(NextFileUID);
-
+
// Map file entries
for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
FE != FEEnd; ++FE)
if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE)
UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
-
+
// Map virtual file entries
for (const auto &VFE : VirtualFileEntries)
if (VFE && VFE.get() != NON_EXISTENT_FILE)
@@ -534,23 +534,9 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
StringRef CanonicalName(Dir->getName());
-#ifdef LLVM_ON_UNIX
- char CanonicalNameBuf[PATH_MAX];
- if (realpath(Dir->getName().str().c_str(), CanonicalNameBuf))
+ SmallString<4096> CanonicalNameBuf;
+ if (!FS->getRealPath(Dir->getName(), CanonicalNameBuf))
CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
-#else
- SmallString<256> CanonicalNameBuf(CanonicalName);
- llvm::sys::fs::make_absolute(CanonicalNameBuf);
- llvm::sys::path::native(CanonicalNameBuf);
- // We've run into needing to remove '..' here in the wild though, so
- // remove it.
- // On Windows, symlinks are significantly less prevalent, so removing
- // '..' is pretty safe.
- // Ideally we'd have an equivalent of `realpath` and could implement
- // sys::fs::canonical across all the platforms.
- llvm::sys::path::remove_dots(CanonicalNameBuf, /* remove_dot_dot */ true);
- CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
-#endif
CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
return CanonicalName;
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
index 799df1d3c3a6..f5856cb6542a 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
@@ -1,4 +1,4 @@
-//===--- FileSystemStatCache.cpp - Caching for 'stat' calls ---------------===//
+//===- FileSystemStatCache.cpp - Caching for 'stat' calls -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,11 +13,14 @@
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
+#include <utility>
using namespace clang;
-void FileSystemStatCache::anchor() { }
+void FileSystemStatCache::anchor() {}
static void copyStatusToFileData(const vfs::Status &Status,
FileData &Data) {
@@ -92,17 +95,17 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
// If the path doesn't exist, return failure.
if (R == CacheMissing) return true;
-
+
// If the path exists, make sure that its "directoryness" matches the clients
// demands.
if (Data.IsDirectory != isForDir) {
// If not, close the file if opened.
if (F)
*F = nullptr;
-
+
return true;
}
-
+
return false;
}
@@ -117,7 +120,7 @@ MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
// entries).
if (Result == CacheMissing)
return Result;
-
+
// Cache file 'stat' results and directories with absolutely paths.
if (!Data.IsDirectory || llvm::sys::path::is_absolute(Path))
StatCalls[Path] = Data;
diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
index 2bed531ae3d7..7ec3cb7dd65b 100644
--- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -65,7 +65,7 @@ IdentifierInfoLookup::~IdentifierInfoLookup() = default;
namespace {
-/// \brief A simple identifier lookup iterator that represents an
+/// A simple identifier lookup iterator that represents an
/// empty sequence of identifiers.
class EmptyLookupIterator : public IdentifierIterator
{
@@ -79,16 +79,16 @@ IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
return new EmptyLookupIterator();
}
+IdentifierTable::IdentifierTable(IdentifierInfoLookup *ExternalLookup)
+ : HashTable(8192), // Start with space for 8K identifiers.
+ ExternalLookup(ExternalLookup) {}
+
IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
- IdentifierInfoLookup* externalLookup)
- : HashTable(8192), // Start with space for 8K identifiers.
- ExternalLookup(externalLookup) {
+ IdentifierInfoLookup *ExternalLookup)
+ : IdentifierTable(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);
}
//===----------------------------------------------------------------------===//
@@ -108,25 +108,27 @@ namespace {
KEYALTIVEC = 0x40,
KEYNOCXX = 0x80,
KEYBORLAND = 0x100,
- KEYOPENCL = 0x200,
+ KEYOPENCLC = 0x200,
KEYC11 = 0x400,
KEYARC = 0x800,
KEYNOMS18 = 0x01000,
KEYNOOPENCL = 0x02000,
WCHARSUPPORT = 0x04000,
HALFSUPPORT = 0x08000,
- KEYCONCEPTS = 0x10000,
- KEYOBJC2 = 0x20000,
- KEYZVECTOR = 0x40000,
- KEYCOROUTINES = 0x80000,
- KEYMODULES = 0x100000,
- KEYCXX2A = 0x200000,
+ CHAR8SUPPORT = 0x10000,
+ KEYCONCEPTS = 0x20000,
+ KEYOBJC2 = 0x40000,
+ KEYZVECTOR = 0x80000,
+ KEYCOROUTINES = 0x100000,
+ KEYMODULES = 0x200000,
+ KEYCXX2A = 0x400000,
+ KEYOPENCLCXX = 0x800000,
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A,
- KEYALL = (0x3fffff & ~KEYNOMS18 &
+ KEYALL = (0xffffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
- /// \brief How a keyword is treated in the selected standard.
+ /// How a keyword is treated in the selected standard.
enum KeywordStatus {
KS_Disabled, // Disabled
KS_Extension, // Is an extension
@@ -136,7 +138,7 @@ namespace {
} // namespace
-/// \brief Translates flags as specified in TokenKinds.def into keyword status
+/// Translates flags as specified in TokenKinds.def into keyword status
/// in the given language standard.
static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
unsigned Flags) {
@@ -151,8 +153,11 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.Bool && (Flags & BOOLSUPPORT)) return KS_Enabled;
if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled;
if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled;
+ if (LangOpts.Char8 && (Flags & CHAR8SUPPORT)) return KS_Enabled;
if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled;
- if (LangOpts.OpenCL && (Flags & KEYOPENCL)) return KS_Enabled;
+ if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLC))
+ return KS_Enabled;
+ if (LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLCXX)) return KS_Enabled;
if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) return KS_Enabled;
if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled;
// We treat bridge casts as objective-C keywords so we can warn on them
@@ -237,9 +242,12 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
if (LangOpts.DeclSpecKeyword)
AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
+
+ // Add the '_experimental_modules_import' contextual keyword.
+ get("import").setModulesImport(true);
}
-/// \brief Checks if the specified token kind represents a keyword in the
+/// Checks if the specified token kind represents a keyword in the
/// specified language.
/// \returns Status of the keyword in the language.
static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
@@ -252,7 +260,7 @@ static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
}
}
-/// \brief Returns true if the identifier represents a keyword in the
+/// Returns true if the identifier represents a keyword in the
/// specified language.
bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
switch (getTokenKwStatus(LangOpts, getTokenID())) {
@@ -264,7 +272,7 @@ bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
}
}
-/// \brief Returns true if the identifier represents a C++ keyword in the
+/// Returns true if the identifier represents a C++ keyword in the
/// specified language.
bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
@@ -311,7 +319,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
CASE( 6, 'i', 'n', ifndef);
CASE( 6, 'i', 'p', import);
CASE( 6, 'p', 'a', pragma);
-
+
CASE( 7, 'd', 'f', defined);
CASE( 7, 'i', 'c', include);
CASE( 7, 'w', 'r', warning);
@@ -320,7 +328,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
CASE(12, 'i', 'c', include_next);
CASE(14, '_', 'p', __public_macro);
-
+
CASE(15, '_', 'p', __private_macro);
CASE(16, '_', 'i', __include_macros);
@@ -496,6 +504,8 @@ void Selector::print(llvm::raw_ostream &OS) const {
OS << getAsString();
}
+LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
+
/// Interpreting the given string using the normal CamelCase
/// conventions, determine whether the given string starts with the
/// given "word", which is assumed to end in a lowercase letter.
@@ -556,9 +566,9 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
if (!first) return OIT_None;
-
+
StringRef name = first->getName();
-
+
if (name.empty()) return OIT_None;
switch (name.front()) {
case 'a':
@@ -583,22 +593,22 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
if (!first) return SFF_None;
-
+
StringRef name = first->getName();
-
+
switch (name.front()) {
case 'a':
if (name == "appendFormat") return SFF_NSString;
break;
-
+
case 'i':
if (name == "initWithFormat") return SFF_NSString;
break;
-
+
case 'l':
if (name == "localizedStringWithFormat") return SFF_NSString;
break;
-
+
case 's':
if (name == "stringByAppendingFormat" ||
name == "stringWithFormat") return SFF_NSString;
@@ -637,6 +647,12 @@ SelectorTable::constructSetterSelector(IdentifierTable &Idents,
return SelTable.getUnarySelector(SetterName);
}
+std::string SelectorTable::getPropertyNameFromSetterSelector(Selector Sel) {
+ StringRef Name = Sel.getNameForSlot(0);
+ assert(Name.startswith("set") && "invalid setter name");
+ return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
+}
+
size_t SelectorTable::getTotalMemory() const {
SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
return SelTabImpl.Allocator.getTotalMemory();
diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
index db81507aa209..763ba33683bc 100644
--- a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
@@ -1,4 +1,4 @@
-//===--- LangOptions.cpp - C Language Family Language Options ---*- C++ -*-===//
+//===- LangOptions.cpp - C Language Family Language Options ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,13 +10,12 @@
// This file defines the LangOptions class.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/StringRef.h"
using namespace clang;
-LangOptions::LangOptions()
- : IsHeaderFile(false) {
+LangOptions::LangOptions() {
#define LANGOPT(Name, Bits, Default, Description) Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
#include "clang/Basic/LangOptions.def"
@@ -44,3 +43,8 @@ bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const {
return true;
return false;
}
+
+VersionTuple LangOptions::getOpenCLVersionTuple() const {
+ const int Ver = OpenCLCPlusPlus ? OpenCLCPlusPlusVersion : OpenCLVersion;
+ return VersionTuple(Ver / 100, (Ver % 100) / 10);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
index 7124184865c6..1a0c19059058 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
@@ -44,7 +44,8 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
IsSystem(false), IsExternC(false), IsInferred(false),
InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NoUndeclaredIncludes(false), NameVisibility(Hidden) {
+ NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
+ NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -54,8 +55,10 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
IsExternC = true;
if (Parent->NoUndeclaredIncludes)
NoUndeclaredIncludes = true;
+ if (Parent->ModuleMapIsPrivate)
+ ModuleMapIsPrivate = true;
IsMissingRequirement = Parent->IsMissingRequirement;
-
+
Parent->SubModuleIndex[Name] = Parent->SubModules.size();
Parent->SubModules.push_back(this);
}
@@ -68,7 +71,7 @@ Module::~Module() {
}
}
-/// \brief Determine whether a translation unit built using the current
+/// Determine whether a translation unit built using the current
/// language options has the given feature.
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
const TargetInfo &Target) {
@@ -78,6 +81,11 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
.Case("coroutines", LangOpts.CoroutinesTS)
.Case("cplusplus", LangOpts.CPlusPlus)
.Case("cplusplus11", LangOpts.CPlusPlus11)
+ .Case("cplusplus14", LangOpts.CPlusPlus14)
+ .Case("cplusplus17", LangOpts.CPlusPlus17)
+ .Case("c99", LangOpts.C99)
+ .Case("c11", LangOpts.C11)
+ .Case("c17", LangOpts.C17)
.Case("freestanding", LangOpts.Freestanding)
.Case("gnuinlineasm", LangOpts.GNUAsm)
.Case("objc", LangOpts.ObjC1)
@@ -95,11 +103,16 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
Requirement &Req,
- UnresolvedHeaderDirective &MissingHeader) const {
+ UnresolvedHeaderDirective &MissingHeader,
+ Module *&ShadowingModule) const {
if (IsAvailable)
return true;
for (const Module *Current = this; Current; Current = Current->Parent) {
+ if (Current->ShadowingModule) {
+ ShadowingModule = Current->ShadowingModule;
+ return false;
+ }
for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
Current->Requirements[I].second) {
@@ -121,10 +134,10 @@ bool Module::isSubModuleOf(const Module *Other) const {
do {
if (This == Other)
return true;
-
+
This = This->Parent;
} while (This);
-
+
return false;
}
@@ -132,7 +145,7 @@ const Module *Module::getTopLevelModule() const {
const Module *Result = this;
while (Result->Parent)
Result = Result->Parent;
-
+
return Result;
}
@@ -168,16 +181,16 @@ static void printModuleId(raw_ostream &OS, const Container &C) {
std::string Module::getFullModuleName(bool AllowStringLiterals) const {
SmallVector<StringRef, 2> Names;
-
+
// Build up the set of module names (from innermost to outermost).
for (const Module *M = this; M; M = M->Parent)
Names.push_back(M->Name);
-
+
std::string Result;
llvm::raw_string_ostream Out(Result);
printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
- Out.flush();
+ Out.flush();
return Result;
}
@@ -194,7 +207,7 @@ bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
Module::DirectoryName Module::getUmbrellaDir() const {
if (Header U = getUmbrellaHeader())
return {"", U.Entry->getDir()};
-
+
return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
}
@@ -375,7 +388,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
}
OS << " {\n";
-
+
if (!Requirements.empty()) {
OS.indent(Indent + 2);
OS << "requires ";
@@ -388,7 +401,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
}
OS << "\n";
}
-
+
if (Header H = getUmbrellaHeader()) {
OS.indent(Indent + 2);
OS << "umbrella header \"";
@@ -398,7 +411,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS.indent(Indent + 2);
OS << "umbrella \"";
OS.write_escaped(D.NameAsWritten);
- OS << "\"\n";
+ OS << "\"\n";
}
if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
@@ -455,7 +468,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
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
@@ -464,7 +477,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
// those header files anyway.
if (!(*MI)->IsInferred || (*MI)->IsFramework)
(*MI)->print(OS, Indent + 2);
-
+
for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
OS.indent(Indent + 2);
OS << "export ";
@@ -541,7 +554,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS.indent(Indent + 2);
OS << "}\n";
}
-
+
OS.indent(Indent);
OS << "}\n";
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
index 133c66945dde..311bd067261a 100644
--- a/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
@@ -1,4 +1,4 @@
-//===- ObjCRuntime.cpp - Objective-C Runtime Handling -----------*- C++ -*-===//
+//===- ObjCRuntime.cpp - Objective-C Runtime Handling ---------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,8 +11,13 @@
// target Objective-C runtime.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Basic/ObjCRuntime.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <string>
using namespace clang;
@@ -22,7 +27,7 @@ std::string ObjCRuntime::getAsString() const {
llvm::raw_string_ostream Out(Result);
Out << *this;
}
- return Result;
+ return Result;
}
raw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) {
diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
index 09c919e2b072..67b7d91e6292 100644
--- a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements the OpenMP enum and support functions.
+/// This file implements the OpenMP enum and support functions.
///
//===----------------------------------------------------------------------===//
@@ -891,6 +891,7 @@ void clang::getOpenMPCaptureRegions(
case OMPD_target_teams:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
+ CaptureRegions.push_back(OMPD_task);
CaptureRegions.push_back(OMPD_target);
CaptureRegions.push_back(OMPD_teams);
break;
@@ -901,6 +902,7 @@ void clang::getOpenMPCaptureRegions(
break;
case OMPD_target:
case OMPD_target_simd:
+ CaptureRegions.push_back(OMPD_task);
CaptureRegions.push_back(OMPD_target);
break;
case OMPD_teams_distribute_parallel_for:
@@ -911,6 +913,7 @@ void clang::getOpenMPCaptureRegions(
case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_task);
CaptureRegions.push_back(OMPD_target);
CaptureRegions.push_back(OMPD_parallel);
break;
@@ -924,6 +927,13 @@ void clang::getOpenMPCaptureRegions(
case OMPD_taskloop_simd:
CaptureRegions.push_back(OMPD_taskloop);
break;
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_task);
+ CaptureRegions.push_back(OMPD_target);
+ CaptureRegions.push_back(OMPD_teams);
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
case OMPD_simd:
case OMPD_for:
case OMPD_for_simd:
@@ -938,8 +948,6 @@ void clang::getOpenMPCaptureRegions(
case OMPD_atomic:
case OMPD_target_data:
case OMPD_distribute_simd:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegions.push_back(OMPD_unknown);
break;
case OMPD_threadprivate:
diff --git a/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp b/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
index 3743b6ad5fef..bf805fc7deb1 100644
--- a/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines and computes precedence levels for binary/ternary operators.
+/// Defines and computes precedence levels for binary/ternary operators.
///
//===----------------------------------------------------------------------===//
#include "clang/Basic/OperatorPrecedence.h"
diff --git a/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
index 91b6b2dc74eb..8faf17b8f22e 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
@@ -1,4 +1,4 @@
-//===--- Sanitizers.cpp - C Language Family Language Options ----*- C++ -*-===//
+//===- Sanitizers.cpp - C Language Family Language Options ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,9 +10,8 @@
// This file defines the classes from Sanitizers.h
//
//===----------------------------------------------------------------------===//
+
#include "clang/Basic/Sanitizers.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
index 89ddbc946a49..eb916ec76fdc 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
@@ -1,4 +1,4 @@
-//==--- SourceLocation.cpp - Compact identifier for Source Files -*- C++ -*-==//
+//===- SourceLocation.cpp - Compact identifier for Source Files -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,10 +12,17 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include <cstdio>
+#include <cassert>
+#include <string>
+#include <utility>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -42,7 +49,7 @@ void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{
if (isFileID()) {
PresumedLoc PLoc = SM.getPresumedLoc(*this);
-
+
if (PLoc.isInvalid()) {
OS << "<invalid>";
return;
@@ -81,7 +88,6 @@ FileID FullSourceLoc::getFileID() const {
return SrcMgr->getFileID(*this);
}
-
FullSourceLoc FullSourceLoc::getExpansionLoc() const {
assert(isValid());
return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr);
@@ -97,15 +103,6 @@ FullSourceLoc FullSourceLoc::getFileLoc() const {
return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
}
-std::pair<FullSourceLoc, FullSourceLoc>
-FullSourceLoc::getImmediateExpansionRange() const {
- assert(isValid());
- std::pair<SourceLocation, SourceLocation> Range =
- SrcMgr->getImmediateExpansionRange(*this);
- return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
- FullSourceLoc(Range.second, *SrcMgr));
-}
-
PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
if (!isValid())
return PresumedLoc();
@@ -148,15 +145,6 @@ unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
}
-std::pair<FullSourceLoc, FullSourceLoc>
-FullSourceLoc::getExpansionRange() const {
- assert(isValid());
- std::pair<SourceLocation, SourceLocation> Range =
- SrcMgr->getExpansionRange(*this);
- return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
- FullSourceLoc(Range.second, *SrcMgr));
-}
-
const FileEntry *FullSourceLoc::getFileEntry() const {
assert(isValid());
return SrcMgr->getFileEntryForID(getFileID());
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
index 0a51985614c8..efa6ad2493b2 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -105,9 +105,9 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
if (Buffer.getPointer() || !ContentsEntry) {
if (Invalid)
*Invalid = isBufferInvalid();
-
+
return Buffer.getPointer();
- }
+ }
bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile;
auto BufferOrError =
@@ -141,7 +141,7 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
<< ContentsEntry->getName() << BufferOrError.getError().message();
Buffer.setInt(Buffer.getInt() | InvalidFlag);
-
+
if (Invalid) *Invalid = true;
return Buffer.getPointer();
}
@@ -170,8 +170,10 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr)
.StartsWith("\xFE\xFF", "UTF-16 (BE)")
.StartsWith("\xFF\xFE", "UTF-16 (LE)")
- .StartsWith("\x00\x00\xFE\xFF", "UTF-32 (BE)")
- .StartsWith("\xFF\xFE\x00\x00", "UTF-32 (LE)")
+ .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"),
+ "UTF-32 (BE)")
+ .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"),
+ "UTF-32 (LE)")
.StartsWith("\x2B\x2F\x76", "UTF-7")
.StartsWith("\xF7\x64\x4C", "UTF-1")
.StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")
@@ -185,10 +187,10 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
<< InvalidBOM << ContentsEntry->getName();
Buffer.setInt(Buffer.getInt() | InvalidFlag);
}
-
+
if (Invalid)
*Invalid = isBufferInvalid();
-
+
return Buffer.getPointer();
}
@@ -258,7 +260,7 @@ const LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID,
return &*--I;
}
-/// \brief Add a new line entry that has already been encoded into
+/// Add a new line entry that has already been encoded into
/// the internal representation of the line table.
void LineTableInfo::AddEntry(FileID FID,
const std::vector<LineEntry> &Entries) {
@@ -466,7 +468,7 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
return std::make_pair(-ID - 1, CurrentLoadedOffset);
}
-/// \brief As part of recovering from missing or changed content, produce a
+/// As part of recovering from missing or changed content, produce a
/// fake, non-empty buffer.
llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
if (!FakeBufferForRecovery)
@@ -476,7 +478,7 @@ llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
return FakeBufferForRecovery.get();
}
-/// \brief As part of recovering from missing or changed content, produce a
+/// As part of recovering from missing or changed content, produce a
/// fake content cache.
const SrcMgr::ContentCache *
SourceManager::getFakeContentCacheForRecovery() const {
@@ -488,7 +490,7 @@ SourceManager::getFakeContentCacheForRecovery() const {
return FakeContentCacheForRecovery.get();
}
-/// \brief Returns the previous in-order FileID or an invalid FileID if there
+/// Returns the previous in-order FileID or an invalid FileID if there
/// is no previous one.
FileID SourceManager::getPreviousFileID(FileID FID) const {
if (FID.isInvalid())
@@ -508,7 +510,7 @@ FileID SourceManager::getPreviousFileID(FileID FID) const {
return FileID::get(ID-1);
}
-/// \brief Returns the next in-order FileID or an invalid FileID if there is
+/// Returns the next in-order FileID or an invalid FileID if there is
/// no next one.
FileID SourceManager::getNextFileID(FileID FID) const {
if (FID.isInvalid())
@@ -577,13 +579,24 @@ SourceManager::createExpansionLoc(SourceLocation SpellingLoc,
SourceLocation ExpansionLocStart,
SourceLocation ExpansionLocEnd,
unsigned TokLength,
+ bool ExpansionIsTokenRange,
int LoadedID,
unsigned LoadedOffset) {
- ExpansionInfo Info = ExpansionInfo::create(SpellingLoc, ExpansionLocStart,
- ExpansionLocEnd);
+ ExpansionInfo Info = ExpansionInfo::create(
+ SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
}
+SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling,
+ SourceLocation TokenStart,
+ SourceLocation TokenEnd) {
+ assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
+ "token spans multiple files");
+ return createExpansionLocImpl(
+ ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
+ TokenEnd.getOffset() - TokenStart.getOffset());
+}
+
SourceLocation
SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
unsigned TokLength,
@@ -659,7 +672,7 @@ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
bool MyInvalid = false;
const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
if (!SLoc.isFile() || MyInvalid) {
- if (Invalid)
+ if (Invalid)
*Invalid = true;
return "<<<<<INVALID SOURCE LOCATION>>>>>";
}
@@ -671,7 +684,7 @@ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
if (MyInvalid)
return "<<<<<INVALID SOURCE LOCATION>>>>>";
-
+
return Buf->getBuffer();
}
@@ -679,7 +692,7 @@ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
// SourceLocation manipulation methods.
//===----------------------------------------------------------------------===//
-/// \brief Return the FileID for a SourceLocation.
+/// Return the FileID for a SourceLocation.
///
/// This is the cache-miss path of getFileID. Not as hot as that function, but
/// still very important. It is responsible for finding the entry in the
@@ -695,7 +708,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
return getFileIDLoaded(SLocOffset);
}
-/// \brief Return the FileID for a SourceLocation with a low offset.
+/// Return the FileID for a SourceLocation with a low offset.
///
/// This function knows that the SourceLocation is in a local buffer, not a
/// loaded one.
@@ -757,7 +770,7 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset();
if (Invalid)
return FileID::get(0);
-
+
++NumProbes;
// If the offset of the midpoint is too large, chop the high side of the
@@ -786,7 +799,7 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
}
}
-/// \brief Return the FileID for a SourceLocation with a high offset.
+/// Return the FileID for a SourceLocation with a high offset.
///
/// This function knows that the SourceLocation is in a loaded buffer, not a
/// local one.
@@ -893,7 +906,7 @@ SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
if (isMacroArgExpansion(Loc))
Loc = getImmediateSpellingLoc(Loc);
else
- Loc = getImmediateExpansionRange(Loc).first;
+ Loc = getImmediateExpansionRange(Loc).getBegin();
} while (!Loc.isFileID());
return Loc;
}
@@ -948,28 +961,36 @@ SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
/// getImmediateExpansionRange - Loc is required to be an expansion location.
/// Return the start/end of the expansion information.
-std::pair<SourceLocation,SourceLocation>
+CharSourceRange
SourceManager::getImmediateExpansionRange(SourceLocation Loc) const {
assert(Loc.isMacroID() && "Not a macro expansion loc!");
const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
return Expansion.getExpansionLocRange();
}
+SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const {
+ while (isMacroArgExpansion(Loc))
+ Loc = getImmediateSpellingLoc(Loc);
+ return Loc;
+}
+
/// getExpansionRange - Given a SourceLocation object, return the range of
/// tokens covered by the expansion in the ultimate file.
-std::pair<SourceLocation,SourceLocation>
-SourceManager::getExpansionRange(SourceLocation Loc) const {
- if (Loc.isFileID()) return std::make_pair(Loc, Loc);
+CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const {
+ if (Loc.isFileID())
+ return CharSourceRange(SourceRange(Loc, Loc), true);
- std::pair<SourceLocation,SourceLocation> Res =
- getImmediateExpansionRange(Loc);
+ CharSourceRange Res = getImmediateExpansionRange(Loc);
// Fully resolve the start and end locations to their ultimate expansion
// points.
- while (!Res.first.isFileID())
- Res.first = getImmediateExpansionRange(Res.first).first;
- while (!Res.second.isFileID())
- Res.second = getImmediateExpansionRange(Res.second).second;
+ while (!Res.getBegin().isFileID())
+ Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin());
+ while (!Res.getEnd().isFileID()) {
+ CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd());
+ Res.setEnd(EndRange.getEnd());
+ Res.setTokenRange(EndRange.isTokenRange());
+ }
return Res;
}
@@ -1083,7 +1104,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL,
if (CharDataInvalid || !Entry.isFile()) {
if (Invalid)
*Invalid = true;
-
+
return "<<<<INVALID BUFFER>>>>";
}
llvm::MemoryBuffer *Buffer = Entry.getFile().getContentCache()->getBuffer(
@@ -1268,7 +1289,7 @@ FoundSpecialChar:
/// for the position indicated. This requires building and caching a table of
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
-unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
+unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
bool *Invalid) const {
if (FID.isInvalid()) {
if (Invalid)
@@ -1287,10 +1308,10 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
*Invalid = true;
return 1;
}
-
+
Content = const_cast<ContentCache*>(Entry.getFile().getContentCache());
}
-
+
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (!Content->SourceLineCache) {
@@ -1362,7 +1383,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
return LineNo;
}
-unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
@@ -1397,7 +1418,7 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const {
const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid);
if (Invalid || !SEntry.isFile())
return C_User;
-
+
const SrcMgr::FileInfo &FI = SEntry.getFile();
// If there are no #line directives in this file, just return the whole-file
@@ -1445,7 +1466,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
if (Invalid || !Entry.isFile())
return PresumedLoc();
-
+
const SrcMgr::FileInfo &FI = Entry.getFile();
const SrcMgr::ContentCache *C = FI.getContentCache();
@@ -1464,7 +1485,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
if (Invalid)
return PresumedLoc();
-
+
SourceLocation IncludeLoc = FI.getIncludeLoc();
// If we have #line directives in this file, update and overwrite the physical
@@ -1498,7 +1519,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
return PresumedLoc(Filename.data(), LineNo, ColNo, IncludeLoc);
}
-/// \brief Returns whether the PresumedLoc for a given SourceLocation is
+/// Returns whether the PresumedLoc for a given SourceLocation is
/// in the main file.
///
/// This computes the "presumed" location for a SourceLocation, then checks
@@ -1528,7 +1549,7 @@ bool SourceManager::isInMainFile(SourceLocation Loc) const {
return FI.getIncludeLoc().isInvalid();
}
-/// \brief The size of the SLocEntry that \p FID represents.
+/// The size of the SLocEntry that \p FID represents.
unsigned SourceManager::getFileIDSize(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
@@ -1551,7 +1572,7 @@ unsigned SourceManager::getFileIDSize(FileID FID) const {
// Other miscellaneous methods.
//===----------------------------------------------------------------------===//
-/// \brief Retrieve the inode for the given file entry, if possible.
+/// Retrieve the inode for the given file entry, if possible.
///
/// This routine involves a system call, and therefore should only be used
/// in non-performance-critical code.
@@ -1567,7 +1588,7 @@ getActualFileUID(const FileEntry *File) {
return ID;
}
-/// \brief Get the source location for the given file:line:col triplet.
+/// Get the source location for the given file:line:col triplet.
///
/// If the source file is included multiple times, the source location will
/// be based upon an arbitrary inclusion.
@@ -1581,7 +1602,7 @@ SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,
return translateLineCol(FirstFID, Line, Col);
}
-/// \brief Get the FileID for the given file.
+/// Get the FileID for the given file.
///
/// If the source file is included multiple times, the FileID will be the
/// first inclusion.
@@ -1600,7 +1621,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
if (Invalid)
return FileID();
-
+
if (MainSLoc.isFile()) {
const ContentCache *MainContentCache
= MainSLoc.getFile().getContentCache();
@@ -1637,8 +1658,8 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid);
if (Invalid)
return FileID();
-
- if (SLoc.isFile() &&
+
+ if (SLoc.isFile() &&
SLoc.getFile().getContentCache() &&
SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
FirstFID = FileID::get(I);
@@ -1649,7 +1670,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
if (FirstFID.isInvalid()) {
for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
const SLocEntry &SLoc = getLoadedSLocEntry(I);
- if (SLoc.isFile() &&
+ if (SLoc.isFile() &&
SLoc.getFile().getContentCache() &&
SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
FirstFID = FileID::get(-int(I) - 2);
@@ -1660,7 +1681,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
}
// If we haven't found what we want yet, try again, but this time stat()
- // each of the files in case the files have changed since we originally
+ // each of the files in case the files have changed since we originally
// parsed the file.
if (FirstFID.isInvalid() &&
(SourceFileName ||
@@ -1673,13 +1694,13 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid);
if (Invalid)
return FileID();
-
- if (SLoc.isFile()) {
- const ContentCache *FileContentCache
+
+ if (SLoc.isFile()) {
+ const ContentCache *FileContentCache
= SLoc.getFile().getContentCache();
const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry
: nullptr;
- if (Entry &&
+ if (Entry &&
*SourceFileName == llvm::sys::path::filename(Entry->getName())) {
if (Optional<llvm::sys::fs::UniqueID> EntryUID =
getActualFileUID(Entry)) {
@@ -1691,14 +1712,14 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
}
}
}
- }
+ }
}
-
+
(void) SourceFile;
return FirstFID;
}
-/// \brief Get the source location in \arg FID for the given line:col.
+/// Get the source location in \arg FID for the given line:col.
/// Returns null location if \arg FID is not a file SLocEntry.
SourceLocation SourceManager::translateLineCol(FileID FID,
unsigned Line,
@@ -1759,7 +1780,7 @@ SourceLocation SourceManager::translateLineCol(FileID FID,
return FileLoc.getLocWithOffset(FilePos + i);
}
-/// \brief Compute a map of macro argument chunks to their expanded source
+/// Compute a map of macro argument chunks to their expanded source
/// location. Chunks that are not part of a macro argument will map to an
/// invalid source location. e.g. if a file contains one macro argument at
/// offset 100 with length 10, this is how the map will be formed:
@@ -1879,7 +1900,7 @@ void SourceManager::associateFileChunkWithMacroArgExp(
// 0 -> SourceLocation()
// 100 -> Expanded loc #1
// 110 -> SourceLocation()
- // and we found a new macro FileID that lexed from offet 105 with length 3,
+ // and we found a new macro FileID that lexed from offset 105 with length 3,
// the new map will be:
// 0 -> SourceLocation()
// 100 -> Expanded loc #1
@@ -1898,7 +1919,7 @@ void SourceManager::associateFileChunkWithMacroArgExp(
MacroArgsCache[EndOffs] = EndOffsMappedLoc;
}
-/// \brief If \arg Loc points inside a function macro argument, the returned
+/// If \arg Loc points inside a function macro argument, the returned
/// location will be the macro location in which the argument was expanded.
/// If a macro argument is used multiple times, the expanded location will
/// be at the first expansion of the argument.
@@ -1927,7 +1948,7 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
assert(!MacroArgsCache->empty());
MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
--I;
-
+
unsigned MacroArgBeginOffs = I->first;
SourceLocation MacroArgExpandedLoc = I->second;
if (MacroArgExpandedLoc.isValid())
@@ -2007,7 +2028,7 @@ InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
return IBTUCacheOverflow;
}
-/// \brief Determines the order of 2 source locations in the translation unit.
+/// Determines the order of 2 source locations in the translation unit.
///
/// \returns true if LHS source location comes before RHS, false otherwise.
bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
@@ -2130,7 +2151,7 @@ void SourceManager::PrintStats() const {
<< " loaded SLocEntries allocated, "
<< MaxLoadedOffset - CurrentLoadedOffset
<< "B of Sloc address space used.\n";
-
+
unsigned NumLineNumsComputed = 0;
unsigned NumFileBytesMapped = 0;
for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
@@ -2210,7 +2231,7 @@ ExternalSLocEntrySource::~ExternalSLocEntrySource() = default;
SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
size_t malloc_bytes = 0;
size_t mmap_bytes = 0;
-
+
for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
switch (MemBufferInfos[i]->getMemoryBufferKind()) {
@@ -2221,7 +2242,7 @@ SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
malloc_bytes += sized_mapped;
break;
}
-
+
return MemoryBufferSizes(malloc_bytes, mmap_bytes);
}
@@ -2231,9 +2252,35 @@ size_t SourceManager::getDataStructureSizes() const {
+ llvm::capacity_in_bytes(LoadedSLocEntryTable)
+ llvm::capacity_in_bytes(SLocEntryLoaded)
+ llvm::capacity_in_bytes(FileInfos);
-
+
if (OverriddenFilesInfo)
size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
return size;
}
+
+SourceManagerForFile::SourceManagerForFile(StringRef FileName,
+ StringRef Content) {
+ // This is referenced by `FileMgr` and will be released by `FileMgr` when it
+ // is deleted.
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ InMemoryFileSystem->addFile(
+ FileName, 0,
+ llvm::MemoryBuffer::getMemBuffer(Content, FileName,
+ /*RequiresNullTerminator=*/false));
+ // This is passed to `SM` as reference, so the pointer has to be referenced
+ // in `Environment` so that `FileMgr` can out-live this function scope.
+ FileMgr =
+ llvm::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem);
+ // This is passed to `SM` as reference, so the pointer has to be referenced
+ // by `Environment` due to the same reason above.
+ Diagnostics = llvm::make_unique<DiagnosticsEngine>(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+ new DiagnosticOptions);
+ SourceMgr = llvm::make_unique<SourceManager>(*Diagnostics, *FileMgr);
+ FileID ID = SourceMgr->createFileID(FileMgr->getFile(FileName),
+ SourceLocation(), clang::SrcMgr::C_User);
+ assert(ID.isValid());
+ SourceMgr->setMainFileID(ID);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
index ddd292c1b743..3400c8721f7a 100644
--- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -14,6 +14,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
@@ -32,12 +33,31 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
TLSSupported = true;
VLASupported = true;
NoAsmVariants = false;
+ HasLegalHalfType = false;
HasFloat128 = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
LongLongWidth = LongLongAlign = 64;
+
+ // Fixed point default bit widths
+ ShortAccumWidth = ShortAccumAlign = 16;
+ AccumWidth = AccumAlign = 32;
+ LongAccumWidth = LongAccumAlign = 64;
+ ShortFractWidth = ShortFractAlign = 8;
+ FractWidth = FractAlign = 16;
+ LongFractWidth = LongFractAlign = 32;
+
+ // Fixed point default integral and fractional bit sizes
+ // We give the _Accum 1 fewer fractional bits than their corresponding _Fract
+ // types by default to have the same number of fractional bits between _Accum
+ // and _Fract types.
+ PaddingOnUnsignedFixedPoint = false;
+ ShortAccumScale = 7;
+ AccumScale = 15;
+ LongAccumScale = 31;
+
SuitableAlign = 64;
DefaultAlignForAttributeAligned = 128;
MinGlobalAlign = 0;
@@ -114,6 +134,18 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}
+bool
+TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
+ Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch";
+ return false;
+}
+
+bool
+TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
+ Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";
+ return false;
+}
+
/// getTypeName - Return the user string for the specified integer type enum.
/// For example, SignedShort -> "short".
const char *TargetInfo::getTypeName(IntType T) {
@@ -342,6 +374,11 @@ void TargetInfo::adjust(LangOptions &Opts) {
if (Opts.NewAlignOverride)
NewAlign = Opts.NewAlignOverride * getCharWidth();
+
+ // Each unsigned fixed point type has the same number of fractional bits as
+ // its corresponding signed type.
+ PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint;
+ CheckFixedPointBits();
}
bool TargetInfo::initFeatureMap(
@@ -356,6 +393,14 @@ bool TargetInfo::initFeatureMap(
return true;
}
+TargetInfo::CallingConvKind
+TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
+ if (getCXXABI() != TargetCXXABI::Microsoft &&
+ (ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))
+ return CCK_ClangABI4OrPS4;
+ return CCK_Default;
+}
+
LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const {
switch (TK) {
case OCLTK_Image:
@@ -688,3 +733,63 @@ bool TargetInfo::validateInputConstraint(
return true;
}
+
+void TargetInfo::CheckFixedPointBits() const {
+ // Check that the number of fractional and integral bits (and maybe sign) can
+ // fit into the bits given for a fixed point type.
+ assert(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth);
+ assert(AccumScale + getAccumIBits() + 1 <= AccumWidth);
+ assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth);
+ assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <=
+ ShortAccumWidth);
+ assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth);
+ assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <=
+ LongAccumWidth);
+
+ assert(getShortFractScale() + 1 <= ShortFractWidth);
+ assert(getFractScale() + 1 <= FractWidth);
+ assert(getLongFractScale() + 1 <= LongFractWidth);
+ assert(getUnsignedShortFractScale() <= ShortFractWidth);
+ assert(getUnsignedFractScale() <= FractWidth);
+ assert(getUnsignedLongFractScale() <= LongFractWidth);
+
+ // Each unsigned fract type has either the same number of fractional bits
+ // as, or one more fractional bit than, its corresponding signed fract type.
+ assert(getShortFractScale() == getUnsignedShortFractScale() ||
+ getShortFractScale() == getUnsignedShortFractScale() - 1);
+ assert(getFractScale() == getUnsignedFractScale() ||
+ getFractScale() == getUnsignedFractScale() - 1);
+ assert(getLongFractScale() == getUnsignedLongFractScale() ||
+ getLongFractScale() == getUnsignedLongFractScale() - 1);
+
+ // When arranged in order of increasing rank (see 6.3.1.3a), the number of
+ // fractional bits is nondecreasing for each of the following sets of
+ // fixed-point types:
+ // - signed fract types
+ // - unsigned fract types
+ // - signed accum types
+ // - unsigned accum types.
+ assert(getLongFractScale() >= getFractScale() &&
+ getFractScale() >= getShortFractScale());
+ assert(getUnsignedLongFractScale() >= getUnsignedFractScale() &&
+ getUnsignedFractScale() >= getUnsignedShortFractScale());
+ assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale);
+ assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() &&
+ getUnsignedAccumScale() >= getUnsignedShortAccumScale());
+
+ // When arranged in order of increasing rank (see 6.3.1.3a), the number of
+ // integral bits is nondecreasing for each of the following sets of
+ // fixed-point types:
+ // - signed accum types
+ // - unsigned accum types
+ assert(getLongAccumIBits() >= getAccumIBits() &&
+ getAccumIBits() >= getShortAccumIBits());
+ assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() &&
+ getUnsignedAccumIBits() >= getUnsignedShortAccumIBits());
+
+ // Each signed accum type has at least as many integral bits as its
+ // corresponding unsigned accum type.
+ assert(getShortAccumIBits() >= getUnsignedShortAccumIBits());
+ assert(getAccumIBits() >= getUnsignedAccumIBits());
+ assert(getLongAccumIBits() >= getUnsignedLongAccumIBits());
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index 7deebc06c3ef..1ef2fe3b8141 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -29,6 +29,7 @@
#include "Targets/OSTargets.h"
#include "Targets/PNaCl.h"
#include "Targets/PPC.h"
+#include "Targets/RISCV.h"
#include "Targets/SPIR.h"
#include "Targets/Sparc.h"
#include "Targets/SystemZ.h"
@@ -37,6 +38,7 @@
#include "Targets/X86.h"
#include "Targets/XCore.h"
#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
using namespace clang;
@@ -370,6 +372,17 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::r600:
return new AMDGPUTargetInfo(Triple, Opts);
+ case llvm::Triple::riscv32:
+ // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<RISCV32TargetInfo>(Triple, Opts);
+ return new RISCV32TargetInfo(Triple, Opts);
+ case llvm::Triple::riscv64:
+ // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<RISCV64TargetInfo>(Triple, Opts);
+ return new RISCV64TargetInfo(Triple, Opts);
+
case llvm::Triple::sparc:
switch (os) {
case llvm::Triple::Linux:
@@ -595,6 +608,10 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
// Set the target CPU if specified.
if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) {
Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU;
+ SmallVector<StringRef, 32> ValidList;
+ Target->fillValidCPUList(ValidList);
+ if (!ValidList.empty())
+ Diags.Report(diag::note_valid_options) << llvm::join(ValidList, ", ");
return nullptr;
}
@@ -621,6 +638,9 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
Opts->Features.clear();
for (const auto &F : Features)
Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str());
+ // Sort here, so we handle the features in a predictable order. (This matters
+ // when we're dealing with features that overlap.)
+ llvm::sort(Opts->Features.begin(), Opts->Features.end());
if (!Target->handleTargetFeatures(Opts->Features, Diags))
return nullptr;
@@ -632,5 +652,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
if (!Target->validateTarget(Diags))
return nullptr;
+ Target->CheckFixedPointBits();
+
return Target.release();
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.h b/contrib/llvm/tools/clang/lib/Basic/Targets.h
index 6fc967ddabee..d450aa3f37ed 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.h
@@ -1,4 +1,4 @@
-//===------- Targets.h - Declare target feature support -------------------===//
+//===------- Targets.h - Declare target feature support ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
index 8762ef691700..3444591ac593 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
@@ -29,26 +29,27 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
{#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
#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.
+ if (getTriple().getOS() == llvm::Triple::OpenBSD) {
Int64Type = SignedLongLong;
IntMaxType = SignedLongLong;
} else {
- if (!getTriple().isOSDarwin())
+ if (!getTriple().isOSDarwin() && getTriple().getOS() != llvm::Triple::NetBSD)
WCharType = UnsignedInt;
Int64Type = SignedLong;
IntMaxType = SignedLong;
}
+ // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
+ HasLegalHalfType = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxVectorAlign = 128;
@@ -101,6 +102,11 @@ bool AArch64TargetInfo::setCPU(const std::string &Name) {
return isValidCPUName(Name);
}
+void AArch64TargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ llvm::AArch64::fillValidCPUArchList(Values);
+}
+
void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
@@ -183,6 +189,11 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if ((FPU & NeonMode) && HasFullFP16)
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+ if (HasFullFP16)
+ Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
+
+ if (HasDotProd)
+ Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
switch (ArchKind) {
default:
@@ -220,6 +231,7 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
Crypto = 0;
Unaligned = 1;
HasFullFP16 = 0;
+ HasDotProd = 0;
ArchKind = llvm::AArch64::ArchKind::ARMV8A;
for (const auto &Feature : Features) {
@@ -239,6 +251,8 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
if (Feature == "+fullfp16")
HasFullFP16 = 1;
+ if (Feature == "+dotprod")
+ HasDotProd = 1;
}
setDataLayout();
@@ -519,6 +533,11 @@ void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
getVisualStudioDefines(Opts, Builder);
}
+TargetInfo::CallingConvKind
+MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
+ return CCK_MicrosoftWin64;
+}
+
MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARM64TargetInfo(Triple, Opts) {
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
index 33268f0f8d99..a9df895e4dad 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
@@ -33,6 +33,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
unsigned Crypto;
unsigned Unaligned;
unsigned HasFullFP16;
+ unsigned HasDotProd;
llvm::AArch64::ArchKind ArchKind;
static const Builtin::Info BuiltinInfo[];
@@ -46,6 +47,7 @@ public:
bool setABI(const std::string &Name) override;
bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override;
bool useFP16ConversionIntrinsics() const override {
@@ -80,6 +82,11 @@ public:
std::string &SuggestedModifier) const override;
const char *getClobbers() const override;
+ StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const override {
+ return Expression;
+ }
+
int getEHDataRegisterNumber(unsigned RegNo) const override;
};
@@ -119,6 +126,8 @@ public:
MacroBuilder &Builder) const;
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
+ TargetInfo::CallingConvKind
+ getCallingConvKind(bool ClangABICompat4) const override;
};
// ARM64 MinGW target
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
index 4c510e47379f..b6b9aa2f1244 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -30,64 +30,35 @@ namespace targets {
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";
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5";
-static const char *const DataLayoutStringSIPrivateIsZero =
- "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32"
+static const char *const DataLayoutStringAMDGCN =
+ "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6: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
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5";
+
+const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = {
+ Generic, // Default
+ Global, // opencl_global
+ Local, // opencl_local
+ Constant, // opencl_constant
+ Private, // opencl_private
+ Generic, // opencl_generic
+ Global, // cuda_device
+ Constant, // cuda_constant
+ Local // 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
+const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
+ Private, // Default
+ Global, // opencl_global
+ Local, // opencl_local
+ Constant, // opencl_constant
+ Private, // opencl_private
+ Generic, // opencl_generic
+ Global, // cuda_device
+ Constant, // cuda_constant
+ Local // cuda_shared
};
} // namespace targets
} // namespace clang
@@ -144,7 +115,7 @@ const char *const AMDGPUTargetInfo::GCCRegNames[] = {
"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",
+ "m0", "flat_scratch", "exec_lo", "exec_hi", "vcc_lo", "vcc_hi",
"flat_scratch_lo", "flat_scratch_hi"
};
@@ -157,49 +128,66 @@ bool AMDGPUTargetInfo::initFeatureMap(
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 (isAMDGCN(getTriple())) {
if (CPU.empty())
- CPU = "tahiti";
-
- switch (parseAMDGCNName(CPU)) {
- case GK_GFX6:
- case GK_GFX7:
- break;
+ CPU = "gfx600";
- case GK_GFX9:
+ switch (parseAMDGCNName(CPU).Kind) {
+ case GK_GFX906:
+ Features["dl-insts"] = true;
+ LLVM_FALLTHROUGH;
+ case GK_GFX904:
+ case GK_GFX902:
+ case GK_GFX900:
Features["gfx9-insts"] = true;
LLVM_FALLTHROUGH;
- case GK_GFX8:
- Features["s-memrealtime"] = true;
+ case GK_GFX810:
+ case GK_GFX803:
+ case GK_GFX802:
+ case GK_GFX801:
Features["16-bit-insts"] = true;
Features["dpp"] = true;
+ Features["s-memrealtime"] = true;
+ break;
+ case GK_GFX704:
+ case GK_GFX703:
+ case GK_GFX702:
+ case GK_GFX701:
+ case GK_GFX700:
+ case GK_GFX601:
+ case GK_GFX600:
break;
-
case GK_NONE:
return false;
default:
- llvm_unreachable("unhandled subtarget");
+ llvm_unreachable("Unhandled GPU!");
}
} 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:
+ switch (parseR600Name(CPU).Kind) {
case GK_CAYMAN:
+ case GK_CYPRESS:
+ case GK_RV770:
+ case GK_RV670:
// TODO: Add fp64 when implemented.
break;
- case GK_NONE:
- return false;
+ case GK_TURKS:
+ case GK_CAICOS:
+ case GK_BARTS:
+ case GK_SUMO:
+ case GK_REDWOOD:
+ case GK_JUNIPER:
+ case GK_CEDAR:
+ case GK_RV730:
+ case GK_RV710:
+ case GK_RS880:
+ case GK_R630:
+ case GK_R600:
+ break;
default:
- llvm_unreachable("unhandled subtarget");
+ llvm_unreachable("Unhandled GPU!");
}
}
@@ -210,6 +198,7 @@ void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
TargetOptions &TargetOpts) const {
bool hasFP32Denormals = false;
bool hasFP64Denormals = false;
+ GPUInfo CGOptsGPU = parseGPUName(TargetOpts.CPU);
for (auto &I : TargetOpts.FeaturesAsWritten) {
if (I == "+fp32-denormals" || I == "-fp32-denormals")
hasFP32Denormals = true;
@@ -218,120 +207,68 @@ void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
}
if (!hasFP32Denormals)
TargetOpts.Features.push_back(
- (Twine(hasFullSpeedFMAF32(TargetOpts.CPU) && !CGOpts.FlushDenorm
+ (Twine(CGOptsGPU.HasFastFMAF && !CGOpts.FlushDenorm
? '+'
: '-') +
Twine("fp32-denormals"))
.str());
// Always do not flush fp64 or fp16 denorms.
- if (!hasFP64Denormals && hasFP64)
+ if (!hasFP64Denormals && CGOptsGPU.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);
+constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::InvalidGPU;
+constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::R600GPUs[];
+constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::AMDGCNGPUs[];
+
+AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseR600Name(StringRef Name) {
+ const auto *Result = llvm::find_if(
+ R600GPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; });
+
+ if (Result == std::end(R600GPUs))
+ return InvalidGPU;
+ return *Result;
}
-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);
+AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseAMDGCNName(StringRef Name) {
+ const auto *Result = llvm::find_if(
+ AMDGCNGPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; });
+
+ if (Result == std::end(AMDGCNGPUs))
+ return InvalidGPU;
+ return *Result;
+}
+
+AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseGPUName(StringRef Name) const {
+ if (isAMDGCN(getTriple()))
+ return parseAMDGCNName(Name);
+ else
+ return parseR600Name(Name);
+}
+
+void AMDGPUTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ if (isAMDGCN(getTriple()))
+ llvm::for_each(AMDGCNGPUs, [&Values](const GPUInfo &GPU) {
+ Values.emplace_back(GPU.Name);});
+ else
+ llvm::for_each(R600GPUs, [&Values](const GPUInfo &GPU) {
+ Values.emplace_back(GPU.Name);});
}
void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) {
- if (isGenericZero(getTriple())) {
- AddrSpaceMap = DefaultIsPrivate ? &AMDGPUGenIsZeroDefIsPrivMap
- : &AMDGPUGenIsZeroDefIsGenMap;
- } else {
- AddrSpaceMap = DefaultIsPrivate ? &AMDGPUPrivIsZeroDefIsPrivMap
- : &AMDGPUPrivIsZeroDefIsGenMap;
- }
+ AddrSpaceMap = DefaultIsPrivate ? &AMDGPUDefIsPrivMap : &AMDGPUDefIsGenMap;
}
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);
+ GPU(isAMDGCN(Triple) ? AMDGCNGPUs[0] : parseR600Name(Opts.CPU)) {
+ resetDataLayout(isAMDGCN(getTriple()) ? DataLayoutStringAMDGCN
+ : DataLayoutStringR600);
+ assert(DataLayout->getAllocaAddrSpace() == Private);
setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D ||
- Triple.getEnvironment() == llvm::Triple::OpenCL ||
- Triple.getEnvironmentName() == "amdgizcl" ||
!isAMDGCN(Triple));
UseAddrSpaceMapMangling = true;
@@ -349,7 +286,11 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
void AMDGPUTargetInfo::adjust(LangOptions &Opts) {
TargetInfo::adjust(Opts);
- setAddressSpaceMap(Opts.OpenCL || !isAMDGCN(getTriple()));
+ // ToDo: There are still a few places using default address space as private
+ // address space in OpenCL, which needs to be cleaned up, then Opts.OpenCL
+ // can be removed from the following line.
+ setAddressSpaceMap(/*DefaultIsPrivate=*/Opts.OpenCL ||
+ !isAMDGCN(getTriple()));
}
ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {
@@ -359,15 +300,27 @@ ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {
void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
- if (getTriple().getArch() == llvm::Triple::amdgcn)
+ Builder.defineMacro("__AMD__");
+ Builder.defineMacro("__AMDGPU__");
+
+ if (isAMDGCN(getTriple()))
Builder.defineMacro("__AMDGCN__");
else
Builder.defineMacro("__R600__");
- if (hasFMAF)
+ if (GPU.Kind != GK_NONE)
+ Builder.defineMacro(Twine("__") + Twine(GPU.CanonicalName) + Twine("__"));
+
+ // TODO: __HAS_FMAF__, __HAS_LDEXPF__, __HAS_FP64__ are deprecated and will be
+ // removed in the near future.
+ if (GPU.HasFMAF)
Builder.defineMacro("__HAS_FMAF__");
- if (hasLDEXPF)
+ if (GPU.HasFastFMAF)
+ Builder.defineMacro("FP_FAST_FMAF");
+ if (GPU.HasLDEXPF)
Builder.defineMacro("__HAS_LDEXPF__");
- if (hasFP64)
+ if (GPU.HasFP64)
Builder.defineMacro("__HAS_FP64__");
+ if (GPU.HasFastFMA)
+ Builder.defineMacro("FP_FAST_FMA");
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
index a4e070f1cb12..b0221031addf 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
@@ -28,60 +28,157 @@ 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;
- }
- }
+ enum AddrSpace {
+ Generic = 0,
+ Global = 1,
+ Local = 3,
+ Constant = 4,
+ Private = 5
};
+ static const LangASMap AMDGPUDefIsGenMap;
+ static const LangASMap AMDGPUDefIsPrivMap;
+
+ /// GPU kinds supported by the AMDGPU target.
+ enum GPUKind : uint32_t {
+ // Not specified processor.
+ GK_NONE = 0,
- /// \brief The GPU profiles supported by the AMDGPU target.
- enum GPUKind {
- GK_NONE,
+ // R600-based processors.
GK_R600,
- GK_R600_DOUBLE_OPS,
- GK_R700,
- GK_R700_DOUBLE_OPS,
- GK_EVERGREEN,
- GK_EVERGREEN_DOUBLE_OPS,
- GK_NORTHERN_ISLANDS,
+ GK_R630,
+ GK_RS880,
+ GK_RV670,
+ GK_RV710,
+ GK_RV730,
+ GK_RV770,
+ GK_CEDAR,
+ GK_CYPRESS,
+ GK_JUNIPER,
+ GK_REDWOOD,
+ GK_SUMO,
+ GK_BARTS,
+ GK_CAICOS,
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;
- }
+ GK_TURKS,
+
+ GK_R600_FIRST = GK_R600,
+ GK_R600_LAST = GK_TURKS,
+
+ // AMDGCN-based processors.
+ GK_GFX600,
+ GK_GFX601,
+ GK_GFX700,
+ GK_GFX701,
+ GK_GFX702,
+ GK_GFX703,
+ GK_GFX704,
+ GK_GFX801,
+ GK_GFX802,
+ GK_GFX803,
+ GK_GFX810,
+ GK_GFX900,
+ GK_GFX902,
+ GK_GFX904,
+ GK_GFX906,
+
+ GK_AMDGCN_FIRST = GK_GFX600,
+ GK_AMDGCN_LAST = GK_GFX906,
+ };
+
+ struct GPUInfo {
+ llvm::StringLiteral Name;
+ llvm::StringLiteral CanonicalName;
+ AMDGPUTargetInfo::GPUKind Kind;
+ bool HasFMAF;
+ bool HasFastFMAF;
+ bool HasLDEXPF;
+ bool HasFP64;
+ bool HasFastFMA;
+ };
+
+ static constexpr GPUInfo InvalidGPU =
+ {{""}, {""}, GK_NONE, false, false, false, false, false};
+ static constexpr GPUInfo R600GPUs[26] = {
+ // Name Canonical Kind Has Has Has Has Has
+ // Name FMAF Fast LDEXPF FP64 Fast
+ // FMAF FMA
+ {{"r600"}, {"r600"}, GK_R600, false, false, false, false, false},
+ {{"rv630"}, {"r600"}, GK_R600, false, false, false, false, false},
+ {{"rv635"}, {"r600"}, GK_R600, false, false, false, false, false},
+ {{"r630"}, {"r630"}, GK_R630, false, false, false, false, false},
+ {{"rs780"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rs880"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rv610"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rv620"}, {"rs880"}, GK_RS880, false, false, false, false, false},
+ {{"rv670"}, {"rv670"}, GK_RV670, false, false, false, false, false},
+ {{"rv710"}, {"rv710"}, GK_RV710, false, false, false, false, false},
+ {{"rv730"}, {"rv730"}, GK_RV730, false, false, false, false, false},
+ {{"rv740"}, {"rv770"}, GK_RV770, false, false, false, false, false},
+ {{"rv770"}, {"rv770"}, GK_RV770, false, false, false, false, false},
+ {{"cedar"}, {"cedar"}, GK_CEDAR, false, false, false, false, false},
+ {{"palm"}, {"cedar"}, GK_CEDAR, false, false, false, false, false},
+ {{"cypress"}, {"cypress"}, GK_CYPRESS, true, false, false, false, false},
+ {{"hemlock"}, {"cypress"}, GK_CYPRESS, true, false, false, false, false},
+ {{"juniper"}, {"juniper"}, GK_JUNIPER, false, false, false, false, false},
+ {{"redwood"}, {"redwood"}, GK_REDWOOD, false, false, false, false, false},
+ {{"sumo"}, {"sumo"}, GK_SUMO, false, false, false, false, false},
+ {{"sumo2"}, {"sumo"}, GK_SUMO, false, false, false, false, false},
+ {{"barts"}, {"barts"}, GK_BARTS, false, false, false, false, false},
+ {{"caicos"}, {"caicos"}, GK_BARTS, false, false, false, false, false},
+ {{"aruba"}, {"cayman"}, GK_CAYMAN, true, false, false, false, false},
+ {{"cayman"}, {"cayman"}, GK_CAYMAN, true, false, false, false, false},
+ {{"turks"}, {"turks"}, GK_TURKS, false, false, false, false, false},
+ };
+ static constexpr GPUInfo AMDGCNGPUs[32] = {
+ // Name Canonical Kind Has Has Has Has Has
+ // Name FMAF Fast LDEXPF FP64 Fast
+ // FMAF FMA
+ {{"gfx600"}, {"gfx600"}, GK_GFX600, true, true, true, true, true},
+ {{"tahiti"}, {"gfx600"}, GK_GFX600, true, true, true, true, true},
+ {{"gfx601"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"hainan"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"oland"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"pitcairn"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"verde"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
+ {{"gfx700"}, {"gfx700"}, GK_GFX700, true, false, true, true, true},
+ {{"kaveri"}, {"gfx700"}, GK_GFX700, true, false, true, true, true},
+ {{"gfx701"}, {"gfx701"}, GK_GFX701, true, true, true, true, true},
+ {{"hawaii"}, {"gfx701"}, GK_GFX701, true, true, true, true, true},
+ {{"gfx702"}, {"gfx702"}, GK_GFX702, true, true, true, true, true},
+ {{"gfx703"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
+ {{"kabini"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
+ {{"mullins"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
+ {{"gfx704"}, {"gfx704"}, GK_GFX704, true, false, true, true, true},
+ {{"bonaire"}, {"gfx704"}, GK_GFX704, true, false, true, true, true},
+ {{"gfx801"}, {"gfx801"}, GK_GFX801, true, true, true, true, true},
+ {{"carrizo"}, {"gfx801"}, GK_GFX801, true, true, true, true, true},
+ {{"gfx802"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
+ {{"iceland"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
+ {{"tonga"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
+ {{"gfx803"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"fiji"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"polaris10"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"polaris11"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
+ {{"gfx810"}, {"gfx810"}, GK_GFX810, true, false, true, true, true},
+ {{"stoney"}, {"gfx810"}, GK_GFX810, true, false, true, true, true},
+ {{"gfx900"}, {"gfx900"}, GK_GFX900, true, true, true, true, true},
+ {{"gfx902"}, {"gfx902"}, GK_GFX900, true, true, true, true, true},
+ {{"gfx904"}, {"gfx904"}, GK_GFX904, true, true, true, true, true},
+ {{"gfx906"}, {"gfx906"}, GK_GFX906, true, true, true, true, true},
+ };
+
+ static GPUInfo parseR600Name(StringRef Name);
+
+ static GPUInfo parseAMDGCNName(StringRef Name);
+
+ GPUInfo parseGPUName(StringRef Name) const;
+
+ GPUInfo GPU;
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);
@@ -90,12 +187,10 @@ public:
void adjust(LangOptions &Opts) override;
uint64_t getPointerWidthV(unsigned AddrSpace) const override {
- if (GPU <= GK_CAYMAN)
+ if (GPU.Kind <= GK_R600_LAST)
return 32;
-
- if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
+ if (AddrSpace == Private || AddrSpace == Local)
return 32;
- }
return 64;
}
@@ -194,6 +289,19 @@ public:
return true;
}
+ // \p Constraint will be left pointing at the last character of
+ // the constraint. In practice, it won't be changed unless the
+ // constraint is longer than one character.
+ std::string convertConstraint(const char *&Constraint) const override {
+ const char *Begin = Constraint;
+ TargetInfo::ConstraintInfo Info("", "");
+ if (validateAsmConstraint(Constraint, Info))
+ return std::string(Begin).substr(0, Constraint - Begin + 1);
+
+ Constraint = Begin;
+ return std::string(1, *Constraint);
+ }
+
bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
@@ -211,24 +319,22 @@ public:
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);
+ return GK_NONE != parseAMDGCNName(Name).Kind;
else
- return GK_NONE != parseR600Name(Name);
+ return GK_NONE != parseR600Name(Name).Kind;
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override {
if (getTriple().getArch() == llvm::Triple::amdgcn)
GPU = parseAMDGCNName(Name);
else
GPU = parseR600Name(Name);
- return GPU != GK_NONE;
+ return GK_NONE != GPU.Kind;
}
void setSupportedOpenCLOpts() override {
@@ -236,16 +342,16 @@ public:
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("cl_khr_icd");
- if (hasFP64)
+ if (GPU.HasFP64)
Opts.support("cl_khr_fp64");
- if (GPU >= GK_EVERGREEN) {
+ if (GPU.Kind >= GK_CEDAR) {
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) {
+ if (GPU.Kind >= GK_AMDGCN_FIRST) {
Opts.support("cl_khr_fp16");
Opts.support("cl_khr_int64_base_atomics");
Opts.support("cl_khr_int64_extended_atomics");
@@ -273,11 +379,13 @@ public:
}
llvm::Optional<LangAS> getConstantAddressSpace() const override {
- return getLangASFromTargetAS(AS.Constant);
+ return getLangASFromTargetAS(Constant);
}
/// \returns Target specific vtbl ptr address space.
- unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }
+ unsigned getVtblPtrAddressSpace() const override {
+ return static_cast<unsigned>(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
@@ -289,9 +397,9 @@ public:
getDWARFAddressSpace(unsigned AddressSpace) const override {
const unsigned DWARF_Private = 1;
const unsigned DWARF_Local = 2;
- if (AddressSpace == AS.Private) {
+ if (AddressSpace == Private) {
return DWARF_Private;
- } else if (AddressSpace == AS.Local) {
+ } else if (AddressSpace == Local) {
return DWARF_Local;
} else {
return None;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
index 6fb0ab41ff5b..19fcc5abea97 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
@@ -185,6 +185,10 @@ StringRef ARMTargetInfo::getCPUAttr() const {
return "8_1A";
case llvm::ARM::ArchKind::ARMV8_2A:
return "8_2A";
+ case llvm::ARM::ArchKind::ARMV8_3A:
+ return "8_3A";
+ case llvm::ARM::ArchKind::ARMV8_4A:
+ return "8_4A";
case llvm::ARM::ArchKind::ARMV8MBaseline:
return "8M_BASE";
case llvm::ARM::ArchKind::ARMV8MMainline:
@@ -334,9 +338,20 @@ bool ARMTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
+ std::string ArchFeature;
std::vector<StringRef> TargetFeatures;
llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
+ // Map the base architecture to an appropriate target feature, so we don't
+ // rely on the target triple.
+ llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
+ if (CPUArch == llvm::ARM::ArchKind::INVALID)
+ CPUArch = Arch;
+ if (CPUArch != llvm::ARM::ArchKind::INVALID) {
+ ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
+ TargetFeatures.push_back(ArchFeature);
+ }
+
// get default FPU features
unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
@@ -379,6 +394,7 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
Unaligned = 1;
SoftFloat = SoftFloatABI = false;
HWDiv = 0;
+ DotProd = 0;
// This does not diagnose illegal cases like having both
// "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
@@ -419,6 +435,10 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
Unaligned = 0;
} else if (Feature == "+fp16") {
HW_FP |= HW_FP_HP;
+ } else if (Feature == "+fullfp16") {
+ HasLegalHalfType = true;
+ } else if (Feature == "+dotprod") {
+ DotProd = true;
}
}
HW_FP &= ~HW_FP_remove;
@@ -478,6 +498,10 @@ bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
}
+void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ llvm::ARM::fillValidCPUArchList(Values);
+}
+
bool ARMTargetInfo::setCPU(const std::string &Name) {
if (Name != "generic")
setArchInfo(llvm::ARM::parseCPUArch(Name));
@@ -706,6 +730,18 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
if (Opts.UnsafeFPMath)
Builder.defineMacro("__ARM_FP_FAST", "1");
+ // Armv8.2-A FP16 vector intrinsic
+ if ((FPU & NeonFPU) && HasLegalHalfType)
+ Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+
+ // Armv8.2-A FP16 scalar intrinsics
+ if (HasLegalHalfType)
+ Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
+
+ // Armv8.2-A dot product intrinsics
+ if (DotProd)
+ Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
+
switch (ArchKind) {
default:
break;
@@ -956,6 +992,8 @@ WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
return CCCR_Ignore;
case CC_C:
case CC_OpenCLKernel:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
return CCCR_OK;
default:
return CCCR_Warning;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
index fb0e7e66bea3..9c72c3387f7a 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
@@ -69,6 +69,7 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
unsigned Crypto : 1;
unsigned DSP : 1;
unsigned Unaligned : 1;
+ unsigned DotProd : 1;
enum {
LDREX_B = (1 << 0), /// byte (8-bit)
@@ -122,6 +123,8 @@ public:
bool hasFeature(StringRef Feature) const override;
bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override;
bool setFPMath(StringRef Name) override;
@@ -153,6 +156,11 @@ public:
std::string &SuggestedModifier) const override;
const char *getClobbers() const override;
+ StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const override {
+ return Expression;
+ }
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
int getEHDataRegisterNumber(unsigned RegNo) const override;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
index 3022fe33d76c..9b66449cbca6 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
@@ -28,7 +28,7 @@ struct LLVM_LIBRARY_VISIBILITY MCUInfo {
};
// This list should be kept up-to-date with AVRDevices.td in LLVM.
-static ArrayRef<MCUInfo> AVRMcus = {
+static MCUInfo AVRMcus[] = {
{"at90s1200", "__AVR_AT90S1200__"},
{"attiny11", "__AVR_ATtiny11__"},
{"attiny12", "__AVR_ATtiny12__"},
@@ -273,35 +273,29 @@ static ArrayRef<MCUInfo> AVRMcus = {
} // namespace targets
} // namespace clang
+static constexpr llvm::StringLiteral ValidFamilyNames[] = {
+ "avr1", "avr2", "avr25", "avr3", "avr31",
+ "avr35", "avr4", "avr5", "avr51", "avr6",
+ "avrxmega1", "avrxmega2", "avrxmega3", "avrxmega4", "avrxmega5",
+ "avrxmega6", "avrxmega7", "avrtiny"};
+
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 IsFamily =
+ llvm::find(ValidFamilyNames, Name) != std::end(ValidFamilyNames);
bool IsMCU =
- std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) {
+ llvm::find_if(AVRMcus, [&](const MCUInfo &Info) {
return Info.Name == Name;
- }) != AVRMcus.end();
+ }) != std::end(AVRMcus);
return IsFamily || IsMCU;
}
+void AVRTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidFamilyNames), std::end(ValidFamilyNames));
+ for (const MCUInfo &Info : AVRMcus)
+ Values.push_back(Info.Name);
+}
+
void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("AVR");
@@ -309,12 +303,10 @@ void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AVR__");
if (!this->CPU.empty()) {
- auto It =
- std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) {
- return Info.Name == this->CPU;
- });
+ auto It = llvm::find_if(
+ AVRMcus, [&](const MCUInfo &Info) { return Info.Name == this->CPU; });
- if (It != AVRMcus.end())
+ if (It != std::end(AVRMcus))
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
index 3dfb84f75668..d595f48e8ef7 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h
@@ -55,7 +55,7 @@ public:
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");
+ resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
}
void getTargetDefines(const LangOptions &Opts,
@@ -167,6 +167,7 @@ public:
}
bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override {
bool isValid = isValidCPUName(Name);
if (isValid)
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
index 54e34f15532d..cf41a09d76f5 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
@@ -14,6 +14,7 @@
#include "BPF.h"
#include "Targets.h"
#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringRef.h"
using namespace clang;
using namespace clang::targets;
@@ -23,3 +24,14 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
DefineStd(Builder, "bpf", Opts);
Builder.defineMacro("__BPF__");
}
+
+static constexpr llvm::StringLiteral ValidCPUNames[] = {"generic", "v1", "v2",
+ "probe"};
+
+bool BPFTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void BPFTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
index 4dd9cbd9d221..7f97f8189145 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
@@ -46,7 +46,14 @@ public:
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
- bool hasFeature(StringRef Feature) const override { return Feature == "bpf"; }
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "bpf" || Feature == "alu32" || Feature == "dwarfris";
+ }
+
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override {
+ Features[Name] = Enabled;
+ }
ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
@@ -56,6 +63,7 @@ public:
return TargetInfo::VoidPtrBuiltinVaList;
}
+ bool isValidGCCRegisterName(StringRef Name) const override { return true; }
ArrayRef<const char *> getGCCRegNames() const override { return None; }
bool validateAsmConstraint(const char *&Name,
@@ -77,12 +85,9 @@ public:
}
}
- bool isValidCPUName(StringRef Name) const override {
- if (Name == "generic" || Name == "v1" ||
- Name == "v2" || Name == "probe")
- return true;
- return false;
- }
+ bool isValidCPUName(StringRef Name) const override;
+
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override {
StringRef CPUName(Name);
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
index 71d4c1e0f161..0ef1f6db281e 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
@@ -75,7 +75,6 @@ void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
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);
@@ -132,6 +131,10 @@ const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
};
bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
+ std::string VS = "hvxv" + HVXVersion;
+ if (Feature == VS)
+ return true;
+
return llvm::StringSwitch<bool>(Feature)
.Case("hexagon", true)
.Case("hvx", HasHVX)
@@ -141,15 +144,29 @@ bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
+struct CPUSuffix {
+ llvm::StringLiteral Name;
+ llvm::StringLiteral Suffix;
+};
+
+static constexpr CPUSuffix Suffixes[] = {
+ {{"hexagonv4"}, {"4"}}, {{"hexagonv5"}, {"5"}},
+ {{"hexagonv55"}, {"55"}}, {{"hexagonv60"}, {"60"}},
+ {{"hexagonv62"}, {"62"}}, {{"hexagonv65"}, {"65"}},
+};
+
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);
+ const CPUSuffix *Item = llvm::find_if(
+ Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
+ if (Item == std::end(Suffixes))
+ return nullptr;
+ return Item->Suffix.data();
+}
+
+void HexagonTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const CPUSuffix &Suffix : Suffixes)
+ Values.push_back(Suffix.Name);
}
ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
index 7b0966457c4b..fb4956a9e53d 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
@@ -112,6 +112,8 @@ public:
return getHexagonCPUSuffix(Name);
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override {
if (!isValidCPUName(Name))
return false;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
index 1d8314af99fb..0e8030c04e5c 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
@@ -40,6 +40,10 @@ ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
bool LanaiTargetInfo::isValidCPUName(StringRef Name) const {
return llvm::StringSwitch<bool>(Name).Case("v11", true).Default(false);
}
+void LanaiTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ Values.emplace_back("v11");
+}
bool LanaiTargetInfo::setCPU(const std::string &Name) {
CPU = llvm::StringSwitch<CPUKind>(Name).Case("v11", CK_V11).Default(CK_NONE);
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
index 5f99c17a5344..b9e6dbe04433 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
@@ -65,6 +65,8 @@ public:
bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override;
bool hasFeature(StringRef Feature) const override;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
index a8a1bcc36361..cbd5a01c3da8 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
@@ -44,26 +44,19 @@ bool MipsTargetInfo::processorSupportsGPR64() const {
return false;
}
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+ {"mips1"}, {"mips2"}, {"mips3"}, {"mips4"}, {"mips5"},
+ {"mips32"}, {"mips32r2"}, {"mips32r3"}, {"mips32r5"}, {"mips32r6"},
+ {"mips64"}, {"mips64r2"}, {"mips64r3"}, {"mips64r5"}, {"mips64r6"},
+ {"octeon"}, {"p5600"}};
+
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);
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void MipsTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
}
void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
@@ -207,9 +200,7 @@ ArrayRef<Builtin::Info> MipsTargetInfo::getTargetBuiltins() const {
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")) {
+ if (getTriple().isMIPS64() && IsMicromips && (ABI == "n32" || ABI == "n64")) {
Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU;
return false;
}
@@ -229,9 +220,7 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
// 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") {
+ if (getTriple().isMIPS64() && ABI == "o32") {
Diags.Report(diag::err_target_unsupported_abi_for_triple)
<< ABI << getTriple().str();
return false;
@@ -240,9 +229,7 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
// 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")) {
+ if (getTriple().isMIPS32() && (ABI == "n32" || ABI == "n64")) {
Diags.Report(diag::err_target_unsupported_abi_for_triple)
<< ABI << getTriple().str();
return false;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
index 4b61116a3256..11e9ac914430 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
@@ -69,10 +69,7 @@ public:
UseIndirectJumpHazard(false), HasFP64(false) {
TheCXXABI.set(TargetCXXABI::GenericMIPS);
- setABI((getTriple().getArch() == llvm::Triple::mips ||
- getTriple().getArch() == llvm::Triple::mipsel)
- ? "o32"
- : "n64");
+ setABI(getTriple().isMIPS32() ? "o32" : "n64");
CPU = ABI == "o32" ? "mips32r2" : "mips64r2";
@@ -163,6 +160,7 @@ public:
}
bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override {
CPU = Name;
@@ -391,7 +389,9 @@ public:
return llvm::makeArrayRef(NewABIRegAliases);
}
- bool hasInt128Type() const override { return ABI == "n32" || ABI == "n64"; }
+ bool hasInt128Type() const override {
+ return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128;
+ }
bool validateTarget(DiagnosticsEngine &Diags) const override;
};
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
index add3b318aeb6..fd4ee1606061 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
@@ -40,6 +40,22 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
"NVPTX only supports 32- and 64-bit modes.");
+ PTXVersion = 32;
+ for (const StringRef Feature : Opts.FeaturesAsWritten) {
+ if (!Feature.startswith("+ptx"))
+ continue;
+ PTXVersion = llvm::StringSwitch<unsigned>(Feature)
+ .Case("+ptx61", 61)
+ .Case("+ptx60", 60)
+ .Case("+ptx50", 50)
+ .Case("+ptx43", 43)
+ .Case("+ptx42", 42)
+ .Case("+ptx41", 41)
+ .Case("+ptx40", 40)
+ .Case("+ptx32", 32)
+ .Default(32);
+ }
+
TLSSupported = false;
VLASupported = false;
AddrSpaceMap = &NVPTXAddrSpaceMap;
@@ -52,6 +68,9 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
if (TargetPointerWidth == 32)
resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+ else if (Opts.NVPTXUseShortPointers)
+ resetDataLayout(
+ "e-p3:32:32-p4:32:32-p5: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");
@@ -145,7 +164,6 @@ ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
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);
}
@@ -157,6 +175,21 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
// Set __CUDA_ARCH__ for the GPU specified.
std::string CUDAArchCode = [this] {
switch (GPU) {
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ case CudaArch::LAST:
+ break;
case CudaArch::UNKNOWN:
assert(false && "No GPU arch when compiling CUDA device code.");
return "";
@@ -186,6 +219,8 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
return "620";
case CudaArch::SM_70:
return "700";
+ case CudaArch::SM_72:
+ return "720";
}
llvm_unreachable("unhandled CudaArch");
}();
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
index a84870763f54..84d466d2f49f 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
@@ -40,6 +40,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
static const char *const GCCRegNames[];
static const Builtin::Info BuiltinInfo[];
CudaArch GPU;
+ uint32_t PTXVersion;
std::unique_ptr<TargetInfo> HostTarget;
public:
@@ -55,7 +56,8 @@ public:
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override {
- Features["satom"] = GPU >= CudaArch::SM_60;
+ Features[CudaArchToString(GPU)] = true;
+ Features["ptx" + std::to_string(PTXVersion)] = true;
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
@@ -98,6 +100,12 @@ public:
return StringToCudaArch(Name) != CudaArch::UNKNOWN;
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
+ for (int i = static_cast<int>(CudaArch::SM_20);
+ i < static_cast<int>(CudaArch::LAST); ++i)
+ Values.emplace_back(CudaArchToString(static_cast<CudaArch>(i)));
+ }
+
bool setCPU(const std::string &Name) override {
GPU = StringToCudaArch(Name);
return GPU != CudaArch::UNKNOWN;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
index aa02f8f6262f..ffeb414d4778 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
@@ -56,6 +56,10 @@ public:
return Name == "nios2r1" || Name == "nios2r2";
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
+ Values.append({"nios2r1", "nios2r2"});
+ }
+
bool setCPU(const std::string &Name) override {
if (isValidCPUName(Name)) {
CPU = Name;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
index 5af63615dc5e..d0354784acf9 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
@@ -95,16 +95,22 @@ public:
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)
+ // 64-bit iOS supported it from 8 onwards, 32-bit device from 9 onwards,
+ // 32-bit simulator from 10 onwards.
+ if (Triple.isArch64Bit())
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);
+ else if (Triple.isArch32Bit()) {
+ if (!Triple.isSimulatorEnvironment())
+ this->TLSSupported = !Triple.isOSVersionLT(9);
+ else
+ this->TLSSupported = !Triple.isOSVersionLT(10);
+ }
+ } else if (Triple.isWatchOS()) {
+ if (!Triple.isSimulatorEnvironment())
+ this->TLSSupported = !Triple.isOSVersionLT(2);
+ else
+ this->TLSSupported = !Triple.isOSVersionLT(3);
+ }
this->MCountName = "\01mcount";
}
@@ -363,7 +369,7 @@ protected:
public:
NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
- this->MCountName = "_mcount";
+ this->MCountName = "__mcount";
}
};
@@ -479,6 +485,7 @@ public:
default:
case llvm::Triple::x86_64:
this->MCountName = ".mcount";
+ this->NewAlign = 256;
break;
}
}
@@ -544,13 +551,24 @@ protected:
Builder.defineMacro("_LARGEFILE_SOURCE");
Builder.defineMacro("_LARGEFILE64_SOURCE");
Builder.defineMacro("__EXTENSIONS__");
- Builder.defineMacro("_REENTRANT");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
}
public:
SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
// FIXME: WIntType should be SignedLong
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->HasFloat128 = true;
+ break;
+ }
}
};
@@ -599,8 +617,10 @@ protected:
Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
- if (Opts.CPlusPlus17)
- Builder.defineMacro("_MSVC_LANG", "201403L");
+ if (Opts.CPlusPlus2a)
+ Builder.defineMacro("_MSVC_LANG", "201704L");
+ else if (Opts.CPlusPlus17)
+ Builder.defineMacro("_MSVC_LANG", "201703L");
else if (Opts.CPlusPlus14)
Builder.defineMacro("_MSVC_LANG", "201402L");
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
index a44aa0cd96f0..b4eb3b1b97b7 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
@@ -15,7 +15,6 @@
#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;
@@ -96,7 +95,7 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
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
+ // our support 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");
@@ -116,111 +115,37 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
(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)
+ if (ArchDefs & ArchDefineName)
Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper()));
- if (defs & ArchDefinePpcgr)
+ if (ArchDefs & ArchDefinePpcgr)
Builder.defineMacro("_ARCH_PPCGR");
- if (defs & ArchDefinePpcsq)
+ if (ArchDefs & ArchDefinePpcsq)
Builder.defineMacro("_ARCH_PPCSQ");
- if (defs & ArchDefine440)
+ if (ArchDefs & ArchDefine440)
Builder.defineMacro("_ARCH_440");
- if (defs & ArchDefine603)
+ if (ArchDefs & ArchDefine603)
Builder.defineMacro("_ARCH_603");
- if (defs & ArchDefine604)
+ if (ArchDefs & ArchDefine604)
Builder.defineMacro("_ARCH_604");
- if (defs & ArchDefinePwr4)
+ if (ArchDefs & ArchDefinePwr4)
Builder.defineMacro("_ARCH_PWR4");
- if (defs & ArchDefinePwr5)
+ if (ArchDefs & ArchDefinePwr5)
Builder.defineMacro("_ARCH_PWR5");
- if (defs & ArchDefinePwr5x)
+ if (ArchDefs & ArchDefinePwr5x)
Builder.defineMacro("_ARCH_PWR5X");
- if (defs & ArchDefinePwr6)
+ if (ArchDefs & ArchDefinePwr6)
Builder.defineMacro("_ARCH_PWR6");
- if (defs & ArchDefinePwr6x)
+ if (ArchDefs & ArchDefinePwr6x)
Builder.defineMacro("_ARCH_PWR6X");
- if (defs & ArchDefinePwr7)
+ if (ArchDefs & ArchDefinePwr7)
Builder.defineMacro("_ARCH_PWR7");
- if (defs & ArchDefinePwr8)
+ if (ArchDefs & ArchDefinePwr8)
Builder.defineMacro("_ARCH_PWR8");
- if (defs & ArchDefinePwr9)
+ if (ArchDefs & ArchDefinePwr9)
Builder.defineMacro("_ARCH_PWR9");
- if (defs & ArchDefineA2)
+ if (ArchDefs & ArchDefineA2)
Builder.defineMacro("_ARCH_A2");
- if (defs & ArchDefineA2q) {
+ if (ArchDefs & ArchDefineA2q) {
Builder.defineMacro("_ARCH_A2Q");
Builder.defineMacro("_ARCH_QP");
}
@@ -384,6 +309,14 @@ bool PPCTargetInfo::initFeatureMap(
if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
return false;
+ if (!(ArchDefs & ArchDefinePwr9) && (ArchDefs & ArchDefinePpcgr) &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
+ FeaturesVec.end()) {
+ // We have __float128 on PPC but not power 9 and above.
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" << CPU;
+ return false;
+ }
+
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
@@ -479,57 +412,25 @@ ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+ {"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
+ {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
+ {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"},
+ {"7450"}, {"g4+"}, {"750"}, {"970"}, {"g5"},
+ {"a2"}, {"a2q"}, {"e500mc"}, {"e5500"}, {"power3"},
+ {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"}, {"pwr5"},
+ {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"}, {"power6x"},
+ {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"}, {"pwr8"},
+ {"power9"}, {"pwr9"}, {"powerpc"}, {"ppc"}, {"powerpc64"},
+ {"ppc64"}, {"powerpc64le"}, {"ppc64le"},
+};
+
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);
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void PPCTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
}
void PPCTargetInfo::adjust(LangOptions &Opts) {
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
index 04bef258e386..439c73a0e326 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
@@ -18,6 +18,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
namespace clang {
@@ -25,39 +26,8 @@ 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.
+ /// Flags for architecture specific defines.
typedef enum {
ArchDefineNone = 0,
ArchDefineName = 1 << 0, // <name> is substituted for arch name.
@@ -78,6 +48,37 @@ public:
ArchDefineA2q = 1 << 15
} ArchDefineTypes;
+
+ ArchDefineTypes ArchDefs = ArchDefineNone;
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ std::string CPU;
+
+ // Target cpu features.
+ bool HasAltivec = false;
+ bool HasVSX = false;
+ bool HasP8Vector = false;
+ bool HasP8Crypto = false;
+ bool HasDirectMove = false;
+ bool HasQPX = false;
+ bool HasHTM = false;
+ bool HasBPERMD = false;
+ bool HasExtDiv = false;
+ bool HasP9Vector = false;
+
+protected:
+ std::string ABI;
+
+public:
+ PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ SuitableAlign = 128;
+ SimdDefaultAlign = 128;
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
+ }
+
// Set the language option for altivec based on our value.
void adjust(LangOptions &Opts) override;
@@ -86,11 +87,66 @@ public:
// 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell,
// titan, rs64.
bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override {
bool CPUKnown = isValidCPUName(Name);
- if (CPUKnown)
+ if (CPUKnown) {
CPU = Name;
+
+ // CPU identification.
+ ArchDefs =
+ (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)
+ .Cases("power3", "pwr3", ArchDefinePpcgr)
+ .Cases("power4", "pwr4",
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power5", "pwr5",
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Cases("power5x", "pwr5x",
+ ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power6", "pwr6",
+ ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power6x", "pwr6x",
+ ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Cases("power7", "pwr7",
+ ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 |
+ ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ // powerpc64le automatically defaults to at least power8.
+ .Cases("power8", "pwr8", "ppc64le",
+ ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
+ ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Cases("power9", "pwr9",
+ ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |
+ ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Default(ArchDefineNone);
+ }
return CPUKnown;
}
@@ -310,10 +366,6 @@ public:
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
break;
- case llvm::Triple::NetBSD:
- IntMaxType = SignedLongLong;
- Int64Type = SignedLongLong;
- break;
default:
break;
}
@@ -334,6 +386,15 @@ public:
}
return false;
}
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_Swift:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
};
class LLVM_LIBRARY_VISIBILITY DarwinPPC32TargetInfo
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp
new file mode 100644
index 000000000000..7eb5e6a686a9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.cpp
@@ -0,0 +1,104 @@
+//===--- RISCV.cpp - Implement RISCV 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 RISCV TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
+ static const char *const GCCRegNames[] = {
+ "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", "x29", "x30", "x31"};
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
+ static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+ {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"},
+ {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"},
+ {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"},
+ {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x15"}, {{"a5"}, "x15"},
+ {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"},
+ {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"},
+ {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"},
+ {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}};
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__riscv");
+ bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
+ Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
+ // TODO: modify when more code models and ABIs are supported.
+ Builder.defineMacro("__riscv_cmodel_medlow");
+ Builder.defineMacro("__riscv_float_abi_soft");
+
+ if (HasM) {
+ Builder.defineMacro("__riscv_mul");
+ Builder.defineMacro("__riscv_div");
+ Builder.defineMacro("__riscv_muldiv");
+ }
+
+ if (HasA)
+ Builder.defineMacro("__riscv_atomic");
+
+ if (HasF || HasD) {
+ Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
+ Builder.defineMacro("__riscv_fdiv");
+ Builder.defineMacro("__riscv_fsqrt");
+ }
+
+ if (HasC)
+ Builder.defineMacro("__riscv_compressed");
+}
+
+/// Return true if has this feature, need to sync with handleTargetFeatures.
+bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
+ bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("riscv", true)
+ .Case("riscv32", !Is64Bit)
+ .Case("riscv64", Is64Bit)
+ .Case("m", HasM)
+ .Case("a", HasA)
+ .Case("f", HasF)
+ .Case("d", HasD)
+ .Case("c", HasC)
+ .Default(false);
+}
+
+/// Perform initialization based on the user configured set of features.
+bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature == "+m")
+ HasM = true;
+ else if (Feature == "+a")
+ HasA = true;
+ else if (Feature == "+f")
+ HasF = true;
+ else if (Feature == "+d")
+ HasD = true;
+ else if (Feature == "+c")
+ HasC = true;
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h
new file mode 100644
index 000000000000..f83aae539391
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/RISCV.h
@@ -0,0 +1,114 @@
+//===--- RISCV.h - Declare RISCV 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 RISCV TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_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 {
+
+// RISC-V Target
+class RISCVTargetInfo : public TargetInfo {
+protected:
+ std::string ABI;
+ bool HasM;
+ bool HasA;
+ bool HasF;
+ bool HasD;
+ bool HasC;
+
+public:
+ RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), HasM(false), HasA(false), HasF(false),
+ HasD(false), HasC(false) {
+ TLSSupported = false;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ SuitableAlign = 128;
+ WCharType = SignedInt;
+ WIntType = UnsignedInt;
+ }
+
+ StringRef getABI() const override { return ABI; }
+ 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;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+};
+class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
+public:
+ RISCV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : RISCVTargetInfo(Triple, Opts) {
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ SizeType = UnsignedInt;
+ resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128");
+ }
+
+ bool setABI(const std::string &Name) override {
+ // TODO: support ilp32f and ilp32d ABIs.
+ if (Name == "ilp32") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+};
+class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {
+public:
+ RISCV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : RISCVTargetInfo(Triple, Opts) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ IntMaxType = Int64Type = SignedLong;
+ resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n64-S128");
+ }
+
+ bool setABI(const std::string &Name) override {
+ // TODO: support lp64f and lp64d ABIs.
+ if (Name == "lp64") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
index c384d4260ca9..9815292fc276 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
@@ -47,6 +47,7 @@ public:
LongWidth = LongAlign = 64;
AddrSpaceMap = &SPIRAddrSpaceMap;
UseAddrSpaceMapMangling = true;
+ HasLegalHalfType = true;
// Define available target features
// These must be defined in sorted order!
NoAsmVariants = true;
@@ -59,6 +60,10 @@ public:
return Feature == "spir";
}
+ // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is
+ // memcpy as per section 3 of the SPIR spec.
+ bool useFP16ConversionIntrinsics() const override { return false; }
+
ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
const char *getClobbers() const override { return ""; }
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
index 429c1ee3a23c..ee4f309363af 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
@@ -20,9 +20,17 @@ using namespace clang;
using namespace clang::targets;
const char *const SparcTargetInfo::GCCRegNames[] = {
+ // Integer registers
"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"
+ "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ // Floating-point registers
+ "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", "f32",
+ "f34", "f36", "f38", "f40", "f42", "f44", "f46", "f48", "f50", "f52", "f54",
+ "f56", "f58", "f60", "f62",
};
ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
@@ -51,49 +59,81 @@ bool SparcTargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
+struct SparcCPUInfo {
+ llvm::StringLiteral Name;
+ SparcTargetInfo::CPUKind Kind;
+ SparcTargetInfo::CPUGeneration Generation;
+};
+
+static constexpr SparcCPUInfo CPUInfo[] = {
+ {{"v8"}, SparcTargetInfo::CK_V8, SparcTargetInfo::CG_V8},
+ {{"supersparc"}, SparcTargetInfo::CK_SUPERSPARC, SparcTargetInfo::CG_V8},
+ {{"sparclite"}, SparcTargetInfo::CK_SPARCLITE, SparcTargetInfo::CG_V8},
+ {{"f934"}, SparcTargetInfo::CK_F934, SparcTargetInfo::CG_V8},
+ {{"hypersparc"}, SparcTargetInfo::CK_HYPERSPARC, SparcTargetInfo::CG_V8},
+ {{"sparclite86x"},
+ SparcTargetInfo::CK_SPARCLITE86X,
+ SparcTargetInfo::CG_V8},
+ {{"sparclet"}, SparcTargetInfo::CK_SPARCLET, SparcTargetInfo::CG_V8},
+ {{"tsc701"}, SparcTargetInfo::CK_TSC701, SparcTargetInfo::CG_V8},
+ {{"v9"}, SparcTargetInfo::CK_V9, SparcTargetInfo::CG_V9},
+ {{"ultrasparc"}, SparcTargetInfo::CK_ULTRASPARC, SparcTargetInfo::CG_V9},
+ {{"ultrasparc3"}, SparcTargetInfo::CK_ULTRASPARC3, SparcTargetInfo::CG_V9},
+ {{"niagara"}, SparcTargetInfo::CK_NIAGARA, SparcTargetInfo::CG_V9},
+ {{"niagara2"}, SparcTargetInfo::CK_NIAGARA2, SparcTargetInfo::CG_V9},
+ {{"niagara3"}, SparcTargetInfo::CK_NIAGARA3, SparcTargetInfo::CG_V9},
+ {{"niagara4"}, SparcTargetInfo::CK_NIAGARA4, SparcTargetInfo::CG_V9},
+ {{"ma2100"}, SparcTargetInfo::CK_MYRIAD2100, SparcTargetInfo::CG_V8},
+ {{"ma2150"}, SparcTargetInfo::CK_MYRIAD2150, SparcTargetInfo::CG_V8},
+ {{"ma2155"}, SparcTargetInfo::CK_MYRIAD2155, SparcTargetInfo::CG_V8},
+ {{"ma2450"}, SparcTargetInfo::CK_MYRIAD2450, SparcTargetInfo::CG_V8},
+ {{"ma2455"}, SparcTargetInfo::CK_MYRIAD2455, SparcTargetInfo::CG_V8},
+ {{"ma2x5x"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
+ {{"ma2080"}, SparcTargetInfo::CK_MYRIAD2080, SparcTargetInfo::CG_V8},
+ {{"ma2085"}, SparcTargetInfo::CK_MYRIAD2085, SparcTargetInfo::CG_V8},
+ {{"ma2480"}, SparcTargetInfo::CK_MYRIAD2480, SparcTargetInfo::CG_V8},
+ {{"ma2485"}, SparcTargetInfo::CK_MYRIAD2485, SparcTargetInfo::CG_V8},
+ {{"ma2x8x"}, SparcTargetInfo::CK_MYRIAD2x8x, SparcTargetInfo::CG_V8},
+ // FIXME: the myriad2[.n] spellings are obsolete,
+ // but a grace period is needed to allow updating dependent builds.
+ {{"myriad2"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
+ {{"myriad2.1"}, SparcTargetInfo::CK_MYRIAD2100, SparcTargetInfo::CG_V8},
+ {{"myriad2.2"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
+ {{"myriad2.3"}, SparcTargetInfo::CK_MYRIAD2x8x, SparcTargetInfo::CG_V8},
+ {{"leon2"}, SparcTargetInfo::CK_LEON2, SparcTargetInfo::CG_V8},
+ {{"at697e"}, SparcTargetInfo::CK_LEON2_AT697E, SparcTargetInfo::CG_V8},
+ {{"at697f"}, SparcTargetInfo::CK_LEON2_AT697F, SparcTargetInfo::CG_V8},
+ {{"leon3"}, SparcTargetInfo::CK_LEON3, SparcTargetInfo::CG_V8},
+ {{"ut699"}, SparcTargetInfo::CK_LEON3_UT699, SparcTargetInfo::CG_V8},
+ {{"gr712rc"}, SparcTargetInfo::CK_LEON3_GR712RC, SparcTargetInfo::CG_V8},
+ {{"leon4"}, SparcTargetInfo::CK_LEON4, SparcTargetInfo::CG_V8},
+ {{"gr740"}, SparcTargetInfo::CK_LEON4_GR740, SparcTargetInfo::CG_V8},
+};
+
+SparcTargetInfo::CPUGeneration
+SparcTargetInfo::getCPUGeneration(CPUKind Kind) const {
+ if (Kind == CK_GENERIC)
+ return CG_V8;
+ const SparcCPUInfo *Item = llvm::find_if(
+ CPUInfo, [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; });
+ if (Item == std::end(CPUInfo))
+ llvm_unreachable("Unexpected CPU kind");
+ return Item->Generation;
+}
+
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);
+ const SparcCPUInfo *Item = llvm::find_if(
+ CPUInfo, [Name](const SparcCPUInfo &Info) { return Info.Name == Name; });
+
+ if (Item == std::end(CPUInfo))
+ return CK_GENERIC;
+ return Item->Kind;
+}
+
+void SparcTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const SparcCPUInfo &Info : CPUInfo)
+ Values.push_back(Info.Name);
}
void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
@@ -178,6 +218,13 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro(MyriadArchValue, "1");
Builder.defineMacro(MyriadArchValue + "__", "1");
}
+ if (Myriad2Value == "2") {
+ Builder.defineMacro("__ma2x5x", "1");
+ Builder.defineMacro("__ma2x5x__", "1");
+ } else if (Myriad2Value == "3") {
+ Builder.defineMacro("__ma2x8x", "1");
+ Builder.defineMacro("__ma2x8x__", "1");
+ }
Builder.defineMacro("__myriad2__", Myriad2Value);
Builder.defineMacro("__myriad2", Myriad2Value);
}
@@ -195,3 +242,10 @@ void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__sparcv9__");
}
}
+
+void SparcV9TargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const SparcCPUInfo &Info : CPUInfo)
+ if (Info.Generation == CG_V9)
+ Values.push_back(Info.Name);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
index aacc26119dfb..af2189f21468 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
@@ -1,4 +1,4 @@
-//===--- Sparc.h - Declare Sparc target feature support -------------------===//
+//===--- Sparc.h - declare sparc target feature support ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -131,48 +131,7 @@ public:
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");
- }
+ CPUGeneration getCPUGeneration(CPUKind Kind) const;
CPUKind getCPUKind(StringRef Name) const;
@@ -180,6 +139,8 @@ public:
return getCPUKind(Name) != CK_GENERIC;
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override {
CPU = getCPUKind(Name);
return CPU != CK_GENERIC;
@@ -259,6 +220,8 @@ public:
return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9;
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override {
if (!SparcTargetInfo::setCPU(Name))
return false;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
index 98f3ae2f72b4..6f06f1fc760c 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
@@ -30,15 +30,30 @@ const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
};
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"
+ "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",
+ /*ap*/"", "cc", /*fp*/"", /*rp*/"", "a0", "a1",
+ "v16", "v18", "v20", "v22", "v17", "v19", "v21", "v23",
+ "v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31"
+};
+
+const TargetInfo::AddlRegName GCCAddlRegNames[] = {
+ {{"v0"}, 16}, {{"v2"}, 17}, {{"v4"}, 18}, {{"v6"}, 19},
+ {{"v1"}, 20}, {{"v3"}, 21}, {{"v5"}, 22}, {{"v7"}, 23},
+ {{"v8"}, 24}, {{"v10"}, 25}, {{"v12"}, 26}, {{"v14"}, 27},
+ {{"v9"}, 28}, {{"v11"}, 29}, {{"v13"}, 30}, {{"v15"}, 31}
};
ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
+ArrayRef<TargetInfo::AddlRegName> SystemZTargetInfo::getGCCAddlRegNames() const {
+ return llvm::makeArrayRef(GCCAddlRegNames);
+}
+
bool SystemZTargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
@@ -48,6 +63,7 @@ bool SystemZTargetInfo::validateAsmConstraint(
case 'a': // Address register
case 'd': // Data register (equivalent to 'r')
case 'f': // Floating-point register
+ case 'v': // Vector register
Info.setAllowsRegister();
return true;
@@ -67,14 +83,32 @@ bool SystemZTargetInfo::validateAsmConstraint(
}
}
-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);
+struct ISANameRevision {
+ llvm::StringLiteral Name;
+ int ISARevisionID;
+};
+static constexpr ISANameRevision ISARevisions[] = {
+ {{"arch8"}, 8}, {{"z10"}, 8},
+ {{"arch9"}, 9}, {{"z196"}, 9},
+ {{"arch10"}, 10}, {{"zEC12"}, 10},
+ {{"arch11"}, 11}, {{"z13"}, 11},
+ {{"arch12"}, 12}, {{"z14"}, 12}
+};
+
+int SystemZTargetInfo::getISARevision(StringRef Name) const {
+ const auto Rev =
+ llvm::find_if(ISARevisions, [Name](const ISANameRevision &CR) {
+ return CR.Name == Name;
+ });
+ if (Rev == std::end(ISARevisions))
+ return -1;
+ return Rev->ISARevisionID;
+}
+
+void SystemZTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ for (const ISANameRevision &Rev : ISARevisions)
+ Values.push_back(Rev.Name);
}
bool SystemZTargetInfo::hasFeature(StringRef Feature) const {
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
index 3023c1d2ea26..842316005ed9 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
@@ -62,6 +62,8 @@ public:
return None;
}
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
+
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
@@ -74,12 +76,14 @@ public:
return TargetInfo::SystemZBuiltinVaList;
}
- int getISARevision(const StringRef &Name) const;
+ int getISARevision(StringRef Name) const;
bool isValidCPUName(StringRef Name) const override {
return getISARevision(Name) != -1;
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override {
CPU = Name;
ISARevision = getISARevision(CPU);
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
index 915aad4b563b..b8a2a092aff4 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -29,19 +29,25 @@ const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
#include "clang/Basic/BuiltinsWebAssembly.def"
};
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+ {"mvp"}, {"bleeding-edge"}, {"generic"}};
+
bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("simd128", SIMDLevel >= SIMD128)
.Case("nontrapping-fptoint", HasNontrappingFPToInt)
+ .Case("sign-ext", HasSignExt)
+ .Case("exception-handling", HasExceptionHandling)
.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);
+ return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
+}
+
+void WebAssemblyTargetInfo::fillValidCPUList(
+ SmallVectorImpl<StringRef> &Values) const {
+ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
}
void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
@@ -70,6 +76,22 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasNontrappingFPToInt = false;
continue;
}
+ if (Feature == "+sign-ext") {
+ HasSignExt = true;
+ continue;
+ }
+ if (Feature == "-sign-ext") {
+ HasSignExt = false;
+ continue;
+ }
+ if (Feature == "+exception-handling") {
+ HasExceptionHandling = true;
+ continue;
+ }
+ if (Feature == "-exception-handling") {
+ HasExceptionHandling = false;
+ continue;
+ }
Diags.Report(diag::err_opt_not_valid_with_opt)
<< Feature << "-target-feature";
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
index ee0073d081e0..c04c5cb6fb3a 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
@@ -31,10 +31,13 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
} SIMDLevel;
bool HasNontrappingFPToInt;
+ bool HasSignExt;
+ bool HasExceptionHandling;
public:
explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
- : TargetInfo(T), SIMDLevel(NoSIMD), HasNontrappingFPToInt(false) {
+ : TargetInfo(T), SIMDLevel(NoSIMD), HasNontrappingFPToInt(false),
+ HasSignExt(false), HasExceptionHandling(false) {
NoAsmVariants = true;
SuitableAlign = 128;
LargeArrayMinWidth = 128;
@@ -43,9 +46,12 @@ public:
SigAtomicType = SignedLong;
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad();
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ // size_t being unsigned long for both wasm32 and wasm64 makes mangled names
+ // more consistent between the two.
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
}
protected:
@@ -60,6 +66,7 @@ private:
if (CPU == "bleeding-edge") {
Features["simd128"] = true;
Features["nontrapping-fptoint"] = true;
+ Features["sign-ext"] = true;
}
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
@@ -70,6 +77,7 @@ private:
DiagnosticsEngine &Diags) final;
bool isValidCPUName(StringRef Name) const final;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final;
bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
@@ -115,7 +123,6 @@ 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");
}
@@ -132,7 +139,6 @@ public:
: WebAssemblyTargetInfo(T, Opts) {
LongAlign = LongWidth = 64;
PointerAlign = PointerWidth = 64;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntPtrType = SignedLong;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
index 8251e6abd649..e295cff9d5d2 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
@@ -15,8 +15,10 @@
#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"
+#include "llvm/Support/TargetParser.h"
namespace clang {
namespace targets {
@@ -131,7 +133,11 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "mmx", true);
break;
- case CK_Icelake:
+ case CK_IcelakeServer:
+ setFeatureEnabledImpl(Features, "pconfig", true);
+ setFeatureEnabledImpl(Features, "wbnoinvd", true);
+ LLVM_FALLTHROUGH;
+ case CK_IcelakeClient:
setFeatureEnabledImpl(Features, "vaes", true);
setFeatureEnabledImpl(Features, "gfni", true);
setFeatureEnabledImpl(Features, "vpclmulqdq", true);
@@ -139,6 +145,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512vnni", true);
setFeatureEnabledImpl(Features, "avx512vbmi2", true);
setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
+ setFeatureEnabledImpl(Features, "rdpid", true);
LLVM_FALLTHROUGH;
case CK_Cannonlake:
setFeatureEnabledImpl(Features, "avx512ifma", true);
@@ -159,7 +166,8 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "xsavec", true);
setFeatureEnabledImpl(Features, "xsaves", true);
setFeatureEnabledImpl(Features, "mpx", true);
- setFeatureEnabledImpl(Features, "sgx", true);
+ if (Kind != CK_SkylakeServer) // SKX inherits all SKL features, except SGX
+ setFeatureEnabledImpl(Features, "sgx", true);
setFeatureEnabledImpl(Features, "clflushopt", true);
setFeatureEnabledImpl(Features, "rtm", true);
LLVM_FALLTHROUGH;
@@ -174,6 +182,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "bmi", true);
setFeatureEnabledImpl(Features, "bmi2", true);
setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "invpcid", true);
setFeatureEnabledImpl(Features, "movbe", true);
LLVM_FALLTHROUGH;
case CK_IvyBridge:
@@ -217,9 +226,20 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "fxsr", true);
break;
+ case CK_Tremont:
+ setFeatureEnabledImpl(Features, "cldemote", true);
+ setFeatureEnabledImpl(Features, "movdiri", true);
+ setFeatureEnabledImpl(Features, "movdir64b", true);
+ setFeatureEnabledImpl(Features, "gfni", true);
+ setFeatureEnabledImpl(Features, "waitpkg", true);
+ LLVM_FALLTHROUGH;
+ case CK_GoldmontPlus:
+ setFeatureEnabledImpl(Features, "ptwrite", true);
+ setFeatureEnabledImpl(Features, "rdpid", true);
+ setFeatureEnabledImpl(Features, "sgx", true);
+ LLVM_FALLTHROUGH;
case CK_Goldmont:
setFeatureEnabledImpl(Features, "sha", true);
- setFeatureEnabledImpl(Features, "rdrnd", true);
setFeatureEnabledImpl(Features, "rdseed", true);
setFeatureEnabledImpl(Features, "xsave", true);
setFeatureEnabledImpl(Features, "xsaveopt", true);
@@ -230,6 +250,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "fsgsbase", true);
LLVM_FALLTHROUGH;
case CK_Silvermont:
+ setFeatureEnabledImpl(Features, "rdrnd", true);
setFeatureEnabledImpl(Features, "aes", true);
setFeatureEnabledImpl(Features, "pclmul", true);
setFeatureEnabledImpl(Features, "sse4.2", true);
@@ -741,8 +762,6 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasMPX = true;
} else if (Feature == "+shstk") {
HasSHSTK = true;
- } else if (Feature == "+ibt") {
- HasIBT = true;
} else if (Feature == "+movbe") {
HasMOVBE = true;
} else if (Feature == "+sgx") {
@@ -767,16 +786,34 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasCLFLUSHOPT = true;
} else if (Feature == "+clwb") {
HasCLWB = true;
+ } else if (Feature == "+wbnoinvd") {
+ HasWBNOINVD = true;
} else if (Feature == "+prefetchwt1") {
HasPREFETCHWT1 = true;
} else if (Feature == "+clzero") {
HasCLZERO = true;
+ } else if (Feature == "+cldemote") {
+ HasCLDEMOTE = true;
+ } else if (Feature == "+rdpid") {
+ HasRDPID = true;
} else if (Feature == "+retpoline") {
HasRetpoline = true;
} else if (Feature == "+retpoline-external-thunk") {
HasRetpolineExternalThunk = true;
} else if (Feature == "+sahf") {
HasLAHFSAHF = true;
+ } else if (Feature == "+waitpkg") {
+ HasWAITPKG = true;
+ } else if (Feature == "+movdiri") {
+ HasMOVDIRI = true;
+ } else if (Feature == "+movdir64b") {
+ HasMOVDIR64B = true;
+ } else if (Feature == "+pconfig") {
+ HasPCONFIG = true;
+ } else if (Feature == "+ptwrite") {
+ HasPTWRITE = true;
+ } else if (Feature == "+invpcid") {
+ HasINVPCID = true;
}
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
@@ -897,6 +934,12 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
case CK_Goldmont:
defineCPUMacros(Builder, "goldmont");
break;
+ case CK_GoldmontPlus:
+ defineCPUMacros(Builder, "goldmont_plus");
+ break;
+ case CK_Tremont:
+ defineCPUMacros(Builder, "tremont");
+ break;
case CK_Nehalem:
case CK_Westmere:
case CK_SandyBridge:
@@ -906,7 +949,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
case CK_SkylakeClient:
case CK_SkylakeServer:
case CK_Cannonlake:
- case CK_Icelake:
+ case CK_IcelakeClient:
+ case CK_IcelakeServer:
// 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.
@@ -1102,12 +1146,12 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
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 (HasWBNOINVD)
+ Builder.defineMacro("__WBNOINVD__");
if (HasMPX)
Builder.defineMacro("__MPX__");
if (HasSHSTK)
@@ -1118,6 +1162,22 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__PREFETCHWT1__");
if (HasCLZERO)
Builder.defineMacro("__CLZERO__");
+ if (HasRDPID)
+ Builder.defineMacro("__RDPID__");
+ if (HasCLDEMOTE)
+ Builder.defineMacro("__CLDEMOTE__");
+ if (HasWAITPKG)
+ Builder.defineMacro("__WAITPKG__");
+ if (HasMOVDIRI)
+ Builder.defineMacro("__MOVDIRI__");
+ if (HasMOVDIR64B)
+ Builder.defineMacro("__MOVDIR64B__");
+ if (HasPCONFIG)
+ Builder.defineMacro("__PCONFIG__");
+ if (HasPTWRITE)
+ Builder.defineMacro("__PTWRITE__");
+ if (HasINVPCID)
+ Builder.defineMacro("__INVPCID__");
// Each case falls through to the previous one here.
switch (SSELevel) {
@@ -1197,6 +1257,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
}
if (CPU >= CK_i586)
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ if (HasCX16)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
if (HasFloat128)
Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
@@ -1225,6 +1287,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("avx512ifma", true)
.Case("bmi", true)
.Case("bmi2", true)
+ .Case("cldemote", true)
.Case("clflushopt", true)
.Case("clwb", true)
.Case("clzero", true)
@@ -1235,17 +1298,23 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("fsgsbase", true)
.Case("fxsr", true)
.Case("gfni", true)
+ .Case("invpcid", true)
.Case("lwp", true)
.Case("lzcnt", true)
.Case("mmx", true)
.Case("movbe", true)
+ .Case("movdiri", true)
+ .Case("movdir64b", true)
.Case("mpx", true)
.Case("mwaitx", true)
.Case("pclmul", true)
+ .Case("pconfig", true)
.Case("pku", true)
.Case("popcnt", true)
.Case("prefetchwt1", true)
.Case("prfchw", true)
+ .Case("ptwrite", true)
+ .Case("rdpid", true)
.Case("rdrnd", true)
.Case("rdseed", true)
.Case("rtm", true)
@@ -1264,6 +1333,8 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("tbm", true)
.Case("vaes", true)
.Case("vpclmulqdq", true)
+ .Case("wbnoinvd", true)
+ .Case("waitpkg", true)
.Case("x87", true)
.Case("xop", true)
.Case("xsave", true)
@@ -1294,6 +1365,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("avx512ifma", HasAVX512IFMA)
.Case("bmi", HasBMI)
.Case("bmi2", HasBMI2)
+ .Case("cldemote", HasCLDEMOTE)
.Case("clflushopt", HasCLFLUSHOPT)
.Case("clwb", HasCLWB)
.Case("clzero", HasCLZERO)
@@ -1304,20 +1376,25 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("fsgsbase", HasFSGSBASE)
.Case("fxsr", HasFXSR)
.Case("gfni", HasGFNI)
- .Case("ibt", HasIBT)
+ .Case("invpcid", HasINVPCID)
.Case("lwp", HasLWP)
.Case("lzcnt", HasLZCNT)
.Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
.Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
.Case("mmx", MMX3DNowLevel >= MMX)
.Case("movbe", HasMOVBE)
+ .Case("movdiri", HasMOVDIRI)
+ .Case("movdir64b", HasMOVDIR64B)
.Case("mpx", HasMPX)
.Case("mwaitx", HasMWAITX)
.Case("pclmul", HasPCLMUL)
+ .Case("pconfig", HasPCONFIG)
.Case("pku", HasPKU)
.Case("popcnt", HasPOPCNT)
.Case("prefetchwt1", HasPREFETCHWT1)
.Case("prfchw", HasPRFCHW)
+ .Case("ptwrite", HasPTWRITE)
+ .Case("rdpid", HasRDPID)
.Case("rdrnd", HasRDRND)
.Case("rdseed", HasRDSEED)
.Case("retpoline", HasRetpoline)
@@ -1337,6 +1414,8 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("tbm", HasTBM)
.Case("vaes", HasVAES)
.Case("vpclmulqdq", HasVPCLMULQDQ)
+ .Case("wbnoinvd", HasWBNOINVD)
+ .Case("waitpkg", HasWAITPKG)
.Case("x86", true)
.Case("x86_32", getTriple().getArch() == llvm::Triple::x86)
.Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64)
@@ -1360,6 +1439,95 @@ bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
.Default(false);
}
+static llvm::X86::ProcessorFeatures getFeature(StringRef Name) {
+ return llvm::StringSwitch<llvm::X86::ProcessorFeatures>(Name)
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, llvm::X86::ENUM)
+#include "llvm/Support/X86TargetParser.def"
+ ;
+ // Note, this function should only be used after ensuring the value is
+ // correct, so it asserts if the value is out of range.
+}
+
+static unsigned getFeaturePriority(llvm::X86::ProcessorFeatures Feat) {
+ enum class FeatPriority {
+#define FEATURE(FEAT) FEAT,
+#include "clang/Basic/X86Target.def"
+ };
+ switch (Feat) {
+#define FEATURE(FEAT) \
+ case llvm::X86::FEAT: \
+ return static_cast<unsigned>(FeatPriority::FEAT);
+#include "clang/Basic/X86Target.def"
+ default:
+ llvm_unreachable("No Feature Priority for non-CPUSupports Features");
+ }
+}
+
+unsigned X86TargetInfo::multiVersionSortPriority(StringRef Name) const {
+ // Valid CPUs have a 'key feature' that compares just better than its key
+ // feature.
+ CPUKind Kind = getCPUKind(Name);
+ if (Kind != CK_Generic) {
+ switch (Kind) {
+ default:
+ llvm_unreachable(
+ "CPU Type without a key feature used in 'target' attribute");
+#define PROC_WITH_FEAT(ENUM, STR, IS64, KEY_FEAT) \
+ case CK_##ENUM: \
+ return (getFeaturePriority(llvm::X86::KEY_FEAT) << 1) + 1;
+#include "clang/Basic/X86Target.def"
+ }
+ }
+
+ // Now we know we have a feature, so get its priority and shift it a few so
+ // that we have sufficient room for the CPUs (above).
+ return getFeaturePriority(getFeature(Name)) << 1;
+}
+
+bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, true)
+#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, true)
+#include "clang/Basic/X86Target.def"
+ .Default(false);
+}
+
+static StringRef CPUSpecificCPUDispatchNameDealias(StringRef Name) {
+ return llvm::StringSwitch<StringRef>(Name)
+#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, NAME)
+#include "clang/Basic/X86Target.def"
+ .Default(Name);
+}
+
+char X86TargetInfo::CPUSpecificManglingCharacter(StringRef Name) const {
+ return llvm::StringSwitch<char>(CPUSpecificCPUDispatchNameDealias(Name))
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, MANGLING)
+#include "clang/Basic/X86Target.def"
+ .Default(0);
+}
+
+void X86TargetInfo::getCPUSpecificCPUDispatchFeatures(
+ StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const {
+ StringRef WholeList =
+ llvm::StringSwitch<StringRef>(CPUSpecificCPUDispatchNameDealias(Name))
+#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, FEATURES)
+#include "clang/Basic/X86Target.def"
+ .Default("");
+ WholeList.split(Features, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+}
+
+std::string X86TargetInfo::getCPUKindCanonicalName(CPUKind Kind) const {
+ switch (Kind) {
+ case CK_Generic:
+ return "";
+#define PROC(ENUM, STRING, IS64BIT) \
+ case CK_##ENUM: \
+ return STRING;
+#include "clang/Basic/X86Target.def"
+ }
+ llvm_unreachable("Invalid CPUKind");
+}
+
// 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
@@ -1445,7 +1613,7 @@ bool X86TargetInfo::validateAsmConstraint(
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
+ case 'k': // Any AVX512 mask register (same as Yk, additionally 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.
@@ -1573,8 +1741,6 @@ std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
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!
@@ -1587,6 +1753,18 @@ bool X86TargetInfo::checkCPUKind(CPUKind Kind) const {
llvm_unreachable("Unhandled CPU kind");
}
+void X86TargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+#define PROC(ENUM, STRING, IS64BIT) \
+ if (IS64BIT || getTriple().getArch() == llvm::Triple::x86) \
+ Values.emplace_back(STRING);
+ // Go through CPUKind checking to ensure that the alias is de-aliased and
+ // 64 bit-ness is checked.
+#define PROC_ALIAS(ENUM, ALIAS) \
+ if (checkCPUKind(getCPUKind(ALIAS))) \
+ Values.emplace_back(ALIAS);
+#include "clang/Basic/X86Target.def"
+}
+
X86TargetInfo::CPUKind X86TargetInfo::getCPUKind(StringRef CPU) const {
return llvm::StringSwitch<CPUKind>(CPU)
#define PROC(ENUM, STRING, IS64BIT) .Case(STRING, CK_##ENUM)
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
index fa2fbee387b6..1d23b0ef6933 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
@@ -81,7 +81,6 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasSHA = false;
bool HasMPX = false;
bool HasSHSTK = false;
- bool HasIBT = false;
bool HasSGX = false;
bool HasCX16 = false;
bool HasFXSR = false;
@@ -91,16 +90,26 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasXSAVES = false;
bool HasMWAITX = false;
bool HasCLZERO = false;
+ bool HasCLDEMOTE = false;
+ bool HasPCONFIG = false;
bool HasPKU = false;
bool HasCLFLUSHOPT = false;
bool HasCLWB = false;
bool HasMOVBE = false;
bool HasPREFETCHWT1 = false;
+ bool HasRDPID = false;
bool HasRetpoline = false;
bool HasRetpolineExternalThunk = false;
bool HasLAHFSAHF = false;
-
- /// \brief Enumeration of all of the X86 CPUs supported by Clang.
+ bool HasWBNOINVD = false;
+ bool HasWAITPKG = false;
+ bool HasMOVDIRI = false;
+ bool HasMOVDIR64B = false;
+ bool HasPTWRITE = false;
+ bool HasINVPCID = false;
+
+protected:
+ /// 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.
@@ -114,6 +123,8 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
CPUKind getCPUKind(StringRef CPU) const;
+ std::string getCPUKindCanonicalName(CPUKind Kind) const;
+
enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
public:
@@ -121,7 +132,7 @@ public:
: TargetInfo(Triple) {
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
}
-
+
unsigned getFloatEvalMethod() const override {
// X87 evaluates with 80 bits "long double" precision.
return SSELevel == NoSSE ? 2 : 0;
@@ -139,6 +150,14 @@ public:
bool validateCpuIs(StringRef Name) const override;
+ bool validateCPUSpecificCPUDispatch(StringRef Name) const override;
+
+ char CPUSpecificManglingCharacter(StringRef Name) const override;
+
+ void getCPUSpecificCPUDispatchFeatures(
+ StringRef Name,
+ llvm::SmallVectorImpl<StringRef> &Features) const override;
+
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
@@ -159,6 +178,17 @@ public:
bool validateInputSize(StringRef Constraint, unsigned Size) const override;
+ virtual bool
+ checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
+ return true;
+ };
+
+ virtual bool
+ checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override {
+ return true;
+ };
+
+
virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
std::string convertConstraint(const char *&Constraint) const override;
@@ -166,8 +196,8 @@ public:
return "~{dirflag},~{fpsr},~{flags}";
}
- StringRef getConstraintRegister(const StringRef &Constraint,
- const StringRef &Expression) const override {
+ StringRef getConstraintRegister(StringRef Constraint,
+ StringRef Expression) const override {
StringRef::iterator I, E;
for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
if (isalpha(*I))
@@ -208,7 +238,7 @@ public:
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
-
+
static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level,
bool Enabled);
@@ -255,10 +285,17 @@ public:
return checkCPUKind(getCPUKind(Name));
}
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+
bool setCPU(const std::string &Name) override {
return checkCPUKind(CPU = getCPUKind(Name));
}
+ bool supportsMultiVersioning() const override {
+ return getTriple().isOSBinFormatELF();
+ }
+ unsigned multiVersionSortPriority(StringRef Name) const override;
+
bool setFPMath(StringRef Name) override;
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
@@ -270,6 +307,7 @@ public:
case CC_X86VectorCall:
case CC_X86RegCall:
case CC_C:
+ case CC_PreserveMost:
case CC_Swift:
case CC_X86Pascal:
case CC_IntelOclBicc:
@@ -537,7 +575,7 @@ public:
IntPtrType = SignedLong;
PtrDiffType = SignedLong;
}
-
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
X86_32TargetInfo::getTargetDefines(Opts, Builder);
@@ -624,7 +662,7 @@ public:
bool hasInt128Type() const override { return true; }
unsigned getUnwindWordWidth() const override { return 64; }
-
+
unsigned getRegisterWidth() const override { return 64; }
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
@@ -709,6 +747,11 @@ public:
Builder.defineMacro("_M_X64", "100");
Builder.defineMacro("_M_AMD64", "100");
}
+
+ TargetInfo::CallingConvKind
+ getCallingConvKind(bool ClangABICompat4) const override {
+ return CCK_MicrosoftWin64;
+ }
};
// x86-64 MinGW target
diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
index ea3754e02af5..badf5d9dec52 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_601/final/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_70/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/VersionTuple.cpp b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp
deleted file mode 100644
index 9c73fd98a174..000000000000
--- a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the VersionTuple class, which represents a version in
-// the form major[.minor[.subminor]].
-//
-//===----------------------------------------------------------------------===//
-#include "clang/Basic/VersionTuple.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace clang;
-
-std::string VersionTuple::getAsString() const {
- std::string Result;
- {
- llvm::raw_string_ostream Out(Result);
- Out << *this;
- }
- return Result;
-}
-
-raw_ostream& clang::operator<<(raw_ostream &Out,
- const VersionTuple &V) {
- Out << V.getMajor();
- if (Optional<unsigned> Minor = V.getMinor())
- Out << (V.usesUnderscores() ? '_' : '.') << *Minor;
- if (Optional<unsigned> Subminor = V.getSubminor())
- Out << (V.usesUnderscores() ? '_' : '.') << *Subminor;
- if (Optional<unsigned> Build = V.getBuild())
- Out << (V.usesUnderscores() ? '_' : '.') << *Build;
- return Out;
-}
-
-static bool parseInt(StringRef &input, unsigned &value) {
- assert(value == 0);
- if (input.empty()) return true;
-
- char next = input[0];
- input = input.substr(1);
- if (next < '0' || next > '9') return true;
- value = (unsigned) (next - '0');
-
- while (!input.empty()) {
- next = input[0];
- if (next < '0' || next > '9') return false;
- input = input.substr(1);
- value = value * 10 + (unsigned) (next - '0');
- }
-
- return false;
-}
-
-bool VersionTuple::tryParse(StringRef input) {
- unsigned major = 0, minor = 0, micro = 0, build = 0;
-
- // Parse the major version, [0-9]+
- if (parseInt(input, major)) return true;
-
- if (input.empty()) {
- *this = VersionTuple(major);
- return false;
- }
-
- // If we're not done, parse the minor version, \.[0-9]+
- if (input[0] != '.') return true;
- input = input.substr(1);
- if (parseInt(input, minor)) return true;
-
- if (input.empty()) {
- *this = VersionTuple(major, minor);
- return false;
- }
-
- // If we're not done, parse the micro version, \.[0-9]+
- if (input[0] != '.') return true;
- input = input.substr(1);
- if (parseInt(input, micro)) return true;
-
- if (input.empty()) {
- *this = VersionTuple(major, minor, micro);
- return false;
- }
-
- // If we're not done, parse the micro version, \.[0-9]+
- if (input[0] != '.') return true;
- input = input.substr(1);
- if (parseInt(input, build)) return true;
-
- // If we have characters left over, it's an error.
- if (!input.empty()) return true;
-
- *this = VersionTuple(major, minor, micro, build);
- return false;
-}
diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
index 9d44597dc3fb..bcfcbdbb9014 100644
--- a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
@@ -1,4 +1,4 @@
-//===- VirtualFileSystem.cpp - Virtual File System Layer --------*- C++ -*-===//
+//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,30 +6,57 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
// This file implements the VirtualFileSystem interface.
+//
//===----------------------------------------------------------------------===//
#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Chrono.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <atomic>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+#include <map>
#include <memory>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
using namespace clang;
-using namespace clang::vfs;
+using namespace vfs;
using namespace llvm;
+
using llvm::sys::fs::file_status;
using llvm::sys::fs::file_type;
using llvm::sys::fs::perms;
@@ -38,13 +65,13 @@ using llvm::sys::fs::UniqueID;
Status::Status(const file_status &Status)
: UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
- Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {}
+ Type(Status.type()), Perms(Status.permissions()) {}
Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,
uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
perms Perms)
: Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
- Type(Type), Perms(Perms), IsVFSMapped(false) {}
+ Type(Type), Perms(Perms) {}
Status Status::copyWithNewName(const Status &In, StringRef NewName) {
return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
@@ -62,28 +89,34 @@ bool Status::equivalent(const Status &Other) const {
assert(isStatusKnown() && Other.isStatusKnown());
return getUniqueID() == Other.getUniqueID();
}
+
bool Status::isDirectory() const {
return Type == file_type::directory_file;
}
+
bool Status::isRegularFile() const {
return Type == file_type::regular_file;
}
+
bool Status::isOther() const {
return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
}
+
bool Status::isSymlink() const {
return Type == file_type::symlink_file;
}
+
bool Status::isStatusKnown() const {
return Type != file_type::status_error;
}
+
bool Status::exists() const {
return isStatusKnown() && Type != file_type::file_not_found;
}
-File::~File() {}
+File::~File() = default;
-FileSystem::~FileSystem() {}
+FileSystem::~FileSystem() = default;
ErrorOr<std::unique_ptr<MemoryBuffer>>
FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
@@ -97,7 +130,7 @@ FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
if (llvm::sys::path::is_absolute(Path))
- return std::error_code();
+ return {};
auto WorkingDir = getCurrentWorkingDirectory();
if (!WorkingDir)
@@ -106,6 +139,11 @@ std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
return llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
}
+std::error_code FileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ return errc::operation_not_permitted;
+}
+
bool FileSystem::exists(const Twine &Path) {
auto Status = status(Path);
return Status && Status->exists();
@@ -118,6 +156,7 @@ static bool isTraversalComponent(StringRef Component) {
static bool pathHasTraversal(StringRef Path) {
using namespace llvm::sys;
+
for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
if (isTraversalComponent(Comp))
return true;
@@ -130,12 +169,15 @@ static bool pathHasTraversal(StringRef Path) {
//===-----------------------------------------------------------------------===/
namespace {
-/// \brief Wrapper around a raw file descriptor.
+
+/// Wrapper around a raw file descriptor.
class RealFile : public File {
+ friend class RealFileSystem;
+
int FD;
Status S;
std::string RealName;
- friend class RealFileSystem;
+
RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
: FD(FD), S(NewName, {}, {}, {}, {}, {},
llvm::sys::fs::file_type::status_error, {}),
@@ -145,6 +187,7 @@ class RealFile : public File {
public:
~RealFile() override;
+
ErrorOr<Status> status() override;
ErrorOr<std::string> getName() override;
ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
@@ -153,7 +196,9 @@ public:
bool IsVolatile) override;
std::error_code close() override;
};
-} // end anonymous namespace
+
+} // namespace
+
RealFile::~RealFile() { close(); }
ErrorOr<Status> RealFile::status() {
@@ -186,7 +231,8 @@ std::error_code RealFile::close() {
}
namespace {
-/// \brief The file system according to your operating system.
+
+/// The file system according to your operating system.
class RealFileSystem : public FileSystem {
public:
ErrorOr<Status> status(const Twine &Path) override;
@@ -195,8 +241,11 @@ public:
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override;
};
-} // end anonymous namespace
+
+} // namespace
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
sys::fs::file_status RealStatus;
@@ -209,7 +258,8 @@ ErrorOr<std::unique_ptr<File>>
RealFileSystem::openFileForRead(const Twine &Name) {
int FD;
SmallString<256> RealName;
- if (std::error_code EC = sys::fs::openFileForRead(Name, FD, &RealName))
+ if (std::error_code EC =
+ sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName))
return EC;
return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
}
@@ -232,39 +282,50 @@ std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
return llvm::sys::fs::set_current_path(Path);
}
+std::error_code
+RealFileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ return llvm::sys::fs::real_path(Path, Output);
+}
+
IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
return FS;
}
namespace {
+
class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
llvm::sys::fs::directory_iterator Iter;
+
public:
RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
- if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
+ if (Iter != llvm::sys::fs::directory_iterator()) {
llvm::sys::fs::file_status S;
- EC = llvm::sys::fs::status(Iter->path(), S, true);
+ std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
CurrentEntry = Status::copyWithNewName(S, Iter->path());
+ if (!EC)
+ EC = ErrorCode;
}
}
std::error_code increment() override {
std::error_code EC;
Iter.increment(EC);
- if (EC) {
- return EC;
- } else if (Iter == llvm::sys::fs::directory_iterator()) {
+ if (Iter == llvm::sys::fs::directory_iterator()) {
CurrentEntry = Status();
} else {
llvm::sys::fs::file_status S;
- EC = llvm::sys::fs::status(Iter->path(), S, true);
+ std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
CurrentEntry = Status::copyWithNewName(S, Iter->path());
+ if (!EC)
+ EC = ErrorCode;
}
return EC;
}
};
-}
+
+} // namespace
directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
@@ -274,6 +335,7 @@ directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
//===-----------------------------------------------------------------------===/
// OverlayFileSystem implementation
//===-----------------------------------------------------------------------===/
+
OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
FSList.push_back(std::move(BaseFS));
}
@@ -311,17 +373,28 @@ OverlayFileSystem::getCurrentWorkingDirectory() const {
// All file systems are synchronized, just take the first working directory.
return FSList.front()->getCurrentWorkingDirectory();
}
+
std::error_code
OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
for (auto &FS : FSList)
if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
return EC;
- return std::error_code();
+ return {};
+}
+
+std::error_code
+OverlayFileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ for (auto &FS : FSList)
+ if (FS->exists(Path))
+ return FS->getRealPath(Path, Output);
+ return errc::no_such_file_or_directory;
}
-clang::vfs::detail::DirIterImpl::~DirIterImpl() { }
+clang::vfs::detail::DirIterImpl::~DirIterImpl() = default;
namespace {
+
class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
OverlayFileSystem &Overlays;
std::string Path;
@@ -340,7 +413,7 @@ class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
if (CurrentDirIter != directory_iterator())
break; // found
}
- return std::error_code();
+ return {};
}
std::error_code incrementDirIter(bool IsFirstTime) {
@@ -379,7 +452,8 @@ public:
std::error_code increment() override { return incrementImpl(false); }
};
-} // end anonymous namespace
+
+} // namespace
directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
@@ -389,6 +463,7 @@ directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
namespace clang {
namespace vfs {
+
namespace detail {
enum InMemoryNodeKind { IME_File, IME_Directory };
@@ -402,13 +477,15 @@ class InMemoryNode {
public:
InMemoryNode(Status Stat, InMemoryNodeKind Kind)
: Stat(std::move(Stat)), Kind(Kind) {}
- virtual ~InMemoryNode() {}
+ virtual ~InMemoryNode() = default;
+
const Status &getStatus() const { return Stat; }
InMemoryNodeKind getKind() const { return Kind; }
virtual std::string toString(unsigned Indent) const = 0;
};
namespace {
+
class InMemoryFile : public InMemoryNode {
std::unique_ptr<llvm::MemoryBuffer> Buffer;
@@ -417,9 +494,11 @@ public:
: InMemoryNode(std::move(Stat), IME_File), Buffer(std::move(Buffer)) {}
llvm::MemoryBuffer *getBuffer() { return Buffer.get(); }
+
std::string toString(unsigned Indent) const override {
return (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
}
+
static bool classof(const InMemoryNode *N) {
return N->getKind() == IME_File;
}
@@ -433,6 +512,7 @@ public:
explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
llvm::ErrorOr<Status> status() override { return Node.getStatus(); }
+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile) override {
@@ -440,9 +520,11 @@ public:
return llvm::MemoryBuffer::getMemBuffer(
Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
}
- std::error_code close() override { return std::error_code(); }
+
+ std::error_code close() override { return {}; }
};
-} // end anonymous namespace
+
+} // namespace
class InMemoryDirectory : public InMemoryNode {
std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
@@ -450,34 +532,38 @@ class InMemoryDirectory : public InMemoryNode {
public:
InMemoryDirectory(Status Stat)
: InMemoryNode(std::move(Stat), IME_Directory) {}
+
InMemoryNode *getChild(StringRef Name) {
auto I = Entries.find(Name);
if (I != Entries.end())
return I->second.get();
return nullptr;
}
+
InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
return Entries.insert(make_pair(Name, std::move(Child)))
.first->second.get();
}
- typedef decltype(Entries)::const_iterator const_iterator;
+ using const_iterator = decltype(Entries)::const_iterator;
+
const_iterator begin() const { return Entries.begin(); }
const_iterator end() const { return Entries.end(); }
std::string toString(unsigned Indent) const override {
std::string Result =
(std::string(Indent, ' ') + getStatus().getName() + "\n").str();
- for (const auto &Entry : Entries) {
+ for (const auto &Entry : Entries)
Result += Entry.second->toString(Indent + 2);
- }
return Result;
}
+
static bool classof(const InMemoryNode *N) {
return N->getKind() == IME_Directory;
}
};
-}
+
+} // namespace detail
InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
: Root(new detail::InMemoryDirectory(
@@ -486,7 +572,7 @@ InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
llvm::sys::fs::perms::all_all))),
UseNormalizedPaths(UseNormalizedPaths) {}
-InMemoryFileSystem::~InMemoryFileSystem() {}
+InMemoryFileSystem::~InMemoryFileSystem() = default;
std::string InMemoryFileSystem::toString() const {
return Root->toString(/*Indent=*/0);
@@ -645,13 +731,15 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) {
}
namespace {
+
/// Adaptor from InMemoryDir::iterator to directory_iterator.
class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
detail::InMemoryDirectory::const_iterator I;
detail::InMemoryDirectory::const_iterator E;
public:
- InMemoryDirIterator() {}
+ InMemoryDirIterator() = default;
+
explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
: I(Dir.begin()), E(Dir.end()) {
if (I != E)
@@ -663,10 +751,11 @@ public:
// When we're at the end, make CurrentEntry invalid and DirIterImpl will do
// the rest.
CurrentEntry = I != E ? I->second->getStatus() : Status();
- return std::error_code();
+ return {};
}
};
-} // end anonymous namespace
+
+} // namespace
directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
@@ -697,11 +786,25 @@ std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
if (!Path.empty())
WorkingDirectory = Path.str();
- return std::error_code();
-}
+ return {};
}
+
+std::error_code
+InMemoryFileSystem::getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const {
+ auto CWD = getCurrentWorkingDirectory();
+ if (!CWD || CWD->empty())
+ return errc::operation_not_permitted;
+ Path.toVector(Output);
+ if (auto EC = makeAbsolute(Output))
+ return EC;
+ llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
+ return {};
}
+} // namespace vfs
+} // namespace clang
+
//===-----------------------------------------------------------------------===/
// RedirectingFileSystem implementation
//===-----------------------------------------------------------------------===/
@@ -713,14 +816,15 @@ enum EntryKind {
EK_File
};
-/// \brief A single file or directory in the VFS.
+/// A single file or directory in the VFS.
class Entry {
EntryKind Kind;
std::string Name;
public:
- virtual ~Entry();
Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
+ virtual ~Entry() = default;
+
StringRef getName() const { return Name; }
EntryKind getKind() const { return Kind; }
};
@@ -737,14 +841,20 @@ public:
S(std::move(S)) {}
RedirectingDirectoryEntry(StringRef Name, Status S)
: Entry(EK_Directory, Name), S(std::move(S)) {}
+
Status getStatus() { return S; }
+
void addContent(std::unique_ptr<Entry> Content) {
Contents.push_back(std::move(Content));
}
+
Entry *getLastContent() const { return Contents.back().get(); }
- typedef decltype(Contents)::iterator iterator;
+
+ using iterator = decltype(Contents)::iterator;
+
iterator contents_begin() { return Contents.begin(); }
iterator contents_end() { return Contents.end(); }
+
static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
};
@@ -755,21 +865,27 @@ public:
NK_External,
NK_Virtual
};
+
private:
std::string ExternalContentsPath;
NameKind UseName;
+
public:
RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
NameKind UseName)
: Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
UseName(UseName) {}
+
StringRef getExternalContentsPath() const { return ExternalContentsPath; }
- /// \brief whether to use the external path as the name for this file.
+
+ /// whether to use the external path as the name for this file.
bool useExternalName(bool GlobalUseExternalName) const {
return UseName == NK_NotSet ? GlobalUseExternalName
: (UseName == NK_External);
}
+
NameKind getUseName() const { return UseName; }
+
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
};
@@ -785,10 +901,11 @@ public:
RedirectingDirectoryEntry::iterator Begin,
RedirectingDirectoryEntry::iterator End,
std::error_code &EC);
+
std::error_code increment() override;
};
-/// \brief A virtual file system parsed from a YAML file.
+/// A virtual file system parsed from a YAML file.
///
/// Currently, this class allows creating virtual directories and mapping
/// virtual file paths to existing external files, available in \c ExternalFS.
@@ -844,10 +961,14 @@ public:
/// /path/to/file). However, any directory that contains more than one child
/// must be uniquely represented by a directory entry.
class RedirectingFileSystem : public vfs::FileSystem {
+ friend class RedirectingFileSystemParser;
+
/// The root(s) of the virtual file system.
std::vector<std::unique_ptr<Entry>> Roots;
- /// \brief The file system to use for external references.
+
+ /// The file system to use for external references.
IntrusiveRefCntPtr<FileSystem> ExternalFS;
+
/// If IsRelativeOverlay is set, this represents the directory
/// path that should be prefixed to each 'external-contents' entry
/// when reading from YAML files.
@@ -856,7 +977,7 @@ class RedirectingFileSystem : public vfs::FileSystem {
/// @name Configuration
/// @{
- /// \brief Whether to perform case-sensitive comparisons.
+ /// Whether to perform case-sensitive comparisons.
///
/// Currently, case-insensitive matching only works correctly with ASCII.
bool CaseSensitive = true;
@@ -865,11 +986,11 @@ class RedirectingFileSystem : public vfs::FileSystem {
/// be prefixed in every 'external-contents' when reading from YAML files.
bool IsRelativeOverlay = false;
- /// \brief Whether to use to use the value of 'external-contents' for the
+ /// Whether to use to use the value of 'external-contents' for the
/// names of files. This global value is overridable on a per-file basis.
bool UseExternalNames = true;
- /// \brief Whether an invalid path obtained via 'external-contents' should
+ /// Whether an invalid path obtained via 'external-contents' should
/// cause iteration on the VFS to stop. If 'true', the VFS should ignore
/// the entry and continue with the next. Allows YAML files to be shared
/// across multiple compiler invocations regardless of prior existent
@@ -882,31 +1003,29 @@ class RedirectingFileSystem : public vfs::FileSystem {
/// "." and "./" in their paths. FIXME: some unittests currently fail on
/// win32 when using remove_dots and remove_leading_dotslash on paths.
bool UseCanonicalizedPaths =
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
false;
#else
true;
#endif
- friend class RedirectingFileSystemParser;
-
private:
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
: ExternalFS(std::move(ExternalFS)) {}
- /// \brief Looks up the path <tt>[Start, End)</tt> in \p From, possibly
+ /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
/// recursing into the contents of \p From if it is a directory.
ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start,
sys::path::const_iterator End, Entry *From);
- /// \brief Get the status of a given an \c Entry.
+ /// Get the status of a given an \c Entry.
ErrorOr<Status> status(const Twine &Path, Entry *E);
public:
- /// \brief Looks up \p Path in \c Roots.
+ /// Looks up \p Path in \c Roots.
ErrorOr<Entry *> lookupPath(const Twine &Path);
- /// \brief Parses \p Buffer, which is expected to be in YAML format and
+ /// Parses \p Buffer, which is expected to be in YAML format and
/// returns a virtual file system representing its contents.
static RedirectingFileSystem *
create(std::unique_ptr<MemoryBuffer> Buffer,
@@ -919,6 +1038,7 @@ public:
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
return ExternalFS->getCurrentWorkingDirectory();
}
+
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
return ExternalFS->setCurrentWorkingDirectory(Path);
}
@@ -927,17 +1047,17 @@ public:
ErrorOr<Entry *> E = lookupPath(Dir);
if (!E) {
EC = E.getError();
- return directory_iterator();
+ return {};
}
ErrorOr<Status> S = status(Dir, *E);
if (!S) {
EC = S.getError();
- return directory_iterator();
+ return {};
}
if (!S->isDirectory()) {
EC = std::error_code(static_cast<int>(errc::not_a_directory),
std::system_category());
- return directory_iterator();
+ return {};
}
auto *D = cast<RedirectingDirectoryEntry>(*E);
@@ -959,7 +1079,7 @@ public:
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const {
- for (const std::unique_ptr<Entry> &Root : Roots)
+ for (const auto &Root : Roots)
dumpEntry(Root.get());
}
@@ -979,10 +1099,9 @@ LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const {
}
}
#endif
-
};
-/// \brief A helper class to hold the common YAML parsing state.
+/// A helper class to hold the common YAML parsing state.
class RedirectingFileSystemParser {
yaml::Stream &Stream;
@@ -993,7 +1112,8 @@ class RedirectingFileSystemParser {
// false on error
bool parseScalarString(yaml::Node *N, StringRef &Result,
SmallVectorImpl<char> &Storage) {
- yaml::ScalarNode *S = dyn_cast<yaml::ScalarNode>(N);
+ const auto *S = dyn_cast<yaml::ScalarNode>(N);
+
if (!S) {
error(N, "expected string");
return false;
@@ -1024,11 +1144,13 @@ class RedirectingFileSystemParser {
}
struct KeyStatus {
- KeyStatus(bool Required=false) : Required(Required), Seen(false) {}
bool Required;
- bool Seen;
+ bool Seen = false;
+
+ KeyStatus(bool Required = false) : Required(Required) {}
};
- typedef std::pair<StringRef, KeyStatus> KeyStatusPair;
+
+ using KeyStatusPair = std::pair<StringRef, KeyStatus>;
// false on error
bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
@@ -1048,11 +1170,9 @@ class RedirectingFileSystemParser {
// false on error
bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
- for (DenseMap<StringRef, KeyStatus>::iterator I = Keys.begin(),
- E = Keys.end();
- I != E; ++I) {
- if (I->second.Required && !I->second.Seen) {
- error(Obj, Twine("missing key '") + I->first + "'");
+ for (const auto &I : Keys) {
+ if (I.second.Required && !I.second.Seen) {
+ error(Obj, Twine("missing key '") + I.first + "'");
return false;
}
}
@@ -1062,7 +1182,7 @@ class RedirectingFileSystemParser {
Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
Entry *ParentEntry = nullptr) {
if (!ParentEntry) { // Look for a existent root
- for (const std::unique_ptr<Entry> &Root : FS->Roots) {
+ for (const auto &Root : FS->Roots) {
if (Name.equals(Root->getName())) {
ParentEntry = Root.get();
return ParentEntry;
@@ -1125,7 +1245,7 @@ class RedirectingFileSystemParser {
}
std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
- yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N);
+ auto *M = dyn_cast<yaml::MappingNode>(N);
if (!M) {
error(N, "expected mapping node for file or directory entry");
return nullptr;
@@ -1148,21 +1268,20 @@ class RedirectingFileSystemParser {
auto UseExternalName = RedirectingFileEntry::NK_NotSet;
EntryKind Kind;
- for (yaml::MappingNode::iterator I = M->begin(), E = M->end(); I != E;
- ++I) {
+ for (auto &I : *M) {
StringRef Key;
// Reuse the buffer for key and value, since we don't look at key after
// parsing value.
SmallString<256> Buffer;
- if (!parseScalarString(I->getKey(), Key, Buffer))
+ if (!parseScalarString(I.getKey(), Key, Buffer))
return nullptr;
- if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
+ if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
return nullptr;
StringRef Value;
if (Key == "name") {
- if (!parseScalarString(I->getValue(), Value, Buffer))
+ if (!parseScalarString(I.getValue(), Value, Buffer))
return nullptr;
if (FS->UseCanonicalizedPaths) {
@@ -1176,47 +1295,44 @@ class RedirectingFileSystemParser {
Name = Value;
}
} else if (Key == "type") {
- if (!parseScalarString(I->getValue(), Value, Buffer))
+ if (!parseScalarString(I.getValue(), Value, Buffer))
return nullptr;
if (Value == "file")
Kind = EK_File;
else if (Value == "directory")
Kind = EK_Directory;
else {
- error(I->getValue(), "unknown value for 'type'");
+ error(I.getValue(), "unknown value for 'type'");
return nullptr;
}
} else if (Key == "contents") {
if (HasContents) {
- error(I->getKey(),
+ error(I.getKey(),
"entry already has 'contents' or 'external-contents'");
return nullptr;
}
HasContents = true;
- yaml::SequenceNode *Contents =
- dyn_cast<yaml::SequenceNode>(I->getValue());
+ auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
if (!Contents) {
// FIXME: this is only for directories, what about files?
- error(I->getValue(), "expected array");
+ error(I.getValue(), "expected array");
return nullptr;
}
- for (yaml::SequenceNode::iterator I = Contents->begin(),
- E = Contents->end();
- I != E; ++I) {
- if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
+ for (auto &I : *Contents) {
+ if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
EntryArrayContents.push_back(std::move(E));
else
return nullptr;
}
} else if (Key == "external-contents") {
if (HasContents) {
- error(I->getKey(),
+ error(I.getKey(),
"entry already has 'contents' or 'external-contents'");
return nullptr;
}
HasContents = true;
- if (!parseScalarString(I->getValue(), Value, Buffer))
+ if (!parseScalarString(I.getValue(), Value, Buffer))
return nullptr;
SmallString<256> FullPath;
@@ -1238,7 +1354,7 @@ class RedirectingFileSystemParser {
ExternalContentsPath = FullPath.str();
} else if (Key == "use-external-name") {
bool Val;
- if (!parseScalarBool(I->getValue(), Val))
+ if (!parseScalarBool(I.getValue(), Val))
return nullptr;
UseExternalName = Val ? RedirectingFileEntry::NK_External
: RedirectingFileEntry::NK_Virtual;
@@ -1311,7 +1427,7 @@ public:
// false on error
bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
- yaml::MappingNode *Top = dyn_cast<yaml::MappingNode>(Root);
+ auto *Top = dyn_cast<yaml::MappingNode>(Root);
if (!Top) {
error(Root, "expected mapping node");
return false;
@@ -1330,26 +1446,24 @@ public:
std::vector<std::unique_ptr<Entry>> RootEntries;
// Parse configuration and 'roots'
- for (yaml::MappingNode::iterator I = Top->begin(), E = Top->end(); I != E;
- ++I) {
+ for (auto &I : *Top) {
SmallString<10> KeyBuffer;
StringRef Key;
- if (!parseScalarString(I->getKey(), Key, KeyBuffer))
+ if (!parseScalarString(I.getKey(), Key, KeyBuffer))
return false;
- if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
+ if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
return false;
if (Key == "roots") {
- yaml::SequenceNode *Roots = dyn_cast<yaml::SequenceNode>(I->getValue());
+ auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
if (!Roots) {
- error(I->getValue(), "expected array");
+ error(I.getValue(), "expected array");
return false;
}
- for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end();
- I != E; ++I) {
- if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
+ for (auto &I : *Roots) {
+ if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
RootEntries.push_back(std::move(E));
else
return false;
@@ -1357,32 +1471,32 @@ public:
} else if (Key == "version") {
StringRef VersionString;
SmallString<4> Storage;
- if (!parseScalarString(I->getValue(), VersionString, Storage))
+ if (!parseScalarString(I.getValue(), VersionString, Storage))
return false;
int Version;
if (VersionString.getAsInteger<int>(10, Version)) {
- error(I->getValue(), "expected integer");
+ error(I.getValue(), "expected integer");
return false;
}
if (Version < 0) {
- error(I->getValue(), "invalid version number");
+ error(I.getValue(), "invalid version number");
return false;
}
if (Version != 0) {
- error(I->getValue(), "version mismatch, expected 0");
+ error(I.getValue(), "version mismatch, expected 0");
return false;
}
} else if (Key == "case-sensitive") {
- if (!parseScalarBool(I->getValue(), FS->CaseSensitive))
+ if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
return false;
} else if (Key == "overlay-relative") {
- if (!parseScalarBool(I->getValue(), FS->IsRelativeOverlay))
+ if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
return false;
} else if (Key == "use-external-names") {
- if (!parseScalarBool(I->getValue(), FS->UseExternalNames))
+ if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
return false;
} else if (Key == "ignore-non-existent-contents") {
- if (!parseScalarBool(I->getValue(), FS->IgnoreNonExistentContents))
+ if (!parseScalarBool(I.getValue(), FS->IgnoreNonExistentContents))
return false;
} else {
llvm_unreachable("key missing from Keys");
@@ -1398,22 +1512,20 @@ public:
// Now that we sucessefully parsed the YAML file, canonicalize the internal
// representation to a proper directory tree so that we can search faster
// inside the VFS.
- for (std::unique_ptr<Entry> &E : RootEntries)
+ for (auto &E : RootEntries)
uniqueOverlayTree(FS, E.get());
return true;
}
};
-} // end of anonymous namespace
-Entry::~Entry() = default;
+} // namespace
RedirectingFileSystem *
RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
SourceMgr::DiagHandlerTy DiagHandler,
StringRef YAMLFilePath, void *DiagContext,
IntrusiveRefCntPtr<FileSystem> ExternalFS) {
-
SourceMgr SM;
yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
@@ -1473,7 +1585,7 @@ ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
sys::path::const_iterator Start = sys::path::begin(Path);
sys::path::const_iterator End = sys::path::end(Path);
- for (const std::unique_ptr<Entry> &Root : Roots) {
+ for (const auto &Root : Roots) {
ErrorOr<Entry *> Result = lookupPath(Start, End, Root.get());
if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
@@ -1484,7 +1596,7 @@ ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
ErrorOr<Entry *>
RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
sys::path::const_iterator End, Entry *From) {
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
assert(!isTraversalComponent(*Start) &&
!isTraversalComponent(From->getName()) &&
"Paths should not contain traversal components");
@@ -1557,6 +1669,7 @@ ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
}
namespace {
+
/// Provide a file wrapper with an overriden status.
class FileWithFixedStatus : public File {
std::unique_ptr<File> InnerFile;
@@ -1568,14 +1681,17 @@ public:
ErrorOr<Status> status() override { return S; }
ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile) override {
return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
IsVolatile);
}
+
std::error_code close() override { return InnerFile->close(); }
};
-} // end anonymous namespace
+
+} // namespace
ErrorOr<std::unique_ptr<File>>
RedirectingFileSystem::openFileForRead(const Twine &Path) {
@@ -1670,11 +1786,13 @@ void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
}
namespace {
+
class JSONWriter {
llvm::raw_ostream &OS;
SmallVector<StringRef, 16> DirStack;
- inline unsigned getDirIndent() { return 4 * DirStack.size(); }
- inline unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
+
+ unsigned getDirIndent() { return 4 * DirStack.size(); }
+ unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
bool containedIn(StringRef Parent, StringRef Path);
StringRef containedPart(StringRef Parent, StringRef Path);
void startDirectory(StringRef Path);
@@ -1683,14 +1801,17 @@ class JSONWriter {
public:
JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
+
void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);
};
-}
+
+} // namespace
bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
using namespace llvm::sys;
+
// Compare each path component.
auto IParent = path::begin(Parent), EParent = path::end(Parent);
for (auto IChild = path::begin(Path), EChild = path::end(Path);
@@ -1812,8 +1933,8 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
}
void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
- std::sort(Mappings.begin(), Mappings.end(),
- [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
+ llvm::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
return LHS.VPath < RHS.VPath;
});
@@ -1868,7 +1989,7 @@ std::error_code VFSFromYamlDirIterImpl::increment() {
if (Current == End)
CurrentEntry = Status();
- return std::error_code();
+ return {};
}
vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
diff --git a/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp b/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp
index 6306ceabc638..a999c45a0c3e 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp
@@ -51,7 +51,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Diags.setElideType(Opts.ElideType);
Diags.setPrintTemplateTree(Opts.ShowTemplateTree);
Diags.setShowColors(Opts.ShowColors);
-
+
// Handle -ferror-limit
if (Opts.ErrorLimit)
Diags.setErrorLimit(Opts.ErrorLimit);
@@ -75,7 +75,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Diags.getDiagnosticIDs();
// We parse the warning options twice. The first pass sets diagnostic state,
// while the second pass reports warnings/errors. This has the effect that
- // we follow the more canonical "last option wins" paradigm when there are
+ // we follow the more canonical "last option wins" paradigm when there are
// conflicting options.
for (unsigned Report = 0, ReportEnd = 2; Report != ReportEnd; ++Report) {
bool SetDiagnostic = (Report == 0);
@@ -114,7 +114,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Diags.setSuppressSystemWarnings(!isPositive);
continue;
}
-
+
// -Weverything is a special case as well. It implicitly enables all
// warnings, including ones not explicitly in a warning group.
if (Opt == "everything") {
@@ -128,8 +128,8 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
}
continue;
}
-
- // -Werror/-Wno-error is a special case, not controlled by the option
+
+ // -Werror/-Wno-error is a special case, not controlled by the option
// table. It also has the "specifier" form of -Werror=foo and -Werror-foo.
if (Opt.startswith("error")) {
StringRef Specifier;
@@ -142,13 +142,13 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
}
Specifier = Opt.substr(6);
}
-
+
if (Specifier.empty()) {
if (SetDiagnostic)
Diags.setWarningsAsErrors(isPositive);
continue;
}
-
+
if (SetDiagnostic) {
// Set the warning as error flag for this specifier.
Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive);
@@ -157,7 +157,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
}
continue;
}
-
+
// -Wfatal-errors is yet another special case.
if (Opt.startswith("fatal-errors")) {
StringRef Specifier;
@@ -176,7 +176,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Diags.setErrorsAsFatal(isPositive);
continue;
}
-
+
if (SetDiagnostic) {
// Set the error as fatal flag for this specifier.
Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive);
@@ -185,7 +185,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
}
continue;
}
-
+
if (Report) {
if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags))
EmitUnknownDiagWarning(Diags, Flavor, isPositive ? "-W" : "-Wno-",
diff --git a/contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp b/contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp
new file mode 100644
index 000000000000..8cc36df79468
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/XRayInstr.cpp
@@ -0,0 +1,30 @@
+//===--- XRayInstr.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is part of XRay, a function call instrumentation system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace clang {
+
+XRayInstrMask parseXRayInstrValue(StringRef Value) {
+ XRayInstrMask ParsedKind = llvm::StringSwitch<XRayInstrMask>(Value)
+ .Case("all", XRayInstrKind::All)
+ .Case("custom", XRayInstrKind::Custom)
+ .Case("function", XRayInstrKind::Function)
+ .Case("typed", XRayInstrKind::Typed)
+ .Case("none", XRayInstrKind::None)
+ .Default(XRayInstrKind::None);
+ return ParsedKind;
+}
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp b/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
index 462777d53400..ad331899d2e2 100644
--- a/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
@@ -16,24 +16,32 @@ using namespace clang;
XRayFunctionFilter::XRayFunctionFilter(
ArrayRef<std::string> AlwaysInstrumentPaths,
- ArrayRef<std::string> NeverInstrumentPaths, SourceManager &SM)
+ ArrayRef<std::string> NeverInstrumentPaths,
+ ArrayRef<std::string> AttrListPaths, SourceManager &SM)
: AlwaysInstrument(
llvm::SpecialCaseList::createOrDie(AlwaysInstrumentPaths)),
NeverInstrument(llvm::SpecialCaseList::createOrDie(NeverInstrumentPaths)),
- SM(SM) {}
+ AttrList(llvm::SpecialCaseList::createOrDie(AttrListPaths)), SM(SM) {}
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.
+ // TODO: Remove these as they're deprecated; use the AttrList exclusively.
if (AlwaysInstrument->inSection("xray_always_instrument", "fun", FunctionName,
- "arg1"))
+ "arg1") ||
+ AttrList->inSection("always", "fun", FunctionName, "arg1"))
return ImbueAttribute::ALWAYS_ARG1;
if (AlwaysInstrument->inSection("xray_always_instrument", "fun",
- FunctionName))
+ FunctionName) ||
+ AttrList->inSection("always", "fun", FunctionName))
return ImbueAttribute::ALWAYS;
- if (NeverInstrument->inSection("xray_never_instrument", "fun", FunctionName))
+
+ if (NeverInstrument->inSection("xray_never_instrument", "fun",
+ FunctionName) ||
+ AttrList->inSection("never", "fun", FunctionName))
return ImbueAttribute::NEVER;
+
return ImbueAttribute::NONE;
}
@@ -41,10 +49,12 @@ XRayFunctionFilter::ImbueAttribute
XRayFunctionFilter::shouldImbueFunctionsInFile(StringRef Filename,
StringRef Category) const {
if (AlwaysInstrument->inSection("xray_always_instrument", "src", Filename,
- Category))
+ Category) ||
+ AttrList->inSection("always", "src", Filename, Category))
return ImbueAttribute::ALWAYS;
if (NeverInstrument->inSection("xray_never_instrument", "src", Filename,
- Category))
+ Category) ||
+ AttrList->inSection("never", "src", Filename, Category))
return ImbueAttribute::NEVER;
return ImbueAttribute::NONE;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
index 575506da84d4..feed3833f24a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
@@ -53,12 +53,9 @@ namespace swiftcall {
CodeGen::CodeGenTypes &CGT;
protected:
llvm::CallingConv::ID RuntimeCC;
- llvm::CallingConv::ID BuiltinCC;
public:
ABIInfo(CodeGen::CodeGenTypes &cgt)
- : CGT(cgt),
- RuntimeCC(llvm::CallingConv::C),
- BuiltinCC(llvm::CallingConv::C) {}
+ : CGT(cgt), RuntimeCC(llvm::CallingConv::C) {}
virtual ~ABIInfo();
@@ -77,11 +74,6 @@ namespace swiftcall {
return RuntimeCC;
}
- /// Return the calling convention to use for compiler builtins
- llvm::CallingConv::ID getBuiltinCC() const {
- return BuiltinCC;
- }
-
virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
/// EmitVAArg - Emit the target dependent code to load a value of
@@ -108,8 +100,6 @@ namespace swiftcall {
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base,
uint64_t Members) const;
- virtual bool shouldSignExtUnsignedType(QualType Ty) const;
-
bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t &Members) const;
@@ -137,8 +127,7 @@ namespace swiftcall {
bool supportsSwift() const final override { return true; }
- virtual bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type*> types,
+ virtual bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> types,
bool asReturnValue) const = 0;
virtual bool isLegalVectorTypeForSwift(CharUnits totalSize,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
index e2349da5f0a4..415bd9626220 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
@@ -26,6 +26,7 @@
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -44,17 +45,19 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.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/InstCombine/InstCombine.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
+#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
+#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include <memory>
@@ -101,7 +104,18 @@ class EmitAssemblyHelper {
///
/// \return True on success.
bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action,
- raw_pwrite_stream &OS);
+ raw_pwrite_stream &OS, raw_pwrite_stream *DwoOS);
+
+ std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) {
+ std::error_code EC;
+ auto F = llvm::make_unique<llvm::ToolOutputFile>(Path, EC,
+ llvm::sys::fs::F_None);
+ if (EC) {
+ Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
+ F.reset();
+ }
+ return F;
+ }
public:
EmitAssemblyHelper(DiagnosticsEngine &_Diags,
@@ -231,10 +245,9 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
PM.add(createAddressSanitizerFunctionPass(
- /*CompileKernel*/ true,
- /*Recover*/ true, /*UseAfterScope*/ false));
- PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true,
- /*Recover*/true));
+ /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false));
+ PM.add(createAddressSanitizerModulePass(
+ /*CompileKernel*/ true, /*Recover*/ true));
}
static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
@@ -243,7 +256,13 @@ static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
static_cast<const PassManagerBuilderWrapper &>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
- PM.add(createHWAddressSanitizerPass(Recover));
+ PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ false, Recover));
+}
+
+static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createHWAddressSanitizerPass(
+ /*CompileKernel*/ true, /*Recover*/ true));
}
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
@@ -361,21 +380,6 @@ getCodeModel(const CodeGenOptions &CodeGenOpts) {
return static_cast<llvm::CodeModel::Model>(CodeModel);
}
-static llvm::Reloc::Model getRelocModel(const CodeGenOptions &CodeGenOpts) {
- // Keep this synced with the equivalent code in
- // lib/Frontend/CompilerInvocation.cpp
- llvm::Optional<llvm::Reloc::Model> RM;
- RM = llvm::StringSwitch<llvm::Reloc::Model>(CodeGenOpts.RelocationModel)
- .Case("static", llvm::Reloc::Static)
- .Case("pic", llvm::Reloc::PIC_)
- .Case("ropi", llvm::Reloc::ROPI)
- .Case("rwpi", llvm::Reloc::RWPI)
- .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
- .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC);
- assert(RM.hasValue() && "invalid PIC model!");
- return *RM;
-}
-
static TargetMachine::CodeGenFileType getCodeGenFileType(BackendAction Action) {
if (Action == Backend_EmitObj)
return TargetMachine::CGFT_ObjectFile;
@@ -447,7 +451,10 @@ static void initTargetOptions(llvm::TargetOptions &Options,
Options.DataSections = CodeGenOpts.DataSections;
Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
+ Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
+ Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
+ Options.EmitAddrsig = CodeGenOpts.Addrsig;
if (CodeGenOpts.EnableSplitDwarf)
Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
@@ -470,6 +477,23 @@ static void initTargetOptions(llvm::TargetOptions &Options,
Options.MCOptions.IASSearchPaths.push_back(
Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path);
}
+static Optional<GCOVOptions> getGCOVOptions(const CodeGenOptions &CodeGenOpts) {
+ if (CodeGenOpts.DisableGCov)
+ return None;
+ if (!CodeGenOpts.EmitGcovArcs && !CodeGenOpts.EmitGcovNotes)
+ return None;
+ // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if
+ // LLVM's -default-gcov-version flag is set to something invalid.
+ GCOVOptions Options;
+ Options.EmitNotes = CodeGenOpts.EmitGcovNotes;
+ Options.EmitData = CodeGenOpts.EmitGcovArcs;
+ llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version));
+ Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum;
+ Options.NoRedZone = CodeGenOpts.DisableRedZone;
+ Options.FunctionNamesInData = !CodeGenOpts.CoverageNoFunctionNamesInData;
+ Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody;
+ return Options;
+}
void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
legacy::FunctionPassManager &FPM) {
@@ -501,7 +525,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
PMBuilder.Inliner = createFunctionInliningPass(
CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize,
(!CodeGenOpts.SampleProfileFile.empty() &&
- CodeGenOpts.EmitSummaryIndex));
+ CodeGenOpts.PrepareForThinLTO));
}
PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel;
@@ -511,7 +535,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions;
- PMBuilder.PrepareForThinLTO = CodeGenOpts.EmitSummaryIndex;
+ PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO;
PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO;
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
@@ -535,6 +559,9 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
addObjCARCOptPass);
}
+ if (LangOpts.CoroutinesTS)
+ addCoroutinePassesToExtensionPoints(PMBuilder);
+
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) {
PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
addBoundsCheckingPass);
@@ -572,6 +599,13 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
addHWAddressSanitizerPasses);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addKernelHWAddressSanitizerPasses);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addKernelHWAddressSanitizerPasses);
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addMemorySanitizerPass);
@@ -593,9 +627,6 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
addDataFlowSanitizerPass);
}
- if (LangOpts.CoroutinesTS)
- addCoroutinePassesToExtensionPoints(PMBuilder);
-
if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addEfficiencySanitizerPass);
@@ -612,20 +643,8 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
if (!CodeGenOpts.RewriteMapFiles.empty())
addSymbolRewriterPass(CodeGenOpts, &MPM);
- if (!CodeGenOpts.DisableGCov &&
- (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)) {
- // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if
- // LLVM's -default-gcov-version flag is set to something invalid.
- GCOVOptions Options;
- Options.EmitNotes = CodeGenOpts.EmitGcovNotes;
- Options.EmitData = CodeGenOpts.EmitGcovArcs;
- memcpy(Options.Version, CodeGenOpts.CoverageVersion, 4);
- Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum;
- Options.NoRedZone = CodeGenOpts.DisableRedZone;
- Options.FunctionNamesInData =
- !CodeGenOpts.CoverageNoFunctionNamesInData;
- Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody;
- MPM.add(createGCOVProfilerPass(Options));
+ if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) {
+ MPM.add(createGCOVProfilerPass(*Options));
if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo)
MPM.add(createStripSymbolsPass(true));
}
@@ -664,8 +683,6 @@ static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {
BackendArgs.push_back("-limit-float-precision");
BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
}
- for (const std::string &BackendOption : CodeGenOpts.BackendOptions)
- BackendArgs.push_back(BackendOption.c_str());
BackendArgs.push_back(nullptr);
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
BackendArgs.data());
@@ -685,7 +702,7 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
Optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts);
std::string FeaturesStr =
llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ",");
- llvm::Reloc::Model RM = getRelocModel(CodeGenOpts);
+ llvm::Reloc::Model RM = CodeGenOpts.RelocationModel;
CodeGenOpt::Level OptLevel = getCGOptLevel(CodeGenOpts);
llvm::TargetOptions Options;
@@ -696,7 +713,8 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
BackendAction Action,
- raw_pwrite_stream &OS) {
+ raw_pwrite_stream &OS,
+ raw_pwrite_stream *DwoOS) {
// Add LibraryInfo.
llvm::Triple TargetTriple(TheModule->getTargetTriple());
std::unique_ptr<TargetLibraryInfoImpl> TLII(
@@ -713,7 +731,7 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
if (CodeGenOpts.OptimizationLevel > 0)
CodeGenPasses.add(createObjCARCContractPass());
- if (TM->addPassesToEmitFile(CodeGenPasses, OS, CGFT,
+ if (TM->addPassesToEmitFile(CodeGenPasses, OS, DwoOS, CGFT,
/*DisableVerify=*/!CodeGenOpts.VerifyModule)) {
Diags.Report(diag::err_fe_unable_to_interface_with_target);
return false;
@@ -724,7 +742,7 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS) {
- TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
+ TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr);
setCommandLineOpts(CodeGenOpts);
@@ -752,31 +770,35 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
CodeGenPasses.add(
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
- std::unique_ptr<raw_fd_ostream> ThinLinkOS;
+ std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
switch (Action) {
case Backend_EmitNothing:
break;
case Backend_EmitBC:
- if (CodeGenOpts.EmitSummaryIndex) {
+ if (CodeGenOpts.PrepareForThinLTO) {
if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
- std::error_code EC;
- ThinLinkOS.reset(new llvm::raw_fd_ostream(
- CodeGenOpts.ThinLinkBitcodeFile, EC,
- llvm::sys::fs::F_None));
- if (EC) {
- Diags.Report(diag::err_fe_unable_to_open_output) << CodeGenOpts.ThinLinkBitcodeFile
- << EC.message();
+ ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
+ if (!ThinLinkOS)
return;
- }
}
+ PerModulePasses.add(createWriteThinLTOBitcodePass(
+ *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
+ } else {
+ // Emit a module summary by default for Regular LTO except for ld64
+ // targets
+ bool EmitLTOSummary =
+ (CodeGenOpts.PrepareForLTO &&
+ llvm::Triple(TheModule->getTargetTriple()).getVendor() !=
+ llvm::Triple::Apple);
+ if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO"))
+ TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
+
PerModulePasses.add(
- createWriteThinLTOBitcodePass(*OS, ThinLinkOS.get()));
+ createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
+ EmitLTOSummary));
}
- else
- PerModulePasses.add(
- createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists));
break;
case Backend_EmitLL:
@@ -785,7 +807,13 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
break;
default:
- if (!AddEmitPasses(CodeGenPasses, Action, *OS))
+ if (!CodeGenOpts.SplitDwarfFile.empty()) {
+ DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile);
+ if (!DwoOS)
+ return;
+ }
+ if (!AddEmitPasses(CodeGenPasses, Action, *OS,
+ DwoOS ? &DwoOS->os() : nullptr))
return;
}
@@ -814,6 +842,11 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
PrettyStackTraceString CrashInfo("Code generation");
CodeGenPasses.run(*TheModule);
}
+
+ if (ThinLinkOS)
+ ThinLinkOS->keep();
+ if (DwoOS)
+ DwoOS->keep();
}
static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
@@ -827,7 +860,7 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
case 2:
switch (Opts.OptimizeSize) {
default:
- llvm_unreachable("Invalide optimization level for size!");
+ llvm_unreachable("Invalid optimization level for size!");
case 0:
return PassBuilder::O2;
@@ -854,7 +887,7 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
/// `EmitAssembly` at some point in the future when the default switches.
void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) {
- TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
+ TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr);
setCommandLineOpts(CodeGenOpts);
// The new pass manager always makes a target machine available to passes
@@ -913,10 +946,13 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
ModulePassManager MPM(CodeGenOpts.DebugPassManager);
if (!CodeGenOpts.DisableLLVMPasses) {
- bool IsThinLTO = CodeGenOpts.EmitSummaryIndex;
+ bool IsThinLTO = CodeGenOpts.PrepareForThinLTO;
bool IsLTO = CodeGenOpts.PrepareForLTO;
if (CodeGenOpts.OptimizationLevel == 0) {
+ if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts))
+ MPM.addPass(GCOVProfilerPass(*Options));
+
// Build a minimal pipeline based on the semantics required by Clang,
// which is just that always inlining occurs.
MPM.addPass(AlwaysInlinerPass());
@@ -925,8 +961,8 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass()));
- // Lastly, add a semantically necessary pass for ThinLTO.
- if (IsThinLTO)
+ // Lastly, add a semantically necessary pass for LTO.
+ if (IsLTO || IsThinLTO)
MPM.addPass(NameAnonGlobalPass());
} else {
// Map our optimization levels into one of the distinct levels used to
@@ -940,6 +976,10 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
FPM.addPass(BoundsCheckingPass());
});
+ if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts))
+ PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) {
+ MPM.addPass(GCOVProfilerPass(*Options));
+ });
if (IsThinLTO) {
MPM = PB.buildThinLTOPreLinkDefaultPipeline(
@@ -948,6 +988,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
} else if (IsLTO) {
MPM = PB.buildLTOPreLinkDefaultPipeline(Level,
CodeGenOpts.DebugPassManager);
+ MPM.addPass(NameAnonGlobalPass());
} else {
MPM = PB.buildPerModuleDefaultPipeline(Level,
CodeGenOpts.DebugPassManager);
@@ -959,7 +1000,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
// create that pass manager here and use it as needed below.
legacy::PassManager CodeGenPasses;
bool NeedCodeGen = false;
- Optional<raw_fd_ostream> ThinLinkOS;
+ std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
// Append any output we need to the pass manager.
switch (Action) {
@@ -967,23 +1008,26 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
break;
case Backend_EmitBC:
- if (CodeGenOpts.EmitSummaryIndex) {
+ if (CodeGenOpts.PrepareForThinLTO) {
if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
- std::error_code EC;
- ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC,
- llvm::sys::fs::F_None);
- if (EC) {
- Diags.Report(diag::err_fe_unable_to_open_output)
- << CodeGenOpts.ThinLinkBitcodeFile << EC.message();
+ ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
+ if (!ThinLinkOS)
return;
- }
}
- MPM.addPass(
- ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr));
+ MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os()
+ : nullptr));
} else {
+ // Emit a module summary by default for Regular LTO except for ld64
+ // targets
+ bool EmitLTOSummary =
+ (CodeGenOpts.PrepareForLTO &&
+ llvm::Triple(TheModule->getTargetTriple()).getVendor() !=
+ llvm::Triple::Apple);
+ if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO"))
+ TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
+
MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
- CodeGenOpts.EmitSummaryIndex,
- CodeGenOpts.EmitSummaryIndex));
+ EmitLTOSummary));
}
break;
@@ -997,7 +1041,13 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
NeedCodeGen = true;
CodeGenPasses.add(
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
- if (!AddEmitPasses(CodeGenPasses, Action, *OS))
+ if (!CodeGenOpts.SplitDwarfFile.empty()) {
+ DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile);
+ if (!DwoOS)
+ return;
+ }
+ if (!AddEmitPasses(CodeGenPasses, Action, *OS,
+ DwoOS ? &DwoOS->os() : nullptr))
// FIXME: Should we handle this error differently?
return;
break;
@@ -1017,6 +1067,11 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
PrettyStackTraceString CrashInfo("Code generation");
CodeGenPasses.run(*TheModule);
}
+
+ if (ThinLinkOS)
+ ThinLinkOS->keep();
+ if (DwoOS)
+ DwoOS->keep();
}
Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) {
@@ -1026,16 +1081,22 @@ Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) {
// The bitcode file may contain multiple modules, we want the one that is
// marked as being the ThinLTO module.
- for (BitcodeModule &BM : *BMsOrErr) {
- Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo();
- if (LTOInfo && LTOInfo->IsThinLTO)
- return BM;
- }
+ if (const BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr))
+ return *Bm;
return make_error<StringError>("Could not find module summary",
inconvertibleErrorCode());
}
+BitcodeModule *clang::FindThinLTOModule(MutableArrayRef<BitcodeModule> BMs) {
+ for (BitcodeModule &BM : BMs) {
+ Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo();
+ if (LTOInfo && LTOInfo->IsThinLTO)
+ return &BM;
+ }
+ return nullptr;
+}
+
static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
const HeaderSearchOptions &HeaderOpts,
const CodeGenOptions &CGOpts,
@@ -1067,9 +1128,8 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
// e.g. record required linkage changes.
if (Summary->modulePath() == M->getModuleIdentifier())
continue;
- // Doesn't matter what value we plug in to the map, just needs an entry
- // to provoke importing by thinBackend.
- ImportList[Summary->modulePath()][GUID] = 1;
+ // Add an entry to provoke importing by thinBackend.
+ ImportList[Summary->modulePath()].insert(GUID);
}
std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports;
@@ -1100,15 +1160,27 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
return llvm::make_unique<lto::NativeObjectStream>(std::move(OS));
};
lto::Config Conf;
+ if (CGOpts.SaveTempsFilePrefix != "") {
+ if (Error E = Conf.addSaveTemps(CGOpts.SaveTempsFilePrefix + ".",
+ /* UseInputModulePath */ false)) {
+ handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
+ errs() << "Error setting up ThinLTO save-temps: " << EIB.message()
+ << '\n';
+ });
+ }
+ }
Conf.CPU = TOpts.CPU;
Conf.CodeModel = getCodeModel(CGOpts);
Conf.MAttrs = TOpts.Features;
- Conf.RelocModel = getRelocModel(CGOpts);
+ Conf.RelocModel = CGOpts.RelocationModel;
Conf.CGOptLevel = getCGOptLevel(CGOpts);
initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts);
Conf.SampleProfile = std::move(SampleProfile);
Conf.UseNewPM = CGOpts.ExperimentalNewPassManager;
Conf.DebugPassManager = CGOpts.DebugPassManager;
+ Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;
+ Conf.RemarksFilename = CGOpts.OptRecordFile;
+ Conf.DwoPath = CGOpts.SplitDwarfFile;
switch (Action) {
case Backend_EmitNothing:
Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) {
@@ -1123,7 +1195,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
break;
case Backend_EmitBC:
Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) {
- WriteBitcodeToFile(M, *OS, CGOpts.EmitLLVMUseLists);
+ WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists);
return false;
};
break;
@@ -1132,7 +1204,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
break;
}
if (Error E = thinBackend(
- Conf, 0, AddStream, *M, *CombinedIndex, ImportList,
+ Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
ModuleToDefinedGVSummaries[M->getModuleIdentifier()], ModuleMap)) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
@@ -1148,6 +1220,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
const llvm::DataLayout &TDesc, Module *M,
BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS) {
+ std::unique_ptr<llvm::Module> EmptyModule;
if (!CGOpts.ThinLTOIndexFile.empty()) {
// If we are performing a ThinLTO importing compile, load the function index
// into memory and pass it into runThinLTOBackend, which will run the
@@ -1165,11 +1238,22 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
// A null CombinedIndex means we should skip ThinLTO compilation
// (LLVM will optionally ignore empty index files, returning null instead
// of an error).
- bool DoThinLTOBackend = CombinedIndex != nullptr;
- if (DoThinLTOBackend) {
- runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts,
- LOpts, std::move(OS), CGOpts.SampleProfileFile, Action);
- return;
+ if (CombinedIndex) {
+ if (!CombinedIndex->skipModuleByDistributedBackend()) {
+ runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts,
+ LOpts, std::move(OS), CGOpts.SampleProfileFile,
+ Action);
+ return;
+ }
+ // Distributed indexing detected that nothing from the module is needed
+ // for the final linking. So we can skip the compilation. We sill need to
+ // output an empty object file to make sure that a linker does not fail
+ // trying to read it. Also for some features, like CFI, we must skip
+ // the compilation as CombinedIndex does not contain all required
+ // information.
+ EmptyModule = llvm::make_unique<llvm::Module>("empty", M->getContext());
+ EmptyModule->setTargetTriple(M->getTargetTriple());
+ M = EmptyModule.get();
}
}
@@ -1228,7 +1312,7 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
// Save llvm.compiler.used and remote it.
SmallVector<Constant*, 2> UsedArray;
- SmallSet<GlobalValue*, 4> UsedGlobals;
+ SmallPtrSet<GlobalValue*, 4> UsedGlobals;
Type *UsedElementType = Type::getInt8Ty(M->getContext())->getPointerTo(0);
GlobalVariable *Used = collectUsedGlobalVariables(*M, UsedGlobals, true);
for (auto *GV : UsedGlobals) {
@@ -1253,7 +1337,7 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
// If the input is LLVM Assembly, bitcode is produced by serializing
// the module. Use-lists order need to be perserved in this case.
llvm::raw_string_ostream OS(Data);
- llvm::WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ true);
+ llvm::WriteBitcodeToFile(*M, OS, /* ShouldPreserveUseListOrder */ true);
ModuleData =
ArrayRef<uint8_t>((const uint8_t *)OS.str().data(), OS.str().size());
} else
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
index 6862fd811186..b34bcdc1fc38 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
@@ -18,6 +18,7 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
@@ -186,7 +187,7 @@ namespace {
RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
SourceLocation loc, bool AsValue) const;
- /// \brief Converts a rvalue to integer value.
+ /// Converts a rvalue to integer value.
llvm::Value *convertRValueToInt(RValue RVal) const;
RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal,
@@ -207,13 +208,13 @@ namespace {
LVal.getBaseInfo(), LVal.getTBAAInfo());
}
- /// \brief Emits atomic load.
+ /// Emits atomic load.
/// \returns Loaded value.
RValue EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
bool AsValue, llvm::AtomicOrdering AO,
bool IsVolatile);
- /// \brief Emits atomic compare-and-exchange sequence.
+ /// Emits atomic compare-and-exchange sequence.
/// \param Expected Expected value.
/// \param Desired Desired value.
/// \param Success Atomic ordering for success operation.
@@ -229,13 +230,13 @@ namespace {
llvm::AtomicOrdering::SequentiallyConsistent,
bool IsWeak = false);
- /// \brief Emits atomic update.
+ /// Emits atomic update.
/// \param AO Atomic ordering.
/// \param UpdateOp Update operation for the current lvalue.
void EmitAtomicUpdate(llvm::AtomicOrdering AO,
const llvm::function_ref<RValue(RValue)> &UpdateOp,
bool IsVolatile);
- /// \brief Emits atomic update.
+ /// Emits atomic update.
/// \param AO Atomic ordering.
void EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,
bool IsVolatile);
@@ -243,25 +244,25 @@ namespace {
/// Materialize an atomic r-value in atomic-layout memory.
Address materializeRValue(RValue rvalue) const;
- /// \brief Creates temp alloca for intermediate operations on atomic value.
+ /// Creates temp alloca for intermediate operations on atomic value.
Address CreateTempAlloca() const;
private:
bool requiresMemSetZero(llvm::Type *type) const;
- /// \brief Emits atomic load as a libcall.
+ /// Emits atomic load as a libcall.
void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
llvm::AtomicOrdering AO, bool IsVolatile);
- /// \brief Emits atomic load as LLVM instruction.
+ /// Emits atomic load as LLVM instruction.
llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile);
- /// \brief Emits atomic compare-and-exchange op as a libcall.
+ /// Emits atomic compare-and-exchange op as a libcall.
llvm::Value *EmitAtomicCompareExchangeLibcall(
llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
llvm::AtomicOrdering Success =
llvm::AtomicOrdering::SequentiallyConsistent,
llvm::AtomicOrdering Failure =
llvm::AtomicOrdering::SequentiallyConsistent);
- /// \brief Emits atomic compare-and-exchange op as LLVM instruction.
+ /// Emits atomic compare-and-exchange op as LLVM instruction.
std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp(
llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
llvm::AtomicOrdering Success =
@@ -269,19 +270,19 @@ namespace {
llvm::AtomicOrdering Failure =
llvm::AtomicOrdering::SequentiallyConsistent,
bool IsWeak = false);
- /// \brief Emit atomic update as libcalls.
+ /// Emit atomic update as libcalls.
void
EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
const llvm::function_ref<RValue(RValue)> &UpdateOp,
bool IsVolatile);
- /// \brief Emit atomic update as LLVM instructions.
+ /// Emit atomic update as LLVM instructions.
void EmitAtomicUpdateOp(llvm::AtomicOrdering AO,
const llvm::function_ref<RValue(RValue)> &UpdateOp,
bool IsVolatile);
- /// \brief Emit atomic update as libcalls.
+ /// Emit atomic update as libcalls.
void EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, RValue UpdateRVal,
bool IsVolatile);
- /// \brief Emit atomic update as LLVM instructions.
+ /// Emit atomic update as LLVM instructions.
void EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRal,
bool IsVolatile);
};
@@ -590,11 +591,13 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
break;
case AtomicExpr::AO__opencl_atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_min:
Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min
: llvm::AtomicRMWInst::UMin;
break;
case AtomicExpr::AO__opencl_atomic_fetch_max:
+ case AtomicExpr::AO__atomic_fetch_max:
Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max
: llvm::AtomicRMWInst::UMax;
break;
@@ -751,6 +754,13 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
Address Dest = Address::invalid();
Address Ptr = EmitPointerWithAlignment(E->getPtr());
+ 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);
+ }
+
CharUnits sizeChars, alignChars;
std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy);
uint64_t Size = sizeChars.getQuantity();
@@ -758,12 +768,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
bool UseLibcall = ((Ptr.getAlignment() % sizeChars) != 0 ||
getContext().toBits(sizeChars) > MaxInlineWidthInBits);
- 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);
- }
+ if (UseLibcall)
+ CGM.getDiags().Report(E->getLocStart(), diag::warn_atomic_op_misaligned);
llvm::Value *Order = EmitScalarExpr(E->getOrder());
llvm::Value *Scope =
@@ -855,6 +861,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__atomic_or_fetch:
case AtomicExpr::AO__atomic_xor_fetch:
case AtomicExpr::AO__atomic_nand_fetch:
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_max:
Val1 = EmitValToTemp(*this, E->getVal1());
break;
}
@@ -909,6 +917,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__atomic_or_fetch:
case AtomicExpr::AO__atomic_sub_fetch:
case AtomicExpr::AO__atomic_xor_fetch:
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_max:
// For these, only library calls for certain sizes exist.
UseOptimizedLibcall = true;
break;
@@ -1091,6 +1101,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
MemTy, E->getExprLoc(), sizeChars);
break;
+ case AtomicExpr::AO__atomic_fetch_min:
case AtomicExpr::AO__opencl_atomic_fetch_min:
LibCallName = E->getValueType()->isSignedIntegerType()
? "__atomic_fetch_min"
@@ -1098,6 +1109,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
LoweredMemTy, E->getExprLoc(), sizeChars);
break;
+ case AtomicExpr::AO__atomic_fetch_max:
case AtomicExpr::AO__opencl_atomic_fetch_max:
LibCallName = E->getValueType()->isSignedIntegerType()
? "__atomic_fetch_max"
@@ -1160,7 +1172,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
if (UseOptimizedLibcall && Res.getScalarVal()) {
llvm::Value *ResVal = Res.getScalarVal();
if (PostOp) {
- llvm::Value *LoadVal1 = Args[1].RV.getScalarVal();
+ llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal();
ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1);
}
if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch)
@@ -1508,11 +1520,13 @@ void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
// which means that the caller is responsible for having zeroed
// any padding. Just do an aggregate copy of that type.
if (rvalue.isAggregate()) {
- CGF.EmitAggregateCopy(getAtomicAddress(),
- rvalue.getAggregateAddress(),
- getAtomicType(),
- (rvalue.isVolatileQualified()
- || LVal.isVolatileQualified()));
+ LValue Dest = CGF.MakeAddrLValue(getAtomicAddress(), getAtomicType());
+ LValue Src = CGF.MakeAddrLValue(rvalue.getAggregateAddress(),
+ getAtomicType());
+ bool IsVolatile = rvalue.isVolatileQualified() ||
+ LVal.isVolatileQualified();
+ CGF.EmitAggregateCopy(Dest, Src, getAtomicType(),
+ AggValueSlot::DoesNotOverlap, IsVolatile);
return;
}
@@ -2007,6 +2021,7 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap,
Zeroed ? AggValueSlot::IsZeroed :
AggValueSlot::IsNotZeroed);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
index 5f73d4cf7913..906b98bfbafe 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -66,7 +66,7 @@ static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
/// buildBlockDescriptor - Build the block descriptor meta-data for a block.
/// buildBlockDescriptor is accessed from 5th field of the Block_literal
/// meta-data and contains stationary information about the block literal.
-/// Its definition will have 4 (or optinally 6) words.
+/// Its definition will have 4 (or optionally 6) words.
/// \code
/// struct Block_descriptor {
/// unsigned long reserved;
@@ -85,7 +85,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy));
llvm::PointerType *i8p = nullptr;
if (CGM.getLangOpts().OpenCL)
- i8p =
+ i8p =
llvm::Type::getInt8PtrTy(
CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant));
else
@@ -104,7 +104,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
// Optional copy/dispose helpers.
- if (blockInfo.NeedsCopyDispose) {
+ if (blockInfo.needsCopyDisposeHelpers()) {
// copy_func_helper_decl
elements.add(buildCopyHelper(CGM, blockInfo));
@@ -117,7 +117,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
elements.add(llvm::ConstantExpr::getBitCast(
CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
-
+
// GC layout.
if (C.getLangOpts().ObjC1) {
if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
@@ -159,6 +159,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
/// These are the flags (with corresponding bit number) that the
/// compiler is actually supposed to know about.
+ /// 23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping
/// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
/// descriptor provides copy and dispose helper functions
/// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
@@ -307,25 +308,12 @@ static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
assert(elementTypes.empty());
if (CGM.getLangOpts().OpenCL) {
- // The header is basically 'struct { int; int; generic void *;
+ // The header is basically 'struct { int; int;
// 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();
+ unsigned Offset = 2 * CGM.getIntSize().getQuantity();
+ unsigned BlockAlign = CGM.getIntAlign().getQuantity();
if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ {
@@ -343,7 +331,7 @@ static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
info.BlockSize = CharUnits::fromQuantity(Offset);
} else {
// The header is basically 'struct { void *; int; int; void *; void *; }'.
- // Assert that that struct is packed.
+ // Assert that the struct is packed.
assert(CGM.getIntSize() <= CGM.getPointerSize());
assert(CGM.getIntAlign() <= CGM.getPointerAlign());
assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign()));
@@ -393,7 +381,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
else if (C.getLangOpts().ObjC1 &&
CGM.getLangOpts().getGC() == LangOptions::NonGC)
info.HasCapturedVariableLayout = true;
-
+
// Collect the layout chunks.
SmallVector<BlockLayoutChunk, 16> layout;
layout.reserve(block->capturesCXXThis() +
@@ -477,6 +465,14 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
info.NeedsCopyDispose = true;
info.HasCXXObject = true;
+ // So do C structs that require non-trivial copy construction or
+ // destruction.
+ } else if (variable->getType().isNonTrivialToPrimitiveCopy() ==
+ QualType::PCK_Struct ||
+ variable->getType().isDestructedType() ==
+ QualType::DK_nontrivial_c_struct) {
+ info.NeedsCopyDispose = true;
+
// And so do types with destructors.
} else if (CGM.getLangOpts().CPlusPlus) {
if (const CXXRecordDecl *record =
@@ -491,12 +487,12 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
QualType VT = getCaptureFieldType(*CGF, CI);
CharUnits size = C.getTypeSizeInChars(VT);
CharUnits align = C.getDeclAlign(variable);
-
+
maxFieldAlign = std::max(maxFieldAlign, align);
llvm::Type *llvmType =
CGM.getTypes().ConvertTypeForMem(VT);
-
+
layout.push_back(
BlockLayoutChunk(align, size, lifetime, &CI, llvmType, VT));
}
@@ -513,11 +509,11 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
// to get reproducible results. There should probably be an
// llvm::array_pod_stable_sort.
std::stable_sort(layout.begin(), layout.end());
-
+
// Needed for blocks layout info.
info.BlockHeaderForcedGapOffset = info.BlockSize;
info.BlockHeaderForcedGapSize = CharUnits::Zero();
-
+
CharUnits &blockSize = info.BlockSize;
info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign);
@@ -568,7 +564,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
}
assert(endAlign == getLowBit(blockSize));
-
+
// At this point, we just have to add padding if the end align still
// isn't aligned right.
if (endAlign < maxFieldAlign) {
@@ -689,7 +685,7 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
CleanupKind cleanupKind = InactiveNormalCleanup;
bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind);
- if (useArrayEHCleanup)
+ if (useArrayEHCleanup)
cleanupKind = InactiveNormalAndEHCleanup;
CGF.pushDestroy(cleanupKind, addr, VT,
@@ -705,11 +701,8 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
/// kind of cleanup object is a BlockDecl*.
void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) {
assert(E->getNumObjects() != 0);
- ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects();
- for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator
- i = cleanups.begin(), e = cleanups.end(); i != e; ++i) {
- enterBlockScope(*this, *i);
- }
+ for (const ExprWithCleanups::CleanupObject &C : E->getObjects())
+ enterBlockScope(*this, C);
}
/// Find the layout for the given block in a linked list and remove it.
@@ -740,27 +733,19 @@ void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) {
}
/// Emit a block literal expression in the current function.
-llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr,
- llvm::Function **InvokeF) {
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
// If the block has no captures, we won't have a pre-computed
// layout for it.
if (!blockExpr->getBlockDecl()->hasCaptures()) {
// 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, InvokeF);
+ return EmitBlockLiteral(blockInfo);
}
// Find the block info for this block and take ownership of it.
@@ -769,28 +754,17 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr,
blockExpr->getBlockDecl()));
blockInfo->BlockExpression = blockExpr;
- return EmitBlockLiteral(*blockInfo, InvokeF);
+ return EmitBlockLiteral(*blockInfo);
}
-llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
- llvm::Function **InvokeF) {
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
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();
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)
@@ -805,8 +779,13 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
llvm::Constant *descriptor;
BlockFlags flags;
if (!IsOpenCL) {
- isa = llvm::ConstantExpr::getBitCast(CGM.getNSConcreteStackBlock(),
- VoidPtrTy);
+ // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock
+ // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping
+ // block just returns the original block and releasing it is a no-op.
+ llvm::Constant *blockISA = blockInfo.getBlockDecl()->doesNotEscape()
+ ? CGM.getNSConcreteGlobalBlock()
+ : CGM.getNSConcreteStackBlock();
+ isa = llvm::ConstantExpr::getBitCast(blockISA, VoidPtrTy);
// Build the block descriptor.
descriptor = buildBlockDescriptor(CGM, blockInfo);
@@ -815,12 +794,14 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
flags = BLOCK_HAS_SIGNATURE;
if (blockInfo.HasCapturedVariableLayout)
flags |= BLOCK_HAS_EXTENDED_LAYOUT;
- if (blockInfo.NeedsCopyDispose)
+ if (blockInfo.needsCopyDisposeHelpers())
flags |= BLOCK_HAS_COPY_DISPOSE;
if (blockInfo.HasCXXObject)
flags |= BLOCK_HAS_CXX_OBJ;
if (blockInfo.UsesStret)
flags |= BLOCK_USE_STRET;
+ if (blockInfo.getBlockDecl()->doesNotEscape())
+ flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
}
auto projectField =
@@ -859,11 +840,12 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
getIntSize(), "block.align");
}
- addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
- if (!IsOpenCL)
+ if (!IsOpenCL) {
+ addHeaderField(llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy),
+ getPointerSize(), "block.invoke");
addHeaderField(descriptor, getPointerSize(), "block.descriptor");
- else if (auto *Helper =
- CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ } else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
addHeaderField(
I.first,
@@ -913,7 +895,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
const CGBlockInfo::Capture &enclosingCapture =
BlockInfo->getCapture(variable);
- // This is a [[type]]*, except that a byref entry wil just be an i8**.
+ // This is a [[type]]*, except that a byref entry will just be an i8**.
src = Builder.CreateStructGEP(LoadBlockStruct(),
enclosingCapture.getIndex(),
enclosingCapture.getOffset(),
@@ -955,7 +937,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
AggValueSlot::forAddr(blockField, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap);
EmitAggExpr(copyExpr, Slot);
} else {
EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
@@ -1024,6 +1007,11 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
llvm::Value *result = Builder.CreatePointerCast(
blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType()));
+ if (IsOpenCL) {
+ CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn,
+ result);
+ }
+
return result;
}
@@ -1061,38 +1049,23 @@ llvm::Type *CodeGenModule::getBlockDescriptorType() {
}
llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
+ assert(!getLangOpts().OpenCL && "OpenCL does not need this");
+
if (GenericBlockLiteralType)
return GenericBlockLiteralType;
llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
- 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);
- }
+ // 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;
}
@@ -1103,27 +1076,21 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
E->getCallee()->getType()->getAs<BlockPointerType>();
llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
+ llvm::Value *FuncPtr;
- // Get a pointer to the generic block literal.
- // For OpenCL we generate generic AS void ptr to be able to reuse the same
- // block definition for blocks with captures generated as private AS local
- // variables and without captures generated as global AS program scope
- // variables.
- unsigned AddrSpace = 0;
- if (getLangOpts().OpenCL)
- AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_generic);
-
- llvm::Type *BlockLiteralTy =
- llvm::PointerType::get(CGM.getGenericBlockLiteralType(), AddrSpace);
+ if (!CGM.getLangOpts().OpenCL) {
+ // Get a pointer to the generic block literal.
+ llvm::Type *BlockLiteralTy =
+ llvm::PointerType::get(CGM.getGenericBlockLiteralType(), 0);
- // Bitcast the callee to a block literal.
- BlockPtr =
- Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
+ // Bitcast the callee to a block literal.
+ BlockPtr =
+ Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
- // Get the function pointer from the literal.
- llvm::Value *FuncPtr =
- Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr,
- CGM.getLangOpts().OpenCL ? 2 : 3);
+ // Get the function pointer from the literal.
+ FuncPtr =
+ Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
+ }
// Add the block literal.
CallArgList Args;
@@ -1146,7 +1113,11 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
// Load the function.
- llvm::Value *Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
+ llvm::Value *Func;
+ if (CGM.getLangOpts().OpenCL)
+ Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
+ else
+ Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
const FunctionType *FuncTy = FnType->castAs<FunctionType>();
const CGFunctionInfo &FnInfo =
@@ -1242,9 +1213,13 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
auto fields = builder.beginStruct();
bool IsOpenCL = CGM.getLangOpts().OpenCL;
+ bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
if (!IsOpenCL) {
// isa
- fields.add(CGM.getNSConcreteGlobalBlock());
+ if (IsWindows)
+ fields.addNullPointer(CGM.Int8PtrPtrTy);
+ else
+ fields.add(CGM.getNSConcreteGlobalBlock());
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
@@ -1255,14 +1230,14 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
// Reserved
fields.addInt(CGM.IntTy, 0);
+
+ // Function
+ fields.add(blockFn);
} else {
fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity());
fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity());
}
- // Function
- fields.add(blockFn);
-
if (!IsOpenCL) {
// Descriptor
fields.add(buildBlockDescriptor(CGM, blockInfo));
@@ -1279,7 +1254,27 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
llvm::Constant *literal = fields.finishAndCreateGlobal(
"__block_literal_global", blockInfo.BlockAlign,
- /*constant*/ true, llvm::GlobalVariable::InternalLinkage, AddrSpace);
+ /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
+
+ // Windows does not allow globals to be initialised to point to globals in
+ // different DLLs. Any such variables must run code to initialise them.
+ if (IsWindows) {
+ auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
+ {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init",
+ &CGM.getModule());
+ llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
+ Init));
+ b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(),
+ b.CreateStructGEP(literal, 0), CGM.getPointerAlign().getQuantity());
+ b.CreateRetVoid();
+ // We can't use the normal LLVM global initialisation array, because we
+ // need to specify that this runs early in library initialisation.
+ auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
+ Init, ".block_isa_init_ptr");
+ InitVar->setSection(".CRT$XCLa");
+ CGM.addUsedGlobal(InitVar);
+ }
// Return a constant of the appropriately-casted type.
llvm::Type *RequiredType =
@@ -1287,6 +1282,10 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
llvm::Constant *Result =
llvm::ConstantExpr::getPointerCast(literal, RequiredType);
CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
+ if (CGM.getContext().getLangOpts().OpenCL)
+ CGM.getOpenCLRuntime().recordBlockInfo(
+ blockInfo.BlockExpression,
+ cast<llvm::Function>(blockFn->stripPointerCasts()), Result);
return Result;
}
@@ -1340,7 +1339,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
CurGD = GD;
CurEHLocation = blockInfo.getBlockExpr()->getLocEnd();
-
+
BlockInfo = &blockInfo;
// Arrange for local static and local extern declarations to appear
@@ -1479,8 +1478,8 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
if (capture.isConstant()) {
auto addr = LocalDeclMap.find(variable)->second;
- DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
- Builder);
+ (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
+ Builder);
continue;
}
@@ -1513,6 +1512,7 @@ enum class BlockCaptureEntityKind {
CXXRecord, // Copy or destroy
ARCWeak,
ARCStrong,
+ NonTrivialCStruct,
BlockObject, // Assign or release
None
};
@@ -1548,39 +1548,46 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
Flags |= BLOCK_FIELD_IS_WEAK;
return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
}
- if (!T->isObjCRetainableType())
- // For all other types, the memcpy is fine.
- return std::make_pair(BlockCaptureEntityKind::None, Flags);
Flags = BLOCK_FIELD_IS_OBJECT;
bool isBlockPointer = T->isBlockPointerType();
if (isBlockPointer)
Flags = BLOCK_FIELD_IS_BLOCK;
- // Special rules for ARC captures:
- Qualifiers QS = T.getQualifiers();
-
- // We need to register __weak direct captures with the runtime.
- if (QS.getObjCLifetime() == Qualifiers::OCL_Weak)
+ switch (T.isNonTrivialToPrimitiveCopy()) {
+ case QualType::PCK_Struct:
+ return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
+ BlockFieldFlags());
+ case QualType::PCK_ARCWeak:
+ // We need to register __weak direct captures with the runtime.
return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);
-
- // We need to retain the copied value for __strong direct captures.
- if (QS.getObjCLifetime() == Qualifiers::OCL_Strong) {
- // If it's a block pointer, we have to copy the block and
- // assign that to the destination pointer, so we might as
- // well use _Block_object_assign. Otherwise we can avoid that.
+ case QualType::PCK_ARCStrong:
+ // We need to retain the copied value for __strong direct captures.
+ // If it's a block pointer, we have to copy the block and assign that to
+ // the destination pointer, so we might as well use _Block_object_assign.
+ // Otherwise we can avoid that.
return std::make_pair(!isBlockPointer ? BlockCaptureEntityKind::ARCStrong
: BlockCaptureEntityKind::BlockObject,
Flags);
- }
+ case QualType::PCK_Trivial:
+ case QualType::PCK_VolatileTrivial: {
+ if (!T->isObjCRetainableType())
+ // For all other types, the memcpy is fine.
+ return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
- // Non-ARC captures of retainable pointers are strong and
- // therefore require a call to _Block_object_assign.
- if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)
- return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
+ // Special rules for ARC captures:
+ Qualifiers QS = T.getQualifiers();
+
+ // Non-ARC captures of retainable pointers are strong and
+ // therefore require a call to _Block_object_assign.
+ if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)
+ return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
- // Otherwise the memcpy is fine.
- return std::make_pair(BlockCaptureEntityKind::None, Flags);
+ // Otherwise the memcpy is fine.
+ return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
+ }
+ }
+ llvm_unreachable("after exhaustive PrimitiveCopyKind switch");
}
/// Find the set of block captures that need to be explicitly copied or destroy.
@@ -1602,6 +1609,64 @@ static void findBlockCapturedManagedEntities(
}
}
+namespace {
+/// Release a __block variable.
+struct CallBlockRelease final : EHScopeStack::Cleanup {
+ Address Addr;
+ BlockFieldFlags FieldFlags;
+ bool LoadBlockVarAddr;
+
+ CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue)
+ : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue) {}
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ llvm::Value *BlockVarAddr;
+ if (LoadBlockVarAddr) {
+ BlockVarAddr = CGF.Builder.CreateLoad(Addr);
+ BlockVarAddr = CGF.Builder.CreateBitCast(BlockVarAddr, CGF.VoidPtrTy);
+ } else {
+ BlockVarAddr = Addr.getPointer();
+ }
+
+ CGF.BuildBlockRelease(BlockVarAddr, FieldFlags);
+ }
+};
+} // end anonymous namespace
+
+static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
+ Address Field, QualType CaptureType,
+ BlockFieldFlags Flags, bool EHOnly,
+ CodeGenFunction &CGF) {
+ switch (CaptureKind) {
+ case BlockCaptureEntityKind::CXXRecord:
+ case BlockCaptureEntityKind::ARCWeak:
+ case BlockCaptureEntityKind::NonTrivialCStruct:
+ case BlockCaptureEntityKind::ARCStrong: {
+ if (CaptureType.isDestructedType() &&
+ (!EHOnly || CGF.needsEHCleanup(CaptureType.isDestructedType()))) {
+ CodeGenFunction::Destroyer *Destroyer =
+ CaptureKind == BlockCaptureEntityKind::ARCStrong
+ ? CodeGenFunction::destroyARCStrongImprecise
+ : CGF.getDestroyer(CaptureType.isDestructedType());
+ CleanupKind Kind =
+ EHOnly ? EHCleanup
+ : CGF.getCleanupKind(CaptureType.isDestructedType());
+ CGF.pushDestroy(Kind, Field, CaptureType, Destroyer, Kind & EHCleanup);
+ }
+ break;
+ }
+ case BlockCaptureEntityKind::BlockObject: {
+ if (!EHOnly || CGF.getLangOpts().Exceptions) {
+ CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup;
+ CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true);
+ }
+ break;
+ }
+ case BlockCaptureEntityKind::None:
+ llvm_unreachable("unexpected BlockCaptureEntityKind");
+ }
+}
+
/// Generate the copy-helper function for a block closure object:
/// static void block_copy_helper(block_t *dst, block_t *src);
/// The runtime will have previously initialized 'dst' by doing a
@@ -1644,7 +1709,7 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
false,
false);
- CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
StartFunction(FD, C.VoidTy, Fn, FI, args);
ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getLocStart()};
@@ -1665,6 +1730,7 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
for (const auto &CopiedCapture : CopiedCaptures) {
const BlockDecl::Capture &CI = CopiedCapture.CI;
const CGBlockInfo::Capture &capture = CopiedCapture.Capture;
+ QualType captureType = CI.getVariable()->getType();
BlockFieldFlags flags = CopiedCapture.Flags;
unsigned index = capture.getIndex();
@@ -1677,6 +1743,13 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
EmitSynthesizedCXXCopyCtor(dstField, srcField, CI.getCopyExpr());
} else if (CopiedCapture.Kind == BlockCaptureEntityKind::ARCWeak) {
EmitARCCopyWeak(dstField, srcField);
+ // If this is a C struct that requires non-trivial copy construction, emit a
+ // call to its copy constructor.
+ } else if (CopiedCapture.Kind ==
+ BlockCaptureEntityKind::NonTrivialCStruct) {
+ QualType varType = CI.getVariable()->getType();
+ callCStructCopyConstructor(MakeAddrLValue(dstField, varType),
+ MakeAddrLValue(srcField, varType));
} else {
llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
if (CopiedCapture.Kind == BlockCaptureEntityKind::ARCStrong) {
@@ -1695,9 +1768,11 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
} else {
EmitARCRetainNonBlock(srcValue);
- // We don't need this anymore, so kill it. It's not quite
- // worth the annoyance to avoid creating it in the first place.
- cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
+ // Unless EH cleanup is required, we don't need this anymore, so kill
+ // it. It's not quite worth the annoyance to avoid creating it in the
+ // first place.
+ if (!needsEHCleanup(captureType.isDestructedType()))
+ cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
}
} else {
assert(CopiedCapture.Kind == BlockCaptureEntityKind::BlockObject);
@@ -1725,6 +1800,11 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
}
}
}
+
+ // Ensure that we destroy the copied object if an exception is thrown later
+ // in the helper function.
+ pushCaptureCleanup(CopiedCapture.Kind, dstField, captureType, flags, /*EHOnly*/ true,
+ *this);
}
FinishFunction();
@@ -1732,50 +1812,51 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
}
+static BlockFieldFlags
+getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI,
+ QualType T) {
+ BlockFieldFlags Flags = BLOCK_FIELD_IS_OBJECT;
+ if (T->isBlockPointerType())
+ Flags = BLOCK_FIELD_IS_BLOCK;
+ return Flags;
+}
+
static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
const LangOptions &LangOpts) {
- BlockFieldFlags Flags;
if (CI.isByRef()) {
- Flags = BLOCK_FIELD_IS_BYREF;
+ BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
if (T.isObjCGCWeak())
Flags |= BLOCK_FIELD_IS_WEAK;
return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
}
- if (const CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
- if (Record->hasTrivialDestructor())
- return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
+ switch (T.isDestructedType()) {
+ case QualType::DK_cxx_destructor:
return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags());
- }
-
- // Other types don't need to be destroy explicitly.
- if (!T->isObjCRetainableType())
- return std::make_pair(BlockCaptureEntityKind::None, Flags);
-
- Flags = BLOCK_FIELD_IS_OBJECT;
- if (T->isBlockPointerType())
- Flags = BLOCK_FIELD_IS_BLOCK;
-
- // Special rules for ARC captures.
- Qualifiers QS = T.getQualifiers();
-
- // Use objc_storeStrong for __strong direct captures; the
- // dynamic tools really like it when we do this.
- if (QS.getObjCLifetime() == Qualifiers::OCL_Strong)
- return std::make_pair(BlockCaptureEntityKind::ARCStrong, Flags);
-
- // Support __weak direct captures.
- if (QS.getObjCLifetime() == Qualifiers::OCL_Weak)
- return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);
-
- // Non-ARC captures are strong, and we need to use
- // _Block_object_dispose.
- if (!QS.hasObjCLifetime() && !LangOpts.ObjCAutoRefCount)
- return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
-
- // Otherwise, we have nothing to do.
- return std::make_pair(BlockCaptureEntityKind::None, Flags);
+ case QualType::DK_objc_strong_lifetime:
+ // Use objc_storeStrong for __strong direct captures; the
+ // dynamic tools really like it when we do this.
+ return std::make_pair(BlockCaptureEntityKind::ARCStrong,
+ getBlockFieldFlagsForObjCObjectPointer(CI, T));
+ case QualType::DK_objc_weak_lifetime:
+ // Support __weak direct captures.
+ return std::make_pair(BlockCaptureEntityKind::ARCWeak,
+ getBlockFieldFlagsForObjCObjectPointer(CI, T));
+ case QualType::DK_nontrivial_c_struct:
+ return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
+ BlockFieldFlags());
+ case QualType::DK_none: {
+ // Non-ARC captures are strong, and we need to use _Block_object_dispose.
+ if (T->isObjCRetainableType() && !T.getQualifiers().hasObjCLifetime() &&
+ !LangOpts.ObjCAutoRefCount)
+ return std::make_pair(BlockCaptureEntityKind::BlockObject,
+ getBlockFieldFlagsForObjCObjectPointer(CI, T));
+ // Otherwise, we have nothing to do.
+ return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
+ }
+ }
+ llvm_unreachable("after exhaustive DestructionKind switch");
}
/// Generate the destroy-helper function for a block closure object:
@@ -1814,7 +1895,7 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
nullptr, SC_Static,
false, false);
- CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
StartFunction(FD, C.VoidTy, Fn, FI, args);
ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getLocStart()};
@@ -1839,29 +1920,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
Address srcField =
Builder.CreateStructGEP(src, capture.getIndex(), capture.getOffset());
- // If the captured record has a destructor then call it.
- if (DestroyedCapture.Kind == BlockCaptureEntityKind::CXXRecord) {
- const auto *Dtor =
- CI.getVariable()->getType()->getAsCXXRecordDecl()->getDestructor();
- PushDestructorCleanup(Dtor, srcField);
-
- // If this is a __weak capture, emit the release directly.
- } else if (DestroyedCapture.Kind == BlockCaptureEntityKind::ARCWeak) {
- EmitARCDestroyWeak(srcField);
-
- // Destroy strong objects with a call if requested.
- } else if (DestroyedCapture.Kind == BlockCaptureEntityKind::ARCStrong) {
- EmitARCDestroyStrong(srcField, ARCImpreciseLifetime);
-
- // Otherwise we call _Block_object_dispose. It wouldn't be too
- // hard to just emit this as a cleanup if we wanted to make sure
- // that things were done in reverse.
- } else {
- assert(DestroyedCapture.Kind == BlockCaptureEntityKind::BlockObject);
- llvm::Value *value = Builder.CreateLoad(srcField);
- value = Builder.CreateBitCast(value, VoidPtrTy);
- BuildBlockRelease(value, flags);
- }
+ pushCaptureCleanup(DestroyedCapture.Kind, srcField,
+ CI.getVariable()->getType(), flags, /*EHOnly*/ false, *this);
}
cleanups.ForceCleanup();
@@ -1941,7 +2001,7 @@ public:
// variable.
llvm::Value *value = CGF.Builder.CreateLoad(srcField);
-
+
llvm::Value *null =
llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
@@ -2020,6 +2080,36 @@ public:
id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
}
};
+
+/// Emits the copy/dispose helpers for a __block variable that is a non-trivial
+/// C struct.
+class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {
+ QualType VarType;
+
+public:
+ NonTrivialCStructByrefHelpers(CharUnits alignment, QualType type)
+ : BlockByrefHelpers(alignment), VarType(type) {}
+
+ void emitCopy(CodeGenFunction &CGF, Address destField,
+ Address srcField) override {
+ CGF.callCStructMoveConstructor(CGF.MakeAddrLValue(destField, VarType),
+ CGF.MakeAddrLValue(srcField, VarType));
+ }
+
+ bool needsDispose() const override {
+ return VarType.isDestructedType();
+ }
+
+ void emitDispose(CodeGenFunction &CGF, Address field) override {
+ EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
+ CGF.pushDestroy(VarType.isDestructedType(), field, VarType);
+ CGF.PopCleanupBlocks(cleanupDepth);
+ }
+
+ void profileImpl(llvm::FoldingSetNodeID &id) const override {
+ id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
+ }
+};
} // end anonymous namespace
static llvm::Constant *
@@ -2059,7 +2149,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
SC_Static,
false, false);
- CGF.CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+ CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
CGF.StartFunction(FD, R, Fn, FI, args);
@@ -2083,7 +2173,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
"src-object");
generator.emitCopy(CGF, destField, srcField);
- }
+ }
CGF.FinishFunction();
@@ -2133,7 +2223,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
SC_Static,
false, false);
- CGF.CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+ CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
CGF.StartFunction(FD, R, Fn, FI, args);
@@ -2205,6 +2295,13 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));
}
+ // If type is a non-trivial C struct type that is non-trivial to
+ // destructly move or destroy, build the copy and dispose helpers.
+ if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct ||
+ type.isDestructedType() == QualType::DK_nontrivial_c_struct)
+ return ::buildByrefHelpers(
+ CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment, type));
+
// Otherwise, if we don't have a retainable type, there's nothing to do.
// that the runtime does extra copies.
if (!type->isObjCRetainableType()) return nullptr;
@@ -2248,7 +2345,7 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
BlockFieldFlags flags;
if (type->isBlockPointerType()) {
flags |= BLOCK_FIELD_IS_BLOCK;
- } else if (CGM.getContext().isObjCNSObjectType(type) ||
+ } else if (CGM.getContext().isObjCNSObjectType(type) ||
type->isObjCObjectPointerType()) {
flags |= BLOCK_FIELD_IS_OBJECT;
} else {
@@ -2307,24 +2404,24 @@ const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) {
llvm::StructType *byrefType =
llvm::StructType::create(getLLVMContext(),
"struct.__block_byref_" + D->getNameAsString());
-
+
QualType Ty = D->getType();
CharUnits size;
SmallVector<llvm::Type *, 8> types;
-
+
// void *__isa;
types.push_back(Int8PtrTy);
size += getPointerSize();
-
+
// void *__forwarding;
types.push_back(llvm::PointerType::getUnqual(byrefType));
size += getPointerSize();
-
+
// int32_t __flags;
types.push_back(Int32Ty);
size += CharUnits::fromQuantity(4);
-
+
// int32_t __size;
types.push_back(Int32Ty);
size += CharUnits::fromQuantity(4);
@@ -2335,7 +2432,7 @@ const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) {
/// void *__copy_helper;
types.push_back(Int8PtrTy);
size += getPointerSize();
-
+
/// void *__destroy_helper;
types.push_back(Int8PtrTy);
size += getPointerSize();
@@ -2503,30 +2600,10 @@ void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
EmitNounwindRuntimeCall(F, args); // FIXME: throwing destructors?
}
-namespace {
- /// Release a __block variable.
- struct CallBlockRelease final : EHScopeStack::Cleanup {
- llvm::Value *Addr;
- CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- // Should we be passing FIELD_IS_WEAK here?
- CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
- }
- };
-} // end anonymous namespace
-
-/// Enter a cleanup to destroy a __block variable. Note that this
-/// cleanup should be a no-op if the variable hasn't left the stack
-/// yet; if a cleanup is required for the variable itself, that needs
-/// to be done externally.
-void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
- // We don't enter this cleanup if we're in pure-GC mode.
- if (CGM.getLangOpts().getGC() == LangOptions::GCOnly)
- return;
-
- EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup,
- emission.Addr.getPointer());
+void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr,
+ BlockFieldFlags Flags,
+ bool LoadBlockVarAddr) {
+ EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr);
}
/// Adjust the declaration of something from the blocks API.
@@ -2559,11 +2636,11 @@ static void configureBlocksRuntimeObject(CodeGenModule &CGM,
}
}
- if (!CGM.getLangOpts().BlocksRuntimeOptional)
- return;
-
- if (GV->isDeclaration() && GV->hasExternalLinkage())
+ if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&
+ GV->hasExternalLinkage())
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+
+ CGM.setDSOLocal(GV);
}
llvm::Constant *CodeGenModule::getBlockObjectDispose() {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
index 80e255f75417..5abf82b3f6e1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
@@ -54,6 +54,7 @@ enum BlockByrefFlags {
};
enum BlockLiteralFlags {
+ BLOCK_IS_NOESCAPE = (1 << 23),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CXX_OBJ = (1 << 26),
BLOCK_IS_GLOBAL = (1 << 28),
@@ -69,7 +70,7 @@ public:
BlockFlags() : flags(0) {}
BlockFlags(BlockLiteralFlags flag) : flags(flag) {}
BlockFlags(BlockByrefFlags flag) : flags(flag) {}
-
+
uint32_t getBitMask() const { return flags; }
bool empty() const { return flags == 0; }
@@ -207,14 +208,15 @@ public:
Capture v;
v.Data = reinterpret_cast<uintptr_t>(value);
return v;
- }
+ }
};
/// CanBeGlobal - True if the block can be global, i.e. it has
/// no non-constant captures.
bool CanBeGlobal : 1;
- /// True if the block needs a custom copy or dispose function.
+ /// True if the block has captures that would necessitate custom copy or
+ /// dispose helper functions if the block were escaping.
bool NeedsCopyDispose : 1;
/// HasCXXObject - True if the block's custom copy/dispose functions
@@ -224,13 +226,13 @@ public:
/// UsesStret : True if the block uses an stret return. Mutable
/// because it gets set later in the block-creation process.
mutable bool UsesStret : 1;
-
+
/// HasCapturedVariableLayout : True if block has captured variables
/// and their layout meta-data has been generated.
bool HasCapturedVariableLayout : 1;
/// The mapping of allocated indexes within the block.
- llvm::DenseMap<const VarDecl*, Capture> Captures;
+ llvm::DenseMap<const VarDecl*, Capture> Captures;
Address LocalAddress;
llvm::StructType *StructureType;
@@ -239,7 +241,7 @@ public:
CharUnits BlockSize;
CharUnits BlockAlign;
CharUnits CXXThisOffset;
-
+
// Offset of the gap caused by block header having a smaller
// alignment than the alignment of the block descriptor. This
// is the gap offset before the first capturued field.
@@ -276,6 +278,11 @@ public:
}
CGBlockInfo(const BlockDecl *blockDecl, StringRef Name);
+
+ // Indicates whether the block needs a custom copy or dispose function.
+ bool needsCopyDisposeHelpers() const {
+ return NeedsCopyDispose && !Block->doesNotEscape();
+ }
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
index 61fe4aac3afa..654ef72060b7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
@@ -20,7 +20,7 @@ namespace CodeGen {
class CodeGenFunction;
-/// \brief This is an IRBuilder insertion helper that forwards to
+/// This is an IRBuilder insertion helper that forwards to
/// CodeGenFunction::InsertHelper, which adds necessary metadata to
/// instructions.
class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter {
@@ -29,7 +29,7 @@ public:
explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
protected:
- /// \brief This forwards to CodeGenFunction::InsertHelper.
+ /// This forwards to CodeGenFunction::InsertHelper.
void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
llvm::BasicBlock *BB,
llvm::BasicBlock::iterator InsertPt) const;
@@ -116,7 +116,7 @@ public:
CharUnits Align, bool IsVolatile = false) {
return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile);
}
-
+
// FIXME: these "default-aligned" APIs should be removed,
// but I don't feel like fixing all the builtin code right now.
llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
@@ -244,6 +244,21 @@ public:
Addr.getAlignment().alignmentAtOffset(Offset));
}
+ using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
+ Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0,
+ unsigned Idx1, const llvm::DataLayout &DL,
+ const llvm::Twine &Name = "") {
+ auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
+ Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
+ llvm::APInt Offset(
+ DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
+ /*IsSigned=*/true);
+ if (!GEP->accumulateConstantOffset(DL, Offset))
+ llvm_unreachable("offset of GEP with constants is always computable");
+ return Address(GEP, Addr.getAlignment().alignmentAtOffset(
+ CharUnits::fromQuantity(Offset.getSExtValue())));
+ }
+
llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset,
const llvm::Twine &Name = "") {
assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
@@ -258,23 +273,23 @@ public:
using CGBuilderBaseTy::CreateMemCpy;
llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
bool IsVolatile = false) {
- auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
- return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
- Align.getQuantity(), IsVolatile);
+ return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(),
+ Src.getPointer(), Src.getAlignment().getQuantity(),
+ Size,IsVolatile);
}
llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
bool IsVolatile = false) {
- auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
- return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
- Align.getQuantity(), IsVolatile);
+ return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(),
+ Src.getPointer(), Src.getAlignment().getQuantity(),
+ Size, IsVolatile);
}
using CGBuilderBaseTy::CreateMemMove;
llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
bool IsVolatile = false) {
- auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
- return CreateMemMove(Dest.getPointer(), Src.getPointer(), Size,
- Align.getQuantity(), IsVolatile);
+ return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getQuantity(),
+ Src.getPointer(), Src.getAlignment().getQuantity(),
+ Size, IsVolatile);
}
using CGBuilderBaseTy::CreateMemSet;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
index 35ae114c4f25..e99121c46d9b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -14,6 +14,7 @@
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
+#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
@@ -188,7 +189,7 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
return RValue::get(Result);
}
-/// @brief Utility to insert an atomic cmpxchg instruction.
+/// Utility to insert an atomic cmpxchg instruction.
///
/// @param CGF The current codegen function.
/// @param E Builtin call expression to convert to cmpxchg.
@@ -319,7 +320,7 @@ static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
}
-/// \brief Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.*
+/// Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.*
/// depending on IntrinsicID.
///
/// \arg CGF The current codegen function.
@@ -384,7 +385,7 @@ EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> Types) {
}
// The encompassing type must have a width greater than or equal to the width
- // of the specified types. Aditionally, if the encompassing type is signed,
+ // of the specified types. Additionally, if the encompassing type is signed,
// its width must be strictly greater than the width of any unsigned types
// given.
unsigned Width = 0;
@@ -478,13 +479,261 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
// LLVM only supports 0 and 2, make sure that we pass along that as a boolean.
Value *Min = Builder.getInt1((Type & 2) != 0);
- // For GCC compatability, __builtin_object_size treat NULL as unknown size.
+ // For GCC compatibility, __builtin_object_size treat NULL as unknown size.
Value *NullIsUnknown = Builder.getTrue();
return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown});
}
-// Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we
-// handle them here.
+namespace {
+/// A struct to generically desribe a bit test intrinsic.
+struct BitTest {
+ enum ActionKind : uint8_t { TestOnly, Complement, Reset, Set };
+ enum InterlockingKind : uint8_t {
+ Unlocked,
+ Sequential,
+ Acquire,
+ Release,
+ NoFence
+ };
+
+ ActionKind Action;
+ InterlockingKind Interlocking;
+ bool Is64Bit;
+
+ static BitTest decodeBitTestBuiltin(unsigned BuiltinID);
+};
+} // namespace
+
+BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) {
+ switch (BuiltinID) {
+ // Main portable variants.
+ case Builtin::BI_bittest:
+ return {TestOnly, Unlocked, false};
+ case Builtin::BI_bittestandcomplement:
+ return {Complement, Unlocked, false};
+ case Builtin::BI_bittestandreset:
+ return {Reset, Unlocked, false};
+ case Builtin::BI_bittestandset:
+ return {Set, Unlocked, false};
+ case Builtin::BI_interlockedbittestandreset:
+ return {Reset, Sequential, false};
+ case Builtin::BI_interlockedbittestandset:
+ return {Set, Sequential, false};
+
+ // X86-specific 64-bit variants.
+ case Builtin::BI_bittest64:
+ return {TestOnly, Unlocked, true};
+ case Builtin::BI_bittestandcomplement64:
+ return {Complement, Unlocked, true};
+ case Builtin::BI_bittestandreset64:
+ return {Reset, Unlocked, true};
+ case Builtin::BI_bittestandset64:
+ return {Set, Unlocked, true};
+ case Builtin::BI_interlockedbittestandreset64:
+ return {Reset, Sequential, true};
+ case Builtin::BI_interlockedbittestandset64:
+ return {Set, Sequential, true};
+
+ // ARM/AArch64-specific ordering variants.
+ case Builtin::BI_interlockedbittestandset_acq:
+ return {Set, Acquire, false};
+ case Builtin::BI_interlockedbittestandset_rel:
+ return {Set, Release, false};
+ case Builtin::BI_interlockedbittestandset_nf:
+ return {Set, NoFence, false};
+ case Builtin::BI_interlockedbittestandreset_acq:
+ return {Reset, Acquire, false};
+ case Builtin::BI_interlockedbittestandreset_rel:
+ return {Reset, Release, false};
+ case Builtin::BI_interlockedbittestandreset_nf:
+ return {Reset, NoFence, false};
+ }
+ llvm_unreachable("expected only bittest intrinsics");
+}
+
+static char bitActionToX86BTCode(BitTest::ActionKind A) {
+ switch (A) {
+ case BitTest::TestOnly: return '\0';
+ case BitTest::Complement: return 'c';
+ case BitTest::Reset: return 'r';
+ case BitTest::Set: return 's';
+ }
+ llvm_unreachable("invalid action");
+}
+
+static llvm::Value *EmitX86BitTestIntrinsic(CodeGenFunction &CGF,
+ BitTest BT,
+ const CallExpr *E, Value *BitBase,
+ Value *BitPos) {
+ char Action = bitActionToX86BTCode(BT.Action);
+ char SizeSuffix = BT.Is64Bit ? 'q' : 'l';
+
+ // Build the assembly.
+ SmallString<64> Asm;
+ raw_svector_ostream AsmOS(Asm);
+ if (BT.Interlocking != BitTest::Unlocked)
+ AsmOS << "lock ";
+ AsmOS << "bt";
+ if (Action)
+ AsmOS << Action;
+ AsmOS << SizeSuffix << " $2, ($1)\n\tsetc ${0:b}";
+
+ // Build the constraints. FIXME: We should support immediates when possible.
+ std::string Constraints = "=r,r,r,~{cc},~{flags},~{fpsr}";
+ llvm::IntegerType *IntType = llvm::IntegerType::get(
+ CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(E->getArg(1)->getType()));
+ llvm::Type *IntPtrType = IntType->getPointerTo();
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGF.Int8Ty, {IntPtrType, IntType}, false);
+
+ llvm::InlineAsm *IA =
+ llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true);
+ return CGF.Builder.CreateCall(IA, {BitBase, BitPos});
+}
+
+static llvm::AtomicOrdering
+getBitTestAtomicOrdering(BitTest::InterlockingKind I) {
+ switch (I) {
+ case BitTest::Unlocked: return llvm::AtomicOrdering::NotAtomic;
+ case BitTest::Sequential: return llvm::AtomicOrdering::SequentiallyConsistent;
+ case BitTest::Acquire: return llvm::AtomicOrdering::Acquire;
+ case BitTest::Release: return llvm::AtomicOrdering::Release;
+ case BitTest::NoFence: return llvm::AtomicOrdering::Monotonic;
+ }
+ llvm_unreachable("invalid interlocking");
+}
+
+/// Emit a _bittest* intrinsic. These intrinsics take a pointer to an array of
+/// bits and a bit position and read and optionally modify the bit at that
+/// position. The position index can be arbitrarily large, i.e. it can be larger
+/// than 31 or 63, so we need an indexed load in the general case.
+static llvm::Value *EmitBitTestIntrinsic(CodeGenFunction &CGF,
+ unsigned BuiltinID,
+ const CallExpr *E) {
+ Value *BitBase = CGF.EmitScalarExpr(E->getArg(0));
+ Value *BitPos = CGF.EmitScalarExpr(E->getArg(1));
+
+ BitTest BT = BitTest::decodeBitTestBuiltin(BuiltinID);
+
+ // X86 has special BT, BTC, BTR, and BTS instructions that handle the array
+ // indexing operation internally. Use them if possible.
+ llvm::Triple::ArchType Arch = CGF.getTarget().getTriple().getArch();
+ if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64)
+ return EmitX86BitTestIntrinsic(CGF, BT, E, BitBase, BitPos);
+
+ // Otherwise, use generic code to load one byte and test the bit. Use all but
+ // the bottom three bits as the array index, and the bottom three bits to form
+ // a mask.
+ // Bit = BitBaseI8[BitPos >> 3] & (1 << (BitPos & 0x7)) != 0;
+ Value *ByteIndex = CGF.Builder.CreateAShr(
+ BitPos, llvm::ConstantInt::get(BitPos->getType(), 3), "bittest.byteidx");
+ Value *BitBaseI8 = CGF.Builder.CreatePointerCast(BitBase, CGF.Int8PtrTy);
+ Address ByteAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BitBaseI8,
+ ByteIndex, "bittest.byteaddr"),
+ CharUnits::One());
+ Value *PosLow =
+ CGF.Builder.CreateAnd(CGF.Builder.CreateTrunc(BitPos, CGF.Int8Ty),
+ llvm::ConstantInt::get(CGF.Int8Ty, 0x7));
+
+ // The updating instructions will need a mask.
+ Value *Mask = nullptr;
+ if (BT.Action != BitTest::TestOnly) {
+ Mask = CGF.Builder.CreateShl(llvm::ConstantInt::get(CGF.Int8Ty, 1), PosLow,
+ "bittest.mask");
+ }
+
+ // Check the action and ordering of the interlocked intrinsics.
+ llvm::AtomicOrdering Ordering = getBitTestAtomicOrdering(BT.Interlocking);
+
+ Value *OldByte = nullptr;
+ if (Ordering != llvm::AtomicOrdering::NotAtomic) {
+ // Emit a combined atomicrmw load/store operation for the interlocked
+ // intrinsics.
+ llvm::AtomicRMWInst::BinOp RMWOp = llvm::AtomicRMWInst::Or;
+ if (BT.Action == BitTest::Reset) {
+ Mask = CGF.Builder.CreateNot(Mask);
+ RMWOp = llvm::AtomicRMWInst::And;
+ }
+ OldByte = CGF.Builder.CreateAtomicRMW(RMWOp, ByteAddr.getPointer(), Mask,
+ Ordering);
+ } else {
+ // Emit a plain load for the non-interlocked intrinsics.
+ OldByte = CGF.Builder.CreateLoad(ByteAddr, "bittest.byte");
+ Value *NewByte = nullptr;
+ switch (BT.Action) {
+ case BitTest::TestOnly:
+ // Don't store anything.
+ break;
+ case BitTest::Complement:
+ NewByte = CGF.Builder.CreateXor(OldByte, Mask);
+ break;
+ case BitTest::Reset:
+ NewByte = CGF.Builder.CreateAnd(OldByte, CGF.Builder.CreateNot(Mask));
+ break;
+ case BitTest::Set:
+ NewByte = CGF.Builder.CreateOr(OldByte, Mask);
+ break;
+ }
+ if (NewByte)
+ CGF.Builder.CreateStore(NewByte, ByteAddr);
+ }
+
+ // However we loaded the old byte, either by plain load or atomicrmw, shift
+ // the bit into the low position and mask it to 0 or 1.
+ Value *ShiftedByte = CGF.Builder.CreateLShr(OldByte, PosLow, "bittest.shr");
+ return CGF.Builder.CreateAnd(
+ ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res");
+}
+
+namespace {
+enum class MSVCSetJmpKind {
+ _setjmpex,
+ _setjmp3,
+ _setjmp
+};
+}
+
+/// MSVC handles setjmp a bit differently on different platforms. On every
+/// architecture except 32-bit x86, the frame address is passed. On x86, extra
+/// parameters can be passed as variadic arguments, but we always pass none.
+static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind,
+ const CallExpr *E) {
+ llvm::Value *Arg1 = nullptr;
+ llvm::Type *Arg1Ty = nullptr;
+ StringRef Name;
+ bool IsVarArg = false;
+ if (SJKind == MSVCSetJmpKind::_setjmp3) {
+ Name = "_setjmp3";
+ Arg1Ty = CGF.Int32Ty;
+ Arg1 = llvm::ConstantInt::get(CGF.IntTy, 0);
+ IsVarArg = true;
+ } else {
+ Name = SJKind == MSVCSetJmpKind::_setjmp ? "_setjmp" : "_setjmpex";
+ Arg1Ty = CGF.Int8PtrTy;
+ Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::frameaddress),
+ llvm::ConstantInt::get(CGF.Int32Ty, 0));
+ }
+
+ // Mark the call site and declaration with ReturnsTwice.
+ llvm::Type *ArgTypes[2] = {CGF.Int8PtrTy, Arg1Ty};
+ llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get(
+ CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::ReturnsTwice);
+ llvm::Constant *SetJmpFn = CGF.CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(CGF.IntTy, ArgTypes, IsVarArg), Name,
+ ReturnsTwiceAttr, /*Local=*/true);
+
+ llvm::Value *Buf = CGF.Builder.CreateBitOrPointerCast(
+ CGF.EmitScalarExpr(E->getArg(0)), CGF.Int8PtrTy);
+ llvm::Value *Args[] = {Buf, Arg1};
+ llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(SetJmpFn, Args);
+ CS.setAttributes(ReturnsTwiceAttr);
+ return RValue::get(CS.getInstruction());
+}
+
+// Many of MSVC builtins are on x64, ARM and AArch64; to avoid repeating code,
+// we handle them here.
enum class CodeGenFunction::MSVCIntrin {
_BitScanForward,
_BitScanReverse,
@@ -496,7 +745,6 @@ enum class CodeGenFunction::MSVCIntrin {
_InterlockedIncrement,
_InterlockedOr,
_InterlockedXor,
- _interlockedbittestandset,
__fastfail,
};
@@ -564,22 +812,6 @@ Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID,
case MSVCIntrin::_InterlockedXor:
return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E);
- case MSVCIntrin::_interlockedbittestandset: {
- llvm::Value *Addr = EmitScalarExpr(E->getArg(0));
- llvm::Value *Bit = EmitScalarExpr(E->getArg(1));
- AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
- AtomicRMWInst::Or, Addr,
- Builder.CreateShl(ConstantInt::get(Bit->getType(), 1), Bit),
- llvm::AtomicOrdering::SequentiallyConsistent);
- // Shift the relevant bit to the least significant position, truncate to
- // the result type, and test the low bit.
- llvm::Value *Shifted = Builder.CreateLShr(RMWI, Bit);
- llvm::Value *Truncated =
- Builder.CreateTrunc(Shifted, ConvertType(E->getType()));
- return Builder.CreateAnd(Truncated,
- ConstantInt::get(Truncated->getType(), 1));
- }
-
case MSVCIntrin::_InterlockedDecrement: {
llvm::Type *IntTy = ConvertType(E->getType());
AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
@@ -930,6 +1162,96 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
return RValue::get(Overflow);
}
+static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
+ Value *&RecordPtr, CharUnits Align, Value *Func,
+ int Lvl) {
+ const auto *RT = RType->getAs<RecordType>();
+ ASTContext &Context = CGF.getContext();
+ RecordDecl *RD = RT->getDecl()->getDefinition();
+ ASTContext &Ctx = RD->getASTContext();
+ const ASTRecordLayout &RL = Ctx.getASTRecordLayout(RD);
+ std::string Pad = std::string(Lvl * 4, ' ');
+
+ Value *GString =
+ CGF.Builder.CreateGlobalStringPtr(RType.getAsString() + " {\n");
+ Value *Res = CGF.Builder.CreateCall(Func, {GString});
+
+ static llvm::DenseMap<QualType, const char *> Types;
+ if (Types.empty()) {
+ Types[Context.CharTy] = "%c";
+ Types[Context.BoolTy] = "%d";
+ Types[Context.SignedCharTy] = "%hhd";
+ Types[Context.UnsignedCharTy] = "%hhu";
+ Types[Context.IntTy] = "%d";
+ Types[Context.UnsignedIntTy] = "%u";
+ Types[Context.LongTy] = "%ld";
+ Types[Context.UnsignedLongTy] = "%lu";
+ Types[Context.LongLongTy] = "%lld";
+ Types[Context.UnsignedLongLongTy] = "%llu";
+ Types[Context.ShortTy] = "%hd";
+ Types[Context.UnsignedShortTy] = "%hu";
+ Types[Context.VoidPtrTy] = "%p";
+ Types[Context.FloatTy] = "%f";
+ Types[Context.DoubleTy] = "%f";
+ Types[Context.LongDoubleTy] = "%Lf";
+ Types[Context.getPointerType(Context.CharTy)] = "%s";
+ Types[Context.getPointerType(Context.getConstType(Context.CharTy))] = "%s";
+ }
+
+ for (const auto *FD : RD->fields()) {
+ uint64_t Off = RL.getFieldOffset(FD->getFieldIndex());
+ Off = Ctx.toCharUnitsFromBits(Off).getQuantity();
+
+ Value *FieldPtr = RecordPtr;
+ if (RD->isUnion())
+ FieldPtr = CGF.Builder.CreatePointerCast(
+ FieldPtr, CGF.ConvertType(Context.getPointerType(FD->getType())));
+ else
+ FieldPtr = CGF.Builder.CreateStructGEP(CGF.ConvertType(RType), FieldPtr,
+ FD->getFieldIndex());
+
+ GString = CGF.Builder.CreateGlobalStringPtr(
+ llvm::Twine(Pad)
+ .concat(FD->getType().getAsString())
+ .concat(llvm::Twine(' '))
+ .concat(FD->getNameAsString())
+ .concat(" : ")
+ .str());
+ Value *TmpRes = CGF.Builder.CreateCall(Func, {GString});
+ Res = CGF.Builder.CreateAdd(Res, TmpRes);
+
+ QualType CanonicalType =
+ FD->getType().getUnqualifiedType().getCanonicalType();
+
+ // We check whether we are in a recursive type
+ if (CanonicalType->isRecordType()) {
+ Value *TmpRes =
+ dumpRecord(CGF, CanonicalType, FieldPtr, Align, Func, Lvl + 1);
+ Res = CGF.Builder.CreateAdd(TmpRes, Res);
+ continue;
+ }
+
+ // We try to determine the best format to print the current field
+ llvm::Twine Format = Types.find(CanonicalType) == Types.end()
+ ? Types[Context.VoidPtrTy]
+ : Types[CanonicalType];
+
+ Address FieldAddress = Address(FieldPtr, Align);
+ FieldPtr = CGF.Builder.CreateLoad(FieldAddress);
+
+ // FIXME Need to handle bitfield here
+ GString = CGF.Builder.CreateGlobalStringPtr(
+ Format.concat(llvm::Twine('\n')).str());
+ TmpRes = CGF.Builder.CreateCall(Func, {GString, FieldPtr});
+ Res = CGF.Builder.CreateAdd(Res, TmpRes);
+ }
+
+ GString = CGF.Builder.CreateGlobalStringPtr(Pad + "}\n");
+ Value *TmpRes = CGF.Builder.CreateCall(Func, {GString});
+ Res = CGF.Builder.CreateAdd(Res, TmpRes);
+ return Res;
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -966,6 +1288,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_copysign:
case Builtin::BI__builtin_copysignf:
case Builtin::BI__builtin_copysignl:
+ case Builtin::BI__builtin_copysignf128:
return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::copysign));
case Builtin::BIcos:
@@ -998,6 +1321,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_fabs:
case Builtin::BI__builtin_fabsf:
case Builtin::BI__builtin_fabsl:
+ case Builtin::BI__builtin_fabsf128:
return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs));
case Builtin::BIfloor:
@@ -1158,16 +1482,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_abs:
case Builtin::BI__builtin_labs:
case Builtin::BI__builtin_llabs: {
+ // X < 0 ? -X : X
+ // The negation has 'nsw' because abs of INT_MIN is undefined.
Value *ArgValue = EmitScalarExpr(E->getArg(0));
-
- Value *NegOp = Builder.CreateNeg(ArgValue, "neg");
- Value *CmpResult =
- Builder.CreateICmpSGE(ArgValue,
- llvm::Constant::getNullValue(ArgValue->getType()),
- "abscond");
- Value *Result =
- Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs");
-
+ Value *NegOp = Builder.CreateNSWNeg(ArgValue, "neg");
+ Constant *Zero = llvm::Constant::getNullValue(ArgValue->getType());
+ Value *CmpResult = Builder.CreateICmpSLT(ArgValue, Zero, "abscond");
+ Value *Result = Builder.CreateSelect(CmpResult, NegOp, ArgValue, "abs");
return RValue::get(Result);
}
case Builtin::BI__builtin_conj:
@@ -1194,6 +1515,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(ComplexVal.first);
}
+ case Builtin::BI__builtin_dump_struct: {
+ Value *Func = EmitScalarExpr(E->getArg(1)->IgnoreImpCasts());
+ CharUnits Arg0Align = EmitPointerWithAlignment(E->getArg(0)).getAlignment();
+
+ const Expr *Arg0 = E->getArg(0)->IgnoreImpCasts();
+ QualType Arg0Type = Arg0->getType()->getPointeeType();
+
+ Value *RecordPtr = EmitScalarExpr(Arg0);
+ Value *Res = dumpRecord(*this, Arg0Type, RecordPtr, Arg0Align, Func, 0);
+ return RValue::get(Res);
+ }
+
case Builtin::BI__builtin_cimag:
case Builtin::BI__builtin_cimagf:
case Builtin::BI__builtin_cimagl:
@@ -1304,20 +1637,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ArgType = Val->getType();
Shift = Builder.CreateIntCast(Shift, ArgType, false);
- unsigned ArgWidth = cast<llvm::IntegerType>(ArgType)->getBitWidth();
- Value *ArgTypeSize = llvm::ConstantInt::get(ArgType, ArgWidth);
- Value *ArgZero = llvm::Constant::getNullValue(ArgType);
-
+ unsigned ArgWidth = ArgType->getIntegerBitWidth();
Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1);
- Shift = Builder.CreateAnd(Shift, Mask);
- Value *LeftShift = Builder.CreateSub(ArgTypeSize, Shift);
-
- Value *RightShifted = Builder.CreateLShr(Val, Shift);
- Value *LeftShifted = Builder.CreateShl(Val, LeftShift);
- Value *Rotated = Builder.CreateOr(LeftShifted, RightShifted);
- Value *ShiftIsZero = Builder.CreateICmpEQ(Shift, ArgZero);
- Value *Result = Builder.CreateSelect(ShiftIsZero, Val, Rotated);
+ Value *RightShiftAmt = Builder.CreateAnd(Shift, Mask);
+ Value *RightShifted = Builder.CreateLShr(Val, RightShiftAmt);
+ Value *LeftShiftAmt = Builder.CreateAnd(Builder.CreateNeg(Shift), Mask);
+ Value *LeftShifted = Builder.CreateShl(Val, LeftShiftAmt);
+ Value *Result = Builder.CreateOr(LeftShifted, RightShifted);
return RValue::get(Result);
}
case Builtin::BI_rotl8:
@@ -1330,20 +1657,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ArgType = Val->getType();
Shift = Builder.CreateIntCast(Shift, ArgType, false);
- unsigned ArgWidth = cast<llvm::IntegerType>(ArgType)->getBitWidth();
- Value *ArgTypeSize = llvm::ConstantInt::get(ArgType, ArgWidth);
- Value *ArgZero = llvm::Constant::getNullValue(ArgType);
-
+ unsigned ArgWidth = ArgType->getIntegerBitWidth();
Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1);
- Shift = Builder.CreateAnd(Shift, Mask);
- Value *RightShift = Builder.CreateSub(ArgTypeSize, Shift);
-
- Value *LeftShifted = Builder.CreateShl(Val, Shift);
- Value *RightShifted = Builder.CreateLShr(Val, RightShift);
- Value *Rotated = Builder.CreateOr(LeftShifted, RightShifted);
- Value *ShiftIsZero = Builder.CreateICmpEQ(Shift, ArgZero);
- Value *Result = Builder.CreateSelect(ShiftIsZero, Val, Rotated);
+ Value *LeftShiftAmt = Builder.CreateAnd(Shift, Mask);
+ Value *LeftShifted = Builder.CreateShl(Val, LeftShiftAmt);
+ Value *RightShiftAmt = Builder.CreateAnd(Builder.CreateNeg(Shift), Mask);
+ Value *RightShifted = Builder.CreateLShr(Val, RightShiftAmt);
+ Value *Result = Builder.CreateOr(LeftShifted, RightShifted);
return RValue::get(Result);
}
case Builtin::BI__builtin_unpredictable: {
@@ -1739,6 +2060,63 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Builder.CreateMemSet(Dest, ByteVal, SizeVal, false);
return RValue::get(Dest.getPointer());
}
+ case Builtin::BI__builtin_wmemcmp: {
+ // The MSVC runtime library does not provide a definition of wmemcmp, so we
+ // need an inline implementation.
+ if (!getTarget().getTriple().isOSMSVCRT())
+ break;
+
+ llvm::Type *WCharTy = ConvertType(getContext().WCharTy);
+
+ Value *Dst = EmitScalarExpr(E->getArg(0));
+ Value *Src = EmitScalarExpr(E->getArg(1));
+ Value *Size = EmitScalarExpr(E->getArg(2));
+
+ BasicBlock *Entry = Builder.GetInsertBlock();
+ BasicBlock *CmpGT = createBasicBlock("wmemcmp.gt");
+ BasicBlock *CmpLT = createBasicBlock("wmemcmp.lt");
+ BasicBlock *Next = createBasicBlock("wmemcmp.next");
+ BasicBlock *Exit = createBasicBlock("wmemcmp.exit");
+ Value *SizeEq0 = Builder.CreateICmpEQ(Size, ConstantInt::get(SizeTy, 0));
+ Builder.CreateCondBr(SizeEq0, Exit, CmpGT);
+
+ EmitBlock(CmpGT);
+ PHINode *DstPhi = Builder.CreatePHI(Dst->getType(), 2);
+ DstPhi->addIncoming(Dst, Entry);
+ PHINode *SrcPhi = Builder.CreatePHI(Src->getType(), 2);
+ SrcPhi->addIncoming(Src, Entry);
+ PHINode *SizePhi = Builder.CreatePHI(SizeTy, 2);
+ SizePhi->addIncoming(Size, Entry);
+ CharUnits WCharAlign =
+ getContext().getTypeAlignInChars(getContext().WCharTy);
+ Value *DstCh = Builder.CreateAlignedLoad(WCharTy, DstPhi, WCharAlign);
+ Value *SrcCh = Builder.CreateAlignedLoad(WCharTy, SrcPhi, WCharAlign);
+ Value *DstGtSrc = Builder.CreateICmpUGT(DstCh, SrcCh);
+ Builder.CreateCondBr(DstGtSrc, Exit, CmpLT);
+
+ EmitBlock(CmpLT);
+ Value *DstLtSrc = Builder.CreateICmpULT(DstCh, SrcCh);
+ Builder.CreateCondBr(DstLtSrc, Exit, Next);
+
+ EmitBlock(Next);
+ Value *NextDst = Builder.CreateConstInBoundsGEP1_32(WCharTy, DstPhi, 1);
+ Value *NextSrc = Builder.CreateConstInBoundsGEP1_32(WCharTy, SrcPhi, 1);
+ Value *NextSize = Builder.CreateSub(SizePhi, ConstantInt::get(SizeTy, 1));
+ Value *NextSizeEq0 =
+ Builder.CreateICmpEQ(NextSize, ConstantInt::get(SizeTy, 0));
+ Builder.CreateCondBr(NextSizeEq0, Exit, CmpGT);
+ DstPhi->addIncoming(NextDst, Next);
+ SrcPhi->addIncoming(NextSrc, Next);
+ SizePhi->addIncoming(NextSize, Next);
+
+ EmitBlock(Exit);
+ PHINode *Ret = Builder.CreatePHI(IntTy, 4);
+ Ret->addIncoming(ConstantInt::get(IntTy, 0), Entry);
+ Ret->addIncoming(ConstantInt::get(IntTy, 1), CmpGT);
+ Ret->addIncoming(ConstantInt::get(IntTy, -1), CmpLT);
+ Ret->addIncoming(ConstantInt::get(IntTy, 0), Next);
+ return RValue::get(Ret);
+ }
case Builtin::BI__builtin_dwarf_cfa: {
// The offset in bytes from the first argument to the CFA.
//
@@ -2037,7 +2415,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_synchronize: {
// We assume this is supposed to correspond to a C++0x-style
// sequentially-consistent fence (i.e. this is only usable for
- // synchonization, not device I/O or anything like that). This intrinsic
+ // synchronization, not device I/O or anything like that). This intrinsic
// is really badly designed in the sense that in theory, there isn't
// any way to safely use it... but in practice, it mostly works
// to use it with non-atomic loads and stores to get acquire/release
@@ -2552,11 +2930,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_addressof:
return RValue::get(EmitLValue(E->getArg(0)).getPointer());
case Builtin::BI__builtin_operator_new:
- return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
- E->getArg(0), false);
+ return EmitBuiltinNewDeleteCall(
+ E->getCallee()->getType()->castAs<FunctionProtoType>(), E, false);
case Builtin::BI__builtin_operator_delete:
- return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
- E->getArg(0), true);
+ return EmitBuiltinNewDeleteCall(
+ E->getCallee()->getType()->castAs<FunctionProtoType>(), E, true);
+
case Builtin::BI__noop:
// __noop always evaluates to an integer literal zero.
return RValue::get(ConstantInt::get(IntTy, 0));
@@ -2643,9 +3022,26 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI_InterlockedXor16:
case Builtin::BI_InterlockedXor:
return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E));
+
+ case Builtin::BI_bittest64:
+ case Builtin::BI_bittest:
+ case Builtin::BI_bittestandcomplement64:
+ case Builtin::BI_bittestandcomplement:
+ case Builtin::BI_bittestandreset64:
+ case Builtin::BI_bittestandreset:
+ case Builtin::BI_bittestandset64:
+ case Builtin::BI_bittestandset:
+ case Builtin::BI_interlockedbittestandreset:
+ case Builtin::BI_interlockedbittestandreset64:
+ case Builtin::BI_interlockedbittestandset64:
case Builtin::BI_interlockedbittestandset:
- return RValue::get(
- EmitMSVCBuiltinExpr(MSVCIntrin::_interlockedbittestandset, E));
+ case Builtin::BI_interlockedbittestandset_acq:
+ case Builtin::BI_interlockedbittestandset_rel:
+ case Builtin::BI_interlockedbittestandset_nf:
+ case Builtin::BI_interlockedbittestandreset_acq:
+ case Builtin::BI_interlockedbittestandreset_rel:
+ case Builtin::BI_interlockedbittestandreset_nf:
+ return RValue::get(EmitBitTestIntrinsic(*this, BuiltinID, E));
case Builtin::BI__exception_code:
case Builtin::BI_exception_code:
@@ -2656,59 +3052,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__abnormal_termination:
case Builtin::BI_abnormal_termination:
return RValue::get(EmitSEHAbnormalTermination());
- case Builtin::BI_setjmpex: {
- if (getTarget().getTriple().isOSMSVCRT()) {
- llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy};
- llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get(
- getLLVMContext(), llvm::AttributeList::FunctionIndex,
- llvm::Attribute::ReturnsTwice);
- llvm::Constant *SetJmpEx = CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false),
- "_setjmpex", ReturnsTwiceAttr, /*Local=*/true);
- llvm::Value *Buf = Builder.CreateBitOrPointerCast(
- EmitScalarExpr(E->getArg(0)), Int8PtrTy);
- llvm::Value *FrameAddr =
- Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress),
- ConstantInt::get(Int32Ty, 0));
- llvm::Value *Args[] = {Buf, FrameAddr};
- llvm::CallSite CS = EmitRuntimeCallOrInvoke(SetJmpEx, Args);
- CS.setAttributes(ReturnsTwiceAttr);
- return RValue::get(CS.getInstruction());
- }
+ case Builtin::BI_setjmpex:
+ if (getTarget().getTriple().isOSMSVCRT())
+ return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E);
break;
- }
- case Builtin::BI_setjmp: {
+ case Builtin::BI_setjmp:
if (getTarget().getTriple().isOSMSVCRT()) {
- llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get(
- getLLVMContext(), llvm::AttributeList::FunctionIndex,
- llvm::Attribute::ReturnsTwice);
- llvm::Value *Buf = Builder.CreateBitOrPointerCast(
- EmitScalarExpr(E->getArg(0)), Int8PtrTy);
- llvm::CallSite CS;
- if (getTarget().getTriple().getArch() == llvm::Triple::x86) {
- llvm::Type *ArgTypes[] = {Int8PtrTy, IntTy};
- llvm::Constant *SetJmp3 = CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/true),
- "_setjmp3", ReturnsTwiceAttr, /*Local=*/true);
- llvm::Value *Count = ConstantInt::get(IntTy, 0);
- llvm::Value *Args[] = {Buf, Count};
- CS = EmitRuntimeCallOrInvoke(SetJmp3, Args);
- } else {
- llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy};
- llvm::Constant *SetJmp = CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false),
- "_setjmp", ReturnsTwiceAttr, /*Local=*/true);
- llvm::Value *FrameAddr =
- Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress),
- ConstantInt::get(Int32Ty, 0));
- llvm::Value *Args[] = {Buf, FrameAddr};
- CS = EmitRuntimeCallOrInvoke(SetJmp, Args);
- }
- CS.setAttributes(ReturnsTwiceAttr);
- return RValue::get(CS.getInstruction());
+ if (getTarget().getTriple().getArch() == llvm::Triple::x86)
+ return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp3, E);
+ else if (getTarget().getTriple().getArch() == llvm::Triple::aarch64)
+ return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E);
+ return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp, E);
}
break;
- }
case Builtin::BI__GetExceptionInfo: {
if (llvm::GlobalVariable *GV =
@@ -2736,6 +3092,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return EmitCoroutineIntrinsic(E, Intrinsic::coro_resume);
case Builtin::BI__builtin_coro_frame:
return EmitCoroutineIntrinsic(E, Intrinsic::coro_frame);
+ case Builtin::BI__builtin_coro_noop:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_noop);
case Builtin::BI__builtin_coro_free:
return EmitCoroutineIntrinsic(E, Intrinsic::coro_free);
case Builtin::BI__builtin_coro_destroy:
@@ -2886,11 +3244,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// OpenCL v2.0 s6.13.16.4 Built-in pipe query functions
case Builtin::BIget_pipe_num_packets:
case Builtin::BIget_pipe_max_packets: {
- const char *Name;
+ const char *BaseName;
+ const PipeType *PipeTy = E->getArg(0)->getType()->getAs<PipeType>();
if (BuiltinID == Builtin::BIget_pipe_num_packets)
- Name = "__get_pipe_num_packets";
+ BaseName = "__get_pipe_num_packets";
else
- Name = "__get_pipe_max_packets";
+ BaseName = "__get_pipe_max_packets";
+ auto Name = std::string(BaseName) +
+ std::string(PipeTy->isReadOnly() ? "_ro" : "_wo");
// Building the generic function prototype.
Value *Arg0 = EmitScalarExpr(E->getArg(0));
@@ -2996,10 +3357,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return Ptr;
};
- // Could have events and/or vaargs.
+ // Could have events and/or varargs.
if (E->getArg(3)->getType()->isBlockPointerType()) {
// No events passed, but has variadic arguments.
- Name = "__enqueue_kernel_vaargs";
+ Name = "__enqueue_kernel_varargs";
auto Info =
CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3));
llvm::Value *Kernel =
@@ -3067,7 +3428,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Pass the number of variadics to the runtime function too.
Args.push_back(ConstantInt::get(Int32Ty, NumArgs - 7));
ArgTys.push_back(Int32Ty);
- Name = "__enqueue_kernel_events_vaargs";
+ Name = "__enqueue_kernel_events_varargs";
auto *PtrToSizeArray = CreateArrayForSizeVar(7);
Args.push_back(PtrToSizeArray);
@@ -3108,7 +3469,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy},
false),
- "__get_kernel_preferred_work_group_multiple_impl"),
+ "__get_kernel_preferred_work_group_size_multiple_impl"),
{Kernel, Arg}));
}
case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
@@ -3179,6 +3540,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__xray_customevent: {
if (!ShouldXRayInstrumentFunction())
return RValue::getIgnored();
+
+ if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
+ XRayInstrKind::Custom))
+ return RValue::getIgnored();
+
if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>())
if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayCustomEvents())
return RValue::getIgnored();
@@ -3202,6 +3568,44 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, {Arg0Val, Arg1}));
}
+ case Builtin::BI__xray_typedevent: {
+ // TODO: There should be a way to always emit events even if the current
+ // function is not instrumented. Losing events in a stream can cripple
+ // a trace.
+ if (!ShouldXRayInstrumentFunction())
+ return RValue::getIgnored();
+
+ if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
+ XRayInstrKind::Typed))
+ return RValue::getIgnored();
+
+ if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>())
+ if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayTypedEvents())
+ return RValue::getIgnored();
+
+ Function *F = CGM.getIntrinsic(Intrinsic::xray_typedevent);
+ auto FTy = F->getFunctionType();
+ auto Arg0 = EmitScalarExpr(E->getArg(0));
+ auto PTy0 = FTy->getParamType(0);
+ if (PTy0 != Arg0->getType())
+ Arg0 = Builder.CreateTruncOrBitCast(Arg0, PTy0);
+ auto Arg1 = E->getArg(1);
+ auto Arg1Val = EmitScalarExpr(Arg1);
+ auto Arg1Ty = Arg1->getType();
+ auto PTy1 = FTy->getParamType(1);
+ if (PTy1 != Arg1Val->getType()) {
+ if (Arg1Ty->isArrayType())
+ Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer();
+ else
+ Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1);
+ }
+ auto Arg2 = EmitScalarExpr(E->getArg(2));
+ auto PTy2 = FTy->getParamType(2);
+ if (PTy2 != Arg2->getType())
+ Arg2 = Builder.CreateTruncOrBitCast(Arg2, PTy2);
+ return RValue::get(Builder.CreateCall(F, {Arg0, Arg1Val, Arg2}));
+ }
+
case Builtin::BI__builtin_ms_va_start:
case Builtin::BI__builtin_ms_va_end:
return RValue::get(
@@ -3250,6 +3654,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// can move this up to the beginning of the function.
checkTargetFeatures(E, FD);
+ if (unsigned VectorWidth = getContext().BuiltinInfo.getRequiredVectorWidth(BuiltinID))
+ LargestVectorWidth = std::max(LargestVectorWidth, VectorWidth);
+
// See if we have a target specific intrinsic.
const char *Name = getContext().BuiltinInfo.getName(BuiltinID);
Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
@@ -3257,7 +3664,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch());
if (!Prefix.empty()) {
IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix.data(), Name);
- // NOTE we dont need to perform a compatibility flag check here since the
+ // NOTE we don't need to perform a compatibility flag check here since the
// intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
// MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
if (IntrinsicID == Intrinsic::not_intrinsic)
@@ -3382,7 +3789,7 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
NeonTypeFlags TypeFlags,
- llvm::Triple::ArchType Arch,
+ bool HasLegalHalfType=true,
bool V1Ty=false) {
int IsQuad = TypeFlags.isQuad();
switch (TypeFlags.getEltType()) {
@@ -3393,9 +3800,7 @@ static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
case NeonTypeFlags::Poly16:
return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Float16:
- // FIXME: Only AArch64 backend can so far properly handle half types.
- // Remove else part once ARM backend support for half is complete.
- if (Arch == llvm::Triple::aarch64)
+ if (HasLegalHalfType)
return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
else
return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
@@ -3458,7 +3863,7 @@ Value *CodeGenFunction::EmitNeonShiftVector(Value *V, llvm::Type *Ty,
return ConstantInt::get(Ty, neg ? -SV : SV);
}
-// \brief Right-shift a vector by a constant.
+// Right-shift a vector by a constant.
Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value *Shift,
llvm::Type *Ty, bool usgn,
const char *name) {
@@ -3561,13 +3966,24 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vcaleq_v, arm_neon_vacge, 0),
NEONMAP1(vcalt_v, arm_neon_vacgt, 0),
NEONMAP1(vcaltq_v, arm_neon_vacgt, 0),
+ NEONMAP0(vceqz_v),
+ NEONMAP0(vceqzq_v),
+ NEONMAP0(vcgez_v),
+ NEONMAP0(vcgezq_v),
+ NEONMAP0(vcgtz_v),
+ NEONMAP0(vcgtzq_v),
+ NEONMAP0(vclez_v),
+ NEONMAP0(vclezq_v),
NEONMAP1(vcls_v, arm_neon_vcls, Add1ArgType),
NEONMAP1(vclsq_v, arm_neon_vcls, Add1ArgType),
+ NEONMAP0(vcltz_v),
+ NEONMAP0(vcltzq_v),
NEONMAP1(vclz_v, ctlz, Add1ArgType),
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
NEONMAP1(vcvt_f16_f32, arm_neon_vcvtfp2hf, 0),
+ NEONMAP0(vcvt_f16_v),
NEONMAP1(vcvt_f32_f16, arm_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
NEONMAP2(vcvt_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
@@ -3587,6 +4003,7 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vcvta_s16_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_s32_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_s64_v, arm_neon_vcvtas, 0),
+ NEONMAP1(vcvta_u16_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvta_u32_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvta_u64_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtaq_s16_v, arm_neon_vcvtas, 0),
@@ -3631,6 +4048,7 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vcvtpq_u16_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_u32_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_u64_v, arm_neon_vcvtpu, 0),
+ NEONMAP0(vcvtq_f16_v),
NEONMAP0(vcvtq_f32_v),
NEONMAP2(vcvtq_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
@@ -3646,6 +4064,8 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP0(vcvtq_u16_v),
NEONMAP0(vcvtq_u32_v),
NEONMAP0(vcvtq_u64_v),
+ NEONMAP2(vdot_v, arm_neon_udot, arm_neon_sdot, 0),
+ NEONMAP2(vdotq_v, arm_neon_udot, arm_neon_sdot, 0),
NEONMAP0(vext_v),
NEONMAP0(vextq_v),
NEONMAP0(vfma_v),
@@ -3656,18 +4076,30 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP2(vhsubq_v, arm_neon_vhsubu, arm_neon_vhsubs, Add1ArgType | UnsignedAlts),
NEONMAP0(vld1_dup_v),
NEONMAP1(vld1_v, arm_neon_vld1, 0),
+ NEONMAP1(vld1_x2_v, arm_neon_vld1x2, 0),
+ NEONMAP1(vld1_x3_v, arm_neon_vld1x3, 0),
+ NEONMAP1(vld1_x4_v, arm_neon_vld1x4, 0),
NEONMAP0(vld1q_dup_v),
NEONMAP1(vld1q_v, arm_neon_vld1, 0),
+ NEONMAP1(vld1q_x2_v, arm_neon_vld1x2, 0),
+ NEONMAP1(vld1q_x3_v, arm_neon_vld1x3, 0),
+ NEONMAP1(vld1q_x4_v, arm_neon_vld1x4, 0),
+ NEONMAP1(vld2_dup_v, arm_neon_vld2dup, 0),
NEONMAP1(vld2_lane_v, arm_neon_vld2lane, 0),
NEONMAP1(vld2_v, arm_neon_vld2, 0),
+ NEONMAP1(vld2q_dup_v, arm_neon_vld2dup, 0),
NEONMAP1(vld2q_lane_v, arm_neon_vld2lane, 0),
NEONMAP1(vld2q_v, arm_neon_vld2, 0),
+ NEONMAP1(vld3_dup_v, arm_neon_vld3dup, 0),
NEONMAP1(vld3_lane_v, arm_neon_vld3lane, 0),
NEONMAP1(vld3_v, arm_neon_vld3, 0),
+ NEONMAP1(vld3q_dup_v, arm_neon_vld3dup, 0),
NEONMAP1(vld3q_lane_v, arm_neon_vld3lane, 0),
NEONMAP1(vld3q_v, arm_neon_vld3, 0),
+ NEONMAP1(vld4_dup_v, arm_neon_vld4dup, 0),
NEONMAP1(vld4_lane_v, arm_neon_vld4lane, 0),
NEONMAP1(vld4_v, arm_neon_vld4, 0),
+ NEONMAP1(vld4q_dup_v, arm_neon_vld4dup, 0),
NEONMAP1(vld4q_lane_v, arm_neon_vld4lane, 0),
NEONMAP1(vld4q_v, arm_neon_vld4, 0),
NEONMAP2(vmax_v, arm_neon_vmaxu, arm_neon_vmaxs, Add1ArgType | UnsignedAlts),
@@ -3726,6 +4158,8 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vrnd_v, arm_neon_vrintz, Add1ArgType),
NEONMAP1(vrnda_v, arm_neon_vrinta, Add1ArgType),
NEONMAP1(vrndaq_v, arm_neon_vrinta, Add1ArgType),
+ NEONMAP0(vrndi_v),
+ NEONMAP0(vrndiq_v),
NEONMAP1(vrndm_v, arm_neon_vrintm, Add1ArgType),
NEONMAP1(vrndmq_v, arm_neon_vrintm, Add1ArgType),
NEONMAP1(vrndn_v, arm_neon_vrintn, Add1ArgType),
@@ -3759,7 +4193,13 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP0(vshrn_n_v),
NEONMAP0(vshrq_n_v),
NEONMAP1(vst1_v, arm_neon_vst1, 0),
+ NEONMAP1(vst1_x2_v, arm_neon_vst1x2, 0),
+ NEONMAP1(vst1_x3_v, arm_neon_vst1x3, 0),
+ NEONMAP1(vst1_x4_v, arm_neon_vst1x4, 0),
NEONMAP1(vst1q_v, arm_neon_vst1, 0),
+ NEONMAP1(vst1q_x2_v, arm_neon_vst1x2, 0),
+ NEONMAP1(vst1q_x3_v, arm_neon_vst1x3, 0),
+ NEONMAP1(vst1q_x4_v, arm_neon_vst1x4, 0),
NEONMAP1(vst2_lane_v, arm_neon_vst2lane, 0),
NEONMAP1(vst2_v, arm_neon_vst2, 0),
NEONMAP1(vst2q_lane_v, arm_neon_vst2lane, 0),
@@ -3799,8 +4239,18 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vcaleq_v, aarch64_neon_facge, 0),
NEONMAP1(vcalt_v, aarch64_neon_facgt, 0),
NEONMAP1(vcaltq_v, aarch64_neon_facgt, 0),
+ NEONMAP0(vceqz_v),
+ NEONMAP0(vceqzq_v),
+ NEONMAP0(vcgez_v),
+ NEONMAP0(vcgezq_v),
+ NEONMAP0(vcgtz_v),
+ NEONMAP0(vcgtzq_v),
+ NEONMAP0(vclez_v),
+ NEONMAP0(vclezq_v),
NEONMAP1(vcls_v, aarch64_neon_cls, Add1ArgType),
NEONMAP1(vclsq_v, aarch64_neon_cls, Add1ArgType),
+ NEONMAP0(vcltz_v),
+ NEONMAP0(vcltzq_v),
NEONMAP1(vclz_v, ctlz, Add1ArgType),
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
@@ -3830,6 +4280,8 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vcvtq_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtx_f32_v, aarch64_neon_fcvtxn, AddRetType | Add1ArgType),
+ NEONMAP2(vdot_v, aarch64_neon_udot, aarch64_neon_sdot, 0),
+ NEONMAP2(vdotq_v, aarch64_neon_udot, aarch64_neon_sdot, 0),
NEONMAP0(vext_v),
NEONMAP0(vextq_v),
NEONMAP0(vfma_v),
@@ -3838,6 +4290,12 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP2(vhaddq_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts),
NEONMAP2(vhsub_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts),
NEONMAP2(vhsubq_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts),
+ NEONMAP1(vld1_x2_v, aarch64_neon_ld1x2, 0),
+ NEONMAP1(vld1_x3_v, aarch64_neon_ld1x3, 0),
+ NEONMAP1(vld1_x4_v, aarch64_neon_ld1x4, 0),
+ NEONMAP1(vld1q_x2_v, aarch64_neon_ld1x2, 0),
+ NEONMAP1(vld1q_x3_v, aarch64_neon_ld1x3, 0),
+ NEONMAP1(vld1q_x4_v, aarch64_neon_ld1x4, 0),
NEONMAP0(vmovl_v),
NEONMAP0(vmovn_v),
NEONMAP1(vmul_v, aarch64_neon_pmul, Add1ArgType),
@@ -3878,6 +4336,8 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vrecpsq_v, aarch64_neon_frecps, Add1ArgType),
NEONMAP2(vrhadd_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts),
NEONMAP2(vrhaddq_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts),
+ NEONMAP0(vrndi_v),
+ NEONMAP0(vrndiq_v),
NEONMAP2(vrshl_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts),
NEONMAP2(vrshlq_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts),
NEONMAP2(vrshr_n_v, aarch64_neon_urshl, aarch64_neon_srshl, UnsignedAlts),
@@ -3901,6 +4361,12 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP0(vshr_n_v),
NEONMAP0(vshrn_n_v),
NEONMAP0(vshrq_n_v),
+ NEONMAP1(vst1_x2_v, aarch64_neon_st1x2, 0),
+ NEONMAP1(vst1_x3_v, aarch64_neon_st1x3, 0),
+ NEONMAP1(vst1_x4_v, aarch64_neon_st1x4, 0),
+ NEONMAP1(vst1q_x2_v, aarch64_neon_st1x2, 0),
+ NEONMAP1(vst1q_x3_v, aarch64_neon_st1x3, 0),
+ NEONMAP1(vst1q_x4_v, aarch64_neon_st1x4, 0),
NEONMAP0(vsubhn_v),
NEONMAP0(vtst_v),
NEONMAP0(vtstq_v),
@@ -4099,6 +4565,37 @@ static const NeonIntrinsicInfo AArch64SISDIntrinsicMap[] = {
NEONMAP1(vuqaddd_s64, aarch64_neon_suqadd, Add1ArgType),
NEONMAP1(vuqaddh_s16, aarch64_neon_suqadd, Vectorize1ArgType | Use64BitVectors),
NEONMAP1(vuqadds_s32, aarch64_neon_suqadd, Add1ArgType),
+ // FP16 scalar intrinisics go here.
+ NEONMAP1(vabdh_f16, aarch64_sisd_fabd, Add1ArgType),
+ NEONMAP1(vcvtah_s32_f16, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtah_s64_f16, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtah_u32_f16, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtah_u64_f16, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_f16_s32, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_f16_s64, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_f16_u32, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_f16_u64, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_s32_f16, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_s64_f16, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_u32_f16, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvth_n_u64_f16, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmh_s32_f16, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmh_s64_f16, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmh_u32_f16, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmh_u64_f16, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnh_s32_f16, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnh_s64_f16, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnh_u32_f16, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnh_u64_f16, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtph_s32_f16, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtph_s64_f16, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtph_u32_f16, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtph_u64_f16, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
+ NEONMAP1(vmulxh_f16, aarch64_neon_fmulx, Add1ArgType),
+ NEONMAP1(vrecpeh_f16, aarch64_neon_frecpe, Add1ArgType),
+ NEONMAP1(vrecpxh_f16, aarch64_neon_frecpx, Add1ArgType),
+ NEONMAP1(vrsqrteh_f16, aarch64_neon_frsqrte, Add1ArgType),
+ NEONMAP1(vrsqrtsh_f16, aarch64_neon_frsqrts, Add1ArgType),
};
#undef NEONMAP0
@@ -4248,8 +4745,9 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
NeonTypeFlags Type(NeonTypeConst.getZExtValue());
bool Usgn = Type.isUnsigned();
bool Quad = Type.isQuad();
+ const bool HasLegalHalfType = getTarget().hasLegalHalfType();
- llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
+ llvm::VectorType *VTy = GetNeonType(this, Type, HasLegalHalfType);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -4314,6 +4812,26 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
return EmitNeonCall(F, Ops, NameHint);
}
+ case NEON::BI__builtin_neon_vceqz_v:
+ case NEON::BI__builtin_neon_vceqzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ,
+ ICmpInst::ICMP_EQ, "vceqz");
+ case NEON::BI__builtin_neon_vcgez_v:
+ case NEON::BI__builtin_neon_vcgezq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE,
+ ICmpInst::ICMP_SGE, "vcgez");
+ case NEON::BI__builtin_neon_vclez_v:
+ case NEON::BI__builtin_neon_vclezq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE,
+ ICmpInst::ICMP_SLE, "vclez");
+ case NEON::BI__builtin_neon_vcgtz_v:
+ case NEON::BI__builtin_neon_vcgtzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT,
+ ICmpInst::ICMP_SGT, "vcgtz");
+ case NEON::BI__builtin_neon_vcltz_v:
+ case NEON::BI__builtin_neon_vcltzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT,
+ ICmpInst::ICMP_SLT, "vcltz");
case NEON::BI__builtin_neon_vclz_v:
case NEON::BI__builtin_neon_vclzq_v:
// We generate target-independent intrinsic, which needs a second argument
@@ -4323,13 +4841,15 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvt_f32_v:
case NEON::BI__builtin_neon_vcvtq_f32_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad), Arch);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad),
+ HasLegalHalfType);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_f16_v:
case NEON::BI__builtin_neon_vcvtq_f16_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad), Arch);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad),
+ HasLegalHalfType);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_n_f16_v:
@@ -4378,6 +4898,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvta_s16_v:
case NEON::BI__builtin_neon_vcvta_s32_v:
case NEON::BI__builtin_neon_vcvta_s64_v:
+ case NEON::BI__builtin_neon_vcvta_u16_v:
case NEON::BI__builtin_neon_vcvta_u32_v:
case NEON::BI__builtin_neon_vcvta_u64_v:
case NEON::BI__builtin_neon_vcvtaq_s16_v:
@@ -4452,12 +4973,33 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Ops.push_back(getAlignmentValue32(PtrOp0));
return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "vld1");
}
+ case NEON::BI__builtin_neon_vld1_x2_v:
+ case NEON::BI__builtin_neon_vld1q_x2_v:
+ case NEON::BI__builtin_neon_vld1_x3_v:
+ case NEON::BI__builtin_neon_vld1q_x3_v:
+ case NEON::BI__builtin_neon_vld1_x4_v:
+ case NEON::BI__builtin_neon_vld1q_x4_v: {
+ llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType());
+ Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
+ llvm::Type *Tys[2] = { VTy, PTy };
+ Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
+ Ops[1] = Builder.CreateCall(F, Ops[1], "vld1xN");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
+ }
case NEON::BI__builtin_neon_vld2_v:
case NEON::BI__builtin_neon_vld2q_v:
case NEON::BI__builtin_neon_vld3_v:
case NEON::BI__builtin_neon_vld3q_v:
case NEON::BI__builtin_neon_vld4_v:
- case NEON::BI__builtin_neon_vld4q_v: {
+ case NEON::BI__builtin_neon_vld4q_v:
+ case NEON::BI__builtin_neon_vld2_dup_v:
+ case NEON::BI__builtin_neon_vld2q_dup_v:
+ case NEON::BI__builtin_neon_vld3_dup_v:
+ case NEON::BI__builtin_neon_vld3q_dup_v:
+ case NEON::BI__builtin_neon_vld4_dup_v:
+ case NEON::BI__builtin_neon_vld4q_dup_v: {
llvm::Type *Tys[] = {Ty, Int8PtrTy};
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
Value *Align = getAlignmentValue32(PtrOp1);
@@ -4556,7 +5098,10 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vrsqrteq_v:
Int = Ty->isFPOrFPVectorTy() ? LLVMIntrinsic : AltLLVMIntrinsic;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint);
-
+ case NEON::BI__builtin_neon_vrndi_v:
+ case NEON::BI__builtin_neon_vrndiq_v:
+ Int = Intrinsic::nearbyint;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint);
case NEON::BI__builtin_neon_vrshr_n_v:
case NEON::BI__builtin_neon_vrshrq_n_v:
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n",
@@ -4607,6 +5152,23 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Ops.push_back(getAlignmentValue32(PtrOp0));
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
}
+ case NEON::BI__builtin_neon_vst1_x2_v:
+ case NEON::BI__builtin_neon_vst1q_x2_v:
+ case NEON::BI__builtin_neon_vst1_x3_v:
+ case NEON::BI__builtin_neon_vst1q_x3_v:
+ case NEON::BI__builtin_neon_vst1_x4_v:
+ case NEON::BI__builtin_neon_vst1q_x4_v: {
+ llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType());
+ // TODO: Currently in AArch32 mode the pointer operand comes first, whereas
+ // in AArch64 it comes last. We may want to stick to one or another.
+ if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) {
+ llvm::Type *Tys[2] = { VTy, PTy };
+ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
+ return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "");
+ }
+ llvm::Type *Tys[2] = { PTy, VTy };
+ return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "");
+ }
case NEON::BI__builtin_neon_vsubhn_v: {
llvm::VectorType *SrcTy =
llvm::VectorType::getExtendedElementVectorType(VTy);
@@ -4689,6 +5251,14 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
}
return SV;
}
+ case NEON::BI__builtin_neon_vdot_v:
+ case NEON::BI__builtin_neon_vdotq_v: {
+ llvm::Type *InputTy =
+ llvm::VectorType::get(Int8Ty, Ty->getPrimitiveSizeInBits() / 8);
+ llvm::Type *Tys[2] = { Ty, InputTy };
+ Int = Usgn ? LLVMIntrinsic : AltLLVMIntrinsic;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vdot");
+ }
}
assert(Int && "Expected valid intrinsic number");
@@ -4897,6 +5467,34 @@ static bool HasExtraNeonArgument(unsigned BuiltinID) {
return true;
}
+Value *CodeGenFunction::EmitISOVolatileLoad(const CallExpr *E) {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ QualType ElTy = E->getArg(0)->getType()->getPointeeType();
+ CharUnits LoadSize = getContext().getTypeSizeInChars(ElTy);
+ llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(),
+ LoadSize.getQuantity() * 8);
+ Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo());
+ llvm::LoadInst *Load =
+ Builder.CreateAlignedLoad(Ptr, LoadSize);
+ Load->setVolatile(true);
+ return Load;
+}
+
+Value *CodeGenFunction::EmitISOVolatileStore(const CallExpr *E) {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ Value *Value = EmitScalarExpr(E->getArg(1));
+ QualType ElTy = E->getArg(0)->getType()->getPointeeType();
+ CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy);
+ llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(),
+ StoreSize.getQuantity() * 8);
+ Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo());
+ llvm::StoreInst *Store =
+ Builder.CreateAlignedStore(Value, Ptr,
+ StoreSize);
+ Store->setVolatile(true);
+ return Store;
+}
+
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E,
llvm::Triple::ArchType Arch) {
@@ -5139,35 +5737,13 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__iso_volatile_load8:
case ARM::BI__iso_volatile_load16:
case ARM::BI__iso_volatile_load32:
- case ARM::BI__iso_volatile_load64: {
- Value *Ptr = EmitScalarExpr(E->getArg(0));
- QualType ElTy = E->getArg(0)->getType()->getPointeeType();
- CharUnits LoadSize = getContext().getTypeSizeInChars(ElTy);
- llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(),
- LoadSize.getQuantity() * 8);
- Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo());
- llvm::LoadInst *Load =
- Builder.CreateAlignedLoad(Ptr, LoadSize);
- Load->setVolatile(true);
- return Load;
- }
+ case ARM::BI__iso_volatile_load64:
+ return EmitISOVolatileLoad(E);
case ARM::BI__iso_volatile_store8:
case ARM::BI__iso_volatile_store16:
case ARM::BI__iso_volatile_store32:
- case ARM::BI__iso_volatile_store64: {
- Value *Ptr = EmitScalarExpr(E->getArg(0));
- Value *Value = EmitScalarExpr(E->getArg(1));
- QualType ElTy = E->getArg(0)->getType()->getPointeeType();
- CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy);
- llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(),
- StoreSize.getQuantity() * 8);
- Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo());
- llvm::StoreInst *Store =
- Builder.CreateAlignedStore(Value, Ptr,
- StoreSize);
- Store->setVolatile(true);
- return Store;
- }
+ case ARM::BI__iso_volatile_store64:
+ return EmitISOVolatileStore(E);
}
if (BuiltinID == ARM::BI__builtin_arm_clrex) {
@@ -5312,8 +5888,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vld4_lane_v:
case NEON::BI__builtin_neon_vld4q_lane_v:
case NEON::BI__builtin_neon_vld2_dup_v:
+ case NEON::BI__builtin_neon_vld2q_dup_v:
case NEON::BI__builtin_neon_vld3_dup_v:
+ case NEON::BI__builtin_neon_vld3q_dup_v:
case NEON::BI__builtin_neon_vld4_dup_v:
+ case NEON::BI__builtin_neon_vld4q_dup_v:
// Get the alignment for the argument in addition to the value;
// we'll use it later.
PtrOp1 = EmitPointerWithAlignment(E->getArg(1));
@@ -5349,6 +5928,12 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vgetq_lane_f32:
return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
+ case NEON::BI__builtin_neon_vrndns_f32: {
+ Value *Arg = EmitScalarExpr(E->getArg(0));
+ llvm::Type *Tys[] = {Arg->getType()};
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vrintn, Tys);
+ return Builder.CreateCall(F, {Arg}, "vrndn"); }
+
case NEON::BI__builtin_neon_vset_lane_i8:
case NEON::BI__builtin_neon_vset_lane_i16:
case NEON::BI__builtin_neon_vset_lane_i32:
@@ -5438,7 +6023,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
bool usgn = Type.isUnsigned();
bool rightShift = false;
- llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
+ llvm::VectorType *VTy = GetNeonType(this, Type,
+ getTarget().hasLegalHalfType());
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -5483,68 +6069,6 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Value *Ld = Builder.CreateLoad(PtrOp0);
return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane");
}
- case NEON::BI__builtin_neon_vld2_dup_v:
- case NEON::BI__builtin_neon_vld3_dup_v:
- case NEON::BI__builtin_neon_vld4_dup_v: {
- // Handle 64-bit elements as a special-case. There is no "dup" needed.
- if (VTy->getElementType()->getPrimitiveSizeInBits() == 64) {
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld2_dup_v:
- Int = Intrinsic::arm_neon_vld2;
- break;
- case NEON::BI__builtin_neon_vld3_dup_v:
- Int = Intrinsic::arm_neon_vld3;
- break;
- case NEON::BI__builtin_neon_vld4_dup_v:
- Int = Intrinsic::arm_neon_vld4;
- break;
- default: llvm_unreachable("unknown vld_dup intrinsic?");
- }
- llvm::Type *Tys[] = {Ty, Int8PtrTy};
- Function *F = CGM.getIntrinsic(Int, Tys);
- llvm::Value *Align = getAlignmentValue32(PtrOp1);
- Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, "vld_dup");
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
- }
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld2_dup_v:
- Int = Intrinsic::arm_neon_vld2lane;
- break;
- case NEON::BI__builtin_neon_vld3_dup_v:
- Int = Intrinsic::arm_neon_vld3lane;
- break;
- case NEON::BI__builtin_neon_vld4_dup_v:
- Int = Intrinsic::arm_neon_vld4lane;
- break;
- default: llvm_unreachable("unknown vld_dup intrinsic?");
- }
- llvm::Type *Tys[] = {Ty, Int8PtrTy};
- Function *F = CGM.getIntrinsic(Int, Tys);
- llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType());
-
- SmallVector<Value*, 6> Args;
- Args.push_back(Ops[1]);
- Args.append(STy->getNumElements(), UndefValue::get(Ty));
-
- llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
- Args.push_back(CI);
- Args.push_back(getAlignmentValue32(PtrOp1));
-
- Ops[1] = Builder.CreateCall(F, Args, "vld_dup");
- // splat lane 0 to all elts in each vector of the result.
- for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- Value *Val = Builder.CreateExtractValue(Ops[1], i);
- Value *Elt = Builder.CreateBitCast(Val, Ty);
- Elt = EmitNeonSplat(Elt, CI);
- Elt = Builder.CreateBitCast(Elt, Val->getType());
- Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i);
- }
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
- }
case NEON::BI__builtin_neon_vqrshrn_n_v:
Int =
usgn ? Intrinsic::arm_neon_vqrshiftnu : Intrinsic::arm_neon_vqrshiftns;
@@ -5684,7 +6208,7 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID
// Determine the type of this overloaded NEON intrinsic.
NeonTypeFlags Type(Result.getZExtValue());
- llvm::VectorType *Ty = GetNeonType(&CGF, Type, Arch);
+ llvm::VectorType *Ty = GetNeonType(&CGF, Type);
if (!Ty)
return nullptr;
@@ -5803,18 +6327,23 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
HintID = 0;
break;
case AArch64::BI__builtin_arm_yield:
+ case AArch64::BI__yield:
HintID = 1;
break;
case AArch64::BI__builtin_arm_wfe:
+ case AArch64::BI__wfe:
HintID = 2;
break;
case AArch64::BI__builtin_arm_wfi:
+ case AArch64::BI__wfi:
HintID = 3;
break;
case AArch64::BI__builtin_arm_sev:
+ case AArch64::BI__sev:
HintID = 4;
break;
case AArch64::BI__builtin_arm_sevl:
+ case AArch64::BI__sevl:
HintID = 5;
break;
}
@@ -6081,6 +6610,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
// Handle non-overloaded intrinsics first.
switch (BuiltinID) {
default: break;
+ case NEON::BI__builtin_neon_vabsh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, HalfTy), Ops, "vabs");
case NEON::BI__builtin_neon_vldrq_p128: {
llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
llvm::Type *Int128PTy = llvm::PointerType::get(Int128Ty, 0);
@@ -6123,6 +6655,153 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return Builder.CreateUIToFP(Ops[0], FTy);
return Builder.CreateSIToFP(Ops[0], FTy);
}
+ case NEON::BI__builtin_neon_vcvth_f16_u16:
+ case NEON::BI__builtin_neon_vcvth_f16_u32:
+ case NEON::BI__builtin_neon_vcvth_f16_u64:
+ usgn = true;
+ // FALL THROUGH
+ case NEON::BI__builtin_neon_vcvth_f16_s16:
+ case NEON::BI__builtin_neon_vcvth_f16_s32:
+ case NEON::BI__builtin_neon_vcvth_f16_s64: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ llvm::Type *FTy = HalfTy;
+ llvm::Type *InTy;
+ if (Ops[0]->getType()->getPrimitiveSizeInBits() == 64)
+ InTy = Int64Ty;
+ else if (Ops[0]->getType()->getPrimitiveSizeInBits() == 32)
+ InTy = Int32Ty;
+ else
+ InTy = Int16Ty;
+ Ops[0] = Builder.CreateBitCast(Ops[0], InTy);
+ if (usgn)
+ return Builder.CreateUIToFP(Ops[0], FTy);
+ return Builder.CreateSIToFP(Ops[0], FTy);
+ }
+ case NEON::BI__builtin_neon_vcvth_u16_f16:
+ usgn = true;
+ // FALL THROUGH
+ case NEON::BI__builtin_neon_vcvth_s16_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
+ if (usgn)
+ return Builder.CreateFPToUI(Ops[0], Int16Ty);
+ return Builder.CreateFPToSI(Ops[0], Int16Ty);
+ }
+ case NEON::BI__builtin_neon_vcvth_u32_f16:
+ usgn = true;
+ // FALL THROUGH
+ case NEON::BI__builtin_neon_vcvth_s32_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
+ if (usgn)
+ return Builder.CreateFPToUI(Ops[0], Int32Ty);
+ return Builder.CreateFPToSI(Ops[0], Int32Ty);
+ }
+ case NEON::BI__builtin_neon_vcvth_u64_f16:
+ usgn = true;
+ // FALL THROUGH
+ case NEON::BI__builtin_neon_vcvth_s64_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
+ if (usgn)
+ return Builder.CreateFPToUI(Ops[0], Int64Ty);
+ return Builder.CreateFPToSI(Ops[0], Int64Ty);
+ }
+ case NEON::BI__builtin_neon_vcvtah_u16_f16:
+ case NEON::BI__builtin_neon_vcvtmh_u16_f16:
+ case NEON::BI__builtin_neon_vcvtnh_u16_f16:
+ case NEON::BI__builtin_neon_vcvtph_u16_f16:
+ case NEON::BI__builtin_neon_vcvtah_s16_f16:
+ case NEON::BI__builtin_neon_vcvtmh_s16_f16:
+ case NEON::BI__builtin_neon_vcvtnh_s16_f16:
+ case NEON::BI__builtin_neon_vcvtph_s16_f16: {
+ unsigned Int;
+ llvm::Type* InTy = Int32Ty;
+ llvm::Type* FTy = HalfTy;
+ llvm::Type *Tys[2] = {InTy, FTy};
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ switch (BuiltinID) {
+ default: llvm_unreachable("missing builtin ID in switch!");
+ case NEON::BI__builtin_neon_vcvtah_u16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtau; break;
+ case NEON::BI__builtin_neon_vcvtmh_u16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtmu; break;
+ case NEON::BI__builtin_neon_vcvtnh_u16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtnu; break;
+ case NEON::BI__builtin_neon_vcvtph_u16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtpu; break;
+ case NEON::BI__builtin_neon_vcvtah_s16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtas; break;
+ case NEON::BI__builtin_neon_vcvtmh_s16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtms; break;
+ case NEON::BI__builtin_neon_vcvtnh_s16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtns; break;
+ case NEON::BI__builtin_neon_vcvtph_s16_f16:
+ Int = Intrinsic::aarch64_neon_fcvtps; break;
+ }
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvt");
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
+ }
+ case NEON::BI__builtin_neon_vcaleh_f16:
+ case NEON::BI__builtin_neon_vcalth_f16:
+ case NEON::BI__builtin_neon_vcageh_f16:
+ case NEON::BI__builtin_neon_vcagth_f16: {
+ unsigned Int;
+ llvm::Type* InTy = Int32Ty;
+ llvm::Type* FTy = HalfTy;
+ llvm::Type *Tys[2] = {InTy, FTy};
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ switch (BuiltinID) {
+ default: llvm_unreachable("missing builtin ID in switch!");
+ case NEON::BI__builtin_neon_vcageh_f16:
+ Int = Intrinsic::aarch64_neon_facge; break;
+ case NEON::BI__builtin_neon_vcagth_f16:
+ Int = Intrinsic::aarch64_neon_facgt; break;
+ case NEON::BI__builtin_neon_vcaleh_f16:
+ Int = Intrinsic::aarch64_neon_facge; std::swap(Ops[0], Ops[1]); break;
+ case NEON::BI__builtin_neon_vcalth_f16:
+ Int = Intrinsic::aarch64_neon_facgt; std::swap(Ops[0], Ops[1]); break;
+ }
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "facg");
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
+ }
+ case NEON::BI__builtin_neon_vcvth_n_s16_f16:
+ case NEON::BI__builtin_neon_vcvth_n_u16_f16: {
+ unsigned Int;
+ llvm::Type* InTy = Int32Ty;
+ llvm::Type* FTy = HalfTy;
+ llvm::Type *Tys[2] = {InTy, FTy};
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ switch (BuiltinID) {
+ default: llvm_unreachable("missing builtin ID in switch!");
+ case NEON::BI__builtin_neon_vcvth_n_s16_f16:
+ Int = Intrinsic::aarch64_neon_vcvtfp2fxs; break;
+ case NEON::BI__builtin_neon_vcvth_n_u16_f16:
+ Int = Intrinsic::aarch64_neon_vcvtfp2fxu; break;
+ }
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvth_n");
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
+ }
+ case NEON::BI__builtin_neon_vcvth_n_f16_s16:
+ case NEON::BI__builtin_neon_vcvth_n_f16_u16: {
+ unsigned Int;
+ llvm::Type* FTy = HalfTy;
+ llvm::Type* InTy = Int32Ty;
+ llvm::Type *Tys[2] = {FTy, InTy};
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ switch (BuiltinID) {
+ default: llvm_unreachable("missing builtin ID in switch!");
+ case NEON::BI__builtin_neon_vcvth_n_f16_s16:
+ Int = Intrinsic::aarch64_neon_vcvtfxs2fp;
+ Ops[0] = Builder.CreateSExt(Ops[0], InTy, "sext");
+ break;
+ case NEON::BI__builtin_neon_vcvth_n_f16_u16:
+ Int = Intrinsic::aarch64_neon_vcvtfxu2fp;
+ Ops[0] = Builder.CreateZExt(Ops[0], InTy);
+ break;
+ }
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvth_n");
+ }
case NEON::BI__builtin_neon_vpaddd_s64: {
llvm::Type *Ty = llvm::VectorType::get(Int64Ty, 2);
Value *Vec = EmitScalarExpr(E->getArg(0));
@@ -6164,6 +6843,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vceqzd_s64:
case NEON::BI__builtin_neon_vceqzd_f64:
case NEON::BI__builtin_neon_vceqzs_f32:
+ case NEON::BI__builtin_neon_vceqzh_f16:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
Ops[0], ConvertType(E->getCallReturnType(getContext())),
@@ -6171,6 +6851,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcgezd_s64:
case NEON::BI__builtin_neon_vcgezd_f64:
case NEON::BI__builtin_neon_vcgezs_f32:
+ case NEON::BI__builtin_neon_vcgezh_f16:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
Ops[0], ConvertType(E->getCallReturnType(getContext())),
@@ -6178,6 +6859,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vclezd_s64:
case NEON::BI__builtin_neon_vclezd_f64:
case NEON::BI__builtin_neon_vclezs_f32:
+ case NEON::BI__builtin_neon_vclezh_f16:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
Ops[0], ConvertType(E->getCallReturnType(getContext())),
@@ -6185,6 +6867,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcgtzd_s64:
case NEON::BI__builtin_neon_vcgtzd_f64:
case NEON::BI__builtin_neon_vcgtzs_f32:
+ case NEON::BI__builtin_neon_vcgtzh_f16:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
Ops[0], ConvertType(E->getCallReturnType(getContext())),
@@ -6192,6 +6875,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcltzd_s64:
case NEON::BI__builtin_neon_vcltzd_f64:
case NEON::BI__builtin_neon_vcltzs_f32:
+ case NEON::BI__builtin_neon_vcltzh_f16:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
Ops[0], ConvertType(E->getCallReturnType(getContext())),
@@ -6244,6 +6928,26 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]);
return Builder.CreateSExt(Ops[0], Int32Ty, "vcmpd");
}
+ case NEON::BI__builtin_neon_vceqh_f16:
+ case NEON::BI__builtin_neon_vcleh_f16:
+ case NEON::BI__builtin_neon_vclth_f16:
+ case NEON::BI__builtin_neon_vcgeh_f16:
+ case NEON::BI__builtin_neon_vcgth_f16: {
+ llvm::CmpInst::Predicate P;
+ switch (BuiltinID) {
+ default: llvm_unreachable("missing builtin ID in switch!");
+ case NEON::BI__builtin_neon_vceqh_f16: P = llvm::FCmpInst::FCMP_OEQ; break;
+ case NEON::BI__builtin_neon_vcleh_f16: P = llvm::FCmpInst::FCMP_OLE; break;
+ case NEON::BI__builtin_neon_vclth_f16: P = llvm::FCmpInst::FCMP_OLT; break;
+ case NEON::BI__builtin_neon_vcgeh_f16: P = llvm::FCmpInst::FCMP_OGE; break;
+ case NEON::BI__builtin_neon_vcgth_f16: P = llvm::FCmpInst::FCMP_OGT; break;
+ }
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], HalfTy);
+ Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]);
+ return Builder.CreateSExt(Ops[0], Int16Ty, "vcmpd");
+ }
case NEON::BI__builtin_neon_vceqd_s64:
case NEON::BI__builtin_neon_vceqd_u64:
case NEON::BI__builtin_neon_vcgtd_s64:
@@ -6381,6 +7085,31 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::VectorType::get(DoubleTy, 2));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
+ case NEON::BI__builtin_neon_vaddh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ return Builder.CreateFAdd(Ops[0], Ops[1], "vaddh");
+ case NEON::BI__builtin_neon_vsubh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ return Builder.CreateFSub(Ops[0], Ops[1], "vsubh");
+ case NEON::BI__builtin_neon_vmulh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ return Builder.CreateFMul(Ops[0], Ops[1], "vmulh");
+ case NEON::BI__builtin_neon_vdivh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ return Builder.CreateFDiv(Ops[0], Ops[1], "vdivh");
+ case NEON::BI__builtin_neon_vfmah_f16: {
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, HalfTy);
+ // NEON intrinsic puts accumulator first, unlike the LLVM fma.
+ return Builder.CreateCall(F,
+ {EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), Ops[0]});
+ }
+ case NEON::BI__builtin_neon_vfmsh_f16: {
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, HalfTy);
+ Value *Zero = llvm::ConstantFP::getZeroValueForNegation(HalfTy);
+ Value* Sub = Builder.CreateFSub(Zero, EmitScalarExpr(E->getArg(1)), "vsubh");
+ // NEON intrinsic puts accumulator first, unlike the LLVM fma.
+ return Builder.CreateCall(F, {Sub, EmitScalarExpr(E->getArg(2)), Ops[0]});
+ }
case NEON::BI__builtin_neon_vaddd_s64:
case NEON::BI__builtin_neon_vaddd_u64:
return Builder.CreateAdd(Ops[0], EmitScalarExpr(E->getArg(1)), "vaddd");
@@ -6538,7 +7267,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
}
- llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
+ llvm::VectorType *VTy = GetNeonType(this, Type);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -6603,7 +7332,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, true), Arch);
+ NeonTypeFlags(NeonTypeFlags::Float64, false, true));
Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
@@ -6655,12 +7384,22 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = usgn ? Intrinsic::aarch64_neon_umax : Intrinsic::aarch64_neon_smax;
if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmax;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmax");
+ case NEON::BI__builtin_neon_vmaxh_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ Int = Intrinsic::aarch64_neon_fmax;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmax");
+ }
case NEON::BI__builtin_neon_vmin_v:
case NEON::BI__builtin_neon_vminq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
Int = usgn ? Intrinsic::aarch64_neon_umin : Intrinsic::aarch64_neon_smin;
if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmin;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmin");
+ case NEON::BI__builtin_neon_vminh_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ Int = Intrinsic::aarch64_neon_fmin;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmin");
+ }
case NEON::BI__builtin_neon_vabd_v:
case NEON::BI__builtin_neon_vabdq_v:
// FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics.
@@ -6699,20 +7438,31 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vminnmq_v:
Int = Intrinsic::aarch64_neon_fminnm;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm");
+ case NEON::BI__builtin_neon_vminnmh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ Int = Intrinsic::aarch64_neon_fminnm;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vminnm");
case NEON::BI__builtin_neon_vmaxnm_v:
case NEON::BI__builtin_neon_vmaxnmq_v:
Int = Intrinsic::aarch64_neon_fmaxnm;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm");
+ case NEON::BI__builtin_neon_vmaxnmh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ Int = Intrinsic::aarch64_neon_fmaxnm;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmaxnm");
case NEON::BI__builtin_neon_vrecpss_f32: {
Ops.push_back(EmitScalarExpr(E->getArg(1)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, FloatTy),
Ops, "vrecps");
}
- case NEON::BI__builtin_neon_vrecpsd_f64: {
+ case NEON::BI__builtin_neon_vrecpsd_f64:
Ops.push_back(EmitScalarExpr(E->getArg(1)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, DoubleTy),
Ops, "vrecps");
- }
+ case NEON::BI__builtin_neon_vrecpsh_f16:
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, HalfTy),
+ Ops, "vrecps");
case NEON::BI__builtin_neon_vqshrun_n_v:
Int = Intrinsic::aarch64_neon_sqshrun;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n");
@@ -6728,72 +7478,87 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vqrshrn_n_v:
Int = usgn ? Intrinsic::aarch64_neon_uqrshrn : Intrinsic::aarch64_neon_sqrshrn;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n");
+ case NEON::BI__builtin_neon_vrndah_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::round;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrnda");
+ }
case NEON::BI__builtin_neon_vrnda_v:
case NEON::BI__builtin_neon_vrndaq_v: {
Int = Intrinsic::round;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnda");
}
- case NEON::BI__builtin_neon_vrndi_v:
- case NEON::BI__builtin_neon_vrndiq_v: {
+ case NEON::BI__builtin_neon_vrndih_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
Int = Intrinsic::nearbyint;
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndi");
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndi");
+ }
+ case NEON::BI__builtin_neon_vrndmh_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::floor;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndm");
}
case NEON::BI__builtin_neon_vrndm_v:
case NEON::BI__builtin_neon_vrndmq_v: {
Int = Intrinsic::floor;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndm");
}
+ case NEON::BI__builtin_neon_vrndnh_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::aarch64_neon_frintn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndn");
+ }
case NEON::BI__builtin_neon_vrndn_v:
case NEON::BI__builtin_neon_vrndnq_v: {
Int = Intrinsic::aarch64_neon_frintn;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn");
}
+ case NEON::BI__builtin_neon_vrndns_f32: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::aarch64_neon_frintn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, FloatTy), Ops, "vrndn");
+ }
+ case NEON::BI__builtin_neon_vrndph_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::ceil;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndp");
+ }
case NEON::BI__builtin_neon_vrndp_v:
case NEON::BI__builtin_neon_vrndpq_v: {
Int = Intrinsic::ceil;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndp");
}
+ case NEON::BI__builtin_neon_vrndxh_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::rint;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndx");
+ }
case NEON::BI__builtin_neon_vrndx_v:
case NEON::BI__builtin_neon_vrndxq_v: {
Int = Intrinsic::rint;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndx");
}
+ case NEON::BI__builtin_neon_vrndh_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::trunc;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndz");
+ }
case NEON::BI__builtin_neon_vrnd_v:
case NEON::BI__builtin_neon_vrndq_v: {
Int = Intrinsic::trunc;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndz");
}
- case NEON::BI__builtin_neon_vceqz_v:
- case NEON::BI__builtin_neon_vceqzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ,
- ICmpInst::ICMP_EQ, "vceqz");
- case NEON::BI__builtin_neon_vcgez_v:
- case NEON::BI__builtin_neon_vcgezq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE,
- ICmpInst::ICMP_SGE, "vcgez");
- case NEON::BI__builtin_neon_vclez_v:
- case NEON::BI__builtin_neon_vclezq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE,
- ICmpInst::ICMP_SLE, "vclez");
- case NEON::BI__builtin_neon_vcgtz_v:
- case NEON::BI__builtin_neon_vcgtzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT,
- ICmpInst::ICMP_SGT, "vcgtz");
- case NEON::BI__builtin_neon_vcltz_v:
- case NEON::BI__builtin_neon_vcltzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT,
- ICmpInst::ICMP_SLT, "vcltz");
case NEON::BI__builtin_neon_vcvt_f64_v:
case NEON::BI__builtin_neon_vcvtq_f64_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad), Arch);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_f64_f32: {
assert(Type.getEltType() == NeonTypeFlags::Float64 && quad &&
"unexpected vcvt_f64_f32 builtin");
NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float32, false, false);
- Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch));
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
return Builder.CreateFPExt(Ops[0], Ty, "vcvt");
}
@@ -6801,7 +7566,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
assert(Type.getEltType() == NeonTypeFlags::Float32 &&
"unexpected vcvt_f32_f64 builtin");
NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float64, false, true);
- Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch));
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt");
}
@@ -6809,20 +7574,21 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvt_u32_v:
case NEON::BI__builtin_neon_vcvt_s64_v:
case NEON::BI__builtin_neon_vcvt_u64_v:
- case NEON::BI__builtin_neon_vcvt_s16_v:
- case NEON::BI__builtin_neon_vcvt_u16_v:
+ case NEON::BI__builtin_neon_vcvt_s16_v:
+ case NEON::BI__builtin_neon_vcvt_u16_v:
case NEON::BI__builtin_neon_vcvtq_s32_v:
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
case NEON::BI__builtin_neon_vcvtq_u64_v:
- case NEON::BI__builtin_neon_vcvtq_s16_v:
- case NEON::BI__builtin_neon_vcvtq_u16_v: {
+ case NEON::BI__builtin_neon_vcvtq_s16_v:
+ case NEON::BI__builtin_neon_vcvtq_u16_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
if (usgn)
return Builder.CreateFPToUI(Ops[0], Ty);
return Builder.CreateFPToSI(Ops[0], Ty);
}
case NEON::BI__builtin_neon_vcvta_s16_v:
+ case NEON::BI__builtin_neon_vcvta_u16_v:
case NEON::BI__builtin_neon_vcvta_s32_v:
case NEON::BI__builtin_neon_vcvtaq_s16_v:
case NEON::BI__builtin_neon_vcvtaq_s32_v:
@@ -6890,6 +7656,16 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = Intrinsic::aarch64_neon_fmulx;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
}
+ case NEON::BI__builtin_neon_vmulxh_lane_f16:
+ case NEON::BI__builtin_neon_vmulxh_laneq_f16: {
+ // vmulx_lane should be mapped to Neon scalar mulx after
+ // extracting the scalar element
+ Ops.push_back(EmitScalarExpr(E->getArg(2)));
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
+ Ops.pop_back();
+ Int = Intrinsic::aarch64_neon_fmulx;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmulx");
+ }
case NEON::BI__builtin_neon_vmul_lane_v:
case NEON::BI__builtin_neon_vmul_laneq_v: {
// v1f64 vmul_lane should be mapped to Neon scalar mul lane
@@ -6898,7 +7674,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Quad = true;
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, Quad), Arch);
+ NeonTypeFlags(NeonTypeFlags::Float64, false, Quad));
Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);
@@ -6906,6 +7682,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vnegd_s64:
return Builder.CreateNeg(EmitScalarExpr(E->getArg(0)), "vnegd");
+ case NEON::BI__builtin_neon_vnegh_f16:
+ return Builder.CreateFNeg(EmitScalarExpr(E->getArg(0)), "vnegh");
case NEON::BI__builtin_neon_vpmaxnm_v:
case NEON::BI__builtin_neon_vpmaxnmq_v: {
Int = Intrinsic::aarch64_neon_fmaxnmp;
@@ -6916,6 +7694,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = Intrinsic::aarch64_neon_fminnmp;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm");
}
+ case NEON::BI__builtin_neon_vsqrth_f16: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::sqrt;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vsqrt");
+ }
case NEON::BI__builtin_neon_vsqrt_v:
case NEON::BI__builtin_neon_vsqrtq_v: {
Int = Intrinsic::sqrt;
@@ -7293,64 +8076,6 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], VTy);
return Builder.CreateAdd(Ops[0], tmp);
}
- // FIXME: Sharing loads & stores with 32-bit is complicated by the absence
- // of an Align parameter here.
- case NEON::BI__builtin_neon_vld1_x2_v:
- case NEON::BI__builtin_neon_vld1q_x2_v:
- case NEON::BI__builtin_neon_vld1_x3_v:
- case NEON::BI__builtin_neon_vld1q_x3_v:
- case NEON::BI__builtin_neon_vld1_x4_v:
- case NEON::BI__builtin_neon_vld1q_x4_v: {
- llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType());
- Ops[1] = Builder.CreateBitCast(Ops[1], PTy);
- llvm::Type *Tys[2] = { VTy, PTy };
- unsigned Int;
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vld1_x2_v:
- case NEON::BI__builtin_neon_vld1q_x2_v:
- Int = Intrinsic::aarch64_neon_ld1x2;
- break;
- case NEON::BI__builtin_neon_vld1_x3_v:
- case NEON::BI__builtin_neon_vld1q_x3_v:
- Int = Intrinsic::aarch64_neon_ld1x3;
- break;
- case NEON::BI__builtin_neon_vld1_x4_v:
- case NEON::BI__builtin_neon_vld1q_x4_v:
- Int = Intrinsic::aarch64_neon_ld1x4;
- break;
- }
- Function *F = CGM.getIntrinsic(Int, Tys);
- Ops[1] = Builder.CreateCall(F, Ops[1], "vld1xN");
- Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
- }
- case NEON::BI__builtin_neon_vst1_x2_v:
- case NEON::BI__builtin_neon_vst1q_x2_v:
- case NEON::BI__builtin_neon_vst1_x3_v:
- case NEON::BI__builtin_neon_vst1q_x3_v:
- case NEON::BI__builtin_neon_vst1_x4_v:
- case NEON::BI__builtin_neon_vst1q_x4_v: {
- llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType());
- llvm::Type *Tys[2] = { VTy, PTy };
- unsigned Int;
- switch (BuiltinID) {
- case NEON::BI__builtin_neon_vst1_x2_v:
- case NEON::BI__builtin_neon_vst1q_x2_v:
- Int = Intrinsic::aarch64_neon_st1x2;
- break;
- case NEON::BI__builtin_neon_vst1_x3_v:
- case NEON::BI__builtin_neon_vst1q_x3_v:
- Int = Intrinsic::aarch64_neon_st1x3;
- break;
- case NEON::BI__builtin_neon_vst1_x4_v:
- case NEON::BI__builtin_neon_vst1q_x4_v:
- Int = Intrinsic::aarch64_neon_st1x4;
- break;
- }
- std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
- return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
- }
case NEON::BI__builtin_neon_vld1_v:
case NEON::BI__builtin_neon_vld1q_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy));
@@ -7657,6 +8382,38 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = Intrinsic::aarch64_neon_suqadd;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd");
}
+ case AArch64::BI__iso_volatile_load8:
+ case AArch64::BI__iso_volatile_load16:
+ case AArch64::BI__iso_volatile_load32:
+ case AArch64::BI__iso_volatile_load64:
+ return EmitISOVolatileLoad(E);
+ case AArch64::BI__iso_volatile_store8:
+ case AArch64::BI__iso_volatile_store16:
+ case AArch64::BI__iso_volatile_store32:
+ case AArch64::BI__iso_volatile_store64:
+ return EmitISOVolatileStore(E);
+ case AArch64::BI_BitScanForward:
+ case AArch64::BI_BitScanForward64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E);
+ case AArch64::BI_BitScanReverse:
+ case AArch64::BI_BitScanReverse64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E);
+ case AArch64::BI_InterlockedAnd64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E);
+ case AArch64::BI_InterlockedExchange64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E);
+ case AArch64::BI_InterlockedExchangeAdd64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E);
+ case AArch64::BI_InterlockedExchangeSub64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E);
+ case AArch64::BI_InterlockedOr64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E);
+ case AArch64::BI_InterlockedXor64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E);
+ case AArch64::BI_InterlockedDecrement64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
+ case AArch64::BI_InterlockedIncrement64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
}
}
@@ -7708,42 +8465,66 @@ static Value *getMaskVecValue(CodeGenFunction &CGF, Value *Mask,
}
static Value *EmitX86MaskedStore(CodeGenFunction &CGF,
- SmallVectorImpl<Value *> &Ops,
+ ArrayRef<Value *> Ops,
unsigned Align) {
// Cast the pointer to right type.
- Ops[0] = CGF.Builder.CreateBitCast(Ops[0],
+ Value *Ptr = CGF.Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- // If the mask is all ones just emit a regular store.
- if (const auto *C = dyn_cast<Constant>(Ops[2]))
- if (C->isAllOnesValue())
- return CGF.Builder.CreateAlignedStore(Ops[1], Ops[0], Align);
-
Value *MaskVec = getMaskVecValue(CGF, Ops[2],
Ops[1]->getType()->getVectorNumElements());
- return CGF.Builder.CreateMaskedStore(Ops[1], Ops[0], Align, MaskVec);
+ return CGF.Builder.CreateMaskedStore(Ops[1], Ptr, Align, MaskVec);
}
static Value *EmitX86MaskedLoad(CodeGenFunction &CGF,
- SmallVectorImpl<Value *> &Ops, unsigned Align) {
+ ArrayRef<Value *> Ops, unsigned Align) {
// Cast the pointer to right type.
- Ops[0] = CGF.Builder.CreateBitCast(Ops[0],
+ Value *Ptr = CGF.Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- // If the mask is all ones just emit a regular store.
- if (const auto *C = dyn_cast<Constant>(Ops[2]))
- if (C->isAllOnesValue())
- return CGF.Builder.CreateAlignedLoad(Ops[0], Align);
-
Value *MaskVec = getMaskVecValue(CGF, Ops[2],
Ops[1]->getType()->getVectorNumElements());
- return CGF.Builder.CreateMaskedLoad(Ops[0], Align, MaskVec, Ops[1]);
+ return CGF.Builder.CreateMaskedLoad(Ptr, Align, MaskVec, Ops[1]);
+}
+
+static Value *EmitX86ExpandLoad(CodeGenFunction &CGF,
+ ArrayRef<Value *> Ops) {
+ llvm::Type *ResultTy = Ops[1]->getType();
+ llvm::Type *PtrTy = ResultTy->getVectorElementType();
+
+ // Cast the pointer to element type.
+ Value *Ptr = CGF.Builder.CreateBitCast(Ops[0],
+ llvm::PointerType::getUnqual(PtrTy));
+
+ Value *MaskVec = getMaskVecValue(CGF, Ops[2],
+ ResultTy->getVectorNumElements());
+
+ llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_expandload,
+ ResultTy);
+ return CGF.Builder.CreateCall(F, { Ptr, MaskVec, Ops[1] });
+}
+
+static Value *EmitX86CompressStore(CodeGenFunction &CGF,
+ ArrayRef<Value *> Ops) {
+ llvm::Type *ResultTy = Ops[1]->getType();
+ llvm::Type *PtrTy = ResultTy->getVectorElementType();
+
+ // Cast the pointer to element type.
+ Value *Ptr = CGF.Builder.CreateBitCast(Ops[0],
+ llvm::PointerType::getUnqual(PtrTy));
+
+ Value *MaskVec = getMaskVecValue(CGF, Ops[2],
+ ResultTy->getVectorNumElements());
+
+ llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_compressstore,
+ ResultTy);
+ return CGF.Builder.CreateCall(F, { Ops[1], Ptr, MaskVec });
}
static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc,
- unsigned NumElts, SmallVectorImpl<Value *> &Ops,
+ unsigned NumElts, ArrayRef<Value *> Ops,
bool InvertLHS = false) {
Value *LHS = getMaskVecValue(CGF, Ops[0], NumElts);
Value *RHS = getMaskVecValue(CGF, Ops[1], NumElts);
@@ -7755,26 +8536,6 @@ static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc,
CGF.Builder.getIntNTy(std::max(NumElts, 8U)));
}
-static Value *EmitX86SubVectorBroadcast(CodeGenFunction &CGF,
- SmallVectorImpl<Value *> &Ops,
- llvm::Type *DstTy,
- unsigned SrcSizeInBits,
- unsigned Align) {
- // Load the subvector.
- Ops[0] = CGF.Builder.CreateAlignedLoad(Ops[0], Align);
-
- // Create broadcast mask.
- unsigned NumDstElts = DstTy->getVectorNumElements();
- unsigned NumSrcElts = SrcSizeInBits / DstTy->getScalarSizeInBits();
-
- SmallVector<uint32_t, 8> Mask;
- for (unsigned i = 0; i != NumDstElts; i += NumSrcElts)
- for (unsigned j = 0; j != NumSrcElts; ++j)
- Mask.push_back(j);
-
- return CGF.Builder.CreateShuffleVector(Ops[0], Ops[0], Mask, "subvecbcst");
-}
-
static Value *EmitX86Select(CodeGenFunction &CGF,
Value *Mask, Value *Op0, Value *Op1) {
@@ -7788,8 +8549,48 @@ static Value *EmitX86Select(CodeGenFunction &CGF,
return CGF.Builder.CreateSelect(Mask, Op0, Op1);
}
+static Value *EmitX86ScalarSelect(CodeGenFunction &CGF,
+ Value *Mask, Value *Op0, Value *Op1) {
+ // If the mask is all ones just return first argument.
+ if (const auto *C = dyn_cast<Constant>(Mask))
+ if (C->isAllOnesValue())
+ return Op0;
+
+ llvm::VectorType *MaskTy =
+ llvm::VectorType::get(CGF.Builder.getInt1Ty(),
+ Mask->getType()->getIntegerBitWidth());
+ Mask = CGF.Builder.CreateBitCast(Mask, MaskTy);
+ Mask = CGF.Builder.CreateExtractElement(Mask, (uint64_t)0);
+ return CGF.Builder.CreateSelect(Mask, Op0, Op1);
+}
+
+static Value *EmitX86MaskedCompareResult(CodeGenFunction &CGF, Value *Cmp,
+ unsigned NumElts, Value *MaskIn) {
+ if (MaskIn) {
+ const auto *C = dyn_cast<Constant>(MaskIn);
+ if (!C || !C->isAllOnesValue())
+ Cmp = CGF.Builder.CreateAnd(Cmp, getMaskVecValue(CGF, MaskIn, NumElts));
+ }
+
+ if (NumElts < 8) {
+ uint32_t Indices[8];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i;
+ for (unsigned i = NumElts; i != 8; ++i)
+ Indices[i] = i % NumElts + NumElts;
+ Cmp = CGF.Builder.CreateShuffleVector(
+ Cmp, llvm::Constant::getNullValue(Cmp->getType()), Indices);
+ }
+
+ return CGF.Builder.CreateBitCast(Cmp,
+ IntegerType::get(CGF.getLLVMContext(),
+ std::max(NumElts, 8U)));
+}
+
static Value *EmitX86MaskedCompare(CodeGenFunction &CGF, unsigned CC,
- bool Signed, SmallVectorImpl<Value *> &Ops) {
+ bool Signed, ArrayRef<Value *> Ops) {
+ assert((Ops.size() == 2 || Ops.size() == 4) &&
+ "Unexpected number of arguments");
unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
Value *Cmp;
@@ -7813,22 +8614,16 @@ static Value *EmitX86MaskedCompare(CodeGenFunction &CGF, unsigned CC,
Cmp = CGF.Builder.CreateICmp(Pred, Ops[0], Ops[1]);
}
- const auto *C = dyn_cast<Constant>(Ops.back());
- if (!C || !C->isAllOnesValue())
- Cmp = CGF.Builder.CreateAnd(Cmp, getMaskVecValue(CGF, Ops.back(), NumElts));
+ Value *MaskIn = nullptr;
+ if (Ops.size() == 4)
+ MaskIn = Ops[3];
- if (NumElts < 8) {
- uint32_t Indices[8];
- for (unsigned i = 0; i != NumElts; ++i)
- Indices[i] = i;
- for (unsigned i = NumElts; i != 8; ++i)
- Indices[i] = i % NumElts + NumElts;
- Cmp = CGF.Builder.CreateShuffleVector(
- Cmp, llvm::Constant::getNullValue(Cmp->getType()), Indices);
- }
- return CGF.Builder.CreateBitCast(Cmp,
- IntegerType::get(CGF.getLLVMContext(),
- std::max(NumElts, 8U)));
+ return EmitX86MaskedCompareResult(CGF, Cmp, NumElts, MaskIn);
+}
+
+static Value *EmitX86ConvertToMask(CodeGenFunction &CGF, Value *In) {
+ Value *Zero = Constant::getNullValue(In->getType());
+ return EmitX86MaskedCompare(CGF, 1, true, { In, Zero });
}
static Value *EmitX86Abs(CodeGenFunction &CGF, ArrayRef<Value *> Ops) {
@@ -7838,9 +8633,7 @@ static Value *EmitX86Abs(CodeGenFunction &CGF, ArrayRef<Value *> Ops) {
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]);
+ return Res;
}
static Value *EmitX86MinMax(CodeGenFunction &CGF, ICmpInst::Predicate Pred,
@@ -7848,14 +8641,214 @@ static Value *EmitX86MinMax(CodeGenFunction &CGF, ICmpInst::Predicate Pred,
Value *Cmp = CGF.Builder.CreateICmp(Pred, Ops[0], Ops[1]);
Value *Res = CGF.Builder.CreateSelect(Cmp, Ops[0], Ops[1]);
- if (Ops.size() == 2)
- return Res;
+ assert(Ops.size() == 2);
+ return Res;
+}
+
+// Lowers X86 FMA intrinsics to IR.
+static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef<Value *> Ops,
+ unsigned BuiltinID, bool IsAddSub) {
- assert(Ops.size() == 4);
- return EmitX86Select(CGF, Ops[3], Res, Ops[2]);
+ bool Subtract = false;
+ Intrinsic::ID IID = Intrinsic::not_intrinsic;
+ switch (BuiltinID) {
+ default: break;
+ case clang::X86::BI__builtin_ia32_vfmsubps512_mask3:
+ Subtract = true;
+ LLVM_FALLTHROUGH;
+ case clang::X86::BI__builtin_ia32_vfmaddps512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddps512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddps512_mask3:
+ IID = llvm::Intrinsic::x86_avx512_vfmadd_ps_512; break;
+ case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3:
+ Subtract = true;
+ LLVM_FALLTHROUGH;
+ case clang::X86::BI__builtin_ia32_vfmaddpd512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3:
+ IID = llvm::Intrinsic::x86_avx512_vfmadd_pd_512; break;
+ case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3:
+ Subtract = true;
+ LLVM_FALLTHROUGH;
+ case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3:
+ IID = llvm::Intrinsic::x86_avx512_vfmaddsub_ps_512;
+ break;
+ case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
+ Subtract = true;
+ LLVM_FALLTHROUGH;
+ case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
+ IID = llvm::Intrinsic::x86_avx512_vfmaddsub_pd_512;
+ break;
+ }
+
+ Value *A = Ops[0];
+ Value *B = Ops[1];
+ Value *C = Ops[2];
+
+ if (Subtract)
+ C = CGF.Builder.CreateFNeg(C);
+
+ Value *Res;
+
+ // Only handle in case of _MM_FROUND_CUR_DIRECTION/4 (no rounding).
+ if (IID != Intrinsic::not_intrinsic &&
+ cast<llvm::ConstantInt>(Ops.back())->getZExtValue() != (uint64_t)4) {
+ Function *Intr = CGF.CGM.getIntrinsic(IID);
+ Res = CGF.Builder.CreateCall(Intr, {A, B, C, Ops.back() });
+ } else {
+ llvm::Type *Ty = A->getType();
+ Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Res = CGF.Builder.CreateCall(FMA, {A, B, C} );
+
+ if (IsAddSub) {
+ // Negate even elts in C using a mask.
+ unsigned NumElts = Ty->getVectorNumElements();
+ SmallVector<uint32_t, 16> Indices(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i + (i % 2) * NumElts;
+
+ Value *NegC = CGF.Builder.CreateFNeg(C);
+ Value *FMSub = CGF.Builder.CreateCall(FMA, {A, B, NegC} );
+ Res = CGF.Builder.CreateShuffleVector(FMSub, Res, Indices);
+ }
+ }
+
+ // Handle any required masking.
+ Value *MaskFalseVal = nullptr;
+ switch (BuiltinID) {
+ case clang::X86::BI__builtin_ia32_vfmaddps512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddpd512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask:
+ case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask:
+ MaskFalseVal = Ops[0];
+ break;
+ case clang::X86::BI__builtin_ia32_vfmaddps512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz:
+ case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
+ MaskFalseVal = Constant::getNullValue(Ops[0]->getType());
+ break;
+ case clang::X86::BI__builtin_ia32_vfmsubps512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmaddps512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
+ case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
+ MaskFalseVal = Ops[2];
+ break;
+ }
+
+ if (MaskFalseVal)
+ return EmitX86Select(CGF, Ops[3], Res, MaskFalseVal);
+
+ return Res;
}
-static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op,
+static Value *
+EmitScalarFMAExpr(CodeGenFunction &CGF, MutableArrayRef<Value *> Ops,
+ Value *Upper, bool ZeroMask = false, unsigned PTIdx = 0,
+ bool NegAcc = false) {
+ unsigned Rnd = 4;
+ if (Ops.size() > 4)
+ Rnd = cast<llvm::ConstantInt>(Ops[4])->getZExtValue();
+
+ if (NegAcc)
+ Ops[2] = CGF.Builder.CreateFNeg(Ops[2]);
+
+ Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], (uint64_t)0);
+ Ops[1] = CGF.Builder.CreateExtractElement(Ops[1], (uint64_t)0);
+ Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], (uint64_t)0);
+ Value *Res;
+ if (Rnd != 4) {
+ Intrinsic::ID IID = Ops[0]->getType()->getPrimitiveSizeInBits() == 32 ?
+ Intrinsic::x86_avx512_vfmadd_f32 :
+ Intrinsic::x86_avx512_vfmadd_f64;
+ Res = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID),
+ {Ops[0], Ops[1], Ops[2], Ops[4]});
+ } else {
+ Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ops[0]->getType());
+ Res = CGF.Builder.CreateCall(FMA, Ops.slice(0, 3));
+ }
+ // If we have more than 3 arguments, we need to do masking.
+ if (Ops.size() > 3) {
+ Value *PassThru = ZeroMask ? Constant::getNullValue(Res->getType())
+ : Ops[PTIdx];
+
+ // If we negated the accumulator and the its the PassThru value we need to
+ // bypass the negate. Conveniently Upper should be the same thing in this
+ // case.
+ if (NegAcc && PTIdx == 2)
+ PassThru = CGF.Builder.CreateExtractElement(Upper, (uint64_t)0);
+
+ Res = EmitX86ScalarSelect(CGF, Ops[3], Res, PassThru);
+ }
+ return CGF.Builder.CreateInsertElement(Upper, Res, (uint64_t)0);
+}
+
+static Value *EmitX86Muldq(CodeGenFunction &CGF, bool IsSigned,
+ ArrayRef<Value *> Ops) {
+ llvm::Type *Ty = Ops[0]->getType();
+ // Arguments have a vXi32 type so cast to vXi64.
+ Ty = llvm::VectorType::get(CGF.Int64Ty,
+ Ty->getPrimitiveSizeInBits() / 64);
+ Value *LHS = CGF.Builder.CreateBitCast(Ops[0], Ty);
+ Value *RHS = CGF.Builder.CreateBitCast(Ops[1], Ty);
+
+ if (IsSigned) {
+ // Shift left then arithmetic shift right.
+ Constant *ShiftAmt = ConstantInt::get(Ty, 32);
+ LHS = CGF.Builder.CreateShl(LHS, ShiftAmt);
+ LHS = CGF.Builder.CreateAShr(LHS, ShiftAmt);
+ RHS = CGF.Builder.CreateShl(RHS, ShiftAmt);
+ RHS = CGF.Builder.CreateAShr(RHS, ShiftAmt);
+ } else {
+ // Clear the upper bits.
+ Constant *Mask = ConstantInt::get(Ty, 0xffffffff);
+ LHS = CGF.Builder.CreateAnd(LHS, Mask);
+ RHS = CGF.Builder.CreateAnd(RHS, Mask);
+ }
+
+ return CGF.Builder.CreateMul(LHS, RHS);
+}
+
+// Emit a masked pternlog intrinsic. This only exists because the header has to
+// use a macro and we aren't able to pass the input argument to a pternlog
+// builtin and a select builtin without evaluating it twice.
+static Value *EmitX86Ternlog(CodeGenFunction &CGF, bool ZeroMask,
+ ArrayRef<Value *> Ops) {
+ llvm::Type *Ty = Ops[0]->getType();
+
+ unsigned VecWidth = Ty->getPrimitiveSizeInBits();
+ unsigned EltWidth = Ty->getScalarSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pternlog_d_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pternlog_d_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pternlog_d_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pternlog_q_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pternlog_q_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pternlog_q_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Value *Ternlog = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID),
+ Ops.drop_back());
+ Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty) : Ops[0];
+ return EmitX86Select(CGF, Ops[4], Ternlog, PassThru);
+}
+
+static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op,
llvm::Type *DstTy) {
unsigned NumberOfElements = DstTy->getVectorNumElements();
Value *Mask = getMaskVecValue(CGF, Op, NumberOfElements);
@@ -7918,11 +8911,10 @@ Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) {
return EmitX86CpuSupports(FeatureStr);
}
-Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {
+uint32_t
+CodeGenFunction::GetX86CpuSupportsMask(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)
@@ -7931,7 +8923,14 @@ Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {
;
FeaturesMask |= (1U << Feature);
}
+ return FeaturesMask;
+}
+
+Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {
+ return EmitX86CpuSupports(GetX86CpuSupportsMask(FeatureStrs));
+}
+llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint32_t FeaturesMask) {
// Matching the struct layout from the compiler-rt/libgcc structure that is
// filled in:
// unsigned int __cpu_vendor;
@@ -8067,8 +9066,37 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return Builder.CreateBitCast(BuildVector(Ops),
llvm::Type::getX86_MMXTy(getLLVMContext()));
case X86::BI__builtin_ia32_vec_ext_v2si:
- return Builder.CreateExtractElement(Ops[0],
- llvm::ConstantInt::get(Ops[1]->getType(), 0));
+ case X86::BI__builtin_ia32_vec_ext_v16qi:
+ case X86::BI__builtin_ia32_vec_ext_v8hi:
+ case X86::BI__builtin_ia32_vec_ext_v4si:
+ case X86::BI__builtin_ia32_vec_ext_v4sf:
+ case X86::BI__builtin_ia32_vec_ext_v2di:
+ case X86::BI__builtin_ia32_vec_ext_v32qi:
+ case X86::BI__builtin_ia32_vec_ext_v16hi:
+ case X86::BI__builtin_ia32_vec_ext_v8si:
+ case X86::BI__builtin_ia32_vec_ext_v4di: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ uint64_t Index = cast<ConstantInt>(Ops[1])->getZExtValue();
+ Index &= NumElts - 1;
+ // These builtins exist so we can ensure the index is an ICE and in range.
+ // Otherwise we could just do this in the header file.
+ return Builder.CreateExtractElement(Ops[0], Index);
+ }
+ case X86::BI__builtin_ia32_vec_set_v16qi:
+ case X86::BI__builtin_ia32_vec_set_v8hi:
+ case X86::BI__builtin_ia32_vec_set_v4si:
+ case X86::BI__builtin_ia32_vec_set_v2di:
+ case X86::BI__builtin_ia32_vec_set_v32qi:
+ case X86::BI__builtin_ia32_vec_set_v16hi:
+ case X86::BI__builtin_ia32_vec_set_v8si:
+ case X86::BI__builtin_ia32_vec_set_v4di: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ unsigned Index = cast<ConstantInt>(Ops[2])->getZExtValue();
+ Index &= NumElts - 1;
+ // These builtins exist so we can ensure the index is an ICE and in range.
+ // Otherwise we could just do this in the header file.
+ return Builder.CreateInsertElement(Ops[0], Ops[1], Index);
+ }
case X86::BI_mm_setcsr:
case X86::BI__builtin_ia32_ldmxcsr: {
Address Tmp = CreateMemTemp(E->getArg(0)->getType());
@@ -8145,7 +9173,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_storess128_mask:
case X86::BI__builtin_ia32_storesd128_mask: {
- return EmitX86MaskedStore(*this, Ops, 16);
+ return EmitX86MaskedStore(*this, Ops, 1);
}
case X86::BI__builtin_ia32_vpopcntb_128:
case X86::BI__builtin_ia32_vpopcntd_128:
@@ -8177,6 +9205,66 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_cvtmask2q512:
return EmitX86SExtMask(*this, Ops[0], ConvertType(E->getType()));
+ case X86::BI__builtin_ia32_cvtb2mask128:
+ case X86::BI__builtin_ia32_cvtb2mask256:
+ case X86::BI__builtin_ia32_cvtb2mask512:
+ case X86::BI__builtin_ia32_cvtw2mask128:
+ case X86::BI__builtin_ia32_cvtw2mask256:
+ case X86::BI__builtin_ia32_cvtw2mask512:
+ case X86::BI__builtin_ia32_cvtd2mask128:
+ case X86::BI__builtin_ia32_cvtd2mask256:
+ case X86::BI__builtin_ia32_cvtd2mask512:
+ case X86::BI__builtin_ia32_cvtq2mask128:
+ case X86::BI__builtin_ia32_cvtq2mask256:
+ case X86::BI__builtin_ia32_cvtq2mask512:
+ return EmitX86ConvertToMask(*this, Ops[0]);
+
+ case X86::BI__builtin_ia32_vfmaddss3:
+ case X86::BI__builtin_ia32_vfmaddsd3:
+ case X86::BI__builtin_ia32_vfmaddss3_mask:
+ case X86::BI__builtin_ia32_vfmaddsd3_mask:
+ return EmitScalarFMAExpr(*this, Ops, Ops[0]);
+ case X86::BI__builtin_ia32_vfmaddss:
+ case X86::BI__builtin_ia32_vfmaddsd:
+ return EmitScalarFMAExpr(*this, Ops,
+ Constant::getNullValue(Ops[0]->getType()));
+ case X86::BI__builtin_ia32_vfmaddss3_maskz:
+ case X86::BI__builtin_ia32_vfmaddsd3_maskz:
+ return EmitScalarFMAExpr(*this, Ops, Ops[0], /*ZeroMask*/true);
+ case X86::BI__builtin_ia32_vfmaddss3_mask3:
+ case X86::BI__builtin_ia32_vfmaddsd3_mask3:
+ return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2);
+ case X86::BI__builtin_ia32_vfmsubss3_mask3:
+ case X86::BI__builtin_ia32_vfmsubsd3_mask3:
+ return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2,
+ /*NegAcc*/true);
+ case X86::BI__builtin_ia32_vfmaddps:
+ case X86::BI__builtin_ia32_vfmaddpd:
+ case X86::BI__builtin_ia32_vfmaddps256:
+ case X86::BI__builtin_ia32_vfmaddpd256:
+ case X86::BI__builtin_ia32_vfmaddps512_mask:
+ case X86::BI__builtin_ia32_vfmaddps512_maskz:
+ case X86::BI__builtin_ia32_vfmaddps512_mask3:
+ case X86::BI__builtin_ia32_vfmsubps512_mask3:
+ case X86::BI__builtin_ia32_vfmaddpd512_mask:
+ case X86::BI__builtin_ia32_vfmaddpd512_maskz:
+ case X86::BI__builtin_ia32_vfmaddpd512_mask3:
+ case X86::BI__builtin_ia32_vfmsubpd512_mask3:
+ return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/false);
+ case X86::BI__builtin_ia32_vfmaddsubps:
+ case X86::BI__builtin_ia32_vfmaddsubpd:
+ case X86::BI__builtin_ia32_vfmaddsubps256:
+ case X86::BI__builtin_ia32_vfmaddsubpd256:
+ case X86::BI__builtin_ia32_vfmaddsubps512_mask:
+ case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
+ case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
+ case X86::BI__builtin_ia32_vfmsubaddps512_mask3:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_mask:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
+ case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
+ return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/true);
+
case X86::BI__builtin_ia32_movdqa32store128_mask:
case X86::BI__builtin_ia32_movdqa64store128_mask:
case X86::BI__builtin_ia32_storeaps128_mask:
@@ -8215,7 +9303,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_loadss128_mask:
case X86::BI__builtin_ia32_loadsd128_mask:
- return EmitX86MaskedLoad(*this, Ops, 16);
+ return EmitX86MaskedLoad(*this, Ops, 1);
case X86::BI__builtin_ia32_loadaps128_mask:
case X86::BI__builtin_ia32_loadaps256_mask:
@@ -8234,11 +9322,45 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitX86MaskedLoad(*this, Ops, Align);
}
- case X86::BI__builtin_ia32_vbroadcastf128_pd256:
- case X86::BI__builtin_ia32_vbroadcastf128_ps256: {
- llvm::Type *DstTy = ConvertType(E->getType());
- return EmitX86SubVectorBroadcast(*this, Ops, DstTy, 128, 1);
- }
+ case X86::BI__builtin_ia32_expandloaddf128_mask:
+ case X86::BI__builtin_ia32_expandloaddf256_mask:
+ case X86::BI__builtin_ia32_expandloaddf512_mask:
+ case X86::BI__builtin_ia32_expandloadsf128_mask:
+ case X86::BI__builtin_ia32_expandloadsf256_mask:
+ case X86::BI__builtin_ia32_expandloadsf512_mask:
+ case X86::BI__builtin_ia32_expandloaddi128_mask:
+ case X86::BI__builtin_ia32_expandloaddi256_mask:
+ case X86::BI__builtin_ia32_expandloaddi512_mask:
+ case X86::BI__builtin_ia32_expandloadsi128_mask:
+ case X86::BI__builtin_ia32_expandloadsi256_mask:
+ case X86::BI__builtin_ia32_expandloadsi512_mask:
+ case X86::BI__builtin_ia32_expandloadhi128_mask:
+ case X86::BI__builtin_ia32_expandloadhi256_mask:
+ case X86::BI__builtin_ia32_expandloadhi512_mask:
+ case X86::BI__builtin_ia32_expandloadqi128_mask:
+ case X86::BI__builtin_ia32_expandloadqi256_mask:
+ case X86::BI__builtin_ia32_expandloadqi512_mask:
+ return EmitX86ExpandLoad(*this, Ops);
+
+ case X86::BI__builtin_ia32_compressstoredf128_mask:
+ case X86::BI__builtin_ia32_compressstoredf256_mask:
+ case X86::BI__builtin_ia32_compressstoredf512_mask:
+ case X86::BI__builtin_ia32_compressstoresf128_mask:
+ case X86::BI__builtin_ia32_compressstoresf256_mask:
+ case X86::BI__builtin_ia32_compressstoresf512_mask:
+ case X86::BI__builtin_ia32_compressstoredi128_mask:
+ case X86::BI__builtin_ia32_compressstoredi256_mask:
+ case X86::BI__builtin_ia32_compressstoredi512_mask:
+ case X86::BI__builtin_ia32_compressstoresi128_mask:
+ case X86::BI__builtin_ia32_compressstoresi256_mask:
+ case X86::BI__builtin_ia32_compressstoresi512_mask:
+ case X86::BI__builtin_ia32_compressstorehi128_mask:
+ case X86::BI__builtin_ia32_compressstorehi256_mask:
+ case X86::BI__builtin_ia32_compressstorehi512_mask:
+ case X86::BI__builtin_ia32_compressstoreqi128_mask:
+ case X86::BI__builtin_ia32_compressstoreqi256_mask:
+ case X86::BI__builtin_ia32_compressstoreqi512_mask:
+ return EmitX86CompressStore(*this, Ops);
case X86::BI__builtin_ia32_storehps:
case X86::BI__builtin_ia32_storelps: {
@@ -8250,17 +9372,275 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
// extract (0, 1)
unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1;
- llvm::Value *Idx = llvm::ConstantInt::get(SizeTy, Index);
- Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract");
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Index, "extract");
// cast pointer to i64 & store
Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
+ case X86::BI__builtin_ia32_vextractf128_pd256:
+ case X86::BI__builtin_ia32_vextractf128_ps256:
+ case X86::BI__builtin_ia32_vextractf128_si256:
+ case X86::BI__builtin_ia32_extract128i256:
+ case X86::BI__builtin_ia32_extractf64x4_mask:
+ case X86::BI__builtin_ia32_extractf32x4_mask:
+ case X86::BI__builtin_ia32_extracti64x4_mask:
+ case X86::BI__builtin_ia32_extracti32x4_mask:
+ case X86::BI__builtin_ia32_extractf32x8_mask:
+ case X86::BI__builtin_ia32_extracti32x8_mask:
+ case X86::BI__builtin_ia32_extractf32x4_256_mask:
+ case X86::BI__builtin_ia32_extracti32x4_256_mask:
+ case X86::BI__builtin_ia32_extractf64x2_256_mask:
+ case X86::BI__builtin_ia32_extracti64x2_256_mask:
+ case X86::BI__builtin_ia32_extractf64x2_512_mask:
+ case X86::BI__builtin_ia32_extracti64x2_512_mask: {
+ llvm::Type *DstTy = ConvertType(E->getType());
+ unsigned NumElts = DstTy->getVectorNumElements();
+ unsigned SrcNumElts = Ops[0]->getType()->getVectorNumElements();
+ unsigned SubVectors = SrcNumElts / NumElts;
+ unsigned Index = cast<ConstantInt>(Ops[1])->getZExtValue();
+ assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors");
+ Index &= SubVectors - 1; // Remove any extra bits.
+ Index *= NumElts;
+
+ uint32_t Indices[16];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i + Index;
+
+ Value *Res = Builder.CreateShuffleVector(Ops[0],
+ UndefValue::get(Ops[0]->getType()),
+ makeArrayRef(Indices, NumElts),
+ "extract");
+
+ if (Ops.size() == 4)
+ Res = EmitX86Select(*this, Ops[3], Res, Ops[2]);
+
+ return Res;
+ }
+ case X86::BI__builtin_ia32_vinsertf128_pd256:
+ case X86::BI__builtin_ia32_vinsertf128_ps256:
+ case X86::BI__builtin_ia32_vinsertf128_si256:
+ case X86::BI__builtin_ia32_insert128i256:
+ case X86::BI__builtin_ia32_insertf64x4:
+ case X86::BI__builtin_ia32_insertf32x4:
+ case X86::BI__builtin_ia32_inserti64x4:
+ case X86::BI__builtin_ia32_inserti32x4:
+ case X86::BI__builtin_ia32_insertf32x8:
+ case X86::BI__builtin_ia32_inserti32x8:
+ case X86::BI__builtin_ia32_insertf32x4_256:
+ case X86::BI__builtin_ia32_inserti32x4_256:
+ case X86::BI__builtin_ia32_insertf64x2_256:
+ case X86::BI__builtin_ia32_inserti64x2_256:
+ case X86::BI__builtin_ia32_insertf64x2_512:
+ case X86::BI__builtin_ia32_inserti64x2_512: {
+ unsigned DstNumElts = Ops[0]->getType()->getVectorNumElements();
+ unsigned SrcNumElts = Ops[1]->getType()->getVectorNumElements();
+ unsigned SubVectors = DstNumElts / SrcNumElts;
+ unsigned Index = cast<ConstantInt>(Ops[2])->getZExtValue();
+ assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors");
+ Index &= SubVectors - 1; // Remove any extra bits.
+ Index *= SrcNumElts;
+
+ uint32_t Indices[16];
+ for (unsigned i = 0; i != DstNumElts; ++i)
+ Indices[i] = (i >= SrcNumElts) ? SrcNumElts + (i % SrcNumElts) : i;
+
+ Value *Op1 = Builder.CreateShuffleVector(Ops[1],
+ UndefValue::get(Ops[1]->getType()),
+ makeArrayRef(Indices, DstNumElts),
+ "widen");
+
+ for (unsigned i = 0; i != DstNumElts; ++i) {
+ if (i >= Index && i < (Index + SrcNumElts))
+ Indices[i] = (i - Index) + DstNumElts;
+ else
+ Indices[i] = i;
+ }
+
+ return Builder.CreateShuffleVector(Ops[0], Op1,
+ makeArrayRef(Indices, DstNumElts),
+ "insert");
+ }
+ case X86::BI__builtin_ia32_pmovqd512_mask:
+ case X86::BI__builtin_ia32_pmovwb512_mask: {
+ Value *Res = Builder.CreateTrunc(Ops[0], Ops[1]->getType());
+ return EmitX86Select(*this, Ops[2], Res, Ops[1]);
+ }
+ case X86::BI__builtin_ia32_pmovdb512_mask:
+ case X86::BI__builtin_ia32_pmovdw512_mask:
+ case X86::BI__builtin_ia32_pmovqw512_mask: {
+ if (const auto *C = dyn_cast<Constant>(Ops[2]))
+ if (C->isAllOnesValue())
+ return Builder.CreateTrunc(Ops[0], Ops[1]->getType());
+
+ Intrinsic::ID IID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_pmovdb512_mask:
+ IID = Intrinsic::x86_avx512_mask_pmov_db_512;
+ break;
+ case X86::BI__builtin_ia32_pmovdw512_mask:
+ IID = Intrinsic::x86_avx512_mask_pmov_dw_512;
+ break;
+ case X86::BI__builtin_ia32_pmovqw512_mask:
+ IID = Intrinsic::x86_avx512_mask_pmov_qw_512;
+ break;
+ }
+
+ Function *Intr = CGM.getIntrinsic(IID);
+ return Builder.CreateCall(Intr, Ops);
+ }
+ case X86::BI__builtin_ia32_pblendw128:
+ case X86::BI__builtin_ia32_blendpd:
+ case X86::BI__builtin_ia32_blendps:
+ case X86::BI__builtin_ia32_blendpd256:
+ case X86::BI__builtin_ia32_blendps256:
+ case X86::BI__builtin_ia32_pblendw256:
+ case X86::BI__builtin_ia32_pblendd128:
+ case X86::BI__builtin_ia32_pblendd256: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+
+ uint32_t Indices[16];
+ // If there are more than 8 elements, the immediate is used twice so make
+ // sure we handle that.
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = ((Imm >> (i % 8)) & 0x1) ? NumElts + i : i;
+
+ return Builder.CreateShuffleVector(Ops[0], Ops[1],
+ makeArrayRef(Indices, NumElts),
+ "blend");
+ }
+ case X86::BI__builtin_ia32_pshuflw:
+ case X86::BI__builtin_ia32_pshuflw256:
+ case X86::BI__builtin_ia32_pshuflw512: {
+ uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();
+ llvm::Type *Ty = Ops[0]->getType();
+ unsigned NumElts = Ty->getVectorNumElements();
+
+ // Splat the 8-bits of immediate 4 times to help the loop wrap around.
+ Imm = (Imm & 0xff) * 0x01010101;
+
+ uint32_t Indices[32];
+ for (unsigned l = 0; l != NumElts; l += 8) {
+ for (unsigned i = 0; i != 4; ++i) {
+ Indices[l + i] = l + (Imm & 3);
+ Imm >>= 2;
+ }
+ for (unsigned i = 4; i != 8; ++i)
+ Indices[l + i] = l + i;
+ }
+
+ return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty),
+ makeArrayRef(Indices, NumElts),
+ "pshuflw");
+ }
+ case X86::BI__builtin_ia32_pshufhw:
+ case X86::BI__builtin_ia32_pshufhw256:
+ case X86::BI__builtin_ia32_pshufhw512: {
+ uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();
+ llvm::Type *Ty = Ops[0]->getType();
+ unsigned NumElts = Ty->getVectorNumElements();
+
+ // Splat the 8-bits of immediate 4 times to help the loop wrap around.
+ Imm = (Imm & 0xff) * 0x01010101;
+
+ uint32_t Indices[32];
+ for (unsigned l = 0; l != NumElts; l += 8) {
+ for (unsigned i = 0; i != 4; ++i)
+ Indices[l + i] = l + i;
+ for (unsigned i = 4; i != 8; ++i) {
+ Indices[l + i] = l + 4 + (Imm & 3);
+ Imm >>= 2;
+ }
+ }
+
+ return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty),
+ makeArrayRef(Indices, NumElts),
+ "pshufhw");
+ }
+ case X86::BI__builtin_ia32_pshufd:
+ case X86::BI__builtin_ia32_pshufd256:
+ case X86::BI__builtin_ia32_pshufd512:
+ case X86::BI__builtin_ia32_vpermilpd:
+ case X86::BI__builtin_ia32_vpermilps:
+ case X86::BI__builtin_ia32_vpermilpd256:
+ case X86::BI__builtin_ia32_vpermilps256:
+ case X86::BI__builtin_ia32_vpermilpd512:
+ case X86::BI__builtin_ia32_vpermilps512: {
+ uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();
+ llvm::Type *Ty = Ops[0]->getType();
+ unsigned NumElts = Ty->getVectorNumElements();
+ unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128;
+ unsigned NumLaneElts = NumElts / NumLanes;
+
+ // Splat the 8-bits of immediate 4 times to help the loop wrap around.
+ Imm = (Imm & 0xff) * 0x01010101;
+
+ uint32_t Indices[16];
+ for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
+ for (unsigned i = 0; i != NumLaneElts; ++i) {
+ Indices[i + l] = (Imm % NumLaneElts) + l;
+ Imm /= NumLaneElts;
+ }
+ }
+
+ return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty),
+ makeArrayRef(Indices, NumElts),
+ "permil");
+ }
+ case X86::BI__builtin_ia32_shufpd:
+ case X86::BI__builtin_ia32_shufpd256:
+ case X86::BI__builtin_ia32_shufpd512:
+ case X86::BI__builtin_ia32_shufps:
+ case X86::BI__builtin_ia32_shufps256:
+ case X86::BI__builtin_ia32_shufps512: {
+ uint32_t Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+ llvm::Type *Ty = Ops[0]->getType();
+ unsigned NumElts = Ty->getVectorNumElements();
+ unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128;
+ unsigned NumLaneElts = NumElts / NumLanes;
+
+ // Splat the 8-bits of immediate 4 times to help the loop wrap around.
+ Imm = (Imm & 0xff) * 0x01010101;
+
+ uint32_t Indices[16];
+ for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
+ for (unsigned i = 0; i != NumLaneElts; ++i) {
+ unsigned Index = Imm % NumLaneElts;
+ Imm /= NumLaneElts;
+ if (i >= (NumLaneElts / 2))
+ Index += NumElts;
+ Indices[l + i] = l + Index;
+ }
+ }
+
+ return Builder.CreateShuffleVector(Ops[0], Ops[1],
+ makeArrayRef(Indices, NumElts),
+ "shufp");
+ }
+ case X86::BI__builtin_ia32_permdi256:
+ case X86::BI__builtin_ia32_permdf256:
+ case X86::BI__builtin_ia32_permdi512:
+ case X86::BI__builtin_ia32_permdf512: {
+ unsigned Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();
+ llvm::Type *Ty = Ops[0]->getType();
+ unsigned NumElts = Ty->getVectorNumElements();
+
+ // These intrinsics operate on 256-bit lanes of four 64-bit elements.
+ uint32_t Indices[8];
+ for (unsigned l = 0; l != NumElts; l += 4)
+ for (unsigned i = 0; i != 4; ++i)
+ Indices[l + i] = l + ((Imm >> (2 * i)) & 0x3);
+
+ return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty),
+ makeArrayRef(Indices, NumElts),
+ "perm");
+ }
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256:
- case X86::BI__builtin_ia32_palignr512_mask: {
- unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+ case X86::BI__builtin_ia32_palignr512: {
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff;
unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
assert(NumElts % 16 == 0);
@@ -8289,15 +9669,58 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
}
}
- Value *Align = Builder.CreateShuffleVector(Ops[1], Ops[0],
- makeArrayRef(Indices, NumElts),
- "palignr");
+ return Builder.CreateShuffleVector(Ops[1], Ops[0],
+ makeArrayRef(Indices, NumElts),
+ "palignr");
+ }
+ case X86::BI__builtin_ia32_alignd128:
+ case X86::BI__builtin_ia32_alignd256:
+ case X86::BI__builtin_ia32_alignd512:
+ case X86::BI__builtin_ia32_alignq128:
+ case X86::BI__builtin_ia32_alignq256:
+ case X86::BI__builtin_ia32_alignq512: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff;
+
+ // Mask the shift amount to width of two vectors.
+ ShiftVal &= (2 * NumElts) - 1;
- // If this isn't a masked builtin, just return the align operation.
- if (Ops.size() == 3)
- return Align;
+ uint32_t Indices[16];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i + ShiftVal;
- return EmitX86Select(*this, Ops[4], Align, Ops[3]);
+ return Builder.CreateShuffleVector(Ops[1], Ops[0],
+ makeArrayRef(Indices, NumElts),
+ "valign");
+ }
+ case X86::BI__builtin_ia32_shuf_f32x4_256:
+ case X86::BI__builtin_ia32_shuf_f64x2_256:
+ case X86::BI__builtin_ia32_shuf_i32x4_256:
+ case X86::BI__builtin_ia32_shuf_i64x2_256:
+ case X86::BI__builtin_ia32_shuf_f32x4:
+ case X86::BI__builtin_ia32_shuf_f64x2:
+ case X86::BI__builtin_ia32_shuf_i32x4:
+ case X86::BI__builtin_ia32_shuf_i64x2: {
+ unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+ llvm::Type *Ty = Ops[0]->getType();
+ unsigned NumElts = Ty->getVectorNumElements();
+ unsigned NumLanes = Ty->getPrimitiveSizeInBits() == 512 ? 4 : 2;
+ unsigned NumLaneElts = NumElts / NumLanes;
+
+ uint32_t Indices[16];
+ for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
+ unsigned Index = (Imm % NumLanes) * NumLaneElts;
+ Imm /= NumLanes; // Discard the bits we just used.
+ if (l >= (NumElts / 2))
+ Index += NumElts; // Switch to other source.
+ for (unsigned i = 0; i != NumLaneElts; ++i) {
+ Indices[l + i] = Index + i;
+ }
+ }
+
+ return Builder.CreateShuffleVector(Ops[0], Ops[1],
+ makeArrayRef(Indices, NumElts),
+ "shuf");
}
case X86::BI__builtin_ia32_vperm2f128_pd256:
@@ -8339,6 +9762,66 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
"vperm");
}
+ case X86::BI__builtin_ia32_pslldqi128_byteshift:
+ case X86::BI__builtin_ia32_pslldqi256_byteshift:
+ case X86::BI__builtin_ia32_pslldqi512_byteshift: {
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;
+ llvm::Type *ResultType = Ops[0]->getType();
+ // Builtin type is vXi64 so multiply by 8 to get bytes.
+ unsigned NumElts = ResultType->getVectorNumElements() * 8;
+
+ // If pslldq is shifting the vector more than 15 bytes, emit zero.
+ if (ShiftVal >= 16)
+ return llvm::Constant::getNullValue(ResultType);
+
+ uint32_t Indices[64];
+ // 256/512-bit pslldq operates on 128-bit lanes so we need to handle that
+ for (unsigned l = 0; l != NumElts; l += 16) {
+ for (unsigned i = 0; i != 16; ++i) {
+ unsigned Idx = NumElts + i - ShiftVal;
+ if (Idx < NumElts) Idx -= NumElts - 16; // end of lane, switch operand.
+ Indices[l + i] = Idx + l;
+ }
+ }
+
+ llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, NumElts);
+ Value *Cast = Builder.CreateBitCast(Ops[0], VecTy, "cast");
+ Value *Zero = llvm::Constant::getNullValue(VecTy);
+ Value *SV = Builder.CreateShuffleVector(Zero, Cast,
+ makeArrayRef(Indices, NumElts),
+ "pslldq");
+ return Builder.CreateBitCast(SV, Ops[0]->getType(), "cast");
+ }
+ case X86::BI__builtin_ia32_psrldqi128_byteshift:
+ case X86::BI__builtin_ia32_psrldqi256_byteshift:
+ case X86::BI__builtin_ia32_psrldqi512_byteshift: {
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;
+ llvm::Type *ResultType = Ops[0]->getType();
+ // Builtin type is vXi64 so multiply by 8 to get bytes.
+ unsigned NumElts = ResultType->getVectorNumElements() * 8;
+
+ // If psrldq is shifting the vector more than 15 bytes, emit zero.
+ if (ShiftVal >= 16)
+ return llvm::Constant::getNullValue(ResultType);
+
+ uint32_t Indices[64];
+ // 256/512-bit psrldq operates on 128-bit lanes so we need to handle that
+ for (unsigned l = 0; l != NumElts; l += 16) {
+ for (unsigned i = 0; i != 16; ++i) {
+ unsigned Idx = i + ShiftVal;
+ if (Idx >= 16) Idx += NumElts - 16; // end of lane, switch operand.
+ Indices[l + i] = Idx + l;
+ }
+ }
+
+ llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, NumElts);
+ Value *Cast = Builder.CreateBitCast(Ops[0], VecTy, "cast");
+ Value *Zero = llvm::Constant::getNullValue(VecTy);
+ Value *SV = Builder.CreateShuffleVector(Cast, Zero,
+ makeArrayRef(Indices, NumElts),
+ "psrldq");
+ return Builder.CreateBitCast(SV, ResultType, "cast");
+ }
case X86::BI__builtin_ia32_movnti:
case X86::BI__builtin_ia32_movnti64:
case X86::BI__builtin_ia32_movntsd:
@@ -8384,6 +9867,13 @@ 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_selectss_128:
+ case X86::BI__builtin_ia32_selectsd_128: {
+ Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
+ Value *B = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
+ A = EmitX86ScalarSelect(*this, Ops[0], A, B);
+ return Builder.CreateInsertElement(Ops[1], A, (uint64_t)0);
+ }
case X86::BI__builtin_ia32_cmpb128_mask:
case X86::BI__builtin_ia32_cmpb256_mask:
case X86::BI__builtin_ia32_cmpb512_mask:
@@ -8415,6 +9905,18 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitX86MaskedCompare(*this, CC, false, Ops);
}
+ case X86::BI__builtin_ia32_kortestchi:
+ case X86::BI__builtin_ia32_kortestzhi: {
+ Value *Or = EmitX86MaskLogic(*this, Instruction::Or, 16, Ops);
+ Value *C;
+ if (BuiltinID == X86::BI__builtin_ia32_kortestchi)
+ C = llvm::Constant::getAllOnesValue(Builder.getInt16Ty());
+ else
+ C = llvm::Constant::getNullValue(Builder.getInt16Ty());
+ Value *Cmp = Builder.CreateICmpEQ(Or, C);
+ return Builder.CreateZExt(Cmp, ConvertType(E->getType()));
+ }
+
case X86::BI__builtin_ia32_kandhi:
return EmitX86MaskLogic(*this, Instruction::And, 16, Ops);
case X86::BI__builtin_ia32_kandnhi:
@@ -8431,85 +9933,176 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
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:
- case X86::BI__builtin_ia32_vplzcntq_128_mask:
- case X86::BI__builtin_ia32_vplzcntq_256_mask:
- case X86::BI__builtin_ia32_vplzcntq_512_mask: {
+ case X86::BI__builtin_ia32_kunpckdi:
+ case X86::BI__builtin_ia32_kunpcksi:
+ case X86::BI__builtin_ia32_kunpckhi: {
+ unsigned NumElts = Ops[0]->getType()->getScalarSizeInBits();
+ Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);
+ Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);
+ uint32_t Indices[64];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i;
+
+ // First extract half of each vector. This gives better codegen than
+ // doing it in a single shuffle.
+ LHS = Builder.CreateShuffleVector(LHS, LHS,
+ makeArrayRef(Indices, NumElts / 2));
+ RHS = Builder.CreateShuffleVector(RHS, RHS,
+ makeArrayRef(Indices, NumElts / 2));
+ // Concat the vectors.
+ // NOTE: Operands are swapped to match the intrinsic definition.
+ Value *Res = Builder.CreateShuffleVector(RHS, LHS,
+ makeArrayRef(Indices, NumElts));
+ return Builder.CreateBitCast(Res, Ops[0]->getType());
+ }
+
+ case X86::BI__builtin_ia32_vplzcntd_128:
+ case X86::BI__builtin_ia32_vplzcntd_256:
+ case X86::BI__builtin_ia32_vplzcntd_512:
+ case X86::BI__builtin_ia32_vplzcntq_128:
+ case X86::BI__builtin_ia32_vplzcntq_256:
+ case X86::BI__builtin_ia32_vplzcntq_512: {
Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Ops[0]->getType());
- return EmitX86Select(*this, Ops[2],
- Builder.CreateCall(F, {Ops[0],Builder.getInt1(false)}),
- Ops[1]);
+ return Builder.CreateCall(F, {Ops[0],Builder.getInt1(false)});
+ }
+ case X86::BI__builtin_ia32_sqrtss:
+ case X86::BI__builtin_ia32_sqrtsd: {
+ Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
+ Function *F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType());
+ A = Builder.CreateCall(F, {A});
+ return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0);
+ }
+ case X86::BI__builtin_ia32_sqrtsd_round_mask:
+ case X86::BI__builtin_ia32_sqrtss_round_mask: {
+ unsigned CC = cast<llvm::ConstantInt>(Ops[4])->getZExtValue();
+ // Support only if the rounding mode is 4 (AKA CUR_DIRECTION),
+ // otherwise keep the intrinsic.
+ if (CC != 4) {
+ Intrinsic::ID IID = BuiltinID == X86::BI__builtin_ia32_sqrtsd_round_mask ?
+ Intrinsic::x86_avx512_mask_sqrt_sd :
+ Intrinsic::x86_avx512_mask_sqrt_ss;
+ return Builder.CreateCall(CGM.getIntrinsic(IID), Ops);
+ }
+ Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
+ Function *F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType());
+ A = Builder.CreateCall(F, A);
+ Value *Src = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
+ A = EmitX86ScalarSelect(*this, Ops[3], A, Src);
+ return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0);
+ }
+ case X86::BI__builtin_ia32_sqrtpd256:
+ case X86::BI__builtin_ia32_sqrtpd:
+ case X86::BI__builtin_ia32_sqrtps256:
+ case X86::BI__builtin_ia32_sqrtps:
+ case X86::BI__builtin_ia32_sqrtps512:
+ case X86::BI__builtin_ia32_sqrtpd512: {
+ if (Ops.size() == 2) {
+ unsigned CC = cast<llvm::ConstantInt>(Ops[1])->getZExtValue();
+ // Support only if the rounding mode is 4 (AKA CUR_DIRECTION),
+ // otherwise keep the intrinsic.
+ if (CC != 4) {
+ Intrinsic::ID IID = BuiltinID == X86::BI__builtin_ia32_sqrtps512 ?
+ Intrinsic::x86_avx512_sqrt_ps_512 :
+ Intrinsic::x86_avx512_sqrt_pd_512;
+ return Builder.CreateCall(CGM.getIntrinsic(IID), Ops);
+ }
+ }
+ Function *F = CGM.getIntrinsic(Intrinsic::sqrt, Ops[0]->getType());
+ return Builder.CreateCall(F, Ops[0]);
}
-
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:
+ case X86::BI__builtin_ia32_pabsq128:
+ case X86::BI__builtin_ia32_pabsq256:
+ case X86::BI__builtin_ia32_pabsb512:
+ case X86::BI__builtin_ia32_pabsw512:
+ case X86::BI__builtin_ia32_pabsd512:
+ case X86::BI__builtin_ia32_pabsq512:
return EmitX86Abs(*this, Ops);
case X86::BI__builtin_ia32_pmaxsb128:
case X86::BI__builtin_ia32_pmaxsw128:
case X86::BI__builtin_ia32_pmaxsd128:
- case X86::BI__builtin_ia32_pmaxsq128_mask:
+ case X86::BI__builtin_ia32_pmaxsq128:
case X86::BI__builtin_ia32_pmaxsb256:
case X86::BI__builtin_ia32_pmaxsw256:
case X86::BI__builtin_ia32_pmaxsd256:
- case X86::BI__builtin_ia32_pmaxsq256_mask:
- case X86::BI__builtin_ia32_pmaxsb512_mask:
- case X86::BI__builtin_ia32_pmaxsw512_mask:
- case X86::BI__builtin_ia32_pmaxsd512_mask:
- case X86::BI__builtin_ia32_pmaxsq512_mask:
+ case X86::BI__builtin_ia32_pmaxsq256:
+ case X86::BI__builtin_ia32_pmaxsb512:
+ case X86::BI__builtin_ia32_pmaxsw512:
+ case X86::BI__builtin_ia32_pmaxsd512:
+ case X86::BI__builtin_ia32_pmaxsq512:
return EmitX86MinMax(*this, ICmpInst::ICMP_SGT, Ops);
case X86::BI__builtin_ia32_pmaxub128:
case X86::BI__builtin_ia32_pmaxuw128:
case X86::BI__builtin_ia32_pmaxud128:
- case X86::BI__builtin_ia32_pmaxuq128_mask:
+ case X86::BI__builtin_ia32_pmaxuq128:
case X86::BI__builtin_ia32_pmaxub256:
case X86::BI__builtin_ia32_pmaxuw256:
case X86::BI__builtin_ia32_pmaxud256:
- case X86::BI__builtin_ia32_pmaxuq256_mask:
- case X86::BI__builtin_ia32_pmaxub512_mask:
- case X86::BI__builtin_ia32_pmaxuw512_mask:
- case X86::BI__builtin_ia32_pmaxud512_mask:
- case X86::BI__builtin_ia32_pmaxuq512_mask:
+ case X86::BI__builtin_ia32_pmaxuq256:
+ case X86::BI__builtin_ia32_pmaxub512:
+ case X86::BI__builtin_ia32_pmaxuw512:
+ case X86::BI__builtin_ia32_pmaxud512:
+ case X86::BI__builtin_ia32_pmaxuq512:
return EmitX86MinMax(*this, ICmpInst::ICMP_UGT, Ops);
case X86::BI__builtin_ia32_pminsb128:
case X86::BI__builtin_ia32_pminsw128:
case X86::BI__builtin_ia32_pminsd128:
- case X86::BI__builtin_ia32_pminsq128_mask:
+ case X86::BI__builtin_ia32_pminsq128:
case X86::BI__builtin_ia32_pminsb256:
case X86::BI__builtin_ia32_pminsw256:
case X86::BI__builtin_ia32_pminsd256:
- case X86::BI__builtin_ia32_pminsq256_mask:
- case X86::BI__builtin_ia32_pminsb512_mask:
- case X86::BI__builtin_ia32_pminsw512_mask:
- case X86::BI__builtin_ia32_pminsd512_mask:
- case X86::BI__builtin_ia32_pminsq512_mask:
+ case X86::BI__builtin_ia32_pminsq256:
+ case X86::BI__builtin_ia32_pminsb512:
+ case X86::BI__builtin_ia32_pminsw512:
+ case X86::BI__builtin_ia32_pminsd512:
+ case X86::BI__builtin_ia32_pminsq512:
return EmitX86MinMax(*this, ICmpInst::ICMP_SLT, Ops);
case X86::BI__builtin_ia32_pminub128:
case X86::BI__builtin_ia32_pminuw128:
case X86::BI__builtin_ia32_pminud128:
- case X86::BI__builtin_ia32_pminuq128_mask:
+ case X86::BI__builtin_ia32_pminuq128:
case X86::BI__builtin_ia32_pminub256:
case X86::BI__builtin_ia32_pminuw256:
case X86::BI__builtin_ia32_pminud256:
- case X86::BI__builtin_ia32_pminuq256_mask:
- case X86::BI__builtin_ia32_pminub512_mask:
- case X86::BI__builtin_ia32_pminuw512_mask:
- case X86::BI__builtin_ia32_pminud512_mask:
- case X86::BI__builtin_ia32_pminuq512_mask:
+ case X86::BI__builtin_ia32_pminuq256:
+ case X86::BI__builtin_ia32_pminub512:
+ case X86::BI__builtin_ia32_pminuw512:
+ case X86::BI__builtin_ia32_pminud512:
+ case X86::BI__builtin_ia32_pminuq512:
return EmitX86MinMax(*this, ICmpInst::ICMP_ULT, Ops);
+ case X86::BI__builtin_ia32_pmuludq128:
+ case X86::BI__builtin_ia32_pmuludq256:
+ case X86::BI__builtin_ia32_pmuludq512:
+ return EmitX86Muldq(*this, /*IsSigned*/false, Ops);
+
+ case X86::BI__builtin_ia32_pmuldq128:
+ case X86::BI__builtin_ia32_pmuldq256:
+ case X86::BI__builtin_ia32_pmuldq512:
+ return EmitX86Muldq(*this, /*IsSigned*/true, Ops);
+
+ case X86::BI__builtin_ia32_pternlogd512_mask:
+ case X86::BI__builtin_ia32_pternlogq512_mask:
+ case X86::BI__builtin_ia32_pternlogd128_mask:
+ case X86::BI__builtin_ia32_pternlogd256_mask:
+ case X86::BI__builtin_ia32_pternlogq128_mask:
+ case X86::BI__builtin_ia32_pternlogq256_mask:
+ return EmitX86Ternlog(*this, /*ZeroMask*/false, Ops);
+
+ case X86::BI__builtin_ia32_pternlogd512_maskz:
+ case X86::BI__builtin_ia32_pternlogq512_maskz:
+ case X86::BI__builtin_ia32_pternlogd128_maskz:
+ case X86::BI__builtin_ia32_pternlogd256_maskz:
+ case X86::BI__builtin_ia32_pternlogq128_maskz:
+ case X86::BI__builtin_ia32_pternlogq256_maskz:
+ return EmitX86Ternlog(*this, /*ZeroMask*/true, Ops);
+
// 3DNow!
case X86::BI__builtin_ia32_pswapdsf:
case X86::BI__builtin_ia32_pswapdsi: {
@@ -8553,7 +10146,44 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return Builder.CreateExtractValue(Call, 1);
}
- // SSE packed comparison intrinsics
+ case X86::BI__builtin_ia32_fpclassps128_mask:
+ case X86::BI__builtin_ia32_fpclassps256_mask:
+ case X86::BI__builtin_ia32_fpclassps512_mask:
+ case X86::BI__builtin_ia32_fpclasspd128_mask:
+ case X86::BI__builtin_ia32_fpclasspd256_mask:
+ case X86::BI__builtin_ia32_fpclasspd512_mask: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ Value *MaskIn = Ops[2];
+ Ops.erase(&Ops[2]);
+
+ Intrinsic::ID ID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_fpclassps128_mask:
+ ID = Intrinsic::x86_avx512_fpclass_ps_128;
+ break;
+ case X86::BI__builtin_ia32_fpclassps256_mask:
+ ID = Intrinsic::x86_avx512_fpclass_ps_256;
+ break;
+ case X86::BI__builtin_ia32_fpclassps512_mask:
+ ID = Intrinsic::x86_avx512_fpclass_ps_512;
+ break;
+ case X86::BI__builtin_ia32_fpclasspd128_mask:
+ ID = Intrinsic::x86_avx512_fpclass_pd_128;
+ break;
+ case X86::BI__builtin_ia32_fpclasspd256_mask:
+ ID = Intrinsic::x86_avx512_fpclass_pd_256;
+ break;
+ case X86::BI__builtin_ia32_fpclasspd512_mask:
+ ID = Intrinsic::x86_avx512_fpclass_pd_512;
+ break;
+ }
+
+ Value *Fpclass = Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
+ return EmitX86MaskedCompareResult(*this, Fpclass, NumElts, MaskIn);
+ }
+
+ // packed comparison intrinsics
case X86::BI__builtin_ia32_cmpeqps:
case X86::BI__builtin_ia32_cmpeqpd:
return getVectorFCmpIR(CmpInst::FCMP_OEQ);
@@ -8581,64 +10211,79 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_cmpps:
case X86::BI__builtin_ia32_cmpps256:
case X86::BI__builtin_ia32_cmppd:
- case X86::BI__builtin_ia32_cmppd256: {
- unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
- // If this one of the SSE immediates, we can use native IR.
- if (CC < 8) {
- FCmpInst::Predicate Pred;
- switch (CC) {
- case 0: Pred = FCmpInst::FCMP_OEQ; break;
- case 1: Pred = FCmpInst::FCMP_OLT; break;
- case 2: Pred = FCmpInst::FCMP_OLE; break;
- case 3: Pred = FCmpInst::FCMP_UNO; break;
- case 4: Pred = FCmpInst::FCMP_UNE; break;
- case 5: Pred = FCmpInst::FCMP_UGE; break;
- case 6: Pred = FCmpInst::FCMP_UGT; break;
- case 7: Pred = FCmpInst::FCMP_ORD; break;
- }
- return getVectorFCmpIR(Pred);
+ case X86::BI__builtin_ia32_cmppd256:
+ case X86::BI__builtin_ia32_cmpps128_mask:
+ case X86::BI__builtin_ia32_cmpps256_mask:
+ case X86::BI__builtin_ia32_cmpps512_mask:
+ case X86::BI__builtin_ia32_cmppd128_mask:
+ case X86::BI__builtin_ia32_cmppd256_mask:
+ case X86::BI__builtin_ia32_cmppd512_mask: {
+ // Lowering vector comparisons to fcmp instructions, while
+ // ignoring signalling behaviour requested
+ // ignoring rounding mode requested
+ // This is is only possible as long as FENV_ACCESS is not implemented.
+ // See also: https://reviews.llvm.org/D45616
+
+ // The third argument is the comparison condition, and integer in the
+ // range [0, 31]
+ unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x1f;
+
+ // Lowering to IR fcmp instruction.
+ // Ignoring requested signaling behaviour,
+ // e.g. both _CMP_GT_OS & _CMP_GT_OQ are translated to FCMP_OGT.
+ FCmpInst::Predicate Pred;
+ switch (CC) {
+ case 0x00: Pred = FCmpInst::FCMP_OEQ; break;
+ case 0x01: Pred = FCmpInst::FCMP_OLT; break;
+ case 0x02: Pred = FCmpInst::FCMP_OLE; break;
+ case 0x03: Pred = FCmpInst::FCMP_UNO; break;
+ case 0x04: Pred = FCmpInst::FCMP_UNE; break;
+ case 0x05: Pred = FCmpInst::FCMP_UGE; break;
+ case 0x06: Pred = FCmpInst::FCMP_UGT; break;
+ case 0x07: Pred = FCmpInst::FCMP_ORD; break;
+ case 0x08: Pred = FCmpInst::FCMP_UEQ; break;
+ case 0x09: Pred = FCmpInst::FCMP_ULT; break;
+ case 0x0a: Pred = FCmpInst::FCMP_ULE; break;
+ case 0x0b: Pred = FCmpInst::FCMP_FALSE; break;
+ case 0x0c: Pred = FCmpInst::FCMP_ONE; break;
+ case 0x0d: Pred = FCmpInst::FCMP_OGE; break;
+ case 0x0e: Pred = FCmpInst::FCMP_OGT; break;
+ case 0x0f: Pred = FCmpInst::FCMP_TRUE; break;
+ case 0x10: Pred = FCmpInst::FCMP_OEQ; break;
+ case 0x11: Pred = FCmpInst::FCMP_OLT; break;
+ case 0x12: Pred = FCmpInst::FCMP_OLE; break;
+ case 0x13: Pred = FCmpInst::FCMP_UNO; break;
+ case 0x14: Pred = FCmpInst::FCMP_UNE; break;
+ case 0x15: Pred = FCmpInst::FCMP_UGE; break;
+ case 0x16: Pred = FCmpInst::FCMP_UGT; break;
+ case 0x17: Pred = FCmpInst::FCMP_ORD; break;
+ case 0x18: Pred = FCmpInst::FCMP_UEQ; break;
+ case 0x19: Pred = FCmpInst::FCMP_ULT; break;
+ case 0x1a: Pred = FCmpInst::FCMP_ULE; break;
+ case 0x1b: Pred = FCmpInst::FCMP_FALSE; break;
+ case 0x1c: Pred = FCmpInst::FCMP_ONE; break;
+ case 0x1d: Pred = FCmpInst::FCMP_OGE; break;
+ case 0x1e: Pred = FCmpInst::FCMP_OGT; break;
+ case 0x1f: Pred = FCmpInst::FCMP_TRUE; break;
+ default: llvm_unreachable("Unhandled CC");
}
- // We can't handle 8-31 immediates with native IR, use the intrinsic.
- // Except for predicates that create constants.
- Intrinsic::ID ID;
+ // Builtins without the _mask suffix return a vector of integers
+ // of the same width as the input vectors
switch (BuiltinID) {
- default: llvm_unreachable("Unsupported intrinsic!");
- case X86::BI__builtin_ia32_cmpps:
- ID = Intrinsic::x86_sse_cmp_ps;
- break;
- case X86::BI__builtin_ia32_cmpps256:
- // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector
- // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0...
- if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) {
- Value *Constant = (CC == 0xf || CC == 0x1f) ?
- llvm::Constant::getAllOnesValue(Builder.getInt32Ty()) :
- llvm::Constant::getNullValue(Builder.getInt32Ty());
- Value *Vec = Builder.CreateVectorSplat(
- Ops[0]->getType()->getVectorNumElements(), Constant);
- return Builder.CreateBitCast(Vec, Ops[0]->getType());
- }
- ID = Intrinsic::x86_avx_cmp_ps_256;
- break;
- case X86::BI__builtin_ia32_cmppd:
- ID = Intrinsic::x86_sse2_cmp_pd;
- break;
- case X86::BI__builtin_ia32_cmppd256:
- // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector
- // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0...
- if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) {
- Value *Constant = (CC == 0xf || CC == 0x1f) ?
- llvm::Constant::getAllOnesValue(Builder.getInt64Ty()) :
- llvm::Constant::getNullValue(Builder.getInt64Ty());
- Value *Vec = Builder.CreateVectorSplat(
- Ops[0]->getType()->getVectorNumElements(), Constant);
- return Builder.CreateBitCast(Vec, Ops[0]->getType());
- }
- ID = Intrinsic::x86_avx_cmp_pd_256;
- break;
+ case X86::BI__builtin_ia32_cmpps512_mask:
+ case X86::BI__builtin_ia32_cmppd512_mask:
+ case X86::BI__builtin_ia32_cmpps128_mask:
+ case X86::BI__builtin_ia32_cmpps256_mask:
+ case X86::BI__builtin_ia32_cmppd128_mask:
+ case X86::BI__builtin_ia32_cmppd256_mask: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ Value *Cmp = Builder.CreateFCmp(Pred, Ops[0], Ops[1]);
+ return EmitX86MaskedCompareResult(*this, Cmp, NumElts, Ops[3]);
+ }
+ default:
+ return getVectorFCmpIR(Pred);
}
-
- return Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
}
// SSE scalar comparison intrinsics
@@ -9199,19 +10844,11 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2));
Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int64Ty, 2));
- // Element zero comes from the first input vector and element one comes from
- // the second. The element indices within each vector are numbered in big
- // endian order so the shuffle mask must be adjusted for this on little
- // endian platforms (i.e. index is complemented and source vector reversed).
- unsigned ElemIdx0;
- unsigned ElemIdx1;
- if (getTarget().isLittleEndian()) {
- ElemIdx0 = (~Index & 1) + 2;
- ElemIdx1 = (~Index & 2) >> 1;
- } else { // BigEndian
- ElemIdx0 = (Index & 2) >> 1;
- ElemIdx1 = 2 + (Index & 1);
- }
+ // Account for endianness by treating this as just a shuffle. So we use the
+ // same indices for both LE and BE in order to produce expected results in
+ // both cases.
+ unsigned ElemIdx0 = (Index & 2) >> 1;
+ unsigned ElemIdx1 = 2 + (Index & 1);
Constant *ShuffleElts[2] = {ConstantInt::get(Int32Ty, ElemIdx0),
ConstantInt::get(Int32Ty, ElemIdx1)};
@@ -9402,6 +11039,49 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
CI->setConvergent();
return CI;
}
+ case AMDGPU::BI__builtin_amdgcn_ds_faddf:
+ case AMDGPU::BI__builtin_amdgcn_ds_fminf:
+ case AMDGPU::BI__builtin_amdgcn_ds_fmaxf: {
+ llvm::SmallVector<llvm::Value *, 5> Args;
+ for (unsigned I = 0; I != 5; ++I)
+ Args.push_back(EmitScalarExpr(E->getArg(I)));
+ const llvm::Type *PtrTy = Args[0]->getType();
+ // check pointer parameter
+ if (!PtrTy->isPointerTy() ||
+ E->getArg(0)
+ ->getType()
+ ->getPointeeType()
+ .getQualifiers()
+ .getAddressSpace() != LangAS::opencl_local ||
+ !PtrTy->getPointerElementType()->isFloatTy()) {
+ CGM.Error(E->getArg(0)->getLocStart(),
+ "parameter should have type \"local float*\"");
+ return nullptr;
+ }
+ // check float parameter
+ if (!Args[1]->getType()->isFloatTy()) {
+ CGM.Error(E->getArg(1)->getLocStart(),
+ "parameter should have type \"float\"");
+ return nullptr;
+ }
+
+ Intrinsic::ID ID;
+ switch (BuiltinID) {
+ case AMDGPU::BI__builtin_amdgcn_ds_faddf:
+ ID = Intrinsic::amdgcn_ds_fadd;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_ds_fminf:
+ ID = Intrinsic::amdgcn_ds_fmin;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_ds_fmaxf:
+ ID = Intrinsic::amdgcn_ds_fmax;
+ break;
+ default:
+ llvm_unreachable("Unknown BuiltinID");
+ }
+ Value *F = CGM.getIntrinsic(ID);
+ return Builder.CreateCall(F, Args);
+ }
// amdgcn workitem
case AMDGPU::BI__builtin_amdgcn_workitem_id_x:
@@ -10032,7 +11712,15 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
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: {
+ case NVPTX::BI__hmma_m16n16k16_ld_c_f32:
+ case NVPTX::BI__hmma_m32n8k16_ld_a:
+ case NVPTX::BI__hmma_m32n8k16_ld_b:
+ case NVPTX::BI__hmma_m32n8k16_ld_c_f16:
+ case NVPTX::BI__hmma_m32n8k16_ld_c_f32:
+ case NVPTX::BI__hmma_m8n32k16_ld_a:
+ case NVPTX::BI__hmma_m8n32k16_ld_b:
+ case NVPTX::BI__hmma_m8n32k16_ld_c_f16:
+ case NVPTX::BI__hmma_m8n32k16_ld_c_f32: {
Address Dst = EmitPointerWithAlignment(E->getArg(0));
Value *Src = EmitScalarExpr(E->getArg(1));
Value *Ldm = EmitScalarExpr(E->getArg(2));
@@ -10044,31 +11732,70 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
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;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_a_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_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;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_b_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_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;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_c_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_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;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_c_f32_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_load_c_f32_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_ld_a:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_a_f16_col_stride
+ : Intrinsic::nvvm_wmma_m32n8k16_load_a_f16_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_ld_b:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_b_f16_col_stride
+ : Intrinsic::nvvm_wmma_m32n8k16_load_b_f16_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_ld_c_f16:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_c_f16_col_stride
+ : Intrinsic::nvvm_wmma_m32n8k16_load_c_f16_row_stride;
+ NumResults = 4;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_ld_c_f32:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_c_f32_col_stride
+ : Intrinsic::nvvm_wmma_m32n8k16_load_c_f32_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_ld_a:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_a_f16_col_stride
+ : Intrinsic::nvvm_wmma_m8n32k16_load_a_f16_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_ld_b:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_b_f16_col_stride
+ : Intrinsic::nvvm_wmma_m8n32k16_load_b_f16_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_ld_c_f16:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_c_f16_col_stride
+ : Intrinsic::nvvm_wmma_m8n32k16_load_c_f16_row_stride;
+ NumResults = 4;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_ld_c_f32:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_c_f32_col_stride
+ : Intrinsic::nvvm_wmma_m8n32k16_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});
+ Builder.CreateCall(CGM.getIntrinsic(IID, Src->getType()), {Src, Ldm});
// Save returned values.
for (unsigned i = 0; i < NumResults; ++i) {
@@ -10082,7 +11809,11 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
}
case NVPTX::BI__hmma_m16n16k16_st_c_f16:
- case NVPTX::BI__hmma_m16n16k16_st_c_f32: {
+ case NVPTX::BI__hmma_m16n16k16_st_c_f32:
+ case NVPTX::BI__hmma_m32n8k16_st_c_f16:
+ case NVPTX::BI__hmma_m32n8k16_st_c_f32:
+ case NVPTX::BI__hmma_m8n32k16_st_c_f16:
+ case NVPTX::BI__hmma_m8n32k16_st_c_f32: {
Value *Dst = EmitScalarExpr(E->getArg(0));
Address Src = EmitPointerWithAlignment(E->getArg(1));
Value *Ldm = EmitScalarExpr(E->getArg(2));
@@ -10096,21 +11827,38 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
// 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;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_store_d_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_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;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_store_d_f32_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_store_d_f32_row_stride;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_st_c_f16:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_store_d_f16_col_stride
+ : Intrinsic::nvvm_wmma_m32n8k16_store_d_f16_row_stride;
+ NumResults = 4;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_st_c_f32:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_store_d_f32_col_stride
+ : Intrinsic::nvvm_wmma_m32n8k16_store_d_f32_row_stride;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_st_c_f16:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_store_d_f16_col_stride
+ : Intrinsic::nvvm_wmma_m8n32k16_store_d_f16_row_stride;
+ NumResults = 4;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_st_c_f32:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_store_d_f32_col_stride
+ : Intrinsic::nvvm_wmma_m8n32k16_store_d_f32_row_stride;
break;
default:
llvm_unreachable("Unexpected builtin ID.");
}
- Function *Intrinsic = CGM.getIntrinsic(IID);
+ Function *Intrinsic = CGM.getIntrinsic(IID, Dst->getType());
llvm::Type *ParamType = Intrinsic->getFunctionType()->getParamType(1);
- SmallVector<Value *, 10> Values;
- Values.push_back(Builder.CreatePointerCast(Dst, VoidPtrTy));
+ SmallVector<Value *, 10> Values = {Dst};
for (unsigned i = 0; i < NumResults; ++i) {
Value *V = Builder.CreateAlignedLoad(
Builder.CreateGEP(Src.getPointer(), llvm::ConstantInt::get(IntTy, i)),
@@ -10122,12 +11870,20 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
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>
+ // BI__hmma_m16n16k16_mma_<Dtype><CType>(d, a, b, c, layout, satf) -->
+ // Intrinsic::nvvm_wmma_m16n16k16_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: {
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
+ case NVPTX::BI__hmma_m32n8k16_mma_f16f16:
+ case NVPTX::BI__hmma_m32n8k16_mma_f32f16:
+ case NVPTX::BI__hmma_m32n8k16_mma_f32f32:
+ case NVPTX::BI__hmma_m32n8k16_mma_f16f32:
+ case NVPTX::BI__hmma_m8n32k16_mma_f16f16:
+ case NVPTX::BI__hmma_m8n32k16_mma_f32f16:
+ case NVPTX::BI__hmma_m8n32k16_mma_f32f32:
+ case NVPTX::BI__hmma_m8n32k16_mma_f16f32: {
Address Dst = EmitPointerWithAlignment(E->getArg(0));
Address SrcA = EmitPointerWithAlignment(E->getArg(1));
Address SrcB = EmitPointerWithAlignment(E->getArg(2));
@@ -10144,15 +11900,15 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
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 \
+#define MMA_VARIANTS(geom, type) {{ \
+ Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type, \
+ Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \
+ Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type, \
+ Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type, \
+ Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type##_satfinite \
}}
// clang-format on
@@ -10166,22 +11922,62 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
unsigned NumEltsD;
switch (BuiltinID) {
case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
- IID = getMMAIntrinsic(MMA_VARIANTS(f16_f16));
+ IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f16_f16));
NumEltsC = 4;
NumEltsD = 4;
break;
case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
- IID = getMMAIntrinsic(MMA_VARIANTS(f32_f16));
+ IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f32_f16));
NumEltsC = 4;
NumEltsD = 8;
break;
case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
- IID = getMMAIntrinsic(MMA_VARIANTS(f16_f32));
+ IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f16_f32));
NumEltsC = 8;
NumEltsD = 4;
break;
case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
- IID = getMMAIntrinsic(MMA_VARIANTS(f32_f32));
+ IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f32_f32));
+ NumEltsC = 8;
+ NumEltsD = 8;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_mma_f16f16:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f16_f16));
+ NumEltsC = 4;
+ NumEltsD = 4;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_mma_f32f16:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f32_f16));
+ NumEltsC = 4;
+ NumEltsD = 8;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_mma_f16f32:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f16_f32));
+ NumEltsC = 8;
+ NumEltsD = 4;
+ break;
+ case NVPTX::BI__hmma_m32n8k16_mma_f32f32:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f32_f32));
+ NumEltsC = 8;
+ NumEltsD = 8;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_mma_f16f16:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f16_f16));
+ NumEltsC = 4;
+ NumEltsD = 4;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_mma_f32f16:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f32_f16));
+ NumEltsC = 4;
+ NumEltsD = 8;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_mma_f16f32:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f16_f32));
+ NumEltsC = 8;
+ NumEltsD = 4;
+ break;
+ case NVPTX::BI__hmma_m8n32k16_mma_f32f32:
+ IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f32_f32));
NumEltsC = 8;
NumEltsD = 8;
break;
@@ -10235,6 +12031,36 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
switch (BuiltinID) {
+ case WebAssembly::BI__builtin_wasm_memory_size: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *I = EmitScalarExpr(E->getArg(0));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_size, ResultType);
+ return Builder.CreateCall(Callee, I);
+ }
+ case WebAssembly::BI__builtin_wasm_memory_grow: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Args[] = {
+ EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1))
+ };
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_grow, ResultType);
+ return Builder.CreateCall(Callee, Args);
+ }
+ case WebAssembly::BI__builtin_wasm_mem_size: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *I = EmitScalarExpr(E->getArg(0));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_mem_size, ResultType);
+ return Builder.CreateCall(Callee, I);
+ }
+ case WebAssembly::BI__builtin_wasm_mem_grow: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Args[] = {
+ EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1))
+ };
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_mem_grow, ResultType);
+ return Builder.CreateCall(Callee, Args);
+ }
case WebAssembly::BI__builtin_wasm_current_memory: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_current_memory, ResultType);
@@ -10266,6 +12092,93 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
SmallVector<llvm::Value *, 4> Ops;
Intrinsic::ID ID = Intrinsic::not_intrinsic;
+ auto MakeCircLd = [&](unsigned IntID, bool HasImm) {
+ // The base pointer is passed by address, so it needs to be loaded.
+ Address BP = EmitPointerWithAlignment(E->getArg(0));
+ BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy),
+ BP.getAlignment());
+ llvm::Value *Base = Builder.CreateLoad(BP);
+ // Operands are Base, Increment, Modifier, Start.
+ if (HasImm)
+ Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)) };
+ else
+ Ops = { Base, EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)) };
+
+ llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
+ llvm::Value *NewBase = Builder.CreateExtractValue(Result, 1);
+ llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)),
+ NewBase->getType()->getPointerTo());
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ // The intrinsic generates two results. The new value for the base pointer
+ // needs to be stored.
+ Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment());
+ return Builder.CreateExtractValue(Result, 0);
+ };
+
+ auto MakeCircSt = [&](unsigned IntID, bool HasImm) {
+ // The base pointer is passed by address, so it needs to be loaded.
+ Address BP = EmitPointerWithAlignment(E->getArg(0));
+ BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy),
+ BP.getAlignment());
+ llvm::Value *Base = Builder.CreateLoad(BP);
+ // Operands are Base, Increment, Modifier, Value, Start.
+ if (HasImm)
+ Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)), EmitScalarExpr(E->getArg(4)) };
+ else
+ Ops = { Base, EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)), EmitScalarExpr(E->getArg(3)) };
+
+ llvm::Value *NewBase = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
+ llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)),
+ NewBase->getType()->getPointerTo());
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ // The intrinsic generates one result, which is the new value for the base
+ // pointer. It needs to be stored.
+ return Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment());
+ };
+
+ // Handle the conversion of bit-reverse load intrinsics to bit code.
+ // The intrinsic call after this function only reads from memory and the
+ // write to memory is dealt by the store instruction.
+ auto MakeBrevLd = [&](unsigned IntID, llvm::Type *DestTy) {
+ // The intrinsic generates one result, which is the new value for the base
+ // pointer. It needs to be returned. The result of the load instruction is
+ // passed to intrinsic by address, so the value needs to be stored.
+ llvm::Value *BaseAddress =
+ Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int8PtrTy);
+
+ // Expressions like &(*pt++) will be incremented per evaluation.
+ // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression
+ // per call.
+ Address DestAddr = EmitPointerWithAlignment(E->getArg(1));
+ DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), Int8PtrTy),
+ DestAddr.getAlignment());
+ llvm::Value *DestAddress = DestAddr.getPointer();
+
+ // Operands are Base, Dest, Modifier.
+ // The intrinsic format in LLVM IR is defined as
+ // { ValueType, i8* } (i8*, i32).
+ Ops = {BaseAddress, EmitScalarExpr(E->getArg(2))};
+
+ llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
+ // The value needs to be stored as the variable is passed by reference.
+ llvm::Value *DestVal = Builder.CreateExtractValue(Result, 0);
+
+ // The store needs to be truncated to fit the destination type.
+ // While i32 and i64 are natively supported on Hexagon, i8 and i16 needs
+ // to be handled with stores of respective destination type.
+ DestVal = Builder.CreateTrunc(DestVal, DestTy);
+
+ llvm::Value *DestForStore =
+ Builder.CreateBitCast(DestAddress, DestVal->getType()->getPointerTo());
+ Builder.CreateAlignedStore(DestVal, DestForStore, DestAddr.getAlignment());
+ // The updated value of the base pointer is returned.
+ return Builder.CreateExtractValue(Result, 1);
+ };
+
switch (BuiltinID) {
case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry:
case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: {
@@ -10311,6 +12224,64 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment());
return Builder.CreateExtractValue(Result, 0);
}
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadri_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadri_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadri_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadri_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerb_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerb_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerh_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerh_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerf_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerf_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_S2_storeri_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storeri_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerd_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerd_pci, /*HasImm*/true);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerb_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerb_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerh_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerh_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerf_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerf_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storeri_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storeri_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerd_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerd_pcr, /*HasImm*/false);
+ case Hexagon::BI__builtin_brev_ldub:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrub_pbr, Int8Ty);
+ case Hexagon::BI__builtin_brev_ldb:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrb_pbr, Int8Ty);
+ case Hexagon::BI__builtin_brev_lduh:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadruh_pbr, Int16Ty);
+ case Hexagon::BI__builtin_brev_ldh:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrh_pbr, Int16Ty);
+ case Hexagon::BI__builtin_brev_ldw:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadri_pbr, Int32Ty);
+ case Hexagon::BI__builtin_brev_ldd:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrd_pbr, Int64Ty);
+ default:
+ break;
} // switch
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
index d24ef0a8a974..5fcc9e011bcb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
@@ -15,17 +15,20 @@
#include "CGCUDARuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
-#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/Decl.h"
+#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Support/Format.h"
using namespace clang;
using namespace CodeGen;
namespace {
+constexpr unsigned CudaFatMagic = 0x466243b1;
+constexpr unsigned HIPFatMagic = 0x48495046; // "HIPF"
class CGNVCUDARuntime : public CGCUDARuntime {
@@ -41,14 +44,22 @@ private:
/// Keeps track of kernel launch stubs emitted in this module
llvm::SmallVector<llvm::Function *, 16> EmittedKernels;
llvm::SmallVector<std::pair<llvm::GlobalVariable *, unsigned>, 16> DeviceVars;
- /// Keeps track of variables containing handles of GPU binaries. Populated by
+ /// Keeps track of variable containing handle of GPU binary. Populated by
/// ModuleCtorFunction() and used to create corresponding cleanup calls in
/// ModuleDtorFunction()
- llvm::SmallVector<llvm::GlobalVariable *, 16> GpuBinaryHandles;
+ llvm::GlobalVariable *GpuBinaryHandle = nullptr;
+ /// Whether we generate relocatable device code.
+ bool RelocatableDeviceCode;
llvm::Constant *getSetupArgumentFn() const;
llvm::Constant *getLaunchFn() const;
+ llvm::FunctionType *getRegisterGlobalsFnTy() const;
+ llvm::FunctionType *getCallbackFnTy() const;
+ llvm::FunctionType *getRegisterLinkedBinaryFnTy() const;
+ std::string addPrefixToName(StringRef FuncName) const;
+ std::string addUnderscoredPrefixToName(StringRef FuncName) const;
+
/// Creates a function to register all kernel stubs generated in this module.
llvm::Function *makeRegisterGlobalsFn();
@@ -64,14 +75,34 @@ private:
auto ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
llvm::GlobalVariable *GV =
cast<llvm::GlobalVariable>(ConstStr.getPointer());
- if (!SectionName.empty())
+ if (!SectionName.empty()) {
GV->setSection(SectionName);
+ // Mark the address as used which make sure that this section isn't
+ // merged and we will really have it in the object file.
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
+ }
if (Alignment)
GV->setAlignment(Alignment);
return llvm::ConstantExpr::getGetElementPtr(ConstStr.getElementType(),
ConstStr.getPointer(), Zeros);
- }
+ }
+
+ /// Helper function that generates an empty dummy function returning void.
+ llvm::Function *makeDummyFunction(llvm::FunctionType *FnTy) {
+ assert(FnTy->getReturnType()->isVoidTy() &&
+ "Can only generate dummy functions returning void!");
+ llvm::Function *DummyFunc = llvm::Function::Create(
+ FnTy, llvm::GlobalValue::InternalLinkage, "dummy", &TheModule);
+
+ llvm::BasicBlock *DummyBlock =
+ llvm::BasicBlock::Create(Context, "", DummyFunc);
+ CGBuilderTy FuncBuilder(CGM, Context);
+ FuncBuilder.SetInsertPoint(DummyBlock);
+ FuncBuilder.CreateRetVoid();
+
+ return DummyFunc;
+ }
void emitDeviceStubBody(CodeGenFunction &CGF, FunctionArgList &Args);
@@ -91,9 +122,22 @@ public:
}
+std::string CGNVCUDARuntime::addPrefixToName(StringRef FuncName) const {
+ if (CGM.getLangOpts().HIP)
+ return ((Twine("hip") + Twine(FuncName)).str());
+ return ((Twine("cuda") + Twine(FuncName)).str());
+}
+std::string
+CGNVCUDARuntime::addUnderscoredPrefixToName(StringRef FuncName) const {
+ if (CGM.getLangOpts().HIP)
+ return ((Twine("__hip") + Twine(FuncName)).str());
+ return ((Twine("__cuda") + Twine(FuncName)).str());
+}
+
CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
: CGCUDARuntime(CGM), Context(CGM.getLLVMContext()),
- TheModule(CGM.getModule()) {
+ TheModule(CGM.getModule()),
+ RelocatableDeviceCode(CGM.getLangOpts().CUDARelocatableDeviceCode) {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -109,15 +153,37 @@ CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
llvm::Constant *CGNVCUDARuntime::getSetupArgumentFn() const {
// cudaError_t cudaSetupArgument(void *, size_t, size_t)
llvm::Type *Params[] = {VoidPtrTy, SizeTy, SizeTy};
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(IntTy,
- Params, false),
- "cudaSetupArgument");
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, Params, false),
+ addPrefixToName("SetupArgument"));
}
llvm::Constant *CGNVCUDARuntime::getLaunchFn() const {
- // cudaError_t cudaLaunch(char *)
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, CharPtrTy, false), "cudaLaunch");
+ if (CGM.getLangOpts().HIP) {
+ // hipError_t hipLaunchByPtr(char *);
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, CharPtrTy, false), "hipLaunchByPtr");
+ } else {
+ // cudaError_t cudaLaunch(char *);
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, CharPtrTy, false), "cudaLaunch");
+ }
+}
+
+llvm::FunctionType *CGNVCUDARuntime::getRegisterGlobalsFnTy() const {
+ return llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false);
+}
+
+llvm::FunctionType *CGNVCUDARuntime::getCallbackFnTy() const {
+ return llvm::FunctionType::get(VoidTy, VoidPtrTy, false);
+}
+
+llvm::FunctionType *CGNVCUDARuntime::getRegisterLinkedBinaryFnTy() const {
+ auto CallbackFnTy = getCallbackFnTy();
+ auto RegisterGlobalsFnTy = getRegisterGlobalsFnTy();
+ llvm::Type *Params[] = {RegisterGlobalsFnTy->getPointerTo(), VoidPtrTy,
+ VoidPtrTy, CallbackFnTy->getPointerTo()};
+ return llvm::FunctionType::get(VoidTy, Params, false);
}
void CGNVCUDARuntime::emitDeviceStub(CodeGenFunction &CGF,
@@ -181,8 +247,8 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() {
return nullptr;
llvm::Function *RegisterKernelsFunc = llvm::Function::Create(
- llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false),
- llvm::GlobalValue::InternalLinkage, "__cuda_register_globals", &TheModule);
+ getRegisterGlobalsFnTy(), llvm::GlobalValue::InternalLinkage,
+ addUnderscoredPrefixToName("_register_globals"), &TheModule);
llvm::BasicBlock *EntryBB =
llvm::BasicBlock::Create(Context, "entry", RegisterKernelsFunc);
CGBuilderTy Builder(CGM, Context);
@@ -195,7 +261,7 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() {
VoidPtrTy, VoidPtrTy, VoidPtrTy, VoidPtrTy, IntTy->getPointerTo()};
llvm::Constant *RegisterFunc = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, RegisterFuncParams, false),
- "__cudaRegisterFunction");
+ addUnderscoredPrefixToName("RegisterFunction"));
// Extract GpuBinaryHandle passed as the first argument passed to
// __cuda_register_globals() and generate __cudaRegisterFunction() call for
@@ -219,7 +285,7 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() {
IntTy, IntTy};
llvm::Constant *RegisterVar = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, RegisterVarParams, false),
- "__cudaRegisterVar");
+ addUnderscoredPrefixToName("RegisterVar"));
for (auto &Pair : DeviceVars) {
llvm::GlobalVariable *Var = Pair.first;
unsigned Flags = Pair.second;
@@ -243,133 +309,307 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() {
}
/// Creates a global constructor function for the module:
+///
+/// For CUDA:
/// \code
/// void __cuda_module_ctor(void*) {
-/// Handle0 = __cudaRegisterFatBinary(GpuBinaryBlob0);
-/// __cuda_register_globals(Handle0);
-/// ...
-/// HandleN = __cudaRegisterFatBinary(GpuBinaryBlobN);
-/// __cuda_register_globals(HandleN);
+/// Handle = __cudaRegisterFatBinary(GpuBinaryBlob);
+/// __cuda_register_globals(Handle);
+/// }
+/// \endcode
+///
+/// For HIP:
+/// \code
+/// void __hip_module_ctor(void*) {
+/// if (__hip_gpubin_handle == 0) {
+/// __hip_gpubin_handle = __hipRegisterFatBinary(GpuBinaryBlob);
+/// __hip_register_globals(__hip_gpubin_handle);
+/// }
/// }
/// \endcode
llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
- // No need to generate ctors/dtors if there are no GPU binaries.
- if (CGM.getCodeGenOpts().CudaGpuBinaryFileNames.empty())
+ bool IsHIP = CGM.getLangOpts().HIP;
+ // No need to generate ctors/dtors if there is no GPU binary.
+ StringRef CudaGpuBinaryFileName = CGM.getCodeGenOpts().CudaGpuBinaryFileName;
+ if (CudaGpuBinaryFileName.empty() && !IsHIP)
return nullptr;
- // void __cuda_register_globals(void* handle);
+ // void __{cuda|hip}_register_globals(void* handle);
llvm::Function *RegisterGlobalsFunc = makeRegisterGlobalsFn();
- // void ** __cudaRegisterFatBinary(void *);
+ // We always need a function to pass in as callback. Create a dummy
+ // implementation if we don't need to register anything.
+ if (RelocatableDeviceCode && !RegisterGlobalsFunc)
+ RegisterGlobalsFunc = makeDummyFunction(getRegisterGlobalsFnTy());
+
+ // void ** __{cuda|hip}RegisterFatBinary(void *);
llvm::Constant *RegisterFatbinFunc = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(VoidPtrPtrTy, VoidPtrTy, false),
- "__cudaRegisterFatBinary");
+ addUnderscoredPrefixToName("RegisterFatBinary"));
// struct { int magic, int version, void * gpu_binary, void * dont_care };
llvm::StructType *FatbinWrapperTy =
llvm::StructType::get(IntTy, IntTy, VoidPtrTy, VoidPtrTy);
+ // Register GPU binary with the CUDA runtime, store returned handle in a
+ // global variable and save a reference in GpuBinaryHandle to be cleaned up
+ // in destructor on exit. Then associate all known kernels with the GPU binary
+ // handle so CUDA runtime can figure out what to call on the GPU side.
+ std::unique_ptr<llvm::MemoryBuffer> CudaGpuBinary;
+ if (!IsHIP) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CudaGpuBinaryOrErr =
+ llvm::MemoryBuffer::getFileOrSTDIN(CudaGpuBinaryFileName);
+ if (std::error_code EC = CudaGpuBinaryOrErr.getError()) {
+ CGM.getDiags().Report(diag::err_cannot_open_file)
+ << CudaGpuBinaryFileName << EC.message();
+ return nullptr;
+ }
+ CudaGpuBinary = std::move(CudaGpuBinaryOrErr.get());
+ }
+
llvm::Function *ModuleCtorFunc = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, VoidPtrTy, false),
- llvm::GlobalValue::InternalLinkage, "__cuda_module_ctor", &TheModule);
+ llvm::GlobalValue::InternalLinkage,
+ addUnderscoredPrefixToName("_module_ctor"), &TheModule);
llvm::BasicBlock *CtorEntryBB =
llvm::BasicBlock::Create(Context, "entry", ModuleCtorFunc);
CGBuilderTy CtorBuilder(CGM, Context);
CtorBuilder.SetInsertPoint(CtorEntryBB);
- // For each GPU binary, register it with the CUDA runtime and store returned
- // handle in a global variable and save the handle in GpuBinaryHandles vector
- // to be cleaned up in destructor on exit. Then associate all known kernels
- // with the GPU binary handle so CUDA runtime can figure out what to call on
- // the GPU side.
- for (const std::string &GpuBinaryFileName :
- CGM.getCodeGenOpts().CudaGpuBinaryFileNames) {
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> GpuBinaryOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(GpuBinaryFileName);
- if (std::error_code EC = GpuBinaryOrErr.getError()) {
- CGM.getDiags().Report(diag::err_cannot_open_file) << GpuBinaryFileName
- << EC.message();
- continue;
- }
-
- const char *FatbinConstantName =
- CGM.getTriple().isMacOSX() ? "__NV_CUDA,__nv_fatbin" : ".nv_fatbin";
+ const char *FatbinConstantName;
+ const char *FatbinSectionName;
+ const char *ModuleIDSectionName;
+ StringRef ModuleIDPrefix;
+ llvm::Constant *FatBinStr;
+ unsigned FatMagic;
+ if (IsHIP) {
+ FatbinConstantName = ".hip_fatbin";
+ FatbinSectionName = ".hipFatBinSegment";
+
+ ModuleIDSectionName = "__hip_module_id";
+ ModuleIDPrefix = "__hip_";
+
+ // For HIP, create an external symbol __hip_fatbin in section .hip_fatbin.
+ // The external symbol is supposed to contain the fat binary but will be
+ // populated somewhere else, e.g. by lld through link script.
+ FatBinStr = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty,
+ /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr,
+ "__hip_fatbin", nullptr,
+ llvm::GlobalVariable::NotThreadLocal);
+ cast<llvm::GlobalVariable>(FatBinStr)->setSection(FatbinConstantName);
+
+ FatMagic = HIPFatMagic;
+ } else {
+ if (RelocatableDeviceCode)
+ FatbinConstantName = CGM.getTriple().isMacOSX()
+ ? "__NV_CUDA,__nv_relfatbin"
+ : "__nv_relfatbin";
+ else
+ FatbinConstantName =
+ CGM.getTriple().isMacOSX() ? "__NV_CUDA,__nv_fatbin" : ".nv_fatbin";
// NVIDIA's cuobjdump looks for fatbins in this section.
- const char *FatbinSectionName =
+ FatbinSectionName =
CGM.getTriple().isMacOSX() ? "__NV_CUDA,__fatbin" : ".nvFatBinSegment";
- // Create initialized wrapper structure that points to the loaded GPU binary
- ConstantInitBuilder Builder(CGM);
- auto Values = Builder.beginStruct(FatbinWrapperTy);
- // Fatbin wrapper magic.
- Values.addInt(IntTy, 0x466243b1);
- // Fatbin version.
- Values.addInt(IntTy, 1);
- // Data.
- Values.add(makeConstantString(GpuBinaryOrErr.get()->getBuffer(),
- "", FatbinConstantName, 8));
- // Unused in fatbin v1.
- Values.add(llvm::ConstantPointerNull::get(VoidPtrTy));
- llvm::GlobalVariable *FatbinWrapper =
- Values.finishAndCreateGlobal("__cuda_fatbin_wrapper",
- CGM.getPointerAlign(),
- /*constant*/ true);
- FatbinWrapper->setSection(FatbinSectionName);
+ ModuleIDSectionName = CGM.getTriple().isMacOSX()
+ ? "__NV_CUDA,__nv_module_id"
+ : "__nv_module_id";
+ ModuleIDPrefix = "__nv_";
+
+ // For CUDA, create a string literal containing the fat binary loaded from
+ // the given file.
+ FatBinStr = makeConstantString(CudaGpuBinary->getBuffer(), "",
+ FatbinConstantName, 8);
+ FatMagic = CudaFatMagic;
+ }
+ // Create initialized wrapper structure that points to the loaded GPU binary
+ ConstantInitBuilder Builder(CGM);
+ auto Values = Builder.beginStruct(FatbinWrapperTy);
+ // Fatbin wrapper magic.
+ Values.addInt(IntTy, FatMagic);
+ // Fatbin version.
+ Values.addInt(IntTy, 1);
+ // Data.
+ Values.add(FatBinStr);
+ // Unused in fatbin v1.
+ Values.add(llvm::ConstantPointerNull::get(VoidPtrTy));
+ llvm::GlobalVariable *FatbinWrapper = Values.finishAndCreateGlobal(
+ addUnderscoredPrefixToName("_fatbin_wrapper"), CGM.getPointerAlign(),
+ /*constant*/ true);
+ FatbinWrapper->setSection(FatbinSectionName);
+
+ // There is only one HIP fat binary per linked module, however there are
+ // multiple constructor functions. Make sure the fat binary is registered
+ // only once. The constructor functions are executed by the dynamic loader
+ // before the program gains control. The dynamic loader cannot execute the
+ // constructor functions concurrently since doing that would not guarantee
+ // thread safety of the loaded program. Therefore we can assume sequential
+ // execution of constructor functions here.
+ if (IsHIP) {
+ llvm::BasicBlock *IfBlock =
+ llvm::BasicBlock::Create(Context, "if", ModuleCtorFunc);
+ llvm::BasicBlock *ExitBlock =
+ llvm::BasicBlock::Create(Context, "exit", ModuleCtorFunc);
+ // The name, size, and initialization pattern of this variable is part
+ // of HIP ABI.
+ GpuBinaryHandle = new llvm::GlobalVariable(
+ TheModule, VoidPtrPtrTy, /*isConstant=*/false,
+ llvm::GlobalValue::LinkOnceAnyLinkage,
+ /*Initializer=*/llvm::ConstantPointerNull::get(VoidPtrPtrTy),
+ "__hip_gpubin_handle");
+ GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity());
+ Address GpuBinaryAddr(
+ GpuBinaryHandle,
+ CharUnits::fromQuantity(GpuBinaryHandle->getAlignment()));
+ {
+ auto HandleValue = CtorBuilder.CreateLoad(GpuBinaryAddr);
+ llvm::Constant *Zero =
+ llvm::Constant::getNullValue(HandleValue->getType());
+ llvm::Value *EQZero = CtorBuilder.CreateICmpEQ(HandleValue, Zero);
+ CtorBuilder.CreateCondBr(EQZero, IfBlock, ExitBlock);
+ }
+ {
+ CtorBuilder.SetInsertPoint(IfBlock);
+ // GpuBinaryHandle = __hipRegisterFatBinary(&FatbinWrapper);
+ llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall(
+ RegisterFatbinFunc,
+ CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy));
+ CtorBuilder.CreateStore(RegisterFatbinCall, GpuBinaryAddr);
+ CtorBuilder.CreateBr(ExitBlock);
+ }
+ {
+ CtorBuilder.SetInsertPoint(ExitBlock);
+ // Call __hip_register_globals(GpuBinaryHandle);
+ if (RegisterGlobalsFunc) {
+ auto HandleValue = CtorBuilder.CreateLoad(GpuBinaryAddr);
+ CtorBuilder.CreateCall(RegisterGlobalsFunc, HandleValue);
+ }
+ }
+ } else if (!RelocatableDeviceCode) {
+ // Register binary with CUDA runtime. This is substantially different in
+ // default mode vs. separate compilation!
// GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper);
llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall(
RegisterFatbinFunc,
CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy));
- llvm::GlobalVariable *GpuBinaryHandle = new llvm::GlobalVariable(
+ GpuBinaryHandle = new llvm::GlobalVariable(
TheModule, VoidPtrPtrTy, false, llvm::GlobalValue::InternalLinkage,
llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__cuda_gpubin_handle");
+ GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity());
CtorBuilder.CreateAlignedStore(RegisterFatbinCall, GpuBinaryHandle,
CGM.getPointerAlign());
// Call __cuda_register_globals(GpuBinaryHandle);
if (RegisterGlobalsFunc)
CtorBuilder.CreateCall(RegisterGlobalsFunc, RegisterFatbinCall);
+ } else {
+ // Generate a unique module ID.
+ SmallString<64> ModuleID;
+ llvm::raw_svector_ostream OS(ModuleID);
+ OS << ModuleIDPrefix << llvm::format("%x", FatbinWrapper->getGUID());
+ llvm::Constant *ModuleIDConstant =
+ makeConstantString(ModuleID.str(), "", ModuleIDSectionName, 32);
+
+ // Create an alias for the FatbinWrapper that nvcc will look for.
+ llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage,
+ Twine("__fatbinwrap") + ModuleID, FatbinWrapper);
+
+ // void __cudaRegisterLinkedBinary%ModuleID%(void (*)(void *), void *,
+ // void *, void (*)(void **))
+ SmallString<128> RegisterLinkedBinaryName("__cudaRegisterLinkedBinary");
+ RegisterLinkedBinaryName += ModuleID;
+ llvm::Constant *RegisterLinkedBinaryFunc = CGM.CreateRuntimeFunction(
+ getRegisterLinkedBinaryFnTy(), RegisterLinkedBinaryName);
+
+ assert(RegisterGlobalsFunc && "Expecting at least dummy function!");
+ llvm::Value *Args[] = {RegisterGlobalsFunc,
+ CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy),
+ ModuleIDConstant,
+ makeDummyFunction(getCallbackFnTy())};
+ CtorBuilder.CreateCall(RegisterLinkedBinaryFunc, Args);
+ }
- // Save GpuBinaryHandle so we can unregister it in destructor.
- GpuBinaryHandles.push_back(GpuBinaryHandle);
+ // Create destructor and register it with atexit() the way NVCC does it. Doing
+ // it during regular destructor phase worked in CUDA before 9.2 but results in
+ // double-free in 9.2.
+ if (llvm::Function *CleanupFn = makeModuleDtorFunction()) {
+ // extern "C" int atexit(void (*f)(void));
+ llvm::FunctionType *AtExitTy =
+ llvm::FunctionType::get(IntTy, CleanupFn->getType(), false);
+ llvm::Constant *AtExitFunc =
+ CGM.CreateRuntimeFunction(AtExitTy, "atexit", llvm::AttributeList(),
+ /*Local=*/true);
+ CtorBuilder.CreateCall(AtExitFunc, CleanupFn);
}
CtorBuilder.CreateRetVoid();
return ModuleCtorFunc;
}
-/// Creates a global destructor function that unregisters all GPU code blobs
+/// Creates a global destructor function that unregisters the GPU code blob
/// registered by constructor.
+///
+/// For CUDA:
/// \code
/// void __cuda_module_dtor(void*) {
-/// __cudaUnregisterFatBinary(Handle0);
-/// ...
-/// __cudaUnregisterFatBinary(HandleN);
+/// __cudaUnregisterFatBinary(Handle);
+/// }
+/// \endcode
+///
+/// For HIP:
+/// \code
+/// void __hip_module_dtor(void*) {
+/// if (__hip_gpubin_handle) {
+/// __hipUnregisterFatBinary(__hip_gpubin_handle);
+/// __hip_gpubin_handle = 0;
+/// }
/// }
/// \endcode
llvm::Function *CGNVCUDARuntime::makeModuleDtorFunction() {
- // No need for destructor if we don't have handles to unregister.
- if (GpuBinaryHandles.empty())
+ // No need for destructor if we don't have a handle to unregister.
+ if (!GpuBinaryHandle)
return nullptr;
// void __cudaUnregisterFatBinary(void ** handle);
llvm::Constant *UnregisterFatbinFunc = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false),
- "__cudaUnregisterFatBinary");
+ addUnderscoredPrefixToName("UnregisterFatBinary"));
llvm::Function *ModuleDtorFunc = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, VoidPtrTy, false),
- llvm::GlobalValue::InternalLinkage, "__cuda_module_dtor", &TheModule);
+ llvm::GlobalValue::InternalLinkage,
+ addUnderscoredPrefixToName("_module_dtor"), &TheModule);
+
llvm::BasicBlock *DtorEntryBB =
llvm::BasicBlock::Create(Context, "entry", ModuleDtorFunc);
CGBuilderTy DtorBuilder(CGM, Context);
DtorBuilder.SetInsertPoint(DtorEntryBB);
- for (llvm::GlobalVariable *GpuBinaryHandle : GpuBinaryHandles) {
- auto HandleValue =
- DtorBuilder.CreateAlignedLoad(GpuBinaryHandle, CGM.getPointerAlign());
+ Address GpuBinaryAddr(GpuBinaryHandle, CharUnits::fromQuantity(
+ GpuBinaryHandle->getAlignment()));
+ auto HandleValue = DtorBuilder.CreateLoad(GpuBinaryAddr);
+ // There is only one HIP fat binary per linked module, however there are
+ // multiple destructor functions. Make sure the fat binary is unregistered
+ // only once.
+ if (CGM.getLangOpts().HIP) {
+ llvm::BasicBlock *IfBlock =
+ llvm::BasicBlock::Create(Context, "if", ModuleDtorFunc);
+ llvm::BasicBlock *ExitBlock =
+ llvm::BasicBlock::Create(Context, "exit", ModuleDtorFunc);
+ llvm::Constant *Zero = llvm::Constant::getNullValue(HandleValue->getType());
+ llvm::Value *NEZero = DtorBuilder.CreateICmpNE(HandleValue, Zero);
+ DtorBuilder.CreateCondBr(NEZero, IfBlock, ExitBlock);
+
+ DtorBuilder.SetInsertPoint(IfBlock);
DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue);
- }
+ DtorBuilder.CreateStore(Zero, GpuBinaryAddr);
+ DtorBuilder.CreateBr(ExitBlock);
+ DtorBuilder.SetInsertPoint(ExitBlock);
+ } else {
+ DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue);
+ }
DtorBuilder.CreateRetVoid();
return ModuleDtorFunc;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
index 5ef4dc45fba1..d5945be43458 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
@@ -109,17 +109,8 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
D->getType()->getAs<FunctionType>()->getCallConv())
return true;
- return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
- 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) {
- if (!getCodeGenOpts().CXXCtorDtorAliases)
- return true;
+ GlobalDecl AliasDecl(D, Dtor_Base);
+ GlobalDecl TargetDecl(BaseD, Dtor_Base);
// The alias will use the linkage of the referent. If we can't
// support aliases with that linkage, fail.
@@ -193,6 +184,9 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
Aliasee, &getModule());
+ // Destructors are always unnamed_addr.
+ Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
// Switch any previous uses to the alias.
if (Entry) {
assert(Entry->getType() == AliasType &&
@@ -205,7 +199,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
}
// Finally, set up the alias with its proper name and attributes.
- setAliasAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
+ SetCommonAttributes(AliasDecl, Alias);
return false;
}
@@ -227,10 +221,9 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
}
setFunctionLinkage(GD, Fn);
- setFunctionDLLStorageClass(GD, Fn);
CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo);
- setFunctionDefinitionAttributes(MD, Fn);
+ setNonAliasAttributes(GD, Fn);
SetLLVMFunctionAttributesForDefinition(MD, Fn);
return Fn;
}
@@ -243,6 +236,11 @@ llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
} else {
+ // Always alias equivalent complete destructors to base destructors in the
+ // MS ABI.
+ if (getTarget().getCXXABI().isMicrosoft() &&
+ Type == StructorType::Complete && MD->getParent()->getNumVBases() == 0)
+ Type = StructorType::Base;
GD = GlobalDecl(cast<CXXDestructorDecl>(MD), toCXXDtorType(Type));
}
@@ -263,7 +261,6 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() &&
"No kext in Microsoft ABI");
- GD = GD.getCanonicalDecl();
CodeGenModule &CGM = CGF.CGM;
llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
Ty = Ty->getPointerTo()->getPointerTo();
@@ -279,7 +276,7 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
llvm::Value *VFunc =
CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes);
- CGCallee Callee(GD.getDecl(), VFunc);
+ CGCallee Callee(GD.getDecl()->getCanonicalDecl(), VFunc);
return Callee;
}
@@ -287,12 +284,12 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
/// indirect call to virtual functions. It makes the call through indexing
/// into the vtable.
CGCallee
-CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Type *Ty) {
assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
"BuildAppleKextVirtualCall - bad Qual kind");
-
+
const Type *QTy = Qual->getAsType();
QualType T = QualType(QTy, 0);
const RecordType *RT = T->getAs<RecordType>();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
index a27c3e9d27e3..3b1b47cdfe07 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
@@ -51,9 +51,9 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
ErrorUnsupportedABI(CGF, "calls through member pointers");
ThisPtrForCall = This.getPointer();
- 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(
CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
@@ -287,6 +287,20 @@ CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
return nullptr;
}
+void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const {
+ // Assume the base C++ ABI has no special rules for destructor variants.
+ CGM.setDLLImportDLLExport(GV, Dtor);
+}
+
+llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(
+ GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
+ // Delegate back to CGM by default.
+ return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
+ /*isConstantVariable=*/false);
+}
+
bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
index 83426dc3a03c..65b50e14f436 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
@@ -40,7 +40,7 @@ class CodeGenFunction;
class CodeGenModule;
struct CatchTypeInfo;
-/// \brief Implements C++ ABI-specific code generation functions.
+/// Implements C++ ABI-specific code generation functions.
class CGCXXABI {
protected:
CodeGenModule &CGM;
@@ -222,7 +222,7 @@ protected:
/// is required.
llvm::Constant *getMemberPointerAdjustment(const CastExpr *E);
- /// \brief Computes the non-virtual adjustment needed for a member pointer
+ /// Computes the non-virtual adjustment needed for a member pointer
/// conversion along an inheritance path stored in an APValue. Unlike
/// getMemberPointerAdjustment(), the adjustment can be negative if the path
/// is from a derived type to a base type.
@@ -237,7 +237,7 @@ public:
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
- /// \brief Determine whether it's possible to emit a vtable for \p RD, even
+ /// Determine whether it's possible to emit a vtable for \p RD, even
/// though we do not know that the vtable has been marked as used by semantic
/// analysis.
virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const = 0;
@@ -319,6 +319,14 @@ public:
virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
CXXDtorType DT) const = 0;
+ virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const;
+
+ virtual llvm::GlobalValue::LinkageTypes
+ getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const;
+
/// Emit destructor variants required by this ABI.
virtual void EmitCXXDestructors(const CXXDestructorDecl *D) = 0;
@@ -414,8 +422,7 @@ public:
/// Build a virtual function pointer in the ABI-specific way.
virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF,
- GlobalDecl GD,
- Address This,
+ GlobalDecl GD, Address This,
llvm::Type *Ty,
SourceLocation Loc) = 0;
@@ -434,6 +441,7 @@ public:
/// base tables.
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;
+ virtual bool exportThunk() = 0;
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
GlobalDecl GD, bool ReturnAdjustment) = 0;
@@ -599,6 +607,17 @@ CGCXXABI *CreateItaniumCXXABI(CodeGenModule &CGM);
/// Creates a Microsoft-family ABI.
CGCXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM);
+struct CatchRetScope final : EHScopeStack::Cleanup {
+ llvm::CatchPadInst *CPI;
+
+ CatchRetScope(llvm::CatchPadInst *CPI) : CPI(CPI) {}
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ llvm::BasicBlock *BB = CGF.createBasicBlock("catchret.dest");
+ CGF.Builder.CreateCatchRet(CPI, BB);
+ CGF.EmitBlock(BB);
+ }
+};
}
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 38d7344572d3..fa51dc30c58b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -29,15 +29,15 @@
#include "clang/CodeGen/SwiftCallingConv.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Attributes.h"
-#include "llvm/IR/CallingConv.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/IR/Intrinsics.h"
using namespace clang;
using namespace CodeGen;
@@ -255,6 +255,16 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(), MD);
}
+/// Set calling convention for CUDA/HIP kernel.
+static void setCUDAKernelCallingConvention(CanQualType &FTy, CodeGenModule &CGM,
+ const FunctionDecl *FD) {
+ if (FD->hasAttr<CUDAGlobalAttr>()) {
+ const FunctionType *FT = FTy->getAs<FunctionType>();
+ CGM.getTargetCodeGenInfo().setCUDAKernelCallingConvention(FT);
+ FTy = FT->getCanonicalTypeUnqualified();
+ }
+}
+
/// Arrange the argument and result information for a declaration or
/// definition of the given C++ non-static member function. The
/// member function must be an ordinary function, i.e. not a
@@ -264,7 +274,9 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
assert(!isa<CXXConstructorDecl>(MD) && "wrong method for constructors!");
assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
- CanQual<FunctionProtoType> prototype = GetFormalType(MD);
+ CanQualType FT = GetFormalType(MD).getAs<Type>();
+ setCUDAKernelCallingConvention(FT, CGM, MD);
+ auto prototype = FT.getAs<FunctionProtoType>();
if (MD->isInstance()) {
// The abstract case is perfectly fine.
@@ -424,6 +436,7 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified();
assert(isa<FunctionType>(FTy));
+ setCUDAKernelCallingConvention(FTy, CGM, FD);
// When declaring a function without a prototype, always use a
// non-variadic type.
@@ -513,8 +526,8 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
/// correct type, and the caller will bitcast the function to the correct
/// prototype.
const CGFunctionInfo &
-CodeGenTypes::arrangeMSMemberPointerThunk(const CXXMethodDecl *MD) {
- assert(MD->isVirtual() && "only virtual memptrs have thunks");
+CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
+ assert(MD->isVirtual() && "only methods have thunks");
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
@@ -776,7 +789,7 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
bool erased = FunctionsBeingProcessed.erase(FI); (void)erased;
assert(erased && "Not in set?");
-
+
return *FI;
}
@@ -803,6 +816,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
FI->NoReturn = info.getNoReturn();
FI->ReturnsRetained = info.getProducesResult();
FI->NoCallerSavedRegs = info.getNoCallerSavedRegs();
+ FI->NoCfCheck = info.getNoCfCheck();
FI->Required = required;
FI->HasRegParm = info.getHasRegParm();
FI->RegParm = info.getRegParm();
@@ -904,8 +918,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
CharUnits UnionSize = CharUnits::Zero();
for (const auto *FD : RD->fields()) {
- // Skip zero length bitfields.
- if (FD->isBitField() && FD->getBitWidthValue(Context) == 0)
+ if (FD->isZeroLengthBitField(Context))
continue;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
@@ -926,8 +939,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
}
for (const auto *FD : RD->fields()) {
- // Skip zero length bitfields.
- if (FD->isBitField() && FD->getBitWidthValue(Context) == 0)
+ if (FD->isZeroLengthBitField(Context))
continue;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
@@ -1040,42 +1052,49 @@ void CodeGenFunction::ExpandTypeFromArgs(
}
void CodeGenFunction::ExpandTypeToArgs(
- QualType Ty, RValue RV, llvm::FunctionType *IRFuncTy,
+ QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy,
SmallVectorImpl<llvm::Value *> &IRCallArgs, unsigned &IRCallArgPos) {
auto Exp = getTypeExpansion(Ty, getContext());
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
- forConstantArrayExpansion(*this, CAExp, RV.getAggregateAddress(),
- [&](Address EltAddr) {
- RValue EltRV =
- convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation());
- ExpandTypeToArgs(CAExp->EltTy, EltRV, IRFuncTy, IRCallArgs, IRCallArgPos);
- });
+ Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress()
+ : Arg.getKnownRValue().getAggregateAddress();
+ forConstantArrayExpansion(
+ *this, CAExp, Addr, [&](Address EltAddr) {
+ CallArg EltArg = CallArg(
+ convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation()),
+ CAExp->EltTy);
+ ExpandTypeToArgs(CAExp->EltTy, EltArg, IRFuncTy, IRCallArgs,
+ IRCallArgPos);
+ });
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
- Address This = RV.getAggregateAddress();
+ Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress()
+ : Arg.getKnownRValue().getAggregateAddress();
for (const CXXBaseSpecifier *BS : RExp->Bases) {
// Perform a single step derived-to-base conversion.
Address Base =
GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
/*NullCheckValue=*/false, SourceLocation());
- RValue BaseRV = RValue::getAggregate(Base);
+ CallArg BaseArg = CallArg(RValue::getAggregate(Base), BS->getType());
// Recurse onto bases.
- ExpandTypeToArgs(BS->getType(), BaseRV, IRFuncTy, IRCallArgs,
+ ExpandTypeToArgs(BS->getType(), BaseArg, IRFuncTy, IRCallArgs,
IRCallArgPos);
}
LValue LV = MakeAddrLValue(This, Ty);
for (auto FD : RExp->Fields) {
- RValue FldRV = EmitRValueForField(LV, FD, SourceLocation());
- ExpandTypeToArgs(FD->getType(), FldRV, IRFuncTy, IRCallArgs,
+ CallArg FldArg =
+ CallArg(EmitRValueForField(LV, FD, SourceLocation()), FD->getType());
+ ExpandTypeToArgs(FD->getType(), FldArg, IRFuncTy, IRCallArgs,
IRCallArgPos);
}
} else if (isa<ComplexExpansion>(Exp.get())) {
- ComplexPairTy CV = RV.getComplexVal();
+ ComplexPairTy CV = Arg.getKnownRValue().getComplexVal();
IRCallArgs[IRCallArgPos++] = CV.first;
IRCallArgs[IRCallArgPos++] = CV.second;
} else {
assert(isa<NoExpansion>(Exp.get()));
+ auto RV = Arg.getKnownRValue();
assert(RV.isScalar() &&
"Unexpected non-scalar rvalue during struct expansion.");
@@ -1325,7 +1344,7 @@ static void CreateCoercedStore(llvm::Value *Src,
}
static Address emitAddressAtOffset(CodeGenFunction &CGF, Address addr,
- const ABIArgInfo &info) {
+ const ABIArgInfo &info) {
if (unsigned offset = info.getDirectOffset()) {
addr = CGF.Builder.CreateElementBitCast(addr, CGF.Int8Ty);
addr = CGF.Builder.CreateConstInBoundsByteGEP(addr,
@@ -1479,7 +1498,8 @@ void ClangToLLVMArgMapping::construct(const ASTContext &Context,
/***/
bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) {
- return FI.getReturnInfo().isIndirect();
+ const auto &RI = FI.getReturnInfo();
+ return RI.isIndirect() || (RI.isInAlloca() && RI.getInAllocaSRet());
}
bool CodeGenModule::ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI) {
@@ -1655,7 +1675,7 @@ llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
if (!isFuncTypeConvertible(FPT))
return llvm::StructType::get(getLLVMContext());
-
+
const CGFunctionInfo *Info;
if (isa<CXXDestructorDecl>(MD))
Info =
@@ -1672,7 +1692,7 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
return;
if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
- FPT->isNothrow(Ctx))
+ FPT->isNothrow())
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}
@@ -1714,12 +1734,19 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
FuncAttrs.addAttribute("less-precise-fpmad",
llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
+ if (CodeGenOpts.NullPointerIsValid)
+ FuncAttrs.addAttribute("null-pointer-is-valid", "true");
if (!CodeGenOpts.FPDenormalMode.empty())
FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode);
FuncAttrs.addAttribute("no-trapping-math",
llvm::toStringRef(CodeGenOpts.NoTrappingMath));
+ // Strict (compliant) code is the default, so only add this attribute to
+ // indicate that we are trying to workaround a problem case.
+ if (!CodeGenOpts.StrictFloatCastOverflow)
+ FuncAttrs.addAttribute("strict-float-cast-overflow", "false");
+
// TODO: Are these all needed?
// unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
FuncAttrs.addAttribute("no-infs-fp-math",
@@ -1738,6 +1765,10 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
"correctly-rounded-divide-sqrt-fp-math",
llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt));
+ if (getLangOpts().OpenCL)
+ FuncAttrs.addAttribute("denorms-are-zero",
+ llvm::toStringRef(CodeGenOpts.FlushDenorm));
+
// TODO: Reciprocal estimate codegen options should apply to instructions?
const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals;
if (!Recips.empty())
@@ -1769,7 +1800,7 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
// Respect -fcuda-flush-denormals-to-zero.
- if (getLangOpts().CUDADeviceFlushDenormalsToZero)
+ if (CodeGenOpts.FlushDenorm)
FuncAttrs.addAttribute("nvptx-f32ftz", "true");
}
}
@@ -1793,7 +1824,7 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
// If we have information about the function prototype, we can learn
- // attributes form there.
+ // attributes from there.
AddAttributesFromFunctionProtoType(getContext(), FuncAttrs,
CalleeInfo.getCalleeFunctionProtoType());
@@ -1838,18 +1869,20 @@ void CodeGenModule::ConstructAttributeList(
}
if (TargetDecl->hasAttr<RestrictAttr>())
RetAttrs.addAttribute(llvm::Attribute::NoAlias);
- if (TargetDecl->hasAttr<ReturnsNonNullAttr>())
+ if (TargetDecl->hasAttr<ReturnsNonNullAttr>() &&
+ !CodeGenOpts.NullPointerIsValid)
RetAttrs.addAttribute(llvm::Attribute::NonNull);
if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
FuncAttrs.addAttribute("no_caller_saved_registers");
+ if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck);
HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
Optional<unsigned> NumElemsParam;
- // alloc_size args are base-1, 0 means not present.
- if (unsigned N = AllocSize->getNumElemsParam())
- NumElemsParam = N - 1;
- FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam() - 1,
+ if (AllocSize->getNumElemsParam().isValid())
+ NumElemsParam = AllocSize->getNumElemsParam().getLLVMIndex();
+ FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam().getLLVMIndex(),
NumElemsParam);
}
}
@@ -1870,53 +1903,40 @@ void CodeGenModule::ConstructAttributeList(
}
}
- if (!AttrOnCallSite) {
- bool DisableTailCalls =
- CodeGenOpts.DisableTailCalls ||
- (TargetDecl && (TargetDecl->hasAttr<DisableTailCallsAttr>() ||
- TargetDecl->hasAttr<AnyX86InterruptAttr>()));
- FuncAttrs.addAttribute("disable-tail-calls",
- llvm::toStringRef(DisableTailCalls));
-
- // Add target-cpu and target-features attributes to functions. If
- // 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.
- for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(),
- ie = FeatureMap.end();
- it != ie; ++it)
- Features.push_back((it->second ? "+" : "-") + it->first().str());
-
- // Now add the target-cpu and target-features to the function.
- // While we populated the feature map above, we still need to
- // get and parse the target attribute so we can get the cpu for
- // the function.
- const auto *TD = FD->getAttr<TargetAttr>();
- TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
- if (ParsedAttr.Architecture != "" &&
- getTarget().isValidCPUName(ParsedAttr.Architecture))
- TargetCPU = ParsedAttr.Architecture;
+ if (TargetDecl && TargetDecl->hasAttr<OpenCLKernelAttr>()) {
+ if (getLangOpts().OpenCLVersion <= 120) {
+ // OpenCL v1.2 Work groups are always uniform
+ FuncAttrs.addAttribute("uniform-work-group-size", "true");
} else {
- // Otherwise just add the existing target cpu and target features to the
- // function.
- Features = getTarget().getTargetOpts().Features;
+ // OpenCL v2.0 Work groups may be whether uniform or not.
+ // '-cl-uniform-work-group-size' compile option gets a hint
+ // to the compiler that the global work-size be a multiple of
+ // the work-group size specified to clEnqueueNDRangeKernel
+ // (i.e. work groups are uniform).
+ FuncAttrs.addAttribute("uniform-work-group-size",
+ llvm::toStringRef(CodeGenOpts.UniformWGSize));
}
+ }
- if (TargetCPU != "")
- FuncAttrs.addAttribute("target-cpu", TargetCPU);
- if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
- FuncAttrs.addAttribute(
- "target-features",
- llvm::join(Features, ","));
+ if (!AttrOnCallSite) {
+ bool DisableTailCalls = false;
+
+ if (CodeGenOpts.DisableTailCalls)
+ DisableTailCalls = true;
+ else if (TargetDecl) {
+ if (TargetDecl->hasAttr<DisableTailCallsAttr>() ||
+ TargetDecl->hasAttr<AnyX86InterruptAttr>())
+ DisableTailCalls = true;
+ else if (CodeGenOpts.NoEscapingBlockTailCalls) {
+ if (const auto *BD = dyn_cast<BlockDecl>(TargetDecl))
+ if (!BD->doesNotEscape())
+ DisableTailCalls = true;
+ }
}
+
+ FuncAttrs.addAttribute("disable-tail-calls",
+ llvm::toStringRef(DisableTailCalls));
+ GetCPUAndFeaturesAttributes(TargetDecl, FuncAttrs);
}
ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI);
@@ -1925,9 +1945,9 @@ void CodeGenModule::ConstructAttributeList(
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
- if (RetTy->hasSignedIntegerRepresentation())
+ if (RetAI.isSignExt())
RetAttrs.addAttribute(llvm::Attribute::SExt);
- else if (RetTy->hasUnsignedIntegerRepresentation())
+ else
RetAttrs.addAttribute(llvm::Attribute::ZExt);
LLVM_FALLTHROUGH;
case ABIArgInfo::Direct:
@@ -1957,7 +1977,8 @@ void CodeGenModule::ConstructAttributeList(
if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
RetAttrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy)
.getQuantity());
- else if (getContext().getTargetAddressSpace(PTy) == 0)
+ else if (getContext().getTargetAddressSpace(PTy) == 0 &&
+ !CodeGenOpts.NullPointerIsValid)
RetAttrs.addAttribute(llvm::Attribute::NonNull);
}
@@ -1967,7 +1988,8 @@ void CodeGenModule::ConstructAttributeList(
// Attach attributes to sret.
if (IRFunctionArgs.hasSRetArg()) {
llvm::AttrBuilder SRETAttrs;
- SRETAttrs.addAttribute(llvm::Attribute::StructRet);
+ if (!RetAI.getSuppressSRet())
+ SRETAttrs.addAttribute(llvm::Attribute::StructRet);
hasUsedSRet = true;
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
@@ -2006,14 +2028,10 @@ void CodeGenModule::ConstructAttributeList(
// sense to do it here because parameters are so messed up.
switch (AI.getKind()) {
case ABIArgInfo::Extend:
- if (ParamType->isSignedIntegerOrEnumerationType())
+ if (AI.isSignExt())
Attrs.addAttribute(llvm::Attribute::SExt);
- else if (ParamType->isUnsignedIntegerOrEnumerationType()) {
- if (getTypes().getABIInfo().shouldSignExtUnsignedType(ParamType))
- Attrs.addAttribute(llvm::Attribute::SExt);
- else
- Attrs.addAttribute(llvm::Attribute::ZExt);
- }
+ else
+ Attrs.addAttribute(llvm::Attribute::ZExt);
LLVM_FALLTHROUGH;
case ABIArgInfo::Direct:
if (ArgNo == 0 && FI.isChainCall())
@@ -2070,7 +2088,8 @@ void CodeGenModule::ConstructAttributeList(
if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
Attrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy)
.getQuantity());
- else if (getContext().getTargetAddressSpace(PTy) == 0)
+ else if (getContext().getTargetAddressSpace(PTy) == 0 &&
+ !CodeGenOpts.NullPointerIsValid)
Attrs.addAttribute(llvm::Attribute::NonNull);
}
@@ -2255,11 +2274,16 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
i != e; ++i, ++info_it, ++ArgNo) {
const VarDecl *Arg = *i;
- QualType Ty = info_it->type;
const ABIArgInfo &ArgI = info_it->info;
bool isPromoted =
isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted();
+ // We are converting from ABIArgInfo type to VarDecl type directly, unless
+ // the parameter is promoted. In this case we convert to
+ // CGFunctionInfo::ArgInfo type with subsequent argument demotion.
+ QualType Ty = isPromoted ? info_it->type : Arg->getType();
+ assert(hasScalarEvaluationKind(Ty) ==
+ hasScalarEvaluationKind(Arg->getType()));
unsigned FirstIRArg, NumIRArgs;
std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
@@ -2325,7 +2349,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(),
- PVD->getFunctionScopeIndex()))
+ PVD->getFunctionScopeIndex()) &&
+ !CGM.getCodeGenOpts().NullPointerIsValid)
AI->addAttr(llvm::Attribute::NonNull);
QualType OTy = PVD->getOriginalType();
@@ -2344,7 +2369,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Attrs.addDereferenceableAttr(
getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize);
AI->addAttrs(Attrs);
- } else if (getContext().getTargetAddressSpace(ETy) == 0) {
+ } else if (getContext().getTargetAddressSpace(ETy) == 0 &&
+ !CGM.getCodeGenOpts().NullPointerIsValid) {
AI->addAttr(llvm::Attribute::NonNull);
}
}
@@ -2354,7 +2380,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// we can't use the dereferenceable attribute, but in addrspace(0)
// we know that it must be nonnull.
if (ArrTy->getSizeModifier() == VariableArrayType::Static &&
- !getContext().getTargetAddressSpace(ArrTy->getElementType()))
+ !getContext().getTargetAddressSpace(ArrTy->getElementType()) &&
+ !CGM.getCodeGenOpts().NullPointerIsValid)
AI->addAttr(llvm::Attribute::NonNull);
}
@@ -2656,7 +2683,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF,
llvm::Value *retainedValue = retainCall->getArgOperand(0);
llvm::LoadInst *load =
dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts());
- if (!load || load->isAtomic() || load->isVolatile() ||
+ if (!load || load->isAtomic() || load->isVolatile() ||
load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer())
return nullptr;
@@ -3022,7 +3049,8 @@ static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF,
Ty.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap);
}
void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
@@ -3062,6 +3090,19 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
} else {
args.add(convertTempToRValue(local, type, loc), type);
}
+
+ // Deactivate the cleanup for the callee-destructed param that was pushed.
+ if (hasAggregateEvaluationKind(type) && !CurFuncIsThunk &&
+ type->getAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
+ type.isDestructedType()) {
+ EHScopeStack::stable_iterator cleanup =
+ CalleeDestructedParamCleanups.lookup(cast<ParmVarDecl>(param));
+ assert(cleanup.isValid() &&
+ "cleanup for callee-destructed param not recorded");
+ // This unreachable is a temporary marker which will be removed later.
+ llvm::Instruction *isActive = Builder.CreateUnreachable();
+ args.addArgCleanupDeactivation(cleanup, isActive);
+ }
}
static bool isProvablyNull(llvm::Value *addr) {
@@ -3098,7 +3139,7 @@ static void emitWriteback(CodeGenFunction &CGF,
// Cast it back, in case we're writing an id to a Foo* or something.
value = CGF.Builder.CreateBitCast(value, srcAddr.getElementType(),
"icr.writeback-cast");
-
+
// Perform the writeback.
// If we have a "to use" value, it's something we need to emit a use
@@ -3143,7 +3184,6 @@ static void emitWritebacks(CodeGenFunction &CGF,
static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF,
const CallArgList &CallArgs) {
- assert(CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee());
ArrayRef<CallArgList::CallArgCleanup> Cleanups =
CallArgs.getCleanupsToDeactivate();
// Iterate in reverse to increase the likelihood of popping the cleanup.
@@ -3205,7 +3245,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// isn't null, so we need to register a dominating point so that the cleanups
// system will make valid IR.
CodeGenFunction::ConditionalEvaluation condEval(CGF);
-
+
// Zero-initialize it if we're not doing a copy-initialization.
bool shouldCopy = CRE->shouldCopy();
if (!shouldCopy) {
@@ -3229,7 +3269,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
llvm::Value *isNull =
CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull");
- finalArgument = CGF.Builder.CreateSelect(isNull,
+ finalArgument = CGF.Builder.CreateSelect(isNull,
llvm::ConstantPointerNull::get(destType),
temp.getPointer(), "icr.argument");
@@ -3269,7 +3309,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
valueToUse = src;
}
}
-
+
// Finish the control flow if we needed it.
if (shouldCopy && !provablyNonNull) {
llvm::BasicBlock *copyBB = CGF.Builder.GetInsertBlock();
@@ -3320,7 +3360,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr;
unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum;
- // Prefer the nonnull attribute if it's present.
+ // Prefer the nonnull attribute if it's present.
const NonNullAttr *NNAttr = nullptr;
if (SanOpts.has(SanitizerKind::NonnullAttribute))
NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo);
@@ -3430,13 +3470,17 @@ void CodeGenFunction::EmitCallArgs(
assert(InitialArgSize + 1 == Args.size() &&
"The code below depends on only adding one arg per EmitCallArg");
(void)InitialArgSize;
- RValue RVArg = Args.back().RV;
- EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC,
- ParamsToSkip + Idx);
- // @llvm.objectsize should never have side-effects and shouldn't need
- // destruction/cleanups, so we can safely "emit" it after its arg,
- // regardless of right-to-leftness
- MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg);
+ // Since pointer argument are never emitted as LValue, it is safe to emit
+ // non-null argument check for r-value only.
+ if (!Args.back().hasLValue()) {
+ RValue RVArg = Args.back().getKnownRValue();
+ EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC,
+ ParamsToSkip + Idx);
+ // @llvm.objectsize should never have side-effects and shouldn't need
+ // destruction/cleanups, so we can safely "emit" it after its arg,
+ // regardless of right-to-leftness
+ MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg);
+ }
}
if (!LeftToRight) {
@@ -3456,10 +3500,15 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup {
QualType Ty;
void Emit(CodeGenFunction &CGF, Flags flags) override {
- const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
- assert(!Dtor->isTrivial());
- CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false,
- /*Delegating=*/false, Addr);
+ QualType::DestructionKind DtorKind = Ty.isDestructedType();
+ if (DtorKind == QualType::DK_cxx_destructor) {
+ const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
+ assert(!Dtor->isTrivial());
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false,
+ /*Delegating=*/false, Addr);
+ } else {
+ CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty));
+ }
}
};
@@ -3478,6 +3527,33 @@ struct DisableDebugLocationUpdates {
} // end anonymous namespace
+RValue CallArg::getRValue(CodeGenFunction &CGF) const {
+ if (!HasLV)
+ return RV;
+ LValue Copy = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty), Ty);
+ CGF.EmitAggregateCopy(Copy, LV, Ty, AggValueSlot::DoesNotOverlap,
+ LV.isVolatile());
+ IsUsed = true;
+ return RValue::getAggregate(Copy.getAddress());
+}
+
+void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const {
+ LValue Dst = CGF.MakeAddrLValue(Addr, Ty);
+ if (!HasLV && RV.isScalar())
+ CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*init=*/true);
+ else if (!HasLV && RV.isComplex())
+ CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true);
+ else {
+ auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress();
+ LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty);
+ // We assume that call args are never copied into subobjects.
+ CGF.EmitAggregateCopy(Dst, SrcLV, Ty, AggValueSlot::DoesNotOverlap,
+ HasLV ? LV.isVolatileQualified()
+ : RV.isVolatileQualified());
+ }
+ IsUsed = true;
+}
+
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
QualType type) {
DisableDebugLocationUpdates Dis(*this, E);
@@ -3501,7 +3577,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
if (HasAggregateEvalKind &&
- CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+ type->getAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
// If we're using inalloca, use the argument memory. Otherwise, use a
// temporary.
AggValueSlot Slot;
@@ -3510,10 +3586,12 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
else
Slot = CreateAggTemp(type, "agg.tmp");
- const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
- bool DestroyedInCallee =
- RD && RD->hasNonTrivialDestructor() &&
- CGM.getCXXABI().getRecordArgABI(RD) != CGCXXABI::RAA_Default;
+ bool DestroyedInCallee = true, NeedsEHCleanup = true;
+ if (const auto *RD = type->getAsCXXRecordDecl())
+ DestroyedInCallee = RD->hasNonTrivialDestructor();
+ else
+ NeedsEHCleanup = needsEHCleanup(type.isDestructedType());
+
if (DestroyedInCallee)
Slot.setExternallyDestructed();
@@ -3521,7 +3599,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
RValue RV = Slot.asRValue();
args.add(RV, type);
- if (DestroyedInCallee) {
+ if (DestroyedInCallee && NeedsEHCleanup) {
// Create a no-op GEP between the placeholder and the cleanup so we can
// RAUW it successfully. It also serves as a marker of the first
// instruction where the cleanup is active.
@@ -3538,15 +3616,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue) {
LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
assert(L.isSimple());
- if (L.getAlignment() >= getContext().getTypeAlignInChars(type)) {
- args.add(L.asAggregateRValue(), type, /*NeedsCopy*/true);
- } else {
- // We can't represent a misaligned lvalue in the CallArgList, so copy
- // to an aligned temporary now.
- Address tmp = CreateMemTemp(type);
- EmitAggregateCopy(tmp, L.getAddress(), type, L.isVolatile());
- args.add(RValue::getAggregate(tmp), type);
- }
+ args.addUncopiedAggregate(L, type);
return;
}
@@ -3608,20 +3678,21 @@ CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
// Calls which may throw must have operand bundles indicating which funclet
// they are nested within.
-static void
-getBundlesForFunclet(llvm::Value *Callee, llvm::Instruction *CurrentFuncletPad,
- SmallVectorImpl<llvm::OperandBundleDef> &BundleList) {
+SmallVector<llvm::OperandBundleDef, 1>
+CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) {
+ SmallVector<llvm::OperandBundleDef, 1> BundleList;
// There is no need for a funclet operand bundle if we aren't inside a
// funclet.
if (!CurrentFuncletPad)
- return;
+ return BundleList;
// Skip intrinsics which cannot throw.
auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts());
if (CalleeFn && CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow())
- return;
+ return BundleList;
BundleList.emplace_back("funclet", CurrentFuncletPad);
+ return BundleList;
}
/// Emits a simple call (never an invoke) to the given runtime function.
@@ -3629,10 +3700,8 @@ llvm::CallInst *
CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
ArrayRef<llvm::Value*> args,
const llvm::Twine &name) {
- SmallVector<llvm::OperandBundleDef, 1> BundleList;
- getBundlesForFunclet(callee, CurrentFuncletPad, BundleList);
-
- llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList, name);
+ llvm::CallInst *call =
+ Builder.CreateCall(callee, args, getBundlesForFunclet(callee), name);
call->setCallingConv(getRuntimeCC());
return call;
}
@@ -3640,11 +3709,11 @@ CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
/// Emits a call or invoke to the given noreturn runtime function.
void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args) {
- SmallVector<llvm::OperandBundleDef, 1> BundleList;
- getBundlesForFunclet(callee, CurrentFuncletPad, BundleList);
+ SmallVector<llvm::OperandBundleDef, 1> BundleList =
+ getBundlesForFunclet(callee);
if (getInvokeDest()) {
- llvm::InvokeInst *invoke =
+ llvm::InvokeInst *invoke =
Builder.CreateInvoke(callee,
getUnreachableBlock(),
getInvokeDest(),
@@ -3684,8 +3753,8 @@ CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
ArrayRef<llvm::Value *> Args,
const Twine &Name) {
llvm::BasicBlock *InvokeDest = getInvokeDest();
- SmallVector<llvm::OperandBundleDef, 1> BundleList;
- getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList);
+ SmallVector<llvm::OperandBundleDef, 1> BundleList =
+ getBundlesForFunclet(Callee);
llvm::Instruction *Inst;
if (!InvokeDest)
@@ -3705,16 +3774,6 @@ CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
return llvm::CallSite(Inst);
}
-/// \brief Store a non-aggregate value to an address to initialize it. For
-/// initialization, a non-atomic store will be used.
-static void EmitInitStoreOfNonAggregate(CodeGenFunction &CGF, RValue Src,
- LValue Dst) {
- if (Src.isScalar())
- CGF.EmitStoreOfScalar(Src.getScalarVal(), Dst, /*init=*/true);
- else
- CGF.EmitStoreOfComplex(Src.getComplexVal(), Dst, /*init=*/true);
-}
-
void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
llvm::Value *New) {
DeferredReplacements.push_back(std::make_pair(Old, New));
@@ -3728,7 +3787,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SourceLocation Loc) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
- assert(Callee.isOrdinary());
+ assert(Callee.isOrdinary() || Callee.isVirtual());
// Handle struct-return functions by passing a pointer to the
// location that we would like to return into.
@@ -3775,17 +3834,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- size_t UnusedReturnSize = 0;
+ Address SRetAlloca = Address::invalid();
+ llvm::Value *UnusedReturnSizePtr = nullptr;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
if (!ReturnValue.isNull()) {
SRetPtr = ReturnValue.getValue();
} else {
- SRetPtr = CreateMemTemp(RetTy);
+ SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca);
if (HaveInsertPoint() && ReturnValue.isUnused()) {
uint64_t size =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- if (EmitLifetimeStart(size, SRetPtr.getPointer()))
- UnusedReturnSize = size;
+ UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer());
}
}
if (IRFunctionArgs.hasSRetArg()) {
@@ -3807,7 +3866,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
I != E; ++I, ++info_it, ++ArgNo) {
const ABIArgInfo &ArgInfo = info_it->info;
- RValue RV = I->RV;
// Insert a padding argument to ensure proper alignment.
if (IRFunctionArgs.hasPaddingArg(ArgNo))
@@ -3821,13 +3879,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca: {
assert(NumIRArgs == 0);
assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
- if (RV.isAggregate()) {
+ if (I->isAggregate()) {
// Replace the placeholder with the appropriate argument slot GEP.
+ Address Addr = I->hasLValue()
+ ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
llvm::Instruction *Placeholder =
- cast<llvm::Instruction>(RV.getAggregatePointer());
+ cast<llvm::Instruction>(Addr.getPointer());
CGBuilderTy::InsertPoint IP = Builder.saveIP();
Builder.SetInsertPoint(Placeholder);
- Address Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex());
+ Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex());
Builder.restoreIP(IP);
deferPlaceholderReplacement(Placeholder, Addr.getPointer());
} else {
@@ -3840,22 +3901,20 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// from {}* to (%struct.foo*)*.
if (Addr.getType() != MemType)
Addr = Builder.CreateBitCast(Addr, MemType);
- LValue argLV = MakeAddrLValue(Addr, I->Ty);
- EmitInitStoreOfNonAggregate(*this, RV, argLV);
+ I->copyInto(*this, Addr);
}
break;
}
case ABIArgInfo::Indirect: {
assert(NumIRArgs == 1);
- if (RV.isScalar() || RV.isComplex()) {
+ if (!I->isAggregate()) {
// Make a temporary alloca to pass the argument.
- Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
- "indirect-arg-temp", false);
+ Address Addr = CreateMemTempWithoutCast(
+ I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp");
IRCallArgs[FirstIRArg] = Addr.getPointer();
- LValue argLV = MakeAddrLValue(Addr, I->Ty);
- EmitInitStoreOfNonAggregate(*this, RV, argLV);
+ I->copyInto(*this, Addr);
} else {
// We want to avoid creating an unnecessary temporary+copy here;
// however, we need one in three cases:
@@ -3863,30 +3922,51 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// source. (This case doesn't occur on any common architecture.)
// 2. If the argument is byval, RV is not sufficiently aligned, and
// we cannot force it to be sufficiently aligned.
- // 3. If the argument is byval, but RV is located in an address space
- // different than that of the argument (0).
- Address Addr = RV.getAggregateAddress();
+ // 3. If the argument is byval, but RV is not located in default
+ // or alloca address space.
+ Address Addr = I->hasLValue()
+ ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
+ llvm::Value *V = Addr.getPointer();
CharUnits Align = ArgInfo.getIndirectAlign();
const llvm::DataLayout *TD = &CGM.getDataLayout();
- const unsigned RVAddrSpace = Addr.getType()->getAddressSpace();
- const unsigned ArgAddrSpace =
- (FirstIRArg < IRFuncTy->getNumParams()
- ? IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace()
- : 0);
- if ((!ArgInfo.getIndirectByVal() && I->NeedsCopy) ||
- (ArgInfo.getIndirectByVal() && Addr.getAlignment() < Align &&
- llvm::getOrEnforceKnownAlignment(Addr.getPointer(),
- Align.getQuantity(), *TD)
- < Align.getQuantity()) ||
- (ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
+
+ assert((FirstIRArg >= IRFuncTy->getNumParams() ||
+ IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace() ==
+ TD->getAllocaAddrSpace()) &&
+ "indirect argument must be in alloca address space");
+
+ bool NeedCopy = false;
+
+ if (Addr.getAlignment() < Align &&
+ llvm::getOrEnforceKnownAlignment(V, Align.getQuantity(), *TD) <
+ Align.getQuantity()) {
+ NeedCopy = true;
+ } else if (I->hasLValue()) {
+ auto LV = I->getKnownLValue();
+ auto AS = LV.getAddressSpace();
+ if ((!ArgInfo.getIndirectByVal() &&
+ (LV.getAlignment() >=
+ getContext().getTypeAlignInChars(I->Ty))) ||
+ (ArgInfo.getIndirectByVal() &&
+ ((AS != LangAS::Default && AS != LangAS::opencl_private &&
+ AS != CGM.getASTAllocaAddressSpace())))) {
+ NeedCopy = true;
+ }
+ }
+ if (NeedCopy) {
// Create an aligned temporary, and copy to it.
- Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
- "byval-temp", false);
+ Address AI = CreateMemTempWithoutCast(
+ I->Ty, ArgInfo.getIndirectAlign(), "byval-temp");
IRCallArgs[FirstIRArg] = AI.getPointer();
- EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified());
+ I->copyInto(*this, AI);
} else {
// Skip the extra memcpy call.
- IRCallArgs[FirstIRArg] = Addr.getPointer();
+ auto *T = V->getType()->getPointerElementType()->getPointerTo(
+ CGM.getDataLayout().getAllocaAddrSpace());
+ IRCallArgs[FirstIRArg] = getTargetHooks().performAddrSpaceCast(
+ *this, V, LangAS::Default, CGM.getASTAllocaAddressSpace(), T,
+ true);
}
}
break;
@@ -3903,10 +3983,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
ArgInfo.getDirectOffset() == 0) {
assert(NumIRArgs == 1);
llvm::Value *V;
- if (RV.isScalar())
- V = RV.getScalarVal();
+ if (!I->isAggregate())
+ V = I->getKnownRValue().getScalarVal();
else
- V = Builder.CreateLoad(RV.getAggregateAddress());
+ V = Builder.CreateLoad(
+ I->hasLValue() ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress());
// Implement swifterror by copying into a new swifterror argument.
// We'll write back in the normal path out of the call.
@@ -3944,12 +4026,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// FIXME: Avoid the conversion through memory if possible.
Address Src = Address::invalid();
- if (RV.isScalar() || RV.isComplex()) {
+ if (!I->isAggregate()) {
Src = CreateMemTemp(I->Ty, "coerce");
- LValue SrcLV = MakeAddrLValue(Src, I->Ty);
- EmitInitStoreOfNonAggregate(*this, RV, SrcLV);
+ I->copyInto(*this, Src);
} else {
- Src = RV.getAggregateAddress();
+ Src = I->hasLValue() ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
}
// If the value is offset in memory, apply the offset now.
@@ -4003,22 +4085,26 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
- if (RV.isAggregate()) {
- addr = RV.getAggregateAddress();
+ Address AllocaAddr = Address::invalid();
+ if (I->isAggregate()) {
+ addr = I->hasLValue() ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
+
} else {
+ RValue RV = I->getKnownRValue();
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlignment(scalarType);
- tempSize = llvm::ConstantInt::get(CGM.Int64Ty, scalarSize);
-
// Materialize to a temporary.
addr = CreateTempAlloca(RV.getScalarVal()->getType(),
- CharUnits::fromQuantity(std::max(layout->getAlignment(),
- scalarAlign)));
- EmitLifetimeStart(scalarSize, addr.getPointer());
+ CharUnits::fromQuantity(std::max(
+ layout->getAlignment(), scalarAlign)),
+ "tmp",
+ /*ArraySize=*/nullptr, &AllocaAddr);
+ tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -4036,7 +4122,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(IRArgPos == FirstIRArg + NumIRArgs);
if (tempSize) {
- EmitLifetimeEnd(tempSize, addr.getPointer());
+ EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
}
break;
@@ -4044,13 +4130,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::Expand:
unsigned IRArgPos = FirstIRArg;
- ExpandTypeToArgs(I->Ty, RV, IRFuncTy, IRCallArgs, IRArgPos);
+ ExpandTypeToArgs(I->Ty, *I, IRFuncTy, IRCallArgs, IRArgPos);
assert(IRArgPos == FirstIRArg + NumIRArgs);
break;
}
}
- llvm::Value *CalleePtr = Callee.getFunctionPointer();
+ const CGCallee &ConcreteCallee = Callee.prepareConcreteCallee(*this);
+ llvm::Value *CalleePtr = ConcreteCallee.getFunctionPointer();
// If we're using inalloca, set up that argument.
if (ArgMemory.isValid()) {
@@ -4191,10 +4278,19 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
CannotThrow = Attrs.hasAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoUnwind);
}
+
+ // If we made a temporary, be sure to clean up after ourselves. Note that we
+ // can't depend on being inside of an ExprWithCleanups, so we need to manually
+ // pop this cleanup later on. Being eager about this is OK, since this
+ // temporary is 'invisible' outside of the callee.
+ if (UnusedReturnSizePtr)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca,
+ UnusedReturnSizePtr);
+
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
- SmallVector<llvm::OperandBundleDef, 1> BundleList;
- getBundlesForFunclet(CalleePtr, CurrentFuncletPad, BundleList);
+ SmallVector<llvm::OperandBundleDef, 1> BundleList =
+ getBundlesForFunclet(CalleePtr);
// Emit the actual call/invoke instruction.
llvm::CallSite CS;
@@ -4244,9 +4340,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CS.doesNotReturn()) {
- if (UnusedReturnSize)
- EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
- SRetPtr.getPointer());
+ if (UnusedReturnSizePtr)
+ PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
if (SanOpts.has(SanitizerKind::Unreachable)) {
@@ -4315,9 +4410,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSize)
- EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
- SRetPtr.getPointer());
+ if (UnusedReturnSizePtr)
+ PopCleanupBlock();
return ret;
}
@@ -4395,7 +4489,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
OffsetValue);
} else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) {
llvm::Value *ParamVal =
- CallArgs[AA->getParamIndex() - 1].RV.getScalarVal();
+ CallArgs[AA->getParamIndex().getLLVMIndex()].getRValue(
+ *this).getScalarVal();
EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal);
}
}
@@ -4403,6 +4498,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
return Ret;
}
+CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const {
+ if (isVirtual()) {
+ const CallExpr *CE = getVirtualCallExpr();
+ return CGF.CGM.getCXXABI().getVirtualFunctionPointer(
+ CGF, getVirtualMethodDecl(), getThisAddress(),
+ getFunctionType(), CE ? CE->getLocStart() : SourceLocation());
+ }
+
+ return *this;
+}
+
/* VarArg handling */
Address CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
index 7e10407fc31c..99a36e4e12f1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
@@ -18,6 +18,7 @@
#include "CGValue.h"
#include "EHScopeStack.h"
#include "clang/AST/CanonicalType.h"
+#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
@@ -42,9 +43,9 @@ namespace CodeGen {
/// Abstract information about a function or function prototype.
class CGCalleeInfo {
- /// \brief The function prototype of the callee.
+ /// The function prototype of the callee.
const FunctionProtoType *CalleeProtoTy;
- /// \brief The function declaration of the callee.
+ /// The function declaration of the callee.
const Decl *CalleeDecl;
public:
@@ -68,8 +69,9 @@ public:
Invalid,
Builtin,
PseudoDestructor,
+ Virtual,
- Last = PseudoDestructor
+ Last = Virtual
};
struct BuiltinInfoStorage {
@@ -79,12 +81,19 @@ public:
struct PseudoDestructorInfoStorage {
const CXXPseudoDestructorExpr *Expr;
};
+ struct VirtualInfoStorage {
+ const CallExpr *CE;
+ GlobalDecl MD;
+ Address Addr;
+ llvm::FunctionType *FTy;
+ };
SpecialKind KindOrFunctionPointer;
union {
CGCalleeInfo AbstractInfo;
BuiltinInfoStorage BuiltinInfo;
PseudoDestructorInfoStorage PseudoDestructorInfo;
+ VirtualInfoStorage VirtualInfo;
};
explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
@@ -127,6 +136,16 @@ public:
return CGCallee(abstractInfo, functionPtr);
}
+ static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
+ llvm::FunctionType *FTy) {
+ CGCallee result(SpecialKind::Virtual);
+ result.VirtualInfo.CE = CE;
+ result.VirtualInfo.MD = MD;
+ result.VirtualInfo.Addr = Addr;
+ result.VirtualInfo.FTy = FTy;
+ return result;
+ }
+
bool isBuiltin() const {
return KindOrFunctionPointer == SpecialKind::Builtin;
}
@@ -150,7 +169,9 @@ public:
bool isOrdinary() const {
return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
}
- const CGCalleeInfo &getAbstractInfo() const {
+ CGCalleeInfo getAbstractInfo() const {
+ if (isVirtual())
+ return VirtualInfo.MD.getDecl();
assert(isOrdinary());
return AbstractInfo;
}
@@ -158,29 +179,86 @@ public:
assert(isOrdinary());
return reinterpret_cast<llvm::Value*>(uintptr_t(KindOrFunctionPointer));
}
- llvm::FunctionType *getFunctionType() const {
- return cast<llvm::FunctionType>(
- getFunctionPointer()->getType()->getPointerElementType());
- }
void setFunctionPointer(llvm::Value *functionPtr) {
assert(isOrdinary());
KindOrFunctionPointer = SpecialKind(uintptr_t(functionPtr));
}
+
+ bool isVirtual() const {
+ return KindOrFunctionPointer == SpecialKind::Virtual;
+ }
+ const CallExpr *getVirtualCallExpr() const {
+ assert(isVirtual());
+ return VirtualInfo.CE;
+ }
+ GlobalDecl getVirtualMethodDecl() const {
+ assert(isVirtual());
+ return VirtualInfo.MD;
+ }
+ Address getThisAddress() const {
+ assert(isVirtual());
+ return VirtualInfo.Addr;
+ }
+
+ llvm::FunctionType *getFunctionType() const {
+ if (isVirtual())
+ return VirtualInfo.FTy;
+ return cast<llvm::FunctionType>(
+ getFunctionPointer()->getType()->getPointerElementType());
+ }
+
+ /// If this is a delayed callee computation of some sort, prepare
+ /// a concrete callee.
+ CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;
};
struct CallArg {
- RValue RV;
+ private:
+ union {
+ RValue RV;
+ LValue LV; /// The argument is semantically a load from this l-value.
+ };
+ bool HasLV;
+
+ /// A data-flow flag to make sure getRValue and/or copyInto are not
+ /// called twice for duplicated IR emission.
+ mutable bool IsUsed;
+
+ public:
QualType Ty;
- bool NeedsCopy;
- CallArg(RValue rv, QualType ty, bool needscopy)
- : RV(rv), Ty(ty), NeedsCopy(needscopy)
- { }
+ CallArg(RValue rv, QualType ty)
+ : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
+ CallArg(LValue lv, QualType ty)
+ : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
+ bool hasLValue() const { return HasLV; }
+ QualType getType() const { return Ty; }
+
+ /// \returns an independent RValue. If the CallArg contains an LValue,
+ /// a temporary copy is returned.
+ RValue getRValue(CodeGenFunction &CGF) const;
+
+ LValue getKnownLValue() const {
+ assert(HasLV && !IsUsed);
+ return LV;
+ }
+ RValue getKnownRValue() const {
+ assert(!HasLV && !IsUsed);
+ return RV;
+ }
+ void setRValue(RValue _RV) {
+ assert(!HasLV);
+ RV = _RV;
+ }
+
+ bool isAggregate() const { return HasLV || RV.isAggregate(); }
+
+ void copyInto(CodeGenFunction &CGF, Address A) const;
};
/// CallArgList - Type for representing both the value and type of
/// arguments in a call.
class CallArgList :
- public SmallVector<CallArg, 16> {
+ public SmallVector<CallArg, 8> {
public:
CallArgList() : StackBase(nullptr) {}
@@ -204,8 +282,10 @@ public:
llvm::Instruction *IsActiveIP;
};
- void add(RValue rvalue, QualType type, bool needscopy = false) {
- push_back(CallArg(rvalue, type, needscopy));
+ void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }
+
+ void addUncopiedAggregate(LValue LV, QualType type) {
+ push_back(CallArg(LV, type));
}
/// Add all the arguments from another CallArgList to this one. After doing
@@ -254,7 +334,7 @@ public:
llvm::Instruction *getStackBase() const { return StackBase; }
void freeArgumentMemory(CodeGenFunction &CGF) const;
- /// \brief Returns if we're using an inalloca struct to pass arguments in
+ /// Returns if we're using an inalloca struct to pass arguments in
/// memory.
bool isUsingInAlloca() const { return StackBase; }
@@ -276,7 +356,7 @@ public:
class FunctionArgList : public SmallVector<const VarDecl*, 16> {
};
- /// ReturnValueSlot - Contains the address where the return value of a
+ /// ReturnValueSlot - Contains the address where the return value of a
/// function can be stored, and whether the address is volatile or not.
class ReturnValueSlot {
llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value;
@@ -301,7 +381,7 @@ public:
Address getValue() const { return Address(Value.getPointer(), Alignment); }
bool isUnused() const { return Value.getInt() & IS_UNUSED; }
};
-
+
} // end namespace CodeGen
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
index a6915071ec17..ec4eb000a3b9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -406,8 +406,8 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
// Apply the offset.
llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy);
- Value = Builder.CreateGEP(Value, Builder.CreateNeg(NonVirtualOffset),
- "sub.ptr");
+ Value = Builder.CreateInBoundsGEP(Value, Builder.CreateNeg(NonVirtualOffset),
+ "sub.ptr");
// Just cast.
Value = Builder.CreateBitCast(Value, DerivedPtrTy);
@@ -555,10 +555,12 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
BaseClassDecl,
isBaseVirtual);
AggValueSlot AggSlot =
- AggValueSlot::forAddr(V, Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::forAddr(
+ V, Qualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased,
+ CGF.overlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual));
CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
@@ -615,7 +617,14 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
llvm::Value *ThisPtr = CGF.LoadCXXThis();
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
- LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
+ LValue LHS;
+
+ // If a base constructor is being emitted, create an LValue that has the
+ // non-virtual alignment.
+ if (CGF.CurGD.getCtorType() == Ctor_Base)
+ LHS = CGF.MakeNaturalAlignPointeeAddrLValue(ThisPtr, RecordTy);
+ else
+ LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS);
@@ -640,13 +649,13 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
// Copy the aggregate.
- CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
+ CGF.EmitAggregateCopy(LHS, Src, FieldType, CGF.overlapForFieldInit(Field),
LHS.isVolatileQualified());
// Ensure that we destroy the objects if an exception is thrown later in
// the constructor.
QualType::DestructionKind dtorKind = FieldType.isDestructedType();
if (CGF.needsEHCleanup(dtorKind))
- CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
+ CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
return;
}
}
@@ -671,10 +680,15 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
break;
case TEK_Aggregate: {
AggValueSlot Slot =
- AggValueSlot::forLValue(LHS,
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::forLValue(
+ LHS,
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased,
+ overlapForFieldInit(Field),
+ AggValueSlot::IsNotZeroed,
+ // Checks are made by the code that calls constructor.
+ AggValueSlot::IsSanitizerChecked);
EmitAggExpr(Init, Slot);
break;
}
@@ -876,7 +890,7 @@ namespace {
SanitizerSet OldSanOpts;
};
} // end anonymous namespace
-
+
namespace {
class FieldMemcpyizer {
public:
@@ -905,15 +919,15 @@ namespace {
}
CharUnits getMemcpySize(uint64_t FirstByteOffset) const {
+ ASTContext &Ctx = CGF.getContext();
unsigned LastFieldSize =
- LastField->isBitField() ?
- LastField->getBitWidthValue(CGF.getContext()) :
- CGF.getContext().getTypeSize(LastField->getType());
- uint64_t MemcpySizeBits =
- LastFieldOffset + LastFieldSize - FirstByteOffset +
- CGF.getContext().getCharWidth() - 1;
- CharUnits MemcpySize =
- CGF.getContext().toCharUnitsFromBits(MemcpySizeBits);
+ LastField->isBitField()
+ ? LastField->getBitWidthValue(Ctx)
+ : Ctx.toBits(
+ Ctx.getTypeInfoDataSizeInChars(LastField->getType()).first);
+ uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
+ FirstByteOffset + Ctx.getCharWidth() - 1;
+ CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits);
return MemcpySize;
}
@@ -1265,7 +1279,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isInitializerOfDynamicClass(*B))
- CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
}
@@ -1282,7 +1296,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isInitializerOfDynamicClass(*B))
- CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
}
@@ -1466,11 +1480,11 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Initialize the vtable pointers before entering the body.
if (!CanSkipVTablePointerInitialization(*this, Dtor)) {
- // Insert the llvm.invariant.group.barrier intrinsic before initializing
+ // Insert the llvm.launder.invariant.group intrinsic before initializing
// the vptrs to cancel any previous assumptions we might have made.
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0)
- CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
InitializeVTablePointers(Dtor->getParent());
}
@@ -1728,7 +1742,7 @@ namespace {
};
} // end anonymous namespace
-/// \brief Emit all code that comes at the end of class's
+/// 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.
///
@@ -1858,12 +1872,14 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
/// zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(
const CXXConstructorDecl *ctor, const ArrayType *arrayType,
- Address arrayBegin, const CXXConstructExpr *E, bool zeroInitialize) {
+ Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked,
+ bool zeroInitialize) {
QualType elementType;
llvm::Value *numElements =
emitArrayLength(arrayType, elementType, arrayBegin);
- EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E, zeroInitialize);
+ EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E,
+ NewPointerIsChecked, zeroInitialize);
}
/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
@@ -1879,6 +1895,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
llvm::Value *numElements,
Address arrayBase,
const CXXConstructExpr *E,
+ bool NewPointerIsChecked,
bool zeroInitialize) {
// It's legal for numElements to be zero. This can happen both
// dynamically, because x can be zero in 'new A[x]', and statically,
@@ -1920,7 +1937,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
// The alignment of the base, adjusted by the size of a single element,
// provides a conservative estimate of the alignment of every element.
// (This assumes we never start tracking offsetted alignments.)
- //
+ //
// Note that these are complete objects and so we don't need to
// use the non-virtual size or alignment.
QualType type = getContext().getTypeDeclType(ctor->getParent());
@@ -1954,7 +1971,8 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
}
EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, curAddr, E);
+ /*Delegating=*/false, curAddr, E,
+ AggValueSlot::DoesNotOverlap, NewPointerIsChecked);
}
// Go to the next element.
@@ -1989,7 +2007,9 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CXXCtorType Type,
bool ForVirtualBase,
bool Delegating, Address This,
- const CXXConstructExpr *E) {
+ const CXXConstructExpr *E,
+ AggValueSlot::Overlap_t Overlap,
+ bool NewPointerIsChecked) {
CallArgList Args;
// Push the this ptr.
@@ -2002,10 +2022,10 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
const Expr *Arg = E->getArg(0);
- QualType SrcTy = Arg->getType();
- Address Src = EmitLValue(Arg).getAddress();
+ LValue Src = EmitLValue(Arg);
QualType DestTy = getContext().getTypeDeclType(D->getParent());
- EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
+ LValue Dest = MakeAddrLValue(This, DestTy);
+ EmitAggregateCopyCtor(Dest, Src, Overlap);
return;
}
@@ -2017,7 +2037,8 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(),
/*ParamsToSkip*/ 0, Order);
- EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args);
+ EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args,
+ Overlap, E->getExprLoc(), NewPointerIsChecked);
}
static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
@@ -2049,15 +2070,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
bool ForVirtualBase,
bool Delegating,
Address This,
- CallArgList &Args) {
+ CallArgList &Args,
+ AggValueSlot::Overlap_t Overlap,
+ SourceLocation Loc,
+ bool NewPointerIsChecked) {
const CXXRecordDecl *ClassDecl = D->getParent();
- // C++11 [class.mfct.non-static]p2:
- // If a non-static member function of a class X is called for an object that
- // is not of type X, or of a type derived from X, the behavior is undefined.
- // FIXME: Provide a source location here.
- EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(),
- This.getPointer(), getContext().getRecordType(ClassDecl));
+ if (!NewPointerIsChecked)
+ EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(),
+ getContext().getRecordType(ClassDecl), CharUnits::Zero());
if (D->isTrivial() && D->isDefaultConstructor()) {
assert(Args.size() == 1 && "trivial default ctor with args");
@@ -2071,9 +2092,12 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
assert(Args.size() == 2 && "unexpected argcount for trivial ctor");
QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();
- Address Src(Args[1].RV.getScalarVal(), getNaturalTypeAlignment(SrcTy));
+ Address Src(Args[1].getRValue(*this).getScalarVal(),
+ getNaturalTypeAlignment(SrcTy));
+ LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
QualType DestTy = getContext().getTypeDeclType(ClassDecl);
- EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
+ LValue DestLVal = MakeAddrLValue(This, DestTy);
+ EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap);
return;
}
@@ -2123,8 +2147,7 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
CallArgList Args;
- CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext()),
- /*NeedsCopy=*/false);
+ CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext()));
// Forward the parameters.
if (InheritedFromVBase &&
@@ -2163,7 +2186,8 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
}
EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false,
- This, Args);
+ This, Args, AggValueSlot::MayOverlap,
+ E->getLocation(), /*NewPointerIsChecked*/true);
}
void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
@@ -2188,7 +2212,7 @@ void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
assert(Args.size() >= Params.size() && "too few arguments for call");
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) {
- const RValue &RV = Args[I].RV;
+ const RValue &RV = Args[I].getRValue(*this);
assert(!RV.isComplex() && "complex indirect params not supported");
ParamValue Val = RV.isScalar()
? ParamValue::forDirect(RV.getScalarVal())
@@ -2259,7 +2283,10 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
/*ParamsToSkip*/ 1);
- EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args);
+ EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/false,
+ /*Delegating*/false, This, Args,
+ AggValueSlot::MayOverlap, E->getExprLoc(),
+ /*NewPointerIsChecked*/false);
}
void
@@ -2294,7 +2321,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
}
EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
- /*Delegating=*/true, This, DelegateArgs);
+ /*Delegating=*/true, This, DelegateArgs,
+ AggValueSlot::MayOverlap, Loc,
+ /*NewPointerIsChecked=*/true);
}
namespace {
@@ -2325,7 +2354,11 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
AggValueSlot::forAddr(ThisPtr, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::MayOverlap,
+ AggValueSlot::IsNotZeroed,
+ // Checks are made by the code that calls constructor.
+ AggValueSlot::IsSanitizerChecked);
EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
@@ -2667,7 +2700,9 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
SSK = llvm::SanStat_CFI_UnrelatedCast;
break;
case CFITCK_ICall:
- llvm_unreachable("not expecting CFITCK_ICall");
+ case CFITCK_NVMFCall:
+ case CFITCK_VMFCall:
+ llvm_unreachable("unexpected sanitizer kind");
}
std::string TypeName = RD->getQualifiedNameAsString();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
index 22055b2cb902..0a766d176200 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -281,10 +281,10 @@ void EHScopeStack::popNullFixups() {
BranchFixups.pop_back();
}
-void CodeGenFunction::initFullExprCleanup() {
+Address CodeGenFunction::createCleanupActiveFlag() {
// Create a variable to decide whether the cleanup needs to be run.
- Address active = CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(),
- "cleanup.cond");
+ Address active = CreateTempAllocaWithoutCast(
+ Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond");
// Initialize it to false at a site that's guaranteed to be run
// before each evaluation.
@@ -293,10 +293,14 @@ void CodeGenFunction::initFullExprCleanup() {
// Initialize it to true at the current location.
Builder.CreateStore(Builder.getTrue(), active);
+ return active;
+}
+
+void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) {
// Set that as the active flag in the cleanup.
EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?");
- cleanup.setActiveFlag(active);
+ cleanup.setActiveFlag(ActiveFlag);
if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup();
if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup();
@@ -315,7 +319,7 @@ static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name,
auto load = new llvm::LoadInst(addr.getPointer(), name, beforeInst);
load->setAlignment(addr.getAlignment().getQuantity());
return load;
-}
+}
/// All the branch fixups on the EH stack have propagated out past the
/// outermost normal cleanup; resolve them all by adding cases to the
@@ -494,6 +498,13 @@ void CodeGenFunction::PopCleanupBlocks(
&LifetimeExtendedCleanupStack[I],
Header.getSize());
I += Header.getSize();
+
+ if (Header.isConditional()) {
+ Address ActiveFlag =
+ reinterpret_cast<Address &>(LifetimeExtendedCleanupStack[I]);
+ initFullExprCleanupWithFlag(ActiveFlag);
+ I += sizeof(ActiveFlag);
+ }
}
LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize);
}
@@ -610,7 +621,7 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF,
++i;
use.set(unreachableBB);
-
+
// The only uses should be fixup switches.
llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser());
if (si->getNumCases() == 1 && si->getDefaultDest() == unreachableBB) {
@@ -624,12 +635,12 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF,
si->eraseFromParent();
// Destroy the load.
- assert(condition->getOperand(0) == CGF.NormalCleanupDest);
+ assert(condition->getOperand(0) == CGF.NormalCleanupDest.getPointer());
assert(condition->use_empty());
condition->eraseFromParent();
}
}
-
+
assert(entry->use_empty());
delete entry;
}
@@ -648,7 +659,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
Address NormalActiveFlag =
Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag()
: Address::invalid();
- Address EHActiveFlag =
+ Address EHActiveFlag =
Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag()
: Address::invalid();
@@ -697,7 +708,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// cleanup, rewrite it so that it leads to the appropriate place.
if (Scope.isNormalCleanup() && HasPrebranchedFallthrough && !IsActive) {
llvm::BasicBlock *prebranchDest;
-
+
// If the prebranch is semantically branching through the next
// cleanup, just forward it to the next block, leaving the
// insertion point in the prebranched block.
@@ -833,7 +844,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (NormalCleanupDestSlot->hasOneUse()) {
NormalCleanupDestSlot->user_back()->eraseFromParent();
NormalCleanupDestSlot->eraseFromParent();
- NormalCleanupDest = nullptr;
+ NormalCleanupDest = Address::invalid();
}
llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);
@@ -911,7 +922,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
}
// V. Set up the fallthrough edge out.
-
+
// Case 1: a fallthrough source exists but doesn't branch to the
// cleanup because the cleanup is inactive.
if (!HasFallthrough && FallthroughSource) {
@@ -971,16 +982,21 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
CurrentFuncletPad);
llvm::CleanupPadInst *CPI = nullptr;
- if (!EHPersonality::get(*this).usesFuncletPads()) {
- EHStack.pushTerminate();
- PushedTerminate = true;
- } else {
+
+ const EHPersonality &Personality = EHPersonality::get(*this);
+ if (Personality.usesFuncletPads()) {
llvm::Value *ParentPad = CurrentFuncletPad;
if (!ParentPad)
ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad);
}
+ // Non-MSVC personalities need to terminate when an EH cleanup throws.
+ if (!Personality.isMSVCPersonality()) {
+ EHStack.pushTerminate();
+ PushedTerminate = true;
+ }
+
// We only actually emit the cleanup code if the cleanup is either
// active or was used before it was deactivated.
if (EHActiveFlag.isValid() || IsActive) {
@@ -1009,11 +1025,11 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
bool CodeGenFunction::isObviouslyBranchWithoutCleanups(JumpDest Dest) const {
assert(Dest.getScopeDepth().encloses(EHStack.stable_begin())
&& "stale jump destination");
-
+
// Calculate the innermost active normal cleanup.
EHScopeStack::stable_iterator TopCleanup =
EHStack.getInnermostActiveNormalCleanup();
-
+
// If we're not in an active normal cleanup scope, or if the
// destination scope is within the innermost active normal cleanup
// scope, we don't need to worry about fixups.
@@ -1103,7 +1119,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
break;
}
}
-
+
Builder.ClearInsertionPoint();
}
@@ -1233,8 +1249,10 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C));
assert(Scope.isActive() && "double deactivation");
- // If it's the top of the stack, just pop it.
- if (C == EHStack.stable_begin()) {
+ // If it's the top of the stack, just pop it, but do so only if it belongs
+ // to the current RunCleanupsScope.
+ if (C == EHStack.stable_begin() &&
+ CurrentCleanupScopeDepth.strictlyEncloses(C)) {
// If it's a normal cleanup, we need to pretend that the
// fallthrough is unreachable.
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
@@ -1250,10 +1268,10 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
}
Address CodeGenFunction::getNormalCleanupDestSlot() {
- if (!NormalCleanupDest)
+ if (!NormalCleanupDest.isValid())
NormalCleanupDest =
- CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
- return Address(NormalCleanupDest, CharUnits::fromQuantity(4));
+ CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
+ return NormalCleanupDest;
}
/// Emits all the code to cause the given temporary to be cleaned up.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
index 105c5629d50c..15d6f46dcb56 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
@@ -230,7 +230,7 @@ public:
};
/// A cleanup scope which generates the cleanup blocks lazily.
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EHCleanupScope : public EHScope {
+class alignas(8) EHCleanupScope : public EHScope {
/// The nearest normal cleanup scope enclosing this one.
EHScopeStack::stable_iterator EnclosingNormal;
@@ -509,7 +509,7 @@ class EHScopeStack::iterator {
public:
iterator() : Ptr(nullptr) {}
- EHScope *get() const {
+ EHScope *get() const {
return reinterpret_cast<EHScope*>(Ptr);
}
@@ -627,16 +627,21 @@ struct EHPersonality {
static const EHPersonality MSVC_except_handler;
static const EHPersonality MSVC_C_specific_handler;
static const EHPersonality MSVC_CxxFrameHandler3;
+ static const EHPersonality GNU_Wasm_CPlusPlus;
/// Does this personality use landingpads or the family of pad instructions
/// designed to form funclets?
- bool usesFuncletPads() const { return isMSVCPersonality(); }
+ bool usesFuncletPads() const {
+ return isMSVCPersonality() || isWasmPersonality();
+ }
bool isMSVCPersonality() const {
return this == &MSVC_except_handler || this == &MSVC_C_specific_handler ||
this == &MSVC_CxxFrameHandler3;
}
+ bool isWasmPersonality() const { return this == &GNU_Wasm_CPlusPlus; }
+
bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
};
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp
index 5842e7b3ff93..4f525c8aac85 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp
@@ -44,6 +44,15 @@ struct clang::CodeGen::CGCoroData {
// A branch to this block is emitted when coroutine needs to suspend.
llvm::BasicBlock *SuspendBB = nullptr;
+ // The promise type's 'unhandled_exception' handler, if it defines one.
+ Stmt *ExceptionHandler = nullptr;
+
+ // A temporary i1 alloca that stores whether 'await_resume' threw an
+ // exception. If it did, 'true' is stored in this variable, and the coroutine
+ // body must be skipped. If the promise type does not define an exception
+ // handler, this is null.
+ llvm::Value *ResumeEHVar = nullptr;
+
// Stores the jump destination just before the coroutine memory is freed.
// This is the destination that every suspend point jumps to for the cleanup
// branch.
@@ -121,6 +130,16 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) {
return Prefix;
}
+static bool memberCallExpressionCanThrow(const Expr *E) {
+ if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E))
+ if (const auto *Proto =
+ CE->getMethodDecl()->getType()->getAs<FunctionProtoType>())
+ if (isNoexceptExceptionSpec(Proto->getExceptionSpecType()) &&
+ Proto->canThrow() == CT_Cannot)
+ return false;
+ return true;
+}
+
// Emit suspend expression which roughly looks like:
//
// auto && x = CommonExpr();
@@ -208,11 +227,36 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
// Emit await_resume expression.
CGF.EmitBlock(ReadyBlock);
+
+ // Exception handling requires additional IR. If the 'await_resume' function
+ // is marked as 'noexcept', we avoid generating this additional IR.
+ CXXTryStmt *TryStmt = nullptr;
+ if (Coro.ExceptionHandler && Kind == AwaitKind::Init &&
+ memberCallExpressionCanThrow(S.getResumeExpr())) {
+ Coro.ResumeEHVar =
+ CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh"));
+ Builder.CreateFlagStore(true, Coro.ResumeEHVar);
+
+ auto Loc = S.getResumeExpr()->getExprLoc();
+ auto *Catch = new (CGF.getContext())
+ CXXCatchStmt(Loc, /*exDecl=*/nullptr, Coro.ExceptionHandler);
+ auto *TryBody =
+ CompoundStmt::Create(CGF.getContext(), S.getResumeExpr(), Loc, Loc);
+ TryStmt = CXXTryStmt::Create(CGF.getContext(), Loc, TryBody, Catch);
+ CGF.EnterCXXTryStmt(*TryStmt);
+ }
+
LValueOrRValue Res;
if (forLValue)
Res.LV = CGF.EmitLValue(S.getResumeExpr());
else
Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);
+
+ if (TryStmt) {
+ Builder.CreateFlagStore(false, Coro.ResumeEHVar);
+ CGF.ExitCXXTryStmt(*TryStmt);
+ }
+
return Res;
}
@@ -315,7 +359,7 @@ namespace {
GetParamRef Visitor;
Visitor.Visit(const_cast<Expr*>(InitExpr));
assert(Visitor.Expr);
- auto *DREOrig = cast<DeclRefExpr>(Visitor.Expr);
+ DeclRefExpr *DREOrig = Visitor.Expr;
auto *PD = DREOrig->getDecl();
auto it = LocalDeclMap.find(PD);
@@ -588,19 +632,40 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
EHStack.pushCleanup<CallCoroEnd>(EHCleanup);
CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
+ CurCoro.Data->ExceptionHandler = S.getExceptionHandler();
EmitStmt(S.getInitSuspendStmt());
CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
- if (auto *OnException = S.getExceptionHandler()) {
+ if (CurCoro.Data->ExceptionHandler) {
+ // If we generated IR to record whether an exception was thrown from
+ // 'await_resume', then use that IR to determine whether the coroutine
+ // body should be skipped.
+ // If we didn't generate the IR (perhaps because 'await_resume' was marked
+ // as 'noexcept'), then we skip this check.
+ BasicBlock *ContBB = nullptr;
+ if (CurCoro.Data->ResumeEHVar) {
+ BasicBlock *BodyBB = createBasicBlock("coro.resumed.body");
+ ContBB = createBasicBlock("coro.resumed.cont");
+ Value *SkipBody = Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar,
+ "coro.resumed.eh");
+ Builder.CreateCondBr(SkipBody, ContBB, BodyBB);
+ EmitBlock(BodyBB);
+ }
+
auto Loc = S.getLocStart();
- CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, OnException);
- auto *TryStmt = CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch);
+ CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr,
+ CurCoro.Data->ExceptionHandler);
+ auto *TryStmt =
+ CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch);
EnterCXXTryStmt(*TryStmt);
emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock());
ExitCXXTryStmt(*TryStmt);
+
+ if (ContBB)
+ EmitBlock(ContBB);
}
else {
emitBodyAndFallthrough(*this, S, S.getBody());
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
index aeed4d658a4e..5be6fb3e4245 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -289,8 +289,7 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
<< OC->getIdentifier()->getNameStart() << ')';
}
} else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
- OS << OCD->getClassInterface()->getName() << '('
- << OCD->getName() << ')';
+ OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
} else if (isa<ObjCProtocolDecl>(DC)) {
// We can extract the type of the class from the self pointer.
if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) {
@@ -361,18 +360,19 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
return StringRef();
}
-llvm::DIFile::ChecksumKind
+Optional<llvm::DIFile::ChecksumKind>
CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const {
Checksum.clear();
- if (!CGM.getCodeGenOpts().EmitCodeView)
- return llvm::DIFile::CSK_None;
+ if (!CGM.getCodeGenOpts().EmitCodeView &&
+ CGM.getCodeGenOpts().DwarfVersion < 5)
+ return None;
SourceManager &SM = CGM.getContext().getSourceManager();
bool Invalid;
llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid);
if (Invalid)
- return llvm::DIFile::CSK_None;
+ return None;
llvm::MD5 Hash;
llvm::MD5::MD5Result Result;
@@ -384,51 +384,62 @@ CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const {
return llvm::DIFile::CSK_MD5;
}
+Optional<StringRef> CGDebugInfo::getSource(const SourceManager &SM,
+ FileID FID) {
+ if (!CGM.getCodeGenOpts().EmbedSource)
+ return None;
+
+ bool SourceInvalid = false;
+ StringRef Source = SM.getBufferData(FID, &SourceInvalid);
+
+ if (SourceInvalid)
+ return None;
+
+ return Source;
+}
+
llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()),
- TheCU->getFile()->getChecksumKind(),
- TheCU->getFile()->getChecksum());
+ return getOrCreateMainFile();
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()),
- TheCU->getFile()->getChecksumKind(),
- TheCU->getFile()->getChecksum());
+ return getOrCreateMainFile();
// Cache the results.
const char *fname = PLoc.getFilename();
- auto it = DIFileCache.find(fname);
+ auto It = DIFileCache.find(fname);
- if (it != DIFileCache.end()) {
+ if (It != DIFileCache.end()) {
// Verify that the information still exists.
- if (llvm::Metadata *V = it->second)
+ if (llvm::Metadata *V = It->second)
return cast<llvm::DIFile>(V);
}
SmallString<32> Checksum;
- llvm::DIFile::ChecksumKind CSKind =
+ Optional<llvm::DIFile::ChecksumKind> CSKind =
computeChecksum(SM.getFileID(Loc), Checksum);
+ Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
+ if (CSKind)
+ CSInfo.emplace(*CSKind, Checksum);
- llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()),
- remapDIPath(getCurrentDirname()),
- CSKind, Checksum);
+ llvm::DIFile *F = DBuilder.createFile(
+ remapDIPath(PLoc.getFilename()), remapDIPath(getCurrentDirname()), CSInfo,
+ getSource(SM, SM.getFileID(Loc)));
DIFileCache[fname].reset(F);
return F;
}
llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()),
- TheCU->getFile()->getChecksumKind(),
- TheCU->getFile()->getChecksum());
+ return DBuilder.createFile(
+ remapDIPath(TheCU->getFilename()), remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksum(),
+ CGM.getCodeGenOpts().EmbedSource ? TheCU->getSource() : None);
}
std::string CGDebugInfo::remapDIPath(StringRef Path) const {
@@ -472,7 +483,8 @@ StringRef CGDebugInfo::getCurrentDirname() {
void CGDebugInfo::CreateCompileUnit() {
SmallString<32> Checksum;
- llvm::DIFile::ChecksumKind CSKind = llvm::DIFile::CSK_None;
+ Optional<llvm::DIFile::ChecksumKind> CSKind;
+ Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
// Should we be asking the SourceManager for the main file name, instead of
// accepting it as an argument? This just causes the main file name to
@@ -551,14 +563,19 @@ void CGDebugInfo::CreateCompileUnit() {
break;
}
+ if (CSKind)
+ CSInfo.emplace(*CSKind, Checksum);
+
// 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 || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex,
+ remapDIPath(getCurrentDirname()), CSInfo,
+ getSource(SM, SM.getMainFileID())),
+ CGOpts.EmitVersionIdentMetadata ? Producer : "",
+ LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO,
CGOpts.DwarfDebugFlags, RuntimeVers,
CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind,
0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
@@ -620,14 +637,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return SelTy;
}
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
- case BuiltinType::Id: \
- return getOrCreateStructPtrType("opencl_" #ImgType "_" #Suffix "_t", \
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id: \
+ return getOrCreateStructPtrType("opencl_" #ImgType "_" #Suffix "_t", \
SingletonId);
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
- return getOrCreateStructPtrType("opencl_sampler_t",
- OCLSamplerDITy);
+ return getOrCreateStructPtrType("opencl_sampler_t", OCLSamplerDITy);
case BuiltinType::OCLEvent:
return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy);
case BuiltinType::OCLClkEvent:
@@ -645,6 +661,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::SChar:
Encoding = llvm::dwarf::DW_ATE_signed_char;
break;
+ case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
Encoding = llvm::dwarf::DW_ATE_UTF;
@@ -681,6 +698,34 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
// floating point types of the same size.
Encoding = llvm::dwarf::DW_ATE_float;
break;
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ Encoding = llvm::dwarf::DW_ATE_signed_fixed;
+ break;
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
+ Encoding = llvm::dwarf::DW_ATE_unsigned_fixed;
+ break;
}
switch (BT->getKind()) {
@@ -780,27 +825,49 @@ static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
}
}
-/// In C++ mode, types have linkage, so we can rely on the ODR and
-/// on their mangled names, if they're external.
-static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
- CodeGenModule &CGM,
- llvm::DICompileUnit *TheCU) {
- SmallString<256> FullName;
+// Determines if the tag declaration will require a type identifier.
+static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM,
+ llvm::DICompileUnit *TheCU) {
+ // We only add a type identifier for types with C++ name mangling.
+ if (!hasCXXMangling(TD, TheCU))
+ return false;
+
+ // CodeView types with C++ mangling need a type identifier.
+ if (CGM.getCodeGenOpts().EmitCodeView)
+ return true;
+
+ // Externally visible types with C++ mangling need a type identifier.
+ if (TD->isExternallyVisible())
+ return true;
+
+ return false;
+}
+
+// When emitting CodeView debug information we need to produce a type
+// identifier for all types which have a C++ mangling. Until a GUID is added
+// to the identifier (not currently implemented) the result will not be unique
+// across compilation units.
+// When emitting DWARF debug information, we need to produce a type identifier
+// for all externally visible types with C++ name mangling. This identifier
+// should be unique across ODR-compliant compilation units.
+static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM,
+ llvm::DICompileUnit *TheCU) {
+ SmallString<256> Identifier;
const TagDecl *TD = Ty->getDecl();
- if (!hasCXXMangling(TD, TheCU) || !TD->isExternallyVisible())
- return FullName;
+ if (!needsTypeIdentifier(TD, CGM, TheCU))
+ return Identifier;
// TODO: This is using the RTTI name. Is there a better way to get
// a unique string for a type?
- llvm::raw_svector_ostream Out(FullName);
+ llvm::raw_svector_ostream Out(Identifier);
CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out);
- return FullName;
+ return Identifier;
}
-/// \return the approproate DWARF tag for a composite type.
+/// \return the appropriate DWARF tag for a composite type.
static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
- llvm::dwarf::Tag Tag;
+ llvm::dwarf::Tag Tag;
if (RD->isStruct() || RD->isInterface())
Tag = llvm::dwarf::DW_TAG_structure_type;
else if (RD->isUnion())
@@ -828,10 +895,10 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
uint32_t Align = 0;
// Create the type.
- SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType(
getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align,
- llvm::DINode::FlagFwdDecl, FullName);
+ llvm::DINode::FlagFwdDecl, Identifier);
if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
@@ -904,31 +971,35 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
auto *DescTy = DBuilder.createPointerType(EltTy, Size);
FieldOffset = 0;
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
- FType = CGM.getContext().IntTy;
- EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
- FType = CGM.getContext().getPointerType(Ty->getPointeeType());
- EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
-
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- FieldSize = CGM.getContext().getTypeSize(Ty);
- FieldAlign = CGM.getContext().getTypeAlign(Ty);
- EltTys.push_back(DBuilder.createMemberType(
- Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset,
- llvm::DINode::FlagZero, DescTy));
+ if (CGM.getLangOpts().OpenCL) {
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__align", &FieldOffset));
+ } else {
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
+ FType = CGM.getContext().getPointerType(Ty->getPointeeType());
+ EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ FieldSize = CGM.getContext().getTypeSize(Ty);
+ FieldAlign = CGM.getContext().getTypeAlign(Ty);
+ EltTys.push_back(DBuilder.createMemberType(
+ Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset,
+ llvm::DINode::FlagZero, DescTy));
+ FieldOffset += FieldSize;
+ }
- FieldOffset += FieldSize;
Elements = DBuilder.getOrCreateArray(EltTys);
// The __block_literal_generic structs are marked with a special
// DW_AT_APPLE_BLOCK attribute and are an implementation detail only
// the debugger needs to know about. To allow type uniquing, emit
// them without a name or a location.
- EltTy =
- DBuilder.createStructType(Unit, "", nullptr, LineNo,
- FieldOffset, 0, Flags, nullptr, Elements);
+ EltTy = DBuilder.createStructType(Unit, "", nullptr, LineNo, FieldOffset, 0,
+ Flags, nullptr, Elements);
return DBuilder.createPointerType(EltTy, Size);
}
@@ -943,8 +1014,9 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false);
printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy());
- auto *AliasDecl = cast<TypeAliasTemplateDecl>(
- Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl();
+ auto *AliasDecl =
+ cast<TypeAliasTemplateDecl>(Ty->getTemplateName().getAsTemplateDecl())
+ ->getTemplatedDecl();
SourceLocation Loc = AliasDecl->getLocation();
return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc),
@@ -981,20 +1053,28 @@ static unsigned getDwarfCC(CallingConv CC) {
return llvm::dwarf::DW_CC_LLVM_vectorcall;
case CC_X86Pascal:
return llvm::dwarf::DW_CC_BORLAND_pascal;
-
- // FIXME: Create new DW_CC_ codes for these calling conventions.
case CC_Win64:
+ return llvm::dwarf::DW_CC_LLVM_Win64;
case CC_X86_64SysV:
+ return llvm::dwarf::DW_CC_LLVM_X86_64SysV;
case CC_AAPCS:
+ return llvm::dwarf::DW_CC_LLVM_AAPCS;
case CC_AAPCS_VFP:
+ return llvm::dwarf::DW_CC_LLVM_AAPCS_VFP;
case CC_IntelOclBicc:
+ return llvm::dwarf::DW_CC_LLVM_IntelOclBicc;
case CC_SpirFunction:
+ return llvm::dwarf::DW_CC_LLVM_SpirFunction;
case CC_OpenCLKernel:
+ return llvm::dwarf::DW_CC_LLVM_OpenCLKernel;
case CC_Swift:
+ return llvm::dwarf::DW_CC_LLVM_Swift;
case CC_PreserveMost:
+ return llvm::dwarf::DW_CC_LLVM_PreserveMost;
case CC_PreserveAll:
+ return llvm::dwarf::DW_CC_LLVM_PreserveAll;
case CC_X86RegCall:
- return 0;
+ return llvm::dwarf::DW_CC_LLVM_X86RegCall;
}
return 0;
}
@@ -1102,8 +1182,8 @@ CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
}
llvm::DINode::DIFlags flags = getAccessFlag(AS, RD);
- return DBuilder.createMemberType(scope, name, file, line, SizeInBits,
- Align, offsetInBits, flags, debugType);
+ return DBuilder.createMemberType(scope, name, file, line, SizeInBits, Align,
+ offsetInBits, flags, debugType);
}
void CGDebugInfo::CollectRecordLambdaFields(
@@ -1223,10 +1303,6 @@ void CGDebugInfo::CollectRecordFields(
else {
const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
- // Debug info for nested types is included in the member list only for
- // CodeView.
- bool IncludeNestedTypes = CGM.getCodeGenOpts().EmitCodeView;
-
// Field number for non-static fields.
unsigned fieldNo = 0;
@@ -1236,6 +1312,13 @@ void CGDebugInfo::CollectRecordFields(
if (const auto *V = dyn_cast<VarDecl>(I)) {
if (V->hasAttr<NoDebugAttr>())
continue;
+
+ // Skip variable template specializations when emitting CodeView. MSVC
+ // doesn't emit them.
+ if (CGM.getCodeGenOpts().EmitCodeView &&
+ isa<VarTemplateSpecializationDecl>(V))
+ continue;
+
// Reuse the existing static member declaration if one exists
auto MI = StaticDataMemberCache.find(V->getCanonicalDecl());
if (MI != StaticDataMemberCache.end()) {
@@ -1252,7 +1335,9 @@ void CGDebugInfo::CollectRecordFields(
// Bump field number for next field.
++fieldNo;
- } else if (IncludeNestedTypes) {
+ } else if (CGM.getCodeGenOpts().EmitCodeView) {
+ // Debug info for nested types is included in the member list only for
+ // CodeView.
if (const auto *nestedType = dyn_cast<TypeDecl>(I))
if (!nestedType->isImplicit() &&
nestedType->getDeclContext() == record)
@@ -1386,7 +1471,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
// deleting dtor.
const auto *DD = dyn_cast<CXXDestructorDecl>(Method);
GlobalDecl GD = DD ? GlobalDecl(DD, Dtor_Deleting) : GlobalDecl(Method);
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
VIndex = ML.Index;
@@ -1507,6 +1592,7 @@ void CGDebugInfo::CollectCXXBasesAux(
auto *BaseTy = getOrCreateType(BI.getType(), Unit);
llvm::DINode::DIFlags BFlags = StartingFlags;
uint64_t BaseOffset;
+ uint32_t VBPtrOffset = 0;
if (BI.isVirtual()) {
if (CGM.getTarget().getCXXABI().isItaniumFamily()) {
@@ -1520,6 +1606,10 @@ void CGDebugInfo::CollectCXXBasesAux(
// vbase offset offset in Itanium.
BaseOffset =
4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base);
+ VBPtrOffset = CGM.getContext()
+ .getASTRecordLayout(RD)
+ .getVBPtrOffset()
+ .getQuantity();
}
BFlags |= llvm::DINode::FlagVirtual;
} else
@@ -1528,8 +1618,8 @@ void CGDebugInfo::CollectCXXBasesAux(
// BI->isVirtual() and bits when not.
BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD);
- llvm::DIType *DTy =
- DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, BFlags);
+ llvm::DIType *DTy = DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset,
+ VBPtrOffset, BFlags);
EltTys.push_back(DTy);
}
}
@@ -1603,8 +1693,8 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
V = CGM.getCXXABI().EmitNullMemberPointer(MPT);
if (!V)
V = llvm::ConstantInt::get(CGM.Int8Ty, 0);
- TemplateParams.push_back(DBuilder.createTemplateValueParameter(
- TheCU, Name, TTy, V));
+ TemplateParams.push_back(
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V));
} break;
case TemplateArgument::Template:
TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(
@@ -1676,9 +1766,8 @@ llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
Optional<unsigned> DWARFAddressSpace =
CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace);
- llvm::DIType *vtbl_ptr_type =
- DBuilder.createPointerType(SubTy, Size, 0, DWARFAddressSpace,
- "__vtbl_ptr_type");
+ llvm::DIType *vtbl_ptr_type = DBuilder.createPointerType(
+ SubTy, Size, 0, DWARFAddressSpace, "__vtbl_ptr_type");
VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
return VTablePtrType;
}
@@ -1722,9 +1811,8 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace);
// Create a very wide void* type and insert it directly in the element list.
- llvm::DIType *VTableType =
- DBuilder.createPointerType(nullptr, VTableWidth, 0, DWARFAddressSpace,
- "__vtbl_ptr_type");
+ llvm::DIType *VTableType = DBuilder.createPointerType(
+ nullptr, VTableWidth, 0, DWARFAddressSpace, "__vtbl_ptr_type");
EltTys.push_back(VTableType);
// The vptr is a pointer to this special vtable type.
@@ -1739,9 +1827,9 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
VPtrTy = getOrCreateVTablePtrType(Unit);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType *VPtrMember = DBuilder.createMemberType(
- Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
- llvm::DINode::FlagArtificial, VPtrTy);
+ llvm::DIType *VPtrMember =
+ DBuilder.createMemberType(Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
+ llvm::DINode::FlagArtificial, VPtrTy);
EltTys.push_back(VPtrMember);
}
@@ -2079,7 +2167,7 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
llvm::raw_svector_ostream OS(ConfigMacros);
const auto &PPOpts = CGM.getPreprocessorOpts();
unsigned I = 0;
- // Translate the macro definitions back into a commmand line.
+ // Translate the macro definitions back into a command line.
for (auto &M : PPOpts.Macros) {
if (++I > 1)
OS << " ";
@@ -2088,9 +2176,14 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
OS << "\"-" << (Undef ? 'U' : 'D');
for (char c : Macro)
switch (c) {
- case '\\' : OS << "\\\\"; break;
- case '"' : OS << "\\\""; break;
- default: OS << c;
+ case '\\':
+ OS << "\\\\";
+ break;
+ case '"':
+ OS << "\\\"";
+ break;
+ default:
+ OS << c;
}
OS << '\"';
}
@@ -2107,6 +2200,7 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
: ~1ULL;
llvm::DIBuilder DIB(CGM.getModule());
DIB.createCompileUnit(TheCU->getSourceLanguage(),
+ // TODO: Support "Source" from external AST providers?
DIB.createFile(Mod.getModuleName(), Mod.getPath()),
TheCU->getProducer(), true, StringRef(), 0,
Mod.getASTFile(), llvm::DICompileUnit::FullDebug,
@@ -2162,7 +2256,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
if (!SClassTy)
return nullptr;
- llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0,
+ llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0,
llvm::DINode::FlagZero);
EltTys.push_back(InhTag);
}
@@ -2184,7 +2278,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
EltTys.push_back(PropertyNode);
};
{
- llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
+ llvm::SmallPtrSet<const IdentifierInfo *, 16> PropertySet;
for (const ObjCCategoryDecl *ClassExt : ID->known_extensions())
for (auto *PD : ClassExt->properties()) {
PropertySet.insert(PD->getIdentifier());
@@ -2265,10 +2359,12 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
PropertyNode = DBuilder.createObjCProperty(
PD->getName(), PUnit, PLine,
- hasDefaultGetterName(PD, Getter) ? "" : getSelectorName(
- PD->getGetterName()),
- hasDefaultSetterName(PD, Setter) ? "" : getSelectorName(
- PD->getSetterName()),
+ hasDefaultGetterName(PD, Getter)
+ ? ""
+ : getSelectorName(PD->getGetterName()),
+ hasDefaultSetterName(PD, Setter)
+ ? ""
+ : getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(),
getOrCreateType(PD->getType(), PUnit));
}
@@ -2291,12 +2387,14 @@ llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
llvm::DIFile *Unit) {
llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit);
int64_t Count = Ty->getNumElements();
- if (Count == 0)
- // If number of elements are not known then this is an unbounded array.
- // Use Count == -1 to express such arrays.
- Count = -1;
- llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(0, Count);
+ llvm::Metadata *Subscript;
+ QualType QTy(Ty, 0);
+ auto SizeExpr = SizeExprCache.find(QTy);
+ if (SizeExpr != SizeExprCache.end())
+ Subscript = DBuilder.getOrCreateSubrange(0, SizeExpr->getSecond());
+ else
+ Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1);
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
@@ -2353,8 +2451,12 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
}
}
- // FIXME: Verify this is right for VLAs.
- Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
+ auto SizeNode = SizeExprCache.find(EltTy);
+ if (SizeNode != SizeExprCache.end())
+ Subscripts.push_back(
+ DBuilder.getOrCreateSubrange(0, SizeNode->getSecond()));
+ else
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
EltTy = Ty->getElementType();
}
@@ -2422,8 +2524,7 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy);
}
-llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
- llvm::DIFile *U) {
+llvm::DIType *CGDebugInfo::CreateType(const PipeType *Ty, llvm::DIFile *U) {
return getOrCreateType(Ty->getElementType(), U);
}
@@ -2437,7 +2538,7 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
- SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
bool isImportedFromModule =
DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition();
@@ -2460,7 +2561,7 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
StringRef EDName = ED->getName();
llvm::DIType *RetTy = DBuilder.createReplaceableCompositeType(
llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line,
- 0, Size, Align, llvm::DINode::FlagFwdDecl, FullName);
+ 0, Size, Align, llvm::DINode::FlagFwdDecl, Identifier);
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
@@ -2480,14 +2581,17 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
- SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
// Create elements for each enumerator.
SmallVector<llvm::Metadata *, 16> Enumerators;
ED = ED->getDefinition();
+ bool IsSigned = ED->getIntegerType()->isSignedIntegerType();
for (const auto *Enum : ED->enumerators()) {
- Enumerators.push_back(DBuilder.createEnumerator(
- Enum->getName(), Enum->getInitVal().getSExtValue()));
+ const auto &InitVal = Enum->getInitVal();
+ auto Value = IsSigned ? InitVal.getSExtValue() : InitVal.getZExtValue();
+ Enumerators.push_back(
+ DBuilder.createEnumerator(Enum->getName(), Value, !IsSigned));
}
// Return a CompositeType for the enum itself.
@@ -2496,11 +2600,10 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
llvm::DIScope *EnumContext = getDeclContextDescriptor(ED);
- llvm::DIType *ClassTy =
- ED->isFixed() ? getOrCreateType(ED->getIntegerType(), DefUnit) : nullptr;
+ llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit);
return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit,
Line, Size, Align, EltArray, ClassTy,
- FullName);
+ Identifier, ED->isFixed());
}
llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
@@ -2585,10 +2688,10 @@ llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
- auto it = TypeCache.find(Ty.getAsOpaquePtr());
- if (it != TypeCache.end()) {
+ auto It = TypeCache.find(Ty.getAsOpaquePtr());
+ if (It != TypeCache.end()) {
// Verify that the debug info still exists.
- if (llvm::Metadata *V = it->second)
+ if (llvm::Metadata *V = It->second)
return cast<llvm::DIType>(V);
}
@@ -2623,7 +2726,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
return T;
llvm::DIType *Res = CreateTypeNode(Ty, Unit);
- void* TyPtr = Ty.getAsOpaquePtr();
+ void *TyPtr = Ty.getAsOpaquePtr();
// And update the type cache.
TypeCache[TyPtr].reset(Res);
@@ -2801,11 +2904,24 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
auto Align = getDeclAlignIfRequired(D, CGM.getContext());
- SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
+
+ // Explicitly record the calling convention for C++ records.
+ auto Flags = llvm::DINode::FlagZero;
+ if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (CGM.getCXXABI().getRecordArgABI(CXXRD) == CGCXXABI::RAA_Indirect)
+ Flags |= llvm::DINode::FlagTypePassByReference;
+ else
+ Flags |= llvm::DINode::FlagTypePassByValue;
+
+ // Record if a C++ record is trivial type.
+ if (CXXRD->isTrivial())
+ Flags |= llvm::DINode::FlagTrivial;
+ }
llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align,
- llvm::DINode::FlagZero, FullName);
+ Flags, Identifier);
// Elements of composite types usually have back to the type, creating
// uniquing cycles. Distinct nodes are more efficient.
@@ -2819,14 +2935,14 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
// so they don't tend to be involved in uniquing cycles and there is some
// chance of merging them when linking together two modules. Only make
// them distinct if they are ODR-uniqued.
- if (FullName.empty())
+ if (Identifier.empty())
break;
LLVM_FALLTHROUGH;
case llvm::dwarf::DW_TAG_structure_type:
case llvm::dwarf::DW_TAG_union_type:
case llvm::dwarf::DW_TAG_class_type:
- // Immediatley resolve to a distinct node.
+ // Immediately resolve to a distinct node.
RealDecl =
llvm::MDNode::replaceWithDistinct(llvm::TempDICompositeType(RealDecl));
break;
@@ -2901,10 +3017,10 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
if (DebugKind >= codegenoptions::LimitedDebugInfo) {
if (const NamespaceDecl *NSDecl =
- dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
+ dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNamespace(NSDecl);
else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {
llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
}
@@ -2931,8 +3047,8 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
llvm::APInt ConstVal(32, 1);
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
- T = CGM.getContext().getConstantArrayType(ET, ConstVal,
- ArrayType::Normal, 0);
+ T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal,
+ 0);
}
Name = VD->getName();
@@ -2959,8 +3075,8 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
if (DC->isRecord())
DC = CGM.getContext().getTranslationUnitDecl();
- llvm::DIScope *Mod = getParentModuleOrNull(VD);
- VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);
+ llvm::DIScope *Mod = getParentModuleOrNull(VD);
+ VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);
}
llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
@@ -2972,8 +3088,8 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *DContext = Unit;
unsigned Line = getLineNumber(Loc);
- collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext,
- TParamsArray, Flags);
+ collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, TParamsArray,
+ Flags);
auto *FD = dyn_cast<FunctionDecl>(GD.getDecl());
// Build function type.
@@ -2999,20 +3115,18 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
!FD->isExternallyVisible(),
/* isDefinition = */ false, 0, Flags, CGM.getLangOpts().Optimize,
TParamsArray.get(), getFunctionDeclaration(FD));
- const auto *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl());
+ const FunctionDecl *CanonDecl = FD->getCanonicalDecl();
FwdDeclReplaceMap.emplace_back(std::piecewise_construct,
std::make_tuple(CanonDecl),
std::make_tuple(SP));
return SP;
}
-llvm::DISubprogram *
-CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) {
+llvm::DISubprogram *CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) {
return getFunctionFwdDeclOrStub(GD, /* Stub = */ false);
}
-llvm::DISubprogram *
-CGDebugInfo::getFunctionStub(GlobalDecl GD) {
+llvm::DISubprogram *CGDebugInfo::getFunctionStub(GlobalDecl GD) {
return getFunctionFwdDeclOrStub(GD, /* Stub = */ true);
}
@@ -3136,7 +3250,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
if (FPT->getNumParams() > 1)
SelfDeclTy = FPT->getParamType(0);
if (!SelfDeclTy.isNull())
- Elts.push_back(CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F)));
+ Elts.push_back(
+ CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F)));
// "_cmd" pointer is always second argument.
Elts.push_back(DBuilder.createArtificialType(
getOrCreateType(CGM.getContext().getObjCSelType(), F)));
@@ -3172,7 +3287,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
- llvm::Function *Fn, CGBuilderTy &Builder) {
+ llvm::Function *Fn, bool CurFuncIsThunk,
+ CGBuilderTy &Builder) {
StringRef Name;
StringRef LinkageName;
@@ -3213,11 +3329,15 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (Name.startswith("\01"))
Name = Name.substr(1);
- if (!HasDecl || D->isImplicit()) {
+ if (!HasDecl || D->isImplicit() || D->hasAttr<ArtificialAttr>()) {
Flags |= llvm::DINode::FlagArtificial;
// Artificial functions should not silently reuse CurLoc.
CurLoc = SourceLocation();
}
+
+ if (CurFuncIsThunk)
+ Flags |= llvm::DINode::FlagThunk;
+
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = getLineNumber(ScopeLoc);
@@ -3238,6 +3358,27 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (HasDecl && isa<FunctionDecl>(D))
DeclCache[D->getCanonicalDecl()].reset(SP);
+ if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
+ // Starting with DWARF V5 method declarations are emitted as children of
+ // the interface type.
+ if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
+ const ObjCInterfaceDecl *ID = OMD->getClassInterface();
+ QualType QTy(ID->getTypeForDecl(), 0);
+ auto It = TypeCache.find(QTy.getAsOpaquePtr());
+ if (It != TypeCache.end()) {
+ llvm::DICompositeType *InterfaceDecl =
+ cast<llvm::DICompositeType>(It->second);
+ llvm::DISubprogram *FD = DBuilder.createFunction(
+ InterfaceDecl, Name, LinkageName, Unit, LineNo,
+ getOrCreateFunctionType(D, FnType, Unit), Fn->hasLocalLinkage(),
+ false /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize,
+ TParamsArray.get());
+ DBuilder.finalizeSubprogram(FD);
+ ObjCMethodCache[ID].push_back(FD);
+ }
+ }
+ }
+
// Push the function onto the lexical block stack.
LexicalBlockStack.emplace_back(SP);
@@ -3330,8 +3471,7 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
}
void CGDebugInfo::AppendAddressSpaceXDeref(
- unsigned AddressSpace,
- SmallVectorImpl<int64_t> &Expr) const {
+ unsigned AddressSpace, SmallVectorImpl<int64_t> &Expr) const {
Optional<unsigned> DWARFAddressSpace =
CGM.getTarget().getDWARFAddressSpace(AddressSpace);
if (!DWARFAddressSpace)
@@ -3463,13 +3603,14 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
nullptr, Elements);
}
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
- llvm::Optional<unsigned> ArgNo,
- CGBuilderTy &Builder) {
+llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
+ llvm::Value *Storage,
+ llvm::Optional<unsigned> ArgNo,
+ CGBuilderTy &Builder) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
if (VD->hasAttr<NoDebugAttr>())
- return;
+ return nullptr;
bool Unwritten =
VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) &&
@@ -3487,7 +3628,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
// If there is no debug info for this type then do not emit debug info
// for this variable.
if (!Ty)
- return;
+ return nullptr;
// Get location information.
unsigned Line = 0;
@@ -3538,15 +3679,15 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
} else if (const auto *RT = dyn_cast<RecordType>(VD->getType())) {
// If VD is an anonymous union then Storage represents value for
// all union fields.
- const auto *RD = cast<RecordDecl>(RT->getDecl());
+ const RecordDecl *RD = RT->getDecl();
if (RD->isUnion() && RD->isAnonymousStructOrUnion()) {
// GDB has trouble finding local variables in anonymous unions, so we emit
- // artifical local variables for each of the members.
+ // artificial local variables for each of the members.
//
// FIXME: Remove this code as soon as GDB supports this.
// The debug info verifier in LLVM operates based on the assumption that a
- // variable has the same size as its storage and we had to disable the check
- // for artificial variables.
+ // variable has the same size as its storage and we had to disable the
+ // check for artificial variables.
for (const auto *Field : RD->fields()) {
llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
StringRef FieldName = Field->getName();
@@ -3571,25 +3712,26 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
}
// Create the descriptor for the variable.
- auto *D = ArgNo
- ? DBuilder.createParameterVariable(
- Scope, Name, *ArgNo, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags)
- : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags,
- Align);
+ auto *D = ArgNo ? DBuilder.createParameterVariable(
+ Scope, Name, *ArgNo, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags)
+ : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize,
+ Flags, Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt),
Builder.GetInsertBlock());
+
+ return D;
}
-void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
- llvm::Value *Storage,
- CGBuilderTy &Builder) {
+llvm::DILocalVariable *
+CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage,
+ CGBuilderTy &Builder) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
- EmitDeclare(VD, Storage, llvm::None, Builder);
+ return EmitDeclare(VD, Storage, llvm::None, Builder);
}
llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
@@ -3686,7 +3828,7 @@ struct BlockLayoutChunk {
bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
return l.OffsetInBits < r.OffsetInBits;
}
-}
+} // namespace
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
StringRef Name,
@@ -3710,25 +3852,35 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
CGM.getDataLayout().getStructLayout(block.StructureType);
SmallVector<llvm::Metadata *, 16> fields;
- fields.push_back(createFieldType("__isa", C.VoidPtrTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(0),
- tunit, tunit));
- fields.push_back(createFieldType("__flags", C.IntTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(1),
- tunit, tunit));
- fields.push_back(createFieldType("__reserved", C.IntTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(2),
- tunit, tunit));
- auto *FnTy = block.getBlockExpr()->getFunctionType();
- auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar());
- fields.push_back(createFieldType("__FuncPtr", FnPtrType, loc, AS_public,
- blockLayout->getElementOffsetInBits(3),
- tunit, tunit));
- fields.push_back(createFieldType(
- "__descriptor", C.getPointerType(block.NeedsCopyDispose
- ? C.getBlockDescriptorExtendedType()
- : C.getBlockDescriptorType()),
- loc, AS_public, blockLayout->getElementOffsetInBits(4), tunit, tunit));
+ if (CGM.getLangOpts().OpenCL) {
+ fields.push_back(createFieldType("__size", C.IntTy, loc, AS_public,
+ blockLayout->getElementOffsetInBits(0),
+ tunit, tunit));
+ fields.push_back(createFieldType("__align", C.IntTy, loc, AS_public,
+ blockLayout->getElementOffsetInBits(1),
+ tunit, tunit));
+ } else {
+ fields.push_back(createFieldType("__isa", C.VoidPtrTy, loc, AS_public,
+ blockLayout->getElementOffsetInBits(0),
+ tunit, tunit));
+ fields.push_back(createFieldType("__flags", C.IntTy, loc, AS_public,
+ blockLayout->getElementOffsetInBits(1),
+ tunit, tunit));
+ fields.push_back(createFieldType("__reserved", C.IntTy, loc, AS_public,
+ blockLayout->getElementOffsetInBits(2),
+ tunit, tunit));
+ auto *FnTy = block.getBlockExpr()->getFunctionType();
+ auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar());
+ fields.push_back(createFieldType("__FuncPtr", FnPtrType, loc, AS_public,
+ blockLayout->getElementOffsetInBits(3),
+ tunit, tunit));
+ fields.push_back(createFieldType(
+ "__descriptor",
+ C.getPointerType(block.NeedsCopyDispose
+ ? C.getBlockDescriptorExtendedType()
+ : C.getBlockDescriptorType()),
+ loc, AS_public, blockLayout->getElementOffsetInBits(4), tunit, tunit));
+ }
// We want to sort the captures by offset, not because DWARF
// requires this, but because we're paranoid about debuggers.
@@ -3806,8 +3958,8 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
}
SmallString<36> typeName;
- llvm::raw_svector_ostream(typeName) << "__block_literal_"
- << CGM.getUniqueBlockCount();
+ llvm::raw_svector_ostream(typeName)
+ << "__block_literal_" << CGM.getUniqueBlockCount();
llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields);
@@ -3823,8 +3975,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
// Create the descriptor for the parameter.
auto *debugVar = DBuilder.createParameterVariable(
- scope, Name, ArgNo, tunit, line, type,
- CGM.getLangOpts().Optimize, flags);
+ scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(),
@@ -3863,7 +4014,7 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls(
if (FieldName.empty()) {
if (const auto *RT = dyn_cast<RecordType>(Field->getType()))
GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
- Var, DContext);
+ Var, DContext);
continue;
}
// Use VarDecl's Tag, Scope and Line number.
@@ -4090,7 +4241,6 @@ void CGDebugInfo::setDwoId(uint64_t Signature) {
TheCU->setDWOId(Signature);
}
-
void CGDebugInfo::finalize() {
// Creating types might create further types - invalidating the current
// element and the size(), so don't cache/reference them.
@@ -4102,32 +4252,55 @@ void CGDebugInfo::finalize() {
DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty);
}
- for (auto p : ReplaceMap) {
- assert(p.second);
- auto *Ty = cast<llvm::DIType>(p.second);
+ if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
+ // Add methods to interface.
+ for (const auto &P : ObjCMethodCache) {
+ if (P.second.empty())
+ continue;
+
+ QualType QTy(P.first->getTypeForDecl(), 0);
+ auto It = TypeCache.find(QTy.getAsOpaquePtr());
+ assert(It != TypeCache.end());
+
+ llvm::DICompositeType *InterfaceDecl =
+ cast<llvm::DICompositeType>(It->second);
+
+ SmallVector<llvm::Metadata *, 16> EltTys;
+ auto CurrenetElts = InterfaceDecl->getElements();
+ EltTys.append(CurrenetElts.begin(), CurrenetElts.end());
+ for (auto &MD : P.second)
+ EltTys.push_back(MD);
+ llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
+ DBuilder.replaceArrays(InterfaceDecl, Elements);
+ }
+ }
+
+ for (const auto &P : ReplaceMap) {
+ assert(P.second);
+ auto *Ty = cast<llvm::DIType>(P.second);
assert(Ty->isForwardDecl());
- auto it = TypeCache.find(p.first);
- assert(it != TypeCache.end());
- assert(it->second);
+ auto It = TypeCache.find(P.first);
+ assert(It != TypeCache.end());
+ assert(It->second);
DBuilder.replaceTemporary(llvm::TempDIType(Ty),
- cast<llvm::DIType>(it->second));
+ cast<llvm::DIType>(It->second));
}
- for (const auto &p : FwdDeclReplaceMap) {
- assert(p.second);
- llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(p.second));
+ for (const auto &P : FwdDeclReplaceMap) {
+ assert(P.second);
+ llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(P.second));
llvm::Metadata *Repl;
- auto it = DeclCache.find(p.first);
+ auto It = DeclCache.find(P.first);
// If there has been no definition for the declaration, call RAUW
// with ourselves, that will destroy the temporary MDNode and
// replace it with a standard one, avoiding leaking memory.
- if (it == DeclCache.end())
- Repl = p.second;
+ if (It == DeclCache.end())
+ Repl = P.second;
else
- Repl = it->second;
+ Repl = It->second;
if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(Repl))
Repl = GVE->getVariable();
@@ -4157,6 +4330,5 @@ llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) {
return llvm::DebugLoc();
llvm::MDNode *Scope = LexicalBlockStack.back();
- return llvm::DebugLoc::get(
- getLineNumber(Loc), getColumnNumber(Loc), Scope);
+ return llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), Scope);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
index 4f7b7f2a0d9c..e632806138f0 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseMap.h"
@@ -66,7 +67,7 @@ class CGDebugInfo {
llvm::DIType *ClassTy = nullptr;
llvm::DICompositeType *ObjTy = nullptr;
llvm::DIType *SelTy = nullptr;
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
llvm::DIType *SingletonId = nullptr;
#include "clang/Basic/OpenCLImageTypes.def"
llvm::DIType *OCLSamplerDITy = nullptr;
@@ -81,6 +82,10 @@ class CGDebugInfo {
llvm::SmallDenseMap<llvm::StringRef, llvm::StringRef> DebugPrefixMap;
+ /// Cache that maps VLA types to size expressions for that type,
+ /// represented by instantiated Metadata nodes.
+ llvm::SmallDenseMap<QualType, llvm::Metadata *> SizeExprCache;
+
struct ObjCInterfaceCacheEntry {
const ObjCInterfaceType *Type;
llvm::DIType *Decl;
@@ -93,6 +98,10 @@ class CGDebugInfo {
/// Cache of previously constructed interfaces which may change.
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
+ /// Cache of forward declarations for methods belonging to the interface.
+ llvm::DenseMap<const ObjCInterfaceDecl *, std::vector<llvm::DISubprogram *>>
+ ObjCMethodCache;
+
/// Cache of references to clang modules and precompiled headers.
llvm::DenseMap<const Module *, llvm::TrackingMDRef> ModuleCache;
@@ -223,12 +232,12 @@ class CGDebugInfo {
/// Helper function for CollectCXXBases.
/// Adds debug info entries for types in Bases that are not in SeenTypes.
- void CollectCXXBasesAux(const CXXRecordDecl *RD, llvm::DIFile *Unit,
- SmallVectorImpl<llvm::Metadata *> &EltTys,
- llvm::DIType *RecordTy,
- const CXXRecordDecl::base_class_const_range &Bases,
- llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes,
- llvm::DINode::DIFlags StartingFlags);
+ void CollectCXXBasesAux(
+ const CXXRecordDecl *RD, llvm::DIFile *Unit,
+ SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy,
+ const CXXRecordDecl::base_class_const_range &Bases,
+ llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes,
+ llvm::DINode::DIFlags StartingFlags);
/// A helper function to collect template parameters.
llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList,
@@ -247,8 +256,7 @@ class CGDebugInfo {
llvm::DIType *createFieldType(StringRef name, QualType type,
SourceLocation loc, AccessSpecifier AS,
- uint64_t offsetInBits,
- uint32_t AlignInBits,
+ uint64_t offsetInBits, uint32_t AlignInBits,
llvm::DIFile *tunit, llvm::DIScope *scope,
const RecordDecl *RD = nullptr);
@@ -309,6 +317,11 @@ public:
void finalize();
+ /// Register VLA size expression debug node with the qualified type.
+ void registerVLASizeExpression(QualType Ty, llvm::Metadata *SizeExpr) {
+ SizeExprCache[Ty] = SizeExpr;
+ }
+
/// Module debugging: Support for building PCMs.
/// @{
/// Set the main CU's DwoId field to \p Signature.
@@ -356,7 +369,8 @@ public:
/// \param ScopeLoc The location of the function body.
void EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
- llvm::Function *Fn, CGBuilderTy &Builder);
+ llvm::Function *Fn, bool CurFnIsThunk,
+ CGBuilderTy &Builder);
/// Start a new scope for an inlined function.
void EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD);
@@ -379,16 +393,17 @@ public:
/// Emit call to \c llvm.dbg.declare for an automatic variable
/// declaration.
- void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
- CGBuilderTy &Builder);
+ /// Returns a pointer to the DILocalVariable associated with the
+ /// llvm.dbg.declare, or nullptr otherwise.
+ llvm::DILocalVariable *EmitDeclareOfAutoVariable(const VarDecl *Decl,
+ llvm::Value *AI,
+ CGBuilderTy &Builder);
/// Emit call to \c llvm.dbg.declare for an imported variable
/// declaration in a block.
- void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,
- llvm::Value *storage,
- CGBuilderTy &Builder,
- const CGBlockInfo &blockInfo,
- llvm::Instruction *InsertPoint = nullptr);
+ void EmitDeclareOfBlockDeclRefVariable(
+ const VarDecl *variable, llvm::Value *storage, CGBuilderTy &Builder,
+ const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint = nullptr);
/// Emit call to \c llvm.dbg.declare for an argument variable
/// declaration.
@@ -451,10 +466,14 @@ public:
llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent,
SourceLocation LineLoc,
SourceLocation FileLoc);
+
private:
/// Emit call to llvm.dbg.declare for a variable declaration.
- void EmitDeclare(const VarDecl *decl, llvm::Value *AI,
- llvm::Optional<unsigned> ArgNo, CGBuilderTy &Builder);
+ /// Returns a pointer to the DILocalVariable associated with the
+ /// llvm.dbg.declare, or nullptr otherwise.
+ llvm::DILocalVariable *EmitDeclare(const VarDecl *decl, llvm::Value *AI,
+ llvm::Optional<unsigned> ArgNo,
+ CGBuilderTy &Builder);
/// Build up structure info for the byref. See \a BuildByRefType.
llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
@@ -482,8 +501,11 @@ private:
std::string remapDIPath(StringRef) const;
/// Compute the file checksum debug info for input file ID.
- llvm::DIFile::ChecksumKind computeChecksum(FileID FID,
- SmallString<32> &Checksum) const;
+ Optional<llvm::DIFile::ChecksumKind>
+ computeChecksum(FileID FID, SmallString<32> &Checksum) const;
+
+ /// Get the source of the given file ID.
+ Optional<StringRef> getSource(const SourceManager &SM, FileID FID);
/// Get the file debug info descriptor for the input location.
llvm::DIFile *getOrCreateFile(SourceLocation Loc);
@@ -637,7 +659,7 @@ public:
~ApplyDebugLocation();
- /// \brief Apply TemporaryLocation if it is valid. Otherwise switch
+ /// Apply TemporaryLocation if it is valid. Otherwise switch
/// to an artificial debug location that has a valid scope, but no
/// line information.
///
@@ -651,7 +673,7 @@ public:
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, false, SourceLocation());
}
- /// \brief Apply TemporaryLocation if it is valid. Otherwise switch
+ /// Apply TemporaryLocation if it is valid. Otherwise switch
/// to an artificial debug location that has a valid scope, but no
/// line information.
static ApplyDebugLocation
@@ -668,7 +690,6 @@ public:
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, true, SourceLocation());
}
-
};
/// A scoped helper to set the current debug location to an inlined location.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
index 04585a8afbb6..57b2fbadbeec 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -229,18 +229,19 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
LangAS AS = GetGlobalVarAddressSpace(&D);
unsigned TargetAS = getContext().getTargetAddressSpace(AS);
- // Local address space cannot have an initializer.
+ // OpenCL variables in local address space and CUDA shared
+ // variables cannot have an initializer.
llvm::Constant *Init = nullptr;
- if (Ty.getAddressSpace() != LangAS::opencl_local)
- Init = EmitNullConstant(Ty);
- else
+ if (Ty.getAddressSpace() == LangAS::opencl_local ||
+ D.hasAttr<CUDASharedAttr>())
Init = llvm::UndefValue::get(LTy);
+ else
+ Init = EmitNullConstant(Ty);
llvm::GlobalVariable *GV = new llvm::GlobalVariable(
getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name,
nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
- setGlobalVisibility(GV, &D, ForDefinition);
if (supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
@@ -248,12 +249,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
if (D.getTLSKind())
setTLSMode(GV, D);
- if (D.isExternallyVisible()) {
- if (D.hasAttr<DLLImportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- else if (D.hasAttr<DLLExportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
- }
+ setGVProperties(GV, &D);
// Make sure the result is of the correct type.
LangAS ExpectedAS = Ty.getAddressSpace();
@@ -291,8 +287,11 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
// never defer them.
assert(isa<ObjCMethodDecl>(DC) && "unexpected parent code decl");
}
- if (GD.getDecl())
+ if (GD.getDecl()) {
+ // Disable emission of the parent function for the OpenMP device codegen.
+ CGOpenMPRuntime::DisableAutoDeclareTargetRAII NoDeclTarget(*this);
(void)GetAddrOfGlobal(GD);
+ }
return Addr;
}
@@ -344,6 +343,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
OldGV->getThreadLocalMode(),
CGM.getContext().getTargetAddressSpace(D.getType()));
GV->setVisibility(OldGV->getVisibility());
+ GV->setDSOLocal(OldGV->isDSOLocal());
GV->setComdat(OldGV->getComdat());
// Steal the name of the old global
@@ -469,13 +469,11 @@ namespace {
}
};
- struct DestroyNRVOVariable final : EHScopeStack::Cleanup {
- DestroyNRVOVariable(Address addr,
- const CXXDestructorDecl *Dtor,
- llvm::Value *NRVOFlag)
- : Dtor(Dtor), NRVOFlag(NRVOFlag), Loc(addr) {}
+ template <class Derived>
+ struct DestroyNRVOVariable : EHScopeStack::Cleanup {
+ DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag)
+ : NRVOFlag(NRVOFlag), Loc(addr) {}
- const CXXDestructorDecl *Dtor;
llvm::Value *NRVOFlag;
Address Loc;
@@ -494,12 +492,39 @@ namespace {
CGF.EmitBlock(RunDtorBB);
}
+ static_cast<Derived *>(this)->emitDestructorCall(CGF);
+
+ if (NRVO) CGF.EmitBlock(SkipDtorBB);
+ }
+
+ virtual ~DestroyNRVOVariable() = default;
+ };
+
+ struct DestroyNRVOVariableCXX final
+ : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
+ DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor,
+ llvm::Value *NRVOFlag)
+ : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, NRVOFlag),
+ Dtor(Dtor) {}
+
+ const CXXDestructorDecl *Dtor;
+
+ void emitDestructorCall(CodeGenFunction &CGF) {
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
/*ForVirtualBase=*/false,
- /*Delegating=*/false,
- Loc);
+ /*Delegating=*/false, Loc);
+ }
+ };
- if (NRVO) CGF.EmitBlock(SkipDtorBB);
+ struct DestroyNRVOVariableC final
+ : DestroyNRVOVariable<DestroyNRVOVariableC> {
+ DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty)
+ : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, NRVOFlag), Ty(Ty) {}
+
+ QualType Ty;
+
+ void emitDestructorCall(CodeGenFunction &CGF) {
+ CGF.destroyNonTrivialCStruct(CGF, Loc, Ty);
}
};
@@ -821,11 +846,10 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
EmitStoreOfScalar(value, lvalue, /* isInitialization */ true);
}
-/// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the
-/// non-zero parts of the specified initializer with equal or fewer than
-/// NumStores scalar stores.
-static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
- unsigned &NumStores) {
+/// Decide whether we can emit the non-zero parts of the specified initializer
+/// with equal or fewer than NumStores scalar stores.
+static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init,
+ unsigned &NumStores) {
// Zero and Undef never requires any extra stores.
if (isa<llvm::ConstantAggregateZero>(Init) ||
isa<llvm::ConstantPointerNull>(Init) ||
@@ -840,7 +864,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
if (isa<llvm::ConstantArray>(Init) || isa<llvm::ConstantStruct>(Init)) {
for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i));
- if (!canEmitInitWithFewStoresAfterMemset(Elt, NumStores))
+ if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores))
return false;
}
return true;
@@ -850,7 +874,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
dyn_cast<llvm::ConstantDataSequential>(Init)) {
for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) {
llvm::Constant *Elt = CDS->getElementAsConstant(i);
- if (!canEmitInitWithFewStoresAfterMemset(Elt, NumStores))
+ if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores))
return false;
}
return true;
@@ -860,18 +884,18 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
return false;
}
-/// emitStoresForInitAfterMemset - For inits that
-/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
-/// stores that would be required.
-static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
- bool isVolatile, CGBuilderTy &Builder) {
+/// For inits that canEmitInitWithFewStoresAfterBZero returned true for, emit
+/// the scalar stores that would be required.
+static void emitStoresForInitAfterBZero(CodeGenModule &CGM,
+ llvm::Constant *Init, Address Loc,
+ bool isVolatile, CGBuilderTy &Builder) {
assert(!Init->isNullValue() && !isa<llvm::UndefValue>(Init) &&
- "called emitStoresForInitAfterMemset for zero or undef value.");
+ "called emitStoresForInitAfterBZero for zero or undef value.");
if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
- Builder.CreateDefaultAlignedStore(Init, Loc, isVolatile);
+ Builder.CreateStore(Init, Loc, isVolatile);
return;
}
@@ -882,8 +906,9 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// If necessary, get a pointer to the element and emit it.
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
- emitStoresForInitAfterMemset(
- Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
+ emitStoresForInitAfterBZero(
+ CGM, Elt,
+ Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()),
isVolatile, Builder);
}
return;
@@ -897,19 +922,19 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// If necessary, get a pointer to the element and emit it.
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
- emitStoresForInitAfterMemset(
- Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
+ emitStoresForInitAfterBZero(
+ CGM, Elt,
+ Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()),
isVolatile, Builder);
}
}
-/// shouldUseMemSetPlusStoresToInitialize - Decide whether we should use memset
-/// plus some stores to initialize a local variable instead of using a memcpy
-/// from a constant global. It is beneficial to use memset if the global is all
-/// zeros, or mostly zeros and large.
-static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
- uint64_t GlobalSize) {
- // If a global is all zeros, always use a memset.
+/// Decide whether we should use bzero plus some stores to initialize a local
+/// variable instead of using a memcpy from a constant global. It is beneficial
+/// to use bzero if the global is all zeros, or mostly zeros and large.
+static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init,
+ uint64_t GlobalSize) {
+ // If a global is all zeros, always use a bzero.
if (isa<llvm::ConstantAggregateZero>(Init)) return true;
// If a non-zero global is <= 32 bytes, always use a memcpy. If it is large,
@@ -920,7 +945,114 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
uint64_t SizeLimit = 32;
return GlobalSize > SizeLimit &&
- canEmitInitWithFewStoresAfterMemset(Init, StoreBudget);
+ canEmitInitWithFewStoresAfterBZero(Init, StoreBudget);
+}
+
+/// A byte pattern.
+///
+/// Can be "any" pattern if the value was padding or known to be undef.
+/// Can be "none" pattern if a sequence doesn't exist.
+class BytePattern {
+ uint8_t Val;
+ enum class ValueType : uint8_t { Specific, Any, None } Type;
+ BytePattern(ValueType Type) : Type(Type) {}
+
+public:
+ BytePattern(uint8_t Value) : Val(Value), Type(ValueType::Specific) {}
+ static BytePattern Any() { return BytePattern(ValueType::Any); }
+ static BytePattern None() { return BytePattern(ValueType::None); }
+ bool isAny() const { return Type == ValueType::Any; }
+ bool isNone() const { return Type == ValueType::None; }
+ bool isValued() const { return Type == ValueType::Specific; }
+ uint8_t getValue() const {
+ assert(isValued());
+ return Val;
+ }
+ BytePattern merge(const BytePattern Other) const {
+ if (isNone() || Other.isNone())
+ return None();
+ if (isAny())
+ return Other;
+ if (Other.isAny())
+ return *this;
+ if (getValue() == Other.getValue())
+ return *this;
+ return None();
+ }
+};
+
+/// Figures out whether the constant can be initialized with memset.
+static BytePattern constantIsRepeatedBytePattern(llvm::Constant *C) {
+ if (isa<llvm::ConstantAggregateZero>(C) || isa<llvm::ConstantPointerNull>(C))
+ return BytePattern(0x00);
+ if (isa<llvm::UndefValue>(C))
+ return BytePattern::Any();
+
+ if (isa<llvm::ConstantInt>(C)) {
+ auto *Int = cast<llvm::ConstantInt>(C);
+ if (Int->getBitWidth() % 8 != 0)
+ return BytePattern::None();
+ const llvm::APInt &Value = Int->getValue();
+ if (Value.isSplat(8))
+ return BytePattern(Value.getLoBits(8).getLimitedValue());
+ return BytePattern::None();
+ }
+
+ if (isa<llvm::ConstantFP>(C)) {
+ auto *FP = cast<llvm::ConstantFP>(C);
+ llvm::APInt Bits = FP->getValueAPF().bitcastToAPInt();
+ if (Bits.getBitWidth() % 8 != 0)
+ return BytePattern::None();
+ if (!Bits.isSplat(8))
+ return BytePattern::None();
+ return BytePattern(Bits.getLimitedValue() & 0xFF);
+ }
+
+ if (isa<llvm::ConstantVector>(C)) {
+ llvm::Constant *Splat = cast<llvm::ConstantVector>(C)->getSplatValue();
+ if (Splat)
+ return constantIsRepeatedBytePattern(Splat);
+ return BytePattern::None();
+ }
+
+ if (isa<llvm::ConstantArray>(C) || isa<llvm::ConstantStruct>(C)) {
+ BytePattern Pattern(BytePattern::Any());
+ for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) {
+ llvm::Constant *Elt = cast<llvm::Constant>(C->getOperand(I));
+ Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt));
+ if (Pattern.isNone())
+ return Pattern;
+ }
+ return Pattern;
+ }
+
+ if (llvm::ConstantDataSequential *CDS =
+ dyn_cast<llvm::ConstantDataSequential>(C)) {
+ BytePattern Pattern(BytePattern::Any());
+ for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) {
+ llvm::Constant *Elt = CDS->getElementAsConstant(I);
+ Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt));
+ if (Pattern.isNone())
+ return Pattern;
+ }
+ return Pattern;
+ }
+
+ // BlockAddress, ConstantExpr, and everything else is scary.
+ return BytePattern::None();
+}
+
+/// Decide whether we should use memset to initialize a local variable instead
+/// of using a memcpy from a constant global. Assumes we've already decided to
+/// not user bzero.
+/// FIXME We could be more clever, as we are for bzero above, and generate
+/// memset followed by stores. It's unclear that's worth the effort.
+static BytePattern shouldUseMemSetToInitialize(llvm::Constant *Init,
+ uint64_t GlobalSize) {
+ uint64_t SizeLimit = 32;
+ if (GlobalSize <= SizeLimit)
+ return BytePattern::None();
+ return constantIsRepeatedBytePattern(Init);
}
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
@@ -940,6 +1072,9 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
if (!ShouldEmitLifetimeMarkers)
return nullptr;
+ assert(Addr->getType()->getPointerAddressSpace() ==
+ CGM.getDataLayout().getAllocaAddrSpace() &&
+ "Pointer should be in alloca address space");
llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
llvm::CallInst *C =
@@ -949,12 +1084,68 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
}
void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+ assert(Addr->getType()->getPointerAddressSpace() ==
+ CGM.getDataLayout().getAllocaAddrSpace() &&
+ "Pointer should be in alloca address space");
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
llvm::CallInst *C =
Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
C->setDoesNotThrow();
}
+void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
+ CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo) {
+ // For each dimension stores its QualType and corresponding
+ // size-expression Value.
+ SmallVector<CodeGenFunction::VlaSizePair, 4> Dimensions;
+
+ // Break down the array into individual dimensions.
+ QualType Type1D = D.getType();
+ while (getContext().getAsVariableArrayType(Type1D)) {
+ auto VlaSize = getVLAElements1D(Type1D);
+ if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts))
+ Dimensions.emplace_back(C, Type1D.getUnqualifiedType());
+ else {
+ auto SizeExprAddr = CreateDefaultAlignTempAlloca(
+ VlaSize.NumElts->getType(), "__vla_expr");
+ Builder.CreateStore(VlaSize.NumElts, SizeExprAddr);
+ Dimensions.emplace_back(SizeExprAddr.getPointer(),
+ Type1D.getUnqualifiedType());
+ }
+ Type1D = VlaSize.Type;
+ }
+
+ if (!EmitDebugInfo)
+ return;
+
+ // Register each dimension's size-expression with a DILocalVariable,
+ // so that it can be used by CGDebugInfo when instantiating a DISubrange
+ // to describe this array.
+ for (auto &VlaSize : Dimensions) {
+ llvm::Metadata *MD;
+ if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts))
+ MD = llvm::ConstantAsMetadata::get(C);
+ else {
+ // Create an artificial VarDecl to generate debug info for.
+ IdentifierInfo &NameIdent = getContext().Idents.getOwn(
+ cast<llvm::AllocaInst>(VlaSize.NumElts)->getName());
+ auto VlaExprTy = VlaSize.NumElts->getType()->getPointerElementType();
+ auto QT = getContext().getIntTypeForBitwidth(
+ VlaExprTy->getScalarSizeInBits(), false);
+ auto *ArtificialDecl = VarDecl::Create(
+ getContext(), const_cast<DeclContext *>(D.getDeclContext()),
+ D.getLocation(), D.getLocation(), &NameIdent, QT,
+ getContext().CreateTypeSourceInfo(QT), SC_Auto);
+ ArtificialDecl->setImplicit();
+
+ MD = DI->EmitDeclareOfAutoVariable(ArtificialDecl, VlaSize.NumElts,
+ Builder);
+ }
+ assert(MD && "No Size expression debug node created");
+ DI->registerVLASizeExpression(VlaSize.Type, MD);
+ }
+}
+
/// EmitAutoVarAlloca - Emit the alloca and debug information for a
/// local variable. Does not emit initialization or destruction.
CodeGenFunction::AutoVarEmission
@@ -975,7 +1166,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
if (Ty->isVariablyModifiedType())
EmitVariablyModifiedType(Ty);
+ auto *DI = getDebugInfo();
+ bool EmitDebugInfo = DI && CGM.getCodeGenOpts().getDebugInfo() >=
+ codegenoptions::LimitedDebugInfo;
+
Address address = Address::invalid();
+ Address AllocaAddr = Address::invalid();
if (Ty->isConstantSizeType()) {
bool NRVO = getLangOpts().ElideConstructors &&
D.isNRVOVariable();
@@ -1016,16 +1212,27 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
}
// A normal fixed sized variable becomes an alloca in the entry block,
- // unless it's an NRVO variable.
-
- if (NRVO) {
+ // unless:
+ // - it's an NRVO variable.
+ // - we are compiling OpenMP and it's an OpenMP local variable.
+
+ Address OpenMPLocalAddr =
+ getLangOpts().OpenMP
+ ? CGM.getOpenMPRuntime().getAddressOfLocalVariable(*this, &D)
+ : Address::invalid();
+ if (getLangOpts().OpenMP && OpenMPLocalAddr.isValid()) {
+ address = OpenMPLocalAddr;
+ } else if (NRVO) {
// The named return value optimization: allocate this variable in the
// return slot, so that we can elide the copy when returning this
// variable (C++0x [class.copy]p34).
address = ReturnValue;
if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
- if (!cast<CXXRecordDecl>(RecordTy->getDecl())->hasTrivialDestructor()) {
+ const auto *RD = RecordTy->getDecl();
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ if ((CXXRD && !CXXRD->hasTrivialDestructor()) ||
+ RD->isNonTrivialToPrimitiveDestroy()) {
// Create a flag that is used to indicate when the NRVO was applied
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
@@ -1055,7 +1262,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Create the alloca. Note that we set the name separately from
// building the instruction so that it's there even in no-asserts
// builds.
- address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName());
+ address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName(),
+ /*ArraySize=*/nullptr, &AllocaAddr);
// Don't emit lifetime markers for MSVC catch parameters. The lifetime of
// the catch parameter starts in the catchpad instruction, and we can't
@@ -1083,7 +1291,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(size, address.getPointer());
+ EmitLifetimeStart(size, AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1108,28 +1316,28 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
pushStackRestore(NormalCleanup, Stack);
}
- llvm::Value *elementCount;
- QualType elementType;
- std::tie(elementCount, elementType) = getVLASize(Ty);
-
- llvm::Type *llvmTy = ConvertTypeForMem(elementType);
+ auto VlaSize = getVLASize(Ty);
+ llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type);
// Allocate memory for the array.
- address = CreateTempAlloca(llvmTy, alignment, "vla", elementCount);
+ address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts,
+ &AllocaAddr);
+
+ // If we have debug info enabled, properly describe the VLA dimensions for
+ // this type by registering the vla size expression for each of the
+ // dimensions.
+ EmitAndRegisterVariableArrayDimensions(DI, D, EmitDebugInfo);
}
setAddrOfLocalVar(&D, address);
emission.Addr = address;
+ emission.AllocaAddr = AllocaAddr;
// Emit debug info for local var declaration.
- if (HaveInsertPoint())
- if (CGDebugInfo *DI = getDebugInfo()) {
- if (CGM.getCodeGenOpts().getDebugInfo() >=
- codegenoptions::LimitedDebugInfo) {
- DI->setLocation(D.getLocation());
- DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder);
- }
- }
+ if (EmitDebugInfo && HaveInsertPoint()) {
+ DI->setLocation(D.getLocation());
+ (void)DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder);
+ }
if (D.hasAttr<AnnotateAttr>())
EmitVarAnnotations(&D, address.getPointer());
@@ -1137,23 +1345,36 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
- emission.getAllocatedAddress(),
+ emission.getOriginalAllocatedAddress(),
emission.getSizeForLifetimeMarkers());
return emission;
}
+static bool isCapturedBy(const VarDecl &, const Expr *);
+
+/// Determines whether the given __block variable is potentially
+/// captured by the given statement.
+static bool isCapturedBy(const VarDecl &Var, const Stmt *S) {
+ if (const Expr *E = dyn_cast<Expr>(S))
+ return isCapturedBy(Var, E);
+ for (const Stmt *SubStmt : S->children())
+ if (isCapturedBy(Var, SubStmt))
+ return true;
+ return false;
+}
+
/// Determines whether the given __block variable is potentially
/// captured by the given expression.
-static bool isCapturedBy(const VarDecl &var, const Expr *e) {
+static bool isCapturedBy(const VarDecl &Var, const Expr *E) {
// Skip the most common kinds of expressions that make
// hierarchy-walking expensive.
- e = e->IgnoreParenCasts();
+ E = E->IgnoreParenCasts();
- if (const BlockExpr *be = dyn_cast<BlockExpr>(e)) {
- const BlockDecl *block = be->getBlockDecl();
- for (const auto &I : block->captures()) {
- if (I.getVariable() == &var)
+ if (const BlockExpr *BE = dyn_cast<BlockExpr>(E)) {
+ const BlockDecl *Block = BE->getBlockDecl();
+ for (const auto &I : Block->captures()) {
+ if (I.getVariable() == &Var)
return true;
}
@@ -1161,19 +1382,19 @@ static bool isCapturedBy(const VarDecl &var, const Expr *e) {
return false;
}
- if (const StmtExpr *SE = dyn_cast<StmtExpr>(e)) {
+ if (const StmtExpr *SE = dyn_cast<StmtExpr>(E)) {
const CompoundStmt *CS = SE->getSubStmt();
for (const auto *BI : CS->body())
- if (const auto *E = dyn_cast<Expr>(BI)) {
- if (isCapturedBy(var, E))
- return true;
+ if (const auto *BIE = dyn_cast<Expr>(BI)) {
+ if (isCapturedBy(Var, BIE))
+ return true;
}
else if (const auto *DS = dyn_cast<DeclStmt>(BI)) {
// special case declarations
for (const auto *I : DS->decls()) {
if (const auto *VD = dyn_cast<VarDecl>((I))) {
const Expr *Init = VD->getInit();
- if (Init && isCapturedBy(var, Init))
+ if (Init && isCapturedBy(Var, Init))
return true;
}
}
@@ -1185,14 +1406,14 @@ static bool isCapturedBy(const VarDecl &var, const Expr *e) {
return false;
}
- for (const Stmt *SubStmt : e->children())
- if (isCapturedBy(var, cast<Expr>(SubStmt)))
+ for (const Stmt *SubStmt : E->children())
+ if (isCapturedBy(Var, SubStmt))
return true;
return false;
}
-/// \brief Determine whether the given initializer is trivial in the sense
+/// Determine whether the given initializer is trivial in the sense
/// that it requires no code to be generated.
bool CodeGenFunction::isTrivialInitializer(const Expr *Init) {
if (!Init)
@@ -1232,6 +1453,19 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
if (emission.IsByRef)
emitByrefStructureInit(emission);
+ // Initialize the variable here if it doesn't have a initializer and it is a
+ // C struct that is non-trivial to initialize or an array containing such a
+ // struct.
+ if (!Init &&
+ type.isNonTrivialToPrimitiveDefaultInitialize() ==
+ QualType::PDIK_Struct) {
+ LValue Dst = MakeAddrLValue(emission.getAllocatedAddress(), type);
+ if (emission.IsByRef)
+ drillIntoBlockVariable(*this, Dst, &D);
+ defaultInitNonTrivialCStructVar(Dst);
+ return;
+ }
+
if (isTrivialInitializer(Init))
return;
@@ -1270,58 +1504,66 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
llvm::ConstantInt::get(IntPtrTy,
getContext().getTypeSizeInChars(type).getQuantity());
- llvm::Type *BP = AllocaInt8PtrTy;
+ llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace());
if (Loc.getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP);
- // If the initializer is all or mostly zeros, codegen with memset then do
- // a few stores afterward.
- if (shouldUseMemSetPlusStoresToInitialize(constant,
- CGM.getDataLayout().getTypeAllocSize(constant->getType()))) {
+ // If the initializer is all or mostly the same, codegen with bzero / memset
+ // then do a few stores afterward.
+ uint64_t ConstantSize =
+ CGM.getDataLayout().getTypeAllocSize(constant->getType());
+ if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) {
Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
isVolatile);
// Zero and undef don't require a stores.
if (!constant->isNullValue() && !isa<llvm::UndefValue>(constant)) {
- Loc = Builder.CreateBitCast(Loc, constant->getType()->getPointerTo());
- emitStoresForInitAfterMemset(constant, Loc.getPointer(),
- isVolatile, Builder);
- }
- } else {
- // Otherwise, create a temporary global with the initializer then
- // memcpy from the global to the alloca.
- std::string Name = getStaticDeclName(CGM, D);
- unsigned AS = 0;
- if (getLangOpts().OpenCL) {
- AS = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
- BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS);
+ Loc = Builder.CreateBitCast(Loc,
+ constant->getType()->getPointerTo(Loc.getAddressSpace()));
+ emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder);
}
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true,
- llvm::GlobalValue::PrivateLinkage,
- constant, Name, nullptr,
- llvm::GlobalValue::NotThreadLocal, AS);
- GV->setAlignment(Loc.getAlignment().getQuantity());
- GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
-
- Address SrcPtr = Address(GV, Loc.getAlignment());
- if (SrcPtr.getType() != BP)
- SrcPtr = Builder.CreateBitCast(SrcPtr, BP);
+ return;
+ }
- Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile);
+ BytePattern Pattern = shouldUseMemSetToInitialize(constant, ConstantSize);
+ if (!Pattern.isNone()) {
+ uint8_t Value = Pattern.isAny() ? 0x00 : Pattern.getValue();
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, Value), SizeVal,
+ isVolatile);
+ return;
}
+
+ // Otherwise, create a temporary global with the initializer then
+ // memcpy from the global to the alloca.
+ std::string Name = getStaticDeclName(CGM, D);
+ unsigned AS = CGM.getContext().getTargetAddressSpace(
+ CGM.getStringLiteralAddressSpace());
+ BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS);
+
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ CGM.getModule(), constant->getType(), true,
+ llvm::GlobalValue::PrivateLinkage, constant, Name, nullptr,
+ llvm::GlobalValue::NotThreadLocal, AS);
+ GV->setAlignment(Loc.getAlignment().getQuantity());
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
+ Address SrcPtr = Address(GV, Loc.getAlignment());
+ if (SrcPtr.getType() != BP)
+ SrcPtr = Builder.CreateBitCast(SrcPtr, BP);
+
+ Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile);
}
-/// Emit an expression as an initializer for a variable at the given
-/// location. The expression is not necessarily the normal
-/// initializer for the variable, and the address is not necessarily
+/// Emit an expression as an initializer for an object (variable, field, etc.)
+/// at the given location. The expression is not necessarily the normal
+/// initializer for the object, and the address is not necessarily
/// its normal location.
///
/// \param init the initializing expression
-/// \param var the variable to act as if we're initializing
+/// \param D the object to act as if we're initializing
/// \param loc the address to initialize; its type is a pointer
-/// to the LLVM mapping of the variable's type
+/// to the LLVM mapping of the object's type
/// \param alignment the alignment of the address
-/// \param capturedByInit true if the variable is a __block variable
+/// \param capturedByInit true if \p D is a __block variable
/// whose address is potentially changed by the initializer
void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D,
LValue lvalue, bool capturedByInit) {
@@ -1349,11 +1591,17 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D,
if (type->isAtomicType()) {
EmitAtomicInit(const_cast<Expr*>(init), lvalue);
} else {
+ AggValueSlot::Overlap_t Overlap = AggValueSlot::MayOverlap;
+ if (isa<VarDecl>(D))
+ Overlap = AggValueSlot::DoesNotOverlap;
+ else if (auto *FD = dyn_cast<FieldDecl>(D))
+ Overlap = overlapForFieldInit(FD);
// TODO: how can we delay here if D is captured by its initializer?
EmitAggExpr(init, AggValueSlot::forLValue(lvalue,
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ Overlap));
}
return;
}
@@ -1386,8 +1634,8 @@ void CodeGenFunction::emitAutoVarTypeCleanup(
if (emission.NRVOFlag) {
assert(!type->isArrayType());
CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
- EHStack.pushCleanup<DestroyNRVOVariable>(cleanupKind, addr,
- dtor, emission.NRVOFlag);
+ EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, dtor,
+ emission.NRVOFlag);
return;
}
break;
@@ -1406,6 +1654,16 @@ void CodeGenFunction::emitAutoVarTypeCleanup(
case QualType::DK_objc_weak_lifetime:
break;
+
+ case QualType::DK_nontrivial_c_struct:
+ destroyer = CodeGenFunction::destroyNonTrivialCStruct;
+ if (emission.NRVOFlag) {
+ assert(!type->isArrayType());
+ EHStack.pushCleanup<DestroyNRVOVariableC>(cleanupKind, addr,
+ emission.NRVOFlag, type);
+ return;
+ }
+ break;
}
// If we haven't chosen a more specific destroyer, use the default.
@@ -1452,9 +1710,15 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
}
// If this is a block variable, call _Block_object_destroy
- // (on the unforwarded address).
- if (emission.IsByRef)
- enterByrefCleanup(emission);
+ // (on the unforwarded address). Don't enter this cleanup if we're in pure-GC
+ // mode.
+ if (emission.IsByRef && CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
+ BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
+ if (emission.Variable->getType().isObjCGCWeak())
+ Flags |= BLOCK_FIELD_IS_WEAK;
+ enterByrefCleanup(NormalAndEHCleanup, emission.Addr, Flags,
+ /*LoadBlockVarAddr*/ false);
+ }
}
CodeGenFunction::Destroyer *
@@ -1467,6 +1731,8 @@ CodeGenFunction::getDestroyer(QualType::DestructionKind kind) {
return destroyARCStrongPrecise;
case QualType::DK_objc_weak_lifetime:
return destroyARCWeak;
+ case QualType::DK_nontrivial_c_struct:
+ return destroyNonTrivialCStruct;
}
llvm_unreachable("Unknown DestructionKind");
}
@@ -1506,9 +1772,6 @@ void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) {
void CodeGenFunction::pushLifetimeExtendedDestroy(
CleanupKind cleanupKind, Address addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray) {
- assert(!isInConditionalBranch() &&
- "performing lifetime extension from within conditional");
-
// Push an EH-only cleanup for the object now.
// FIXME: When popping normal cleanups, we need to keep this EH cleanup
// around in case a temporary's destructor throws an exception.
@@ -1791,9 +2054,12 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
// Use better IR generation for certain implicit parameters.
if (auto IPD = dyn_cast<ImplicitParamDecl>(&D)) {
// The only implicit argument a block has is its literal.
- // We assume this is always passed directly.
+ // This may be passed as an inalloca'ed value on Windows x86.
if (BlockInfo) {
- setBlockContextParameter(IPD, ArgNo, Arg.getDirectValue());
+ llvm::Value *V = Arg.isIndirect()
+ ? Builder.CreateLoad(Arg.getIndirectAddress())
+ : Arg.getDirectValue();
+ setBlockContextParameter(IPD, ArgNo, V);
return;
}
}
@@ -1809,20 +2075,50 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
llvm::Type *IRTy = ConvertTypeForMem(Ty)->getPointerTo(AS);
if (DeclPtr.getType() != IRTy)
DeclPtr = Builder.CreateBitCast(DeclPtr, IRTy, D.getName());
+ // Indirect argument is in alloca address space, which may be different
+ // from the default address space.
+ auto AllocaAS = CGM.getASTAllocaAddressSpace();
+ auto *V = DeclPtr.getPointer();
+ auto SrcLangAS = getLangOpts().OpenCL ? LangAS::opencl_private : AllocaAS;
+ auto DestLangAS =
+ getLangOpts().OpenCL ? LangAS::opencl_private : LangAS::Default;
+ if (SrcLangAS != DestLangAS) {
+ assert(getContext().getTargetAddressSpace(SrcLangAS) ==
+ CGM.getDataLayout().getAllocaAddrSpace());
+ auto DestAS = getContext().getTargetAddressSpace(DestLangAS);
+ auto *T = V->getType()->getPointerElementType()->getPointerTo(DestAS);
+ DeclPtr = Address(getTargetHooks().performAddrSpaceCast(
+ *this, V, SrcLangAS, DestLangAS, T, true),
+ DeclPtr.getAlignment());
+ }
// Push a destructor cleanup for this parameter if the ABI requires it.
// Don't push a cleanup in a thunk for a method that will also emit a
// cleanup.
- if (!IsScalar && !CurFuncIsThunk &&
- getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
- const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- if (RD && RD->hasNonTrivialDestructor())
- pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty);
+ if (hasAggregateEvaluationKind(Ty) && !CurFuncIsThunk &&
+ Ty->getAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
+ if (QualType::DestructionKind DtorKind = Ty.isDestructedType()) {
+ assert((DtorKind == QualType::DK_cxx_destructor ||
+ DtorKind == QualType::DK_nontrivial_c_struct) &&
+ "unexpected destructor type");
+ pushDestroy(DtorKind, DeclPtr, Ty);
+ CalleeDestructedParamCleanups[cast<ParmVarDecl>(&D)] =
+ EHStack.stable_begin();
+ }
}
} else {
- // Otherwise, create a temporary to hold the value.
- DeclPtr = CreateMemTemp(Ty, getContext().getDeclAlign(&D),
- D.getName() + ".addr");
+ // Check if the parameter address is controlled by OpenMP runtime.
+ Address OpenMPLocalAddr =
+ getLangOpts().OpenMP
+ ? CGM.getOpenMPRuntime().getAddressOfLocalVariable(*this, &D)
+ : Address::invalid();
+ if (getLangOpts().OpenMP && OpenMPLocalAddr.isValid()) {
+ DeclPtr = OpenMPLocalAddr;
+ } else {
+ // Otherwise, create a temporary to hold the value.
+ DeclPtr = CreateMemTemp(Ty, getContext().getDeclAlign(&D),
+ D.getName() + ".addr");
+ }
DoStore = true;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
index 8c0e01e5624a..510863f68eff 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -27,9 +27,9 @@ using namespace CodeGen;
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
ConstantAddress DeclPtr) {
assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
- assert(!D.getType()->isReferenceType() &&
+ assert(!D.getType()->isReferenceType() &&
"Should not call EmitDeclInit on a reference!");
-
+
QualType type = D.getType();
LValue lv = CGF.MakeAddrLValue(DeclPtr, type);
@@ -53,7 +53,8 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
case TEK_Aggregate:
CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
return;
}
llvm_unreachable("bad evaluation kind");
@@ -66,7 +67,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
CodeGenModule &CGM = CGF.CGM;
// FIXME: __attribute__((cleanup)) ?
-
+
QualType type = D.getType();
QualType::DestructionKind dtorKind = type.isDestructedType();
@@ -79,6 +80,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
case QualType::DK_objc_strong_lifetime:
case QualType::DK_objc_weak_lifetime:
+ case QualType::DK_nontrivial_c_struct:
// We don't care about releasing objects during process teardown.
assert(!D.getTLSKind() && "should have rejected this");
return;
@@ -217,7 +219,7 @@ llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn, FI, FunctionArgList());
llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
-
+
// Make sure the call and the callee agree on calling convention.
if (llvm::Function *dtorFn =
dyn_cast<llvm::Function>(dtor->stripPointerCasts()))
@@ -234,7 +236,10 @@ void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
llvm::Constant *addr) {
// Create a function which calls the destructor.
llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);
+ registerGlobalDtorWithAtExit(dtorStub);
+}
+void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) {
// extern "C" int atexit(void (*f)(void));
llvm::FunctionType *atexitTy =
llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
@@ -311,7 +316,7 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
Fn->setSection(Section);
}
- SetInternalFunctionAttributes(nullptr, Fn, FI);
+ SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
Fn->setCallingConv(getRuntimeCC());
@@ -330,6 +335,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
!isInSanitizerBlacklist(SanitizerKind::HWAddress, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
+ if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) &&
+ !isInSanitizerBlacklist(SanitizerKind::KernelHWAddress, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
+
if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
!isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
@@ -342,6 +351,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
!isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SafeStack);
+ if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) &&
+ !isInSanitizerBlacklist(SanitizerKind::ShadowCallStack, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
+
return Fn;
}
@@ -378,6 +391,10 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
D->hasAttr<CUDASharedAttr>()))
return;
+ if (getLangOpts().OpenMP &&
+ getOpenMPRuntime().emitDeclareTargetVarDefinition(D, Addr, PerformInit))
+ return;
+
// Check if we've already initialized this decl.
auto I = DelayedCXXInitPosition.find(D);
if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
@@ -471,7 +488,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
// Create our global initialization function.
if (!PrioritizedCXXGlobalInits.empty()) {
SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
- llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
+ llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
PrioritizedCXXGlobalInits.end());
// Iterate over "chunks" of ctors with same priority and emit each chunk
// into separate function. Note - everything is sorted first by priority,
@@ -667,8 +684,8 @@ llvm::Function *CodeGenFunction::generateDestroyHelper(
StartFunction(VD, getContext().VoidTy, fn, FI, args);
emitDestroy(addr, type, destroyer, useEHCleanupForArray);
-
+
FinishFunction();
-
+
return fn;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
index 1978d2757ac5..5890b407e767 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -65,7 +65,7 @@ llvm::Constant *CodeGenModule::getTerminateFn() {
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
name = "__std_terminate";
else
- name = "\01?terminate@@YAXXZ";
+ name = "?terminate@@YAXXZ";
} else if (getLangOpts().ObjC1 &&
getLangOpts().ObjCRuntime.hasTerminate())
name = "objc_terminate";
@@ -111,21 +111,32 @@ const EHPersonality
EHPersonality::MSVC_C_specific_handler = { "__C_specific_handler", nullptr };
const EHPersonality
EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr };
+const EHPersonality
+EHPersonality::GNU_Wasm_CPlusPlus = { "__gxx_wasm_personality_v0", nullptr };
-static const EHPersonality &getCPersonality(const llvm::Triple &T,
+static const EHPersonality &getCPersonality(const TargetInfo &Target,
const LangOptions &L) {
+ const llvm::Triple &T = Target.getTriple();
+ if (T.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
if (L.SjLjExceptions)
return EHPersonality::GNU_C_SJLJ;
+ if (L.DWARFExceptions)
+ return EHPersonality::GNU_C;
if (L.SEHExceptions)
return EHPersonality::GNU_C_SEH;
return EHPersonality::GNU_C;
}
-static const EHPersonality &getObjCPersonality(const llvm::Triple &T,
+static const EHPersonality &getObjCPersonality(const TargetInfo &Target,
const LangOptions &L) {
+ const llvm::Triple &T = Target.getTriple();
+ if (T.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
+
switch (L.ObjCRuntime.getKind()) {
case ObjCRuntime::FragileMacOSX:
- return getCPersonality(T, L);
+ return getCPersonality(Target, L);
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
case ObjCRuntime::WatchOS:
@@ -145,24 +156,37 @@ static const EHPersonality &getObjCPersonality(const llvm::Triple &T,
llvm_unreachable("bad runtime kind");
}
-static const EHPersonality &getCXXPersonality(const llvm::Triple &T,
+static const EHPersonality &getCXXPersonality(const TargetInfo &Target,
const LangOptions &L) {
+ const llvm::Triple &T = Target.getTriple();
+ if (T.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
if (L.SjLjExceptions)
return EHPersonality::GNU_CPlusPlus_SJLJ;
+ if (L.DWARFExceptions)
+ return EHPersonality::GNU_CPlusPlus;
if (L.SEHExceptions)
return EHPersonality::GNU_CPlusPlus_SEH;
+ // Wasm EH is a non-MVP feature for now.
+ if (Target.hasFeature("exception-handling") &&
+ (T.getArch() == llvm::Triple::wasm32 ||
+ T.getArch() == llvm::Triple::wasm64))
+ return EHPersonality::GNU_Wasm_CPlusPlus;
return EHPersonality::GNU_CPlusPlus;
}
/// Determines the personality function to use when both C++
/// and Objective-C exceptions are being caught.
-static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
+static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target,
const LangOptions &L) {
+ if (Target.getTriple().isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
+
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);
+ return getCXXPersonality(Target, L);
// The ObjC personality defers to the C++ personality for non-ObjC
// handlers. Unlike the C++ case, we use the same personality
@@ -170,7 +194,7 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
case ObjCRuntime::WatchOS:
- return getObjCPersonality(T, L);
+ return getObjCPersonality(Target, L);
case ObjCRuntime::GNUstep:
return EHPersonality::GNU_ObjCXX;
@@ -179,7 +203,7 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
// mixed EH. Use the ObjC personality just to avoid returning null.
case ObjCRuntime::GCC:
case ObjCRuntime::ObjFW:
- return getObjCPersonality(T, L);
+ return getObjCPersonality(Target, L);
}
llvm_unreachable("bad runtime kind");
}
@@ -194,30 +218,17 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
const FunctionDecl *FD) {
const llvm::Triple &T = CGM.getTarget().getTriple();
const LangOptions &L = CGM.getLangOpts();
+ const TargetInfo &Target = CGM.getTarget();
// Functions using SEH get an SEH personality.
if (FD && FD->usesSEHTry())
return getSEHPersonalityMSVC(T);
- // Try to pick a personality function that is compatible with MSVC if we're
- // not compiling Obj-C. Obj-C users better have an Obj-C runtime that supports
- // the GCC-style personality function.
- if (T.isWindowsMSVCEnvironment() && !L.ObjC1) {
- if (L.SjLjExceptions)
- return EHPersonality::GNU_CPlusPlus_SJLJ;
- if (L.DWARFExceptions)
- return EHPersonality::GNU_CPlusPlus;
- return EHPersonality::MSVC_CxxFrameHandler3;
- }
-
- if (L.CPlusPlus && L.ObjC1)
- return getObjCXXPersonality(T, L);
- else if (L.CPlusPlus)
- return getCXXPersonality(T, L);
- else if (L.ObjC1)
- return getObjCPersonality(T, L);
- else
- return getCPersonality(T, L);
+ if (L.ObjC1)
+ return L.CPlusPlus ? getObjCXXPersonality(Target, L)
+ : getObjCPersonality(Target, L);
+ return L.CPlusPlus ? getCXXPersonality(Target, L)
+ : getCPersonality(Target, L);
}
const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
@@ -313,8 +324,7 @@ void CodeGenModule::SimplifyPersonality() {
return;
const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr);
- const EHPersonality &CXX =
- getCXXPersonality(getTarget().getTriple(), LangOpts);
+ const EHPersonality &CXX = getCXXPersonality(getTarget(), LangOpts);
if (&ObjCXX == &CXX)
return;
@@ -325,7 +335,7 @@ void CodeGenModule::SimplifyPersonality() {
// Nothing to do if it's unused.
if (!Fn || Fn->use_empty()) return;
-
+
// Can't do the optimization if it has non-C++ uses.
if (!PersonalityHasOnlyCXXUses(Fn)) return;
@@ -433,7 +443,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
if (!CGM.getLangOpts().CXXExceptions)
return;
-
+
const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) {
// Check if CapturedDecl is nothrow and create terminate scope for it.
@@ -448,11 +458,9 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
- if (isNoexceptExceptionSpec(EST)) {
- if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) {
- // noexcept functions are simple terminate scopes.
- EHStack.pushTerminate();
- }
+ if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
+ // noexcept functions are simple terminate scopes.
+ EHStack.pushTerminate();
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
// TODO: Revisit exception specifications for the MS ABI. There is a way to
// encode these in an object file but MSVC doesn't do anything with it.
@@ -512,7 +520,7 @@ static void emitFilterDispatchBlock(CodeGenFunction &CGF,
void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
if (!CGM.getLangOpts().CXXExceptions)
return;
-
+
const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) {
// Check if CapturedDecl is nothrow and pop terminate scope for it.
@@ -527,10 +535,8 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
- if (isNoexceptExceptionSpec(EST)) {
- if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) {
- EHStack.popTerminate();
- }
+ if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
+ EHStack.popTerminate();
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
// TODO: Revisit exception specifications for the MS ABI. There is a way to
// encode these in an object file but MSVC doesn't do anything with it.
@@ -584,7 +590,7 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
llvm::BasicBlock *
CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
if (EHPersonality::get(*this).usesFuncletPads())
- return getMSVCDispatchBlock(si);
+ return getFuncletEHDispatchBlock(si);
// The dispatch block for the end of the scope chain is a block that
// just resumes unwinding.
@@ -632,7 +638,7 @@ CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
}
llvm::BasicBlock *
-CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) {
+CodeGenFunction::getFuncletEHDispatchBlock(EHScopeStack::stable_iterator SI) {
// Returning nullptr indicates that the previous dispatch block should unwind
// to caller.
if (SI == EHStack.stable_end())
@@ -926,10 +932,121 @@ static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) {
CGF.Builder.restoreIP(SavedIP);
}
+// Wasm uses Windows-style EH instructions, but it merges all catch clauses into
+// one big catchpad, within which we use Itanium's landingpad-style selector
+// comparison instructions.
+static void emitWasmCatchPadBlock(CodeGenFunction &CGF,
+ EHCatchScope &CatchScope) {
+ llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock();
+ assert(DispatchBlock);
+
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
+ CGF.EmitBlockAfterUses(DispatchBlock);
+
+ llvm::Value *ParentPad = CGF.CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
+ llvm::BasicBlock *UnwindBB =
+ CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope());
+
+ unsigned NumHandlers = CatchScope.getNumHandlers();
+ llvm::CatchSwitchInst *CatchSwitch =
+ CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers);
+
+ // We don't use a landingpad instruction, so generate intrinsic calls to
+ // provide exception and selector values.
+ llvm::BasicBlock *WasmCatchStartBlock = CGF.createBasicBlock("catch.start");
+ CatchSwitch->addHandler(WasmCatchStartBlock);
+ CGF.EmitBlockAfterUses(WasmCatchStartBlock);
+
+ // Create a catchpad instruction.
+ SmallVector<llvm::Value *, 4> CatchTypes;
+ for (unsigned I = 0, E = NumHandlers; I < E; ++I) {
+ const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
+ CatchTypeInfo TypeInfo = Handler.Type;
+ if (!TypeInfo.RTTI)
+ TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy);
+ CatchTypes.push_back(TypeInfo.RTTI);
+ }
+ auto *CPI = CGF.Builder.CreateCatchPad(CatchSwitch, CatchTypes);
+
+ // Create calls to wasm.get.exception and wasm.get.ehselector intrinsics.
+ // Before they are lowered appropriately later, they provide values for the
+ // exception and selector.
+ llvm::Value *GetExnFn =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::wasm_get_exception);
+ llvm::Value *GetSelectorFn =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::wasm_get_ehselector);
+ llvm::CallInst *Exn = CGF.Builder.CreateCall(GetExnFn, CPI);
+ CGF.Builder.CreateStore(Exn, CGF.getExceptionSlot());
+ llvm::CallInst *Selector = CGF.Builder.CreateCall(GetSelectorFn, CPI);
+
+ llvm::Value *TypeIDFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
+
+ // If there's only a single catch-all, branch directly to its handler.
+ if (CatchScope.getNumHandlers() == 1 &&
+ CatchScope.getHandler(0).isCatchAll()) {
+ CGF.Builder.CreateBr(CatchScope.getHandler(0).Block);
+ CGF.Builder.restoreIP(SavedIP);
+ return;
+ }
+
+ // Test against each of the exception types we claim to catch.
+ for (unsigned I = 0, E = NumHandlers;; ++I) {
+ assert(I < E && "ran off end of handlers!");
+ const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
+ CatchTypeInfo TypeInfo = Handler.Type;
+ if (!TypeInfo.RTTI)
+ TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy);
+
+ // Figure out the next block.
+ llvm::BasicBlock *NextBlock;
+
+ bool EmitNextBlock = false, NextIsEnd = false;
+
+ // If this is the last handler, we're at the end, and the next block is a
+ // block that contains a call to the rethrow function, so we can unwind to
+ // the enclosing EH scope. The call itself will be generated later.
+ if (I + 1 == E) {
+ NextBlock = CGF.createBasicBlock("rethrow");
+ EmitNextBlock = true;
+ NextIsEnd = true;
+
+ // If the next handler is a catch-all, we're at the end, and the
+ // next block is that handler.
+ } else if (CatchScope.getHandler(I + 1).isCatchAll()) {
+ NextBlock = CatchScope.getHandler(I + 1).Block;
+ NextIsEnd = true;
+
+ // Otherwise, we're not at the end and we need a new block.
+ } else {
+ NextBlock = CGF.createBasicBlock("catch.fallthrough");
+ EmitNextBlock = true;
+ }
+
+ // Figure out the catch type's index in the LSDA's type table.
+ llvm::CallInst *TypeIndex = CGF.Builder.CreateCall(TypeIDFn, TypeInfo.RTTI);
+ TypeIndex->setDoesNotThrow();
+
+ llvm::Value *MatchesTypeIndex =
+ CGF.Builder.CreateICmpEQ(Selector, TypeIndex, "matches");
+ CGF.Builder.CreateCondBr(MatchesTypeIndex, Handler.Block, NextBlock);
+
+ if (EmitNextBlock)
+ CGF.EmitBlock(NextBlock);
+ if (NextIsEnd)
+ break;
+ }
+
+ CGF.Builder.restoreIP(SavedIP);
+}
+
/// Emit the structure of the dispatch block for the given catch scope.
/// It is an invariant that the dispatch block already exists.
static void emitCatchDispatchBlock(CodeGenFunction &CGF,
EHCatchScope &catchScope) {
+ if (EHPersonality::get(CGF).isWasmPersonality())
+ return emitWasmCatchPadBlock(CGF, catchScope);
if (EHPersonality::get(CGF).usesFuncletPads())
return emitCatchPadBlock(CGF, catchScope);
@@ -1017,6 +1134,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
unsigned NumHandlers = S.getNumHandlers();
EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin());
assert(CatchScope.getNumHandlers() == NumHandlers);
+ llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock();
// If the catch was not required, bail out now.
if (!CatchScope.hasEHBranches()) {
@@ -1049,6 +1167,22 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
isa<CXXConstructorDecl>(CurCodeDecl);
+ // Wasm uses Windows-style EH instructions, but merges all catch clauses into
+ // one big catchpad. So we save the old funclet pad here before we traverse
+ // each catch handler.
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
+ llvm::BasicBlock *WasmCatchStartBlock = nullptr;
+ if (EHPersonality::get(*this).isWasmPersonality()) {
+ auto *CatchSwitch =
+ cast<llvm::CatchSwitchInst>(DispatchBlock->getFirstNonPHI());
+ WasmCatchStartBlock = CatchSwitch->hasUnwindDest()
+ ? CatchSwitch->getSuccessor(1)
+ : CatchSwitch->getSuccessor(0);
+ auto *CPI = cast<llvm::CatchPadInst>(WasmCatchStartBlock->getFirstNonPHI());
+ CurrentFuncletPad = CPI;
+ }
+
// Perversely, we emit the handlers backwards precisely because we
// want them to appear in source order. In all of these cases, the
// catch block will have exactly one predecessor, which will be a
@@ -1056,7 +1190,9 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// a catch-all, one of the dispatch blocks will branch to two
// different handlers, and EmitBlockAfterUses will cause the second
// handler to be moved before the first.
+ bool HasCatchAll = false;
for (unsigned I = NumHandlers; I != 0; --I) {
+ HasCatchAll |= Handlers[I - 1].isCatchAll();
llvm::BasicBlock *CatchBlock = Handlers[I-1].Block;
EmitBlockAfterUses(CatchBlock);
@@ -1101,6 +1237,27 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
Builder.CreateBr(ContBB);
}
+ // Because in wasm we merge all catch clauses into one big catchpad, in case
+ // none of the types in catch handlers matches after we test against each of
+ // them, we should unwind to the next EH enclosing scope. We generate a call
+ // to rethrow function here to do that.
+ if (EHPersonality::get(*this).isWasmPersonality() && !HasCatchAll) {
+ assert(WasmCatchStartBlock);
+ // Navigate for the "rethrow" block we created in emitWasmCatchPadBlock().
+ // Wasm uses landingpad-style conditional branches to compare selectors, so
+ // we follow the false destination for each of the cond branches to reach
+ // the rethrow block.
+ llvm::BasicBlock *RethrowBlock = WasmCatchStartBlock;
+ while (llvm::TerminatorInst *TI = RethrowBlock->getTerminator()) {
+ auto *BI = cast<llvm::BranchInst>(TI);
+ assert(BI->isConditional());
+ RethrowBlock = BI->getSuccessor(1);
+ }
+ assert(RethrowBlock != WasmCatchStartBlock && RethrowBlock->empty());
+ Builder.SetInsertPoint(RethrowBlock);
+ CGM.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
+ }
+
EmitBlock(ContBB);
incrementProfileCounter(&S);
}
@@ -1188,7 +1345,7 @@ namespace {
CGF.PopCleanupBlock();
CGF.Builder.restoreIP(SavedIP);
}
-
+
// Now make sure we actually have an insertion point or the
// cleanup gods will hate us.
CGF.EnsureInsertPoint();
@@ -1379,8 +1536,17 @@ llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() {
CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
// Emit the __std_terminate call.
+ llvm::Value *Exn = nullptr;
+ // In case of wasm personality, we need to pass the exception value to
+ // __clang_call_terminate function.
+ if (getLangOpts().CPlusPlus &&
+ EHPersonality::get(*this).isWasmPersonality()) {
+ llvm::Value *GetExnFn =
+ CGM.getIntrinsic(llvm::Intrinsic::wasm_get_exception);
+ Exn = Builder.CreateCall(GetExnFn, CurrentFuncletPad);
+ }
llvm::CallInst *terminateCall =
- CGM.getCXXABI().emitTerminateForUnexpectedException(*this, nullptr);
+ CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
terminateCall->setDoesNotReturn();
Builder.CreateUnreachable();
@@ -1663,7 +1829,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
- const FunctionDecl *ParentSEHFn = ParentCGF.CurSEHParent;
+ const NamedDecl *ParentSEHFn = ParentCGF.CurSEHParent;
assert(ParentSEHFn && "No CurSEHParent!");
MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
if (IsFilter)
@@ -1806,6 +1972,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
return Builder.CreateZExt(&*AI, Int32Ty);
}
+void CodeGenFunction::pushSEHCleanup(CleanupKind Kind,
+ llvm::Function *FinallyFunc) {
+ EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc);
+}
+
void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index ac82b3eebc3c..f168dd02ead1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -61,18 +61,30 @@ llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
+Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty,
+ CharUnits Align,
+ const Twine &Name,
+ llvm::Value *ArraySize) {
+ auto Alloca = CreateTempAlloca(Ty, Name, ArraySize);
+ Alloca->setAlignment(Align.getQuantity());
+ return Address(Alloca, Align);
+}
+
+/// CreateTempAlloca - This creates a alloca and inserts it into the entry
+/// block. The alloca is casted to default address space if necessary.
Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
const Twine &Name,
llvm::Value *ArraySize,
- bool CastToDefaultAddrSpace) {
- auto Alloca = CreateTempAlloca(Ty, Name, ArraySize);
- Alloca->setAlignment(Align.getQuantity());
- llvm::Value *V = Alloca;
+ Address *AllocaAddr) {
+ auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize);
+ if (AllocaAddr)
+ *AllocaAddr = Alloca;
+ llvm::Value *V = Alloca.getPointer();
// Alloca always returns a pointer in alloca address space, which may
// be different from the type defined by the language. For example,
// in C++ the auto variables are in the default address space. Therefore
// cast alloca to the default address space when necessary.
- if (CastToDefaultAddrSpace && getASTAllocaAddressSpace() != LangAS::Default) {
+ if (getASTAllocaAddressSpace() != LangAS::Default) {
auto DestAddrSpace = getContext().getTargetAddressSpace(LangAS::Default);
llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
// When ArraySize is nullptr, alloca is inserted at AllocaInsertPt,
@@ -125,17 +137,26 @@ Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) {
}
Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name,
- bool CastToDefaultAddrSpace) {
+ Address *Alloca) {
// FIXME: Should we prefer the preferred type alignment here?
- return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name,
- CastToDefaultAddrSpace);
+ return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca);
}
Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
- const Twine &Name,
- bool CastToDefaultAddrSpace) {
- return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, nullptr,
- CastToDefaultAddrSpace);
+ const Twine &Name, Address *Alloca) {
+ return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name,
+ /*ArraySize=*/nullptr, Alloca);
+}
+
+Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align,
+ const Twine &Name) {
+ return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name);
+}
+
+Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty,
+ const Twine &Name) {
+ return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty),
+ Name);
}
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
@@ -187,7 +208,7 @@ RValue CodeGenFunction::EmitAnyExpr(const Expr *E,
llvm_unreachable("bad evaluation kind");
}
-/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
+/// EmitAnyExprToTemp - Similar to EmitAnyExpr(), however, the result will
/// always be accessible even if no aggregate location is provided.
RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
AggValueSlot AggSlot = AggValueSlot::ignored();
@@ -214,7 +235,8 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals,
AggValueSlot::IsDestructed_t(IsInit),
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsAliased_t(!IsInit)));
+ AggValueSlot::IsAliased_t(!IsInit),
+ AggValueSlot::MayOverlap));
return;
}
@@ -347,7 +369,8 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
static Address createReferenceTemporary(CodeGenFunction &CGF,
const MaterializeTemporaryExpr *M,
- const Expr *Inner) {
+ const Expr *Inner,
+ Address *Alloca = nullptr) {
auto &TCG = CGF.getTargetHooks();
switch (M->getStorageDuration()) {
case SD_FullExpression:
@@ -380,7 +403,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
return Address(C, alignment);
}
}
- return CGF.CreateMemTemp(Ty, "ref.tmp");
+ return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca);
}
case SD_Thread:
case SD_Static:
@@ -432,7 +455,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
E->getType().getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
break;
}
}
@@ -456,7 +480,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
}
// Create and initialize the reference temporary.
- Address Object = createReferenceTemporary(*this, M, E);
+ Address Alloca = Address::invalid();
+ Address Object = createReferenceTemporary(*this, M, E, &Alloca);
if (auto *Var = dyn_cast<llvm::GlobalVariable>(
Object.getPointer()->stripPointerCasts())) {
Object = Address(llvm::ConstantExpr::getBitCast(
@@ -475,13 +500,13 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
case SD_Automatic:
case SD_FullExpression:
if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Object.getElementType()),
- Object.getPointer())) {
+ CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
+ Alloca.getPointer())) {
if (M->getStorageDuration() == SD_Automatic)
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Object, Size);
+ Alloca, Size);
else
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Object,
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
Size);
}
break;
@@ -873,7 +898,7 @@ static llvm::Value *getArrayIndexingBound(
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
return CGF.Builder.getInt(CAT->getSize());
else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
- return CGF.getVLASize(VAT).first;
+ return CGF.getVLASize(VAT).NumElts;
// Ignore pass_object_size here. It's not applicable on decayed pointers.
}
}
@@ -1789,20 +1814,20 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
return RValue::get(Vec);
}
-/// @brief Generates lvalue for partial ext_vector access.
+/// Generates lvalue for partial ext_vector access.
Address CodeGenFunction::EmitExtVectorElementLValue(LValue LV) {
Address VectorAddress = LV.getExtVectorAddress();
const VectorType *ExprVT = LV.getType()->getAs<VectorType>();
QualType EQT = ExprVT->getElementType();
llvm::Type *VectorElementTy = CGM.getTypes().ConvertType(EQT);
-
+
Address CastToPointerElement =
Builder.CreateElementBitCast(VectorAddress, VectorElementTy,
"conv.ptr.element");
-
+
const llvm::Constant *Elts = LV.getExtVectorElts();
unsigned ix = getAccessedFieldNo(0, Elts);
-
+
Address VectorBasePtrPlusIx =
Builder.CreateConstInBoundsGEP(CastToPointerElement, ix,
getContext().getTypeSizeInChars(EQT),
@@ -1811,7 +1836,7 @@ Address CodeGenFunction::EmitExtVectorElementLValue(LValue LV) {
return VectorBasePtrPlusIx;
}
-/// @brief Load of global gamed gegisters are always calls to intrinsics.
+/// Load of global gamed gegisters are always calls to intrinsics.
RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) {
assert((LV.getType()->isIntegerType() || LV.getType()->isPointerType()) &&
"Bad type for register variable");
@@ -2071,7 +2096,7 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
Dst.isVolatileQualified());
}
-/// @brief Store of global named registers are always calls to intrinsics.
+/// Store of global named registers are always calls to intrinsics.
void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) {
assert((Dst.getType()->isIntegerType() || Dst.getType()->isPointerType()) &&
"Bad type for register variable");
@@ -2210,6 +2235,22 @@ static LValue EmitThreadPrivateVarDeclLValue(
return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
}
+static Address emitDeclTargetLinkVarDeclLValue(CodeGenFunction &CGF,
+ const VarDecl *VD, QualType T) {
+ for (const auto *D : VD->redecls()) {
+ if (!VD->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ if (Attr->getMapType() == OMPDeclareTargetDeclAttr::MT_Link) {
+ QualType PtrTy = CGF.getContext().getPointerType(VD->getType());
+ Address Addr =
+ CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
+ return CGF.EmitLoadOfPointer(Addr, PtrTy->castAs<PointerType>());
+ }
+ }
+ return Address::invalid();
+}
+
Address
CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
LValueBaseInfo *PointeeBaseInfo,
@@ -2259,6 +2300,13 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
CGF.CGM.getCXXABI().usesThreadWrapperFunction())
return CGF.CGM.getCXXABI().EmitThreadLocalVarDeclLValue(CGF, VD, T);
+ // Check if the variable is marked as declare target with link clause in
+ // device codegen.
+ if (CGF.getLangOpts().OpenMPIsDevice) {
+ Address Addr = emitDeclTargetLinkVarDeclLValue(CGF, VD, T);
+ if (Addr.isValid())
+ return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
+ }
llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
@@ -2586,7 +2634,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
StringRef NameItems[] = {
PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
- if (auto *BD = dyn_cast<BlockDecl>(CurCodeDecl)) {
+ if (auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl)) {
std::string Name = SL->getString();
if (!Name.empty()) {
unsigned Discriminator =
@@ -2685,7 +2733,7 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) {
return Builder.CreatePtrToInt(V, TargetTy);
}
-/// \brief Emit a representation of a SourceLocation for passing to a handler
+/// Emit a representation of a SourceLocation for passing to a handler
/// in a sanitizer runtime library. The format for this data is:
/// \code
/// struct SourceLocation {
@@ -2744,7 +2792,7 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
}
namespace {
-/// \brief Specify under what conditions this check can be recovered
+/// Specify under what conditions this check can be recovered
enum class CheckRecoverableKind {
/// Always terminate program execution if this check fails.
Unrecoverable,
@@ -2952,6 +3000,7 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
bool WithDiag = !CGM.getCodeGenOpts().SanitizeTrap.has(Kind);
llvm::CallInst *CheckCall;
+ llvm::Constant *SlowPathFn;
if (WithDiag) {
llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
auto *InfoPtr =
@@ -2960,20 +3009,20 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
- llvm::Constant *SlowPathDiagFn = CGM.getModule().getOrInsertFunction(
+ SlowPathFn = CGM.getModule().getOrInsertFunction(
"__cfi_slowpath_diag",
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy},
false));
CheckCall = Builder.CreateCall(
- SlowPathDiagFn,
- {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)});
+ SlowPathFn, {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)});
} else {
- llvm::Constant *SlowPathFn = CGM.getModule().getOrInsertFunction(
+ SlowPathFn = CGM.getModule().getOrInsertFunction(
"__cfi_slowpath",
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy}, false));
CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr});
}
+ CGM.setDSOLocal(cast<llvm::GlobalValue>(SlowPathFn->stripPointerCasts()));
CheckCall->setDoesNotThrow();
EmitBlock(Cont);
@@ -2987,6 +3036,7 @@ void CodeGenFunction::EmitCfiCheckStub() {
llvm::Function *F = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false),
llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M);
+ CGM.setDSOLocal(F);
llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F);
// FIXME: consider emitting an intrinsic call like
// call void @llvm.cfi_check(i64 %0, i8* %1, i8* %2)
@@ -3025,6 +3075,11 @@ void CodeGenFunction::EmitCfiCheckFail() {
StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args,
SourceLocation());
+ // This function should not be affected by blacklist. This function does
+ // not have a source location, but "src:*" would still apply. Revert any
+ // changes to SanOpts made in StartFunction.
+ SanOpts = CGM.getLangOpts().Sanitize;
+
llvm::Value *Data =
EmitLoadOfScalar(GetAddrOfLocalVar(&ArgData), /*Volatile=*/false,
CGM.getContext().VoidPtrTy, ArgData.getLocation());
@@ -3227,7 +3282,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
for (auto idx : indices.drop_back())
assert(isa<llvm::ConstantInt>(idx) &&
cast<llvm::ConstantInt>(idx)->isZero());
-#endif
+#endif
// Determine the element size of the statically-sized base. This is
// the thing that the indices are expressed in terms of.
@@ -3313,7 +3368,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// The element count here is the total number of non-VLA elements.
- llvm::Value *numElements = getVLASize(vla).first;
+ llvm::Value *numElements = getVLASize(vla).NumElts;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
@@ -3547,7 +3602,7 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
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;
+ llvm::Value *NumElements = getVLASize(VLA).NumElts;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
@@ -3709,7 +3764,7 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) {
static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
const FieldDecl *field) {
const RecordDecl *rec = field->getParent();
-
+
unsigned idx =
CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
@@ -3815,6 +3870,18 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
}
Address addr = base.getAddress();
+ if (auto *ClassDef = dyn_cast<CXXRecordDecl>(rec)) {
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ ClassDef->isDynamicClass()) {
+ // Getting to any field of dynamic object requires stripping dynamic
+ // information provided by invariant.group. This is because accessing
+ // fields may leak the real address of dynamic object, which could result
+ // in miscompilation when leaked pointer would be compared.
+ auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer());
+ addr = Address(stripped, addr.getAlignment());
+ }
+ }
+
unsigned RecordCVR = base.getVRQualifiers();
if (rec->isUnion()) {
// For unions, there is no pointer adjustment.
@@ -3823,7 +3890,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
hasAnyVptr(FieldType, getContext()))
// Because unions can easily skip invariant.barriers, we need to add
// a barrier every time CXXRecord field with vptr is referenced.
- addr = Address(Builder.CreateInvariantGroupBarrier(addr.getPointer()),
+ addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()),
addr.getAlignment());
} else {
// For structs, we GEP to the field that the record layout suggests.
@@ -4167,7 +4234,35 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
assert(OpaqueValueMappingData::shouldBindAsLValue(e));
- return getOpaqueLValueMapping(e);
+ return getOrCreateOpaqueLValueMapping(e);
+}
+
+LValue
+CodeGenFunction::getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e) {
+ assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
+
+ if (it != OpaqueLValues.end())
+ return it->second;
+
+ assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
+ return EmitLValue(e->getSourceExpr());
+}
+
+RValue
+CodeGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) {
+ assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+ it = OpaqueRValues.find(e);
+
+ if (it != OpaqueRValues.end())
+ return it->second;
+
+ assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
+ return EmitAnyExpr(e->getSourceExpr());
}
RValue CodeGenFunction::EmitRValueForField(LValue LV,
@@ -4483,8 +4578,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
CalleeType = getContext().getCanonicalType(CalleeType);
- const auto *FnType =
- cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
+ auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType();
CGCallee Callee = OrigCallee;
@@ -4493,8 +4587,12 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
if (llvm::Constant *PrefixSig =
CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
SanitizerScope SanScope(this);
+ // Remove any (C++17) exception specifications, to allow calling e.g. a
+ // noexcept function through a non-noexcept pointer.
+ auto ProtoTy =
+ getContext().getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
llvm::Constant *FTRTTIConst =
- CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true);
+ CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty};
llvm::StructType *PrefixStructTy = llvm::StructType::get(
CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
@@ -4534,6 +4632,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
}
}
+ const auto *FnType = cast<FunctionType>(PointeeType);
+
// If we are checking indirect calls and this call is indirect, check that the
// function pointer is a member of the bit set for the function type.
if (SanOpts.has(SanitizerKind::CFIICall) &&
@@ -4714,6 +4814,12 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
// If this semantic expression is an opaque value, bind it
// to the result of its source expression.
if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
+ // Skip unique OVEs.
+ if (ov->isUnique()) {
+ assert(ov != resultExpr &&
+ "A unique OVE cannot be used as the result expression");
+ continue;
+ }
// If this is the result expression, we may need to evaluate
// directly into the slot.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
index 0f05cab66d7e..62641102861c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
@@ -22,6 +24,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
using namespace clang;
using namespace CodeGen;
@@ -36,23 +39,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
AggValueSlot Dest;
bool IsResultUnused;
- /// We want to use 'dest' as the return slot except under two
- /// conditions:
- /// - The destination slot requires garbage collection, so we
- /// need to use the GC API.
- /// - The destination slot is potentially aliased.
- bool shouldUseDestForReturnSlot() const {
- return !(Dest.requiresGCollection() || Dest.isPotentiallyAliased());
- }
-
- ReturnValueSlot getReturnValueSlot() const {
- if (!shouldUseDestForReturnSlot())
- return ReturnValueSlot();
-
- return ReturnValueSlot(Dest.getAddress(), Dest.isVolatile(),
- IsResultUnused);
- }
-
AggValueSlot EnsureSlot(QualType T) {
if (!Dest.isIgnored()) return Dest;
return CGF.CreateAggTemp(T, "agg.tmp.ensured");
@@ -62,6 +48,15 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
Dest = CGF.CreateAggTemp(T, "agg.tmp.ensured");
}
+ // Calls `Fn` with a valid return value slot, potentially creating a temporary
+ // to do so. If a temporary is created, an appropriate copy into `Dest` will
+ // be emitted, as will lifetime markers.
+ //
+ // The given function should take a ReturnValueSlot, and return an RValue that
+ // points to said slot.
+ void withReturnValueSlot(const Expr *E,
+ llvm::function_ref<RValue(ReturnValueSlot)> Fn);
+
public:
AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused)
: CGF(cgf), Builder(CGF.Builder), Dest(Dest),
@@ -76,8 +71,15 @@ public:
/// then loads the result into DestPtr.
void EmitAggLoadOfLValue(const Expr *E);
+ enum ExprValueKind {
+ EVK_RValue,
+ EVK_NonRValue
+ };
+
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
- void EmitFinalDestCopy(QualType type, const LValue &src);
+ /// SrcIsRValue is true if source comes from an RValue.
+ void EmitFinalDestCopy(QualType type, const LValue &src,
+ ExprValueKind SrcValueKind = EVK_NonRValue);
void EmitFinalDestCopy(QualType type, RValue src);
void EmitCopy(QualType type, const AggValueSlot &dest,
const AggValueSlot &src);
@@ -85,7 +87,7 @@ public:
void EmitMoveFromReturnSlot(const Expr *E, RValue Src);
void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
- QualType elementType, InitListExpr *E);
+ QualType ArrayQTy, InitListExpr *E);
AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) {
if (CGF.getLangOpts().getGC() && TypeRequiresGCollection(T))
@@ -144,6 +146,7 @@ public:
void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
void VisitBinAssign(const BinaryOperator *E);
void VisitBinComma(const BinaryOperator *E);
+ void VisitBinCmp(const BinaryOperator *E);
void VisitObjCMessageExpr(ObjCMessageExpr *E);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -217,7 +220,7 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {
EmitFinalDestCopy(E->getType(), LV);
}
-/// \brief True if the given aggregate type requires special GC API calls.
+/// True if the given aggregate type requires special GC API calls.
bool AggExprEmitter::TypeRequiresGCollection(QualType T) {
// Only record types have members that might require garbage collection.
const RecordType *RecordTy = T->getAs<RecordType>();
@@ -234,38 +237,78 @@ bool AggExprEmitter::TypeRequiresGCollection(QualType T) {
return Record->hasObjectMember();
}
-/// \brief Perform the final move to DestPtr if for some reason
-/// getReturnValueSlot() didn't use it directly.
-///
-/// The idea is that you do something like this:
-/// RValue Result = EmitSomething(..., getReturnValueSlot());
-/// EmitMoveFromReturnSlot(E, Result);
-///
-/// If nothing interferes, this will cause the result to be emitted
-/// directly into the return value slot. Otherwise, a final move
-/// will be performed.
-void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue src) {
- if (shouldUseDestForReturnSlot()) {
- // Logically, Dest.getAddr() should equal Src.getAggregateAddr().
- // The possibility of undef rvalues complicates that a lot,
- // though, so we can't really assert.
- return;
+void AggExprEmitter::withReturnValueSlot(
+ const Expr *E, llvm::function_ref<RValue(ReturnValueSlot)> EmitCall) {
+ QualType RetTy = E->getType();
+ bool RequiresDestruction =
+ Dest.isIgnored() &&
+ RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct;
+
+ // If it makes no observable difference, save a memcpy + temporary.
+ //
+ // We need to always provide our own temporary if destruction is required.
+ // Otherwise, EmitCall will emit its own, notice that it's "unused", and end
+ // its lifetime before we have the chance to emit a proper destructor call.
+ bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() ||
+ (RequiresDestruction && !Dest.getAddress().isValid());
+
+ Address RetAddr = Address::invalid();
+ Address RetAllocaAddr = Address::invalid();
+
+ EHScopeStack::stable_iterator LifetimeEndBlock;
+ llvm::Value *LifetimeSizePtr = nullptr;
+ llvm::IntrinsicInst *LifetimeStartInst = nullptr;
+ if (!UseTemp) {
+ RetAddr = Dest.getAddress();
+ } else {
+ RetAddr = CGF.CreateMemTemp(RetTy, "tmp", &RetAllocaAddr);
+ uint64_t Size =
+ CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
+ LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAllocaAddr.getPointer());
+ if (LifetimeSizePtr) {
+ LifetimeStartInst =
+ cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
+ assert(LifetimeStartInst->getIntrinsicID() ==
+ llvm::Intrinsic::lifetime_start &&
+ "Last insertion wasn't a lifetime.start?");
+
+ CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
+ NormalEHLifetimeMarker, RetAllocaAddr, LifetimeSizePtr);
+ LifetimeEndBlock = CGF.EHStack.stable_begin();
+ }
}
- // Otherwise, copy from there to the destination.
- assert(Dest.getPointer() != src.getAggregatePointer());
- EmitFinalDestCopy(E->getType(), src);
+ RValue Src =
+ EmitCall(ReturnValueSlot(RetAddr, Dest.isVolatile(), IsResultUnused));
+
+ if (RequiresDestruction)
+ CGF.pushDestroy(RetTy.isDestructedType(), Src.getAggregateAddress(), RetTy);
+
+ if (!UseTemp)
+ return;
+
+ assert(Dest.getPointer() != Src.getAggregatePointer());
+ EmitFinalDestCopy(E->getType(), Src);
+
+ if (!RequiresDestruction && LifetimeStartInst) {
+ // If there's no dtor to run, the copy was the last use of our temporary.
+ // Since we're not guaranteed to be in an ExprWithCleanups, clean up
+ // eagerly.
+ CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
+ CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAllocaAddr.getPointer());
+ }
}
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
void AggExprEmitter::EmitFinalDestCopy(QualType type, RValue src) {
assert(src.isAggregate() && "value must be aggregate value!");
LValue srcLV = CGF.MakeAddrLValue(src.getAggregateAddress(), type);
- EmitFinalDestCopy(type, srcLV);
+ EmitFinalDestCopy(type, srcLV, EVK_RValue);
}
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
-void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src) {
+void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src,
+ ExprValueKind SrcValueKind) {
// If Dest is ignored, then we're evaluating an aggregate expression
// in a context that doesn't care about the result. Note that loads
// from volatile l-values force the existence of a non-ignored
@@ -273,9 +316,32 @@ void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src) {
if (Dest.isIgnored())
return;
+ // Copy non-trivial C structs here.
+ LValue DstLV = CGF.MakeAddrLValue(
+ Dest.getAddress(), Dest.isVolatile() ? type.withVolatile() : type);
+
+ if (SrcValueKind == EVK_RValue) {
+ if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
+ if (Dest.isPotentiallyAliased())
+ CGF.callCStructMoveAssignmentOperator(DstLV, src);
+ else
+ CGF.callCStructMoveConstructor(DstLV, src);
+ return;
+ }
+ } else {
+ if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
+ if (Dest.isPotentiallyAliased())
+ CGF.callCStructCopyAssignmentOperator(DstLV, src);
+ else
+ CGF.callCStructCopyConstructor(DstLV, src);
+ return;
+ }
+ }
+
AggValueSlot srcAgg =
AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,
- needsGC(type), AggValueSlot::IsAliased);
+ needsGC(type), AggValueSlot::IsAliased,
+ AggValueSlot::MayOverlap);
EmitCopy(type, Dest, srcAgg);
}
@@ -286,7 +352,7 @@ void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src) {
void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
const AggValueSlot &src) {
if (dest.requiresGCollection()) {
- CharUnits sz = CGF.getContext().getTypeSizeInChars(type);
+ CharUnits sz = dest.getPreferredSize(CGF.getContext(), type);
llvm::Value *size = llvm::ConstantInt::get(CGF.SizeTy, sz.getQuantity());
CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF,
dest.getAddress(),
@@ -298,11 +364,13 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
// If the result of the assignment is used, copy the LHS there also.
// It's volatile if either side is. Use the minimum alignment of
// the two sides.
- CGF.EmitAggregateCopy(dest.getAddress(), src.getAddress(), type,
+ LValue DestLV = CGF.MakeAddrLValue(dest.getAddress(), type);
+ LValue SrcLV = CGF.MakeAddrLValue(src.getAddress(), type);
+ CGF.EmitAggregateCopy(DestLV, SrcLV, type, dest.mayOverlap(),
dest.isVolatile() || src.isVolatile());
}
-/// \brief Emit the initializer for a std::initializer_list initialized with a
+/// Emit the initializer for a std::initializer_list initialized with a
/// real initializer list.
void
AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
@@ -367,7 +435,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
}
}
-/// \brief Determine if E is a trivial array filler, that is, one that is
+/// Determine if E is a trivial array filler, that is, one that is
/// equivalent to zero-initialization.
static bool isTrivialFiller(Expr *E) {
if (!E)
@@ -390,14 +458,17 @@ static bool isTrivialFiller(Expr *E) {
return false;
}
-/// \brief Emit initialization of an array from an initializer list.
+/// Emit initialization of an array from an initializer list.
void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
- QualType elementType, InitListExpr *E) {
+ QualType ArrayQTy, InitListExpr *E) {
uint64_t NumInitElements = E->getNumInits();
uint64_t NumArrayElements = AType->getNumElements();
assert(NumInitElements <= NumArrayElements);
+ QualType elementType =
+ CGF.getContext().getAsArrayType(ArrayQTy)->getElementType();
+
// DestPtr is an array*. Construct an elementType* by drilling
// down a level.
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
@@ -409,6 +480,29 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
CharUnits elementAlign =
DestPtr.getAlignment().alignmentOfArrayElement(elementSize);
+ // Consider initializing the array by copying from a global. For this to be
+ // more efficient than per-element initialization, the size of the elements
+ // with explicit initializers should be large enough.
+ if (NumInitElements * elementSize.getQuantity() > 16 &&
+ elementType.isTriviallyCopyableType(CGF.getContext())) {
+ CodeGen::CodeGenModule &CGM = CGF.CGM;
+ ConstantEmitter Emitter(CGM);
+ LangAS AS = ArrayQTy.getAddressSpace();
+ if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) {
+ auto GV = new llvm::GlobalVariable(
+ CGM.getModule(), C->getType(),
+ CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true),
+ llvm::GlobalValue::PrivateLinkage, C, "constinit",
+ /* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(AS));
+ Emitter.finalize(GV);
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(ArrayQTy);
+ GV->setAlignment(Align.getQuantity());
+ EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GV, ArrayQTy, Align));
+ return;
+ }
+ }
+
// Exception safety requires us to destroy all the
// already-constructed members if an initializer throws.
// For that, we'll need an EH cleanup.
@@ -540,7 +634,11 @@ void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){
}
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
- EmitFinalDestCopy(e->getType(), CGF.getOpaqueLValueMapping(e));
+ // If this is a unique OVE, just visit its source expression.
+ if (e->isUnique())
+ Visit(e->getSourceExpr());
+ else
+ EmitFinalDestCopy(e->getType(), CGF.getOrCreateOpaqueLValueMapping(e));
}
void
@@ -552,7 +650,7 @@ AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
EmitAggLoadOfLValue(E);
return;
}
-
+
AggValueSlot Slot = EnsureSlot(E->getType());
CGF.EmitAggExpr(E->getInitializer(), Slot);
}
@@ -586,12 +684,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E));
else
CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast");
-
+
if (!Dest.isIgnored())
CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination");
break;
}
-
+
case CK_ToUnion: {
// Evaluate even if the destination is ignored.
if (Dest.isIgnored()) {
@@ -651,7 +749,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
if (isToAtomic) {
AggValueSlot valueDest = Dest;
if (!valueDest.isIgnored() && CGF.CGM.isPaddedAtomicType(atomicType)) {
- // Zero-initialize. (Strictly speaking, we only need to intialize
+ // Zero-initialize. (Strictly speaking, we only need to initialize
// the padding at the end, but this is simpler.)
if (!Dest.isZeroed())
CGF.EmitNullInitialization(Dest.getAddress(), atomicType);
@@ -665,9 +763,10 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
valueDest.isExternallyDestructed(),
valueDest.requiresGCollection(),
valueDest.isPotentiallyAliased(),
+ AggValueSlot::DoesNotOverlap,
AggValueSlot::IsZeroed);
}
-
+
CGF.EmitAggExpr(E->getSubExpr(), valueDest);
return;
}
@@ -702,7 +801,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
"Implicit cast types must be compatible");
Visit(E->getSubExpr());
break;
-
+
case CK_LValueBitCast:
llvm_unreachable("should not be emitting lvalue bitcast as rvalue");
@@ -762,13 +861,15 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) {
return;
}
- RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot());
- EmitMoveFromReturnSlot(E, RV);
+ withReturnValueSlot(E, [&](ReturnValueSlot Slot) {
+ return CGF.EmitCallExpr(E, Slot);
+ });
}
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
- RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot());
- EmitMoveFromReturnSlot(E, RV);
+ withReturnValueSlot(E, [&](ReturnValueSlot Slot) {
+ return CGF.EmitObjCMessageExpr(E, Slot);
+ });
}
void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
@@ -781,6 +882,150 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CGF.EmitCompoundStmt(*E->getSubStmt(), true, Dest);
}
+enum CompareKind {
+ CK_Less,
+ CK_Greater,
+ CK_Equal,
+};
+
+static llvm::Value *EmitCompare(CGBuilderTy &Builder, CodeGenFunction &CGF,
+ const BinaryOperator *E, llvm::Value *LHS,
+ llvm::Value *RHS, CompareKind Kind,
+ const char *NameSuffix = "") {
+ QualType ArgTy = E->getLHS()->getType();
+ if (const ComplexType *CT = ArgTy->getAs<ComplexType>())
+ ArgTy = CT->getElementType();
+
+ if (const auto *MPT = ArgTy->getAs<MemberPointerType>()) {
+ assert(Kind == CK_Equal &&
+ "member pointers may only be compared for equality");
+ return CGF.CGM.getCXXABI().EmitMemberPointerComparison(
+ CGF, LHS, RHS, MPT, /*IsInequality*/ false);
+ }
+
+ // Compute the comparison instructions for the specified comparison kind.
+ struct CmpInstInfo {
+ const char *Name;
+ llvm::CmpInst::Predicate FCmp;
+ llvm::CmpInst::Predicate SCmp;
+ llvm::CmpInst::Predicate UCmp;
+ };
+ CmpInstInfo InstInfo = [&]() -> CmpInstInfo {
+ using FI = llvm::FCmpInst;
+ using II = llvm::ICmpInst;
+ switch (Kind) {
+ case CK_Less:
+ return {"cmp.lt", FI::FCMP_OLT, II::ICMP_SLT, II::ICMP_ULT};
+ case CK_Greater:
+ return {"cmp.gt", FI::FCMP_OGT, II::ICMP_SGT, II::ICMP_UGT};
+ case CK_Equal:
+ return {"cmp.eq", FI::FCMP_OEQ, II::ICMP_EQ, II::ICMP_EQ};
+ }
+ llvm_unreachable("Unrecognised CompareKind enum");
+ }();
+
+ if (ArgTy->hasFloatingRepresentation())
+ return Builder.CreateFCmp(InstInfo.FCmp, LHS, RHS,
+ llvm::Twine(InstInfo.Name) + NameSuffix);
+ if (ArgTy->isIntegralOrEnumerationType() || ArgTy->isPointerType()) {
+ auto Inst =
+ ArgTy->hasSignedIntegerRepresentation() ? InstInfo.SCmp : InstInfo.UCmp;
+ return Builder.CreateICmp(Inst, LHS, RHS,
+ llvm::Twine(InstInfo.Name) + NameSuffix);
+ }
+
+ llvm_unreachable("unsupported aggregate binary expression should have "
+ "already been handled");
+}
+
+void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) {
+ using llvm::BasicBlock;
+ using llvm::PHINode;
+ using llvm::Value;
+ assert(CGF.getContext().hasSameType(E->getLHS()->getType(),
+ E->getRHS()->getType()));
+ const ComparisonCategoryInfo &CmpInfo =
+ CGF.getContext().CompCategories.getInfoForType(E->getType());
+ assert(CmpInfo.Record->isTriviallyCopyable() &&
+ "cannot copy non-trivially copyable aggregate");
+
+ QualType ArgTy = E->getLHS()->getType();
+
+ // TODO: Handle comparing these types.
+ if (ArgTy->isVectorType())
+ return CGF.ErrorUnsupported(
+ E, "aggregate three-way comparison with vector arguments");
+ if (!ArgTy->isIntegralOrEnumerationType() && !ArgTy->isRealFloatingType() &&
+ !ArgTy->isNullPtrType() && !ArgTy->isPointerType() &&
+ !ArgTy->isMemberPointerType() && !ArgTy->isAnyComplexType()) {
+ return CGF.ErrorUnsupported(E, "aggregate three-way comparison");
+ }
+ bool IsComplex = ArgTy->isAnyComplexType();
+
+ // Evaluate the operands to the expression and extract their values.
+ auto EmitOperand = [&](Expr *E) -> std::pair<Value *, Value *> {
+ RValue RV = CGF.EmitAnyExpr(E);
+ if (RV.isScalar())
+ return {RV.getScalarVal(), nullptr};
+ if (RV.isAggregate())
+ return {RV.getAggregatePointer(), nullptr};
+ assert(RV.isComplex());
+ return RV.getComplexVal();
+ };
+ auto LHSValues = EmitOperand(E->getLHS()),
+ RHSValues = EmitOperand(E->getRHS());
+
+ auto EmitCmp = [&](CompareKind K) {
+ Value *Cmp = EmitCompare(Builder, CGF, E, LHSValues.first, RHSValues.first,
+ K, IsComplex ? ".r" : "");
+ if (!IsComplex)
+ return Cmp;
+ assert(K == CompareKind::CK_Equal);
+ Value *CmpImag = EmitCompare(Builder, CGF, E, LHSValues.second,
+ RHSValues.second, K, ".i");
+ return Builder.CreateAnd(Cmp, CmpImag, "and.eq");
+ };
+ auto EmitCmpRes = [&](const ComparisonCategoryInfo::ValueInfo *VInfo) {
+ return Builder.getInt(VInfo->getIntValue());
+ };
+
+ Value *Select;
+ if (ArgTy->isNullPtrType()) {
+ Select = EmitCmpRes(CmpInfo.getEqualOrEquiv());
+ } else if (CmpInfo.isEquality()) {
+ Select = Builder.CreateSelect(
+ EmitCmp(CK_Equal), EmitCmpRes(CmpInfo.getEqualOrEquiv()),
+ EmitCmpRes(CmpInfo.getNonequalOrNonequiv()), "sel.eq");
+ } else if (!CmpInfo.isPartial()) {
+ Value *SelectOne =
+ Builder.CreateSelect(EmitCmp(CK_Less), EmitCmpRes(CmpInfo.getLess()),
+ EmitCmpRes(CmpInfo.getGreater()), "sel.lt");
+ Select = Builder.CreateSelect(EmitCmp(CK_Equal),
+ EmitCmpRes(CmpInfo.getEqualOrEquiv()),
+ SelectOne, "sel.eq");
+ } else {
+ Value *SelectEq = Builder.CreateSelect(
+ EmitCmp(CK_Equal), EmitCmpRes(CmpInfo.getEqualOrEquiv()),
+ EmitCmpRes(CmpInfo.getUnordered()), "sel.eq");
+ Value *SelectGT = Builder.CreateSelect(EmitCmp(CK_Greater),
+ EmitCmpRes(CmpInfo.getGreater()),
+ SelectEq, "sel.gt");
+ Select = Builder.CreateSelect(
+ EmitCmp(CK_Less), EmitCmpRes(CmpInfo.getLess()), SelectGT, "sel.lt");
+ }
+ // Create the return value in the destination slot.
+ EnsureDest(E->getType());
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
+
+ // Emit the address of the first (and only) field in the comparison category
+ // type, and initialize it from the constant integer value selected above.
+ LValue FieldLV = CGF.EmitLValueForFieldInitialization(
+ DestLV, *CmpInfo.Record->field_begin());
+ CGF.EmitStoreThroughLValue(RValue::get(Select), FieldLV, /*IsInit*/ true);
+
+ // All done! The result is in the Dest slot.
+}
+
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
if (E->getOpcode() == BO_PtrMemD || E->getOpcode() == BO_PtrMemI)
VisitPointerToDataMemberBinaryOperator(E);
@@ -890,11 +1135,12 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
EmitCopy(E->getLHS()->getType(),
AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
needsGC(E->getLHS()->getType()),
- AggValueSlot::IsAliased),
+ AggValueSlot::IsAliased,
+ AggValueSlot::MayOverlap),
Dest);
return;
}
-
+
LValue LHS = CGF.EmitLValue(E->getLHS());
// If we have an atomic type, evaluate into the destination and then
@@ -909,14 +1155,15 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// Codegen the RHS so that it stores directly into the LHS.
AggValueSlot LHSSlot =
- AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
+ AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
needsGC(E->getLHS()->getType()),
- AggValueSlot::IsAliased);
+ AggValueSlot::IsAliased,
+ AggValueSlot::MayOverlap);
// A non-volatile aggregate destination might have volatile member.
if (!LHSSlot.isVolatile() &&
CGF.hasVolatileMember(E->getLHS()->getType()))
LHSSlot.setVolatile(true);
-
+
CGF.EmitAggExpr(E->getRHS(), LHSSlot);
// Copy into the destination if the assignment isn't ignored.
@@ -1056,13 +1303,13 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
// '\0'
if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E))
return CL->getValue() == 0;
-
+
// Otherwise, hard case: conservatively return false.
return false;
}
-void
+void
AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
QualType type = LV.getType();
// FIXME: Ignore result?
@@ -1079,7 +1326,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
RValue RV = CGF.EmitReferenceBindingToExpr(E);
return CGF.EmitStoreThroughLValue(RV, LV);
}
-
+
switch (CGF.getEvaluationKind(type)) {
case TEK_Complex:
CGF.EmitComplexExprIntoLValue(E, LV, /*isInit*/ true);
@@ -1089,6 +1336,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased,
+ AggValueSlot::MayOverlap,
Dest.isZeroed()));
return;
case TEK_Scalar:
@@ -1109,7 +1357,7 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue lv) {
// copied into it, we don't have to emit any zeros here.
if (Dest.isZeroed() && CGF.getTypes().isZeroInitializable(type))
return;
-
+
if (CGF.hasScalarEvaluationKind(type)) {
// For non-aggregates, we can store the appropriate null constant.
llvm::Value *null = CGF.CGM.EmitNullConstant(type);
@@ -1156,11 +1404,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// Handle initialization of an array.
if (E->getType()->isArrayType()) {
- QualType elementType =
- CGF.getContext().getAsArrayType(E->getType())->getElementType();
-
auto AType = cast<llvm::ArrayType>(Dest.getAddress().getElementType());
- EmitArrayInit(Dest.getAddress(), AType, elementType, E);
+ EmitArrayInit(Dest.getAddress(), AType, E->getType(), E);
return;
}
@@ -1190,11 +1435,12 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
Address V = CGF.GetAddressOfDirectBaseInCompleteClass(
Dest.getAddress(), CXXRD, BaseRD,
/*isBaseVirtual*/ false);
- AggValueSlot AggSlot =
- AggValueSlot::forAddr(V, Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot AggSlot = AggValueSlot::forAddr(
+ V, Qualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased,
+ CGF.overlapForBaseInit(CXXRD, BaseRD, Base.isVirtual()));
CGF.EmitAggExpr(E->getInit(curInitIndex++), AggSlot);
if (QualType::DestructionKind dtorKind =
@@ -1255,12 +1501,12 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
if (curInitIndex == NumInitElements && Dest.isZeroed() &&
CGF.getTypes().isZeroInitializable(E->getType()))
break;
-
+
LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, field);
// We never generate write-barries for initialized fields.
LV.setNonGC(true);
-
+
if (curInitIndex < NumInitElements) {
// Store the initializer into the field.
EmitInitializationToLValue(E->getInit(curInitIndex++), LV);
@@ -1289,10 +1535,10 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
pushedCleanup = true;
}
}
-
+
// If the GEP didn't get used because of a dead zero init or something
// else, clean it up for -O0 builds and general tidiness.
- if (!pushedCleanup && LV.isSimple())
+ if (!pushedCleanup && LV.isSimple())
if (llvm::GetElementPtrInst *GEP =
dyn_cast<llvm::GetElementPtrInst>(LV.getPointer()))
if (GEP->use_empty())
@@ -1375,7 +1621,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
// If the subexpression is an ArrayInitLoopExpr, share its cleanup.
auto elementSlot = AggValueSlot::forLValue(
elementLV, AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased);
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap);
AggExprEmitter(CGF, elementSlot, false)
.VisitArrayInitLoopExpr(InnerLoop, outerBegin);
} else
@@ -1425,9 +1673,11 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
// If this is an initlist expr, sum up the size of sizes of the (present)
// elements. If this is something weird, assume the whole thing is non-zero.
const InitListExpr *ILE = dyn_cast<InitListExpr>(E);
+ while (ILE && ILE->isTransparent())
+ ILE = dyn_cast<InitListExpr>(ILE->getInit(0));
if (!ILE || !CGF.getTypes().isZeroInitializable(ILE->getType()))
return CGF.getContext().getTypeSizeInChars(E->getType());
-
+
// InitListExprs for structs have to be handled carefully. If there are
// reference members, we need to consider the size of the reference, not the
// referencee. InitListExprs for unions and arrays can't have references.
@@ -1435,7 +1685,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
if (!RT->isUnionType()) {
RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl();
CharUnits NumNonZeroBytes = CharUnits::Zero();
-
+
unsigned ILEElement = 0;
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(SD))
while (ILEElement != CXXRD->getNumBases())
@@ -1451,7 +1701,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
continue;
const Expr *E = ILE->getInit(ILEElement++);
-
+
// Reference values are always non-null and have the width of a pointer.
if (Field->getType()->isReferenceType())
NumNonZeroBytes += CGF.getContext().toCharUnitsFromBits(
@@ -1459,12 +1709,12 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
else
NumNonZeroBytes += GetNumNonZeroBytesInInit(E, CGF);
}
-
+
return NumNonZeroBytes;
}
}
-
-
+
+
CharUnits NumNonZeroBytes = CharUnits::Zero();
for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i)
NumNonZeroBytes += GetNumNonZeroBytesInInit(ILE->getInit(i), CGF);
@@ -1491,7 +1741,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
}
// If the type is 16-bytes or smaller, prefer individual stores over memset.
- CharUnits Size = CGF.getContext().getTypeSizeInChars(E->getType());
+ CharUnits Size = Slot.getPreferredSize(CGF.getContext(), E->getType());
if (Size <= CharUnits::fromQuantity(16))
return;
@@ -1500,14 +1750,14 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF);
if (NumNonZeroBytes*4 > Size)
return;
-
+
// Okay, it seems like a good idea to use an initial memset, emit the call.
llvm::Constant *SizeVal = CGF.Builder.getInt64(Size.getQuantity());
- Address Loc = Slot.getAddress();
+ Address Loc = Slot.getAddress();
Loc = CGF.Builder.CreateElementBitCast(Loc, CGF.Int8Ty);
CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, false);
-
+
// Tell the AggExprEmitter that the slot is known zero.
Slot.setZeroed();
}
@@ -1527,7 +1777,7 @@ void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
// Optimize the slot if possible.
CheckAggExprForMemSetUse(Slot, E, *this);
-
+
AggExprEmitter(*this, Slot, Slot.isIgnored()).Visit(const_cast<Expr*>(E));
}
@@ -1537,20 +1787,46 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
LValue LV = MakeAddrLValue(Temp, E->getType());
EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
return LV;
}
-void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
- Address SrcPtr, QualType Ty,
- bool isVolatile,
- bool isAssignment) {
+AggValueSlot::Overlap_t CodeGenFunction::overlapForBaseInit(
+ const CXXRecordDecl *RD, const CXXRecordDecl *BaseRD, bool IsVirtual) {
+ // Virtual bases are initialized first, in address order, so there's never
+ // any overlap during their initialization.
+ //
+ // FIXME: Under P0840, this is no longer true: the tail padding of a vbase
+ // of a field could be reused by a vbase of a containing class.
+ if (IsVirtual)
+ return AggValueSlot::DoesNotOverlap;
+
+ // If the base class is laid out entirely within the nvsize of the derived
+ // class, its tail padding cannot yet be initialized, so we can issue
+ // stores at the full width of the base class.
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+ if (Layout.getBaseClassOffset(BaseRD) +
+ getContext().getASTRecordLayout(BaseRD).getSize() <=
+ Layout.getNonVirtualSize())
+ return AggValueSlot::DoesNotOverlap;
+
+ // The tail padding may contain values we need to preserve.
+ return AggValueSlot::MayOverlap;
+}
+
+void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
+ AggValueSlot::Overlap_t MayOverlap,
+ bool isVolatile) {
assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
+ Address DestPtr = Dest.getAddress();
+ Address SrcPtr = Src.getAddress();
+
if (getLangOpts().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
- assert((Record->hasTrivialCopyConstructor() ||
+ assert((Record->hasTrivialCopyConstructor() ||
Record->hasTrivialCopyAssignment() ||
Record->hasTrivialMoveConstructor() ||
Record->hasTrivialMoveAssignment() ||
@@ -1562,7 +1838,7 @@ void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
return;
}
}
-
+
// Aggregate assignment turns into llvm.memcpy. This is almost valid per
// C99 6.5.16.1p3, which states "If the value being stored in an object is
// read from another object that overlaps in anyway the storage of the first
@@ -1574,12 +1850,11 @@ void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
// implementation handles this case safely. If there is a libc that does not
// safely handle this, we can add a target hook.
- // Get data size info for this aggregate. If this is an assignment,
- // don't copy the tail padding, because we might be assigning into a
- // base subobject where the tail padding is claimed. Otherwise,
- // copying it is fine.
+ // Get data size info for this aggregate. Don't copy the tail padding if this
+ // might be a potentially-overlapping subobject, since the tail padding might
+ // be occupied by a different object. Otherwise, copying it is fine.
std::pair<CharUnits, CharUnits> TypeInfo;
- if (isAssignment)
+ if (MayOverlap)
TypeInfo = getContext().getTypeInfoDataSizeInChars(Ty);
else
TypeInfo = getContext().getTypeInfoInChars(Ty);
@@ -1591,22 +1866,11 @@ void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
getContext().getAsArrayType(Ty))) {
QualType BaseEltTy;
SizeVal = emitArrayLength(VAT, BaseEltTy, DestPtr);
- TypeInfo = getContext().getTypeInfoDataSizeInChars(BaseEltTy);
- std::pair<CharUnits, CharUnits> LastElementTypeInfo;
- if (!isAssignment)
- LastElementTypeInfo = getContext().getTypeInfoInChars(BaseEltTy);
+ TypeInfo = getContext().getTypeInfoInChars(BaseEltTy);
assert(!TypeInfo.first.isZero());
SizeVal = Builder.CreateNUWMul(
SizeVal,
llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()));
- if (!isAssignment) {
- SizeVal = Builder.CreateNUWSub(
- SizeVal,
- llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()));
- SizeVal = Builder.CreateNUWAdd(
- SizeVal, llvm::ConstantInt::get(
- SizeTy, LastElementTypeInfo.first.getQuantity()));
- }
}
}
if (!SizeVal) {
@@ -1635,7 +1899,7 @@ void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
} else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
RecordDecl *Record = RecordTy->getDecl();
if (Record->hasObjectMember()) {
- CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
+ CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
return;
}
@@ -1643,7 +1907,7 @@ void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
QualType BaseType = getContext().getBaseElementType(Ty);
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
if (RecordTy->getDecl()->hasObjectMember()) {
- CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
+ CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
return;
}
@@ -1657,4 +1921,10 @@ void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
// the optimizer wishes to expand it in to scalar memory operations.
if (llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty))
Inst->setMetadata(llvm::LLVMContext::MD_tbaa_struct, TBAAStructTag);
+
+ if (CGM.getCodeGenOpts().NewStructPathTBAA) {
+ TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer(
+ Dest.getTBAAInfo(), Src.getTBAAInfo());
+ CGM.DecorateInstructionWithTBAA(Inst, TBAAInfo);
+ }
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
index c32f1e5415da..f29ef754c03f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
@@ -242,16 +242,20 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
}
}
- Address This = Address::invalid();
- if (IsArrow)
- This = EmitPointerWithAlignment(Base);
- else
- This = EmitLValue(Base).getAddress();
+ LValue This;
+ if (IsArrow) {
+ LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
+ Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo);
+ This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo);
+ } else {
+ This = EmitLValue(Base);
+ }
if (MD->isTrivial() || (MD->isDefaulted() && MD->getParent()->isUnion())) {
if (isa<CXXDestructorDecl>(MD)) return RValue::get(nullptr);
- if (isa<CXXConstructorDecl>(MD) &&
+ if (isa<CXXConstructorDecl>(MD) &&
cast<CXXConstructorDecl>(MD)->isDefaultConstructor())
return RValue::get(nullptr);
@@ -261,10 +265,10 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// when it isn't necessary; just produce the proper effect here.
LValue RHS = isa<CXXOperatorCallExpr>(CE)
? MakeNaturalAlignAddrLValue(
- (*RtlArgs)[0].RV.getScalarVal(),
+ (*RtlArgs)[0].getRValue(*this).getScalarVal(),
(*(CE->arg_begin() + 1))->getType())
: EmitLValue(*CE->arg_begin());
- EmitAggregateAssign(This, RHS.getAddress(), CE->getType());
+ EmitAggregateAssign(This, RHS, CE->getType());
return RValue::get(This.getPointer());
}
@@ -272,8 +276,13 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
cast<CXXConstructorDecl>(MD)->isCopyOrMoveConstructor()) {
// Trivial move and copy ctor are the same.
assert(CE->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
- Address RHS = EmitLValue(*CE->arg_begin()).getAddress();
- EmitAggregateCopy(This, RHS, (*CE->arg_begin())->getType());
+ const Expr *Arg = *CE->arg_begin();
+ LValue RHS = EmitLValue(Arg);
+ LValue Dest = MakeAddrLValue(This.getAddress(), Arg->getType());
+ // This is the MSVC p->Ctor::Ctor(...) extension. We assume that's
+ // constructing a new complete object of type Ctor.
+ EmitAggregateCopy(Dest, RHS, Arg->getType(),
+ AggValueSlot::DoesNotOverlap);
return RValue::get(This.getPointer());
}
llvm_unreachable("unknown trivial member function");
@@ -328,14 +337,15 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;
-
+
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
assert(CE->arg_begin() == CE->arg_end() &&
"Destructor shouldn't have explicit parameters");
assert(ReturnValue.isNull() && "Destructor shouldn't have return value");
if (UseVirtualCall) {
CGM.getCXXABI().EmitVirtualDestructorCall(
- *this, Dtor, Dtor_Complete, This, cast<CXXMemberCallExpr>(CE));
+ *this, Dtor, Dtor_Complete, This.getAddress(),
+ cast<CXXMemberCallExpr>(CE));
} else {
CGCallee Callee;
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
@@ -357,22 +367,22 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
}
return RValue::get(nullptr);
}
-
+
CGCallee Callee;
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGCallee::forDirect(
CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty),
Ctor);
} else if (UseVirtualCall) {
- Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty,
- CE->getLocStart());
+ Callee = CGCallee::forVirtual(CE, MD, This.getAddress(), Ty);
} else {
if (SanOpts.has(SanitizerKind::CFINVCall) &&
MD->getParent()->isDynamicClass()) {
llvm::Value *VTable;
const CXXRecordDecl *RD;
std::tie(VTable, RD) =
- CGM.getCXXABI().LoadVTablePtr(*this, This, MD->getParent());
+ CGM.getCXXABI().LoadVTablePtr(*this, This.getAddress(),
+ MD->getParent());
EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getLocStart());
}
@@ -388,8 +398,10 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
}
if (MD->isVirtual()) {
- This = CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall(
- *this, CalleeDecl, This, UseVirtualCall);
+ Address NewThisAddr =
+ CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall(
+ *this, CalleeDecl, This.getAddress(), UseVirtualCall);
+ This.setAddress(NewThisAddr);
}
return EmitCXXMemberOrOperatorCall(
@@ -404,20 +416,20 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
cast<BinaryOperator>(E->getCallee()->IgnoreParens());
const Expr *BaseExpr = BO->getLHS();
const Expr *MemFnExpr = BO->getRHS();
-
- const MemberPointerType *MPT =
+
+ const MemberPointerType *MPT =
MemFnExpr->getType()->castAs<MemberPointerType>();
- const FunctionProtoType *FPT =
+ const FunctionProtoType *FPT =
MPT->getPointeeType()->castAs<FunctionProtoType>();
- const CXXRecordDecl *RD =
+ const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
// Emit the 'this' pointer.
Address This = Address::invalid();
if (BO->getOpcode() == BO_PtrMemI)
This = EmitPointerWithAlignment(BaseExpr);
- else
+ else
This = EmitLValue(BaseExpr).getAddress();
EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(),
@@ -431,10 +443,10 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
CGCallee Callee =
CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This,
ThisPtrForCall, MemFnPtr, MPT);
-
+
CallArgList Args;
- QualType ThisType =
+ QualType ThisType =
getContext().getPointerType(getContext().getTagDeclType(RD));
// Push the this ptr.
@@ -558,7 +570,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
AggValueSlot Dest) {
assert(!Dest.isIgnored() && "Must have a destination!");
const CXXConstructorDecl *CD = E->getConstructor();
-
+
// If we require zero initialization before (or instead of) calling the
// constructor, as can be the case with a non-user-provided default
// constructor, emit the zero initialization now, unless destination is
@@ -576,11 +588,11 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
break;
}
}
-
+
// If this is a call to a trivial default constructor, do nothing.
if (CD->isTrivial() && CD->isDefaultConstructor())
return;
-
+
// Elide the constructor if we're constructing from a temporary.
// The temporary check is required because Sema sets this on NRVO
// returns.
@@ -592,15 +604,16 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
return;
}
}
-
+
if (const ArrayType *arrayType
= getContext().getAsArrayType(E->getType())) {
- EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E);
+ EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E,
+ Dest.isSanitizerChecked());
} else {
CXXCtorType Type = Ctor_Complete;
bool ForVirtualBase = false;
bool Delegating = false;
-
+
switch (E->getConstructionKind()) {
case CXXConstructExpr::CK_Delegating:
// We should be emitting a constructor; GlobalDecl will assert this
@@ -619,10 +632,11 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
case CXXConstructExpr::CK_NonVirtualBase:
Type = Ctor_Base;
}
-
+
// Call the constructor.
EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating,
- Dest.getAddress(), E);
+ Dest.getAddress(), E, Dest.mayOverlap(),
+ Dest.isSanitizerChecked());
}
}
@@ -630,19 +644,19 @@ void CodeGenFunction::EmitSynthesizedCXXCopyCtor(Address Dest, Address Src,
const Expr *Exp) {
if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(Exp))
Exp = E->getSubExpr();
- assert(isa<CXXConstructExpr>(Exp) &&
+ assert(isa<CXXConstructExpr>(Exp) &&
"EmitSynthesizedCXXCopyCtor - unknown copy ctor expr");
const CXXConstructExpr* E = cast<CXXConstructExpr>(Exp);
const CXXConstructorDecl *CD = E->getConstructor();
RunCleanupsScope Scope(*this);
-
+
// If we require zero initialization before (or instead of) calling the
// constructor, as can be the case with a non-user-provided default
// constructor, emit the zero initialization now.
// FIXME. Do I still need this for a copy ctor synthesis?
if (E->requiresZeroInitialization())
EmitNullInitialization(Dest, E->getType());
-
+
assert(!getContext().getAsConstantArrayType(E->getType())
&& "EmitSynthesizedCXXCopyCtor - Copied-in Array");
EmitSynthesizedCXXCopyCtorCall(CD, Dest, Src, E);
@@ -697,7 +711,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// size_t. That's just a gloss, though, and it's wrong in one
// important way: if the count is negative, it's an error even if
// the cookie size would bring the total size >= 0.
- bool isSigned
+ bool isSigned
= e->getArraySize()->getType()->isSignedIntegerOrEnumerationType();
llvm::IntegerType *numElementsType
= cast<llvm::IntegerType>(numElements->getType());
@@ -717,7 +731,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// This will be a size_t.
llvm::Value *size;
-
+
// If someone is doing 'new int[42]' there is no need to do a dynamic check.
// Don't bloat the -O0 code.
if (llvm::ConstantInt *numElementsC =
@@ -808,7 +822,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
} else if (isSigned) {
if (numElementsWidth < sizeWidth)
numElements = CGF.Builder.CreateSExt(numElements, CGF.SizeTy);
-
+
// If there's a non-1 type size multiplier, then we can do the
// signedness check at the same time as we do the multiply
// because a negative number times anything will cause an
@@ -885,7 +899,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// numElements doesn't need to be scaled.
assert(arraySizeMultiplier == 1);
}
-
+
// Add in the cookie size if necessary.
if (cookieSize != 0) {
sizeWithoutCookie = size;
@@ -924,7 +938,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
}
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
- QualType AllocType, Address NewPtr) {
+ QualType AllocType, Address NewPtr,
+ AggValueSlot::Overlap_t MayOverlap) {
// FIXME: Refactor with EmitExprAsInit.
switch (CGF.getEvaluationKind(AllocType)) {
case TEK_Scalar:
@@ -940,7 +955,9 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
= AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ MayOverlap, AggValueSlot::IsNotZeroed,
+ AggValueSlot::IsSanitizerChecked);
CGF.EmitAggExpr(Init, Slot);
return;
}
@@ -1009,7 +1026,10 @@ void CodeGenFunction::EmitNewArrayInitializer(
AggValueSlot::forAddr(CurPtr, ElementType.getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap,
+ AggValueSlot::IsNotZeroed,
+ AggValueSlot::IsSanitizerChecked);
EmitAggExpr(ILE->getInit(0), Slot);
// Move past these elements.
@@ -1074,7 +1094,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
// an array, and we have an array filler, we can fold together the two
// initialization loops.
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
- ILE->getInit(i)->getType(), CurPtr);
+ ILE->getInit(i)->getType(), CurPtr,
+ AggValueSlot::DoesNotOverlap);
CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(),
Builder.getSize(1),
"array.exp.next"),
@@ -1138,6 +1159,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
NumElements,
llvm::ConstantInt::get(NumElements->getType(), InitListElements));
EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE,
+ /*NewPointerIsChecked*/true,
CCE->requiresZeroInitialization());
return;
}
@@ -1214,7 +1236,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
CurPtr = Address(CurPtrPhi, ElementAlign);
// Store the new Cleanup position for irregular Cleanups.
- if (EndOfInit.isValid())
+ if (EndOfInit.isValid())
Builder.CreateStore(CurPtr.getPointer(), EndOfInit);
// Enter a partial-destruction Cleanup if necessary.
@@ -1227,7 +1249,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
}
// Emit the initializer into this element.
- StoreAnyExprIntoOneUnit(*this, Init, Init->getType(), CurPtr);
+ StoreAnyExprIntoOneUnit(*this, Init, Init->getType(), CurPtr,
+ AggValueSlot::DoesNotOverlap);
// Leave the Cleanup if we entered one.
if (CleanupDominator) {
@@ -1258,7 +1281,8 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
CGF.EmitNewArrayInitializer(E, ElementType, ElementTy, NewPtr, NumElements,
AllocSizeWithoutCookie);
else if (const Expr *Init = E->getInitializer())
- StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
+ StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr,
+ AggValueSlot::DoesNotOverlap);
}
/// Emit a call to an operator new or operator delete function, as implicitly
@@ -1298,19 +1322,19 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
}
RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
- const Expr *Arg,
+ const CallExpr *TheCall,
bool IsDelete) {
CallArgList Args;
- const Stmt *ArgS = Arg;
- EmitCallArgs(Args, *Type->param_type_begin(), llvm::makeArrayRef(ArgS));
+ EmitCallArgs(Args, Type->getParamTypes(), TheCall->arguments());
// Find the allocation or deallocation function that we're calling.
ASTContext &Ctx = getContext();
DeclarationName Name = Ctx.DeclarationNames
.getCXXOperatorName(IsDelete ? OO_Delete : OO_New);
+
for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name))
if (auto *FD = dyn_cast<FunctionDecl>(Decl))
if (Ctx.hasSameType(FD->getType(), QualType(Type, 0)))
- return EmitNewDeleteCall(*this, cast<FunctionDecl>(Decl), Type, Args);
+ return EmitNewDeleteCall(*this, FD, Type, Args);
llvm_unreachable("predeclared global operator new/delete is missing");
}
@@ -1481,7 +1505,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
AllocAlign);
for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
auto &Arg = NewArgs[I + NumNonPlacementArgs];
- Cleanup->setPlacementArg(I, Arg.RV, Arg.Ty);
+ Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty);
}
return;
@@ -1512,8 +1536,8 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
AllocAlign);
for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
auto &Arg = NewArgs[I + NumNonPlacementArgs];
- Cleanup->setPlacementArg(I, DominatingValue<RValue>::save(CGF, Arg.RV),
- Arg.Ty);
+ Cleanup->setPlacementArg(
+ I, DominatingValue<RValue>::save(CGF, Arg.getRValue(CGF)), Arg.Ty);
}
CGF.initFullExprCleanup();
@@ -1678,15 +1702,21 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::Type *elementTy = ConvertTypeForMem(allocType);
Address result = Builder.CreateElementBitCast(allocation, elementTy);
- // Passing pointer through invariant.group.barrier to avoid propagation of
+ // Passing pointer through launder.invariant.group to avoid propagation of
// vptrs information which may be included in previous type.
// To not break LTO with different optimizations levels, we do it regardless
// of optimization level.
if (CGM.getCodeGenOpts().StrictVTablePointers &&
allocator->isReservedGlobalPlacementOperator())
- result = Address(Builder.CreateInvariantGroupBarrier(result.getPointer()),
+ result = Address(Builder.CreateLaunderInvariantGroup(result.getPointer()),
result.getAlignment());
+ // Emit sanitizer checks for pointer value now, so that in the case of an
+ // array it was checked only once and not at each constructor call.
+ EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall,
+ E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ result.getPointer(), allocType);
+
EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
allocSizeWithoutCookie);
if (E->isArray()) {
@@ -1719,7 +1749,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
resultPtr = PHI;
}
-
+
return resultPtr;
}
@@ -1883,13 +1913,13 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
case Qualifiers::OCL_Strong:
CGF.EmitARCDestroyStrong(Ptr, ARCPreciseLifetime);
break;
-
+
case Qualifiers::OCL_Weak:
CGF.EmitARCDestroyWeak(Ptr);
break;
}
}
-
+
CGF.PopCleanupBlock();
}
@@ -2092,9 +2122,9 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E,
}
llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
- llvm::Type *StdTypeInfoPtrTy =
+ llvm::Type *StdTypeInfoPtrTy =
ConvertType(E->getType())->getPointerTo();
-
+
if (E->isTypeOperand()) {
llvm::Constant *TypeInfo =
CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand(getContext()));
@@ -2107,7 +2137,7 @@ llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
// representing the type of the most derived object (that is, the dynamic
// type) to which the glvalue refers.
if (E->isPotentiallyEvaluated())
- return EmitTypeidFromVTable(*this, E->getExprOperand(),
+ return EmitTypeidFromVTable(*this, E->getExprOperand(),
StdTypeInfoPtrTy);
QualType OperandTy = E->getExprOperand()->getType();
@@ -2169,7 +2199,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
assert(SrcRecordTy->isRecordType() && "source type must be a record type!");
- // C++ [expr.dynamic.cast]p4:
+ // C++ [expr.dynamic.cast]p4:
// If the value of v is a null pointer value in the pointer case, the result
// is the null pointer value of type T.
bool ShouldNullCheckSrcValue =
@@ -2179,7 +2209,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
llvm::BasicBlock *CastNull = nullptr;
llvm::BasicBlock *CastNotNull = nullptr;
llvm::BasicBlock *CastEnd = createBasicBlock("dynamic_cast.end");
-
+
if (ShouldNullCheckSrcValue) {
CastNull = createBasicBlock("dynamic_cast.null");
CastNotNull = createBasicBlock("dynamic_cast.notnull");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
index 9094d3f8a91c..fb176093a741 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
@@ -155,8 +155,9 @@ public:
}
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
- return CGF.getOpaqueRValueMapping(E).getComplexVal();
+ return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
+ E->getExprLoc());
+ return CGF.getOrCreateOpaqueRValueMapping(E).getComplexVal();
}
ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
@@ -594,7 +595,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
return ComplexPairTy(ResR, ResI);
}
-/// \brief Emit a libcall for a binary operation on complex types.
+/// Emit a libcall for a binary operation on complex types.
ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
const BinOpInfo &Op) {
CallArgList Args;
@@ -628,11 +629,11 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
llvm::Instruction *Call;
RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call);
- cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
+ cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getRuntimeCC());
return Res.getComplexVal();
}
-/// \brief Lookup the libcall name for a given floating point type complex
+/// Lookup the libcall name for a given floating point type complex
/// multiply.
static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) {
switch (Ty->getTypeID()) {
@@ -1055,7 +1056,7 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
return Visit(E->getInit(0));
}
- // Empty init list intializes to null
+ // Empty init list initializes to null
assert(E->getNumInits() == 0 && "Unexpected number of inits");
QualType Ty = E->getType()->castAs<ComplexType>()->getElementType();
llvm::Type* LTy = CGF.ConvertType(Ty);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
index d1b9e13a6f93..68766479a539 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
@@ -57,7 +57,7 @@ public:
private:
ConstStructBuilder(ConstantEmitter &emitter)
- : CGM(emitter.CGM), Emitter(emitter), Packed(false),
+ : CGM(emitter.CGM), Emitter(emitter), Packed(false),
NextFieldOffsetInChars(CharUnits::Zero()),
LLVMStructAlignment(CharUnits::One()) { }
@@ -244,11 +244,11 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
assert(AT->getElementType()->isIntegerTy(CharWidth) &&
AT->getNumElements() != 0 &&
"Expected non-empty array padding of undefs");
-
+
// Remove the padding array.
NextFieldOffsetInChars -= CharUnits::fromQuantity(AT->getNumElements());
Elements.pop_back();
-
+
// Add the padding back in two chunks.
AppendPadding(CharUnits::fromQuantity(AT->getNumElements()-1));
AppendPadding(CharUnits::One());
@@ -269,7 +269,7 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
if (CGM.getDataLayout().isBigEndian()) {
// We want the high bits.
- Tmp =
+ Tmp =
FieldValue.lshr(FieldValue.getBitWidth() - CharWidth).trunc(CharWidth);
} else {
// We want the low bits.
@@ -314,14 +314,14 @@ void ConstStructBuilder::AppendPadding(CharUnits PadSize) {
llvm::Constant *C = llvm::UndefValue::get(Ty);
Elements.push_back(C);
- assert(getAlignment(C) == CharUnits::One() &&
+ assert(getAlignment(C) == CharUnits::One() &&
"Padding must have 1 byte alignment!");
NextFieldOffsetInChars += getSizeInChars(C);
}
void ConstStructBuilder::AppendTailPadding(CharUnits RecordSize) {
- assert(NextFieldOffsetInChars <= RecordSize &&
+ assert(NextFieldOffsetInChars <= RecordSize &&
"Size mismatch!");
AppendPadding(RecordSize - NextFieldOffsetInChars);
@@ -364,7 +364,7 @@ void ConstStructBuilder::ConvertStructToPacked() {
LLVMStructAlignment = CharUnits::One();
Packed = true;
}
-
+
bool ConstStructBuilder::Build(InitListExpr *ILE) {
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
@@ -635,6 +635,72 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM,
return ConstantAddress(GV, Align);
}
+static llvm::Constant *
+EmitArrayConstant(CodeGenModule &CGM, const ConstantArrayType *DestType,
+ llvm::Type *CommonElementType, unsigned ArrayBound,
+ SmallVectorImpl<llvm::Constant *> &Elements,
+ llvm::Constant *Filler) {
+ // Figure out how long the initial prefix of non-zero elements is.
+ unsigned NonzeroLength = ArrayBound;
+ if (Elements.size() < NonzeroLength && Filler->isNullValue())
+ NonzeroLength = Elements.size();
+ if (NonzeroLength == Elements.size()) {
+ while (NonzeroLength > 0 && Elements[NonzeroLength - 1]->isNullValue())
+ --NonzeroLength;
+ }
+
+ if (NonzeroLength == 0) {
+ return llvm::ConstantAggregateZero::get(
+ CGM.getTypes().ConvertType(QualType(DestType, 0)));
+ }
+
+ // Add a zeroinitializer array filler if we have lots of trailing zeroes.
+ unsigned TrailingZeroes = ArrayBound - NonzeroLength;
+ if (TrailingZeroes >= 8) {
+ assert(Elements.size() >= NonzeroLength &&
+ "missing initializer for non-zero element");
+
+ // If all the elements had the same type up to the trailing zeroes, emit a
+ // struct of two arrays (the nonzero data and the zeroinitializer).
+ if (CommonElementType && NonzeroLength >= 8) {
+ llvm::Constant *Initial = llvm::ConstantArray::get(
+ llvm::ArrayType::get(CommonElementType, NonzeroLength),
+ makeArrayRef(Elements).take_front(NonzeroLength));
+ Elements.resize(2);
+ Elements[0] = Initial;
+ } else {
+ Elements.resize(NonzeroLength + 1);
+ }
+
+ auto *FillerType =
+ CommonElementType
+ ? CommonElementType
+ : CGM.getTypes().ConvertType(DestType->getElementType());
+ FillerType = llvm::ArrayType::get(FillerType, TrailingZeroes);
+ Elements.back() = llvm::ConstantAggregateZero::get(FillerType);
+ CommonElementType = nullptr;
+ } else if (Elements.size() != ArrayBound) {
+ // Otherwise pad to the right size with the filler if necessary.
+ Elements.resize(ArrayBound, Filler);
+ if (Filler->getType() != CommonElementType)
+ CommonElementType = nullptr;
+ }
+
+ // If all elements have the same type, just emit an array constant.
+ if (CommonElementType)
+ return llvm::ConstantArray::get(
+ llvm::ArrayType::get(CommonElementType, ArrayBound), Elements);
+
+ // We have mixed types. Use a packed struct.
+ llvm::SmallVector<llvm::Type *, 16> Types;
+ Types.reserve(Elements.size());
+ for (llvm::Constant *Elt : Elements)
+ Types.push_back(Elt->getType());
+ llvm::StructType *SType =
+ llvm::StructType::get(CGM.getLLVMContext(), Types, true);
+ return llvm::ConstantStruct::get(SType, Elements);
+}
+
/// 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
@@ -832,60 +898,47 @@ public:
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) {
- llvm::ArrayType *AType =
- cast<llvm::ArrayType>(ConvertType(ILE->getType()));
- llvm::Type *ElemTy = AType->getElementType();
+ auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType());
+ assert(CAT && "can't emit array init for non-constant-bound array");
unsigned NumInitElements = ILE->getNumInits();
- unsigned NumElements = AType->getNumElements();
+ unsigned NumElements = CAT->getSize().getZExtValue();
// Initialising an array requires us to automatically
// initialise any elements that have not been initialised explicitly
unsigned NumInitableElts = std::min(NumInitElements, NumElements);
- QualType EltType = CGM.getContext().getAsArrayType(T)->getElementType();
+ QualType EltType = CAT->getElementType();
// Initialize remaining array elements.
- llvm::Constant *fillC;
- if (Expr *filler = ILE->getArrayFiller())
+ llvm::Constant *fillC = nullptr;
+ if (Expr *filler = ILE->getArrayFiller()) {
fillC = Emitter.tryEmitAbstractForMemory(filler, EltType);
- else
- fillC = Emitter.emitNullForMemory(EltType);
- if (!fillC)
- return nullptr;
-
- // Try to use a ConstantAggregateZero if we can.
- if (fillC->isNullValue() && !NumInitableElts)
- return llvm::ConstantAggregateZero::get(AType);
+ if (!fillC)
+ return nullptr;
+ }
// Copy initializer elements.
SmallVector<llvm::Constant*, 16> Elts;
- Elts.reserve(NumInitableElts + NumElements);
+ if (fillC && fillC->isNullValue())
+ Elts.reserve(NumInitableElts + 1);
+ else
+ Elts.reserve(NumElements);
- bool RewriteType = false;
+ llvm::Type *CommonElementType = nullptr;
for (unsigned i = 0; i < NumInitableElts; ++i) {
Expr *Init = ILE->getInit(i);
llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType);
if (!C)
return nullptr;
- RewriteType |= (C->getType() != ElemTy);
+ if (i == 0)
+ CommonElementType = C->getType();
+ else if (C->getType() != CommonElementType)
+ CommonElementType = nullptr;
Elts.push_back(C);
}
- RewriteType |= (fillC->getType() != ElemTy);
- Elts.resize(NumElements, fillC);
-
- if (RewriteType) {
- // FIXME: Try to avoid packing the array
- std::vector<llvm::Type*> Types;
- Types.reserve(NumInitableElts + NumElements);
- for (unsigned i = 0, e = Elts.size(); i < e; ++i)
- Types.push_back(Elts[i]->getType());
- llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
- Types, true);
- return llvm::ConstantStruct::get(SType, Elts);
- }
-
- return llvm::ConstantArray::get(AType, Elts);
+ return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts,
+ fillC);
}
llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) {
@@ -919,7 +972,7 @@ public:
unsigned NumInitElements = Updater->getNumInits();
unsigned NumElements = AType->getNumElements();
-
+
std::vector<llvm::Constant *> Elts;
Elts.reserve(NumElements);
@@ -953,7 +1006,7 @@ public:
Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE, destElemType);
else
Elts[i] = Emitter.tryEmitPrivateForMemory(Init, destElemType);
-
+
if (!Elts[i])
return nullptr;
RewriteType |= (Elts[i]->getType() != ElemType);
@@ -984,17 +1037,17 @@ public:
auto C = Visit(E->getBase(), destType);
if (!C) return nullptr;
return EmitDesignatedInitUpdater(C, E->getUpdater(), destType);
- }
+ }
llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E, QualType Ty) {
if (!E->getConstructor()->isTrivial())
return nullptr;
// FIXME: We should not have to call getBaseElementType here.
- const RecordType *RT =
+ const RecordType *RT =
CGM.getContext().getBaseElementType(Ty)->getAs<RecordType>();
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-
+
// If the class doesn't have a trivial destructor, we can't emit it as a
// constant expr.
if (!RD->hasTrivialDestructor())
@@ -1429,7 +1482,7 @@ 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);
+ return (C ? emitForMemory(C, destType) : nullptr);
}
llvm::Constant *
@@ -1437,7 +1490,7 @@ ConstantEmitter::tryEmitAbstractForMemory(const APValue &value,
QualType destType) {
auto nonMemoryDestType = getNonMemoryType(CGM, destType);
auto C = tryEmitAbstract(value, nonMemoryDestType);
- return (C ? emitForMemory(C, destType) : nullptr);
+ return (C ? emitForMemory(C, destType) : nullptr);
}
llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const Expr *E,
@@ -1881,40 +1934,31 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
case APValue::Union:
return ConstStructBuilder::BuildStruct(*this, Value, DestType);
case APValue::Array: {
- const ArrayType *CAT = CGM.getContext().getAsArrayType(DestType);
+ const ConstantArrayType *CAT =
+ CGM.getContext().getAsConstantArrayType(DestType);
unsigned NumElements = Value.getArraySize();
unsigned NumInitElts = Value.getArrayInitializedElts();
// Emit array filler, if there is one.
llvm::Constant *Filler = nullptr;
- if (Value.hasArrayFiller())
+ if (Value.hasArrayFiller()) {
Filler = tryEmitAbstractForMemory(Value.getArrayFiller(),
CAT->getElementType());
-
- // Emit initializer elements.
- llvm::Type *CommonElementType =
- CGM.getTypes().ConvertType(CAT->getElementType());
-
- // Try to use a ConstantAggregateZero if we can.
- if (Filler && Filler->isNullValue() && !NumInitElts) {
- llvm::ArrayType *AType =
- llvm::ArrayType::get(CommonElementType, NumElements);
- return llvm::ConstantAggregateZero::get(AType);
+ if (!Filler)
+ return nullptr;
}
+ // Emit initializer elements.
SmallVector<llvm::Constant*, 16> Elts;
- Elts.reserve(NumElements);
- for (unsigned I = 0; I < NumElements; ++I) {
- llvm::Constant *C = Filler;
- 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 (Filler && Filler->isNullValue())
+ Elts.reserve(NumInitElts + 1);
+ else
+ Elts.reserve(NumElements);
+
+ llvm::Type *CommonElementType = nullptr;
+ for (unsigned I = 0; I < NumInitElts; ++I) {
+ llvm::Constant *C = tryEmitPrivateForMemory(
+ Value.getArrayInitializedElt(I), CAT->getElementType());
if (!C) return nullptr;
if (I == 0)
@@ -1924,20 +1968,8 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
Elts.push_back(C);
}
- if (!CommonElementType) {
- // FIXME: Try to avoid packing the array
- std::vector<llvm::Type*> Types;
- 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(CGM.getLLVMContext(), Types, true);
- return llvm::ConstantStruct::get(SType, Elts);
- }
-
- llvm::ArrayType *AType =
- llvm::ArrayType::get(CommonElementType, NumElements);
- return llvm::ConstantArray::get(AType, Elts);
+ return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts,
+ Filler);
}
case APValue::MemberPointer:
return CGM.getCXXABI().EmitMemberPointer(Value, DestType);
@@ -2032,8 +2064,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
if (record->isUnion()) {
if (Field->getIdentifier())
break;
- if (const auto *FieldRD =
- dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
+ if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
if (FieldRD->findFirstNamedDataMember())
break;
}
@@ -2042,7 +2073,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
// Fill in the virtual bases, if we're working with the complete object.
if (CXXR && asCompleteObject) {
for (const auto &I : CXXR->vbases()) {
- const CXXRecordDecl *base =
+ const CXXRecordDecl *base =
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
// Ignore empty bases.
@@ -2064,7 +2095,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
if (!elements[i])
elements[i] = llvm::Constant::getNullValue(structure->getElementType(i));
}
-
+
return llvm::ConstantStruct::get(structure, elements);
}
@@ -2094,7 +2125,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
if (getTypes().isZeroInitializable(T))
return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
-
+
if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
llvm::ArrayType *ATy =
cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
index c46215067a68..c62588c68272 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
@@ -165,7 +165,7 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
// If a unary op has a widened operand, the op cannot overflow.
if (const auto *UO = dyn_cast<UnaryOperator>(Op.E))
- return IsWidenedIntegerOp(Ctx, UO->getSubExpr());
+ return !UO->canOverflow();
// We usually don't need overflow checks for binops with widened operands.
// Multiplication with promoted unsigned operands is a special case.
@@ -299,13 +299,31 @@ public:
Value *Src, QualType SrcType, QualType DstType,
llvm::Type *DstTy, SourceLocation Loc);
+ /// Known implicit conversion check kinds.
+ /// Keep in sync with the enum of the same name in ubsan_handlers.h
+ enum ImplicitConversionCheckKind : unsigned char {
+ ICCK_IntegerTruncation = 0,
+ };
+
+ /// Emit a check that an [implicit] truncation of an integer does not
+ /// discard any bits. It is not UB, so we use the value after truncation.
+ void EmitIntegerTruncationCheck(Value *Src, QualType SrcType, Value *Dst,
+ QualType DstType, SourceLocation Loc);
+
/// Emit a conversion from the specified type to the specified destination
/// type, both of which are LLVM scalar types.
- Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
- SourceLocation Loc);
+ struct ScalarConversionOpts {
+ bool TreatBooleanAsSigned;
+ bool EmitImplicitIntegerTruncationChecks;
- Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
- SourceLocation Loc, bool TreatBooleanAsSigned);
+ ScalarConversionOpts()
+ : TreatBooleanAsSigned(false),
+ EmitImplicitIntegerTruncationChecks(false) {}
+ };
+ Value *
+ EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
+ SourceLocation Loc,
+ ScalarConversionOpts Opts = ScalarConversionOpts());
/// Emit a conversion from the specified complex type to the specified
/// destination type, where the destination type is an LLVM scalar type.
@@ -387,6 +405,9 @@ public:
Value *VisitIntegerLiteral(const IntegerLiteral *E) {
return Builder.getInt(E->getValue());
}
+ Value *VisitFixedPointLiteral(const FixedPointLiteral *E) {
+ return Builder.getInt(E->getValue());
+ }
Value *VisitFloatingLiteral(const FloatingLiteral *E) {
return llvm::ConstantFP::get(VMContext, E->getValue());
}
@@ -422,10 +443,11 @@ public:
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
+ return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
+ E->getExprLoc());
// Otherwise, assume the mapping is the scalar directly.
- return CGF.getOpaqueRValueMapping(E).getScalarVal();
+ return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
}
Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
@@ -919,18 +941,59 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
}
-/// Emit a conversion from the specified type to the specified destination type,
-/// both of which are LLVM scalar types.
-Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
- QualType DstType,
- SourceLocation Loc) {
- return EmitScalarConversion(Src, SrcType, DstType, Loc, false);
+void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
+ Value *Dst, QualType DstType,
+ SourceLocation Loc) {
+ if (!CGF.SanOpts.has(SanitizerKind::ImplicitIntegerTruncation))
+ return;
+
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = Dst->getType();
+
+ // We only care about int->int conversions here.
+ // We ignore conversions to/from pointer and/or bool.
+ if (!(SrcType->isIntegerType() && DstType->isIntegerType()))
+ return;
+
+ assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) &&
+ "clang integer type lowered to non-integer llvm type");
+
+ unsigned SrcBits = SrcTy->getScalarSizeInBits();
+ unsigned DstBits = DstTy->getScalarSizeInBits();
+ // This must be truncation. Else we do not care.
+ if (SrcBits <= DstBits)
+ return;
+
+ assert(!DstType->isBooleanType() && "we should not get here with booleans.");
+
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+
+ llvm::Value *Check = nullptr;
+
+ // 1. Extend the truncated value back to the same width as the Src.
+ bool InputSigned = DstType->isSignedIntegerOrEnumerationType();
+ Check = Builder.CreateIntCast(Dst, SrcTy, InputSigned, "anyext");
+ // 2. Equality-compare with the original source value
+ Check = Builder.CreateICmpEQ(Check, Src, "truncheck");
+ // If the comparison result is 'i1 false', then the truncation was lossy.
+
+ llvm::Constant *StaticArgs[] = {
+ CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
+ CGF.EmitCheckTypeDescriptor(DstType),
+ llvm::ConstantInt::get(Builder.getInt8Ty(), ICCK_IntegerTruncation)};
+ CGF.EmitCheck(std::make_pair(Check, SanitizerKind::ImplicitIntegerTruncation),
+ SanitizerHandler::ImplicitConversion, StaticArgs, {Src, Dst});
}
+/// Emit a conversion from the specified type to the specified destination type,
+/// both of which are LLVM scalar types.
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
QualType DstType,
SourceLocation Loc,
- bool TreatBooleanAsSigned) {
+ ScalarConversionOpts Opts) {
+ QualType NoncanonicalSrcType = SrcType;
+ QualType NoncanonicalDstType = DstType;
+
SrcType = CGF.getContext().getCanonicalType(SrcType);
DstType = CGF.getContext().getCanonicalType(DstType);
if (SrcType == DstType) return Src;
@@ -1079,7 +1142,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (isa<llvm::IntegerType>(SrcTy)) {
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
- if (SrcType->isBooleanType() && TreatBooleanAsSigned) {
+ if (SrcType->isBooleanType() && Opts.TreatBooleanAsSigned) {
InputSigned = true;
}
if (isa<llvm::IntegerType>(DstTy))
@@ -1114,6 +1177,10 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
}
}
+ if (Opts.EmitImplicitIntegerTruncationChecks)
+ EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res,
+ NoncanonicalDstType, Loc);
+
return Res;
}
@@ -1144,7 +1211,7 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
return CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(Ty), Ty);
}
-/// \brief Emit a sanitization check for the given "binary" operation (which
+/// Emit a sanitization check for the given "binary" operation (which
/// might actually be a unary increment which has been lowered to a binary
/// operation). The check passes if all values in \p Checks (which are \c i1),
/// are \c true.
@@ -1617,6 +1684,24 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
CE->getLocStart());
}
+ if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
+ const QualType SrcType = E->getType();
+
+ if (SrcType.mayBeNotDynamicClass() && DestTy.mayBeDynamicClass()) {
+ // Casting to pointer that could carry dynamic information (provided by
+ // invariant.group) requires launder.
+ Src = Builder.CreateLaunderInvariantGroup(Src);
+ } else if (SrcType.mayBeDynamicClass() && DestTy.mayBeNotDynamicClass()) {
+ // Casting to pointer that does not carry dynamic information (provided
+ // by invariant.group) requires stripping it. Note that we don't do it
+ // if the source could not be dynamic type and destination could be
+ // dynamic because dynamic information is already laundered. It is
+ // because launder(strip(src)) == launder(src), so there is no need to
+ // add extra strip before launder.
+ Src = Builder.CreateStripInvariantGroup(Src);
+ }
+ }
+
return Builder.CreateBitCast(Src, DstTy);
}
case CK_AddressSpaceConversion: {
@@ -1753,12 +1838,31 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
- return Builder.CreateIntToPtr(IntResult, DestLLVMTy);
+ auto *IntToPtr = Builder.CreateIntToPtr(IntResult, DestLLVMTy);
+
+ if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
+ // Going from integer to pointer that could be dynamic requires reloading
+ // dynamic information from invariant.group.
+ if (DestTy.mayBeDynamicClass())
+ IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr);
+ }
+ return IntToPtr;
}
- case CK_PointerToIntegral:
+ case CK_PointerToIntegral: {
assert(!DestTy->isBooleanType() && "bool should use PointerToBool");
- return Builder.CreatePtrToInt(Visit(E), ConvertType(DestTy));
+ auto *PtrExpr = Visit(E);
+
+ if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
+ const QualType SrcType = E->getType();
+
+ // Casting to integer requires stripping dynamic information as it does
+ // not carries it.
+ if (SrcType.mayBeDynamicClass())
+ PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr);
+ }
+ return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy));
+ }
case CK_ToVoid: {
CGF.EmitIgnoredExpr(E);
return nullptr;
@@ -1771,16 +1875,26 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
}
- case CK_IntegralCast:
+ case CK_IntegralCast: {
+ ScalarConversionOpts Opts;
+ if (CGF.SanOpts.has(SanitizerKind::ImplicitIntegerTruncation)) {
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE))
+ Opts.EmitImplicitIntegerTruncationChecks = !ICE->isPartOfExplicitCast();
+ }
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc(), Opts);
+ }
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
- case CK_BooleanToSignedIntegral:
+ case CK_BooleanToSignedIntegral: {
+ ScalarConversionOpts Opts;
+ Opts.TreatBooleanAsSigned = true;
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
- CE->getExprLoc(),
- /*TreatBooleanAsSigned=*/true);
+ CE->getExprLoc(), Opts);
+ }
case CK_IntegralToBoolean:
return EmitIntToBoolConversion(Visit(E));
case CK_PointerToBoolean:
@@ -1873,7 +1987,7 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
return Builder.CreateNSWAdd(InVal, Amount, Name);
// Fall through.
case LangOptions::SOB_Trapping:
- if (IsWidenedIntegerOp(CGF.getContext(), E->getSubExpr()))
+ if (!E->canOverflow())
return Builder.CreateNSWAdd(InVal, Amount, Name);
return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc));
}
@@ -1955,11 +2069,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
} else if (type->isIntegerType()) {
// Note that signed integer inc/dec with width less than int can't
// overflow because of promotion rules; we're just eliding a few steps here.
- bool CanOverflow = value->getType()->getIntegerBitWidth() >=
- CGF.IntTy->getIntegerBitWidth();
- if (CanOverflow && type->isSignedIntegerOrEnumerationType()) {
+ if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
- } else if (CanOverflow && type->isUnsignedIntegerType() &&
+ } else if (E->canOverflow() && type->isUnsignedIntegerType() &&
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
value =
EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc));
@@ -1975,7 +2087,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// VLA types don't have constant size.
if (const VariableArrayType *vla
= CGF.getContext().getAsVariableArrayType(type)) {
- llvm::Value *numElts = CGF.getVLASize(vla).first;
+ llvm::Value *numElts = CGF.getVLASize(vla).NumElts;
if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize");
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, numElts, "vla.inc");
@@ -2273,16 +2385,13 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
CGF.EmitIgnoredExpr(E->getArgumentExpr());
}
- QualType eltType;
- llvm::Value *numElts;
- std::tie(numElts, eltType) = CGF.getVLASize(VAT);
-
- llvm::Value *size = numElts;
+ auto VlaSize = CGF.getVLASize(VAT);
+ llvm::Value *size = VlaSize.NumElts;
// Scale the number of non-VLA elements by the non-VLA element size.
- CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType);
+ CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type);
if (!eltSize.isOne())
- size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), numElts);
+ size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), size);
return size;
}
@@ -2730,7 +2839,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
//
if (BinaryOperator::isNullPointerArithmeticExtension(CGF.getContext(),
op.Opcode,
- expr->getLHS(),
+ expr->getLHS(),
expr->getRHS()))
return CGF.Builder.CreateIntToPtr(index, pointer->getType());
@@ -2769,7 +2878,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
if (const VariableArrayType *vla
= CGF.getContext().getAsVariableArrayType(elementType)) {
// The element count here is the total number of non-VLA elements.
- llvm::Value *numElements = CGF.getVLASize(vla).first;
+ llvm::Value *numElements = CGF.getVLASize(vla).NumElts;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
@@ -2964,10 +3073,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
// For a variable-length array, this is going to be non-constant.
if (const VariableArrayType *vla
= CGF.getContext().getAsVariableArrayType(elementType)) {
- llvm::Value *numElements;
- std::tie(numElements, elementType) = CGF.getVLASize(vla);
-
- divisor = numElements;
+ auto VlaSize = CGF.getVLASize(vla);
+ elementType = VlaSize.Type;
+ divisor = VlaSize.NumElts;
// Scale the number of non-VLA elements by the non-VLA element size.
CharUnits eltSize = CGF.getContext().getTypeSizeInChars(elementType);
@@ -3243,6 +3351,23 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp");
} else {
// Unsigned integers and pointers.
+
+ if (CGF.CGM.getCodeGenOpts().StrictVTablePointers &&
+ !isa<llvm::ConstantPointerNull>(LHS) &&
+ !isa<llvm::ConstantPointerNull>(RHS)) {
+
+ // Dynamic information is required to be stripped for comparisons,
+ // because it could leak the dynamic information. Based on comparisons
+ // of pointers to dynamic objects, the optimizer can replace one pointer
+ // with another, which might be incorrect in presence of invariant
+ // groups. Comparison with null is safe because null does not carry any
+ // dynamic information.
+ if (LHSTy.mayBeDynamicClass())
+ LHS = Builder.CreateStripInvariantGroup(LHS);
+ if (RHSTy.mayBeDynamicClass())
+ RHS = Builder.CreateStripInvariantGroup(RHS);
+ }
+
Result = Builder.CreateICmp(UICmpOpc, LHS, RHS, "cmp");
}
@@ -3433,6 +3558,12 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
// Insert an entry into the phi node for the edge with the value of RHSCond.
PN->addIncoming(RHSCond, RHSBlock);
+ // Artificial location to preserve the scope information
+ {
+ auto NL = ApplyDebugLocation::CreateArtificial(CGF);
+ PN->setDebugLoc(Builder.getCurrentDebugLocation());
+ }
+
// ZExt result to int.
return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp
index 48156b1b26b7..b5375ffb8db7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp
@@ -83,8 +83,9 @@ CodeGenFunction::EmitNVPTXDevicePrintfCallExpr(const CallExpr *E,
/* ParamsToSkip = */ 0);
// We don't know how to emit non-scalar varargs.
- if (std::any_of(Args.begin() + 1, Args.end(),
- [](const CallArg &A) { return !A.RV.isScalar(); })) {
+ if (std::any_of(Args.begin() + 1, Args.end(), [&](const CallArg &A) {
+ return !A.getRValue(*this).isScalar();
+ })) {
CGM.ErrorUnsupported(E, "non-scalar arg to printf");
return RValue::get(llvm::ConstantInt::get(IntTy, 0));
}
@@ -97,7 +98,7 @@ CodeGenFunction::EmitNVPTXDevicePrintfCallExpr(const CallExpr *E,
} else {
llvm::SmallVector<llvm::Type *, 8> ArgTypes;
for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I)
- ArgTypes.push_back(Args[I].RV.getScalarVal()->getType());
+ ArgTypes.push_back(Args[I].getRValue(*this).getScalarVal()->getType());
// Using llvm::StructType is correct only because printf doesn't accept
// aggregates. If we had to handle aggregates here, we'd have to manually
@@ -109,7 +110,7 @@ CodeGenFunction::EmitNVPTXDevicePrintfCallExpr(const CallExpr *E,
for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I) {
llvm::Value *P = Builder.CreateStructGEP(AllocaTy, Alloca, I - 1);
- llvm::Value *Arg = Args[I].RV.getScalarVal();
+ llvm::Value *Arg = Args[I].getRValue(*this).getScalarVal();
Builder.CreateAlignedStore(Arg, P, DL.getPrefTypeAlignment(Arg->getType()));
}
BufferPtr = Builder.CreatePointerCast(Alloca, llvm::Type::getInt8PtrTy(Ctx));
@@ -117,6 +118,6 @@ CodeGenFunction::EmitNVPTXDevicePrintfCallExpr(const CallExpr *E,
// Invoke vprintf and return.
llvm::Function* VprintfFunc = GetVprintfDeclaration(CGM.getModule());
- return RValue::get(
- Builder.CreateCall(VprintfFunc, {Args[0].RV.getScalarVal(), BufferPtr}));
+ return RValue::get(Builder.CreateCall(
+ VprintfFunc, {Args[0].getRValue(*this).getScalarVal(), BufferPtr}));
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
index 28998ce8db44..21e2b8dd8c31 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -155,7 +155,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
unsigned ValueInt = 1;
// Translate opencl_unroll_hint attribute argument to
// equivalent LoopHintAttr enums.
- // OpenCL v2.0 s6.11.5:
+ // OpenCL v2.0 s6.11.5:
// 0 - full unroll (no argument).
// 1 - disable unroll.
// other positive integer n - unroll by n.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
index 15608c105dc7..9d5f23ff9a2a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
@@ -32,62 +32,62 @@ class Attr;
class ASTContext;
namespace CodeGen {
-/// \brief Attributes that may be specified on loops.
+/// Attributes that may be specified on loops.
struct LoopAttributes {
explicit LoopAttributes(bool IsParallel = false);
void clear();
- /// \brief Generate llvm.loop.parallel metadata for loads and stores.
+ /// Generate llvm.loop.parallel metadata for loads and stores.
bool IsParallel;
- /// \brief State of loop vectorization or unrolling.
+ /// State of loop vectorization or unrolling.
enum LVEnableState { Unspecified, Enable, Disable, Full };
- /// \brief Value for llvm.loop.vectorize.enable metadata.
+ /// Value for llvm.loop.vectorize.enable metadata.
LVEnableState VectorizeEnable;
- /// \brief Value for llvm.loop.unroll.* metadata (enable, disable, or full).
+ /// Value for llvm.loop.unroll.* metadata (enable, disable, or full).
LVEnableState UnrollEnable;
- /// \brief Value for llvm.loop.vectorize.width metadata.
+ /// Value for llvm.loop.vectorize.width metadata.
unsigned VectorizeWidth;
- /// \brief Value for llvm.loop.interleave.count metadata.
+ /// Value for llvm.loop.interleave.count metadata.
unsigned InterleaveCount;
- /// \brief llvm.unroll.
+ /// llvm.unroll.
unsigned UnrollCount;
- /// \brief Value for llvm.loop.distribute.enable metadata.
+ /// Value for llvm.loop.distribute.enable metadata.
LVEnableState DistributeEnable;
};
-/// \brief Information used when generating a structured loop.
+/// Information used when generating a structured loop.
class LoopInfo {
public:
- /// \brief Construct a new LoopInfo for the loop with entry Header.
+ /// Construct a new LoopInfo for the loop with entry Header.
LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs,
const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc);
- /// \brief Get the loop id metadata for this loop.
+ /// Get the loop id metadata for this loop.
llvm::MDNode *getLoopID() const { return LoopID; }
- /// \brief Get the header block of this loop.
+ /// Get the header block of this loop.
llvm::BasicBlock *getHeader() const { return Header; }
- /// \brief Get the set of attributes active for this loop.
+ /// Get the set of attributes active for this loop.
const LoopAttributes &getAttributes() const { return Attrs; }
private:
- /// \brief Loop ID metadata.
+ /// Loop ID metadata.
llvm::MDNode *LoopID;
- /// \brief Header block of this loop.
+ /// Header block of this loop.
llvm::BasicBlock *Header;
- /// \brief The attributes for this loop.
+ /// The attributes for this loop.
LoopAttributes Attrs;
};
-/// \brief A stack of loop information corresponding to loop nesting levels.
+/// A stack of loop information corresponding to loop nesting levels.
/// This stack can be used to prepare attributes which are applied when a loop
/// is emitted.
class LoopInfoStack {
@@ -97,70 +97,70 @@ class LoopInfoStack {
public:
LoopInfoStack() {}
- /// \brief Begin a new structured loop. The set of staged attributes will be
+ /// Begin a new structured loop. The set of staged attributes will be
/// applied to the loop and then cleared.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc,
const llvm::DebugLoc &EndLoc);
- /// \brief Begin a new structured loop. Stage attributes from the Attrs list.
+ /// Begin a new structured loop. Stage attributes from the Attrs list.
/// The staged attributes are applied to the loop and then cleared.
void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc,
const llvm::DebugLoc &EndLoc);
- /// \brief End the current loop.
+ /// End the current loop.
void pop();
- /// \brief Return the top loop id metadata.
+ /// Return the top loop id metadata.
llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); }
- /// \brief Return true if the top loop is parallel.
+ /// Return true if the top loop is parallel.
bool getCurLoopParallel() const {
return hasInfo() ? getInfo().getAttributes().IsParallel : false;
}
- /// \brief Function called by the CodeGenFunction when an instruction is
+ /// Function called by the CodeGenFunction when an instruction is
/// created.
void InsertHelper(llvm::Instruction *I) const;
- /// \brief Set the next pushed loop as parallel.
+ /// Set the next pushed loop as parallel.
void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; }
- /// \brief Set the next pushed loop 'vectorize.enable'
+ /// Set the next pushed loop 'vectorize.enable'
void setVectorizeEnable(bool Enable = true) {
StagedAttrs.VectorizeEnable =
Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
}
- /// \brief Set the next pushed loop as a distribution candidate.
+ /// Set the next pushed loop as a distribution candidate.
void setDistributeState(bool Enable = true) {
StagedAttrs.DistributeEnable =
Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
}
- /// \brief Set the next pushed loop unroll state.
+ /// Set the next pushed loop unroll state.
void setUnrollState(const LoopAttributes::LVEnableState &State) {
StagedAttrs.UnrollEnable = State;
}
- /// \brief Set the vectorize width for the next loop pushed.
+ /// Set the vectorize width for the next loop pushed.
void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; }
- /// \brief Set the interleave count for the next loop pushed.
+ /// Set the interleave count for the next loop pushed.
void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; }
- /// \brief Set the unroll count for the next loop pushed.
+ /// Set the unroll count for the next loop pushed.
void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; }
private:
- /// \brief Returns true if there is LoopInfo on the stack.
+ /// Returns true if there is LoopInfo on the stack.
bool hasInfo() const { return !Active.empty(); }
- /// \brief Return the LoopInfo for the current loop. HasInfo should be called
+ /// Return the LoopInfo for the current loop. HasInfo should be called
/// first to ensure LoopInfo is present.
const LoopInfo &getInfo() const { return Active.back(); }
- /// \brief The set of attributes that will be applied to the next pushed loop.
+ /// The set of attributes that will be applied to the next pushed loop.
LoopAttributes StagedAttrs;
- /// \brief Stack of active loops.
+ /// Stack of active loops.
llvm::SmallVector<LoopInfo, 4> Active;
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp
new file mode 100644
index 000000000000..922e0934b866
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -0,0 +1,885 @@
+//===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions to generate various special functions for C
+// structs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/NonTrivialTypeVisitor.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include <array>
+
+using namespace clang;
+using namespace CodeGen;
+
+// Return the size of a field in number of bits.
+static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
+ ASTContext &Ctx) {
+ if (FD && FD->isBitField())
+ return FD->getBitWidthValue(Ctx);
+ return Ctx.getTypeSize(FT);
+}
+
+namespace {
+enum { DstIdx = 0, SrcIdx = 1 };
+const char *ValNameStr[2] = {"dst", "src"};
+
+template <class Derived> struct StructVisitor {
+ StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
+
+ template <class... Ts>
+ void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
+ const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+
+ // Iterate over the fields of the struct.
+ for (const FieldDecl *FD : RD->fields()) {
+ QualType FT = FD->getType();
+ FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
+ asDerived().visit(FT, FD, CurStructOffset, Args...);
+ }
+
+ asDerived().flushTrivialFields(Args...);
+ }
+
+ template <class... Ts> void visitTrivial(Ts... Args) {}
+
+ template <class... Ts> void visitCXXDestructor(Ts... Args) {
+ llvm_unreachable("field of a C++ struct type is not expected");
+ }
+
+ template <class... Ts> void flushTrivialFields(Ts... Args) {}
+
+ uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
+ return FD ? Ctx.getASTRecordLayout(FD->getParent())
+ .getFieldOffset(FD->getFieldIndex())
+ : 0;
+ }
+
+ CharUnits getFieldOffset(const FieldDecl *FD) {
+ return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+
+ ASTContext &getContext() { return Ctx; }
+ ASTContext &Ctx;
+};
+
+template <class Derived, bool IsMove>
+struct CopyStructVisitor : StructVisitor<Derived>,
+ CopiedTypeVisitor<Derived, IsMove> {
+ using StructVisitor<Derived>::asDerived;
+ using Super = CopiedTypeVisitor<Derived, IsMove>;
+
+ CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
+
+ template <class... Ts>
+ void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffsset,
+ Ts &&... Args) {
+ if (PCK)
+ asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffsset,
+ Ts &&... Args) {
+ if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+ asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
+ CurStructOffsset, std::forward<Ts>(Args)...);
+ return;
+ }
+
+ Super::visitWithKind(PCK, FT, FD, CurStructOffsset,
+ std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
+ Ts... Args) {
+ assert(!FT.isVolatileQualified() && "volatile field not expected");
+ ASTContext &Ctx = asDerived().getContext();
+ uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
+
+ // Ignore zero-sized fields.
+ if (FieldSize == 0)
+ return;
+
+ uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
+ uint64_t FEndInBits = FStartInBits + FieldSize;
+ uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
+
+ // Set Start if this is the first field of a sequence of trivial fields.
+ if (Start == End)
+ Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
+ End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
+ }
+
+ CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
+};
+
+// This function creates the mangled name of a special function of a non-trivial
+// C struct. Since there is no ODR in C, the function is mangled based on the
+// struct contents and not the name. The mangled name has the following
+// structure:
+//
+// <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
+// <prefix> ::= "__destructor_" | "__default_constructor_" |
+// "__copy_constructor_" | "__move_constructor_" |
+// "__copy_assignment_" | "__move_assignment_"
+// <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
+// <struct-field-info> ::= <field-info>+
+// <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
+// <struct-or-scalar-field-info> ::= <struct-field-info> | <strong-field-info> |
+// <trivial-field-info>
+// <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
+// <num-elements> <innermost-element-info> "_AE"
+// <innermost-element-info> ::= <struct-or-scalar-field-info>
+// <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
+// <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
+
+template <class Derived> struct GenFuncNameBase {
+ std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
+ std::string S;
+ if (IsVolatile)
+ S = "v";
+ S += llvm::to_string(Offset.getQuantity());
+ return S;
+ }
+
+ void visitARCStrong(QualType FT, const FieldDecl *FD,
+ CharUnits CurStructOffset) {
+ appendStr("_s");
+ if (FT->isBlockPointerType())
+ appendStr("b");
+ CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
+ appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
+ }
+
+ void visitARCWeak(QualType FT, const FieldDecl *FD,
+ CharUnits CurStructOffset) {
+ appendStr("_w");
+ CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
+ appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
+ }
+
+ void visitStruct(QualType QT, const FieldDecl *FD,
+ CharUnits CurStructOffset) {
+ CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
+ asDerived().visitStructFields(QT, FieldOffset);
+ }
+
+ template <class FieldKind>
+ void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+ const FieldDecl *FD, CharUnits CurStructOffset) {
+ // String for non-volatile trivial fields is emitted when
+ // flushTrivialFields is called.
+ if (!FK)
+ return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
+
+ CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
+ ASTContext &Ctx = asDerived().getContext();
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
+ unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
+ QualType EltTy = Ctx.getBaseElementType(CAT);
+ CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
+ appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
+ llvm::to_string(EltSize.getQuantity()) + "n" +
+ llvm::to_string(NumElts));
+ EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
+ asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
+ appendStr("_AE");
+ }
+
+ void appendStr(StringRef Str) { Name += Str; }
+
+ std::string getName(QualType QT, bool IsVolatile) {
+ QT = IsVolatile ? QT.withVolatile() : QT;
+ asDerived().visitStructFields(QT, CharUnits::Zero());
+ return Name;
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+
+ std::string Name;
+};
+
+template <class Derived>
+struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
+ GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
+ : StructVisitor<Derived>(Ctx) {
+ this->appendStr(Prefix);
+ this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
+ }
+};
+
+// Helper function to create a null constant.
+static llvm::Constant *getNullForVariable(Address Addr) {
+ llvm::Type *Ty = Addr.getElementType();
+ return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
+}
+
+template <bool IsMove>
+struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
+ GenFuncNameBase<GenBinaryFuncName<IsMove>> {
+
+ GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
+ CharUnits SrcAlignment, ASTContext &Ctx)
+ : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
+ this->appendStr(Prefix);
+ this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
+ this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
+ }
+
+ void flushTrivialFields() {
+ if (this->Start == this->End)
+ return;
+
+ this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
+ llvm::to_string((this->End - this->Start).getQuantity()));
+
+ this->Start = this->End = CharUnits::Zero();
+ }
+
+ void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
+ CharUnits CurStackOffset) {
+ // Because volatile fields can be bit-fields and are individually copied,
+ // their offset and width are in bits.
+ uint64_t OffsetInBits =
+ this->Ctx.toBits(CurStackOffset) + this->getFieldOffsetInBits(FD);
+ this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
+ llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
+ }
+};
+
+struct GenDefaultInitializeFuncName
+ : GenUnaryFuncName<GenDefaultInitializeFuncName>,
+ DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
+ using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
+ GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
+ : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
+ DstAlignment, Ctx) {}
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
+ return;
+ }
+
+ Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
+ }
+};
+
+struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
+ DestructedTypeVisitor<GenDestructorFuncName> {
+ using Super = DestructedTypeVisitor<GenDestructorFuncName>;
+ GenDestructorFuncName(CharUnits DstAlignment, ASTContext &Ctx)
+ : GenUnaryFuncName<GenDestructorFuncName>("__destructor_", DstAlignment,
+ Ctx) {}
+ void visitWithKind(QualType::DestructionKind DK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
+ return;
+ }
+
+ Super::visitWithKind(DK, FT, FD, CurStructOffset);
+ }
+};
+
+// Helper function that creates CGFunctionInfo for an N-ary special function.
+template <size_t N>
+static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
+ FunctionArgList &Args) {
+ ASTContext &Ctx = CGM.getContext();
+ llvm::SmallVector<ImplicitParamDecl *, N> Params;
+ QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
+
+ for (unsigned I = 0; I < N; ++I)
+ Params.push_back(ImplicitParamDecl::Create(
+ Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
+ ImplicitParamDecl::Other));
+
+ for (auto &P : Params)
+ Args.push_back(P);
+
+ return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
+}
+
+// Template classes that are used as bases for classes that emit special
+// functions.
+template <class Derived> struct GenFuncBase {
+ template <size_t N>
+ void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, N> Addrs) {
+ this->asDerived().callSpecialFunction(
+ FT, CurStackOffset + asDerived().getFieldOffset(FD), Addrs);
+ }
+
+ template <class FieldKind, size_t N>
+ void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+ const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, N> Addrs) {
+ // Non-volatile trivial fields are copied when flushTrivialFields is called.
+ if (!FK)
+ return asDerived().visitTrivial(QualType(AT, 0), FD, CurStackOffset,
+ Addrs);
+
+ CodeGenFunction &CGF = *this->CGF;
+ ASTContext &Ctx = CGF.getContext();
+
+ // Compute the end address.
+ QualType BaseEltQT;
+ std::array<Address, N> StartAddrs = Addrs;
+ for (unsigned I = 0; I < N; ++I)
+ StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStackOffset, FD);
+ Address DstAddr = StartAddrs[DstIdx];
+ llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
+ unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
+ llvm::Value *BaseEltSizeVal =
+ llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
+ llvm::Value *SizeInBytes =
+ CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
+ Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy);
+ llvm::Value *DstArrayEnd =
+ CGF.Builder.CreateInBoundsGEP(BC.getPointer(), SizeInBytes);
+ DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy,
+ "dstarray.end");
+ llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
+
+ // Create the header block and insert the phi instructions.
+ llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
+ CGF.EmitBlock(HeaderBB);
+ llvm::PHINode *PHIs[N];
+
+ for (unsigned I = 0; I < N; ++I) {
+ PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
+ PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
+ }
+
+ // Create the exit and loop body blocks.
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
+ llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
+
+ // Emit the comparison and conditional branch instruction that jumps to
+ // either the exit or the loop body.
+ llvm::Value *Done =
+ CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
+ CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
+
+ // Visit the element of the array in the loop body.
+ CGF.EmitBlock(LoopBB);
+ QualType EltQT = AT->getElementType();
+ CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
+ std::array<Address, N> NewAddrs = Addrs;
+
+ for (unsigned I = 0; I < N; ++I)
+ NewAddrs[I] = Address(
+ PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
+
+ EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
+ this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
+ NewAddrs);
+
+ LoopBB = CGF.Builder.GetInsertBlock();
+
+ for (unsigned I = 0; I < N; ++I) {
+ // Instrs to update the destination and source addresses.
+ // Update phi instructions.
+ NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
+ PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
+ }
+
+ // Insert an unconditional branch to the header block.
+ CGF.Builder.CreateBr(HeaderBB);
+ CGF.EmitBlock(ExitBB);
+ }
+
+ /// Return an address with the specified offset from the passed address.
+ Address getAddrWithOffset(Address Addr, CharUnits Offset) {
+ assert(Addr.isValid() && "invalid address");
+ if (Offset.getQuantity() == 0)
+ return Addr;
+ Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy);
+ Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity(),
+ CharUnits::One());
+ return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy);
+ }
+
+ Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
+ const FieldDecl *FD) {
+ return getAddrWithOffset(Addr, StructFieldOffset +
+ asDerived().getFieldOffset(FD));
+ }
+
+ template <size_t N>
+ llvm::Function *
+ getFunction(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
+ std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
+ // If the special function already exists in the module, return it.
+ if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
+ bool WrongType = false;
+ if (!F->getReturnType()->isVoidTy())
+ WrongType = true;
+ else {
+ for (const llvm::Argument &Arg : F->args())
+ if (Arg.getType() != CGM.Int8PtrPtrTy)
+ WrongType = true;
+ }
+
+ if (WrongType) {
+ std::string FuncName = F->getName();
+ SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
+ CGM.Error(Loc, "special function " + FuncName +
+ " for non-trivial C struct has incorrect type");
+ return nullptr;
+ }
+ return F;
+ }
+
+ ASTContext &Ctx = CGM.getContext();
+ FunctionArgList Args;
+ const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
+ llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
+ llvm::Function *F =
+ llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
+ FuncName, &CGM.getModule());
+ F->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ CGM.SetLLVMFunctionAttributes(nullptr, FI, F);
+ CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
+ IdentifierInfo *II = &Ctx.Idents.get(FuncName);
+ FunctionDecl *FD = FunctionDecl::Create(
+ Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
+ II, Ctx.VoidTy, nullptr, SC_PrivateExtern, false, false);
+ CodeGenFunction NewCGF(CGM);
+ setCGF(&NewCGF);
+ CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args);
+
+ for (unsigned I = 0; I < N; ++I) {
+ llvm::Value *V = CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[I]));
+ Addrs[I] = Address(V, Alignments[I]);
+ }
+
+ asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
+ CGF->FinishFunction();
+ return F;
+ }
+
+ template <size_t N>
+ void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
+ CodeGenFunction &CallerCGF) {
+ std::array<CharUnits, N> Alignments;
+ llvm::Value *Ptrs[N];
+
+ for (unsigned I = 0; I < N; ++I) {
+ Alignments[I] = Addrs[I].getAlignment();
+ Ptrs[I] =
+ CallerCGF.Builder.CreateBitCast(Addrs[I], CallerCGF.CGM.Int8PtrPtrTy)
+ .getPointer();
+ }
+
+ if (llvm::Function *F =
+ getFunction(FuncName, QT, Addrs, Alignments, CallerCGF.CGM))
+ CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+
+ void setCGF(CodeGenFunction *F) { CGF = F; }
+
+ CodeGenFunction *CGF = nullptr;
+};
+
+template <class Derived, bool IsMove>
+struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
+ GenFuncBase<Derived> {
+ GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
+
+ void flushTrivialFields(std::array<Address, 2> Addrs) {
+ CharUnits Size = this->End - this->Start;
+
+ if (Size.getQuantity() == 0)
+ return;
+
+ Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
+ Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
+
+ // Emit memcpy.
+ if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
+ DstAddr =
+ this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
+ SrcAddr =
+ this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
+ this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
+ } else {
+ llvm::Type *Ty = llvm::Type::getIntNTy(
+ this->CGF->getLLVMContext(),
+ Size.getQuantity() * this->CGF->getContext().getCharWidth());
+ DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
+ SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
+ llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
+ this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
+ }
+
+ this->Start = this->End = CharUnits::Zero();
+ }
+
+ template <class... Ts>
+ void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
+ std::array<Address, 2> Addrs) {
+ LValue DstLV, SrcLV;
+ if (FD) {
+ QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
+ llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
+ Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
+ LValue DstBase = this->CGF->MakeAddrLValue(
+ this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
+ DstLV = this->CGF->EmitLValueForField(DstBase, FD);
+ Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
+ LValue SrcBase = this->CGF->MakeAddrLValue(
+ this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
+ SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
+ } else {
+ llvm::PointerType *Ty = this->CGF->ConvertType(FT)->getPointerTo();
+ Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
+ Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
+ DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
+ SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
+ }
+ RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
+ this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
+ }
+};
+
+// These classes that emit the special functions for a non-trivial struct.
+struct GenDestructor : StructVisitor<GenDestructor>,
+ GenFuncBase<GenDestructor>,
+ DestructedTypeVisitor<GenDestructor> {
+ using Super = DestructedTypeVisitor<GenDestructor>;
+ GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
+
+ void visitWithKind(QualType::DestructionKind DK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset,
+ std::array<Address, 1> Addrs) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
+ return;
+ }
+
+ Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
+ }
+
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
+ CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
+ CGF->destroyARCStrongImprecise(
+ *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
+ }
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 1> Addrs) {
+ CGF->destroyARCWeak(
+ *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
+ }
+
+ void callSpecialFunction(QualType FT, CharUnits Offset,
+ std::array<Address, 1> Addrs) {
+ CGF->callCStructDestructor(
+ CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
+ }
+};
+
+struct GenDefaultInitialize
+ : StructVisitor<GenDefaultInitialize>,
+ GenFuncBase<GenDefaultInitialize>,
+ DefaultInitializedTypeVisitor<GenDefaultInitialize> {
+ using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
+ typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
+
+ GenDefaultInitialize(ASTContext &Ctx)
+ : StructVisitor<GenDefaultInitialize>(Ctx) {}
+
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset,
+ std::array<Address, 1> Addrs) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
+ Addrs);
+ return;
+ }
+
+ Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
+ }
+
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
+ CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
+ CGF->EmitNullInitialization(
+ getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
+ }
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 1> Addrs) {
+ CGF->EmitNullInitialization(
+ getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
+ }
+
+ template <class FieldKind, size_t... Is>
+ void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+ const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 1> Addrs) {
+ if (!FK)
+ return visitTrivial(QualType(AT, 0), FD, CurStackOffset, Addrs);
+
+ ASTContext &Ctx = getContext();
+ CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
+ QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
+
+ if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
+ GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStackOffset, Addrs);
+ return;
+ }
+
+ llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
+ Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
+ CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
+ IsVolatile);
+ }
+
+ void callSpecialFunction(QualType FT, CharUnits Offset,
+ std::array<Address, 1> Addrs) {
+ CGF->callCStructDefaultConstructor(
+ CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
+ }
+};
+
+struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
+ GenCopyConstructor(ASTContext &Ctx)
+ : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
+
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
+ CharUnits CurStackOffset, std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
+ Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
+ llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
+ CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
+ }
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
+ void callSpecialFunction(QualType FT, CharUnits Offset,
+ std::array<Address, 2> Addrs) {
+ CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
+ CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
+ }
+};
+
+struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
+ GenMoveConstructor(ASTContext &Ctx)
+ : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
+
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
+ CharUnits CurStackOffset, std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
+ llvm::Value *SrcVal =
+ CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
+ CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
+ CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
+ /* isInitialization */ true);
+ }
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
+ void callSpecialFunction(QualType FT, CharUnits Offset,
+ std::array<Address, 2> Addrs) {
+ CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
+ CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
+ }
+};
+
+struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
+ GenCopyAssignment(ASTContext &Ctx)
+ : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
+
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
+ CharUnits CurStackOffset, std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
+ Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
+ CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
+ false);
+ }
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
+ void callSpecialFunction(QualType FT, CharUnits Offset,
+ std::array<Address, 2> Addrs) {
+ CGF->callCStructCopyAssignmentOperator(
+ CGF->MakeAddrLValue(Addrs[DstIdx], FT),
+ CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
+ }
+};
+
+struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
+ GenMoveAssignment(ASTContext &Ctx)
+ : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
+
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
+ CharUnits CurStackOffset, std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
+ llvm::Value *SrcVal =
+ CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
+ CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
+ LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
+ llvm::Value *DstVal =
+ CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
+ CGF->EmitStoreOfScalar(SrcVal, DstLV);
+ CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
+ }
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
+ void callSpecialFunction(QualType FT, CharUnits Offset,
+ std::array<Address, 2> Addrs) {
+ CGF->callCStructMoveAssignmentOperator(
+ CGF->MakeAddrLValue(Addrs[DstIdx], FT),
+ CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
+ }
+};
+
+} // namespace
+
+void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
+ Address Addr, QualType Type) {
+ CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
+}
+
+// Default-initialize a variable that is a non-trivial struct or an array of
+// such structure.
+void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
+ GenDefaultInitialize Gen(getContext());
+ Address DstPtr = Builder.CreateBitCast(Dst.getAddress(), CGM.Int8PtrPtrTy);
+ Gen.setCGF(this);
+ QualType QT = Dst.getType();
+ QT = Dst.isVolatile() ? QT.withVolatile() : QT;
+ Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
+}
+
+template <class G, size_t N>
+static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
+ bool IsVolatile, CodeGenFunction &CGF,
+ std::array<Address, N> Addrs) {
+ for (unsigned I = 0; I < N; ++I)
+ Addrs[I] = CGF.Builder.CreateBitCast(Addrs[I], CGF.CGM.Int8PtrPtrTy);
+ QT = IsVolatile ? QT.withVolatile() : QT;
+ Gen.callFunc(FuncName, QT, Addrs, CGF);
+}
+
+// Functions to emit calls to the special functions of a non-trivial C struct.
+void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
+ bool IsVolatile = Dst.isVolatile();
+ Address DstPtr = Dst.getAddress();
+ QualType QT = Dst.getType();
+ GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
+ std::string FuncName = GenName.getName(QT, IsVolatile);
+ callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
+ IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
+}
+
+void CodeGenFunction::callCStructDestructor(LValue Dst) {
+ bool IsVolatile = Dst.isVolatile();
+ Address DstPtr = Dst.getAddress();
+ QualType QT = Dst.getType();
+ GenDestructorFuncName GenName(DstPtr.getAlignment(), getContext());
+ std::string FuncName = GenName.getName(QT, IsVolatile);
+ callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
+ *this, std::array<Address, 1>({{DstPtr}}));
+}
+
+void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
+ bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
+ Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
+ QualType QT = Dst.getType();
+ GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
+ SrcPtr.getAlignment(), getContext());
+ std::string FuncName = GenName.getName(QT, IsVolatile);
+ callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
+ IsVolatile, *this,
+ std::array<Address, 2>({{DstPtr, SrcPtr}}));
+}
+
+void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
+
+) {
+ bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
+ Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
+ QualType QT = Dst.getType();
+ GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
+ SrcPtr.getAlignment(), getContext());
+ std::string FuncName = GenName.getName(QT, IsVolatile);
+ callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
+ *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
+}
+
+void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
+ bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
+ Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
+ QualType QT = Dst.getType();
+ GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
+ SrcPtr.getAlignment(), getContext());
+ std::string FuncName = GenName.getName(QT, IsVolatile);
+ callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
+ IsVolatile, *this,
+ std::array<Address, 2>({{DstPtr, SrcPtr}}));
+}
+
+void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
+
+) {
+ bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
+ Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
+ QualType QT = Dst.getType();
+ GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
+ SrcPtr.getAlignment(), getContext());
+ std::string FuncName = GenName.getName(QT, IsVolatile);
+ callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
+ *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
index f26263d9472d..b94bbf2a384f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
@@ -45,7 +45,7 @@ static llvm::Constant *getNullForVariable(Address addr) {
/// Emits an instance of NSConstantString representing the object.
llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
{
- llvm::Constant *C =
+ llvm::Constant *C =
CGM.getObjCRuntime().GenerateConstantString(E->getString()).getPointer();
// FIXME: This bitcast should just be made an invariant on the Runtime.
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
@@ -65,7 +65,7 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
assert(BoxingMethod && "BoxingMethod is null");
assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method");
Selector Sel = BoxingMethod->getSelector();
-
+
// Generate a reference to the class pointer, which will be the receiver.
// Assumes that the method was introduced in the class that should be
// messaged (avoids pulling it out of the result type).
@@ -76,8 +76,8 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
CallArgList Args;
const ParmVarDecl *ArgDecl = *BoxingMethod->param_begin();
QualType ArgQT = ArgDecl->getType().getUnqualifiedType();
-
- // ObjCBoxedExpr supports boxing of structs and unions
+
+ // ObjCBoxedExpr supports boxing of structs and unions
// via [NSValue valueWithBytes:objCType:]
const QualType ValueType(SubExpr->getType().getCanonicalType());
if (ValueType->isObjCBoxableRecordType()) {
@@ -92,7 +92,7 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
std::string Str;
getContext().getObjCEncodingForType(ValueType, Str);
llvm::Constant *GV = CGM.GetAddrOfConstantCString(Str).getPointer();
-
+
// Cast type encoding to correct type
const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1];
QualType EncodingQT = EncodingDecl->getType().getUnqualifiedType();
@@ -106,7 +106,7 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
RValue result = Runtime.GenerateMessageSend(
*this, ReturnValueSlot(), BoxingMethod->getReturnType(), Sel, Receiver,
Args, ClassDecl, BoxingMethod);
- return Builder.CreateBitCast(result.getScalarVal(),
+ return Builder.CreateBitCast(result.getScalarVal(),
ConvertType(E->getType()));
}
@@ -119,7 +119,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
DLE = cast<ObjCDictionaryLiteral>(E);
// Optimize empty collections by referencing constants, when available.
- uint64_t NumElements =
+ uint64_t NumElements =
ALE ? ALE->getNumElements() : DLE->getNumElements();
if (NumElements == 0 && CGM.getLangOpts().ObjCRuntime.hasEmptyCollections()) {
StringRef ConstantName = ALE ? "__NSArray0__" : "__NSDictionary0__";
@@ -138,8 +138,8 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()),
NumElements);
QualType ElementType = Context.getObjCIdType().withConst();
- QualType ElementArrayType
- = Context.getConstantArrayType(ElementType, APNumElements,
+ QualType ElementArrayType
+ = Context.getConstantArrayType(ElementType, APNumElements,
ArrayType::Normal, /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
@@ -147,7 +147,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
Address Keys = Address::invalid();
if (DLE)
Keys = CreateMemTemp(ElementArrayType, "keys");
-
+
// In ARC, we may need to do extra work to keep all the keys and
// values alive until after the call.
SmallVector<llvm::Value *, 16> NeededObjects;
@@ -169,7 +169,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
if (TrackNeededObjects) {
NeededObjects.push_back(value);
}
- } else {
+ } else {
// Emit the key and store it to the appropriate array slot.
const Expr *Key = DLE->getKeyValueElement(i).Key;
LValue KeyLV = MakeAddrLValue(
@@ -191,9 +191,9 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
}
}
}
-
+
// Generate the argument list.
- CallArgList Args;
+ CallArgList Args;
ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin();
const ParmVarDecl *argDecl = *PI++;
QualType ArgQT = argDecl->getType().getUnqualifiedType();
@@ -205,7 +205,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
}
argDecl = *PI;
ArgQT = argDecl->getType().getUnqualifiedType();
- llvm::Value *Count =
+ llvm::Value *Count =
llvm::ConstantInt::get(CGM.getTypes().ConvertType(ArgQT), NumElements);
Args.add(RValue::get(Count), ArgQT);
@@ -214,7 +214,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
QualType ResultType = E->getType();
const ObjCObjectPointerType *InterfacePointerType
= ResultType->getAsObjCInterfacePointerType();
- ObjCInterfaceDecl *Class
+ ObjCInterfaceDecl *Class
= InterfacePointerType->getObjectType()->getInterface();
CGObjCRuntime &Runtime = CGM.getObjCRuntime();
llvm::Value *Receiver = Runtime.GetClass(*this, Class);
@@ -232,7 +232,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
EmitARCIntrinsicUse(NeededObjects);
}
- return Builder.CreateBitCast(result.getScalarVal(),
+ return Builder.CreateBitCast(result.getScalarVal(),
ConvertType(E->getType()));
}
@@ -259,7 +259,7 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol());
}
-/// \brief Adjust the type of an Objective-C object that doesn't match up due
+/// Adjust the type of an Objective-C object that doesn't match up due
/// to type erasure at various points, e.g., related result types or the use
/// of parameterized classes.
static RValue AdjustObjCObjectType(CodeGenFunction &CGF, QualType ExpT,
@@ -557,7 +557,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
if (CGM.getLangOpts().ObjCAutoRefCount &&
OMD->isInstanceMethod() &&
OMD->getSelector().isUnarySelector()) {
- const IdentifierInfo *ident =
+ const IdentifierInfo *ident =
OMD->getSelector().getIdentifierInfoForSlot(0);
if (ident->isStr("dealloc"))
EHStack.pushCleanup<FinishARCDealloc>(getARCCleanupKind());
@@ -580,7 +580,7 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
/// emitStructGetterCall - Call the runtime function to load a property
/// into the return value slot.
-static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
+static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
bool isAtomic, bool hasStrong) {
ASTContext &Context = CGF.getContext();
@@ -588,7 +588,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0)
.getAddress();
- // objc_copyStruct (ReturnValue, &structIvar,
+ // objc_copyStruct (ReturnValue, &structIvar,
// sizeof (Type of Ivar), isAtomic, false);
CallArgList args;
@@ -803,7 +803,7 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM,
Kind = Native;
}
-/// \brief Generate an Objective-C property getter function.
+/// Generate an Objective-C property getter function.
///
/// The given Decl must be an ObjCImplementationDecl. \@synthesize
/// is illegal within a category.
@@ -844,30 +844,30 @@ static bool hasTrivialGetExpr(const ObjCPropertyImplDecl *propImpl) {
return false;
}
-/// emitCPPObjectAtomicGetterCall - Call the runtime function to
+/// emitCPPObjectAtomicGetterCall - Call the runtime function to
/// copy the ivar into the resturn slot.
-static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
+static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
llvm::Value *returnAddr,
ObjCIvarDecl *ivar,
llvm::Constant *AtomicHelperFn) {
// objc_copyCppObjectAtomic (&returnSlot, &CppObjectIvar,
// AtomicHelperFn);
CallArgList args;
-
+
// The 1st argument is the return Slot.
args.add(RValue::get(returnAddr), CGF.getContext().VoidPtrTy);
-
+
// The 2nd argument is the address of the ivar.
- llvm::Value *ivarAddr =
- CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
+ llvm::Value *ivarAddr =
+ CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
CGF.LoadObjCSelf(), ivar, 0).getPointer();
ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
-
+
// Third argument is the helper function.
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
-
- llvm::Constant *copyCppAtomicObjectFn =
+
+ llvm::Constant *copyCppAtomicObjectFn =
CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction();
CGCallee callee = CGCallee::forDirect(copyCppAtomicObjectFn);
CGF.EmitCall(
@@ -889,7 +889,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
}
else {
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
- emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(),
+ emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(),
ivar, AtomicHelperFn);
}
return;
@@ -899,7 +899,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
QualType propType = prop->getType();
ObjCMethodDecl *getterMethod = prop->getGetterMethodDecl();
- ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
+ ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
// Pick an implementation strategy.
PropertyImplStrategy strategy(CGM, propImpl);
@@ -1008,12 +1008,14 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
/*init*/ true);
return;
}
- case TEK_Aggregate:
+ case TEK_Aggregate: {
// The return value slot is guaranteed to not be aliased, but
// that's not necessarily the same as "on the stack", so
// we still potentially need objc_memmove_collectable.
- EmitAggregateCopy(ReturnValue, LV.getAddress(), ivarType);
+ EmitAggregateCopy(/* Dest= */ MakeAddrLValue(ReturnValue, ivarType),
+ /* Src= */ LV, ivarType, overlapForReturnValue());
return;
+ }
case TEK_Scalar: {
llvm::Value *value;
if (propType->isReferenceType()) {
@@ -1037,7 +1039,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
value = Builder.CreateBitCast(
value, ConvertType(GetterMethodDecl->getReturnType()));
}
-
+
EmitReturnOfRValue(RValue::get(value), propType);
return;
}
@@ -1053,7 +1055,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
/// from the first formal parameter into the given ivar.
static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
ObjCIvarDecl *ivar) {
- // objc_copyStruct (&structIvar, &Arg,
+ // objc_copyStruct (&structIvar, &Arg,
// sizeof (struct something), true, false);
CallArgList args;
@@ -1066,7 +1068,7 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
// The second argument is the address of the parameter variable.
ParmVarDecl *argVar = *OMD->param_begin();
- DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
+ DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
VK_LValue, SourceLocation());
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer();
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
@@ -1091,36 +1093,36 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
callee, ReturnValueSlot(), args);
}
-/// emitCPPObjectAtomicSetterCall - Call the runtime function to store
-/// the value from the first formal parameter into the given ivar, using
+/// emitCPPObjectAtomicSetterCall - Call the runtime function to store
+/// the value from the first formal parameter into the given ivar, using
/// the Cpp API for atomic Cpp objects with non-trivial copy assignment.
-static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
+static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
ObjCMethodDecl *OMD,
ObjCIvarDecl *ivar,
llvm::Constant *AtomicHelperFn) {
- // objc_copyCppObjectAtomic (&CppObjectIvar, &Arg,
+ // objc_copyCppObjectAtomic (&CppObjectIvar, &Arg,
// AtomicHelperFn);
CallArgList args;
-
+
// The first argument is the address of the ivar.
- llvm::Value *ivarAddr =
- CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
+ llvm::Value *ivarAddr =
+ CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
CGF.LoadObjCSelf(), ivar, 0).getPointer();
ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
-
+
// The second argument is the address of the parameter variable.
ParmVarDecl *argVar = *OMD->param_begin();
- DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
+ DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
VK_LValue, SourceLocation());
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer();
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
-
+
// Third argument is the helper function.
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
-
- llvm::Constant *fn =
+
+ llvm::Constant *fn =
CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction();
CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall(
@@ -1166,7 +1168,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl();
-
+
// Just use the setter expression if Sema gave us one and it's
// non-trivial.
if (!hasTrivialSetExpr(propImpl)) {
@@ -1219,7 +1221,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
llvm::Constant *setPropertyFn = nullptr;
if (UseOptimizedSetter(CGM)) {
// 10.8 and iOS 6.0 code and GC is off
- setOptimizedPropertyFn =
+ setOptimizedPropertyFn =
CGM.getObjCRuntime()
.GetOptimizedPropertySetFunction(strategy.isAtomic(),
strategy.isCopy());
@@ -1235,7 +1237,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
return;
}
}
-
+
// Emit objc_setProperty((id) self, _cmd, offset, arg,
// <is-atomic>, <is-copy>).
llvm::Value *cmd =
@@ -1270,7 +1272,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args),
callee, ReturnValueSlot(), args);
}
-
+
return;
}
@@ -1299,7 +1301,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack,
argType.getUnqualifiedType(), CK_LValueToRValue,
&arg, VK_RValue);
-
+
// The property type can differ from the ivar type in some situations with
// Objective-C pointer types, we can always bit cast the RHS in these cases.
// The following absurdity is just to ensure well-formed IR.
@@ -1334,7 +1336,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
EmitStmt(&assign);
}
-/// \brief Generate an Objective-C property setter function.
+/// Generate an Objective-C property setter function.
///
/// The given Decl must be an ObjCImplementationDecl. \@synthesize
/// is illegal within a category.
@@ -1433,12 +1435,13 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
for (const auto *IvarInit : IMP->inits()) {
FieldDecl *Field = IvarInit->getAnyMember();
ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
- LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
LoadObjCSelf(), Ivar, 0);
EmitAggExpr(IvarInit->getInit(),
AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
}
// constructor returns 'self'.
CodeGenTypes &Types = CGM.getTypes();
@@ -1814,22 +1817,6 @@ void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) {
}
-static bool IsForwarding(StringRef Name) {
- return llvm::StringSwitch<bool>(Name)
- .Cases("objc_autoreleaseReturnValue", // ARCInstKind::AutoreleaseRV
- "objc_autorelease", // ARCInstKind::Autorelease
- "objc_retainAutoreleaseReturnValue", // ARCInstKind::FusedRetainAutoreleaseRV
- "objc_retainAutoreleasedReturnValue", // ARCInstKind::RetainRV
- "objc_retainAutorelease", // ARCInstKind::FusedRetainAutorelease
- "objc_retainedObject", // ARCInstKind::NoopCast
- "objc_retain", // ARCInstKind::Retain
- "objc_unretainedObject", // ARCInstKind::NoopCast
- "objc_unretainedPointer", // ARCInstKind::NoopCast
- "objc_unsafeClaimAutoreleasedReturnValue", // ARCInstKind::ClaimRV
- true)
- .Default(false);
-}
-
static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
llvm::FunctionType *FTy,
StringRef Name) {
@@ -1847,9 +1834,6 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
// performance.
F->addFnAttr(llvm::Attribute::NonLazyBind);
}
-
- if (IsForwarding(Name))
- F->arg_begin()->addAttr(llvm::Attribute::Returned);
}
return RTF;
@@ -2031,7 +2015,7 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {
} else if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
llvm::FunctionType *type =
llvm::FunctionType::get(CGF.VoidTy, /*variadic*/false);
-
+
marker = llvm::InlineAsm::get(type, assembly, "", /*sideeffects*/ true);
// If we're at -O1 and above, we don't want to litter the code
@@ -2052,7 +2036,7 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {
// Call the marker asm if we made one, which we do only at -O0.
if (marker)
- CGF.Builder.CreateCall(marker);
+ CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker));
}
/// Retain the given object which is the result of a function call.
@@ -2070,7 +2054,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
/// Claim a possibly-autoreleased return value at +0. This is only
/// valid to do in contexts which do not rely on the retain to keep
-/// the object valid for for all of its uses; for example, when
+/// the object valid for all of its uses; for example, when
/// the value is ignored, or when it is being assigned to an
/// __unsafe_unretained variable.
///
@@ -2325,6 +2309,21 @@ void CodeGenFunction::EmitARCCopyWeak(Address dst, Address src) {
"objc_copyWeak");
}
+void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr,
+ Address SrcAddr) {
+ llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr);
+ Object = EmitObjCConsumeObject(Ty, Object);
+ EmitARCStoreWeak(DstAddr, Object, false);
+}
+
+void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,
+ Address SrcAddr) {
+ llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr);
+ Object = EmitObjCConsumeObject(Ty, Object);
+ EmitARCStoreWeak(DstAddr, Object, false);
+ EmitARCDestroyWeak(SrcAddr);
+}
+
/// Produce the code to do a objc_autoreleasepool_push.
/// call i8* \@objc_autoreleasePoolPush(void)
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
@@ -2369,10 +2368,10 @@ llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() {
IdentifierInfo *II = &CGM.getContext().Idents.get("alloc");
Selector AllocSel = getContext().Selectors.getSelector(0, &II);
CallArgList Args;
- RValue AllocRV =
- Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
+ RValue AllocRV =
+ Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
getContext().getObjCIdType(),
- AllocSel, Receiver, Args);
+ AllocSel, Receiver, Args);
// [Receiver init]
Receiver = AllocRV.getScalarVal();
@@ -2381,7 +2380,7 @@ llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() {
RValue InitRV =
Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
getContext().getObjCIdType(),
- InitSel, Receiver, Args);
+ InitSel, Receiver, Args);
return InitRV.getScalarVal();
}
@@ -2392,7 +2391,7 @@ void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) {
Selector DrainSel = getContext().Selectors.getSelector(0, &II);
CallArgList Args;
CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
- getContext().VoidTy, DrainSel, Arg, Args);
+ getContext().VoidTy, DrainSel, Arg, Args);
}
void CodeGenFunction::destroyARCStrongPrecise(CodeGenFunction &CGF,
@@ -2472,7 +2471,7 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
e = e->IgnoreParens();
QualType type = e->getType();
- // If we're loading retained from a __strong xvalue, we can avoid
+ // If we're loading retained from a __strong xvalue, we can avoid
// an extra retain/release pair by zeroing out the source of this
// "move" operation.
if (e->isXValue() &&
@@ -2480,14 +2479,14 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
type.getObjCLifetime() == Qualifiers::OCL_Strong) {
// Emit the lvalue.
LValue lv = CGF.EmitLValue(e);
-
+
// Load the object pointer.
llvm::Value *result = CGF.EmitLoadOfLValue(lv,
SourceLocation()).getScalarVal();
-
+
// Set the source pointer to NULL.
CGF.EmitStoreOfScalar(getNullForVariable(lv.getAddress()), lv);
-
+
return TryEmitResult(result, true);
}
@@ -3226,7 +3225,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null");
if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty)))
return HelperFn;
-
+
ASTContext &C = getContext();
IdentifierInfo *II
= &CGM.getContext().Idents.get("__assign_helper_atomic_property_");
@@ -3242,7 +3241,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
QualType SrcTy = Ty;
SrcTy.addConst();
SrcTy = C.getPointerType(SrcTy);
-
+
FunctionArgList args;
ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
DestTy, ImplicitParamDecl::Other);
@@ -3255,32 +3254,32 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
-
+
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__assign_helper_atomic_property_",
&CGM.getModule());
- CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
StartFunction(FD, C.VoidTy, Fn, FI, args);
-
+
DeclRefExpr DstExpr(&DstDecl, false, DestTy,
VK_RValue, SourceLocation());
UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(),
- VK_LValue, OK_Ordinary, SourceLocation());
-
+ VK_LValue, OK_Ordinary, SourceLocation(), false);
+
DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy,
VK_RValue, SourceLocation());
UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
- VK_LValue, OK_Ordinary, SourceLocation());
-
+ VK_LValue, OK_Ordinary, SourceLocation(), false);
+
Expr *Args[2] = { &DST, &SRC };
CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
CXXOperatorCallExpr TheCall(C, OO_Equal, CalleeExp->getCallee(),
Args, DestTy->getPointeeType(),
VK_LValue, SourceLocation(), FPOptions());
-
+
EmitStmt(&TheCall);
FinishFunction();
@@ -3308,8 +3307,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null");
if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty)))
return HelperFn;
-
-
+
+
ASTContext &C = getContext();
IdentifierInfo *II
= &CGM.getContext().Idents.get("__copy_helper_atomic_property_");
@@ -3325,7 +3324,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
QualType SrcTy = Ty;
SrcTy.addConst();
SrcTy = C.getPointerType(SrcTy);
-
+
FunctionArgList args;
ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
DestTy, ImplicitParamDecl::Other);
@@ -3338,24 +3337,24 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
-
+
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__copy_helper_atomic_property_", &CGM.getModule());
-
- CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
StartFunction(FD, C.VoidTy, Fn, FI, args);
-
+
DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy,
VK_RValue, SourceLocation());
-
+
UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
- VK_LValue, OK_Ordinary, SourceLocation());
-
- CXXConstructExpr *CXXConstExpr =
+ VK_LValue, OK_Ordinary, SourceLocation(), false);
+
+ CXXConstructExpr *CXXConstExpr =
cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
-
+
SmallVector<Expr*, 4> ConstructorArgs;
ConstructorArgs.push_back(&SRC);
ConstructorArgs.append(std::next(CXXConstExpr->arg_begin()),
@@ -3372,20 +3371,21 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
CXXConstExpr->requiresZeroInitialization(),
CXXConstExpr->getConstructionKind(),
SourceRange());
-
+
DeclRefExpr DstExpr(&DstDecl, false, DestTy,
VK_RValue, SourceLocation());
-
+
RValue DV = EmitAnyExpr(&DstExpr);
CharUnits Alignment
= getContext().getTypeAlignInChars(TheCXXConstructExpr->getType());
- EmitAggExpr(TheCXXConstructExpr,
+ EmitAggExpr(TheCXXConstructExpr,
AggValueSlot::forAddr(Address(DV.getScalarVal(), Alignment),
Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
-
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
+
FinishFunction();
HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
CGM.setAtomicGetterHelperFnMap(Ty, HelperFn);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index c8b8be7f4552..622c8bfb500f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -18,6 +18,7 @@
#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -34,11 +35,24 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ConvertUTF.h"
+#include <cctype>
using namespace clang;
using namespace CodeGen;
namespace {
+
+std::string SymbolNameForMethod( StringRef ClassName,
+ StringRef CategoryName, const Selector MethodName,
+ bool isClassMethod) {
+ std::string MethodNameColonStripped = MethodName.getAsString();
+ std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
+ ':', '_');
+ return (Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
+ CategoryName + "_" + MethodNameColonStripped).str();
+}
+
/// Class that lazily initialises the runtime function. Avoids inserting the
/// types and the function declaration into a module if they're not used, and
/// avoids constructing the type more than once if it's used more than once.
@@ -80,8 +94,7 @@ public:
if (!Function) {
if (!FunctionName)
return nullptr;
- Function =
- cast<llvm::Constant>(CGM->CreateRuntimeFunction(FTy, FunctionName));
+ Function = CGM->CreateRuntimeFunction(FTy, FunctionName);
}
return Function;
}
@@ -102,7 +115,7 @@ protected:
/// contains the receiver (object) and the expected class.
llvm::StructType *ObjCSuperTy;
/// struct objc_super*. The type of the argument to the superclass message
- /// lookup functions.
+ /// lookup functions.
llvm::PointerType *PtrToObjCSuperTy;
/// LLVM type for selectors. Opaque pointer (i8*) unless a header declaring
/// SEL is included in a header somewhere, in which case it will be whatever
@@ -114,6 +127,10 @@ protected:
/// Pointer to i8 - LLVM type of char*, for all of the places where the
/// runtime needs to deal with C strings.
llvm::PointerType *PtrToInt8Ty;
+ /// struct objc_protocol type
+ llvm::StructType *ProtocolTy;
+ /// Protocol * type.
+ llvm::PointerType *ProtocolPtrTy;
/// Instance Method Pointer type. This is a pointer to a function that takes,
/// at a minimum, an object and a selector, and is the generic type for
/// Objective-C methods. Due to differences between variadic / non-variadic
@@ -143,7 +160,7 @@ protected:
llvm::IntegerType *LongTy;
/// LLVM type for C size_t. Used in various runtime data structures.
llvm::IntegerType *SizeTy;
- /// LLVM type for C intptr_t.
+ /// LLVM type for C intptr_t.
llvm::IntegerType *IntPtrTy;
/// LLVM type for C ptrdiff_t. Mainly used in property accessor functions.
llvm::IntegerType *PtrDiffTy;
@@ -156,14 +173,35 @@ protected:
llvm::IntegerType *Int32Ty;
/// 64-bit integer type, to save us needing to look it up every time it's used.
llvm::IntegerType *Int64Ty;
+ /// The type of struct objc_property.
+ llvm::StructType *PropertyMetadataTy;
/// Metadata kind used to tie method lookups to message sends. The GNUstep
/// runtime provides some LLVM passes that can use this to do things like
/// automatic IMP caching and speculative inlining.
unsigned msgSendMDKind;
+ /// Does the current target use SEH-based exceptions? False implies
+ /// Itanium-style DWARF unwinding.
+ bool usesSEHExceptions;
+
+ /// Helper to check if we are targeting a specific runtime version or later.
+ bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
+ const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
+ return (R.getKind() == kind) &&
+ (R.getVersion() >= VersionTuple(major, minor));
+ }
+
+ std::string SymbolForProtocol(StringRef Name) {
+ return (StringRef("._OBJC_PROTOCOL_") + Name).str();
+ }
+
+ std::string SymbolForProtocolRef(StringRef Name) {
+ return (StringRef("._OBJC_REF_PROTOCOL_") + Name).str();
+ }
+
/// Helper function that generates a constant string and returns a pointer to
/// the start of the string. The result of this function can be used anywhere
- /// where the C code specifies const char*.
+ /// where the C code specifies const char*.
llvm::Constant *MakeConstantString(StringRef Str, const char *Name = "") {
ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name);
return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(),
@@ -174,39 +212,29 @@ protected:
/// string value. This allows the linker to combine the strings between
/// different modules. Used for EH typeinfo names, selector strings, and a
/// few other things.
- llvm::Constant *ExportUniqueString(const std::string &Str, StringRef Prefix) {
- std::string Name = Prefix.str() + Str;
- auto *ConstStr = TheModule.getGlobalVariable(Name);
+ llvm::Constant *ExportUniqueString(const std::string &Str,
+ const std::string &prefix,
+ bool Private=false) {
+ std::string name = prefix + Str;
+ auto *ConstStr = TheModule.getGlobalVariable(name);
if (!ConstStr) {
llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
- ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
- llvm::GlobalValue::LinkOnceODRLinkage,
- value, Name);
+ auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true,
+ llvm::GlobalValue::LinkOnceODRLinkage, value, name);
+ GV->setComdat(TheModule.getOrInsertComdat(name));
+ if (Private)
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ ConstStr = GV;
}
return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
ConstStr, Zeros);
}
- /// Generates a global structure, initialized by the elements in the vector.
- /// The element types must match the types of the structure elements in the
- /// first argument.
- llvm::GlobalVariable *MakeGlobal(llvm::Constant *C,
- CharUnits Align,
- StringRef Name="",
- llvm::GlobalValue::LinkageTypes linkage
- =llvm::GlobalValue::InternalLinkage) {
- auto GV = new llvm::GlobalVariable(TheModule, C->getType(), false,
- linkage, C, Name);
- GV->setAlignment(Align.getQuantity());
- return GV;
- }
-
/// Returns a property name and encoding string.
llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
const Decl *Container) {
- const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
- if ((R.getKind() == ObjCRuntime::GNUstep) &&
- (R.getVersion() >= VersionTuple(1, 6))) {
+ assert(!isRuntime(ObjCRuntime::GNUstep, 2));
+ if (isRuntime(ObjCRuntime::GNUstep, 1, 6)) {
std::string NameAndAttributes;
std::string TypeStr =
CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
@@ -220,9 +248,9 @@ protected:
return MakeConstantString(PD->getNameAsString());
}
- /// Push the property attributes into two structure fields.
+ /// Push the property attributes into two structure fields.
void PushPropertyAttributes(ConstantStructBuilder &Fields,
- ObjCPropertyDecl *property, bool isSynthesized=true, bool
+ const ObjCPropertyDecl *property, bool isSynthesized=true, bool
isDynamic=true) {
int attrs = property->getPropertyAttributes();
// For read-only properties, clear the copy and retain flags
@@ -249,6 +277,46 @@ protected:
Fields.addInt(Int8Ty, 0);
}
+ virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
+ int count) {
+ // int count;
+ Fields.addInt(IntTy, count);
+ // int size; (only in GNUstep v2 ABI.
+ if (isRuntime(ObjCRuntime::GNUstep, 2)) {
+ llvm::DataLayout td(&TheModule);
+ Fields.addInt(IntTy, td.getTypeSizeInBits(PropertyMetadataTy) /
+ CGM.getContext().getCharWidth());
+ }
+ // struct objc_property_list *next;
+ Fields.add(NULLPtr);
+ // struct objc_property properties[]
+ return Fields.beginArray(PropertyMetadataTy);
+ }
+ virtual void PushProperty(ConstantArrayBuilder &PropertiesArray,
+ const ObjCPropertyDecl *property,
+ const Decl *OCD,
+ bool isSynthesized=true, bool
+ isDynamic=true) {
+ auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
+ ASTContext &Context = CGM.getContext();
+ Fields.add(MakePropertyEncodingString(property, OCD));
+ PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
+ auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
+ if (accessor) {
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ Fields.add(MakeConstantString(accessor->getSelector().getAsString()));
+ Fields.add(TypeEncoding);
+ } else {
+ Fields.add(NULLPtr);
+ Fields.add(NULLPtr);
+ }
+ };
+ addPropertyMethod(property->getGetterMethodDecl());
+ addPropertyMethod(property->getSetterMethodDecl());
+ Fields.finishAndAddTo(PropertiesArray);
+ }
+
/// Ensures that the value has the required type, by inserting a bitcast if
/// required. This function lets us avoid inserting bitcasts that are
/// redundant.
@@ -268,7 +336,8 @@ protected:
/// LLVM context.
llvm::LLVMContext &VMContext;
-private:
+protected:
+
/// Placeholder for the class. Lots of things refer to the class before we've
/// actually emitted it. We use this alias as a placeholder, and then replace
/// it with a pointer to the class structure before finally emitting the
@@ -313,7 +382,7 @@ private:
/// Runtime functions used for memory management in GC mode. Note that clang
/// supports code generation for calling these functions, but neither GNU
/// runtime actually supports this API properly yet.
- LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
+ LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
WeakAssignFn, GlobalAssignFn;
typedef std::pair<std::string, std::string> ClassAliasPair;
@@ -352,6 +421,7 @@ private:
/// Function used for non-object declared property setters.
LazyRuntimeFunction SetStructPropertyFn;
+protected:
/// The version of the runtime that this class targets. Must match the
/// version in the runtime.
int RuntimeVersion;
@@ -362,14 +432,18 @@ private:
/// Objective-C 1 property structures when targeting the GCC runtime or it
/// will abort.
const int ProtocolVersion;
-
+ /// The version of the class ABI. This value is used in the class structure
+ /// and indicates how various fields should be interpreted.
+ const int ClassABIVersion;
/// Generates an instance variable list structure. This is a structure
/// containing a size and an array of structures containing instance variable
/// metadata. This is used purely for introspection in the fragile ABI. In
/// the non-fragile ABI, it's used for instance variable fixup.
- llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
- ArrayRef<llvm::Constant *> IvarTypes,
- ArrayRef<llvm::Constant *> IvarOffsets);
+ virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
+ ArrayRef<llvm::Constant *> IvarTypes,
+ ArrayRef<llvm::Constant *> IvarOffsets,
+ ArrayRef<llvm::Constant *> IvarAlign,
+ ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership);
/// Generates a method list structure. This is a structure containing a size
/// and an array of structures containing method metadata.
@@ -378,20 +452,20 @@ private:
/// pointer allowing them to be chained together in a linked list.
llvm::Constant *GenerateMethodList(StringRef ClassName,
StringRef CategoryName,
- ArrayRef<Selector> MethodSels,
- ArrayRef<llvm::Constant *> MethodTypes,
+ ArrayRef<const ObjCMethodDecl*> Methods,
bool isClassMethodList);
/// Emits an empty protocol. This is used for \@protocol() where no protocol
/// is found. The runtime will (hopefully) fix up the pointer to refer to the
/// real protocol.
- llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
+ virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName);
/// Generates a list of property metadata structures. This follows the same
/// pattern as method and instance variable metadata lists.
- llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID,
- SmallVectorImpl<Selector> &InstanceMethodSels,
- SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes);
+ llvm::Constant *GeneratePropertyList(const Decl *Container,
+ const ObjCContainerDecl *OCD,
+ bool isClassProperty=false,
+ bool protocolOptionalProperties=false);
/// Generates a list of referenced protocols. Classes, categories, and
/// protocols all use this structure.
@@ -422,22 +496,42 @@ private:
/// Generates a method list. This is used by protocols to define the required
/// and optional methods.
- llvm::Constant *GenerateProtocolMethodList(
- ArrayRef<llvm::Constant *> MethodNames,
- ArrayRef<llvm::Constant *> MethodTypes);
+ virtual llvm::Constant *GenerateProtocolMethodList(
+ ArrayRef<const ObjCMethodDecl*> Methods);
+ /// Emits optional and required method lists.
+ template<class T>
+ void EmitProtocolMethodList(T &&Methods, llvm::Constant *&Required,
+ llvm::Constant *&Optional) {
+ SmallVector<const ObjCMethodDecl*, 16> RequiredMethods;
+ SmallVector<const ObjCMethodDecl*, 16> OptionalMethods;
+ for (const auto *I : Methods)
+ if (I->isOptional())
+ OptionalMethods.push_back(I);
+ else
+ RequiredMethods.push_back(I);
+ Required = GenerateProtocolMethodList(RequiredMethods);
+ Optional = GenerateProtocolMethodList(OptionalMethods);
+ }
/// Returns a selector with the specified type encoding. An empty string is
/// used to return an untyped selector (with the types field set to NULL).
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding);
-
+ virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding);
+
+ /// Returns the name of ivar offset variables. In the GNUstep v1 ABI, this
+ /// contains the class and ivar names, in the v2 ABI this contains the type
+ /// encoding as well.
+ virtual std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar) {
+ const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
+ + '.' + Ivar->getNameAsString();
+ return Name;
+ }
/// Returns the variable used to store the offset of an instance variable.
llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
/// Emits a reference to a class. This allows the linker to object if there
/// is no class of the matching name.
-
-protected:
void EmitClassRef(const std::string &className);
/// Emits a pointer to the named class
@@ -465,7 +559,7 @@ protected:
/// stored in a 64-bit value with the low bit set to 1 and the remaining 63
/// bits set to their values, LSB first, while larger ones are stored in a
/// structure of this / form:
- ///
+ ///
/// struct { int32_t length; int32_t values[length]; };
///
/// The values in the array are stored in host-endian format, with the least
@@ -476,7 +570,7 @@ protected:
public:
CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
- unsigned protocolClassVersion);
+ unsigned protocolClassVersion, unsigned classABI=1);
ConstantAddress GenerateConstantString(const StringLiteral *) override;
@@ -499,6 +593,14 @@ public:
Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
llvm::Value *GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) override;
+ virtual llvm::Constant *GetConstantSelector(Selector Sel,
+ const std::string &TypeEncoding) {
+ llvm_unreachable("Runtime unable to generate constant selector");
+ }
+ llvm::Constant *GetConstantSelector(const ObjCMethodDecl *M) {
+ return GetConstantSelector(M->getSelector(),
+ CGM.getContext().getObjCEncodingForMethodDecl(M));
+ }
llvm::Constant *GetEHType(QualType T) override;
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
@@ -698,7 +800,10 @@ class CGObjCGNUstep : public CGObjCGNU {
}
public:
- CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) {
+ CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
+ CGObjCGNUstep(CodeGenModule &Mod, unsigned ABI, unsigned ProtocolABI,
+ unsigned ClassABI) :
+ CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
llvm::StructType *SlotStructTy =
@@ -707,11 +812,15 @@ class CGObjCGNUstep : public CGObjCGNU {
// Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy,
SelectorTy, IdTy);
- // Slot_t objc_msg_lookup_super(struct objc_super*, SEL);
+ // Slot_t objc_slot_lookup_super(struct objc_super*, SEL);
SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
PtrToObjCSuperTy, SelectorTy);
// If we're in ObjC++ mode, then we want to make
- if (CGM.getLangOpts().CPlusPlus) {
+ if (usesSEHExceptions) {
+ llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
+ // void objc_exception_rethrow(void)
+ ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
+ } else if (CGM.getLangOpts().CPlusPlus) {
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
// void *__cxa_begin_catch(void *e)
EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
@@ -784,6 +893,1018 @@ class CGObjCGNUstep : public CGObjCGNU {
}
};
+/// GNUstep Objective-C ABI version 2 implementation.
+/// This is the ABI that provides a clean break with the legacy GCC ABI and
+/// cleans up a number of things that were added to work around 1980s linkers.
+class CGObjCGNUstep2 : public CGObjCGNUstep {
+ enum SectionKind
+ {
+ SelectorSection = 0,
+ ClassSection,
+ ClassReferenceSection,
+ CategorySection,
+ ProtocolSection,
+ ProtocolReferenceSection,
+ ClassAliasSection,
+ ConstantStringSection
+ };
+ static const char *const SectionsBaseNames[8];
+ template<SectionKind K>
+ std::string sectionName() {
+ std::string name(SectionsBaseNames[K]);
+ if (CGM.getTriple().isOSBinFormatCOFF())
+ name += "$m";
+ return name;
+ }
+ /// The GCC ABI superclass message lookup function. Takes a pointer to a
+ /// structure describing the receiver and the class, and a selector as
+ /// arguments. Returns the IMP for the corresponding method.
+ LazyRuntimeFunction MsgLookupSuperFn;
+ /// A flag indicating if we've emitted at least one protocol.
+ /// If we haven't, then we need to emit an empty protocol, to ensure that the
+ /// __start__objc_protocols and __stop__objc_protocols sections exist.
+ bool EmittedProtocol = false;
+ /// A flag indicating if we've emitted at least one protocol reference.
+ /// If we haven't, then we need to emit an empty protocol, to ensure that the
+ /// __start__objc_protocol_refs and __stop__objc_protocol_refs sections
+ /// exist.
+ bool EmittedProtocolRef = false;
+ /// A flag indicating if we've emitted at least one class.
+ /// If we haven't, then we need to emit an empty protocol, to ensure that the
+ /// __start__objc_classes and __stop__objc_classes sections / exist.
+ bool EmittedClass = false;
+ /// Generate the name of a symbol for a reference to a class. Accesses to
+ /// classes should be indirected via this.
+ std::string SymbolForClassRef(StringRef Name, bool isWeak) {
+ if (isWeak)
+ return (StringRef("._OBJC_WEAK_REF_CLASS_") + Name).str();
+ else
+ return (StringRef("._OBJC_REF_CLASS_") + Name).str();
+ }
+ /// Generate the name of a class symbol.
+ std::string SymbolForClass(StringRef Name) {
+ return (StringRef("._OBJC_CLASS_") + Name).str();
+ }
+ void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
+ ArrayRef<llvm::Value*> Args) {
+ SmallVector<llvm::Type *,8> Types;
+ for (auto *Arg : Args)
+ Types.push_back(Arg->getType());
+ llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
+ false);
+ llvm::Value *Fn = CGM.CreateRuntimeFunction(FT, FunctionName);
+ B.CreateCall(Fn, Args);
+ }
+
+ ConstantAddress GenerateConstantString(const StringLiteral *SL) override {
+
+ auto Str = SL->getString();
+ CharUnits Align = CGM.getPointerAlign();
+
+ // Look for an existing one
+ llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
+ if (old != ObjCStrings.end())
+ return ConstantAddress(old->getValue(), Align);
+
+ bool isNonASCII = SL->containsNonAscii();
+
+ auto LiteralLength = SL->getLength();
+
+ if ((CGM.getTarget().getPointerWidth(0) == 64) &&
+ (LiteralLength < 9) && !isNonASCII) {
+ // Tiny strings are only used on 64-bit platforms. They store 8 7-bit
+ // ASCII characters in the high 56 bits, followed by a 4-bit length and a
+ // 3-bit tag (which is always 4).
+ uint64_t str = 0;
+ // Fill in the characters
+ for (unsigned i=0 ; i<LiteralLength ; i++)
+ str |= ((uint64_t)SL->getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
+ // Fill in the length
+ str |= LiteralLength << 3;
+ // Set the tag
+ str |= 4;
+ auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(Int64Ty, str), IdTy);
+ ObjCStrings[Str] = ObjCStr;
+ return ConstantAddress(ObjCStr, Align);
+ }
+
+ StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
+
+ if (StringClass.empty()) StringClass = "NSConstantString";
+
+ std::string Sym = SymbolForClass(StringClass);
+
+ llvm::Constant *isa = TheModule.getNamedGlobal(Sym);
+
+ if (!isa)
+ isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, Sym);
+ else if (isa->getType() != PtrToIdTy)
+ isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
+
+ // struct
+ // {
+ // Class isa;
+ // uint32_t flags;
+ // uint32_t length; // Number of codepoints
+ // uint32_t size; // Number of bytes
+ // uint32_t hash;
+ // const char *data;
+ // };
+
+ ConstantInitBuilder Builder(CGM);
+ auto Fields = Builder.beginStruct();
+ Fields.add(isa);
+ // For now, all non-ASCII strings are represented as UTF-16. As such, the
+ // number of bytes is simply double the number of UTF-16 codepoints. In
+ // ASCII strings, the number of bytes is equal to the number of non-ASCII
+ // codepoints.
+ if (isNonASCII) {
+ unsigned NumU8CodeUnits = Str.size();
+ // A UTF-16 representation of a unicode string contains at most the same
+ // number of code units as a UTF-8 representation. Allocate that much
+ // space, plus one for the final null character.
+ SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
+ const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)Str.data();
+ llvm::UTF16 *ToPtr = &ToBuf[0];
+ (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
+ &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
+ uint32_t StringLength = ToPtr - &ToBuf[0];
+ // Add null terminator
+ *ToPtr = 0;
+ // Flags: 2 indicates UTF-16 encoding
+ Fields.addInt(Int32Ty, 2);
+ // Number of UTF-16 codepoints
+ Fields.addInt(Int32Ty, StringLength);
+ // Number of bytes
+ Fields.addInt(Int32Ty, StringLength * 2);
+ // Hash. Not currently initialised by the compiler.
+ Fields.addInt(Int32Ty, 0);
+ // pointer to the data string.
+ auto Arr = llvm::makeArrayRef(&ToBuf[0], ToPtr+1);
+ auto *C = llvm::ConstantDataArray::get(VMContext, Arr);
+ auto *Buffer = new llvm::GlobalVariable(TheModule, C->getType(),
+ /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, C, ".str");
+ Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ Fields.add(Buffer);
+ } else {
+ // Flags: 0 indicates ASCII encoding
+ Fields.addInt(Int32Ty, 0);
+ // Number of UTF-16 codepoints, each ASCII byte is a UTF-16 codepoint
+ Fields.addInt(Int32Ty, Str.size());
+ // Number of bytes
+ Fields.addInt(Int32Ty, Str.size());
+ // Hash. Not currently initialised by the compiler.
+ Fields.addInt(Int32Ty, 0);
+ // Data pointer
+ Fields.add(MakeConstantString(Str));
+ }
+ std::string StringName;
+ bool isNamed = !isNonASCII;
+ if (isNamed) {
+ StringName = ".objc_str_";
+ for (int i=0,e=Str.size() ; i<e ; ++i) {
+ unsigned char c = Str[i];
+ if (isalnum(c))
+ StringName += c;
+ else if (c == ' ')
+ StringName += '_';
+ else {
+ isNamed = false;
+ break;
+ }
+ }
+ }
+ auto *ObjCStrGV =
+ Fields.finishAndCreateGlobal(
+ isNamed ? StringRef(StringName) : ".objc_string",
+ Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
+ : llvm::GlobalValue::PrivateLinkage);
+ ObjCStrGV->setSection(sectionName<ConstantStringSection>());
+ if (isNamed) {
+ ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
+ ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ }
+ llvm::Constant *ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStrGV, IdTy);
+ ObjCStrings[Str] = ObjCStr;
+ ConstantStrings.push_back(ObjCStr);
+ return ConstantAddress(ObjCStr, Align);
+ }
+
+ void PushProperty(ConstantArrayBuilder &PropertiesArray,
+ const ObjCPropertyDecl *property,
+ const Decl *OCD,
+ bool isSynthesized=true, bool
+ isDynamic=true) override {
+ // struct objc_property
+ // {
+ // const char *name;
+ // const char *attributes;
+ // const char *type;
+ // SEL getter;
+ // SEL setter;
+ // };
+ auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
+ ASTContext &Context = CGM.getContext();
+ Fields.add(MakeConstantString(property->getNameAsString()));
+ std::string TypeStr =
+ CGM.getContext().getObjCEncodingForPropertyDecl(property, OCD);
+ Fields.add(MakeConstantString(TypeStr));
+ std::string typeStr;
+ Context.getObjCEncodingForType(property->getType(), typeStr);
+ Fields.add(MakeConstantString(typeStr));
+ auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
+ if (accessor) {
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
+ Fields.add(GetConstantSelector(accessor->getSelector(), TypeStr));
+ } else {
+ Fields.add(NULLPtr);
+ }
+ };
+ addPropertyMethod(property->getGetterMethodDecl());
+ addPropertyMethod(property->getSetterMethodDecl());
+ Fields.finishAndAddTo(PropertiesArray);
+ }
+
+ llvm::Constant *
+ GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) override {
+ // struct objc_protocol_method_description
+ // {
+ // SEL selector;
+ // const char *types;
+ // };
+ llvm::StructType *ObjCMethodDescTy =
+ llvm::StructType::get(CGM.getLLVMContext(),
+ { PtrToInt8Ty, PtrToInt8Ty });
+ ASTContext &Context = CGM.getContext();
+ ConstantInitBuilder Builder(CGM);
+ // struct objc_protocol_method_description_list
+ // {
+ // int count;
+ // int size;
+ // struct objc_protocol_method_description methods[];
+ // };
+ auto MethodList = Builder.beginStruct();
+ // int count;
+ MethodList.addInt(IntTy, Methods.size());
+ // int size; // sizeof(struct objc_method_description)
+ llvm::DataLayout td(&TheModule);
+ MethodList.addInt(IntTy, td.getTypeSizeInBits(ObjCMethodDescTy) /
+ CGM.getContext().getCharWidth());
+ // struct objc_method_description[]
+ auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
+ for (auto *M : Methods) {
+ auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
+ Method.add(CGObjCGNU::GetConstantSelector(M));
+ Method.add(GetTypeString(Context.getObjCEncodingForMethodDecl(M, true)));
+ Method.finishAndAddTo(MethodArray);
+ }
+ MethodArray.finishAndAddTo(MethodList);
+ return MethodList.finishAndCreateGlobal(".objc_protocol_method_list",
+ CGM.getPointerAlign());
+ }
+
+ llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
+ llvm::Value *cmd, MessageSendInfo &MSI) override {
+ // Don't access the slot unless we're trying to cache the result.
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, ObjCSuper,
+ PtrToObjCSuperTy).getPointer(), cmd};
+ return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
+ }
+
+ llvm::GlobalVariable *GetClassVar(StringRef Name, bool isWeak=false) {
+ std::string SymbolName = SymbolForClassRef(Name, isWeak);
+ auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
+ if (ClassSymbol)
+ return ClassSymbol;
+ ClassSymbol = new llvm::GlobalVariable(TheModule,
+ IdTy, false, llvm::GlobalValue::ExternalLinkage,
+ nullptr, SymbolName);
+ // If this is a weak symbol, then we are creating a valid definition for
+ // the symbol, pointing to a weak definition of the real class pointer. If
+ // this is not a weak reference, then we are expecting another compilation
+ // unit to provide the real indirection symbol.
+ if (isWeak)
+ ClassSymbol->setInitializer(new llvm::GlobalVariable(TheModule,
+ Int8Ty, false, llvm::GlobalValue::ExternalWeakLinkage,
+ nullptr, SymbolForClass(Name)));
+ assert(ClassSymbol->getName() == SymbolName);
+ return ClassSymbol;
+ }
+ llvm::Value *GetClassNamed(CodeGenFunction &CGF,
+ const std::string &Name,
+ bool isWeak) override {
+ return CGF.Builder.CreateLoad(Address(GetClassVar(Name, isWeak),
+ CGM.getPointerAlign()));
+ }
+ int32_t FlagsForOwnership(Qualifiers::ObjCLifetime Ownership) {
+ // typedef enum {
+ // ownership_invalid = 0,
+ // ownership_strong = 1,
+ // ownership_weak = 2,
+ // ownership_unsafe = 3
+ // } ivar_ownership;
+ int Flag;
+ switch (Ownership) {
+ case Qualifiers::OCL_Strong:
+ Flag = 1;
+ break;
+ case Qualifiers::OCL_Weak:
+ Flag = 2;
+ break;
+ case Qualifiers::OCL_ExplicitNone:
+ Flag = 3;
+ break;
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_Autoreleasing:
+ assert(Ownership != Qualifiers::OCL_Autoreleasing);
+ Flag = 0;
+ }
+ return Flag;
+ }
+ llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
+ ArrayRef<llvm::Constant *> IvarTypes,
+ ArrayRef<llvm::Constant *> IvarOffsets,
+ ArrayRef<llvm::Constant *> IvarAlign,
+ ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) override {
+ llvm_unreachable("Method should not be called!");
+ }
+
+ llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName) override {
+ std::string Name = SymbolForProtocol(ProtocolName);
+ auto *GV = TheModule.getGlobalVariable(Name);
+ if (!GV) {
+ // Emit a placeholder symbol.
+ GV = new llvm::GlobalVariable(TheModule, ProtocolTy, false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, Name);
+ GV->setAlignment(CGM.getPointerAlign().getQuantity());
+ }
+ return llvm::ConstantExpr::getBitCast(GV, ProtocolPtrTy);
+ }
+
+ /// Existing protocol references.
+ llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;
+
+ llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
+ const ObjCProtocolDecl *PD) override {
+ auto Name = PD->getNameAsString();
+ auto *&Ref = ExistingProtocolRefs[Name];
+ if (!Ref) {
+ auto *&Protocol = ExistingProtocols[Name];
+ if (!Protocol)
+ Protocol = GenerateProtocolRef(PD);
+ std::string RefName = SymbolForProtocolRef(Name);
+ assert(!TheModule.getGlobalVariable(RefName));
+ // Emit a reference symbol.
+ auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
+ false, llvm::GlobalValue::LinkOnceODRLinkage,
+ llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName);
+ GV->setComdat(TheModule.getOrInsertComdat(RefName));
+ GV->setSection(sectionName<ProtocolReferenceSection>());
+ GV->setAlignment(CGM.getPointerAlign().getQuantity());
+ Ref = GV;
+ }
+ EmittedProtocolRef = true;
+ return CGF.Builder.CreateAlignedLoad(Ref, CGM.getPointerAlign());
+ }
+
+ llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
+ llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
+ Protocols.size());
+ llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
+ Protocols);
+ ConstantInitBuilder builder(CGM);
+ auto ProtocolBuilder = builder.beginStruct();
+ ProtocolBuilder.addNullPointer(PtrTy);
+ ProtocolBuilder.addInt(SizeTy, Protocols.size());
+ ProtocolBuilder.add(ProtocolArray);
+ return ProtocolBuilder.finishAndCreateGlobal(".objc_protocol_list",
+ CGM.getPointerAlign(), false, llvm::GlobalValue::InternalLinkage);
+ }
+
+ void GenerateProtocol(const ObjCProtocolDecl *PD) override {
+ // Do nothing - we only emit referenced protocols.
+ }
+ llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) {
+ std::string ProtocolName = PD->getNameAsString();
+ auto *&Protocol = ExistingProtocols[ProtocolName];
+ if (Protocol)
+ return Protocol;
+
+ EmittedProtocol = true;
+
+ auto SymName = SymbolForProtocol(ProtocolName);
+ auto *OldGV = TheModule.getGlobalVariable(SymName);
+
+ // Use the protocol definition, if there is one.
+ if (const ObjCProtocolDecl *Def = PD->getDefinition())
+ PD = Def;
+ else {
+ // If there is no definition, then create an external linkage symbol and
+ // hope that someone else fills it in for us (and fail to link if they
+ // don't).
+ assert(!OldGV);
+ Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy,
+ /*isConstant*/false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, SymName);
+ return Protocol;
+ }
+
+ SmallVector<llvm::Constant*, 16> Protocols;
+ for (const auto *PI : PD->protocols())
+ Protocols.push_back(
+ llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
+ ProtocolPtrTy));
+ llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
+
+ // Collect information about methods
+ llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
+ llvm::Constant *ClassMethodList, *OptionalClassMethodList;
+ EmitProtocolMethodList(PD->instance_methods(), InstanceMethodList,
+ OptionalInstanceMethodList);
+ EmitProtocolMethodList(PD->class_methods(), ClassMethodList,
+ OptionalClassMethodList);
+
+ // The isa pointer must be set to a magic number so the runtime knows it's
+ // the correct layout.
+ ConstantInitBuilder builder(CGM);
+ auto ProtocolBuilder = builder.beginStruct();
+ ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
+ ProtocolBuilder.add(MakeConstantString(ProtocolName));
+ ProtocolBuilder.add(ProtocolList);
+ ProtocolBuilder.add(InstanceMethodList);
+ ProtocolBuilder.add(ClassMethodList);
+ ProtocolBuilder.add(OptionalInstanceMethodList);
+ ProtocolBuilder.add(OptionalClassMethodList);
+ // Required instance properties
+ ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, false));
+ // Optional instance properties
+ ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, true));
+ // Required class properties
+ ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, false));
+ // Optional class properties
+ ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, true));
+
+ auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
+ CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
+ GV->setSection(sectionName<ProtocolSection>());
+ GV->setComdat(TheModule.getOrInsertComdat(SymName));
+ if (OldGV) {
+ OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV,
+ OldGV->getType()));
+ OldGV->removeFromParent();
+ GV->setName(SymName);
+ }
+ Protocol = GV;
+ return GV;
+ }
+ llvm::Constant *EnforceType(llvm::Constant *Val, llvm::Type *Ty) {
+ if (Val->getType() == Ty)
+ return Val;
+ return llvm::ConstantExpr::getBitCast(Val, Ty);
+ }
+ llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding) override {
+ return GetConstantSelector(Sel, TypeEncoding);
+ }
+ llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
+ if (TypeEncoding.empty())
+ return NULLPtr;
+ std::string MangledTypes = TypeEncoding;
+ std::replace(MangledTypes.begin(), MangledTypes.end(),
+ '@', '\1');
+ std::string TypesVarName = ".objc_sel_types_" + MangledTypes;
+ auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
+ if (!TypesGlobal) {
+ llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
+ TypeEncoding);
+ auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(),
+ true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName);
+ GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ TypesGlobal = GV;
+ }
+ return llvm::ConstantExpr::getGetElementPtr(TypesGlobal->getValueType(),
+ TypesGlobal, Zeros);
+ }
+ llvm::Constant *GetConstantSelector(Selector Sel,
+ const std::string &TypeEncoding) override {
+ // @ is used as a special character in symbol names (used for symbol
+ // versioning), so mangle the name to not include it. Replace it with a
+ // character that is not a valid type encoding character (and, being
+ // non-printable, never will be!)
+ std::string MangledTypes = TypeEncoding;
+ std::replace(MangledTypes.begin(), MangledTypes.end(),
+ '@', '\1');
+ auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" +
+ MangledTypes).str();
+ if (auto *GV = TheModule.getNamedGlobal(SelVarName))
+ return EnforceType(GV, SelectorTy);
+ ConstantInitBuilder builder(CGM);
+ auto SelBuilder = builder.beginStruct();
+ SelBuilder.add(ExportUniqueString(Sel.getAsString(), ".objc_sel_name_",
+ true));
+ SelBuilder.add(GetTypeString(TypeEncoding));
+ auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
+ CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
+ GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ GV->setSection(sectionName<SelectorSection>());
+ auto *SelVal = EnforceType(GV, SelectorTy);
+ return SelVal;
+ }
+ llvm::StructType *emptyStruct = nullptr;
+
+ /// Return pointers to the start and end of a section. On ELF platforms, we
+ /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set
+ /// to the start and end of section names, as long as those section names are
+ /// valid identifiers and the symbols are referenced but not defined. On
+ /// Windows, we use the fact that MSVC-compatible linkers will lexically sort
+ /// by subsections and place everything that we want to reference in a middle
+ /// subsection and then insert zero-sized symbols in subsections a and z.
+ std::pair<llvm::Constant*,llvm::Constant*>
+ GetSectionBounds(StringRef Section) {
+ if (CGM.getTriple().isOSBinFormatCOFF()) {
+ if (emptyStruct == nullptr) {
+ emptyStruct = llvm::StructType::create(VMContext, ".objc_section_sentinel");
+ emptyStruct->setBody({}, /*isPacked*/true);
+ }
+ auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
+ auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
+ auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct,
+ /*isConstant*/false,
+ llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
+ Section);
+ Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ Sym->setSection((Section + SecSuffix).str());
+ Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
+ Section).str()));
+ Sym->setAlignment(1);
+ return Sym;
+ };
+ return { Sym("__start_", "$a"), Sym("__stop", "$z") };
+ }
+ auto *Start = new llvm::GlobalVariable(TheModule, PtrTy,
+ /*isConstant*/false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") +
+ Section);
+ Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ auto *Stop = new llvm::GlobalVariable(TheModule, PtrTy,
+ /*isConstant*/false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__stop_") +
+ Section);
+ Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ return { Start, Stop };
+ }
+ CatchTypeInfo getCatchAllTypeInfo() override {
+ return CGM.getCXXABI().getCatchAllTypeInfo();
+ }
+ llvm::Function *ModuleInitFunction() override {
+ llvm::Function *LoadFunction = llvm::Function::Create(
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
+ llvm::GlobalValue::LinkOnceODRLinkage, ".objcv2_load_function",
+ &TheModule);
+ LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ LoadFunction->setComdat(TheModule.getOrInsertComdat(".objcv2_load_function"));
+
+ llvm::BasicBlock *EntryBB =
+ llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
+ CGBuilderTy B(CGM, VMContext);
+ B.SetInsertPoint(EntryBB);
+ ConstantInitBuilder builder(CGM);
+ auto InitStructBuilder = builder.beginStruct();
+ InitStructBuilder.addInt(Int64Ty, 0);
+ for (auto *s : SectionsBaseNames) {
+ auto bounds = GetSectionBounds(s);
+ InitStructBuilder.add(bounds.first);
+ InitStructBuilder.add(bounds.second);
+ };
+ auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init",
+ CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
+ InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ InitStruct->setComdat(TheModule.getOrInsertComdat(".objc_init"));
+
+ CallRuntimeFunction(B, "__objc_load", {InitStruct});;
+ B.CreateRetVoid();
+ // Make sure that the optimisers don't delete this function.
+ CGM.addCompilerUsedGlobal(LoadFunction);
+ // FIXME: Currently ELF only!
+ // We have to do this by hand, rather than with @llvm.ctors, so that the
+ // linker can remove the duplicate invocations.
+ auto *InitVar = new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
+ /*isConstant*/true, llvm::GlobalValue::LinkOnceAnyLinkage,
+ LoadFunction, ".objc_ctor");
+ // Check that this hasn't been renamed. This shouldn't happen, because
+ // this function should be called precisely once.
+ assert(InitVar->getName() == ".objc_ctor");
+ // In Windows, initialisers are sorted by the suffix. XCL is for library
+ // initialisers, which run before user initialisers. We are running
+ // Objective-C loads at the end of library load. This means +load methods
+ // will run before any other static constructors, but that static
+ // constructors can see a fully initialised Objective-C state.
+ if (CGM.getTriple().isOSBinFormatCOFF())
+ InitVar->setSection(".CRT$XCLz");
+ else
+ InitVar->setSection(".ctors");
+ InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
+ CGM.addUsedGlobal(InitVar);
+ for (auto *C : Categories) {
+ auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
+ Cat->setSection(sectionName<CategorySection>());
+ CGM.addUsedGlobal(Cat);
+ }
+ auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init,
+ StringRef Section) {
+ auto nullBuilder = builder.beginStruct();
+ for (auto *F : Init)
+ nullBuilder.add(F);
+ auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
+ false, llvm::GlobalValue::LinkOnceODRLinkage);
+ GV->setSection(Section);
+ GV->setComdat(TheModule.getOrInsertComdat(Name));
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ CGM.addUsedGlobal(GV);
+ return GV;
+ };
+ for (auto clsAlias : ClassAliases)
+ createNullGlobal(std::string(".objc_class_alias") +
+ clsAlias.second, { MakeConstantString(clsAlias.second),
+ GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
+ // On ELF platforms, add a null value for each special section so that we
+ // can always guarantee that the _start and _stop symbols will exist and be
+ // meaningful. This is not required on COFF platforms, where our start and
+ // stop symbols will create the section.
+ if (!CGM.getTriple().isOSBinFormatCOFF()) {
+ createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr},
+ sectionName<SelectorSection>());
+ if (Categories.empty())
+ createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
+ sectionName<CategorySection>());
+ if (!EmittedClass) {
+ createNullGlobal(".objc_null_cls_init_ref", NULLPtr,
+ sectionName<ClassReferenceSection>());
+ createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
+ sectionName<ClassReferenceSection>());
+ }
+ if (!EmittedProtocol)
+ createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr}, sectionName<ProtocolSection>());
+ if (!EmittedProtocolRef)
+ createNullGlobal(".objc_null_protocol_ref", {NULLPtr},
+ sectionName<ProtocolReferenceSection>());
+ if (ClassAliases.empty())
+ createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
+ sectionName<ClassAliasSection>());
+ if (ConstantStrings.empty()) {
+ auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
+ createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
+ i32Zero, i32Zero, i32Zero, NULLPtr },
+ sectionName<ConstantStringSection>());
+ }
+ }
+ ConstantStrings.clear();
+ Categories.clear();
+ Classes.clear();
+ return nullptr;
+ }
+ /// In the v2 ABI, ivar offset variables use the type encoding in their name
+ /// to trigger linker failures if the types don't match.
+ std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar) override {
+ std::string TypeEncoding;
+ CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding);
+ // Prevent the @ from being interpreted as a symbol version.
+ std::replace(TypeEncoding.begin(), TypeEncoding.end(),
+ '@', '\1');
+ const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
+ + '.' + Ivar->getNameAsString() + '.' + TypeEncoding;
+ return Name;
+ }
+ llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar) override {
+ const std::string Name = GetIVarOffsetVariableName(Ivar->getContainingInterface(), Ivar);
+ llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
+ if (!IvarOffsetPointer)
+ IvarOffsetPointer = new llvm::GlobalVariable(TheModule, IntTy, false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, Name);
+ CharUnits Align = CGM.getIntAlign();
+ llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(IvarOffsetPointer, Align);
+ if (Offset->getType() != PtrDiffTy)
+ Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
+ return Offset;
+ }
+ void GenerateClass(const ObjCImplementationDecl *OID) override {
+ ASTContext &Context = CGM.getContext();
+
+ // Get the class name
+ ObjCInterfaceDecl *classDecl =
+ const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
+ std::string className = classDecl->getNameAsString();
+ auto *classNameConstant = MakeConstantString(className);
+
+ ConstantInitBuilder builder(CGM);
+ auto metaclassFields = builder.beginStruct();
+ // struct objc_class *isa;
+ metaclassFields.addNullPointer(PtrTy);
+ // struct objc_class *super_class;
+ metaclassFields.addNullPointer(PtrTy);
+ // const char *name;
+ metaclassFields.add(classNameConstant);
+ // long version;
+ metaclassFields.addInt(LongTy, 0);
+ // unsigned long info;
+ // objc_class_flag_meta
+ metaclassFields.addInt(LongTy, 1);
+ // long instance_size;
+ // Setting this to zero is consistent with the older ABI, but it might be
+ // more sensible to set this to sizeof(struct objc_class)
+ metaclassFields.addInt(LongTy, 0);
+ // struct objc_ivar_list *ivars;
+ metaclassFields.addNullPointer(PtrTy);
+ // struct objc_method_list *methods
+ // FIXME: Almost identical code is copied and pasted below for the
+ // class, but refactoring it cleanly requires C++14 generic lambdas.
+ if (OID->classmeth_begin() == OID->classmeth_end())
+ metaclassFields.addNullPointer(PtrTy);
+ else {
+ SmallVector<ObjCMethodDecl*, 16> ClassMethods;
+ ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
+ OID->classmeth_end());
+ metaclassFields.addBitCast(
+ GenerateMethodList(className, "", ClassMethods, true),
+ PtrTy);
+ }
+ // void *dtable;
+ metaclassFields.addNullPointer(PtrTy);
+ // IMP cxx_construct;
+ metaclassFields.addNullPointer(PtrTy);
+ // IMP cxx_destruct;
+ metaclassFields.addNullPointer(PtrTy);
+ // struct objc_class *subclass_list
+ metaclassFields.addNullPointer(PtrTy);
+ // struct objc_class *sibling_class
+ metaclassFields.addNullPointer(PtrTy);
+ // struct objc_protocol_list *protocols;
+ metaclassFields.addNullPointer(PtrTy);
+ // struct reference_list *extra_data;
+ metaclassFields.addNullPointer(PtrTy);
+ // long abi_version;
+ metaclassFields.addInt(LongTy, 0);
+ // struct objc_property_list *properties
+ metaclassFields.add(GeneratePropertyList(OID, classDecl, /*isClassProperty*/true));
+
+ auto *metaclass = metaclassFields.finishAndCreateGlobal("._OBJC_METACLASS_"
+ + className, CGM.getPointerAlign());
+
+ auto classFields = builder.beginStruct();
+ // struct objc_class *isa;
+ classFields.add(metaclass);
+ // struct objc_class *super_class;
+ // Get the superclass name.
+ const ObjCInterfaceDecl * SuperClassDecl =
+ OID->getClassInterface()->getSuperClass();
+ if (SuperClassDecl) {
+ auto SuperClassName = SymbolForClass(SuperClassDecl->getNameAsString());
+ llvm::Constant *SuperClass = TheModule.getNamedGlobal(SuperClassName);
+ if (!SuperClass)
+ {
+ SuperClass = new llvm::GlobalVariable(TheModule, PtrTy, false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, SuperClassName);
+ }
+ classFields.add(llvm::ConstantExpr::getBitCast(SuperClass, PtrTy));
+ } else
+ classFields.addNullPointer(PtrTy);
+ // const char *name;
+ classFields.add(classNameConstant);
+ // long version;
+ classFields.addInt(LongTy, 0);
+ // unsigned long info;
+ // !objc_class_flag_meta
+ classFields.addInt(LongTy, 0);
+ // long instance_size;
+ int superInstanceSize = !SuperClassDecl ? 0 :
+ Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
+ // Instance size is negative for classes that have not yet had their ivar
+ // layout calculated.
+ classFields.addInt(LongTy,
+ 0 - (Context.getASTObjCImplementationLayout(OID).getSize().getQuantity() -
+ superInstanceSize));
+
+ if (classDecl->all_declared_ivar_begin() == nullptr)
+ classFields.addNullPointer(PtrTy);
+ else {
+ int ivar_count = 0;
+ for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
+ IVD = IVD->getNextIvar()) ivar_count++;
+ llvm::DataLayout td(&TheModule);
+ // struct objc_ivar_list *ivars;
+ ConstantInitBuilder b(CGM);
+ auto ivarListBuilder = b.beginStruct();
+ // int count;
+ ivarListBuilder.addInt(IntTy, ivar_count);
+ // size_t size;
+ llvm::StructType *ObjCIvarTy = llvm::StructType::get(
+ PtrToInt8Ty,
+ PtrToInt8Ty,
+ PtrToInt8Ty,
+ Int32Ty,
+ Int32Ty);
+ ivarListBuilder.addInt(SizeTy, td.getTypeSizeInBits(ObjCIvarTy) /
+ CGM.getContext().getCharWidth());
+ // struct objc_ivar ivars[]
+ auto ivarArrayBuilder = ivarListBuilder.beginArray();
+ CodeGenTypes &Types = CGM.getTypes();
+ for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
+ IVD = IVD->getNextIvar()) {
+ auto ivarTy = IVD->getType();
+ auto ivarBuilder = ivarArrayBuilder.beginStruct();
+ // const char *name;
+ ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
+ // const char *type;
+ std::string TypeStr;
+ //Context.getObjCEncodingForType(ivarTy, TypeStr, IVD, true);
+ Context.getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, ivarTy, TypeStr, true);
+ ivarBuilder.add(MakeConstantString(TypeStr));
+ // int *offset;
+ uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
+ uint64_t Offset = BaseOffset - superInstanceSize;
+ llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
+ std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
+ llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
+ if (OffsetVar)
+ OffsetVar->setInitializer(OffsetValue);
+ else
+ OffsetVar = new llvm::GlobalVariable(TheModule, IntTy,
+ false, llvm::GlobalValue::ExternalLinkage,
+ OffsetValue, OffsetName);
+ auto ivarVisibility =
+ (IVD->getAccessControl() == ObjCIvarDecl::Private ||
+ IVD->getAccessControl() == ObjCIvarDecl::Package ||
+ classDecl->getVisibility() == HiddenVisibility) ?
+ llvm::GlobalValue::HiddenVisibility :
+ llvm::GlobalValue::DefaultVisibility;
+ OffsetVar->setVisibility(ivarVisibility);
+ ivarBuilder.add(OffsetVar);
+ // Ivar size
+ ivarBuilder.addInt(Int32Ty,
+ td.getTypeSizeInBits(Types.ConvertType(ivarTy)) /
+ CGM.getContext().getCharWidth());
+ // Alignment will be stored as a base-2 log of the alignment.
+ int align = llvm::Log2_32(Context.getTypeAlignInChars(ivarTy).getQuantity());
+ // Objects that require more than 2^64-byte alignment should be impossible!
+ assert(align < 64);
+ // uint32_t flags;
+ // Bits 0-1 are ownership.
+ // Bit 2 indicates an extended type encoding
+ // Bits 3-8 contain log2(aligment)
+ ivarBuilder.addInt(Int32Ty,
+ (align << 3) | (1<<2) |
+ FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
+ ivarBuilder.finishAndAddTo(ivarArrayBuilder);
+ }
+ ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
+ auto ivarList = ivarListBuilder.finishAndCreateGlobal(".objc_ivar_list",
+ CGM.getPointerAlign(), /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ classFields.add(ivarList);
+ }
+ // struct objc_method_list *methods
+ SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
+ InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
+ OID->instmeth_end());
+ for (auto *propImpl : OID->property_impls())
+ if (propImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Synthesize) {
+ ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
+ auto addIfExists = [&](const ObjCMethodDecl* OMD) {
+ if (OMD)
+ InstanceMethods.push_back(OMD);
+ };
+ addIfExists(prop->getGetterMethodDecl());
+ addIfExists(prop->getSetterMethodDecl());
+ }
+
+ if (InstanceMethods.size() == 0)
+ classFields.addNullPointer(PtrTy);
+ else
+ classFields.addBitCast(
+ GenerateMethodList(className, "", InstanceMethods, false),
+ PtrTy);
+ // void *dtable;
+ classFields.addNullPointer(PtrTy);
+ // IMP cxx_construct;
+ classFields.addNullPointer(PtrTy);
+ // IMP cxx_destruct;
+ classFields.addNullPointer(PtrTy);
+ // struct objc_class *subclass_list
+ classFields.addNullPointer(PtrTy);
+ // struct objc_class *sibling_class
+ classFields.addNullPointer(PtrTy);
+ // struct objc_protocol_list *protocols;
+ SmallVector<llvm::Constant*, 16> Protocols;
+ for (const auto *I : classDecl->protocols())
+ Protocols.push_back(
+ llvm::ConstantExpr::getBitCast(GenerateProtocolRef(I),
+ ProtocolPtrTy));
+ if (Protocols.empty())
+ classFields.addNullPointer(PtrTy);
+ else
+ classFields.add(GenerateProtocolList(Protocols));
+ // struct reference_list *extra_data;
+ classFields.addNullPointer(PtrTy);
+ // long abi_version;
+ classFields.addInt(LongTy, 0);
+ // struct objc_property_list *properties
+ classFields.add(GeneratePropertyList(OID, classDecl));
+
+ auto *classStruct =
+ classFields.finishAndCreateGlobal(SymbolForClass(className),
+ CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
+
+ if (CGM.getTriple().isOSBinFormatCOFF()) {
+ auto Storage = llvm::GlobalValue::DefaultStorageClass;
+ if (OID->getClassInterface()->hasAttr<DLLImportAttr>())
+ Storage = llvm::GlobalValue::DLLImportStorageClass;
+ else if (OID->getClassInterface()->hasAttr<DLLExportAttr>())
+ Storage = llvm::GlobalValue::DLLExportStorageClass;
+ cast<llvm::GlobalValue>(classStruct)->setDLLStorageClass(Storage);
+ }
+
+ auto *classRefSymbol = GetClassVar(className);
+ classRefSymbol->setSection(sectionName<ClassReferenceSection>());
+ classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy));
+
+
+ // Resolve the class aliases, if they exist.
+ // FIXME: Class pointer aliases shouldn't exist!
+ if (ClassPtrAlias) {
+ ClassPtrAlias->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(classStruct, IdTy));
+ ClassPtrAlias->eraseFromParent();
+ ClassPtrAlias = nullptr;
+ }
+ if (auto Placeholder =
+ TheModule.getNamedGlobal(SymbolForClass(className)))
+ if (Placeholder != classStruct) {
+ Placeholder->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(classStruct, Placeholder->getType()));
+ Placeholder->eraseFromParent();
+ classStruct->setName(SymbolForClass(className));
+ }
+ if (MetaClassPtrAlias) {
+ MetaClassPtrAlias->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(metaclass, IdTy));
+ MetaClassPtrAlias->eraseFromParent();
+ MetaClassPtrAlias = nullptr;
+ }
+ assert(classStruct->getName() == SymbolForClass(className));
+
+ auto classInitRef = new llvm::GlobalVariable(TheModule,
+ classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage,
+ classStruct, "._OBJC_INIT_CLASS_" + className);
+ classInitRef->setSection(sectionName<ClassSection>());
+ CGM.addUsedGlobal(classInitRef);
+
+ EmittedClass = true;
+ }
+ public:
+ CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
+ MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
+ PtrToObjCSuperTy, SelectorTy);
+ // struct objc_property
+ // {
+ // const char *name;
+ // const char *attributes;
+ // const char *type;
+ // SEL getter;
+ // SEL setter;
+ // }
+ PropertyMetadataTy =
+ llvm::StructType::get(CGM.getLLVMContext(),
+ { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
+ }
+
+};
+
+const char *const CGObjCGNUstep2::SectionsBaseNames[8] =
+{
+"__objc_selectors",
+"__objc_classes",
+"__objc_class_refs",
+"__objc_cats",
+"__objc_protocols",
+"__objc_protocol_refs",
+"__objc_class_aliases",
+"__objc_constant_string"
+};
+
/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
@@ -878,24 +1999,16 @@ void CGObjCGNU::EmitClassRef(const std::string &className) {
llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
}
-static std::string SymbolNameForMethod( StringRef ClassName,
- StringRef CategoryName, const Selector MethodName,
- bool isClassMethod) {
- std::string MethodNameColonStripped = MethodName.getAsString();
- std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
- ':', '_');
- return (Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
- CategoryName + "_" + MethodNameColonStripped).str();
-}
-
CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
- unsigned protocolClassVersion)
+ unsigned protocolClassVersion, unsigned classABI)
: CGObjCRuntime(cgm), TheModule(CGM.getModule()),
VMContext(cgm.getLLVMContext()), ClassPtrAlias(nullptr),
MetaClassPtrAlias(nullptr), RuntimeVersion(runtimeABIVersion),
- ProtocolVersion(protocolClassVersion) {
+ ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
+ usesSEHExceptions =
+ cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
CodeGenTypes &Types = CGM.getTypes();
IntTy = cast<llvm::IntegerType>(
@@ -911,6 +2024,8 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
Int8Ty = llvm::Type::getInt8Ty(VMContext);
// C string type. Used in lots of places.
PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
+ ProtocolPtrTy = llvm::PointerType::getUnqual(
+ Types.ConvertType(CGM.getContext().getObjCProtoType()));
Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
Zeros[1] = Zeros[0];
@@ -942,6 +2057,31 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
IdTy = PtrToInt8Ty;
}
PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
+ ProtocolTy = llvm::StructType::get(IdTy,
+ PtrToInt8Ty, // name
+ PtrToInt8Ty, // protocols
+ PtrToInt8Ty, // instance methods
+ PtrToInt8Ty, // class methods
+ PtrToInt8Ty, // optional instance methods
+ PtrToInt8Ty, // optional class methods
+ PtrToInt8Ty, // properties
+ PtrToInt8Ty);// optional properties
+
+ // struct objc_property_gsv1
+ // {
+ // const char *name;
+ // char attributes;
+ // char attributes2;
+ // char unused1;
+ // char unused2;
+ // const char *getter_name;
+ // const char *getter_types;
+ // const char *setter_name;
+ // const char *setter_types;
+ // }
+ PropertyMetadataTy = llvm::StructType::get(CGM.getLLVMContext(), {
+ PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
+ PtrToInt8Ty, PtrToInt8Ty });
ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy);
@@ -1035,16 +2175,8 @@ llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
const ObjCInterfaceDecl *OID) {
auto *Value =
GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) {
- auto DLLStorage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->hasAttr<DLLExportAttr>())
- DLLStorage = llvm::GlobalValue::DLLExportStorageClass;
- else if (OID->hasAttr<DLLImportAttr>())
- DLLStorage = llvm::GlobalValue::DLLImportStorageClass;
- ClassSymbol->setDLLStorageClass(DLLStorage);
- }
- }
+ if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value))
+ CGM.setGVProperties(ClassSymbol, OID);
return Value;
}
@@ -1061,20 +2193,14 @@ llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
if ((VD = dyn_cast<VarDecl>(Result)))
break;
- auto DLLStorage = llvm::GlobalValue::DefaultStorageClass;
- if (!VD || VD->hasAttr<DLLImportAttr>())
- DLLStorage = llvm::GlobalValue::DLLImportStorageClass;
- else if (VD->hasAttr<DLLExportAttr>())
- DLLStorage = llvm::GlobalValue::DLLExportStorageClass;
-
- ClassSymbol->setDLLStorageClass(DLLStorage);
+ CGM.setGVProperties(ClassSymbol, VD);
}
}
return Value;
}
-llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding) {
+llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding) {
SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
llvm::GlobalAlias *SelValue = nullptr;
@@ -1107,13 +2233,13 @@ Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
- return GetSelector(CGF, Sel, std::string());
+ return GetTypedSelector(CGF, Sel, std::string());
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) {
std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method);
- return GetSelector(CGF, Method->getSelector(), SelTypes);
+ return GetTypedSelector(CGF, Method->getSelector(), SelTypes);
}
llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
@@ -1138,6 +2264,9 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
}
llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
+ if (usesSEHExceptions)
+ return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);
+
if (!CGM.getLangOpts().CPlusPlus)
return CGObjCGNU::GetEHType(T);
@@ -1217,7 +2346,7 @@ ConstantAddress CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
- if (StringClass.empty()) StringClass = "NXConstantString";
+ if (StringClass.empty()) StringClass = "NSConstantString";
std::string Sym = "_OBJC_CLASS_";
Sym += StringClass;
@@ -1278,54 +2407,67 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
llvm::Value *ReceiverClass = nullptr;
- if (isCategoryImpl) {
- llvm::Constant *classLookupFunction = nullptr;
+ bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
+ if (isV2ABI) {
+ ReceiverClass = GetClassNamed(CGF,
+ Class->getSuperClass()->getNameAsString(), /*isWeak*/false);
if (IsClassMessage) {
- classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
- IdTy, PtrTy, true), "objc_get_meta_class");
- } else {
- classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
- IdTy, PtrTy, true), "objc_get_class");
+ // Load the isa pointer of the superclass is this is a class method.
+ ReceiverClass = Builder.CreateBitCast(ReceiverClass,
+ llvm::PointerType::getUnqual(IdTy));
+ ReceiverClass =
+ Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
}
- ReceiverClass = Builder.CreateCall(classLookupFunction,
- MakeConstantString(Class->getNameAsString()));
+ ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
} else {
- // Set up global aliases for the metaclass or class pointer if they do not
- // already exist. These will are forward-references which will be set to
- // pointers to the class and metaclass structure created for the runtime
- // load function. To send a message to super, we look up the value of the
- // super_class pointer from either the class or metaclass structure.
- if (IsClassMessage) {
- if (!MetaClassPtrAlias) {
- MetaClassPtrAlias = llvm::GlobalAlias::create(
- IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
- ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
+ if (isCategoryImpl) {
+ llvm::Constant *classLookupFunction = nullptr;
+ if (IsClassMessage) {
+ classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ IdTy, PtrTy, true), "objc_get_meta_class");
+ } else {
+ classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ IdTy, PtrTy, true), "objc_get_class");
}
- ReceiverClass = MetaClassPtrAlias;
+ ReceiverClass = Builder.CreateCall(classLookupFunction,
+ MakeConstantString(Class->getNameAsString()));
} else {
- if (!ClassPtrAlias) {
- ClassPtrAlias = llvm::GlobalAlias::create(
- IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
- ".objc_class_ref" + Class->getNameAsString(), &TheModule);
+ // Set up global aliases for the metaclass or class pointer if they do not
+ // already exist. These will are forward-references which will be set to
+ // pointers to the class and metaclass structure created for the runtime
+ // load function. To send a message to super, we look up the value of the
+ // super_class pointer from either the class or metaclass structure.
+ if (IsClassMessage) {
+ if (!MetaClassPtrAlias) {
+ MetaClassPtrAlias = llvm::GlobalAlias::create(
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
+ }
+ ReceiverClass = MetaClassPtrAlias;
+ } else {
+ if (!ClassPtrAlias) {
+ ClassPtrAlias = llvm::GlobalAlias::create(
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ ".objc_class_ref" + Class->getNameAsString(), &TheModule);
+ }
+ ReceiverClass = ClassPtrAlias;
}
- ReceiverClass = ClassPtrAlias;
}
+ // Cast the pointer to a simplified version of the class structure
+ llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
+ ReceiverClass = Builder.CreateBitCast(ReceiverClass,
+ llvm::PointerType::getUnqual(CastTy));
+ // Get the superclass pointer
+ ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
+ // Load the superclass pointer
+ ReceiverClass =
+ Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
}
- // Cast the pointer to a simplified version of the class structure
- llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
- ReceiverClass = Builder.CreateBitCast(ReceiverClass,
- llvm::PointerType::getUnqual(CastTy));
- // Get the superclass pointer
- ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
- // Load the superclass pointer
- ReceiverClass =
- Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
// Construct the structure used to look up the IMP
llvm::StructType *ObjCSuperTy =
llvm::StructType::get(Receiver->getType(), IdTy);
- // FIXME: Is this really supposed to be a dynamic alloca?
- Address ObjCSuper = Address(Builder.CreateAlloca(ObjCSuperTy),
+ Address ObjCSuper = CGF.CreateTempAlloca(ObjCSuperTy,
CGF.getPointerAlign());
Builder.CreateStore(Receiver,
@@ -1387,7 +2529,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
// returns. With GCC, this generates a random return value (whatever happens
// to be on the stack / in those registers at the time) on most platforms,
// and generates an illegal instruction trap on SPARC. With LLVM it corrupts
- // the stack.
+ // the stack.
bool isPointerSizedReturn = (ResultType->isAnyPointerType() ||
ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType());
@@ -1400,7 +2542,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
messageBB = CGF.createBasicBlock("msgSend");
continueBB = CGF.createBasicBlock("continue");
- llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
+ llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
llvm::Constant::getNullValue(Receiver->getType()));
Builder.CreateCondBr(isNil, continueBB, messageBB);
CGF.EmitBlock(messageBB);
@@ -1434,7 +2576,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
// If we have non-legacy dispatch specified, we try using the objc_msgSend()
// functions. These are not supported on all platforms (or all runtimes on a
- // given platform), so we
+ // given platform), so we
switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
case CodeGenOptions::Legacy:
imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
@@ -1456,7 +2598,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
}
// Reset the receiver in case the lookup modified it
- ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy, false);
+ ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy);
imp = EnforceType(Builder, imp, MSI.MessengerType);
@@ -1506,17 +2648,16 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
llvm::Constant *CGObjCGNU::
GenerateMethodList(StringRef ClassName,
StringRef CategoryName,
- ArrayRef<Selector> MethodSels,
- ArrayRef<llvm::Constant *> MethodTypes,
+ ArrayRef<const ObjCMethodDecl*> Methods,
bool isClassMethodList) {
- if (MethodSels.empty())
+ if (Methods.empty())
return NULLPtr;
ConstantInitBuilder Builder(CGM);
auto MethodList = Builder.beginStruct();
MethodList.addNullPointer(CGM.Int8PtrTy);
- MethodList.addInt(Int32Ty, MethodTypes.size());
+ MethodList.addInt(Int32Ty, Methods.size());
// Get the method structure type.
llvm::StructType *ObjCMethodTy =
@@ -1525,20 +2666,48 @@ GenerateMethodList(StringRef ClassName,
PtrToInt8Ty, // Method types
IMPTy // Method pointer
});
- auto Methods = MethodList.beginArray();
- for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
+ bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
+ if (isV2ABI) {
+ // size_t size;
+ llvm::DataLayout td(&TheModule);
+ MethodList.addInt(SizeTy, td.getTypeSizeInBits(ObjCMethodTy) /
+ CGM.getContext().getCharWidth());
+ ObjCMethodTy =
+ llvm::StructType::get(CGM.getLLVMContext(), {
+ IMPTy, // Method pointer
+ PtrToInt8Ty, // Selector
+ PtrToInt8Ty // Extended type encoding
+ });
+ } else {
+ ObjCMethodTy =
+ llvm::StructType::get(CGM.getLLVMContext(), {
+ PtrToInt8Ty, // Really a selector, but the runtime creates it us.
+ PtrToInt8Ty, // Method types
+ IMPTy // Method pointer
+ });
+ }
+ auto MethodArray = MethodList.beginArray();
+ ASTContext &Context = CGM.getContext();
+ for (const auto *OMD : Methods) {
llvm::Constant *FnPtr =
TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
- MethodSels[i],
+ OMD->getSelector(),
isClassMethodList));
assert(FnPtr && "Can't generate metadata for method that doesn't exist");
- auto Method = Methods.beginStruct(ObjCMethodTy);
- Method.add(MakeConstantString(MethodSels[i].getAsString()));
- Method.add(MethodTypes[i]);
- Method.addBitCast(FnPtr, IMPTy);
- Method.finishAndAddTo(Methods);
+ auto Method = MethodArray.beginStruct(ObjCMethodTy);
+ if (isV2ABI) {
+ Method.addBitCast(FnPtr, IMPTy);
+ Method.add(GetConstantSelector(OMD->getSelector(),
+ Context.getObjCEncodingForMethodDecl(OMD)));
+ Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD, true)));
+ } else {
+ Method.add(MakeConstantString(OMD->getSelector().getAsString()));
+ Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD)));
+ Method.addBitCast(FnPtr, IMPTy);
+ }
+ Method.finishAndAddTo(MethodArray);
}
- Methods.finishAndAddTo(MethodList);
+ MethodArray.finishAndAddTo(MethodList);
// Create an instance of the structure
return MethodList.finishAndCreateGlobal(".objc_method_list",
@@ -1549,7 +2718,9 @@ GenerateMethodList(StringRef ClassName,
llvm::Constant *CGObjCGNU::
GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
ArrayRef<llvm::Constant *> IvarTypes,
- ArrayRef<llvm::Constant *> IvarOffsets) {
+ ArrayRef<llvm::Constant *> IvarOffsets,
+ ArrayRef<llvm::Constant *> IvarAlign,
+ ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
if (IvarNames.empty())
return NULLPtr;
@@ -1630,7 +2801,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
// Fill in the structure
- // isa
+ // isa
Elements.addBitCast(MetaClass, PtrToInt8Ty);
// super_class
Elements.add(SuperClass);
@@ -1664,7 +2835,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
// gc_object_type
Elements.add(NULLPtr);
// abi_version
- Elements.addInt(LongTy, 1);
+ Elements.addInt(LongTy, ClassABIVersion);
// ivar_offsets
Elements.add(IvarOffsets);
// properties
@@ -1693,22 +2864,22 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
}
llvm::Constant *CGObjCGNU::
-GenerateProtocolMethodList(ArrayRef<llvm::Constant *> MethodNames,
- ArrayRef<llvm::Constant *> MethodTypes) {
+GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
// Get the method structure type.
llvm::StructType *ObjCMethodDescTy =
llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
+ ASTContext &Context = CGM.getContext();
ConstantInitBuilder Builder(CGM);
auto MethodList = Builder.beginStruct();
- MethodList.addInt(IntTy, MethodNames.size());
- auto Methods = MethodList.beginArray(ObjCMethodDescTy);
- for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
- auto Method = Methods.beginStruct(ObjCMethodDescTy);
- Method.add(MethodNames[i]);
- Method.add(MethodTypes[i]);
- Method.finishAndAddTo(Methods);
- }
- Methods.finishAndAddTo(MethodList);
+ MethodList.addInt(IntTy, Methods.size());
+ auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
+ for (auto *M : Methods) {
+ auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
+ Method.add(MakeConstantString(M->getSelector().getAsString()));
+ Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(M)));
+ Method.finishAndAddTo(MethodArray);
+ }
+ MethodArray.finishAndAddTo(MethodList);
return MethodList.finishAndCreateGlobal(".objc_method_list",
CGM.getPointerAlign());
}
@@ -1742,16 +2913,19 @@ CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
const ObjCProtocolDecl *PD) {
- llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
+ llvm::Constant *&protocol = ExistingProtocols[PD->getNameAsString()];
+ if (!protocol)
+ GenerateProtocol(PD);
llvm::Type *T =
CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
}
llvm::Constant *
-CGObjCGNU::GenerateEmptyProtocol(const std::string &ProtocolName) {
+CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
llvm::Constant *ProtocolList = GenerateProtocolList({});
- llvm::Constant *MethodList = GenerateProtocolMethodList({}, {});
+ llvm::Constant *MethodList = GenerateProtocolMethodList({});
+ MethodList = llvm::ConstantExpr::getBitCast(MethodList, PtrToInt8Ty);
// Protocols are objects containing lists of the methods implemented and
// protocols adopted.
ConstantInitBuilder Builder(CGM);
@@ -1763,19 +2937,20 @@ CGObjCGNU::GenerateEmptyProtocol(const std::string &ProtocolName) {
llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
Elements.add(MakeConstantString(ProtocolName, ".objc_protocol_name"));
- Elements.add(ProtocolList);
- Elements.add(MethodList);
- Elements.add(MethodList);
- Elements.add(MethodList);
- Elements.add(MethodList);
- return Elements.finishAndCreateGlobal(".objc_protocol",
+ Elements.add(ProtocolList); /* .protocol_list */
+ Elements.add(MethodList); /* .instance_methods */
+ Elements.add(MethodList); /* .class_methods */
+ Elements.add(MethodList); /* .optional_instance_methods */
+ Elements.add(MethodList); /* .optional_class_methods */
+ Elements.add(NULLPtr); /* .properties */
+ Elements.add(NULLPtr); /* .optional_properties */
+ return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
CGM.getPointerAlign());
}
void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
- ASTContext &Context = CGM.getContext();
std::string ProtocolName = PD->getNameAsString();
-
+
// Use the protocol definition, if there is one.
if (const ObjCProtocolDecl *Def = PD->getDefinition())
PD = Def;
@@ -1783,51 +2958,31 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
SmallVector<std::string, 16> Protocols;
for (const auto *PI : PD->protocols())
Protocols.push_back(PI->getNameAsString());
- SmallVector<llvm::Constant*, 16> InstanceMethodNames;
- SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
- SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
- SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
- for (const auto *I : PD->instance_methods()) {
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
- if (I->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptionalInstanceMethodNames.push_back(
- MakeConstantString(I->getSelector().getAsString()));
- OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
- } else {
- InstanceMethodNames.push_back(
- MakeConstantString(I->getSelector().getAsString()));
- InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
- }
- }
+ SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
+ SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
+ for (const auto *I : PD->instance_methods())
+ if (I->isOptional())
+ OptionalInstanceMethods.push_back(I);
+ else
+ InstanceMethods.push_back(I);
// Collect information about class methods:
- SmallVector<llvm::Constant*, 16> ClassMethodNames;
- SmallVector<llvm::Constant*, 16> ClassMethodTypes;
- SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
- SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
- for (const auto *I : PD->class_methods()) {
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
- if (I->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptionalClassMethodNames.push_back(
- MakeConstantString(I->getSelector().getAsString()));
- OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
- } else {
- ClassMethodNames.push_back(
- MakeConstantString(I->getSelector().getAsString()));
- ClassMethodTypes.push_back(MakeConstantString(TypeStr));
- }
- }
+ SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
+ SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
+ for (const auto *I : PD->class_methods())
+ if (I->isOptional())
+ OptionalClassMethods.push_back(I);
+ else
+ ClassMethods.push_back(I);
llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
llvm::Constant *InstanceMethodList =
- GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
+ GenerateProtocolMethodList(InstanceMethods);
llvm::Constant *ClassMethodList =
- GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
+ GenerateProtocolMethodList(ClassMethods);
llvm::Constant *OptionalInstanceMethodList =
- GenerateProtocolMethodList(OptionalInstanceMethodNames,
- OptionalInstanceMethodTypes);
+ GenerateProtocolMethodList(OptionalInstanceMethods);
llvm::Constant *OptionalClassMethodList =
- GenerateProtocolMethodList(OptionalClassMethodNames,
- OptionalClassMethodTypes);
+ GenerateProtocolMethodList(OptionalClassMethods);
// Property metadata: name, attributes, isSynthesized, setter name, setter
// types, getter name, getter types.
@@ -1835,78 +2990,10 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
// simplify the runtime library by allowing it to use the same data
// structures for protocol metadata everywhere.
- llvm::Constant *PropertyList;
- llvm::Constant *OptionalPropertyList;
- {
- llvm::StructType *propertyMetadataTy =
- llvm::StructType::get(CGM.getLLVMContext(),
- { PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
-
- unsigned numReqProperties = 0, numOptProperties = 0;
- for (auto property : PD->instance_properties()) {
- if (property->isOptional())
- numOptProperties++;
- else
- numReqProperties++;
- }
-
- ConstantInitBuilder reqPropertyListBuilder(CGM);
- auto reqPropertiesList = reqPropertyListBuilder.beginStruct();
- reqPropertiesList.addInt(IntTy, numReqProperties);
- reqPropertiesList.add(NULLPtr);
- auto reqPropertiesArray = reqPropertiesList.beginArray(propertyMetadataTy);
-
- ConstantInitBuilder optPropertyListBuilder(CGM);
- auto optPropertiesList = optPropertyListBuilder.beginStruct();
- optPropertiesList.addInt(IntTy, numOptProperties);
- optPropertiesList.add(NULLPtr);
- auto optPropertiesArray = optPropertiesList.beginArray(propertyMetadataTy);
-
- // Add all of the property methods need adding to the method list and to the
- // property metadata list.
- for (auto *property : PD->instance_properties()) {
- auto &propertiesArray =
- (property->isOptional() ? optPropertiesArray : reqPropertiesArray);
- auto fields = propertiesArray.beginStruct(propertyMetadataTy);
-
- fields.add(MakePropertyEncodingString(property, nullptr));
- PushPropertyAttributes(fields, property);
-
- if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
- std::string typeStr = Context.getObjCEncodingForMethodDecl(getter);
- llvm::Constant *typeEncoding = MakeConstantString(typeStr);
- InstanceMethodTypes.push_back(typeEncoding);
- fields.add(MakeConstantString(getter->getSelector().getAsString()));
- fields.add(typeEncoding);
- } else {
- fields.add(NULLPtr);
- fields.add(NULLPtr);
- }
- if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
- std::string typeStr = Context.getObjCEncodingForMethodDecl(setter);
- llvm::Constant *typeEncoding = MakeConstantString(typeStr);
- InstanceMethodTypes.push_back(typeEncoding);
- fields.add(MakeConstantString(setter->getSelector().getAsString()));
- fields.add(typeEncoding);
- } else {
- fields.add(NULLPtr);
- fields.add(NULLPtr);
- }
-
- fields.finishAndAddTo(propertiesArray);
- }
-
- reqPropertiesArray.finishAndAddTo(reqPropertiesList);
- PropertyList =
- reqPropertiesList.finishAndCreateGlobal(".objc_property_list",
- CGM.getPointerAlign());
-
- optPropertiesArray.finishAndAddTo(optPropertiesList);
- OptionalPropertyList =
- optPropertiesList.finishAndCreateGlobal(".objc_property_list",
- CGM.getPointerAlign());
- }
+ llvm::Constant *PropertyList =
+ GeneratePropertyList(nullptr, PD, false, false);
+ llvm::Constant *OptionalPropertyList =
+ GeneratePropertyList(nullptr, PD, false, true);
// Protocols are objects containing lists of the methods implemented and
// protocols adopted.
@@ -1917,8 +3004,7 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
Elements.add(
llvm::ConstantExpr::getIntToPtr(
llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
- Elements.add(
- MakeConstantString(ProtocolName, ".objc_protocol_name"));
+ Elements.add(MakeConstantString(ProtocolName));
Elements.add(ProtocolList);
Elements.add(InstanceMethodList);
Elements.add(ClassMethodList);
@@ -1933,8 +3019,6 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
}
void CGObjCGNU::GenerateProtocolHolderCategory() {
// Collect information about instance methods
- SmallVector<Selector, 1> MethodSels;
- SmallVector<llvm::Constant*, 1> MethodTypes;
ConstantInitBuilder Builder(CGM);
auto Elements = Builder.beginStruct();
@@ -1945,10 +3029,10 @@ void CGObjCGNU::GenerateProtocolHolderCategory() {
Elements.add(MakeConstantString(ClassName));
// Instance method list
Elements.addBitCast(GenerateMethodList(
- ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy);
+ ClassName, CategoryName, {}, false), PtrTy);
// Class method list
Elements.addBitCast(GenerateMethodList(
- ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy);
+ ClassName, CategoryName, {}, true), PtrTy);
// Protocol list
ConstantInitBuilder ProtocolListBuilder(CGM);
@@ -1974,7 +3058,7 @@ void CGObjCGNU::GenerateProtocolHolderCategory() {
/// stored in a 64-bit value with the low bit set to 1 and the remaining 63
/// bits set to their values, LSB first, while larger ones are stored in a
/// structure of this / form:
-///
+///
/// struct { int32_t length; int32_t values[length]; };
///
/// The values in the array are stored in host-endian format, with the least
@@ -2016,25 +3100,9 @@ llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
}
void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
- std::string ClassName = OCD->getClassInterface()->getNameAsString();
+ const ObjCInterfaceDecl *Class = OCD->getClassInterface();
+ std::string ClassName = Class->getNameAsString();
std::string CategoryName = OCD->getNameAsString();
- // Collect information about instance methods
- SmallVector<Selector, 16> InstanceMethodSels;
- SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
- for (const auto *I : OCD->instance_methods()) {
- InstanceMethodSels.push_back(I->getSelector());
- std::string TypeStr = CGM.getContext().getObjCEncodingForMethodDecl(I);
- InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
- }
-
- // Collect information about class methods
- SmallVector<Selector, 16> ClassMethodSels;
- SmallVector<llvm::Constant*, 16> ClassMethodTypes;
- for (const auto *I : OCD->class_methods()) {
- ClassMethodSels.push_back(I->getSelector());
- std::string TypeStr = CGM.getContext().getObjCEncodingForMethodDecl(I);
- ClassMethodTypes.push_back(MakeConstantString(TypeStr));
- }
// Collect the names of referenced protocols
SmallVector<std::string, 16> Protocols;
@@ -2049,84 +3117,125 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Elements.add(MakeConstantString(CategoryName));
Elements.add(MakeConstantString(ClassName));
// Instance method list
+ SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
+ InstanceMethods.insert(InstanceMethods.begin(), OCD->instmeth_begin(),
+ OCD->instmeth_end());
Elements.addBitCast(
- GenerateMethodList(ClassName, CategoryName, InstanceMethodSels,
- InstanceMethodTypes, false),
+ GenerateMethodList(ClassName, CategoryName, InstanceMethods, false),
PtrTy);
// Class method list
+
+ SmallVector<ObjCMethodDecl*, 16> ClassMethods;
+ ClassMethods.insert(ClassMethods.begin(), OCD->classmeth_begin(),
+ OCD->classmeth_end());
Elements.addBitCast(
- GenerateMethodList(ClassName, CategoryName, ClassMethodSels,
- ClassMethodTypes, true),
+ GenerateMethodList(ClassName, CategoryName, ClassMethods, true),
PtrTy);
// Protocol list
Elements.addBitCast(GenerateProtocolList(Protocols), PtrTy);
+ if (isRuntime(ObjCRuntime::GNUstep, 2)) {
+ const ObjCCategoryDecl *Category =
+ Class->FindCategoryDeclaration(OCD->getIdentifier());
+ if (Category) {
+ // Instance properties
+ Elements.addBitCast(GeneratePropertyList(OCD, Category, false), PtrTy);
+ // Class properties
+ Elements.addBitCast(GeneratePropertyList(OCD, Category, true), PtrTy);
+ } else {
+ Elements.addNullPointer(PtrTy);
+ Elements.addNullPointer(PtrTy);
+ }
+ }
+
Categories.push_back(llvm::ConstantExpr::getBitCast(
- Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
+ Elements.finishAndCreateGlobal(
+ std::string(".objc_category_")+ClassName+CategoryName,
+ CGM.getPointerAlign()),
PtrTy));
}
-llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
- SmallVectorImpl<Selector> &InstanceMethodSels,
- SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) {
+llvm::Constant *CGObjCGNU::GeneratePropertyList(const Decl *Container,
+ const ObjCContainerDecl *OCD,
+ bool isClassProperty,
+ bool protocolOptionalProperties) {
+
+ SmallVector<const ObjCPropertyDecl *, 16> Properties;
+ llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
+ bool isProtocol = isa<ObjCProtocolDecl>(OCD);
ASTContext &Context = CGM.getContext();
- // Property metadata: name, attributes, attributes2, padding1, padding2,
- // setter name, setter types, getter name, getter types.
- llvm::StructType *propertyMetadataTy =
- llvm::StructType::get(CGM.getLLVMContext(),
- { PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
- unsigned numProperties = 0;
- for (auto *propertyImpl : OID->property_impls()) {
- (void) propertyImpl;
- numProperties++;
+ std::function<void(const ObjCProtocolDecl *Proto)> collectProtocolProperties
+ = [&](const ObjCProtocolDecl *Proto) {
+ for (const auto *P : Proto->protocols())
+ collectProtocolProperties(P);
+ for (const auto *PD : Proto->properties()) {
+ if (isClassProperty != PD->isClassProperty())
+ continue;
+ // Skip any properties that are declared in protocols that this class
+ // conforms to but are not actually implemented by this class.
+ if (!isProtocol && !Context.getObjCPropertyImplDeclForPropertyDecl(PD, Container))
+ continue;
+ if (!PropertySet.insert(PD->getIdentifier()).second)
+ continue;
+ Properties.push_back(PD);
+ }
+ };
+
+ if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
+ for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
+ for (auto *PD : ClassExt->properties()) {
+ if (isClassProperty != PD->isClassProperty())
+ continue;
+ PropertySet.insert(PD->getIdentifier());
+ Properties.push_back(PD);
+ }
+
+ for (const auto *PD : OCD->properties()) {
+ if (isClassProperty != PD->isClassProperty())
+ continue;
+ // If we're generating a list for a protocol, skip optional / required ones
+ // when generating the other list.
+ if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
+ continue;
+ // Don't emit duplicate metadata for properties that were already in a
+ // class extension.
+ if (!PropertySet.insert(PD->getIdentifier()).second)
+ continue;
+
+ Properties.push_back(PD);
}
+ if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
+ for (const auto *P : OID->all_referenced_protocols())
+ collectProtocolProperties(P);
+ else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
+ for (const auto *P : CD->protocols())
+ collectProtocolProperties(P);
+
+ auto numProperties = Properties.size();
+
+ if (numProperties == 0)
+ return NULLPtr;
+
ConstantInitBuilder builder(CGM);
auto propertyList = builder.beginStruct();
- propertyList.addInt(IntTy, numProperties);
- propertyList.add(NULLPtr);
- auto properties = propertyList.beginArray(propertyMetadataTy);
+ auto properties = PushPropertyListHeader(propertyList, numProperties);
// Add all of the property methods need adding to the method list and to the
// property metadata list.
- for (auto *propertyImpl : OID->property_impls()) {
- auto fields = properties.beginStruct(propertyMetadataTy);
- ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
- bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Synthesize);
- bool isDynamic = (propertyImpl->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Dynamic);
-
- fields.add(MakePropertyEncodingString(property, OID));
- PushPropertyAttributes(fields, property, isSynthesized, isDynamic);
- if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(getter);
- llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- if (isSynthesized) {
- InstanceMethodTypes.push_back(TypeEncoding);
- InstanceMethodSels.push_back(getter->getSelector());
- }
- fields.add(MakeConstantString(getter->getSelector().getAsString()));
- fields.add(TypeEncoding);
- } else {
- fields.add(NULLPtr);
- fields.add(NULLPtr);
- }
- if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(setter);
- llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- if (isSynthesized) {
- InstanceMethodTypes.push_back(TypeEncoding);
- InstanceMethodSels.push_back(setter->getSelector());
+ for (auto *property : Properties) {
+ bool isSynthesized = false;
+ bool isDynamic = false;
+ if (!isProtocol) {
+ auto *propertyImpl = Context.getObjCPropertyImplDeclForPropertyDecl(property, Container);
+ if (propertyImpl) {
+ isSynthesized = (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Synthesize);
+ isDynamic = (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Dynamic);
}
- fields.add(MakeConstantString(setter->getSelector().getAsString()));
- fields.add(TypeEncoding);
- } else {
- fields.add(NULLPtr);
- fields.add(NULLPtr);
}
- fields.finishAndAddTo(properties);
+ PushProperty(properties, property, Container, isSynthesized, isDynamic);
}
properties.finishAndAddTo(propertyList);
@@ -2172,13 +3281,15 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
}
// Get the size of instances.
- int instanceSize =
+ int instanceSize =
Context.getASTObjCImplementationLayout(OID).getSize().getQuantity();
// Collect information about instance variables.
SmallVector<llvm::Constant*, 16> IvarNames;
SmallVector<llvm::Constant*, 16> IvarTypes;
SmallVector<llvm::Constant*, 16> IvarOffsets;
+ SmallVector<llvm::Constant*, 16> IvarAligns;
+ SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
ConstantInitBuilder IvarOffsetBuilder(CGM);
auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
@@ -2201,6 +3312,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
std::string TypeStr;
Context.getObjCEncodingForType(IVD->getType(), TypeStr, IVD);
IvarTypes.push_back(MakeConstantString(TypeStr));
+ IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
+ Context.getTypeSize(IVD->getType())));
// Get the offset
uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
uint64_t Offset = BaseOffset;
@@ -2211,6 +3324,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
// Create the direct offset value
std::string OffsetName = "__objc_ivar_offset_value_" + ClassName +"." +
IVD->getNameAsString();
+
llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
if (OffsetVar) {
OffsetVar->setInitializer(OffsetValue);
@@ -2219,14 +3333,13 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
// copy.
OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
} else
- OffsetVar = new llvm::GlobalVariable(TheModule, IntTy,
+ OffsetVar = new llvm::GlobalVariable(TheModule, Int32Ty,
false, llvm::GlobalValue::ExternalLinkage,
- OffsetValue,
- "__objc_ivar_offset_value_" + ClassName +"." +
- IVD->getNameAsString());
+ OffsetValue, OffsetName);
IvarOffsets.push_back(OffsetValue);
IvarOffsetValues.add(OffsetVar);
Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
+ IvarOwnership.push_back(lt);
switch (lt) {
case Qualifiers::OCL_Strong:
StrongIvars.push_back(true);
@@ -2248,25 +3361,30 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
CGM.getPointerAlign());
// Collect information about instance methods
- SmallVector<Selector, 16> InstanceMethodSels;
- SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
- for (const auto *I : OID->instance_methods()) {
- InstanceMethodSels.push_back(I->getSelector());
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
- InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
- }
+ SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
+ InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
+ OID->instmeth_end());
+
+ SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
+ ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
+ OID->classmeth_end());
+
+ // Collect the same information about synthesized properties, which don't
+ // show up in the instance method lists.
+ for (auto *propertyImpl : OID->property_impls())
+ if (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Synthesize) {
+ ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
+ auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
+ if (accessor)
+ InstanceMethods.push_back(accessor);
+ };
+ addPropertyMethod(property->getGetterMethodDecl());
+ addPropertyMethod(property->getSetterMethodDecl());
+ }
- llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels,
- InstanceMethodTypes);
+ llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
- // Collect information about class methods
- SmallVector<Selector, 16> ClassMethodSels;
- SmallVector<llvm::Constant*, 16> ClassMethodTypes;
- for (const auto *I : OID->class_methods()) {
- ClassMethodSels.push_back(I->getSelector());
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
- ClassMethodTypes.push_back(MakeConstantString(TypeStr));
- }
// Collect the names of referenced protocols
SmallVector<std::string, 16> Protocols;
for (const auto *I : ClassDecl->protocols())
@@ -2283,11 +3401,11 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
SmallVector<llvm::Constant*, 1> empty;
// Generate the method and instance variable lists
llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
- InstanceMethodSels, InstanceMethodTypes, false);
+ InstanceMethods, false);
llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
- ClassMethodSels, ClassMethodTypes, true);
+ ClassMethods, true);
llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
- IvarOffsets);
+ IvarOffsets, IvarAligns, IvarOwnership);
// Irrespective of whether we are compiling for a fragile or non-fragile ABI,
// we emit a symbol containing the offset for each ivar in the class. This
// allows code compiled for the non-Fragile ABI to inherit from code compiled
@@ -2300,14 +3418,13 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
// the offset (third field in ivar structure)
llvm::Type *IndexTy = Int32Ty;
llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
- llvm::ConstantInt::get(IndexTy, 1), nullptr,
- llvm::ConstantInt::get(IndexTy, 2) };
+ llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1), nullptr,
+ llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
unsigned ivarIndex = 0;
for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD;
IVD = IVD->getNextIvar()) {
- const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
- + IVD->getNameAsString();
+ const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
// Get the correct ivar field
llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
@@ -2321,12 +3438,10 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
// different modules will use this one, rather than their private
// copy.
offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else {
+ } else
// Add a new alias if there isn't one already.
- offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
+ new llvm::GlobalVariable(TheModule, offsetValue->getType(),
false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
- (void) offset; // Silence dead store warning.
- }
++ivarIndex;
}
llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
@@ -2334,16 +3449,10 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
//Generate metaclass for class methods
llvm::Constant *MetaClassStruct = GenerateClassStructure(
NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0],
- GenerateIvarList(empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr,
- NULLPtr, ZeroPtr, ZeroPtr, true);
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- auto Storage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->getClassInterface()->hasAttr<DLLImportAttr>())
- Storage = llvm::GlobalValue::DLLImportStorageClass;
- else if (OID->getClassInterface()->hasAttr<DLLExportAttr>())
- Storage = llvm::GlobalValue::DLLExportStorageClass;
- cast<llvm::GlobalValue>(MetaClassStruct)->setDLLStorageClass(Storage);
- }
+ NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
+ GeneratePropertyList(OID, ClassDecl, true), ZeroPtr, ZeroPtr, true);
+ CGM.setGVProperties(cast<llvm::GlobalValue>(MetaClassStruct),
+ OID->getClassInterface());
// Generate the class structure
llvm::Constant *ClassStruct = GenerateClassStructure(
@@ -2351,14 +3460,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
llvm::ConstantInt::get(LongTy, instanceSize), IvarList, MethodList,
GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
StrongIvarBitmap, WeakIvarBitmap);
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- auto Storage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->getClassInterface()->hasAttr<DLLImportAttr>())
- Storage = llvm::GlobalValue::DLLImportStorageClass;
- else if (OID->getClassInterface()->hasAttr<DLLExportAttr>())
- Storage = llvm::GlobalValue::DLLExportStorageClass;
- cast<llvm::GlobalValue>(ClassStruct)->setDLLStorageClass(Storage);
- }
+ CGM.setGVProperties(cast<llvm::GlobalValue>(ClassStruct),
+ OID->getClassInterface());
// Resolve the class aliases, if they exist.
if (ClassPtrAlias) {
@@ -2696,7 +3799,7 @@ void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
// interoperate very well with foreign exceptions.
//
// In Objective-C++ mode, we actually emit something equivalent to the C++
- // exception handler.
+ // exception handler.
EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
}
@@ -2704,6 +3807,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
bool ClearInsertionPoint) {
llvm::Value *ExceptionAsObject;
+ bool isRethrow = false;
if (const Expr *ThrowExpr = S.getThrowExpr()) {
llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
@@ -2712,11 +3816,24 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
"Unexpected rethrow outside @catch block.");
ExceptionAsObject = CGF.ObjCEHValueStack.back();
+ isRethrow = true;
+ }
+ if (isRethrow && usesSEHExceptions) {
+ // For SEH, ExceptionAsObject may be undef, because the catch handler is
+ // not passed it for catchalls and so it is not visible to the catch
+ // funclet. The real thrown object will still be live on the stack at this
+ // point and will be rethrown. If we are explicitly rethrowing the object
+ // that was passed into the `@catch` block, then this code path is not
+ // reached and we will instead call `objc_exception_throw` with an explicit
+ // argument.
+ CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn).setDoesNotReturn();
+ }
+ else {
+ ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
+ llvm::CallSite Throw =
+ CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
+ Throw.setDoesNotReturn();
}
- ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
- llvm::CallSite Throw =
- CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
- Throw.setDoesNotReturn();
CGF.Builder.CreateUnreachable();
if (ClearInsertionPoint)
CGF.Builder.ClearInsertionPoint();
@@ -2785,46 +3902,15 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar) {
- const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
- + '.' + Ivar->getNameAsString();
+ const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
// Emit the variable and initialize it with what we think the correct value
// is. This allows code compiled with non-fragile ivars to work correctly
// when linked against code which isn't (most of the time).
llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
- if (!IvarOffsetPointer) {
- // This will cause a run-time crash if we accidentally use it. A value of
- // 0 would seem more sensible, but will silently overwrite the isa pointer
- // causing a great deal of confusion.
- uint64_t Offset = -1;
- // We can't call ComputeIvarBaseOffset() here if we have the
- // implementation, because it will create an invalid ASTRecordLayout object
- // that we are then stuck with forever, so we only initialize the ivar
- // offset variable with a guess if we only have the interface. The
- // initializer will be reset later anyway, when we are generating the class
- // description.
- if (!CGM.getContext().getObjCImplementation(
- const_cast<ObjCInterfaceDecl *>(ID)))
- Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
-
- llvm::ConstantInt *OffsetGuess = llvm::ConstantInt::get(Int32Ty, Offset,
- /*isSigned*/true);
- // Don't emit the guess in non-PIC code because the linker will not be able
- // to replace it with the real version for a library. In non-PIC code you
- // must compile with the fragile ABI if you want to use ivars from a
- // GCC-compiled class.
- if (CGM.getLangOpts().PICLevel) {
- llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
- Int32Ty, false,
- llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
- IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
- IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
- IvarOffsetGV, Name);
- } else {
- IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
- llvm::Type::getInt32PtrTy(VMContext), false,
- llvm::GlobalValue::ExternalLinkage, nullptr, Name);
- }
- }
+ if (!IvarOffsetPointer)
+ IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
+ llvm::Type::getInt32PtrTy(VMContext), false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, Name);
return IvarOffsetPointer;
}
@@ -2895,8 +3981,11 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
CGObjCRuntime *
clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
- switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
+ auto Runtime = CGM.getLangOpts().ObjCRuntime;
+ switch (Runtime.getKind()) {
case ObjCRuntime::GNUstep:
+ if (Runtime.getVersion() >= VersionTuple(2, 0))
+ return new CGObjCGNUstep2(CGM);
return new CGObjCGNUstep(CGM);
case ObjCRuntime::GCC:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
index ef4e6cd4f01b..2b54e7bd67af 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -57,7 +57,7 @@ private:
// should always bitcast before calling them.
/// id objc_msgSend (id, SEL, ...)
- ///
+ ///
/// The default messenger, used for sends whose ABI is unchanged from
/// the all-integer/pointer case.
llvm::Constant *getMessageSendFn() const {
@@ -184,12 +184,12 @@ public:
/// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
llvm::PointerType *SelectorPtrTy;
-
+
private:
/// ProtocolPtrTy - LLVM type for external protocol handles
/// (typeof(Protocol))
llvm::Type *ExternalProtocolPtrTy;
-
+
public:
llvm::Type *getExternalProtocolPtrTy() {
if (!ExternalProtocolPtrTy) {
@@ -200,10 +200,10 @@ public:
llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
}
-
+
return ExternalProtocolPtrTy;
}
-
+
// SuperCTy - clang type for struct objc_super.
QualType SuperCTy;
// SuperPtrCTy - clang type for struct objc_super *.
@@ -231,7 +231,7 @@ public:
llvm::Type *CacheTy;
/// CachePtrTy - LLVM type for struct objc_cache *.
llvm::PointerType *CachePtrTy;
-
+
llvm::Constant *getGetPropertyFn() {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -269,15 +269,15 @@ public:
llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
- // void objc_setProperty_atomic(id self, SEL _cmd,
+ // void objc_setProperty_atomic(id self, SEL _cmd,
// id newValue, ptrdiff_t offset);
- // void objc_setProperty_nonatomic(id self, SEL _cmd,
+ // void objc_setProperty_nonatomic(id self, SEL _cmd,
// id newValue, ptrdiff_t offset);
- // void objc_setProperty_atomic_copy(id self, SEL _cmd,
+ // void objc_setProperty_atomic_copy(id self, SEL _cmd,
// id newValue, ptrdiff_t offset);
- // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
+ // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
// id newValue, ptrdiff_t offset);
-
+
SmallVector<CanQualType,4> Params;
CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
@@ -297,10 +297,10 @@ public:
name = "objc_setProperty_nonatomic_copy";
else
name = "objc_setProperty_nonatomic";
-
+
return CGM.CreateRuntimeFunction(FTy, name);
}
-
+
llvm::Constant *getCopyStructFn() {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -316,10 +316,10 @@ public:
Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
}
-
+
/// This routine declares and returns address of:
/// void objc_copyCppObjectAtomic(
- /// void *dest, const void *src,
+ /// void *dest, const void *src,
/// void (*copyHelper) (void *dest, const void *source));
llvm::Constant *getCppAtomicObjectFunction() {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
@@ -334,7 +334,7 @@ public:
Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
}
-
+
llvm::Constant *getEnumerationMutationFn() {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -396,7 +396,7 @@ public:
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
}
-
+
/// GcAssignIvarFn -- LLVM objc_assign_ivar function.
llvm::Constant *getGcAssignIvarFn() {
// id objc_assign_ivar(id, id *, ptrdiff_t)
@@ -439,7 +439,7 @@ public:
llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
}
-
+
/// SyncEnterFn - LLVM object_sync_enter function.
llvm::Constant *getSyncEnterFn() {
// int objc_sync_enter (id)
@@ -550,7 +550,7 @@ public:
/// ExceptionDataTy - LLVM type for struct _objc_exception_data.
llvm::StructType *ExceptionDataTy;
-
+
/// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
llvm::Constant *getExceptionTryEnterFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
@@ -727,7 +727,7 @@ public:
llvm::StructType *EHTypeTy;
llvm::Type *EHTypePtrTy;
-
+
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
};
@@ -760,33 +760,33 @@ public:
/// to '\0'.
/// I != 0: Currently unused.
BLOCK_LAYOUT_OPERATOR = 0,
-
+
/// The next I+1 bytes do not contain a value of object pointer type.
/// Note that this can leave the stream unaligned, meaning that
/// subsequent word-size instructions do not begin at a multiple of
/// the pointer size.
BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
-
+
/// The next I+1 words do not contain a value of object pointer type.
/// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
/// when the required skip quantity is a multiple of the pointer size.
BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
-
+
/// The next I+1 words are __strong pointers to Objective-C
/// objects or blocks.
BLOCK_LAYOUT_STRONG = 3,
-
+
/// The next I+1 words are pointers to __block variables.
BLOCK_LAYOUT_BYREF = 4,
-
+
/// The next I+1 words are __weak pointers to Objective-C
/// objects or blocks.
BLOCK_LAYOUT_WEAK = 5,
-
+
/// The next I+1 words are __unsafe_unretained pointers to
/// Objective-C objects or blocks.
BLOCK_LAYOUT_UNRETAINED = 6
-
+
/// The next I+1 words are block or object pointers with some
/// as-yet-unspecified ownership semantics. If we add more
/// flavors of ownership semantics, values will be taken from
@@ -795,11 +795,11 @@ public:
/// This is included so that older tools can at least continue
/// processing the layout past such things.
//BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
-
+
/// All other opcodes are reserved. Halt interpretation and
/// treat everything else as opaque.
};
-
+
class RUN_SKIP {
public:
enum BLOCK_LAYOUT_OPCODE opcode;
@@ -809,13 +809,13 @@ public:
CharUnits BytePos = CharUnits::Zero(),
CharUnits Size = CharUnits::Zero())
: opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
-
+
// Allow sorting based on byte pos.
bool operator<(const RUN_SKIP &b) const {
return block_var_bytepos < b.block_var_bytepos;
}
};
-
+
protected:
llvm::LLVMContext &VMContext;
// FIXME! May not be needing this after all.
@@ -871,7 +871,7 @@ protected:
/// DefinedClasses - List of defined classes.
SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
-
+
/// ImplementedClasses - List of @implemented classes.
SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
@@ -888,7 +888,7 @@ protected:
/// int * but is actually an Obj-C class pointer.
llvm::WeakTrackingVH ConstantStringClassRef;
- /// \brief The LLVM type corresponding to NSConstantString.
+ /// The LLVM type corresponding to NSConstantString.
llvm::StructType *NSConstantStringType = nullptr;
llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
@@ -952,28 +952,28 @@ protected:
bool hasMRCWeakIvars) {
return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
}
-
+
Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
-
+
void UpdateRunSkipBlockVars(bool IsByref,
Qualifiers::ObjCLifetime LifeTime,
CharUnits FieldOffset,
CharUnits FieldSize);
-
+
void BuildRCBlockVarRecordLayout(const RecordType *RT,
CharUnits BytePos, bool &HasUnion,
bool ByrefLayout=false);
-
+
void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
const RecordDecl *RD,
ArrayRef<const FieldDecl*> RecFields,
CharUnits BytePos, bool &HasUnion,
bool ByrefLayout);
-
+
uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
-
+
llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
-
+
/// GetIvarLayoutName - Returns a unique constant for the given
/// ivar layout bitmap.
llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
@@ -987,9 +987,9 @@ protected:
const ObjCCommonTypesHelper &ObjCTypes,
bool IsClassProperty);
- /// EmitProtocolMethodTypes - Generate the array of extended method type
+ /// EmitProtocolMethodTypes - Generate the array of extended method type
/// strings. The return value has type Int8PtrPtrTy.
- llvm::Constant *EmitProtocolMethodTypes(Twine Name,
+ llvm::Constant *EmitProtocolMethodTypes(Twine Name,
ArrayRef<llvm::Constant*> MethodTypes,
const ObjCCommonTypesHelper &ObjCTypes);
@@ -1205,7 +1205,7 @@ private:
/// for the given class.
llvm::Value *EmitClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID);
-
+
llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
IdentifierInfo *II);
@@ -1382,7 +1382,7 @@ private:
/// DefinedMetaClasses - List of defined meta-classes.
std::vector<llvm::GlobalValue*> DefinedMetaClasses;
-
+
/// isVTableDispatchedSelector - Returns true if SEL is a
/// vtable-based selector.
bool isVTableDispatchedSelector(Selector Sel);
@@ -1453,7 +1453,7 @@ private:
bool IsSuper,
const CallArgList &CallArgs,
const ObjCMethodDecl *Method);
-
+
/// GetClassGlobal - Return the global variable for the Objective-C
/// class of the given name.
llvm::Constant *GetClassGlobal(StringRef Name,
@@ -1467,7 +1467,7 @@ private:
/// for the given class reference.
llvm::Value *EmitClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID);
-
+
llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
IdentifierInfo *II,
const ObjCInterfaceDecl *ID);
@@ -1700,7 +1700,7 @@ struct NullReturnState {
// Okay, start emitting the null-receiver block.
CGF.EmitBlock(NullBB);
-
+
// Release any consumed arguments we've got.
if (Method) {
CallArgList::const_iterator I = CallArgs.begin();
@@ -1708,8 +1708,8 @@ struct NullReturnState {
e = Method->param_end(); i != e; ++i, ++I) {
const ParmVarDecl *ParamDecl = (*i);
if (ParamDecl->hasAttr<NSConsumedAttr>()) {
- RValue RV = I->RV;
- assert(RV.isScalar() &&
+ RValue RV = I->getRValue(CGF);
+ assert(RV.isScalar() &&
"NullReturnState::complete - arg not on object");
CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
}
@@ -1839,7 +1839,7 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) {
}
if (T->isObjCObjectPointerType())
return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
-
+
llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
}
@@ -1898,8 +1898,8 @@ llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
return cast<llvm::Constant>(V);
auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
- std::string str =
- StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
+ std::string str =
+ StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
: "OBJC_CLASS_$_" + StringClass;
auto GV = GetClassGlobal(str, NotForDefinition);
@@ -2162,7 +2162,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
if (RequiresNullCheck) {
nullReturn.init(CGF, Arg0);
}
-
+
llvm::Instruction *CallSite;
Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
CGCallee Callee = CGCallee::forDirect(Fn);
@@ -2202,17 +2202,17 @@ static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
}
llvm_unreachable("bad objc ownership");
}
-
+
// Treat unqualified retainable pointers as strong.
if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
return Qualifiers::Strong;
-
+
// Walk into C pointer types, but only in GC.
if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
if (const PointerType *PT = FQT->getAs<PointerType>())
return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
}
-
+
return Qualifiers::GCNone;
}
@@ -2258,7 +2258,7 @@ namespace {
void visitRecord(const RecordType *RT, CharUnits offset);
template <class Iterator, class GetOffsetFn>
- void visitAggregate(Iterator begin, Iterator end,
+ void visitAggregate(Iterator begin, Iterator end,
CharUnits aggrOffset,
const GetOffsetFn &getOffset);
@@ -2287,7 +2287,7 @@ namespace {
llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
const CGBlockInfo &blockInfo) {
-
+
llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
return nullPtr;
@@ -2306,7 +2306,7 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
printf("\n block variable layout for block: ");
builder.dump(buffer);
}
-
+
return C;
}
@@ -2351,7 +2351,7 @@ void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
visitRecord(record, fieldOffset);
continue;
}
-
+
Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
if (GCAttr == Qualifiers::Strong) {
@@ -2374,11 +2374,11 @@ Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
// If it doesn't, and this is ARC, it has no ownership.
if (CGM.getLangOpts().ObjCAutoRefCount)
return Qualifiers::OCL_None;
-
+
// In MRC, retainable pointers are owned by non-__block variables.
if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
-
+
return Qualifiers::OCL_None;
}
@@ -2416,11 +2416,11 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
CharUnits MaxFieldOffset = CharUnits::Zero();
CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
-
+
if (RecFields.empty())
return;
unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
-
+
for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
const FieldDecl *Field = RecFields[i];
// Note that 'i' here is actually the field index inside RD of Field,
@@ -2428,7 +2428,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
CharUnits FieldOffset =
CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
-
+
// Skip over unnamed or bitfields
if (!Field->getIdentifier() || Field->isBitField()) {
LastFieldBitfieldOrUnnamed = Field;
@@ -2441,12 +2441,12 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
if (FQT->isRecordType() || FQT->isUnionType()) {
if (FQT->isUnionType())
HasUnion = true;
-
+
BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
BytePos + FieldOffset, HasUnion);
continue;
}
-
+
if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
const ConstantArrayType *CArray =
dyn_cast_or_null<ConstantArrayType>(Array);
@@ -2464,7 +2464,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
const RecordType *RT = FQT->getAs<RecordType>();
BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
HasUnion);
-
+
// Replicate layout information for each array element. Note that
// one element is already done.
uint64_t ElIx = 1;
@@ -2494,7 +2494,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
FieldSize);
}
}
-
+
if (LastFieldBitfieldOrUnnamed) {
if (LastFieldBitfieldOrUnnamed->isBitField()) {
// Last field was a bitfield. Must update the info.
@@ -2521,7 +2521,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
FieldSize);
}
}
-
+
if (MaxField)
UpdateRunSkipBlockVars(false,
getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
@@ -2538,7 +2538,7 @@ void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
const llvm::StructLayout *RecLayout =
CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
-
+
BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
}
@@ -2580,7 +2580,7 @@ uint64_t CGObjCCommonMac::InlineLayoutInstruction(
else
return 0;
break;
-
+
case 2:
inst = Layout[0];
opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
@@ -2607,7 +2607,7 @@ uint64_t CGObjCCommonMac::InlineLayoutInstruction(
else
return 0;
break;
-
+
case 1:
inst = Layout[0];
opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
@@ -2620,20 +2620,20 @@ uint64_t CGObjCCommonMac::InlineLayoutInstruction(
else
return 0;
break;
-
+
default:
return 0;
}
-
+
// Cannot inline when any of the word counts is 15. Because this is one less
// than the actual work count (so 15 means 16 actual word counts),
// and we can only display 0 thru 15 word counts.
if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
return 0;
-
+
unsigned count =
(strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
-
+
if (size == count) {
if (strong_word_count)
Result = strong_word_count;
@@ -2655,12 +2655,12 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
-
+
// Sort on byte position; captures might not be allocated in order,
// and unions can do funny things.
llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
SmallVector<unsigned char, 16> Layout;
-
+
unsigned size = RunSkipBlockVars.size();
for (unsigned i = 0; i < size; i++) {
enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
@@ -2689,7 +2689,7 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
size_in_bytes -= residue_in_bytes;
opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
}
-
+
unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
while (size_in_words >= 16) {
// Note that value in imm. is one less that the actual
@@ -2710,7 +2710,7 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
Layout.push_back(inst);
}
}
-
+
while (!Layout.empty()) {
unsigned char inst = Layout.back();
enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
@@ -2719,7 +2719,7 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
else
break;
}
-
+
uint64_t Result = InlineLayoutInstruction(Layout);
if (Result != 0) {
// Block variable layout instruction has been inlined.
@@ -2739,13 +2739,13 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
}
return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
}
-
+
unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
Layout.push_back(inst);
std::string BitMap;
for (unsigned i = 0, e = Layout.size(); i != e; i++)
BitMap += Layout[i];
-
+
if (CGM.getLangOpts().ObjCGCBitmapPrint) {
if (ComputeByrefLayout)
printf("\n Byref variable layout: ");
@@ -2798,20 +2798,20 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
const CGBlockInfo &blockInfo) {
assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
-
+
RunSkipBlockVars.clear();
bool hasUnion = false;
-
+
unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
-
+
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
-
+
// Calculate the basic layout of the block structure.
const llvm::StructLayout *layout =
CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
-
+
// Ignore the optional 'this' capture: C++ objects are not assumed
// to be GC'ed.
if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
@@ -2822,15 +2822,15 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
for (const auto &CI : blockDecl->captures()) {
const VarDecl *variable = CI.getVariable();
QualType type = variable->getType();
-
+
const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
-
+
// Ignore constant captures.
if (capture.isConstant()) continue;
-
+
CharUnits fieldOffset =
CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
-
+
assert(!type->isArrayType() && "array variable should not be caught");
if (!CI.isByRef())
if (const RecordType *record = type->getAs<RecordType>()) {
@@ -2891,7 +2891,7 @@ void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
if (DefinedProtocols.count(PD->getIdentifier()))
return GetOrEmitProtocol(PD);
-
+
return GetOrEmitProtocolRef(PD);
}
@@ -3094,12 +3094,12 @@ CGObjCMac::EmitProtocolList(Twine name,
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
}
-static void
+static void
PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
const ObjCProtocolDecl *Proto,
bool IsClassProperty) {
- for (const auto *P : Proto->protocols())
+ for (const auto *P : Proto->protocols())
PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
for (const auto *PD : Proto->properties()) {
@@ -3401,7 +3401,9 @@ static bool hasMRCWeakIvars(CodeGenModule &CGM,
See EmitClassExtension();
*/
void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
- DefinedSymbols.insert(ID->getIdentifier());
+ IdentifierInfo *RuntimeName =
+ &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
+ DefinedSymbols.insert(RuntimeName);
std::string ClassName = ID->getNameAsString();
// FIXME: Gross
@@ -3677,7 +3679,7 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
auto countSlot = ivarList.addPlaceholder();
auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
- for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
+ for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar()) {
// Ignore unnamed bit-fields.
if (!IVD->getDeclName())
@@ -3962,7 +3964,7 @@ llvm::Constant *CGObjCMac::GetPropertySetFunction() {
return ObjCTypes.getSetPropertyFn();
}
-llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
+llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
bool copy) {
return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
}
@@ -4179,10 +4181,6 @@ void FragileHazards::emitHazardsInNewBlocks() {
}
}
-static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
- if (V) S.insert(V);
-}
-
static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
if (V.isValid()) S.insert(V.getPointer());
}
@@ -4961,9 +4959,9 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() {
llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
IdentifierInfo *II) {
LazySymbols.insert(II);
-
+
llvm::GlobalVariable *&Entry = ClassReferences[II];
-
+
if (!Entry) {
llvm::Constant *Casted =
llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
@@ -4973,7 +4971,7 @@ llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
"__OBJC,__cls_refs,literal_pointers,no_dead_strip",
CGM.getPointerAlign(), true);
}
-
+
return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
}
@@ -4984,7 +4982,9 @@ llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
- return EmitClassRefFromId(CGF, ID->getIdentifier());
+ IdentifierInfo *RuntimeName =
+ &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
+ return EmitClassRefFromId(CGF, RuntimeName);
}
llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
@@ -5056,7 +5056,7 @@ void IvarLayoutBuilder::visitRecord(const RecordType *RT,
}
template <class Iterator, class GetOffsetFn>
-void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
+void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
CharUnits aggregateOffset,
const GetOffsetFn &getOffset) {
for (; begin != end; ++begin) {
@@ -5317,7 +5317,7 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
// MRC weak layout strings follow the ARC style.
CharUnits baseOffset;
if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
- for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
+ for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar())
ivars.push_back(IVD);
@@ -5353,7 +5353,7 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
llvm::SmallVector<unsigned char, 4> buffer;
llvm::Constant *C = builder.buildBitmap(*this, buffer);
-
+
if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
printf("\n%s ivar layout for class '%s': ",
ForStrongLayout ? "strong" : "weak",
@@ -5903,7 +5903,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
// SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
-
+
// struct objc_typeinfo {
// const void** vtable; // objc_ehtype_vtable + 2
@@ -6033,7 +6033,7 @@ bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
VTableDispatchMethods.insert(GetNullarySelector("hash"));
VTableDispatchMethods.insert(GetUnarySelector("addObject"));
-
+
// "countByEnumeratingWithState:objects:count"
IdentifierInfo *KeyIdents[] = {
&CGM.getContext().Idents.get("countByEnumeratingWithState"),
@@ -6309,9 +6309,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalVariable *MetaTClass =
BuildClassObject(CI, /*metaclass*/ true,
IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (CI->hasAttr<DLLExportAttr>())
- MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(MetaTClass, CI);
DefinedMetaClasses.push_back(MetaTClass);
// Metadata for the class
@@ -6351,9 +6349,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalVariable *ClassMD =
BuildClassObject(CI, /*metaclass*/ false,
MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (CI->hasAttr<DLLExportAttr>())
- ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(ClassMD, CI);
DefinedClasses.push_back(ClassMD);
ImplementedClasses.push_back(CI);
@@ -6403,7 +6399,7 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
PTGV->setAlignment(Align.getQuantity());
if (!CGM.getTriple().isOSBinFormatMachO())
PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
- CGM.addCompilerUsedGlobal(PTGV);
+ CGM.addUsedGlobal(PTGV);
return CGF.Builder.CreateAlignedLoad(PTGV, Align);
}
@@ -6422,12 +6418,12 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
const char *Prefix = "\01l_OBJC_$_CATEGORY_";
-
+
llvm::SmallString<64> ExtCatName(Prefix);
ExtCatName += Interface->getObjCRuntimeNameAsString();
ExtCatName += "_$_";
ExtCatName += OCD->getNameAsString();
-
+
ConstantInitBuilder builder(CGM);
auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
values.add(GetClassName(OCD->getIdentifier()->getName()));
@@ -6688,7 +6684,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
// FIXME. Consolidate this with similar code in GenerateClass.
- for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
+ for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar()) {
// Ignore unnamed bit-fields.
if (!IVD->getDeclName())
@@ -6789,7 +6785,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
// Use the protocol definition, if there is one.
if (const ObjCProtocolDecl *Def = PD->getDefinition())
PD = Def;
-
+
auto methodLists = ProtocolMethodLists::get(PD);
ConstantInitBuilder builder(CGM);
@@ -6828,7 +6824,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
values.add(EmitPropertyList(
"\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
nullptr, PD, ObjCTypes, true));
-
+
if (Entry) {
// Already created, fix the linkage and update the initializer.
Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
@@ -6847,7 +6843,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Protocols[PD->getIdentifier()] = Entry;
}
Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.addCompilerUsedGlobal(Entry);
+ CGM.addUsedGlobal(Entry);
// Use this protocol meta-data to build protocol list table in section
// __DATA, __objc_protolist
@@ -6866,7 +6862,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
PTGV->setSection(GetSectionName("__objc_protolist",
"coalesced,no_dead_strip"));
PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.addCompilerUsedGlobal(PTGV);
+ CGM.addUsedGlobal(PTGV);
return Entry;
}
@@ -6952,7 +6948,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
// This could be 32bit int or 64bit integer depending on the architecture.
// Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
- // as this is what caller always expectes.
+ // as this is what caller always expects.
if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
IvarOffsetValue = CGF.Builder.CreateIntCast(
IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
@@ -7062,7 +7058,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
}
-
+
bool requiresnullCheck = false;
if (CGM.getLangOpts().ObjCAutoRefCount && method)
for (const auto *ParamDecl : method->parameters()) {
@@ -7073,13 +7069,13 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
break;
}
}
-
+
Address mref =
Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
CGF.getPointerAlign());
// Update the message ref argument.
- args[1].RV = RValue::get(mref.getPointer());
+ args[1].setRValue(RValue::get(mref.getPointer()));
// Load the function to call from the message ref table.
Address calleeAddr =
@@ -7157,7 +7153,7 @@ CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID) {
CharUnits Align = CGF.getPointerAlign();
llvm::GlobalVariable *&Entry = ClassReferences[II];
-
+
if (!Entry) {
llvm::Constant *ClassGV;
if (ID) {
@@ -7247,7 +7243,7 @@ llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
assert(!isa<llvm::GlobalVariable>(ClassGV) ||
cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
}
-
+
return EmitClassRef(CGF, ID);
}
@@ -7308,7 +7304,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
Address Addr = EmitSelectorAddr(CGF, Sel);
llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
- LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
+ LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
llvm::MDNode::get(VMContext, None));
return LI;
}
@@ -7528,12 +7524,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
false, llvm::GlobalValue::ExternalLinkage,
nullptr, EHTypeName);
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- if (ID->hasAttr<DLLExportAttr>())
- Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- else if (ID->hasAttr<DLLImportAttr>())
- Entry->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- }
+ CGM.setGVProperties(Entry, ID);
return Entry;
}
}
@@ -7572,10 +7563,8 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
CGM.getPointerAlign(),
/*constant*/ false,
L);
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (hasObjCExceptionAttribute(CGM.getContext(), ID))
- if (ID->hasAttr<DLLExportAttr>())
- Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID))
+ CGM.setGVProperties(Entry, ID);
}
assert(Entry->getLinkage() == L);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
index 2f886fd82caa..64a9df2bfc0d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -15,6 +15,7 @@
#include "CGObjCRuntime.h"
#include "CGCleanup.h"
+#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -22,6 +23,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -120,6 +122,8 @@ namespace {
const Stmt *Body;
llvm::BasicBlock *Block;
llvm::Constant *TypeInfo;
+ /// Flags used to differentiate cleanups and catchalls in Windows SEH
+ unsigned Flags;
};
struct CallObjCEndCatch final : EHScopeStack::Cleanup {
@@ -148,13 +152,17 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
if (S.getNumCatchStmts())
Cont = CGF.getJumpDestInCurrentScope("eh.cont");
+ bool useFunclets = EHPersonality::get(CGF).usesFuncletPads();
+
CodeGenFunction::FinallyInfo FinallyInfo;
- if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
- FinallyInfo.enter(CGF, Finally->getFinallyBody(),
- beginCatchFn, endCatchFn, exceptionRethrowFn);
+ if (!useFunclets)
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
+ FinallyInfo.enter(CGF, Finally->getFinallyBody(),
+ beginCatchFn, endCatchFn, exceptionRethrowFn);
SmallVector<CatchHandler, 8> Handlers;
+
// Enter the catch, if there is one.
if (S.getNumCatchStmts()) {
for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
@@ -166,10 +174,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
Handler.Variable = CatchDecl;
Handler.Body = CatchStmt->getCatchBody();
Handler.Block = CGF.createBasicBlock("catch");
+ Handler.Flags = 0;
// @catch(...) always matches.
if (!CatchDecl) {
- Handler.TypeInfo = nullptr; // catch-all
+ auto catchAll = getCatchAllTypeInfo();
+ Handler.TypeInfo = catchAll.RTTI;
+ Handler.Flags = catchAll.Flags;
// Don't consider any other catches.
break;
}
@@ -179,8 +190,30 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
- Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
+ Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block);
}
+
+ if (useFunclets)
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (!CGF.CurSEHParent)
+ CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl);
+ // Outline the finally block.
+ const Stmt *FinallyBlock = Finally->getFinallyBody();
+ HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock);
+
+ // Emit the original filter expression, convert to i32, and return.
+ HelperCGF.EmitStmt(FinallyBlock);
+
+ HelperCGF.FinishFunction(FinallyBlock->getLocEnd());
+
+ llvm::Function *FinallyFunc = HelperCGF.CurFn;
+
+
+ // Push a cleanup for __finally blocks.
+ CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc);
+ }
+
// Emit the try body.
CGF.EmitStmt(S.getTryBody());
@@ -197,6 +230,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CatchHandler &Handler = Handlers[I];
CGF.EmitBlock(Handler.Block);
+ llvm::CatchPadInst *CPI = nullptr;
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad);
+ if (useFunclets)
+ if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) {
+ CGF.CurrentFuncletPad = CPI;
+ CPI->setOperand(2, CGF.getExceptionSlot().getPointer());
+ }
llvm::Value *RawExn = CGF.getExceptionFromSlot();
// Enter the catch.
@@ -223,6 +263,8 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CGF.EmitAutoVarDecl(*CatchParam);
EmitInitOfCatchParam(CGF, CastExn, CatchParam);
}
+ if (CPI)
+ CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
CGF.ObjCEHValueStack.push_back(Exn);
CGF.EmitStmt(Handler.Body);
@@ -238,7 +280,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CGF.Builder.restoreIP(SavedIP);
// Pop out of the finally.
- if (S.getFinallyStmt())
+ if (!useFunclets && S.getFinallyStmt())
FinallyInfo.exit(CGF);
if (Cont.isValid())
@@ -277,7 +319,7 @@ namespace {
: SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg);
}
};
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
index a14b44abf413..78d5aba4128e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H
#include "CGBuilder.h"
#include "CGCall.h"
+#include "CGCleanup.h"
#include "CGValue.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h" // Selector
@@ -141,9 +142,11 @@ public:
/// error to Sema.
virtual llvm::Constant *GetEHType(QualType T) = 0;
+ virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; }
+
/// Generate a constant string object.
virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0;
-
+
/// Generate a category. A category contains a list of methods (and
/// accompanying metadata) and a list of protocols.
virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0;
@@ -211,7 +214,7 @@ public:
virtual llvm::Constant *GetPropertySetFunction() = 0;
/// Return the runtime function for optimized setting properties.
- virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
+ virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
bool copy) = 0;
// API for atomic copying of qualified aggregates in getter.
@@ -224,17 +227,17 @@ public:
/// API for atomic copying of qualified aggregates with non-trivial copy
/// assignment (c++) in getter.
virtual llvm::Constant *GetCppAtomicObjectGetFunction() = 0;
-
+
/// GetClass - Return a reference to the class for the given
/// interface decl.
virtual llvm::Value *GetClass(CodeGenFunction &CGF,
const ObjCInterfaceDecl *OID) = 0;
-
-
+
+
virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
llvm_unreachable("autoreleasepool unsupported in this ABI");
}
-
+
/// EnumerationMutationFunction - Return the function that's called by the
/// compiler when a mutation is detected during foreach iteration.
virtual llvm::Constant *EnumerationMutationFunction() = 0;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
index d140e7f09e9a..1da19a90c387 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -66,13 +66,19 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
}
llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
- if (!PipeTy){
- uint32_t PipeAddrSpc = CGM.getContext().getTargetAddressSpace(
- CGM.getContext().getOpenCLTypeAddrSpace(T));
- PipeTy = llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
- }
+ if (T->isReadOnly())
+ return getPipeType(T, "opencl.pipe_ro_t", PipeROTy);
+ else
+ return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy);
+}
+llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name,
+ llvm::Type *&PipeTy) {
+ if (!PipeTy)
+ PipeTy = llvm::PointerType::get(llvm::StructType::create(
+ CGM.getLLVMContext(), Name),
+ CGM.getContext().getTargetAddressSpace(
+ CGM.getContext().getOpenCLTypeAddrSpace(T)));
return PipeTy;
}
@@ -112,37 +118,64 @@ llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
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.
+// Get the block literal from an expression derived from the block expression.
+// OpenCL v2.0 s6.12.5:
+// Block variable declarations are implicitly qualified with const. Therefore
+// all block variables must be initialized at declaration time and may not be
+// reassigned.
+static const BlockExpr *getBlockExpr(const Expr *E) {
+ if (auto Cast = dyn_cast<CastExpr>(E)) {
+ E = Cast->getSubExpr();
+ }
if (auto DR = dyn_cast<DeclRefExpr>(E)) {
E = cast<VarDecl>(DR->getDecl())->getInit();
}
+ E = E->IgnoreImplicit();
if (auto Cast = dyn_cast<CastExpr>(E)) {
E = Cast->getSubExpr();
}
- auto *Block = cast<BlockExpr>(E);
+ return cast<BlockExpr>(E);
+}
+
+/// Record emitted llvm invoke function and llvm block literal for the
+/// corresponding block expression.
+void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
+ llvm::Function *InvokeF,
+ llvm::Value *Block) {
+ assert(EnqueuedBlockMap.find(E) == EnqueuedBlockMap.end() &&
+ "Block expression emitted twice");
+ assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function");
+ assert(Block->getType()->isPointerTy() && "Invalid block literal type");
+ EnqueuedBlockMap[E].InvokeFunc = InvokeF;
+ EnqueuedBlockMap[E].BlockArg = Block;
+ EnqueuedBlockMap[E].Kernel = nullptr;
+}
+
+llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {
+ return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;
+}
+
+CGOpenCLRuntime::EnqueuedBlockInfo
+CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
+ CGF.EmitScalarExpr(E);
+
+ const BlockExpr *Block = getBlockExpr(E);
+ assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
+ "Block expression not emitted");
- // 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;
+ // Do not emit the block wrapper again if it has been emitted.
+ if (EnqueuedBlockMap[Block].Kernel) {
+ return EnqueuedBlockMap[Block];
}
- // 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());
+ CGF, EnqueuedBlockMap[Block].InvokeFunc,
+ EnqueuedBlockMap[Block].BlockArg->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;
+ EnqueuedBlockMap[Block].Kernel = F;
+ return EnqueuedBlockMap[Block];
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
index ead303d1d0d5..a513340827a8 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
@@ -23,6 +23,7 @@
namespace clang {
+class BlockExpr;
class Expr;
class VarDecl;
@@ -34,20 +35,25 @@ class CodeGenModule;
class CGOpenCLRuntime {
protected:
CodeGenModule &CGM;
- llvm::Type *PipeTy;
+ llvm::Type *PipeROTy;
+ llvm::Type *PipeWOTy;
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.
+ llvm::Function *InvokeFunc; /// Block invoke function.
+ 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;
+ virtual llvm::Type *getPipeType(const PipeType *T, StringRef Name,
+ llvm::Type *&PipeTy);
+
public:
- CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr),
- SamplerTy(nullptr) {}
+ CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM),
+ PipeROTy(nullptr), PipeWOTy(nullptr), SamplerTy(nullptr) {}
virtual ~CGOpenCLRuntime();
/// Emit the IR required for a work-group-local variable declaration, and add
@@ -62,11 +68,11 @@ public:
llvm::PointerType *getSamplerType(const Type *T);
- // \brief Returnes a value which indicates the size in bytes of the pipe
+ // Returns a value which indicates the size in bytes of the pipe
// element.
virtual llvm::Value *getPipeElemSize(const Expr *PipeArg);
- // \brief Returnes a value which indicates the alignment in bytes of the pipe
+ // Returns a value which indicates the alignment in bytes of the pipe
// element.
virtual llvm::Value *getPipeElemAlign(const Expr *PipeArg);
@@ -76,6 +82,19 @@ public:
/// \return enqueued block information for enqueued block.
EnqueuedBlockInfo emitOpenCLEnqueuedBlock(CodeGenFunction &CGF,
const Expr *E);
+
+ /// Record invoke function and block literal emitted during normal
+ /// codegen for a block expression. The information is used by
+ /// emitOpenCLEnqueuedBlock to emit wrapper kernel.
+ ///
+ /// \param InvokeF invoke function emitted for the block expression.
+ /// \param Block block literal emitted for the block expression.
+ void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF,
+ llvm::Value *Block);
+
+ /// \return LLVM block invoke function emitted for an expression derived from
+ /// the block expression.
+ llvm::Function *getInvokeFunction(const Expr *E);
};
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 784c90a9eb91..4454c719864f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -14,12 +14,13 @@
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGOpenMPRuntime.h"
+#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Basic/BitmaskEnum.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"
@@ -33,20 +34,20 @@ using namespace clang;
using namespace CodeGen;
namespace {
-/// \brief Base class for handling code generation inside OpenMP regions.
+/// Base class for handling code generation inside OpenMP regions.
class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
public:
- /// \brief Kinds of OpenMP regions used in codegen.
+ /// Kinds of OpenMP regions used in codegen.
enum CGOpenMPRegionKind {
- /// \brief Region with outlined function for standalone 'parallel'
+ /// Region with outlined function for standalone 'parallel'
/// directive.
ParallelOutlinedRegion,
- /// \brief Region with outlined function for standalone 'task' directive.
+ /// Region with outlined function for standalone 'task' directive.
TaskOutlinedRegion,
- /// \brief Region for constructs that do not require function outlining,
+ /// Region for constructs that do not require function outlining,
/// like 'for', 'sections', 'atomic' etc. directives.
InlinedRegion,
- /// \brief Region with outlined function for standalone 'target' directive.
+ /// Region with outlined function for standalone 'target' directive.
TargetRegion,
};
@@ -63,14 +64,14 @@ public:
: CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Kind(Kind), HasCancel(HasCancel) {}
- /// \brief Get a variable or parameter for storing global thread id
+ /// Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
virtual const VarDecl *getThreadIDVariable() const = 0;
- /// \brief Emit the captured statement body.
+ /// Emit the captured statement body.
void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
- /// \brief Get an LValue for the current ThreadID variable.
+ /// Get an LValue for the current ThreadID variable.
/// \return LValue for thread id variable. This LValue always has type int32*.
virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
@@ -95,7 +96,7 @@ protected:
bool HasCancel;
};
-/// \brief API for captured statement code generation in OpenMP constructs.
+/// API for captured statement code generation in OpenMP constructs.
class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
public:
CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
@@ -108,11 +109,11 @@ public:
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
- /// \brief Get a variable or parameter for storing global thread id
+ /// Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
- /// \brief Get the name of the capture helper.
+ /// Get the name of the capture helper.
StringRef getHelperName() const override { return HelperName; }
static bool classof(const CGCapturedStmtInfo *Info) {
@@ -122,13 +123,13 @@ public:
}
private:
- /// \brief A variable or parameter storing global thread id for OpenMP
+ /// A variable or parameter storing global thread id for OpenMP
/// constructs.
const VarDecl *ThreadIDVar;
StringRef HelperName;
};
-/// \brief API for captured statement code generation in OpenMP constructs.
+/// API for captured statement code generation in OpenMP constructs.
class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
public:
class UntiedTaskActionTy final : public PrePostActionTy {
@@ -144,11 +145,12 @@ public:
void Enter(CodeGenFunction &CGF) override {
if (Untied) {
// Emit task switching point.
- auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
+ LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
CGF.GetAddrOfLocalVar(PartIDVar),
PartIDVar->getType()->castAs<PointerType>());
- auto *Res = CGF.EmitLoadOfScalar(PartIdLVal, SourceLocation());
- auto *DoneBB = CGF.createBasicBlock(".untied.done.");
+ llvm::Value *Res =
+ CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
+ llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
CGF.EmitBlock(DoneBB);
CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
@@ -160,7 +162,7 @@ public:
}
void emitUntiedSwitch(CodeGenFunction &CGF) const {
if (Untied) {
- auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
+ LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
CGF.GetAddrOfLocalVar(PartIDVar),
PartIDVar->getType()->castAs<PointerType>());
CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
@@ -188,14 +190,14 @@ public:
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
- /// \brief Get a variable or parameter for storing global thread id
+ /// Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
- /// \brief Get an LValue for the current ThreadID variable.
+ /// Get an LValue for the current ThreadID variable.
LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
- /// \brief Get the name of the capture helper.
+ /// Get the name of the capture helper.
StringRef getHelperName() const override { return ".omp_outlined."; }
void emitUntiedSwitch(CodeGenFunction &CGF) override {
@@ -209,14 +211,14 @@ public:
}
private:
- /// \brief A variable or parameter storing global thread id for OpenMP
+ /// A variable or parameter storing global thread id for OpenMP
/// constructs.
const VarDecl *ThreadIDVar;
/// Action for emitting code for untied tasks.
const UntiedTaskActionTy &Action;
};
-/// \brief API for inlined captured statement code generation in OpenMP
+/// API for inlined captured statement code generation in OpenMP
/// constructs.
class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
public:
@@ -227,7 +229,7 @@ public:
OldCSI(OldCSI),
OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
- // \brief Retrieve the value of the context parameter.
+ // Retrieve the value of the context parameter.
llvm::Value *getContextValue() const override {
if (OuterRegionInfo)
return OuterRegionInfo->getContextValue();
@@ -242,7 +244,7 @@ public:
llvm_unreachable("No context value for inlined OpenMP region");
}
- /// \brief Lookup the captured field decl for a variable.
+ /// Lookup the captured field decl for a variable.
const FieldDecl *lookup(const VarDecl *VD) const override {
if (OuterRegionInfo)
return OuterRegionInfo->lookup(VD);
@@ -257,7 +259,7 @@ public:
return nullptr;
}
- /// \brief Get a variable or parameter for storing global thread id
+ /// Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
const VarDecl *getThreadIDVariable() const override {
if (OuterRegionInfo)
@@ -265,14 +267,14 @@ public:
return nullptr;
}
- /// \brief Get an LValue for the current ThreadID variable.
+ /// Get an LValue for the current ThreadID variable.
LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
if (OuterRegionInfo)
return OuterRegionInfo->getThreadIDVariableLValue(CGF);
llvm_unreachable("No LValue for inlined OpenMP construct");
}
- /// \brief Get the name of the capture helper.
+ /// Get the name of the capture helper.
StringRef getHelperName() const override {
if (auto *OuterRegionInfo = getOldCSI())
return OuterRegionInfo->getHelperName();
@@ -294,12 +296,12 @@ public:
~CGOpenMPInlinedRegionInfo() override = default;
private:
- /// \brief CodeGen info about outer OpenMP region.
+ /// CodeGen info about outer OpenMP region.
CodeGenFunction::CGCapturedStmtInfo *OldCSI;
CGOpenMPRegionInfo *OuterRegionInfo;
};
-/// \brief API for captured statement code generation in OpenMP target
+/// API for captured statement code generation in OpenMP target
/// constructs. For this captures, implicit parameters are used instead of the
/// captured fields. The name of the target region has to be unique in a given
/// application so it is provided by the client, because only the client has
@@ -312,11 +314,11 @@ public:
/*HasCancel=*/false),
HelperName(HelperName) {}
- /// \brief This is unused for target regions because each starts executing
+ /// This is unused for target regions because each starts executing
/// with a single thread.
const VarDecl *getThreadIDVariable() const override { return nullptr; }
- /// \brief Get the name of the capture helper.
+ /// Get the name of the capture helper.
StringRef getHelperName() const override { return HelperName; }
static bool classof(const CGCapturedStmtInfo *Info) {
@@ -331,7 +333,7 @@ private:
static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
llvm_unreachable("No codegen for expressions");
}
-/// \brief API for generation of expressions captured in a innermost OpenMP
+/// API for generation of expressions captured in a innermost OpenMP
/// region.
class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
public:
@@ -343,7 +345,7 @@ public:
// Make sure the globals captured in the provided statement are local by
// using the privatization logic. We assume the same variable is not
// captured more than once.
- for (auto &C : CS.captures()) {
+ for (const auto &C : CS.captures()) {
if (!C.capturesVariable() && !C.capturesVariableByCopy())
continue;
@@ -354,33 +356,32 @@ public:
DeclRefExpr DRE(const_cast<VarDecl *>(VD),
/*RefersToEnclosingVariableOrCapture=*/false,
VD->getType().getNonReferenceType(), VK_LValue,
- SourceLocation());
- PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address {
- return CGF.EmitLValue(&DRE).getAddress();
- });
+ C.getLocation());
+ PrivScope.addPrivate(
+ VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); });
}
(void)PrivScope.Privatize();
}
- /// \brief Lookup the captured field decl for a variable.
+ /// Lookup the captured field decl for a variable.
const FieldDecl *lookup(const VarDecl *VD) const override {
- if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
+ if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
return FD;
return nullptr;
}
- /// \brief Emit the captured statement body.
+ /// Emit the captured statement body.
void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
llvm_unreachable("No body for expressions");
}
- /// \brief Get a variable or parameter for storing global thread id
+ /// Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
const VarDecl *getThreadIDVariable() const override {
llvm_unreachable("No thread id for expressions");
}
- /// \brief Get the name of the capture helper.
+ /// Get the name of the capture helper.
StringRef getHelperName() const override {
llvm_unreachable("No helper name for expressions");
}
@@ -392,7 +393,7 @@ private:
CodeGenFunction::OMPPrivateScope PrivScope;
};
-/// \brief RAII for emitting code of OpenMP constructs.
+/// RAII for emitting code of OpenMP constructs.
class InlinedOpenMPRegionRAII {
CodeGenFunction &CGF;
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
@@ -400,7 +401,7 @@ class InlinedOpenMPRegionRAII {
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
public:
- /// \brief Constructs region for combined constructs.
+ /// Constructs region for combined constructs.
/// \param CodeGen Code generation sequence for combined directives. Includes
/// a list of functions used for code generation of implicitly inlined
/// regions.
@@ -429,25 +430,25 @@ public:
}
};
-/// \brief Values for bit flags used in the ident_t to describe the fields.
+/// 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 : unsigned {
- /// \brief Use trampoline for internal microtask.
+ /// Use trampoline for internal microtask.
OMP_IDENT_IMD = 0x01,
- /// \brief Use c-style ident structure.
+ /// Use c-style ident structure.
OMP_IDENT_KMPC = 0x02,
- /// \brief Atomic reduction option for kmpc_reduce.
+ /// Atomic reduction option for kmpc_reduce.
OMP_ATOMIC_REDUCE = 0x10,
- /// \brief Explicit 'barrier' directive.
+ /// Explicit 'barrier' directive.
OMP_IDENT_BARRIER_EXPL = 0x20,
- /// \brief Implicit barrier in code.
+ /// Implicit barrier in code.
OMP_IDENT_BARRIER_IMPL = 0x40,
- /// \brief Implicit barrier in 'for' directive.
+ /// Implicit barrier in 'for' directive.
OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
- /// \brief Implicit barrier in 'sections' directive.
+ /// Implicit barrier in 'sections' directive.
OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
- /// \brief Implicit barrier in 'single' directive.
+ /// Implicit barrier in 'single' directive.
OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
/// Call of __kmp_for_static_init for static loop.
OMP_IDENT_WORK_LOOP = 0x200,
@@ -458,7 +459,7 @@ enum OpenMPLocationFlags : unsigned {
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
};
-/// \brief Describes ident structure that describes a source location.
+/// Describes ident structure that describes a source location.
/// All descriptions are taken from
/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
/// Original structure:
@@ -485,24 +486,24 @@ enum OpenMPLocationFlags : unsigned {
/// */
/// } ident_t;
enum IdentFieldIndex {
- /// \brief might be used in Fortran
+ /// might be used in Fortran
IdentField_Reserved_1,
- /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
+ /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
IdentField_Flags,
- /// \brief Not really used in Fortran any more
+ /// Not really used in Fortran any more
IdentField_Reserved_2,
- /// \brief Source[4] in Fortran, do not use for C++
+ /// Source[4] in Fortran, do not use for C++
IdentField_Reserved_3,
- /// \brief String describing the source location. The string is composed of
+ /// String describing the source location. The string is composed of
/// semi-colon separated fields which describe the source file, the function
/// and a pair of line numbers that delimit the construct.
IdentField_PSource
};
-/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
+/// Schedule types for 'omp for' loops (these enumerators are taken from
/// the enum sched_type in kmp.h).
enum OpenMPSchedType {
- /// \brief Lower bound for default (unordered) versions.
+ /// Lower bound for default (unordered) versions.
OMP_sch_lower = 32,
OMP_sch_static_chunked = 33,
OMP_sch_static = 34,
@@ -512,7 +513,7 @@ enum OpenMPSchedType {
OMP_sch_auto = 38,
/// static with chunk adjustment (e.g., simd)
OMP_sch_static_balanced_chunked = 45,
- /// \brief Lower bound for 'ordered' versions.
+ /// Lower bound for 'ordered' versions.
OMP_ord_lower = 64,
OMP_ord_static_chunked = 65,
OMP_ord_static = 66,
@@ -521,7 +522,7 @@ enum OpenMPSchedType {
OMP_ord_runtime = 69,
OMP_ord_auto = 70,
OMP_sch_default = OMP_sch_static,
- /// \brief dist_schedule types
+ /// dist_schedule types
OMP_dist_sch_static_chunked = 91,
OMP_dist_sch_static = 92,
/// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
@@ -532,13 +533,13 @@ enum OpenMPSchedType {
};
enum OpenMPRTLFunction {
- /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
+ /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
/// kmpc_micro microtask, ...);
OMPRTL__kmpc_fork_call,
- /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
+ /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
/// kmp_int32 global_tid, void *data, size_t size, void ***cache);
OMPRTL__kmpc_threadprivate_cached,
- /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
+ /// Call to void __kmpc_threadprivate_register( ident_t *,
/// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
OMPRTL__kmpc_threadprivate_register,
// Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
@@ -746,11 +747,11 @@ void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
/// UDR decl used for reduction.
static const OMPDeclareReductionDecl *
getReductionInit(const Expr *ReductionOp) {
- if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
- if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
- if (auto *DRE =
+ if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
+ if (const auto *DRE =
dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
- if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
+ if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
return DRD;
return nullptr;
}
@@ -763,48 +764,51 @@ static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
if (DRD->getInitializer()) {
std::pair<llvm::Function *, llvm::Function *> Reduction =
CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
- auto *CE = cast<CallExpr>(InitOp);
- auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
+ const auto *CE = cast<CallExpr>(InitOp);
+ const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
- auto *LHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
- auto *RHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
+ const auto *LHSDRE =
+ cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
+ const auto *RHSDRE =
+ cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
- [=]() -> Address { return Private; });
+ [=]() { return Private; });
PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
- [=]() -> Address { return Original; });
+ [=]() { return Original; });
(void)PrivateScope.Privatize();
RValue Func = RValue::get(Reduction.second);
CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
CGF.EmitIgnoredExpr(InitOp);
} else {
llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
+ std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
auto *GV = new llvm::GlobalVariable(
CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
- llvm::GlobalValue::PrivateLinkage, Init, ".init");
+ llvm::GlobalValue::PrivateLinkage, Init, Name);
LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
RValue InitRVal;
switch (CGF.getEvaluationKind(Ty)) {
case TEK_Scalar:
- InitRVal = CGF.EmitLoadOfLValue(LV, SourceLocation());
+ InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
break;
case TEK_Complex:
InitRVal =
- RValue::getComplex(CGF.EmitLoadOfComplex(LV, SourceLocation()));
+ RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
break;
case TEK_Aggregate:
InitRVal = RValue::getAggregate(LV.getAddress());
break;
}
- OpaqueValueExpr OVE(SourceLocation(), Ty, VK_RValue);
+ OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
/*IsInitializer=*/false);
}
}
-/// \brief Emit initialization of arrays of complex types.
+/// Emit initialization of arrays of complex types.
/// \param DestAddr Address of the array.
/// \param Type Type of array.
/// \param Init Initial expression of array.
@@ -818,8 +822,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
QualType ElementTy;
// Drill down to the base element type on both arrays.
- auto ArrayTy = Type->getAsArrayTypeUnsafe();
- auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
+ const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
+ llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
DestAddr =
CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
if (DRD)
@@ -829,18 +833,18 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
llvm::Value *SrcBegin = nullptr;
if (DRD)
SrcBegin = SrcAddr.getPointer();
- auto DestBegin = DestAddr.getPointer();
+ llvm::Value *DestBegin = DestAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- auto DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
+ llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
// The basic structure here is a while-do loop.
- auto BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
- auto DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
- auto IsEmpty =
+ llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
+ llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
+ llvm::Value *IsEmpty =
CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
// Enter the loop body, making that address the current address.
- auto EntryBB = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
CGF.EmitBlock(BodyBB);
CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
@@ -875,16 +879,16 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
if (DRD) {
// Shift the address forward by one element.
- auto SrcElementNext = CGF.Builder.CreateConstGEP1_32(
+ llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
}
// Shift the address forward by one element.
- auto DestElementNext = CGF.Builder.CreateConstGEP1_32(
+ llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
// Check whether we've reached the end.
- auto Done =
+ llvm::Value *Done =
CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
@@ -910,7 +914,7 @@ void ReductionCodeGen::emitAggregateInitialization(
// Emit VarDecl with copy init for arrays.
// Get the address of the original variable captured in current
// captured region.
- auto *PrivateVD =
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
bool EmitDeclareReductionInit =
DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
@@ -930,7 +934,7 @@ ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
BaseDecls.reserve(Shareds.size());
auto IPriv = Privates.begin();
auto IRed = ReductionOps.begin();
- for (const auto *Ref : Shareds) {
+ for (const Expr *Ref : Shareds) {
ClausesData.emplace_back(Ref, *IPriv, *IRed);
std::advance(IPriv, 1);
std::advance(IRed, 1);
@@ -946,7 +950,7 @@ void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
}
void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
- auto *PrivateVD =
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
QualType PrivateType = PrivateVD->getType();
bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
@@ -959,7 +963,7 @@ void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
}
llvm::Value *Size;
llvm::Value *SizeInChars;
- llvm::Type *ElemType =
+ auto *ElemType =
cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType())
->getElementType();
auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
@@ -985,7 +989,7 @@ void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
llvm::Value *Size) {
- auto *PrivateVD =
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
QualType PrivateType = PrivateVD->getType();
if (!PrivateType->isVariablyModifiedType()) {
@@ -1006,9 +1010,10 @@ void ReductionCodeGen::emitInitialization(
CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
assert(SharedAddresses.size() > N && "No variable was generated");
- auto *PrivateVD =
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
- auto *DRD = getReductionInit(ClausesData[N].ReductionOp);
+ const OMPDeclareReductionDecl *DRD =
+ getReductionInit(ClausesData[N].ReductionOp);
QualType PrivateType = PrivateVD->getType();
PrivateAddr = CGF.Builder.CreateElementBitCast(
PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
@@ -1033,7 +1038,7 @@ void ReductionCodeGen::emitInitialization(
}
bool ReductionCodeGen::needCleanups(unsigned N) {
- auto *PrivateVD =
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
QualType PrivateType = PrivateVD->getType();
QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
@@ -1042,7 +1047,7 @@ bool ReductionCodeGen::needCleanups(unsigned N) {
void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
Address PrivateAddr) {
- auto *PrivateVD =
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
QualType PrivateType = PrivateVD->getType();
QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
@@ -1058,9 +1063,9 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
BaseTy = BaseTy.getNonReferenceType();
while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
!CGF.getContext().hasSameType(BaseTy, ElTy)) {
- if (auto *PtrTy = BaseTy->getAs<PointerType>())
+ if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
- else {
+ } else {
LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
}
@@ -1101,28 +1106,32 @@ static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
return Address(Addr, BaseLVAlignment);
}
-Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
- Address PrivateAddr) {
- const DeclRefExpr *DE;
+static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
const VarDecl *OrigVD = nullptr;
- if (auto *OASE = dyn_cast<OMPArraySectionExpr>(ClausesData[N].Ref)) {
- auto *Base = OASE->getBase()->IgnoreParenImpCasts();
- while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
+ if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
+ const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
+ while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Base = TempOASE->getBase()->IgnoreParenImpCasts();
- while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Base = TempASE->getBase()->IgnoreParenImpCasts();
DE = cast<DeclRefExpr>(Base);
OrigVD = cast<VarDecl>(DE->getDecl());
- } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(ClausesData[N].Ref)) {
- auto *Base = ASE->getBase()->IgnoreParenImpCasts();
- while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
+ const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
+ while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Base = TempASE->getBase()->IgnoreParenImpCasts();
DE = cast<DeclRefExpr>(Base);
OrigVD = cast<VarDecl>(DE->getDecl());
}
- if (OrigVD) {
+ return OrigVD;
+}
+
+Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
+ Address PrivateAddr) {
+ const DeclRefExpr *DE;
+ if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
BaseDecls.emplace_back(OrigVD);
- auto OriginalBaseLValue = CGF.EmitLValue(DE);
+ LValue OriginalBaseLValue = CGF.EmitLValue(DE);
LValue BaseLValue =
loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
OriginalBaseLValue);
@@ -1144,7 +1153,8 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
}
bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
- auto *DRD = getReductionInit(ClausesData[N].ReductionOp);
+ const OMPDeclareReductionDecl *DRD =
+ getReductionInit(ClausesData[N].ReductionOp);
return DRD && DRD->getInitializer();
}
@@ -1174,12 +1184,38 @@ LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
AlignmentSource::Decl);
}
-CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
- : CGM(CGM), OffloadEntriesInfoManager(CGM) {
- IdentTy = llvm::StructType::create(
- "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
- CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
- CGM.Int8PtrTy /* psource */);
+static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
+ QualType FieldTy) {
+ auto *Field = FieldDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
+ C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ DC->addDecl(Field);
+ return Field;
+}
+
+CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
+ StringRef Separator)
+ : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
+ OffloadEntriesInfoManager(CGM) {
+ ASTContext &C = CGM.getContext();
+ RecordDecl *RD = C.buildImplicitRecord("ident_t");
+ QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ RD->startDefinition();
+ // reserved_1
+ addFieldToRecordDecl(C, RD, KmpInt32Ty);
+ // flags
+ addFieldToRecordDecl(C, RD, KmpInt32Ty);
+ // reserved_2
+ addFieldToRecordDecl(C, RD, KmpInt32Ty);
+ // reserved_3
+ addFieldToRecordDecl(C, RD, KmpInt32Ty);
+ // psource
+ addFieldToRecordDecl(C, RD, C.VoidPtrTy);
+ RD->completeDefinition();
+ IdentQTy = C.getRecordType(RD);
+ IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
loadOffloadInfoMetadata();
@@ -1189,12 +1225,23 @@ void CGOpenMPRuntime::clear() {
InternalVars.clear();
}
+std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
+ SmallString<128> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+ StringRef Sep = FirstSeparator;
+ for (StringRef Part : Parts) {
+ OS << Sep << Part;
+ Sep = Separator;
+ }
+ return OS.str();
+}
+
static llvm::Function *
emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
const Expr *CombinerInitializer, const VarDecl *In,
const VarDecl *Out, bool IsCombiner) {
// void .omp_combiner.(Ty *in, Ty *out);
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
QualType PtrTy = C.getPointerType(Ty).withRestrict();
FunctionArgList Args;
ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
@@ -1203,28 +1250,30 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
/*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Args.push_back(&OmpOutParm);
Args.push_back(&OmpInParm);
- auto &FnInfo =
+ const CGFunctionInfo &FnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
- auto *Fn = llvm::Function::Create(
- FnTy, llvm::GlobalValue::InternalLinkage,
- IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ std::string Name = CGM.getOpenMPRuntime().getName(
+ {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
+ auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
+ Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Fn->removeFnAttr(llvm::Attribute::NoInline);
Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
Fn->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
// Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
// Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
+ Out->getLocation());
CodeGenFunction::OMPPrivateScope Scope(CGF);
Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
- Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
+ Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
.getAddress();
});
Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
- Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
+ Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
.getAddress();
});
@@ -1246,7 +1295,7 @@ void CGOpenMPRuntime::emitUserDefinedReduction(
CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
if (UDRMap.count(D) > 0)
return;
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
if (!In || !Out) {
In = &C.Idents.get("omp_in");
Out = &C.Idents.get("omp_out");
@@ -1256,7 +1305,7 @@ void CGOpenMPRuntime::emitUserDefinedReduction(
cast<VarDecl>(D->lookup(Out).front()),
/*IsCombiner=*/true);
llvm::Function *Initializer = nullptr;
- if (auto *Init = D->getInitializer()) {
+ if (const Expr *Init = D->getInitializer()) {
if (!Priv || !Orig) {
Priv = &C.Idents.get("omp_priv");
Orig = &C.Idents.get("omp_orig");
@@ -1269,7 +1318,7 @@ void CGOpenMPRuntime::emitUserDefinedReduction(
cast<VarDecl>(D->lookup(Priv).front()),
/*IsCombiner=*/false);
}
- UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
+ UDRMap.try_emplace(D, Combiner, Initializer);
if (CGF) {
auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
Decls.second.push_back(D);
@@ -1285,25 +1334,6 @@ CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
return UDRMap.lookup(D);
}
-// Layout information for ident_t.
-static CharUnits getIdentAlign(CodeGenModule &CGM) {
- return CGM.getPointerAlign();
-}
-static CharUnits getIdentSize(CodeGenModule &CGM) {
- assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
- return CharUnits::fromQuantity(16) + CGM.getPointerSize();
-}
-static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
- // All the fields except the last are i32, so this works beautifully.
- return unsigned(Field) * CharUnits::fromQuantity(4);
-}
-static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
- IdentFieldIndex Field,
- const llvm::Twine &Name = "") {
- auto Offset = getOffsetOfIdentField(Field);
- return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
-}
-
static llvm::Value *emitParallelOrTeamsOutlinedFunction(
CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
@@ -1312,19 +1342,20 @@ static llvm::Value *emitParallelOrTeamsOutlinedFunction(
"thread id variable must be of type kmp_int32 *");
CodeGenFunction CGF(CGM, true);
bool HasCancel = false;
- if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
+ if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
HasCancel = OPD->hasCancel();
- else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
+ else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
HasCancel = OPSD->hasCancel();
- else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
+ else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
HasCancel = OPFD->hasCancel();
- else if (auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
+ else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
HasCancel = OPFD->hasCancel();
- else if (auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
+ else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
HasCancel = OPFD->hasCancel();
- else if (auto *OPFD = dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
+ else if (const auto *OPFD =
+ dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
HasCancel = OPFD->hasCancel();
- else if (auto *OPFD =
+ else if (const auto *OPFD =
dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
HasCancel = OPFD->hasCancel();
CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
@@ -1356,8 +1387,8 @@ llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
bool Tied, unsigned &NumberOfParts) {
auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
PrePostActionTy &) {
- auto *ThreadID = getThreadID(CGF, D.getLocStart());
- auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
+ llvm::Value *ThreadID = getThreadID(CGF, D.getLocStart());
+ llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
llvm::Value *TaskArgs[] = {
UpLoc, ThreadID,
CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
@@ -1370,21 +1401,69 @@ llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
CodeGen.setAction(Action);
assert(!ThreadIDVar->getType()->isPointerType() &&
"thread id variable must be of type kmp_int32 for tasks");
- auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
- auto *TD = dyn_cast<OMPTaskDirective>(&D);
+ const OpenMPDirectiveKind Region =
+ isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
+ : OMPD_task;
+ const CapturedStmt *CS = D.getCapturedStmt(Region);
+ const auto *TD = dyn_cast<OMPTaskDirective>(&D);
CodeGenFunction CGF(CGM, true);
CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
InnermostKind,
TD ? TD->hasCancel() : false, Action);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
- auto *Res = CGF.GenerateCapturedStmtFunction(*CS);
+ llvm::Value *Res = CGF.GenerateCapturedStmtFunction(*CS);
if (!Tied)
NumberOfParts = Action.getNumberOfParts();
return Res;
}
+static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
+ const RecordDecl *RD, const CGRecordLayout &RL,
+ ArrayRef<llvm::Constant *> Data) {
+ llvm::StructType *StructTy = RL.getLLVMType();
+ unsigned PrevIdx = 0;
+ ConstantInitBuilder CIBuilder(CGM);
+ auto DI = Data.begin();
+ for (const FieldDecl *FD : RD->fields()) {
+ unsigned Idx = RL.getLLVMFieldNo(FD);
+ // Fill the alignment.
+ for (unsigned I = PrevIdx; I < Idx; ++I)
+ Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
+ PrevIdx = Idx + 1;
+ Fields.add(*DI);
+ ++DI;
+ }
+}
+
+template <class... As>
+static llvm::GlobalVariable *
+createConstantGlobalStruct(CodeGenModule &CGM, QualType Ty,
+ ArrayRef<llvm::Constant *> Data, const Twine &Name,
+ As &&... Args) {
+ const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
+ const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
+ ConstantInitBuilder CIBuilder(CGM);
+ ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
+ buildStructValue(Fields, CGM, RD, RL, Data);
+ return Fields.finishAndCreateGlobal(
+ Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty),
+ /*isConstant=*/true, std::forward<As>(Args)...);
+}
+
+template <typename T>
+static void
+createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
+ ArrayRef<llvm::Constant *> Data,
+ T &Parent) {
+ const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
+ const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
+ ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
+ buildStructValue(Fields, CGM, RD, RL, Data);
+ Fields.finishAndAddTo(Parent);
+}
+
Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
- CharUnits Align = getIdentAlign(CGM);
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
if (!Entry) {
if (!DefaultOpenMPPSource) {
@@ -1398,17 +1477,15 @@ Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
}
- ConstantInitBuilder builder(CGM);
- auto fields = builder.beginStruct(IdentTy);
- fields.addInt(CGM.Int32Ty, 0);
- fields.addInt(CGM.Int32Ty, Flags);
- fields.addInt(CGM.Int32Ty, 0);
- fields.addInt(CGM.Int32Ty, 0);
- fields.add(DefaultOpenMPPSource);
- auto DefaultOpenMPLocation =
- fields.finishAndCreateGlobal("", Align, /*isConstant*/ true,
- llvm::GlobalValue::PrivateLinkage);
- DefaultOpenMPLocation->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ llvm::Constant *Data[] = {llvm::ConstantInt::getNullValue(CGM.Int32Ty),
+ llvm::ConstantInt::get(CGM.Int32Ty, Flags),
+ llvm::ConstantInt::getNullValue(CGM.Int32Ty),
+ llvm::ConstantInt::getNullValue(CGM.Int32Ty),
+ DefaultOpenMPPSource};
+ llvm::GlobalValue *DefaultOpenMPLocation = createConstantGlobalStruct(
+ CGM, IdentQTy, Data, "", llvm::GlobalValue::PrivateLinkage);
+ DefaultOpenMPLocation->setUnnamedAddr(
+ llvm::GlobalValue::UnnamedAddr::Global);
OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
}
@@ -1426,17 +1503,17 @@ llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
assert(CGF.CurFn && "No function in current CodeGenFunction.");
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Address LocValue = Address::invalid();
auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
if (I != OpenMPLocThreadIDMap.end())
- LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
+ LocValue = Address(I->second.DebugLoc, Align);
// OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
// GetOpenMPThreadID was called before this routine.
if (!LocValue.isValid()) {
// Generate "ident_t .kmpc_loc.addr;"
- Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
- ".kmpc_loc.addr");
+ Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
Elem.second.DebugLoc = AI.getPointer();
LocValue = AI;
@@ -1444,29 +1521,30 @@ llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
- CGM.getSize(getIdentSize(CGF.CGM)));
+ CGF.getTypeSize(IdentQTy));
}
// char **psource = &.kmpc_loc_<flags>.addr.psource;
- Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
+ LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
+ auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
+ LValue PSource =
+ CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
- auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
+ llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
if (OMPDebugLoc == nullptr) {
SmallString<128> Buffer2;
llvm::raw_svector_ostream OS2(Buffer2);
// Build debug location
PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
OS2 << ";" << PLoc.getFilename() << ";";
- if (const FunctionDecl *FD =
- dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
OS2 << FD->getQualifiedNameAsString();
- }
OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
}
// *psource = ";<File>;<Function>;<Line>;<Column>;;";
- CGF.Builder.CreateStore(OMPDebugLoc, PSource);
+ CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
// Our callers always pass this to a runtime function, so for
// convenience, go ahead and return a naked pointer.
@@ -1494,8 +1572,8 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
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();
+ LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
+ ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
// If value loaded in entry block, cache it and use it everywhere in
// function.
if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
@@ -1513,7 +1591,7 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
// function.
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
- auto *Call = CGF.Builder.CreateCall(
+ llvm::CallInst *Call = CGF.Builder.CreateCall(
createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
emitUpdateLocation(CGF, Loc));
Call->setCallingConv(CGF.getRuntimeCC());
@@ -1527,17 +1605,14 @@ void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
if (OpenMPLocThreadIDMap.count(CGF.CurFn))
OpenMPLocThreadIDMap.erase(CGF.CurFn);
if (FunctionUDRMap.count(CGF.CurFn) > 0) {
- for(auto *D : FunctionUDRMap[CGF.CurFn]) {
+ for(auto *D : FunctionUDRMap[CGF.CurFn])
UDRMap.erase(D);
- }
FunctionUDRMap.erase(CGF.CurFn);
}
}
llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
- if (!IdentTy) {
- }
- return llvm::PointerType::getUnqual(IdentTy);
+ return IdentTy->getPointerTo();
}
llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
@@ -1559,7 +1634,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// microtask, ...);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
getKmpc_MicroPointerTy()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
break;
@@ -1567,7 +1642,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_global_thread_num: {
// Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
break;
@@ -1578,7 +1653,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.VoidPtrTy, CGM.SizeTy,
CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
break;
@@ -1589,7 +1664,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), CGM.Int32Ty,
llvm::PointerType::getUnqual(KmpCriticalNameTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
break;
@@ -1600,7 +1675,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
llvm::PointerType::getUnqual(KmpCriticalNameTy),
CGM.IntPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
break;
@@ -1609,21 +1684,22 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build void __kmpc_threadprivate_register(ident_t *, void *data,
// kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
// typedef void *(*kmpc_ctor)(void *);
- auto KmpcCtorTy =
+ auto *KmpcCtorTy =
llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
/*isVarArg*/ false)->getPointerTo();
// typedef void *(*kmpc_cctor)(void *, void *);
llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
- auto KmpcCopyCtorTy =
+ auto *KmpcCopyCtorTy =
llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
- /*isVarArg*/ false)->getPointerTo();
+ /*isVarArg*/ false)
+ ->getPointerTo();
// typedef void (*kmpc_dtor)(void *);
- auto KmpcDtorTy =
+ auto *KmpcDtorTy =
llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
->getPointerTo();
llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
KmpcCopyCtorTy, KmpcDtorTy};
- auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
+ auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
/*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
break;
@@ -1634,7 +1710,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), CGM.Int32Ty,
llvm::PointerType::getUnqual(KmpCriticalNameTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
break;
@@ -1643,7 +1719,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
// global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
break;
@@ -1651,7 +1727,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_barrier: {
// Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
break;
@@ -1659,7 +1735,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_for_static_fini: {
// Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
break;
@@ -1669,7 +1745,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// kmp_int32 num_threads)
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
break;
@@ -1678,7 +1754,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
// global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
break;
@@ -1687,7 +1763,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
// global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
break;
@@ -1695,7 +1771,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_flush: {
// Build void __kmpc_flush(ident_t *loc);
llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
break;
@@ -1703,7 +1779,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_master: {
// Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
break;
@@ -1711,7 +1787,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_end_master: {
// Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
break;
@@ -1720,7 +1796,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
// int end_part);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
break;
@@ -1728,7 +1804,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_single: {
// Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
break;
@@ -1736,7 +1812,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_end_single: {
// Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
break;
@@ -1750,7 +1826,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
// Return void * and then cast to particular kmp_task_t type.
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
break;
@@ -1760,7 +1836,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// *new_task);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
break;
@@ -1775,7 +1851,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
break;
@@ -1791,7 +1867,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
llvm::PointerType::getUnqual(KmpCriticalNameTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
break;
@@ -1808,7 +1884,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
llvm::PointerType::getUnqual(KmpCriticalNameTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
break;
@@ -1819,7 +1895,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), CGM.Int32Ty,
llvm::PointerType::getUnqual(KmpCriticalNameTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
break;
@@ -1830,7 +1906,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), CGM.Int32Ty,
llvm::PointerType::getUnqual(KmpCriticalNameTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn =
CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
@@ -1841,7 +1917,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// *new_task);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn =
CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
@@ -1852,7 +1928,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// *new_task);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy,
/*Name=*/"__kmpc_omp_task_complete_if0");
@@ -1861,7 +1937,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_ordered: {
// Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
break;
@@ -1869,7 +1945,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_end_ordered: {
// Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
break;
@@ -1877,7 +1953,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_omp_taskwait: {
// Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
break;
@@ -1885,7 +1961,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_taskgroup: {
// Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
break;
@@ -1893,7 +1969,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_end_taskgroup: {
// Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
break;
@@ -1902,7 +1978,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
// int proc_bind)
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
break;
@@ -1914,7 +1990,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn =
CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
@@ -1927,7 +2003,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.Int32Ty, CGM.VoidPtrTy,
CGM.Int32Ty, CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
break;
@@ -1936,7 +2012,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
// global_tid, kmp_int32 cncl_kind)
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
break;
@@ -1945,7 +2021,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 cncl_kind)
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
break;
@@ -1955,7 +2031,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// kmp_int32 num_teams, kmp_int32 num_threads)
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
break;
@@ -1965,7 +2041,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// microtask, ...);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
getKmpc_MicroPointerTy()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
break;
@@ -1985,7 +2061,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.IntTy,
CGM.Int64Ty,
CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
break;
@@ -1997,7 +2073,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.Int32Ty,
CGM.Int32Ty,
CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
break;
@@ -2005,7 +2081,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
case OMPRTL__kmpc_doacross_fini: {
// Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
break;
@@ -2015,7 +2091,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// *vec);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
break;
@@ -2025,7 +2101,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// *vec);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
break;
@@ -2034,7 +2110,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
// *data);
llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
RTLFn =
CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
@@ -2044,7 +2120,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
// Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
// *d);
llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
@@ -2061,7 +2137,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
break;
@@ -2077,7 +2153,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
break;
@@ -2095,7 +2171,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.Int64Ty->getPointerTo(),
CGM.Int32Ty,
CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
break;
@@ -2113,7 +2189,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.Int64Ty->getPointerTo(),
CGM.Int32Ty,
CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
break;
@@ -2123,7 +2199,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
QualType ParamTy =
CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
break;
@@ -2133,7 +2209,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
QualType ParamTy =
CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
break;
@@ -2147,7 +2223,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
break;
@@ -2176,7 +2252,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
break;
@@ -2205,7 +2281,7 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
CGM.Int64Ty->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
break;
@@ -2234,12 +2310,12 @@ llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
bool IVSigned) {
assert((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime");
- auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
- : "__kmpc_for_static_init_4u")
- : (IVSigned ? "__kmpc_for_static_init_8"
- : "__kmpc_for_static_init_8u");
- auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
- auto PtrTy = llvm::PointerType::getUnqual(ITy);
+ StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
+ : "__kmpc_for_static_init_4u")
+ : (IVSigned ? "__kmpc_for_static_init_8"
+ : "__kmpc_for_static_init_8u");
+ llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
+ auto *PtrTy = llvm::PointerType::getUnqual(ITy);
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), // loc
CGM.Int32Ty, // tid
@@ -2251,7 +2327,7 @@ llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
ITy, // incr
ITy // chunk
};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
return CGM.CreateRuntimeFunction(FnTy, Name);
}
@@ -2260,11 +2336,11 @@ llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
bool IVSigned) {
assert((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime");
- auto Name =
+ StringRef Name =
IVSize == 32
? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
: (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
- auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
+ llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
CGM.Int32Ty, // tid
CGM.Int32Ty, // schedtype
@@ -2273,7 +2349,7 @@ llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
ITy, // stride
ITy // chunk
};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
return CGM.CreateRuntimeFunction(FnTy, Name);
}
@@ -2282,7 +2358,7 @@ llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
bool IVSigned) {
assert((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime");
- auto Name =
+ StringRef Name =
IVSize == 32
? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
: (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
@@ -2290,7 +2366,7 @@ llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
getIdentTyPointerTy(), // loc
CGM.Int32Ty, // tid
};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FnTy, Name);
}
@@ -2299,12 +2375,12 @@ llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
bool IVSigned) {
assert((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime");
- auto Name =
+ StringRef Name =
IVSize == 32
? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
: (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
- auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
- auto PtrTy = llvm::PointerType::getUnqual(ITy);
+ llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
+ auto *PtrTy = llvm::PointerType::getUnqual(ITy);
llvm::Type *TypeParams[] = {
getIdentTyPointerTy(), // loc
CGM.Int32Ty, // tid
@@ -2313,18 +2389,48 @@ llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
PtrTy, // p_upper
PtrTy // p_stride
};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
return CGM.CreateRuntimeFunction(FnTy, Name);
}
+Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) {
+ if (CGM.getLangOpts().OpenMPSimd)
+ return Address::invalid();
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
+ SmallString<64> PtrName;
+ {
+ llvm::raw_svector_ostream OS(PtrName);
+ OS << CGM.getMangledName(GlobalDecl(VD)) << "_decl_tgt_link_ptr";
+ }
+ llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
+ if (!Ptr) {
+ QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
+ Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
+ PtrName);
+ if (!CGM.getLangOpts().OpenMPIsDevice) {
+ auto *GV = cast<llvm::GlobalVariable>(Ptr);
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setInitializer(CGM.GetAddrOfGlobal(VD));
+ }
+ CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ptr));
+ registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
+ }
+ return Address(Ptr, CGM.getContext().getDeclAlign(VD));
+ }
+ return Address::invalid();
+}
+
llvm::Constant *
CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
assert(!CGM.getLangOpts().OpenMPUseTLS ||
!CGM.getContext().getTargetInfo().isTLSSupported());
// Lookup the entry, lazily creating it if necessary.
- return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
- Twine(CGM.getMangledName(VD)) + ".cache.");
+ std::string Suffix = getName({"cache", ""});
+ return getOrCreateInternalVariable(
+ CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
}
Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
@@ -2335,7 +2441,7 @@ Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
CGM.getContext().getTargetInfo().isTLSSupported())
return VDAddr;
- auto VarTy = VDAddr.getElementType();
+ llvm::Type *VarTy = VDAddr.getElementType();
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
CGM.Int8PtrTy),
@@ -2351,15 +2457,14 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit(
llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
// Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
// library.
- auto OMPLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
OMPLoc);
// Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
// to register constructor/destructor for variable.
- llvm::Value *Args[] = {OMPLoc,
- CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
- CGM.VoidPtrTy),
- Ctor, CopyCtor, Dtor};
+ llvm::Value *Args[] = {
+ OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
+ Ctor, CopyCtor, Dtor};
CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
}
@@ -2377,29 +2482,31 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
QualType ASTTy = VD->getType();
llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
- auto Init = VD->getAnyInitializer();
+ const Expr *Init = VD->getAnyInitializer();
if (CGM.getLangOpts().CPlusPlus && PerformInit) {
// Generate function that re-emits the declaration's initializer into the
// threadprivate copy of the variable VD
CodeGenFunction CtorCGF(CGM);
FunctionArgList Args;
- ImplicitParamDecl Dst(CGM.getContext(), CGM.getContext().VoidPtrTy,
+ ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
ImplicitParamDecl::Other);
Args.push_back(&Dst);
- auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
+ const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
CGM.getContext().VoidPtrTy, Args);
- auto FTy = CGM.getTypes().GetFunctionType(FI);
- auto Fn = CGM.CreateGlobalInitOrDestructFunction(
- FTy, ".__kmpc_global_ctor_.", FI, Loc);
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ std::string Name = getName({"__kmpc_global_ctor_", ""});
+ llvm::Function *Fn =
+ CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
- Args, SourceLocation());
- auto ArgVal = CtorCGF.EmitLoadOfScalar(
+ Args, Loc, Loc);
+ llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
CGM.getContext().VoidPtrTy, Dst.getLocation());
Address Arg = Address(ArgVal, VDAddr.getAlignment());
- Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
- CtorCGF.ConvertTypeForMem(ASTTy));
+ Arg = CtorCGF.Builder.CreateElementBitCast(
+ Arg, CtorCGF.ConvertTypeForMem(ASTTy));
CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
/*IsInitializer=*/true);
ArgVal = CtorCGF.EmitLoadOfScalar(
@@ -2414,21 +2521,23 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
// of the variable VD
CodeGenFunction DtorCGF(CGM);
FunctionArgList Args;
- ImplicitParamDecl Dst(CGM.getContext(), CGM.getContext().VoidPtrTy,
+ ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
ImplicitParamDecl::Other);
Args.push_back(&Dst);
- auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
+ const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
CGM.getContext().VoidTy, Args);
- auto FTy = CGM.getTypes().GetFunctionType(FI);
- auto Fn = CGM.CreateGlobalInitOrDestructFunction(
- FTy, ".__kmpc_global_dtor_.", FI, Loc);
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ std::string Name = getName({"__kmpc_global_dtor_", ""});
+ llvm::Function *Fn =
+ CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
- SourceLocation());
+ Loc, Loc);
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
- auto ArgVal = DtorCGF.EmitLoadOfScalar(
+ llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
DtorCGF.GetAddrOfLocalVar(&Dst),
/*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
@@ -2442,34 +2551,36 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
return nullptr;
llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
- auto CopyCtorTy =
- llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
- /*isVarArg=*/false)->getPointerTo();
+ auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
+ /*isVarArg=*/false)
+ ->getPointerTo();
// Copying constructor for the threadprivate variable.
// Must be NULL - reserved by runtime, but currently it requires that this
// parameter is always NULL. Otherwise it fires assertion.
CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
if (Ctor == nullptr) {
- auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
- /*isVarArg=*/false)->getPointerTo();
+ auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
+ /*isVarArg=*/false)
+ ->getPointerTo();
Ctor = llvm::Constant::getNullValue(CtorTy);
}
if (Dtor == nullptr) {
- auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
- /*isVarArg=*/false)->getPointerTo();
+ auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
+ /*isVarArg=*/false)
+ ->getPointerTo();
Dtor = llvm::Constant::getNullValue(DtorTy);
}
if (!CGF) {
- auto InitFunctionTy =
+ auto *InitFunctionTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
- auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
- InitFunctionTy, ".__omp_threadprivate_init_.",
- CGM.getTypes().arrangeNullaryFunction());
+ std::string Name = getName({"__omp_threadprivate_init_", ""});
+ llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
+ InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
CodeGenFunction InitCGF(CGM);
FunctionArgList ArgList;
InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
CGM.getTypes().arrangeNullaryFunction(), ArgList,
- Loc);
+ Loc, Loc);
emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
InitCGF.FinishFunction();
return InitFunction;
@@ -2479,19 +2590,156 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
return nullptr;
}
+/// Obtain information that uniquely identifies a target entry. This
+/// consists of the file and device IDs as well as line number associated with
+/// the relevant entry source location.
+static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
+ unsigned &DeviceID, unsigned &FileID,
+ unsigned &LineNum) {
+ SourceManager &SM = C.getSourceManager();
+
+ // The loc should be always valid and have a file ID (the user cannot use
+ // #pragma directives in macros)
+
+ assert(Loc.isValid() && "Source location is expected to be always valid.");
+
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ assert(PLoc.isValid() && "Source location is expected to be always valid.");
+
+ llvm::sys::fs::UniqueID ID;
+ if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
+ SM.getDiagnostics().Report(diag::err_cannot_open_file)
+ << PLoc.getFilename() << EC.message();
+
+ DeviceID = ID.getDevice();
+ FileID = ID.getFile();
+ LineNum = PLoc.getLine();
+}
+
+bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
+ llvm::GlobalVariable *Addr,
+ bool PerformInit) {
+ Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link)
+ return false;
+ VD = VD->getDefinition(CGM.getContext());
+ if (VD && !DeclareTargetWithDefinition.insert(VD).second)
+ return CGM.getLangOpts().OpenMPIsDevice;
+
+ QualType ASTTy = VD->getType();
+
+ SourceLocation Loc = VD->getCanonicalDecl()->getLocStart();
+ // Produce the unique prefix to identify the new target regions. We use
+ // the source location of the variable declaration which we know to not
+ // conflict with any target region.
+ unsigned DeviceID;
+ unsigned FileID;
+ unsigned Line;
+ getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
+ SmallString<128> Buffer, Out;
+ {
+ llvm::raw_svector_ostream OS(Buffer);
+ OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
+ << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
+ }
+
+ const Expr *Init = VD->getAnyInitializer();
+ if (CGM.getLangOpts().CPlusPlus && PerformInit) {
+ llvm::Constant *Ctor;
+ llvm::Constant *ID;
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ // Generate function that re-emits the declaration's initializer into
+ // the threadprivate copy of the variable VD
+ CodeGenFunction CtorCGF(CGM);
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, Twine(Buffer, "_ctor"), FI, Loc);
+ auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
+ CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
+ FunctionArgList(), Loc, Loc);
+ auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
+ CtorCGF.EmitAnyExprToMem(Init,
+ Address(Addr, CGM.getContext().getDeclAlign(VD)),
+ Init->getType().getQualifiers(),
+ /*IsInitializer=*/true);
+ CtorCGF.FinishFunction();
+ Ctor = Fn;
+ ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
+ CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
+ } else {
+ Ctor = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage,
+ llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
+ ID = Ctor;
+ }
+
+ // Register the information for the entry associated with the constructor.
+ Out.clear();
+ OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
+ DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
+ ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
+ }
+ if (VD->getType().isDestructedType() != QualType::DK_none) {
+ llvm::Constant *Dtor;
+ llvm::Constant *ID;
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ // Generate function that emits destructor call for the threadprivate
+ // copy of the variable VD
+ CodeGenFunction DtorCGF(CGM);
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, Twine(Buffer, "_dtor"), FI, Loc);
+ auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
+ DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
+ FunctionArgList(), Loc, Loc);
+ // Create a scope with an artificial location for the body of this
+ // function.
+ auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
+ DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
+ ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
+ DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
+ DtorCGF.FinishFunction();
+ Dtor = Fn;
+ ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
+ CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
+ } else {
+ Dtor = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage,
+ llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
+ ID = Dtor;
+ }
+ // Register the information for the entry associated with the destructor.
+ Out.clear();
+ OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
+ DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
+ ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
+ }
+ return CGM.getLangOpts().OpenMPIsDevice;
+}
+
Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
QualType VarType,
StringRef Name) {
- llvm::Twine VarName(Name, ".artificial.");
+ std::string Suffix = getName({"artificial", ""});
+ std::string CacheSuffix = getName({"cache", ""});
llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
- llvm::Value *GAddr = getOrCreateInternalVariable(VarLVType, VarName);
+ llvm::Value *GAddr =
+ getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
llvm::Value *Args[] = {
emitUpdateLocation(CGF, SourceLocation()),
getThreadID(CGF, SourceLocation()),
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
/*IsSigned=*/false),
- getOrCreateInternalVariable(CGM.VoidPtrPtrTy, VarName + ".cache.")};
+ getOrCreateInternalVariable(
+ CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
return Address(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.EmitRuntimeCall(
@@ -2500,13 +2748,6 @@ Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
CGM.getPointerAlign());
}
-/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
-/// function. Here is the logic:
-/// if (Cond) {
-/// ThenGen();
-/// } else {
-/// ElseGen();
-/// }
void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
const RegionCodeGenTy &ThenGen,
const RegionCodeGenTy &ElseGen) {
@@ -2525,9 +2766,9 @@ void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
// Otherwise, the condition did not fold, or we couldn't elide it. Just
// emit the conditional branch.
- auto ThenBlock = CGF.createBasicBlock("omp_if.then");
- auto ElseBlock = CGF.createBasicBlock("omp_if.else");
- auto ContBlock = CGF.createBasicBlock("omp_if.end");
+ llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
+ llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
// Emit the 'then' code.
@@ -2552,11 +2793,11 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
const Expr *IfCond) {
if (!CGF.HaveInsertPoint())
return;
- auto *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
PrePostActionTy &) {
// Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
- auto &RT = CGF.CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
llvm::Value *Args[] = {
RTLoc,
CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
@@ -2565,13 +2806,13 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
RealArgs.append(std::begin(Args), std::end(Args));
RealArgs.append(CapturedVars.begin(), CapturedVars.end());
- auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
+ llvm::Value *RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
CGF.EmitRuntimeCall(RTLFn, RealArgs);
};
auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
PrePostActionTy &) {
- auto &RT = CGF.CGM.getOpenMPRuntime();
- auto ThreadID = RT.getThreadID(CGF, Loc);
+ CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
+ llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
// Build calls:
// __kmpc_serialized_parallel(&Loc, GTid);
llvm::Value *Args[] = {RTLoc, ThreadID};
@@ -2579,13 +2820,12 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
// OutlinedFn(&GTid, &zero, CapturedStruct);
- auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
- Address ZeroAddr =
- CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
- /*Name*/ ".zero.addr");
+ Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
+ /*Name*/ ".zero.addr");
CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
+ // ThreadId for serialized parallels is 0.
+ OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
@@ -2596,9 +2836,9 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
EndArgs);
};
- if (IfCond)
+ if (IfCond) {
emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
- else {
+ } else {
RegionCodeGenTy ThenRCG(ThenGen);
ThenRCG(CGF);
}
@@ -2617,10 +2857,10 @@ Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
if (OMPRegionInfo->getThreadIDVariable())
return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
- auto ThreadID = getThreadID(CGF, Loc);
- auto Int32Ty =
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ QualType Int32Ty =
CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
- auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
+ Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
CGF.EmitStoreOfScalar(ThreadID,
CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
@@ -2633,8 +2873,8 @@ CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
Out << Name;
- auto RuntimeName = Out.str();
- auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
+ StringRef RuntimeName = Out.str();
+ auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
if (Elem.second) {
assert(Elem.second->getType()->getPointerElementType() == Ty &&
"OMP internal variable has different type than requested");
@@ -2648,8 +2888,9 @@ CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
}
llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
- llvm::Twine Name(".gomp_critical_user_", CriticalName);
- return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
+ std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
+ std::string Name = getName({Prefix, "var"});
+ return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
}
namespace {
@@ -2783,21 +3024,28 @@ static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
static llvm::Value *emitCopyprivateCopyFunction(
CodeGenModule &CGM, llvm::Type *ArgsType,
ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
- ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
- auto &C = CGM.getContext();
+ ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
+ SourceLocation Loc) {
+ ASTContext &C = CGM.getContext();
// void copy_func(void *LHSArg, void *RHSArg);
FunctionArgList Args;
- ImplicitParamDecl LHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
- ImplicitParamDecl RHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
+ ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
Args.push_back(&LHSArg);
Args.push_back(&RHSArg);
- auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *Fn = llvm::Function::Create(
- CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
- ".omp.copyprivate.copy_func", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
+ const auto &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ std::string Name =
+ CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
+ auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
+ llvm::GlobalValue::InternalLinkage, Name,
+ &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
// Dest = (void*[n])(LHSArg);
// Src = (void*[n])(RHSArg);
Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
@@ -2811,13 +3059,15 @@ static llvm::Value *emitCopyprivateCopyFunction(
// ...
// *(Typen*)Dst[n] = *(Typen*)Src[n];
for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
- auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
+ const auto *DestVar =
+ cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
- auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
+ const auto *SrcVar =
+ cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
- auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
+ const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
QualType Type = VD->getType();
CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
}
@@ -2837,7 +3087,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
assert(CopyprivateVars.size() == SrcExprs.size() &&
CopyprivateVars.size() == DstExprs.size() &&
CopyprivateVars.size() == AssignmentOps.size());
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
// int32 did_it = 0;
// if(__kmpc_single(ident_t *, gtid)) {
// SingleOpGen();
@@ -2850,7 +3100,8 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Address DidIt = Address::invalid();
if (!CopyprivateVars.empty()) {
// int32 did_it = 0;
- auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ QualType KmpInt32Ty =
+ C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
}
@@ -2870,7 +3121,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
// <copy_func>, did_it);
if (DidIt.isValid()) {
llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
- auto CopyprivateArrayTy =
+ QualType CopyprivateArrayTy =
C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
// Create a list of all private variables for copyprivate.
@@ -2886,14 +3137,14 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
}
// Build function that copies private values from single region to all other
// threads in the corresponding parallel region.
- auto *CpyFn = emitCopyprivateCopyFunction(
+ llvm::Value *CpyFn = emitCopyprivateCopyFunction(
CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
- CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
- auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
+ CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
+ llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
Address CL =
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
CGF.VoidPtrTy);
- auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
+ llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), // ident_t *<loc>
getThreadID(CGF, Loc), // i32 <gtid>
@@ -2952,19 +3203,19 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
- auto *Result = CGF.EmitRuntimeCall(
+ llvm::Value *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
if (EmitChecks) {
// if (__kmpc_cancel_barrier()) {
// exit from construct;
// }
- auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
- auto *ContBB = CGF.createBasicBlock(".cancel.continue");
- auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
+ llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
+ llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// exit from construct;
- auto CancelDestination =
+ CodeGenFunction::JumpDest CancelDestination =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
CGF.EmitBranchThroughCleanup(CancelDestination);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
@@ -2975,7 +3226,7 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
}
-/// \brief Map the OpenMP loop schedule to the runtime enumeration.
+/// Map the OpenMP loop schedule to the runtime enumeration.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
bool Chunked, bool Ordered) {
switch (ScheduleKind) {
@@ -2997,7 +3248,7 @@ static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
llvm_unreachable("Unexpected runtime schedule");
}
-/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
+/// Map the OpenMP distribute schedule to the runtime enumeration.
static OpenMPSchedType
getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
// only static is allowed for dist_schedule
@@ -3006,19 +3257,20 @@ getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
bool Chunked) const {
- auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
+ OpenMPSchedType Schedule =
+ getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
return Schedule == OMP_sch_static;
}
bool CGOpenMPRuntime::isStaticNonchunked(
OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
- auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
+ OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
return Schedule == OMP_dist_sch_static;
}
bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
- auto Schedule =
+ OpenMPSchedType Schedule =
getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
return Schedule != OMP_sch_static;
@@ -3151,12 +3403,12 @@ void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
assert(isOpenMPWorksharingDirective(DKind) &&
"Expected loop-based or sections-based directive.");
- auto *UpdatedLocation = emitUpdateLocation(CGF, Loc,
+ llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
isOpenMPLoopDirective(DKind)
? OMP_IDENT_WORK_LOOP
: OMP_IDENT_WORK_SECTIONS);
- auto *ThreadId = getThreadID(CGF, Loc);
- auto *StaticInitFunction =
+ llvm::Value *ThreadId = getThreadID(CGF, Loc);
+ llvm::Constant *StaticInitFunction =
createForStaticInitFunction(Values.IVSize, Values.IVSigned);
emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
@@ -3168,10 +3420,10 @@ void CGOpenMPRuntime::emitDistributeStaticInit(
const CGOpenMPRuntime::StaticRTInput &Values) {
OpenMPSchedType ScheduleNum =
getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
- auto *UpdatedLocation =
+ llvm::Value *UpdatedLocation =
emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
- auto *ThreadId = getThreadID(CGF, Loc);
- auto *StaticInitFunction =
+ llvm::Value *ThreadId = getThreadID(CGF, Loc);
+ llvm::Constant *StaticInitFunction =
createForStaticInitFunction(Values.IVSize, Values.IVSigned);
emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
@@ -3227,7 +3479,7 @@ llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
llvm::Value *Call =
CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
return CGF.EmitScalarConversion(
- Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
+ Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
CGF.getContext().BoolTy, Loc);
}
@@ -3289,13 +3541,13 @@ void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
}
namespace {
-/// \brief Indexes of fields for type kmp_task_t.
+/// Indexes of fields for type kmp_task_t.
enum KmpTaskTFields {
- /// \brief List of shared variables.
+ /// List of shared variables.
KmpTaskTShareds,
- /// \brief Task routine.
+ /// Task routine.
KmpTaskTRoutine,
- /// \brief Partition id for the untied tasks.
+ /// Partition id for the untied tasks.
KmpTaskTPartId,
/// Function with call of destructors for private variables.
Data1,
@@ -3315,11 +3567,11 @@ enum KmpTaskTFields {
} // anonymous namespace
bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
- // FIXME: Add other entries type when they become supported.
- return OffloadEntriesTargetRegion.empty();
+ return OffloadEntriesTargetRegion.empty() &&
+ OffloadEntriesDeviceGlobalVar.empty();
}
-/// \brief Initialize target region entry.
+/// Initialize target region entry.
void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
@@ -3329,7 +3581,7 @@ void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
"code generation.");
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
- /*Flags=*/0);
+ OMPTargetRegionEntryTargetRegion);
++OffloadingEntriesNum;
}
@@ -3337,22 +3589,27 @@ void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
llvm::Constant *Addr, llvm::Constant *ID,
- int32_t Flags) {
+ OMPTargetRegionEntryKind Flags) {
// If we are emitting code for a target, the entry is already initialized,
// only has to be registered.
if (CGM.getLangOpts().OpenMPIsDevice) {
- assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
- "Entry must exist.");
+ if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "Unable to find target region on line '%0' in the device code.");
+ CGM.getDiags().Report(DiagID) << LineNum;
+ return;
+ }
auto &Entry =
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
assert(Entry.isValid() && "Entry not initialized!");
Entry.setAddress(Addr);
Entry.setID(ID);
Entry.setFlags(Flags);
- return;
} else {
- OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID, Flags);
+ OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
+ ++OffloadingEntriesNum;
}
}
@@ -3380,48 +3637,69 @@ bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
const OffloadTargetRegionEntryInfoActTy &Action) {
// Scan all target region entries and perform the provided action.
- for (auto &D : OffloadEntriesTargetRegion)
- for (auto &F : D.second)
- for (auto &P : F.second)
- for (auto &L : P.second)
+ for (const auto &D : OffloadEntriesTargetRegion)
+ for (const auto &F : D.second)
+ for (const auto &P : F.second)
+ for (const auto &L : P.second)
Action(D.first, F.first, P.first(), L.first, L.second);
}
-/// \brief Create a Ctor/Dtor-like function whose body is emitted through
-/// \a Codegen. This is used to emit the two functions that register and
-/// unregister the descriptor of the current compilation unit.
-static llvm::Function *
-createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
- const RegionCodeGenTy &Codegen) {
- auto &C = CGM.getContext();
- FunctionArgList Args;
- ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
- Args.push_back(&DummyPtr);
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ initializeDeviceGlobalVarEntryInfo(StringRef Name,
+ OMPTargetGlobalVarEntryKind Flags,
+ unsigned Order) {
+ assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
+ "only required for the device "
+ "code generation.");
+ OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
+ ++OffloadingEntriesNum;
+}
- CodeGenFunction CGF(CGM);
- auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto FTy = CGM.getTypes().GetFunctionType(FI);
- auto *Fn =
- CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
- Codegen(CGF);
- CGF.FinishFunction();
- return Fn;
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
+ CharUnits VarSize,
+ OMPTargetGlobalVarEntryKind Flags,
+ llvm::GlobalValue::LinkageTypes Linkage) {
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
+ assert(Entry.isValid() && Entry.getFlags() == Flags &&
+ "Entry not initialized!");
+ assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
+ "Resetting with the new address.");
+ if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName))
+ return;
+ Entry.setAddress(Addr);
+ Entry.setVarSize(VarSize);
+ Entry.setLinkage(Linkage);
+ } else {
+ if (hasDeviceGlobalVarEntryInfo(VarName))
+ return;
+ OffloadEntriesDeviceGlobalVar.try_emplace(
+ VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
+ ++OffloadingEntriesNum;
+ }
+}
+
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ actOnDeviceGlobalVarEntriesInfo(
+ const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
+ // Scan all target region entries and perform the provided action.
+ for (const auto &E : OffloadEntriesDeviceGlobalVar)
+ Action(E.getKey(), E.getValue());
}
llvm::Function *
CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
-
// If we don't have entries or if we are emitting code for the device, we
// don't need to do anything.
if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
return nullptr;
- auto &M = CGM.getModule();
- auto &C = CGM.getContext();
+ llvm::Module &M = CGM.getModule();
+ ASTContext &C = CGM.getContext();
// Get list of devices we care about
- auto &Devices = CGM.getLangOpts().OMPTargetTriples;
+ const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples;
// We should be creating an offloading descriptor only if there are devices
// specified.
@@ -3429,46 +3707,51 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
// Create the external variables that will point to the begin and end of the
// host entries section. These will be defined by the linker.
- auto *OffloadEntryTy =
+ llvm::Type *OffloadEntryTy =
CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
- llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
- M, OffloadEntryTy, /*isConstant=*/true,
- llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
- ".omp_offloading.entries_begin");
- llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
+ std::string EntriesBeginName = getName({"omp_offloading", "entries_begin"});
+ auto *HostEntriesBegin = new llvm::GlobalVariable(
M, OffloadEntryTy, /*isConstant=*/true,
llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
- ".omp_offloading.entries_end");
+ EntriesBeginName);
+ std::string EntriesEndName = getName({"omp_offloading", "entries_end"});
+ auto *HostEntriesEnd =
+ new llvm::GlobalVariable(M, OffloadEntryTy, /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, EntriesEndName);
// Create all device images
auto *DeviceImageTy = cast<llvm::StructType>(
CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
ConstantInitBuilder DeviceImagesBuilder(CGM);
- auto DeviceImagesEntries = DeviceImagesBuilder.beginArray(DeviceImageTy);
+ ConstantArrayBuilder DeviceImagesEntries =
+ DeviceImagesBuilder.beginArray(DeviceImageTy);
- for (unsigned i = 0; i < Devices.size(); ++i) {
- StringRef T = Devices[i].getTriple();
+ for (const llvm::Triple &Device : Devices) {
+ StringRef T = Device.getTriple();
+ std::string BeginName = getName({"omp_offloading", "img_start", ""});
auto *ImgBegin = new llvm::GlobalVariable(
- M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
- /*Initializer=*/nullptr,
- Twine(".omp_offloading.img_start.") + Twine(T));
+ M, CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::ExternalWeakLinkage,
+ /*Initializer=*/nullptr, Twine(BeginName).concat(T));
+ std::string EndName = getName({"omp_offloading", "img_end", ""});
auto *ImgEnd = new llvm::GlobalVariable(
- M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
- /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
+ M, CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::ExternalWeakLinkage,
+ /*Initializer=*/nullptr, Twine(EndName).concat(T));
- auto Dev = DeviceImagesEntries.beginStruct(DeviceImageTy);
- Dev.add(ImgBegin);
- Dev.add(ImgEnd);
- Dev.add(HostEntriesBegin);
- Dev.add(HostEntriesEnd);
- Dev.finishAndAddTo(DeviceImagesEntries);
+ llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin,
+ HostEntriesEnd};
+ createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data,
+ DeviceImagesEntries);
}
// Create device images global array.
+ std::string ImagesName = getName({"omp_offloading", "device_images"});
llvm::GlobalVariable *DeviceImages =
- DeviceImagesEntries.finishAndCreateGlobal(".omp_offloading.device_images",
- CGM.getPointerAlign(),
- /*isConstant=*/true);
+ DeviceImagesEntries.finishAndCreateGlobal(ImagesName,
+ CGM.getPointerAlign(),
+ /*isConstant=*/true);
DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
// This is a Zero array to be used in the creation of the constant expressions
@@ -3476,49 +3759,64 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
llvm::Constant::getNullValue(CGM.Int32Ty)};
// Create the target region descriptor.
- auto *BinaryDescriptorTy = cast<llvm::StructType>(
- CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
- ConstantInitBuilder DescBuilder(CGM);
- auto DescInit = DescBuilder.beginStruct(BinaryDescriptorTy);
- DescInit.addInt(CGM.Int32Ty, Devices.size());
- DescInit.add(llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
- DeviceImages,
- Index));
- DescInit.add(HostEntriesBegin);
- DescInit.add(HostEntriesEnd);
-
- auto *Desc = DescInit.finishAndCreateGlobal(".omp_offloading.descriptor",
- CGM.getPointerAlign(),
- /*isConstant=*/true);
+ llvm::Constant *Data[] = {
+ llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
+ llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
+ DeviceImages, Index),
+ HostEntriesBegin, HostEntriesEnd};
+ std::string Descriptor = getName({"omp_offloading", "descriptor"});
+ llvm::GlobalVariable *Desc = createConstantGlobalStruct(
+ CGM, getTgtBinaryDescriptorQTy(), Data, Descriptor);
// Emit code to register or unregister the descriptor at execution
// startup or closing, respectively.
- // Create a variable to drive the registration and unregistration of the
- // descriptor, so we can reuse the logic that emits Ctors and Dtors.
- auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
- ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
- IdentInfo, C.CharTy, ImplicitParamDecl::Other);
-
- auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
- CGM, ".omp_offloading.descriptor_unreg",
- [&](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
- Desc);
- });
- auto *RegFn = createOffloadingBinaryDescriptorFunction(
- CGM, ".omp_offloading.descriptor_reg",
- [&](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib),
- Desc);
- CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
- });
+ llvm::Function *UnRegFn;
+ {
+ FunctionArgList Args;
+ ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ Args.push_back(&DummyPtr);
+
+ CodeGenFunction CGF(CGM);
+ // Disable debug info for global (de-)initializer because they are not part
+ // of some particular construct.
+ CGF.disableDebugInfo();
+ const auto &FI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ std::string UnregName = getName({"omp_offloading", "descriptor_unreg"});
+ UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
+ Desc);
+ CGF.FinishFunction();
+ }
+ llvm::Function *RegFn;
+ {
+ CodeGenFunction CGF(CGM);
+ // Disable debug info for global (de-)initializer because they are not part
+ // of some particular construct.
+ CGF.disableDebugInfo();
+ const auto &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ std::string Descriptor = getName({"omp_offloading", "descriptor_reg"});
+ RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
+ // Create a variable to drive the registration and unregistration of the
+ // descriptor, so we can reuse the logic that emits Ctors and Dtors.
+ ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
+ SourceLocation(), nullptr, C.CharTy,
+ ImplicitParamDecl::Other);
+ CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
+ CGF.FinishFunction();
+ }
if (CGM.supportsCOMDAT()) {
// It is sufficient to call registration function only once, so create a
// COMDAT group for registration/unregistration functions and associated
// data. That would reduce startup time and code size. Registration
// function serves as a COMDAT group key.
- auto ComdatKey = M.getOrInsertComdat(RegFn->getName());
+ llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName());
RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
RegFn->setComdat(ComdatKey);
@@ -3529,48 +3827,35 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
return RegFn;
}
-void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
- llvm::Constant *Addr, uint64_t Size,
- int32_t Flags) {
+void CGOpenMPRuntime::createOffloadEntry(
+ llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
+ llvm::GlobalValue::LinkageTypes Linkage) {
StringRef Name = Addr->getName();
- auto *TgtOffloadEntryType = cast<llvm::StructType>(
- CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
- llvm::LLVMContext &C = CGM.getModule().getContext();
llvm::Module &M = CGM.getModule();
-
- // Make sure the address has the right type.
- llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
+ llvm::LLVMContext &C = M.getContext();
// Create constant string with the name.
llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
- llvm::GlobalVariable *Str =
- new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
- llvm::GlobalValue::InternalLinkage, StrPtrInit,
- ".omp_offloading.entry_name");
+ std::string StringName = getName({"omp_offloading", "entry_name"});
+ auto *Str = new llvm::GlobalVariable(
+ M, StrPtrInit->getType(), /*isConstant=*/true,
+ llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
-
- // We can't have any padding between symbols, so we need to have 1-byte
- // alignment.
- auto Align = CharUnits::fromQuantity(1);
-
- // Create the entry struct.
- ConstantInitBuilder EntryBuilder(CGM);
- auto EntryInit = EntryBuilder.beginStruct(TgtOffloadEntryType);
- EntryInit.add(AddrPtr);
- EntryInit.add(StrPtr);
- EntryInit.addInt(CGM.SizeTy, Size);
- EntryInit.addInt(CGM.Int32Ty, Flags);
- EntryInit.addInt(CGM.Int32Ty, 0);
- llvm::GlobalVariable *Entry =
- EntryInit.finishAndCreateGlobal(".omp_offloading.entry",
- Align,
- /*constant*/ true,
- llvm::GlobalValue::ExternalLinkage);
+
+ llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
+ llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
+ llvm::ConstantInt::get(CGM.SizeTy, Size),
+ llvm::ConstantInt::get(CGM.Int32Ty, Flags),
+ llvm::ConstantInt::get(CGM.Int32Ty, 0)};
+ std::string EntryName = getName({"omp_offloading", "entry", ""});
+ llvm::GlobalVariable *Entry = createConstantGlobalStruct(
+ CGM, getTgtOffloadEntryQTy(), Data, Twine(EntryName).concat(Name),
+ llvm::GlobalValue::WeakAnyLinkage);
// The entry has to be created in the section the linker expects it to be.
- Entry->setSection(".omp_offloading.entries");
+ std::string Section = getName({"omp_offloading", "entries"});
+ Entry->setSection(Section);
}
void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
@@ -3583,71 +3868,142 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
// Right now we only generate metadata for function that contain target
// regions.
- // If we do not have entries, we dont need to do anything.
+ // If we do not have entries, we don't need to do anything.
if (OffloadEntriesInfoManager.empty())
return;
llvm::Module &M = CGM.getModule();
llvm::LLVMContext &C = M.getContext();
- SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
+ SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
OrderedEntries(OffloadEntriesInfoManager.size());
- // Create the offloading info metadata node.
- llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
-
// Auxiliary methods to create metadata values and strings.
- auto getMDInt = [&](unsigned v) {
+ auto &&GetMDInt = [this](unsigned V) {
return llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
+ llvm::ConstantInt::get(CGM.Int32Ty, V));
};
- auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
+ auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
+
+ // Create the offloading info metadata node.
+ llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
// Create function that emits metadata for each target region entry;
- auto &&TargetRegionMetadataEmitter = [&](
- unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
- OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
- llvm::SmallVector<llvm::Metadata *, 32> Ops;
- // Generate metadata for target regions. Each entry of this metadata
- // contains:
- // - Entry 0 -> Kind of this type of metadata (0).
- // - Entry 1 -> Device ID of the file where the entry was identified.
- // - Entry 2 -> File ID of the file where the entry was identified.
- // - Entry 3 -> Mangled name of the function where the entry was identified.
- // - Entry 4 -> Line in the file where the entry was identified.
- // - Entry 5 -> Order the entry was created.
- // The first element of the metadata node is the kind.
- Ops.push_back(getMDInt(E.getKind()));
- Ops.push_back(getMDInt(DeviceID));
- Ops.push_back(getMDInt(FileID));
- Ops.push_back(getMDString(ParentName));
- Ops.push_back(getMDInt(Line));
- Ops.push_back(getMDInt(E.getOrder()));
-
- // Save this entry in the right position of the ordered entries array.
- OrderedEntries[E.getOrder()] = &E;
-
- // Add metadata to the named metadata node.
- MD->addOperand(llvm::MDNode::get(C, Ops));
- };
+ auto &&TargetRegionMetadataEmitter =
+ [&C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
+ unsigned DeviceID, unsigned FileID, StringRef ParentName,
+ unsigned Line,
+ const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
+ // Generate metadata for target regions. Each entry of this metadata
+ // contains:
+ // - Entry 0 -> Kind of this type of metadata (0).
+ // - Entry 1 -> Device ID of the file where the entry was identified.
+ // - Entry 2 -> File ID of the file where the entry was identified.
+ // - Entry 3 -> Mangled name of the function where the entry was
+ // identified.
+ // - Entry 4 -> Line in the file where the entry was identified.
+ // - Entry 5 -> Order the entry was created.
+ // The first element of the metadata node is the kind.
+ llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
+ GetMDInt(FileID), GetMDString(ParentName),
+ GetMDInt(Line), GetMDInt(E.getOrder())};
+
+ // Save this entry in the right position of the ordered entries array.
+ OrderedEntries[E.getOrder()] = &E;
+
+ // Add metadata to the named metadata node.
+ MD->addOperand(llvm::MDNode::get(C, Ops));
+ };
OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
TargetRegionMetadataEmitter);
- for (auto *E : OrderedEntries) {
+ // Create function that emits metadata for each device global variable entry;
+ auto &&DeviceGlobalVarMetadataEmitter =
+ [&C, &OrderedEntries, &GetMDInt, &GetMDString,
+ MD](StringRef MangledName,
+ const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
+ &E) {
+ // Generate metadata for global variables. Each entry of this metadata
+ // contains:
+ // - Entry 0 -> Kind of this type of metadata (1).
+ // - Entry 1 -> Mangled name of the variable.
+ // - Entry 2 -> Declare target kind.
+ // - Entry 3 -> Order the entry was created.
+ // The first element of the metadata node is the kind.
+ llvm::Metadata *Ops[] = {
+ GetMDInt(E.getKind()), GetMDString(MangledName),
+ GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
+
+ // Save this entry in the right position of the ordered entries array.
+ OrderedEntries[E.getOrder()] = &E;
+
+ // Add metadata to the named metadata node.
+ MD->addOperand(llvm::MDNode::get(C, Ops));
+ };
+
+ OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
+ DeviceGlobalVarMetadataEmitter);
+
+ for (const auto *E : OrderedEntries) {
assert(E && "All ordered entries must exist!");
- if (auto *CE =
+ if (const auto *CE =
dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
E)) {
- assert(CE->getID() && CE->getAddress() &&
- "Entry ID and Addr are invalid!");
- createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
- } else
+ if (!CE->getID() || !CE->getAddress()) {
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "Offloading entry for target region is incorrect: either the "
+ "address or the ID is invalid.");
+ CGM.getDiags().Report(DiagID);
+ continue;
+ }
+ createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
+ CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
+ } else if (const auto *CE =
+ dyn_cast<OffloadEntriesInfoManagerTy::
+ OffloadEntryInfoDeviceGlobalVar>(E)) {
+ OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
+ static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
+ CE->getFlags());
+ switch (Flags) {
+ case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
+ if (!CE->getAddress()) {
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "Offloading entry for declare target variable is incorrect: the "
+ "address is invalid.");
+ CGM.getDiags().Report(DiagID);
+ continue;
+ }
+ break;
+ }
+ case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
+ assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
+ (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
+ "Declaret target link address is set.");
+ if (CGM.getLangOpts().OpenMPIsDevice)
+ continue;
+ if (!CE->getAddress()) {
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "Offloading entry for declare target variable is incorrect: the "
+ "address is invalid.");
+ CGM.getDiags().Report(DiagID);
+ continue;
+ }
+ break;
+ }
+ createOffloadEntry(CE->getAddress(), CE->getAddress(),
+ CE->getVarSize().getQuantity(), Flags,
+ CE->getLinkage());
+ } else {
llvm_unreachable("Unsupported entry kind.");
+ }
}
}
-/// \brief Loads all the offload entries information from the host IR
+/// Loads all the offload entries information from the host IR
/// metadata.
void CGOpenMPRuntime::loadOffloadInfoMetadata() {
// If we are in target mode, load the metadata from the host IR. This code has
@@ -3660,44 +4016,57 @@ void CGOpenMPRuntime::loadOffloadInfoMetadata() {
return;
auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
- if (Buf.getError())
+ if (auto EC = Buf.getError()) {
+ CGM.getDiags().Report(diag::err_cannot_open_file)
+ << CGM.getLangOpts().OMPHostIRFile << EC.message();
return;
+ }
llvm::LLVMContext C;
auto ME = expectedToErrorOrAndEmitErrors(
C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
- if (ME.getError())
+ if (auto EC = ME.getError()) {
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
+ CGM.getDiags().Report(DiagID)
+ << CGM.getLangOpts().OMPHostIRFile << EC.message();
return;
+ }
llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
if (!MD)
return;
- for (auto I : MD->operands()) {
- llvm::MDNode *MN = cast<llvm::MDNode>(I);
-
- auto getMDInt = [&](unsigned Idx) {
- llvm::ConstantAsMetadata *V =
- cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
+ for (llvm::MDNode *MN : MD->operands()) {
+ auto &&GetMDInt = [MN](unsigned Idx) {
+ auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
};
- auto getMDString = [&](unsigned Idx) {
- llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
+ auto &&GetMDString = [MN](unsigned Idx) {
+ auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
return V->getString();
};
- switch (getMDInt(0)) {
+ switch (GetMDInt(0)) {
default:
llvm_unreachable("Unexpected metadata!");
break;
case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
- OFFLOAD_ENTRY_INFO_TARGET_REGION:
+ OffloadingEntryInfoTargetRegion:
OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
- /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
- /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
- /*Order=*/getMDInt(5));
+ /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
+ /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
+ /*Order=*/GetMDInt(5));
+ break;
+ case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
+ OffloadingEntryInfoDeviceGlobalVar:
+ OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
+ /*MangledName=*/GetMDString(1),
+ static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
+ /*Flags=*/GetMDInt(2)),
+ /*Order=*/GetMDInt(3));
break;
}
}
@@ -3706,7 +4075,7 @@ void CGOpenMPRuntime::loadOffloadInfoMetadata() {
void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
if (!KmpRoutineEntryPtrTy) {
// Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
FunctionProtoType::ExtProtoInfo EPI;
KmpRoutineEntryPtrQTy = C.getPointerType(
@@ -3715,19 +4084,7 @@ void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
}
}
-static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
- QualType FieldTy) {
- auto *Field = FieldDecl::Create(
- C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
- C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
- /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
- Field->setAccess(AS_public);
- DC->addDecl(Field);
- return Field;
-}
-
QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
-
// Make sure the type of the entry is already created. This is the type we
// have to create:
// struct __tgt_offload_entry{
@@ -3740,7 +4097,7 @@ QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
// };
if (TgtOffloadEntryQTy.isNull()) {
ASTContext &C = CGM.getContext();
- auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
+ RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
RD->startDefinition();
addFieldToRecordDecl(C, RD, C.VoidPtrTy);
addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
@@ -3750,6 +4107,7 @@ QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
addFieldToRecordDecl(
C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
RD->completeDefinition();
+ RD->addAttr(PackedAttr::CreateImplicit(C));
TgtOffloadEntryQTy = C.getRecordType(RD);
}
return TgtOffloadEntryQTy;
@@ -3769,7 +4127,7 @@ QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
// };
if (TgtDeviceImageQTy.isNull()) {
ASTContext &C = CGM.getContext();
- auto *RD = C.buildImplicitRecord("__tgt_device_image");
+ RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
RD->startDefinition();
addFieldToRecordDecl(C, RD, C.VoidPtrTy);
addFieldToRecordDecl(C, RD, C.VoidPtrTy);
@@ -3793,7 +4151,7 @@ QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
// };
if (TgtBinaryDescriptorQTy.isNull()) {
ASTContext &C = CGM.getContext();
- auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
+ RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
RD->startDefinition();
addFieldToRecordDecl(
C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
@@ -3822,17 +4180,16 @@ typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
static RecordDecl *
createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
if (!Privates.empty()) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
// Build struct .kmp_privates_t. {
// /* private vars */
// };
- auto *RD = C.buildImplicitRecord(".kmp_privates.t");
+ RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
RD->startDefinition();
- for (auto &&Pair : Privates) {
- auto *VD = Pair.second.Original;
- auto Type = VD->getType();
- Type = Type.getNonReferenceType();
- auto *FD = addFieldToRecordDecl(C, RD, Type);
+ for (const auto &Pair : Privates) {
+ const VarDecl *VD = Pair.second.Original;
+ QualType Type = VD->getType().getNonReferenceType();
+ FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
if (VD->hasAttrs()) {
for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
E(VD->getAttrs().end());
@@ -3850,7 +4207,7 @@ static RecordDecl *
createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
QualType KmpInt32Ty,
QualType KmpRoutineEntryPointerQTy) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
// Build struct kmp_task_t {
// void * shareds;
// kmp_routine_entry_t routine;
@@ -3864,13 +4221,13 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
// kmp_int32 liter;
// void * reductions;
// };
- auto *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
+ RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
UD->startDefinition();
addFieldToRecordDecl(C, UD, KmpInt32Ty);
addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
UD->completeDefinition();
QualType KmpCmplrdataTy = C.getRecordType(UD);
- auto *RD = C.buildImplicitRecord("kmp_task_t");
+ RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
RD->startDefinition();
addFieldToRecordDecl(C, RD, C.VoidPtrTy);
addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
@@ -3895,22 +4252,21 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
static RecordDecl *
createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
ArrayRef<PrivateDataTy> Privates) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
// Build struct kmp_task_t_with_privates {
// kmp_task_t task_data;
// .kmp_privates_t. privates;
// };
- auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
+ RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
RD->startDefinition();
addFieldToRecordDecl(C, RD, KmpTaskTQTy);
- if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
+ if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
- }
RD->completeDefinition();
return RD;
}
-/// \brief Emit a proxy function which accepts kmp_task_t as the second
+/// Emit a proxy function which accepts kmp_task_t as the second
/// argument.
/// \code
/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
@@ -3928,7 +4284,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
QualType SharedsPtrTy, llvm::Value *TaskFunction,
llvm::Value *TaskPrivatesMap) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
FunctionArgList Args;
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
ImplicitParamDecl::Other);
@@ -3937,49 +4293,53 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
ImplicitParamDecl::Other);
Args.push_back(&GtidArg);
Args.push_back(&TaskTypeArg);
- auto &TaskEntryFnInfo =
+ const auto &TaskEntryFnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
- auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
- auto *TaskEntry =
- llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
- ".omp_task_entry.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
+ llvm::FunctionType *TaskEntryTy =
+ CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
+ std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
+ auto *TaskEntry = llvm::Function::Create(
+ TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
+ TaskEntry->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
+ CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
+ Loc, Loc);
// TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
// tt,
// For taskloops:
// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
// tt->task_data.shareds);
- auto *GtidParam = CGF.EmitLoadOfScalar(
+ llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
LValue TDBase = CGF.EmitLoadOfPointerLValue(
CGF.GetAddrOfLocalVar(&TaskTypeArg),
KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
- auto *KmpTaskTWithPrivatesQTyRD =
+ const auto *KmpTaskTWithPrivatesQTyRD =
cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
LValue Base =
CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
- auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
+ const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
- auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
- auto *PartidParam = PartIdLVal.getPointer();
+ LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
+ llvm::Value *PartidParam = PartIdLVal.getPointer();
auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
- auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
- auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
+ LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
+ llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.EmitLoadOfScalar(SharedsLVal, Loc),
CGF.ConvertTypeForMem(SharedsPtrTy));
auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
llvm::Value *PrivatesParam;
if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
- auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
+ LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
PrivatesLVal.getPointer(), CGF.VoidPtrTy);
- } else
+ } else {
PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
+ }
llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
TaskPrivatesMap,
@@ -3991,20 +4351,20 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
std::end(CommonArgs));
if (isOpenMPTaskLoopDirective(Kind)) {
auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
- auto LBLVal = CGF.EmitLValueForField(Base, *LBFI);
- auto *LBParam = CGF.EmitLoadOfLValue(LBLVal, Loc).getScalarVal();
+ LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
+ llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
- auto UBLVal = CGF.EmitLValueForField(Base, *UBFI);
- auto *UBParam = CGF.EmitLoadOfLValue(UBLVal, Loc).getScalarVal();
+ LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
+ llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
- auto StLVal = CGF.EmitLValueForField(Base, *StFI);
- auto *StParam = CGF.EmitLoadOfLValue(StLVal, Loc).getScalarVal();
+ LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
+ llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
- auto LILVal = CGF.EmitLValueForField(Base, *LIFI);
- auto *LIParam = CGF.EmitLoadOfLValue(LILVal, Loc).getScalarVal();
+ LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
+ llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
- auto RLVal = CGF.EmitLValueForField(Base, *RFI);
- auto *RParam = CGF.EmitLoadOfLValue(RLVal, Loc).getScalarVal();
+ LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
+ llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
CallArgs.push_back(LBParam);
CallArgs.push_back(UBParam);
CallArgs.push_back(StParam);
@@ -4015,9 +4375,8 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
CallArgs);
- CGF.EmitStoreThroughLValue(
- RValue::get(CGF.Builder.getInt32(/*C=*/0)),
- CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
+ CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
+ CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
CGF.FinishFunction();
return TaskEntry;
}
@@ -4027,7 +4386,7 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
QualType KmpInt32Ty,
QualType KmpTaskTWithPrivatesPtrQTy,
QualType KmpTaskTWithPrivatesQTy) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
FunctionArgList Args;
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
ImplicitParamDecl::Other);
@@ -4036,30 +4395,34 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
ImplicitParamDecl::Other);
Args.push_back(&GtidArg);
Args.push_back(&TaskTypeArg);
- auto &DestructorFnInfo =
+ const auto &DestructorFnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
- auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
+ llvm::FunctionType *DestructorFnTy =
+ CGM.getTypes().GetFunctionType(DestructorFnInfo);
+ std::string Name =
+ CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
auto *DestructorFn =
llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
- ".omp_task_destructor.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
+ Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
DestructorFnInfo);
+ DestructorFn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
- Args);
+ Args, Loc, Loc);
LValue Base = CGF.EmitLoadOfPointerLValue(
CGF.GetAddrOfLocalVar(&TaskTypeArg),
KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
- auto *KmpTaskTWithPrivatesQTyRD =
+ const auto *KmpTaskTWithPrivatesQTyRD =
cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Base = CGF.EmitLValueForField(Base, *FI);
- for (auto *Field :
+ for (const auto *Field :
cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
- if (auto DtorKind = Field->getType().isDestructedType()) {
- auto FieldLValue = CGF.EmitLValueForField(Base, Field);
+ if (QualType::DestructionKind DtorKind =
+ Field->getType().isDestructedType()) {
+ LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
}
}
@@ -4067,7 +4430,7 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
return DestructorFn;
}
-/// \brief Emit a privates mapping function for correct handling of private and
+/// Emit a privates mapping function for correct handling of private and
/// firstprivate variables.
/// \code
/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
@@ -4084,7 +4447,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
ArrayRef<const Expr *> LastprivateVars,
QualType PrivatesQTy,
ArrayRef<PrivateDataTy> Privates) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
FunctionArgList Args;
ImplicitParamDecl TaskPrivatesArg(
C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
@@ -4093,67 +4456,69 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Args.push_back(&TaskPrivatesArg);
llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
unsigned Counter = 1;
- for (auto *E: PrivateVars) {
+ for (const Expr *E : PrivateVars) {
Args.push_back(ImplicitParamDecl::Create(
C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
C.getPointerType(C.getPointerType(E->getType()))
.withConst()
.withRestrict(),
ImplicitParamDecl::Other));
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
PrivateVarsPos[VD] = Counter;
++Counter;
}
- for (auto *E : FirstprivateVars) {
+ for (const Expr *E : FirstprivateVars) {
Args.push_back(ImplicitParamDecl::Create(
C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
C.getPointerType(C.getPointerType(E->getType()))
.withConst()
.withRestrict(),
ImplicitParamDecl::Other));
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
PrivateVarsPos[VD] = Counter;
++Counter;
}
- for (auto *E: LastprivateVars) {
+ for (const Expr *E : LastprivateVars) {
Args.push_back(ImplicitParamDecl::Create(
C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
C.getPointerType(C.getPointerType(E->getType()))
.withConst()
.withRestrict(),
ImplicitParamDecl::Other));
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
PrivateVarsPos[VD] = Counter;
++Counter;
}
- auto &TaskPrivatesMapFnInfo =
+ const auto &TaskPrivatesMapFnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *TaskPrivatesMapTy =
+ llvm::FunctionType *TaskPrivatesMapTy =
CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
+ std::string Name =
+ CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
auto *TaskPrivatesMap = llvm::Function::Create(
- TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
- ".omp_task_privates_map.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
+ TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
+ &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
TaskPrivatesMapFnInfo);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
- TaskPrivatesMapFnInfo, Args);
+ TaskPrivatesMapFnInfo, Args, Loc, Loc);
// *privi = &.privates.privi;
LValue Base = CGF.EmitLoadOfPointerLValue(
CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
TaskPrivatesArg.getType()->castAs<PointerType>());
- auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
+ const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Counter = 0;
- for (auto *Field : PrivatesQTyRD->fields()) {
- auto FieldLVal = CGF.EmitLValueForField(Base, Field);
- auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
- auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
- auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
+ for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
+ LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
+ const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
+ LValue RefLVal =
+ CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
+ LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
++Counter;
@@ -4175,9 +4540,14 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
QualType SharedsTy, QualType SharedsPtrTy,
const OMPTaskDataTy &Data,
ArrayRef<PrivateDataTy> Privates, bool ForDup) {
- auto &C = CGF.getContext();
+ ASTContext &C = CGF.getContext();
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
+ OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
+ ? OMPD_taskloop
+ : OMPD_task;
+ const CapturedStmt &CS = *D.getCapturedStmt(Kind);
+ CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
LValue SrcBase;
bool IsTargetTask =
isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
@@ -4186,40 +4556,38 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
// PointersArray and SizesArray. The original variables for these arrays are
// not captured and we get their addresses explicitly.
if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
- (IsTargetTask && Data.FirstprivateVars.size() > 3)) {
+ (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
SrcBase = CGF.MakeAddrLValue(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
SharedsTy);
}
- OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
- ? OMPD_taskloop
- : OMPD_task;
- CodeGenFunction::CGCapturedStmtInfo CapturesInfo(*D.getCapturedStmt(Kind));
FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
- for (auto &&Pair : Privates) {
- auto *VD = Pair.second.PrivateCopy;
- auto *Init = VD->getAnyInitializer();
+ for (const PrivateDataTy &Pair : Privates) {
+ const VarDecl *VD = Pair.second.PrivateCopy;
+ const Expr *Init = VD->getAnyInitializer();
if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
!CGF.isTrivialInitializer(Init)))) {
LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
- if (auto *Elem = Pair.second.PrivateElemInit) {
- auto *OriginalVD = Pair.second.Original;
+ if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
+ const VarDecl *OriginalVD = Pair.second.Original;
// Check if the variable is the target-based BasePointersArray,
// PointersArray or SizesArray.
LValue SharedRefLValue;
QualType Type = OriginalVD->getType();
- if (IsTargetTask && isa<ImplicitParamDecl>(OriginalVD) &&
- isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
- cast<CapturedDecl>(OriginalVD->getDeclContext())->getNumParams() ==
- 0 &&
- isa<TranslationUnitDecl>(
- cast<CapturedDecl>(OriginalVD->getDeclContext())
- ->getDeclContext())) {
+ const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
+ if (IsTargetTask && !SharedField) {
+ assert(isa<ImplicitParamDecl>(OriginalVD) &&
+ isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
+ cast<CapturedDecl>(OriginalVD->getDeclContext())
+ ->getNumParams() == 0 &&
+ isa<TranslationUnitDecl>(
+ cast<CapturedDecl>(OriginalVD->getDeclContext())
+ ->getDeclContext()) &&
+ "Expected artificial target data variable.");
SharedRefLValue =
CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
} else {
- auto *SharedField = CapturesInfo.lookup(OriginalVD);
SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
SharedRefLValue = CGF.MakeAddrLValue(
Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
@@ -4230,8 +4598,7 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
// Initialize firstprivate array.
if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
// Perform simple memcpy.
- CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
- SharedRefLValue.getAddress(), Type);
+ CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
} else {
// Initialize firstprivate array using element-by-element
// initialization.
@@ -4262,8 +4629,9 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
CGF.EmitExprAsInit(Init, VD, PrivateLValue,
/*capturedByInit=*/false);
}
- } else
+ } else {
CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
+ }
}
++FI;
}
@@ -4273,11 +4641,13 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
static bool checkInitIsRequired(CodeGenFunction &CGF,
ArrayRef<PrivateDataTy> Privates) {
bool InitRequired = false;
- for (auto &&Pair : Privates) {
- auto *VD = Pair.second.PrivateCopy;
- auto *Init = VD->getAnyInitializer();
+ for (const PrivateDataTy &Pair : Privates) {
+ const VarDecl *VD = Pair.second.PrivateCopy;
+ const Expr *Init = VD->getAnyInitializer();
InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
!CGF.isTrivialInitializer(Init));
+ if (InitRequired)
+ break;
}
return InitRequired;
}
@@ -4301,7 +4671,7 @@ emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
QualType SharedsPtrTy, const OMPTaskDataTy &Data,
ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
FunctionArgList Args;
ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
KmpTaskTWithPrivatesPtrQTy,
@@ -4314,16 +4684,17 @@ emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
Args.push_back(&DstArg);
Args.push_back(&SrcArg);
Args.push_back(&LastprivArg);
- auto &TaskDupFnInfo =
+ const auto &TaskDupFnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
- auto *TaskDup =
- llvm::Function::Create(TaskDupTy, llvm::GlobalValue::InternalLinkage,
- ".omp_task_dup.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskDup, TaskDupFnInfo);
+ llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
+ std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
+ auto *TaskDup = llvm::Function::Create(
+ TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
+ TaskDup->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
+ Loc);
LValue TDBase = CGF.EmitLoadOfPointerLValue(
CGF.GetAddrOfLocalVar(&DstArg),
@@ -4366,9 +4737,9 @@ emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
static bool
checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
bool NeedsCleanup = false;
- auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
- auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
- for (auto *FD : PrivateRD->fields()) {
+ auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
+ const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
+ for (const FieldDecl *FD : PrivateRD->fields()) {
NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
if (NeedsCleanup)
break;
@@ -4381,41 +4752,41 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
const OMPExecutableDirective &D,
llvm::Value *TaskFunction, QualType SharedsTy,
Address Shareds, const OMPTaskDataTy &Data) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
llvm::SmallVector<PrivateDataTy, 4> Privates;
// Aggregate privates and sort them by the alignment.
auto I = Data.PrivateCopies.begin();
- for (auto *E : Data.PrivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- Privates.push_back(std::make_pair(
+ for (const Expr *E : Data.PrivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.emplace_back(
C.getDeclAlign(VD),
PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
- /*PrivateElemInit=*/nullptr)));
+ /*PrivateElemInit=*/nullptr));
++I;
}
I = Data.FirstprivateCopies.begin();
auto IElemInitRef = Data.FirstprivateInits.begin();
- for (auto *E : Data.FirstprivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- Privates.push_back(std::make_pair(
+ for (const Expr *E : Data.FirstprivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.emplace_back(
C.getDeclAlign(VD),
PrivateHelpersTy(
VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
- cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
+ cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
++I;
++IElemInitRef;
}
I = Data.LastprivateCopies.begin();
- for (auto *E : Data.LastprivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- Privates.push_back(std::make_pair(
+ for (const Expr *E : Data.LastprivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.emplace_back(
C.getDeclAlign(VD),
PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
- /*PrivateElemInit=*/nullptr)));
+ /*PrivateElemInit=*/nullptr));
++I;
}
std::stable_sort(Privates.begin(), Privates.end(), stable_sort_comparator);
- auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
// Build type kmp_routine_entry_t (if not built yet).
emitKmpRoutineEntryT(KmpInt32Ty);
// Build type kmp_task_t (if not built yet).
@@ -4436,21 +4807,23 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
}
KmpTaskTQTy = SavedKmpTaskTQTy;
}
- auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
+ const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
// Build particular struct kmp_task_t for the given task.
- auto *KmpTaskTWithPrivatesQTyRD =
+ const RecordDecl *KmpTaskTWithPrivatesQTyRD =
createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
- auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
+ QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
QualType KmpTaskTWithPrivatesPtrQTy =
C.getPointerType(KmpTaskTWithPrivatesQTy);
- auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
- auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
- auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
+ llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
+ llvm::Type *KmpTaskTWithPrivatesPtrTy =
+ KmpTaskTWithPrivatesTy->getPointerTo();
+ llvm::Value *KmpTaskTWithPrivatesTySize =
+ CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
QualType SharedsPtrTy = C.getPointerType(SharedsTy);
// Emit initial values for private copies (if any).
llvm::Value *TaskPrivatesMap = nullptr;
- auto *TaskPrivatesMapTy =
+ llvm::Type *TaskPrivatesMapTy =
std::next(cast<llvm::Function>(TaskFunction)->arg_begin(), 3)->getType();
if (!Privates.empty()) {
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
@@ -4465,7 +4838,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
}
// Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
// kmp_task_t *tt);
- auto *TaskEntry = emitProxyTaskFunction(
+ llvm::Value *TaskEntry = emitProxyTaskFunction(
CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
TaskPrivatesMap);
@@ -4491,23 +4864,24 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
}
if (Data.Priority.getInt())
Flags = Flags | PriorityFlag;
- auto *TaskFlags =
+ llvm::Value *TaskFlags =
Data.Final.getPointer()
? CGF.Builder.CreateSelect(Data.Final.getPointer(),
CGF.Builder.getInt32(FinalFlag),
CGF.Builder.getInt32(/*C=*/0))
: CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
- auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
+ llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
getThreadID(CGF, Loc), TaskFlags,
KmpTaskTWithPrivatesTySize, SharedsSize,
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
TaskEntry, KmpRoutineEntryPtrTy)};
- auto *NewTask = CGF.EmitRuntimeCall(
+ llvm::Value *NewTask = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
- auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- NewTask, KmpTaskTWithPrivatesPtrTy);
+ llvm::Value *NewTaskNewTaskTTy =
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ NewTask, KmpTaskTWithPrivatesPtrTy);
LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
KmpTaskTWithPrivatesQTy);
LValue TDBase =
@@ -4523,7 +4897,9 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
KmpTaskTShareds)),
Loc),
CGF.getNaturalTypeAlignment(SharedsTy));
- CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
+ LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
+ LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
+ CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
}
// Emit initial values for private copies (if any).
TaskResultTy Result;
@@ -4543,7 +4919,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
enum { Priority = 0, Destructors = 1 };
// Provide pointer to function with destructors for privates.
auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
- auto *KmpCmplrdataUD = (*FI)->getType()->getAsUnionType()->getDecl();
+ const RecordDecl *KmpCmplrdataUD =
+ (*FI)->getType()->getAsUnionType()->getDecl();
if (NeedsCleanup) {
llvm::Value *DestructorFn = emitDestructorsFunction(
CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
@@ -4586,8 +4963,8 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *TaskEntry = Result.TaskEntry;
llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
LValue TDBase = Result.TDBase;
- RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
- auto &C = CGM.getContext();
+ const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
+ ASTContext &C = CGM.getContext();
// Process list of dependences.
Address DependenciesArray = Address::invalid();
unsigned NumDependencies = Data.Dependences.size();
@@ -4607,8 +4984,9 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
KmpDependInfoRD->completeDefinition();
KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
- } else
+ } else {
KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
+ }
CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
// Define type kmp_depend_info[<Dependences.size()>];
QualType KmpDependInfoArrayTy = C.getConstantArrayType(
@@ -4617,12 +4995,13 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
// kmp_depend_info[<Dependences.size()>] deps;
DependenciesArray =
CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
- for (unsigned i = 0; i < NumDependencies; ++i) {
- const Expr *E = Data.Dependences[i].second;
- auto Addr = CGF.EmitLValue(E);
+ for (unsigned I = 0; I < NumDependencies; ++I) {
+ const Expr *E = Data.Dependences[I].second;
+ LValue Addr = CGF.EmitLValue(E);
llvm::Value *Size;
QualType Ty = E->getType();
- if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
+ if (const auto *ASE =
+ dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
LValue UpAddrLVal =
CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
llvm::Value *UpAddr =
@@ -4631,24 +5010,25 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
- } else
+ } else {
Size = CGF.getTypeSize(Ty);
- auto Base = CGF.MakeAddrLValue(
- CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
+ }
+ LValue Base = CGF.MakeAddrLValue(
+ CGF.Builder.CreateConstArrayGEP(DependenciesArray, I, DependencySize),
KmpDependInfoTy);
// deps[i].base_addr = &<Dependences[i].second>;
- auto BaseAddrLVal = CGF.EmitLValueForField(
+ LValue BaseAddrLVal = CGF.EmitLValueForField(
Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
CGF.EmitStoreOfScalar(
CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
BaseAddrLVal);
// deps[i].len = sizeof(<Dependences[i].second>);
- auto LenLVal = CGF.EmitLValueForField(
+ LValue LenLVal = CGF.EmitLValueForField(
Base, *std::next(KmpDependInfoRD->field_begin(), Len));
CGF.EmitStoreOfScalar(Size, LenLVal);
// deps[i].flags = <Dependences[i].first>;
RTLDependenceKindTy DepKind;
- switch (Data.Dependences[i].first) {
+ switch (Data.Dependences[I].first) {
case OMPC_DEPEND_in:
DepKind = DepIn;
break;
@@ -4662,7 +5042,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
case OMPC_DEPEND_unknown:
llvm_unreachable("Unknown task dependence type");
}
- auto FlagsLVal = CGF.EmitLValueForField(
+ LValue FlagsLVal = CGF.EmitLValueForField(
Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
FlagsLVal);
@@ -4672,14 +5052,14 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.VoidPtrTy);
}
- // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
+ // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
// libcall.
// Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
// kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
// kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
// list is not empty
- auto *ThreadID = getThreadID(CGF, Loc);
- auto *UpLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
llvm::Value *DepTaskArgs[7];
if (NumDependencies) {
@@ -4696,7 +5076,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
&DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
if (!Data.Tied) {
auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
- auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
+ LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
}
if (NumDependencies) {
@@ -4724,7 +5104,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
NumDependencies, &DepWaitTaskArgs,
Loc](CodeGenFunction &CGF, PrePostActionTy &) {
- auto &RT = CGF.CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
CodeGenFunction::RunCleanupsScope LocalScope(CGF);
// Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
// kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
@@ -4754,9 +5134,9 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
RCG(CGF);
};
- if (IfCond)
+ if (IfCond) {
emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
- else {
+ } else {
RegionCodeGenTy ThenRCG(ThenCodeGen);
ThenRCG(CGF);
}
@@ -4772,7 +5152,7 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
return;
TaskResultTy Result =
emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
- // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
+ // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
// libcall.
// Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
// if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
@@ -4783,27 +5163,28 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
if (IfCond) {
IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
/*isSigned=*/true);
- } else
+ } else {
IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
+ }
LValue LBLVal = CGF.EmitLValueForField(
Result.TDBase,
*std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
- auto *LBVar =
+ const auto *LBVar =
cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
/*IsInitializer=*/true);
LValue UBLVal = CGF.EmitLValueForField(
Result.TDBase,
*std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
- auto *UBVar =
+ const auto *UBVar =
cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
/*IsInitializer=*/true);
LValue StLVal = CGF.EmitLValueForField(
Result.TDBase,
*std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
- auto *StVar =
+ const auto *StVar =
cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
/*IsInitializer=*/true);
@@ -4811,9 +5192,9 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
LValue RedLVal = CGF.EmitLValueForField(
Result.TDBase,
*std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
- if (Data.Reductions)
+ if (Data.Reductions) {
CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
- else {
+ } else {
CGF.EmitNullInitialization(RedLVal.getAddress(),
CGF.getContext().VoidPtrTy);
}
@@ -4825,7 +5206,7 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
IfVal,
LBLVal.getPointer(),
UBLVal.getPointer(),
- CGF.EmitLoadOfScalar(StLVal, SourceLocation()),
+ CGF.EmitLoadOfScalar(StLVal, Loc),
llvm::ConstantInt::getNullValue(
CGF.IntTy), // Always 0 because taskgroup emitted by the compiler
llvm::ConstantInt::getSigned(
@@ -4842,7 +5223,7 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
}
-/// \brief Emit reduction operation for each element of array (required for
+/// Emit reduction operation for each element of array (required for
/// array sections) LHS op = RHS.
/// \param Type Type of array.
/// \param LHSVar Variable on the left side of the reduction operation
@@ -4864,22 +5245,22 @@ static void EmitOMPAggregateReduction(
Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
// Drill down to the base element type on both arrays.
- auto ArrayTy = Type->getAsArrayTypeUnsafe();
- auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
+ const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
+ llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
- auto RHSBegin = RHSAddr.getPointer();
- auto LHSBegin = LHSAddr.getPointer();
+ llvm::Value *RHSBegin = RHSAddr.getPointer();
+ llvm::Value *LHSBegin = LHSAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
+ llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
// The basic structure here is a while-do loop.
- auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
- auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
- auto IsEmpty =
+ llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
+ llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
+ llvm::Value *IsEmpty =
CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
// Enter the loop body, making that address the current address.
- auto EntryBB = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
CGF.EmitBlock(BodyBB);
CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
@@ -4900,19 +5281,19 @@ static void EmitOMPAggregateReduction(
// Emit copy.
CodeGenFunction::OMPPrivateScope Scope(CGF);
- Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
- Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
+ Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
+ Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Scope.Privatize();
RedOpGen(CGF, XExpr, EExpr, UpExpr);
Scope.ForceCleanup();
// Shift the address forward by one element.
- auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
+ llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
- auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
+ llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
// Check whether we've reached the end.
- auto Done =
+ llvm::Value *Done =
CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
@@ -4927,11 +5308,12 @@ static void EmitOMPAggregateReduction(
/// UDR combiner function.
static void emitReductionCombiner(CodeGenFunction &CGF,
const Expr *ReductionOp) {
- if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
- if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
- if (auto *DRE =
+ if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
+ if (const auto *DRE =
dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
- if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
+ if (const auto *DRD =
+ dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
std::pair<llvm::Function *, llvm::Function *> Reduction =
CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
RValue Func = RValue::get(Reduction.first);
@@ -4943,24 +5325,29 @@ static void emitReductionCombiner(CodeGenFunction &CGF,
}
llvm::Value *CGOpenMPRuntime::emitReductionFunction(
- CodeGenModule &CGM, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
- ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
- ArrayRef<const Expr *> ReductionOps) {
- auto &C = CGM.getContext();
+ CodeGenModule &CGM, SourceLocation Loc, llvm::Type *ArgsType,
+ ArrayRef<const Expr *> Privates, ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs, ArrayRef<const Expr *> ReductionOps) {
+ ASTContext &C = CGM.getContext();
// void reduction_func(void *LHSArg, void *RHSArg);
FunctionArgList Args;
- ImplicitParamDecl LHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
- ImplicitParamDecl RHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
+ ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
Args.push_back(&LHSArg);
Args.push_back(&RHSArg);
- auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *Fn = llvm::Function::Create(
- CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
- ".omp.reduction.reduction_func", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
+ const auto &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ std::string Name = getName({"omp", "reduction", "reduction_func"});
+ auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
+ llvm::GlobalValue::InternalLinkage, Name,
+ &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
// Dst = (void*[n])(LHSArg);
// Src = (void*[n])(RHSArg);
@@ -4978,12 +5365,14 @@ llvm::Value *CGOpenMPRuntime::emitReductionFunction(
auto IPriv = Privates.begin();
unsigned Idx = 0;
for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
- auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
- Scope.addPrivate(RHSVar, [&]() -> Address {
+ const auto *RHSVar =
+ cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
+ Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
});
- auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
- Scope.addPrivate(LHSVar, [&]() -> Address {
+ const auto *LHSVar =
+ cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
+ Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
});
QualType PrivTy = (*IPriv)->getType();
@@ -4993,8 +5382,9 @@ llvm::Value *CGOpenMPRuntime::emitReductionFunction(
Address Elem =
CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
- auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
- auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
+ const VariableArrayType *VLA =
+ CGF.getContext().getAsVariableArrayType(PrivTy);
+ const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
CodeGenFunction::OpaqueValueMapping OpaqueMap(
CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
CGF.EmitVariablyModifiedType(PrivTy);
@@ -5004,19 +5394,20 @@ llvm::Value *CGOpenMPRuntime::emitReductionFunction(
IPriv = Privates.begin();
auto ILHS = LHSExprs.begin();
auto IRHS = RHSExprs.begin();
- for (auto *E : ReductionOps) {
+ for (const Expr *E : ReductionOps) {
if ((*IPriv)->getType()->isArrayType()) {
// Emit reduction for array section.
- auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
- auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
EmitOMPAggregateReduction(
CGF, (*IPriv)->getType(), LHSVar, RHSVar,
[=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
emitReductionCombiner(CGF, E);
});
- } else
+ } else {
// Emit reduction for array subscript or single variable.
emitReductionCombiner(CGF, E);
+ }
++IPriv;
++ILHS;
++IRHS;
@@ -5033,16 +5424,17 @@ void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
const DeclRefExpr *RHS) {
if (PrivateRef->getType()->isArrayType()) {
// Emit reduction for array section.
- auto *LHSVar = cast<VarDecl>(LHS->getDecl());
- auto *RHSVar = cast<VarDecl>(RHS->getDecl());
+ const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
+ const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
EmitOMPAggregateReduction(
CGF, PrivateRef->getType(), LHSVar, RHSVar,
[=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
emitReductionCombiner(CGF, ReductionOp);
});
- } else
+ } else {
// Emit reduction for array subscript or single variable.
emitReductionCombiner(CGF, ReductionOp);
+ }
}
void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
@@ -5092,14 +5484,14 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
// ...
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
if (SimpleReduction) {
CodeGenFunction::RunCleanupsScope Scope(CGF);
auto IPriv = Privates.begin();
auto ILHS = LHSExprs.begin();
auto IRHS = RHSExprs.begin();
- for (auto *E : ReductionOps) {
+ for (const Expr *E : ReductionOps) {
emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
cast<DeclRefExpr>(*IRHS));
++IPriv;
@@ -5112,7 +5504,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
// 1. Build a list of reduction variables.
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
auto Size = RHSExprs.size();
- for (auto *E : Privates) {
+ for (const Expr *E : Privates) {
if (E->getType()->isVariablyModifiedType())
// Reserve place for array size.
++Size;
@@ -5140,7 +5532,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *Size = CGF.Builder.CreateIntCast(
CGF.getVLASize(
CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
- .first,
+ .NumElts,
CGF.SizeTy, /*isSigned=*/false);
CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
Elem);
@@ -5148,19 +5540,20 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
}
// 2. Emit reduce_func().
- auto *ReductionFn = emitReductionFunction(
- CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
- LHSExprs, RHSExprs, ReductionOps);
+ llvm::Value *ReductionFn = emitReductionFunction(
+ CGM, Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(),
+ Privates, LHSExprs, RHSExprs, ReductionOps);
// 3. Create static kmp_critical_name lock = { 0 };
- auto *Lock = getCriticalRegionLock(".reduction");
+ std::string Name = getName({"reduction"});
+ llvm::Value *Lock = getCriticalRegionLock(Name);
// 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
// RedList, reduce_func, &<lock>);
- auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
- auto *ThreadId = getThreadID(CGF, Loc);
- auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
- auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
+ llvm::Value *ThreadId = getThreadID(CGF, Loc);
+ llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
+ llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
ReductionList.getPointer(), CGF.VoidPtrTy);
llvm::Value *Args[] = {
IdentTLoc, // ident_t *<loc>
@@ -5171,14 +5564,15 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
ReductionFn, // void (*) (void *, void *) <reduce_func>
Lock // kmp_critical_name *&<lock>
};
- auto Res = CGF.EmitRuntimeCall(
+ llvm::Value *Res = CGF.EmitRuntimeCall(
createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
: OMPRTL__kmpc_reduce),
Args);
// 5. Build switch(res)
- auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
- auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
+ llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
+ llvm::SwitchInst *SwInst =
+ CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
// 6. Build case 1:
// ...
@@ -5186,7 +5580,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
// ...
// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
// break;
- auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
+ llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
CGF.EmitBlock(Case1BB);
@@ -5196,13 +5590,13 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
ThreadId, // i32 <gtid>
Lock // kmp_critical_name *&<lock>
};
- auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
- auto &RT = CGF.CGM.getOpenMPRuntime();
+ auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
+ CodeGenFunction &CGF, PrePostActionTy &Action) {
+ CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
auto IPriv = Privates.begin();
auto ILHS = LHSExprs.begin();
auto IRHS = RHSExprs.begin();
- for (auto *E : ReductionOps) {
+ for (const Expr *E : ReductionOps) {
RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
cast<DeclRefExpr>(*IRHS));
++IPriv;
@@ -5226,44 +5620,44 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
// ...
// break;
- auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
+ llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
CGF.EmitBlock(Case2BB);
- auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
+ auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
+ CodeGenFunction &CGF, PrePostActionTy &Action) {
auto ILHS = LHSExprs.begin();
auto IRHS = RHSExprs.begin();
auto IPriv = Privates.begin();
- for (auto *E : ReductionOps) {
+ for (const Expr *E : ReductionOps) {
const Expr *XExpr = nullptr;
const Expr *EExpr = nullptr;
const Expr *UpExpr = nullptr;
BinaryOperatorKind BO = BO_Comma;
- if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->getOpcode() == BO_Assign) {
XExpr = BO->getLHS();
UpExpr = BO->getRHS();
}
}
// Try to emit update expression as a simple atomic.
- auto *RHSExpr = UpExpr;
+ const Expr *RHSExpr = UpExpr;
if (RHSExpr) {
// Analyze RHS part of the whole expression.
- if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
+ if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
RHSExpr->IgnoreParenImpCasts())) {
// If this is a conditional operator, analyze its condition for
// min/max reduction operator.
RHSExpr = ACO->getCond();
}
- if (auto *BORHS =
+ if (const auto *BORHS =
dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
EExpr = BORHS->getRHS();
BO = BORHS->getOpcode();
}
}
if (XExpr) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
auto &&AtomicRedGen = [BO, VD,
Loc](CodeGenFunction &CGF, const Expr *XExpr,
const Expr *EExpr, const Expr *UpExpr) {
@@ -5277,7 +5671,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
[&CGF, UpExpr, VD, Loc](RValue XRValue) {
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
PrivateScope.addPrivate(
- VD, [&CGF, VD, XRValue, Loc]() -> Address {
+ VD, [&CGF, VD, XRValue, Loc]() {
Address LHSTemp = CGF.CreateMemTemp(VD->getType());
CGF.emitOMPSimpleStore(
CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
@@ -5290,19 +5684,22 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
};
if ((*IPriv)->getType()->isArrayType()) {
// Emit atomic reduction for array section.
- auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ const auto *RHSVar =
+ cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
AtomicRedGen, XExpr, EExpr, UpExpr);
- } else
+ } else {
// Emit atomic reduction for array subscript or single variable.
AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
+ }
} else {
// Emit as a critical region.
auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
- const Expr *, const Expr *) {
- auto &RT = CGF.CGM.getOpenMPRuntime();
+ const Expr *, const Expr *) {
+ CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
+ std::string Name = RT.getName({"atomic_reduction"});
RT.emitCriticalRegion(
- CGF, ".atomic_reduction",
+ CGF, Name,
[=](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
emitReductionCombiner(CGF, E);
@@ -5310,12 +5707,15 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Loc);
};
if ((*IPriv)->getType()->isArrayType()) {
- auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
- auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ const auto *LHSVar =
+ cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ const auto *RHSVar =
+ cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
CritRedGen);
- } else
+ } else {
CritRedGen(CGF, nullptr, nullptr, nullptr);
+ }
}
++ILHS;
++IRHS;
@@ -5335,20 +5735,29 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
EndArgs);
AtomicRCG.setAction(Action);
AtomicRCG(CGF);
- } else
+ } else {
AtomicRCG(CGF);
+ }
CGF.EmitBranch(DefaultBB);
CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
}
/// Generates unique name for artificial threadprivate variables.
-/// Format is: <Prefix> "." <Loc_raw_encoding> "_" <N>
-static std::string generateUniqueName(StringRef Prefix, SourceLocation Loc,
- unsigned N) {
+/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
+static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
+ const Expr *Ref) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
- Out << Prefix << "." << Loc.getRawEncoding() << "_" << N;
+ const clang::DeclRefExpr *DE;
+ const VarDecl *D = ::getBaseDecl(Ref, DE);
+ if (!D)
+ D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
+ D = D->getCanonicalDecl();
+ std::string Name = CGM.getOpenMPRuntime().getName(
+ {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
+ Out << Prefix << Name << "_"
+ << D->getCanonicalDecl()->getLocStart().getRawEncoding();
return Out.str();
}
@@ -5363,19 +5772,21 @@ static std::string generateUniqueName(StringRef Prefix, SourceLocation Loc,
static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
SourceLocation Loc,
ReductionCodeGen &RCG, unsigned N) {
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
FunctionArgList Args;
- ImplicitParamDecl Param(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
Args.emplace_back(&Param);
- auto &FnInfo =
+ const auto &FnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
- ".red_init.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+ Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Address PrivateAddr = CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&Param),
C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
@@ -5385,10 +5796,9 @@ static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
if (RCG.getSizes(N).second) {
Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().getSizeType(),
- generateUniqueName("reduction_size", Loc, N));
- Size =
- CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
- CGM.getContext().getSizeType(), SourceLocation());
+ generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
+ Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
+ CGM.getContext().getSizeType(), Loc);
}
RCG.emitAggregateType(CGF, N, Size);
LValue SharedLVal;
@@ -5399,7 +5809,10 @@ static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
Address SharedAddr =
CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().VoidPtrTy,
- generateUniqueName("reduction", Loc, N));
+ generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
+ SharedAddr = CGF.EmitLoadOfPointer(
+ SharedAddr,
+ CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
} else {
SharedLVal = CGF.MakeNaturalAlignAddrLValue(
@@ -5431,40 +5844,42 @@ static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
const Expr *ReductionOp,
const Expr *LHS, const Expr *RHS,
const Expr *PrivateRef) {
- auto &C = CGM.getContext();
- auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
- auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
+ ASTContext &C = CGM.getContext();
+ const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
+ const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
FunctionArgList Args;
- ImplicitParamDecl ParamInOut(C, C.VoidPtrTy, ImplicitParamDecl::Other);
- ImplicitParamDecl ParamIn(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
Args.emplace_back(&ParamInOut);
Args.emplace_back(&ParamIn);
- auto &FnInfo =
+ const auto &FnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
- ".red_comb.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+ Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
llvm::Value *Size = nullptr;
// If the size of the reduction item is non-constant, load it from global
// threadprivate variable.
if (RCG.getSizes(N).second) {
Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().getSizeType(),
- generateUniqueName("reduction_size", Loc, N));
- Size =
- CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
- CGM.getContext().getSizeType(), SourceLocation());
+ generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
+ Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
+ CGM.getContext().getSizeType(), Loc);
}
RCG.emitAggregateType(CGF, N, Size);
// Remap lhs and rhs variables to the addresses of the function arguments.
// %lhs = bitcast void* %arg0 to <type>*
// %rhs = bitcast void* %arg1 to <type>*
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
- PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() -> Address {
+ PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
// Pull out the pointer to the variable.
Address PtrAddr = CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&ParamInOut),
@@ -5472,7 +5887,7 @@ static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
return CGF.Builder.CreateElementBitCast(
PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
});
- PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() -> Address {
+ PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
// Pull out the pointer to the variable.
Address PtrAddr = CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&ParamIn),
@@ -5504,19 +5919,21 @@ static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
ReductionCodeGen &RCG, unsigned N) {
if (!RCG.needCleanups(N))
return nullptr;
- auto &C = CGM.getContext();
+ ASTContext &C = CGM.getContext();
FunctionArgList Args;
- ImplicitParamDecl Param(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
+ ImplicitParamDecl::Other);
Args.emplace_back(&Param);
- auto &FnInfo =
+ const auto &FnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
- ".red_fini.", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+ Name, &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Address PrivateAddr = CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&Param),
C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
@@ -5526,10 +5943,9 @@ static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
if (RCG.getSizes(N).second) {
Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().getSizeType(),
- generateUniqueName("reduction_size", Loc, N));
- Size =
- CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
- CGM.getContext().getSizeType(), SourceLocation());
+ generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
+ Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
+ CGM.getContext().getSizeType(), Loc);
}
RCG.emitAggregateType(CGF, N, Size);
// Emit the finalizer body:
@@ -5555,7 +5971,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
// kmp_task_red_flags_t flags; // flags for additional info from compiler
// } kmp_task_red_input_t;
ASTContext &C = CGM.getContext();
- auto *RD = C.buildImplicitRecord("kmp_task_red_input_t");
+ RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
RD->startDefinition();
const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
@@ -5656,14 +6072,14 @@ void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
/*isSigned=*/false);
Address SizeAddr = getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().getSizeType(),
- generateUniqueName("reduction_size", Loc, N));
+ generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
}
// Store address of the original reduction item if custom initializer is used.
if (RCG.usesReductionInitializer(N)) {
Address SharedAddr = getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().VoidPtrTy,
- generateUniqueName("reduction", Loc, N));
+ generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
CGF.Builder.CreateStore(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
@@ -5753,18 +6169,18 @@ void CGOpenMPRuntime::emitCancellationPointCall(
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
// Ignore return result until untied tasks are supported.
- auto *Result = CGF.EmitRuntimeCall(
+ llvm::Value *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
// if (__kmpc_cancellationpoint()) {
// exit from construct;
// }
- auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
- auto *ContBB = CGF.createBasicBlock(".cancel.continue");
- auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
+ llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
+ llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// exit from construct;
- auto CancelDest =
+ CodeGenFunction::JumpDest CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
CGF.EmitBranchThroughCleanup(CancelDest);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
@@ -5783,70 +6199,42 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
PrePostActionTy &) {
- auto &RT = CGF.CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
llvm::Value *Args[] = {
RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
// Ignore return result until untied tasks are supported.
- auto *Result = CGF.EmitRuntimeCall(
+ llvm::Value *Result = CGF.EmitRuntimeCall(
RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
// if (__kmpc_cancel()) {
// exit from construct;
// }
- auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
- auto *ContBB = CGF.createBasicBlock(".cancel.continue");
- auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
+ llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
+ llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// exit from construct;
- auto CancelDest =
+ CodeGenFunction::JumpDest CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
CGF.EmitBranchThroughCleanup(CancelDest);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
};
- if (IfCond)
+ if (IfCond) {
emitOMPIfClause(CGF, IfCond, ThenGen,
[](CodeGenFunction &, PrePostActionTy &) {});
- else {
+ } else {
RegionCodeGenTy ThenRCG(ThenGen);
ThenRCG(CGF);
}
}
}
-/// \brief Obtain information that uniquely identifies a target entry. This
-/// consists of the file and device IDs as well as line number associated with
-/// the relevant entry source location.
-static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
- unsigned &DeviceID, unsigned &FileID,
- unsigned &LineNum) {
-
- auto &SM = C.getSourceManager();
-
- // The loc should be always valid and have a file ID (the user cannot use
- // #pragma directives in macros)
-
- assert(Loc.isValid() && "Source location is expected to be always valid.");
- assert(Loc.isFileID() && "Source location is expected to refer to a file.");
-
- PresumedLoc PLoc = SM.getPresumedLoc(Loc);
- assert(PLoc.isValid() && "Source location is expected to be always valid.");
-
- llvm::sys::fs::UniqueID ID;
- if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
- llvm_unreachable("Source file with target region no longer exists!");
-
- DeviceID = ID.getDevice();
- FileID = ID.getFile();
- LineNum = PLoc.getLine();
-}
-
void CGOpenMPRuntime::emitTargetOutlinedFunction(
const OMPExecutableDirective &D, StringRef ParentName,
llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
assert(!ParentName.empty() && "Invalid target region parent name!");
-
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
}
@@ -5876,7 +6264,7 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
<< llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
}
- const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+ const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
CodeGenFunction CGF(CGM, true);
CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
@@ -5902,22 +6290,25 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
if (CGM.getLangOpts().OpenMPIsDevice) {
OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
- OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else
+ OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+ OutlinedFn->setDSOLocal(false);
+ } else {
+ std::string Name = getName({EntryFnName, "region_id"});
OutlinedFnID = new llvm::GlobalVariable(
CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
- llvm::GlobalValue::PrivateLinkage,
- llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
+ llvm::GlobalValue::WeakAnyLinkage,
+ llvm::Constant::getNullValue(CGM.Int8Ty), Name);
+ }
// Register the information for the entry associated with this target region.
OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
- /*Flags=*/0);
+ OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
}
/// discard all CompoundStmts intervening between two constructs
static const Stmt *ignoreCompoundStmts(const Stmt *Body) {
- while (auto *CS = dyn_cast_or_null<CompoundStmt>(Body))
+ while (const auto *CS = dyn_cast_or_null<CompoundStmt>(Body))
Body = CS->body_front();
return Body;
@@ -5935,12 +6326,11 @@ static llvm::Value *
emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
CodeGenFunction &CGF,
const OMPExecutableDirective &D) {
-
assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
"teams directive expected to be "
"emitted only for the host!");
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
// If the target directive is combined with a teams directive:
// Return the value in the num_teams clause, if any.
@@ -5948,8 +6338,8 @@ emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
if (isOpenMPTeamsDirective(D.getDirectiveKind())) {
if (const auto *NumTeamsClause = D.getSingleClause<OMPNumTeamsClause>()) {
CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
- auto NumTeams = CGF.EmitScalarExpr(NumTeamsClause->getNumTeams(),
- /*IgnoreResultAssign*/ true);
+ llvm::Value *NumTeams = CGF.EmitScalarExpr(NumTeamsClause->getNumTeams(),
+ /*IgnoreResultAssign*/ true);
return Bld.CreateIntCast(NumTeams, CGF.Int32Ty,
/*IsSigned=*/true);
}
@@ -5969,12 +6359,12 @@ emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
// the expression is captured in the enclosing target environment when the
// teams directive is not combined with target.
- const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+ const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
- if (auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>(
+ if (const auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>(
ignoreCompoundStmts(CS.getCapturedStmt()))) {
if (isOpenMPTeamsDirective(TeamsDir->getDirectiveKind())) {
- if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
+ if (const auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
CGOpenMPInnerExprInfo CGInfo(CGF, CS);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
@@ -6004,12 +6394,11 @@ static llvm::Value *
emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
CodeGenFunction &CGF,
const OMPExecutableDirective &D) {
-
assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
"teams directive expected to be "
"emitted only for the host!");
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
//
// If the target directive is combined with a teams directive:
@@ -6034,8 +6423,9 @@ emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
if (const auto *ThreadLimitClause =
D.getSingleClause<OMPThreadLimitClause>()) {
CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
- auto ThreadLimit = CGF.EmitScalarExpr(ThreadLimitClause->getThreadLimit(),
- /*IgnoreResultAssign*/ true);
+ llvm::Value *ThreadLimit =
+ CGF.EmitScalarExpr(ThreadLimitClause->getThreadLimit(),
+ /*IgnoreResultAssign*/ true);
ThreadLimitVal = Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty,
/*IsSigned=*/true);
}
@@ -6072,12 +6462,12 @@ emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
// the expression is captured in the enclosing target environment when the
// teams directive is not combined with target.
- const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+ const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
- if (auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>(
+ if (const auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>(
ignoreCompoundStmts(CS.getCapturedStmt()))) {
if (isOpenMPTeamsDirective(TeamsDir->getDirectiveKind())) {
- if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
+ if (const auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
CGOpenMPInnerExprInfo CGInfo(CGF, CS);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
@@ -6096,42 +6486,50 @@ emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
}
namespace {
-// \brief Utility to handle information from clauses associated with a given
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+// Utility to handle information from clauses associated with a given
// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
// It provides a convenient interface to obtain the information and generate
// code for that information.
class MappableExprsHandler {
public:
- /// \brief Values for bit flags used to specify the mapping type for
+ /// Values for bit flags used to specify the mapping type for
/// offloading.
- enum OpenMPOffloadMappingFlags {
- /// \brief Allocate memory on the device and move data from host to device.
+ enum OpenMPOffloadMappingFlags : uint64_t {
+ /// No flags
+ OMP_MAP_NONE = 0x0,
+ /// Allocate memory on the device and move data from host to device.
OMP_MAP_TO = 0x01,
- /// \brief Allocate memory on the device and move data from device to host.
+ /// Allocate memory on the device and move data from device to host.
OMP_MAP_FROM = 0x02,
- /// \brief Always perform the requested mapping action on the element, even
+ /// Always perform the requested mapping action on the element, even
/// if it was already mapped before.
OMP_MAP_ALWAYS = 0x04,
- /// \brief Delete the element from the device environment, ignoring the
+ /// 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-pointee pair; both the
+ /// 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
+ /// 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
+ /// Signal that the runtime library has to return the device pointer
/// 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
+ /// This flag signals that the reference being passed is a pointer to
/// private data.
OMP_MAP_PRIVATE = 0x80,
- /// \brief Pass the element to the device by value.
+ /// Pass the element to the device by value.
OMP_MAP_LITERAL = 0x100,
/// Implicit map
OMP_MAP_IMPLICIT = 0x200,
+ /// The 16 MSBs of the flags indicate whether the entry is member of some
+ /// struct/class.
+ OMP_MAP_MEMBER_OF = 0xffff000000000000,
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
};
/// Class that associates information with a base pointer to be passed to the
@@ -6151,21 +6549,60 @@ public:
void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
};
- typedef SmallVector<BasePointerInfo, 16> MapBaseValuesArrayTy;
- typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy;
- typedef SmallVector<uint64_t, 16> MapFlagsArrayTy;
+ using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
+ using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
+ using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
+
+ /// Map between a struct and the its lowest & highest elements which have been
+ /// mapped.
+ /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
+ /// HE(FieldIndex, Pointer)}
+ struct StructRangeInfoTy {
+ std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
+ 0, Address::invalid()};
+ std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
+ 0, Address::invalid()};
+ Address Base = Address::invalid();
+ };
private:
- /// \brief Directive from where the map clauses were extracted.
+ /// Kind that defines how a device pointer has to be returned.
+ struct MapInfo {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+ OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ bool ReturnDevicePointer = false;
+ bool IsImplicit = false;
+
+ MapInfo() = default;
+ MapInfo(
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
+ OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
+ bool ReturnDevicePointer, bool IsImplicit)
+ : Components(Components), MapType(MapType),
+ MapTypeModifier(MapTypeModifier),
+ ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
+ };
+
+ /// If use_device_ptr is used on a pointer which is a struct member and there
+ /// is no map information about it, then emission of that entry is deferred
+ /// until the whole struct has been processed.
+ struct DeferredDevicePtrEntryTy {
+ const Expr *IE = nullptr;
+ const ValueDecl *VD = nullptr;
+
+ DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
+ : IE(IE), VD(VD) {}
+ };
+
+ /// Directive from where the map clauses were extracted.
const OMPExecutableDirective &CurDir;
- /// \brief Function the directive is being generated for.
+ /// Function the directive is being generated for.
CodeGenFunction &CGF;
- /// \brief Set of all first private variables in the current directive.
+ /// 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.
@@ -6175,10 +6612,10 @@ private:
DevPointersMap;
llvm::Value *getExprTypeSize(const Expr *E) const {
- auto ExprTy = E->getType().getCanonicalType();
+ QualType ExprTy = E->getType().getCanonicalType();
// Reference types are ignored for mapping purposes.
- if (auto *RefTy = ExprTy->getAs<ReferenceType>())
+ if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
ExprTy = RefTy->getPointeeType().getCanonicalType();
// Given that an array section is considered a built-in type, we need to
@@ -6195,10 +6632,10 @@ private:
return CGF.getTypeSize(BaseTy);
llvm::Value *ElemSize;
- if (auto *PTy = BaseTy->getAs<PointerType>())
+ if (const auto *PTy = BaseTy->getAs<PointerType>()) {
ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
- else {
- auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
+ } else {
+ const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
assert(ATy && "Expecting array type if not a pointer type.");
ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
}
@@ -6208,7 +6645,7 @@ private:
if (!OAE->getLength())
return ElemSize;
- auto *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
+ llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
LengthVal =
CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
@@ -6216,14 +6653,16 @@ private:
return CGF.getTypeSize(ExprTy);
}
- /// \brief Return the corresponding bits for a given map clause modifier. Add
+ /// Return the corresponding bits for a given map clause modifier. Add
/// 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.
- uint64_t getMapTypeBits(OpenMPMapClauseKind MapType,
- OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag,
- bool AddIsTargetParamFlag) const {
- uint64_t Bits = 0u;
+ OpenMPOffloadMappingFlags getMapTypeBits(OpenMPMapClauseKind MapType,
+ OpenMPMapClauseKind MapTypeModifier,
+ bool IsImplicit, bool AddPtrFlag,
+ bool AddIsTargetParamFlag) const {
+ OpenMPOffloadMappingFlags Bits =
+ IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
switch (MapType) {
case OMPC_MAP_alloc:
case OMPC_MAP_release:
@@ -6233,20 +6672,20 @@ private:
// type modifiers.
break;
case OMPC_MAP_to:
- Bits = OMP_MAP_TO;
+ Bits |= OMP_MAP_TO;
break;
case OMPC_MAP_from:
- Bits = OMP_MAP_FROM;
+ Bits |= OMP_MAP_FROM;
break;
case OMPC_MAP_tofrom:
- Bits = OMP_MAP_TO | OMP_MAP_FROM;
+ Bits |= OMP_MAP_TO | OMP_MAP_FROM;
break;
case OMPC_MAP_delete:
- Bits = OMP_MAP_DELETE;
+ Bits |= OMP_MAP_DELETE;
break;
- default:
+ case OMPC_MAP_always:
+ case OMPC_MAP_unknown:
llvm_unreachable("Unexpected map type!");
- break;
}
if (AddPtrFlag)
Bits |= OMP_MAP_PTR_AND_OBJ;
@@ -6257,10 +6696,10 @@ private:
return Bits;
}
- /// \brief Return true if the provided expression is a final array section. A
+ /// Return true if the provided expression is a final array section. A
/// final array section, is one whose length can't be proved to be one.
bool isFinalArraySectionExpression(const Expr *E) const {
- auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
// It is not an array section and therefore not a unity-size one.
if (!OASE)
@@ -6270,16 +6709,16 @@ private:
if (OASE->getColonLoc().isInvalid())
return false;
- auto *Length = OASE->getLength();
+ const Expr *Length = OASE->getLength();
// If we don't have a length we have to check if the array has size 1
// for this dimension. Also, we should always expect a length if the
// base type is pointer.
if (!Length) {
- auto BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
- OASE->getBase()->IgnoreParenImpCasts())
- .getCanonicalType();
- if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
+ QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
+ OASE->getBase()->IgnoreParenImpCasts())
+ .getCanonicalType();
+ if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
// If we don't have a constant dimension length, we have to consider
// the current section as having any size, so it is not necessarily
@@ -6295,7 +6734,7 @@ private:
return ConstLength.getSExtValue() != 1;
}
- /// \brief Generate the base pointers, section pointers, sizes and map type
+ /// Generate the base pointers, section pointers, sizes and map type
/// bits for the provided map type, map modifier, and expression components.
/// \a IsFirstComponent should be set to true if the provided set of
/// components is the first associated with a capture.
@@ -6304,10 +6743,10 @@ private:
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
- bool IsFirstComponentList, bool IsImplicit) const {
-
+ StructRangeInfoTy &PartialStruct, 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:
+ // types below. The generated information is expressed in this order:
// base pointer, section pointer, size, flags
// (to add to the ones that come from the map type and modifier).
//
@@ -6330,96 +6769,141 @@ private:
// S2 *ps;
//
// map(d)
- // &d, &d, sizeof(double), noflags
+ // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
//
// map(i)
- // &i, &i, 100*sizeof(int), noflags
+ // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
//
// map(i[1:23])
- // &i(=&i[0]), &i[1], 23*sizeof(int), noflags
+ // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
//
// map(p)
- // &p, &p, sizeof(float*), noflags
+ // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
//
// map(p[1:24])
- // p, &p[1], 24*sizeof(float), noflags
+ // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
//
// map(s)
- // &s, &s, sizeof(S2), noflags
+ // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
//
// map(s.i)
- // &s, &(s.i), sizeof(int), noflags
+ // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
//
// map(s.s.f)
- // &s, &(s.i.f), 50*sizeof(int), noflags
+ // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
//
// map(s.p)
- // &s, &(s.p), sizeof(double*), noflags
+ // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
//
- // map(s.p[:22], s.a s.b)
- // &s, &(s.p), sizeof(double*), noflags
- // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag
+ // map(to: s.p[:22])
+ // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
+ // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
+ // &(s.p), &(s.p[0]), 22*sizeof(double),
+ // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
+ // (*) alloc space for struct members, only this is a target parameter
+ // (**) map the pointer (nothing to be mapped in this example) (the compiler
+ // optimizes this entry out, same in the examples below)
+ // (***) map the pointee (map: to)
//
// map(s.ps)
- // &s, &(s.ps), sizeof(S2*), noflags
+ // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
//
- // map(s.ps->s.i)
- // &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag
+ // map(from: s.ps->s.i)
+ // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
+ // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
+ // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
//
- // map(s.ps->ps)
- // &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag
+ // map(to: s.ps->ps)
+ // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
+ // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
+ // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
//
// map(s.ps->ps->ps)
- // &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag
- // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag
+ // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
+ // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
+ // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
+ // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
//
- // map(s.ps->ps->s.f[:22])
- // &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag
- // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag
+ // map(to: s.ps->ps->s.f[:22])
+ // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
+ // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
+ // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
+ // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
//
// map(ps)
- // &ps, &ps, sizeof(S2*), noflags
+ // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
//
// map(ps->i)
- // ps, &(ps->i), sizeof(int), noflags
+ // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
//
// map(ps->s.f)
- // ps, &(ps->s.f[0]), 50*sizeof(float), noflags
+ // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
//
- // map(ps->p)
- // ps, &(ps->p), sizeof(double*), noflags
+ // map(from: ps->p)
+ // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
//
- // map(ps->p[:22])
- // ps, &(ps->p), sizeof(double*), noflags
- // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag
+ // map(to: ps->p[:22])
+ // ps, &(ps->p), sizeof(double*), TARGET_PARAM
+ // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
+ // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
//
// map(ps->ps)
- // ps, &(ps->ps), sizeof(S2*), noflags
+ // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
//
- // map(ps->ps->s.i)
- // ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag
+ // map(from: ps->ps->s.i)
+ // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
+ // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
+ // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
//
- // map(ps->ps->ps)
- // ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag
+ // map(from: ps->ps->ps)
+ // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
+ // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
+ // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
//
// map(ps->ps->ps->ps)
- // ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag
- // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag
+ // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
+ // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
+ // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
+ // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
+ //
+ // map(to: ps->ps->ps->s.f[:22])
+ // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
+ // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
+ // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
+ // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
+ //
+ // map(to: s.f[:22]) map(from: s.p[:33])
+ // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
+ // sizeof(double*) (**), TARGET_PARAM
+ // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
+ // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
+ // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
+ // (*) allocate contiguous space needed to fit all mapped members even if
+ // we allocate space for members not mapped (in this example,
+ // s.f[22..49] and s.s are not mapped, yet we must allocate space for
+ // them as well because they fall between &s.f[0] and &s.p)
//
- // map(ps->ps->ps->s.f[:22])
- // ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag
- // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag
+ // map(from: s.f[:22]) map(to: ps->p[:33])
+ // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
+ // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
+ // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
+ // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
+ // (*) the struct this entry pertains to is the 2nd element in the list of
+ // arguments, hence MEMBER_OF(2)
+ //
+ // map(from: s.f[:22], s.s) map(to: ps->p[:33])
+ // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
+ // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
+ // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
+ // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
+ // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
+ // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
+ // (*) the struct this entry pertains to is the 4th element in the list
+ // of arguments, hence MEMBER_OF(4)
// Track if the map information being generated is the first for a capture.
bool IsCaptureFirstInfo = IsFirstComponentList;
+ bool IsLink = false; // Is this variable a "declare target link"?
// Scan the components from the base to the complete expression.
auto CI = Components.rbegin();
@@ -6429,16 +6913,25 @@ private:
// Track if the map information being generated is the first for a list of
// components.
bool IsExpressionFirstInfo = true;
- llvm::Value *BP = nullptr;
+ Address BP = Address::invalid();
- if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
+ if (isa<MemberExpr>(I->getAssociatedExpression())) {
// The base is the 'this' pointer. The content of the pointer is going
// to be the base of the field being mapped.
- BP = CGF.EmitScalarExpr(ME->getBase());
+ BP = CGF.LoadCXXThisAddress();
} else {
// The base is the reference to the variable.
// BP = &Var.
- BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer();
+ BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
+ if (const auto *VD =
+ dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
+ if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ if (*Res == OMPDeclareTargetDeclAttr::MT_Link) {
+ IsLink = true;
+ BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
+ }
+ }
// 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
@@ -6446,10 +6939,7 @@ private:
QualType Ty =
I->getAssociatedDeclaration()->getType().getNonReferenceType();
if (Ty->isAnyPointerType() && std::next(I) != CE) {
- auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(BP, Ty);
- BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(),
- Ty->castAs<PointerType>())
- .getPointer();
+ BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
// We do not need to generate individual map information for the
// pointer, it can be associated with the combined storage.
@@ -6457,8 +6947,41 @@ private:
}
}
- uint64_t DefaultFlags = IsImplicit ? OMP_MAP_IMPLICIT : 0;
+ // Track whether a component of the list should be marked as MEMBER_OF some
+ // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
+ // in a component list should be marked as MEMBER_OF, all subsequent entries
+ // do not belong to the base struct. E.g.
+ // struct S2 s;
+ // s.ps->ps->ps->f[:]
+ // (1) (2) (3) (4)
+ // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
+ // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
+ // is the pointee of ps(2) which is not member of struct s, so it should not
+ // be marked as such (it is still PTR_AND_OBJ).
+ // The variable is initialized to false so that PTR_AND_OBJ entries which
+ // are not struct members are not considered (e.g. array of pointers to
+ // data).
+ bool ShouldBeMemberOf = false;
+
+ // Variable keeping track of whether or not we have encountered a component
+ // in the component list which is a member expression. Useful when we have a
+ // pointer or a final array section, in which case it is the previous
+ // component in the list which tells us whether we have a member expression.
+ // E.g. X.f[:]
+ // While processing the final array section "[:]" it is "f" which tells us
+ // whether we are dealing with a member of a declared struct.
+ const MemberExpr *EncounteredME = nullptr;
+
for (; I != CE; ++I) {
+ // If the current component is member of a struct (parent struct) mark it.
+ if (!EncounteredME) {
+ EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
+ // If we encounter a PTR_AND_OBJ entry from now on it should be marked
+ // as MEMBER_OF the parent struct.
+ if (EncounteredME)
+ ShouldBeMemberOf = true;
+ }
+
auto Next = std::next(I);
// We need to generate the addresses and sizes if this is the last
@@ -6476,14 +6999,12 @@ private:
const auto *OASE =
dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
bool IsPointer =
- (OASE &&
- OMPArraySectionExpr::getBaseOriginalType(OASE)
- .getCanonicalType()
- ->isAnyPointerType()) ||
+ (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
+ .getCanonicalType()
+ ->isAnyPointerType()) ||
I->getAssociatedExpression()->getType()->isAnyPointerType();
if (Next == CE || IsPointer || IsFinalArraySection) {
-
// If this is not the last component, we expect the pointer to be
// associated with an array expression or member expression.
assert((Next == CE ||
@@ -6492,44 +7013,68 @@ private:
isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
"Unexpected expression");
- 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
- // reference, we have to map the reference too. Whenever we have a
- // reference, the section that reference refers to is going to be a
- // load instruction from the storage assigned to the reference.
- if (isa<MemberExpr>(I->getAssociatedExpression()) &&
- I->getAssociatedDeclaration()->getType()->isReferenceType()) {
- auto *LI = cast<llvm::LoadInst>(LB);
- auto *RefAddr = LI->getPointerOperand();
-
- BasePointers.push_back(BP);
- Pointers.push_back(RefAddr);
- Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
- 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.
- BP = RefAddr;
- }
+ Address LB =
+ CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
+ llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
+
+ // If this component is a pointer inside the base struct then we don't
+ // need to create any entry for it - it will be combined with the object
+ // it is pointing to into a single PTR_AND_OBJ entry.
+ bool IsMemberPointer =
+ IsPointer && EncounteredME &&
+ (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
+ EncounteredME);
+ if (!IsMemberPointer) {
+ BasePointers.push_back(BP.getPointer());
+ Pointers.push_back(LB.getPointer());
+ Sizes.push_back(Size);
+
+ // We need to add a pointer flag for each map that comes from the
+ // 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).
+ OpenMPOffloadMappingFlags Flags = getMapTypeBits(
+ MapType, MapTypeModifier, IsImplicit,
+ !IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink);
+
+ if (!IsExpressionFirstInfo) {
+ // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
+ // then we reset the TO/FROM/ALWAYS/DELETE flags.
+ if (IsPointer)
+ Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
+ OMP_MAP_DELETE);
+
+ if (ShouldBeMemberOf) {
+ // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
+ // should be later updated with the correct value of MEMBER_OF.
+ Flags |= OMP_MAP_MEMBER_OF;
+ // From now on, all subsequent PTR_AND_OBJ entries should not be
+ // marked as MEMBER_OF.
+ ShouldBeMemberOf = false;
+ }
+ }
- BasePointers.push_back(BP);
- Pointers.push_back(LB);
- Sizes.push_back(Size);
+ Types.push_back(Flags);
+ }
- // We need to add a pointer flag for each map that comes from the
- // 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(DefaultFlags | getMapTypeBits(MapType, MapTypeModifier,
- !IsExpressionFirstInfo,
- IsCaptureFirstInfo));
+ // If we have encountered a member expression so far, keep track of the
+ // mapped member. If the parent is "*this", then the value declaration
+ // is nullptr.
+ if (EncounteredME) {
+ const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
+ unsigned FieldIndex = FD->getFieldIndex();
+
+ // Update info about the lowest and highest elements for this struct
+ if (!PartialStruct.Base.isValid()) {
+ PartialStruct.LowestElem = {FieldIndex, LB};
+ PartialStruct.HighestElem = {FieldIndex, LB};
+ PartialStruct.Base = BP;
+ } else if (FieldIndex < PartialStruct.LowestElem.first) {
+ PartialStruct.LowestElem = {FieldIndex, LB};
+ } else if (FieldIndex > PartialStruct.HighestElem.first) {
+ PartialStruct.HighestElem = {FieldIndex, LB};
+ }
+ }
// If we have a final array section, we are done with this expression.
if (IsFinalArraySection)
@@ -6545,11 +7090,11 @@ private:
}
}
- /// \brief Return the adjusted map modifiers if the declaration a capture
- /// refers to appears in a first-private clause. This is expected to be used
- /// only with directives that start with 'target'.
- unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap,
- unsigned CurrentModifiers) {
+ /// Return the adjusted map modifiers if the declaration a capture refers to
+ /// appears in a first-private clause. This is expected to be used only with
+ /// directives that start with 'target'.
+ MappableExprsHandler::OpenMPOffloadMappingFlags
+ getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
assert(Cap.capturesVariable() && "Expected capture by reference only!");
// A first private variable captured by reference will use only the
@@ -6558,15 +7103,29 @@ private:
if (FirstPrivateDecls.count(Cap.getCapturedVar()))
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;
- }
+ return MappableExprsHandler::OMP_MAP_TO |
+ MappableExprsHandler::OMP_MAP_FROM;
+ }
+
+ static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
+ // Member of is given by the 16 MSB of the flag, so rotate by 48 bits.
+ return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
+ << 48);
+ }
+
+ static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
+ OpenMPOffloadMappingFlags MemberOfFlag) {
+ // If the entry is PTR_AND_OBJ but has not been marked with the special
+ // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
+ // marked as MEMBER_OF.
+ if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
+ ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
+ return;
- // We didn't modify anything.
- return CurrentModifiers;
+ // Reset the placeholder value to prepare the flag for the assignment of the
+ // proper MEMBER_OF value.
+ Flags &= ~OMP_MAP_MEMBER_OF;
+ Flags |= MemberOfFlag;
}
public:
@@ -6577,58 +7136,54 @@ 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())
DevPointersMap[L.first].push_back(L.second);
}
- /// \brief Generate all the base pointers, section pointers, sizes and map
+ /// Generate code for the combined entry if we have a partially mapped struct
+ /// and take care of the mapping flags of the arguments corresponding to
+ /// individual struct members.
+ void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
+ MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
+ MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
+ const StructRangeInfoTy &PartialStruct) const {
+ // Base is the base of the struct
+ BasePointers.push_back(PartialStruct.Base.getPointer());
+ // Pointer is the address of the lowest element
+ llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
+ Pointers.push_back(LB);
+ // Size is (addr of {highest+1} element) - (addr of lowest element)
+ llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
+ llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
+ llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
+ llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
+ llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
+ llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.SizeTy,
+ /*isSinged=*/false);
+ Sizes.push_back(Size);
+ // Map type is always TARGET_PARAM
+ Types.push_back(OMP_MAP_TARGET_PARAM);
+ // Remove TARGET_PARAM flag from the first element
+ (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
+
+ // All other current entries will be MEMBER_OF the combined entry
+ // (except for PTR_AND_OBJ entries which do not have a placeholder value
+ // 0xFFFF in the MEMBER_OF field).
+ OpenMPOffloadMappingFlags MemberOfFlag =
+ getMemberOfFlag(BasePointers.size() - 1);
+ for (auto &M : CurTypes)
+ setCorrectMemberOfFlag(M, MemberOfFlag);
+ }
+
+ /// Generate all the base pointers, section pointers, sizes and map
/// types for the extracted mappable expressions. Also, for each item that
/// relates with a device pointer, a pair of the relevant declaration and
/// index where it occurs is appended to the device pointers info array.
void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
MapFlagsArrayTy &Types) const {
- BasePointers.clear();
- Pointers.clear();
- Sizes.clear();
- Types.clear();
-
- struct MapInfo {
- /// Kind that defines how a device pointer has to be returned.
- enum ReturnPointerKind {
- // Don't have to return any pointer.
- RPK_None,
- // Pointer is the base of the declaration.
- RPK_Base,
- // Pointer is a member of the base declaration - 'this'
- RPK_Member,
- // Pointer is a reference and a member of the base declaration - 'this'
- RPK_MemberReference,
- };
- OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
- OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
- OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
- ReturnPointerKind ReturnDevicePointer = RPK_None;
- bool IsImplicit = false;
-
- MapInfo() = default;
- MapInfo(
- OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
- OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
- ReturnPointerKind ReturnDevicePointer, bool IsImplicit)
- : Components(Components), MapType(MapType),
- MapTypeModifier(MapTypeModifier),
- ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
- };
-
// We have to process the component lists that relate with the same
// declaration in a single chunk so that we can generate the map flags
// correctly. Therefore, we organize all lists in a map.
@@ -6640,7 +7195,7 @@ public:
const ValueDecl *D,
OMPClauseMappableExprCommon::MappableExprComponentListRef L,
OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier,
- MapInfo::ReturnPointerKind ReturnDevicePointer, bool IsImplicit) {
+ bool ReturnDevicePointer, bool IsImplicit) {
const ValueDecl *VD =
D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Info[VD].emplace_back(L, MapType, MapModifier, ReturnDevicePointer,
@@ -6648,33 +7203,39 @@ public:
};
// 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 (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
+ for (const auto &L : C->component_lists()) {
InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(),
- MapInfo::RPK_None, C->isImplicit());
+ /*ReturnDevicePointer=*/false, C->isImplicit());
}
- for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
- for (auto L : C->component_lists()) {
+ for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
+ for (const auto &L : C->component_lists()) {
InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown,
- MapInfo::RPK_None, C->isImplicit());
+ /*ReturnDevicePointer=*/false, C->isImplicit());
}
- for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
- for (auto L : C->component_lists()) {
+ for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
+ for (const auto &L : C->component_lists()) {
InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown,
- MapInfo::RPK_None, C->isImplicit());
+ /*ReturnDevicePointer=*/false, 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
// use_device_ptr list, we create one with map type 'alloc' and zero size
- // section. It is the user fault if that was not mapped before.
+ // section. It is the user fault if that was not mapped before. If there is
+ // no map information and the pointer is a struct member, then we defer the
+ // emission of that entry until the whole struct has been processed.
+ llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
+ DeferredInfo;
+
// FIXME: MSVC 2013 seems to require this-> to find member CurDir.
- for (auto *C : this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>())
- for (auto L : C->component_lists()) {
+ for (const auto *C :
+ this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) {
+ for (const auto &L : C->component_lists()) {
assert(!L.second.empty() && "Not expecting empty list of components!");
const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
VD = cast<ValueDecl>(VD->getCanonicalDecl());
- auto *IE = L.second.back().getAssociatedExpression();
+ const Expr *IE = L.second.back().getAssociatedExpression();
// If the first component is a member expression, we have to look into
// 'this', which maps to null in the map of map information. Otherwise
// look directly for the information.
@@ -6690,113 +7251,135 @@ public:
// If we found a map entry, signal that the pointer has to be returned
// and move on to the next declaration.
if (CI != It->second.end()) {
- CI->ReturnDevicePointer = isa<MemberExpr>(IE)
- ? (VD->getType()->isReferenceType()
- ? MapInfo::RPK_MemberReference
- : MapInfo::RPK_Member)
- : MapInfo::RPK_Base;
+ CI->ReturnDevicePointer = true;
continue;
}
}
// We didn't find any match in our map information - generate a zero
- // size array section.
+ // size array section - if the pointer is a struct member we defer this
+ // action until the whole struct has been processed.
// FIXME: MSVC 2013 seems to require this-> to find member CGF.
- llvm::Value *Ptr =
- this->CGF
- .EmitLoadOfLValue(this->CGF.EmitLValue(IE), SourceLocation())
- .getScalarVal();
- BasePointers.push_back({Ptr, VD});
- Pointers.push_back(Ptr);
- Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
- Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
+ if (isa<MemberExpr>(IE)) {
+ // Insert the pointer into Info to be processed by
+ // generateInfoForComponentList. Because it is a member pointer
+ // without a pointee, no entry will be generated for it, therefore
+ // we need to generate one after the whole struct has been processed.
+ // Nonetheless, generateInfoForComponentList must be called to take
+ // the pointer into account for the calculation of the range of the
+ // partial struct.
+ InfoGen(nullptr, L.second, OMPC_MAP_unknown, OMPC_MAP_unknown,
+ /*ReturnDevicePointer=*/false, C->isImplicit());
+ DeferredInfo[nullptr].emplace_back(IE, VD);
+ } else {
+ llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
+ this->CGF.EmitLValue(IE), IE->getExprLoc());
+ BasePointers.emplace_back(Ptr, VD);
+ Pointers.push_back(Ptr);
+ Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
+ Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
+ }
}
+ }
- for (auto &M : Info) {
+ for (const auto &M : Info) {
// We need to know when we generate information for the first component
// associated with a capture, because the mapping flags depend on it.
bool IsFirstComponentList = true;
- for (MapInfo &L : M.second) {
+
+ // Temporary versions of arrays
+ MapBaseValuesArrayTy CurBasePointers;
+ MapValuesArrayTy CurPointers;
+ MapValuesArrayTy CurSizes;
+ MapFlagsArrayTy CurTypes;
+ StructRangeInfoTy PartialStruct;
+
+ for (const MapInfo &L : M.second) {
assert(!L.Components.empty() &&
"Not expecting declaration with no component lists.");
// Remember the current base pointer index.
- unsigned CurrentBasePointersIdx = BasePointers.size();
+ unsigned CurrentBasePointersIdx = CurBasePointers.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, L.IsImplicit);
+ L.MapType, L.MapTypeModifier, L.Components, CurBasePointers,
+ CurPointers, CurSizes, CurTypes, PartialStruct,
+ IsFirstComponentList, L.IsImplicit);
// If this entry relates with a device pointer, set the relevant
// declaration and add the 'return pointer' flag.
- if (IsFirstComponentList &&
- L.ReturnDevicePointer != MapInfo::RPK_None) {
- // If the pointer is not the base of the map, we need to skip the
- // base. If it is a reference in a member field, we also need to skip
- // the map of the reference.
- if (L.ReturnDevicePointer != MapInfo::RPK_Base) {
- ++CurrentBasePointersIdx;
- if (L.ReturnDevicePointer == MapInfo::RPK_MemberReference)
- ++CurrentBasePointersIdx;
- }
- assert(BasePointers.size() > CurrentBasePointersIdx &&
+ if (L.ReturnDevicePointer) {
+ assert(CurBasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.");
- auto *RelevantVD = L.Components.back().getAssociatedDeclaration();
+ const ValueDecl *RelevantVD =
+ L.Components.back().getAssociatedDeclaration();
assert(RelevantVD &&
"No relevant declaration related with device pointer??");
- BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
- Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
+ CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
+ CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
}
IsFirstComponentList = false;
}
+
+ // Append any pending zero-length pointers which are struct members and
+ // used with use_device_ptr.
+ auto CI = DeferredInfo.find(M.first);
+ if (CI != DeferredInfo.end()) {
+ for (const DeferredDevicePtrEntryTy &L : CI->second) {
+ llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
+ llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
+ this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
+ CurBasePointers.emplace_back(BasePtr, L.VD);
+ CurPointers.push_back(Ptr);
+ CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
+ // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
+ // value MEMBER_OF=FFFF so that the entry is later updated with the
+ // correct value of MEMBER_OF.
+ CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
+ OMP_MAP_MEMBER_OF);
+ }
+ }
+
+ // If there is an entry in PartialStruct it means we have a struct with
+ // individual members mapped. Emit an extra combined entry.
+ if (PartialStruct.Base.isValid())
+ emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
+ PartialStruct);
+
+ // We need to append the results of this capture to what we already have.
+ BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
+ Pointers.append(CurPointers.begin(), CurPointers.end());
+ Sizes.append(CurSizes.begin(), CurSizes.end());
+ Types.append(CurTypes.begin(), CurTypes.end());
}
}
- /// \brief Generate the base pointers, section pointers, sizes and map types
+ /// Generate the base pointers, section pointers, sizes and map types
/// associated to a given capture.
void generateInfoForCapture(const CapturedStmt::Capture *Cap,
llvm::Value *Arg,
MapBaseValuesArrayTy &BasePointers,
MapValuesArrayTy &Pointers,
- MapValuesArrayTy &Sizes,
- MapFlagsArrayTy &Types) const {
+ MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
+ StructRangeInfoTy &PartialStruct) const {
assert(!Cap->capturesVariableArrayType() &&
"Not expecting to generate map info for a variable array type!");
- BasePointers.clear();
- Pointers.clear();
- Sizes.clear();
- Types.clear();
-
// We need to know when we generating information for the first component
// associated with a capture, because the mapping flags depend on it.
bool IsFirstComponentList = true;
- const ValueDecl *VD =
- Cap->capturesThis()
- ? nullptr
- : cast<ValueDecl>(Cap->getCapturedVar()->getCanonicalDecl());
+ const ValueDecl *VD = Cap->capturesThis()
+ ? nullptr
+ : Cap->getCapturedVar()->getCanonicalDecl();
// If this declaration appears in a is_device_ptr clause we just have to
// pass the pointer by value. If it is a reference to a declaration, we just
- // pass its value, otherwise, if it is a member expression, we need to map
- // 'to' the field.
- if (!VD) {
- auto It = DevPointersMap.find(VD);
- if (It != DevPointersMap.end()) {
- for (auto L : It->second) {
- generateInfoForComponentList(
- /*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L,
- BasePointers, Pointers, Sizes, Types, IsFirstComponentList,
- /*IsImplicit=*/false);
- IsFirstComponentList = false;
- }
- return;
- }
- } else if (DevPointersMap.count(VD)) {
- BasePointers.push_back({Arg, VD});
+ // pass its value.
+ if (DevPointersMap.count(VD)) {
+ BasePointers.emplace_back(Arg, VD);
Pointers.push_back(Arg);
Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
@@ -6804,35 +7387,63 @@ public:
}
// FIXME: MSVC 2013 seems to require this-> to find member CurDir.
- for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
- for (auto L : C->decl_component_lists(VD)) {
+ for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
+ for (const auto &L : C->decl_component_lists(VD)) {
assert(L.first == VD &&
"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, C->isImplicit());
+ generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(),
+ L.second, BasePointers, Pointers, Sizes,
+ Types, PartialStruct, IsFirstComponentList,
+ C->isImplicit());
IsFirstComponentList = false;
}
+ }
- return;
+ /// Generate the base pointers, section pointers, sizes and map types
+ /// associated with the declare target link variables.
+ void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
+ MapValuesArrayTy &Pointers,
+ MapValuesArrayTy &Sizes,
+ MapFlagsArrayTy &Types) const {
+ // Map other list items in the map clause which are not captured variables
+ // but "declare target link" global variables.,
+ for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
+ for (const auto &L : C->component_lists()) {
+ if (!L.first)
+ continue;
+ const auto *VD = dyn_cast<VarDecl>(L.first);
+ if (!VD)
+ continue;
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
+ continue;
+ StructRangeInfoTy PartialStruct;
+ generateInfoForComponentList(
+ C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers,
+ Pointers, Sizes, Types, PartialStruct,
+ /*IsFirstComponentList=*/true, C->isImplicit());
+ assert(!PartialStruct.Base.isValid() &&
+ "No partial structs for declare target link expected.");
+ }
+ }
}
- /// \brief Generate the default map information for a given capture \a CI,
+ /// Generate the default map information for a given capture \a CI,
/// record field declaration \a RI and captured value \a CV.
void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
const FieldDecl &RI, llvm::Value *CV,
MapBaseValuesArrayTy &CurBasePointers,
MapValuesArrayTy &CurPointers,
MapValuesArrayTy &CurSizes,
- MapFlagsArrayTy &CurMapTypes) {
-
+ MapFlagsArrayTy &CurMapTypes) const {
// Do the default mapping.
if (CI.capturesThis()) {
CurBasePointers.push_back(CV);
CurPointers.push_back(CV);
- const PointerType *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
+ const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType()));
// Default map type.
CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
@@ -6847,7 +7458,7 @@ public:
} else {
// Pointers are implicitly mapped with a zero size and no flags
// (other than first map that is added for all implicit maps).
- CurMapTypes.push_back(0u);
+ CurMapTypes.push_back(OMP_MAP_NONE);
CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy));
}
} else {
@@ -6855,30 +7466,30 @@ public:
CurBasePointers.push_back(CV);
CurPointers.push_back(CV);
- const ReferenceType *PtrTy =
- cast<ReferenceType>(RI.getType().getTypePtr());
+ const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
QualType ElementType = PtrTy->getPointeeType();
CurSizes.push_back(CGF.getTypeSize(ElementType));
// 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.emplace_back(adjustMapModifiersForPrivateClauses(
- CI, ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
- : OMP_MAP_TO));
+ CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
}
// Every default map produces a single argument which is a target parameter.
CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
+
+ // Add flag stating this is an implicit map.
+ CurMapTypes.back() |= OMP_MAP_IMPLICIT;
}
};
enum OpenMPOffloadingReservedDeviceIDs {
- /// \brief Device ID if the device was not defined, runtime should get it
+ /// Device ID if the device was not defined, runtime should get it
/// from environment variables in the spec.
OMP_DEVICEID_UNDEF = -1,
};
} // anonymous namespace
-/// \brief Emit the arrays used to pass the captures and map information to the
+/// Emit the arrays used to pass the captures and map information to the
/// offloading runtime library. If there is no map or capture information,
/// return nullptr by reference.
static void
@@ -6888,8 +7499,8 @@ emitOffloadingArrays(CodeGenFunction &CGF,
MappableExprsHandler::MapValuesArrayTy &Sizes,
MappableExprsHandler::MapFlagsArrayTy &MapTypes,
CGOpenMPRuntime::TargetDataInfo &Info) {
- auto &CGM = CGF.CGM;
- auto &Ctx = CGF.getContext();
+ CodeGenModule &CGM = CGF.CGM;
+ ASTContext &Ctx = CGF.getContext();
// Reset the array information.
Info.clearArrayInfo();
@@ -6899,7 +7510,7 @@ emitOffloadingArrays(CodeGenFunction &CGF,
// Detect if we have any capture size requiring runtime evaluation of the
// size so that a constant array could be eventually used.
bool hasRuntimeEvaluationCaptureSize = false;
- for (auto *S : Sizes)
+ for (llvm::Value *S : Sizes)
if (!isa<llvm::Constant>(S)) {
hasRuntimeEvaluationCaptureSize = true;
break;
@@ -6928,48 +7539,53 @@ emitOffloadingArrays(CodeGenFunction &CGF,
// We expect all the sizes to be constant, so we collect them to create
// a constant array.
SmallVector<llvm::Constant *, 16> ConstSizes;
- for (auto S : Sizes)
+ for (llvm::Value *S : Sizes)
ConstSizes.push_back(cast<llvm::Constant>(S));
auto *SizesArrayInit = llvm::ConstantArray::get(
llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
+ std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
auto *SizesArrayGbl = new llvm::GlobalVariable(
CGM.getModule(), SizesArrayInit->getType(),
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
- SizesArrayInit, ".offload_sizes");
+ SizesArrayInit, Name);
SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Info.SizesArray = SizesArrayGbl;
}
// The map types are always constant so we don't need to generate code to
// fill arrays. Instead, we create an array constant.
+ SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
+ llvm::copy(MapTypes, Mapping.begin());
llvm::Constant *MapTypesArrayInit =
- llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
+ llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
+ std::string MaptypesName =
+ CGM.getOpenMPRuntime().getName({"offload_maptypes"});
auto *MapTypesArrayGbl = new llvm::GlobalVariable(
CGM.getModule(), MapTypesArrayInit->getType(),
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
- MapTypesArrayInit, ".offload_maptypes");
+ MapTypesArrayInit, MaptypesName);
MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Info.MapTypesArray = MapTypesArrayGbl;
- for (unsigned i = 0; i < Info.NumberOfPtrs; ++i) {
- llvm::Value *BPVal = *BasePointers[i];
+ for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
+ llvm::Value *BPVal = *BasePointers[I];
llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
- Info.BasePointersArray, 0, i);
+ Info.BasePointersArray, 0, I);
BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
CGF.Builder.CreateStore(BPVal, BPAddr);
if (Info.requiresDevicePointerInfo())
- if (auto *DevVD = BasePointers[i].getDevicePtrDecl())
- Info.CaptureDeviceAddrMap.insert(std::make_pair(DevVD, BPAddr));
+ if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
+ Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
- llvm::Value *PVal = Pointers[i];
+ llvm::Value *PVal = Pointers[I];
llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
- Info.PointersArray, 0, i);
+ Info.PointersArray, 0, I);
P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
@@ -6980,22 +7596,22 @@ emitOffloadingArrays(CodeGenFunction &CGF,
llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs),
Info.SizesArray,
/*Idx0=*/0,
- /*Idx1=*/i);
+ /*Idx1=*/I);
Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
CGF.Builder.CreateStore(
- CGF.Builder.CreateIntCast(Sizes[i], CGM.SizeTy, /*isSigned=*/true),
+ CGF.Builder.CreateIntCast(Sizes[I], CGM.SizeTy, /*isSigned=*/true),
SAddr);
}
}
}
}
-/// \brief Emit the arguments to be passed to the runtime library based on the
+/// Emit the arguments to be passed to the runtime library based on the
/// arrays of pointers, sizes and map types.
static void emitOffloadingArraysArgument(
CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
- auto &CGM = CGF.CGM;
+ CodeGenModule &CGM = CGF.CGM;
if (Info.NumberOfPtrs) {
BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
@@ -7027,86 +7643,27 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
llvm::Value *OutlinedFn,
llvm::Value *OutlinedFnID,
- const Expr *IfCond, const Expr *Device,
- ArrayRef<llvm::Value *> CapturedVars) {
+ const Expr *IfCond, const Expr *Device) {
if (!CGF.HaveInsertPoint())
return;
assert(OutlinedFn && "Invalid outlined function!");
- // Fill up the arrays with all the captured variables.
- MappableExprsHandler::MapValuesArrayTy KernelArgs;
- MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
- MappableExprsHandler::MapValuesArrayTy Pointers;
- MappableExprsHandler::MapValuesArrayTy Sizes;
- MappableExprsHandler::MapFlagsArrayTy MapTypes;
-
- MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
- MappableExprsHandler::MapValuesArrayTy CurPointers;
- MappableExprsHandler::MapValuesArrayTy CurSizes;
- MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
-
- // Get mappable expression information.
- MappableExprsHandler MEHandler(D, CGF);
-
- const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
- auto RI = CS.getCapturedRecordDecl()->field_begin();
- auto CV = CapturedVars.begin();
- for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
- CE = CS.capture_end();
- CI != CE; ++CI, ++RI, ++CV) {
- CurBasePointers.clear();
- CurPointers.clear();
- CurSizes.clear();
- CurMapTypes.clear();
-
- // VLA sizes are passed to the outlined region by copy and do not have map
- // information associated.
- if (CI->capturesVariableArrayType()) {
- CurBasePointers.push_back(*CV);
- 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_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.
- MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
- CurSizes, CurMapTypes);
- if (CurBasePointers.empty())
- MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
- CurPointers, CurSizes, CurMapTypes);
- }
- // We expect to have at least an element of information for this capture.
- assert(!CurBasePointers.empty() && "Non-existing map pointer for capture!");
- assert(CurBasePointers.size() == CurPointers.size() &&
- CurBasePointers.size() == CurSizes.size() &&
- CurBasePointers.size() == CurMapTypes.size() &&
- "Inconsistent map information sizes!");
-
- // The kernel args are always the first elements of the base pointers
- // associated with a capture.
- KernelArgs.push_back(*CurBasePointers.front());
- // We need to append the results of this capture to what we already have.
- BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
- Pointers.append(CurPointers.begin(), CurPointers.end());
- Sizes.append(CurSizes.begin(), CurSizes.end());
- MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
- }
+ const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
+ llvm::SmallVector<llvm::Value *, 16> CapturedVars;
+ const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
+ auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
+ };
+ emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
+ CodeGenFunction::OMPTargetDataInfo InputInfo;
+ llvm::Value *MapTypesArray = nullptr;
// Fill up the pointer arrays and transfer execution to the device.
- 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;
- emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
- emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
- Info.PointersArray, Info.SizesArray,
- Info.MapTypesArray, Info);
-
+ auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
+ &MapTypesArray, &CS, RequiresOuterTask,
+ &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) {
// On top of the arrays that were filled up, the target offloading call
// takes as arguments the device id as well as the host pointer. The host
// pointer is used by the runtime library to identify the current target
@@ -7129,13 +7686,14 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
}
// Emit the number of elements in the offloading arrays.
- llvm::Value *PointerNum = CGF.Builder.getInt32(BasePointers.size());
+ llvm::Value *PointerNum =
+ CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
// Return value of the runtime offloading call.
llvm::Value *Return;
- auto *NumTeams = emitNumTeamsForTargetDirective(RT, CGF, D);
- auto *NumThreads = emitNumThreadsForTargetDirective(RT, CGF, D);
+ llvm::Value *NumTeams = emitNumTeamsForTargetDirective(*this, CGF, D);
+ llvm::Value *NumThreads = emitNumThreadsForTargetDirective(*this, CGF, D);
bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
// The target region is an outlined function launched by the runtime
@@ -7173,25 +7731,30 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
// passed to the runtime library - a 32-bit integer with the value zero.
assert(NumThreads && "Thread limit expression should be available along "
"with number of teams.");
- llvm::Value *OffloadingArgs[] = {
- DeviceID, OutlinedFnID,
- PointerNum, Info.BasePointersArray,
- Info.PointersArray, Info.SizesArray,
- Info.MapTypesArray, NumTeams,
- NumThreads};
+ llvm::Value *OffloadingArgs[] = {DeviceID,
+ OutlinedFnID,
+ PointerNum,
+ InputInfo.BasePointersArray.getPointer(),
+ InputInfo.PointersArray.getPointer(),
+ InputInfo.SizesArray.getPointer(),
+ MapTypesArray,
+ NumTeams,
+ NumThreads};
Return = CGF.EmitRuntimeCall(
- RT.createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
- : OMPRTL__tgt_target_teams),
+ 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};
+ llvm::Value *OffloadingArgs[] = {DeviceID,
+ OutlinedFnID,
+ PointerNum,
+ InputInfo.BasePointersArray.getPointer(),
+ InputInfo.PointersArray.getPointer(),
+ InputInfo.SizesArray.getPointer(),
+ MapTypesArray};
Return = CGF.EmitRuntimeCall(
- RT.createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
- : OMPRTL__tgt_target),
+ createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
+ : OMPRTL__tgt_target),
OffloadingArgs);
}
@@ -7204,17 +7767,120 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
CGF.EmitBlock(OffloadFailedBlock);
- emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn, KernelArgs);
+ if (RequiresOuterTask) {
+ CapturedVars.clear();
+ CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
+ }
+ emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn, CapturedVars);
CGF.EmitBranch(OffloadContBlock);
CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
};
// Notify that the host version must be executed.
- auto &&ElseGen = [this, &D, OutlinedFn, &KernelArgs](CodeGenFunction &CGF,
- PrePostActionTy &) {
- emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn,
- KernelArgs);
+ auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
+ RequiresOuterTask](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ if (RequiresOuterTask) {
+ CapturedVars.clear();
+ CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
+ }
+ emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn, CapturedVars);
+ };
+
+ auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
+ &CapturedVars, RequiresOuterTask,
+ &CS](CodeGenFunction &CGF, PrePostActionTy &) {
+ // Fill up the arrays with all the captured variables.
+ MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
+ MappableExprsHandler::MapValuesArrayTy Pointers;
+ MappableExprsHandler::MapValuesArrayTy Sizes;
+ MappableExprsHandler::MapFlagsArrayTy MapTypes;
+
+ // Get mappable expression information.
+ MappableExprsHandler MEHandler(D, CGF);
+
+ auto RI = CS.getCapturedRecordDecl()->field_begin();
+ auto CV = CapturedVars.begin();
+ for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
+ CE = CS.capture_end();
+ CI != CE; ++CI, ++RI, ++CV) {
+ MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
+ MappableExprsHandler::MapValuesArrayTy CurPointers;
+ MappableExprsHandler::MapValuesArrayTy CurSizes;
+ MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
+ MappableExprsHandler::StructRangeInfoTy PartialStruct;
+
+ // VLA sizes are passed to the outlined region by copy and do not have map
+ // information associated.
+ if (CI->capturesVariableArrayType()) {
+ CurBasePointers.push_back(*CV);
+ 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_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.
+ MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
+ CurSizes, CurMapTypes, PartialStruct);
+ if (CurBasePointers.empty())
+ MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
+ CurPointers, CurSizes, CurMapTypes);
+ }
+ // We expect to have at least an element of information for this capture.
+ assert(!CurBasePointers.empty() &&
+ "Non-existing map pointer for capture!");
+ assert(CurBasePointers.size() == CurPointers.size() &&
+ CurBasePointers.size() == CurSizes.size() &&
+ CurBasePointers.size() == CurMapTypes.size() &&
+ "Inconsistent map information sizes!");
+
+ // If there is an entry in PartialStruct it means we have a struct with
+ // individual members mapped. Emit an extra combined entry.
+ if (PartialStruct.Base.isValid())
+ MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
+ CurMapTypes, PartialStruct);
+
+ // We need to append the results of this capture to what we already have.
+ BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
+ Pointers.append(CurPointers.begin(), CurPointers.end());
+ Sizes.append(CurSizes.begin(), CurSizes.end());
+ MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
+ }
+ // Map other list items in the map clause which are not captured variables
+ // but "declare target link" global variables.
+ MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
+ MapTypes);
+
+ TargetDataInfo Info;
+ // Fill up the arrays and create the arguments.
+ emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
+ emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
+ Info.PointersArray, Info.SizesArray,
+ Info.MapTypesArray, Info);
+ InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
+ InputInfo.BasePointersArray =
+ Address(Info.BasePointersArray, CGM.getPointerAlign());
+ InputInfo.PointersArray =
+ Address(Info.PointersArray, CGM.getPointerAlign());
+ InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
+ MapTypesArray = Info.MapTypesArray;
+ if (RequiresOuterTask)
+ CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
+ else
+ emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
+ };
+
+ auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
+ CodeGenFunction &CGF, PrePostActionTy &) {
+ if (RequiresOuterTask) {
+ CodeGenFunction::OMPTargetDataInfo InputInfo;
+ CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
+ } else {
+ emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
+ }
};
// If we have a target function ID it means that we need to support
@@ -7222,14 +7888,14 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
// regardless of the conditional in the if clause if, e.g., the user do not
// specify target triples.
if (OutlinedFnID) {
- if (IfCond)
- emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
- else {
- RegionCodeGenTy ThenRCG(ThenGen);
+ if (IfCond) {
+ emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
+ } else {
+ RegionCodeGenTy ThenRCG(TargetThenGen);
ThenRCG(CGF);
}
} else {
- RegionCodeGenTy ElseRCG(ElseGen);
+ RegionCodeGenTy ElseRCG(TargetElseGen);
ElseRCG(CGF);
}
}
@@ -7240,13 +7906,13 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
return;
// Codegen OMP target directives that offload compute to the device.
- bool requiresDeviceCodegen =
+ bool RequiresDeviceCodegen =
isa<OMPExecutableDirective>(S) &&
isOpenMPTargetExecutionDirective(
cast<OMPExecutableDirective>(S)->getDirectiveKind());
- if (requiresDeviceCodegen) {
- auto &E = *cast<OMPExecutableDirective>(S);
+ if (RequiresDeviceCodegen) {
+ const auto &E = *cast<OMPExecutableDirective>(S);
unsigned DeviceID;
unsigned FileID;
unsigned Line;
@@ -7259,66 +7925,118 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
ParentName, Line))
return;
- switch (S->getStmtClass()) {
- case Stmt::OMPTargetDirectiveClass:
- CodeGenFunction::EmitOMPTargetDeviceFunction(
- CGM, ParentName, cast<OMPTargetDirective>(*S));
+ switch (E.getDirectiveKind()) {
+ case OMPD_target:
+ CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
+ cast<OMPTargetDirective>(E));
break;
- case Stmt::OMPTargetParallelDirectiveClass:
+ case OMPD_target_parallel:
CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
- CGM, ParentName, cast<OMPTargetParallelDirective>(*S));
+ CGM, ParentName, cast<OMPTargetParallelDirective>(E));
break;
- case Stmt::OMPTargetTeamsDirectiveClass:
+ case OMPD_target_teams:
CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
- CGM, ParentName, cast<OMPTargetTeamsDirective>(*S));
+ CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
break;
- case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ case OMPD_target_teams_distribute:
CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
- CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(*S));
+ CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
break;
- case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ case OMPD_target_teams_distribute_simd:
CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
- CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(*S));
+ CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
break;
- case Stmt::OMPTargetParallelForDirectiveClass:
+ case OMPD_target_parallel_for:
CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
- CGM, ParentName, cast<OMPTargetParallelForDirective>(*S));
+ CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
break;
- case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ case OMPD_target_parallel_for_simd:
CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
- CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(*S));
+ CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
break;
- case Stmt::OMPTargetSimdDirectiveClass:
+ case OMPD_target_simd:
CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
- CGM, ParentName, cast<OMPTargetSimdDirective>(*S));
+ CGM, ParentName, cast<OMPTargetSimdDirective>(E));
break;
- default:
+ case OMPD_target_teams_distribute_parallel_for:
+ CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
+ CGM, ParentName,
+ cast<OMPTargetTeamsDistributeParallelForDirective>(E));
+ break;
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ CodeGenFunction::
+ EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
+ CGM, ParentName,
+ cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
+ break;
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_unknown:
llvm_unreachable("Unknown target directive for OpenMP device codegen.");
}
return;
}
- if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
- if (!E->hasAssociatedStmt())
+ if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
+ if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
return;
scanForTargetRegionsFunctions(
- cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
- ParentName);
+ E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
return;
}
// If this is a lambda function, look into its body.
- if (auto *L = dyn_cast<LambdaExpr>(S))
+ if (const auto *L = dyn_cast<LambdaExpr>(S))
S = L->getBody();
// Keep looking for target regions recursively.
- for (auto *II : S->children())
+ for (const Stmt *II : S->children())
scanForTargetRegionsFunctions(II, ParentName);
}
bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
- auto &FD = *cast<FunctionDecl>(GD.getDecl());
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
// If emitting code for the host, we do not process FD here. Instead we do
// the normal code generation.
@@ -7326,12 +8044,11 @@ bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
return false;
// Try to detect target regions in the function.
- scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
+ scanForTargetRegionsFunctions(FD->getBody(), CGM.getMangledName(GD));
- // We should not emit any function other that the ones created during the
- // scanning. Therefore, we signal that this function is completely dealt
- // with.
- return true;
+ // Do not to emit function if it is not marked as declare target.
+ return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD) &&
+ AlreadyEmittedTargetFunctions.count(FD->getCanonicalDecl()) == 0;
}
bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
@@ -7342,33 +8059,115 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
// regions in it. We use the complete variant to produce the kernel name
// mangling.
QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
- if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
- for (auto *Ctor : RD->ctors()) {
+ if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
+ for (const CXXConstructorDecl *Ctor : RD->ctors()) {
StringRef ParentName =
CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
}
- auto *Dtor = RD->getDestructor();
- if (Dtor) {
+ if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
StringRef ParentName =
CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
}
}
- // If we are in target mode, we do not emit any global (declare target is not
- // implemented yet). Therefore we signal that GD was processed in this case.
- return true;
+ // Do not to emit variable if it is not marked as declare target.
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
+ cast<VarDecl>(GD.getDecl()));
+ return !Res || *Res == OMPDeclareTargetDeclAttr::MT_Link;
+}
+
+void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
+ llvm::Constant *Addr) {
+ if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
+ OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
+ StringRef VarName;
+ CharUnits VarSize;
+ llvm::GlobalValue::LinkageTypes Linkage;
+ switch (*Res) {
+ case OMPDeclareTargetDeclAttr::MT_To:
+ Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
+ VarName = CGM.getMangledName(VD);
+ VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
+ Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
+ // Temp solution to prevent optimizations of the internal variables.
+ if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
+ std::string RefName = getName({VarName, "ref"});
+ if (!CGM.GetGlobalValue(RefName)) {
+ llvm::Constant *AddrRef =
+ getOrCreateInternalVariable(Addr->getType(), RefName);
+ auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
+ GVAddrRef->setConstant(/*Val=*/true);
+ GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
+ GVAddrRef->setInitializer(Addr);
+ CGM.addCompilerUsedGlobal(GVAddrRef);
+ }
+ }
+ break;
+ case OMPDeclareTargetDeclAttr::MT_Link:
+ Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ VarName = Addr->getName();
+ Addr = nullptr;
+ } else {
+ VarName = getAddrOfDeclareTargetLink(VD).getName();
+ Addr =
+ cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer());
+ }
+ VarSize = CGM.getPointerSize();
+ Linkage = llvm::GlobalValue::WeakAnyLinkage;
+ break;
+ }
+ OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
+ VarName, Addr, VarSize, Flags, Linkage);
+ }
}
bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
- auto *VD = GD.getDecl();
- if (isa<FunctionDecl>(VD))
+ if (isa<FunctionDecl>(GD.getDecl()))
return emitTargetFunctions(GD);
return emitTargetGlobalVariable(GD);
}
+CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
+ CodeGenModule &CGM)
+ : CGM(CGM) {
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
+ CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
+ }
+}
+
+CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
+ if (CGM.getLangOpts().OpenMPIsDevice)
+ CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
+}
+
+bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
+ if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
+ return true;
+
+ const auto *D = cast<FunctionDecl>(GD.getDecl());
+ const FunctionDecl *FD = D->getCanonicalDecl();
+ // Do not to emit function if it is marked as declare target as it was already
+ // emitted.
+ if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
+ if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) {
+ if (auto *F = dyn_cast_or_null<llvm::Function>(
+ CGM.GetGlobalValue(CGM.getMangledName(GD))))
+ return !F->isDeclaration();
+ return false;
+ }
+ return true;
+ }
+
+ return !AlreadyEmittedTargetFunctions.insert(FD).second;
+}
+
llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
// If we have offloading in the current module, we need to emit the entries
// now and register the offloading descriptor.
@@ -7388,7 +8187,7 @@ void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
if (!CGF.HaveInsertPoint())
return;
- auto *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
CodeGenFunction::RunCleanupsScope Scope(CGF);
// Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
@@ -7400,7 +8199,7 @@ void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
RealArgs.append(std::begin(Args), std::end(Args));
RealArgs.append(CapturedVars.begin(), CapturedVars.end());
- auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
+ llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
CGF.EmitRuntimeCall(RTLFn, RealArgs);
}
@@ -7411,16 +8210,16 @@ void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
if (!CGF.HaveInsertPoint())
return;
- auto *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
llvm::Value *NumTeamsVal =
- (NumTeams)
+ NumTeams
? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
CGF.CGM.Int32Ty, /* isSigned = */ true)
: CGF.Builder.getInt32(0);
llvm::Value *ThreadLimitVal =
- (ThreadLimit)
+ ThreadLimit
? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
CGF.CGM.Int32Ty, /* isSigned = */ true)
: CGF.Builder.getInt32(0);
@@ -7477,7 +8276,7 @@ void CGOpenMPRuntime::emitTargetDataCalls(
}
// Emit the number of elements in the offloading arrays.
- auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
+ llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
llvm::Value *OffloadingArgs[] = {
DeviceID, PointerNum, BasePointersArrayArg,
@@ -7513,7 +8312,7 @@ void CGOpenMPRuntime::emitTargetDataCalls(
}
// Emit the number of elements in the offloading arrays.
- auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
+ llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
llvm::Value *OffloadingArgs[] = {
DeviceID, PointerNum, BasePointersArrayArg,
@@ -7600,9 +8399,6 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
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 = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
: OMPRTL__tgt_target_data_begin;
@@ -7615,6 +8411,58 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
: OMPRTL__tgt_target_data_update;
break;
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_target:
+ case OMPD_target_simd:
+ 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_target_teams:
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_unknown:
+ llvm_unreachable("Unexpected standalone target data directive.");
+ break;
}
CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
};
@@ -7648,13 +8496,13 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
if (D.hasClausesOfKind<OMPDependClause>())
CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
else
- emitInlinedDirective(CGF, OMPD_target_update, ThenGen);
+ emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
};
- if (IfCond)
+ if (IfCond) {
emitOMPIfClause(CGF, IfCond, TargetThenGen,
[](CodeGenFunction &CGF, PrePostActionTy &) {});
- else {
+ } else {
RegionCodeGenTy ThenRCG(TargetThenGen);
ThenRCG(CGF);
}
@@ -7697,11 +8545,11 @@ static unsigned evaluateCDTSize(const FunctionDecl *FD,
return 0;
ASTContext &C = FD->getASTContext();
QualType CDT;
- if (!RetType.isNull() && !RetType->isVoidType())
+ if (!RetType.isNull() && !RetType->isVoidType()) {
CDT = RetType;
- else {
+ } else {
unsigned Offset = 0;
- if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (ParamAttrs[Offset].Kind == Vector)
CDT = C.getPointerType(C.getRecordType(MD->getParent()));
++Offset;
@@ -7759,17 +8607,18 @@ emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Masked.push_back('M');
break;
}
- for (auto Mask : Masked) {
- for (auto &Data : ISAData) {
+ for (char Mask : Masked) {
+ for (const ISADataTy &Data : ISAData) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
Out << "_ZGV" << Data.ISA << Mask;
if (!VLENVal) {
Out << llvm::APSInt::getUnsigned(Data.VecRegSize /
evaluateCDTSize(FD, ParamAttrs));
- } else
+ } else {
Out << VLENVal;
- for (auto &ParamAttr : ParamAttrs) {
+ }
+ for (const ParamAttrTy &ParamAttr : ParamAttrs) {
switch (ParamAttr.Kind){
case LinearWithVarStride:
Out << 's' << ParamAttr.StrideOrArg;
@@ -7798,90 +8647,95 @@ emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
llvm::Function *Fn) {
ASTContext &C = CGM.getContext();
- FD = FD->getCanonicalDecl();
+ FD = FD->getMostRecentDecl();
// Map params to their positions in function decl.
llvm::DenseMap<const Decl *, unsigned> ParamPositions;
if (isa<CXXMethodDecl>(FD))
- ParamPositions.insert({FD, 0});
+ ParamPositions.try_emplace(FD, 0);
unsigned ParamPos = ParamPositions.size();
- for (auto *P : FD->parameters()) {
- ParamPositions.insert({P->getCanonicalDecl(), ParamPos});
+ for (const ParmVarDecl *P : FD->parameters()) {
+ ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
++ParamPos;
}
- for (auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
- llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
- // Mark uniform parameters.
- for (auto *E : Attr->uniforms()) {
- E = E->IgnoreParenImpCasts();
- unsigned Pos;
- if (isa<CXXThisExpr>(E))
- Pos = ParamPositions[FD];
- else {
- auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
- ->getCanonicalDecl();
- Pos = ParamPositions[PVD];
- }
- ParamAttrs[Pos].Kind = Uniform;
- }
- // Get alignment info.
- auto NI = Attr->alignments_begin();
- for (auto *E : Attr->aligneds()) {
- E = E->IgnoreParenImpCasts();
- unsigned Pos;
- QualType ParmTy;
- if (isa<CXXThisExpr>(E)) {
- Pos = ParamPositions[FD];
- ParmTy = E->getType();
- } else {
- auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
- ->getCanonicalDecl();
- Pos = ParamPositions[PVD];
- ParmTy = PVD->getType();
+ while (FD) {
+ for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
+ llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
+ // Mark uniform parameters.
+ for (const Expr *E : Attr->uniforms()) {
+ E = E->IgnoreParenImpCasts();
+ unsigned Pos;
+ if (isa<CXXThisExpr>(E)) {
+ Pos = ParamPositions[FD];
+ } else {
+ const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
+ ->getCanonicalDecl();
+ Pos = ParamPositions[PVD];
+ }
+ ParamAttrs[Pos].Kind = Uniform;
}
- ParamAttrs[Pos].Alignment =
- (*NI) ? (*NI)->EvaluateKnownConstInt(C)
+ // Get alignment info.
+ auto NI = Attr->alignments_begin();
+ for (const Expr *E : Attr->aligneds()) {
+ E = E->IgnoreParenImpCasts();
+ unsigned Pos;
+ QualType ParmTy;
+ if (isa<CXXThisExpr>(E)) {
+ Pos = ParamPositions[FD];
+ ParmTy = E->getType();
+ } else {
+ const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
+ ->getCanonicalDecl();
+ Pos = ParamPositions[PVD];
+ ParmTy = PVD->getType();
+ }
+ ParamAttrs[Pos].Alignment =
+ (*NI)
+ ? (*NI)->EvaluateKnownConstInt(C)
: llvm::APSInt::getUnsigned(
C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
.getQuantity());
- ++NI;
- }
- // Mark linear parameters.
- auto SI = Attr->steps_begin();
- auto MI = Attr->modifiers_begin();
- for (auto *E : Attr->linears()) {
- E = E->IgnoreParenImpCasts();
- unsigned Pos;
- if (isa<CXXThisExpr>(E))
- Pos = ParamPositions[FD];
- else {
- auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
- ->getCanonicalDecl();
- Pos = ParamPositions[PVD];
+ ++NI;
}
- auto &ParamAttr = ParamAttrs[Pos];
- ParamAttr.Kind = Linear;
- if (*SI) {
- if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C,
- Expr::SE_AllowSideEffects)) {
- if (auto *DRE = cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
- if (auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
- ParamAttr.Kind = LinearWithVarStride;
- ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
- ParamPositions[StridePVD->getCanonicalDecl()]);
+ // Mark linear parameters.
+ auto SI = Attr->steps_begin();
+ auto MI = Attr->modifiers_begin();
+ for (const Expr *E : Attr->linears()) {
+ E = E->IgnoreParenImpCasts();
+ unsigned Pos;
+ if (isa<CXXThisExpr>(E)) {
+ Pos = ParamPositions[FD];
+ } else {
+ const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
+ ->getCanonicalDecl();
+ Pos = ParamPositions[PVD];
+ }
+ ParamAttrTy &ParamAttr = ParamAttrs[Pos];
+ ParamAttr.Kind = Linear;
+ if (*SI) {
+ if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C,
+ Expr::SE_AllowSideEffects)) {
+ if (const auto *DRE =
+ cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
+ if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
+ ParamAttr.Kind = LinearWithVarStride;
+ ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
+ ParamPositions[StridePVD->getCanonicalDecl()]);
+ }
}
}
}
+ ++SI;
+ ++MI;
}
- ++SI;
- ++MI;
+ llvm::APSInt VLENVal;
+ if (const Expr *VLEN = Attr->getSimdlen())
+ VLENVal = VLEN->EvaluateKnownConstInt(C);
+ OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
+ if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
+ CGM.getTriple().getArch() == llvm::Triple::x86_64)
+ emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
}
- llvm::APSInt VLENVal;
- if (const Expr *VLEN = Attr->getSimdlen())
- VLENVal = VLEN->EvaluateKnownConstInt(C);
- OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
- if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
- CGM.getTriple().getArch() == llvm::Triple::x86_64)
- emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
+ FD = FD->getPreviousDecl();
}
}
@@ -7910,7 +8764,8 @@ public:
} // namespace
void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) {
+ const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) {
if (!CGF.HaveInsertPoint())
return;
@@ -7930,34 +8785,48 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
addFieldToRecordDecl(C, RD, Int64Ty);
RD->completeDefinition();
KmpDimTy = C.getRecordType(RD);
- } else
+ } else {
RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
+ }
+ llvm::APInt Size(/*numBits=*/32, NumIterations.size());
+ QualType ArrayTy =
+ C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
- Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims");
- CGF.EmitNullInitialization(DimsAddr, KmpDimTy);
+ Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
+ CGF.EmitNullInitialization(DimsAddr, ArrayTy);
enum { LowerFD = 0, UpperFD, StrideFD };
// Fill dims with data.
- LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy);
- // dims.upper = num_iterations;
- LValue UpperLVal =
- CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD));
- llvm::Value *NumIterVal = CGF.EmitScalarConversion(
- CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(),
- Int64Ty, D.getNumIterations()->getExprLoc());
- CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
- // dims.stride = 1;
- LValue StrideLVal =
- CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD));
- CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
- StrideLVal);
+ for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
+ LValue DimsLVal =
+ CGF.MakeAddrLValue(CGF.Builder.CreateConstArrayGEP(
+ DimsAddr, I, C.getTypeSizeInChars(KmpDimTy)),
+ KmpDimTy);
+ // dims.upper = num_iterations;
+ LValue UpperLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), UpperFD));
+ llvm::Value *NumIterVal =
+ CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
+ D.getNumIterations()->getType(), Int64Ty,
+ D.getNumIterations()->getExprLoc());
+ CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
+ // dims.stride = 1;
+ LValue StrideLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), StrideFD));
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
+ StrideLVal);
+ }
// Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
// kmp_int32 num_dims, struct kmp_dim * dims);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()),
- getThreadID(CGF, D.getLocStart()),
- llvm::ConstantInt::getSigned(CGM.Int32Ty, 1),
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- DimsAddr.getPointer(), CGM.VoidPtrTy)};
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, D.getLocStart()),
+ getThreadID(CGF, D.getLocStart()),
+ llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder
+ .CreateConstArrayGEP(DimsAddr, 0, C.getTypeSizeInChars(KmpDimTy))
+ .getPointer(),
+ CGM.VoidPtrTy)};
llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init);
CGF.EmitRuntimeCall(RTLFn, Args);
@@ -7972,29 +8841,43 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
const OMPDependClause *C) {
QualType Int64Ty =
CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
- const Expr *CounterVal = C->getCounterValue();
- assert(CounterVal);
- llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal),
- CounterVal->getType(), Int64Ty,
- CounterVal->getExprLoc());
- Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr");
- CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()),
- getThreadID(CGF, C->getLocStart()),
- CntAddr.getPointer()};
+ llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
+ QualType ArrayTy = CGM.getContext().getConstantArrayType(
+ Int64Ty, Size, ArrayType::Normal, 0);
+ Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
+ const Expr *CounterVal = C->getLoopData(I);
+ assert(CounterVal);
+ llvm::Value *CntVal = CGF.EmitScalarConversion(
+ CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
+ CounterVal->getExprLoc());
+ CGF.EmitStoreOfScalar(
+ CntVal,
+ CGF.Builder.CreateConstArrayGEP(
+ CntAddr, I, CGM.getContext().getTypeSizeInChars(Int64Ty)),
+ /*Volatile=*/false, Int64Ty);
+ }
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, C->getLocStart()),
+ getThreadID(CGF, C->getLocStart()),
+ CGF.Builder
+ .CreateConstArrayGEP(CntAddr, 0,
+ CGM.getContext().getTypeSizeInChars(Int64Ty))
+ .getPointer()};
llvm::Value *RTLFn;
- if (C->getDependencyKind() == OMPC_DEPEND_source)
+ if (C->getDependencyKind() == OMPC_DEPEND_source) {
RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
- else {
+ } else {
assert(C->getDependencyKind() == OMPC_DEPEND_sink);
RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
}
CGF.EmitRuntimeCall(RTLFn, Args);
}
-void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, llvm::Value *Callee,
- ArrayRef<llvm::Value *> Args,
- SourceLocation Loc) const {
+void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *Callee,
+ ArrayRef<llvm::Value *> Args) const {
+ assert(Loc.isValid() && "Outlined function call location must be valid.");
auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
if (auto *Fn = dyn_cast<llvm::Function>(Callee)) {
@@ -8009,8 +8892,7 @@ void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, llvm::Value *Callee,
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);
+ emitCall(CGF, Loc, OutlinedFn, Args);
}
Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
@@ -8019,6 +8901,11 @@ Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
return CGF.GetAddrOfLocalVar(NativeParam);
}
+Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD) {
+ return Address::invalid();
+}
+
llvm::Value *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
@@ -8243,8 +9130,7 @@ void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
llvm::Value *OutlinedFn,
llvm::Value *OutlinedFnID,
- const Expr *IfCond, const Expr *Device,
- ArrayRef<llvm::Value *> CapturedVars) {
+ const Expr *IfCond, const Expr *Device) {
llvm_unreachable("Not supported in SIMD-only mode");
}
@@ -8292,7 +9178,8 @@ void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
}
void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) {
+ const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) {
llvm_unreachable("Not supported in SIMD-only mode");
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
index 98e09e09b5ec..94731b64ebdb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -133,7 +133,7 @@ private:
/// Base declarations for the reduction items.
SmallVector<const VarDecl *, 4> BaseDecls;
- /// Emits lvalue for shared expresion.
+ /// Emits lvalue for shared expression.
LValue emitSharedLValue(CodeGenFunction &CGF, const Expr *E);
/// Emits upper bound for shared expression (if array section).
LValue emitSharedLValueUB(CodeGenFunction &CGF, const Expr *E);
@@ -191,21 +191,41 @@ public:
}
/// Returns the base declaration of the reduction item.
const VarDecl *getBaseDecl(unsigned N) const { return BaseDecls[N]; }
+ /// Returns the base declaration of the reduction item.
+ const Expr *getRefExpr(unsigned N) const { return ClausesData[N].Ref; }
/// Returns true if the initialization of the reduction item uses initializer
/// from declare reduction construct.
bool usesReductionInitializer(unsigned N) const;
};
class CGOpenMPRuntime {
+public:
+ /// Allows to disable automatic handling of functions used in target regions
+ /// as those marked as `omp declare target`.
+ class DisableAutoDeclareTargetRAII {
+ CodeGenModule &CGM;
+ bool SavedShouldMarkAsGlobal;
+
+ public:
+ DisableAutoDeclareTargetRAII(CodeGenModule &CGM);
+ ~DisableAutoDeclareTargetRAII();
+ };
+
protected:
CodeGenModule &CGM;
+ StringRef FirstSeparator, Separator;
- /// \brief Creates offloading entry for the provided entry ID \a ID,
+ /// Constructor allowing to redefine the name separator for the variables.
+ explicit CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
+ StringRef Separator);
+
+ /// Creates offloading entry for the provided entry ID \a ID,
/// address \a Addr, size \a Size, and flags \a Flags.
virtual void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr,
- uint64_t Size, int32_t Flags = 0);
+ uint64_t Size, int32_t Flags,
+ llvm::GlobalValue::LinkageTypes Linkage);
- /// \brief Helper to emit outlined function for 'target' directive.
+ /// Helper to emit outlined function for 'target' directive.
/// \param D Directive to emit.
/// \param ParentName Name of the function that encloses the target region.
/// \param OutlinedFn Outlined function value to be defined by this call.
@@ -221,7 +241,7 @@ protected:
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen);
- /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
+ /// Emits code for OpenMP 'if' clause using specified \a CodeGen
/// function. Here is the logic:
/// if (Cond) {
/// ThenGen();
@@ -232,52 +252,56 @@ protected:
const RegionCodeGenTy &ThenGen,
const RegionCodeGenTy &ElseGen);
- /// \brief Emits object of ident_t type with info for source location.
+ /// Emits object of ident_t type with info for source location.
/// \param Flags Flags for OpenMP location.
///
llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
unsigned Flags = 0);
- /// \brief Returns pointer to ident_t type.
+ /// Returns pointer to ident_t type.
llvm::Type *getIdentTyPointerTy();
- /// \brief Gets thread id value for the current thread.
+ /// Gets thread id value for the current thread.
///
llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc);
- /// \brief Get the function name of an outlined region.
+ /// Get the function name of an outlined region.
// The name can be customized depending on the target.
//
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;
+ void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Callee,
+ ArrayRef<llvm::Value *> Args = llvm::None) const;
+
+ /// Emits address of the word in a memory where current thread id is
+ /// stored.
+ virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
private:
- /// \brief Default const ident_t object used for initialization of all other
+ /// Default const ident_t object used for initialization of all other
/// ident_t objects.
llvm::Constant *DefaultOpenMPPSource = nullptr;
- /// \brief Map of flags and corresponding default locations.
+ /// Map of flags and corresponding default locations.
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
Address getOrCreateDefaultLocation(unsigned Flags);
+ QualType IdentQTy;
llvm::StructType *IdentTy = nullptr;
- /// \brief Map for SourceLocation and OpenMP runtime library debug locations.
+ /// Map for SourceLocation and OpenMP runtime library debug locations.
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy;
OpenMPDebugLocMapTy OpenMPDebugLocMap;
- /// \brief The type for a microtask which gets passed to __kmpc_fork_call().
+ /// The type for a microtask which gets passed to __kmpc_fork_call().
/// Original representation is:
/// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...);
llvm::FunctionType *Kmpc_MicroTy = nullptr;
- /// \brief Stores debug location and ThreadID for the function.
+ /// Stores debug location and ThreadID for the function.
struct DebugLocThreadIdTy {
llvm::Value *DebugLoc;
llvm::Value *ThreadID;
};
- /// \brief Map of local debug location, ThreadId and functions.
+ /// Map of local debug location, ThreadId and functions.
typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy>
OpenMPLocThreadIDMapTy;
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap;
@@ -295,20 +319,20 @@ private:
IdentifierInfo *Out = nullptr;
IdentifierInfo *Priv = nullptr;
IdentifierInfo *Orig = nullptr;
- /// \brief Type kmp_critical_name, originally defined as typedef kmp_int32
+ /// Type kmp_critical_name, originally defined as typedef kmp_int32
/// kmp_critical_name[8];
llvm::ArrayType *KmpCriticalNameTy;
- /// \brief An ordered map of auto-generated variables to their unique names.
+ /// An ordered map of auto-generated variables to their unique names.
/// It stores variables with the following names: 1) ".gomp_critical_user_" +
/// <critical_section_name> + ".var" for "omp critical" directives; 2)
/// <mangled_name_for_global_var> + ".cache." for cache for threadprivate
/// variables.
llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator>
InternalVars;
- /// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
+ /// Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
llvm::Type *KmpRoutineEntryPtrTy = nullptr;
QualType KmpRoutineEntryPtrQTy;
- /// \brief Type typedef struct kmp_task {
+ /// Type typedef struct kmp_task {
/// void * shareds; /**< pointer to block of pointers to
/// shared vars */
/// kmp_routine_entry_t routine; /**< pointer to routine to call for
@@ -322,7 +346,7 @@ private:
QualType SavedKmpTaskTQTy;
/// Saved kmp_task_t for taskloop-based directive.
QualType SavedKmpTaskloopTQTy;
- /// \brief Type typedef struct kmp_depend_info {
+ /// Type typedef struct kmp_depend_info {
/// kmp_intptr_t base_addr;
/// size_t len;
/// struct {
@@ -337,7 +361,7 @@ private:
/// kmp_int64 st; // stride
/// };
QualType KmpDimTy;
- /// \brief Type struct __tgt_offload_entry{
+ /// Type struct __tgt_offload_entry{
/// void *addr; // Pointer to the offload entry info.
/// // (function or global)
/// char *name; // Name of the function or global.
@@ -365,112 +389,195 @@ private:
/// // entries (non inclusive).
/// };
QualType TgtBinaryDescriptorQTy;
- /// \brief Entity that registers the offloading constants that were emitted so
+ /// Entity that registers the offloading constants that were emitted so
/// far.
class OffloadEntriesInfoManagerTy {
CodeGenModule &CGM;
- /// \brief Number of entries registered so far.
- unsigned OffloadingEntriesNum;
+ /// Number of entries registered so far.
+ unsigned OffloadingEntriesNum = 0;
public:
/// Base class of the entries info.
class OffloadEntryInfo {
public:
- /// Kind of a given entry. Currently, only target regions are
- /// supported.
+ /// Kind of a given entry.
enum OffloadingEntryInfoKinds : unsigned {
- // Entry is a target region.
- OFFLOAD_ENTRY_INFO_TARGET_REGION = 0,
- // Invalid entry info.
- OFFLOAD_ENTRY_INFO_INVALID = ~0u
+ /// Entry is a target region.
+ OffloadingEntryInfoTargetRegion = 0,
+ /// Entry is a declare target variable.
+ OffloadingEntryInfoDeviceGlobalVar = 1,
+ /// Invalid entry info.
+ OffloadingEntryInfoInvalid = ~0u
};
- OffloadEntryInfo()
- : Flags(0), Order(~0u), Kind(OFFLOAD_ENTRY_INFO_INVALID) {}
+ protected:
+ OffloadEntryInfo() = delete;
+ explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind) : Kind(Kind) {}
explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order,
- int32_t Flags)
+ uint32_t Flags)
: Flags(Flags), Order(Order), Kind(Kind) {}
+ ~OffloadEntryInfo() = default;
+ public:
bool isValid() const { return Order != ~0u; }
unsigned getOrder() const { return Order; }
OffloadingEntryInfoKinds getKind() const { return Kind; }
- int32_t getFlags() const { return Flags; }
- void setFlags(int32_t NewFlags) { Flags = NewFlags; }
+ uint32_t getFlags() const { return Flags; }
+ void setFlags(uint32_t NewFlags) { Flags = NewFlags; }
+ llvm::Constant *getAddress() const {
+ return cast_or_null<llvm::Constant>(Addr);
+ }
+ void setAddress(llvm::Constant *V) {
+ assert(!Addr.pointsToAliveValue() && "Address has been set before!");
+ Addr = V;
+ }
static bool classof(const OffloadEntryInfo *Info) { return true; }
private:
+ /// Address of the entity that has to be mapped for offloading.
+ llvm::WeakTrackingVH Addr;
+
/// Flags associated with the device global.
- int32_t Flags;
+ uint32_t Flags = 0u;
/// Order this entry was emitted.
- unsigned Order;
+ unsigned Order = ~0u;
- OffloadingEntryInfoKinds Kind;
+ OffloadingEntryInfoKinds Kind = OffloadingEntryInfoInvalid;
};
- /// \brief Return true if a there are no entries defined.
+ /// Return true if a there are no entries defined.
bool empty() const;
- /// \brief Return number of entries defined so far.
+ /// Return number of entries defined so far.
unsigned size() const { return OffloadingEntriesNum; }
- OffloadEntriesInfoManagerTy(CodeGenModule &CGM)
- : CGM(CGM), OffloadingEntriesNum(0) {}
-
- ///
- /// Target region entries related.
- ///
- /// \brief Target region entries info.
- class OffloadEntryInfoTargetRegion : public OffloadEntryInfo {
- // \brief Address of the entity that has to be mapped for offloading.
- llvm::Constant *Addr;
- // \brief Address that can be used as the ID of the entry.
- llvm::Constant *ID;
+ OffloadEntriesInfoManagerTy(CodeGenModule &CGM) : CGM(CGM) {}
+
+ //
+ // Target region entries related.
+ //
+
+ /// Kind of the target registry entry.
+ enum OMPTargetRegionEntryKind : uint32_t {
+ /// Mark the entry as target region.
+ OMPTargetRegionEntryTargetRegion = 0x0,
+ /// Mark the entry as a global constructor.
+ OMPTargetRegionEntryCtor = 0x02,
+ /// Mark the entry as a global destructor.
+ OMPTargetRegionEntryDtor = 0x04,
+ };
+
+ /// Target region entries info.
+ class OffloadEntryInfoTargetRegion final : public OffloadEntryInfo {
+ /// Address that can be used as the ID of the entry.
+ llvm::Constant *ID = nullptr;
public:
OffloadEntryInfoTargetRegion()
- : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, ~0u,
- /*Flags=*/0),
- Addr(nullptr), ID(nullptr) {}
+ : OffloadEntryInfo(OffloadingEntryInfoTargetRegion) {}
explicit OffloadEntryInfoTargetRegion(unsigned Order,
llvm::Constant *Addr,
- llvm::Constant *ID, int32_t Flags)
- : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, Order, Flags),
- Addr(Addr), ID(ID) {}
+ llvm::Constant *ID,
+ OMPTargetRegionEntryKind Flags)
+ : OffloadEntryInfo(OffloadingEntryInfoTargetRegion, Order, Flags),
+ ID(ID) {
+ setAddress(Addr);
+ }
- llvm::Constant *getAddress() const { return Addr; }
llvm::Constant *getID() const { return ID; }
- void setAddress(llvm::Constant *V) {
- assert(!Addr && "Address as been set before!");
- Addr = V;
- }
void setID(llvm::Constant *V) {
- assert(!ID && "ID as been set before!");
+ assert(!ID && "ID has been set before!");
ID = V;
}
static bool classof(const OffloadEntryInfo *Info) {
- return Info->getKind() == OFFLOAD_ENTRY_INFO_TARGET_REGION;
+ return Info->getKind() == OffloadingEntryInfoTargetRegion;
}
};
- /// \brief Initialize target region entry.
+
+ /// Initialize target region entry.
void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
unsigned Order);
- /// \brief Register target region entry.
+ /// Register target region entry.
void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
llvm::Constant *Addr, llvm::Constant *ID,
- int32_t Flags);
- /// \brief Return true if a target region entry with the provided
- /// information exists.
+ OMPTargetRegionEntryKind Flags);
+ /// Return true if a target region entry with the provided information
+ /// exists.
bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum) const;
/// brief Applies action \a Action on all registered entries.
typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned,
- OffloadEntryInfoTargetRegion &)>
+ const OffloadEntryInfoTargetRegion &)>
OffloadTargetRegionEntryInfoActTy;
void actOnTargetRegionEntriesInfo(
const OffloadTargetRegionEntryInfoActTy &Action);
+ //
+ // Device global variable entries related.
+ //
+
+ /// Kind of the global variable entry..
+ enum OMPTargetGlobalVarEntryKind : uint32_t {
+ /// Mark the entry as a to declare target.
+ OMPTargetGlobalVarEntryTo = 0x0,
+ /// Mark the entry as a to declare target link.
+ OMPTargetGlobalVarEntryLink = 0x1,
+ };
+
+ /// Device global variable entries info.
+ class OffloadEntryInfoDeviceGlobalVar final : public OffloadEntryInfo {
+ /// Type of the global variable.
+ CharUnits VarSize;
+ llvm::GlobalValue::LinkageTypes Linkage;
+
+ public:
+ OffloadEntryInfoDeviceGlobalVar()
+ : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar) {}
+ explicit OffloadEntryInfoDeviceGlobalVar(unsigned Order,
+ OMPTargetGlobalVarEntryKind Flags)
+ : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags) {}
+ explicit OffloadEntryInfoDeviceGlobalVar(
+ unsigned Order, llvm::Constant *Addr, CharUnits VarSize,
+ OMPTargetGlobalVarEntryKind Flags,
+ llvm::GlobalValue::LinkageTypes Linkage)
+ : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags),
+ VarSize(VarSize), Linkage(Linkage) {
+ setAddress(Addr);
+ }
+
+ CharUnits getVarSize() const { return VarSize; }
+ void setVarSize(CharUnits Size) { VarSize = Size; }
+ llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
+ void setLinkage(llvm::GlobalValue::LinkageTypes LT) { Linkage = LT; }
+ static bool classof(const OffloadEntryInfo *Info) {
+ return Info->getKind() == OffloadingEntryInfoDeviceGlobalVar;
+ }
+ };
+
+ /// Initialize device global variable entry.
+ void initializeDeviceGlobalVarEntryInfo(StringRef Name,
+ OMPTargetGlobalVarEntryKind Flags,
+ unsigned Order);
+
+ /// Register device global variable entry.
+ void
+ registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
+ CharUnits VarSize,
+ OMPTargetGlobalVarEntryKind Flags,
+ llvm::GlobalValue::LinkageTypes Linkage);
+ /// Checks if the variable with the given name has been registered already.
+ bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const {
+ return OffloadEntriesDeviceGlobalVar.count(VarName) > 0;
+ }
+ /// Applies action \a Action on all registered entries.
+ typedef llvm::function_ref<void(StringRef,
+ const OffloadEntryInfoDeviceGlobalVar &)>
+ OffloadDeviceGlobalVarEntryInfoActTy;
+ void actOnDeviceGlobalVarEntriesInfo(
+ const OffloadDeviceGlobalVarEntryInfoActTy &Action);
+
private:
// Storage for target region entries kind. The storage is to be indexed by
// file ID, device ID, parent function name and line number.
@@ -484,75 +591,79 @@ private:
OffloadEntriesTargetRegionPerDevice;
typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy;
OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion;
+ /// Storage for device global variable entries kind. The storage is to be
+ /// indexed by mangled name.
+ typedef llvm::StringMap<OffloadEntryInfoDeviceGlobalVar>
+ OffloadEntriesDeviceGlobalVarTy;
+ OffloadEntriesDeviceGlobalVarTy OffloadEntriesDeviceGlobalVar;
};
OffloadEntriesInfoManagerTy OffloadEntriesInfoManager;
- /// \brief Creates and registers offloading binary descriptor for the current
+ bool ShouldMarkAsGlobal = true;
+ llvm::SmallDenseSet<const FunctionDecl *> AlreadyEmittedTargetFunctions;
+
+ /// Creates and registers offloading binary descriptor for the current
/// compilation unit. The function that does the registration is returned.
llvm::Function *createOffloadingBinaryDescriptorRegistration();
- /// \brief Creates all the offload entries in the current compilation unit
+ /// Creates all the offload entries in the current compilation unit
/// along with the associated metadata.
void createOffloadEntriesAndInfoMetadata();
- /// \brief Loads all the offload entries information from the host IR
+ /// Loads all the offload entries information from the host IR
/// metadata.
void loadOffloadInfoMetadata();
- /// \brief Returns __tgt_offload_entry type.
+ /// Returns __tgt_offload_entry type.
QualType getTgtOffloadEntryQTy();
- /// \brief Returns __tgt_device_image type.
+ /// Returns __tgt_device_image type.
QualType getTgtDeviceImageQTy();
- /// \brief Returns __tgt_bin_desc type.
+ /// Returns __tgt_bin_desc type.
QualType getTgtBinaryDescriptorQTy();
- /// \brief Start scanning from statement \a S and and emit all target regions
+ /// Start scanning from statement \a S and and emit all target regions
/// found along the way.
/// \param S Starting statement.
/// \param ParentName Name of the function declaration that is being scanned.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName);
- /// \brief Build type kmp_routine_entry_t (if not built yet).
+ /// Build type kmp_routine_entry_t (if not built yet).
void emitKmpRoutineEntryT(QualType KmpInt32Ty);
- /// \brief Returns pointer to kmpc_micro type.
+ /// Returns pointer to kmpc_micro type.
llvm::Type *getKmpc_MicroPointerTy();
- /// \brief Returns specified OpenMP runtime function.
+ /// Returns specified OpenMP runtime function.
/// \param Function OpenMP runtime function.
/// \return Specified function.
llvm::Constant *createRuntimeFunction(unsigned Function);
- /// \brief Returns __kmpc_for_static_init_* runtime function for the specified
+ /// Returns __kmpc_for_static_init_* runtime function for the specified
/// size \a IVSize and sign \a IVSigned.
llvm::Constant *createForStaticInitFunction(unsigned IVSize, bool IVSigned);
- /// \brief Returns __kmpc_dispatch_init_* runtime function for the specified
+ /// Returns __kmpc_dispatch_init_* runtime function for the specified
/// size \a IVSize and sign \a IVSigned.
llvm::Constant *createDispatchInitFunction(unsigned IVSize, bool IVSigned);
- /// \brief Returns __kmpc_dispatch_next_* runtime function for the specified
+ /// Returns __kmpc_dispatch_next_* runtime function for the specified
/// size \a IVSize and sign \a IVSigned.
llvm::Constant *createDispatchNextFunction(unsigned IVSize, bool IVSigned);
- /// \brief Returns __kmpc_dispatch_fini_* runtime function for the specified
+ /// Returns __kmpc_dispatch_fini_* runtime function for the specified
/// size \a IVSize and sign \a IVSigned.
llvm::Constant *createDispatchFiniFunction(unsigned IVSize, bool IVSigned);
- /// \brief If the specified mangled name is not in the module, create and
+ /// If the specified mangled name is not in the module, create and
/// return threadprivate cache object. This object is a pointer's worth of
/// storage that's reserved for use by the OpenMP runtime.
/// \param VD Threadprivate variable.
/// \return Cache variable for the specified threadprivate.
llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD);
- /// \brief Emits address of the word in a memory where current thread id is
- /// stored.
- virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
-
- /// \brief Gets (if variable with the given name already exist) or creates
+ /// Gets (if variable with the given name already exist) or creates
/// internal global variable with the specified Name. The created variable has
/// linkage CommonLinkage by default and is initialized by null value.
/// \param Ty Type of the global variable. If it is exist already the type
@@ -561,10 +672,13 @@ private:
llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
const llvm::Twine &Name);
- /// \brief Set of threadprivate variables with the generated initializer.
+ /// Set of threadprivate variables with the generated initializer.
llvm::SmallPtrSet<const VarDecl *, 4> ThreadPrivateWithDefinition;
- /// \brief Emits initialization code for the threadprivate variables.
+ /// Set of declare target variables with the generated initializer.
+ llvm::SmallPtrSet<const VarDecl *, 4> DeclareTargetWithDefinition;
+
+ /// Emits initialization code for the threadprivate variables.
/// \param VDAddr Address of the global variable \a VD.
/// \param Ctor Pointer to a global init function for \a VD.
/// \param CopyCtor Pointer to a global copy function for \a VD.
@@ -574,7 +688,7 @@ private:
llvm::Value *Ctor, llvm::Value *CopyCtor,
llvm::Value *Dtor, SourceLocation Loc);
- /// \brief Returns corresponding lock object for the specified critical region
+ /// Returns corresponding lock object for the specified critical region
/// name. If the lock object does not exist it is created, otherwise the
/// reference to the existing copy is returned.
/// \param CriticalName Name of the critical region.
@@ -586,7 +700,7 @@ private:
llvm::Value *TaskEntry = nullptr;
llvm::Value *NewTaskNewTaskTTy = nullptr;
LValue TDBase;
- RecordDecl *KmpTaskTQTyRD = nullptr;
+ const RecordDecl *KmpTaskTQTyRD = nullptr;
llvm::Value *TaskDupFn = nullptr;
};
/// Emit task region for the task directive. The task region is emitted in
@@ -617,10 +731,14 @@ private:
Address Shareds, const OMPTaskDataTy &Data);
public:
- explicit CGOpenMPRuntime(CodeGenModule &CGM);
+ explicit CGOpenMPRuntime(CodeGenModule &CGM)
+ : CGOpenMPRuntime(CGM, ".", ".") {}
virtual ~CGOpenMPRuntime() {}
virtual void clear();
+ /// Get the platform-specific name separator.
+ std::string getName(ArrayRef<StringRef> Parts) const;
+
/// Emit code for the specified user defined reduction construct.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF,
const OMPDeclareReductionDecl *D);
@@ -628,7 +746,7 @@ public:
virtual std::pair<llvm::Function *, llvm::Function *>
getUserDefinedReduction(const OMPDeclareReductionDecl *D);
- /// \brief Emits outlined function for the specified OpenMP parallel directive
+ /// Emits outlined function for the specified OpenMP parallel directive
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
/// \param D OpenMP directive.
@@ -640,7 +758,7 @@ public:
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
- /// \brief Emits outlined function for the specified OpenMP teams directive
+ /// Emits outlined function for the specified OpenMP teams directive
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
/// \param D OpenMP directive.
@@ -652,7 +770,7 @@ public:
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
- /// \brief Emits outlined function for the OpenMP task directive \a D. This
+ /// Emits outlined function for the OpenMP task directive \a D. This
/// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
/// TaskT).
/// \param D OpenMP directive.
@@ -673,11 +791,11 @@ public:
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
bool Tied, unsigned &NumberOfParts);
- /// \brief Cleans up references to the objects in finished function.
+ /// Cleans up references to the objects in finished function.
///
- void functionFinished(CodeGenFunction &CGF);
+ virtual void functionFinished(CodeGenFunction &CGF);
- /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// Emits code for parallel or serial call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
@@ -692,7 +810,7 @@ public:
ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond);
- /// \brief Emits a critical region.
+ /// Emits a critical region.
/// \param CriticalName Name of the critical region.
/// \param CriticalOpGen Generator for the statement associated with the given
/// critical region.
@@ -702,24 +820,24 @@ public:
SourceLocation Loc,
const Expr *Hint = nullptr);
- /// \brief Emits a master region.
+ /// Emits a master region.
/// \param MasterOpGen Generator for the statement associated with the given
/// master region.
virtual void emitMasterRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc);
- /// \brief Emits code for a taskyield directive.
+ /// Emits code for a taskyield directive.
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc);
- /// \brief Emit a taskgroup region.
+ /// Emit a taskgroup region.
/// \param TaskgroupOpGen Generator for the statement associated with the
/// given taskgroup region.
virtual void emitTaskgroupRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &TaskgroupOpGen,
SourceLocation Loc);
- /// \brief Emits a single region.
+ /// Emits a single region.
/// \param SingleOpGen Generator for the statement associated with the given
/// single region.
virtual void emitSingleRegion(CodeGenFunction &CGF,
@@ -730,14 +848,14 @@ public:
ArrayRef<const Expr *> SrcExprs,
ArrayRef<const Expr *> AssignmentOps);
- /// \brief Emit an ordered region.
+ /// Emit an ordered region.
/// \param OrderedOpGen Generator for the statement associated with the given
/// ordered region.
virtual void emitOrderedRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &OrderedOpGen,
SourceLocation Loc, bool IsThreads);
- /// \brief Emit an implicit/explicit barrier for OpenMP threads.
+ /// Emit an implicit/explicit barrier for OpenMP threads.
/// \param Kind Directive for which this implicit barrier call must be
/// generated. Must be OMPD_barrier for explicit barrier generation.
/// \param EmitChecks true if need to emit checks for cancellation barriers.
@@ -750,7 +868,7 @@ public:
bool EmitChecks = true,
bool ForceSimpleCall = false);
- /// \brief Check if the specified \a ScheduleKind is static non-chunked.
+ /// Check if the specified \a ScheduleKind is static non-chunked.
/// This kind of worksharing directive is emitted without outer loop.
/// \param ScheduleKind Schedule kind specified in the 'schedule' clause.
/// \param Chunked True if chunk is specified in the clause.
@@ -758,7 +876,7 @@ public:
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
bool Chunked) const;
- /// \brief Check if the specified \a ScheduleKind is static non-chunked.
+ /// Check if the specified \a ScheduleKind is static non-chunked.
/// This kind of distribute directive is emitted without outer loop.
/// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause.
/// \param Chunked True if chunk is specified in the clause.
@@ -766,7 +884,7 @@ public:
virtual bool isStaticNonchunked(OpenMPDistScheduleClauseKind ScheduleKind,
bool Chunked) const;
- /// \brief Check if the specified \a ScheduleKind is dynamic.
+ /// Check if the specified \a ScheduleKind is dynamic.
/// This kind of worksharing directive is emitted without outer loop.
/// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
///
@@ -839,7 +957,7 @@ public:
: 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
+ /// Call the appropriate runtime routine to initialize it before start
/// of loop.
///
/// This is used only in case of static schedule, when the user did not
@@ -870,7 +988,7 @@ public:
OpenMPDistScheduleClauseKind SchedKind,
const StaticRTInput &Values);
- /// \brief Call the appropriate runtime routine to notify that we finished
+ /// Call the appropriate runtime routine to notify that we finished
/// iteration of the ordered loop with the dynamic scheduling.
///
/// \param CGF Reference to current CodeGenFunction.
@@ -882,7 +1000,7 @@ public:
SourceLocation Loc, unsigned IVSize,
bool IVSigned);
- /// \brief Call the appropriate runtime routine to notify that we finished
+ /// Call the appropriate runtime routine to notify that we finished
/// all the work with current loop.
///
/// \param CGF Reference to current CodeGenFunction.
@@ -911,7 +1029,7 @@ public:
Address IL, Address LB,
Address UB, Address ST);
- /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
+ /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
/// clause.
/// \param NumThreads An integer value of threads.
@@ -919,13 +1037,13 @@ public:
llvm::Value *NumThreads,
SourceLocation Loc);
- /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
+ /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
/// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
virtual void emitProcBindClause(CodeGenFunction &CGF,
OpenMPProcBindClauseKind ProcBind,
SourceLocation Loc);
- /// \brief Returns address of the threadprivate variable for the current
+ /// Returns address of the threadprivate variable for the current
/// thread.
/// \param VD Threadprivate variable.
/// \param VDAddr Address of the global variable \a VD.
@@ -936,7 +1054,11 @@ public:
Address VDAddr,
SourceLocation Loc);
- /// \brief Emit a code for initialization of threadprivate variable. It emits
+ /// Returns the address of the variable marked as declare target with link
+ /// clause.
+ virtual Address getAddrOfDeclareTargetLink(const VarDecl *VD);
+
+ /// Emit a code for initialization of threadprivate variable. It emits
/// a call to runtime library which adds initial value to the newly created
/// threadprivate variable (if it is not constant) and registers destructor
/// for the variable (if any).
@@ -949,6 +1071,14 @@ public:
SourceLocation Loc, bool PerformInit,
CodeGenFunction *CGF = nullptr);
+ /// Emit a code for initialization of declare target variable.
+ /// \param VD Declare target variable.
+ /// \param Addr Address of the global variable \a VD.
+ /// \param PerformInit true if initialization expression is not constant.
+ virtual bool emitDeclareTargetVarDefinition(const VarDecl *VD,
+ llvm::GlobalVariable *Addr,
+ bool PerformInit);
+
/// Creates artificial threadprivate variable with name \p Name and type \p
/// VarType.
/// \param VarType Type of the artificial threadprivate variable.
@@ -957,12 +1087,12 @@ public:
QualType VarType,
StringRef Name);
- /// \brief Emit flush of the variables specified in 'omp flush' directive.
+ /// Emit flush of the variables specified in 'omp flush' directive.
/// \param Vars List of variables to flush.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
SourceLocation Loc);
- /// \brief Emit task region for the task directive. The task region is
+ /// Emit task region for the task directive. The task region is
/// emitted in several steps:
/// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
/// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
@@ -1029,7 +1159,7 @@ public:
llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
const Expr *IfCond, const OMPTaskDataTy &Data);
- /// \brief Emit code for the directive that does not require outlining.
+ /// Emit code for the directive that does not require outlining.
///
/// \param InnermostKind Kind of innermost directive (for simple directives it
/// is a directive itself, for combined - its innermost directive).
@@ -1048,7 +1178,8 @@ public:
/// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
/// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
/// or 'operator binop(LHS, RHS)'.
- llvm::Value *emitReductionFunction(CodeGenModule &CGM, llvm::Type *ArgsType,
+ llvm::Value *emitReductionFunction(CodeGenModule &CGM, SourceLocation Loc,
+ llvm::Type *ArgsType,
ArrayRef<const Expr *> Privates,
ArrayRef<const Expr *> LHSExprs,
ArrayRef<const Expr *> RHSExprs,
@@ -1066,7 +1197,7 @@ public:
bool SimpleReduction;
OpenMPDirectiveKind ReductionKind;
};
- /// \brief Emit a code for reduction clause. Next code should be emitted for
+ /// Emit a code for reduction clause. Next code should be emitted for
/// reduction:
/// \code
///
@@ -1160,10 +1291,10 @@ public:
llvm::Value *ReductionsPtr,
LValue SharedLVal);
- /// \brief Emit code for 'taskwait' directive.
+ /// Emit code for 'taskwait' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
- /// \brief Emit code for 'cancellation point' construct.
+ /// Emit code for 'cancellation point' construct.
/// \param CancelRegion Region kind for which the cancellation point must be
/// emitted.
///
@@ -1171,7 +1302,7 @@ public:
SourceLocation Loc,
OpenMPDirectiveKind CancelRegion);
- /// \brief Emit code for 'cancel' construct.
+ /// Emit code for 'cancel' construct.
/// \param IfCond Condition in the associated 'if' clause, if it was
/// specified, nullptr otherwise.
/// \param CancelRegion Region kind for which the cancel must be emitted.
@@ -1180,7 +1311,7 @@ public:
const Expr *IfCond,
OpenMPDirectiveKind CancelRegion);
- /// \brief Emit outilined function for 'target' directive.
+ /// Emit outilined function for 'target' directive.
/// \param D Directive to emit.
/// \param ParentName Name of the function that encloses the target region.
/// \param OutlinedFn Outlined function value to be defined by this call.
@@ -1196,7 +1327,7 @@ public:
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen);
- /// \brief Emit the target offloading code associated with \a D. The emitted
+ /// Emit the target offloading code associated with \a D. The emitted
/// code attempts offloading the execution to the device, an the event of
/// a failure it executes the host version outlined in \a OutlinedFn.
/// \param D Directive to emit.
@@ -1206,36 +1337,39 @@ public:
/// directive, or null if no if clause is used.
/// \param Device Expression evaluated in device clause associated with the
/// target directive, or null if no device clause is used.
- /// \param CapturedVars Values captured in the current region.
virtual void emitTargetCall(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
llvm::Value *OutlinedFn,
llvm::Value *OutlinedFnID, const Expr *IfCond,
- const Expr *Device,
- ArrayRef<llvm::Value *> CapturedVars);
+ const Expr *Device);
- /// \brief Emit the target regions enclosed in \a GD function definition or
+ /// Emit the target regions enclosed in \a GD function definition or
/// the function itself in case it is a valid device function. Returns true if
/// \a GD was dealt with successfully.
/// \param GD Function to scan.
virtual bool emitTargetFunctions(GlobalDecl GD);
- /// \brief Emit the global variable if it is a valid device global variable.
+ /// Emit the global variable if it is a valid device global variable.
/// Returns true if \a GD was dealt with successfully.
/// \param GD Variable declaration to emit.
virtual bool emitTargetGlobalVariable(GlobalDecl GD);
- /// \brief Emit the global \a GD if it is meaningful for the target. Returns
+ /// Checks if the provided global decl \a GD is a declare target variable and
+ /// registers it when emitting code for the host.
+ virtual void registerTargetGlobalVariable(const VarDecl *VD,
+ llvm::Constant *Addr);
+
+ /// Emit the global \a GD if it is meaningful for the target. Returns
/// if it was emitted successfully.
/// \param GD Global to scan.
virtual bool emitTargetGlobal(GlobalDecl GD);
- /// \brief Creates the offloading descriptor in the event any target region
+ /// Creates the offloading descriptor in the event any target region
/// was emitted in the current module and return the function that registers
/// it.
virtual llvm::Function *emitRegistrationFunction();
- /// \brief Emits code for teams call of the \a OutlinedFn with
+ /// Emits code for teams call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run by team masters. Type of
@@ -1248,7 +1382,7 @@ public:
SourceLocation Loc, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars);
- /// \brief Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
+ /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
/// for num_teams clause.
/// \param NumTeams An integer expression of teams.
@@ -1296,7 +1430,7 @@ public:
bool requiresDevicePointerInfo() { return RequiresDevicePointerInfo; }
};
- /// \brief Emit the target data mapping code associated with \a D.
+ /// Emit the target data mapping code associated with \a D.
/// \param D Directive to emit.
/// \param IfCond Expression evaluated in if clause associated with the
/// target directive, or null if no device clause is used.
@@ -1310,7 +1444,7 @@ public:
const RegionCodeGenTy &CodeGen,
TargetDataInfo &Info);
- /// \brief Emit the data mapping/movement code associated with the directive
+ /// Emit the data mapping/movement code associated with the directive
/// \a D that should be of the form 'target [{enter|exit} data | update]'.
/// \param D Directive to emit.
/// \param IfCond Expression evaluated in if clause associated with the target
@@ -1331,8 +1465,8 @@ public:
/// Emit initialization for doacross loop nesting support.
/// \param D Loop-based construct used in doacross nesting construct.
- virtual void emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D);
+ virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations);
/// Emit code for doacross ordered directive with 'depend' clause.
/// \param C 'depend' clause with 'sink|source' dependency kind.
@@ -1341,7 +1475,7 @@ public:
/// Translates the native parameter of outlined function if this is required
/// for target.
- /// \param FD Field decl from captured record for the paramater.
+ /// \param FD Field decl from captured record for the parameter.
/// \param NativeParam Parameter itself.
virtual const VarDecl *translateParameter(const FieldDecl *FD,
const VarDecl *NativeParam) const {
@@ -1362,6 +1496,19 @@ public:
emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> Args = llvm::None) const;
+
+ /// Emits OpenMP-specific function prolog.
+ /// Required for device constructs.
+ virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {}
+
+ /// Gets the OpenMP-specific address of the local variable.
+ virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD);
+
+ /// Marks the declaration as alread emitted for the device code and returns
+ /// true, if it was marked already, and false, otherwise.
+ bool markAsGlobalTarget(GlobalDecl GD);
+
};
/// Class supports emissionof SIMD-only code.
@@ -1370,7 +1517,7 @@ public:
explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {}
~CGOpenMPSIMDRuntime() override {}
- /// \brief Emits outlined function for the specified OpenMP parallel directive
+ /// Emits outlined function for the specified OpenMP parallel directive
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
/// \param D OpenMP directive.
@@ -1384,7 +1531,7 @@ public:
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) override;
- /// \brief Emits outlined function for the specified OpenMP teams directive
+ /// Emits outlined function for the specified OpenMP teams directive
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
/// \param D OpenMP directive.
@@ -1398,7 +1545,7 @@ public:
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) override;
- /// \brief Emits outlined function for the OpenMP task directive \a D. This
+ /// Emits outlined function for the OpenMP task directive \a D. This
/// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
/// TaskT).
/// \param D OpenMP directive.
@@ -1419,7 +1566,7 @@ public:
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
bool Tied, unsigned &NumberOfParts) override;
- /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// Emits code for parallel or serial call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
@@ -1434,7 +1581,7 @@ public:
ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond) override;
- /// \brief Emits a critical region.
+ /// Emits a critical region.
/// \param CriticalName Name of the critical region.
/// \param CriticalOpGen Generator for the statement associated with the given
/// critical region.
@@ -1444,24 +1591,24 @@ public:
SourceLocation Loc,
const Expr *Hint = nullptr) override;
- /// \brief Emits a master region.
+ /// Emits a master region.
/// \param MasterOpGen Generator for the statement associated with the given
/// master region.
void emitMasterRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc) override;
- /// \brief Emits code for a taskyield directive.
+ /// Emits code for a taskyield directive.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
- /// \brief Emit a taskgroup region.
+ /// Emit a taskgroup region.
/// \param TaskgroupOpGen Generator for the statement associated with the
/// given taskgroup region.
void emitTaskgroupRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &TaskgroupOpGen,
SourceLocation Loc) override;
- /// \brief Emits a single region.
+ /// Emits a single region.
/// \param SingleOpGen Generator for the statement associated with the given
/// single region.
void emitSingleRegion(CodeGenFunction &CGF,
@@ -1471,14 +1618,14 @@ public:
ArrayRef<const Expr *> SrcExprs,
ArrayRef<const Expr *> AssignmentOps) override;
- /// \brief Emit an ordered region.
+ /// Emit an ordered region.
/// \param OrderedOpGen Generator for the statement associated with the given
/// ordered region.
void emitOrderedRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &OrderedOpGen,
SourceLocation Loc, bool IsThreads) override;
- /// \brief Emit an implicit/explicit barrier for OpenMP threads.
+ /// Emit an implicit/explicit barrier for OpenMP threads.
/// \param Kind Directive for which this implicit barrier call must be
/// generated. Must be OMPD_barrier for explicit barrier generation.
/// \param EmitChecks true if need to emit checks for cancellation barriers.
@@ -1511,7 +1658,7 @@ public:
unsigned IVSize, bool IVSigned, bool Ordered,
const DispatchRTInput &DispatchValues) override;
- /// \brief Call the appropriate runtime routine to initialize it before start
+ /// Call the appropriate runtime routine to initialize it before start
/// of loop.
///
/// This is used only in case of static schedule, when the user did not
@@ -1541,7 +1688,7 @@ public:
OpenMPDistScheduleClauseKind SchedKind,
const StaticRTInput &Values) override;
- /// \brief Call the appropriate runtime routine to notify that we finished
+ /// Call the appropriate runtime routine to notify that we finished
/// iteration of the ordered loop with the dynamic scheduling.
///
/// \param CGF Reference to current CodeGenFunction.
@@ -1552,7 +1699,7 @@ public:
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc,
unsigned IVSize, bool IVSigned) override;
- /// \brief Call the appropriate runtime routine to notify that we finished
+ /// Call the appropriate runtime routine to notify that we finished
/// all the work with current loop.
///
/// \param CGF Reference to current CodeGenFunction.
@@ -1580,20 +1727,20 @@ public:
unsigned IVSize, bool IVSigned, Address IL,
Address LB, Address UB, Address ST) override;
- /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
+ /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
/// clause.
/// \param NumThreads An integer value of threads.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads,
SourceLocation Loc) override;
- /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
+ /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
/// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
void emitProcBindClause(CodeGenFunction &CGF,
OpenMPProcBindClauseKind ProcBind,
SourceLocation Loc) override;
- /// \brief Returns address of the threadprivate variable for the current
+ /// Returns address of the threadprivate variable for the current
/// thread.
/// \param VD Threadprivate variable.
/// \param VDAddr Address of the global variable \a VD.
@@ -1602,7 +1749,7 @@ public:
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD,
Address VDAddr, SourceLocation Loc) override;
- /// \brief Emit a code for initialization of threadprivate variable. It emits
+ /// Emit a code for initialization of threadprivate variable. It emits
/// a call to runtime library which adds initial value to the newly created
/// threadprivate variable (if it is not constant) and registers destructor
/// for the variable (if any).
@@ -1623,12 +1770,12 @@ public:
QualType VarType,
StringRef Name) override;
- /// \brief Emit flush of the variables specified in 'omp flush' directive.
+ /// Emit flush of the variables specified in 'omp flush' directive.
/// \param Vars List of variables to flush.
void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
SourceLocation Loc) override;
- /// \brief Emit task region for the task directive. The task region is
+ /// Emit task region for the task directive. The task region is
/// emitted in several steps:
/// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
/// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
@@ -1694,7 +1841,7 @@ public:
QualType SharedsTy, Address Shareds, const Expr *IfCond,
const OMPTaskDataTy &Data) override;
- /// \brief Emit a code for reduction clause. Next code should be emitted for
+ /// Emit a code for reduction clause. Next code should be emitted for
/// reduction:
/// \code
///
@@ -1787,17 +1934,17 @@ public:
llvm::Value *ReductionsPtr,
LValue SharedLVal) override;
- /// \brief Emit code for 'taskwait' directive.
+ /// Emit code for 'taskwait' directive.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
- /// \brief Emit code for 'cancellation point' construct.
+ /// Emit code for 'cancellation point' construct.
/// \param CancelRegion Region kind for which the cancellation point must be
/// emitted.
///
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind CancelRegion) override;
- /// \brief Emit code for 'cancel' construct.
+ /// Emit code for 'cancel' construct.
/// \param IfCond Condition in the associated 'if' clause, if it was
/// specified, nullptr otherwise.
/// \param CancelRegion Region kind for which the cancel must be emitted.
@@ -1806,7 +1953,7 @@ public:
const Expr *IfCond,
OpenMPDirectiveKind CancelRegion) override;
- /// \brief Emit outilined function for 'target' directive.
+ /// Emit outilined function for 'target' directive.
/// \param D Directive to emit.
/// \param ParentName Name of the function that encloses the target region.
/// \param OutlinedFn Outlined function value to be defined by this call.
@@ -1822,7 +1969,7 @@ public:
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen) override;
- /// \brief Emit the target offloading code associated with \a D. The emitted
+ /// Emit the target offloading code associated with \a D. The emitted
/// code attempts offloading the execution to the device, an the event of
/// a failure it executes the host version outlined in \a OutlinedFn.
/// \param D Directive to emit.
@@ -1832,34 +1979,32 @@ public:
/// directive, or null if no if clause is used.
/// \param Device Expression evaluated in device clause associated with the
/// target directive, or null if no device clause is used.
- /// \param CapturedVars Values captured in the current region.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
llvm::Value *OutlinedFn, llvm::Value *OutlinedFnID,
- const Expr *IfCond, const Expr *Device,
- ArrayRef<llvm::Value *> CapturedVars) override;
+ const Expr *IfCond, const Expr *Device) override;
- /// \brief Emit the target regions enclosed in \a GD function definition or
+ /// Emit the target regions enclosed in \a GD function definition or
/// the function itself in case it is a valid device function. Returns true if
/// \a GD was dealt with successfully.
/// \param GD Function to scan.
bool emitTargetFunctions(GlobalDecl GD) override;
- /// \brief Emit the global variable if it is a valid device global variable.
+ /// Emit the global variable if it is a valid device global variable.
/// Returns true if \a GD was dealt with successfully.
/// \param GD Variable declaration to emit.
bool emitTargetGlobalVariable(GlobalDecl GD) override;
- /// \brief Emit the global \a GD if it is meaningful for the target. Returns
+ /// Emit the global \a GD if it is meaningful for the target. Returns
/// if it was emitted successfully.
/// \param GD Global to scan.
bool emitTargetGlobal(GlobalDecl GD) override;
- /// \brief Creates the offloading descriptor in the event any target region
+ /// Creates the offloading descriptor in the event any target region
/// was emitted in the current module and return the function that registers
/// it.
llvm::Function *emitRegistrationFunction() override;
- /// \brief Emits code for teams call of the \a OutlinedFn with
+ /// Emits code for teams call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run by team masters. Type of
@@ -1871,7 +2016,7 @@ public:
SourceLocation Loc, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars) override;
- /// \brief Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
+ /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
/// for num_teams clause.
/// \param NumTeams An integer expression of teams.
@@ -1879,7 +2024,7 @@ public:
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
const Expr *ThreadLimit, SourceLocation Loc) override;
- /// \brief Emit the target data mapping code associated with \a D.
+ /// Emit the target data mapping code associated with \a D.
/// \param D Directive to emit.
/// \param IfCond Expression evaluated in if clause associated with the
/// target directive, or null if no device clause is used.
@@ -1892,7 +2037,7 @@ public:
const Expr *Device, const RegionCodeGenTy &CodeGen,
TargetDataInfo &Info) override;
- /// \brief Emit the data mapping/movement code associated with the directive
+ /// Emit the data mapping/movement code associated with the directive
/// \a D that should be of the form 'target [{enter|exit} data | update]'.
/// \param D Directive to emit.
/// \param IfCond Expression evaluated in if clause associated with the target
@@ -1906,8 +2051,8 @@ public:
/// Emit initialization for doacross loop nesting support.
/// \param D Loop-based construct used in doacross nesting construct.
- void emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) override;
+ void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) override;
/// Emit code for doacross ordered directive with 'depend' clause.
/// \param C 'depend' clause with 'sink|source' dependency kind.
@@ -1916,7 +2061,7 @@ public:
/// Translates the native parameter of outlined function if this is required
/// for target.
- /// \param FD Field decl from captured record for the paramater.
+ /// \param FD Field decl from captured record for the parameter.
/// \param NativeParam Parameter itself.
const VarDecl *translateParameter(const FieldDecl *FD,
const VarDecl *NativeParam) const override;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 7b2993cfd38d..2768a8eb1857 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -13,33 +13,35 @@
//===----------------------------------------------------------------------===//
#include "CGOpenMPRuntimeNVPTX.h"
-#include "clang/AST/DeclOpenMP.h"
#include "CodeGenFunction.h"
+#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/SmallPtrSet.h"
using namespace clang;
using namespace CodeGen;
namespace {
enum OpenMPRTLFunctionNVPTX {
- /// \brief Call to void __kmpc_kernel_init(kmp_int32 thread_limit,
+ /// 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(int16_t IsOMPRuntimeInitialized);
+ /// 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,
+ /// Call to void __kmpc_spmd_kernel_init(kmp_int32 thread_limit,
/// int16_t RequiresOMPRuntime, int16_t RequiresDataSharing);
OMPRTL_NVPTX__kmpc_spmd_kernel_init,
- /// \brief Call to void __kmpc_spmd_kernel_deinit();
+ /// Call to void __kmpc_spmd_kernel_deinit();
OMPRTL_NVPTX__kmpc_spmd_kernel_deinit,
- /// \brief Call to void __kmpc_kernel_prepare_parallel(void
- /// *outlined_function, void ***args, kmp_int32 nArgs, int16_t
+ /// Call to void __kmpc_kernel_prepare_parallel(void
+ /// *outlined_function, int16_t
/// IsOMPRuntimeInitialized);
OMPRTL_NVPTX__kmpc_kernel_prepare_parallel,
- /// \brief Call to bool __kmpc_kernel_parallel(void **outlined_function, void
- /// ***args, int16_t IsOMPRuntimeInitialized);
+ /// Call to bool __kmpc_kernel_parallel(void **outlined_function,
+ /// int16_t IsOMPRuntimeInitialized);
OMPRTL_NVPTX__kmpc_kernel_parallel,
- /// \brief Call to void __kmpc_kernel_end_parallel();
+ /// Call to void __kmpc_kernel_end_parallel();
OMPRTL_NVPTX__kmpc_kernel_end_parallel,
/// Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
/// global_tid);
@@ -47,19 +49,25 @@ enum OpenMPRTLFunctionNVPTX {
/// Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
/// global_tid);
OMPRTL_NVPTX__kmpc_end_serialized_parallel,
- /// \brief Call to int32_t __kmpc_shuffle_int32(int32_t element,
+ /// Call to int32_t __kmpc_shuffle_int32(int32_t element,
/// int16_t lane_offset, int16_t warp_size);
OMPRTL_NVPTX__kmpc_shuffle_int32,
- /// \brief Call to int64_t __kmpc_shuffle_int64(int64_t element,
+ /// Call to int64_t __kmpc_shuffle_int64(int64_t element,
/// int16_t lane_offset, int16_t warp_size);
OMPRTL_NVPTX__kmpc_shuffle_int64,
- /// \brief Call to __kmpc_nvptx_parallel_reduce_nowait(kmp_int32
+ /// Call to __kmpc_nvptx_parallel_reduce_nowait(kmp_int32
/// global_tid, kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
/// void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
/// lane_offset, int16_t shortCircuit),
/// void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num));
OMPRTL_NVPTX__kmpc_parallel_reduce_nowait,
- /// \brief Call to __kmpc_nvptx_teams_reduce_nowait(int32_t global_tid,
+ /// Call to __kmpc_nvptx_simd_reduce_nowait(kmp_int32
+ /// global_tid, kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
+ /// void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
+ /// lane_offset, int16_t shortCircuit),
+ /// void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num));
+ OMPRTL_NVPTX__kmpc_simd_reduce_nowait,
+ /// Call to __kmpc_nvptx_teams_reduce_nowait(int32_t global_tid,
/// int32_t num_vars, size_t reduce_size, void *reduce_data,
/// void (*kmp_ShuffleReductFctPtr)(void *rhs, int16_t lane_id, int16_t
/// lane_offset, int16_t shortCircuit),
@@ -69,17 +77,38 @@ enum OpenMPRTLFunctionNVPTX {
/// void (*kmp_LoadReduceFctPtr)(void *reduce_data, void * scratchpad, int32_t
/// index, int32_t width, int32_t reduce))
OMPRTL_NVPTX__kmpc_teams_reduce_nowait,
- /// \brief Call to __kmpc_nvptx_end_reduce_nowait(int32_t global_tid);
- OMPRTL_NVPTX__kmpc_end_reduce_nowait
+ /// Call to __kmpc_nvptx_end_reduce_nowait(int32_t global_tid);
+ OMPRTL_NVPTX__kmpc_end_reduce_nowait,
+ /// Call to void __kmpc_data_sharing_init_stack();
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack,
+ /// Call to void __kmpc_data_sharing_init_stack_spmd();
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd,
+ /// Call to void* __kmpc_data_sharing_push_stack(size_t size,
+ /// int16_t UseSharedMemory);
+ OMPRTL_NVPTX__kmpc_data_sharing_push_stack,
+ /// Call to void __kmpc_data_sharing_pop_stack(void *a);
+ OMPRTL_NVPTX__kmpc_data_sharing_pop_stack,
+ /// Call to void __kmpc_begin_sharing_variables(void ***args,
+ /// size_t n_args);
+ OMPRTL_NVPTX__kmpc_begin_sharing_variables,
+ /// Call to void __kmpc_end_sharing_variables();
+ OMPRTL_NVPTX__kmpc_end_sharing_variables,
+ /// Call to void __kmpc_get_shared_variables(void ***GlobalArgs)
+ OMPRTL_NVPTX__kmpc_get_shared_variables,
+ /// Call to uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32
+ /// global_tid);
+ OMPRTL_NVPTX__kmpc_parallel_level,
+ /// Call to int8_t __kmpc_is_spmd_exec_mode();
+ OMPRTL_NVPTX__kmpc_is_spmd_exec_mode,
};
/// Pre(post)-action for different OpenMP constructs specialized for NVPTX.
class NVPTXActionTy final : public PrePostActionTy {
- llvm::Value *EnterCallee;
+ llvm::Value *EnterCallee = nullptr;
ArrayRef<llvm::Value *> EnterArgs;
- llvm::Value *ExitCallee;
+ llvm::Value *ExitCallee = nullptr;
ArrayRef<llvm::Value *> ExitArgs;
- bool Conditional;
+ bool Conditional = false;
llvm::BasicBlock *ContBlock = nullptr;
public:
@@ -109,21 +138,21 @@ public:
}
};
-// A class to track the execution mode when codegening directives within
-// a target region. The appropriate mode (generic/spmd) is set on entry
-// to the target region and used by containing directives such as 'parallel'
-// to emit optimized code.
+/// A class to track the execution mode when codegening directives within
+/// a target region. The appropriate mode (SPMD|NON-SPMD) is set on entry
+/// to the target region and used by containing directives such as 'parallel'
+/// to emit optimized code.
class ExecutionModeRAII {
private:
CGOpenMPRuntimeNVPTX::ExecutionMode SavedMode;
CGOpenMPRuntimeNVPTX::ExecutionMode &Mode;
public:
- ExecutionModeRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &Mode,
- CGOpenMPRuntimeNVPTX::ExecutionMode NewMode)
+ ExecutionModeRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &Mode, bool IsSPMD)
: Mode(Mode) {
SavedMode = Mode;
- Mode = NewMode;
+ Mode = IsSPMD ? CGOpenMPRuntimeNVPTX::EM_SPMD
+ : CGOpenMPRuntimeNVPTX::EM_NonSPMD;
}
~ExecutionModeRAII() { Mode = SavedMode; }
};
@@ -149,6 +178,343 @@ enum NamedBarrier : unsigned {
/// barrier.
NB_Parallel = 1,
};
+
+/// Get the list of variables that can escape their declaration context.
+class CheckVarsEscapingDeclContext final
+ : public ConstStmtVisitor<CheckVarsEscapingDeclContext> {
+ CodeGenFunction &CGF;
+ llvm::SetVector<const ValueDecl *> EscapedDecls;
+ llvm::SetVector<const ValueDecl *> EscapedVariableLengthDecls;
+ llvm::SmallPtrSet<const Decl *, 4> EscapedParameters;
+ RecordDecl *GlobalizedRD = nullptr;
+ llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
+ bool AllEscaped = false;
+ bool IsForCombinedParallelRegion = false;
+
+ void markAsEscaped(const ValueDecl *VD) {
+ // Do not globalize declare target variables.
+ if (!isa<VarDecl>(VD) ||
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ return;
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ // Variables captured by value must be globalized.
+ if (auto *CSI = CGF.CapturedStmtInfo) {
+ if (const FieldDecl *FD = CSI->lookup(cast<VarDecl>(VD))) {
+ // Check if need to capture the variable that was already captured by
+ // value in the outer region.
+ if (!IsForCombinedParallelRegion) {
+ if (!FD->hasAttrs())
+ return;
+ const auto *Attr = FD->getAttr<OMPCaptureKindAttr>();
+ if (!Attr)
+ return;
+ if (!isOpenMPPrivate(
+ static_cast<OpenMPClauseKind>(Attr->getCaptureKind())) ||
+ Attr->getCaptureKind() == OMPC_map)
+ return;
+ }
+ if (!FD->getType()->isReferenceType()) {
+ assert(!VD->getType()->isVariablyModifiedType() &&
+ "Parameter captured by value with variably modified type");
+ EscapedParameters.insert(VD);
+ } else if (!IsForCombinedParallelRegion) {
+ return;
+ }
+ }
+ }
+ if ((!CGF.CapturedStmtInfo ||
+ (IsForCombinedParallelRegion && CGF.CapturedStmtInfo)) &&
+ VD->getType()->isReferenceType())
+ // Do not globalize variables with reference type.
+ return;
+ if (VD->getType()->isVariablyModifiedType())
+ EscapedVariableLengthDecls.insert(VD);
+ else
+ EscapedDecls.insert(VD);
+ }
+
+ void VisitValueDecl(const ValueDecl *VD) {
+ if (VD->getType()->isLValueReferenceType())
+ markAsEscaped(VD);
+ if (const auto *VarD = dyn_cast<VarDecl>(VD)) {
+ if (!isa<ParmVarDecl>(VarD) && VarD->hasInit()) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = VD->getType()->isLValueReferenceType();
+ Visit(VarD->getInit());
+ AllEscaped = SavedAllEscaped;
+ }
+ }
+ }
+ void VisitOpenMPCapturedStmt(const CapturedStmt *S,
+ ArrayRef<OMPClause *> Clauses,
+ bool IsCombinedParallelRegion) {
+ if (!S)
+ return;
+ for (const CapturedStmt::Capture &C : S->captures()) {
+ if (C.capturesVariable() && !C.capturesVariableByCopy()) {
+ const ValueDecl *VD = C.getCapturedVar();
+ bool SavedIsForCombinedParallelRegion = IsForCombinedParallelRegion;
+ if (IsCombinedParallelRegion) {
+ // Check if the variable is privatized in the combined construct and
+ // those private copies must be shared in the inner parallel
+ // directive.
+ IsForCombinedParallelRegion = false;
+ for (const OMPClause *C : Clauses) {
+ if (!isOpenMPPrivate(C->getClauseKind()) ||
+ C->getClauseKind() == OMPC_reduction ||
+ C->getClauseKind() == OMPC_linear ||
+ C->getClauseKind() == OMPC_private)
+ continue;
+ ArrayRef<const Expr *> Vars;
+ if (const auto *PC = dyn_cast<OMPFirstprivateClause>(C))
+ Vars = PC->getVarRefs();
+ else if (const auto *PC = dyn_cast<OMPLastprivateClause>(C))
+ Vars = PC->getVarRefs();
+ else
+ llvm_unreachable("Unexpected clause.");
+ for (const auto *E : Vars) {
+ const Decl *D =
+ cast<DeclRefExpr>(E)->getDecl()->getCanonicalDecl();
+ if (D == VD->getCanonicalDecl()) {
+ IsForCombinedParallelRegion = true;
+ break;
+ }
+ }
+ if (IsForCombinedParallelRegion)
+ break;
+ }
+ }
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ IsForCombinedParallelRegion = SavedIsForCombinedParallelRegion;
+ }
+ }
+ }
+
+ typedef std::pair<CharUnits /*Align*/, const ValueDecl *> VarsDataTy;
+ static bool stable_sort_comparator(const VarsDataTy P1, const VarsDataTy P2) {
+ return P1.first > P2.first;
+ }
+
+ void buildRecordForGlobalizedVars() {
+ assert(!GlobalizedRD &&
+ "Record for globalized variables is built already.");
+ if (EscapedDecls.empty())
+ return;
+ ASTContext &C = CGF.getContext();
+ SmallVector<VarsDataTy, 4> GlobalizedVars;
+ for (const ValueDecl *D : EscapedDecls)
+ GlobalizedVars.emplace_back(C.getDeclAlign(D), D);
+ std::stable_sort(GlobalizedVars.begin(), GlobalizedVars.end(),
+ stable_sort_comparator);
+ // Build struct _globalized_locals_ty {
+ // /* globalized vars */
+ // };
+ GlobalizedRD = C.buildImplicitRecord("_globalized_locals_ty");
+ GlobalizedRD->startDefinition();
+ for (const auto &Pair : GlobalizedVars) {
+ const ValueDecl *VD = Pair.second;
+ QualType Type = VD->getType();
+ if (Type->isLValueReferenceType())
+ Type = C.getPointerType(Type.getNonReferenceType());
+ else
+ Type = Type.getNonReferenceType();
+ SourceLocation Loc = VD->getLocation();
+ auto *Field = FieldDecl::Create(
+ C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type,
+ C.getTrivialTypeSourceInfo(Type, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ GlobalizedRD->addDecl(Field);
+ if (VD->hasAttrs()) {
+ for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
+ E(VD->getAttrs().end());
+ I != E; ++I)
+ Field->addAttr(*I);
+ }
+ MappedDeclsFields.try_emplace(VD, Field);
+ }
+ GlobalizedRD->completeDefinition();
+ }
+
+public:
+ CheckVarsEscapingDeclContext(CodeGenFunction &CGF) : CGF(CGF) {}
+ virtual ~CheckVarsEscapingDeclContext() = default;
+ void VisitDeclStmt(const DeclStmt *S) {
+ if (!S)
+ return;
+ for (const Decl *D : S->decls())
+ if (const auto *VD = dyn_cast_or_null<ValueDecl>(D))
+ VisitValueDecl(VD);
+ }
+ void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
+ if (!D)
+ return;
+ if (!D->hasAssociatedStmt())
+ return;
+ if (const auto *S =
+ dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) {
+ // Do not analyze directives that do not actually require capturing,
+ // like `omp for` or `omp simd` directives.
+ llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+ getOpenMPCaptureRegions(CaptureRegions, D->getDirectiveKind());
+ if (CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown) {
+ VisitStmt(S->getCapturedStmt());
+ return;
+ }
+ VisitOpenMPCapturedStmt(
+ S, D->clauses(),
+ CaptureRegions.back() == OMPD_parallel &&
+ isOpenMPDistributeDirective(D->getDirectiveKind()));
+ }
+ }
+ void VisitCapturedStmt(const CapturedStmt *S) {
+ if (!S)
+ return;
+ for (const CapturedStmt::Capture &C : S->captures()) {
+ if (C.capturesVariable() && !C.capturesVariableByCopy()) {
+ const ValueDecl *VD = C.getCapturedVar();
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ }
+ }
+ }
+ void VisitLambdaExpr(const LambdaExpr *E) {
+ if (!E)
+ return;
+ for (const LambdaCapture &C : E->captures()) {
+ if (C.capturesVariable()) {
+ if (C.getCaptureKind() == LCK_ByRef) {
+ const ValueDecl *VD = C.getCapturedVar();
+ markAsEscaped(VD);
+ if (E->isInitCapture(&C) || isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ }
+ }
+ }
+ }
+ void VisitBlockExpr(const BlockExpr *E) {
+ if (!E)
+ return;
+ for (const BlockDecl::Capture &C : E->getBlockDecl()->captures()) {
+ if (C.isByRef()) {
+ const VarDecl *VD = C.getVariable();
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD) || VD->isInitCapture())
+ VisitValueDecl(VD);
+ }
+ }
+ }
+ void VisitCallExpr(const CallExpr *E) {
+ if (!E)
+ return;
+ for (const Expr *Arg : E->arguments()) {
+ if (!Arg)
+ continue;
+ if (Arg->isLValue()) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = true;
+ Visit(Arg);
+ AllEscaped = SavedAllEscaped;
+ } else {
+ Visit(Arg);
+ }
+ }
+ Visit(E->getCallee());
+ }
+ void VisitDeclRefExpr(const DeclRefExpr *E) {
+ if (!E)
+ return;
+ const ValueDecl *VD = E->getDecl();
+ if (AllEscaped)
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ else if (const auto *VarD = dyn_cast<VarDecl>(VD))
+ if (VarD->isInitCapture())
+ VisitValueDecl(VD);
+ }
+ void VisitUnaryOperator(const UnaryOperator *E) {
+ if (!E)
+ return;
+ if (E->getOpcode() == UO_AddrOf) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = true;
+ Visit(E->getSubExpr());
+ AllEscaped = SavedAllEscaped;
+ } else {
+ Visit(E->getSubExpr());
+ }
+ }
+ void VisitImplicitCastExpr(const ImplicitCastExpr *E) {
+ if (!E)
+ return;
+ if (E->getCastKind() == CK_ArrayToPointerDecay) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = true;
+ Visit(E->getSubExpr());
+ AllEscaped = SavedAllEscaped;
+ } else {
+ Visit(E->getSubExpr());
+ }
+ }
+ void VisitExpr(const Expr *E) {
+ if (!E)
+ return;
+ bool SavedAllEscaped = AllEscaped;
+ if (!E->isLValue())
+ AllEscaped = false;
+ for (const Stmt *Child : E->children())
+ if (Child)
+ Visit(Child);
+ AllEscaped = SavedAllEscaped;
+ }
+ void VisitStmt(const Stmt *S) {
+ if (!S)
+ return;
+ for (const Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
+ }
+
+ /// Returns the record that handles all the escaped local variables and used
+ /// instead of their original storage.
+ const RecordDecl *getGlobalizedRecord() {
+ if (!GlobalizedRD)
+ buildRecordForGlobalizedVars();
+ return GlobalizedRD;
+ }
+
+ /// Returns the field in the globalized record for the escaped variable.
+ const FieldDecl *getFieldForGlobalizedVar(const ValueDecl *VD) const {
+ assert(GlobalizedRD &&
+ "Record for globalized variables must be generated already.");
+ auto I = MappedDeclsFields.find(VD);
+ if (I == MappedDeclsFields.end())
+ return nullptr;
+ return I->getSecond();
+ }
+
+ /// Returns the list of the escaped local variables/parameters.
+ ArrayRef<const ValueDecl *> getEscapedDecls() const {
+ return EscapedDecls.getArrayRef();
+ }
+
+ /// Checks if the escaped local variable is actually a parameter passed by
+ /// value.
+ const llvm::SmallPtrSetImpl<const Decl *> &getEscapedParameters() const {
+ return EscapedParameters;
+ }
+
+ /// Returns the list of the escaped variables with the variably modified
+ /// types.
+ ArrayRef<const ValueDecl *> getEscapedVariableLengthDecls() const {
+ return EscapedVariableLengthDecls.getArrayRef();
+ }
+};
} // anonymous namespace
/// Get the GPU warp size.
@@ -223,12 +589,12 @@ static void syncParallelThreads(CodeGenFunction &CGF, llvm::Value *NumThreads) {
/// CTA. The threads in the last warp are reserved for master execution.
/// For the 'spmd' execution mode, all threads in a CTA are part of the team.
static llvm::Value *getThreadLimit(CodeGenFunction &CGF,
- bool IsInSpmdExecutionMode = false) {
+ bool IsInSPMDExecutionMode = false) {
CGBuilderTy &Bld = CGF.Builder;
- return IsInSpmdExecutionMode
+ return IsInSPMDExecutionMode
? getNVPTXNumThreads(CGF)
- : Bld.CreateSub(getNVPTXNumThreads(CGF), getNVPTXWarpSize(CGF),
- "thread_limit");
+ : Bld.CreateNUWSub(getNVPTXNumThreads(CGF), getNVPTXWarpSize(CGF),
+ "thread_limit");
}
/// Get the thread id of the OMP master thread.
@@ -243,96 +609,295 @@ static llvm::Value *getMasterThreadID(CodeGenFunction &CGF) {
llvm::Value *NumThreads = getNVPTXNumThreads(CGF);
// We assume that the warp size is a power of 2.
- llvm::Value *Mask = Bld.CreateSub(getNVPTXWarpSize(CGF), Bld.getInt32(1));
+ llvm::Value *Mask = Bld.CreateNUWSub(getNVPTXWarpSize(CGF), Bld.getInt32(1));
- return Bld.CreateAnd(Bld.CreateSub(NumThreads, Bld.getInt32(1)),
+ return Bld.CreateAnd(Bld.CreateNUWSub(NumThreads, Bld.getInt32(1)),
Bld.CreateNot(Mask), "master_tid");
}
CGOpenMPRuntimeNVPTX::WorkerFunctionState::WorkerFunctionState(
- CodeGenModule &CGM)
- : WorkerFn(nullptr), CGFI(nullptr) {
+ CodeGenModule &CGM, SourceLocation Loc)
+ : WorkerFn(nullptr), CGFI(CGM.getTypes().arrangeNullaryFunction()),
+ Loc(Loc) {
createWorkerFunction(CGM);
}
void CGOpenMPRuntimeNVPTX::WorkerFunctionState::createWorkerFunction(
CodeGenModule &CGM) {
// Create an worker function with no arguments.
- CGFI = &CGM.getTypes().arrangeNullaryFunction();
WorkerFn = llvm::Function::Create(
- CGM.getTypes().GetFunctionType(*CGFI), llvm::GlobalValue::InternalLinkage,
- /* placeholder */ "_worker", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, WorkerFn, *CGFI);
+ CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
+ /*placeholder=*/"_worker", &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), WorkerFn, CGFI);
+ WorkerFn->setDoesNotRecurse();
+}
+
+CGOpenMPRuntimeNVPTX::ExecutionMode
+CGOpenMPRuntimeNVPTX::getExecutionMode() const {
+ return CurrentExecutionMode;
}
-bool CGOpenMPRuntimeNVPTX::isInSpmdExecutionMode() const {
- return CurrentExecutionMode == CGOpenMPRuntimeNVPTX::ExecutionMode::Spmd;
+static CGOpenMPRuntimeNVPTX::DataSharingMode
+getDataSharingMode(CodeGenModule &CGM) {
+ return CGM.getLangOpts().OpenMPCUDAMode ? CGOpenMPRuntimeNVPTX::CUDA
+ : CGOpenMPRuntimeNVPTX::Generic;
}
-static CGOpenMPRuntimeNVPTX::ExecutionMode
-getExecutionModeForDirective(CodeGenModule &CGM,
- const OMPExecutableDirective &D) {
+/// Checks if the \p Body is the \a CompoundStmt and returns its child statement
+/// iff there is only one.
+static const Stmt *getSingleCompoundChild(const Stmt *Body) {
+ if (const auto *C = dyn_cast<CompoundStmt>(Body))
+ if (C->size() == 1)
+ return C->body_front();
+ return Body;
+}
+
+/// Check if the parallel directive has an 'if' clause with non-constant or
+/// false condition. Also, check if the number of threads is strictly specified
+/// and run those directives in non-SPMD mode.
+static bool hasParallelIfNumThreadsClause(ASTContext &Ctx,
+ const OMPExecutableDirective &D) {
+ if (D.hasClausesOfKind<OMPNumThreadsClause>())
+ return true;
+ for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
+ OpenMPDirectiveKind NameModifier = C->getNameModifier();
+ if (NameModifier != OMPD_parallel && NameModifier != OMPD_unknown)
+ continue;
+ const Expr *Cond = C->getCondition();
+ bool Result;
+ if (!Cond->EvaluateAsBooleanCondition(Result, Ctx) || !Result)
+ return true;
+ }
+ return false;
+}
+
+/// Check for inner (nested) SPMD construct, if any
+static bool hasNestedSPMDDirective(ASTContext &Ctx,
+ const OMPExecutableDirective &D) {
+ const auto *CS = D.getInnermostCapturedStmt();
+ const auto *Body = CS->getCapturedStmt()->IgnoreContainers();
+ const Stmt *ChildStmt = getSingleCompoundChild(Body);
+
+ if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
+ switch (D.getDirectiveKind()) {
+ case OMPD_target:
+ if (isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NestedDir))
+ return true;
+ if (DKind == OMPD_teams || DKind == OMPD_teams_distribute) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers();
+ if (!Body)
+ return false;
+ ChildStmt = getSingleCompoundChild(Body);
+ if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ DKind = NND->getDirectiveKind();
+ if (isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NND))
+ return true;
+ if (DKind == OMPD_distribute) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers();
+ if (!Body)
+ return false;
+ ChildStmt = getSingleCompoundChild(Body);
+ if (!ChildStmt)
+ return false;
+ if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ DKind = NND->getDirectiveKind();
+ return isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NND);
+ }
+ }
+ }
+ }
+ return false;
+ case OMPD_target_teams:
+ if (isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NestedDir))
+ return true;
+ if (DKind == OMPD_distribute) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers();
+ if (!Body)
+ return false;
+ ChildStmt = getSingleCompoundChild(Body);
+ if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ DKind = NND->getDirectiveKind();
+ return isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NND);
+ }
+ }
+ return false;
+ case OMPD_target_teams_distribute:
+ return isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NestedDir);
+ case OMPD_target_simd:
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_unknown:
+ llvm_unreachable("Unexpected directive.");
+ }
+ }
+
+ return false;
+}
+
+static bool supportsSPMDExecutionMode(ASTContext &Ctx,
+ const OMPExecutableDirective &D) {
OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
switch (DirectiveKind) {
case OMPD_target:
case OMPD_target_teams:
- return CGOpenMPRuntimeNVPTX::ExecutionMode::Generic;
+ case OMPD_target_teams_distribute:
+ return hasNestedSPMDDirective(Ctx, D);
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.");
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ return !hasParallelIfNumThreadsClause(Ctx, D);
+ case OMPD_target_simd:
+ case OMPD_target_teams_distribute_simd:
+ return false;
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_unknown:
+ break;
}
- llvm_unreachable("Unsupported directive on NVPTX device.");
+ llvm_unreachable(
+ "Unknown programming model for OpenMP directive on NVPTX target.");
}
-void CGOpenMPRuntimeNVPTX::emitGenericKernel(const OMPExecutableDirective &D,
+void CGOpenMPRuntimeNVPTX::emitNonSPMDKernel(const OMPExecutableDirective &D,
StringRef ParentName,
llvm::Function *&OutlinedFn,
llvm::Constant *&OutlinedFnID,
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen) {
- ExecutionModeRAII ModeRAII(CurrentExecutionMode,
- CGOpenMPRuntimeNVPTX::ExecutionMode::Generic);
+ ExecutionModeRAII ModeRAII(CurrentExecutionMode, /*IsSPMD=*/false);
EntryFunctionState EST;
- WorkerFunctionState WST(CGM);
+ WorkerFunctionState WST(CGM, D.getLocStart());
Work.clear();
WrapperFunctionsMap.clear();
// Emit target region as a standalone region.
class NVPTXPrePostActionTy : public PrePostActionTy {
- CGOpenMPRuntimeNVPTX &RT;
CGOpenMPRuntimeNVPTX::EntryFunctionState &EST;
CGOpenMPRuntimeNVPTX::WorkerFunctionState &WST;
public:
- NVPTXPrePostActionTy(CGOpenMPRuntimeNVPTX &RT,
- CGOpenMPRuntimeNVPTX::EntryFunctionState &EST,
+ NVPTXPrePostActionTy(CGOpenMPRuntimeNVPTX::EntryFunctionState &EST,
CGOpenMPRuntimeNVPTX::WorkerFunctionState &WST)
- : RT(RT), EST(EST), WST(WST) {}
+ : EST(EST), WST(WST) {}
void Enter(CodeGenFunction &CGF) override {
- RT.emitGenericEntryHeader(CGF, EST, WST);
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitNonSPMDEntryHeader(CGF, EST, WST);
}
void Exit(CodeGenFunction &CGF) override {
- RT.emitGenericEntryFooter(CGF, EST);
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitNonSPMDEntryFooter(CGF, EST);
}
- } Action(*this, EST, WST);
+ } Action(EST, WST);
CodeGen.setAction(Action);
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
- // Create the worker function
- emitWorkerFunction(WST);
-
// Now change the name of the worker function to correspond to this target
// region's entry function.
- WST.WorkerFn->setName(OutlinedFn->getName() + "_worker");
+ WST.WorkerFn->setName(Twine(OutlinedFn->getName(), "_worker"));
+
+ // Create the worker function
+ emitWorkerFunction(WST);
}
// Setup NVPTX threads for master-worker OpenMP scheme.
-void CGOpenMPRuntimeNVPTX::emitGenericEntryHeader(CodeGenFunction &CGF,
+void CGOpenMPRuntimeNVPTX::emitNonSPMDEntryHeader(CodeGenFunction &CGF,
EntryFunctionState &EST,
WorkerFunctionState &WST) {
CGBuilderTy &Bld = CGF.Builder;
@@ -342,20 +907,22 @@ void CGOpenMPRuntimeNVPTX::emitGenericEntryHeader(CodeGenFunction &CGF,
llvm::BasicBlock *MasterBB = CGF.createBasicBlock(".master");
EST.ExitBB = CGF.createBasicBlock(".exit");
- auto *IsWorker =
+ llvm::Value *IsWorker =
Bld.CreateICmpULT(getNVPTXThreadID(CGF), getThreadLimit(CGF));
Bld.CreateCondBr(IsWorker, WorkerBB, MasterCheckBB);
CGF.EmitBlock(WorkerBB);
- emitCall(CGF, WST.WorkerFn);
+ emitCall(CGF, WST.Loc, WST.WorkerFn);
CGF.EmitBranch(EST.ExitBB);
CGF.EmitBlock(MasterCheckBB);
- auto *IsMaster =
+ llvm::Value *IsMaster =
Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF));
Bld.CreateCondBr(IsMaster, MasterBB, EST.ExitBB);
CGF.EmitBlock(MasterBB);
+ IsInTargetMasterThreadRegion = true;
+ // SEQUENTIAL (MASTER) REGION START
// First action in sequential region:
// Initialize the state of the OpenMP runtime library on the GPU.
// TODO: Optimize runtime initialization and pass in correct value.
@@ -363,10 +930,23 @@ void CGOpenMPRuntimeNVPTX::emitGenericEntryHeader(CodeGenFunction &CGF,
Bld.getInt16(/*RequiresOMPRuntime=*/1)};
CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_init), Args);
+
+ // For data sharing, we need to initialize the stack.
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack));
+
+ emitGenericVarsProlog(CGF, WST.Loc);
}
-void CGOpenMPRuntimeNVPTX::emitGenericEntryFooter(CodeGenFunction &CGF,
+void CGOpenMPRuntimeNVPTX::emitNonSPMDEntryFooter(CodeGenFunction &CGF,
EntryFunctionState &EST) {
+ IsInTargetMasterThreadRegion = false;
+ if (!CGF.HaveInsertPoint())
+ return;
+
+ emitGenericVarsEpilog(CGF);
+
if (!EST.ExitBB)
EST.ExitBB = CGF.createBasicBlock(".exit");
@@ -388,14 +968,13 @@ void CGOpenMPRuntimeNVPTX::emitGenericEntryFooter(CodeGenFunction &CGF,
EST.ExitBB = nullptr;
}
-void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D,
+void CGOpenMPRuntimeNVPTX::emitSPMDKernel(const OMPExecutableDirective &D,
StringRef ParentName,
llvm::Function *&OutlinedFn,
llvm::Constant *&OutlinedFnID,
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen) {
- ExecutionModeRAII ModeRAII(CurrentExecutionMode,
- CGOpenMPRuntimeNVPTX::ExecutionMode::Spmd);
+ ExecutionModeRAII ModeRAII(CurrentExecutionMode, /*IsSPMD=*/true);
EntryFunctionState EST;
// Emit target region as a standalone region.
@@ -410,10 +989,10 @@ void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D,
const OMPExecutableDirective &D)
: RT(RT), EST(EST), D(D) {}
void Enter(CodeGenFunction &CGF) override {
- RT.emitSpmdEntryHeader(CGF, EST, D);
+ RT.emitSPMDEntryHeader(CGF, EST, D);
}
void Exit(CodeGenFunction &CGF) override {
- RT.emitSpmdEntryFooter(CGF, EST);
+ RT.emitSPMDEntryFooter(CGF, EST);
}
} Action(*this, EST, D);
CodeGen.setAction(Action);
@@ -421,10 +1000,10 @@ void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D,
IsOffloadEntry, CodeGen);
}
-void CGOpenMPRuntimeNVPTX::emitSpmdEntryHeader(
+void CGOpenMPRuntimeNVPTX::emitSPMDEntryHeader(
CodeGenFunction &CGF, EntryFunctionState &EST,
const OMPExecutableDirective &D) {
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
// Setup BBs in entry function.
llvm::BasicBlock *ExecuteBB = CGF.createBasicBlock(".execute");
@@ -433,18 +1012,30 @@ void CGOpenMPRuntimeNVPTX::emitSpmdEntryHeader(
// Initialize the OMP state in the runtime; called by all active threads.
// TODO: Set RequiresOMPRuntime and RequiresDataSharing parameters
// based on code analysis of the target region.
- llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSpmdExecutionMode=*/true),
+ llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSPMDExecutionMode=*/true),
/*RequiresOMPRuntime=*/Bld.getInt16(1),
/*RequiresDataSharing=*/Bld.getInt16(1)};
CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_spmd_kernel_init), Args);
+
+ // For data sharing, we need to initialize the stack.
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd));
+
CGF.EmitBranch(ExecuteBB);
CGF.EmitBlock(ExecuteBB);
+
+ IsInTargetMasterThreadRegion = true;
}
-void CGOpenMPRuntimeNVPTX::emitSpmdEntryFooter(CodeGenFunction &CGF,
+void CGOpenMPRuntimeNVPTX::emitSPMDEntryFooter(CodeGenFunction &CGF,
EntryFunctionState &EST) {
+ IsInTargetMasterThreadRegion = false;
+ if (!CGF.HaveInsertPoint())
+ return;
+
if (!EST.ExitBB)
EST.ExitBB = CGF.createBasicBlock(".exit");
@@ -468,19 +1059,21 @@ void CGOpenMPRuntimeNVPTX::emitSpmdEntryFooter(CodeGenFunction &CGF,
// 'generic', the runtime reserves one warp for the master, otherwise, all
// warps participate in parallel work.
static void setPropertyExecutionMode(CodeGenModule &CGM, StringRef Name,
- CGOpenMPRuntimeNVPTX::ExecutionMode Mode) {
- (void)new llvm::GlobalVariable(
- CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
- llvm::GlobalValue::WeakAnyLinkage,
- llvm::ConstantInt::get(CGM.Int8Ty, Mode), Name + Twine("_exec_mode"));
+ bool Mode) {
+ auto *GVMode =
+ new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::WeakAnyLinkage,
+ llvm::ConstantInt::get(CGM.Int8Ty, Mode ? 0 : 1),
+ Twine(Name, "_exec_mode"));
+ CGM.addCompilerUsedGlobal(GVMode);
}
void CGOpenMPRuntimeNVPTX::emitWorkerFunction(WorkerFunctionState &WST) {
ASTContext &Ctx = CGM.getContext();
CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, WST.WorkerFn, *WST.CGFI, {});
+ CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, WST.WorkerFn, WST.CGFI, {},
+ WST.Loc, WST.Loc);
emitWorkerLoop(CGF, WST);
CGF.FinishFunction();
}
@@ -519,19 +1112,16 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
CGF.InitTempAlloca(ExecStatus, Bld.getInt8(/*C=*/0));
CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy));
- // Set up shared arguments
- Address SharedArgs =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrPtrTy, "shared_args");
// TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {WorkFn.getPointer(), SharedArgs.getPointer(),
+ llvm::Value *Args[] = {WorkFn.getPointer(),
/*RequiresOMPRuntime=*/Bld.getInt16(1)};
llvm::Value *Ret = CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_parallel), Args);
Bld.CreateStore(Bld.CreateZExt(Ret, CGF.Int8Ty), ExecStatus);
// On termination condition (workid == 0), exit loop.
- llvm::Value *ShouldTerminate =
- Bld.CreateIsNull(Bld.CreateLoad(WorkFn), "should_terminate");
+ llvm::Value *WorkID = Bld.CreateLoad(WorkFn);
+ llvm::Value *ShouldTerminate = Bld.CreateIsNull(WorkID, "should_terminate");
Bld.CreateCondBr(ShouldTerminate, ExitBB, SelectWorkersBB);
// Activate requested workers.
@@ -543,13 +1133,10 @@ 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) {
+ for (llvm::Function *W : Work) {
// Try to match this outlined function.
- auto *ID = Bld.CreatePointerBitCastOrAddrSpaceCast(W, CGM.Int8PtrTy);
+ llvm::Value *ID = Bld.CreatePointerBitCastOrAddrSpaceCast(W, CGM.Int8PtrTy);
llvm::Value *WorkFnMatch =
Bld.CreateICmpEQ(Bld.CreateLoad(WorkFn), ID, "work_match");
@@ -562,23 +1149,33 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
CGF.EmitBlock(ExecuteFNBB);
// Insert call to work function via shared wrapper. The shared
- // wrapper takes exactly three arguments:
+ // wrapper takes two 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()});
+ // - the thread ID;
+ emitCall(CGF, WST.Loc, W,
+ {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)});
// Go to end of parallel region.
CGF.EmitBranch(TerminateBB);
CGF.EmitBlock(CheckNextBB);
}
+ // Default case: call to outlined function through pointer if the target
+ // region makes a declare target call that may contain an orphaned parallel
+ // directive.
+ auto *ParallelFnTy =
+ llvm::FunctionType::get(CGM.VoidTy, {CGM.Int16Ty, CGM.Int32Ty},
+ /*isVarArg=*/false)
+ ->getPointerTo();
+ llvm::Value *WorkFnCast = Bld.CreateBitCast(WorkID, ParallelFnTy);
+ // Insert call to work function via shared wrapper. The shared
+ // wrapper takes two arguments:
+ // - the parallelism level;
+ // - the thread ID;
+ emitCall(CGF, WST.Loc, WorkFnCast,
+ {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)});
+ // Go to end of parallel region.
+ CGF.EmitBranch(TerminateBB);
// Signal end of parallel region.
CGF.EmitBlock(TerminateBB);
@@ -597,7 +1194,7 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
CGF.EmitBlock(ExitBB);
}
-/// \brief Returns specified OpenMP runtime function for the current OpenMP
+/// Returns specified OpenMP runtime function for the current OpenMP
/// implementation. Specialized for the NVPTX device.
/// \param Function OpenMP runtime function.
/// \return Specified function.
@@ -609,7 +1206,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
// Build void __kmpc_kernel_init(kmp_int32 thread_limit, int16_t
// RequiresOMPRuntime);
llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_init");
break;
@@ -617,7 +1214,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
case OMPRTL_NVPTX__kmpc_kernel_deinit: {
// Build void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized);
llvm::Type *TypeParams[] = {CGM.Int16Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_deinit");
break;
@@ -626,44 +1223,40 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
// Build void __kmpc_spmd_kernel_init(kmp_int32 thread_limit,
// int16_t RequiresOMPRuntime, int16_t RequiresDataSharing);
llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty, CGM.Int16Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_init");
break;
}
case OMPRTL_NVPTX__kmpc_spmd_kernel_deinit: {
// Build void __kmpc_spmd_kernel_deinit();
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_deinit");
break;
}
case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: {
/// Build void __kmpc_kernel_prepare_parallel(
- /// void *outlined_function, void ***args, kmp_int32 nArgs, int16_t
- /// IsOMPRuntimeInitialized);
- llvm::Type *TypeParams[] = {CGM.Int8PtrTy,
- CGM.Int8PtrPtrTy->getPointerTo(0), CGM.Int32Ty,
- CGM.Int16Ty};
- llvm::FunctionType *FnTy =
+ /// void *outlined_function, int16_t IsOMPRuntimeInitialized);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrTy, CGM.Int16Ty};
+ auto *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, void
- /// ***args, int16_t IsOMPRuntimeInitialized);
- llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy,
- CGM.Int8PtrPtrTy->getPointerTo(0), CGM.Int16Ty};
+ /// Build bool __kmpc_kernel_parallel(void **outlined_function,
+ /// int16_t IsOMPRuntimeInitialized);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy, CGM.Int16Ty};
llvm::Type *RetTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(RetTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_parallel");
break;
}
case OMPRTL_NVPTX__kmpc_kernel_end_parallel: {
/// Build void __kmpc_kernel_end_parallel();
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_end_parallel");
break;
@@ -672,7 +1265,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
// Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
// global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
break;
@@ -681,7 +1274,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
// Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
// global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
break;
@@ -690,7 +1283,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
// Build int32_t __kmpc_shuffle_int32(int32_t element,
// int16_t lane_offset, int16_t warp_size);
llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty, CGM.Int16Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_shuffle_int32");
break;
@@ -699,7 +1292,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
// Build int64_t __kmpc_shuffle_int64(int64_t element,
// int16_t lane_offset, int16_t warp_size);
llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int16Ty, CGM.Int16Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_shuffle_int64");
break;
@@ -725,12 +1318,39 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
CGM.VoidPtrTy,
ShuffleReduceFnTy->getPointerTo(),
InterWarpCopyFnTy->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
FnTy, /*Name=*/"__kmpc_nvptx_parallel_reduce_nowait");
break;
}
+ case OMPRTL_NVPTX__kmpc_simd_reduce_nowait: {
+ // Build int32_t kmpc_nvptx_simd_reduce_nowait(kmp_int32 global_tid,
+ // kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
+ // void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
+ // lane_offset, int16_t Algorithm Version),
+ // void (*kmp_InterWarpCopyFctPtr)(void* src, int warp_num));
+ llvm::Type *ShuffleReduceTypeParams[] = {CGM.VoidPtrTy, CGM.Int16Ty,
+ CGM.Int16Ty, CGM.Int16Ty};
+ auto *ShuffleReduceFnTy =
+ llvm::FunctionType::get(CGM.VoidTy, ShuffleReduceTypeParams,
+ /*isVarArg=*/false);
+ llvm::Type *InterWarpCopyTypeParams[] = {CGM.VoidPtrTy, CGM.Int32Ty};
+ auto *InterWarpCopyFnTy =
+ llvm::FunctionType::get(CGM.VoidTy, InterWarpCopyTypeParams,
+ /*isVarArg=*/false);
+ llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ CGM.Int32Ty,
+ CGM.SizeTy,
+ CGM.VoidPtrTy,
+ ShuffleReduceFnTy->getPointerTo(),
+ InterWarpCopyFnTy->getPointerTo()};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(
+ FnTy, /*Name=*/"__kmpc_nvptx_simd_reduce_nowait");
+ break;
+ }
case OMPRTL_NVPTX__kmpc_teams_reduce_nowait: {
// Build int32_t __kmpc_nvptx_teams_reduce_nowait(int32_t global_tid,
// int32_t num_vars, size_t reduce_size, void *reduce_data,
@@ -768,7 +1388,7 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
InterWarpCopyFnTy->getPointerTo(),
CopyToScratchpadFnTy->getPointerTo(),
LoadReduceFnTy->getPointerTo()};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
FnTy, /*Name=*/"__kmpc_nvptx_teams_reduce_nowait");
@@ -777,32 +1397,103 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
case OMPRTL_NVPTX__kmpc_end_reduce_nowait: {
// Build __kmpc_end_reduce_nowait(kmp_int32 global_tid);
llvm::Type *TypeParams[] = {CGM.Int32Ty};
- llvm::FunctionType *FnTy =
+ auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
FnTy, /*Name=*/"__kmpc_nvptx_end_reduce_nowait");
break;
}
+ case OMPRTL_NVPTX__kmpc_data_sharing_init_stack: {
+ /// Build void __kmpc_data_sharing_init_stack();
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd: {
+ /// Build void __kmpc_data_sharing_init_stack_spmd();
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack_spmd");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_data_sharing_push_stack: {
+ // Build void *__kmpc_data_sharing_push_stack(size_t size,
+ // int16_t UseSharedMemory);
+ llvm::Type *TypeParams[] = {CGM.SizeTy, CGM.Int16Ty};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(
+ FnTy, /*Name=*/"__kmpc_data_sharing_push_stack");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_data_sharing_pop_stack: {
+ // Build void __kmpc_data_sharing_pop_stack(void *a);
+ llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy,
+ /*Name=*/"__kmpc_data_sharing_pop_stack");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_begin_sharing_variables: {
+ /// Build void __kmpc_begin_sharing_variables(void ***args,
+ /// size_t n_args);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy->getPointerTo(), CGM.SizeTy};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_begin_sharing_variables");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_end_sharing_variables: {
+ /// Build void __kmpc_end_sharing_variables();
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_sharing_variables");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_get_shared_variables: {
+ /// Build void __kmpc_get_shared_variables(void ***GlobalArgs);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy->getPointerTo()};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_get_shared_variables");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_parallel_level: {
+ // Build uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.Int16Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_parallel_level");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_is_spmd_exec_mode: {
+ // Build int8_t __kmpc_is_spmd_exec_mode();
+ auto *FnTy = llvm::FunctionType::get(CGM.Int8Ty, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_is_spmd_exec_mode");
+ break;
+ }
}
return RTLFn;
}
void CGOpenMPRuntimeNVPTX::createOffloadEntry(llvm::Constant *ID,
llvm::Constant *Addr,
- uint64_t Size, int32_t) {
- auto *F = dyn_cast<llvm::Function>(Addr);
+ uint64_t Size, int32_t,
+ llvm::GlobalValue::LinkageTypes) {
// TODO: Add support for global variables on the device after declare target
// support.
- if (!F)
+ if (!isa<llvm::Function>(Addr))
return;
- llvm::Module *M = F->getParent();
- llvm::LLVMContext &Ctx = M->getContext();
+ llvm::Module &M = CGM.getModule();
+ llvm::LLVMContext &Ctx = CGM.getLLVMContext();
// Get "nvvm.annotations" metadata node
- llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata("nvvm.annotations");
+ llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("nvvm.annotations");
llvm::Metadata *MDVals[] = {
- llvm::ConstantAsMetadata::get(F), llvm::MDString::get(Ctx, "kernel"),
+ llvm::ConstantAsMetadata::get(Addr), llvm::MDString::get(Ctx, "kernel"),
llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 1))};
// Append metadata to nvvm.annotations
@@ -818,27 +1509,19 @@ void CGOpenMPRuntimeNVPTX::emitTargetOutlinedFunction(
assert(!ParentName.empty() && "Invalid target region parent name!");
- CGOpenMPRuntimeNVPTX::ExecutionMode Mode =
- getExecutionModeForDirective(CGM, D);
- switch (Mode) {
- case CGOpenMPRuntimeNVPTX::ExecutionMode::Generic:
- emitGenericKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
- CodeGen);
- break;
- case CGOpenMPRuntimeNVPTX::ExecutionMode::Spmd:
- emitSpmdKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
+ bool Mode = supportsSPMDExecutionMode(CGM.getContext(), D);
+ if (Mode)
+ emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
CodeGen);
- break;
- case CGOpenMPRuntimeNVPTX::ExecutionMode::Unknown:
- llvm_unreachable(
- "Unknown programming model for OpenMP directive on NVPTX target.");
- }
+ else
+ emitNonSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
+ CodeGen);
setPropertyExecutionMode(CGM, OutlinedFn->getName(), Mode);
}
CGOpenMPRuntimeNVPTX::CGOpenMPRuntimeNVPTX(CodeGenModule &CGM)
- : CGOpenMPRuntime(CGM), CurrentExecutionMode(ExecutionMode::Unknown) {
+ : CGOpenMPRuntime(CGM, "_", "$") {
if (!CGM.getLangOpts().OpenMPIsDevice)
llvm_unreachable("OpenMP NVPTX can only handle device code.");
}
@@ -846,9 +1529,8 @@ CGOpenMPRuntimeNVPTX::CGOpenMPRuntimeNVPTX(CodeGenModule &CGM)
void CGOpenMPRuntimeNVPTX::emitProcBindClause(CodeGenFunction &CGF,
OpenMPProcBindClauseKind ProcBind,
SourceLocation Loc) {
- // Do nothing in case of Spmd mode and L0 parallel.
- // TODO: If in Spmd mode and L1 parallel emit the clause.
- if (isInSpmdExecutionMode())
+ // Do nothing in case of SPMD mode and L0 parallel.
+ if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD)
return;
CGOpenMPRuntime::emitProcBindClause(CGF, ProcBind, Loc);
@@ -857,9 +1539,8 @@ void CGOpenMPRuntimeNVPTX::emitProcBindClause(CodeGenFunction &CGF,
void CGOpenMPRuntimeNVPTX::emitNumThreadsClause(CodeGenFunction &CGF,
llvm::Value *NumThreads,
SourceLocation Loc) {
- // Do nothing in case of Spmd mode and L0 parallel.
- // TODO: If in Spmd mode and L1 parallel emit the clause.
- if (isInSpmdExecutionMode())
+ // Do nothing in case of SPMD mode and L0 parallel.
+ if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD)
return;
CGOpenMPRuntime::emitNumThreadsClause(CGF, NumThreads, Loc);
@@ -873,13 +1554,33 @@ void CGOpenMPRuntimeNVPTX::emitNumTeamsClause(CodeGenFunction &CGF,
llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ // Emit target region as a standalone region.
+ class NVPTXPrePostActionTy : public PrePostActionTy {
+ bool &IsInParallelRegion;
+ bool PrevIsInParallelRegion;
- auto *OutlinedFun = cast<llvm::Function>(
- CGOpenMPRuntime::emitParallelOutlinedFunction(
+ public:
+ NVPTXPrePostActionTy(bool &IsInParallelRegion)
+ : IsInParallelRegion(IsInParallelRegion) {}
+ void Enter(CodeGenFunction &CGF) override {
+ PrevIsInParallelRegion = IsInParallelRegion;
+ IsInParallelRegion = true;
+ }
+ void Exit(CodeGenFunction &CGF) override {
+ IsInParallelRegion = PrevIsInParallelRegion;
+ }
+ } Action(IsInParallelRegion);
+ CodeGen.setAction(Action);
+ bool PrevIsInTargetMasterThreadRegion = IsInTargetMasterThreadRegion;
+ IsInTargetMasterThreadRegion = false;
+ auto *OutlinedFun =
+ cast<llvm::Function>(CGOpenMPRuntime::emitParallelOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen));
- if (!isInSpmdExecutionMode()) {
+ IsInTargetMasterThreadRegion = PrevIsInTargetMasterThreadRegion;
+ if (getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD &&
+ !IsInParallelRegion) {
llvm::Function *WrapperFun =
- createDataSharingWrapper(OutlinedFun, D);
+ createParallelDataSharingWrapper(OutlinedFun, D);
WrapperFunctionsMap[OutlinedFun] = WrapperFun;
}
@@ -889,7 +1590,24 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ SourceLocation Loc = D.getLocStart();
+
+ // Emit target region as a standalone region.
+ class NVPTXPrePostActionTy : public PrePostActionTy {
+ SourceLocation &Loc;
+ public:
+ NVPTXPrePostActionTy(SourceLocation &Loc) : Loc(Loc) {}
+ void Enter(CodeGenFunction &CGF) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsProlog(CGF, Loc);
+ }
+ void Exit(CodeGenFunction &CGF) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsEpilog(CGF);
+ }
+ } Action(Loc);
+ CodeGen.setAction(Action);
llvm::Value *OutlinedFunVal = CGOpenMPRuntime::emitTeamsOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen);
llvm::Function *OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
@@ -900,6 +1618,119 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
return OutlinedFun;
}
+void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic)
+ return;
+
+ CGBuilderTy &Bld = CGF.Builder;
+
+ const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
+ if (I == FunctionGlobalizedDecls.end())
+ return;
+ if (const RecordDecl *GlobalizedVarsRecord = I->getSecond().GlobalRecord) {
+ QualType RecTy = CGM.getContext().getRecordType(GlobalizedVarsRecord);
+
+ // Recover pointer to this function's global record. The runtime will
+ // handle the specifics of the allocation of the memory.
+ // Use actual memory size of the record including the padding
+ // for alignment purposes.
+ unsigned Alignment =
+ CGM.getContext().getTypeAlignInChars(RecTy).getQuantity();
+ unsigned GlobalRecordSize =
+ CGM.getContext().getTypeSizeInChars(RecTy).getQuantity();
+ GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment);
+ // TODO: allow the usage of shared memory to be controlled by
+ // the user, for now, default to global.
+ llvm::Value *GlobalRecordSizeArg[] = {
+ llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize),
+ CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
+ llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_push_stack),
+ GlobalRecordSizeArg);
+ llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, CGF.ConvertTypeForMem(RecTy)->getPointerTo());
+ LValue Base =
+ CGF.MakeNaturalAlignPointeeAddrLValue(GlobalRecCastAddr, RecTy);
+ I->getSecond().GlobalRecordAddr = GlobalRecValue;
+
+ // Emit the "global alloca" which is a GEP from the global declaration
+ // record using the pointer returned by the runtime.
+ for (auto &Rec : I->getSecond().LocalVarData) {
+ bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
+ llvm::Value *ParValue;
+ if (EscapedParam) {
+ const auto *VD = cast<VarDecl>(Rec.first);
+ LValue ParLVal =
+ CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
+ ParValue = CGF.EmitLoadOfScalar(ParLVal, Loc);
+ }
+ const FieldDecl *FD = Rec.second.first;
+ LValue VarAddr = CGF.EmitLValueForField(Base, FD);
+ Rec.second.second = VarAddr.getAddress();
+ if (EscapedParam) {
+ const auto *VD = cast<VarDecl>(Rec.first);
+ CGF.EmitStoreOfScalar(ParValue, VarAddr);
+ I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress());
+ }
+ }
+ }
+ for (const ValueDecl *VD : I->getSecond().EscapedVariableLengthDecls) {
+ // Recover pointer to this function's global record. The runtime will
+ // handle the specifics of the allocation of the memory.
+ // Use actual memory size of the record including the padding
+ // for alignment purposes.
+ CGBuilderTy &Bld = CGF.Builder;
+ llvm::Value *Size = CGF.getTypeSize(VD->getType());
+ CharUnits Align = CGM.getContext().getDeclAlign(VD);
+ Size = Bld.CreateNUWAdd(
+ Size, llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity() - 1));
+ llvm::Value *AlignVal =
+ llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity());
+ Size = Bld.CreateUDiv(Size, AlignVal);
+ Size = Bld.CreateNUWMul(Size, AlignVal);
+ // TODO: allow the usage of shared memory to be controlled by
+ // the user, for now, default to global.
+ llvm::Value *GlobalRecordSizeArg[] = {
+ Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
+ llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_push_stack),
+ GlobalRecordSizeArg);
+ llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, CGF.ConvertTypeForMem(VD->getType())->getPointerTo());
+ LValue Base = CGF.MakeAddrLValue(GlobalRecCastAddr, VD->getType(),
+ CGM.getContext().getDeclAlign(VD),
+ AlignmentSource::Decl);
+ I->getSecond().MappedParams->setVarAddr(CGF, cast<VarDecl>(VD),
+ Base.getAddress());
+ I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(GlobalRecValue);
+ }
+ I->getSecond().MappedParams->apply(CGF);
+}
+
+void CGOpenMPRuntimeNVPTX::emitGenericVarsEpilog(CodeGenFunction &CGF) {
+ if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic)
+ return;
+
+ const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
+ if (I != FunctionGlobalizedDecls.end()) {
+ I->getSecond().MappedParams->restore(CGF);
+ if (!CGF.HaveInsertPoint())
+ return;
+ for (llvm::Value *Addr :
+ llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) {
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
+ Addr);
+ }
+ if (I->getSecond().GlobalRecordAddr) {
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
+ I->getSecond().GlobalRecordAddr);
+ }
+ }
+}
+
void CGOpenMPRuntimeNVPTX::emitTeamsCall(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
SourceLocation Loc,
@@ -908,12 +1739,12 @@ void CGOpenMPRuntimeNVPTX::emitTeamsCall(CodeGenFunction &CGF,
if (!CGF.HaveInsertPoint())
return;
- Address ZeroAddr =
- CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
- /*Name*/ ".zero.addr");
+ Address ZeroAddr = CGF.CreateMemTemp(
+ CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
+ /*Name*/ ".zero.addr");
CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(ZeroAddr.getPointer());
+ OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer());
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
@@ -925,66 +1756,102 @@ void CGOpenMPRuntimeNVPTX::emitParallelCall(
if (!CGF.HaveInsertPoint())
return;
- if (isInSpmdExecutionMode())
- emitSpmdParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond);
+ if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD)
+ emitSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond);
else
- emitGenericParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond);
+ emitNonSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond);
}
-void CGOpenMPRuntimeNVPTX::emitGenericParallelCall(
+void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
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, WFn, &CapturedVars](CodeGenFunction &CGF,
- PrePostActionTy &) {
- CGBuilderTy &Bld = CGF.Builder;
+ Address ZeroAddr = CGF.CreateMemTemp(CGF.getContext().getIntTypeForBitwidth(
+ /*DestWidth=*/32, /*Signed=*/1),
+ ".zero.addr");
+ CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
+ // ThreadId for serialized parallels is 0.
+ Address ThreadIDAddr = ZeroAddr;
+ auto &&CodeGen = [this, Fn, CapturedVars, Loc, ZeroAddr, &ThreadIDAddr](
+ CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
+
+ llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
+ OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
+ OutlinedFnArgs.push_back(ZeroAddr.getPointer());
+ OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
+ emitOutlinedFunctionCall(CGF, Loc, Fn, OutlinedFnArgs);
+ };
+ auto &&SeqGen = [this, &CodeGen, Loc](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+
+ RegionCodeGenTy RCG(CodeGen);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ llvm::Value *Args[] = {RTLoc, ThreadID};
+
+ NVPTXActionTy Action(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_serialized_parallel),
+ Args,
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_serialized_parallel),
+ Args);
+ RCG.setAction(Action);
+ RCG(CGF);
+ };
+ auto &&L0ParallelGen = [this, CapturedVars, Fn](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
+ CGBuilderTy &Bld = CGF.Builder;
+ llvm::Function *WFn = WrapperFunctionsMap[Fn];
+ assert(WFn && "Wrapper function does not exist!");
llvm::Value *ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy);
+ // Prepare for parallel region. Indicate the outlined function.
+ llvm::Value *Args[] = {ID, /*RequiresOMPRuntime=*/Bld.getInt16(1)};
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
+ Args);
+
+ // Create a private scope that will globalize the arguments
+ // passed from the outside of the target region.
+ CodeGenFunction::OMPPrivateScope PrivateArgScope(CGF);
+
+ // There's somehting to share.
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");
+ CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "shared_arg_refs");
llvm::Value *SharedArgsPtr = SharedArgs.getPointer();
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {ID, SharedArgsPtr,
- Bld.getInt32(CapturedVars.size()),
- /*RequiresOMPRuntime=*/Bld.getInt16(1)};
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
- Args);
+ llvm::Value *DataSharingArgs[] = {
+ SharedArgsPtr,
+ llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())};
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_begin_sharing_variables),
+ DataSharingArgs);
+ // Store variable address in a list of references to pass to workers.
unsigned Idx = 0;
ASTContext &Ctx = CGF.getContext();
+ Address SharedArgListAddress = CGF.EmitLoadOfPointer(
+ SharedArgs, Ctx.getPointerType(Ctx.getPointerType(Ctx.VoidPtrTy))
+ .castAs<PointerType>());
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);
+ Address Dst = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx,
+ CGF.getPointerSize());
+ llvm::Value *PtrV;
+ if (V->getType()->isIntegerTy())
+ PtrV = Bld.CreateIntToPtr(V, CGF.VoidPtrTy);
+ else
+ PtrV = Bld.CreatePointerBitCastOrAddrSpaceCast(V, CGF.VoidPtrTy);
CGF.EmitStoreOfScalar(PtrV, Dst, /*Volatile=*/false,
- Ctx.getPointerType(Ctx.VoidPtrTy));
- Idx++;
+ Ctx.getPointerType(Ctx.VoidPtrTy));
+ ++Idx;
}
- } else {
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {
- ID, llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy->getPointerTo(0)),
- /*nArgs=*/Bld.getInt32(0), /*RequiresOMPRuntime=*/Bld.getInt16(1)};
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
- Args);
}
// Activate workers. This barrier is used by the master to signal
@@ -999,96 +1866,332 @@ void CGOpenMPRuntimeNVPTX::emitGenericParallelCall(
// The master waits at this barrier until all workers are done.
syncCTAThreads(CGF);
+ if (!CapturedVars.empty())
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_sharing_variables));
+
// Remember for post-processing in worker loop.
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, Loc](CodeGenFunction &CGF,
- PrePostActionTy &) {
- auto &&CodeGen = [this, Fn, &CapturedVars, Loc](CodeGenFunction &CGF,
- PrePostActionTy &Action) {
- Action.Enter(CGF);
-
- llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
- OutlinedFnArgs.push_back(
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
- OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- emitOutlinedFunctionCall(CGF, Loc, Fn, OutlinedFnArgs);
- };
-
+ auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen, &CodeGen,
+ &ThreadIDAddr](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
RegionCodeGenTy RCG(CodeGen);
- NVPTXActionTy Action(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_serialized_parallel),
- Args,
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_serialized_parallel),
- Args);
- RCG.setAction(Action);
- RCG(CGF);
+ if (IsInParallelRegion) {
+ SeqGen(CGF, Action);
+ } else if (IsInTargetMasterThreadRegion) {
+ L0ParallelGen(CGF, Action);
+ } else if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_NonSPMD) {
+ RCG(CGF);
+ } else {
+ // Check for master and then parallelism:
+ // if (__kmpc_is_spmd_exec_mode() || __kmpc_parallel_level(loc, gtid)) {
+ // Serialized execution.
+ // } else if (master) {
+ // Worker call.
+ // } else {
+ // Outlined function call.
+ // }
+ CGBuilderTy &Bld = CGF.Builder;
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
+ llvm::BasicBlock *SeqBB = CGF.createBasicBlock(".sequential");
+ llvm::BasicBlock *ParallelCheckBB = CGF.createBasicBlock(".parcheck");
+ llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck");
+ llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode)));
+ Bld.CreateCondBr(IsSPMD, SeqBB, ParallelCheckBB);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(ParallelCheckBB);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ llvm::Value *PL = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_level),
+ {RTLoc, ThreadID});
+ llvm::Value *Res = Bld.CreateIsNotNull(PL);
+ Bld.CreateCondBr(Res, SeqBB, MasterCheckBB);
+ CGF.EmitBlock(SeqBB);
+ SeqGen(CGF, Action);
+ CGF.EmitBranch(ExitBB);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(MasterCheckBB);
+ llvm::BasicBlock *MasterThenBB = CGF.createBasicBlock("master.then");
+ llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
+ llvm::Value *IsMaster =
+ Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF));
+ Bld.CreateCondBr(IsMaster, MasterThenBB, ElseBlock);
+ CGF.EmitBlock(MasterThenBB);
+ L0ParallelGen(CGF, Action);
+ CGF.EmitBranch(ExitBB);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(ElseBlock);
+ // In the worker need to use the real thread id.
+ ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
+ RCG(CGF);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ // Emit the continuation block for code after the if.
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+ }
};
- if (IfCond)
- emitOMPIfClause(CGF, IfCond, L0ParallelGen, SeqGen);
- else {
+ if (IfCond) {
+ emitOMPIfClause(CGF, IfCond, LNParallelGen, SeqGen);
+ } else {
CodeGenFunction::RunCleanupsScope Scope(CGF);
- RegionCodeGenTy ThenRCG(L0ParallelGen);
+ RegionCodeGenTy ThenRCG(LNParallelGen);
ThenRCG(CGF);
}
}
-void CGOpenMPRuntimeNVPTX::emitSpmdParallelCall(
+void CGOpenMPRuntimeNVPTX::emitSPMDParallelCall(
CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) {
// Just call the outlined function to execute the parallel region.
// OutlinedFn(&GTid, &zero, CapturedStruct);
//
- // TODO: Do something with IfCond when support for the 'if' clause
- // is added on Spmd target directives.
llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
- OutlinedFnArgs.push_back(
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
- OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
+
+ Address ZeroAddr = CGF.CreateMemTemp(CGF.getContext().getIntTypeForBitwidth(
+ /*DestWidth=*/32, /*Signed=*/1),
+ ".zero.addr");
+ CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
+ // ThreadId for serialized parallels is 0.
+ Address ThreadIDAddr = ZeroAddr;
+ auto &&CodeGen = [this, OutlinedFn, CapturedVars, Loc, ZeroAddr,
+ &ThreadIDAddr](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+
+ llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
+ OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
+ OutlinedFnArgs.push_back(ZeroAddr.getPointer());
+ OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
+ emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
+ };
+ auto &&SeqGen = [this, &CodeGen, Loc](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+
+ RegionCodeGenTy RCG(CodeGen);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ llvm::Value *Args[] = {RTLoc, ThreadID};
+
+ NVPTXActionTy Action(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_serialized_parallel),
+ Args,
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_serialized_parallel),
+ Args);
+ RCG.setAction(Action);
+ RCG(CGF);
+ };
+
+ if (IsInTargetMasterThreadRegion) {
+ // In the worker need to use the real thread id.
+ ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
+ RegionCodeGenTy RCG(CodeGen);
+ RCG(CGF);
+ } else {
+ // If we are not in the target region, it is definitely L2 parallelism or
+ // more, because for SPMD mode we always has L1 parallel level, sowe don't
+ // need to check for orphaned directives.
+ RegionCodeGenTy RCG(SeqGen);
+ RCG(CGF);
+ }
+}
+
+void CGOpenMPRuntimeNVPTX::emitCriticalRegion(
+ CodeGenFunction &CGF, StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
+ const Expr *Hint) {
+ llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.critical.loop");
+ llvm::BasicBlock *TestBB = CGF.createBasicBlock("omp.critical.test");
+ llvm::BasicBlock *SyncBB = CGF.createBasicBlock("omp.critical.sync");
+ llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.critical.body");
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.critical.exit");
+
+ // Fetch team-local id of the thread.
+ llvm::Value *ThreadID = getNVPTXThreadID(CGF);
+
+ // Get the width of the team.
+ llvm::Value *TeamWidth = getNVPTXNumThreads(CGF);
+
+ // Initialize the counter variable for the loop.
+ QualType Int32Ty =
+ CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/0);
+ Address Counter = CGF.CreateMemTemp(Int32Ty, "critical_counter");
+ LValue CounterLVal = CGF.MakeAddrLValue(Counter, Int32Ty);
+ CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty), CounterLVal,
+ /*isInit=*/true);
+
+ // Block checks if loop counter exceeds upper bound.
+ CGF.EmitBlock(LoopBB);
+ llvm::Value *CounterVal = CGF.EmitLoadOfScalar(CounterLVal, Loc);
+ llvm::Value *CmpLoopBound = CGF.Builder.CreateICmpSLT(CounterVal, TeamWidth);
+ CGF.Builder.CreateCondBr(CmpLoopBound, TestBB, ExitBB);
+
+ // Block tests which single thread should execute region, and which threads
+ // should go straight to synchronisation point.
+ CGF.EmitBlock(TestBB);
+ CounterVal = CGF.EmitLoadOfScalar(CounterLVal, Loc);
+ llvm::Value *CmpThreadToCounter =
+ CGF.Builder.CreateICmpEQ(ThreadID, CounterVal);
+ CGF.Builder.CreateCondBr(CmpThreadToCounter, BodyBB, SyncBB);
+
+ // Block emits the body of the critical region.
+ CGF.EmitBlock(BodyBB);
+
+ // Output the critical statement.
+ CriticalOpGen(CGF);
+
+ // After the body surrounded by the critical region, the single executing
+ // thread will jump to the synchronisation point.
+ // Block waits for all threads in current team to finish then increments the
+ // counter variable and returns to the loop.
+ CGF.EmitBlock(SyncBB);
+ getNVPTXCTABarrier(CGF);
+
+ llvm::Value *IncCounterVal =
+ CGF.Builder.CreateNSWAdd(CounterVal, CGF.Builder.getInt32(1));
+ CGF.EmitStoreOfScalar(IncCounterVal, CounterLVal);
+ CGF.EmitBranch(LoopBB);
+
+ // Block that is reached when all threads in the team complete the region.
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+}
+
+/// Cast value to the specified type.
+static llvm::Value *castValueToType(CodeGenFunction &CGF, llvm::Value *Val,
+ QualType ValTy, QualType CastTy,
+ SourceLocation Loc) {
+ assert(!CGF.getContext().getTypeSizeInChars(CastTy).isZero() &&
+ "Cast type must sized.");
+ assert(!CGF.getContext().getTypeSizeInChars(ValTy).isZero() &&
+ "Val type must sized.");
+ llvm::Type *LLVMCastTy = CGF.ConvertTypeForMem(CastTy);
+ if (ValTy == CastTy)
+ return Val;
+ if (CGF.getContext().getTypeSizeInChars(ValTy) ==
+ CGF.getContext().getTypeSizeInChars(CastTy))
+ return CGF.Builder.CreateBitCast(Val, LLVMCastTy);
+ if (CastTy->isIntegerType() && ValTy->isIntegerType())
+ return CGF.Builder.CreateIntCast(Val, LLVMCastTy,
+ CastTy->hasSignedIntegerRepresentation());
+ Address CastItem = CGF.CreateMemTemp(CastTy);
+ Address ValCastItem = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CastItem, Val->getType()->getPointerTo(CastItem.getAddressSpace()));
+ CGF.EmitStoreOfScalar(Val, ValCastItem, /*Volatile=*/false, ValTy);
+ return CGF.EmitLoadOfScalar(CastItem, /*Volatile=*/false, CastTy, Loc);
}
/// This function creates calls to one of two shuffle functions to copy
/// variables between lanes in a warp.
static llvm::Value *createRuntimeShuffleFunction(CodeGenFunction &CGF,
- QualType ElemTy,
llvm::Value *Elem,
- llvm::Value *Offset) {
- auto &CGM = CGF.CGM;
- auto &C = CGM.getContext();
- auto &Bld = CGF.Builder;
+ QualType ElemType,
+ llvm::Value *Offset,
+ SourceLocation Loc) {
+ CodeGenModule &CGM = CGF.CGM;
+ CGBuilderTy &Bld = CGF.Builder;
CGOpenMPRuntimeNVPTX &RT =
*(static_cast<CGOpenMPRuntimeNVPTX *>(&CGM.getOpenMPRuntime()));
- unsigned Size = CGM.getContext().getTypeSizeInChars(ElemTy).getQuantity();
- assert(Size <= 8 && "Unsupported bitwidth in shuffle instruction.");
+ CharUnits Size = CGF.getContext().getTypeSizeInChars(ElemType);
+ assert(Size.getQuantity() <= 8 &&
+ "Unsupported bitwidth in shuffle instruction.");
- OpenMPRTLFunctionNVPTX ShuffleFn = Size <= 4
+ OpenMPRTLFunctionNVPTX ShuffleFn = Size.getQuantity() <= 4
? OMPRTL_NVPTX__kmpc_shuffle_int32
: OMPRTL_NVPTX__kmpc_shuffle_int64;
// Cast all types to 32- or 64-bit values before calling shuffle routines.
- auto CastTy = Size <= 4 ? CGM.Int32Ty : CGM.Int64Ty;
- auto *ElemCast = Bld.CreateSExtOrBitCast(Elem, CastTy);
- auto *WarpSize = CGF.EmitScalarConversion(
- getNVPTXWarpSize(CGF), C.getIntTypeForBitwidth(32, /* Signed */ true),
- C.getIntTypeForBitwidth(16, /* Signed */ true), SourceLocation());
+ QualType CastTy = CGF.getContext().getIntTypeForBitwidth(
+ Size.getQuantity() <= 4 ? 32 : 64, /*Signed=*/1);
+ llvm::Value *ElemCast = castValueToType(CGF, Elem, ElemType, CastTy, Loc);
+ llvm::Value *WarpSize =
+ Bld.CreateIntCast(getNVPTXWarpSize(CGF), CGM.Int16Ty, /*isSigned=*/true);
- auto *ShuffledVal =
- CGF.EmitRuntimeCall(RT.createNVPTXRuntimeFunction(ShuffleFn),
- {ElemCast, Offset, WarpSize});
+ llvm::Value *ShuffledVal = CGF.EmitRuntimeCall(
+ RT.createNVPTXRuntimeFunction(ShuffleFn), {ElemCast, Offset, WarpSize});
- return Bld.CreateTruncOrBitCast(ShuffledVal, CGF.ConvertTypeForMem(ElemTy));
+ return castValueToType(CGF, ShuffledVal, CastTy, ElemType, Loc);
+}
+
+static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr,
+ Address DestAddr, QualType ElemType,
+ llvm::Value *Offset, SourceLocation Loc) {
+ CGBuilderTy &Bld = CGF.Builder;
+
+ CharUnits Size = CGF.getContext().getTypeSizeInChars(ElemType);
+ // Create the loop over the big sized data.
+ // ptr = (void*)Elem;
+ // ptrEnd = (void*) Elem + 1;
+ // Step = 8;
+ // while (ptr + Step < ptrEnd)
+ // shuffle((int64_t)*ptr);
+ // Step = 4;
+ // while (ptr + Step < ptrEnd)
+ // shuffle((int32_t)*ptr);
+ // ...
+ Address ElemPtr = DestAddr;
+ Address Ptr = SrcAddr;
+ Address PtrEnd = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Bld.CreateConstGEP(SrcAddr, 1, Size), CGF.VoidPtrTy);
+ for (int IntSize = 8; IntSize >= 1; IntSize /= 2) {
+ if (Size < CharUnits::fromQuantity(IntSize))
+ continue;
+ QualType IntType = CGF.getContext().getIntTypeForBitwidth(
+ CGF.getContext().toBits(CharUnits::fromQuantity(IntSize)),
+ /*Signed=*/1);
+ llvm::Type *IntTy = CGF.ConvertTypeForMem(IntType);
+ Ptr = Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr, IntTy->getPointerTo());
+ ElemPtr =
+ Bld.CreatePointerBitCastOrAddrSpaceCast(ElemPtr, IntTy->getPointerTo());
+ if (Size.getQuantity() / IntSize > 1) {
+ llvm::BasicBlock *PreCondBB = CGF.createBasicBlock(".shuffle.pre_cond");
+ llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".shuffle.then");
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".shuffle.exit");
+ llvm::BasicBlock *CurrentBB = Bld.GetInsertBlock();
+ CGF.EmitBlock(PreCondBB);
+ llvm::PHINode *PhiSrc =
+ Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2);
+ PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB);
+ llvm::PHINode *PhiDest =
+ Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2);
+ PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB);
+ Ptr = Address(PhiSrc, Ptr.getAlignment());
+ ElemPtr = Address(PhiDest, ElemPtr.getAlignment());
+ llvm::Value *PtrDiff = Bld.CreatePtrDiff(
+ PtrEnd.getPointer(), Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Ptr.getPointer(), CGF.VoidPtrTy));
+ Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)),
+ ThenBB, ExitBB);
+ CGF.EmitBlock(ThenBB);
+ llvm::Value *Res = createRuntimeShuffleFunction(
+ CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc),
+ IntType, Offset, Loc);
+ CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType);
+ Ptr = Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize));
+ ElemPtr =
+ Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize));
+ PhiSrc->addIncoming(Ptr.getPointer(), ThenBB);
+ PhiDest->addIncoming(ElemPtr.getPointer(), ThenBB);
+ CGF.EmitBranch(PreCondBB);
+ CGF.EmitBlock(ExitBB);
+ } else {
+ llvm::Value *Res = createRuntimeShuffleFunction(
+ CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc),
+ IntType, Offset, Loc);
+ CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType);
+ Ptr = Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize));
+ ElemPtr =
+ Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize));
+ }
+ Size = Size % IntSize;
+ }
}
namespace {
@@ -1119,19 +2222,19 @@ static void emitReductionListCopy(
ArrayRef<const Expr *> Privates, Address SrcBase, Address DestBase,
CopyOptionsTy CopyOptions = {nullptr, nullptr, nullptr}) {
- auto &CGM = CGF.CGM;
- auto &C = CGM.getContext();
- auto &Bld = CGF.Builder;
+ CodeGenModule &CGM = CGF.CGM;
+ ASTContext &C = CGM.getContext();
+ CGBuilderTy &Bld = CGF.Builder;
- auto *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
- auto *ScratchpadIndex = CopyOptions.ScratchpadIndex;
- auto *ScratchpadWidth = CopyOptions.ScratchpadWidth;
+ llvm::Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
+ llvm::Value *ScratchpadIndex = CopyOptions.ScratchpadIndex;
+ llvm::Value *ScratchpadWidth = CopyOptions.ScratchpadWidth;
// Iterates, element-by-element, through the source Reduce list and
// make a copy.
unsigned Idx = 0;
unsigned Size = Privates.size();
- for (auto &Private : Privates) {
+ for (const Expr *Private : Privates) {
Address SrcElementAddr = Address::invalid();
Address DestElementAddr = Address::invalid();
Address DestElementPtrAddr = Address::invalid();
@@ -1150,10 +2253,9 @@ static void emitReductionListCopy(
// Step 1.1: Get the address for the src element in the Reduce list.
Address SrcElementPtrAddr =
Bld.CreateConstArrayGEP(SrcBase, Idx, CGF.getPointerSize());
- llvm::Value *SrcElementPtrPtr = CGF.EmitLoadOfScalar(
- SrcElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
- SrcElementAddr =
- Address(SrcElementPtrPtr, C.getTypeAlignInChars(Private->getType()));
+ SrcElementAddr = CGF.EmitLoadOfPointer(
+ SrcElementPtrAddr,
+ C.getPointerType(Private->getType())->castAs<PointerType>());
// Step 1.2: Create a temporary to store the element in the destination
// Reduce list.
@@ -1169,62 +2271,49 @@ static void emitReductionListCopy(
// Step 1.1: Get the address for the src element in the Reduce list.
Address SrcElementPtrAddr =
Bld.CreateConstArrayGEP(SrcBase, Idx, CGF.getPointerSize());
- llvm::Value *SrcElementPtrPtr = CGF.EmitLoadOfScalar(
- SrcElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
- SrcElementAddr =
- Address(SrcElementPtrPtr, C.getTypeAlignInChars(Private->getType()));
+ SrcElementAddr = CGF.EmitLoadOfPointer(
+ SrcElementPtrAddr,
+ C.getPointerType(Private->getType())->castAs<PointerType>());
// Step 1.2: Get the address for dest element. The destination
// element has already been created on the thread's stack.
DestElementPtrAddr =
Bld.CreateConstArrayGEP(DestBase, Idx, CGF.getPointerSize());
- llvm::Value *DestElementPtr =
- CGF.EmitLoadOfScalar(DestElementPtrAddr, /*Volatile=*/false,
- C.VoidPtrTy, SourceLocation());
- Address DestElemAddr =
- Address(DestElementPtr, C.getTypeAlignInChars(Private->getType()));
- DestElementAddr = Bld.CreateElementBitCast(
- DestElemAddr, CGF.ConvertTypeForMem(Private->getType()));
+ DestElementAddr = CGF.EmitLoadOfPointer(
+ DestElementPtrAddr,
+ C.getPointerType(Private->getType())->castAs<PointerType>());
break;
}
case ThreadToScratchpad: {
// Step 1.1: Get the address for the src element in the Reduce list.
Address SrcElementPtrAddr =
Bld.CreateConstArrayGEP(SrcBase, Idx, CGF.getPointerSize());
- llvm::Value *SrcElementPtrPtr = CGF.EmitLoadOfScalar(
- SrcElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
- SrcElementAddr =
- Address(SrcElementPtrPtr, C.getTypeAlignInChars(Private->getType()));
+ SrcElementAddr = CGF.EmitLoadOfPointer(
+ SrcElementPtrAddr,
+ C.getPointerType(Private->getType())->castAs<PointerType>());
// Step 1.2: Get the address for dest element:
// address = base + index * ElementSizeInChars.
- unsigned ElementSizeInChars =
- C.getTypeSizeInChars(Private->getType()).getQuantity();
- auto *CurrentOffset =
- Bld.CreateMul(llvm::ConstantInt::get(CGM.SizeTy, ElementSizeInChars),
- ScratchpadIndex);
- auto *ScratchPadElemAbsolutePtrVal =
- Bld.CreateAdd(DestBase.getPointer(), CurrentOffset);
+ llvm::Value *ElementSizeInChars = CGF.getTypeSize(Private->getType());
+ llvm::Value *CurrentOffset =
+ Bld.CreateNUWMul(ElementSizeInChars, ScratchpadIndex);
+ llvm::Value *ScratchPadElemAbsolutePtrVal =
+ Bld.CreateNUWAdd(DestBase.getPointer(), CurrentOffset);
ScratchPadElemAbsolutePtrVal =
Bld.CreateIntToPtr(ScratchPadElemAbsolutePtrVal, CGF.VoidPtrTy);
- Address ScratchpadPtr =
- Address(ScratchPadElemAbsolutePtrVal,
- C.getTypeAlignInChars(Private->getType()));
- DestElementAddr = Bld.CreateElementBitCast(
- ScratchpadPtr, CGF.ConvertTypeForMem(Private->getType()));
+ DestElementAddr = Address(ScratchPadElemAbsolutePtrVal,
+ C.getTypeAlignInChars(Private->getType()));
IncrScratchpadDest = true;
break;
}
case ScratchpadToThread: {
// Step 1.1: Get the address for the src element in the scratchpad.
// address = base + index * ElementSizeInChars.
- unsigned ElementSizeInChars =
- C.getTypeSizeInChars(Private->getType()).getQuantity();
- auto *CurrentOffset =
- Bld.CreateMul(llvm::ConstantInt::get(CGM.SizeTy, ElementSizeInChars),
- ScratchpadIndex);
- auto *ScratchPadElemAbsolutePtrVal =
- Bld.CreateAdd(SrcBase.getPointer(), CurrentOffset);
+ llvm::Value *ElementSizeInChars = CGF.getTypeSize(Private->getType());
+ llvm::Value *CurrentOffset =
+ Bld.CreateNUWMul(ElementSizeInChars, ScratchpadIndex);
+ llvm::Value *ScratchPadElemAbsolutePtrVal =
+ Bld.CreateNUWAdd(SrcBase.getPointer(), CurrentOffset);
ScratchPadElemAbsolutePtrVal =
Bld.CreateIntToPtr(ScratchPadElemAbsolutePtrVal, CGF.VoidPtrTy);
SrcElementAddr = Address(ScratchPadElemAbsolutePtrVal,
@@ -1246,21 +2335,30 @@ static void emitReductionListCopy(
// element as this is required in all directions
SrcElementAddr = Bld.CreateElementBitCast(
SrcElementAddr, CGF.ConvertTypeForMem(Private->getType()));
- llvm::Value *Elem =
- CGF.EmitLoadOfScalar(SrcElementAddr, /*Volatile=*/false,
- Private->getType(), SourceLocation());
+ DestElementAddr = Bld.CreateElementBitCast(DestElementAddr,
+ SrcElementAddr.getElementType());
// Now that all active lanes have read the element in the
// Reduce list, shuffle over the value from the remote lane.
if (ShuffleInElement) {
- Elem = createRuntimeShuffleFunction(CGF, Private->getType(), Elem,
- RemoteLaneOffset);
+ shuffleAndStore(CGF, SrcElementAddr, DestElementAddr, Private->getType(),
+ RemoteLaneOffset, Private->getExprLoc());
+ } else {
+ if (Private->getType()->isScalarType()) {
+ llvm::Value *Elem =
+ CGF.EmitLoadOfScalar(SrcElementAddr, /*Volatile=*/false,
+ Private->getType(), Private->getExprLoc());
+ // Store the source element value to the dest element address.
+ CGF.EmitStoreOfScalar(Elem, DestElementAddr, /*Volatile=*/false,
+ Private->getType());
+ } else {
+ CGF.EmitAggregateCopy(
+ CGF.MakeAddrLValue(DestElementAddr, Private->getType()),
+ CGF.MakeAddrLValue(SrcElementAddr, Private->getType()),
+ Private->getType(), AggValueSlot::DoesNotOverlap);
+ }
}
- // Store the source element value to the dest element address.
- CGF.EmitStoreOfScalar(Elem, DestElementAddr, /*Volatile=*/false,
- Private->getType());
-
// Step 3.1: Modify reference in dest Reduce list as needed.
// Modifying the reference in Reduce list to point to the newly
// created element. The element is live in the current function
@@ -1279,22 +2377,20 @@ static void emitReductionListCopy(
if ((IncrScratchpadDest || IncrScratchpadSrc) && (Idx + 1 < Size)) {
llvm::Value *ScratchpadBasePtr =
IncrScratchpadDest ? DestBase.getPointer() : SrcBase.getPointer();
- unsigned ElementSizeInChars =
- C.getTypeSizeInChars(Private->getType()).getQuantity();
- ScratchpadBasePtr = Bld.CreateAdd(
+ llvm::Value *ElementSizeInChars = CGF.getTypeSize(Private->getType());
+ ScratchpadBasePtr = Bld.CreateNUWAdd(
ScratchpadBasePtr,
- Bld.CreateMul(ScratchpadWidth, llvm::ConstantInt::get(
- CGM.SizeTy, ElementSizeInChars)));
+ Bld.CreateNUWMul(ScratchpadWidth, ElementSizeInChars));
// Take care of global memory alignment for performance
- ScratchpadBasePtr = Bld.CreateSub(ScratchpadBasePtr,
- llvm::ConstantInt::get(CGM.SizeTy, 1));
- ScratchpadBasePtr = Bld.CreateSDiv(
+ ScratchpadBasePtr = Bld.CreateNUWSub(
+ ScratchpadBasePtr, llvm::ConstantInt::get(CGM.SizeTy, 1));
+ ScratchpadBasePtr = Bld.CreateUDiv(
ScratchpadBasePtr,
llvm::ConstantInt::get(CGM.SizeTy, GlobalMemoryAlignment));
- ScratchpadBasePtr = Bld.CreateAdd(ScratchpadBasePtr,
- llvm::ConstantInt::get(CGM.SizeTy, 1));
- ScratchpadBasePtr = Bld.CreateMul(
+ ScratchpadBasePtr = Bld.CreateNUWAdd(
+ ScratchpadBasePtr, llvm::ConstantInt::get(CGM.SizeTy, 1));
+ ScratchpadBasePtr = Bld.CreateNUWMul(
ScratchpadBasePtr,
llvm::ConstantInt::get(CGM.SizeTy, GlobalMemoryAlignment));
@@ -1304,7 +2400,7 @@ static void emitReductionListCopy(
SrcBase = Address(ScratchpadBasePtr, CGF.getPointerAlign());
}
- Idx++;
+ ++Idx;
}
}
@@ -1319,27 +2415,31 @@ static void emitReductionListCopy(
/// local = local @ remote
/// else
/// local = remote
-static llvm::Value *
-emitReduceScratchpadFunction(CodeGenModule &CGM,
- ArrayRef<const Expr *> Privates,
- QualType ReductionArrayTy, llvm::Value *ReduceFn) {
- auto &C = CGM.getContext();
- auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true);
+static llvm::Value *emitReduceScratchpadFunction(
+ CodeGenModule &CGM, ArrayRef<const Expr *> Privates,
+ QualType ReductionArrayTy, llvm::Value *ReduceFn, SourceLocation Loc) {
+ ASTContext &C = CGM.getContext();
+ QualType Int32Ty = C.getIntTypeForBitwidth(32, /*Signed=*/1);
// Destination of the copy.
- ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
// Base address of the scratchpad array, with each element storing a
// Reduce list per team.
- ImplicitParamDecl ScratchPadArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
// A source index into the scratchpad array.
- ImplicitParamDecl IndexArg(C, Int32Ty, ImplicitParamDecl::Other);
+ ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
+ ImplicitParamDecl::Other);
// Row width of an element in the scratchpad array, typically
// the number of teams.
- ImplicitParamDecl WidthArg(C, Int32Ty, ImplicitParamDecl::Other);
+ ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
+ ImplicitParamDecl::Other);
// If should_reduce == 1, then it's load AND reduce,
// If should_reduce == 0 (or otherwise), then it only loads (+ copy).
// The latter case is used for initialization.
- ImplicitParamDecl ShouldReduceArg(C, Int32Ty, ImplicitParamDecl::Other);
+ ImplicitParamDecl ShouldReduceArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ Int32Ty, ImplicitParamDecl::Other);
FunctionArgList Args;
Args.push_back(&ReduceListArg);
@@ -1348,47 +2448,44 @@ emitReduceScratchpadFunction(CodeGenModule &CGM,
Args.push_back(&WidthArg);
Args.push_back(&ShouldReduceArg);
- auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ const CGFunctionInfo &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
"_omp_reduction_load_and_reduce", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*DC=*/nullptr, Fn, CGFI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- // We don't need debug information in this function as nothing here refers to
- // user code.
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
// Get local Reduce list pointer.
Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg);
Address ReduceListAddr(
Bld.CreatePointerBitCastOrAddrSpaceCast(
CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false,
- C.VoidPtrTy, SourceLocation()),
+ C.VoidPtrTy, Loc),
CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()),
CGF.getPointerAlign());
Address AddrScratchPadArg = CGF.GetAddrOfLocalVar(&ScratchPadArg);
llvm::Value *ScratchPadBase = CGF.EmitLoadOfScalar(
- AddrScratchPadArg, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
+ AddrScratchPadArg, /*Volatile=*/false, C.VoidPtrTy, Loc);
Address AddrIndexArg = CGF.GetAddrOfLocalVar(&IndexArg);
- llvm::Value *IndexVal =
- Bld.CreateIntCast(CGF.EmitLoadOfScalar(AddrIndexArg, /*Volatile=*/false,
- Int32Ty, SourceLocation()),
- CGM.SizeTy, /*isSigned=*/true);
+ llvm::Value *IndexVal = Bld.CreateIntCast(
+ CGF.EmitLoadOfScalar(AddrIndexArg, /*Volatile=*/false, Int32Ty, Loc),
+ CGM.SizeTy, /*isSigned=*/true);
Address AddrWidthArg = CGF.GetAddrOfLocalVar(&WidthArg);
- llvm::Value *WidthVal =
- Bld.CreateIntCast(CGF.EmitLoadOfScalar(AddrWidthArg, /*Volatile=*/false,
- Int32Ty, SourceLocation()),
- CGM.SizeTy, /*isSigned=*/true);
+ llvm::Value *WidthVal = Bld.CreateIntCast(
+ CGF.EmitLoadOfScalar(AddrWidthArg, /*Volatile=*/false, Int32Ty, Loc),
+ CGM.SizeTy, /*isSigned=*/true);
Address AddrShouldReduceArg = CGF.GetAddrOfLocalVar(&ShouldReduceArg);
llvm::Value *ShouldReduceVal = CGF.EmitLoadOfScalar(
- AddrShouldReduceArg, /*Volatile=*/false, Int32Ty, SourceLocation());
+ AddrShouldReduceArg, /*Volatile=*/false, Int32Ty, Loc);
// The absolute ptr address to the base addr of the next element to copy.
llvm::Value *CumulativeElemBasePtr =
@@ -1411,7 +2508,7 @@ emitReduceScratchpadFunction(CodeGenModule &CGM,
llvm::BasicBlock *ElseBB = CGF.createBasicBlock("else");
llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont");
- auto CondReduce = Bld.CreateICmpEQ(ShouldReduceVal, Bld.getInt32(1));
+ llvm::Value *CondReduce = Bld.CreateIsNotNull(ShouldReduceVal);
Bld.CreateCondBr(CondReduce, ThenBB, ElseBB);
CGF.EmitBlock(ThenBB);
@@ -1421,7 +2518,8 @@ emitReduceScratchpadFunction(CodeGenModule &CGM,
ReduceListAddr.getPointer(), CGF.VoidPtrTy);
llvm::Value *RemoteDataPtr = Bld.CreatePointerBitCastOrAddrSpaceCast(
RemoteReduceList.getPointer(), CGF.VoidPtrTy);
- CGF.EmitCallOrInvoke(ReduceFn, {LocalDataPtr, RemoteDataPtr});
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
+ CGF, Loc, ReduceFn, {LocalDataPtr, RemoteDataPtr});
Bld.CreateBr(MergeBB);
CGF.EmitBlock(ElseBB);
@@ -1445,22 +2543,27 @@ emitReduceScratchpadFunction(CodeGenModule &CGM,
///
static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
- QualType ReductionArrayTy) {
+ QualType ReductionArrayTy,
+ SourceLocation Loc) {
- auto &C = CGM.getContext();
- auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true);
+ ASTContext &C = CGM.getContext();
+ QualType Int32Ty = C.getIntTypeForBitwidth(32, /*Signed=*/1);
// Source of the copy.
- ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
// Base address of the scratchpad array, with each element storing a
// Reduce list per team.
- ImplicitParamDecl ScratchPadArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
// A destination index into the scratchpad array, typically the team
// identifier.
- ImplicitParamDecl IndexArg(C, Int32Ty, ImplicitParamDecl::Other);
+ ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
+ ImplicitParamDecl::Other);
// Row width of an element in the scratchpad array, typically
// the number of teams.
- ImplicitParamDecl WidthArg(C, Int32Ty, ImplicitParamDecl::Other);
+ ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
+ ImplicitParamDecl::Other);
FunctionArgList Args;
Args.push_back(&ReduceListArg);
@@ -1468,36 +2571,34 @@ static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
Args.push_back(&IndexArg);
Args.push_back(&WidthArg);
- auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ const CGFunctionInfo &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
"_omp_reduction_copy_to_scratchpad", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*DC=*/nullptr, Fn, CGFI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- // We don't need debug information in this function as nothing here refers to
- // user code.
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg);
Address SrcDataAddr(
Bld.CreatePointerBitCastOrAddrSpaceCast(
CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false,
- C.VoidPtrTy, SourceLocation()),
+ C.VoidPtrTy, Loc),
CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()),
CGF.getPointerAlign());
Address AddrScratchPadArg = CGF.GetAddrOfLocalVar(&ScratchPadArg);
llvm::Value *ScratchPadBase = CGF.EmitLoadOfScalar(
- AddrScratchPadArg, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
+ AddrScratchPadArg, /*Volatile=*/false, C.VoidPtrTy, Loc);
Address AddrIndexArg = CGF.GetAddrOfLocalVar(&IndexArg);
- llvm::Value *IndexVal =
- Bld.CreateIntCast(CGF.EmitLoadOfScalar(AddrIndexArg, /*Volatile=*/false,
- Int32Ty, SourceLocation()),
- CGF.SizeTy, /*isSigned=*/true);
+ llvm::Value *IndexVal = Bld.CreateIntCast(
+ CGF.EmitLoadOfScalar(AddrIndexArg, /*Volatile=*/false, Int32Ty, Loc),
+ CGF.SizeTy, /*isSigned=*/true);
Address AddrWidthArg = CGF.GetAddrOfLocalVar(&WidthArg);
llvm::Value *WidthVal =
@@ -1534,35 +2635,36 @@ static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
/// sync
static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
- QualType ReductionArrayTy) {
- auto &C = CGM.getContext();
- auto &M = CGM.getModule();
+ QualType ReductionArrayTy,
+ SourceLocation Loc) {
+ ASTContext &C = CGM.getContext();
+ llvm::Module &M = CGM.getModule();
// ReduceList: thread local Reduce list.
// At the stage of the computation when this function is called, partially
// aggregated values reside in the first lane of every active warp.
- ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
// NumWarps: number of warps active in the parallel region. This could
// be smaller than 32 (max warps in a CTA) for partial block reduction.
- ImplicitParamDecl NumWarpsArg(C,
+ ImplicitParamDecl NumWarpsArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
C.getIntTypeForBitwidth(32, /* Signed */ true),
ImplicitParamDecl::Other);
FunctionArgList Args;
Args.push_back(&ReduceListArg);
Args.push_back(&NumWarpsArg);
- auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ const CGFunctionInfo &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
"_omp_reduction_inter_warp_copy_func", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*DC=*/nullptr, Fn, CGFI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- // We don't need debug information in this function as nothing here refers to
- // user code.
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
// This array is used as a medium to transfer, one reduce element at a time,
// the data from the first lane of every warp to lanes in the first warp
@@ -1571,7 +2673,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
// for reduced latency, as well as to have a distinct copy for concurrently
// executing target regions. The array is declared with common linkage so
// as to be shared across compilation units.
- const char *TransferMediumName =
+ StringRef TransferMediumName =
"__openmp_nvptx_data_transfer_temporary_storage";
llvm::GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
@@ -1584,14 +2686,15 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
llvm::Constant::getNullValue(Ty), TransferMediumName,
/*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal,
SharedAddressSpace);
+ CGM.addCompilerUsedGlobal(TransferMedium);
}
// Get the CUDA thread id of the current OpenMP thread on the GPU.
- auto *ThreadID = getNVPTXThreadID(CGF);
+ llvm::Value *ThreadID = getNVPTXThreadID(CGF);
// nvptx_lane_id = nvptx_id % warpsize
- auto *LaneID = getNVPTXLaneID(CGF);
+ llvm::Value *LaneID = getNVPTXLaneID(CGF);
// nvptx_warp_id = nvptx_id / warpsize
- auto *WarpID = getNVPTXWarpID(CGF);
+ llvm::Value *WarpID = getNVPTXWarpID(CGF);
Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg);
Address LocalReduceList(
@@ -1602,7 +2705,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
CGF.getPointerAlign());
unsigned Idx = 0;
- for (auto &Private : Privates) {
+ for (const Expr *Private : Privates) {
//
// Warp master copies reduce element to transfer medium in __shared__
// memory.
@@ -1612,8 +2715,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont");
// if (lane_id == 0)
- auto IsWarpMaster =
- Bld.CreateICmpEQ(LaneID, Bld.getInt32(0), "warp_master");
+ llvm::Value *IsWarpMaster = Bld.CreateIsNull(LaneID, "warp_master");
Bld.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
CGF.EmitBlock(ThenBB);
@@ -1627,9 +2729,6 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
Address(ElemPtrPtr, C.getTypeAlignInChars(Private->getType()));
ElemPtr = Bld.CreateElementBitCast(
ElemPtr, CGF.ConvertTypeForMem(Private->getType()));
- // elem = *elemptr
- llvm::Value *Elem = CGF.EmitLoadOfScalar(
- ElemPtr, /*Volatile=*/false, Private->getType(), SourceLocation());
// Get pointer to location in transfer medium.
// MediumPtr = &medium[warp_id]
@@ -1641,8 +2740,19 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
MediumPtr = Bld.CreateElementBitCast(
MediumPtr, CGF.ConvertTypeForMem(Private->getType()));
+ // elem = *elemptr
//*MediumPtr = elem
- Bld.CreateStore(Elem, MediumPtr);
+ if (Private->getType()->isScalarType()) {
+ llvm::Value *Elem = CGF.EmitLoadOfScalar(ElemPtr, /*Volatile=*/false,
+ Private->getType(), Loc);
+ // Store the source element value to the dest element address.
+ CGF.EmitStoreOfScalar(Elem, MediumPtr, /*Volatile=*/false,
+ Private->getType());
+ } else {
+ CGF.EmitAggregateCopy(CGF.MakeAddrLValue(ElemPtr, Private->getType()),
+ CGF.MakeAddrLValue(MediumPtr, Private->getType()),
+ Private->getType(), AggValueSlot::DoesNotOverlap);
+ }
Bld.CreateBr(MergeBB);
@@ -1655,7 +2765,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
llvm::Value *NumWarpsVal = CGF.EmitLoadOfScalar(
AddrNumWarpsArg, /*Volatile=*/false, C.IntTy, SourceLocation());
- auto *NumActiveThreads = Bld.CreateNSWMul(
+ llvm::Value *NumActiveThreads = Bld.CreateNSWMul(
NumWarpsVal, getNVPTXWarpSize(CGF), "num_active_threads");
// named_barrier_sync(ParallelBarrierID, num_active_threads)
syncParallelThreads(CGF, NumActiveThreads);
@@ -1668,7 +2778,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
llvm::BasicBlock *W0MergeBB = CGF.createBasicBlock("ifcont");
// Up to 32 threads in warp 0 are active.
- auto IsActiveThread =
+ llvm::Value *IsActiveThread =
Bld.CreateICmpULT(ThreadID, NumWarpsVal, "is_active_thread");
Bld.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
@@ -1682,8 +2792,6 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
// SrcMediumVal = *SrcMediumPtr;
SrcMediumPtr = Bld.CreateElementBitCast(
SrcMediumPtr, CGF.ConvertTypeForMem(Private->getType()));
- llvm::Value *SrcMediumValue = CGF.EmitLoadOfScalar(
- SrcMediumPtr, /*Volatile=*/false, Private->getType(), SourceLocation());
// TargetElemPtr = (type[i]*)(SrcDataAddr[i])
Address TargetElemPtrPtr =
@@ -1696,8 +2804,17 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
TargetElemPtr, CGF.ConvertTypeForMem(Private->getType()));
// *TargetElemPtr = SrcMediumVal;
- CGF.EmitStoreOfScalar(SrcMediumValue, TargetElemPtr, /*Volatile=*/false,
- Private->getType());
+ if (Private->getType()->isScalarType()) {
+ llvm::Value *SrcMediumValue = CGF.EmitLoadOfScalar(
+ SrcMediumPtr, /*Volatile=*/false, Private->getType(), Loc);
+ CGF.EmitStoreOfScalar(SrcMediumValue, TargetElemPtr, /*Volatile=*/false,
+ Private->getType());
+ } else {
+ CGF.EmitAggregateCopy(
+ CGF.MakeAddrLValue(SrcMediumPtr, Private->getType()),
+ CGF.MakeAddrLValue(TargetElemPtr, Private->getType()),
+ Private->getType(), AggValueSlot::DoesNotOverlap);
+ }
Bld.CreateBr(W0MergeBB);
CGF.EmitBlock(W0ElseBB);
@@ -1708,7 +2825,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
// While warp 0 copies values from transfer medium, all other warps must
// wait.
syncParallelThreads(CGF, NumActiveThreads);
- Idx++;
+ ++Idx;
}
CGF.FinishFunction();
@@ -1781,39 +2898,40 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
/// (2k+1)th thread is ignored in the value aggregation. Therefore
/// we copy the Reduce list from the (2k+1)th lane to (k+1)th lane so
/// that the contiguity assumption still holds.
-static llvm::Value *
-emitShuffleAndReduceFunction(CodeGenModule &CGM,
- ArrayRef<const Expr *> Privates,
- QualType ReductionArrayTy, llvm::Value *ReduceFn) {
- auto &C = CGM.getContext();
+static llvm::Value *emitShuffleAndReduceFunction(
+ CodeGenModule &CGM, ArrayRef<const Expr *> Privates,
+ QualType ReductionArrayTy, llvm::Value *ReduceFn, SourceLocation Loc) {
+ ASTContext &C = CGM.getContext();
// Thread local Reduce list used to host the values of data to be reduced.
- ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.VoidPtrTy, ImplicitParamDecl::Other);
// Current lane id; could be logical.
- ImplicitParamDecl LaneIDArg(C, C.ShortTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl LaneIDArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.ShortTy,
+ ImplicitParamDecl::Other);
// Offset of the remote source lane relative to the current lane.
- ImplicitParamDecl RemoteLaneOffsetArg(C, C.ShortTy,
- ImplicitParamDecl::Other);
+ ImplicitParamDecl RemoteLaneOffsetArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.ShortTy, ImplicitParamDecl::Other);
// Algorithm version. This is expected to be known at compile time.
- ImplicitParamDecl AlgoVerArg(C, C.ShortTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl AlgoVerArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.ShortTy, ImplicitParamDecl::Other);
FunctionArgList Args;
Args.push_back(&ReduceListArg);
Args.push_back(&LaneIDArg);
Args.push_back(&RemoteLaneOffsetArg);
Args.push_back(&AlgoVerArg);
- auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ const CGFunctionInfo &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
"_omp_reduction_shuffle_and_reduce_func", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM);
- // We don't need debug information in this function as nothing here refers to
- // user code.
- CGF.disableDebugInfo();
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
- auto &Bld = CGF.Builder;
+ CGBuilderTy &Bld = CGF.Builder;
Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg);
Address LocalReduceList(
@@ -1870,21 +2988,19 @@ emitShuffleAndReduceFunction(CodeGenModule &CGM,
// When AlgoVer==2, the third conjunction has only the second part to be
// evaluated during runtime. Other conjunctions evaluates to false
// during compile time.
- auto CondAlgo0 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(0));
+ llvm::Value *CondAlgo0 = Bld.CreateIsNull(AlgoVerArgVal);
- auto Algo1 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(1));
- auto CondAlgo1 = Bld.CreateAnd(
+ llvm::Value *Algo1 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(1));
+ llvm::Value *CondAlgo1 = Bld.CreateAnd(
Algo1, Bld.CreateICmpULT(LaneIDArgVal, RemoteLaneOffsetArgVal));
- auto Algo2 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(2));
- auto CondAlgo2 = Bld.CreateAnd(
- Algo2,
- Bld.CreateICmpEQ(Bld.CreateAnd(LaneIDArgVal, Bld.getInt16(1)),
- Bld.getInt16(0)));
+ llvm::Value *Algo2 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(2));
+ llvm::Value *CondAlgo2 = Bld.CreateAnd(
+ Algo2, Bld.CreateIsNull(Bld.CreateAnd(LaneIDArgVal, Bld.getInt16(1))));
CondAlgo2 = Bld.CreateAnd(
CondAlgo2, Bld.CreateICmpSGT(RemoteLaneOffsetArgVal, Bld.getInt16(0)));
- auto CondReduce = Bld.CreateOr(CondAlgo0, CondAlgo1);
+ llvm::Value *CondReduce = Bld.CreateOr(CondAlgo0, CondAlgo1);
CondReduce = Bld.CreateOr(CondReduce, CondAlgo2);
llvm::BasicBlock *ThenBB = CGF.createBasicBlock("then");
@@ -1898,7 +3014,8 @@ emitShuffleAndReduceFunction(CodeGenModule &CGM,
LocalReduceList.getPointer(), CGF.VoidPtrTy);
llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast(
RemoteReduceList.getPointer(), CGF.VoidPtrTy);
- CGF.EmitCallOrInvoke(ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr});
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
+ CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr});
Bld.CreateBr(MergeBB);
CGF.EmitBlock(ElseBB);
@@ -1909,7 +3026,7 @@ emitShuffleAndReduceFunction(CodeGenModule &CGM,
// if (AlgoVer==1 && (LaneId >= Offset)) copy Remote Reduce list to local
// Reduce list.
Algo1 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(1));
- auto CondCopy = Bld.CreateAnd(
+ llvm::Value *CondCopy = Bld.CreateAnd(
Algo1, Bld.CreateICmpUGE(LaneIDArgVal, RemoteLaneOffsetArgVal));
llvm::BasicBlock *CpyThenBB = CGF.createBasicBlock("then");
@@ -2182,16 +3299,22 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
bool ParallelReduction = isOpenMPParallelDirective(Options.ReductionKind);
bool TeamsReduction = isOpenMPTeamsDirective(Options.ReductionKind);
- // FIXME: Add support for simd reduction.
- assert((TeamsReduction || ParallelReduction) &&
+ bool SimdReduction = isOpenMPSimdDirective(Options.ReductionKind);
+ assert((TeamsReduction || ParallelReduction || SimdReduction) &&
"Invalid reduction selection in emitReduction.");
- auto &C = CGM.getContext();
+ if (Options.SimpleReduction) {
+ CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
+ ReductionOps, Options);
+ return;
+ }
+
+ ASTContext &C = CGM.getContext();
// 1. Build a list of reduction variables.
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
auto Size = RHSExprs.size();
- for (auto *E : Privates) {
+ for (const Expr *E : Privates) {
if (E->getType()->isVariablyModifiedType())
// Reserve place for array size.
++Size;
@@ -2219,7 +3342,7 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
llvm::Value *Size = CGF.Builder.CreateIntCast(
CGF.getVLASize(
CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
- .first,
+ .NumElts,
CGF.SizeTy, /*isSigned=*/false);
CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
Elem);
@@ -2227,41 +3350,44 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
}
// 2. Emit reduce_func().
- auto *ReductionFn = emitReductionFunction(
- CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
- LHSExprs, RHSExprs, ReductionOps);
+ llvm::Value *ReductionFn = emitReductionFunction(
+ CGM, Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(),
+ Privates, LHSExprs, RHSExprs, ReductionOps);
// 4. Build res = __kmpc_reduce{_nowait}(<gtid>, <n>, sizeof(RedList),
// RedList, shuffle_reduce_func, interwarp_copy_func);
- auto *ThreadId = getThreadID(CGF, Loc);
- auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
- auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ llvm::Value *ThreadId = getThreadID(CGF, Loc);
+ llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
+ llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
ReductionList.getPointer(), CGF.VoidPtrTy);
- auto *ShuffleAndReduceFn = emitShuffleAndReduceFunction(
- CGM, Privates, ReductionArrayTy, ReductionFn);
- auto *InterWarpCopyFn =
- emitInterWarpCopyFunction(CGM, Privates, ReductionArrayTy);
+ llvm::Value *ShuffleAndReduceFn = emitShuffleAndReduceFunction(
+ CGM, Privates, ReductionArrayTy, ReductionFn, Loc);
+ llvm::Value *InterWarpCopyFn =
+ emitInterWarpCopyFunction(CGM, Privates, ReductionArrayTy, Loc);
- llvm::Value *Res = nullptr;
- if (ParallelReduction) {
- llvm::Value *Args[] = {ThreadId,
- CGF.Builder.getInt32(RHSExprs.size()),
- ReductionArrayTySize,
- RL,
- ShuffleAndReduceFn,
- InterWarpCopyFn};
+ llvm::Value *Args[] = {ThreadId,
+ CGF.Builder.getInt32(RHSExprs.size()),
+ ReductionArrayTySize,
+ RL,
+ ShuffleAndReduceFn,
+ InterWarpCopyFn};
+ llvm::Value *Res = nullptr;
+ if (ParallelReduction)
Res = CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_reduce_nowait),
Args);
- }
+ else if (SimdReduction)
+ Res = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_simd_reduce_nowait),
+ Args);
if (TeamsReduction) {
- auto *ScratchPadCopyFn =
- emitCopyToScratchpad(CGM, Privates, ReductionArrayTy);
- auto *LoadAndReduceFn = emitReduceScratchpadFunction(
- CGM, Privates, ReductionArrayTy, ReductionFn);
+ llvm::Value *ScratchPadCopyFn =
+ emitCopyToScratchpad(CGM, Privates, ReductionArrayTy, Loc);
+ llvm::Value *LoadAndReduceFn = emitReduceScratchpadFunction(
+ CGM, Privates, ReductionArrayTy, ReductionFn, Loc);
llvm::Value *Args[] = {ThreadId,
CGF.Builder.getInt32(RHSExprs.size()),
@@ -2277,25 +3403,26 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
}
// 5. Build switch(res)
- auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
- auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/1);
+ llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
+ llvm::SwitchInst *SwInst =
+ CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/1);
// 6. Build case 1: where we have reduced values in the master
// thread in each team.
// __kmpc_end_reduce{_nowait}(<gtid>);
// break;
- auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
+ llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
CGF.EmitBlock(Case1BB);
// Add emission of __kmpc_end_reduce{_nowait}(<gtid>);
llvm::Value *EndArgs[] = {ThreadId};
- auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps,
+ auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps,
this](CodeGenFunction &CGF, PrePostActionTy &Action) {
auto IPriv = Privates.begin();
auto ILHS = LHSExprs.begin();
auto IRHS = RHSExprs.begin();
- for (auto *E : ReductionOps) {
+ for (const Expr *E : ReductionOps) {
emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
cast<DeclRefExpr>(*IRHS));
++IPriv;
@@ -2334,11 +3461,10 @@ CGOpenMPRuntimeNVPTX::translateParameter(const FieldDecl *FD,
enum { NVPTX_local_addr = 5 };
QC.addAddressSpace(getLangASFromTargetAS(NVPTX_local_addr));
ArgType = QC.apply(CGM.getContext(), ArgType);
- if (isa<ImplicitParamDecl>(NativeParam)) {
+ 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()),
@@ -2397,8 +3523,8 @@ void CGOpenMPRuntimeNVPTX::emitOutlinedFunctionCall(
continue;
}
llvm::Value *TargetArg = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- NativeArg, NativeArg->getType()->getPointerElementType()->getPointerTo(
- /*AddrSpace=*/0));
+ NativeArg,
+ NativeArg->getType()->getPointerElementType()->getPointerTo());
TargetArgs.emplace_back(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TargetArg, TargetType));
}
@@ -2409,10 +3535,10 @@ void CGOpenMPRuntimeNVPTX::emitOutlinedFunctionCall(
/// 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 *CGOpenMPRuntimeNVPTX::createParallelDataSharingWrapper(
llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D) {
ASTContext &Ctx = CGM.getContext();
- const auto &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+ const auto &CS = *D.getCapturedStmt(OMPD_parallel);
// Create a function that takes as argument the source thread.
FunctionArgList WrapperArgs;
@@ -2420,76 +3546,200 @@ llvm::Function *CGOpenMPRuntimeNVPTX::createDataSharingWrapper(
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);
+ ImplicitParamDecl ParallelLevelArg(Ctx, /*DC=*/nullptr, D.getLocStart(),
+ /*Id=*/nullptr, Int16QTy,
+ ImplicitParamDecl::Other);
+ ImplicitParamDecl WrapperArg(Ctx, /*DC=*/nullptr, D.getLocStart(),
+ /*Id=*/nullptr, Int32QTy,
+ ImplicitParamDecl::Other);
WrapperArgs.emplace_back(&ParallelLevelArg);
WrapperArgs.emplace_back(&WrapperArg);
- WrapperArgs.emplace_back(&SharedArgsList);
- auto &CGFI =
+ const CGFunctionInfo &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);
+ Twine(OutlinedParallelFn->getName(), "_wrapper"), &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
+ Fn->setDoesNotRecurse();
CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
- CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, CGFI, WrapperArgs);
+ CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, CGFI, WrapperArgs,
+ D.getLocStart(), D.getLocStart());
const auto *RD = CS.getCapturedRecordDecl();
auto CurField = RD->field_begin();
+ Address ZeroAddr = CGF.CreateMemTemp(
+ CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
+ /*Name*/ ".zero.addr");
+ CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
// 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()));
+ Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer());
+ Args.emplace_back(ZeroAddr.getPointer());
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);
+ // Use global memory for data sharing.
+ // Handle passing of global args to workers.
+ Address GlobalArgs =
+ CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args");
+ llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer();
+ llvm::Value *DataSharingArgs[] = {GlobalArgsPtr};
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_get_shared_variables),
+ DataSharingArgs);
+
+ // Retrieve the shared variables from the list of references returned
+ // by the runtime. Pass the variables to the outlined function.
+ Address SharedArgListAddress = Address::invalid();
+ if (CS.capture_size() > 0 ||
+ isOpenMPLoopBoundSharingDirective(D.getDirectiveKind())) {
+ SharedArgListAddress = CGF.EmitLoadOfPointer(
+ GlobalArgs, CGF.getContext()
+ .getPointerType(CGF.getContext().getPointerType(
+ CGF.getContext().VoidPtrTy))
+ .castAs<PointerType>());
+ }
+ unsigned Idx = 0;
+ if (isOpenMPLoopBoundSharingDirective(D.getDirectiveKind())) {
+ Address Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx,
+ CGF.getPointerSize());
+ Address TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Src, CGF.SizeTy->getPointerTo());
+ llvm::Value *LB = CGF.EmitLoadOfScalar(
+ TypedAddress,
+ /*Volatile=*/false,
+ CGF.getContext().getPointerType(CGF.getContext().getSizeType()),
+ cast<OMPLoopDirective>(D).getLowerBoundVariable()->getExprLoc());
+ Args.emplace_back(LB);
+ ++Idx;
+ Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx,
+ CGF.getPointerSize());
+ TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Src, CGF.SizeTy->getPointerTo());
+ llvm::Value *UB = CGF.EmitLoadOfScalar(
+ TypedAddress,
+ /*Volatile=*/false,
+ CGF.getContext().getPointerType(CGF.getContext().getSizeType()),
+ cast<OMPLoopDirective>(D).getUpperBoundVariable()->getExprLoc());
+ Args.emplace_back(UB);
+ ++Idx;
+ }
+ if (CS.capture_size() > 0) {
+ ASTContext &CGFContext = CGF.getContext();
+ for (unsigned I = 0, E = CS.capture_size(); I < E; ++I, ++CI, ++CurField) {
+ QualType ElemTy = CurField->getType();
+ Address Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, I + Idx,
+ CGF.getPointerSize());
+ Address TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Src, CGF.ConvertTypeForMem(CGFContext.getPointerType(ElemTy)));
+ llvm::Value *Arg = CGF.EmitLoadOfScalar(TypedAddress,
+ /*Volatile=*/false,
+ CGFContext.getPointerType(ElemTy),
+ CI->getLocation());
+ if (CI->capturesVariableByCopy() &&
+ !CI->getCapturedVar()->getType()->isAnyPointerType()) {
+ Arg = castValueToType(CGF, Arg, ElemTy, CGFContext.getUIntPtrType(),
+ CI->getLocation());
+ }
+ Args.emplace_back(Arg);
+ }
+ }
+
+ emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedParallelFn, Args);
CGF.FinishFunction();
return Fn;
}
+
+void CGOpenMPRuntimeNVPTX::emitFunctionProlog(CodeGenFunction &CGF,
+ const Decl *D) {
+ if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic)
+ return;
+
+ assert(D && "Expected function or captured|block decl.");
+ assert(FunctionGlobalizedDecls.count(CGF.CurFn) == 0 &&
+ "Function is registered already.");
+ const Stmt *Body = nullptr;
+ bool NeedToDelayGlobalization = false;
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ Body = FD->getBody();
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+ Body = BD->getBody();
+ } else if (const auto *CD = dyn_cast<CapturedDecl>(D)) {
+ Body = CD->getBody();
+ NeedToDelayGlobalization = CGF.CapturedStmtInfo->getKind() == CR_OpenMP;
+ }
+ if (!Body)
+ return;
+ CheckVarsEscapingDeclContext VarChecker(CGF);
+ VarChecker.Visit(Body);
+ const RecordDecl *GlobalizedVarsRecord = VarChecker.getGlobalizedRecord();
+ ArrayRef<const ValueDecl *> EscapedVariableLengthDecls =
+ VarChecker.getEscapedVariableLengthDecls();
+ if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty())
+ return;
+ auto I = FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first;
+ I->getSecond().MappedParams =
+ llvm::make_unique<CodeGenFunction::OMPMapVars>();
+ I->getSecond().GlobalRecord = GlobalizedVarsRecord;
+ I->getSecond().EscapedParameters.insert(
+ VarChecker.getEscapedParameters().begin(),
+ VarChecker.getEscapedParameters().end());
+ I->getSecond().EscapedVariableLengthDecls.append(
+ EscapedVariableLengthDecls.begin(), EscapedVariableLengthDecls.end());
+ DeclToAddrMapTy &Data = I->getSecond().LocalVarData;
+ for (const ValueDecl *VD : VarChecker.getEscapedDecls()) {
+ assert(VD->isCanonicalDecl() && "Expected canonical declaration");
+ const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD);
+ Data.insert(std::make_pair(VD, std::make_pair(FD, Address::invalid())));
+ }
+ if (!NeedToDelayGlobalization) {
+ emitGenericVarsProlog(CGF, D->getLocStart());
+ struct GlobalizationScope final : EHScopeStack::Cleanup {
+ GlobalizationScope() = default;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsEpilog(CGF);
+ }
+ };
+ CGF.EHStack.pushCleanup<GlobalizationScope>(NormalAndEHCleanup);
+ }
+}
+
+Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD) {
+ if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic)
+ return Address::invalid();
+
+ VD = VD->getCanonicalDecl();
+ auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
+ if (I == FunctionGlobalizedDecls.end())
+ return Address::invalid();
+ auto VDI = I->getSecond().LocalVarData.find(VD);
+ if (VDI != I->getSecond().LocalVarData.end())
+ return VDI->second.second;
+ if (VD->hasAttrs()) {
+ for (specific_attr_iterator<OMPReferencedVarAttr> IT(VD->attr_begin()),
+ E(VD->attr_end());
+ IT != E; ++IT) {
+ auto VDI = I->getSecond().LocalVarData.find(
+ cast<VarDecl>(cast<DeclRefExpr>(IT->getRef())->getDecl())
+ ->getCanonicalDecl());
+ if (VDI != I->getSecond().LocalVarData.end())
+ return VDI->second.second;
+ }
+ }
+ return Address::invalid();
+}
+
+void CGOpenMPRuntimeNVPTX::functionFinished(CodeGenFunction &CGF) {
+ FunctionGlobalizedDecls.erase(CGF.CurFn);
+ CGOpenMPRuntime::functionFinished(CGF);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
index 5d13408318a5..f83e99f8a3b7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
@@ -24,8 +24,18 @@ namespace clang {
namespace CodeGen {
class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime {
+public:
+ /// Defines the execution mode.
+ enum ExecutionMode {
+ /// SPMD execution mode (all threads are worker threads).
+ EM_SPMD,
+ /// Non-SPMD execution mode (1 master thread, others are workers).
+ EM_NonSPMD,
+ /// Unknown execution mode (orphaned directive).
+ EM_Unknown,
+ };
private:
- // Parallel outlined function work for workers to execute.
+ /// Parallel outlined function work for workers to execute.
llvm::SmallVector<llvm::Function *, 16> Work;
struct EntryFunctionState {
@@ -35,48 +45,56 @@ private:
class WorkerFunctionState {
public:
llvm::Function *WorkerFn;
- const CGFunctionInfo *CGFI;
+ const CGFunctionInfo &CGFI;
+ SourceLocation Loc;
- WorkerFunctionState(CodeGenModule &CGM);
+ WorkerFunctionState(CodeGenModule &CGM, SourceLocation Loc);
private:
void createWorkerFunction(CodeGenModule &CGM);
};
- bool isInSpmdExecutionMode() const;
+ ExecutionMode getExecutionMode() const;
- /// \brief Emit the worker function for the current target region.
+ /// Emit the worker function for the current target region.
void emitWorkerFunction(WorkerFunctionState &WST);
- /// \brief Helper for worker function. Emit body of worker loop.
+ /// Helper for worker function. Emit body of worker loop.
void emitWorkerLoop(CodeGenFunction &CGF, WorkerFunctionState &WST);
- /// \brief Helper for generic target entry function. Guide the master and
+ /// Helper for non-SPMD target entry function. Guide the master and
/// worker threads to their respective locations.
- void emitGenericEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
+ void emitNonSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
WorkerFunctionState &WST);
- /// \brief Signal termination of OMP execution for generic target entry
+ /// Signal termination of OMP execution for non-SPMD target entry
/// function.
- void emitGenericEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
+ void emitNonSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
+
+ /// Helper for generic variables globalization prolog.
+ void emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc);
+
+ /// Helper for generic variables globalization epilog.
+ void emitGenericVarsEpilog(CodeGenFunction &CGF);
- /// \brief Helper for Spmd mode target directive's entry function.
- void emitSpmdEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
+ /// Helper for SPMD mode target directive's entry function.
+ void emitSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
const OMPExecutableDirective &D);
- /// \brief Signal termination of Spmd mode execution.
- void emitSpmdEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
+ /// Signal termination of SPMD mode execution.
+ void emitSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
//
// Base class overrides.
//
- /// \brief Creates offloading entry for the provided entry ID \a ID,
+ /// Creates offloading entry for the provided entry ID \a ID,
/// address \a Addr, size \a Size, and flags \a Flags.
void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr,
- uint64_t Size, int32_t Flags = 0) override;
+ uint64_t Size, int32_t Flags,
+ llvm::GlobalValue::LinkageTypes Linkage) override;
- /// \brief Emit outlined function specialized for the Fork-Join
+ /// Emit outlined function specialized for the Fork-Join
/// programming model for applicable target directives on the NVPTX device.
/// \param D Directive to emit.
/// \param ParentName Name of the function that encloses the target region.
@@ -85,12 +103,12 @@ private:
/// \param IsOffloadEntry True if the outlined function is an offload entry.
/// An outlined function may not be an entry if, e.g. the if clause always
/// evaluates to false.
- void emitGenericKernel(const OMPExecutableDirective &D, StringRef ParentName,
+ void emitNonSPMDKernel(const OMPExecutableDirective &D, StringRef ParentName,
llvm::Function *&OutlinedFn,
llvm::Constant *&OutlinedFnID, bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen);
- /// \brief Emit outlined function specialized for the Single Program
+ /// Emit outlined function specialized for the Single Program
/// Multiple Data programming model for applicable target directives on the
/// NVPTX device.
/// \param D Directive to emit.
@@ -101,12 +119,12 @@ private:
/// \param CodeGen Object containing the target statements.
/// An outlined function may not be an entry if, e.g. the if clause always
/// evaluates to false.
- void emitSpmdKernel(const OMPExecutableDirective &D, StringRef ParentName,
+ void emitSPMDKernel(const OMPExecutableDirective &D, StringRef ParentName,
llvm::Function *&OutlinedFn,
llvm::Constant *&OutlinedFnID, bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen);
- /// \brief Emit outlined function for 'target' directive on the NVPTX
+ /// Emit outlined function for 'target' directive on the NVPTX
/// device.
/// \param D Directive to emit.
/// \param ParentName Name of the function that encloses the target region.
@@ -122,22 +140,22 @@ private:
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen) override;
- /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// Emits code for parallel or serial call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
- /// This call is for the Generic Execution Mode.
+ /// This call is for the Non-SPMD Execution Mode.
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
/// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
/// \param CapturedVars A pointer to the record with the references to
/// variables used in \a OutlinedFn function.
/// \param IfCond Condition in the associated 'if' clause, if it was
/// specified, nullptr otherwise.
- void emitGenericParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ void emitNonSPMDParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond);
- /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// Emits code for parallel or serial call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// This call is for a parallel directive within an SPMD target directive.
@@ -148,13 +166,13 @@ private:
/// \param IfCond Condition in the associated 'if' clause, if it was
/// specified, nullptr otherwise.
///
- void emitSpmdParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ void emitSPMDParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond);
protected:
- /// \brief Get the function name of an outlined region.
+ /// Get the function name of an outlined region.
// The name can be customized depending on the target.
//
StringRef getOutlinedHelperName() const override {
@@ -164,13 +182,13 @@ protected:
public:
explicit CGOpenMPRuntimeNVPTX(CodeGenModule &CGM);
- /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
+ /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
/// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
virtual void emitProcBindClause(CodeGenFunction &CGF,
OpenMPProcBindClauseKind ProcBind,
SourceLocation Loc) override;
- /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
+ /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
/// clause.
/// \param NumThreads An integer value of threads.
@@ -178,7 +196,7 @@ public:
llvm::Value *NumThreads,
SourceLocation Loc) override;
- /// \brief This function ought to emit, in the general case, a call to
+ /// This function ought to emit, in the general case, a call to
// the openmp runtime kmpc_push_num_teams. In NVPTX backend it is not needed
// as these numbers are obtained through the PTX grid and block configuration.
/// \param NumTeams An integer expression of teams.
@@ -186,7 +204,7 @@ public:
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
const Expr *ThreadLimit, SourceLocation Loc) override;
- /// \brief Emits inlined function for the specified OpenMP parallel
+ /// Emits inlined function for the specified OpenMP parallel
// directive.
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
@@ -201,7 +219,7 @@ public:
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) override;
- /// \brief Emits inlined function for the specified OpenMP teams
+ /// Emits inlined function for the specified OpenMP teams
// directive.
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
@@ -216,7 +234,7 @@ public:
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) override;
- /// \brief Emits code for teams call of the \a OutlinedFn with
+ /// Emits code for teams call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run by team masters. Type of
@@ -228,7 +246,7 @@ public:
SourceLocation Loc, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars) override;
- /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// Emits code for parallel or serial call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
@@ -242,6 +260,16 @@ public:
ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond) override;
+ /// Emits a critical region.
+ /// \param CriticalName Name of the critical region.
+ /// \param CriticalOpGen Generator for the statement associated with the given
+ /// critical region.
+ /// \param Hint Value of the 'hint' clause (optional).
+ void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen,
+ SourceLocation Loc,
+ const Expr *Hint = nullptr) override;
+
/// Emit a code for reduction clause.
///
/// \param Privates List of private copies for original reduction arguments.
@@ -270,7 +298,7 @@ public:
/// Translates the native parameter of outlined function if this is required
/// for target.
- /// \param FD Field decl from captured record for the paramater.
+ /// \param FD Field decl from captured record for the parameter.
/// \param NativeParam Parameter itself.
const VarDecl *translateParameter(const FieldDecl *FD,
const VarDecl *NativeParam) const override;
@@ -288,23 +316,41 @@ public:
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.
- enum ExecutionMode {
- /// Single Program Multiple Data.
- Spmd,
- /// Generic codegen to support fork-join model.
+ /// Emits OpenMP-specific function prolog.
+ /// Required for device constructs.
+ void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) override;
+
+ /// Gets the OpenMP-specific address of the local variable.
+ Address getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD) override;
+
+ /// Target codegen is specialized based on two data-sharing modes: CUDA, in
+ /// which the local variables are actually global threadlocal, and Generic, in
+ /// which the local variables are placed in global memory if they may escape
+ /// their declaration context.
+ enum DataSharingMode {
+ /// CUDA data sharing mode.
+ CUDA,
+ /// Generic data-sharing mode.
Generic,
- Unknown,
};
+ /// Cleans up references to the objects in finished function.
+ ///
+ void functionFinished(CodeGenFunction &CGF) override;
+
private:
- // Track the execution mode when codegening directives within a target
- // region. The appropriate mode (generic/spmd) is set on entry to the
- // target region and used by containing directives such as 'parallel'
- // to emit optimized code.
- ExecutionMode CurrentExecutionMode;
+ /// Track the execution mode when codegening directives within a target
+ /// region. The appropriate mode (SPMD/NON-SPMD) is set on entry to the
+ /// target region and used by containing directives such as 'parallel'
+ /// to emit optimized code.
+ ExecutionMode CurrentExecutionMode = EM_Unknown;
+
+ /// true if we're emitting the code for the target region and next parallel
+ /// region is L0 for sure.
+ bool IsInTargetMasterThreadRegion = false;
+ /// true if we're definitely in the parallel region.
+ bool IsInParallelRegion = false;
/// Map between an outlined function and its wrapper.
llvm::DenseMap<llvm::Function *, llvm::Function *> WrapperFunctionsMap;
@@ -313,9 +359,26 @@ private:
/// 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);
+ llvm::Function *createParallelDataSharingWrapper(
+ llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D);
+
+ /// The map of local variables to their addresses in the global memory.
+ using DeclToAddrMapTy = llvm::MapVector<const Decl *,
+ std::pair<const FieldDecl *, Address>>;
+ /// Set of the parameters passed by value escaping OpenMP context.
+ using EscapedParamsTy = llvm::SmallPtrSet<const Decl *, 4>;
+ struct FunctionData {
+ DeclToAddrMapTy LocalVarData;
+ EscapedParamsTy EscapedParameters;
+ llvm::SmallVector<const ValueDecl*, 4> EscapedVariableLengthDecls;
+ llvm::SmallVector<llvm::Value *, 4> EscapedVariableLengthDeclsAddrs;
+ const RecordDecl *GlobalRecord = nullptr;
+ llvm::Value *GlobalRecordAddr = nullptr;
+ std::unique_ptr<CodeGenFunction::OMPMapVars> MappedParams;
+ };
+ /// Maps the function to the list of the globalized variables with their
+ /// addresses.
+ llvm::SmallDenseMap<llvm::Function *, FunctionData> FunctionGlobalizedDecls;
};
} // CodeGen namespace.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
index 7b9c27d1d772..41084294ab9a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
@@ -23,7 +23,7 @@ namespace llvm {
namespace clang {
namespace CodeGen {
-/// \brief Structure with information about how a bitfield should be accessed.
+/// Structure with information about how a bitfield should be accessed.
///
/// Often we layout a sequence of bitfields as a contiguous sequence of bits.
/// When the AST record layout does this, we represent it in the LLVM IR's type
@@ -92,7 +92,7 @@ struct CGBitFieldInfo {
void print(raw_ostream &OS) const;
void dump() const;
- /// \brief Given a bit-field decl, build an appropriate helper object for
+ /// Given a bit-field decl, build an appropriate helper object for
/// accessing that field (which is expected to have the given offset and
/// size).
static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types,
@@ -156,31 +156,31 @@ public:
IsZeroInitializable(IsZeroInitializable),
IsZeroInitializableAsBase(IsZeroInitializableAsBase) {}
- /// \brief Return the "complete object" LLVM type associated with
+ /// Return the "complete object" LLVM type associated with
/// this record.
llvm::StructType *getLLVMType() const {
return CompleteObjectType;
}
- /// \brief Return the "base subobject" LLVM type associated with
+ /// Return the "base subobject" LLVM type associated with
/// this record.
llvm::StructType *getBaseSubobjectLLVMType() const {
return BaseSubobjectType;
}
- /// \brief Check whether this struct can be C++ zero-initialized
+ /// Check whether this struct can be C++ zero-initialized
/// with a zeroinitializer.
bool isZeroInitializable() const {
return IsZeroInitializable;
}
- /// \brief Check whether this struct can be C++ zero-initialized
+ /// Check whether this struct can be C++ zero-initialized
/// with a zeroinitializer when considered as a base subobject.
bool isZeroInitializableAsBase() const {
return IsZeroInitializableAsBase;
}
- /// \brief Return llvm::StructType element number that corresponds to the
+ /// Return llvm::StructType element number that corresponds to the
/// field FD.
unsigned getLLVMFieldNo(const FieldDecl *FD) const {
FD = FD->getCanonicalDecl();
@@ -193,14 +193,14 @@ public:
return NonVirtualBases.lookup(RD);
}
- /// \brief Return the LLVM field index corresponding to the given
+ /// Return the LLVM field index corresponding to the given
/// virtual base. Only valid when operating on the complete object.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const {
assert(CompleteObjectVirtualBases.count(base) && "Invalid virtual base!");
return CompleteObjectVirtualBases.lookup(base);
}
- /// \brief Return the BitFieldInfo that corresponds to the field FD.
+ /// Return the BitFieldInfo that corresponds to the field FD.
const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const {
FD = FD->getCanonicalDecl();
assert(FD->isBitField() && "Invalid call for non-bit-field decl!");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 1644ab4c0725..58aaae692552 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -62,7 +62,7 @@ namespace {
/// because LLVM reads from the complete type it can generate incorrect code
/// if we do not clip the tail padding off of the bitfield in the complete
/// layout. This introduces a somewhat awkward extra unnecessary clip stage.
-/// The location of the clip is stored internally as a sentinal of type
+/// The location of the clip is stored internally as a sentinel of type
/// SCISSOR. If LLVM were updated to read base types (which it probably
/// should because locations of things such as VBases are bogus in the llvm
/// type anyway) then we could eliminate the SCISSOR.
@@ -74,7 +74,7 @@ namespace {
struct CGRecordLowering {
// MemberInfo is a helper structure that contains information about a record
// member. In additional to the standard member types, there exists a
- // sentinal member type that ensures correct rounding.
+ // sentinel member type that ensures correct rounding.
struct MemberInfo {
CharUnits Offset;
enum InfoKind { VFPtr, VBPtr, Field, Base, VBase, Scissor } Kind;
@@ -95,7 +95,7 @@ struct CGRecordLowering {
// The constructor.
CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D, bool Packed);
// Short helper routines.
- /// \brief Constructs a MemberInfo instance from an offset and llvm::Type *.
+ /// Constructs a MemberInfo instance from an offset and llvm::Type *.
MemberInfo StorageInfo(CharUnits Offset, llvm::Type *Data) {
return MemberInfo(Offset, MemberInfo::Field, Data);
}
@@ -118,19 +118,19 @@ struct CGRecordLowering {
return !Context.getTargetInfo().getCXXABI().isMicrosoft();
}
- /// \brief Wraps llvm::Type::getIntNTy with some implicit arguments.
+ /// Wraps llvm::Type::getIntNTy with some implicit arguments.
llvm::Type *getIntNType(uint64_t NumBits) {
return llvm::Type::getIntNTy(Types.getLLVMContext(),
(unsigned)llvm::alignTo(NumBits, 8));
}
- /// \brief Gets an llvm type of size NumBytes and alignment 1.
+ /// Gets an llvm type of size NumBytes and alignment 1.
llvm::Type *getByteArrayType(CharUnits NumBytes) {
assert(!NumBytes.isZero() && "Empty byte arrays aren't allowed.");
llvm::Type *Type = llvm::Type::getInt8Ty(Types.getLLVMContext());
return NumBytes == CharUnits::One() ? Type :
(llvm::Type *)llvm::ArrayType::get(Type, NumBytes.getQuantity());
}
- /// \brief Gets the storage type for a field decl and handles storage
+ /// Gets the storage type for a field decl and handles storage
/// for itanium bitfields that are smaller than their declared type.
llvm::Type *getStorageType(const FieldDecl *FD) {
llvm::Type *Type = Types.ConvertTypeForMem(FD->getType());
@@ -139,7 +139,7 @@ struct CGRecordLowering {
return getIntNType(std::min(FD->getBitWidthValue(Context),
(unsigned)Context.toBits(getSize(Type))));
}
- /// \brief Gets the llvm Basesubobject type from a CXXRecordDecl.
+ /// Gets the llvm Basesubobject type from a CXXRecordDecl.
llvm::Type *getStorageType(const CXXRecordDecl *RD) {
return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType();
}
@@ -166,9 +166,9 @@ struct CGRecordLowering {
return Layout.getFieldOffset(FD->getFieldIndex());
}
// Layout routines.
- void setBitFieldInfo(const FieldDecl *FD, CharUnits StartOffset,
+ void setBitFieldInfo(const FieldDecl *FD, CharUnits StartOffset,
llvm::Type *StorageType);
- /// \brief Lowers an ASTRecordLayout to a llvm type.
+ /// Lowers an ASTRecordLayout to a llvm type.
void lower(bool NonVirtualBaseType);
void lowerUnion();
void accumulateFields();
@@ -177,18 +177,18 @@ struct CGRecordLowering {
void accumulateBases();
void accumulateVPtrs();
void accumulateVBases();
- /// \brief Recursively searches all of the bases to find out if a vbase is
+ /// Recursively searches all of the bases to find out if a vbase is
/// not the primary vbase of some base class.
bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query);
void calculateZeroInit();
- /// \brief Lowers bitfield storage types to I8 arrays for bitfields with tail
+ /// Lowers bitfield storage types to I8 arrays for bitfields with tail
/// padding that is or can potentially be used.
void clipTailPadding();
- /// \brief Determines if we need a packed llvm struct.
+ /// Determines if we need a packed llvm struct.
void determinePacked(bool NVBaseType);
- /// \brief Inserts padding everwhere it's needed.
+ /// Inserts padding everywhere it's needed.
void insertPadding();
- /// \brief Fills out the structures that are ultimately consumed.
+ /// Fills out the structures that are ultimately consumed.
void fillOutputFields();
// Input memoization fields.
CodeGenTypes &Types;
@@ -214,12 +214,13 @@ private:
};
} // namespace {
-CGRecordLowering::CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D, bool Packed)
- : Types(Types), Context(Types.getContext()), D(D),
- RD(dyn_cast<CXXRecordDecl>(D)),
- Layout(Types.getContext().getASTRecordLayout(D)),
- DataLayout(Types.getDataLayout()), IsZeroInitializable(true),
- IsZeroInitializableAsBase(true), Packed(Packed) {}
+CGRecordLowering::CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D,
+ bool Packed)
+ : Types(Types), Context(Types.getContext()), D(D),
+ RD(dyn_cast<CXXRecordDecl>(D)),
+ Layout(Types.getContext().getASTRecordLayout(D)),
+ DataLayout(Types.getDataLayout()), IsZeroInitializable(true),
+ IsZeroInitializableAsBase(true), Packed(Packed) {}
void CGRecordLowering::setBitFieldInfo(
const FieldDecl *FD, CharUnits StartOffset, llvm::Type *StorageType) {
@@ -245,7 +246,7 @@ void CGRecordLowering::lower(bool NVBaseType) {
// 1) Store all members (fields and bases) in a list and sort them by offset.
// 2) Add a 1-byte capstone member at the Size of the structure.
// 3) Clip bitfield storages members if their tail padding is or might be
- // used by another field or base. The clipping process uses the capstone
+ // used by another field or base. The clipping process uses the capstone
// by treating it as another object that occurs after the record.
// 4) Determine if the llvm-struct requires packing. It's important that this
// phase occur after clipping, because clipping changes the llvm type.
@@ -294,8 +295,7 @@ void CGRecordLowering::lowerUnion() {
// been doing and cause lit tests to change.
for (const auto *Field : D->fields()) {
if (Field->isBitField()) {
- // Skip 0 sized bitfields.
- if (Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
llvm::Type *FieldType = getStorageType(Field);
if (LayoutSize < getSize(FieldType))
@@ -313,9 +313,8 @@ void CGRecordLowering::lowerUnion() {
if (!SeenNamedMember) {
SeenNamedMember = Field->getIdentifier();
if (!SeenNamedMember)
- if (const auto *FieldRD =
- dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
- SeenNamedMember = FieldRD->findFirstNamedDataMember();
+ if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
+ SeenNamedMember = FieldRD->findFirstNamedDataMember();
if (SeenNamedMember && !isZeroInitializable(Field)) {
IsZeroInitializable = IsZeroInitializableAsBase = false;
StorageType = FieldType;
@@ -380,7 +379,7 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
for (; Field != FieldEnd; ++Field) {
uint64_t BitOffset = getFieldBitOffset(*Field);
// Zero-width bitfields end runs.
- if (Field->getBitWidthValue(Context) == 0) {
+ if (Field->isZeroLengthBitField(Context)) {
Run = FieldEnd;
continue;
}
@@ -404,19 +403,20 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
return;
}
- // Check if current Field is better as a single field run. When current field
+ // Check if OffsetInRecord is better as a single field run. When OffsetInRecord
// 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) {
+ auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord,
+ uint64_t StartBitOffset) {
if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
return false;
- unsigned Width = Field->getBitWidthValue(Context);
- if (!DataLayout.isLegalInteger(Width))
+ if (!DataLayout.isLegalInteger(OffsetInRecord))
return false;
- // Make sure Field is natually aligned if it is treated as an IType integer.
- if (getFieldBitOffset(*Field) %
- Context.toBits(getAlignment(getIntNType(Width))) !=
+ // Make sure StartBitOffset is natually aligned if it is treated as an
+ // IType integer.
+ if (StartBitOffset %
+ Context.toBits(getAlignment(getIntNType(OffsetInRecord))) !=
0)
return false;
return true;
@@ -431,26 +431,31 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
if (Field == FieldEnd)
break;
// Any non-zero-length bitfield can start a new run.
- if (Field->getBitWidthValue(Context) != 0) {
+ if (!Field->isZeroLengthBitField(Context)) {
Run = Field;
StartBitOffset = getFieldBitOffset(*Field);
Tail = StartBitOffset + Field->getBitWidthValue(Context);
- StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Run);
+ StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Tail - StartBitOffset,
+ StartBitOffset);
}
++Field;
continue;
}
// 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 current field (or consecutive fields) is better as a single run, or
+ // if current field has zero width bitfield and either
+ // UseZeroLengthBitfieldAlignment or UseBitFieldTypeAlignment is set to
+ // true, 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 &&
+ !IsBetterAsSingleFieldRun(Tail - StartBitOffset, StartBitOffset) &&
+ (!Field->isZeroLengthBitField(Context) ||
+ (!Context.getTargetInfo().useZeroLengthBitfieldAlignment() &&
+ !Context.getTargetInfo().useBitFieldTypeAlignment())) &&
Tail == getFieldBitOffset(*Field)) {
Tail += Field->getBitWidthValue(Context);
++Field;
@@ -626,7 +631,7 @@ void CGRecordLowering::determinePacked(bool NVBaseType) {
// non-virtual sub-object and an unpacked complete object or vise versa.
if (NVSize % NVAlignment)
Packed = true;
- // Update the alignment of the sentinal.
+ // Update the alignment of the sentinel.
if (!Packed)
Members.back().Data = getIntNType(Context.toBits(Alignment));
}
@@ -681,7 +686,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t Offset, uint64_t Size,
uint64_t StorageSize,
CharUnits StorageOffset) {
- // This function is vestigial from CGRecordLayoutBuilder days but is still
+ // This function is vestigial from CGRecordLayoutBuilder days but is still
// used in GCObjCRuntime.cpp. That usage has a "fixme" attached to it that
// when addressed will allow for the removal of this function.
llvm::Type *Ty = Types.ConvertTypeForMem(FD->getType());
@@ -776,17 +781,16 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
if (BaseTy) {
CharUnits NonVirtualSize = Layout.getNonVirtualSize();
- uint64_t AlignedNonVirtualTypeSizeInBits =
+ uint64_t AlignedNonVirtualTypeSizeInBits =
getContext().toBits(NonVirtualSize);
- assert(AlignedNonVirtualTypeSizeInBits ==
+ assert(AlignedNonVirtualTypeSizeInBits ==
getDataLayout().getTypeAllocSizeInBits(BaseTy) &&
"Type size mismatch!");
}
-
+
// Verify that the LLVM and AST field offsets agree.
- llvm::StructType *ST =
- dyn_cast<llvm::StructType>(RL->getLLVMType());
+ llvm::StructType *ST = RL->getLLVMType();
const llvm::StructLayout *SL = getDataLayout().getStructLayout(ST);
const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D);
@@ -802,13 +806,13 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
"Invalid field offset!");
continue;
}
-
+
// Ignore unnamed bit-fields.
if (!FD->getDeclName())
continue;
// Don't inspect zero-length bitfields.
- if (FD->getBitWidthValue(getContext()) == 0)
+ if (FD->isZeroLengthBitField(getContext()))
continue;
const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD);
@@ -849,7 +853,7 @@ void CGRecordLayout::print(raw_ostream &OS) const {
OS << "<CGRecordLayout\n";
OS << " LLVMType:" << *CompleteObjectType << "\n";
if (BaseSubobjectType)
- OS << " NonVirtualBaseLLVMType:" << *BaseSubobjectType << "\n";
+ OS << " NonVirtualBaseLLVMType:" << *BaseSubobjectType << "\n";
OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";
OS << " BitFields:[\n";
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
index 97e35e2b6e8d..79662ec0099f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
@@ -608,7 +608,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitStmt(S.getInit());
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
@@ -705,7 +705,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
RunCleanupsScope ConditionScope(*this);
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
// Evaluate the conditional in the while header. C99 6.8.5.1: The
// evaluation of the controlling expression takes place before each
@@ -777,11 +777,6 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
- const SourceRange &R = S.getSourceRange();
- LoopStack.push(LoopBody, CGM.getContext(), DoAttrs,
- SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()));
-
EmitBlockWithFallThrough(LoopBody, &S);
{
RunCleanupsScope BodyScope(*this);
@@ -790,6 +785,11 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
EmitBlock(LoopCond.getBlock());
+ const SourceRange &R = S.getSourceRange();
+ LoopStack.push(LoopBody, CGM.getContext(), DoAttrs,
+ SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()));
+
// C99 6.8.5.2: "The evaluation of the controlling expression takes place
// after each execution of the loop body."
@@ -865,7 +865,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
// If the for statement has a condition scope, emit the local variable
// declaration.
if (S.getConditionVariable()) {
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
}
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
@@ -1005,7 +1005,9 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
if (RV.isScalar()) {
Builder.CreateStore(RV.getScalarVal(), ReturnValue);
} else if (RV.isAggregate()) {
- EmitAggregateCopy(ReturnValue, RV.getAggregateAddress(), Ty);
+ LValue Dest = MakeAddrLValue(ReturnValue, Ty);
+ LValue Src = MakeAddrLValue(RV.getAggregateAddress(), Ty);
+ EmitAggregateCopy(Dest, Src, Ty, overlapForReturnValue());
} else {
EmitStoreOfComplex(RV.getComplexVal(), MakeAddrLValue(ReturnValue, Ty),
/*init*/ true);
@@ -1035,7 +1037,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
Builder.ClearInsertionPoint();
}
- // Emit the result value, even if unused, to evalute the side effects.
+ // Emit the result value, even if unused, to evaluate the side effects.
const Expr *RV = S.getRetValue();
// Treat block literals in a return expression as if they appeared
@@ -1083,11 +1085,12 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
/*isInit*/ true);
break;
case TEK_Aggregate:
- EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue,
- Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ EmitAggExpr(RV, AggValueSlot::forAddr(
+ ReturnValue, Qualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased,
+ overlapForReturnValue()));
break;
}
}
@@ -1572,7 +1575,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// Emit the condition variable if needed inside the entire cleanup scope
// used by this special case for constant folded switches.
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
// At this point, we are no longer "within" a switch instance, so
// we can temporarily enforce this to ensure that any embedded case
@@ -1601,7 +1604,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
EmitStmt(S.getInit());
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
llvm::Value *CondV = EmitScalarExpr(S.getCond());
// Create basic block to hold stuff that comes after switch
@@ -1924,7 +1927,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
// Simplify the output constraint.
std::string OutputConstraint(S.getOutputConstraint(i));
OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1,
- getTarget());
+ getTarget(), &OutputConstraintInfos);
const Expr *OutExpr = S.getOutputExpr(i);
OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
@@ -2131,7 +2134,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
llvm::InlineAsm *IA =
llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect,
/* IsAlignStack */ false, AsmDialect);
- llvm::CallInst *Result = Builder.CreateCall(IA, Args);
+ llvm::CallInst *Result =
+ Builder.CreateCall(IA, Args, getBundlesForFunclet(IA));
Result->addAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoUnwind);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 26817ac330ba..03102f04aa9c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -29,12 +29,13 @@ namespace {
class OMPLexicalScope : public CodeGenFunction::LexicalScope {
void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
for (const auto *C : S.clauses()) {
- if (auto *CPI = OMPClauseWithPreInit::get(C)) {
- if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
+ if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
+ if (const auto *PreInit =
+ cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
for (const auto *I : PreInit->decls()) {
- if (!I->hasAttr<OMPCaptureNoInitAttr>())
+ if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
CGF.EmitVarDecl(cast<VarDecl>(*I));
- else {
+ } else {
CodeGenFunction::AutoVarEmission Emission =
CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
CGF.EmitAutoVarCleanups(Emission);
@@ -53,34 +54,35 @@ class OMPLexicalScope : public CodeGenFunction::LexicalScope {
}
public:
- OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S,
- bool AsInlined = false, bool EmitPreInitStmt = true)
+ OMPLexicalScope(
+ CodeGenFunction &CGF, const OMPExecutableDirective &S,
+ const llvm::Optional<OpenMPDirectiveKind> CapturedRegion = llvm::None,
+ const bool EmitPreInitStmt = true)
: CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
InlinedShareds(CGF) {
if (EmitPreInitStmt)
emitPreInitStmt(CGF, S);
- if (AsInlined) {
- if (S.hasAssociatedStmt()) {
- auto *CS = cast<CapturedStmt>(S.getAssociatedStmt());
- 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 &&
- InlinedShareds.isGlobalVarCaptured(VD)),
- VD->getType().getNonReferenceType(), VK_LValue,
- SourceLocation());
- InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
- return CGF.EmitLValue(&DRE).getAddress();
- });
- }
- }
- (void)InlinedShareds.Privatize();
+ if (!CapturedRegion.hasValue())
+ return;
+ assert(S.hasAssociatedStmt() &&
+ "Expected associated statement for inlined directive.");
+ const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
+ for (const 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 &&
+ InlinedShareds.isGlobalVarCaptured(VD)),
+ VD->getType().getNonReferenceType(), VK_LValue, C.getLocation());
+ InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
+ return CGF.EmitLValue(&DRE).getAddress();
+ });
}
}
+ (void)InlinedShareds.Privatize();
}
};
@@ -96,9 +98,8 @@ class OMPParallelScope final : public OMPLexicalScope {
public:
OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
- : OMPLexicalScope(CGF, S,
- /*AsInlined=*/false,
- /*EmitPreInitStmt=*/EmitPreInitStmt(S)) {}
+ : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None,
+ EmitPreInitStmt(S)) {}
};
/// Lexical scope for OpenMP teams construct, that handles correct codegen
@@ -112,29 +113,26 @@ class OMPTeamsScope final : public OMPLexicalScope {
public:
OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
- : OMPLexicalScope(CGF, S,
- /*AsInlined=*/false,
- /*EmitPreInitStmt=*/EmitPreInitStmt(S)) {}
+ : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None,
+ EmitPreInitStmt(S)) {}
};
/// Private scope for OpenMP loop-based directives, that supports capturing
/// 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()) {
+ CodeGenFunction::OMPMapVars PreCondVars;
+ for (const 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)PreCondVars.setVarAddr(
+ CGF, VD, 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())
- CGF.EmitVarDecl(cast<VarDecl>(*I));
- }
+ (void)PreCondVars.apply(CGF);
+ if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) {
+ for (const auto *I : PreInits->decls())
+ CGF.EmitVarDecl(cast<VarDecl>(*I));
}
+ PreCondVars.restore(CGF);
}
public:
@@ -159,12 +157,13 @@ public:
: CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
InlinedShareds(CGF) {
for (const auto *C : S.clauses()) {
- if (auto *CPI = OMPClauseWithPreInit::get(C)) {
- if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
+ if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
+ if (const auto *PreInit =
+ cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
for (const auto *I : PreInit->decls()) {
- if (!I->hasAttr<OMPCaptureNoInitAttr>())
+ if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
CGF.EmitVarDecl(cast<VarDecl>(*I));
- else {
+ } else {
CodeGenFunction::AutoVarEmission Emission =
CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
CGF.EmitAutoVarCleanups(Emission);
@@ -197,7 +196,7 @@ public:
(CGF.CapturedStmtInfo &&
InlinedShareds.isGlobalVarCaptured(VD)),
VD->getType().getNonReferenceType(), VK_LValue,
- SourceLocation());
+ C.getLocation());
InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
return CGF.EmitLValue(&DRE).getAddress();
});
@@ -216,8 +215,8 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen);
LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
- if (auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
- if (auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
+ if (const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
OrigVD = OrigVD->getCanonicalDecl();
bool IsCaptured =
LambdaCaptureFields.lookup(OrigVD) ||
@@ -232,23 +231,23 @@ LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
}
llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
- auto &C = getContext();
+ ASTContext &C = getContext();
llvm::Value *Size = nullptr;
auto SizeInChars = C.getTypeSizeInChars(Ty);
if (SizeInChars.isZero()) {
// getTypeSizeInChars() returns 0 for a VLA.
- while (auto *VAT = C.getAsVariableArrayType(Ty)) {
- llvm::Value *ArraySize;
- std::tie(ArraySize, Ty) = getVLASize(VAT);
- Size = Size ? Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
+ while (const VariableArrayType *VAT = C.getAsVariableArrayType(Ty)) {
+ VlaSizePair VlaSize = getVLASize(VAT);
+ Ty = VlaSize.Type;
+ Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts)
+ : VlaSize.NumElts;
}
SizeInChars = C.getTypeSizeInChars(Ty);
if (SizeInChars.isZero())
return llvm::ConstantInt::get(SizeTy, /*V=*/0);
- Size = Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
- } else
- Size = CGM.getSize(SizeInChars);
- return Size;
+ return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
+ }
+ return CGM.getSize(SizeInChars);
}
void CodeGenFunction::GenerateOpenMPCapturedVars(
@@ -260,27 +259,26 @@ void CodeGenFunction::GenerateOpenMPCapturedVars(
E = S.capture_init_end();
I != E; ++I, ++CurField, ++CurCap) {
if (CurField->hasCapturedVLAType()) {
- auto VAT = CurField->getCapturedVLAType();
- auto *Val = VLASizeMap[VAT->getSizeExpr()];
+ const VariableArrayType *VAT = CurField->getCapturedVLAType();
+ llvm::Value *Val = VLASizeMap[VAT->getSizeExpr()];
CapturedVars.push_back(Val);
- } else if (CurCap->capturesThis())
+ } else if (CurCap->capturesThis()) {
CapturedVars.push_back(CXXThisValue);
- else if (CurCap->capturesVariableByCopy()) {
- llvm::Value *CV =
- EmitLoadOfLValue(EmitLValue(*I), SourceLocation()).getScalarVal();
+ } else if (CurCap->capturesVariableByCopy()) {
+ llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation());
// If the field is not a pointer, we need to save the actual value
// and load it as a void pointer.
if (!CurField->getType()->isAnyPointerType()) {
- auto &Ctx = getContext();
- auto DstAddr = CreateMemTemp(
+ ASTContext &Ctx = getContext();
+ Address DstAddr = CreateMemTemp(
Ctx.getUIntPtrType(),
- Twine(CurCap->getCapturedVar()->getName()) + ".casted");
+ Twine(CurCap->getCapturedVar()->getName(), ".casted"));
LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
- auto *SrcAddrVal = EmitScalarConversion(
+ llvm::Value *SrcAddrVal = EmitScalarConversion(
DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
- Ctx.getPointerType(CurField->getType()), SourceLocation());
+ Ctx.getPointerType(CurField->getType()), CurCap->getLocation());
LValue SrcLV =
MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType());
@@ -288,7 +286,7 @@ void CodeGenFunction::GenerateOpenMPCapturedVars(
EmitStoreThroughLValue(RValue::get(CV), SrcLV);
// Load the value using the destination type pointer.
- CV = EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
+ CV = EmitLoadOfScalar(DstLV, CurCap->getLocation());
}
CapturedVars.push_back(CV);
} else {
@@ -298,15 +296,16 @@ void CodeGenFunction::GenerateOpenMPCapturedVars(
}
}
-static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType,
- StringRef Name, LValue AddrLV,
+static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc,
+ QualType DstType, StringRef Name,
+ LValue AddrLV,
bool isReferenceType = false) {
ASTContext &Ctx = CGF.getContext();
- auto *CastedPtr = CGF.EmitScalarConversion(
+ llvm::Value *CastedPtr = CGF.EmitScalarConversion(
AddrLV.getAddress().getPointer(), Ctx.getUIntPtrType(),
- Ctx.getPointerType(DstType), SourceLocation());
- auto TmpAddr =
+ Ctx.getPointerType(DstType), Loc);
+ Address TmpAddr =
CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType))
.getAddress();
@@ -314,27 +313,26 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType,
// reference instead of the reference of the value.
if (isReferenceType) {
QualType RefType = Ctx.getLValueReferenceType(DstType);
- auto *RefVal = TmpAddr.getPointer();
- TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name) + ".ref");
- auto TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType);
- CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit*/ true);
+ llvm::Value *RefVal = TmpAddr.getPointer();
+ TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name, ".ref"));
+ LValue TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType);
+ CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit=*/true);
}
return TmpAddr;
}
static QualType getCanonicalParamType(ASTContext &C, QualType T) {
- if (T->isLValueReferenceType()) {
+ if (T->isLValueReferenceType())
return C.getLValueReferenceType(
getCanonicalParamType(C, T.getNonReferenceType()),
/*SpelledAsLValue=*/false);
- }
if (T->isPointerType())
return C.getPointerType(getCanonicalParamType(C, T->getPointeeType()));
- if (auto *A = T->getAsArrayTypeUnsafe()) {
- if (auto *VLA = dyn_cast<VariableArrayType>(A))
+ if (const ArrayType *A = T->getAsArrayTypeUnsafe()) {
+ if (const auto *VLA = dyn_cast<VariableArrayType>(A))
return getCanonicalParamType(C, VLA->getElementType());
- else if (!A->isVariablyModifiedType())
+ if (!A->isVariablyModifiedType())
return C.getCanonicalType(T);
}
return C.getCanonicalParamType(T);
@@ -394,7 +392,7 @@ static llvm::Function *emitOutlinedFunctionPrologue(
Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI)),
SC_Static, /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false);
}
- for (auto *FD : RD->fields()) {
+ for (const FieldDecl *FD : RD->fields()) {
QualType ArgType = FD->getType();
IdentifierInfo *II = nullptr;
VarDecl *CapVar = nullptr;
@@ -404,18 +402,17 @@ static llvm::Function *emitOutlinedFunctionPrologue(
// uintptr. This is necessary given that the runtime library is only able to
// deal with pointers. We can pass in the same way the VLA type sizes to the
// outlined function.
- if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
- I->capturesVariableArrayType()) {
- if (FO.UIntPtrCastRequired)
- ArgType = Ctx.getUIntPtrType();
- }
+ if (FO.UIntPtrCastRequired &&
+ ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
+ I->capturesVariableArrayType()))
+ ArgType = Ctx.getUIntPtrType();
if (I->capturesVariable() || I->capturesVariableByCopy()) {
CapVar = I->getCapturedVar();
II = CapVar->getIdentifier();
- } else if (I->capturesThis())
+ } else if (I->capturesThis()) {
II = &Ctx.Idents.get("this");
- else {
+ } else {
assert(I->capturesVariableArrayType());
II = &Ctx.Idents.get("vla");
}
@@ -452,19 +449,20 @@ static llvm::Function *emitOutlinedFunctionPrologue(
CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
- llvm::Function *F =
+ auto *F =
llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
FO.FunctionName, &CGM.getModule());
CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
if (CD->isNothrow())
F->setDoesNotThrow();
+ F->setDoesNotRecurse();
// Generate the function.
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()) {
+ for (const FieldDecl *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]) {
@@ -496,23 +494,23 @@ static llvm::Function *emitOutlinedFunctionPrologue(
AlignmentSource::Decl);
if (FD->hasCapturedVLAType()) {
if (FO.UIntPtrCastRequired) {
- ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(),
- Args[Cnt]->getName(),
- ArgLVal),
- FD->getType(), AlignmentSource::Decl);
+ ArgLVal = CGF.MakeAddrLValue(
+ castValueFromUintptr(CGF, I->getLocation(), FD->getType(),
+ Args[Cnt]->getName(), ArgLVal),
+ FD->getType(), AlignmentSource::Decl);
}
- auto *ExprArg =
- CGF.EmitLoadOfLValue(ArgLVal, SourceLocation()).getScalarVal();
- auto VAT = FD->getCapturedVLAType();
- VLASizes.insert({Args[Cnt], {VAT->getSizeExpr(), ExprArg}});
+ llvm::Value *ExprArg = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
+ const VariableArrayType *VAT = FD->getCapturedVLAType();
+ VLASizes.try_emplace(Args[Cnt], VAT->getSizeExpr(), ExprArg);
} else if (I->capturesVariable()) {
- auto *Var = I->getCapturedVar();
+ const VarDecl *Var = I->getCapturedVar();
QualType VarTy = Var->getType();
Address ArgAddr = ArgLVal.getAddress();
if (!VarTy->isReferenceType()) {
if (ArgLVal.getType()->isLValueReferenceType()) {
ArgAddr = CGF.EmitLoadOfReference(ArgLVal);
- } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
+ } else if (!VarTy->isVariablyModifiedType() ||
+ !VarTy->isPointerType()) {
assert(ArgLVal.getType()->isPointerType());
ArgAddr = CGF.EmitLoadOfPointer(
ArgAddr, ArgLVal.getType()->castAs<PointerType>());
@@ -526,20 +524,19 @@ static llvm::Function *emitOutlinedFunctionPrologue(
} else if (I->capturesVariableByCopy()) {
assert(!FD->getType()->isAnyPointerType() &&
"Not expecting a captured pointer.");
- auto *Var = I->getCapturedVar();
+ const VarDecl *Var = I->getCapturedVar();
QualType VarTy = Var->getType();
LocalAddrs.insert(
{Args[Cnt],
- {Var,
- FO.UIntPtrCastRequired
- ? castValueFromUintptr(CGF, FD->getType(), Args[Cnt]->getName(),
- ArgLVal, VarTy->isReferenceType())
- : ArgLVal.getAddress()}});
+ {Var, FO.UIntPtrCastRequired
+ ? castValueFromUintptr(CGF, I->getLocation(),
+ FD->getType(), Args[Cnt]->getName(),
+ ArgLVal, VarTy->isReferenceType())
+ : ArgLVal.getAddress()}});
} else {
// If 'this' is captured, load it into CXXThisValue.
assert(I->capturesThis());
- CXXThisValue = CGF.EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation())
- .getScalarVal();
+ CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}});
}
++Cnt;
@@ -589,6 +586,7 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
/*RegisterCastedArgsOnly=*/true,
CapturedStmtInfo->getHelperName());
CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
+ WrapperCGF.CapturedStmtInfo = CapturedStmtInfo;
Args.clear();
LocalAddrs.clear();
VLASizes.clear();
@@ -604,16 +602,16 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
I->second.second,
I->second.first ? I->second.first->getType() : Arg->getType(),
AlignmentSource::Decl);
- CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation());
+ CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getLocStart());
} else {
auto EI = VLASizes.find(Arg);
- if (EI != VLASizes.end())
+ if (EI != VLASizes.end()) {
CallArg = EI->second.second;
- else {
+ } else {
LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
Arg->getType(),
AlignmentSource::Decl);
- CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation());
+ CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getLocStart());
}
}
CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
@@ -629,28 +627,28 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
//===----------------------------------------------------------------------===//
void CodeGenFunction::EmitOMPAggregateAssign(
Address DestAddr, Address SrcAddr, QualType OriginalType,
- const llvm::function_ref<void(Address, Address)> &CopyGen) {
+ const llvm::function_ref<void(Address, Address)> CopyGen) {
// Perform element-by-element initialization.
QualType ElementTy;
// Drill down to the base element type on both arrays.
- auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
- auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
+ const ArrayType *ArrayTy = OriginalType->getAsArrayTypeUnsafe();
+ llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
- auto SrcBegin = SrcAddr.getPointer();
- auto DestBegin = DestAddr.getPointer();
+ llvm::Value *SrcBegin = SrcAddr.getPointer();
+ llvm::Value *DestBegin = DestAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- auto DestEnd = Builder.CreateGEP(DestBegin, NumElements);
+ llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements);
// The basic structure here is a while-do loop.
- auto BodyBB = createBasicBlock("omp.arraycpy.body");
- auto DoneBB = createBasicBlock("omp.arraycpy.done");
- auto IsEmpty =
+ llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body");
+ llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done");
+ llvm::Value *IsEmpty =
Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
// Enter the loop body, making that address the current address.
- auto EntryBB = Builder.GetInsertBlock();
+ llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
EmitBlock(BodyBB);
CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
@@ -673,12 +671,12 @@ void CodeGenFunction::EmitOMPAggregateAssign(
CopyGen(DestElementCurrent, SrcElementCurrent);
// Shift the address forward by one element.
- auto DestElementNext = Builder.CreateConstGEP1_32(
+ llvm::Value *DestElementNext = Builder.CreateConstGEP1_32(
DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
- auto SrcElementNext = Builder.CreateConstGEP1_32(
+ llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32(
SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
// Check whether we've reached the end.
- auto Done =
+ llvm::Value *Done =
Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
Builder.CreateCondBr(Done, DoneBB, BodyBB);
DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
@@ -692,10 +690,12 @@ void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
Address SrcAddr, const VarDecl *DestVD,
const VarDecl *SrcVD, const Expr *Copy) {
if (OriginalType->isArrayType()) {
- auto *BO = dyn_cast<BinaryOperator>(Copy);
+ const auto *BO = dyn_cast<BinaryOperator>(Copy);
if (BO && BO->getOpcode() == BO_Assign) {
// Perform simple memcpy for simple copying.
- EmitAggregateAssign(DestAddr, SrcAddr, OriginalType);
+ LValue Dest = MakeAddrLValue(DestAddr, OriginalType);
+ LValue Src = MakeAddrLValue(SrcAddr, OriginalType);
+ EmitAggregateAssign(Dest, Src, OriginalType);
} else {
// For arrays with complex element types perform element by element
// copying.
@@ -706,11 +706,8 @@ void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
// destination and source variables to corresponding array
// elements.
CodeGenFunction::OMPPrivateScope Remap(*this);
- Remap.addPrivate(DestVD, [DestElement]() -> Address {
- return DestElement;
- });
- Remap.addPrivate(
- SrcVD, [SrcElement]() -> Address { return SrcElement; });
+ Remap.addPrivate(DestVD, [DestElement]() { return DestElement; });
+ Remap.addPrivate(SrcVD, [SrcElement]() { return SrcElement; });
(void)Remap.Privatize();
EmitIgnoredExpr(Copy);
});
@@ -718,8 +715,8 @@ void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
} else {
// Remap pseudo source variable to private copy.
CodeGenFunction::OMPPrivateScope Remap(*this);
- Remap.addPrivate(SrcVD, [SrcAddr]() -> Address { return SrcAddr; });
- Remap.addPrivate(DestVD, [DestAddr]() -> Address { return DestAddr; });
+ Remap.addPrivate(SrcVD, [SrcAddr]() { return SrcAddr; });
+ Remap.addPrivate(DestVD, [DestAddr]() { return DestAddr; });
(void)Remap.Privatize();
// Emit copying of the whole variable.
EmitIgnoredExpr(Copy);
@@ -738,17 +735,21 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
}
llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
- CGCapturedStmtInfo CapturesInfo(cast<CapturedStmt>(*D.getAssociatedStmt()));
+ llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+ getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
+ // Force emission of the firstprivate copy if the directive does not emit
+ // outlined function, like omp for, omp simd, omp distribute etc.
+ bool MustEmitFirstprivateCopy =
+ CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
auto IRef = C->varlist_begin();
auto InitsRef = C->inits().begin();
- for (auto IInit : C->private_copies()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *IInit : C->private_copies()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
bool ThisFirstprivateIsLastprivate =
Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
- auto *CapFD = CapturesInfo.lookup(OrigVD);
- auto *FD = CapturedStmtInfo->lookup(OrigVD);
- if (!ThisFirstprivateIsLastprivate && FD && (FD == CapFD) &&
+ const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD);
+ if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
!FD->getType()->isReferenceType()) {
EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
++IRef;
@@ -758,54 +759,61 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
FirstprivateIsLastprivate =
FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
- auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ const auto *VDInit =
+ cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
bool IsRegistered;
DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
/*RefersToEnclosingVariableOrCapture=*/FD != nullptr,
(*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
- Address OriginalAddr = EmitLValue(&DRE).getAddress();
+ LValue OriginalLVal = EmitLValue(&DRE);
QualType Type = VD->getType();
if (Type->isArrayType()) {
// Emit VarDecl with copy init for arrays.
// Get the address of the original variable captured in current
// captured region.
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
- auto Emission = EmitAutoVarAlloca(*VD);
- auto *Init = VD->getInit();
- if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
- // Perform simple memcpy.
- EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
- Type);
- } else {
- EmitOMPAggregateAssign(
- Emission.getAllocatedAddress(), OriginalAddr, Type,
- [this, VDInit, Init](Address DestElement,
- Address SrcElement) {
- // Clean up any temporaries needed by the initialization.
- RunCleanupsScope InitScope(*this);
- // Emit initialization for single element.
- setAddrOfLocalVar(VDInit, SrcElement);
- EmitAnyExprToMem(Init, DestElement,
- Init->getType().getQualifiers(),
- /*IsInitializer*/ false);
- LocalDeclMap.erase(VDInit);
- });
- }
- EmitAutoVarCleanups(Emission);
- return Emission.getAllocatedAddress();
- });
+ IsRegistered = PrivateScope.addPrivate(
+ OrigVD, [this, VD, Type, OriginalLVal, VDInit]() {
+ AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
+ const Expr *Init = VD->getInit();
+ if (!isa<CXXConstructExpr>(Init) ||
+ isTrivialInitializer(Init)) {
+ // Perform simple memcpy.
+ LValue Dest =
+ MakeAddrLValue(Emission.getAllocatedAddress(), Type);
+ EmitAggregateAssign(Dest, OriginalLVal, Type);
+ } else {
+ EmitOMPAggregateAssign(
+ Emission.getAllocatedAddress(), OriginalLVal.getAddress(),
+ Type,
+ [this, VDInit, Init](Address DestElement,
+ Address SrcElement) {
+ // Clean up any temporaries needed by the
+ // initialization.
+ RunCleanupsScope InitScope(*this);
+ // Emit initialization for single element.
+ setAddrOfLocalVar(VDInit, SrcElement);
+ EmitAnyExprToMem(Init, DestElement,
+ Init->getType().getQualifiers(),
+ /*IsInitializer*/ false);
+ LocalDeclMap.erase(VDInit);
+ });
+ }
+ EmitAutoVarCleanups(Emission);
+ return Emission.getAllocatedAddress();
+ });
} else {
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
- // Emit private VarDecl with copy init.
- // Remap temp VDInit variable to the address of the original
- // variable
- // (for proper handling of captured global variables).
- setAddrOfLocalVar(VDInit, OriginalAddr);
- EmitDecl(*VD);
- LocalDeclMap.erase(VDInit);
- return GetAddrOfLocalVar(VD);
- });
+ Address OriginalAddr = OriginalLVal.getAddress();
+ IsRegistered = PrivateScope.addPrivate(
+ OrigVD, [this, VDInit, OriginalAddr, VD]() {
+ // Emit private VarDecl with copy init.
+ // Remap temp VDInit variable to the address of the original
+ // variable (for proper handling of captured global variables).
+ setAddrOfLocalVar(VDInit, OriginalAddr);
+ EmitDecl(*VD);
+ LocalDeclMap.erase(VDInit);
+ return GetAddrOfLocalVar(VD);
+ });
}
assert(IsRegistered &&
"firstprivate var already registered as private");
@@ -827,16 +835,15 @@ void CodeGenFunction::EmitOMPPrivateClause(
llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {
auto IRef = C->varlist_begin();
- for (auto IInit : C->private_copies()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *IInit : C->private_copies()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
- auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
- bool IsRegistered =
- PrivateScope.addPrivate(OrigVD, [&]() -> Address {
- // Emit private VarDecl with copy init.
- EmitDecl(*VD);
- return GetAddrOfLocalVar(VD);
- });
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() {
+ // Emit private VarDecl with copy init.
+ EmitDecl(*VD);
+ return GetAddrOfLocalVar(VD);
+ });
assert(IsRegistered && "private var already registered as private");
// Silence the warning about unused variable.
(void)IsRegistered;
@@ -859,8 +866,8 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
auto IRef = C->varlist_begin();
auto ISrcRef = C->source_exprs().begin();
auto IDestRef = C->destination_exprs().begin();
- for (auto *AssignOp : C->assignment_ops()) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *AssignOp : C->assignment_ops()) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
QualType Type = VD->getType();
if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
// Get the address of the master variable. If we are emitting code with
@@ -891,12 +898,15 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
Builder.CreateCondBr(
Builder.CreateICmpNE(
Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy),
- Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy)),
+ Builder.CreatePtrToInt(PrivateAddr.getPointer(),
+ CGM.IntPtrTy)),
CopyBegin, CopyEnd);
EmitBlock(CopyBegin);
}
- auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
- auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ const auto *SrcVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
+ const auto *DestVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
}
++IRef;
@@ -919,8 +929,8 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
bool HasAtLeastOneLastprivate = false;
llvm::DenseSet<const VarDecl *> SIMDLCVs;
if (isOpenMPSimdDirective(D.getDirectiveKind())) {
- auto *LoopDirective = cast<OMPLoopDirective>(&D);
- for (auto *C : LoopDirective->counters()) {
+ const auto *LoopDirective = cast<OMPLoopDirective>(&D);
+ for (const Expr *C : LoopDirective->counters()) {
SIMDLCVs.insert(
cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
}
@@ -933,15 +943,16 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
break;
auto IRef = C->varlist_begin();
auto IDestRef = C->destination_exprs().begin();
- for (auto *IInit : C->private_copies()) {
+ for (const Expr *IInit : C->private_copies()) {
// Keep the address of the original variable for future update at the end
// of the loop.
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
// Taskloops do not require additional initialization, it is done in
// runtime support library.
if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
- auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
- PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> Address {
+ const auto *DestVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() {
DeclRefExpr DRE(
const_cast<VarDecl *>(OrigVD),
/*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
@@ -953,8 +964,8 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
// not generated. Initialization of this variable will happen in codegen
// for 'firstprivate' clause.
if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
- bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() {
// Emit private VarDecl with copy init.
EmitDecl(*VD);
return GetAddrOfLocalVar(VD);
@@ -992,10 +1003,10 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
}
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
- if (auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
+ if (const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
auto IC = LoopDirective->counters().begin();
- for (auto F : LoopDirective->finals()) {
- auto *D =
+ for (const Expr *F : LoopDirective->finals()) {
+ const auto *D =
cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl();
if (NoFinals)
AlreadyEmittedVars.insert(D);
@@ -1008,23 +1019,26 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
auto IRef = C->varlist_begin();
auto ISrcRef = C->source_exprs().begin();
auto IDestRef = C->destination_exprs().begin();
- for (auto *AssignOp : C->assignment_ops()) {
- auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *AssignOp : C->assignment_ops()) {
+ const auto *PrivateVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
QualType Type = PrivateVD->getType();
- auto *CanonicalVD = PrivateVD->getCanonicalDecl();
+ const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
if (AlreadyEmittedVars.insert(CanonicalVD).second) {
// If lastprivate variable is a loop control variable for loop-based
// directive, update its value before copyin back to original
// variable.
- if (auto *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
+ if (const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
EmitIgnoredExpr(FinalExpr);
- auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
- auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ const auto *SrcVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
+ const auto *DestVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
// Get the address of the original variable.
Address OriginalAddr = GetAddrOfLocalVar(DestVD);
// Get the address of the private variable.
Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
- if (auto RefTy = PrivateVD->getType()->getAs<ReferenceType>())
+ if (const auto *RefTy = PrivateVD->getType()->getAs<ReferenceType>())
PrivateAddr =
Address(Builder.CreateLoad(PrivateAddr),
getNaturalTypeAlignment(RefTy->getPointeeType()));
@@ -1034,7 +1048,7 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
++ISrcRef;
++IDestRef;
}
- if (auto *PostUpdate = C->getPostUpdateExpr())
+ if (const Expr *PostUpdate = C->getPostUpdateExpr())
EmitIgnoredExpr(PostUpdate);
}
if (IsLastIterCond)
@@ -1056,7 +1070,7 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
auto IRed = C->reduction_ops().begin();
auto ILHS = C->lhs_exprs().begin();
auto IRHS = C->rhs_exprs().begin();
- for (const auto *Ref : C->varlists()) {
+ for (const Expr *Ref : C->varlists()) {
Shareds.emplace_back(Ref);
Privates.emplace_back(*IPriv);
ReductionOps.emplace_back(*IRed);
@@ -1073,12 +1087,12 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
auto ILHS = LHSs.begin();
auto IRHS = RHSs.begin();
auto IPriv = Privates.begin();
- for (const auto *IRef : Shareds) {
- auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
+ for (const Expr *IRef : Shareds) {
+ const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
// Emit private VarDecl with reduction init.
RedCG.emitSharedLValue(*this, Count);
RedCG.emitAggregateType(*this, Count);
- auto Emission = EmitAutoVarAlloca(*PrivateVD);
+ AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(),
RedCG.getSharedLValue(Count),
[&Emission](CodeGenFunction &CGF) {
@@ -1089,32 +1103,31 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
Address BaseAddr = RedCG.adjustPrivateAddress(
*this, Count, Emission.getAllocatedAddress());
bool IsRegistered = PrivateScope.addPrivate(
- RedCG.getBaseDecl(Count), [BaseAddr]() -> Address { return BaseAddr; });
+ RedCG.getBaseDecl(Count), [BaseAddr]() { return BaseAddr; });
assert(IsRegistered && "private var already registered as private");
// Silence the warning about unused variable.
(void)IsRegistered;
- auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
- auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
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 {
+ PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() {
return RedCG.getSharedLValue(Count).getAddress();
});
- PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
- return GetAddrOfLocalVar(PrivateVD);
- });
+ PrivateScope.addPrivate(
+ RHSVD, [this, PrivateVD]() { return GetAddrOfLocalVar(PrivateVD); });
} 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 {
+ PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() {
return RedCG.getSharedLValue(Count).getAddress();
});
- PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address {
+ PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() {
return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD),
ConvertTypeForMem(RHSVD->getType()),
"rhs.begin");
@@ -1129,10 +1142,9 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
OriginalAddr = Builder.CreateElementBitCast(
OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");
}
+ PrivateScope.addPrivate(LHSVD, [OriginalAddr]() { return OriginalAddr; });
PrivateScope.addPrivate(
- LHSVD, [OriginalAddr]() -> Address { return OriginalAddr; });
- PrivateScope.addPrivate(
- RHSVD, [this, PrivateVD, RHSVD, IsArray]() -> Address {
+ RHSVD, [this, PrivateVD, RHSVD, IsArray]() {
return IsArray
? Builder.CreateElementBitCast(
GetAddrOfLocalVar(PrivateVD),
@@ -1178,17 +1190,17 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
static void emitPostUpdateForReductionClause(
CodeGenFunction &CGF, const OMPExecutableDirective &D,
- const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
+ const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
if (!CGF.HaveInsertPoint())
return;
llvm::BasicBlock *DoneBB = nullptr;
for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
- if (auto *PostUpdate = C->getPostUpdateExpr()) {
+ if (const Expr *PostUpdate = C->getPostUpdateExpr()) {
if (!DoneBB) {
- if (auto *Cond = CondGen(CGF)) {
+ if (llvm::Value *Cond = CondGen(CGF)) {
// If the first post-update expression is found, emit conditional
// block if it was requested.
- auto *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
+ llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done");
CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB);
CGF.EmitBlock(ThenBB);
@@ -1216,12 +1228,14 @@ static void emitCommonOMPParallelDirective(
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
const CodeGenBoundParametersTy &CodeGenBoundParameters) {
const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
- auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
- S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
+ llvm::Value *OutlinedFn =
+ CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
+ S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
- auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
- /*IgnoreResultAssign*/ true);
+ llvm::Value *NumThreads =
+ CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
+ /*IgnoreResultAssign=*/true);
CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
CGF, NumThreads, NumThreadsClause->getLocStart());
}
@@ -1257,7 +1271,8 @@ static void emitEmptyBoundParameters(CodeGenFunction &,
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
// Emit parallel region as a standalone region.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
bool Copyins = CGF.EmitOMPCopyinClause(S);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
@@ -1272,34 +1287,33 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
CGF.EmitOMPPrivateClause(S, PrivateScope);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
emitEmptyBoundParameters);
- emitPostUpdateForReductionClause(
- *this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
}
void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
JumpDest LoopExit) {
RunCleanupsScope BodyScope(*this);
// Update counters values on current iteration.
- for (auto I : D.updates()) {
- EmitIgnoredExpr(I);
- }
+ for (const Expr *UE : D.updates())
+ EmitIgnoredExpr(UE);
// Update the linear variables.
// 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);
+ for (const Expr *UE : C->updates())
+ EmitIgnoredExpr(UE);
}
}
// On a continue in the body, jump to the end.
- auto Continue = getJumpDestInCurrentScope("omp.body.continue");
+ JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
// Emit loop body.
EmitStmt(D.getBody());
@@ -1311,24 +1325,24 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
void CodeGenFunction::EmitOMPInnerLoop(
const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
const Expr *IncExpr,
- const llvm::function_ref<void(CodeGenFunction &)> &BodyGen,
- const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen) {
+ const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
+ const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) {
auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
// Start the loop with a block that tests the condition.
auto CondBlock = createBasicBlock("omp.inner.for.cond");
EmitBlock(CondBlock);
- const SourceRange &R = S.getSourceRange();
+ const SourceRange R = S.getSourceRange();
LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
SourceLocToDebugLoc(R.getEnd()));
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
- auto ExitBlock = LoopExit.getBlock();
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (RequiresCleanup)
ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
- auto LoopBody = createBasicBlock("omp.inner.for.body");
+ llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body");
// Emit condition.
EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
@@ -1341,7 +1355,7 @@ void CodeGenFunction::EmitOMPInnerLoop(
incrementProfileCounter(&S);
// Create a block for the increment.
- auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
+ JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
BodyGen(*this);
@@ -1363,12 +1377,13 @@ bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
// Emit inits for the linear variables.
bool HasLinears = false;
for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
- for (auto *Init : C->inits()) {
+ for (const Expr *Init : C->inits()) {
HasLinears = true;
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
- if (auto *Ref = dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
+ if (const auto *Ref =
+ dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
- auto *OrigVD = cast<VarDecl>(Ref->getDecl());
+ const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
CapturedStmtInfo->lookup(OrigVD) != nullptr,
VD->getInit()->getType(), VK_LValue,
@@ -1377,13 +1392,14 @@ bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
VD->getType()),
/*capturedByInit=*/false);
EmitAutoVarCleanups(Emission);
- } else
+ } else {
EmitVarDecl(*VD);
+ }
}
// Emit the linear steps for the linear clauses.
// If a step is not constant, it is pre-calculated before the loop.
- if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
- if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
+ if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
+ if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
// Emit calculation of the linear step.
EmitIgnoredExpr(CS);
@@ -1394,36 +1410,36 @@ bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
void CodeGenFunction::EmitOMPLinearClauseFinal(
const OMPLoopDirective &D,
- const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
+ const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
if (!HaveInsertPoint())
return;
llvm::BasicBlock *DoneBB = nullptr;
// Emit the final values of the linear variables.
for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
auto IC = C->varlist_begin();
- for (auto *F : C->finals()) {
+ for (const Expr *F : C->finals()) {
if (!DoneBB) {
- if (auto *Cond = CondGen(*this)) {
+ if (llvm::Value *Cond = CondGen(*this)) {
// If the first post-update expression is found, emit conditional
// block if it was requested.
- auto *ThenBB = createBasicBlock(".omp.linear.pu");
+ llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu");
DoneBB = createBasicBlock(".omp.linear.pu.done");
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
EmitBlock(ThenBB);
}
}
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
CapturedStmtInfo->lookup(OrigVD) != nullptr,
(*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
Address OrigAddr = EmitLValue(&DRE).getAddress();
CodeGenFunction::OMPPrivateScope VarScope(*this);
- VarScope.addPrivate(OrigVD, [OrigAddr]() -> Address { return OrigAddr; });
+ VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
(void)VarScope.Privatize();
EmitIgnoredExpr(F);
++IC;
}
- if (auto *PostUpdate = C->getPostUpdateExpr())
+ if (const Expr *PostUpdate = C->getPostUpdateExpr())
EmitIgnoredExpr(PostUpdate);
}
if (DoneBB)
@@ -1436,12 +1452,12 @@ static void emitAlignedClause(CodeGenFunction &CGF,
return;
for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
unsigned ClauseAlignment = 0;
- if (auto AlignmentExpr = Clause->getAlignment()) {
- auto AlignmentCI =
+ if (const Expr *AlignmentExpr = Clause->getAlignment()) {
+ auto *AlignmentCI =
cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
}
- for (auto E : Clause->varlists()) {
+ for (const Expr *E : Clause->varlists()) {
unsigned Alignment = ClauseAlignment;
if (Alignment == 0) {
// OpenMP [2.8.1, Description]
@@ -1468,31 +1484,48 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters(
if (!HaveInsertPoint())
return;
auto I = S.private_counters().begin();
- for (auto *E : S.counters()) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
- (void)LoopScope.addPrivate(VD, [&]() -> Address {
- // Emit var without initialization.
- if (!LocalDeclMap.count(PrivateVD)) {
- auto VarEmission = EmitAutoVarAlloca(*PrivateVD);
- EmitAutoVarCleanups(VarEmission);
- }
- DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
- /*RefersToEnclosingVariableOrCapture=*/false,
- (*I)->getType(), VK_LValue, (*I)->getExprLoc());
- return EmitLValue(&DRE).getAddress();
+ for (const Expr *E : S.counters()) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
+ // Emit var without initialization.
+ AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD);
+ EmitAutoVarCleanups(VarEmission);
+ LocalDeclMap.erase(PrivateVD);
+ (void)LoopScope.addPrivate(VD, [&VarEmission]() {
+ return VarEmission.getAllocatedAddress();
});
if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
VD->hasGlobalStorage()) {
- (void)LoopScope.addPrivate(PrivateVD, [&]() -> Address {
+ (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() {
DeclRefExpr DRE(const_cast<VarDecl *>(VD),
LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
E->getType(), VK_LValue, E->getExprLoc());
return EmitLValue(&DRE).getAddress();
});
+ } else {
+ (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() {
+ return VarEmission.getAllocatedAddress();
+ });
}
++I;
}
+ // Privatize extra loop counters used in loops for ordered(n) clauses.
+ for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
+ if (!C->getNumForLoops())
+ continue;
+ for (unsigned I = S.getCollapsedNumber(),
+ E = C->getLoopNumIterations().size();
+ I < E; ++I) {
+ const auto *DRE = cast<DeclRefExpr>(C->getLoopCunter(I));
+ const auto *VD = cast<VarDecl>(DRE->getDecl());
+ // Override only those variables that are really emitted already.
+ if (LocalDeclMap.count(VD)) {
+ (void)LoopScope.addPrivate(VD, [this, DRE, VD]() {
+ return CreateMemTemp(DRE->getType(), VD->getName());
+ });
+ }
+ }
+ }
}
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
@@ -1505,7 +1538,7 @@ static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
(void)PreCondScope.Privatize();
// Get initial values of real counters.
- for (auto I : S.inits()) {
+ for (const Expr *I : S.inits()) {
CGF.EmitIgnoredExpr(I);
}
}
@@ -1519,20 +1552,20 @@ void CodeGenFunction::EmitOMPLinearClause(
return;
llvm::DenseSet<const VarDecl *> SIMDLCVs;
if (isOpenMPSimdDirective(D.getDirectiveKind())) {
- auto *LoopDirective = cast<OMPLoopDirective>(&D);
- for (auto *C : LoopDirective->counters()) {
+ const auto *LoopDirective = cast<OMPLoopDirective>(&D);
+ for (const Expr *C : LoopDirective->counters()) {
SIMDLCVs.insert(
cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
}
}
for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
auto CurPrivate = C->privates().begin();
- for (auto *E : C->varlists()) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- auto *PrivateVD =
+ for (const Expr *E : C->varlists()) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ const auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
- bool IsRegistered = PrivateScope.addPrivate(VD, [&]() -> Address {
+ bool IsRegistered = PrivateScope.addPrivate(VD, [this, PrivateVD]() {
// Emit private VarDecl with copy init.
EmitVarDecl(*PrivateVD);
return GetAddrOfLocalVar(PrivateVD);
@@ -1540,8 +1573,9 @@ void CodeGenFunction::EmitOMPLinearClause(
assert(IsRegistered && "linear var already registered as private");
// Silence the warning about unused variable.
(void)IsRegistered;
- } else
+ } else {
EmitVarDecl(*PrivateVD);
+ }
++CurPrivate;
}
}
@@ -1555,7 +1589,7 @@ static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
/*ignoreResult=*/true);
- llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
+ auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
// In presence of finite 'safelen', it may be unsafe to mark all
// the memory instructions parallel, because loop-carried
@@ -1565,12 +1599,12 @@ static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
} else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
/*ignoreResult=*/true);
- llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
+ auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
// In presence of finite 'safelen', it may be unsafe to mark all
// the memory instructions parallel, because loop-carried
// dependences of 'safelen' iterations are possible.
- CGF.LoopStack.setParallel(false);
+ CGF.LoopStack.setParallel(/*Enable=*/false);
}
}
@@ -1578,46 +1612,45 @@ void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
bool IsMonotonic) {
// Walk clauses and process safelen/lastprivate.
LoopStack.setParallel(!IsMonotonic);
- LoopStack.setVectorizeEnable(true);
+ LoopStack.setVectorizeEnable();
emitSimdlenSafelenClause(*this, D, IsMonotonic);
}
void CodeGenFunction::EmitOMPSimdFinal(
const OMPLoopDirective &D,
- const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
+ const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
if (!HaveInsertPoint())
return;
llvm::BasicBlock *DoneBB = nullptr;
auto IC = D.counters().begin();
auto IPC = D.private_counters().begin();
- for (auto F : D.finals()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
- auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
- auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
+ for (const Expr *F : D.finals()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
+ const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
+ const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
OrigVD->hasGlobalStorage() || CED) {
if (!DoneBB) {
- if (auto *Cond = CondGen(*this)) {
+ if (llvm::Value *Cond = CondGen(*this)) {
// If the first post-update expression is found, emit conditional
// block if it was requested.
- auto *ThenBB = createBasicBlock(".omp.final.then");
+ llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then");
DoneBB = createBasicBlock(".omp.final.done");
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
EmitBlock(ThenBB);
}
}
Address OrigAddr = Address::invalid();
- if (CED)
+ if (CED) {
OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
- else {
+ } else {
DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
/*RefersToEnclosingVariableOrCapture=*/false,
(*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
OrigAddr = EmitLValue(&DRE).getAddress();
}
OMPPrivateScope VarScope(*this);
- VarScope.addPrivate(OrigVD,
- [OrigAddr]() -> Address { return OrigAddr; });
+ VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
(void)VarScope.Privatize();
EmitIgnoredExpr(F);
}
@@ -1670,7 +1703,7 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
if (!CondConstant)
return;
} else {
- auto *ThenBlock = CGF.createBasicBlock("simd.if.then");
+ llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then");
ContBlock = CGF.createBasicBlock("simd.if.end");
emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
CGF.getProfileCount(&S));
@@ -1680,14 +1713,14 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
// Emit the loop iteration variable.
const Expr *IVExpr = S.getIterationVariable();
- const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
+ const auto *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())) {
+ if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
// Emit calculation of the iterations count.
CGF.EmitIgnoredExpr(S.getCalcLastIteration());
@@ -1712,17 +1745,15 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
CGF.EmitStopPoint(&S);
},
[](CodeGenFunction &) {});
- CGF.EmitOMPSimdFinal(
- S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { 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; });
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
}
- CGF.EmitOMPLinearClauseFinal(
- S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
// Emit: if (PreCond) - end.
if (ContBlock) {
CGF.EmitBranch(ContBlock);
@@ -1734,7 +1765,7 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
emitOMPSimdRegion(CGF, S, Action);
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
@@ -1744,18 +1775,18 @@ void CodeGenFunction::EmitOMPOuterLoop(
const CodeGenFunction::OMPLoopArguments &LoopArgs,
const CodeGenFunction::CodeGenLoopTy &CodeGenLoop,
const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) {
- auto &RT = CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
const Expr *IVExpr = S.getIterationVariable();
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
- auto LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
+ JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
// Start the loop with a block that tests the condition.
- auto CondBlock = createBasicBlock("omp.dispatch.cond");
+ llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
EmitBlock(CondBlock);
- const SourceRange &R = S.getSourceRange();
+ const SourceRange R = S.getSourceRange();
LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
SourceLocToDebugLoc(R.getEnd()));
@@ -1777,11 +1808,11 @@ void CodeGenFunction::EmitOMPOuterLoop(
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
- auto ExitBlock = LoopExit.getBlock();
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (LoopScope.requiresCleanups())
ExitBlock = createBasicBlock("omp.dispatch.cleanup");
- auto LoopBody = createBasicBlock("omp.dispatch.body");
+ llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body");
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -1795,7 +1826,7 @@ void CodeGenFunction::EmitOMPOuterLoop(
EmitIgnoredExpr(LoopArgs.Init);
// Create a block for the increment.
- auto Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
+ JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
// Generate !llvm.loop.parallel metadata for loads and stores for loops
@@ -1848,7 +1879,7 @@ void CodeGenFunction::EmitOMPForOuterLoop(
const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
const OMPLoopArguments &LoopArgs,
const CodeGenDispatchBoundsTy &CGDispatchBounds) {
- auto &RT = CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
// Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
const bool DynamicOrOrdered =
@@ -1914,7 +1945,8 @@ void CodeGenFunction::EmitOMPForOuterLoop(
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
if (DynamicOrOrdered) {
- auto DispatchBounds = CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
+ const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
+ CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
llvm::Value *LBVal = DispatchBounds.first;
llvm::Value *UBVal = DispatchBounds.second;
CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
@@ -1957,7 +1989,7 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs,
const CodeGenLoopTy &CodeGenLoopContent) {
- auto &RT = CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
// Emit outer loop.
// Same behavior as a OMPForOuterLoop, except that schedule cannot be
@@ -2029,14 +2061,18 @@ emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
// the current ones.
LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable());
LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable());
- llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(PrevLB, SourceLocation());
+ llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(
+ PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
PrevLBVal = CGF.EmitScalarConversion(
PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
- LS.getIterationVariable()->getType(), SourceLocation());
- llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(PrevUB, SourceLocation());
+ LS.getIterationVariable()->getType(),
+ LS.getPrevLowerBoundVariable()->getExprLoc());
+ llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(
+ PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
PrevUBVal = CGF.EmitScalarConversion(
PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
- LS.getIterationVariable()->getType(), SourceLocation());
+ LS.getIterationVariable()->getType(),
+ LS.getPrevUpperBoundVariable()->getExprLoc());
CGF.EmitStoreOfScalar(PrevLBVal, LB);
CGF.EmitStoreOfScalar(PrevUBVal, UB);
@@ -2062,10 +2098,10 @@ emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF,
// is not normalized as each team only executes its own assigned
// distribute chunk
QualType IteratorTy = IVExpr->getType();
- llvm::Value *LBVal = CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy,
- SourceLocation());
- llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy,
- SourceLocation());
+ llvm::Value *LBVal =
+ CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getLocStart());
+ llvm::Value *UBVal =
+ CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getLocStart());
return {LBVal, UBVal};
}
@@ -2075,13 +2111,13 @@ static void emitDistributeParallelForDistributeInnerBoundParams(
const auto &Dir = cast<OMPLoopDirective>(S);
LValue LB =
CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
- auto LBCast = CGF.Builder.CreateIntCast(
+ llvm::Value *LBCast = CGF.Builder.CreateIntCast(
CGF.Builder.CreateLoad(LB.getAddress()), CGF.SizeTy, /*isSigned=*/false);
CapturedVars.push_back(LBCast);
LValue UB =
CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
- auto UBCast = CGF.Builder.CreateIntCast(
+ llvm::Value *UBCast = CGF.Builder.CreateIntCast(
CGF.Builder.CreateLoad(UB.getAddress()), CGF.SizeTy, /*isSigned=*/false);
CapturedVars.push_back(UBCast);
}
@@ -2091,7 +2127,8 @@ emitInnerParallelForWhenCombined(CodeGenFunction &CGF,
const OMPLoopDirective &S,
CodeGenFunction::JumpDest LoopExit) {
auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
bool HasCancel = false;
if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
@@ -2122,7 +2159,7 @@ void CodeGenFunction::EmitOMPDistributeParallelForDirective(
CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
S.getDistInc());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_parallel);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
}
@@ -2132,7 +2169,7 @@ void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective(
CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
S.getDistInc());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_parallel);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
}
@@ -2141,7 +2178,7 @@ void CodeGenFunction::EmitOMPDistributeSimdDirective(
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
@@ -2167,28 +2204,6 @@ void CodeGenFunction::EmitOMPTargetSimdDirective(
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 &) {
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
-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 &) {
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
namespace {
struct ScheduleKindModifiersTy {
OpenMPScheduleClauseKind Kind;
@@ -2206,20 +2221,20 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
const CodeGenLoopBoundsTy &CodeGenLoopBounds,
const CodeGenDispatchBoundsTy &CGDispatchBounds) {
// Emit the loop iteration variable.
- auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
- auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
+ const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
+ const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
EmitVarDecl(*IVDecl);
// 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())) {
+ if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
// Emit calculation of the iterations count.
EmitIgnoredExpr(S.getCalcLastIteration());
}
- auto &RT = CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
bool HasLastprivateClause;
// Check pre-condition.
@@ -2234,7 +2249,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
if (!CondConstant)
return false;
} else {
- auto *ThenBlock = createBasicBlock("omp.precond.then");
+ llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
ContBlock = createBasicBlock("omp.precond.end");
emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
getProfileCount(&S));
@@ -2242,10 +2257,11 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
incrementProfileCounter(&S);
}
+ RunCleanupsScope DoacrossCleanupScope(*this);
bool Ordered = false;
- if (auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
+ if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
if (OrderedClause->getNumForLoops())
- RT.emitDoacrossInit(*this, S);
+ RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
else
Ordered = true;
}
@@ -2284,11 +2300,11 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
// Detect the loop schedule kind and chunk.
llvm::Value *Chunk = nullptr;
OpenMPScheduleTy ScheduleKind;
- if (auto *C = S.getSingleClause<OMPScheduleClause>()) {
+ if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
ScheduleKind.Schedule = C->getScheduleKind();
ScheduleKind.M1 = C->getFirstScheduleModifier();
ScheduleKind.M2 = C->getSecondScheduleModifier();
- if (const auto *Ch = C->getChunkSize()) {
+ if (const Expr *Ch = C->getChunkSize()) {
Chunk = EmitScalarExpr(Ch);
Chunk = EmitScalarConversion(Chunk, Ch->getType(),
S.getIterationVariable()->getType(),
@@ -2316,7 +2332,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
UB.getAddress(), ST.getAddress());
RT.emitForStaticInit(*this, S.getLocStart(), S.getDirectiveKind(),
ScheduleKind, StaticInit);
- auto LoopExit =
+ JumpDest LoopExit =
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
EmitIgnoredExpr(S.getEnsureUpperBound());
@@ -2353,7 +2369,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
}
if (isOpenMPSimdDirective(S.getDirectiveKind())) {
EmitOMPSimdFinal(S,
- [&](CodeGenFunction &CGF) -> llvm::Value * {
+ [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
CGF.EmitLoadOfScalar(IL, S.getLocStart()));
});
@@ -2364,7 +2380,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
: /*Parallel only*/ OMPD_parallel);
// Emit post-update of the reduction variables if IsLastIter != 0.
emitPostUpdateForReductionClause(
- *this, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
+ *this, S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
CGF.EmitLoadOfScalar(IL, S.getLocStart()));
});
@@ -2374,14 +2390,15 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
S, isOpenMPSimdDirective(S.getDirectiveKind()),
Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
}
- EmitOMPLinearClauseFinal(S, [&](CodeGenFunction &CGF) -> llvm::Value * {
+ EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
CGF.EmitLoadOfScalar(IL, S.getLocStart()));
});
+ DoacrossCleanupScope.ForceCleanup();
// We're now done with the loop, so jump to the continuation block.
if (ContBlock) {
EmitBranch(ContBlock);
- EmitBlock(ContBlock, true);
+ EmitBlock(ContBlock, /*IsFinished=*/true);
}
}
return HasLastprivateClause;
@@ -2392,7 +2409,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
/// of the associated 'for' or 'distribute' loop.
static std::pair<LValue, LValue>
emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
- const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
+ const auto &LS = cast<OMPLoopDirective>(S);
LValue LB =
EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
LValue UB =
@@ -2407,7 +2424,7 @@ emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
static std::pair<llvm::Value *, llvm::Value *>
emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S,
Address LB, Address UB) {
- const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
+ const auto &LS = cast<OMPLoopDirective>(S);
const Expr *IVExpr = LS.getIterationVariable();
const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType());
llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0);
@@ -2425,15 +2442,14 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
emitDispatchForLoopBounds);
};
{
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
S.hasCancel());
}
// Emit an implicit barrier at the end.
- if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
+ if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
- }
}
void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
@@ -2445,38 +2461,39 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
emitDispatchForLoopBounds);
};
{
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
// Emit an implicit barrier at the end.
- if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
+ if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
- }
}
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
const Twine &Name,
llvm::Value *Init = nullptr) {
- auto LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
+ LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
if (Init)
CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
return LVal;
}
void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
- auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
- auto *CS = dyn_cast<CompoundStmt>(Stmt);
+ const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
+ const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
bool HasLastprivates = false;
- auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF,
- PrePostActionTy &) {
- auto &C = CGF.CGM.getContext();
- auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ auto &&CodeGen = [&S, CapturedStmt, CS,
+ &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
+ ASTContext &C = CGF.getContext();
+ QualType KmpInt32Ty =
+ C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
// Emit helper vars inits.
LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
CGF.Builder.getInt32(0));
- auto *GlobalUBVal = CS != nullptr ? CGF.Builder.getInt32(CS->size() - 1)
- : CGF.Builder.getInt32(0);
+ llvm::ConstantInt *GlobalUBVal = CS != nullptr
+ ? CGF.Builder.getInt32(CS->size() - 1)
+ : CGF.Builder.getInt32(0);
LValue UB =
createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
@@ -2494,8 +2511,8 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
OK_Ordinary, S.getLocStart(), FPOptions());
// Increment for loop counter.
UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
- S.getLocStart());
- auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) {
+ S.getLocStart(), true);
+ auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
// Iterate through all sections and emit a switch construct:
// switch (IV) {
// case 0:
@@ -2507,13 +2524,13 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// break;
// }
// .omp.sections.exit:
- auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
- auto *SwitchStmt = CGF.Builder.CreateSwitch(
- CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
- CS == nullptr ? 1 : CS->size());
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
+ llvm::SwitchInst *SwitchStmt =
+ CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getLocStart()),
+ ExitBB, CS == nullptr ? 1 : CS->size());
if (CS) {
unsigned CaseNumber = 0;
- for (auto *SubStmt : CS->children()) {
+ for (const Stmt *SubStmt : CS->children()) {
auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
CGF.EmitBlock(CaseBB);
SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
@@ -2522,10 +2539,10 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
++CaseNumber;
}
} else {
- auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
+ llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case");
CGF.EmitBlock(CaseBB);
SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
- CGF.EmitStmt(Stmt);
+ CGF.EmitStmt(CapturedStmt);
CGF.EmitBranch(ExitBB);
}
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
@@ -2554,8 +2571,8 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.CGM.getOpenMPRuntime().emitForStaticInit(
CGF, S.getLocStart(), S.getDirectiveKind(), ScheduleKind, StaticInit);
// UB = min(UB, GlobalUB);
- auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
- auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
+ llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
+ llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
// IV = LB;
@@ -2571,11 +2588,10 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
// Emit post-update of the reduction variables if IsLastIter != 0.
- emitPostUpdateForReductionClause(
- CGF, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
- return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
- });
+ emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
+ return CGF.Builder.CreateIsNotNull(
+ CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ });
// Emit final copy of the lastprivate variables if IsLastIter != 0.
if (HasLastprivates)
@@ -2606,7 +2622,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
{
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
EmitSections(S);
}
// Emit an implicit barrier at the end.
@@ -2618,9 +2634,9 @@ void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
S.hasCancel());
}
@@ -2649,10 +2665,10 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
(void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
CGF.EmitOMPPrivateClause(S, SingleScope);
(void)SingleScope.Privatize();
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
{
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
CopyprivateVars, DestExprs,
SrcExprs, AssignmentOps);
@@ -2669,21 +2685,21 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- Expr *Hint = nullptr;
- if (auto *HintClause = S.getSingleClause<OMPHintClause>())
+ const Expr *Hint = nullptr;
+ if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
Hint = HintClause->getHint();
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitCriticalRegion(*this,
S.getDirectiveName().getAsString(),
CodeGen, S.getLocStart(), Hint);
@@ -2693,7 +2709,8 @@ void CodeGenFunction::EmitOMPParallelForDirective(
const OMPParallelForDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel());
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
@@ -2706,7 +2723,8 @@ void CodeGenFunction::EmitOMPParallelForSimdDirective(
const OMPParallelForSimdDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
};
@@ -2718,27 +2736,28 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective(
const OMPParallelSectionsDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'sections' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CGF.EmitSections(S);
};
emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
emitEmptyBoundParameters);
}
-void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
- const RegionCodeGenTy &BodyGen,
- const TaskGenTy &TaskGen,
- OMPTaskDataTy &Data) {
+void CodeGenFunction::EmitOMPTaskBasedDirective(
+ const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion,
+ const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen,
+ OMPTaskDataTy &Data) {
// Emit outlined function for task construct.
- auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
- auto *I = CS->getCapturedDecl()->param_begin();
- auto *PartId = std::next(I);
- auto *TaskT = std::next(I, 4);
+ const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
+ auto I = CS->getCapturedDecl()->param_begin();
+ auto PartId = std::next(I);
+ auto TaskT = std::next(I, 4);
// Check if the task is final
if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
- auto *Cond = Clause->getCondition();
+ const Expr *Cond = Clause->getCondition();
bool CondConstant;
if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
Data.Final.setInt(CondConstant);
@@ -2750,7 +2769,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
}
// Check if the task has 'priority' clause.
if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
- auto *Prio = Clause->getPriority();
+ const Expr *Prio = Clause->getPriority();
Data.Priority.setInt(/*IntVal=*/true);
Data.Priority.setPointer(EmitScalarConversion(
EmitScalarExpr(Prio), Prio->getType(),
@@ -2763,8 +2782,8 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
// Get list of private variables.
for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
auto IRef = C->varlist_begin();
- for (auto *IInit : C->private_copies()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *IInit : C->private_copies()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Data.PrivateVars.push_back(*IRef);
Data.PrivateCopies.push_back(IInit);
@@ -2777,8 +2796,8 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
auto IRef = C->varlist_begin();
auto IElemInitRef = C->inits().begin();
- for (auto *IInit : C->private_copies()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *IInit : C->private_copies()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Data.FirstprivateVars.push_back(*IRef);
Data.FirstprivateCopies.push_back(IInit);
@@ -2793,8 +2812,8 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
auto IRef = C->varlist_begin();
auto ID = C->destination_exprs().begin();
- for (auto *IInit : C->private_copies()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ for (const Expr *IInit : C->private_copies()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Data.LastprivateVars.push_back(*IRef);
Data.LastprivateCopies.push_back(IInit);
@@ -2813,7 +2832,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
auto IRed = C->reduction_ops().begin();
auto ILHS = C->lhs_exprs().begin();
auto IRHS = C->rhs_exprs().begin();
- for (const auto *Ref : C->varlists()) {
+ for (const Expr *Ref : C->varlists()) {
Data.ReductionVars.emplace_back(Ref);
Data.ReductionCopies.emplace_back(*IPriv);
Data.ReductionOps.emplace_back(*IRed);
@@ -2829,50 +2848,51 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
*this, S.getLocStart(), LHSs, RHSs, Data);
// Build list of dependences.
for (const auto *C : S.getClausesOfKind<OMPDependClause>())
- for (auto *IRef : C->varlists())
- Data.Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef));
- auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
+ for (const Expr *IRef : C->varlists())
+ Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
+ auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
+ CapturedRegion](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
// Set proper addresses for generated private copies.
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(
- CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2)));
+ llvm::Value *CopyFn = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
+ llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
+ CS->getCapturedDecl()->getParam(PrivatesParam)));
// Map privates.
llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
llvm::SmallVector<llvm::Value *, 16> CallArgs;
CallArgs.push_back(PrivatesPtr);
- for (auto *E : Data.PrivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ for (const Expr *E : Data.PrivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Address PrivatePtr = CGF.CreateMemTemp(
CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
- PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
+ PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
}
- for (auto *E : Data.FirstprivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ for (const Expr *E : Data.FirstprivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Address PrivatePtr =
CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
".firstpriv.ptr.addr");
- PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
+ PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
}
- for (auto *E : Data.LastprivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ for (const Expr *E : Data.LastprivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Address PrivatePtr =
CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
".lastpriv.ptr.addr");
- PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
+ PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
}
CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
CopyFn, CallArgs);
- for (auto &&Pair : LastprivateDstsOrigs) {
- auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
+ for (const auto &Pair : LastprivateDstsOrigs) {
+ const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
DeclRefExpr DRE(
const_cast<VarDecl *>(OrigVD),
/*RefersToEnclosingVariableOrCapture=*/CGF.CapturedStmtInfo->lookup(
@@ -2882,14 +2902,14 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
return CGF.EmitLValue(&DRE).getAddress();
});
}
- for (auto &&Pair : PrivatePtrs) {
+ for (const auto &Pair : PrivatePtrs) {
Address Replacement(CGF.Builder.CreateLoad(Pair.second),
CGF.getContext().getDeclAlign(Pair.first));
Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
}
}
if (Data.Reductions) {
- OMPLexicalScope LexScope(CGF, S, /*AsInlined=*/true);
+ OMPLexicalScope LexScope(CGF, S, CapturedRegion);
ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionCopies,
Data.ReductionOps);
llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
@@ -2897,6 +2917,11 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
RedCG.emitSharedLValue(CGF, Cnt);
RedCG.emitAggregateType(CGF, Cnt);
+ // 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);
Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Replacement =
@@ -2904,16 +2929,11 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
Replacement.getPointer(), CGF.getContext().VoidPtrTy,
CGF.getContext().getPointerType(
Data.ReductionCopies[Cnt]->getType()),
- SourceLocation()),
+ Data.ReductionCopies[Cnt]->getExprLoc()),
Replacement.getAlignment());
Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
Scope.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);
}
}
// Privatize all private variables except for in_reduction items.
@@ -2926,7 +2946,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
auto IPriv = C->privates().begin();
auto IRed = C->reduction_ops().begin();
auto ITD = C->taskgroup_descriptors().begin();
- for (const auto *Ref : C->varlists()) {
+ for (const Expr *Ref : C->varlists()) {
InRedVars.emplace_back(Ref);
InRedPrivs.emplace_back(*IPriv);
InRedOps.emplace_back(*IRed);
@@ -2946,24 +2966,25 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
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());
+ // 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);
+ llvm::Value *ReductionsPtr =
+ CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
+ TaskgroupDescriptors[Cnt]->getExprLoc());
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()),
+ InRedPrivs[Cnt]->getExprLoc()),
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();
@@ -2971,7 +2992,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
Action.Enter(CGF);
BodyGen(CGF);
};
- auto *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
+ llvm::Value *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied,
Data.NumberOfParts);
OMPLexicalScope Scope(*this, S);
@@ -2980,27 +3001,24 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
static ImplicitParamDecl *
createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data,
- QualType Ty, CapturedDecl *CD) {
- auto *OrigVD = ImplicitParamDecl::Create(
- C, CD, SourceLocation(), /*Id=*/nullptr, Ty, ImplicitParamDecl::Other);
- auto *OrigRef =
- DeclRefExpr::Create(C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD,
- /*RefersToEnclosingVariableOrCapture=*/false,
- SourceLocation(), Ty, VK_LValue);
- auto *PrivateVD = ImplicitParamDecl::Create(
- C, CD, SourceLocation(), /*Id=*/nullptr, Ty, ImplicitParamDecl::Other);
+ QualType Ty, CapturedDecl *CD,
+ SourceLocation Loc) {
+ auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
+ ImplicitParamDecl::Other);
+ auto *OrigRef = DeclRefExpr::Create(
+ C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD,
+ /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
+ auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
+ ImplicitParamDecl::Other);
auto *PrivateRef = DeclRefExpr::Create(
C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD,
- /*RefersToEnclosingVariableOrCapture=*/false, SourceLocation(), Ty,
- VK_LValue);
+ /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
QualType ElemType = C.getBaseElementType(Ty);
- auto *InitVD =
- ImplicitParamDecl::Create(C, CD, SourceLocation(), /*Id=*/nullptr,
- ElemType, ImplicitParamDecl::Other);
- auto *InitRef =
- DeclRefExpr::Create(C, NestedNameSpecifierLoc(), SourceLocation(), InitVD,
- /*RefersToEnclosingVariableOrCapture=*/false,
- SourceLocation(), ElemType, VK_LValue);
+ auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType,
+ ImplicitParamDecl::Other);
+ auto *InitRef = DeclRefExpr::Create(
+ C, NestedNameSpecifierLoc(), SourceLocation(), InitVD,
+ /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue);
PrivateVD->setInitStyle(VarDecl::CInit);
PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
InitRef, /*BasePath=*/nullptr,
@@ -3015,12 +3033,12 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen,
OMPTargetDataInfo &InputInfo) {
// Emit outlined function for task construct.
- auto CS = S.getCapturedStmt(OMPD_task);
- auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
- auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
- auto *I = CS->getCapturedDecl()->param_begin();
- auto *PartId = std::next(I);
- auto *TaskT = std::next(I, 4);
+ const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
+ Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
+ QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ auto I = CS->getCapturedDecl()->param_begin();
+ auto PartId = std::next(I);
+ auto TaskT = std::next(I, 4);
OMPTaskDataTy Data;
// The task is not final.
Data.Final.setInt(/*IntVal=*/false);
@@ -3047,14 +3065,15 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
QualType BaseAndPointersType = getContext().getConstantArrayType(
getContext().VoidPtrTy, ArrSize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
- BPVD = createImplicitFirstprivateForType(getContext(), Data,
- BaseAndPointersType, CD);
- PVD = createImplicitFirstprivateForType(getContext(), Data,
- BaseAndPointersType, CD);
+ BPVD = createImplicitFirstprivateForType(
+ getContext(), Data, BaseAndPointersType, CD, S.getLocStart());
+ PVD = createImplicitFirstprivateForType(
+ getContext(), Data, BaseAndPointersType, CD, S.getLocStart());
QualType SizesType = getContext().getConstantArrayType(
getContext().getSizeType(), ArrSize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
- SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD);
+ SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
+ S.getLocStart());
TargetScope.addPrivate(
BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; });
TargetScope.addPrivate(PVD,
@@ -3065,33 +3084,33 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
(void)TargetScope.Privatize();
// Build list of dependences.
for (const auto *C : S.getClausesOfKind<OMPDependClause>())
- for (auto *IRef : C->varlists())
- Data.Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef));
+ for (const Expr *IRef : C->varlists())
+ Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD,
&InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) {
// Set proper addresses for generated private copies.
OMPPrivateScope Scope(CGF);
if (!Data.FirstprivateVars.empty()) {
enum { PrivatesParam = 2, CopyFnParam = 3 };
- auto *CopyFn = CGF.Builder.CreateLoad(
- CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3)));
- auto *PrivatesPtr = CGF.Builder.CreateLoad(
- CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2)));
+ llvm::Value *CopyFn = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
+ llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
+ CS->getCapturedDecl()->getParam(PrivatesParam)));
// Map privates.
llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
llvm::SmallVector<llvm::Value *, 16> CallArgs;
CallArgs.push_back(PrivatesPtr);
- for (auto *E : Data.FirstprivateVars) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ for (const Expr *E : Data.FirstprivateVars) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Address PrivatePtr =
CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
".firstpriv.ptr.addr");
- PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
+ PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
}
CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
CopyFn, CallArgs);
- for (auto &&Pair : PrivatePtrs) {
+ for (const auto &Pair : PrivatePtrs) {
Address Replacement(CGF.Builder.CreateLoad(Pair.second),
CGF.getContext().getDeclAlign(Pair.first));
Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
@@ -3099,19 +3118,20 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
}
// Privatize all private variables except for in_reduction items.
(void)Scope.Privatize();
- InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
- CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0, CGF.getPointerSize());
- InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
- CGF.GetAddrOfLocalVar(PVD), /*Index=*/0, CGF.getPointerSize());
- InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
- CGF.GetAddrOfLocalVar(SVD), /*Index=*/0, CGF.getSizeSize());
+ if (InputInfo.NumberOfTargetItems > 0) {
+ InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
+ CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0, CGF.getPointerSize());
+ InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
+ CGF.GetAddrOfLocalVar(PVD), /*Index=*/0, CGF.getPointerSize());
+ InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
+ CGF.GetAddrOfLocalVar(SVD), /*Index=*/0, CGF.getSizeSize());
+ }
Action.Enter(CGF);
- OMPLexicalScope LexScope(CGF, S, /*AsInlined=*/true,
- /*EmitPreInitStmt=*/false);
+ OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false);
BodyGen(CGF);
};
- auto *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
+ llvm::Value *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, /*Tied=*/true,
Data.NumberOfParts);
llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
@@ -3125,9 +3145,9 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Emit outlined function for task construct.
- auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
- auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
- auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
+ Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
+ QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
const Expr *IfCond = nullptr;
for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
if (C->getNameModifier() == OMPD_unknown ||
@@ -3150,7 +3170,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
SharedsTy, CapturedStruct, IfCond,
Data);
};
- EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
+ EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
}
void CodeGenFunction::EmitOMPTaskyieldDirective(
@@ -3179,7 +3199,7 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
auto IRed = C->reduction_ops().begin();
auto ILHS = C->lhs_exprs().begin();
auto IRHS = C->rhs_exprs().begin();
- for (const auto *Ref : C->varlists()) {
+ for (const Expr *Ref : C->varlists()) {
Data.ReductionVars.emplace_back(Ref);
Data.ReductionCopies.emplace_back(*IPriv);
Data.ReductionOps.emplace_back(*IRed);
@@ -3199,40 +3219,42 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
/*Volatile=*/false, E->getType());
}
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart());
}
void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
- CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef<const Expr *> {
- if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) {
- return llvm::makeArrayRef(FlushClause->varlist_begin(),
- FlushClause->varlist_end());
- }
- return llvm::None;
- }(), S.getLocStart());
+ CGM.getOpenMPRuntime().emitFlush(
+ *this,
+ [&S]() -> ArrayRef<const Expr *> {
+ if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>())
+ return llvm::makeArrayRef(FlushClause->varlist_begin(),
+ FlushClause->varlist_end());
+ return llvm::None;
+ }(),
+ S.getLocStart());
}
void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
const CodeGenLoopTy &CodeGenLoop,
Expr *IncExpr) {
// Emit the loop iteration variable.
- auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
- auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
+ const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
+ const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
EmitVarDecl(*IVDecl);
// 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())) {
+ if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
// Emit calculation of the iterations count.
EmitIgnoredExpr(S.getCalcLastIteration());
}
- auto &RT = CGM.getOpenMPRuntime();
+ CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
bool HasLastprivateClause = false;
// Check pre-condition.
@@ -3247,7 +3269,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
if (!CondConstant)
return;
} else {
- auto *ThenBlock = createBasicBlock("omp.precond.then");
+ llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
ContBlock = createBasicBlock("omp.precond.end");
emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
getProfileCount(&S));
@@ -3296,9 +3318,9 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
// Detect the distribute schedule kind and chunk.
llvm::Value *Chunk = nullptr;
OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown;
- if (auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
+ if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
ScheduleKind = C->getDistScheduleKind();
- if (const auto *Ch = C->getChunkSize()) {
+ if (const Expr *Ch = C->getChunkSize()) {
Chunk = EmitScalarExpr(Ch);
Chunk = EmitScalarConversion(Chunk, Ch->getType(),
S.getIterationVariable()->getType(),
@@ -3325,7 +3347,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
LB.getAddress(), UB.getAddress(), ST.getAddress());
RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind,
StaticInit);
- auto LoopExit =
+ JumpDest LoopExit =
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
@@ -3336,9 +3358,10 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
? S.getCombinedInit()
: S.getInit());
- Expr *Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
- ? S.getCombinedCond()
- : S.getCond();
+ const Expr *Cond =
+ isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
+ ? S.getCombinedCond()
+ : S.getCond();
// for distribute alone, codegen
// while (idx <= UB) { BODY; ++idx; }
@@ -3362,31 +3385,35 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
CodeGenLoop);
}
if (isOpenMPSimdDirective(S.getDirectiveKind())) {
- EmitOMPSimdFinal(S, [&](CodeGenFunction &CGF) -> llvm::Value * {
+ EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
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.");
+ if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
+ !isOpenMPParallelDirective(S.getDirectiveKind()) &&
+ !isOpenMPTeamsDirective(S.getDirectiveKind())) {
+ 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, [IL, &S](CodeGenFunction &CGF) {
+ return CGF.Builder.CreateIsNotNull(
+ CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ });
}
- 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) {
EmitOMPLastprivateClauseFinal(
@@ -3406,10 +3433,9 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
void CodeGenFunction::EmitOMPDistributeDirective(
const OMPDistributeDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
-
CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
}
@@ -3418,34 +3444,35 @@ static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
CGF.CapturedStmtInfo = &CapStmtInfo;
- auto *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S);
- Fn->addFnAttr(llvm::Attribute::NoInline);
+ llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S);
+ Fn->setDoesNotRecurse();
return Fn;
}
void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
- if (!S.getAssociatedStmt()) {
+ if (S.hasClausesOfKind<OMPDependClause>()) {
+ assert(!S.getAssociatedStmt() &&
+ "No associated statement must be in ordered depend construct.");
for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
return;
}
- auto *C = S.getSingleClause<OMPSIMDClause>();
+ const auto *C = S.getSingleClause<OMPSIMDClause>();
auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
PrePostActionTy &Action) {
+ const CapturedStmt *CS = S.getInnermostCapturedStmt();
if (C) {
- auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
llvm::SmallVector<llvm::Value *, 16> CapturedVars;
CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
- auto *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS);
+ llvm::Function *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS);
CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
OutlinedFn, CapturedVars);
} else {
Action.Enter(CGF);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(CS->getCapturedStmt());
}
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart(), !C);
}
@@ -3455,11 +3482,10 @@ static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
assert(CGF.hasScalarEvaluationKind(DestType) &&
"DestType must have scalar evaluation kind.");
assert(!Val.isAggregate() && "Must be a scalar or complex.");
- return Val.isScalar()
- ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestType,
- Loc)
- : CGF.EmitComplexToScalarConversion(Val.getComplexVal(), SrcType,
- DestType, Loc);
+ return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
+ DestType, Loc)
+ : CGF.EmitComplexToScalarConversion(
+ Val.getComplexVal(), SrcType, DestType, Loc);
}
static CodeGenFunction::ComplexPairTy
@@ -3470,15 +3496,17 @@ convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
CodeGenFunction::ComplexPairTy ComplexVal;
if (Val.isScalar()) {
// Convert the input element to the element type of the complex.
- auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
- auto ScalarVal = CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
- DestElementType, Loc);
+ QualType DestElementType =
+ DestType->castAs<ComplexType>()->getElementType();
+ llvm::Value *ScalarVal = CGF.EmitScalarConversion(
+ Val.getScalarVal(), SrcType, DestElementType, Loc);
ComplexVal = CodeGenFunction::ComplexPairTy(
ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
} else {
assert(Val.isComplex() && "Must be a scalar or complex.");
- auto SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
- auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
+ QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
+ QualType DestElementType =
+ DestType->castAs<ComplexType>()->getElementType();
ComplexVal.first = CGF.EmitScalarConversion(
Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
ComplexVal.second = CGF.EmitScalarConversion(
@@ -3517,7 +3545,7 @@ void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal,
}
}
-static void EmitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
+static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
const Expr *X, const Expr *V,
SourceLocation Loc) {
// v = x;
@@ -3541,7 +3569,7 @@ static void EmitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
}
-static void EmitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
+static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
const Expr *X, const Expr *E,
SourceLocation Loc) {
// x = expr;
@@ -3560,7 +3588,7 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
BinaryOperatorKind BO,
llvm::AtomicOrdering AO,
bool IsXLHSInRHSPart) {
- auto &Context = CGF.CGM.getContext();
+ ASTContext &Context = CGF.getContext();
// Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
// expression is simple and atomic is allowed for the given type for the
// target platform.
@@ -3638,20 +3666,21 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
case BO_Comma:
llvm_unreachable("Unsupported atomic update operation");
}
- auto *UpdateVal = Update.getScalarVal();
+ llvm::Value *UpdateVal = Update.getScalarVal();
if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
UpdateVal = CGF.Builder.CreateIntCast(
IC, X.getAddress().getElementType(),
X.getType()->hasSignedIntegerRepresentation());
}
- auto *Res = CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(), UpdateVal, AO);
+ llvm::Value *Res =
+ CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(), UpdateVal, AO);
return std::make_pair(true, RValue::get(Res));
}
std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
llvm::AtomicOrdering AO, SourceLocation Loc,
- const llvm::function_ref<RValue(RValue)> &CommonGen) {
+ const llvm::function_ref<RValue(RValue)> CommonGen) {
// Update expressions are allowed to have the following forms:
// x binop= expr; -> xrval + expr;
// x++, ++x -> xrval + 1;
@@ -3672,13 +3701,13 @@ std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
return Res;
}
-static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
+static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
const Expr *X, const Expr *E,
const Expr *UE, bool IsXLHSInRHSPart,
SourceLocation Loc) {
assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
"Update expr in 'atomic update' must be a binary operator.");
- auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
+ const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
// Update expressions are allowed to have the following forms:
// x binop= expr; -> xrval + expr;
// x++, ++x -> xrval + 1;
@@ -3688,18 +3717,18 @@ static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
LValue XLValue = CGF.EmitLValue(X);
RValue ExprRValue = CGF.EmitAnyExpr(E);
- auto AO = IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
- : llvm::AtomicOrdering::Monotonic;
- auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
- auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
- auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
- auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
- auto Gen =
- [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) -> RValue {
- CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
- CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
- return CGF.EmitAnyExpr(UE);
- };
+ llvm::AtomicOrdering AO = IsSeqCst
+ ? llvm::AtomicOrdering::SequentiallyConsistent
+ : llvm::AtomicOrdering::Monotonic;
+ const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
+ const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
+ const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
+ const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
+ auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) {
+ CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
+ CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
+ return CGF.EmitAnyExpr(UE);
+ };
(void)CGF.EmitOMPAtomicSimpleUpdateExpr(
XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
// OpenMP, 2.12.6, atomic Construct
@@ -3727,7 +3756,7 @@ static RValue convertToType(CodeGenFunction &CGF, RValue Value,
llvm_unreachable("Must be a scalar or complex.");
}
-static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
+static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
bool IsPostfixUpdate, const Expr *V,
const Expr *X, const Expr *E,
const Expr *UE, bool IsXLHSInRHSPart,
@@ -3738,27 +3767,28 @@ static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
LValue VLValue = CGF.EmitLValue(V);
LValue XLValue = CGF.EmitLValue(X);
RValue ExprRValue = CGF.EmitAnyExpr(E);
- auto AO = IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
- : llvm::AtomicOrdering::Monotonic;
+ llvm::AtomicOrdering AO = IsSeqCst
+ ? llvm::AtomicOrdering::SequentiallyConsistent
+ : llvm::AtomicOrdering::Monotonic;
QualType NewVValType;
if (UE) {
// 'x' is updated with some additional value.
assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
"Update expr in 'atomic capture' must be a binary operator.");
- auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
+ const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
// Update expressions are allowed to have the following forms:
// x binop= expr; -> xrval + expr;
// x++, ++x -> xrval + 1;
// x--, --x -> xrval - 1;
// x = x binop expr; -> xrval binop expr
// x = expr Op x; - > expr binop xrval;
- auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
- auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
- auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
+ const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
+ const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
+ const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
NewVValType = XRValExpr->getType();
- auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
+ const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
- IsPostfixUpdate](RValue XRValue) -> RValue {
+ IsPostfixUpdate](RValue XRValue) {
CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
RValue Res = CGF.EmitAnyExpr(UE);
@@ -3785,7 +3815,7 @@ static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
NewVValType = X->getType().getNonReferenceType();
ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
X->getType().getNonReferenceType(), Loc);
- auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) -> RValue {
+ auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) {
NewVVal = XRValue;
return ExprRValue;
};
@@ -3808,24 +3838,24 @@ static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
}
-static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
+static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
bool IsSeqCst, bool IsPostfixUpdate,
const Expr *X, const Expr *V, const Expr *E,
const Expr *UE, bool IsXLHSInRHSPart,
SourceLocation Loc) {
switch (Kind) {
case OMPC_read:
- EmitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc);
+ emitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc);
break;
case OMPC_write:
- EmitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc);
+ emitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc);
break;
case OMPC_unknown:
case OMPC_update:
- EmitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc);
+ emitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc);
break;
case OMPC_capture:
- EmitOMPAtomicCaptureExpr(CGF, IsSeqCst, IsPostfixUpdate, V, X, E, UE,
+ emitOMPAtomicCaptureExpr(CGF, IsSeqCst, IsPostfixUpdate, V, X, E, UE,
IsXLHSInRHSPart, Loc);
break;
case OMPC_if:
@@ -3881,7 +3911,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
bool IsSeqCst = S.getSingleClause<OMPSeqCstClause>();
OpenMPClauseKind Kind = OMPC_unknown;
- for (auto *C : S.clauses()) {
+ for (const OMPClause *C : S.clauses()) {
// Find first clause (skip seq_cst clause, if it is first).
if (C->getClauseKind() != OMPC_seq_cst) {
Kind = C->getClauseKind();
@@ -3889,28 +3919,25 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
}
}
- const auto *CS =
- S.getAssociatedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS)) {
+ const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS))
enterFullExpression(EWC);
- }
// Processing for statements under 'atomic capture'.
if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
- for (const auto *C : Compound->body()) {
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(C)) {
+ for (const Stmt *C : Compound->body()) {
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(C))
enterFullExpression(EWC);
- }
}
}
auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF,
PrePostActionTy &) {
CGF.EmitStopPoint(CS);
- EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
+ emitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
S.getV(), S.getExpr(), S.getUpdateExpr(),
S.isXLHSInRHSPart(), S.getLocStart());
};
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
}
@@ -3919,7 +3946,16 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen) {
assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
CodeGenModule &CGM = CGF.CGM;
- const CapturedStmt &CS = *S.getCapturedStmt(OMPD_target);
+
+ // On device emit this construct as inlined code.
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ OMPLexicalScope Scope(CGF, S, OMPD_target);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
+ });
+ return;
+ }
llvm::Function *Fn = nullptr;
llvm::Constant *FnID = nullptr;
@@ -3936,9 +3972,8 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
// Check if we have any device clause associated with the directive.
const Expr *Device = nullptr;
- if (auto *C = S.getSingleClause<OMPDeviceClause>()) {
+ if (auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- }
// Check if we have an if clause whose conditional always evaluates to false
// or if we do not have any targets specified. If so the target region is not
@@ -3956,9 +3991,9 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
StringRef ParentName;
// In case we have Ctors/Dtors we use the complete type variant to produce
// the mangling of the device outlined kernel.
- if (auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
+ if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
- else if (auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
+ else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
else
ParentName =
@@ -3967,22 +4002,19 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
// Emit target region as a standalone region.
CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
IsOffloadEntry, CodeGen);
- OMPLexicalScope Scope(CGF, S);
- llvm::SmallVector<llvm::Value *, 16> CapturedVars;
- CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
- CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device,
- CapturedVars);
+ OMPLexicalScope Scope(CGF, S, OMPD_task);
+ CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device);
}
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S,
PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
(void)PrivateScope.Privatize();
- Action.Enter(CGF);
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
}
void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
@@ -4011,14 +4043,15 @@ static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) {
const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
- auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction(
- S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
+ llvm::Value *OutlinedFn =
+ CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction(
+ S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
- const OMPNumTeamsClause *NT = S.getSingleClause<OMPNumTeamsClause>();
- const OMPThreadLimitClause *TL = S.getSingleClause<OMPThreadLimitClause>();
+ const auto *NT = S.getSingleClause<OMPNumTeamsClause>();
+ const auto *TL = S.getSingleClause<OMPThreadLimitClause>();
if (NT || TL) {
- Expr *NumTeams = (NT) ? NT->getNumTeams() : nullptr;
- Expr *ThreadLimit = (TL) ? TL->getThreadLimit() : nullptr;
+ const Expr *NumTeams = NT ? NT->getNumTeams() : nullptr;
+ const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr;
CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
S.getLocStart());
@@ -4033,18 +4066,19 @@ static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
// Emit teams region as a standalone region.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
};
emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
- emitPostUpdateForReductionClause(
- *this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
}
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
@@ -4053,18 +4087,18 @@ static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
Action.Enter(CGF);
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
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; });
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
}
void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
@@ -4099,7 +4133,8 @@ emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4144,7 +4179,8 @@ static void emitTargetTeamsDistributeSimdRegion(
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4188,7 +4224,8 @@ void CodeGenFunction::EmitOMPTeamsDistributeDirective(
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4209,7 +4246,8 @@ void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4231,7 +4269,8 @@ void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4253,7 +4292,8 @@ void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4266,6 +4306,109 @@ void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
[](CodeGenFunction &) { return nullptr; });
}
+static void emitTargetTeamsDistributeParallelForRegion(
+ CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
+ S.getDistInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ CodeGenFunction::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(CGF, S, OMPD_distribute_parallel_for,
+ CodeGenTeams);
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeParallelForDirective &S) {
+ // Emit SPMD target teams distribute parallel for region as a standalone
+ // region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeParallelForRegion(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::EmitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
+}
+
+static void emitTargetTeamsDistributeParallelForSimdRegion(
+ CodeGenFunction &CGF,
+ const OMPTargetTeamsDistributeParallelForSimdDirective &S,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
+ S.getDistInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ CodeGenFunction::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(CGF, S, OMPD_distribute_parallel_for_simd,
+ CodeGenTeams);
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
+ // Emit SPMD target teams distribute parallel for simd region as a standalone
+ // region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeParallelForSimdRegion(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::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
+ const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
+}
+
void CodeGenFunction::EmitOMPCancellationPointDirective(
const OMPCancellationPointDirective &S) {
CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(),
@@ -4305,19 +4448,19 @@ void CodeGenFunction::EmitOMPUseDevicePtrClause(
const auto &C = cast<OMPUseDevicePtrClause>(NC);
auto OrigVarIt = C.varlist_begin();
auto InitIt = C.inits().begin();
- for (auto PvtVarIt : C.private_copies()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl());
- auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl());
- auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl());
+ for (const Expr *PvtVarIt : C.private_copies()) {
+ const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl());
+ const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl());
+ const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl());
// In order to identify the right initializer we need to match the
// declaration used by the mapping logic. In some cases we may get
// OMPCapturedExprDecl that refers to the original declaration.
const ValueDecl *MatchingVD = OrigVD;
- if (auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
+ if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
// OMPCapturedExprDecl are used to privative fields of the current
// structure.
- auto *ME = cast<MemberExpr>(OED->getInit());
+ const auto *ME = cast<MemberExpr>(OED->getInit());
assert(isa<CXXThisExpr>(ME->getBase()) &&
"Base should be the current struct!");
MatchingVD = ME->getMemberDecl();
@@ -4329,7 +4472,9 @@ void CodeGenFunction::EmitOMPUseDevicePtrClause(
if (InitAddrIt == CaptureDeviceAddrMap.end())
continue;
- bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
+ bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, OrigVD,
+ InitAddrIt, InitVD,
+ PvtVD]() {
// Initialize the temporary initialization variable with the address we
// get from the runtime library. We have to cast the source address
// because it is always a void *. References are materialized in the
@@ -4346,7 +4491,7 @@ void CodeGenFunction::EmitOMPUseDevicePtrClause(
EmitDecl(*PvtVD);
// The initialization variables reached its purpose in the emission
- // ofthe previous declaration, so we don't need it anymore.
+ // of the previous declaration, so we don't need it anymore.
LocalDeclMap.erase(InitVD);
// Return the address of the private variable.
@@ -4383,13 +4528,12 @@ void CodeGenFunction::EmitOMPTargetDataDirective(
DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
+ CodeGenFunction &CGF, PrePostActionTy &Action) {
auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- // Codegen that selects wheather to generate the privatization code or not.
+ // Codegen that selects whether to generate the privatization code or not.
auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers,
&InnermostCodeGen](CodeGenFunction &CGF,
PrePostActionTy &Action) {
@@ -4408,8 +4552,9 @@ void CodeGenFunction::EmitOMPTargetDataDirective(
Info.CaptureDeviceAddrMap);
(void)PrivateScope.Privatize();
RCG(CGF);
- } else
+ } else {
RCG(CGF);
+ }
};
// Forward the provided action to the privatization codegen.
@@ -4435,12 +4580,12 @@ void CodeGenFunction::EmitOMPTargetDataDirective(
// Check if we have any if clause associated with the directive.
const Expr *IfCond = nullptr;
- if (auto *C = S.getSingleClause<OMPIfClause>())
+ if (const auto *C = S.getSingleClause<OMPIfClause>())
IfCond = C->getCondition();
// Check if we have any device clause associated with the directive.
const Expr *Device = nullptr;
- if (auto *C = S.getSingleClause<OMPDeviceClause>())
+ if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
// Set the action to signal privatization of device pointers.
@@ -4460,15 +4605,15 @@ void CodeGenFunction::EmitOMPTargetEnterDataDirective(
// Check if we have any if clause associated with the directive.
const Expr *IfCond = nullptr;
- if (auto *C = S.getSingleClause<OMPIfClause>())
+ if (const auto *C = S.getSingleClause<OMPIfClause>())
IfCond = C->getCondition();
// Check if we have any device clause associated with the directive.
const Expr *Device = nullptr;
- if (auto *C = S.getSingleClause<OMPDeviceClause>())
+ if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_task);
CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
}
@@ -4481,15 +4626,15 @@ void CodeGenFunction::EmitOMPTargetExitDataDirective(
// Check if we have any if clause associated with the directive.
const Expr *IfCond = nullptr;
- if (auto *C = S.getSingleClause<OMPIfClause>())
+ if (const auto *C = S.getSingleClause<OMPIfClause>())
IfCond = C->getCondition();
// Check if we have any device clause associated with the directive.
const Expr *Device = nullptr;
- if (auto *C = S.getSingleClause<OMPDeviceClause>())
+ if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_task);
CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
}
@@ -4497,9 +4642,10 @@ static void emitTargetParallelRegion(CodeGenFunction &CGF,
const OMPTargetParallelDirective &S,
PrePostActionTy &Action) {
// Get the captured statement associated with the 'parallel' region.
- auto *CS = S.getCapturedStmt(OMPD_parallel);
+ const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
Action.Enter(CGF);
- auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
@@ -4511,8 +4657,8 @@ static void emitTargetParallelRegion(CodeGenFunction &CGF,
};
emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen,
emitEmptyBoundParameters);
- emitPostUpdateForReductionClause(
- CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
}
void CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
@@ -4543,7 +4689,8 @@ static void emitTargetParallelForRegion(CodeGenFunction &CGF,
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 &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPCancelStackRAII CancelRegion(
CGF, OMPD_target_parallel_for, S.hasCancel());
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
@@ -4583,7 +4730,8 @@ emitTargetParallelForSimdRegion(CodeGenFunction &CGF,
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 &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
};
@@ -4618,17 +4766,17 @@ void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
const ImplicitParamDecl *PVD,
CodeGenFunction::OMPPrivateScope &Privates) {
- auto *VDecl = cast<VarDecl>(Helper->getDecl());
- Privates.addPrivate(
- VDecl, [&CGF, PVD]() -> Address { return CGF.GetAddrOfLocalVar(PVD); });
+ const auto *VDecl = cast<VarDecl>(Helper->getDecl());
+ Privates.addPrivate(VDecl,
+ [&CGF, PVD]() { return CGF.GetAddrOfLocalVar(PVD); });
}
void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
// Emit outlined function for task construct.
- auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
- auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
- auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
+ Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
+ QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
const Expr *IfCond = nullptr;
for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
if (C->getNameModifier() == OMPD_unknown ||
@@ -4671,7 +4819,7 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
if (!CondConstant)
return;
} else {
- auto *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
+ llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
ContBlock = CGF.createBasicBlock("taskloop.if.end");
emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
CGF.getProfileCount(&S));
@@ -4702,14 +4850,14 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
(void)LoopScope.Privatize();
// Emit the loop iteration variable.
const Expr *IVExpr = S.getIterationVariable();
- const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
+ const auto *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())) {
+ if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
// Emit calculation of the iterations count.
CGF.EmitIgnoredExpr(S.getCalcLastIteration());
@@ -4739,7 +4887,8 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn,
const OMPTaskDataTy &Data) {
- auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
+ &Data](CodeGenFunction &CGF, PrePostActionTy &) {
OMPLoopScope PreInitScope(CGF, S);
CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getLocStart(), S,
OutlinedFn, SharedsTy,
@@ -4748,15 +4897,16 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
CodeGen);
};
- if (Data.Nogroup)
- EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
- else {
+ if (Data.Nogroup) {
+ EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
+ } else {
CGM.getOpenMPRuntime().emitTaskgroupRegion(
*this,
[&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF,
PrePostActionTy &Action) {
Action.Enter(CGF);
- CGF.EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
+ CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
+ Data);
},
S.getLocStart());
}
@@ -4781,15 +4931,15 @@ void CodeGenFunction::EmitOMPTargetUpdateDirective(
// Check if we have any if clause associated with the directive.
const Expr *IfCond = nullptr;
- if (auto *C = S.getSingleClause<OMPIfClause>())
+ if (const auto *C = S.getSingleClause<OMPIfClause>())
IfCond = C->getCondition();
// Check if we have any device clause associated with the directive.
const Expr *Device = nullptr;
- if (auto *C = S.getSingleClause<OMPDeviceClause>())
+ if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPLexicalScope Scope(*this, S, OMPD_task);
CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
}
@@ -4802,7 +4952,7 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
} else {
if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
- for (const auto *E : LD->counters()) {
+ for (const Expr *E : LD->counters()) {
if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
cast<DeclRefExpr>(E)->getDecl())) {
// Emit only those that were not explicitly referenced in clauses.
@@ -4810,11 +4960,22 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
CGF.EmitVarDecl(*VD);
}
}
+ for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
+ if (!C->getNumForLoops())
+ continue;
+ for (unsigned I = LD->getCollapsedNumber(),
+ E = C->getLoopNumIterations().size();
+ I < E; ++I) {
+ if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
+ cast<DeclRefExpr>(C->getLoopCunter(I))->getDecl())) {
+ // Emit only those that were not explicitly referenced in clauses.
+ if (!CGF.LocalDeclMap.count(VD))
+ CGF.EmitVarDecl(*VD);
+ }
+ }
+ }
}
- const auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
- while (const auto *CCS = dyn_cast<CapturedStmt>(CS->getCapturedStmt()))
- CS = CCS;
- CGF.EmitStmt(CS->getCapturedStmt());
+ CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
}
};
OMPSimdLexicalScope Scope(*this, D);
@@ -4824,3 +4985,4 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
: D.getDirectiveKind(),
CodeGen);
}
+
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
index 78928d04220d..b0a3a0bffa2e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
@@ -30,8 +30,8 @@ GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
// This is a regular vtable.
return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits());
}
-
- return CGVT.GenerateConstructionVTable(MostDerivedClass,
+
+ return CGVT.GenerateConstructionVTable(MostDerivedClass,
VTable.getBaseSubobject(),
VTable.isVirtual(),
Linkage,
@@ -45,7 +45,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true);
llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int32Ty = CGM.Int32Ty;
- llvm::ArrayType *ArrayType =
+ llvm::ArrayType *ArrayType =
llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
SmallVector<llvm::GlobalVariable *, 8> VTables;
@@ -100,7 +100,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName()));
// Set the right visibility.
- CGM.setGlobalVisibility(VTT, RD, ForDefinition);
+ CGM.setGVProperties(VTT, RD);
}
llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
@@ -117,42 +117,42 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
- llvm::ArrayType *ArrayType =
+ llvm::ArrayType *ArrayType =
llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
llvm::GlobalVariable *GV =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
llvm::GlobalValue::ExternalLinkage);
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
return GV;
}
-uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
+uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
BaseSubobject Base) {
BaseSubobjectPairTy ClassSubobjectPair(RD, Base);
SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair);
if (I != SubVTTIndicies.end())
return I->second;
-
+
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
- Builder.getSubVTTIndicies().begin(),
+ Builder.getSubVTTIndicies().begin(),
E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
// Insert all indices.
BaseSubobjectPairTy ClassSubobjectPair(RD, I->first);
-
+
SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second));
}
-
+
I = SubVTTIndicies.find(ClassSubobjectPair);
assert(I != SubVTTIndicies.end() && "Did not find index!");
-
+
return I->second;
}
-uint64_t
+uint64_t
CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
BaseSubobject Base) {
SecondaryVirtualPointerIndicesMapTy::iterator I =
@@ -164,17 +164,17 @@ CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
// Insert all secondary vpointer indices.
- for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
+ for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
Builder.getSecondaryVirtualPointerIndices().begin(),
E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) {
std::pair<const CXXRecordDecl *, BaseSubobject> Pair =
std::make_pair(RD, I->first);
-
+
SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second));
}
I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!");
-
+
return I->second;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
index 2d9bf3bce926..cc334637a831 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -31,29 +31,12 @@ using namespace CodeGen;
CodeGenVTables::CodeGenVTables(CodeGenModule &CGM)
: CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {}
-llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
- const ThunkInfo &Thunk) {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-
- // Compute the mangled name.
- SmallString<256> Name;
- llvm::raw_svector_ostream Out(Name);
- if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
- getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(),
- Thunk.This, Out);
- else
- getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Out);
-
- llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
- return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true,
+llvm::Constant *CodeGenModule::GetAddrOfThunk(StringRef Name, llvm::Type *FnTy,
+ GlobalDecl GD) {
+ return GetOrCreateLLVMFunction(Name, FnTy, GD, /*ForVTable=*/true,
/*DontDefer=*/true, /*IsThunk=*/true);
}
-static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
- const ThunkInfo &Thunk, llvm::Function *Fn) {
- CGM.setGlobalVisibility(Fn, MD, ForDefinition);
-}
-
static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk,
llvm::Function *ThunkFn, bool ForVTable,
GlobalDecl GD) {
@@ -62,8 +45,12 @@ static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk,
!Thunk.Return.isEmpty());
// Set the right visibility.
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- setThunkVisibility(CGM, MD, Thunk, ThunkFn);
+ CGM.setGVProperties(ThunkFn, GD);
+
+ if (!CGM.getCXXABI().exportThunk()) {
+ ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ ThunkFn->setDSOLocal(true);
+ }
if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker())
ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
@@ -123,7 +110,7 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
return RValue::get(ReturnValue);
}
-/// This function clones a function's DISubprogram node and enters it into
+/// 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
@@ -236,7 +223,8 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn,
}
void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
- const CGFunctionInfo &FnInfo) {
+ const CGFunctionInfo &FnInfo,
+ bool IsUnprototyped) {
assert(!CurGD.getDecl() && "CurGD was already set!");
CurGD = GD;
CurFuncIsThunk = true;
@@ -245,21 +233,28 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
QualType ThisType = MD->getThisType(getContext());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- QualType ResultType = CGM.getCXXABI().HasThisReturn(GD)
- ? ThisType
- : CGM.getCXXABI().hasMostDerivedReturn(GD)
- ? CGM.getContext().VoidPtrTy
- : FPT->getReturnType();
+ QualType ResultType;
+ if (IsUnprototyped)
+ ResultType = CGM.getContext().VoidTy;
+ else if (CGM.getCXXABI().HasThisReturn(GD))
+ ResultType = ThisType;
+ else if (CGM.getCXXABI().hasMostDerivedReturn(GD))
+ ResultType = CGM.getContext().VoidPtrTy;
+ else
+ ResultType = FPT->getReturnType();
FunctionArgList FunctionArgs;
// Create the implicit 'this' parameter declaration.
CGM.getCXXABI().buildThisParam(*this, FunctionArgs);
- // Add the rest of the parameters.
- FunctionArgs.append(MD->param_begin(), MD->param_end());
+ // Add the rest of the parameters, if we have a prototype to work with.
+ if (!IsUnprototyped) {
+ FunctionArgs.append(MD->param_begin(), MD->param_end());
- if (isa<CXXDestructorDecl>(MD))
- CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs);
+ if (isa<CXXDestructorDecl>(MD))
+ CGM.getCXXABI().addImplicitStructorParams(*this, ResultType,
+ FunctionArgs);
+ }
// Start defining the function.
auto NL = ApplyDebugLocation::CreateEmpty(*this);
@@ -285,7 +280,8 @@ void CodeGenFunction::FinishThunk() {
}
void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
- const ThunkInfo *Thunk) {
+ const ThunkInfo *Thunk,
+ bool IsUnprototyped) {
assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
"Please use a new CGF for this thunk");
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl());
@@ -296,13 +292,17 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
*this, LoadCXXThisAddress(), Thunk->This)
: LoadCXXThis();
- if (CurFnInfo->usesInAlloca()) {
+ if (CurFnInfo->usesInAlloca() || IsUnprototyped) {
// We don't handle return adjusting thunks, because they require us to call
// the copy constructor. For now, fall through and pretend the return
// adjustment was empty so we don't crash.
if (Thunk && !Thunk->Return.isEmpty()) {
- CGM.ErrorUnsupported(
- MD, "non-trivial argument copy for return-adjusting thunk");
+ if (IsUnprototyped)
+ CGM.ErrorUnsupported(
+ MD, "return-adjusting thunk with incomplete parameter type");
+ else
+ CGM.ErrorUnsupported(
+ MD, "non-trivial argument copy for return-adjusting thunk");
}
EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr);
return;
@@ -429,55 +429,98 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
}
void CodeGenFunction::generateThunk(llvm::Function *Fn,
- const CGFunctionInfo &FnInfo,
- GlobalDecl GD, const ThunkInfo &Thunk) {
- StartThunk(Fn, GD, FnInfo);
+ const CGFunctionInfo &FnInfo, GlobalDecl GD,
+ const ThunkInfo &Thunk,
+ bool IsUnprototyped) {
+ StartThunk(Fn, GD, FnInfo, IsUnprototyped);
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(*this);
- // Get our callee.
- llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD));
+ // Get our callee. Use a placeholder type if this method is unprototyped so
+ // that CodeGenModule doesn't try to set attributes.
+ llvm::Type *Ty;
+ if (IsUnprototyped)
+ Ty = llvm::StructType::get(getLLVMContext());
+ else
+ Ty = CGM.getTypes().GetFunctionType(FnInfo);
+
llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+ // Fix up the function type for an unprototyped musttail call.
+ if (IsUnprototyped)
+ Callee = llvm::ConstantExpr::getBitCast(Callee, Fn->getType());
+
// Make the call and return the result.
- EmitCallAndReturnForThunk(Callee, &Thunk);
+ EmitCallAndReturnForThunk(Callee, &Thunk, IsUnprototyped);
}
-void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
- bool ForVTable) {
- const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD);
+static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD,
+ bool IsUnprototyped, bool ForVTable) {
+ // Always emit thunks in the MS C++ ABI. We cannot rely on other TUs to
+ // provide thunks for us.
+ if (CGM.getTarget().getCXXABI().isMicrosoft())
+ return true;
- // FIXME: re-use FnInfo in this computation.
- llvm::Constant *C = CGM.GetAddrOfThunk(GD, Thunk);
- llvm::GlobalValue *Entry;
+ // In the Itanium C++ ABI, vtable thunks are provided by TUs that provide
+ // definitions of the main method. Therefore, emitting thunks with the vtable
+ // is purely an optimization. Emit the thunk if optimizations are enabled and
+ // all of the parameter types are complete.
+ if (ForVTable)
+ return CGM.getCodeGenOpts().OptimizationLevel && !IsUnprototyped;
- // Strip off a bitcast if we got one back.
- if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(C)) {
- assert(CE->getOpcode() == llvm::Instruction::BitCast);
- Entry = cast<llvm::GlobalValue>(CE->getOperand(0));
- } else {
- Entry = cast<llvm::GlobalValue>(C);
- }
+ // Always emit thunks along with the method definition.
+ return true;
+}
- // There's already a declaration with the same name, check if it has the same
- // type or if we need to replace it.
- if (Entry->getType()->getElementType() !=
- CGM.getTypes().GetFunctionTypeForVTable(GD)) {
- llvm::GlobalValue *OldThunkFn = Entry;
+llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
+ const ThunkInfo &TI,
+ bool ForVTable) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- // If the types mismatch then we have to rewrite the definition.
- assert(OldThunkFn->isDeclaration() &&
- "Shouldn't replace non-declaration");
+ // First, get a declaration. Compute the mangled name. Don't worry about
+ // getting the function prototype right, since we may only need this
+ // declaration to fill in a vtable slot.
+ SmallString<256> Name;
+ MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
+ llvm::raw_svector_ostream Out(Name);
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
+ MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI.This, Out);
+ else
+ MCtx.mangleThunk(MD, TI, Out);
+ llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
+ llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
+
+ // If we don't need to emit a definition, return this declaration as is.
+ bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
+ MD->getType()->castAs<FunctionType>());
+ if (!shouldEmitVTableThunk(CGM, MD, IsUnprototyped, ForVTable))
+ return Thunk;
+
+ // Arrange a function prototype appropriate for a function definition. In some
+ // cases in the MS ABI, we may need to build an unprototyped musttail thunk.
+ const CGFunctionInfo &FnInfo =
+ IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
+ : CGM.getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
+
+ // If the type of the underlying GlobalValue is wrong, we'll have to replace
+ // it. It should be a declaration.
+ llvm::Function *ThunkFn = cast<llvm::Function>(Thunk->stripPointerCasts());
+ if (ThunkFn->getFunctionType() != ThunkFnTy) {
+ llvm::GlobalValue *OldThunkFn = ThunkFn;
+
+ assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration");
// Remove the name from the old thunk function and get a new thunk.
OldThunkFn->setName(StringRef());
- Entry = cast<llvm::GlobalValue>(CGM.GetAddrOfThunk(GD, Thunk));
+ ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
+ Name.str(), &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
// If needed, replace the old thunk with a bitcast.
if (!OldThunkFn->use_empty()) {
llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(Entry, OldThunkFn->getType());
+ llvm::ConstantExpr::getBitCast(ThunkFn, OldThunkFn->getType());
OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl);
}
@@ -485,61 +528,48 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
OldThunkFn->eraseFromParent();
}
- llvm::Function *ThunkFn = cast<llvm::Function>(Entry);
bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
if (!ThunkFn->isDeclaration()) {
if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
// There is already a thunk emitted for this function, do nothing.
- return;
+ return ThunkFn;
}
- setThunkProperties(CGM, Thunk, ThunkFn, ForVTable, GD);
- return;
+ setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD);
+ return ThunkFn;
}
+ // If this will be unprototyped, add the "thunk" attribute so that LLVM knows
+ // that the return type is meaningless. These thunks can be used to call
+ // functions with differing return types, and the caller is required to cast
+ // the prototype appropriately to extract the correct value.
+ if (IsUnprototyped)
+ ThunkFn->addFnAttr("thunk");
+
CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn);
- if (ThunkFn->isVarArg()) {
+ if (!IsUnprototyped && ThunkFn->isVarArg()) {
// Varargs thunks are special; we can't just generate a call because
// we can't copy the varargs. Our implementation is rather
// expensive/sucky at the moment, so don't generate the thunk unless
// we have to.
// FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly.
if (UseAvailableExternallyLinkage)
- return;
- ThunkFn =
- CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
+ return ThunkFn;
+ ThunkFn = CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD,
+ TI);
} else {
// Normal thunk body generation.
- CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, Thunk);
+ CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
}
- setThunkProperties(CGM, Thunk, ThunkFn, ForVTable, GD);
-}
-
-void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD,
- const ThunkInfo &Thunk) {
- // If the ABI has key functions, only the TU with the key function should emit
- // the thunk. However, we can allow inlining of thunks if we emit them with
- // available_externally linkage together with vtables when optimizations are
- // enabled.
- if (CGM.getTarget().getCXXABI().hasKeyFunctions() &&
- !CGM.getCodeGenOpts().OptimizationLevel)
- return;
-
- // We can't emit thunks for member functions with incomplete types.
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- if (!CGM.getTypes().isFuncTypeConvertible(
- MD->getType()->castAs<FunctionType>()))
- return;
-
- emitThunk(GD, Thunk, /*ForVTable=*/true);
+ setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD);
+ return ThunkFn;
}
-void CodeGenVTables::EmitThunks(GlobalDecl GD)
-{
+void CodeGenVTables::EmitThunks(GlobalDecl GD) {
const CXXMethodDecl *MD =
cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();
@@ -554,7 +584,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
return;
for (const ThunkInfo& Thunk : *ThunkInfoVector)
- emitThunk(GD, Thunk, /*ForVTable=*/false);
+ maybeEmitThunk(GD, Thunk, /*ForVTable=*/false);
}
void CodeGenVTables::addVTableComponent(
@@ -647,9 +677,8 @@ void CodeGenVTables::addVTableComponent(
layout.vtable_thunks()[nextVTableThunkIndex].first == idx) {
auto &thunkInfo = layout.vtable_thunks()[nextVTableThunkIndex].second;
- maybeEmitThunkForVTable(GD, thunkInfo);
nextVTableThunkIndex++;
- fnPtr = CGM.GetAddrOfThunk(GD, thunkInfo);
+ fnPtr = maybeEmitThunk(GD, thunkInfo, /*ForVTable=*/true);
// Otherwise we can use the method definition directly.
} else {
@@ -730,7 +759,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, ForDefinition);
+ CGM.setGVProperties(VTable, RD);
// V-tables are always unnamed_addr.
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
@@ -845,7 +874,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
llvm_unreachable("Invalid TemplateSpecializationKind!");
}
-/// This is a callback from Sema to tell us that that a particular vtable is
+/// This is a callback from Sema to tell us that a particular vtable is
/// required to be emitted in this translation unit.
///
/// This is only called for vtables that _must_ be emitted (mainly due to key
@@ -983,31 +1012,29 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
CharUnits PointerWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry;
- std::vector<BSEntry> BitsetEntries;
- // Create a bit set entry for each address point.
+ typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint;
+ std::vector<AddressPoint> AddressPoints;
for (auto &&AP : VTLayout.getAddressPoints())
- BitsetEntries.push_back(
- std::make_pair(AP.first.getBase(),
- VTLayout.getVTableOffset(AP.second.VTableIndex) +
- AP.second.AddressPointIndex));
-
- // Sort the bit set entries for determinism.
- std::sort(BitsetEntries.begin(), BitsetEntries.end(),
- [this](const BSEntry &E1, const BSEntry &E2) {
- if (&E1 == &E2)
+ AddressPoints.push_back(std::make_pair(
+ AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) +
+ AP.second.AddressPointIndex));
+
+ // Sort the address points for determinism.
+ llvm::sort(AddressPoints.begin(), AddressPoints.end(),
+ [this](const AddressPoint &AP1, const AddressPoint &AP2) {
+ if (&AP1 == &AP2)
return false;
std::string S1;
llvm::raw_string_ostream O1(S1);
getCXXABI().getMangleContext().mangleTypeName(
- QualType(E1.first->getTypeForDecl(), 0), O1);
+ QualType(AP1.first->getTypeForDecl(), 0), O1);
O1.flush();
std::string S2;
llvm::raw_string_ostream O2(S2);
getCXXABI().getMangleContext().mangleTypeName(
- QualType(E2.first->getTypeForDecl(), 0), O2);
+ QualType(AP2.first->getTypeForDecl(), 0), O2);
O2.flush();
if (S1 < S2)
@@ -1015,10 +1042,26 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
if (S1 != S2)
return false;
- return E1.second < E2.second;
+ return AP1.second < AP2.second;
});
- for (auto BitsetEntry : BitsetEntries)
- AddVTableTypeMetadata(VTable, PointerWidth * BitsetEntry.second,
- BitsetEntry.first);
+ ArrayRef<VTableComponent> Comps = VTLayout.vtable_components();
+ for (auto AP : AddressPoints) {
+ // Create type metadata for the address point.
+ AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first);
+
+ // The class associated with each address point could also potentially be
+ // used for indirect calls via a member function pointer, so we need to
+ // annotate the address of each function pointer with the appropriate member
+ // function pointer type.
+ for (unsigned I = 0; I != Comps.size(); ++I) {
+ if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer)
+ continue;
+ llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType(
+ Context.getMemberPointerType(
+ Comps[I].getFunctionDecl()->getType(),
+ Context.getRecordType(AP.first).getTypePtr()));
+ VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD);
+ }
+ }
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
index b92212c368a9..6377659e4cb3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
@@ -40,7 +40,7 @@ class CodeGenVTables {
typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy;
-
+
/// SubVTTIndicies - Contains indices into the various sub-VTTs.
SubVTTIndiciesMapTy SubVTTIndicies;
@@ -57,12 +57,10 @@ class CodeGenVTables {
/// Cache for the deleted virtual member call function.
llvm::Constant *DeletedVirtualFn = nullptr;
- /// emitThunk - Emit a single thunk.
- void emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, bool ForVTable);
-
- /// maybeEmitThunkForVTable - Emit the given thunk for the vtable if needed by
- /// the ABI.
- void maybeEmitThunkForVTable(GlobalDecl GD, const ThunkInfo &Thunk);
+ /// Get the address of a thunk and emit it if necessary.
+ llvm::Constant *maybeEmitThunk(GlobalDecl GD,
+ const ThunkInfo &ThunkAdjustments,
+ bool ForVTable);
void addVTableComponent(ConstantArrayBuilder &builder,
const VTableLayout &layout, unsigned idx,
@@ -89,21 +87,21 @@ public:
/// getSubVTTIndex - Return the index of the sub-VTT for the base class of the
/// given record decl.
uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base);
-
+
/// getSecondaryVirtualPointerIndex - Return the index in the VTT where the
/// virtual pointer for the given subobject is located.
uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
BaseSubobject Base);
- /// GenerateConstructionVTable - Generate a construction vtable for the given
+ /// GenerateConstructionVTable - Generate a construction vtable for the given
/// base subobject.
llvm::GlobalVariable *
- GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base,
- bool BaseIsVirtual,
+ GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base,
+ bool BaseIsVirtual,
llvm::GlobalVariable::LinkageTypes Linkage,
VTableAddressPointsMapTy& AddressPoints);
-
+
/// GetAddrOfVTT - Get the address of the VTT for the given record decl.
llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD);
@@ -114,7 +112,7 @@ public:
/// EmitThunks - Emit the associated thunks for the given global decl.
void EmitThunks(GlobalDecl GD);
-
+
/// GenerateClassData - Generate all the class data required to be
/// generated upon definition of a KeyFunction. This includes the
/// vtable, the RTTI data structure (if RTTI is enabled) and the VTT
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
index 7d07ea4516c9..0dcbea423ad7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
@@ -193,11 +193,11 @@ class LValue {
// The alignment to use when accessing this lvalue. (For vector elements,
// this is the alignment of the whole vector.)
- int64_t Alignment;
+ unsigned Alignment;
// objective-c's ivar
bool Ivar:1;
-
+
// objective-c's ivar is an array
bool ObjIsArray:1;
@@ -207,7 +207,7 @@ class LValue {
// Lvalue is a global reference of an objective-c object
bool GlobalObjCRef : 1;
-
+
// Lvalue is a thread local reference
bool ThreadLocalRef : 1;
@@ -215,13 +215,13 @@ class LValue {
// to make the default bitfield pattern all-zeroes.
bool ImpreciseLifetime : 1;
- LValueBaseInfo BaseInfo;
- TBAAAccessInfo TBAAInfo;
-
// This flag shows if a nontemporal load/stores should be used when accessing
// this lvalue.
bool Nontemporal : 1;
+ LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
+
Expr *BaseIvarExp;
private:
@@ -231,7 +231,10 @@ private:
"initializing l-value with zero alignment!");
this->Type = Type;
this->Quals = Quals;
- this->Alignment = Alignment.getQuantity();
+ const unsigned MaxAlign = 1U << 31;
+ this->Alignment = Alignment.getQuantity() <= MaxAlign
+ ? Alignment.getQuantity()
+ : MaxAlign;
assert(this->Alignment == Alignment.getQuantity() &&
"Alignment exceeds allowed max!");
this->BaseInfo = BaseInfo;
@@ -298,7 +301,7 @@ public:
bool isVolatile() const {
return Quals.hasVolatile();
}
-
+
Expr *getBaseIvarExp() const { return BaseIvarExp; }
void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
@@ -398,7 +401,7 @@ public:
return R;
}
- /// \brief Create a new object to represent a bit-field access.
+ /// Create a new object to represent a bit-field access.
///
/// \param Addr - The base address of the bit-field sequence this
/// bit-field refers to.
@@ -449,7 +452,7 @@ class AggValueSlot {
/// slot might require calling an appropriate Objective-C GC
/// barrier. The exact interaction here is unnecessarily mysterious.
bool ObjCGCFlag : 1;
-
+
/// ZeroedFlag - This is set to true if the memory in the slot is
/// known to be zero before the assignment into it. This means that
/// zero fields don't need to be set.
@@ -469,17 +472,33 @@ class AggValueSlot {
/// evaluating an expression which constructs such an object.
bool AliasedFlag : 1;
+ /// This is set to true if the tail padding of this slot might overlap
+ /// another object that may have already been initialized (and whose
+ /// value must be preserved by this initialization). If so, we may only
+ /// store up to the dsize of the type. Otherwise we can widen stores to
+ /// the size of the type.
+ bool OverlapFlag : 1;
+
+ /// If is set to true, sanitizer checks are already generated for this address
+ /// or not required. For instance, if this address represents an object
+ /// created in 'new' expression, sanitizer checks for memory is made as a part
+ /// of 'operator new' emission and object constructor should not generate
+ /// them.
+ bool SanitizerCheckedFlag : 1;
+
public:
enum IsAliased_t { IsNotAliased, IsAliased };
enum IsDestructed_t { IsNotDestructed, IsDestructed };
enum IsZeroed_t { IsNotZeroed, IsZeroed };
+ enum Overlap_t { DoesNotOverlap, MayOverlap };
enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
+ enum IsSanitizerChecked_t { IsNotSanitizerChecked, IsSanitizerChecked };
/// ignored - Returns an aggregate value slot indicating that the
/// aggregate value is being ignored.
static AggValueSlot ignored() {
return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed,
- DoesNotNeedGCBarriers, IsNotAliased);
+ DoesNotNeedGCBarriers, IsNotAliased, DoesNotOverlap);
}
/// forAddr - Make a slot for an aggregate value.
@@ -497,7 +516,9 @@ public:
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
- IsZeroed_t isZeroed = IsNotZeroed) {
+ Overlap_t mayOverlap,
+ IsZeroed_t isZeroed = IsNotZeroed,
+ IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) {
AggValueSlot AV;
if (addr.isValid()) {
AV.Addr = addr.getPointer();
@@ -511,6 +532,8 @@ public:
AV.ObjCGCFlag = needsGC;
AV.ZeroedFlag = isZeroed;
AV.AliasedFlag = isAliased;
+ AV.OverlapFlag = mayOverlap;
+ AV.SanitizerCheckedFlag = isChecked;
return AV;
}
@@ -518,9 +541,11 @@ public:
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
- IsZeroed_t isZeroed = IsNotZeroed) {
- return forAddr(LV.getAddress(),
- LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
+ Overlap_t mayOverlap,
+ IsZeroed_t isZeroed = IsNotZeroed,
+ IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) {
+ return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC,
+ isAliased, mayOverlap, isZeroed, isChecked);
}
IsDestructed_t isExternallyDestructed() const {
@@ -539,7 +564,7 @@ public:
void setVolatile(bool flag) {
Quals.setVolatile(flag);
}
-
+
Qualifiers::ObjCLifetime getObjCLifetime() const {
return Quals.getObjCLifetime();
}
@@ -568,6 +593,14 @@ public:
return IsAliased_t(AliasedFlag);
}
+ Overlap_t mayOverlap() const {
+ return Overlap_t(OverlapFlag);
+ }
+
+ bool isSanitizerChecked() const {
+ return SanitizerCheckedFlag;
+ }
+
RValue asRValue() const {
if (isIgnored()) {
return RValue::getIgnored();
@@ -580,6 +613,14 @@ public:
IsZeroed_t isZeroed() const {
return IsZeroed_t(ZeroedFlag);
}
+
+ /// Get the preferred size to use when storing a value to this slot. This
+ /// is the type size unless that might overlap another object, in which
+ /// case it's the dsize.
+ CharUnits getPreferredSize(ASTContext &Ctx, QualType Type) const {
+ return mayOverlap() ? Ctx.getTypeInfoDataSizeInChars(Type).first
+ : Ctx.getTypeSizeInChars(Type);
+ }
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
index 6ca69d63cdce..1a2b0616dc77 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
@@ -51,7 +51,7 @@ namespace clang {
public:
ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon)
: CodeGenOpts(CGOpts), BackendCon(BCon) {}
-
+
bool handleDiagnostics(const DiagnosticInfo &DI) override;
bool isAnalysisRemarkEnabled(StringRef PassName) const override {
@@ -126,6 +126,7 @@ namespace clang {
Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) {
+ FrontendTimesIsEnabled = TimePasses;
llvm::TimePassesIsEnabled = TimePasses;
}
llvm::Module *getModule() const { return Gen->GetModule(); }
@@ -144,12 +145,12 @@ namespace clang {
Context = &Ctx;
- if (llvm::TimePassesIsEnabled)
+ if (FrontendTimesIsEnabled)
LLVMIRGeneration.startTimer();
Gen->Initialize(Ctx);
- if (llvm::TimePassesIsEnabled)
+ if (FrontendTimesIsEnabled)
LLVMIRGeneration.stopTimer();
}
@@ -159,7 +160,7 @@ namespace clang {
"LLVM IR generation of declaration");
// Recurse.
- if (llvm::TimePassesIsEnabled) {
+ if (FrontendTimesIsEnabled) {
LLVMIRGenerationRefCount += 1;
if (LLVMIRGenerationRefCount == 1)
LLVMIRGeneration.startTimer();
@@ -167,7 +168,7 @@ namespace clang {
Gen->HandleTopLevelDecl(D);
- if (llvm::TimePassesIsEnabled) {
+ if (FrontendTimesIsEnabled) {
LLVMIRGenerationRefCount -= 1;
if (LLVMIRGenerationRefCount == 0)
LLVMIRGeneration.stopTimer();
@@ -180,12 +181,12 @@ namespace clang {
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
"LLVM IR generation of inline function");
- if (llvm::TimePassesIsEnabled)
+ if (FrontendTimesIsEnabled)
LLVMIRGeneration.startTimer();
Gen->HandleInlineFunctionDefinition(D);
- if (llvm::TimePassesIsEnabled)
+ if (FrontendTimesIsEnabled)
LLVMIRGeneration.stopTimer();
}
@@ -227,7 +228,7 @@ namespace clang {
void HandleTranslationUnit(ASTContext &C) override {
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
- if (llvm::TimePassesIsEnabled) {
+ if (FrontendTimesIsEnabled) {
LLVMIRGenerationRefCount += 1;
if (LLVMIRGenerationRefCount == 1)
LLVMIRGeneration.startTimer();
@@ -235,13 +236,13 @@ namespace clang {
Gen->HandleTranslationUnit(C);
- if (llvm::TimePassesIsEnabled) {
+ if (FrontendTimesIsEnabled) {
LLVMIRGenerationRefCount -= 1;
if (LLVMIRGenerationRefCount == 0)
LLVMIRGeneration.stopTimer();
}
- IRGenFinished = true;
+ IRGenFinished = true;
}
// Silently ignore if we weren't initialized for some reason.
@@ -341,17 +342,17 @@ namespace clang {
SourceLocation LocCookie);
void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
- /// \brief Specialized handler for InlineAsm diagnostic.
+ /// Specialized handler for InlineAsm diagnostic.
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
- /// \brief Specialized handler for StackSize diagnostic.
+ /// Specialized handler for StackSize diagnostic.
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
- /// \brief Specialized handler for unsupported backend feature diagnostic.
+ /// Specialized handler for unsupported backend feature diagnostic.
void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D);
- /// \brief Specialized handlers for optimization remarks.
+ /// Specialized handlers for optimization remarks.
/// Note that these handlers only accept remarks and they always handle
/// them.
void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
@@ -697,7 +698,7 @@ void BackendConsumer::OptimizationFailureHandler(
EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
}
-/// \brief This function is invoked when the backend needs
+/// This function is invoked when the backend needs
/// to report something to the user.
void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
unsigned DiagID = diag::err_fe_inline_asm;
@@ -846,7 +847,10 @@ GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
std::unique_ptr<ASTConsumer>
CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
BackendAction BA = static_cast<BackendAction>(Act);
- std::unique_ptr<raw_pwrite_stream> OS = GetOutputStream(CI, InFile, BA);
+ std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream();
+ if (!OS)
+ OS = GetOutputStream(CI, InFile, BA);
+
if (BA != Backend_EmitNothing && !OS)
return nullptr;
@@ -947,12 +951,21 @@ std::unique_ptr<llvm::Module> CodeGenAction::loadModule(MemoryBufferRef MBRef) {
return {};
};
- Expected<llvm::BitcodeModule> BMOrErr = FindThinLTOModule(MBRef);
- if (!BMOrErr)
- return DiagErrors(BMOrErr.takeError());
-
+ Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef);
+ if (!BMsOrErr)
+ return DiagErrors(BMsOrErr.takeError());
+ BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr);
+ // We have nothing to do if the file contains no ThinLTO module. This is
+ // possible if ThinLTO compilation was not able to split module. Content of
+ // the file was already processed by indexing and will be passed to the
+ // linker using merged object file.
+ if (!Bm) {
+ auto M = llvm::make_unique<llvm::Module>("empty", *VMContext);
+ M->setTargetTriple(CI.getTargetOpts().Triple);
+ return M;
+ }
Expected<std::unique_ptr<llvm::Module>> MOrErr =
- BMOrErr->parseModule(*VMContext);
+ Bm->parseModule(*VMContext);
if (!MOrErr)
return DiagErrors(MOrErr.takeError());
return std::move(*MOrErr);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
index 664b51078424..3c582688e91e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -65,25 +65,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
: CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(),
CGBuilderInserterTy(this)),
- CurFn(nullptr), ReturnValue(Address::invalid()),
- CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize),
- IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false),
- SawAsmBlock(false), IsOutlinedSEHHelper(false), BlockInfo(nullptr),
- BlockPointer(nullptr), LambdaThisCaptureField(nullptr),
- NormalCleanupDest(nullptr), NextCleanupDestIndex(1),
- FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr),
- EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()),
- DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr),
- PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr),
- CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
- NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
- CXXABIThisValue(nullptr), CXXThisValue(nullptr),
- CXXStructorImplicitParamDecl(nullptr),
- CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
- CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
- TerminateHandler(nullptr), TrapBB(nullptr),
- ShouldEmitLifetimeMarkers(
- shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
+ SanOpts(CGM.getLangOpts().Sanitize), DebugInfo(CGM.getModuleDebugInfo()),
+ PGO(cgm), ShouldEmitLifetimeMarkers(shouldEmitLifetimeMarkers(
+ CGM.getCodeGenOpts(), CGM.getLangOpts())) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
@@ -439,11 +423,17 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// 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()) {
+ if (NormalCleanupDest.isValid() && isCoroutine()) {
llvm::DominatorTree DT(*CurFn);
- llvm::PromoteMemToReg(NormalCleanupDest, DT);
- NormalCleanupDest = nullptr;
+ llvm::PromoteMemToReg(
+ cast<llvm::AllocaInst>(NormalCleanupDest.getPointer()), DT);
+ NormalCleanupDest = Address::invalid();
}
+
+ // Add the required-vector-width attribute.
+ if (LargestVectorWidth != 0)
+ CurFn->addFnAttr("min-legal-vector-width",
+ llvm::utostr(LargestVectorWidth));
}
/// ShouldInstrumentFunction - Return true if the current function should be
@@ -465,9 +455,19 @@ bool CodeGenFunction::ShouldXRayInstrumentFunction() const {
}
/// AlwaysEmitXRayCustomEvents - Return true if we should emit IR for calls to
-/// the __xray_customevent(...) builin calls, when doing XRay instrumentation.
+/// the __xray_customevent(...) builtin calls, when doing XRay instrumentation.
bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const {
- return CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents;
+ return CGM.getCodeGenOpts().XRayInstrumentFunctions &&
+ (CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents ||
+ CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask ==
+ XRayInstrKind::Custom);
+}
+
+bool CodeGenFunction::AlwaysEmitXRayTypedEvents() const {
+ return CGM.getCodeGenOpts().XRayInstrumentFunctions &&
+ (CGM.getCodeGenOpts().XRayAlwaysEmitTypedEvents ||
+ CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask ==
+ XRayInstrKind::Typed);
}
llvm::Constant *
@@ -845,14 +845,24 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (D) {
// Apply the no_sanitize* attributes to SanOpts.
- for (auto Attr : D->specific_attrs<NoSanitizeAttr>())
- SanOpts.Mask &= ~Attr->getMask();
+ for (auto Attr : D->specific_attrs<NoSanitizeAttr>()) {
+ SanitizerMask mask = Attr->getMask();
+ SanOpts.Mask &= ~mask;
+ if (mask & SanitizerKind::Address)
+ SanOpts.set(SanitizerKind::KernelAddress, false);
+ if (mask & SanitizerKind::KernelAddress)
+ SanOpts.set(SanitizerKind::Address, false);
+ if (mask & SanitizerKind::HWAddress)
+ SanOpts.set(SanitizerKind::KernelHWAddress, false);
+ if (mask & SanitizerKind::KernelHWAddress)
+ SanOpts.set(SanitizerKind::HWAddress, false);
+ }
}
// Apply sanitizer attributes to the function.
if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
- if (SanOpts.hasOneOf(SanitizerKind::HWAddress))
+ if (SanOpts.hasOneOf(SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress))
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
@@ -860,6 +870,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
if (SanOpts.has(SanitizerKind::SafeStack))
Fn->addFnAttr(llvm::Attribute::SafeStack);
+ if (SanOpts.has(SanitizerKind::ShadowCallStack))
+ Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
+
+ // Apply fuzzing attribute to the function.
+ if (SanOpts.hasOneOf(SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink))
+ Fn->addFnAttr(llvm::Attribute::OptForFuzzing);
// Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
// .cxx_destruct, __destroy_helper_block_ and all of their calees at run time.
@@ -887,7 +903,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
// Apply xray attributes to the function (as a string, for now)
- if (D && ShouldXRayInstrumentFunction()) {
+ bool InstrumentXray = ShouldXRayInstrumentFunction() &&
+ CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
+ XRayInstrKind::Function);
+ if (D && InstrumentXray) {
if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
if (XRayAttr->alwaysXRayInstrument())
Fn->addFnAttr("function-instrument", "xray-always");
@@ -924,8 +943,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
+ // Remove any (C++17) exception specifications, to allow calling e.g. a
+ // noexcept function through a non-noexcept pointer.
+ auto ProtoTy =
+ getContext().getFunctionTypeWithExceptionSpec(FD->getType(),
+ EST_None);
llvm::Constant *FTRTTIConst =
- CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true);
+ CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
llvm::Constant *FTRTTIConstEncoded =
EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
llvm::Constant *PrologueStructElems[] = {PrologueSig,
@@ -990,7 +1014,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
ArgTypes.push_back(VD->getType());
QualType FnType = getContext().getFunctionType(
RetTy, ArgTypes, FunctionProtoType::ExtProtoInfo(CC));
- DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder);
+ DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, CurFuncIsThunk,
+ Builder);
}
if (ShouldInstrumentFunction()) {
@@ -1009,10 +1034,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// The attribute "counting-function" is set to mcount function name which is
// architecture dependent.
if (CGM.getCodeGenOpts().InstrumentForProfiling) {
- if (CGM.getCodeGenOpts().CallFEntry)
- Fn->addFnAttr("fentry-call", "true");
- else {
- if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>()) {
+ // Calls to fentry/mcount should not be generated if function has
+ // the no_instrument_function attribute.
+ if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>()) {
+ if (CGM.getCodeGenOpts().CallFEntry)
+ Fn->addFnAttr("fentry-call", "true");
+ else {
Fn->addFnAttr("instrument-function-entry-inlined",
getTarget().getMCountName());
}
@@ -1058,6 +1085,11 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
EmitStartEHSpec(CurCodeDecl);
PrologueCleanupDepth = EHStack.stable_begin();
+
+ // Emit OpenMP specific initialization of the device functions.
+ if (getLangOpts().OpenMP && CurCodeDecl)
+ CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
+
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) {
@@ -1111,8 +1143,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// may have a static invoker function, which may call this operator with
// a null 'this' pointer.
if (isLambdaCallOperator(MD) &&
- cast<CXXRecordDecl>(MD->getParent())->getLambdaCaptureDefault() ==
- LCD_None)
+ MD->getParent()->getLambdaCaptureDefault() == LCD_None)
SkippedChecks.set(SanitizerKind::Null, true);
EmitTypeCheck(isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall
@@ -1144,6 +1175,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// Emit a location at the end of the prologue.
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitLocation(Builder, StartLoc);
+
+ // TODO: Do we need to handle this in two places like we do with
+ // target-features/target-cpu?
+ if (CurFuncDecl)
+ if (const auto *VecWidth = CurFuncDecl->getAttr<MinVectorWidthAttr>())
+ LargestVectorWidth = VecWidth->getVectorWidth();
}
void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
@@ -1751,12 +1788,9 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
if (const VariableArrayType *vlaType =
dyn_cast_or_null<VariableArrayType>(
getContext().getAsArrayType(Ty))) {
- QualType eltType;
- llvm::Value *numElts;
- std::tie(numElts, eltType) = getVLASize(vlaType);
-
- SizeVal = numElts;
- CharUnits eltSize = getContext().getTypeSizeInChars(eltType);
+ auto VlaSize = getVLASize(vlaType);
+ SizeVal = VlaSize.NumElts;
+ CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type);
if (!eltSize.isOne())
SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize));
vla = vlaType;
@@ -1839,7 +1873,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
// this is the size of the VLA in bytes, not its size in elements.
llvm::Value *numVLAElements = nullptr;
if (isa<VariableArrayType>(arrayType)) {
- numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).first;
+ numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).NumElts;
// Walk into all VLAs. This doesn't require changes to addr,
// which has type T* where T is the first non-VLA element type.
@@ -1920,14 +1954,13 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
return numElements;
}
-std::pair<llvm::Value*, QualType>
-CodeGenFunction::getVLASize(QualType type) {
+CodeGenFunction::VlaSizePair CodeGenFunction::getVLASize(QualType type) {
const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
assert(vla && "type was not a variable array type!");
return getVLASize(vla);
}
-std::pair<llvm::Value*, QualType>
+CodeGenFunction::VlaSizePair
CodeGenFunction::getVLASize(const VariableArrayType *type) {
// The number of elements so far; always size_t.
llvm::Value *numElements = nullptr;
@@ -1948,7 +1981,22 @@ CodeGenFunction::getVLASize(const VariableArrayType *type) {
}
} while ((type = getContext().getAsVariableArrayType(elementType)));
- return std::pair<llvm::Value*,QualType>(numElements, elementType);
+ return { numElements, elementType };
+}
+
+CodeGenFunction::VlaSizePair
+CodeGenFunction::getVLAElements1D(QualType type) {
+ const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
+ assert(vla && "type was not a variable array type!");
+ return getVLAElements1D(vla);
+}
+
+CodeGenFunction::VlaSizePair
+CodeGenFunction::getVLAElements1D(const VariableArrayType *Vla) {
+ llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()];
+ assert(VlaSize && "no size for VLA!");
+ assert(VlaSize->getType() == SizeTy);
+ return { VlaSize, Vla->getElementType() };
}
void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
@@ -2231,7 +2279,7 @@ static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
return std::all_of(
ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) {
SmallVector<StringRef, 1> OrFeatures;
- Feature.split(OrFeatures, "|");
+ Feature.split(OrFeatures, '|');
return std::any_of(OrFeatures.begin(), OrFeatures.end(),
[&](StringRef Feature) {
if (!CallerFeatureMap.lookup(Feature)) {
@@ -2269,17 +2317,28 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
// Return if the builtin doesn't have any required features.
if (!FeatureList || StringRef(FeatureList) == "")
return;
- StringRef(FeatureList).split(ReqFeatures, ",");
+ StringRef(FeatureList).split(ReqFeatures, ',');
if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature)
<< TargetDecl->getDeclName()
<< CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
- } else if (TargetDecl->hasAttr<TargetAttr>()) {
+ } else if (TargetDecl->hasAttr<TargetAttr>() ||
+ TargetDecl->hasAttr<CPUSpecificAttr>()) {
// Get the required features for the callee.
+
+ const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
+ TargetAttr::ParsedTargetAttr ParsedAttr = CGM.filterFunctionTargetAttrs(TD);
+
SmallVector<StringRef, 1> ReqFeatures;
llvm::StringMap<bool> CalleeFeatureMap;
CGM.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+ for (const auto &F : ParsedAttr.Features) {
+ if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
+ ReqFeatures.push_back(StringRef(F).substr(1));
+ }
+
for (const auto &F : CalleeFeatureMap) {
// Only positive features are "required".
if (F.getValue())
@@ -2300,6 +2359,99 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
CGM.getSanStats().create(IRB, SSK);
}
+llvm::Value *CodeGenFunction::FormResolverCondition(
+ const TargetMultiVersionResolverOption &RO) {
+ llvm::Value *TrueCondition = nullptr;
+ if (!RO.ParsedAttribute.Architecture.empty())
+ TrueCondition = EmitX86CpuIs(RO.ParsedAttribute.Architecture);
+
+ if (!RO.ParsedAttribute.Features.empty()) {
+ SmallVector<StringRef, 8> FeatureList;
+ llvm::for_each(RO.ParsedAttribute.Features,
+ [&FeatureList](const std::string &Feature) {
+ FeatureList.push_back(StringRef{Feature}.substr(1));
+ });
+ llvm::Value *FeatureCmp = EmitX86CpuSupports(FeatureList);
+ TrueCondition = TrueCondition ? Builder.CreateAnd(TrueCondition, FeatureCmp)
+ : FeatureCmp;
+ }
+ return TrueCondition;
+}
+
+void CodeGenFunction::EmitTargetMultiVersionResolver(
+ llvm::Function *Resolver,
+ ArrayRef<TargetMultiVersionResolverOption> Options) {
+ assert((getContext().getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::x86 ||
+ getContext().getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::x86_64) &&
+ "Only implemented for x86 targets");
+
+ // Main function's basic block.
+ llvm::BasicBlock *CurBlock = createBasicBlock("entry", Resolver);
+ Builder.SetInsertPoint(CurBlock);
+ EmitX86CpuInit();
+
+ llvm::Function *DefaultFunc = nullptr;
+ for (const TargetMultiVersionResolverOption &RO : Options) {
+ Builder.SetInsertPoint(CurBlock);
+ llvm::Value *TrueCondition = FormResolverCondition(RO);
+
+ if (!TrueCondition) {
+ DefaultFunc = RO.Function;
+ } else {
+ llvm::BasicBlock *RetBlock = createBasicBlock("ro_ret", Resolver);
+ llvm::IRBuilder<> RetBuilder(RetBlock);
+ RetBuilder.CreateRet(RO.Function);
+ CurBlock = createBasicBlock("ro_else", Resolver);
+ Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
+ }
+ }
+
+ assert(DefaultFunc && "No default version?");
+ // Emit return from the 'else-ist' block.
+ Builder.SetInsertPoint(CurBlock);
+ Builder.CreateRet(DefaultFunc);
+}
+
+void CodeGenFunction::EmitCPUDispatchMultiVersionResolver(
+ llvm::Function *Resolver,
+ ArrayRef<CPUDispatchMultiVersionResolverOption> Options) {
+ assert((getContext().getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::x86 ||
+ getContext().getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::x86_64) &&
+ "Only implemented for x86 targets");
+
+ // Main function's basic block.
+ llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
+ Builder.SetInsertPoint(CurBlock);
+ EmitX86CpuInit();
+
+ for (const CPUDispatchMultiVersionResolverOption &RO : Options) {
+ Builder.SetInsertPoint(CurBlock);
+
+ // "generic" case should catch-all.
+ if (RO.FeatureMask == 0) {
+ Builder.CreateRet(RO.Function);
+ return;
+ }
+ llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
+ llvm::IRBuilder<> RetBuilder(RetBlock);
+ RetBuilder.CreateRet(RO.Function);
+ CurBlock = createBasicBlock("resolver_else", Resolver);
+ llvm::Value *TrueCondition = EmitX86CpuSupports(RO.FeatureMask);
+ Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
+ }
+
+ Builder.SetInsertPoint(CurBlock);
+ llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+}
+
llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
if (CGDebugInfo *DI = getDebugInfo())
return DI->SourceLocToDebugLoc(Location);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
index 3e89586be3a5..878923a85bdf 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -116,6 +116,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(ImplicitConversion, implicit_conversion, 0) \
SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \
SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \
SANITIZER_CHECK(MissingReturn, missing_return, 0) \
@@ -138,6 +139,88 @@ enum SanitizerHandler {
#undef SANITIZER_CHECK
};
+/// Helper class with most of the code for saving a value for a
+/// conditional expression cleanup.
+struct DominatingLLVMValue {
+ typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type;
+
+ /// Answer whether the given value needs extra work to be saved.
+ static bool needsSaving(llvm::Value *value) {
+ // If it's not an instruction, we don't need to save.
+ if (!isa<llvm::Instruction>(value)) return false;
+
+ // If it's an instruction in the entry block, we don't need to save.
+ llvm::BasicBlock *block = cast<llvm::Instruction>(value)->getParent();
+ return (block != &block->getParent()->getEntryBlock());
+ }
+
+ static saved_type save(CodeGenFunction &CGF, llvm::Value *value);
+ static llvm::Value *restore(CodeGenFunction &CGF, saved_type value);
+};
+
+/// A partial specialization of DominatingValue for llvm::Values that
+/// might be llvm::Instructions.
+template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
+ typedef T *type;
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return static_cast<T*>(DominatingLLVMValue::restore(CGF, value));
+ }
+};
+
+/// A specialization of DominatingValue for Address.
+template <> struct DominatingValue<Address> {
+ typedef Address type;
+
+ struct saved_type {
+ DominatingLLVMValue::saved_type SavedValue;
+ CharUnits Alignment;
+ };
+
+ static bool needsSaving(type value) {
+ return DominatingLLVMValue::needsSaving(value.getPointer());
+ }
+ static saved_type save(CodeGenFunction &CGF, type value) {
+ return { DominatingLLVMValue::save(CGF, value.getPointer()),
+ value.getAlignment() };
+ }
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return Address(DominatingLLVMValue::restore(CGF, value.SavedValue),
+ value.Alignment);
+ }
+};
+
+/// A specialization of DominatingValue for RValue.
+template <> struct DominatingValue<RValue> {
+ typedef RValue type;
+ class saved_type {
+ enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral,
+ AggregateAddress, ComplexAddress };
+
+ llvm::Value *Value;
+ unsigned K : 3;
+ unsigned Align : 29;
+ saved_type(llvm::Value *v, Kind k, unsigned a = 0)
+ : Value(v), K(k), Align(a) {}
+
+ public:
+ static bool needsSaving(RValue value);
+ static saved_type save(CodeGenFunction &CGF, RValue value);
+ RValue restore(CodeGenFunction &CGF);
+
+ // implementations in CGCleanup.cpp
+ };
+
+ static bool needsSaving(type value) {
+ return saved_type::needsSaving(value);
+ }
+ static saved_type save(CodeGenFunction &CGF, type value) {
+ return saved_type::save(CGF, value);
+ }
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return value.restore(CGF);
+ }
+};
+
/// CodeGenFunction - This class organizes the per-function state that is used
/// while generating LLVM code.
class CodeGenFunction : public CodeGenTypeCache {
@@ -201,7 +284,7 @@ public:
Address UB)>
CodeGenDispatchBoundsTy;
- /// \brief CGBuilder insert helper. This function is called after an
+ /// CGBuilder insert helper. This function is called after an
/// instruction is created using Builder.
void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
llvm::BasicBlock *BB,
@@ -214,7 +297,7 @@ public:
const Decl *CurCodeDecl;
const CGFunctionInfo *CurFnInfo;
QualType FnRetTy;
- llvm::Function *CurFn;
+ llvm::Function *CurFn = nullptr;
// Holds coroutine data if the current function is a coroutine. We use a
// wrapper to manage its lifetime, so that we don't have to define CGCoroData
@@ -242,7 +325,7 @@ public:
/// ReturnValue - The temporary alloca to hold the return
/// value. This is invalid iff the function has no return value.
- Address ReturnValue;
+ Address ReturnValue = Address::invalid();
/// Return true if a label was seen in the current scope.
bool hasLabelBeenSeenInCurrentScope() const {
@@ -255,7 +338,7 @@ public:
/// we prefer to insert allocas.
llvm::AssertingVH<llvm::Instruction> AllocaInsertPt;
- /// \brief API for captured statement code generation.
+ /// API for captured statement code generation.
class CGCapturedStmtInfo {
public:
explicit CGCapturedStmtInfo(CapturedRegionKind K = CR_Default)
@@ -283,10 +366,10 @@ public:
CapturedRegionKind getKind() const { return Kind; }
virtual void setContextValue(llvm::Value *V) { ThisValue = V; }
- // \brief Retrieve the value of the context parameter.
+ // Retrieve the value of the context parameter.
virtual llvm::Value *getContextValue() const { return ThisValue; }
- /// \brief Lookup the captured field decl for a variable.
+ /// Lookup the captured field decl for a variable.
virtual const FieldDecl *lookup(const VarDecl *VD) const {
return CaptureFields.lookup(VD->getCanonicalDecl());
}
@@ -298,32 +381,32 @@ public:
return true;
}
- /// \brief Emit the captured statement body.
+ /// Emit the captured statement body.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) {
CGF.incrementProfileCounter(S);
CGF.EmitStmt(S);
}
- /// \brief Get the name of the capture helper.
+ /// Get the name of the capture helper.
virtual StringRef getHelperName() const { return "__captured_stmt"; }
private:
- /// \brief The kind of captured statement being generated.
+ /// The kind of captured statement being generated.
CapturedRegionKind Kind;
- /// \brief Keep the map between VarDecl and FieldDecl.
+ /// Keep the map between VarDecl and FieldDecl.
llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields;
- /// \brief The base address of the captured record, passed in as the first
+ /// The base address of the captured record, passed in as the first
/// argument of the parallel region function.
llvm::Value *ThisValue;
- /// \brief Captured 'this' type.
+ /// Captured 'this' type.
FieldDecl *CXXThisFieldDecl;
};
- CGCapturedStmtInfo *CapturedStmtInfo;
+ CGCapturedStmtInfo *CapturedStmtInfo = nullptr;
- /// \brief RAII for correct setting/restoring of CapturedStmtInfo.
+ /// RAII for correct setting/restoring of CapturedStmtInfo.
class CGCapturedStmtRAII {
private:
CodeGenFunction &CGF;
@@ -362,13 +445,13 @@ public:
}
};
- /// \brief Sanitizers enabled for this function.
+ /// Sanitizers enabled for this function.
SanitizerSet SanOpts;
- /// \brief True if CodeGen currently emits code implementing sanitizer checks.
- bool IsSanitizerScope;
+ /// True if CodeGen currently emits code implementing sanitizer checks.
+ bool IsSanitizerScope = false;
- /// \brief RAII object to set/unset CodeGenFunction::IsSanitizerScope.
+ /// RAII object to set/unset CodeGenFunction::IsSanitizerScope.
class SanitizerScope {
CodeGenFunction *CGF;
public:
@@ -378,28 +461,28 @@ public:
/// In C++, whether we are code generating a thunk. This controls whether we
/// should emit cleanups.
- bool CurFuncIsThunk;
+ bool CurFuncIsThunk = false;
/// In ARC, whether we should autorelease the return value.
- bool AutoreleaseResult;
+ bool AutoreleaseResult = false;
/// Whether we processed a Microsoft-style asm block during CodeGen. These can
/// potentially set the return value.
- bool SawAsmBlock;
+ bool SawAsmBlock = false;
- const FunctionDecl *CurSEHParent = nullptr;
+ const NamedDecl *CurSEHParent = nullptr;
/// True if the current function is an outlined SEH helper. This can be a
/// finally block or filter expression.
- bool IsOutlinedSEHHelper;
+ bool IsOutlinedSEHHelper = false;
- const CodeGen::CGBlockInfo *BlockInfo;
- llvm::Value *BlockPointer;
+ const CodeGen::CGBlockInfo *BlockInfo = nullptr;
+ llvm::Value *BlockPointer = nullptr;
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
- FieldDecl *LambdaThisCaptureField;
+ FieldDecl *LambdaThisCaptureField = nullptr;
- /// \brief A mapping from NRVO variables to the flags used to indicate
+ /// A mapping from NRVO variables to the flags used to indicate
/// when the NRVO has been applied to this variable.
llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags;
@@ -427,30 +510,33 @@ public:
/// The size of the following cleanup object.
unsigned Size;
/// The kind of cleanup to push: a value from the CleanupKind enumeration.
- CleanupKind Kind;
+ unsigned Kind : 31;
+ /// Whether this is a conditional cleanup.
+ unsigned IsConditional : 1;
size_t getSize() const { return Size; }
- CleanupKind getKind() const { return Kind; }
+ CleanupKind getKind() const { return (CleanupKind)Kind; }
+ bool isConditional() const { return IsConditional; }
};
/// i32s containing the indexes of the cleanup destinations.
- llvm::AllocaInst *NormalCleanupDest;
+ Address NormalCleanupDest = Address::invalid();
- unsigned NextCleanupDestIndex;
+ unsigned NextCleanupDestIndex = 1;
/// FirstBlockInfo - The head of a singly-linked-list of block layouts.
- CGBlockInfo *FirstBlockInfo;
+ CGBlockInfo *FirstBlockInfo = nullptr;
/// EHResumeBlock - Unified block containing a call to llvm.eh.resume.
- llvm::BasicBlock *EHResumeBlock;
+ llvm::BasicBlock *EHResumeBlock = nullptr;
/// The exception slot. All landing pads write the current exception pointer
/// into this alloca.
- llvm::Value *ExceptionSlot;
+ llvm::Value *ExceptionSlot = nullptr;
/// The selector slot. Under the MandatoryCleanup model, all landing pads
/// write the current selector value into this alloca.
- llvm::AllocaInst *EHSelectorSlot;
+ llvm::AllocaInst *EHSelectorSlot = nullptr;
/// A stack of exception code slots. Entering an __except block pushes a slot
/// on the stack and leaving pops one. The __exception_code() intrinsic loads
@@ -525,28 +611,52 @@ public:
initFullExprCleanup();
}
- /// \brief Queue a cleanup to be pushed after finishing the current
+ /// Queue a cleanup to be pushed after finishing the current
/// full-expression.
template <class T, class... As>
void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) {
- assert(!isInConditionalBranch() && "can't defer conditional cleanup");
+ if (!isInConditionalBranch())
+ return pushCleanupAfterFullExprImpl<T>(Kind, Address::invalid(), A...);
+
+ Address ActiveFlag = createCleanupActiveFlag();
+ assert(!DominatingValue<Address>::needsSaving(ActiveFlag) &&
+ "cleanup active flag should never need saving");
- LifetimeExtendedCleanupHeader Header = { sizeof(T), Kind };
+ typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple;
+ SavedTuple Saved{saveValueInCond(A)...};
+
+ typedef EHScopeStack::ConditionalCleanup<T, As...> CleanupType;
+ pushCleanupAfterFullExprImpl<CleanupType>(Kind, ActiveFlag, Saved);
+ }
+
+ template <class T, class... As>
+ void pushCleanupAfterFullExprImpl(CleanupKind Kind, Address ActiveFlag,
+ As... A) {
+ LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind,
+ ActiveFlag.isValid()};
size_t OldSize = LifetimeExtendedCleanupStack.size();
LifetimeExtendedCleanupStack.resize(
- LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size);
+ LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size +
+ (Header.IsConditional ? sizeof(ActiveFlag) : 0));
static_assert(sizeof(Header) % alignof(T) == 0,
"Cleanup will be allocated on misaligned address");
char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
new (Buffer) LifetimeExtendedCleanupHeader(Header);
new (Buffer + sizeof(Header)) T(A...);
+ if (Header.IsConditional)
+ new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag);
}
- /// Set up the last cleaup that was pushed as a conditional
+ /// Set up the last cleanup that was pushed as a conditional
/// full-expression cleanup.
- void initFullExprCleanup();
+ void initFullExprCleanup() {
+ initFullExprCleanupWithFlag(createCleanupActiveFlag());
+ }
+
+ void initFullExprCleanupWithFlag(Address ActiveFlag);
+ Address createCleanupActiveFlag();
/// PushDestructorCleanup - Push a cleanup to call the
/// complete-object destructor of an object of the given type at the
@@ -584,10 +694,10 @@ public:
void ActivateCleanupBlock(EHScopeStack::stable_iterator Cleanup,
llvm::Instruction *DominatingIP);
- /// \brief Enters a new scope for capturing cleanups, all of which
+ /// Enters a new scope for capturing cleanups, all of which
/// will be executed once the scope is exited.
class RunCleanupsScope {
- EHScopeStack::stable_iterator CleanupStackDepth;
+ EHScopeStack::stable_iterator CleanupStackDepth, OldCleanupScopeDepth;
size_t LifetimeExtendedCleanupStackSize;
bool OldDidCallStackSave;
protected:
@@ -601,7 +711,7 @@ public:
CodeGenFunction& CGF;
public:
- /// \brief Enter a new cleanup scope.
+ /// Enter a new cleanup scope.
explicit RunCleanupsScope(CodeGenFunction &CGF)
: PerformCleanup(true), CGF(CGF)
{
@@ -610,20 +720,22 @@ public:
CGF.LifetimeExtendedCleanupStack.size();
OldDidCallStackSave = CGF.DidCallStackSave;
CGF.DidCallStackSave = false;
+ OldCleanupScopeDepth = CGF.CurrentCleanupScopeDepth;
+ CGF.CurrentCleanupScopeDepth = CleanupStackDepth;
}
- /// \brief Exit this cleanup scope, emitting any accumulated cleanups.
+ /// Exit this cleanup scope, emitting any accumulated cleanups.
~RunCleanupsScope() {
if (PerformCleanup)
ForceCleanup();
}
- /// \brief Determine whether this scope requires any cleanups.
+ /// Determine whether this scope requires any cleanups.
bool requiresCleanups() const {
return CGF.EHStack.stable_begin() != CleanupStackDepth;
}
- /// \brief Force the emission of cleanups now, instead of waiting
+ /// Force the emission of cleanups now, instead of waiting
/// until this object is destroyed.
/// \param ValuesToReload - A list of values that need to be available at
/// the insertion point after cleanup emission. If cleanup emission created
@@ -635,9 +747,14 @@ public:
CGF.PopCleanupBlocks(CleanupStackDepth, LifetimeExtendedCleanupStackSize,
ValuesToReload);
PerformCleanup = false;
+ CGF.CurrentCleanupScopeDepth = OldCleanupScopeDepth;
}
};
+ // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
+ EHScopeStack::stable_iterator CurrentCleanupScopeDepth =
+ EHScopeStack::stable_end();
+
class LexicalScope : public RunCleanupsScope {
SourceRange Range;
SmallVector<const LabelDecl*, 4> Labels;
@@ -647,7 +764,7 @@ public:
void operator=(const LexicalScope &) = delete;
public:
- /// \brief Enter a new cleanup scope.
+ /// Enter a new cleanup scope.
explicit LexicalScope(CodeGenFunction &CGF, SourceRange Range)
: RunCleanupsScope(CGF), Range(Range), ParentScope(CGF.CurLexicalScope) {
CGF.CurLexicalScope = this;
@@ -660,7 +777,7 @@ public:
Labels.push_back(label);
}
- /// \brief Exit this cleanup scope, emitting any accumulated
+ /// Exit this cleanup scope, emitting any accumulated
/// cleanups.
~LexicalScope() {
if (CGDebugInfo *DI = CGF.getDebugInfo())
@@ -674,7 +791,7 @@ public:
}
}
- /// \brief Force the emission of cleanups now, instead of waiting
+ /// Force the emission of cleanups now, instead of waiting
/// until this object is destroyed.
void ForceCleanup() {
CGF.CurLexicalScope = ParentScope;
@@ -693,57 +810,107 @@ public:
typedef llvm::DenseMap<const Decl *, Address> DeclMapTy;
- /// \brief The scope used to remap some variables as private in the OpenMP
- /// loop body (or other captured region emitted without outlining), and to
- /// restore old vars back on exit.
- class OMPPrivateScope : public RunCleanupsScope {
+ /// The class used to assign some variables some temporarily addresses.
+ class OMPMapVars {
DeclMapTy SavedLocals;
- DeclMapTy SavedPrivates;
-
- private:
- OMPPrivateScope(const OMPPrivateScope &) = delete;
- void operator=(const OMPPrivateScope &) = delete;
+ DeclMapTy SavedTempAddresses;
+ OMPMapVars(const OMPMapVars &) = delete;
+ void operator=(const OMPMapVars &) = delete;
public:
- /// \brief Enter a new OpenMP private scope.
- explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {}
-
- /// \brief Registers \a LocalVD variable as a private and apply \a
- /// PrivateGen function for it to generate corresponding private variable.
- /// \a PrivateGen returns an address of the generated private variable.
- /// \return true if the variable is registered as private, false if it has
- /// been privatized already.
- bool
- addPrivate(const VarDecl *LocalVD,
- llvm::function_ref<Address()> PrivateGen) {
- assert(PerformCleanup && "adding private to dead scope");
+ explicit OMPMapVars() = default;
+ ~OMPMapVars() {
+ assert(SavedLocals.empty() && "Did not restored original addresses.");
+ };
+ /// Sets the address of the variable \p LocalVD to be \p TempAddr in
+ /// function \p CGF.
+ /// \return true if at least one variable was set already, false otherwise.
+ bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD,
+ Address TempAddr) {
LocalVD = LocalVD->getCanonicalDecl();
// Only save it once.
if (SavedLocals.count(LocalVD)) return false;
// Copy the existing local entry to SavedLocals.
auto it = CGF.LocalDeclMap.find(LocalVD);
- if (it != CGF.LocalDeclMap.end()) {
- SavedLocals.insert({LocalVD, it->second});
- } else {
- SavedLocals.insert({LocalVD, Address::invalid()});
- }
+ if (it != CGF.LocalDeclMap.end())
+ SavedLocals.try_emplace(LocalVD, it->second);
+ else
+ SavedLocals.try_emplace(LocalVD, Address::invalid());
// Generate the private entry.
- Address Addr = PrivateGen();
QualType VarTy = LocalVD->getType();
if (VarTy->isReferenceType()) {
Address Temp = CGF.CreateMemTemp(VarTy);
- CGF.Builder.CreateStore(Addr.getPointer(), Temp);
- Addr = Temp;
+ CGF.Builder.CreateStore(TempAddr.getPointer(), Temp);
+ TempAddr = Temp;
}
- SavedPrivates.insert({LocalVD, Addr});
+ SavedTempAddresses.try_emplace(LocalVD, TempAddr);
return true;
}
- /// \brief Privatizes local variables previously registered as private.
+ /// Applies new addresses to the list of the variables.
+ /// \return true if at least one variable is using new address, false
+ /// otherwise.
+ bool apply(CodeGenFunction &CGF) {
+ copyInto(SavedTempAddresses, CGF.LocalDeclMap);
+ SavedTempAddresses.clear();
+ return !SavedLocals.empty();
+ }
+
+ /// Restores original addresses of the variables.
+ void restore(CodeGenFunction &CGF) {
+ if (!SavedLocals.empty()) {
+ copyInto(SavedLocals, CGF.LocalDeclMap);
+ SavedLocals.clear();
+ }
+ }
+
+ private:
+ /// Copy all the entries in the source map over the corresponding
+ /// entries in the destination, which must exist.
+ static void copyInto(const DeclMapTy &Src, DeclMapTy &Dest) {
+ for (auto &Pair : Src) {
+ if (!Pair.second.isValid()) {
+ Dest.erase(Pair.first);
+ continue;
+ }
+
+ auto I = Dest.find(Pair.first);
+ if (I != Dest.end())
+ I->second = Pair.second;
+ else
+ Dest.insert(Pair);
+ }
+ }
+ };
+
+ /// The scope used to remap some variables as private in the OpenMP loop body
+ /// (or other captured region emitted without outlining), and to restore old
+ /// vars back on exit.
+ class OMPPrivateScope : public RunCleanupsScope {
+ OMPMapVars MappedVars;
+ OMPPrivateScope(const OMPPrivateScope &) = delete;
+ void operator=(const OMPPrivateScope &) = delete;
+
+ public:
+ /// Enter a new OpenMP private scope.
+ explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {}
+
+ /// Registers \p LocalVD variable as a private and apply \p PrivateGen
+ /// function for it to generate corresponding private variable. \p
+ /// PrivateGen returns an address of the generated private variable.
+ /// \return true if the variable is registered as private, false if it has
+ /// been privatized already.
+ bool addPrivate(const VarDecl *LocalVD,
+ const llvm::function_ref<Address()> PrivateGen) {
+ assert(PerformCleanup && "adding private to dead scope");
+ return MappedVars.setVarAddr(CGF, LocalVD, PrivateGen());
+ }
+
+ /// Privatizes local variables previously registered as private.
/// Registration is separate from the actual privatization to allow
/// initializers use values of the original variables, not the private one.
/// This is important, for example, if the private variable is a class
@@ -751,19 +918,14 @@ public:
/// variables. But at initialization original variables must be used, not
/// private copies.
/// \return true if at least one variable was privatized, false otherwise.
- bool Privatize() {
- copyInto(SavedPrivates, CGF.LocalDeclMap);
- SavedPrivates.clear();
- return !SavedLocals.empty();
- }
+ bool Privatize() { return MappedVars.apply(CGF); }
void ForceCleanup() {
RunCleanupsScope::ForceCleanup();
- copyInto(SavedLocals, CGF.LocalDeclMap);
- SavedLocals.clear();
+ MappedVars.restore(CGF);
}
- /// \brief Exit scope - all the mapped variables are restored.
+ /// Exit scope - all the mapped variables are restored.
~OMPPrivateScope() {
if (PerformCleanup)
ForceCleanup();
@@ -774,34 +936,15 @@ public:
VD = VD->getCanonicalDecl();
return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0;
}
-
- private:
- /// Copy all the entries in the source map over the corresponding
- /// entries in the destination, which must exist.
- static void copyInto(const DeclMapTy &src, DeclMapTy &dest) {
- for (auto &pair : src) {
- if (!pair.second.isValid()) {
- dest.erase(pair.first);
- continue;
- }
-
- auto it = dest.find(pair.first);
- if (it != dest.end()) {
- it->second = pair.second;
- } else {
- dest.insert(pair);
- }
- }
- }
};
- /// \brief Takes the old cleanup stack size and emits the cleanup blocks
+ /// Takes the old cleanup stack size and emits the cleanup blocks
/// that have been added.
void
PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize,
std::initializer_list<llvm::Value **> ValuesToReload = {});
- /// \brief Takes the old cleanup stack size and emits the cleanup blocks
+ /// Takes the old cleanup stack size and emits the cleanup blocks
/// that have been added, then adds all lifetime-extended cleanups from
/// the given position to the stack.
void
@@ -844,7 +987,8 @@ public:
llvm::BasicBlock *getEHResumeBlock(bool isCleanup);
llvm::BasicBlock *getEHDispatchBlock(EHScopeStack::stable_iterator scope);
- llvm::BasicBlock *getMSVCDispatchBlock(EHScopeStack::stable_iterator scope);
+ llvm::BasicBlock *
+ getFuncletEHDispatchBlock(EHScopeStack::stable_iterator scope);
/// An object to manage conditionally-evaluated expressions.
class ConditionalEvaluation {
@@ -1053,22 +1197,27 @@ public:
private:
CGDebugInfo *DebugInfo;
- bool DisableDebugInfo;
+ bool DisableDebugInfo = false;
/// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid
/// calling llvm.stacksave for multiple VLAs in the same scope.
- bool DidCallStackSave;
+ bool DidCallStackSave = false;
/// IndirectBranch - The first time an indirect goto is seen we create a block
/// with an indirect branch. Every time we see the address of a label taken,
/// we add the label to the indirect goto. Every subsequent indirect goto is
/// codegen'd as a jump to the IndirectBranch's basic block.
- llvm::IndirectBrInst *IndirectBranch;
+ llvm::IndirectBrInst *IndirectBranch = nullptr;
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
DeclMapTy LocalDeclMap;
+ // Keep track of the cleanups for callee-destructed parameters pushed to the
+ // cleanup stack so that they can be deactivated later.
+ llvm::DenseMap<const ParmVarDecl *, EHScopeStack::stable_iterator>
+ CalleeDestructedParamCleanups;
+
/// SizeArguments - If a ParmVarDecl had the pass_object_size attribute, this
/// will contain a mapping from said ParmVarDecl to its implicit "object_size"
/// parameter.
@@ -1120,7 +1269,7 @@ private:
/// Emits exit block with special codegen procedure specific for the related
/// OpenMP construct + emits code for normal construct cleanup.
void emitExit(CodeGenFunction &CGF, OpenMPDirectiveKind Kind,
- const llvm::function_ref<void(CodeGenFunction &)> &CodeGen) {
+ const llvm::function_ref<void(CodeGenFunction &)> CodeGen) {
if (Stack.back().Kind == Kind && getExitBlock().isValid()) {
assert(CGF.getOMPCancelDestination(Kind).isValid());
assert(CGF.HaveInsertPoint());
@@ -1208,13 +1357,13 @@ private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
/// current context is not in a switch.
- llvm::SwitchInst *SwitchInsn;
+ llvm::SwitchInst *SwitchInsn = nullptr;
/// The branch weights of SwitchInsn when doing instrumentation based PGO.
- SmallVector<uint64_t, 16> *SwitchWeights;
+ SmallVector<uint64_t, 16> *SwitchWeights = nullptr;
/// CaseRangeBlock - This block holds if condition check for last case
/// statement range in current switch instruction.
- llvm::BasicBlock *CaseRangeBlock;
+ llvm::BasicBlock *CaseRangeBlock = nullptr;
/// OpaqueLValues - Keeps track of the current set of opaque value
/// expressions.
@@ -1231,13 +1380,13 @@ private:
/// A block containing a single 'unreachable' instruction. Created
/// lazily by getUnreachableBlock().
- llvm::BasicBlock *UnreachableBlock;
+ llvm::BasicBlock *UnreachableBlock = nullptr;
/// Counts of the number return expressions in the function.
- unsigned NumReturnExprs;
+ unsigned NumReturnExprs = 0;
/// Count the number of simple (constant) return expressions in the function.
- unsigned NumSimpleReturnExprs;
+ unsigned NumSimpleReturnExprs = 0;
/// The last regular (non-return) debug location (breakpoint) in the function.
SourceLocation LastStopPoint;
@@ -1357,9 +1506,9 @@ public:
private:
/// CXXThisDecl - When generating code for a C++ member function,
/// this will hold the implicit 'this' declaration.
- ImplicitParamDecl *CXXABIThisDecl;
- llvm::Value *CXXABIThisValue;
- llvm::Value *CXXThisValue;
+ ImplicitParamDecl *CXXABIThisDecl = nullptr;
+ llvm::Value *CXXABIThisValue = nullptr;
+ llvm::Value *CXXThisValue = nullptr;
CharUnits CXXABIThisAlignment;
CharUnits CXXThisAlignment;
@@ -1377,16 +1526,16 @@ private:
/// CXXStructorImplicitParamDecl - When generating code for a constructor or
/// destructor, this will hold the implicit argument (e.g. VTT).
- ImplicitParamDecl *CXXStructorImplicitParamDecl;
- llvm::Value *CXXStructorImplicitParamValue;
+ ImplicitParamDecl *CXXStructorImplicitParamDecl = nullptr;
+ llvm::Value *CXXStructorImplicitParamValue = nullptr;
/// OutermostConditional - Points to the outermost active
/// conditional control. This is used so that we know if a
/// temporary should be destroyed conditionally.
- ConditionalEvaluation *OutermostConditional;
+ ConditionalEvaluation *OutermostConditional = nullptr;
/// The current lexical scope.
- LexicalScope *CurLexicalScope;
+ LexicalScope *CurLexicalScope = nullptr;
/// The current source location that should be used for exception
/// handling code.
@@ -1417,17 +1566,21 @@ private:
CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>());
}
- llvm::BasicBlock *TerminateLandingPad;
- llvm::BasicBlock *TerminateHandler;
- llvm::BasicBlock *TrapBB;
+ llvm::BasicBlock *TerminateLandingPad = nullptr;
+ llvm::BasicBlock *TerminateHandler = nullptr;
+ llvm::BasicBlock *TrapBB = nullptr;
/// Terminate funclets keyed by parent funclet pad.
llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets;
+ /// Largest vector width used in ths function. Will be used to create a
+ /// function attribute.
+ unsigned LargestVectorWidth = 0;
+
/// True if we need emit the life-time markers.
const bool ShouldEmitLifetimeMarkers;
- /// Add OpenCL kernel arg metadata and the kernel attribute meatadata to
+ /// Add OpenCL kernel arg metadata and the kernel attribute metadata to
/// the function metadata.
void EmitOpenCLKernelMetadata(const FunctionDecl *FD,
llvm::Function *Fn);
@@ -1536,6 +1689,7 @@ public:
return false;
case QualType::DK_cxx_destructor:
case QualType::DK_objc_weak_lifetime:
+ case QualType::DK_nontrivial_c_struct:
return getLangOpts().Exceptions;
case QualType::DK_objc_strong_lifetime:
return getLangOpts().Exceptions &&
@@ -1583,10 +1737,7 @@ public:
/// \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);
+ llvm::Value *EmitBlockLiteral(const BlockExpr *);
static void destroyBlockInfos(CGBlockInfo *info);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
@@ -1608,7 +1759,25 @@ public:
class AutoVarEmission;
void emitByrefStructureInit(const AutoVarEmission &emission);
- void enterByrefCleanup(const AutoVarEmission &emission);
+
+ /// Enter a cleanup to destroy a __block variable. Note that this
+ /// cleanup should be a no-op if the variable hasn't left the stack
+ /// yet; if a cleanup is required for the variable itself, that needs
+ /// to be done externally.
+ ///
+ /// \param Kind Cleanup kind.
+ ///
+ /// \param Addr When \p LoadBlockVarAddr is false, the address of the __block
+ /// structure that will be passed to _Block_object_dispose. When
+ /// \p LoadBlockVarAddr is true, the address of the field of the block
+ /// structure that holds the address of the __block structure.
+ ///
+ /// \param Flags The flag that will be passed to _Block_object_dispose.
+ ///
+ /// \param LoadBlockVarAddr Indicates whether we need to emit a load from
+ /// \p Addr to get the address of the __block structure.
+ void enterByrefCleanup(CleanupKind Kind, Address Addr, BlockFieldFlags Flags,
+ bool LoadBlockVarAddr);
void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum,
llvm::Value *ptr);
@@ -1631,7 +1800,7 @@ public:
void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo);
- /// \brief Emit code for the start of a function.
+ /// Emit code for the start of a function.
/// \param Loc The location to be associated with the function.
/// \param StartLoc The location of the function body.
void StartFunction(GlobalDecl GD,
@@ -1657,7 +1826,7 @@ public:
void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
void EmitAsanPrologueOrEpilogue(bool Prologue);
- /// \brief Emit the unified return block, trying to avoid its emission when
+ /// Emit the unified return block, trying to avoid its emission when
/// possible.
/// \return The debug location of the user written return statement if the
/// return block is is avoided.
@@ -1668,10 +1837,10 @@ public:
void FinishFunction(SourceLocation EndLoc=SourceLocation());
void StartThunk(llvm::Function *Fn, GlobalDecl GD,
- const CGFunctionInfo &FnInfo);
+ const CGFunctionInfo &FnInfo, bool IsUnprototyped);
- void EmitCallAndReturnForThunk(llvm::Constant *Callee,
- const ThunkInfo *Thunk);
+ void EmitCallAndReturnForThunk(llvm::Constant *Callee, const ThunkInfo *Thunk,
+ bool IsUnprototyped);
void FinishThunk();
@@ -1681,7 +1850,8 @@ public:
/// Generate a thunk for the given method.
void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
- GlobalDecl GD, const ThunkInfo &Thunk);
+ GlobalDecl GD, const ThunkInfo &Thunk,
+ bool IsUnprototyped);
llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
@@ -1692,7 +1862,7 @@ public:
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init);
- /// Struct with all informations about dynamic [sub]class needed to set vptr.
+ /// Struct with all information about dynamic [sub]class needed to set vptr.
struct VPtr {
BaseSubobject Base;
const CXXRecordDecl *NearestVBase;
@@ -1727,9 +1897,11 @@ public:
CFITCK_DerivedCast,
CFITCK_UnrelatedCast,
CFITCK_ICall,
+ CFITCK_NVMFCall,
+ CFITCK_VMFCall,
};
- /// \brief Derived is the presumed address of an object of type T after a
+ /// Derived is the presumed address of an object of type T after a
/// cast. If T is a polymorphic class type, emit a check that the virtual
/// table for Derived belongs to a class derived from T.
void EmitVTablePtrCheckForCast(QualType T, llvm::Value *Derived,
@@ -1779,6 +1951,10 @@ public:
/// XRay custom event handling calls.
bool AlwaysEmitXRayCustomEvents() const;
+ /// AlwaysEmitXRayTypedEvents - Return true if clang must unconditionally emit
+ /// XRay typed event handling calls.
+ bool AlwaysEmitXRayTypedEvents() const;
+
/// Encode an address into a form suitable for use in a function prologue.
llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F,
llvm::Constant *Addr);
@@ -1849,11 +2025,7 @@ public:
llvm::BasicBlock *createBasicBlock(const Twine &name = "",
llvm::Function *parent = nullptr,
llvm::BasicBlock *before = nullptr) {
-#ifdef NDEBUG
- return llvm::BasicBlock::Create(getLLVMContext(), "", parent, before);
-#else
return llvm::BasicBlock::Create(getLLVMContext(), name, parent, before);
-#endif
}
/// getBasicBlockForLabel - Return the LLVM basicblock that the specified
@@ -1983,15 +2155,20 @@ public:
/// to the stack.
///
/// Because the address of a temporary is often exposed to the program in
- /// various ways, this function will perform the cast by default. The cast
- /// may be avoided by passing false as \p CastToDefaultAddrSpace; this is
+ /// various ways, this function will perform the cast. The original alloca
+ /// instruction is returned through \p Alloca if it is not nullptr.
+ ///
+ /// The cast is not performaed in CreateTempAllocaWithoutCast. This is
/// more efficient if the caller knows that the address will not be exposed.
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp",
llvm::Value *ArraySize = nullptr);
Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
const Twine &Name = "tmp",
llvm::Value *ArraySize = nullptr,
- bool CastToDefaultAddrSpace = true);
+ Address *Alloca = nullptr);
+ Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align,
+ const Twine &Name = "tmp",
+ llvm::Value *ArraySize = nullptr);
/// CreateDefaultAlignedTempAlloca - This creates an alloca with the
/// default ABI alignment of the given LLVM type.
@@ -2026,12 +2203,18 @@ public:
Address CreateIRTemp(QualType T, const Twine &Name = "tmp");
/// CreateMemTemp - Create a temporary memory object of the given type, with
- /// appropriate alignment. Cast it to the default address space if
- /// \p CastToDefaultAddrSpace is true.
+ /// appropriate alignmen and cast it to the default address space. Returns
+ /// the original alloca instruction by \p Alloca if it is not nullptr.
Address CreateMemTemp(QualType T, const Twine &Name = "tmp",
- bool CastToDefaultAddrSpace = true);
+ Address *Alloca = nullptr);
Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp",
- bool CastToDefaultAddrSpace = true);
+ Address *Alloca = nullptr);
+
+ /// CreateMemTemp - Create a temporary memory object of the given type, with
+ /// appropriate alignmen without casting it to the default address space.
+ Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp");
+ Address CreateMemTempWithoutCast(QualType T, CharUnits Align,
+ const Twine &Name = "tmp");
/// CreateAggTemp - Create a temporary memory object for the given
/// aggregate type.
@@ -2040,7 +2223,8 @@ public:
T.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap);
}
/// Emit a cast to void* in the appropriate address space.
@@ -2097,31 +2281,52 @@ public:
}
return false;
}
- /// EmitAggregateCopy - Emit an aggregate assignment.
- ///
- /// The difference to EmitAggregateCopy is that tail padding is not copied.
- /// This is required for correctness when assigning non-POD structures in C++.
- void EmitAggregateAssign(Address DestPtr, Address SrcPtr,
- QualType EltTy) {
+
+ /// Determine whether a return value slot may overlap some other object.
+ AggValueSlot::Overlap_t overlapForReturnValue() {
+ // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
+ // class subobjects. These cases may need to be revisited depending on the
+ // resolution of the relevant core issue.
+ return AggValueSlot::DoesNotOverlap;
+ }
+
+ /// Determine whether a field initialization may overlap some other object.
+ AggValueSlot::Overlap_t overlapForFieldInit(const FieldDecl *FD) {
+ // FIXME: These cases can result in overlap as a result of P0840R0's
+ // [[no_unique_address]] attribute. We can still infer NoOverlap in the
+ // presence of that attribute if the field is within the nvsize of its
+ // containing class, because non-virtual subobjects are initialized in
+ // address order.
+ return AggValueSlot::DoesNotOverlap;
+ }
+
+ /// Determine whether a base class initialization may overlap some other
+ /// object.
+ AggValueSlot::Overlap_t overlapForBaseInit(const CXXRecordDecl *RD,
+ const CXXRecordDecl *BaseRD,
+ bool IsVirtual);
+
+ /// Emit an aggregate assignment.
+ void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy) {
bool IsVolatile = hasVolatileMember(EltTy);
- EmitAggregateCopy(DestPtr, SrcPtr, EltTy, IsVolatile, true);
+ EmitAggregateCopy(Dest, Src, EltTy, AggValueSlot::MayOverlap, IsVolatile);
}
- void EmitAggregateCopyCtor(Address DestPtr, Address SrcPtr,
- QualType DestTy, QualType SrcTy) {
- EmitAggregateCopy(DestPtr, SrcPtr, SrcTy, /*IsVolatile=*/false,
- /*IsAssignment=*/false);
+ void EmitAggregateCopyCtor(LValue Dest, LValue Src,
+ AggValueSlot::Overlap_t MayOverlap) {
+ EmitAggregateCopy(Dest, Src, Src.getType(), MayOverlap);
}
/// EmitAggregateCopy - Emit an aggregate copy.
///
- /// \param isVolatile - True iff either the source or the destination is
- /// volatile.
- /// \param isAssignment - If false, allow padding to be copied. This often
- /// yields more efficient.
- void EmitAggregateCopy(Address DestPtr, Address SrcPtr,
- QualType EltTy, bool isVolatile=false,
- bool isAssignment = false);
+ /// \param isVolatile \c true iff either the source or the destination is
+ /// volatile.
+ /// \param MayOverlap Whether the tail padding of the destination might be
+ /// occupied by some other object. More efficient code can often be
+ /// generated if not.
+ void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy,
+ AggValueSlot::Overlap_t MayOverlap,
+ bool isVolatile = false);
/// GetAddrOfLocalVar - Return the address of a local variable.
Address GetAddrOfLocalVar(const VarDecl *VD) {
@@ -2131,27 +2336,13 @@ public:
return it->second;
}
- /// getOpaqueLValueMapping - Given an opaque value expression (which
- /// must be mapped to an l-value), return its mapping.
- const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
- assert(OpaqueValueMapping::shouldBindAsLValue(e));
+ /// Given an opaque value expression, return its LValue mapping if it exists,
+ /// otherwise create one.
+ LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e);
- llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
- it = OpaqueLValues.find(e);
- assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
- return it->second;
- }
-
- /// getOpaqueRValueMapping - Given an opaque value expression (which
- /// must be mapped to an r-value), return its mapping.
- const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
- assert(!OpaqueValueMapping::shouldBindAsLValue(e));
-
- llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
- it = OpaqueRValues.find(e);
- assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
- return it->second;
- }
+ /// Given an opaque value expression, return its RValue mapping if it exists,
+ /// otherwise create one.
+ RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e);
/// Get the index of the current ArrayInitLoopExpr, if any.
llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }
@@ -2201,12 +2392,24 @@ public:
/// This function can be called with a null (unreachable) insert point.
void EmitVariablyModifiedType(QualType Ty);
- /// getVLASize - Returns an LLVM value that corresponds to the size,
+ struct VlaSizePair {
+ llvm::Value *NumElts;
+ QualType Type;
+
+ VlaSizePair(llvm::Value *NE, QualType T) : NumElts(NE), Type(T) {}
+ };
+
+ /// Return the number of elements for a single dimension
+ /// for the given array type.
+ VlaSizePair getVLAElements1D(const VariableArrayType *vla);
+ VlaSizePair getVLAElements1D(QualType vla);
+
+ /// Returns an LLVM value that corresponds to the size,
/// in non-variably-sized elements, of a variable length array type,
/// plus that largest non-variably-sized element type. Assumes that
/// the type has already been emitted with EmitVariablyModifiedType.
- std::pair<llvm::Value*,QualType> getVLASize(const VariableArrayType *vla);
- std::pair<llvm::Value*,QualType> getVLASize(QualType vla);
+ VlaSizePair getVLASize(const VariableArrayType *vla);
+ VlaSizePair getVLASize(QualType vla);
/// LoadCXXThis - Load the value of 'this'. This function is only valid while
/// generating code for an C++ member function.
@@ -2287,11 +2490,16 @@ public:
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating,
- Address This, const CXXConstructExpr *E);
+ Address This, const CXXConstructExpr *E,
+ AggValueSlot::Overlap_t Overlap,
+ bool NewPointerIsChecked);
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating,
- Address This, CallArgList &Args);
+ Address This, CallArgList &Args,
+ AggValueSlot::Overlap_t Overlap,
+ SourceLocation Loc,
+ bool NewPointerIsChecked);
/// Emit assumption load for all bases. Requires to be be called only on
/// most-derived class and not under construction of the object.
@@ -2308,12 +2516,14 @@ public:
const ArrayType *ArrayTy,
Address ArrayPtr,
const CXXConstructExpr *E,
+ bool NewPointerIsChecked,
bool ZeroInitialization = false);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *NumElements,
Address ArrayPtr,
const CXXConstructExpr *E,
+ bool NewPointerIsChecked,
bool ZeroInitialization = false);
static Destroyer destroyCXXObject;
@@ -2341,13 +2551,13 @@ public:
CharUnits CookieSize = CharUnits());
RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
- const Expr *Arg, bool IsDelete);
+ const CallExpr *TheCallExpr, bool IsDelete);
llvm::Value *EmitCXXTypeidExpr(const CXXTypeidExpr *E);
llvm::Value *EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE);
Address EmitCXXUuidofExpr(const CXXUuidofExpr *E);
- /// \brief Situations in which we might emit a check for the suitability of a
+ /// Situations in which we might emit a check for the suitability of a
/// pointer or glvalue.
enum TypeCheckKind {
/// Checking the operand of a load. Must be suitably sized and aligned.
@@ -2391,17 +2601,17 @@ public:
/// 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,
+ /// Whether any type-checking sanitizers are enabled. If \c false,
/// calls to EmitTypeCheck can be skipped.
bool sanitizePerformTypeCheck() const;
- /// \brief Emit a check that \p V is the address of storage of the
+ /// Emit a check that \p V is the address of storage of the
/// appropriate size and alignment for an object of type \p Type.
void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *V,
QualType Type, CharUnits Alignment = CharUnits::Zero(),
SanitizerSet SkippedChecks = SanitizerSet());
- /// \brief Emit a check that \p Base points into an array object, which
+ /// Emit a check that \p Base points into an array object, which
/// we can access at index \p Index. \p Accessed should be \c false if we
/// this expression is used as an lvalue, for instance in "&Arr[Idx]".
void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index,
@@ -2442,7 +2652,7 @@ public:
typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
llvm::Value *Address);
- /// \brief Determine whether the given initializer is trivial in the sense
+ /// Determine whether the given initializer is trivial in the sense
/// that it requires no code to be generated.
bool isTrivialInitializer(const Expr *Init);
@@ -2456,7 +2666,9 @@ public:
const VarDecl *Variable;
- /// The address of the alloca. Invalid if the variable was emitted
+ /// The address of the alloca for languages with explicit address space
+ /// (e.g. OpenCL) or alloca casted to generic pointer for address space
+ /// agnostic languages (e.g. C++). Invalid if the variable was emitted
/// as a global constant.
Address Addr;
@@ -2472,13 +2684,19 @@ public:
/// Non-null if we should use lifetime annotations.
llvm::Value *SizeForLifetimeMarkers;
+ /// Address with original alloca instruction. Invalid if the variable was
+ /// emitted as a global constant.
+ Address AllocaAddr;
+
struct Invalid {};
- AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
+ AutoVarEmission(Invalid)
+ : Variable(nullptr), Addr(Address::invalid()),
+ AllocaAddr(Address::invalid()) {}
AutoVarEmission(const VarDecl &variable)
- : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
- IsByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(nullptr) {}
+ : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
+ IsByRef(false), IsConstantAggregate(false),
+ SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
@@ -2494,11 +2712,15 @@ public:
}
/// Returns the raw, allocated address, which is not necessarily
- /// the address of the object itself.
+ /// the address of the object itself. It is casted to default
+ /// address space for address space agnostic languages.
Address getAllocatedAddress() const {
return Addr;
}
+ /// Returns the address for the original alloca instruction.
+ Address getOriginalAllocatedAddress() const { return AllocaAddr; }
+
/// Returns the address of the object within this declaration.
/// Note that this does not chase the forwarding pointer for
/// __block decls.
@@ -2514,6 +2736,15 @@ public:
void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
QualType::DestructionKind dtorKind);
+ /// Emits the alloca and debug information for the size expressions for each
+ /// dimension of an array. It registers the association of its (1-dimensional)
+ /// QualTypes and size expression's debug node, so that CGDebugInfo can
+ /// reference this node when creating the DISubrange object to describe the
+ /// array types.
+ void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI,
+ const VarDecl &D,
+ bool EmitDebugInfo);
+
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
@@ -2647,6 +2878,8 @@ public:
void EnterSEHTryStmt(const SEHTryStmt &S);
void ExitSEHTryStmt(const SEHTryStmt &S);
+ void pushSEHCleanup(CleanupKind kind,
+ llvm::Function *FinallyFunc);
void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
const Stmt *OutlinedStmt);
@@ -2708,7 +2941,7 @@ public:
SmallVectorImpl<llvm::Value *> &CapturedVars);
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy,
SourceLocation Loc);
- /// \brief Perform element by element copying of arrays with type \a
+ /// Perform element by element copying of arrays with type \a
/// OriginalType from \a SrcAddr to \a DestAddr using copying procedure
/// generated by \a CopyGen.
///
@@ -2719,8 +2952,8 @@ public:
/// to another single array element.
void EmitOMPAggregateAssign(
Address DestAddr, Address SrcAddr, QualType OriginalType,
- const llvm::function_ref<void(Address, Address)> &CopyGen);
- /// \brief Emit proper copying of data from one variable to another.
+ const llvm::function_ref<void(Address, Address)> CopyGen);
+ /// Emit proper copying of data from one variable to another.
///
/// \param OriginalType Original type of the copied variables.
/// \param DestAddr Destination address.
@@ -2735,7 +2968,7 @@ public:
Address DestAddr, Address SrcAddr,
const VarDecl *DestVD, const VarDecl *SrcVD,
const Expr *Copy);
- /// \brief Emit atomic update code for constructs: \a X = \a X \a BO \a E or
+ /// Emit atomic update code for constructs: \a X = \a X \a BO \a E or
/// \a X = \a E \a BO \a E.
///
/// \param X Value to be updated.
@@ -2751,7 +2984,7 @@ public:
std::pair<bool, RValue> EmitOMPAtomicSimpleUpdateExpr(
LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
llvm::AtomicOrdering AO, SourceLocation Loc,
- const llvm::function_ref<RValue(RValue)> &CommonGen);
+ const llvm::function_ref<RValue(RValue)> CommonGen);
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
void EmitOMPPrivateClause(const OMPExecutableDirective &D,
@@ -2759,7 +2992,7 @@ public:
void EmitOMPUseDevicePtrClause(
const OMPClause &C, OMPPrivateScope &PrivateScope,
const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap);
- /// \brief Emit code for copyin clause in \a D directive. The next code is
+ /// Emit code for copyin clause in \a D directive. The next code is
/// generated at the start of outlined functions for directives:
/// \code
/// threadprivate_var1 = master_threadprivate_var1;
@@ -2771,7 +3004,7 @@ public:
/// \param D OpenMP directive possibly with 'copyin' clause(s).
/// \returns true if at least one copyin variable is found, false otherwise.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D);
- /// \brief Emit initial code for lastprivate variables. If some variable is
+ /// Emit initial code for lastprivate variables. If some variable is
/// not also firstprivate, then the default initialization is used. Otherwise
/// initialization of this variable is performed by EmitOMPFirstprivateClause
/// method.
@@ -2784,7 +3017,7 @@ public:
/// otherwise.
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
- /// \brief Emit final copying of lastprivate values to original variables at
+ /// Emit final copying of lastprivate values to original variables at
/// the end of the worksharing or simd directive.
///
/// \param D Directive that has at least one 'lastprivate' directives.
@@ -2802,8 +3035,8 @@ public:
/// linear clause.
void EmitOMPLinearClauseFinal(
const OMPLoopDirective &D,
- const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen);
- /// \brief Emit initial code for reduction variables. Creates reduction copies
+ const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen);
+ /// Emit initial code for reduction variables. Creates reduction copies
/// and initializes them with the values according to OpenMP standard.
///
/// \param D Directive (possibly) with the 'reduction' clause.
@@ -2812,14 +3045,14 @@ public:
///
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
- /// \brief Emit final update of reduction values to original variables at
+ /// Emit final update of reduction values to original variables at
/// the end of the directive.
///
/// \param D Directive that has at least one 'reduction' directives.
/// \param ReductionKind The kind of reduction to perform.
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D,
const OpenMPDirectiveKind ReductionKind);
- /// \brief Emit initial code for linear variables. Creates private copies
+ /// Emit initial code for linear variables. Creates private copies
/// and initializes them with the values according to OpenMP standard.
///
/// \param D Directive (possibly) with the 'linear' clause.
@@ -2832,6 +3065,7 @@ public:
const OMPTaskDataTy & /*Data*/)>
TaskGenTy;
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
+ const OpenMPDirectiveKind CapturedRegion,
const RegionCodeGenTy &BodyGen,
const TaskGenTy &TaskGen, OMPTaskDataTy &Data);
struct OMPTargetDataInfo {
@@ -2941,7 +3175,16 @@ public:
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM,
StringRef ParentName,
const OMPTargetSimdDirective &S);
- /// \brief Emit inner loop of the worksharing/simd construct.
+ /// Emit device code for the target teams distribute parallel for simd
+ /// directive.
+ static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeParallelForSimdDirective &S);
+
+ static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeParallelForDirective &S);
+ /// Emit inner loop of the worksharing/simd construct.
///
/// \param S Directive, for which the inner loop must be emitted.
/// \param RequiresCleanup true, if directive has some associated private
@@ -2954,8 +3197,8 @@ public:
void EmitOMPInnerLoop(
const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
const Expr *IncExpr,
- const llvm::function_ref<void(CodeGenFunction &)> &BodyGen,
- const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen);
+ const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
+ const llvm::function_ref<void(CodeGenFunction &)> PostIncGen);
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind);
/// Emit initial code for loop counters of loop-based directives.
@@ -2965,7 +3208,7 @@ public:
/// Helper for the OpenMP loop directives.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);
- /// \brief Emit code for the worksharing loop-based directive.
+ /// Emit code for the worksharing loop-based directive.
/// \return true, if this construct has any lastprivate clause, false -
/// otherwise.
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB,
@@ -2980,17 +3223,14 @@ public:
void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);
void EmitOMPSimdFinal(
const OMPLoopDirective &D,
- const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen);
+ const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen);
/// 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);
+ /// Helpers for blocks.
+ llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
/// struct with the values to be passed to the OpenMP loop-related functions
struct OMPLoopArguments {
@@ -3041,7 +3281,7 @@ private:
OMPPrivateScope &LoopScope,
const OMPLoopArguments &LoopArgs,
const CodeGenLoopTy &CodeGenLoopContent);
- /// \brief Emit code for sections directive.
+ /// Emit code for sections directive.
void EmitSections(const OMPExecutableDirective &S);
public:
@@ -3082,7 +3322,7 @@ public:
///
LValue EmitLValue(const Expr *E);
- /// \brief Same as EmitLValue but additionally we generate checking code to
+ /// Same as EmitLValue but additionally we generate checking code to
/// guard against undefined behavior. This is only suitable when we know
/// that the address will be used to access the object.
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK);
@@ -3343,6 +3583,9 @@ public:
ArrayRef<llvm::Value*> args,
const Twine &name = "");
+ SmallVector<llvm::OperandBundleDef, 1>
+ getBundlesForFunclet(llvm::Value *Callee);
+
llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee,
ArrayRef<llvm::Value *> Args,
const Twine &Name = "");
@@ -3362,6 +3605,16 @@ public:
CXXDtorType Type,
const CXXRecordDecl *RD);
+ // These functions emit calls to the special functions of non-trivial C
+ // structs.
+ void defaultInitNonTrivialCStructVar(LValue Dst);
+ void callCStructDefaultConstructor(LValue Dst);
+ void callCStructDestructor(LValue Dst);
+ void callCStructCopyConstructor(LValue Dst, LValue Src);
+ void callCStructMoveConstructor(LValue Dst, LValue Src);
+ void callCStructCopyAssignmentOperator(LValue Dst, LValue Src);
+ void callCStructMoveAssignmentOperator(LValue Dst, LValue Src);
+
RValue
EmitCXXMemberOrOperatorCall(const CXXMethodDecl *Method,
const CGCallee &Callee,
@@ -3435,6 +3688,10 @@ public:
SmallVectorImpl<llvm::Value *> &Ops,
Address PtrOp0, Address PtrOp1,
llvm::Triple::ArchType Arch);
+
+ llvm::Value *EmitISOVolatileLoad(const CallExpr *E);
+ llvm::Value *EmitISOVolatileStore(const CallExpr *E);
+
llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
unsigned Modifier, llvm::Type *ArgTy,
const CallExpr *E);
@@ -3493,6 +3750,8 @@ public:
llvm::Value *EmitARCLoadWeak(Address addr);
llvm::Value *EmitARCLoadWeakRetained(Address addr);
llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool ignored);
+ void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr);
+ void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr);
void EmitARCCopyWeak(Address dst, Address src);
void EmitARCMoveWeak(Address dst, Address src);
llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);
@@ -3536,6 +3795,7 @@ public:
static Destroyer destroyARCStrongPrecise;
static Destroyer destroyARCWeak;
static Destroyer emitARCIntrinsicUse;
+ static Destroyer destroyNonTrivialCStruct;
void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr);
llvm::Value *EmitObjCAutoreleasePoolPush();
@@ -3543,7 +3803,7 @@ public:
void EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr);
void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr);
- /// \brief Emits a reference binding to the passed in expression.
+ /// Emits a reference binding to the passed in expression.
RValue EmitReferenceBindingToExpr(const Expr *E);
//===--------------------------------------------------------------------===//
@@ -3621,6 +3881,9 @@ public:
void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::Constant *fn,
llvm::Constant *addr);
+ /// Call atexit() with function dtorStub.
+ void registerGlobalDtorWithAtExit(llvm::Constant *dtorStub);
+
/// Emit code in this function to perform a guarded variable
/// initialization. Guarded initializations are used when it's not
/// possible to prove that an initialization will be done exactly
@@ -3757,26 +4020,26 @@ public:
/// 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
+ /// Emit a description of a type in a format suitable for passing to
/// a runtime sanitizer handler.
llvm::Constant *EmitCheckTypeDescriptor(QualType T);
- /// \brief Convert a value into a format suitable for passing to a runtime
+ /// Convert a value into a format suitable for passing to a runtime
/// sanitizer handler.
llvm::Value *EmitCheckValue(llvm::Value *V);
- /// \brief Emit a description of a source location in a format suitable for
+ /// Emit a description of a source location in a format suitable for
/// passing to a runtime sanitizer handler.
llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc);
- /// \brief Create a basic block that will call a handler function in a
+ /// Create a basic block that will call a handler function in a
/// sanitizer runtime with the provided arguments, and create a conditional
/// branch to it.
void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked,
SanitizerHandler Check, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs);
- /// \brief Emit a slow path cross-DSO CFI check which calls __cfi_slowpath
+ /// Emit a slow path cross-DSO CFI check which calls __cfi_slowpath
/// if Cond if false.
void EmitCfiSlowPathCheck(SanitizerMask Kind, llvm::Value *Cond,
llvm::ConstantInt *TypeId, llvm::Value *Ptr,
@@ -3786,21 +4049,21 @@ public:
/// checking is enabled. Otherwise, just emit an unreachable instruction.
void EmitUnreachable(SourceLocation Loc);
- /// \brief Create a basic block that will call the trap intrinsic, and emit a
+ /// Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
void EmitTrapCheck(llvm::Value *Checked);
- /// \brief Emit a call to trap or debugtrap and attach function attribute
+ /// Emit a call to trap or debugtrap and attach function attribute
/// "trap-func-name" if specified.
llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
- /// \brief Emit a stub for the cross-DSO CFI check function.
+ /// Emit a stub for the cross-DSO CFI check function.
void EmitCfiCheckStub();
- /// \brief Emit a cross-DSO CFI failure handling function.
+ /// Emit a cross-DSO CFI failure handling function.
void EmitCfiCheckFail();
- /// \brief Create a check for a function parameter that may potentially be
+ /// Create a check for a function parameter that may potentially be
/// declared as non-null.
void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc,
AbstractCallee AC, unsigned ParmNum);
@@ -3840,10 +4103,10 @@ private:
void ExpandTypeFromArgs(QualType Ty, LValue Dst,
SmallVectorImpl<llvm::Value *>::iterator &AI);
- /// ExpandTypeToArgs - Expand an RValue \arg RV, with the LLVM type for \arg
+ /// ExpandTypeToArgs - Expand an CallArg \arg Arg, with the LLVM type for \arg
/// Ty, into individual arguments on the provided vector \arg IRCallArgs,
/// starting at index \arg IRCallArgPos. See ABIArgInfo::Expand.
- void ExpandTypeToArgs(QualType Ty, RValue RV, llvm::FunctionType *IRFuncTy,
+ void ExpandTypeToArgs(QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy,
SmallVectorImpl<llvm::Value *> &IRCallArgs,
unsigned &IRCallArgPos);
@@ -3855,7 +4118,7 @@ private:
std::string &ConstraintStr,
SourceLocation Loc);
- /// \brief Attempts to statically evaluate the object size of E. If that
+ /// Attempts to statically evaluate the object size of E. If that
/// fails, emits code to figure the size of E out for us. This is
/// pass_object_size aware.
///
@@ -3864,7 +4127,7 @@ private:
llvm::IntegerType *ResType,
llvm::Value *EmittedE);
- /// \brief Emits the size of E, as required by __builtin_object_size. This
+ /// Emits the size of E, as required by __builtin_object_size. This
/// function is aware of pass_object_size parameters, and will act accordingly
/// if E is a parameter with the pass_object_size attribute.
llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type,
@@ -3984,6 +4247,48 @@ public:
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
+ struct TargetMultiVersionResolverOption {
+ llvm::Function *Function;
+ TargetAttr::ParsedTargetAttr ParsedAttribute;
+ unsigned Priority;
+ TargetMultiVersionResolverOption(
+ const TargetInfo &TargInfo, llvm::Function *F,
+ const clang::TargetAttr::ParsedTargetAttr &PT)
+ : Function(F), ParsedAttribute(PT), Priority(0u) {
+ for (StringRef Feat : PT.Features)
+ Priority = std::max(Priority,
+ TargInfo.multiVersionSortPriority(Feat.substr(1)));
+
+ if (!PT.Architecture.empty())
+ Priority = std::max(Priority,
+ TargInfo.multiVersionSortPriority(PT.Architecture));
+ }
+
+ bool operator>(const TargetMultiVersionResolverOption &Other) const {
+ return Priority > Other.Priority;
+ }
+ };
+ void EmitTargetMultiVersionResolver(
+ llvm::Function *Resolver,
+ ArrayRef<TargetMultiVersionResolverOption> Options);
+
+ struct CPUDispatchMultiVersionResolverOption {
+ llvm::Function *Function;
+ // Note: EmitX86CPUSupports only has 32 bits available, so we store the mask
+ // as 32 bits here. When 64-bit support is added to __builtin_cpu_supports,
+ // this can be extended to 64 bits.
+ uint32_t FeatureMask;
+ CPUDispatchMultiVersionResolverOption(llvm::Function *F, uint64_t Mask)
+ : Function(F), FeatureMask(static_cast<uint32_t>(Mask)) {}
+ bool operator>(const CPUDispatchMultiVersionResolverOption &Other) const {
+ return FeatureMask > Other.FeatureMask;
+ }
+ };
+ void EmitCPUDispatchMultiVersionResolver(
+ llvm::Function *Resolver,
+ ArrayRef<CPUDispatchMultiVersionResolverOption> Options);
+ static uint32_t GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
+
private:
QualType getVarArgType(const Expr *Arg);
@@ -3999,110 +4304,35 @@ private:
llvm::Value *EmitX86CpuIs(StringRef CPUStr);
llvm::Value *EmitX86CpuSupports(const CallExpr *E);
llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
+ llvm::Value *EmitX86CpuSupports(uint32_t Mask);
llvm::Value *EmitX86CpuInit();
+ llvm::Value *
+ FormResolverCondition(const TargetMultiVersionResolverOption &RO);
};
-/// Helper class with most of the code for saving a value for a
-/// conditional expression cleanup.
-struct DominatingLLVMValue {
- typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type;
-
- /// Answer whether the given value needs extra work to be saved.
- static bool needsSaving(llvm::Value *value) {
- // If it's not an instruction, we don't need to save.
- if (!isa<llvm::Instruction>(value)) return false;
-
- // If it's an instruction in the entry block, we don't need to save.
- llvm::BasicBlock *block = cast<llvm::Instruction>(value)->getParent();
- return (block != &block->getParent()->getEntryBlock());
- }
-
- /// Try to save the given value.
- static saved_type save(CodeGenFunction &CGF, llvm::Value *value) {
- if (!needsSaving(value)) return saved_type(value, false);
-
- // Otherwise, we need an alloca.
- auto align = CharUnits::fromQuantity(
- CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType()));
- Address alloca =
- CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save");
- CGF.Builder.CreateStore(value, alloca);
-
- return saved_type(alloca.getPointer(), true);
- }
-
- static llvm::Value *restore(CodeGenFunction &CGF, saved_type value) {
- // If the value says it wasn't saved, trust that it's still dominating.
- if (!value.getInt()) return value.getPointer();
-
- // Otherwise, it should be an alloca instruction, as set up in save().
- auto alloca = cast<llvm::AllocaInst>(value.getPointer());
- return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment());
- }
-};
-
-/// A partial specialization of DominatingValue for llvm::Values that
-/// might be llvm::Instructions.
-template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
- typedef T *type;
- static type restore(CodeGenFunction &CGF, saved_type value) {
- return static_cast<T*>(DominatingLLVMValue::restore(CGF, value));
- }
-};
+inline DominatingLLVMValue::saved_type
+DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
+ if (!needsSaving(value)) return saved_type(value, false);
-/// A specialization of DominatingValue for Address.
-template <> struct DominatingValue<Address> {
- typedef Address type;
+ // Otherwise, we need an alloca.
+ auto align = CharUnits::fromQuantity(
+ CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType()));
+ Address alloca =
+ CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save");
+ CGF.Builder.CreateStore(value, alloca);
- struct saved_type {
- DominatingLLVMValue::saved_type SavedValue;
- CharUnits Alignment;
- };
-
- static bool needsSaving(type value) {
- return DominatingLLVMValue::needsSaving(value.getPointer());
- }
- static saved_type save(CodeGenFunction &CGF, type value) {
- return { DominatingLLVMValue::save(CGF, value.getPointer()),
- value.getAlignment() };
- }
- static type restore(CodeGenFunction &CGF, saved_type value) {
- return Address(DominatingLLVMValue::restore(CGF, value.SavedValue),
- value.Alignment);
- }
-};
-
-/// A specialization of DominatingValue for RValue.
-template <> struct DominatingValue<RValue> {
- typedef RValue type;
- class saved_type {
- enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral,
- AggregateAddress, ComplexAddress };
-
- llvm::Value *Value;
- unsigned K : 3;
- unsigned Align : 29;
- saved_type(llvm::Value *v, Kind k, unsigned a = 0)
- : Value(v), K(k), Align(a) {}
-
- public:
- static bool needsSaving(RValue value);
- static saved_type save(CodeGenFunction &CGF, RValue value);
- RValue restore(CodeGenFunction &CGF);
+ return saved_type(alloca.getPointer(), true);
+}
- // implementations in CGCleanup.cpp
- };
+inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF,
+ saved_type value) {
+ // If the value says it wasn't saved, trust that it's still dominating.
+ if (!value.getInt()) return value.getPointer();
- static bool needsSaving(type value) {
- return saved_type::needsSaving(value);
- }
- static saved_type save(CodeGenFunction &CGF, type value) {
- return saved_type::save(CGF, value);
- }
- static type restore(CodeGenFunction &CGF, saved_type value) {
- return value.restore(CGF);
- }
-};
+ // Otherwise, it should be an alloca instruction, as set up in save().
+ auto alloca = cast<llvm::AllocaInst>(value.getPointer());
+ return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment());
+}
} // end namespace CodeGen
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
index 2172486682cf..8c5e0df0969b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -123,7 +123,6 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
- BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC();
if (LangOpts.ObjC1)
createObjCRuntime();
@@ -395,26 +394,29 @@ void CodeGenModule::Release() {
applyGlobalValReplacements();
applyReplacements();
checkAliases();
+ emitMultiVersionFunctions();
EmitCXXGlobalInitFunc();
EmitCXXGlobalDtorFunc();
+ registerGlobalDtorsWithAtExit();
EmitCXXThreadLocalInitFunc();
if (ObjCRuntime)
if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice &&
CUDARuntime) {
- if (llvm::Function *CudaCtorFunction = CUDARuntime->makeModuleCtorFunction())
+ if (llvm::Function *CudaCtorFunction =
+ CUDARuntime->makeModuleCtorFunction())
AddGlobalCtor(CudaCtorFunction);
- if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction())
- AddGlobalDtor(CudaDtorFunction);
}
- if (OpenMPRuntime)
+ if (OpenMPRuntime) {
if (llvm::Function *OpenMPRegistrationFunction =
OpenMPRuntime->emitRegistrationFunction()) {
auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ?
OpenMPRegistrationFunction : nullptr;
AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey);
}
+ OpenMPRuntime->clear();
+ }
if (PGOReader) {
getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext));
if (PGOStats.hasDiagnostics())
@@ -456,6 +458,10 @@ void CodeGenModule::Release() {
// Indicate that we want CodeView in the metadata.
getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1);
}
+ if (CodeGenOpts.ControlFlowGuard) {
+ // We want function ID tables for Control Flow Guard.
+ getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1);
+ }
if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) {
// We don't support LTO with 2 with different StrictVTablePointers
// FIXME: we could support it by stripping all the information introduced
@@ -501,12 +507,26 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1);
}
+ if (CodeGenOpts.CFProtectionReturn &&
+ Target.checkCFProtectionReturnSupported(getDiags())) {
+ // Indicate that we want to instrument return control flow protection.
+ getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return",
+ 1);
+ }
+
+ if (CodeGenOpts.CFProtectionBranch &&
+ Target.checkCFProtectionBranchSupported(getDiags())) {
+ // Indicate that we want to instrument branch control flow protection.
+ getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch",
+ 1);
+ }
+
if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) {
// Indicate whether __nvvm_reflect should be configured to flush denormal
// floating point values to 0. (This corresponds to its "__CUDA_FTZ"
// property.)
getModule().addModuleFlag(llvm::Module::Override, "nvvm-reflect-ftz",
- LangOpts.CUDADeviceFlushDenormalsToZero ? 1 : 0);
+ CodeGenOpts.FlushDenorm ? 1 : 0);
}
// Emit OpenCL specific module metadata: OpenCL/SPIR version.
@@ -536,6 +556,9 @@ void CodeGenModule::Release() {
getModule().setPIELevel(static_cast<llvm::PIELevel::Level>(PLevel));
}
+ if (CodeGenOpts.NoPLT)
+ getModule().setRtLibUseGOT();
+
SimplifyPersonality();
if (getCodeGenOpts().EmitDeclMetadata)
@@ -547,7 +570,8 @@ void CodeGenModule::Release() {
if (DebugInfo)
DebugInfo->finalize();
- EmitVersionIdentMetadata();
+ if (getCodeGenOpts().EmitVersionIdentMetadata)
+ EmitVersionIdentMetadata();
EmitTargetMetadata();
}
@@ -583,13 +607,9 @@ llvm::MDNode *CodeGenModule::getTBAATypeInfo(QualType QTy) {
}
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);
+ if (!TBAA)
+ return TBAAAccessInfo();
+ return TBAA->getAccessInfo(AccessType);
}
TBAAAccessInfo
@@ -632,6 +652,14 @@ CodeGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
return TBAA->mergeTBAAInfoForConditionalOperator(InfoA, InfoB);
}
+TBAAAccessInfo
+CodeGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo,
+ TBAAAccessInfo SrcInfo) {
+ if (!TBAA)
+ return TBAAAccessInfo();
+ return TBAA->mergeTBAAInfoForConditionalOperator(DestInfo, SrcInfo);
+}
+
void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst,
TBAAAccessInfo TBAAInfo) {
if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo))
@@ -673,21 +701,129 @@ llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
}
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
- const NamedDecl *D,
- ForDefinition_t IsForDefinition) const {
+ const NamedDecl *D) const {
+ if (GV->hasDLLImportStorageClass())
+ return;
// Internal definitions always have default visibility.
if (GV->hasLocalLinkage()) {
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
return;
}
-
+ if (!D)
+ return;
// Set visibility for definitions.
LinkageInfo LV = D->getLinkageAndVisibility();
- if (LV.isVisibilityExplicit() ||
- (IsForDefinition && !GV->hasAvailableExternallyLinkage()))
+ if (LV.isVisibilityExplicit() || !GV->isDeclarationForLinker())
GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));
}
+static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
+ llvm::GlobalValue *GV) {
+ if (GV->hasLocalLinkage())
+ return true;
+
+ if (!GV->hasDefaultVisibility() && !GV->hasExternalWeakLinkage())
+ return true;
+
+ // DLLImport explicitly marks the GV as external.
+ if (GV->hasDLLImportStorageClass())
+ return false;
+
+ const llvm::Triple &TT = CGM.getTriple();
+ // Every other GV is local on COFF.
+ // Make an exception for windows OS in the triple: Some firmware builds use
+ // *-win32-macho triples. This (accidentally?) produced windows relocations
+ // without GOT tables in older clang versions; Keep this behaviour.
+ // FIXME: even thread local variables?
+ if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO()))
+ return true;
+
+ // Only handle COFF and ELF for now.
+ if (!TT.isOSBinFormatELF())
+ return false;
+
+ // If this is not an executable, don't assume anything is local.
+ const auto &CGOpts = CGM.getCodeGenOpts();
+ llvm::Reloc::Model RM = CGOpts.RelocationModel;
+ const auto &LOpts = CGM.getLangOpts();
+ if (RM != llvm::Reloc::Static && !LOpts.PIE)
+ return false;
+
+ // A definition cannot be preempted from an executable.
+ if (!GV->isDeclarationForLinker())
+ return true;
+
+ // Most PIC code sequences that assume that a symbol is local cannot produce a
+ // 0 if it turns out the symbol is undefined. While this is ABI and relocation
+ // depended, it seems worth it to handle it here.
+ if (RM == llvm::Reloc::PIC_ && GV->hasExternalWeakLinkage())
+ return false;
+
+ // PPC has no copy relocations and cannot use a plt entry as a symbol address.
+ llvm::Triple::ArchType Arch = TT.getArch();
+ if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 ||
+ Arch == llvm::Triple::ppc64le)
+ return false;
+
+ // If we can use copy relocations we can assume it is local.
+ if (auto *Var = dyn_cast<llvm::GlobalVariable>(GV))
+ if (!Var->isThreadLocal() &&
+ (RM == llvm::Reloc::Static || CGOpts.PIECopyRelocations))
+ return true;
+
+ // If we can use a plt entry as the symbol address we can assume it
+ // is local.
+ // FIXME: This should work for PIE, but the gold linker doesn't support it.
+ if (isa<llvm::Function>(GV) && !CGOpts.NoPLT && RM == llvm::Reloc::Static)
+ return true;
+
+ // Otherwise don't assue it is local.
+ return false;
+}
+
+void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV) const {
+ GV->setDSOLocal(shouldAssumeDSOLocal(*this, GV));
+}
+
+void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
+ GlobalDecl GD) const {
+ const auto *D = dyn_cast<NamedDecl>(GD.getDecl());
+ // C++ destructors have a few C++ ABI specific special cases.
+ if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(D)) {
+ getCXXABI().setCXXDestructorDLLStorage(GV, Dtor, GD.getDtorType());
+ return;
+ }
+ setDLLImportDLLExport(GV, D);
+}
+
+void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
+ const NamedDecl *D) const {
+ if (D && D->isExternallyVisible()) {
+ if (D->hasAttr<DLLImportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
+ else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker())
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
+ }
+}
+
+void CodeGenModule::setGVProperties(llvm::GlobalValue *GV,
+ GlobalDecl GD) const {
+ setDLLImportDLLExport(GV, GD);
+ setGlobalVisibilityAndLocal(GV, dyn_cast<NamedDecl>(GD.getDecl()));
+}
+
+void CodeGenModule::setGVProperties(llvm::GlobalValue *GV,
+ const NamedDecl *D) const {
+ setDLLImportDLLExport(GV, D);
+ setGlobalVisibilityAndLocal(GV, D);
+}
+
+void CodeGenModule::setGlobalVisibilityAndLocal(llvm::GlobalValue *GV,
+ const NamedDecl *D) const {
+ setGlobalVisibility(GV, D);
+ setDSOLocal(GV);
+}
+
static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) {
return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S)
.Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel)
@@ -725,36 +861,68 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const {
GV->setThreadLocalMode(TLM);
}
-StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
- GlobalDecl CanonicalGD = GD.getCanonicalDecl();
+static std::string getCPUSpecificMangling(const CodeGenModule &CGM,
+ StringRef Name) {
+ const TargetInfo &Target = CGM.getTarget();
+ return (Twine('.') + Twine(Target.CPUSpecificManglingCharacter(Name))).str();
+}
- // Some ABIs don't have constructor variants. Make sure that base and
- // complete constructors get mangled the same.
- if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) {
- if (!getTarget().getCXXABI().hasConstructorVariants()) {
- CXXCtorType OrigCtorType = GD.getCtorType();
- assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete);
- if (OrigCtorType == Ctor_Base)
- CanonicalGD = GlobalDecl(CD, Ctor_Complete);
- }
+static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
+ const CPUSpecificAttr *Attr,
+ raw_ostream &Out) {
+ // cpu_specific gets the current name, dispatch gets the resolver.
+ if (Attr)
+ Out << getCPUSpecificMangling(CGM, Attr->getCurCPUName()->getName());
+ else
+ Out << ".resolver";
+}
+
+static void AppendTargetMangling(const CodeGenModule &CGM,
+ const TargetAttr *Attr, raw_ostream &Out) {
+ if (Attr->isDefaultVersion())
+ return;
+
+ Out << '.';
+ const TargetInfo &Target = CGM.getTarget();
+ TargetAttr::ParsedTargetAttr Info =
+ Attr->parse([&Target](StringRef LHS, StringRef RHS) {
+ // Multiversioning doesn't allow "no-${feature}", so we can
+ // only have "+" prefixes here.
+ assert(LHS.startswith("+") && RHS.startswith("+") &&
+ "Features should always have a prefix.");
+ return Target.multiVersionSortPriority(LHS.substr(1)) >
+ Target.multiVersionSortPriority(RHS.substr(1));
+ });
+
+ bool IsFirst = true;
+
+ if (!Info.Architecture.empty()) {
+ IsFirst = false;
+ Out << "arch_" << Info.Architecture;
}
- auto FoundName = MangledDeclNames.find(CanonicalGD);
- if (FoundName != MangledDeclNames.end())
- return FoundName->second;
+ for (StringRef Feat : Info.Features) {
+ if (!IsFirst)
+ Out << '_';
+ IsFirst = false;
+ Out << Feat.substr(1);
+ }
+}
- const auto *ND = cast<NamedDecl>(GD.getDecl());
+static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD,
+ const NamedDecl *ND,
+ bool OmitMultiVersionMangling = false) {
SmallString<256> Buffer;
- StringRef Str;
- if (getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
+ llvm::raw_svector_ostream Out(Buffer);
+ MangleContext &MC = CGM.getCXXABI().getMangleContext();
+ if (MC.shouldMangleDeclName(ND)) {
llvm::raw_svector_ostream Out(Buffer);
if (const auto *D = dyn_cast<CXXConstructorDecl>(ND))
- getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
+ MC.mangleCXXCtor(D, GD.getCtorType(), Out);
else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND))
- getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
+ MC.mangleCXXDtor(D, GD.getDtorType(), Out);
else
- getCXXABI().getMangleContext().mangleName(ND, Out);
- Str = Out.str();
+ MC.mangleName(ND, Out);
} else {
IdentifierInfo *II = ND->getIdentifier();
assert(II && "Attempt to mangle unnamed decl.");
@@ -764,14 +932,103 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
FD->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
llvm::raw_svector_ostream Out(Buffer);
Out << "__regcall3__" << II->getName();
- Str = Out.str();
} else {
- Str = II->getName();
+ Out << II->getName();
+ }
+ }
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
+ if (FD->isMultiVersion() && !OmitMultiVersionMangling) {
+ if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())
+ AppendCPUSpecificCPUDispatchMangling(
+ CGM, FD->getAttr<CPUSpecificAttr>(), Out);
+ else
+ AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
+ }
+
+ return Out.str();
+}
+
+void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
+ const FunctionDecl *FD) {
+ if (!FD->isMultiVersion())
+ return;
+
+ // Get the name of what this would be without the 'target' attribute. This
+ // allows us to lookup the version that was emitted when this wasn't a
+ // multiversion function.
+ std::string NonTargetName =
+ getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
+ GlobalDecl OtherGD;
+ if (lookupRepresentativeDecl(NonTargetName, OtherGD)) {
+ assert(OtherGD.getCanonicalDecl()
+ .getDecl()
+ ->getAsFunction()
+ ->isMultiVersion() &&
+ "Other GD should now be a multiversioned function");
+ // OtherFD is the version of this function that was mangled BEFORE
+ // becoming a MultiVersion function. It potentially needs to be updated.
+ const FunctionDecl *OtherFD =
+ OtherGD.getCanonicalDecl().getDecl()->getAsFunction();
+ std::string OtherName = getMangledNameImpl(*this, OtherGD, OtherFD);
+ // This is so that if the initial version was already the 'default'
+ // version, we don't try to update it.
+ if (OtherName != NonTargetName) {
+ // Remove instead of erase, since others may have stored the StringRef
+ // to this.
+ const auto ExistingRecord = Manglings.find(NonTargetName);
+ if (ExistingRecord != std::end(Manglings))
+ Manglings.remove(&(*ExistingRecord));
+ auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD));
+ MangledDeclNames[OtherGD.getCanonicalDecl()] = Result.first->first();
+ if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName))
+ Entry->setName(OtherName);
}
}
+}
+
+StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
+ GlobalDecl CanonicalGD = GD.getCanonicalDecl();
+
+ // Some ABIs don't have constructor variants. Make sure that base and
+ // complete constructors get mangled the same.
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) {
+ if (!getTarget().getCXXABI().hasConstructorVariants()) {
+ CXXCtorType OrigCtorType = GD.getCtorType();
+ assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete);
+ if (OrigCtorType == Ctor_Base)
+ CanonicalGD = GlobalDecl(CD, Ctor_Complete);
+ }
+ }
+
+ const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl());
+ // Since CPUSpecific can require multiple emits per decl, store the manglings
+ // separately.
+ if (FD &&
+ (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())) {
+ const auto *SD = FD->getAttr<CPUSpecificAttr>();
+
+ std::pair<GlobalDecl, unsigned> SpecCanonicalGD{
+ CanonicalGD,
+ SD ? SD->ActiveArgIndex : std::numeric_limits<unsigned>::max()};
+
+ auto FoundName = CPUSpecificMangledDeclNames.find(SpecCanonicalGD);
+ if (FoundName != CPUSpecificMangledDeclNames.end())
+ return FoundName->second;
+
+ auto Result = CPUSpecificManglings.insert(
+ std::make_pair(getMangledNameImpl(*this, GD, FD), SpecCanonicalGD));
+ return CPUSpecificMangledDeclNames[SpecCanonicalGD] = Result.first->first();
+ }
+
+ auto FoundName = MangledDeclNames.find(CanonicalGD);
+ if (FoundName != MangledDeclNames.end())
+ return FoundName->second;
// Keep the first result in the case of a mangling collision.
- auto Result = Manglings.insert(std::make_pair(Str, GD));
+ const auto *ND = cast<NamedDecl>(GD.getDecl());
+ auto Result =
+ Manglings.insert(std::make_pair(getMangledNameImpl(*this, GD, ND), GD));
return MangledDeclNames[CanonicalGD] = Result.first->first();
}
@@ -811,6 +1068,11 @@ void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority,
/// AddGlobalDtor - Add a function to the list that will be called
/// when the module is unloaded.
void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) {
+ if (CodeGenOpts.RegisterGlobalDtorsWithAtExit) {
+ DtorsUsingAtExit[Priority].push_back(Dtor);
+ return;
+ }
+
// FIXME: Type coercion of void()* types.
GlobalDtors.push_back(Structor(Priority, Dtor, nullptr));
}
@@ -858,14 +1120,8 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
- if (isa<CXXDestructorDecl>(D) &&
- getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
- GD.getDtorType())) {
- // Destructor variants in the Microsoft C++ ABI are always internal or
- // linkonce_odr thunks emitted on an as-needed basis.
- return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage
- : llvm::GlobalValue::LinkOnceODRLinkage;
- }
+ if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(D))
+ return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType());
if (isa<CXXConstructorDecl>(D) &&
cast<CXXConstructorDecl>(D)->isInheritingConstructor() &&
@@ -879,25 +1135,6 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false);
}
-void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F) {
- const auto *FD = cast<FunctionDecl>(GD.getDecl());
-
- if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(FD)) {
- if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
- // Don't dllexport/import destructor thunks.
- F->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
- return;
- }
- }
-
- if (FD->hasAttr<DLLImportAttr>())
- F->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- else if (FD->hasAttr<DLLExportAttr>())
- F->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
- else
- F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
-}
-
llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
if (!MDS) return nullptr;
@@ -905,11 +1142,6 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
}
-void CodeGenModule::setFunctionDefinitionAttributes(const FunctionDecl *D,
- llvm::Function *F) {
- setNonAliasAttributes(D, F);
-}
-
void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
const CGFunctionInfo &Info,
llvm::Function *F) {
@@ -940,6 +1172,34 @@ static bool hasUnwindExceptions(const LangOptions &LangOpts) {
return true;
}
+static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM,
+ const CXXMethodDecl *MD) {
+ // Check that the type metadata can ever actually be used by a call.
+ if (!CGM.getCodeGenOpts().LTOUnit ||
+ !CGM.HasHiddenLTOVisibility(MD->getParent()))
+ return false;
+
+ // Only functions whose address can be taken with a member function pointer
+ // need this sort of type metadata.
+ return !MD->isStatic() && !MD->isVirtual() && !isa<CXXConstructorDecl>(MD) &&
+ !isa<CXXDestructorDecl>(MD);
+}
+
+std::vector<const CXXRecordDecl *>
+CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) {
+ llvm::SetVector<const CXXRecordDecl *> MostBases;
+
+ std::function<void (const CXXRecordDecl *)> CollectMostBases;
+ CollectMostBases = [&](const CXXRecordDecl *RD) {
+ if (RD->getNumBases() == 0)
+ MostBases.insert(RD);
+ for (const CXXBaseSpecifier &B : RD->bases())
+ CollectMostBases(B.getType()->getAsCXXRecordDecl());
+ };
+ CollectMostBases(RD);
+ return MostBases.takeVector();
+}
+
void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
llvm::Function *F) {
llvm::AttrBuilder B;
@@ -950,12 +1210,14 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (!hasUnwindExceptions(LangOpts))
B.addAttribute(llvm::Attribute::NoUnwind);
- if (LangOpts.getStackProtector() == LangOptions::SSPOn)
- B.addAttribute(llvm::Attribute::StackProtect);
- else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
- B.addAttribute(llvm::Attribute::StackProtectStrong);
- else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
- B.addAttribute(llvm::Attribute::StackProtectReq);
+ if (!D || !D->hasAttr<NoStackProtectorAttr>()) {
+ if (LangOpts.getStackProtector() == LangOptions::SSPOn)
+ B.addAttribute(llvm::Attribute::StackProtect);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
+ B.addAttribute(llvm::Attribute::StackProtectStrong);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
+ B.addAttribute(llvm::Attribute::StackProtectReq);
+ }
if (!D) {
// If we don't have a declaration to control inlining, the function isn't
@@ -1047,6 +1309,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (alignment)
F->setAlignment(alignment);
+ if (!D->hasAttr<AlignedAttr>())
+ if (LangOpts.FunctionAlignment)
+ F->setAlignment(1 << LangOpts.FunctionAlignment);
+
// Some C++ ABIs require 2-byte alignment for member functions, in order to
// reserve a bit for differentiating between virtual and non-virtual member
// functions. If the current target's C++ ABI requires this and this is a
@@ -1059,13 +1325,26 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
// In the cross-dso CFI mode, we want !type attributes on definitions only.
if (CodeGenOpts.SanitizeCfiCrossDso)
if (auto *FD = dyn_cast<FunctionDecl>(D))
- CreateFunctionTypeMetadata(FD, F);
+ CreateFunctionTypeMetadataForIcall(FD, F);
+
+ // Emit type metadata on member functions for member function pointer checks.
+ // These are only ever necessary on definitions; we're guaranteed that the
+ // definition will be present in the LTO unit as a result of LTO visibility.
+ auto *MD = dyn_cast<CXXMethodDecl>(D);
+ if (MD && requiresMemberFunctionPointerTypeMetadata(*this, MD)) {
+ for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) {
+ llvm::Metadata *Id =
+ CreateMetadataIdentifierForType(Context.getMemberPointerType(
+ MD->getType(), Context.getRecordType(Base).getTypePtr()));
+ F->addTypeMetadata(0, Id);
+ }
+ }
}
-void CodeGenModule::SetCommonAttributes(const Decl *D,
- llvm::GlobalValue *GV) {
- if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
- setGlobalVisibility(GV, ND, ForDefinition);
+void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
+ const Decl *D = GD.getDecl();
+ if (dyn_cast_or_null<NamedDecl>(D))
+ setGVProperties(GV, GD);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -1073,19 +1352,59 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
addUsedGlobal(GV);
}
-void CodeGenModule::setAliasAttributes(const Decl *D,
- llvm::GlobalValue *GV) {
- SetCommonAttributes(D, GV);
+bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D,
+ llvm::AttrBuilder &Attrs) {
+ // Add target-cpu and target-features attributes to functions. If
+ // 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 auto *FD = dyn_cast_or_null<FunctionDecl>(D);
+ FD = FD ? FD->getMostRecentDecl() : FD;
+ const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr;
+ const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr;
+ bool AddedAttr = false;
+ if (TD || SD) {
+ llvm::StringMap<bool> FeatureMap;
+ getFunctionFeatureMap(FeatureMap, FD);
+
+ // Produce the canonical string for this set of features.
+ for (const llvm::StringMap<bool>::value_type &Entry : FeatureMap)
+ Features.push_back((Entry.getValue() ? "+" : "-") + Entry.getKey().str());
+
+ // Now add the target-cpu and target-features to the function.
+ // While we populated the feature map above, we still need to
+ // get and parse the target attribute so we can get the cpu for
+ // the function.
+ if (TD) {
+ TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
+ if (ParsedAttr.Architecture != "" &&
+ getTarget().isValidCPUName(ParsedAttr.Architecture))
+ TargetCPU = ParsedAttr.Architecture;
+ }
+ } else {
+ // Otherwise just add the existing target cpu and target features to the
+ // function.
+ Features = getTarget().getTargetOpts().Features;
+ }
+
+ if (TargetCPU != "") {
+ Attrs.addAttribute("target-cpu", TargetCPU);
+ AddedAttr = true;
+ }
+ if (!Features.empty()) {
+ llvm::sort(Features.begin(), Features.end());
+ Attrs.addAttribute("target-features", llvm::join(Features, ","));
+ AddedAttr = true;
+ }
- // Process the dllexport attribute based on whether the original definition
- // (not necessarily the aliasee) was exported.
- if (D->hasAttr<DLLExportAttr>())
- GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ return AddedAttr;
}
-void CodeGenModule::setNonAliasAttributes(const Decl *D,
+void CodeGenModule::setNonAliasAttributes(GlobalDecl GD,
llvm::GlobalObject *GO) {
- SetCommonAttributes(D, GO);
+ const Decl *D = GD.getDecl();
+ SetCommonAttributes(GD, GO);
if (D) {
if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) {
@@ -1099,55 +1418,60 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
if (auto *F = dyn_cast<llvm::Function>(GO)) {
if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>())
- if (!D->getAttr<SectionAttr>())
- F->addFnAttr("implicit-section-name", SA->getName());
+ if (!D->getAttr<SectionAttr>())
+ F->addFnAttr("implicit-section-name", SA->getName());
+
+ llvm::AttrBuilder Attrs;
+ if (GetCPUAndFeaturesAttributes(D, Attrs)) {
+ // We know that GetCPUAndFeaturesAttributes will always have the
+ // newest set, since it has the newest possible FunctionDecl, so the
+ // new ones should replace the old.
+ F->removeFnAttr("target-cpu");
+ F->removeFnAttr("target-features");
+ F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs);
+ }
}
- if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+ if (const auto *CSA = D->getAttr<CodeSegAttr>())
+ GO->setSection(CSA->getName());
+ else if (const auto *SA = D->getAttr<SectionAttr>())
GO->setSection(SA->getName());
}
- getTargetCodeGenInfo().setTargetAttributes(D, GO, *this, ForDefinition);
+ getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
}
-void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
+void CodeGenModule::SetInternalFunctionAttributes(GlobalDecl GD,
llvm::Function *F,
const CGFunctionInfo &FI) {
+ const Decl *D = GD.getDecl();
SetLLVMFunctionAttributes(D, FI, F);
SetLLVMFunctionAttributesForDefinition(D, F);
F->setLinkage(llvm::Function::InternalLinkage);
- setNonAliasAttributes(D, F);
+ setNonAliasAttributes(GD, F);
}
-static void setLinkageForGV(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())) {
- // Don't set internal linkage on declarations.
- } else {
- if (ND->hasAttr<DLLImportAttr>()) {
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- } else if (ND->hasAttr<DLLExportAttr>()) {
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else if (ND->hasAttr<WeakAttr>() || ND->isWeakImported()) {
- // "extern_weak" is overloaded in LLVM; we probably should have
- // separate linkage types for this.
- GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- }
- }
+ // Don't set internal linkage on declarations.
+ // "extern_weak" is overloaded in LLVM; we probably should have
+ // separate linkage types for this.
+ if (isExternallyVisible(LV.getLinkage()) &&
+ (ND->hasAttr<WeakAttr>() || ND->isWeakImported()))
+ GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
}
-void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
- llvm::Function *F) {
+void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
+ llvm::Function *F) {
// Only if we are checking indirect calls.
if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
return;
- // Non-static class methods are handled via vtable pointer checks elsewhere.
+ // Non-static class methods are handled via vtable or member function pointer
+ // checks elsewhere.
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
return;
@@ -1171,8 +1495,7 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
bool IsIncompleteFunction,
- bool IsThunk,
- ForDefinition_t IsForDefinition) {
+ bool IsThunk) {
if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) {
// If this is an intrinsic function, set the function's attributes
@@ -1186,9 +1509,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
if (!IsIncompleteFunction) {
SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
// Setup target-specific attributes.
- if (!IsForDefinition)
- getTargetCodeGenInfo().setTargetAttributes(FD, F, *this,
- NotForDefinition);
+ if (F->isDeclaration())
+ getTargetCodeGenInfo().setTargetAttributes(FD, F, *this);
}
// Add the Returned attribute for "this", except for iOS 5 and earlier
@@ -1207,14 +1529,12 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
// overridden by a definition.
setLinkageForGV(F, FD);
- setGlobalVisibility(F, FD, NotForDefinition);
-
- if (FD->getAttr<PragmaClangTextSectionAttr>()) {
- F->addFnAttr("implicit-section-name");
- }
+ setGVProperties(F, FD);
- if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
- F->setSection(SA->getName());
+ if (const auto *CSA = FD->getAttr<CodeSegAttr>())
+ F->setSection(CSA->getName());
+ else if (const auto *SA = FD->getAttr<SectionAttr>())
+ F->setSection(SA->getName());
if (FD->isReplaceableGlobalAllocationFunction()) {
// A replaceable global allocation function does not act like a builtin by
@@ -1241,7 +1561,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
// Don't emit entries for function declarations in the cross-DSO mode. This
// is handled with better precision by the receiving DSO.
if (!CodeGenOpts.SanitizeCfiCrossDso)
- CreateFunctionTypeMetadata(FD, F);
+ CreateFunctionTypeMetadataForIcall(FD, F);
if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
getOpenMPRuntime().emitDeclareSimdFunction(FD, F);
@@ -1302,6 +1622,12 @@ void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) {
LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
}
+void CodeGenModule::AddELFLibDirective(StringRef Lib) {
+ auto &C = getLLVMContext();
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(
+ C, {llvm::MDString::get(C, "lib"), llvm::MDString::get(C, Lib)}));
+}
+
void CodeGenModule::AddDependentLib(StringRef Lib) {
llvm::SmallString<24> Opt;
getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt);
@@ -1309,7 +1635,7 @@ void CodeGenModule::AddDependentLib(StringRef Lib) {
LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
}
-/// \brief Add link options implied by the given module, including modules
+/// Add link options implied by the given module, including modules
/// it depends on, using a postorder walk.
static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
SmallVectorImpl<llvm::MDNode *> &Metadata,
@@ -1328,6 +1654,12 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
// Add linker options to link against the libraries/frameworks
// described by this module.
llvm::LLVMContext &Context = CGM.getLLVMContext();
+
+ // For modules that use export_as for linking, use that module
+ // name instead.
+ if (Mod->UseExportAsModuleLinkName)
+ return;
+
for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) {
// Link against a framework. Frameworks are currently Darwin only, so we
// don't to ask TargetCodeGenInfo for the spelling of the linker option.
@@ -1589,7 +1921,8 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
StringRef Category) const {
// For now globals can be blacklisted only in ASan and KASan.
const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask &
- (SanitizerKind::Address | SanitizerKind::KernelAddress | SanitizerKind::HWAddress);
+ (SanitizerKind::Address | SanitizerKind::KernelAddress |
+ SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress);
if (!EnabledAsanMask)
return false;
const auto &SanitizerBL = getContext().getSanitizerBlacklist();
@@ -1618,9 +1951,10 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
StringRef Category) const {
if (!LangOpts.XRayInstrument)
return false;
+
const auto &XRayFilter = getContext().getXRayFilter();
using ImbueAttr = XRayFunctionFilter::ImbueAttribute;
- auto Attr = XRayFunctionFilter::ImbueAttribute::NONE;
+ auto Attr = ImbueAttr::NONE;
if (Loc.isValid())
Attr = XRayFilter.shouldImbueLocation(Loc, Category);
if (Attr == ImbueAttr::NONE)
@@ -1665,7 +1999,8 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// If OpenMP is enabled and threadprivates must be generated like TLS, delay
// codegen for global variables, because they may be marked as threadprivate.
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
- getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global))
+ getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) &&
+ !isTypeConstant(Global->getType(), false))
return false;
return true;
@@ -1694,6 +2029,7 @@ ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor(
/*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
if (supportsCOMDAT())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
+ setDSOLocal(GV);
return ConstantAddress(GV, Alignment);
}
@@ -1745,6 +2081,10 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
if (Global->hasAttr<IFuncAttr>())
return emitIFuncDefinition(GD);
+ // If this is a cpu_dispatch multiversion function, emit the resolver.
+ if (Global->hasAttr<CPUDispatchAttr>())
+ return emitCPUDispatchDefinition(GD);
+
// If this is CUDA, be selective about which declarations we emit.
if (LangOpts.CUDA) {
if (LangOpts.CUDAIsDevice) {
@@ -2061,6 +2401,124 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
llvm::Function *NewFn);
+void CodeGenModule::emitMultiVersionFunctions() {
+ for (GlobalDecl GD : MultiVersionFuncs) {
+ SmallVector<CodeGenFunction::TargetMultiVersionResolverOption, 10> Options;
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+ getContext().forEachMultiversionedFunctionVersion(
+ FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
+ GlobalDecl CurGD{
+ (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)};
+ StringRef MangledName = getMangledName(CurGD);
+ llvm::Constant *Func = GetGlobalValue(MangledName);
+ if (!Func) {
+ if (CurFD->isDefined()) {
+ EmitGlobalFunctionDefinition(CurGD, nullptr);
+ Func = GetGlobalValue(MangledName);
+ } else {
+ const CGFunctionInfo &FI =
+ getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
+ Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false,
+ /*DontDefer=*/false, ForDefinition);
+ }
+ assert(Func && "This should have just been created");
+ }
+ Options.emplace_back(getTarget(), cast<llvm::Function>(Func),
+ CurFD->getAttr<TargetAttr>()->parse());
+ });
+
+ llvm::Function *ResolverFunc = cast<llvm::Function>(
+ GetGlobalValue((getMangledName(GD) + ".resolver").str()));
+ if (supportsCOMDAT())
+ ResolverFunc->setComdat(
+ getModule().getOrInsertComdat(ResolverFunc->getName()));
+ std::stable_sort(
+ Options.begin(), Options.end(),
+ std::greater<CodeGenFunction::TargetMultiVersionResolverOption>());
+ CodeGenFunction CGF(*this);
+ CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options);
+ }
+}
+
+void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
+ assert(FD && "Not a FunctionDecl?");
+ const auto *DD = FD->getAttr<CPUDispatchAttr>();
+ assert(DD && "Not a cpu_dispatch Function?");
+ llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType());
+
+ StringRef ResolverName = getMangledName(GD);
+ llvm::Type *ResolverType = llvm::FunctionType::get(
+ llvm::PointerType::get(DeclTy,
+ Context.getTargetAddressSpace(FD->getType())),
+ false);
+ auto *ResolverFunc = cast<llvm::Function>(
+ GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
+ /*ForVTable=*/false));
+
+ SmallVector<CodeGenFunction::CPUDispatchMultiVersionResolverOption, 10>
+ Options;
+ const TargetInfo &Target = getTarget();
+ for (const IdentifierInfo *II : DD->cpus()) {
+ // Get the name of the target function so we can look it up/create it.
+ std::string MangledName = getMangledNameImpl(*this, GD, FD, true) +
+ getCPUSpecificMangling(*this, II->getName());
+ llvm::Constant *Func = GetOrCreateLLVMFunction(
+ MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false,
+ /*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
+ llvm::SmallVector<StringRef, 32> Features;
+ Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features);
+ llvm::transform(Features, Features.begin(),
+ [](StringRef Str) { return Str.substr(1); });
+ Features.erase(std::remove_if(
+ Features.begin(), Features.end(), [&Target](StringRef Feat) {
+ return !Target.validateCpuSupports(Feat);
+ }), Features.end());
+ Options.emplace_back(cast<llvm::Function>(Func),
+ CodeGenFunction::GetX86CpuSupportsMask(Features));
+ }
+
+ llvm::sort(
+ Options.begin(), Options.end(),
+ std::greater<CodeGenFunction::CPUDispatchMultiVersionResolverOption>());
+ CodeGenFunction CGF(*this);
+ CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options);
+}
+
+/// If an ifunc for the specified mangled name is not in the module, create and
+/// return an llvm IFunc Function with the specified type.
+llvm::Constant *
+CodeGenModule::GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy,
+ const FunctionDecl *FD) {
+ std::string MangledName =
+ getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
+ std::string IFuncName = MangledName + ".ifunc";
+ if (llvm::GlobalValue *IFuncGV = GetGlobalValue(IFuncName))
+ return IFuncGV;
+
+ // Since this is the first time we've created this IFunc, make sure
+ // that we put this multiversioned function into the list to be
+ // replaced later if necessary (target multiversioning only).
+ if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion())
+ MultiVersionFuncs.push_back(GD);
+
+ std::string ResolverName = MangledName + ".resolver";
+ llvm::Type *ResolverType = llvm::FunctionType::get(
+ llvm::PointerType::get(DeclTy,
+ Context.getTargetAddressSpace(FD->getType())),
+ false);
+ llvm::Constant *Resolver =
+ GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
+ /*ForVTable=*/false);
+ llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
+ DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule());
+ GIF->setName(IFuncName);
+ SetCommonAttributes(FD, GIF);
+
+ return GIF;
+}
+
/// GetOrCreateLLVMFunction - If the specified mangled name is not in the
/// module, create and return an llvm Function with the specified type. If there
/// is something in the module with the specified name, return it potentially
@@ -2074,6 +2532,33 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
ForDefinition_t IsForDefinition) {
const Decl *D = GD.getDecl();
+ // Any attempts to use a MultiVersion function should result in retrieving
+ // the iFunc instead. Name Mangling will handle the rest of the changes.
+ if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
+ // For the device mark the function as one that should be emitted.
+ if (getLangOpts().OpenMPIsDevice && OpenMPRuntime &&
+ !OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() &&
+ !DontDefer && !IsForDefinition) {
+ const FunctionDecl *FDDef = FD->getDefinition();
+ GlobalDecl GDDef;
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(FDDef))
+ GDDef = GlobalDecl(CD, GD.getCtorType());
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(FDDef))
+ GDDef = GlobalDecl(DD, GD.getDtorType());
+ else
+ GDDef = GlobalDecl(FDDef);
+ addDeferredDeclToEmit(GDDef);
+ }
+
+ if (FD->isMultiVersion()) {
+ const auto *TA = FD->getAttr<TargetAttr>();
+ if (TA && TA->isDefaultVersion())
+ UpdateMultiVersionNames(GD, FD);
+ if (!IsForDefinition)
+ return GetOrCreateMultiVersionIFunc(GD, Ty, FD);
+ }
+ }
+
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
@@ -2084,8 +2569,10 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
}
// Handle dropped DLL attributes.
- if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>())
+ if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) {
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ setDSOLocal(Entry);
+ }
// If there are two attempts to define the same mangled name, issue an
// error.
@@ -2097,8 +2584,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
(GD.getCanonicalDecl().getDecl() !=
OtherGD.getCanonicalDecl().getDecl()) &&
DiagnosedConflictingDefinitions.insert(GD).second) {
- getDiags().Report(D->getLocation(),
- diag::err_duplicate_mangled_name);
+ getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name)
+ << MangledName;
getDiags().Report(OtherGD.getDecl()->getLocation(),
diag::note_previous_definition);
}
@@ -2160,8 +2647,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
assert(F->getName() == MangledName && "name was uniqued!");
if (D)
- SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk,
- IsForDefinition);
+ SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk);
if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) {
llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex);
F->addAttributes(llvm::AttributeList::FunctionIndex, B);
@@ -2237,6 +2723,16 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
Ty = getTypes().ConvertFunctionType(CanonTy, FD);
}
+ // Devirtualized destructor calls may come through here instead of via
+ // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
+ // of the complete destructor when necessary.
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(GD.getDecl())) {
+ if (getTarget().getCXXABI().isMicrosoft() &&
+ GD.getDtorType() == Dtor_Complete &&
+ DD->getParent()->getNumVBases() == 0)
+ GD = GlobalDecl(DD, Dtor_Base);
+ }
+
StringRef MangledName = getMangledName(GD);
return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer,
/*IsThunk=*/false, llvm::AttributeList(),
@@ -2258,7 +2754,7 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
// Demangle the premangled name from getTerminateFn()
IdentifierInfo &CXXII =
- (Name == "_ZSt9terminatev" || Name == "\01?terminate@@YAXXZ")
+ (Name == "_ZSt9terminatev" || Name == "?terminate@@YAXXZ")
? C.Idents.get("terminate")
: C.Idents.get(Name);
@@ -2305,6 +2801,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
+ setDSOLocal(F);
}
}
@@ -2316,13 +2813,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
llvm::Constant *
CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name,
llvm::AttributeList ExtraAttrs) {
- llvm::Constant *C =
- GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
- /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);
- if (auto *F = dyn_cast<llvm::Function>(C))
- if (F->empty())
- F->setCallingConv(getBuiltinCC());
- return C;
+ return CreateRuntimeFunction(FTy, Name, ExtraAttrs, true);
}
/// isTypeConstant - Determine whether an object of this type can be emitted
@@ -2353,7 +2844,7 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
/// If D is non-null, it specifies a decl that correspond to this. This is used
/// to set the attributes on the global when it is first created.
///
-/// If IsForDefinition is true, it is guranteed that an actual global with
+/// If IsForDefinition is true, it is guaranteed that an actual global with
/// type Ty will be returned, not conversion of a variable with the same
/// mangled name but some other type.
llvm::Constant *
@@ -2373,6 +2864,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>())
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
+ getOpenMPRuntime().registerTargetGlobalVariable(D, Entry);
+
if (Entry->getType() == Ty)
return Entry;
@@ -2389,8 +2883,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
(OtherD = dyn_cast<VarDecl>(OtherGD.getDecl())) &&
OtherD->hasInit() &&
DiagnosedConflictingDefinitions.insert(D).second) {
- getDiags().Report(D->getLocation(),
- diag::err_duplicate_mangled_name);
+ getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name)
+ << MangledName;
getDiags().Report(OtherGD.getDecl()->getLocation(),
diag::note_previous_definition);
}
@@ -2441,6 +2935,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
// Handle things which are present even on external declarations.
if (D) {
+ if (LangOpts.OpenMP && !LangOpts.OpenMPSimd)
+ getOpenMPRuntime().registerTargetGlobalVariable(D, GV);
+
// FIXME: This code is overly simple and should be merged with other global
// handling.
GV->setConstant(isTypeConstant(D->getType(), false));
@@ -2448,7 +2945,6 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
setLinkageForGV(GV, D);
- setGlobalVisibility(GV, D, NotForDefinition);
if (D->getTLSKind()) {
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
@@ -2456,6 +2952,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
setTLSMode(GV, *D);
}
+ setGVProperties(GV, D);
+
// If required by the ABI, treat declarations of static data members with
// inline initializers as definitions.
if (getContext().isMSStaticDataMemberInlineDefinition(D)) {
@@ -2504,7 +3002,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
GetAddrOfGlobalVar(D, InitType, IsForDefinition));
// Erase the old global, since it is no longer used.
- cast<llvm::GlobalValue>(GV)->eraseFromParent();
+ GV->eraseFromParent();
GV = NewGV;
} else {
GV->setInitializer(Init);
@@ -2605,7 +3103,7 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
/// given global variable. If Ty is non-null and if the global doesn't exist,
/// then it will be created with the specified type instead of whatever the
-/// normal requested type would be. If IsForDefinition is true, it is guranteed
+/// normal requested type would be. If IsForDefinition is true, it is guaranteed
/// that an actual global with type Ty will be returned, not conversion of a
/// variable with the same mangled name but some other type.
llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
@@ -2628,7 +3126,10 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
llvm::Constant *
CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name) {
- return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr);
+ auto *Ret =
+ GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr);
+ setDSOLocal(cast<llvm::GlobalValue>(Ret->stripPointerCasts()));
+ return Ret;
}
void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
@@ -2675,6 +3176,10 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
return LangAS::cuda_constant;
else if (D && D->hasAttr<CUDASharedAttr>())
return LangAS::cuda_shared;
+ else if (D && D->hasAttr<CUDADeviceAttr>())
+ return LangAS::cuda_device;
+ else if (D && D->getType().isConstQualified())
+ return LangAS::cuda_constant;
else
return LangAS::cuda_device;
}
@@ -2682,6 +3187,39 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D);
}
+LangAS CodeGenModule::getStringLiteralAddressSpace() const {
+ // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
+ if (LangOpts.OpenCL)
+ return LangAS::opencl_constant;
+ if (auto AS = getTarget().getConstantAddressSpace())
+ return AS.getValue();
+ return LangAS::Default;
+}
+
+// In address space agnostic languages, string literals are in default address
+// space in AST. However, certain targets (e.g. amdgcn) request them to be
+// emitted in constant address space in LLVM IR. To be consistent with other
+// parts of AST, string literal global variables in constant address space
+// need to be casted to default address space before being put into address
+// map and referenced by other part of CodeGen.
+// In OpenCL, string literals are in constant address space in AST, therefore
+// they should not be casted to default address space.
+static llvm::Constant *
+castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM,
+ llvm::GlobalVariable *GV) {
+ llvm::Constant *Cast = GV;
+ if (!CGM.getLangOpts().OpenCL) {
+ if (auto AS = CGM.getTarget().getConstantAddressSpace()) {
+ if (AS != LangAS::Default)
+ Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
+ CGM, GV, AS.getValue(), LangAS::Default,
+ GV->getValueType()->getPointerTo(
+ CGM.getContext().getTargetAddressSpace(LangAS::Default)));
+ }
+ }
+ return Cast;
+}
+
template<typename SomeDecl>
void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
llvm::GlobalValue *GV) {
@@ -2756,6 +3294,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
if (getLangOpts().OpenCL && ASTTy->isSamplerT())
return;
+ // If this is OpenMP device, check if it is legal to emit this global
+ // normally.
+ if (LangOpts.OpenMPIsDevice && OpenMPRuntime &&
+ OpenMPRuntime->emitTargetGlobalVariable(D))
+ return;
+
llvm::Constant *Init = nullptr;
CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
bool NeedsGlobalCtor = false;
@@ -2992,7 +3536,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
return true;
// A variable cannot be both common and exist in a section.
- // We dont try to determine which is the right section in the front-end.
+ // We don't try to determine which is the right section in the front-end.
// If no specialized section name is applicable, it will resort to default.
if (D->hasAttr<PragmaClangBSSSectionAttr>() ||
D->hasAttr<PragmaClangDataSectionAttr>() ||
@@ -3264,18 +3808,18 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
// declarations).
auto *Fn = cast<llvm::Function>(GV);
setFunctionLinkage(GD, Fn);
- setFunctionDLLStorageClass(GD, Fn);
// FIXME: this is redundant with part of setFunctionDefinitionAttributes
- setGlobalVisibility(Fn, D, ForDefinition);
+ setGVProperties(Fn, GD);
MaybeHandleStaticInExternC(D, Fn);
+
maybeSetTrivialComdat(*D, *Fn);
CodeGenFunction(*this).GenerateCode(D, Fn, FI);
- setFunctionDefinitionAttributes(D, Fn);
+ setNonAliasAttributes(GD, Fn);
SetLLVMFunctionAttributesForDefinition(D, Fn);
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
@@ -3284,6 +3828,15 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
AddGlobalDtor(Fn, DA->getPriority());
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, Fn);
+
+ if (D->isCPUSpecificMultiVersion()) {
+ auto *Spec = D->getAttr<CPUSpecificAttr>();
+ // If there is another specific version we need to emit, do so here.
+ if (Spec->ActiveArgIndex + 1 < Spec->cpus_size()) {
+ ++Spec->ActiveArgIndex;
+ EmitGlobalFunctionDefinition(GD, nullptr);
+ }
+ }
}
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
@@ -3359,7 +3912,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
if (VD->getTLSKind())
setTLSMode(GA, *VD);
- setAliasAttributes(D, GA);
+ SetCommonAttributes(GD, GA);
}
void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
@@ -3380,7 +3933,8 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
GlobalDecl OtherGD;
if (lookupRepresentativeDecl(MangledName, OtherGD) &&
DiagnosedConflictingDefinitions.insert(GD).second) {
- Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name);
+ Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name)
+ << MangledName;
Diags.Report(OtherGD.getDecl()->getLocation(),
diag::note_previous_definition);
}
@@ -3418,7 +3972,7 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
} else
GIF->setName(MangledName);
- SetCommonAttributes(D, GIF);
+ SetCommonAttributes(GD, GIF);
}
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
@@ -3480,14 +4034,13 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
if (!CFConstantStringClassRef) {
llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
Ty = llvm::ArrayType::get(Ty, 0);
- llvm::Constant *GV =
- CreateRuntimeVariable(Ty, "__CFConstantStringClassReference");
+ llvm::GlobalValue *GV = cast<llvm::GlobalValue>(
+ CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"));
if (getTriple().isOSBinFormatCOFF()) {
IdentifierInfo &II = getContext().Idents.get(GV->getName());
TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl();
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
- llvm::GlobalValue *CGV = cast<llvm::GlobalValue>(GV);
const VarDecl *VD = nullptr;
for (const auto &Result : DC->lookup(&II))
@@ -3495,13 +4048,14 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
break;
if (!VD || !VD->hasAttr<DLLExportAttr>()) {
- CGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- CGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
} else {
- CGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- CGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
+ setDSOLocal(GV);
// Decay array -> ptr
CFConstantStringClassRef =
@@ -3669,10 +4223,8 @@ static llvm::GlobalVariable *
GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
CodeGenModule &CGM, StringRef GlobalName,
CharUnits Alignment) {
- // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
- unsigned AddrSpace = 0;
- if (CGM.getLangOpts().OpenCL)
- AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
+ unsigned AddrSpace = CGM.getContext().getTargetAddressSpace(
+ CGM.getStringLiteralAddressSpace());
llvm::Module &M = CGM.getModule();
// Create a global variable for this string
@@ -3685,6 +4237,7 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals");
GV->setComdat(M.getOrInsertComdat(GV->getName()));
}
+ CGM.setDSOLocal(GV);
return GV;
}
@@ -3733,7 +4286,9 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>",
QualType());
- return ConstantAddress(GV, Alignment);
+
+ return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
+ Alignment);
}
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
@@ -3777,7 +4332,9 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString(
GlobalName, Alignment);
if (Entry)
*Entry = GV;
- return ConstantAddress(GV, Alignment);
+
+ return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
+ Alignment);
}
ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
@@ -3850,7 +4407,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) &&
isa<CXXRecordDecl>(InitVD->getLexicalDeclContext())) {
// Temporaries defined inside a class get linkonce_odr linkage because the
- // class can be defined in multipe translation units.
+ // class can be defined in multiple translation units.
Linkage = llvm::GlobalVariable::LinkOnceODRLinkage;
} else {
// There is no need for this temporary to have external linkage if the
@@ -3863,7 +4420,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
/*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
if (emitter) emitter->finalize(GV);
- setGlobalVisibility(GV, VD, ForDefinition);
+ setGVProperties(GV, VD);
GV->setAlignment(Align.getQuantity());
if (supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
@@ -4139,7 +4696,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
AppendLinkerOptions(PCD->getArg());
break;
case PCK_Lib:
- AddDependentLib(PCD->getArg());
+ if (getTarget().getTriple().isOSBinFormatELF() &&
+ !getTarget().getTriple().isPS4())
+ AddELFLibDirective(PCD->getArg());
+ else
+ AddDependentLib(PCD->getArg());
break;
case PCK_Compiler:
case PCK_ExeStr:
@@ -4345,9 +4906,7 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
/// to such functions with an unmangled name from inline assembly within the
/// same translation unit.
void CodeGenModule::EmitStaticExternCAliases() {
- // Don't do anything if we're generating CUDA device code -- the NVPTX
- // assembly target doesn't support aliases.
- if (Context.getTargetInfo().getTriple().isNVPTX())
+ if (!getTargetCodeGenInfo().shouldEmitStaticExternCAliases())
return;
for (auto &I : StaticExternCValues) {
IdentifierInfo *Name = I.first;
@@ -4491,7 +5050,7 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
// Return a bogus pointer if RTTI is disabled, unless it's for EH.
// FIXME: should we even be calling this method if RTTI is disabled
// and it's not for EH?
- if (!ForEH && !getLangOpts().RTTI)
+ if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice)
return llvm::Constant::getNullValue(Int8PtrTy);
if (ForEH && Ty->isObjCObjectPointerType() &&
@@ -4519,8 +5078,10 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
}
}
-llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
- llvm::Metadata *&InternalId = MetadataIdMap[T.getCanonicalType()];
+llvm::Metadata *
+CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
+ StringRef Suffix) {
+ llvm::Metadata *&InternalId = Map[T.getCanonicalType()];
if (InternalId)
return InternalId;
@@ -4528,6 +5089,7 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
std::string OutName;
llvm::raw_string_ostream Out(OutName);
getCXXABI().getMangleContext().mangleTypeName(T, Out);
+ Out << Suffix;
InternalId = llvm::MDString::get(getLLVMContext(), Out.str());
} else {
@@ -4538,6 +5100,15 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
return InternalId;
}
+llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
+ return CreateMetadataIdentifierImpl(T, MetadataIdMap, "");
+}
+
+llvm::Metadata *
+CodeGenModule::CreateMetadataIdentifierForVirtualMemPtrType(QualType T) {
+ return CreateMetadataIdentifierImpl(T, VirtualMetadataIdMap, ".virtual");
+}
+
// 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
@@ -4571,25 +5142,8 @@ static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) {
}
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;
+ return CreateMetadataIdentifierImpl(GeneralizeFunctionType(getContext(), T),
+ GeneralizedMetadataIdMap, ".generalized");
}
/// Returns whether this module needs the "all-vtables" type identifier.
@@ -4624,22 +5178,28 @@ void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable,
}
}
+TargetAttr::ParsedTargetAttr CodeGenModule::filterFunctionTargetAttrs(const TargetAttr *TD) {
+ assert(TD != nullptr);
+ 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());
+ return ParsedAttr;
+}
+
+
// Fills in the supplied string map with the set of target features for the
// passed in function.
void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
const FunctionDecl *FD) {
StringRef TargetCPU = Target.getTargetOpts().CPU;
if (const auto *TD = FD->getAttr<TargetAttr>()) {
- // 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());
+ TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD);
// Make a copy of the features as passed on the command line into the
// beginning of the additional features from the function to override.
@@ -4657,6 +5217,12 @@ void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
// the attribute.
Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU,
ParsedAttr.Features);
+ } else if (const auto *SD = FD->getAttr<CPUSpecificAttr>()) {
+ llvm::SmallVector<StringRef, 32> FeaturesTmp;
+ Target.getCPUSpecificCPUDispatchFeatures(SD->getCurCPUName()->getName(),
+ FeaturesTmp);
+ std::vector<std::string> Features(FeaturesTmp.begin(), FeaturesTmp.end());
+ Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features);
} else {
Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU,
Target.getTargetOpts().Features);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
index 22c4463b2c81..91f3d94330f1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -280,14 +280,14 @@ private:
llvm::LLVMContext &VMContext;
std::unique_ptr<CodeGenTBAA> TBAA;
-
+
mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo;
-
+
// This should not be moved earlier, since its initialization depends on some
// of the previous reference members being already initialized and also checks
// if TheTargetCodeGenInfo is NULL
CodeGenTypes Types;
-
+
/// Holds information about C++ vtables.
CodeGenVTables VTables;
@@ -324,6 +324,10 @@ private:
/// is defined once we get to the end of the of the translation unit.
std::vector<GlobalDecl> Aliases;
+ /// List of multiversion functions that have to be emitted. Used to make sure
+ /// we properly emit the iFunc.
+ std::vector<GlobalDecl> MultiVersionFuncs;
+
typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
ReplacementsTy Replacements;
@@ -362,6 +366,13 @@ private:
llvm::MapVector<GlobalDecl, StringRef> MangledDeclNames;
llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings;
+ // An ordered map of canonical GlobalDecls paired with the cpu-index for
+ // cpu-specific name manglings.
+ llvm::MapVector<std::pair<GlobalDecl, unsigned>, StringRef>
+ CPUSpecificMangledDeclNames;
+ llvm::StringMap<std::pair<GlobalDecl, unsigned>, llvm::BumpPtrAllocator>
+ CPUSpecificManglings;
+
/// Global annotations.
std::vector<llvm::Constant*> Annotations;
@@ -387,10 +398,10 @@ private:
llvm::GlobalValue *> StaticExternCMap;
StaticExternCMap StaticExternCValues;
- /// \brief thread_local variables defined or used in this TU.
+ /// thread_local variables defined or used in this TU.
std::vector<const VarDecl *> CXXThreadLocals;
- /// \brief thread_local variables with initializers that need to run
+ /// thread_local variables with initializers that need to run
/// before any thread_local variable in this TU is odr-used.
std::vector<llvm::Function *> CXXThreadLocalInits;
std::vector<const VarDecl *> CXXThreadLocalInitVars;
@@ -404,7 +415,7 @@ private:
/// order. Once the decl is emitted, the index is replaced with ~0U to ensure
/// that we don't re-emit the initializer.
llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
-
+
typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData;
struct GlobalInitPriorityCmp {
@@ -421,14 +432,14 @@ private:
/// Global destructor functions and arguments that need to run on termination.
std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>> CXXGlobalDtors;
- /// \brief The complete set of modules that has been imported.
+ /// The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
- /// \brief The set of modules for which the module initializers
+ /// The set of modules for which the module initializers
/// have been emitted.
llvm::SmallPtrSet<clang::Module *, 16> EmittedModuleInitializers;
- /// \brief A vector of metadata strings.
+ /// A vector of metadata strings.
SmallVector<llvm::MDNode *, 16> LinkerOptionsMetadata;
/// @name Cache for Objective-C runtime types
@@ -438,10 +449,10 @@ private:
/// int * but is actually an Obj-C class pointer.
llvm::WeakTrackingVH CFConstantStringClassRef;
- /// \brief The type used to describe the state of a fast enumeration in
+ /// The type used to describe the state of a fast enumeration in
/// Objective-C's for..in loop.
QualType ObjCFastEnumerationStateType;
-
+
/// @}
/// Lazily create the Objective-C runtime
@@ -499,6 +510,7 @@ private:
/// MDNodes.
typedef llvm::DenseMap<QualType, llvm::Metadata *> MetadataTypeMap;
MetadataTypeMap MetadataIdMap;
+ MetadataTypeMap VirtualMetadataIdMap;
MetadataTypeMap GeneralizedMetadataIdMap;
public:
@@ -564,7 +576,7 @@ public:
llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
return StaticLocalDeclMap[D];
}
- void setStaticLocalDeclAddress(const VarDecl *D,
+ void setStaticLocalDeclAddress(const VarDecl *D,
llvm::Constant *C) {
StaticLocalDeclMap[D] = C;
}
@@ -576,7 +588,7 @@ public:
llvm::GlobalVariable *getStaticLocalDeclGuardAddress(const VarDecl *D) {
return StaticLocalDeclGuardMap[D];
}
- void setStaticLocalDeclGuardAddress(const VarDecl *D,
+ void setStaticLocalDeclGuardAddress(const VarDecl *D,
llvm::GlobalVariable *C) {
StaticLocalDeclGuardMap[D] = C;
}
@@ -637,10 +649,10 @@ public:
bool shouldUseTBAA() const { return TBAA != nullptr; }
- const TargetCodeGenInfo &getTargetCodeGenInfo();
-
+ const TargetCodeGenInfo &getTargetCodeGenInfo();
+
CodeGenTypes &getTypes() { return Types; }
-
+
CodeGenVTables &getVTables() { return VTables; }
ItaniumVTableContext &getItaniumVTableContext() {
@@ -685,6 +697,11 @@ public:
TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
TBAAAccessInfo InfoB);
+ /// mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the
+ /// purposes of memory transfer calls.
+ TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo,
+ TBAAAccessInfo SrcInfo);
+
/// getTBAAInfoForSubobject - Get TBAA information for an access with a given
/// base lvalue.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType) {
@@ -710,8 +727,19 @@ public:
llvm::ConstantInt *getSize(CharUnits numChars);
/// Set the visibility for the given LLVM GlobalValue.
- void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D,
- ForDefinition_t IsForDefinition) const;
+ void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
+
+ void setGlobalVisibilityAndLocal(llvm::GlobalValue *GV,
+ const NamedDecl *D) const;
+
+ void setDSOLocal(llvm::GlobalValue *GV) const;
+
+ void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const;
+ void setDLLImportDLLExport(llvm::GlobalValue *GV, const NamedDecl *D) const;
+ /// Set visibility, dllimport/dllexport and dso_local.
+ /// This must be called after dllimport/dllexport is set.
+ void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const;
+ void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const;
/// Set the TLS mode for the given LLVM GlobalValue for the thread-local
/// variable declaration D.
@@ -757,7 +785,7 @@ public:
/// 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
/// with the specified type instead of whatever the normal requested type
- /// would be. If IsForDefinition is true, it is guranteed that an actual
+ /// would be. If IsForDefinition is true, it is guaranteed that an actual
/// global with type Ty will be returned, not conversion of a variable with
/// the same mangled name but some other type.
llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
@@ -765,6 +793,13 @@ public:
ForDefinition_t IsForDefinition
= NotForDefinition);
+ /// Return the AST address space of string literal, which is used to emit
+ /// the string literal as global variable in LLVM IR.
+ /// Note: This is not necessarily the address space of the string literal
+ /// in AST. For address space agnostic language, e.g. C++, string literal
+ /// in AST is always in default address space.
+ LangAS getStringLiteralAddressSpace() const;
+
/// Return the address of the given function. If Ty is non-null, then this
/// function will use the specified type if it has to create it.
llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr,
@@ -780,7 +815,8 @@ public:
ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
/// Get the address of the thunk for the given global decl.
- llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk);
+ llvm::Constant *GetAddrOfThunk(StringRef Name, llvm::Type *FnTy,
+ GlobalDecl GD);
/// Get a reference to the target of VD.
ConstantAddress GetWeakRefReference(const ValueDecl *VD);
@@ -816,7 +852,7 @@ public:
/// Fetches the global unique block count.
int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
-
+
/// Fetches the type of a generic block descriptor.
llvm::Type *getBlockDescriptorType();
@@ -835,7 +871,7 @@ public:
/// Notes that BE's global block is available via Addr. Asserts that BE
/// isn't already emitted.
void setAddrOfGlobalBlock(const BlockExpr *BE, llvm::Constant *Addr);
-
+
/// Return a pointer to a constant CFString object for the given string.
ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal);
@@ -879,12 +915,12 @@ public:
void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *CLE,
llvm::GlobalVariable *GV);
- /// \brief Returns a pointer to a global variable representing a temporary
+ /// Returns a pointer to a global variable representing a temporary
/// with static or thread storage duration.
ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
const Expr *Inner);
- /// \brief Retrieve the record type that describes the state of an
+ /// Retrieve the record type that describes the state of an
/// Objective-C fast enumeration loop (for..in).
QualType getObjCFastEnumerationStateType();
@@ -912,22 +948,22 @@ public:
/// Emit code for a single top level declaration.
void EmitTopLevelDecl(Decl *D);
- /// \brief Stored a deferred empty coverage mapping for an unused
+ /// Stored a deferred empty coverage mapping for an unused
/// and thus uninstrumented top level declaration.
void AddDeferredUnusedCoverageMapping(Decl *D);
- /// \brief Remove the deferred empty coverage mapping as this
+ /// Remove the deferred empty coverage mapping as this
/// declaration is actually instrumented.
void ClearUnusedCoverageMapping(const Decl *D);
- /// \brief Emit all the deferred coverage mappings
+ /// Emit all the deferred coverage mappings
/// for the uninstrumented functions.
void EmitDeferredUnusedCoverageMappings();
/// Tell the consumer that this variable has been instantiated.
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
- /// \brief If the declaration has internal linkage but is inside an
+ /// If the declaration has internal linkage but is inside an
/// extern "C" linkage specification, prepare to emit an alias for it
/// to the expected name.
template<typename SomeDecl>
@@ -976,7 +1012,7 @@ public:
llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
- /// \brief Emit type info if type of an expression is a variably modified
+ /// 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,
CodeGenFunction *CGF = nullptr);
@@ -1002,7 +1038,7 @@ public:
/// Set the attributes on the LLVM function for the given decl and function
/// info. This applies attributes necessary for handling the ABI as well as
/// user specified attributes like section.
- void SetInternalFunctionAttributes(const Decl *D, llvm::Function *F,
+ void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F,
const CGFunctionInfo &FI);
/// Set the LLVM function attributes (sext, zext, etc).
@@ -1061,6 +1097,10 @@ public:
/// It's up to you to ensure that this is safe.
void AddDefaultFnAttrs(llvm::Function &F);
+ /// Parses the target attributes passed in, and returns only the ones that are
+ /// valid feature names.
+ TargetAttr::ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD);
+
// Fills in the supplied string map with the set of target features for the
// passed in function.
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
@@ -1075,32 +1115,31 @@ public:
void RefreshTypeCacheForClass(const CXXRecordDecl *Class);
- /// \brief Appends Opts to the "llvm.linker.options" metadata value.
+ /// Appends Opts to the "llvm.linker.options" metadata value.
void AppendLinkerOptions(StringRef Opts);
- /// \brief Appends a detect mismatch command to the linker options.
+ /// Appends a detect mismatch command to the linker options.
void AddDetectMismatch(StringRef Name, StringRef Value);
- /// \brief Appends a dependent lib to the "llvm.linker.options" metadata
+ /// Appends a dependent lib to the "llvm.linker.options" metadata
/// value.
void AddDependentLib(StringRef Lib);
+ void AddELFLibDirective(StringRef Lib);
+
llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) {
F->setLinkage(getFunctionLinkage(GD));
}
- /// Set the DLL storage class on F.
- void setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F);
-
/// Return the appropriate linkage for the vtable, VTT, and type information
/// of the given class.
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
/// Return the store size, in character units, of the given LLVM type.
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const;
-
+
/// Returns LLVM linkage for a declarator.
llvm::GlobalValue::LinkageTypes
getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage,
@@ -1158,40 +1197,29 @@ public:
DeferredVTables.push_back(RD);
}
- /// Emit code for a singal global function or var decl. Forward declarations
+ /// Emit code for a single global function or var decl. Forward declarations
/// are emitted lazily.
void EmitGlobal(GlobalDecl D);
- bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
- /// Set attributes for a global definition.
- void setFunctionDefinitionAttributes(const FunctionDecl *D,
- llvm::Function *F);
-
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
/// Set attributes which are common to any form of a global definition (alias,
/// Objective-C method, function, global variable).
///
/// NOTE: This should only be called for definitions.
- void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
-
- /// Set attributes which must be preserved by an alias. This includes common
- /// attributes (i.e. it includes a call to SetCommonAttributes).
- ///
- /// NOTE: This should only be called for definitions.
- void setAliasAttributes(const Decl *D, llvm::GlobalValue *GV);
+ void SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV);
void addReplacement(StringRef Name, llvm::Constant *C);
void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C);
- /// \brief Emit a code for threadprivate directive.
+ /// Emit a code for threadprivate directive.
/// \param D Threadprivate declaration.
void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D);
- /// \brief Emit a code for declare reduction construct.
+ /// Emit a code for declare reduction construct.
void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
CodeGenFunction *CGF = nullptr);
@@ -1212,13 +1240,18 @@ public:
/// internal identifiers).
llvm::Metadata *CreateMetadataIdentifierForType(QualType T);
+ /// Create a metadata identifier that is intended to be used to check virtual
+ /// calls via a member function pointer.
+ llvm::Metadata *CreateMetadataIdentifierForVirtualMemPtrType(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);
+ void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
+ llvm::Function *F);
/// Returns whether this module needs the "all-vtables" type identifier.
bool NeedAllVtablesTypeId() const;
@@ -1227,7 +1260,15 @@ public:
void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset,
const CXXRecordDecl *RD);
- /// \brief Get the declaration of std::terminate for the platform.
+ /// Return a vector of most-base classes for RD. This is used to implement
+ /// control flow integrity checks for member function pointers.
+ ///
+ /// A most-base class of a class C is defined as a recursive base class of C,
+ /// including C itself, that does not have any bases.
+ std::vector<const CXXRecordDecl *>
+ getMostBaseClasses(const CXXRecordDecl *RD);
+
+ /// Get the declaration of std::terminate for the platform.
llvm::Constant *getTerminateFn();
llvm::SanitizerStatReport &getSanStats();
@@ -1247,18 +1288,24 @@ private:
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
ForDefinition_t IsForDefinition = NotForDefinition);
+ llvm::Constant *GetOrCreateMultiVersionIFunc(GlobalDecl GD,
+ llvm::Type *DeclTy,
+ const FunctionDecl *FD);
+ void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD);
+
llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::PointerType *PTy,
const VarDecl *D,
ForDefinition_t IsForDefinition
= NotForDefinition);
- void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO);
+ bool GetCPUAndFeaturesAttributes(const Decl *D,
+ llvm::AttrBuilder &AttrBuilder);
+ void setNonAliasAttributes(GlobalDecl GD, llvm::GlobalObject *GO);
/// Set function attributes for a function declaration.
void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
- bool IsIncompleteFunction, bool IsThunk,
- ForDefinition_t IsForDefinition);
+ bool IsIncompleteFunction, bool IsThunk);
void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
@@ -1266,15 +1313,16 @@ private:
void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false);
void EmitAliasDefinition(GlobalDecl GD);
void emitIFuncDefinition(GlobalDecl GD);
+ void emitCPUDispatchDefinition(GlobalDecl GD);
void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
void EmitObjCIvarInitializations(ObjCImplementationDecl *D);
-
+
// C++ related functions.
void EmitDeclContext(const DeclContext *DC);
void EmitLinkageSpec(const LinkageSpecDecl *D);
- /// \brief Emit the function that initializes C++ thread_local variables.
+ /// Emit the function that initializes C++ thread_local variables.
void EmitCXXThreadLocalInitFunc();
/// Emit the function that initializes C++ globals.
@@ -1319,6 +1367,14 @@ private:
void checkAliases();
+ std::map<int, llvm::TinyPtrVector<llvm::Function *>> DtorsUsingAtExit;
+
+ /// Register functions annotated with __attribute__((destructor)) using
+ /// __cxa_atexit, if it is available, or atexit otherwise.
+ void registerGlobalDtorsWithAtExit();
+
+ void emitMultiVersionFunctions();
+
/// Emit any vtables which we deferred and still have a use for.
void EmitDeferredVTables();
@@ -1329,16 +1385,16 @@ private:
/// Emit the llvm.used and llvm.compiler.used metadata.
void emitLLVMUsed();
- /// \brief Emit the link options introduced by imported modules.
+ /// Emit the link options introduced by imported modules.
void EmitModuleLinkOptions();
- /// \brief Emit aliases for internal-linkage declarations inside "C" language
+ /// Emit aliases for internal-linkage declarations inside "C" language
/// linkage specifications, giving them the "expected" name where possible.
void EmitStaticExternCAliases();
void EmitDeclMetadata();
- /// \brief Emit the Clang version as llvm.ident metadata.
+ /// Emit the Clang version as llvm.ident metadata.
void EmitVersionIdentMetadata();
/// Emits target specific Metadata for global declarations.
@@ -1373,6 +1429,9 @@ private:
void ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
bool AttrOnCallSite,
llvm::AttrBuilder &FuncAttrs);
+
+ llvm::Metadata *CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
+ StringRef Suffix);
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
index 295893c64fbc..c8c2a1b956b8 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -58,7 +58,7 @@ enum PGOHashVersion : unsigned {
};
namespace {
-/// \brief Stable hasher for PGO region counters.
+/// Stable hasher for PGO region counters.
///
/// PGOHash produces a stable hash of a given function's control flow.
///
@@ -79,7 +79,7 @@ class PGOHash {
static const unsigned TooBig = 1u << NumBitsPerType;
public:
- /// \brief Hash values for AST nodes.
+ /// Hash values for AST nodes.
///
/// Distinct values for AST nodes that have region counters attached.
///
@@ -978,7 +978,7 @@ void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
RegionCounts = ProfRecord->Counts;
}
-/// \brief Calculate what to divide by to scale weights.
+/// Calculate what to divide by to scale weights.
///
/// Given the maximum weight, calculate a divisor that will scale all the
/// weights to strictly less than UINT32_MAX.
@@ -986,7 +986,7 @@ static uint64_t calculateWeightScale(uint64_t MaxWeight) {
return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
}
-/// \brief Scale an individual branch weight (and add 1).
+/// Scale an individual branch weight (and add 1).
///
/// Scale a 64-bit weight down to 32-bits using \c Scale.
///
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
index ad473032db17..ec48231e5247 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -215,6 +215,19 @@ llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
return MetadataCache[Ty] = TypeNode;
}
+TBAAAccessInfo CodeGenTBAA::getAccessInfo(QualType AccessType) {
+ // Pointee values may have incomplete types, but they shall never be
+ // dereferenced.
+ if (AccessType->isIncompleteType())
+ return TBAAAccessInfo::getIncompleteInfo();
+
+ if (TypeHasMayAlias(AccessType))
+ return TBAAAccessInfo::getMayAliasInfo();
+
+ uint64_t Size = Context.getTypeSizeInChars(AccessType).getQuantity();
+ return TBAAAccessInfo(getTypeInfo(AccessType), Size);
+}
+
TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo(llvm::Type *VTablePtrType) {
llvm::DataLayout DL(&Module);
unsigned Size = DL.getPointerTypeSize(VTablePtrType);
@@ -391,3 +404,21 @@ CodeGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
// access type regardless of their base types.
return TBAAAccessInfo::getMayAliasInfo();
}
+
+TBAAAccessInfo
+CodeGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo,
+ TBAAAccessInfo SrcInfo) {
+ if (DestInfo == SrcInfo)
+ return DestInfo;
+
+ if (!DestInfo || !SrcInfo)
+ return TBAAAccessInfo();
+
+ if (DestInfo.isMayAlias() || SrcInfo.isMayAlias())
+ return TBAAAccessInfo::getMayAliasInfo();
+
+ // 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 a5b1f66bcd1a..86ba407c05c6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
@@ -177,6 +177,10 @@ public:
/// given type.
llvm::MDNode *getTypeInfo(QualType QTy);
+ /// getAccessInfo - Get TBAA information that describes an access to
+ /// an object of the given type.
+ TBAAAccessInfo getAccessInfo(QualType AccessType);
+
/// getVTablePtrAccessInfo - Get the TBAA information that describes an
/// access to a virtual table pointer.
TBAAAccessInfo getVTablePtrAccessInfo(llvm::Type *VTablePtrType);
@@ -201,6 +205,11 @@ public:
/// purpose of conditional operator.
TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
TBAAAccessInfo InfoB);
+
+ /// mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the
+ /// purpose of memory transfer calls.
+ TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo,
+ TBAAAccessInfo SrcInfo);
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
index fb096ac89987..901aed6c00b2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
@@ -112,8 +112,6 @@ struct CodeGenTypeCache {
llvm::CallingConv::ID RuntimeCC;
llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
- llvm::CallingConv::ID BuiltinCC;
- llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
LangAS getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; }
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
index 529a13b7adc8..1a1395e6ae74 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -54,7 +54,7 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
SmallString<256> TypeName;
llvm::raw_svector_ostream OS(TypeName);
OS << RD->getKindName() << '.';
-
+
// Name the codegen type after the typedef name
// if there is no tag type name available
if (RD->getIdentifier()) {
@@ -100,7 +100,7 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
/// isRecordLayoutComplete - Return true if the specified type is already
/// completely laid out.
bool CodeGenTypes::isRecordLayoutComplete(const Type *Ty) const {
- llvm::DenseMap<const Type*, llvm::StructType *>::const_iterator I =
+ llvm::DenseMap<const Type*, llvm::StructType *>::const_iterator I =
RecordDeclTypes.find(Ty);
return I != RecordDeclTypes.end() && !I->second->isOpaque();
}
@@ -113,7 +113,7 @@ isSafeToConvert(QualType T, CodeGenTypes &CGT,
/// isSafeToConvert - Return true if it is safe to convert the specified record
/// decl to IR and lay it out, false if doing so would cause us to get into a
/// recursive compilation mess.
-static bool
+static bool
isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT,
llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked) {
// If we have already checked this type (maybe the same type is used by-value
@@ -122,14 +122,14 @@ isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT,
return true;
const Type *Key = CGT.getContext().getTagDeclType(RD).getTypePtr();
-
+
// If this type is already laid out, converting it is a noop.
if (CGT.isRecordLayoutComplete(Key)) return true;
-
+
// If this type is currently being laid out, we can't recursively compile it.
if (CGT.isRecordBeingLaidOut(Key))
return false;
-
+
// If this type would require laying out bases that are currently being laid
// out, don't do it. This includes virtual base classes which get laid out
// when a class is translated, even though they aren't embedded by-value into
@@ -140,13 +140,13 @@ isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT,
CGT, AlreadyChecked))
return false;
}
-
+
// If this type would require laying out members that are currently being laid
// out, don't do it.
for (const auto *I : RD->fields())
if (!isSafeToConvert(I->getType(), CGT, AlreadyChecked))
return false;
-
+
// If there are no problems, lets do it.
return true;
}
@@ -170,7 +170,7 @@ isSafeToConvert(QualType T, CodeGenTypes &CGT,
return isSafeToConvert(AT->getElementType(), CGT, AlreadyChecked);
// Otherwise, there is no concern about transforming this. We only care about
- // things that are contained by-value in a structure that can have another
+ // things that are contained by-value in a structure that can have another
// structure as a member.
return true;
}
@@ -182,7 +182,7 @@ isSafeToConvert(QualType T, CodeGenTypes &CGT,
static bool isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT) {
// If no structs are being laid out, we can certainly do this one.
if (CGT.noRecordsBeingLaidOut()) return true;
-
+
llvm::SmallPtrSet<const RecordDecl*, 16> AlreadyChecked;
return isSafeToConvert(RD, CGT, AlreadyChecked);
}
@@ -229,7 +229,7 @@ bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) {
bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) {
if (!isFuncParamTypeConvertible(FT->getReturnType()))
return false;
-
+
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
if (!isFuncParamTypeConvertible(FPT->getParamType(i)))
@@ -259,7 +259,7 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
DI->completeType(ED);
return;
}
-
+
// If we completed a RecordDecl that we previously used and converted to an
// anonymous type, then go ahead and complete it now.
const RecordDecl *RD = cast<RecordDecl>(TD);
@@ -388,7 +388,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// RecordTypes are cached and processed specially.
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
return ConvertRecordDeclType(RT->getDecl());
-
+
// See if type is already cached.
llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = TypeCache.find(Ty);
// If type is found in map then use it. Otherwise, convert type T.
@@ -437,8 +437,33 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::ULongLong:
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
+ case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
ResultType = llvm::IntegerType::get(getLLVMContext(),
static_cast<unsigned>(Context.getTypeSize(T)));
break;
@@ -469,7 +494,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// Model std::nullptr_t as i8*
ResultType = llvm::Type::getInt8PtrTy(getLLVMContext());
break;
-
+
case BuiltinType::UInt128:
case BuiltinType::Int128:
ResultType = llvm::IntegerType::get(getLLVMContext(), 128);
@@ -485,7 +510,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::OCLReserveID:
ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
break;
-
+
case BuiltinType::Dependent:
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
@@ -549,8 +574,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case Type::ConstantArray: {
const ConstantArrayType *A = cast<ConstantArrayType>(Ty);
llvm::Type *EltTy = ConvertTypeForMem(A->getElementType());
-
- // Lower arrays of undefined struct type to arrays of i8 just to have a
+
+ // Lower arrays of undefined struct type to arrays of i8 just to have a
// concrete type.
if (!EltTy->isSized()) {
SkippedLayout = true;
@@ -649,9 +674,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;
}
}
-
+
assert(ResultType && "Didn't convert a type?");
-
+
TypeCache[Ty] = ResultType;
return ResultType;
}
@@ -684,7 +709,7 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
RD = RD->getDefinition();
if (!RD || !RD->isCompleteDefinition() || !Ty->isOpaque())
return Ty;
-
+
// If converting this type would cause us to infinitely loop, don't do it!
if (!isSafeToConvert(RD, *this)) {
DeferredRecords.push_back(RD);
@@ -695,12 +720,12 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
bool InsertResult = RecordsBeingLaidOut.insert(Key).second;
(void)InsertResult;
assert(InsertResult && "Recursively compiling a struct?");
-
+
// Force conversion of non-virtual base classes recursively.
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const auto &I : CRD->bases()) {
if (I.isVirtual()) continue;
-
+
ConvertRecordDeclType(I.getType()->getAs<RecordType>()->getDecl());
}
}
@@ -712,13 +737,13 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
// We're done laying out this struct.
bool EraseResult = RecordsBeingLaidOut.erase(Key); (void)EraseResult;
assert(EraseResult && "struct not in RecordsBeingLaidOut set?");
-
+
// If this struct blocked a FunctionType conversion, then recompute whatever
// was derived from that.
// FIXME: This is hugely overconservative.
if (SkippedLayout)
TypeCache.clear();
-
+
// If we're done converting the outer-most record, then convert any deferred
// structs as well.
if (RecordsBeingLaidOut.empty())
@@ -767,14 +792,14 @@ bool CodeGenTypes::isZeroInitializable(QualType T) {
// Records are non-zero-initializable if they contain any
// non-zero-initializable subobjects.
if (const RecordType *RT = T->getAs<RecordType>()) {
- auto RD = cast<RecordDecl>(RT->getDecl());
+ const RecordDecl *RD = RT->getDecl();
return isZeroInitializable(RD);
}
// We have to ask the ABI about member pointers.
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
return getCXXABI().isZeroInitializable(MPT);
-
+
// Everything else is okay.
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
index d082342bf592..626869f00021 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
@@ -140,7 +140,7 @@ class CodeGenTypes {
/// Contains the LLVM IR type for any converted RecordDecl.
llvm::DenseMap<const Type*, llvm::StructType *> RecordDeclTypes;
-
+
/// Hold memoized CGFunctionInfo results.
llvm::FoldingSet<CGFunctionInfo> FunctionInfos;
@@ -149,15 +149,15 @@ class CodeGenTypes {
/// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B'
/// types will be in this set.
llvm::SmallPtrSet<const Type*, 4> RecordsBeingLaidOut;
-
+
llvm::SmallPtrSet<const CGFunctionInfo*, 4> FunctionsBeingProcessed;
-
+
/// True if we didn't layout a function due to a being inside
/// a recursive struct conversion, set this to true.
bool SkippedLayout;
SmallVector<const RecordDecl *, 8> DeferredRecords;
-
+
/// This map keeps cache of llvm::Types and maps clang::Type to
/// corresponding llvm::Type.
llvm::DenseMap<const Type *, llvm::Type *> TypeCache;
@@ -184,7 +184,7 @@ public:
/// ConvertType - Convert type T into a llvm::Type.
llvm::Type *ConvertType(QualType T);
- /// \brief Converts the GlobalDecl into an llvm::Type. This should be used
+ /// Converts the GlobalDecl into an llvm::Type. This should be used
/// when we know the target of the function we want to convert. This is
/// because some functions (explicitly, those with pass_object_size
/// parameters) may not have the same signature as their type portrays, and
@@ -225,7 +225,7 @@ public:
/// replace the 'opaque' type we previously made for it if applicable.
void UpdateCompletedType(const TagDecl *TD);
- /// \brief Remove stale types from the type cache when an inheritance model
+ /// Remove stale types from the type cache when an inheritance model
/// gets assigned to a class.
void RefreshTypeCacheForClass(const CXXRecordDecl *RD);
@@ -313,7 +313,8 @@ public:
const FunctionProtoType *type,
RequiredArgs required,
unsigned numPrefixArgs);
- const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
+ const CGFunctionInfo &
+ arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD);
const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD,
CXXCtorType CT);
const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
@@ -334,7 +335,7 @@ public:
ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
RequiredArgs args);
- /// \brief Compute a new LLVM record layout object for the given record.
+ /// Compute a new LLVM record layout object for the given record.
CGRecordLayout *ComputeRecordLayout(const RecordDecl *D,
llvm::StructType *Ty);
@@ -342,7 +343,7 @@ public:
/// optional suffix and name the given LLVM type using it.
void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty,
StringRef suffix);
-
+
public: // These are internal details of CGT that shouldn't be used externally.
/// ConvertRecordDeclType - Lay out a tagged decl type like struct or union.
@@ -364,7 +365,7 @@ public: // These are internal details of CGT that shouldn't be used externally.
/// IsZeroInitializable - Return whether a record type can be
/// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool isZeroInitializable(const RecordDecl *RD);
-
+
bool isRecordLayoutComplete(const Type *Ty) const;
bool noRecordsBeingLaidOut() const {
return RecordsBeingLaidOut.empty();
@@ -372,7 +373,7 @@ public: // These are internal details of CGT that shouldn't be used externally.
bool isRecordBeingLaidOut(const Type *Ty) const {
return RecordsBeingLaidOut.count(Ty);
}
-
+
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h b/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h
index 90c9fcd8cf81..b4d1b65743c7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h
@@ -50,7 +50,7 @@ public:
: CGM(CGM), CGF(CGF) {}
/// Initialize this emission in the context of the given function.
- /// Use this if the expression might contain contextaul references like
+ /// Use this if the expression might contain contextual references like
/// block addresses or PredefinedExprs.
ConstantEmitter(CodeGenFunction &CGF)
: CGM(CGF.CGM), CGF(&CGF) {}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp
index 7f8d80985032..59e66b88fb01 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp
@@ -166,7 +166,7 @@ void ConstantAggregateBuilderBase::getGEPIndicesTo(
if (Parent) {
Parent->getGEPIndicesTo(indices, Begin);
- // Otherwise, add an index to drill into the first level of pointer.
+ // Otherwise, add an index to drill into the first level of pointer.
} else {
assert(indices.empty());
indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
index 89a30dc7040c..2d8446463594 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -35,14 +35,14 @@ void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
namespace {
-/// \brief A region of source code that can be mapped to a counter.
+/// A region of source code that can be mapped to a counter.
class SourceMappingRegion {
Counter Count;
- /// \brief The region's starting location.
+ /// The region's starting location.
Optional<SourceLocation> LocStart;
- /// \brief The region's ending location.
+ /// The region's ending location.
Optional<SourceLocation> LocEnd;
/// Whether this region should be emitted after its parent is emitted.
@@ -74,7 +74,10 @@ public:
bool hasEndLoc() const { return LocEnd.hasValue(); }
- void setEndLoc(SourceLocation Loc) { LocEnd = Loc; }
+ void setEndLoc(SourceLocation Loc) {
+ assert(Loc.isValid() && "Setting an invalid end location");
+ LocEnd = Loc;
+ }
SourceLocation getEndLoc() const {
assert(LocEnd && "Region has no end location");
@@ -123,7 +126,7 @@ struct SpellingRegion {
}
};
-/// \brief Provides the common functionality for the different
+/// Provides the common functionality for the different
/// coverage mapping region builders.
class CoverageMappingBuilder {
public:
@@ -132,17 +135,17 @@ public:
const LangOptions &LangOpts;
private:
- /// \brief Map of clang's FileIDs to IDs used for coverage mapping.
+ /// Map of clang's FileIDs to IDs used for coverage mapping.
llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
FileIDMapping;
public:
- /// \brief The coverage mapping regions for this function
+ /// The coverage mapping regions for this function
llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
- /// \brief The source mapping regions for this function.
+ /// The source mapping regions for this function.
std::vector<SourceMappingRegion> SourceRegions;
- /// \brief A set of regions which can be used as a filter.
+ /// A set of regions which can be used as a filter.
///
/// It is produced by emitExpansionRegions() and is used in
/// emitSourceRegions() to suppress producing code regions if
@@ -154,7 +157,7 @@ public:
const LangOptions &LangOpts)
: CVM(CVM), SM(SM), LangOpts(LangOpts) {}
- /// \brief Return the precise end location for the given token.
+ /// Return the precise end location for the given token.
SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
// We avoid getLocForEndOfToken here, because it doesn't do what we want for
// macro locations, which we just treat as expanded files.
@@ -163,14 +166,14 @@ public:
return Loc.getLocWithOffset(TokLen);
}
- /// \brief Return the start location of an included file or expanded macro.
+ /// Return the start location of an included file or expanded macro.
SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
if (Loc.isMacroID())
return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
return SM.getLocForStartOfFile(SM.getFileID(Loc));
}
- /// \brief Return the end location of an included file or expanded macro.
+ /// Return the end location of an included file or expanded macro.
SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
if (Loc.isMacroID())
return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
@@ -178,18 +181,18 @@ public:
return SM.getLocForEndOfFile(SM.getFileID(Loc));
}
- /// \brief Find out where the current file is included or macro is expanded.
+ /// Find out where the current file is included or macro is expanded.
SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
- return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).first
+ return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
: SM.getIncludeLoc(SM.getFileID(Loc));
}
- /// \brief Return true if \c Loc is a location in a built-in macro.
+ /// Return true if \c Loc is a location in a built-in macro.
bool isInBuiltin(SourceLocation Loc) {
return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
}
- /// \brief Check whether \c Loc is included or expanded from \c Parent.
+ /// Check whether \c Loc is included or expanded from \c Parent.
bool isNestedIn(SourceLocation Loc, FileID Parent) {
do {
Loc = getIncludeOrExpansionLoc(Loc);
@@ -199,23 +202,23 @@ public:
return true;
}
- /// \brief Get the start of \c S ignoring macro arguments and builtin macros.
+ /// Get the start of \c S ignoring macro arguments and builtin macros.
SourceLocation getStart(const Stmt *S) {
SourceLocation Loc = S->getLocStart();
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
- Loc = SM.getImmediateExpansionRange(Loc).first;
+ Loc = SM.getImmediateExpansionRange(Loc).getBegin();
return Loc;
}
- /// \brief Get the end of \c S ignoring macro arguments and builtin macros.
+ /// Get the end of \c S ignoring macro arguments and builtin macros.
SourceLocation getEnd(const Stmt *S) {
SourceLocation Loc = S->getLocEnd();
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
- Loc = SM.getImmediateExpansionRange(Loc).first;
+ Loc = SM.getImmediateExpansionRange(Loc).getBegin();
return getPreciseTokenLocEnd(Loc);
}
- /// \brief Find the set of files we have regions for and assign IDs
+ /// Find the set of files we have regions for and assign IDs
///
/// Fills \c Mapping with the virtual file mapping needed to write out
/// coverage and collects the necessary file information to emit source and
@@ -255,7 +258,7 @@ public:
}
}
- /// \brief Get the coverage mapping file ID for \c Loc.
+ /// Get the coverage mapping file ID for \c Loc.
///
/// If such file id doesn't exist, return None.
Optional<unsigned> getCoverageFileID(SourceLocation Loc) {
@@ -265,7 +268,7 @@ public:
return None;
}
- /// \brief Gather all the regions that were skipped by the preprocessor
+ /// Gather all the regions that were skipped by the preprocessor
/// using the constructs like #if.
void gatherSkippedRegions() {
/// An array of the minimum lineStarts and the maximum lineEnds
@@ -295,14 +298,14 @@ public:
auto Region = CounterMappingRegion::makeSkipped(
*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.
+ // the source code of this function.
if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
Region.LineEnd <= FileLineRanges[*CovFileID].second)
MappingRegions.push_back(Region);
}
}
- /// \brief Generate the coverage counter mapping regions from collected
+ /// Generate the coverage counter mapping regions from collected
/// source regions.
void emitSourceRegions(const SourceRegionFilter &Filter) {
for (const auto &Region : SourceRegions) {
@@ -347,7 +350,7 @@ public:
}
}
- /// \brief Generate expansion regions for each virtual file we've seen.
+ /// Generate expansion regions for each virtual file we've seen.
SourceRegionFilter emitExpansionRegions() {
SourceRegionFilter Filter;
for (const auto &FM : FileIDMapping) {
@@ -377,7 +380,7 @@ public:
}
};
-/// \brief Creates unreachable coverage regions for the functions that
+/// Creates unreachable coverage regions for the functions that
/// are not emitted.
struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
@@ -411,7 +414,7 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
SourceRegions.emplace_back(Counter(), Start, End);
}
- /// \brief Write the mapping data to the output stream
+ /// Write the mapping data to the output stream
void write(llvm::raw_ostream &OS) {
SmallVector<unsigned, 16> FileIDMapping;
gatherFileIDs(FileIDMapping);
@@ -425,15 +428,15 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
}
};
-/// \brief A StmtVisitor that creates coverage mapping regions which map
+/// A StmtVisitor that creates coverage mapping regions which map
/// from the source code locations to the PGO counters.
struct CounterCoverageMappingBuilder
: public CoverageMappingBuilder,
public ConstStmtVisitor<CounterCoverageMappingBuilder> {
- /// \brief The map of statements to count values.
+ /// The map of statements to count values.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
- /// \brief A stack of currently live regions.
+ /// A stack of currently live regions.
std::vector<SourceMappingRegion> RegionStack;
/// The currently deferred region: its end location and count can be set once
@@ -442,7 +445,7 @@ struct CounterCoverageMappingBuilder
CounterExpressionBuilder Builder;
- /// \brief A location in the most recently visited file or macro.
+ /// A location in the most recently visited file or macro.
///
/// This is used to adjust the active source regions appropriately when
/// expressions cross file or macro boundaries.
@@ -451,12 +454,12 @@ struct CounterCoverageMappingBuilder
/// 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
+ /// Return a counter for the subtraction of \c RHS from \c LHS
Counter subtractCounters(Counter LHS, Counter RHS) {
return Builder.subtract(LHS, RHS);
}
- /// \brief Return a counter for the sum of \c LHS and \c RHS.
+ /// Return a counter for the sum of \c LHS and \c RHS.
Counter addCounters(Counter LHS, Counter RHS) {
return Builder.add(LHS, RHS);
}
@@ -465,14 +468,14 @@ struct CounterCoverageMappingBuilder
return addCounters(addCounters(C1, C2), C3);
}
- /// \brief Return the region counter for the given statement.
+ /// Return the region counter for the given statement.
///
/// This should only be called on statements that have a dedicated counter.
Counter getRegionCounter(const Stmt *S) {
return Counter::getCounter(CounterMap[S]);
}
- /// \brief Push a region onto the stack.
+ /// Push a region onto the stack.
///
/// Returns the index on the stack where the region was pushed. This can be
/// used with popRegions to exit a "scope", ending the region that was pushed.
@@ -549,7 +552,7 @@ struct CounterCoverageMappingBuilder
completeDeferred(Count, DeferredEndLoc);
}
- /// \brief Pop regions from the stack into the function's list of regions.
+ /// 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.
@@ -616,13 +619,13 @@ struct CounterCoverageMappingBuilder
assert(!ParentOfDeferredRegion && "Deferred region with no parent");
}
- /// \brief Return the currently active region.
+ /// Return the currently active region.
SourceMappingRegion &getRegion() {
assert(!RegionStack.empty() && "statement has no region");
return RegionStack.back();
}
- /// \brief Propagate counts through the children of \c S.
+ /// Propagate counts through the children of \c S.
Counter propagateCounts(Counter TopCount, const Stmt *S) {
SourceLocation StartLoc = getStart(S);
SourceLocation EndLoc = getEnd(S);
@@ -639,7 +642,7 @@ struct CounterCoverageMappingBuilder
return ExitCount;
}
- /// \brief Check whether a region with bounds \c StartLoc and \c EndLoc
+ /// Check whether a region with bounds \c StartLoc and \c EndLoc
/// is already added to \c SourceRegions.
bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) {
return SourceRegions.rend() !=
@@ -650,7 +653,7 @@ struct CounterCoverageMappingBuilder
});
}
- /// \brief Adjust the most recently visited location to \c EndLoc.
+ /// Adjust the most recently visited location to \c EndLoc.
///
/// This should be used after visiting any statements in non-source order.
void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
@@ -667,7 +670,7 @@ struct CounterCoverageMappingBuilder
MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
}
- /// \brief Adjust regions and state when \c NewLoc exits a file.
+ /// Adjust regions and state when \c NewLoc exits a file.
///
/// If moving from our most recently tracked location to \c NewLoc exits any
/// files, this adjusts our current region stack and creates the file regions
@@ -734,7 +737,7 @@ struct CounterCoverageMappingBuilder
MostRecentLocation = NewLoc;
}
- /// \brief Ensure that \c S is included in the current region.
+ /// Ensure that \c S is included in the current region.
void extendRegion(const Stmt *S) {
SourceMappingRegion &Region = getRegion();
SourceLocation StartLoc = getStart(S);
@@ -746,7 +749,7 @@ struct CounterCoverageMappingBuilder
completeDeferred(Region.getCounter(), StartLoc);
}
- /// \brief Mark \c S as a terminator, starting a zero region.
+ /// Mark \c S as a terminator, starting a zero region.
void terminateRegion(const Stmt *S) {
extendRegion(S);
SourceMappingRegion &Region = getRegion();
@@ -791,7 +794,7 @@ struct CounterCoverageMappingBuilder
popRegions(Index);
}
- /// \brief Keep counts of breaks and continues inside loops.
+ /// Keep counts of breaks and continues inside loops.
struct BreakContinue {
Counter BreakCount;
Counter ContinueCount;
@@ -805,7 +808,7 @@ struct CounterCoverageMappingBuilder
: CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
DeferredRegion(None) {}
- /// \brief Write the mapping data to the output stream
+ /// Write the mapping data to the output stream
void write(llvm::raw_ostream &OS) {
llvm::SmallVector<unsigned, 8> VirtualFileMapping;
gatherFileIDs(VirtualFileMapping);
@@ -831,22 +834,6 @@ 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");
@@ -856,17 +843,13 @@ struct CounterCoverageMappingBuilder
if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
return;
- Counter ExitCount = propagateCounts(getRegionCounter(Body), Body);
+ 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)));
- }
+ // Discard the last uncompleted deferred region in a decl, if one exists.
+ // This prevents lines at the end of a function containing only whitespace
+ // or closing braces from being marked as uncovered.
+ DeferredRegion = None;
}
void VisitReturnStmt(const ReturnStmt *S) {
@@ -889,6 +872,7 @@ struct CounterCoverageMappingBuilder
Counter LabelCount = getRegionCounter(S);
SourceLocation Start = getStart(S);
completeTopLevelDeferredRegion(LabelCount, Start);
+ completeDeferred(LabelCount, Start);
// We can't extendRegion here or we risk overlapping with our new region.
handleFileExit(Start);
pushRegion(LabelCount, Start);
@@ -979,20 +963,28 @@ struct CounterCoverageMappingBuilder
Counter ParentCount = getRegion().getCounter();
Counter BodyCount = getRegionCounter(S);
+ // The loop increment may contain a break or continue.
+ if (S->getInc())
+ BreakContinueStack.emplace_back();
+
// Handle the body first so that we can get the backedge count.
- BreakContinueStack.push_back(BreakContinue());
+ BreakContinueStack.emplace_back();
extendRegion(S->getBody());
Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
- BreakContinue BC = BreakContinueStack.pop_back_val();
+ BreakContinue BodyBC = BreakContinueStack.pop_back_val();
// The increment is essentially part of the body but it needs to include
// the count for all the continue statements.
- if (const Stmt *Inc = S->getInc())
- propagateCounts(addCounters(BackedgeCount, BC.ContinueCount), Inc);
+ BreakContinue IncrementBC;
+ if (const Stmt *Inc = S->getInc()) {
+ propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
+ IncrementBC = BreakContinueStack.pop_back_val();
+ }
// Go back to handle the condition.
- Counter CondCount =
- addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+ Counter CondCount = addCounters(
+ addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
+ IncrementBC.ContinueCount);
if (const Expr *Cond = S->getCond()) {
propagateCounts(CondCount, Cond);
adjustForOutOfOrderTraversal(getEnd(S));
@@ -1004,8 +996,8 @@ struct CounterCoverageMappingBuilder
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
- Counter OutCount =
- addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
+ Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
+ subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount)
pushRegion(OutCount);
}
@@ -1361,8 +1353,7 @@ void CoverageMappingModuleGen::emit() {
// and coverage mappings is a multiple of 8.
if (size_t Rem = OS.str().size() % 8) {
CoverageMappingSize += 8 - Rem;
- for (size_t I = 0, S = 8 - Rem; I < S; ++I)
- OS << '\0';
+ OS.write_zeros(8 - Rem);
}
auto *FilenamesAndMappingsVal =
llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
index d07ed5ebcf2b..b08ad896d7a5 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
@@ -31,7 +31,7 @@ class Preprocessor;
class Decl;
class Stmt;
-/// \brief Stores additional source code information like skipped ranges which
+/// Stores additional source code information like skipped ranges which
/// is required by the coverage mapping generator and is obtained from
/// the preprocessor.
class CoverageSourceInfo : public PPCallbacks {
@@ -46,7 +46,7 @@ namespace CodeGen {
class CodeGenModule;
-/// \brief Organizes the cross-function state that is used while generating
+/// Organizes the cross-function state that is used while generating
/// code coverage mapping data.
class CoverageMappingModuleGen {
CodeGenModule &CGM;
@@ -65,7 +65,7 @@ public:
return SourceInfo;
}
- /// \brief Add a function's coverage mapping record to the collection of the
+ /// Add a function's coverage mapping record to the collection of the
/// function mapping records.
void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
StringRef FunctionNameValue,
@@ -73,15 +73,15 @@ public:
const std::string &CoverageMapping,
bool IsUsed = true);
- /// \brief Emit the coverage mapping data for a translation unit.
+ /// Emit the coverage mapping data for a translation unit.
void emit();
- /// \brief Return the coverage mapping translation unit file id
+ /// Return the coverage mapping translation unit file id
/// for the given file.
unsigned getFileID(const FileEntry *File);
};
-/// \brief Organizes the per-function state that is used while generating
+/// Organizes the per-function state that is used while generating
/// code coverage mapping data.
class CoverageMappingGen {
CoverageMappingModuleGen &CVM;
@@ -99,12 +99,12 @@ public:
llvm::DenseMap<const Stmt *, unsigned> *CounterMap)
: CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap) {}
- /// \brief Emit the coverage mapping data which maps the regions of
+ /// Emit the coverage mapping data which maps the regions of
/// code to counters that will be used to find the execution
/// counts for those regions.
void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);
- /// \brief Emit the coverage mapping data for an unused function.
+ /// Emit the coverage mapping data for an unused function.
/// It creates mapping regions with the counter of zero.
void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
index a3c2766dbb49..00fff144b597 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -31,9 +31,11 @@
#include "clang/AST/StmtCXX.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/ScopedPrinter.h"
using namespace clang;
using namespace CodeGen;
@@ -63,13 +65,6 @@ public:
bool classifyReturnType(CGFunctionInfo &FI) const override;
bool passClassIndirect(const CXXRecordDecl *RD) const {
- // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
- // The PS4 platform ABI follows the behavior of Clang 3.2.
- if (CGM.getCodeGenOpts().getClangABICompat() <=
- CodeGenOptions::ClangABI::Ver4 ||
- CGM.getTriple().getOS() == llvm::Triple::PS4)
- return RD->hasNonTrivialDestructor() ||
- RD->hasNonTrivialCopyConstructor();
return !canCopyArgument(RD);
}
@@ -187,8 +182,7 @@ public:
emitTerminateForUnexpectedException(CodeGenFunction &CGF,
llvm::Value *Exn) override;
- void EmitFundamentalRTTIDescriptor(QualType Type, bool DLLExport);
- void EmitFundamentalRTTIDescriptors(bool DLLExport);
+ void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
CatchTypeInfo
getAddrOfCXXCatchHandlerType(QualType Ty,
@@ -300,16 +294,11 @@ 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);
+ CGM.setGVProperties(Thunk, GD);
}
+ bool exportThunk() override { return true; }
+
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
const ThisAdjustment &TA) override;
@@ -480,6 +469,7 @@ public:
explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)
: ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
/*UseARMGuardVarABI=*/true) {}
+ void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
private:
bool HasThisReturn(GlobalDecl GD) const override {
@@ -632,13 +622,53 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
}
- VTable = Builder.CreateGEP(VTable, VTableOffset);
+ // Compute the address of the virtual function pointer.
+ llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);
+
+ // Check the address of the function pointer if CFI on member function
+ // pointers is enabled.
+ llvm::Constant *CheckSourceLocation;
+ llvm::Constant *CheckTypeDesc;
+ bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&
+ CGM.HasHiddenLTOVisibility(RD);
+ if (ShouldEmitCFICheck) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+
+ CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getLocStart());
+ CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0));
+ llvm::Constant *StaticData[] = {
+ llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
+ CheckSourceLocation,
+ CheckTypeDesc,
+ };
+
+ llvm::Metadata *MD =
+ CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
+ llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
+
+ llvm::Value *TypeTest = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {VFPAddr, TypeId});
+
+ if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
+ CGF.EmitTrapCheck(TypeTest);
+ } else {
+ llvm::Value *AllVtables = llvm::MetadataAsValue::get(
+ CGM.getLLVMContext(),
+ llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
+ llvm::Value *ValidVtable = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
+ CGF.EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIMFCall),
+ SanitizerHandler::CFICheckFail, StaticData,
+ {VTable, ValidVtable});
+ }
+
+ FnVirtual = Builder.GetInsertBlock();
+ }
// Load the virtual function to call.
- VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
- llvm::Value *VirtualFn =
- Builder.CreateAlignedLoad(VTable, CGF.getPointerAlign(),
- "memptr.virtualfn");
+ VFPAddr = Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo());
+ llvm::Value *VirtualFn = Builder.CreateAlignedLoad(
+ VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn");
CGF.EmitBranch(FnEnd);
// In the non-virtual path, the function pointer is actually a
@@ -647,6 +677,43 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
llvm::Value *NonVirtualFn =
Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
+ // Check the function pointer if CFI on member function pointers is enabled.
+ if (ShouldEmitCFICheck) {
+ CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ if (RD->hasDefinition()) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+
+ llvm::Constant *StaticData[] = {
+ llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
+ CheckSourceLocation,
+ CheckTypeDesc,
+ };
+
+ llvm::Value *Bit = Builder.getFalse();
+ llvm::Value *CastedNonVirtualFn =
+ Builder.CreateBitCast(NonVirtualFn, CGF.Int8PtrTy);
+ for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
+ llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
+ getContext().getMemberPointerType(
+ MPT->getPointeeType(),
+ getContext().getRecordType(Base).getTypePtr()));
+ llvm::Value *TypeId =
+ llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
+
+ llvm::Value *TypeTest =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
+ {CastedNonVirtualFn, TypeId});
+ Bit = Builder.CreateOr(Bit, TypeTest);
+ }
+
+ CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall),
+ SanitizerHandler::CFICheckFail, StaticData,
+ {CastedNonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});
+
+ FnNonVirtual = Builder.GetInsertBlock();
+ }
+ }
+
// We're done.
CGF.EmitBlock(FnEnd);
llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
@@ -836,7 +903,6 @@ ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
CharUnits ThisAdjustment) {
assert(MD->isInstance() && "Member function must not be static!");
- MD = MD->getCanonicalDecl();
CodeGenTypes &Types = CGM.getTypes();
@@ -1182,7 +1248,7 @@ static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
}
-/// \brief Compute the src2dst_offset hint as described in the
+/// Compute the src2dst_offset hint as described in the
/// Itanium C++ ABI [2.9.7]
static CharUnits computeOffsetHint(ASTContext &Context,
const CXXRecordDecl *Src,
@@ -1448,7 +1514,7 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
return;
/// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
- /// adjustments are required, becuase they are all handled by thunks.
+ /// adjustments are required, because they are all handled by thunks.
setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
/// Initialize the 'vtt' slot if needed.
@@ -1479,8 +1545,7 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(
llvm::Value *VTT =
CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
- Args.insert(Args.begin() + 1,
- CallArg(RValue::get(VTT), VTTTy, /*needscopy=*/false));
+ Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy));
return AddedStructorArgs::prefix(1); // Added one arg.
}
@@ -1531,7 +1596,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
// Set the right visibility.
- CGM.setGlobalVisibility(VTable, RD, ForDefinition);
+ CGM.setGVProperties(VTable, RD);
// 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
@@ -1548,7 +1613,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
DC->getParent()->isTranslationUnit())
- EmitFundamentalRTTIDescriptors(RD->hasAttr<DLLExportAttr>());
+ EmitFundamentalRTTIDescriptors(RD);
if (!VTable->isDeclarationForLinker())
CGM.EmitVTableTypeMetadata(VTable, VTLayout);
@@ -1641,12 +1706,8 @@ 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);
- else if (RD->hasAttr<DLLExportAttr>())
- VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(VTable, RD);
return VTable;
}
@@ -1656,7 +1717,6 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
Address This,
llvm::Type *Ty,
SourceLocation Loc) {
- GD = GD.getCanonicalDecl();
Ty = Ty->getPointerTo()->getPointerTo();
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent());
@@ -1690,7 +1750,7 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
VFunc = VFuncLoad;
}
- CGCallee Callee(MethodDecl, VFunc);
+ CGCallee Callee(MethodDecl->getCanonicalDecl(), VFunc);
return Callee;
}
@@ -1702,10 +1762,9 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, getFromDtorType(DtorType));
- llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
+ llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
CGCallee Callee =
- getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty,
- CE ? CE->getLocStart() : SourceLocation());
+ CGCallee::forVirtual(CE, GlobalDecl(Dtor, DtorType), This, Ty);
CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(),
This.getPointer(), /*ImplicitParam=*/nullptr,
@@ -1725,11 +1784,19 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
if (CGM.getLangOpts().AppleKext)
return false;
- // If we don't have any not emitted inline virtual function, and if vtable is
- // not hidden, then we are safe to emit available_externally copy of vtable.
+ // If the vtable is hidden then it is not safe to emit an available_externally
+ // copy of vtable.
+ if (isVTableHidden(RD))
+ return false;
+
+ if (CGM.getCodeGenOpts().ForceEmitVTables)
+ return true;
+
+ // If we don't have any not emitted inline virtual function then we are safe
+ // to emit an available_externally copy of vtable.
// FIXME we can still emit a copy of the vtable if we
// can emit definition of the inline functions.
- return !hasAnyUnusedVirtualInlineFunction(RD) && !isVTableHidden(RD);
+ return !hasAnyUnusedVirtualInlineFunction(RD);
}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
Address InitialPtr,
@@ -1848,7 +1915,8 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
// Handle the array cookie specially in ASan.
if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
- expr->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+ (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
+ CGM.getCodeGenOpts().SanitizeAddressPoisonClassMemberArrayNewCookie)) {
// The store to the CookiePtr does not need to be instrumented.
CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI);
llvm::FunctionType *FTy =
@@ -2052,6 +2120,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
false, var->getLinkage(),
llvm::ConstantInt::get(guardTy, 0),
guardName.str());
+ guard->setDSOLocal(var->isDSOLocal());
guard->setVisibility(var->getVisibility());
// If the variable is thread-local, so is its guard variable.
guard->setThreadLocalMode(var->getThreadLocalMode());
@@ -2211,6 +2280,13 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ if (!addr)
+ // addr is null when we are trying to register a dtor annotated with
+ // __attribute__((destructor)) in a constructor function. Using null here is
+ // okay because this argument is just passed back to the destructor
+ // function.
+ addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
+
llvm::Value *args[] = {
llvm::ConstantExpr::getBitCast(dtor, dtorTy),
llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy),
@@ -2219,6 +2295,48 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
CGF.EmitNounwindRuntimeCall(atexit, args);
}
+void CodeGenModule::registerGlobalDtorsWithAtExit() {
+ for (const auto I : DtorsUsingAtExit) {
+ int Priority = I.first;
+ const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
+
+ // Create a function that registers destructors that have the same priority.
+ //
+ // Since constructor functions are run in non-descending order of their
+ // priorities, destructors are registered in non-descending order of their
+ // priorities, and since destructor functions are run in the reverse order
+ // of their registration, destructor functions are run in non-ascending
+ // order of their priorities.
+ CodeGenFunction CGF(*this);
+ std::string GlobalInitFnName =
+ std::string("__GLOBAL_init_") + llvm::to_string(Priority);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ llvm::Function *GlobalInitFn = CreateGlobalInitOrDestructFunction(
+ FTy, GlobalInitFnName, getTypes().arrangeNullaryFunction(),
+ SourceLocation());
+ ASTContext &Ctx = getContext();
+ FunctionDecl *FD = FunctionDecl::Create(
+ Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
+ &Ctx.Idents.get(GlobalInitFnName), Ctx.VoidTy, nullptr, SC_Static,
+ false, false);
+ CGF.StartFunction(GlobalDecl(FD), getContext().VoidTy, GlobalInitFn,
+ getTypes().arrangeNullaryFunction(), FunctionArgList(),
+ SourceLocation(), SourceLocation());
+
+ for (auto *Dtor : Dtors) {
+ // Register the destructor function calling __cxa_atexit if it is
+ // available. Otherwise fall back on calling atexit.
+ if (getCodeGenOpts().CXAAtExit)
+ emitGlobalDtorWithCXAAtExit(CGF, Dtor, nullptr, false);
+ else
+ CGF.registerGlobalDtorWithAtExit(Dtor);
+ }
+
+ CGF.FinishFunction();
+ AddGlobalCtor(GlobalInitFn, Priority, nullptr);
+ }
+}
+
/// Register a global destructor as best as we know how.
void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
@@ -2407,8 +2525,10 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
CGM.SetLLVMFunctionAttributes(nullptr, FI, cast<llvm::Function>(Init));
}
- if (Init)
+ if (Init) {
Init->setVisibility(Var->getVisibility());
+ Init->setDSOLocal(Var->isDSOLocal());
+ }
llvm::LLVMContext &Context = CGM.getModule().getContext();
llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
@@ -2416,8 +2536,12 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
if (InitIsInitFunc) {
if (Init) {
llvm::CallInst *CallVal = Builder.CreateCall(Init);
- if (isThreadWrapperReplaceable(VD, CGM))
+ if (isThreadWrapperReplaceable(VD, CGM)) {
CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
+ llvm::Function *Fn =
+ cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
+ Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
+ }
}
} else {
// Don't know whether we have an init function. Call it if it exists.
@@ -2574,12 +2698,16 @@ public:
BCTI_Public = 0x2
};
+ /// BuildTypeInfo - Build the RTTI type info struct for the given type, or
+ /// link to an existing RTTI descriptor if one already exists.
+ llvm::Constant *BuildTypeInfo(QualType Ty);
+
/// BuildTypeInfo - Build the RTTI type info struct for the given type.
- ///
- /// \param Force - true to force the creation of this RTTI value
- /// \param DLLExport - true to mark the RTTI value as DLLExport
- llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false,
- bool DLLExport = false);
+ llvm::Constant *BuildTypeInfo(
+ QualType Ty,
+ llvm::GlobalVariable::LinkageTypes Linkage,
+ llvm::GlobalValue::VisibilityTypes Visibility,
+ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
};
}
@@ -2622,11 +2750,8 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
/*Constant=*/true,
llvm::GlobalValue::ExternalLinkage, nullptr,
Name);
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (RD->hasAttr<DLLImportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- }
+ const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ CGM.setGVProperties(GV, RD);
}
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
@@ -2673,6 +2798,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::LongDouble:
case BuiltinType::Float16:
case BuiltinType::Float128:
+ case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Int128:
@@ -2687,6 +2813,30 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
return false;
case BuiltinType::Dependent:
@@ -2958,6 +3108,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
llvm::Constant *VTable =
CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
+ CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
llvm::Type *PtrDiffTy =
CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
@@ -2971,7 +3122,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
Fields.push_back(VTable);
}
-/// \brief Return the linkage that the type info and type info name constants
+/// Return the linkage that the type info and type info name constants
/// should have for the given type.
static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
QualType Ty) {
@@ -3025,8 +3176,7 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
llvm_unreachable("Invalid linkage!");
}
-llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
- bool DLLExport) {
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
// We want to operate on the canonical type.
Ty = Ty.getCanonicalType();
@@ -3044,17 +3194,41 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
}
// Check if there is already an external RTTI descriptor for this type.
- bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
- if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
+ if (IsStandardLibraryRTTIDescriptor(Ty) ||
+ ShouldUseExternalRTTIDescriptor(CGM, Ty))
return GetAddrOfExternalRTTIDescriptor(Ty);
// Emit the standard library with external linkage.
- llvm::GlobalVariable::LinkageTypes Linkage;
- if (IsStdLib)
- Linkage = llvm::GlobalValue::ExternalLinkage;
+ llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
+
+ // Give the type_info object and name the formal visibility of the
+ // type itself.
+ llvm::GlobalValue::VisibilityTypes llvmVisibility;
+ if (llvm::GlobalValue::isLocalLinkage(Linkage))
+ // If the linkage is local, only default visibility makes sense.
+ llvmVisibility = llvm::GlobalValue::DefaultVisibility;
+ else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==
+ ItaniumCXXABI::RUK_NonUniqueHidden)
+ llvmVisibility = llvm::GlobalValue::HiddenVisibility;
else
- Linkage = getTypeInfoLinkage(CGM, Ty);
+ llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
+ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
+ llvm::GlobalValue::DefaultStorageClass;
+ if (CGM.getTriple().isWindowsItaniumEnvironment()) {
+ auto RD = Ty->getAsCXXRecordDecl();
+ if (RD && RD->hasAttr<DLLExportAttr>())
+ DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
+ }
+
+ return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);
+}
+
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
+ QualType Ty,
+ llvm::GlobalVariable::LinkageTypes Linkage,
+ llvm::GlobalValue::VisibilityTypes Visibility,
+ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
// Add the vtable pointer.
BuildVTablePointer(cast<Type>(Ty));
@@ -3168,7 +3342,11 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
llvm::Module &M = CGM.getModule();
+ llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(M, Init->getType(),
/*Constant=*/true, Linkage, Init, Name);
@@ -3200,37 +3378,14 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
// All of this is to say that it's important that both the type_info
// object and the type_info name be uniqued when weakly emitted.
- // Give the type_info object and name the formal visibility of the
- // type itself.
- llvm::GlobalValue::VisibilityTypes llvmVisibility;
- if (llvm::GlobalValue::isLocalLinkage(Linkage))
- // If the linkage is local, only default visibility makes sense.
- llvmVisibility = llvm::GlobalValue::DefaultVisibility;
- else if (RTTIUniqueness == ItaniumCXXABI::RUK_NonUniqueHidden)
- llvmVisibility = llvm::GlobalValue::HiddenVisibility;
- else
- llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
+ TypeName->setVisibility(Visibility);
+ CGM.setDSOLocal(TypeName);
- TypeName->setVisibility(llvmVisibility);
- GV->setVisibility(llvmVisibility);
+ GV->setVisibility(Visibility);
+ CGM.setDSOLocal(GV);
- if (CGM.getTriple().isWindowsItaniumEnvironment()) {
- auto RD = Ty->getAsCXXRecordDecl();
- if (DLLExport || (RD && RD->hasAttr<DLLExportAttr>())) {
- TypeName->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- } else if (RD && RD->hasAttr<DLLImportAttr>() &&
- ShouldUseExternalRTTIDescriptor(CGM, Ty)) {
- TypeName->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
-
- // Because the typename and the typeinfo are DLL import, convert them to
- // declarations rather than definitions. The initializers still need to
- // be constructed to calculate the type for the declarations.
- TypeName->setInitializer(nullptr);
- GV->setInitializer(nullptr);
- }
- }
+ TypeName->setDLLStorageClass(DLLStorageClass);
+ GV->setDLLStorageClass(DLLStorageClass);
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
}
@@ -3438,11 +3593,9 @@ static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
if (auto *Proto = Type->getAs<FunctionProtoType>()) {
- if (Proto->isNothrow(Ctx)) {
+ if (Proto->isNothrow()) {
Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
- Type = Ctx.getFunctionType(
- Proto->getReturnType(), Proto->getParamTypes(),
- Proto->getExtProtoInfo().withExceptionSpec(EST_None));
+ Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
}
}
@@ -3507,18 +3660,7 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
}
-void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type,
- bool DLLExport) {
- QualType PointerType = getContext().getPointerType(Type);
- QualType PointerTypeConst = getContext().getPointerType(Type.withConst());
- ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, /*Force=*/true, DLLExport);
- ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, /*Force=*/true,
- DLLExport);
- ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, /*Force=*/true,
- DLLExport);
-}
-
-void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) {
+void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
// Types added here must also be added to TypeInfoIsInStandardLibrary.
QualType FundamentalTypes[] = {
getContext().VoidTy, getContext().NullPtrTy,
@@ -3532,10 +3674,24 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) {
getContext().UnsignedInt128Ty, getContext().HalfTy,
getContext().FloatTy, getContext().DoubleTy,
getContext().LongDoubleTy, getContext().Float128Ty,
- getContext().Char16Ty, getContext().Char32Ty
+ getContext().Char8Ty, getContext().Char16Ty,
+ getContext().Char32Ty
};
- for (const QualType &FundamentalType : FundamentalTypes)
- EmitFundamentalRTTIDescriptor(FundamentalType, DLLExport);
+ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
+ RD->hasAttr<DLLExportAttr>()
+ ? llvm::GlobalValue::DLLExportStorageClass
+ : llvm::GlobalValue::DefaultStorageClass;
+ llvm::GlobalValue::VisibilityTypes Visibility =
+ CodeGenModule::GetLLVMVisibility(RD->getVisibility());
+ for (const QualType &FundamentalType : FundamentalTypes) {
+ QualType PointerType = getContext().getPointerType(FundamentalType);
+ QualType PointerTypeConst = getContext().getPointerType(
+ FundamentalType.withConst());
+ for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(
+ Type, llvm::GlobalValue::ExternalLinkage,
+ Visibility, DLLStorageClass);
+ }
}
/// What sort of uniqueness rules should we use for the RTTI for the
@@ -3621,6 +3777,9 @@ static void emitConstructorDestructorAlias(CodeGenModule &CGM,
// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);
+ // Constructors and destructors are always unnamed_addr.
+ Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
// Switch any previous uses to the alias.
if (Entry) {
assert(Entry->getType() == Aliasee->getType() &&
@@ -3633,7 +3792,7 @@ static void emitConstructorDestructorAlias(CodeGenModule &CGM,
}
// Finally, set up the alias with its proper name and attributes.
- CGM.setAliasAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
+ CGM.SetCommonAttributes(AliasDecl, Alias);
}
void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
@@ -3909,7 +4068,9 @@ static void InitCatchParam(CodeGenFunction &CGF,
llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
caughtExnAlignment);
- CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);
+ LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType);
+ LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType);
+ CGF.EmitAggregateCopy(Dest, Src, CatchType, AggValueSlot::DoesNotOverlap);
return;
}
@@ -3936,7 +4097,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
AggValueSlot::forAddr(ParamAddr, Qualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
// Leave the terminate scope.
CGF.EHStack.popTerminate();
@@ -4056,3 +4218,11 @@ ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *RD) {
return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD};
}
+
+void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
+ const CXXCatchStmt *C) {
+ if (CGF.getTarget().hasFeature("exception-handling"))
+ CGF.EHStack.pushCleanup<CatchRetScope>(
+ NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad));
+ ItaniumCXXABI::emitBeginCatch(CGF, C);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp
index a6f21d8ddcfb..48dea7d54b1e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp
@@ -178,7 +178,8 @@ void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
void MacroPPCallbacks::InclusionDirective(
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
- StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
+ StringRef SearchPath, StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
// Record the line location of the current included file.
LastHashLoc = HashLoc;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h b/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h
index e117f96f47df..48c67e2d36ad 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h
@@ -101,7 +101,8 @@ public:
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override;
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
/// Hook called whenever a macro definition is seen.
void MacroDefined(const Token &MacroNameTok,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index ffb3681c2585..059adb78ca30 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -165,7 +165,7 @@ public:
llvm::BasicBlock *
EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD) override;
-
+
llvm::BasicBlock *
EmitDtorCompleteObjectHandler(CodeGenFunction &CGF);
@@ -216,13 +216,20 @@ public:
return DT != Dtor_Base;
}
+ void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const override;
+
+ llvm::GlobalValue::LinkageTypes
+ getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const override;
+
void EmitCXXDestructors(const CXXDestructorDecl *D) override;
const CXXRecordDecl *
getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override {
- MD = MD->getCanonicalDecl();
if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) {
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
// The vbases might be ordered differently in the final overrider object
// and the complete object, so the "this" argument may sometimes point to
@@ -357,9 +364,6 @@ public:
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
GlobalDecl GD, bool ReturnAdjustment) override {
- // Never dllimport/dllexport thunks.
- Thunk->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
-
GVALinkage Linkage =
getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl()));
@@ -371,6 +375,8 @@ public:
Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
}
+ bool exportThunk() override { return false; }
+
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
const ThisAdjustment &TA) override;
@@ -516,10 +522,12 @@ public:
if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name))
return GV;
- return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
- /*isConstant=*/true,
- llvm::GlobalValue::ExternalLinkage,
- /*Initializer=*/nullptr, Name);
+ auto *GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
+ /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, Name);
+ CGM.setDSOLocal(GV);
+ return GV;
}
llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
@@ -558,7 +566,7 @@ private:
GetNullMemberPointerFields(const MemberPointerType *MPT,
llvm::SmallVectorImpl<llvm::Constant *> &fields);
- /// \brief Shared code for virtual base adjustment. Returns the offset from
+ /// Shared code for virtual base adjustment. Returns the offset from
/// the vbptr to the virtual base. Optionally returns the address of the
/// vbptr itself.
llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
@@ -582,14 +590,14 @@ private:
performBaseAdjustment(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy);
- /// \brief Performs a full virtual base adjustment. Used to dereference
+ /// Performs a full virtual base adjustment. Used to dereference
/// pointers to members of virtual bases.
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E,
const CXXRecordDecl *RD, Address Base,
llvm::Value *VirtualBaseAdjustmentOffset,
llvm::Value *VBPtrOffset /* optional */);
- /// \brief Emits a full member pointer with the fields common to data and
+ /// Emits a full member pointer with the fields common to data and
/// function member pointers.
llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
bool IsMemberFunction,
@@ -600,16 +608,15 @@ private:
bool MemberPointerConstantIsNull(const MemberPointerType *MPT,
llvm::Constant *MP);
- /// \brief - Initialize all vbptrs of 'this' with RD as the complete type.
+ /// - Initialize all vbptrs of 'this' with RD as the complete type.
void EmitVBPtrStores(CodeGenFunction &CGF, const CXXRecordDecl *RD);
- /// \brief Caching wrapper around VBTableBuilder::enumerateVBTables().
+ /// Caching wrapper around VBTableBuilder::enumerateVBTables().
const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD);
- /// \brief Generate a thunk for calling a virtual member function MD.
- llvm::Function *EmitVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML);
+ /// Generate a thunk for calling a virtual member function MD.
+ llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ const MethodVFTableLocation &ML);
public:
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
@@ -753,15 +760,15 @@ private:
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
- /// \brief All the vftables that have been referenced.
+ /// All the vftables that have been referenced.
VFTablesMapTy VFTablesMap;
VTablesMapTy VTablesMap;
- /// \brief This set holds the record decls we've deferred vtable emission for.
+ /// This set holds the record decls we've deferred vtable emission for.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
- /// \brief All the vbtables which have been referenced.
+ /// All the vbtables which have been referenced.
llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
/// Info on the global variable used to guard initialization of static locals.
@@ -820,45 +827,8 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
return RAA_Default;
case llvm::Triple::x86_64:
- // If a class has a destructor, we'd really like to pass it indirectly
- // because it allows us to elide copies. Unfortunately, MSVC makes that
- // impossible for small types, which it will pass in a single register or
- // stack slot. Most objects with dtors are large-ish, so handle that early.
- // We can't call out all large objects as being indirect because there are
- // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
- // how we pass large POD types.
- //
- // Note: This permits small classes with nontrivial destructors to be
- // passed in registers, which is non-conforming.
- if (RD->hasNonTrivialDestructor() &&
- getContext().getTypeSize(RD->getTypeForDecl()) > 64)
- return RAA_Indirect;
-
- // If a class has at least one non-deleted, trivial copy constructor, it
- // is passed according to the C ABI. Otherwise, it is passed indirectly.
- //
- // Note: This permits classes with non-trivial copy or move ctors to be
- // passed in registers, so long as they *also* have a trivial copy ctor,
- // which is non-conforming.
- if (RD->needsImplicitCopyConstructor()) {
- // If the copy ctor has not yet been declared, we can read its triviality
- // off the AST.
- if (!RD->defaultedCopyConstructorIsDeleted() &&
- RD->hasTrivialCopyConstructor())
- return RAA_Default;
- } else {
- // Otherwise, we need to find the copy constructor(s) and ask.
- for (const CXXConstructorDecl *CD : RD->ctors()) {
- if (CD->isCopyConstructor()) {
- // We had at least one nondeleted trivial copy ctor. Return directly.
- if (!CD->isDeleted() && CD->isTrivial())
- return RAA_Default;
- }
- }
- }
-
- // We have no trivial, non-deleted copy constructor.
- return RAA_Indirect;
+ case llvm::Triple::aarch64:
+ return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default;
}
llvm_unreachable("invalid enum");
@@ -890,20 +860,6 @@ void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
CGF.EmitRuntimeCallOrInvoke(Fn, Args);
}
-namespace {
-struct CatchRetScope final : EHScopeStack::Cleanup {
- llvm::CatchPadInst *CPI;
-
- CatchRetScope(llvm::CatchPadInst *CPI) : CPI(CPI) {}
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- llvm::BasicBlock *BB = CGF.createBasicBlock("catchret.dest");
- CGF.Builder.CreateCatchRet(CPI, BB);
- CGF.EmitBlock(BB);
- }
-};
-}
-
void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
const CXXCatchStmt *S) {
// In the MS ABI, the runtime handles the copy, and the catch handler is
@@ -1105,10 +1061,22 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
// the second parameter.
FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+
+ // aarch64-windows requires that instance methods use X1 for the return
+ // address. So for aarch64-windows we do not mark the
+ // return as SRet.
+ FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
+ llvm::Triple::aarch64);
return true;
} else if (!RD->isPOD()) {
// If it's a free function, non-POD types are returned indirectly.
FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+
+ // aarch64-windows requires that non-POD, non-instance returns use X0 for
+ // the return address. So for aarch64-windows we do not mark the return as
+ // SRet.
+ FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
+ llvm::Triple::aarch64);
return true;
}
@@ -1155,7 +1123,7 @@ MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) {
CGF.EmitBlock(CallVbaseDtorsBB);
// CGF will put the base dtor calls in this basic block for us later.
-
+
return SkipVbaseDtorsBB;
}
@@ -1182,15 +1150,16 @@ void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
unsigned AS = getThisAddress(CGF).getAddressSpace();
llvm::Value *Int8This = nullptr; // Initialize lazily.
- for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end();
- I != E; ++I) {
+ for (const CXXBaseSpecifier &S : RD->vbases()) {
+ const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
+ auto I = VBaseMap.find(VBase);
+ assert(I != VBaseMap.end());
if (!I->second.hasVtorDisp())
continue;
llvm::Value *VBaseOffset =
- GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, I->first);
- uint64_t ConstantVBaseOffset =
- Layout.getVBaseClassOffset(I->first).getQuantity();
+ GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
+ uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
// vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase).
llvm::Value *VtorDispValue = Builder.CreateSub(
@@ -1233,7 +1202,7 @@ void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
if (!hasDefaultCXXMethodCC(getContext(), D) || D->getNumParams() != 0) {
llvm::Function *Fn = getAddrOfCXXCtorClosure(D, Ctor_DefaultClosure);
Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
- Fn->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(Fn, D);
}
}
@@ -1295,6 +1264,52 @@ MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
return Added;
}
+void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const {
+ // Deleting destructor variants are never imported or exported. Give them the
+ // default storage class.
+ if (DT == Dtor_Deleting) {
+ GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ } else {
+ const NamedDecl *ND = Dtor;
+ CGM.setDLLImportDLLExport(GV, ND);
+ }
+}
+
+llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
+ GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
+ // Internal things are always internal, regardless of attributes. After this,
+ // we know the thunk is externally visible.
+ if (Linkage == GVA_Internal)
+ return llvm::GlobalValue::InternalLinkage;
+
+ switch (DT) {
+ case Dtor_Base:
+ // The base destructor most closely tracks the user-declared constructor, so
+ // we delegate back to the normal declarator case.
+ return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
+ /*isConstantVariable=*/false);
+ case Dtor_Complete:
+ // The complete destructor is like an inline function, but it may be
+ // imported and therefore must be exported as well. This requires changing
+ // the linkage if a DLL attribute is present.
+ if (Dtor->hasAttr<DLLExportAttr>())
+ return llvm::GlobalValue::WeakODRLinkage;
+ if (Dtor->hasAttr<DLLImportAttr>())
+ return llvm::GlobalValue::AvailableExternallyLinkage;
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ case Dtor_Deleting:
+ // Deleting destructors are like inline functions. They have vague linkage
+ // and are emitted everywhere they are used. They are internal if the class
+ // is internal.
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ case Dtor_Comdat:
+ llvm_unreachable("MS C++ ABI does not support comdat dtors");
+ }
+ llvm_unreachable("invalid dtor type");
+}
+
void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
// The TU defining a dtor is only guaranteed to emit a base destructor. All
// other destructor variants are delegating thunks.
@@ -1303,10 +1318,8 @@ void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
CharUnits
MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
- GD = GD.getCanonicalDecl();
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- GlobalDecl LookupGD = GD;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
// Complete destructors take a pointer to the complete object as a
// parameter, thus don't need this adjustment.
@@ -1315,11 +1328,11 @@ MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
// There's no Dtor_Base in vftable but it shares the this adjustment with
// the deleting one, so look it up instead.
- LookupGD = GlobalDecl(DD, Dtor_Deleting);
+ GD = GlobalDecl(DD, Dtor_Deleting);
}
- MicrosoftVTableContext::MethodVFTableLocation ML =
- CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
+ MethodVFTableLocation ML =
+ CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
CharUnits Adjustment = ML.VFPtrOffset;
// Normal virtual instance methods need to adjust from the vfptr that first
@@ -1353,7 +1366,6 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
return CGF.Builder.CreateConstByteGEP(This, Adjustment);
}
- GD = GD.getCanonicalDecl();
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
GlobalDecl LookupGD = GD;
@@ -1367,7 +1379,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
// with the base one, so look up the deleting one instead.
LookupGD = GlobalDecl(DD, Dtor_Deleting);
}
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
CharUnits StaticOffset = ML.VFPtrOffset;
@@ -1381,7 +1393,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
Address Result = This;
if (ML.VBase) {
Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty);
-
+
const CXXRecordDecl *Derived = MD->getParent();
const CXXRecordDecl *VBase = ML.VBase;
llvm::Value *VBaseOffset =
@@ -1523,8 +1535,7 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs(
}
RValue RV = RValue::get(MostDerivedArg);
if (FPT->isVariadic()) {
- Args.insert(Args.begin() + 1,
- CallArg(RV, getContext().IntTy, /*needscopy=*/false));
+ Args.insert(Args.begin() + 1, CallArg(RV, getContext().IntTy));
return AddedStructorArgs::prefix(1);
}
Args.add(RV, getContext().IntTy);
@@ -1535,6 +1546,12 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
bool Delegating, Address This) {
+ // Use the base destructor variant in place of the complete destructor variant
+ // if the class has no virtual bases. This effectively implements some of the
+ // -mconstructor-aliases optimization, but as part of the MS C++ ABI.
+ if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0)
+ Type = Dtor_Base;
+
CGCallee Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
DD);
@@ -1545,21 +1562,21 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type),
This, false);
}
-
+
llvm::BasicBlock *BaseDtorEndBB = nullptr;
if (ForVirtualBase && isa<CXXConstructorDecl>(CGF.CurCodeDecl)) {
BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
- }
+ }
CGF.EmitCXXDestructorCall(DD, Callee, This.getPointer(),
/*ImplicitParam=*/nullptr,
/*ImplicitParamTy=*/QualType(), nullptr,
getFromDtorType(Type));
if (BaseDtorEndBB) {
- // Complete object handler should continue to be the remaining
+ // Complete object handler should continue to be the remaining
CGF.Builder.CreateBr(BaseDtorEndBB);
CGF.EmitBlock(BaseDtorEndBB);
- }
+ }
}
void MicrosoftCXXABI::emitVTableTypeMetadata(const VPtrInfo &Info,
@@ -1817,7 +1834,6 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
Address This,
llvm::Type *Ty,
SourceLocation Loc) {
- GD = GD.getCanonicalDecl();
CGBuilderTy &Builder = CGF.Builder;
Ty = Ty->getPointerTo()->getPointerTo();
@@ -1828,8 +1844,7 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent());
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
- MicrosoftVTableContext::MethodVFTableLocation ML =
- VFTContext.getMethodVFTableLocation(GD);
+ MethodVFTableLocation ML = VFTContext.getMethodVFTableLocation(GD);
// Compute the identity of the most derived class whose virtual table is
// located at the MethodVFTableLocation ML.
@@ -1857,7 +1872,7 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
}
- CGCallee Callee(MethodDecl, VFunc);
+ CGCallee Callee(MethodDecl->getCanonicalDecl(), VFunc);
return Callee;
}
@@ -1872,9 +1887,8 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
GlobalDecl GD(Dtor, Dtor_Deleting);
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Deleting);
- llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- CGCallee Callee = getVirtualFunctionPointer(
- CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation());
+ llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
+ CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty);
ASTContext &Context = getContext();
llvm::Value *ImplicitParam = llvm::ConstantInt::get(
@@ -1915,23 +1929,24 @@ MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) {
return VBGlobals;
}
-llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+llvm::Function *
+MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ const MethodVFTableLocation &ML) {
assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) &&
"can't form pointers to ctors or virtual dtors");
// Calculate the mangled name.
SmallString<256> ThunkName;
llvm::raw_svector_ostream Out(ThunkName);
- getMangleContext().mangleVirtualMemPtrThunk(MD, Out);
+ getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
// If the thunk has been generated previously, just return it.
if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
return cast<llvm::Function>(GV);
// Create the llvm::Function.
- const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSMemberPointerThunk(MD);
+ const CGFunctionInfo &FnInfo =
+ CGM.getTypes().arrangeUnprototypedMustTailThunk(MD);
llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
llvm::Function *ThunkFn =
llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
@@ -2716,9 +2731,8 @@ llvm::Constant *
MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
assert(MD->isInstance() && "Member function must not be static!");
- MD = MD->getCanonicalDecl();
CharUnits NonVirtualBaseAdjustment = CharUnits::Zero();
- const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl();
+ const CXXRecordDecl *RD = MD->getParent()->getMostRecentNonInjectedDecl();
CodeGenTypes &Types = CGM.getTypes();
unsigned VBTableIndex = 0;
@@ -2738,8 +2752,7 @@ MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
FirstField = CGM.GetAddrOfFunction(MD, Ty);
} else {
auto &VTableContext = CGM.getMicrosoftVTableContext();
- MicrosoftVTableContext::MethodVFTableLocation ML =
- VTableContext.getMethodVFTableLocation(MD);
+ MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD);
FirstField = EmitVirtualMemPtrThunk(MD, ML);
// Include the vfptr adjustment if the method is in a non-primary vftable.
NonVirtualBaseAdjustment += ML.VFPtrOffset;
@@ -3336,14 +3349,14 @@ CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
// a reference to the TypeInfo for the type and a reference to the
// CompleteHierarchyDescriptor for the type.
//
-// ClassHieararchyDescriptor: Contains information about a class hierarchy.
+// ClassHierarchyDescriptor: Contains information about a class hierarchy.
// Used during dynamic_cast to walk a class hierarchy. References a base
// class array and the size of said array.
//
// BaseClassArray: Contains a list of classes in a hierarchy. BaseClassArray is
// somewhat of a misnomer because the most derived class is also in the list
// as well as multiple copies of virtual bases (if they occur multiple times
-// in the hiearchy.) The BaseClassArray contains one BaseClassDescriptor for
+// in the hierarchy.) The BaseClassArray contains one BaseClassDescriptor for
// every path in the hierarchy, in pre-order depth first order. Note, we do
// not declare a specific llvm type for BaseClassArray, it's merely an array
// of BaseClassDescriptor pointers.
@@ -3356,7 +3369,7 @@ CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
// mangled into them so they can be aggressively deduplicated by the linker.
static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
- StringRef MangledName("\01??_7type_info@@6B@");
+ StringRef MangledName("??_7type_info@@6B@");
if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
return VTable;
return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
@@ -3367,7 +3380,7 @@ static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
namespace {
-/// \brief A Helper struct that stores information about a class in a class
+/// A Helper struct that stores information about a class in a class
/// hierarchy. The information stored in these structs struct is used during
/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors.
// During RTTI creation, MSRTTIClasses are stored in a contiguous array with
@@ -3394,7 +3407,7 @@ struct MSRTTIClass {
uint32_t Flags, NumBases, OffsetInVBase;
};
-/// \brief Recursively initialize the base class array.
+/// Recursively initialize the base class array.
uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
const CXXBaseSpecifier *Specifier) {
Flags = HasHierarchyDescriptor;
@@ -3441,7 +3454,7 @@ static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
llvm_unreachable("Invalid linkage!");
}
-/// \brief An ephemeral helper class for building MS RTTI types. It caches some
+/// An ephemeral helper class for building MS RTTI types. It caches some
/// calls to the module and information about the most derived class in a
/// hierarchy.
struct MSRTTIBuilder {
@@ -3474,7 +3487,7 @@ struct MSRTTIBuilder {
} // namespace
-/// \brief Recursively serializes a class hierarchy in pre-order depth first
+/// Recursively serializes a class hierarchy in pre-order depth first
/// order.
static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
const CXXRecordDecl *RD) {
@@ -3483,7 +3496,7 @@ static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl());
}
-/// \brief Find ambiguity among base classes.
+/// Find ambiguity among base classes.
static void
detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
@@ -3749,7 +3762,7 @@ MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type,
Flags};
}
-/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
+/// Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
/// llvm::GlobalVariable * because different type descriptors have different
/// types, and need to be abstracted. They are abstracting by casting the
/// address to an Int8PtrTy.
@@ -3791,7 +3804,7 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
return llvm::ConstantExpr::getBitCast(Var, CGM.Int8PtrTy);
}
-/// \brief Gets or a creates a Microsoft CompleteObjectLocator.
+/// Gets or a creates a Microsoft CompleteObjectLocator.
llvm::GlobalVariable *
MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
const VPtrInfo &Info) {
@@ -3808,19 +3821,12 @@ static void emitCXXConstructor(CodeGenModule &CGM,
static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
StructorType dtorType) {
- // The complete destructor is equivalent to the base destructor for
- // classes with no virtual bases, so try to emit it as an alias.
- if (!dtor->getParent()->getNumVBases() &&
- (dtorType == StructorType::Complete || dtorType == StructorType::Base)) {
- bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
- GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base));
- if (ProducedAlias) {
- if (dtorType == StructorType::Complete)
- return;
- if (dtor->isVirtual())
- CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
- }
- }
+ // Emit the base destructor if the base and complete (vbase) destructors are
+ // equivalent. This effectively implements -mconstructor-aliases as part of
+ // the ABI.
+ if (dtorType == StructorType::Complete &&
+ dtor->getParent()->getNumVBases() == 0)
+ dtorType = StructorType::Base;
// The base destructor is equivalent to the base destructor of its
// base class if there is exactly one non-virtual base class with a
@@ -3898,7 +3904,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
SourceLocation(),
&getContext().Idents.get("is_most_derived"),
getContext().IntTy, ImplicitParamDecl::Other);
- // Only add the parameter to the list if thie class has virtual bases.
+ // Only add the parameter to the list if the class has virtual bases.
if (RD->getNumVBases() > 0)
FunctionArgs.push_back(&IsMostDerived);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index 0fe9f5da07c8..c164cec5d942 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -71,9 +71,8 @@ class PCHContainerGenerator : public ASTConsumer {
}
bool VisitImportDecl(ImportDecl *D) {
- auto *Import = cast<ImportDecl>(D);
- if (!Import->getImportedOwningModule())
- DI.EmitImportDecl(*Import);
+ if (!D->getImportedOwningModule())
+ DI.EmitImportDecl(*D);
return true;
}
@@ -291,7 +290,7 @@ public:
else
ASTSym->setSection("__clangast");
- DEBUG({
+ LLVM_DEBUG({
// Print the IR for the PCH container to the debug output.
llvm::SmallString<0> Buffer;
clang::EmitBackendOutput(
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
index f891cfbe4bb2..23cf9e490828 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -27,7 +27,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
bool IsBlacklisted) {
if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress |
- SanitizerKind::HWAddress))
+ SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress))
return;
IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
@@ -60,7 +61,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
const VarDecl &D, bool IsDynInit) {
if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress |
- SanitizerKind::HWAddress))
+ SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress))
return;
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -79,7 +81,8 @@ void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
// instrumentation.
if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress |
- SanitizerKind::HWAddress))
+ SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress))
reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp b/contrib/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp
index fc8e36d2c599..b411a501ea81 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp
@@ -163,7 +163,7 @@ void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin,
// - virtual bases
for (auto &vbaseSpecifier : cxxRecord->vbases()) {
auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl();
- addTypedData(baseRecord, begin + layout.getVBaseClassOffset(baseRecord));
+ addTypedData(baseRecord, begin + layout.getVBaseClassOffset(baseRecord));
}
}
}
@@ -579,13 +579,11 @@ bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const {
// Empty types don't need to be passed indirectly.
if (Entries.empty()) return false;
- CharUnits totalSize = Entries.back().End;
-
// Avoid copying the array of types when there's just a single element.
if (Entries.size() == 1) {
- return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(totalSize,
+ return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(
Entries.back().Type,
- asReturnValue);
+ asReturnValue);
}
SmallVector<llvm::Type*, 8> componentTys;
@@ -593,8 +591,14 @@ bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const {
for (auto &entry : Entries) {
componentTys.push_back(entry.Type);
}
- return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(totalSize,
- componentTys,
+ return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys,
+ asReturnValue);
+}
+
+bool swiftcall::shouldPassIndirectly(CodeGenModule &CGM,
+ ArrayRef<llvm::Type*> componentTys,
+ bool asReturnValue) {
+ return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys,
asReturnValue);
}
@@ -736,24 +740,12 @@ void swiftcall::legalizeVectorType(CodeGenModule &CGM, CharUnits origVectorSize,
components.append(numElts, eltTy);
}
-bool swiftcall::shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
- const CXXRecordDecl *record) {
- // Following a recommendation from Richard Smith, pass a C++ type
- // indirectly only if the destructor is non-trivial or *all* of the
- // copy/move constructors are deleted or non-trivial.
-
- if (record->hasNonTrivialDestructor())
- return true;
-
- // It would be nice if this were summarized on the CXXRecordDecl.
- for (auto ctor : record->ctors()) {
- if (ctor->isCopyOrMoveConstructor() && !ctor->isDeleted() &&
- ctor->isTrivial()) {
- return false;
- }
- }
-
- return true;
+bool swiftcall::mustPassRecordIndirectly(CodeGenModule &CGM,
+ const RecordDecl *record) {
+ // FIXME: should we not rely on the standard computation in Sema, just in
+ // case we want to diverge from the platform ABI (e.g. on targets where
+ // that uses the MSVC rule)?
+ return !record->canPassInRegisters();
}
static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering,
@@ -775,10 +767,8 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type,
auto record = recordType->getDecl();
auto &layout = CGM.getContext().getASTRecordLayout(record);
- if (auto cxxRecord = dyn_cast<CXXRecordDecl>(record)) {
- if (shouldPassCXXRecordIndirectly(CGM, cxxRecord))
- return ABIArgInfo::getIndirect(layout.getAlignment(), /*byval*/ false);
- }
+ if (mustPassRecordIndirectly(CGM, record))
+ return ABIArgInfo::getIndirect(layout.getAlignment(), /*byval*/ false);
SwiftAggLowering lowering(CGM);
lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index f2352a373401..6f6c5f50c2e7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -140,8 +140,11 @@ bool SwiftABIInfo::isLegalVectorTypeForSwift(CharUnits vectorSize,
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
CGCXXABI &CXXABI) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
+ if (!RD) {
+ if (!RT->getDecl()->canPassInRegisters())
+ return CGCXXABI::RAA_Indirect;
return CGCXXABI::RAA_Default;
+ }
return CXXABI.getRecordArgABI(RD);
}
@@ -153,6 +156,20 @@ static CGCXXABI::RecordArgABI getRecordArgABI(QualType T,
return getRecordArgABI(RT, CXXABI);
}
+static bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,
+ const ABIInfo &Info) {
+ QualType Ty = FI.getReturnType();
+
+ if (const auto *RT = Ty->getAs<RecordType>())
+ if (!isa<CXXRecordDecl>(RT->getDecl()) &&
+ !RT->getDecl()->canPassInRegisters()) {
+ FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty);
+ return true;
+ }
+
+ return CXXABI.classifyReturnType(FI);
+}
+
/// Pass transparent unions as if they were the type of the first element. Sema
/// should ensure that all elements of the union have the same "machine type".
static QualType useFirstFieldIfTransparentUnion(QualType Ty) {
@@ -201,10 +218,6 @@ bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
return false;
}
-bool ABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
- return false;
-}
-
LLVM_DUMP_METHOD void ABIArgInfo::dump() const {
raw_ostream &OS = llvm::errs();
OS << "(ABIArgInfo Kind=";
@@ -292,7 +305,7 @@ static Address emitVoidPtrDirectVAArg(CodeGenFunction &CGF,
Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign),
DirectAlign);
} else {
- Addr = Address(Ptr, SlotSize);
+ Addr = Address(Ptr, SlotSize);
}
// Advance the pointer past the argument, then store that back.
@@ -356,7 +369,7 @@ static Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
}
return Addr;
-
+
}
static Address emitMergePHI(CodeGenFunction &CGF,
@@ -682,8 +695,8 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
@@ -697,8 +710,8 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
//===----------------------------------------------------------------------===//
@@ -734,9 +747,18 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
public:
explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(new WebAssemblyABIInfo(CGT)) {}
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override {
+ if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+ if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype())
+ Fn->addFnAttr("no-prototype");
+ }
+ }
};
-/// \brief Classify argument of given type \p Ty.
+/// Classify argument of given type \p Ty.
ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const {
Ty = useFirstFieldIfTransparentUnion(Ty);
@@ -831,7 +853,7 @@ Address PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect());
}
-/// \brief Classify argument of given type \p Ty.
+/// Classify argument of given type \p Ty.
ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
if (isAggregateTypeForABI(Ty)) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
@@ -845,8 +867,8 @@ ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect();
}
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
@@ -861,8 +883,8 @@ ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
/// IsX86_MMXType - Return true if this is an MMX type.
@@ -932,7 +954,7 @@ static ABIArgInfo getDirectX86Hva(llvm::Type* T = nullptr) {
// X86-32 ABI Implementation
//===----------------------------------------------------------------------===//
-/// \brief Similar to llvm::CCState, but for Clang.
+/// Similar to llvm::CCState, but for Clang.
struct CCState {
CCState(unsigned CC) : CC(CC), FreeRegs(0), FreeSSERegs(0) {}
@@ -985,14 +1007,14 @@ class X86_32ABIInfo : public SwiftABIInfo {
ABIArgInfo getIndirectReturnResult(QualType Ty, CCState &State) const;
- /// \brief Return the alignment to use for the given type on the stack.
+ /// Return the alignment to use for the given type on the stack.
unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
Class classify(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
- /// \brief Updates the number of available free registers, returns
+ /// Updates the number of available free registers, returns
/// true if any registers were allocated.
bool updateFreeRegs(QualType Ty, CCState &State) const;
@@ -1002,7 +1024,7 @@ class X86_32ABIInfo : public SwiftABIInfo {
bool canExpandIndirectArgument(QualType Ty) const;
- /// \brief Rewrite the function info so that all memory arguments use
+ /// Rewrite the function info so that all memory arguments use
/// inalloca.
void rewriteWithInAlloca(CGFunctionInfo &FI) const;
@@ -1022,21 +1044,20 @@ public:
bool RetSmallStructInRegABI, bool Win32StructABI,
unsigned NumRegisterParameters, bool SoftFloatABI)
: SwiftABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI),
- IsRetSmallStructInRegABI(RetSmallStructInRegABI),
+ IsRetSmallStructInRegABI(RetSmallStructInRegABI),
IsWin32StructABI(Win32StructABI),
IsSoftFloatABI(SoftFloatABI),
IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()),
DefaultNumRegisterParameters(NumRegisterParameters) {}
- bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type*> scalars,
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
bool asReturnValue) const override {
// LLVM's x86-32 lowering currently only assigns up to three
// integer registers and three fp registers. Oddly, it'll use up to
// four vector registers for vectors, but those can overlap with the
// scalar registers.
return occupiesMoreThan(CGT, scalars, /*total*/ 3);
- }
+ }
bool isSwiftErrorInRegister() const override {
// x86-32 lowering does not support passing swifterror in a register.
@@ -1057,8 +1078,7 @@ public:
const llvm::Triple &Triple, const CodeGenOptions &Opts);
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &CGM) const override;
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
// Darwin uses different dwarf register numbers for EH.
@@ -1404,8 +1424,8 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
static bool isSSEVectorType(ASTContext &Context, QualType Ty) {
@@ -1526,7 +1546,7 @@ bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State) const {
return true;
}
-bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
+bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
bool &InReg,
bool &NeedsPadding) const {
// On Windows, aggregates other than HFAs are never passed in registers, and
@@ -1569,7 +1589,7 @@ bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State) const {
if (getContext().getTypeSize(Ty) > 32)
return false;
- return (Ty->isIntegralOrEnumerationType() || Ty->isPointerType() ||
+ return (Ty->isIntegralOrEnumerationType() || Ty->isPointerType() ||
Ty->isReferenceType());
}
@@ -1677,8 +1697,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
if (Ty->isPromotableIntegerType()) {
if (InReg)
- return ABIArgInfo::getExtendInReg();
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtendInReg(Ty);
+ return ABIArgInfo::getExtend(Ty);
}
if (InReg)
@@ -1755,7 +1775,7 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
} else
State.FreeRegs = DefaultNumRegisterParameters;
- if (!getCXXABI().classifyReturnType(FI)) {
+ if (!::classifyReturnType(getCXXABI(), FI, *this)) {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
} else if (FI.getReturnInfo().isIndirect()) {
// The C++ ABI is not aware of register usage, so we have to check if the
@@ -1925,9 +1945,8 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
}
void X86_32TargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const {
- if (!IsForDefinition)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ if (GV->isDeclaration())
return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
@@ -2116,8 +2135,8 @@ class X86_64ABIInfo : public SwiftABIInfo {
/// classify it as INTEGER (for compatibility with older clang compilers).
bool classifyIntegerMMXAsSSE() const {
// Clang <= 3.8 did not do this.
- if (getCodeGenOpts().getClangABICompat() <=
- CodeGenOptions::ClangABI::Ver3_8)
+ if (getContext().getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver3_8)
return false;
const llvm::Triple &Triple = getTarget().getTriple();
@@ -2163,11 +2182,10 @@ public:
return Has64BitPointers;
}
- bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type*> scalars,
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
- }
+ }
bool isSwiftErrorInRegister() const override {
return true;
}
@@ -2196,8 +2214,7 @@ public:
return isX86VectorCallAggregateSmallEnough(NumMembers);
}
- bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type *> scalars,
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type *> scalars,
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
@@ -2281,9 +2298,8 @@ public:
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override {
- if (!IsForDefinition)
+ CodeGen::CodeGenModule &CGM) const override {
+ if (GV->isDeclaration())
return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
@@ -2336,8 +2352,7 @@ public:
Win32StructABI, NumRegisterParameters, false) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &CGM) const override;
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
@@ -2352,26 +2367,24 @@ public:
}
};
-static void addStackProbeSizeTargetAttribute(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) {
- if (D && isa<FunctionDecl>(D)) {
- if (CGM.getCodeGenOpts().StackProbeSize != 4096) {
- llvm::Function *Fn = cast<llvm::Function>(GV);
+static void addStackProbeTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) {
+ if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(GV)) {
+ if (CGM.getCodeGenOpts().StackProbeSize != 4096)
Fn->addFnAttr("stack-probe-size",
llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
- }
+ if (CGM.getCodeGenOpts().NoStackArgProbe)
+ Fn->addFnAttr("no-stack-arg-probe");
}
}
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)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ if (GV->isDeclaration())
return;
- addStackProbeSizeTargetAttribute(D, GV, CGM);
+ addStackProbeTargetAttributes(D, GV, CGM);
}
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -2381,8 +2394,7 @@ public:
: TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &CGM) const override;
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
return 7;
@@ -2412,10 +2424,9 @@ public:
};
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)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ if (GV->isDeclaration())
return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
@@ -2428,7 +2439,7 @@ void WinX86_64TargetCodeGenInfo::setTargetAttributes(
}
}
- addStackProbeSizeTargetAttribute(D, GV, CGM);
+ addStackProbeTargetAttributes(D, GV, CGM);
}
}
@@ -2853,8 +2864,8 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
return getNaturalAlignIndirect(Ty);
@@ -2886,8 +2897,8 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
@@ -3256,7 +3267,7 @@ classifyReturnType(QualType RetTy) const {
if (RetTy->isIntegralOrEnumerationType() &&
RetTy->isPromotableIntegerType())
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(RetTy);
}
break;
@@ -3401,7 +3412,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(
if (Ty->isIntegralOrEnumerationType() &&
Ty->isPromotableIntegerType())
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(Ty);
}
break;
@@ -3545,7 +3556,7 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
unsigned FreeSSERegs = IsRegCall ? 16 : 8;
unsigned NeededInt, NeededSSE;
- if (!getCXXABI().classifyReturnType(FI)) {
+ if (!::classifyReturnType(getCXXABI(), FI, *this)) {
if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
!FI.getReturnType()->getTypePtr()->isUnionType()) {
FI.getReturnInfo() =
@@ -3774,7 +3785,7 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false);
RegAddr = Tmp;
}
-
+
} else if (neededSSE == 1) {
RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset),
CharUnits::fromQuantity(16));
@@ -3792,17 +3803,18 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
Address RegAddrHi =
CGF.Builder.CreateConstInBoundsByteGEP(RegAddrLo,
CharUnits::fromQuantity(16));
- llvm::Type *DoubleTy = CGF.DoubleTy;
- llvm::StructType *ST = llvm::StructType::get(DoubleTy, DoubleTy);
+ llvm::Type *ST = AI.canHaveCoerceToType()
+ ? AI.getCoerceToType()
+ : llvm::StructType::get(CGF.DoubleTy, CGF.DoubleTy);
llvm::Value *V;
Address Tmp = CGF.CreateMemTemp(Ty);
Tmp = CGF.Builder.CreateElementBitCast(Tmp, ST);
- V = CGF.Builder.CreateLoad(
- CGF.Builder.CreateElementBitCast(RegAddrLo, DoubleTy));
+ V = CGF.Builder.CreateLoad(CGF.Builder.CreateElementBitCast(
+ RegAddrLo, ST->getStructElementType(0)));
CGF.Builder.CreateStore(V,
CGF.Builder.CreateStructGEP(Tmp, 0, CharUnits::Zero()));
- V = CGF.Builder.CreateLoad(
- CGF.Builder.CreateElementBitCast(RegAddrHi, DoubleTy));
+ V = CGF.Builder.CreateLoad(CGF.Builder.CreateElementBitCast(
+ RegAddrHi, ST->getStructElementType(1)));
CGF.Builder.CreateStore(V,
CGF.Builder.CreateStructGEP(Tmp, 1, CharUnits::fromQuantity(8)));
@@ -3936,7 +3948,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
// extended.
const BuiltinType *BT = Ty->getAs<BuiltinType>();
if (BT && BT->getKind() == BuiltinType::Bool)
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(Ty);
// Mingw64 GCC uses the old 80 bit extended precision floating point unit. It
// passes them indirectly through memory.
@@ -4168,7 +4180,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
}
// Get the address of the saved value by scaling the number of
- // registers we've used by the number of
+ // registers we've used by the number of
CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8);
llvm::Value *RegOffset =
Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity()));
@@ -4179,7 +4191,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
// Increase the used-register count.
NumRegs =
- Builder.CreateAdd(NumRegs,
+ Builder.CreateAdd(NumRegs,
Builder.getInt8((isI64 || (isF64 && IsSoftFloatABI)) ? 2 : 1));
Builder.CreateStore(NumRegs, NumRegsAddr);
@@ -4215,7 +4227,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align),
Align);
}
-
+
MemAddr = Builder.CreateElementBitCast(OverflowArea, DirectTy);
// Increase the overflow area.
@@ -4284,7 +4296,7 @@ PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
namespace {
/// PPC64_SVR4_ABIInfo - The 64-bit PowerPC ELF (SVR4) ABI information.
-class PPC64_SVR4_ABIInfo : public ABIInfo {
+class PPC64_SVR4_ABIInfo : public SwiftABIInfo {
public:
enum ABIKind {
ELFv1 = 0,
@@ -4328,7 +4340,7 @@ private:
public:
PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind, bool HasQPX,
bool SoftFloatABI)
- : ABIInfo(CGT), Kind(Kind), HasQPX(HasQPX),
+ : SwiftABIInfo(CGT), Kind(Kind), HasQPX(HasQPX),
IsSoftFloatABI(SoftFloatABI) {}
bool isPromotableTypeForABI(QualType Ty) const;
@@ -4371,6 +4383,15 @@ public:
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
+
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
+ bool asReturnValue) const override {
+ return occupiesMoreThan(CGT, scalars, /*total*/ 4);
+ }
+
+ bool isSwiftErrorInRegister() const override {
+ return false;
+ }
};
class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -4538,7 +4559,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
// For compatibility with GCC, ignore empty bitfields in C++ mode.
if (getContext().getLangOpts().CPlusPlus &&
- FD->isBitField() && FD->getBitWidthValue(getContext()) == 0)
+ FD->isZeroLengthBitField(getContext()))
continue;
uint64_t FldMembers;
@@ -4598,7 +4619,9 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
if (BT->getKind() == BuiltinType::Float ||
BT->getKind() == BuiltinType::Double ||
- BT->getKind() == BuiltinType::LongDouble) {
+ BT->getKind() == BuiltinType::LongDouble ||
+ (getContext().getTargetInfo().hasFloat128Type() &&
+ (BT->getKind() == BuiltinType::Float128))) {
if (IsSoftFloatABI)
return false;
return true;
@@ -4613,10 +4636,13 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateSmallEnough(
const Type *Base, uint64_t Members) const {
- // Vector types require one register, floating point types require one
- // or two registers depending on their size.
+ // Vector and fp128 types require one register, other floating point types
+ // require one or two registers depending on their size.
uint32_t NumRegs =
- Base->isVectorType() ? 1 : (getContext().getTypeSize(Base) + 63) / 64;
+ ((getContext().getTargetInfo().hasFloat128Type() &&
+ Base->isFloat128Type()) ||
+ Base->isVectorType()) ? 1
+ : (getContext().getTypeSize(Base) + 63) / 64;
// Homogeneous Aggregates may occupy at most 8 registers.
return Members * NumRegs <= 8;
@@ -4689,8 +4715,8 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
/*Realign=*/TyAlign > ABIAlign);
}
- return (isPromotableTypeForABI(Ty) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (isPromotableTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
ABIArgInfo
@@ -4744,8 +4770,8 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
return getNaturalAlignIndirect(RetTy);
}
- return (isPromotableTypeForABI(RetTy) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (isPromotableTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
// Based on ARMABIInfo::EmitVAArg, adjusted for 64-bit machine.
@@ -4894,7 +4920,7 @@ private:
bool isIllegalVectorType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override {
- if (!getCXXABI().classifyReturnType(FI))
+ if (!::classifyReturnType(getCXXABI(), FI, *this))
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &it : FI.arguments())
@@ -4917,8 +4943,7 @@ private:
Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
- bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type*> scalars,
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
@@ -4997,7 +5022,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
Ty = EnumTy->getDecl()->getIntegerType();
return (Ty->isPromotableIntegerType() && isDarwinPCS()
- ? ABIArgInfo::getExtend()
+ ? ABIArgInfo::getExtend(Ty)
: ABIArgInfo::getDirect());
}
@@ -5038,7 +5063,13 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
if (getTarget().isRenderScriptTarget()) {
return coerceToIntArray(Ty, getContext(), getVMContext());
}
- unsigned Alignment = getContext().getTypeAlign(Ty);
+ unsigned Alignment;
+ if (Kind == AArch64ABIInfo::AAPCS) {
+ Alignment = getContext().getTypeUnadjustedAlign(Ty);
+ Alignment = Alignment < 128 ? 64 : 128;
+ } else {
+ Alignment = getContext().getTypeAlign(Ty);
+ }
Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
// We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
@@ -5067,7 +5098,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
RetTy = EnumTy->getDecl()->getIntegerType();
return (RetTy->isPromotableIntegerType() && isDarwinPCS()
- ? ABIArgInfo::getExtend()
+ ? ABIArgInfo::getExtend(RetTy)
: ABIArgInfo::getDirect());
}
@@ -5516,8 +5547,7 @@ private:
llvm::CallingConv::ID getABIDefaultCC() const;
void setCCs();
- bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type*> scalars,
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
@@ -5560,9 +5590,8 @@ public:
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override {
- if (!IsForDefinition)
+ CodeGen::CodeGenModule &CGM) const override {
+ if (GV->isDeclaration())
return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
@@ -5605,8 +5634,7 @@ public:
: ARMTargetCodeGenInfo(CGT, K) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &CGM) const override;
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
@@ -5620,17 +5648,16 @@ public:
};
void WindowsARMTargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const {
- ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
- if (!IsForDefinition)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ if (GV->isDeclaration())
return;
- addStackProbeSizeTargetAttribute(D, GV, CGM);
+ addStackProbeTargetAttributes(D, GV, CGM);
}
}
void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
- if (!getCXXABI().classifyReturnType(FI))
+ if (!::classifyReturnType(getCXXABI(), FI, *this))
FI.getReturnInfo() =
classifyReturnType(FI.getReturnType(), FI.isVariadic());
@@ -5677,18 +5704,6 @@ void ARMABIInfo::setCCs() {
llvm::CallingConv::ID abiCC = getABIDefaultCC();
if (abiCC != getLLVMDefaultCC())
RuntimeCC = abiCC;
-
- // AAPCS apparently requires runtime support functions to be soft-float, but
- // that's almost certainly for historic reasons (Thumb1 not supporting VFP
- // most likely). It's more convenient for AAPCS16_VFP to be hard-float.
-
- // The Run-time ABI for the ARM Architecture section 4.1.2 requires
- // AEABI-complying FP helper functions to use the base AAPCS.
- // These AEABI functions are expanded in the ARM llvm backend, all the builtin
- // support functions emitted by clang such as the _Complex helpers follow the
- // abiCC.
- if (abiCC != getLLVMDefaultCC())
- BuiltinCC = abiCC;
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
@@ -5725,10 +5740,11 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
}
- // __fp16 gets passed as if it were an int or float, but with the top 16 bits
- // unspecified. This is not done for OpenCL as it handles the half type
- // natively, and does not need to interwork with AAPCS code.
- if (Ty->isHalfType() && !getContext().getLangOpts().NativeHalfArgsAndReturns) {
+ // _Float16 and __fp16 get passed as if it were an int or float, but with
+ // the top 16 bits unspecified. This is not done for OpenCL as it handles the
+ // half type natively, and does not need to interwork with AAPCS code.
+ if ((Ty->isFloat16Type() || Ty->isHalfType()) &&
+ !getContext().getLangOpts().NativeHalfArgsAndReturns) {
llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
llvm::Type::getFloatTy(getVMContext()) :
llvm::Type::getInt32Ty(getVMContext());
@@ -5741,7 +5757,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
Ty = EnumTy->getDecl()->getIntegerType();
}
- return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend()
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
: ABIArgInfo::getDirect());
}
@@ -5791,11 +5807,14 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
// most 8-byte. We realign the indirect argument if type alignment is bigger
// than ABI alignment.
uint64_t ABIAlign = 4;
- uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
+ uint64_t TyAlign;
if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
- getABIKind() == ARMABIInfo::AAPCS)
+ getABIKind() == ARMABIInfo::AAPCS) {
+ TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
-
+ } else {
+ TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
+ }
if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) {
assert(getABIKind() != ARMABIInfo::AAPCS16_VFP && "unexpected byval");
return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign),
@@ -5814,7 +5833,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
unsigned SizeRegs;
// FIXME: Try to match the types of the arguments more accurately where
// we can.
- if (getContext().getTypeAlign(Ty) <= 32) {
+ if (TyAlign <= 4) {
ElemTy = llvm::Type::getInt32Ty(getVMContext());
SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
} else {
@@ -5923,10 +5942,11 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
return getNaturalAlignIndirect(RetTy);
}
- // __fp16 gets returned as if it were an int or float, but with the top 16
- // bits unspecified. This is not done for OpenCL as it handles the half type
- // natively, and does not need to interwork with AAPCS code.
- if (RetTy->isHalfType() && !getContext().getLangOpts().NativeHalfArgsAndReturns) {
+ // _Float16 and __fp16 get returned as if it were an int or float, but with
+ // the top 16 bits unspecified. This is not done for OpenCL as it handles the
+ // half type natively, and does not need to interwork with AAPCS code.
+ if ((RetTy->isFloat16Type() || RetTy->isHalfType()) &&
+ !getContext().getLangOpts().NativeHalfArgsAndReturns) {
llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
llvm::Type::getFloatTy(getVMContext()) :
llvm::Type::getInt32Ty(getVMContext());
@@ -5938,7 +5958,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend()
+ return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
: ABIArgInfo::getDirect();
}
@@ -6150,8 +6170,8 @@ public:
: TargetCodeGenInfo(new NVPTXABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &M) const override;
+ bool shouldEmitStaticExternCAliases() const override;
private:
// Adds a NamedMDNode with F, Name, and Operand as operands, and adds the
@@ -6171,8 +6191,8 @@ ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const {
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const {
@@ -6184,8 +6204,8 @@ ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const {
if (isAggregateTypeForABI(Ty))
return getNaturalAlignIndirect(Ty, /* byval */ true);
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -6207,9 +6227,8 @@ Address NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
}
void NVPTXTargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const {
- if (!IsForDefinition)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+ if (GV->isDeclaration())
return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
@@ -6274,6 +6293,10 @@ void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::Function *F, StringRef Name,
// Append metadata to nvvm.annotations
MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
}
+
+bool NVPTXTargetCodeGenInfo::shouldEmitStaticExternCAliases() const {
+ return false;
+}
}
//===----------------------------------------------------------------------===//
@@ -6308,8 +6331,7 @@ public:
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
- bool shouldPassIndirectlyForSwift(CharUnits totalSize,
- ArrayRef<llvm::Type*> scalars,
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
@@ -6397,7 +6419,7 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
// Unlike isSingleElementStruct(), empty structure and array fields
// do count. So do anonymous bitfields that aren't zero-sized.
if (getContext().getLangOpts().CPlusPlus &&
- FD->isBitField() && FD->getBitWidthValue(getContext()) == 0)
+ FD->isZeroLengthBitField(getContext()))
continue;
// Unlike isSingleElementStruct(), arrays do not count.
@@ -6581,8 +6603,8 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
return ABIArgInfo::getDirect();
if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64)
return getNaturalAlignIndirect(RetTy);
- return (isPromotableIntegerType(RetTy) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (isPromotableIntegerType(RetTy) ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
@@ -6592,7 +6614,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Integers and enums are extended to full register width.
if (isPromotableIntegerType(Ty))
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(Ty);
// Handle vector types and vector-like structure types. Note that
// as opposed to float-like structure types, we do not allow any
@@ -6646,16 +6668,14 @@ public:
MSP430TargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &M) const override;
};
}
void MSP430TargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const {
- if (!IsForDefinition)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+ if (GV->isDeclaration())
return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
@@ -6700,7 +6720,7 @@ public:
void computeInfo(CGFunctionInfo &FI) const override;
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
- bool shouldSignExtUnsignedType(QualType Ty) const override;
+ ABIArgInfo extendType(QualType Ty) const;
};
class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -6715,8 +6735,7 @@ public:
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override {
+ CodeGen::CodeGenModule &CGM) const override {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -6727,7 +6746,7 @@ public:
Fn->addFnAttr("short-call");
// Other attributes do not have a meaning for declarations.
- if (!IsForDefinition)
+ if (GV->isDeclaration())
return;
if (FD->hasAttr<Mips16Attr>()) {
@@ -6893,7 +6912,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
// All integral types are promoted to the GPR width.
if (Ty->isIntegralOrEnumerationType())
- return ABIArgInfo::getExtend();
+ return extendType(Ty);
return ABIArgInfo::getDirect(
nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
@@ -6975,8 +6994,14 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ if (RetTy->isPromotableIntegerType())
+ return ABIArgInfo::getExtend(RetTy);
+
+ if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
+ RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
+ return ABIArgInfo::getSignExtend(RetTy);
+
+ return ABIArgInfo::getDirect();
}
void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -7042,14 +7067,14 @@ Address MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
return Addr;
}
-bool MipsABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
+ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
int TySize = getContext().getTypeSize(Ty);
// MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
- return true;
+ return ABIArgInfo::getSignExtend(Ty);
- return false;
+ return ABIArgInfo::getExtend(Ty);
}
bool
@@ -7091,9 +7116,8 @@ public:
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) { }
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM,
- ForDefinition_t IsForDefinition) const override {
- if (!IsForDefinition)
+ CodeGen::CodeGenModule &CGM) const override {
+ if (GV->isDeclaration())
return;
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
@@ -7122,14 +7146,12 @@ public:
: DefaultTargetCodeGenInfo(CGT) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &M) const override;
};
void TCETargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const {
- if (!IsForDefinition)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+ if (GV->isDeclaration())
return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
@@ -7222,8 +7244,8 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const {
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+ : ABIArgInfo::getDirect());
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
@@ -7260,8 +7282,8 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
+ : ABIArgInfo::getDirect());
}
if (isEmptyRecord(getContext(), RetTy, true))
@@ -7404,7 +7426,7 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
if (Ty->isPromotableIntegerType()) {
if (InReg)
return ABIArgInfo::getDirectInReg();
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(Ty);
}
if (InReg)
return ABIArgInfo::getDirectInReg();
@@ -7634,8 +7656,7 @@ public:
AMDGPUTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new AMDGPUABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const override;
+ CodeGen::CodeGenModule &M) const override;
unsigned getOpenCLKernelCallingConv() const override;
llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
@@ -7653,13 +7674,14 @@ public:
createEnqueuedBlockKernel(CodeGenFunction &CGF,
llvm::Function *BlockInvokeFunc,
llvm::Value *BlockLiteral) const override;
+ bool shouldEmitStaticExternCAliases() const override;
+ void setCUDAKernelCallingConvention(const FunctionType *&FT) const override;
};
}
void AMDGPUTargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
- ForDefinition_t IsForDefinition) const {
- if (!IsForDefinition)
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+ if (GV->isDeclaration())
return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
@@ -7669,6 +7691,11 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes(
const auto *ReqdWGS = M.getLangOpts().OpenCL ?
FD->getAttr<ReqdWorkGroupSizeAttr>() : nullptr;
+
+ if (M.getLangOpts().OpenCL && FD->hasAttr<OpenCLKernelAttr>() &&
+ (M.getTriple().getOS() == llvm::Triple::AMDHSA))
+ F->addFnAttr("amdgpu-implicitarg-num-bytes", "48");
+
const auto *FlatWGS = FD->getAttr<AMDGPUFlatWorkGroupSizeAttr>();
if (ReqdWGS || FlatWGS) {
unsigned Min = FlatWGS ? FlatWGS->getMin() : 0;
@@ -7780,6 +7807,16 @@ AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(SyncScope S,
return C.getOrInsertSyncScopeID(Name);
}
+bool AMDGPUTargetCodeGenInfo::shouldEmitStaticExternCAliases() const {
+ return false;
+}
+
+void AMDGPUTargetCodeGenInfo::setCUDAKernelCallingConvention(
+ const FunctionType *&FT) const {
+ FT = getABIInfo().getContext().adjustFunctionType(
+ FT, FT->getExtInfo().withCallingConv(CC_OpenCLKernel));
+}
+
//===----------------------------------------------------------------------===//
// SPARC v8 ABI Implementation.
// Based on the SPARC Compliance Definition version 2.4.1.
@@ -7986,7 +8023,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
// Integer types smaller than a register are extended.
if (Size < 64 && Ty->isIntegerType())
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(Ty);
// Other non-aggregates go in registers.
if (!isAggregateTypeForABI(Ty))
@@ -8516,7 +8553,7 @@ static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT,
// The ABI requires unions to be sorted but not structures.
// See FieldEncoding::operator< for sort algorithm.
if (RT->isUnionType())
- std::sort(FE.begin(), FE.end());
+ llvm::sort(FE.begin(), FE.end());
// We can now complete the TypeString.
unsigned E = FE.size();
for (unsigned I = 0; I != E; ++I) {
@@ -8560,7 +8597,7 @@ static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
EnumEnc += '}';
FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
}
- std::sort(FE.begin(), FE.end());
+ llvm::sort(FE.begin(), FE.end());
unsigned E = FE.size();
for (unsigned I = 0; I != E; ++I) {
if (I)
@@ -8775,6 +8812,203 @@ static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
return false;
}
+//===----------------------------------------------------------------------===//
+// RISCV ABI Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RISCVABIInfo : public DefaultABIInfo {
+private:
+ unsigned XLen; // Size of the integer ('x') registers in bits.
+ static const int NumArgGPRs = 8;
+
+public:
+ RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen)
+ : DefaultABIInfo(CGT), XLen(XLen) {}
+
+ // DefaultABIInfo's classifyReturnType and classifyArgumentType are
+ // non-virtual, but computeInfo is virtual, so we overload it.
+ void computeInfo(CGFunctionInfo &FI) const override;
+
+ ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed,
+ int &ArgGPRsLeft) const;
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
+
+ ABIArgInfo extendType(QualType Ty) const;
+};
+} // end anonymous namespace
+
+void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ QualType RetTy = FI.getReturnType();
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(RetTy);
+
+ // IsRetIndirect is true if classifyArgumentType indicated the value should
+ // be passed indirect or if the type size is greater than 2*xlen. e.g. fp128
+ // is passed direct in LLVM IR, relying on the backend lowering code to
+ // rewrite the argument list and pass indirectly on RV32.
+ bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect ||
+ getContext().getTypeSize(RetTy) > (2 * XLen);
+
+ // We must track the number of GPRs used in order to conform to the RISC-V
+ // ABI, as integer scalars passed in registers should have signext/zeroext
+ // when promoted, but are anyext if passed on the stack. As GPR usage is
+ // different for variadic arguments, we must also track whether we are
+ // examining a vararg or not.
+ int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
+ int NumFixedArgs = FI.getNumRequiredArgs();
+
+ int ArgNum = 0;
+ for (auto &ArgInfo : FI.arguments()) {
+ bool IsFixed = ArgNum < NumFixedArgs;
+ ArgInfo.info = classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft);
+ ArgNum++;
+ }
+}
+
+ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
+ int &ArgGPRsLeft) const {
+ assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
+ Ty = useFirstFieldIfTransparentUnion(Ty);
+
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always passed indirectly.
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
+ if (ArgGPRsLeft)
+ ArgGPRsLeft -= 1;
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
+ CGCXXABI::RAA_DirectInMemory);
+ }
+
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), Ty, true))
+ return ABIArgInfo::getIgnore();
+
+ uint64_t Size = getContext().getTypeSize(Ty);
+ uint64_t NeededAlign = getContext().getTypeAlign(Ty);
+ bool MustUseStack = false;
+ // Determine the number of GPRs needed to pass the current argument
+ // according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
+ // register pairs, so may consume 3 registers.
+ int NeededArgGPRs = 1;
+ if (!IsFixed && NeededAlign == 2 * XLen)
+ NeededArgGPRs = 2 + (ArgGPRsLeft % 2);
+ else if (Size > XLen && Size <= 2 * XLen)
+ NeededArgGPRs = 2;
+
+ if (NeededArgGPRs > ArgGPRsLeft) {
+ MustUseStack = true;
+ NeededArgGPRs = ArgGPRsLeft;
+ }
+
+ ArgGPRsLeft -= NeededArgGPRs;
+
+ if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ // All integral types are promoted to XLen width, unless passed on the
+ // stack.
+ if (Size < XLen && Ty->isIntegralOrEnumerationType() && !MustUseStack) {
+ return extendType(Ty);
+ }
+
+ return ABIArgInfo::getDirect();
+ }
+
+ // Aggregates which are <= 2*XLen will be passed in registers if possible,
+ // so coerce to integers.
+ if (Size <= 2 * XLen) {
+ unsigned Alignment = getContext().getTypeAlign(Ty);
+
+ // Use a single XLen int if possible, 2*XLen if 2*XLen alignment is
+ // required, and a 2-element XLen array if only XLen alignment is required.
+ if (Size <= XLen) {
+ return ABIArgInfo::getDirect(
+ llvm::IntegerType::get(getVMContext(), XLen));
+ } else if (Alignment == 2 * XLen) {
+ return ABIArgInfo::getDirect(
+ llvm::IntegerType::get(getVMContext(), 2 * XLen));
+ } else {
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(
+ llvm::IntegerType::get(getVMContext(), XLen), 2));
+ }
+ }
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+}
+
+ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
+ return ABIArgInfo::getIgnore();
+
+ int ArgGPRsLeft = 2;
+
+ // The rules for return and argument types are the same, so defer to
+ // classifyArgumentType.
+ return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft);
+}
+
+Address RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);
+
+ // Empty records are ignored for parameter passing purposes.
+ if (isEmptyRecord(getContext(), Ty, true)) {
+ Address Addr(CGF.Builder.CreateLoad(VAListAddr), SlotSize);
+ Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
+ return Addr;
+ }
+
+ std::pair<CharUnits, CharUnits> SizeAndAlign =
+ getContext().getTypeInfoInChars(Ty);
+
+ // Arguments bigger than 2*Xlen bytes are passed indirectly.
+ bool IsIndirect = SizeAndAlign.first > 2 * SlotSize;
+
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, SizeAndAlign,
+ SlotSize, /*AllowHigherAlign=*/true);
+}
+
+ABIArgInfo RISCVABIInfo::extendType(QualType Ty) const {
+ int TySize = getContext().getTypeSize(Ty);
+ // RV64 ABI requires unsigned 32 bit integers to be sign extended.
+ if (XLen == 64 && Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
+ return ABIArgInfo::getSignExtend(Ty);
+ return ABIArgInfo::getExtend(Ty);
+}
+
+namespace {
+class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen)
+ : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen)) {}
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override {
+ const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (!FD) return;
+
+ const auto *Attr = FD->getAttr<RISCVInterruptAttr>();
+ if (!Attr)
+ return;
+
+ const char *Kind;
+ switch (Attr->getInterrupt()) {
+ case RISCVInterruptAttr::user: Kind = "user"; break;
+ case RISCVInterruptAttr::supervisor: Kind = "supervisor"; break;
+ case RISCVInterruptAttr::machine: Kind = "machine"; break;
+ }
+
+ auto *Fn = cast<llvm::Function>(GV);
+
+ Fn->addFnAttr("interrupt", Kind);
+ }
+};
+} // namespace
//===----------------------------------------------------------------------===//
// Driver code
@@ -8889,6 +9123,11 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
case llvm::Triple::msp430:
return SetCGInfo(new MSP430TargetCodeGenInfo(Types));
+ case llvm::Triple::riscv32:
+ return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 32));
+ case llvm::Triple::riscv64:
+ return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 64));
+
case llvm::Triple::systemz: {
bool HasVector = getTarget().getABI() == "vector";
return SetCGInfo(new SystemZTargetCodeGenInfo(Types, HasVector));
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
index d745e420c4a5..b530260ea48f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
@@ -57,8 +57,7 @@ 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,
- ForDefinition_t IsForDefinition) const {}
+ CodeGen::CodeGenModule &M) const {}
/// emitTargetMD - Provides a convenient hook to handle extra
/// target-specific metadata for the given global.
@@ -267,7 +266,7 @@ public:
virtual llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S,
llvm::LLVMContext &C) const;
- /// Inteface class for filling custom fields of a block literal for OpenCL.
+ /// Interface class for filling custom fields of a block literal for OpenCL.
class TargetOpenCLBlockHelper {
public:
typedef std::pair<llvm::Value *, StringRef> ValueTy;
@@ -297,6 +296,13 @@ public:
createEnqueuedBlockKernel(CodeGenFunction &CGF,
llvm::Function *BlockInvokeFunc,
llvm::Value *BlockLiteral) const;
+
+ /// \return true if the target supports alias from the unmangled name to the
+ /// mangled name of functions declared within an extern "C" region and marked
+ /// as 'used', and having internal linkage.
+ virtual bool shouldEmitStaticExternCAliases() const { return true; }
+
+ virtual void setCUDAKernelCallingConvention(const FunctionType *&FT) const {}
};
} // namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp b/contrib/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp
index cfb93d6a9fcc..2f8a591a3e7f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp
@@ -95,7 +95,7 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
case Stmt::CaseStmtClass:
case Stmt::DefaultStmtClass:
case Stmt::LabelStmtClass:
- llvm_unreachable("the loop bellow handles labels and cases");
+ llvm_unreachable("the loop below handles labels and cases");
break;
default:
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
index 85e466a4409d..99d588d9c009 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
@@ -1,4 +1,4 @@
-//===--- Action.cpp - Abstract compilation steps --------------------------===//
+//===- Action.cpp - Abstract compilation steps ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,16 +8,15 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Action.h"
-#include "clang/Driver/ToolChain.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Regex.h"
#include <cassert>
-using namespace clang::driver;
+#include <string>
+
+using namespace clang;
+using namespace driver;
using namespace llvm::opt;
-Action::~Action() {}
+Action::~Action() = default;
const char *Action::getClassName(ActionClass AC) {
switch (AC) {
@@ -97,16 +96,23 @@ std::string Action::getOffloadingKindPrefix() const {
return "device-cuda";
case OFK_OpenMP:
return "device-openmp";
+ case OFK_HIP:
+ return "device-hip";
// TODO: Add other programming models here.
}
if (!ActiveOffloadKindMask)
- return "";
+ return {};
std::string Res("host");
+ assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
+ (ActiveOffloadKindMask & OFK_HIP)) &&
+ "Cannot offload CUDA and HIP at the same time");
if (ActiveOffloadKindMask & OFK_Cuda)
Res += "-cuda";
+ if (ActiveOffloadKindMask & OFK_HIP)
+ Res += "-hip";
if (ActiveOffloadKindMask & OFK_OpenMP)
Res += "-openmp";
@@ -119,11 +125,11 @@ std::string Action::getOffloadingKindPrefix() const {
/// for each offloading kind.
std::string
Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
- llvm::StringRef NormalizedTriple,
+ StringRef NormalizedTriple,
bool CreatePrefixForHost) {
// Don't generate prefix for host actions unless required.
if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
- return "";
+ return {};
std::string Res("-");
Res += GetOffloadKindName(Kind);
@@ -134,7 +140,7 @@ Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
/// Return a string with the offload kind name. If that is not defined, we
/// assume 'host'.
-llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) {
+StringRef Action::GetOffloadKindName(OffloadKind Kind) {
switch (Kind) {
case OFK_None:
case OFK_Host:
@@ -143,6 +149,8 @@ llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) {
return "cuda";
case OFK_OpenMP:
return "openmp";
+ case OFK_HIP:
+ return "hip";
// TODO: Add other programming models here.
}
@@ -153,12 +161,11 @@ llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) {
void InputAction::anchor() {}
InputAction::InputAction(const Arg &_Input, types::ID _Type)
- : Action(InputClass, _Type), Input(_Input) {
-}
+ : Action(InputClass, _Type), Input(_Input) {}
void BindArchAction::anchor() {}
-BindArchAction::BindArchAction(Action *Input, llvm::StringRef ArchName)
+BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
: Action(BindArchClass, Input), ArchName(ArchName) {}
void OffloadAction::anchor() {}
@@ -300,8 +307,7 @@ JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
: Action(Kind, Input, Type) {}
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
- : Action(Kind, Inputs, Type) {
-}
+ : Action(Kind, Inputs, Type) {}
void PreprocessJobAction::anchor() {}
@@ -341,20 +347,17 @@ AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
void LinkJobAction::anchor() {}
LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
- : JobAction(LinkJobClass, Inputs, Type) {
-}
+ : JobAction(LinkJobClass, Inputs, Type) {}
void LipoJobAction::anchor() {}
LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
- : JobAction(LipoJobClass, Inputs, Type) {
-}
+ : JobAction(LipoJobClass, Inputs, Type) {}
void DsymutilJobAction::anchor() {}
DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
- : JobAction(DsymutilJobClass, Inputs, Type) {
-}
+ : JobAction(DsymutilJobClass, Inputs, Type) {}
void VerifyJobAction::anchor() {}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
index 645da5059587..ca2525dd07fb 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -1,4 +1,4 @@
-//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
+//===- Compilation.cpp - Compilation Task Implementation ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,32 +8,48 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Compilation.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+#include <system_error>
+#include <utility>
-using namespace clang::driver;
using namespace clang;
+using namespace driver;
using namespace llvm::opt;
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
InputArgList *_Args, DerivedArgList *_TranslatedArgs,
bool ContainsError)
- : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
- Args(_Args), TranslatedArgs(_TranslatedArgs), ForDiagnostics(false),
- ContainsError(ContainsError) {
+ : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
+ TranslatedArgs(_TranslatedArgs), ContainsError(ContainsError) {
// The offloading host toolchain is the default toolchain.
OrderedOffloadingToolchains.insert(
std::make_pair(Action::OFK_Host, &DefaultToolChain));
}
Compilation::~Compilation() {
+ // Remove temporary files. This must be done before arguments are freed, as
+ // the file names might be derived from the input arguments.
+ if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
+ CleanupFileList(TempFiles);
+
delete TranslatedArgs;
delete Args;
@@ -74,9 +90,8 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
}
// Add allocated arguments to the final DAL.
- for (auto ArgPtr : AllocatedArgs) {
+ for (auto ArgPtr : AllocatedArgs)
Entry->AddSynthesizedArg(ArgPtr);
- }
}
return *Entry;
@@ -105,7 +120,7 @@ bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
// so we don't need to check again.
if (IssueErrors)
- getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
+ getDriver().Diag(diag::err_drv_unable_to_remove_file)
<< EC.message();
return false;
}
@@ -115,9 +130,8 @@ bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
bool Compilation::CleanupFileList(const ArgStringList &Files,
bool IssueErrors) const {
bool Success = true;
- for (ArgStringList::const_iterator
- it = Files.begin(), ie = Files.end(); it != ie; ++it)
- Success &= CleanupFile(*it, IssueErrors);
+ for (const auto &File: Files)
+ Success &= CleanupFile(File, IssueErrors);
return Success;
}
@@ -125,14 +139,12 @@ bool Compilation::CleanupFileMap(const ArgStringMap &Files,
const JobAction *JA,
bool IssueErrors) const {
bool Success = true;
- for (ArgStringMap::const_iterator
- it = Files.begin(), ie = Files.end(); it != ie; ++it) {
-
+ for (const auto &File : Files) {
// If specified, only delete the files associated with the JobAction.
// Otherwise, delete all files in the map.
- if (JA && it->first != JA)
+ if (JA && File.first != JA)
continue;
- Success &= CleanupFile(it->second, IssueErrors);
+ Success &= CleanupFile(File.second, IssueErrors);
}
return Success;
}
@@ -151,7 +163,7 @@ int Compilation::ExecuteCommand(const Command &C,
llvm::sys::fs::F_Append |
llvm::sys::fs::F_Text);
if (EC) {
- getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
+ getDriver().Diag(diag::err_drv_cc_print_options_failure)
<< EC.message();
FailingCommand = &C;
delete OS;
@@ -173,7 +185,7 @@ int Compilation::ExecuteCommand(const Command &C,
int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
if (!Error.empty()) {
assert(Res && "Error string set with 0 result code!");
- getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
+ getDriver().Diag(diag::err_drv_command_failure) << Error;
}
if (Res)
@@ -186,21 +198,20 @@ 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))
+ // CUDA/HIP 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) || A->isOffloading(Action::OFK_HIP))
return true;
for (const auto &CI : FailingCommands)
if (A == &(CI.second->getSource()))
return true;
- for (const Action *AI : A->inputs())
+ for (const auto *AI : A->inputs())
if (ActionFailed(AI, FailingCommands))
return true;
@@ -239,6 +250,10 @@ void Compilation::initCompilationForDiagnostics() {
AllActions.clear();
Jobs.clear();
+ // Remove temporary files.
+ if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
+ CleanupFileList(TempFiles);
+
// Clear temporary/results file lists.
TempFiles.clear();
ResultFiles.clear();
@@ -256,6 +271,9 @@ void Compilation::initCompilationForDiagnostics() {
// Redirect stdout/stderr to /dev/null.
Redirects = {None, {""}, {""}};
+
+ // Temporary files added by diagnostics should be kept.
+ ForceKeepTempFiles = true;
}
StringRef Compilation::getSysRoot() const {
diff --git a/contrib/llvm/tools/clang/lib/Driver/Distro.cpp b/contrib/llvm/tools/clang/lib/Driver/Distro.cpp
index f15c919b9aae..2c4d44faf8d0 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Distro.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Distro.cpp
@@ -24,7 +24,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
StringRef Data = File.get()->getBuffer();
SmallVector<StringRef, 16> Lines;
Data.split(Lines, "\n");
- Distro::DistroType Version = Distro::UnknownDistro;
+ Distro::DistroType Version = Distro::UnknownDistro;
for (StringRef Line : Lines)
if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(17))
@@ -49,6 +49,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
.Case("zesty", Distro::UbuntuZesty)
.Case("artful", Distro::UbuntuArtful)
.Case("bionic", Distro::UbuntuBionic)
+ .Case("cosmic", Distro::UbuntuCosmic)
.Default(Distro::UnknownDistro);
if (Version != Distro::UnknownDistro)
return Version;
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
index c890f7741503..952a716cb6e6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -12,6 +12,7 @@
#include "ToolChains/AMDGPU.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
+#include "ToolChains/BareMetal.h"
#include "ToolChains/Clang.h"
#include "ToolChains/CloudABI.h"
#include "ToolChains/Contiki.h"
@@ -22,20 +23,21 @@
#include "ToolChains/FreeBSD.h"
#include "ToolChains/Fuchsia.h"
#include "ToolChains/Gnu.h"
-#include "ToolChains/BareMetal.h"
+#include "ToolChains/HIP.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
#include "ToolChains/Lanai.h"
#include "ToolChains/Linux.h"
+#include "ToolChains/MSVC.h"
#include "ToolChains/MinGW.h"
#include "ToolChains/Minix.h"
#include "ToolChains/MipsLinux.h"
-#include "ToolChains/MSVC.h"
#include "ToolChains/Myriad.h"
#include "ToolChains/NaCl.h"
#include "ToolChains/NetBSD.h"
#include "ToolChains/OpenBSD.h"
#include "ToolChains/PS4CPU.h"
+#include "ToolChains/RISCV.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
#include "ToolChains/WebAssembly.h"
@@ -57,6 +59,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptSpecifier.h"
@@ -69,9 +72,9 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/StringSaver.h"
#include <map>
#include <memory>
#include <utility>
@@ -83,20 +86,20 @@ using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
-Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
+Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> VFS)
: Opts(createDriverOptTable()), Diags(Diags), VFS(std::move(VFS)),
Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
- SysRoot(DEFAULT_SYSROOT),
- DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
- CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
- CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
- CCGenDiagnostics(false), DefaultTargetTriple(DefaultTargetTriple),
- CCCGenericGCCName(""), Saver(Alloc),
- CheckInputsExist(true), CCCUsePCH(true),
- GenReproducer(false), SuppressMissingInputWarning(false) {
+ SysRoot(DEFAULT_SYSROOT), DriverTitle("clang LLVM compiler"),
+ CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
+ CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false),
+ CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+ CCGenDiagnostics(false), TargetTriple(TargetTriple),
+ CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
+ CCCUsePCH(true), GenReproducer(false),
+ SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
@@ -129,11 +132,12 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
void Driver::ParseDriverMode(StringRef ProgramName,
ArrayRef<const char *> Args) {
- ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
+ if (ClangNameParts.isEmpty())
+ ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
setDriverModeFromOption(ClangNameParts.DriverMode);
for (const char *ArgPtr : Args) {
- // Ingore nullptrs, they are response file's EOL markers
+ // Ignore nullptrs, they are the response file's EOL markers.
if (ArgPtr == nullptr)
continue;
const StringRef Arg = ArgPtr;
@@ -148,15 +152,13 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
return;
StringRef Value = Opt.drop_front(OptName.size());
- const unsigned M = llvm::StringSwitch<unsigned>(Value)
- .Case("gcc", GCCMode)
- .Case("g++", GXXMode)
- .Case("cpp", CPPMode)
- .Case("cl", CLMode)
- .Default(~0U);
-
- if (M != ~0U)
- Mode = static_cast<DriverMode>(M);
+ if (auto M = llvm::StringSwitch<llvm::Optional<DriverMode>>(Value)
+ .Case("gcc", GCCMode)
+ .Case("g++", GXXMode)
+ .Case("cpp", CPPMode)
+ .Case("cl", CLMode)
+ .Default(None))
+ Mode = *M;
else
Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
}
@@ -188,9 +190,19 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
// Check for unsupported options.
for (const Arg *A : Args) {
if (A->getOption().hasFlag(options::Unsupported)) {
- Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
- ContainsError |= Diags.getDiagnosticLevel(diag::err_drv_unsupported_opt,
- SourceLocation()) >
+ unsigned DiagID;
+ auto ArgString = A->getAsString(Args);
+ std::string Nearest;
+ if (getOpts().findNearest(
+ ArgString, Nearest, IncludedFlagsBitmask,
+ ExcludedFlagsBitmask | options::Unsupported) > 1) {
+ DiagID = diag::err_drv_unsupported_opt;
+ Diag(DiagID) << ArgString;
+ } else {
+ DiagID = diag::err_drv_unsupported_opt_with_suggestion;
+ Diag(DiagID) << ArgString << Nearest;
+ }
+ ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
DiagnosticsEngine::Warning;
continue;
}
@@ -205,11 +217,20 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
}
for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
- auto ID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
- : diag::err_drv_unknown_argument;
-
- Diags.Report(ID) << A->getAsString(Args);
- ContainsError |= Diags.getDiagnosticLevel(ID, SourceLocation()) >
+ unsigned DiagID;
+ auto ArgString = A->getAsString(Args);
+ std::string Nearest;
+ if (getOpts().findNearest(
+ ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) {
+ DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
+ : diag::err_drv_unknown_argument;
+ Diags.Report(DiagID) << ArgString;
+ } else {
+ DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion
+ : diag::err_drv_unknown_argument_with_suggestion;
+ Diags.Report(DiagID) << ArgString << Nearest;
+ }
+ ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
DiagnosticsEngine::Warning;
}
@@ -266,11 +287,12 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
}
static Arg *MakeInputArg(DerivedArgList &Args, OptTable &Opts,
- StringRef Value) {
+ StringRef Value, bool Claim = true) {
Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,
Args.getBaseArgs().MakeIndex(Value), Value.data());
Args.AddSynthesizedArg(A);
- A->claim();
+ if (Claim)
+ A->claim();
return A;
}
@@ -338,7 +360,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
if (A->getOption().matches(options::OPT__DASH_DASH)) {
A->claim();
for (StringRef Val : A->getValues())
- DAL->append(MakeInputArg(*DAL, *Opts, Val));
+ DAL->append(MakeInputArg(*DAL, *Opts, Val, false));
continue;
}
@@ -363,23 +385,23 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
return DAL;
}
-/// \brief Compute target triple from args.
+/// Compute target triple from args.
///
/// This routine provides the logic to compute a target triple from various
/// args passed to the driver and the default triple string.
static llvm::Triple computeTargetTriple(const Driver &D,
- StringRef DefaultTargetTriple,
+ StringRef TargetTriple,
const ArgList &Args,
StringRef DarwinArchName = "") {
// FIXME: Already done in Compilation *Driver::BuildCompilation
if (const Arg *A = Args.getLastArg(options::OPT_target))
- DefaultTargetTriple = A->getValue();
+ TargetTriple = A->getValue();
- llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+ llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
// Handle Apple-specific options available here.
if (Target.isOSBinFormatMachO()) {
- // If an explict Darwin arch name is given, that trumps all.
+ // If an explicit Darwin arch name is given, that trumps all.
if (!DarwinArchName.empty()) {
tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName);
return Target;
@@ -462,7 +484,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
return Target;
}
-// \brief Parse the LTO options and record the type of LTO compilation
+// Parse the LTO options and record the type of LTO compilation
// based on which -f(no-)?lto(=.*)? option occurs last.
void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
LTOMode = LTOK_None;
@@ -518,24 +540,55 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
InputList &Inputs) {
//
- // CUDA
+ // CUDA/HIP
//
- // We need to generate a CUDA toolchain if any of the inputs has a CUDA type.
- if (llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
+ // We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA
+ // or HIP type. However, mixed CUDA/HIP compilation is not supported.
+ bool IsCuda =
+ llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
return types::isCuda(I.first);
- })) {
+ });
+ bool IsHIP =
+ llvm::any_of(Inputs,
+ [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
+ return types::isHIP(I.first);
+ }) ||
+ C.getInputArgs().hasArg(options::OPT_hip_link);
+ if (IsCuda && IsHIP) {
+ Diag(clang::diag::err_drv_mix_cuda_hip);
+ return;
+ }
+ if (IsCuda) {
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
const llvm::Triple &HostTriple = HostTC->getTriple();
- llvm::Triple CudaTriple(HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda"
- : "nvptx-nvidia-cuda");
- // Use the CUDA and host triples as the key into the ToolChains map, because
- // the device toolchain we create depends on both.
+ StringRef DeviceTripleStr;
+ auto OFK = Action::OFK_Cuda;
+ DeviceTripleStr =
+ HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda";
+ llvm::Triple CudaTriple(DeviceTripleStr);
+ // Use the CUDA and host triples as the key into the ToolChains map,
+ // because the device toolchain we create depends on both.
auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()];
if (!CudaTC) {
CudaTC = llvm::make_unique<toolchains::CudaToolChain>(
- *this, CudaTriple, *HostTC, C.getInputArgs(), Action::OFK_Cuda);
+ *this, CudaTriple, *HostTC, C.getInputArgs(), OFK);
}
- C.addOffloadDeviceToolChain(CudaTC.get(), Action::OFK_Cuda);
+ C.addOffloadDeviceToolChain(CudaTC.get(), OFK);
+ } else if (IsHIP) {
+ const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
+ const llvm::Triple &HostTriple = HostTC->getTriple();
+ StringRef DeviceTripleStr;
+ auto OFK = Action::OFK_HIP;
+ DeviceTripleStr = "amdgcn-amd-amdhsa";
+ llvm::Triple HIPTriple(DeviceTripleStr);
+ // Use the HIP and host triples as the key into the ToolChains map,
+ // because the device toolchain we create depends on both.
+ auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()];
+ if (!HIPTC) {
+ HIPTC = llvm::make_unique<toolchains::HIPToolChain>(
+ *this, HIPTriple, *HostTC, C.getInputArgs());
+ }
+ C.addOffloadDeviceToolChain(HIPTC.get(), OFK);
}
//
@@ -899,19 +952,19 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
GenReproducer = Args.hasFlag(options::OPT_gen_reproducer,
options::OPT_fno_crash_diagnostics,
!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"));
- // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld
+ // FIXME: TargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
// clang-cl targets MSVC-style Win32.
- llvm::Triple T(DefaultTargetTriple);
+ llvm::Triple T(TargetTriple);
T.setOS(llvm::Triple::Win32);
T.setVendor(llvm::Triple::PC);
T.setEnvironment(llvm::Triple::MSVC);
T.setObjectFormat(llvm::Triple::COFF);
- DefaultTargetTriple = T.str();
+ TargetTriple = T.str();
}
if (const Arg *A = Args.getLastArg(options::OPT_target))
- DefaultTargetTriple = A->getValue();
+ TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Dir = InstalledDir = A->getValue();
for (const Arg *A : Args.filtered(options::OPT_B)) {
@@ -959,7 +1012,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Owned by the host.
const ToolChain &TC = getToolChain(
- *UArgs, computeTargetTriple(*this, DefaultTargetTriple, *UArgs));
+ *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
// The compilation takes ownership of Args.
Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,
@@ -1097,8 +1150,9 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
// When clang crashes, produce diagnostic information including the fully
// preprocessed source file(s). Request that the developer attach the
// diagnostic information to a bug report.
-void Driver::generateCompilationDiagnostics(Compilation &C,
- const Command &FailingCommand) {
+void Driver::generateCompilationDiagnostics(
+ Compilation &C, const Command &FailingCommand,
+ StringRef AdditionalInformation, CompilationDiagnosticReport *Report) {
if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))
return;
@@ -1200,9 +1254,6 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// If any of the preprocessing commands failed, clean up and exit.
if (!FailingCommands.empty()) {
- if (!isSaveTempsEnabled())
- C.CleanupFileList(C.getTempFiles(), true);
-
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating preprocessed source(s).";
return;
@@ -1224,6 +1275,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
SmallString<128> ReproCrashFilename;
for (const char *TempFile : TempFiles) {
Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
+ if (Report)
+ Report->TemporaryFiles.push_back(TempFile);
if (ReproCrashFilename.empty()) {
ReproCrashFilename = TempFile;
llvm::sys::path::replace_extension(ReproCrashFilename, ".crash");
@@ -1239,12 +1292,13 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// Assume associated files are based off of the first temporary file.
CrashReportInfo CrashInfo(TempFiles[0], VFS);
- std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh";
+ llvm::SmallString<128> Script(CrashInfo.Filename);
+ llvm::sys::path::replace_extension(Script, "sh");
std::error_code EC;
- llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::F_Excl);
+ llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew);
if (EC) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating run script: " + Script + " " + EC.message();
+ << "Error generating run script: " << Script << " " << EC.message();
} else {
ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"
<< "# Driver args: ";
@@ -1252,6 +1306,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
ScriptOS << "# Original command: ";
Cmd.Print(ScriptOS, "\n", /*Quote=*/true);
Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
+ if (!AdditionalInformation.empty())
+ ScriptOS << "\n# Additional information: " << AdditionalInformation
+ << "\n";
+ if (Report)
+ Report->TemporaryFiles.push_back(Script.str());
Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
}
@@ -1312,9 +1371,6 @@ int Driver::ExecuteCompilation(
C.ExecuteJobs(C.getJobs(), FailingCommands);
- // Remove temp files.
- C.CleanupFileList(C.getTempFiles());
-
// If the command succeeded, we are done.
if (FailingCommands.empty())
return 0;
@@ -1405,53 +1461,66 @@ static void PrintDiagnosticCategories(raw_ostream &OS) {
OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';
}
-void Driver::handleAutocompletions(StringRef PassedFlags) const {
+void Driver::HandleAutocompletions(StringRef PassedFlags) const {
+ if (PassedFlags == "")
+ return;
// Print out all options that start with a given argument. This is used for
// shell autocompletion.
std::vector<std::string> SuggestedCompletions;
+ std::vector<std::string> Flags;
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] == '#') {
+
+ // Parse PassedFlags by "," as all the command-line flags are passed to this
+ // function separated by ","
+ StringRef TargetFlags = PassedFlags;
+ while (TargetFlags != "") {
+ StringRef CurFlag;
+ std::tie(CurFlag, TargetFlags) = TargetFlags.split(",");
+ Flags.push_back(std::string(CurFlag));
+ }
+
+ // We want to show cc1-only options only when clang is invoked with -cc1 or
+ // -Xclang.
+ if (std::find(Flags.begin(), Flags.end(), "-Xclang") != Flags.end() ||
+ std::find(Flags.begin(), Flags.end(), "-cc1") != Flags.end())
DisableFlags &= ~options::NoDriverOption;
- PassedFlags = PassedFlags.substr(1);
+
+ StringRef Cur;
+ Cur = Flags.at(Flags.size() - 1);
+ StringRef Prev;
+ if (Flags.size() >= 2) {
+ Prev = Flags.at(Flags.size() - 2);
+ SuggestedCompletions = Opts->suggestValueCompletions(Prev, Cur);
}
- if (PassedFlags.find(',') == StringRef::npos) {
+ if (SuggestedCompletions.empty())
+ SuggestedCompletions = Opts->suggestValueCompletions(Cur, "");
+
+ if (SuggestedCompletions.empty()) {
// 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);
+ SuggestedCompletions = Opts->findByPrefix(Cur, 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))
+ if (S.startswith(Cur))
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::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';
@@ -1554,13 +1623,19 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
- llvm::outs() << GetProgramPath(A->getValue(), TC) << "\n";
+ StringRef ProgName = A->getValue();
+
+ // Null program name cannot have a path.
+ if (! ProgName.empty())
+ llvm::outs() << GetProgramPath(ProgName, TC);
+
+ llvm::outs() << "\n";
return false;
}
if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
StringRef PassedFlags = A->getValue();
- handleAutocompletions(PassedFlags);
+ HandleAutocompletions(PassedFlags);
return false;
}
@@ -1686,7 +1761,7 @@ void Driver::PrintActions(const Compilation &C) const {
PrintActions1(C, A, Ids);
}
-/// \brief Check whether the given input tree contains any compilation or
+/// Check whether the given input tree contains any compilation or
/// assembly actions.
static bool ContainsCompileOrAssembleAction(const Action *A) {
if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) ||
@@ -1787,7 +1862,7 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
}
}
-/// \brief Check that the file referenced by Value exists. If it doesn't,
+/// Check that the file referenced by Value exists. If it doesn't,
/// issue a diagnostic and return false.
static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
StringRef Value, types::ID Ty) {
@@ -2082,9 +2157,10 @@ class OffloadingActionBuilder final {
}
};
- /// \brief CUDA action builder. It injects device code in the host backend
- /// action.
- class CudaActionBuilder final : public DeviceActionBuilder {
+ /// Base class for CUDA/HIP action builder. It injects device code in
+ /// the host backend action.
+ class CudaActionBuilderBase : public DeviceActionBuilder {
+ protected:
/// Flags to signal if the user requested host-only or device-only
/// compilation.
bool CompileHostOnly = false;
@@ -2101,115 +2177,11 @@ class OffloadingActionBuilder final {
/// Flag that is set to true if this builder acted on the current input.
bool IsActive = false;
-
public:
- CudaActionBuilder(Compilation &C, DerivedArgList &Args,
- const Driver::InputList &Inputs)
- : DeviceActionBuilder(C, Args, Inputs, Action::OFK_Cuda) {}
-
- ActionBuilderReturnCode
- getDeviceDependences(OffloadAction::DeviceDependences &DA,
- phases::ID CurPhase, phases::ID FinalPhase,
- PhasesTy &Phases) override {
- if (!IsActive)
- return ABRT_Inactive;
-
- // If we don't have more CUDA actions, we don't have any dependences to
- // create for the host.
- if (CudaDeviceActions.empty())
- return ABRT_Success;
-
- assert(CudaDeviceActions.size() == GpuArchList.size() &&
- "Expecting one action per GPU architecture.");
- assert(!CompileHostOnly &&
- "Not expecting CUDA actions in host-only compilation.");
-
- // If we are generating code for the device or we are in a backend phase,
- // we attempt to generate the fat binary. We compile each arch to ptx and
- // assemble to cubin, then feed the cubin *and* the ptx into a device
- // "link" action, which uses fatbinary to combine these cubins into one
- // fatbin. The fatbin is then an input to the host action if not in
- // device-only mode.
- if (CompileDeviceOnly || CurPhase == phases::Backend) {
- ActionList DeviceActions;
- for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
- // Produce the device action from the current phase up to the assemble
- // phase.
- for (auto Ph : Phases) {
- // Skip the phases that were already dealt with.
- if (Ph < CurPhase)
- continue;
- // We have to be consistent with the host final phase.
- if (Ph > FinalPhase)
- break;
-
- CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction(
- C, Args, Ph, CudaDeviceActions[I]);
-
- if (Ph == phases::Assemble)
- break;
- }
-
- // If we didn't reach the assemble phase, we can't generate the fat
- // binary. We don't need to generate the fat binary if we are not in
- // device-only mode.
- if (!isa<AssembleJobAction>(CudaDeviceActions[I]) ||
- CompileDeviceOnly)
- continue;
-
- Action *AssembleAction = CudaDeviceActions[I];
- assert(AssembleAction->getType() == types::TY_Object);
- assert(AssembleAction->getInputs().size() == 1);
-
- Action *BackendAction = AssembleAction->getInputs()[0];
- assert(BackendAction->getType() == types::TY_PP_Asm);
-
- for (auto &A : {AssembleAction, BackendAction}) {
- OffloadAction::DeviceDependences DDep;
- DDep.add(*A, *ToolChains.front(), CudaArchToString(GpuArchList[I]),
- Action::OFK_Cuda);
- DeviceActions.push_back(
- C.MakeAction<OffloadAction>(DDep, A->getType()));
- }
- }
-
- // We generate the fat binary if we have device input actions.
- if (!DeviceActions.empty()) {
- CudaFatBinary =
- C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);
-
- if (!CompileDeviceOnly) {
- DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
- Action::OFK_Cuda);
- // Clear the fat binary, it is already a dependence to an host
- // action.
- CudaFatBinary = nullptr;
- }
-
- // Remove the CUDA actions as they are already connected to an host
- // action or fat binary.
- CudaDeviceActions.clear();
- }
-
- // We avoid creating host action in device-only mode.
- return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
- } else if (CurPhase > phases::Backend) {
- // If we are past the backend phase and still have a device action, we
- // don't have to do anything as this action is already a device
- // top-level action.
- return ABRT_Success;
- }
-
- assert(CurPhase < phases::Backend && "Generating single CUDA "
- "instructions should only occur "
- "before the backend phase!");
-
- // By default, we produce an action for each device arch.
- for (Action *&A : CudaDeviceActions)
- A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
-
- return ABRT_Success;
- }
+ CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs,
+ Action::OffloadKind OFKind)
+ : DeviceActionBuilder(C, Args, Inputs, OFKind) {}
ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override {
// While generating code for CUDA, we only depend on the host input action
@@ -2222,9 +2194,10 @@ class OffloadingActionBuilder final {
assert(!GpuArchList.empty() &&
"We should have at least one GPU architecture.");
- // If the host input is not CUDA, we don't need to bother about this
- // input.
- if (IA->getType() != types::TY_CUDA) {
+ // If the host input is not CUDA or HIP, we don't need to bother about
+ // this input.
+ if (IA->getType() != types::TY_CUDA &&
+ IA->getType() != types::TY_HIP) {
// The builder will ignore this input.
IsActive = false;
return ABRT_Inactive;
@@ -2237,13 +2210,27 @@ class OffloadingActionBuilder final {
return ABRT_Success;
// Replicate inputs for each GPU architecture.
- for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
- CudaDeviceActions.push_back(C.MakeAction<InputAction>(
- IA->getInputArg(), types::TY_CUDA_DEVICE));
+ auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE
+ : types::TY_CUDA_DEVICE;
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ CudaDeviceActions.push_back(
+ C.MakeAction<InputAction>(IA->getInputArg(), Ty));
+ }
return ABRT_Success;
}
+ // If this is an unbundling action use it as is for each CUDA toolchain.
+ if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
+ CudaDeviceActions.clear();
+ for (auto Arch : GpuArchList) {
+ CudaDeviceActions.push_back(UA);
+ UA->registerDependentActionInfo(ToolChains[0], CudaArchToString(Arch),
+ AssociatedOffloadKind);
+ }
+ return ABRT_Success;
+ }
+
return IsActive ? ABRT_Success : ABRT_Inactive;
}
@@ -2252,7 +2239,7 @@ class OffloadingActionBuilder final {
auto AddTopLevel = [&](Action *A, CudaArch BoundArch) {
OffloadAction::DeviceDependences Dep;
Dep.add(*A, *ToolChains.front(), CudaArchToString(BoundArch),
- Action::OFK_Cuda);
+ AssociatedOffloadKind);
AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
};
@@ -2281,21 +2268,35 @@ class OffloadingActionBuilder final {
}
bool initialize() override {
+ assert(AssociatedOffloadKind == Action::OFK_Cuda ||
+ AssociatedOffloadKind == Action::OFK_HIP);
+
// We don't need to support CUDA.
- if (!C.hasOffloadToolChain<Action::OFK_Cuda>())
+ if (AssociatedOffloadKind == Action::OFK_Cuda &&
+ !C.hasOffloadToolChain<Action::OFK_Cuda>())
+ return false;
+
+ // We don't need to support HIP.
+ if (AssociatedOffloadKind == Action::OFK_HIP &&
+ !C.hasOffloadToolChain<Action::OFK_HIP>())
return false;
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
assert(HostTC && "No toolchain for host compilation.");
- if (HostTC->getTriple().isNVPTX()) {
- // We do not support targeting NVPTX for host compilation. Throw
+ if (HostTC->getTriple().isNVPTX() ||
+ HostTC->getTriple().getArch() == llvm::Triple::amdgcn) {
+ // We do not support targeting NVPTX/AMDGCN for host compilation. Throw
// an error and abort pipeline construction early so we don't trip
// asserts that assume device-side compilation.
- C.getDriver().Diag(diag::err_drv_cuda_nvptx_host);
+ C.getDriver().Diag(diag::err_drv_cuda_host_arch)
+ << HostTC->getTriple().getArchName();
return true;
}
- ToolChains.push_back(C.getSingleOffloadToolChain<Action::OFK_Cuda>());
+ ToolChains.push_back(
+ AssociatedOffloadKind == Action::OFK_Cuda
+ ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
+ : C.getSingleOffloadToolChain<Action::OFK_HIP>());
Arg *PartialCompilationArg = Args.getLastArg(
options::OPT_cuda_host_only, options::OPT_cuda_device_only,
@@ -2348,6 +2349,187 @@ class OffloadingActionBuilder final {
}
};
+ /// \brief CUDA action builder. It injects device code in the host backend
+ /// action.
+ class CudaActionBuilder final : public CudaActionBuilderBase {
+ public:
+ CudaActionBuilder(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs)
+ : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {}
+
+ ActionBuilderReturnCode
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) override {
+ if (!IsActive)
+ return ABRT_Inactive;
+
+ // If we don't have more CUDA actions, we don't have any dependences to
+ // create for the host.
+ if (CudaDeviceActions.empty())
+ return ABRT_Success;
+
+ assert(CudaDeviceActions.size() == GpuArchList.size() &&
+ "Expecting one action per GPU architecture.");
+ assert(!CompileHostOnly &&
+ "Not expecting CUDA actions in host-only compilation.");
+
+ // If we are generating code for the device or we are in a backend phase,
+ // we attempt to generate the fat binary. We compile each arch to ptx and
+ // assemble to cubin, then feed the cubin *and* the ptx into a device
+ // "link" action, which uses fatbinary to combine these cubins into one
+ // fatbin. The fatbin is then an input to the host action if not in
+ // device-only mode.
+ if (CompileDeviceOnly || CurPhase == phases::Backend) {
+ ActionList DeviceActions;
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ // Produce the device action from the current phase up to the assemble
+ // phase.
+ for (auto Ph : Phases) {
+ // Skip the phases that were already dealt with.
+ if (Ph < CurPhase)
+ continue;
+ // We have to be consistent with the host final phase.
+ if (Ph > FinalPhase)
+ break;
+
+ CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction(
+ C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda);
+
+ if (Ph == phases::Assemble)
+ break;
+ }
+
+ // If we didn't reach the assemble phase, we can't generate the fat
+ // binary. We don't need to generate the fat binary if we are not in
+ // device-only mode.
+ if (!isa<AssembleJobAction>(CudaDeviceActions[I]) ||
+ CompileDeviceOnly)
+ continue;
+
+ Action *AssembleAction = CudaDeviceActions[I];
+ assert(AssembleAction->getType() == types::TY_Object);
+ assert(AssembleAction->getInputs().size() == 1);
+
+ Action *BackendAction = AssembleAction->getInputs()[0];
+ assert(BackendAction->getType() == types::TY_PP_Asm);
+
+ for (auto &A : {AssembleAction, BackendAction}) {
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*A, *ToolChains.front(), CudaArchToString(GpuArchList[I]),
+ Action::OFK_Cuda);
+ DeviceActions.push_back(
+ C.MakeAction<OffloadAction>(DDep, A->getType()));
+ }
+ }
+
+ // We generate the fat binary if we have device input actions.
+ if (!DeviceActions.empty()) {
+ CudaFatBinary =
+ C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);
+
+ if (!CompileDeviceOnly) {
+ DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
+ Action::OFK_Cuda);
+ // Clear the fat binary, it is already a dependence to an host
+ // action.
+ CudaFatBinary = nullptr;
+ }
+
+ // Remove the CUDA actions as they are already connected to an host
+ // action or fat binary.
+ CudaDeviceActions.clear();
+ }
+
+ // We avoid creating host action in device-only mode.
+ return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
+ } else if (CurPhase > phases::Backend) {
+ // If we are past the backend phase and still have a device action, we
+ // don't have to do anything as this action is already a device
+ // top-level action.
+ return ABRT_Success;
+ }
+
+ assert(CurPhase < phases::Backend && "Generating single CUDA "
+ "instructions should only occur "
+ "before the backend phase!");
+
+ // By default, we produce an action for each device arch.
+ for (Action *&A : CudaDeviceActions)
+ A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
+
+ return ABRT_Success;
+ }
+ };
+ /// \brief HIP action builder. It injects device code in the host backend
+ /// action.
+ class HIPActionBuilder final : public CudaActionBuilderBase {
+ /// The linker inputs obtained for each device arch.
+ SmallVector<ActionList, 8> DeviceLinkerInputs;
+
+ public:
+ HIPActionBuilder(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs)
+ : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {}
+
+ bool canUseBundlerUnbundler() const override { return true; }
+
+ ActionBuilderReturnCode
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) override {
+ // amdgcn does not support linking of object files, therefore we skip
+ // backend and assemble phases to output LLVM IR.
+ if (CudaDeviceActions.empty() || CurPhase == phases::Backend ||
+ CurPhase == phases::Assemble)
+ return ABRT_Success;
+
+ assert((CurPhase == phases::Link ||
+ CudaDeviceActions.size() == GpuArchList.size()) &&
+ "Expecting one action per GPU architecture.");
+ assert(!CompileHostOnly &&
+ "Not expecting CUDA actions in host-only compilation.");
+
+ // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
+ // This happens to each device action originated from each input file.
+ // Later on, device actions in DeviceLinkerInputs are used to create
+ // device link actions in appendLinkDependences and the created device
+ // link actions are passed to the offload action as device dependence.
+ if (CurPhase == phases::Link) {
+ DeviceLinkerInputs.resize(CudaDeviceActions.size());
+ auto LI = DeviceLinkerInputs.begin();
+ for (auto *A : CudaDeviceActions) {
+ LI->push_back(A);
+ ++LI;
+ }
+
+ // We will pass the device action as a host dependence, so we don't
+ // need to do anything else with them.
+ CudaDeviceActions.clear();
+ return ABRT_Success;
+ }
+
+ // By default, we produce an action for each device arch.
+ for (Action *&A : CudaDeviceActions)
+ A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,
+ AssociatedOffloadKind);
+
+ return ABRT_Success;
+ }
+
+ void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {
+ // Append a new link action for each device.
+ unsigned I = 0;
+ for (auto &LI : DeviceLinkerInputs) {
+ auto *DeviceLinkAction =
+ C.MakeAction<LinkJobAction>(LI, types::TY_Image);
+ DA.add(*DeviceLinkAction, *ToolChains[0],
+ CudaArchToString(GpuArchList[I]), AssociatedOffloadKind);
+ ++I;
+ }
+ }
+ };
+
/// OpenMP action builder. The host bitcode is passed to the device frontend
/// and all the device linked images are passed to the host link phase.
class OpenMPActionBuilder final : public DeviceActionBuilder {
@@ -2514,6 +2696,9 @@ public:
// Create a specialized builder for CUDA.
SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs));
+ // Create a specialized builder for HIP.
+ SpecializedBuilders.push_back(new HIPActionBuilder(C, Args, Inputs));
+
// Create a specialized builder for OpenMP.
SpecializedBuilders.push_back(new OpenMPActionBuilder(C, Args, Inputs));
@@ -2808,22 +2993,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Args.eraseArg(options::OPT__SLASH_Yu);
YcArg = YuArg = nullptr;
}
- if (YcArg || YuArg) {
- StringRef Val = YcArg ? YcArg->getValue() : YuArg->getValue();
- bool FoundMatchingInclude = false;
- for (const Arg *Inc : Args.filtered(options::OPT_include)) {
- // FIXME: Do case-insensitive matching and consider / and \ as equal.
- if (Inc->getValue() == Val)
- FoundMatchingInclude = true;
- }
- if (!FoundMatchingInclude) {
- Diag(clang::diag::warn_drv_ycyu_no_fi_arg_clang_cl)
- << (YcArg ? YcArg : YuArg)->getSpelling();
- Args.eraseArg(options::OPT__SLASH_Yc);
- Args.eraseArg(options::OPT__SLASH_Yu);
- YcArg = YuArg = nullptr;
- }
- }
if (YcArg && Inputs.size() > 1) {
Diag(clang::diag::warn_drv_yc_multiple_inputs_clang_cl);
Args.eraseArg(options::OPT__SLASH_Yc);
@@ -2856,6 +3025,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// this compilation, warn the user about it.
phases::ID InitialPhase = PL[0];
if (InitialPhase > FinalPhase) {
+ if (InputArg->isClaimed())
+ continue;
+
// Claim here to avoid the more general unused warning.
InputArg->claim();
@@ -2890,11 +3062,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PCHPL;
types::getCompilationPhases(HeaderType, PCHPL);
- Arg *PchInputArg = MakeInputArg(Args, *Opts, YcArg->getValue());
-
// Build the pipeline for the pch file.
Action *ClangClPch =
- C.MakeAction<InputAction>(*PchInputArg, HeaderType);
+ C.MakeAction<InputAction>(*InputArg, HeaderType);
for (phases::ID Phase : PCHPL)
ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
assert(ClangClPch);
@@ -2902,6 +3072,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// The driver currently exits after the first failed command. This
// relies on that behavior, to make sure if the pch generation fails,
// the main compilation won't run.
+ // FIXME: If the main compilation fails, the PCH generation should
+ // probably not be considered successful either.
}
}
@@ -2984,8 +3156,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Args.ClaimAllArgs(options::OPT_cuda_compile_host_device);
}
-Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args,
- phases::ID Phase, Action *Input) const {
+Action *Driver::ConstructPhaseAction(
+ Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input,
+ Action::OffloadKind TargetDeviceOffloadKind) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
// Some types skip the assembler phase (e.g., llvm-bc), but we can't
@@ -3047,7 +3220,7 @@ Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args,
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
- if (isUsingLTO()) {
+ if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
@@ -3343,19 +3516,34 @@ class ToolSelector final {
const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
const ActionList *&Inputs,
ActionList &CollapsedOffloadAction) {
- if (ActionInfo.size() < 2 || !canCollapsePreprocessorAction())
+ if (ActionInfo.size() < 2)
return nullptr;
auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[0].JA);
auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[1].JA);
if (!BJ || !CJ)
return nullptr;
+ // Check if the initial input (to the compile job or its predessor if one
+ // exists) is LLVM bitcode. In that case, no preprocessor step is required
+ // and we can still collapse the compile and backend jobs when we have
+ // -save-temps. I.e. there is no need for a separate compile job just to
+ // emit unoptimized bitcode.
+ bool InputIsBitcode = true;
+ for (size_t i = 1; i < ActionInfo.size(); i++)
+ if (ActionInfo[i].JA->getType() != types::TY_LLVM_BC &&
+ ActionInfo[i].JA->getType() != types::TY_LTO_BC) {
+ InputIsBitcode = false;
+ break;
+ }
+ if (!InputIsBitcode && !canCollapsePreprocessorAction())
+ return nullptr;
+
// Get compiler tool.
const Tool *T = TC.SelectTool(*CJ);
if (!T)
return nullptr;
- if (T->canEmitIR() && (SaveTemps || EmbedBitcode))
+ if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))
return nullptr;
Inputs = &CJ->getInputs();
@@ -3571,7 +3759,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (!ArchName.empty())
TC = &getToolChain(C.getArgs(),
- computeTargetTriple(*this, DefaultTargetTriple,
+ computeTargetTriple(*this, TargetTriple,
C.getArgs(), ArchName));
else
TC = &C.getDefaultToolChain();
@@ -3666,18 +3854,30 @@ InputInfo Driver::BuildJobsForActionNoCache(
UI.DependentToolChain->getTriple().normalize(),
/*CreatePrefixForHost=*/true);
auto CurI = InputInfo(
- UA, GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,
- /*AtTopLevel=*/false, MultipleArchs,
- OffloadingPrefix),
+ UA,
+ GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,
+ /*AtTopLevel=*/false,
+ MultipleArchs ||
+ UI.DependentOffloadKind == Action::OFK_HIP,
+ OffloadingPrefix),
BaseInput);
// Save the unbundling result.
UnbundlingResults.push_back(CurI);
// Get the unique string identifier for this dependence and cache the
// result.
- CachedResults[{A, GetTriplePlusArchString(
- UI.DependentToolChain, BoundArch,
- UI.DependentOffloadKind)}] = CurI;
+ StringRef Arch;
+ if (TargetDeviceOffloadKind == Action::OFK_HIP) {
+ if (UI.DependentOffloadKind == Action::OFK_Host)
+ Arch = StringRef();
+ else
+ Arch = UI.DependentBoundArch;
+ } else
+ Arch = BoundArch;
+
+ CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch,
+ UI.DependentOffloadKind)}] =
+ CurI;
}
// Now that we have all the results generated, select the one that should be
@@ -3737,11 +3937,11 @@ InputInfo Driver::BuildJobsForActionNoCache(
}
const char *Driver::getDefaultImageName() const {
- llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+ llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
return Target.isOSWindows() ? "a.exe" : "a.out";
}
-/// \brief Create output filename based on ArgValue, which could either be a
+/// Create output filename based on ArgValue, which could either be a
/// full filename, filename without extension, or a directory. If ArgValue
/// does not provide a filename, then use BaseName, and use the extension
/// suitable for FileType.
@@ -3799,8 +3999,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
}
// Default to writing to stdout?
- if (AtTopLevel && !CCGenDiagnostics &&
- (isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile))
+ if (AtTopLevel && !CCGenDiagnostics && isa<PreprocessJobAction>(JA))
return "-";
// Is this the assembly listing for /FA?
@@ -3821,8 +4020,22 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
CCGenDiagnostics) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
- std::string TmpName = GetTemporaryPath(
- Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode()));
+ SmallString<128> TmpName;
+ const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
+ Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir);
+ if (CCGenDiagnostics && A) {
+ SmallString<128> CrashDirectory(A->getValue());
+ llvm::sys::path::append(CrashDirectory, Split.first);
+ const char *Middle = Suffix ? "-%%%%%%." : "-%%%%%%";
+ std::error_code EC =
+ llvm::sys::fs::createUniqueFile(CrashDirectory + Middle + Suffix, TmpName);
+ if (EC) {
+ Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return "";
+ }
+ } else {
+ TmpName = GetTemporaryPath(Split.first, Suffix);
+ }
return C.addTempFile(C.getArgs().MakeArgString(TmpName));
}
@@ -3976,14 +4189,14 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
void Driver::generatePrefixedToolNames(
StringRef Tool, const ToolChain &TC,
SmallVectorImpl<std::string> &Names) const {
- // FIXME: Needs a better variable than DefaultTargetTriple
- Names.emplace_back((DefaultTargetTriple + "-" + Tool).str());
+ // FIXME: Needs a better variable than TargetTriple
+ Names.emplace_back((TargetTriple + "-" + Tool).str());
Names.emplace_back(Tool);
// Allow the discovery of tools prefixed with LLVM's default target triple.
- std::string LLVMDefaultTargetTriple = llvm::sys::getDefaultTargetTriple();
- if (LLVMDefaultTargetTriple != DefaultTargetTriple)
- Names.emplace_back((LLVMDefaultTargetTriple + "-" + Tool).str());
+ std::string DefaultTargetTriple = llvm::sys::getDefaultTargetTriple();
+ if (DefaultTargetTriple != TargetTriple)
+ Names.emplace_back((DefaultTargetTriple + "-" + Tool).str());
}
static bool ScanDirForExecutable(SmallString<128> &Dir,
@@ -4054,6 +4267,9 @@ std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
// extension of .pch is assumed. "
if (!llvm::sys::path::has_extension(Output))
Output += ".pch";
+ } else if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc)) {
+ Output = YcArg->getValue();
+ llvm::sys::path::replace_extension(Output, ".pch");
} else {
Output = BaseName;
llvm::sys::path::replace_extension(Output, ".pch");
@@ -4184,6 +4400,10 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::avr:
TC = llvm::make_unique<toolchains::AVRToolChain>(*this, Target, Args);
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ TC = llvm::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
+ break;
default:
if (Target.getVendor() == llvm::Triple::Myriad)
TC = llvm::make_unique<toolchains::MyriadToolChain>(*this, Target,
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
index 765c05752d8f..bd1a9bd8e3eb 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -1,4 +1,4 @@
-//===--- Job.cpp - Command to Execute -------------------------------------===//
+//===- Job.cpp - Command to Execute ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,14 +9,14 @@
#include "clang/Driver/Job.h"
#include "InputInfo.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#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/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
@@ -24,23 +24,27 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <cassert>
-using namespace clang::driver;
-using llvm::raw_ostream;
-using llvm::StringRef;
-using llvm::ArrayRef;
+#include <cstddef>
+#include <string>
+#include <system_error>
+#include <utility>
+
+using namespace clang;
+using namespace driver;
Command::Command(const Action &Source, const Tool &Creator,
const char *Executable, const ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs)
: Source(Source), Creator(Creator), Executable(Executable),
- Arguments(Arguments), ResponseFile(nullptr) {
+ Arguments(Arguments) {
for (const auto &II : Inputs)
if (II.isFilename())
InputFilenames.push_back(II.getFilename());
}
-/// @brief Check if the compiler flag in question should be skipped when
+/// Check if the compiler flag in question should be skipped when
/// emitting a reproducer. Also track how many arguments it has and if the
/// option is some kind of include path.
static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
@@ -67,7 +71,7 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
.Cases("-iframework", "-include-pch", true)
.Default(false);
if (IsInclude)
- return HaveCrashVFS ? false : true;
+ return !HaveCrashVFS;
// The remaining flags are treated as a single argument.
@@ -86,7 +90,7 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
StringRef FlagRef(Flag);
IsInclude = FlagRef.startswith("-F") || FlagRef.startswith("-I");
if (IsInclude)
- return HaveCrashVFS ? false : true;
+ return !HaveCrashVFS;
if (FlagRef.startswith("-fmodules-cache-path="))
return true;
@@ -104,7 +108,7 @@ void Command::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
// Quote and escape. This isn't really complete, but good enough.
OS << '"';
- for (const char c : Arg) {
+ for (const auto c : Arg) {
if (c == '"' || c == '\\' || c == '$')
OS << '\\';
OS << c;
@@ -115,7 +119,7 @@ void Command::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
void Command::writeResponseFile(raw_ostream &OS) const {
// In a file list, we only write the set of inputs to the response file
if (Creator.getResponseFilesSupport() == Tool::RF_FileList) {
- for (const char *Arg : InputFileList) {
+ for (const auto *Arg : InputFileList) {
OS << Arg << '\n';
}
return;
@@ -124,7 +128,7 @@ void Command::writeResponseFile(raw_ostream &OS) const {
// In regular response files, we send all arguments to the response file.
// Wrapping all arguments in double quotes ensures that both Unix tools and
// Windows tools understand the response file.
- for (const char *Arg : Arguments) {
+ for (const auto *Arg : Arguments) {
OS << '"';
for (; *Arg != '\0'; Arg++) {
@@ -150,13 +154,13 @@ void Command::buildArgvForResponseFile(
}
llvm::StringSet<> Inputs;
- for (const char *InputName : InputFileList)
+ for (const auto *InputName : InputFileList)
Inputs.insert(InputName);
Out.push_back(Executable);
// In a file list, build args vector ignoring parameters that will go in the
// response file (elements of the InputFileList vector)
bool FirstInput = true;
- for (const char *Arg : Arguments) {
+ for (const auto *Arg : Arguments) {
if (Inputs.count(Arg) == 0) {
Out.push_back(Arg);
} else if (FirstInput) {
@@ -167,13 +171,14 @@ void Command::buildArgvForResponseFile(
}
}
-/// @brief Rewrite relative include-like flag paths to absolute ones.
+/// Rewrite relative include-like flag paths to absolute ones.
static void
rewriteIncludes(const llvm::ArrayRef<const char *> &Args, size_t Idx,
size_t NumArgs,
llvm::SmallVectorImpl<llvm::SmallString<128>> &IncFlags) {
using namespace llvm;
using namespace sys;
+
auto getAbsPath = [](StringRef InInc, SmallVectorImpl<char> &OutInc) -> bool {
if (path::is_absolute(InInc)) // Nothing to do here...
return false;
@@ -212,8 +217,8 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
OS << ' ';
printArg(OS, Executable, /*Quote=*/true);
- llvm::ArrayRef<const char *> Args = Arguments;
- llvm::SmallVector<const char *, 128> ArgsRespFile;
+ ArrayRef<const char *> Args = Arguments;
+ SmallVector<const char *, 128> ArgsRespFile;
if (ResponseFile != nullptr) {
buildArgvForResponseFile(ArgsRespFile);
Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name
@@ -312,13 +317,13 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
std::string *ErrMsg, bool *ExecutionFailed) const {
SmallVector<const char*, 128> Argv;
- const char **Envp;
- if (Environment.empty()) {
- Envp = nullptr;
- } else {
+ Optional<ArrayRef<StringRef>> Env;
+ std::vector<StringRef> ArgvVectorStorage;
+ if (!Environment.empty()) {
assert(Environment.back() == nullptr &&
"Environment vector should be null-terminated by now");
- Envp = const_cast<const char **>(Environment.data());
+ ArgvVectorStorage = llvm::toStringRefArray(Environment.data());
+ Env = makeArrayRef(ArgvVectorStorage);
}
if (ResponseFile == nullptr) {
@@ -326,8 +331,9 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
Argv.append(Arguments.begin(), Arguments.end());
Argv.push_back(nullptr);
+ auto Args = llvm::toStringRefArray(Argv.data());
return llvm::sys::ExecuteAndWait(
- Executable, Argv.data(), Envp, Redirects, /*secondsToWait*/ 0,
+ Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}
@@ -352,7 +358,8 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
return -1;
}
- return llvm::sys::ExecuteAndWait(Executable, Argv.data(), Envp, Redirects,
+ auto Args = llvm::toStringRefArray(Argv.data());
+ return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
/*secondsToWait*/ 0,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
index 16a81603b31e..178a60db60e5 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
@@ -1,4 +1,4 @@
-//===--- Multilib.cpp - Multilib Implementation ---------------------------===//
+//===- Multilib.cpp - Multilib Implementation -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,25 +8,22 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Multilib.h"
-#include "ToolChains/CommonArgs.h"
-#include "clang/Driver/Options.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/OptTable.h"
-#include "llvm/Option/Option.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <string>
-using namespace clang::driver;
using namespace clang;
-using namespace llvm::opt;
+using namespace driver;
using namespace llvm::sys;
/// normalize Segment to "/foo/bar" or "".
@@ -34,7 +31,7 @@ static void normalizePathSegment(std::string &Segment) {
StringRef seg = Segment;
// Prune trailing "/" or "./"
- while (1) {
+ while (true) {
StringRef last = path::filename(seg);
if (last != ".")
break;
@@ -42,7 +39,7 @@ static void normalizePathSegment(std::string &Segment) {
}
if (seg.empty() || seg == "/") {
- Segment = "";
+ Segment.clear();
return;
}
@@ -198,8 +195,8 @@ MultilibSet &MultilibSet::Either(ArrayRef<Multilib> MultilibSegments) {
Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
MultilibSegments.end());
else {
- for (const Multilib &New : MultilibSegments) {
- for (const Multilib &Base : *this) {
+ for (const auto &New : MultilibSegments) {
+ for (const auto &Base : *this) {
Multilib MO = compose(Base, New);
if (MO.isValid())
Composed.push_back(MO);
@@ -262,7 +259,7 @@ bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
return false;
}, Multilibs);
- if (Filtered.size() == 0)
+ if (Filtered.empty())
return false;
if (Filtered.size() == 1) {
M = Filtered[0];
@@ -279,7 +276,7 @@ LLVM_DUMP_METHOD void MultilibSet::dump() const {
}
void MultilibSet::print(raw_ostream &OS) const {
- for (const Multilib &M : *this)
+ for (const auto &M : *this)
OS << M << "\n";
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
index 3c985a1f71d7..5d3e31567ce6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SpecialCaseList.h"
+#include "llvm/Support/TargetParser.h"
#include <memory>
using namespace clang;
@@ -26,24 +27,26 @@ using namespace clang::driver;
using namespace llvm::opt;
enum : SanitizerMask {
- NeedsUbsanRt = Undefined | Integer | Nullability | CFI,
+ NeedsUbsanRt = Undefined | Integer | ImplicitConversion | Nullability | CFI,
NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
NotAllowedWithMinimalRuntime = Vptr,
- RequiresPIE = DataFlow | Scudo,
+ RequiresPIE = DataFlow | HWAddress | Scudo,
NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
- SupportsCoverage = Address | HWAddress | KernelAddress | Memory | Leak |
- Undefined | Integer | Nullability | DataFlow | Fuzzer |
- FuzzerNoLink,
- RecoverableByDefault = Undefined | Integer | Nullability,
+ SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
+ Memory | Leak | Undefined | Integer | ImplicitConversion |
+ Nullability | DataFlow | Fuzzer | FuzzerNoLink,
+ RecoverableByDefault = Undefined | Integer | ImplicitConversion | Nullability,
Unrecoverable = Unreachable | Return,
+ AlwaysRecoverable = KernelAddress | KernelHWAddress,
LegacyFsanitizeRecoverMask = Undefined | Integer,
NeedsLTO = CFI,
TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow |
- Nullability | LocalBounds | CFI,
+ ImplicitConversion | Nullability | LocalBounds | CFI,
TrappingDefault = CFI,
- CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast,
- CompatibleWithMinimalRuntime = TrappingSupported,
+ CFIClasses =
+ CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast,
+ CompatibleWithMinimalRuntime = TrappingSupported | Scudo,
};
enum CoverageFeature {
@@ -92,31 +95,32 @@ static std::string describeSanitizeArg(const llvm::opt::Arg *A,
/// Sanitizers set.
static std::string toString(const clang::SanitizerSet &Sanitizers);
-static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
- std::string &BLPath) {
- 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)
- BlacklistFile = "tsan_blacklist.txt";
- else if (Kinds & DataFlow)
- BlacklistFile = "dfsan_abilist.txt";
- else if (Kinds & CFI)
- BlacklistFile = "cfi_blacklist.txt";
- else if (Kinds & (Undefined | Integer | Nullability))
- BlacklistFile = "ubsan_blacklist.txt";
-
- if (BlacklistFile) {
+static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds,
+ std::vector<std::string> &BlacklistFiles) {
+ struct Blacklist {
+ const char *File;
+ SanitizerMask Mask;
+ } Blacklists[] = {{"asan_blacklist.txt", Address},
+ {"hwasan_blacklist.txt", HWAddress},
+ {"msan_blacklist.txt", Memory},
+ {"tsan_blacklist.txt", Thread},
+ {"dfsan_abilist.txt", DataFlow},
+ {"cfi_blacklist.txt", CFI},
+ {"ubsan_blacklist.txt", Undefined | Integer | Nullability}};
+
+ for (auto BL : Blacklists) {
+ if (!(Kinds & BL.Mask))
+ continue;
+
clang::SmallString<64> Path(D.ResourceDir);
- llvm::sys::path::append(Path, BlacklistFile);
- BLPath = Path.str();
- return true;
+ llvm::sys::path::append(Path, "share", BL.File);
+ if (llvm::sys::fs::exists(Path))
+ BlacklistFiles.push_back(Path.str());
+ else if (BL.Mask == CFI)
+ // If cfi_blacklist.txt cannot be found in the resource dir, driver
+ // should fail.
+ D.Diag(clang::diag::err_drv_no_such_file) << Path;
}
- return false;
}
/// Sets group bits for every group that has at least one representative already
@@ -176,7 +180,8 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
bool SanitizerArgs::needsUbsanRt() const {
// All of these include ubsan.
if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
- needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || needsScudoRt())
+ needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
+ (needsScudoRt() && !requiresMinimalRuntime()))
return false;
return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
@@ -215,6 +220,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Used to deduplicate diagnostics.
SanitizerMask Kinds = 0;
const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
+
+ CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
+ options::OPT_fno_sanitize_cfi_cross_dso, false);
+
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
const Driver &D = TC.getDriver();
@@ -274,6 +283,24 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Add &= ~NotAllowedWithMinimalRuntime;
}
+ // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
+ // There are currently two problems:
+ // - Virtual function call checks need to pass a pointer to the function
+ // address to llvm.type.test and a pointer to the address point to the
+ // diagnostic function. Currently we pass the same pointer to both
+ // places.
+ // - Non-virtual function call checks may need to check multiple type
+ // identifiers.
+ // Fixing both of those may require changes to the cross-DSO CFI
+ // interface.
+ if (CfiCrossDso && (Add & CFIMFCall & ~DiagnosedKinds)) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize=cfi-mfcall"
+ << "-fsanitize-cfi-cross-dso";
+ Add &= ~CFIMFCall;
+ DiagnosedKinds |= CFIMFCall;
+ }
+
if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
D.Diag(diag::err_drv_unsupported_opt_for_target)
@@ -285,19 +312,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
// so we don't error out if -fno-rtti and -fsanitize=undefined were
// passed.
- if (Add & Vptr &&
- (RTTIMode == ToolChain::RM_DisabledImplicitly ||
- RTTIMode == ToolChain::RM_DisabledExplicitly)) {
- if (RTTIMode == ToolChain::RM_DisabledImplicitly)
- // Warn about not having rtti enabled if the vptr sanitizer is
- // explicitly enabled
- D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
- else {
- const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
- assert(NoRTTIArg &&
- "RTTI disabled explicitly but we have no argument!");
+ if ((Add & Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
+ if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
+ assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
+ "RTTI disabled without -fno-rtti option?");
+ // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
+ // the vptr sanitizer requires RTTI, so this is a user error.
D.Diag(diag::err_drv_argument_not_allowed_with)
<< "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
+ } else {
+ // The vptr sanitizer requires RTTI, but RTTI is disabled (by
+ // default). Warn that the vptr sanitizer is being disabled.
+ D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
}
// Take out the Vptr sanitizer from the enabled sanitizers
@@ -313,6 +339,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if (MinimalRuntime) {
Add &= ~NotAllowedWithMinimalRuntime;
}
+ if (CfiCrossDso)
+ Add &= ~CFIMFCall;
Add &= Supported;
if (Add & Fuzzer)
@@ -335,14 +363,41 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
+ std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
+ 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),
+ std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress | Efficiency),
+ std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
+ Memory | KernelAddress | Efficiency |
+ SafeStack),
+ std::make_pair(KernelHWAddress, Address | HWAddress | Leak | Thread |
+ Memory | KernelAddress | Efficiency |
+ SafeStack | ShadowCallStack)};
+
// Enable toolchain specific default sanitizers if not explicitly disabled.
- Kinds |= TC.getDefaultSanitizers() & ~AllRemove;
+ SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
+
+ // Disable default sanitizers that are incompatible with explicitly requested
+ // ones.
+ for (auto G : IncompatibleGroups) {
+ SanitizerMask Group = G.first;
+ if ((Default & Group) && (Kinds & G.second))
+ Default &= ~Group;
+ }
+
+ Kinds |= Default;
// We disable the vptr sanitizer if it was enabled by group expansion but RTTI
// is disabled.
- if ((Kinds & Vptr) &&
- (RTTIMode == ToolChain::RM_DisabledImplicitly ||
- RTTIMode == ToolChain::RM_DisabledExplicitly)) {
+ if ((Kinds & Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
Kinds &= ~Vptr;
}
@@ -352,6 +407,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
<< lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
}
+ if ((Kinds & ShadowCallStack) &&
+ TC.getTriple().getArch() == llvm::Triple::aarch64 &&
+ !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
+ !Args.hasArg(options::OPT_ffixed_x18)) {
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << lastArgumentForMask(D, Args, Kinds & ShadowCallStack)
+ << "-ffixed-x18";
+ }
+
// Report error if there are non-trapping sanitizers that require
// c++abi-specific parts of UBSan runtime, and they are not provided by the
// toolchain. We don't have a good way to check the latter, so we just
@@ -372,16 +436,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
// Warn about incompatible groups of sanitizers.
- std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
- 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) {
@@ -399,8 +453,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// default in ASan?
// Parse -f(no-)?sanitize-recover flags.
- SanitizerMask RecoverableKinds = RecoverableByDefault;
+ SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
SanitizerMask DiagnosedUnrecoverableKinds = 0;
+ SanitizerMask DiagnosedAlwaysRecoverableKinds = 0;
for (const auto *Arg : Args) {
const char *DeprecatedReplacement = nullptr;
if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
@@ -428,7 +483,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
RecoverableKinds |= expandSanitizerGroups(Add);
Arg->claim();
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
- RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true));
+ SanitizerMask Remove = parseArgValues(D, Arg, true);
+ // Report error if user explicitly tries to disable recovery from
+ // always recoverable sanitizer.
+ if (SanitizerMask KindsToDiagnose =
+ Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
+ SanitizerSet SetToDiagnose;
+ SetToDiagnose.Mask |= KindsToDiagnose;
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << toString(SetToDiagnose);
+ DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
+ }
+ RecoverableKinds &= ~expandSanitizerGroups(Remove);
Arg->claim();
}
if (DeprecatedReplacement) {
@@ -444,11 +510,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Setup blacklist files.
// Add default blacklist from resource directory.
- {
- std::string BLPath;
- if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
- BlacklistFiles.push_back(BLPath);
- }
+ addDefaultBlacklists(D, Kinds, BlacklistFiles);
// Parse -f(no-)sanitize-blacklist options.
for (const auto *Arg : Args) {
if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
@@ -457,9 +519,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if (llvm::sys::fs::exists(BLPath)) {
BlacklistFiles.push_back(BLPath);
ExtraDeps.push_back(BLPath);
- } else
+ } else {
D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
-
+ }
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
Arg->claim();
BlacklistFiles.clear();
@@ -517,8 +579,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
if (AllAddedKinds & CFI) {
- CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
- options::OPT_fno_sanitize_cfi_cross_dso, false);
// Without PIE, external function address may resolve to a PLT record, which
// can not be verified by the target module.
NeedPIE |= CfiCrossDso;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index f96a1182e3ca..cf3db34688df 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -1,4 +1,4 @@
-//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
+//===- ToolChain.cpp - Collections of tools for one platform --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,33 +8,45 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/ToolChain.h"
-#include "ToolChains/CommonArgs.h"
+#include "InputInfo.h"
#include "ToolChains/Arch/ARM.h"
#include "ToolChains/Clang.h"
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/XRayArgs.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#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"
+#include "llvm/Support/VersionTuple.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <string>
-using namespace clang::driver;
-using namespace clang::driver::tools;
using namespace clang;
+using namespace driver;
+using namespace tools;
using namespace llvm;
using namespace llvm::opt;
@@ -49,33 +61,24 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
// Explicit rtti/no-rtti args
if (CachedRTTIArg) {
if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
- return ToolChain::RM_EnabledExplicitly;
+ return ToolChain::RM_Enabled;
else
- return ToolChain::RM_DisabledExplicitly;
+ return ToolChain::RM_Disabled;
}
// -frtti is default, except for the PS4 CPU.
- if (!Triple.isPS4CPU())
- return ToolChain::RM_EnabledImplicitly;
-
- // On the PS4, turning on c++ exceptions turns on rtti.
- // We're assuming that, if we see -fexceptions, rtti gets turned on.
- Arg *Exceptions = Args.getLastArgNoClaim(
- options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
- options::OPT_fexceptions, options::OPT_fno_exceptions);
- if (Exceptions &&
- (Exceptions->getOption().matches(options::OPT_fexceptions) ||
- Exceptions->getOption().matches(options::OPT_fcxx_exceptions)))
- return ToolChain::RM_EnabledImplicitly;
-
- return ToolChain::RM_DisabledImplicitly;
+ return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
}
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
- CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),
- EffectiveTriple() {
+ CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, D.getTargetTriple(), "lib");
+ if (getVFS().exists(P))
+ getFilePaths().push_back(P.str());
+
std::string CandidateLibPath = getArchSpecificLibPath();
if (getVFS().exists(CandidateLibPath))
getFilePaths().push_back(CandidateLibPath);
@@ -87,8 +90,7 @@ void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
EffectiveTriple.setEnvironment(Env);
}
-ToolChain::~ToolChain() {
-}
+ToolChain::~ToolChain() = default;
vfs::FileSystem &ToolChain::getVFS() const { return getDriver().getVFS(); }
@@ -115,12 +117,15 @@ const XRayArgs& ToolChain::getXRayArgs() const {
}
namespace {
+
struct DriverSuffix {
const char *Suffix;
const char *ModeFlag;
};
-const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
+} // namespace
+
+static 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.
@@ -151,16 +156,16 @@ const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
/// Normalize the program name from argv[0] by stripping the file extension if
/// present and lower-casing the string on Windows.
-std::string normalizeProgramName(llvm::StringRef Argv0) {
+static std::string normalizeProgramName(llvm::StringRef Argv0) {
std::string ProgName = llvm::sys::path::stem(Argv0);
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
// Transform to lowercase for case insensitive file systems.
std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
#endif
return ProgName;
}
-const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
+static 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.
@@ -185,7 +190,6 @@ const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
}
return DS;
}
-} // anonymous namespace
ParsedClangName
ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
@@ -193,7 +197,7 @@ ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
size_t SuffixPos;
const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
if (!DS)
- return ParsedClangName();
+ return {};
size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
size_t LastComponent = ProgName.rfind('-', SuffixPos);
@@ -323,13 +327,27 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
return llvm::Triple::getArchTypeName(TC.getArch());
}
+StringRef ToolChain::getOSLibName() const {
+ switch (Triple.getOS()) {
+ case llvm::Triple::FreeBSD:
+ return "freebsd";
+ case llvm::Triple::NetBSD:
+ return "netbsd";
+ case llvm::Triple::OpenBSD:
+ return "openbsd";
+ case llvm::Triple::Solaris:
+ return "sunos";
+ default:
+ return getOS();
+ }
+}
+
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);
+ llvm::sys::path::append(Path, "lib", getOSLibName());
}
return Path.str();
}
@@ -337,15 +355,23 @@ std::string ToolChain::getCompilerRTPath() const {
std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
bool Shared) const {
const llvm::Triple &TT = getTriple();
- const char *Env = TT.isAndroid() ? "-android" : "";
bool IsITANMSVCWindows =
TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
- StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
const char *Prefix = IsITANMSVCWindows ? "" : "lib";
const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so")
: (IsITANMSVCWindows ? ".lib" : ".a");
+ const Driver &D = getDriver();
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, D.getTargetTriple(), "lib");
+ if (getVFS().exists(P)) {
+ llvm::sys::path::append(P, Prefix + Twine("clang_rt.") + Component + Suffix);
+ return P.str();
+ }
+
+ StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
+ const char *Env = TT.isAndroid() ? "-android" : "";
SmallString<128> Path(getCompilerRTPath());
llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
Arch + Env + Suffix);
@@ -360,8 +386,7 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
std::string ToolChain::getArchSpecificLibPath() const {
SmallString<128> Path(getDriver().ResourceDir);
- StringRef OSLibName = getTriple().isOSFreeBSD() ? "freebsd" : getOS();
- llvm::sys::path::append(Path, "lib", OSLibName,
+ llvm::sys::path::append(Path, "lib", getOSLibName(),
llvm::Triple::getArchTypeName(getArch()));
return Path.str();
}
@@ -403,7 +428,7 @@ std::string ToolChain::GetLinkerPath() const {
if (llvm::sys::path::is_absolute(UseLinker)) {
// If we're passed what looks like an absolute path, don't attempt to
// second-guess that.
- if (llvm::sys::fs::exists(UseLinker))
+ if (llvm::sys::fs::can_execute(UseLinker))
return UseLinker;
} else if (UseLinker.empty() || UseLinker == "ld") {
// If we're passed -fuse-ld= with no argument, or with the argument ld,
@@ -418,7 +443,7 @@ std::string ToolChain::GetLinkerPath() const {
LinkerName.append(UseLinker);
std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
- if (llvm::sys::fs::exists(LinkerPath))
+ if (llvm::sys::fs::can_execute(LinkerPath))
return LinkerPath;
}
@@ -459,8 +484,6 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
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;
}
@@ -541,7 +564,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
StringRef Suffix =
tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::ProfileKind::M;
- bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 &&
+ bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 &&
getTriple().isOSBinFormatMachO());
// FIXME: this is invalid for WindowsCE
if (getTriple().isOSWindows())
@@ -576,7 +599,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
// 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 :
+ for (const auto *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
for (StringRef Value : A->getValues()) {
if (Value == "-mthumb")
@@ -660,7 +683,7 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
return GetDefaultCXXStdlibType();
}
-/// \brief Utility function to add a system include directory to CC1 arguments.
+/// Utility function to add a system include directory to CC1 arguments.
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
ArgStringList &CC1Args,
const Twine &Path) {
@@ -668,7 +691,7 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
-/// \brief Utility function to add a system include directory with extern "C"
+/// Utility function to add a system include directory with extern "C"
/// semantics to CC1 arguments.
///
/// Note that this should be used rarely, and only for directories that
@@ -690,11 +713,11 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, Path);
}
-/// \brief Utility function to add a list of system include directories to CC1.
+/// Utility function to add a list of system include directories to CC1.
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,
ArrayRef<StringRef> Paths) {
- for (StringRef Path : Paths) {
+ for (const auto Path : Paths) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
@@ -776,10 +799,12 @@ bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
SanitizerMask ToolChain::getSupportedSanitizers() const {
// Return sanitizers which don't require runtime support and are not
// platform dependent.
+
using namespace SanitizerKind;
+
SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) |
- CFICastStrict | UnsignedIntegerOverflow | Nullability |
- LocalBounds;
+ CFICastStrict | UnsignedIntegerOverflow |
+ ImplicitConversion | Nullability | LocalBounds;
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().getArch() == llvm::Triple::arm ||
@@ -787,6 +812,9 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
getTriple().getArch() == llvm::Triple::wasm32 ||
getTriple().getArch() == llvm::Triple::wasm64)
Res |= CFIICall;
+ if (getTriple().getArch() == llvm::Triple::x86_64 ||
+ getTriple().getArch() == llvm::Triple::aarch64)
+ Res |= ShadowCallStack;
return Res;
}
@@ -858,7 +886,7 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
bool Modified = false;
// Handle -Xopenmp-target flags
- for (Arg *A : Args) {
+ for (auto *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
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp
index a313bc5c35de..6b673feeadfc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -43,7 +43,6 @@ void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
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);
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp
index ee072cc03e7c..006fdc029ef8 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp
@@ -10,7 +10,6 @@
#include "Ananas.h"
#include "InputInfo.h"
#include "CommonArgs.h"
-#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
@@ -64,8 +63,19 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
- // Ananas only supports static linkage for now.
- CmdArgs.push_back("-Bstatic");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ Args.AddAllArgs(CmdArgs, options::OPT_pie);
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/lib/ld-ananas.so");
+ }
+ }
if (Output.isFilename()) {
CmdArgs.push_back("-o");
@@ -75,9 +85,15 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ }
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ }
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -86,8 +102,11 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
- if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
+ }
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -97,7 +116,10 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.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 ad04aedd098e..5114279b4b45 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -69,6 +69,9 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
+ if (CPU == "native")
+ CPU = llvm::sys::getHostCPUName();
+
if (CPU == "generic") {
Features.push_back("+neon");
} else {
@@ -198,6 +201,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
if (Args.hasArg(options::OPT_ffixed_x18))
Features.push_back("+reserve-x18");
+ if (Args.hasArg(options::OPT_ffixed_x20))
+ Features.push_back("+reserve-x20");
+
if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
}
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 44c8871d0e1f..886d947c586b 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -232,7 +232,7 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
break;
case llvm::Triple::OpenBSD:
- ABI = FloatABI::Soft;
+ ABI = FloatABI::SoftFP;
break;
default:
@@ -391,12 +391,22 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
} else if (HDivArg)
getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
- // Setting -msoft-float effectively disables NEON because of the GCC
- // implementation, although the same isn't true of VFP or VFP3.
+ // Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC
+ // ignores the -mfpu options in this case).
+ // Note that the ABI can also be set implicitly by the target selected.
if (ABI == arm::FloatABI::Soft) {
- Features.push_back("-neon");
- // Also need to explicitly disable features which imply NEON.
- Features.push_back("-crypto");
+ llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
+
+ // Disable hardware FP features which have been enabled.
+ // FIXME: Disabling vfp2 and neon should be enough as all the other
+ // features are dependent on these 2 features in LLVM. However
+ // there is currently no easy way to test this in clang, so for
+ // now just be explicit and disable all known dependent features
+ // as well.
+ for (std::string Feature : {"vfp2", "vfp3", "vfp4", "fp-armv8", "fullfp16",
+ "neon", "crypto", "dotprod"})
+ if (std::find(std::begin(Features), std::end(Features), "+" + Feature) != std::end(Features))
+ Features.push_back(Args.MakeArgString("-" + Feature));
}
// En/disable crc code generation.
@@ -438,7 +448,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
if (B->getOption().matches(options::OPT_mlong_calls))
D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
}
- Features.push_back("+execute-only");
+ Features.push_back("+execute-only");
}
}
}
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 e72754d5ad53..6d814631d05f 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -20,11 +20,6 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-bool tools::isMipsArch(llvm::Triple::ArchType Arch) {
- return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
- Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
-}
-
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
@@ -50,6 +45,13 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
if (Triple.getOS() == llvm::Triple::OpenBSD)
DefMips64CPU = "mips3";
+ // MIPS2 is the default for mips(el)?-unknown-freebsd.
+ // MIPS3 is the default for mips64(el)?-unknown-freebsd.
+ if (Triple.getOS() == llvm::Triple::FreeBSD) {
+ DefMips32CPU = "mips2";
+ DefMips64CPU = "mips3";
+ }
+
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,
options::OPT_mcpu_EQ))
CPUName = A->getValue();
@@ -106,11 +108,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
if (ABIName.empty()) {
// Deduce ABI name from the target triple.
- if (Triple.getArch() == llvm::Triple::mips ||
- Triple.getArch() == llvm::Triple::mipsel)
- ABIName = "o32";
- else
- ABIName = "n64";
+ ABIName = Triple.isMIPS32() ? "o32" : "n64";
}
if (CPUName.empty()) {
@@ -214,6 +212,7 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// For case (a) we need to add +noabicalls for N64.
bool IsN64 = ABIName == "64";
+ bool IsPIC = false;
bool NonPIC = false;
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
@@ -225,6 +224,9 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
NonPIC =
(O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
+ IsPIC =
+ (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));
}
bool UseAbiCalls = false;
@@ -234,9 +236,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
UseAbiCalls =
!ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);
- if (UseAbiCalls && IsN64 && NonPIC) {
- D.Diag(diag::warn_drv_unsupported_abicalls);
- UseAbiCalls = false;
+ if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
+ D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)
+ << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
+ NonPIC = false;
+ }
+
+ if (ABICallsArg && !UseAbiCalls && IsPIC) {
+ D.Diag(diag::err_drv_unsupported_noabicalls_pic);
}
if (!UseAbiCalls)
@@ -343,6 +350,12 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
"nomadd4");
AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
+ AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
+ "crc");
+ AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
+ "virt");
+ AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
+ "ginv");
if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
StringRef Val = StringRef(A->getValue());
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 7e90488363a5..a232ddbc8f3d 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
@@ -21,8 +21,6 @@ namespace clang {
namespace driver {
namespace tools {
-bool isMipsArch(llvm::Triple::ArchType Arch);
-
namespace mips {
typedef enum { Legacy = 1, Std2008 = 2 } IEEE754Standard;
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 7c7e1c70e550..f6a95962ace3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -106,6 +106,16 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
if (FloatABI == ppc::FloatABI::Soft)
Features.push_back("-hard-float");
+
+ ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args);
+ if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
+ Features.push_back("+secure-plt");
+}
+
+ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) {
+ if (Args.getLastArg(options::OPT_msecure_plt))
+ return ppc::ReadGOTPtrMode::SecurePlt;
+ return ppc::ReadGOTPtrMode::Bss;
}
ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
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 7d7c68101b7b..3acee91a2ac3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
@@ -29,10 +29,17 @@ enum class FloatABI {
Hard,
};
+enum class ReadGOTPtrMode {
+ Bss,
+ SecurePlt,
+};
+
FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
const char *getPPCAsmModeForCPU(StringRef Name);
+ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D,
+ const llvm::opt::ArgList &Args);
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/RISCV.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
new file mode 100644
index 000000000000..1321fedcec51
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -0,0 +1,378 @@
+//===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include "ToolChains/CommonArgs.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static StringRef getExtensionTypeDesc(StringRef Ext) {
+ if (Ext.startswith("sx"))
+ return "non-standard supervisor-level extension";
+ if (Ext.startswith("s"))
+ return "standard supervisor-level extension";
+ if (Ext.startswith("x"))
+ return "non-standard user-level extension";
+ return StringRef();
+}
+
+static StringRef getExtensionType(StringRef Ext) {
+ if (Ext.startswith("sx"))
+ return "sx";
+ if (Ext.startswith("s"))
+ return "s";
+ if (Ext.startswith("x"))
+ return "x";
+ return StringRef();
+}
+
+static bool isSupportedExtension(StringRef Ext) {
+ // LLVM does not support "sx", "s" nor "x" extensions.
+ return false;
+}
+
+// Extensions may have a version number, and may be separated by
+// an underscore '_' e.g.: rv32i2_m2.
+// Version number is divided into major and minor version numbers,
+// separated by a 'p'. If the minor version is 0 then 'p0' can be
+// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
+static bool getExtensionVersion(const Driver &D, StringRef MArch,
+ StringRef Ext, StringRef In,
+ std::string &Major, std::string &Minor) {
+ auto I = In.begin();
+ auto E = In.end();
+
+ while (I != E && isDigit(*I))
+ Major.append(1, *I++);
+
+ if (Major.empty())
+ return true;
+
+ if (I != E && *I == 'p') {
+ ++I;
+
+ while (I != E && isDigit(*I))
+ Minor.append(1, *I++);
+
+ // Expected 'p' to be followed by minor version number.
+ if (Minor.empty()) {
+ std::string Error =
+ "minor version number missing after 'p' for extension";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return false;
+ }
+ }
+
+ // TODO: Handle extensions with version number.
+ std::string Error = "unsupported version number " + Major;
+ if (!Minor.empty())
+ Error += "." + Minor;
+ Error += " for extension";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
+
+ return false;
+}
+
+// Handle other types of extensions other than the standard
+// general purpose and standard user-level extensions.
+// Parse the ISA string containing non-standard user-level
+// extensions, standard supervisor-level extensions and
+// non-standard supervisor-level extensions.
+// These extensions start with 'x', 's', 'sx' prefixes, follow a
+// canonical order, might have a version number (major, minor)
+// and are separated by a single underscore '_'.
+// Set the hardware features for the extensions that are supported.
+static void getExtensionFeatures(const Driver &D,
+ const ArgList &Args,
+ std::vector<StringRef> &Features,
+ StringRef &MArch, StringRef &Exts) {
+ if (Exts.empty())
+ return;
+
+ // Multi-letter extensions are seperated by a single underscore
+ // as described in RISC-V User-Level ISA V2.2.
+ SmallVector<StringRef, 8> Split;
+ Exts.split(Split, StringRef("_"));
+
+ SmallVector<StringRef, 3> Prefix;
+ Prefix.push_back("x");
+ Prefix.push_back("s");
+ Prefix.push_back("sx");
+ auto I = Prefix.begin();
+ auto E = Prefix.end();
+
+ SmallVector<StringRef, 8> AllExts;
+
+ for (StringRef Ext : Split) {
+
+ if (Ext.empty()) {
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "extension name missing after separator '_'";
+ return;
+ }
+
+ StringRef Type = getExtensionType(Ext);
+ StringRef Name(Ext.substr(Type.size()));
+ StringRef Desc = getExtensionTypeDesc(Ext);
+
+ if (Type.empty()) {
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << "invalid extension prefix" << Ext;
+ return;
+ }
+
+ // Check ISA extensions are specified in the canonical order.
+ while (I != E && *I != Type)
+ ++I;
+
+ if (I == E) {
+ std::string Error = Desc;
+ Error += " not given in canonical order";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ // The order is OK, do not advance I to the next prefix
+ // to allow repeated extension type, e.g.: rv32ixabc_xdef.
+
+ if (Name.empty()) {
+ std::string Error = Desc;
+ Error += " name missing after";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ std::string Major, Minor;
+ auto Pos = Name.find_if(isDigit);
+ if (Pos != StringRef::npos) {
+ auto Next = Name.substr(Pos);
+ Name = Name.substr(0, Pos);
+ if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
+ return;
+ }
+
+ // Check if duplicated extension.
+ if (std::find(AllExts.begin(), AllExts.end(), Ext) != AllExts.end()) {
+ std::string Error = "duplicated ";
+ Error += Desc;
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ // Extension format is correct, keep parsing the extensions.
+ // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
+ AllExts.push_back(Ext);
+ }
+
+ // Set target features.
+ // TODO: Hardware features to be handled in Support/TargetParser.cpp.
+ // TODO: Use version number when setting target features.
+ for (auto Ext : AllExts) {
+ if (!isSupportedExtension(Ext)) {
+ StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
+ std::string Error = "unsupported ";
+ Error += Desc;
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+ Features.push_back(Args.MakeArgString("+" + Ext));
+ }
+}
+
+void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ StringRef MArch = A->getValue();
+
+ // RISC-V ISA strings must be lowercase.
+ if (std::any_of(std::begin(MArch), std::end(MArch),
+ [](char c) { return isupper(c); })) {
+
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "string must be lowercase";
+ return;
+ }
+
+ // ISA string must begin with rv32 or rv64.
+ if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
+ (MArch.size() < 5)) {
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "string must begin with rv32{i,e,g} or rv64{i,g}";
+ return;
+ }
+
+ bool HasRV64 = MArch.startswith("rv64") ? true : false;
+
+ // The canonical order specified in ISA manual.
+ // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
+ StringRef StdExts = "mafdqlcbjtpvn";
+ bool HasF = false, HasD = false;
+ char Baseline = MArch[4];
+
+ // First letter should be 'e', 'i' or 'g'.
+ switch (Baseline) {
+ default:
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "first letter should be 'e', 'i' or 'g'";
+ return;
+ case 'e': {
+ StringRef Error;
+ // Currently LLVM does not support 'e'.
+ // Extension 'e' is not allowed in rv64.
+ if (HasRV64)
+ Error = "standard user-level extension 'e' requires 'rv32'";
+ else
+ Error = "unsupported standard user-level extension 'e'";
+ D.Diag(diag::err_drv_invalid_riscv_arch_name)
+ << MArch << Error;
+ return;
+ }
+ case 'i':
+ break;
+ case 'g':
+ // g = imafd
+ StdExts = StdExts.drop_front(4);
+ Features.push_back("+m");
+ Features.push_back("+a");
+ Features.push_back("+f");
+ Features.push_back("+d");
+ HasF = true;
+ HasD = true;
+ break;
+ }
+
+ // Skip rvxxx
+ StringRef Exts = MArch.substr(5);
+
+ // Remove non-standard extensions and supervisor-level extensions.
+ // They have 'x', 's', 'sx' prefixes. Parse them at the end.
+ // Find the very first occurrence of 's' or 'x'.
+ StringRef OtherExts;
+ size_t Pos = Exts.find_first_of("sx");
+ if (Pos != StringRef::npos) {
+ OtherExts = Exts.substr(Pos);
+ Exts = Exts.substr(0, Pos);
+ }
+
+ std::string Major, Minor;
+ if (!getExtensionVersion(D, MArch, std::string(1, Baseline),
+ Exts, Major, Minor))
+ return;
+
+ // TODO: Use version number when setting target features
+ // and consume the underscore '_' that might follow.
+
+ auto StdExtsItr = StdExts.begin();
+ auto StdExtsEnd = StdExts.end();
+
+ for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
+ char c = *I;
+
+ // Check ISA extensions are specified in the canonical order.
+ while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
+ ++StdExtsItr;
+
+ if (StdExtsItr == StdExtsEnd) {
+ // Either c contains a valid extension but it was not given in
+ // canonical order or it is an invalid extension.
+ StringRef Error;
+ if (StdExts.contains(c))
+ Error = "standard user-level extension not given in canonical order";
+ else
+ Error = "invalid standard user-level extension";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << std::string(1, c);
+ return;
+ }
+
+ // Move to next char to prevent repeated letter.
+ ++StdExtsItr;
+
+ if (std::next(I) != E) {
+ // Skip c.
+ std::string Next = std::string(std::next(I), E);
+ std::string Major, Minor;
+ if (!getExtensionVersion(D, MArch, std::string(1, c),
+ Next, Major, Minor))
+ return;
+
+ // TODO: Use version number when setting target features
+ // and consume the underscore '_' that might follow.
+ }
+
+ // The order is OK, then push it into features.
+ switch (c) {
+ default:
+ // Currently LLVM supports only "mafdc".
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << "unsupported standard user-level extension"
+ << std::string(1, c);
+ return;
+ case 'm':
+ Features.push_back("+m");
+ break;
+ case 'a':
+ Features.push_back("+a");
+ break;
+ case 'f':
+ Features.push_back("+f");
+ HasF = true;
+ break;
+ case 'd':
+ Features.push_back("+d");
+ HasD = true;
+ break;
+ case 'c':
+ Features.push_back("+c");
+ break;
+ }
+ }
+
+ // Dependency check.
+ // It's illegal to specify the 'd' (double-precision floating point)
+ // extension without also specifying the 'f' (single precision
+ // floating-point) extension.
+ if (HasD && !HasF)
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "d requires f extension to also be specified";
+
+ // Additional dependency checks.
+ // TODO: The 'q' extension requires rv64.
+ // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
+
+ // Handle all other types of extensions.
+ getExtensionFeatures(D, Args, Features, MArch, OtherExts);
+ }
+
+ // Now add any that the user explicitly requested on the command line,
+ // which may override the defaults.
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
+}
+
+StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ return A->getValue();
+
+ return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64";
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h
new file mode 100644
index 000000000000..beda14979fab
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h
@@ -0,0 +1,32 @@
+//===--- RISCV.h - RISCV-specific Tool Helpers ------------------*- 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_ARCH_RISCV_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_RISCV_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace riscv {
+void getRISCVTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+StringRef getRISCVABI(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+} // end namespace riscv
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_RISCV_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
index 594ec9986d8e..c177031b9f75 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
@@ -45,14 +45,29 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("niagara2", "-Av8plusb")
.Case("niagara3", "-Av8plusd")
.Case("niagara4", "-Av8plusd")
+ .Case("ma2100", "-Aleon")
+ .Case("ma2150", "-Aleon")
+ .Case("ma2155", "-Aleon")
+ .Case("ma2450", "-Aleon")
+ .Case("ma2455", "-Aleon")
+ .Case("ma2x5x", "-Aleon")
+ .Case("ma2080", "-Aleon")
+ .Case("ma2085", "-Aleon")
+ .Case("ma2480", "-Aleon")
+ .Case("ma2485", "-Aleon")
+ .Case("ma2x8x", "-Aleon")
+ .Case("myriad2", "-Aleon")
+ .Case("myriad2.1", "-Aleon")
+ .Case("myriad2.2", "-Aleon")
+ .Case("myriad2.3", "-Aleon")
.Case("leon2", "-Av8")
.Case("at697e", "-Av8")
.Case("at697f", "-Av8")
- .Case("leon3", "-Av8")
+ .Case("leon3", "-Aleon")
.Case("ut699", "-Av8")
- .Case("gr712rc", "-Av8")
- .Case("leon4", "-Av8")
- .Case("gr740", "-Av8")
+ .Case("gr712rc", "-Aleon")
+ .Case("leon4", "-Aleon")
+ .Case("gr740", "-Aleon")
.Default("-Av8");
}
}
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 a18b2aa35b03..7a4f836d2e1a 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -40,26 +40,29 @@ const char *x86::getX86TargetCPU(const ArgList &Args,
return Args.MakeArgString(CPU);
}
- if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
- // Mapping built by referring to X86TargetInfo::getDefaultFeatures().
+ if (const Arg *A = Args.getLastArgNoClaim(options::OPT__SLASH_arch)) {
+ // Mapping built by looking at lib/Basic's X86TargetInfo::initFeatureMap().
StringRef Arch = A->getValue();
- const char *CPU;
- if (Triple.getArch() == llvm::Triple::x86) {
+ const char *CPU = nullptr;
+ if (Triple.getArch() == llvm::Triple::x86) { // 32-bit-only /arch: flags.
CPU = llvm::StringSwitch<const char *>(Arch)
.Case("IA32", "i386")
.Case("SSE", "pentium3")
.Case("SSE2", "pentium4")
- .Case("AVX", "sandybridge")
- .Case("AVX2", "haswell")
.Default(nullptr);
- } else {
+ }
+ if (CPU == nullptr) { // 32-bit and 64-bit /arch: flags.
CPU = llvm::StringSwitch<const char *>(Arch)
.Case("AVX", "sandybridge")
.Case("AVX2", "haswell")
+ .Case("AVX512F", "knl")
+ .Case("AVX512", "skylake-avx512")
.Default(nullptr);
}
- if (CPU)
+ if (CPU) {
+ A->claim();
return CPU;
+ }
}
// Select the default CPU if none was given (or detection failed).
@@ -141,30 +144,6 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+ssse3");
}
- // Set features according to the -arch flag on MSVC.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
- StringRef Arch = A->getValue();
- bool ArchUsed = false;
- // First, look for flags that are shared in x86 and x86-64.
- if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) {
- if (Arch == "AVX" || Arch == "AVX2") {
- ArchUsed = true;
- Features.push_back(Args.MakeArgString("+" + Arch.lower()));
- }
- }
- // Then, look for x86-specific flags.
- if (ArchType == llvm::Triple::x86) {
- if (Arch == "IA32") {
- ArchUsed = true;
- } else if (Arch == "SSE" || Arch == "SSE2") {
- ArchUsed = true;
- Features.push_back(Args.MakeArgString("+" + Arch.lower()));
- }
- }
- if (!ArchUsed)
- D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
- }
-
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp
index 57a668650e6b..c302d647b973 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -95,16 +95,23 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
CC1Args.push_back("-nostdsysteminc");
}
-std::string BareMetal::findLibCxxIncludePath(CXXStdlibType LibType) const {
+void BareMetal::AddClangCXXStdlibIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
StringRef SysRoot = getDriver().SysRoot;
if (SysRoot.empty())
- return "";
+ return;
- switch (LibType) {
+ switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx: {
SmallString<128> Dir(SysRoot);
llvm::sys::path::append(Dir, "include", "c++", "v1");
- return Dir.str();
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ break;
}
case ToolChain::CST_Libstdcxx: {
SmallString<128> Dir(SysRoot);
@@ -124,24 +131,12 @@ std::string BareMetal::findLibCxxIncludePath(CXXStdlibType LibType) const {
Version = CandidateVersion;
}
if (Version.Major == -1)
- return "";
+ return;
llvm::sys::path::append(Dir, Version.Text);
- return Dir.str();
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ break;
}
}
- llvm_unreachable("unhandled LibType");
-}
-
-void BareMetal::AddClangCXXStdlibIncludeArgs(
- const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdinc) ||
- DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- std::string Path = findLibCxxIncludePath(GetCXXStdlibType(DriverArgs));
- if (!Path.empty())
- addSystemInclude(DriverArgs, CC1Args, Path);
}
void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h
index 0bed63332cad..43a6a8b4bec3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h
@@ -53,7 +53,6 @@ public:
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
- std::string findLibCxxIncludePath(ToolChain::CXXStdlibType LibType) const;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
index a2821b70d716..45a29a0225a4 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
@@ -12,6 +12,7 @@
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
@@ -24,12 +25,12 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
-#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/XRayArgs.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compression.h"
@@ -130,6 +131,10 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>());
else if (JA.isDeviceOffloading(Action::OFK_Cuda))
Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
+ else if (JA.isHostOffloading(Action::OFK_HIP))
+ Work(*C.getSingleOffloadToolChain<Action::OFK_HIP>());
+ else if (JA.isDeviceOffloading(Action::OFK_HIP))
+ Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
if (JA.isHostOffloading(Action::OFK_OpenMP)) {
auto TCs = C.getOffloadToolChains<Action::OFK_OpenMP>();
@@ -327,6 +332,10 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
case llvm::Triple::ppc64le:
ppc::getPPCTargetFeatures(D, Triple, Args, Features);
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ riscv::getRISCVTargetFeatures(D, Args, Features);
+ break;
case llvm::Triple::systemz:
systemz::getSystemZTargetFeatures(Args, Features);
break;
@@ -403,7 +412,6 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
- const Driver &D = TC.getDriver();
const llvm::Triple &Triple = TC.getTriple();
if (KernelOrKext) {
@@ -445,21 +453,6 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
ExceptionArg->getOption().matches(options::OPT_fexceptions);
if (CXXExceptionsEnabled) {
- if (Triple.isPS4CPU()) {
- ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
- assert(ExceptionArg &&
- "On the PS4 exceptions should only be enabled if passing "
- "an argument");
- if (RTTIMode == ToolChain::RM_DisabledExplicitly) {
- const Arg *RTTIArg = TC.getRTTIArg();
- assert(RTTIArg && "RTTI disabled explicitly but no RTTIArg!");
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << RTTIArg->getAsString(Args) << ExceptionArg->getAsString(Args);
- } else if (RTTIMode == ToolChain::RM_EnabledImplicitly)
- D.Diag(diag::warn_drv_enabling_rtti_with_exceptions);
- } else
- assert(TC.getRTTIMode() != ToolChain::RM_DisabledImplicitly);
-
CmdArgs.push_back("-fcxx-exceptions");
EH = true;
@@ -524,10 +517,17 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
// XCore never wants frame pointers, regardless of OS.
// WebAssembly never wants frame pointers.
return false;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ return !areOptimizationsEnabled(Args);
default:
break;
}
+ if (Triple.getOS() == llvm::Triple::NetBSD) {
+ return !areOptimizationsEnabled(Args);
+ }
+
if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
switch (Triple.getArch()) {
// Don't use a frame pointer on linux if optimizing for certain targets.
@@ -604,7 +604,19 @@ static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
}
}
-/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
+/// Add a CC1 and CC1AS option to specify the debug file path prefix map.
+static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) {
+ for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) {
+ StringRef Map = A->getValue();
+ if (Map.find('=') == StringRef::npos)
+ D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map;
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
+ A->claim();
+ }
+}
+
+/// Vectorize at all optimization levels greater than 1 except for -Oz.
/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
@@ -826,7 +838,7 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
}
}
-/// \brief Check whether the given input tree contains any compilation actions.
+/// Check whether the given input tree contains any compilation actions.
static bool ContainsCompileAction(const Action *A) {
if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
return true;
@@ -838,7 +850,7 @@ static bool ContainsCompileAction(const Action *A) {
return false;
}
-/// \brief Check if -relax-all should be passed to the internal assembler.
+/// Check if -relax-all should be passed to the internal assembler.
/// This is done by default when compiling non-assembler source with -O0.
static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
bool RelaxDefault = true;
@@ -907,34 +919,46 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
}
}
+static bool checkDebugInfoOption(const Arg *A, const ArgList &Args,
+ const Driver &D, const ToolChain &TC) {
+ assert(A && "Expected non-nullptr argument.");
+ if (TC.supportsDebugInfoOption(A))
+ return true;
+ D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
+ << A->getAsString(Args) << TC.getTripleString();
+ return false;
+}
+
static void RenderDebugInfoCompressionArgs(const ArgList &Args,
ArgStringList &CmdArgs,
- const Driver &D) {
+ const Driver &D,
+ const ToolChain &TC) {
const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ);
if (!A)
return;
+ if (checkDebugInfoOption(A, Args, D, TC)) {
+ if (A->getOption().getID() == options::OPT_gz) {
+ if (llvm::zlib::isAvailable())
+ CmdArgs.push_back("-compress-debug-sections");
+ else
+ D.Diag(diag::warn_debug_compression_unavailable);
+ return;
+ }
- if (A->getOption().getID() == options::OPT_gz) {
- if (llvm::zlib::isAvailable())
- CmdArgs.push_back("-compress-debug-sections");
- else
- D.Diag(diag::warn_debug_compression_unavailable);
- return;
- }
-
- StringRef Value = A->getValue();
- if (Value == "none") {
- CmdArgs.push_back("-compress-debug-sections=none");
- } else if (Value == "zlib" || Value == "zlib-gnu") {
- if (llvm::zlib::isAvailable()) {
- CmdArgs.push_back(
- Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
+ StringRef Value = A->getValue();
+ if (Value == "none") {
+ CmdArgs.push_back("-compress-debug-sections=none");
+ } else if (Value == "zlib" || Value == "zlib-gnu") {
+ if (llvm::zlib::isAvailable()) {
+ CmdArgs.push_back(
+ Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
+ } else {
+ D.Diag(diag::warn_debug_compression_unavailable);
+ }
} else {
- D.Diag(diag::warn_debug_compression_unavailable);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
}
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
}
}
@@ -1064,73 +1088,28 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// wonky, but we include looking for .gch so we can support seamless
// replacement into a build system already set up to be generating
// .gch files.
- int YcIndex = -1, YuIndex = -1;
- {
- int AI = -1;
+
+ if (getToolChain().getDriver().IsCLMode()) {
const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
- for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
- // Walk the whole i_Group and skip non "-include" flags so that the index
- // here matches the index in the next loop below.
- ++AI;
- if (!A->getOption().matches(options::OPT_include))
- continue;
- if (YcArg && strcmp(A->getValue(), YcArg->getValue()) == 0)
- YcIndex = AI;
- if (YuArg && strcmp(A->getValue(), YuArg->getValue()) == 0)
- YuIndex = AI;
+ if (YcArg && JA.getKind() >= Action::PrecompileJobClass &&
+ JA.getKind() <= Action::AssembleJobClass) {
+ CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj"));
+ }
+ if (YcArg || YuArg) {
+ StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue();
+ if (!isa<PrecompileJobAction>(JA)) {
+ CmdArgs.push_back("-include-pch");
+ CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(C, ThroughHeader)));
+ }
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader));
}
- }
- if (isa<PrecompileJobAction>(JA) && YcIndex != -1) {
- Driver::InputList Inputs;
- D.BuildInputs(getToolChain(), C.getArgs(), Inputs);
- assert(Inputs.size() == 1 && "Need one input when building pch");
- CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") +
- Inputs[0].second->getValue()));
}
bool RenderedImplicitInclude = false;
- int AI = -1;
for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
- ++AI;
-
- if (getToolChain().getDriver().IsCLMode() &&
- A->getOption().matches(options::OPT_include)) {
- // In clang-cl mode, /Ycfoo.h means that all code up to a foo.h
- // include is compiled into foo.h, and everything after goes into
- // the .obj file. /Yufoo.h means that all includes prior to and including
- // foo.h are completely skipped and replaced with a use of the pch file
- // for foo.h. (Each flag can have at most one value, multiple /Yc flags
- // just mean that the last one wins.) If /Yc and /Yu are both present
- // and refer to the same file, /Yc wins.
- // Note that OPT__SLASH_FI gets mapped to OPT_include.
- // FIXME: The code here assumes that /Yc and /Yu refer to the same file.
- // cl.exe seems to support both flags with different values, but that
- // seems strange (which flag does /Fp now refer to?), so don't implement
- // that until someone needs it.
- int PchIndex = YcIndex != -1 ? YcIndex : YuIndex;
- if (PchIndex != -1) {
- if (isa<PrecompileJobAction>(JA)) {
- // When building the pch, skip all includes after the pch.
- assert(YcIndex != -1 && PchIndex == YcIndex);
- if (AI >= YcIndex)
- continue;
- } else {
- // When using the pch, skip all includes prior to the pch.
- if (AI < PchIndex) {
- A->claim();
- continue;
- }
- if (AI == PchIndex) {
- A->claim();
- CmdArgs.push_back("-include-pch");
- CmdArgs.push_back(
- Args.MakeArgString(D.GetClPchPath(C, A->getValue())));
- continue;
- }
- }
- }
- } else if (A->getOption().matches(options::OPT_include)) {
+ if (A->getOption().matches(options::OPT_include)) {
// Handling of gcc-style gch precompiled headers.
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
@@ -1282,6 +1261,8 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
case llvm::Triple::hexagon:
case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
case llvm::Triple::systemz:
case llvm::Triple::xcore:
return false;
@@ -1291,6 +1272,8 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
static bool isNoCommonDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
default:
+ if (Triple.isOSFuchsia())
+ return true;
return false;
case llvm::Triple::xcore:
@@ -1338,7 +1321,7 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
// Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_mno_global_merge))
CmdArgs.push_back("-arm-global-merge=false");
else
@@ -1391,6 +1374,11 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
AddPPCTargetArgs(Args, CmdArgs);
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ AddRISCVTargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
@@ -1447,21 +1435,21 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
options::OPT_mno_fix_cortex_a53_835769)) {
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
else
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
} else if (Triple.isAndroid()) {
// Enabled A53 errata (835769) workaround by default on android
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
}
// Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_mno_global_merge))
CmdArgs.push_back("-aarch64-enable-global-merge=false");
else
@@ -1668,6 +1656,25 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
}
+void Clang::AddRISCVTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // FIXME: currently defaults to the soft-float ABIs. Will need to be
+ // expanded to select ilp32f, ilp32d, lp64f, lp64d when appropriate.
+ const char *ABIName = nullptr;
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ ABIName = A->getValue();
+ else if (Triple.getArch() == llvm::Triple::riscv32)
+ ABIName = "ilp32";
+ else if (Triple.getArch() == llvm::Triple::riscv64)
+ ABIName = "lp64";
+ else
+ llvm_unreachable("Unexpected triple!");
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+}
+
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
sparc::FloatABI FloatABI =
@@ -1722,6 +1729,9 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
+ } else if (getToolChain().getDriver().IsCLMode()) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-x86-asm-syntax=intel");
}
// Set flags to support MCU ABI.
@@ -2043,7 +2053,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// 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
+ // adjusting what we think is enabled/disabled, then at the end setting the
// LLVM flags based on the final state.
bool HonorINFs = true;
bool HonorNaNs = true;
@@ -2202,6 +2212,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-mfpmath");
CmdArgs.push_back(A->getValue());
}
+
+ // Disable a codegen optimization for floating-point casts.
+ if (Args.hasFlag(options::OPT_fno_strict_float_cast_overflow,
+ options::OPT_fstrict_float_cast_overflow, false))
+ CmdArgs.push_back("-fno-strict-float-cast-overflow");
}
static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
@@ -2337,6 +2352,7 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
options::OPT_cl_no_signed_zeros,
options::OPT_cl_denorms_are_zero,
options::OPT_cl_fp32_correctly_rounded_divide_sqrt,
+ options::OPT_cl_uniform_work_group_size
};
if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
@@ -2458,6 +2474,13 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
CmdArgs.push_back("-fno-math-builtin");
}
+void Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
+ llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Result);
+ llvm::sys::path::append(Result, "org.llvm.clang.");
+ appendUserToPath(Result);
+ llvm::sys::path::append(Result, "ModuleCache");
+}
+
static void RenderModulesOptions(Compilation &C, const Driver &D,
const ArgList &Args, const InputInfo &Input,
const InputInfo &Output,
@@ -2499,11 +2522,13 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
CmdArgs.push_back("-fmodules-strict-decluse");
// -fno-implicit-modules turns off implicitly compiling modules on demand.
+ bool ImplicitModules = false;
if (!Args.hasFlag(options::OPT_fimplicit_modules,
options::OPT_fno_implicit_modules, HaveClangModules)) {
if (HaveModules)
CmdArgs.push_back("-fno-implicit-modules");
} else if (HaveModules) {
+ ImplicitModules = true;
// -fmodule-cache-path specifies where our implicitly-built module files
// should be written.
SmallString<128> Path;
@@ -2518,10 +2543,7 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
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");
+ Driver::getDefaultModuleCachePath(Path);
}
const char Arg[] = "-fmodules-cache-path=";
@@ -2613,7 +2635,11 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
options::OPT_fmodules_validate_once_per_build_session);
}
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);
+ if (Args.hasFlag(options::OPT_fmodules_validate_system_headers,
+ options::OPT_fno_modules_validate_system_headers,
+ ImplicitModules))
+ CmdArgs.push_back("-fmodules-validate-system-headers");
+
Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
}
@@ -2632,6 +2658,9 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
CmdArgs.push_back("-fno-signed-char");
}
+ if (Args.hasFlag(options::OPT_fchar8__t, options::OPT_fno_char8__t, false))
+ CmdArgs.push_back("-fchar8_t");
+
if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
options::OPT_fno_short_wchar)) {
if (A->getOption().matches(options::OPT_fshort_wchar)) {
@@ -2850,7 +2879,9 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
codegenoptions::DebugInfoKind &DebugInfoKind,
const Arg *&SplitDWARFArg) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
- options::OPT_fno_debug_info_for_profiling, false))
+ options::OPT_fno_debug_info_for_profiling, false) &&
+ checkDebugInfoOption(
+ Args.getLastArg(options::OPT_fdebug_info_for_profiling), Args, D, TC))
CmdArgs.push_back("-fdebug-info-for-profiling");
// The 'g' groups options involve a somewhat intricate sequence of decisions
@@ -2873,29 +2904,38 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf);
+ if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
+ SplitDWARFArg = nullptr;
+ SplitDWARFInlining = false;
+ }
+
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;
+ if (checkDebugInfoOption(A, Args, D, TC)) {
+ // 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;
}
} else {
- // For any other 'g' option, use Limited.
DebugInfoKind = codegenoptions::LimitedDebugInfo;
}
}
@@ -2903,52 +2943,65 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// 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 (checkDebugInfoOption(A, Args, D, TC)) {
+ 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());
+ if (checkDebugInfoOption(A, Args, D, TC))
+ 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();
+ if (EmitCodeView) {
+ if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
+ EmitCodeView = checkDebugInfoOption(A, Args, D, TC);
+ if (EmitCodeView) {
+ // DWARFVersion remains at 0 if no explicit choice was made.
+ CmdArgs.push_back("-gcodeview");
+ }
+ }
}
+ if (!EmitCodeView && 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.
+ // 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 (const Arg *A = Args.getLastArg(options::OPT_gcolumn_info))
+ (void)checkDebugInfoOption(A, Args, D, TC);
if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default=*/!(IsWindowsMSVC && EmitCodeView) &&
+ /*Default=*/!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");
- }
+ if (const Arg *A = Args.getLastArg(options::OPT_gmodules))
+ if (checkDebugInfoOption(A, Args, D, TC)) {
+ if (DebugInfoKind != codegenoptions::DebugLineTablesOnly) {
+ 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.
@@ -2972,34 +3025,66 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
options::OPT_fno_standalone_debug,
TC.GetDefaultStandaloneDebug());
+ if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug))
+ (void)checkDebugInfoOption(A, Args, D, TC);
if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
DebugInfoKind = codegenoptions::FullDebugInfo;
+ if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source,
+ false)) {
+ // Source embedding is a vendor extension to DWARF v5. By now we have
+ // checked if a DWARF version was stated explicitly, and have otherwise
+ // fallen back to the target default, so if this is still not at least 5
+ // we emit an error.
+ const Arg *A = Args.getLastArg(options::OPT_gembed_source);
+ if (DWARFVersion < 5)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-gdwarf-5";
+ else if (checkDebugInfoOption(A, Args, D, TC))
+ CmdArgs.push_back("-gembed-source");
+ }
+
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");
+ if (checkDebugInfoOption(Args.getLastArg(options::OPT_fdebug_macro), Args,
+ D, TC))
+ 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");
+ if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
+ false))
+ if (checkDebugInfoOption(Args.getLastArg(options::OPT_ggnu_pubnames), Args,
+ D, TC))
+ 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");
+ bool NeedAranges = DebuggerTuning == llvm::DebuggerKind::SCE;
+ if (const Arg *A = Args.getLastArg(options::OPT_gdwarf_aranges))
+ NeedAranges = checkDebugInfoOption(A, Args, D, TC) || NeedAranges;
+ if (NeedAranges) {
+ CmdArgs.push_back("-mllvm");
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");
+ if (!T.isOSBinFormatELF()) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_fdebug_types_section)
+ ->getAsString(Args)
+ << T.getTriple();
+ } else if (checkDebugInfoOption(
+ Args.getLastArg(options::OPT_fdebug_types_section), Args, D,
+ TC)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-generate-type-units");
+ }
}
// Decide how to render forward declarations of template instantiations.
@@ -3007,11 +3092,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
if (DebuggerTuning == llvm::DebuggerKind::SCE)
CmdArgs.push_back("-debug-forward-template-params");
- // Do we need to explicitly import anonymous namespaces into the parent scope?
+ // 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);
+ RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
}
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
@@ -3029,13 +3115,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
const InputInfo &Input = Inputs[0];
- // CUDA compilation may have multiple inputs (source file + results of
+ // CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP device jobs also take the host IR as a
// second input. All other jobs are expected to have exactly one
// input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
+ bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
- assert((IsCuda || (IsOpenMPDevice && Inputs.size() == 2) ||
+ assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) ||
Inputs.size() == 1) &&
"Unable to handle multiple inputs.");
@@ -3047,10 +3134,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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) {
+ // Adjust IsWindowsXYZ for CUDA/HIP compilations. Even when compiling in
+ // device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not
+ // Windows), we need to pass Windows-specific flags to cc1.
+ if (IsCuda || IsHIP) {
IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment();
IsWindowsGNU |= AuxTriple && AuxTriple->isWindowsGNUEnvironment();
IsWindowsCygnus |= AuxTriple && AuxTriple->isWindowsCygwinEnvironment();
@@ -3074,18 +3161,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_MJ);
}
- if (IsCuda) {
- // We have to pass the triple of the host if compiling for a CUDA device and
- // vice-versa.
+ if (IsCuda || IsHIP) {
+ // We have to pass the triple of the host if compiling for a CUDA/HIP device
+ // and vice-versa.
std::string NormalizedTriple;
- if (JA.isDeviceOffloading(Action::OFK_Cuda))
+ if (JA.isDeviceOffloading(Action::OFK_Cuda) ||
+ JA.isDeviceOffloading(Action::OFK_HIP))
NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Host>()
->getTriple()
.normalize();
else
- NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Cuda>()
- ->getTriple()
- .normalize();
+ NormalizedTriple =
+ (IsCuda ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
+ : C.getSingleOffloadToolChain<Action::OFK_HIP>())
+ ->getTriple()
+ .normalize();
CmdArgs.push_back("-aux-triple");
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
@@ -3188,7 +3278,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_LLVM_BC)
CmdArgs.push_back("-emit-llvm-uselists");
- if (D.isUsingLTO()) {
+ // Device-side jobs do not support LTO.
+ bool isDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
+ JA.isDeviceOffloading(Action::OFK_Host));
+
+ if (D.isUsingLTO() && !isDeviceOffloadAction) {
Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ);
// The Darwin and PS4 linkers currently use the legacy LTO API, which
@@ -3207,6 +3301,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
}
+ if (Args.getLastArg(options::OPT_save_temps_EQ))
+ Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
+
// Embed-bitcode option.
if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() &&
(isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
@@ -3224,13 +3321,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!C.isForDiagnostics())
CmdArgs.push_back("-disable-free");
-// Disable the verification pass in -asserts builds.
#ifdef NDEBUG
- CmdArgs.push_back("-disable-llvm-verifier");
- // Discard LLVM value names in -asserts builds.
- CmdArgs.push_back("-discard-value-names");
+ const bool IsAssertBuild = false;
+#else
+ const bool IsAssertBuild = true;
#endif
+ // Disable the verification pass in -asserts builds.
+ if (!IsAssertBuild)
+ CmdArgs.push_back("-disable-llvm-verifier");
+
+ // Discard value names in assert builds unless otherwise specified.
+ if (Args.hasFlag(options::OPT_fdiscard_value_names,
+ options::OPT_fno_discard_value_names, !IsAssertBuild))
+ CmdArgs.push_back("-discard-value-names");
+
// Set the main file name, so that debug info works even with
// -save-temps.
CmdArgs.push_back("-main-file-name");
@@ -3246,6 +3351,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CheckCodeGenerationOptions(D, Args);
+ unsigned FunctionAlignment = ParseFunctionAlignment(getToolChain(), Args);
+ assert(FunctionAlignment <= 31 && "function alignment will be truncated!");
+ if (FunctionAlignment) {
+ CmdArgs.push_back("-function-alignment");
+ CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment)));
+ }
+
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
@@ -3292,6 +3404,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_merge_all_constants, false))
CmdArgs.push_back("-fmerge-all-constants");
+ if (Args.hasFlag(options::OPT_fno_delete_null_pointer_checks,
+ options::OPT_fdelete_null_pointer_checks, false))
+ CmdArgs.push_back("-fno-delete-null-pointer-checks");
+
// LLVM Code Generator Options.
if (Args.hasArg(options::OPT_frewrite_map_file) ||
@@ -3382,9 +3498,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_strict_vtable_pointers,
false))
CmdArgs.push_back("-fstrict-vtable-pointers");
+ if (Args.hasFlag(options::OPT_fforce_emit_vtables,
+ options::OPT_fno_force_emit_vtables,
+ false))
+ CmdArgs.push_back("-fforce-emit-vtables");
if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
+ if (Args.hasFlag(options::OPT_fno_escaping_block_tail_calls,
+ options::OPT_fescaping_block_tail_calls, false))
+ CmdArgs.push_back("-fno-escaping-block-tail-calls");
Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
options::OPT_fno_fine_grained_bitfield_accesses);
@@ -3404,8 +3527,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.hasArg(options::OPT_dA))
CmdArgs.push_back("-masm-verbose");
- if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
- IsIntegratedAssemblerDefault))
+ if (!getToolChain().useIntegratedAs())
CmdArgs.push_back("-no-integrated-as");
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
@@ -3498,6 +3620,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
types::ID InputType = Input.getType();
if (D.IsCLMode())
AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
+ else
+ EmitCodeView = Args.hasArg(options::OPT_gcodeview);
const Arg *SplitDWARFArg = nullptr;
RenderDebugOptions(getToolChain(), D, RawTriple, Args, EmitCodeView,
@@ -3583,14 +3707,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_finstrument_function_entry_bare))
A->render(Args, CmdArgs);
- addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
+ // NVPTX doesn't support PGO or coverage. There's no runtime support for
+ // sampling, overhead of call arc collection is way too high and there's no
+ // way to collect the output.
+ if (!Triple.isNVPTX())
+ addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
if (auto *ABICompatArg = Args.getLastArg(options::OPT_fclang_abi_compat_EQ))
ABICompatArg->render(Args, CmdArgs);
- // Add runtime flag for PS4 when PGO or Coverage are enabled.
- if (RawTriple.isPS4CPU())
+ // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.
+ if (RawTriple.isPS4CPU()) {
PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs);
+ PS4cpu::addSanitizerArgs(getToolChain(), CmdArgs);
+ }
// Pass options for controlling the default header search paths.
if (Args.hasArg(options::OPT_nostdinc)) {
@@ -3657,6 +3787,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
Args.AddLastArg(CmdArgs, options::OPT_w);
+ // Fixed point flags
+ if (Args.hasFlag(options::OPT_ffixed_point, options::OPT_fno_fixed_point,
+ /*Default=*/false))
+ Args.AddLastArg(CmdArgs, options::OPT_ffixed_point);
+
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
// (-ansi is equivalent to -std=c89 or -std=c++98).
//
@@ -3741,14 +3876,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add in -fdebug-compilation-dir if necessary.
addDebugCompDirArg(Args, CmdArgs);
- for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) {
- StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
- D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map;
- else
- CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
- A->claim();
- }
+ addDebugPrefixMapArg(D, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
options::OPT_ftemplate_depth_EQ)) {
@@ -3798,6 +3926,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Args.hasFlag(options::OPT_fstack_size_section,
+ options::OPT_fno_stack_size_section, RawTriple.isPS4()))
+ CmdArgs.push_back("-fstack-size-section");
+
CmdArgs.push_back("-ferror-limit");
if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
CmdArgs.push_back(A->getValue());
@@ -3857,14 +3989,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// 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);
+ Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
- // Emulated TLS is enabled by default on Android and OpenBSD, and can be enabled
- // manually with -femulated-tls.
- bool EmulatedTLSDefault = Triple.isAndroid() || Triple.isOSOpenBSD() ||
- Triple.isWindowsCygwinEnvironment();
- if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
- EmulatedTLSDefault))
- CmdArgs.push_back("-femulated-tls");
+ Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
+ options::OPT_fno_emulated_tls);
+
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
Args.AddLastArg(CmdArgs, options::OPT_fzvector);
@@ -3890,7 +4019,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_fopenmp_use_tls,
options::OPT_fnoopenmp_use_tls, /*Default=*/true))
CmdArgs.push_back("-fnoopenmp-use-tls");
+ Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
+ options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
+
+ // When in OpenMP offloading mode with NVPTX target, forward
+ // cuda-mode flag
+ Args.AddLastArg(CmdArgs, options::OPT_fopenmp_cuda_mode,
+ options::OPT_fno_openmp_cuda_mode);
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -3984,26 +4120,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mstack-probe-size=0");
}
+ if (!Args.hasFlag(options::OPT_mstack_arg_probe,
+ options::OPT_mno_stack_arg_probe, true))
+ CmdArgs.push_back(Args.MakeArgString("-mno-stack-arg-probe"));
+
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
options::OPT_mno_restrict_it)) {
if (A->getOption().matches(options::OPT_mrestrict_it)) {
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-restrict-it");
} else {
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-no-restrict-it");
}
} else if (Triple.isOSWindows() &&
(Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb)) {
// Windows on ARM expects restricted IT blocks
- CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-restrict-it");
}
// Forward -cl options to -cc1
RenderOpenCLOptions(Args, CmdArgs);
+ if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));
+ }
+
// Forward -f options with positive and negative forms; we translate
// these by hand.
if (Arg *A = getLastProfileSampleUseArg(Args)) {
@@ -4062,8 +4207,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
if (KernelOrKext || (types::isCXX(InputType) &&
- (RTTIMode == ToolChain::RM_DisabledExplicitly ||
- RTTIMode == ToolChain::RM_DisabledImplicitly)))
+ (RTTIMode == ToolChain::RM_Disabled)))
CmdArgs.push_back("-fno-rtti");
// -fshort-enums=0 is default for all architectures except Hexagon.
@@ -4085,6 +4229,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
+ if (Args.hasFlag(options::OPT_fregister_global_dtors_with_atexit,
+ options::OPT_fno_register_global_dtors_with_atexit,
+ RawTriple.isOSDarwin() && !KernelOrKext))
+ CmdArgs.push_back("-fregister-global-dtors-with-atexit");
+
// -fms-extensions=0 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC))
@@ -4151,7 +4300,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!IsWindowsMSVC || IsMSVC2015Compatible))
CmdArgs.push_back("-fno-threadsafe-statics");
- // -fno-delayed-template-parsing is default, except when targetting MSVC.
+ // -fno-delayed-template-parsing is default, except when targeting 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.
@@ -4296,6 +4445,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (!Args.hasFlag(options::OPT_Qy, options::OPT_Qn, true))
+ CmdArgs.push_back("-Qn");
+
// -fcommon is the default unless compiling kernel code or the target says so
bool NoCommonDefault = KernelOrKext || isNoCommonDefault(RawTriple);
if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
@@ -4477,31 +4629,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Setup statistics file output.
- if (const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ)) {
- StringRef SaveStats = A->getValue();
-
- SmallString<128> StatsFile;
- bool DoSaveStats = false;
- if (SaveStats == "obj") {
- if (Output.isFilename()) {
- StatsFile.assign(Output.getFilename());
- llvm::sys::path::remove_filename(StatsFile);
- }
- DoSaveStats = true;
- } else if (SaveStats == "cwd") {
- DoSaveStats = true;
- } else {
- D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
- }
-
- if (DoSaveStats) {
- StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
- llvm::sys::path::append(StatsFile, BaseName);
- llvm::sys::path::replace_extension(StatsFile, "stats");
- CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") +
- StatsFile));
- }
- }
+ SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
+ if (!StatsFile.empty())
+ CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + StatsFile));
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
@@ -4588,14 +4718,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Flags));
}
- // Host-side cuda compilation receives device-side outputs as Inputs[1...].
- // Include them with -fcuda-include-gpubinary.
- if (IsCuda && Inputs.size() > 1)
- for (auto I = std::next(Inputs.begin()), E = Inputs.end(); I != E; ++I) {
+ if (IsCuda) {
+ // Host-side cuda compilation receives all device-side outputs in a single
+ // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
+ if (Inputs.size() > 1) {
+ assert(Inputs.size() == 2 && "More than one GPU binary!");
CmdArgs.push_back("-fcuda-include-gpubinary");
- CmdArgs.push_back(I->getFilename());
+ CmdArgs.push_back(Inputs[1].getFilename());
}
+ if (Args.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, false))
+ CmdArgs.push_back("-fcuda-rdc");
+ if (Args.hasFlag(options::OPT_fcuda_short_ptr,
+ options::OPT_fno_cuda_short_ptr, false))
+ CmdArgs.push_back("-fcuda-short-ptr");
+ }
+
// OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
// to specify the result of the compile phase on the host, so the meaningful
// device declarations can be identified. Also, -fopenmp-is-device is passed
@@ -4611,7 +4749,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// For all the host OpenMP offloading compile jobs we need to pass the targets
// information using -fopenmp-targets= option.
- if (isa<CompileJobAction>(JA) && JA.isHostOffloading(Action::OFK_OpenMP)) {
+ if (JA.isHostOffloading(Action::OFK_OpenMP)) {
SmallString<128> TargetInfo("-fopenmp-targets=");
Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
@@ -4670,6 +4808,40 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (Arg *A = Args.getLastArg(options::OPT_fforce_enable_int128,
+ options::OPT_fno_force_enable_int128)) {
+ if (A->getOption().matches(options::OPT_fforce_enable_int128))
+ CmdArgs.push_back("-fforce-enable-int128");
+ }
+
+ if (Args.hasFlag(options::OPT_fcomplete_member_pointers,
+ options::OPT_fno_complete_member_pointers, false))
+ CmdArgs.push_back("-fcomplete-member-pointers");
+
+ if (Arg *A = Args.getLastArg(options::OPT_moutline,
+ options::OPT_mno_outline)) {
+ if (A->getOption().matches(options::OPT_moutline)) {
+ // We only support -moutline in AArch64 right now. If we're not compiling
+ // for AArch64, emit a warning and ignore the flag. Otherwise, add the
+ // proper mllvm flags.
+ if (Triple.getArch() != llvm::Triple::aarch64) {
+ D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName();
+ } else {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-machine-outliner");
+ }
+ } else {
+ // Disable all outlining behaviour.
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-machine-outliner=never");
+ }
+ }
+
+ if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
+ getToolChain().getTriple().isOSBinFormatELF() &&
+ getToolChain().useIntegratedAs()))
+ CmdArgs.push_back("-faddrsig");
+
// Finally add the compile command to the compilation.
if (Args.hasArg(options::OPT__SLASH_fallback) &&
Output.getType() == types::TY_Object &&
@@ -4688,12 +4860,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
- // 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 (Arg *A = Args.getLastArg(options::OPT_pg))
if (Args.hasArg(options::OPT_fomit_frame_pointer))
D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
@@ -4744,6 +4910,14 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
<< value;
}
+ if ((runtime.getKind() == ObjCRuntime::GNUstep) &&
+ (runtime.getVersion() >= VersionTuple(2, 0)))
+ if (!getToolChain().getTriple().isOSBinFormatELF() &&
+ !getToolChain().getTriple().isOSBinFormatCOFF()) {
+ getToolChain().getDriver().Diag(
+ diag::err_drv_gnustep_objc_runtime_incompatible_binary)
+ << runtime.getVersion().getMajor();
+ }
runtimeArg->render(args, cmdArgs);
return runtime;
@@ -4837,7 +5011,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
// Legacy behaviour is to target the gnustep runtime if we are in
// non-fragile mode or the GCC runtime in fragile mode.
if (isNonFragile)
- runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1, 6));
+ runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(2, 0));
else
runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
}
@@ -4965,13 +5139,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("--dependent-lib=oldnames");
}
- // 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)) ||
- (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);
+ if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+ A->render(Args, CmdArgs);
// This controls whether or not we emit RTTI data for polymorphic types.
if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
@@ -5101,6 +5270,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
else
CmdArgs.push_back("msvc");
}
+
+ if (Args.hasArg(options::OPT__SLASH_Guard) &&
+ Args.getLastArgValue(options::OPT__SLASH_Guard).equals_lower("cf"))
+ CmdArgs.push_back("-cfguard");
}
visualstudio::Compiler *Clang::getCLFallback() const {
@@ -5255,6 +5428,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs);
+ addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs);
+
// Set the AT_producer to the clang version when using the integrated
// assembler on assembly source files.
CmdArgs.push_back("-dwarf-debug-producer");
@@ -5265,7 +5440,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
llvm::DebuggerKind::Default);
- RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
+ RenderDebugInfoCompressionArgs(Args, CmdArgs, D, getToolChain());
// Handle -fPIC et al -- the relocation-model affects the assembler
@@ -5351,19 +5526,17 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
+ if (Args.hasArg(options::OPT_gsplit_dwarf) &&
+ getToolChain().getTriple().isOSLinux()) {
+ CmdArgs.push_back("-split-dwarf-file");
+ CmdArgs.push_back(SplitDebugName(Args, Input));
+ }
+
assert(Input.isFilename() && "Invalid input.");
CmdArgs.push_back(Input.getFilename());
const char *Exec = getToolChain().getDriver().getClangProgramPath();
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
-
- // 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 (Args.hasArg(options::OPT_gsplit_dwarf) &&
- getToolChain().getTriple().isOSLinux())
- SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Input));
}
// Begin OffloadBundler
@@ -5414,6 +5587,10 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
Triples += Action::GetOffloadKindName(CurKind);
Triples += '-';
Triples += CurTC->getTriple().normalize();
+ if (CurKind == Action::OFK_HIP && CurDep->getOffloadingArch()) {
+ Triples += '-';
+ Triples += CurDep->getOffloadingArch();
+ }
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
@@ -5483,6 +5660,11 @@ void OffloadBundler::ConstructJobMultipleOutputs(
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
Triples += '-';
Triples += Dep.DependentToolChain->getTriple().normalize();
+ if (Dep.DependentOffloadKind == Action::OFK_HIP &&
+ !Dep.DependentBoundArch.empty()) {
+ Triples += '-';
+ Triples += Dep.DependentBoundArch;
+ }
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h
index e23822b9c678..df67fb2cb331 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h
@@ -25,7 +25,7 @@ namespace driver {
namespace tools {
-/// \brief Clang compiler tool.
+/// Clang compiler tool.
class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
public:
static const char *getBaseInputName(const llvm::opt::ArgList &Args,
@@ -60,6 +60,8 @@ private:
llvm::opt::ArgStringList &CmdArgs) const;
void AddR600TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ void AddRISCVTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
void AddSparcTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void AddSystemZTargetArgs(const llvm::opt::ArgList &Args,
@@ -109,7 +111,7 @@ public:
const char *LinkingOutput) const override;
};
-/// \brief Clang integrated assembler tool.
+/// Clang integrated assembler tool.
class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
public:
ClangAs(const ToolChain &TC)
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp
index cdf807f7f91f..80f9fc493fd8 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp
@@ -10,7 +10,6 @@
#include "CloudABI.h"
#include "InputInfo.h"
#include "CommonArgs.h"
-#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
@@ -75,8 +74,11 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
- if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
+ }
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -104,10 +106,11 @@ CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(P.str());
}
-std::string CloudABI::findLibCxxIncludePath() const {
+void CloudABI::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
SmallString<128> P(getDriver().Dir);
llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1");
- return P.str();
+ addSystemInclude(DriverArgs, CC1Args, P.str());
}
void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.h
index a284eb3dc0a4..7464c5954555 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.h
@@ -50,7 +50,9 @@ public:
GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
return ToolChain::CST_Libcxx;
}
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp
index f26880123d8c..1e093b25b909 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -8,14 +8,14 @@
//===----------------------------------------------------------------------===//
#include "CommonArgs.h"
-#include "InputInfo.h"
-#include "Hexagon.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
+#include "Hexagon.h"
+#include "InputInfo.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
@@ -31,6 +31,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
+#include "clang/Driver/XRayArgs.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -41,6 +42,7 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compression.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -144,12 +146,14 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
for (const auto &II : Inputs) {
- // If the current tool chain refers to an OpenMP offloading host, we should
- // ignore inputs that refer to OpenMP offloading devices - they will be
- // embedded according to a proper linker script.
+ // If the current tool chain refers to an OpenMP or HIP offloading host, we
+ // should ignore inputs that refer to OpenMP or HIP offloading devices -
+ // they will be embedded according to a proper linker script.
if (auto *IA = II.getAction())
- if (JA.isHostOffloading(Action::OFK_OpenMP) &&
- IA->isDeviceOffloading(Action::OFK_OpenMP))
+ if ((JA.isHostOffloading(Action::OFK_OpenMP) &&
+ IA->isDeviceOffloading(Action::OFK_OpenMP)) ||
+ (JA.isHostOffloading(Action::OFK_HIP) &&
+ IA->isDeviceOffloading(Action::OFK_HIP)))
continue;
if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
@@ -363,23 +367,20 @@ unsigned tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
return Parallelism;
}
-// CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
-// default.
+// CloudABI uses -ffunction-sections and -fdata-sections by default.
bool tools::isUseSeparateSections(const llvm::Triple &Triple) {
- return Triple.getOS() == llvm::Triple::CloudABI ||
- Triple.getArch() == llvm::Triple::wasm32 ||
- Triple.getArch() == llvm::Triple::wasm64;
+ return Triple.getOS() == llvm::Triple::CloudABI;
}
void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
- ArgStringList &CmdArgs, bool IsThinLTO,
- const Driver &D) {
+ ArgStringList &CmdArgs, const InputInfo &Output,
+ const InputInfo &Input, bool IsThinLTO) {
// Tell the linker to load the plugin. This has to come before AddLinkerInputs
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
CmdArgs.push_back("-plugin");
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
const char *Suffix = ".dll";
#elif defined(__APPLE__)
const char *Suffix = ".dylib";
@@ -415,10 +416,16 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt));
}
+ if (Args.hasArg(options::OPT_gsplit_dwarf)) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=dwo_dir=") +
+ Output.getFilename() + "_dwo"));
+ }
+
if (IsThinLTO)
CmdArgs.push_back("-plugin-opt=thinlto");
- if (unsigned Parallelism = getLTOParallelism(Args, D))
+ if (unsigned Parallelism = getLTOParallelism(Args, ToolChain.getDriver()))
CmdArgs.push_back(
Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism)));
@@ -449,7 +456,7 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
if (Arg *A = getLastProfileSampleUseArg(Args)) {
StringRef FName = A->getValue();
if (!llvm::sys::fs::exists(FName))
- D.Diag(diag::err_drv_no_such_file) << FName;
+ ToolChain.getDriver().Diag(diag::err_drv_no_such_file) << FName;
else
CmdArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName));
@@ -458,14 +465,24 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
// 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)) {
+ /* Default */ ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER)) {
CmdArgs.push_back("-plugin-opt=new-pass-manager");
}
+ // Setup statistics file output.
+ SmallString<128> StatsFile =
+ getStatsFileName(Args, Output, Input, ToolChain.getDriver());
+ if (!StatsFile.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
}
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
+ if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
+ options::OPT_fno_rtlib_add_rpath, false))
+ return;
+
std::string CandidateRPath = TC.getArchSpecificLibPath();
if (TC.getVFS().exists(CandidateRPath)) {
CmdArgs.push_back("-rpath");
@@ -511,9 +528,9 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
bool IsShared, bool IsWhole) {
// Wrap any static runtimes that must be forced into executable in
// whole-archive.
- if (IsWhole) CmdArgs.push_back("-whole-archive");
+ if (IsWhole) CmdArgs.push_back("--whole-archive");
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Sanitizer, IsShared));
- if (IsWhole) CmdArgs.push_back("-no-whole-archive");
+ if (IsWhole) CmdArgs.push_back("--no-whole-archive");
if (IsShared) {
addArchSpecificRPath(TC, Args, CmdArgs);
@@ -525,6 +542,15 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs,
StringRef Sanitizer) {
+ // Solaris ld defaults to --export-dynamic behaviour but doesn't support
+ // the option, so don't try to pass it.
+ if (TC.getTriple().getOS() == llvm::Triple::Solaris)
+ return true;
+ // Myriad is static linking only. Furthermore, some versions of its
+ // linker have the bug where --export-dynamic overrides -static, so
+ // don't use --export-dynamic on that platform.
+ if (TC.getTriple().getVendor() == llvm::Triple::Myriad)
+ return true;
SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
if (llvm::sys::fs::exists(SanRT + ".syms")) {
CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
@@ -538,22 +564,23 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
CmdArgs.push_back("--no-as-needed");
- // There's no libpthread or librt on RTEMS.
- if (TC.getTriple().getOS() != llvm::Triple::RTEMS) {
+ // There's no libpthread or librt on RTEMS & Android.
+ if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
+ !TC.getTriple().isAndroid()) {
CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lrt");
+ if (TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ CmdArgs.push_back("-lrt");
}
CmdArgs.push_back("-lm");
// 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::OpenBSD &&
TC.getTriple().getOS() != llvm::Triple::RTEMS)
CmdArgs.push_back("-ldl");
- // Required for forkpty on some OSes
- if (TC.getTriple().getOS() == llvm::Triple::NetBSD)
- CmdArgs.push_back("-lutil");
// Required for backtrace on some OSes
- if (TC.getTriple().getOS() == llvm::Triple::NetBSD)
+ if (TC.getTriple().getOS() == llvm::Triple::NetBSD ||
+ TC.getTriple().getOS() == llvm::Triple::FreeBSD)
CmdArgs.push_back("-lexecinfo");
}
@@ -573,14 +600,17 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
HelperStaticRuntimes.push_back("asan-preinit");
}
if (SanArgs.needsUbsanRt()) {
- if (SanArgs.requiresMinimalRuntime()) {
+ if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
- } else {
+ else
SharedRuntimes.push_back("ubsan_standalone");
- }
}
- if (SanArgs.needsScudoRt())
- SharedRuntimes.push_back("scudo");
+ if (SanArgs.needsScudoRt()) {
+ if (SanArgs.requiresMinimalRuntime())
+ SharedRuntimes.push_back("scudo_minimal");
+ else
+ SharedRuntimes.push_back("scudo");
+ }
if (SanArgs.needsHwasanRt())
SharedRuntimes.push_back("hwasan");
}
@@ -646,9 +676,15 @@ 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");
+ if (SanArgs.requiresMinimalRuntime()) {
+ StaticRuntimes.push_back("scudo_minimal");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("scudo_cxx_minimal");
+ } else {
+ StaticRuntimes.push_back("scudo");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("scudo_cxx");
+ }
}
}
@@ -691,7 +727,7 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
// If there is a static runtime with no dynamic list, force all the symbols
// to be dynamic to be sure we export sanitizer interface functions.
if (AddExportDynamic)
- CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--export-dynamic");
const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
@@ -700,6 +736,35 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
}
+bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) {
+ if (Args.hasArg(options::OPT_shared))
+ return false;
+
+ if (TC.getXRayArgs().needsXRayRt()) {
+ CmdArgs.push_back("-whole-archive");
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray", false));
+ for (const auto &Mode : TC.getXRayArgs().modeList())
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode, false));
+ CmdArgs.push_back("-no-whole-archive");
+ return true;
+ }
+
+ return false;
+}
+
+void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) {
+ CmdArgs.push_back("--no-as-needed");
+ CmdArgs.push_back("-lpthread");
+ if (TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ CmdArgs.push_back("-lrt");
+ CmdArgs.push_back("-lm");
+
+ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
+ TC.getTriple().getOS() != llvm::Triple::NetBSD &&
+ TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ CmdArgs.push_back("-ldl");
+}
+
bool tools::areOptimizationsEnabled(const ArgList &Args) {
// Find the last -O arg and see if it is non-zero.
if (Arg *A = Args.getLastArg(options::OPT_O_Group))
@@ -859,6 +924,10 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
}
}
+ // AMDGPU-specific defaults for PIC.
+ if (Triple.getArch() == llvm::Triple::amdgcn)
+ PIC = true;
+
// The last argument relating to either PIC or PIE wins, and no
// other argument is used. If the last argument is any flavor of the
// '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
@@ -964,16 +1033,26 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
RWPI = true;
}
- // ROPI and RWPI are not comaptible with PIC or PIE.
+ // ROPI and RWPI are not compatible with PIC or PIE.
if ((ROPI || RWPI) && (PIC || PIE))
ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic);
- // When targettng MIPS64 with N64, the default is PIC, unless -mno-abicalls is
- // used.
- if ((Triple.getArch() == llvm::Triple::mips64 ||
- Triple.getArch() == llvm::Triple::mips64el) &&
- Args.hasArg(options::OPT_mno_abicalls))
- return std::make_tuple(llvm::Reloc::Static, 0U, false);
+ if (Triple.isMIPS()) {
+ StringRef CPUName;
+ StringRef ABIName;
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+ // When targeting the N64 ABI, PIC is the default, except in the case
+ // when the -mno-abicalls option is used. In that case we exit
+ // at next check regardless of PIC being set below.
+ if (ABIName == "n64")
+ PIC = true;
+ // When targettng MIPS with -mno-abicalls, it's always static.
+ if(Args.hasArg(options::OPT_mno_abicalls))
+ return std::make_tuple(llvm::Reloc::Static, 0U, false);
+ // Unlike other architectures, MIPS, even with -fPIC/-mxgot/multigot,
+ // does not use PIC level 2 for historical reasons.
+ IsPICLevelTwo = false;
+ }
if (PIC)
return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE);
@@ -989,6 +1068,40 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
return std::make_tuple(RelocM, 0U, false);
}
+// `-falign-functions` indicates that the functions should be aligned to a
+// 16-byte boundary.
+//
+// `-falign-functions=1` is the same as `-fno-align-functions`.
+//
+// The scalar `n` in `-falign-functions=n` must be an integral value between
+// [0, 65536]. If the value is not a power-of-two, it will be rounded up to
+// the nearest power-of-two.
+//
+// If we return `0`, the frontend will default to the backend's preferred
+// alignment.
+//
+// NOTE: icc only allows values between [0, 4096]. icc uses `-falign-functions`
+// to mean `-falign-functions=16`. GCC defaults to the backend's preferred
+// alignment. For unaligned functions, we default to the backend's preferred
+// alignment.
+unsigned tools::ParseFunctionAlignment(const ToolChain &TC,
+ const ArgList &Args) {
+ const Arg *A = Args.getLastArg(options::OPT_falign_functions,
+ options::OPT_falign_functions_EQ,
+ options::OPT_fno_align_functions);
+ if (!A || A->getOption().matches(options::OPT_fno_align_functions))
+ return 0;
+
+ if (A->getOption().matches(options::OPT_falign_functions))
+ return 0;
+
+ unsigned Value = 0;
+ if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536)
+ TC.getDriver().Diag(diag::err_drv_invalid_int_value)
+ << A->getAsString(Args) << A->getValue();
+ return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value;
+}
+
void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs) {
llvm::Reloc::Model RelocationModel;
@@ -1000,7 +1113,7 @@ void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back("-KPIC");
}
-/// \brief Determine whether Objective-C automated reference counting is
+/// Determine whether Objective-C automated reference counting is
/// enabled.
bool tools::isObjCAutoRefCount(const ArgList &Args) {
return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
@@ -1189,3 +1302,146 @@ void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
Lksf << LksBuffer;
}
+
+/// Add HIP linker script arguments at the end of the argument list so that
+/// the fat binary is built by embedding the device images into the host. The
+/// linker script also defines a symbol required by the code generation so that
+/// the image can be retrieved at runtime. This should be used only in tool
+/// chains that support linker scripts.
+void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
+ const InputInfo &Output,
+ const InputInfoList &Inputs, const ArgList &Args,
+ ArgStringList &CmdArgs, const JobAction &JA,
+ const Tool &T) {
+
+ // If this is not a HIP host toolchain, we don't need to do anything.
+ if (!JA.isHostOffloading(Action::OFK_HIP))
+ 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 HIP offload tool chain.
+ auto *HIPTC = static_cast<const toolchains::CudaToolChain *>(
+ C.getSingleOffloadToolChain<Action::OFK_HIP>());
+ assert(HIPTC->getTriple().getArch() == llvm::Triple::amdgcn &&
+ "Wrong platform");
+ (void)HIPTC;
+
+ // Construct clang-offload-bundler command to bundle object files for
+ // for different GPU archs.
+ ArgStringList BundlerArgs;
+ BundlerArgs.push_back(Args.MakeArgString("-type=o"));
+
+ // ToDo: Remove the dummy host binary entry which is required by
+ // clang-offload-bundler.
+ std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
+ std::string BundlerInputArg = "-inputs=/dev/null";
+
+ for (const auto &II : Inputs) {
+ const Action *A = II.getAction();
+ // Is this a device linking action?
+ if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) {
+ BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" +
+ StringRef(A->getOffloadingArch()).str();
+ BundlerInputArg = BundlerInputArg + "," + II.getFilename();
+ }
+ }
+ BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
+ BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+
+ std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "o");
+ const char *BundleFile =
+ C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str()));
+ auto BundlerOutputArg =
+ Args.MakeArgString(std::string("-outputs=").append(BundleFile));
+ BundlerArgs.push_back(BundlerOutputArg);
+
+ SmallString<128> BundlerPath(C.getDriver().Dir);
+ llvm::sys::path::append(BundlerPath, "clang-offload-bundler");
+ const char *Bundler = Args.MakeArgString(BundlerPath);
+ C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
+
+ // 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 << " HIP Offload Linker Script\n";
+ LksStream << " *** Automatically generated by Clang ***\n";
+ LksStream << "*/\n";
+ LksStream << "TARGET(binary)\n";
+ LksStream << "INPUT(" << BundleFileName << ")\n";
+ LksStream << "SECTIONS\n";
+ LksStream << "{\n";
+ LksStream << " .hip_fatbin :\n";
+ LksStream << " ALIGN(0x10)\n";
+ LksStream << " {\n";
+ LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n";
+ LksStream << " " << BundleFileName << "\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_fhip_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;
+}
+
+SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
+ const InputInfo &Output,
+ const InputInfo &Input,
+ const Driver &D) {
+ const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ);
+ if (!A)
+ return {};
+
+ StringRef SaveStats = A->getValue();
+ SmallString<128> StatsFile;
+ if (SaveStats == "obj" && Output.isFilename()) {
+ StatsFile.assign(Output.getFilename());
+ llvm::sys::path::remove_filename(StatsFile);
+ } else if (SaveStats != "cwd") {
+ D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
+ return {};
+ }
+
+ StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
+ llvm::sys::path::append(StatsFile, BaseName);
+ llvm::sys::path::replace_extension(StatsFile, "stats");
+ return StatsFile;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h
index 012f5b9f87ae..e8ebe2225e1c 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -35,6 +35,12 @@ bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
void linkSanitizerRuntimeDeps(const ToolChain &TC,
llvm::opt::ArgStringList &CmdArgs);
+bool addXRayRuntime(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
+void linkXRayRuntimeDeps(const ToolChain &TC,
+ llvm::opt::ArgStringList &CmdArgs);
+
void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
llvm::opt::ArgStringList &CmdArgs,
const llvm::opt::ArgList &Args);
@@ -46,6 +52,12 @@ void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
llvm::opt::ArgStringList &CmdArgs,
const JobAction &JA);
+void AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, const JobAction &JA,
+ const Tool &T);
+
const char *SplitDebugName(const llvm::opt::ArgList &Args,
const InputInfo &Input);
@@ -54,12 +66,15 @@ void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
const InputInfo &Output, const char *OutFile);
void AddGoldPlugin(const ToolChain &ToolChain, const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs, bool IsThinLTO,
- const Driver &D);
+ llvm::opt::ArgStringList &CmdArgs, const InputInfo &Output,
+ const InputInfo &Input, bool IsThinLTO);
std::tuple<llvm::Reloc::Model, unsigned, bool>
ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args);
+unsigned ParseFunctionAlignment(const ToolChain &TC,
+ const llvm::opt::ArgList &Args);
+
void AddAssemblerKPIC(const ToolChain &ToolChain,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
@@ -98,6 +113,11 @@ void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args,
std::vector<StringRef> &Features,
llvm::opt::OptSpecifier Group);
+/// Handles the -save-stats option and returns the filename to save statistics
+/// to.
+SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args,
+ const InputInfo &Output,
+ const InputInfo &Input, const Driver &D);
} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Contiki.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Contiki.h
index f6e15073887b..86d59ac92b16 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Contiki.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Contiki.h
@@ -23,7 +23,9 @@ public:
const llvm::opt::ArgList &Args);
// No support for finding a C++ standard library yet.
- std::string findLibCxxIncludePath() const override { return ""; }
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override {}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp
index bc4820797b2f..7fb4ae4ea9cf 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -8,18 +8,21 @@
//===----------------------------------------------------------------------===//
#include "Cuda.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
+#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
-#include "clang/Config/config.h"
#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Driver/Distro.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Distro.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
#include <system_error>
using namespace clang::driver;
@@ -52,6 +55,10 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
return CudaVersion::CUDA_80;
if (Major == 9 && Minor == 0)
return CudaVersion::CUDA_90;
+ if (Major == 9 && Minor == 1)
+ return CudaVersion::CUDA_91;
+ if (Major == 9 && Minor == 2)
+ return CudaVersion::CUDA_92;
return CudaVersion::UNKNOWN;
}
@@ -59,42 +66,75 @@ CudaInstallationDetector::CudaInstallationDetector(
const Driver &D, const llvm::Triple &HostTriple,
const llvm::opt::ArgList &Args)
: D(D) {
- SmallVector<std::string, 4> CudaPathCandidates;
+ struct Candidate {
+ std::string Path;
+ bool StrictChecking;
+
+ Candidate(std::string Path, bool StrictChecking = false)
+ : Path(Path), StrictChecking(StrictChecking) {}
+ };
+ SmallVector<Candidate, 4> Candidates;
// In decreasing order so we prefer newer versions to older versions.
std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"};
if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) {
- CudaPathCandidates.push_back(
- Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ));
+ Candidates.emplace_back(
+ Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ).str());
} else if (HostTriple.isOSWindows()) {
for (const char *Ver : Versions)
- CudaPathCandidates.push_back(
+ Candidates.emplace_back(
D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" +
Ver);
} else {
- CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda");
+ if (!Args.hasArg(clang::driver::options::OPT_cuda_path_ignore_env)) {
+ // Try to find ptxas binary. If the executable is located in a directory
+ // called 'bin/', its parent directory might be a good guess for a valid
+ // CUDA installation.
+ // However, some distributions might installs 'ptxas' to /usr/bin. In that
+ // case the candidate would be '/usr' which passes the following checks
+ // because '/usr/include' exists as well. To avoid this case, we always
+ // check for the directory potentially containing files for libdevice,
+ // even if the user passes -nocudalib.
+ if (llvm::ErrorOr<std::string> ptxas =
+ llvm::sys::findProgramByName("ptxas")) {
+ SmallString<256> ptxasAbsolutePath;
+ llvm::sys::fs::real_path(*ptxas, ptxasAbsolutePath);
+
+ StringRef ptxasDir = llvm::sys::path::parent_path(ptxasAbsolutePath);
+ if (llvm::sys::path::filename(ptxasDir) == "bin")
+ Candidates.emplace_back(llvm::sys::path::parent_path(ptxasDir),
+ /*StrictChecking=*/true);
+ }
+ }
+
+ Candidates.emplace_back(D.SysRoot + "/usr/local/cuda");
for (const char *Ver : Versions)
- CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-" + Ver);
+ Candidates.emplace_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");
+ Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda");
}
- for (const auto &CudaPath : CudaPathCandidates) {
- if (CudaPath.empty() || !D.getVFS().exists(CudaPath))
+ bool NoCudaLib = Args.hasArg(options::OPT_nocudalib);
+
+ for (const auto &Candidate : Candidates) {
+ InstallPath = Candidate.Path;
+ if (InstallPath.empty() || !D.getVFS().exists(InstallPath))
continue;
- InstallPath = CudaPath;
- BinPath = CudaPath + "/bin";
+ BinPath = InstallPath + "/bin";
IncludePath = InstallPath + "/include";
LibDevicePath = InstallPath + "/nvvm/libdevice";
auto &FS = D.getVFS();
if (!(FS.exists(IncludePath) && FS.exists(BinPath)))
continue;
+ bool CheckLibDevice = (!NoCudaLib || Candidate.StrictChecking);
+ if (CheckLibDevice && !FS.exists(LibDevicePath))
+ continue;
// On Linux, we have both lib and lib64 directories, and we need to choose
// based on our triple. On MacOS, we have only a lib directory.
@@ -119,14 +159,18 @@ CudaInstallationDetector::CudaInstallationDetector(
Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
}
- if (Version == CudaVersion::CUDA_90) {
- // CUDA-9 uses single libdevice file for all GPU variants.
+ 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;
+ for (const char *GpuArchName :
+ {"sm_30", "sm_32", "sm_35", "sm_37", "sm_50", "sm_52", "sm_53",
+ "sm_60", "sm_61", "sm_62", "sm_70", "sm_72"}) {
+ const CudaArch GpuArch = StringToCudaArch(GpuArchName);
+ if (Version >= MinVersionForCudaArch(GpuArch) &&
+ Version <= MaxVersionForCudaArch(GpuArch))
+ LibDeviceMap[GpuArchName] = FilePath;
+ }
}
} else {
std::error_code EC;
@@ -142,7 +186,7 @@ CudaInstallationDetector::CudaInstallationDetector(
StringRef GpuArch = FileName.slice(
LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
LibDeviceMap[GpuArch] = FilePath.str();
- // Insert map entries for specifc devices with this compute
+ // Insert map entries for specific 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") {
@@ -174,7 +218,7 @@ CudaInstallationDetector::CudaInstallationDetector(
// 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))
+ if (LibDeviceMap.empty() && !NoCudaLib)
continue;
IsValid = true;
@@ -231,6 +275,35 @@ void CudaInstallationDetector::print(raw_ostream &OS) const {
<< CudaVersionToString(Version) << "\n";
}
+namespace {
+ /// Debug info kind.
+enum DebugInfoKind {
+ NoDebug, /// No debug info.
+ LineTableOnly, /// Line tables only.
+ FullDebug /// Full debug info.
+};
+} // anonymous namespace
+
+static DebugInfoKind mustEmitDebugInfo(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_O_Group);
+ if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
+ options::OPT_no_cuda_noopt_device_debug,
+ !A || A->getOption().matches(options::OPT_O0))) {
+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ const Option &Opt = A->getOption();
+ if (Opt.matches(options::OPT_gN_Group)) {
+ if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0))
+ return NoDebug;
+ if (Opt.matches(options::OPT_gline_tables_only) ||
+ Opt.matches(options::OPT_ggdb1))
+ return LineTableOnly;
+ }
+ return FullDebug;
+ }
+ }
+ return NoDebug;
+}
+
void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -262,8 +335,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32");
- if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
- options::OPT_no_cuda_noopt_device_debug, false)) {
+ DebugInfoKind DIKind = mustEmitDebugInfo(Args);
+ if (DIKind == FullDebug) {
// ptxas does not accept -g option if optimization is enabled, so
// we ignore the compiler's -O* options if we want debug info.
CmdArgs.push_back("-g");
@@ -299,6 +372,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// to no optimizations, but ptxas's default is -O3.
CmdArgs.push_back("-O0");
}
+ if (DIKind == LineTableOnly)
+ CmdArgs.push_back("-lineinfo");
// Pass -v to ptxas if it was passed to the driver.
if (Args.hasArg(options::OPT_v))
@@ -314,11 +389,17 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
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))
+ bool Relocatable = false;
+ if (JA.isOffloading(Action::OFK_OpenMP))
+ // In OpenMP we need to generate relocatable code.
+ Relocatable = Args.hasFlag(options::OPT_fopenmp_relocatable_target,
+ options::OPT_fnoopenmp_relocatable_target,
+ /*Default=*/true);
+ else if (JA.isOffloading(Action::OFK_Cuda))
+ Relocatable = Args.hasFlag(options::OPT_fcuda_rdc,
+ options::OPT_fno_cuda_rdc, /*Default=*/false);
+
+ if (Relocatable)
CmdArgs.push_back("-c");
const char *Exec;
@@ -329,6 +410,22 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) {
+ bool includePTX = true;
+ for (Arg *A : Args) {
+ if (!(A->getOption().matches(options::OPT_cuda_include_ptx_EQ) ||
+ A->getOption().matches(options::OPT_no_cuda_include_ptx_EQ)))
+ continue;
+ A->claim();
+ const StringRef ArchStr = A->getValue();
+ if (ArchStr == "all" || ArchStr == gpu_arch) {
+ includePTX = A->getOption().matches(options::OPT_cuda_include_ptx_EQ);
+ continue;
+ }
+ }
+ return includePTX;
+}
+
// All inputs to this linker must be from CudaDeviceActions, as we need to look
// at the Inputs' Actions in order to figure out which GPU architecture they
// correspond to.
@@ -346,6 +443,8 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32");
CmdArgs.push_back(Args.MakeArgString("--create"));
CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));
+ if (mustEmitDebugInfo(Args) == FullDebug)
+ CmdArgs.push_back("-g");
for (const auto& II : Inputs) {
auto *A = II.getAction();
@@ -356,6 +455,9 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
"Device action expected to have associated a GPU architecture!");
CudaArch gpu_arch = StringToCudaArch(gpu_arch_str);
+ if (II.getType() == types::TY_PP_Asm &&
+ !shouldIncludePTX(Args, gpu_arch_str))
+ continue;
// We need to pass an Arch of the form "sm_XX" for cubin files and
// "compute_XX" for ptx.
const char *Arch =
@@ -394,7 +496,7 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Output.getFilename());
} else
assert(Output.isNothing() && "Invalid output.");
- if (Args.hasArg(options::OPT_g_Flag))
+ if (mustEmitDebugInfo(Args) == FullDebug)
CmdArgs.push_back("-g");
if (Args.hasArg(options::OPT_v))
@@ -499,6 +601,10 @@ 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.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
+ false))
+ CC1Args.push_back("-fcuda-rdc");
}
if (DriverArgs.hasArg(options::OPT_nocudalib))
@@ -518,17 +624,71 @@ void CudaToolChain::addClangTargetOptions(
CC1Args.push_back("-mlink-cuda-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
- 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");
+ // Libdevice in CUDA-7.0 requires PTX version that's more recent than LLVM
+ // defaults to. Use PTX4.2 by default, which is the PTX version that came with
+ // CUDA-7.0.
+ const char *PtxFeature = "+ptx42";
+ if (CudaInstallation.version() >= CudaVersion::CUDA_91) {
+ // CUDA-9.1 uses new instructions that are only available in PTX6.1+
+ PtxFeature = "+ptx61";
+ } else if (CudaInstallation.version() >= CudaVersion::CUDA_90) {
+ // CUDA-9.0 uses new instructions that are only available in PTX6.0+
+ PtxFeature = "+ptx60";
}
+ CC1Args.append({"-target-feature", PtxFeature});
+ if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
+ options::OPT_fno_cuda_short_ptr, false))
+ CC1Args.append({"-mllvm", "--nvptx-short-ptr"});
+
+ if (DeviceOffloadingKind == Action::OFK_OpenMP) {
+ SmallVector<StringRef, 8> LibraryPaths;
+ // Add path to lib and/or lib64 folders.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath,
+ Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
+ // Add user defined library paths from LIBRARY_PATH.
+ llvm::Optional<std::string> LibPath =
+ llvm::sys::Process::GetEnv("LIBRARY_PATH");
+ if (LibPath) {
+ SmallVector<StringRef, 8> Frags;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
+ for (StringRef Path : Frags)
+ LibraryPaths.emplace_back(Path.trim());
+ }
+
+ std::string LibOmpTargetName =
+ "libomptarget-nvptx-" + GpuArch.str() + ".bc";
+ bool FoundBCLibrary = false;
+ for (StringRef LibraryPath : LibraryPaths) {
+ SmallString<128> LibOmpTargetFile(LibraryPath);
+ llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
+ if (llvm::sys::fs::exists(LibOmpTargetFile)) {
+ CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
+ FoundBCLibrary = true;
+ break;
+ }
+ }
+ if (!FoundBCLibrary)
+ getDriver().Diag(diag::warn_drv_omp_offload_target_missingbcruntime)
+ << LibOmpTargetName;
+ }
+}
+
+bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
+ const Option &O = A->getOption();
+ return (O.matches(options::OPT_gN_Group) &&
+ !O.matches(options::OPT_gmodules)) ||
+ O.matches(options::OPT_g_Flag) ||
+ O.matches(options::OPT_ggdbN_Group) || O.matches(options::OPT_ggdb) ||
+ O.matches(options::OPT_gdwarf) || O.matches(options::OPT_gdwarf_2) ||
+ O.matches(options::OPT_gdwarf_3) || O.matches(options::OPT_gdwarf_4) ||
+ O.matches(options::OPT_gdwarf_5) ||
+ O.matches(options::OPT_gcolumn_info);
}
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h
index 3d08cec1643e..01580cb66920 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h
@@ -11,14 +11,14 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CUDA_H
#include "clang/Basic/Cuda.h"
-#include "clang/Basic/VersionTuple.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
-#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/VersionTuple.h"
#include <set>
#include <vector>
@@ -49,30 +49,30 @@ public:
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
- /// \brief Emit an error if Version does not support the given Arch.
+ /// Emit an error if Version does not support the given Arch.
///
/// If either Version or Arch is unknown, does not emit an error. Emits at
/// most one error per Arch.
void CheckCudaVersionSupportsArch(CudaArch Arch) const;
- /// \brief Check whether we detected a valid Cuda install.
+ /// Check whether we detected a valid Cuda install.
bool isValid() const { return IsValid; }
- /// \brief Print information about the detected CUDA installation.
+ /// Print information about the detected CUDA installation.
void print(raw_ostream &OS) const;
- /// \brief Get the detected Cuda install's version.
+ /// Get the detected Cuda install's version.
CudaVersion version() const { return Version; }
- /// \brief Get the detected Cuda installation path.
+ /// Get the detected Cuda installation path.
StringRef getInstallPath() const { return InstallPath; }
- /// \brief Get the detected path to Cuda's bin directory.
+ /// Get the detected path to Cuda's bin directory.
StringRef getBinPath() const { return BinPath; }
- /// \brief Get the detected Cuda Include path.
+ /// Get the detected Cuda Include path.
StringRef getIncludePath() const { return IncludePath; }
- /// \brief Get the detected Cuda library path.
+ /// Get the detected Cuda library path.
StringRef getLibPath() const { return LibPath; }
- /// \brief Get the detected Cuda device library path.
+ /// Get the detected Cuda device library path.
StringRef getLibDevicePath() const { return LibDevicePath; }
- /// \brief Get libdevice file for given architecture
+ /// Get libdevice file for given architecture
std::string getLibDeviceFile(StringRef Gpu) const {
return LibDeviceMap.lookup(Gpu);
}
@@ -115,7 +115,7 @@ class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
public:
OpenMPLinker(const ToolChain &TC)
- : Tool("NVPTX::OpenMPLinker", "fatbinary", TC, RF_Full, llvm::sys::WEM_UTF8,
+ : Tool("NVPTX::OpenMPLinker", "nvlink", TC, RF_Full, llvm::sys::WEM_UTF8,
"--options-file") {}
bool hasIntegratedCPP() const override { return false; }
@@ -158,6 +158,7 @@ public:
bool isPIEDefault() const override { return false; }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
+ bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
bool IsMathErrnoDefault() const override { return false; }
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -180,6 +181,8 @@ public:
computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const override;
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
+
const ToolChain &HostTC;
CudaInstallationDetector CudaInstallation;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp
index 802b89b07002..dc540688d2b1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -175,7 +175,7 @@ bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
return false;
}
-/// \brief Pass -no_deduplicate to ld64 under certain conditions:
+/// Pass -no_deduplicate to ld64 under certain conditions:
///
/// - Either -O0 or -O1 is explicitly specified
/// - No -O option is specified *and* this is a compile+link (implicit -O0)
@@ -409,7 +409,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
Args.AddLastArg(CmdArgs, options::OPT_Mach);
}
-/// \brief Determine whether we are linking the ObjC runtime.
+/// Determine whether we are linking the ObjC runtime.
static bool isObjCRuntimeLinked(const ArgList &Args) {
if (isObjCAutoRefCount(Args)) {
Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
@@ -452,7 +452,8 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// we follow suite for ease of comparison.
AddLinkArgs(C, Args, CmdArgs, Inputs);
- // For LTO, pass the name of the optimization record file.
+ // For LTO, pass the name of the optimization record file and other
+ // opt-remarks flags.
if (Args.hasFlag(options::OPT_fsave_optimization_record,
options::OPT_fno_save_optimization_record, false)) {
CmdArgs.push_back("-mllvm");
@@ -467,6 +468,26 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (getLastProfileUseArg(Args)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-lto-pass-remarks-with-hotness");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+ CmdArgs.push_back("-mllvm");
+ std::string Opt =
+ std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+ }
+ }
+
+ // Propagate the -moutline flag to the linker in LTO.
+ if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) {
+ if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-machine-outliner");
+
+ // Outline from linkonceodr functions by default in LTO.
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-linkonceodr-outlining");
}
}
@@ -979,6 +1000,8 @@ StringRef Darwin::getOSLibraryNameSuffix() const {
/// 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_exported__symbols__list))
+ return true;
if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
!A->getOption().matches(options::OPT_Xlinker))
continue;
@@ -1008,7 +1031,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
// 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");
@@ -1186,6 +1208,11 @@ struct DarwinPlatform {
DarwinEnvironmentKind getEnvironment() const { return Environment; }
+ void setEnvironment(DarwinEnvironmentKind Kind) {
+ Environment = Kind;
+ InferSimulatorFromArch = false;
+ }
+
StringRef getOSVersion() const {
if (Kind == OSVersionArg)
return Argument->getValue();
@@ -1202,6 +1229,9 @@ struct DarwinPlatform {
/// Returns true if the target OS was explicitly specified.
bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
+ /// Returns true if the simulator environment can be inferred from the arch.
+ bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
+
/// Adds the -m<os>-version-min argument to the compiler invocation.
void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
if (Argument)
@@ -1271,8 +1301,13 @@ struct DarwinPlatform {
return Result;
}
static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
- StringRef Value) {
- return DarwinPlatform(InferredFromSDK, Platform, Value);
+ StringRef Value,
+ bool IsSimulator = false) {
+ DarwinPlatform Result(InferredFromSDK, Platform, Value);
+ if (IsSimulator)
+ Result.Environment = DarwinEnvironmentKind::Simulator;
+ Result.InferSimulatorFromArch = false;
+ return Result;
}
static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
StringRef Value) {
@@ -1306,7 +1341,7 @@ private:
DarwinPlatformKind Platform;
DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
std::string OSVersion;
- bool HasOSVersion = true;
+ bool HasOSVersion = true, InferSimulatorFromArch = true;
Arg *Argument;
StringRef EnvVarName;
};
@@ -1428,14 +1463,20 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
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);
+ return DarwinPlatform::createFromSDK(
+ Darwin::IPhoneOS, Version,
+ /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
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);
+ return DarwinPlatform::createFromSDK(
+ Darwin::WatchOS, Version,
+ /*IsSimulator=*/SDK.startswith("WatchSimulator"));
else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
- return DarwinPlatform::createFromSDK(Darwin::TvOS, Version);
+ return DarwinPlatform::createFromSDK(
+ Darwin::TvOS, Version,
+ /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
}
return None;
}
@@ -1443,10 +1484,16 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
const Driver &TheDriver) {
unsigned Major, Minor, Micro;
+ llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
switch (OS) {
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
- if (!Triple.getMacOSXVersion(Major, Minor, Micro))
+ // If there is no version specified on triple, and both host and target are
+ // macos, use the host triple to infer OS version.
+ if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
+ !Triple.getOSMajorVersion())
+ SystemTriple.getMacOSXVersion(Major, Minor, Micro);
+ else if (!Triple.getMacOSXVersion(Major, Minor, Micro))
TheDriver.Diag(diag::err_drv_invalid_darwin_version)
<< Triple.getOSName();
break;
@@ -1569,9 +1616,16 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
// If no deployment target was specified on the command line, check for
// environment defines.
- if (!OSTarget)
+ if (!OSTarget) {
OSTarget =
getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
+ if (OSTarget) {
+ // Don't infer simulator from the arch when the SDK is also specified.
+ Optional<DarwinPlatform> SDKTarget = inferDeploymentTargetFromSDK(Args);
+ if (SDKTarget)
+ OSTarget->setEnvironment(SDKTarget->getEnvironment());
+ }
+ }
// 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.
@@ -1636,6 +1690,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
// Recognize iOS targets with an x86 architecture as the iOS simulator.
if (Environment == NativeEnvironment && Platform != MacOS &&
+ OSTarget->canInferSimulatorFromArch() &&
(getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64))
Environment = Simulator;
@@ -1980,7 +2035,11 @@ bool Darwin::isAlignedAllocationUnavailable() const {
void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
- if (isAlignedAllocationUnavailable())
+ // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
+ // enabled or disabled aligned allocations.
+ if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
+ options::OPT_fno_aligned_allocation) &&
+ isAlignedAllocationUnavailable())
CC1Args.push_back("-faligned-alloc-unavailable");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp
index dd0334b9c28b..c16eabf06961 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -57,11 +57,10 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
- if (getToolChain().getArch() == llvm::Triple::mips ||
- getToolChain().getArch() == llvm::Triple::mips64)
- CmdArgs.push_back("-EB");
- else
+ if (getToolChain().getTriple().isLittleEndian())
CmdArgs.push_back("-EL");
+ else
+ CmdArgs.push_back("-EB");
if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
@@ -166,23 +165,45 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--enable-new-dtags");
}
- // When building 32-bit code on FreeBSD/amd64, we have to explicitly
- // instruct ld in the base system to link 32-bit code.
- if (Arch == llvm::Triple::x86) {
+ // Explicitly set the linker emulation for platforms that might not
+ // be the default emulation for the linker.
+ switch (Arch) {
+ case llvm::Triple::x86:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386_fbsd");
- }
-
- if (Arch == llvm::Triple::ppc) {
+ break;
+ case llvm::Triple::ppc:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ppc_fbsd");
+ break;
+ case llvm::Triple::mips:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32btsmip_fbsd");
+ break;
+ case llvm::Triple::mipsel:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32ltsmip_fbsd");
+ break;
+ case llvm::Triple::mips64:
+ CmdArgs.push_back("-m");
+ if (tools::mips::hasMipsAbiArg(Args, "n32"))
+ CmdArgs.push_back("elf32btsmipn32_fbsd");
+ else
+ CmdArgs.push_back("elf64btsmip_fbsd");
+ break;
+ case llvm::Triple::mips64el:
+ CmdArgs.push_back("-m");
+ if (tools::mips::hasMipsAbiArg(Args, "n32"))
+ CmdArgs.push_back("elf32ltsmipn32_fbsd");
+ else
+ CmdArgs.push_back("elf64ltsmip_fbsd");
+ break;
+ default:
+ break;
}
if (Arg *A = Args.getLastArg(options::OPT_G)) {
- if (ToolChain.getArch() == llvm::Triple::mips ||
- ToolChain.getArch() == llvm::Triple::mipsel ||
- ToolChain.getArch() == llvm::Triple::mips64 ||
- ToolChain.getArch() == llvm::Triple::mips64el) {
+ if (ToolChain.getTriple().isMIPS()) {
StringRef v = A->getValue();
CmdArgs.push_back(Args.MakeArgString("-G" + v));
A->claim();
@@ -231,10 +252,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
+ }
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -249,6 +274,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ if (NeedsXRayDeps)
+ linkXRayRuntimeDeps(ToolChain, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
if (Args.hasArg(options::OPT_pg))
@@ -316,7 +343,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
// When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
// back to '/usr/lib' if it doesn't exist.
- if ((Triple.getArch() == llvm::Triple::x86 ||
+ if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() ||
Triple.getArch() == llvm::Triple::ppc) &&
D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
@@ -381,8 +408,7 @@ bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
SanitizerMask FreeBSD::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
- const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
- getTriple().getArch() == llvm::Triple::mips64el;
+ const bool IsMIPS64 = getTriple().isMIPS64();
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::Vptr;
@@ -391,7 +417,12 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::Thread;
}
if (IsX86 || IsX86_64) {
+ Res |= SanitizerKind::Function;
Res |= SanitizerKind::SafeStack;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
}
+ if (IsX86_64)
+ Res |= SanitizerKind::Memory;
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 269d34d18f1e..54c34ff159b1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -100,17 +100,31 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
+ }
+
addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-Bdynamic");
if (D.CCCIsCXX()) {
- if (ToolChain.ShouldLinkCXXStdlib(Args))
+ 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");
}
@@ -131,21 +145,6 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
/// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly.
-static std::string normalizeTriple(llvm::Triple Triple) {
- SmallString<64> T;
- T += Triple.getArchName();
- T += "-";
- T += Triple.getOSName();
- return T.str();
-}
-
-static std::string getTargetDir(const Driver &D,
- llvm::Triple Triple) {
- SmallString<128> P(llvm::sys::path::parent_path(D.Dir));
- llvm::sys::path::append(P, "lib", normalizeTriple(Triple));
- return P.str();
-}
-
Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
@@ -153,10 +152,6 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
if (getDriver().getInstalledDir() != D.Dir)
getProgramPaths().push_back(D.Dir);
- SmallString<128> P(getTargetDir(D, getTriple()));
- llvm::sys::path::append(P, "lib");
- getFilePaths().push_back(P.str());
-
if (!D.SysRoot.empty()) {
SmallString<128> P(D.SysRoot);
llvm::sys::path::append(P, "lib");
@@ -167,8 +162,7 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
- Triple.setTriple(normalizeTriple(Triple));
- return Triple.getTriple();
+ return (Triple.getArchName() + "-" + Triple.getOSName()).str();
}
Tool *Fuchsia::buildLinker() const {
@@ -251,7 +245,7 @@ void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx: {
- SmallString<128> P(getTargetDir(getDriver(), getTriple()));
+ SmallString<128> P(getDriver().ResourceDir);
llvm::sys::path::append(P, "include", "c++", "v1");
addSystemInclude(DriverArgs, CC1Args, P.str());
break;
@@ -267,8 +261,6 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
- CmdArgs.push_back("-lc++abi");
- CmdArgs.push_back("-lunwind");
break;
case ToolChain::CST_Libstdcxx:
@@ -278,8 +270,14 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
SanitizerMask Fuchsia::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
- Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Scudo;
return Res;
}
+
+SanitizerMask Fuchsia::getDefaultSanitizers() const {
+ return SanitizerKind::SafeStack;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h
index 6f438deca7ff..e61eddc2aad1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -60,10 +60,15 @@ public:
return llvm::DebuggerKind::GDB;
}
+ unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return 2; // SSPStrong
+ }
+
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
SanitizerMask getSupportedSanitizers() const override;
+ SanitizerMask getDefaultSanitizers() const override;
RuntimeLibType
GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp
index 544429788075..3755673250b2 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -8,13 +8,14 @@
//===----------------------------------------------------------------------===//
#include "Gnu.h"
-#include "Linux.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "CommonArgs.h"
+#include "Linux.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#include "clang/Driver/Compilation.h"
@@ -84,6 +85,13 @@ void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().matches(options::OPT_W_Group))
continue;
+ // Don't forward -mno-unaligned-access since GCC doesn't understand
+ // it and because it doesn't affect the assembly or link steps.
+ if ((isa<AssembleJobAction>(JA) || isa<LinkJobAction>(JA)) &&
+ (A->getOption().matches(options::OPT_munaligned_access) ||
+ A->getOption().matches(options::OPT_mno_unaligned_access)))
+ continue;
+
A->render(Args, CmdArgs);
}
}
@@ -220,35 +228,6 @@ void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
// The types are (hopefully) good enough.
}
-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");
- CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray", false));
- CmdArgs.push_back("-no-whole-archive");
- return true;
- }
-
- return false;
-}
-
-static void linkXRayRuntimeDeps(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- CmdArgs.push_back("--no-as-needed");
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lrt");
- CmdArgs.push_back("-lm");
-
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
- TC.getTriple().getOS() != llvm::Triple::NetBSD)
- CmdArgs.push_back("-ldl");
-}
-
static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
switch (T.getArch()) {
case llvm::Triple::x86:
@@ -271,6 +250,10 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
return "elf64ppc";
case llvm::Triple::ppc64le:
return "elf64lppc";
+ case llvm::Triple::riscv32:
+ return "elf32lriscv";
+ case llvm::Triple::riscv64:
+ return "elf64lriscv";
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
return "elf32_sparc";
@@ -300,7 +283,8 @@ 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))
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_r))
return false;
Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
@@ -373,9 +357,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &Opt : ToolChain.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
- if (!Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("--eh-frame-hdr");
- }
+ CmdArgs.push_back("--eh-frame-hdr");
if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {
CmdArgs.push_back("-m");
@@ -453,8 +435,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
+ }
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
@@ -490,7 +475,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
if (NeedsXRayDeps)
- linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
+ linkXRayRuntimeDeps(ToolChain, CmdArgs);
bool WantPthread = Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads);
@@ -550,6 +535,10 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Add OpenMP offloading linker script args if required.
AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA);
+ // Add HIP offloading linker script args if required.
+ AddHIPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA,
+ *this);
+
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -624,6 +613,18 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
break;
}
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64: {
+ StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
+ CmdArgs.push_back("-mabi");
+ CmdArgs.push_back(ABIName.data());
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ StringRef MArch = A->getValue();
+ CmdArgs.push_back("-march");
+ CmdArgs.push_back(MArch.data());
+ }
+ break;
+ }
case llvm::Triple::sparc:
case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
@@ -706,11 +707,10 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
if (ABIName != "64" && !Args.hasArg(options::OPT_mno_abicalls))
CmdArgs.push_back("-call_nonpic");
- if (getToolChain().getArch() == llvm::Triple::mips ||
- getToolChain().getArch() == llvm::Triple::mips64)
- CmdArgs.push_back("-EB");
- else
+ if (getToolChain().getTriple().isLittleEndian())
CmdArgs.push_back("-EL");
+ else
+ CmdArgs.push_back("-EB");
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
if (StringRef(A->getValue()) == "2008")
@@ -834,14 +834,6 @@ static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb;
}
-static bool isMips32(llvm::Triple::ArchType Arch) {
- return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel;
-}
-
-static bool isMips64(llvm::Triple::ArchType Arch) {
- return Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
-}
-
static bool isMipsEL(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;
}
@@ -856,6 +848,10 @@ static bool isMicroMips(const ArgList &Args) {
return A && A->getOption().matches(options::OPT_mmicromips);
}
+static bool isRISCV(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64;
+}
+
static Multilib makeMultilib(StringRef commonSuffix) {
return Multilib(commonSuffix, commonSuffix, commonSuffix);
}
@@ -1300,8 +1296,8 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
Multilib::flags_list Flags;
- addMultilibFlag(isMips32(TargetArch), "m32", Flags);
- addMultilibFlag(isMips64(TargetArch), "m64", Flags);
+ addMultilibFlag(TargetTriple.isMIPS32(), "m32", Flags);
+ addMultilibFlag(TargetTriple.isMIPS64(), "m64", Flags);
addMultilibFlag(isMips16(Args), "mips16", Flags);
addMultilibFlag(CPUName == "mips32", "march=mips32", Flags);
addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
@@ -1401,11 +1397,48 @@ static void findAndroidArmMultilibs(const Driver &D,
Result.Multilibs = AndroidArmMultilibs;
}
+static void findRISCVMultilibs(const Driver &D,
+ const llvm::Triple &TargetTriple, StringRef Path,
+ const ArgList &Args, DetectedMultilibs &Result) {
+
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+ Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32");
+ Multilib Ilp32f =
+ makeMultilib("lib32/ilp32f").flag("+m32").flag("+mabi=ilp32f");
+ Multilib Ilp32d =
+ makeMultilib("lib32/ilp32d").flag("+m32").flag("+mabi=ilp32d");
+ Multilib Lp64 = makeMultilib("lib64/lp64").flag("+m64").flag("+mabi=lp64");
+ Multilib Lp64f = makeMultilib("lib64/lp64f").flag("+m64").flag("+mabi=lp64f");
+ Multilib Lp64d = makeMultilib("lib64/lp64d").flag("+m64").flag("+mabi=lp64d");
+ MultilibSet RISCVMultilibs =
+ MultilibSet()
+ .Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
+ .FilterOut(NonExistent);
+
+ Multilib::flags_list Flags;
+ bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
+
+ addMultilibFlag(!IsRV64, "m32", Flags);
+ addMultilibFlag(IsRV64, "m64", Flags);
+ addMultilibFlag(ABIName == "ilp32", "mabi=ilp32", Flags);
+ addMultilibFlag(ABIName == "ilp32f", "mabi=ilp32f", Flags);
+ addMultilibFlag(ABIName == "ilp32d", "mabi=ilp32d", Flags);
+ addMultilibFlag(ABIName == "lp64", "mabi=lp64", Flags);
+ addMultilibFlag(ABIName == "lp64f", "mabi=lp64f", Flags);
+ addMultilibFlag(ABIName == "lp64d", "mabi=lp64d", Flags);
+
+ if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
+ Result.Multilibs = RISCVMultilibs;
+}
+
static bool findBiarchMultilibs(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef Path, const ArgList &Args,
bool NeedsBiarchSuffix,
DetectedMultilibs &Result) {
+ Multilib Default;
+
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
// libs in a subdirectory named 64. The simple logic we follow is that
@@ -1413,10 +1446,26 @@ static bool findBiarchMultilibs(const Driver &D,
// we use that. If not, and if not a biarch triple alias, we look for
// crtbegin.o without the subdirectory.
- Multilib Default;
+ StringRef Suff64 = "/64";
+ // Solaris uses platform-specific suffixes instead of /64.
+ if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+ switch (TargetTriple.getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ Suff64 = "/amd64";
+ break;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
+ Suff64 = "/sparcv9";
+ break;
+ default:
+ break;
+ }
+ }
+
Multilib Alt64 = Multilib()
- .gccSuffix("/64")
- .includeSuffix("/64")
+ .gccSuffix(Suff64)
+ .includeSuffix(Suff64)
.flag("-m32")
.flag("+m64")
.flag("-mx32");
@@ -1491,7 +1540,7 @@ static bool findBiarchMultilibs(const Driver &D,
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
-/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering.
+/// Less-than for GCCVersion, implementing a Strict Weak Ordering.
bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
int RHSPatch,
StringRef RHSPatchSuffix) const {
@@ -1525,7 +1574,7 @@ bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
return false;
}
-/// \brief Parse a GCCVersion object out of a string of text.
+/// Parse a GCCVersion object out of a string of text.
///
/// This is the primary means of forming GCCVersion objects.
/*static*/
@@ -1540,21 +1589,29 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
GoodVersion.MajorStr = First.first.str();
if (First.second.empty())
return GoodVersion;
- if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
+ StringRef MinorStr = Second.first;
+ if (Second.second.empty()) {
+ if (size_t EndNumber = MinorStr.find_first_not_of("0123456789")) {
+ GoodVersion.PatchSuffix = MinorStr.substr(EndNumber);
+ MinorStr = MinorStr.slice(0, EndNumber);
+ }
+ }
+ if (MinorStr.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
return BadVersion;
- GoodVersion.MinorStr = Second.first.str();
+ GoodVersion.MinorStr = MinorStr.str();
// First look for a number prefix and parse that if present. Otherwise just
// stash the entire patch string in the suffix, and leave the number
// unspecified. This covers versions strings such as:
// 5 (handled above)
// 4.4
+ // 4.4-patched
// 4.4.0
// 4.4.x
// 4.4.2-rc4
// 4.4.x-patched
// And retains any patch number it finds.
- StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str();
+ StringRef PatchText = Second.second;
if (!PatchText.empty()) {
if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
// Try to parse the number and any suffix.
@@ -1575,7 +1632,7 @@ static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
return GCC_INSTALL_PREFIX;
}
-/// \brief Initialize a GCCInstallationDetector from the driver.
+/// Initialize a GCCInstallationDetector from the driver.
///
/// This performs all of the autodetection and sets up the various paths.
/// Once constructed, a GCCInstallationDetector is essentially immutable.
@@ -1613,21 +1670,17 @@ void Generic_GCC::GCCInstallationDetector::init(
// If we have a SysRoot, try that first.
if (!D.SysRoot.empty()) {
Prefixes.push_back(D.SysRoot);
- Prefixes.push_back(D.SysRoot + "/usr");
+ AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
}
// Then look for gcc installed alongside clang.
Prefixes.push_back(D.InstalledDir + "/..");
- // Then look for distribution supplied gcc installations.
+ // Next, look for prefix(es) that correspond to distribution-supplied gcc
+ // installations.
if (D.SysRoot.empty()) {
- // Look for RHEL devtoolsets.
- Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
- // And finally in /usr.
- Prefixes.push_back("/usr");
+ // Typically /usr.
+ AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
}
}
@@ -1636,18 +1689,21 @@ void Generic_GCC::GCCInstallationDetector::init(
// in /usr. This avoids accidentally enforcing the system GCC version
// when using a custom toolchain.
if (GCCToolchainDir == "" || GCCToolchainDir == D.SysRoot + "/usr") {
- for (StringRef CandidateTriple : ExtraTripleAliases) {
- if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple))
- return;
- }
- for (StringRef CandidateTriple : CandidateTripleAliases) {
- if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple))
- return;
- }
- for (StringRef CandidateTriple : CandidateBiarchTripleAliases) {
- if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple, true))
- return;
- }
+ SmallVector<StringRef, 16> GentooTestTriples;
+ // Try to match an exact triple as target triple first.
+ // e.g. crossdev -S x86_64-gentoo-linux-gnu will install gcc libs for
+ // x86_64-gentoo-linux-gnu. But "clang -target x86_64-gentoo-linux-gnu"
+ // may pick the libraries for x86_64-pc-linux-gnu even when exact matching
+ // triple x86_64-gentoo-linux-gnu is present.
+ GentooTestTriples.push_back(TargetTriple.str());
+ // Check rest of triples.
+ GentooTestTriples.append(ExtraTripleAliases.begin(),
+ ExtraTripleAliases.end());
+ GentooTestTriples.append(CandidateTripleAliases.begin(),
+ CandidateTripleAliases.end());
+ if (ScanGentooConfigs(TargetTriple, Args, GentooTestTriples,
+ CandidateBiarchTripleAliases))
+ return;
}
// Loop over the various components which exist and select the best GCC
@@ -1660,6 +1716,9 @@ void Generic_GCC::GCCInstallationDetector::init(
const std::string LibDir = Prefix + Suffix.str();
if (!D.getVFS().exists(LibDir))
continue;
+ // Try to match the exact target triple first.
+ ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, TargetTriple.str());
+ // Try rest of possible triples.
for (StringRef Candidate : ExtraTripleAliases) // Try these first.
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate);
for (StringRef Candidate : CandidateTripleAliases)
@@ -1698,6 +1757,49 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
return false;
}
+void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
+ const llvm::Triple &TargetTriple, SmallVectorImpl<std::string> &Prefixes,
+ StringRef SysRoot) {
+ if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+ // Solaris is a special case.
+ // The GCC installation is under
+ // /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/
+ // so we need to find those /usr/gcc/*/lib/gcc libdirs and go with
+ // /usr/gcc/<version> as a prefix.
+
+ std::string PrefixDir = SysRoot.str() + "/usr/gcc";
+ std::error_code EC;
+ for (vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
+
+ // Filter out obviously bad entries.
+ if (CandidateVersion.Major == -1 || CandidateVersion.isOlderThan(4, 1, 1))
+ continue;
+
+ std::string CandidatePrefix = PrefixDir + "/" + VersionText.str();
+ std::string CandidateLibPath = CandidatePrefix + "/lib/gcc";
+ if (!D.getVFS().exists(CandidateLibPath))
+ continue;
+
+ Prefixes.push_back(CandidatePrefix);
+ }
+ return;
+ }
+
+ // Non-Solaris is much simpler - most systems just go with "/usr".
+ if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux) {
+ // Yet, still look for RHEL devtoolsets.
+ Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
+ }
+ Prefixes.push_back(SysRoot.str() + "/usr");
+}
+
/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,
SmallVectorImpl<StringRef> &LibDirs,
@@ -1709,22 +1811,20 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
// lifetime or initialization issues.
static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
static const char *const AArch64Triples[] = {
- "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-linux-android",
- "aarch64-redhat-linux", "aarch64-suse-linux"};
+ "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",
+ "aarch64-suse-linux"};
static const char *const AArch64beLibDirs[] = {"/lib"};
static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu"};
static const char *const ARMLibDirs[] = {"/lib"};
- static const char *const ARMTriples[] = {"arm-linux-gnueabi",
- "arm-linux-androideabi"};
+ static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
"armv7hl-redhat-linux-gnueabi",
"armv6hl-suse-linux-gnueabi",
"armv7hl-suse-linux-gnueabi"};
static const char *const ARMebLibDirs[] = {"/lib"};
- static const char *const ARMebTriples[] = {"armeb-linux-gnueabi",
- "armeb-linux-androideabi"};
+ static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};
static const char *const ARMebHFTriples[] = {
"armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
@@ -1734,16 +1834,15 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",
"x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
- "x86_64-slackware-linux", "x86_64-linux-android",
- "x86_64-unknown-linux"};
+ "x86_64-slackware-linux", "x86_64-unknown-linux",
+ "x86_64-amazon-linux"};
static const char *const X32LibDirs[] = {"/libx32"};
static const char *const X86LibDirs[] = {"/lib32", "/lib"};
static const char *const X86Triples[] = {
"i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu",
"i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
"i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
- "i486-slackware-linux", "i686-montavista-linux", "i686-linux-android",
- "i586-linux-gnu"};
+ "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu"};
static const char *const MIPSLibDirs[] = {"/lib"};
static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux",
@@ -1762,13 +1861,6 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
"mips64el-linux-gnuabi64"};
- static const char *const MIPSELAndroidLibDirs[] = {"/lib", "/libr2",
- "/libr6"};
- static const char *const MIPSELAndroidTriples[] = {"mipsel-linux-android"};
- static const char *const MIPS64ELAndroidLibDirs[] = {"/lib64", "/lib",
- "/libr2", "/libr6"};
- static const char *const MIPS64ELAndroidTriples[] = {
- "mips64el-linux-android"};
static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
static const char *const PPCTriples[] = {
@@ -1783,6 +1875,11 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu",
"powerpc64le-suse-linux", "ppc64le-redhat-linux"};
+ static const char *const RISCV32LibDirs[] = {"/lib", "/lib32"};
+ static const char *const RISCVTriples[] = {"riscv32-unknown-linux-gnu",
+ "riscv64-unknown-linux-gnu",
+ "riscv32-unknown-elf"};
+
static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
"sparcv8-linux-gnu"};
@@ -1795,17 +1892,109 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
"s390x-suse-linux", "s390x-redhat-linux"};
- // Solaris.
- static const char *const SolarisSPARCLibDirs[] = {"/gcc"};
- static const char *const SolarisSPARCTriples[] = {"sparc-sun-solaris2.11",
- "i386-pc-solaris2.11"};
using std::begin;
using std::end;
if (TargetTriple.getOS() == llvm::Triple::Solaris) {
- LibDirs.append(begin(SolarisSPARCLibDirs), end(SolarisSPARCLibDirs));
- TripleAliases.append(begin(SolarisSPARCTriples), end(SolarisSPARCTriples));
+ static const char *const SolarisLibDirs[] = {"/lib"};
+ static const char *const SolarisSparcV8Triples[] = {
+ "sparc-sun-solaris2.11", "sparc-sun-solaris2.12"};
+ static const char *const SolarisSparcV9Triples[] = {
+ "sparcv9-sun-solaris2.11", "sparcv9-sun-solaris2.12"};
+ static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11",
+ "i386-pc-solaris2.12"};
+ static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11",
+ "x86_64-pc-solaris2.12"};
+ LibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
+ BiarchLibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
+ switch (TargetTriple.getArch()) {
+ case llvm::Triple::x86:
+ TripleAliases.append(begin(SolarisX86Triples), end(SolarisX86Triples));
+ BiarchTripleAliases.append(begin(SolarisX86_64Triples),
+ end(SolarisX86_64Triples));
+ break;
+ case llvm::Triple::x86_64:
+ TripleAliases.append(begin(SolarisX86_64Triples),
+ end(SolarisX86_64Triples));
+ BiarchTripleAliases.append(begin(SolarisX86Triples),
+ end(SolarisX86Triples));
+ break;
+ case llvm::Triple::sparc:
+ TripleAliases.append(begin(SolarisSparcV8Triples),
+ end(SolarisSparcV8Triples));
+ BiarchTripleAliases.append(begin(SolarisSparcV9Triples),
+ end(SolarisSparcV9Triples));
+ break;
+ case llvm::Triple::sparcv9:
+ TripleAliases.append(begin(SolarisSparcV9Triples),
+ end(SolarisSparcV9Triples));
+ BiarchTripleAliases.append(begin(SolarisSparcV8Triples),
+ end(SolarisSparcV8Triples));
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+ // Android targets should not use GNU/Linux tools or libraries.
+ if (TargetTriple.isAndroid()) {
+ static const char *const AArch64AndroidTriples[] = {
+ "aarch64-linux-android"};
+ static const char *const ARMAndroidTriples[] = {"arm-linux-androideabi"};
+ static const char *const MIPSELAndroidTriples[] = {"mipsel-linux-android"};
+ static const char *const MIPS64ELAndroidTriples[] = {
+ "mips64el-linux-android"};
+ static const char *const X86AndroidTriples[] = {"i686-linux-android"};
+ static const char *const X86_64AndroidTriples[] = {"x86_64-linux-android"};
+
+ switch (TargetTriple.getArch()) {
+ case llvm::Triple::aarch64:
+ LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
+ TripleAliases.append(begin(AArch64AndroidTriples),
+ end(AArch64AndroidTriples));
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
+ TripleAliases.append(begin(ARMAndroidTriples), end(ARMAndroidTriples));
+ break;
+ case llvm::Triple::mipsel:
+ LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
+ TripleAliases.append(begin(MIPSELAndroidTriples),
+ end(MIPSELAndroidTriples));
+ BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
+ BiarchTripleAliases.append(begin(MIPS64ELAndroidTriples),
+ end(MIPS64ELAndroidTriples));
+ break;
+ case llvm::Triple::mips64el:
+ LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
+ TripleAliases.append(begin(MIPS64ELAndroidTriples),
+ end(MIPS64ELAndroidTriples));
+ BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
+ BiarchTripleAliases.append(begin(MIPSELAndroidTriples),
+ end(MIPSELAndroidTriples));
+ break;
+ case llvm::Triple::x86_64:
+ LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
+ TripleAliases.append(begin(X86_64AndroidTriples),
+ end(X86_64AndroidTriples));
+ BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
+ BiarchTripleAliases.append(begin(X86AndroidTriples),
+ end(X86AndroidTriples));
+ break;
+ case llvm::Triple::x86:
+ LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
+ TripleAliases.append(begin(X86AndroidTriples), end(X86AndroidTriples));
+ BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
+ BiarchTripleAliases.append(begin(X86_64AndroidTriples),
+ end(X86_64AndroidTriples));
+ break;
+ default:
+ break;
+ }
+
return;
}
@@ -1870,22 +2059,11 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
break;
case llvm::Triple::mipsel:
- if (TargetTriple.isAndroid()) {
- LibDirs.append(begin(MIPSELAndroidLibDirs), end(MIPSELAndroidLibDirs));
- TripleAliases.append(begin(MIPSELAndroidTriples),
- end(MIPSELAndroidTriples));
- BiarchLibDirs.append(begin(MIPS64ELAndroidLibDirs),
- end(MIPS64ELAndroidLibDirs));
- BiarchTripleAliases.append(begin(MIPS64ELAndroidTriples),
- end(MIPS64ELAndroidTriples));
-
- } else {
- LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
- TripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
- TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
- BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
- BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
- }
+ LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
+ TripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
+ TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
+ BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
+ BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
break;
case llvm::Triple::mips64:
LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
@@ -1894,23 +2072,11 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
break;
case llvm::Triple::mips64el:
- if (TargetTriple.isAndroid()) {
- LibDirs.append(begin(MIPS64ELAndroidLibDirs),
- end(MIPS64ELAndroidLibDirs));
- TripleAliases.append(begin(MIPS64ELAndroidTriples),
- end(MIPS64ELAndroidTriples));
- BiarchLibDirs.append(begin(MIPSELAndroidLibDirs),
- end(MIPSELAndroidLibDirs));
- BiarchTripleAliases.append(begin(MIPSELAndroidTriples),
- end(MIPSELAndroidTriples));
-
- } else {
- LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
- TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
- BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
- BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
- BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
- }
+ LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
+ TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
+ BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
+ BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
+ BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
break;
case llvm::Triple::ppc:
LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
@@ -1928,6 +2094,12 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));
TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
break;
+ case llvm::Triple::riscv32:
+ LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
+ BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
+ TripleAliases.append(begin(RISCVTriples), end(RISCVTriples));
+ BiarchTripleAliases.append(begin(RISCVTriples), end(RISCVTriples));
+ break;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
@@ -1960,56 +2132,6 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.push_back(BiarchTriple.str());
}
-void Generic_GCC::GCCInstallationDetector::scanLibDirForGCCTripleSolaris(
- const llvm::Triple &TargetArch, const llvm::opt::ArgList &Args,
- const std::string &LibDir, StringRef CandidateTriple,
- bool NeedsBiarchSuffix) {
- // Solaris is a special case. The GCC installation is under
- // /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/, so we
- // need to iterate twice.
- std::error_code EC;
- for (vfs::directory_iterator LI = D.getVFS().dir_begin(LibDir, EC), LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
- GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
-
- if (CandidateVersion.Major != -1) // Filter obviously bad entries.
- if (!CandidateGCCInstallPaths.insert(LI->getName()).second)
- continue; // Saw this path before; no need to look at it again.
- if (CandidateVersion.isOlderThan(4, 1, 1))
- continue;
- if (CandidateVersion <= Version)
- continue;
-
- GCCInstallPath =
- LibDir + "/" + VersionText.str() + "/lib/gcc/" + CandidateTriple.str();
- if (!D.getVFS().exists(GCCInstallPath))
- continue;
-
- // If we make it here there has to be at least one GCC version, let's just
- // use the latest one.
- std::error_code EEC;
- for (vfs::directory_iterator
- LLI = D.getVFS().dir_begin(GCCInstallPath, EEC),
- LLE;
- !EEC && LLI != LLE; LLI = LLI.increment(EEC)) {
-
- StringRef SubVersionText = llvm::sys::path::filename(LLI->getName());
- GCCVersion CandidateSubVersion = GCCVersion::Parse(SubVersionText);
-
- if (CandidateSubVersion > Version)
- Version = CandidateSubVersion;
- }
-
- GCCTriple.setTriple(CandidateTriple);
-
- GCCInstallPath += "/" + Version.Text;
- GCCParentLibPath = GCCInstallPath + "/../../../../";
-
- IsValid = true;
- }
-}
-
bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
const llvm::Triple &TargetTriple, const ArgList &Args,
StringRef Path, bool NeedsBiarchSuffix) {
@@ -2022,9 +2144,11 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
// It should also work without multilibs in a simplified toolchain.
findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
- } else if (tools::isMipsArch(TargetArch)) {
+ } else if (TargetTriple.isMIPS()) {
if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
return false;
+ } else if (isRISCV(TargetArch)) {
+ findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);
} else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
NeedsBiarchSuffix, Detected)) {
return false;
@@ -2041,12 +2165,6 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
bool NeedsBiarchSuffix) {
- if (TargetTriple.getOS() == llvm::Triple::Solaris) {
- scanLibDirForGCCTripleSolaris(TargetTriple, Args, LibDir, CandidateTriple,
- NeedsBiarchSuffix);
- return;
- }
-
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
// Locations relative to the system lib directory where GCC's triple-specific
// directories might reside.
@@ -2059,31 +2177,34 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// Whether this library suffix is relevant for the triple.
bool Active;
} Suffixes[] = {
- // This is the normal place.
- {"gcc/" + CandidateTriple.str(), "../..", true},
-
- // Debian puts cross-compilers in gcc-cross.
- {"gcc-cross/" + CandidateTriple.str(), "../..", true},
-
- // The Freescale PPC SDK has the gcc libraries in
- // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do
- // this on Freescale triples, though, since some systems put a *lot* of
- // files in that location, not just GCC installation data.
- {CandidateTriple.str(), "..",
- TargetTriple.getVendor() == llvm::Triple::Freescale},
-
- // Natively multiarch systems sometimes put the GCC triple-specific
- // directory within their multiarch lib directory, resulting in the
- // triple appearing twice.
- {CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), "../../..", true},
-
- // Deal with cases (on Ubuntu) where the system architecture could be i386
- // but the GCC target architecture could be (say) i686.
- // FIXME: It may be worthwhile to generalize this and look for a second
- // triple.
- {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
- TargetArch == llvm::Triple::x86}
- };
+ // This is the normal place.
+ {"gcc/" + CandidateTriple.str(), "../..", true},
+
+ // Debian puts cross-compilers in gcc-cross.
+ {"gcc-cross/" + CandidateTriple.str(), "../..",
+ TargetTriple.getOS() != llvm::Triple::Solaris},
+
+ // The Freescale PPC SDK has the gcc libraries in
+ // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do
+ // this on Freescale triples, though, since some systems put a *lot* of
+ // files in that location, not just GCC installation data.
+ {CandidateTriple.str(), "..",
+ TargetTriple.getVendor() == llvm::Triple::Freescale ||
+ TargetTriple.getVendor() == llvm::Triple::OpenEmbedded},
+
+ // Natively multiarch systems sometimes put the GCC triple-specific
+ // directory within their multiarch lib directory, resulting in the
+ // triple appearing twice.
+ {CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), "../../..",
+ TargetTriple.getOS() != llvm::Triple::Solaris},
+
+ // Deal with cases (on Ubuntu) where the system architecture could be i386
+ // but the GCC target architecture could be (say) i686.
+ // FIXME: It may be worthwhile to generalize this and look for a second
+ // triple.
+ {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
+ (TargetArch == llvm::Triple::x86 &&
+ TargetTriple.getOS() != llvm::Triple::Solaris)}};
for (auto &Suffix : Suffixes) {
if (!Suffix.Active)
@@ -2121,6 +2242,22 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
}
}
+bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
+ const llvm::Triple &TargetTriple, const ArgList &Args,
+ const SmallVectorImpl<StringRef> &CandidateTriples,
+ const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {
+ for (StringRef CandidateTriple : CandidateTriples) {
+ if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple))
+ return true;
+ }
+
+ for (StringRef CandidateTriple : CandidateBiarchTriples) {
+ if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple, true))
+ return true;
+ }
+ return false;
+}
+
bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
const llvm::Triple &TargetTriple, const ArgList &Args,
StringRef CandidateTriple, bool NeedsBiarchSuffix) {
@@ -2133,23 +2270,53 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
for (StringRef Line : Lines) {
Line = Line.trim();
// CURRENT=triple-version
- if (Line.consume_front("CURRENT=")) {
- const std::pair<StringRef, StringRef> ActiveVersion =
- Line.rsplit('-');
- // Note: Strictly speaking, we should be reading
- // /etc/env.d/gcc/${CURRENT} now. However, the file doesn't
- // contain anything new or especially useful to us.
- const std::string GentooPath = D.SysRoot + "/usr/lib/gcc/" +
- ActiveVersion.first.str() + "/" +
- ActiveVersion.second.str();
+ if (!Line.consume_front("CURRENT="))
+ continue;
+ // Process the config file pointed to by CURRENT.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =
+ D.getVFS().getBufferForFile(D.SysRoot + "/etc/env.d/gcc/" +
+ Line.str());
+ std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');
+ // List of paths to scan for libraries.
+ SmallVector<StringRef, 4> GentooScanPaths;
+ // Scan the Config file to find installed GCC libraries path.
+ // Typical content of the GCC config file:
+ // LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x:/usr/lib/gcc/
+ // (continued from previous line) x86_64-pc-linux-gnu/4.9.x/32"
+ // MANPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/man"
+ // INFOPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/info"
+ // STDCXX_INCDIR="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4"
+ // We are looking for the paths listed in LDPATH=... .
+ if (ConfigFile) {
+ SmallVector<StringRef, 2> ConfigLines;
+ ConfigFile.get()->getBuffer().split(ConfigLines, "\n");
+ for (StringRef ConfLine : ConfigLines) {
+ ConfLine = ConfLine.trim();
+ if (ConfLine.consume_front("LDPATH=")) {
+ // Drop '"' from front and back if present.
+ ConfLine.consume_back("\"");
+ ConfLine.consume_front("\"");
+ // Get all paths sperated by ':'
+ ConfLine.split(GentooScanPaths, ':', -1, /*AllowEmpty*/ false);
+ }
+ }
+ }
+ // Test the path based on the version in /etc/env.d/gcc/config-{tuple}.
+ std::string basePath = "/usr/lib/gcc/" + ActiveVersion.first.str() + "/"
+ + ActiveVersion.second.str();
+ GentooScanPaths.push_back(StringRef(basePath));
+
+ // Scan all paths for GCC libraries.
+ for (const auto &GentooScanPath : GentooScanPaths) {
+ std::string GentooPath = D.SysRoot + std::string(GentooScanPath);
if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
NeedsBiarchSuffix))
- return false;
+ continue;
Version = GCCVersion::Parse(ActiveVersion.second);
GCCInstallPath = GentooPath;
- GCCParentLibPath = GentooPath + "/../../..";
+ GCCParentLibPath = GentooPath + std::string("/../../..");
GCCTriple.setTriple(ActiveVersion.first);
IsValid = true;
return true;
@@ -2240,17 +2407,21 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
case llvm::Triple::systemz:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
return true;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
- // Enabled for Debian and Android mips64/mipsel, as they can precisely
- // identify the ABI in use (Debian) or only use N64 for MIPS64 (Android).
- // Other targets are unable to distinguish N32 from N64.
+ // Enabled for Debian, Android, FreeBSD and OpenBSD mips64/mipsel, as they
+ // can precisely identify the ABI in use (Debian) or only use N64 for MIPS64
+ // (Android). Other targets are unable to distinguish N32 from N64.
if (getTriple().getEnvironment() == llvm::Triple::GNUABI64 ||
- getTriple().isAndroid())
+ getTriple().isAndroid() ||
+ getTriple().isOSFreeBSD() ||
+ getTriple().isOSOpenBSD())
return true;
return false;
default:
@@ -2265,12 +2436,9 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
return;
switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx: {
- std::string Path = findLibCxxIncludePath();
- if (!Path.empty())
- addSystemInclude(DriverArgs, CC1Args, Path);
+ case ToolChain::CST_Libcxx:
+ addLibCxxIncludePaths(DriverArgs, CC1Args);
break;
- }
case ToolChain::CST_Libstdcxx:
addLibStdCxxIncludePaths(DriverArgs, CC1Args);
@@ -2278,9 +2446,12 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
-std::string Generic_GCC::findLibCxxIncludePath() const {
+void
+Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
// FIXME: The Linux behavior would probaby be a better approach here.
- return getDriver().SysRoot + "/usr/include/c++/v1";
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/v1");
}
void
@@ -2290,7 +2461,7 @@ Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
// FIXME: If we have a valid GCCInstallation, use it.
}
-/// \brief Helper to add the variant paths of a libstdc++ installation.
+/// Helper to add the variant paths of a libstdc++ installation.
bool Generic_GCC::addLibStdCXXIncludePaths(
Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
StringRef TargetMultiarchTriple, Twine IncludeSuffix,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.h
index f29342b95a07..e8e74e4d80fd 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.h
@@ -36,7 +36,7 @@ bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
namespace tools {
-/// \brief Base class for all GNU tools that provide the same behavior when
+/// Base class for all GNU tools that provide the same behavior when
/// it comes to response files support
class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
virtual void anchor();
@@ -139,7 +139,7 @@ namespace toolchains {
/// command line options.
class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
public:
- /// \brief Struct to store and manipulate GCC versions.
+ /// Struct to store and manipulate GCC versions.
///
/// We rely on assumptions about the form and structure of GCC version
/// numbers: they consist of at most three '.'-separated components, and each
@@ -155,16 +155,16 @@ public:
/// in the way that (for example) Debian's version format does. If that ever
/// becomes necessary, it can be added.
struct GCCVersion {
- /// \brief The unparsed text of the version.
+ /// The unparsed text of the version.
std::string Text;
- /// \brief The parsed major, minor, and patch numbers.
+ /// The parsed major, minor, and patch numbers.
int Major, Minor, Patch;
- /// \brief The text of the parsed major, and major+minor versions.
+ /// The text of the parsed major, and major+minor versions.
std::string MajorStr, MinorStr;
- /// \brief Any textual suffix on the patch number.
+ /// Any textual suffix on the patch number.
std::string PatchSuffix;
static GCCVersion Parse(StringRef VersionText);
@@ -178,7 +178,7 @@ public:
bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
};
- /// \brief This is a class to find a viable GCC installation for Clang to
+ /// This is a class to find a viable GCC installation for Clang to
/// use.
///
/// This class tries to find a GCC installation on the system, and report
@@ -213,32 +213,32 @@ public:
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
ArrayRef<std::string> ExtraTripleAliases = None);
- /// \brief Check whether we detected a valid GCC install.
+ /// Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
- /// \brief Get the GCC triple for the detected install.
+ /// Get the GCC triple for the detected install.
const llvm::Triple &getTriple() const { return GCCTriple; }
- /// \brief Get the detected GCC installation path.
+ /// Get the detected GCC installation path.
StringRef getInstallPath() const { return GCCInstallPath; }
- /// \brief Get the detected GCC parent lib path.
+ /// Get the detected GCC parent lib path.
StringRef getParentLibPath() const { return GCCParentLibPath; }
- /// \brief Get the detected Multilib
+ /// Get the detected Multilib
const Multilib &getMultilib() const { return SelectedMultilib; }
- /// \brief Get the whole MultilibSet
+ /// Get the whole MultilibSet
const MultilibSet &getMultilibs() const { return Multilibs; }
/// Get the biarch sibling multilib (if it exists).
/// \return true iff such a sibling exists
bool getBiarchSibling(Multilib &M) const;
- /// \brief Get the detected GCC version string.
+ /// Get the detected GCC version string.
const GCCVersion &getVersion() const { return Version; }
- /// \brief Print information about the detected GCC installation.
+ /// Print information about the detected GCC installation.
void print(raw_ostream &OS) const;
private:
@@ -250,6 +250,10 @@ public:
SmallVectorImpl<StringRef> &BiarchLibDirs,
SmallVectorImpl<StringRef> &BiarchTripleAliases);
+ void AddDefaultGCCPrefixes(const llvm::Triple &TargetTriple,
+ SmallVectorImpl<std::string> &Prefixes,
+ StringRef SysRoot);
+
bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
const llvm::opt::ArgList &Args,
StringRef Path,
@@ -261,11 +265,10 @@ public:
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);
- void scanLibDirForGCCTripleSolaris(const llvm::Triple &TargetArch,
- const llvm::opt::ArgList &Args,
- const std::string &LibDir,
- StringRef CandidateTriple,
- bool NeedsBiarchSuffix = false);
+ bool ScanGentooConfigs(const llvm::Triple &TargetTriple,
+ const llvm::opt::ArgList &Args,
+ const SmallVectorImpl<StringRef> &CandidateTriples,
+ const SmallVectorImpl<StringRef> &BiarchTriples);
bool ScanGentooGccConfig(const llvm::Triple &TargetTriple,
const llvm::opt::ArgList &Args,
@@ -301,19 +304,21 @@ protected:
/// \name ToolChain Implementation Helper Functions
/// @{
- /// \brief Check whether the target triple's architecture is 64-bits.
+ /// Check whether the target triple's architecture is 64-bits.
bool isTarget64Bit() const { return getTriple().isArch64Bit(); }
- /// \brief Check whether the target triple's architecture is 32-bits.
+ /// Check whether the target triple's architecture is 32-bits.
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
- // FIXME: This should be final, but the Solaris tool chain does weird
- // things we can't easily represent.
+ // FIXME: This should be final, but the CrossWindows toolchain does weird
+ // things that can't be easily generalized.
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- virtual std::string findLibCxxIncludePath() const;
+ virtual void
+ addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
virtual void
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.cpp
new file mode 100644
index 000000000000..03acf45a9b31
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.cpp
@@ -0,0 +1,350 @@
+//===--- HIP.cpp - HIP Tool and 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 "HIP.h"
+#include "CommonArgs.h"
+#include "InputInfo.h"
+#include "clang/Basic/Cuda.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+namespace {
+
+static void addBCLib(Compilation &C, const ArgList &Args,
+ ArgStringList &CmdArgs, ArgStringList LibraryPaths,
+ StringRef BCName) {
+ StringRef FullName;
+ for (std::string LibraryPath : LibraryPaths) {
+ SmallString<128> Path(LibraryPath);
+ llvm::sys::path::append(Path, BCName);
+ FullName = Path;
+ if (llvm::sys::fs::exists(FullName)) {
+ CmdArgs.push_back(Args.MakeArgString(FullName));
+ return;
+ }
+ }
+ C.getDriver().Diag(diag::err_drv_no_such_file) << BCName;
+}
+
+} // namespace
+
+const char *AMDGCN::Linker::constructLLVMLinkCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const ArgList &Args, StringRef SubArchName,
+ StringRef OutputFilePrefix) const {
+ ArgStringList CmdArgs;
+ // Add the input bc's created by compile step.
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ ArgStringList LibraryPaths;
+
+ // Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
+ for (auto Path : Args.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
+ LibraryPaths.push_back(Args.MakeArgString(Path));
+
+ addDirectoryList(Args, LibraryPaths, "-L", "HIP_DEVICE_LIB_PATH");
+
+ llvm::SmallVector<std::string, 10> BCLibs;
+
+ // Add bitcode library in --hip-device-lib.
+ for (auto Lib : Args.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
+ BCLibs.push_back(Args.MakeArgString(Lib));
+ }
+
+ // If --hip-device-lib is not set, add the default bitcode libraries.
+ if (BCLibs.empty()) {
+ // Get the bc lib file name for ISA version. For example,
+ // gfx803 => oclc_isa_version_803.amdgcn.bc.
+ std::string ISAVerBC =
+ "oclc_isa_version_" + SubArchName.drop_front(3).str() + ".amdgcn.bc";
+
+ llvm::StringRef FlushDenormalControlBC;
+ if (Args.hasArg(options::OPT_fcuda_flush_denormals_to_zero))
+ FlushDenormalControlBC = "oclc_daz_opt_on.amdgcn.bc";
+ else
+ FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc";
+
+ BCLibs.append({"opencl.amdgcn.bc",
+ "ocml.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc",
+ "oclc_finite_only_off.amdgcn.bc",
+ FlushDenormalControlBC,
+ "oclc_correctly_rounded_sqrt_on.amdgcn.bc",
+ "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC});
+ }
+ for (auto Lib : BCLibs)
+ addBCLib(C, Args, CmdArgs, LibraryPaths, Lib);
+
+ // Add an intermediate output file.
+ CmdArgs.push_back("-o");
+ std::string TmpName =
+ C.getDriver().GetTemporaryPath(OutputFilePrefix.str() + "-linked", "bc");
+ const char *OutputFileName =
+ C.addTempFile(C.getArgs().MakeArgString(TmpName));
+ CmdArgs.push_back(OutputFileName);
+ SmallString<128> ExecPath(C.getDriver().Dir);
+ llvm::sys::path::append(ExecPath, "llvm-link");
+ const char *Exec = Args.MakeArgString(ExecPath);
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ return OutputFileName;
+}
+
+const char *AMDGCN::Linker::constructOptCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
+ // Construct opt command.
+ ArgStringList OptArgs;
+ // The input to opt is the output from llvm-link.
+ OptArgs.push_back(InputFileName);
+ // Pass optimization arg to opt.
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ StringRef OOpt = "3";
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ OOpt = "3";
+ else if (A->getOption().matches(options::OPT_O0))
+ OOpt = "0";
+ else if (A->getOption().matches(options::OPT_O)) {
+ // -Os, -Oz, and -O(anything else) map to -O2
+ OOpt = llvm::StringSwitch<const char *>(A->getValue())
+ .Case("1", "1")
+ .Case("2", "2")
+ .Case("3", "3")
+ .Case("s", "2")
+ .Case("z", "2")
+ .Default("2");
+ }
+ OptArgs.push_back(Args.MakeArgString("-O" + OOpt));
+ }
+ OptArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
+ OptArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
+ OptArgs.push_back("-o");
+ std::string TmpFileName = C.getDriver().GetTemporaryPath(
+ OutputFilePrefix.str() + "-optimized", "bc");
+ const char *OutputFileName =
+ C.addTempFile(C.getArgs().MakeArgString(TmpFileName));
+ OptArgs.push_back(OutputFileName);
+ SmallString<128> OptPath(C.getDriver().Dir);
+ llvm::sys::path::append(OptPath, "opt");
+ const char *OptExec = Args.MakeArgString(OptPath);
+ C.addCommand(llvm::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs));
+ return OutputFileName;
+}
+
+const char *AMDGCN::Linker::constructLlcCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
+ // Construct llc command.
+ ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa",
+ "-filetype=obj",
+ Args.MakeArgString("-mcpu=" + SubArchName), "-o"};
+ std::string LlcOutputFileName =
+ C.getDriver().GetTemporaryPath(OutputFilePrefix, "o");
+ const char *LlcOutputFile =
+ C.addTempFile(C.getArgs().MakeArgString(LlcOutputFileName));
+ LlcArgs.push_back(LlcOutputFile);
+ SmallString<128> LlcPath(C.getDriver().Dir);
+ llvm::sys::path::append(LlcPath, "llc");
+ const char *Llc = Args.MakeArgString(LlcPath);
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs));
+ return LlcOutputFile;
+}
+
+void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args,
+ const char *InputFileName) const {
+ // Construct lld command.
+ // The output from ld.lld is an HSA code object file.
+ ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined",
+ "-shared", "-o", Output.getFilename(),
+ InputFileName};
+ SmallString<128> LldPath(C.getDriver().Dir);
+ llvm::sys::path::append(LldPath, "lld");
+ const char *Lld = Args.MakeArgString(LldPath);
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs));
+}
+
+// For amdgcn the inputs of the linker job are device bitcode and output is
+// object file. It calls llvm-link, opt, llc, then lld steps.
+void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
+ "Unsupported target");
+
+ std::string SubArchName = JA.getOffloadingArch();
+ assert(StringRef(SubArchName).startswith("gfx") && "Unsupported sub arch");
+
+ // Prefix for temporary file name.
+ std::string Prefix =
+ llvm::sys::path::stem(Inputs[0].getFilename()).str() + "-" + SubArchName;
+
+ // Each command outputs different files.
+ const char *LLVMLinkCommand =
+ constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
+ const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
+ Prefix, LLVMLinkCommand);
+ const char *LlcCommand =
+ constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
+ constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
+}
+
+HIPToolChain::HIPToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const ArgList &Args)
+ : ToolChain(D, Triple, Args), HostTC(HostTC) {
+ // Lookup binaries into the driver directory, this is used to
+ // discover the clang-offload-bundler executable.
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+void HIPToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
+
+ StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
+ assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
+ (void) GpuArch;
+ assert(DeviceOffloadingKind == Action::OFK_HIP &&
+ "Only HIP offloading kinds are supported for GPUs.");
+
+ CC1Args.push_back("-target-cpu");
+ CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch));
+ CC1Args.push_back("-fcuda-is-device");
+
+ if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
+ options::OPT_fno_cuda_flush_denormals_to_zero, false))
+ CC1Args.push_back("-fcuda-flush-denormals-to-zero");
+
+ if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
+ options::OPT_fno_cuda_approx_transcendentals, false))
+ CC1Args.push_back("-fcuda-approx-transcendentals");
+
+ if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
+ false))
+ CC1Args.push_back("-fcuda-rdc");
+}
+
+llvm::opt::DerivedArgList *
+HIPToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL =
+ HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+ if (!DAL)
+ DAL = new DerivedArgList(Args.getBaseArgs());
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ for (Arg *A : Args) {
+ if (A->getOption().matches(options::OPT_Xarch__)) {
+ // Skip this argument unless the architecture matches BoundArch.
+ if (BoundArch.empty() || A->getValue(0) != BoundArch)
+ continue;
+
+ unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
+ unsigned Prev = Index;
+ std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
+
+ // If the argument parsing failed or more than one argument was
+ // consumed, the -Xarch_ argument's parameter tried to consume
+ // extra arguments. Emit an error and ignore.
+ //
+ // We also want to disallow any options which would alter the
+ // driver behavior; that isn't going to work in our model. We
+ // use isDriverOption() as an approximation, although things
+ // like -O4 are going to slip through.
+ if (!XarchArg || Index > Prev + 1) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
+ << A->getAsString(Args);
+ continue;
+ } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
+ << A->getAsString(Args);
+ continue;
+ }
+ XarchArg->setBaseArg(A);
+ A = XarchArg.release();
+ DAL->AddSynthesizedArg(A);
+ }
+ DAL->append(A);
+ }
+
+ if (!BoundArch.empty()) {
+ DAL->eraseArg(options::OPT_march_EQ);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
+ }
+
+ return DAL;
+}
+
+Tool *HIPToolChain::buildLinker() const {
+ assert(getTriple().getArch() == llvm::Triple::amdgcn);
+ return new tools::AMDGCN::Linker(*this);
+}
+
+void HIPToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
+ HostTC.addClangWarningOptions(CC1Args);
+}
+
+ToolChain::CXXStdlibType
+HIPToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ return HostTC.GetCXXStdlibType(Args);
+}
+
+void HIPToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
+
+void HIPToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
+}
+
+void HIPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
+}
+
+SanitizerMask HIPToolChain::getSupportedSanitizers() const {
+ // The HIPToolChain only supports sanitizers in the sense that it allows
+ // sanitizer arguments on the command line if they are supported by the host
+ // toolchain. The HIPToolChain will actually ignore any command line
+ // arguments for any of these "supported" sanitizers. That means that no
+ // sanitization of device code is actually supported at this time.
+ //
+ // This behavior is necessary because the host and device toolchains
+ // invocations often share the command line, so the device toolchain must
+ // tolerate flags meant only for the host toolchain.
+ return HostTC.getSupportedSanitizers();
+}
+
+VersionTuple HIPToolChain::computeMSVCVersion(const Driver *D,
+ const ArgList &Args) const {
+ return HostTC.computeMSVCVersion(D, Args);
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.h
new file mode 100644
index 000000000000..40c9128e2f59
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/HIP.h
@@ -0,0 +1,123 @@
+//===--- HIP.h - HIP 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_HIP_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
+
+#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Tool.h"
+
+namespace clang {
+namespace driver {
+
+namespace tools {
+
+namespace AMDGCN {
+// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
+// device library, then compiles it to ISA in a shared object.
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("AMDGCN::Linker", "amdgcn-link", 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;
+
+private:
+ /// \return llvm-link output file name.
+ const char *constructLLVMLinkCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix) const;
+
+ /// \return opt output file name.
+ const char *constructOptCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix,
+ const char *InputFileName) const;
+
+ /// \return llc output file name.
+ const char *constructLlcCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix,
+ const char *InputFileName) const;
+
+ void constructLldCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs, const InputInfo &Output,
+ const llvm::opt::ArgList &Args,
+ const char *InputFileName) const;
+};
+
+} // end namespace AMDGCN
+} // end namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY HIPToolChain : public ToolChain {
+public:
+ HIPToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args);
+
+ const llvm::Triple *getAuxTriple() const override {
+ return &HostTC.getTriple();
+ }
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
+ bool useIntegratedAs() const override { return true; }
+ bool isCrossCompiling() const override { return true; }
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault() const override { return false; }
+ bool isPICDefaultForced() const override { return false; }
+ bool SupportsProfiling() const override { return false; }
+ bool IsMathErrnoDefault() const override { return false; }
+
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+ VersionTuple
+ computeMSVCVersion(const Driver *D,
+ const llvm::opt::ArgList &Args) const override;
+
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
+
+ const ToolChain &HostTC;
+
+protected:
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.cpp
index 284d269a0c1b..12461ec9c4bd 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -22,8 +22,10 @@ Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
}
-std::string Haiku::findLibCxxIncludePath() const {
- return getDriver().SysRoot + "/system/develop/headers/c++/v1";
+void Haiku::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/system/develop/headers/c++/v1");
}
void Haiku::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.h
index 8b5b48e59023..a12a48e00976 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Haiku.h
@@ -27,7 +27,9 @@ public:
return getTriple().getArch() == llvm::Triple::x86_64;
}
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
index 31281737c7a1..c2b27b6d9ac6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -11,7 +11,6 @@
#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -37,12 +36,6 @@ static StringRef getDefaultHvxLength(StringRef Cpu) {
}
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();
@@ -63,14 +56,13 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
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)) {
+ // Handle -mhvx, -mhvx=, -mno-hvx.
+ if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx,
+ options::OPT_mhexagon_hvx,
+ options::OPT_mhexagon_hvx_EQ)) {
+ if (A->getOption().matches(options::OPT_mno_hexagon_hvx))
return;
- } else if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
+ if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
HasHVX = true;
HVXFeature = Cpu = A->getValue();
HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower());
@@ -81,16 +73,13 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
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)) {
+ // Handle -mhvx-length=.
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
// 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)
@@ -118,8 +107,11 @@ void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
- bool HasHVX(false);
+ bool HasHVX = false;
handleHVXTargetFeatures(D, Args, Features, HasHVX);
+
+ if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
+ D.Diag(diag::warn_drv_vectorize_needs_hvx);
}
// Hexagon tools start.
@@ -521,11 +513,19 @@ unsigned HexagonToolChain::getOptimizationLevel(
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- if (DriverArgs.hasArg(options::OPT_ffp_contract))
- return;
- unsigned OptLevel = getOptimizationLevel(DriverArgs);
- if (OptLevel >= 3)
- CC1Args.push_back("-ffp-contract=fast");
+ if (!DriverArgs.hasArg(options::OPT_ffp_contract)) {
+ unsigned OptLevel = getOptimizationLevel(DriverArgs);
+ if (OptLevel >= 3)
+ CC1Args.push_back("-ffp-contract=fast");
+ }
+ if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+reserved-r19");
+ }
+ if (isAutoHVXEnabled(DriverArgs)) {
+ CC1Args.push_back("-mllvm");
+ CC1Args.push_back("-hexagon-autohvx");
+ }
}
void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -563,6 +563,13 @@ HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
return ToolChain::CST_Libstdcxx;
}
+bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
+ options::OPT_fno_vectorize))
+ return A->getOption().matches(options::OPT_fvectorize);
+ return false;
+}
+
//
// Returns the default CPU for Hexagon. This is the default compilation target
// if no Hexagon processor is selected at the command-line.
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h
index 229a08c76dfb..e43b8a5b8800 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h
@@ -94,6 +94,7 @@ public:
void getHexagonLibraryPaths(const llvm::opt::ArgList &Args,
ToolChain::path_list &LibPaths) const;
+ static bool isAutoHVXEnabled(const llvm::opt::ArgList &Args);
static const StringRef GetDefaultCPU();
static const StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Lanai.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Lanai.h
index 4ce658dc7775..bb92bfaea7e2 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Lanai.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Lanai.h
@@ -24,7 +24,9 @@ public:
: Generic_ELF(D, Triple, Args) {}
// No support for finding a C++ standard library yet.
- std::string findLibCxxIncludePath() const override { return ""; }
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override {}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp
index 1301cdf114ae..f8f36239180c 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp
@@ -11,6 +11,7 @@
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "CommonArgs.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
@@ -21,6 +22,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/ScopedPrinter.h"
#include <system_error>
using namespace clang::driver;
@@ -30,7 +32,7 @@ using namespace llvm::opt;
using tools::addPathIfExists;
-/// \brief Get our best guess at the multiarch triple for a target.
+/// Get our best guess at the multiarch triple for a target.
///
/// Debian-based systems are starting to use a multiarch setup where they use
/// a target-triple directory in the library and header search paths.
@@ -41,6 +43,7 @@ static std::string getMultiarchTriple(const Driver &D,
StringRef SysRoot) {
llvm::Triple::EnvironmentType TargetEnvironment =
TargetTriple.getEnvironment();
+ bool IsAndroid = TargetTriple.isAndroid();
// For most architectures, just use whatever we have rather than trying to be
// clever.
@@ -54,7 +57,9 @@ static std::string getMultiarchTriple(const Driver &D,
// regardless of what the actual target triple is.
case llvm::Triple::arm:
case llvm::Triple::thumb:
- if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
+ if (IsAndroid) {
+ return "arm-linux-androideabi";
+ } else if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabihf"))
return "arm-linux-gnueabihf";
} else {
@@ -73,16 +78,22 @@ static std::string getMultiarchTriple(const Driver &D,
}
break;
case llvm::Triple::x86:
+ if (IsAndroid)
+ return "i686-linux-android";
if (D.getVFS().exists(SysRoot + "/lib/i386-linux-gnu"))
return "i386-linux-gnu";
break;
case llvm::Triple::x86_64:
+ if (IsAndroid)
+ return "x86_64-linux-android";
// We don't want this for x32, otherwise it will match x86_64 libs
if (TargetEnvironment != llvm::Triple::GNUX32 &&
D.getVFS().exists(SysRoot + "/lib/x86_64-linux-gnu"))
return "x86_64-linux-gnu";
break;
case llvm::Triple::aarch64:
+ if (IsAndroid)
+ return "aarch64-linux-android";
if (D.getVFS().exists(SysRoot + "/lib/aarch64-linux-gnu"))
return "aarch64-linux-gnu";
break;
@@ -95,6 +106,8 @@ static std::string getMultiarchTriple(const Driver &D,
return "mips-linux-gnu";
break;
case llvm::Triple::mipsel:
+ if (IsAndroid)
+ return "mipsel-linux-android";
if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu"))
return "mipsel-linux-gnu";
break;
@@ -105,6 +118,8 @@ static std::string getMultiarchTriple(const Driver &D,
return "mips64-linux-gnuabi64";
break;
case llvm::Triple::mips64el:
+ if (IsAndroid)
+ return "mips64el-linux-android";
if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
return "mips64el-linux-gnu";
if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
@@ -141,7 +156,7 @@ static std::string getMultiarchTriple(const Driver &D,
}
static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
- if (tools::isMipsArch(Triple.getArch())) {
+ if (Triple.isMIPS()) {
if (Triple.isAndroid()) {
StringRef CPUName;
StringRef ABIName;
@@ -176,6 +191,9 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Triple.getEnvironment() == llvm::Triple::GNUX32)
return "libx32";
+ if (Triple.getArch() == llvm::Triple::riscv32)
+ return "lib32";
+
return Triple.isArch32Bit() ? "lib" : "lib64";
}
@@ -220,12 +238,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
ExtraOpts.push_back("relro");
}
+ if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") !=
+ StringRef::npos)
+ // With devtoolset on RHEL, we want to add a bin directory that is relative
+ // to the detected gcc install, because if we are using devtoolset gcc then
+ // we want to use other tools from devtoolset (e.g. ld) instead of the
+ // standard system tools.
+ PPaths.push_back(Twine(GCCInstallation.getParentLibPath() +
+ "/../bin").str());
+
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
ExtraOpts.push_back("-X");
const bool IsAndroid = Triple.isAndroid();
- const bool IsMips = tools::isMipsArch(Arch);
+ const bool IsMips = Triple.isMIPS();
const bool IsHexagon = Arch == llvm::Triple::hexagon;
+ const bool IsRISCV =
+ Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64;
if (IsMips && !SysRoot.empty())
ExtraOpts.push_back("--sysroot=" + SysRoot);
@@ -331,8 +360,35 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+
+ if (IsAndroid) {
+ // Android sysroots contain a library directory for each supported OS
+ // version as well as some unversioned libraries in the usual multiarch
+ // directory.
+ unsigned Major;
+ unsigned Minor;
+ unsigned Micro;
+ Triple.getEnvironmentVersion(Major, Minor, Micro);
+ addPathIfExists(D,
+ SysRoot + "/usr/lib/" + MultiarchTriple + "/" +
+ llvm::to_string(Major),
+ Paths);
+ }
+
addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
- addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+ // 64-bit OpenEmbedded sysroots may not have a /usr/lib dir. So they cannot
+ // find /usr/lib64 as it is referenced as /usr/lib/../lib64. So we handle
+ // this here.
+ if (Triple.getVendor() == llvm::Triple::OpenEmbedded &&
+ Triple.isArch64Bit())
+ addPathIfExists(D, SysRoot + "/usr/" + OSLibDir, Paths);
+ else
+ addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+ if (IsRISCV) {
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
+ addPathIfExists(D, SysRoot + "/" + OSLibDir + "/" + ABIName, Paths);
+ addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
+ }
// Try walking via the GCC triple path in case of biarch or multiarch GCC
// installations with strange symlinks.
@@ -389,7 +445,16 @@ std::string Linux::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;
- if (!GCCInstallation.isValid() || !tools::isMipsArch(getTriple().getArch()))
+ if (getTriple().isAndroid()) {
+ // Android toolchains typically include a sysroot at ../sysroot relative to
+ // the clang binary.
+ const StringRef ClangDir = getDriver().getInstalledDir();
+ std::string AndroidSysRootPath = (ClangDir + "/../sysroot").str();
+ if (getVFS().exists(AndroidSysRootPath))
+ return AndroidSysRootPath;
+ }
+
+ if (!GCCInstallation.isValid() || !getTriple().isMIPS())
return std::string();
// Standalone MIPS toolchains use different names for sysroot folder
@@ -481,8 +546,6 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el: {
- bool LE = (Triple.getArch() == llvm::Triple::mipsel) ||
- (Triple.getArch() == llvm::Triple::mips64el);
bool IsNaN2008 = tools::mips::isNaN2008(Args, Triple);
LibDir = "lib" + tools::mips::getMipsABILibSuffix(Args, Triple);
@@ -491,7 +554,8 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
Loader = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0";
else if (!Triple.hasEnvironment() &&
Triple.getVendor() == llvm::Triple::VendorType::MipsTechnologies)
- Loader = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1";
+ Loader =
+ Triple.isLittleEndian() ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1";
else
Loader = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
@@ -511,6 +575,18 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
Loader =
(tools::ppc::hasPPCAbiArg(Args, "elfv1")) ? "ld64.so.1" : "ld64.so.2";
break;
+ case llvm::Triple::riscv32: {
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
+ LibDir = "lib";
+ Loader = ("ld-linux-riscv32-" + ABIName + ".so.1").str();
+ break;
+ }
+ case llvm::Triple::riscv64: {
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
+ LibDir = "lib";
+ Loader = ("ld-linux-riscv64-" + ABIName + ".so.1").str();
+ break;
+ }
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
LibDir = "lib";
@@ -694,6 +770,14 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
default:
break;
}
+
+ const std::string AndroidMultiarchIncludeDir =
+ std::string("/usr/include/") +
+ getMultiarchTriple(D, getTriple(), SysRoot);
+ const StringRef AndroidMultiarchIncludeDirs[] = {AndroidMultiarchIncludeDir};
+ if (getTriple().isAndroid())
+ MultiarchIncludeDirs = AndroidMultiarchIncludeDirs;
+
for (StringRef Dir : MultiarchIncludeDirs) {
if (D.getVFS().exists(SysRoot + Dir)) {
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir);
@@ -731,21 +815,24 @@ static std::string DetectLibcxxIncludePath(StringRef base) {
return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
}
-std::string Linux::findLibCxxIncludePath() const {
+void Linux::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const std::string& SysRoot = computeSysRoot();
const std::string LibCXXIncludePathCandidates[] = {
+ DetectLibcxxIncludePath(getDriver().ResourceDir + "/include/c++"),
DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"),
// If this is a development, non-installed, clang, libcxx will
// not be found at ../include/c++ but it likely to be found at
// one of the following two locations:
- DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/local/include/c++"),
- DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/include/c++") };
+ DetectLibcxxIncludePath(SysRoot + "/usr/local/include/c++"),
+ DetectLibcxxIncludePath(SysRoot + "/usr/include/c++") };
for (const auto &IncludePath : LibCXXIncludePathCandidates) {
if (IncludePath.empty() || !getVFS().exists(IncludePath))
continue;
// Use the first candidate that exists.
- return IncludePath;
+ addSystemInclude(DriverArgs, CC1Args, IncludePath);
+ return;
}
- return "";
}
void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
@@ -823,8 +910,8 @@ bool Linux::isPIEDefault() const {
SanitizerMask Linux::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
- const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
- getTriple().getArch() == llvm::Triple::mips64el;
+ const bool IsMIPS = getTriple().isMIPS32();
+ const bool IsMIPS64 = getTriple().isMIPS64();
const bool IsPowerPC64 = getTriple().getArch() == llvm::Triple::ppc64 ||
getTriple().getArch() == llvm::Triple::ppc64le;
const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
@@ -838,6 +925,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::Memory;
Res |= SanitizerKind::Vptr;
Res |= SanitizerKind::SafeStack;
if (IsX86_64 || IsMIPS64 || IsAArch64)
@@ -846,16 +934,17 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
- if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64)
- Res |= SanitizerKind::Memory;
if (IsX86_64 || IsMIPS64)
Res |= SanitizerKind::Efficiency;
if (IsX86 || IsX86_64)
Res |= SanitizerKind::Function;
- if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
+ IsPowerPC64)
Res |= SanitizerKind::Scudo;
- if (IsAArch64)
+ if (IsX86_64 || IsAArch64) {
Res |= SanitizerKind::HWAddress;
+ Res |= SanitizerKind::KernelHWAddress;
+ }
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.h
index 9778c1832ccc..22dbbecf6b96 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.h
@@ -27,7 +27,9 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp
index ae41ee9e22cf..d062c6abc955 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -19,7 +19,6 @@
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/ConvertUTF.h"
@@ -31,13 +30,7 @@
#include "llvm/Support/Process.h"
#include <cstdio>
-// Include the necessary headers to interface with the Windows registry and
-// environment.
-#if defined(LLVM_ON_WIN32)
-#define USE_WIN32
-#endif
-
-#ifdef USE_WIN32
+#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#ifndef NOMINMAX
@@ -476,7 +469,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// their own link.exe which may come first.
linkPath = FindVisualStudioExecutable(TC, "link.exe");
-#ifdef USE_WIN32
+ if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath))
+ C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
+
+#ifdef _WIN32
// When cross-compiling with VS2017 or newer, link.exe expects to have
// its containing bin directory at the top of PATH, followed by the
// native target bin directory.
@@ -691,8 +687,6 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
}
Tool *MSVCToolChain::buildLinker() const {
- if (VCToolChainPath.empty())
- getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
return new tools::visualstudio::Linker(*this);
}
@@ -752,6 +746,8 @@ static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
return "x64";
case ArchType::arm:
return "arm";
+ case ArchType::aarch64:
+ return "arm64";
default:
return "";
}
@@ -769,6 +765,8 @@ static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
return "amd64";
case ArchType::arm:
return "arm";
+ case ArchType::aarch64:
+ return "arm64";
default:
return "";
}
@@ -784,6 +782,8 @@ static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
return "amd64";
case ArchType::arm:
return "arm";
+ case ArchType::aarch64:
+ return "arm64";
default:
return "";
}
@@ -835,7 +835,7 @@ MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
return Path.str();
}
-#ifdef USE_WIN32
+#ifdef _WIN32
static bool readFullStringValue(HKEY hkey, const char *valueName,
std::string &value) {
std::wstring WideValueName;
@@ -869,7 +869,7 @@ static bool readFullStringValue(HKEY hkey, const char *valueName,
}
#endif
-/// \brief Read registry string.
+/// Read registry string.
/// This also supports a means to look for high-versioned keys by use
/// of a $VERSION placeholder in the key path.
/// $VERSION in the key path is a placeholder for the version number,
@@ -879,7 +879,7 @@ static bool readFullStringValue(HKEY hkey, const char *valueName,
/// characters are compared. This function only searches HKLM.
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
std::string &value, std::string *phValue) {
-#ifndef USE_WIN32
+#ifndef _WIN32
return false;
#else
HKEY hRootKey = HKEY_LOCAL_MACHINE;
@@ -961,7 +961,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
}
}
return returnValue;
-#endif // USE_WIN32
+#endif // _WIN32
}
// Find the most recent version of Universal CRT or Windows 10 SDK.
@@ -992,7 +992,7 @@ static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
return !SDKVersion.empty();
}
-/// \brief Get Windows SDK installation directory.
+/// Get Windows SDK installation directory.
static bool getWindowsSDKDir(std::string &Path, int &Major,
std::string &WindowsSDKIncludeVersion,
std::string &WindowsSDKLibVersion) {
@@ -1122,7 +1122,7 @@ static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
VersionTuple Version;
-#ifdef USE_WIN32
+#ifdef _WIN32
SmallString<128> ClExe(BinDir);
llvm::sys::path::append(ClExe, "cl.exe");
@@ -1236,7 +1236,7 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
}
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
// As a fallback, select default install paths.
// FIXME: Don't guess drives and paths like this on Windows.
const StringRef Paths[] = {
@@ -1298,6 +1298,7 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
+ Res &= ~SanitizerKind::CFIMFCall;
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.h
index 854f88a36fd2..1db589ec9706 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.h
@@ -110,7 +110,7 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
bool getWindowsSDKLibraryPath(std::string &path) const;
- /// \brief Check if Universal CRT should be used if available
+ /// Check if Universal CRT should be used if available
bool getUniversalCRTLibraryPath(std::string &path) const;
bool useUniversalCRT() const;
VersionTuple
@@ -123,6 +123,8 @@ public:
void printVerboseInfo(raw_ostream &OS) const override;
+ bool FoundMSVCInstall() const { return !VCToolChainPath.empty(); }
+
protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp
index db83ac6fa7a2..a88e00f0c8e8 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -83,7 +83,7 @@ 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")
+ if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt"))
return;
CmdArgs.push_back("-lmsvcrt");
}
@@ -201,6 +201,14 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Bdynamic");
}
+ bool HasWindowsApp = false;
+ for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
+ if (Lib == "windowsapp") {
+ HasWindowsApp = true;
+ break;
+ }
+ }
+
if (!Args.hasArg(options::OPT_nostdlib)) {
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
if (Args.hasArg(options::OPT_static))
@@ -223,15 +231,19 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
- // add system libraries
- if (Args.hasArg(options::OPT_mwindows)) {
- CmdArgs.push_back("-lgdi32");
- CmdArgs.push_back("-lcomdlg32");
+ if (!HasWindowsApp) {
+ // Add system libraries. If linking to libwindowsapp.a, that import
+ // library replaces all these and we shouldn't accidentally try to
+ // link to the normal desktop mode dlls.
+ if (Args.hasArg(options::OPT_mwindows)) {
+ CmdArgs.push_back("-lgdi32");
+ CmdArgs.push_back("-lcomdlg32");
+ }
+ CmdArgs.push_back("-ladvapi32");
+ CmdArgs.push_back("-lshell32");
+ CmdArgs.push_back("-luser32");
+ CmdArgs.push_back("-lkernel32");
}
- CmdArgs.push_back("-ladvapi32");
- CmdArgs.push_back("-lshell32");
- CmdArgs.push_back("-luser32");
- CmdArgs.push_back("-lkernel32");
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--end-group");
@@ -275,7 +287,8 @@ void toolchains::MinGW::findGccLibDir() {
Archs.emplace_back(getTriple().getArchName());
Archs[0] += "-w64-mingw32";
Archs.emplace_back("mingw32");
- Arch = Archs[0].str();
+ if (Arch.empty())
+ Arch = Archs[0].str();
// lib: Arch Linux, Ubuntu, Windows
// lib64: openSUSE Linux
for (StringRef CandidateLib : {"lib", "lib64"}) {
@@ -302,6 +315,23 @@ llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
return make_error_code(std::errc::no_such_file_or_directory);
}
+llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() {
+ llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs;
+ Subdirs.emplace_back(getTriple().str());
+ Subdirs.emplace_back(getTriple().getArchName());
+ Subdirs[1] += "-w64-mingw32";
+ StringRef ClangRoot =
+ llvm::sys::path::parent_path(getDriver().getInstalledDir());
+ StringRef Sep = llvm::sys::path::get_separator();
+ for (StringRef CandidateSubdir : Subdirs) {
+ if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
+ Arch = CandidateSubdir;
+ return (ClangRoot + Sep + CandidateSubdir).str();
+ }
+ }
+ return make_error_code(std::errc::no_such_file_or_directory);
+}
+
toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
@@ -309,6 +339,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
if (getDriver().SysRoot.size())
Base = getDriver().SysRoot;
+ // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
+ // base as it could still be a base for a gcc setup with libgcc.
+ else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot())
+ Base = llvm::sys::path::parent_path(TargetSubdir.get());
else if (llvm::ErrorOr<std::string> GPPName = findGcc())
Base = llvm::sys::path::parent_path(
llvm::sys::path::parent_path(GPPName.get()));
@@ -453,11 +487,14 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
+ StringRef Slash = llvm::sys::path::get_separator();
+
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx:
+ addSystemInclude(DriverArgs, CC1Args, Base + Arch + Slash + "include" +
+ Slash + "c++" + Slash + "v1");
addSystemInclude(DriverArgs, CC1Args,
- Base + "include" + llvm::sys::path::get_separator() +
- "c++" + llvm::sys::path::get_separator() + "v1");
+ Base + "include" + Slash + "c++" + Slash + "v1");
break;
case ToolChain::CST_Libstdcxx:
@@ -472,7 +509,7 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
for (auto &CppIncludeBase : CppIncludeBases) {
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
- CppIncludeBase += llvm::sys::path::get_separator();
+ CppIncludeBase += Slash;
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h
index f8dbcae62756..0c3919d29f77 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h
@@ -96,6 +96,7 @@ private:
mutable std::unique_ptr<tools::gcc::Compiler> Compiler;
void findGccLibDir();
llvm::ErrorOr<std::string> findGcc();
+ llvm::ErrorOr<std::string> findClangRelativeSysroot();
};
} // end namespace toolchains
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.cpp
index b394208336ed..9f23996b764a 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.cpp
@@ -10,7 +10,6 @@
#include "MipsLinux.h"
#include "Arch/Mips.h"
#include "CommonArgs.h"
-#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
@@ -94,16 +93,18 @@ MipsLLVMToolChain::GetCXXStdlibType(const ArgList &Args) const {
return ToolChain::CST_Libcxx;
}
-std::string MipsLLVMToolChain::findLibCxxIncludePath() const {
+void MipsLLVMToolChain::addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
if (const auto &Callback = Multilibs.includeDirsCallback()) {
for (std::string Path : Callback(SelectedMultilib)) {
Path = getDriver().getInstalledDir() + Path + "/c++/v1";
if (llvm::sys::fs::exists(Path)) {
- return Path;
+ addSystemInclude(DriverArgs, CC1Args, Path);
+ return;
}
}
}
- return "";
}
void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.h
index fa82efbbfc8f..d4b476d883e6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MipsLinux.h
@@ -31,7 +31,9 @@ public:
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.cpp
index 06079b109dd1..2b4c1d165576 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.cpp
@@ -107,7 +107,6 @@ void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString(std::string("-i:") + A->getValue(0)));
}
- CmdArgs.push_back("-elf"); // Output format.
CmdArgs.push_back(II.getFilename());
CmdArgs.push_back(
Args.MakeArgString(std::string("-o:") + Output.getFilename()));
@@ -243,9 +242,11 @@ void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
}
-std::string MyriadToolChain::findLibCxxIncludePath() const {
+void MyriadToolChain::addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
std::string Path(getDriver().getInstalledDir());
- return Path + "/../include/c++/v1";
+ addSystemInclude(DriverArgs, CC1Args, Path + "/../include/c++/v1");
}
void MyriadToolChain::addLibStdCxxIncludePaths(
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.h
index 4c213c726219..33307c3f871a 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Myriad.h
@@ -76,7 +76,9 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp
index 128478d63871..89a18944c319 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp
@@ -309,25 +309,31 @@ void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
CmdArgs.push_back("-lc++");
}
-std::string NaClToolChain::findLibCxxIncludePath() const {
+void NaClToolChain::addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
SmallString<128> P(D.Dir + "/../");
switch (getTriple().getArch()) {
+ default:
+ break;
case llvm::Triple::arm:
llvm::sys::path::append(P, "arm-nacl/include/c++/v1");
- return P.str();
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
case llvm::Triple::x86:
llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
- return P.str();
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
case llvm::Triple::x86_64:
llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
- return P.str();
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
case llvm::Triple::mipsel:
llvm::sys::path::append(P, "mipsel-nacl/include/c++/v1");
- return P.str();
- default:
- return "";
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.h
index 31af3a53ad3c..e0885b526d70 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.h
@@ -53,7 +53,9 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp
index 0db6578f7407..02caafda1657 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -64,11 +64,10 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
- if (getToolChain().getArch() == llvm::Triple::mips ||
- getToolChain().getArch() == llvm::Triple::mips64)
- CmdArgs.push_back("-EB");
- else
+ if (getToolChain().getTriple().isLittleEndian())
CmdArgs.push_back("-EL");
+ else
+ CmdArgs.push_back("-EB");
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
@@ -112,7 +111,9 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const Driver &D = getToolChain().getDriver();
+ const toolchains::NetBSD &ToolChain =
+ static_cast<const toolchains::NetBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
if (!D.SysRoot.empty())
@@ -121,6 +122,10 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
+ if (Args.hasArg(options::OPT_pie)) {
+ Args.AddAllArgs(CmdArgs, options::OPT_pie);
+ CmdArgs.push_back("--no-dynamic-linker");
+ }
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
@@ -135,7 +140,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Many NetBSD architectures support more than one ABI.
// Determine the correct emulation for ld.
- switch (getToolChain().getArch()) {
+ switch (ToolChain.getArch()) {
case llvm::Triple::x86:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386");
@@ -143,7 +148,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::arm:
case llvm::Triple::thumb:
CmdArgs.push_back("-m");
- switch (getToolChain().getTriple().getEnvironment()) {
+ switch (ToolChain.getTriple().getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
CmdArgs.push_back("armelf_nbsd_eabi");
@@ -159,9 +164,9 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getEffectiveTriple());
+ arm::appendEBLinkFlags(Args, CmdArgs, ToolChain.getEffectiveTriple());
CmdArgs.push_back("-m");
- switch (getToolChain().getTriple().getEnvironment()) {
+ switch (ToolChain.getTriple().getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
CmdArgs.push_back("armelfb_nbsd_eabi");
@@ -179,13 +184,13 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::mips64el:
if (mips::hasMipsAbiArg(Args, "32")) {
CmdArgs.push_back("-m");
- if (getToolChain().getArch() == llvm::Triple::mips64)
+ if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("elf32btsmip");
else
CmdArgs.push_back("elf32ltsmip");
} else if (mips::hasMipsAbiArg(Args, "64")) {
CmdArgs.push_back("-m");
- if (getToolChain().getArch() == llvm::Triple::mips64)
+ if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("elf64btsmip");
else
CmdArgs.push_back("elf64ltsmip");
@@ -226,16 +231,16 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
+ Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
}
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
+ Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
} else {
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
}
}
@@ -248,13 +253,14 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_r);
bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
unsigned Major, Minor, Micro;
- getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
+ ToolChain.getTriple().getOSVersion(Major, Minor, Micro);
bool useLibgcc = true;
if (Major >= 7 || Major == 0) {
- switch (getToolChain().getArch()) {
+ switch (ToolChain.getArch()) {
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
@@ -278,12 +284,14 @@ 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()) {
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
+ if (NeedsXRayDeps)
+ linkXRayRuntimeDeps(ToolChain, CmdArgs);
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
@@ -308,16 +316,16 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
+ Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
else
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
+ Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
- getToolChain().addProfileRTLibs(Args, CmdArgs);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -406,8 +414,10 @@ ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const {
return ToolChain::CST_Libstdcxx;
}
-std::string NetBSD::findLibCxxIncludePath() const {
- return getDriver().SysRoot + "/usr/include/c++/";
+void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/");
}
void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h
index e98df72ce65c..49e3a58d02c3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h
@@ -60,7 +60,9 @@ public:
CXXStdlibType GetDefaultCXXStdlibType() const override;
- std::string findLibCxxIncludePath() const override;
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
index fbb84a62ca89..7b98cd62bbfc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -13,6 +13,7 @@
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
using namespace clang::driver;
@@ -67,10 +68,10 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
- if (getToolChain().getArch() == llvm::Triple::mips64)
- CmdArgs.push_back("-EB");
- else
+ if (getToolChain().getTriple().isLittleEndian())
CmdArgs.push_back("-EL");
+ else
+ CmdArgs.push_back("-EB");
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
@@ -97,6 +98,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const toolchains::OpenBSD &ToolChain =
+ static_cast<const toolchains::OpenBSD &>(getToolChain());
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -170,11 +173,14 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Triple.replace(0, 6, "amd64");
CmdArgs.push_back(
Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1"));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib"));
Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_e, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -186,7 +192,14 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-lm");
}
-
+ if (NeedsSanitizerDeps) {
+ CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false));
+ linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ }
+ if (NeedsXRayDeps) {
+ CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false));
+ linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ }
// FIXME: For some reason GCC passes -lgcc before adding
// the default system libraries. Just mimic this for now.
CmdArgs.push_back("-lgcc");
@@ -217,10 +230,28 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
}
- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(
+ !NeedsSanitizerDeps ? getToolChain().GetLinkerPath()
+ : getToolChain().GetProgramPath("ld.lld"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+SanitizerMask OpenBSD::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+
+ // For future use, only UBsan at the moment
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+
+ if (IsX86 || IsX86_64) {
+ Res |= SanitizerKind::Vptr;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ }
+
+ return Res;
+}
+
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
@@ -230,6 +261,14 @@ OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back("/usr/lib");
}
+void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ bool Profiling = Args.hasArg(options::OPT_pg);
+
+ CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
+ CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
+}
+
Tool *OpenBSD::buildAssembler() const {
return new tools::openbsd::Assembler(*this);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.h
index 1cc0ca71984a..bf8dfa4653cb 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -58,12 +58,16 @@ public:
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
bool isPIEDefault() const override { return true; }
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
return 2;
}
unsigned GetDefaultDwarfVersion() const override { return 2; }
+ SanitizerMask getSupportedSanitizers() const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp
index b37fe7d1f9b9..a4b74d492331 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -76,6 +76,15 @@ static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
}
}
+void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC,
+ ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ if (SanArgs.needsUbsanRt())
+ CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a");
+ if (SanArgs.needsAsanRt())
+ CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a");
+}
+
static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
const JobAction &JA, const InputInfo &Output,
const InputInfoList &Inputs,
@@ -303,7 +312,7 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
}
const char *Exec =
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld.gold"));
#else
Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.h
index e507edbad4d5..bd0a44352f4d 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -23,6 +23,8 @@ namespace PS4cpu {
void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
+void addSanitizerArgs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs);
+
class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
public:
Assemble(const ToolChain &TC)
@@ -61,7 +63,9 @@ public:
const llvm::opt::ArgList &Args);
// No support for finding a C++ standard library yet.
- std::string findLibCxxIncludePath() const override { return ""; }
+ void addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override {}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.cpp
new file mode 100644
index 000000000000..31996fc588f1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.cpp
@@ -0,0 +1,117 @@
+//===--- RISCV.cpp - RISCV 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 "RISCV.h"
+#include "CommonArgs.h"
+#include "InputInfo.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+/// RISCV Toolchain
+RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ GCCInstallation.init(Triple, Args);
+ getFilePaths().push_back(D.SysRoot + "/lib");
+ if (GCCInstallation.isValid()) {
+ getFilePaths().push_back(GCCInstallation.getInstallPath().str());
+ getProgramPaths().push_back(
+ (GCCInstallation.getParentLibPath() + "/../bin").str());
+ }
+}
+
+Tool *RISCVToolChain::buildLinker() const {
+ return new tools::RISCV::Linker(*this);
+}
+
+void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+ SmallString<128> Dir(getDriver().SysRoot);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+}
+
+void RISCVToolChain::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ const GCCVersion &Version = GCCInstallation.getVersion();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ addLibStdCXXIncludePaths(
+ LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
+ "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
+}
+
+void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ std::string Linker = getToolChain().GetProgramPath(getShortName());
+
+ bool WantCRTs =
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
+
+ if (WantCRTs) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_T_Group, options::OPT_e, options::OPT_s,
+ options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ // TODO: add C++ includes and libs if compiling C++.
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgloss");
+ CmdArgs.push_back("--end-group");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (WantCRTs)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
+ CmdArgs, Inputs));
+}
+// RISCV tools end.
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.h
new file mode 100644
index 000000000000..6f59d84020d8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/RISCV.h
@@ -0,0 +1,57 @@
+//===--- RISCV.h - RISCV 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_RISCV_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF {
+public:
+ RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsIntegratedAssemblerDefault() const override { return true; }
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+protected:
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+
+namespace tools {
+namespace RISCV {
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("RISCV::Linker", "ld", 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 RISCV
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp
index 9fe6e9d520d0..b48edbb08ee6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -71,6 +71,11 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("ld.so.1")));
}
+
+ // libpthread has been folded into libc since Solaris 10, no need to do
+ // anything for pthreads. Claim argument to avoid warning.
+ Args.ClaimAllArgs(options::OPT_pthread);
+ Args.ClaimAllArgs(options::OPT_pthreads);
}
if (Output.isFilename()) {
@@ -92,24 +97,48 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
}
+ // Provide __start___sancov_guards. Solaris ld doesn't automatically create
+ // __start_SECNAME labels.
+ CmdArgs.push_back("--whole-archive");
+ CmdArgs.push_back(
+ getToolChain().getCompilerRTArgString(Args, "sancov_begin", false));
+ CmdArgs.push_back("--no-whole-archive");
+
getToolChain().AddFilePathLibArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_e, options::OPT_r});
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (getToolChain().ShouldLinkCXXStdlib(Args))
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_fstack_protector) ||
+ Args.hasArg(options::OPT_fstack_protector_strong) ||
+ Args.hasArg(options::OPT_fstack_protector_all)) {
+ // Explicitly link ssp libraries, not folded into Solaris libc.
+ CmdArgs.push_back("-lssp_nonshared");
+ CmdArgs.push_back("-lssp");
+ }
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("-lc");
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("-lm");
}
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
}
+ // Provide __stop___sancov_guards. Solaris ld doesn't automatically create
+ // __stop_SECNAME labels.
+ CmdArgs.push_back("--whole-archive");
+ CmdArgs.push_back(
+ getToolChain().getCompilerRTArgString(Args, "sancov_end", false));
+ CmdArgs.push_back("--no-whole-archive");
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
@@ -122,6 +151,21 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::sparc:
+ break;
+ case llvm::Triple::x86_64:
+ return "/amd64";
+ case llvm::Triple::sparcv9:
+ return "/sparcv9";
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+ return "";
+}
+
/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
@@ -130,32 +174,35 @@ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
GCCInstallation.init(Triple, Args);
+ StringRef LibSuffix = getSolarisLibSuffix(Triple);
path_list &Paths = getFilePaths();
- if (GCCInstallation.isValid())
- addPathIfExists(D, GCCInstallation.getInstallPath(), Paths);
+ if (GCCInstallation.isValid()) {
+ // On Solaris gcc uses both an architecture-specific path with triple in it
+ // as well as a more generic lib path (+arch suffix).
+ addPathIfExists(D,
+ GCCInstallation.getInstallPath() +
+ GCCInstallation.getMultilib().gccSuffix(),
+ Paths);
+ addPathIfExists(D, GCCInstallation.getParentLibPath() + LibSuffix, Paths);
+ }
- addPathIfExists(D, getDriver().getInstalledDir(), Paths);
- if (getDriver().getInstalledDir() != getDriver().Dir)
- addPathIfExists(D, getDriver().Dir, Paths);
+ // If we are currently running Clang inside of the requested system root,
+ // add its parent library path to those searched.
+ if (StringRef(D.Dir).startswith(D.SysRoot))
+ addPathIfExists(D, D.Dir + "/../lib", Paths);
- addPathIfExists(D, getDriver().SysRoot + getDriver().Dir + "/../lib", Paths);
+ addPathIfExists(D, D.SysRoot + "/usr/lib" + LibSuffix, Paths);
+}
- std::string LibPath = "/usr/lib/";
- switch (Triple.getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::sparc:
- break;
- case llvm::Triple::x86_64:
- LibPath += "amd64/";
- break;
- case llvm::Triple::sparcv9:
- LibPath += "sparcv9/";
- break;
- default:
- llvm_unreachable("Unsupported architecture");
+SanitizerMask Solaris::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ // FIXME: Omit X86_64 until 64-bit support is figured out.
+ if (IsX86) {
+ Res |= SanitizerKind::Address;
}
-
- addPathIfExists(D, getDriver().SysRoot + LibPath, Paths);
+ Res |= SanitizerKind::Vptr;
+ return Res;
}
Tool *Solaris::buildAssembler() const {
@@ -164,30 +211,72 @@ Tool *Solaris::buildAssembler() const {
Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); }
-void Solaris::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
+void Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
+ addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/local/include");
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
- // Include the support directory for things like xlocale and fudged system
- // headers.
- // FIXME: This is a weird mix of libc++ and libstdc++. We should also be
- // checking the value of -stdlib= here and adding the includes for libc++
- // rather than libstdc++ if it's requested.
- addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/v1/support/solaris");
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (StringRef dir : dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+ }
+ return;
+ }
+ // Add include directories specific to the selected multilib set and multilib.
if (GCCInstallation.isValid()) {
- GCCVersion Version = GCCInstallation.getVersion();
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/gcc/" +
- Version.MajorStr + "." +
- Version.MinorStr +
- "/include/c++/" + Version.Text);
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/gcc/" + Version.MajorStr +
- "." + Version.MinorStr + "/include/c++/" +
- Version.Text + "/" +
- GCCInstallation.getTriple().str());
+ const MultilibSet::IncludeDirsFunc &Callback =
+ Multilibs.includeDirsCallback();
+ if (Callback) {
+ for (const auto &Path : Callback(GCCInstallation.getMultilib()))
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
+ }
}
+
+ addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
+}
+
+void Solaris::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // We need a detected GCC installation on Solaris (similar to Linux)
+ // to provide libstdc++'s headers.
+ if (!GCCInstallation.isValid())
+ return;
+
+ // By default, look for the C++ headers in an include directory adjacent to
+ // the lib directory of the GCC installation.
+ // On Solaris this usually looks like /usr/gcc/X.Y/include/c++/X.Y.Z
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ const GCCVersion &Version = GCCInstallation.getVersion();
+
+ // The primary search for libstdc++ supports multiarch variants.
+ addLibStdCXXIncludePaths(LibDir.str() + "/../include", "/c++/" + Version.Text,
+ TripleStr,
+ /*GCCMultiarchTriple*/ "",
+ /*TargetMultiarchTriple*/ "",
+ Multilib.includeSuffix(), DriverArgs, CC1Args);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.h
index 787917afab6e..9e14269b393e 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.h
@@ -57,10 +57,15 @@ public:
bool IsIntegratedAssemblerDefault() const override { return true; }
- void AddClangCXXStdlibIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ SanitizerMask getSupportedSanitizers() const override;
unsigned GetDefaultDwarfVersion() const override { return 2; }
protected:
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 8ae1b6c2f55d..94f7279bbdba 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -11,6 +11,7 @@
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
@@ -62,8 +63,6 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-allow-undefined-file");
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("wasm.syms")));
CmdArgs.push_back("-lc");
AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
}
@@ -119,6 +118,12 @@ ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const {
}
ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value != "libc++")
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
return ToolChain::CST_Libcxx;
}
@@ -136,6 +141,19 @@ void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
getDriver().SysRoot + "/include/c++/v1");
}
+void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+
+ switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ llvm_unreachable("invalid stdlib name");
+ }
+}
+
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.
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h
index 8784e12dfb0e..cdbb34ff919f 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -62,6 +62,8 @@ private:
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
std::string getThreadModel() const override;
const char *getDefaultLinker() const override {
diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
index ab63f0e81b12..45bb699cfb88 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
@@ -102,6 +102,9 @@ bool types::isAcceptedByClang(ID Id) {
case TY_CL:
case TY_CUDA: case TY_PP_CUDA:
case TY_CUDA_DEVICE:
+ case TY_HIP:
+ case TY_PP_HIP:
+ case TY_HIP_DEVICE:
case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
case TY_CXX: case TY_PP_CXX:
case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
@@ -141,6 +144,9 @@ bool types::isCXX(ID Id) {
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
case TY_CXXModule: case TY_PP_CXXModule:
case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
+ case TY_HIP:
+ case TY_PP_HIP:
+ case TY_HIP_DEVICE:
return true;
}
}
@@ -170,6 +176,18 @@ bool types::isCuda(ID Id) {
}
}
+bool types::isHIP(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_HIP:
+ case TY_PP_HIP:
+ case TY_HIP_DEVICE:
+ return true;
+ }
+}
+
bool types::isSrcFile(ID Id) {
return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
}
@@ -221,6 +239,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
.Case("fpp", TY_Fortran)
.Case("FPP", TY_Fortran)
.Case("gch", TY_PCH)
+ .Case("hip", TY_HIP)
.Case("hpp", TY_CXXHeader)
.Case("iim", TY_PP_CXXModule)
.Case("lib", TY_Object)
diff --git a/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp
index 232bacd5f095..30b0e72760c9 100644
--- a/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp
@@ -27,6 +27,7 @@ namespace {
constexpr char XRayInstrumentOption[] = "-fxray-instrument";
constexpr char XRayInstructionThresholdOption[] =
"-fxray-instruction-threshold=";
+constexpr const char *const XRaySupportedModes[] = {"xray-fdr", "xray-basic"};
} // namespace
XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
@@ -34,7 +35,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
const llvm::Triple &Triple = TC.getTriple();
if (Args.hasFlag(options::OPT_fxray_instrument,
options::OPT_fnoxray_instrument, false)) {
- if (Triple.getOS() == llvm::Triple::Linux)
+ if (Triple.getOS() == llvm::Triple::Linux) {
switch (Triple.getArch()) {
case llvm::Triple::x86_64:
case llvm::Triple::arm:
@@ -49,9 +50,17 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
- else
+ } else if (Triple.getOS() == llvm::Triple::FreeBSD ||
+ Triple.getOS() == llvm::Triple::OpenBSD ||
+ Triple.getOS() == llvm::Triple::NetBSD) {
+ if (Triple.getArch() != llvm::Triple::x86_64) {
+ D.Diag(diag::err_drv_clang_unsupported)
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+ }
+ } else {
D.Diag(diag::err_drv_clang_unsupported)
- << (std::string(XRayInstrumentOption) + " on non-Linux target OS");
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+ }
XRayInstrument = true;
if (const Arg *A =
Args.getLastArg(options::OPT_fxray_instruction_threshold_,
@@ -69,6 +78,44 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
options::OPT_fnoxray_always_emit_customevents, false))
XRayAlwaysEmitCustomEvents = true;
+ if (Args.hasFlag(options::OPT_fxray_always_emit_typedevents,
+ options::OPT_fnoxray_always_emit_typedevents, false))
+ XRayAlwaysEmitTypedEvents = true;
+
+ if (!Args.hasFlag(options::OPT_fxray_link_deps,
+ options::OPT_fnoxray_link_deps, true))
+ XRayRT = false;
+
+ auto Bundles =
+ Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
+ if (Bundles.empty())
+ InstrumentationBundle.Mask = XRayInstrKind::All;
+ else
+ for (const auto &B : Bundles) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ llvm::SplitString(B, BundleParts, ",");
+ for (const auto &P : BundleParts) {
+ // TODO: Automate the generation of the string case table.
+ auto Valid = llvm::StringSwitch<bool>(P)
+ .Cases("none", "all", "function", "custom", true)
+ .Default(false);
+
+ if (!Valid) {
+ D.Diag(clang::diag::err_drv_invalid_value)
+ << "-fxray-instrumentation-bundle=" << P;
+ continue;
+ }
+
+ auto Mask = parseXRayInstrValue(P);
+ if (Mask == XRayInstrKind::None) {
+ InstrumentationBundle.clear();
+ break;
+ }
+
+ InstrumentationBundle.Mask |= Mask;
+ }
+ }
+
// Validate the always/never attribute files. We also make sure that they
// are treated as actual dependencies.
for (const auto &Filename :
@@ -88,6 +135,37 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
} else
D.Diag(clang::diag::err_drv_no_such_file) << Filename;
}
+
+ for (const auto &Filename :
+ Args.getAllArgValues(options::OPT_fxray_attr_list)) {
+ if (llvm::sys::fs::exists(Filename)) {
+ AttrListFiles.push_back(Filename);
+ ExtraDeps.push_back(Filename);
+ } else
+ D.Diag(clang::diag::err_drv_no_such_file) << Filename;
+ }
+
+ // Get the list of modes we want to support.
+ auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
+ if (SpecifiedModes.empty())
+ llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
+ else
+ for (const auto &Arg : SpecifiedModes) {
+ // Parse CSV values for -fxray-modes=...
+ llvm::SmallVector<StringRef, 2> ModeParts;
+ llvm::SplitString(Arg, ModeParts, ",");
+ for (const auto &M : ModeParts)
+ if (M == "none")
+ Modes.clear();
+ else if (M == "all")
+ llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
+ else
+ Modes.push_back(M);
+ }
+
+ // Then we want to sort and unique the modes we've collected.
+ llvm::sort(Modes.begin(), Modes.end());
+ Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
}
}
@@ -101,6 +179,9 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
if (XRayAlwaysEmitCustomEvents)
CmdArgs.push_back("-fxray-always-emit-customevents");
+ if (XRayAlwaysEmitTypedEvents)
+ CmdArgs.push_back("-fxray-always-emit-typedevents");
+
CmdArgs.push_back(Args.MakeArgString(Twine(XRayInstructionThresholdOption) +
Twine(InstructionThreshold)));
@@ -116,9 +197,21 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
}
+ for (const auto &AttrFile : AttrListFiles) {
+ SmallString<64> AttrListFileOpt("-fxray-attr-list=");
+ AttrListFileOpt += AttrFile;
+ CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
+ }
+
for (const auto &Dep : ExtraDeps) {
SmallString<64> ExtraDepOpt("-fdepfile-entry=");
ExtraDepOpt += Dep;
CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
}
+
+ for (const auto &Mode : Modes) {
+ SmallString<64> ModeOpt("-fxray-modes=");
+ ModeOpt += Mode;
+ CmdArgs.push_back(Args.MakeArgString(ModeOpt));
+ }
}
diff --git a/contrib/llvm/tools/clang/lib/Edit/Commit.cpp b/contrib/llvm/tools/clang/lib/Edit/Commit.cpp
index cb7a784a41af..e72b13cf8198 100644
--- a/contrib/llvm/tools/clang/lib/Edit/Commit.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/Commit.cpp
@@ -1,4 +1,4 @@
-//===----- Commit.cpp - A unit of edits -----------------------------------===//
+//===- Commit.cpp - A unit of edits ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,10 +8,16 @@
//===----------------------------------------------------------------------===//
#include "clang/Edit/Commit.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/EditedSource.h"
+#include "clang/Edit/FileOffset.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PPConditionalDirectiveRecord.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <utility>
using namespace clang;
using namespace edit;
@@ -36,9 +42,9 @@ CharSourceRange Commit::Edit::getInsertFromRange(SourceManager &SM) const {
}
Commit::Commit(EditedSource &Editor)
- : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
- PPRec(Editor.getPPCondDirectiveRecord()),
- Editor(&Editor), IsCommitable(true) { }
+ : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
+ PPRec(Editor.getPPCondDirectiveRecord()),
+ Editor(&Editor) {}
bool Commit::insert(SourceLocation loc, StringRef text,
bool afterToken, bool beforePreviousInsertions) {
@@ -141,7 +147,7 @@ bool Commit::replaceWithInner(CharSourceRange range,
}
FileOffset OuterEnd = OuterBegin.getWithOffset(OuterLen);
- FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen);
+ FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen);
if (OuterBegin.getFID() != InnerBegin.getFID() ||
InnerBegin < OuterBegin ||
InnerBegin > OuterEnd ||
@@ -225,8 +231,7 @@ bool Commit::canInsert(SourceLocation loc, FileOffset &offs) {
isAtStartOfMacroExpansion(loc, &loc);
const SourceManager &SM = SourceMgr;
- while (SM.isMacroArgExpansion(loc))
- loc = SM.getImmediateSpellingLoc(loc);
+ loc = SM.getTopMacroCallerLoc(loc);
if (loc.isMacroID())
if (!isAtStartOfMacroExpansion(loc, &loc))
@@ -256,8 +261,7 @@ bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,
isAtEndOfMacroExpansion(loc, &loc);
const SourceManager &SM = SourceMgr;
- while (SM.isMacroArgExpansion(loc))
- loc = SM.getImmediateSpellingLoc(loc);
+ loc = SM.getTopMacroCallerLoc(loc);
if (loc.isMacroID())
if (!isAtEndOfMacroExpansion(loc, &loc))
@@ -278,14 +282,12 @@ bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,
}
bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
- for (unsigned i = 0, e = CachedEdits.size(); i != e; ++i) {
- Edit &act = CachedEdits[i];
+ for (const auto &act : CachedEdits)
if (act.Kind == Act_Remove) {
if (act.Offset.getFID() == Offs.getFID() &&
Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))
return false; // position has been removed.
}
- }
if (!Editor)
return true;
@@ -298,7 +300,7 @@ bool Commit::canRemoveRange(CharSourceRange range,
range = Lexer::makeFileCharRange(range, SM, LangOpts);
if (range.isInvalid())
return false;
-
+
if (range.getBegin().isMacroID() || range.getEnd().isMacroID())
return false;
if (SM.isInSystemHeader(range.getBegin()) ||
@@ -340,6 +342,7 @@ bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroBegin) const {
return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin);
}
+
bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroEnd) const {
return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
diff --git a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
index 444d0393cccd..b38f8fd0d9cb 100644
--- a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
@@ -1,4 +1,4 @@
-//===----- EditedSource.cpp - Collection of source edits ------------------===//
+//===- EditedSource.cpp - Collection of source edits ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,12 +9,21 @@
#include "clang/Edit/EditedSource.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
+#include "clang/Edit/FileOffset.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include <algorithm>
+#include <cassert>
+#include <tuple>
+#include <utility>
using namespace clang;
using namespace edit;
@@ -27,12 +36,14 @@ void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
SourceLocation &ExpansionLoc,
MacroArgUse &ArgUse) {
assert(SourceMgr.isMacroArgExpansion(Loc));
- SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
+ SourceLocation DefArgLoc =
+ SourceMgr.getImmediateExpansionRange(Loc).getBegin();
SourceLocation ImmediateExpansionLoc =
- SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
+ SourceMgr.getImmediateExpansionRange(DefArgLoc).getBegin();
ExpansionLoc = ImmediateExpansionLoc;
while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
- ExpansionLoc = SourceMgr.getImmediateExpansionRange(ExpansionLoc).first;
+ ExpansionLoc =
+ SourceMgr.getImmediateExpansionRange(ExpansionLoc).getBegin();
SmallString<20> Buf;
StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
Buf, SourceMgr, LangOpts);
@@ -269,9 +280,11 @@ bool EditedSource::commit(const Commit &commit) {
struct CommitRAII {
EditedSource &Editor;
+
CommitRAII(EditedSource &Editor) : Editor(Editor) {
Editor.startingCommit();
}
+
~CommitRAII() {
Editor.finishedCommit();
}
@@ -298,7 +311,7 @@ bool EditedSource::commit(const Commit &commit) {
return true;
}
-// \brief Returns true if it is ok to make the two given characters adjacent.
+// Returns true if it is ok to make the two given characters adjacent.
static bool canBeJoined(char left, char right, const LangOptions &LangOpts) {
// FIXME: Should use TokenConcatenation to make sure we don't allow stuff like
// making two '<' adjacent.
@@ -306,7 +319,7 @@ static bool canBeJoined(char left, char right, const LangOptions &LangOpts) {
Lexer::isIdentifierBodyChar(right, LangOpts));
}
-/// \brief Returns true if it is ok to eliminate the trailing whitespace between
+/// Returns true if it is ok to eliminate the trailing whitespace between
/// the given characters.
static bool canRemoveWhitespace(char left, char beforeWSpace, char right,
const LangOptions &LangOpts) {
@@ -319,7 +332,7 @@ static bool canRemoveWhitespace(char left, char beforeWSpace, char right,
return true;
}
-/// \brief Check the range that we are going to remove and:
+/// Check the range that we are going to remove and:
/// -Remove any trailing whitespace if possible.
/// -Insert a space if removing the range is going to mess up the source tokens.
static void adjustRemoval(const SourceManager &SM, const LangOptions &LangOpts,
diff --git a/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
index dc501b564eea..b53a70d87582 100644
--- a/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -82,7 +82,7 @@ bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
(NS.getNSDictionarySelector(
NSAPI::NSDict_dictionaryWithDictionary) == Sel ||
NS.getNSDictionarySelector(NSAPI::NSDict_initWithDictionary) == Sel))) {
-
+
commit.replaceWithInner(Msg->getSourceRange(),
Msg->getArg(0)->getSourceRange());
return true;
@@ -95,7 +95,7 @@ bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
// rewriteToObjCSubscriptSyntax.
//===----------------------------------------------------------------------===//
-/// \brief Check for classes that accept 'objectForKey:' (or the other selectors
+/// Check for classes that accept 'objectForKey:' (or the other selectors
/// that the migrator handles) but return their instances as 'id', resulting
/// in the compiler resolving 'objectForKey:' as the method from NSDictionary.
///
@@ -355,7 +355,7 @@ bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
return false;
}
-/// \brief Returns true if the immediate message arguments of \c Msg should not
+/// Returns true if the immediate message arguments of \c Msg should not
/// be rewritten because it will interfere with the rewrite of the parent
/// message expression. e.g.
/// \code
@@ -372,7 +372,7 @@ static bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg,
// rewriteToArrayLiteral.
//===----------------------------------------------------------------------===//
-/// \brief Adds an explicit cast to 'id' if the type is not objc object.
+/// Adds an explicit cast to 'id' if the type is not objc object.
static void objectifyExpr(const Expr *E, Commit &commit);
static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
@@ -434,7 +434,7 @@ static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
// rewriteToDictionaryLiteral.
//===----------------------------------------------------------------------===//
-/// \brief If \c Msg is an NSArray creation message or literal, this gets the
+/// If \c Msg is an NSArray creation message or literal, this gets the
/// objects that were used to create it.
/// \returns true if it is an NSArray and we got objects, or false otherwise.
static bool getNSArrayObjects(const Expr *E, const NSAPI &NS,
@@ -726,7 +726,7 @@ static bool getLiteralInfo(SourceRange literalRange,
} else
break;
}
-
+
if (!UpperU.hasValue() && !UpperL.hasValue())
UpperU = UpperL = true;
else if (UpperU.hasValue() && !UpperL.hasValue())
@@ -738,7 +738,7 @@ static bool getLiteralInfo(SourceRange literalRange,
Info.L = *UpperL ? "L" : "l";
Info.LL = *UpperL ? "LL" : "ll";
Info.F = UpperF ? "F" : "f";
-
+
Info.Hex = Info.Octal = false;
if (text.startswith("0x"))
Info.Hex = true;
@@ -851,7 +851,7 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
// Try to modify the literal make it the same type as the method call.
// -Modify the suffix, and/or
// -Change integer to float
-
+
LiteralInfo LitInfo;
bool isIntZero = false;
if (const IntegerLiteral *IntE = dyn_cast<IntegerLiteral>(literalE))
@@ -862,7 +862,7 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
// Not easy to do int -> float with hex/octal and uncommon anyway.
if (!LitIsFloat && CallIsFloating && (LitInfo.Hex || LitInfo.Octal))
return rewriteToNumericBoxedExpression(Msg, NS, commit);
-
+
SourceLocation LitB = LitInfo.WithoutSuffRange.getBegin();
SourceLocation LitE = LitInfo.WithoutSuffRange.getEnd();
@@ -879,7 +879,7 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
} else {
if (CallIsUnsigned)
commit.insert(LitE, LitInfo.U);
-
+
if (CallIsLong)
commit.insert(LitE, LitInfo.L);
else if (CallIsLongLong)
@@ -997,7 +997,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
uint64_t FinalTySize = Ctx.getTypeSize(FinalTy);
uint64_t OrigTySize = Ctx.getTypeSize(OrigTy);
- bool isTruncated = FinalTySize < OrigTySize;
+ bool isTruncated = FinalTySize < OrigTySize;
bool needsCast = false;
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
@@ -1090,7 +1090,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
}
if (needsCast) {
- DiagnosticsEngine &Diags = Ctx.getDiagnostics();
+ DiagnosticsEngine &Diags = Ctx.getDiagnostics();
// FIXME: Use a custom category name to distinguish migration diagnostics.
unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
"converting to boxing syntax requires casting %0 to %1");
@@ -1145,7 +1145,7 @@ static bool doRewriteToUTF8StringBoxedExpressionHelper(
commit.insertBefore(ArgRange.getBegin(), "@");
else
commit.insertWrap("@(", ArgRange, ")");
-
+
return true;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.cpp b/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.cpp
index 5d4df1941209..b14316a14cd9 100644
--- a/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements AffectRangeManager class.
+/// This file implements AffectRangeManager class.
///
//===----------------------------------------------------------------------===//
@@ -21,8 +21,9 @@ namespace clang {
namespace format {
bool AffectedRangeManager::computeAffectedLines(
- SmallVectorImpl<AnnotatedLine *>::iterator I,
- SmallVectorImpl<AnnotatedLine *>::iterator E) {
+ SmallVectorImpl<AnnotatedLine *> &Lines) {
+ SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin();
+ SmallVectorImpl<AnnotatedLine *>::iterator E = Lines.end();
bool SomeLineAffected = false;
const AnnotatedLine *PreviousLine = nullptr;
while (I != E) {
@@ -48,7 +49,7 @@ bool AffectedRangeManager::computeAffectedLines(
continue;
}
- if (nonPPLineAffected(Line, PreviousLine))
+ if (nonPPLineAffected(Line, PreviousLine, Lines))
SomeLineAffected = true;
PreviousLine = Line;
@@ -99,10 +100,10 @@ void AffectedRangeManager::markAllAsAffected(
}
bool AffectedRangeManager::nonPPLineAffected(
- AnnotatedLine *Line, const AnnotatedLine *PreviousLine) {
+ AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
+ SmallVectorImpl<AnnotatedLine *> &Lines) {
bool SomeLineAffected = false;
- Line->ChildrenAffected =
- computeAffectedLines(Line->Children.begin(), Line->Children.end());
+ Line->ChildrenAffected = computeAffectedLines(Line->Children);
if (Line->ChildrenAffected)
SomeLineAffected = true;
@@ -138,8 +139,13 @@ bool AffectedRangeManager::nonPPLineAffected(
Line->First->NewlinesBefore < 2 && PreviousLine &&
PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
+ bool IsAffectedClosingBrace =
+ Line->First->is(tok::r_brace) &&
+ Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
+ Lines[Line->MatchingOpeningBlockLineIndex]->Affected;
+
if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
- IsContinuedComment) {
+ IsContinuedComment || IsAffectedClosingBrace) {
Line->Affected = true;
SomeLineAffected = true;
}
diff --git a/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.h b/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.h
index d8d5ee55acd8..b0c9dd259fb8 100644
--- a/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.h
+++ b/contrib/llvm/tools/clang/lib/Format/AffectedRangeManager.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief AffectedRangeManager class manages affected ranges in the code.
+/// AffectedRangeManager class manages affected ranges in the code.
///
//===----------------------------------------------------------------------===//
@@ -30,10 +30,9 @@ public:
: SourceMgr(SourceMgr), Ranges(Ranges.begin(), Ranges.end()) {}
// Determines which lines are affected by the SourceRanges given as input.
- // Returns \c true if at least one line between I and E or one of their
+ // Returns \c true if at least one line in \p Lines or one of their
// children is affected.
- bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I,
- SmallVectorImpl<AnnotatedLine *>::iterator E);
+ bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *> &Lines);
// Returns true if 'Range' intersects with one of the input ranges.
bool affectsCharSourceRange(const CharSourceRange &Range);
@@ -54,8 +53,8 @@ private:
// Determines whether 'Line' is affected by the SourceRanges given as input.
// Returns \c true if line or one if its children is affected.
- bool nonPPLineAffected(AnnotatedLine *Line,
- const AnnotatedLine *PreviousLine);
+ bool nonPPLineAffected(AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
+ SmallVectorImpl<AnnotatedLine *> &Lines);
const SourceManager &SourceMgr;
const SmallVector<CharSourceRange, 8> Ranges;
diff --git a/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp b/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
index 4735ab3564f0..fc2f891e0857 100644
--- a/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Contains implementation of BreakableToken class and classes derived
+/// Contains implementation of BreakableToken class and classes derived
/// from it.
///
//===----------------------------------------------------------------------===//
@@ -44,7 +44,8 @@ static StringRef getLineCommentIndentPrefix(StringRef Comment,
const FormatStyle &Style) {
static const char *const KnownCStylePrefixes[] = {"///<", "//!<", "///", "//",
"//!"};
- static const char *const KnownTextProtoPrefixes[] = {"//", "#"};
+ static const char *const KnownTextProtoPrefixes[] = {"//", "#", "##", "###",
+ "####"};
ArrayRef<const char *> KnownPrefixes(KnownCStylePrefixes);
if (Style.Language == FormatStyle::LK_TextProto)
KnownPrefixes = KnownTextProtoPrefixes;
@@ -67,8 +68,9 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
unsigned ColumnLimit,
unsigned TabWidth,
encoding::Encoding Encoding) {
- DEBUG(llvm::dbgs() << "Comment split: \"" << Text << ", " << ColumnLimit
- << "\", Content start: " << ContentStartColumn << "\n");
+ LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text << ", " << ColumnLimit
+ << "\", Content start: " << ContentStartColumn
+ << "\n");
if (ColumnLimit <= ContentStartColumn + 1)
return BreakableToken::Split(StringRef::npos, 0);
@@ -89,9 +91,9 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
// Do not split before a number followed by a dot: this would be interpreted
// as a numbered list, which would prevent re-flowing in subsequent passes.
- static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
+ static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\.");
if (SpaceOffset != StringRef::npos &&
- kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks)))
+ kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
if (SpaceOffset == StringRef::npos ||
@@ -214,11 +216,11 @@ unsigned BreakableStringLiteral::getContentStartColumn(unsigned LineIndex,
BreakableStringLiteral::BreakableStringLiteral(
const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
- StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
- const FormatStyle &Style)
+ StringRef Postfix, unsigned UnbreakableTailLength, bool InPPDirective,
+ encoding::Encoding Encoding, const FormatStyle &Style)
: BreakableToken(Tok, InPPDirective, Encoding, Style),
StartColumn(StartColumn), Prefix(Prefix), Postfix(Postfix),
- UnbreakableTailLength(Tok.UnbreakableTailLength) {
+ UnbreakableTailLength(UnbreakableTailLength) {
assert(Tok.TokenText.startswith(Prefix) && Tok.TokenText.endswith(Postfix));
Line = Tok.TokenText.substr(
Prefix.size(), Tok.TokenText.size() - Prefix.size() - Postfix.size());
@@ -233,6 +235,7 @@ BreakableToken::Split BreakableStringLiteral::getSplit(
void BreakableStringLiteral::insertBreak(unsigned LineIndex,
unsigned TailOffset, Split Split,
+ unsigned ContentIndent,
WhitespaceManager &Whitespaces) const {
Whitespaces.replaceWhitespaceInToken(
Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix,
@@ -284,10 +287,9 @@ static bool mayReflowContent(StringRef Content) {
Content = Content.trim(Blanks);
// Lines starting with '@' commonly have special meaning.
// Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists.
- static const SmallVector<StringRef, 8> kSpecialMeaningPrefixes = {
- "@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "};
bool hasSpecialMeaningPrefix = false;
- for (StringRef Prefix : kSpecialMeaningPrefixes) {
+ for (StringRef Prefix :
+ {"@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) {
if (Content.startswith(Prefix)) {
hasSpecialMeaningPrefix = true;
break;
@@ -297,9 +299,9 @@ static bool mayReflowContent(StringRef Content) {
// Numbered lists may also start with a number followed by '.'
// 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]?\\. ");
+ static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\. ");
hasSpecialMeaningPrefix =
- hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);
+ 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
@@ -425,7 +427,7 @@ BreakableBlockComment::BreakableBlockComment(
}
}
- DEBUG({
+ LLVM_DEBUG({
llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";
llvm::dbgs() << "DelimitersOnNewline " << DelimitersOnNewline << "\n";
for (size_t i = 0; i < Lines.size(); ++i) {
@@ -509,8 +511,33 @@ unsigned BreakableBlockComment::getContentStartColumn(unsigned LineIndex,
return std::max(0, ContentColumn[LineIndex]);
}
+const llvm::StringSet<>
+ BreakableBlockComment::ContentIndentingJavadocAnnotations = {
+ "@param", "@return", "@returns", "@throws", "@type", "@template",
+ "@see", "@deprecated", "@define", "@exports", "@mods", "@private",
+};
+
+unsigned BreakableBlockComment::getContentIndent(unsigned LineIndex) const {
+ if (Style.Language != FormatStyle::LK_Java &&
+ Style.Language != FormatStyle::LK_JavaScript)
+ return 0;
+ // The content at LineIndex 0 of a comment like:
+ // /** line 0 */
+ // is "* line 0", so we need to skip over the decoration in that case.
+ StringRef ContentWithNoDecoration = Content[LineIndex];
+ if (LineIndex == 0 && ContentWithNoDecoration.startswith("*")) {
+ ContentWithNoDecoration = ContentWithNoDecoration.substr(1).ltrim(Blanks);
+ }
+ StringRef FirstWord = ContentWithNoDecoration.substr(
+ 0, ContentWithNoDecoration.find_first_of(Blanks));
+ if (ContentIndentingJavadocAnnotations.find(FirstWord) !=
+ ContentIndentingJavadocAnnotations.end())
+ return Style.ContinuationIndentWidth;
+ return 0;
+}
+
void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
- Split Split,
+ Split Split, unsigned ContentIndent,
WhitespaceManager &Whitespaces) const {
StringRef Text = Content[LineIndex].substr(TailOffset);
StringRef Prefix = Decoration;
@@ -531,10 +558,14 @@ void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
unsigned CharsToRemove = Split.second;
assert(LocalIndentAtLineBreak >= Prefix.size());
+ std::string PrefixWithTrailingIndent = Prefix;
+ for (unsigned I = 0; I < ContentIndent; ++I)
+ PrefixWithTrailingIndent += " ";
Whitespaces.replaceWhitespaceInToken(
- tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", Prefix,
- InPPDirective, /*Newlines=*/1,
- /*Spaces=*/LocalIndentAtLineBreak - Prefix.size());
+ tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
+ PrefixWithTrailingIndent, InPPDirective, /*Newlines=*/1,
+ /*Spaces=*/LocalIndentAtLineBreak + ContentIndent -
+ PrefixWithTrailingIndent.size());
}
BreakableToken::Split
@@ -543,7 +574,16 @@ BreakableBlockComment::getReflowSplit(unsigned LineIndex,
if (!mayReflow(LineIndex, CommentPragmasRegex))
return Split(StringRef::npos, 0);
+ // If we're reflowing into a line with content indent, only reflow the next
+ // line if its starting whitespace matches the content indent.
size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);
+ if (LineIndex) {
+ unsigned PreviousContentIndent = getContentIndent(LineIndex - 1);
+ if (PreviousContentIndent && Trimmed != StringRef::npos &&
+ Trimmed != PreviousContentIndent)
+ return Split(StringRef::npos, 0);
+ }
+
return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);
}
@@ -582,7 +622,8 @@ void BreakableBlockComment::adaptStartOfLine(
// 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);
+ insertBreak(LineIndex, 0, Split(1, BreakLength), /*ContentIndent=*/0,
+ Whitespaces);
}
return;
}
@@ -753,7 +794,7 @@ unsigned BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
void BreakableLineCommentSection::insertBreak(
unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) const {
+ unsigned ContentIndent, WhitespaceManager &Whitespaces) const {
StringRef Text = Content[LineIndex].substr(TailOffset);
// Compute the offset of the split relative to the beginning of the token
// text.
@@ -788,16 +829,47 @@ BreakableComment::Split BreakableLineCommentSection::getReflowSplit(
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);
+ if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {
+ // 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);
+ } else if (LineIndex > 0) {
+ // In case we're reflowing after the '\' in:
+ //
+ // // line comment \
+ // // line 2
+ //
+ // the reflow happens inside the single comment token (it is a single line
+ // comment with an unescaped newline).
+ // Replace the whitespace between the '\' and '//' with the empty string.
+ //
+ // Offset points to after the '\' relative to start of the token.
+ unsigned Offset = Lines[LineIndex - 1].data() +
+ Lines[LineIndex - 1].size() -
+ tokenAt(LineIndex - 1).TokenText.data();
+ // WhitespaceLength is the number of chars between the '\' and the '//' on
+ // the next line.
+ unsigned WhitespaceLength =
+ Lines[LineIndex].data() - tokenAt(LineIndex).TokenText.data() - Offset;
+ Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex],
+ Offset,
+ /*ReplaceChars=*/WhitespaceLength,
+ /*PreviousPostfix=*/"",
+ /*CurrentPrefix=*/"",
+ /*InPPDirective=*/false,
+ /*Newlines=*/0,
+ /*Spaces=*/0);
+
+ }
// Replace the indent and prefix of the token with the reflow prefix.
+ unsigned Offset =
+ Lines[LineIndex].data() - tokenAt(LineIndex).TokenText.data();
unsigned WhitespaceLength =
- Content[LineIndex].data() - tokenAt(LineIndex).TokenText.data();
+ Content[LineIndex].data() - Lines[LineIndex].data();
Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex],
- /*Offset=*/0,
+ Offset,
/*ReplaceChars=*/WhitespaceLength,
/*PreviousPostfix=*/"",
/*CurrentPrefix=*/ReflowPrefix,
diff --git a/contrib/llvm/tools/clang/lib/Format/BreakableToken.h b/contrib/llvm/tools/clang/lib/Format/BreakableToken.h
index 8ef26ef464da..10e180178021 100644
--- a/contrib/llvm/tools/clang/lib/Format/BreakableToken.h
+++ b/contrib/llvm/tools/clang/lib/Format/BreakableToken.h
@@ -1,4 +1,4 @@
-//===--- BreakableToken.h - Format C++ code -------------------------------===//
+//===--- BreakableToken.h - Format C++ code ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Declares BreakableToken, BreakableStringLiteral, BreakableComment,
+/// Declares BreakableToken, BreakableStringLiteral, BreakableComment,
/// BreakableBlockComment and BreakableLineCommentSection classes, that contain
/// token type-specific logic to break long lines in tokens and reflow content
/// between tokens.
@@ -21,19 +21,20 @@
#include "Encoding.h"
#include "TokenAnnotator.h"
#include "WhitespaceManager.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Regex.h"
#include <utility>
namespace clang {
namespace format {
-/// \brief Checks if \p Token switches formatting, like /* clang-format off */.
+/// Checks if \p Token switches formatting, like /* clang-format off */.
/// \p Token must be a comment.
bool switchesFormatting(const FormatToken &Token);
struct FormatStyle;
-/// \brief Base class for tokens / ranges of tokens that can allow breaking
+/// 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.
///
@@ -88,15 +89,15 @@ struct FormatStyle;
///
class BreakableToken {
public:
- /// \brief Contains starting character index and length of split.
+ /// Contains starting character index and length of split.
typedef std::pair<StringRef::size_type, unsigned> Split;
virtual ~BreakableToken() {}
- /// \brief Returns the number of lines in this token in the original code.
+ /// 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 text in the
+ /// 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
@@ -108,7 +109,7 @@ public:
StringRef::size_type Length,
unsigned StartColumn) const = 0;
- /// \brief Returns the number of columns required to format the text following
+ /// 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.
///
@@ -125,7 +126,7 @@ public:
return getRangeLength(LineIndex, Offset, StringRef::npos, StartColumn);
}
- /// \brief Returns the column at which content in line \p LineIndex starts,
+ /// Returns the column at which content in line \p LineIndex starts,
/// assuming no reflow.
///
/// If \p Break is true, returns the column at which the line should start
@@ -135,7 +136,22 @@ public:
virtual unsigned getContentStartColumn(unsigned LineIndex,
bool Break) const = 0;
- /// \brief Returns a range (offset, length) at which to break the line at
+ /// Returns additional content indent required for the second line after the
+ /// content at line \p LineIndex is broken.
+ ///
+ // (Next lines do not start with `///` since otherwise -Wdocumentation picks
+ // up the example annotations and generates warnings for them)
+ // For example, Javadoc @param annotations require and indent of 4 spaces and
+ // in this example getContentIndex(1) returns 4.
+ // /**
+ // * @param loooooooooooooong line
+ // * continuation
+ // */
+ virtual unsigned getContentIndent(unsigned LineIndex) const {
+ return 0;
+ }
+
+ /// 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, assuming the text starting at \p TailOffset in
/// the token is formatted starting at ContentStartColumn in the reformatted
@@ -144,27 +160,28 @@ public:
unsigned ColumnLimit, unsigned ContentStartColumn,
llvm::Regex &CommentPragmasRegex) const = 0;
- /// \brief Emits the previously retrieved \p Split via \p Whitespaces.
+ /// Emits the previously retrieved \p Split via \p Whitespaces.
virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+ unsigned ContentIndent,
WhitespaceManager &Whitespaces) const = 0;
- /// \brief Returns the number of columns needed to format
+ /// 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
+ /// Replaces the whitespace range described by \p Split with a single
/// space.
virtual void compressWhitespace(unsigned LineIndex, unsigned TailOffset,
Split Split,
WhitespaceManager &Whitespaces) const = 0;
- /// \brief Returns whether the token supports reflowing text.
+ /// 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
+ /// 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.
///
@@ -180,21 +197,21 @@ public:
return Split(StringRef::npos, 0);
}
- /// \brief Reflows the current line into the end of the previous one.
+ /// 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
+ /// 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.
+ /// Replaces the whitespace between \p LineIndex-1 and \p LineIndex.
virtual void adaptStartOfLine(unsigned LineIndex,
WhitespaceManager &Whitespaces) const {}
- /// \brief Returns a whitespace range (offset, length) of the content at
+ /// 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.
///
@@ -204,16 +221,16 @@ public:
return Split(StringRef::npos, 0);
}
- /// \brief Replaces the whitespace from \p SplitAfterLastLine on the last line
+ /// 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);
+ /*ContentIndent=*/0, Whitespaces);
}
- /// \brief Updates the next token of \p State to the next token after this
+ /// 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
/// as a unit and is responsible for the formatting of the them.
virtual void updateNextToken(LineState &State) const {}
@@ -232,19 +249,20 @@ protected:
class BreakableStringLiteral : public BreakableToken {
public:
- /// \brief Creates a breakable token for a single line string literal.
+ /// Creates a breakable token for a single line string literal.
///
/// \p StartColumn specifies the column in which the token will start
/// after formatting.
BreakableStringLiteral(const FormatToken &Tok, unsigned StartColumn,
StringRef Prefix, StringRef Postfix,
- bool InPPDirective, encoding::Encoding Encoding,
- const FormatStyle &Style);
+ unsigned UnbreakableTailLength, bool InPPDirective,
+ encoding::Encoding Encoding, const FormatStyle &Style);
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
- unsigned ReflowColumn,
+ unsigned ContentStartColumn,
llvm::Regex &CommentPragmasRegex) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+ unsigned ContentIndent,
WhitespaceManager &Whitespaces) const override;
void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,
WhitespaceManager &Whitespaces) const override {}
@@ -272,7 +290,7 @@ protected:
class BreakableComment : public BreakableToken {
protected:
- /// \brief Creates a breakable token for a comment.
+ /// Creates a breakable token for a comment.
///
/// \p StartColumn specifies the column in which the comment will start after
/// formatting.
@@ -284,7 +302,7 @@ public:
bool supportsReflow() const override { return true; }
unsigned getLineCount() const override;
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
- unsigned ReflowColumn,
+ unsigned ContentStartColumn,
llvm::Regex &CommentPragmasRegex) const override;
void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,
WhitespaceManager &Whitespaces) const override;
@@ -354,7 +372,9 @@ public:
unsigned getRemainingLength(unsigned LineIndex, unsigned Offset,
unsigned StartColumn) const override;
unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
+ unsigned getContentIndent(unsigned LineIndex) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+ unsigned ContentIndent,
WhitespaceManager &Whitespaces) const override;
Split getReflowSplit(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
@@ -368,6 +388,10 @@ public:
bool mayReflow(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
+ // Contains Javadoc annotations that require additional indent when continued
+ // on multiple lines.
+ static const llvm::StringSet<> ContentIndentingJavadocAnnotations;
+
private:
// Rearranges the whitespace between Lines[LineIndex-1] and Lines[LineIndex].
//
@@ -423,6 +447,7 @@ public:
unsigned StartColumn) const override;
unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+ unsigned ContentIndent,
WhitespaceManager &Whitespaces) const override;
Split getReflowSplit(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
@@ -453,7 +478,7 @@ private:
SmallVector<unsigned, 16> OriginalContentColumn;
- /// \brief The token to which the last line of this breakable token belongs
+ /// The token to which the last line of this breakable token belongs
/// to; nullptr if that token is the initial token.
///
/// The distinction is because if the token of the last line of this breakable
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
index a3d38b244c5c..7ca588a675b5 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the continuation indenter.
+/// This file implements the continuation indenter.
///
//===----------------------------------------------------------------------===//
@@ -26,14 +26,81 @@
namespace clang {
namespace format {
+// Returns true if a TT_SelectorName should be indented when wrapped,
+// false otherwise.
+static bool shouldIndentWrappedSelectorName(const FormatStyle &Style,
+ LineType LineType) {
+ return Style.IndentWrappedFunctionNames || LineType == LT_ObjCMethodDecl;
+}
+
// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
-static unsigned getLengthToMatchingParen(const FormatToken &Tok) {
+static unsigned getLengthToMatchingParen(const FormatToken &Tok,
+ const std::vector<ParenState> &Stack) {
+ // Normally whether or not a break before T is possible is calculated and
+ // stored in T.CanBreakBefore. Braces, array initializers and text proto
+ // messages like `key: < ... >` are an exception: a break is possible
+ // before a closing brace R if a break was inserted after the corresponding
+ // opening brace. The information about whether or not a break is needed
+ // before a closing brace R is stored in the ParenState field
+ // S.BreakBeforeClosingBrace where S is the state that R closes.
+ //
+ // In order to decide whether there can be a break before encountered right
+ // braces, this implementation iterates over the sequence of tokens and over
+ // the paren stack in lockstep, keeping track of the stack level which visited
+ // right braces correspond to in MatchingStackIndex.
+ //
+ // For example, consider:
+ // L. <- line number
+ // 1. {
+ // 2. {1},
+ // 3. {2},
+ // 4. {{3}}}
+ // ^ where we call this method with this token.
+ // The paren stack at this point contains 3 brace levels:
+ // 0. { at line 1, BreakBeforeClosingBrace: true
+ // 1. first { at line 4, BreakBeforeClosingBrace: false
+ // 2. second { at line 4, BreakBeforeClosingBrace: false,
+ // where there might be fake parens levels in-between these levels.
+ // The algorithm will start at the first } on line 4, which is the matching
+ // brace of the initial left brace and at level 2 of the stack. Then,
+ // examining BreakBeforeClosingBrace: false at level 2, it will continue to
+ // the second } on line 4, and will traverse the stack downwards until it
+ // finds the matching { on level 1. Then, examining BreakBeforeClosingBrace:
+ // false at level 1, it will continue to the third } on line 4 and will
+ // traverse the stack downwards until it finds the matching { on level 0.
+ // Then, examining BreakBeforeClosingBrace: true at level 0, the algorithm
+ // will stop and will use the second } on line 4 to determine the length to
+ // return, as in this example the range will include the tokens: {3}}
+ //
+ // The algorithm will only traverse the stack if it encounters braces, array
+ // initializer squares or text proto angle brackets.
if (!Tok.MatchingParen)
return 0;
FormatToken *End = Tok.MatchingParen;
- while (End->Next && !End->Next->CanBreakBefore) {
- End = End->Next;
+ // Maintains a stack level corresponding to the current End token.
+ int MatchingStackIndex = Stack.size() - 1;
+ // Traverses the stack downwards, looking for the level to which LBrace
+ // corresponds. Returns either a pointer to the matching level or nullptr if
+ // LParen is not found in the initial portion of the stack up to
+ // MatchingStackIndex.
+ auto FindParenState = [&](const FormatToken *LBrace) -> const ParenState * {
+ while (MatchingStackIndex >= 0 && Stack[MatchingStackIndex].Tok != LBrace)
+ --MatchingStackIndex;
+ return MatchingStackIndex >= 0 ? &Stack[MatchingStackIndex] : nullptr;
+ };
+ for (; End->Next; End = End->Next) {
+ if (End->Next->CanBreakBefore)
+ break;
+ if (!End->Next->closesScope())
+ continue;
+ if (End->Next->MatchingParen &&
+ End->Next->MatchingParen->isOneOf(
+ tok::l_brace, TT_ArrayInitializerLSquare, tok::less)) {
+ const ParenState *State = FindParenState(End->Next->MatchingParen);
+ if (State && State->BreakBeforeClosingBrace)
+ break;
+ }
}
return End->TotalLength - Tok.TotalLength + 1;
}
@@ -64,7 +131,7 @@ static bool startsNextParameter(const FormatToken &Current,
Style.BreakConstructorInitializers !=
FormatStyle::BCIS_BeforeComma) &&
(Previous.isNot(TT_InheritanceComma) ||
- !Style.BreakBeforeInheritanceComma));
+ Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma));
}
static bool opensProtoMessageField(const FormatToken &LessTok,
@@ -102,28 +169,59 @@ static llvm::Optional<StringRef> getRawStringDelimiter(StringRef TokenText) {
return Delimiter;
}
+// Returns the canonical delimiter for \p Language, or the empty string if no
+// canonical delimiter is specified.
+static StringRef
+getCanonicalRawStringDelimiter(const FormatStyle &Style,
+ FormatStyle::LanguageKind Language) {
+ for (const auto &Format : Style.RawStringFormats) {
+ if (Format.Language == Language)
+ return StringRef(Format.CanonicalDelimiter);
+ }
+ return "";
+}
+
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;
+ llvm::Optional<FormatStyle> LanguageStyle =
+ CodeStyle.GetLanguageStyle(RawStringFormat.Language);
+ if (!LanguageStyle) {
+ FormatStyle PredefinedStyle;
+ if (!getPredefinedStyle(RawStringFormat.BasedOnStyle,
+ RawStringFormat.Language, &PredefinedStyle)) {
+ PredefinedStyle = getLLVMStyle();
+ PredefinedStyle.Language = RawStringFormat.Language;
+ }
+ LanguageStyle = PredefinedStyle;
+ }
+ LanguageStyle->ColumnLimit = CodeStyle.ColumnLimit;
+ for (StringRef Delimiter : RawStringFormat.Delimiters) {
+ DelimiterStyle.insert({Delimiter, *LanguageStyle});
+ }
+ for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions) {
+ EnclosingFunctionStyle.insert({EnclosingFunction, *LanguageStyle});
}
- Style.ColumnLimit = CodeStyle.ColumnLimit;
- DelimiterStyle.insert({RawStringFormat.Delimiter, Style});
}
}
llvm::Optional<FormatStyle>
-RawStringFormatStyleManager::get(StringRef Delimiter) const {
+RawStringFormatStyleManager::getDelimiterStyle(StringRef Delimiter) const {
auto It = DelimiterStyle.find(Delimiter);
if (It == DelimiterStyle.end())
return None;
return It->second;
}
+llvm::Optional<FormatStyle>
+RawStringFormatStyleManager::getEnclosingFunctionStyle(
+ StringRef EnclosingFunction) const {
+ auto It = EnclosingFunctionStyle.find(EnclosingFunction);
+ if (It == EnclosingFunctionStyle.end())
+ return None;
+ return It->second;
+}
+
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
const SourceManager &SourceMgr,
@@ -154,7 +252,7 @@ LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
State.Column = 0;
State.Line = Line;
State.NextToken = Line->First;
- State.Stack.push_back(ParenState(FirstIndent, FirstIndent,
+ State.Stack.push_back(ParenState(/*Tok=*/nullptr, FirstIndent, FirstIndent,
/*AvoidBinPacking=*/false,
/*NoLineBreak=*/false));
State.LineContainsContinuedForLoopSection = false;
@@ -169,6 +267,7 @@ LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
// global scope.
State.Stack.back().AvoidBinPacking = true;
State.Stack.back().BreakBeforeParameter = true;
+ State.Stack.back().AlignColons = false;
}
// The first token has already been indented and thus consumed.
@@ -222,6 +321,9 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
State.Stack.back().NoLineBreakInOperand)
return false;
+ if (Previous.is(tok::l_square) && Previous.is(TT_ObjCMethodExpr))
+ return false;
+
return !State.Stack.back().NoLineBreak;
}
@@ -235,6 +337,11 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true;
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
return true;
+ if (Style.Language == FormatStyle::LK_ObjC &&
+ Current.ObjCSelectorNameParts > 1 &&
+ Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
+ return true;
+ }
if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) ||
(Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
Style.isCpp() &&
@@ -255,7 +362,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Previous.ParameterCount > 1) ||
opensProtoMessageField(Previous, Style)) &&
Style.ColumnLimit > 0 &&
- getLengthToMatchingParen(Previous) + State.Column - 1 >
+ getLengthToMatchingParen(Previous, State.Stack) + State.Column - 1 >
getColumnLimit(State))
return true;
@@ -275,7 +382,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (Current.is(TT_ObjCMethodExpr) && !Previous.is(TT_SelectorName) &&
State.Line->startsWith(TT_ObjCMethodSpecifier))
return true;
- if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound &&
+ if (Current.is(TT_SelectorName) && !Previous.is(tok::at) &&
+ State.Stack.back().ObjCSelectorNameFound &&
State.Stack.back().BreakBeforeParameter)
return true;
@@ -298,6 +406,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Style.Language == FormatStyle::LK_JavaScript))
return true;
+ // If the template declaration spans multiple lines, force wrap before the
+ // function/class declaration
+ if (Previous.ClosesTemplateDeclaration &&
+ State.Stack.back().BreakBeforeParameter && Current.CanBreakBefore)
+ return true;
+
if (State.Column <= NewLineColumn)
return false;
@@ -349,7 +463,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// for cases where the entire line does not fit on a single line as a
// different LineFormatter would be used otherwise.
if (Previous.ClosesTemplateDeclaration)
- return true;
+ return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No;
if (Previous.is(TT_FunctionAnnotationRParen))
return true;
if (Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
@@ -466,7 +580,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
// If "BreakBeforeInheritanceComma" mode, don't break within the inheritance
// declaration unless there is multiple inheritance.
- if (Style.BreakBeforeInheritanceComma && Current.is(TT_InheritanceColon))
+ if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
+ Current.is(TT_InheritanceColon))
+ State.Stack.back().NoLineBreak = true;
+ if (Style.BreakInheritanceList == FormatStyle::BILS_AfterColon &&
+ Previous.is(TT_InheritanceColon))
State.Stack.back().NoLineBreak = true;
if (Current.is(TT_SelectorName) &&
@@ -661,11 +779,12 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Stack.back().AlignColons = false;
} else {
State.Stack.back().ColonPos =
- (Style.IndentWrappedFunctionNames
+ (shouldIndentWrappedSelectorName(Style, State.Line->Type)
? std::max(State.Stack.back().Indent,
State.FirstIndent + Style.ContinuationIndentWidth)
: State.Stack.back().Indent) +
- NextNonComment->LongestObjCSelectorName;
+ std::max(NextNonComment->LongestObjCSelectorName,
+ NextNonComment->ColumnWidth);
}
} else if (State.Stack.back().AlignColons &&
State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) {
@@ -693,7 +812,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
!State.Stack.back().AvoidBinPacking) ||
Previous.is(TT_BinaryOperator))
State.Stack.back().BreakBeforeParameter = false;
- if (Previous.isOneOf(TT_TemplateCloser, TT_JavaAnnotation) &&
+ if (PreviousNonComment &&
+ PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) &&
Current.NestingLevel == 0)
State.Stack.back().BreakBeforeParameter = false;
if (NextNonComment->is(tok::question) ||
@@ -826,7 +946,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
(Current.Next->is(TT_DictLiteral) ||
((Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) &&
- Current.Next->isOneOf(TT_TemplateOpener, tok::l_brace))))
+ Current.Next->isOneOf(tok::less, tok::l_brace))))
return State.Stack.back().Indent;
if (NextNonComment->is(TT_ObjCStringLiteral) &&
State.StartOfStringLiteral != 0)
@@ -851,20 +971,29 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if ((PreviousNonComment &&
(PreviousNonComment->ClosesTemplateDeclaration ||
PreviousNonComment->isOneOf(
- TT_AttributeParen, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
- TT_LeadingJavaAnnotation))) ||
+ TT_AttributeParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
+ TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
(!Style.IndentWrappedFunctionNames &&
NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName)))
return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
if (NextNonComment->is(TT_SelectorName)) {
if (!State.Stack.back().ObjCSelectorNameFound) {
- if (NextNonComment->LongestObjCSelectorName == 0)
- return State.Stack.back().Indent;
- return (Style.IndentWrappedFunctionNames
- ? std::max(State.Stack.back().Indent,
- State.FirstIndent + Style.ContinuationIndentWidth)
- : State.Stack.back().Indent) +
- NextNonComment->LongestObjCSelectorName -
+ unsigned MinIndent = State.Stack.back().Indent;
+ if (shouldIndentWrappedSelectorName(Style, State.Line->Type))
+ MinIndent = std::max(MinIndent,
+ State.FirstIndent + Style.ContinuationIndentWidth);
+ // If LongestObjCSelectorName is 0, we are indenting the first
+ // part of an ObjC selector (or a selector component which is
+ // not colon-aligned due to block formatting).
+ //
+ // Otherwise, we are indenting a subsequent part of an ObjC
+ // selector which should be colon-aligned to the longest
+ // component of the ObjC selector.
+ //
+ // In either case, we want to respect Style.IndentWrappedFunctionNames.
+ return MinIndent +
+ std::max(NextNonComment->LongestObjCSelectorName,
+ NextNonComment->ColumnWidth) -
NextNonComment->ColumnWidth;
}
if (!State.Stack.back().AlignColons)
@@ -898,12 +1027,17 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon)
return State.Stack.back().Indent;
+ if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
+ Style.BreakInheritanceList == FormatStyle::BILS_AfterColon)
+ return State.Stack.back().Indent;
if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
TT_InheritanceComma))
return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment))
return ContinuationIndent;
+ if (Current.is(TT_ProtoExtensionLSquare))
+ return State.Stack.back().Indent;
if (State.Stack.back().Indent == State.FirstIndent && PreviousNonComment &&
PreviousNonComment->isNot(tok::r_brace))
// Ensure that we fall back to the continuation indent width instead of
@@ -951,13 +1085,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
!Current.NextOperator ? 0 : State.Column;
- if (Current.is(TT_SelectorName)) {
+ if (Current.is(TT_SelectorName))
State.Stack.back().ObjCSelectorNameFound = true;
- if (Style.IndentWrappedFunctionNames) {
- State.Stack.back().Indent =
- State.FirstIndent + Style.ContinuationIndentWidth;
- }
- }
if (Current.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon) {
// Indent 2 from the column, so:
@@ -985,7 +1114,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
}
if (Current.is(TT_InheritanceColon))
State.Stack.back().Indent =
- State.FirstIndent + Style.ContinuationIndentWidth;
+ State.FirstIndent + Style.ConstructorInitializerIndentWidth;
if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
State.Stack.back().NestedBlockIndent =
State.Column + Current.ColumnWidth + 1;
@@ -1071,6 +1200,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
E = Current.FakeLParens.rend();
I != E; ++I) {
ParenState NewParenState = State.Stack.back();
+ NewParenState.Tok = nullptr;
NewParenState.ContainsLineBreak = false;
NewParenState.LastOperatorWrapped = true;
NewParenState.NoLineBreak =
@@ -1180,7 +1310,6 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
// void SomeFunction(vector< // break
// int> v);
// FIXME: We likely want to do this for more combinations of brackets.
- // Verify that it is wanted for ObjC, too.
if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
NewIndent = std::max(NewIndent, State.Stack.back().Indent);
LastSpace = std::max(LastSpace, State.Stack.back().Indent);
@@ -1191,9 +1320,20 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
Current.MatchingParen->getPreviousNonComment() &&
Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
+ // If ObjCBinPackProtocolList is unspecified, fall back to BinPackParameters
+ // for backwards compatibility.
+ bool ObjCBinPackProtocolList =
+ (Style.ObjCBinPackProtocolList == FormatStyle::BPS_Auto &&
+ Style.BinPackParameters) ||
+ Style.ObjCBinPackProtocolList == FormatStyle::BPS_Always;
+
+ bool BinPackDeclaration =
+ (State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) ||
+ (State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList);
+
AvoidBinPacking =
(Style.Language == FormatStyle::LK_JavaScript && EndsInComma) ||
- (State.Line->MustBeDeclaration && !Style.BinPackParameters) ||
+ (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
(!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
(Style.ExperimentalAutoDetectBinPacking &&
(Current.PackingKind == PPK_OnePerLine ||
@@ -1204,7 +1344,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
if (Style.ColumnLimit) {
// If this '[' opens an ObjC call, determine whether all parameters fit
// into one line and put one per line if they don't.
- if (getLengthToMatchingParen(Current) + State.Column >
+ if (getLengthToMatchingParen(Current, State.Stack) + State.Column >
getColumnLimit(State))
BreakBeforeParameter = true;
} else {
@@ -1235,10 +1375,13 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
(Current.is(TT_TemplateOpener) &&
State.Stack.back().ContainsUnwrappedBuilder));
State.Stack.push_back(
- ParenState(NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
+ ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1;
+ State.Stack.back().IsInsideObjCArrayLiteral =
+ Current.is(TT_ArrayInitializerLSquare) && Current.Previous &&
+ Current.Previous->is(tok::at);
}
void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
@@ -1251,9 +1394,34 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
if (State.Stack.size() > 1 &&
(Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
(Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
- State.NextToken->is(TT_TemplateCloser)))
+ State.NextToken->is(TT_TemplateCloser) ||
+ (Current.is(tok::greater) && Current.is(TT_DictLiteral))))
State.Stack.pop_back();
+ // Reevaluate whether ObjC message arguments fit into one line.
+ // If a receiver spans multiple lines, e.g.:
+ // [[object block:^{
+ // return 42;
+ // }] a:42 b:42];
+ // BreakBeforeParameter is calculated based on an incorrect assumption
+ // (it is checked whether the whole expression fits into one line without
+ // considering a line break inside a message receiver).
+ // We check whether arguements fit after receiver scope closer (into the same
+ // line).
+ if (State.Stack.back().BreakBeforeParameter && Current.MatchingParen &&
+ Current.MatchingParen->Previous) {
+ const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
+ if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
+ CurrentScopeOpener.MatchingParen) {
+ int NecessarySpaceInLine =
+ getLengthToMatchingParen(CurrentScopeOpener, State.Stack) +
+ CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
+ if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
+ Style.ColumnLimit)
+ State.Stack.back().BreakBeforeParameter = false;
+ }
+ }
+
if (Current.is(tok::r_square)) {
// If this ends the array subscript expr, reset the corresponding value.
const FormatToken *NextNonComment = Current.getNextNonComment();
@@ -1269,7 +1437,8 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
? Style.ObjCBlockIndentWidth
: Style.IndentWidth);
- State.Stack.push_back(ParenState(NewIndent, State.Stack.back().LastSpace,
+ State.Stack.push_back(ParenState(State.NextToken, NewIndent,
+ State.Stack.back().LastSpace,
/*AvoidBinPacking=*/true,
/*NoLineBreak=*/false));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
@@ -1293,14 +1462,32 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
const FormatToken &Current, LineState &State,
const FormatStyle &RawStringStyle, bool DryRun) {
unsigned StartColumn = State.Column - Current.ColumnWidth;
- auto Delimiter = *getRawStringDelimiter(Current.TokenText);
+ StringRef OldDelimiter = *getRawStringDelimiter(Current.TokenText);
+ StringRef NewDelimiter =
+ getCanonicalRawStringDelimiter(Style, RawStringStyle.Language);
+ if (NewDelimiter.empty() || OldDelimiter.empty())
+ NewDelimiter = OldDelimiter;
// 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();
+ unsigned OldPrefixSize = 3 + OldDelimiter.size();
+ unsigned OldSuffixSize = 2 + OldDelimiter.size();
+ // We create a virtual text environment which expects a null-terminated
+ // string, so we cannot use StringRef.
+ std::string RawText =
+ Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize);
+ if (NewDelimiter != OldDelimiter) {
+ // Don't update to the canonical delimiter 'deli' if ')deli"' occurs in the
+ // raw string.
+ std::string CanonicalDelimiterSuffix = (")" + NewDelimiter + "\"").str();
+ if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
+ NewDelimiter = OldDelimiter;
+ }
+
+ unsigned NewPrefixSize = 3 + NewDelimiter.size();
+ unsigned NewSuffixSize = 2 + NewDelimiter.size();
- // The first start column is the column the raw text starts.
- unsigned FirstStartColumn = StartColumn + PrefixSize;
+ // The first start column is the column the raw text starts after formatting.
+ unsigned FirstStartColumn = StartColumn + NewPrefixSize;
// 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:
@@ -1311,10 +1498,11 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
// 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;
+ bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] == '\n';
+ unsigned NextStartColumn =
+ ContentStartsOnNewline
+ ? State.Stack.back().NestedBlockIndent + Style.IndentWidth
+ : FirstStartColumn;
// The last start column is the column the raw string suffix starts if it is
// put on a newline.
@@ -1325,11 +1513,8 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
// - 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);
+ ? FirstStartColumn - NewPrefixSize
+ : State.Stack.back().NestedBlockIndent;
std::pair<tooling::Replacements, unsigned> Fixes = internal::reformat(
RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
@@ -1343,8 +1528,33 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
return 0;
}
if (!DryRun) {
+ if (NewDelimiter != OldDelimiter) {
+ // In 'R"delimiter(...', the delimiter starts 2 characters after the start
+ // of the token.
+ SourceLocation PrefixDelimiterStart =
+ Current.Tok.getLocation().getLocWithOffset(2);
+ auto PrefixErr = Whitespaces.addReplacement(tooling::Replacement(
+ SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
+ if (PrefixErr) {
+ llvm::errs()
+ << "Failed to update the prefix delimiter of a raw string: "
+ << llvm::toString(std::move(PrefixErr)) << "\n";
+ }
+ // In 'R"delimiter(...)delimiter"', the suffix delimiter starts at
+ // position length - 1 - |delimiter|.
+ SourceLocation SuffixDelimiterStart =
+ Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
+ 1 - OldDelimiter.size());
+ auto SuffixErr = Whitespaces.addReplacement(tooling::Replacement(
+ SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
+ if (SuffixErr) {
+ llvm::errs()
+ << "Failed to update the suffix delimiter of a raw string: "
+ << llvm::toString(std::move(SuffixErr)) << "\n";
+ }
+ }
SourceLocation OriginLoc =
- Current.Tok.getLocation().getLocWithOffset(PrefixSize);
+ Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
for (const tooling::Replacement &Fix : Fixes.first) {
auto Err = Whitespaces.addReplacement(tooling::Replacement(
SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
@@ -1357,8 +1567,14 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
}
unsigned RawLastLineEndColumn = getLastLineEndColumn(
*NewCode, FirstStartColumn, Style.TabWidth, Encoding);
- State.Column = RawLastLineEndColumn + SuffixSize;
- return Fixes.second;
+ State.Column = RawLastLineEndColumn + NewSuffixSize;
+ // Since we're updating the column to after the raw string literal here, we
+ // have to manually add the penalty for the prefix R"delim( over the column
+ // limit.
+ unsigned PrefixExcessCharacters =
+ StartColumn + NewPrefixSize > Style.ColumnLimit ?
+ StartColumn + NewPrefixSize - Style.ColumnLimit : 0;
+ return Fixes.second + PrefixExcessCharacters * Style.PenaltyExcessCharacter;
}
unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
@@ -1384,7 +1600,7 @@ unsigned ContinuationIndenter::handleEndOfLine(const FormatToken &Current,
// 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) {
+ if (RawStringStyle && !Current.Finalized) {
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
@@ -1430,6 +1646,26 @@ unsigned ContinuationIndenter::handleEndOfLine(const FormatToken &Current,
return Penalty;
}
+// Returns the enclosing function name of a token, or the empty string if not
+// found.
+static StringRef getEnclosingFunctionName(const FormatToken &Current) {
+ // Look for: 'function(' or 'function<templates>(' before Current.
+ auto Tok = Current.getPreviousNonComment();
+ if (!Tok || !Tok->is(tok::l_paren))
+ return "";
+ Tok = Tok->getPreviousNonComment();
+ if (!Tok)
+ return "";
+ if (Tok->is(TT_TemplateCloser)) {
+ Tok = Tok->MatchingParen;
+ if (Tok)
+ Tok = Tok->getPreviousNonComment();
+ }
+ if (!Tok || !Tok->is(tok::identifier))
+ return "";
+ return Tok->TokenText;
+}
+
llvm::Optional<FormatStyle>
ContinuationIndenter::getRawStringStyle(const FormatToken &Current,
const LineState &State) {
@@ -1438,7 +1674,10 @@ ContinuationIndenter::getRawStringStyle(const FormatToken &Current,
auto Delimiter = getRawStringDelimiter(Current.TokenText);
if (!Delimiter)
return None;
- auto RawStringStyle = RawStringFormats.get(*Delimiter);
+ auto RawStringStyle = RawStringFormats.getDelimiterStyle(*Delimiter);
+ if (!RawStringStyle && Delimiter->empty())
+ RawStringStyle = RawStringFormats.getEnclosingFunctionStyle(
+ getEnclosingFunctionName(Current));
if (!RawStringStyle)
return None;
RawStringStyle->ColumnLimit = getColumnLimit(State);
@@ -1468,6 +1707,11 @@ std::unique_ptr<BreakableToken> ContinuationIndenter::createBreakableToken(
// likely want to terminate the string before any line breaking is done.
if (Current.IsUnterminatedLiteral)
return nullptr;
+ // Don't break string literals inside Objective-C array literals (doing so
+ // raises the warning -Wobjc-string-concatenation).
+ if (State.Stack.back().IsInsideObjCArrayLiteral) {
+ return nullptr;
+ }
StringRef Text = Current.TokenText;
StringRef Prefix;
@@ -1482,9 +1726,16 @@ std::unique_ptr<BreakableToken> ContinuationIndenter::createBreakableToken(
Text.startswith(Prefix = "u8\"") ||
Text.startswith(Prefix = "L\""))) ||
(Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")"))) {
+ // We need this to address the case where there is an unbreakable tail
+ // only if certain other formatting decisions have been taken. The
+ // UnbreakableTailLength of Current is an overapproximation is that case
+ // and we need to be correct here.
+ unsigned UnbreakableTailLength = (State.NextToken && canBreak(State))
+ ? 0
+ : Current.UnbreakableTailLength;
return llvm::make_unique<BreakableStringLiteral>(
- Current, StartColumn, Prefix, Postfix, State.Line->InPPDirective,
- Encoding, Style);
+ Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
+ State.Line->InPPDirective, Encoding, Style);
}
} else if (Current.is(TT_BlockComment)) {
if (!Style.ReflowComments ||
@@ -1558,13 +1809,14 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
if (!DryRun)
Token->adaptStartOfLine(0, Whitespaces);
+ unsigned ContentIndent = 0;
unsigned Penalty = 0;
- DEBUG(llvm::dbgs() << "Breaking protruding token at column " << StartColumn
- << ".\n");
+ LLVM_DEBUG(llvm::dbgs() << "Breaking protruding token at column "
+ << StartColumn << ".\n");
for (unsigned LineIndex = 0, EndIndex = Token->getLineCount();
LineIndex != EndIndex; ++LineIndex) {
- DEBUG(llvm::dbgs() << " Line: " << LineIndex << " (Reflow: " << Reflow
- << ")\n");
+ LLVM_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
@@ -1572,11 +1824,11 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
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");
+ LLVM_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
@@ -1591,7 +1843,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// The last line's penalty is handled in addNextStateToQueue().
Penalty += Style.PenaltyExcessCharacter *
(ContentStartColumn + RemainingTokenColumns - ColumnLimit);
- DEBUG(llvm::dbgs() << " No break opportunity.\n");
+ LLVM_DEBUG(llvm::dbgs() << " No break opportunity.\n");
break;
}
assert(Split.first != 0);
@@ -1618,7 +1870,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// ^--------------- to next split columns
unsigned ToSplitColumns = Token->getRangeLength(
LineIndex, TailOffset, Split.first, ContentStartColumn);
- DEBUG(llvm::dbgs() << " ToSplit: " << ToSplitColumns << "\n");
+ LLVM_DEBUG(llvm::dbgs() << " ToSplit: " << ToSplitColumns << "\n");
BreakableToken::Split NextSplit = Token->getSplit(
LineIndex, TailOffset + Split.first + Split.second, ColumnLimit,
@@ -1638,9 +1890,10 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// unbreakable sequence.
ToNextSplitColumns =
Token->getLengthAfterCompression(ToNextSplitColumns, Split);
- DEBUG(llvm::dbgs() << " ContentStartColumn: " << ContentStartColumn
- << "\n");
- DEBUG(llvm::dbgs() << " ToNextSplit: " << ToNextSplitColumns << "\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << " ContentStartColumn: " << ContentStartColumn << "\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << " ToNextSplit: " << ToNextSplitColumns << "\n");
// If the whitespace compression makes us fit, continue on the current
// line.
bool ContinueOnLine =
@@ -1652,16 +1905,16 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
ExcessCharactersPenalty =
(ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
Style.PenaltyExcessCharacter;
- DEBUG(llvm::dbgs()
- << " Penalty excess: " << ExcessCharactersPenalty
- << "\n break : " << NewBreakPenalty << "\n");
+ LLVM_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");
+ LLVM_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;
@@ -1677,12 +1930,29 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
continue;
}
}
- DEBUG(llvm::dbgs() << " Breaking...\n");
- ContentStartColumn =
- Token->getContentStartColumn(LineIndex, /*Break=*/true);
+ LLVM_DEBUG(llvm::dbgs() << " Breaking...\n");
+ // Update the ContentIndent only if the current line was not reflown with
+ // the previous line, since in that case the previous line should still
+ // determine the ContentIndent. Also never intent the last line.
+ if (!Reflow)
+ ContentIndent = Token->getContentIndent(LineIndex);
+ LLVM_DEBUG(llvm::dbgs()
+ << " ContentIndent: " << ContentIndent << "\n");
+ ContentStartColumn = ContentIndent + Token->getContentStartColumn(
+ LineIndex, /*Break=*/true);
+
unsigned NewRemainingTokenColumns = Token->getRemainingLength(
LineIndex, TailOffset + Split.first + Split.second,
ContentStartColumn);
+ if (NewRemainingTokenColumns == 0) {
+ // No content to indent.
+ ContentIndent = 0;
+ ContentStartColumn =
+ Token->getContentStartColumn(LineIndex, /*Break=*/true);
+ 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
@@ -1693,10 +1963,11 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
}
assert(NewRemainingTokenColumns < RemainingTokenColumns);
- DEBUG(llvm::dbgs() << " Breaking at: " << TailOffset + Split.first
- << ", " << Split.second << "\n");
+ LLVM_DEBUG(llvm::dbgs() << " Breaking at: " << TailOffset + Split.first
+ << ", " << Split.second << "\n");
if (!DryRun)
- Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces);
+ Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
+ Whitespaces);
Penalty += NewBreakPenalty;
TailOffset += Split.first + Split.second;
@@ -1732,11 +2003,12 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// the next logical line.
BreakableToken::Split SplitBeforeNext =
Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
- DEBUG(llvm::dbgs() << " Size of reflown text: " << ContentStartColumn
- << "\n Potential reflow split: ");
+ LLVM_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");
+ LLVM_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.
@@ -1744,11 +2016,12 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
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");
+ LLVM_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
@@ -1757,7 +2030,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
ContentStartColumn, CommentPragmasRegex);
if (Split.first == StringRef::npos) {
- DEBUG(llvm::dbgs() << " Did not find later break\n");
+ LLVM_DEBUG(llvm::dbgs() << " Did not find later break\n");
Reflow = false;
} else {
// Check whether the first split point gets us below the column
@@ -1766,9 +2039,9 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
unsigned ToSplitColumns = Token->getRangeLength(
NextLineIndex, TailOffset, Split.first, ContentStartColumn);
if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
- DEBUG(llvm::dbgs() << " Next split protrudes, need: "
- << (ContentStartColumn + ToSplitColumns)
- << ", space: " << ColumnLimit);
+ LLVM_DEBUG(llvm::dbgs() << " Next split protrudes, need: "
+ << (ContentStartColumn + ToSplitColumns)
+ << ", space: " << ColumnLimit);
unsigned ExcessCharactersPenalty =
(ContentStartColumn + ToSplitColumns - ColumnLimit) *
Style.PenaltyExcessCharacter;
@@ -1779,7 +2052,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
}
}
} else {
- DEBUG(llvm::dbgs() << "not found.\n");
+ LLVM_DEBUG(llvm::dbgs() << "not found.\n");
}
}
if (!Reflow) {
@@ -1821,7 +2094,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
BreakableToken::Split SplitAfterLastLine =
Token->getSplitAfterLastLine(TailOffset);
if (SplitAfterLastLine.first != StringRef::npos) {
- DEBUG(llvm::dbgs() << "Replacing whitespace after last line.\n");
+ LLVM_DEBUG(llvm::dbgs() << "Replacing whitespace after last line.\n");
if (!DryRun)
Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
Whitespaces);
@@ -1875,7 +2148,7 @@ bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {
if (Current.getNextNonComment() &&
Current.getNextNonComment()->isStringLiteral())
return true; // Implicit concatenation.
- if (Style.ColumnLimit != 0 &&
+ if (Style.ColumnLimit != 0 && Style.BreakStringLiterals &&
State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
Style.ColumnLimit)
return true; // String will be split.
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
index ded7bfab4267..fde89db864b1 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements an indenter that manages the indentation of
+/// This file implements an indenter that manages the indentation of
/// continuations.
///
//===----------------------------------------------------------------------===//
@@ -38,15 +38,19 @@ class WhitespaceManager;
struct RawStringFormatStyleManager {
llvm::StringMap<FormatStyle> DelimiterStyle;
+ llvm::StringMap<FormatStyle> EnclosingFunctionStyle;
RawStringFormatStyleManager(const FormatStyle &CodeStyle);
- llvm::Optional<FormatStyle> get(StringRef Delimiter) const;
+ llvm::Optional<FormatStyle> getDelimiterStyle(StringRef Delimiter) const;
+
+ llvm::Optional<FormatStyle>
+ getEnclosingFunctionStyle(StringRef EnclosingFunction) const;
};
class ContinuationIndenter {
public:
- /// \brief Constructs a \c ContinuationIndenter to format \p Line starting in
+ /// Constructs a \c ContinuationIndenter to format \p Line starting in
/// column \p FirstIndent.
ContinuationIndenter(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
@@ -55,7 +59,7 @@ public:
encoding::Encoding Encoding,
bool BinPackInconclusiveFunctions);
- /// \brief Get the initial state, i.e. the state after placing \p Line's
+ /// Get the initial state, i.e. the state after placing \p Line's
/// 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.
@@ -64,13 +68,13 @@ public:
// FIXME: canBreak and mustBreak aren't strictly indentation-related. Find a
// better home.
- /// \brief Returns \c true, if a line break after \p State is allowed.
+ /// Returns \c true, if a line break after \p State is allowed.
bool canBreak(const LineState &State);
- /// \brief Returns \c true, if a line break after \p State is mandatory.
+ /// Returns \c true, if a line break after \p State is mandatory.
bool mustBreak(const LineState &State);
- /// \brief Appends the next token to \p State and updates information
+ /// Appends the next token to \p State and updates information
/// necessary for indentation.
///
/// Puts the token on the current line if \p Newline is \c false and adds a
@@ -81,46 +85,46 @@ public:
unsigned addTokenToState(LineState &State, bool Newline, bool DryRun,
unsigned ExtraSpaces = 0);
- /// \brief Get the column limit for this line. This is the style's column
+ /// Get the column limit for this line. This is the style's column
/// limit, potentially reduced for preprocessor definitions.
unsigned getColumnLimit(const LineState &State) const;
private:
- /// \brief Mark the next token as consumed in \p State and modify its stacks
+ /// Mark the next token as consumed in \p State and modify its stacks
/// accordingly.
unsigned moveStateToNextToken(LineState &State, bool DryRun, bool Newline);
- /// \brief Update 'State' according to the next token's fake left parentheses.
+ /// Update 'State' according to the next token's fake left parentheses.
void moveStatePastFakeLParens(LineState &State, bool Newline);
- /// \brief Update 'State' according to the next token's fake r_parens.
+ /// Update 'State' according to the next token's fake r_parens.
void moveStatePastFakeRParens(LineState &State);
- /// \brief Update 'State' according to the next token being one of "(<{[".
+ /// Update 'State' according to the next token being one of "(<{[".
void moveStatePastScopeOpener(LineState &State, bool Newline);
- /// \brief Update 'State' according to the next token being one of ")>}]".
+ /// Update 'State' according to the next token being one of ")>}]".
void moveStatePastScopeCloser(LineState &State);
- /// \brief Update 'State' with the next token opening a nested block.
+ /// Update 'State' with the next token opening a nested block.
void moveStateToNewBlock(LineState &State);
- /// \brief Reformats a raw string literal.
- ///
+ /// 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
+ /// 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,
+ /// 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
+ /// If the current token sticks out over the end of the line, break
/// it if possible.
///
/// \returns A pair (penalty, exceeded), where penalty is the extra penalty
@@ -143,13 +147,13 @@ private:
bool AllowBreak, bool DryRun,
bool Strict);
- /// \brief Returns the \c BreakableToken starting at \p Current, or nullptr
+ /// 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
+ /// Appends the next token to \p State and updates information
/// necessary for indentation.
///
/// Puts the token on the current line.
@@ -159,7 +163,7 @@ private:
void addTokenOnCurrentLine(LineState &State, bool DryRun,
unsigned ExtraSpaces);
- /// \brief Appends the next token to \p State and updates information
+ /// Appends the next token to \p State and updates information
/// necessary for indentation.
///
/// Adds a line break and necessary indentation.
@@ -168,17 +172,17 @@ private:
/// \c Replacement.
unsigned addTokenOnNewLine(LineState &State, bool DryRun);
- /// \brief Calculate the new column for a line wrap before the next token.
+ /// Calculate the new column for a line wrap before the next token.
unsigned getNewLineColumn(const LineState &State);
- /// \brief Adds a multiline token to the \p State.
+ /// Adds a multiline token to the \p State.
///
/// \returns Extra penalty for the first line of the literal: last line is
/// handled in \c addNextStateToQueue, and the penalty for other lines doesn't
/// matter, as we don't change them.
unsigned addMultilineToken(const FormatToken &Current, LineState &State);
- /// \brief Returns \c true if the next token starts a multiline string
+ /// Returns \c true if the next token starts a multiline string
/// literal.
///
/// This includes implicitly concatenated strings, strings that will be broken
@@ -196,124 +200,136 @@ private:
};
struct ParenState {
- ParenState(unsigned Indent, unsigned LastSpace, bool AvoidBinPacking,
- bool NoLineBreak)
- : Indent(Indent), LastSpace(LastSpace), NestedBlockIndent(Indent),
- BreakBeforeClosingBrace(false), AvoidBinPacking(AvoidBinPacking),
- BreakBeforeParameter(false), NoLineBreak(NoLineBreak),
- NoLineBreakInOperand(false), LastOperatorWrapped(true),
- ContainsLineBreak(false), ContainsUnwrappedBuilder(false),
- AlignColons(true), ObjCSelectorNameFound(false),
- HasMultipleNestedBlocks(false), NestedBlockInlined(false) {}
-
- /// \brief The position to which a specific parenthesis level needs to be
+ ParenState(const FormatToken *Tok, unsigned Indent, unsigned LastSpace,
+ bool AvoidBinPacking, bool NoLineBreak)
+ : Tok(Tok), Indent(Indent), LastSpace(LastSpace),
+ NestedBlockIndent(Indent), BreakBeforeClosingBrace(false),
+ AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
+ NoLineBreak(NoLineBreak), NoLineBreakInOperand(false),
+ LastOperatorWrapped(true), ContainsLineBreak(false),
+ ContainsUnwrappedBuilder(false), AlignColons(true),
+ ObjCSelectorNameFound(false), HasMultipleNestedBlocks(false),
+ NestedBlockInlined(false), IsInsideObjCArrayLiteral(false) {}
+
+ /// \brief The token opening this parenthesis level, or nullptr if this level
+ /// is opened by fake parenthesis.
+ ///
+ /// Not considered for memoization as it will always have the same value at
+ /// the same token.
+ const FormatToken *Tok;
+
+ /// The position to which a specific parenthesis level needs to be
/// indented.
unsigned Indent;
- /// \brief The position of the last space on each level.
+ /// The position of the last space on each level.
///
/// Used e.g. to break like:
/// functionCall(Parameter, otherCall(
/// OtherParameter));
unsigned LastSpace;
- /// \brief If a block relative to this parenthesis level gets wrapped, indent
+ /// If a block relative to this parenthesis level gets wrapped, indent
/// it this much.
unsigned NestedBlockIndent;
- /// \brief The position the first "<<" operator encountered on each level.
+ /// The position the first "<<" operator encountered on each level.
///
/// Used to align "<<" operators. 0 if no such operator has been encountered
/// on a level.
unsigned FirstLessLess = 0;
- /// \brief The column of a \c ? in a conditional expression;
+ /// The column of a \c ? in a conditional expression;
unsigned QuestionColumn = 0;
- /// \brief The position of the colon in an ObjC method declaration/call.
+ /// The position of the colon in an ObjC method declaration/call.
unsigned ColonPos = 0;
- /// \brief The start of the most recent function in a builder-type call.
+ /// The start of the most recent function in a builder-type call.
unsigned StartOfFunctionCall = 0;
- /// \brief Contains the start of array subscript expressions, so that they
+ /// Contains the start of array subscript expressions, so that they
/// can be aligned.
unsigned StartOfArraySubscripts = 0;
- /// \brief If a nested name specifier was broken over multiple lines, this
+ /// If a nested name specifier was broken over multiple lines, this
/// contains the start column of the second line. Otherwise 0.
unsigned NestedNameSpecifierContinuation = 0;
- /// \brief If a call expression was broken over multiple lines, this
+ /// If a call expression was broken over multiple lines, this
/// contains the start column of the second line. Otherwise 0.
unsigned CallContinuation = 0;
- /// \brief The column of the first variable name in a variable declaration.
+ /// The column of the first variable name in a variable declaration.
///
/// Used to align further variables if necessary.
unsigned VariablePos = 0;
- /// \brief Whether a newline needs to be inserted before the block's closing
+ /// Whether a newline needs to be inserted before the block's closing
/// brace.
///
/// We only want to insert a newline before the closing brace if there also
/// was a newline after the beginning left brace.
bool BreakBeforeClosingBrace : 1;
- /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
+ /// Avoid bin packing, i.e. multiple parameters/elements on multiple
/// lines, in this context.
bool AvoidBinPacking : 1;
- /// \brief Break after the next comma (or all the commas in this context if
+ /// Break after the next comma (or all the commas in this context if
/// \c AvoidBinPacking is \c true).
bool BreakBeforeParameter : 1;
- /// \brief Line breaking in this context would break a formatting rule.
+ /// Line breaking in this context would break a formatting rule.
bool NoLineBreak : 1;
- /// \brief Same as \c NoLineBreak, but is restricted until the end of the
+ /// Same as \c NoLineBreak, but is restricted until the end of the
/// operand (including the next ",").
bool NoLineBreakInOperand : 1;
- /// \brief True if the last binary operator on this level was wrapped to the
+ /// True if the last binary operator on this level was wrapped to the
/// next line.
bool LastOperatorWrapped : 1;
- /// \brief \c true if this \c ParenState already contains a line-break.
+ /// \c true if this \c ParenState already contains a line-break.
///
/// The first line break in a certain \c ParenState causes extra penalty so
/// that clang-format prefers similar breaks, i.e. breaks in the same
/// parenthesis.
bool ContainsLineBreak : 1;
- /// \brief \c true if this \c ParenState contains multiple segments of a
+ /// \c true if this \c ParenState contains multiple segments of a
/// builder-type call on one line.
bool ContainsUnwrappedBuilder : 1;
- /// \brief \c true if the colons of the curren ObjC method expression should
+ /// \c true if the colons of the curren ObjC method expression should
/// be aligned.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
bool AlignColons : 1;
- /// \brief \c true if at least one selector name was found in the current
+ /// \c true if at least one selector name was found in the current
/// ObjC method expression.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
bool ObjCSelectorNameFound : 1;
- /// \brief \c true if there are multiple nested blocks inside these parens.
+ /// \c true if there are multiple nested blocks inside these parens.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
bool HasMultipleNestedBlocks : 1;
- // \brief The start of a nested block (e.g. lambda introducer in C++ or
- // "function" in JavaScript) is not wrapped to a new line.
+ /// The start of a nested block (e.g. lambda introducer in C++ or
+ /// "function" in JavaScript) is not wrapped to a new line.
bool NestedBlockInlined : 1;
+ /// \c true if the current \c ParenState represents an Objective-C
+ /// array literal.
+ bool IsInsideObjCArrayLiteral : 1;
+
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
return Indent < Other.Indent;
@@ -355,37 +371,37 @@ struct ParenState {
}
};
-/// \brief The current state when indenting a unwrapped line.
+/// The current state when indenting a unwrapped line.
///
/// As the indenting tries different combinations this is copied by value.
struct LineState {
- /// \brief The number of used columns in the current line.
+ /// The number of used columns in the current line.
unsigned Column;
- /// \brief The token that needs to be next formatted.
+ /// The token that needs to be next formatted.
FormatToken *NextToken;
- /// \brief \c true if this line contains a continued for-loop section.
+ /// \c true if this line contains a continued for-loop section.
bool LineContainsContinuedForLoopSection;
- /// \brief \c true if \p NextToken should not continue this line.
+ /// \c true if \p NextToken should not continue this line.
bool NoContinuation;
- /// \brief The \c NestingLevel at the start of this line.
+ /// The \c NestingLevel at the start of this line.
unsigned StartOfLineLevel;
- /// \brief The lowest \c NestingLevel on the current line.
+ /// The lowest \c NestingLevel on the current line.
unsigned LowestLevelOnLine;
- /// \brief The start column of the string literal, if we're in a string
+ /// The start column of the string literal, if we're in a string
/// literal sequence, 0 otherwise.
unsigned StartOfStringLiteral;
- /// \brief A stack keeping track of properties applying to parenthesis
+ /// A stack keeping track of properties applying to parenthesis
/// levels.
std::vector<ParenState> Stack;
- /// \brief Ignore the stack of \c ParenStates for state comparison.
+ /// Ignore the stack of \c ParenStates for state comparison.
///
/// In long and deeply nested unwrapped lines, the current algorithm can
/// be insufficient for finding the best formatting with a reasonable amount
@@ -400,15 +416,15 @@ struct LineState {
/// FIXME: Come up with a better algorithm instead.
bool IgnoreStackForComparison;
- /// \brief The indent of the first token.
+ /// The indent of the first token.
unsigned FirstIndent;
- /// \brief The line that is being formatted.
+ /// The line that is being formatted.
///
/// Does not need to be considered for memoization because it doesn't change.
const AnnotatedLine *Line;
- /// \brief Comparison operator to be able to used \c LineState in \c map.
+ /// Comparison operator to be able to used \c LineState in \c map.
bool operator<(const LineState &Other) const {
if (NextToken != Other.NextToken)
return NextToken < Other.NextToken;
diff --git a/contrib/llvm/tools/clang/lib/Format/Encoding.h b/contrib/llvm/tools/clang/lib/Format/Encoding.h
index 3339597b4edd..4c877e7e49d5 100644
--- a/contrib/llvm/tools/clang/lib/Format/Encoding.h
+++ b/contrib/llvm/tools/clang/lib/Format/Encoding.h
@@ -1,4 +1,4 @@
-//===--- Encoding.h - Format C++ code -------------------------------------===//
+//===--- Encoding.h - Format C++ code ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Contains functions for text encoding manipulation. Supports UTF-8,
+/// Contains functions for text encoding manipulation. Supports UTF-8,
/// 8-bit encodings and escape sequences in C++ string literals.
///
//===----------------------------------------------------------------------===//
@@ -30,7 +30,7 @@ enum Encoding {
Encoding_Unknown // We treat all other encodings as 8-bit encodings.
};
-/// \brief Detects encoding of the Text. If the Text can be decoded using UTF-8,
+/// Detects encoding of the Text. If the Text can be decoded using UTF-8,
/// it is considered UTF8, otherwise we treat it as some 8-bit encoding.
inline Encoding detectEncoding(StringRef Text) {
const llvm::UTF8 *Ptr = reinterpret_cast<const llvm::UTF8 *>(Text.begin());
@@ -40,7 +40,7 @@ inline Encoding detectEncoding(StringRef Text) {
return Encoding_Unknown;
}
-/// \brief Returns the number of columns required to display the \p Text on a
+/// Returns the number of columns required to display the \p Text on a
/// generic Unicode-capable terminal. Text is assumed to use the specified
/// \p Encoding.
inline unsigned columnWidth(StringRef Text, Encoding Encoding) {
@@ -56,7 +56,7 @@ inline unsigned columnWidth(StringRef Text, Encoding Encoding) {
return Text.size();
}
-/// \brief Returns the number of columns required to display the \p Text,
+/// Returns the number of columns required to display the \p Text,
/// starting from the \p StartColumn on a terminal with the \p TabWidth. The
/// text is assumed to use the specified \p Encoding.
inline unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn,
@@ -73,7 +73,7 @@ inline unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn,
}
}
-/// \brief Gets the number of bytes in a sequence representing a single
+/// Gets the number of bytes in a sequence representing a single
/// codepoint and starting with FirstChar in the specified Encoding.
inline unsigned getCodePointNumBytes(char FirstChar, Encoding Encoding) {
switch (Encoding) {
@@ -91,7 +91,7 @@ inline bool isHexDigit(char c) {
('A' <= c && c <= 'F');
}
-/// \brief Gets the length of an escape sequence inside a C++ string literal.
+/// Gets the length of an escape sequence inside a C++ string literal.
/// Text should span from the beginning of the escape sequence (starting with a
/// backslash) to the end of the string literal.
inline unsigned getEscapeSequenceLength(StringRef Text) {
diff --git a/contrib/llvm/tools/clang/lib/Format/Format.cpp b/contrib/llvm/tools/clang/lib/Format/Format.cpp
index 217c6729ee39..9a2da69e89b1 100644
--- a/contrib/llvm/tools/clang/lib/Format/Format.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/Format.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements functions declared in Format.h. This will be
+/// This file implements functions declared in Format.h. This will be
/// split into separate files as we go.
///
//===----------------------------------------------------------------------===//
@@ -31,7 +31,9 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Inclusions/HeaderIncludes.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
@@ -39,13 +41,14 @@
#include "llvm/Support/YAMLTraits.h"
#include <algorithm>
#include <memory>
+#include <mutex>
#include <string>
+#include <unordered_map>
#define DEBUG_TYPE "format-formatter"
using clang::format::FormatStyle;
-LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory)
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
namespace llvm {
@@ -104,6 +107,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
+ static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
+ IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
+ IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
+ IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
IO.enumCase(Value, "All", FormatStyle::BOS_All);
@@ -138,6 +149,16 @@ struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::BreakInheritanceListStyle &Value) {
+ IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
+ IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
+ IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
@@ -158,6 +179,19 @@ struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
+ static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value) {
+ IO.enumCase(Value, "No", FormatStyle::BTDS_No);
+ IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
+ IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
+ IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
static void
enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
@@ -326,8 +360,19 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
+
+ bool BreakBeforeInheritanceComma = false;
IO.mapOptional("BreakBeforeInheritanceComma",
- Style.BreakBeforeInheritanceComma);
+ BreakBeforeInheritanceComma);
+ IO.mapOptional("BreakInheritanceList",
+ Style.BreakInheritanceList);
+ // If BreakBeforeInheritanceComma was specified but
+ // BreakInheritance was not, initialize the latter from the
+ // former for backwards compatibility.
+ if (BreakBeforeInheritanceComma &&
+ Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
+ Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
+
IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators);
@@ -361,9 +406,9 @@ 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("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
+ IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
+ IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
IO.mapOptional("IndentWidth", Style.IndentWidth);
@@ -377,6 +422,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
+ IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
IO.mapOptional("ObjCSpaceBeforeProtocolList",
@@ -388,6 +434,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PenaltyBreakFirstLessLess",
Style.PenaltyBreakFirstLessLess);
IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
+ IO.mapOptional("PenaltyBreakTemplateDeclaration",
+ Style.PenaltyBreakTemplateDeclaration);
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
@@ -401,7 +449,15 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpaceAfterTemplateKeyword);
IO.mapOptional("SpaceBeforeAssignmentOperators",
Style.SpaceBeforeAssignmentOperators);
+ IO.mapOptional("SpaceBeforeCpp11BracedList",
+ Style.SpaceBeforeCpp11BracedList);
+ IO.mapOptional("SpaceBeforeCtorInitializerColon",
+ Style.SpaceBeforeCtorInitializerColon);
+ IO.mapOptional("SpaceBeforeInheritanceColon",
+ Style.SpaceBeforeInheritanceColon);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
+ IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
+ Style.SpaceBeforeRangeBasedForLoopColon);
IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
@@ -438,25 +494,12 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
}
};
-template <> struct MappingTraits<FormatStyle::IncludeCategory> {
- static void mapping(IO &IO, FormatStyle::IncludeCategory &Category) {
- IO.mapOptional("Regex", Category.Regex);
- IO.mapOptional("Priority", Category.Priority);
- }
-};
-
-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("Delimiters", Format.Delimiters);
+ IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
+ IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
}
};
@@ -493,7 +536,7 @@ namespace clang {
namespace format {
const std::error_category &getParseCategory() {
- static ParseErrorCategory C;
+ static const ParseErrorCategory C{};
return C;
}
std::error_code make_error_code(ParseError e) {
@@ -593,7 +636,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
- LLVMStyle.AlwaysBreakTemplateDeclarations = false;
+ LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
LLVMStyle.BinPackArguments = true;
LLVMStyle.BinPackParameters = true;
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
@@ -604,7 +647,7 @@ FormatStyle getLLVMStyle() {
false, false, true, true, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
- LLVMStyle.BreakBeforeInheritanceComma = false;
+ LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.ColumnLimit = 80;
LLVMStyle.CommentPragmas = "^ IWYU pragma:";
@@ -619,11 +662,12 @@ FormatStyle getLLVMStyle() {
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
- LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2},
- {"^(<|\"(gtest|gmock|isl|json)/)", 3},
- {".*", 1}};
- LLVMStyle.IncludeIsMainRegex = "(Test)?$";
- LLVMStyle.IncludeBlocks = FormatStyle::IBS_Preserve;
+ LLVMStyle.IncludeStyle.IncludeCategories = {
+ {"^\"(llvm|llvm-c|clang|clang-c)/", 2},
+ {"^(<|\"(gtest|gmock|isl|json)/)", 3},
+ {".*", 1}};
+ LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
+ LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
LLVMStyle.IndentWrappedFunctionNames = false;
@@ -634,6 +678,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.MaxEmptyLinesToKeep = 1;
LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
+ LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
LLVMStyle.ObjCBlockIndentWidth = 2;
LLVMStyle.ObjCSpaceAfterProperty = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
@@ -641,7 +686,6 @@ 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;
@@ -650,8 +694,12 @@ FormatStyle getLLVMStyle() {
LLVMStyle.SpacesInCStyleCastParentheses = false;
LLVMStyle.SpaceAfterCStyleCast = false;
LLVMStyle.SpaceAfterTemplateKeyword = true;
+ LLVMStyle.SpaceBeforeCtorInitializerColon = true;
+ LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
+ LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
LLVMStyle.SpaceBeforeAssignmentOperators = true;
+ LLVMStyle.SpaceBeforeCpp11BracedList = false;
LLVMStyle.SpacesInAngles = false;
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
@@ -661,6 +709,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.PenaltyExcessCharacter = 1000000;
LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
+ LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
LLVMStyle.DisableFormat = false;
LLVMStyle.SortIncludes = true;
@@ -673,6 +722,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
if (Language == FormatStyle::LK_TextProto) {
FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
GoogleStyle.Language = FormatStyle::LK_TextProto;
+
return GoogleStyle;
}
@@ -684,17 +734,59 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
GoogleStyle.AllowShortLoopsOnASingleLine = true;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
- GoogleStyle.AlwaysBreakTemplateDeclarations = true;
+ GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
GoogleStyle.DerivePointerAlignment = true;
- GoogleStyle.IncludeCategories = {
+ GoogleStyle.IncludeStyle.IncludeCategories = {
{"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
- GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
+ GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
GoogleStyle.IndentCaseLabels = true;
GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
+ GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
GoogleStyle.ObjCSpaceAfterProperty = false;
- GoogleStyle.ObjCSpaceBeforeProtocolList = false;
+ GoogleStyle.ObjCSpaceBeforeProtocolList = true;
GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
+ GoogleStyle.RawStringFormats = {
+ {
+ FormatStyle::LK_Cpp,
+ /*Delimiters=*/
+ {
+ "cc",
+ "CC",
+ "cpp",
+ "Cpp",
+ "CPP",
+ "c++",
+ "C++",
+ },
+ /*EnclosingFunctionNames=*/
+ {},
+ /*CanonicalDelimiter=*/"",
+ /*BasedOnStyle=*/"google",
+ },
+ {
+ FormatStyle::LK_TextProto,
+ /*Delimiters=*/
+ {
+ "pb",
+ "PB",
+ "proto",
+ "PROTO",
+ },
+ /*EnclosingFunctionNames=*/
+ {
+ "EqualsProto",
+ "EquivToProto",
+ "PARSE_PARTIAL_TEXT_PROTO",
+ "PARSE_TEST_PROTO",
+ "PARSE_TEXT_PROTO",
+ "ParseTextOrDie",
+ "ParseTextProtoOrDie",
+ },
+ /*CanonicalDelimiter=*/"",
+ /*BasedOnStyle=*/"google",
+ },
+ };
GoogleStyle.SpacesBeforeTrailingComments = 2;
GoogleStyle.Standard = FormatStyle::LS_Auto;
@@ -718,10 +810,9 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.BreakBeforeTernaryOperators = false;
- // taze:, triple slash directives (`/// <...`), @tag followed by { for a lot
- // of JSDoc tags, and @see, which is commonly followed by overlong URLs.
- GoogleStyle.CommentPragmas =
- "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)";
+ // taze:, triple slash directives (`/// <...`), @see, which is commonly
+ // followed by overlong URLs.
+ GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|@see)";
GoogleStyle.MaxEmptyLinesToKeep = 3;
GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
GoogleStyle.SpacesInContainerLiterals = false;
@@ -729,8 +820,17 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.JavaScriptWrapImports = false;
} else if (Language == FormatStyle::LK_Proto) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.SpacesInContainerLiterals = false;
+ GoogleStyle.Cpp11BracedListStyle = false;
+ // This affects protocol buffer options specifications and text protos.
+ // Text protos are currently mostly formatted inside C++ raw string literals
+ // and often the current breaking behavior of string literals is not
+ // beneficial there. Investigate turning this on once proper string reflow
+ // has been implemented.
+ GoogleStyle.BreakStringLiterals = false;
} else if (Language == FormatStyle::LK_ObjC) {
+ GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.ColumnLimit = 100;
}
@@ -767,12 +867,12 @@ FormatStyle getMozillaStyle() {
MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
FormatStyle::DRTBS_TopLevel;
- MozillaStyle.AlwaysBreakTemplateDeclarations = true;
+ MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
MozillaStyle.BinPackParameters = false;
MozillaStyle.BinPackArguments = false;
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
- MozillaStyle.BreakBeforeInheritanceComma = true;
+ MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
MozillaStyle.ConstructorInitializerIndentWidth = 2;
MozillaStyle.ContinuationIndentWidth = 2;
MozillaStyle.Cpp11BracedListStyle = false;
@@ -803,6 +903,7 @@ FormatStyle getWebKitStyle() {
Style.ObjCBlockIndentWidth = 4;
Style.ObjCSpaceAfterProperty = true;
Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.SpaceBeforeCpp11BracedList = true;
return Style;
}
@@ -859,7 +960,7 @@ std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
assert(Language != FormatStyle::LK_None);
if (Text.trim().empty())
return make_error_code(ParseError::Error);
-
+ Style->StyleSet.Clear();
std::vector<FormatStyle> Styles;
llvm::yaml::Input Input(Text);
// DocumentListTraits<vector<FormatStyle>> uses the context to get default
@@ -878,9 +979,9 @@ std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
// Ensure that each language is configured at most once.
for (unsigned j = 0; j < i; ++j) {
if (Styles[i].Language == Styles[j].Language) {
- DEBUG(llvm::dbgs()
- << "Duplicate languages in the config file on positions " << j
- << " and " << i << "\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << "Duplicate languages in the config file on positions "
+ << j << " and " << i << "\n");
return make_error_code(ParseError::Error);
}
}
@@ -888,15 +989,23 @@ std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
// Look for a suitable configuration starting from the end, so we can
// find the configuration for the specific language first, and the default
// configuration (which can only be at slot 0) after it.
+ FormatStyle::FormatStyleSet StyleSet;
+ bool LanguageFound = false;
for (int i = Styles.size() - 1; i >= 0; --i) {
- if (Styles[i].Language == Language ||
- Styles[i].Language == FormatStyle::LK_None) {
- *Style = Styles[i];
- Style->Language = Language;
- return make_error_code(ParseError::Success);
- }
- }
- return make_error_code(ParseError::Unsuitable);
+ if (Styles[i].Language != FormatStyle::LK_None)
+ StyleSet.Add(Styles[i]);
+ if (Styles[i].Language == Language)
+ LanguageFound = true;
+ }
+ if (!LanguageFound) {
+ if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
+ return make_error_code(ParseError::Unsuitable);
+ FormatStyle DefaultStyle = Styles[0];
+ DefaultStyle.Language = Language;
+ StyleSet.Add(std::move(DefaultStyle));
+ }
+ *Style = *StyleSet.Get(Language);
+ return make_error_code(ParseError::Success);
}
std::string configurationAsText(const FormatStyle &Style) {
@@ -910,6 +1019,38 @@ std::string configurationAsText(const FormatStyle &Style) {
return Stream.str();
}
+llvm::Optional<FormatStyle>
+FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
+ if (!Styles)
+ return None;
+ auto It = Styles->find(Language);
+ if (It == Styles->end())
+ return None;
+ FormatStyle Style = It->second;
+ Style.StyleSet = *this;
+ return Style;
+}
+
+void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
+ assert(Style.Language != LK_None &&
+ "Cannot add a style for LK_None to a StyleSet");
+ assert(
+ !Style.StyleSet.Styles &&
+ "Cannot add a style associated with an existing StyleSet to a StyleSet");
+ if (!Styles)
+ Styles = std::make_shared<MapType>();
+ (*Styles)[Style.Language] = std::move(Style);
+}
+
+void FormatStyle::FormatStyleSet::Clear() {
+ Styles.reset();
+}
+
+llvm::Optional<FormatStyle>
+FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
+ return StyleSet.Get(Language);
+}
+
namespace {
class JavaScriptRequoter : public TokenAnalyzer {
@@ -921,8 +1062,7 @@ public:
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
- AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
- AnnotatedLines.end());
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
tooling::Replacements Result;
requoteJSStringLiteral(AnnotatedLines, Result);
return {Result, 0};
@@ -1012,8 +1152,7 @@ public:
FormatTokenLexer &Tokens) override {
tooling::Replacements Result;
deriveLocalStyle(AnnotatedLines);
- AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
- AnnotatedLines.end());
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
}
@@ -1137,8 +1276,7 @@ public:
// To determine if some redundant code is actually introduced by
// replacements(e.g. deletions), we need to come up with a more
// sophisticated way of computing affected ranges.
- AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
- AnnotatedLines.end());
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
checkEmptyNamespace(AnnotatedLines);
@@ -1341,6 +1479,128 @@ private:
std::set<FormatToken *, FormatTokenLess> DeletedTokens;
};
+class ObjCHeaderStyleGuesser : public TokenAnalyzer {
+public:
+ ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
+ : TokenAnalyzer(Env, Style), IsObjC(false) {}
+
+ std::pair<tooling::Replacements, unsigned>
+ analyze(TokenAnnotator &Annotator,
+ SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+ FormatTokenLexer &Tokens) override {
+ assert(Style.Language == FormatStyle::LK_Cpp);
+ IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
+ tooling::Replacements Result;
+ return {Result, 0};
+ }
+
+ bool isObjC() { return IsObjC; }
+
+private:
+ static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+ const AdditionalKeywords &Keywords) {
+ // Keep this array sorted, since we are binary searching over it.
+ static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
+ "CGFloat",
+ "CGPoint",
+ "CGPointMake",
+ "CGPointZero",
+ "CGRect",
+ "CGRectEdge",
+ "CGRectInfinite",
+ "CGRectMake",
+ "CGRectNull",
+ "CGRectZero",
+ "CGSize",
+ "CGSizeMake",
+ "CGVector",
+ "CGVectorMake",
+ "NSAffineTransform",
+ "NSArray",
+ "NSAttributedString",
+ "NSBlockOperation",
+ "NSBundle",
+ "NSCache",
+ "NSCalendar",
+ "NSCharacterSet",
+ "NSCountedSet",
+ "NSData",
+ "NSDataDetector",
+ "NSDecimal",
+ "NSDecimalNumber",
+ "NSDictionary",
+ "NSEdgeInsets",
+ "NSHashTable",
+ "NSIndexPath",
+ "NSIndexSet",
+ "NSInteger",
+ "NSInvocationOperation",
+ "NSLocale",
+ "NSMapTable",
+ "NSMutableArray",
+ "NSMutableAttributedString",
+ "NSMutableCharacterSet",
+ "NSMutableData",
+ "NSMutableDictionary",
+ "NSMutableIndexSet",
+ "NSMutableOrderedSet",
+ "NSMutableSet",
+ "NSMutableString",
+ "NSNumber",
+ "NSNumberFormatter",
+ "NSObject",
+ "NSOperation",
+ "NSOperationQueue",
+ "NSOperationQueuePriority",
+ "NSOrderedSet",
+ "NSPoint",
+ "NSPointerArray",
+ "NSQualityOfService",
+ "NSRange",
+ "NSRect",
+ "NSRegularExpression",
+ "NSSet",
+ "NSSize",
+ "NSString",
+ "NSTimeZone",
+ "NSUInteger",
+ "NSURL",
+ "NSURLComponents",
+ "NSURLQueryItem",
+ "NSUUID",
+ "NSValue",
+ "UIImage",
+ "UIView",
+ };
+
+ for (auto Line : AnnotatedLines) {
+ for (const FormatToken *FormatTok = Line->First; FormatTok;
+ FormatTok = FormatTok->Next) {
+ if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
+ (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
+ FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
+ tok::l_brace))) ||
+ (FormatTok->Tok.isAnyIdentifier() &&
+ std::binary_search(std::begin(FoundationIdentifiers),
+ std::end(FoundationIdentifiers),
+ FormatTok->TokenText)) ||
+ FormatTok->is(TT_ObjCStringLiteral) ||
+ FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
+ TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
+ TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
+ TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
+ return true;
+ }
+ if (guessIsObjC(Line->Children, Keywords))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool IsObjC;
+};
+
struct IncludeDirective {
StringRef Filename;
StringRef Text;
@@ -1436,14 +1696,15 @@ static void sortCppIncludes(const FormatStyle &Style,
// the entire block. Otherwise, no replacement is generated.
if (Indices.size() == Includes.size() &&
std::is_sorted(Indices.begin(), Indices.end()) &&
- Style.IncludeBlocks == FormatStyle::IBS_Preserve)
+ Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
return;
std::string result;
for (unsigned Index : Indices) {
if (!result.empty()) {
result += "\n";
- if (Style.IncludeBlocks == FormatStyle::IBS_Regroup &&
+ if (Style.IncludeStyle.IncludeBlocks ==
+ tooling::IncludeStyle::IBS_Regroup &&
CurrentCategory != Includes[Index].Category)
result += "\n";
}
@@ -1465,60 +1726,6 @@ static void sortCppIncludes(const FormatStyle &Style,
namespace {
-// This class manages priorities of #include categories and calculates
-// priorities for headers.
-class IncludeCategoryManager {
-public:
- IncludeCategoryManager(const FormatStyle &Style, StringRef FileName)
- : Style(Style), FileName(FileName) {
- FileStem = llvm::sys::path::stem(FileName);
- for (const auto &Category : Style.IncludeCategories)
- CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
- IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
- FileName.endswith(".cpp") || FileName.endswith(".c++") ||
- FileName.endswith(".cxx") || FileName.endswith(".m") ||
- FileName.endswith(".mm");
- }
-
- // Returns the priority of the category which \p IncludeName belongs to.
- // If \p CheckMainHeader is true and \p IncludeName is a main header, returns
- // 0. Otherwise, returns the priority of the matching category or INT_MAX.
- int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) {
- int Ret = INT_MAX;
- for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
- if (CategoryRegexs[i].match(IncludeName)) {
- Ret = Style.IncludeCategories[i].Priority;
- break;
- }
- if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
- Ret = 0;
- return Ret;
- }
-
-private:
- bool isMainHeader(StringRef IncludeName) const {
- if (!IncludeName.startswith("\""))
- return false;
- StringRef HeaderStem =
- llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
- if (FileStem.startswith(HeaderStem) ||
- FileStem.startswith_lower(HeaderStem)) {
- llvm::Regex MainIncludeRegex(
- (HeaderStem + Style.IncludeIsMainRegex).str(),
- llvm::Regex::IgnoreCase);
- if (MainIncludeRegex.match(FileStem))
- return true;
- }
- return false;
- }
-
- const FormatStyle &Style;
- bool IsMainFile;
- StringRef FileName;
- StringRef FileStem;
- SmallVector<llvm::Regex, 4> CategoryRegexs;
-};
-
const char IncludeRegexPattern[] =
R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
@@ -1542,7 +1749,7 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
//
// FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
// cases where the first #include is unlikely to be the main header.
- IncludeCategoryManager Categories(Style, FileName);
+ tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
bool FirstIncludeBlock = true;
bool MainIncludeFound = false;
bool FormattingOff = false;
@@ -1559,8 +1766,10 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
FormattingOff = false;
const bool EmptyLineSkipped =
- Trimmed.empty() && (Style.IncludeBlocks == FormatStyle::IBS_Merge ||
- Style.IncludeBlocks == FormatStyle::IBS_Regroup);
+ Trimmed.empty() &&
+ (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
+ Style.IncludeStyle.IncludeBlocks ==
+ tooling::IncludeStyle::IBS_Regroup);
if (!FormattingOff && !Line.endswith("\\")) {
if (IncludeRegex.match(Line, &Matches)) {
@@ -1670,122 +1879,6 @@ inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
}
-// Returns the offset after skipping a sequence of tokens, matched by \p
-// GetOffsetAfterSequence, from the start of the code.
-// \p GetOffsetAfterSequence should be a function that matches a sequence of
-// tokens and returns an offset after the sequence.
-unsigned getOffsetAfterTokenSequence(
- StringRef FileName, StringRef Code, const FormatStyle &Style,
- llvm::function_ref<unsigned(const SourceManager &, Lexer &, Token &)>
- GetOffsetAfterSequence) {
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{});
- const SourceManager &SourceMgr = Env->getSourceManager();
- Lexer Lex(Env->getFileID(), SourceMgr.getBuffer(Env->getFileID()), SourceMgr,
- getFormattingLangOpts(Style));
- Token Tok;
- // Get the first token.
- Lex.LexFromRawLexer(Tok);
- return GetOffsetAfterSequence(SourceMgr, Lex, Tok);
-}
-
-// Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is,
-// \p Tok will be the token after this directive; otherwise, it can be any token
-// after the given \p Tok (including \p Tok).
-bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &Tok) {
- bool Matched = Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
- Tok.is(tok::raw_identifier) &&
- Tok.getRawIdentifier() == Name && !Lex.LexFromRawLexer(Tok) &&
- Tok.is(tok::raw_identifier);
- if (Matched)
- Lex.LexFromRawLexer(Tok);
- return Matched;
-}
-
-void skipComments(Lexer &Lex, Token &Tok) {
- while (Tok.is(tok::comment))
- if (Lex.LexFromRawLexer(Tok))
- return;
-}
-
-// Returns the offset after header guard directives and any comments
-// before/after header guards. If no header guard presents in the code, this
-// will returns the offset after skipping all comments from the start of the
-// code.
-unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName,
- StringRef Code,
- const FormatStyle &Style) {
- return getOffsetAfterTokenSequence(
- FileName, Code, Style,
- [](const SourceManager &SM, Lexer &Lex, Token Tok) {
- skipComments(Lex, Tok);
- unsigned InitialOffset = SM.getFileOffset(Tok.getLocation());
- if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) {
- skipComments(Lex, Tok);
- if (checkAndConsumeDirectiveWithName(Lex, "define", Tok))
- return SM.getFileOffset(Tok.getLocation());
- }
- return InitialOffset;
- });
-}
-
-// Check if a sequence of tokens is like
-// "#include ("header.h" | <header.h>)".
-// If it is, \p Tok will be the token after this directive; otherwise, it can be
-// any token after the given \p Tok (including \p Tok).
-bool checkAndConsumeInclusiveDirective(Lexer &Lex, Token &Tok) {
- auto Matched = [&]() {
- Lex.LexFromRawLexer(Tok);
- return true;
- };
- if (Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
- Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "include") {
- if (Lex.LexFromRawLexer(Tok))
- return false;
- if (Tok.is(tok::string_literal))
- return Matched();
- if (Tok.is(tok::less)) {
- while (!Lex.LexFromRawLexer(Tok) && Tok.isNot(tok::greater)) {
- }
- if (Tok.is(tok::greater))
- return Matched();
- }
- }
- return false;
-}
-
-// Returns the offset of the last #include directive after which a new
-// #include can be inserted. This ignores #include's after the #include block(s)
-// in the beginning of a file to avoid inserting headers into code sections
-// where new #include's should not be added by default.
-// These code sections include:
-// - raw string literals (containing #include).
-// - #if blocks.
-// - Special #include's among declarations (e.g. functions).
-//
-// If no #include after which a new #include can be inserted, this returns the
-// offset after skipping all comments from the start of the code.
-// Inserting after an #include is not allowed if it comes after code that is not
-// #include (e.g. pre-processing directive that is not #include, declarations).
-unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code,
- const FormatStyle &Style) {
- return getOffsetAfterTokenSequence(
- FileName, Code, Style,
- [](const SourceManager &SM, Lexer &Lex, Token Tok) {
- skipComments(Lex, Tok);
- unsigned MaxOffset = SM.getFileOffset(Tok.getLocation());
- while (checkAndConsumeInclusiveDirective(Lex, Tok))
- MaxOffset = SM.getFileOffset(Tok.getLocation());
- return MaxOffset;
- });
-}
-
-bool isDeletedHeader(llvm::StringRef HeaderName,
- const std::set<llvm::StringRef> &HeadersToDelete) {
- return HeadersToDelete.count(HeaderName) ||
- HeadersToDelete.count(HeaderName.trim("\"<>"));
-}
-
// FIXME: insert empty lines between newly created blocks.
tooling::Replacements
fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
@@ -1814,85 +1907,26 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
if (HeaderInsertions.empty() && HeadersToDelete.empty())
return Replaces;
- llvm::Regex IncludeRegex(IncludeRegexPattern);
- llvm::Regex DefineRegex(R"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)");
- SmallVector<StringRef, 4> Matches;
StringRef FileName = Replaces.begin()->getFilePath();
- IncludeCategoryManager Categories(Style, FileName);
-
- // Record the offset of the end of the last include in each category.
- std::map<int, int> CategoryEndOffsets;
- // All possible priorities.
- // Add 0 for main header and INT_MAX for headers that are not in any category.
- std::set<int> Priorities = {0, INT_MAX};
- for (const auto &Category : Style.IncludeCategories)
- Priorities.insert(Category.Priority);
- int FirstIncludeOffset = -1;
- // All new headers should be inserted after this offset.
- unsigned MinInsertOffset =
- getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style);
- StringRef TrimmedCode = Code.drop_front(MinInsertOffset);
- // Max insertion offset in the original code.
- unsigned MaxInsertOffset =
- MinInsertOffset +
- getMaxHeaderInsertionOffset(FileName, TrimmedCode, Style);
- SmallVector<StringRef, 32> Lines;
- TrimmedCode.split(Lines, '\n');
- unsigned Offset = MinInsertOffset;
- unsigned NextLineOffset;
- std::set<StringRef> ExistingIncludes;
- for (auto Line : Lines) {
- NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1);
- if (IncludeRegex.match(Line, &Matches)) {
- // The header name with quotes or angle brackets.
- StringRef IncludeName = Matches[2];
- ExistingIncludes.insert(IncludeName);
- // Only record the offset of current #include if we can insert after it.
- if (Offset <= MaxInsertOffset) {
- int Category = Categories.getIncludePriority(
- IncludeName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
- CategoryEndOffsets[Category] = NextLineOffset;
- if (FirstIncludeOffset < 0)
- FirstIncludeOffset = Offset;
- }
- if (isDeletedHeader(IncludeName, HeadersToDelete)) {
- // If this is the last line without trailing newline, we need to make
- // sure we don't delete across the file boundary.
- unsigned Length = std::min(Line.size() + 1, Code.size() - Offset);
- llvm::Error Err =
- Result.add(tooling::Replacement(FileName, Offset, Length, ""));
- if (Err) {
- // Ignore the deletion on conflict.
- llvm::errs() << "Failed to add header deletion replacement for "
- << IncludeName << ": " << llvm::toString(std::move(Err))
- << "\n";
- }
+ tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
+
+ for (const auto &Header : HeadersToDelete) {
+ tooling::Replacements Replaces =
+ Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
+ for (const auto &R : Replaces) {
+ auto Err = Result.add(R);
+ if (Err) {
+ // Ignore the deletion on conflict.
+ llvm::errs() << "Failed to add header deletion replacement for "
+ << Header << ": " << llvm::toString(std::move(Err))
+ << "\n";
}
}
- Offset = NextLineOffset;
- }
-
- // Populate CategoryEndOfssets:
- // - Ensure that CategoryEndOffset[Highest] is always populated.
- // - If CategoryEndOffset[Priority] isn't set, use the next higher value that
- // is set, up to CategoryEndOffset[Highest].
- auto Highest = Priorities.begin();
- if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) {
- if (FirstIncludeOffset >= 0)
- CategoryEndOffsets[*Highest] = FirstIncludeOffset;
- else
- CategoryEndOffsets[*Highest] = MinInsertOffset;
- }
- // By this point, CategoryEndOffset[Highest] is always set appropriately:
- // - to an appropriate location before/after existing #includes, or
- // - to right after the header guard, or
- // - to the beginning of the file.
- for (auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I)
- if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
- CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];
-
- bool NeedNewLineAtEnd = !Code.empty() && Code.back() != '\n';
+ }
+
+ llvm::Regex IncludeRegex = llvm::Regex(IncludeRegexPattern);
+ llvm::SmallVector<StringRef, 4> Matches;
for (const auto &R : HeaderInsertions) {
auto IncludeDirective = R.getReplacementText();
bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
@@ -1900,30 +1934,17 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
"'#include ...'");
(void)Matched;
auto IncludeName = Matches[2];
- if (ExistingIncludes.find(IncludeName) != ExistingIncludes.end()) {
- DEBUG(llvm::dbgs() << "Skip adding existing include : " << IncludeName
- << "\n");
- continue;
- }
- int Category =
- Categories.getIncludePriority(IncludeName, /*CheckMainHeader=*/true);
- Offset = CategoryEndOffsets[Category];
- std::string NewInclude = !IncludeDirective.endswith("\n")
- ? (IncludeDirective + "\n").str()
- : IncludeDirective.str();
- // When inserting headers at end of the code, also append '\n' to the code
- // if it does not end with '\n'.
- if (NeedNewLineAtEnd && Offset == Code.size()) {
- NewInclude = "\n" + NewInclude;
- NeedNewLineAtEnd = false;
- }
- auto NewReplace = tooling::Replacement(FileName, Offset, 0, NewInclude);
- auto Err = Result.add(NewReplace);
- if (Err) {
- llvm::consumeError(std::move(Err));
- unsigned NewOffset = Result.getShiftedCodePosition(Offset);
- NewReplace = tooling::Replacement(FileName, NewOffset, 0, NewInclude);
- Result = Result.merge(tooling::Replacements(NewReplace));
+ auto Replace =
+ Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
+ if (Replace) {
+ auto Err = Result.add(*Replace);
+ if (Err) {
+ llvm::consumeError(std::move(Err));
+ unsigned NewOffset = Result.getShiftedCodePosition(Replace->getOffset());
+ auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
+ Replace->getReplacementText());
+ Result = Result.merge(tooling::Replacements(Shifted));
+ }
}
}
return Result;
@@ -1988,9 +2009,9 @@ reformat(const FormatStyle &Style, StringRef Code,
return Formatter(Env, Expanded, Status).process();
});
- std::unique_ptr<Environment> Env = Environment::CreateVirtualEnvironment(
- Code, FileName, Ranges, FirstStartColumn, NextStartColumn,
- LastStartColumn);
+ auto Env =
+ llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
+ NextStartColumn, LastStartColumn);
llvm::Optional<std::string> CurrentCode = None;
tooling::Replacements Fixes;
unsigned Penalty = 0;
@@ -2003,7 +2024,7 @@ reformat(const FormatStyle &Style, StringRef Code,
Penalty += PassFixes.second;
if (I + 1 < E) {
CurrentCode = std::move(*NewCode);
- Env = Environment::CreateVirtualEnvironment(
+ Env = llvm::make_unique<Environment>(
*CurrentCode, FileName,
tooling::calculateRangesAfterReplacements(Fixes, Ranges),
FirstStartColumn, NextStartColumn, LastStartColumn);
@@ -2032,10 +2053,7 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
// cleanups only apply to C++ (they mostly concern ctor commas etc.)
if (Style.Language != FormatStyle::LK_Cpp)
return tooling::Replacements();
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
- Cleaner Clean(*Env, Style);
- return Clean.process().first;
+ return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
}
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
@@ -2052,20 +2070,18 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) {
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
- NamespaceEndCommentsFixer Fix(*Env, Style);
- return Fix.process().first;
+ return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
+ .process()
+ .first;
}
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) {
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
- UsingDeclarationsSorter Sorter(*Env, Style);
- return Sorter.process().first;
+ return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
+ .process()
+ .first;
}
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
@@ -2117,6 +2133,28 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
return FormatStyle::LK_Cpp;
}
+FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
+ const auto GuessedLanguage = getLanguageByFileName(FileName);
+ if (GuessedLanguage == FormatStyle::LK_Cpp) {
+ auto Extension = llvm::sys::path::extension(FileName);
+ // If there's no file extension (or it's .h), we need to check the contents
+ // of the code to see if it contains Objective-C.
+ if (Extension.empty() || Extension == ".h") {
+ auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
+ Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
+ ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
+ Guesser.process();
+ if (Guesser.isObjC())
+ return FormatStyle::LK_ObjC;
+ }
+ }
+ return GuessedLanguage;
+}
+
+const char *DefaultFormatStyle = "file";
+
+const char *DefaultFallbackStyle = "LLVM";
+
llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
StringRef FallbackStyleName,
StringRef Code, vfs::FileSystem *FS) {
@@ -2124,16 +2162,7 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
FS = vfs::getRealFileSystem().get();
}
FormatStyle Style = getLLVMStyle();
- Style.Language = getLanguageByFileName(FileName);
-
- // This is a very crude detection of whether a header contains ObjC code that
- // 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@end\n") || Code.contains("\n@end ") ||
- Code.endswith("@end")))
- Style.Language = FormatStyle::LK_ObjC;
+ Style.Language = guessLanguage(FileName, Code);
FormatStyle FallbackStyle = getNoStyle();
if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
@@ -2170,7 +2199,7 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
SmallString<128> ConfigFile(Directory);
llvm::sys::path::append(ConfigFile, ".clang-format");
- DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
+ LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
Status = FS->status(ConfigFile.str());
bool FoundConfigFile =
@@ -2179,7 +2208,7 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
// Try _clang-format too, since dotfiles are not commonly used on Windows.
ConfigFile = Directory;
llvm::sys::path::append(ConfigFile, "_clang-format");
- DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
+ LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
Status = FS->status(ConfigFile.str());
FoundConfigFile = Status && (Status->getType() ==
llvm::sys::fs::file_type::regular_file);
@@ -2201,7 +2230,8 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
return make_string_error("Error reading " + ConfigFile + ": " +
ec.message());
}
- DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << "Using configuration file " << ConfigFile << "\n");
return Style;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatInternal.h b/contrib/llvm/tools/clang/lib/Format/FormatInternal.h
index 3984158467b3..5c59e7656eee 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatInternal.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatInternal.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares Format APIs to be used internally by the
+/// This file declares Format APIs to be used internally by the
/// formatting library implementation.
///
//===----------------------------------------------------------------------===//
@@ -24,7 +24,7 @@ namespace clang {
namespace format {
namespace internal {
-/// \brief Reformats the given \p Ranges in the code fragment \p Code.
+/// 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.
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
index 10ac392abbf2..62b08c576e05 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements specific functions of \c FormatTokens and their
+/// This file implements specific functions of \c FormatTokens and their
/// roles.
///
//===----------------------------------------------------------------------===//
@@ -57,6 +57,7 @@ bool FormatToken::isSimpleTypeSpecifier() const {
case tok::kw_bool:
case tok::kw___underlying_type:
case tok::annot_typename:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_typeof:
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.h b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
index 3dc0ab0e7cca..9094e7689e1d 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file contains the declaration of the FormatToken, a wrapper
+/// This file contains the declaration of the FormatToken, a wrapper
/// around Token with additional information related to formatting.
///
//===----------------------------------------------------------------------===//
@@ -29,7 +29,9 @@ namespace format {
#define LIST_TOKEN_TYPES \
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
+ TYPE(AttributeColon) \
TYPE(AttributeParen) \
+ TYPE(AttributeSquare) \
TYPE(BinaryOperator) \
TYPE(BitFieldColon) \
TYPE(BlockComment) \
@@ -88,6 +90,7 @@ namespace format {
TYPE(TemplateCloser) \
TYPE(TemplateOpener) \
TYPE(TemplateString) \
+ TYPE(ProtoExtensionLSquare) \
TYPE(TrailingAnnotation) \
TYPE(TrailingReturnArrow) \
TYPE(TrailingUnaryOperator) \
@@ -101,7 +104,7 @@ enum TokenType {
NUM_TOKEN_TYPES
};
-/// \brief Determines the name of a token type.
+/// Determines the name of a token type.
const char *getTokenTypeName(TokenType Type);
// Represents what type of block a set of braces open.
@@ -115,181 +118,191 @@ enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };
class TokenRole;
class AnnotatedLine;
-/// \brief A wrapper around a \c Token storing information about the
+/// A wrapper around a \c Token storing information about the
/// whitespace characters preceding it.
struct FormatToken {
FormatToken() {}
- /// \brief The \c Token.
+ /// The \c Token.
Token Tok;
- /// \brief The number of newlines immediately before the \c Token.
+ /// The number of newlines immediately before the \c Token.
///
/// This can be used to determine what the user wrote in the original code
/// and thereby e.g. leave an empty line between two function definitions.
unsigned NewlinesBefore = 0;
- /// \brief Whether there is at least one unescaped newline before the \c
+ /// Whether there is at least one unescaped newline before the \c
/// Token.
bool HasUnescapedNewline = false;
- /// \brief The range of the whitespace immediately preceding the \c Token.
+ /// The range of the whitespace immediately preceding the \c Token.
SourceRange WhitespaceRange;
- /// \brief The offset just past the last '\n' in this token's leading
+ /// The offset just past the last '\n' in this token's leading
/// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.
unsigned LastNewlineOffset = 0;
- /// \brief The width of the non-whitespace parts of the token (or its first
+ /// The width of the non-whitespace parts of the token (or its first
/// line for multi-line tokens) in columns.
/// We need this to correctly measure number of columns a token spans.
unsigned ColumnWidth = 0;
- /// \brief Contains the width in columns of the last line of a multi-line
+ /// Contains the width in columns of the last line of a multi-line
/// token.
unsigned LastLineColumnWidth = 0;
- /// \brief Whether the token text contains newlines (escaped or not).
+ /// Whether the token text contains newlines (escaped or not).
bool IsMultiline = false;
- /// \brief Indicates that this is the first token of the file.
+ /// Indicates that this is the first token of the file.
bool IsFirst = false;
- /// \brief Whether there must be a line break before this token.
+ /// Whether there must be a line break before this token.
///
/// This happens for example when a preprocessor directive ended directly
/// before the token.
bool MustBreakBefore = false;
- /// \brief The raw text of the token.
+ /// The raw text of the token.
///
/// Contains the raw token text without leading whitespace and without leading
/// escaped newlines.
StringRef TokenText;
- /// \brief Set to \c true if this token is an unterminated literal.
+ /// Set to \c true if this token is an unterminated literal.
bool IsUnterminatedLiteral = 0;
- /// \brief Contains the kind of block if this token is a brace.
+ /// Contains the kind of block if this token is a brace.
BraceBlockKind BlockKind = BK_Unknown;
TokenType Type = TT_Unknown;
- /// \brief The number of spaces that should be inserted before this token.
+ /// The number of spaces that should be inserted before this token.
unsigned SpacesRequiredBefore = 0;
- /// \brief \c true if it is allowed to break before this token.
+ /// \c true if it is allowed to break before this token.
bool CanBreakBefore = false;
- /// \brief \c true if this is the ">" of "template<..>".
+ /// \c true if this is the ">" of "template<..>".
bool ClosesTemplateDeclaration = false;
- /// \brief Number of parameters, if this is "(", "[" or "<".
+ /// Number of parameters, if this is "(", "[" or "<".
///
/// This is initialized to 1 as we don't need to distinguish functions with
/// 0 parameters from functions with 1 parameter. Thus, we can simply count
/// the number of commas.
unsigned ParameterCount = 0;
- /// \brief Number of parameters that are nested blocks,
+ /// Number of parameters that are nested blocks,
/// if this is "(", "[" or "<".
unsigned BlockParameterCount = 0;
- /// \brief If this is a bracket ("<", "(", "[" or "{"), contains the kind of
+ /// If this is a bracket ("<", "(", "[" or "{"), contains the kind of
/// the surrounding bracket.
tok::TokenKind ParentBracket = tok::unknown;
- /// \brief A token can have a special role that can carry extra information
+ /// A token can have a special role that can carry extra information
/// about the token's formatting.
std::unique_ptr<TokenRole> Role;
- /// \brief If this is an opening parenthesis, how are the parameters packed?
+ /// If this is an opening parenthesis, how are the parameters packed?
ParameterPackingKind PackingKind = PPK_Inconclusive;
- /// \brief The total length of the unwrapped line up to and including this
+ /// The total length of the unwrapped line up to and including this
/// token.
unsigned TotalLength = 0;
- /// \brief The original 0-based column of this token, including expanded tabs.
+ /// The original 0-based column of this token, including expanded tabs.
/// The configured TabWidth is used as tab width.
unsigned OriginalColumn = 0;
- /// \brief The length of following tokens until the next natural split point,
+ /// The length of following tokens until the next natural split point,
/// or the next token that can be broken.
unsigned UnbreakableTailLength = 0;
// FIXME: Come up with a 'cleaner' concept.
- /// \brief The binding strength of a token. This is a combined value of
+ /// The binding strength of a token. This is a combined value of
/// operator precedence, parenthesis nesting, etc.
unsigned BindingStrength = 0;
- /// \brief The nesting level of this token, i.e. the number of surrounding (),
+ /// The nesting level of this token, i.e. the number of surrounding (),
/// [], {} or <>.
unsigned NestingLevel = 0;
- /// \brief The indent level of this token. Copied from the surrounding line.
+ /// The indent level of this token. Copied from the surrounding line.
unsigned IndentLevel = 0;
- /// \brief Penalty for inserting a line break before this token.
+ /// Penalty for inserting a line break before this token.
unsigned SplitPenalty = 0;
- /// \brief If this is the first ObjC selector name in an ObjC method
+ /// If this is the first ObjC selector name in an ObjC method
/// definition or call, this contains the length of the longest name.
///
/// This being set to 0 means that the selectors should not be colon-aligned,
/// e.g. because several of them are block-type.
unsigned LongestObjCSelectorName = 0;
- /// \brief Stores the number of required fake parentheses and the
+ /// If this is the first ObjC selector name in an ObjC method
+ /// definition or call, this contains the number of parts that the whole
+ /// selector consist of.
+ unsigned ObjCSelectorNameParts = 0;
+
+ /// The 0-based index of the parameter/argument. For ObjC it is set
+ /// for the selector name token.
+ /// For now calculated only for ObjC.
+ unsigned ParameterIndex = 0;
+
+ /// Stores the number of required fake parentheses and the
/// corresponding operator precedence.
///
/// If multiple fake parentheses start at a token, this vector stores them in
/// reverse order, i.e. inner fake parenthesis first.
SmallVector<prec::Level, 4> FakeLParens;
- /// \brief Insert this many fake ) after this token for correct indentation.
+ /// Insert this many fake ) after this token for correct indentation.
unsigned FakeRParens = 0;
- /// \brief \c true if this token starts a binary expression, i.e. has at least
+ /// \c true if this token starts a binary expression, i.e. has at least
/// one fake l_paren with a precedence greater than prec::Unknown.
bool StartsBinaryExpression = false;
- /// \brief \c true if this token ends a binary expression.
+ /// \c true if this token ends a binary expression.
bool EndsBinaryExpression = false;
- /// \brief Is this is an operator (or "."/"->") in a sequence of operators
+ /// Is this is an operator (or "."/"->") in a sequence of operators
/// with the same precedence, contains the 0-based operator index.
unsigned OperatorIndex = 0;
- /// \brief If this is an operator (or "."/"->") in a sequence of operators
+ /// If this is an operator (or "."/"->") in a sequence of operators
/// with the same precedence, points to the next operator.
FormatToken *NextOperator = nullptr;
- /// \brief Is this token part of a \c DeclStmt defining multiple variables?
+ /// Is this token part of a \c DeclStmt defining multiple variables?
///
/// Only set if \c Type == \c TT_StartOfName.
bool PartOfMultiVariableDeclStmt = false;
- /// \brief Does this line comment continue a line comment section?
+ /// Does this line comment continue a line comment section?
///
/// Only set to true if \c Type == \c TT_LineComment.
bool ContinuesLineCommentSection = false;
- /// \brief If this is a bracket, this points to the matching one.
+ /// If this is a bracket, this points to the matching one.
FormatToken *MatchingParen = nullptr;
- /// \brief The previous token in the unwrapped line.
+ /// The previous token in the unwrapped line.
FormatToken *Previous = nullptr;
- /// \brief The next token in the unwrapped line.
+ /// The next token in the unwrapped line.
FormatToken *Next = nullptr;
- /// \brief If this token starts a block, this contains all the unwrapped lines
+ /// If this token starts a block, this contains all the unwrapped lines
/// in it.
SmallVector<AnnotatedLine *, 1> Children;
- /// \brief Stores the formatting decision for the token once it was made.
+ /// Stores the formatting decision for the token once it was made.
FormatDecision Decision = FD_Unformatted;
- /// \brief If \c true, this token has been fully formatted (indented and
+ /// If \c true, this token has been fully formatted (indented and
/// potentially re-formatted inside), and we do not allow further formatting
/// changes.
bool Finalized = false;
@@ -337,7 +350,7 @@ struct FormatToken {
(!ColonRequired || (Next && Next->is(tok::colon)));
}
- /// \brief Determine whether the token is a simple-type-specifier.
+ /// Determine whether the token is a simple-type-specifier.
bool isSimpleTypeSpecifier() const;
bool isObjCAccessSpecifier() const {
@@ -348,22 +361,28 @@ struct FormatToken {
Next->isObjCAtKeyword(tok::objc_private));
}
- /// \brief Returns whether \p Tok is ([{ or a template opening <.
+ /// Returns whether \p Tok is ([{ or an opening < of a template or in
+ /// protos.
bool opensScope() const {
if (is(TT_TemplateString) && TokenText.endswith("${"))
return true;
+ if (is(TT_DictLiteral) && is(tok::less))
+ return true;
return isOneOf(tok::l_paren, tok::l_brace, tok::l_square,
TT_TemplateOpener);
}
- /// \brief Returns whether \p Tok is )]} or a template closing >.
+ /// Returns whether \p Tok is )]} or a closing > of a template or in
+ /// protos.
bool closesScope() const {
if (is(TT_TemplateString) && TokenText.startswith("}"))
return true;
+ if (is(TT_DictLiteral) && is(tok::greater))
+ return true;
return isOneOf(tok::r_paren, tok::r_brace, tok::r_square,
TT_TemplateCloser);
}
- /// \brief Returns \c true if this is a "." or "->" accessing a member.
+ /// Returns \c true if this is a "." or "->" accessing a member.
bool isMemberAccess() const {
return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&
!isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow,
@@ -396,7 +415,7 @@ struct FormatToken {
(is(TT_LineComment) || !Next || Next->NewlinesBefore > 0);
}
- /// \brief Returns \c true if this is a keyword that can be used
+ /// Returns \c true if this is a keyword that can be used
/// like a function call (e.g. sizeof, typeid, ...).
bool isFunctionLikeKeyword() const {
switch (Tok.getKind()) {
@@ -416,7 +435,7 @@ struct FormatToken {
}
}
- /// \brief Returns \c true if this is a string literal that's like a label,
+ /// Returns \c true if this is a string literal that's like a label,
/// e.g. ends with "=" or ":".
bool isLabelString() const {
if (!is(tok::string_literal))
@@ -431,7 +450,7 @@ struct FormatToken {
(Content.back() == ':' || Content.back() == '=');
}
- /// \brief Returns actual token start location without leading escaped
+ /// Returns actual token start location without leading escaped
/// newlines and whitespace.
///
/// This can be different to Tok.getLocation(), which includes leading escaped
@@ -441,10 +460,11 @@ struct FormatToken {
}
prec::Level getPrecedence() const {
- return getBinOpPrecedence(Tok.getKind(), true, true);
+ return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true,
+ /*CPlusPlus11=*/true);
}
- /// \brief Returns the previous token ignoring comments.
+ /// Returns the previous token ignoring comments.
FormatToken *getPreviousNonComment() const {
FormatToken *Tok = Previous;
while (Tok && Tok->is(tok::comment))
@@ -452,7 +472,7 @@ struct FormatToken {
return Tok;
}
- /// \brief Returns the next token ignoring comments.
+ /// Returns the next token ignoring comments.
const FormatToken *getNextNonComment() const {
const FormatToken *Tok = Next;
while (Tok && Tok->is(tok::comment))
@@ -460,12 +480,13 @@ struct FormatToken {
return Tok;
}
- /// \brief Returns \c true if this tokens starts a block-type list, i.e. a
+ /// Returns \c true if this tokens starts a block-type list, i.e. a
/// list that should be indented with a block indent.
bool opensBlockOrBlockTypeList(const FormatStyle &Style) const {
if (is(TT_TemplateString) && opensScope())
return true;
return is(TT_ArrayInitializerLSquare) ||
+ is(TT_ProtoExtensionLSquare) ||
(is(tok::l_brace) &&
(BlockKind == BK_Block || is(TT_DictLiteral) ||
(!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
@@ -473,7 +494,7 @@ struct FormatToken {
Style.Language == FormatStyle::LK_TextProto));
}
- /// \brief Returns whether the token is the left square bracket of a C++
+ /// 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))
@@ -486,14 +507,14 @@ struct FormatToken {
return T && T->is(tok::kw_auto);
}
- /// \brief Same as opensBlockOrBlockTypeList, but for the closing token.
+ /// Same as opensBlockOrBlockTypeList, but for the closing token.
bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {
if (is(TT_TemplateString) && closesScope())
return true;
return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);
}
- /// \brief Return the actual namespace token, if this token starts a namespace
+ /// Return the actual namespace token, if this token starts a namespace
/// block.
const FormatToken *getNamespaceToken() const {
const FormatToken *NamespaceTok = this;
@@ -546,11 +567,11 @@ public:
TokenRole(const FormatStyle &Style) : Style(Style) {}
virtual ~TokenRole();
- /// \brief After the \c TokenAnnotator has finished annotating all the tokens,
+ /// After the \c TokenAnnotator has finished annotating all the tokens,
/// this function precomputes required information for formatting.
virtual void precomputeFormattingInfos(const FormatToken *Token);
- /// \brief Apply the special formatting that the given role demands.
+ /// Apply the special formatting that the given role demands.
///
/// Assumes that the token having this role is already formatted.
///
@@ -562,7 +583,7 @@ public:
return 0;
}
- /// \brief Same as \c formatFromToken, but assumes that the first token has
+ /// Same as \c formatFromToken, but assumes that the first token has
/// already been set thereby deciding on the first line break.
virtual unsigned formatAfterToken(LineState &State,
ContinuationIndenter *Indenter,
@@ -570,7 +591,7 @@ public:
return 0;
}
- /// \brief Notifies the \c Role that a comma was found.
+ /// Notifies the \c Role that a comma was found.
virtual void CommaFound(const FormatToken *Token) {}
protected:
@@ -590,46 +611,46 @@ public:
unsigned formatFromToken(LineState &State, ContinuationIndenter *Indenter,
bool DryRun) override;
- /// \brief Adds \p Token as the next comma to the \c CommaSeparated list.
+ /// Adds \p Token as the next comma to the \c CommaSeparated list.
void CommaFound(const FormatToken *Token) override {
Commas.push_back(Token);
}
private:
- /// \brief A struct that holds information on how to format a given list with
+ /// A struct that holds information on how to format a given list with
/// a specific number of columns.
struct ColumnFormat {
- /// \brief The number of columns to use.
+ /// The number of columns to use.
unsigned Columns;
- /// \brief The total width in characters.
+ /// The total width in characters.
unsigned TotalWidth;
- /// \brief The number of lines required for this format.
+ /// The number of lines required for this format.
unsigned LineCount;
- /// \brief The size of each column in characters.
+ /// The size of each column in characters.
SmallVector<unsigned, 8> ColumnSizes;
};
- /// \brief Calculate which \c ColumnFormat fits best into
+ /// Calculate which \c ColumnFormat fits best into
/// \p RemainingCharacters.
const ColumnFormat *getColumnFormat(unsigned RemainingCharacters) const;
- /// \brief The ordered \c FormatTokens making up the commas of this list.
+ /// The ordered \c FormatTokens making up the commas of this list.
SmallVector<const FormatToken *, 8> Commas;
- /// \brief The length of each of the list's items in characters including the
+ /// The length of each of the list's items in characters including the
/// trailing comma.
SmallVector<unsigned, 8> ItemLengths;
- /// \brief Precomputed formats that can be used for this list.
+ /// Precomputed formats that can be used for this list.
SmallVector<ColumnFormat, 4> Formats;
bool HasNestedBracedList;
};
-/// \brief Encapsulates keywords that are context sensitive or for languages not
+/// Encapsulates keywords that are context sensitive or for languages not
/// properly supported by Clang's lexer.
struct AdditionalKeywords {
AdditionalKeywords(IdentifierTable &IdentTable) {
@@ -761,7 +782,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_slots;
IdentifierInfo *kw_qslots;
- /// \brief Returns \c true if \p Tok is a true JavaScript identifier, returns
+ /// Returns \c true if \p Tok is a true JavaScript identifier, returns
/// \c false if it is a keyword or a pseudo keyword.
bool IsJavaScriptIdentifier(const FormatToken &Tok) const {
return Tok.is(tok::identifier) &&
@@ -770,7 +791,7 @@ struct AdditionalKeywords {
}
private:
- /// \brief The JavaScript keywords beyond the C++ keyword set.
+ /// The JavaScript keywords beyond the C++ keyword set.
std::unordered_set<IdentifierInfo *> JsExtraKeywords;
};
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp
index 199d2974c5c7..c7f720a443d3 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements FormatTokenLexer, which tokenizes a source file
+/// This file implements FormatTokenLexer, which tokenizes a source file
/// into a FormatToken stream suitable for ClangFormat.
///
//===----------------------------------------------------------------------===//
@@ -38,7 +38,7 @@ FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
for (const std::string &ForEachMacro : Style.ForEachMacros)
ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
- std::sort(ForEachMacros.begin(), ForEachMacros.end());
+ llvm::sort(ForEachMacros.begin(), ForEachMacros.end());
}
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@@ -334,7 +334,7 @@ void FormatTokenLexer::handleTemplateStrings() {
void FormatTokenLexer::tryParsePythonComment() {
FormatToken *HashToken = Tokens.back();
- if (HashToken->isNot(tok::hash))
+ if (!HashToken->isOneOf(tok::hash, tok::hashhash))
return;
// Turn the remainder of this line into a comment.
const char *CommentBegin =
@@ -691,7 +691,9 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) {
}
}
- if (Style.Language == FormatStyle::LK_JavaScript &&
+ if ((Style.Language == FormatStyle::LK_JavaScript ||
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
Tok.is(tok::char_constant)) {
Tok.Tok.setKind(tok::string_literal);
}
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h
index 59dc2a752f1f..3b79d27480e3 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file contains FormatTokenLexer, which tokenizes a source file
+/// This file contains FormatTokenLexer, which tokenizes a source file
/// into a token stream suitable for ClangFormat.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp
index df99bb2e1381..995b3219a1f4 100644
--- a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements NamespaceEndCommentsFixer, a TokenAnalyzer that
+/// This file implements NamespaceEndCommentsFixer, a TokenAnalyzer that
/// fixes namespace end comments.
///
//===----------------------------------------------------------------------===//
@@ -27,13 +27,6 @@ namespace {
// Short namespaces don't need an end comment.
static const int kShortNamespaceMaxLines = 1;
-// Matches a valid namespace end comment.
-// Valid namespace end comments don't need to be edited.
-static llvm::Regex kNamespaceCommentPattern =
- llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
- "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
- llvm::Regex::IgnoreCase);
-
// Computes the name of a namespace given the namespace token.
// Returns "" for anonymous namespace.
std::string computeName(const FormatToken *NamespaceTok) {
@@ -67,8 +60,15 @@ bool hasEndComment(const FormatToken *RBraceTok) {
bool validEndComment(const FormatToken *RBraceTok, StringRef NamespaceName) {
assert(hasEndComment(RBraceTok));
const FormatToken *Comment = RBraceTok->Next;
+
+ // Matches a valid namespace end comment.
+ // Valid namespace end comments don't need to be edited.
+ static llvm::Regex *const NamespaceCommentPattern =
+ new llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
+ "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
+ llvm::Regex::IgnoreCase);
SmallVector<StringRef, 7> Groups;
- if (kNamespaceCommentPattern.match(Comment->TokenText, &Groups)) {
+ if (NamespaceCommentPattern->match(Comment->TokenText, &Groups)) {
StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] : "";
// Anonymous namespace comments must not mention a namespace name.
if (NamespaceName.empty() && !NamespaceNameInComment.empty())
@@ -107,13 +107,14 @@ void updateEndComment(const FormatToken *RBraceTok, StringRef EndCommentText,
<< llvm::toString(std::move(Err)) << "\n";
}
}
+} // namespace
const FormatToken *
-getNamespaceToken(const AnnotatedLine *line,
+getNamespaceToken(const AnnotatedLine *Line,
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
- if (!line->Affected || line->InPPDirective || !line->startsWith(tok::r_brace))
+ if (!Line->Affected || Line->InPPDirective || !Line->startsWith(tok::r_brace))
return nullptr;
- size_t StartLineIndex = line->MatchingOpeningBlockLineIndex;
+ size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;
if (StartLineIndex == UnwrappedLine::kInvalidIndex)
return nullptr;
assert(StartLineIndex < AnnotatedLines.size());
@@ -131,7 +132,6 @@ getNamespaceToken(const AnnotatedLine *line,
return nullptr;
return NamespaceTok;
}
-} // namespace
NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env,
const FormatStyle &Style)
@@ -141,8 +141,7 @@ std::pair<tooling::Replacements, unsigned> NamespaceEndCommentsFixer::analyze(
TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) {
const SourceManager &SourceMgr = Env.getSourceManager();
- AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
- AnnotatedLines.end());
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
tooling::Replacements Fixes;
std::string AllNamespaceNames = "";
size_t StartLineIndex = SIZE_MAX;
diff --git a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h
index 4779f0d27c92..07a1c7bb0c35 100644
--- a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h
+++ b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares NamespaceEndCommentsFixer, a TokenAnalyzer that
+/// This file declares NamespaceEndCommentsFixer, a TokenAnalyzer that
/// fixes namespace end comments.
///
//===----------------------------------------------------------------------===//
@@ -21,6 +21,16 @@
namespace clang {
namespace format {
+// Finds the namespace token corresponding to a closing namespace `}`, if that
+// is to be formatted.
+// If \p Line contains the closing `}` of a namespace, is affected and is not in
+// a preprocessor directive, the result will be the matching namespace token.
+// Otherwise returns null.
+// \p AnnotatedLines is the sequence of lines from which \p Line is a member of.
+const FormatToken *
+getNamespaceToken(const AnnotatedLine *Line,
+ const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines);
+
class NamespaceEndCommentsFixer : public TokenAnalyzer {
public:
NamespaceEndCommentsFixer(const Environment &Env, const FormatStyle &Style);
diff --git a/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp b/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp
index d0b979e100d5..2ec577382ffb 100644
--- a/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a sort operation for JavaScript ES6 imports.
+/// This file implements a sort operation for JavaScript ES6 imports.
///
//===----------------------------------------------------------------------===//
@@ -128,8 +128,7 @@ public:
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
tooling::Replacements Result;
- AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
- AnnotatedLines.end());
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
const AdditionalKeywords &Keywords = Tokens.getKeywords();
SmallVector<JsModuleReference, 16> References;
@@ -189,9 +188,9 @@ public:
if (FirstNonImportLine && FirstNonImportLine->First->NewlinesBefore < 2)
ReferencesText += "\n";
- DEBUG(llvm::dbgs() << "Replacing imports:\n"
- << getSourceText(InsertionPoint) << "\nwith:\n"
- << ReferencesText << "\n");
+ LLVM_DEBUG(llvm::dbgs() << "Replacing imports:\n"
+ << getSourceText(InsertionPoint) << "\nwith:\n"
+ << ReferencesText << "\n");
auto Err = Result.add(tooling::Replacement(
Env.getSourceManager(), CharSourceRange::getCharRange(InsertionPoint),
ReferencesText));
@@ -308,7 +307,7 @@ private:
FirstNonImportLine = nullptr;
AnyImportAffected = AnyImportAffected || Line->Affected;
Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
- DEBUG({
+ LLVM_DEBUG({
llvm::dbgs() << "JsModuleReference: {"
<< "is_export: " << Reference.IsExport
<< ", cat: " << Reference.Category
@@ -446,10 +445,9 @@ tooling::Replacements sortJavaScriptImports(const FormatStyle &Style,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) {
// FIXME: Cursor support.
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
- JavaScriptImportSorter Sorter(*Env, Style);
- return Sorter.process().first;
+ return JavaScriptImportSorter(Environment(Code, FileName, Ranges), Style)
+ .process()
+ .first;
}
} // end namespace format
diff --git a/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.h b/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.h
index f22a051008f0..ecab0ae54cb3 100644
--- a/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.h
+++ b/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a sorter for JavaScript ES6 imports.
+/// This file implements a sorter for JavaScript ES6 imports.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp
index d1dfb1fea32b..99fc61ef1c32 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements an abstract TokenAnalyzer and associated helper
+/// This file implements an abstract TokenAnalyzer and associated helper
/// classes. TokenAnalyzer can be extended to generate replacements based on
/// an annotated and pre-processed token stream.
///
@@ -34,48 +34,19 @@
namespace clang {
namespace format {
-// This sets up an virtual file system with file \p FileName containing \p
-// Code.
-std::unique_ptr<Environment>
-Environment::CreateVirtualEnvironment(StringRef Code, StringRef FileName,
- 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(
- new vfs::InMemoryFileSystem);
- // This is passed to `SM` as reference, so the pointer has to be referenced
- // in `Environment` so that `FileMgr` can out-live this function scope.
- std::unique_ptr<FileManager> FileMgr(
- new FileManager(FileSystemOptions(), InMemoryFileSystem));
- // This is passed to `SM` as reference, so the pointer has to be referenced
- // by `Environment` due to the same reason above.
- std::unique_ptr<DiagnosticsEngine> Diagnostics(new DiagnosticsEngine(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
- new DiagnosticOptions));
- // This will be stored as reference, so the pointer has to be stored in
- // due to the same reason above.
- std::unique_ptr<SourceManager> VirtualSM(
- new SourceManager(*Diagnostics, *FileMgr));
- InMemoryFileSystem->addFile(
- FileName, 0,
- llvm::MemoryBuffer::getMemBuffer(Code, FileName,
- /*RequiresNullTerminator=*/false));
- FileID ID = VirtualSM->createFileID(FileMgr->getFile(FileName),
- SourceLocation(), clang::SrcMgr::C_User);
- assert(ID.isValid());
- SourceLocation StartOfFile = VirtualSM->getLocForStartOfFile(ID);
- std::vector<CharSourceRange> CharRanges;
+Environment::Environment(StringRef Code, StringRef FileName,
+ ArrayRef<tooling::Range> Ranges,
+ unsigned FirstStartColumn, unsigned NextStartColumn,
+ unsigned LastStartColumn)
+ : VirtualSM(new SourceManagerForFile(FileName, Code)), SM(VirtualSM->get()),
+ ID(VirtualSM->get().getMainFileID()), FirstStartColumn(FirstStartColumn),
+ NextStartColumn(NextStartColumn), LastStartColumn(LastStartColumn) {
+ SourceLocation StartOfFile = SM.getLocForStartOfFile(ID);
for (const tooling::Range &Range : Ranges) {
SourceLocation Start = StartOfFile.getLocWithOffset(Range.getOffset());
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, FirstStartColumn, NextStartColumn, LastStartColumn);
}
TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
@@ -84,12 +55,12 @@ TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
UnwrappedLines(1),
Encoding(encoding::detectEncoding(
Env.getSourceManager().getBufferData(Env.getFileID()))) {
- DEBUG(
+ LLVM_DEBUG(
llvm::dbgs() << "File encoding: "
<< (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown")
<< "\n");
- DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)
- << "\n");
+ LLVM_DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)
+ << "\n");
}
std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() {
@@ -103,7 +74,7 @@ std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() {
assert(UnwrappedLines.rbegin()->empty());
unsigned Penalty = 0;
for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE; ++Run) {
- DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
+ LLVM_DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
SmallVector<AnnotatedLine *, 16> AnnotatedLines;
TokenAnnotator Annotator(Style, Tokens.getKeywords());
@@ -115,7 +86,7 @@ std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() {
std::pair<tooling::Replacements, unsigned> RunResult =
analyze(Annotator, AnnotatedLines, Tokens);
- DEBUG({
+ LLVM_DEBUG({
llvm::dbgs() << "Replacements for run " << Run << ":\n";
for (tooling::Replacements::const_iterator I = RunResult.first.begin(),
E = RunResult.first.end();
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h
index 96ea00b25ba1..e43a860e46cf 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares an abstract TokenAnalyzer, and associated helper
+/// This file declares an abstract TokenAnalyzer, and associated helper
/// classes. TokenAnalyzer can be extended to generate replacements based on
/// an annotated and pre-processed token stream.
///
@@ -37,44 +37,24 @@ namespace format {
class Environment {
public:
Environment(SourceManager &SM, FileID ID, ArrayRef<CharSourceRange> Ranges)
- : 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,
- unsigned FirstStartColumn,
- unsigned NextStartColumn,
- unsigned LastStartColumn)
- : ID(ID), CharRanges(CharRanges.begin(), CharRanges.end()),
- SM(*VirtualSM),
- FirstStartColumn(FirstStartColumn),
- NextStartColumn(NextStartColumn),
- LastStartColumn(LastStartColumn),
- FileMgr(std::move(FileMgr)),
- VirtualSM(std::move(VirtualSM)), Diagnostics(std::move(Diagnostics)) {}
+ : SM(SM), ID(ID), CharRanges(Ranges.begin(), Ranges.end()),
+ FirstStartColumn(0), NextStartColumn(0), LastStartColumn(0) {}
// 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,
- unsigned FirstStartColumn = 0,
- unsigned NextStartColumn = 0,
- unsigned LastStartColumn = 0);
+ Environment(StringRef Code, StringRef FileName,
+ ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn = 0,
+ unsigned NextStartColumn = 0, unsigned LastStartColumn = 0);
FileID getFileID() const { return ID; }
- ArrayRef<CharSourceRange> getCharRanges() const { return CharRanges; }
-
const SourceManager &getSourceManager() const { return SM; }
+ ArrayRef<CharSourceRange> getCharRanges() const { return CharRanges; }
+
// Returns the column at which the fragment of code managed by this
// environment starts.
unsigned getFirstStartColumn() const { return FirstStartColumn; }
@@ -88,19 +68,18 @@ public:
unsigned getLastStartColumn() const { return LastStartColumn; }
private:
+ // This is only set if constructed from string.
+ std::unique_ptr<SourceManagerForFile> VirtualSM;
+
+ // This refers to either a SourceManager provided by users or VirtualSM
+ // created for a single file.
+ SourceManager &SM;
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
- // deleted in the reverse order as they are created.
- std::unique_ptr<FileManager> FileMgr;
- std::unique_ptr<SourceManager> VirtualSM;
- std::unique_ptr<DiagnosticsEngine> Diagnostics;
};
class TokenAnalyzer : public UnwrappedLineConsumer {
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
index 079b330f3a7d..3a19215e1803 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a token annotator, i.e. creates
+/// This file implements a token annotator, i.e. creates
/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
///
//===----------------------------------------------------------------------===//
@@ -25,7 +25,22 @@ namespace format {
namespace {
-/// \brief A parser that gathers additional information about tokens.
+/// Returns \c true if the token can be used as an identifier in
+/// an Objective-C \c @selector, \c false otherwise.
+///
+/// Because getFormattingLangOpts() always lexes source code as
+/// Objective-C++, C++ keywords like \c new and \c delete are
+/// lexed as tok::kw_*, not tok::identifier, even for Objective-C.
+///
+/// For Objective-C and Objective-C++, both identifiers and keywords
+/// are valid inside @selector(...) (or a macro which
+/// invokes @selector(...)). So, we allow treat any identifier or
+/// keyword as a potential Objective-C selector component.
+static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
+ return Tok.Tok.getIdentifierInfo() != nullptr;
+}
+
+/// A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
/// store a parenthesis levels. It also tries to resolve matching "<" and ">"
@@ -79,7 +94,17 @@ private:
if (CurrentToken->is(tok::greater)) {
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
- CurrentToken->Type = TT_TemplateCloser;
+ // In TT_Proto, we must distignuish between:
+ // map<key, value>
+ // msg < item: data >
+ // msg: < item: data >
+ // In TT_TextProto, map<key, value> does not occur.
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto && Left->Previous &&
+ Left->Previous->isOneOf(TT_SelectorName, TT_DictLiteral)))
+ CurrentToken->Type = TT_DictLiteral;
+ else
+ CurrentToken->Type = TT_TemplateCloser;
next();
return true;
}
@@ -131,10 +156,7 @@ private:
Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
bool StartsObjCMethodExpr = false;
- if (CurrentToken->is(tok::caret)) {
- // (^ can start a block type.
- Left->Type = TT_ObjCBlockLParen;
- } else if (FormatToken *MaybeSel = Left->Previous) {
+ if (FormatToken *MaybeSel = Left->Previous) {
// @selector( starts a selector.
if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
MaybeSel->Previous->is(tok::at)) {
@@ -200,12 +222,21 @@ private:
Left->Type = TT_ObjCMethodExpr;
}
+ // MightBeFunctionType and ProbablyFunctionType are used for
+ // function pointer and reference types as well as Objective-C
+ // block types:
+ //
+ // void (*FunctionPointer)(void);
+ // void (&FunctionReference)(void);
+ // void (^ObjCBlock)(void);
bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;
- bool ProbablyFunctionType = CurrentToken->isOneOf(tok::star, tok::amp);
+ bool ProbablyFunctionType =
+ CurrentToken->isOneOf(tok::star, tok::amp, tok::caret);
bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false;
bool MightBeObjCForRangeLoop =
Left->Previous && Left->Previous->is(tok::kw_for);
+ FormatToken *PossibleObjCForInToken = nullptr;
while (CurrentToken) {
// LookForDecls is set when "if (" has been seen. Check for
// 'identifier' '*' 'identifier' followed by not '=' -- this
@@ -237,7 +268,8 @@ private:
if (MightBeFunctionType && ProbablyFunctionType && CurrentToken->Next &&
(CurrentToken->Next->is(tok::l_paren) ||
(CurrentToken->Next->is(tok::l_square) && Line.MustBeDeclaration)))
- Left->Type = TT_FunctionTypeLParen;
+ Left->Type = Left->Next->is(tok::caret) ? TT_ObjCBlockLParen
+ : TT_FunctionTypeLParen;
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
@@ -291,10 +323,17 @@ private:
CurrentToken->Previous->isSimpleTypeSpecifier()) &&
!CurrentToken->is(tok::l_brace))
Contexts.back().IsExpression = false;
- if (CurrentToken->isOneOf(tok::semi, tok::colon))
+ if (CurrentToken->isOneOf(tok::semi, tok::colon)) {
MightBeObjCForRangeLoop = false;
- if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in))
- CurrentToken->Type = TT_ObjCForIn;
+ if (PossibleObjCForInToken) {
+ PossibleObjCForInToken->Type = TT_Unknown;
+ PossibleObjCForInToken = nullptr;
+ }
+ }
+ if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) {
+ PossibleObjCForInToken = CurrentToken;
+ PossibleObjCForInToken->Type = TT_ObjCForIn;
+ }
// When we discover a 'new', we set CanBeExpression to 'false' in order to
// parse the type correctly. Reset that after a comma.
if (CurrentToken->is(tok::comma))
@@ -310,13 +349,40 @@ private:
return false;
}
+ bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
+ if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square))
+ return false;
+ const FormatToken *AttrTok = Tok.Next->Next;
+ if (!AttrTok)
+ return false;
+ // C++17 '[[using ns: foo, bar(baz, blech)]]'
+ // We assume nobody will name an ObjC variable 'using'.
+ if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
+ return true;
+ if (AttrTok->isNot(tok::identifier))
+ return false;
+ while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
+ // ObjC message send. We assume nobody will use : in a C++11 attribute
+ // specifier parameter, although this is technically valid:
+ // [[foo(:)]]
+ if (AttrTok->is(tok::colon) ||
+ AttrTok->startsSequence(tok::identifier, tok::identifier))
+ return false;
+ if (AttrTok->is(tok::ellipsis))
+ return true;
+ AttrTok = AttrTok->Next;
+ }
+ return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
+ }
+
bool parseSquare() {
if (!CurrentToken)
return false;
// A '[' could be an index subscript (after an identifier or after
// ')' or ']'), it could be the start of an Objective-C method
- // expression, or it could the start of an Objective-C array literal.
+ // expression, it could the start of an Objective-C array literal,
+ // or it could be a C++ attribute specifier [[foo::bar]].
FormatToken *Left = CurrentToken->Previous;
Left->ParentBracket = Contexts.back().ContextKind;
FormatToken *Parent = Left->getPreviousNonComment();
@@ -329,14 +395,18 @@ private:
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().InTemplateArgument);
+ bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
+ Contexts.back().InCpp11AttributeSpecifier;
+
bool StartsObjCMethodExpr =
- !CppArrayTemplates && Style.isCpp() &&
+ !CppArrayTemplates && Style.isCpp() && !IsCpp11AttributeSpecifier &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
- CurrentToken->isNot(tok::l_brace) &&
+ !CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
(!Parent ||
Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
tok::kw_return, tok::kw_throw) ||
Parent->isUnaryOperator() ||
+ // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
bool ColonFound = false;
@@ -347,6 +417,8 @@ private:
} else if (Left->is(TT_Unknown)) {
if (StartsObjCMethodExpr) {
Left->Type = TT_ObjCMethodExpr;
+ } else if (IsCpp11AttributeSpecifier) {
+ Left->Type = TT_AttributeSquare;
} else if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
@@ -358,12 +430,48 @@ private:
Parent->is(TT_TemplateCloser)) {
Left->Type = TT_ArraySubscriptLSquare;
} else if (Style.Language == FormatStyle::LK_Proto ||
- (!CppArrayTemplates && Parent &&
- Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,
- tok::comma, tok::l_paren, tok::l_square,
- tok::question, tok::colon, tok::kw_return,
- // Should only be relevant to JavaScript:
- tok::kw_default))) {
+ Style.Language == FormatStyle::LK_TextProto) {
+ // Square braces in LK_Proto can either be message field attributes:
+ //
+ // optional Aaa aaa = 1 [
+ // (aaa) = aaa
+ // ];
+ //
+ // extensions 123 [
+ // (aaa) = aaa
+ // ];
+ //
+ // or text proto extensions (in options):
+ //
+ // option (Aaa.options) = {
+ // [type.type/type] {
+ // key: value
+ // }
+ // }
+ //
+ // or repeated fields (in options):
+ //
+ // option (Aaa.options) = {
+ // keys: [ 1, 2, 3 ]
+ // }
+ //
+ // In the first and the third case we want to spread the contents inside
+ // the square braces; in the second we want to keep them inline.
+ Left->Type = TT_ArrayInitializerLSquare;
+ if (!Left->endsSequence(tok::l_square, tok::numeric_constant,
+ tok::equal) &&
+ !Left->endsSequence(tok::l_square, tok::numeric_constant,
+ tok::identifier) &&
+ !Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) {
+ Left->Type = TT_ProtoExtensionLSquare;
+ BindingIncrease = 10;
+ }
+ } else if (!CppArrayTemplates && Parent &&
+ Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,
+ tok::comma, tok::l_paren, tok::l_square,
+ tok::question, tok::colon, tok::kw_return,
+ // Should only be relevant to JavaScript:
+ tok::kw_default)) {
Left->Type = TT_ArrayInitializerLSquare;
} else {
BindingIncrease = 10;
@@ -378,11 +486,14 @@ private:
Contexts.back().IsExpression = false;
Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
+ Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;
while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
- if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
- Left->is(TT_ObjCMethodExpr)) {
+ if (IsCpp11AttributeSpecifier)
+ CurrentToken->Type = TT_AttributeSquare;
+ else if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
+ Left->is(TT_ObjCMethodExpr)) {
// An ObjC method call is rarely followed by an open parenthesis.
// FIXME: Do we incorrectly label ":" with this?
StartsObjCMethodExpr = false;
@@ -390,6 +501,12 @@ private:
}
if (StartsObjCMethodExpr && CurrentToken->Previous != Left) {
CurrentToken->Type = TT_ObjCMethodExpr;
+ // If we haven't seen a colon yet, make sure the last identifier
+ // before the r_square is tagged as a selector name component.
+ if (!ColonFound && CurrentToken->Previous &&
+ CurrentToken->Previous->is(TT_Unknown) &&
+ canBeObjCSelectorComponent(*CurrentToken->Previous))
+ CurrentToken->Previous->Type = TT_SelectorName;
// determineStarAmpUsage() thinks that '*' '[' is allocating an
// array of pointers, but if '[' starts a selector then '*' is a
// binary operator.
@@ -398,6 +515,20 @@ private:
}
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
+ // FirstObjCSelectorName is set when a colon is found. This does
+ // not work, however, when the method has no parameters.
+ // Here, we set FirstObjCSelectorName when the end of the method call is
+ // reached, in case it was not set already.
+ if (!Contexts.back().FirstObjCSelectorName) {
+ FormatToken* Previous = CurrentToken->getPreviousNonComment();
+ if (Previous && Previous->is(TT_SelectorName)) {
+ Previous->ObjCSelectorNameParts = 1;
+ Contexts.back().FirstObjCSelectorName = Previous;
+ }
+ } else {
+ Left->ParameterCount =
+ Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
+ }
if (Contexts.back().FirstObjCSelectorName) {
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
@@ -410,12 +541,19 @@ private:
if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
return false;
if (CurrentToken->is(tok::colon)) {
- if (Left->isOneOf(TT_ArraySubscriptLSquare,
- TT_DesignatedInitializerLSquare)) {
+ if (IsCpp11AttributeSpecifier &&
+ CurrentToken->endsSequence(tok::colon, tok::identifier,
+ tok::kw_using)) {
+ // Remember that this is a [[using ns: foo]] C++ attribute, so we
+ // don't add a space before the colon (unlike other colons).
+ CurrentToken->Type = TT_AttributeColon;
+ } else if (Left->isOneOf(TT_ArraySubscriptLSquare,
+ TT_DesignatedInitializerLSquare)) {
Left->Type = TT_ObjCMethodExpr;
StartsObjCMethodExpr = true;
Contexts.back().ColonIsObjCMethodExpr = true;
if (Parent && Parent->is(tok::r_paren))
+ // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
Parent->Type = TT_CastRParen;
}
ColonFound = true;
@@ -462,13 +600,15 @@ private:
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 ||
- Style.Language == FormatStyle::LK_TextProto) &&
- (Previous->Tok.getIdentifierInfo() ||
- Previous->is(tok::string_literal)))
- Previous->Type = TT_SelectorName;
+ if ((CurrentToken->is(tok::colon) &&
+ (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) {
+ Left->Type = TT_DictLiteral;
+ if (Previous->Tok.getIdentifierInfo() ||
+ Previous->is(tok::string_literal))
+ Previous->Type = TT_SelectorName;
+ }
if (CurrentToken->is(tok::colon) ||
Style.Language == FormatStyle::LK_JavaScript)
Left->Type = TT_DictLiteral;
@@ -484,6 +624,9 @@ private:
}
void updateParameterCount(FormatToken *Left, FormatToken *Current) {
+ // For ObjC methods, the number of parameters is calculated differently as
+ // method declarations have a different structure (the parameters are not
+ // inside a bracket scope).
if (Current->is(tok::l_brace) && Current->BlockKind == BK_Block)
++Left->BlockParameterCount;
if (Current->is(tok::comma)) {
@@ -562,19 +705,29 @@ private:
Line.startsWith(TT_ObjCMethodSpecifier)) {
Tok->Type = TT_ObjCMethodExpr;
const FormatToken *BeforePrevious = Tok->Previous->Previous;
+ // Ensure we tag all identifiers in method declarations as
+ // TT_SelectorName.
+ bool UnknownIdentifierInMethodDeclaration =
+ Line.startsWith(TT_ObjCMethodSpecifier) &&
+ Tok->Previous->is(tok::identifier) && Tok->Previous->is(TT_Unknown);
if (!BeforePrevious ||
+ // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
!(BeforePrevious->is(TT_CastRParen) ||
(BeforePrevious->is(TT_ObjCMethodExpr) &&
BeforePrevious->is(tok::colon))) ||
BeforePrevious->is(tok::r_square) ||
- Contexts.back().LongestObjCSelectorName == 0) {
+ Contexts.back().LongestObjCSelectorName == 0 ||
+ UnknownIdentifierInMethodDeclaration) {
Tok->Previous->Type = TT_SelectorName;
- if (Tok->Previous->ColumnWidth >
- Contexts.back().LongestObjCSelectorName)
- Contexts.back().LongestObjCSelectorName =
- Tok->Previous->ColumnWidth;
if (!Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName = Tok->Previous;
+ else if (Tok->Previous->ColumnWidth >
+ Contexts.back().LongestObjCSelectorName)
+ Contexts.back().LongestObjCSelectorName =
+ Tok->Previous->ColumnWidth;
+ Tok->Previous->ParameterIndex =
+ Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
+ ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
}
} else if (Contexts.back().ColonIsForRangeExpr) {
Tok->Type = TT_RangeBasedForLoopColon;
@@ -587,8 +740,10 @@ private:
Tok->Type = TT_CtorInitializerColon;
else
Tok->Type = TT_InheritanceColon;
- } else if (Tok->Previous->is(tok::identifier) && Tok->Next &&
- Tok->Next->isOneOf(tok::r_paren, tok::comma)) {
+ } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
+ (Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
+ (canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next &&
+ Tok->Next->Next->is(tok::colon)))) {
// This handles a special macro in ObjC code where selectors including
// the colon are passed as macro arguments.
Tok->Type = TT_ObjCMethodExpr;
@@ -668,7 +823,15 @@ private:
case tok::less:
if (parseAngle()) {
Tok->Type = TT_TemplateOpener;
- if (Style.Language == FormatStyle::LK_TextProto) {
+ // In TT_Proto, we must distignuish between:
+ // map<key, value>
+ // msg < item: data >
+ // msg: < item: data >
+ // In TT_TextProto, map<key, value> does not occur.
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto && Tok->Previous &&
+ Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
+ Tok->Type = TT_DictLiteral;
FormatToken *Previous = Tok->getPreviousNonComment();
if (Previous && Previous->Type != TT_DictLiteral)
Previous->Type = TT_SelectorName;
@@ -689,9 +852,13 @@ private:
return false;
break;
case tok::greater:
- Tok->Type = TT_BinaryOperator;
+ if (Style.Language != FormatStyle::LK_TextProto)
+ Tok->Type = TT_BinaryOperator;
break;
case tok::kw_operator:
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ Style.Language == FormatStyle::LK_Proto)
+ break;
while (CurrentToken &&
!CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
if (CurrentToken->isOneOf(tok::star, tok::amp))
@@ -987,7 +1154,7 @@ private:
resetTokenMetadata(CurrentToken);
}
- /// \brief A struct to hold information valid in a specific context, e.g.
+ /// A struct to hold information valid in a specific context, e.g.
/// a pair of parenthesis.
struct Context {
Context(tok::TokenKind ContextKind, unsigned BindingStrength,
@@ -1010,9 +1177,10 @@ private:
bool InInheritanceList = false;
bool CaretFound = false;
bool IsForEachMacro = false;
+ bool InCpp11AttributeSpecifier = false;
};
- /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
+ /// Puts a new \c Context onto the stack \c Contexts for the lifetime
/// of each instance.
struct ScopedContextCreator {
AnnotatingParser &P;
@@ -1155,7 +1323,9 @@ private:
Current.Type = TT_ConditionalExpr;
}
} else if (Current.isBinaryOperator() &&
- (!Current.Previous || Current.Previous->isNot(tok::l_square))) {
+ (!Current.Previous || Current.Previous->isNot(tok::l_square)) &&
+ (!Current.is(tok::greater) &&
+ Style.Language != FormatStyle::LK_TextProto)) {
Current.Type = TT_BinaryOperator;
} else if (Current.is(tok::comment)) {
if (Current.TokenText.startswith("/*")) {
@@ -1214,6 +1384,17 @@ private:
TT_LeadingJavaAnnotation)) {
Current.Type = Current.Previous->Type;
}
+ } else if (canBeObjCSelectorComponent(Current) &&
+ // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
+ Current.Previous && Current.Previous->is(TT_CastRParen) &&
+ Current.Previous->MatchingParen &&
+ Current.Previous->MatchingParen->Previous &&
+ Current.Previous->MatchingParen->Previous->is(
+ TT_ObjCMethodSpecifier)) {
+ // This is the first part of an Objective-C selector name. (If there's no
+ // colon after this, this is the only place which annotates the identifier
+ // as a selector.)
+ Current.Type = TT_SelectorName;
} else if (Current.isOneOf(tok::identifier, tok::kw_const) &&
Current.Previous &&
!Current.Previous->isOneOf(tok::equal, tok::at) &&
@@ -1240,7 +1421,7 @@ private:
}
}
- /// \brief Take a guess at whether \p Tok starts a name of a function or
+ /// Take a guess at whether \p Tok starts a name of a function or
/// variable declaration.
///
/// This is a heuristic based on whether \p Tok is an identifier following
@@ -1285,7 +1466,7 @@ private:
PreviousNotConst->isSimpleTypeSpecifier();
}
- /// \brief Determine whether ')' is ending a cast.
+ /// Determine whether ')' is ending a cast.
bool rParenEndsCast(const FormatToken &Tok) {
// C-style casts are only used in C++ and Java.
if (!Style.isCpp() && Style.Language != FormatStyle::LK_Java)
@@ -1382,7 +1563,7 @@ private:
return true;
}
- /// \brief Return the type of the given token assuming it is * or &.
+ /// Return the type of the given token assuming it is * or &.
TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
bool InTemplateArgument) {
if (Style.Language == FormatStyle::LK_JavaScript)
@@ -1459,10 +1640,8 @@ private:
if (!PrevToken)
return TT_UnaryOperator;
- if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator) &&
- !PrevToken->is(tok::exclaim))
- // There aren't any trailing unary operators except for TypeScript's
- // non-null operator (!). Thus, this must be squence of leading operators.
+ if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator))
+ // This must be a sequence of leading unary operators.
return TT_UnaryOperator;
// Use heuristics to recognize unary operators.
@@ -1479,7 +1658,7 @@ private:
return TT_BinaryOperator;
}
- /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
+ /// Determine whether ++/-- are pre- or post-increments/-decrements.
TokenType determineIncrementUsage(const FormatToken &Tok) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
if (!PrevToken || PrevToken->is(TT_CastRParen))
@@ -1508,7 +1687,7 @@ private:
static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;
static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
-/// \brief Parses binary expressions by inserting fake parenthesis based on
+/// Parses binary expressions by inserting fake parenthesis based on
/// operator precedence.
class ExpressionParser {
public:
@@ -1516,7 +1695,7 @@ public:
AnnotatedLine &Line)
: Style(Style), Keywords(Keywords), Current(Line.First) {}
- /// \brief Parse expressions with the given operatore precedence.
+ /// Parse expressions with the given operator precedence.
void parse(int Precedence = 0) {
// Skip 'return' and ObjC selector colons as they are not part of a binary
// expression.
@@ -1603,7 +1782,7 @@ public:
}
private:
- /// \brief Gets the precedence (+1) of the given token for binary operators
+ /// Gets the precedence (+1) of the given token for binary operators
/// and other tokens that we treat like binary operators.
int getCurrentPrecedence() {
if (Current) {
@@ -1662,7 +1841,7 @@ private:
}
}
- /// \brief Parse unary operator expressions and surround them with fake
+ /// Parse unary operator expressions and surround them with fake
/// parentheses if appropriate.
void parseUnaryOperator() {
llvm::SmallVector<FormatToken *, 2> Tokens;
@@ -1965,8 +2144,20 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
// FIXME: Only calculate this if CanBreakBefore is true once static
// initializers etc. are sorted out.
// FIXME: Move magic numbers to a better place.
- Current->SplitPenalty = 20 * Current->BindingStrength +
- splitPenalty(Line, *Current, InFunctionDecl);
+
+ // Reduce penalty for aligning ObjC method arguments using the colon
+ // alignment as this is the canonical way (still prefer fitting everything
+ // into one line if possible). Trying to fit a whole expression into one
+ // line should not force other line breaks (e.g. when ObjC method
+ // expression is a part of other expression).
+ Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl);
+ if (Style.Language == FormatStyle::LK_ObjC &&
+ Current->is(TT_SelectorName) && Current->ParameterIndex > 0) {
+ if (Current->ParameterIndex == 1)
+ Current->SplitPenalty += 5 * Current->BindingStrength;
+ } else {
+ Current->SplitPenalty += 20 * Current->BindingStrength;
+ }
Current = Current->Next;
}
@@ -1986,7 +2177,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
++IndentLevel;
}
- DEBUG({ printDebugInfo(Line); });
+ LLVM_DEBUG({ printDebugInfo(Line); });
}
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
@@ -2046,7 +2237,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 35;
if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_ArrayInitializerLSquare,
- TT_DesignatedInitializerLSquare))
+ TT_DesignatedInitializerLSquare, TT_AttributeSquare))
return 500;
}
@@ -2131,6 +2322,13 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr))
return Line.MightBeFunctionDecl ? 50 : 500;
+ // In Objective-C type declarations, avoid breaking after the category's
+ // open paren (we'll prefer breaking after the protocol list's opening
+ // angle bracket, if present).
+ if (Line.Type == LT_ObjCDecl && Left.is(tok::l_paren) && Left.Previous &&
+ Left.Previous->isOneOf(tok::identifier, tok::greater))
+ return 500;
+
if (Left.is(tok::l_paren) && InFunctionDecl &&
Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
return 100;
@@ -2147,6 +2345,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.opensScope()) {
if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
return 0;
+ if (Left.is(tok::l_brace) && !Style.Cpp11BracedListStyle)
+ return 19;
return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
: 19;
}
@@ -2172,6 +2372,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 2;
return 1;
}
+ if (Left.ClosesTemplateDeclaration)
+ return Style.PenaltyBreakTemplateDeclaration;
if (Left.is(TT_ConditionalExpr))
return prec::Conditional;
prec::Level Level = Left.getPrecedence();
@@ -2208,9 +2410,12 @@ 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)
- return true;
+ if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) {
+ bool IsLightweightGeneric =
+ Right.MatchingParen && Right.MatchingParen->Next &&
+ Right.MatchingParen->Next->is(tok::colon);
+ return !IsLightweightGeneric && Style.ObjCSpaceBeforeProtocolList;
+ }
if (Right.is(tok::less) && Left.is(tok::kw_template))
return Style.SpaceAfterTemplateKeyword;
if (Left.isOneOf(tok::exclaim, tok::tilde))
@@ -2224,8 +2429,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return !Left.is(TT_ObjCMethodExpr);
if (Left.is(tok::coloncolon))
return false;
- if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
+ if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto &&
+ (Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) {
+ // Format empty list as `<>`.
+ if (Left.is(tok::less) && Right.is(tok::greater))
+ return false;
+ return !Style.Cpp11BracedListStyle;
+ }
return false;
+ }
if (Right.is(tok::ellipsis))
return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
Left.Previous->is(tok::kw_case));
@@ -2266,23 +2480,34 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
+ const auto SpaceRequiredForArrayInitializerLSquare =
+ [](const FormatToken &LSquareTok, const FormatStyle &Style) {
+ return Style.SpacesInContainerLiterals ||
+ ((Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
+ !Style.Cpp11BracedListStyle &&
+ LSquareTok.endsSequence(tok::l_square, tok::colon,
+ TT_SelectorName));
+ };
if (Left.is(tok::l_square))
- return (Left.is(TT_ArrayInitializerLSquare) &&
- Style.SpacesInContainerLiterals && Right.isNot(tok::r_square)) ||
+ return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
+ SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
(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)) ||
+ ((Right.MatchingParen->is(TT_ArrayInitializerLSquare) &&
+ SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen,
+ Style)) ||
(Style.SpacesInSquareBrackets &&
Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
- TT_StructuredBindingLSquare)));
+ TT_StructuredBindingLSquare)) ||
+ Right.MatchingParen->is(TT_AttributeParen));
if (Right.is(tok::l_square) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_DesignatedInitializerLSquare,
- TT_StructuredBindingLSquare) &&
+ TT_StructuredBindingLSquare, TT_AttributeSquare) &&
!Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
@@ -2294,7 +2519,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(TT_BlockComment))
return !Left.TokenText.endswith("=*/");
if (Right.is(tok::l_paren)) {
- if (Left.is(tok::r_paren) && Left.is(TT_AttributeParen))
+ if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
+ (Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
return true;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
@@ -2332,6 +2558,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
return false;
+ if (Left.is(tok::l_brace) && Left.endsSequence(TT_DictLiteral, tok::at))
+ // Objective-C dictionary literal -> no space after opening brace.
+ return false;
+ if (Right.is(tok::r_brace) && Right.MatchingParen &&
+ Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at))
+ // Objective-C dictionary literal -> no space before closing brace.
+ return false;
return true;
}
@@ -2343,6 +2576,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Style.isCpp()) {
if (Left.is(tok::kw_operator))
return Right.is(tok::coloncolon);
+ if (Right.is(tok::l_brace) && Right.BlockKind == BK_BracedInit &&
+ !Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
+ return true;
} else if (Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) {
if (Right.is(tok::period) &&
@@ -2354,6 +2590,19 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))
return true;
+ // Slashes occur in text protocol extension syntax: [type/type] { ... }.
+ if (Left.is(tok::slash) || Right.is(tok::slash))
+ return false;
+ if (Left.MatchingParen && Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&
+ Right.isOneOf(tok::l_brace, tok::less))
+ return !Style.Cpp11BracedListStyle;
+ // A percent is probably part of a formatting specification, such as %lld.
+ if (Left.is(tok::percent))
+ return false;
+ // Preserve the existence of a space before a percent for cases like 0x%04x
+ // and "%d %d"
+ if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
+ return Right.WhitespaceRange.getEnd() != Right.WhitespaceRange.getBegin();
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
@@ -2405,7 +2654,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// (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.is(tok::identifier) ||
Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
(!Left.Previous || !Left.Previous->is(tok::period)))
return true;
@@ -2458,8 +2707,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Line.Type == LT_ObjCMethodDecl) {
if (Left.is(TT_ObjCMethodSpecifier))
return true;
- if (Left.is(tok::r_paren) && Right.is(tok::identifier))
- // Don't space between ')' and <id>
+ if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right))
+ // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
+ // keyword in Objective-C, and '+ (instancetype)new;' is a standard class
+ // method declaration.
return false;
}
if (Line.Type == LT_ObjCProperty &&
@@ -2475,8 +2726,15 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
if (Right.is(tok::comma))
return false;
- if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen))
+ if (Right.is(TT_ObjCBlockLParen))
return true;
+ if (Right.is(TT_CtorInitializerColon))
+ return Style.SpaceBeforeCtorInitializerColon;
+ if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)
+ return false;
+ if (Right.is(TT_RangeBasedForLoopColon) &&
+ !Style.SpaceBeforeRangeBasedForLoopColon)
+ return false;
if (Right.is(tok::colon)) {
if (Line.First->isOneOf(tok::kw_case, tok::kw_default) ||
!Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
@@ -2489,6 +2747,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
if (Right.is(TT_DictLiteral))
return Style.SpacesInContainerLiterals;
+ if (Right.is(TT_AttributeColon))
+ return false;
return true;
}
if (Left.is(TT_UnaryOperator))
@@ -2500,9 +2760,13 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return Style.SpaceAfterCStyleCast ||
Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
- if (Left.is(tok::greater) && Right.is(tok::greater))
+ if (Left.is(tok::greater) && Right.is(tok::greater)) {
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
+ return !Style.Cpp11BracedListStyle;
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
(Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
+ }
if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
(Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
@@ -2520,7 +2784,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Style.Standard == FormatStyle::LS_Cpp03) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
tok::kw___super, TT_TemplateCloser,
- TT_TemplateOpener));
+ TT_TemplateOpener)) ||
+ (Left.is(tok ::l_paren) && Style.SpacesInParentheses);
if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
return Style.SpacesInAngles;
// Space before TT_StructuredBindingLSquare.
@@ -2600,7 +2865,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return true;
} else if (Style.Language == FormatStyle::LK_Cpp ||
Style.Language == FormatStyle::LK_ObjC ||
- Style.Language == FormatStyle::LK_Proto) {
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) {
if (Left.isStringLiteral() && Right.isStringLiteral())
return true;
}
@@ -2642,7 +2908,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.Previous->ClosesTemplateDeclaration &&
Right.Previous->MatchingParen &&
Right.Previous->MatchingParen->NestingLevel == 0 &&
- Style.AlwaysBreakTemplateDeclarations)
+ Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes)
return true;
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
@@ -2653,13 +2919,14 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
return true;
// Break only if we have multiple inheritance.
- if (Style.BreakBeforeInheritanceComma && Right.is(TT_InheritanceComma))
+ if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
+ 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;
+ // Multiline 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.IsMultiline && Right.NewlinesBefore > 0;
if ((Right.Previous->is(tok::l_brace) ||
(Right.Previous->is(tok::less) && Right.Previous->Previous &&
Right.Previous->Previous->is(tok::equal))) &&
@@ -2686,6 +2953,94 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
(Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations))
return true;
+ if (Right.is(TT_ProtoExtensionLSquare))
+ return true;
+
+ // In text proto instances if a submessage contains at least 2 entries and at
+ // least one of them is a submessage, like A { ... B { ... } ... },
+ // put all of the entries of A on separate lines by forcing the selector of
+ // the submessage B to be put on a newline.
+ //
+ // Example: these can stay on one line:
+ // a { scalar_1: 1 scalar_2: 2 }
+ // a { b { key: value } }
+ //
+ // and these entries need to be on a new line even if putting them all in one
+ // line is under the column limit:
+ // a {
+ // scalar: 1
+ // b { key: value }
+ // }
+ //
+ // We enforce this by breaking before a submessage field that has previous
+ // siblings, *and* breaking before a field that follows a submessage field.
+ //
+ // Be careful to exclude the case [proto.ext] { ... } since the `]` is
+ // the TT_SelectorName there, but we don't want to break inside the brackets.
+ //
+ // Another edge case is @submessage { key: value }, which is a common
+ // substitution placeholder. In this case we want to keep `@` and `submessage`
+ // together.
+ //
+ // We ensure elsewhere that extensions are always on their own line.
+ if ((Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
+ Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
+ // Keep `@submessage` together in:
+ // @submessage { key: value }
+ if (Right.Previous && Right.Previous->is(tok::at))
+ return false;
+ // Look for the scope opener after selector in cases like:
+ // selector { ...
+ // selector: { ...
+ // selector: @base { ...
+ FormatToken *LBrace = Right.Next;
+ if (LBrace && LBrace->is(tok::colon)) {
+ LBrace = LBrace->Next;
+ if (LBrace && LBrace->is(tok::at)) {
+ LBrace = LBrace->Next;
+ if (LBrace)
+ LBrace = LBrace->Next;
+ }
+ }
+ if (LBrace &&
+ // The scope opener is one of {, [, <:
+ // selector { ... }
+ // selector [ ... ]
+ // selector < ... >
+ //
+ // In case of selector { ... }, the l_brace is TT_DictLiteral.
+ // In case of an empty selector {}, the l_brace is not TT_DictLiteral,
+ // so we check for immediately following r_brace.
+ ((LBrace->is(tok::l_brace) &&
+ (LBrace->is(TT_DictLiteral) ||
+ (LBrace->Next && LBrace->Next->is(tok::r_brace)))) ||
+ LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) {
+ // If Left.ParameterCount is 0, then this submessage entry is not the
+ // first in its parent submessage, and we want to break before this entry.
+ // If Left.ParameterCount is greater than 0, then its parent submessage
+ // might contain 1 or more entries and we want to break before this entry
+ // if it contains at least 2 entries. We deal with this case later by
+ // detecting and breaking before the next entry in the parent submessage.
+ if (Left.ParameterCount == 0)
+ return true;
+ // However, if this submessage is the first entry in its parent
+ // submessage, Left.ParameterCount might be 1 in some cases.
+ // We deal with this case later by detecting an entry
+ // following a closing paren of this submessage.
+ }
+
+ // If this is an entry immediately following a submessage, it will be
+ // preceded by a closing paren of that submessage, like in:
+ // left---. .---right
+ // v v
+ // sub: { ... } key: value
+ // If there was a comment between `}` an `key` above, then `key` would be
+ // put on a new line anyways.
+ if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))
+ return true;
+ }
+
return false;
}
@@ -2711,14 +3066,19 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
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 (Right.NestingLevel == 0 &&
+ (Left.Tok.getIdentifierInfo() ||
+ Left.isOneOf(tok::r_square, tok::r_paren)) &&
+ Right.isOneOf(tok::l_square, tok::l_paren))
+ return false; // Otherwise automatic semicolon insertion would trigger.
if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
return false;
if (Left.is(TT_JsTypeColon))
return true;
- if (Right.NestingLevel == 0 && Right.is(Keywords.kw_is))
+ // Don't wrap between ":" and "!" of a strict prop init ("field!: type;").
+ if (Left.is(tok::exclaim) && Right.is(tok::colon))
+ return false;
+ if (Right.is(Keywords.kw_is))
return false;
if (Left.is(Keywords.kw_in))
return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;
@@ -2777,16 +3137,56 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return Style.BreakBeforeTernaryOperators;
if (Left.is(TT_ConditionalExpr) || Left.is(tok::question))
return !Style.BreakBeforeTernaryOperators;
+ if (Left.is(TT_InheritanceColon))
+ return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon;
if (Right.is(TT_InheritanceColon))
- return true;
+ return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon;
if (Right.is(TT_ObjCMethodExpr) && !Right.is(tok::r_square) &&
Left.isNot(TT_SelectorName))
return true;
+
if (Right.is(tok::colon) &&
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon))
return false;
- if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr))
+ if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
+ if (Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) {
+ if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral())
+ return false;
+ // Prevent cases like:
+ //
+ // submessage:
+ // { key: valueeeeeeeeeeee }
+ //
+ // when the snippet does not fit into one line.
+ // Prefer:
+ //
+ // submessage: {
+ // key: valueeeeeeeeeeee
+ // }
+ //
+ // instead, even if it is longer by one line.
+ //
+ // Note that this allows allows the "{" to go over the column limit
+ // when the column limit is just between ":" and "{", but that does
+ // not happen too often and alternative formattings in this case are
+ // not much better.
+ //
+ // The code covers the cases:
+ //
+ // submessage: { ... }
+ // submessage: < ... >
+ // repeated: [ ... ]
+ if (((Right.is(tok::l_brace) || Right.is(tok::less)) &&
+ Right.is(TT_DictLiteral)) ||
+ Right.is(TT_ArrayInitializerLSquare))
+ return false;
+ }
return true;
+ }
+ if (Right.is(tok::r_square) && Right.MatchingParen &&
+ Right.MatchingParen->is(TT_ProtoExtensionLSquare))
+ return false;
if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&
Right.Next->is(TT_ObjCMethodExpr)))
return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.
@@ -2809,6 +3209,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&
Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0)
return false;
+ if (Left.is(tok::equal) && Right.is(tok::l_brace) &&
+ !Style.Cpp11BracedListStyle)
+ return false;
if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen))
return false;
if (Left.is(tok::l_paren) && Left.Previous &&
@@ -2834,7 +3237,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,
tok::less, tok::coloncolon);
- if (Right.is(tok::kw___attribute))
+ if (Right.is(tok::kw___attribute) ||
+ (Right.is(tok::l_square) && Right.is(TT_AttributeSquare)))
return true;
if (Left.is(tok::identifier) && Right.is(tok::string_literal))
@@ -2853,9 +3257,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
return true;
- if (Left.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma)
+ if (Left.is(TT_InheritanceComma) &&
+ Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma)
return false;
- if (Right.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma)
+ if (Right.is(TT_InheritanceComma) &&
+ Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma)
return true;
if ((Left.is(tok::greater) && Right.is(tok::greater)) ||
(Left.is(tok::less) && Right.is(tok::less)))
@@ -2875,6 +3281,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
(Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||
Left.getPrecedence() == prec::Assignment))
return true;
+ if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||
+ (Left.is(tok::r_square) && Right.is(TT_AttributeSquare)))
+ return false;
return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct, tok::comment) ||
Right.isMemberAccess() ||
@@ -2901,6 +3310,7 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
+ llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo();
llvm::errs() << " Text='" << Tok->TokenText << "'\n";
if (!Tok->Next)
assert(Tok == Line.Last);
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
index 04a18d45b82e..a3124fcb3d65 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a token annotator, i.e. creates
+/// This file implements a token annotator, i.e. creates
/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
///
//===----------------------------------------------------------------------===//
@@ -40,6 +40,7 @@ public:
AnnotatedLine(const UnwrappedLine &Line)
: First(Line.Tokens.front().Tok), Level(Line.Level),
MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
+ MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
InPPDirective(Line.InPPDirective),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
IsMultiVariableDeclStmt(false), Affected(false),
@@ -112,6 +113,7 @@ public:
LineType Type;
unsigned Level;
size_t MatchingOpeningBlockLineIndex;
+ size_t MatchingClosingBlockLineIndex;
bool InPPDirective;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
@@ -136,14 +138,14 @@ private:
void operator=(const AnnotatedLine &) = delete;
};
-/// \brief Determines extra information about the tokens comprising an
+/// Determines extra information about the tokens comprising an
/// \c UnwrappedLine.
class TokenAnnotator {
public:
TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
: Style(Style), Keywords(Keywords) {}
- /// \brief Adapts the indent levels of comment lines to the indent of the
+ /// Adapts the indent levels of comment lines to the indent of the
/// subsequent line.
// FIXME: Can/should this be done in the UnwrappedLineParser?
void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
@@ -152,14 +154,14 @@ public:
void calculateFormattingInformation(AnnotatedLine &Line);
private:
- /// \brief Calculate the penalty for splitting before \c Tok.
+ /// Calculate the penalty for splitting before \c Tok.
unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
bool InFunctionDecl);
bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
const FormatToken &Right);
- bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
+ bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Right);
bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
index 60dc1a7169d1..906dae40cbee 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "NamespaceEndCommentsFixer.h"
#include "UnwrappedLineFormatter.h"
#include "WhitespaceManager.h"
#include "llvm/Support/Debug.h"
@@ -26,7 +27,7 @@ bool startsExternCBlock(const AnnotatedLine &Line) {
NextNext && NextNext->is(tok::l_brace);
}
-/// \brief Tracks the indent level of \c AnnotatedLines across levels.
+/// Tracks the indent level of \c AnnotatedLines across levels.
///
/// \c nextLine must be called for each \c AnnotatedLine, after which \c
/// getIndent() will return the indent for the last line \c nextLine was called
@@ -45,10 +46,10 @@ public:
IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
}
- /// \brief Returns the indent for the current line.
+ /// Returns the indent for the current line.
unsigned getIndent() const { return Indent; }
- /// \brief Update the indent state given that \p Line is going to be formatted
+ /// Update the indent state given that \p Line is going to be formatted
/// next.
void nextLine(const AnnotatedLine &Line) {
Offset = getIndentOffset(*Line.First);
@@ -66,14 +67,14 @@ public:
Indent += Offset;
}
- /// \brief Update the indent state given that \p Line indent should be
+ /// Update the indent state given that \p Line indent should be
/// skipped.
void skipLine(const AnnotatedLine &Line) {
while (IndentForLevel.size() <= Line.Level)
IndentForLevel.push_back(Indent);
}
- /// \brief Update the level indent to adapt to the given \p Line.
+ /// Update the level indent to adapt to the given \p Line.
///
/// When a line is not formatted, we move the subsequent lines on the same
/// level to the same indent.
@@ -88,7 +89,7 @@ public:
}
private:
- /// \brief Get the offset of the line relatively to the level.
+ /// Get the offset of the line relatively to the level.
///
/// For example, 'public:' labels in classes are offset by 1 or 2
/// characters to the left from their level.
@@ -104,7 +105,7 @@ private:
return 0;
}
- /// \brief Get the indent of \p Level from \p IndentForLevel.
+ /// Get the indent of \p Level from \p IndentForLevel.
///
/// \p IndentForLevel must contain the indent for the level \c l
/// at \p IndentForLevel[l], or a value < 0 if the indent for
@@ -121,16 +122,16 @@ private:
const AdditionalKeywords &Keywords;
const unsigned AdditionalIndent;
- /// \brief The indent in characters for each level.
+ /// The indent in characters for each level.
std::vector<int> IndentForLevel;
- /// \brief Offset of the current line relative to the indent level.
+ /// Offset of the current line relative to the indent level.
///
/// For example, the 'public' keywords is often indented with a negative
/// offset.
int Offset = 0;
- /// \brief The current line's indent.
+ /// The current line's indent.
unsigned Indent = 0;
};
@@ -157,7 +158,7 @@ public:
: Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()),
AnnotatedLines(Lines) {}
- /// \brief Returns the next line, merging multiple lines into one if possible.
+ /// Returns the next line, merging multiple lines into one if possible.
const AnnotatedLine *getNextMergedLine(bool DryRun,
LevelIndentTracker &IndentTracker) {
if (Next == End)
@@ -179,7 +180,7 @@ public:
}
private:
- /// \brief Calculates how many lines can be merged into 1 starting at \p I.
+ /// Calculates how many lines can be merged into 1 starting at \p I.
unsigned
tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
SmallVectorImpl<AnnotatedLine *>::const_iterator I,
@@ -251,9 +252,9 @@ private:
if (Style.CompactNamespaces) {
if (isNamespaceDeclaration(TheLine)) {
int i = 0;
- unsigned closingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
+ unsigned closingLine = TheLine->MatchingClosingBlockLineIndex - 1;
for (; I + 1 + i != E && isNamespaceDeclaration(I[i + 1]) &&
- closingLine == I[i + 1]->MatchingOpeningBlockLineIndex &&
+ closingLine == I[i + 1]->MatchingClosingBlockLineIndex &&
I[i + 1]->Last->TotalLength < Limit;
i++, closingLine--) {
// No extra indent for compacted namespaces
@@ -304,9 +305,23 @@ private:
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;
+ unsigned MergedLines = 0;
+ if (Style.AllowShortBlocksOnASingleLine) {
+ MergedLines = tryMergeSimpleBlock(I - 1, E, Limit);
+ // If we managed to merge the block, discard the first merged line
+ // since we are merging starting from I.
+ if (MergedLines > 0)
+ --MergedLines;
+ }
+ return MergedLines;
+ }
+ // Don't merge block with left brace wrapped after ObjC special blocks
+ if (TheLine->First->is(tok::l_brace) && I != AnnotatedLines.begin() &&
+ I[-1]->First->is(tok::at) && I[-1]->First->Next) {
+ tok::ObjCKeywordKind kwId = I[-1]->First->Next->Tok.getObjCKeywordID();
+ if (kwId == clang::tok::objc_autoreleasepool ||
+ kwId == clang::tok::objc_synchronized)
+ return 0;
}
// Try to merge a block with left brace wrapped that wasn't yet covered
if (TheLine->Last->is(tok::l_brace)) {
@@ -644,14 +659,14 @@ static void markFinalized(FormatToken *Tok) {
static void printLineState(const LineState &State) {
llvm::dbgs() << "State: ";
for (const ParenState &P : State.Stack) {
- llvm::dbgs() << P.Indent << "|" << P.LastSpace << "|" << P.NestedBlockIndent
- << " ";
+ llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent << "|"
+ << P.LastSpace << "|" << P.NestedBlockIndent << " ";
}
llvm::dbgs() << State.NextToken->TokenText << "\n";
}
#endif
-/// \brief Base class for classes that format one \c AnnotatedLine.
+/// Base class for classes that format one \c AnnotatedLine.
class LineFormatter {
public:
LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
@@ -661,7 +676,7 @@ public:
BlockFormatter(BlockFormatter) {}
virtual ~LineFormatter() {}
- /// \brief Formats an \c AnnotatedLine and returns the penalty.
+ /// Formats an \c AnnotatedLine and returns the penalty.
///
/// If \p DryRun is \c false, directly applies the changes.
virtual unsigned formatLine(const AnnotatedLine &Line,
@@ -670,7 +685,7 @@ public:
bool DryRun) = 0;
protected:
- /// \brief If the \p State's next token is an r_brace closing a nested block,
+ /// If the \p State's next token is an r_brace closing a nested block,
/// format the nested block before it.
///
/// Returns \c true if all children could be placed successfully and adapts
@@ -752,7 +767,7 @@ private:
UnwrappedLineFormatter *BlockFormatter;
};
-/// \brief Formatter that keeps the existing line breaks.
+/// Formatter that keeps the existing line breaks.
class NoColumnLimitLineFormatter : public LineFormatter {
public:
NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
@@ -761,7 +776,7 @@ public:
UnwrappedLineFormatter *BlockFormatter)
: LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
- /// \brief Formats the line, simply keeping all of the input's line breaking
+ /// Formats the line, simply keeping all of the input's line breaking
/// decisions.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
unsigned FirstStartColumn, bool DryRun) override {
@@ -780,7 +795,7 @@ public:
}
};
-/// \brief Formatter that puts all tokens into a single line without breaks.
+/// Formatter that puts all tokens into a single line without breaks.
class NoLineBreakFormatter : public LineFormatter {
public:
NoLineBreakFormatter(ContinuationIndenter *Indenter,
@@ -788,7 +803,7 @@ public:
UnwrappedLineFormatter *BlockFormatter)
: LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
- /// \brief Puts all tokens into a single line.
+ /// Puts all tokens into a single line.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
unsigned FirstStartColumn, bool DryRun) override {
unsigned Penalty = 0;
@@ -803,7 +818,7 @@ public:
}
};
-/// \brief Finds the best way to break lines.
+/// Finds the best way to break lines.
class OptimizingLineFormatter : public LineFormatter {
public:
OptimizingLineFormatter(ContinuationIndenter *Indenter,
@@ -812,7 +827,7 @@ public:
UnwrappedLineFormatter *BlockFormatter)
: LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
- /// \brief Formats the line by finding the best line breaks with line lengths
+ /// Formats the line by finding the best line breaks with line lengths
/// below the column limit.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
unsigned FirstStartColumn, bool DryRun) override {
@@ -835,14 +850,14 @@ private:
}
};
- /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.
+ /// A pair of <penalty, count> that is used to prioritize the BFS on.
///
/// In case of equal penalties, we want to prefer states that were inserted
/// first. During state generation we make sure that we insert states first
/// that break the line as late as possible.
typedef std::pair<unsigned, unsigned> OrderedPenalty;
- /// \brief An edge in the solution space from \c Previous->State to \c State,
+ /// An edge in the solution space from \c Previous->State to \c State,
/// inserting a newline dependent on the \c NewLine.
struct StateNode {
StateNode(const LineState &State, bool NewLine, StateNode *Previous)
@@ -852,16 +867,16 @@ private:
StateNode *Previous;
};
- /// \brief An item in the prioritized BFS search queue. The \c StateNode's
+ /// An item in the prioritized BFS search queue. The \c StateNode's
/// \c State has the given \c OrderedPenalty.
typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
- /// \brief The BFS queue type.
+ /// The BFS queue type.
typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
std::greater<QueueItem>>
QueueType;
- /// \brief Analyze the entire solution space starting from \p InitialState.
+ /// Analyze the entire solution space starting from \p InitialState.
///
/// This implements a variant of Dijkstra's algorithm on the graph that spans
/// the solution space (\c LineStates are the nodes). The algorithm tries to
@@ -890,7 +905,8 @@ private:
Penalty = Queue.top().first.first;
StateNode *Node = Queue.top().second;
if (!Node->State.NextToken) {
- DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << "\n---\nPenalty for line: " << Penalty << "\n");
break;
}
Queue.pop();
@@ -914,7 +930,7 @@ private:
if (Queue.empty()) {
// We were unable to find a solution, do nothing.
// FIXME: Add diagnostic?
- DEBUG(llvm::dbgs() << "Could not find a solution.\n");
+ LLVM_DEBUG(llvm::dbgs() << "Could not find a solution.\n");
return 0;
}
@@ -922,13 +938,14 @@ private:
if (!DryRun)
reconstructPath(InitialState, Queue.top().second);
- DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
- DEBUG(llvm::dbgs() << "---\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << "Total number of analyzed states: " << Count << "\n");
+ LLVM_DEBUG(llvm::dbgs() << "---\n");
return Penalty;
}
- /// \brief Add the following state to the analysis queue \c Queue.
+ /// Add the following state to the analysis queue \c Queue.
///
/// Assume the current state is \p PreviousNode and has been reached with a
/// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
@@ -950,7 +967,7 @@ private:
++(*Count);
}
- /// \brief Applies the best formatting by reconstructing the path in the
+ /// Applies the best formatting by reconstructing the path in the
/// solution space that leads to \c Best.
void reconstructPath(LineState &State, StateNode *Best) {
std::deque<StateNode *> Path;
@@ -965,7 +982,7 @@ private:
formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);
- DEBUG({
+ LLVM_DEBUG({
printLineState((*I)->Previous->State);
if ((*I)->NewLine) {
llvm::dbgs() << "Penalty for placing "
@@ -1018,9 +1035,12 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
// scope was added. However, we need to carefully stop doing this when we
// exit the scope of affected lines to prevent indenting a the entire
// remaining file if it currently missing a closing brace.
+ bool PreviousRBrace =
+ PreviousLine && PreviousLine->startsWith(tok::r_brace);
bool ContinueFormatting =
TheLine.Level > RangeMinLevel ||
- (TheLine.Level == RangeMinLevel && !TheLine.startsWith(tok::r_brace));
+ (TheLine.Level == RangeMinLevel && !PreviousRBrace &&
+ !TheLine.startsWith(tok::r_brace));
bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
Indent != TheLine.First->OriginalColumn;
@@ -1036,8 +1056,7 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
if (ShouldFormat && TheLine.Type != LT_Invalid) {
if (!DryRun) {
bool LastLine = Line->First->is(tok::eof);
- formatFirstToken(TheLine, PreviousLine,
- Indent,
+ formatFirstToken(TheLine, PreviousLine, Lines, Indent,
LastLine ? LastStartColumn : NextStartColumn + Indent);
}
@@ -1081,7 +1100,7 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
TheLine.LeadingEmptyLinesAffected);
// Format the first token.
if (ReformatLeadingWhitespace)
- formatFirstToken(TheLine, PreviousLine,
+ formatFirstToken(TheLine, PreviousLine, Lines,
TheLine.First->OriginalColumn,
TheLine.First->OriginalColumn);
else
@@ -1103,10 +1122,10 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
return Penalty;
}
-void UnwrappedLineFormatter::formatFirstToken(const AnnotatedLine &Line,
- const AnnotatedLine *PreviousLine,
- unsigned Indent,
- unsigned NewlineIndent) {
+void UnwrappedLineFormatter::formatFirstToken(
+ const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
+ const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
+ unsigned NewlineIndent) {
FormatToken &RootToken = *Line.First;
if (RootToken.is(tok::eof)) {
unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u);
@@ -1120,7 +1139,9 @@ void UnwrappedLineFormatter::formatFirstToken(const AnnotatedLine &Line,
// Remove empty lines before "}" where applicable.
if (RootToken.is(tok::r_brace) &&
(!RootToken.Next ||
- (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))
+ (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
+ // Do not remove empty lines before namespace closing "}".
+ !getNamespaceToken(&Line, Lines))
Newlines = std::min(Newlines, 1u);
// Remove empty lines at the start of nested blocks (lambdas/arrow functions)
if (PreviousLine == nullptr && Line.Level > 0)
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
index 6432ca83a4c9..dac210ea62b1 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements a combinartorial exploration of all the different
+/// Implements a combinartorial exploration of all the different
/// linebreaks unwrapped lines can be formatted in.
///
//===----------------------------------------------------------------------===//
@@ -37,7 +37,7 @@ public:
: Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
Keywords(Keywords), SourceMgr(SourceMgr), Status(Status) {}
- /// \brief Format the current block and return the penalty.
+ /// Format the current block and return the penalty.
unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,
bool DryRun = false, int AdditionalIndent = 0,
bool FixBadIndentation = false,
@@ -46,13 +46,14 @@ public:
unsigned LastStartColumn = 0);
private:
- /// \brief Add a new line and the required indent before the first Token
+ /// 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,
- unsigned NewlineIndent);
+ const AnnotatedLine *PreviousLine,
+ const SmallVectorImpl<AnnotatedLine *> &Lines,
+ unsigned Indent, unsigned NewlineIndent);
- /// \brief Returns the column limit for a line, taking into account whether we
+ /// Returns the column limit for a line, taking into account whether we
/// need an escaped newline due to a continued preprocessor directive.
unsigned getColumnLimit(bool InPPDirective,
const AnnotatedLine *NextLine) const;
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
index 34d4ce28aad1..e5afa1264abb 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file contains the implementation of the UnwrappedLineParser,
+/// This file contains the implementation of the UnwrappedLineParser,
/// which turns a stream of tokens into UnwrappedLines.
///
//===----------------------------------------------------------------------===//
@@ -83,6 +83,8 @@ public:
: Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
Token(nullptr), PreviousToken(nullptr) {
+ FakeEOF.Tok.startToken();
+ FakeEOF.Tok.setKind(tok::eof);
TokenSource = this;
Line.Level = 0;
Line.InPPDirective = true;
@@ -102,7 +104,7 @@ public:
PreviousToken = Token;
Token = PreviousTokenSource->getNextToken();
if (eof())
- return getFakeEOF();
+ return &FakeEOF;
return Token;
}
@@ -121,17 +123,7 @@ private:
/*MinColumnToken=*/PreviousToken);
}
- FormatToken *getFakeEOF() {
- static bool EOFInitialized = false;
- static FormatToken FormatTok;
- if (!EOFInitialized) {
- FormatTok.Tok.startToken();
- FormatTok.Tok.setKind(tok::eof);
- EOFInitialized = true;
- }
- return &FormatTok;
- }
-
+ FormatToken FakeEOF;
UnwrappedLine &Line;
FormatTokenSource *&TokenSource;
FormatToken *&ResetToken;
@@ -260,7 +252,7 @@ void UnwrappedLineParser::parse() {
IndexedTokenSource TokenSource(AllTokens);
Line->FirstStartColumn = FirstStartColumn;
do {
- DEBUG(llvm::dbgs() << "----\n");
+ LLVM_DEBUG(llvm::dbgs() << "----\n");
reset();
Tokens = &TokenSource;
TokenSource.reset();
@@ -311,6 +303,18 @@ void UnwrappedLineParser::parseFile() {
else
parseLevel(/*HasOpeningBrace=*/false);
// Make sure to format the remaining tokens.
+ //
+ // LK_TextProto is special since its top-level is parsed as the body of a
+ // braced list, which does not necessarily have natural line separators such
+ // as a semicolon. Comments after the last entry that have been determined to
+ // not belong to that line, as in:
+ // key: value
+ // // endfile comment
+ // do not have a chance to be put on a line of their own until this point.
+ // Here we add this newline before end-of-file comments.
+ if (Style.Language == FormatStyle::LK_TextProto &&
+ !CommentsBeforeNextToken.empty())
+ addUnwrappedLine();
flushComments(true);
addUnwrappedLine();
}
@@ -344,7 +348,19 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
nextToken();
addUnwrappedLine();
break;
- case tok::kw_default:
+ case tok::kw_default: {
+ unsigned StoredPosition = Tokens->getPosition();
+ FormatToken *Next = Tokens->getNextToken();
+ FormatTok = Tokens->setPosition(StoredPosition);
+ if (Next && Next->isNot(tok::colon)) {
+ // default not followed by ':' is not a case label; treat it like
+ // an identifier.
+ parseStructuralElement();
+ break;
+ }
+ // Else, if it is 'default:', fall through to the case handling.
+ LLVM_FALLTHROUGH;
+ }
case tok::kw_case:
if (Style.Language == FormatStyle::LK_JavaScript &&
Line->MustBeDeclaration) {
@@ -437,12 +453,19 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
(Style.isCpp() && NextTok->is(tok::l_paren)) ||
NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
- tok::l_square, tok::ellipsis) ||
+ tok::ellipsis) ||
(NextTok->is(tok::identifier) &&
!PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace)) ||
(NextTok->is(tok::semi) &&
(!ExpectClassBody || LBraceStack.size() != 1)) ||
(NextTok->isBinaryOperator() && !NextIsObjCMethod);
+ if (NextTok->is(tok::l_square)) {
+ // We can have an array subscript after a braced init
+ // list, but C++11 attributes are expected after blocks.
+ NextTok = Tokens->getNextToken();
+ ++ReadTokens;
+ ProbablyBracedList = NextTok->isNot(tok::l_square);
+ }
}
if (ProbablyBracedList) {
Tok->BlockKind = BK_BracedInit;
@@ -551,7 +574,7 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
// Update the opening line to add the forward reference as well
- (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex =
+ (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
CurrentLines->size() - 1;
}
}
@@ -946,49 +969,6 @@ void UnwrappedLineParser::parseStructuralElement() {
return;
}
switch (FormatTok->Tok.getKind()) {
- case tok::at:
- nextToken();
- if (FormatTok->Tok.is(tok::l_brace)) {
- nextToken();
- parseBracedList();
- break;
- }
- switch (FormatTok->Tok.getObjCKeywordID()) {
- case tok::objc_public:
- case tok::objc_protected:
- case tok::objc_package:
- case tok::objc_private:
- return parseAccessSpecifier();
- case tok::objc_interface:
- case tok::objc_implementation:
- return parseObjCInterfaceOrImplementation();
- case tok::objc_protocol:
- return parseObjCProtocol();
- case tok::objc_end:
- return; // Handled by the caller.
- case tok::objc_optional:
- case tok::objc_required:
- nextToken();
- addUnwrappedLine();
- return;
- case tok::objc_autoreleasepool:
- nextToken();
- if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BraceWrapping.AfterObjCDeclaration)
- addUnwrappedLine();
- parseBlock(/*MustBeDeclaration=*/false);
- }
- addUnwrappedLine();
- return;
- case tok::objc_try:
- // This branch isn't strictly necessary (the kw_try case below would
- // do this too after the tok::at is parsed above). But be explicit.
- parseTryCatch();
- return;
- default:
- break;
- }
- break;
case tok::kw_asm:
nextToken();
if (FormatTok->is(tok::l_brace)) {
@@ -1046,8 +1026,12 @@ void UnwrappedLineParser::parseStructuralElement() {
// 'default: string' field declaration.
break;
nextToken();
- parseLabel();
- return;
+ if (FormatTok->is(tok::colon)) {
+ parseLabel();
+ return;
+ }
+ // e.g. "default void f() {}" in a Java interface.
+ break;
case tok::kw_case:
if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
// 'case: string' field declaration.
@@ -1131,6 +1115,56 @@ void UnwrappedLineParser::parseStructuralElement() {
if (FormatTok->Tok.is(tok::l_brace)) {
nextToken();
parseBracedList();
+ break;
+ }
+ switch (FormatTok->Tok.getObjCKeywordID()) {
+ case tok::objc_public:
+ case tok::objc_protected:
+ case tok::objc_package:
+ case tok::objc_private:
+ return parseAccessSpecifier();
+ case tok::objc_interface:
+ case tok::objc_implementation:
+ return parseObjCInterfaceOrImplementation();
+ case tok::objc_protocol:
+ if (parseObjCProtocol())
+ return;
+ break;
+ case tok::objc_end:
+ return; // Handled by the caller.
+ case tok::objc_optional:
+ case tok::objc_required:
+ nextToken();
+ addUnwrappedLine();
+ return;
+ case tok::objc_autoreleasepool:
+ nextToken();
+ if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BraceWrapping.AfterControlStatement)
+ addUnwrappedLine();
+ parseBlock(/*MustBeDeclaration=*/false);
+ }
+ addUnwrappedLine();
+ return;
+ case tok::objc_synchronized:
+ nextToken();
+ if (FormatTok->Tok.is(tok::l_paren))
+ // Skip synchronization object
+ parseParens();
+ if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BraceWrapping.AfterControlStatement)
+ addUnwrappedLine();
+ parseBlock(/*MustBeDeclaration=*/false);
+ }
+ addUnwrappedLine();
+ return;
+ case tok::objc_try:
+ // This branch isn't strictly necessary (the kw_try case below would
+ // do this too after the tok::at is parsed above). But be explicit.
+ parseTryCatch();
+ return;
+ default:
+ break;
}
break;
case tok::kw_enum:
@@ -1383,13 +1417,16 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
const FormatToken *Previous = FormatTok->Previous;
if (Previous &&
(Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
- tok::kw_delete) ||
+ tok::kw_delete, tok::l_square) ||
FormatTok->isCppStructuredBinding(Style) || Previous->closesScope() ||
Previous->isSimpleTypeSpecifier())) {
nextToken();
return false;
}
nextToken();
+ if (FormatTok->is(tok::l_square)) {
+ return false;
+ }
parseSquare(/*LambdaIntroducer=*/true);
return true;
}
@@ -2097,11 +2134,33 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
// "} n, m;" will end up in one unwrapped line.
}
+void UnwrappedLineParser::parseObjCMethod() {
+ assert(FormatTok->Tok.isOneOf(tok::l_paren, tok::identifier) &&
+ "'(' or identifier expected.");
+ do {
+ if (FormatTok->Tok.is(tok::semi)) {
+ nextToken();
+ addUnwrappedLine();
+ return;
+ } else if (FormatTok->Tok.is(tok::l_brace)) {
+ parseBlock(/*MustBeDeclaration=*/false);
+ addUnwrappedLine();
+ return;
+ } else {
+ nextToken();
+ }
+ } while (!eof());
+}
+
void UnwrappedLineParser::parseObjCProtocolList() {
assert(FormatTok->Tok.is(tok::less) && "'<' expected.");
- do
+ do {
nextToken();
- while (!eof() && FormatTok->Tok.isNot(tok::greater));
+ // Early exit in case someone forgot a close angle.
+ if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
+ FormatTok->Tok.isObjCAtKeyword(tok::objc_end))
+ return;
+ } while (!eof() && FormatTok->Tok.isNot(tok::greater));
nextToken(); // Skip '>'.
}
@@ -2120,6 +2179,9 @@ void UnwrappedLineParser::parseObjCUntilAtEnd() {
// Ignore stray "}". parseStructuralElement doesn't consume them.
nextToken();
addUnwrappedLine();
+ } else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
+ nextToken();
+ parseObjCMethod();
} else {
parseStructuralElement();
}
@@ -2127,10 +2189,37 @@ void UnwrappedLineParser::parseObjCUntilAtEnd() {
}
void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
+ assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface ||
+ FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation);
nextToken();
nextToken(); // interface name
- // @interface can be followed by either a base class, or a category.
+ // @interface can be followed by a lightweight generic
+ // specialization list, then either a base class or a category.
+ if (FormatTok->Tok.is(tok::less)) {
+ // Unlike protocol lists, generic parameterizations support
+ // nested angles:
+ //
+ // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :
+ // NSObject <NSCopying, NSSecureCoding>
+ //
+ // so we need to count how many open angles we have left.
+ unsigned NumOpenAngles = 1;
+ do {
+ nextToken();
+ // Early exit in case someone forgot a close angle.
+ if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
+ FormatTok->Tok.isObjCAtKeyword(tok::objc_end))
+ break;
+ if (FormatTok->Tok.is(tok::less))
+ ++NumOpenAngles;
+ else if (FormatTok->Tok.is(tok::greater)) {
+ assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
+ --NumOpenAngles;
+ }
+ } while (!eof() && NumOpenAngles != 0);
+ nextToken(); // Skip '>'.
+ }
if (FormatTok->Tok.is(tok::colon)) {
nextToken();
nextToken(); // base class name
@@ -2154,8 +2243,21 @@ void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
parseObjCUntilAtEnd();
}
-void UnwrappedLineParser::parseObjCProtocol() {
+// Returns true for the declaration/definition form of @protocol,
+// false for the expression form.
+bool UnwrappedLineParser::parseObjCProtocol() {
+ assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol);
nextToken();
+
+ if (FormatTok->is(tok::l_paren))
+ // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".
+ return false;
+
+ // The definition/declaration form,
+ // @protocol Foo
+ // - (int)someMethod;
+ // @end
+
nextToken(); // protocol name
if (FormatTok->Tok.is(tok::less))
@@ -2164,11 +2266,13 @@ void UnwrappedLineParser::parseObjCProtocol() {
// Check for protocol declaration.
if (FormatTok->Tok.is(tok::semi)) {
nextToken();
- return addUnwrappedLine();
+ addUnwrappedLine();
+ return true;
}
addUnwrappedLine();
parseObjCUntilAtEnd();
+ return true;
}
void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
@@ -2245,7 +2349,7 @@ LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
void UnwrappedLineParser::addUnwrappedLine() {
if (Line->Tokens.empty())
return;
- DEBUG({
+ LLVM_DEBUG({
if (CurrentLines == &Lines)
printDebugInfo(*Line);
});
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
index cee03e9bce33..87254832c635 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file contains the declaration of the UnwrappedLineParser,
+/// This file contains the declaration of the UnwrappedLineParser,
/// which turns a stream of tokens into UnwrappedLines.
///
//===----------------------------------------------------------------------===//
@@ -28,7 +28,7 @@ namespace format {
struct UnwrappedLineNode;
-/// \brief An unwrapped line is a sequence of \c Token, that we would like to
+/// An unwrapped line is a sequence of \c Token, that we would like to
/// put on a single line if there was no column limit.
///
/// This is used as a main interface between the \c UnwrappedLineParser and the
@@ -38,22 +38,26 @@ struct UnwrappedLine {
UnwrappedLine();
// FIXME: Don't use std::list here.
- /// \brief The \c Tokens comprising this \c UnwrappedLine.
+ /// The \c Tokens comprising this \c UnwrappedLine.
std::list<UnwrappedLineNode> Tokens;
- /// \brief The indent level of the \c UnwrappedLine.
+ /// The indent level of the \c UnwrappedLine.
unsigned Level;
- /// \brief Whether this \c UnwrappedLine is part of a preprocessor directive.
+ /// Whether this \c UnwrappedLine is part of a preprocessor directive.
bool InPPDirective;
bool MustBeDeclaration;
- /// \brief If this \c UnwrappedLine closes a block in a sequence of lines,
+ /// If this \c UnwrappedLine closes a block in a sequence of lines,
/// \c MatchingOpeningBlockLineIndex stores the index of the corresponding
/// opening line. Otherwise, \c MatchingOpeningBlockLineIndex must be
/// \c kInvalidIndex.
- size_t MatchingOpeningBlockLineIndex;
+ size_t MatchingOpeningBlockLineIndex = kInvalidIndex;
+
+ /// If this \c UnwrappedLine opens a block, stores the index of the
+ /// line with the corresponding closing brace.
+ size_t MatchingClosingBlockLineIndex = kInvalidIndex;
static const size_t kInvalidIndex = -1;
@@ -116,10 +120,11 @@ private:
// parses the record as a child block, i.e. if the class declaration is an
// expression.
void parseRecord(bool ParseAsExpr = false);
+ void parseObjCMethod();
void parseObjCProtocolList();
void parseObjCUntilAtEnd();
void parseObjCInterfaceOrImplementation();
- void parseObjCProtocol();
+ bool parseObjCProtocol();
void parseJavaScriptEs6ImportExport();
bool tryToParseLambda();
bool tryToParseLambdaIntroducer();
@@ -141,7 +146,7 @@ private:
// token.
//
// NextTok specifies the next token. A null pointer NextTok is supported, and
- // signifies either the absense of a next token, or that the next token
+ // signifies either the absence of a next token, or that the next token
// shouldn't be taken into accunt for the analysis.
void distributeComments(const SmallVectorImpl<FormatToken *> &Comments,
const FormatToken *NextTok);
diff --git a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp
index ef0c7a7d5a45..9e49e7913033 100644
--- a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements UsingDeclarationsSorter, a TokenAnalyzer that
+/// This file implements UsingDeclarationsSorter, a TokenAnalyzer that
/// sorts consecutive using declarations.
///
//===----------------------------------------------------------------------===//
@@ -161,7 +161,7 @@ void endUsingDeclarationBlock(
StringRef Text(SourceMgr.getCharacterData(SortedBegin),
SourceMgr.getCharacterData(SortedEnd) -
SourceMgr.getCharacterData(SortedBegin));
- DEBUG({
+ LLVM_DEBUG({
StringRef OldText(SourceMgr.getCharacterData(Begin),
SourceMgr.getCharacterData(End) -
SourceMgr.getCharacterData(Begin));
@@ -187,8 +187,7 @@ std::pair<tooling::Replacements, unsigned> UsingDeclarationsSorter::analyze(
TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) {
const SourceManager &SourceMgr = Env.getSourceManager();
- AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
- AnnotatedLines.end());
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
tooling::Replacements Fixes;
SmallVector<UsingDeclaration, 4> UsingDeclarations;
for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) {
diff --git a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h
index 6f137712d841..7e5cf7610d67 100644
--- a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h
+++ b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares UsingDeclarationsSorter, a TokenAnalyzer that
+/// This file declares UsingDeclarationsSorter, a TokenAnalyzer that
/// sorts consecutive using declarations.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
index a5477a996327..7070ce03c864 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements WhitespaceManager class.
+/// This file implements WhitespaceManager class.
///
//===----------------------------------------------------------------------===//
@@ -90,7 +90,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
if (Changes.empty())
return Replaces;
- std::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
+ llvm::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
alignConsecutiveDeclarations();
alignConsecutiveAssignments();
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
index af20dc5616a7..db90343f7294 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief WhitespaceManager class manages whitespace around tokens and their
+/// WhitespaceManager class manages whitespace around tokens and their
/// replacements.
///
//===----------------------------------------------------------------------===//
@@ -24,7 +24,7 @@
namespace clang {
namespace format {
-/// \brief Manages the whitespaces around tokens and their replacements.
+/// Manages the whitespaces around tokens and their replacements.
///
/// This includes special handling for certain constructs, e.g. the alignment of
/// trailing line comments.
@@ -41,7 +41,7 @@ public:
bool UseCRLF)
: SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {}
- /// \brief Replaces the whitespace in front of \p Tok. Only call once for
+ /// Replaces the whitespace in front of \p Tok. Only call once for
/// each \c AnnotatedToken.
///
/// \p StartOfTokenColumn is the column at which the token will start after
@@ -51,7 +51,7 @@ public:
unsigned StartOfTokenColumn,
bool InPPDirective = false);
- /// \brief Adds information about an unchangeable token's whitespace.
+ /// Adds information about an unchangeable token's whitespace.
///
/// Needs to be called for every token for which \c replaceWhitespace
/// was not called.
@@ -59,7 +59,7 @@ public:
llvm::Error addReplacement(const tooling::Replacement &Replacement);
- /// \brief Inserts or replaces whitespace in the middle of a token.
+ /// Inserts or replaces whitespace in the middle of a token.
///
/// Inserts \p PreviousPostfix, \p Newlines, \p Spaces and \p CurrentPrefix
/// (in this order) at \p Offset inside \p Tok, replacing \p ReplaceChars
@@ -79,13 +79,13 @@ public:
StringRef CurrentPrefix, bool InPPDirective,
unsigned Newlines, int Spaces);
- /// \brief Returns all the \c Replacements created during formatting.
+ /// Returns all the \c Replacements created during formatting.
const tooling::Replacements &generateReplacements();
- /// \brief Represents a change before a token, a break inside a token,
+ /// Represents a change before a token, a break inside a token,
/// or the layout of an unchanged token (or whitespace within).
struct Change {
- /// \brief Functor to sort changes in original source order.
+ /// Functor to sort changes in original source order.
class IsBeforeInFile {
public:
IsBeforeInFile(const SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
@@ -95,7 +95,7 @@ public:
const SourceManager &SourceMgr;
};
- /// \brief Creates a \c Change.
+ /// Creates a \c Change.
///
/// The generated \c Change will replace the characters at
/// \p OriginalWhitespaceRange with a concatenation of
@@ -165,35 +165,35 @@ public:
};
private:
- /// \brief Calculate \c IsTrailingComment, \c TokenLength for the last tokens
+ /// Calculate \c IsTrailingComment, \c TokenLength for the last tokens
/// or token parts in a line and \c PreviousEndOfTokenColumn and
/// \c EscapedNewlineColumn for the first tokens or token parts in a line.
void calculateLineBreakInformation();
- /// \brief Align consecutive assignments over all \c Changes.
+ /// Align consecutive assignments over all \c Changes.
void alignConsecutiveAssignments();
- /// \brief Align consecutive declarations over all \c Changes.
+ /// Align consecutive declarations over all \c Changes.
void alignConsecutiveDeclarations();
- /// \brief Align trailing comments over all \c Changes.
+ /// Align trailing comments over all \c Changes.
void alignTrailingComments();
- /// \brief Align trailing comments from change \p Start to change \p End at
+ /// Align trailing comments from change \p Start to change \p End at
/// the specified \p Column.
void alignTrailingComments(unsigned Start, unsigned End, unsigned Column);
- /// \brief Align escaped newlines over all \c Changes.
+ /// Align escaped newlines over all \c Changes.
void alignEscapedNewlines();
- /// \brief Align escaped newlines from change \p Start to change \p End at
+ /// Align escaped newlines from change \p Start to change \p End at
/// the specified \p Column.
void alignEscapedNewlines(unsigned Start, unsigned End, unsigned Column);
- /// \brief Fill \c Replaces with the replacements for all effective changes.
+ /// Fill \c Replaces with the replacements for all effective changes.
void generateChanges();
- /// \brief Stores \p Text as the replacement for the whitespace in \p Range.
+ /// 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 appendEscapedNewlineText(std::string &Text, unsigned Newlines,
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
index 7dc475e26f76..2a8bfef68eb9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
@@ -87,9 +87,10 @@ namespace {
<< DC->getPrimaryContext() << "\n";
} else
Out << "Not a DeclContext\n";
- } else if (OutputKind == Print)
- D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
- else if (OutputKind != None)
+ } else if (OutputKind == Print) {
+ PrintingPolicy Policy(D->getASTContext().getLangOpts());
+ D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
+ } else if (OutputKind != None)
D->dump(Out, OutputKind == DumpFull);
}
@@ -138,12 +139,14 @@ clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
FilterString);
}
-std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
- bool DumpDecls,
- bool Deserialize,
- bool DumpLookups) {
+std::unique_ptr<ASTConsumer>
+clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out,
+ StringRef FilterString,
+ bool DumpDecls,
+ bool Deserialize,
+ bool DumpLookups) {
assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
- return llvm::make_unique<ASTPrinter>(nullptr,
+ return llvm::make_unique<ASTPrinter>(std::move(Out),
Deserialize ? ASTPrinter::DumpFull :
DumpDecls ? ASTPrinter::Dump :
ASTPrinter::None,
@@ -178,7 +181,7 @@ namespace {
void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
D->print(llvm::errs());
-
+
if (Stmt *Body = D->getBody()) {
llvm::errs() << '\n';
Body->viewAST();
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
index 354527db7bad..2434113ab0db 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
@@ -1,4 +1,4 @@
-//===-- ASTMerge.cpp - AST Merging Frontent Action --------------*- C++ -*-===//
+//===-- ASTMerge.cpp - AST Merging Frontend Action --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -51,9 +51,9 @@ void ASTMergeAction::ExecuteAction() {
if (!Unit)
continue;
- ASTImporter Importer(CI.getASTContext(),
+ ASTImporter Importer(CI.getASTContext(),
CI.getFileManager(),
- Unit->getASTContext(),
+ Unit->getASTContext(),
Unit->getFileManager(),
/*MinimalImport=*/false);
@@ -64,9 +64,9 @@ void ASTMergeAction::ExecuteAction() {
if (IdentifierInfo *II = ND->getIdentifier())
if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list"))
continue;
-
+
Decl *ToD = Importer.Import(D);
-
+
if (ToD) {
DeclGroupRef DGR(ToD);
CI.getASTConsumer().HandleTopLevelDecl(DGR);
@@ -88,7 +88,7 @@ ASTMergeAction::ASTMergeAction(std::unique_ptr<FrontendAction> adaptedAction,
assert(AdaptedAction && "ASTMergeAction needs an action to adapt");
}
-ASTMergeAction::~ASTMergeAction() {
+ASTMergeAction::~ASTMergeAction() {
}
bool ASTMergeAction::usesPreprocessorOnly() const {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index 83731c0d39e2..e4c313fed30f 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -1,4 +1,4 @@
-//===--- ASTUnit.cpp - ASTUnit utility --------------------------*- C++ -*-===//
+//===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,45 +14,99 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.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/MemoryBufferCache.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/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Sema/Sema.h"
+#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/Module.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CrashRecoveryContext.h"
-#include "llvm/Support/Host.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <atomic>
+#include <cassert>
+#include <cstdint>
#include <cstdio>
#include <cstdlib>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using llvm::TimeRecord;
namespace {
+
class SimpleTimer {
bool WantTiming;
TimeRecord Start;
@@ -64,11 +118,6 @@ namespace {
Start = TimeRecord::getCurrentTime();
}
- void setOutput(const Twine &Output) {
- if (WantTiming)
- this->Output = Output.str();
- }
-
~SimpleTimer() {
if (WantTiming) {
TimeRecord Elapsed = TimeRecord::getCurrentTime();
@@ -78,29 +127,37 @@ namespace {
llvm::errs() << '\n';
}
}
+
+ void setOutput(const Twine &Output) {
+ if (WantTiming)
+ this->Output = Output.str();
+ }
};
- template <class T>
- std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
- if (!Val)
- return nullptr;
- return std::move(*Val);
- }
+} // namespace
- template <class T>
- bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
- if (!Val)
- return false;
- Output = std::move(*Val);
- return true;
- }
+template <class T>
+static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
+ if (!Val)
+ return nullptr;
+ return std::move(*Val);
+}
+
+template <class T>
+static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
+ if (!Val)
+ return false;
+ Output = std::move(*Val);
+ return true;
+}
-/// \brief Get a source buffer for \p MainFilePath, handling all file-to-file
+/// Get a source buffer for \p MainFilePath, handling all file-to-file
/// and file-to-buffer remappings inside \p Invocation.
static std::unique_ptr<llvm::MemoryBuffer>
getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
vfs::FileSystem *VFS,
- StringRef FilePath) {
+ StringRef FilePath,
+ bool isVolatile) {
const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();
// Try to determine if the main file has been remapped, either from the
@@ -120,7 +177,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
if (MainFileID == MID) {
// We found a remapping. Try to load the resulting, remapped source.
- BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second));
+ BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));
if (!BufferOwner)
return nullptr;
}
@@ -145,7 +202,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
// If the main source file was not remapped, load it now.
if (!Buffer && !BufferOwner) {
- BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath));
+ BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));
if (!BufferOwner)
return nullptr;
}
@@ -156,7 +213,6 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
return nullptr;
return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);
}
-}
struct ASTUnit::ASTWriterData {
SmallString<128> Buffer;
@@ -171,32 +227,22 @@ void ASTUnit::clearFileLevelDecls() {
llvm::DeleteContainerSeconds(FileDecls);
}
-/// \brief After failing to build a precompiled preamble (due to
+/// After failing to build a precompiled preamble (due to
/// errors in the source that occurs in the preamble), the number of
/// reparses during which we'll skip even trying to precompile the
/// preamble.
const unsigned DefaultPreambleRebuildInterval = 5;
-/// \brief Tracks the number of ASTUnit objects that are currently active.
+/// Tracks the number of ASTUnit objects that are currently active.
///
/// Used for debugging purposes only.
static std::atomic<unsigned> ActiveASTUnitObjects;
ASTUnit::ASTUnit(bool _MainFileIsAST)
- : Reader(nullptr), HadModuleLoaderFatalFailure(false),
- OnlyLocalDecls(false), CaptureDiagnostics(false),
- MainFileIsAST(_MainFileIsAST),
- TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
- OwnsRemappedFileBuffers(true),
- NumStoredDiagnosticsFromDriver(0),
- PreambleRebuildCounter(0),
- NumWarningsInPreamble(0),
- ShouldCacheCodeCompletionResults(false),
- IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
- CompletionCacheTopLevelHashValue(0),
- PreambleTopLevelHashValue(0),
- CurrentTopLevelHashValue(0),
- UnsafeToFree(false) {
+ : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
+ ShouldCacheCodeCompletionResults(false),
+ IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
+ UnsafeToFree(false) {
if (getenv("LIBCLANG_OBJTRACKING"))
fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);
}
@@ -219,8 +265,8 @@ ASTUnit::~ASTUnit() {
delete RB.second;
}
- ClearCachedCompletionResults();
-
+ ClearCachedCompletionResults();
+
if (getenv("LIBCLANG_OBJTRACKING"))
fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);
}
@@ -229,20 +275,26 @@ void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
this->PP = std::move(PP);
}
-/// \brief Determine the set of code-completion contexts in which this
+void ASTUnit::enableSourceFileDiagnostics() {
+ assert(getDiagnostics().getClient() && Ctx &&
+ "Bad context for source file");
+ getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());
+}
+
+/// Determine the set of code-completion contexts in which this
/// declaration should be shown.
static unsigned getDeclShowContexts(const NamedDecl *ND,
const LangOptions &LangOpts,
bool &IsNestedNameSpecifier) {
IsNestedNameSpecifier = false;
-
+
if (isa<UsingShadowDecl>(ND))
- ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
if (!ND)
return 0;
-
+
uint64_t Contexts = 0;
- if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||
isa<TypeAliasTemplateDecl>(ND)) {
// Types can appear in these contexts.
@@ -257,12 +309,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
// In C++, types can appear in expressions contexts (for functional casts).
if (LangOpts.CPlusPlus)
Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
-
+
// In Objective-C, message sends can send interfaces. In Objective-C++,
// all types are available due to functional casts.
if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
-
+
// In Objective-C, you can only be a subclass of another Objective-C class
if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
// Objective-C interfaces can be used in a class property expression.
@@ -274,16 +326,16 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
// Deal with tag names.
if (isa<EnumDecl>(ND)) {
Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);
-
+
// Part of the nested-name-specifier in C++0x.
if (LangOpts.CPlusPlus11)
IsNestedNameSpecifier = true;
- } else if (const RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
+ } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {
if (Record->isUnion())
Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
else
Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
-
+
if (LangOpts.CPlusPlus)
IsNestedNameSpecifier = true;
} else if (isa<ClassTemplateDecl>(ND))
@@ -300,37 +352,37 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);
} else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
Contexts = (1LL << CodeCompletionContext::CCC_Namespace);
-
+
// Part of the nested-name-specifier.
IsNestedNameSpecifier = true;
}
-
+
return Contexts;
}
void ASTUnit::CacheCodeCompletionResults() {
if (!TheSema)
return;
-
+
SimpleTimer Timer(WantTiming);
Timer.setOutput("Cache global code completions for " + getMainFileName());
// Clear out the previous results.
ClearCachedCompletionResults();
-
+
// Gather the set of global code completions.
- typedef CodeCompletionResult Result;
+ using Result = CodeCompletionResult;
SmallVector<Result, 8> Results;
CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);
TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator,
CCTUInfo, Results);
-
+
// Translate global code completions into cached completions.
llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
- for (Result &R : Results) {
+ for (auto &R : Results) {
switch (R.Kind) {
case Result::RK_Declaration: {
bool IsNestedNameSpecifier = false;
@@ -344,7 +396,7 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedResult.Kind = R.CursorKind;
CachedResult.Availability = R.Availability;
- // Keep track of the type of this completion in an ASTContext-agnostic
+ // Keep track of the type of this completion in an ASTContext-agnostic
// way.
QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);
if (UsageType.isNull()) {
@@ -356,7 +408,7 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
// Determine whether we have already seen this type. If so, we save
- // ourselves the work of formatting the type string by using the
+ // ourselves the work of formatting the type string by using the
// temporary, CanQualType-based hash table to find the associated value.
unsigned &TypeValue = CompletionTypes[CanUsageType];
if (TypeValue == 0) {
@@ -364,12 +416,12 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedCompletionTypes[QualType(CanUsageType).getAsString()]
= TypeValue;
}
-
+
CachedResult.Type = TypeValue;
}
-
+
CachedCompletionResults.push_back(CachedResult);
-
+
/// Handle nested-name-specifiers in C++.
if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&
!R.StartsNestedNameSpecifier) {
@@ -392,10 +444,10 @@ void ASTUnit::CacheCodeCompletionResults() {
isa<NamespaceAliasDecl>(R.Declaration))
NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
- if (unsigned RemainingContexts
+ if (unsigned RemainingContexts
= NNSContexts & ~CachedResult.ShowInContexts) {
- // If there any contexts where this completion can be a
- // nested-name-specifier but isn't already an option, create a
+ // If there any contexts where this completion can be a
+ // nested-name-specifier but isn't already an option, create a
// nested-name-specifier completion.
R.StartsNestedNameSpecifier = true;
CachedResult.Completion = R.CreateCodeCompletionString(
@@ -410,13 +462,13 @@ void ASTUnit::CacheCodeCompletionResults() {
}
break;
}
-
+
case Result::RK_Keyword:
case Result::RK_Pattern:
// Ignore keywords and patterns; we don't care, since they are so
// easily regenerated.
break;
-
+
case Result::RK_Macro: {
CachedCodeCompletionResult CachedResult;
CachedResult.Completion = R.CreateCodeCompletionString(
@@ -446,7 +498,7 @@ void ASTUnit::CacheCodeCompletionResults() {
}
}
}
-
+
// Save the current top-level hash value.
CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
}
@@ -459,7 +511,7 @@ void ASTUnit::ClearCachedCompletionResults() {
namespace {
-/// \brief Gathers information from ASTReader that will be used to initialize
+/// Gathers information from ASTReader that will be used to initialize
/// a Preprocessor.
class ASTInfoCollector : public ASTReaderListener {
Preprocessor &PP;
@@ -470,8 +522,8 @@ class ASTInfoCollector : public ASTReaderListener {
std::shared_ptr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target;
unsigned &Counter;
+ bool InitializedLanguage = false;
- bool InitializedLanguage;
public:
ASTInfoCollector(Preprocessor &PP, ASTContext *Context,
HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
@@ -480,30 +532,29 @@ public:
IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
: PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),
LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
- Counter(Counter), InitializedLanguage(false) {}
+ Counter(Counter) {}
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool AllowCompatibleDifferences) override {
if (InitializedLanguage)
return false;
-
+
LangOpt = LangOpts;
InitializedLanguage = true;
-
+
updated();
return false;
}
- virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
- StringRef SpecificModuleCachePath,
- bool Complain) override {
+ bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) override {
this->HSOpts = HSOpts;
return false;
}
- virtual bool
- ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
- std::string &SuggestedPredefines) override {
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
+ std::string &SuggestedPredefines) override {
this->PPOpts = PPOpts;
return false;
}
@@ -557,19 +608,18 @@ private:
}
};
- /// \brief Diagnostic consumer that saves each diagnostic it is given.
+/// Diagnostic consumer that saves each diagnostic it is given.
class StoredDiagnosticConsumer : public DiagnosticConsumer {
SmallVectorImpl<StoredDiagnostic> *StoredDiags;
SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;
- const LangOptions *LangOpts;
- SourceManager *SourceMgr;
+ const LangOptions *LangOpts = nullptr;
+ SourceManager *SourceMgr = nullptr;
public:
StoredDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
- : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),
- LangOpts(nullptr), SourceMgr(nullptr) {
+ : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags) {
assert((StoredDiags || StandaloneDiags) &&
"No output collections were passed to StoredDiagnosticConsumer.");
}
@@ -585,20 +635,20 @@ public:
const Diagnostic &Info) override;
};
-/// \brief RAII object that optionally captures diagnostics, if
+/// RAII object that optionally captures diagnostics, if
/// there is no diagnostic client to capture them already.
class CaptureDroppedDiagnostics {
DiagnosticsEngine &Diags;
StoredDiagnosticConsumer Client;
- DiagnosticConsumer *PreviousClient;
+ DiagnosticConsumer *PreviousClient = nullptr;
std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
public:
- CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags,
- SmallVectorImpl<StoredDiagnostic> *StoredDiags,
- SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
- : Diags(Diags), Client(StoredDiags, StandaloneDiags), PreviousClient(nullptr)
- {
+ CaptureDroppedDiagnostics(
+ bool RequestCapture, DiagnosticsEngine &Diags,
+ SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+ SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
+ : Diags(Diags), Client(StoredDiags, StandaloneDiags) {
if (RequestCapture || Diags.getClient() == nullptr) {
OwningPreviousClient = Diags.takeClient();
PreviousClient = Diags.getClient();
@@ -612,7 +662,7 @@ public:
}
};
-} // anonymous namespace
+} // namespace
static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions &LangOpts,
@@ -634,7 +684,7 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
}
if (StandaloneDiags) {
- llvm::Optional<StoredDiagnostic> StoredDiag = llvm::None;
+ llvm::Optional<StoredDiagnostic> StoredDiag = None;
if (!ResultDiag) {
StoredDiag.emplace(Level, Info);
ResultDiag = StoredDiag.getPointer();
@@ -664,7 +714,7 @@ ASTDeserializationListener *ASTUnit::getDeserializationListener() {
std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {
assert(FileMgr);
- auto Buffer = FileMgr->getBufferForFile(Filename);
+ auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);
if (Buffer)
return std::move(*Buffer);
if (ErrorStr)
@@ -672,7 +722,7 @@ ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {
return nullptr;
}
-/// \brief Configure the diagnostics object for use with ASTUnit.
+/// Configure the diagnostics object for use with ASTUnit.
void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
ASTUnit &AST, bool CaptureDiagnostics) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
@@ -693,7 +743,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
DiagCleanup(Diags.get());
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
@@ -741,7 +791,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
bool disableValid = false;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = true;
- AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, { },
+ AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, {},
/*isysroot=*/"",
/*DisableValidation=*/disableValid,
AllowPCHWithCompilerErrors);
@@ -794,20 +844,20 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
return AST;
}
-namespace {
-
-/// \brief Add the given macro to the hash of all top-level entities.
-void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
- Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash);
+/// Add the given macro to the hash of all top-level entities.
+static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
+ Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);
}
-/// \brief Preprocessor callback class that updates a hash value with the names
+namespace {
+
+/// Preprocessor callback class that updates a hash value with the names
/// of all macros that have been defined by the translation unit.
class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
unsigned &Hash;
-
+
public:
- explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
+ explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
@@ -815,55 +865,59 @@ public:
}
};
-/// \brief Add the given declaration to the hash of all top-level entities.
-void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
+} // namespace
+
+/// Add the given declaration to the hash of all top-level entities.
+static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
if (!D)
return;
-
+
DeclContext *DC = D->getDeclContext();
if (!DC)
return;
-
+
if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
return;
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- if (EnumDecl *EnumD = dyn_cast<EnumDecl>(D)) {
+ if (const auto *ND = dyn_cast<NamedDecl>(D)) {
+ if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {
// For an unscoped enum include the enumerators in the hash since they
// enter the top-level namespace.
if (!EnumD->isScoped()) {
for (const auto *EI : EnumD->enumerators()) {
if (EI->getIdentifier())
- Hash = llvm::HashString(EI->getIdentifier()->getName(), Hash);
+ Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);
}
}
}
if (ND->getIdentifier())
- Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash);
+ Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);
else if (DeclarationName Name = ND->getDeclName()) {
std::string NameStr = Name.getAsString();
- Hash = llvm::HashString(NameStr, Hash);
+ Hash = llvm::djbHash(NameStr, Hash);
}
return;
}
- if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D)) {
- if (Module *Mod = ImportD->getImportedModule()) {
+ if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {
+ if (const Module *Mod = ImportD->getImportedModule()) {
std::string ModName = Mod->getFullModuleName();
- Hash = llvm::HashString(ModName, Hash);
+ Hash = llvm::djbHash(ModName, Hash);
}
return;
}
}
+namespace {
+
class TopLevelDeclTrackerConsumer : public ASTConsumer {
ASTUnit &Unit;
unsigned &Hash;
-
+
public:
TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
- : Unit(_Unit), Hash(Hash) {
+ : Unit(_Unit), Hash(Hash) {
Hash = 0;
}
@@ -886,14 +940,14 @@ public:
void handleFileLevelDecl(Decl *D) {
Unit.addFileLevelDecl(D);
- if (NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(D)) {
+ if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
for (auto *I : NSD->decls())
handleFileLevelDecl(I);
}
}
bool HandleTopLevelDecl(DeclGroupRef D) override {
- for (Decl *TopLevelDecl : D)
+ for (auto *TopLevelDecl : D)
handleTopLevelDecl(TopLevelDecl);
return true;
}
@@ -902,7 +956,7 @@ public:
void HandleInterestingDecl(DeclGroupRef) override {}
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
- for (Decl *TopLevelDecl : D)
+ for (auto *TopLevelDecl : D)
handleTopLevelDecl(TopLevelDecl);
}
@@ -932,8 +986,9 @@ public:
TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
bool hasCodeCompletionSupport() const override { return false; }
+
TranslationUnitKind getTranslationUnitKind() override {
- return Unit.getTranslationUnitKind();
+ return Unit.getTranslationUnitKind();
}
};
@@ -949,7 +1004,7 @@ public:
void AfterPCHEmitted(ASTWriter &Writer) override {
TopLevelDeclIDs.reserve(TopLevelDecls.size());
- for (Decl *D : TopLevelDecls) {
+ for (const auto *D : TopLevelDecls) {
// Invalid top-level decls may not have been serialized.
if (D->isInvalidDecl())
continue;
@@ -958,7 +1013,7 @@ public:
}
void HandleTopLevelDecl(DeclGroupRef DG) override {
- for (Decl *D : DG) {
+ for (auto *D : DG) {
// FIXME: Currently ObjC method declarations are incorrectly being
// reported as top-level declarations, even though their DeclContext
// is the containing ObjC @interface/@implementation. This is a
@@ -981,7 +1036,7 @@ private:
llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;
};
-} // anonymous namespace
+} // namespace
static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {
return StoredDiag.getLocation().isValid();
@@ -1004,7 +1059,7 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
// been careful to make sure that the source manager's state
// before and after are identical, so that we can reuse the source
// location itself.
- for (StoredDiagnostic &SD : StoredDiagnostics) {
+ for (auto &SD : StoredDiagnostics) {
if (SD.getLocation().isValid()) {
FullSourceLoc Loc(SD.getLocation(), SM);
SD.setLocation(Loc);
@@ -1052,11 +1107,11 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
Clang->setInvocation(CCInvocation);
OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
-
+
// Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped.
Clang->setDiagnostics(&getDiagnostics());
-
+
// Create the target instance.
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
@@ -1068,7 +1123,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts());
-
+
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@@ -1097,10 +1152,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(&getFileManager());
-
+
// Create the source manager.
Clang->setSourceManager(&getSourceManager());
-
+
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
if (OverrideMainBuffer) {
@@ -1135,7 +1190,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
goto error;
transferASTDataFromCompilerInstance(*Clang);
-
+
Act->EndSourceFile();
FailedParseDiagnostics.clear();
@@ -1192,22 +1247,22 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
if (OutDiag.Filename.empty())
return OutDiag;
OutDiag.LocOffset = SM.getFileOffset(FileLoc);
- for (const CharSourceRange &Range : InDiag.getRanges())
+ for (const auto &Range : InDiag.getRanges())
OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));
- for (const FixItHint &FixIt : InDiag.getFixIts())
+ for (const auto &FixIt : InDiag.getFixIts())
OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));
return OutDiag;
}
-/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
+/// Attempt to build or re-use a precompiled preamble when (re-)parsing
/// the source file.
///
/// This routine will compute the preamble of the main source file. If a
-/// non-trivial preamble is found, it will precompile that preamble into a
+/// non-trivial preamble is found, it will precompile that preamble into a
/// precompiled header so that the precompiled preamble can be used to reduce
/// reparsing time. If a precompiled preamble has already been constructed,
-/// this routine will determine if it is still valid and, if so, avoid
+/// this routine will determine if it is still valid and, if so, avoid
/// rebuilding the precompiled preamble.
///
/// \param AllowRebuild When true (the default), this routine is
@@ -1223,15 +1278,14 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- const CompilerInvocation &PreambleInvocationIn,
+ CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
unsigned MaxLines) {
-
auto MainFilePath =
PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =
getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),
- MainFilePath);
+ MainFilePath, UserFilesAreVolatile);
if (!MainFileBuffer)
return nullptr;
@@ -1291,9 +1345,18 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
SimpleTimer PreambleTimer(WantTiming);
PreambleTimer.setOutput("Precompiling preamble");
+ const bool PreviousSkipFunctionBodies =
+ PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;
+ if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)
+ PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;
+
llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
+
+ PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =
+ PreviousSkipFunctionBodies;
+
if (NewPreamble) {
Preamble = std::move(*NewPreamble);
PreambleRebuildCounter = 1;
@@ -1307,7 +1370,6 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
case BuildPreambleError::CouldntCreateTargetInfo:
case BuildPreambleError::BeginSourceFileFailed:
case BuildPreambleError::CouldntEmitPCH:
- case BuildPreambleError::CouldntCreateVFSOverlay:
// These erros are more likely to repeat, retry after some period.
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
return nullptr;
@@ -1345,7 +1407,7 @@ void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
std::vector<Decl *> Resolved;
Resolved.reserve(TopLevelDeclsInPreamble.size());
ExternalASTSource &Source = *getASTContext().getExternalSource();
- for (serialization::DeclID TopLevelDecl : TopLevelDeclsInPreamble) {
+ for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {
// Resolve the declaration ID to an actual declaration, possibly
// deserializing the declaration in the process.
if (Decl *D = Source.GetExternalDecl(TopLevelDecl))
@@ -1389,12 +1451,12 @@ StringRef ASTUnit::getMainFileName() const {
return FE->getName();
}
- return StringRef();
+ return {};
}
StringRef ASTUnit::getASTFileName() const {
if (!isMainFileAST())
- return StringRef();
+ return {};
serialization::ModuleFile &
Mod = Reader->getModuleManager().getPrimaryModule();
@@ -1409,8 +1471,6 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
IntrusiveRefCntPtr<vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(*CI, *Diags);
- if (!VFS)
- return nullptr;
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->Invocation = std::move(CI);
@@ -1443,7 +1503,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
if (!AST)
return nullptr;
}
-
+
if (!ResourceFilesPath.empty()) {
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
@@ -1461,7 +1521,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(OwnAST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
DiagCleanup(Diags.get());
// We'll manage file buffers ourselves.
@@ -1479,11 +1539,11 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
Clang->setInvocation(std::move(CI));
AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
-
+
// Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped.
Clang->setDiagnostics(&AST->getDiagnostics());
-
+
// Create the target instance.
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
@@ -1495,7 +1555,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts());
-
+
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@@ -1513,7 +1573,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(&AST->getFileManager());
-
+
// Create the source manager.
Clang->setSourceManager(&AST->getSourceManager());
@@ -1559,7 +1619,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// Steal the created target, context, and preprocessor.
AST->transferASTDataFromCompilerInstance(*Clang);
-
+
Act->EndSourceFile();
if (OwnAST)
@@ -1624,12 +1684,12 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
AST->FileSystemOpts = FileMgr->getFileSystemOpts();
AST->FileMgr = FileMgr;
AST->UserFilesAreVolatile = UserFilesAreVolatile;
-
+
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
DiagCleanup(Diags.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
@@ -1647,7 +1707,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
- bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
+ bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
@@ -1658,11 +1718,10 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
std::shared_ptr<CompilerInvocation> CI;
{
-
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
&StoredDiagnostics, nullptr);
- CI = clang::createInvocationFromCommandLine(
+ CI = createInvocationFromCommandLine(
llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS);
if (!CI)
return nullptr;
@@ -1677,11 +1736,12 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
PPOpts.SingleFileParseMode = SingleFileParse;
-
+
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
- CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies;
+ CI->getFrontendOpts().SkipFunctionBodies =
+ SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;
if (ModuleFormat)
CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();
@@ -1689,14 +1749,14 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
// Create the AST unit.
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
+ AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
+ AST->StoredDiagnostics.swap(StoredDiagnostics);
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
if (!VFS)
VFS = vfs::getRealFileSystem();
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
- if (!VFS)
- return nullptr;
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->PCMCache = new MemoryBufferCache;
AST->OnlyLocalDecls = OnlyLocalDecls;
@@ -1706,9 +1766,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
AST->IncludeBriefCommentsInCodeCompletion
= IncludeBriefCommentsInCodeCompletion;
AST->UserFilesAreVolatile = UserFilesAreVolatile;
- AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
- AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI;
+ AST->SkipFunctionBodies = SkipFunctionBodies;
if (ForSerialization)
AST->WriterData.reset(new ASTWriterData(*AST->PCMCache));
// Zero out now to ease cleanup during crash recovery.
@@ -1746,7 +1805,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
}
clearFileLevelDecls();
-
+
SimpleTimer ParsingTimer(WantTiming);
ParsingTimer.setOutput("Reparsing " + getMainFileName());
@@ -1768,7 +1827,6 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
-
// Clear out the diagnostics state.
FileMgr.reset();
getDiagnostics().Reset();
@@ -1780,7 +1838,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
bool Result =
Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
- // If we're caching global code-completion results, and the top-level
+ // If we're caching global code-completion results, and the top-level
// declarations have changed, clear out the code-completion cache.
if (!Result && ShouldCacheCodeCompletionResults &&
CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
@@ -1789,7 +1847,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// We now need to clear out the completion info related to this translation
// unit; it'll be recreated if necessary.
CCTUInfo.reset();
-
+
return Result;
}
@@ -1811,23 +1869,23 @@ void ASTUnit::ResetForParse() {
//----------------------------------------------------------------------------//
namespace {
- /// \brief Code completion consumer that combines the cached code-completion
+
+ /// Code completion consumer that combines the cached code-completion
/// results from an ASTUnit with the code-completion results provided to it,
- /// then passes the result on to
+ /// then passes the result on to
class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
uint64_t NormalContexts;
ASTUnit &AST;
CodeCompleteConsumer &Next;
-
+
public:
AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
const CodeCompleteOptions &CodeCompleteOpts)
- : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
- AST(AST), Next(Next)
- {
+ : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
+ AST(AST), Next(Next) {
// Compute the set of contexts in which we will look when we don't have
// any information about the specific context.
- NormalContexts
+ NormalContexts
= (1LL << CodeCompletionContext::CCC_TopLevel)
| (1LL << CodeCompletionContext::CCC_ObjCInterface)
| (1LL << CodeCompletionContext::CCC_ObjCImplementation)
@@ -1866,9 +1924,10 @@ namespace {
return Next.getCodeCompletionTUInfo();
}
};
-} // anonymous namespace
-/// \brief Helper function that computes which global names are hidden by the
+} // namespace
+
+/// Helper function that computes which global names are hidden by the
/// local code-completion results.
static void CalculateHiddenNames(const CodeCompletionContext &Context,
CodeCompletionResult *Results,
@@ -1896,13 +1955,13 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
case CodeCompletionContext::CCC_ParenthesizedExpression:
case CodeCompletionContext::CCC_ObjCInterfaceName:
break;
-
+
case CodeCompletionContext::CCC_EnumTag:
case CodeCompletionContext::CCC_UnionTag:
case CodeCompletionContext::CCC_ClassOrStructTag:
OnlyTagNames = true;
break;
-
+
case CodeCompletionContext::CCC_ObjCProtocolName:
case CodeCompletionContext::CCC_MacroName:
case CodeCompletionContext::CCC_MacroNameUse:
@@ -1920,12 +1979,12 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
// be hidden.
return;
}
-
- typedef CodeCompletionResult Result;
+
+ using Result = CodeCompletionResult;
for (unsigned I = 0; I != NumResults; ++I) {
if (Results[I].Kind != Result::RK_Declaration)
continue;
-
+
unsigned IDNS
= Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
@@ -1933,17 +1992,17 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
if (OnlyTagNames)
Hiding = (IDNS & Decl::IDNS_Tag);
else {
- unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
+ unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
Decl::IDNS_NonMemberOperator);
if (Ctx.getLangOpts().CPlusPlus)
HiddenIDNS |= Decl::IDNS_Tag;
Hiding = (IDNS & HiddenIDNS);
}
-
+
if (!Hiding)
continue;
-
+
DeclarationName Name = Results[I].Declaration->getDeclName();
if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
HiddenNames.insert(Identifier->getName());
@@ -1955,7 +2014,7 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
CodeCompletionContext Context,
CodeCompletionResult *Results,
- unsigned NumResults) {
+ unsigned NumResults) {
// Merge the results we were given with the results we cached.
bool AddedResult = false;
uint64_t InContexts =
@@ -1963,31 +2022,31 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
? NormalContexts : (1LL << Context.getKind());
// Contains the set of names that are hidden by "local" completion results.
llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
- typedef CodeCompletionResult Result;
+ using Result = CodeCompletionResult;
SmallVector<Result, 8> AllResults;
- for (ASTUnit::cached_completion_iterator
+ for (ASTUnit::cached_completion_iterator
C = AST.cached_completion_begin(),
CEnd = AST.cached_completion_end();
C != CEnd; ++C) {
- // If the context we are in matches any of the contexts we are
+ // If the context we are in matches any of the contexts we are
// interested in, we'll add this result.
if ((C->ShowInContexts & InContexts) == 0)
continue;
-
+
// If we haven't added any results previously, do so now.
if (!AddedResult) {
- CalculateHiddenNames(Context, Results, NumResults, S.Context,
+ CalculateHiddenNames(Context, Results, NumResults, S.Context,
HiddenNames);
AllResults.insert(AllResults.end(), Results, Results + NumResults);
AddedResult = true;
}
-
+
// Determine whether this global completion result is hidden by a local
// completion result. If so, skip it.
if (C->Kind != CXCursor_MacroDefinition &&
HiddenNames.count(C->Completion->getTypedText()))
continue;
-
+
// Adjust priority based on similar type classes.
unsigned Priority = C->Priority;
CodeCompletionString *Completion = C->Completion;
@@ -1995,7 +2054,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
if (C->Kind == CXCursor_MacroDefinition) {
Priority = getMacroUsagePriority(C->Completion->getTypedText(),
S.getLangOpts(),
- Context.getPreferredType()->isAnyPointerType());
+ Context.getPreferredType()->isAnyPointerType());
} else if (C->Type) {
CanQualType Expected
= S.Context.getCanonicalType(
@@ -2014,7 +2073,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
}
}
}
-
+
// Adjust the completion string, if required.
if (C->Kind == CXCursor_MacroDefinition &&
Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
@@ -2026,18 +2085,18 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
Priority = CCP_CodePattern;
Completion = Builder.TakeString();
}
-
+
AllResults.push_back(Result(Completion, Priority, C->Kind,
C->Availability));
}
-
+
// If we did not add any cached completion results, just forward the
// results we were given to the next consumer.
if (!AddedResult) {
Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
return;
}
-
+
Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
AllResults.size());
}
@@ -2069,6 +2128,8 @@ void ASTUnit::CodeComplete(
CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
+ CodeCompleteOpts.LoadExternal = Consumer.loadExternal();
+ CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts();
assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);
@@ -2093,11 +2154,11 @@ void ASTUnit::CodeComplete(
auto &Inv = *CCInvocation;
Clang->setInvocation(std::move(CCInvocation));
OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
-
+
// Set up diagnostics, capturing any diagnostics produced.
Clang->setDiagnostics(&Diag);
- CaptureDroppedDiagnostics Capture(true,
- Clang->getDiagnostics(),
+ CaptureDroppedDiagnostics Capture(true,
+ Clang->getDiagnostics(),
&StoredDiagnostics, nullptr);
ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());
@@ -2108,13 +2169,13 @@ void ASTUnit::CodeComplete(
Clang->setInvocation(nullptr);
return;
}
-
+
// Inform the target of the language options.
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts());
-
+
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@@ -2123,7 +2184,7 @@ void ASTUnit::CodeComplete(
assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
InputKind::LLVM_IR &&
"IR inputs not support here!");
-
+
// Use the source and file managers that we were given.
Clang->setFileManager(&FileMgr);
Clang->setSourceManager(&SourceMgr);
@@ -2210,7 +2271,7 @@ bool ASTUnit::Save(StringRef File) {
if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath))
return true;
- // FIXME: Can we somehow regenerate the stat cache here, or do we need to
+ // FIXME: Can we somehow regenerate the stat cache here, or do we need to
// unconditionally create a stat cache when we parse the file?
llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
@@ -2258,7 +2319,7 @@ bool ASTUnit::serialize(raw_ostream &OS) {
return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
}
-typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
+using SLocRemap = ContinuousRangeMap<unsigned, int, 2>;
void ASTUnit::TranslateStoredDiagnostics(
FileManager &FileMgr,
@@ -2272,7 +2333,7 @@ void ASTUnit::TranslateStoredDiagnostics(
SmallVector<StoredDiagnostic, 4> Result;
Result.reserve(Diags.size());
- for (const StandaloneDiagnostic &SD : Diags) {
+ for (const auto &SD : Diags) {
// Rebuild the StoredDiagnostic.
if (SD.Filename.empty())
continue;
@@ -2304,7 +2365,7 @@ void ASTUnit::TranslateStoredDiagnostics(
SmallVector<FixItHint, 2> FixIts;
FixIts.reserve(SD.FixIts.size());
- for (const StandaloneFixIt &FixIt : SD.FixIts) {
+ for (const auto &FixIt : SD.FixIts) {
FixIts.push_back(FixItHint());
FixItHint &FH = FixIts.back();
FH.CodeToInsert = FixIt.CodeToInsert;
@@ -2313,7 +2374,7 @@ void ASTUnit::TranslateStoredDiagnostics(
FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
}
- Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
+ Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
SD.Message, Loc, Ranges, FixIts));
}
Result.swap(Out);
@@ -2321,7 +2382,7 @@ void ASTUnit::TranslateStoredDiagnostics(
void ASTUnit::addFileLevelDecl(Decl *D) {
assert(D);
-
+
// We only care about local declarations.
if (D->isFromASTFile())
return;
@@ -2398,7 +2459,7 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first());
if (EndIt != LocDecls.end())
++EndIt;
-
+
for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)
Decls.push_back(DIt->second);
}
@@ -2417,7 +2478,7 @@ SourceLocation ASTUnit::getLocation(const FileEntry *File,
return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
}
-/// \brief If \arg Loc is a loaded location from the preamble, returns
+/// 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) const {
@@ -2438,7 +2499,7 @@ SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {
return Loc;
}
-/// \brief If \arg Loc is a local location of the main file but inside the
+/// 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) const {
@@ -2463,10 +2524,10 @@ bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getPreambleFileID();
-
+
if (Loc.isInvalid() || FID.isInvalid())
return false;
-
+
return SourceMgr->isInFileID(Loc, FID);
}
@@ -2474,10 +2535,10 @@ bool ASTUnit::isInMainFileID(SourceLocation Loc) const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getMainFileID();
-
+
if (Loc.isInvalid() || FID.isInvalid())
return false;
-
+
return SourceMgr->isInFileID(Loc, FID);
}
@@ -2485,9 +2546,9 @@ SourceLocation ASTUnit::getEndOfPreambleFileID() const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getPreambleFileID();
-
+
if (FID.isInvalid())
- return SourceLocation();
+ return {};
return SourceMgr->getLocForEndOfFile(FID);
}
@@ -2496,10 +2557,10 @@ SourceLocation ASTUnit::getStartOfMainFileID() const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getMainFileID();
-
+
if (FID.isInvalid())
- return SourceLocation();
-
+ return {};
+
return SourceMgr->getLocForStartOfFile(FID);
}
@@ -2522,7 +2583,7 @@ bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
if (isMainFileAST()) {
serialization::ModuleFile &
Mod = Reader->getModuleManager().getPrimaryModule();
- for (const Decl *D : Reader->getModuleFileLevelDecls(Mod)) {
+ for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {
if (!Fn(context, D))
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
index 72e8f68dc051..c4504a14456d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
@@ -21,8 +21,8 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/DJB.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -88,7 +88,7 @@ public:
void EmitData(raw_ostream& Out) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
switch (Kind) {
case IsFE: {
// Emit stat information.
@@ -128,14 +128,14 @@ public:
typedef unsigned offset_type;
static hash_value_type ComputeHash(PTHEntryKeyVariant V) {
- return llvm::HashString(V.getString());
+ return llvm::djbHash(V.getString());
}
static std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, PTHEntryKeyVariant V,
const PTHEntry& E) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
unsigned n = V.getString().size() + 1 + 1;
LE.write<uint16_t>(n);
@@ -149,7 +149,7 @@ public:
static void EmitKey(raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){
using namespace llvm::support;
// Emit the entry kind.
- endian::Writer<little>(Out).write<uint8_t>((unsigned)V.getKind());
+ Out << char(V.getKind());
// Emit the string.
Out.write(V.getString().data(), n - 1);
}
@@ -157,7 +157,7 @@ public:
static void EmitData(raw_ostream& Out, PTHEntryKeyVariant V,
const PTHEntry& E, unsigned) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
// For file entries emit the offsets into the PTH file for token data
// and the preprocessor blocks table.
@@ -205,18 +205,17 @@ class PTHWriter {
void EmitToken(const Token& T);
void Emit8(uint32_t V) {
- using namespace llvm::support;
- endian::Writer<little>(Out).write<uint8_t>(V);
+ Out << char(V);
}
void Emit16(uint32_t V) {
using namespace llvm::support;
- endian::Writer<little>(Out).write<uint16_t>(V);
+ endian::write<uint16_t>(Out, V, little);
}
void Emit32(uint32_t V) {
using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(V);
+ endian::write<uint32_t>(Out, V, little);
}
void EmitBuf(const char *Ptr, unsigned NumBytes) {
@@ -225,7 +224,7 @@ class PTHWriter {
void EmitString(StringRef V) {
using namespace llvm::support;
- endian::Writer<little>(Out).write<uint16_t>(V.size());
+ endian::write<uint16_t>(Out, V.size(), little);
EmitBuf(V.data(), V.size());
}
@@ -299,7 +298,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
// Pad 0's so that we emit tokens to a 4-byte alignment.
// This speed up reading them back in.
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
uint32_t TokenOff = Out.tell();
for (uint64_t N = llvm::OffsetToAlignment(TokenOff, 4); N; --N, ++TokenOff)
LE.write<uint8_t>(0);
@@ -625,14 +624,14 @@ public:
typedef unsigned offset_type;
static hash_value_type ComputeHash(PTHIdKey* key) {
- return llvm::HashString(key->II->getName());
+ return llvm::djbHash(key->II->getName());
}
static std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, const PTHIdKey* key, uint32_t) {
using namespace llvm::support;
unsigned n = key->II->getLength() + 1;
- endian::Writer<little>(Out).write<uint16_t>(n);
+ endian::write<uint16_t>(Out, n, little);
return std::make_pair(n, sizeof(uint32_t));
}
@@ -646,7 +645,7 @@ public:
static void EmitData(raw_ostream& Out, PTHIdKey*, uint32_t pID,
unsigned) {
using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(pID);
+ endian::write<uint32_t>(Out, pID, little);
}
};
} // end anonymous namespace
@@ -662,7 +661,8 @@ std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
// (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs
// Note that we use 'calloc', so all the bytes are 0.
- PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey));
+ PTHIdKey *IIDMap = static_cast<PTHIdKey*>(
+ llvm::safe_calloc(idcount, sizeof(PTHIdKey)));
// Create the hashtable.
llvm::OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp b/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
index 534c7587f48d..4e8eb32121dc 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -126,7 +126,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
bool firstInclude = (i == 0);
std::unique_ptr<CompilerInvocation> CInvok;
CInvok.reset(new CompilerInvocation(CI.getInvocation()));
-
+
CInvok->getPreprocessorOpts().ChainedIncludes.clear();
CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
@@ -134,7 +134,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
CInvok->getPreprocessorOpts().Includes.clear();
CInvok->getPreprocessorOpts().MacroIncludes.clear();
CInvok->getPreprocessorOpts().Macros.clear();
-
+
CInvok->getFrontendOpts().Inputs.clear();
FrontendInputFile InputFile(includes[i], IK);
CInvok->getFrontendOpts().Inputs.push_back(InputFile);
@@ -193,7 +193,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
Clang->setModuleManager(Reader);
Clang->getASTContext().setExternalSource(Reader);
}
-
+
if (!Clang->InitializeSourceManager(InputFile))
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp b/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp
index 50bb9f951be4..84a39f2d570d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp
@@ -17,7 +17,7 @@ CodeGenOptions::CodeGenOptions() {
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default);
#include "clang/Frontend/CodeGenOptions.def"
- RelocationModel = "pic";
+ RelocationModel = llvm::Reloc::PIC_;
memcpy(CoverageVersion, "402*", 4);
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
index 7208177aa012..ecb09da3c1ef 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@@ -291,7 +292,7 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
if (!Opts->DiagnosticSerializationFile.empty())
SetupSerializedDiagnostics(Opts, *Diags,
Opts->DiagnosticSerializationFile);
-
+
// Configure our handling of diagnostics.
ProcessWarningOptions(*Diags, *Opts);
@@ -302,11 +303,9 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
FileManager *CompilerInstance::createFileManager() {
if (!hasVirtualFileSystem()) {
- if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
- createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()))
- setVirtualFileSystem(VFS);
- else
- return nullptr;
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(getInvocation(), getDiagnostics());
+ setVirtualFileSystem(VFS);
}
FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem);
return FileMgr.get();
@@ -464,7 +463,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
/*ShowDepth=*/false);
}
- if (DepOpts.PrintShowIncludes) {
+ if (DepOpts.ShowIncludesDest != ShowIncludesDestination::None) {
AttachHeaderIncludeGen(*PP, DepOpts,
/*ShowAllHeaders=*/true, /*OutputPath=*/"",
/*ShowDepth=*/true, /*MSStyle=*/true);
@@ -854,36 +853,7 @@ bool CompilerInstance::InitializeSourceManager(
// Figure out where to get and map in the main file.
if (InputFile != "-") {
- const FileEntry *File;
- if (Opts.FindPchSource.empty()) {
- File = FileMgr.getFile(InputFile, /*OpenFile=*/true);
- } else {
- // When building a pch file in clang-cl mode, the .h file is built as if
- // it was included by a cc file. Since the driver doesn't know about
- // all include search directories, the frontend must search the input
- // file through HeaderSearch here, as if it had been included by the
- // cc file at Opts.FindPchSource.
- const FileEntry *FindFile = FileMgr.getFile(Opts.FindPchSource);
- if (!FindFile) {
- Diags.Report(diag::err_fe_error_reading) << Opts.FindPchSource;
- return false;
- }
- const DirectoryLookup *UnusedCurDir;
- SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
- Includers;
- Includers.push_back(std::make_pair(FindFile, FindFile->getDir()));
- File = HS->LookupFile(InputFile, SourceLocation(), /*isAngled=*/false,
- /*FromDir=*/nullptr,
- /*CurDir=*/UnusedCurDir, Includers,
- /*SearchPath=*/nullptr,
- /*RelativePath=*/nullptr,
- /*RequestingModule=*/nullptr,
- /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr,
- /*SkipCache=*/true);
- // Also add the header to /showIncludes output.
- if (File)
- DepOpts.ShowIncludesPretendHeader = File->getName();
- }
+ const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true);
if (!File) {
Diags.Report(diag::err_fe_error_reading) << InputFile;
return false;
@@ -965,7 +935,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// Adjust target options based on codegen options.
getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
- // rewriter project will change target built-in bool type from its default.
+ // rewriter project will change target built-in bool type from its default.
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
getTarget().noSignedCharForObjCBool();
@@ -1044,7 +1014,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
return !getDiagnostics().getClient()->getNumErrors();
}
-/// \brief Determine the appropriate source input kind based on language
+/// Determine the appropriate source input kind based on language
/// options.
static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) {
if (LangOpts.OpenCL)
@@ -1056,7 +1026,7 @@ static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) {
return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C;
}
-/// \brief Compile a module file for the given module, using the options
+/// Compile a module file for the given module, using the options
/// provided by the importing compiler instance. Returns true if the module
/// was built without errors.
static bool
@@ -1072,7 +1042,7 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
-
+
// For any options that aren't intended to affect how a module is built,
// reset them to their default values.
Invocation->getLangOpts()->resetNonModularOptions();
@@ -1090,6 +1060,10 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
}),
PPOpts.Macros.end());
+ // If the original compiler invocation had -fmodule-name, pass it through.
+ Invocation->getLangOpts()->ModuleName =
+ ImportingInstance.getInvocation().getLangOpts()->ModuleName;
+
// Note the name of the module we're building.
Invocation->getLangOpts()->CurrentModule = ModuleName;
@@ -1118,11 +1092,11 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
// Don't free the remapped file buffers; they are owned by our caller.
PPOpts.RetainRemappedFileBuffers = true;
-
+
Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
assert(ImportingInstance.getInvocation().getModuleHash() ==
Invocation->getModuleHash() && "Module hash mismatch!");
-
+
// Construct a compiler instance that will be used to actually create the
// module. Since we're sharing a PCMCache,
// CompilerInstance::CompilerInstance is responsible for finalizing the
@@ -1162,14 +1136,13 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
// Execute the action to actually build the module in-place. Use a separate
// thread so that we get a stack large enough.
- const unsigned ThreadStackSize = 8 << 20;
llvm::CrashRecoveryContext CRC;
CRC.RunSafelyOnThread(
[&]() {
GenerateModuleFromModuleMapAction Action;
Instance.ExecuteAction(Action);
},
- ThreadStackSize);
+ DesiredStackSize);
PostBuildStep(Instance);
@@ -1186,7 +1159,20 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
return !Instance.getDiagnostics().hasErrorOccurred();
}
-/// \brief Compile a module file for the given module, using the options
+static const FileEntry *getPublicModuleMap(const FileEntry *File,
+ FileManager &FileMgr) {
+ StringRef Filename = llvm::sys::path::filename(File->getName());
+ SmallString<128> PublicFilename(File->getDir()->getName());
+ if (Filename == "module_private.map")
+ llvm::sys::path::append(PublicFilename, "module.map");
+ else if (Filename == "module.private.modulemap")
+ llvm::sys::path::append(PublicFilename, "module.modulemap");
+ else
+ return nullptr;
+ return FileMgr.getFile(PublicFilename);
+}
+
+/// Compile a module file for the given module, using the options
/// provided by the importing compiler instance. Returns true if the module
/// was built without errors.
static bool compileModuleImpl(CompilerInstance &ImportingInstance,
@@ -1197,11 +1183,18 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
InputKind::ModuleMap);
// Get or create the module map that we'll use to build this module.
- ModuleMap &ModMap
+ ModuleMap &ModMap
= ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
bool Result;
if (const FileEntry *ModuleMapFile =
ModMap.getContainingModuleMapFile(Module)) {
+ // Canonicalize compilation to start with the public module map. This is
+ // vital for submodules declarations in the private module maps to be
+ // correctly parsed when depending on a top level module in the public one.
+ if (const FileEntry *PublicMMFile = getPublicModuleMap(
+ ModuleMapFile, ImportingInstance.getFileManager()))
+ ModuleMapFile = PublicMMFile;
+
// Use the module map where this module resides.
Result = compileModuleImpl(
ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
@@ -1298,7 +1291,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
// case of timeout, build it ourselves.
Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout)
<< Module->Name;
- // Clear the lock file so that future invokations can make progress.
+ // Clear the lock file so that future invocations can make progress.
Locked.unsafeRemoveLockFile();
continue;
}
@@ -1328,13 +1321,13 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
}
}
-/// \brief Diagnose differences between the current definition of the given
+/// Diagnose differences between the current definition of the given
/// configuration macro and the definition provided on the command line.
static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
Module *Mod, SourceLocation ImportLoc) {
IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro);
SourceManager &SourceMgr = PP.getSourceManager();
-
+
// If this identifier has never had a macro definition, then it could
// not have changed.
if (!Id->hadMacroDefinition())
@@ -1386,13 +1379,13 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
}
}
-/// \brief Write a new timestamp file with the given path.
+/// Write a new timestamp file with the given path.
static void writeTimestampFile(StringRef TimestampFile) {
std::error_code EC;
llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None);
}
-/// \brief Prune the module cache of modules that haven't been accessed in
+/// Prune the module cache of modules that haven't been accessed in
/// a long time.
static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
struct stat StatBuf;
@@ -1580,15 +1573,22 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
if (!ModuleManager)
createModuleManager();
+ // If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the
+ // ASTReader to diagnose it, since it can produce better errors that we can.
+ bool ConfigMismatchIsRecoverable =
+ getDiagnostics().getDiagnosticLevel(diag::warn_module_config_mismatch,
+ SourceLocation())
+ <= DiagnosticsEngine::Warning;
+
auto Listener = llvm::make_unique<ReadModuleNames>(*this);
auto &ListenerRef = *Listener;
ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager,
std::move(Listener));
// Try to load the module file.
- switch (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule,
- SourceLocation(),
- ASTReader::ARR_ConfigurationMismatch)) {
+ switch (ModuleManager->ReadAST(
+ FileName, serialization::MK_ExplicitModule, SourceLocation(),
+ ConfigMismatchIsRecoverable ? ASTReader::ARR_ConfigurationMismatch : 0)) {
case ASTReader::Success:
// We successfully loaded the module file; remember the set of provided
// modules so that we don't try to load implicit modules for them.
@@ -1651,10 +1651,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
= KnownModules.find(Path[0].first);
if (Known != KnownModules.end()) {
// Retrieve the cached top-level module.
- Module = Known->second;
+ Module = Known->second;
} else if (ModuleName == getLangOpts().CurrentModule) {
- // This is the module we're building.
- Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
+ // This is the module we're building.
+ Module = PP->getHeaderSearchInfo().lookupModule(
+ ModuleName, /*AllowSearch*/ true,
+ /*AllowExtraModuleMapSearch*/ !IsInclusionDirective);
/// 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) {
@@ -1666,7 +1668,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
} else {
// Search for a module with the given name.
- Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
+ Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true,
+ !IsInclusionDirective);
HeaderSearchOptions &HSOpts =
PP->getHeaderSearchInfo().getHeaderSearchOpts();
@@ -1743,7 +1746,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
ImportLoc, ARRFlags)) {
case ASTReader::Success: {
if (Source != ModuleCache && !Module) {
- Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
+ Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true,
+ !IsInclusionDirective);
if (!Module || !Module->getASTFile() ||
FileMgr->getFile(ModuleFileName) != Module->getASTFile()) {
// Error out if Module does not refer to the file in the prebuilt
@@ -1847,7 +1851,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Cache the result of this top-level module lookup for later.
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
}
-
+
// If we never found the module, fail.
if (!Module)
return ModuleLoadResult();
@@ -1859,40 +1863,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
StringRef Name = Path[I].first->getName();
clang::Module *Sub = Module->findSubmodule(Name);
-
- if (!Sub) {
- // Attempt to perform typo correction to find a module name that works.
- SmallVector<StringRef, 2> Best;
- unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
-
- for (clang::Module::submodule_iterator J = Module->submodule_begin(),
- JEnd = Module->submodule_end();
- J != JEnd; ++J) {
- unsigned ED = Name.edit_distance((*J)->Name,
- /*AllowReplacements=*/true,
- BestEditDistance);
- if (ED <= BestEditDistance) {
- if (ED < BestEditDistance) {
- Best.clear();
- BestEditDistance = ED;
- }
-
- Best.push_back((*J)->Name);
- }
- }
-
- // If there was a clear winner, user it.
- if (Best.size() == 1) {
- getDiagnostics().Report(Path[I].second,
- diag::err_no_submodule_suggest)
- << Path[I].first << Module->getFullModuleName() << Best[0]
- << SourceRange(Path[0].second, Path[I-1].second)
- << FixItHint::CreateReplacement(SourceRange(Path[I].second),
- Best[0]);
-
- Sub = Module->findSubmodule(Best[0]);
- }
- }
// If the user is requesting Foo.Private and it doesn't exist, try to
// match Foo_Private and emit a warning asking for the user to write
@@ -1908,7 +1878,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
PrivPath.push_back(std::make_pair(&II, Path[0].second));
- if (PP->getHeaderSearchInfo().lookupModule(PrivateModule))
+ if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true,
+ !IsInclusionDirective))
Sub =
loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
if (Sub) {
@@ -1928,6 +1899,40 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
}
if (!Sub) {
+ // Attempt to perform typo correction to find a module name that works.
+ SmallVector<StringRef, 2> Best;
+ unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
+
+ for (clang::Module::submodule_iterator J = Module->submodule_begin(),
+ JEnd = Module->submodule_end();
+ J != JEnd; ++J) {
+ unsigned ED = Name.edit_distance((*J)->Name,
+ /*AllowReplacements=*/true,
+ BestEditDistance);
+ if (ED <= BestEditDistance) {
+ if (ED < BestEditDistance) {
+ Best.clear();
+ BestEditDistance = ED;
+ }
+
+ Best.push_back((*J)->Name);
+ }
+ }
+
+ // If there was a clear winner, user it.
+ if (Best.size() == 1) {
+ getDiagnostics().Report(Path[I].second,
+ diag::err_no_submodule_suggest)
+ << Path[I].first << Module->getFullModuleName() << Best[0]
+ << SourceRange(Path[0].second, Path[I-1].second)
+ << FixItHint::CreateReplacement(SourceRange(Path[I].second),
+ Best[0]);
+
+ Sub = Module->findSubmodule(Best[0]);
+ }
+ }
+
+ if (!Sub) {
// No submodule by this name. Complain, and don't look for further
// submodules.
getDiagnostics().Report(Path[I].second, diag::err_no_submodule)
@@ -1935,7 +1940,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
<< SourceRange(Path[0].second, Path[I-1].second);
break;
}
-
+
Module = Sub;
}
}
@@ -1977,6 +1982,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module, ImportLoc);
}
+ // Resolve any remaining module using export_as for this one.
+ getPreprocessor()
+ .getHeaderSearchInfo()
+ .getModuleMap()
+ .resolveLinkAsDependencies(TopModule);
+
LastModuleImportLoc = ImportLoc;
LastModuleImportResult = ModuleLoadResult(Module);
return LastModuleImportResult;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 438a48083ef6..78e6babd0251 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1,4 +1,4 @@
-//===--- CompilerInvocation.cpp -------------------------------------------===//
+//===- CompilerInvocation.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,54 +10,99 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "TestModuleFileExtension.h"
#include "clang/Basic/Builtins.h"
-#include "clang/Basic/FileManager.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/DebugInfoOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Basic/Visibility.h"
+#include "clang/Basic/XRayInstr.h"
#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
-#include "clang/Driver/Util.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/CommandLineSourceLoc.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/LangStandard.h"
+#include "clang/Frontend/MigratorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Serialization/ASTReader.h"
+#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Serialization/ModuleFileExtension.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Linker/Linker.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Support/ScopedPrinter.h"
+#include <algorithm>
#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
#include <memory>
-#include <sys/stat.h>
-#include <system_error>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
using namespace clang;
+using namespace driver;
+using namespace options;
+using namespace llvm::opt;
//===----------------------------------------------------------------------===//
// Initialization.
//===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase()
- : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
- DiagnosticOpts(new DiagnosticOptions()),
- HeaderSearchOpts(new HeaderSearchOptions()),
- PreprocessorOpts(new PreprocessorOptions()) {}
+ : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
+ DiagnosticOpts(new DiagnosticOptions()),
+ HeaderSearchOpts(new HeaderSearchOptions()),
+ PreprocessorOpts(new PreprocessorOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
: LangOpts(new LangOptions(*X.getLangOpts())),
@@ -66,18 +111,12 @@ CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
-CompilerInvocationBase::~CompilerInvocationBase() {}
+CompilerInvocationBase::~CompilerInvocationBase() = default;
//===----------------------------------------------------------------------===//
// Deserialization (from args)
//===----------------------------------------------------------------------===//
-using namespace clang::driver;
-using namespace clang::driver::options;
-using namespace llvm::opt;
-
-//
-
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
unsigned DefaultOpt = 0;
@@ -91,7 +130,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
if (A->getOption().matches(options::OPT_Ofast))
return 3;
- assert (A->getOption().matches(options::OPT_O));
+ assert(A->getOption().matches(options::OPT_O));
StringRef S(A->getValue());
if (S == "s" || S == "z" || S.empty())
@@ -125,7 +164,7 @@ static unsigned getOptimizationLevelSize(ArgList &Args) {
static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
OptSpecifier GroupWithValue,
std::vector<std::string> &Diagnostics) {
- for (Arg *A : Args.filtered(Group)) {
+ for (auto *A : Args.filtered(Group)) {
if (A->getOption().getKind() == Option::FlagClass) {
// The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
// its name (minus the "W" or "R" at the beginning) to the warning list.
@@ -135,7 +174,7 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
} else {
// Otherwise, add its value (for OPT_W_Joined and similar).
- for (const char *Arg : A->getValues())
+ for (const auto *Arg : A->getValues())
Diagnostics.emplace_back(Arg);
}
}
@@ -157,7 +196,6 @@ static void getAllNoBuiltinFuncValues(ArgList &Args,
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- using namespace options;
bool Success = true;
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
StringRef Name = A->getValue();
@@ -273,31 +311,31 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
StringRef checkerList = A->getValue();
SmallVector<StringRef, 4> checkers;
checkerList.split(checkers, ",");
- for (StringRef checker : checkers)
+ for (auto checker : checkers)
Opts.CheckersControlList.emplace_back(checker, enable);
}
// Go through the analyzer configuration options.
- for (const Arg *A : Args.filtered(OPT_analyzer_config)) {
+ for (const auto *A : Args.filtered(OPT_analyzer_config)) {
A->claim();
// We can have a list of comma separated config names, e.g:
// '-analyzer-config key1=val1,key2=val2'
StringRef configList = A->getValue();
SmallVector<StringRef, 4> configVals;
configList.split(configVals, ",");
- for (unsigned i = 0, e = configVals.size(); i != e; ++i) {
+ for (const auto &configVal : configVals) {
StringRef key, val;
- std::tie(key, val) = configVals[i].split("=");
+ std::tie(key, val) = configVal.split("=");
if (val.empty()) {
Diags.Report(SourceLocation(),
- diag::err_analyzer_config_no_value) << configVals[i];
+ diag::err_analyzer_config_no_value) << configVal;
Success = false;
break;
}
if (val.find('=') != StringRef::npos) {
Diags.Report(SourceLocation(),
diag::err_analyzer_config_multiple_values)
- << configVals[i];
+ << configVal;
Success = false;
break;
}
@@ -305,6 +343,14 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
}
+ llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
+ for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
+ if (i != 0)
+ os << " ";
+ os << Args.getArgString(i);
+ }
+ os.flush();
+
return Success;
}
@@ -330,18 +376,26 @@ static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) {
return "default";
}
-static StringRef getRelocModel(ArgList &Args, DiagnosticsEngine &Diags) {
+static llvm::Reloc::Model getRelocModel(ArgList &Args,
+ DiagnosticsEngine &Diags) {
if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) {
StringRef Value = A->getValue();
- if (Value == "static" || Value == "pic" || Value == "ropi" ||
- Value == "rwpi" || Value == "ropi-rwpi" || Value == "dynamic-no-pic")
- return Value;
+ auto RM = llvm::StringSwitch<llvm::Optional<llvm::Reloc::Model>>(Value)
+ .Case("static", llvm::Reloc::Static)
+ .Case("pic", llvm::Reloc::PIC_)
+ .Case("ropi", llvm::Reloc::ROPI)
+ .Case("rwpi", llvm::Reloc::RWPI)
+ .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
+ .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
+ .Default(None);
+ if (RM.hasValue())
+ return *RM;
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
}
- return "pic";
+ return llvm::Reloc::PIC_;
}
-/// \brief Create a new Regex instance out of the string value in \p RpassArg.
+/// Create a new Regex instance out of the string value in \p RpassArg.
/// It returns a pointer to the newly generated Regex instance.
static std::shared_ptr<llvm::Regex>
GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
@@ -392,6 +446,25 @@ static void parseSanitizerKinds(StringRef FlagName,
}
}
+static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
+ ArgList &Args, DiagnosticsEngine &D,
+ XRayInstrSet &S) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ llvm::SplitString(Bundle, BundleParts, ",");
+ for (const auto B : BundleParts) {
+ auto Mask = parseXRayInstrValue(B);
+ if (Mask == XRayInstrKind::None)
+ if (B != "none")
+ D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
+ else
+ S.Mask = Mask;
+ else if (Mask == XRayInstrKind::All)
+ S.Mask = Mask;
+ else
+ S.set(Mask, true);
+ }
+}
+
// Set the profile kind for fprofile-instrument.
static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
@@ -409,8 +482,7 @@ static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args,
<< S;
return;
}
- CodeGenOptions::ProfileInstrKind Instrumentor =
- static_cast<CodeGenOptions::ProfileInstrKind>(I);
+ auto Instrumentor = static_cast<CodeGenOptions::ProfileInstrKind>(I);
Opts.setProfileInstr(Instrumentor);
}
@@ -434,8 +506,8 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
- const TargetOptions &TargetOpts) {
- using namespace options;
+ const TargetOptions &TargetOpts,
+ const FrontendOptions &FrontendOpts) {
bool Success = true;
llvm::Triple Triple = llvm::Triple(TargetOpts.Triple);
@@ -474,7 +546,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.ExperimentalNewPassManager = Args.hasFlag(
OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager,
- /* Default */ false);
+ /* Default */ ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER);
Opts.DebugPassManager =
Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager,
@@ -529,6 +601,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
+ Opts.EmbedSource = Args.hasArg(OPT_gembed_source);
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
@@ -580,33 +653,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
if (!Opts.ProfileInstrumentUsePath.empty())
setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath);
- if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
- Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest);
-
- StringRef Ver = A->getValue();
- std::pair<StringRef, StringRef> VerParts = Ver.split('.');
- unsigned Major, Minor = 0;
-
- // Check the version number is valid: either 3.x (0 <= x <= 9) or
- // y or y.0 (4 <= y <= current version).
- if (!VerParts.first.startswith("0") &&
- !VerParts.first.getAsInteger(10, Major) &&
- 3 <= Major && Major <= CLANG_VERSION_MAJOR &&
- (Major == 3 ? VerParts.second.size() == 1 &&
- !VerParts.second.getAsInteger(10, Minor)
- : VerParts.first.size() == Ver.size() ||
- VerParts.second == "0")) {
- // Got a valid version number.
- if (Major == 3 && Minor <= 8)
- Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8);
- else if (Major <= 4)
- Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4);
- } else if (Ver != "latest") {
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue();
- }
- }
-
Opts.CoverageMapping =
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
@@ -615,6 +661,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
+ Opts.RegisterGlobalDtorsWithAtExit =
+ Args.hasArg(OPT_fregister_global_dtors_with_atexit);
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
Opts.CodeModel = getCodeModel(Args, Diags);
Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
@@ -623,6 +671,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DisableFree = Args.hasArg(OPT_disable_free);
Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names);
Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls);
+ Opts.NoEscapingBlockTailCalls =
+ Args.hasArg(OPT_fno_escaping_block_tail_calls);
Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) ||
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
@@ -640,14 +690,20 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
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.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero) ||
+ (Args.hasArg(OPT_fcuda_is_device) &&
+ Args.hasArg(OPT_fcuda_flush_denormals_to_zero));
Opts.CorrectlyRoundedDivSqrt =
Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt);
+ Opts.UniformWGSize =
+ Args.hasArg(OPT_cl_uniform_work_group_size);
Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
+ Opts.StrictFloatCastOverflow =
+ !Args.hasArg(OPT_fno_strict_float_cast_overflow);
+
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
- Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
@@ -665,6 +721,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums);
Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return);
Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers);
+ Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables);
Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
@@ -682,6 +739,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
OPT_fno_function_sections, false);
Opts.DataSections = Args.hasFlag(OPT_fdata_sections,
OPT_fno_data_sections, false);
+ Opts.StackSizeSection =
+ Args.hasFlag(OPT_fstack_size_section, OPT_fno_stack_size_section, false);
Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names,
OPT_fno_unique_section_names, true);
@@ -689,14 +748,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables);
+ Opts.NullPointerIsValid = Args.hasArg(OPT_fno_delete_null_pointer_checks);
+
Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate);
Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
- Opts.EmitSummaryIndex = false;
+ Opts.PrepareForThinLTO = false;
if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
StringRef S = A->getValue();
if (S == "thin")
- Opts.EmitSummaryIndex = true;
+ Opts.PrepareForThinLTO = true;
else if (S != "full")
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
}
@@ -707,6 +768,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
<< A->getAsString(Args) << "-x ir";
Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ);
}
+ if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
+ Opts.SaveTempsFilePrefix =
+ llvm::StringSwitch<std::string>(A->getValue())
+ .Case("obj", FrontendOpts.OutputFile)
+ .Default(llvm::sys::path::filename(FrontendOpts.OutputFile).str());
+
Opts.ThinLinkBitcodeFile = Args.getLastArgValue(OPT_fthin_link_bitcode_EQ);
Opts.MSVolatile = Args.hasArg(OPT_fms_volatile);
@@ -719,6 +786,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
+ Opts.ControlFlowGuard = Args.hasArg(OPT_cfguard);
+
Opts.DisableGCov = Args.hasArg(OPT_test_coverage);
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
@@ -741,7 +810,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
}
- // Handle -fembed-bitcode option.
+ // Handle -fembed-bitcode option.
if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
StringRef Name = A->getValue();
unsigned Model = llvm::StringSwitch<unsigned>(Name)
@@ -787,15 +856,44 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_finstrument_functions_after_inlining);
Opts.InstrumentFunctionEntryBare =
Args.hasArg(OPT_finstrument_function_entry_bare);
- Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument);
+
+ Opts.XRayInstrumentFunctions =
+ Args.hasArg(OPT_fxray_instrument);
Opts.XRayAlwaysEmitCustomEvents =
Args.hasArg(OPT_fxray_always_emit_customevents);
+ Opts.XRayAlwaysEmitTypedEvents =
+ Args.hasArg(OPT_fxray_always_emit_typedevents);
Opts.XRayInstructionThreshold =
getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
+
+ auto XRayInstrBundles =
+ Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
+ if (XRayInstrBundles.empty())
+ Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;
+ else
+ for (const auto &A : XRayInstrBundles)
+ parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
+ Diags, Opts.XRayInstrumentationBundle);
+
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
Opts.CallFEntry = Args.hasArg(OPT_mfentry);
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
+ if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
+ StringRef Name = A->getValue();
+ if (Name == "full") {
+ Opts.CFProtectionReturn = 1;
+ Opts.CFProtectionBranch = 1;
+ } else if (Name == "return")
+ Opts.CFProtectionReturn = 1;
+ else if (Name == "branch")
+ Opts.CFProtectionBranch = 1;
+ else if (Name != "none") {
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+ Success = false;
+ }
+ }
+
if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
OPT_compress_debug_sections_EQ)) {
if (A->getOption().getID() == OPT_compress_debug_sections) {
@@ -813,7 +911,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
- for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
+ for (auto *A :
+ Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
CodeGenOptions::BitcodeFileToLink F;
F.Filename = A->getValue();
if (A->getOption().matches(OPT_mlink_cuda_bitcode)) {
@@ -855,6 +954,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
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_poison_class_member_array_new_cookie,
+ OPT_fno_sanitize_address_poison_class_member_array_new_cookie)) {
+ Opts.SanitizeAddressPoisonClassMemberArrayNewCookie =
+ A->getOption().getID() ==
+ OPT_fsanitize_address_poison_class_member_array_new_cookie;
+ }
if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope,
OPT_fno_sanitize_address_use_after_scope)) {
Opts.SanitizeAddressUseAfterScope =
@@ -879,6 +985,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.StackProbeSize = StackProbeSize;
}
+ Opts.NoStackArgProbe = Args.hasArg(OPT_mno_stack_arg_probe);
+
if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
StringRef Name = A->getValue();
unsigned Method = llvm::StringSwitch<unsigned>(Name)
@@ -895,8 +1003,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
- Opts.EmulatedTLS =
- Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false);
+ if (Args.getLastArg(OPT_femulated_tls) ||
+ Args.getLastArg(OPT_fno_emulated_tls)) {
+ Opts.ExplicitEmulatedTLS = true;
+ Opts.EmulatedTLS =
+ Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false);
+ }
if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
StringRef Name = A->getValue();
@@ -967,7 +1079,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
bool UsingProfile = UsingSampleProfile ||
(Opts.getProfileUse() != CodeGenOptions::ProfileNone);
- if (Opts.DiagnosticsWithHotness && !UsingProfile)
+ if (Opts.DiagnosticsWithHotness && !UsingProfile &&
+ // An IR file will contain PGO as metadata
+ IK.getLanguage() != InputKind::LLVM_IR)
Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
<< "-fdiagnostics-show-hotness";
@@ -999,20 +1113,23 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
Opts.SanitizeTrap);
- Opts.CudaGpuBinaryFileNames =
- Args.getAllArgValues(OPT_fcuda_include_gpubinary);
+ Opts.CudaGpuBinaryFileName =
+ Args.getLastArgValue(OPT_fcuda_include_gpubinary);
Opts.Backchain = Args.hasArg(OPT_mbackchain);
Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue(
Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags);
+ Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
+
+ Opts.Addrsig = Args.hasArg(OPT_faddrsig);
+
return Success;
}
static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
ArgList &Args) {
- using namespace options;
Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file);
Opts.Targets = Args.getAllArgValues(OPT_MT);
Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
@@ -1021,7 +1138,17 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
- Opts.PrintShowIncludes = Args.hasArg(OPT_show_includes);
+ if (Args.hasArg(OPT_show_includes)) {
+ // Writing both /showIncludes and preprocessor output to stdout
+ // would produce interleaved output, so use stderr for /showIncludes.
+ // This behaves the same as cl.exe, when /E, /EP or /P are passed.
+ if (Args.hasArg(options::OPT_E) || Args.hasArg(options::OPT_P))
+ Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;
+ else
+ Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;
+ } else {
+ Opts.ShowIncludesDest = ShowIncludesDestination::None;
+ }
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
Opts.ModuleDependencyOutputDir =
Args.getLastArgValue(OPT_module_dependency_dir);
@@ -1032,7 +1159,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
// we let make / ninja to know about this implicit dependency.
Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry);
// Only the -fmodule-file=<file> form.
- for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
Opts.ExtraDeps.push_back(Val);
@@ -1049,7 +1176,7 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
Colors_Off,
Colors_Auto
} ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
- for (Arg *A : Args) {
+ for (auto *A : Args) {
const Option &O = A->getOption();
if (O.matches(options::OPT_fcolor_diagnostics) ||
O.matches(options::OPT_fdiagnostics_color)) {
@@ -1095,7 +1222,6 @@ static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags,
bool DefaultDiagColor, bool DefaultShowOpt) {
- using namespace options;
bool Success = true;
Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
@@ -1190,7 +1316,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Success = false;
}
else
- std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
+ llvm::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
@@ -1262,7 +1388,6 @@ static bool parseTestModuleFileExtensionArg(StringRef Arg,
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags,
bool &IsHeaderFile) {
- using namespace options;
Opts.ProgramAction = frontend::ParseSyntaxOnly;
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
switch (A->getOption().getID()) {
@@ -1278,6 +1403,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::ASTPrint; break;
case OPT_ast_view:
Opts.ProgramAction = frontend::ASTView; break;
+ case OPT_compiler_options_dump:
+ Opts.ProgramAction = frontend::DumpCompilerOptions; break;
case OPT_dump_raw_tokens:
Opts.ProgramAction = frontend::DumpRawTokens; break;
case OPT_dump_tokens:
@@ -1323,6 +1450,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
+ case OPT_templight_dump:
+ Opts.ProgramAction = frontend::TemplightDump; break;
case OPT_rewrite_macros:
Opts.ProgramAction = frontend::RewriteMacros; break;
case OPT_rewrite_objc:
@@ -1344,7 +1473,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ActionName = A->getValue();
}
Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
- for (const Arg *AA : Args.filtered(OPT_plugin_arg))
+ for (const auto *AA : Args.filtered(OPT_plugin_arg))
Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
for (const std::string &Arg :
@@ -1397,7 +1526,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
// Only the -fmodule-file=<file> form.
- for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
Opts.ModuleFiles.push_back(Val);
@@ -1416,12 +1545,13 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
= !Args.hasArg(OPT_no_code_completion_ns_level_decls);
Opts.CodeCompleteOpts.IncludeBriefComments
= Args.hasArg(OPT_code_completion_brief_comments);
+ Opts.CodeCompleteOpts.IncludeFixIts
+ = Args.hasArg(OPT_code_completion_with_fixits);
Opts.OverrideRecordLayoutsFile
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
Opts.AuxTriple =
llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));
- Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ);
Opts.StatsFile = Args.getLastArgValue(OPT_stats_file);
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
@@ -1502,6 +1632,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
.Case("c", InputKind::C)
.Case("cl", InputKind::OpenCL)
.Case("cuda", InputKind::CUDA)
+ .Case("hip", InputKind::HIP)
.Case("c++", InputKind::CXX)
.Case("objective-c", InputKind::ObjC)
.Case("objective-c++", InputKind::ObjCXX)
@@ -1585,7 +1716,6 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
const std::string &WorkingDir) {
- using namespace options;
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
@@ -1608,12 +1738,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
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)) {
+ for (const auto *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))
+ for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
Opts.AddPrebuiltModulePath(A->getValue());
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
@@ -1634,7 +1764,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
if (const Arg *A = Args.getLastArg(OPT_fmodule_format_EQ))
Opts.ModuleFormat = A->getValue();
- for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) {
+ for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
StringRef MacroDef = A->getValue();
Opts.ModulesIgnoreMacros.insert(
llvm::CachedHashString(MacroDef.split('=').first));
@@ -1644,7 +1774,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
bool IsIndexHeaderMap = false;
bool IsSysrootSpecified =
Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
- for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
+ for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
if (A->getOption().matches(OPT_index_header_map)) {
// -index-header-map applies to the next -I or -F.
IsIndexHeaderMap = true;
@@ -1671,7 +1801,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
// Add -iprefix/-iwithprefix/-iwithprefixbefore options.
StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
if (A->getOption().matches(OPT_iprefix))
Prefix = A->getValue();
@@ -1681,31 +1811,31 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
}
- for (const Arg *A : Args.filtered(OPT_idirafter))
+ for (const auto *A : Args.filtered(OPT_idirafter))
Opts.AddPath(A->getValue(), frontend::After, false, true);
- for (const Arg *A : Args.filtered(OPT_iquote))
+ for (const auto *A : Args.filtered(OPT_iquote))
Opts.AddPath(A->getValue(), frontend::Quoted, false, true);
- for (const Arg *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
+ for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
Opts.AddPath(A->getValue(), frontend::System, false,
!A->getOption().matches(OPT_iwithsysroot));
- for (const Arg *A : Args.filtered(OPT_iframework))
+ for (const auto *A : Args.filtered(OPT_iframework))
Opts.AddPath(A->getValue(), frontend::System, true, true);
- for (const Arg *A : Args.filtered(OPT_iframeworkwithsysroot))
+ for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
/*IgnoreSysRoot=*/false);
// Add the paths for the various language specific isystem flags.
- for (const Arg *A : Args.filtered(OPT_c_isystem))
+ for (const auto *A : Args.filtered(OPT_c_isystem))
Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
- for (const Arg *A : Args.filtered(OPT_cxx_isystem))
+ for (const auto *A : Args.filtered(OPT_cxx_isystem))
Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
- for (const Arg *A : Args.filtered(OPT_objc_isystem))
+ for (const auto *A : Args.filtered(OPT_objc_isystem))
Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
- for (const Arg *A : Args.filtered(OPT_objcxx_isystem))
+ for (const auto *A : Args.filtered(OPT_objcxx_isystem))
Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
// Add the internal paths from a driver that detects standard include paths.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
frontend::IncludeDirGroup Group = frontend::System;
if (A->getOption().matches(OPT_internal_externc_isystem))
@@ -1714,12 +1844,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
}
// Add the path prefixes which are implicitly treated as being system headers.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
Opts.AddSystemHeaderPrefix(
A->getValue(), A->getOption().matches(OPT_system_header_prefix));
- for (const Arg *A : Args.filtered(OPT_ivfsoverlay))
+ for (const auto *A : Args.filtered(OPT_ivfsoverlay))
Opts.AddVFSOverlayFile(A->getValue());
}
@@ -1754,22 +1884,37 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
break;
case InputKind::Asm:
case InputKind::C:
+#if defined(CLANG_DEFAULT_STD_C)
+ LangStd = CLANG_DEFAULT_STD_C;
+#else
// The PS4 uses C99 as the default C standard.
if (T.isPS4())
LangStd = LangStandard::lang_gnu99;
else
LangStd = LangStandard::lang_gnu11;
+#endif
break;
case InputKind::ObjC:
+#if defined(CLANG_DEFAULT_STD_C)
+ LangStd = CLANG_DEFAULT_STD_C;
+#else
LangStd = LangStandard::lang_gnu11;
+#endif
break;
case InputKind::CXX:
case InputKind::ObjCXX:
+#if defined(CLANG_DEFAULT_STD_CXX)
+ LangStd = CLANG_DEFAULT_STD_CXX;
+#else
LangStd = LangStandard::lang_gnucxx14;
+#endif
break;
case InputKind::RenderScript:
LangStd = LangStandard::lang_c99;
break;
+ case InputKind::HIP:
+ LangStd = LangStandard::lang_hip;
+ break;
}
}
@@ -1799,6 +1944,8 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.OpenCLVersion = 120;
else if (LangStd == LangStandard::lang_opencl20)
Opts.OpenCLVersion = 200;
+ else if (LangStd == LangStandard::lang_openclcpp)
+ Opts.OpenCLCPlusPlusVersion = 100;
// OpenCL has some additional defaults.
if (Opts.OpenCL) {
@@ -1808,13 +1955,15 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.setDefaultFPContractMode(LangOptions::FPC_On);
Opts.NativeHalfType = 1;
Opts.NativeHalfArgsAndReturns = 1;
+ Opts.OpenCLCPlusPlus = Opts.CPlusPlus;
// Include default header file for OpenCL.
if (Opts.IncludeDefaultHeader) {
PPOpts.Includes.push_back("opencl-c.h");
}
}
- Opts.CUDA = IK.getLanguage() == InputKind::CUDA;
+ Opts.HIP = IK.getLanguage() == InputKind::HIP;
+ Opts.CUDA = IK.getLanguage() == InputKind::CUDA || Opts.HIP;
if (Opts.CUDA)
// Set default FP_CONTRACT to FAST.
Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
@@ -1885,6 +2034,10 @@ static bool IsInputCompatibleWithStandard(InputKind IK,
return S.getLanguage() == InputKind::CUDA ||
S.getLanguage() == InputKind::CXX;
+ case InputKind::HIP:
+ return S.getLanguage() == InputKind::CXX ||
+ S.getLanguage() == InputKind::HIP;
+
case InputKind::Asm:
// Accept (and ignore) all -std= values.
// FIXME: The -std= value is not ignored; it affects the tokenization
@@ -1912,6 +2065,8 @@ static const StringRef GetInputKindName(InputKind IK) {
return "CUDA";
case InputKind::RenderScript:
return "RenderScript";
+ case InputKind::HIP:
+ return "HIP";
case InputKind::Asm:
return "Asm";
@@ -1975,6 +2130,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
+ StringRef Name = A->getValue();
+ if (Name == "full" || Name == "branch") {
+ Opts.CFProtectionBranch = 1;
+ }
+ }
// -cl-std only applies for OpenCL language standards.
// Override the -std option in this case.
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
@@ -1984,6 +2145,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
.Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
.Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
.Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
+ .Case("c++", LangStandard::lang_openclcpp)
.Default(LangStandard::lang_unspecified);
if (OpenCLLangStd == LangStandard::lang_unspecified) {
@@ -2004,11 +2166,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// this option was added for compatibility with OpenCL 1.0.
if (Args.getLastArg(OPT_cl_strict_aliasing)
&& Opts.OpenCLVersion > 100) {
- std::string VerSpec = llvm::to_string(Opts.OpenCLVersion / 100) +
- std::string(".") +
- llvm::to_string((Opts.OpenCLVersion % 100) / 10);
Diags.Report(diag::warn_option_invalid_ocl_version)
- << VerSpec << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
+ << Opts.getOpenCLVersionTuple().getAsString()
+ << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
}
// We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
@@ -2019,6 +2179,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords,
Opts.GNUKeywords);
+ Opts.Digraphs = Args.hasFlag(OPT_fdigraphs, OPT_fno_digraphs, Opts.Digraphs);
+
if (Args.hasArg(OPT_fno_operator_names))
Opts.CXXOperatorNames = 0;
@@ -2031,12 +2193,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fno_cuda_host_device_constexpr))
Opts.CUDAHostDeviceConstexpr = 0;
- if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_flush_denormals_to_zero))
- Opts.CUDADeviceFlushDenormalsToZero = 1;
-
if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals))
Opts.CUDADeviceApproxTranscendentals = 1;
+ Opts.CUDARelocatableDeviceCode = Args.hasArg(OPT_fcuda_rdc);
+
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
StringRef value = arg->getValue();
@@ -2177,12 +2338,27 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
+ // -ffixed-point
+ Opts.FixedPoint =
+ Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) &&
+ !Opts.CPlusPlus;
+ Opts.PaddingOnUnsignedFixedPoint =
+ Args.hasFlag(OPT_fpadding_on_unsigned_fixed_point,
+ OPT_fno_padding_on_unsigned_fixed_point,
+ /*Default=*/false) &&
+ Opts.FixedPoint;
+
// 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();
+ llvm::Triple T(TargetOpts.Triple);
+ if (T.isWindowsMSVCEnvironment())
+ Diags.Report(diag::err_fe_invalid_exception_model)
+ << Opt.getName() << T.str();
+
Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions);
Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions);
Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions);
@@ -2194,7 +2370,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti);
Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
- && Opts.OpenCLVersion >= 200);
+ && Opts.OpenCLVersion == 200);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts);
@@ -2219,6 +2395,7 @@ 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.Char8 = Args.hasArg(OPT_fchar8__t);
if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) {
Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue())
.Case("char", 1)
@@ -2297,10 +2474,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id);
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
- Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name_EQ);
+ Opts.ModuleName = Args.getLastArgValue(OPT_fmodule_name_EQ);
+ Opts.CurrentModule = Opts.ModuleName;
Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature);
- std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
+ llvm::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type);
Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns);
// Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns
@@ -2408,20 +2586,23 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Check if -fopenmp is specified.
Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0;
// Check if -fopenmp-simd is specified.
- Opts.OpenMPSimd = !Opts.OpenMP && Args.hasFlag(options::OPT_fopenmp_simd,
- options::OPT_fno_openmp_simd,
- /*Default=*/false);
+ bool IsSimdSpecified =
+ Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
+ /*Default=*/false);
+ Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
Opts.OpenMPUseTLS =
Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
Opts.OpenMPIsDevice =
Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
+ bool IsTargetSpecified =
+ Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);
if (Opts.OpenMP || Opts.OpenMPSimd) {
- if (int Version =
- getLastArgIntValue(Args, OPT_fopenmp_version_EQ,
- Opts.OpenMPSimd ? 45 : Opts.OpenMP, Diags))
+ if (int Version = getLastArgIntValue(
+ Args, OPT_fopenmp_version_EQ,
+ (IsSimdSpecified || IsTargetSpecified) ? 45 : Opts.OpenMP, Diags))
Opts.OpenMP = Version;
- else if (Opts.OpenMPSimd)
+ else if (IsSimdSpecified || IsTargetSpecified)
Opts.OpenMP = 45;
// Provide diagnostic when a given target is not expected to be an OpenMP
// device or host.
@@ -2432,7 +2613,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Add unsupported host targets here:
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
- Diags.Report(clang::diag::err_drv_omp_host_target_not_supported)
+ Diags.Report(diag::err_drv_omp_host_target_not_supported)
<< TargetOpts.Triple;
break;
}
@@ -2441,7 +2622,8 @@ 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.OpenMPHostCXXExceptions = Opts.Exceptions && Opts.CXXExceptions;
+ if ((Opts.OpenMPIsDevice && T.isNVPTX()) || Opts.OpenCLCPlusPlus) {
Opts.Exceptions = 0;
Opts.CXXExceptions = 0;
}
@@ -2460,7 +2642,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
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);
+ Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
else
Opts.OMPTargetTriples.push_back(TT);
}
@@ -2471,10 +2653,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
Opts.OMPHostIRFile = A->getValue();
if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
- Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
+ Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
<< Opts.OMPHostIRFile;
}
+ // set CUDA mode for OpenMP target NVPTX if specified in options
+ Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() &&
+ Args.hasArg(options::OPT_fopenmp_cuda_mode);
+
// Record whether the __DEPRECATED define was requested.
Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro,
OPT_fno_deprecated_macro,
@@ -2549,14 +2735,55 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Args.hasFlag(OPT_fxray_always_emit_customevents,
OPT_fnoxray_always_emit_customevents, false);
+ // -fxray-always-emit-typedevents
+ Opts.XRayAlwaysEmitTypedEvents =
+ Args.hasFlag(OPT_fxray_always_emit_typedevents,
+ OPT_fnoxray_always_emit_customevents, false);
+
// -fxray-{always,never}-instrument= filenames.
Opts.XRayAlwaysInstrumentFiles =
Args.getAllArgValues(OPT_fxray_always_instrument);
Opts.XRayNeverInstrumentFiles =
Args.getAllArgValues(OPT_fxray_never_instrument);
+ Opts.XRayAttrListFiles = Args.getAllArgValues(OPT_fxray_attr_list);
+
+ // -fforce-emit-vtables
+ Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables);
// -fallow-editor-placeholders
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
+
+ if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
+ Opts.setClangABICompat(LangOptions::ClangABI::Latest);
+
+ StringRef Ver = A->getValue();
+ std::pair<StringRef, StringRef> VerParts = Ver.split('.');
+ unsigned Major, Minor = 0;
+
+ // Check the version number is valid: either 3.x (0 <= x <= 9) or
+ // y or y.0 (4 <= y <= current version).
+ if (!VerParts.first.startswith("0") &&
+ !VerParts.first.getAsInteger(10, Major) &&
+ 3 <= Major && Major <= CLANG_VERSION_MAJOR &&
+ (Major == 3 ? VerParts.second.size() == 1 &&
+ !VerParts.second.getAsInteger(10, Minor)
+ : VerParts.first.size() == Ver.size() ||
+ VerParts.second == "0")) {
+ // Got a valid version number.
+ if (Major == 3 && Minor <= 8)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);
+ else if (Major <= 4)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
+ else if (Major <= 6)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
+ } else if (Ver != "latest") {
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ }
+ }
+
+ Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers);
+ Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj);
}
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
@@ -2585,9 +2812,11 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::RewriteObjC:
case frontend::RewriteTest:
case frontend::RunAnalysis:
+ case frontend::TemplightDump:
case frontend::MigrateSource:
return false;
+ case frontend::DumpCompilerOptions:
case frontend::DumpRawTokens:
case frontend::DumpTokens:
case frontend::InitOnly:
@@ -2601,12 +2830,11 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
- FileManager &FileMgr,
DiagnosticsEngine &Diags,
frontend::ActionKind Action) {
- using namespace options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
+ Opts.PCHThroughHeader = Args.getLastArgValue(OPT_pch_through_header_EQ);
if (const Arg *A = Args.getLastArg(OPT_token_cache))
Opts.TokenCache = A->getValue();
else
@@ -2617,7 +2845,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors);
Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
- for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
+ for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
@@ -2636,8 +2864,19 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
}
}
+ // Add the __CET__ macro if a CFProtection option is set.
+ if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
+ StringRef Name = A->getValue();
+ if (Name == "branch")
+ Opts.addMacroDef("__CET__=1");
+ else if (Name == "return")
+ Opts.addMacroDef("__CET__=2");
+ else if (Name == "full")
+ Opts.addMacroDef("__CET__=3");
+ }
+
// Add macros from the command line.
- for (const Arg *A : Args.filtered(OPT_D, OPT_U)) {
+ for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
if (A->getOption().matches(OPT_D))
Opts.addMacroDef(A->getValue());
else
@@ -2647,13 +2886,13 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
// Add the ordered list of -includes.
- for (const Arg *A : Args.filtered(OPT_include))
+ for (const auto *A : Args.filtered(OPT_include))
Opts.Includes.emplace_back(A->getValue());
- for (const Arg *A : Args.filtered(OPT_chain_include))
+ for (const auto *A : Args.filtered(OPT_chain_include))
Opts.ChainedIncludes.emplace_back(A->getValue());
- for (const Arg *A : Args.filtered(OPT_remap_file)) {
+ for (const auto *A : Args.filtered(OPT_remap_file)) {
std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
if (Split.second.empty()) {
@@ -2687,8 +2926,6 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
ArgList &Args,
frontend::ActionKind Action) {
- using namespace options;
-
if (isStrictlyPreprocessorAction(Action))
Opts.ShowCPP = !Args.hasArg(OPT_dM);
else
@@ -2706,7 +2943,6 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- using namespace options;
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
if (Arg *A = Args.getLastArg(OPT_meabi)) {
StringRef Value = A->getValue();
@@ -2726,11 +2962,15 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
Opts.FPMath = Args.getLastArgValue(OPT_mfpmath);
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.Triple = Args.getLastArgValue(OPT_triple);
// Use the default target triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getDefaultTargetTriple();
+ Opts.Triple = llvm::Triple::normalize(Opts.Triple);
Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ);
+ Opts.ForceEnableInt128 = Args.hasArg(OPT_fforce_enable_int128);
+ Opts.NVPTXUseShortPointers = Args.hasFlag(
+ options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false);
}
bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
@@ -2756,8 +2996,14 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
}
// Issue errors on unknown arguments.
- for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
- Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
+ for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
+ auto ArgString = A->getAsString(Args);
+ std::string Nearest;
+ if (Opts->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
+ Diags.Report(diag::err_drv_unknown_argument) << ArgString;
+ else
+ Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
+ << ArgString << Nearest;
Success = false;
}
@@ -2774,7 +3020,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
LangOpts.IsHeaderFile);
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
- Res.getTargetOpts());
+ Res.getTargetOpts(), Res.getFrontendOpts());
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args,
Res.getFileSystemOpts().WorkingDir);
if (DashX.getFormat() == InputKind::Precompiled ||
@@ -2799,6 +3045,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
LangOpts.ObjCExceptions = 1;
}
+ LangOpts.FunctionAlignment =
+ getLastArgIntValue(Args, OPT_function_alignment, 0, Diags);
+
if (LangOpts.CUDA) {
// During CUDA device-side compilation, the aux triple is the
// triple used for host compilation.
@@ -2817,12 +3066,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
!LangOpts.Sanitize.has(SanitizerKind::Address) &&
!LangOpts.Sanitize.has(SanitizerKind::Memory);
- // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of
- // PCH file and find the original header name. Remove the need to do that in
- // ParsePreprocessorArgs and remove the FileManager
- // parameters from the function and the "FileManager.h" #include.
- FileManager FileMgr(Res.getFileSystemOpts());
- ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags,
+ ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
Res.getFrontendOpts().ProgramAction);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
Res.getFrontendOpts().ProgramAction);
@@ -2870,29 +3114,26 @@ std::string CompilerInvocation::getModuleHash() const {
// Extend the signature with the target options.
code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
TargetOpts->ABI);
- for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i)
- code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]);
+ for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten)
+ code = hash_combine(code, FeatureAsWritten);
// Extend the signature with preprocessor options.
const PreprocessorOptions &ppOpts = getPreprocessorOpts();
const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
- for (std::vector<std::pair<std::string, bool/*isUndef*/>>::const_iterator
- I = getPreprocessorOpts().Macros.begin(),
- IEnd = getPreprocessorOpts().Macros.end();
- I != IEnd; ++I) {
+ for (const auto &I : getPreprocessorOpts().Macros) {
// If we're supposed to ignore this macro for the purposes of modules,
// don't put it into the hash.
if (!hsOpts.ModulesIgnoreMacros.empty()) {
// Check whether we're ignoring this macro.
- StringRef MacroDef = I->first;
+ StringRef MacroDef = I.first;
if (hsOpts.ModulesIgnoreMacros.count(
llvm::CachedHashString(MacroDef.split('=').first)))
continue;
}
- code = hash_combine(code, I->first, I->second);
+ code = hash_combine(code, I.first, I.second);
}
// Extend the signature with the sysroot and other header search options.
@@ -2925,8 +3166,6 @@ std::string CompilerInvocation::getModuleHash() const {
return llvm::APInt(64, code).toString(36, /*Signed=*/false);
}
-namespace clang {
-
template<typename IntTy>
static IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id,
IntTy Default,
@@ -2942,6 +3181,7 @@ static IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id,
return Res;
}
+namespace clang {
// Declared in clang/Frontend/Utils.h.
int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default,
@@ -2986,22 +3226,22 @@ createVFSFromCompilerInvocation(const CompilerInvocation &CI,
IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
new vfs::OverlayFileSystem(BaseFS));
// earlier vfs files are on the bottom
- for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
+ for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
BaseFS->getBufferForFile(File);
if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
- return IntrusiveRefCntPtr<vfs::FileSystem>();
+ continue;
}
IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
std::move(Buffer.get()), /*DiagHandler*/ nullptr, File);
- if (!FS.get()) {
+ if (FS)
+ Overlay->pushOverlay(FS);
+ else
Diags.Report(diag::err_invalid_vfs_overlay) << File;
- return IntrusiveRefCntPtr<vfs::FileSystem>();
- }
- Overlay->pushOverlay(FS);
}
return Overlay;
}
-} // end namespace clang
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
index 561eb9c4a316..e6e07190e1ff 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
@@ -63,7 +63,8 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override {
if (!File)
DepCollector.maybeAddDependency(FileName, /*FromModule*/false,
/*IsSystem*/false, /*IsModuleFile*/false,
@@ -162,6 +163,7 @@ class DFGImpl : public PPCallbacks {
bool SeenMissingHeader;
bool IncludeModuleFiles;
DependencyOutputFormat OutputFormat;
+ unsigned InputFileIndex;
private:
bool FileMatchesDepCriteria(const char *Filename,
@@ -176,26 +178,33 @@ public:
AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
SeenMissingHeader(false),
IncludeModuleFiles(Opts.IncludeModuleFiles),
- OutputFormat(Opts.OutputFormat) {
+ OutputFormat(Opts.OutputFormat),
+ InputFileIndex(0) {
for (const auto &ExtraDep : Opts.ExtraDeps) {
- AddFilename(ExtraDep);
+ if (AddFilename(ExtraDep))
+ ++InputFileIndex;
}
}
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) override;
+
+ void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) override;
+
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override;
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
void EndOfMainFile() override {
OutputDependencyFile();
}
- void AddFilename(StringRef Filename);
+ bool AddFilename(StringRef Filename);
bool includeSystemHeaders() const { return IncludeSystemHeaders; }
bool includeModuleFiles() const { return IncludeModuleFiles; }
};
@@ -291,6 +300,16 @@ void DFGImpl::FileChanged(SourceLocation Loc,
AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
}
+void DFGImpl::FileSkipped(const FileEntry &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+ StringRef Filename = SkippedFile.getName();
+ if (!FileMatchesDepCriteria(Filename.data(), FileType))
+ return;
+
+ AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
+}
+
void DFGImpl::InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
@@ -299,7 +318,8 @@ void DFGImpl::InclusionDirective(SourceLocation HashLoc,
const FileEntry *File,
StringRef SearchPath,
StringRef RelativePath,
- const Module *Imported) {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
if (!File) {
if (AddMissingHeaderDeps)
AddFilename(FileName);
@@ -308,9 +328,12 @@ void DFGImpl::InclusionDirective(SourceLocation HashLoc,
}
}
-void DFGImpl::AddFilename(StringRef Filename) {
- if (FilesSet.insert(Filename).second)
+bool DFGImpl::AddFilename(StringRef Filename) {
+ if (FilesSet.insert(Filename).second) {
Files.push_back(Filename);
+ return true;
+ }
+ return false;
}
/// Print the filename, with escaping or quoting that accommodates the three
@@ -446,8 +469,10 @@ void DFGImpl::OutputDependencyFile() {
// Create phony targets if requested.
if (PhonyTarget && !Files.empty()) {
- // Skip the first entry, this is always the input file itself.
- for (auto I = Files.begin() + 1, E = Files.end(); I != E; ++I) {
+ unsigned Index = 0;
+ for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {
+ if (Index++ == InputFileIndex)
+ continue;
OS << '\n';
PrintFilename(OS, *I, OutputFormat);
OS << ":\n";
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DependencyGraph.cpp b/contrib/llvm/tools/clang/lib/Frontend/DependencyGraph.cpp
index 67a977e38be2..c6c9ac2ea2fa 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DependencyGraph.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DependencyGraph.cpp
@@ -33,9 +33,9 @@ class DependencyGraphCallback : public PPCallbacks {
llvm::SetVector<const FileEntry *> AllFiles;
typedef llvm::DenseMap<const FileEntry *,
SmallVector<const FileEntry *, 2> > DependencyMap;
-
+
DependencyMap Dependencies;
-
+
private:
raw_ostream &writeNodeReference(raw_ostream &OS,
const FileEntry *Node);
@@ -50,12 +50,13 @@ public:
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override;
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
void EndOfMainFile() override {
OutputGraphFile();
}
-
+
};
}
@@ -65,18 +66,20 @@ void clang::AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
SysRoot));
}
-void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc,
- const Token &IncludeTok,
- StringRef FileName,
- bool IsAngled,
- CharSourceRange FilenameRange,
- const FileEntry *File,
- StringRef SearchPath,
- StringRef RelativePath,
- const Module *Imported) {
+void DependencyGraphCallback::InclusionDirective(
+ SourceLocation HashLoc,
+ const Token &IncludeTok,
+ StringRef FileName,
+ bool IsAngled,
+ CharSourceRange FilenameRange,
+ const FileEntry *File,
+ StringRef SearchPath,
+ StringRef RelativePath,
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
if (!File)
return;
-
+
SourceManager &SM = PP->getSourceManager();
const FileEntry *FromFile
= SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(HashLoc)));
@@ -84,7 +87,7 @@ void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc,
return;
Dependencies[FromFile].push_back(File);
-
+
AllFiles.insert(File);
AllFiles.insert(FromFile);
}
@@ -106,7 +109,7 @@ void DependencyGraphCallback::OutputGraphFile() {
}
OS << "digraph \"dependencies\" {\n";
-
+
// Write the nodes
for (unsigned I = 0, N = AllFiles.size(); I != N; ++I) {
// Write the node itself.
@@ -116,15 +119,15 @@ void DependencyGraphCallback::OutputGraphFile() {
StringRef FileName = AllFiles[I]->getName();
if (FileName.startswith(SysRoot))
FileName = FileName.substr(SysRoot.size());
-
+
OS << DOT::EscapeString(FileName)
<< "\"];\n";
}
// Write the edges
- for (DependencyMap::iterator F = Dependencies.begin(),
+ for (DependencyMap::iterator F = Dependencies.begin(),
FEnd = Dependencies.end();
- F != FEnd; ++F) {
+ F != FEnd; ++F) {
for (unsigned I = 0, N = F->second.size(); I != N; ++I) {
OS.indent(2);
writeNodeReference(OS, F->first);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp b/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp
index e3263843e29b..757ceec7ec9d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp
@@ -1,4 +1,4 @@
-//===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===//
+//===- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,24 +8,34 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/DiagnosticRenderer.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <utility>
+
using namespace clang;
DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
DiagnosticOptions *DiagOpts)
- : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
+ : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
-DiagnosticRenderer::~DiagnosticRenderer() {}
+DiagnosticRenderer::~DiagnosticRenderer() = default;
namespace {
@@ -34,24 +44,24 @@ class FixitReceiver : public edit::EditsReceiver {
public:
FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits)
- : MergedFixits(MergedFixits) { }
+ : MergedFixits(MergedFixits) {}
+
void insert(SourceLocation loc, StringRef text) override {
MergedFixits.push_back(FixItHint::CreateInsertion(loc, text));
}
+
void replace(CharSourceRange range, StringRef text) override {
MergedFixits.push_back(FixItHint::CreateReplacement(range, text));
}
};
-}
+} // namespace
static void mergeFixits(ArrayRef<FixItHint> FixItHints,
const SourceManager &SM, const LangOptions &LangOpts,
SmallVectorImpl<FixItHint> &MergedFixits) {
edit::Commit commit(SM, LangOpts);
- for (ArrayRef<FixItHint>::const_iterator
- I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) {
- const FixItHint &Hint = *I;
+ for (const auto &Hint : FixItHints)
if (Hint.CodeToInsert.empty()) {
if (Hint.InsertFromRange.isValid())
commit.insertFromRange(Hint.RemoveRange.getBegin(),
@@ -67,7 +77,6 @@ static void mergeFixits(ArrayRef<FixItHint> FixItHints,
commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
/*afterToken=*/false, Hint.BeforePreviousInsertions);
}
- }
edit::EditedSource Editor(SM, LangOpts);
if (Editor.commit(commit)) {
@@ -100,11 +109,9 @@ void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc,
FixItHints = MergedFixits;
}
- for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(),
- E = FixItHints.end();
- I != E; ++I)
- if (I->RemoveRange.isValid())
- MutableRanges.push_back(I->RemoveRange);
+ for (const auto &Hint : FixItHints)
+ if (Hint.RemoveRange.isValid())
+ MutableRanges.push_back(Hint.RemoveRange);
FullSourceLoc UnexpandedLoc = Loc;
@@ -134,7 +141,6 @@ void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc,
endDiagnostic(D, Level);
}
-
void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
Diag.getRanges(), Diag.getFixIts(),
@@ -146,7 +152,7 @@ void DiagnosticRenderer::emitBasicNote(StringRef Message) {
Message, None, DiagOrStoredDiag());
}
-/// \brief Prints an include stack when appropriate for a particular
+/// Prints an include stack when appropriate for a particular
/// diagnostic level and location.
///
/// This routine handles all the logic of suppressing particular include
@@ -166,9 +172,9 @@ void DiagnosticRenderer::emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
// Skip redundant include stacks altogether.
if (LastIncludeLoc == IncludeLoc)
return;
-
+
LastIncludeLoc = IncludeLoc;
-
+
if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
return;
@@ -180,7 +186,7 @@ void DiagnosticRenderer::emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
}
}
-/// \brief Helper to recursivly walk up the include stack and print each layer
+/// Helper to recursively walk up the include stack and print each layer
/// on the way back down.
void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) {
if (Loc.isInvalid()) {
@@ -193,7 +199,7 @@ void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) {
return;
// If this source location was imported from a module, print the module
- // import stack rather than the
+ // import stack rather than the
// FIXME: We want submodule granularity here.
std::pair<FullSourceLoc, StringRef> Imported = Loc.getModuleImportLoc();
if (!Imported.second.empty()) {
@@ -210,7 +216,7 @@ void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) {
emitIncludeLocation(Loc, PLoc);
}
-/// \brief Emit the module import stack associated with the current location.
+/// Emit the module import stack associated with the current location.
void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) {
if (Loc.isInvalid()) {
emitModuleBuildStack(Loc.getManager());
@@ -221,7 +227,7 @@ void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) {
emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
}
-/// \brief Helper to recursivly walk up the import stack and print each layer
+/// Helper to recursively walk up the import stack and print each layer
/// on the way back down.
void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc,
StringRef ModuleName) {
@@ -239,14 +245,14 @@ void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc,
emitImportLocation(Loc, PLoc, ModuleName);
}
-/// \brief Emit the module build stack, for cases where a module is (re-)built
+/// Emit the module build stack, for cases where a module is (re-)built
/// on demand.
void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
ModuleBuildStack Stack = SM.getModuleBuildStack();
- for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
- emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc(
- DiagOpts->ShowPresumedLoc),
- Stack[I].first);
+ for (const auto &I : Stack) {
+ emitBuildingModuleLocation(I.second, I.second.getPresumedLoc(
+ DiagOpts->ShowPresumedLoc),
+ I.first);
}
}
@@ -256,41 +262,54 @@ static SourceLocation
retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID,
FileID CaretFileID,
const SmallVectorImpl<FileID> &CommonArgExpansions,
- bool IsBegin, const SourceManager *SM) {
+ bool IsBegin, const SourceManager *SM,
+ bool &IsTokenRange) {
assert(SM->getFileID(Loc) == MacroFileID);
if (MacroFileID == CaretFileID)
return Loc;
if (!Loc.isMacroID())
- return SourceLocation();
+ return {};
- SourceLocation MacroLocation, MacroArgLocation;
+ CharSourceRange MacroRange, MacroArgRange;
if (SM->isMacroArgExpansion(Loc)) {
// Only look at the immediate spelling location of this macro argument if
// the other location in the source range is also present in that expansion.
if (std::binary_search(CommonArgExpansions.begin(),
CommonArgExpansions.end(), MacroFileID))
- MacroLocation = SM->getImmediateSpellingLoc(Loc);
- MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
- : SM->getImmediateExpansionRange(Loc).second;
+ MacroRange =
+ CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange);
+ MacroArgRange = SM->getImmediateExpansionRange(Loc);
} else {
- MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
- : SM->getImmediateExpansionRange(Loc).second;
- MacroArgLocation = SM->getImmediateSpellingLoc(Loc);
+ MacroRange = SM->getImmediateExpansionRange(Loc);
+ MacroArgRange =
+ CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange);
}
+ SourceLocation MacroLocation =
+ IsBegin ? MacroRange.getBegin() : MacroRange.getEnd();
if (MacroLocation.isValid()) {
MacroFileID = SM->getFileID(MacroLocation);
+ bool TokenRange = IsBegin ? IsTokenRange : MacroRange.isTokenRange();
MacroLocation =
retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
- CommonArgExpansions, IsBegin, SM);
- if (MacroLocation.isValid())
+ CommonArgExpansions, IsBegin, SM, TokenRange);
+ if (MacroLocation.isValid()) {
+ IsTokenRange = TokenRange;
return MacroLocation;
+ }
}
+ // If we moved the end of the range to an expansion location, we now have
+ // a range of the same kind as the expansion range.
+ if (!IsBegin)
+ IsTokenRange = MacroArgRange.isTokenRange();
+
+ SourceLocation MacroArgLocation =
+ IsBegin ? MacroArgRange.getBegin() : MacroArgRange.getEnd();
MacroFileID = SM->getFileID(MacroArgLocation);
return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
- CommonArgExpansions, IsBegin, SM);
+ CommonArgExpansions, IsBegin, SM, IsTokenRange);
}
/// Walk up the chain of macro expansions and collect the FileIDs identifying the
@@ -304,7 +323,7 @@ static void getMacroArgExpansionFileIDs(SourceLocation Loc,
Loc = SM->getImmediateSpellingLoc(Loc);
} else {
auto ExpRange = SM->getImmediateExpansionRange(Loc);
- Loc = IsBegin ? ExpRange.first : ExpRange.second;
+ Loc = IsBegin ? ExpRange.getBegin() : ExpRange.getEnd();
}
}
}
@@ -318,8 +337,8 @@ static void computeCommonMacroArgExpansionFileIDs(
SmallVector<FileID, 4> EndArgExpansions;
getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
- std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
- std::sort(EndArgExpansions.begin(), EndArgExpansions.end());
+ llvm::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
+ llvm::sort(EndArgExpansions.begin(), EndArgExpansions.end());
std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
EndArgExpansions.begin(), EndArgExpansions.end(),
std::back_inserter(CommonArgExpansions));
@@ -342,11 +361,12 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM = &CaretLoc.getManager();
- for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
- if (I->isInvalid()) continue;
+ for (const auto &Range : Ranges) {
+ if (Range.isInvalid())
+ continue;
- SourceLocation Begin = I->getBegin(), End = I->getEnd();
- bool IsTokenRange = I->isTokenRange();
+ SourceLocation Begin = Range.getBegin(), End = Range.getEnd();
+ bool IsTokenRange = Range.isTokenRange();
FileID BeginFileID = SM->getFileID(Begin);
FileID EndFileID = SM->getFileID(End);
@@ -357,14 +377,16 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
while (Begin.isMacroID() && BeginFileID != EndFileID) {
BeginLocsMap[BeginFileID] = Begin;
- Begin = SM->getImmediateExpansionRange(Begin).first;
+ Begin = SM->getImmediateExpansionRange(Begin).getBegin();
BeginFileID = SM->getFileID(Begin);
}
// Then, crawl the expansion chain for the end of the range.
if (BeginFileID != EndFileID) {
while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
- End = SM->getImmediateExpansionRange(End).second;
+ auto Exp = SM->getImmediateExpansionRange(End);
+ IsTokenRange = Exp.isTokenRange();
+ End = Exp.getEnd();
EndFileID = SM->getFileID(End);
}
if (End.isMacroID()) {
@@ -377,9 +399,11 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
SmallVector<FileID, 4> CommonArgExpansions;
computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
- CommonArgExpansions, /*IsBegin=*/true, SM);
+ CommonArgExpansions, /*IsBegin=*/true, SM,
+ IsTokenRange);
End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
- CommonArgExpansions, /*IsBegin=*/false, SM);
+ CommonArgExpansions, /*IsBegin=*/false, SM,
+ IsTokenRange);
if (Begin.isInvalid() || End.isInvalid()) continue;
// Return the spelling location of the beginning and end of the range.
@@ -400,7 +424,7 @@ void DiagnosticRenderer::emitCaret(FullSourceLoc Loc,
emitCodeContext(Loc, Level, SpellingRanges, Hints);
}
-/// \brief A helper function for emitMacroExpansion to print the
+/// A helper function for emitMacroExpansion to print the
/// macro expansion message
void DiagnosticRenderer::emitSingleMacroExpansion(
FullSourceLoc Loc, DiagnosticsEngine::Level Level,
@@ -441,7 +465,7 @@ static bool checkLocForMacroArgExpansion(SourceLocation Loc,
}
/// Check if all the locations in the range have the same macro argument
-/// expansion, and that that expansion starts with ArgumentLoc.
+/// expansion, and that the expansion starts with ArgumentLoc.
static bool checkRangeForMacroArgExpansion(CharSourceRange Range,
const SourceManager &SM,
SourceLocation ArgumentLoc) {
@@ -466,8 +490,9 @@ static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc,
/// Count all valid ranges.
unsigned ValidCount = 0;
- for (auto I : Ranges)
- if (I.isValid()) ValidCount++;
+ for (const auto &Range : Ranges)
+ if (Range.isValid())
+ ValidCount++;
if (ValidCount > SpellingRanges.size())
return false;
@@ -480,15 +505,14 @@ static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc,
if (!Loc.isMacroArgExpansion(&ArgumentLoc))
return false;
- for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
- if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc))
+ for (const auto &Range : SpellingRanges)
+ if (!checkRangeForMacroArgExpansion(Range, Loc.getManager(), ArgumentLoc))
return false;
- }
return true;
}
-/// \brief Recursively emit notes for each macro expansion and caret
+/// Recursively emit notes for each macro expansion and caret
/// diagnostics where appropriate.
///
/// Walks up the macro expansion stack printing expansion notes, the code
@@ -504,29 +528,31 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Hints) {
assert(Loc.isValid() && "must have a valid source location here");
+ const SourceManager &SM = Loc.getManager();
+ SourceLocation L = Loc;
// Produce a stack of macro backtraces.
- SmallVector<FullSourceLoc, 8> LocationStack;
+ SmallVector<SourceLocation, 8> LocationStack;
unsigned IgnoredEnd = 0;
- while (Loc.isMacroID()) {
+ while (L.isMacroID()) {
// If this is the expansion of a macro argument, point the caret at the
// use of the argument in the definition of the macro, not the expansion.
- if (Loc.isMacroArgExpansion())
- LocationStack.push_back(Loc.getImmediateExpansionRange().first);
+ if (SM.isMacroArgExpansion(L))
+ LocationStack.push_back(SM.getImmediateExpansionRange(L).getBegin());
else
- LocationStack.push_back(Loc);
+ LocationStack.push_back(L);
- if (checkRangesForMacroArgExpansion(Loc, Ranges))
+ if (checkRangesForMacroArgExpansion(FullSourceLoc(L, SM), Ranges))
IgnoredEnd = LocationStack.size();
- Loc = Loc.getImmediateMacroCallerLoc();
+ L = SM.getImmediateMacroCallerLoc(L);
// Once the location no longer points into a macro, try stepping through
// the last found location. This sometimes produces additional useful
// backtraces.
- if (Loc.isFileID())
- Loc = LocationStack.back().getImmediateMacroCallerLoc();
- assert(Loc.isValid() && "must have a valid source location here");
+ if (L.isFileID())
+ L = SM.getImmediateMacroCallerLoc(LocationStack.back());
+ assert(L.isValid() && "must have a valid source location here");
}
LocationStack.erase(LocationStack.begin(),
@@ -537,7 +563,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
if (MacroDepth <= MacroLimit || MacroLimit == 0) {
for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
I != E; ++I)
- emitSingleMacroExpansion(*I, Level, Ranges);
+ emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
return;
}
@@ -547,7 +573,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
for (auto I = LocationStack.rbegin(),
E = LocationStack.rbegin() + MacroStartMessages;
I != E; ++I)
- emitSingleMacroExpansion(*I, Level, Ranges);
+ emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
@@ -559,10 +585,10 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
for (auto I = LocationStack.rend() - MacroEndMessages,
E = LocationStack.rend();
I != E; ++I)
- emitSingleMacroExpansion(*I, Level, Ranges);
+ emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
}
-DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
+DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default;
void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc,
PresumedLoc PLoc) {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
index 12226b231417..74550c410396 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
@@ -79,7 +79,7 @@ public:
}
};
-/// \brief Dumps deserialized declarations.
+/// Dumps deserialized declarations.
class DeserializedDeclsDumper : public DelegatingDeserializationListener {
public:
explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,
@@ -88,15 +88,17 @@ public:
void DeclRead(serialization::DeclID ID, const Decl *D) override {
llvm::outs() << "PCH DECL: " << D->getDeclKindName();
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- llvm::outs() << " - " << *ND;
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ llvm::outs() << " - ";
+ ND->printQualifiedName(llvm::outs());
+ }
llvm::outs() << "\n";
DelegatingDeserializationListener::DeclRead(ID, D);
}
};
-/// \brief Checks deserialized declarations and emits error if a name
+/// Checks deserialized declarations and emits error if a name
/// matches one given in command-line using -error-on-deserialized-decl.
class DeserializedDeclsChecker : public DelegatingDeserializationListener {
ASTContext &Ctx;
@@ -153,6 +155,10 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end())
return Consumer;
+ // If this is a code completion run, avoid invoking the plugin consumers
+ if (CI.hasCodeCompletionConsumer())
+ return Consumer;
+
// Collect the list of plugins that go before the main action (in Consumers)
// or after it (in AfterConsumers)
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
@@ -282,7 +288,7 @@ static void addHeaderInclude(StringRef HeaderName,
Includes += "}\n";
}
-/// \brief Collect the set of header includes needed to construct the given
+/// Collect the set of header includes needed to construct the given
/// module and update the TopHeaders file set of the module.
///
/// \param Module The module we're collecting includes from.
@@ -339,7 +345,7 @@ static std::error_code collectModuleHeaderIncludes(
vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
Dir != End && !EC; Dir.increment(EC)) {
- // Check whether this entry has an extension typically associated with
+ // Check whether this entry has an extension typically associated with
// headers.
if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName()))
.Cases(".h", ".H", ".hh", ".hpp", true)
@@ -352,7 +358,7 @@ static std::error_code collectModuleHeaderIncludes(
if (!Header)
continue;
- // If this header is marked 'unavailable' in this module, don't include
+ // If this header is marked 'unavailable' in this module, don't include
// it.
if (ModMap.isHeaderUnavailableInModule(Header, Module))
continue;
@@ -425,7 +431,7 @@ static Module *prepareToBuildModule(CompilerInstance &CI,
CI.getDiagnostics().Report(diag::err_missing_module_name);
// FIXME: Eventually, we could consider asking whether there was just
- // a single module described in the module map, and use that as a
+ // a single module described in the module map, and use that as a
// default. Then it would be fairly trivial to just "compile" a module
// map with a single module (the common case).
return nullptr;
@@ -760,6 +766,22 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!BeginSourceFileAction(CI))
goto failure;
+ // If we were asked to load any module map files, do so now.
+ for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {
+ if (auto *File = CI.getFileManager().getFile(Filename))
+ CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile(
+ File, /*IsSystem*/false);
+ else
+ CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
+ }
+
+ // Add a module declaration scope so that modules from -fmodule-map-file
+ // arguments may shadow modules found implicitly in search paths.
+ CI.getPreprocessor()
+ .getHeaderSearchInfo()
+ .getModuleMap()
+ .finishModuleDeclarationScope();
+
// Create the AST context and consumer unless this is a preprocessor only
// action.
if (!usesPreprocessorOnly()) {
@@ -849,15 +871,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
"doesn't support modules");
}
- // If we were asked to load any module map files, do so now.
- for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {
- if (auto *File = CI.getFileManager().getFile(Filename))
- CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile(
- File, /*IsSystem*/false);
- else
- CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
- }
-
// If we were asked to load any module files, do so now.
for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles)
if (!CI.loadModuleFile(ModuleFile))
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
index ffa5b410d2d8..8a8354c7d4c9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
@@ -18,17 +18,36 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/YAMLTraits.h"
#include <memory>
#include <system_error>
using namespace clang;
+namespace {
+CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {
+ return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer()
+ : nullptr;
+}
+
+void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
+ if (Action.hasCodeCompletionSupport() &&
+ !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+ CI.createCodeCompletionConsumer();
+
+ if (!CI.hasSema())
+ CI.createSema(Action.getTranslationUnitKind(),
+ GetCodeCompletionConsumer(CI));
+}
+} // namespace
+
//===----------------------------------------------------------------------===//
// Custom Actions
//===----------------------------------------------------------------------===//
@@ -55,7 +74,8 @@ ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<ASTConsumer>
ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter,
+ return CreateASTDumper(nullptr /*Dump to stdout.*/,
+ CI.getFrontendOpts().ASTDumpFilter,
CI.getFrontendOpts().ASTDumpDecls,
CI.getFrontendOpts().ASTDumpAll,
CI.getFrontendOpts().ASTDumpLookups);
@@ -92,14 +112,14 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
+ const auto &FrontendOpts = CI.getFrontendOpts();
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
CI.getPreprocessor(), OutputFile, Sysroot,
- Buffer, CI.getFrontendOpts().ModuleFileExtensions,
- /*AllowASTWithErrors*/CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
- /*IncludeTimestamps*/
- +CI.getFrontendOpts().IncludeTimestamps));
+ Buffer, FrontendOpts.ModuleFileExtensions,
+ CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
+ FrontendOpts.IncludeTimestamps));
Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
CI, InFile, OutputFile, std::move(OS), Buffer));
@@ -262,7 +282,141 @@ void VerifyPCHAction::ExecuteAction() {
}
namespace {
- /// \brief AST reader listener that dumps module information for a module
+struct TemplightEntry {
+ std::string Name;
+ std::string Kind;
+ std::string Event;
+ std::string DefinitionLocation;
+ std::string PointOfInstantiation;
+};
+} // namespace
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<TemplightEntry> {
+ static void mapping(IO &io, TemplightEntry &fields) {
+ io.mapRequired("name", fields.Name);
+ io.mapRequired("kind", fields.Kind);
+ io.mapRequired("event", fields.Event);
+ io.mapRequired("orig", fields.DefinitionLocation);
+ io.mapRequired("poi", fields.PointOfInstantiation);
+ }
+};
+} // namespace yaml
+} // namespace llvm
+
+namespace {
+class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
+ using CodeSynthesisContext = Sema::CodeSynthesisContext;
+
+public:
+ void initialize(const Sema &) override {}
+
+ void finalize(const Sema &) override {}
+
+ void atTemplateBegin(const Sema &TheSema,
+ const CodeSynthesisContext &Inst) override {
+ displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);
+ }
+
+ void atTemplateEnd(const Sema &TheSema,
+ const CodeSynthesisContext &Inst) override {
+ displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);
+ }
+
+private:
+ static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
+ switch (Kind) {
+ case CodeSynthesisContext::TemplateInstantiation:
+ return "TemplateInstantiation";
+ case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
+ return "DefaultTemplateArgumentInstantiation";
+ case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
+ return "DefaultFunctionArgumentInstantiation";
+ case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
+ return "ExplicitTemplateArgumentSubstitution";
+ case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
+ return "DeducedTemplateArgumentSubstitution";
+ case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
+ return "PriorTemplateArgumentSubstitution";
+ case CodeSynthesisContext::DefaultTemplateArgumentChecking:
+ return "DefaultTemplateArgumentChecking";
+ case CodeSynthesisContext::ExceptionSpecInstantiation:
+ return "ExceptionSpecInstantiation";
+ case CodeSynthesisContext::DeclaringSpecialMember:
+ return "DeclaringSpecialMember";
+ case CodeSynthesisContext::DefiningSynthesizedFunction:
+ return "DefiningSynthesizedFunction";
+ case CodeSynthesisContext::Memoization:
+ return "Memoization";
+ }
+ return "";
+ }
+
+ template <bool BeginInstantiation>
+ static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema,
+ const CodeSynthesisContext &Inst) {
+ std::string YAML;
+ {
+ llvm::raw_string_ostream OS(YAML);
+ llvm::yaml::Output YO(OS);
+ TemplightEntry Entry =
+ getTemplightEntry<BeginInstantiation>(TheSema, Inst);
+ llvm::yaml::EmptyContext Context;
+ llvm::yaml::yamlize(YO, Entry, true, Context);
+ }
+ Out << "---" << YAML << "\n";
+ }
+
+ template <bool BeginInstantiation>
+ static TemplightEntry getTemplightEntry(const Sema &TheSema,
+ const CodeSynthesisContext &Inst) {
+ TemplightEntry Entry;
+ Entry.Kind = toString(Inst.Kind);
+ Entry.Event = BeginInstantiation ? "Begin" : "End";
+ if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) {
+ llvm::raw_string_ostream OS(Entry.Name);
+ NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
+ const PresumedLoc DefLoc =
+ TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());
+ if(!DefLoc.isInvalid())
+ Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +
+ std::to_string(DefLoc.getLine()) + ":" +
+ std::to_string(DefLoc.getColumn());
+ }
+ const PresumedLoc PoiLoc =
+ TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);
+ if (!PoiLoc.isInvalid()) {
+ Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +
+ std::to_string(PoiLoc.getLine()) + ":" +
+ std::to_string(PoiLoc.getColumn());
+ }
+ return Entry;
+ }
+};
+} // namespace
+
+std::unique_ptr<ASTConsumer>
+TemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
+}
+
+void TemplightDumpAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // This part is normally done by ASTFrontEndAction, but needs to happen
+ // before Templight observers can be created
+ // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+ // here so the source manager would be initialized.
+ EnsureSemaIsCreated(CI, *this);
+
+ CI.getSema().TemplateInstCallbacks.push_back(
+ llvm::make_unique<DefaultTemplateInstCallback>());
+ ASTFrontendAction::ExecuteAction();
+}
+
+namespace {
+ /// AST reader listener that dumps module information for a module
/// file.
class DumpModuleInfoListener : public ASTReaderListener {
llvm::raw_ostream &Out;
@@ -406,6 +560,45 @@ namespace {
Out << "\n";
}
+
+ /// Tells the \c ASTReaderListener that we want to receive the
+ /// input files of the AST file via \c visitInputFile.
+ bool needsInputFileVisitation() override { return true; }
+
+ /// Tells the \c ASTReaderListener that we want to receive the
+ /// input files of the AST file via \c visitInputFile.
+ bool needsSystemInputFileVisitation() override { return true; }
+
+ /// Indicates that the AST file contains particular input file.
+ ///
+ /// \returns true to continue receiving the next input file, false to stop.
+ bool visitInputFile(StringRef Filename, bool isSystem,
+ bool isOverridden, bool isExplicitModule) override {
+
+ Out.indent(2) << "Input file: " << Filename;
+
+ if (isSystem || isOverridden || isExplicitModule) {
+ Out << " [";
+ if (isSystem) {
+ Out << "System";
+ if (isOverridden || isExplicitModule)
+ Out << ", ";
+ }
+ if (isOverridden) {
+ Out << "Overridden";
+ if (isExplicitModule)
+ Out << ", ";
+ }
+ if (isExplicitModule)
+ Out << "ExplicitModule";
+
+ Out << "]";
+ }
+
+ Out << "\n";
+
+ return true;
+ }
#undef DUMP_BOOLEAN
};
}
@@ -516,13 +709,13 @@ void PrintPreprocessedAction::ExecuteAction() {
// the input format has inconsistent line endings.
//
// This should be a relatively fast operation since most files won't have
- // all of their source code on a single line. However, that is still a
+ // all of their source code on a single line. However, that is still a
// concern, so if we scan for too long, we'll just assume the file should
// be opened in binary mode.
bool BinaryMode = true;
bool InvalidFile = false;
const SourceManager& SM = CI.getSourceManager();
- const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
+ const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
&InvalidFile);
if (!InvalidFile) {
const char *cur = Buffer->getBufferStart();
@@ -530,7 +723,7 @@ void PrintPreprocessedAction::ExecuteAction() {
const char *next = (cur != end) ? cur + 1 : end;
// Limit ourselves to only scanning 256 characters into the source
- // file. This is mostly a sanity check in case the file has no
+ // file. This is mostly a sanity check in case the file has no
// newlines whatsoever.
if (end - cur > 256) end = cur + 256;
@@ -579,8 +772,9 @@ void PrintPreambleAction::ExecuteAction() {
case InputKind::ObjCXX:
case InputKind::OpenCL:
case InputKind::CUDA:
+ case InputKind::HIP:
break;
-
+
case InputKind::Unknown:
case InputKind::Asm:
case InputKind::LLVM_IR:
@@ -601,3 +795,51 @@ void PrintPreambleAction::ExecuteAction() {
llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
}
}
+
+void DumpCompilerOptionsAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ std::unique_ptr<raw_ostream> OSP =
+ CI.createDefaultOutputFile(false, getCurrentFile());
+ if (!OSP)
+ return;
+
+ raw_ostream &OS = *OSP;
+ const Preprocessor &PP = CI.getPreprocessor();
+ const LangOptions &LangOpts = PP.getLangOpts();
+
+ // FIXME: Rather than manually format the JSON (which is awkward due to
+ // needing to remove trailing commas), this should make use of a JSON library.
+ // FIXME: Instead of printing enums as an integral value and specifying the
+ // type as a separate field, use introspection to print the enumerator.
+
+ OS << "{\n";
+ OS << "\n\"features\" : [\n";
+ {
+ llvm::SmallString<128> Str;
+#define FEATURE(Name, Predicate) \
+ ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
+ .toVector(Str);
+#include "clang/Basic/Features.def"
+#undef FEATURE
+ // Remove the newline and comma from the last entry to ensure this remains
+ // valid JSON.
+ OS << Str.substr(0, Str.size() - 2);
+ }
+ OS << "\n],\n";
+
+ OS << "\n\"extensions\" : [\n";
+ {
+ llvm::SmallString<128> Str;
+#define EXTENSION(Name, Predicate) \
+ ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
+ .toVector(Str);
+#include "clang/Basic/Features.def"
+#undef EXTENSION
+ // Remove the newline and comma from the last entry to ensure this remains
+ // valid JSON.
+ OS << Str.substr(0, Str.size() - 2);
+ }
+ OS << "\n]\n";
+
+ OS << "}";
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
index dca434588fb1..0744d447e816 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
@@ -1,4 +1,4 @@
-//===--- FrontendOptions.cpp ----------------------------------------------===//
+//===- FrontendOptions.cpp ------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,6 +9,7 @@
#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringSwitch.h"
+
using namespace clang;
InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendTiming.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendTiming.cpp
new file mode 100644
index 000000000000..9ea7347e7797
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendTiming.cpp
@@ -0,0 +1,20 @@
+//===- FronendTiming.cpp - Implements Frontend timing utils --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file keps implementation of frontend timing utils.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+
+namespace clang {
+
+bool FrontendTimesIsEnabled = false;
+
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
index 5bff4ecd0b46..9dc107c9d546 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
@@ -80,9 +80,23 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP,
const DependencyOutputOptions &DepOpts,
bool ShowAllHeaders, StringRef OutputPath,
bool ShowDepth, bool MSStyle) {
- raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs();
+ raw_ostream *OutputFile = &llvm::errs();
bool OwnsOutputFile = false;
+ // Choose output stream, when printing in cl.exe /showIncludes style.
+ if (MSStyle) {
+ switch (DepOpts.ShowIncludesDest) {
+ default:
+ llvm_unreachable("Invalid destination for /showIncludes output!");
+ case ShowIncludesDestination::Stderr:
+ OutputFile = &llvm::errs();
+ break;
+ case ShowIncludesDestination::Stdout:
+ OutputFile = &llvm::outs();
+ break;
+ }
+ }
+
// Open the output file, if used.
if (!OutputPath.empty()) {
std::error_code EC;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
index 8c6faced76ac..8a70404629d3 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -14,6 +14,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Config/config.h" // C_INCLUDE_DIRS
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearch.h"
@@ -55,11 +56,13 @@ public:
/// AddPath - Add the specified path to the specified group list, prefixing
/// the sysroot if used.
- void AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework);
+ /// Returns true if the path exists, false if it was ignored.
+ bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework);
/// AddUnmappedPath - Add the specified path to the specified group list,
/// without performing any sysroot remapping.
- void AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
+ /// Returns true if the path exists, false if it was ignored.
+ bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
bool isFramework);
/// AddSystemHeaderPrefix - Add the specified prefix to the system header
@@ -70,10 +73,9 @@ public:
/// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
/// libstdc++.
- void AddGnuCPlusPlusIncludePaths(StringRef Base,
- StringRef ArchDir,
- StringRef Dir32,
- StringRef Dir64,
+ /// Returns true if the \p Base path was found, false if it does not exist.
+ bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir,
+ StringRef Dir32, StringRef Dir64,
const llvm::Triple &triple);
/// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW
@@ -88,7 +90,8 @@ public:
// AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
// compiling c++.
- void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple,
+ void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts,
+ const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts);
/// AddDefaultSystemIncludePaths - Adds the default system include paths so
@@ -105,14 +108,14 @@ public:
} // end anonymous namespace.
static bool CanPrefixSysroot(StringRef Path) {
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
#else
return llvm::sys::path::is_absolute(Path);
#endif
}
-void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
+bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
bool isFramework) {
// Add the path with sysroot prepended, if desired and this is a system header
// group.
@@ -120,15 +123,14 @@ void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
SmallString<256> MappedPathStorage;
StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
if (CanPrefixSysroot(MappedPathStr)) {
- AddUnmappedPath(IncludeSysroot + Path, Group, isFramework);
- return;
+ return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework);
}
}
- AddUnmappedPath(Path, Group, isFramework);
+ return AddUnmappedPath(Path, Group, isFramework);
}
-void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
+bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
bool isFramework) {
assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
@@ -150,7 +152,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
IncludePath.push_back(
std::make_pair(Group, DirectoryLookup(DE, Type, isFramework)));
- return;
+ return true;
}
// Check to see if this is an apple-style headermap (which are not allowed to
@@ -162,7 +164,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
IncludePath.push_back(
std::make_pair(Group,
DirectoryLookup(HM, Type, Group == IndexHeaderMap)));
- return;
+ return true;
}
}
}
@@ -170,15 +172,16 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
if (Verbose)
llvm::errs() << "ignoring nonexistent directory \""
<< MappedPathStr << "\"\n";
+ return false;
}
-void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
+bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
StringRef ArchDir,
StringRef Dir32,
StringRef Dir64,
const llvm::Triple &triple) {
// Add the base dir
- AddPath(Base, CXXSystem, false);
+ bool IsBaseFound = AddPath(Base, CXXSystem, false);
// Add the multilib dirs
llvm::Triple::ArchType arch = triple.getArch();
@@ -190,6 +193,7 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
// Add the backward dir
AddPath(Base + "/backward", CXXSystem, false);
+ return IsBaseFound;
}
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
@@ -216,6 +220,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
case llvm::Triple::NaCl:
case llvm::Triple::PS4:
case llvm::Triple::ELFIAMCU:
+ case llvm::Triple::Fuchsia:
break;
case llvm::Triple::Win32:
if (triple.getEnvironment() != llvm::Triple::Cygnus)
@@ -255,6 +260,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
switch (os) {
case llvm::Triple::Linux:
+ case llvm::Triple::Solaris:
llvm_unreachable("Include management is handled in the driver.");
case llvm::Triple::CloudABI: {
@@ -321,6 +327,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
case llvm::Triple::RTEMS:
case llvm::Triple::NaCl:
case llvm::Triple::ELFIAMCU:
+ case llvm::Triple::Fuchsia:
break;
case llvm::Triple::PS4: {
// <isysroot> gets prepended later in AddPath().
@@ -351,51 +358,61 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
}
}
-void InitHeaderSearch::
-AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) {
+void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
+ const LangOptions &LangOpts, const llvm::Triple &triple,
+ const HeaderSearchOptions &HSOpts) {
llvm::Triple::OSType os = triple.getOS();
// FIXME: temporary hack: hard-coded paths.
if (triple.isOSDarwin()) {
+ bool IsBaseFound = true;
switch (triple.getArch()) {
default: break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "powerpc-apple-darwin10", "", "ppc64",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
- "powerpc-apple-darwin10", "", "ppc64",
- triple);
+ IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "powerpc-apple-darwin10", "",
+ "ppc64", triple);
+ IsBaseFound |= AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
+ "powerpc-apple-darwin10", "",
+ "ppc64", triple);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "i686-apple-darwin10", "", "x86_64", triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
- "i686-apple-darwin8", "", "", triple);
+ IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "i686-apple-darwin10", "",
+ "x86_64", triple);
+ IsBaseFound |= AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple);
break;
case llvm::Triple::arm:
case llvm::Triple::thumb:
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "arm-apple-darwin10", "v7", "", triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "arm-apple-darwin10", "v6", "", triple);
+ IsBaseFound = AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v7", "", triple);
+ IsBaseFound |= AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v6", "", triple);
break;
case llvm::Triple::aarch64:
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "arm64-apple-darwin10", "", "", triple);
+ IsBaseFound = AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.2.1", "arm64-apple-darwin10", "", "", triple);
break;
}
+ // Warn when compiling pure C++ / Objective-C++ only.
+ if (!IsBaseFound &&
+ !(LangOpts.CUDA || LangOpts.OpenCL || LangOpts.RenderScript)) {
+ Headers.getDiags().Report(SourceLocation(),
+ diag::warn_stdlibcxx_not_found);
+ }
return;
}
switch (os) {
case llvm::Triple::Linux:
+ case llvm::Triple::Solaris:
llvm_unreachable("Include management is handled in the driver.");
break;
case llvm::Triple::Win32:
@@ -443,6 +460,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
break; // Everything else continues to use this routine's logic.
case llvm::Triple::Linux:
+ case llvm::Triple::Solaris:
return;
case llvm::Triple::Win32:
@@ -452,8 +470,8 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
break;
}
- if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes &&
- HSOpts.UseStandardSystemIncludes) {
+ if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
+ HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
if (HSOpts.UseLibcxx) {
if (triple.isOSDarwin()) {
// On Darwin, libc++ may be installed alongside the compiler in
@@ -473,7 +491,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
}
AddPath("/usr/include/c++/v1", CXXSystem, false);
} else {
- AddDefaultCPlusPlusIncludePaths(triple, HSOpts);
+ AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
index 321d963827d1..e576fc098dad 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -93,7 +93,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
AddImplicitInclude(Builder, OriginalFile);
}
-/// \brief Add an implicit \#include using the original file used to generate
+/// Add an implicit \#include using the original file used to generate
/// a PCH file.
static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
const PCHContainerReader &PCHContainerRdr,
@@ -301,7 +301,7 @@ static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign,
return "1"; // "sometimes lock free"
}
-/// \brief Add definitions required for a smooth interaction between
+/// Add definitions required for a smooth interaction between
/// Objective-C++ automated reference counting and libstdc++ (4.2).
static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
MacroBuilder &Builder) {
@@ -426,45 +426,59 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// OpenCL v1.0/1.1 s6.9, v1.2/2.0 s6.10: Preprocessor Directives and Macros.
if (LangOpts.OpenCL) {
- // OpenCL v1.0 and v1.1 do not have a predefined macro to indicate the
- // language standard with which the program is compiled. __OPENCL_VERSION__
- // is for the OpenCL version supported by the OpenCL device, which is not
- // necessarily the language standard with which the program is compiled.
- // A shared OpenCL header file requires a macro to indicate the language
- // standard. As a workaround, __OPENCL_C_VERSION__ is defined for
- // OpenCL v1.0 and v1.1.
- switch (LangOpts.OpenCLVersion) {
- case 100:
- Builder.defineMacro("__OPENCL_C_VERSION__", "100");
- break;
- case 110:
- Builder.defineMacro("__OPENCL_C_VERSION__", "110");
- break;
- case 120:
- Builder.defineMacro("__OPENCL_C_VERSION__", "120");
- break;
- case 200:
- Builder.defineMacro("__OPENCL_C_VERSION__", "200");
- break;
- default:
- llvm_unreachable("Unsupported OpenCL version");
- }
- Builder.defineMacro("CL_VERSION_1_0", "100");
- Builder.defineMacro("CL_VERSION_1_1", "110");
- Builder.defineMacro("CL_VERSION_1_2", "120");
- Builder.defineMacro("CL_VERSION_2_0", "200");
+ if (LangOpts.CPlusPlus) {
+ if (LangOpts.OpenCLCPlusPlusVersion == 100)
+ Builder.defineMacro("__OPENCL_CPP_VERSION__", "100");
+ else
+ llvm_unreachable("Unsupported OpenCL C++ version");
+ Builder.defineMacro("__CL_CPP_VERSION_1_0__", "100");
+ } else {
+ // OpenCL v1.0 and v1.1 do not have a predefined macro to indicate the
+ // language standard with which the program is compiled. __OPENCL_VERSION__
+ // is for the OpenCL version supported by the OpenCL device, which is not
+ // necessarily the language standard with which the program is compiled.
+ // A shared OpenCL header file requires a macro to indicate the language
+ // standard. As a workaround, __OPENCL_C_VERSION__ is defined for
+ // OpenCL v1.0 and v1.1.
+ switch (LangOpts.OpenCLVersion) {
+ case 100:
+ Builder.defineMacro("__OPENCL_C_VERSION__", "100");
+ break;
+ case 110:
+ Builder.defineMacro("__OPENCL_C_VERSION__", "110");
+ break;
+ case 120:
+ Builder.defineMacro("__OPENCL_C_VERSION__", "120");
+ break;
+ case 200:
+ Builder.defineMacro("__OPENCL_C_VERSION__", "200");
+ break;
+ default:
+ llvm_unreachable("Unsupported OpenCL version");
+ }
+ Builder.defineMacro("CL_VERSION_1_0", "100");
+ Builder.defineMacro("CL_VERSION_1_1", "110");
+ Builder.defineMacro("CL_VERSION_1_2", "120");
+ Builder.defineMacro("CL_VERSION_2_0", "200");
- if (TI.isLittleEndian())
- Builder.defineMacro("__ENDIAN_LITTLE__");
+ if (TI.isLittleEndian())
+ Builder.defineMacro("__ENDIAN_LITTLE__");
- if (LangOpts.FastRelaxedMath)
- Builder.defineMacro("__FAST_RELAXED_MATH__");
+ if (LangOpts.FastRelaxedMath)
+ Builder.defineMacro("__FAST_RELAXED_MATH__");
+ }
}
// Not "standard" per se, but available even with the -undef flag.
if (LangOpts.AsmPreprocessor)
Builder.defineMacro("__ASSEMBLER__");
- if (LangOpts.CUDA)
+ if (LangOpts.CUDA && !LangOpts.HIP)
Builder.defineMacro("__CUDA__");
+ if (LangOpts.HIP) {
+ Builder.defineMacro("__HIP__");
+ Builder.defineMacro("__HIPCC__");
+ if (LangOpts.CUDAIsDevice)
+ Builder.defineMacro("__HIP_DEVICE_COMPILE__");
+ }
}
/// Initialize the predefined C++ language feature test macros defined in
@@ -473,78 +487,86 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
MacroBuilder &Builder) {
// C++98 features.
if (LangOpts.RTTI)
- Builder.defineMacro("__cpp_rtti", "199711");
+ Builder.defineMacro("__cpp_rtti", "199711L");
if (LangOpts.CXXExceptions)
- Builder.defineMacro("__cpp_exceptions", "199711");
+ Builder.defineMacro("__cpp_exceptions", "199711L");
// C++11 features.
if (LangOpts.CPlusPlus11) {
- Builder.defineMacro("__cpp_unicode_characters", "200704");
- Builder.defineMacro("__cpp_raw_strings", "200710");
- Builder.defineMacro("__cpp_unicode_literals", "200710");
- Builder.defineMacro("__cpp_user_defined_literals", "200809");
- Builder.defineMacro("__cpp_lambdas", "200907");
+ Builder.defineMacro("__cpp_unicode_characters", "200704L");
+ Builder.defineMacro("__cpp_raw_strings", "200710L");
+ Builder.defineMacro("__cpp_unicode_literals", "200710L");
+ Builder.defineMacro("__cpp_user_defined_literals", "200809L");
+ Builder.defineMacro("__cpp_lambdas", "200907L");
Builder.defineMacro("__cpp_constexpr",
- LangOpts.CPlusPlus17 ? "201603" :
- LangOpts.CPlusPlus14 ? "201304" : "200704");
+ LangOpts.CPlusPlus17 ? "201603L" :
+ LangOpts.CPlusPlus14 ? "201304L" : "200704");
Builder.defineMacro("__cpp_range_based_for",
- LangOpts.CPlusPlus17 ? "201603" : "200907");
+ LangOpts.CPlusPlus17 ? "201603L" : "200907");
Builder.defineMacro("__cpp_static_assert",
- LangOpts.CPlusPlus17 ? "201411" : "200410");
- Builder.defineMacro("__cpp_decltype", "200707");
- Builder.defineMacro("__cpp_attributes", "200809");
- Builder.defineMacro("__cpp_rvalue_references", "200610");
- Builder.defineMacro("__cpp_variadic_templates", "200704");
- Builder.defineMacro("__cpp_initializer_lists", "200806");
- Builder.defineMacro("__cpp_delegating_constructors", "200604");
- Builder.defineMacro("__cpp_nsdmi", "200809");
- Builder.defineMacro("__cpp_inheriting_constructors", "201511");
- Builder.defineMacro("__cpp_ref_qualifiers", "200710");
- Builder.defineMacro("__cpp_alias_templates", "200704");
+ LangOpts.CPlusPlus17 ? "201411L" : "200410");
+ Builder.defineMacro("__cpp_decltype", "200707L");
+ Builder.defineMacro("__cpp_attributes", "200809L");
+ Builder.defineMacro("__cpp_rvalue_references", "200610L");
+ Builder.defineMacro("__cpp_variadic_templates", "200704L");
+ Builder.defineMacro("__cpp_initializer_lists", "200806L");
+ Builder.defineMacro("__cpp_delegating_constructors", "200604L");
+ Builder.defineMacro("__cpp_nsdmi", "200809L");
+ Builder.defineMacro("__cpp_inheriting_constructors", "201511L");
+ Builder.defineMacro("__cpp_ref_qualifiers", "200710L");
+ Builder.defineMacro("__cpp_alias_templates", "200704L");
}
if (LangOpts.ThreadsafeStatics)
- Builder.defineMacro("__cpp_threadsafe_static_init", "200806");
+ Builder.defineMacro("__cpp_threadsafe_static_init", "200806L");
// C++14 features.
if (LangOpts.CPlusPlus14) {
- Builder.defineMacro("__cpp_binary_literals", "201304");
- Builder.defineMacro("__cpp_digit_separators", "201309");
- Builder.defineMacro("__cpp_init_captures", "201304");
- Builder.defineMacro("__cpp_generic_lambdas", "201304");
- Builder.defineMacro("__cpp_decltype_auto", "201304");
- Builder.defineMacro("__cpp_return_type_deduction", "201304");
- Builder.defineMacro("__cpp_aggregate_nsdmi", "201304");
- Builder.defineMacro("__cpp_variable_templates", "201304");
+ Builder.defineMacro("__cpp_binary_literals", "201304L");
+ Builder.defineMacro("__cpp_digit_separators", "201309L");
+ Builder.defineMacro("__cpp_init_captures", "201304L");
+ Builder.defineMacro("__cpp_generic_lambdas", "201304L");
+ Builder.defineMacro("__cpp_decltype_auto", "201304L");
+ Builder.defineMacro("__cpp_return_type_deduction", "201304L");
+ Builder.defineMacro("__cpp_aggregate_nsdmi", "201304L");
+ Builder.defineMacro("__cpp_variable_templates", "201304L");
}
if (LangOpts.SizedDeallocation)
- Builder.defineMacro("__cpp_sized_deallocation", "201309");
+ Builder.defineMacro("__cpp_sized_deallocation", "201309L");
// C++17 features.
if (LangOpts.CPlusPlus17) {
- Builder.defineMacro("__cpp_hex_float", "201603");
- Builder.defineMacro("__cpp_inline_variables", "201606");
- Builder.defineMacro("__cpp_noexcept_function_type", "201510");
- Builder.defineMacro("__cpp_capture_star_this", "201603");
- Builder.defineMacro("__cpp_if_constexpr", "201606");
- Builder.defineMacro("__cpp_deduction_guides", "201611");
- Builder.defineMacro("__cpp_template_auto", "201606");
- Builder.defineMacro("__cpp_namespace_attributes", "201411");
- Builder.defineMacro("__cpp_enumerator_attributes", "201411");
- Builder.defineMacro("__cpp_nested_namespace_definitions", "201411");
- Builder.defineMacro("__cpp_variadic_using", "201611");
- Builder.defineMacro("__cpp_aggregate_bases", "201603");
- Builder.defineMacro("__cpp_structured_bindings", "201606");
- Builder.defineMacro("__cpp_nontype_template_args", "201411");
- Builder.defineMacro("__cpp_fold_expressions", "201603");
+ Builder.defineMacro("__cpp_hex_float", "201603L");
+ Builder.defineMacro("__cpp_inline_variables", "201606L");
+ Builder.defineMacro("__cpp_noexcept_function_type", "201510L");
+ Builder.defineMacro("__cpp_capture_star_this", "201603L");
+ Builder.defineMacro("__cpp_if_constexpr", "201606L");
+ Builder.defineMacro("__cpp_deduction_guides", "201703L");
+ Builder.defineMacro("__cpp_template_auto", "201606L"); // (old name)
+ Builder.defineMacro("__cpp_namespace_attributes", "201411L");
+ Builder.defineMacro("__cpp_enumerator_attributes", "201411L");
+ Builder.defineMacro("__cpp_nested_namespace_definitions", "201411L");
+ Builder.defineMacro("__cpp_variadic_using", "201611L");
+ Builder.defineMacro("__cpp_aggregate_bases", "201603L");
+ Builder.defineMacro("__cpp_structured_bindings", "201606L");
+ Builder.defineMacro("__cpp_nontype_template_args", "201411L");
+ Builder.defineMacro("__cpp_fold_expressions", "201603L");
+ Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L");
+ Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L");
}
- if (LangOpts.AlignedAllocation)
- Builder.defineMacro("__cpp_aligned_new", "201606");
+ if (LangOpts.AlignedAllocation && !LangOpts.AlignedAllocationUnavailable)
+ Builder.defineMacro("__cpp_aligned_new", "201606L");
+ if (LangOpts.RelaxedTemplateTemplateArgs)
+ Builder.defineMacro("__cpp_template_template_args", "201611L");
// TS features.
if (LangOpts.ConceptsTS)
- Builder.defineMacro("__cpp_experimental_concepts", "1");
+ Builder.defineMacro("__cpp_experimental_concepts", "1L");
if (LangOpts.CoroutinesTS)
Builder.defineMacro("__cpp_coroutines", "201703L");
+
+ // Potential future breaking changes.
+ if (LangOpts.Char8)
+ Builder.defineMacro("__cpp_char8_t", "201803L");
}
static void InitializePredefinedMacros(const TargetInfo &TI,
@@ -627,6 +649,19 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (LangOpts.ObjCRuntime.isNeXTFamily())
Builder.defineMacro("__NEXT_RUNTIME__");
+ if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::GNUstep) {
+ auto version = LangOpts.ObjCRuntime.getVersion();
+ std::string versionString = "1";
+ // Don't rely on the tuple argument, because we can be asked to target
+ // later ABIs than we actually support, so clamp these values to those
+ // currently supported
+ if (version >= VersionTuple(2, 0))
+ Builder.defineMacro("__OBJC_GNUSTEP_RUNTIME_ABI__", "20");
+ else
+ Builder.defineMacro("__OBJC_GNUSTEP_RUNTIME_ABI__",
+ "1" + Twine(std::min(8U, version.getMinor().getValueOr(0))));
+ }
+
if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::ObjFW) {
VersionTuple tuple = LangOpts.ObjCRuntime.getVersion();
@@ -925,6 +960,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
InlineWidthBits));
DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
DEFINE_LOCK_FREE_MACRO(CHAR, Char);
+ if (LangOpts.Char8)
+ DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char.
DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16);
DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32);
DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar);
@@ -1007,23 +1044,25 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// macro name is defined to have the decimal value yyyymm where
// yyyy and mm are the year and the month designations of the
// version of the OpenMP API that the implementation support.
- switch (LangOpts.OpenMP) {
- case 0:
- break;
- case 40:
- Builder.defineMacro("_OPENMP", "201307");
- break;
- case 45:
- Builder.defineMacro("_OPENMP", "201511");
- break;
- default:
- // Default version is OpenMP 3.1, in Simd only mode - 4.5
- Builder.defineMacro("_OPENMP", LangOpts.OpenMPSimd ? "201511" : "201107");
- break;
+ if (!LangOpts.OpenMPSimd) {
+ switch (LangOpts.OpenMP) {
+ case 0:
+ break;
+ case 40:
+ Builder.defineMacro("_OPENMP", "201307");
+ break;
+ case 45:
+ Builder.defineMacro("_OPENMP", "201511");
+ break;
+ default:
+ // Default version is OpenMP 3.1
+ Builder.defineMacro("_OPENMP", "201107");
+ break;
+ }
}
// CUDA device path compilaton
- if (LangOpts.CUDAIsDevice) {
+ if (LangOpts.CUDAIsDevice && !LangOpts.HIP) {
// The CUDA_ARCH value is set for the GPU target specified in the NVPTX
// backend's target defines.
Builder.defineMacro("__CUDA_ARCH__");
diff --git a/contrib/llvm/tools/clang/lib/Frontend/LayoutOverrideSource.cpp b/contrib/llvm/tools/clang/lib/Frontend/LayoutOverrideSource.cpp
index 06e9a7dc50b4..b31fbd087ba7 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/LayoutOverrideSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/LayoutOverrideSource.cpp
@@ -15,7 +15,7 @@
using namespace clang;
-/// \brief Parse a simple identifier.
+/// Parse a simple identifier.
static std::string parseName(StringRef S) {
if (S.empty() || !isIdentifierHead(S[0]))
return "";
@@ -23,7 +23,7 @@ static std::string parseName(StringRef S) {
unsigned Offset = 1;
while (Offset < S.size() && isIdentifierBody(S[Offset]))
++Offset;
-
+
return S.substr(0, Offset).str();
}
@@ -31,33 +31,33 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
std::ifstream Input(Filename.str().c_str());
if (!Input.is_open())
return;
-
+
// Parse the output of -fdump-record-layouts.
std::string CurrentType;
Layout CurrentLayout;
bool ExpectingType = false;
-
+
while (Input.good()) {
std::string Line;
getline(Input, Line);
-
+
StringRef LineStr(Line);
- // Determine whether the following line will start a
+ // Determine whether the following line will start a
if (LineStr.find("*** Dumping AST Record Layout") != StringRef::npos) {
// Flush the last type/layout, if there is one.
if (!CurrentType.empty())
Layouts[CurrentType] = CurrentLayout;
CurrentLayout = Layout();
-
+
ExpectingType = true;
continue;
}
-
+
// If we're expecting a type, grab it.
if (ExpectingType) {
ExpectingType = false;
-
+
StringRef::size_type Pos;
if ((Pos = LineStr.find("struct ")) != StringRef::npos)
LineStr = LineStr.substr(Pos + strlen("struct "));
@@ -67,19 +67,19 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
LineStr = LineStr.substr(Pos + strlen("union "));
else
continue;
-
+
// Find the name of the type.
CurrentType = parseName(LineStr);
CurrentLayout = Layout();
continue;
}
-
+
// Check for the size of the type.
StringRef::size_type Pos = LineStr.find(" Size:");
if (Pos != StringRef::npos) {
// Skip past the " Size:" prefix.
LineStr = LineStr.substr(Pos + strlen(" Size:"));
-
+
unsigned long long Size = 0;
(void)LineStr.getAsInteger(10, Size);
CurrentLayout.Size = Size;
@@ -91,13 +91,13 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
if (Pos != StringRef::npos) {
// Skip past the "Alignment:" prefix.
LineStr = LineStr.substr(Pos + strlen("Alignment:"));
-
+
unsigned long long Alignment = 0;
(void)LineStr.getAsInteger(10, Alignment);
CurrentLayout.Align = Alignment;
continue;
}
-
+
// Check for the size/alignment of the type.
Pos = LineStr.find("sizeof=");
if (Pos != StringRef::npos) {
@@ -113,16 +113,16 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
if (Pos != StringRef::npos) {
/* Skip past the align= prefix. */
LineStr = LineStr.substr(Pos + strlen("align="));
-
+
// Parse alignment.
unsigned long long Alignment = 0;
(void)LineStr.getAsInteger(10, Alignment);
CurrentLayout.Align = Alignment;
}
-
+
continue;
}
-
+
// Check for the field offsets of the type.
Pos = LineStr.find("FieldOffsets: [");
if (Pos == StringRef::npos)
@@ -134,55 +134,55 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
unsigned Idx = 1;
while (Idx < LineStr.size() && isDigit(LineStr[Idx]))
++Idx;
-
+
unsigned long long Offset = 0;
(void)LineStr.substr(0, Idx).getAsInteger(10, Offset);
-
+
CurrentLayout.FieldOffsets.push_back(Offset);
-
+
// Skip over this offset, the following comma, and any spaces.
LineStr = LineStr.substr(Idx + 1);
while (!LineStr.empty() && isWhitespace(LineStr[0]))
LineStr = LineStr.substr(1);
}
}
-
+
// Flush the last type/layout, if there is one.
if (!CurrentType.empty())
Layouts[CurrentType] = CurrentLayout;
}
-bool
+bool
LayoutOverrideSource::layoutRecordType(const RecordDecl *Record,
uint64_t &Size, uint64_t &Alignment,
llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
- llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)
{
// We can't override unnamed declarations.
if (!Record->getIdentifier())
return false;
-
+
// Check whether we have a layout for this record.
llvm::StringMap<Layout>::iterator Known = Layouts.find(Record->getName());
if (Known == Layouts.end())
return false;
-
+
// Provide field layouts.
unsigned NumFields = 0;
- for (RecordDecl::field_iterator F = Record->field_begin(),
+ for (RecordDecl::field_iterator F = Record->field_begin(),
FEnd = Record->field_end();
F != FEnd; ++F, ++NumFields) {
if (NumFields >= Known->second.FieldOffsets.size())
continue;
-
+
FieldOffsets[*F] = Known->second.FieldOffsets[NumFields];
}
-
+
// Wrong number of fields.
if (NumFields != Known->second.FieldOffsets.size())
return false;
-
+
Size = Known->second.Size;
Alignment = Known->second.Align;
return true;
@@ -190,7 +190,7 @@ LayoutOverrideSource::layoutRecordType(const RecordDecl *Record,
LLVM_DUMP_METHOD void LayoutOverrideSource::dump() {
raw_ostream &OS = llvm::errs();
- for (llvm::StringMap<Layout>::iterator L = Layouts.begin(),
+ for (llvm::StringMap<Layout>::iterator L = Layouts.begin(),
LEnd = Layouts.end();
L != LEnd; ++L) {
OS << "Type: blah " << L->first() << '\n';
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
index ede12aab6e69..25cad8be6d00 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
@@ -16,6 +16,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -49,7 +50,8 @@ struct ModuleDependencyPPCallbacks : public PPCallbacks {
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override {
if (!File)
return;
Collector.addFile(File->getName());
@@ -135,7 +137,7 @@ static bool isCaseSensitivePath(StringRef Path) {
// Change path to all upper case and ask for its real path, if the latter
// exists and is equal to Path, it's not case sensitive. Default to case
- // sensitive in the absense of realpath, since this is what the VFSWriter
+ // sensitive in the absence of realpath, since this is what the VFSWriter
// already expects when sensitivity isn't setup.
for (auto &C : Path)
UpperDest.push_back(toUppercase(C));
diff --git a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
index 04a8f6c1cdfb..c6e18d9cae21 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -16,35 +16,11 @@
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclGroup.h"
-#include "clang/Serialization/ASTDeserializationListener.h"
using namespace clang;
namespace clang {
-// This ASTDeserializationListener forwards its notifications to a set of
-// child listeners.
-class MultiplexASTDeserializationListener
- : public ASTDeserializationListener {
-public:
- // Does NOT take ownership of the elements in L.
- MultiplexASTDeserializationListener(
- const std::vector<ASTDeserializationListener*>& L);
- void ReaderInitialized(ASTReader *Reader) override;
- void IdentifierRead(serialization::IdentID ID,
- IdentifierInfo *II) override;
- void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
- void TypeRead(serialization::TypeIdx Idx, QualType T) override;
- void DeclRead(serialization::DeclID ID, const Decl *D) override;
- void SelectorRead(serialization::SelectorID iD, Selector Sel) override;
- void MacroDefinitionRead(serialization::PreprocessedEntityID,
- MacroDefinitionRecord *MD) override;
- void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override;
-
-private:
- std::vector<ASTDeserializationListener *> Listeners;
-};
-
MultiplexASTDeserializationListener::MultiplexASTDeserializationListener(
const std::vector<ASTDeserializationListener*>& L)
: Listeners(L) {
@@ -131,7 +107,7 @@ public:
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) override;
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
- void AddedAttributeToRecord(const Attr *Attr,
+ void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) override;
private:
@@ -243,9 +219,9 @@ void MultiplexASTMutationListener::RedefinedHiddenDefinition(const NamedDecl *D,
for (auto *L : Listeners)
L->RedefinedHiddenDefinition(D, M);
}
-
+
void MultiplexASTMutationListener::AddedAttributeToRecord(
- const Attr *Attr,
+ const Attr *Attr,
const RecordDecl *Record) {
for (auto *L : Listeners)
L->AddedAttributeToRecord(Attr, Record);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
index eebebf327a19..340e8ce63ff4 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
@@ -25,7 +25,7 @@ PCHContainerReader::~PCHContainerReader() {}
namespace {
-/// \brief A PCHContainerGenerator that writes out the PCH to a flat file.
+/// A PCHContainerGenerator that writes out the PCH to a flat file.
class RawPCHContainerGenerator : public ASTConsumer {
std::shared_ptr<PCHBuffer> Buffer;
std::unique_ptr<raw_pwrite_stream> OS;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp
index 7e1323fd83bb..30ae2db26d86 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -40,7 +40,7 @@ namespace {
StringRef getInMemoryPreamblePath() {
#if defined(LLVM_ON_UNIX)
return "/__clang_tmp/___clang_inmemory_preamble___";
-#elif defined(LLVM_ON_WIN32)
+#elif defined(_WIN32)
return "C:\\__clang_tmp\\___clang_inmemory_preamble___";
#else
#warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs"
@@ -63,6 +63,16 @@ createVFSOverlayForPreamblePCH(StringRef PCHFilename,
return Overlay;
}
+class PreambleDependencyCollector : public DependencyCollector {
+public:
+ // We want to collect all dependencies for correctness. Avoiding the real
+ // system dependencies (e.g. stl from /usr/lib) would probably be a good idea,
+ // but there is no way to distinguish between those and the ones that can be
+ // spuriously added by '-isystem' (e.g. to suppress warnings from those
+ // headers).
+ bool needSystemDependencies() override { return true; }
+};
+
/// Keeps a track of files to be deleted in destructor.
class TemporaryFiles {
public:
@@ -303,8 +313,6 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
VFS =
createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS);
- if (!VFS)
- return BuildPreambleError::CouldntCreateVFSOverlay;
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
@@ -313,7 +321,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
Clang->setSourceManager(
new SourceManager(Diagnostics, Clang->getFileManager()));
- auto PreambleDepCollector = std::make_shared<DependencyCollector>();
+ auto PreambleDepCollector = std::make_shared<PreambleDependencyCollector>();
Clang->addDependencyCollector(PreambleDepCollector);
// Remap the main source file to the preamble buffer.
@@ -485,20 +493,15 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
void PrecompiledPreamble::AddImplicitPreamble(
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.DisablePCHValidation = true;
+ PreambleBounds Bounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
+ configurePreamble(Bounds, CI, VFS, MainFileBuffer);
+}
- setupPreambleStorage(Storage, PreprocessorOpts, VFS);
+void PrecompiledPreamble::OverridePreamble(
+ CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ llvm::MemoryBuffer *MainFileBuffer) const {
+ auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), MainFileBuffer, 0);
+ configurePreamble(Bounds, CI, VFS, MainFileBuffer);
}
PrecompiledPreamble::PrecompiledPreamble(
@@ -681,6 +684,27 @@ PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
return Result;
}
+void PrecompiledPreamble::configurePreamble(
+ PreambleBounds Bounds, CompilerInvocation &CI,
+ IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ llvm::MemoryBuffer *MainFileBuffer) const {
+ assert(VFS);
+
+ 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 = Bounds.Size;
+ PreprocessorOpts.PrecompiledPreambleBytes.second =
+ Bounds.PreambleEndsAtStartOfLine;
+ PreprocessorOpts.DisablePCHValidation = true;
+
+ setupPreambleStorage(Storage, PreprocessorOpts, VFS);
+}
+
void PrecompiledPreamble::setupPreambleStorage(
const PCHStorage &Storage, PreprocessorOptions &PreprocessorOpts,
IntrusiveRefCntPtr<vfs::FileSystem> &VFS) {
@@ -740,8 +764,6 @@ std::string BuildPreambleErrorCategory::message(int condition) const {
return "Could not create temporary file for PCH";
case BuildPreambleError::CouldntCreateTargetInfo:
return "CreateTargetInfo() return null";
- case BuildPreambleError::CouldntCreateVFSOverlay:
- return "Could not create VFS Overlay";
case BuildPreambleError::BeginSourceFileFailed:
return "BeginSourceFile() return an error";
case BuildPreambleError::CouldntEmitPCH:
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index 2e023294f1e8..69cd072ea57f 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -130,7 +130,8 @@ public:
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override;
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
void Ident(SourceLocation Loc, StringRef str) override;
void PragmaMessage(SourceLocation Loc, StringRef Namespace,
PragmaMessageKind Kind, StringRef Str) override;
@@ -159,7 +160,7 @@ public:
}
bool MoveToLine(unsigned LineNo);
- bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok,
+ bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok,
const Token &Tok) {
return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok);
}
@@ -247,7 +248,7 @@ PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) {
++CurLine;
return true;
}
-
+
return false;
}
@@ -261,11 +262,11 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
// Unless we are exiting a #include, make sure to skip ahead to the line the
// #include directive was at.
SourceManager &SourceMgr = SM;
-
+
PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc);
if (UserLoc.isInvalid())
return;
-
+
unsigned NewLine = UserLoc.getLine();
if (Reason == PPCallbacks::EnterFile) {
@@ -280,7 +281,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
// off by one. We can do better by simply incrementing NewLine here.
NewLine += 1;
}
-
+
CurLine = NewLine;
CurFilename.clear();
@@ -291,7 +292,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
return;
}
-
+
if (!Initialized) {
WriteLineInfo(CurLine);
Initialized = true;
@@ -320,15 +321,17 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
}
}
-void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
- const Token &IncludeTok,
- StringRef FileName,
- bool IsAngled,
- CharSourceRange FilenameRange,
- const FileEntry *File,
- StringRef SearchPath,
- StringRef RelativePath,
- const Module *Imported) {
+void PrintPPOutputPPCallbacks::InclusionDirective(
+ SourceLocation HashLoc,
+ const Token &IncludeTok,
+ StringRef FileName,
+ bool IsAngled,
+ CharSourceRange FilenameRange,
+ const FileEntry *File,
+ StringRef SearchPath,
+ StringRef RelativePath,
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
// In -dI mode, dump #include directives prior to dumping their content or
// interpretation.
if (DumpIncludeDirectives) {
@@ -752,7 +755,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
} else if (Tok.isLiteral() && !Tok.needsCleaning() &&
Tok.getLiteralData()) {
OS.write(Tok.getLiteralData(), Tok.getLength());
- } else if (Tok.getLength() < 256) {
+ } else if (Tok.getLength() < llvm::array_lengthof(Buffer)) {
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OS.write(TokPtr, Len);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp
index dc787ac9557c..1c2efe63aa19 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp
@@ -1,4 +1,4 @@
-//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
+//===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,28 +14,32 @@
//===----------------------------------------------------------------------===//
#include "clang/Rewrite/Frontend/FixItRewriter.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Frontend/FrontendDiagnostic.h"
-#include "llvm/Support/Path.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
using namespace clang;
FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const LangOptions &LangOpts,
FixItOptions *FixItOpts)
- : Diags(Diags),
- Editor(SourceMgr, LangOpts),
- Rewrite(SourceMgr, LangOpts),
- FixItOpts(FixItOpts),
- NumFailures(0),
- PrevDiagSilenced(false) {
+ : Diags(Diags), Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts),
+ FixItOpts(FixItOpts) {
Owner = Diags.takeClient();
Client = Diags.getClient();
Diags.setClient(this, false);
@@ -59,20 +63,21 @@ class RewritesReceiver : public edit::EditsReceiver {
Rewriter &Rewrite;
public:
- RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
+ RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) {}
void insert(SourceLocation loc, StringRef text) override {
Rewrite.InsertText(loc, text);
}
+
void replace(CharSourceRange range, StringRef text) override {
Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
}
};
-}
+} // namespace
bool FixItRewriter::WriteFixedFiles(
- std::vector<std::pair<std::string, std::string> > *RewrittenFiles) {
+ std::vector<std::pair<std::string, std::string>> *RewrittenFiles) {
if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
return true;
@@ -179,7 +184,7 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
}
return;
}
-
+
if (!Editor.commit(commit)) {
++NumFailures;
Diag(Info.getLocation(), diag::note_fixit_failed);
@@ -189,7 +194,7 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Diag(Info.getLocation(), diag::note_fixit_applied);
}
-/// \brief Emit a diagnostic via the adapted diagnostic client.
+/// Emit a diagnostic via the adapted diagnostic client.
void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
// When producing this diagnostic, we temporarily bypass ourselves,
// clear out any current diagnostic, and let the downstream client
@@ -200,4 +205,4 @@ void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
Diags.setClient(this, false);
}
-FixItOptions::~FixItOptions() {}
+FixItOptions::~FixItOptions() = default;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 4d587048f62d..fa17b3e7cb3f 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -131,9 +131,9 @@ bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
CI.getLangOpts(), FixItOpts.get());
FixAction->Execute();
-
+
err = Rewriter.WriteFixedFiles(&RewrittenFiles);
-
+
FixAction->EndSourceFile();
CI.setSourceManager(nullptr);
CI.setFileManager(nullptr);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/HTMLPrint.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/HTMLPrint.cpp
index 11e431de0a31..34ee9673cc54 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/HTMLPrint.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/HTMLPrint.cpp
@@ -86,8 +86,7 @@ void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
// Emit the HTML.
const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
- char *Buffer = (char*)malloc(RewriteBuf.size());
- std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
- Out->write(Buffer, RewriteBuf.size());
- free(Buffer);
+ std::unique_ptr<char[]> Buffer(new char[RewriteBuf.size()]);
+ std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer.get());
+ Out->write(Buffer.get(), RewriteBuf.size());
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
index e0477069b340..1631eccd7013 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -32,8 +32,10 @@ class InclusionRewriter : public PPCallbacks {
struct IncludedFile {
FileID Id;
SrcMgr::CharacteristicKind FileType;
- IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType)
- : Id(Id), FileType(FileType) {}
+ const DirectoryLookup *DirLookup;
+ IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType,
+ const DirectoryLookup *DirLookup)
+ : Id(Id), FileType(FileType), DirLookup(DirLookup) {}
};
Preprocessor &PP; ///< Used to find inclusion directives.
SourceManager &SM; ///< Used to read and manage source files.
@@ -54,7 +56,8 @@ class InclusionRewriter : public PPCallbacks {
public:
InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers,
bool UseLineDirectives);
- void Process(FileID FileId, SrcMgr::CharacteristicKind FileType);
+ void Process(FileID FileId, SrcMgr::CharacteristicKind FileType,
+ const DirectoryLookup *DirLookup);
void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) {
PredefinesBuffer = Buf;
}
@@ -74,7 +77,8 @@ private:
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override;
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
void WriteLineInfo(StringRef Filename, int Line,
SrcMgr::CharacteristicKind FileType,
StringRef Extra = StringRef());
@@ -156,8 +160,9 @@ void InclusionRewriter::FileChanged(SourceLocation Loc,
// we didn't reach this file (eg: the main file) via an inclusion directive
return;
FileID Id = FullSourceLoc(Loc, SM).getFileID();
- auto P = FileIncludes.insert(std::make_pair(
- LastInclusionLocation.getRawEncoding(), IncludedFile(Id, NewFileType)));
+ auto P = FileIncludes.insert(
+ std::make_pair(LastInclusionLocation.getRawEncoding(),
+ IncludedFile(Id, NewFileType, PP.GetCurDirLookup())));
(void)P;
assert(P.second && "Unexpected revisitation of the same include directive");
LastInclusionLocation = SourceLocation();
@@ -188,7 +193,8 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
const FileEntry * /*File*/,
StringRef /*SearchPath*/,
StringRef /*RelativePath*/,
- const Module *Imported) {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType){
if (Imported) {
auto P = ModuleIncludes.insert(
std::make_pair(HashLoc.getRawEncoding(), Imported));
@@ -408,7 +414,7 @@ bool InclusionRewriter::HandleHasInclude(
Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
// FIXME: Why don't we call PP.LookupFile here?
const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
- Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr,
+ Filename, SourceLocation(), isAngled, Lookup, CurDir, Includers, nullptr,
nullptr, nullptr, nullptr, nullptr);
FileExists = File != nullptr;
@@ -418,7 +424,8 @@ bool InclusionRewriter::HandleHasInclude(
/// Use a raw lexer to analyze \p FileId, incrementally copying parts of it
/// and including content of included files recursively.
void InclusionRewriter::Process(FileID FileId,
- SrcMgr::CharacteristicKind FileType) {
+ SrcMgr::CharacteristicKind FileType,
+ const DirectoryLookup *DirLookup) {
bool Invalid;
const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
assert(!Invalid && "Attempting to process invalid inclusion");
@@ -475,7 +482,7 @@ void InclusionRewriter::Process(FileID FileId,
<< Mod->getFullModuleName(true) << "\n";
// Include and recursively process the file.
- Process(Inc->Id, Inc->FileType);
+ Process(Inc->Id, Inc->FileType, Inc->DirLookup);
if (Mod)
OS << "#pragma clang module end /*"
@@ -532,11 +539,10 @@ void InclusionRewriter::Process(FileID FileId,
// Rewrite __has_include_next(x)
} else if (RawToken.getIdentifierInfo()->isStr(
"__has_include_next")) {
- const DirectoryLookup *Lookup = PP.GetCurDirLookup();
- if (Lookup)
- ++Lookup;
+ if (DirLookup)
+ ++DirLookup;
- if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken,
+ if (!HandleHasInclude(FileId, RawLex, DirLookup, RawToken,
HasFile))
continue;
} else {
@@ -621,7 +627,7 @@ void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
Rewrite->handleModuleBegin(Tok);
} while (Tok.isNot(tok::eof));
Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID()));
- Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User);
- Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User);
+ Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User, nullptr);
+ Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User, nullptr);
OS->flush();
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 1954b24aedad..36382e1438d5 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -39,12 +39,12 @@ using llvm::utostr;
namespace {
class RewriteModernObjC : public ASTConsumer {
protected:
-
+
enum {
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
block, ... */
BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
- BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
+ BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
__block variable */
BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
helpers */
@@ -52,7 +52,7 @@ namespace {
support routines */
BLOCK_BYREF_CURRENT_MAX = 256
};
-
+
enum {
BLOCK_NEEDS_FREE = (1 << 24),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
@@ -61,7 +61,7 @@ namespace {
BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_HAS_DESCRIPTOR = (1 << 29)
};
-
+
Rewriter Rewrite;
DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
@@ -75,7 +75,7 @@ namespace {
std::string InFileName;
std::unique_ptr<raw_ostream> OutFile;
std::string Preamble;
-
+
TypeDecl *ProtocolTypeDecl;
VarDecl *GlobalVarDecl;
Expr *GlobalConstructionExp;
@@ -88,13 +88,13 @@ namespace {
// ObjC foreach break/continue generation support.
int BcLabelCount;
-
+
unsigned TryFinallyContainsReturnDiag;
// Needed for super.
ObjCMethodDecl *CurMethodDef;
RecordDecl *SuperStructDecl;
RecordDecl *ConstantStringDecl;
-
+
FunctionDecl *MsgSendFunctionDecl;
FunctionDecl *MsgSendSuperFunctionDecl;
FunctionDecl *MsgSendStretFunctionDecl;
@@ -118,22 +118,22 @@ namespace {
SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
/// DefinedNonLazyClasses - List of defined "non-lazy" classes.
SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
-
+
/// DefinedNonLazyCategories - List of defined "non-lazy" categories.
SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;
-
+
SmallVector<Stmt *, 32> Stmts;
SmallVector<int, 8> ObjCBcLabelNo;
// Remember all the @protocol(<expr>) expressions.
llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
-
+
llvm::DenseSet<uint64_t> CopyDestroyCache;
// Block expressions.
SmallVector<BlockExpr *, 32> Blocks;
SmallVector<int, 32> InnerDeclRefsCount;
SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
-
+
SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
// Block related declarations.
@@ -144,11 +144,11 @@ namespace {
llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
-
+
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
- llvm::DenseMap<ObjCInterfaceDecl *,
+ llvm::DenseMap<ObjCInterfaceDecl *,
llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars;
-
+
// ivar bitfield grouping containers
llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;
llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber;
@@ -156,7 +156,7 @@ namespace {
// of the struct where the bitfield belongs.
llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;
SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;
-
+
// This maps an original source AST to it's rewritten form. This allows
// us to avoid rewriting the same node twice (which is very uncommon).
// This is needed to support some of the exotic property rewriting.
@@ -167,12 +167,12 @@ namespace {
bool SilenceRewriteMacroWarning;
bool GenerateLineInfo;
bool objc_impl_method;
-
+
bool DisableReplaceStmt;
class DisableReplaceStmtScope {
RewriteModernObjC &R;
bool SavedValue;
-
+
public:
DisableReplaceStmtScope(RewriteModernObjC &R)
: R(R), SavedValue(R.DisableReplaceStmt) {
@@ -237,7 +237,7 @@ namespace {
}
}
}
-
+
void HandleTopLevelSingleDecl(Decl *D);
void HandleDeclInMainFile(Decl *D);
RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
@@ -314,7 +314,7 @@ namespace {
std::string &LineString);
void RewriteForwardClassDecl(DeclGroupRef D);
void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
- void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
+ void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
const std::string &typedefString);
void RewriteImplementations();
void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
@@ -341,9 +341,9 @@ namespace {
void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
void RewriteTypeOfDecl(VarDecl *VD);
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
-
+
std::string getIvarAccessString(ObjCIvarDecl *D);
-
+
// Expression Rewriting.
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
@@ -367,7 +367,7 @@ namespace {
Stmt *RewriteContinueStmt(ContinueStmt *S);
void RewriteCastExpr(CStyleCastExpr *CE);
void RewriteImplicitCastObjCExpr(CastExpr *IE);
-
+
// Computes ivar bitfield group no.
unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);
// Names field decl. for ivar bitfield group.
@@ -381,28 +381,28 @@ namespace {
QualType SynthesizeBitfieldGroupStructType(
ObjCIvarDecl *IV,
SmallVectorImpl<ObjCIvarDecl *> &IVars);
-
+
// Block rewriting.
void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
-
+
// Block specific rewrite rules.
void RewriteBlockPointerDecl(NamedDecl *VD);
void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);
Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
-
+
void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result);
-
+
void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,
bool &IsNamedDefinition);
- void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
+ void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
std::string &Result);
-
+
bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
-
+
void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
std::string &Result);
@@ -414,9 +414,9 @@ namespace {
ArrayRef<Expr *> Args,
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
-
+
Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
- QualType returnType,
+ QualType returnType,
SmallVectorImpl<QualType> &ArgTypes,
SmallVectorImpl<Expr*> &MsgExprs,
ObjCMethodDecl *Method);
@@ -424,7 +424,7 @@ namespace {
Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
-
+
void SynthCountByEnumWithState(std::string &buf);
void SynthMsgSendFunctionDecl();
void SynthMsgSendSuperFunctionDecl();
@@ -436,7 +436,7 @@ namespace {
void SynthGetSuperClassFunctionDecl();
void SynthSelGetUidFunctionDecl();
void SynthSuperConstructorFunctionDecl();
-
+
// Rewriting metadata
template<typename MethodIterator>
void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
@@ -450,27 +450,27 @@ namespace {
void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
std::string &Result);
void RewriteClassSetupInitHook(std::string &Result);
-
+
void RewriteMetaDataIntoBuffer(std::string &Result);
void WriteImageInfo(std::string &Result);
void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
std::string &Result);
void RewriteCategorySetupInitHook(std::string &Result);
-
+
// Rewriting ivar
void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
std::string &Result);
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
-
+
std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
StringRef funcName, std::string Tag);
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
StringRef funcName, std::string Tag);
- std::string SynthesizeBlockImpl(BlockExpr *CE,
+ std::string SynthesizeBlockImpl(BlockExpr *CE,
std::string Tag, std::string Desc);
- std::string SynthesizeBlockDescriptor(std::string DescTag,
+ std::string SynthesizeBlockDescriptor(std::string DescTag,
std::string ImplTag,
int i, StringRef funcName,
unsigned hasCopy);
@@ -512,18 +512,18 @@ namespace {
}
return false;
}
-
+
bool convertObjCTypeToCStyleType(QualType &T);
-
+
bool needToScanForQualifiers(QualType T);
QualType getSuperStructType();
QualType getConstantStringStructType();
QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
-
+
void convertToUnqualifiedObjCType(QualType &T) {
if (T->isObjCQualifiedIdType()) {
bool isConst = T.isConstQualified();
- T = isConst ? Context->getObjCIdType().withConst()
+ T = isConst ? Context->getObjCIdType().withConst()
: Context->getObjCIdType();
}
else if (T->isObjCQualifiedClassType())
@@ -538,7 +538,7 @@ namespace {
}
}
}
-
+
// FIXME: This predicate seems like it would be useful to add to ASTContext.
bool isObjCType(QualType T) {
if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
@@ -562,7 +562,7 @@ namespace {
bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
void GetExtentOfArgList(const char *Name, const char *&LParen,
const char *&RParen);
-
+
void QuoteDoublequotes(std::string &From, std::string &To) {
for (unsigned i = 0; i < From.length(); i++) {
if (From[i] == '"')
@@ -589,7 +589,7 @@ namespace {
return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr,
TInfo, SourceLocation(), SourceLocation());
}
-
+
bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
IdentifierInfo* II = &Context->Idents.get("load");
Selector LoadSel = Context->Selectors.getSelector(0, &II);
@@ -653,7 +653,7 @@ RewriteModernObjC::RewriteModernObjC(std::string inFile,
// may break including some headers.
GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
"rewriting block literal declared in global scope is not implemented");
-
+
TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
DiagnosticsEngine::Warning,
"rewriter doesn't support user-specified control flow semantics "
@@ -756,7 +756,7 @@ void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
DG.push_back(*DI);
else
break;
-
+
++DI;
} while (DI != DIEnd);
RewriteForwardClassDecl(DG);
@@ -781,14 +781,14 @@ void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
DG.push_back(*DI);
else
break;
-
+
++DI;
} while (DI != DIEnd);
RewriteForwardProtocolDecl(DG);
continue;
}
}
-
+
HandleTopLevelSingleDecl(*DI);
++DI;
}
@@ -836,28 +836,28 @@ static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,
Result += IvarDecl->getName();
}
-std::string
+std::string
RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();
-
+
// Build name of symbol holding ivar offset.
std::string IvarOffsetName;
if (D->isBitField())
ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
else
WriteInternalIvarName(ClassDecl, D, IvarOffsetName);
-
+
std::string S = "(*(";
QualType IvarT = D->getType();
if (D->isBitField())
IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
-
+
if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) {
RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl();
RD = RD->getDefinition();
if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
// decltype(((Foo_IMPL*)0)->bar) *
- ObjCContainerDecl *CDecl =
+ ObjCContainerDecl *CDecl =
dyn_cast<ObjCContainerDecl>(D->getDeclContext());
// ivar in class extensions requires special treatment.
if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
@@ -868,7 +868,7 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
RecordDecl::Create(*Context, TTK_Struct, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(RecName));
QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
- unsigned UnsignedIntSize =
+ unsigned UnsignedIntSize =
static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
Expr *Zero = IntegerLiteral::Create(*Context,
llvm::APInt(UnsignedIntSize, 0),
@@ -893,7 +893,7 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));
S += TypeString;
S += ")";
-
+
// ((char *)self + IVAR_OFFSET_SYMBOL_NAME)
S += "((char *)self + ";
S += IvarOffsetName;
@@ -913,7 +913,7 @@ static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
bool getter) {
return getter ? !IMP->getInstanceMethod(PD->getGetterName())
: !IMP->getInstanceMethod(PD->getSetterName());
-
+
}
void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
@@ -922,7 +922,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
static bool objcGetPropertyDefined = false;
static bool objcSetPropertyDefined = false;
SourceLocation startGetterSetterLoc;
-
+
if (PID->getLocStart().isValid()) {
SourceLocation startLoc = PID->getLocStart();
InsertText(startLoc, "// ");
@@ -946,7 +946,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
unsigned Attributes = PD->getPropertyAttributes();
if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {
bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
- (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy));
std::string Getr;
if (GenGetProperty && !objcGetPropertyDefined) {
@@ -955,7 +955,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Getr = "\nextern \"C\" __declspec(dllimport) "
"id objc_getProperty(id, SEL, long, bool);\n";
}
- RewriteObjCMethodDecl(OID->getContainingInterface(),
+ RewriteObjCMethodDecl(OID->getContainingInterface(),
PD->getGetterMethodDecl(), Getr);
Getr += "{ ";
// Synthesize an explicit cast to gain access to the ivar.
@@ -969,7 +969,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Getr += " _TYPE";
if (FPRetType) {
Getr += ")"; // close the precedence "scope" for "*".
-
+
// Now, emit the argument types (if any).
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
Getr += "(";
@@ -999,14 +999,14 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Getr += "; }";
InsertText(startGetterSetterLoc, Getr);
}
-
- if (PD->isReadOnly() ||
+
+ if (PD->isReadOnly() ||
!mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))
return;
// Generate the 'setter' function.
std::string Setr;
- bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy);
if (GenSetProperty && !objcSetPropertyDefined) {
objcSetPropertyDefined = true;
@@ -1015,7 +1015,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
"void objc_setProperty (id, SEL, long, id, bool, bool);\n";
}
- RewriteObjCMethodDecl(OID->getContainingInterface(),
+ RewriteObjCMethodDecl(OID->getContainingInterface(),
PD->getSetterMethodDecl(), Setr);
Setr += "{ ";
// Synthesize an explicit cast to initialize the ivar.
@@ -1063,9 +1063,9 @@ void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl
const std::string &typedefString) {
SourceLocation startLoc = ClassDecl->getLocStart();
const char *startBuf = SM->getCharacterData(startLoc);
- const char *semiPtr = strchr(startBuf, ';');
+ const char *semiPtr = strchr(startBuf, ';');
// Replace the @class with typedefs corresponding to the classes.
- ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
+ ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
}
void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {
@@ -1139,24 +1139,24 @@ void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
else {
ReplaceText(LocStart, 0, "// ");
}
-
+
for (auto *I : CatDecl->instance_properties())
RewriteProperty(I);
-
+
for (auto *I : CatDecl->instance_methods())
RewriteMethodDeclaration(I);
for (auto *I : CatDecl->class_methods())
RewriteMethodDeclaration(I);
// Lastly, comment out the @end.
- ReplaceText(CatDecl->getAtEndRange().getBegin(),
+ ReplaceText(CatDecl->getAtEndRange().getBegin(),
strlen("@end"), "/* @end */\n");
}
void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
SourceLocation LocStart = PDecl->getLocStart();
assert(PDecl->isThisDeclarationADefinition());
-
+
// FIXME: handle protocol headers that are declared across multiple lines.
ReplaceText(LocStart, 0, "// ");
@@ -1166,7 +1166,7 @@ void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
RewriteMethodDeclaration(I);
for (auto *I : PDecl->instance_properties())
RewriteProperty(I);
-
+
// Lastly, comment out the @end.
SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");
@@ -1196,7 +1196,7 @@ void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
ReplaceText(LocStart, 0, "// ");
}
-void
+void
RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
SourceLocation LocStart = DG[0]->getLocStart();
if (LocStart.isInvalid())
@@ -1390,11 +1390,11 @@ void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
// we haven't seen a forward decl - generate a typedef.
RewriteOneForwardClassDecl(ClassDecl, ResultStr);
RewriteIvarOffsetSymbols(ClassDecl, ResultStr);
-
+
RewriteObjCInternalStruct(ClassDecl, ResultStr);
// Mark this typedef as having been written into its c++ equivalent.
ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());
-
+
for (auto *I : ClassDecl->instance_properties())
RewriteProperty(I);
for (auto *I : ClassDecl->instance_methods())
@@ -1403,7 +1403,7 @@ void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
RewriteMethodDeclaration(I);
// Lastly, comment out the @end.
- ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
+ ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
"/* @end */\n");
}
}
@@ -1431,7 +1431,7 @@ Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseud
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
}
-
+
unsigned numArgs = OldMsg->getNumArgs();
for (unsigned i = 0; i < numArgs; i++) {
Expr *Arg = OldMsg->getArg(i);
@@ -1714,7 +1714,7 @@ Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
else {
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
elementName = DR->getDecl()->getName();
- ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
+ ValueDecl *VD = DR->getDecl();
if (VD->getType()->isObjCQualifiedIdType() ||
VD->getType()->isObjCQualifiedInterfaceType())
// Simply use 'id' for all qualified types.
@@ -1869,11 +1869,11 @@ Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S)
SourceLocation SynchLoc = S->getAtSynchronizedLoc();
ConvertSourceLocationToLineDirective(SynchLoc, buf);
buf += "{ id _rethrow = 0; id _sync_obj = (id)";
-
+
const char *lparenBuf = startBuf;
while (*lparenBuf != '(') lparenBuf++;
ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
-
+
buf = "; objc_sync_enter(_sync_obj);\n";
buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";
buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";
@@ -1887,16 +1887,16 @@ Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S)
const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);
while (*RParenExprLocBuf != ')') RParenExprLocBuf--;
RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);
-
+
SourceLocation LBranceLoc = S->getSynchBody()->getLocStart();
const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);
assert (*LBraceLocBuf == '{');
ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
-
+
SourceLocation startRBraceLoc = S->getSynchBody()->getLocEnd();
assert((*SM->getCharacterData(startRBraceLoc) == '}') &&
"bogus @synchronized block");
-
+
buf = "} catch (id e) {_rethrow = e;}\n";
Write_RethrowObject(buf);
buf += "}\n";
@@ -1923,7 +1923,7 @@ void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
SourceLocation startLoc = S->getAtLoc();
ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");
- ReplaceText(S->getSubStmt()->getLocStart(), 1,
+ ReplaceText(S->getSubStmt()->getLocStart(), 1,
"{ __AtAutoreleasePool __autoreleasepool; ");
return nullptr;
@@ -1935,7 +1935,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
std::string buf;
SourceLocation TryLocation = S->getAtTryLoc();
ConvertSourceLocationToLineDirective(TryLocation, buf);
-
+
if (finalStmt) {
if (noCatch)
buf += "{ id volatile _rethrow = 0;\n";
@@ -1953,11 +1953,11 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
else
// @try -> try
ReplaceText(startLoc, 1, "");
-
+
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
VarDecl *catchDecl = Catch->getCatchParamDecl();
-
+
startLoc = Catch->getLocStart();
bool AtRemoved = false;
if (catchDecl) {
@@ -1968,12 +1968,12 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
if (IDecl) {
std::string Result;
ConvertSourceLocationToLineDirective(Catch->getLocStart(), Result);
-
+
startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @catch location");
SourceLocation rParenLoc = Catch->getRParenLoc();
const char *rParenBuf = SM->getCharacterData(rParenLoc);
-
+
// _objc_exc_Foo *_e as argument to catch.
Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();
Result += " *_"; Result += catchDecl->getNameAsString();
@@ -1986,7 +1986,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
Result += " *"; Result += catchDecl->getNameAsString();
Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";
Result += "_"; Result += catchDecl->getNameAsString();
-
+
Result += "; ";
SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart();
ReplaceText(lBraceLoc, 1, Result);
@@ -1997,12 +1997,12 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
if (!AtRemoved)
// @catch -> catch
ReplaceText(startLoc, 1, "");
-
+
}
if (finalStmt) {
buf.clear();
SourceLocation FinallyLoc = finalStmt->getLocStart();
-
+
if (noCatch) {
ConvertSourceLocationToLineDirective(FinallyLoc, buf);
buf += "catch (id e) {_rethrow = e;}\n";
@@ -2012,7 +2012,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
ConvertSourceLocationToLineDirective(FinallyLoc, buf);
buf += "catch (id e) {_rethrow = e;}\n";
}
-
+
SourceLocation startFinalLoc = finalStmt->getLocStart();
ReplaceText(startFinalLoc, 8, buf);
Stmt *body = finalStmt->getFinallyBody();
@@ -2020,7 +2020,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
buf.clear();
Write_RethrowObject(buf);
ReplaceText(startFinalBodyLoc, 1, buf);
-
+
SourceLocation endFinalBodyLoc = body->getLocEnd();
ReplaceText(endFinalBodyLoc, 1, "}\n}");
// Now check for any return/continue/go statements within the @try.
@@ -2102,7 +2102,7 @@ RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
// Now, we cast the reference to a pointer to the objc_msgSend type.
QualType pToFunc = Context->getPointerType(msgSendType);
- ImplicitCastExpr *ICE =
+ ImplicitCastExpr *ICE =
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
DRE, nullptr, VK_RValue);
@@ -2525,7 +2525,7 @@ void RewriteModernObjC::SynthGetClassFunctionDecl() {
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {
- IdentifierInfo *getSuperClassIdent =
+ IdentifierInfo *getSuperClassIdent =
&Context->Idents.get("class_getSuperclass");
SmallVector<QualType, 16> ArgTys;
ArgTys.push_back(Context->getObjCClassType());
@@ -2590,7 +2590,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_CPointerToObjCPointerCast, Unop);
@@ -2602,13 +2602,13 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {
unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
-
- Expr *FlagExp = IntegerLiteral::Create(*Context,
- llvm::APInt(IntSize, Exp->getValue()),
+
+ Expr *FlagExp = IntegerLiteral::Create(*Context,
+ llvm::APInt(IntSize, Exp->getValue()),
Context->IntTy, Exp->getLocation());
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,
CK_BitCast, FlagExp);
- ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),
+ ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),
cast);
ReplaceStmt(Exp, PE);
return PE;
@@ -2623,25 +2623,25 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
SynthMsgSendFunctionDecl();
if (!GetClassFunctionDecl)
SynthGetClassFunctionDecl();
-
+
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
SourceLocation StartLoc = Exp->getLocStart();
SourceLocation EndLoc = Exp->getLocEnd();
-
+
// Synthesize a call to objc_msgSend().
SmallVector<Expr*, 4> MsgExprs;
SmallVector<Expr*, 4> ClsExprs;
-
+
// Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.
ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();
ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();
-
+
IdentifierInfo *clsName = BoxingClass->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
-
+
// Create a call to sel_registerName("<BoxingMethod>:"), etc.
// it will be the 2nd argument.
SmallVector<Expr*, 4> SelExprs;
@@ -2650,7 +2650,7 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
-
+
// User provided sub-expression is the 3rd, and last, argument.
Expr *subExpr = Exp->getSubExpr();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {
@@ -2662,35 +2662,35 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);
}
MsgExprs.push_back(subExpr);
-
+
SmallVector<QualType, 4> ArgTypes;
ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto PI : BoxingMethod->parameters())
ArgTypes.push_back(PI->getType());
-
+
QualType returnType = Exp->getType();
// Get the type, we will need to reference it in a couple spots.
QualType msgSendType = MsgSendFlavor->getType();
-
+
// Create a reference to the objc_msgSend() declaration.
DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
VK_LValue, SourceLocation());
-
+
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidTy),
CK_BitCast, DRE);
-
+
// Now do the "normal" pointer to function cast.
QualType castType =
getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());
castType = Context->getPointerType(castType);
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
cast);
-
+
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
-
+
const FunctionType *FT = msgSendType->getAs<FunctionType>();
CallExpr *CE = new (Context)
CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
@@ -2707,24 +2707,24 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
SynthMsgSendFunctionDecl();
if (!GetClassFunctionDecl)
SynthGetClassFunctionDecl();
-
+
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
SourceLocation StartLoc = Exp->getLocStart();
SourceLocation EndLoc = Exp->getLocEnd();
-
+
// Build the expression: __NSContainer_literal(int, ...).arr
QualType IntQT = Context->IntTy;
QualType NSArrayFType =
getSimpleFunctionType(Context->VoidTy, IntQT, true);
std::string NSArrayFName("__NSContainer_literal");
FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);
- DeclRefExpr *NSArrayDRE =
+ DeclRefExpr *NSArrayDRE =
new (Context) DeclRefExpr(NSArrayFD, false, NSArrayFType, VK_RValue,
SourceLocation());
SmallVector<Expr*, 16> InitExprs;
unsigned NumElements = Exp->getNumElements();
- unsigned UnsignedIntSize =
+ unsigned UnsignedIntSize =
static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
Expr *count = IntegerLiteral::Create(*Context,
llvm::APInt(UnsignedIntSize, NumElements),
@@ -2732,7 +2732,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
InitExprs.push_back(count);
for (unsigned i = 0; i < NumElements; i++)
InitExprs.push_back(Exp->getElement(i));
- Expr *NSArrayCallExpr =
+ Expr *NSArrayCallExpr =
new (Context) CallExpr(*Context, NSArrayDRE, InitExprs,
NSArrayFType, VK_LValue, SourceLocation());
@@ -2746,27 +2746,27 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
- CStyleCastExpr * ArrayLiteralObjects =
- NoTypeInfoCStyleCastExpr(Context,
+ CStyleCastExpr * ArrayLiteralObjects =
+ NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
CK_BitCast,
ArrayLiteralME);
-
+
// Synthesize a call to objc_msgSend().
SmallVector<Expr*, 32> MsgExprs;
SmallVector<Expr*, 4> ClsExprs;
QualType expType = Exp->getType();
-
+
// Create a call to objc_getClass("NSArray"). It will be th 1st argument.
- ObjCInterfaceDecl *Class =
+ ObjCInterfaceDecl *Class =
expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface();
-
+
IdentifierInfo *clsName = Class->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
-
+
// Create a call to sel_registerName("arrayWithObjects:count:").
// it will be the 2nd argument.
SmallVector<Expr*, 4> SelExprs;
@@ -2776,44 +2776,44 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
-
+
// (const id [])objects
MsgExprs.push_back(ArrayLiteralObjects);
-
+
// (NSUInteger)cnt
Expr *cnt = IntegerLiteral::Create(*Context,
llvm::APInt(UnsignedIntSize, NumElements),
Context->UnsignedIntTy, SourceLocation());
MsgExprs.push_back(cnt);
-
+
SmallVector<QualType, 4> ArgTypes;
ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto *PI : ArrayMethod->parameters())
ArgTypes.push_back(PI->getType());
-
+
QualType returnType = Exp->getType();
// Get the type, we will need to reference it in a couple spots.
QualType msgSendType = MsgSendFlavor->getType();
-
+
// Create a reference to the objc_msgSend() declaration.
DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
VK_LValue, SourceLocation());
-
+
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidTy),
CK_BitCast, DRE);
-
+
// Now do the "normal" pointer to function cast.
QualType castType =
getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());
castType = Context->getPointerType(castType);
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
cast);
-
+
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
-
+
const FunctionType *FT = msgSendType->getAs<FunctionType>();
CallExpr *CE = new (Context)
CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
@@ -2830,26 +2830,26 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
SynthMsgSendFunctionDecl();
if (!GetClassFunctionDecl)
SynthGetClassFunctionDecl();
-
+
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
SourceLocation StartLoc = Exp->getLocStart();
SourceLocation EndLoc = Exp->getLocEnd();
-
+
// Build the expression: __NSContainer_literal(int, ...).arr
QualType IntQT = Context->IntTy;
QualType NSDictFType =
getSimpleFunctionType(Context->VoidTy, IntQT, true);
std::string NSDictFName("__NSContainer_literal");
FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);
- DeclRefExpr *NSDictDRE =
+ DeclRefExpr *NSDictDRE =
new (Context) DeclRefExpr(NSDictFD, false, NSDictFType, VK_RValue,
SourceLocation());
-
+
SmallVector<Expr*, 16> KeyExprs;
SmallVector<Expr*, 16> ValueExprs;
-
+
unsigned NumElements = Exp->getNumElements();
- unsigned UnsignedIntSize =
+ unsigned UnsignedIntSize =
static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
Expr *count = IntegerLiteral::Create(*Context,
llvm::APInt(UnsignedIntSize, NumElements),
@@ -2861,9 +2861,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
KeyExprs.push_back(Element.Key);
ValueExprs.push_back(Element.Value);
}
-
+
// (const id [])objects
- Expr *NSValueCallExpr =
+ Expr *NSValueCallExpr =
new (Context) CallExpr(*Context, NSDictDRE, ValueExprs,
NSDictFType, VK_LValue, SourceLocation());
@@ -2877,13 +2877,13 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
- CStyleCastExpr * DictValueObjects =
- NoTypeInfoCStyleCastExpr(Context,
+ CStyleCastExpr * DictValueObjects =
+ NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
CK_BitCast,
DictLiteralValueME);
// (const id <NSCopying> [])keys
- Expr *NSKeyCallExpr =
+ Expr *NSKeyCallExpr =
new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
NSDictFType, VK_LValue, SourceLocation());
@@ -2891,27 +2891,27 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
- CStyleCastExpr * DictKeyObjects =
- NoTypeInfoCStyleCastExpr(Context,
+ CStyleCastExpr * DictKeyObjects =
+ NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
CK_BitCast,
DictLiteralKeyME);
-
+
// Synthesize a call to objc_msgSend().
SmallVector<Expr*, 32> MsgExprs;
SmallVector<Expr*, 4> ClsExprs;
QualType expType = Exp->getType();
-
+
// Create a call to objc_getClass("NSArray"). It will be th 1st argument.
- ObjCInterfaceDecl *Class =
+ ObjCInterfaceDecl *Class =
expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface();
-
+
IdentifierInfo *clsName = Class->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
-
+
// Create a call to sel_registerName("arrayWithObjects:count:").
// it will be the 2nd argument.
SmallVector<Expr*, 4> SelExprs;
@@ -2920,19 +2920,19 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
-
+
// (const id [])objects
MsgExprs.push_back(DictValueObjects);
-
+
// (const id <NSCopying> [])keys
MsgExprs.push_back(DictKeyObjects);
-
+
// (NSUInteger)cnt
Expr *cnt = IntegerLiteral::Create(*Context,
llvm::APInt(UnsignedIntSize, NumElements),
Context->UnsignedIntTy, SourceLocation());
MsgExprs.push_back(cnt);
-
+
SmallVector<QualType, 8> ArgTypes;
ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
@@ -2945,29 +2945,29 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
}
ArgTypes.push_back(T);
}
-
+
QualType returnType = Exp->getType();
// Get the type, we will need to reference it in a couple spots.
QualType msgSendType = MsgSendFlavor->getType();
-
+
// Create a reference to the objc_msgSend() declaration.
DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
VK_LValue, SourceLocation());
-
+
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidTy),
CK_BitCast, DRE);
-
+
// Now do the "normal" pointer to function cast.
QualType castType =
getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());
castType = Context->getPointerType(castType);
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
cast);
-
+
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
-
+
const FunctionType *FT = msgSendType->getAs<FunctionType>();
CallExpr *CE = new (Context)
CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
@@ -2975,8 +2975,8 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
return CE;
}
-// struct __rw_objc_super {
-// struct objc_object *object; struct objc_object *superClass;
+// struct __rw_objc_super {
+// struct objc_object *object; struct objc_object *superClass;
// };
QualType RewriteModernObjC::getSuperStructType() {
if (!SuperStructDecl) {
@@ -3057,9 +3057,9 @@ static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
}
void RewriteModernObjC::RewriteLineDirective(const Decl *D) {
-
+
SourceLocation Location = D->getLocation();
-
+
if (Location.isFileID() && GenerateLineInfo) {
std::string LineString("\n#line ");
PresumedLoc PLoc = SM->getPresumedLoc(Location);
@@ -3069,7 +3069,7 @@ void RewriteModernObjC::RewriteLineDirective(const Decl *D) {
if (isa<ObjCMethodDecl>(D))
LineString += "\"";
else LineString += "\"\n";
-
+
Location = D->getLocStart();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isExternC() && !FD->isMain()) {
@@ -3091,11 +3091,11 @@ void RewriteModernObjC::RewriteLineDirective(const Decl *D) {
/// msgSendType - function type of objc_msgSend_stret(...)
/// returnType - Result type of the method being synthesized.
/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
-/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
+/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
/// starting with receiver.
/// Method - Method being rewritten.
Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
- QualType returnType,
+ QualType returnType,
SmallVectorImpl<QualType> &ArgTypes,
SmallVectorImpl<Expr*> &MsgExprs,
ObjCMethodDecl *Method) {
@@ -3104,11 +3104,11 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
Method ? Method->isVariadic()
: false);
castType = Context->getPointerType(castType);
-
+
// build type for containing the objc_msgSend_stret object.
static unsigned stretCount=0;
std::string name = "__Stret"; name += utostr(stretCount);
- std::string str =
+ std::string str =
"extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";
str += "namespace {\n";
str += "struct "; str += name;
@@ -3127,13 +3127,13 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
Context->getPrintingPolicy());
str += ", "; str += ArgName;
}
-
+
str += ") {\n";
str += "\t unsigned size = sizeof(";
str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";
-
+
str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n";
-
+
str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());
str += ")(void *)objc_msgSend)(receiver, sel";
for (unsigned i = 2; i < ArgTypes.size(); i++) {
@@ -3144,11 +3144,11 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
str += ", arg"; str += utostr(i);
}
str+= ");\n";
-
+
str += "\t else if (receiver == 0)\n";
str += "\t memset((void*)&s, 0, sizeof(s));\n";
str += "\t else\n";
-
+
str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());
str += ")(void *)objc_msgSend_stret)(receiver, sel";
for (unsigned i = 2; i < ArgTypes.size(); i++) {
@@ -3159,7 +3159,7 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
str += ", arg"; str += utostr(i);
}
str += ");\n";
-
+
str += "\t}\n";
str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
str += " s;\n";
@@ -3174,7 +3174,7 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
InsertText(FunLocStart, str);
++stretCount;
-
+
// AST for __Stretn(receiver, args).s;
IdentifierInfo *ID = &Context->Idents.get(name);
FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
@@ -3266,7 +3266,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ClsExprs.push_back(Cls);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
-
+
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back( // set 'super class', using class_getSuperclass().
@@ -3295,7 +3295,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -3313,7 +3313,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
}
MsgExprs.push_back(SuperRep);
break;
@@ -3350,7 +3350,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
Context->getObjCIdType(),
VK_RValue, SourceLocation()))
); // set the 'receiver'.
-
+
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
@@ -3361,7 +3361,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ClsExprs.push_back(Cls);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
-
+
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back(
@@ -3389,7 +3389,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -3446,7 +3446,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
(void)convertBlockPointerToFunctionPointer(type);
const Expr *SubExpr = ICE->IgnoreParenImpCasts();
CastKind CK;
- if (SubExpr->getType()->isIntegralType(*Context) &&
+ if (SubExpr->getType()->isIntegralType(*Context) &&
type->isBooleanType()) {
CK = CK_IntegralToBoolean;
} else if (type->isObjCObjectPointerType()) {
@@ -3591,7 +3591,7 @@ QualType RewriteModernObjC::getProtocolType() {
/// The forward references (and metadata) are generated in
/// RewriteModernObjC::HandleTranslationUnit().
Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
- std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +
+ std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +
Exp->getProtocol()->getNameAsString();
IdentifierInfo *ID = &Context->Idents.get(Name);
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
@@ -3608,9 +3608,9 @@ Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
return castExpr;
}
-/// IsTagDefinedInsideClass - This routine checks that a named tagged type
-/// is defined inside an objective-c class. If so, it returns true.
-bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,
+/// IsTagDefinedInsideClass - This routine checks that a named tagged type
+/// is defined inside an objective-c class. If so, it returns true.
+bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,
TagDecl *Tag,
bool &IsNamedDefinition) {
if (!IDecl)
@@ -3638,13 +3638,13 @@ bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,
/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.
/// It handles elaborated types, as well as enum types in the process.
-bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
+bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
std::string &Result) {
if (isa<TypedefType>(Type)) {
Result += "\t";
return false;
}
-
+
if (Type->isArrayType()) {
QualType ElemTy = Context->getBaseElementType(Type);
return RewriteObjCFieldDeclType(ElemTy, Result);
@@ -3658,7 +3658,7 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
Result += "\n\tunion ";
else
assert(false && "class not allowed as an ivar type");
-
+
Result += RD->getName();
if (GlobalDefinedTags.count(RD)) {
// struct/union is defined globally, use it.
@@ -3668,7 +3668,7 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
Result += " {\n";
for (auto *FD : RD->fields())
RewriteObjCFieldDecl(FD, Result);
- Result += "\t} ";
+ Result += "\t} ";
return true;
}
}
@@ -3682,7 +3682,7 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
Result += " ";
return true;
}
-
+
Result += " {\n";
for (const auto *EC : ED->enumerators()) {
Result += "\t"; Result += EC->getName(); Result += " = ";
@@ -3690,11 +3690,11 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
Result += Val.toString(10);
Result += ",\n";
}
- Result += "\t} ";
+ Result += "\t} ";
return true;
}
}
-
+
Result += "\t";
convertObjCTypeToCStyleType(Type);
return false;
@@ -3703,12 +3703,12 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.
/// It handles elaborated types, as well as enum types in the process.
-void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
+void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
std::string &Result) {
QualType Type = fieldDecl->getType();
std::string Name = fieldDecl->getNameAsString();
-
- bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
+
+ bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
if (!EleboratedType)
Type.getAsStringInternal(Name, Context->getPrintingPolicy());
Result += Name;
@@ -3727,20 +3727,20 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
AT = Context->getAsArrayType(AT->getElementType());
} while (AT);
}
-
+
Result += ";\n";
}
/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined
/// named aggregate types into the input buffer.
-void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
+void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
std::string &Result) {
QualType Type = fieldDecl->getType();
if (isa<TypedefType>(Type))
return;
if (Type->isArrayType())
Type = Context->getBaseElementType(Type);
- ObjCContainerDecl *IDecl =
+ ObjCContainerDecl *IDecl =
dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
TagDecl *TD = nullptr;
@@ -3750,11 +3750,11 @@ void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDec
else if (Type->isEnumeralType()) {
TD = Type->getAs<EnumType>()->getDecl();
}
-
+
if (TD) {
if (GlobalDefinedTags.count(TD))
return;
-
+
bool IsNamedDefinition = false;
if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {
RewriteObjCFieldDeclType(Type, Result);
@@ -3775,7 +3775,7 @@ unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {
for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar())
IVars.push_back(IVD);
-
+
for (unsigned i = 0, e = IVars.size(); i < e; i++)
if (IVars[i]->isBitField()) {
IvarGroupNumber[IVars[i++]] = ++GroupNo;
@@ -3816,7 +3816,7 @@ QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *
std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);
if (GroupRecordType.count(tuple))
return GroupRecordType[tuple];
-
+
SmallVector<ObjCIvarDecl *, 8> IVars;
for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar()) {
@@ -3840,7 +3840,7 @@ QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *
}
QualType RetQT = GroupRecordType[tuple];
assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");
-
+
return RetQT;
}
@@ -3895,13 +3895,13 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar())
IVars.push_back(IVD);
-
+
SourceLocation LocStart = CDecl->getLocStart();
SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
-
+
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
-
+
// If no ivars and no root or if its root, directly or indirectly,
// have no ivars (thus not synthesized) then no need to synthesize this class.
if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&
@@ -3910,13 +3910,13 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
ReplaceText(LocStart, endBuf-startBuf, Result);
return;
}
-
+
// Insert named struct/union definitions inside class to
// outer scope. This follows semantics of locally defined
// struct/unions in objective-c classes.
for (unsigned i = 0, e = IVars.size(); i < e; i++)
RewriteLocallyDefinedNamedAggregates(IVars[i], Result);
-
+
// Insert named structs which are syntheized to group ivar bitfields
// to outer scope as well.
for (unsigned i = 0, e = IVars.size(); i < e; i++)
@@ -3928,17 +3928,17 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
// skip over ivar bitfields in this group.
SKIP_BITFIELDS(i , e, IVars);
}
-
+
Result += "\nstruct ";
Result += CDecl->getNameAsString();
Result += "_IMPL {\n";
-
+
if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
Result += "\tstruct "; Result += RCDecl->getNameAsString();
Result += "_IMPL "; Result += RCDecl->getNameAsString();
Result += "_IVARS;\n";
}
-
+
for (unsigned i = 0, e = IVars.size(); i < e; i++) {
if (IVars[i]->isBitField()) {
ObjCIvarDecl *IV = IVars[i];
@@ -3984,7 +3984,7 @@ void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
if (LangOpts.MicrosoftExt)
Result += "__declspec(allocate(\".objc_ivar$B\")) ";
Result += "extern \"C\" ";
- if (LangOpts.MicrosoftExt &&
+ if (LangOpts.MicrosoftExt &&
IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&
IvarDecl->getAccessControl() != ObjCIvarDecl::Package)
Result += "__declspec(dllimport) ";
@@ -4031,14 +4031,14 @@ void RewriteModernObjC::RewriteImplementations() {
}
}
-void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
+void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
const std::string &Name,
ValueDecl *VD, bool def) {
- assert(BlockByRefDeclNo.count(VD) &&
+ assert(BlockByRefDeclNo.count(VD) &&
"RewriteByRefString: ByRef decl missing");
if (def)
ResultStr += "struct ";
- ResultStr += "__Block_byref_" + Name +
+ ResultStr += "__Block_byref_" + Name +
"_" + utostr(BlockByRefDeclNo[VD]) ;
}
@@ -4057,7 +4057,7 @@ std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
SourceLocation BlockLoc = CE->getExprLoc();
std::string S;
ConvertSourceLocationToLineDirective(BlockLoc, S);
-
+
S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
funcName.str() + "_block_func_" + utostr(i);
@@ -4132,7 +4132,7 @@ std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
if (HasLocalVariableExternalStorage(*I))
QT = Context->getPointerType(QT);
QT.getAsStringInternal(Name, Context->getPrintingPolicy());
- S += Name + " = __cself->" +
+ S += Name + " = __cself->" +
(*I)->getNameAsString() + "; // bound by copy\n";
}
}
@@ -4168,7 +4168,7 @@ std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
}
S += "}\n";
-
+
S += "\nstatic void __";
S += funcName;
S += "_block_dispose_" + utostr(i);
@@ -4188,7 +4188,7 @@ std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
return S;
}
-std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
+std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
std::string Desc) {
std::string S = "\nstruct " + Tag;
std::string Constructor = " " + Tag;
@@ -4277,7 +4277,7 @@ std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Ta
Constructor += ", ";
Constructor += Name + "(_" + Name + "->__forwarding)";
}
-
+
Constructor += " {\n";
if (GlobalVarDecl)
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
@@ -4303,19 +4303,19 @@ std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Ta
return S;
}
-std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
+std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
std::string ImplTag, int i,
StringRef FunName,
unsigned hasCopy) {
std::string S = "\nstatic struct " + DescTag;
-
+
S += " {\n size_t reserved;\n";
S += " size_t Block_size;\n";
if (hasCopy) {
S += " void (*copy)(struct ";
S += ImplTag; S += "*, struct ";
S += ImplTag; S += "*);\n";
-
+
S += " void (*dispose)(struct ";
S += ImplTag; S += "*);\n";
}
@@ -4343,7 +4343,7 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
SC += "() {}";
InsertText(FunLocStart, SC);
}
-
+
// Insert closures that were part of the function.
for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
CollectBlockDeclRefInfo(Blocks[i]);
@@ -4368,7 +4368,7 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
// imported objects in the inner blocks not used in the outer
// blocks must be copied/disposed in the outer block as well.
- if (VD->getType()->isObjCObjectPointerType() ||
+ if (VD->getType()->isObjCObjectPointerType() ||
VD->getType()->isBlockPointerType())
ImportedBlockDecls.insert(VD);
}
@@ -4415,7 +4415,7 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
}
if (GlobalConstructionExp) {
// extra fancy dance for global literal expression.
-
+
// Always the latest block expression on the block stack.
std::string Tag = "__";
Tag += FunName;
@@ -4424,7 +4424,7 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
std::string globalBuf = "static ";
globalBuf += Tag; globalBuf += " ";
std::string SStr;
-
+
llvm::raw_string_ostream constructorExprBuf(SStr);
GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,
PrintingPolicy(LangOpts));
@@ -4441,7 +4441,7 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
}
void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
- SourceLocation FunLocStart =
+ SourceLocation FunLocStart =
(!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)
: FD->getTypeSpecStartLoc();
StringRef FuncName = FD->getName();
@@ -4528,7 +4528,7 @@ bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {
}
}
}
-
+
convertToUnqualifiedObjCType(T);
return T != oldT;
}
@@ -4544,7 +4544,7 @@ QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT)
SmallVector<QualType, 8> ArgTypes;
QualType Res = FT->getReturnType();
bool modified = convertObjCTypeToCStyleType(Res);
-
+
if (FTP) {
for (auto &I : FTP->param_types()) {
QualType t = I;
@@ -4569,13 +4569,13 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp
CPT = DRE->getType()->getAs<BlockPointerType>();
} else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
CPT = MExpr->getType()->getAs<BlockPointerType>();
- }
+ }
else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
return SynthesizeBlockCall(Exp, PRE->getSubExpr());
}
- else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
+ else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
CPT = IEXPR->getType()->getAs<BlockPointerType>();
- else if (const ConditionalOperator *CEXPR =
+ else if (const ConditionalOperator *CEXPR =
dyn_cast<ConditionalOperator>(BlockExp)) {
Expr *LHSExp = CEXPR->getLHS();
Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
@@ -4676,7 +4676,7 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp
// };
//}
Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
- // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
+ // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
// for each DeclRefExp where BYREFVAR is name of the variable.
ValueDecl *VD = DeclRefExp->getDecl();
bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
@@ -4684,7 +4684,7 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
- &Context->Idents.get("__forwarding"),
+ &Context->Idents.get("__forwarding"),
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
@@ -4694,7 +4694,7 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
- &Context->Idents.get(Name),
+ &Context->Idents.get(Name),
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
@@ -4703,14 +4703,14 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
DeclRefExp->getType(), VK_LValue, OK_Ordinary);
// Need parens to enforce precedence.
- ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
- DeclRefExp->getExprLoc(),
+ ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
+ DeclRefExp->getExprLoc(),
ME);
ReplaceStmt(DeclRefExp, PE);
return PE;
}
-// Rewrites the imported local variable V with external storage
+// Rewrites the imported local variable V with external storage
// (static, extern, etc.) as *V
//
Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
@@ -4720,9 +4720,9 @@ Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
return DRE;
Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
VK_LValue, OK_Ordinary,
- DRE->getLocation());
+ DRE->getLocation(), false);
// Need parens to enforce precedence.
- ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Exp);
ReplaceStmt(DRE, PE);
return PE;
@@ -4771,7 +4771,7 @@ void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
if (CastKind != CK_BlockPointerToObjCPointerCast &&
CastKind != CK_AnyPointerToBlockPointerCast)
return;
-
+
QualType QT = IC->getType();
(void)convertBlockPointerToFunctionPointer(QT);
std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));
@@ -4851,7 +4851,7 @@ bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
I->getPointeeType()->isObjCQualifiedInterfaceType())
return true;
}
-
+
}
return false;
}
@@ -4917,7 +4917,7 @@ void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
}
buf += ')';
OrigLength++;
-
+
if (PointerTypeTakesAnyBlockArguments(DeclT) ||
PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
// Replace the '^' with '*' for arguments.
@@ -4930,7 +4930,7 @@ void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
if (*argListBegin == '^')
buf += '*';
else if (*argListBegin == '<') {
- buf += "/*";
+ buf += "/*";
buf += *argListBegin++;
OrigLength++;
while (*argListBegin != '>') {
@@ -4954,19 +4954,19 @@ void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
/// struct Block_byref_id_object *src) {
-/// _Block_object_assign (&_dest->object, _src->object,
+/// _Block_object_assign (&_dest->object, _src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
/// [|BLOCK_FIELD_IS_WEAK]) // object
-/// _Block_object_assign(&_dest->object, _src->object,
+/// _Block_object_assign(&_dest->object, _src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
/// [|BLOCK_FIELD_IS_WEAK]) // block
/// }
/// And:
/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
-/// _Block_object_dispose(_src->object,
+/// _Block_object_dispose(_src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
/// [|BLOCK_FIELD_IS_WEAK]) // object
-/// _Block_object_dispose(_src->object,
+/// _Block_object_dispose(_src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
/// [|BLOCK_FIELD_IS_WEAK]) // block
/// }
@@ -4980,14 +4980,14 @@ std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
S = "static void __Block_byref_id_object_copy_";
S += utostr(flag);
S += "(void *dst, void *src) {\n";
-
+
// offset into the object pointer is computed as:
// void * + void* + int + int + void* + void *
- unsigned IntSize =
+ unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
- unsigned VoidPtrSize =
+ unsigned VoidPtrSize =
static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
-
+
unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
S += " _Block_object_assign((char*)dst + ";
S += utostr(offset);
@@ -4996,7 +4996,7 @@ std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
S += "), ";
S += utostr(flag);
S += ");\n}\n";
-
+
S += "static void __Block_byref_id_object_dispose_";
S += utostr(flag);
S += "(void *src) {\n";
@@ -5021,8 +5021,8 @@ std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
/// };
///
/// It then replaces declaration of ND variable with:
-/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
-/// __size=sizeof(struct __Block_byref_ND),
+/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
+/// __size=sizeof(struct __Block_byref_ND),
/// ND=initializer-if-any};
///
///
@@ -5048,7 +5048,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
ByrefType += " *__forwarding;\n";
ByrefType += " int __flags;\n";
ByrefType += " int __size;\n";
- // Add void *__Block_byref_id_object_copy;
+ // Add void *__Block_byref_id_object_copy;
// void *__Block_byref_id_object_dispose; if needed.
QualType Ty = ND->getType();
bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
@@ -5060,7 +5060,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
QualType T = Ty;
(void)convertBlockPointerToFunctionPointer(T);
T.getAsStringInternal(Name, Context->getPrintingPolicy());
-
+
ByrefType += " " + Name + ";\n";
ByrefType += "};\n";
// Insert this type in global scope. It is needed by helper function.
@@ -5072,7 +5072,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
FunLocStart = CurMethodDef->getLocStart();
}
InsertText(FunLocStart, ByrefType);
-
+
if (Ty.isObjCGCWeak()) {
flag |= BLOCK_FIELD_IS_WEAK;
isa = 1;
@@ -5089,9 +5089,9 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
if (!HF.empty())
Preamble += HF;
}
-
- // struct __Block_byref_ND ND =
- // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
+
+ // struct __Block_byref_ND ND =
+ // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
// initializer-if-any};
bool hasInit = (ND->getInit() != nullptr);
// FIXME. rewriter does not support __block c++ objects which
@@ -5102,7 +5102,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
if (CXXDecl && CXXDecl->isDefaultConstructor())
hasInit = false;
}
-
+
unsigned flags = 0;
if (HasCopyAndDispose)
flags |= BLOCK_HAS_COPY_DISPOSE;
@@ -5125,7 +5125,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
ByrefType += ", __Block_byref_id_object_dispose_";
ByrefType += utostr(flag);
}
-
+
if (!firstDecl) {
// In multiple __block declarations, and for all but 1st declaration,
// find location of the separating comma. This would be start location
@@ -5139,7 +5139,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);
startBuf = commaBuf;
}
-
+
if (!hasInit) {
ByrefType += "};\n";
unsigned nameSize = Name.size();
@@ -5164,11 +5164,11 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
const char separator = lastDecl ? ';' : ',';
const char *startInitializerBuf = SM->getCharacterData(startLoc);
const char *separatorBuf = strchr(startInitializerBuf, separator);
- assert((*separatorBuf == separator) &&
+ assert((*separatorBuf == separator) &&
"RewriteByRefVar: can't find ';' or ','");
SourceLocation separatorLoc =
startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);
-
+
InsertText(separatorLoc, lastDecl ? "}" : "};\n");
}
}
@@ -5196,7 +5196,7 @@ void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
// Find any imported blocks...they will need special attention.
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
- BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
+ BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
BlockDeclRefs[i]->getType()->isBlockPointerType())
ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
}
@@ -5213,11 +5213,11 @@ FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
const BlockDecl *block = Exp->getBlockDecl();
-
+
Blocks.push_back(Exp);
CollectBlockDeclRefInfo(Exp);
-
+
// Add inner imported variables now used in current block.
int countOfInnerDecls = 0;
if (!InnerBlockDeclRefs.empty()) {
@@ -5243,12 +5243,12 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
// Find any imported blocks...they will need special attention.
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
- InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
+ InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
}
InnerDeclRefsCount.push_back(countOfInnerDecls);
-
+
std::string FuncName;
if (CurFunctionDef)
@@ -5258,14 +5258,14 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
else if (GlobalVarDecl)
FuncName = std::string(GlobalVarDecl->getNameAsString());
- bool GlobalBlockExpr =
+ bool GlobalBlockExpr =
block->getDeclContext()->getRedeclContext()->isFileContext();
-
+
if (GlobalBlockExpr && !GlobalVarDecl) {
Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
GlobalBlockExpr = false;
}
-
+
std::string BlockNumber = utostr(Blocks.size()-1);
std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
@@ -5279,13 +5279,13 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
// Simulate a constructor call...
std::string Tag;
-
+
if (GlobalBlockExpr)
Tag = "__global_";
else
Tag = "__";
Tag += FuncName + "_block_impl_" + BlockNumber;
-
+
FD = SynthBlockInitFunctionDecl(Tag);
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
SourceLocation());
@@ -5310,13 +5310,13 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Context->VoidPtrTy,
VK_LValue,
- SourceLocation()),
+ SourceLocation()),
UO_AddrOf,
- Context->getPointerType(Context->VoidPtrTy),
+ Context->getPointerType(Context->VoidPtrTy),
VK_RValue, OK_Ordinary,
- SourceLocation());
- InitExprs.push_back(DescRefExpr);
-
+ SourceLocation(), false);
+ InitExprs.push_back(DescRefExpr);
+
// Add initializers for any closure decl refs.
if (BlockDeclRefs.size()) {
Expr *Exp;
@@ -5332,7 +5332,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation());
+ OK_Ordinary, SourceLocation(),
+ false);
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -5348,9 +5349,10 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation());
+ OK_Ordinary, SourceLocation(),
+ false);
}
-
+
}
InitExprs.push_back(Exp);
}
@@ -5361,14 +5363,14 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
std::string Name(ND->getNameAsString());
std::string RecName;
RewriteByRefString(RecName, Name, ND, true);
- IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
+ IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
+ sizeof("struct"));
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
SourceLocation(), SourceLocation(),
II);
assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
-
+
FD = SynthBlockInitFunctionDecl((*I)->getName());
Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
SourceLocation());
@@ -5377,7 +5379,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
for (const auto &CI : block->captures()) {
const VarDecl *variable = CI.getVariable();
if (variable == ND && CI.isNested()) {
- assert (CI.isByRef() &&
+ assert (CI.isByRef() &&
"SynthBlockInitExpr - captured block variable is not byref");
isNestedCapturedVar = true;
break;
@@ -5388,7 +5390,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
if (!isNestedCapturedVar)
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
Context->getPointerType(Exp->getType()),
- VK_RValue, OK_Ordinary, SourceLocation());
+ VK_RValue, OK_Ordinary, SourceLocation(),
+ false);
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
InitExprs.push_back(Exp);
}
@@ -5396,31 +5399,31 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
if (ImportedBlockDecls.size()) {
// generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
- unsigned IntSize =
+ unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
- Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
+ Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
Context->IntTy, SourceLocation());
InitExprs.push_back(FlagExp);
}
NewRep = new (Context) CallExpr(*Context, DRE, InitExprs,
FType, VK_LValue, SourceLocation());
-
+
if (GlobalBlockExpr) {
assert (!GlobalConstructionExp &&
"SynthBlockInitExpr - GlobalConstructionExp must be null");
GlobalConstructionExp = NewRep;
NewRep = DRE;
}
-
+
NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
Context->getPointerType(NewRep->getType()),
- VK_RValue, OK_Ordinary, SourceLocation());
+ VK_RValue, OK_Ordinary, SourceLocation(), false);
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
// Put Paren around the call.
NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
NewRep);
-
+
BlockDeclRefs.clear();
BlockByRefDecls.clear();
BlockByRefDeclsPtrSet.clear();
@@ -5431,7 +5434,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
}
bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
- if (const ObjCForCollectionStmt * CS =
+ if (const ObjCForCollectionStmt * CS =
dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
return CS->getElement() == DS;
return false;
@@ -5503,7 +5506,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
RewrittenBlockExprs[BE] = Str;
Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
-
+
//blockTranscribed->dump();
ReplaceStmt(S, blockTranscribed);
return blockTranscribed;
@@ -5517,17 +5520,17 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
return RewriteObjCStringLiteral(AtString);
-
+
if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
return RewriteObjCBoolLiteralExpr(BoolLitExpr);
-
+
if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
return RewriteObjCBoxedExpr(BoxedExpr);
-
+
if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
-
- if (ObjCDictionaryLiteral *DictionaryLitExpr =
+
+ if (ObjCDictionaryLiteral *DictionaryLitExpr =
dyn_cast<ObjCDictionaryLiteral>(S))
return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);
@@ -5554,11 +5557,11 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
return RewriteMessageExpr(MessExpr);
}
- if (ObjCAutoreleasePoolStmt *StmtAutoRelease =
+ if (ObjCAutoreleasePoolStmt *StmtAutoRelease =
dyn_cast<ObjCAutoreleasePoolStmt>(S)) {
return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);
}
-
+
if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
return RewriteObjCTryStmt(StmtTry);
@@ -5592,7 +5595,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// the context of an ObjCForCollectionStmt. For example:
// NSArray *someArray;
// for (id <FooProtocol> index in someArray) ;
- // This is because RewriteObjCForCollectionStmt() does textual rewriting
+ // This is because RewriteObjCForCollectionStmt() does textual rewriting
// and it depends on the original text locations/positions.
if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
@@ -5614,7 +5617,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));
}
- else
+ else
RewriteTypeOfDecl(VD);
}
}
@@ -5640,13 +5643,13 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
}
// Handle blocks rewriting.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
- ValueDecl *VD = DRE->getDecl();
+ ValueDecl *VD = DRE->getDecl();
if (VD->hasAttr<BlocksAttr>())
return RewriteBlockDeclRefExpr(DRE);
if (HasLocalVariableExternalStorage(VD))
return RewriteLocalVariableExternalStorage(DRE);
}
-
+
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
if (CE->getCallee()->getType()->isBlockPointerType()) {
Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
@@ -5809,7 +5812,7 @@ void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
case Decl::CXXRecord:
case Decl::Record: {
RecordDecl *RD = cast<RecordDecl>(D);
- if (RD->isCompleteDefinition())
+ if (RD->isCompleteDefinition())
RewriteRecordBody(RD);
break;
}
@@ -5822,7 +5825,7 @@ void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
/// Write_ProtocolExprReferencedMetadata - This routine writer out the
/// protocol reference symbols in the for of:
/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.
-static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
+static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
ObjCProtocolDecl *PDecl,
std::string &Result) {
// Also output .objc_protorefs$B section and its meta-data.
@@ -5858,10 +5861,10 @@ void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
}
InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
-
+
if (ClassImplementation.size() || CategoryImplementation.size())
RewriteImplementations();
-
+
for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {
ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];
// Write struct declaration for the class matching its ivar declarations.
@@ -5870,7 +5873,7 @@ void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
// private ivars.
RewriteInterfaceDecl(CDecl);
}
-
+
// Get the buffer corresponding to MainFileID. If we haven't changed it, then
// we are done.
if (const RewriteBuffer *RewriteBuf =
@@ -5900,7 +5903,7 @@ void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
void RewriteModernObjC::Initialize(ASTContext &context) {
InitializeCommon(context);
-
+
Preamble += "#ifndef __OBJC2__\n";
Preamble += "#define __OBJC2__\n";
Preamble += "#endif\n";
@@ -5916,7 +5919,7 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";
Preamble += ": object(o), superClass(s) {} ";
Preamble += "\n};\n";
-
+
if (LangOpts.MicrosoftExt) {
// Define all sections using syntax that makes sense.
// These are currently generated.
@@ -5930,13 +5933,13 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";
-
+
// These need be generated for performance. Currently they are not,
// using API calls instead.
Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";
-
+
}
Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
Preamble += "typedef struct objc_object Protocol;\n";
@@ -5945,10 +5948,10 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
if (LangOpts.MicrosoftExt) {
Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
- }
+ }
else
Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
-
+
Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";
Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";
Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";
@@ -6038,7 +6041,7 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
Preamble += "#define __block\n";
Preamble += "#define __weak\n";
}
-
+
// Declarations required for modern objective-c array and dictionary literals.
Preamble += "\n#include <stdarg.h>\n";
Preamble += "struct __NSContainer_literal {\n";
@@ -6055,7 +6058,7 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
Preamble += "\tdelete[] arr;\n";
Preamble += " }\n";
Preamble += "};\n";
-
+
// Declaration required for implementation of @autoreleasepool statement.
Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";
Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";
@@ -6064,7 +6067,7 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";
Preamble += " void * atautoreleasepoolobj;\n";
Preamble += "};\n";
-
+
// NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
// as this avoids warning in any 64bit/32bit compilation model.
Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
@@ -6192,20 +6195,20 @@ static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Re
static bool meta_data_declared = false;
if (meta_data_declared)
return;
-
+
Result += "\nstruct _prop_t {\n";
Result += "\tconst char *name;\n";
Result += "\tconst char *attributes;\n";
Result += "};\n";
-
+
Result += "\nstruct _protocol_t;\n";
-
+
Result += "\nstruct _objc_method {\n";
Result += "\tstruct objc_selector * _cmd;\n";
Result += "\tconst char *method_type;\n";
Result += "\tvoid *_imp;\n";
Result += "};\n";
-
+
Result += "\nstruct _protocol_t {\n";
Result += "\tvoid * isa; // NULL\n";
Result += "\tconst char *protocol_name;\n";
@@ -6219,7 +6222,7 @@ static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Re
Result += "\tconst unsigned int flags; // = 0\n";
Result += "\tconst char ** extendedMethodTypes;\n";
Result += "};\n";
-
+
Result += "\nstruct _ivar_t {\n";
Result += "\tunsigned long int *offset; // pointer to ivar offset location\n";
Result += "\tconst char *name;\n";
@@ -6227,7 +6230,7 @@ static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Re
Result += "\tunsigned int alignment;\n";
Result += "\tunsigned int size;\n";
Result += "};\n";
-
+
Result += "\nstruct _class_ro_t {\n";
Result += "\tunsigned int flags;\n";
Result += "\tunsigned int instanceStart;\n";
@@ -6243,7 +6246,7 @@ static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Re
Result += "\tconst unsigned char *weakIvarLayout;\n";
Result += "\tconst struct _prop_list_t *properties;\n";
Result += "};\n";
-
+
Result += "\nstruct _class_t {\n";
Result += "\tstruct _class_t *isa;\n";
Result += "\tstruct _class_t *superclass;\n";
@@ -6251,7 +6254,7 @@ static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Re
Result += "\tvoid *vtable;\n";
Result += "\tstruct _class_ro_t *ro;\n";
Result += "};\n";
-
+
Result += "\nstruct _category_t {\n";
Result += "\tconst char *name;\n";
Result += "\tstruct _class_t *cls;\n";
@@ -6260,7 +6263,7 @@ static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Re
Result += "\tconst struct _protocol_list_t *protocols;\n";
Result += "\tconst struct _prop_list_t *properties;\n";
Result += "};\n";
-
+
Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";
Result += "#pragma warning(disable:4273)\n";
meta_data_declared = true;
@@ -6313,12 +6316,12 @@ static void Write_protocol_list_initializer(ASTContext *Context, std::string &Re
Result += "\nstatic ";
Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());
Result += " "; Result += VarName;
- Result += ProtocolName;
+ Result += ProtocolName;
Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";
for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {
ObjCProtocolDecl *SuperPD = SuperProtocols[i];
- Result += "\t&"; Result += "_OBJC_PROTOCOL_";
+ Result += "\t&"; Result += "_OBJC_PROTOCOL_";
Result += SuperPD->getNameAsString();
if (i == e-1)
Result += "\n};\n";
@@ -6338,7 +6341,7 @@ static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
Result += "\nstatic ";
Write_method_list_t_TypeDecl(Result, Methods.size());
Result += " "; Result += VarName;
- Result += TopLevelDeclName;
+ Result += TopLevelDeclName;
Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
@@ -6378,7 +6381,7 @@ static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
Result += "\nstatic ";
Write__prop_list_t_TypeDecl(Result, Properties.size());
Result += " "; Result += VarName;
- Result += ProtocolName;
+ Result += ProtocolName;
Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";
Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";
@@ -6410,16 +6413,16 @@ enum MetaDataDlags {
CLS_ROOT = 0x2,
OBJC2_CLS_HIDDEN = 0x10,
CLS_EXCEPTION = 0x20,
-
+
/// (Obsolete) ARC-specific: this class has a .release_ivars method
CLS_HAS_IVAR_RELEASER = 0x40,
/// class was compiled with -fobjc-arr
CLS_COMPILED_BY_ARC = 0x80 // (1<<7)
};
-static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
- unsigned int flags,
- const std::string &InstanceStart,
+static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
+ unsigned int flags,
+ const std::string &InstanceStart,
const std::string &InstanceSize,
ArrayRef<ObjCMethodDecl *>baseMethods,
ArrayRef<ObjCProtocolDecl *>baseProtocols,
@@ -6430,8 +6433,8 @@ static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Resu
Result += "\nstatic struct _class_ro_t ";
Result += VarName; Result += ClassName;
Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
- Result += "\t";
- Result += llvm::utostr(flags); Result += ", ";
+ Result += "\t";
+ Result += llvm::utostr(flags); Result += ", ";
Result += InstanceStart; Result += ", ";
Result += InstanceSize; Result += ", \n";
Result += "\t";
@@ -6489,7 +6492,7 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
const ObjCInterfaceDecl *CDecl, bool metaclass) {
bool rootClass = (!CDecl->getSuperClass());
const ObjCInterfaceDecl *RootClass = CDecl;
-
+
if (!rootClass) {
// Find the Root class
RootClass = CDecl->getSuperClass();
@@ -6506,7 +6509,7 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
Result += "__declspec(dllexport) ";
else
Result += "__declspec(dllimport) ";
-
+
Result += "struct _class_t OBJC_CLASS_$_";
Result += CDecl->getNameAsString();
Result += ";\n";
@@ -6521,11 +6524,11 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
else
Result += "__declspec(dllimport) ";
- Result += "struct _class_t ";
+ Result += "struct _class_t ";
Result += VarName;
Result += SuperClass->getNameAsString();
Result += ";\n";
-
+
if (metaclass && RootClass != SuperClass) {
Result += "extern \"C\" ";
if (RootClass->getImplementation())
@@ -6533,14 +6536,14 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
else
Result += "__declspec(dllimport) ";
- Result += "struct _class_t ";
+ Result += "struct _class_t ";
Result += VarName;
Result += RootClass->getNameAsString();
Result += ";\n";
}
}
-
- Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
+
+ Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
Result += VarName; Result += CDecl->getNameAsString();
Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";
Result += "\t";
@@ -6554,7 +6557,7 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
Result += ",\n\t";
}
else {
- Result += "0, // &"; Result += VarName;
+ Result += "0, // &"; Result += VarName;
Result += CDecl->getNameAsString();
Result += ",\n\t";
Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();
@@ -6562,7 +6565,7 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
}
}
else {
- Result += "0, // &OBJC_METACLASS_$_";
+ Result += "0, // &OBJC_METACLASS_$_";
Result += CDecl->getNameAsString();
Result += ",\n\t";
if (!rootClass) {
@@ -6570,7 +6573,7 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
Result += CDecl->getSuperClass()->getNameAsString();
Result += ",\n\t";
}
- else
+ else
Result += "0,\n\t";
}
Result += "0, // (void *)&_objc_empty_cache,\n\t";
@@ -6581,22 +6584,22 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
Result += "&_OBJC_CLASS_RO_$_";
Result += CDecl->getNameAsString();
Result += ",\n};\n";
-
+
// Add static function to initialize some of the meta-data fields.
// avoid doing it twice.
if (metaclass)
return;
-
- const ObjCInterfaceDecl *SuperClass =
+
+ const ObjCInterfaceDecl *SuperClass =
rootClass ? CDecl : CDecl->getSuperClass();
-
+
Result += "static void OBJC_CLASS_SETUP_$_";
Result += CDecl->getNameAsString();
Result += "(void ) {\n";
Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
Result += RootClass->getNameAsString(); Result += ";\n";
-
+
Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
Result += ".superclass = ";
if (rootClass)
@@ -6605,26 +6608,26 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
Result += "&OBJC_METACLASS_$_";
Result += SuperClass->getNameAsString(); Result += ";\n";
-
+
Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
-
+
Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
Result += CDecl->getNameAsString(); Result += ";\n";
-
+
if (!rootClass) {
Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
Result += ".superclass = "; Result += "&OBJC_CLASS_$_";
Result += SuperClass->getNameAsString(); Result += ";\n";
}
-
+
Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
Result += "}\n";
}
-static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
+static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
std::string &Result,
ObjCCategoryDecl *CatDecl,
ObjCInterfaceDecl *ClassDecl,
@@ -6634,7 +6637,7 @@ static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
ArrayRef<ObjCPropertyDecl *> ClassProperties) {
StringRef CatName = CatDecl->getName();
StringRef ClassName = ClassDecl->getName();
- // must declare an extern class object in case this class is not implemented
+ // must declare an extern class object in case this class is not implemented
// in this TU.
Result += "\n";
Result += "extern \"C\" ";
@@ -6642,11 +6645,11 @@ static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
Result += "__declspec(dllexport) ";
else
Result += "__declspec(dllimport) ";
-
+
Result += "struct _class_t ";
Result += "OBJC_CLASS_$_"; Result += ClassName;
Result += ";\n";
-
+
Result += "\nstatic struct _category_t ";
Result += "_OBJC_$_CATEGORY_";
Result += ClassName; Result += "_$_"; Result += CatName;
@@ -6656,32 +6659,32 @@ static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;
Result += ",\n";
if (InstanceMethods.size() > 0) {
- Result += "\t(const struct _method_list_t *)&";
+ Result += "\t(const struct _method_list_t *)&";
Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
-
+
if (ClassMethods.size() > 0) {
- Result += "\t(const struct _method_list_t *)&";
+ Result += "\t(const struct _method_list_t *)&";
Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
-
+
if (RefedProtocols.size() > 0) {
- Result += "\t(const struct _protocol_list_t *)&";
+ Result += "\t(const struct _protocol_list_t *)&";
Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
-
+
if (ClassProperties.size() > 0) {
Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";
Result += ClassName; Result += "_$_"; Result += CatName;
@@ -6689,16 +6692,16 @@ static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
}
else
Result += "\t0,\n";
-
+
Result += "};\n";
-
+
// Add static function to initialize the class pointer in the category structure.
Result += "static void OBJC_CATEGORY_SETUP_$_";
Result += ClassDecl->getNameAsString();
Result += "_$_";
Result += CatName;
Result += "(void ) {\n";
- Result += "\t_OBJC_$_CATEGORY_";
+ Result += "\t_OBJC_$_CATEGORY_";
Result += ClassDecl->getNameAsString();
Result += "_$_";
Result += CatName;
@@ -6713,7 +6716,7 @@ static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj
StringRef ProtocolName) {
if (Methods.size() == 0)
return;
-
+
Result += "\nstatic const char *";
Result += VarName; Result += ProtocolName;
Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
@@ -6735,8 +6738,8 @@ static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj
static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,
ASTContext *Context,
- std::string &Result,
- ArrayRef<ObjCIvarDecl *> Ivars,
+ std::string &Result,
+ ArrayRef<ObjCIvarDecl *> Ivars,
ObjCInterfaceDecl *CDecl) {
// FIXME. visibilty of offset symbols may have to be set; for Darwin
// this is what happens:
@@ -6744,21 +6747,21 @@ static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,
if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
Ivar->getAccessControl() == ObjCIvarDecl::Package ||
Class->getVisibility() == HiddenVisibility)
- Visibility shoud be: HiddenVisibility;
+ Visibility should be: HiddenVisibility;
else
- Visibility shoud be: DefaultVisibility;
+ Visibility should be: DefaultVisibility;
*/
-
+
Result += "\n";
for (unsigned i =0, e = Ivars.size(); i < e; i++) {
ObjCIvarDecl *IvarDecl = Ivars[i];
if (Context->getLangOpts().MicrosoftExt)
Result += "__declspec(allocate(\".objc_ivar$B\")) ";
-
+
if (!Context->getLangOpts().MicrosoftExt ||
IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||
IvarDecl->getAccessControl() == ObjCIvarDecl::Package)
- Result += "extern \"C\" unsigned long int ";
+ Result += "extern \"C\" unsigned long int ";
else
Result += "extern \"C\" __declspec(dllexport) unsigned long int ";
if (Ivars[i]->isBitField())
@@ -6796,7 +6799,7 @@ static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
else
Ivars.push_back(OriginalIvars[i]);
}
-
+
Result += "\nstatic ";
Write__ivar_list_t_TypeDecl(Result, Ivars.size());
Result += " "; Result += VarName;
@@ -6816,24 +6819,24 @@ static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
else
WriteInternalIvarName(CDecl, IvarDecl, Result);
Result += ", ";
-
+
Result += "\"";
if (Ivars[i]->isBitField())
RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);
else
Result += IvarDecl->getName();
Result += "\", ";
-
+
QualType IVQT = IvarDecl->getType();
if (IvarDecl->isBitField())
IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);
-
+
std::string IvarTypeString, QuoteIvarTypeString;
Context->getObjCEncodingForType(IVQT, IvarTypeString,
IvarDecl);
RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);
Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";
-
+
// FIXME. this alignment represents the host alignment and need be changed to
// represent the target alignment.
unsigned Align = Context->getTypeAlign(IVQT)/8;
@@ -6851,21 +6854,21 @@ static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
}
/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
-void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
+void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
std::string &Result) {
-
+
// Do not synthesize the protocol more than once.
if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
return;
WriteModernMetadataDeclarations(Context, Result);
-
+
if (ObjCProtocolDecl *Def = PDecl->getDefinition())
PDecl = Def;
// Must write out all protocol definitions in current qualifier list,
// and in their nested qualifiers before writing out current definition.
for (auto *I : PDecl->protocols())
RewriteObjCProtocolMetaData(I, Result);
-
+
// Construct method lists.
std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
@@ -6876,7 +6879,7 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
InstanceMethods.push_back(MD);
}
}
-
+
for (auto *MD : PDecl->class_methods()) {
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptClassMethods.push_back(MD);
@@ -6899,27 +6902,27 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
"_OBJC_PROTOCOL_METHOD_TYPES_",
PDecl->getNameAsString());
// Protocol's super protocol list
- SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());
+ SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());
Write_protocol_list_initializer(Context, Result, SuperProtocols,
"_OBJC_PROTOCOL_REFS_",
PDecl->getNameAsString());
-
- Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
+
+ Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
"_OBJC_PROTOCOL_INSTANCE_METHODS_",
PDecl->getNameAsString(), false);
-
- Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
+
+ Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
"_OBJC_PROTOCOL_CLASS_METHODS_",
PDecl->getNameAsString(), false);
- Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
+ Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
"_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
PDecl->getNameAsString(), false);
-
- Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
+
+ Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
"_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
PDecl->getNameAsString(), false);
-
+
// Protocol's property metadata.
SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(
PDecl->instance_properties());
@@ -6944,43 +6947,43 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
else
Result += "\t0,\n";
if (InstanceMethods.size() > 0) {
- Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
+ Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
Result += PDecl->getNameAsString(); Result += ",\n";
}
else
Result += "\t0,\n";
if (ClassMethods.size() > 0) {
- Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
+ Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
Result += PDecl->getNameAsString(); Result += ",\n";
}
else
Result += "\t0,\n";
-
+
if (OptInstanceMethods.size() > 0) {
- Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
+ Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
Result += PDecl->getNameAsString(); Result += ",\n";
}
else
Result += "\t0,\n";
-
+
if (OptClassMethods.size() > 0) {
- Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
+ Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
Result += PDecl->getNameAsString(); Result += ",\n";
}
else
Result += "\t0,\n";
-
+
if (ProtocolProperties.size() > 0) {
- Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
+ Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
Result += PDecl->getNameAsString(); Result += ",\n";
}
else
Result += "\t0,\n";
-
+
Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";
Result += "\t0,\n";
-
+
if (AllMethods.size() > 0) {
Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";
Result += PDecl->getNameAsString();
@@ -6988,14 +6991,14 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
}
else
Result += "\t0\n};\n";
-
+
if (LangOpts.MicrosoftExt)
Result += "static ";
Result += "struct _protocol_t *";
Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
Result += ";\n";
-
+
// Mark this protocol as having been generated.
if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
llvm_unreachable("protocol already synthesized");
@@ -7016,15 +7019,15 @@ static bool hasObjCExceptionAttribute(ASTContext &Context,
void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
std::string &Result) {
ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
-
+
// Explicitly declared @interface's are already synthesized.
if (CDecl->isImplicitInterfaceDecl())
- assert(false &&
+ assert(false &&
"Legacy implicit interface rewriting not supported in moder abi");
-
+
WriteModernMetadataDeclarations(Context, Result);
SmallVector<ObjCIvarDecl *, 8> IVars;
-
+
for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar()) {
// Ignore unnamed bit-fields.
@@ -7032,14 +7035,14 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
continue;
IVars.push_back(IVD);
}
-
- Write__ivar_list_t_initializer(*this, Context, Result, IVars,
+
+ Write__ivar_list_t_initializer(*this, Context, Result, IVars,
"_OBJC_$_INSTANCE_VARIABLES_",
CDecl);
-
+
// Build _objc_method_list for class's instance methods if needed
SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
-
+
// If any of our property implementations have associated getters or
// setters, produce metadata for them as well.
for (const auto *Prop : IDecl->property_impls()) {
@@ -7059,17 +7062,17 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
InstanceMethods.push_back(Setter);
}
-
+
Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
"_OBJC_$_INSTANCE_METHODS_",
IDecl->getNameAsString(), true);
-
+
SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
-
+
Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
"_OBJC_$_CLASS_METHODS_",
IDecl->getNameAsString(), true);
-
+
// Protocols referenced in class declaration?
// Protocol's super protocol list
std::vector<ObjCProtocolDecl *> RefedProtocols;
@@ -7082,12 +7085,12 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
// and in their nested qualifiers before writing out current definition.
RewriteObjCProtocolMetaData(*I, Result);
}
-
- Write_protocol_list_initializer(Context, Result,
+
+ Write_protocol_list_initializer(Context, Result,
RefedProtocols,
"_OBJC_CLASS_PROTOCOLS_$_",
IDecl->getNameAsString());
-
+
// Protocol's property metadata.
SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
CDecl->instance_properties());
@@ -7095,22 +7098,22 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
/* Container */IDecl,
"_OBJC_$_PROP_LIST_",
CDecl->getNameAsString());
-
+
// Data for initializing _class_ro_t metaclass meta-data
uint32_t flags = CLS_META;
std::string InstanceSize;
std::string InstanceStart;
-
+
bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
-
+
if (!CDecl->getSuperClass())
// class is root
flags |= CLS_ROOT;
InstanceSize = "sizeof(struct _class_t)";
InstanceStart = InstanceSize;
- Write__class_ro_t_initializer(Context, Result, flags,
+ Write__class_ro_t_initializer(Context, Result, flags,
InstanceStart, InstanceSize,
ClassMethods,
nullptr,
@@ -7123,14 +7126,14 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
flags = CLS;
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
-
+
if (hasObjCExceptionAttribute(*Context, CDecl))
flags |= CLS_EXCEPTION;
if (!CDecl->getSuperClass())
// class is root
flags |= CLS_ROOT;
-
+
InstanceSize.clear();
InstanceStart.clear();
if (!ObjCSynthesizedStructs.count(CDecl)) {
@@ -7141,15 +7144,15 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
InstanceSize = "sizeof(struct ";
InstanceSize += CDecl->getNameAsString();
InstanceSize += "_IMPL)";
-
+
ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
if (IVD) {
RewriteIvarOffsetComputation(IVD, InstanceStart);
}
- else
+ else
InstanceStart = InstanceSize;
}
- Write__class_ro_t_initializer(Context, Result, flags,
+ Write__class_ro_t_initializer(Context, Result, flags,
InstanceStart, InstanceSize,
InstanceMethods,
RefedProtocols,
@@ -7157,15 +7160,15 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
ClassProperties,
"_OBJC_CLASS_RO_$_",
CDecl->getNameAsString());
-
+
Write_class_t(Context, Result,
"OBJC_METACLASS_$_",
CDecl, /*metaclass*/true);
-
+
Write_class_t(Context, Result,
"OBJC_CLASS_$_",
CDecl, /*metaclass*/false);
-
+
if (ImplementationIsNonLazy(IDecl))
DefinedNonLazyClasses.push_back(CDecl);
}
@@ -7189,25 +7192,25 @@ void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {
void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
int ClsDefCount = ClassImplementation.size();
int CatDefCount = CategoryImplementation.size();
-
+
// For each implemented class, write out all its meta data.
for (int i = 0; i < ClsDefCount; i++)
RewriteObjCClassMetaData(ClassImplementation[i], Result);
-
+
RewriteClassSetupInitHook(Result);
-
+
// For each implemented category, write out all its meta data.
for (int i = 0; i < CatDefCount; i++)
RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
-
+
RewriteCategorySetupInitHook(Result);
-
+
if (ClsDefCount > 0) {
if (LangOpts.MicrosoftExt)
Result += "__declspec(allocate(\".objc_classlist$B\")) ";
Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";
Result += llvm::utostr(ClsDefCount); Result += "]";
- Result +=
+ Result +=
" __attribute__((used, section (\"__DATA, __objc_classlist,"
"regular,no_dead_strip\")))= {\n";
for (int i = 0; i < ClsDefCount; i++) {
@@ -7216,7 +7219,7 @@ void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
Result += ",\n";
}
Result += "};\n";
-
+
if (!DefinedNonLazyClasses.empty()) {
if (LangOpts.MicrosoftExt)
Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";
@@ -7228,34 +7231,34 @@ void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
Result += "};\n";
}
}
-
+
if (CatDefCount > 0) {
if (LangOpts.MicrosoftExt)
Result += "__declspec(allocate(\".objc_catlist$B\")) ";
Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
Result += llvm::utostr(CatDefCount); Result += "]";
- Result +=
+ Result +=
" __attribute__((used, section (\"__DATA, __objc_catlist,"
"regular,no_dead_strip\")))= {\n";
for (int i = 0; i < CatDefCount; i++) {
Result += "\t&_OBJC_$_CATEGORY_";
- Result +=
- CategoryImplementation[i]->getClassInterface()->getNameAsString();
+ Result +=
+ CategoryImplementation[i]->getClassInterface()->getNameAsString();
Result += "_$_";
Result += CategoryImplementation[i]->getNameAsString();
Result += ",\n";
}
Result += "};\n";
}
-
+
if (!DefinedNonLazyCategories.empty()) {
if (LangOpts.MicrosoftExt)
Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";
Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";
for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {
Result += "\t&_OBJC_$_CATEGORY_";
- Result +=
- DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
+ Result +=
+ DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
Result += "_$_";
Result += DefinedNonLazyCategories[i]->getNameAsString();
Result += ",\n";
@@ -7267,7 +7270,7 @@ void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
void RewriteModernObjC::WriteImageInfo(std::string &Result) {
if (LangOpts.MicrosoftExt)
Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";
-
+
Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";
// version 0, ObjCABI is 2
Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";
@@ -7282,14 +7285,14 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
// Find category declaration for this implementation.
ObjCCategoryDecl *CDecl
= ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
-
+
std::string FullCategoryName = ClassDecl->getNameAsString();
FullCategoryName += "_$_";
FullCategoryName += CDecl->getNameAsString();
-
+
// Build _objc_method_list for class's instance methods if needed
SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
-
+
// If any of our property implementations have associated getters or
// setters, produce metadata for them as well.
for (const auto *Prop : IDecl->property_impls()) {
@@ -7307,17 +7310,17 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
InstanceMethods.push_back(Setter);
}
-
+
Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
"_OBJC_$_CATEGORY_INSTANCE_METHODS_",
FullCategoryName, true);
-
+
SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
-
+
Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
"_OBJC_$_CATEGORY_CLASS_METHODS_",
FullCategoryName, true);
-
+
// Protocols referenced in class declaration?
// Protocol's super protocol list
SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());
@@ -7325,12 +7328,12 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
// Must write out all protocol definitions in current qualifier list,
// and in their nested qualifiers before writing out current definition.
RewriteObjCProtocolMetaData(I, Result);
-
- Write_protocol_list_initializer(Context, Result,
+
+ Write_protocol_list_initializer(Context, Result,
RefedProtocols,
"_OBJC_CATEGORY_PROTOCOLS_$_",
FullCategoryName);
-
+
// Protocol's property metadata.
SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
CDecl->instance_properties());
@@ -7338,7 +7341,7 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
/* Container */IDecl,
"_OBJC_$_PROP_LIST_",
FullCategoryName);
-
+
Write_category_t(*this, Context, Result,
CDecl,
ClassDecl,
@@ -7346,7 +7349,7 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
ClassMethods,
RefedProtocols,
ClassProperties);
-
+
// Determine if this category is also "non-lazy".
if (ImplementationIsNonLazy(IDecl))
DefinedNonLazyCategories.push_back(CDecl);
@@ -7382,7 +7385,7 @@ void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
StringRef ClassName,
std::string &Result) {
if (MethodBegin == MethodEnd) return;
-
+
if (!objc_impl_method) {
/* struct _objc_method {
SEL _cmd;
@@ -7395,12 +7398,12 @@ void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
Result += "\tchar *method_types;\n";
Result += "\tvoid *_imp;\n";
Result += "};\n";
-
+
objc_impl_method = true;
}
-
+
// Build _objc_method_list for class's methods if needed
-
+
/* struct {
struct _objc_method_list *next_method;
int method_count;
@@ -7429,7 +7432,7 @@ void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
Result += IsInstanceMethod ? "inst" : "cls";
Result += "_meth\")))= ";
Result += "{\n\t0, " + utostr(NumMethods) + "\n";
-
+
Result += "\t,{{(SEL)\"";
Result += (*MethodBegin)->getSelector().getAsString().c_str();
std::string MethodTypeString;
@@ -7456,18 +7459,18 @@ void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
SourceRange OldRange = IV->getSourceRange();
Expr *BaseExpr = IV->getBase();
-
+
// Rewrite the base, but without actually doing replaces.
{
DisableReplaceStmtScope S(*this);
BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
IV->setBase(BaseExpr);
}
-
+
ObjCIvarDecl *D = IV->getDecl();
-
+
Expr *Replacement = IV;
-
+
if (BaseExpr->getType()->isObjCObjectPointerType()) {
const ObjCInterfaceType *iFaceDecl =
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
@@ -7477,18 +7480,18 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
clsDeclared);
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
+
// Build name of symbol holding ivar offset.
std::string IvarOffsetName;
if (D->isBitField())
ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
else
WriteInternalIvarName(clsDeclared, D, IvarOffsetName);
-
+
ReferencedIvars[clsDeclared].insert(D);
-
+
// cast offset to "char *".
- CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->CharTy),
CK_BitCast,
BaseExpr);
@@ -7499,8 +7502,8 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false,
Context->UnsignedLongTy, VK_LValue,
SourceLocation());
- BinaryOperator *addExpr =
- new (Context) BinaryOperator(castExpr, DRE, BO_Add,
+ BinaryOperator *addExpr =
+ new (Context) BinaryOperator(castExpr, DRE, BO_Add,
Context->getPointerType(Context->CharTy),
VK_RValue, OK_Ordinary, SourceLocation(), FPOptions());
// Don't forget the parens to enforce the proper binding.
@@ -7516,7 +7519,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
RD = RD->getDefinition();
if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
// decltype(((Foo_IMPL*)0)->bar) *
- ObjCContainerDecl *CDecl =
+ ObjCContainerDecl *CDecl =
dyn_cast<ObjCContainerDecl>(D->getDeclContext());
// ivar in class extensions requires special treatment.
if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
@@ -7527,7 +7530,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
*Context, TTK_Struct, TUDecl, SourceLocation(), SourceLocation(),
&Context->Idents.get(RecName));
QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
- unsigned UnsignedIntSize =
+ unsigned UnsignedIntSize =
static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
Expr *Zero = IntegerLiteral::Create(*Context,
llvm::APInt(UnsignedIntSize, 0),
@@ -7549,20 +7552,20 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
}
convertObjCTypeToCStyleType(IvarT);
QualType castT = Context->getPointerType(IvarT);
-
- castExpr = NoTypeInfoCStyleCastExpr(Context,
+
+ castExpr = NoTypeInfoCStyleCastExpr(Context,
castT,
CK_BitCast,
PE);
-
-
+
+
Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT,
VK_LValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
PE = new (Context) ParenExpr(OldRange.getBegin(),
OldRange.getEnd(),
Exp);
-
+
if (D->isBitField()) {
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -7579,9 +7582,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
else
Replacement = PE;
}
-
+
ReplaceStmtWithRange(IV, Replacement, OldRange);
- return Replacement;
+ return Replacement;
}
#endif // CLANG_ENABLE_OBJC_REWRITER
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 096b81bc3f08..6229351e8f54 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -42,7 +42,7 @@ namespace {
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
block, ... */
BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
- BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
+ BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
__block variable */
BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
helpers */
@@ -50,7 +50,7 @@ namespace {
support routines */
BLOCK_BYREF_CURRENT_MAX = 256
};
-
+
enum {
BLOCK_NEEDS_FREE = (1 << 24),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
@@ -60,7 +60,7 @@ namespace {
BLOCK_HAS_DESCRIPTOR = (1 << 29)
};
static const int OBJC_ABI_VERSION = 7;
-
+
Rewriter Rewrite;
DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
@@ -74,7 +74,7 @@ namespace {
std::string InFileName;
std::unique_ptr<raw_ostream> OutFile;
std::string Preamble;
-
+
TypeDecl *ProtocolTypeDecl;
VarDecl *GlobalVarDecl;
unsigned RewriteFailedDiag;
@@ -85,13 +85,13 @@ namespace {
// ObjC foreach break/continue generation support.
int BcLabelCount;
-
+
unsigned TryFinallyContainsReturnDiag;
// Needed for super.
ObjCMethodDecl *CurMethodDef;
RecordDecl *SuperStructDecl;
RecordDecl *ConstantStringDecl;
-
+
FunctionDecl *MsgSendFunctionDecl;
FunctionDecl *MsgSendSuperFunctionDecl;
FunctionDecl *MsgSendStretFunctionDecl;
@@ -117,14 +117,14 @@ namespace {
SmallVector<int, 8> ObjCBcLabelNo;
// Remember all the @protocol(<expr>) expressions.
llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
-
+
llvm::DenseSet<uint64_t> CopyDestroyCache;
// Block expressions.
SmallVector<BlockExpr *, 32> Blocks;
SmallVector<int, 32> InnerDeclRefsCount;
SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
-
+
SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
// Block related declarations.
@@ -135,7 +135,7 @@ namespace {
llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
-
+
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
// This maps an original source AST to it's rewritten form. This allows
@@ -147,12 +147,12 @@ namespace {
bool IsHeader;
bool SilenceRewriteMacroWarning;
bool objc_impl_method;
-
+
bool DisableReplaceStmt;
class DisableReplaceStmtScope {
RewriteObjC &R;
bool SavedValue;
-
+
public:
DisableReplaceStmtScope(RewriteObjC &R)
: R(R), SavedValue(R.DisableReplaceStmt) {
@@ -262,7 +262,7 @@ namespace {
void RewriteInclude();
void RewriteForwardClassDecl(DeclGroupRef D);
void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
- void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
+ void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
const std::string &typedefString);
void RewriteImplementations();
void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
@@ -289,7 +289,7 @@ namespace {
void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
void RewriteTypeOfDecl(VarDecl *VD);
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
-
+
// Expression Rewriting.
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
@@ -309,17 +309,17 @@ namespace {
Stmt *RewriteBreakStmt(BreakStmt *S);
Stmt *RewriteContinueStmt(ContinueStmt *S);
void RewriteCastExpr(CStyleCastExpr *CE);
-
+
// Block rewriting.
void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
-
+
// Block specific rewrite rules.
void RewriteBlockPointerDecl(NamedDecl *VD);
void RewriteByRefVar(VarDecl *VD);
Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
-
+
void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result);
@@ -339,12 +339,12 @@ namespace {
std::string &Result) = 0;
virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
std::string &Result) = 0;
-
+
// Rewriting ivar access
virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
std::string &Result) = 0;
-
+
// Misc. AST transformation routines. Sometimes they end up calling
// rewriting routines on the new ASTs.
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
@@ -352,15 +352,15 @@ namespace {
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
- QualType msgSendType,
- QualType returnType,
+ QualType msgSendType,
+ QualType returnType,
SmallVectorImpl<QualType> &ArgTypes,
SmallVectorImpl<Expr*> &MsgExprs,
ObjCMethodDecl *Method);
Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
-
+
void SynthCountByEnumWithState(std::string &buf);
void SynthMsgSendFunctionDecl();
void SynthMsgSendSuperFunctionDecl();
@@ -372,15 +372,15 @@ namespace {
void SynthGetSuperClassFunctionDecl();
void SynthSelGetUidFunctionDecl();
void SynthSuperConstructorFunctionDecl();
-
+
std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
StringRef funcName, std::string Tag);
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
StringRef funcName, std::string Tag);
- std::string SynthesizeBlockImpl(BlockExpr *CE,
+ std::string SynthesizeBlockImpl(BlockExpr *CE,
std::string Tag, std::string Desc);
- std::string SynthesizeBlockDescriptor(std::string DescTag,
+ std::string SynthesizeBlockDescriptor(std::string DescTag,
std::string ImplTag,
int i, StringRef funcName,
unsigned hasCopy);
@@ -423,13 +423,13 @@ namespace {
}
return false;
}
-
+
bool needToScanForQualifiers(QualType T);
QualType getSuperStructType();
QualType getConstantStringStructType();
QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
-
+
void convertToUnqualifiedObjCType(QualType &T) {
if (T->isObjCQualifiedIdType())
T = Context->getObjCIdType();
@@ -445,7 +445,7 @@ namespace {
}
}
}
-
+
// FIXME: This predicate seems like it would be useful to add to ASTContext.
bool isObjCType(QualType T) {
if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
@@ -468,7 +468,7 @@ namespace {
bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
void GetExtentOfArgList(const char *Name, const char *&LParen,
const char *&RParen);
-
+
void QuoteDoublequotes(std::string &From, std::string &To) {
for (unsigned i = 0; i < From.length(); i++) {
if (From[i] == '"')
@@ -504,7 +504,7 @@ namespace {
/*Pascal=*/false, StrType, SourceLocation());
}
};
-
+
class RewriteObjCFragileABI : public RewriteObjC {
public:
RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
@@ -688,7 +688,7 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
DG.push_back(*DI);
else
break;
-
+
++DI;
} while (DI != DIEnd);
RewriteForwardClassDecl(DG);
@@ -707,14 +707,14 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
DG.push_back(*DI);
else
break;
-
+
++DI;
} while (DI != DIEnd);
RewriteForwardProtocolDecl(DG);
continue;
}
}
-
+
HandleTopLevelSingleDecl(*DI);
++DI;
}
@@ -790,7 +790,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
unsigned Attributes = PD->getPropertyAttributes();
if (!PD->getGetterMethodDecl()->isDefined()) {
bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
- (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy));
std::string Getr;
if (GenGetProperty && !objcGetPropertyDefined) {
@@ -799,7 +799,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Getr = "\nextern \"C\" __declspec(dllimport) "
"id objc_getProperty(id, SEL, long, bool);\n";
}
- RewriteObjCMethodDecl(OID->getContainingInterface(),
+ RewriteObjCMethodDecl(OID->getContainingInterface(),
PD->getGetterMethodDecl(), Getr);
Getr += "{ ";
// Synthesize an explicit cast to gain access to the ivar.
@@ -813,7 +813,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Getr += " _TYPE";
if (FPRetType) {
Getr += ")"; // close the precedence "scope" for "*".
-
+
// Now, emit the argument types (if any).
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
Getr += "(";
@@ -843,13 +843,13 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Getr += "; }";
InsertText(onePastSemiLoc, Getr);
}
-
+
if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
return;
// Generate the 'setter' function.
std::string Setr;
- bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy);
if (GenSetProperty && !objcSetPropertyDefined) {
objcSetPropertyDefined = true;
@@ -857,8 +857,8 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Setr = "\nextern \"C\" __declspec(dllimport) "
"void objc_setProperty (id, SEL, long, id, bool, bool);\n";
}
-
- RewriteObjCMethodDecl(OID->getContainingInterface(),
+
+ RewriteObjCMethodDecl(OID->getContainingInterface(),
PD->getSetterMethodDecl(), Setr);
Setr += "{ ";
// Synthesize an explicit cast to initialize the ivar.
@@ -903,9 +903,9 @@ void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
const std::string &typedefString) {
SourceLocation startLoc = ClassDecl->getLocStart();
const char *startBuf = SM->getCharacterData(startLoc);
- const char *semiPtr = strchr(startBuf, ';');
+ const char *semiPtr = strchr(startBuf, ';');
// Replace the @class with typedefs corresponding to the classes.
- ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
+ ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
}
void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
@@ -971,21 +971,21 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
ReplaceText(LocStart, 0, "// ");
for (auto *I : CatDecl->instance_properties())
- RewriteProperty(I);
+ RewriteProperty(I);
for (auto *I : CatDecl->instance_methods())
RewriteMethodDeclaration(I);
for (auto *I : CatDecl->class_methods())
RewriteMethodDeclaration(I);
// Lastly, comment out the @end.
- ReplaceText(CatDecl->getAtEndRange().getBegin(),
+ ReplaceText(CatDecl->getAtEndRange().getBegin(),
strlen("@end"), "/* @end */");
}
void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
SourceLocation LocStart = PDecl->getLocStart();
assert(PDecl->isThisDeclarationADefinition());
-
+
// FIXME: handle protocol headers that are declared across multiple lines.
ReplaceText(LocStart, 0, "// ");
@@ -995,7 +995,7 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
RewriteMethodDeclaration(I);
for (auto *I : PDecl->instance_properties())
RewriteProperty(I);
-
+
// Lastly, comment out the @end.
SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
ReplaceText(LocEnd, strlen("@end"), "/* @end */");
@@ -1025,7 +1025,7 @@ void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
ReplaceText(LocStart, 0, "// ");
}
-void
+void
RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
SourceLocation LocStart = DG[0]->getLocStart();
if (LocStart.isInvalid())
@@ -1220,7 +1220,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
RewriteMethodDeclaration(I);
// Lastly, comment out the @end.
- ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
+ ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
"/* @end */");
}
@@ -1502,7 +1502,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
else {
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
elementName = DR->getDecl()->getName();
- ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
+ ValueDecl *VD = DR->getDecl();
if (VD->getType()->isObjCQualifiedIdType() ||
VD->getType()->isObjCQualifiedInterfaceType())
// Simply use 'id' for all qualified types.
@@ -1677,7 +1677,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
buf += "}\n";
buf += "{ /* implicit finally clause */\n";
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
-
+
std::string syncBuf;
syncBuf += " objc_sync_exit(";
@@ -1695,7 +1695,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts));
syncBuf += syncExprBuf.str();
syncBuf += ");";
-
+
buf += syncBuf;
buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
buf += "}\n";
@@ -1724,8 +1724,8 @@ void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
}
}
-void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
-{
+void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
+{
// Perform a bottom up traversal of all children.
for (Stmt *SubStmt : S->children())
if (SubStmt)
@@ -1750,7 +1750,7 @@ void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
std::string buf;
buf = "{ objc_exception_try_exit(&_stack); return";
-
+
ReplaceText(startLoc, 6, buf);
InsertText(onePastSemiLoc, "}");
}
@@ -1774,7 +1774,7 @@ void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
buf = "{ objc_exception_try_exit(&_stack);";
buf += syncExitBuf;
buf += " return";
-
+
ReplaceText(startLoc, 6, buf);
InsertText(onePastSemiLoc, "}");
}
@@ -1930,7 +1930,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
buf += "}";
ReplaceText(lastCurlyLoc, 1, buf);
-
+
// Now check for any return/continue/go statements within the @try.
// The implicit finally clause won't called if the @try contains any
// jump statements.
@@ -2446,7 +2446,7 @@ void RewriteObjC::SynthGetClassFunctionDecl() {
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
void RewriteObjC::SynthGetSuperClassFunctionDecl() {
- IdentifierInfo *getSuperClassIdent =
+ IdentifierInfo *getSuperClassIdent =
&Context->Idents.get("class_getSuperclass");
SmallVector<QualType, 16> ArgTys;
ArgTys.push_back(Context->getObjCClassType());
@@ -2511,7 +2511,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_CPointerToObjCPointerCast, Unop);
@@ -2583,8 +2583,8 @@ QualType RewriteObjC::getConstantStringStructType() {
}
CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
- QualType msgSendType,
- QualType returnType,
+ QualType msgSendType,
+ QualType returnType,
SmallVectorImpl<QualType> &ArgTypes,
SmallVectorImpl<Expr*> &MsgExprs,
ObjCMethodDecl *Method) {
@@ -2603,10 +2603,10 @@ CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavo
castType = Context->getPointerType(castType);
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
cast);
-
+
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
-
+
const FunctionType *FT = msgSendType->getAs<FunctionType>();
CallExpr *STCE = new (Context) CallExpr(
*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, SourceLocation());
@@ -2712,7 +2712,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -2730,7 +2730,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
}
MsgExprs.push_back(SuperRep);
break;
@@ -2764,7 +2764,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
Context->getObjCIdType(),
VK_RValue, SourceLocation()))
); // set the 'receiver'.
-
+
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
@@ -2778,7 +2778,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
-
+
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back(
@@ -2806,7 +2806,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -2863,7 +2863,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
(void)convertBlockPointerToFunctionPointer(type);
const Expr *SubExpr = ICE->IgnoreParenImpCasts();
CastKind CK;
- if (SubExpr->getType()->isIntegralType(*Context) &&
+ if (SubExpr->getType()->isIntegralType(*Context) &&
type->isBooleanType()) {
CK = CK_IntegralToBoolean;
} else if (type->isObjCObjectPointerType()) {
@@ -2968,9 +2968,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// call to objc_msgSend_stret and hang both varieties on a conditional
// expression which dictate which one to envoke depending on size of
// method's return type.
-
- CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
- msgSendType, returnType,
+
+ CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
+ msgSendType, returnType,
ArgTypes, MsgExprs,
Exp->getMethodDecl());
@@ -2990,7 +2990,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
llvm::APInt(IntSize, 8),
Context->IntTy,
SourceLocation());
- BinaryOperator *lessThanExpr =
+ BinaryOperator *lessThanExpr =
new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
VK_RValue, OK_Ordinary, SourceLocation(),
FPOptions());
@@ -3000,7 +3000,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation(), CE,
SourceLocation(), STCE,
returnType, VK_RValue, OK_Ordinary);
- ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
CondExpr);
}
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
@@ -3045,7 +3045,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
VK_LValue, SourceLocation());
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()),
- VK_RValue, OK_Ordinary, SourceLocation());
+ VK_RValue, OK_Ordinary, SourceLocation(), false);
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
CK_BitCast,
DerefExpr);
@@ -3232,14 +3232,14 @@ void RewriteObjC::RewriteImplementations() {
RewriteImplementationDecl(CategoryImplementation[i]);
}
-void RewriteObjC::RewriteByRefString(std::string &ResultStr,
+void RewriteObjC::RewriteByRefString(std::string &ResultStr,
const std::string &Name,
ValueDecl *VD, bool def) {
- assert(BlockByRefDeclNo.count(VD) &&
+ assert(BlockByRefDeclNo.count(VD) &&
"RewriteByRefString: ByRef decl missing");
if (def)
ResultStr += "struct ";
- ResultStr += "__Block_byref_" + Name +
+ ResultStr += "__Block_byref_" + Name +
"_" + utostr(BlockByRefDeclNo[VD]) ;
}
@@ -3329,7 +3329,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
if (HasLocalVariableExternalStorage(*I))
QT = Context->getPointerType(QT);
QT.getAsStringInternal(Name, Context->getPrintingPolicy());
- S += Name + " = __cself->" +
+ S += Name + " = __cself->" +
(*I)->getNameAsString() + "; // bound by copy\n";
}
}
@@ -3365,7 +3365,7 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
}
S += "}\n";
-
+
S += "\nstatic void __";
S += funcName;
S += "_block_dispose_" + utostr(i);
@@ -3385,7 +3385,7 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
return S;
}
-std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
+std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
std::string Desc) {
std::string S = "\nstruct " + Tag;
std::string Constructor = " " + Tag;
@@ -3474,7 +3474,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
Constructor += ", ";
Constructor += Name + "(_" + Name + "->__forwarding)";
}
-
+
Constructor += " {\n";
if (GlobalVarDecl)
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
@@ -3500,19 +3500,19 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
return S;
}
-std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
+std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
std::string ImplTag, int i,
StringRef FunName,
unsigned hasCopy) {
std::string S = "\nstatic struct " + DescTag;
-
+
S += " {\n unsigned long reserved;\n";
S += " unsigned long Block_size;\n";
if (hasCopy) {
S += " void (*copy)(struct ";
S += ImplTag; S += "*, struct ";
S += ImplTag; S += "*);\n";
-
+
S += " void (*dispose)(struct ";
S += ImplTag; S += "*);\n";
}
@@ -3543,7 +3543,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
SC += "() {}";
InsertText(FunLocStart, SC);
}
-
+
// Insert closures that were part of the function.
for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
CollectBlockDeclRefInfo(Blocks[i]);
@@ -3564,7 +3564,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
// imported objects in the inner blocks not used in the outer
// blocks must be copied/disposed in the outer block as well.
if (VD->hasAttr<BlocksAttr>() ||
- VD->getType()->isObjCObjectPointerType() ||
+ VD->getType()->isObjCObjectPointerType() ||
VD->getType()->isBlockPointerType())
ImportedBlockDecls.insert(VD);
}
@@ -3609,7 +3609,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
SC += "restrict ";
InsertText(FunLocStart, SC);
}
-
+
Blocks.clear();
InnerDeclRefsCount.clear();
InnerDeclRefs.clear();
@@ -3697,7 +3697,7 @@ QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
SmallVector<QualType, 8> ArgTypes;
QualType Res = FT->getReturnType();
bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
-
+
if (FTP) {
for (auto &I : FTP->param_types()) {
QualType t = I;
@@ -3724,13 +3724,13 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
CPT = DRE->getType()->getAs<BlockPointerType>();
} else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
CPT = MExpr->getType()->getAs<BlockPointerType>();
- }
+ }
else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
return SynthesizeBlockCall(Exp, PRE->getSubExpr());
}
- else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
+ else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
CPT = IEXPR->getType()->getAs<BlockPointerType>();
- else if (const ConditionalOperator *CEXPR =
+ else if (const ConditionalOperator *CEXPR =
dyn_cast<ConditionalOperator>(BlockExp)) {
Expr *LHSExp = CEXPR->getLHS();
Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
@@ -3831,7 +3831,7 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
// };
//}
Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
- // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
+ // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
// for each DeclRefExp where BYREFVAR is name of the variable.
ValueDecl *VD = DeclRefExp->getDecl();
bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
@@ -3839,7 +3839,7 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
- &Context->Idents.get("__forwarding"),
+ &Context->Idents.get("__forwarding"),
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
@@ -3849,7 +3849,7 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
- &Context->Idents.get(Name),
+ &Context->Idents.get(Name),
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
@@ -3858,14 +3858,14 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
DeclRefExp->getType(), VK_LValue, OK_Ordinary);
// Need parens to enforce precedence.
- ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
- DeclRefExp->getExprLoc(),
+ ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
+ DeclRefExp->getExprLoc(),
ME);
ReplaceStmt(DeclRefExp, PE);
return PE;
}
-// Rewrites the imported local variable V with external storage
+// Rewrites the imported local variable V with external storage
// (static, extern, etc.) as *V
//
Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
@@ -3875,9 +3875,9 @@ Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
return DRE;
Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
VK_LValue, OK_Ordinary,
- DRE->getLocation());
+ DRE->getLocation(), false);
// Need parens to enforce precedence.
- ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Exp);
ReplaceStmt(DRE, PE);
return PE;
@@ -3991,7 +3991,7 @@ bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
I->getPointeeType()->isObjCQualifiedInterfaceType())
return true;
}
-
+
}
return false;
}
@@ -4057,7 +4057,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
}
buf += ')';
OrigLength++;
-
+
if (PointerTypeTakesAnyBlockArguments(DeclT) ||
PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
// Replace the '^' with '*' for arguments.
@@ -4070,7 +4070,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
if (*argListBegin == '^')
buf += '*';
else if (*argListBegin == '<') {
- buf += "/*";
+ buf += "/*";
buf += *argListBegin++;
OrigLength++;
while (*argListBegin != '>') {
@@ -4094,19 +4094,19 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
/// struct Block_byref_id_object *src) {
-/// _Block_object_assign (&_dest->object, _src->object,
+/// _Block_object_assign (&_dest->object, _src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
/// [|BLOCK_FIELD_IS_WEAK]) // object
-/// _Block_object_assign(&_dest->object, _src->object,
+/// _Block_object_assign(&_dest->object, _src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
/// [|BLOCK_FIELD_IS_WEAK]) // block
/// }
/// And:
/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
-/// _Block_object_dispose(_src->object,
+/// _Block_object_dispose(_src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
/// [|BLOCK_FIELD_IS_WEAK]) // object
-/// _Block_object_dispose(_src->object,
+/// _Block_object_dispose(_src->object,
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
/// [|BLOCK_FIELD_IS_WEAK]) // block
/// }
@@ -4120,14 +4120,14 @@ std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
S = "static void __Block_byref_id_object_copy_";
S += utostr(flag);
S += "(void *dst, void *src) {\n";
-
+
// offset into the object pointer is computed as:
// void * + void* + int + int + void* + void *
- unsigned IntSize =
+ unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
- unsigned VoidPtrSize =
+ unsigned VoidPtrSize =
static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
-
+
unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
S += " _Block_object_assign((char*)dst + ";
S += utostr(offset);
@@ -4136,7 +4136,7 @@ std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
S += "), ";
S += utostr(flag);
S += ");\n}\n";
-
+
S += "static void __Block_byref_id_object_dispose_";
S += utostr(flag);
S += "(void *src) {\n";
@@ -4161,8 +4161,8 @@ std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
/// };
///
/// It then replaces declaration of ND variable with:
-/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
-/// __size=sizeof(struct __Block_byref_ND),
+/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
+/// __size=sizeof(struct __Block_byref_ND),
/// ND=initializer-if-any};
///
///
@@ -4191,7 +4191,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
ByrefType += " *__forwarding;\n";
ByrefType += " int __flags;\n";
ByrefType += " int __size;\n";
- // Add void *__Block_byref_id_object_copy;
+ // Add void *__Block_byref_id_object_copy;
// void *__Block_byref_id_object_dispose; if needed.
QualType Ty = ND->getType();
bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
@@ -4203,7 +4203,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
QualType T = Ty;
(void)convertBlockPointerToFunctionPointer(T);
T.getAsStringInternal(Name, Context->getPrintingPolicy());
-
+
ByrefType += " " + Name + ";\n";
ByrefType += "};\n";
// Insert this type in global scope. It is needed by helper function.
@@ -4219,7 +4219,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
flag |= BLOCK_FIELD_IS_WEAK;
isa = 1;
}
-
+
if (HasCopyAndDispose) {
flag = BLOCK_BYREF_CALLER;
QualType Ty = ND->getType();
@@ -4232,9 +4232,9 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
if (!HF.empty())
InsertText(FunLocStart, HF);
}
-
- // struct __Block_byref_ND ND =
- // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
+
+ // struct __Block_byref_ND ND =
+ // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
// initializer-if-any};
bool hasInit = (ND->getInit() != nullptr);
unsigned flags = 0;
@@ -4294,13 +4294,13 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
ByrefType += ", ";
}
ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
-
+
// Complete the newly synthesized compound expression by inserting a right
// curly brace before the end of the declaration.
// FIXME: This approach avoids rewriting the initializer expression. It
// also assumes there is only one declarator. For example, the following
// isn't currently supported by this routine (in general):
- //
+ //
// double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
//
const char *startInitializerBuf = SM->getCharacterData(startLoc);
@@ -4336,7 +4336,7 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
// Find any imported blocks...they will need special attention.
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
- BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
+ BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
BlockDeclRefs[i]->getType()->isBlockPointerType())
ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
}
@@ -4356,7 +4356,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
Blocks.push_back(Exp);
CollectBlockDeclRefInfo(Exp);
-
+
// Add inner imported variables now used in current block.
int countOfInnerDecls = 0;
if (!InnerBlockDeclRefs.empty()) {
@@ -4382,12 +4382,12 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
// Find any imported blocks...they will need special attention.
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
- InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
+ InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
}
InnerDeclRefsCount.push_back(countOfInnerDecls);
-
+
std::string FuncName;
if (CurFunctionDef)
@@ -4434,13 +4434,13 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Context->VoidPtrTy,
VK_LValue,
- SourceLocation()),
+ SourceLocation()),
UO_AddrOf,
- Context->getPointerType(Context->VoidPtrTy),
+ Context->getPointerType(Context->VoidPtrTy),
VK_RValue, OK_Ordinary,
- SourceLocation());
- InitExprs.push_back(DescRefExpr);
-
+ SourceLocation(), false);
+ InitExprs.push_back(DescRefExpr);
+
// Add initializers for any closure decl refs.
if (BlockDeclRefs.size()) {
Expr *Exp;
@@ -4456,7 +4456,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation());
+ OK_Ordinary, SourceLocation(),
+ false);
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -4472,7 +4473,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation());
+ OK_Ordinary, SourceLocation(),
+ false);
}
}
InitExprs.push_back(Exp);
@@ -4484,14 +4486,14 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
std::string Name(ND->getNameAsString());
std::string RecName;
RewriteByRefString(RecName, Name, ND, true);
- IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
+ IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
+ sizeof("struct"));
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
SourceLocation(), SourceLocation(),
II);
assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
-
+
FD = SynthBlockInitFunctionDecl((*I)->getName());
Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
SourceLocation());
@@ -4500,7 +4502,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
for (const auto &CI : block->captures()) {
const VarDecl *variable = CI.getVariable();
if (variable == ND && CI.isNested()) {
- assert (CI.isByRef() &&
+ assert (CI.isByRef() &&
"SynthBlockInitExpr - captured block variable is not byref");
isNestedCapturedVar = true;
break;
@@ -4509,9 +4511,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
// captured nested byref variable has its address passed. Do not take
// its address again.
if (!isNestedCapturedVar)
- Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
- Context->getPointerType(Exp->getType()),
- VK_RValue, OK_Ordinary, SourceLocation());
+ Exp = new (Context) UnaryOperator(
+ Exp, UO_AddrOf, Context->getPointerType(Exp->getType()), VK_RValue,
+ OK_Ordinary, SourceLocation(), false);
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
InitExprs.push_back(Exp);
}
@@ -4519,9 +4521,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
if (ImportedBlockDecls.size()) {
// generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
- unsigned IntSize =
+ unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
- Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
+ Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
Context->IntTy, SourceLocation());
InitExprs.push_back(FlagExp);
}
@@ -4529,7 +4531,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
FType, VK_LValue, SourceLocation());
NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
Context->getPointerType(NewRep->getType()),
- VK_RValue, OK_Ordinary, SourceLocation());
+ VK_RValue, OK_Ordinary, SourceLocation(), false);
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
BlockDeclRefs.clear();
@@ -4542,7 +4544,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
}
bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
- if (const ObjCForCollectionStmt * CS =
+ if (const ObjCForCollectionStmt * CS =
dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
return CS->getElement() == DS;
return false;
@@ -4612,7 +4614,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
RewrittenBlockExprs[BE] = Str;
Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
-
+
//blockTranscribed->dump();
ReplaceStmt(S, blockTranscribed);
return blockTranscribed;
@@ -4683,7 +4685,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// the context of an ObjCForCollectionStmt. For example:
// NSArray *someArray;
// for (id <FooProtocol> index in someArray) ;
- // This is because RewriteObjCForCollectionStmt() does textual rewriting
+ // This is because RewriteObjCForCollectionStmt() does textual rewriting
// and it depends on the original text locations/positions.
if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
@@ -4703,7 +4705,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
RewriteByRefVar(VD);
}
- else
+ else
RewriteTypeOfDecl(VD);
}
}
@@ -4729,13 +4731,13 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
}
// Handle blocks rewriting.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
- ValueDecl *VD = DRE->getDecl();
+ ValueDecl *VD = DRE->getDecl();
if (VD->hasAttr<BlocksAttr>())
return RewriteBlockDeclRefExpr(DRE);
if (HasLocalVariableExternalStorage(VD))
return RewriteLocalVariableExternalStorage(DRE);
}
-
+
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
if (CE->getCallee()->getType()->isBlockPointerType()) {
Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
@@ -4892,7 +4894,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
case Decl::CXXRecord:
case Decl::Record: {
RecordDecl *RD = cast<RecordDecl>(D);
- if (RD->isCompleteDefinition())
+ if (RD->isCompleteDefinition())
RewriteRecordBody(RD);
break;
}
@@ -4940,7 +4942,7 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
void RewriteObjCFragileABI::Initialize(ASTContext &context) {
InitializeCommon(context);
-
+
// declaring objc_selector outside the parameter list removes a silly
// scope related warning...
if (IsHeader)
@@ -5077,7 +5079,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
ObjCProtocolDecl *PDecl, StringRef prefix,
StringRef ClassName, std::string &Result) {
static bool objc_protocol_methods = false;
-
+
// Output struct protocol_methods holder of method selector and type.
if (!objc_protocol_methods && PDecl->hasDefinition()) {
/* struct protocol_methods {
@@ -5089,16 +5091,16 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
Result += "\tstruct objc_selector *_cmd;\n";
Result += "\tchar *method_types;\n";
Result += "};\n";
-
+
objc_protocol_methods = true;
}
// Do not synthesize the protocol more than once.
if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
return;
-
+
if (ObjCProtocolDecl *Def = PDecl->getDefinition())
PDecl = Def;
-
+
if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
PDecl->instmeth_end());
@@ -5115,7 +5117,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
Result += PDecl->getNameAsString();
Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
"{\n\t" + utostr(NumMethods) + "\n";
-
+
// Output instance methods declared in this protocol.
for (ObjCProtocolDecl::instmeth_iterator
I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
@@ -5132,7 +5134,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
}
Result += "\t }\n};\n";
}
-
+
// Output class methods declared in this protocol.
unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
PDecl->classmeth_end());
@@ -5152,7 +5154,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
"{\n\t";
Result += utostr(NumMethods);
Result += "\n";
-
+
// Output instance methods declared in this protocol.
for (ObjCProtocolDecl::classmeth_iterator
I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
@@ -5169,7 +5171,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
}
Result += "\t }\n};\n";
}
-
+
// Output:
/* struct _objc_protocol {
// Objective-C 1.0 extensions
@@ -5189,10 +5191,10 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
Result += "};\n";
-
+
objc_protocol = true;
}
-
+
Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
Result += PDecl->getNameAsString();
Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
@@ -5214,7 +5216,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
else
Result += "0\n";
Result += "};\n";
-
+
// Mark this protocol as having been generated.
if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
llvm_unreachable("protocol already synthesized");
@@ -5225,10 +5227,10 @@ void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
StringRef prefix, StringRef ClassName,
std::string &Result) {
if (Protocols.empty()) return;
-
+
for (unsigned i = 0; i != Protocols.size(); i++)
RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
-
+
// Output the top lovel protocol meta-data for the class.
/* struct _objc_protocol_list {
struct _objc_protocol_list *next;
@@ -5249,11 +5251,11 @@ void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
"{\n\t0, ";
Result += utostr(Protocols.size());
Result += "\n";
-
+
Result += "\t,{&_OBJC_PROTOCOL_";
Result += Protocols[0]->getNameAsString();
Result += " \n";
-
+
for (unsigned i = 1; i != Protocols.size(); i++) {
Result += "\t ,&_OBJC_PROTOCOL_";
Result += Protocols[i]->getNameAsString();
@@ -5265,14 +5267,14 @@ void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
std::string &Result) {
ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
-
+
// Explicitly declared @interface's are already synthesized.
if (CDecl->isImplicitInterfaceDecl()) {
// FIXME: Implementation of a class with no @interface (legacy) does not
// produce correct synthesis as yet.
RewriteObjCInternalStruct(CDecl, Result);
}
-
+
// Build _objc_ivar_list metadata for classes ivars if needed
unsigned NumIvars = !IDecl->ivar_empty()
? IDecl->ivar_size()
@@ -5291,10 +5293,10 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
Result += "\tchar *ivar_type;\n";
Result += "\tint ivar_offset;\n";
Result += "};\n";
-
+
objc_ivar = true;
}
-
+
/* struct {
int ivar_count;
struct _objc_ivar ivar_list[nIvars];
@@ -5310,7 +5312,7 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
"{\n\t";
Result += utostr(NumIvars);
Result += "\n";
-
+
ObjCInterfaceDecl::ivar_iterator IVI, IVE;
SmallVector<ObjCIvarDecl *, 8> IVars;
if (!IDecl->ivar_empty()) {
@@ -5344,13 +5346,13 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
RewriteIvarOffsetComputation(*IVI, Result);
Result += "}\n";
}
-
+
Result += "\t }\n};\n";
}
-
+
// Build _objc_method_list for class's instance methods if needed
SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
-
+
// If any of our property implementations have associated getters or
// setters, produce metadata for them as well.
for (const auto *Prop : IDecl->property_impls()) {
@@ -5372,15 +5374,15 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
}
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
true, "", IDecl->getName(), Result);
-
+
// Build _objc_method_list for class's class methods if needed
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
false, "", IDecl->getName(), Result);
-
+
// Protocols referenced in class declaration?
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
"CLASS", CDecl->getName(), Result);
-
+
// Declaration of class/meta-class metadata
/* struct _objc_class {
struct _objc_class *isa; // or const char *root_class_name when metadata
@@ -5415,7 +5417,7 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
Result += "};\n";
objc_class = true;
}
-
+
// Meta-class metadata generation.
ObjCInterfaceDecl *RootClass = nullptr;
ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
@@ -5424,14 +5426,14 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
SuperClass = SuperClass->getSuperClass();
}
SuperClass = CDecl->getSuperClass();
-
+
Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
Result += CDecl->getNameAsString();
Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
"{\n\t(struct _objc_class *)\"";
Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
Result += "\"";
-
+
if (SuperClass) {
Result += ", \"";
Result += SuperClass->getNameAsString();
@@ -5462,7 +5464,7 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
else
Result += "\t,0,0,0,0\n";
Result += "};\n";
-
+
// class metadata generation.
Result += "\nstatic struct _objc_class _OBJC_CLASS_";
Result += CDecl->getNameAsString();
@@ -5520,15 +5522,15 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
int ClsDefCount = ClassImplementation.size();
int CatDefCount = CategoryImplementation.size();
-
+
// For each implemented class, write out all its meta data.
for (int i = 0; i < ClsDefCount; i++)
RewriteObjCClassMetaData(ClassImplementation[i], Result);
-
+
// For each implemented category, write out all its meta data.
for (int i = 0; i < CatDefCount; i++)
RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
-
+
// Write objc_symtab metadata
/*
struct _objc_symtab
@@ -5540,7 +5542,7 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
void *defs[cls_def_cnt + cat_def_cnt];
};
*/
-
+
Result += "\nstruct _objc_symtab {\n";
Result += "\tlong sel_ref_cnt;\n";
Result += "\tSEL *refs;\n";
@@ -5548,7 +5550,7 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
Result += "\tshort cat_def_cnt;\n";
Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
Result += "};\n\n";
-
+
Result += "static struct _objc_symtab "
"_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
Result += "\t0, 0, " + utostr(ClsDefCount)
@@ -5558,7 +5560,7 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
Result += ClassImplementation[i]->getNameAsString();
Result += "\n";
}
-
+
for (int i = 0; i < CatDefCount; i++) {
Result += "\t,&_OBJC_CATEGORY_";
Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
@@ -5566,11 +5568,11 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
Result += CategoryImplementation[i]->getNameAsString();
Result += "\n";
}
-
+
Result += "};\n\n";
-
+
// Write objc_module metadata
-
+
/*
struct _objc_module {
long version;
@@ -5579,7 +5581,7 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
struct _objc_symtab *symtab;
}
*/
-
+
Result += "\nstruct _objc_module {\n";
Result += "\tlong version;\n";
Result += "\tlong size;\n";
@@ -5591,7 +5593,7 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
Result += "\t" + utostr(OBJC_ABI_VERSION) +
", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Result += "};\n\n";
-
+
if (LangOpts.MicrosoftExt) {
if (ProtocolExprDecls.size()) {
Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
@@ -5621,14 +5623,14 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
// Find category declaration for this implementation.
ObjCCategoryDecl *CDecl
= ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
-
+
std::string FullCategoryName = ClassDecl->getNameAsString();
FullCategoryName += '_';
FullCategoryName += IDecl->getNameAsString();
-
+
// Build _objc_method_list for class's instance methods if needed
SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
-
+
// If any of our property implementations have associated getters or
// setters, produce metadata for them as well.
for (const auto *Prop : IDecl->property_impls()) {
@@ -5670,7 +5672,7 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
// @property decl.
};
*/
-
+
static bool objc_category = false;
if (!objc_category) {
Result += "\nstruct _objc_category {\n";
@@ -5691,7 +5693,7 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
Result += "\"\n\t, \"";
Result += ClassDecl->getNameAsString();
Result += "\"\n";
-
+
if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
Result += "\t, (struct _objc_method_list *)"
"&_OBJC_CATEGORY_INSTANCE_METHODS_";
@@ -5708,7 +5710,7 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
}
else
Result += "\t, 0\n";
-
+
if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
Result += FullCategoryName;
@@ -5729,7 +5731,7 @@ void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegi
StringRef ClassName,
std::string &Result) {
if (MethodBegin == MethodEnd) return;
-
+
if (!objc_impl_method) {
/* struct _objc_method {
SEL _cmd;
@@ -5742,12 +5744,12 @@ void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegi
Result += "\tchar *method_types;\n";
Result += "\tvoid *_imp;\n";
Result += "};\n";
-
+
objc_impl_method = true;
}
-
+
// Build _objc_method_list for class's methods if needed
-
+
/* struct {
struct _objc_method_list *next_method;
int method_count;
@@ -5769,7 +5771,7 @@ void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegi
Result += IsInstanceMethod ? "inst" : "cls";
Result += "_meth\")))= ";
Result += "{\n\t0, " + utostr(NumMethods) + "\n";
-
+
Result += "\t,{{(SEL)\"";
Result += (*MethodBegin)->getSelector().getAsString();
std::string MethodTypeString =
@@ -5796,16 +5798,16 @@ void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegi
Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
SourceRange OldRange = IV->getSourceRange();
Expr *BaseExpr = IV->getBase();
-
+
// Rewrite the base, but without actually doing replaces.
{
DisableReplaceStmtScope S(*this);
BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
IV->setBase(BaseExpr);
}
-
+
ObjCIvarDecl *D = IV->getDecl();
-
+
Expr *Replacement = IV;
if (CurMethodDef) {
if (BaseExpr->getType()->isObjCObjectPointerType()) {
@@ -5817,7 +5819,7 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
clsDeclared);
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
+
// Synthesize an explicit cast to gain access to the ivar.
std::string RecName = clsDeclared->getIdentifier()->getName();
RecName += "_IMPL";
@@ -5846,7 +5848,7 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
}
} else { // we are outside a method.
assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
-
+
// Explicit ivar refs need to have a cast inserted.
// FIXME: consider sharing some of this code with the code above.
if (BaseExpr->getType()->isObjCObjectPointerType()) {
@@ -5857,7 +5859,7 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
clsDeclared);
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
+
// Synthesize an explicit cast to gain access to the ivar.
std::string RecName = clsDeclared->getIdentifier()->getName();
RecName += "_IMPL";
@@ -5879,9 +5881,9 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
IV->setBase(PE);
}
}
-
+
ReplaceStmtWithRange(IV, Replacement, OldRange);
- return Replacement;
+ return Replacement;
}
#endif // CLANG_ENABLE_OBJC_REWRITER
diff --git a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 7666fe10b381..22546ce4c097 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -28,31 +28,31 @@ using namespace clang;
using namespace clang::serialized_diags;
namespace {
-
+
class AbbreviationMap {
llvm::DenseMap<unsigned, unsigned> Abbrevs;
public:
AbbreviationMap() {}
-
+
void set(unsigned recordID, unsigned abbrevID) {
- assert(Abbrevs.find(recordID) == Abbrevs.end()
+ assert(Abbrevs.find(recordID) == Abbrevs.end()
&& "Abbreviation already set.");
Abbrevs[recordID] = abbrevID;
}
-
+
unsigned get(unsigned recordID) {
assert(Abbrevs.find(recordID) != Abbrevs.end() &&
"Abbreviation not set.");
return Abbrevs[recordID];
}
};
-
+
typedef SmallVector<uint64_t, 64> RecordData;
typedef SmallVectorImpl<uint64_t> RecordDataImpl;
typedef ArrayRef<uint64_t> RecordDataRef;
class SDiagsWriter;
-
+
class SDiagsRenderer : public DiagnosticNoteRenderer {
SDiagsWriter &Writer;
public:
@@ -162,131 +162,131 @@ public:
void finish() override;
private:
- /// \brief Build a DiagnosticsEngine to emit diagnostics about the diagnostics
+ /// Build a DiagnosticsEngine to emit diagnostics about the diagnostics
DiagnosticsEngine *getMetaDiags();
- /// \brief Remove old copies of the serialized diagnostics. This is necessary
+ /// Remove old copies of the serialized diagnostics. This is necessary
/// so that we can detect when subprocesses write diagnostics that we should
/// merge into our own.
void RemoveOldDiagnostics();
- /// \brief Emit the preamble for the serialized diagnostics.
+ /// Emit the preamble for the serialized diagnostics.
void EmitPreamble();
-
- /// \brief Emit the BLOCKINFO block.
+
+ /// Emit the BLOCKINFO block.
void EmitBlockInfoBlock();
- /// \brief Emit the META data block.
+ /// Emit the META data block.
void EmitMetaBlock();
- /// \brief Start a DIAG block.
+ /// Start a DIAG block.
void EnterDiagBlock();
- /// \brief End a DIAG block.
+ /// End a DIAG block.
void ExitDiagBlock();
- /// \brief Emit a DIAG record.
+ /// Emit a DIAG record.
void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, StringRef Message,
DiagOrStoredDiag D);
- /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
+ /// Emit FIXIT and SOURCE_RANGE records for a diagnostic.
void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
ArrayRef<FixItHint> Hints,
const SourceManager &SM);
- /// \brief Emit a record for a CharSourceRange.
+ /// Emit a record for a CharSourceRange.
void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
-
- /// \brief Emit the string information for the category.
+
+ /// Emit the string information for the category.
unsigned getEmitCategory(unsigned category = 0);
-
- /// \brief Emit the string information for diagnostic flags.
+
+ /// Emit the string information for diagnostic flags.
unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
unsigned DiagID = 0);
unsigned getEmitDiagnosticFlag(StringRef DiagName);
- /// \brief Emit (lazily) the file string and retrieved the file identifier.
+ /// Emit (lazily) the file string and retrieved the file identifier.
unsigned getEmitFile(const char *Filename);
- /// \brief Add SourceLocation information the specified record.
+ /// Add SourceLocation information the specified record.
void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
RecordDataImpl &Record, unsigned TokSize = 0);
- /// \brief Add SourceLocation information the specified record.
+ /// Add SourceLocation information the specified record.
void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record,
unsigned TokSize = 0) {
AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(),
Record, TokSize);
}
- /// \brief Add CharSourceRange information the specified record.
+ /// Add CharSourceRange information the specified record.
void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
const SourceManager &SM);
- /// \brief Language options, which can differ from one clone of this client
+ /// Language options, which can differ from one clone of this client
/// to another.
const LangOptions *LangOpts;
- /// \brief Whether this is the original instance (rather than one of its
+ /// Whether this is the original instance (rather than one of its
/// clones), responsible for writing the file at the end.
bool OriginalInstance;
- /// \brief Whether this instance should aggregate diagnostics that are
+ /// Whether this instance should aggregate diagnostics that are
/// generated from child processes.
bool MergeChildRecords;
- /// \brief State that is shared among the various clones of this diagnostic
+ /// State that is shared among the various clones of this diagnostic
/// consumer.
struct SharedState {
SharedState(StringRef File, DiagnosticOptions *Diags)
: DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()),
EmittedAnyDiagBlocks(false) {}
- /// \brief Diagnostic options.
+ /// Diagnostic options.
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
- /// \brief The byte buffer for the serialized content.
+ /// The byte buffer for the serialized content.
SmallString<1024> Buffer;
- /// \brief The BitStreamWriter for the serialized diagnostics.
+ /// The BitStreamWriter for the serialized diagnostics.
llvm::BitstreamWriter Stream;
- /// \brief The name of the diagnostics file.
+ /// The name of the diagnostics file.
std::string OutputFile;
- /// \brief The set of constructed record abbreviations.
+ /// The set of constructed record abbreviations.
AbbreviationMap Abbrevs;
- /// \brief A utility buffer for constructing record content.
+ /// A utility buffer for constructing record content.
RecordData Record;
- /// \brief A text buffer for rendering diagnostic text.
+ /// A text buffer for rendering diagnostic text.
SmallString<256> diagBuf;
- /// \brief The collection of diagnostic categories used.
+ /// The collection of diagnostic categories used.
llvm::DenseSet<unsigned> Categories;
- /// \brief The collection of files used.
+ /// The collection of files used.
llvm::DenseMap<const char *, unsigned> Files;
typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> >
DiagFlagsTy;
- /// \brief Map for uniquing strings.
+ /// Map for uniquing strings.
DiagFlagsTy DiagFlags;
- /// \brief Whether we have already started emission of any DIAG blocks. Once
+ /// Whether we have already started emission of any DIAG blocks. Once
/// this becomes \c true, we never close a DIAG block until we know that we're
/// starting another one or we're done.
bool EmittedAnyDiagBlocks;
- /// \brief Engine for emitting diagnostics about the diagnostics.
+ /// Engine for emitting diagnostics about the diagnostics.
std::unique_ptr<DiagnosticsEngine> MetaDiagnostics;
};
- /// \brief State shared among the various clones of this diagnostic consumer.
+ /// State shared among the various clones of this diagnostic consumer.
std::shared_ptr<SharedState> State;
};
} // end anonymous namespace
@@ -305,14 +305,14 @@ create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) {
// Serialization methods.
//===----------------------------------------------------------------------===//
-/// \brief Emits a block ID in the BLOCKINFO block.
+/// Emits a block ID in the BLOCKINFO block.
static void EmitBlockID(unsigned ID, const char *Name,
llvm::BitstreamWriter &Stream,
RecordDataImpl &Record) {
Record.clear();
Record.push_back(ID);
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
-
+
// Emit the block name if present.
if (!Name || Name[0] == 0)
return;
@@ -325,7 +325,7 @@ static void EmitBlockID(unsigned ID, const char *Name,
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
}
-/// \brief Emits a record ID in the BLOCKINFO block.
+/// Emits a record ID in the BLOCKINFO block.
static void EmitRecordID(unsigned ID, const char *Name,
llvm::BitstreamWriter &Stream,
RecordDataImpl &Record){
@@ -370,11 +370,11 @@ void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
unsigned SDiagsWriter::getEmitFile(const char *FileName){
if (!FileName)
return 0;
-
+
unsigned &entry = State->Files[FileName];
if (entry)
return entry;
-
+
// Lazily generate the record for the file.
entry = State->Files.size();
StringRef Name(FileName);
@@ -395,7 +395,7 @@ void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
State->Record);
}
-/// \brief Emits the preamble of the diagnostics file.
+/// Emits the preamble of the diagnostics file.
void SDiagsWriter::EmitPreamble() {
// Emit the file header.
State->Stream.Emit((unsigned)'D', 8);
@@ -417,7 +417,7 @@ static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev &Abbrev) {
static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev &Abbrev) {
AddSourceLocationAbbrev(Abbrev);
- AddSourceLocationAbbrev(Abbrev);
+ AddSourceLocationAbbrev(Abbrev);
}
void SDiagsWriter::EmitBlockInfoBlock() {
@@ -456,13 +456,13 @@ void SDiagsWriter::EmitBlockInfoBlock() {
Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level.
AddSourceLocationAbbrev(*Abbrev);
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Text size.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
-
- // Emit abbrevation for RECORD_CATEGORY.
+
+ // Emit abbreviation for RECORD_CATEGORY.
Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
@@ -470,13 +470,13 @@ void SDiagsWriter::EmitBlockInfoBlock() {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text.
Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
- // Emit abbrevation for RECORD_SOURCE_RANGE.
+ // Emit abbreviation for RECORD_SOURCE_RANGE.
Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
AddRangeLocationAbbrev(*Abbrev);
Abbrevs.set(RECORD_SOURCE_RANGE,
Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
-
+
// Emit the abbreviation for RECORD_DIAG_FLAG.
Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
@@ -485,18 +485,18 @@ void SDiagsWriter::EmitBlockInfoBlock() {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
Abbrev));
-
+
// Emit the abbreviation for RECORD_FILENAME.
Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modification time.
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modification time.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
Abbrev));
-
+
// Emit the abbreviation for RECORD_FIXIT.
Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
@@ -529,7 +529,7 @@ unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
RecordData::value_type Record[] = {RECORD_CATEGORY, category, catName.size()};
State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record,
catName);
-
+
return category;
}
@@ -537,7 +537,7 @@ unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
unsigned DiagID) {
if (DiagLevel == DiagnosticsEngine::Note)
return 0; // No flag for notes.
-
+
StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
return getEmitDiagnosticFlag(FlagName);
}
@@ -553,7 +553,7 @@ unsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) {
if (entry.first == 0) {
entry.first = State->DiagFlags.size();
entry.second = FlagName;
-
+
// Lazily emit the string in a separate record.
RecordData::value_type Record[] = {RECORD_DIAG_FLAG, entry.first,
FlagName.size()};
@@ -630,7 +630,7 @@ void SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
llvm::BitstreamWriter &Stream = State->Stream;
RecordData &Record = State->Record;
AbbreviationMap &Abbrevs = State->Abbrevs;
-
+
// Emit the RECORD_DIAG record.
Record.clear();
Record.push_back(RECORD_DIAG);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp
index 08b7087fbad6..458717819c41 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp
@@ -1,4 +1,4 @@
-//===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
+//===- SerializedDiagnosticReader.cpp - Reads diagnostics -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,11 +9,22 @@
#include "clang/Frontend/SerializedDiagnosticReader.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang/Frontend/SerializedDiagnostics.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/ManagedStatic.h"
+#include <cstdint>
+#include <system_error>
using namespace clang;
-using namespace clang::serialized_diags;
+using namespace serialized_diags;
std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
// Open the diagnostics file.
@@ -44,13 +55,12 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
std::error_code EC;
switch (Stream.ReadSubBlockID()) {
- case llvm::bitc::BLOCKINFO_BLOCK_ID: {
+ case llvm::bitc::BLOCKINFO_BLOCK_ID:
BlockInfo = Stream.ReadBlockInfoBlock();
if (!BlockInfo)
return SDError::MalformedBlockInfoBlock;
Stream.setBlockInfo(&*BlockInfo);
continue;
- }
case BLOCK_META:
if ((EC = readMetaBlock(Stream)))
return EC;
@@ -65,7 +75,7 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
continue;
}
}
- return std::error_code();
+ return {};
}
enum class SerializedDiagnosticReader::Cursor {
@@ -132,7 +142,7 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
case Cursor::BlockEnd:
if (!VersionChecked)
return SDError::MissingVersion;
- return std::error_code();
+ return {};
}
SmallVector<uint64_t, 1> Record;
@@ -176,7 +186,7 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
case Cursor::BlockEnd:
if ((EC = visitEndOfDiagnostic()))
return EC;
- return std::error_code();
+ return {};
case Cursor::Record:
break;
}
@@ -253,12 +263,14 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
}
namespace {
+
class SDErrorCategoryType final : public std::error_category {
const char *name() const noexcept override {
return "clang.serialized_diags";
}
+
std::string message(int IE) const override {
- SDError E = static_cast<SDError>(IE);
+ auto E = static_cast<SDError>(IE);
switch (E) {
case SDError::CouldNotLoad:
return "Failed to open diagnostics file";
@@ -290,7 +302,8 @@ class SDErrorCategoryType final : public std::error_category {
llvm_unreachable("Unknown error type!");
}
};
-}
+
+} // namespace
static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
const std::error_category &clang::serialized_diags::SDErrorCategory() {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp
index 294f7e44cee5..087bdc543548 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp
@@ -91,7 +91,7 @@ llvm::hash_code TestModuleFileExtension::hashExtension(
Code = llvm::hash_combine(Code, MinorVersion);
Code = llvm::hash_combine(Code, UserInfo);
}
-
+
return Code;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
index 6a72b00c602b..35b99b10f94a 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
@@ -42,7 +42,7 @@ static const enum raw_ostream::Colors fatalColor = raw_ostream::RED;
static const enum raw_ostream::Colors savedColor =
raw_ostream::SAVEDCOLOR;
-/// \brief Add highlights to differences in template strings.
+/// Add highlights to differences in template strings.
static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
bool &Normal, bool Bold) {
while (1) {
@@ -63,7 +63,7 @@ static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
}
}
-/// \brief Number of spaces to indent when word-wrapping.
+/// Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6;
static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
@@ -76,7 +76,7 @@ static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
return bytes;
}
-/// \brief returns a printable representation of first item from input range
+/// returns a printable representation of first item from input range
///
/// This function returns a printable representation of the next item in a line
/// of source. If the next byte begins a valid and printable character, that
@@ -100,7 +100,7 @@ printableTextForNextCharacter(StringRef SourceLine, size_t *i,
unsigned TabStop) {
assert(i && "i must not be null");
assert(*i<SourceLine.size() && "must point to a valid index");
-
+
if (SourceLine[*i]=='\t') {
assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
"Invalid -ftabstop value");
@@ -118,7 +118,7 @@ printableTextForNextCharacter(StringRef SourceLine, size_t *i,
unsigned char const *begin, *end;
begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
end = begin + (SourceLine.size() - *i);
-
+
if (llvm::isLegalUTF8Sequence(begin, end)) {
llvm::UTF32 c;
llvm::UTF32 *cptr = &c;
@@ -203,7 +203,7 @@ static void byteToColumn(StringRef SourceLine, unsigned TabStop,
out.resize(1u,0);
return;
}
-
+
out.resize(SourceLine.size()+1, -1);
int columns = 0;
@@ -255,10 +255,10 @@ namespace {
struct SourceColumnMap {
SourceColumnMap(StringRef SourceLine, unsigned TabStop)
: m_SourceLine(SourceLine) {
-
+
::byteToColumn(SourceLine, TabStop, m_byteToColumn);
::columnToByte(SourceLine, TabStop, m_columnToByte);
-
+
assert(m_byteToColumn.size()==SourceLine.size()+1);
assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
assert(m_byteToColumn.size()
@@ -269,14 +269,14 @@ struct SourceColumnMap {
int columns() const { return m_byteToColumn.back(); }
int bytes() const { return m_columnToByte.back(); }
- /// \brief Map a byte to the column which it is at the start of, or return -1
+ /// Map a byte to the column which it is at the start of, or return -1
/// if it is not at the start of a column (for a UTF-8 trailing byte).
int byteToColumn(int n) const {
assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
return m_byteToColumn[n];
}
- /// \brief Map a byte to the first column which contains it.
+ /// Map a byte to the first column which contains it.
int byteToContainingColumn(int N) const {
assert(0 <= N && N < static_cast<int>(m_byteToColumn.size()));
while (m_byteToColumn[N] == -1)
@@ -284,7 +284,7 @@ struct SourceColumnMap {
return m_byteToColumn[N];
}
- /// \brief Map a column to the byte which starts the column, or return -1 if
+ /// Map a column to the byte which starts the column, or return -1 if
/// the column the second or subsequent column of an expanded tab or similar
/// multi-column entity.
int columnToByte(int n) const {
@@ -292,14 +292,14 @@ struct SourceColumnMap {
return m_columnToByte[n];
}
- /// \brief Map from a byte index to the next byte which starts a column.
+ /// Map from a byte index to the next byte which starts a column.
int startOfNextColumn(int N) const {
assert(0 <= N && N < static_cast<int>(m_byteToColumn.size() - 1));
while (byteToColumn(++N) == -1) {}
return N;
}
- /// \brief Map from a byte index to the previous byte which starts a column.
+ /// Map from a byte index to the previous byte which starts a column.
int startOfPreviousColumn(int N) const {
assert(0 < N && N < static_cast<int>(m_byteToColumn.size()));
while (byteToColumn(--N) == -1) {}
@@ -309,7 +309,7 @@ struct SourceColumnMap {
StringRef getSourceLine() const {
return m_SourceLine;
}
-
+
private:
const std::string m_SourceLine;
SmallVector<int,200> m_byteToColumn;
@@ -317,7 +317,7 @@ private:
};
} // end anonymous namespace
-/// \brief When the source code line we want to print is too long for
+/// When the source code line we want to print is too long for
/// the terminal, select the "interesting" region.
static void selectInterestingSourceRegion(std::string &SourceLine,
std::string &CaretLine,
@@ -507,7 +507,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
}
}
-/// \brief Skip over whitespace in the string, starting at the given
+/// Skip over whitespace in the string, starting at the given
/// index.
///
/// \returns The index of the first non-whitespace character that is
@@ -519,7 +519,7 @@ static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {
return Idx;
}
-/// \brief If the given character is the start of some kind of
+/// If the given character is the start of some kind of
/// balanced punctuation (e.g., quotes or parentheses), return the
/// character that will terminate the punctuation.
///
@@ -539,7 +539,7 @@ static inline char findMatchingPunctuation(char c) {
return 0;
}
-/// \brief Find the end of the word starting at the given offset
+/// Find the end of the word starting at the given offset
/// within a string.
///
/// \returns the index pointing one character past the end of the
@@ -596,7 +596,7 @@ static unsigned findEndOfWord(unsigned Start, StringRef Str,
return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
}
-/// \brief Print the given string to a stream, word-wrapping it to
+/// Print the given string to a stream, word-wrapping it to
/// some number of columns in the process.
///
/// \param OS the stream to which the word-wrapping string will be
@@ -684,7 +684,7 @@ void TextDiagnostic::emitDiagnosticMessage(
if (DiagOpts->ShowColors)
OS.resetColor();
-
+
printDiagnosticLevel(OS, Level, DiagOpts->ShowColors,
DiagOpts->CLFallbackMode);
printDiagnosticMessage(OS,
@@ -777,7 +777,7 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
OS << Filename;
}
-/// \brief Print out the file/line/column information and include trace.
+/// Print out the file/line/column information and include trace.
///
/// This method handlen the emission of the diagnostic location information.
/// This includes extracting as much location information as is present for
@@ -852,23 +852,14 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
// Ignore invalid ranges.
if (!RI->isValid()) continue;
- FullSourceLoc B =
- FullSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc();
- FullSourceLoc E =
- FullSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc();
-
- // If the End location and the start location are the same and are a
- // macro location, then the range was something that came from a
- // macro expansion or _Pragma. If this is an object-like macro, the
- // best we can do is to highlight the range. If this is a
- // function-like macro, we'd also like to highlight the arguments.
- if (B == E && RI->getEnd().isMacroID())
- E = FullSourceLoc(RI->getEnd(), Loc.getManager())
- .getExpansionRange()
- .second;
+ auto &SM = Loc.getManager();
+ SourceLocation B = SM.getExpansionLoc(RI->getBegin());
+ CharSourceRange ERange = SM.getExpansionRange(RI->getEnd());
+ SourceLocation E = ERange.getEnd();
+ bool IsTokenRange = ERange.isTokenRange();
- std::pair<FileID, unsigned> BInfo = B.getDecomposedLoc();
- std::pair<FileID, unsigned> EInfo = E.getDecomposedLoc();
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
+ std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
// If the start or end of the range is in another file, just discard
// it.
@@ -878,11 +869,14 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
// Add in the length of the token, so that we cover multi-char
// tokens.
unsigned TokSize = 0;
- if (RI->isTokenRange())
- TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts);
-
- OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-'
- << E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}';
+ if (IsTokenRange)
+ TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
+
+ FullSourceLoc BF(B, SM), EF(E, SM);
+ OS << '{'
+ << BF.getLineNumber() << ':' << BF.getColumnNumber() << '-'
+ << EF.getLineNumber() << ':' << (EF.getColumnNumber() + TokSize)
+ << '}';
PrintedRange = true;
}
@@ -897,7 +891,7 @@ void TextDiagnostic::emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) {
OS << "In file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":\n";
else
- OS << "In included file:\n";
+ OS << "In included file:\n";
}
void TextDiagnostic::emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
@@ -919,7 +913,7 @@ void TextDiagnostic::emitBuildingModuleLocation(FullSourceLoc Loc,
OS << "While building module '" << ModuleName << "':\n";
}
-/// \brief Find the suitable set of lines to show to include a set of ranges.
+/// Find the suitable set of lines to show to include a set of ranges.
static llvm::Optional<std::pair<unsigned, unsigned>>
findLinesForRange(const CharSourceRange &R, FileID FID,
const SourceManager &SM) {
@@ -969,7 +963,7 @@ maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,
return A;
}
-/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
+/// Highlight a SourceRange (with ~'s) for any characters on LineNo.
static void highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
const SourceColumnMap &map,
@@ -1116,7 +1110,7 @@ static std::string buildFixItInsertionLine(FileID FID,
return FixItInsertionLine;
}
-/// \brief Emit a code snippet and caret line.
+/// Emit a code snippet and caret line.
///
/// This routine emits a single line's code snippet and caret line..
///
@@ -1275,15 +1269,15 @@ void TextDiagnostic::emitSnippet(StringRef line) {
return;
size_t i = 0;
-
+
std::string to_print;
bool print_reversed = false;
-
+
while (i<line.size()) {
std::pair<SmallString<16>,bool> res
= printableTextForNextCharacter(line, &i, DiagOpts->TabStop);
bool was_printable = res.second;
-
+
if (DiagOpts->ShowColors && was_printable == print_reversed) {
if (print_reversed)
OS.reverseColor();
@@ -1292,17 +1286,17 @@ void TextDiagnostic::emitSnippet(StringRef line) {
if (DiagOpts->ShowColors)
OS.resetColor();
}
-
+
print_reversed = !was_printable;
to_print += res.first.str();
}
-
+
if (print_reversed && DiagOpts->ShowColors)
OS.reverseColor();
OS << to_print;
if (print_reversed && DiagOpts->ShowColors)
OS.resetColor();
-
+
OS << '\n';
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
index 288507310baa..44bb2bc29bc0 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -1,4 +1,4 @@
-//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
+//===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,13 +12,15 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
+
using namespace clang;
/// HandleDiagnostic - Store the errors, warnings, and notes that are
/// reported.
-///
void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info) {
// Default implementation (Warnings/errors count).
@@ -50,25 +52,24 @@ void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level,
}
void TextDiagnosticBuffer::FlushDiagnostics(DiagnosticsEngine &Diags) const {
- for (auto it = All.begin(), ie = All.end(); it != ie; ++it) {
- auto Diag = Diags.Report(Diags.getCustomDiagID(it->first, "%0"));
- switch (it->first) {
+ for (const auto &I : All) {
+ auto Diag = Diags.Report(Diags.getCustomDiagID(I.first, "%0"));
+ switch (I.first) {
default: llvm_unreachable(
"Diagnostic not handled during diagnostic flushing!");
case DiagnosticsEngine::Note:
- Diag << Notes[it->second].second;
+ Diag << Notes[I.second].second;
break;
case DiagnosticsEngine::Warning:
- Diag << Warnings[it->second].second;
+ Diag << Warnings[I.second].second;
break;
case DiagnosticsEngine::Remark:
- Diag << Remarks[it->second].second;
+ Diag << Remarks[I.second].second;
break;
case DiagnosticsEngine::Error:
case DiagnosticsEngine::Fatal:
- Diag << Errors[it->second].second;
+ Diag << Errors[I.second].second;
break;
}
}
}
-
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
index 5dd3252d5b1e..a37382c116ae 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -44,7 +44,7 @@ void TextDiagnosticPrinter::EndSourceFile() {
TextDiag.reset();
}
-/// \brief Print any diagnostic option information to a raw_ostream.
+/// Print any diagnostic option information to a raw_ostream.
///
/// This implements all of the logic for adding diagnostic options to a message
/// (via OS). Each relevant option is comma separated and all are enclosed in
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 0df5393a309b..21933f474ff5 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -1,4 +1,4 @@
-//===---- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ------===//
+//===- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ---------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,27 +13,48 @@
#include "clang/Frontend/VerifyDiagnosticConsumer.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/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
using namespace clang;
-typedef VerifyDiagnosticConsumer::Directive Directive;
-typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList;
-typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;
+
+using Directive = VerifyDiagnosticConsumer::Directive;
+using DirectiveList = VerifyDiagnosticConsumer::DirectiveList;
+using ExpectedData = VerifyDiagnosticConsumer::ExpectedData;
VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &Diags_)
- : Diags(Diags_),
- PrimaryClient(Diags.getClient()), PrimaryClientOwner(Diags.takeClient()),
- Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(nullptr),
- LangOpts(nullptr), SrcManager(nullptr), ActiveSourceFiles(0),
- Status(HasNoDirectives)
-{
+ : Diags(Diags_), PrimaryClient(Diags.getClient()),
+ PrimaryClientOwner(Diags.takeClient()),
+ Buffer(new TextDiagnosticBuffer()), Status(HasNoDirectives) {
if (Diags.hasSourceManager())
setSourceManager(Diags.getSourceManager());
}
@@ -48,16 +69,18 @@ VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
}
#ifndef NDEBUG
+
namespace {
+
class VerifyFileTracker : public PPCallbacks {
VerifyDiagnosticConsumer &Verify;
SourceManager &SM;
public:
VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
- : Verify(Verify), SM(SM) { }
+ : Verify(Verify), SM(SM) {}
- /// \brief Hook into the preprocessor and update the list of parsed
+ /// Hook into the preprocessor and update the list of parsed
/// files when the preprocessor indicates a new file is entered.
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@@ -66,7 +89,9 @@ public:
VerifyDiagnosticConsumer::IsParsed);
}
};
-} // End anonymous namespace.
+
+} // namespace
+
#endif
// DiagnosticConsumer interface.
@@ -79,10 +104,10 @@ void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
CurrentPreprocessor = PP;
this->LangOpts = &LangOpts;
setSourceManager(PP->getSourceManager());
- const_cast<Preprocessor*>(PP)->addCommentHandler(this);
+ const_cast<Preprocessor *>(PP)->addCommentHandler(this);
#ifndef NDEBUG
// Debug build tracks parsed files.
- const_cast<Preprocessor*>(PP)->addPPCallbacks(
+ const_cast<Preprocessor *>(PP)->addPPCallbacks(
llvm::make_unique<VerifyFileTracker>(*this, *SrcManager));
#endif
}
@@ -99,7 +124,8 @@ void VerifyDiagnosticConsumer::EndSourceFile() {
// Detach comment handler once last active source file completed.
if (--ActiveSourceFiles == 0) {
if (CurrentPreprocessor)
- const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this);
+ const_cast<Preprocessor *>(CurrentPreprocessor)->
+ removeCommentHandler(this);
// Check diagnostics once last file completed.
CheckDiagnostics();
@@ -152,19 +178,18 @@ void VerifyDiagnosticConsumer::HandleDiagnostic(
// Checking diagnostics implementation.
//===----------------------------------------------------------------------===//
-typedef TextDiagnosticBuffer::DiagList DiagList;
-typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+using DiagList = TextDiagnosticBuffer::DiagList;
+using const_diag_iterator = TextDiagnosticBuffer::const_iterator;
namespace {
/// StandardDirective - Directive with string matching.
-///
class StandardDirective : public Directive {
public:
StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min,
unsigned Max)
- : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) { }
+ : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) {}
bool isValid(std::string &Error) override {
// all strings are considered valid; even empty ones
@@ -177,14 +202,13 @@ public:
};
/// RegexDirective - Directive with regular-expression matching.
-///
class RegexDirective : public Directive {
public:
RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
StringRef RegexStr)
- : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
- Regex(RegexStr) { }
+ : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
+ Regex(RegexStr) {}
bool isValid(std::string &Error) override {
return Regex.isValid(Error);
@@ -202,7 +226,7 @@ class ParseHelper
{
public:
ParseHelper(StringRef S)
- : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(nullptr) {}
+ : Begin(S.begin()), End(S.end()), C(Begin), P(Begin) {}
// Return true if string literal is next.
bool Next(StringRef S) {
@@ -210,7 +234,7 @@ public:
PEnd = C + S.size();
if (PEnd > End)
return false;
- return !memcmp(P, S.data(), S.size());
+ return memcmp(P, S.data(), S.size()) == 0;
}
// Return true if number is next.
@@ -321,16 +345,23 @@ public:
return !(C < End);
}
- const char * const Begin; // beginning of expected content
- const char * const End; // end of expected content (1-past)
- const char *C; // position of next char in content
+ // Beginning of expected content.
+ const char * const Begin;
+
+ // End of expected content (1-past).
+ const char * const End;
+
+ // Position of next char in content.
+ const char *C;
+
const char *P;
private:
- const char *PEnd; // previous next/search subject end (1-past)
+ // Previous next/search subject end (1-past).
+ const char *PEnd = nullptr;
};
-} // namespace anonymous
+} // anonymous
/// ParseDirective - Go through the comment and see if it indicates expected
/// diagnostics. If so, then put them in the appropriate directive list.
@@ -625,7 +656,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
}
#ifndef NDEBUG
-/// \brief Lex the specified source file to determine whether it contains
+/// Lex the specified source file to determine whether it contains
/// any expected-* directives. As a Lexer is used rather than a full-blown
/// Preprocessor, directives inside skipped #if blocks will still be found.
///
@@ -663,7 +694,7 @@ static bool findDirectives(SourceManager &SM, FileID FID,
}
#endif // !NDEBUG
-/// \brief Takes a list of diagnostics that have been generated but not matched
+/// Takes a list of diagnostics that have been generated but not matched
/// by an expected-* directive and produces a diagnostic to the user from this.
static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
const_diag_iterator diag_begin,
@@ -691,7 +722,7 @@ static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceM
return std::distance(diag_begin, diag_end);
}
-/// \brief Takes a list of diagnostics that were expected to have been generated
+/// Takes a list of diagnostics that were expected to have been generated
/// but were not and produces a diagnostic to the user from this.
static unsigned PrintExpected(DiagnosticsEngine &Diags,
SourceManager &SourceMgr,
@@ -701,21 +732,20 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags,
SmallString<256> Fmt;
llvm::raw_svector_ostream OS(Fmt);
- for (auto *DirPtr : DL) {
- Directive &D = *DirPtr;
- if (D.DiagnosticLoc.isInvalid())
+ for (const auto *D : DL) {
+ if (D->DiagnosticLoc.isInvalid())
OS << "\n File *";
else
- OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc);
- if (D.MatchAnyLine)
+ OS << "\n File " << SourceMgr.getFilename(D->DiagnosticLoc);
+ if (D->MatchAnyLine)
OS << " Line *";
else
- OS << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
- if (D.DirectiveLoc != D.DiagnosticLoc)
+ OS << " Line " << SourceMgr.getPresumedLineNumber(D->DiagnosticLoc);
+ if (D->DirectiveLoc != D->DiagnosticLoc)
OS << " (directive at "
- << SourceMgr.getFilename(D.DirectiveLoc) << ':'
- << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')';
- OS << ": " << D.Text;
+ << SourceMgr.getFilename(D->DirectiveLoc) << ':'
+ << SourceMgr.getPresumedLineNumber(D->DirectiveLoc) << ')';
+ OS << ": " << D->Text;
}
Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
@@ -723,7 +753,7 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags,
return DL.size();
}
-/// \brief Determine whether two source locations come from the same file.
+/// Determine whether two source locations come from the same file.
static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
SourceLocation DiagnosticLoc) {
while (DiagnosticLoc.isMacroID())
@@ -741,7 +771,6 @@ static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
/// CheckLists - Compare expected to seen diagnostic lists and return the
/// the difference between them.
-///
static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const char *Label,
DirectiveList &Left,
@@ -792,7 +821,6 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
/// CheckResults - This compares the expected results to those that
/// were actually reported. It emits any discrepencies. Return "true" if there
/// were problems. Return "false" otherwise.
-///
static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const TextDiagnosticBuffer &Buffer,
ExpectedData &ED) {
@@ -875,19 +903,16 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
// this file is being parsed separately from the main file, in which
// case consider moving the directives to the correct place, if this
// is applicable.
- if (UnparsedFiles.size() > 0) {
+ if (!UnparsedFiles.empty()) {
// Generate a cache of parsed FileEntry pointers for alias lookups.
llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
- for (ParsedFilesMap::iterator I = ParsedFiles.begin(),
- End = ParsedFiles.end(); I != End; ++I) {
- if (const FileEntry *FE = I->second)
+ for (const auto &I : ParsedFiles)
+ if (const FileEntry *FE = I.second)
ParsedFileCache.insert(FE);
- }
// Iterate through list of unparsed files.
- for (UnparsedFilesMap::iterator I = UnparsedFiles.begin(),
- End = UnparsedFiles.end(); I != End; ++I) {
- const UnparsedFileStatus &Status = I->second;
+ for (const auto &I : UnparsedFiles) {
+ const UnparsedFileStatus &Status = I.second;
const FileEntry *FE = Status.getFile();
// Skip files that have been parsed via an alias.
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 4167e1fe20b8..747fdd241640 100644
--- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -32,6 +32,8 @@
using namespace clang;
using namespace llvm::opt;
+namespace clang {
+
static std::unique_ptr<FrontendAction>
CreateFrontendBaseAction(CompilerInstance &CI) {
using namespace clang::frontend;
@@ -43,6 +45,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case ASTDump: return llvm::make_unique<ASTDumpAction>();
case ASTPrint: return llvm::make_unique<ASTPrintAction>();
case ASTView: return llvm::make_unique<ASTViewAction>();
+ case DumpCompilerOptions:
+ return llvm::make_unique<DumpCompilerOptionsAction>();
case DumpRawTokens: return llvm::make_unique<DumpRawTokensAction>();
case DumpTokens: return llvm::make_unique<DumpTokensAction>();
case EmitAssembly: return llvm::make_unique<EmitAssemblyAction>();
@@ -63,6 +67,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>();
case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>();
case VerifyPCH: return llvm::make_unique<VerifyPCHAction>();
+ case TemplightDump: return llvm::make_unique<TemplightDumpAction>();
case PluginAction: {
for (FrontendPluginRegistry::iterator it =
@@ -122,7 +127,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
#endif
}
-static std::unique_ptr<FrontendAction>
+std::unique_ptr<FrontendAction>
CreateFrontendAction(CompilerInstance &CI) {
// Create the underlying action.
std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI);
@@ -134,7 +139,7 @@ CreateFrontendAction(CompilerInstance &CI) {
if (FEOpts.FixAndRecompile) {
Act = llvm::make_unique<FixItRecompile>(std::move(Act));
}
-
+
#if CLANG_ENABLE_ARCMT
if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource &&
CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) {
@@ -173,7 +178,7 @@ CreateFrontendAction(CompilerInstance &CI) {
return Act;
}
-bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
+bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
// Honor -help.
if (Clang->getFrontendOpts().ShowHelp) {
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
@@ -254,3 +259,5 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
BuryPointer(std::move(Act));
return Success;
}
+
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_builtin_vars.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_builtin_vars.h
index 6f5eb9c78d85..290c4b298433 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_builtin_vars.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_builtin_vars.h
@@ -54,7 +54,7 @@ struct dim3;
#define __DELETE
#endif
-// Make sure nobody can create instances of the special varible types. nvcc
+// Make sure nobody can create instances of the special variable types. nvcc
// also disallows taking address of special variables, so we disable address-of
// operator as well.
#define __CUDA_DISALLOW_BUILTINVAR_ACCESS(TypeName) \
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_device_functions.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_device_functions.h
new file mode 100644
index 000000000000..67bbc68b1637
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_device_functions.h
@@ -0,0 +1,1768 @@
+/*===---- __clang_cuda_device_functions.h - CUDA runtime support -----------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __CLANG_CUDA_DEVICE_FUNCTIONS_H__
+#define __CLANG_CUDA_DEVICE_FUNCTIONS_H__
+
+#if CUDA_VERSION < 9000
+#error This file is intended to be used with CUDA-9+ only.
+#endif
+
+// __DEVICE__ is a helper macro with common set of attributes for the wrappers
+// we implement in this file. We need static in order to avoid emitting unused
+// functions and __forceinline__ helps inlining these wrappers at -O1.
+#pragma push_macro("__DEVICE__")
+#define __DEVICE__ static __device__ __forceinline__
+
+// libdevice provides fast low precision and slow full-recision implementations
+// for some functions. Which one gets selected depends on
+// __CLANG_CUDA_APPROX_TRANSCENDENTALS__ which gets defined by clang if
+// -ffast-math or -fcuda-approx-transcendentals are in effect.
+#pragma push_macro("__FAST_OR_SLOW")
+#if defined(__CLANG_CUDA_APPROX_TRANSCENDENTALS__)
+#define __FAST_OR_SLOW(fast, slow) fast
+#else
+#define __FAST_OR_SLOW(fast, slow) slow
+#endif
+
+__DEVICE__ int __all(int __a) { return __nvvm_vote_all(__a); }
+__DEVICE__ int __any(int __a) { return __nvvm_vote_any(__a); }
+__DEVICE__ unsigned int __ballot(int __a) { return __nvvm_vote_ballot(__a); }
+__DEVICE__ unsigned int __brev(unsigned int __a) { return __nv_brev(__a); }
+__DEVICE__ unsigned long long __brevll(unsigned long long __a) {
+ return __nv_brevll(__a);
+}
+__DEVICE__ void __brkpt() { asm volatile("brkpt;"); }
+__DEVICE__ void __brkpt(int __a) { __brkpt(); }
+__DEVICE__ unsigned int __byte_perm(unsigned int __a, unsigned int __b,
+ unsigned int __c) {
+ return __nv_byte_perm(__a, __b, __c);
+}
+__DEVICE__ int __clz(int __a) { return __nv_clz(__a); }
+__DEVICE__ int __clzll(long long __a) { return __nv_clzll(__a); }
+__DEVICE__ float __cosf(float __a) { return __nv_fast_cosf(__a); }
+__DEVICE__ double __dAtomicAdd(double *__p, double __v) {
+ return __nvvm_atom_add_gen_d(__p, __v);
+}
+__DEVICE__ double __dAtomicAdd_block(double *__p, double __v) {
+ return __nvvm_atom_cta_add_gen_d(__p, __v);
+}
+__DEVICE__ double __dAtomicAdd_system(double *__p, double __v) {
+ return __nvvm_atom_sys_add_gen_d(__p, __v);
+}
+__DEVICE__ double __dadd_rd(double __a, double __b) {
+ return __nv_dadd_rd(__a, __b);
+}
+__DEVICE__ double __dadd_rn(double __a, double __b) {
+ return __nv_dadd_rn(__a, __b);
+}
+__DEVICE__ double __dadd_ru(double __a, double __b) {
+ return __nv_dadd_ru(__a, __b);
+}
+__DEVICE__ double __dadd_rz(double __a, double __b) {
+ return __nv_dadd_rz(__a, __b);
+}
+__DEVICE__ double __ddiv_rd(double __a, double __b) {
+ return __nv_ddiv_rd(__a, __b);
+}
+__DEVICE__ double __ddiv_rn(double __a, double __b) {
+ return __nv_ddiv_rn(__a, __b);
+}
+__DEVICE__ double __ddiv_ru(double __a, double __b) {
+ return __nv_ddiv_ru(__a, __b);
+}
+__DEVICE__ double __ddiv_rz(double __a, double __b) {
+ return __nv_ddiv_rz(__a, __b);
+}
+__DEVICE__ double __dmul_rd(double __a, double __b) {
+ return __nv_dmul_rd(__a, __b);
+}
+__DEVICE__ double __dmul_rn(double __a, double __b) {
+ return __nv_dmul_rn(__a, __b);
+}
+__DEVICE__ double __dmul_ru(double __a, double __b) {
+ return __nv_dmul_ru(__a, __b);
+}
+__DEVICE__ double __dmul_rz(double __a, double __b) {
+ return __nv_dmul_rz(__a, __b);
+}
+__DEVICE__ float __double2float_rd(double __a) {
+ return __nv_double2float_rd(__a);
+}
+__DEVICE__ float __double2float_rn(double __a) {
+ return __nv_double2float_rn(__a);
+}
+__DEVICE__ float __double2float_ru(double __a) {
+ return __nv_double2float_ru(__a);
+}
+__DEVICE__ float __double2float_rz(double __a) {
+ return __nv_double2float_rz(__a);
+}
+__DEVICE__ int __double2hiint(double __a) { return __nv_double2hiint(__a); }
+__DEVICE__ int __double2int_rd(double __a) { return __nv_double2int_rd(__a); }
+__DEVICE__ int __double2int_rn(double __a) { return __nv_double2int_rn(__a); }
+__DEVICE__ int __double2int_ru(double __a) { return __nv_double2int_ru(__a); }
+__DEVICE__ int __double2int_rz(double __a) { return __nv_double2int_rz(__a); }
+__DEVICE__ long long __double2ll_rd(double __a) {
+ return __nv_double2ll_rd(__a);
+}
+__DEVICE__ long long __double2ll_rn(double __a) {
+ return __nv_double2ll_rn(__a);
+}
+__DEVICE__ long long __double2ll_ru(double __a) {
+ return __nv_double2ll_ru(__a);
+}
+__DEVICE__ long long __double2ll_rz(double __a) {
+ return __nv_double2ll_rz(__a);
+}
+__DEVICE__ int __double2loint(double __a) { return __nv_double2loint(__a); }
+__DEVICE__ unsigned int __double2uint_rd(double __a) {
+ return __nv_double2uint_rd(__a);
+}
+__DEVICE__ unsigned int __double2uint_rn(double __a) {
+ return __nv_double2uint_rn(__a);
+}
+__DEVICE__ unsigned int __double2uint_ru(double __a) {
+ return __nv_double2uint_ru(__a);
+}
+__DEVICE__ unsigned int __double2uint_rz(double __a) {
+ return __nv_double2uint_rz(__a);
+}
+__DEVICE__ unsigned long long __double2ull_rd(double __a) {
+ return __nv_double2ull_rd(__a);
+}
+__DEVICE__ unsigned long long __double2ull_rn(double __a) {
+ return __nv_double2ull_rn(__a);
+}
+__DEVICE__ unsigned long long __double2ull_ru(double __a) {
+ return __nv_double2ull_ru(__a);
+}
+__DEVICE__ unsigned long long __double2ull_rz(double __a) {
+ return __nv_double2ull_rz(__a);
+}
+__DEVICE__ long long __double_as_longlong(double __a) {
+ return __nv_double_as_longlong(__a);
+}
+__DEVICE__ double __drcp_rd(double __a) { return __nv_drcp_rd(__a); }
+__DEVICE__ double __drcp_rn(double __a) { return __nv_drcp_rn(__a); }
+__DEVICE__ double __drcp_ru(double __a) { return __nv_drcp_ru(__a); }
+__DEVICE__ double __drcp_rz(double __a) { return __nv_drcp_rz(__a); }
+__DEVICE__ double __dsqrt_rd(double __a) { return __nv_dsqrt_rd(__a); }
+__DEVICE__ double __dsqrt_rn(double __a) { return __nv_dsqrt_rn(__a); }
+__DEVICE__ double __dsqrt_ru(double __a) { return __nv_dsqrt_ru(__a); }
+__DEVICE__ double __dsqrt_rz(double __a) { return __nv_dsqrt_rz(__a); }
+__DEVICE__ double __dsub_rd(double __a, double __b) {
+ return __nv_dsub_rd(__a, __b);
+}
+__DEVICE__ double __dsub_rn(double __a, double __b) {
+ return __nv_dsub_rn(__a, __b);
+}
+__DEVICE__ double __dsub_ru(double __a, double __b) {
+ return __nv_dsub_ru(__a, __b);
+}
+__DEVICE__ double __dsub_rz(double __a, double __b) {
+ return __nv_dsub_rz(__a, __b);
+}
+__DEVICE__ float __exp10f(float __a) { return __nv_fast_exp10f(__a); }
+__DEVICE__ float __expf(float __a) { return __nv_fast_expf(__a); }
+__DEVICE__ float __fAtomicAdd(float *__p, float __v) {
+ return __nvvm_atom_add_gen_f(__p, __v);
+}
+__DEVICE__ float __fAtomicAdd_block(float *__p, float __v) {
+ return __nvvm_atom_cta_add_gen_f(__p, __v);
+}
+__DEVICE__ float __fAtomicAdd_system(float *__p, float __v) {
+ return __nvvm_atom_sys_add_gen_f(__p, __v);
+}
+__DEVICE__ float __fAtomicExch(float *__p, float __v) {
+ return __nv_int_as_float(
+ __nvvm_atom_xchg_gen_i((int *)__p, __nv_float_as_int(__v)));
+}
+__DEVICE__ float __fAtomicExch_block(float *__p, float __v) {
+ return __nv_int_as_float(
+ __nvvm_atom_cta_xchg_gen_i((int *)__p, __nv_float_as_int(__v)));
+}
+__DEVICE__ float __fAtomicExch_system(float *__p, float __v) {
+ return __nv_int_as_float(
+ __nvvm_atom_sys_xchg_gen_i((int *)__p, __nv_float_as_int(__v)));
+}
+__DEVICE__ float __fadd_rd(float __a, float __b) {
+ return __nv_fadd_rd(__a, __b);
+}
+__DEVICE__ float __fadd_rn(float __a, float __b) {
+ return __nv_fadd_rn(__a, __b);
+}
+__DEVICE__ float __fadd_ru(float __a, float __b) {
+ return __nv_fadd_ru(__a, __b);
+}
+__DEVICE__ float __fadd_rz(float __a, float __b) {
+ return __nv_fadd_rz(__a, __b);
+}
+__DEVICE__ float __fdiv_rd(float __a, float __b) {
+ return __nv_fdiv_rd(__a, __b);
+}
+__DEVICE__ float __fdiv_rn(float __a, float __b) {
+ return __nv_fdiv_rn(__a, __b);
+}
+__DEVICE__ float __fdiv_ru(float __a, float __b) {
+ return __nv_fdiv_ru(__a, __b);
+}
+__DEVICE__ float __fdiv_rz(float __a, float __b) {
+ return __nv_fdiv_rz(__a, __b);
+}
+__DEVICE__ float __fdividef(float __a, float __b) {
+ return __nv_fast_fdividef(__a, __b);
+}
+__DEVICE__ int __ffs(int __a) { return __nv_ffs(__a); }
+__DEVICE__ int __ffsll(long long __a) { return __nv_ffsll(__a); }
+__DEVICE__ int __finite(double __a) { return __nv_isfinited(__a); }
+__DEVICE__ int __finitef(float __a) { return __nv_finitef(__a); }
+__DEVICE__ int __float2int_rd(float __a) { return __nv_float2int_rd(__a); }
+__DEVICE__ int __float2int_rn(float __a) { return __nv_float2int_rn(__a); }
+__DEVICE__ int __float2int_ru(float __a) { return __nv_float2int_ru(__a); }
+__DEVICE__ int __float2int_rz(float __a) { return __nv_float2int_rz(__a); }
+__DEVICE__ long long __float2ll_rd(float __a) { return __nv_float2ll_rd(__a); }
+__DEVICE__ long long __float2ll_rn(float __a) { return __nv_float2ll_rn(__a); }
+__DEVICE__ long long __float2ll_ru(float __a) { return __nv_float2ll_ru(__a); }
+__DEVICE__ long long __float2ll_rz(float __a) { return __nv_float2ll_rz(__a); }
+__DEVICE__ unsigned int __float2uint_rd(float __a) {
+ return __nv_float2uint_rd(__a);
+}
+__DEVICE__ unsigned int __float2uint_rn(float __a) {
+ return __nv_float2uint_rn(__a);
+}
+__DEVICE__ unsigned int __float2uint_ru(float __a) {
+ return __nv_float2uint_ru(__a);
+}
+__DEVICE__ unsigned int __float2uint_rz(float __a) {
+ return __nv_float2uint_rz(__a);
+}
+__DEVICE__ unsigned long long __float2ull_rd(float __a) {
+ return __nv_float2ull_rd(__a);
+}
+__DEVICE__ unsigned long long __float2ull_rn(float __a) {
+ return __nv_float2ull_rn(__a);
+}
+__DEVICE__ unsigned long long __float2ull_ru(float __a) {
+ return __nv_float2ull_ru(__a);
+}
+__DEVICE__ unsigned long long __float2ull_rz(float __a) {
+ return __nv_float2ull_rz(__a);
+}
+__DEVICE__ int __float_as_int(float __a) { return __nv_float_as_int(__a); }
+__DEVICE__ unsigned int __float_as_uint(float __a) {
+ return __nv_float_as_uint(__a);
+}
+__DEVICE__ double __fma_rd(double __a, double __b, double __c) {
+ return __nv_fma_rd(__a, __b, __c);
+}
+__DEVICE__ double __fma_rn(double __a, double __b, double __c) {
+ return __nv_fma_rn(__a, __b, __c);
+}
+__DEVICE__ double __fma_ru(double __a, double __b, double __c) {
+ return __nv_fma_ru(__a, __b, __c);
+}
+__DEVICE__ double __fma_rz(double __a, double __b, double __c) {
+ return __nv_fma_rz(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_ieee_rd(float __a, float __b, float __c) {
+ return __nv_fmaf_ieee_rd(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_ieee_rn(float __a, float __b, float __c) {
+ return __nv_fmaf_ieee_rn(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_ieee_ru(float __a, float __b, float __c) {
+ return __nv_fmaf_ieee_ru(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_ieee_rz(float __a, float __b, float __c) {
+ return __nv_fmaf_ieee_rz(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_rd(float __a, float __b, float __c) {
+ return __nv_fmaf_rd(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_rn(float __a, float __b, float __c) {
+ return __nv_fmaf_rn(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_ru(float __a, float __b, float __c) {
+ return __nv_fmaf_ru(__a, __b, __c);
+}
+__DEVICE__ float __fmaf_rz(float __a, float __b, float __c) {
+ return __nv_fmaf_rz(__a, __b, __c);
+}
+__DEVICE__ float __fmul_rd(float __a, float __b) {
+ return __nv_fmul_rd(__a, __b);
+}
+__DEVICE__ float __fmul_rn(float __a, float __b) {
+ return __nv_fmul_rn(__a, __b);
+}
+__DEVICE__ float __fmul_ru(float __a, float __b) {
+ return __nv_fmul_ru(__a, __b);
+}
+__DEVICE__ float __fmul_rz(float __a, float __b) {
+ return __nv_fmul_rz(__a, __b);
+}
+__DEVICE__ float __frcp_rd(float __a) { return __nv_frcp_rd(__a); }
+__DEVICE__ float __frcp_rn(float __a) { return __nv_frcp_rn(__a); }
+__DEVICE__ float __frcp_ru(float __a) { return __nv_frcp_ru(__a); }
+__DEVICE__ float __frcp_rz(float __a) { return __nv_frcp_rz(__a); }
+__DEVICE__ float __frsqrt_rn(float __a) { return __nv_frsqrt_rn(__a); }
+__DEVICE__ float __fsqrt_rd(float __a) { return __nv_fsqrt_rd(__a); }
+__DEVICE__ float __fsqrt_rn(float __a) { return __nv_fsqrt_rn(__a); }
+__DEVICE__ float __fsqrt_ru(float __a) { return __nv_fsqrt_ru(__a); }
+__DEVICE__ float __fsqrt_rz(float __a) { return __nv_fsqrt_rz(__a); }
+__DEVICE__ float __fsub_rd(float __a, float __b) {
+ return __nv_fsub_rd(__a, __b);
+}
+__DEVICE__ float __fsub_rn(float __a, float __b) {
+ return __nv_fsub_rn(__a, __b);
+}
+__DEVICE__ float __fsub_ru(float __a, float __b) {
+ return __nv_fsub_ru(__a, __b);
+}
+__DEVICE__ float __fsub_rz(float __a, float __b) {
+ return __nv_fsub_rz(__a, __b);
+}
+__DEVICE__ int __hadd(int __a, int __b) { return __nv_hadd(__a, __b); }
+__DEVICE__ double __hiloint2double(int __a, int __b) {
+ return __nv_hiloint2double(__a, __b);
+}
+__DEVICE__ int __iAtomicAdd(int *__p, int __v) {
+ return __nvvm_atom_add_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicAdd_block(int *__p, int __v) {
+ __nvvm_atom_cta_add_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicAdd_system(int *__p, int __v) {
+ __nvvm_atom_sys_add_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicAnd(int *__p, int __v) {
+ return __nvvm_atom_and_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicAnd_block(int *__p, int __v) {
+ return __nvvm_atom_cta_and_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicAnd_system(int *__p, int __v) {
+ return __nvvm_atom_sys_and_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicCAS(int *__p, int __cmp, int __v) {
+ return __nvvm_atom_cas_gen_i(__p, __cmp, __v);
+}
+__DEVICE__ int __iAtomicCAS_block(int *__p, int __cmp, int __v) {
+ return __nvvm_atom_cta_cas_gen_i(__p, __cmp, __v);
+}
+__DEVICE__ int __iAtomicCAS_system(int *__p, int __cmp, int __v) {
+ return __nvvm_atom_sys_cas_gen_i(__p, __cmp, __v);
+}
+__DEVICE__ int __iAtomicExch(int *__p, int __v) {
+ return __nvvm_atom_xchg_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicExch_block(int *__p, int __v) {
+ return __nvvm_atom_cta_xchg_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicExch_system(int *__p, int __v) {
+ return __nvvm_atom_sys_xchg_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicMax(int *__p, int __v) {
+ return __nvvm_atom_max_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicMax_block(int *__p, int __v) {
+ return __nvvm_atom_cta_max_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicMax_system(int *__p, int __v) {
+ return __nvvm_atom_sys_max_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicMin(int *__p, int __v) {
+ return __nvvm_atom_min_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicMin_block(int *__p, int __v) {
+ return __nvvm_atom_cta_min_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicMin_system(int *__p, int __v) {
+ return __nvvm_atom_sys_min_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicOr(int *__p, int __v) {
+ return __nvvm_atom_or_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicOr_block(int *__p, int __v) {
+ return __nvvm_atom_cta_or_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicOr_system(int *__p, int __v) {
+ return __nvvm_atom_sys_or_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicXor(int *__p, int __v) {
+ return __nvvm_atom_xor_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicXor_block(int *__p, int __v) {
+ return __nvvm_atom_cta_xor_gen_i(__p, __v);
+}
+__DEVICE__ int __iAtomicXor_system(int *__p, int __v) {
+ return __nvvm_atom_sys_xor_gen_i(__p, __v);
+}
+__DEVICE__ long long __illAtomicMax(long long *__p, long long __v) {
+ return __nvvm_atom_max_gen_ll(__p, __v);
+}
+__DEVICE__ long long __illAtomicMax_block(long long *__p, long long __v) {
+ return __nvvm_atom_cta_max_gen_ll(__p, __v);
+}
+__DEVICE__ long long __illAtomicMax_system(long long *__p, long long __v) {
+ return __nvvm_atom_sys_max_gen_ll(__p, __v);
+}
+__DEVICE__ long long __illAtomicMin(long long *__p, long long __v) {
+ return __nvvm_atom_min_gen_ll(__p, __v);
+}
+__DEVICE__ long long __illAtomicMin_block(long long *__p, long long __v) {
+ return __nvvm_atom_cta_min_gen_ll(__p, __v);
+}
+__DEVICE__ long long __illAtomicMin_system(long long *__p, long long __v) {
+ return __nvvm_atom_sys_min_gen_ll(__p, __v);
+}
+__DEVICE__ double __int2double_rn(int __a) { return __nv_int2double_rn(__a); }
+__DEVICE__ float __int2float_rd(int __a) { return __nv_int2float_rd(__a); }
+__DEVICE__ float __int2float_rn(int __a) { return __nv_int2float_rn(__a); }
+__DEVICE__ float __int2float_ru(int __a) { return __nv_int2float_ru(__a); }
+__DEVICE__ float __int2float_rz(int __a) { return __nv_int2float_rz(__a); }
+__DEVICE__ float __int_as_float(int __a) { return __nv_int_as_float(__a); }
+__DEVICE__ int __isfinited(double __a) { return __nv_isfinited(__a); }
+__DEVICE__ int __isinf(double __a) { return __nv_isinfd(__a); }
+__DEVICE__ int __isinff(float __a) { return __nv_isinff(__a); }
+__DEVICE__ int __isnan(double __a) { return __nv_isnand(__a); }
+__DEVICE__ int __isnanf(float __a) { return __nv_isnanf(__a); }
+__DEVICE__ double __ll2double_rd(long long __a) {
+ return __nv_ll2double_rd(__a);
+}
+__DEVICE__ double __ll2double_rn(long long __a) {
+ return __nv_ll2double_rn(__a);
+}
+__DEVICE__ double __ll2double_ru(long long __a) {
+ return __nv_ll2double_ru(__a);
+}
+__DEVICE__ double __ll2double_rz(long long __a) {
+ return __nv_ll2double_rz(__a);
+}
+__DEVICE__ float __ll2float_rd(long long __a) { return __nv_ll2float_rd(__a); }
+__DEVICE__ float __ll2float_rn(long long __a) { return __nv_ll2float_rn(__a); }
+__DEVICE__ float __ll2float_ru(long long __a) { return __nv_ll2float_ru(__a); }
+__DEVICE__ float __ll2float_rz(long long __a) { return __nv_ll2float_rz(__a); }
+__DEVICE__ long long __llAtomicAnd(long long *__p, long long __v) {
+ return __nvvm_atom_and_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicAnd_block(long long *__p, long long __v) {
+ return __nvvm_atom_cta_and_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicAnd_system(long long *__p, long long __v) {
+ return __nvvm_atom_sys_and_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicOr(long long *__p, long long __v) {
+ return __nvvm_atom_or_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicOr_block(long long *__p, long long __v) {
+ return __nvvm_atom_cta_or_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicOr_system(long long *__p, long long __v) {
+ return __nvvm_atom_sys_or_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicXor(long long *__p, long long __v) {
+ return __nvvm_atom_xor_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicXor_block(long long *__p, long long __v) {
+ return __nvvm_atom_cta_xor_gen_ll(__p, __v);
+}
+__DEVICE__ long long __llAtomicXor_system(long long *__p, long long __v) {
+ return __nvvm_atom_sys_xor_gen_ll(__p, __v);
+}
+__DEVICE__ float __log10f(float __a) { return __nv_fast_log10f(__a); }
+__DEVICE__ float __log2f(float __a) { return __nv_fast_log2f(__a); }
+__DEVICE__ float __logf(float __a) { return __nv_fast_logf(__a); }
+__DEVICE__ double __longlong_as_double(long long __a) {
+ return __nv_longlong_as_double(__a);
+}
+__DEVICE__ int __mul24(int __a, int __b) { return __nv_mul24(__a, __b); }
+__DEVICE__ long long __mul64hi(long long __a, long long __b) {
+ return __nv_mul64hi(__a, __b);
+}
+__DEVICE__ int __mulhi(int __a, int __b) { return __nv_mulhi(__a, __b); }
+__DEVICE__ unsigned int __pm0(void) { return __nvvm_read_ptx_sreg_pm0(); }
+__DEVICE__ unsigned int __pm1(void) { return __nvvm_read_ptx_sreg_pm1(); }
+__DEVICE__ unsigned int __pm2(void) { return __nvvm_read_ptx_sreg_pm2(); }
+__DEVICE__ unsigned int __pm3(void) { return __nvvm_read_ptx_sreg_pm3(); }
+__DEVICE__ int __popc(int __a) { return __nv_popc(__a); }
+__DEVICE__ int __popcll(long long __a) { return __nv_popcll(__a); }
+__DEVICE__ float __powf(float __a, float __b) {
+ return __nv_fast_powf(__a, __b);
+}
+
+// Parameter must have a known integer value.
+#define __prof_trigger(__a) asm __volatile__("pmevent \t%0;" ::"i"(__a))
+__DEVICE__ int __rhadd(int __a, int __b) { return __nv_rhadd(__a, __b); }
+__DEVICE__ unsigned int __sad(int __a, int __b, unsigned int __c) {
+ return __nv_sad(__a, __b, __c);
+}
+__DEVICE__ float __saturatef(float __a) { return __nv_saturatef(__a); }
+__DEVICE__ int __signbitd(double __a) { return __nv_signbitd(__a); }
+__DEVICE__ int __signbitf(float __a) { return __nv_signbitf(__a); }
+__DEVICE__ void __sincosf(float __a, float *__sptr, float *__cptr) {
+ return __nv_fast_sincosf(__a, __sptr, __cptr);
+}
+__DEVICE__ float __sinf(float __a) { return __nv_fast_sinf(__a); }
+__DEVICE__ int __syncthreads_and(int __a) { return __nvvm_bar0_and(__a); }
+__DEVICE__ int __syncthreads_count(int __a) { return __nvvm_bar0_popc(__a); }
+__DEVICE__ int __syncthreads_or(int __a) { return __nvvm_bar0_or(__a); }
+__DEVICE__ float __tanf(float __a) { return __nv_fast_tanf(__a); }
+__DEVICE__ void __threadfence(void) { __nvvm_membar_gl(); }
+__DEVICE__ void __threadfence_block(void) { __nvvm_membar_cta(); };
+__DEVICE__ void __threadfence_system(void) { __nvvm_membar_sys(); };
+__DEVICE__ void __trap(void) { asm volatile("trap;"); }
+__DEVICE__ unsigned int __uAtomicAdd(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_add_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicAdd_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_add_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicAdd_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_add_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicAnd(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_and_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicAnd_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_and_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicAnd_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_and_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicCAS(unsigned int *__p, unsigned int __cmp,
+ unsigned int __v) {
+ return __nvvm_atom_cas_gen_i((int *)__p, __cmp, __v);
+}
+__DEVICE__ unsigned int
+__uAtomicCAS_block(unsigned int *__p, unsigned int __cmp, unsigned int __v) {
+ return __nvvm_atom_cta_cas_gen_i((int *)__p, __cmp, __v);
+}
+__DEVICE__ unsigned int
+__uAtomicCAS_system(unsigned int *__p, unsigned int __cmp, unsigned int __v) {
+ return __nvvm_atom_sys_cas_gen_i((int *)__p, __cmp, __v);
+}
+__DEVICE__ unsigned int __uAtomicDec(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_dec_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicDec_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_dec_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicDec_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_dec_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicExch(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_xchg_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicExch_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_xchg_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicExch_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_xchg_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicInc(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_inc_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicInc_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_inc_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicInc_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_inc_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicMax(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_max_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicMax_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_max_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicMax_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_max_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicMin(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_min_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicMin_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_min_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicMin_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_min_gen_ui(__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicOr(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_or_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicOr_block(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_cta_or_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicOr_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_or_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicXor(unsigned int *__p, unsigned int __v) {
+ return __nvvm_atom_xor_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicXor_block(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_cta_xor_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uAtomicXor_system(unsigned int *__p,
+ unsigned int __v) {
+ return __nvvm_atom_sys_xor_gen_i((int *)__p, __v);
+}
+__DEVICE__ unsigned int __uhadd(unsigned int __a, unsigned int __b) {
+ return __nv_uhadd(__a, __b);
+}
+__DEVICE__ double __uint2double_rn(unsigned int __a) {
+ return __nv_uint2double_rn(__a);
+}
+__DEVICE__ float __uint2float_rd(unsigned int __a) {
+ return __nv_uint2float_rd(__a);
+}
+__DEVICE__ float __uint2float_rn(unsigned int __a) {
+ return __nv_uint2float_rn(__a);
+}
+__DEVICE__ float __uint2float_ru(unsigned int __a) {
+ return __nv_uint2float_ru(__a);
+}
+__DEVICE__ float __uint2float_rz(unsigned int __a) {
+ return __nv_uint2float_rz(__a);
+}
+__DEVICE__ float __uint_as_float(unsigned int __a) {
+ return __nv_uint_as_float(__a);
+} //
+__DEVICE__ double __ull2double_rd(unsigned long long __a) {
+ return __nv_ull2double_rd(__a);
+}
+__DEVICE__ double __ull2double_rn(unsigned long long __a) {
+ return __nv_ull2double_rn(__a);
+}
+__DEVICE__ double __ull2double_ru(unsigned long long __a) {
+ return __nv_ull2double_ru(__a);
+}
+__DEVICE__ double __ull2double_rz(unsigned long long __a) {
+ return __nv_ull2double_rz(__a);
+}
+__DEVICE__ float __ull2float_rd(unsigned long long __a) {
+ return __nv_ull2float_rd(__a);
+}
+__DEVICE__ float __ull2float_rn(unsigned long long __a) {
+ return __nv_ull2float_rn(__a);
+}
+__DEVICE__ float __ull2float_ru(unsigned long long __a) {
+ return __nv_ull2float_ru(__a);
+}
+__DEVICE__ float __ull2float_rz(unsigned long long __a) {
+ return __nv_ull2float_rz(__a);
+}
+__DEVICE__ unsigned long long __ullAtomicAdd(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_add_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicAdd_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_add_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicAdd_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_add_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicAnd(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_and_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicAnd_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_and_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicAnd_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_and_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicCAS(unsigned long long *__p,
+ unsigned long long __cmp,
+ unsigned long long __v) {
+ return __nvvm_atom_cas_gen_ll((long long *)__p, __cmp, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicCAS_block(unsigned long long *__p,
+ unsigned long long __cmp,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_cas_gen_ll((long long *)__p, __cmp, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicCAS_system(unsigned long long *__p,
+ unsigned long long __cmp,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_cas_gen_ll((long long *)__p, __cmp, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicExch(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_xchg_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicExch_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_xchg_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicExch_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_xchg_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicMax(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_max_gen_ull(__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicMax_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_max_gen_ull(__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicMax_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_max_gen_ull(__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicMin(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_min_gen_ull(__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicMin_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_min_gen_ull(__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicMin_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_min_gen_ull(__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicOr(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_or_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicOr_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_or_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicOr_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_or_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicXor(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_xor_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicXor_block(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_cta_xor_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned long long __ullAtomicXor_system(unsigned long long *__p,
+ unsigned long long __v) {
+ return __nvvm_atom_sys_xor_gen_ll((long long *)__p, __v);
+}
+__DEVICE__ unsigned int __umul24(unsigned int __a, unsigned int __b) {
+ return __nv_umul24(__a, __b);
+}
+__DEVICE__ unsigned long long __umul64hi(unsigned long long __a,
+ unsigned long long __b) {
+ return __nv_umul64hi(__a, __b);
+}
+__DEVICE__ unsigned int __umulhi(unsigned int __a, unsigned int __b) {
+ return __nv_umulhi(__a, __b);
+}
+__DEVICE__ unsigned int __urhadd(unsigned int __a, unsigned int __b) {
+ return __nv_urhadd(__a, __b);
+}
+__DEVICE__ unsigned int __usad(unsigned int __a, unsigned int __b,
+ unsigned int __c) {
+ return __nv_usad(__a, __b, __c);
+}
+
+#if CUDA_VERSION >= 9000 && CUDA_VERSION < 9020
+__DEVICE__ unsigned int __vabs2(unsigned int __a) { return __nv_vabs2(__a); }
+__DEVICE__ unsigned int __vabs4(unsigned int __a) { return __nv_vabs4(__a); }
+__DEVICE__ unsigned int __vabsdiffs2(unsigned int __a, unsigned int __b) {
+ return __nv_vabsdiffs2(__a, __b);
+}
+__DEVICE__ unsigned int __vabsdiffs4(unsigned int __a, unsigned int __b) {
+ return __nv_vabsdiffs4(__a, __b);
+}
+__DEVICE__ unsigned int __vabsdiffu2(unsigned int __a, unsigned int __b) {
+ return __nv_vabsdiffu2(__a, __b);
+}
+__DEVICE__ unsigned int __vabsdiffu4(unsigned int __a, unsigned int __b) {
+ return __nv_vabsdiffu4(__a, __b);
+}
+__DEVICE__ unsigned int __vabsss2(unsigned int __a) {
+ return __nv_vabsss2(__a);
+}
+__DEVICE__ unsigned int __vabsss4(unsigned int __a) {
+ return __nv_vabsss4(__a);
+}
+__DEVICE__ unsigned int __vadd2(unsigned int __a, unsigned int __b) {
+ return __nv_vadd2(__a, __b);
+}
+__DEVICE__ unsigned int __vadd4(unsigned int __a, unsigned int __b) {
+ return __nv_vadd4(__a, __b);
+}
+__DEVICE__ unsigned int __vaddss2(unsigned int __a, unsigned int __b) {
+ return __nv_vaddss2(__a, __b);
+}
+__DEVICE__ unsigned int __vaddss4(unsigned int __a, unsigned int __b) {
+ return __nv_vaddss4(__a, __b);
+}
+__DEVICE__ unsigned int __vaddus2(unsigned int __a, unsigned int __b) {
+ return __nv_vaddus2(__a, __b);
+}
+__DEVICE__ unsigned int __vaddus4(unsigned int __a, unsigned int __b) {
+ return __nv_vaddus4(__a, __b);
+}
+__DEVICE__ unsigned int __vavgs2(unsigned int __a, unsigned int __b) {
+ return __nv_vavgs2(__a, __b);
+}
+__DEVICE__ unsigned int __vavgs4(unsigned int __a, unsigned int __b) {
+ return __nv_vavgs4(__a, __b);
+}
+__DEVICE__ unsigned int __vavgu2(unsigned int __a, unsigned int __b) {
+ return __nv_vavgu2(__a, __b);
+}
+__DEVICE__ unsigned int __vavgu4(unsigned int __a, unsigned int __b) {
+ return __nv_vavgu4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpeq2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpeq2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpeq4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpeq4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpges2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpges2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpges4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpges4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpgeu2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpgeu2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpgeu4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpgeu4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpgts2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpgts2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpgts4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpgts4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpgtu2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpgtu2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpgtu4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpgtu4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmples2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmples2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmples4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmples4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpleu2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpleu2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpleu4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpleu4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmplts2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmplts2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmplts4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmplts4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpltu2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpltu2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpltu4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpltu4(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpne2(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpne2(__a, __b);
+}
+__DEVICE__ unsigned int __vcmpne4(unsigned int __a, unsigned int __b) {
+ return __nv_vcmpne4(__a, __b);
+}
+__DEVICE__ unsigned int __vhaddu2(unsigned int __a, unsigned int __b) {
+ return __nv_vhaddu2(__a, __b);
+}
+__DEVICE__ unsigned int __vhaddu4(unsigned int __a, unsigned int __b) {
+ return __nv_vhaddu4(__a, __b);
+}
+__DEVICE__ unsigned int __vmaxs2(unsigned int __a, unsigned int __b) {
+ return __nv_vmaxs2(__a, __b);
+}
+__DEVICE__ unsigned int __vmaxs4(unsigned int __a, unsigned int __b) {
+ return __nv_vmaxs4(__a, __b);
+}
+__DEVICE__ unsigned int __vmaxu2(unsigned int __a, unsigned int __b) {
+ return __nv_vmaxu2(__a, __b);
+}
+__DEVICE__ unsigned int __vmaxu4(unsigned int __a, unsigned int __b) {
+ return __nv_vmaxu4(__a, __b);
+}
+__DEVICE__ unsigned int __vmins2(unsigned int __a, unsigned int __b) {
+ return __nv_vmins2(__a, __b);
+}
+__DEVICE__ unsigned int __vmins4(unsigned int __a, unsigned int __b) {
+ return __nv_vmins4(__a, __b);
+}
+__DEVICE__ unsigned int __vminu2(unsigned int __a, unsigned int __b) {
+ return __nv_vminu2(__a, __b);
+}
+__DEVICE__ unsigned int __vminu4(unsigned int __a, unsigned int __b) {
+ return __nv_vminu4(__a, __b);
+}
+__DEVICE__ unsigned int __vneg2(unsigned int __a) { return __nv_vneg2(__a); }
+__DEVICE__ unsigned int __vneg4(unsigned int __a) { return __nv_vneg4(__a); }
+__DEVICE__ unsigned int __vnegss2(unsigned int __a) {
+ return __nv_vnegss2(__a);
+}
+__DEVICE__ unsigned int __vnegss4(unsigned int __a) {
+ return __nv_vnegss4(__a);
+}
+__DEVICE__ unsigned int __vsads2(unsigned int __a, unsigned int __b) {
+ return __nv_vsads2(__a, __b);
+}
+__DEVICE__ unsigned int __vsads4(unsigned int __a, unsigned int __b) {
+ return __nv_vsads4(__a, __b);
+}
+__DEVICE__ unsigned int __vsadu2(unsigned int __a, unsigned int __b) {
+ return __nv_vsadu2(__a, __b);
+}
+__DEVICE__ unsigned int __vsadu4(unsigned int __a, unsigned int __b) {
+ return __nv_vsadu4(__a, __b);
+}
+__DEVICE__ unsigned int __vseteq2(unsigned int __a, unsigned int __b) {
+ return __nv_vseteq2(__a, __b);
+}
+__DEVICE__ unsigned int __vseteq4(unsigned int __a, unsigned int __b) {
+ return __nv_vseteq4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetges2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetges2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetges4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetges4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetgeu2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetgeu2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetgeu4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetgeu4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetgts2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetgts2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetgts4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetgts4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetgtu2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetgtu2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetgtu4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetgtu4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetles2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetles2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetles4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetles4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetleu2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetleu2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetleu4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetleu4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetlts2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetlts2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetlts4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetlts4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetltu2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetltu2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetltu4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetltu4(__a, __b);
+}
+__DEVICE__ unsigned int __vsetne2(unsigned int __a, unsigned int __b) {
+ return __nv_vsetne2(__a, __b);
+}
+__DEVICE__ unsigned int __vsetne4(unsigned int __a, unsigned int __b) {
+ return __nv_vsetne4(__a, __b);
+}
+__DEVICE__ unsigned int __vsub2(unsigned int __a, unsigned int __b) {
+ return __nv_vsub2(__a, __b);
+}
+__DEVICE__ unsigned int __vsub4(unsigned int __a, unsigned int __b) {
+ return __nv_vsub4(__a, __b);
+}
+__DEVICE__ unsigned int __vsubss2(unsigned int __a, unsigned int __b) {
+ return __nv_vsubss2(__a, __b);
+}
+__DEVICE__ unsigned int __vsubss4(unsigned int __a, unsigned int __b) {
+ return __nv_vsubss4(__a, __b);
+}
+__DEVICE__ unsigned int __vsubus2(unsigned int __a, unsigned int __b) {
+ return __nv_vsubus2(__a, __b);
+}
+__DEVICE__ unsigned int __vsubus4(unsigned int __a, unsigned int __b) {
+ return __nv_vsubus4(__a, __b);
+}
+#else // CUDA_VERSION >= 9020
+// CUDA no longer provides inline assembly (or bitcode) implementation of these
+// functions, so we have to reimplment them. The implementation is naive and is
+// not optimized for performance.
+
+// Helper function to convert N-bit boolean subfields into all-0 or all-1.
+// E.g. __bool2mask(0x01000100,8) -> 0xff00ff00
+// __bool2mask(0x00010000,16) -> 0xffff0000
+__DEVICE__ unsigned int __bool2mask(unsigned int __a, int shift) {
+ return (__a << shift) - __a;
+}
+__DEVICE__ unsigned int __vabs2(unsigned int __a) {
+ unsigned int r;
+ asm("vabsdiff2.s32.s32.s32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(0), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vabs4(unsigned int __a) {
+ unsigned int r;
+ asm("vabsdiff4.s32.s32.s32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(0), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vabsdiffs2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff2.s32.s32.s32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+
+__DEVICE__ unsigned int __vabsdiffs4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff4.s32.s32.s32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vabsdiffu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff2.u32.u32.u32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vabsdiffu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff4.u32.u32.u32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vabsss2(unsigned int __a) {
+ unsigned int r;
+ asm("vabsdiff2.s32.s32.s32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(0), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vabsss4(unsigned int __a) {
+ unsigned int r;
+ asm("vabsdiff4.s32.s32.s32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(0), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vadd2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vadd2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vadd4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vadd4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vaddss2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vadd2.s32.s32.s32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vaddss4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vadd4.s32.s32.s32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vaddus2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vadd2.u32.u32.u32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vaddus4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vadd4.u32.u32.u32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vavgs2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vavrg2.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vavgs4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vavrg4.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vavgu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vavrg2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vavgu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vavrg4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vseteq2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.u32.u32.eq %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpeq2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vseteq2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vseteq4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.u32.u32.eq %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpeq4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vseteq4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetges2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.s32.s32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpges2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetges2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetges4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.s32.s32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpges4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetges4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetgeu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.u32.u32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpgeu2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetgeu2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetgeu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.u32.u32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpgeu4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetgeu4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetgts2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.s32.s32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpgts2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetgts2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetgts4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.s32.s32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpgts4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetgts4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetgtu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.u32.u32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpgtu2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetgtu2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetgtu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.u32.u32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpgtu4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetgtu4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetles2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.s32.s32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmples2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetles2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetles4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.s32.s32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmples4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetles4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetleu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.u32.u32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpleu2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetleu2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetleu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.u32.u32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpleu4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetleu4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetlts2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.s32.s32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmplts2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetlts2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetlts4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.s32.s32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmplts4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetlts4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetltu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.u32.u32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpltu2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetltu2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetltu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.u32.u32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpltu4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetltu4(__a, __b), 8);
+}
+__DEVICE__ unsigned int __vsetne2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset2.u32.u32.ne %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpne2(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetne2(__a, __b), 16);
+}
+__DEVICE__ unsigned int __vsetne4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vset4.u32.u32.ne %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vcmpne4(unsigned int __a, unsigned int __b) {
+ return __bool2mask(__vsetne4(__a, __b), 8);
+}
+
+// Based on ITEM 23 in AIM-239: http://dspace.mit.edu/handle/1721.1/6086
+// (a & b) + (a | b) = a + b = (a ^ b) + 2 * (a & b) =>
+// (a + b) / 2 = ((a ^ b) >> 1) + (a & b)
+// To operate on multiple sub-elements we need to make sure to mask out bits
+// that crossed over into adjacent elements during the shift.
+__DEVICE__ unsigned int __vhaddu2(unsigned int __a, unsigned int __b) {
+ return (((__a ^ __b) >> 1) & ~0x80008000u) + (__a & __b);
+}
+__DEVICE__ unsigned int __vhaddu4(unsigned int __a, unsigned int __b) {
+ return (((__a ^ __b) >> 1) & ~0x80808080u) + (__a & __b);
+}
+
+__DEVICE__ unsigned int __vmaxs2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ if ((__a & 0x8000) && (__b & 0x8000)) {
+ // Work around a bug in ptxas which produces invalid result if low element
+ // is negative.
+ unsigned mask = __vcmpgts2(__a, __b);
+ r = (__a & mask) | (__b & ~mask);
+ } else {
+ asm("vmax2.s32.s32.s32 %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ }
+ return r;
+}
+__DEVICE__ unsigned int __vmaxs4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmax4.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vmaxu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmax2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vmaxu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmax4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vmins2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmin2.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vmins4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmin4.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vminu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmin2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vminu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vmin4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vsads2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff2.s32.s32.s32.add %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vsads4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff4.s32.s32.s32.add %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vsadu2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff2.u32.u32.u32.add %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vsadu4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vabsdiff4.u32.u32.u32.add %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+
+__DEVICE__ unsigned int __vsub2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vsub2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vneg2(unsigned int __a) { return __vsub2(0, __a); }
+
+__DEVICE__ unsigned int __vsub4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vsub4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vneg4(unsigned int __a) { return __vsub4(0, __a); }
+__DEVICE__ unsigned int __vsubss2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vsub2.s32.s32.s32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vnegss2(unsigned int __a) {
+ return __vsubss2(0, __a);
+}
+__DEVICE__ unsigned int __vsubss4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vsub4.s32.s32.s32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vnegss4(unsigned int __a) {
+ return __vsubss4(0, __a);
+}
+__DEVICE__ unsigned int __vsubus2(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vsub2.u32.u32.u32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+__DEVICE__ unsigned int __vsubus4(unsigned int __a, unsigned int __b) {
+ unsigned int r;
+ asm("vsub4.u32.u32.u32.sat %0,%1,%2,%3;"
+ : "=r"(r)
+ : "r"(__a), "r"(__b), "r"(0));
+ return r;
+}
+#endif // CUDA_VERSION >= 9020
+__DEVICE__ int abs(int __a) { return __nv_abs(__a); }
+__DEVICE__ double acos(double __a) { return __nv_acos(__a); }
+__DEVICE__ float acosf(float __a) { return __nv_acosf(__a); }
+__DEVICE__ double acosh(double __a) { return __nv_acosh(__a); }
+__DEVICE__ float acoshf(float __a) { return __nv_acoshf(__a); }
+__DEVICE__ double asin(double __a) { return __nv_asin(__a); }
+__DEVICE__ float asinf(float __a) { return __nv_asinf(__a); }
+__DEVICE__ double asinh(double __a) { return __nv_asinh(__a); }
+__DEVICE__ float asinhf(float __a) { return __nv_asinhf(__a); }
+__DEVICE__ double atan(double __a) { return __nv_atan(__a); }
+__DEVICE__ double atan2(double __a, double __b) { return __nv_atan2(__a, __b); }
+__DEVICE__ float atan2f(float __a, float __b) { return __nv_atan2f(__a, __b); }
+__DEVICE__ float atanf(float __a) { return __nv_atanf(__a); }
+__DEVICE__ double atanh(double __a) { return __nv_atanh(__a); }
+__DEVICE__ float atanhf(float __a) { return __nv_atanhf(__a); }
+__DEVICE__ double cbrt(double __a) { return __nv_cbrt(__a); }
+__DEVICE__ float cbrtf(float __a) { return __nv_cbrtf(__a); }
+__DEVICE__ double ceil(double __a) { return __nv_ceil(__a); }
+__DEVICE__ float ceilf(float __a) { return __nv_ceilf(__a); }
+__DEVICE__ int clock() { return __nvvm_read_ptx_sreg_clock(); }
+__DEVICE__ long long clock64() { return __nvvm_read_ptx_sreg_clock64(); }
+__DEVICE__ double copysign(double __a, double __b) {
+ return __nv_copysign(__a, __b);
+}
+__DEVICE__ float copysignf(float __a, float __b) {
+ return __nv_copysignf(__a, __b);
+}
+__DEVICE__ double cos(double __a) { return __nv_cos(__a); }
+__DEVICE__ float cosf(float __a) {
+ return __FAST_OR_SLOW(__nv_fast_cosf, __nv_cosf)(__a);
+}
+__DEVICE__ double cosh(double __a) { return __nv_cosh(__a); }
+__DEVICE__ float coshf(float __a) { return __nv_coshf(__a); }
+__DEVICE__ double cospi(double __a) { return __nv_cospi(__a); }
+__DEVICE__ float cospif(float __a) { return __nv_cospif(__a); }
+__DEVICE__ double cyl_bessel_i0(double __a) { return __nv_cyl_bessel_i0(__a); }
+__DEVICE__ float cyl_bessel_i0f(float __a) { return __nv_cyl_bessel_i0f(__a); }
+__DEVICE__ double cyl_bessel_i1(double __a) { return __nv_cyl_bessel_i1(__a); }
+__DEVICE__ float cyl_bessel_i1f(float __a) { return __nv_cyl_bessel_i1f(__a); }
+__DEVICE__ double erf(double __a) { return __nv_erf(__a); }
+__DEVICE__ double erfc(double __a) { return __nv_erfc(__a); }
+__DEVICE__ float erfcf(float __a) { return __nv_erfcf(__a); }
+__DEVICE__ double erfcinv(double __a) { return __nv_erfcinv(__a); }
+__DEVICE__ float erfcinvf(float __a) { return __nv_erfcinvf(__a); }
+__DEVICE__ double erfcx(double __a) { return __nv_erfcx(__a); }
+__DEVICE__ float erfcxf(float __a) { return __nv_erfcxf(__a); }
+__DEVICE__ float erff(float __a) { return __nv_erff(__a); }
+__DEVICE__ double erfinv(double __a) { return __nv_erfinv(__a); }
+__DEVICE__ float erfinvf(float __a) { return __nv_erfinvf(__a); }
+__DEVICE__ double exp(double __a) { return __nv_exp(__a); }
+__DEVICE__ double exp10(double __a) { return __nv_exp10(__a); }
+__DEVICE__ float exp10f(float __a) { return __nv_exp10f(__a); }
+__DEVICE__ double exp2(double __a) { return __nv_exp2(__a); }
+__DEVICE__ float exp2f(float __a) { return __nv_exp2f(__a); }
+__DEVICE__ float expf(float __a) { return __nv_expf(__a); }
+__DEVICE__ double expm1(double __a) { return __nv_expm1(__a); }
+__DEVICE__ float expm1f(float __a) { return __nv_expm1f(__a); }
+__DEVICE__ double fabs(double __a) { return __nv_fabs(__a); }
+__DEVICE__ float fabsf(float __a) { return __nv_fabsf(__a); }
+__DEVICE__ double fdim(double __a, double __b) { return __nv_fdim(__a, __b); }
+__DEVICE__ float fdimf(float __a, float __b) { return __nv_fdimf(__a, __b); }
+__DEVICE__ double fdivide(double __a, double __b) { return __a / __b; }
+__DEVICE__ float fdividef(float __a, float __b) {
+#if __FAST_MATH__ && !__CUDA_PREC_DIV
+ return __nv_fast_fdividef(__a, __b);
+#else
+ return __a / __b;
+#endif
+}
+__DEVICE__ double floor(double __f) { return __nv_floor(__f); }
+__DEVICE__ float floorf(float __f) { return __nv_floorf(__f); }
+__DEVICE__ double fma(double __a, double __b, double __c) {
+ return __nv_fma(__a, __b, __c);
+}
+__DEVICE__ float fmaf(float __a, float __b, float __c) {
+ return __nv_fmaf(__a, __b, __c);
+}
+__DEVICE__ double fmax(double __a, double __b) { return __nv_fmax(__a, __b); }
+__DEVICE__ float fmaxf(float __a, float __b) { return __nv_fmaxf(__a, __b); }
+__DEVICE__ double fmin(double __a, double __b) { return __nv_fmin(__a, __b); }
+__DEVICE__ float fminf(float __a, float __b) { return __nv_fminf(__a, __b); }
+__DEVICE__ double fmod(double __a, double __b) { return __nv_fmod(__a, __b); }
+__DEVICE__ float fmodf(float __a, float __b) { return __nv_fmodf(__a, __b); }
+__DEVICE__ double frexp(double __a, int *__b) { return __nv_frexp(__a, __b); }
+__DEVICE__ float frexpf(float __a, int *__b) { return __nv_frexpf(__a, __b); }
+__DEVICE__ double hypot(double __a, double __b) { return __nv_hypot(__a, __b); }
+__DEVICE__ float hypotf(float __a, float __b) { return __nv_hypotf(__a, __b); }
+__DEVICE__ int ilogb(double __a) { return __nv_ilogb(__a); }
+__DEVICE__ int ilogbf(float __a) { return __nv_ilogbf(__a); }
+__DEVICE__ double j0(double __a) { return __nv_j0(__a); }
+__DEVICE__ float j0f(float __a) { return __nv_j0f(__a); }
+__DEVICE__ double j1(double __a) { return __nv_j1(__a); }
+__DEVICE__ float j1f(float __a) { return __nv_j1f(__a); }
+__DEVICE__ double jn(int __n, double __a) { return __nv_jn(__n, __a); }
+__DEVICE__ float jnf(int __n, float __a) { return __nv_jnf(__n, __a); }
+#if defined(__LP64__)
+__DEVICE__ long labs(long __a) { return llabs(__a); };
+#else
+__DEVICE__ long labs(long __a) { return __nv_abs(__a); };
+#endif
+__DEVICE__ double ldexp(double __a, int __b) { return __nv_ldexp(__a, __b); }
+__DEVICE__ float ldexpf(float __a, int __b) { return __nv_ldexpf(__a, __b); }
+__DEVICE__ double lgamma(double __a) { return __nv_lgamma(__a); }
+__DEVICE__ float lgammaf(float __a) { return __nv_lgammaf(__a); }
+__DEVICE__ long long llabs(long long __a) { return __nv_llabs(__a); }
+__DEVICE__ long long llmax(long long __a, long long __b) {
+ return __nv_llmax(__a, __b);
+}
+__DEVICE__ long long llmin(long long __a, long long __b) {
+ return __nv_llmin(__a, __b);
+}
+__DEVICE__ long long llrint(double __a) { return __nv_llrint(__a); }
+__DEVICE__ long long llrintf(float __a) { return __nv_llrintf(__a); }
+__DEVICE__ long long llround(double __a) { return __nv_llround(__a); }
+__DEVICE__ long long llroundf(float __a) { return __nv_llroundf(__a); }
+__DEVICE__ double log(double __a) { return __nv_log(__a); }
+__DEVICE__ double log10(double __a) { return __nv_log10(__a); }
+__DEVICE__ float log10f(float __a) { return __nv_log10f(__a); }
+__DEVICE__ double log1p(double __a) { return __nv_log1p(__a); }
+__DEVICE__ float log1pf(float __a) { return __nv_log1pf(__a); }
+__DEVICE__ double log2(double __a) { return __nv_log2(__a); }
+__DEVICE__ float log2f(float __a) {
+ return __FAST_OR_SLOW(__nv_fast_log2f, __nv_log2f)(__a);
+}
+__DEVICE__ double logb(double __a) { return __nv_logb(__a); }
+__DEVICE__ float logbf(float __a) { return __nv_logbf(__a); }
+__DEVICE__ float logf(float __a) {
+ return __FAST_OR_SLOW(__nv_fast_logf, __nv_logf)(__a);
+}
+#if defined(__LP64__)
+__DEVICE__ long lrint(double __a) { return llrint(__a); }
+__DEVICE__ long lrintf(float __a) { return __float2ll_rn(__a); }
+__DEVICE__ long lround(double __a) { return llround(__a); }
+__DEVICE__ long lroundf(float __a) { return llroundf(__a); }
+#else
+__DEVICE__ long lrint(double __a) { return (long)rint(__a); }
+__DEVICE__ long lrintf(float __a) { return __float2int_rn(__a); }
+__DEVICE__ long lround(double __a) { return round(__a); }
+__DEVICE__ long lroundf(float __a) { return roundf(__a); }
+#endif
+__DEVICE__ int max(int __a, int __b) { return __nv_max(__a, __b); }
+__DEVICE__ void *memcpy(void *__a, const void *__b, size_t __c) {
+ return __builtin_memcpy(__a, __b, __c);
+}
+__DEVICE__ void *memset(void *__a, int __b, size_t __c) {
+ return __builtin_memset(__a, __b, __c);
+}
+__DEVICE__ int min(int __a, int __b) { return __nv_min(__a, __b); }
+__DEVICE__ double modf(double __a, double *__b) { return __nv_modf(__a, __b); }
+__DEVICE__ float modff(float __a, float *__b) { return __nv_modff(__a, __b); }
+__DEVICE__ double nearbyint(double __a) { return __nv_nearbyint(__a); }
+__DEVICE__ float nearbyintf(float __a) { return __nv_nearbyintf(__a); }
+__DEVICE__ double nextafter(double __a, double __b) {
+ return __nv_nextafter(__a, __b);
+}
+__DEVICE__ float nextafterf(float __a, float __b) {
+ return __nv_nextafterf(__a, __b);
+}
+__DEVICE__ double norm(int __dim, const double *__t) {
+ return __nv_norm(__dim, __t);
+}
+__DEVICE__ double norm3d(double __a, double __b, double __c) {
+ return __nv_norm3d(__a, __b, __c);
+}
+__DEVICE__ float norm3df(float __a, float __b, float __c) {
+ return __nv_norm3df(__a, __b, __c);
+}
+__DEVICE__ double norm4d(double __a, double __b, double __c, double __d) {
+ return __nv_norm4d(__a, __b, __c, __d);
+}
+__DEVICE__ float norm4df(float __a, float __b, float __c, float __d) {
+ return __nv_norm4df(__a, __b, __c, __d);
+}
+__DEVICE__ double normcdf(double __a) { return __nv_normcdf(__a); }
+__DEVICE__ float normcdff(float __a) { return __nv_normcdff(__a); }
+__DEVICE__ double normcdfinv(double __a) { return __nv_normcdfinv(__a); }
+__DEVICE__ float normcdfinvf(float __a) { return __nv_normcdfinvf(__a); }
+__DEVICE__ float normf(int __dim, const float *__t) {
+ return __nv_normf(__dim, __t);
+}
+__DEVICE__ double pow(double __a, double __b) { return __nv_pow(__a, __b); }
+__DEVICE__ float powf(float __a, float __b) { return __nv_powf(__a, __b); }
+__DEVICE__ double powi(double __a, int __b) { return __nv_powi(__a, __b); }
+__DEVICE__ float powif(float __a, int __b) { return __nv_powif(__a, __b); }
+__DEVICE__ double rcbrt(double __a) { return __nv_rcbrt(__a); }
+__DEVICE__ float rcbrtf(float __a) { return __nv_rcbrtf(__a); }
+__DEVICE__ double remainder(double __a, double __b) {
+ return __nv_remainder(__a, __b);
+}
+__DEVICE__ float remainderf(float __a, float __b) {
+ return __nv_remainderf(__a, __b);
+}
+__DEVICE__ double remquo(double __a, double __b, int *__c) {
+ return __nv_remquo(__a, __b, __c);
+}
+__DEVICE__ float remquof(float __a, float __b, int *__c) {
+ return __nv_remquof(__a, __b, __c);
+}
+__DEVICE__ double rhypot(double __a, double __b) {
+ return __nv_rhypot(__a, __b);
+}
+__DEVICE__ float rhypotf(float __a, float __b) {
+ return __nv_rhypotf(__a, __b);
+}
+__DEVICE__ double rint(double __a) { return __nv_rint(__a); }
+__DEVICE__ float rintf(float __a) { return __nv_rintf(__a); }
+__DEVICE__ double rnorm(int __a, const double *__b) {
+ return __nv_rnorm(__a, __b);
+}
+__DEVICE__ double rnorm3d(double __a, double __b, double __c) {
+ return __nv_rnorm3d(__a, __b, __c);
+}
+__DEVICE__ float rnorm3df(float __a, float __b, float __c) {
+ return __nv_rnorm3df(__a, __b, __c);
+}
+__DEVICE__ double rnorm4d(double __a, double __b, double __c, double __d) {
+ return __nv_rnorm4d(__a, __b, __c, __d);
+}
+__DEVICE__ float rnorm4df(float __a, float __b, float __c, float __d) {
+ return __nv_rnorm4df(__a, __b, __c, __d);
+}
+__DEVICE__ float rnormf(int __dim, const float *__t) {
+ return __nv_rnormf(__dim, __t);
+}
+__DEVICE__ double round(double __a) { return __nv_round(__a); }
+__DEVICE__ float roundf(float __a) { return __nv_roundf(__a); }
+__DEVICE__ double rsqrt(double __a) { return __nv_rsqrt(__a); }
+__DEVICE__ float rsqrtf(float __a) { return __nv_rsqrtf(__a); }
+__DEVICE__ double scalbn(double __a, int __b) { return __nv_scalbn(__a, __b); }
+__DEVICE__ float scalbnf(float __a, int __b) { return __nv_scalbnf(__a, __b); }
+__DEVICE__ double scalbln(double __a, long __b) {
+ if (__b > INT_MAX)
+ return __a > 0 ? HUGE_VAL : -HUGE_VAL;
+ if (__b < INT_MIN)
+ return __a > 0 ? 0.0 : -0.0;
+ return scalbn(__a, (int)__b);
+}
+__DEVICE__ float scalblnf(float __a, long __b) {
+ if (__b > INT_MAX)
+ return __a > 0 ? HUGE_VALF : -HUGE_VALF;
+ if (__b < INT_MIN)
+ return __a > 0 ? 0.f : -0.f;
+ return scalbnf(__a, (int)__b);
+}
+__DEVICE__ double sin(double __a) { return __nv_sin(__a); }
+__DEVICE__ void sincos(double __a, double *__sptr, double *__cptr) {
+ return __nv_sincos(__a, __sptr, __cptr);
+}
+__DEVICE__ void sincosf(float __a, float *__sptr, float *__cptr) {
+ return __FAST_OR_SLOW(__nv_fast_sincosf, __nv_sincosf)(__a, __sptr, __cptr);
+}
+__DEVICE__ void sincospi(double __a, double *__sptr, double *__cptr) {
+ return __nv_sincospi(__a, __sptr, __cptr);
+}
+__DEVICE__ void sincospif(float __a, float *__sptr, float *__cptr) {
+ return __nv_sincospif(__a, __sptr, __cptr);
+}
+__DEVICE__ float sinf(float __a) {
+ return __FAST_OR_SLOW(__nv_fast_sinf, __nv_sinf)(__a);
+}
+__DEVICE__ double sinh(double __a) { return __nv_sinh(__a); }
+__DEVICE__ float sinhf(float __a) { return __nv_sinhf(__a); }
+__DEVICE__ double sinpi(double __a) { return __nv_sinpi(__a); }
+__DEVICE__ float sinpif(float __a) { return __nv_sinpif(__a); }
+__DEVICE__ double sqrt(double __a) { return __nv_sqrt(__a); }
+__DEVICE__ float sqrtf(float __a) { return __nv_sqrtf(__a); }
+__DEVICE__ double tan(double __a) { return __nv_tan(__a); }
+__DEVICE__ float tanf(float __a) { return __nv_tanf(__a); }
+__DEVICE__ double tanh(double __a) { return __nv_tanh(__a); }
+__DEVICE__ float tanhf(float __a) { return __nv_tanhf(__a); }
+__DEVICE__ double tgamma(double __a) { return __nv_tgamma(__a); }
+__DEVICE__ float tgammaf(float __a) { return __nv_tgammaf(__a); }
+__DEVICE__ double trunc(double __a) { return __nv_trunc(__a); }
+__DEVICE__ float truncf(float __a) { return __nv_truncf(__a); }
+__DEVICE__ unsigned long long ullmax(unsigned long long __a,
+ unsigned long long __b) {
+ return __nv_ullmax(__a, __b);
+}
+__DEVICE__ unsigned long long ullmin(unsigned long long __a,
+ unsigned long long __b) {
+ return __nv_ullmin(__a, __b);
+}
+__DEVICE__ unsigned int umax(unsigned int __a, unsigned int __b) {
+ return __nv_umax(__a, __b);
+}
+__DEVICE__ unsigned int umin(unsigned int __a, unsigned int __b) {
+ return __nv_umin(__a, __b);
+}
+__DEVICE__ double y0(double __a) { return __nv_y0(__a); }
+__DEVICE__ float y0f(float __a) { return __nv_y0f(__a); }
+__DEVICE__ double y1(double __a) { return __nv_y1(__a); }
+__DEVICE__ float y1f(float __a) { return __nv_y1f(__a); }
+__DEVICE__ double yn(int __a, double __b) { return __nv_yn(__a, __b); }
+__DEVICE__ float ynf(int __a, float __b) { return __nv_ynf(__a, __b); }
+
+#pragma pop_macro("__DEVICE__")
+#pragma pop_macro("__FAST_OR_SLOW")
+#endif // __CLANG_CUDA_DEVICE_FUNCTIONS_H__
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 1794eb3dc1d6..3c0cde94ed44 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h
@@ -277,6 +277,9 @@ inline __device__ long long __ldg(const long long *ptr) {
inline __device__ unsigned char __ldg(const unsigned char *ptr) {
return __nvvm_ldg_uc(ptr);
}
+inline __device__ signed char __ldg(const signed char *ptr) {
+ return __nvvm_ldg_uc((const unsigned char *)ptr);
+}
inline __device__ unsigned short __ldg(const unsigned short *ptr) {
return __nvvm_ldg_us(ptr);
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_libdevice_declares.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_libdevice_declares.h
new file mode 100644
index 000000000000..71df7f849d15
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_libdevice_declares.h
@@ -0,0 +1,466 @@
+/*===-- __clang_cuda_libdevice_declares.h - decls for libdevice functions --===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __CLANG_CUDA_LIBDEVICE_DECLARES_H__
+#define __CLANG_CUDA_LIBDEVICE_DECLARES_H__
+
+extern "C" {
+
+__device__ int __nv_abs(int __a);
+__device__ double __nv_acos(double __a);
+__device__ float __nv_acosf(float __a);
+__device__ double __nv_acosh(double __a);
+__device__ float __nv_acoshf(float __a);
+__device__ double __nv_asin(double __a);
+__device__ float __nv_asinf(float __a);
+__device__ double __nv_asinh(double __a);
+__device__ float __nv_asinhf(float __a);
+__device__ double __nv_atan2(double __a, double __b);
+__device__ float __nv_atan2f(float __a, float __b);
+__device__ double __nv_atan(double __a);
+__device__ float __nv_atanf(float __a);
+__device__ double __nv_atanh(double __a);
+__device__ float __nv_atanhf(float __a);
+__device__ int __nv_brev(int __a);
+__device__ long long __nv_brevll(long long __a);
+__device__ int __nv_byte_perm(int __a, int __b, int __c);
+__device__ double __nv_cbrt(double __a);
+__device__ float __nv_cbrtf(float __a);
+__device__ double __nv_ceil(double __a);
+__device__ float __nv_ceilf(float __a);
+__device__ int __nv_clz(int __a);
+__device__ int __nv_clzll(long long __a);
+__device__ double __nv_copysign(double __a, double __b);
+__device__ float __nv_copysignf(float __a, float __b);
+__device__ double __nv_cos(double __a);
+__device__ float __nv_cosf(float __a);
+__device__ double __nv_cosh(double __a);
+__device__ float __nv_coshf(float __a);
+__device__ double __nv_cospi(double __a);
+__device__ float __nv_cospif(float __a);
+__device__ double __nv_cyl_bessel_i0(double __a);
+__device__ float __nv_cyl_bessel_i0f(float __a);
+__device__ double __nv_cyl_bessel_i1(double __a);
+__device__ float __nv_cyl_bessel_i1f(float __a);
+__device__ double __nv_dadd_rd(double __a, double __b);
+__device__ double __nv_dadd_rn(double __a, double __b);
+__device__ double __nv_dadd_ru(double __a, double __b);
+__device__ double __nv_dadd_rz(double __a, double __b);
+__device__ double __nv_ddiv_rd(double __a, double __b);
+__device__ double __nv_ddiv_rn(double __a, double __b);
+__device__ double __nv_ddiv_ru(double __a, double __b);
+__device__ double __nv_ddiv_rz(double __a, double __b);
+__device__ double __nv_dmul_rd(double __a, double __b);
+__device__ double __nv_dmul_rn(double __a, double __b);
+__device__ double __nv_dmul_ru(double __a, double __b);
+__device__ double __nv_dmul_rz(double __a, double __b);
+__device__ float __nv_double2float_rd(double __a);
+__device__ float __nv_double2float_rn(double __a);
+__device__ float __nv_double2float_ru(double __a);
+__device__ float __nv_double2float_rz(double __a);
+__device__ int __nv_double2hiint(double __a);
+__device__ int __nv_double2int_rd(double __a);
+__device__ int __nv_double2int_rn(double __a);
+__device__ int __nv_double2int_ru(double __a);
+__device__ int __nv_double2int_rz(double __a);
+__device__ long long __nv_double2ll_rd(double __a);
+__device__ long long __nv_double2ll_rn(double __a);
+__device__ long long __nv_double2ll_ru(double __a);
+__device__ long long __nv_double2ll_rz(double __a);
+__device__ int __nv_double2loint(double __a);
+__device__ unsigned int __nv_double2uint_rd(double __a);
+__device__ unsigned int __nv_double2uint_rn(double __a);
+__device__ unsigned int __nv_double2uint_ru(double __a);
+__device__ unsigned int __nv_double2uint_rz(double __a);
+__device__ unsigned long long __nv_double2ull_rd(double __a);
+__device__ unsigned long long __nv_double2ull_rn(double __a);
+__device__ unsigned long long __nv_double2ull_ru(double __a);
+__device__ unsigned long long __nv_double2ull_rz(double __a);
+__device__ unsigned long long __nv_double_as_longlong(double __a);
+__device__ double __nv_drcp_rd(double __a);
+__device__ double __nv_drcp_rn(double __a);
+__device__ double __nv_drcp_ru(double __a);
+__device__ double __nv_drcp_rz(double __a);
+__device__ double __nv_dsqrt_rd(double __a);
+__device__ double __nv_dsqrt_rn(double __a);
+__device__ double __nv_dsqrt_ru(double __a);
+__device__ double __nv_dsqrt_rz(double __a);
+__device__ double __nv_dsub_rd(double __a, double __b);
+__device__ double __nv_dsub_rn(double __a, double __b);
+__device__ double __nv_dsub_ru(double __a, double __b);
+__device__ double __nv_dsub_rz(double __a, double __b);
+__device__ double __nv_erfc(double __a);
+__device__ float __nv_erfcf(float __a);
+__device__ double __nv_erfcinv(double __a);
+__device__ float __nv_erfcinvf(float __a);
+__device__ double __nv_erfcx(double __a);
+__device__ float __nv_erfcxf(float __a);
+__device__ double __nv_erf(double __a);
+__device__ float __nv_erff(float __a);
+__device__ double __nv_erfinv(double __a);
+__device__ float __nv_erfinvf(float __a);
+__device__ double __nv_exp10(double __a);
+__device__ float __nv_exp10f(float __a);
+__device__ double __nv_exp2(double __a);
+__device__ float __nv_exp2f(float __a);
+__device__ double __nv_exp(double __a);
+__device__ float __nv_expf(float __a);
+__device__ double __nv_expm1(double __a);
+__device__ float __nv_expm1f(float __a);
+__device__ double __nv_fabs(double __a);
+__device__ float __nv_fabsf(float __a);
+__device__ float __nv_fadd_rd(float __a, float __b);
+__device__ float __nv_fadd_rn(float __a, float __b);
+__device__ float __nv_fadd_ru(float __a, float __b);
+__device__ float __nv_fadd_rz(float __a, float __b);
+__device__ float __nv_fast_cosf(float __a);
+__device__ float __nv_fast_exp10f(float __a);
+__device__ float __nv_fast_expf(float __a);
+__device__ float __nv_fast_fdividef(float __a, float __b);
+__device__ float __nv_fast_log10f(float __a);
+__device__ float __nv_fast_log2f(float __a);
+__device__ float __nv_fast_logf(float __a);
+__device__ float __nv_fast_powf(float __a, float __b);
+__device__ void __nv_fast_sincosf(float __a, float *__sptr, float *__cptr);
+__device__ float __nv_fast_sinf(float __a);
+__device__ float __nv_fast_tanf(float __a);
+__device__ double __nv_fdim(double __a, double __b);
+__device__ float __nv_fdimf(float __a, float __b);
+__device__ float __nv_fdiv_rd(float __a, float __b);
+__device__ float __nv_fdiv_rn(float __a, float __b);
+__device__ float __nv_fdiv_ru(float __a, float __b);
+__device__ float __nv_fdiv_rz(float __a, float __b);
+__device__ int __nv_ffs(int __a);
+__device__ int __nv_ffsll(long long __a);
+__device__ int __nv_finitef(float __a);
+__device__ unsigned short __nv_float2half_rn(float __a);
+__device__ int __nv_float2int_rd(float __a);
+__device__ int __nv_float2int_rn(float __a);
+__device__ int __nv_float2int_ru(float __a);
+__device__ int __nv_float2int_rz(float __a);
+__device__ long long __nv_float2ll_rd(float __a);
+__device__ long long __nv_float2ll_rn(float __a);
+__device__ long long __nv_float2ll_ru(float __a);
+__device__ long long __nv_float2ll_rz(float __a);
+__device__ unsigned int __nv_float2uint_rd(float __a);
+__device__ unsigned int __nv_float2uint_rn(float __a);
+__device__ unsigned int __nv_float2uint_ru(float __a);
+__device__ unsigned int __nv_float2uint_rz(float __a);
+__device__ unsigned long long __nv_float2ull_rd(float __a);
+__device__ unsigned long long __nv_float2ull_rn(float __a);
+__device__ unsigned long long __nv_float2ull_ru(float __a);
+__device__ unsigned long long __nv_float2ull_rz(float __a);
+__device__ int __nv_float_as_int(float __a);
+__device__ unsigned int __nv_float_as_uint(float __a);
+__device__ double __nv_floor(double __a);
+__device__ float __nv_floorf(float __a);
+__device__ double __nv_fma(double __a, double __b, double __c);
+__device__ float __nv_fmaf(float __a, float __b, float __c);
+__device__ float __nv_fmaf_ieee_rd(float __a, float __b, float __c);
+__device__ float __nv_fmaf_ieee_rn(float __a, float __b, float __c);
+__device__ float __nv_fmaf_ieee_ru(float __a, float __b, float __c);
+__device__ float __nv_fmaf_ieee_rz(float __a, float __b, float __c);
+__device__ float __nv_fmaf_rd(float __a, float __b, float __c);
+__device__ float __nv_fmaf_rn(float __a, float __b, float __c);
+__device__ float __nv_fmaf_ru(float __a, float __b, float __c);
+__device__ float __nv_fmaf_rz(float __a, float __b, float __c);
+__device__ double __nv_fma_rd(double __a, double __b, double __c);
+__device__ double __nv_fma_rn(double __a, double __b, double __c);
+__device__ double __nv_fma_ru(double __a, double __b, double __c);
+__device__ double __nv_fma_rz(double __a, double __b, double __c);
+__device__ double __nv_fmax(double __a, double __b);
+__device__ float __nv_fmaxf(float __a, float __b);
+__device__ double __nv_fmin(double __a, double __b);
+__device__ float __nv_fminf(float __a, float __b);
+__device__ double __nv_fmod(double __a, double __b);
+__device__ float __nv_fmodf(float __a, float __b);
+__device__ float __nv_fmul_rd(float __a, float __b);
+__device__ float __nv_fmul_rn(float __a, float __b);
+__device__ float __nv_fmul_ru(float __a, float __b);
+__device__ float __nv_fmul_rz(float __a, float __b);
+__device__ float __nv_frcp_rd(float __a);
+__device__ float __nv_frcp_rn(float __a);
+__device__ float __nv_frcp_ru(float __a);
+__device__ float __nv_frcp_rz(float __a);
+__device__ double __nv_frexp(double __a, int *__b);
+__device__ float __nv_frexpf(float __a, int *__b);
+__device__ float __nv_frsqrt_rn(float __a);
+__device__ float __nv_fsqrt_rd(float __a);
+__device__ float __nv_fsqrt_rn(float __a);
+__device__ float __nv_fsqrt_ru(float __a);
+__device__ float __nv_fsqrt_rz(float __a);
+__device__ float __nv_fsub_rd(float __a, float __b);
+__device__ float __nv_fsub_rn(float __a, float __b);
+__device__ float __nv_fsub_ru(float __a, float __b);
+__device__ float __nv_fsub_rz(float __a, float __b);
+__device__ int __nv_hadd(int __a, int __b);
+__device__ float __nv_half2float(unsigned short __h);
+__device__ double __nv_hiloint2double(int __a, int __b);
+__device__ double __nv_hypot(double __a, double __b);
+__device__ float __nv_hypotf(float __a, float __b);
+__device__ int __nv_ilogb(double __a);
+__device__ int __nv_ilogbf(float __a);
+__device__ double __nv_int2double_rn(int __a);
+__device__ float __nv_int2float_rd(int __a);
+__device__ float __nv_int2float_rn(int __a);
+__device__ float __nv_int2float_ru(int __a);
+__device__ float __nv_int2float_rz(int __a);
+__device__ float __nv_int_as_float(int __a);
+__device__ int __nv_isfinited(double __a);
+__device__ int __nv_isinfd(double __a);
+__device__ int __nv_isinff(float __a);
+__device__ int __nv_isnand(double __a);
+__device__ int __nv_isnanf(float __a);
+__device__ double __nv_j0(double __a);
+__device__ float __nv_j0f(float __a);
+__device__ double __nv_j1(double __a);
+__device__ float __nv_j1f(float __a);
+__device__ float __nv_jnf(int __a, float __b);
+__device__ double __nv_jn(int __a, double __b);
+__device__ double __nv_ldexp(double __a, int __b);
+__device__ float __nv_ldexpf(float __a, int __b);
+__device__ double __nv_lgamma(double __a);
+__device__ float __nv_lgammaf(float __a);
+__device__ double __nv_ll2double_rd(long long __a);
+__device__ double __nv_ll2double_rn(long long __a);
+__device__ double __nv_ll2double_ru(long long __a);
+__device__ double __nv_ll2double_rz(long long __a);
+__device__ float __nv_ll2float_rd(long long __a);
+__device__ float __nv_ll2float_rn(long long __a);
+__device__ float __nv_ll2float_ru(long long __a);
+__device__ float __nv_ll2float_rz(long long __a);
+__device__ long long __nv_llabs(long long __a);
+__device__ long long __nv_llmax(long long __a, long long __b);
+__device__ long long __nv_llmin(long long __a, long long __b);
+__device__ long long __nv_llrint(double __a);
+__device__ long long __nv_llrintf(float __a);
+__device__ long long __nv_llround(double __a);
+__device__ long long __nv_llroundf(float __a);
+__device__ double __nv_log10(double __a);
+__device__ float __nv_log10f(float __a);
+__device__ double __nv_log1p(double __a);
+__device__ float __nv_log1pf(float __a);
+__device__ double __nv_log2(double __a);
+__device__ float __nv_log2f(float __a);
+__device__ double __nv_logb(double __a);
+__device__ float __nv_logbf(float __a);
+__device__ double __nv_log(double __a);
+__device__ float __nv_logf(float __a);
+__device__ double __nv_longlong_as_double(long long __a);
+__device__ int __nv_max(int __a, int __b);
+__device__ int __nv_min(int __a, int __b);
+__device__ double __nv_modf(double __a, double *__b);
+__device__ float __nv_modff(float __a, float *__b);
+__device__ int __nv_mul24(int __a, int __b);
+__device__ long long __nv_mul64hi(long long __a, long long __b);
+__device__ int __nv_mulhi(int __a, int __b);
+__device__ double __nv_nan(const signed char *__a);
+__device__ float __nv_nanf(const signed char *__a);
+__device__ double __nv_nearbyint(double __a);
+__device__ float __nv_nearbyintf(float __a);
+__device__ double __nv_nextafter(double __a, double __b);
+__device__ float __nv_nextafterf(float __a, float __b);
+__device__ double __nv_norm3d(double __a, double __b, double __c);
+__device__ float __nv_norm3df(float __a, float __b, float __c);
+__device__ double __nv_norm4d(double __a, double __b, double __c, double __d);
+__device__ float __nv_norm4df(float __a, float __b, float __c, float __d);
+__device__ double __nv_normcdf(double __a);
+__device__ float __nv_normcdff(float __a);
+__device__ double __nv_normcdfinv(double __a);
+__device__ float __nv_normcdfinvf(float __a);
+__device__ float __nv_normf(int __a, const float *__b);
+__device__ double __nv_norm(int __a, const double *__b);
+__device__ int __nv_popc(int __a);
+__device__ int __nv_popcll(long long __a);
+__device__ double __nv_pow(double __a, double __b);
+__device__ float __nv_powf(float __a, float __b);
+__device__ double __nv_powi(double __a, int __b);
+__device__ float __nv_powif(float __a, int __b);
+__device__ double __nv_rcbrt(double __a);
+__device__ float __nv_rcbrtf(float __a);
+__device__ double __nv_rcp64h(double __a);
+__device__ double __nv_remainder(double __a, double __b);
+__device__ float __nv_remainderf(float __a, float __b);
+__device__ double __nv_remquo(double __a, double __b, int *__c);
+__device__ float __nv_remquof(float __a, float __b, int *__c);
+__device__ int __nv_rhadd(int __a, int __b);
+__device__ double __nv_rhypot(double __a, double __b);
+__device__ float __nv_rhypotf(float __a, float __b);
+__device__ double __nv_rint(double __a);
+__device__ float __nv_rintf(float __a);
+__device__ double __nv_rnorm3d(double __a, double __b, double __c);
+__device__ float __nv_rnorm3df(float __a, float __b, float __c);
+__device__ double __nv_rnorm4d(double __a, double __b, double __c, double __d);
+__device__ float __nv_rnorm4df(float __a, float __b, float __c, float __d);
+__device__ float __nv_rnormf(int __a, const float *__b);
+__device__ double __nv_rnorm(int __a, const double *__b);
+__device__ double __nv_round(double __a);
+__device__ float __nv_roundf(float __a);
+__device__ double __nv_rsqrt(double __a);
+__device__ float __nv_rsqrtf(float __a);
+__device__ int __nv_sad(int __a, int __b, int __c);
+__device__ float __nv_saturatef(float __a);
+__device__ double __nv_scalbn(double __a, int __b);
+__device__ float __nv_scalbnf(float __a, int __b);
+__device__ int __nv_signbitd(double __a);
+__device__ int __nv_signbitf(float __a);
+__device__ void __nv_sincos(double __a, double *__b, double *__c);
+__device__ void __nv_sincosf(float __a, float *__b, float *__c);
+__device__ void __nv_sincospi(double __a, double *__b, double *__c);
+__device__ void __nv_sincospif(float __a, float *__b, float *__c);
+__device__ double __nv_sin(double __a);
+__device__ float __nv_sinf(float __a);
+__device__ double __nv_sinh(double __a);
+__device__ float __nv_sinhf(float __a);
+__device__ double __nv_sinpi(double __a);
+__device__ float __nv_sinpif(float __a);
+__device__ double __nv_sqrt(double __a);
+__device__ float __nv_sqrtf(float __a);
+__device__ double __nv_tan(double __a);
+__device__ float __nv_tanf(float __a);
+__device__ double __nv_tanh(double __a);
+__device__ float __nv_tanhf(float __a);
+__device__ double __nv_tgamma(double __a);
+__device__ float __nv_tgammaf(float __a);
+__device__ double __nv_trunc(double __a);
+__device__ float __nv_truncf(float __a);
+__device__ int __nv_uhadd(unsigned int __a, unsigned int __b);
+__device__ double __nv_uint2double_rn(unsigned int __i);
+__device__ float __nv_uint2float_rd(unsigned int __a);
+__device__ float __nv_uint2float_rn(unsigned int __a);
+__device__ float __nv_uint2float_ru(unsigned int __a);
+__device__ float __nv_uint2float_rz(unsigned int __a);
+__device__ float __nv_uint_as_float(unsigned int __a);
+__device__ double __nv_ull2double_rd(unsigned long long __a);
+__device__ double __nv_ull2double_rn(unsigned long long __a);
+__device__ double __nv_ull2double_ru(unsigned long long __a);
+__device__ double __nv_ull2double_rz(unsigned long long __a);
+__device__ float __nv_ull2float_rd(unsigned long long __a);
+__device__ float __nv_ull2float_rn(unsigned long long __a);
+__device__ float __nv_ull2float_ru(unsigned long long __a);
+__device__ float __nv_ull2float_rz(unsigned long long __a);
+__device__ unsigned long long __nv_ullmax(unsigned long long __a,
+ unsigned long long __b);
+__device__ unsigned long long __nv_ullmin(unsigned long long __a,
+ unsigned long long __b);
+__device__ unsigned int __nv_umax(unsigned int __a, unsigned int __b);
+__device__ unsigned int __nv_umin(unsigned int __a, unsigned int __b);
+__device__ unsigned int __nv_umul24(unsigned int __a, unsigned int __b);
+__device__ unsigned long long __nv_umul64hi(unsigned long long __a,
+ unsigned long long __b);
+__device__ unsigned int __nv_umulhi(unsigned int __a, unsigned int __b);
+__device__ unsigned int __nv_urhadd(unsigned int __a, unsigned int __b);
+__device__ unsigned int __nv_usad(unsigned int __a, unsigned int __b,
+ unsigned int __c);
+#if CUDA_VERSION >= 9000 && CUDA_VERSION < 9020
+__device__ int __nv_vabs2(int __a);
+__device__ int __nv_vabs4(int __a);
+__device__ int __nv_vabsdiffs2(int __a, int __b);
+__device__ int __nv_vabsdiffs4(int __a, int __b);
+__device__ int __nv_vabsdiffu2(int __a, int __b);
+__device__ int __nv_vabsdiffu4(int __a, int __b);
+__device__ int __nv_vabsss2(int __a);
+__device__ int __nv_vabsss4(int __a);
+__device__ int __nv_vadd2(int __a, int __b);
+__device__ int __nv_vadd4(int __a, int __b);
+__device__ int __nv_vaddss2(int __a, int __b);
+__device__ int __nv_vaddss4(int __a, int __b);
+__device__ int __nv_vaddus2(int __a, int __b);
+__device__ int __nv_vaddus4(int __a, int __b);
+__device__ int __nv_vavgs2(int __a, int __b);
+__device__ int __nv_vavgs4(int __a, int __b);
+__device__ int __nv_vavgu2(int __a, int __b);
+__device__ int __nv_vavgu4(int __a, int __b);
+__device__ int __nv_vcmpeq2(int __a, int __b);
+__device__ int __nv_vcmpeq4(int __a, int __b);
+__device__ int __nv_vcmpges2(int __a, int __b);
+__device__ int __nv_vcmpges4(int __a, int __b);
+__device__ int __nv_vcmpgeu2(int __a, int __b);
+__device__ int __nv_vcmpgeu4(int __a, int __b);
+__device__ int __nv_vcmpgts2(int __a, int __b);
+__device__ int __nv_vcmpgts4(int __a, int __b);
+__device__ int __nv_vcmpgtu2(int __a, int __b);
+__device__ int __nv_vcmpgtu4(int __a, int __b);
+__device__ int __nv_vcmples2(int __a, int __b);
+__device__ int __nv_vcmples4(int __a, int __b);
+__device__ int __nv_vcmpleu2(int __a, int __b);
+__device__ int __nv_vcmpleu4(int __a, int __b);
+__device__ int __nv_vcmplts2(int __a, int __b);
+__device__ int __nv_vcmplts4(int __a, int __b);
+__device__ int __nv_vcmpltu2(int __a, int __b);
+__device__ int __nv_vcmpltu4(int __a, int __b);
+__device__ int __nv_vcmpne2(int __a, int __b);
+__device__ int __nv_vcmpne4(int __a, int __b);
+__device__ int __nv_vhaddu2(int __a, int __b);
+__device__ int __nv_vhaddu4(int __a, int __b);
+__device__ int __nv_vmaxs2(int __a, int __b);
+__device__ int __nv_vmaxs4(int __a, int __b);
+__device__ int __nv_vmaxu2(int __a, int __b);
+__device__ int __nv_vmaxu4(int __a, int __b);
+__device__ int __nv_vmins2(int __a, int __b);
+__device__ int __nv_vmins4(int __a, int __b);
+__device__ int __nv_vminu2(int __a, int __b);
+__device__ int __nv_vminu4(int __a, int __b);
+__device__ int __nv_vneg2(int __a);
+__device__ int __nv_vneg4(int __a);
+__device__ int __nv_vnegss2(int __a);
+__device__ int __nv_vnegss4(int __a);
+__device__ int __nv_vsads2(int __a, int __b);
+__device__ int __nv_vsads4(int __a, int __b);
+__device__ int __nv_vsadu2(int __a, int __b);
+__device__ int __nv_vsadu4(int __a, int __b);
+__device__ int __nv_vseteq2(int __a, int __b);
+__device__ int __nv_vseteq4(int __a, int __b);
+__device__ int __nv_vsetges2(int __a, int __b);
+__device__ int __nv_vsetges4(int __a, int __b);
+__device__ int __nv_vsetgeu2(int __a, int __b);
+__device__ int __nv_vsetgeu4(int __a, int __b);
+__device__ int __nv_vsetgts2(int __a, int __b);
+__device__ int __nv_vsetgts4(int __a, int __b);
+__device__ int __nv_vsetgtu2(int __a, int __b);
+__device__ int __nv_vsetgtu4(int __a, int __b);
+__device__ int __nv_vsetles2(int __a, int __b);
+__device__ int __nv_vsetles4(int __a, int __b);
+__device__ int __nv_vsetleu2(int __a, int __b);
+__device__ int __nv_vsetleu4(int __a, int __b);
+__device__ int __nv_vsetlts2(int __a, int __b);
+__device__ int __nv_vsetlts4(int __a, int __b);
+__device__ int __nv_vsetltu2(int __a, int __b);
+__device__ int __nv_vsetltu4(int __a, int __b);
+__device__ int __nv_vsetne2(int __a, int __b);
+__device__ int __nv_vsetne4(int __a, int __b);
+__device__ int __nv_vsub2(int __a, int __b);
+__device__ int __nv_vsub4(int __a, int __b);
+__device__ int __nv_vsubss2(int __a, int __b);
+__device__ int __nv_vsubss4(int __a, int __b);
+__device__ int __nv_vsubus2(int __a, int __b);
+__device__ int __nv_vsubus4(int __a, int __b);
+#endif // CUDA_VERSION
+__device__ double __nv_y0(double __a);
+__device__ float __nv_y0f(float __a);
+__device__ double __nv_y1(double __a);
+__device__ float __nv_y1f(float __a);
+__device__ float __nv_ynf(int __a, float __b);
+__device__ double __nv_yn(int __a, double __b);
+} // extern "C"
+#endif // __CLANG_CUDA_LIBDEVICE_DECLARES_H__
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 a82a8490f367..09705a273a47 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 > 9000
+#elif CUDA_VERSION < 7000 || CUDA_VERSION > 9020
#error "Unsupported CUDA version!"
#endif
@@ -84,6 +84,9 @@
#define __DEVICE_FUNCTIONS_H__
#define __MATH_FUNCTIONS_H__
#define __COMMON_FUNCTIONS_H__
+// device_functions_decls is replaced by __clang_cuda_device_functions.h
+// included below.
+#define __DEVICE_FUNCTIONS_DECLS_H__
#undef __CUDACC__
#if CUDA_VERSION < 9000
@@ -97,11 +100,17 @@
#include "host_config.h"
#include "host_defines.h"
+// Temporarily replace "nv_weak" with weak, so __attribute__((nv_weak)) in
+// cuda_device_runtime_api.h ends up being __attribute__((weak)) which is the
+// functional equivalent of what we need.
+#pragma push_macro("nv_weak")
+#define nv_weak weak
#undef __CUDABE__
#undef __CUDA_LIBDEVICE__
#define __CUDACC__
#include "cuda_runtime.h"
+#pragma pop_macro("nv_weak")
#undef __CUDACC__
#define __CUDABE__
@@ -137,20 +146,22 @@ inline __host__ double __signbitd(double x) {
}
#endif
-// We need decls for functions in CUDA's libdevice with __device__
-// attribute only. Alas they come either as __host__ __device__ or
-// with no attributes at all. To work around that, define __CUDA_RTC__
-// which produces HD variant and undef __host__ which gives us desided
-// decls with __device__ attribute.
-#pragma push_macro("__host__")
-#define __host__
-#define __CUDACC_RTC__
-#include "device_functions_decls.h"
-#undef __CUDACC_RTC__
+// CUDA 9.1 no longer provides declarations for libdevice functions, so we need
+// to provide our own.
+#include <__clang_cuda_libdevice_declares.h>
-// Temporarily poison __host__ macro to ensure it's not used by any of
-// the headers we're about to include.
-#define __host__ UNEXPECTED_HOST_ATTRIBUTE
+// Wrappers for many device-side standard library functions became compiler
+// builtins in CUDA-9 and have been removed from the CUDA headers. Clang now
+// provides its own implementation of the wrappers.
+#if CUDA_VERSION >= 9000
+#include <__clang_cuda_device_functions.h>
+#endif
+
+// __THROW is redefined to be empty by device_functions_decls.h in CUDA. Clang's
+// counterpart does not do it, so we need to make it empty here to keep
+// following CUDA includes happy.
+#undef __THROW
+#define __THROW
// CUDA 8.0.41 relies on __USE_FAST_MATH__ and __CUDA_PREC_DIV's values.
// Previous versions used to check whether they are defined or not.
@@ -167,24 +178,20 @@ inline __host__ double __signbitd(double x) {
#endif
#endif
+// Temporarily poison __host__ macro to ensure it's not used by any of
+// the headers we're about to include.
+#pragma push_macro("__host__")
+#define __host__ UNEXPECTED_HOST_ATTRIBUTE
+
// device_functions.hpp and math_functions*.hpp use 'static
// __forceinline__' (with no __device__) for definitions of device
// functions. Temporarily redefine __forceinline__ to include
// __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
-
+#if CUDA_VERSION < 9000
#include "device_functions.hpp"
-#pragma pop_macro("__float2half_rn")
-
+#endif
// 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
@@ -196,17 +203,32 @@ inline __host__ double __signbitd(double x) {
#if defined(__CLANG_CUDA_APPROX_TRANSCENDENTALS__)
#define __USE_FAST_MATH__ 1
#endif
+
+#if CUDA_VERSION >= 9000
+// CUDA-9.2 needs host-side memcpy for some host functions in
+// device_functions.hpp
+#if CUDA_VERSION >= 9020
+#include <string.h>
+#endif
+#include "crt/math_functions.hpp"
+#else
#include "math_functions.hpp"
+#endif
+
#pragma pop_macro("__USE_FAST_MATH__")
+#if CUDA_VERSION < 9000
#include "math_functions_dbl_ptx3.hpp"
+#endif
#pragma pop_macro("__forceinline__")
// Pull in host-only functions that are only available when neither
// __CUDACC__ nor __CUDABE__ are defined.
#undef __MATH_FUNCTIONS_HPP__
#undef __CUDABE__
+#if CUDA_VERSION < 9000
#include "math_functions.hpp"
+#endif
// Alas, additional overloads for these functions are hard to get to.
// Considering that we only need these overloads for a few functions,
// we can provide them here.
@@ -222,22 +244,36 @@ static inline float normcdfinv(float __a) { return normcdfinvf(__a); }
static inline float normcdf(float __a) { return normcdff(__a); }
static inline float erfcx(float __a) { return erfcxf(__a); }
+#if CUDA_VERSION < 9000
// For some reason single-argument variant is not always declared by
// CUDA headers. Alas, device_functions.hpp included below needs it.
static inline __device__ void __brkpt(int __c) { __brkpt(); }
+#endif
// Now include *.hpp with definitions of various GPU functions. Alas,
// a lot of thins get declared/defined with __host__ attribute which
// we don't want and we have to define it out. We also have to include
// {device,math}_functions.hpp again in order to extract the other
// branch of #if/else inside.
-
#define __host__
#undef __CUDABE__
#define __CUDACC__
+#if CUDA_VERSION >= 9000
+// Some atomic functions became compiler builtins in CUDA-9 , so we need their
+// declarations.
+#include "device_atomic_functions.h"
+#endif
#undef __DEVICE_FUNCTIONS_HPP__
#include "device_atomic_functions.hpp"
+#if CUDA_VERSION >= 9000
+#include "crt/device_functions.hpp"
+#include "crt/device_double_functions.hpp"
+#else
#include "device_functions.hpp"
+#define __CUDABE__
+#include "device_double_functions.h"
+#undef __CUDABE__
+#endif
#include "sm_20_atomic_functions.hpp"
#include "sm_20_intrinsics.hpp"
#include "sm_32_atomic_functions.hpp"
@@ -251,8 +287,11 @@ static inline __device__ void __brkpt(int __c) { __brkpt(); }
// reason about our code.
#if CUDA_VERSION >= 8000
+#pragma push_macro("__CUDA_ARCH__")
+#undef __CUDA_ARCH__
#include "sm_60_atomic_functions.hpp"
#include "sm_61_intrinsics.hpp"
+#pragma pop_macro("__CUDA_ARCH__")
#endif
#undef __MATH_FUNCTIONS_HPP__
@@ -279,7 +318,11 @@ static inline __device__ void __brkpt(int __c) { __brkpt(); }
#endif
#endif
+#if CUDA_VERSION >= 9000
+#include "crt/math_functions.hpp"
+#else
#include "math_functions.hpp"
+#endif
#pragma pop_macro("_GLIBCXX_MATH_H")
#pragma pop_macro("_LIBCPP_VERSION")
#pragma pop_macro("__GNUC__")
diff --git a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
index 3a2ee1b2ef2e..70c355efc48c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
@@ -20,15 +20,18 @@
*
*===-----------------------------------------------------------------------===
*/
-#ifndef _WMMINTRIN_AES_H
-#define _WMMINTRIN_AES_H
-#include <emmintrin.h>
+#ifndef __WMMINTRIN_H
+#error "Never use <__wmmintrin_aes.h> directly; include <wmmintrin.h> instead."
+#endif
+
+#ifndef __WMMINTRIN_AES_H
+#define __WMMINTRIN_AES_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("aes")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("aes"), __min_vector_width__(128)))
-/// \brief Performs a single round of AES encryption using the Equivalent
+/// Performs a single round of AES encryption using the Equivalent
/// Inverse Cipher, transforming the state value from the first source
/// operand using a 128-bit round key value contained in the second source
/// operand, and writes the result to the destination.
@@ -48,7 +51,7 @@ _mm_aesenc_si128(__m128i __V, __m128i __R)
return (__m128i)__builtin_ia32_aesenc128((__v2di)__V, (__v2di)__R);
}
-/// \brief Performs the final round of AES encryption using the Equivalent
+/// Performs the final round of AES encryption using the Equivalent
/// Inverse Cipher, transforming the state value from the first source
/// operand using a 128-bit round key value contained in the second source
/// operand, and writes the result to the destination.
@@ -68,7 +71,7 @@ _mm_aesenclast_si128(__m128i __V, __m128i __R)
return (__m128i)__builtin_ia32_aesenclast128((__v2di)__V, (__v2di)__R);
}
-/// \brief Performs a single round of AES decryption using the Equivalent
+/// Performs a single round of AES decryption using the Equivalent
/// Inverse Cipher, transforming the state value from the first source
/// operand using a 128-bit round key value contained in the second source
/// operand, and writes the result to the destination.
@@ -88,7 +91,7 @@ _mm_aesdec_si128(__m128i __V, __m128i __R)
return (__m128i)__builtin_ia32_aesdec128((__v2di)__V, (__v2di)__R);
}
-/// \brief Performs the final round of AES decryption using the Equivalent
+/// Performs the final round of AES decryption using the Equivalent
/// Inverse Cipher, transforming the state value from the first source
/// operand using a 128-bit round key value contained in the second source
/// operand, and writes the result to the destination.
@@ -108,7 +111,7 @@ _mm_aesdeclast_si128(__m128i __V, __m128i __R)
return (__m128i)__builtin_ia32_aesdeclast128((__v2di)__V, (__v2di)__R);
}
-/// \brief Applies the AES InvMixColumns() transformation to an expanded key
+/// Applies the AES InvMixColumns() transformation to an expanded key
/// contained in the source operand, and writes the result to the
/// destination.
///
@@ -125,7 +128,7 @@ _mm_aesimc_si128(__m128i __V)
return (__m128i)__builtin_ia32_aesimc128((__v2di)__V);
}
-/// \brief Generates a round key for AES encyption, operating on 128-bit data
+/// Generates a round key for AES encryption, operating on 128-bit data
/// specified in the first source operand and using an 8-bit round constant
/// specified by the second source operand, and writes the result to the
/// destination.
@@ -148,4 +151,4 @@ _mm_aesimc_si128(__m128i __V)
#undef __DEFAULT_FN_ATTRS
-#endif /* _WMMINTRIN_AES_H */
+#endif /* __WMMINTRIN_AES_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h
index e9c6a9f6d415..e0f928796ac1 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h
@@ -20,10 +20,15 @@
*
*===-----------------------------------------------------------------------===
*/
-#ifndef _WMMINTRIN_PCLMUL_H
-#define _WMMINTRIN_PCLMUL_H
-/// \brief Multiplies two 64-bit integer values, which are selected from source
+#ifndef __WMMINTRIN_H
+#error "Never use <__wmmintrin_pclmul.h> directly; include <wmmintrin.h> instead."
+#endif
+
+#ifndef __WMMINTRIN_PCLMUL_H
+#define __WMMINTRIN_PCLMUL_H
+
+/// Multiplies two 64-bit integer values, which are selected from source
/// operands using the immediate-value operand. The multiplication is a
/// carry-less multiplication, and the 128-bit integer product is stored in
/// the destination.
@@ -50,8 +55,8 @@
/// Bit[4]=1 indicates that bits[127:64] of operand \a __Y are used.
/// \returns The 128-bit integer vector containing the result of the carry-less
/// multiplication of the selected 64-bit values.
-#define _mm_clmulepi64_si128(__X, __Y, __I) \
- ((__m128i)__builtin_ia32_pclmulqdq128((__v2di)(__m128i)(__X), \
- (__v2di)(__m128i)(__Y), (char)(__I)))
+#define _mm_clmulepi64_si128(X, Y, I) \
+ ((__m128i)__builtin_ia32_pclmulqdq128((__v2di)(__m128i)(X), \
+ (__v2di)(__m128i)(Y), (char)(I)))
-#endif /* _WMMINTRIN_PCLMUL_H */
+#endif /* __WMMINTRIN_PCLMUL_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/ammintrin.h b/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
index 2843a7a2677f..680b4465eaae 100644
--- a/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
@@ -27,9 +27,9 @@
#include <pmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4a")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4a"), __min_vector_width__(128)))
-/// \brief Extracts the specified bits from the lower 64 bits of the 128-bit
+/// Extracts the specified bits from the lower 64 bits of the 128-bit
/// integer vector operand at the index \a idx and of the length \a len.
///
/// \headerfile <x86intrin.h>
@@ -57,7 +57,7 @@
((__m128i)__builtin_ia32_extrqi((__v2di)(__m128i)(x), \
(char)(len), (char)(idx)))
-/// \brief Extracts the specified bits from the lower 64 bits of the 128-bit
+/// Extracts the specified bits from the lower 64 bits of the 128-bit
/// integer vector operand at the index and of the length specified by
/// \a __y.
///
@@ -82,7 +82,7 @@ _mm_extract_si64(__m128i __x, __m128i __y)
return (__m128i)__builtin_ia32_extrq((__v2di)__x, (__v16qi)__y);
}
-/// \brief Inserts bits of a specified length from the source integer vector
+/// Inserts bits of a specified length from the source integer vector
/// \a y into the lower 64 bits of the destination integer vector \a x at
/// the index \a idx and of the length \a len.
///
@@ -120,7 +120,7 @@ _mm_extract_si64(__m128i __x, __m128i __y)
(__v2di)(__m128i)(y), \
(char)(len), (char)(idx)))
-/// \brief Inserts bits of a specified length from the source integer vector
+/// Inserts bits of a specified length from the source integer vector
/// \a __y into the lower 64 bits of the destination integer vector \a __x
/// at the index and of the length specified by \a __y.
///
@@ -152,7 +152,7 @@ _mm_insert_si64(__m128i __x, __m128i __y)
return (__m128i)__builtin_ia32_insertq((__v2di)__x, (__v2di)__y);
}
-/// \brief Stores a 64-bit double-precision value in a 64-bit memory location.
+/// Stores a 64-bit double-precision value in a 64-bit memory location.
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon).
///
@@ -170,7 +170,7 @@ _mm_stream_sd(double *__p, __m128d __a)
__builtin_ia32_movntsd(__p, (__v2df)__a);
}
-/// \brief Stores a 32-bit single-precision floating-point value in a 32-bit
+/// Stores a 32-bit single-precision floating-point value in a 32-bit
/// memory location. To minimize caching, the data is flagged as
/// non-temporal (unlikely to be used again soon).
///
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
index caf4ced92054..9688a96fde18 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
@@ -29,120 +29,121 @@
#define __AVX2INTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx2")))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx2"), __min_vector_width__(256)))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx2"), __min_vector_width__(128)))
/* SSE4 Multiple Packed Sums of Absolute Difference. */
#define _mm256_mpsadbw_epu8(X, Y, M) \
(__m256i)__builtin_ia32_mpsadbw256((__v32qi)(__m256i)(X), \
(__v32qi)(__m256i)(Y), (int)(M))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_abs_epi8(__m256i __a)
{
return (__m256i)__builtin_ia32_pabsb256((__v32qi)__a);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_abs_epi16(__m256i __a)
{
return (__m256i)__builtin_ia32_pabsw256((__v16hi)__a);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_abs_epi32(__m256i __a)
{
return (__m256i)__builtin_ia32_pabsd256((__v8si)__a);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_packs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_packsswb256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_packs_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_packssdw256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_packus_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_packuswb256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_packus_epi32(__m256i __V1, __m256i __V2)
{
return (__m256i) __builtin_ia32_packusdw256((__v8si)__V1, (__v8si)__V2);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_add_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qu)__a + (__v32qu)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_add_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hu)__a + (__v16hu)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_add_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8su)__a + (__v8su)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_add_epi64(__m256i __a, __m256i __b)
{
return (__m256i)((__v4du)__a + (__v4du)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_adds_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_adds_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_adds_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddusb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_adds_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddusw256((__v16hi)__a, (__v16hi)__b);
}
-#define _mm256_alignr_epi8(a, b, n) __extension__ ({ \
+#define _mm256_alignr_epi8(a, b, n) \
(__m256i)__builtin_ia32_palignr256((__v32qi)(__m256i)(a), \
- (__v32qi)(__m256i)(b), (n)); })
+ (__v32qi)(__m256i)(b), (n))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_and_si256(__m256i __a, __m256i __b)
{
return (__m256i)((__v4du)__a & (__v4du)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_andnot_si256(__m256i __a, __m256i __b)
{
return (__m256i)(~(__v4du)__a & (__v4du)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_avg_epu8(__m256i __a, __m256i __b)
{
typedef unsigned short __v32hu __attribute__((__vector_size__(64)));
@@ -152,7 +153,7 @@ _mm256_avg_epu8(__m256i __a, __m256i __b)
>> 1, __v32qu);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_avg_epu16(__m256i __a, __m256i __b)
{
typedef unsigned int __v16su __attribute__((__vector_size__(64)));
@@ -162,58 +163,42 @@ _mm256_avg_epu16(__m256i __a, __m256i __b)
>> 1, __v16hu);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M)
{
return (__m256i)__builtin_ia32_pblendvb256((__v32qi)__V1, (__v32qi)__V2,
(__v32qi)__M);
}
-#define _mm256_blend_epi16(V1, V2, M) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(V1), \
- (__v16hi)(__m256i)(V2), \
- (((M) & 0x01) ? 16 : 0), \
- (((M) & 0x02) ? 17 : 1), \
- (((M) & 0x04) ? 18 : 2), \
- (((M) & 0x08) ? 19 : 3), \
- (((M) & 0x10) ? 20 : 4), \
- (((M) & 0x20) ? 21 : 5), \
- (((M) & 0x40) ? 22 : 6), \
- (((M) & 0x80) ? 23 : 7), \
- (((M) & 0x01) ? 24 : 8), \
- (((M) & 0x02) ? 25 : 9), \
- (((M) & 0x04) ? 26 : 10), \
- (((M) & 0x08) ? 27 : 11), \
- (((M) & 0x10) ? 28 : 12), \
- (((M) & 0x20) ? 29 : 13), \
- (((M) & 0x40) ? 30 : 14), \
- (((M) & 0x80) ? 31 : 15)); })
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+#define _mm256_blend_epi16(V1, V2, M) \
+ (__m256i)__builtin_ia32_pblendw256((__v16hi)(__m256i)(V1), \
+ (__v16hi)(__m256i)(V2), (int)(M))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpeq_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qi)__a == (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpeq_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a == (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpeq_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a == (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpeq_epi64(__m256i __a, __m256i __b)
{
return (__m256i)((__v4di)__a == (__v4di)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpgt_epi8(__m256i __a, __m256i __b)
{
/* This function always performs a signed comparison, but __v32qi is a char
@@ -221,151 +206,151 @@ _mm256_cmpgt_epi8(__m256i __a, __m256i __b)
return (__m256i)((__v32qs)__a > (__v32qs)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpgt_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a > (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpgt_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a > (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmpgt_epi64(__m256i __a, __m256i __b)
{
return (__m256i)((__v4di)__a > (__v4di)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_hadd_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phaddw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_hadd_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phaddd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_hadds_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phaddsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_hsub_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phsubw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_hsub_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phsubd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_hsubs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phsubsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maddubs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaddubsw256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_madd_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaddwd256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxsd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxub256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxuw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epu32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxud256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminsd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminub256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminuw256 ((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epu32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminud256((__v8si)__a, (__v8si)__b);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS256
_mm256_movemask_epi8(__m256i __a)
{
return __builtin_ia32_pmovmskb256((__v32qi)__a);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepi8_epi16(__m128i __V)
{
/* This function always performs a signed extension, but __v16qi is a char
@@ -373,7 +358,7 @@ _mm256_cvtepi8_epi16(__m128i __V)
return (__m256i)__builtin_convertvector((__v16qs)__V, __v16hi);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepi8_epi32(__m128i __V)
{
/* This function always performs a signed extension, but __v16qi is a char
@@ -381,7 +366,7 @@ _mm256_cvtepi8_epi32(__m128i __V)
return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8si);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepi8_epi64(__m128i __V)
{
/* This function always performs a signed extension, but __v16qi is a char
@@ -389,920 +374,795 @@ _mm256_cvtepi8_epi64(__m128i __V)
return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3), __v4di);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepi16_epi32(__m128i __V)
{
return (__m256i)__builtin_convertvector((__v8hi)__V, __v8si);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepi16_epi64(__m128i __V)
{
return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1, 2, 3), __v4di);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepi32_epi64(__m128i __V)
{
return (__m256i)__builtin_convertvector((__v4si)__V, __v4di);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepu8_epi16(__m128i __V)
{
return (__m256i)__builtin_convertvector((__v16qu)__V, __v16hi);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepu8_epi32(__m128i __V)
{
return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8si);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepu8_epi64(__m128i __V)
{
return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1, 2, 3), __v4di);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepu16_epi32(__m128i __V)
{
return (__m256i)__builtin_convertvector((__v8hu)__V, __v8si);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepu16_epi64(__m128i __V)
{
return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v8hu)__V, (__v8hu)__V, 0, 1, 2, 3), __v4di);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtepu32_epi64(__m128i __V)
{
return (__m256i)__builtin_convertvector((__v4su)__V, __v4di);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mul_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmuldq256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mulhrs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmulhrsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mulhi_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmulhuw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mulhi_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmulhw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mullo_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hu)__a * (__v16hu)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mullo_epi32 (__m256i __a, __m256i __b)
{
return (__m256i)((__v8su)__a * (__v8su)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mul_epu32(__m256i __a, __m256i __b)
{
return __builtin_ia32_pmuludq256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_or_si256(__m256i __a, __m256i __b)
{
return (__m256i)((__v4du)__a | (__v4du)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sad_epu8(__m256i __a, __m256i __b)
{
return __builtin_ia32_psadbw256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shuffle_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pshufb256((__v32qi)__a, (__v32qi)__b);
}
-#define _mm256_shuffle_epi32(a, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v8si)(__m256i)(a), \
- (__v8si)_mm256_undefined_si256(), \
- 0 + (((imm) >> 0) & 0x3), \
- 0 + (((imm) >> 2) & 0x3), \
- 0 + (((imm) >> 4) & 0x3), \
- 0 + (((imm) >> 6) & 0x3), \
- 4 + (((imm) >> 0) & 0x3), \
- 4 + (((imm) >> 2) & 0x3), \
- 4 + (((imm) >> 4) & 0x3), \
- 4 + (((imm) >> 6) & 0x3)); })
-
-#define _mm256_shufflehi_epi16(a, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(a), \
- (__v16hi)_mm256_undefined_si256(), \
- 0, 1, 2, 3, \
- 4 + (((imm) >> 0) & 0x3), \
- 4 + (((imm) >> 2) & 0x3), \
- 4 + (((imm) >> 4) & 0x3), \
- 4 + (((imm) >> 6) & 0x3), \
- 8, 9, 10, 11, \
- 12 + (((imm) >> 0) & 0x3), \
- 12 + (((imm) >> 2) & 0x3), \
- 12 + (((imm) >> 4) & 0x3), \
- 12 + (((imm) >> 6) & 0x3)); })
-
-#define _mm256_shufflelo_epi16(a, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(a), \
- (__v16hi)_mm256_undefined_si256(), \
- 0 + (((imm) >> 0) & 0x3), \
- 0 + (((imm) >> 2) & 0x3), \
- 0 + (((imm) >> 4) & 0x3), \
- 0 + (((imm) >> 6) & 0x3), \
- 4, 5, 6, 7, \
- 8 + (((imm) >> 0) & 0x3), \
- 8 + (((imm) >> 2) & 0x3), \
- 8 + (((imm) >> 4) & 0x3), \
- 8 + (((imm) >> 6) & 0x3), \
- 12, 13, 14, 15); })
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+#define _mm256_shuffle_epi32(a, imm) \
+ (__m256i)__builtin_ia32_pshufd256((__v8si)(__m256i)(a), (int)(imm))
+
+#define _mm256_shufflehi_epi16(a, imm) \
+ (__m256i)__builtin_ia32_pshufhw256((__v16hi)(__m256i)(a), (int)(imm))
+
+#define _mm256_shufflelo_epi16(a, imm) \
+ (__m256i)__builtin_ia32_pshuflw256((__v16hi)(__m256i)(a), (int)(imm))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sign_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psignb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sign_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psignw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sign_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psignd256((__v8si)__a, (__v8si)__b);
}
-#define _mm256_slli_si256(a, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector( \
- (__v32qi)_mm256_setzero_si256(), \
- (__v32qi)(__m256i)(a), \
- ((char)(imm)&0xF0) ? 0 : ((char)(imm)>0x0 ? 16 : 32) - (char)(imm), \
- ((char)(imm)&0xF0) ? 1 : ((char)(imm)>0x1 ? 17 : 33) - (char)(imm), \
- ((char)(imm)&0xF0) ? 2 : ((char)(imm)>0x2 ? 18 : 34) - (char)(imm), \
- ((char)(imm)&0xF0) ? 3 : ((char)(imm)>0x3 ? 19 : 35) - (char)(imm), \
- ((char)(imm)&0xF0) ? 4 : ((char)(imm)>0x4 ? 20 : 36) - (char)(imm), \
- ((char)(imm)&0xF0) ? 5 : ((char)(imm)>0x5 ? 21 : 37) - (char)(imm), \
- ((char)(imm)&0xF0) ? 6 : ((char)(imm)>0x6 ? 22 : 38) - (char)(imm), \
- ((char)(imm)&0xF0) ? 7 : ((char)(imm)>0x7 ? 23 : 39) - (char)(imm), \
- ((char)(imm)&0xF0) ? 8 : ((char)(imm)>0x8 ? 24 : 40) - (char)(imm), \
- ((char)(imm)&0xF0) ? 9 : ((char)(imm)>0x9 ? 25 : 41) - (char)(imm), \
- ((char)(imm)&0xF0) ? 10 : ((char)(imm)>0xA ? 26 : 42) - (char)(imm), \
- ((char)(imm)&0xF0) ? 11 : ((char)(imm)>0xB ? 27 : 43) - (char)(imm), \
- ((char)(imm)&0xF0) ? 12 : ((char)(imm)>0xC ? 28 : 44) - (char)(imm), \
- ((char)(imm)&0xF0) ? 13 : ((char)(imm)>0xD ? 29 : 45) - (char)(imm), \
- ((char)(imm)&0xF0) ? 14 : ((char)(imm)>0xE ? 30 : 46) - (char)(imm), \
- ((char)(imm)&0xF0) ? 15 : ((char)(imm)>0xF ? 31 : 47) - (char)(imm), \
- ((char)(imm)&0xF0) ? 16 : ((char)(imm)>0x0 ? 32 : 48) - (char)(imm), \
- ((char)(imm)&0xF0) ? 17 : ((char)(imm)>0x1 ? 33 : 49) - (char)(imm), \
- ((char)(imm)&0xF0) ? 18 : ((char)(imm)>0x2 ? 34 : 50) - (char)(imm), \
- ((char)(imm)&0xF0) ? 19 : ((char)(imm)>0x3 ? 35 : 51) - (char)(imm), \
- ((char)(imm)&0xF0) ? 20 : ((char)(imm)>0x4 ? 36 : 52) - (char)(imm), \
- ((char)(imm)&0xF0) ? 21 : ((char)(imm)>0x5 ? 37 : 53) - (char)(imm), \
- ((char)(imm)&0xF0) ? 22 : ((char)(imm)>0x6 ? 38 : 54) - (char)(imm), \
- ((char)(imm)&0xF0) ? 23 : ((char)(imm)>0x7 ? 39 : 55) - (char)(imm), \
- ((char)(imm)&0xF0) ? 24 : ((char)(imm)>0x8 ? 40 : 56) - (char)(imm), \
- ((char)(imm)&0xF0) ? 25 : ((char)(imm)>0x9 ? 41 : 57) - (char)(imm), \
- ((char)(imm)&0xF0) ? 26 : ((char)(imm)>0xA ? 42 : 58) - (char)(imm), \
- ((char)(imm)&0xF0) ? 27 : ((char)(imm)>0xB ? 43 : 59) - (char)(imm), \
- ((char)(imm)&0xF0) ? 28 : ((char)(imm)>0xC ? 44 : 60) - (char)(imm), \
- ((char)(imm)&0xF0) ? 29 : ((char)(imm)>0xD ? 45 : 61) - (char)(imm), \
- ((char)(imm)&0xF0) ? 30 : ((char)(imm)>0xE ? 46 : 62) - (char)(imm), \
- ((char)(imm)&0xF0) ? 31 : ((char)(imm)>0xF ? 47 : 63) - (char)(imm)); })
-
-#define _mm256_bslli_epi128(a, count) _mm256_slli_si256((a), (count))
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+#define _mm256_slli_si256(a, imm) \
+ (__m256i)__builtin_ia32_pslldqi256_byteshift((__v4di)(__m256i)(a), (int)(imm))
+
+#define _mm256_bslli_epi128(a, imm) \
+ (__m256i)__builtin_ia32_pslldqi256_byteshift((__v4di)(__m256i)(a), (int)(imm))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_slli_epi16(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psllwi256((__v16hi)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sll_epi16(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psllw256((__v16hi)__a, (__v8hi)__count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_slli_epi32(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_pslldi256((__v8si)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sll_epi32(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_pslld256((__v8si)__a, (__v4si)__count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_slli_epi64(__m256i __a, int __count)
{
return __builtin_ia32_psllqi256((__v4di)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sll_epi64(__m256i __a, __m128i __count)
{
return __builtin_ia32_psllq256((__v4di)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srai_epi16(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psrawi256((__v16hi)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sra_epi16(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psraw256((__v16hi)__a, (__v8hi)__count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srai_epi32(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psradi256((__v8si)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sra_epi32(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psrad256((__v8si)__a, (__v4si)__count);
}
-#define _mm256_srli_si256(a, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector( \
- (__v32qi)(__m256i)(a), \
- (__v32qi)_mm256_setzero_si256(), \
- ((char)(imm)&0xF0) ? 32 : (char)(imm) + ((char)(imm)>0xF ? 16 : 0), \
- ((char)(imm)&0xF0) ? 33 : (char)(imm) + ((char)(imm)>0xE ? 17 : 1), \
- ((char)(imm)&0xF0) ? 34 : (char)(imm) + ((char)(imm)>0xD ? 18 : 2), \
- ((char)(imm)&0xF0) ? 35 : (char)(imm) + ((char)(imm)>0xC ? 19 : 3), \
- ((char)(imm)&0xF0) ? 36 : (char)(imm) + ((char)(imm)>0xB ? 20 : 4), \
- ((char)(imm)&0xF0) ? 37 : (char)(imm) + ((char)(imm)>0xA ? 21 : 5), \
- ((char)(imm)&0xF0) ? 38 : (char)(imm) + ((char)(imm)>0x9 ? 22 : 6), \
- ((char)(imm)&0xF0) ? 39 : (char)(imm) + ((char)(imm)>0x8 ? 23 : 7), \
- ((char)(imm)&0xF0) ? 40 : (char)(imm) + ((char)(imm)>0x7 ? 24 : 8), \
- ((char)(imm)&0xF0) ? 41 : (char)(imm) + ((char)(imm)>0x6 ? 25 : 9), \
- ((char)(imm)&0xF0) ? 42 : (char)(imm) + ((char)(imm)>0x5 ? 26 : 10), \
- ((char)(imm)&0xF0) ? 43 : (char)(imm) + ((char)(imm)>0x4 ? 27 : 11), \
- ((char)(imm)&0xF0) ? 44 : (char)(imm) + ((char)(imm)>0x3 ? 28 : 12), \
- ((char)(imm)&0xF0) ? 45 : (char)(imm) + ((char)(imm)>0x2 ? 29 : 13), \
- ((char)(imm)&0xF0) ? 46 : (char)(imm) + ((char)(imm)>0x1 ? 30 : 14), \
- ((char)(imm)&0xF0) ? 47 : (char)(imm) + ((char)(imm)>0x0 ? 31 : 15), \
- ((char)(imm)&0xF0) ? 48 : (char)(imm) + ((char)(imm)>0xF ? 32 : 16), \
- ((char)(imm)&0xF0) ? 49 : (char)(imm) + ((char)(imm)>0xE ? 33 : 17), \
- ((char)(imm)&0xF0) ? 50 : (char)(imm) + ((char)(imm)>0xD ? 34 : 18), \
- ((char)(imm)&0xF0) ? 51 : (char)(imm) + ((char)(imm)>0xC ? 35 : 19), \
- ((char)(imm)&0xF0) ? 52 : (char)(imm) + ((char)(imm)>0xB ? 36 : 20), \
- ((char)(imm)&0xF0) ? 53 : (char)(imm) + ((char)(imm)>0xA ? 37 : 21), \
- ((char)(imm)&0xF0) ? 54 : (char)(imm) + ((char)(imm)>0x9 ? 38 : 22), \
- ((char)(imm)&0xF0) ? 55 : (char)(imm) + ((char)(imm)>0x8 ? 39 : 23), \
- ((char)(imm)&0xF0) ? 56 : (char)(imm) + ((char)(imm)>0x7 ? 40 : 24), \
- ((char)(imm)&0xF0) ? 57 : (char)(imm) + ((char)(imm)>0x6 ? 41 : 25), \
- ((char)(imm)&0xF0) ? 58 : (char)(imm) + ((char)(imm)>0x5 ? 42 : 26), \
- ((char)(imm)&0xF0) ? 59 : (char)(imm) + ((char)(imm)>0x4 ? 43 : 27), \
- ((char)(imm)&0xF0) ? 60 : (char)(imm) + ((char)(imm)>0x3 ? 44 : 28), \
- ((char)(imm)&0xF0) ? 61 : (char)(imm) + ((char)(imm)>0x2 ? 45 : 29), \
- ((char)(imm)&0xF0) ? 62 : (char)(imm) + ((char)(imm)>0x1 ? 46 : 30), \
- ((char)(imm)&0xF0) ? 63 : (char)(imm) + ((char)(imm)>0x0 ? 47 : 31)); })
-
-#define _mm256_bsrli_epi128(a, count) _mm256_srli_si256((a), (count))
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+#define _mm256_srli_si256(a, imm) \
+ (__m256i)__builtin_ia32_psrldqi256_byteshift((__m256i)(a), (int)(imm))
+
+#define _mm256_bsrli_epi128(a, imm) \
+ (__m256i)__builtin_ia32_psrldqi256_byteshift((__m256i)(a), (int)(imm))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srli_epi16(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psrlwi256((__v16hi)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srl_epi16(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psrlw256((__v16hi)__a, (__v8hi)__count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srli_epi32(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psrldi256((__v8si)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srl_epi32(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psrld256((__v8si)__a, (__v4si)__count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srli_epi64(__m256i __a, int __count)
{
return __builtin_ia32_psrlqi256((__v4di)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srl_epi64(__m256i __a, __m128i __count)
{
return __builtin_ia32_psrlq256((__v4di)__a, __count);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sub_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qu)__a - (__v32qu)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sub_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hu)__a - (__v16hu)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sub_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8su)__a - (__v8su)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sub_epi64(__m256i __a, __m256i __b)
{
return (__m256i)((__v4du)__a - (__v4du)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_subs_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_subs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_subs_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubusb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_subs_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubusw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpackhi_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b, 8, 32+8, 9, 32+9, 10, 32+10, 11, 32+11, 12, 32+12, 13, 32+13, 14, 32+14, 15, 32+15, 24, 32+24, 25, 32+25, 26, 32+26, 27, 32+27, 28, 32+28, 29, 32+29, 30, 32+30, 31, 32+31);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpackhi_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)__b, 4, 16+4, 5, 16+5, 6, 16+6, 7, 16+7, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpackhi_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)__b, 2, 8+2, 3, 8+3, 6, 8+6, 7, 8+7);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpackhi_epi64(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v4di)__a, (__v4di)__b, 1, 4+1, 3, 4+3);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpacklo_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b, 0, 32+0, 1, 32+1, 2, 32+2, 3, 32+3, 4, 32+4, 5, 32+5, 6, 32+6, 7, 32+7, 16, 32+16, 17, 32+17, 18, 32+18, 19, 32+19, 20, 32+20, 21, 32+21, 22, 32+22, 23, 32+23);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpacklo_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)__b, 0, 16+0, 1, 16+1, 2, 16+2, 3, 16+3, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpacklo_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)__b, 0, 8+0, 1, 8+1, 4, 8+4, 5, 8+5);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_unpacklo_epi64(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v4di)__a, (__v4di)__b, 0, 4+0, 2, 4+2);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_xor_si256(__m256i __a, __m256i __b)
{
return (__m256i)((__v4du)__a ^ (__v4du)__b);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_stream_load_si256(__m256i const *__V)
{
typedef __v4di __v4di_aligned __attribute__((aligned(32)));
return (__m256i)__builtin_nontemporal_load((const __v4di_aligned *)__V);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_broadcastss_ps(__m128 __X)
{
return (__m128)__builtin_shufflevector((__v4sf)__X, (__v4sf)__X, 0, 0, 0, 0);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_broadcastsd_pd(__m128d __a)
{
return __builtin_shufflevector((__v2df)__a, (__v2df)__a, 0, 0);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_broadcastss_ps(__m128 __X)
{
return (__m256)__builtin_shufflevector((__v4sf)__X, (__v4sf)__X, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_broadcastsd_pd(__m128d __X)
{
return (__m256d)__builtin_shufflevector((__v2df)__X, (__v2df)__X, 0, 0, 0, 0);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastsi128_si256(__m128i __X)
{
return (__m256i)__builtin_shufflevector((__v2di)__X, (__v2di)__X, 0, 1, 0, 1);
}
-#define _mm_blend_epi32(V1, V2, M) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v4si)(__m128i)(V1), \
- (__v4si)(__m128i)(V2), \
- (((M) & 0x01) ? 4 : 0), \
- (((M) & 0x02) ? 5 : 1), \
- (((M) & 0x04) ? 6 : 2), \
- (((M) & 0x08) ? 7 : 3)); })
-
-#define _mm256_blend_epi32(V1, V2, M) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v8si)(__m256i)(V1), \
- (__v8si)(__m256i)(V2), \
- (((M) & 0x01) ? 8 : 0), \
- (((M) & 0x02) ? 9 : 1), \
- (((M) & 0x04) ? 10 : 2), \
- (((M) & 0x08) ? 11 : 3), \
- (((M) & 0x10) ? 12 : 4), \
- (((M) & 0x20) ? 13 : 5), \
- (((M) & 0x40) ? 14 : 6), \
- (((M) & 0x80) ? 15 : 7)); })
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+#define _mm_blend_epi32(V1, V2, M) \
+ (__m128i)__builtin_ia32_pblendd128((__v4si)(__m128i)(V1), \
+ (__v4si)(__m128i)(V2), (int)(M))
+
+#define _mm256_blend_epi32(V1, V2, M) \
+ (__m256i)__builtin_ia32_pblendd256((__v8si)(__m256i)(V1), \
+ (__v8si)(__m256i)(V2), (int)(M))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastb_epi8(__m128i __X)
{
return (__m256i)__builtin_shufflevector((__v16qi)__X, (__v16qi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastw_epi16(__m128i __X)
{
return (__m256i)__builtin_shufflevector((__v8hi)__X, (__v8hi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastd_epi32(__m128i __X)
{
return (__m256i)__builtin_shufflevector((__v4si)__X, (__v4si)__X, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastq_epi64(__m128i __X)
{
return (__m256i)__builtin_shufflevector((__v2di)__X, (__v2di)__X, 0, 0, 0, 0);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcastb_epi8(__m128i __X)
{
return (__m128i)__builtin_shufflevector((__v16qi)__X, (__v16qi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcastw_epi16(__m128i __X)
{
return (__m128i)__builtin_shufflevector((__v8hi)__X, (__v8hi)__X, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcastd_epi32(__m128i __X)
{
return (__m128i)__builtin_shufflevector((__v4si)__X, (__v4si)__X, 0, 0, 0, 0);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcastq_epi64(__m128i __X)
{
return (__m128i)__builtin_shufflevector((__v2di)__X, (__v2di)__X, 0, 0);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_permutevar8x32_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_permvarsi256((__v8si)__a, (__v8si)__b);
}
-#define _mm256_permute4x64_pd(V, M) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v4df)(__m256d)(V), \
- (__v4df)_mm256_undefined_pd(), \
- ((M) >> 0) & 0x3, \
- ((M) >> 2) & 0x3, \
- ((M) >> 4) & 0x3, \
- ((M) >> 6) & 0x3); })
+#define _mm256_permute4x64_pd(V, M) \
+ (__m256d)__builtin_ia32_permdf256((__v4df)(__m256d)(V), (int)(M))
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_permutevar8x32_ps(__m256 __a, __m256i __b)
{
return (__m256)__builtin_ia32_permvarsf256((__v8sf)__a, (__v8si)__b);
}
-#define _mm256_permute4x64_epi64(V, M) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v4di)(__m256i)(V), \
- (__v4di)_mm256_undefined_si256(), \
- ((M) >> 0) & 0x3, \
- ((M) >> 2) & 0x3, \
- ((M) >> 4) & 0x3, \
- ((M) >> 6) & 0x3); })
-
-#define _mm256_permute2x128_si256(V1, V2, M) __extension__ ({ \
- (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (M)); })
-
-#define _mm256_extracti128_si256(V, M) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v4di)(__m256i)(V), \
- (__v4di)_mm256_undefined_si256(), \
- (((M) & 1) ? 2 : 0), \
- (((M) & 1) ? 3 : 1) ); })
-
-#define _mm256_inserti128_si256(V1, V2, M) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v4di)(__m256i)(V1), \
- (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
- (((M) & 1) ? 0 : 4), \
- (((M) & 1) ? 1 : 5), \
- (((M) & 1) ? 4 : 2), \
- (((M) & 1) ? 5 : 3) ); })
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+#define _mm256_permute4x64_epi64(V, M) \
+ (__m256i)__builtin_ia32_permdi256((__v4di)(__m256i)(V), (int)(M))
+
+#define _mm256_permute2x128_si256(V1, V2, M) \
+ (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (int)(M))
+
+#define _mm256_extracti128_si256(V, M) \
+ (__m128i)__builtin_ia32_extract128i256((__v4di)(__m256i)(V), (int)(M))
+
+#define _mm256_inserti128_si256(V1, V2, M) \
+ (__m256i)__builtin_ia32_insert128i256((__v4di)(__m256i)(V1), \
+ (__v2di)(__m128i)(V2), (int)(M))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskload_epi32(int const *__X, __m256i __M)
{
return (__m256i)__builtin_ia32_maskloadd256((const __v8si *)__X, (__v8si)__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskload_epi64(long long const *__X, __m256i __M)
{
return (__m256i)__builtin_ia32_maskloadq256((const __v4di *)__X, (__v4di)__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskload_epi32(int const *__X, __m128i __M)
{
return (__m128i)__builtin_ia32_maskloadd((const __v4si *)__X, (__v4si)__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskload_epi64(long long const *__X, __m128i __M)
{
return (__m128i)__builtin_ia32_maskloadq((const __v2di *)__X, (__v2di)__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_maskstore_epi32(int *__X, __m256i __M, __m256i __Y)
{
__builtin_ia32_maskstored256((__v8si *)__X, (__v8si)__M, (__v8si)__Y);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_maskstore_epi64(long long *__X, __m256i __M, __m256i __Y)
{
__builtin_ia32_maskstoreq256((__v4di *)__X, (__v4di)__M, (__v4di)__Y);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_maskstore_epi32(int *__X, __m128i __M, __m128i __Y)
{
__builtin_ia32_maskstored((__v4si *)__X, (__v4si)__M, (__v4si)__Y);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_maskstore_epi64(long long *__X, __m128i __M, __m128i __Y)
{
__builtin_ia32_maskstoreq(( __v2di *)__X, (__v2di)__M, (__v2di)__Y);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sllv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv8si((__v8si)__X, (__v8si)__Y);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_sllv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv4si((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sllv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv4di((__v4di)__X, (__v4di)__Y);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_sllv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv2di((__v2di)__X, (__v2di)__Y);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srav_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrav8si((__v8si)__X, (__v8si)__Y);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srav_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrav4si((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srlv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv8si((__v8si)__X, (__v8si)__Y);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srlv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv4si((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srlv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv4di((__v4di)__X, (__v4di)__Y);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srlv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv2di((__v2di)__X, (__v2di)__Y);
}
-#define _mm_mask_i32gather_pd(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i32gather_pd(a, m, i, mask, s) \
(__m128d)__builtin_ia32_gatherd_pd((__v2df)(__m128i)(a), \
(double const *)(m), \
(__v4si)(__m128i)(i), \
- (__v2df)(__m128d)(mask), (s)); })
+ (__v2df)(__m128d)(mask), (s))
-#define _mm256_mask_i32gather_pd(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i32gather_pd(a, m, i, mask, s) \
(__m256d)__builtin_ia32_gatherd_pd256((__v4df)(__m256d)(a), \
(double const *)(m), \
(__v4si)(__m128i)(i), \
- (__v4df)(__m256d)(mask), (s)); })
+ (__v4df)(__m256d)(mask), (s))
-#define _mm_mask_i64gather_pd(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i64gather_pd(a, m, i, mask, s) \
(__m128d)__builtin_ia32_gatherq_pd((__v2df)(__m128d)(a), \
(double const *)(m), \
(__v2di)(__m128i)(i), \
- (__v2df)(__m128d)(mask), (s)); })
+ (__v2df)(__m128d)(mask), (s))
-#define _mm256_mask_i64gather_pd(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i64gather_pd(a, m, i, mask, s) \
(__m256d)__builtin_ia32_gatherq_pd256((__v4df)(__m256d)(a), \
(double const *)(m), \
(__v4di)(__m256i)(i), \
- (__v4df)(__m256d)(mask), (s)); })
+ (__v4df)(__m256d)(mask), (s))
-#define _mm_mask_i32gather_ps(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i32gather_ps(a, m, i, mask, s) \
(__m128)__builtin_ia32_gatherd_ps((__v4sf)(__m128)(a), \
(float const *)(m), \
(__v4si)(__m128i)(i), \
- (__v4sf)(__m128)(mask), (s)); })
+ (__v4sf)(__m128)(mask), (s))
-#define _mm256_mask_i32gather_ps(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i32gather_ps(a, m, i, mask, s) \
(__m256)__builtin_ia32_gatherd_ps256((__v8sf)(__m256)(a), \
(float const *)(m), \
(__v8si)(__m256i)(i), \
- (__v8sf)(__m256)(mask), (s)); })
+ (__v8sf)(__m256)(mask), (s))
-#define _mm_mask_i64gather_ps(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i64gather_ps(a, m, i, mask, s) \
(__m128)__builtin_ia32_gatherq_ps((__v4sf)(__m128)(a), \
(float const *)(m), \
(__v2di)(__m128i)(i), \
- (__v4sf)(__m128)(mask), (s)); })
+ (__v4sf)(__m128)(mask), (s))
-#define _mm256_mask_i64gather_ps(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i64gather_ps(a, m, i, mask, s) \
(__m128)__builtin_ia32_gatherq_ps256((__v4sf)(__m128)(a), \
(float const *)(m), \
(__v4di)(__m256i)(i), \
- (__v4sf)(__m128)(mask), (s)); })
+ (__v4sf)(__m128)(mask), (s))
-#define _mm_mask_i32gather_epi32(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i32gather_epi32(a, m, i, mask, s) \
(__m128i)__builtin_ia32_gatherd_d((__v4si)(__m128i)(a), \
(int const *)(m), \
(__v4si)(__m128i)(i), \
- (__v4si)(__m128i)(mask), (s)); })
+ (__v4si)(__m128i)(mask), (s))
-#define _mm256_mask_i32gather_epi32(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i32gather_epi32(a, m, i, mask, s) \
(__m256i)__builtin_ia32_gatherd_d256((__v8si)(__m256i)(a), \
(int const *)(m), \
(__v8si)(__m256i)(i), \
- (__v8si)(__m256i)(mask), (s)); })
+ (__v8si)(__m256i)(mask), (s))
-#define _mm_mask_i64gather_epi32(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i64gather_epi32(a, m, i, mask, s) \
(__m128i)__builtin_ia32_gatherq_d((__v4si)(__m128i)(a), \
(int const *)(m), \
(__v2di)(__m128i)(i), \
- (__v4si)(__m128i)(mask), (s)); })
+ (__v4si)(__m128i)(mask), (s))
-#define _mm256_mask_i64gather_epi32(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i64gather_epi32(a, m, i, mask, s) \
(__m128i)__builtin_ia32_gatherq_d256((__v4si)(__m128i)(a), \
(int const *)(m), \
(__v4di)(__m256i)(i), \
- (__v4si)(__m128i)(mask), (s)); })
+ (__v4si)(__m128i)(mask), (s))
-#define _mm_mask_i32gather_epi64(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i32gather_epi64(a, m, i, mask, s) \
(__m128i)__builtin_ia32_gatherd_q((__v2di)(__m128i)(a), \
(long long const *)(m), \
(__v4si)(__m128i)(i), \
- (__v2di)(__m128i)(mask), (s)); })
+ (__v2di)(__m128i)(mask), (s))
-#define _mm256_mask_i32gather_epi64(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i32gather_epi64(a, m, i, mask, s) \
(__m256i)__builtin_ia32_gatherd_q256((__v4di)(__m256i)(a), \
(long long const *)(m), \
(__v4si)(__m128i)(i), \
- (__v4di)(__m256i)(mask), (s)); })
+ (__v4di)(__m256i)(mask), (s))
-#define _mm_mask_i64gather_epi64(a, m, i, mask, s) __extension__ ({ \
+#define _mm_mask_i64gather_epi64(a, m, i, mask, s) \
(__m128i)__builtin_ia32_gatherq_q((__v2di)(__m128i)(a), \
(long long const *)(m), \
(__v2di)(__m128i)(i), \
- (__v2di)(__m128i)(mask), (s)); })
+ (__v2di)(__m128i)(mask), (s))
-#define _mm256_mask_i64gather_epi64(a, m, i, mask, s) __extension__ ({ \
+#define _mm256_mask_i64gather_epi64(a, m, i, mask, s) \
(__m256i)__builtin_ia32_gatherq_q256((__v4di)(__m256i)(a), \
(long long const *)(m), \
(__v4di)(__m256i)(i), \
- (__v4di)(__m256i)(mask), (s)); })
+ (__v4di)(__m256i)(mask), (s))
-#define _mm_i32gather_pd(m, i, s) __extension__ ({ \
+#define _mm_i32gather_pd(m, i, s) \
(__m128d)__builtin_ia32_gatherd_pd((__v2df)_mm_undefined_pd(), \
(double const *)(m), \
(__v4si)(__m128i)(i), \
(__v2df)_mm_cmpeq_pd(_mm_setzero_pd(), \
_mm_setzero_pd()), \
- (s)); })
+ (s))
-#define _mm256_i32gather_pd(m, i, s) __extension__ ({ \
+#define _mm256_i32gather_pd(m, i, s) \
(__m256d)__builtin_ia32_gatherd_pd256((__v4df)_mm256_undefined_pd(), \
(double const *)(m), \
(__v4si)(__m128i)(i), \
(__v4df)_mm256_cmp_pd(_mm256_setzero_pd(), \
_mm256_setzero_pd(), \
_CMP_EQ_OQ), \
- (s)); })
+ (s))
-#define _mm_i64gather_pd(m, i, s) __extension__ ({ \
+#define _mm_i64gather_pd(m, i, s) \
(__m128d)__builtin_ia32_gatherq_pd((__v2df)_mm_undefined_pd(), \
(double const *)(m), \
(__v2di)(__m128i)(i), \
(__v2df)_mm_cmpeq_pd(_mm_setzero_pd(), \
_mm_setzero_pd()), \
- (s)); })
+ (s))
-#define _mm256_i64gather_pd(m, i, s) __extension__ ({ \
+#define _mm256_i64gather_pd(m, i, s) \
(__m256d)__builtin_ia32_gatherq_pd256((__v4df)_mm256_undefined_pd(), \
(double const *)(m), \
(__v4di)(__m256i)(i), \
(__v4df)_mm256_cmp_pd(_mm256_setzero_pd(), \
_mm256_setzero_pd(), \
_CMP_EQ_OQ), \
- (s)); })
+ (s))
-#define _mm_i32gather_ps(m, i, s) __extension__ ({ \
+#define _mm_i32gather_ps(m, i, s) \
(__m128)__builtin_ia32_gatherd_ps((__v4sf)_mm_undefined_ps(), \
(float const *)(m), \
(__v4si)(__m128i)(i), \
(__v4sf)_mm_cmpeq_ps(_mm_setzero_ps(), \
_mm_setzero_ps()), \
- (s)); })
+ (s))
-#define _mm256_i32gather_ps(m, i, s) __extension__ ({ \
+#define _mm256_i32gather_ps(m, i, s) \
(__m256)__builtin_ia32_gatherd_ps256((__v8sf)_mm256_undefined_ps(), \
(float const *)(m), \
(__v8si)(__m256i)(i), \
(__v8sf)_mm256_cmp_ps(_mm256_setzero_ps(), \
_mm256_setzero_ps(), \
_CMP_EQ_OQ), \
- (s)); })
+ (s))
-#define _mm_i64gather_ps(m, i, s) __extension__ ({ \
+#define _mm_i64gather_ps(m, i, s) \
(__m128)__builtin_ia32_gatherq_ps((__v4sf)_mm_undefined_ps(), \
(float const *)(m), \
(__v2di)(__m128i)(i), \
(__v4sf)_mm_cmpeq_ps(_mm_setzero_ps(), \
_mm_setzero_ps()), \
- (s)); })
+ (s))
-#define _mm256_i64gather_ps(m, i, s) __extension__ ({ \
+#define _mm256_i64gather_ps(m, i, s) \
(__m128)__builtin_ia32_gatherq_ps256((__v4sf)_mm_undefined_ps(), \
(float const *)(m), \
(__v4di)(__m256i)(i), \
(__v4sf)_mm_cmpeq_ps(_mm_setzero_ps(), \
_mm_setzero_ps()), \
- (s)); })
+ (s))
-#define _mm_i32gather_epi32(m, i, s) __extension__ ({ \
+#define _mm_i32gather_epi32(m, i, s) \
(__m128i)__builtin_ia32_gatherd_d((__v4si)_mm_undefined_si128(), \
(int const *)(m), (__v4si)(__m128i)(i), \
- (__v4si)_mm_set1_epi32(-1), (s)); })
+ (__v4si)_mm_set1_epi32(-1), (s))
-#define _mm256_i32gather_epi32(m, i, s) __extension__ ({ \
+#define _mm256_i32gather_epi32(m, i, s) \
(__m256i)__builtin_ia32_gatherd_d256((__v8si)_mm256_undefined_si256(), \
(int const *)(m), (__v8si)(__m256i)(i), \
- (__v8si)_mm256_set1_epi32(-1), (s)); })
+ (__v8si)_mm256_set1_epi32(-1), (s))
-#define _mm_i64gather_epi32(m, i, s) __extension__ ({ \
+#define _mm_i64gather_epi32(m, i, s) \
(__m128i)__builtin_ia32_gatherq_d((__v4si)_mm_undefined_si128(), \
(int const *)(m), (__v2di)(__m128i)(i), \
- (__v4si)_mm_set1_epi32(-1), (s)); })
+ (__v4si)_mm_set1_epi32(-1), (s))
-#define _mm256_i64gather_epi32(m, i, s) __extension__ ({ \
+#define _mm256_i64gather_epi32(m, i, s) \
(__m128i)__builtin_ia32_gatherq_d256((__v4si)_mm_undefined_si128(), \
(int const *)(m), (__v4di)(__m256i)(i), \
- (__v4si)_mm_set1_epi32(-1), (s)); })
+ (__v4si)_mm_set1_epi32(-1), (s))
-#define _mm_i32gather_epi64(m, i, s) __extension__ ({ \
+#define _mm_i32gather_epi64(m, i, s) \
(__m128i)__builtin_ia32_gatherd_q((__v2di)_mm_undefined_si128(), \
(long long const *)(m), \
(__v4si)(__m128i)(i), \
- (__v2di)_mm_set1_epi64x(-1), (s)); })
+ (__v2di)_mm_set1_epi64x(-1), (s))
-#define _mm256_i32gather_epi64(m, i, s) __extension__ ({ \
+#define _mm256_i32gather_epi64(m, i, s) \
(__m256i)__builtin_ia32_gatherd_q256((__v4di)_mm256_undefined_si256(), \
(long long const *)(m), \
(__v4si)(__m128i)(i), \
- (__v4di)_mm256_set1_epi64x(-1), (s)); })
+ (__v4di)_mm256_set1_epi64x(-1), (s))
-#define _mm_i64gather_epi64(m, i, s) __extension__ ({ \
+#define _mm_i64gather_epi64(m, i, s) \
(__m128i)__builtin_ia32_gatherq_q((__v2di)_mm_undefined_si128(), \
(long long const *)(m), \
(__v2di)(__m128i)(i), \
- (__v2di)_mm_set1_epi64x(-1), (s)); })
+ (__v2di)_mm_set1_epi64x(-1), (s))
-#define _mm256_i64gather_epi64(m, i, s) __extension__ ({ \
+#define _mm256_i64gather_epi64(m, i, s) \
(__m256i)__builtin_ia32_gatherq_q256((__v4di)_mm256_undefined_si256(), \
(long long const *)(m), \
(__v4di)(__m256i)(i), \
- (__v4di)_mm256_set1_epi64x(-1), (s)); })
+ (__v4di)_mm256_set1_epi64x(-1), (s))
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS256
+#undef __DEFAULT_FN_ATTRS128
#endif /* __AVX2INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512bitalgintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512bitalgintrin.h
index 2dd1471d2f7e..56046f8c4999 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512bitalgintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512bitalgintrin.h
@@ -29,7 +29,7 @@
#define __AVX512BITALGINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bitalg")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bitalg"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_popcnt_epi16(__m512i __A)
@@ -48,7 +48,7 @@ _mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B)
{
- return _mm512_mask_popcnt_epi16((__m512i) _mm512_setzero_hi(),
+ return _mm512_mask_popcnt_epi16((__m512i) _mm512_setzero_si512(),
__U,
__B);
}
@@ -70,7 +70,7 @@ _mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B)
{
- return _mm512_mask_popcnt_epi8((__m512i) _mm512_setzero_qi(),
+ return _mm512_mask_popcnt_epi8((__m512i) _mm512_setzero_si512(),
__U,
__B);
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
index 064300a48798..fc4632374977 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
@@ -32,69 +32,49 @@ typedef unsigned int __mmask32;
typedef unsigned long long __mmask64;
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw")))
-
-static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_setzero_qi(void) {
- return (__m512i)(__v64qi){ 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
-}
-
-static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_setzero_hi(void) {
- return (__m512i)(__v32hi){ 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
-}
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw"), __min_vector_width__(512)))
/* Integer compare */
-#define _mm512_cmp_epi8_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epi8_mask(a, b, p) \
(__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
(__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)-1); })
+ (__mmask64)-1)
-#define _mm512_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epi8_mask(m, a, b, p) \
(__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
(__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)(m)); })
+ (__mmask64)(m))
-#define _mm512_cmp_epu8_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epu8_mask(a, b, p) \
(__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
(__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)-1); })
+ (__mmask64)-1)
-#define _mm512_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epu8_mask(m, a, b, p) \
(__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
(__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)(m)); })
+ (__mmask64)(m))
-#define _mm512_cmp_epi16_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epi16_mask(a, b, p) \
(__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
(__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)-1); })
+ (__mmask32)-1)
-#define _mm512_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epi16_mask(m, a, b, p) \
(__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
(__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)(m)); })
+ (__mmask32)(m))
-#define _mm512_cmp_epu16_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epu16_mask(a, b, p) \
(__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
(__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)-1); })
+ (__mmask32)-1)
-#define _mm512_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epu16_mask(m, a, b, p) \
(__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
(__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)(m)); })
+ (__mmask32)(m))
#define _mm512_cmpeq_epi8_mask(A, B) \
_mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_EQ)
@@ -212,7 +192,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_add_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_add_epi8(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -231,7 +211,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_sub_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_sub_epi8(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -250,7 +230,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_add_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_add_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -269,7 +249,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_sub_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_sub_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -288,7 +268,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_mullo_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_mullo_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -310,49 +290,45 @@ _mm512_mask_blend_epi16 (__mmask32 __U, __m512i __A, __m512i __W)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_abs_epi8 (__m512i __A)
{
- return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_pabsb512((__v64qi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_abs_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_abs_epi8(__A),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_abs_epi8 (__mmask64 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_abs_epi8(__A),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_abs_epi16 (__m512i __A)
{
- return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pabsw512((__v32hi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_abs_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_abs_epi16(__A),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_abs_epi16 (__mmask32 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_abs_epi16(__A),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -366,7 +342,7 @@ _mm512_maskz_packs_epi32(__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
(__v32hi)_mm512_packs_epi32(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -396,7 +372,7 @@ _mm512_maskz_packs_epi16(__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
(__v64qi)_mm512_packs_epi16(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -410,7 +386,7 @@ _mm512_maskz_packus_epi32(__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
(__v32hi)_mm512_packus_epi32(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -440,7 +416,7 @@ _mm512_maskz_packus_epi16(__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
(__v64qi)_mm512_packus_epi16(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -448,7 +424,7 @@ _mm512_adds_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) -1);
}
@@ -467,7 +443,7 @@ _mm512_maskz_adds_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) __U);
}
@@ -476,7 +452,7 @@ _mm512_adds_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) -1);
}
@@ -495,7 +471,7 @@ _mm512_maskz_adds_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) __U);
}
@@ -504,7 +480,7 @@ _mm512_adds_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) -1);
}
@@ -523,7 +499,7 @@ _mm512_maskz_adds_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) __U);
}
@@ -532,7 +508,7 @@ _mm512_adds_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) -1);
}
@@ -551,7 +527,7 @@ _mm512_maskz_adds_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) __U);
}
@@ -579,7 +555,7 @@ _mm512_maskz_avg_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_avg_epu8(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -606,231 +582,184 @@ _mm512_maskz_avg_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_avg_epu16(__A, __B),
- (__v32hi) _mm512_setzero_hi());
+ (__v32hi) _mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_max_epi8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_pmaxsb512((__v64qi) __A, (__v64qi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_max_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_max_epi8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_max_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_max_epi8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_max_epi8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_max_epi16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pmaxsw512((__v32hi) __A, (__v32hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_max_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_max_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_max_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_max_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_max_epu8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_pmaxub512((__v64qi)__A, (__v64qi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_max_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_max_epu8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_max_epu8 (__m512i __W, __mmask64 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_max_epu8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_max_epu8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_max_epu16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pmaxuw512((__v32hi)__A, (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_max_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_max_epu16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_max_epu16 (__m512i __W, __mmask32 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_max_epu16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_max_epu16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_min_epi8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_pminsb512((__v64qi) __A, (__v64qi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_min_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_min_epi8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_min_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_min_epi8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_min_epi8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_min_epi16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pminsw512((__v32hi) __A, (__v32hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_min_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_min_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_min_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_min_epi16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_min_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_min_epu8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_pminub512((__v64qi)__A, (__v64qi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_min_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_min_epu8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_min_epu8 (__m512i __W, __mmask64 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_min_epu8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_min_epu8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_min_epu16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pminuw512((__v32hi)__A, (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_min_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_min_epu16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A,
- __m512i __B)
+_mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_min_epu16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -852,7 +781,7 @@ _mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_shuffle_epi8(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -860,7 +789,7 @@ _mm512_subs_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) -1);
}
@@ -879,7 +808,7 @@ _mm512_maskz_subs_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) __U);
}
@@ -888,7 +817,7 @@ _mm512_subs_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) -1);
}
@@ -907,7 +836,7 @@ _mm512_maskz_subs_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) __U);
}
@@ -916,7 +845,7 @@ _mm512_subs_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) -1);
}
@@ -935,7 +864,7 @@ _mm512_maskz_subs_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
(__mmask64) __U);
}
@@ -944,7 +873,7 @@ _mm512_subs_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) -1);
}
@@ -963,182 +892,148 @@ _mm512_maskz_subs_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
(__mmask32) __U);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask2_permutex2var_epi16 (__m512i __A, __m512i __I,
- __mmask32 __U, __m512i __B)
+_mm512_permutex2var_epi16(__m512i __A, __m512i __I, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermi2varhi512_mask ((__v32hi) __A,
- (__v32hi) __I /* idx */ ,
- (__v32hi) __B,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_vpermi2varhi512((__v32hi)__A, (__v32hi)__I,
+ (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_permutex2var_epi16 (__m512i __A, __m512i __I, __m512i __B)
+_mm512_mask_permutex2var_epi16(__m512i __A, __mmask32 __U, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varhi512_mask ((__v32hi) __I /* idx */,
- (__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_permutex2var_epi16(__A, __I, __B),
+ (__v32hi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_permutex2var_epi16 (__m512i __A, __mmask32 __U,
- __m512i __I, __m512i __B)
+_mm512_mask2_permutex2var_epi16(__m512i __A, __m512i __I, __mmask32 __U,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varhi512_mask ((__v32hi) __I /* idx */,
- (__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_permutex2var_epi16(__A, __I, __B),
+ (__v32hi)__I);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_permutex2var_epi16 (__mmask32 __U, __m512i __A,
- __m512i __I, __m512i __B)
+_mm512_maskz_permutex2var_epi16(__mmask32 __U, __m512i __A, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varhi512_maskz ((__v32hi) __I
- /* idx */ ,
- (__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_permutex2var_epi16(__A, __I, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mulhrs_epi16 (__m512i __A, __m512i __B)
+_mm512_mulhrs_epi16(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pmulhrsw512((__v32hi)__A, (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mulhrs_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+_mm512_mask_mulhrs_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mulhrs_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mulhrs_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+_mm512_maskz_mulhrs_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mulhrs_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mulhi_epi16 (__m512i __A, __m512i __B)
+_mm512_mulhi_epi16(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pmulhw512((__v32hi) __A, (__v32hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mulhi_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+_mm512_mask_mulhi_epi16(__m512i __W, __mmask32 __U, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mulhi_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mulhi_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+_mm512_maskz_mulhi_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mulhi_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mulhi_epu16 (__m512i __A, __m512i __B)
+_mm512_mulhi_epu16(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_pmulhuw512((__v32hi) __A, (__v32hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mulhi_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+_mm512_mask_mulhi_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mulhi_epu16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_mulhi_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mulhi_epu16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maddubs_epi16 (__m512i __X, __m512i __Y) {
- return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X,
- (__v64qi) __Y,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+_mm512_maddubs_epi16(__m512i __X, __m512i __Y) {
+ return (__m512i)__builtin_ia32_pmaddubsw512((__v64qi)__X, (__v64qi)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_maddubs_epi16 (__m512i __W, __mmask32 __U, __m512i __X,
- __m512i __Y) {
- return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X,
- (__v64qi) __Y,
- (__v32hi) __W,
- (__mmask32) __U);
+_mm512_mask_maddubs_epi16(__m512i __W, __mmask32 __U, __m512i __X,
+ __m512i __Y) {
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32) __U,
+ (__v32hi)_mm512_maddubs_epi16(__X, __Y),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_maddubs_epi16 (__mmask32 __U, __m512i __X, __m512i __Y) {
- return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X,
- (__v64qi) __Y,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+_mm512_maskz_maddubs_epi16(__mmask32 __U, __m512i __X, __m512i __Y) {
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32) __U,
+ (__v32hi)_mm512_maddubs_epi16(__X, __Y),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_madd_epi16 (__m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v16si) _mm512_setzero_si512(),
- (__mmask16) -1);
+_mm512_madd_epi16(__m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_pmaddwd512((__v32hi)__A, (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_madd_epi16 (__m512i __W, __mmask16 __U, __m512i __A,
- __m512i __B) {
- return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v16si) __W,
- (__mmask16) __U);
+_mm512_mask_madd_epi16(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_madd_epi16(__A, __B),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_madd_epi16 (__mmask16 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v16si) _mm512_setzero_si512(),
- (__mmask16) __U);
+_mm512_maskz_madd_epi16(__mmask16 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_madd_epi16(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
@@ -1186,7 +1081,7 @@ _mm512_maskz_cvtusepi16_epi8 (__mmask32 __M, __m512i __A) {
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm512_cvtepi16_epi8 (__m512i __A) {
return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
- (__v32qi) _mm256_setzero_si256(),
+ (__v32qi) _mm256_undefined_si256(),
(__mmask32) -1);
}
@@ -1254,7 +1149,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_unpackhi_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_unpackhi_epi8(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1281,7 +1176,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_unpackhi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_unpackhi_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1316,7 +1211,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_unpacklo_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_unpacklo_epi8(__A, __B),
- (__v64qi)_mm512_setzero_qi());
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1343,7 +1238,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_unpacklo_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_unpacklo_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1367,7 +1262,7 @@ _mm512_maskz_cvtepi8_epi16(__mmask32 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_cvtepi8_epi16(__A),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1389,83 +1284,41 @@ _mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_cvtepu8_epi16(__A),
- (__v32hi)_mm512_setzero_hi());
-}
-
-
-#define _mm512_shufflehi_epi16(A, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v32hi)(__m512i)(A), \
- (__v32hi)_mm512_undefined_epi32(), \
- 0, 1, 2, 3, \
- 4 + (((imm) >> 0) & 0x3), \
- 4 + (((imm) >> 2) & 0x3), \
- 4 + (((imm) >> 4) & 0x3), \
- 4 + (((imm) >> 6) & 0x3), \
- 8, 9, 10, 11, \
- 12 + (((imm) >> 0) & 0x3), \
- 12 + (((imm) >> 2) & 0x3), \
- 12 + (((imm) >> 4) & 0x3), \
- 12 + (((imm) >> 6) & 0x3), \
- 16, 17, 18, 19, \
- 20 + (((imm) >> 0) & 0x3), \
- 20 + (((imm) >> 2) & 0x3), \
- 20 + (((imm) >> 4) & 0x3), \
- 20 + (((imm) >> 6) & 0x3), \
- 24, 25, 26, 27, \
- 28 + (((imm) >> 0) & 0x3), \
- 28 + (((imm) >> 2) & 0x3), \
- 28 + (((imm) >> 4) & 0x3), \
- 28 + (((imm) >> 6) & 0x3)); })
-
-#define _mm512_mask_shufflehi_epi16(W, U, A, imm) __extension__ ({ \
+ (__v32hi)_mm512_setzero_si512());
+}
+
+
+#define _mm512_shufflehi_epi16(A, imm) \
+ (__m512i)__builtin_ia32_pshufhw512((__v32hi)(__m512i)(A), (int)(imm))
+
+#define _mm512_mask_shufflehi_epi16(W, U, A, imm) \
(__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
(__v32hi)_mm512_shufflehi_epi16((A), \
(imm)), \
- (__v32hi)(__m512i)(W)); })
+ (__v32hi)(__m512i)(W))
-#define _mm512_maskz_shufflehi_epi16(U, A, imm) __extension__ ({ \
+#define _mm512_maskz_shufflehi_epi16(U, A, imm) \
(__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
(__v32hi)_mm512_shufflehi_epi16((A), \
(imm)), \
- (__v32hi)_mm512_setzero_hi()); })
-
-#define _mm512_shufflelo_epi16(A, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v32hi)(__m512i)(A), \
- (__v32hi)_mm512_undefined_epi32(), \
- 0 + (((imm) >> 0) & 0x3), \
- 0 + (((imm) >> 2) & 0x3), \
- 0 + (((imm) >> 4) & 0x3), \
- 0 + (((imm) >> 6) & 0x3), \
- 4, 5, 6, 7, \
- 8 + (((imm) >> 0) & 0x3), \
- 8 + (((imm) >> 2) & 0x3), \
- 8 + (((imm) >> 4) & 0x3), \
- 8 + (((imm) >> 6) & 0x3), \
- 12, 13, 14, 15, \
- 16 + (((imm) >> 0) & 0x3), \
- 16 + (((imm) >> 2) & 0x3), \
- 16 + (((imm) >> 4) & 0x3), \
- 16 + (((imm) >> 6) & 0x3), \
- 20, 21, 22, 23, \
- 24 + (((imm) >> 0) & 0x3), \
- 24 + (((imm) >> 2) & 0x3), \
- 24 + (((imm) >> 4) & 0x3), \
- 24 + (((imm) >> 6) & 0x3), \
- 28, 29, 30, 31); })
-
-
-#define _mm512_mask_shufflelo_epi16(W, U, A, imm) __extension__ ({ \
+ (__v32hi)_mm512_setzero_si512())
+
+#define _mm512_shufflelo_epi16(A, imm) \
+ (__m512i)__builtin_ia32_pshuflw512((__v32hi)(__m512i)(A), (int)(imm))
+
+
+#define _mm512_mask_shufflelo_epi16(W, U, A, imm) \
(__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
(__v32hi)_mm512_shufflelo_epi16((A), \
(imm)), \
- (__v32hi)(__m512i)(W)); })
+ (__v32hi)(__m512i)(W))
-#define _mm512_maskz_shufflelo_epi16(U, A, imm) __extension__ ({ \
+#define _mm512_maskz_shufflelo_epi16(U, A, imm) \
(__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
(__v32hi)_mm512_shufflelo_epi16((A), \
(imm)), \
- (__v32hi)_mm512_setzero_hi()); })
+ (__v32hi)_mm512_setzero_si512())
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_sllv_epi16(__m512i __A, __m512i __B)
@@ -1486,7 +1339,7 @@ _mm512_maskz_sllv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_sllv_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1508,7 +1361,7 @@ _mm512_maskz_sll_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_sll_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1530,77 +1383,11 @@ _mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_slli_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
-}
-
-#define _mm512_bslli_epi128(a, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector( \
- (__v64qi)_mm512_setzero_si512(), \
- (__v64qi)(__m512i)(a), \
- ((char)(imm)&0xF0) ? 0 : ((char)(imm)>0x0 ? 16 : 64) - (char)(imm), \
- ((char)(imm)&0xF0) ? 1 : ((char)(imm)>0x1 ? 17 : 65) - (char)(imm), \
- ((char)(imm)&0xF0) ? 2 : ((char)(imm)>0x2 ? 18 : 66) - (char)(imm), \
- ((char)(imm)&0xF0) ? 3 : ((char)(imm)>0x3 ? 19 : 67) - (char)(imm), \
- ((char)(imm)&0xF0) ? 4 : ((char)(imm)>0x4 ? 20 : 68) - (char)(imm), \
- ((char)(imm)&0xF0) ? 5 : ((char)(imm)>0x5 ? 21 : 69) - (char)(imm), \
- ((char)(imm)&0xF0) ? 6 : ((char)(imm)>0x6 ? 22 : 70) - (char)(imm), \
- ((char)(imm)&0xF0) ? 7 : ((char)(imm)>0x7 ? 23 : 71) - (char)(imm), \
- ((char)(imm)&0xF0) ? 8 : ((char)(imm)>0x8 ? 24 : 72) - (char)(imm), \
- ((char)(imm)&0xF0) ? 9 : ((char)(imm)>0x9 ? 25 : 73) - (char)(imm), \
- ((char)(imm)&0xF0) ? 10 : ((char)(imm)>0xA ? 26 : 74) - (char)(imm), \
- ((char)(imm)&0xF0) ? 11 : ((char)(imm)>0xB ? 27 : 75) - (char)(imm), \
- ((char)(imm)&0xF0) ? 12 : ((char)(imm)>0xC ? 28 : 76) - (char)(imm), \
- ((char)(imm)&0xF0) ? 13 : ((char)(imm)>0xD ? 29 : 77) - (char)(imm), \
- ((char)(imm)&0xF0) ? 14 : ((char)(imm)>0xE ? 30 : 78) - (char)(imm), \
- ((char)(imm)&0xF0) ? 15 : ((char)(imm)>0xF ? 31 : 79) - (char)(imm), \
- ((char)(imm)&0xF0) ? 16 : ((char)(imm)>0x0 ? 32 : 80) - (char)(imm), \
- ((char)(imm)&0xF0) ? 17 : ((char)(imm)>0x1 ? 33 : 81) - (char)(imm), \
- ((char)(imm)&0xF0) ? 18 : ((char)(imm)>0x2 ? 34 : 82) - (char)(imm), \
- ((char)(imm)&0xF0) ? 19 : ((char)(imm)>0x3 ? 35 : 83) - (char)(imm), \
- ((char)(imm)&0xF0) ? 20 : ((char)(imm)>0x4 ? 36 : 84) - (char)(imm), \
- ((char)(imm)&0xF0) ? 21 : ((char)(imm)>0x5 ? 37 : 85) - (char)(imm), \
- ((char)(imm)&0xF0) ? 22 : ((char)(imm)>0x6 ? 38 : 86) - (char)(imm), \
- ((char)(imm)&0xF0) ? 23 : ((char)(imm)>0x7 ? 39 : 87) - (char)(imm), \
- ((char)(imm)&0xF0) ? 24 : ((char)(imm)>0x8 ? 40 : 88) - (char)(imm), \
- ((char)(imm)&0xF0) ? 25 : ((char)(imm)>0x9 ? 41 : 89) - (char)(imm), \
- ((char)(imm)&0xF0) ? 26 : ((char)(imm)>0xA ? 42 : 90) - (char)(imm), \
- ((char)(imm)&0xF0) ? 27 : ((char)(imm)>0xB ? 43 : 91) - (char)(imm), \
- ((char)(imm)&0xF0) ? 28 : ((char)(imm)>0xC ? 44 : 92) - (char)(imm), \
- ((char)(imm)&0xF0) ? 29 : ((char)(imm)>0xD ? 45 : 93) - (char)(imm), \
- ((char)(imm)&0xF0) ? 30 : ((char)(imm)>0xE ? 46 : 94) - (char)(imm), \
- ((char)(imm)&0xF0) ? 31 : ((char)(imm)>0xF ? 47 : 95) - (char)(imm), \
- ((char)(imm)&0xF0) ? 32 : ((char)(imm)>0x0 ? 48 : 96) - (char)(imm), \
- ((char)(imm)&0xF0) ? 33 : ((char)(imm)>0x1 ? 49 : 97) - (char)(imm), \
- ((char)(imm)&0xF0) ? 34 : ((char)(imm)>0x2 ? 50 : 98) - (char)(imm), \
- ((char)(imm)&0xF0) ? 35 : ((char)(imm)>0x3 ? 51 : 99) - (char)(imm), \
- ((char)(imm)&0xF0) ? 36 : ((char)(imm)>0x4 ? 52 : 100) - (char)(imm), \
- ((char)(imm)&0xF0) ? 37 : ((char)(imm)>0x5 ? 53 : 101) - (char)(imm), \
- ((char)(imm)&0xF0) ? 38 : ((char)(imm)>0x6 ? 54 : 102) - (char)(imm), \
- ((char)(imm)&0xF0) ? 39 : ((char)(imm)>0x7 ? 55 : 103) - (char)(imm), \
- ((char)(imm)&0xF0) ? 40 : ((char)(imm)>0x8 ? 56 : 104) - (char)(imm), \
- ((char)(imm)&0xF0) ? 41 : ((char)(imm)>0x9 ? 57 : 105) - (char)(imm), \
- ((char)(imm)&0xF0) ? 42 : ((char)(imm)>0xA ? 58 : 106) - (char)(imm), \
- ((char)(imm)&0xF0) ? 43 : ((char)(imm)>0xB ? 59 : 107) - (char)(imm), \
- ((char)(imm)&0xF0) ? 44 : ((char)(imm)>0xC ? 60 : 108) - (char)(imm), \
- ((char)(imm)&0xF0) ? 45 : ((char)(imm)>0xD ? 61 : 109) - (char)(imm), \
- ((char)(imm)&0xF0) ? 46 : ((char)(imm)>0xE ? 62 : 110) - (char)(imm), \
- ((char)(imm)&0xF0) ? 47 : ((char)(imm)>0xF ? 63 : 111) - (char)(imm), \
- ((char)(imm)&0xF0) ? 48 : ((char)(imm)>0x0 ? 64 : 112) - (char)(imm), \
- ((char)(imm)&0xF0) ? 49 : ((char)(imm)>0x1 ? 65 : 113) - (char)(imm), \
- ((char)(imm)&0xF0) ? 50 : ((char)(imm)>0x2 ? 66 : 114) - (char)(imm), \
- ((char)(imm)&0xF0) ? 51 : ((char)(imm)>0x3 ? 67 : 115) - (char)(imm), \
- ((char)(imm)&0xF0) ? 52 : ((char)(imm)>0x4 ? 68 : 116) - (char)(imm), \
- ((char)(imm)&0xF0) ? 53 : ((char)(imm)>0x5 ? 69 : 117) - (char)(imm), \
- ((char)(imm)&0xF0) ? 54 : ((char)(imm)>0x6 ? 70 : 118) - (char)(imm), \
- ((char)(imm)&0xF0) ? 55 : ((char)(imm)>0x7 ? 71 : 119) - (char)(imm), \
- ((char)(imm)&0xF0) ? 56 : ((char)(imm)>0x8 ? 72 : 120) - (char)(imm), \
- ((char)(imm)&0xF0) ? 57 : ((char)(imm)>0x9 ? 73 : 121) - (char)(imm), \
- ((char)(imm)&0xF0) ? 58 : ((char)(imm)>0xA ? 74 : 122) - (char)(imm), \
- ((char)(imm)&0xF0) ? 59 : ((char)(imm)>0xB ? 75 : 123) - (char)(imm), \
- ((char)(imm)&0xF0) ? 60 : ((char)(imm)>0xC ? 76 : 124) - (char)(imm), \
- ((char)(imm)&0xF0) ? 61 : ((char)(imm)>0xD ? 77 : 125) - (char)(imm), \
- ((char)(imm)&0xF0) ? 62 : ((char)(imm)>0xE ? 78 : 126) - (char)(imm), \
- ((char)(imm)&0xF0) ? 63 : ((char)(imm)>0xF ? 79 : 127) - (char)(imm)); })
+ (__v32hi)_mm512_setzero_si512());
+}
+
+#define _mm512_bslli_epi128(a, imm) \
+ (__m512i)__builtin_ia32_pslldqi512_byteshift((__v8di)(__m512i)(a), (int)(imm))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_srlv_epi16(__m512i __A, __m512i __B)
@@ -1621,7 +1408,7 @@ _mm512_maskz_srlv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_srlv_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1643,7 +1430,7 @@ _mm512_maskz_srav_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_srav_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1665,7 +1452,7 @@ _mm512_maskz_sra_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_sra_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1687,7 +1474,7 @@ _mm512_maskz_srai_epi16(__mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_srai_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1709,7 +1496,7 @@ _mm512_maskz_srl_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_srl_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1731,77 +1518,11 @@ _mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_srli_epi16(__A, __B),
- (__v32hi)_mm512_setzero_hi());
-}
-
-#define _mm512_bsrli_epi128(a, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector( \
- (__v64qi)(__m512i)(a), \
- (__v64qi)_mm512_setzero_si512(), \
- ((char)(imm)&0xF0) ? 64 : (char)(imm) + ((char)(imm)>0xF ? 48 : 0), \
- ((char)(imm)&0xF0) ? 65 : (char)(imm) + ((char)(imm)>0xE ? 49 : 1), \
- ((char)(imm)&0xF0) ? 66 : (char)(imm) + ((char)(imm)>0xD ? 50 : 2), \
- ((char)(imm)&0xF0) ? 67 : (char)(imm) + ((char)(imm)>0xC ? 51 : 3), \
- ((char)(imm)&0xF0) ? 68 : (char)(imm) + ((char)(imm)>0xB ? 52 : 4), \
- ((char)(imm)&0xF0) ? 69 : (char)(imm) + ((char)(imm)>0xA ? 53 : 5), \
- ((char)(imm)&0xF0) ? 70 : (char)(imm) + ((char)(imm)>0x9 ? 54 : 6), \
- ((char)(imm)&0xF0) ? 71 : (char)(imm) + ((char)(imm)>0x8 ? 55 : 7), \
- ((char)(imm)&0xF0) ? 72 : (char)(imm) + ((char)(imm)>0x7 ? 56 : 8), \
- ((char)(imm)&0xF0) ? 73 : (char)(imm) + ((char)(imm)>0x6 ? 57 : 9), \
- ((char)(imm)&0xF0) ? 74 : (char)(imm) + ((char)(imm)>0x5 ? 58 : 10), \
- ((char)(imm)&0xF0) ? 75 : (char)(imm) + ((char)(imm)>0x4 ? 59 : 11), \
- ((char)(imm)&0xF0) ? 76 : (char)(imm) + ((char)(imm)>0x3 ? 60 : 12), \
- ((char)(imm)&0xF0) ? 77 : (char)(imm) + ((char)(imm)>0x2 ? 61 : 13), \
- ((char)(imm)&0xF0) ? 78 : (char)(imm) + ((char)(imm)>0x1 ? 62 : 14), \
- ((char)(imm)&0xF0) ? 79 : (char)(imm) + ((char)(imm)>0x0 ? 63 : 15), \
- ((char)(imm)&0xF0) ? 80 : (char)(imm) + ((char)(imm)>0xF ? 64 : 16), \
- ((char)(imm)&0xF0) ? 81 : (char)(imm) + ((char)(imm)>0xE ? 65 : 17), \
- ((char)(imm)&0xF0) ? 82 : (char)(imm) + ((char)(imm)>0xD ? 66 : 18), \
- ((char)(imm)&0xF0) ? 83 : (char)(imm) + ((char)(imm)>0xC ? 67 : 19), \
- ((char)(imm)&0xF0) ? 84 : (char)(imm) + ((char)(imm)>0xB ? 68 : 20), \
- ((char)(imm)&0xF0) ? 85 : (char)(imm) + ((char)(imm)>0xA ? 69 : 21), \
- ((char)(imm)&0xF0) ? 86 : (char)(imm) + ((char)(imm)>0x9 ? 70 : 22), \
- ((char)(imm)&0xF0) ? 87 : (char)(imm) + ((char)(imm)>0x8 ? 71 : 23), \
- ((char)(imm)&0xF0) ? 88 : (char)(imm) + ((char)(imm)>0x7 ? 72 : 24), \
- ((char)(imm)&0xF0) ? 89 : (char)(imm) + ((char)(imm)>0x6 ? 73 : 25), \
- ((char)(imm)&0xF0) ? 90 : (char)(imm) + ((char)(imm)>0x5 ? 74 : 26), \
- ((char)(imm)&0xF0) ? 91 : (char)(imm) + ((char)(imm)>0x4 ? 75 : 27), \
- ((char)(imm)&0xF0) ? 92 : (char)(imm) + ((char)(imm)>0x3 ? 76 : 28), \
- ((char)(imm)&0xF0) ? 93 : (char)(imm) + ((char)(imm)>0x2 ? 77 : 29), \
- ((char)(imm)&0xF0) ? 94 : (char)(imm) + ((char)(imm)>0x1 ? 78 : 30), \
- ((char)(imm)&0xF0) ? 95 : (char)(imm) + ((char)(imm)>0x0 ? 79 : 31), \
- ((char)(imm)&0xF0) ? 96 : (char)(imm) + ((char)(imm)>0xF ? 80 : 32), \
- ((char)(imm)&0xF0) ? 97 : (char)(imm) + ((char)(imm)>0xE ? 81 : 33), \
- ((char)(imm)&0xF0) ? 98 : (char)(imm) + ((char)(imm)>0xD ? 82 : 34), \
- ((char)(imm)&0xF0) ? 99 : (char)(imm) + ((char)(imm)>0xC ? 83 : 35), \
- ((char)(imm)&0xF0) ? 100 : (char)(imm) + ((char)(imm)>0xB ? 84 : 36), \
- ((char)(imm)&0xF0) ? 101 : (char)(imm) + ((char)(imm)>0xA ? 85 : 37), \
- ((char)(imm)&0xF0) ? 102 : (char)(imm) + ((char)(imm)>0x9 ? 86 : 38), \
- ((char)(imm)&0xF0) ? 103 : (char)(imm) + ((char)(imm)>0x8 ? 87 : 39), \
- ((char)(imm)&0xF0) ? 104 : (char)(imm) + ((char)(imm)>0x7 ? 88 : 40), \
- ((char)(imm)&0xF0) ? 105 : (char)(imm) + ((char)(imm)>0x6 ? 89 : 41), \
- ((char)(imm)&0xF0) ? 106 : (char)(imm) + ((char)(imm)>0x5 ? 90 : 42), \
- ((char)(imm)&0xF0) ? 107 : (char)(imm) + ((char)(imm)>0x4 ? 91 : 43), \
- ((char)(imm)&0xF0) ? 108 : (char)(imm) + ((char)(imm)>0x3 ? 92 : 44), \
- ((char)(imm)&0xF0) ? 109 : (char)(imm) + ((char)(imm)>0x2 ? 93 : 45), \
- ((char)(imm)&0xF0) ? 110 : (char)(imm) + ((char)(imm)>0x1 ? 94 : 46), \
- ((char)(imm)&0xF0) ? 111 : (char)(imm) + ((char)(imm)>0x0 ? 95 : 47), \
- ((char)(imm)&0xF0) ? 112 : (char)(imm) + ((char)(imm)>0xF ? 96 : 48), \
- ((char)(imm)&0xF0) ? 113 : (char)(imm) + ((char)(imm)>0xE ? 97 : 49), \
- ((char)(imm)&0xF0) ? 114 : (char)(imm) + ((char)(imm)>0xD ? 98 : 50), \
- ((char)(imm)&0xF0) ? 115 : (char)(imm) + ((char)(imm)>0xC ? 99 : 51), \
- ((char)(imm)&0xF0) ? 116 : (char)(imm) + ((char)(imm)>0xB ? 100 : 52), \
- ((char)(imm)&0xF0) ? 117 : (char)(imm) + ((char)(imm)>0xA ? 101 : 53), \
- ((char)(imm)&0xF0) ? 118 : (char)(imm) + ((char)(imm)>0x9 ? 102 : 54), \
- ((char)(imm)&0xF0) ? 119 : (char)(imm) + ((char)(imm)>0x8 ? 103 : 55), \
- ((char)(imm)&0xF0) ? 120 : (char)(imm) + ((char)(imm)>0x7 ? 104 : 56), \
- ((char)(imm)&0xF0) ? 121 : (char)(imm) + ((char)(imm)>0x6 ? 105 : 57), \
- ((char)(imm)&0xF0) ? 122 : (char)(imm) + ((char)(imm)>0x5 ? 106 : 58), \
- ((char)(imm)&0xF0) ? 123 : (char)(imm) + ((char)(imm)>0x4 ? 107 : 59), \
- ((char)(imm)&0xF0) ? 124 : (char)(imm) + ((char)(imm)>0x3 ? 108 : 60), \
- ((char)(imm)&0xF0) ? 125 : (char)(imm) + ((char)(imm)>0x2 ? 109 : 61), \
- ((char)(imm)&0xF0) ? 126 : (char)(imm) + ((char)(imm)>0x1 ? 110 : 62), \
- ((char)(imm)&0xF0) ? 127 : (char)(imm) + ((char)(imm)>0x0 ? 111 : 63)); })
+ (__v32hi)_mm512_setzero_si512());
+}
+
+#define _mm512_bsrli_epi128(a, imm) \
+ (__m512i)__builtin_ia32_psrldqi512_byteshift((__v8di)(__m512i)(a), (int)(imm))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_mov_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
@@ -1816,7 +1537,7 @@ _mm512_maskz_mov_epi16 (__mmask32 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectw_512 ((__mmask32) __U,
(__v32hi) __A,
- (__v32hi) _mm512_setzero_hi ());
+ (__v32hi) _mm512_setzero_si512 ());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1832,7 +1553,7 @@ _mm512_maskz_mov_epi8 (__mmask64 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectb_512 ((__mmask64) __U,
(__v64qi) __A,
- (__v64qi) _mm512_setzero_hi ());
+ (__v64qi) _mm512_setzero_si512 ());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1878,7 +1599,7 @@ _mm512_maskz_loadu_epi16 (__mmask32 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddquhi512_mask ((__v32hi *) __P,
(__v32hi)
- _mm512_setzero_hi (),
+ _mm512_setzero_si512 (),
(__mmask32) __U);
}
@@ -1895,7 +1616,7 @@ _mm512_maskz_loadu_epi8 (__mmask64 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddquqi512_mask ((__v64qi *) __P,
(__v64qi)
- _mm512_setzero_hi (),
+ _mm512_setzero_si512 (),
(__mmask64) __U);
}
static __inline__ void __DEFAULT_FN_ATTRS
@@ -1918,55 +1639,55 @@ static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_test_epi8_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpneq_epi8_mask (_mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_mask_test_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpneq_epi8_mask (__U, _mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_test_epi16_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpneq_epi16_mask (_mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_mask_test_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpneq_epi16_mask (__U, _mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_testn_epi8_mask (__m512i __A, __m512i __B)
{
- return _mm512_cmpeq_epi8_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_qi());
+ return _mm512_cmpeq_epi8_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_si512());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_mask_testn_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpeq_epi8_mask (__U, _mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_testn_epi16_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpeq_epi16_mask (_mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_mask_testn_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpeq_epi16_mask (__U, _mm512_and_epi32 (__A, __B),
- _mm512_setzero_qi());
+ _mm512_setzero_si512());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
@@ -1996,8 +1717,7 @@ _mm512_movm_epi16 (__mmask32 __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_broadcastb_epi8 (__m128i __A)
{
- return (__m512i)__builtin_shufflevector((__v16qi) __A,
- (__v16qi)_mm_undefined_si128(),
+ return (__m512i)__builtin_shufflevector((__v16qi) __A, (__v16qi) __A,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -2039,8 +1759,7 @@ _mm512_maskz_set1_epi16 (__mmask32 __M, short __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_broadcastw_epi16 (__m128i __A)
{
- return (__m512i)__builtin_shufflevector((__v8hi) __A,
- (__v8hi)_mm_undefined_si128(),
+ return (__m512i)__builtin_shufflevector((__v8hi) __A, (__v8hi) __A,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@@ -2064,67 +1783,54 @@ _mm512_maskz_broadcastw_epi16 (__mmask32 __M, __m128i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_permutexvar_epi16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_permvarhi512_mask ((__v32hi) __B,
- (__v32hi) __A,
- (__v32hi) _mm512_undefined_epi32 (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_permvarhi512((__v32hi)__B, (__v32hi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_permutexvar_epi16 (__mmask32 __M, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_permvarhi512_mask ((__v32hi) __B,
- (__v32hi) __A,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __M);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_permutexvar_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_permutexvar_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_permvarhi512_mask ((__v32hi) __B,
- (__v32hi) __A,
- (__v32hi) __W,
- (__mmask32) __M);
-}
-
-#define _mm512_alignr_epi8(A, B, N) __extension__ ({\
- (__m512i)__builtin_ia32_palignr512_mask((__v64qi)(__m512i)(A), \
- (__v64qi)(__m512i)(B), (int)(N), \
- (__v64qi)_mm512_undefined_pd(), \
- (__mmask64)-1); })
-
-#define _mm512_mask_alignr_epi8(W, U, A, B, N) __extension__({\
- (__m512i)__builtin_ia32_palignr512_mask((__v64qi)(__m512i)(A), \
- (__v64qi)(__m512i)(B), (int)(N), \
- (__v64qi)(__m512i)(W), \
- (__mmask64)(U)); })
-
-#define _mm512_maskz_alignr_epi8(U, A, B, N) __extension__({\
- (__m512i)__builtin_ia32_palignr512_mask((__v64qi)(__m512i)(A), \
- (__v64qi)(__m512i)(B), (int)(N), \
- (__v64qi)_mm512_setzero_si512(), \
- (__mmask64)(U)); })
-
-#define _mm512_dbsad_epu8(A, B, imm) __extension__ ({\
- (__m512i)__builtin_ia32_dbpsadbw512_mask((__v64qi)(__m512i)(A), \
- (__v64qi)(__m512i)(B), (int)(imm), \
- (__v32hi)_mm512_undefined_epi32(), \
- (__mmask32)-1); })
-
-#define _mm512_mask_dbsad_epu8(W, U, A, B, imm) ({\
- (__m512i)__builtin_ia32_dbpsadbw512_mask((__v64qi)(__m512i)(A), \
- (__v64qi)(__m512i)(B), (int)(imm), \
- (__v32hi)(__m512i)(W), \
- (__mmask32)(U)); })
-
-#define _mm512_maskz_dbsad_epu8(U, A, B, imm) ({\
- (__m512i)__builtin_ia32_dbpsadbw512_mask((__v64qi)(__m512i)(A), \
- (__v64qi)(__m512i)(B), (int)(imm), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)(U)); })
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
+ (__v32hi)_mm512_permutexvar_epi16(__A, __B),
+ (__v32hi)__W);
+}
+
+#define _mm512_alignr_epi8(A, B, N) \
+ (__m512i)__builtin_ia32_palignr512((__v64qi)(__m512i)(A), \
+ (__v64qi)(__m512i)(B), (int)(N))
+
+#define _mm512_mask_alignr_epi8(W, U, A, B, N) \
+ (__m512i)__builtin_ia32_selectb_512((__mmask64)(U), \
+ (__v64qi)_mm512_alignr_epi8((A), (B), (int)(N)), \
+ (__v64qi)(__m512i)(W))
+
+#define _mm512_maskz_alignr_epi8(U, A, B, N) \
+ (__m512i)__builtin_ia32_selectb_512((__mmask64)(U), \
+ (__v64qi)_mm512_alignr_epi8((A), (B), (int)(N)), \
+ (__v64qi)(__m512i)_mm512_setzero_si512())
+
+#define _mm512_dbsad_epu8(A, B, imm) \
+ (__m512i)__builtin_ia32_dbpsadbw512((__v64qi)(__m512i)(A), \
+ (__v64qi)(__m512i)(B), (int)(imm))
+
+#define _mm512_mask_dbsad_epu8(W, U, A, B, imm) \
+ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
+ (__v32hi)_mm512_dbsad_epu8((A), (B), (imm)), \
+ (__v32hi)(__m512i)(W))
+
+#define _mm512_maskz_dbsad_epu8(U, A, B, imm) \
+ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
+ (__v32hi)_mm512_dbsad_epu8((A), (B), (imm)), \
+ (__v32hi)_mm512_setzero_si512())
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_sad_epu8 (__m512i __A, __m512i __B)
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
index ec7e0cd443b4..e63902743c06 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
@@ -29,7 +29,7 @@
#define __AVX512CDINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512cd")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512cd"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_conflict_epi64 (__m512i __A)
@@ -82,49 +82,45 @@ _mm512_maskz_conflict_epi32 (__mmask16 __U, __m512i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_lzcnt_epi32 (__m512i __A)
{
- return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
- (__v16si) _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i) __builtin_ia32_vplzcntd_512 ((__v16si) __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_lzcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_lzcnt_epi32(__A),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_lzcnt_epi32 (__mmask16 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
- (__v16si) _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_lzcnt_epi32(__A),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_lzcnt_epi64 (__m512i __A)
{
- return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
- (__v8di) _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i) __builtin_ia32_vplzcntq_512 ((__v8di) __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_lzcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_lzcnt_epi64(__A),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_lzcnt_epi64 (__mmask8 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
- (__v8di) _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_lzcnt_epi64(__A),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
index 2c431d9740cd..8a00b3afa9d5 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
@@ -29,7 +29,7 @@
#define __AVX512DQINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
@@ -226,20 +226,20 @@ _mm512_maskz_cvtpd_epi64 (__mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundpd_epi64(A, R) __extension__ ({ \
+#define _mm512_cvt_roundpd_epi64(A, R) \
(__m512i)__builtin_ia32_cvtpd2qq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundpd_epi64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundpd_epi64(W, U, A, R) \
(__m512i)__builtin_ia32_cvtpd2qq512_mask((__v8df)(__m512d)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundpd_epi64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundpd_epi64(U, A, R) \
(__m512i)__builtin_ia32_cvtpd2qq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvtpd_epu64 (__m512d __A) {
@@ -265,20 +265,20 @@ _mm512_maskz_cvtpd_epu64 (__mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundpd_epu64(A, R) __extension__ ({ \
+#define _mm512_cvt_roundpd_epu64(A, R) \
(__m512i)__builtin_ia32_cvtpd2uqq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundpd_epu64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundpd_epu64(W, U, A, R) \
(__m512i)__builtin_ia32_cvtpd2uqq512_mask((__v8df)(__m512d)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundpd_epu64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundpd_epu64(U, A, R) \
(__m512i)__builtin_ia32_cvtpd2uqq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvtps_epi64 (__m256 __A) {
@@ -304,20 +304,20 @@ _mm512_maskz_cvtps_epi64 (__mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundps_epi64(A, R) __extension__ ({ \
+#define _mm512_cvt_roundps_epi64(A, R) \
(__m512i)__builtin_ia32_cvtps2qq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundps_epi64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundps_epi64(W, U, A, R) \
(__m512i)__builtin_ia32_cvtps2qq512_mask((__v8sf)(__m256)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundps_epi64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundps_epi64(U, A, R) \
(__m512i)__builtin_ia32_cvtps2qq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvtps_epu64 (__m256 __A) {
@@ -343,60 +343,55 @@ _mm512_maskz_cvtps_epu64 (__mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundps_epu64(A, R) __extension__ ({ \
+#define _mm512_cvt_roundps_epu64(A, R) \
(__m512i)__builtin_ia32_cvtps2uqq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundps_epu64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundps_epu64(W, U, A, R) \
(__m512i)__builtin_ia32_cvtps2uqq512_mask((__v8sf)(__m256)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundps_epu64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundps_epu64(U, A, R) \
(__m512i)__builtin_ia32_cvtps2uqq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_cvtepi64_pd (__m512i __A) {
- return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A,
- (__v8df) _mm512_setzero_pd(),
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_convertvector((__v8di)__A, __v8df);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_cvtepi64_pd (__m512d __W, __mmask8 __U, __m512i __A) {
- return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_cvtepi64_pd(__A),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_cvtepi64_pd (__mmask8 __U, __m512i __A) {
- return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A,
- (__v8df) _mm512_setzero_pd(),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_cvtepi64_pd(__A),
+ (__v8df)_mm512_setzero_pd());
}
-#define _mm512_cvt_roundepi64_pd(A, R) __extension__ ({ \
+#define _mm512_cvt_roundepi64_pd(A, R) \
(__m512d)__builtin_ia32_cvtqq2pd512_mask((__v8di)(__m512i)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundepi64_pd(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundepi64_pd(W, U, A, R) \
(__m512d)__builtin_ia32_cvtqq2pd512_mask((__v8di)(__m512i)(A), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundepi64_pd(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundepi64_pd(U, A, R) \
(__m512d)__builtin_ia32_cvtqq2pd512_mask((__v8di)(__m512i)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm512_cvtepi64_ps (__m512i __A) {
@@ -422,20 +417,20 @@ _mm512_maskz_cvtepi64_ps (__mmask8 __U, __m512i __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundepi64_ps(A, R) __extension__ ({ \
+#define _mm512_cvt_roundepi64_ps(A, R) \
(__m256)__builtin_ia32_cvtqq2ps512_mask((__v8di)(__m512i)(A), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundepi64_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundepi64_ps(W, U, A, R) \
(__m256)__builtin_ia32_cvtqq2ps512_mask((__v8di)(__m512i)(A), \
(__v8sf)(__m256)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_cvt_roundepi64_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundepi64_ps(U, A, R) \
(__m256)__builtin_ia32_cvtqq2ps512_mask((__v8di)(__m512i)(A), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -462,20 +457,20 @@ _mm512_maskz_cvttpd_epi64 (__mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvtt_roundpd_epi64(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundpd_epi64(A, R) \
(__m512i)__builtin_ia32_cvttpd2qq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvtt_roundpd_epi64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundpd_epi64(W, U, A, R) \
(__m512i)__builtin_ia32_cvttpd2qq512_mask((__v8df)(__m512d)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundpd_epi64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundpd_epi64(U, A, R) \
(__m512i)__builtin_ia32_cvttpd2qq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvttpd_epu64 (__m512d __A) {
@@ -501,20 +496,20 @@ _mm512_maskz_cvttpd_epu64 (__mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvtt_roundpd_epu64(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundpd_epu64(A, R) \
(__m512i)__builtin_ia32_cvttpd2uqq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvtt_roundpd_epu64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundpd_epu64(W, U, A, R) \
(__m512i)__builtin_ia32_cvttpd2uqq512_mask((__v8df)(__m512d)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundpd_epu64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundpd_epu64(U, A, R) \
(__m512i)__builtin_ia32_cvttpd2uqq512_mask((__v8df)(__m512d)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvttps_epi64 (__m256 __A) {
@@ -540,20 +535,20 @@ _mm512_maskz_cvttps_epi64 (__mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvtt_roundps_epi64(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundps_epi64(A, R) \
(__m512i)__builtin_ia32_cvttps2qq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvtt_roundps_epi64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundps_epi64(W, U, A, R) \
(__m512i)__builtin_ia32_cvttps2qq512_mask((__v8sf)(__m256)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundps_epi64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundps_epi64(U, A, R) \
(__m512i)__builtin_ia32_cvttps2qq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvttps_epu64 (__m256 __A) {
@@ -579,60 +574,55 @@ _mm512_maskz_cvttps_epu64 (__mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvtt_roundps_epu64(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundps_epu64(A, R) \
(__m512i)__builtin_ia32_cvttps2uqq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvtt_roundps_epu64(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundps_epu64(W, U, A, R) \
(__m512i)__builtin_ia32_cvttps2uqq512_mask((__v8sf)(__m256)(A), \
(__v8di)(__m512i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundps_epu64(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundps_epu64(U, A, R) \
(__m512i)__builtin_ia32_cvttps2uqq512_mask((__v8sf)(__m256)(A), \
(__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_cvtepu64_pd (__m512i __A) {
- return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A,
- (__v8df) _mm512_setzero_pd(),
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_convertvector((__v8du)__A, __v8df);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_cvtepu64_pd (__m512d __W, __mmask8 __U, __m512i __A) {
- return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_cvtepu64_pd(__A),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_cvtepu64_pd (__mmask8 __U, __m512i __A) {
- return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A,
- (__v8df) _mm512_setzero_pd(),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_cvtepu64_pd(__A),
+ (__v8df)_mm512_setzero_pd());
}
-#define _mm512_cvt_roundepu64_pd(A, R) __extension__ ({ \
+#define _mm512_cvt_roundepu64_pd(A, R) \
(__m512d)__builtin_ia32_cvtuqq2pd512_mask((__v8di)(__m512i)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundepu64_pd(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundepu64_pd(W, U, A, R) \
(__m512d)__builtin_ia32_cvtuqq2pd512_mask((__v8di)(__m512i)(A), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundepu64_pd(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundepu64_pd(U, A, R) \
(__m512d)__builtin_ia32_cvtuqq2pd512_mask((__v8di)(__m512i)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline__ __m256 __DEFAULT_FN_ATTRS
@@ -659,292 +649,292 @@ _mm512_maskz_cvtepu64_ps (__mmask8 __U, __m512i __A) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundepu64_ps(A, R) __extension__ ({ \
+#define _mm512_cvt_roundepu64_ps(A, R) \
(__m256)__builtin_ia32_cvtuqq2ps512_mask((__v8di)(__m512i)(A), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundepu64_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundepu64_ps(W, U, A, R) \
(__m256)__builtin_ia32_cvtuqq2ps512_mask((__v8di)(__m512i)(A), \
(__v8sf)(__m256)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_cvt_roundepu64_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundepu64_ps(U, A, R) \
(__m256)__builtin_ia32_cvtuqq2ps512_mask((__v8di)(__m512i)(A), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_range_pd(A, B, C) __extension__ ({ \
+#define _mm512_range_pd(A, B, C) \
(__m512d)__builtin_ia32_rangepd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_range_pd(W, U, A, B, C) __extension__ ({ \
+#define _mm512_mask_range_pd(W, U, A, B, C) \
(__m512d)__builtin_ia32_rangepd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(C), \
(__v8df)(__m512d)(W), (__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_range_pd(U, A, B, C) __extension__ ({ \
+#define _mm512_maskz_range_pd(U, A, B, C) \
(__m512d)__builtin_ia32_rangepd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_range_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_range_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_rangepd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_range_round_pd(W, U, A, B, C, R) __extension__ ({ \
+#define _mm512_mask_range_round_pd(W, U, A, B, C, R) \
(__m512d)__builtin_ia32_rangepd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(C), \
(__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_range_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_range_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_rangepd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_range_ps(A, B, C) __extension__ ({ \
+#define _mm512_range_ps(A, B, C) \
(__m512)__builtin_ia32_rangeps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_setzero_ps(), \
(__mmask16)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_range_ps(W, U, A, B, C) __extension__ ({ \
+#define _mm512_mask_range_ps(W, U, A, B, C) \
(__m512)__builtin_ia32_rangeps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(C), \
(__v16sf)(__m512)(W), (__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_range_ps(U, A, B, C) __extension__ ({ \
+#define _mm512_maskz_range_ps(U, A, B, C) \
(__m512)__builtin_ia32_rangeps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_setzero_ps(), \
(__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_range_round_ps(A, B, C, R) __extension__ ({ \
+#define _mm512_range_round_ps(A, B, C, R) \
(__m512)__builtin_ia32_rangeps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_range_round_ps(W, U, A, B, C, R) __extension__ ({ \
+#define _mm512_mask_range_round_ps(W, U, A, B, C, R) \
(__m512)__builtin_ia32_rangeps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(C), \
(__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_range_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_range_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_rangeps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm_range_round_ss(A, B, C, R) __extension__ ({ \
+#define _mm_range_round_ss(A, B, C, R) \
(__m128)__builtin_ia32_rangess128_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8) -1, (int)(C),\
- (int)(R)); })
+ (int)(R))
#define _mm_range_ss(A ,B , C) _mm_range_round_ss(A, B, C ,_MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_range_round_ss(W, U, A, B, C, R) __extension__ ({ \
+#define _mm_mask_range_round_ss(W, U, A, B, C, R) \
(__m128)__builtin_ia32_rangess128_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W),\
(__mmask8)(U), (int)(C),\
- (int)(R)); })
+ (int)(R))
#define _mm_mask_range_ss(W , U, A, B, C) _mm_mask_range_round_ss(W, U, A, B, C , _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_range_round_ss(U, A, B, C, R) __extension__ ({ \
+#define _mm_maskz_range_round_ss(U, A, B, C, R) \
(__m128)__builtin_ia32_rangess128_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), (int)(C),\
- (int)(R)); })
+ (int)(R))
#define _mm_maskz_range_ss(U, A ,B , C) _mm_maskz_range_round_ss(U, A, B, C ,_MM_FROUND_CUR_DIRECTION)
-#define _mm_range_round_sd(A, B, C, R) __extension__ ({ \
+#define _mm_range_round_sd(A, B, C, R) \
(__m128d)__builtin_ia32_rangesd128_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8) -1, (int)(C),\
- (int)(R)); })
+ (int)(R))
#define _mm_range_sd(A ,B , C) _mm_range_round_sd(A, B, C ,_MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_range_round_sd(W, U, A, B, C, R) __extension__ ({ \
+#define _mm_mask_range_round_sd(W, U, A, B, C, R) \
(__m128d)__builtin_ia32_rangesd128_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W),\
(__mmask8)(U), (int)(C),\
- (int)(R)); })
+ (int)(R))
#define _mm_mask_range_sd(W, U, A, B, C) _mm_mask_range_round_sd(W, U, A, B, C ,_MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_range_round_sd(U, A, B, C, R) __extension__ ({ \
+#define _mm_maskz_range_round_sd(U, A, B, C, R) \
(__m128d)__builtin_ia32_rangesd128_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(U), (int)(C),\
- (int)(R)); })
+ (int)(R))
#define _mm_maskz_range_sd(U, A, B, C) _mm_maskz_range_round_sd(U, A, B, C ,_MM_FROUND_CUR_DIRECTION)
-#define _mm512_reduce_pd(A, B) __extension__ ({ \
+#define _mm512_reduce_pd(A, B) \
(__m512d)__builtin_ia32_reducepd512_mask((__v8df)(__m512d)(A), (int)(B), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_reduce_pd(W, U, A, B) __extension__ ({ \
+#define _mm512_mask_reduce_pd(W, U, A, B) \
(__m512d)__builtin_ia32_reducepd512_mask((__v8df)(__m512d)(A), (int)(B), \
(__v8df)(__m512d)(W), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_reduce_pd(U, A, B) __extension__ ({ \
+#define _mm512_maskz_reduce_pd(U, A, B) \
(__m512d)__builtin_ia32_reducepd512_mask((__v8df)(__m512d)(A), (int)(B), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_reduce_ps(A, B) __extension__ ({ \
+#define _mm512_reduce_ps(A, B) \
(__m512)__builtin_ia32_reduceps512_mask((__v16sf)(__m512)(A), (int)(B), \
(__v16sf)_mm512_setzero_ps(), \
(__mmask16)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_reduce_ps(W, U, A, B) __extension__ ({ \
+#define _mm512_mask_reduce_ps(W, U, A, B) \
(__m512)__builtin_ia32_reduceps512_mask((__v16sf)(__m512)(A), (int)(B), \
(__v16sf)(__m512)(W), \
(__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_reduce_ps(U, A, B) __extension__ ({ \
+#define _mm512_maskz_reduce_ps(U, A, B) \
(__m512)__builtin_ia32_reduceps512_mask((__v16sf)(__m512)(A), (int)(B), \
(__v16sf)_mm512_setzero_ps(), \
(__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_reduce_round_pd(A, B, R) __extension__ ({\
+#define _mm512_reduce_round_pd(A, B, R) \
(__m512d)__builtin_ia32_reducepd512_mask((__v8df)(__m512d)(A), (int)(B), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_reduce_round_pd(W, U, A, B, R) __extension__ ({\
+#define _mm512_mask_reduce_round_pd(W, U, A, B, R) \
(__m512d)__builtin_ia32_reducepd512_mask((__v8df)(__m512d)(A), (int)(B), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_reduce_round_pd(U, A, B, R) __extension__ ({\
+#define _mm512_maskz_reduce_round_pd(U, A, B, R) \
(__m512d)__builtin_ia32_reducepd512_mask((__v8df)(__m512d)(A), (int)(B), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_reduce_round_ps(A, B, R) __extension__ ({\
+#define _mm512_reduce_round_ps(A, B, R) \
(__m512)__builtin_ia32_reduceps512_mask((__v16sf)(__m512)(A), (int)(B), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_reduce_round_ps(W, U, A, B, R) __extension__ ({\
+#define _mm512_mask_reduce_round_ps(W, U, A, B, R) \
(__m512)__builtin_ia32_reduceps512_mask((__v16sf)(__m512)(A), (int)(B), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_reduce_round_ps(U, A, B, R) __extension__ ({\
+#define _mm512_maskz_reduce_round_ps(U, A, B, R) \
(__m512)__builtin_ia32_reduceps512_mask((__v16sf)(__m512)(A), (int)(B), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm_reduce_ss(A, B, C) __extension__ ({ \
+#define _mm_reduce_ss(A, B, C) \
(__m128)__builtin_ia32_reducess_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), (__mmask8)-1, \
- (int)(C), _MM_FROUND_CUR_DIRECTION); })
+ (int)(C), _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_reduce_ss(W, U, A, B, C) __extension__ ({ \
+#define _mm_mask_reduce_ss(W, U, A, B, C) \
(__m128)__builtin_ia32_reducess_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(C), _MM_FROUND_CUR_DIRECTION); })
+ (int)(C), _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_reduce_ss(U, A, B, C) __extension__ ({ \
+#define _mm_maskz_reduce_ss(U, A, B, C) \
(__m128)__builtin_ia32_reducess_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), (int)(C), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_reduce_round_ss(A, B, C, R) __extension__ ({ \
+#define _mm_reduce_round_ss(A, B, C, R) \
(__m128)__builtin_ia32_reducess_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), (__mmask8)-1, \
- (int)(C), (int)(R)); })
+ (int)(C), (int)(R))
-#define _mm_mask_reduce_round_ss(W, U, A, B, C, R) __extension__ ({ \
+#define _mm_mask_reduce_round_ss(W, U, A, B, C, R) \
(__m128)__builtin_ia32_reducess_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(C), (int)(R)); })
+ (int)(C), (int)(R))
-#define _mm_maskz_reduce_round_ss(U, A, B, C, R) __extension__ ({ \
+#define _mm_maskz_reduce_round_ss(U, A, B, C, R) \
(__m128)__builtin_ia32_reducess_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(C), (int)(R)); })
+ (__mmask8)(U), (int)(C), (int)(R))
-#define _mm_reduce_sd(A, B, C) __extension__ ({ \
+#define _mm_reduce_sd(A, B, C) \
(__m128d)__builtin_ia32_reducesd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)-1, (int)(C), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_reduce_sd(W, U, A, B, C) __extension__ ({ \
+#define _mm_mask_reduce_sd(W, U, A, B, C) \
(__m128d)__builtin_ia32_reducesd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), (__mmask8)(U), \
- (int)(C), _MM_FROUND_CUR_DIRECTION); })
+ (int)(C), _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_reduce_sd(U, A, B, C) __extension__ ({ \
+#define _mm_maskz_reduce_sd(U, A, B, C) \
(__m128d)__builtin_ia32_reducesd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(U), (int)(C), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_reduce_round_sd(A, B, C, R) __extension__ ({ \
+#define _mm_reduce_round_sd(A, B, C, R) \
(__m128d)__builtin_ia32_reducesd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(C), (int)(R)); })
+ (__mmask8)-1, (int)(C), (int)(R))
-#define _mm_mask_reduce_round_sd(W, U, A, B, C, R) __extension__ ({ \
+#define _mm_mask_reduce_round_sd(W, U, A, B, C, R) \
(__m128d)__builtin_ia32_reducesd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), (__mmask8)(U), \
- (int)(C), (int)(R)); })
+ (int)(C), (int)(R))
-#define _mm_maskz_reduce_round_sd(U, A, B, C, R) __extension__ ({ \
+#define _mm_maskz_reduce_round_sd(U, A, B, C, R) \
(__m128d)__builtin_ia32_reducesd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(C), (int)(R)); })
-
+ (__mmask8)(U), (int)(C), (int)(R))
+
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_movepi32_mask (__m512i __A)
{
@@ -973,8 +963,7 @@ _mm512_movepi64_mask (__m512i __A)
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_broadcast_f32x2 (__m128 __A)
{
- return (__m512)__builtin_shufflevector((__v4sf)__A,
- (__v4sf)_mm_undefined_ps(),
+ return (__m512)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A,
0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1);
}
@@ -1006,7 +995,7 @@ _mm512_broadcast_f32x8(__m256 __A)
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_mask_broadcast_f32x8(__m512 __O, __mmask16 __M, __m256 __A)
{
- return (__m512)__builtin_ia32_selectps_512((__mmask8)__M,
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
(__v16sf)_mm512_broadcast_f32x8(__A),
(__v16sf)__O);
}
@@ -1014,7 +1003,7 @@ _mm512_mask_broadcast_f32x8(__m512 __O, __mmask16 __M, __m256 __A)
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_broadcast_f32x8(__mmask16 __M, __m256 __A)
{
- return (__m512)__builtin_ia32_selectps_512((__mmask8)__M,
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
(__v16sf)_mm512_broadcast_f32x8(__A),
(__v16sf)_mm512_setzero_ps());
}
@@ -1045,8 +1034,7 @@ _mm512_maskz_broadcast_f64x2(__mmask8 __M, __m128d __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_broadcast_i32x2 (__m128i __A)
{
- return (__m512i)__builtin_shufflevector((__v4si)__A,
- (__v4si)_mm_undefined_si128(),
+ return (__m512i)__builtin_shufflevector((__v4si)__A, (__v4si)__A,
0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1);
}
@@ -1078,7 +1066,7 @@ _mm512_broadcast_i32x8(__m256i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_broadcast_i32x8(__m512i __O, __mmask16 __M, __m256i __A)
{
- return (__m512i)__builtin_ia32_selectd_512((__mmask8)__M,
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
(__v16si)_mm512_broadcast_i32x8(__A),
(__v16si)__O);
}
@@ -1086,7 +1074,7 @@ _mm512_mask_broadcast_i32x8(__m512i __O, __mmask16 __M, __m256i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_broadcast_i32x8(__mmask16 __M, __m256i __A)
{
- return (__m512i)__builtin_ia32_selectd_512((__mmask8)__M,
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
(__v16si)_mm512_broadcast_i32x8(__A),
(__v16si)_mm512_setzero_si512());
}
@@ -1114,217 +1102,159 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A)
(__v8di)_mm512_setzero_si512());
}
-#define _mm512_extractf32x8_ps(A, imm) __extension__ ({ \
- (__m256)__builtin_shufflevector((__v16sf)(__m512)(A), \
- (__v16sf)_mm512_undefined_ps(), \
- ((imm) & 1) ? 8 : 0, \
- ((imm) & 1) ? 9 : 1, \
- ((imm) & 1) ? 10 : 2, \
- ((imm) & 1) ? 11 : 3, \
- ((imm) & 1) ? 12 : 4, \
- ((imm) & 1) ? 13 : 5, \
- ((imm) & 1) ? 14 : 6, \
- ((imm) & 1) ? 15 : 7); })
-
-#define _mm512_mask_extractf32x8_ps(W, U, A, imm) __extension__ ({ \
- (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
- (__v8sf)_mm512_extractf32x8_ps((A), (imm)), \
- (__v8sf)(W)); })
-
-#define _mm512_maskz_extractf32x8_ps(U, A, imm) __extension__ ({ \
- (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
- (__v8sf)_mm512_extractf32x8_ps((A), (imm)), \
- (__v8sf)_mm256_setzero_ps()); })
-
-#define _mm512_extractf64x2_pd(A, imm) __extension__ ({ \
- (__m128d)__builtin_shufflevector((__v8df)(__m512d)(A), \
- (__v8df)_mm512_undefined_pd(), \
- 0 + ((imm) & 0x3) * 2, \
- 1 + ((imm) & 0x3) * 2); })
-
-#define _mm512_mask_extractf64x2_pd(W, U, A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
- (__v2df)_mm512_extractf64x2_pd((A), (imm)), \
- (__v2df)(W)); })
-
-#define _mm512_maskz_extractf64x2_pd(U, A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
- (__v2df)_mm512_extractf64x2_pd((A), (imm)), \
- (__v2df)_mm_setzero_pd()); })
-
-#define _mm512_extracti32x8_epi32(A, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v16si)(__m512i)(A), \
- (__v16si)_mm512_undefined_epi32(), \
- ((imm) & 1) ? 8 : 0, \
- ((imm) & 1) ? 9 : 1, \
- ((imm) & 1) ? 10 : 2, \
- ((imm) & 1) ? 11 : 3, \
- ((imm) & 1) ? 12 : 4, \
- ((imm) & 1) ? 13 : 5, \
- ((imm) & 1) ? 14 : 6, \
- ((imm) & 1) ? 15 : 7); })
-
-#define _mm512_mask_extracti32x8_epi32(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
- (__v8si)_mm512_extracti32x8_epi32((A), (imm)), \
- (__v8si)(W)); })
-
-#define _mm512_maskz_extracti32x8_epi32(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
- (__v8si)_mm512_extracti32x8_epi32((A), (imm)), \
- (__v8si)_mm256_setzero_si256()); })
-
-#define _mm512_extracti64x2_epi64(A, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v8di)(__m512i)(A), \
- (__v8di)_mm512_undefined_epi32(), \
- 0 + ((imm) & 0x3) * 2, \
- 1 + ((imm) & 0x3) * 2); })
-
-#define _mm512_mask_extracti64x2_epi64(W, U, A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_selectq_128((__mmask8)(U), \
- (__v2di)_mm512_extracti64x2_epi64((A), (imm)), \
- (__v2di)(W)); })
-
-#define _mm512_maskz_extracti64x2_epi64(U, A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_selectq_128((__mmask8)(U), \
- (__v2di)_mm512_extracti64x2_epi64((A), (imm)), \
- (__v2di)_mm_setzero_di()); })
-
-#define _mm512_insertf32x8(A, B, imm) __extension__ ({ \
- (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \
- (__v16sf)_mm512_castps256_ps512((__m256)(B)),\
- ((imm) & 0x1) ? 0 : 16, \
- ((imm) & 0x1) ? 1 : 17, \
- ((imm) & 0x1) ? 2 : 18, \
- ((imm) & 0x1) ? 3 : 19, \
- ((imm) & 0x1) ? 4 : 20, \
- ((imm) & 0x1) ? 5 : 21, \
- ((imm) & 0x1) ? 6 : 22, \
- ((imm) & 0x1) ? 7 : 23, \
- ((imm) & 0x1) ? 16 : 8, \
- ((imm) & 0x1) ? 17 : 9, \
- ((imm) & 0x1) ? 18 : 10, \
- ((imm) & 0x1) ? 19 : 11, \
- ((imm) & 0x1) ? 20 : 12, \
- ((imm) & 0x1) ? 21 : 13, \
- ((imm) & 0x1) ? 22 : 14, \
- ((imm) & 0x1) ? 23 : 15); })
-
-#define _mm512_mask_insertf32x8(W, U, A, B, imm) __extension__ ({ \
+#define _mm512_extractf32x8_ps(A, imm) \
+ (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
+ (__v8sf)_mm256_undefined_ps(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extractf32x8_ps(W, U, A, imm) \
+ (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
+ (__v8sf)(__m256)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extractf32x8_ps(U, A, imm) \
+ (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
+ (__v8sf)_mm256_setzero_ps(), \
+ (__mmask8)(U))
+
+#define _mm512_extractf64x2_pd(A, imm) \
+ (__m128d)__builtin_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \
+ (int)(imm), \
+ (__v2df)_mm_undefined_pd(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extractf64x2_pd(W, U, A, imm) \
+ (__m128d)__builtin_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \
+ (int)(imm), \
+ (__v2df)(__m128d)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extractf64x2_pd(U, A, imm) \
+ (__m128d)__builtin_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \
+ (int)(imm), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)(U))
+
+#define _mm512_extracti32x8_epi32(A, imm) \
+ (__m256i)__builtin_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \
+ (__v8si)_mm256_undefined_si256(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extracti32x8_epi32(W, U, A, imm) \
+ (__m256i)__builtin_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \
+ (__v8si)(__m256i)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extracti32x8_epi32(U, A, imm) \
+ (__m256i)__builtin_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \
+ (__v8si)_mm256_setzero_si256(), \
+ (__mmask8)(U))
+
+#define _mm512_extracti64x2_epi64(A, imm) \
+ (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \
+ (int)(imm), \
+ (__v2di)_mm_undefined_si128(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extracti64x2_epi64(W, U, A, imm) \
+ (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \
+ (int)(imm), \
+ (__v2di)(__m128i)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extracti64x2_epi64(U, A, imm) \
+ (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \
+ (int)(imm), \
+ (__v2di)_mm_setzero_si128(), \
+ (__mmask8)(U))
+
+#define _mm512_insertf32x8(A, B, imm) \
+ (__m512)__builtin_ia32_insertf32x8((__v16sf)(__m512)(A), \
+ (__v8sf)(__m256)(B), (int)(imm))
+
+#define _mm512_mask_insertf32x8(W, U, A, B, imm) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_insertf32x8((A), (B), (imm)), \
- (__v16sf)(W)); })
+ (__v16sf)(__m512)(W))
-#define _mm512_maskz_insertf32x8(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_insertf32x8(U, A, B, imm) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_insertf32x8((A), (B), (imm)), \
- (__v16sf)_mm512_setzero_ps()); })
-
-#define _mm512_insertf64x2(A, B, imm) __extension__ ({ \
- (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \
- (__v8df)_mm512_castpd128_pd512((__m128d)(B)),\
- (((imm) & 0x3) == 0) ? 8 : 0, \
- (((imm) & 0x3) == 0) ? 9 : 1, \
- (((imm) & 0x3) == 1) ? 8 : 2, \
- (((imm) & 0x3) == 1) ? 9 : 3, \
- (((imm) & 0x3) == 2) ? 8 : 4, \
- (((imm) & 0x3) == 2) ? 9 : 5, \
- (((imm) & 0x3) == 3) ? 8 : 6, \
- (((imm) & 0x3) == 3) ? 9 : 7); })
-
-#define _mm512_mask_insertf64x2(W, U, A, B, imm) __extension__ ({ \
+ (__v16sf)_mm512_setzero_ps())
+
+#define _mm512_insertf64x2(A, B, imm) \
+ (__m512d)__builtin_ia32_insertf64x2_512((__v8df)(__m512d)(A), \
+ (__v2df)(__m128d)(B), (int)(imm))
+
+#define _mm512_mask_insertf64x2(W, U, A, B, imm) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_insertf64x2((A), (B), (imm)), \
- (__v8df)(W)); })
+ (__v8df)(__m512d)(W))
-#define _mm512_maskz_insertf64x2(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_insertf64x2(U, A, B, imm) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_insertf64x2((A), (B), (imm)), \
- (__v8df)_mm512_setzero_pd()); })
-
-#define _mm512_inserti32x8(A, B, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v16si)(__m512i)(A), \
- (__v16si)_mm512_castsi256_si512((__m256i)(B)),\
- ((imm) & 0x1) ? 0 : 16, \
- ((imm) & 0x1) ? 1 : 17, \
- ((imm) & 0x1) ? 2 : 18, \
- ((imm) & 0x1) ? 3 : 19, \
- ((imm) & 0x1) ? 4 : 20, \
- ((imm) & 0x1) ? 5 : 21, \
- ((imm) & 0x1) ? 6 : 22, \
- ((imm) & 0x1) ? 7 : 23, \
- ((imm) & 0x1) ? 16 : 8, \
- ((imm) & 0x1) ? 17 : 9, \
- ((imm) & 0x1) ? 18 : 10, \
- ((imm) & 0x1) ? 19 : 11, \
- ((imm) & 0x1) ? 20 : 12, \
- ((imm) & 0x1) ? 21 : 13, \
- ((imm) & 0x1) ? 22 : 14, \
- ((imm) & 0x1) ? 23 : 15); })
-
-#define _mm512_mask_inserti32x8(W, U, A, B, imm) __extension__ ({ \
+ (__v8df)_mm512_setzero_pd())
+
+#define _mm512_inserti32x8(A, B, imm) \
+ (__m512i)__builtin_ia32_inserti32x8((__v16si)(__m512i)(A), \
+ (__v8si)(__m256i)(B), (int)(imm))
+
+#define _mm512_mask_inserti32x8(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_inserti32x8((A), (B), (imm)), \
- (__v16si)(W)); })
+ (__v16si)(__m512i)(W))
-#define _mm512_maskz_inserti32x8(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_inserti32x8(U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_inserti32x8((A), (B), (imm)), \
- (__v16si)_mm512_setzero_si512()); })
-
-#define _mm512_inserti64x2(A, B, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \
- (__v8di)_mm512_castsi128_si512((__m128i)(B)),\
- (((imm) & 0x3) == 0) ? 8 : 0, \
- (((imm) & 0x3) == 0) ? 9 : 1, \
- (((imm) & 0x3) == 1) ? 8 : 2, \
- (((imm) & 0x3) == 1) ? 9 : 3, \
- (((imm) & 0x3) == 2) ? 8 : 4, \
- (((imm) & 0x3) == 2) ? 9 : 5, \
- (((imm) & 0x3) == 3) ? 8 : 6, \
- (((imm) & 0x3) == 3) ? 9 : 7); })
-
-#define _mm512_mask_inserti64x2(W, U, A, B, imm) __extension__ ({ \
+ (__v16si)_mm512_setzero_si512())
+
+#define _mm512_inserti64x2(A, B, imm) \
+ (__m512i)__builtin_ia32_inserti64x2_512((__v8di)(__m512i)(A), \
+ (__v2di)(__m128i)(B), (int)(imm))
+
+#define _mm512_mask_inserti64x2(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_inserti64x2((A), (B), (imm)), \
- (__v8di)(W)); })
+ (__v8di)(__m512i)(W))
-#define _mm512_maskz_inserti64x2(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_inserti64x2(U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_inserti64x2((A), (B), (imm)), \
- (__v8di)_mm512_setzero_si512()); })
+ (__v8di)_mm512_setzero_si512())
-#define _mm512_mask_fpclass_ps_mask(U, A, imm) __extension__ ({ \
+#define _mm512_mask_fpclass_ps_mask(U, A, imm) \
(__mmask16)__builtin_ia32_fpclassps512_mask((__v16sf)(__m512)(A), \
- (int)(imm), (__mmask16)(U)); })
+ (int)(imm), (__mmask16)(U))
-#define _mm512_fpclass_ps_mask(A, imm) __extension__ ({ \
+#define _mm512_fpclass_ps_mask(A, imm) \
(__mmask16)__builtin_ia32_fpclassps512_mask((__v16sf)(__m512)(A), \
- (int)(imm), (__mmask16)-1); })
+ (int)(imm), (__mmask16)-1)
-#define _mm512_mask_fpclass_pd_mask(U, A, imm) __extension__ ({ \
+#define _mm512_mask_fpclass_pd_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclasspd512_mask((__v8df)(__m512d)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm512_fpclass_pd_mask(A, imm) __extension__ ({ \
+#define _mm512_fpclass_pd_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclasspd512_mask((__v8df)(__m512d)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_fpclass_sd_mask(A, imm) __extension__ ({ \
+#define _mm_fpclass_sd_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclasssd_mask((__v2df)(__m128d)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_fpclass_sd_mask(U, A, imm) __extension__ ({ \
+#define _mm_mask_fpclass_sd_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclasssd_mask((__v2df)(__m128d)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_fpclass_ss_mask(A, imm) __extension__ ({ \
+#define _mm_fpclass_ss_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclassss_mask((__v4sf)(__m128)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_fpclass_ss_mask(U, A, imm) __extension__ ({ \
+#define _mm_mask_fpclass_ss_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclassss_mask((__v4sf)(__m128)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
index 8ff212c42211..6348275c8d31 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
@@ -27,21 +27,21 @@
#ifndef __AVX512ERINTRIN_H
#define __AVX512ERINTRIN_H
-// exp2a23
-#define _mm512_exp2a23_round_pd(A, R) __extension__ ({ \
+/* exp2a23 */
+#define _mm512_exp2a23_round_pd(A, R) \
(__m512d)__builtin_ia32_exp2pd_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_exp2a23_round_pd(S, M, A, R) __extension__ ({ \
+#define _mm512_mask_exp2a23_round_pd(S, M, A, R) \
(__m512d)__builtin_ia32_exp2pd_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(S), (__mmask8)(M), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_exp2a23_round_pd(M, A, R) __extension__ ({ \
+#define _mm512_maskz_exp2a23_round_pd(M, A, R) \
(__m512d)__builtin_ia32_exp2pd_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm512_exp2a23_pd(A) \
_mm512_exp2a23_round_pd((A), _MM_FROUND_CUR_DIRECTION)
@@ -52,20 +52,20 @@
#define _mm512_maskz_exp2a23_pd(M, A) \
_mm512_maskz_exp2a23_round_pd((M), (A), _MM_FROUND_CUR_DIRECTION)
-#define _mm512_exp2a23_round_ps(A, R) __extension__ ({ \
+#define _mm512_exp2a23_round_ps(A, R) \
(__m512)__builtin_ia32_exp2ps_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_exp2a23_round_ps(S, M, A, R) __extension__ ({ \
+#define _mm512_mask_exp2a23_round_ps(S, M, A, R) \
(__m512)__builtin_ia32_exp2ps_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(S), (__mmask16)(M), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_exp2a23_round_ps(M, A, R) __extension__ ({ \
+#define _mm512_maskz_exp2a23_round_ps(M, A, R) \
(__m512)__builtin_ia32_exp2ps_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(M), (int)(R)); })
+ (__mmask16)(M), (int)(R))
#define _mm512_exp2a23_ps(A) \
_mm512_exp2a23_round_ps((A), _MM_FROUND_CUR_DIRECTION)
@@ -76,21 +76,21 @@
#define _mm512_maskz_exp2a23_ps(M, A) \
_mm512_maskz_exp2a23_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
-// rsqrt28
-#define _mm512_rsqrt28_round_pd(A, R) __extension__ ({ \
+/* rsqrt28 */
+#define _mm512_rsqrt28_round_pd(A, R) \
(__m512d)__builtin_ia32_rsqrt28pd_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_rsqrt28_round_pd(S, M, A, R) __extension__ ({ \
+#define _mm512_mask_rsqrt28_round_pd(S, M, A, R) \
(__m512d)__builtin_ia32_rsqrt28pd_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(S), (__mmask8)(M), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_rsqrt28_round_pd(M, A, R) __extension__ ({ \
+#define _mm512_maskz_rsqrt28_round_pd(M, A, R) \
(__m512d)__builtin_ia32_rsqrt28pd_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm512_rsqrt28_pd(A) \
_mm512_rsqrt28_round_pd((A), _MM_FROUND_CUR_DIRECTION)
@@ -101,20 +101,20 @@
#define _mm512_maskz_rsqrt28_pd(M, A) \
_mm512_maskz_rsqrt28_round_pd((M), (A), _MM_FROUND_CUR_DIRECTION)
-#define _mm512_rsqrt28_round_ps(A, R) __extension__ ({ \
+#define _mm512_rsqrt28_round_ps(A, R) \
(__m512)__builtin_ia32_rsqrt28ps_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_rsqrt28_round_ps(S, M, A, R) __extension__ ({ \
+#define _mm512_mask_rsqrt28_round_ps(S, M, A, R) \
(__m512)__builtin_ia32_rsqrt28ps_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(S), (__mmask16)(M), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_rsqrt28_round_ps(M, A, R) __extension__ ({ \
+#define _mm512_maskz_rsqrt28_round_ps(M, A, R) \
(__m512)__builtin_ia32_rsqrt28ps_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(M), (int)(R)); })
+ (__mmask16)(M), (int)(R))
#define _mm512_rsqrt28_ps(A) \
_mm512_rsqrt28_round_ps((A), _MM_FROUND_CUR_DIRECTION)
@@ -125,23 +125,23 @@
#define _mm512_maskz_rsqrt28_ps(M, A) \
_mm512_maskz_rsqrt28_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
-#define _mm_rsqrt28_round_ss(A, B, R) __extension__ ({ \
+#define _mm_rsqrt28_round_ss(A, B, R) \
(__m128)__builtin_ia32_rsqrt28ss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_rsqrt28_round_ss(S, M, A, B, R) __extension__ ({ \
+#define _mm_mask_rsqrt28_round_ss(S, M, A, B, R) \
(__m128)__builtin_ia32_rsqrt28ss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(S), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
-#define _mm_maskz_rsqrt28_round_ss(M, A, B, R) __extension__ ({ \
+#define _mm_maskz_rsqrt28_round_ss(M, A, B, R) \
(__m128)__builtin_ia32_rsqrt28ss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm_rsqrt28_ss(A, B) \
_mm_rsqrt28_round_ss((A), (B), _MM_FROUND_CUR_DIRECTION)
@@ -152,23 +152,23 @@
#define _mm_maskz_rsqrt28_ss(M, A, B) \
_mm_maskz_rsqrt28_round_ss((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
-#define _mm_rsqrt28_round_sd(A, B, R) __extension__ ({ \
+#define _mm_rsqrt28_round_sd(A, B, R) \
(__m128d)__builtin_ia32_rsqrt28sd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_rsqrt28_round_sd(S, M, A, B, R) __extension__ ({ \
+#define _mm_mask_rsqrt28_round_sd(S, M, A, B, R) \
(__m128d)__builtin_ia32_rsqrt28sd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(S), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
-#define _mm_maskz_rsqrt28_round_sd(M, A, B, R) __extension__ ({ \
+#define _mm_maskz_rsqrt28_round_sd(M, A, B, R) \
(__m128d)__builtin_ia32_rsqrt28sd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm_rsqrt28_sd(A, B) \
_mm_rsqrt28_round_sd((A), (B), _MM_FROUND_CUR_DIRECTION)
@@ -179,21 +179,21 @@
#define _mm_maskz_rsqrt28_sd(M, A, B) \
_mm_maskz_rsqrt28_round_sd((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
-// rcp28
-#define _mm512_rcp28_round_pd(A, R) __extension__ ({ \
+/* rcp28 */
+#define _mm512_rcp28_round_pd(A, R) \
(__m512d)__builtin_ia32_rcp28pd_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_rcp28_round_pd(S, M, A, R) __extension__ ({ \
+#define _mm512_mask_rcp28_round_pd(S, M, A, R) \
(__m512d)__builtin_ia32_rcp28pd_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(S), (__mmask8)(M), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_rcp28_round_pd(M, A, R) __extension__ ({ \
+#define _mm512_maskz_rcp28_round_pd(M, A, R) \
(__m512d)__builtin_ia32_rcp28pd_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm512_rcp28_pd(A) \
_mm512_rcp28_round_pd((A), _MM_FROUND_CUR_DIRECTION)
@@ -204,20 +204,20 @@
#define _mm512_maskz_rcp28_pd(M, A) \
_mm512_maskz_rcp28_round_pd((M), (A), _MM_FROUND_CUR_DIRECTION)
-#define _mm512_rcp28_round_ps(A, R) __extension__ ({ \
+#define _mm512_rcp28_round_ps(A, R) \
(__m512)__builtin_ia32_rcp28ps_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_rcp28_round_ps(S, M, A, R) __extension__ ({ \
+#define _mm512_mask_rcp28_round_ps(S, M, A, R) \
(__m512)__builtin_ia32_rcp28ps_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(S), (__mmask16)(M), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_rcp28_round_ps(M, A, R) __extension__ ({ \
+#define _mm512_maskz_rcp28_round_ps(M, A, R) \
(__m512)__builtin_ia32_rcp28ps_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(M), (int)(R)); })
+ (__mmask16)(M), (int)(R))
#define _mm512_rcp28_ps(A) \
_mm512_rcp28_round_ps((A), _MM_FROUND_CUR_DIRECTION)
@@ -228,23 +228,23 @@
#define _mm512_maskz_rcp28_ps(M, A) \
_mm512_maskz_rcp28_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
-#define _mm_rcp28_round_ss(A, B, R) __extension__ ({ \
+#define _mm_rcp28_round_ss(A, B, R) \
(__m128)__builtin_ia32_rcp28ss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_rcp28_round_ss(S, M, A, B, R) __extension__ ({ \
+#define _mm_mask_rcp28_round_ss(S, M, A, B, R) \
(__m128)__builtin_ia32_rcp28ss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(S), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
-#define _mm_maskz_rcp28_round_ss(M, A, B, R) __extension__ ({ \
+#define _mm_maskz_rcp28_round_ss(M, A, B, R) \
(__m128)__builtin_ia32_rcp28ss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm_rcp28_ss(A, B) \
_mm_rcp28_round_ss((A), (B), _MM_FROUND_CUR_DIRECTION)
@@ -255,23 +255,23 @@
#define _mm_maskz_rcp28_ss(M, A, B) \
_mm_maskz_rcp28_round_ss((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
-#define _mm_rcp28_round_sd(A, B, R) __extension__ ({ \
+#define _mm_rcp28_round_sd(A, B, R) \
(__m128d)__builtin_ia32_rcp28sd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_rcp28_round_sd(S, M, A, B, R) __extension__ ({ \
+#define _mm_mask_rcp28_round_sd(S, M, A, B, R) \
(__m128d)__builtin_ia32_rcp28sd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(S), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
-#define _mm_maskz_rcp28_round_sd(M, A, B, R) __extension__ ({ \
+#define _mm_maskz_rcp28_round_sd(M, A, B, R) \
(__m128d)__builtin_ia32_rcp28sd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
#define _mm_rcp28_sd(A, B) \
_mm_rcp28_round_sd((A), (B), _MM_FROUND_CUR_DIRECTION)
@@ -282,4 +282,4 @@
#define _mm_maskz_rcp28_sd(M, A, B) \
_mm_maskz_rcp28_round_sd((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
-#endif // __AVX512ERINTRIN_H
+#endif /* __AVX512ERINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
index f5137428ba3f..8dd4a0a40eea 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
@@ -173,51 +173,51 @@ typedef enum
} _MM_MANTISSA_SIGN_ENUM;
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512f")))
+#define __DEFAULT_FN_ATTRS512 __attribute__((__always_inline__, __nodebug__, __target__("avx512f"), __min_vector_width__(512)))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512f"), __min_vector_width__(128)))
/* Create vectors with repeated elements */
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_setzero_si512(void)
{
- return (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 };
+ return __extension__ (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 };
}
#define _mm512_setzero_epi32 _mm512_setzero_si512
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_undefined_pd(void)
{
return (__m512d)__builtin_ia32_undef512();
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_undefined(void)
{
return (__m512)__builtin_ia32_undef512();
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_undefined_ps(void)
{
return (__m512)__builtin_ia32_undef512();
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_undefined_epi32(void)
{
return (__m512i)__builtin_ia32_undef512();
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcastd_epi32 (__m128i __A)
{
- return (__m512i)__builtin_shufflevector((__v4si) __A,
- (__v4si)_mm_undefined_si128(),
+ return (__m512i)__builtin_shufflevector((__v4si) __A, (__v4si) __A,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcastd_epi32 (__m512i __O, __mmask16 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512(__M,
@@ -225,7 +225,7 @@ _mm512_mask_broadcastd_epi32 (__m512i __O, __mmask16 __M, __m128i __A)
(__v16si) __O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcastd_epi32 (__mmask16 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512(__M,
@@ -233,15 +233,14 @@ _mm512_maskz_broadcastd_epi32 (__mmask16 __M, __m128i __A)
(__v16si) _mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcastq_epi64 (__m128i __A)
{
- return (__m512i)__builtin_shufflevector((__v2di) __A,
- (__v2di) _mm_undefined_si128(),
+ return (__m512i)__builtin_shufflevector((__v2di) __A, (__v2di) __A,
0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcastq_epi64 (__m512i __O, __mmask8 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512(__M,
@@ -250,7 +249,7 @@ _mm512_mask_broadcastq_epi64 (__m512i __O, __mmask8 __M, __m128i __A)
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512(__M,
@@ -259,122 +258,122 @@ _mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_setzero_ps(void)
{
- return (__m512){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+ return __extension__ (__m512){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
}
#define _mm512_setzero _mm512_setzero_ps
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_setzero_pd(void)
{
- return (__m512d){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+ return __extension__ (__m512d){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_set1_ps(float __w)
{
- return (__m512){ __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w };
+ return __extension__ (__m512){ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_set1_pd(double __w)
{
- return (__m512d){ __w, __w, __w, __w, __w, __w, __w, __w };
+ return __extension__ (__m512d){ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set1_epi8(char __w)
{
- return (__m512i)(__v64qi){ __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w };
+ return __extension__ (__m512i)(__v64qi){
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set1_epi16(short __w)
{
- return (__m512i)(__v32hi){ __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w, __w, __w };
+ return __extension__ (__m512i)(__v32hi){
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set1_epi32(int __s)
{
- return (__m512i)(__v16si){ __s, __s, __s, __s, __s, __s, __s, __s,
- __s, __s, __s, __s, __s, __s, __s, __s };
+ return __extension__ (__m512i)(__v16si){
+ __s, __s, __s, __s, __s, __s, __s, __s,
+ __s, __s, __s, __s, __s, __s, __s, __s };
}
-static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
+static __inline __m512i __DEFAULT_FN_ATTRS512
+_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
{
- return (__m512i)__builtin_ia32_selectd_512(__M,
+ return (__m512i)__builtin_ia32_selectd_512(__M,
(__v16si)_mm512_set1_epi32(__A),
(__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set1_epi64(long long __d)
{
- return (__m512i)(__v8di){ __d, __d, __d, __d, __d, __d, __d, __d };
+ return __extension__(__m512i)(__v8di){ __d, __d, __d, __d, __d, __d, __d, __d };
}
-#ifdef __x86_64__
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_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
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_broadcastss_ps(__m128 __A)
{
- return (__m512)__builtin_shufflevector((__v4sf) __A,
- (__v4sf)_mm_undefined_ps(),
+ return (__m512)__builtin_shufflevector((__v4sf) __A, (__v4sf) __A,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set4_epi32 (int __A, int __B, int __C, int __D)
{
- return (__m512i)(__v16si)
+ return __extension__ (__m512i)(__v16si)
{ __D, __C, __B, __A, __D, __C, __B, __A,
__D, __C, __B, __A, __D, __C, __B, __A };
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set4_epi64 (long long __A, long long __B, long long __C,
long long __D)
{
- return (__m512i) (__v8di)
+ return __extension__ (__m512i) (__v8di)
{ __D, __C, __B, __A, __D, __C, __B, __A };
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_set4_pd (double __A, double __B, double __C, double __D)
{
- return (__m512d)
+ return __extension__ (__m512d)
{ __D, __C, __B, __A, __D, __C, __B, __A };
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_set4_ps (float __A, float __B, float __C, float __D)
{
- return (__m512)
+ return __extension__ (__m512)
{ __D, __C, __B, __A, __D, __C, __B, __A,
__D, __C, __B, __A, __D, __C, __B, __A };
}
@@ -391,138 +390,137 @@ _mm512_set4_ps (float __A, float __B, float __C, float __D)
#define _mm512_setr4_ps(e0,e1,e2,e3) \
_mm512_set4_ps((e3),(e2),(e1),(e0))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_broadcastsd_pd(__m128d __A)
{
- return (__m512d)__builtin_shufflevector((__v2df) __A,
- (__v2df) _mm_undefined_pd(),
+ return (__m512d)__builtin_shufflevector((__v2df) __A, (__v2df) __A,
0, 0, 0, 0, 0, 0, 0, 0);
}
/* Cast between vector types */
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_castpd256_pd512(__m256d __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, -1, -1, -1, -1);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_castps256_ps512(__m256 __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, 4, 5, 6, 7,
-1, -1, -1, -1, -1, -1, -1, -1);
}
-static __inline __m128d __DEFAULT_FN_ATTRS
+static __inline __m128d __DEFAULT_FN_ATTRS512
_mm512_castpd512_pd128(__m512d __a)
{
return __builtin_shufflevector(__a, __a, 0, 1);
}
-static __inline __m256d __DEFAULT_FN_ATTRS
+static __inline __m256d __DEFAULT_FN_ATTRS512
_mm512_castpd512_pd256 (__m512d __A)
{
return __builtin_shufflevector(__A, __A, 0, 1, 2, 3);
}
-static __inline __m128 __DEFAULT_FN_ATTRS
+static __inline __m128 __DEFAULT_FN_ATTRS512
_mm512_castps512_ps128(__m512 __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3);
}
-static __inline __m256 __DEFAULT_FN_ATTRS
+static __inline __m256 __DEFAULT_FN_ATTRS512
_mm512_castps512_ps256 (__m512 __A)
{
return __builtin_shufflevector(__A, __A, 0, 1, 2, 3, 4, 5, 6, 7);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_castpd_ps (__m512d __A)
{
return (__m512) (__A);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_castpd_si512 (__m512d __A)
{
return (__m512i) (__A);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_castpd128_pd512 (__m128d __A)
{
return __builtin_shufflevector( __A, __A, 0, 1, -1, -1, -1, -1, -1, -1);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_castps_pd (__m512 __A)
{
return (__m512d) (__A);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_castps_si512 (__m512 __A)
{
return (__m512i) (__A);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_castps128_ps512 (__m128 __A)
{
return __builtin_shufflevector( __A, __A, 0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_castsi128_si512 (__m128i __A)
{
return __builtin_shufflevector( __A, __A, 0, 1, -1, -1, -1, -1, -1, -1);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_castsi256_si512 (__m256i __A)
{
return __builtin_shufflevector( __A, __A, 0, 1, 2, 3, -1, -1, -1, -1);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_castsi512_ps (__m512i __A)
{
return (__m512) (__A);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_castsi512_pd (__m512i __A)
{
return (__m512d) (__A);
}
-static __inline __m128i __DEFAULT_FN_ATTRS
+static __inline __m128i __DEFAULT_FN_ATTRS512
_mm512_castsi512_si128 (__m512i __A)
{
return (__m128i)__builtin_shufflevector(__A, __A , 0, 1);
}
-static __inline __m256i __DEFAULT_FN_ATTRS
+static __inline __m256i __DEFAULT_FN_ATTRS512
_mm512_castsi512_si256 (__m512i __A)
{
return (__m256i)__builtin_shufflevector(__A, __A , 0, 1, 2, 3);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_int2mask(int __a)
{
return (__mmask16)__a;
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_mask2int(__mmask16 __a)
{
return (int)__a;
}
-/// \brief Constructs a 512-bit floating-point vector of [8 x double] from a
+/// Constructs a 512-bit floating-point vector of [8 x double] from a
/// 128-bit floating-point vector of [2 x double]. The lower 128 bits
/// contain the value of the source vector. The upper 384 bits are set
/// to zero.
@@ -535,13 +533,13 @@ _mm512_mask2int(__mmask16 __a)
/// A 128-bit vector of [2 x double].
/// \returns A 512-bit floating-point vector of [8 x double]. The lower 128 bits
/// contain the value of the parameter. The upper 384 bits are set to zero.
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_zextpd128_pd512(__m128d __a)
{
return __builtin_shufflevector((__v2df)__a, (__v2df)_mm_setzero_pd(), 0, 1, 2, 3, 2, 3, 2, 3);
}
-/// \brief Constructs a 512-bit floating-point vector of [8 x double] from a
+/// Constructs a 512-bit floating-point vector of [8 x double] from a
/// 256-bit floating-point vector of [4 x double]. The lower 256 bits
/// contain the value of the source vector. The upper 256 bits are set
/// to zero.
@@ -554,13 +552,13 @@ _mm512_zextpd128_pd512(__m128d __a)
/// A 256-bit vector of [4 x double].
/// \returns A 512-bit floating-point vector of [8 x double]. The lower 256 bits
/// contain the value of the parameter. The upper 256 bits are set to zero.
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_zextpd256_pd512(__m256d __a)
{
return __builtin_shufflevector((__v4df)__a, (__v4df)_mm256_setzero_pd(), 0, 1, 2, 3, 4, 5, 6, 7);
}
-/// \brief Constructs a 512-bit floating-point vector of [16 x float] from a
+/// Constructs a 512-bit floating-point vector of [16 x float] from a
/// 128-bit floating-point vector of [4 x float]. The lower 128 bits contain
/// the value of the source vector. The upper 384 bits are set to zero.
///
@@ -572,13 +570,13 @@ _mm512_zextpd256_pd512(__m256d __a)
/// A 128-bit vector of [4 x float].
/// \returns A 512-bit floating-point vector of [16 x float]. The lower 128 bits
/// contain the value of the parameter. The upper 384 bits are set to zero.
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_zextps128_ps512(__m128 __a)
{
return __builtin_shufflevector((__v4sf)__a, (__v4sf)_mm_setzero_ps(), 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7);
}
-/// \brief Constructs a 512-bit floating-point vector of [16 x float] from a
+/// Constructs a 512-bit floating-point vector of [16 x float] from a
/// 256-bit floating-point vector of [8 x float]. The lower 256 bits contain
/// the value of the source vector. The upper 256 bits are set to zero.
///
@@ -590,13 +588,13 @@ _mm512_zextps128_ps512(__m128 __a)
/// A 256-bit vector of [8 x float].
/// \returns A 512-bit floating-point vector of [16 x float]. The lower 256 bits
/// contain the value of the parameter. The upper 256 bits are set to zero.
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_zextps256_ps512(__m256 __a)
{
return __builtin_shufflevector((__v8sf)__a, (__v8sf)_mm256_setzero_ps(), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
}
-/// \brief Constructs a 512-bit integer vector from a 128-bit integer vector.
+/// Constructs a 512-bit integer vector from a 128-bit integer vector.
/// The lower 128 bits contain the value of the source vector. The upper
/// 384 bits are set to zero.
///
@@ -608,13 +606,13 @@ _mm512_zextps256_ps512(__m256 __a)
/// A 128-bit integer vector.
/// \returns A 512-bit integer vector. The lower 128 bits contain the value of
/// the parameter. The upper 384 bits are set to zero.
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_zextsi128_si512(__m128i __a)
{
return __builtin_shufflevector((__v2di)__a, (__v2di)_mm_setzero_si128(), 0, 1, 2, 3, 2, 3, 2, 3);
}
-/// \brief Constructs a 512-bit integer vector from a 256-bit integer vector.
+/// Constructs a 512-bit integer vector from a 256-bit integer vector.
/// The lower 256 bits contain the value of the source vector. The upper
/// 256 bits are set to zero.
///
@@ -626,20 +624,20 @@ _mm512_zextsi128_si512(__m128i __a)
/// A 256-bit integer vector.
/// \returns A 512-bit integer vector. The lower 256 bits contain the value of
/// the parameter. The upper 256 bits are set to zero.
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_zextsi256_si512(__m256i __a)
{
return __builtin_shufflevector((__v4di)__a, (__v4di)_mm256_setzero_si256(), 0, 1, 2, 3, 4, 5, 6, 7);
}
/* Bitwise operators */
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_and_epi32(__m512i __a, __m512i __b)
{
return (__m512i)((__v16su)__a & (__v16su)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_and_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__k,
@@ -647,20 +645,20 @@ _mm512_mask_and_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
(__v16si) __src);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_and_epi32(__mmask16 __k, __m512i __a, __m512i __b)
{
return (__m512i) _mm512_mask_and_epi32(_mm512_setzero_si512 (),
__k, __a, __b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_and_epi64(__m512i __a, __m512i __b)
{
return (__m512i)((__v8du)__a & (__v8du)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_and_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
{
return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __k,
@@ -668,26 +666,26 @@ _mm512_mask_and_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
(__v8di) __src);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_and_epi64(__mmask8 __k, __m512i __a, __m512i __b)
{
return (__m512i) _mm512_mask_and_epi64(_mm512_setzero_si512 (),
__k, __a, __b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_andnot_si512 (__m512i __A, __m512i __B)
{
- return (__m512i)(~(__v8du)(__A) & (__v8du)__B);
+ return (__m512i)(~(__v8du)__A & (__v8du)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_andnot_epi32 (__m512i __A, __m512i __B)
{
- return (__m512i)(~(__v16su)(__A) & (__v16su)__B);
+ return (__m512i)(~(__v16su)__A & (__v16su)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_andnot_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -695,20 +693,20 @@ _mm512_mask_andnot_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_andnot_epi32(__mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)_mm512_mask_andnot_epi32(_mm512_setzero_si512(),
__U, __A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_andnot_epi64(__m512i __A, __m512i __B)
{
- return (__m512i)(~(__v8du)(__A) & (__v8du)__B);
+ return (__m512i)(~(__v8du)__A & (__v8du)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_andnot_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -716,20 +714,20 @@ _mm512_mask_andnot_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_andnot_epi64(__mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)_mm512_mask_andnot_epi64(_mm512_setzero_si512(),
__U, __A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_or_epi32(__m512i __a, __m512i __b)
{
return (__m512i)((__v16su)__a | (__v16su)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_or_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__k,
@@ -737,19 +735,19 @@ _mm512_mask_or_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
(__v16si)__src);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_or_epi32(__mmask16 __k, __m512i __a, __m512i __b)
{
return (__m512i)_mm512_mask_or_epi32(_mm512_setzero_si512(), __k, __a, __b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_or_epi64(__m512i __a, __m512i __b)
{
return (__m512i)((__v8du)__a | (__v8du)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_or_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__k,
@@ -757,19 +755,19 @@ _mm512_mask_or_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
(__v8di)__src);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_or_epi64(__mmask8 __k, __m512i __a, __m512i __b)
{
return (__m512i)_mm512_mask_or_epi64(_mm512_setzero_si512(), __k, __a, __b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_xor_epi32(__m512i __a, __m512i __b)
{
return (__m512i)((__v16su)__a ^ (__v16su)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_xor_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__k,
@@ -777,19 +775,19 @@ _mm512_mask_xor_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
(__v16si)__src);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_xor_epi32(__mmask16 __k, __m512i __a, __m512i __b)
{
return (__m512i)_mm512_mask_xor_epi32(_mm512_setzero_si512(), __k, __a, __b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_xor_epi64(__m512i __a, __m512i __b)
{
return (__m512i)((__v8du)__a ^ (__v8du)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_xor_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__k,
@@ -797,25 +795,25 @@ _mm512_mask_xor_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
(__v8di)__src);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_xor_epi64(__mmask8 __k, __m512i __a, __m512i __b)
{
return (__m512i)_mm512_mask_xor_epi64(_mm512_setzero_si512(), __k, __a, __b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_and_si512(__m512i __a, __m512i __b)
{
return (__m512i)((__v8du)__a & (__v8du)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_or_si512(__m512i __a, __m512i __b)
{
return (__m512i)((__v8du)__a | (__v8du)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_xor_si512(__m512i __a, __m512i __b)
{
return (__m512i)((__v8du)__a ^ (__v8du)__b);
@@ -823,49 +821,49 @@ _mm512_xor_si512(__m512i __a, __m512i __b)
/* Arithmetic */
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_add_pd(__m512d __a, __m512d __b)
{
return (__m512d)((__v8df)__a + (__v8df)__b);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_add_ps(__m512 __a, __m512 __b)
{
return (__m512)((__v16sf)__a + (__v16sf)__b);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_mul_pd(__m512d __a, __m512d __b)
{
return (__m512d)((__v8df)__a * (__v8df)__b);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_mul_ps(__m512 __a, __m512 __b)
{
return (__m512)((__v16sf)__a * (__v16sf)__b);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_sub_pd(__m512d __a, __m512d __b)
{
return (__m512d)((__v8df)__a - (__v8df)__b);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_sub_ps(__m512 __a, __m512 __b)
{
return (__m512)((__v16sf)__a - (__v16sf)__b);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_add_epi64 (__m512i __A, __m512i __B)
{
return (__m512i) ((__v8du) __A + (__v8du) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_add_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -873,7 +871,7 @@ _mm512_mask_add_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_add_epi64(__mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -881,13 +879,13 @@ _mm512_maskz_add_epi64(__mmask8 __U, __m512i __A, __m512i __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sub_epi64 (__m512i __A, __m512i __B)
{
return (__m512i) ((__v8du) __A - (__v8du) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sub_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -895,7 +893,7 @@ _mm512_mask_sub_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sub_epi64(__mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -903,13 +901,13 @@ _mm512_maskz_sub_epi64(__mmask8 __U, __m512i __A, __m512i __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_add_epi32 (__m512i __A, __m512i __B)
{
return (__m512i) ((__v16su) __A + (__v16su) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_add_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -917,7 +915,7 @@ _mm512_mask_add_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -925,13 +923,13 @@ _mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sub_epi32 (__m512i __A, __m512i __B)
{
return (__m512i) ((__v16su) __A - (__v16su) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sub_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -939,7 +937,7 @@ _mm512_mask_sub_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -947,107 +945,81 @@ _mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B)
(__v16si)_mm512_setzero_si512());
}
-#define _mm512_mask_max_round_pd(W, U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
+#define _mm512_max_round_pd(A, B, R) \
+ (__m512d)__builtin_ia32_maxpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(R))
-#define _mm512_maskz_max_round_pd(U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+#define _mm512_mask_max_round_pd(W, U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_max_round_pd((A), (B), (R)), \
+ (__v8df)(W))
-#define _mm512_max_round_pd(A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+#define _mm512_maskz_max_round_pd(U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_max_round_pd((A), (B), (R)), \
+ (__v8df)_mm512_setzero_pd())
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_max_pd(__m512d __A, __m512d __B)
{
- return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_maxpd512((__v8df) __A, (__v8df) __B,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
- return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_max_pd(__A, __B),
+ (__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B)
{
- return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_max_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
-#define _mm512_mask_max_round_ps(W, U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); })
+#define _mm512_max_round_ps(A, B, R) \
+ (__m512)__builtin_ia32_maxps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(R))
-#define _mm512_maskz_max_round_ps(U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+#define _mm512_mask_max_round_ps(W, U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_max_round_ps((A), (B), (R)), \
+ (__v16sf)(W))
-#define _mm512_max_round_ps(A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+#define _mm512_maskz_max_round_ps(U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_max_round_ps((A), (B), (R)), \
+ (__v16sf)_mm512_setzero_ps())
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_max_ps(__m512 __A, __m512 __B)
{
- return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_maxps512((__v16sf) __A, (__v16sf) __B,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
- return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_max_ps(__A, __B),
+ (__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
- return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_max_ps(__A, __B),
+ (__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_max_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_maxss_round_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -1056,7 +1028,7 @@ _mm_mask_max_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_max_ss(__mmask8 __U,__m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_maxss_round_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -1065,25 +1037,25 @@ _mm_maskz_max_ss(__mmask8 __U,__m128 __A, __m128 __B) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_max_round_ss(A, B, R) __extension__ ({ \
+#define _mm_max_round_ss(A, B, R) \
(__m128)__builtin_ia32_maxss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_max_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_max_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_maxss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_max_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_max_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_maxss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_max_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
return (__m128d) __builtin_ia32_maxsd_round_mask ((__v2df) __A,
(__v2df) __B,
@@ -1092,7 +1064,7 @@ _mm_mask_max_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_max_sd(__mmask8 __U,__m128d __A, __m128d __B) {
return (__m128d) __builtin_ia32_maxsd_round_mask ((__v2df) __A,
(__v2df) __B,
@@ -1101,238 +1073,188 @@ _mm_maskz_max_sd(__mmask8 __U,__m128d __A, __m128d __B) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_max_round_sd(A, B, R) __extension__ ({ \
+#define _mm_max_round_sd(A, B, R) \
(__m128d)__builtin_ia32_maxsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_max_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_max_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_maxsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_max_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_max_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_maxsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline __m512i
-__DEFAULT_FN_ATTRS
+__DEFAULT_FN_ATTRS512
_mm512_max_epi32(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_pmaxsd512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W, __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_max_epi32(__A, __B),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epi32 (__mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_max_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epu32(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_pmaxud512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W, __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_max_epu32(__A, __B),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epu32 (__mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_max_epu32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epi64(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pmaxsq512((__v8di)__A, (__v8di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W, __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_max_epi64(__A, __B),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epi64 (__mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_max_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epu64(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pmaxuq512((__v8di)__A, (__v8di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W, __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_max_epu64(__A, __B),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_max_epu64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
-#define _mm512_mask_min_round_pd(W, U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
+#define _mm512_min_round_pd(A, B, R) \
+ (__m512d)__builtin_ia32_minpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(R))
-#define _mm512_maskz_min_round_pd(U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+#define _mm512_mask_min_round_pd(W, U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_min_round_pd((A), (B), (R)), \
+ (__v8df)(W))
-#define _mm512_min_round_pd(A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+#define _mm512_maskz_min_round_pd(U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_min_round_pd((A), (B), (R)), \
+ (__v8df)_mm512_setzero_pd())
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_min_pd(__m512d __A, __m512d __B)
{
- return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_minpd512((__v8df) __A, (__v8df) __B,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
- return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_min_pd(__A, __B),
+ (__v8df)__W);
}
-#define _mm512_mask_min_round_ps(W, U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); })
-
-#define _mm512_maskz_min_round_ps(U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
-
-#define _mm512_min_round_ps(A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
-
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B)
{
- return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_min_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+#define _mm512_min_round_ps(A, B, R) \
+ (__m512)__builtin_ia32_minps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(R))
+
+#define _mm512_mask_min_round_ps(W, U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_min_round_ps((A), (B), (R)), \
+ (__v16sf)(W))
+
+#define _mm512_maskz_min_round_ps(U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_min_round_ps((A), (B), (R)), \
+ (__v16sf)_mm512_setzero_ps())
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_min_ps(__m512 __A, __m512 __B)
{
- return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_minps512((__v16sf) __A, (__v16sf) __B,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
- return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_min_ps(__A, __B),
+ (__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
- return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_min_ps(__A, __B),
+ (__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_min_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_minss_round_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -1341,7 +1263,7 @@ _mm_mask_min_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_min_ss(__mmask8 __U,__m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_minss_round_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -1350,25 +1272,25 @@ _mm_maskz_min_ss(__mmask8 __U,__m128 __A, __m128 __B) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_min_round_ss(A, B, R) __extension__ ({ \
+#define _mm_min_round_ss(A, B, R) \
(__m128)__builtin_ia32_minss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_min_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_min_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_minss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_min_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_min_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_minss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_min_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
return (__m128d) __builtin_ia32_minsd_round_mask ((__v2df) __A,
(__v2df) __B,
@@ -1377,7 +1299,7 @@ _mm_mask_min_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_min_sd(__mmask8 __U,__m128d __A, __m128d __B) {
return (__m128d) __builtin_ia32_minsd_round_mask ((__v2df) __A,
(__v2df) __B,
@@ -1386,144 +1308,120 @@ _mm_maskz_min_sd(__mmask8 __U,__m128d __A, __m128d __B) {
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_min_round_sd(A, B, R) __extension__ ({ \
+#define _mm_min_round_sd(A, B, R) \
(__m128d)__builtin_ia32_minsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_min_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_min_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_minsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_min_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_min_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_minsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
static __inline __m512i
-__DEFAULT_FN_ATTRS
+__DEFAULT_FN_ATTRS512
_mm512_min_epi32(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_pminsd512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W, __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_min_epi32(__A, __B),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epi32 (__mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_min_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epu32(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_pminud512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W, __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_min_epu32(__A, __B),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epu32 (__mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_min_epu32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epi64(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pminsq512((__v8di)__A, (__v8di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W, __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_min_epi64(__A, __B),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epi64 (__mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_min_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epu64(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pminuq512((__v8di)__A, (__v8di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W, __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_min_epu64(__A, __B),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_min_epu64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mul_epi32(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_pmuldq512((__v16si)__X, (__v16si) __Y);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mul_epi32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -1531,7 +1429,7 @@ _mm512_mask_mul_epi32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
(__v8di)__W);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -1539,13 +1437,13 @@ _mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y)
(__v8di)_mm512_setzero_si512 ());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mul_epu32(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_pmuludq512((__v16si)__X, (__v16si)__Y);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mul_epu32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -1553,7 +1451,7 @@ _mm512_mask_mul_epu32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
(__v8di)__W);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mul_epu32(__mmask8 __M, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -1561,13 +1459,13 @@ _mm512_maskz_mul_epu32(__mmask8 __M, __m512i __X, __m512i __Y)
(__v8di)_mm512_setzero_si512 ());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mullo_epi32 (__m512i __A, __m512i __B)
{
return (__m512i) ((__v16su) __A * (__v16su) __B);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mullo_epi32(__mmask16 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -1575,7 +1473,7 @@ _mm512_maskz_mullo_epi32(__mmask16 __M, __m512i __A, __m512i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mullo_epi32(__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -1583,92 +1481,91 @@ _mm512_mask_mullo_epi32(__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
(__v16si)__W);
}
-#define _mm512_mask_sqrt_round_pd(W, U, A, R) __extension__ ({ \
- (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mullox_epi64 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v8du) __A * (__v8du) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_mullox_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_mullox_epi64(__A, __B),
+ (__v8di)__W);
+}
+
+#define _mm512_sqrt_round_pd(A, R) \
+ (__m512d)__builtin_ia32_sqrtpd512((__v8df)(__m512d)(A), (int)(R))
-#define _mm512_maskz_sqrt_round_pd(U, A, R) __extension__ ({ \
- (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+#define _mm512_mask_sqrt_round_pd(W, U, A, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_sqrt_round_pd((A), (R)), \
+ (__v8df)(__m512d)(W))
-#define _mm512_sqrt_round_pd(A, R) __extension__ ({ \
- (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+#define _mm512_maskz_sqrt_round_pd(U, A, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_sqrt_round_pd((A), (R)), \
+ (__v8df)_mm512_setzero_pd())
-static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_sqrt_pd(__m512d __a)
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
+_mm512_sqrt_pd(__m512d __A)
{
- return (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)__a,
- (__v8df) _mm512_setzero_pd (),
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_sqrtpd512((__v8df)__A,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_sqrt_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
- return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_sqrt_pd(__A),
+ (__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A)
{
- return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_sqrt_pd(__A),
+ (__v8df)_mm512_setzero_pd());
}
-#define _mm512_mask_sqrt_round_ps(W, U, A, R) __extension__ ({ \
- (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); })
+#define _mm512_sqrt_round_ps(A, R) \
+ (__m512)__builtin_ia32_sqrtps512((__v16sf)(__m512)(A), (int)(R))
-#define _mm512_maskz_sqrt_round_ps(U, A, R) __extension__ ({ \
- (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+#define _mm512_mask_sqrt_round_ps(W, U, A, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_sqrt_round_ps((A), (R)), \
+ (__v16sf)(__m512)(W))
-#define _mm512_sqrt_round_ps(A, R) __extension__ ({ \
- (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+#define _mm512_maskz_sqrt_round_ps(U, A, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_sqrt_round_ps((A), (R)), \
+ (__v16sf)_mm512_setzero_ps())
-static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_sqrt_ps(__m512 __a)
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
+_mm512_sqrt_ps(__m512 __A)
{
- return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__a,
- (__v16sf) _mm512_setzero_ps (),
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_sqrtps512((__v16sf)__A,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_sqrt_ps(__m512 __W, __mmask16 __U, __m512 __A)
{
- return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__A,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_sqrt_ps(__A),
+ (__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_sqrt_ps( __mmask16 __U, __m512 __A)
{
- return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__A,
- (__v16sf) _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_sqrt_ps(__A),
+ (__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_rsqrt14_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A,
@@ -1676,7 +1573,7 @@ _mm512_rsqrt14_pd(__m512d __A)
_mm512_setzero_pd (),
(__mmask8) -1);}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_rsqrt14_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A,
@@ -1684,7 +1581,7 @@ _mm512_mask_rsqrt14_pd (__m512d __W, __mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_rsqrt14_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A,
@@ -1693,7 +1590,7 @@ _mm512_maskz_rsqrt14_pd (__mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_rsqrt14_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A,
@@ -1702,7 +1599,7 @@ _mm512_rsqrt14_ps(__m512 __A)
(__mmask16) -1);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_rsqrt14_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A,
@@ -1710,7 +1607,7 @@ _mm512_mask_rsqrt14_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_rsqrt14_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A,
@@ -1719,7 +1616,7 @@ _mm512_maskz_rsqrt14_ps (__mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_rsqrt14_ss(__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A,
@@ -1729,7 +1626,7 @@ _mm_rsqrt14_ss(__m128 __A, __m128 __B)
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_rsqrt14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A,
@@ -1738,7 +1635,7 @@ _mm_mask_rsqrt14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_rsqrt14_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A,
@@ -1747,7 +1644,7 @@ _mm_maskz_rsqrt14_ss (__mmask8 __U, __m128 __A, __m128 __B)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_rsqrt14_sd(__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rsqrt14sd_mask ((__v2df) __A,
@@ -1757,7 +1654,7 @@ _mm_rsqrt14_sd(__m128d __A, __m128d __B)
(__mmask8) -1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_rsqrt14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rsqrt14sd_mask ( (__v2df) __A,
@@ -1766,7 +1663,7 @@ _mm_mask_rsqrt14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_rsqrt14_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rsqrt14sd_mask ( (__v2df) __A,
@@ -1775,7 +1672,7 @@ _mm_maskz_rsqrt14_sd (__mmask8 __U, __m128d __A, __m128d __B)
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_rcp14_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A,
@@ -1784,7 +1681,7 @@ _mm512_rcp14_pd(__m512d __A)
(__mmask8) -1);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_rcp14_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A,
@@ -1792,7 +1689,7 @@ _mm512_mask_rcp14_pd (__m512d __W, __mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_rcp14_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A,
@@ -1801,7 +1698,7 @@ _mm512_maskz_rcp14_pd (__mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_rcp14_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A,
@@ -1810,7 +1707,7 @@ _mm512_rcp14_ps(__m512 __A)
(__mmask16) -1);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_rcp14_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A,
@@ -1818,7 +1715,7 @@ _mm512_mask_rcp14_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_rcp14_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A,
@@ -1827,7 +1724,7 @@ _mm512_maskz_rcp14_ps (__mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_rcp14_ss(__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A,
@@ -1837,7 +1734,7 @@ _mm_rcp14_ss(__m128 __A, __m128 __B)
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_rcp14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A,
@@ -1846,7 +1743,7 @@ _mm_mask_rcp14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_rcp14_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A,
@@ -1855,7 +1752,7 @@ _mm_maskz_rcp14_ss (__mmask8 __U, __m128 __A, __m128 __B)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_rcp14_sd(__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rcp14sd_mask ((__v2df) __A,
@@ -1865,7 +1762,7 @@ _mm_rcp14_sd(__m128d __A, __m128d __B)
(__mmask8) -1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_rcp14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rcp14sd_mask ( (__v2df) __A,
@@ -1874,7 +1771,7 @@ _mm_mask_rcp14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_rcp14_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rcp14sd_mask ( (__v2df) __A,
@@ -1883,7 +1780,7 @@ _mm_maskz_rcp14_sd (__mmask8 __U, __m128d __A, __m128d __B)
(__mmask8) __U);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_floor_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A,
@@ -1892,7 +1789,7 @@ _mm512_floor_ps(__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_floor_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A,
@@ -1901,7 +1798,7 @@ _mm512_mask_floor_ps (__m512 __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_floor_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A,
@@ -1910,7 +1807,7 @@ _mm512_floor_pd(__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_floor_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A,
@@ -1919,7 +1816,7 @@ _mm512_mask_floor_pd (__m512d __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_ceil_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A,
@@ -1928,7 +1825,7 @@ _mm512_mask_ceil_ps (__m512 __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_ceil_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A,
@@ -1937,7 +1834,7 @@ _mm512_ceil_ps(__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_ceil_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A,
@@ -1946,7 +1843,7 @@ _mm512_ceil_pd(__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_ceil_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A,
@@ -1955,758 +1852,672 @@ _mm512_mask_ceil_pd (__m512d __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_abs_epi64(__m512i __A)
{
- return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pabsq512((__v8di)__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_abs_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_abs_epi64(__A),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_abs_epi64 (__mmask8 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_abs_epi64(__A),
+ (__v8di)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_abs_epi32(__m512i __A)
{
- return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_pabsd512((__v16si) __A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_abs_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_abs_epi32(__A),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_abs_epi32 (__mmask16 __U, __m512i __A)
{
- return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_abs_epi32(__A),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_add_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_addss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_add_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, __W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_addss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) _mm_setzero_ps (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_add_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps());
}
-#define _mm_add_round_ss(A, B, R) __extension__ ({ \
+#define _mm_add_round_ss(A, B, R) \
(__m128)__builtin_ia32_addss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_add_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_add_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_addss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_add_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_add_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_addss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_add_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_addsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_add_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, __W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_addsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) _mm_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_add_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd());
}
-#define _mm_add_round_sd(A, B, R) __extension__ ({ \
+#define _mm_add_round_sd(A, B, R) \
(__m128d)__builtin_ia32_addsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_add_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_add_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_addsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_add_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_add_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_addsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_add_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_add_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_add_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_add_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_add_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_add_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-#define _mm512_add_round_pd(A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_addpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
-
-#define _mm512_mask_add_round_pd(W, U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_addpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
-
-#define _mm512_maskz_add_round_pd(U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_addpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
-
-#define _mm512_add_round_ps(A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_addps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
-
-#define _mm512_mask_add_round_ps(W, U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_addps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); })
-
-#define _mm512_maskz_add_round_ps(U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_addps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+#define _mm512_add_round_pd(A, B, R) \
+ (__m512d)__builtin_ia32_addpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(R))
+
+#define _mm512_mask_add_round_pd(W, U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_add_round_pd((A), (B), (R)), \
+ (__v8df)(__m512d)(W));
+
+#define _mm512_maskz_add_round_pd(U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_add_round_pd((A), (B), (R)), \
+ (__v8df)_mm512_setzero_pd());
+
+#define _mm512_add_round_ps(A, B, R) \
+ (__m512)__builtin_ia32_addps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(R))
+
+#define _mm512_mask_add_round_ps(W, U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_add_round_ps((A), (B), (R)), \
+ (__v16sf)(__m512)(W));
+
+#define _mm512_maskz_add_round_ps(U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_add_round_ps((A), (B), (R)), \
+ (__v16sf)_mm512_setzero_ps());
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_subss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_sub_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, __W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_subss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) _mm_setzero_ps (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_sub_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps());
}
-#define _mm_sub_round_ss(A, B, R) __extension__ ({ \
+#define _mm_sub_round_ss(A, B, R) \
(__m128)__builtin_ia32_subss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_sub_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_sub_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_subss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_sub_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_sub_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_subss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_sub_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_subsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_sub_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, __W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_subsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) _mm_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_sub_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd());
}
-#define _mm_sub_round_sd(A, B, R) __extension__ ({ \
+#define _mm_sub_round_sd(A, B, R) \
(__m128d)__builtin_ia32_subsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_sub_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_sub_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_subsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_sub_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_sub_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_subsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_sub_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_sub_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_sub_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_sub_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_sub_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_sub_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-#define _mm512_sub_round_pd(A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_subpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
-
-#define _mm512_mask_sub_round_pd(W, U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_subpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
-
-#define _mm512_maskz_sub_round_pd(U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_subpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
-
-#define _mm512_sub_round_ps(A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_subps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
-
-#define _mm512_mask_sub_round_ps(W, U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_subps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); });
-
-#define _mm512_maskz_sub_round_ps(U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_subps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); });
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+#define _mm512_sub_round_pd(A, B, R) \
+ (__m512d)__builtin_ia32_subpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(R))
+
+#define _mm512_mask_sub_round_pd(W, U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_sub_round_pd((A), (B), (R)), \
+ (__v8df)(__m512d)(W));
+
+#define _mm512_maskz_sub_round_pd(U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_sub_round_pd((A), (B), (R)), \
+ (__v8df)_mm512_setzero_pd());
+
+#define _mm512_sub_round_ps(A, B, R) \
+ (__m512)__builtin_ia32_subps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(R))
+
+#define _mm512_mask_sub_round_ps(W, U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \
+ (__v16sf)(__m512)(W));
+
+#define _mm512_maskz_sub_round_ps(U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \
+ (__v16sf)_mm512_setzero_ps());
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_mulss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_mul_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, __W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_mulss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) _mm_setzero_ps (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_mul_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps());
}
-#define _mm_mul_round_ss(A, B, R) __extension__ ({ \
+#define _mm_mul_round_ss(A, B, R) \
(__m128)__builtin_ia32_mulss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_mul_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_mul_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_mulss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_mul_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_mul_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_mulss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_mul_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_mulsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_mul_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, __W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_mulsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) _mm_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_mul_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd());
}
-#define _mm_mul_round_sd(A, B, R) __extension__ ({ \
+#define _mm_mul_round_sd(A, B, R) \
(__m128d)__builtin_ia32_mulsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_mul_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_mul_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_mulsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_mul_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_mul_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_mulsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_mul_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_mul_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_mul_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_mul_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_mul_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_mul_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-#define _mm512_mul_round_pd(A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_mulpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
-
-#define _mm512_mask_mul_round_pd(W, U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_mulpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
-
-#define _mm512_maskz_mul_round_pd(U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_mulpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
-
-#define _mm512_mul_round_ps(A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_mulps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
-
-#define _mm512_mask_mul_round_ps(W, U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_mulps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); });
-
-#define _mm512_maskz_mul_round_ps(U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_mulps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); });
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+#define _mm512_mul_round_pd(A, B, R) \
+ (__m512d)__builtin_ia32_mulpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(R))
+
+#define _mm512_mask_mul_round_pd(W, U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_mul_round_pd((A), (B), (R)), \
+ (__v8df)(__m512d)(W));
+
+#define _mm512_maskz_mul_round_pd(U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_mul_round_pd((A), (B), (R)), \
+ (__v8df)_mm512_setzero_pd());
+
+#define _mm512_mul_round_ps(A, B, R) \
+ (__m512)__builtin_ia32_mulps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(R))
+
+#define _mm512_mask_mul_round_ps(W, U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \
+ (__v16sf)(__m512)(W));
+
+#define _mm512_maskz_mul_round_ps(U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \
+ (__v16sf)_mm512_setzero_ps());
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_divss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_div_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, __W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_divss_round_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) _mm_setzero_ps (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_div_ss(__A, __B);
+ return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps());
}
-#define _mm_div_round_ss(A, B, R) __extension__ ({ \
+#define _mm_div_round_ss(A, B, R) \
(__m128)__builtin_ia32_divss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_div_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_div_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_divss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_div_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_div_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_divss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_divsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_div_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, __W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_divsd_round_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) _mm_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ __A = _mm_div_sd(__A, __B);
+ return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd());
}
-#define _mm_div_round_sd(A, B, R) __extension__ ({ \
+#define _mm_div_round_sd(A, B, R) \
(__m128d)__builtin_ia32_divsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_div_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_div_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_divsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_div_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_div_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_divsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_div_pd(__m512d __a, __m512d __b)
{
return (__m512d)((__v8df)__a/(__v8df)__b);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_div_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_div_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_div_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_div_ps(__m512 __a, __m512 __b)
{
return (__m512)((__v16sf)__a/(__v16sf)__b);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_div_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_div_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_div_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-#define _mm512_div_round_pd(A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_divpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
-
-#define _mm512_mask_div_round_pd(W, U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_divpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(W), (__mmask8)(U), \
- (int)(R)); })
-
-#define _mm512_maskz_div_round_pd(U, A, B, R) __extension__ ({ \
- (__m512d)__builtin_ia32_divpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
-
-#define _mm512_div_round_ps(A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_divps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
-
-#define _mm512_mask_div_round_ps(W, U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_divps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(W), (__mmask16)(U), \
- (int)(R)); });
-
-#define _mm512_maskz_div_round_ps(U, A, B, R) __extension__ ({ \
- (__m512)__builtin_ia32_divps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); });
-
-#define _mm512_roundscale_ps(A, B) __extension__ ({ \
+#define _mm512_div_round_pd(A, B, R) \
+ (__m512d)__builtin_ia32_divpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(R))
+
+#define _mm512_mask_div_round_pd(W, U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_div_round_pd((A), (B), (R)), \
+ (__v8df)(__m512d)(W));
+
+#define _mm512_maskz_div_round_pd(U, A, B, R) \
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_div_round_pd((A), (B), (R)), \
+ (__v8df)_mm512_setzero_pd());
+
+#define _mm512_div_round_ps(A, B, R) \
+ (__m512)__builtin_ia32_divps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(R))
+
+#define _mm512_mask_div_round_ps(W, U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_div_round_ps((A), (B), (R)), \
+ (__v16sf)(__m512)(W));
+
+#define _mm512_maskz_div_round_ps(U, A, B, R) \
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_div_round_ps((A), (B), (R)), \
+ (__v16sf)_mm512_setzero_ps());
+
+#define _mm512_roundscale_ps(A, B) \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(A), (int)(B), \
- (__v16sf)(__m512)(A), (__mmask16)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ (__v16sf)_mm512_undefined_ps(), \
+ (__mmask16)-1, \
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_roundscale_ps(A, B, C, imm) __extension__ ({\
+#define _mm512_mask_roundscale_ps(A, B, C, imm) \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(C), (int)(imm), \
(__v16sf)(__m512)(A), (__mmask16)(B), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_roundscale_ps(A, B, imm) __extension__ ({\
+#define _mm512_maskz_roundscale_ps(A, B, imm) \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(B), (int)(imm), \
(__v16sf)_mm512_setzero_ps(), \
(__mmask16)(A), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_roundscale_round_ps(A, B, C, imm, R) __extension__ ({ \
+#define _mm512_mask_roundscale_round_ps(A, B, C, imm, R) \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(C), (int)(imm), \
(__v16sf)(__m512)(A), (__mmask16)(B), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_roundscale_round_ps(A, B, imm, R) __extension__ ({ \
+#define _mm512_maskz_roundscale_round_ps(A, B, imm, R) \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(B), (int)(imm), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(A), (int)(R)); })
+ (__mmask16)(A), (int)(R))
-#define _mm512_roundscale_round_ps(A, imm, R) __extension__ ({ \
+#define _mm512_roundscale_round_ps(A, imm, R) \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(A), (int)(imm), \
(__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_roundscale_pd(A, B) __extension__ ({ \
+#define _mm512_roundscale_pd(A, B) \
(__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(__m512d)(A), (int)(B), \
- (__v8df)(__m512d)(A), (__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ (__v8df)_mm512_undefined_pd(), \
+ (__mmask8)-1, \
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_roundscale_pd(A, B, C, imm) __extension__ ({\
+#define _mm512_mask_roundscale_pd(A, B, C, imm) \
(__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(__m512d)(C), (int)(imm), \
(__v8df)(__m512d)(A), (__mmask8)(B), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_roundscale_pd(A, B, imm) __extension__ ({\
+#define _mm512_maskz_roundscale_pd(A, B, imm) \
(__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(__m512d)(B), (int)(imm), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)(A), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_roundscale_round_pd(A, B, C, imm, R) __extension__ ({ \
+#define _mm512_mask_roundscale_round_pd(A, B, C, imm, R) \
(__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(__m512d)(C), (int)(imm), \
(__v8df)(__m512d)(A), (__mmask8)(B), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_roundscale_round_pd(A, B, imm, R) __extension__ ({ \
+#define _mm512_maskz_roundscale_round_pd(A, B, imm, R) \
(__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(__m512d)(B), (int)(imm), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(A), (int)(R)); })
+ (__mmask8)(A), (int)(R))
-#define _mm512_roundscale_round_pd(A, imm, R) __extension__ ({ \
+#define _mm512_roundscale_round_pd(A, imm, R) \
(__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(__m512d)(A), (int)(imm), \
(__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_fmadd_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_fmadd_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(C), (__mmask8)-1, \
- (int)(R)); })
+ (__v8df)(__m512d)(C), \
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_fmadd_round_pd(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmadd_round_pd(A, U, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_mask3_fmadd_round_pd(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmadd_round_pd(A, B, C, U, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask3((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_fmadd_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmadd_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_maskz((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_fmsub_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_fmsub_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_fmsub_round_pd(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmsub_round_pd(A, U, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_fmsub_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmsub_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_maskz((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_fnmadd_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_fnmadd_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask(-(__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(C), (__mmask8)-1, \
- (int)(R)); })
+ (__v8df)(__m512d)(C), \
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask3_fnmadd_round_pd(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fnmadd_round_pd(A, B, C, U, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask3(-(__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_fnmadd_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fnmadd_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_maskz(-(__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_fnmsub_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_fnmsub_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_mask(-(__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_maskz_fnmsub_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fnmsub_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddpd512_maskz(-(__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
@@ -2716,7 +2527,7 @@ _mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
@@ -2726,7 +2537,7 @@ _mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
{
return (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) __A,
@@ -2736,7 +2547,7 @@ _mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A,
@@ -2746,7 +2557,7 @@ _mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
@@ -2756,7 +2567,7 @@ _mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
@@ -2766,7 +2577,7 @@ _mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A,
@@ -2776,17 +2587,17 @@ _mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C)
{
- return (__m512d) __builtin_ia32_vfmaddpd512_mask (-(__v8df) __A,
- (__v8df) __B,
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ -(__v8df) __B,
(__v8df) __C,
(__mmask8) -1,
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
{
return (__m512d) __builtin_ia32_vfmaddpd512_mask3 (-(__v8df) __A,
@@ -2796,7 +2607,7 @@ _mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A,
@@ -2806,17 +2617,17 @@ _mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C)
{
- return (__m512d) __builtin_ia32_vfmaddpd512_mask (-(__v8df) __A,
- (__v8df) __B,
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ -(__v8df) __B,
-(__v8df) __C,
(__mmask8) -1,
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A,
@@ -2826,91 +2637,91 @@ _mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_fmadd_round_ps(A, B, C, R) __extension__ ({ \
+#define _mm512_fmadd_round_ps(A, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(C), (__mmask16)-1, \
- (int)(R)); })
+ (__v16sf)(__m512)(C), \
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_fmadd_round_ps(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmadd_round_ps(A, U, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_mask3_fmadd_round_ps(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmadd_round_ps(A, B, C, U, R) \
(__m512)__builtin_ia32_vfmaddps512_mask3((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_fmadd_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmadd_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_maskz((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_fmsub_round_ps(A, B, C, R) __extension__ ({ \
+#define _mm512_fmsub_round_ps(A, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_fmsub_round_ps(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmsub_round_ps(A, U, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_fmsub_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmsub_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_maskz((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_fnmadd_round_ps(A, B, C, R) __extension__ ({ \
- (__m512)__builtin_ia32_vfmaddps512_mask(-(__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(C), (__mmask16)-1, \
- (int)(R)); })
+#define _mm512_fnmadd_round_ps(A, B, C, R) \
+ (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
+ -(__v16sf)(__m512)(B), \
+ (__v16sf)(__m512)(C), \
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask3_fnmadd_round_ps(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fnmadd_round_ps(A, B, C, U, R) \
(__m512)__builtin_ia32_vfmaddps512_mask3(-(__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_fnmadd_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fnmadd_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_maskz(-(__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_fnmsub_round_ps(A, B, C, R) __extension__ ({ \
- (__m512)__builtin_ia32_vfmaddps512_mask(-(__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
+#define _mm512_fnmsub_round_ps(A, B, C, R) \
+ (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
+ -(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_maskz_fnmsub_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fnmsub_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_vfmaddps512_maskz(-(__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
@@ -2920,7 +2731,7 @@ _mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
@@ -2930,7 +2741,7 @@ _mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
{
return (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) __A,
@@ -2940,7 +2751,7 @@ _mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A,
@@ -2950,7 +2761,7 @@ _mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
@@ -2960,7 +2771,7 @@ _mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
@@ -2970,7 +2781,7 @@ _mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A,
@@ -2980,17 +2791,17 @@ _mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C)
{
- return (__m512) __builtin_ia32_vfmaddps512_mask (-(__v16sf) __A,
- (__v16sf) __B,
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ -(__v16sf) __B,
(__v16sf) __C,
(__mmask16) -1,
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
{
return (__m512) __builtin_ia32_vfmaddps512_mask3 (-(__v16sf) __A,
@@ -3000,7 +2811,7 @@ _mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A,
@@ -3010,17 +2821,17 @@ _mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C)
{
- return (__m512) __builtin_ia32_vfmaddps512_mask (-(__v16sf) __A,
- (__v16sf) __B,
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ -(__v16sf) __B,
-(__v16sf) __C,
(__mmask16) -1,
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A,
@@ -3030,96 +2841,96 @@ _mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_fmaddsub_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_fmaddsub_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_fmaddsub_round_pd(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmaddsub_round_pd(A, U, B, C, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_mask3_fmaddsub_round_pd(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmaddsub_round_pd(A, B, C, U, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_mask3((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_fmaddsub_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmaddsub_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_maskz((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_fmsubadd_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_fmsubadd_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_fmsubadd_round_pd(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmsubadd_round_pd(A, U, B, C, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_fmsubadd_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmsubadd_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_vfmaddsubpd512_maskz((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
-(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
@@ -3129,7 +2940,7 @@ _mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
@@ -3139,7 +2950,7 @@ _mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A,
@@ -3149,56 +2960,56 @@ _mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_fmaddsub_round_ps(A, B, C, R) __extension__ ({ \
+#define _mm512_fmaddsub_round_ps(A, B, C, R) \
(__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_fmaddsub_round_ps(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmaddsub_round_ps(A, U, B, C, R) \
(__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_mask3_fmaddsub_round_ps(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmaddsub_round_ps(A, B, C, U, R) \
(__m512)__builtin_ia32_vfmaddsubps512_mask3((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_fmaddsub_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmaddsub_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_vfmaddsubps512_maskz((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_fmsubadd_round_ps(A, B, C, R) __extension__ ({ \
+#define _mm512_fmsubadd_round_ps(A, B, C, R) \
(__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_fmsubadd_round_ps(A, U, B, C, R) __extension__ ({ \
+#define _mm512_mask_fmsubadd_round_ps(A, U, B, C, R) \
(__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_fmsubadd_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_fmsubadd_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_vfmaddsubps512_maskz((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
-(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
@@ -3208,7 +3019,7 @@ _mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
@@ -3218,7 +3029,7 @@ _mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
{
return (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) __A,
@@ -3228,7 +3039,7 @@ _mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A,
@@ -3238,7 +3049,7 @@ _mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
@@ -3248,7 +3059,7 @@ _mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
@@ -3258,7 +3069,7 @@ _mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
{
return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A,
@@ -3268,337 +3079,309 @@ _mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask3_fmsub_round_pd(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmsub_round_pd(A, B, C, U, R) \
(__m512d)__builtin_ia32_vfmsubpd512_mask3((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
{
- return (__m512d) __builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask3_fmsub_round_ps(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmsub_round_ps(A, B, C, U, R) \
(__m512)__builtin_ia32_vfmsubps512_mask3((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
-
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
{
- return (__m512) __builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __C,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask3_fmsubadd_round_pd(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmsubadd_round_pd(A, B, C, U, R) \
(__m512d)__builtin_ia32_vfmsubaddpd512_mask3((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
{
- return (__m512d) __builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask3_fmsubadd_round_ps(A, B, C, U, R) __extension__ ({ \
+#define _mm512_mask3_fmsubadd_round_ps(A, B, C, U, R) \
(__m512)__builtin_ia32_vfmsubaddps512_mask3((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
{
- return (__m512) __builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __C,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask_fnmadd_round_pd(A, U, B, C, R) __extension__ ({ \
- (__m512d)__builtin_ia32_vfnmaddpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+#define _mm512_mask_fnmadd_round_pd(A, U, B, C, R) \
+ (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \
+ -(__v8df)(__m512d)(B), \
+ (__v8df)(__m512d)(C), \
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
- return (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ -(__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask_fnmadd_round_ps(A, U, B, C, R) __extension__ ({ \
- (__m512)__builtin_ia32_vfnmaddps512_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+#define _mm512_mask_fnmadd_round_ps(A, U, B, C, R) \
+ (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
+ -(__v16sf)(__m512)(B), \
+ (__v16sf)(__m512)(C), \
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
{
- return (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __C,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ -(__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_mask_fnmsub_round_pd(A, U, B, C, R) __extension__ ({ \
- (__m512d)__builtin_ia32_vfnmsubpd512_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+#define _mm512_mask_fnmsub_round_pd(A, U, B, C, R) \
+ (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \
+ -(__v8df)(__m512d)(B), \
+ -(__v8df)(__m512d)(C), \
+ (__mmask8)(U), (int)(R))
-#define _mm512_mask3_fnmsub_round_pd(A, B, C, U, R) __extension__ ({ \
- (__m512d)__builtin_ia32_vfnmsubpd512_mask3((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), \
- (__v8df)(__m512d)(C), \
- (__mmask8)(U), (int)(R)); })
+#define _mm512_mask3_fnmsub_round_pd(A, B, C, U, R) \
+ (__m512d)__builtin_ia32_vfmsubpd512_mask3(-(__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), \
+ (__v8df)(__m512d)(C), \
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_fnmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
- return (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) __A,
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ -(__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
+_mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
+{
+ return (__m512d) __builtin_ia32_vfmsubpd512_mask3 (-(__v8df) __A,
(__v8df) __B,
(__v8df) __C,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
-{
- return (__m512d) __builtin_ia32_vfnmsubpd512_mask3 ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
-}
+#define _mm512_mask_fnmsub_round_ps(A, U, B, C, R) \
+ (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \
+ -(__v16sf)(__m512)(B), \
+ -(__v16sf)(__m512)(C), \
+ (__mmask16)(U), (int)(R))
-#define _mm512_mask_fnmsub_round_ps(A, U, B, C, R) __extension__ ({ \
- (__m512)__builtin_ia32_vfnmsubps512_mask((__v16sf)(__m512)(A), \
+
+#define _mm512_mask3_fnmsub_round_ps(A, B, C, U, R) \
+ (__m512)__builtin_ia32_vfmsubps512_mask3(-(__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
-
-
-#define _mm512_mask3_fnmsub_round_ps(A, B, C, U, R) __extension__ ({ \
- (__m512)__builtin_ia32_vfnmsubps512_mask3((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- (__v16sf)(__m512)(C), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_fnmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
{
- return (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __C,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ -(__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask3_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
{
- return (__m512) __builtin_ia32_vfnmsubps512_mask3 ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __C,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_vfmsubps512_mask3 (-(__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
/* Vector permutations */
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_permutex2var_epi32(__m512i __A, __m512i __I, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2vard512_mask ((__v16si) __I
- /* idx */ ,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_vpermi2vard512((__v16si)__A, (__v16si) __I,
+ (__v16si) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_permutex2var_epi32(__m512i __A, __mmask16 __U, __m512i __I,
+ __m512i __B)
+{
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_permutex2var_epi32(__A, __I, __B),
+ (__v16si)__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_permutex2var_epi32 (__m512i __A, __mmask16 __U,
- __m512i __I, __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask2_permutex2var_epi32(__m512i __A, __m512i __I, __mmask16 __U,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2vard512_mask ((__v16si) __I
- /* idx */ ,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_permutex2var_epi32(__A, __I, __B),
+ (__v16si)__I);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_permutex2var_epi32 (__mmask16 __U, __m512i __A,
- __m512i __I, __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_maskz_permutex2var_epi32(__mmask16 __U, __m512i __A, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2vard512_maskz ((__v16si) __I
- /* idx */ ,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_permutex2var_epi32(__A, __I, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_permutex2var_epi64(__m512i __A, __m512i __I, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varq512_mask ((__v8di) __I
- /* idx */ ,
- (__v8di) __A,
- (__v8di) __B,
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_vpermi2varq512((__v8di)__A, (__v8di) __I,
+ (__v8di) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_permutex2var_epi64 (__m512i __A, __mmask8 __U, __m512i __I,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_permutex2var_epi64(__m512i __A, __mmask8 __U, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varq512_mask ((__v8di) __I
- /* idx */ ,
- (__v8di) __A,
- (__v8di) __B,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_permutex2var_epi64(__A, __I, __B),
+ (__v8di)__A);
}
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask2_permutex2var_epi64(__m512i __A, __m512i __I, __mmask8 __U,
+ __m512i __B)
+{
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_permutex2var_epi64(__A, __I, __B),
+ (__v8di)__I);
+}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_permutex2var_epi64 (__mmask8 __U, __m512i __A,
- __m512i __I, __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varq512_maskz ((__v8di) __I
- /* idx */ ,
- (__v8di) __A,
- (__v8di) __B,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_permutex2var_epi64(__A, __I, __B),
+ (__v8di)_mm512_setzero_si512());
}
-#define _mm512_alignr_epi64(A, B, I) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v8di)(__m512i)(B), \
- (__v8di)(__m512i)(A), \
- ((int)(I) & 0x7) + 0, \
- ((int)(I) & 0x7) + 1, \
- ((int)(I) & 0x7) + 2, \
- ((int)(I) & 0x7) + 3, \
- ((int)(I) & 0x7) + 4, \
- ((int)(I) & 0x7) + 5, \
- ((int)(I) & 0x7) + 6, \
- ((int)(I) & 0x7) + 7); })
+#define _mm512_alignr_epi64(A, B, I) \
+ (__m512i)__builtin_ia32_alignq512((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), (int)(I))
-#define _mm512_mask_alignr_epi64(W, U, A, B, imm) __extension__({\
+#define _mm512_mask_alignr_epi64(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_alignr_epi64((A), (B), (imm)), \
- (__v8di)(__m512i)(W)); })
+ (__v8di)(__m512i)(W))
-#define _mm512_maskz_alignr_epi64(U, A, B, imm) __extension__({\
+#define _mm512_maskz_alignr_epi64(U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_alignr_epi64((A), (B), (imm)), \
- (__v8di)_mm512_setzero_si512()); })
-
-#define _mm512_alignr_epi32(A, B, I) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v16si)(__m512i)(B), \
- (__v16si)(__m512i)(A), \
- ((int)(I) & 0xf) + 0, \
- ((int)(I) & 0xf) + 1, \
- ((int)(I) & 0xf) + 2, \
- ((int)(I) & 0xf) + 3, \
- ((int)(I) & 0xf) + 4, \
- ((int)(I) & 0xf) + 5, \
- ((int)(I) & 0xf) + 6, \
- ((int)(I) & 0xf) + 7, \
- ((int)(I) & 0xf) + 8, \
- ((int)(I) & 0xf) + 9, \
- ((int)(I) & 0xf) + 10, \
- ((int)(I) & 0xf) + 11, \
- ((int)(I) & 0xf) + 12, \
- ((int)(I) & 0xf) + 13, \
- ((int)(I) & 0xf) + 14, \
- ((int)(I) & 0xf) + 15); })
-
-#define _mm512_mask_alignr_epi32(W, U, A, B, imm) __extension__ ({\
+ (__v8di)_mm512_setzero_si512())
+
+#define _mm512_alignr_epi32(A, B, I) \
+ (__m512i)__builtin_ia32_alignd512((__v16si)(__m512i)(A), \
+ (__v16si)(__m512i)(B), (int)(I))
+
+#define _mm512_mask_alignr_epi32(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_alignr_epi32((A), (B), (imm)), \
- (__v16si)(__m512i)(W)); })
+ (__v16si)(__m512i)(W))
-#define _mm512_maskz_alignr_epi32(U, A, B, imm) __extension__({\
+#define _mm512_maskz_alignr_epi32(U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_alignr_epi32((A), (B), (imm)), \
- (__v16si)_mm512_setzero_si512()); })
+ (__v16si)_mm512_setzero_si512())
/* Vector Extract */
-#define _mm512_extractf64x4_pd(A, I) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v8df)(__m512d)(A), \
- (__v8df)_mm512_undefined_pd(), \
- ((I) & 1) ? 4 : 0, \
- ((I) & 1) ? 5 : 1, \
- ((I) & 1) ? 6 : 2, \
- ((I) & 1) ? 7 : 3); })
-
-#define _mm512_mask_extractf64x4_pd(W, U, A, imm) __extension__ ({\
- (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
- (__v4df)_mm512_extractf64x4_pd((A), (imm)), \
- (__v4df)(W)); })
-
-#define _mm512_maskz_extractf64x4_pd(U, A, imm) __extension__ ({\
- (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
- (__v4df)_mm512_extractf64x4_pd((A), (imm)), \
- (__v4df)_mm256_setzero_pd()); })
-
-#define _mm512_extractf32x4_ps(A, I) __extension__ ({ \
- (__m128)__builtin_shufflevector((__v16sf)(__m512)(A), \
- (__v16sf)_mm512_undefined_ps(), \
- 0 + ((I) & 0x3) * 4, \
- 1 + ((I) & 0x3) * 4, \
- 2 + ((I) & 0x3) * 4, \
- 3 + ((I) & 0x3) * 4); })
-
-#define _mm512_mask_extractf32x4_ps(W, U, A, imm) __extension__ ({\
- (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
- (__v4sf)_mm512_extractf32x4_ps((A), (imm)), \
- (__v4sf)(W)); })
-
-#define _mm512_maskz_extractf32x4_ps(U, A, imm) __extension__ ({\
- (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
- (__v4sf)_mm512_extractf32x4_ps((A), (imm)), \
- (__v4sf)_mm_setzero_ps()); })
+#define _mm512_extractf64x4_pd(A, I) \
+ (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(I), \
+ (__v4df)_mm256_undefined_pd(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extractf64x4_pd(W, U, A, imm) \
+ (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(imm), \
+ (__v4df)(__m256d)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extractf64x4_pd(U, A, imm) \
+ (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(imm), \
+ (__v4df)_mm256_setzero_pd(), \
+ (__mmask8)(U))
+
+#define _mm512_extractf32x4_ps(A, I) \
+ (__m128)__builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(I), \
+ (__v4sf)_mm_undefined_ps(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extractf32x4_ps(W, U, A, imm) \
+ (__m128)__builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(imm), \
+ (__v4sf)(__m128)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extractf32x4_ps(U, A, imm) \
+ (__m128)__builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(imm), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)(U))
/* Vector Blend */
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_blend_pd(__mmask8 __U, __m512d __A, __m512d __W)
{
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
@@ -3606,7 +3389,7 @@ _mm512_mask_blend_pd(__mmask8 __U, __m512d __A, __m512d __W)
(__v8df) __A);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_blend_ps(__mmask16 __U, __m512 __A, __m512 __W)
{
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
@@ -3614,7 +3397,7 @@ _mm512_mask_blend_ps(__mmask16 __U, __m512 __A, __m512 __W)
(__v16sf) __A);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_blend_epi64(__mmask8 __U, __m512i __A, __m512i __W)
{
return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __U,
@@ -3622,7 +3405,7 @@ _mm512_mask_blend_epi64(__mmask8 __U, __m512i __A, __m512i __W)
(__v8di) __A);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
{
return (__m512i) __builtin_ia32_selectd_512 ((__mmask16) __U,
@@ -3632,15 +3415,15 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
/* Compare */
-#define _mm512_cmp_round_ps_mask(A, B, P, R) __extension__ ({ \
+#define _mm512_cmp_round_ps_mask(A, B, P, R) \
(__mmask16)__builtin_ia32_cmpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(P), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cmp_round_ps_mask(U, A, B, P, R) __extension__ ({ \
+#define _mm512_mask_cmp_round_ps_mask(U, A, B, P, R) \
(__mmask16)__builtin_ia32_cmpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), (int)(P), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
#define _mm512_cmp_ps_mask(A, B, P) \
_mm512_cmp_round_ps_mask((A), (B), (P), _MM_FROUND_CUR_DIRECTION)
@@ -3687,15 +3470,15 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
#define _mm512_mask_cmpord_ps_mask(k, A, B) \
_mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_ORD_Q)
-#define _mm512_cmp_round_pd_mask(A, B, P, R) __extension__ ({ \
+#define _mm512_cmp_round_pd_mask(A, B, P, R) \
(__mmask8)__builtin_ia32_cmppd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(P), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cmp_round_pd_mask(U, A, B, P, R) __extension__ ({ \
+#define _mm512_mask_cmp_round_pd_mask(U, A, B, P, R) \
(__mmask8)__builtin_ia32_cmppd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(P), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
#define _mm512_cmp_pd_mask(A, B, P) \
_mm512_cmp_round_pd_mask((A), (B), (P), _MM_FROUND_CUR_DIRECTION)
@@ -3744,23 +3527,23 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
/* Conversion */
-#define _mm512_cvtt_roundps_epu32(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundps_epu32(A, R) \
(__m512i)__builtin_ia32_cvttps2udq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_undefined_epi32(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvtt_roundps_epu32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundps_epu32(W, U, A, R) \
(__m512i)__builtin_ia32_cvttps2udq512_mask((__v16sf)(__m512)(A), \
(__v16si)(__m512i)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundps_epu32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundps_epu32(U, A, R) \
(__m512i)__builtin_ia32_cvttps2udq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_cvttps_epu32(__m512 __A)
{
return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A,
@@ -3770,7 +3553,7 @@ _mm512_cvttps_epu32(__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttps_epu32 (__m512i __W, __mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A,
@@ -3779,7 +3562,7 @@ _mm512_mask_cvttps_epu32 (__m512i __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttps_epu32 (__mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A,
@@ -3788,70 +3571,65 @@ _mm512_maskz_cvttps_epu32 (__mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundepi32_ps(A, R) __extension__ ({ \
+#define _mm512_cvt_roundepi32_ps(A, R) \
(__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(__m512i)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvt_roundepi32_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundepi32_ps(W, U, A, R) \
(__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(__m512i)(A), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvt_roundepi32_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundepi32_ps(U, A, R) \
(__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(__m512i)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_cvt_roundepu32_ps(A, R) __extension__ ({ \
+#define _mm512_cvt_roundepu32_ps(A, R) \
(__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(__m512i)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvt_roundepu32_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundepu32_ps(W, U, A, R) \
(__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(__m512i)(A), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvt_roundepu32_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundepu32_ps(U, A, R) \
(__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(__m512i)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_cvtepu32_ps (__m512i __A)
{
- return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A,
- (__v16sf) _mm512_undefined_ps (),
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_convertvector((__v16su)__A, __v16sf);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu32_ps (__m512 __W, __mmask16 __U, __m512i __A)
{
- return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_cvtepu32_ps(__A),
+ (__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A)
{
- return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A,
- (__v16sf) _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_cvtepu32_ps(__A),
+ (__v16sf)_mm512_setzero_ps());
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtepi32_pd(__m256i __A)
{
return (__m512d)__builtin_convertvector((__v8si)__A, __v8df);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -3859,7 +3637,7 @@ _mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A)
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -3867,52 +3645,47 @@ _mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A)
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtepi32lo_pd(__m512i __A)
{
return (__m512d) _mm512_cvtepi32_pd(_mm512_castsi512_si256(__A));
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32lo_pd(__m512d __W, __mmask8 __U,__m512i __A)
{
return (__m512d) _mm512_mask_cvtepi32_pd(__W, __U, _mm512_castsi512_si256(__A));
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_cvtepi32_ps (__m512i __A)
{
- return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A,
- (__v16sf) _mm512_undefined_ps (),
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_convertvector((__v16si)__A, __v16sf);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_ps (__m512 __W, __mmask16 __U, __m512i __A)
{
- return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_cvtepi32_ps(__A),
+ (__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A)
{
- return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A,
- (__v16sf) _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_cvtepi32_ps(__A),
+ (__v16sf)_mm512_setzero_ps());
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtepu32_pd(__m256i __A)
{
return (__m512d)__builtin_convertvector((__v8su)__A, __v8df);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -3920,7 +3693,7 @@ _mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A)
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -3928,34 +3701,34 @@ _mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A)
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtepu32lo_pd(__m512i __A)
{
return (__m512d) _mm512_cvtepu32_pd(_mm512_castsi512_si256(__A));
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu32lo_pd(__m512d __W, __mmask8 __U,__m512i __A)
{
return (__m512d) _mm512_mask_cvtepu32_pd(__W, __U, _mm512_castsi512_si256(__A));
}
-#define _mm512_cvt_roundpd_ps(A, R) __extension__ ({ \
+#define _mm512_cvt_roundpd_ps(A, R) \
(__m256)__builtin_ia32_cvtpd2ps512_mask((__v8df)(__m512d)(A), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundpd_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundpd_ps(W, U, A, R) \
(__m256)__builtin_ia32_cvtpd2ps512_mask((__v8df)(__m512d)(A), \
(__v8sf)(__m256)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_cvt_roundpd_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundpd_ps(U, A, R) \
(__m256)__builtin_ia32_cvtpd2ps512_mask((__v8df)(__m512d)(A), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_cvtpd_ps (__m512d __A)
{
return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A,
@@ -3964,7 +3737,7 @@ _mm512_cvtpd_ps (__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpd_ps (__m256 __W, __mmask8 __U, __m512d __A)
{
return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A,
@@ -3973,7 +3746,7 @@ _mm512_mask_cvtpd_ps (__m256 __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A)
{
return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A,
@@ -3982,7 +3755,7 @@ _mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_cvtpd_pslo (__m512d __A)
{
return (__m512) __builtin_shufflevector((__v8sf) _mm512_cvtpd_ps(__A),
@@ -3990,7 +3763,7 @@ _mm512_cvtpd_pslo (__m512d __A)
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpd_pslo (__m512 __W, __mmask8 __U,__m512d __A)
{
return (__m512) __builtin_shufflevector (
@@ -4000,53 +3773,53 @@ _mm512_mask_cvtpd_pslo (__m512 __W, __mmask8 __U,__m512d __A)
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
}
-#define _mm512_cvt_roundps_ph(A, I) __extension__ ({ \
+#define _mm512_cvt_roundps_ph(A, I) \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)_mm256_undefined_si256(), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm512_mask_cvt_roundps_ph(U, W, A, I) __extension__ ({ \
+#define _mm512_mask_cvt_roundps_ph(U, W, A, I) \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)(__m256i)(U), \
- (__mmask16)(W)); })
+ (__mmask16)(W))
-#define _mm512_maskz_cvt_roundps_ph(W, A, I) __extension__ ({ \
+#define _mm512_maskz_cvt_roundps_ph(W, A, I) \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)_mm256_setzero_si256(), \
- (__mmask16)(W)); })
+ (__mmask16)(W))
-#define _mm512_cvtps_ph(A, I) __extension__ ({ \
+#define _mm512_cvtps_ph(A, I) \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)_mm256_setzero_si256(), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm512_mask_cvtps_ph(U, W, A, I) __extension__ ({ \
+#define _mm512_mask_cvtps_ph(U, W, A, I) \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)(__m256i)(U), \
- (__mmask16)(W)); })
+ (__mmask16)(W))
-#define _mm512_maskz_cvtps_ph(W, A, I) __extension__ ({\
+#define _mm512_maskz_cvtps_ph(W, A, I) \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)_mm256_setzero_si256(), \
- (__mmask16)(W)); })
+ (__mmask16)(W))
-#define _mm512_cvt_roundph_ps(A, R) __extension__ ({ \
+#define _mm512_cvt_roundph_ps(A, R) \
(__m512)__builtin_ia32_vcvtph2ps512_mask((__v16hi)(__m256i)(A), \
(__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvt_roundph_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundph_ps(W, U, A, R) \
(__m512)__builtin_ia32_vcvtph2ps512_mask((__v16hi)(__m256i)(A), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvt_roundph_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundph_ps(U, A, R) \
(__m512)__builtin_ia32_vcvtph2ps512_mask((__v16hi)(__m256i)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_cvtph_ps(__m256i __A)
{
return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A,
@@ -4056,7 +3829,7 @@ _mm512_cvtph_ps(__m256i __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtph_ps (__m512 __W, __mmask16 __U, __m256i __A)
{
return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A,
@@ -4065,7 +3838,7 @@ _mm512_mask_cvtph_ps (__m512 __W, __mmask16 __U, __m256i __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtph_ps (__mmask16 __U, __m256i __A)
{
return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A,
@@ -4074,22 +3847,22 @@ _mm512_maskz_cvtph_ps (__mmask16 __U, __m256i __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvtt_roundpd_epi32(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundpd_epi32(A, R) \
(__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvtt_roundpd_epi32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundpd_epi32(W, U, A, R) \
(__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df)(__m512d)(A), \
(__v8si)(__m256i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundpd_epi32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundpd_epi32(U, A, R) \
(__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline __m256i __DEFAULT_FN_ATTRS
+static __inline __m256i __DEFAULT_FN_ATTRS512
_mm512_cvttpd_epi32(__m512d __a)
{
return (__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df) __a,
@@ -4098,7 +3871,7 @@ _mm512_cvttpd_epi32(__m512d __a)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A,
@@ -4107,7 +3880,7 @@ _mm512_mask_cvttpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttpd_epi32 (__mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A,
@@ -4116,22 +3889,22 @@ _mm512_maskz_cvttpd_epi32 (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvtt_roundps_epi32(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundps_epi32(A, R) \
(__m512i)__builtin_ia32_cvttps2dq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvtt_roundps_epi32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundps_epi32(W, U, A, R) \
(__m512i)__builtin_ia32_cvttps2dq512_mask((__v16sf)(__m512)(A), \
(__v16si)(__m512i)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundps_epi32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundps_epi32(U, A, R) \
(__m512i)__builtin_ia32_cvttps2dq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_cvttps_epi32(__m512 __a)
{
return (__m512i)
@@ -4140,7 +3913,7 @@ _mm512_cvttps_epi32(__m512 __a)
(__mmask16) -1, _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttps_epi32 (__m512i __W, __mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A,
@@ -4149,7 +3922,7 @@ _mm512_mask_cvttps_epi32 (__m512i __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttps_epi32 (__mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A,
@@ -4158,22 +3931,22 @@ _mm512_maskz_cvttps_epi32 (__mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundps_epi32(A, R) __extension__ ({ \
+#define _mm512_cvt_roundps_epi32(A, R) \
(__m512i)__builtin_ia32_cvtps2dq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvt_roundps_epi32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundps_epi32(W, U, A, R) \
(__m512i)__builtin_ia32_cvtps2dq512_mask((__v16sf)(__m512)(A), \
(__v16si)(__m512i)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvt_roundps_epi32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundps_epi32(U, A, R) \
(__m512i)__builtin_ia32_cvtps2dq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtps_epi32 (__m512 __A)
{
return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A,
@@ -4182,7 +3955,7 @@ _mm512_cvtps_epi32 (__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtps_epi32 (__m512i __W, __mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A,
@@ -4191,7 +3964,7 @@ _mm512_mask_cvtps_epi32 (__m512i __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtps_epi32 (__mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A,
@@ -4201,22 +3974,22 @@ _mm512_maskz_cvtps_epi32 (__mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundpd_epi32(A, R) __extension__ ({ \
+#define _mm512_cvt_roundpd_epi32(A, R) \
(__m256i)__builtin_ia32_cvtpd2dq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundpd_epi32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundpd_epi32(W, U, A, R) \
(__m256i)__builtin_ia32_cvtpd2dq512_mask((__v8df)(__m512d)(A), \
(__v8si)(__m256i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundpd_epi32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundpd_epi32(U, A, R) \
(__m256i)__builtin_ia32_cvtpd2dq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtpd_epi32 (__m512d __A)
{
return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A,
@@ -4226,7 +3999,7 @@ _mm512_cvtpd_epi32 (__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A,
@@ -4235,7 +4008,7 @@ _mm512_mask_cvtpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtpd_epi32 (__mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A,
@@ -4245,32 +4018,32 @@ _mm512_maskz_cvtpd_epi32 (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundps_epu32(A, R) __extension__ ({ \
+#define _mm512_cvt_roundps_epu32(A, R) \
(__m512i)__builtin_ia32_cvtps2udq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_cvt_roundps_epu32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundps_epu32(W, U, A, R) \
(__m512i)__builtin_ia32_cvtps2udq512_mask((__v16sf)(__m512)(A), \
(__v16si)(__m512i)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_cvt_roundps_epu32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundps_epu32(U, A, R) \
(__m512i)__builtin_ia32_cvtps2udq512_mask((__v16sf)(__m512)(A), \
(__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtps_epu32 ( __m512 __A)
{
return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A,\
(__v16si)\
- _mm512_undefined_epi32 (),\
+ _mm512_undefined_epi32 (),
(__mmask16) -1,\
- _MM_FROUND_CUR_DIRECTION);\
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtps_epu32 (__m512i __W, __mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A,
@@ -4279,7 +4052,7 @@ _mm512_mask_cvtps_epu32 (__m512i __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtps_epu32 ( __mmask16 __U, __m512 __A)
{
return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A,
@@ -4289,22 +4062,22 @@ _mm512_maskz_cvtps_epu32 ( __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_cvt_roundpd_epu32(A, R) __extension__ ({ \
+#define _mm512_cvt_roundpd_epu32(A, R) \
(__m256i)__builtin_ia32_cvtpd2udq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundpd_epu32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundpd_epu32(W, U, A, R) \
(__m256i)__builtin_ia32_cvtpd2udq512_mask((__v8df)(__m512d)(A), \
- (__v8si)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__v8si)(__m256i)(W), \
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundpd_epu32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundpd_epu32(U, A, R) \
(__m256i)__builtin_ia32_cvtpd2udq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtpd_epu32 (__m512d __A)
{
return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A,
@@ -4314,7 +4087,7 @@ _mm512_cvtpd_epu32 (__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A,
@@ -4323,7 +4096,7 @@ _mm512_mask_cvtpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtpd_epu32 (__mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A,
@@ -4333,13 +4106,13 @@ _mm512_maskz_cvtpd_epu32 (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ double __DEFAULT_FN_ATTRS
+static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_cvtsd_f64(__m512d __a)
{
return __a[0];
}
-static __inline__ float __DEFAULT_FN_ATTRS
+static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_cvtss_f32(__m512 __a)
{
return __a[0];
@@ -4347,14 +4120,14 @@ _mm512_cvtss_f32(__m512 __a)
/* Unpack and Interleave */
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_unpackhi_pd(__m512d __a, __m512d __b)
{
return (__m512d)__builtin_shufflevector((__v8df)__a, (__v8df)__b,
1, 9, 1+2, 9+2, 1+4, 9+4, 1+6, 9+6);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_unpackhi_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -4362,7 +4135,7 @@ _mm512_mask_unpackhi_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_unpackhi_pd(__mmask8 __U, __m512d __A, __m512d __B)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -4370,14 +4143,14 @@ _mm512_maskz_unpackhi_pd(__mmask8 __U, __m512d __A, __m512d __B)
(__v8df)_mm512_setzero_pd());
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_unpacklo_pd(__m512d __a, __m512d __b)
{
return (__m512d)__builtin_shufflevector((__v8df)__a, (__v8df)__b,
0, 8, 0+2, 8+2, 0+4, 8+4, 0+6, 8+6);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_unpacklo_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -4385,7 +4158,7 @@ _mm512_mask_unpacklo_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_unpacklo_pd (__mmask8 __U, __m512d __A, __m512d __B)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
@@ -4393,7 +4166,7 @@ _mm512_maskz_unpacklo_pd (__mmask8 __U, __m512d __A, __m512d __B)
(__v8df)_mm512_setzero_pd());
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_unpackhi_ps(__m512 __a, __m512 __b)
{
return (__m512)__builtin_shufflevector((__v16sf)__a, (__v16sf)__b,
@@ -4403,7 +4176,7 @@ _mm512_unpackhi_ps(__m512 __a, __m512 __b)
2+12, 18+12, 3+12, 19+12);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_unpackhi_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16) __U,
@@ -4411,7 +4184,7 @@ _mm512_mask_unpackhi_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_unpackhi_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16) __U,
@@ -4419,7 +4192,7 @@ _mm512_maskz_unpackhi_ps (__mmask16 __U, __m512 __A, __m512 __B)
(__v16sf)_mm512_setzero_ps());
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_unpacklo_ps(__m512 __a, __m512 __b)
{
return (__m512)__builtin_shufflevector((__v16sf)__a, (__v16sf)__b,
@@ -4429,7 +4202,7 @@ _mm512_unpacklo_ps(__m512 __a, __m512 __b)
0+12, 16+12, 1+12, 17+12);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_unpacklo_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16) __U,
@@ -4437,7 +4210,7 @@ _mm512_mask_unpacklo_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_unpacklo_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16) __U,
@@ -4445,7 +4218,7 @@ _mm512_maskz_unpacklo_ps (__mmask16 __U, __m512 __A, __m512 __B)
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpackhi_epi32(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_shufflevector((__v16si)__A, (__v16si)__B,
@@ -4455,7 +4228,7 @@ _mm512_unpackhi_epi32(__m512i __A, __m512i __B)
2+12, 18+12, 3+12, 19+12);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpackhi_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U,
@@ -4463,7 +4236,7 @@ _mm512_mask_unpackhi_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpackhi_epi32(__mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U,
@@ -4471,7 +4244,7 @@ _mm512_maskz_unpackhi_epi32(__mmask16 __U, __m512i __A, __m512i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpacklo_epi32(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_shufflevector((__v16si)__A, (__v16si)__B,
@@ -4481,7 +4254,7 @@ _mm512_unpacklo_epi32(__m512i __A, __m512i __B)
0+12, 16+12, 1+12, 17+12);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpacklo_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U,
@@ -4489,7 +4262,7 @@ _mm512_mask_unpacklo_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpacklo_epi32(__mmask16 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U,
@@ -4497,14 +4270,14 @@ _mm512_maskz_unpacklo_epi32(__mmask16 __U, __m512i __A, __m512i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpackhi_epi64(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_shufflevector((__v8di)__A, (__v8di)__B,
1, 9, 1+2, 9+2, 1+4, 9+4, 1+6, 9+6);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpackhi_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U,
@@ -4512,7 +4285,7 @@ _mm512_mask_unpackhi_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpackhi_epi64(__mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U,
@@ -4520,14 +4293,14 @@ _mm512_maskz_unpackhi_epi64(__mmask8 __U, __m512i __A, __m512i __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpacklo_epi64 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_shufflevector((__v8di)__A, (__v8di)__B,
0, 8, 0+2, 8+2, 0+4, 8+4, 0+6, 8+6);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpacklo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U,
@@ -4535,7 +4308,7 @@ _mm512_mask_unpacklo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U,
@@ -4546,16 +4319,16 @@ _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
/* SIMD load ops */
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_loadu_si512 (void const *__P)
{
- return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ struct __loadu_si512 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_si512*)__P)->__v;
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P,
@@ -4564,7 +4337,7 @@ _mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P)
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *)__P,
@@ -4573,7 +4346,7 @@ _mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *) __P,
@@ -4581,7 +4354,7 @@ _mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_loadu_epi64(__mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *)__P,
@@ -4590,7 +4363,7 @@ _mm512_maskz_loadu_epi64(__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_ps (__m512 __W, __mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_loadups512_mask ((const float *) __P,
@@ -4598,7 +4371,7 @@ _mm512_mask_loadu_ps (__m512 __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_loadu_ps(__mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_loadups512_mask ((const float *)__P,
@@ -4607,7 +4380,7 @@ _mm512_maskz_loadu_ps(__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_pd (__m512d __W, __mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_loadupd512_mask ((const double *) __P,
@@ -4615,7 +4388,7 @@ _mm512_mask_loadu_pd (__m512d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_loadu_pd(__mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_loadupd512_mask ((const double *)__P,
@@ -4624,7 +4397,7 @@ _mm512_maskz_loadu_pd(__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_loadu_pd(void const *__p)
{
struct __loadu_pd {
@@ -4633,7 +4406,7 @@ _mm512_loadu_pd(void const *__p)
return ((struct __loadu_pd*)__p)->__v;
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_loadu_ps(void const *__p)
{
struct __loadu_ps {
@@ -4642,16 +4415,13 @@ _mm512_loadu_ps(void const *__p)
return ((struct __loadu_ps*)__p)->__v;
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_load_ps(void const *__p)
{
- return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *)__p,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) -1);
+ return *(__m512*)__p;
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_load_ps (__m512 __W, __mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *) __P,
@@ -4659,7 +4429,7 @@ _mm512_mask_load_ps (__m512 __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_load_ps(__mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *)__P,
@@ -4668,16 +4438,13 @@ _mm512_maskz_load_ps(__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_load_pd(void const *__p)
{
- return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *)__p,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) -1);
+ return *(__m512d*)__p;
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_load_pd (__m512d __W, __mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *) __P,
@@ -4685,7 +4452,7 @@ _mm512_mask_load_pd (__m512d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_load_pd(__mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *)__P,
@@ -4694,19 +4461,19 @@ _mm512_maskz_load_pd(__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_load_si512 (void const *__P)
{
return *(__m512i *) __P;
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_load_epi32 (void const *__P)
{
return *(__m512i *) __P;
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_load_epi64 (void const *__P)
{
return *(__m512i *) __P;
@@ -4714,90 +4481,98 @@ _mm512_load_epi64 (void const *__P)
/* SIMD store ops */
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A)
{
__builtin_ia32_storedqudi512_mask ((long long *)__P, (__v8di) __A,
(__mmask8) __U);
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_storeu_si512 (void *__P, __m512i __A)
{
- __builtin_ia32_storedqusi512_mask ((int *) __P, (__v16si) __A,
- (__mmask16) -1);
+ struct __storeu_si512 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_si512*)__P)->__v = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_epi32(void *__P, __mmask16 __U, __m512i __A)
{
__builtin_ia32_storedqusi512_mask ((int *)__P, (__v16si) __A,
(__mmask16) __U);
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_pd(void *__P, __mmask8 __U, __m512d __A)
{
__builtin_ia32_storeupd512_mask ((double *)__P, (__v8df) __A, (__mmask8) __U);
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_storeu_pd(void *__P, __m512d __A)
{
- __builtin_ia32_storeupd512_mask((double *)__P, (__v8df)__A, (__mmask8)-1);
+ struct __storeu_pd {
+ __m512d __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_pd*)__P)->__v = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_ps(void *__P, __mmask16 __U, __m512 __A)
{
__builtin_ia32_storeups512_mask ((float *)__P, (__v16sf) __A,
(__mmask16) __U);
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_storeu_ps(void *__P, __m512 __A)
{
- __builtin_ia32_storeups512_mask((float *)__P, (__v16sf)__A, (__mmask16)-1);
+ struct __storeu_ps {
+ __m512 __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_ps*)__P)->__v = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_store_pd(void *__P, __mmask8 __U, __m512d __A)
{
__builtin_ia32_storeapd512_mask ((__v8df *)__P, (__v8df) __A, (__mmask8) __U);
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_store_pd(void *__P, __m512d __A)
{
*(__m512d*)__P = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_store_ps(void *__P, __mmask16 __U, __m512 __A)
{
__builtin_ia32_storeaps512_mask ((__v16sf *)__P, (__v16sf) __A,
(__mmask16) __U);
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_store_ps(void *__P, __m512 __A)
{
*(__m512*)__P = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_store_si512 (void *__P, __m512i __A)
{
*(__m512i *) __P = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_store_epi32 (void *__P, __m512i __A)
{
*(__m512i *) __P = __A;
}
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_store_epi64 (void *__P, __m512i __A)
{
*(__m512i *) __P = __A;
@@ -4805,7 +4580,7 @@ _mm512_store_epi64 (void *__P, __m512i __A)
/* Mask ops */
-static __inline __mmask16 __DEFAULT_FN_ATTRS
+static __inline __mmask16 __DEFAULT_FN_ATTRS512
_mm512_knot(__mmask16 __M)
{
return __builtin_ia32_knothi(__M);
@@ -4913,7 +4688,7 @@ _mm512_knot(__mmask16 __M)
#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
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepi8_epi32(__m128i __A)
{
/* This function always performs a signed extension, but __v16qi is a char
@@ -4921,7 +4696,7 @@ _mm512_cvtepi8_epi32(__m128i __A)
return (__m512i)__builtin_convertvector((__v16qs)__A, __v16si);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi8_epi32(__m512i __W, __mmask16 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -4929,7 +4704,7 @@ _mm512_mask_cvtepi8_epi32(__m512i __W, __mmask16 __U, __m128i __A)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi8_epi32(__mmask16 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -4937,7 +4712,7 @@ _mm512_maskz_cvtepi8_epi32(__mmask16 __U, __m128i __A)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepi8_epi64(__m128i __A)
{
/* This function always performs a signed extension, but __v16qi is a char
@@ -4945,7 +4720,7 @@ _mm512_cvtepi8_epi64(__m128i __A)
return (__m512i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__A, (__v16qs)__A, 0, 1, 2, 3, 4, 5, 6, 7), __v8di);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi8_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -4953,7 +4728,7 @@ _mm512_mask_cvtepi8_epi64(__m512i __W, __mmask8 __U, __m128i __A)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -4961,13 +4736,13 @@ _mm512_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
(__v8di)_mm512_setzero_si512 ());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepi32_epi64(__m256i __X)
{
return (__m512i)__builtin_convertvector((__v8si)__X, __v8di);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_epi64(__m512i __W, __mmask8 __U, __m256i __X)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -4975,7 +4750,7 @@ _mm512_mask_cvtepi32_epi64(__m512i __W, __mmask8 __U, __m256i __X)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi32_epi64(__mmask8 __U, __m256i __X)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -4983,13 +4758,13 @@ _mm512_maskz_cvtepi32_epi64(__mmask8 __U, __m256i __X)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepi16_epi32(__m256i __A)
{
return (__m512i)__builtin_convertvector((__v16hi)__A, __v16si);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi16_epi32(__m512i __W, __mmask16 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -4997,7 +4772,7 @@ _mm512_mask_cvtepi16_epi32(__m512i __W, __mmask16 __U, __m256i __A)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi16_epi32(__mmask16 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5005,13 +4780,13 @@ _mm512_maskz_cvtepi16_epi32(__mmask16 __U, __m256i __A)
(__v16si)_mm512_setzero_si512 ());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepi16_epi64(__m128i __A)
{
return (__m512i)__builtin_convertvector((__v8hi)__A, __v8di);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi16_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5019,7 +4794,7 @@ _mm512_mask_cvtepi16_epi64(__m512i __W, __mmask8 __U, __m128i __A)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5027,13 +4802,13 @@ _mm512_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepu8_epi32(__m128i __A)
{
return (__m512i)__builtin_convertvector((__v16qu)__A, __v16si);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu8_epi32(__m512i __W, __mmask16 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5041,7 +4816,7 @@ _mm512_mask_cvtepu8_epi32(__m512i __W, __mmask16 __U, __m128i __A)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu8_epi32(__mmask16 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5049,13 +4824,13 @@ _mm512_maskz_cvtepu8_epi32(__mmask16 __U, __m128i __A)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepu8_epi64(__m128i __A)
{
return (__m512i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__A, (__v16qu)__A, 0, 1, 2, 3, 4, 5, 6, 7), __v8di);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu8_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5063,7 +4838,7 @@ _mm512_mask_cvtepu8_epi64(__m512i __W, __mmask8 __U, __m128i __A)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5071,13 +4846,13 @@ _mm512_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepu32_epi64(__m256i __X)
{
return (__m512i)__builtin_convertvector((__v8su)__X, __v8di);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu32_epi64(__m512i __W, __mmask8 __U, __m256i __X)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5085,7 +4860,7 @@ _mm512_mask_cvtepu32_epi64(__m512i __W, __mmask8 __U, __m256i __X)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu32_epi64(__mmask8 __U, __m256i __X)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5093,13 +4868,13 @@ _mm512_maskz_cvtepu32_epi64(__mmask8 __U, __m256i __X)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepu16_epi32(__m256i __A)
{
return (__m512i)__builtin_convertvector((__v16hu)__A, __v16si);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu16_epi32(__m512i __W, __mmask16 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5107,7 +4882,7 @@ _mm512_mask_cvtepu16_epi32(__m512i __W, __mmask16 __U, __m256i __A)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu16_epi32(__mmask16 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5115,13 +4890,13 @@ _mm512_maskz_cvtepu16_epi32(__mmask16 __U, __m256i __A)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepu16_epi64(__m128i __A)
{
return (__m512i)__builtin_convertvector((__v8hu)__A, __v8di);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu16_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5129,7 +4904,7 @@ _mm512_mask_cvtepu16_epi64(__m512i __W, __mmask8 __U, __m128i __A)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5137,228 +4912,195 @@ _mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_rorv_epi32 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_prorvd512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_rorv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_rorv_epi32(__A, __B),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_rorv_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_rorv_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_rorv_epi64 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_prorvq512((__v8di)__A, (__v8di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_rorv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_rorv_epi64(__A, __B),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_rorv_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_rorv_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
-#define _mm512_cmp_epi32_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epi32_mask(a, b, p) \
(__mmask16)__builtin_ia32_cmpd512_mask((__v16si)(__m512i)(a), \
(__v16si)(__m512i)(b), (int)(p), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm512_cmp_epu32_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epu32_mask(a, b, p) \
(__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)(__m512i)(a), \
(__v16si)(__m512i)(b), (int)(p), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm512_cmp_epi64_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epi64_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpq512_mask((__v8di)(__m512i)(a), \
(__v8di)(__m512i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm512_cmp_epu64_mask(a, b, p) __extension__ ({ \
+#define _mm512_cmp_epu64_mask(a, b, p) \
(__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)(__m512i)(a), \
(__v8di)(__m512i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm512_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epi32_mask(m, a, b, p) \
(__mmask16)__builtin_ia32_cmpd512_mask((__v16si)(__m512i)(a), \
(__v16si)(__m512i)(b), (int)(p), \
- (__mmask16)(m)); })
+ (__mmask16)(m))
-#define _mm512_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epu32_mask(m, a, b, p) \
(__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)(__m512i)(a), \
(__v16si)(__m512i)(b), (int)(p), \
- (__mmask16)(m)); })
+ (__mmask16)(m))
-#define _mm512_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epi64_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpq512_mask((__v8di)(__m512i)(a), \
(__v8di)(__m512i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm512_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
+#define _mm512_mask_cmp_epu64_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)(__m512i)(a), \
(__v8di)(__m512i)(b), (int)(p), \
- (__mmask8)(m)); })
-
-#define _mm512_rol_epi32(a, b) __extension__ ({ \
- (__m512i)__builtin_ia32_prold512_mask((__v16si)(__m512i)(a), (int)(b), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
-
-#define _mm512_mask_rol_epi32(W, U, a, b) __extension__ ({ \
- (__m512i)__builtin_ia32_prold512_mask((__v16si)(__m512i)(a), (int)(b), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
-
-#define _mm512_maskz_rol_epi32(U, a, b) __extension__ ({ \
- (__m512i)__builtin_ia32_prold512_mask((__v16si)(__m512i)(a), (int)(b), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
-
-#define _mm512_rol_epi64(a, b) __extension__ ({ \
- (__m512i)__builtin_ia32_prolq512_mask((__v8di)(__m512i)(a), (int)(b), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
-
-#define _mm512_mask_rol_epi64(W, U, a, b) __extension__ ({ \
- (__m512i)__builtin_ia32_prolq512_mask((__v8di)(__m512i)(a), (int)(b), \
- (__v8di)(__m512i)(W), (__mmask8)(U)); })
-
-#define _mm512_maskz_rol_epi64(U, a, b) __extension__ ({ \
- (__m512i)__builtin_ia32_prolq512_mask((__v8di)(__m512i)(a), (int)(b), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+ (__mmask8)(m))
+
+#define _mm512_rol_epi32(a, b) \
+ (__m512i)__builtin_ia32_prold512((__v16si)(__m512i)(a), (int)(b))
+
+#define _mm512_mask_rol_epi32(W, U, a, b) \
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_rol_epi32((a), (b)), \
+ (__v16si)(__m512i)(W))
+
+#define _mm512_maskz_rol_epi32(U, a, b) \
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_rol_epi32((a), (b)), \
+ (__v16si)_mm512_setzero_si512())
+
+#define _mm512_rol_epi64(a, b) \
+ (__m512i)__builtin_ia32_prolq512((__v8di)(__m512i)(a), (int)(b))
+
+#define _mm512_mask_rol_epi64(W, U, a, b) \
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_rol_epi64((a), (b)), \
+ (__v8di)(__m512i)(W))
+
+#define _mm512_maskz_rol_epi64(U, a, b) \
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_rol_epi64((a), (b)), \
+ (__v8di)_mm512_setzero_si512())
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_rolv_epi32 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_prolvd512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_rolv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_rolv_epi32(__A, __B),
+ (__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_rolv_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_rolv_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_rolv_epi64 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_prolvq512((__v8di)__A, (__v8di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_rolv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_rolv_epi64(__A, __B),
+ (__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_rolv_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_rolv_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
-#define _mm512_ror_epi32(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_prord512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+#define _mm512_ror_epi32(A, B) \
+ (__m512i)__builtin_ia32_prord512((__v16si)(__m512i)(A), (int)(B))
-#define _mm512_mask_ror_epi32(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_prord512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+#define _mm512_mask_ror_epi32(W, U, A, B) \
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_ror_epi32((A), (B)), \
+ (__v16si)(__m512i)(W))
-#define _mm512_maskz_ror_epi32(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_prord512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+#define _mm512_maskz_ror_epi32(U, A, B) \
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_ror_epi32((A), (B)), \
+ (__v16si)_mm512_setzero_si512())
-#define _mm512_ror_epi64(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_prorq512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+#define _mm512_ror_epi64(A, B) \
+ (__m512i)__builtin_ia32_prorq512((__v8di)(__m512i)(A), (int)(B))
-#define _mm512_mask_ror_epi64(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_prorq512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)(__m512i)(W), (__mmask8)(U)); })
+#define _mm512_mask_ror_epi64(W, U, A, B) \
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_ror_epi64((A), (B)), \
+ (__v8di)(__m512i)(W))
-#define _mm512_maskz_ror_epi64(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_prorq512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+#define _mm512_maskz_ror_epi64(U, A, B) \
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_ror_epi64((A), (B)), \
+ (__v8di)_mm512_setzero_si512())
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_slli_epi32(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_pslldi512((__v16si)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5366,20 +5108,20 @@ _mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_slli_epi32(__mmask16 __U, __m512i __A, int __B) {
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
(__v16si)_mm512_slli_epi32(__A, __B),
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_slli_epi64(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psllqi512((__v8di)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5387,7 +5129,7 @@ _mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5395,13 +5137,13 @@ _mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A, int __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srli_epi32(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psrldi512((__v16si)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5409,20 +5151,20 @@ _mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srli_epi32(__mmask16 __U, __m512i __A, int __B) {
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
(__v16si)_mm512_srli_epi32(__A, __B),
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srli_epi64(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psrlqi512((__v8di)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5430,7 +5172,7 @@ _mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5438,7 +5180,7 @@ _mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A, int __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_load_epi32 (__m512i __W, __mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_movdqa32load512_mask ((const __v16si *) __P,
@@ -5446,7 +5188,7 @@ _mm512_mask_load_epi32 (__m512i __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_load_epi32 (__mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_movdqa32load512_mask ((const __v16si *) __P,
@@ -5455,14 +5197,14 @@ _mm512_maskz_load_epi32 (__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_store_epi32 (void *__P, __mmask16 __U, __m512i __A)
{
__builtin_ia32_movdqa32store512_mask ((__v16si *) __P, (__v16si) __A,
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mov_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectd_512 ((__mmask16) __U,
@@ -5470,7 +5212,7 @@ _mm512_mask_mov_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
(__v16si) __W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_epi32 (__mmask16 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectd_512 ((__mmask16) __U,
@@ -5478,7 +5220,7 @@ _mm512_maskz_mov_epi32 (__mmask16 __U, __m512i __A)
(__v16si) _mm512_setzero_si512 ());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mov_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __U,
@@ -5486,7 +5228,7 @@ _mm512_mask_mov_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
(__v8di) __W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_epi64 (__mmask8 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __U,
@@ -5494,7 +5236,7 @@ _mm512_maskz_mov_epi64 (__mmask8 __U, __m512i __A)
(__v8di) _mm512_setzero_si512 ());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_load_epi64 (__m512i __W, __mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_movdqa64load512_mask ((const __v8di *) __P,
@@ -5502,7 +5244,7 @@ _mm512_mask_load_epi64 (__m512i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_load_epi64 (__mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_movdqa64load512_mask ((const __v8di *) __P,
@@ -5511,21 +5253,21 @@ _mm512_maskz_load_epi64 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_store_epi64 (void *__P, __mmask8 __U, __m512i __A)
{
__builtin_ia32_movdqa64store512_mask ((__v8di *) __P, (__v8di) __A,
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_movedup_pd (__m512d __A)
{
return (__m512d)__builtin_shufflevector((__v8df)__A, (__v8df)__A,
0, 0, 2, 2, 4, 4, 6, 6);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_movedup_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
@@ -5533,7 +5275,7 @@ _mm512_mask_movedup_pd (__m512d __W, __mmask8 __U, __m512d __A)
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_movedup_pd (__mmask8 __U, __m512d __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
@@ -5541,179 +5283,179 @@ _mm512_maskz_movedup_pd (__mmask8 __U, __m512d __A)
(__v8df)_mm512_setzero_pd());
}
-#define _mm512_fixupimm_round_pd(A, B, C, imm, R) __extension__ ({ \
+#define _mm512_fixupimm_round_pd(A, B, C, imm, R) \
(__m512d)__builtin_ia32_fixupimmpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_fixupimm_round_pd(A, U, B, C, imm, R) __extension__ ({ \
+#define _mm512_mask_fixupimm_round_pd(A, U, B, C, imm, R) \
(__m512d)__builtin_ia32_fixupimmpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_fixupimm_pd(A, B, C, imm) __extension__ ({ \
+#define _mm512_fixupimm_pd(A, B, C, imm) \
(__m512d)__builtin_ia32_fixupimmpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_fixupimm_pd(A, U, B, C, imm) __extension__ ({ \
+#define _mm512_mask_fixupimm_pd(A, U, B, C, imm) \
(__m512d)__builtin_ia32_fixupimmpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_fixupimm_round_pd(U, A, B, C, imm, R) __extension__ ({ \
+#define _mm512_maskz_fixupimm_round_pd(U, A, B, C, imm, R) \
(__m512d)__builtin_ia32_fixupimmpd512_maskz((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8di)(__m512i)(C), \
(int)(imm), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_fixupimm_pd(U, A, B, C, imm) __extension__ ({ \
+#define _mm512_maskz_fixupimm_pd(U, A, B, C, imm) \
(__m512d)__builtin_ia32_fixupimmpd512_maskz((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8di)(__m512i)(C), \
(int)(imm), (__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_fixupimm_round_ps(A, B, C, imm, R) __extension__ ({ \
+#define _mm512_fixupimm_round_ps(A, B, C, imm, R) \
(__m512)__builtin_ia32_fixupimmps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16si)(__m512i)(C), (int)(imm), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_fixupimm_round_ps(A, U, B, C, imm, R) __extension__ ({ \
+#define _mm512_mask_fixupimm_round_ps(A, U, B, C, imm, R) \
(__m512)__builtin_ia32_fixupimmps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16si)(__m512i)(C), (int)(imm), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_fixupimm_ps(A, B, C, imm) __extension__ ({ \
+#define _mm512_fixupimm_ps(A, B, C, imm) \
(__m512)__builtin_ia32_fixupimmps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16si)(__m512i)(C), (int)(imm), \
(__mmask16)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_fixupimm_ps(A, U, B, C, imm) __extension__ ({ \
+#define _mm512_mask_fixupimm_ps(A, U, B, C, imm) \
(__m512)__builtin_ia32_fixupimmps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16si)(__m512i)(C), (int)(imm), \
(__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_fixupimm_round_ps(U, A, B, C, imm, R) __extension__ ({ \
+#define _mm512_maskz_fixupimm_round_ps(U, A, B, C, imm, R) \
(__m512)__builtin_ia32_fixupimmps512_maskz((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16si)(__m512i)(C), \
(int)(imm), (__mmask16)(U), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_maskz_fixupimm_ps(U, A, B, C, imm) __extension__ ({ \
+#define _mm512_maskz_fixupimm_ps(U, A, B, C, imm) \
(__m512)__builtin_ia32_fixupimmps512_maskz((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16si)(__m512i)(C), \
(int)(imm), (__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_fixupimm_round_sd(A, B, C, imm, R) __extension__ ({ \
+#define _mm_fixupimm_round_sd(A, B, C, imm, R) \
(__m128d)__builtin_ia32_fixupimmsd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_fixupimm_round_sd(A, U, B, C, imm, R) __extension__ ({ \
+#define _mm_mask_fixupimm_round_sd(A, U, B, C, imm, R) \
(__m128d)__builtin_ia32_fixupimmsd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_fixupimm_sd(A, B, C, imm) __extension__ ({ \
+#define _mm_fixupimm_sd(A, B, C, imm) \
(__m128d)__builtin_ia32_fixupimmsd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_fixupimm_sd(A, U, B, C, imm) __extension__ ({ \
+#define _mm_mask_fixupimm_sd(A, U, B, C, imm) \
(__m128d)__builtin_ia32_fixupimmsd_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_fixupimm_round_sd(U, A, B, C, imm, R) __extension__ ({ \
+#define _mm_maskz_fixupimm_round_sd(U, A, B, C, imm, R) \
(__m128d)__builtin_ia32_fixupimmsd_maskz((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_fixupimm_sd(U, A, B, C, imm) __extension__ ({ \
+#define _mm_maskz_fixupimm_sd(U, A, B, C, imm) \
(__m128d)__builtin_ia32_fixupimmsd_maskz((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_fixupimm_round_ss(A, B, C, imm, R) __extension__ ({ \
+#define _mm_fixupimm_round_ss(A, B, C, imm, R) \
(__m128)__builtin_ia32_fixupimmss_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_fixupimm_round_ss(A, U, B, C, imm, R) __extension__ ({ \
+#define _mm_mask_fixupimm_round_ss(A, U, B, C, imm, R) \
(__m128)__builtin_ia32_fixupimmss_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_fixupimm_ss(A, B, C, imm) __extension__ ({ \
+#define _mm_fixupimm_ss(A, B, C, imm) \
(__m128)__builtin_ia32_fixupimmss_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_fixupimm_ss(A, U, B, C, imm) __extension__ ({ \
+#define _mm_mask_fixupimm_ss(A, U, B, C, imm) \
(__m128)__builtin_ia32_fixupimmss_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_fixupimm_round_ss(U, A, B, C, imm, R) __extension__ ({ \
+#define _mm_maskz_fixupimm_round_ss(U, A, B, C, imm, R) \
(__m128)__builtin_ia32_fixupimmss_maskz((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_fixupimm_ss(U, A, B, C, imm) __extension__ ({ \
+#define _mm_maskz_fixupimm_ss(U, A, B, C, imm) \
(__m128)__builtin_ia32_fixupimmss_maskz((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_getexp_round_sd(A, B, R) __extension__ ({ \
+#define _mm_getexp_round_sd(A, B, R) \
(__m128d)__builtin_ia32_getexpsd128_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_getexp_sd (__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_getexpsd128_round_mask ((__v2df) __A,
(__v2df) __B, (__v2df) _mm_setzero_pd(), (__mmask8) -1, _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_getexp_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_getexpsd128_round_mask ( (__v2df) __A,
@@ -5723,13 +5465,13 @@ _mm_mask_getexp_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_getexp_round_sd(W, U, A, B, R) __extension__ ({\
+#define _mm_mask_getexp_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_getexpsd128_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_getexp_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_getexpsd128_round_mask ( (__v2df) __A,
@@ -5739,26 +5481,26 @@ _mm_maskz_getexp_sd (__mmask8 __U, __m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_getexp_round_sd(U, A, B, R) __extension__ ({\
+#define _mm_maskz_getexp_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_getexpsd128_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_getexp_round_ss(A, B, R) __extension__ ({ \
+#define _mm_getexp_round_ss(A, B, R) \
(__m128)__builtin_ia32_getexpss128_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_getexp_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A,
(__v4sf) __B, (__v4sf) _mm_setzero_ps(), (__mmask8) -1, _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_getexp_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A,
@@ -5768,155 +5510,144 @@ _mm_mask_getexp_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_getexp_round_ss(W, U, A, B, R) __extension__ ({\
+#define _mm_mask_getexp_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_getexpss128_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A,
(__v4sf) __B,
- (__v4sf) _mm_setzero_pd (),
+ (__v4sf) _mm_setzero_ps (),
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_getexp_round_ss(U, A, B, R) __extension__ ({\
+#define _mm_maskz_getexp_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_getexpss128_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_getmant_round_sd(A, B, C, D, R) __extension__ ({ \
+#define _mm_getmant_round_sd(A, B, C, D, R) \
(__m128d)__builtin_ia32_getmantsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(int)(((D)<<2) | (C)), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_getmant_sd(A, B, C, D) __extension__ ({ \
+#define _mm_getmant_sd(A, B, C, D) \
(__m128d)__builtin_ia32_getmantsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(int)(((D)<<2) | (C)), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_getmant_sd(W, U, A, B, C, D) __extension__ ({\
+#define _mm_mask_getmant_sd(W, U, A, B, C, D) \
(__m128d)__builtin_ia32_getmantsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(int)(((D)<<2) | (C)), \
(__v2df)(__m128d)(W), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_getmant_round_sd(W, U, A, B, C, D, R)({\
+#define _mm_mask_getmant_round_sd(W, U, A, B, C, D, R) \
(__m128d)__builtin_ia32_getmantsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(int)(((D)<<2) | (C)), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_getmant_sd(U, A, B, C, D) __extension__ ({\
+#define _mm_maskz_getmant_sd(U, A, B, C, D) \
(__m128d)__builtin_ia32_getmantsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(int)(((D)<<2) | (C)), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_getmant_round_sd(U, A, B, C, D, R) __extension__ ({\
+#define _mm_maskz_getmant_round_sd(U, A, B, C, D, R) \
(__m128d)__builtin_ia32_getmantsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(int)(((D)<<2) | (C)), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_getmant_round_ss(A, B, C, D, R) __extension__ ({ \
+#define _mm_getmant_round_ss(A, B, C, D, R) \
(__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(int)(((D)<<2) | (C)), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_getmant_ss(A, B, C, D) __extension__ ({ \
+#define _mm_getmant_ss(A, B, C, D) \
(__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(int)(((D)<<2) | (C)), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_getmant_ss(W, U, A, B, C, D) __extension__ ({\
+#define _mm_mask_getmant_ss(W, U, A, B, C, D) \
(__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(int)(((D)<<2) | (C)), \
(__v4sf)(__m128)(W), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_getmant_round_ss(W, U, A, B, C, D, R)({\
+#define _mm_mask_getmant_round_ss(W, U, A, B, C, D, R) \
(__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(int)(((D)<<2) | (C)), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_getmant_ss(U, A, B, C, D) __extension__ ({\
+#define _mm_maskz_getmant_ss(U, A, B, C, D) \
(__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(int)(((D)<<2) | (C)), \
- (__v4sf)_mm_setzero_pd(), \
+ (__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_getmant_round_ss(U, A, B, C, D, R) __extension__ ({\
+#define _mm_maskz_getmant_round_ss(U, A, B, C, D, R) \
(__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(int)(((D)<<2) | (C)), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kmov (__mmask16 __A)
{
return __A;
}
-#define _mm_comi_round_sd(A, B, P, R) __extension__ ({\
+#define _mm_comi_round_sd(A, B, P, R) \
(int)__builtin_ia32_vcomisd((__v2df)(__m128d)(A), (__v2df)(__m128d)(B), \
- (int)(P), (int)(R)); })
+ (int)(P), (int)(R))
-#define _mm_comi_round_ss(A, B, P, R) __extension__ ({\
+#define _mm_comi_round_ss(A, B, P, R) \
(int)__builtin_ia32_vcomiss((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), \
- (int)(P), (int)(R)); })
+ (int)(P), (int)(R))
#ifdef __x86_64__
-#define _mm_cvt_roundsd_si64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvtsd2si64((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvt_roundsd_si64(A, R) \
+ (long long)__builtin_ia32_vcvtsd2si64((__v2df)(__m128d)(A), (int)(R))
#endif
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask2_permutex2var_epi32 (__m512i __A, __m512i __I,
- __mmask16 __U, __m512i __B)
-{
- return (__m512i) __builtin_ia32_vpermi2vard512_mask ((__v16si) __A,
- (__v16si) __I
- /* idx */ ,
- (__v16si) __B,
- (__mmask16) __U);
-}
-
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sll_epi32(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_pslld512((__v16si) __A, (__v4si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sll_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5924,7 +5655,7 @@ _mm512_mask_sll_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sll_epi32(__mmask16 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5932,13 +5663,13 @@ _mm512_maskz_sll_epi32(__mmask16 __U, __m512i __A, __m128i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sll_epi64(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psllq512((__v8di)__A, (__v2di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sll_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5946,7 +5677,7 @@ _mm512_mask_sll_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sll_epi64(__mmask8 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5954,13 +5685,13 @@ _mm512_maskz_sll_epi64(__mmask8 __U, __m512i __A, __m128i __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sllv_epi32(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_psllv16si((__v16si)__X, (__v16si)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sllv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5968,7 +5699,7 @@ _mm512_mask_sllv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sllv_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -5976,13 +5707,13 @@ _mm512_maskz_sllv_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sllv_epi64(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_psllv8di((__v8di)__X, (__v8di)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sllv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5990,7 +5721,7 @@ _mm512_mask_sllv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sllv_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -5998,13 +5729,13 @@ _mm512_maskz_sllv_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sra_epi32(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psrad512((__v16si) __A, (__v4si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sra_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6012,7 +5743,7 @@ _mm512_mask_sra_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sra_epi32(__mmask16 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6020,13 +5751,13 @@ _mm512_maskz_sra_epi32(__mmask16 __U, __m512i __A, __m128i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sra_epi64(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psraq512((__v8di)__A, (__v2di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sra_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6034,7 +5765,7 @@ _mm512_mask_sra_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sra_epi64(__mmask8 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6042,13 +5773,13 @@ _mm512_maskz_sra_epi64(__mmask8 __U, __m512i __A, __m128i __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srav_epi32(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_psrav16si((__v16si)__X, (__v16si)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srav_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6056,7 +5787,7 @@ _mm512_mask_srav_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srav_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6064,13 +5795,13 @@ _mm512_maskz_srav_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srav_epi64(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_psrav8di((__v8di)__X, (__v8di)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srav_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6078,7 +5809,7 @@ _mm512_mask_srav_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srav_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6086,13 +5817,13 @@ _mm512_maskz_srav_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srl_epi32(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psrld512((__v16si) __A, (__v4si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srl_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6100,7 +5831,7 @@ _mm512_mask_srl_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srl_epi32(__mmask16 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6108,13 +5839,13 @@ _mm512_maskz_srl_epi32(__mmask16 __U, __m512i __A, __m128i __B)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srl_epi64(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psrlq512((__v8di)__A, (__v2di)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srl_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6122,7 +5853,7 @@ _mm512_mask_srl_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srl_epi64(__mmask8 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6130,13 +5861,13 @@ _mm512_maskz_srl_epi64(__mmask8 __U, __m512i __A, __m128i __B)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srlv_epi32(__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_psrlv16si((__v16si)__X, (__v16si)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srlv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6144,7 +5875,7 @@ _mm512_mask_srlv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srlv_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
@@ -6152,13 +5883,13 @@ _mm512_maskz_srlv_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srlv_epi64 (__m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_psrlv8di((__v8di)__X, (__v8di)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srlv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6166,7 +5897,7 @@ _mm512_mask_srlv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
@@ -6174,57 +5905,57 @@ _mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)_mm512_setzero_si512());
}
-#define _mm512_ternarylogic_epi32(A, B, C, imm) __extension__ ({ \
+#define _mm512_ternarylogic_epi32(A, B, C, imm) \
(__m512i)__builtin_ia32_pternlogd512_mask((__v16si)(__m512i)(A), \
(__v16si)(__m512i)(B), \
(__v16si)(__m512i)(C), (int)(imm), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm512_mask_ternarylogic_epi32(A, U, B, C, imm) __extension__ ({ \
+#define _mm512_mask_ternarylogic_epi32(A, U, B, C, imm) \
(__m512i)__builtin_ia32_pternlogd512_mask((__v16si)(__m512i)(A), \
(__v16si)(__m512i)(B), \
(__v16si)(__m512i)(C), (int)(imm), \
- (__mmask16)(U)); })
+ (__mmask16)(U))
-#define _mm512_maskz_ternarylogic_epi32(U, A, B, C, imm) __extension__ ({ \
+#define _mm512_maskz_ternarylogic_epi32(U, A, B, C, imm) \
(__m512i)__builtin_ia32_pternlogd512_maskz((__v16si)(__m512i)(A), \
(__v16si)(__m512i)(B), \
(__v16si)(__m512i)(C), \
- (int)(imm), (__mmask16)(U)); })
+ (int)(imm), (__mmask16)(U))
-#define _mm512_ternarylogic_epi64(A, B, C, imm) __extension__ ({ \
+#define _mm512_ternarylogic_epi64(A, B, C, imm) \
(__m512i)__builtin_ia32_pternlogq512_mask((__v8di)(__m512i)(A), \
(__v8di)(__m512i)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm512_mask_ternarylogic_epi64(A, U, B, C, imm) __extension__ ({ \
+#define _mm512_mask_ternarylogic_epi64(A, U, B, C, imm) \
(__m512i)__builtin_ia32_pternlogq512_mask((__v8di)(__m512i)(A), \
(__v8di)(__m512i)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm512_maskz_ternarylogic_epi64(U, A, B, C, imm) __extension__ ({ \
+#define _mm512_maskz_ternarylogic_epi64(U, A, B, C, imm) \
(__m512i)__builtin_ia32_pternlogq512_maskz((__v8di)(__m512i)(A), \
(__v8di)(__m512i)(B), \
(__v8di)(__m512i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
#ifdef __x86_64__
-#define _mm_cvt_roundsd_i64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvtsd2si64((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvt_roundsd_i64(A, R) \
+ (long long)__builtin_ia32_vcvtsd2si64((__v2df)(__m128d)(A), (int)(R))
#endif
-#define _mm_cvt_roundsd_si32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvtsd2si32((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvt_roundsd_si32(A, R) \
+ (int)__builtin_ia32_vcvtsd2si32((__v2df)(__m128d)(A), (int)(R))
-#define _mm_cvt_roundsd_i32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvtsd2si32((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvt_roundsd_i32(A, R) \
+ (int)__builtin_ia32_vcvtsd2si32((__v2df)(__m128d)(A), (int)(R))
-#define _mm_cvt_roundsd_u32(A, R) __extension__ ({ \
- (unsigned int)__builtin_ia32_vcvtsd2usi32((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvt_roundsd_u32(A, R) \
+ (unsigned int)__builtin_ia32_vcvtsd2usi32((__v2df)(__m128d)(A), (int)(R))
-static __inline__ unsigned __DEFAULT_FN_ATTRS
+static __inline__ unsigned __DEFAULT_FN_ATTRS128
_mm_cvtsd_u32 (__m128d __A)
{
return (unsigned) __builtin_ia32_vcvtsd2usi32 ((__v2df) __A,
@@ -6232,11 +5963,11 @@ _mm_cvtsd_u32 (__m128d __A)
}
#ifdef __x86_64__
-#define _mm_cvt_roundsd_u64(A, R) __extension__ ({ \
+#define _mm_cvt_roundsd_u64(A, R) \
(unsigned long long)__builtin_ia32_vcvtsd2usi64((__v2df)(__m128d)(A), \
- (int)(R)); })
+ (int)(R))
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS128
_mm_cvtsd_u64 (__m128d __A)
{
return (unsigned long long) __builtin_ia32_vcvtsd2usi64 ((__v2df)
@@ -6245,24 +5976,24 @@ _mm_cvtsd_u64 (__m128d __A)
}
#endif
-#define _mm_cvt_roundss_si32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvtss2si32((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvt_roundss_si32(A, R) \
+ (int)__builtin_ia32_vcvtss2si32((__v4sf)(__m128)(A), (int)(R))
-#define _mm_cvt_roundss_i32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvtss2si32((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvt_roundss_i32(A, R) \
+ (int)__builtin_ia32_vcvtss2si32((__v4sf)(__m128)(A), (int)(R))
#ifdef __x86_64__
-#define _mm_cvt_roundss_si64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvtss2si64((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvt_roundss_si64(A, R) \
+ (long long)__builtin_ia32_vcvtss2si64((__v4sf)(__m128)(A), (int)(R))
-#define _mm_cvt_roundss_i64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvtss2si64((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvt_roundss_i64(A, R) \
+ (long long)__builtin_ia32_vcvtss2si64((__v4sf)(__m128)(A), (int)(R))
#endif
-#define _mm_cvt_roundss_u32(A, R) __extension__ ({ \
- (unsigned int)__builtin_ia32_vcvtss2usi32((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvt_roundss_u32(A, R) \
+ (unsigned int)__builtin_ia32_vcvtss2usi32((__v4sf)(__m128)(A), (int)(R))
-static __inline__ unsigned __DEFAULT_FN_ATTRS
+static __inline__ unsigned __DEFAULT_FN_ATTRS128
_mm_cvtss_u32 (__m128 __A)
{
return (unsigned) __builtin_ia32_vcvtss2usi32 ((__v4sf) __A,
@@ -6270,11 +6001,11 @@ _mm_cvtss_u32 (__m128 __A)
}
#ifdef __x86_64__
-#define _mm_cvt_roundss_u64(A, R) __extension__ ({ \
+#define _mm_cvt_roundss_u64(A, R) \
(unsigned long long)__builtin_ia32_vcvtss2usi64((__v4sf)(__m128)(A), \
- (int)(R)); })
+ (int)(R))
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS128
_mm_cvtss_u64 (__m128 __A)
{
return (unsigned long long) __builtin_ia32_vcvtss2usi64 ((__v4sf)
@@ -6283,13 +6014,13 @@ _mm_cvtss_u64 (__m128 __A)
}
#endif
-#define _mm_cvtt_roundsd_i32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvttsd2si32((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvtt_roundsd_i32(A, R) \
+ (int)__builtin_ia32_vcvttsd2si32((__v2df)(__m128d)(A), (int)(R))
-#define _mm_cvtt_roundsd_si32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvttsd2si32((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvtt_roundsd_si32(A, R) \
+ (int)__builtin_ia32_vcvttsd2si32((__v2df)(__m128d)(A), (int)(R))
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS128
_mm_cvttsd_i32 (__m128d __A)
{
return (int) __builtin_ia32_vcvttsd2si32 ((__v2df) __A,
@@ -6297,13 +6028,13 @@ _mm_cvttsd_i32 (__m128d __A)
}
#ifdef __x86_64__
-#define _mm_cvtt_roundsd_si64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvttsd2si64((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvtt_roundsd_si64(A, R) \
+ (long long)__builtin_ia32_vcvttsd2si64((__v2df)(__m128d)(A), (int)(R))
-#define _mm_cvtt_roundsd_i64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvttsd2si64((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvtt_roundsd_i64(A, R) \
+ (long long)__builtin_ia32_vcvttsd2si64((__v2df)(__m128d)(A), (int)(R))
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS128
_mm_cvttsd_i64 (__m128d __A)
{
return (long long) __builtin_ia32_vcvttsd2si64 ((__v2df) __A,
@@ -6311,10 +6042,10 @@ _mm_cvttsd_i64 (__m128d __A)
}
#endif
-#define _mm_cvtt_roundsd_u32(A, R) __extension__ ({ \
- (unsigned int)__builtin_ia32_vcvttsd2usi32((__v2df)(__m128d)(A), (int)(R)); })
+#define _mm_cvtt_roundsd_u32(A, R) \
+ (unsigned int)__builtin_ia32_vcvttsd2usi32((__v2df)(__m128d)(A), (int)(R))
-static __inline__ unsigned __DEFAULT_FN_ATTRS
+static __inline__ unsigned __DEFAULT_FN_ATTRS128
_mm_cvttsd_u32 (__m128d __A)
{
return (unsigned) __builtin_ia32_vcvttsd2usi32 ((__v2df) __A,
@@ -6322,11 +6053,11 @@ _mm_cvttsd_u32 (__m128d __A)
}
#ifdef __x86_64__
-#define _mm_cvtt_roundsd_u64(A, R) __extension__ ({ \
+#define _mm_cvtt_roundsd_u64(A, R) \
(unsigned long long)__builtin_ia32_vcvttsd2usi64((__v2df)(__m128d)(A), \
- (int)(R)); })
+ (int)(R))
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS128
_mm_cvttsd_u64 (__m128d __A)
{
return (unsigned long long) __builtin_ia32_vcvttsd2usi64 ((__v2df)
@@ -6335,13 +6066,13 @@ _mm_cvttsd_u64 (__m128d __A)
}
#endif
-#define _mm_cvtt_roundss_i32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvttss2si32((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvtt_roundss_i32(A, R) \
+ (int)__builtin_ia32_vcvttss2si32((__v4sf)(__m128)(A), (int)(R))
-#define _mm_cvtt_roundss_si32(A, R) __extension__ ({ \
- (int)__builtin_ia32_vcvttss2si32((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvtt_roundss_si32(A, R) \
+ (int)__builtin_ia32_vcvttss2si32((__v4sf)(__m128)(A), (int)(R))
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS128
_mm_cvttss_i32 (__m128 __A)
{
return (int) __builtin_ia32_vcvttss2si32 ((__v4sf) __A,
@@ -6349,13 +6080,13 @@ _mm_cvttss_i32 (__m128 __A)
}
#ifdef __x86_64__
-#define _mm_cvtt_roundss_i64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvttss2si64((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvtt_roundss_i64(A, R) \
+ (long long)__builtin_ia32_vcvttss2si64((__v4sf)(__m128)(A), (int)(R))
-#define _mm_cvtt_roundss_si64(A, R) __extension__ ({ \
- (long long)__builtin_ia32_vcvttss2si64((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvtt_roundss_si64(A, R) \
+ (long long)__builtin_ia32_vcvttss2si64((__v4sf)(__m128)(A), (int)(R))
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS128
_mm_cvttss_i64 (__m128 __A)
{
return (long long) __builtin_ia32_vcvttss2si64 ((__v4sf) __A,
@@ -6363,10 +6094,10 @@ _mm_cvttss_i64 (__m128 __A)
}
#endif
-#define _mm_cvtt_roundss_u32(A, R) __extension__ ({ \
- (unsigned int)__builtin_ia32_vcvttss2usi32((__v4sf)(__m128)(A), (int)(R)); })
+#define _mm_cvtt_roundss_u32(A, R) \
+ (unsigned int)__builtin_ia32_vcvttss2usi32((__v4sf)(__m128)(A), (int)(R))
-static __inline__ unsigned __DEFAULT_FN_ATTRS
+static __inline__ unsigned __DEFAULT_FN_ATTRS128
_mm_cvttss_u32 (__m128 __A)
{
return (unsigned) __builtin_ia32_vcvttss2usi32 ((__v4sf) __A,
@@ -6374,11 +6105,11 @@ _mm_cvttss_u32 (__m128 __A)
}
#ifdef __x86_64__
-#define _mm_cvtt_roundss_u64(A, R) __extension__ ({ \
+#define _mm_cvtt_roundss_u64(A, R) \
(unsigned long long)__builtin_ia32_vcvttss2usi64((__v4sf)(__m128)(A), \
- (int)(R)); })
+ (int)(R))
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS128
_mm_cvttss_u64 (__m128 __A)
{
return (unsigned long long) __builtin_ia32_vcvttss2usi64 ((__v4sf)
@@ -6387,98 +6118,39 @@ _mm_cvttss_u64 (__m128 __A)
}
#endif
-static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask2_permutex2var_pd (__m512d __A, __m512i __I, __mmask8 __U,
- __m512d __B)
-{
- return (__m512d) __builtin_ia32_vpermi2varpd512_mask ((__v8df) __A,
- (__v8di) __I
- /* idx */ ,
- (__v8df) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask2_permutex2var_ps (__m512 __A, __m512i __I, __mmask16 __U,
- __m512 __B)
-{
- return (__m512) __builtin_ia32_vpermi2varps512_mask ((__v16sf) __A,
- (__v16si) __I
- /* idx */ ,
- (__v16sf) __B,
- (__mmask16) __U);
-}
-
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask2_permutex2var_epi64 (__m512i __A, __m512i __I,
- __mmask8 __U, __m512i __B)
-{
- return (__m512i) __builtin_ia32_vpermi2varq512_mask ((__v8di) __A,
- (__v8di) __I
- /* idx */ ,
- (__v8di) __B,
- (__mmask8) __U);
-}
-
-#define _mm512_permute_pd(X, C) __extension__ ({ \
- (__m512d)__builtin_shufflevector((__v8df)(__m512d)(X), \
- (__v8df)_mm512_undefined_pd(), \
- 0 + (((C) >> 0) & 0x1), \
- 0 + (((C) >> 1) & 0x1), \
- 2 + (((C) >> 2) & 0x1), \
- 2 + (((C) >> 3) & 0x1), \
- 4 + (((C) >> 4) & 0x1), \
- 4 + (((C) >> 5) & 0x1), \
- 6 + (((C) >> 6) & 0x1), \
- 6 + (((C) >> 7) & 0x1)); })
+#define _mm512_permute_pd(X, C) \
+ (__m512d)__builtin_ia32_vpermilpd512((__v8df)(__m512d)(X), (int)(C))
-#define _mm512_mask_permute_pd(W, U, X, C) __extension__ ({ \
+#define _mm512_mask_permute_pd(W, U, X, C) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_permute_pd((X), (C)), \
- (__v8df)(__m512d)(W)); })
+ (__v8df)(__m512d)(W))
-#define _mm512_maskz_permute_pd(U, X, C) __extension__ ({ \
+#define _mm512_maskz_permute_pd(U, X, C) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_permute_pd((X), (C)), \
- (__v8df)_mm512_setzero_pd()); })
-
-#define _mm512_permute_ps(X, C) __extension__ ({ \
- (__m512)__builtin_shufflevector((__v16sf)(__m512)(X), \
- (__v16sf)_mm512_undefined_ps(), \
- 0 + (((C) >> 0) & 0x3), \
- 0 + (((C) >> 2) & 0x3), \
- 0 + (((C) >> 4) & 0x3), \
- 0 + (((C) >> 6) & 0x3), \
- 4 + (((C) >> 0) & 0x3), \
- 4 + (((C) >> 2) & 0x3), \
- 4 + (((C) >> 4) & 0x3), \
- 4 + (((C) >> 6) & 0x3), \
- 8 + (((C) >> 0) & 0x3), \
- 8 + (((C) >> 2) & 0x3), \
- 8 + (((C) >> 4) & 0x3), \
- 8 + (((C) >> 6) & 0x3), \
- 12 + (((C) >> 0) & 0x3), \
- 12 + (((C) >> 2) & 0x3), \
- 12 + (((C) >> 4) & 0x3), \
- 12 + (((C) >> 6) & 0x3)); })
-
-#define _mm512_mask_permute_ps(W, U, X, C) __extension__ ({ \
+ (__v8df)_mm512_setzero_pd())
+
+#define _mm512_permute_ps(X, C) \
+ (__m512)__builtin_ia32_vpermilps512((__v16sf)(__m512)(X), (int)(C))
+
+#define _mm512_mask_permute_ps(W, U, X, C) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_permute_ps((X), (C)), \
- (__v16sf)(__m512)(W)); })
+ (__v16sf)(__m512)(W))
-#define _mm512_maskz_permute_ps(U, X, C) __extension__ ({ \
+#define _mm512_maskz_permute_ps(U, X, C) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_permute_ps((X), (C)), \
- (__v16sf)_mm512_setzero_ps()); })
+ (__v16sf)_mm512_setzero_ps())
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_permutevar_pd(__m512d __A, __m512i __C)
{
return (__m512d)__builtin_ia32_vpermilvarpd512((__v8df)__A, (__v8di)__C);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_permutevar_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512i __C)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
@@ -6486,7 +6158,7 @@ _mm512_mask_permutevar_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512i __C)
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_permutevar_pd(__mmask8 __U, __m512d __A, __m512i __C)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
@@ -6494,13 +6166,13 @@ _mm512_maskz_permutevar_pd(__mmask8 __U, __m512d __A, __m512i __C)
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_permutevar_ps(__m512 __A, __m512i __C)
{
return (__m512)__builtin_ia32_vpermilvarps512((__v16sf)__A, (__v16si)__C);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_permutevar_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512i __C)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
@@ -6508,7 +6180,7 @@ _mm512_mask_permutevar_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512i __C)
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
@@ -6516,85 +6188,87 @@ _mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C)
(__v16sf)_mm512_setzero_ps());
}
-static __inline __m512d __DEFAULT_FN_ATTRS
+static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_permutex2var_pd(__m512d __A, __m512i __I, __m512d __B)
{
- return (__m512d) __builtin_ia32_vpermt2varpd512_mask ((__v8di) __I
- /* idx */ ,
- (__v8df) __A,
- (__v8df) __B,
- (__mmask8) -1);
+ return (__m512d)__builtin_ia32_vpermi2varpd512((__v8df)__A, (__v8di)__I,
+ (__v8df)__B);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
+_mm512_mask_permutex2var_pd(__m512d __A, __mmask8 __U, __m512i __I, __m512d __B)
+{
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_permutex2var_pd(__A, __I, __B),
+ (__v8df)__A);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask_permutex2var_pd (__m512d __A, __mmask8 __U, __m512i __I, __m512d __B)
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
+_mm512_mask2_permutex2var_pd(__m512d __A, __m512i __I, __mmask8 __U,
+ __m512d __B)
{
- return (__m512d) __builtin_ia32_vpermt2varpd512_mask ((__v8di) __I
- /* idx */ ,
- (__v8df) __A,
- (__v8df) __B,
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_permutex2var_pd(__A, __I, __B),
+ (__v8df)(__m512d)__I);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_maskz_permutex2var_pd (__mmask8 __U, __m512d __A, __m512i __I,
- __m512d __B)
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
+_mm512_maskz_permutex2var_pd(__mmask8 __U, __m512d __A, __m512i __I,
+ __m512d __B)
{
- return (__m512d) __builtin_ia32_vpermt2varpd512_maskz ((__v8di) __I
- /* idx */ ,
- (__v8df) __A,
- (__v8df) __B,
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512(__U,
+ (__v8df)_mm512_permutex2var_pd(__A, __I, __B),
+ (__v8df)_mm512_setzero_pd());
}
-static __inline __m512 __DEFAULT_FN_ATTRS
+static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_permutex2var_ps(__m512 __A, __m512i __I, __m512 __B)
{
- return (__m512) __builtin_ia32_vpermt2varps512_mask ((__v16si) __I
- /* idx */ ,
- (__v16sf) __A,
- (__v16sf) __B,
- (__mmask16) -1);
+ return (__m512)__builtin_ia32_vpermi2varps512((__v16sf)__A, (__v16si)__I,
+ (__v16sf) __B);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_permutex2var_ps (__m512 __A, __mmask16 __U, __m512i __I, __m512 __B)
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
+_mm512_mask_permutex2var_ps(__m512 __A, __mmask16 __U, __m512i __I, __m512 __B)
{
- return (__m512) __builtin_ia32_vpermt2varps512_mask ((__v16si) __I
- /* idx */ ,
- (__v16sf) __A,
- (__v16sf) __B,
- (__mmask16) __U);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_permutex2var_ps(__A, __I, __B),
+ (__v16sf)__A);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_maskz_permutex2var_ps (__mmask16 __U, __m512 __A, __m512i __I,
- __m512 __B)
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
+_mm512_mask2_permutex2var_ps(__m512 __A, __m512i __I, __mmask16 __U, __m512 __B)
{
- return (__m512) __builtin_ia32_vpermt2varps512_maskz ((__v16si) __I
- /* idx */ ,
- (__v16sf) __A,
- (__v16sf) __B,
- (__mmask16) __U);
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_permutex2var_ps(__A, __I, __B),
+ (__v16sf)(__m512)__I);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
+_mm512_maskz_permutex2var_ps(__mmask16 __U, __m512 __A, __m512i __I, __m512 __B)
+{
+ return (__m512)__builtin_ia32_selectps_512(__U,
+ (__v16sf)_mm512_permutex2var_ps(__A, __I, __B),
+ (__v16sf)_mm512_setzero_ps());
}
-#define _mm512_cvtt_roundpd_epu32(A, R) __extension__ ({ \
+#define _mm512_cvtt_roundpd_epu32(A, R) \
(__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_undefined_si256(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvtt_roundpd_epu32(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvtt_roundpd_epu32(W, U, A, R) \
(__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \
(__v8si)(__m256i)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvtt_roundpd_epu32(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvtt_roundpd_epu32(U, A, R) \
(__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \
(__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvttpd_epu32 (__m512d __A)
{
return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A,
@@ -6604,7 +6278,7 @@ _mm512_cvttpd_epu32 (__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A,
@@ -6613,7 +6287,7 @@ _mm512_mask_cvttpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttpd_epu32 (__mmask8 __U, __m512d __A)
{
return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A,
@@ -6623,109 +6297,109 @@ _mm512_maskz_cvttpd_epu32 (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_roundscale_round_sd(A, B, imm, R) __extension__ ({ \
+#define _mm_roundscale_round_sd(A, B, imm, R) \
(__m128d)__builtin_ia32_rndscalesd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)-1, (int)(imm), \
- (int)(R)); })
+ (int)(R))
-#define _mm_roundscale_sd(A, B, imm) __extension__ ({ \
+#define _mm_roundscale_sd(A, B, imm) \
(__m128d)__builtin_ia32_rndscalesd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)-1, (int)(imm), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_roundscale_sd(W, U, A, B, imm) __extension__ ({ \
+#define _mm_mask_roundscale_sd(W, U, A, B, imm) \
(__m128d)__builtin_ia32_rndscalesd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
(__mmask8)(U), (int)(imm), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_roundscale_round_sd(W, U, A, B, I, R) __extension__ ({ \
+#define _mm_mask_roundscale_round_sd(W, U, A, B, I, R) \
(__m128d)__builtin_ia32_rndscalesd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
(__mmask8)(U), (int)(I), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_roundscale_sd(U, A, B, I) __extension__ ({ \
+#define _mm_maskz_roundscale_sd(U, A, B, I) \
(__m128d)__builtin_ia32_rndscalesd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(U), (int)(I), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_roundscale_round_sd(U, A, B, I, R) __extension__ ({ \
+#define _mm_maskz_roundscale_round_sd(U, A, B, I, R) \
(__m128d)__builtin_ia32_rndscalesd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(U), (int)(I), \
- (int)(R)); })
+ (int)(R))
-#define _mm_roundscale_round_ss(A, B, imm, R) __extension__ ({ \
+#define _mm_roundscale_round_ss(A, B, imm, R) \
(__m128)__builtin_ia32_rndscaless_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)-1, (int)(imm), \
- (int)(R)); })
+ (int)(R))
-#define _mm_roundscale_ss(A, B, imm) __extension__ ({ \
+#define _mm_roundscale_ss(A, B, imm) \
(__m128)__builtin_ia32_rndscaless_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)-1, (int)(imm), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_roundscale_ss(W, U, A, B, I) __extension__ ({ \
+#define _mm_mask_roundscale_ss(W, U, A, B, I) \
(__m128)__builtin_ia32_rndscaless_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), \
(__mmask8)(U), (int)(I), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_roundscale_round_ss(W, U, A, B, I, R) __extension__ ({ \
+#define _mm_mask_roundscale_round_ss(W, U, A, B, I, R) \
(__m128)__builtin_ia32_rndscaless_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), \
(__mmask8)(U), (int)(I), \
- (int)(R)); })
+ (int)(R))
-#define _mm_maskz_roundscale_ss(U, A, B, I) __extension__ ({ \
+#define _mm_maskz_roundscale_ss(U, A, B, I) \
(__m128)__builtin_ia32_rndscaless_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), (int)(I), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_maskz_roundscale_round_ss(U, A, B, I, R) __extension__ ({ \
+#define _mm_maskz_roundscale_round_ss(U, A, B, I, R) \
(__m128)__builtin_ia32_rndscaless_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), (int)(I), \
- (int)(R)); })
+ (int)(R))
-#define _mm512_scalef_round_pd(A, B, R) __extension__ ({ \
+#define _mm512_scalef_round_pd(A, B, R) \
(__m512d)__builtin_ia32_scalefpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_scalef_round_pd(W, U, A, B, R) __extension__ ({ \
+#define _mm512_mask_scalef_round_pd(W, U, A, B, R) \
(__m512d)__builtin_ia32_scalefpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_scalef_round_pd(U, A, B, R) __extension__ ({ \
+#define _mm512_maskz_scalef_round_pd(U, A, B, R) \
(__m512d)__builtin_ia32_scalefpd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_scalef_pd (__m512d __A, __m512d __B)
{
return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A,
@@ -6736,7 +6410,7 @@ _mm512_scalef_pd (__m512d __A, __m512d __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_scalef_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A,
@@ -6746,7 +6420,7 @@ _mm512_mask_scalef_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_scalef_pd (__mmask8 __U, __m512d __A, __m512d __B)
{
return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A,
@@ -6757,25 +6431,25 @@ _mm512_maskz_scalef_pd (__mmask8 __U, __m512d __A, __m512d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_scalef_round_ps(A, B, R) __extension__ ({ \
+#define _mm512_scalef_round_ps(A, B, R) \
(__m512)__builtin_ia32_scalefps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_scalef_round_ps(W, U, A, B, R) __extension__ ({ \
+#define _mm512_mask_scalef_round_ps(W, U, A, B, R) \
(__m512)__builtin_ia32_scalefps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_scalef_round_ps(U, A, B, R) __extension__ ({ \
+#define _mm512_maskz_scalef_round_ps(U, A, B, R) \
(__m512)__builtin_ia32_scalefps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(B), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_scalef_ps (__m512 __A, __m512 __B)
{
return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A,
@@ -6786,7 +6460,7 @@ _mm512_scalef_ps (__m512 __A, __m512 __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_scalef_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A,
@@ -6796,7 +6470,7 @@ _mm512_mask_scalef_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_scalef_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A,
@@ -6807,13 +6481,13 @@ _mm512_maskz_scalef_ps (__mmask16 __U, __m512 __A, __m512 __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_scalef_round_sd(A, B, R) __extension__ ({ \
+#define _mm_scalef_round_sd(A, B, R) \
(__m128d)__builtin_ia32_scalefsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_scalef_sd (__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_scalefsd_round_mask ((__v2df) __A,
@@ -6822,7 +6496,7 @@ _mm_scalef_sd (__m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_scalef_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_scalefsd_round_mask ( (__v2df) __A,
@@ -6832,13 +6506,13 @@ _mm_mask_scalef_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_scalef_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_scalef_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_scalefsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_scalef_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_scalefsd_round_mask ( (__v2df) __A,
@@ -6848,19 +6522,19 @@ _mm_maskz_scalef_sd (__mmask8 __U, __m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_scalef_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_scalef_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_scalefsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_scalef_round_ss(A, B, R) __extension__ ({ \
+#define _mm_scalef_round_ss(A, B, R) \
(__m128)__builtin_ia32_scalefss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_scalef_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_scalefss_round_mask ((__v4sf) __A,
@@ -6869,7 +6543,7 @@ _mm_scalef_ss (__m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_scalef_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_scalefss_round_mask ( (__v4sf) __A,
@@ -6879,13 +6553,13 @@ _mm_mask_scalef_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_scalef_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_scalef_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_scalefss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_scalef_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_scalefss_round_mask ( (__v4sf) __A,
@@ -6895,211 +6569,147 @@ _mm_maskz_scalef_ss (__mmask8 __U, __m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_scalef_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_scalef_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_scalefss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srai_epi32(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psradi512((__v16si)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
{
- return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, \
- (__v16si)_mm512_srai_epi32(__A, __B), \
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srai_epi32(__A, __B),
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A, int __B) {
- return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, \
- (__v16si)_mm512_srai_epi32(__A, __B), \
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srai_epi32(__A, __B),
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srai_epi64(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psraqi512((__v8di)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
{
- return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, \
- (__v8di)_mm512_srai_epi64(__A, __B), \
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srai_epi64(__A, __B),
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B)
{
- return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, \
- (__v8di)_mm512_srai_epi64(__A, __B), \
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srai_epi64(__A, __B),
(__v8di)_mm512_setzero_si512());
}
-#define _mm512_shuffle_f32x4(A, B, imm) __extension__ ({ \
- (__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__ ({ \
+#define _mm512_shuffle_f32x4(A, B, imm) \
+ (__m512)__builtin_ia32_shuf_f32x4((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(imm))
+
+#define _mm512_mask_shuffle_f32x4(W, U, A, B, imm) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \
- (__v16sf)(__m512)(W)); })
+ (__v16sf)(__m512)(W))
-#define _mm512_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_shuffle_f32x4(U, A, B, imm) \
(__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_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__ ({ \
+ (__v16sf)_mm512_setzero_ps())
+
+#define _mm512_shuffle_f64x2(A, B, imm) \
+ (__m512d)__builtin_ia32_shuf_f64x2((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(imm))
+
+#define _mm512_mask_shuffle_f64x2(W, U, A, B, imm) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \
- (__v8df)(__m512d)(W)); })
+ (__v8df)(__m512d)(W))
-#define _mm512_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_shuffle_f64x2(U, A, B, imm) \
(__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_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__ ({ \
+ (__v8df)_mm512_setzero_pd())
+
+#define _mm512_shuffle_i32x4(A, B, imm) \
+ (__m512i)__builtin_ia32_shuf_i32x4((__v16si)(__m512i)(A), \
+ (__v16si)(__m512i)(B), (int)(imm))
+
+#define _mm512_mask_shuffle_i32x4(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \
- (__v16si)(__m512i)(W)); })
+ (__v16si)(__m512i)(W))
-#define _mm512_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_shuffle_i32x4(U, A, B, imm) \
(__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_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__ ({ \
+ (__v16si)_mm512_setzero_si512())
+
+#define _mm512_shuffle_i64x2(A, B, imm) \
+ (__m512i)__builtin_ia32_shuf_i64x2((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), (int)(imm))
+
+#define _mm512_mask_shuffle_i64x2(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \
- (__v8di)(__m512i)(W)); })
+ (__v8di)(__m512i)(W))
-#define _mm512_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_shuffle_i64x2(U, A, B, imm) \
(__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), \
- (__v8df)(__m512d)(B), \
- 0 + (((M) >> 0) & 0x1), \
- 8 + (((M) >> 1) & 0x1), \
- 2 + (((M) >> 2) & 0x1), \
- 10 + (((M) >> 3) & 0x1), \
- 4 + (((M) >> 4) & 0x1), \
- 12 + (((M) >> 5) & 0x1), \
- 6 + (((M) >> 6) & 0x1), \
- 14 + (((M) >> 7) & 0x1)); })
-
-#define _mm512_mask_shuffle_pd(W, U, A, B, M) __extension__ ({ \
+ (__v8di)_mm512_setzero_si512())
+
+#define _mm512_shuffle_pd(A, B, M) \
+ (__m512d)__builtin_ia32_shufpd512((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), (int)(M))
+
+#define _mm512_mask_shuffle_pd(W, U, A, B, M) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_shuffle_pd((A), (B), (M)), \
- (__v8df)(__m512d)(W)); })
+ (__v8df)(__m512d)(W))
-#define _mm512_maskz_shuffle_pd(U, A, B, M) __extension__ ({ \
+#define _mm512_maskz_shuffle_pd(U, A, B, M) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_shuffle_pd((A), (B), (M)), \
- (__v8df)_mm512_setzero_pd()); })
-
-#define _mm512_shuffle_ps(A, B, M) __extension__ ({ \
- (__m512d)__builtin_shufflevector((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), \
- 0 + (((M) >> 0) & 0x3), \
- 0 + (((M) >> 2) & 0x3), \
- 16 + (((M) >> 4) & 0x3), \
- 16 + (((M) >> 6) & 0x3), \
- 4 + (((M) >> 0) & 0x3), \
- 4 + (((M) >> 2) & 0x3), \
- 20 + (((M) >> 4) & 0x3), \
- 20 + (((M) >> 6) & 0x3), \
- 8 + (((M) >> 0) & 0x3), \
- 8 + (((M) >> 2) & 0x3), \
- 24 + (((M) >> 4) & 0x3), \
- 24 + (((M) >> 6) & 0x3), \
- 12 + (((M) >> 0) & 0x3), \
- 12 + (((M) >> 2) & 0x3), \
- 28 + (((M) >> 4) & 0x3), \
- 28 + (((M) >> 6) & 0x3)); })
-
-#define _mm512_mask_shuffle_ps(W, U, A, B, M) __extension__ ({ \
+ (__v8df)_mm512_setzero_pd())
+
+#define _mm512_shuffle_ps(A, B, M) \
+ (__m512)__builtin_ia32_shufps512((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), (int)(M))
+
+#define _mm512_mask_shuffle_ps(W, U, A, B, M) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_shuffle_ps((A), (B), (M)), \
- (__v16sf)(__m512)(W)); })
+ (__v16sf)(__m512)(W))
-#define _mm512_maskz_shuffle_ps(U, A, B, M) __extension__ ({ \
+#define _mm512_maskz_shuffle_ps(U, A, B, M) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_shuffle_ps((A), (B), (M)), \
- (__v16sf)_mm512_setzero_ps()); })
+ (__v16sf)_mm512_setzero_ps())
-#define _mm_sqrt_round_sd(A, B, R) __extension__ ({ \
+#define _mm_sqrt_round_sd(A, B, R) \
(__m128d)__builtin_ia32_sqrtsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_sqrt_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_sqrtsd_round_mask ( (__v2df) __A,
@@ -7109,13 +6719,13 @@ _mm_mask_sqrt_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_sqrt_round_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_sqrt_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_sqrtsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_sqrt_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_sqrtsd_round_mask ( (__v2df) __A,
@@ -7125,19 +6735,19 @@ _mm_maskz_sqrt_sd (__mmask8 __U, __m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_sqrt_round_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_sqrt_round_sd(U, A, B, R) \
(__m128d)__builtin_ia32_sqrtsd_round_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_sqrt_round_ss(A, B, R) __extension__ ({ \
+#define _mm_sqrt_round_ss(A, B, R) \
(__m128)__builtin_ia32_sqrtss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_sqrt_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_sqrtss_round_mask ( (__v4sf) __A,
@@ -7147,13 +6757,13 @@ _mm_mask_sqrt_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_sqrt_round_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_sqrt_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_sqrtss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(W), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_sqrt_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_sqrtss_round_mask ( (__v4sf) __A,
@@ -7163,13 +6773,13 @@ _mm_maskz_sqrt_ss (__mmask8 __U, __m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_sqrt_round_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_sqrt_round_ss(U, A, B, R) \
(__m128)__builtin_ia32_sqrtss_round_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_broadcast_f32x4(__m128 __A)
{
return (__m512)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A,
@@ -7177,7 +6787,7 @@ _mm512_broadcast_f32x4(__m128 __A)
0, 1, 2, 3, 0, 1, 2, 3);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_f32x4(__m512 __O, __mmask16 __M, __m128 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
@@ -7185,7 +6795,7 @@ _mm512_mask_broadcast_f32x4(__m512 __O, __mmask16 __M, __m128 __A)
(__v16sf)__O);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_f32x4(__mmask16 __M, __m128 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
@@ -7193,14 +6803,14 @@ _mm512_maskz_broadcast_f32x4(__mmask16 __M, __m128 __A)
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_broadcast_f64x4(__m256d __A)
{
return (__m512d)__builtin_shufflevector((__v4df)__A, (__v4df)__A,
0, 1, 2, 3, 0, 1, 2, 3);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, __m256d __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__M,
@@ -7208,7 +6818,7 @@ _mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, __m256d __A)
(__v8df)__O);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_f64x4(__mmask8 __M, __m256d __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__M,
@@ -7216,7 +6826,7 @@ _mm512_maskz_broadcast_f64x4(__mmask8 __M, __m256d __A)
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcast_i32x4(__m128i __A)
{
return (__m512i)__builtin_shufflevector((__v4si)__A, (__v4si)__A,
@@ -7224,7 +6834,7 @@ _mm512_broadcast_i32x4(__m128i __A)
0, 1, 2, 3, 0, 1, 2, 3);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_i32x4(__m512i __O, __mmask16 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -7232,7 +6842,7 @@ _mm512_mask_broadcast_i32x4(__m512i __O, __mmask16 __M, __m128i __A)
(__v16si)__O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_i32x4(__mmask16 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -7240,14 +6850,14 @@ _mm512_maskz_broadcast_i32x4(__mmask16 __M, __m128i __A)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcast_i64x4(__m256i __A)
{
return (__m512i)__builtin_shufflevector((__v4di)__A, (__v4di)__A,
0, 1, 2, 3, 0, 1, 2, 3);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_i64x4(__m512i __O, __mmask8 __M, __m256i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -7255,7 +6865,7 @@ _mm512_mask_broadcast_i64x4(__m512i __O, __mmask8 __M, __m256i __A)
(__v8di)__O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_i64x4(__mmask8 __M, __m256i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -7263,7 +6873,7 @@ _mm512_maskz_broadcast_i64x4(__mmask8 __M, __m256i __A)
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_broadcastsd_pd (__m512d __O, __mmask8 __M, __m128d __A)
{
return (__m512d)__builtin_ia32_selectpd_512(__M,
@@ -7271,7 +6881,7 @@ _mm512_mask_broadcastsd_pd (__m512d __O, __mmask8 __M, __m128d __A)
(__v8df) __O);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A)
{
return (__m512d)__builtin_ia32_selectpd_512(__M,
@@ -7279,7 +6889,7 @@ _mm512_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A)
(__v8df) _mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_broadcastss_ps (__m512 __O, __mmask16 __M, __m128 __A)
{
return (__m512)__builtin_ia32_selectps_512(__M,
@@ -7287,7 +6897,7 @@ _mm512_mask_broadcastss_ps (__m512 __O, __mmask16 __M, __m128 __A)
(__v16sf) __O);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcastss_ps (__mmask16 __M, __m128 __A)
{
return (__m512)__builtin_ia32_selectps_512(__M,
@@ -7295,7 +6905,7 @@ _mm512_maskz_broadcastss_ps (__mmask16 __M, __m128 __A)
(__v16sf) _mm512_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtsepi32_epi8 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A,
@@ -7303,14 +6913,14 @@ _mm512_cvtsepi32_epi8 (__m512i __A)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtsepi32_epi8 (__mmask16 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A,
@@ -7318,13 +6928,13 @@ _mm512_maskz_cvtsepi32_epi8 (__mmask16 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A)
{
__builtin_ia32_pmovsdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtsepi32_epi16 (__m512i __A)
{
return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A,
@@ -7332,14 +6942,14 @@ _mm512_cvtsepi32_epi16 (__m512i __A)
(__mmask16) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A,
(__v16hi) __O, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtsepi32_epi16 (__mmask16 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A,
@@ -7347,13 +6957,13 @@ _mm512_maskz_cvtsepi32_epi16 (__mmask16 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi32_storeu_epi16 (void *__P, __mmask16 __M, __m512i __A)
{
__builtin_ia32_pmovsdw512mem_mask ((__v16hi*) __P, (__v16si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtsepi64_epi8 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A,
@@ -7361,14 +6971,14 @@ _mm512_cvtsepi64_epi8 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtsepi64_epi8 (__mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A,
@@ -7376,13 +6986,13 @@ _mm512_maskz_cvtsepi64_epi8 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovsqb512mem_mask ((__v16qi *) __P, (__v8di) __A, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtsepi64_epi32 (__m512i __A)
{
return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A,
@@ -7390,14 +7000,14 @@ _mm512_cvtsepi64_epi32 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A,
(__v8si) __O, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtsepi64_epi32 (__mmask8 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A,
@@ -7405,13 +7015,13 @@ _mm512_maskz_cvtsepi64_epi32 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi64_storeu_epi32 (void *__P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovsqd512mem_mask ((__v8si *) __P, (__v8di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtsepi64_epi16 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A,
@@ -7419,14 +7029,14 @@ _mm512_cvtsepi64_epi16 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtsepi64_epi16 (__mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A,
@@ -7434,13 +7044,13 @@ _mm512_maskz_cvtsepi64_epi16 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovsqw512mem_mask ((__v8hi *) __P, (__v8di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtusepi32_epi8 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A,
@@ -7448,7 +7058,7 @@ _mm512_cvtusepi32_epi8 (__m512i __A)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A,
@@ -7456,7 +7066,7 @@ _mm512_mask_cvtusepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtusepi32_epi8 (__mmask16 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A,
@@ -7464,13 +7074,13 @@ _mm512_maskz_cvtusepi32_epi8 (__mmask16 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A)
{
__builtin_ia32_pmovusdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtusepi32_epi16 (__m512i __A)
{
return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A,
@@ -7478,7 +7088,7 @@ _mm512_cvtusepi32_epi16 (__m512i __A)
(__mmask16) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A,
@@ -7486,7 +7096,7 @@ _mm512_mask_cvtusepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A)
__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtusepi32_epi16 (__mmask16 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A,
@@ -7494,13 +7104,13 @@ _mm512_maskz_cvtusepi32_epi16 (__mmask16 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi32_storeu_epi16 (void *__P, __mmask16 __M, __m512i __A)
{
__builtin_ia32_pmovusdw512mem_mask ((__v16hi*) __P, (__v16si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtusepi64_epi8 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A,
@@ -7508,7 +7118,7 @@ _mm512_cvtusepi64_epi8 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A,
@@ -7516,7 +7126,7 @@ _mm512_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtusepi64_epi8 (__mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A,
@@ -7524,13 +7134,13 @@ _mm512_maskz_cvtusepi64_epi8 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovusqb512mem_mask ((__v16qi *) __P, (__v8di) __A, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtusepi64_epi32 (__m512i __A)
{
return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A,
@@ -7538,14 +7148,14 @@ _mm512_cvtusepi64_epi32 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A,
(__v8si) __O, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtusepi64_epi32 (__mmask8 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A,
@@ -7553,13 +7163,13 @@ _mm512_maskz_cvtusepi64_epi32 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovusqd512mem_mask ((__v8si*) __P, (__v8di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtusepi64_epi16 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A,
@@ -7567,14 +7177,14 @@ _mm512_cvtusepi64_epi16 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtusepi64_epi16 (__mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A,
@@ -7582,13 +7192,13 @@ _mm512_maskz_cvtusepi64_epi16 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovusqw512mem_mask ((__v8hi*) __P, (__v8di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtepi32_epi8 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A,
@@ -7596,14 +7206,14 @@ _mm512_cvtepi32_epi8 (__m512i __A)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi32_epi8 (__mmask16 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A,
@@ -7611,13 +7221,13 @@ _mm512_maskz_cvtepi32_epi8 (__mmask16 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A)
{
__builtin_ia32_pmovdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtepi32_epi16 (__m512i __A)
{
return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A,
@@ -7625,14 +7235,14 @@ _mm512_cvtepi32_epi16 (__m512i __A)
(__mmask16) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A,
(__v16hi) __O, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi32_epi16 (__mmask16 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A,
@@ -7640,13 +7250,13 @@ _mm512_maskz_cvtepi32_epi16 (__mmask16 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi32_storeu_epi16 (void * __P, __mmask16 __M, __m512i __A)
{
__builtin_ia32_pmovdw512mem_mask ((__v16hi *) __P, (__v16si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtepi64_epi8 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A,
@@ -7654,14 +7264,14 @@ _mm512_cvtepi64_epi8 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi64_epi8 (__mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A,
@@ -7669,13 +7279,13 @@ _mm512_maskz_cvtepi64_epi8 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovqb512mem_mask ((__v16qi *) __P, (__v8di) __A, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtepi64_epi32 (__m512i __A)
{
return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A,
@@ -7683,14 +7293,14 @@ _mm512_cvtepi64_epi32 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A,
(__v8si) __O, __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi64_epi32 (__mmask8 __M, __m512i __A)
{
return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A,
@@ -7698,13 +7308,13 @@ _mm512_maskz_cvtepi64_epi32 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovqd512mem_mask ((__v8si *) __P, (__v8di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_cvtepi64_epi16 (__m512i __A)
{
return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A,
@@ -7712,14 +7322,14 @@ _mm512_cvtepi64_epi16 (__m512i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi64_epi16 (__mmask8 __M, __m512i __A)
{
return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A,
@@ -7727,246 +7337,192 @@ _mm512_maskz_cvtepi64_epi16 (__mmask8 __M, __m512i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A)
{
__builtin_ia32_pmovqw512mem_mask ((__v8hi *) __P, (__v8di) __A, __M);
}
-#define _mm512_extracti32x4_epi32(A, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v16si)(__m512i)(A), \
- (__v16si)_mm512_undefined_epi32(), \
- 0 + ((imm) & 0x3) * 4, \
- 1 + ((imm) & 0x3) * 4, \
- 2 + ((imm) & 0x3) * 4, \
- 3 + ((imm) & 0x3) * 4); })
-
-#define _mm512_mask_extracti32x4_epi32(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
- (__v4si)_mm512_extracti32x4_epi32((A), (imm)), \
- (__v4si)(W)); })
-
-#define _mm512_maskz_extracti32x4_epi32(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
- (__v4si)_mm512_extracti32x4_epi32((A), (imm)), \
- (__v4si)_mm_setzero_si128()); })
-
-#define _mm512_extracti64x4_epi64(A, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v8di)(__m512i)(A), \
- (__v8di)_mm512_undefined_epi32(), \
- ((imm) & 1) ? 4 : 0, \
- ((imm) & 1) ? 5 : 1, \
- ((imm) & 1) ? 6 : 2, \
- ((imm) & 1) ? 7 : 3); })
-
-#define _mm512_mask_extracti64x4_epi64(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
- (__v4di)_mm512_extracti64x4_epi64((A), (imm)), \
- (__v4di)(W)); })
-
-#define _mm512_maskz_extracti64x4_epi64(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
- (__v4di)_mm512_extracti64x4_epi64((A), (imm)), \
- (__v4di)_mm256_setzero_si256()); })
-
-#define _mm512_insertf64x4(A, B, imm) __extension__ ({ \
- (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \
- (__v8df)_mm512_castpd256_pd512((__m256d)(B)), \
- ((imm) & 0x1) ? 0 : 8, \
- ((imm) & 0x1) ? 1 : 9, \
- ((imm) & 0x1) ? 2 : 10, \
- ((imm) & 0x1) ? 3 : 11, \
- ((imm) & 0x1) ? 8 : 4, \
- ((imm) & 0x1) ? 9 : 5, \
- ((imm) & 0x1) ? 10 : 6, \
- ((imm) & 0x1) ? 11 : 7); })
-
-#define _mm512_mask_insertf64x4(W, U, A, B, imm) __extension__ ({ \
+#define _mm512_extracti32x4_epi32(A, imm) \
+ (__m128i)__builtin_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \
+ (__v4si)_mm_undefined_si128(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extracti32x4_epi32(W, U, A, imm) \
+ (__m128i)__builtin_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \
+ (__v4si)(__m128i)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extracti32x4_epi32(U, A, imm) \
+ (__m128i)__builtin_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \
+ (__v4si)_mm_setzero_si128(), \
+ (__mmask8)(U))
+
+#define _mm512_extracti64x4_epi64(A, imm) \
+ (__m256i)__builtin_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \
+ (__v4di)_mm256_undefined_si256(), \
+ (__mmask8)-1)
+
+#define _mm512_mask_extracti64x4_epi64(W, U, A, imm) \
+ (__m256i)__builtin_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \
+ (__v4di)(__m256i)(W), \
+ (__mmask8)(U))
+
+#define _mm512_maskz_extracti64x4_epi64(U, A, imm) \
+ (__m256i)__builtin_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \
+ (__v4di)_mm256_setzero_si256(), \
+ (__mmask8)(U))
+
+#define _mm512_insertf64x4(A, B, imm) \
+ (__m512d)__builtin_ia32_insertf64x4((__v8df)(__m512d)(A), \
+ (__v4df)(__m256d)(B), (int)(imm))
+
+#define _mm512_mask_insertf64x4(W, U, A, B, imm) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_insertf64x4((A), (B), (imm)), \
- (__v8df)(W)); })
+ (__v8df)(__m512d)(W))
-#define _mm512_maskz_insertf64x4(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_insertf64x4(U, A, B, imm) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_insertf64x4((A), (B), (imm)), \
- (__v8df)_mm512_setzero_pd()); })
-
-#define _mm512_inserti64x4(A, B, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \
- (__v8di)_mm512_castsi256_si512((__m256i)(B)), \
- ((imm) & 0x1) ? 0 : 8, \
- ((imm) & 0x1) ? 1 : 9, \
- ((imm) & 0x1) ? 2 : 10, \
- ((imm) & 0x1) ? 3 : 11, \
- ((imm) & 0x1) ? 8 : 4, \
- ((imm) & 0x1) ? 9 : 5, \
- ((imm) & 0x1) ? 10 : 6, \
- ((imm) & 0x1) ? 11 : 7); })
-
-#define _mm512_mask_inserti64x4(W, U, A, B, imm) __extension__ ({ \
+ (__v8df)_mm512_setzero_pd())
+
+#define _mm512_inserti64x4(A, B, imm) \
+ (__m512i)__builtin_ia32_inserti64x4((__v8di)(__m512i)(A), \
+ (__v4di)(__m256i)(B), (int)(imm))
+
+#define _mm512_mask_inserti64x4(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_inserti64x4((A), (B), (imm)), \
- (__v8di)(W)); })
+ (__v8di)(__m512i)(W))
-#define _mm512_maskz_inserti64x4(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_inserti64x4(U, A, B, imm) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_inserti64x4((A), (B), (imm)), \
- (__v8di)_mm512_setzero_si512()); })
-
-#define _mm512_insertf32x4(A, B, imm) __extension__ ({ \
- (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \
- (__v16sf)_mm512_castps128_ps512((__m128)(B)),\
- (((imm) & 0x3) == 0) ? 16 : 0, \
- (((imm) & 0x3) == 0) ? 17 : 1, \
- (((imm) & 0x3) == 0) ? 18 : 2, \
- (((imm) & 0x3) == 0) ? 19 : 3, \
- (((imm) & 0x3) == 1) ? 16 : 4, \
- (((imm) & 0x3) == 1) ? 17 : 5, \
- (((imm) & 0x3) == 1) ? 18 : 6, \
- (((imm) & 0x3) == 1) ? 19 : 7, \
- (((imm) & 0x3) == 2) ? 16 : 8, \
- (((imm) & 0x3) == 2) ? 17 : 9, \
- (((imm) & 0x3) == 2) ? 18 : 10, \
- (((imm) & 0x3) == 2) ? 19 : 11, \
- (((imm) & 0x3) == 3) ? 16 : 12, \
- (((imm) & 0x3) == 3) ? 17 : 13, \
- (((imm) & 0x3) == 3) ? 18 : 14, \
- (((imm) & 0x3) == 3) ? 19 : 15); })
-
-#define _mm512_mask_insertf32x4(W, U, A, B, imm) __extension__ ({ \
+ (__v8di)_mm512_setzero_si512())
+
+#define _mm512_insertf32x4(A, B, imm) \
+ (__m512)__builtin_ia32_insertf32x4((__v16sf)(__m512)(A), \
+ (__v4sf)(__m128)(B), (int)(imm))
+
+#define _mm512_mask_insertf32x4(W, U, A, B, imm) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_insertf32x4((A), (B), (imm)), \
- (__v16sf)(W)); })
+ (__v16sf)(__m512)(W))
-#define _mm512_maskz_insertf32x4(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_insertf32x4(U, A, B, imm) \
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
(__v16sf)_mm512_insertf32x4((A), (B), (imm)), \
- (__v16sf)_mm512_setzero_ps()); })
-
-#define _mm512_inserti32x4(A, B, imm) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v16si)(__m512i)(A), \
- (__v16si)_mm512_castsi128_si512((__m128i)(B)),\
- (((imm) & 0x3) == 0) ? 16 : 0, \
- (((imm) & 0x3) == 0) ? 17 : 1, \
- (((imm) & 0x3) == 0) ? 18 : 2, \
- (((imm) & 0x3) == 0) ? 19 : 3, \
- (((imm) & 0x3) == 1) ? 16 : 4, \
- (((imm) & 0x3) == 1) ? 17 : 5, \
- (((imm) & 0x3) == 1) ? 18 : 6, \
- (((imm) & 0x3) == 1) ? 19 : 7, \
- (((imm) & 0x3) == 2) ? 16 : 8, \
- (((imm) & 0x3) == 2) ? 17 : 9, \
- (((imm) & 0x3) == 2) ? 18 : 10, \
- (((imm) & 0x3) == 2) ? 19 : 11, \
- (((imm) & 0x3) == 3) ? 16 : 12, \
- (((imm) & 0x3) == 3) ? 17 : 13, \
- (((imm) & 0x3) == 3) ? 18 : 14, \
- (((imm) & 0x3) == 3) ? 19 : 15); })
-
-#define _mm512_mask_inserti32x4(W, U, A, B, imm) __extension__ ({ \
+ (__v16sf)_mm512_setzero_ps())
+
+#define _mm512_inserti32x4(A, B, imm) \
+ (__m512i)__builtin_ia32_inserti32x4((__v16si)(__m512i)(A), \
+ (__v4si)(__m128i)(B), (int)(imm))
+
+#define _mm512_mask_inserti32x4(W, U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_inserti32x4((A), (B), (imm)), \
- (__v16si)(W)); })
+ (__v16si)(__m512i)(W))
-#define _mm512_maskz_inserti32x4(U, A, B, imm) __extension__ ({ \
+#define _mm512_maskz_inserti32x4(U, A, B, imm) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_inserti32x4((A), (B), (imm)), \
- (__v16si)_mm512_setzero_si512()); })
+ (__v16si)_mm512_setzero_si512())
-#define _mm512_getmant_round_pd(A, B, C, R) __extension__ ({ \
+#define _mm512_getmant_round_pd(A, B, C, R) \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
(int)(((C)<<2) | (B)), \
(__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_getmant_round_pd(W, U, A, B, C, R) __extension__ ({ \
+#define _mm512_mask_getmant_round_pd(W, U, A, B, C, R) \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
(int)(((C)<<2) | (B)), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_getmant_round_pd(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_getmant_round_pd(U, A, B, C, R) \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
(int)(((C)<<2) | (B)), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_getmant_pd(A, B, C) __extension__ ({ \
+#define _mm512_getmant_pd(A, B, C) \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
(int)(((C)<<2) | (B)), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_getmant_pd(W, U, A, B, C) __extension__ ({ \
+#define _mm512_mask_getmant_pd(W, U, A, B, C) \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
(int)(((C)<<2) | (B)), \
(__v8df)(__m512d)(W), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_getmant_pd(U, A, B, C) __extension__ ({ \
+#define _mm512_maskz_getmant_pd(U, A, B, C) \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
(int)(((C)<<2) | (B)), \
(__v8df)_mm512_setzero_pd(), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_getmant_round_ps(A, B, C, R) __extension__ ({ \
+#define _mm512_getmant_round_ps(A, B, C, R) \
(__m512)__builtin_ia32_getmantps512_mask((__v16sf)(__m512)(A), \
(int)(((C)<<2) | (B)), \
(__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_getmant_round_ps(W, U, A, B, C, R) __extension__ ({ \
+#define _mm512_mask_getmant_round_ps(W, U, A, B, C, R) \
(__m512)__builtin_ia32_getmantps512_mask((__v16sf)(__m512)(A), \
(int)(((C)<<2) | (B)), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_getmant_round_ps(U, A, B, C, R) __extension__ ({ \
+#define _mm512_maskz_getmant_round_ps(U, A, B, C, R) \
(__m512)__builtin_ia32_getmantps512_mask((__v16sf)(__m512)(A), \
(int)(((C)<<2) | (B)), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_getmant_ps(A, B, C) __extension__ ({ \
+#define _mm512_getmant_ps(A, B, C) \
(__m512)__builtin_ia32_getmantps512_mask((__v16sf)(__m512)(A), \
(int)(((C)<<2)|(B)), \
(__v16sf)_mm512_undefined_ps(), \
(__mmask16)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_mask_getmant_ps(W, U, A, B, C) __extension__ ({ \
+#define _mm512_mask_getmant_ps(W, U, A, B, C) \
(__m512)__builtin_ia32_getmantps512_mask((__v16sf)(__m512)(A), \
(int)(((C)<<2)|(B)), \
(__v16sf)(__m512)(W), \
(__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_maskz_getmant_ps(U, A, B, C) __extension__ ({ \
+#define _mm512_maskz_getmant_ps(U, A, B, C) \
(__m512)__builtin_ia32_getmantps512_mask((__v16sf)(__m512)(A), \
(int)(((C)<<2)|(B)), \
(__v16sf)_mm512_setzero_ps(), \
(__mmask16)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm512_getexp_round_pd(A, R) __extension__ ({ \
+#define _mm512_getexp_round_pd(A, R) \
(__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_getexp_round_pd(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_getexp_round_pd(W, U, A, R) \
(__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_getexp_round_pd(U, A, R) __extension__ ({ \
+#define _mm512_maskz_getexp_round_pd(U, A, R) \
(__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_getexp_pd (__m512d __A)
{
return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A,
@@ -7975,7 +7531,7 @@ _mm512_getexp_pd (__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_getexp_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A,
@@ -7984,7 +7540,7 @@ _mm512_mask_getexp_pd (__m512d __W, __mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_getexp_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A,
@@ -7993,22 +7549,22 @@ _mm512_maskz_getexp_pd (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_getexp_round_ps(A, R) __extension__ ({ \
+#define _mm512_getexp_round_ps(A, R) \
(__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1, (int)(R)); })
+ (__mmask16)-1, (int)(R))
-#define _mm512_mask_getexp_round_ps(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_getexp_round_ps(W, U, A, R) \
(__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)(__m512)(W), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-#define _mm512_maskz_getexp_round_ps(U, A, R) __extension__ ({ \
+#define _mm512_maskz_getexp_round_ps(U, A, R) \
(__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U), (int)(R)); })
+ (__mmask16)(U), (int)(R))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_getexp_ps (__m512 __A)
{
return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A,
@@ -8017,7 +7573,7 @@ _mm512_getexp_ps (__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_getexp_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A,
@@ -8026,7 +7582,7 @@ _mm512_mask_getexp_ps (__m512 __W, __mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A,
@@ -8035,802 +7591,812 @@ _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-#define _mm512_i64gather_ps(index, addr, scale) __extension__ ({ \
+#define _mm512_i64gather_ps(index, addr, scale) \
(__m256)__builtin_ia32_gatherdiv16sf((__v8sf)_mm256_undefined_ps(), \
(float const *)(addr), \
(__v8di)(__m512i)(index), (__mmask8)-1, \
- (int)(scale)); })
+ (int)(scale))
-#define _mm512_mask_i64gather_ps(v1_old, mask, index, addr, scale) __extension__({\
+#define _mm512_mask_i64gather_ps(v1_old, mask, index, addr, scale) \
(__m256)__builtin_ia32_gatherdiv16sf((__v8sf)(__m256)(v1_old),\
(float const *)(addr), \
(__v8di)(__m512i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm512_i64gather_epi32(index, addr, scale) __extension__ ({\
- (__m256i)__builtin_ia32_gatherdiv16si((__v8si)_mm256_undefined_ps(), \
+#define _mm512_i64gather_epi32(index, addr, scale) \
+ (__m256i)__builtin_ia32_gatherdiv16si((__v8si)_mm256_undefined_si256(), \
(int const *)(addr), \
(__v8di)(__m512i)(index), \
- (__mmask8)-1, (int)(scale)); })
+ (__mmask8)-1, (int)(scale))
-#define _mm512_mask_i64gather_epi32(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i64gather_epi32(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gatherdiv16si((__v8si)(__m256i)(v1_old), \
(int const *)(addr), \
(__v8di)(__m512i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm512_i64gather_pd(index, addr, scale) __extension__ ({\
+#define _mm512_i64gather_pd(index, addr, scale) \
(__m512d)__builtin_ia32_gatherdiv8df((__v8df)_mm512_undefined_pd(), \
(double const *)(addr), \
(__v8di)(__m512i)(index), (__mmask8)-1, \
- (int)(scale)); })
+ (int)(scale))
-#define _mm512_mask_i64gather_pd(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i64gather_pd(v1_old, mask, index, addr, scale) \
(__m512d)__builtin_ia32_gatherdiv8df((__v8df)(__m512d)(v1_old), \
(double const *)(addr), \
(__v8di)(__m512i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm512_i64gather_epi64(index, addr, scale) __extension__ ({\
- (__m512i)__builtin_ia32_gatherdiv8di((__v8di)_mm512_undefined_pd(), \
+#define _mm512_i64gather_epi64(index, addr, scale) \
+ (__m512i)__builtin_ia32_gatherdiv8di((__v8di)_mm512_undefined_epi32(), \
(long long const *)(addr), \
(__v8di)(__m512i)(index), (__mmask8)-1, \
- (int)(scale)); })
+ (int)(scale))
-#define _mm512_mask_i64gather_epi64(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i64gather_epi64(v1_old, mask, index, addr, scale) \
(__m512i)__builtin_ia32_gatherdiv8di((__v8di)(__m512i)(v1_old), \
(long long const *)(addr), \
(__v8di)(__m512i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm512_i32gather_ps(index, addr, scale) __extension__ ({\
+#define _mm512_i32gather_ps(index, addr, scale) \
(__m512)__builtin_ia32_gathersiv16sf((__v16sf)_mm512_undefined_ps(), \
(float const *)(addr), \
(__v16sf)(__m512)(index), \
- (__mmask16)-1, (int)(scale)); })
+ (__mmask16)-1, (int)(scale))
-#define _mm512_mask_i32gather_ps(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i32gather_ps(v1_old, mask, index, addr, scale) \
(__m512)__builtin_ia32_gathersiv16sf((__v16sf)(__m512)(v1_old), \
(float const *)(addr), \
(__v16sf)(__m512)(index), \
- (__mmask16)(mask), (int)(scale)); })
+ (__mmask16)(mask), (int)(scale))
-#define _mm512_i32gather_epi32(index, addr, scale) __extension__ ({\
+#define _mm512_i32gather_epi32(index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv16si((__v16si)_mm512_undefined_epi32(), \
(int const *)(addr), \
(__v16si)(__m512i)(index), \
- (__mmask16)-1, (int)(scale)); })
+ (__mmask16)-1, (int)(scale))
-#define _mm512_mask_i32gather_epi32(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i32gather_epi32(v1_old, mask, index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv16si((__v16si)(__m512i)(v1_old), \
(int const *)(addr), \
(__v16si)(__m512i)(index), \
- (__mmask16)(mask), (int)(scale)); })
+ (__mmask16)(mask), (int)(scale))
-#define _mm512_i32gather_pd(index, addr, scale) __extension__ ({\
+#define _mm512_i32gather_pd(index, addr, scale) \
(__m512d)__builtin_ia32_gathersiv8df((__v8df)_mm512_undefined_pd(), \
(double const *)(addr), \
(__v8si)(__m256i)(index), (__mmask8)-1, \
- (int)(scale)); })
+ (int)(scale))
-#define _mm512_mask_i32gather_pd(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i32gather_pd(v1_old, mask, index, addr, scale) \
(__m512d)__builtin_ia32_gathersiv8df((__v8df)(__m512d)(v1_old), \
(double const *)(addr), \
(__v8si)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm512_i32gather_epi64(index, addr, scale) __extension__ ({\
+#define _mm512_i32gather_epi64(index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv8di((__v8di)_mm512_undefined_epi32(), \
(long long const *)(addr), \
(__v8si)(__m256i)(index), (__mmask8)-1, \
- (int)(scale)); })
+ (int)(scale))
-#define _mm512_mask_i32gather_epi64(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm512_mask_i32gather_epi64(v1_old, mask, index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv8di((__v8di)(__m512i)(v1_old), \
(long long const *)(addr), \
(__v8si)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm512_i64scatter_ps(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i64scatter_ps(addr, index, v1, scale) \
__builtin_ia32_scatterdiv16sf((float *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
- (__v8sf)(__m256)(v1), (int)(scale)); })
+ (__v8sf)(__m256)(v1), (int)(scale))
-#define _mm512_mask_i64scatter_ps(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i64scatter_ps(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv16sf((float *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
- (__v8sf)(__m256)(v1), (int)(scale)); })
+ (__v8sf)(__m256)(v1), (int)(scale))
-#define _mm512_i64scatter_epi32(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i64scatter_epi32(addr, index, v1, scale) \
__builtin_ia32_scatterdiv16si((int *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
- (__v8si)(__m256i)(v1), (int)(scale)); })
+ (__v8si)(__m256i)(v1), (int)(scale))
-#define _mm512_mask_i64scatter_epi32(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i64scatter_epi32(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv16si((int *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
- (__v8si)(__m256i)(v1), (int)(scale)); })
+ (__v8si)(__m256i)(v1), (int)(scale))
-#define _mm512_i64scatter_pd(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i64scatter_pd(addr, index, v1, scale) \
__builtin_ia32_scatterdiv8df((double *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
- (__v8df)(__m512d)(v1), (int)(scale)); })
+ (__v8df)(__m512d)(v1), (int)(scale))
-#define _mm512_mask_i64scatter_pd(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i64scatter_pd(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv8df((double *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
- (__v8df)(__m512d)(v1), (int)(scale)); })
+ (__v8df)(__m512d)(v1), (int)(scale))
-#define _mm512_i64scatter_epi64(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i64scatter_epi64(addr, index, v1, scale) \
__builtin_ia32_scatterdiv8di((long long *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
- (__v8di)(__m512i)(v1), (int)(scale)); })
+ (__v8di)(__m512i)(v1), (int)(scale))
-#define _mm512_mask_i64scatter_epi64(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i64scatter_epi64(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv8di((long long *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
- (__v8di)(__m512i)(v1), (int)(scale)); })
+ (__v8di)(__m512i)(v1), (int)(scale))
-#define _mm512_i32scatter_ps(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i32scatter_ps(addr, index, v1, scale) \
__builtin_ia32_scattersiv16sf((float *)(addr), (__mmask16)-1, \
(__v16si)(__m512i)(index), \
- (__v16sf)(__m512)(v1), (int)(scale)); })
+ (__v16sf)(__m512)(v1), (int)(scale))
-#define _mm512_mask_i32scatter_ps(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i32scatter_ps(addr, mask, index, v1, scale) \
__builtin_ia32_scattersiv16sf((float *)(addr), (__mmask16)(mask), \
(__v16si)(__m512i)(index), \
- (__v16sf)(__m512)(v1), (int)(scale)); })
+ (__v16sf)(__m512)(v1), (int)(scale))
-#define _mm512_i32scatter_epi32(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i32scatter_epi32(addr, index, v1, scale) \
__builtin_ia32_scattersiv16si((int *)(addr), (__mmask16)-1, \
(__v16si)(__m512i)(index), \
- (__v16si)(__m512i)(v1), (int)(scale)); })
+ (__v16si)(__m512i)(v1), (int)(scale))
-#define _mm512_mask_i32scatter_epi32(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i32scatter_epi32(addr, mask, index, v1, scale) \
__builtin_ia32_scattersiv16si((int *)(addr), (__mmask16)(mask), \
(__v16si)(__m512i)(index), \
- (__v16si)(__m512i)(v1), (int)(scale)); })
+ (__v16si)(__m512i)(v1), (int)(scale))
-#define _mm512_i32scatter_pd(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i32scatter_pd(addr, index, v1, scale) \
__builtin_ia32_scattersiv8df((double *)(addr), (__mmask8)-1, \
(__v8si)(__m256i)(index), \
- (__v8df)(__m512d)(v1), (int)(scale)); })
+ (__v8df)(__m512d)(v1), (int)(scale))
-#define _mm512_mask_i32scatter_pd(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i32scatter_pd(addr, mask, index, v1, scale) \
__builtin_ia32_scattersiv8df((double *)(addr), (__mmask8)(mask), \
(__v8si)(__m256i)(index), \
- (__v8df)(__m512d)(v1), (int)(scale)); })
+ (__v8df)(__m512d)(v1), (int)(scale))
-#define _mm512_i32scatter_epi64(addr, index, v1, scale) __extension__ ({\
+#define _mm512_i32scatter_epi64(addr, index, v1, scale) \
__builtin_ia32_scattersiv8di((long long *)(addr), (__mmask8)-1, \
(__v8si)(__m256i)(index), \
- (__v8di)(__m512i)(v1), (int)(scale)); })
+ (__v8di)(__m512i)(v1), (int)(scale))
-#define _mm512_mask_i32scatter_epi64(addr, mask, index, v1, scale) __extension__ ({\
+#define _mm512_mask_i32scatter_epi64(addr, mask, index, v1, scale) \
__builtin_ia32_scattersiv8di((long long *)(addr), (__mmask8)(mask), \
(__v8si)(__m256i)(index), \
- (__v8di)(__m512i)(v1), (int)(scale)); })
+ (__v8di)(__m512i)(v1), (int)(scale))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
- (__v4sf) __A,
- (__v4sf) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_mask((__v4sf)__W,
+ (__v4sf)__A,
+ (__v4sf)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fmadd_round_ss(W, U, A, B, R) __extension__({\
+#define _mm_fmadd_round_ss(A, B, C, R) \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)(__m128)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fmadd_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
(__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A,
+ (__v4sf)__B,
+ (__v4sf)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fmadd_round_ss(U, A, B, C, R) __extension__ ({\
+#define _mm_maskz_fmadd_round_ss(U, A, B, C, R) \
(__m128)__builtin_ia32_vfmaddss3_maskz((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(C), (__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask3 ((__v4sf) __W,
- (__v4sf) __X,
- (__v4sf) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_mask3((__v4sf)__W,
+ (__v4sf)__X,
+ (__v4sf)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fmadd_round_ss(W, X, Y, U, R) __extension__ ({\
+#define _mm_mask3_fmadd_round_ss(W, X, Y, U, R) \
(__m128)__builtin_ia32_vfmaddss3_mask3((__v4sf)(__m128)(W), \
(__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
- (__v4sf) __A,
- -(__v4sf) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_mask((__v4sf)__W,
+ (__v4sf)__A,
+ -(__v4sf)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fmsub_round_ss(W, U, A, B, R) __extension__ ({\
+#define _mm_fmsub_round_ss(A, B, C, R) \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ -(__v4sf)(__m128)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fmsub_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
(__v4sf)(__m128)(A), \
- (__v4sf)(__m128)(B), (__mmask8)(U), \
- (int)(R)); })
+ -(__v4sf)(__m128)(B), (__mmask8)(U), \
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A,
+ (__v4sf)__B,
+ -(__v4sf)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fmsub_round_ss(U, A, B, C, R) __extension__ ({\
+#define _mm_maskz_fmsub_round_ss(U, A, B, C, R) \
(__m128)__builtin_ia32_vfmaddss3_maskz((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
-(__v4sf)(__m128)(C), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmsubss3_mask3 ((__v4sf) __W,
- (__v4sf) __X,
- (__v4sf) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmsubss3_mask3((__v4sf)__W,
+ (__v4sf)__X,
+ (__v4sf)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fmsub_round_ss(W, X, Y, U, R) __extension__ ({\
+#define _mm_mask3_fmsub_round_ss(W, X, Y, U, R) \
(__m128)__builtin_ia32_vfmsubss3_mask3((__v4sf)(__m128)(W), \
(__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
- -(__v4sf) __A,
- (__v4sf) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_mask((__v4sf)__W,
+ -(__v4sf)__A,
+ (__v4sf)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fnmadd_round_ss(W, U, A, B, R) __extension__ ({\
+#define _mm_fnmadd_round_ss(A, B, C, R) \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \
+ -(__v4sf)(__m128)(B), \
+ (__v4sf)(__m128)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fnmadd_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
-(__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddss3_maskz (-(__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A,
+ -(__v4sf)__B,
+ (__v4sf)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fnmadd_round_ss(U, A, B, C, R) __extension__ ({\
- (__m128)__builtin_ia32_vfmaddss3_maskz(-(__v4sf)(__m128)(A), \
- (__v4sf)(__m128)(B), \
+#define _mm_maskz_fnmadd_round_ss(U, A, B, C, R) \
+ (__m128)__builtin_ia32_vfmaddss3_maskz((__v4sf)(__m128)(A), \
+ -(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(C), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fnmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask3 (-(__v4sf) __W,
- (__v4sf) __X,
- (__v4sf) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_mask3((__v4sf)__W,
+ -(__v4sf)__X,
+ (__v4sf)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fnmadd_round_ss(W, X, Y, U, R) __extension__({\
- (__m128)__builtin_ia32_vfmaddss3_mask3(-(__v4sf)(__m128)(W), \
- (__v4sf)(__m128)(X), \
+#define _mm_mask3_fnmadd_round_ss(W, X, Y, U, R) \
+ (__m128)__builtin_ia32_vfmaddss3_mask3((__v4sf)(__m128)(W), \
+ -(__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
- -(__v4sf) __A,
- -(__v4sf) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_mask((__v4sf)__W,
+ -(__v4sf)__A,
+ -(__v4sf)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fnmsub_round_ss(W, U, A, B, R) __extension__ ({\
+#define _mm_fnmsub_round_ss(A, B, C, R) \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \
+ -(__v4sf)(__m128)(B), \
+ -(__v4sf)(__m128)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fnmsub_round_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
-(__v4sf)(__m128)(A), \
-(__v4sf)(__m128)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddss3_maskz (-(__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A,
+ -(__v4sf)__B,
+ -(__v4sf)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fnmsub_round_ss(U, A, B, C, R) __extension__ ({\
- (__m128)__builtin_ia32_vfmaddss3_maskz(-(__v4sf)(__m128)(A), \
- (__v4sf)(__m128)(B), \
+#define _mm_maskz_fnmsub_round_ss(U, A, B, C, R) \
+ (__m128)__builtin_ia32_vfmaddss3_maskz((__v4sf)(__m128)(A), \
+ -(__v4sf)(__m128)(B), \
-(__v4sf)(__m128)(C), (__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfnmsubss3_mask3 ((__v4sf) __W,
- (__v4sf) __X,
- (__v4sf) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmsubss3_mask3((__v4sf)__W,
+ -(__v4sf)__X,
+ (__v4sf)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fnmsub_round_ss(W, X, Y, U, R) __extension__({\
- (__m128)__builtin_ia32_vfnmsubss3_mask3((__v4sf)(__m128)(W), \
- (__v4sf)(__m128)(X), \
+#define _mm_mask3_fnmsub_round_ss(W, X, Y, U, R) \
+ (__m128)__builtin_ia32_vfmsubss3_mask3((__v4sf)(__m128)(W), \
+ -(__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
- (__v2df) __A,
- (__v2df) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_mask((__v2df)__W,
+ (__v2df)__A,
+ (__v2df)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fmadd_round_sd(W, U, A, B, R) __extension__({\
+#define _mm_fmadd_round_sd(A, B, C, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)(__m128d)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fmadd_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
(__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_maskz ( (__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A,
+ (__v2df)__B,
+ (__v2df)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fmadd_round_sd(U, A, B, C, R) __extension__ ({\
+#define _mm_maskz_fmadd_round_sd(U, A, B, C, R) \
(__m128d)__builtin_ia32_vfmaddsd3_maskz((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(C), (__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask3 ((__v2df) __W,
- (__v2df) __X,
- (__v2df) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_mask3((__v2df)__W,
+ (__v2df)__X,
+ (__v2df)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fmadd_round_sd(W, X, Y, U, R) __extension__ ({\
+#define _mm_mask3_fmadd_round_sd(W, X, Y, U, R) \
(__m128d)__builtin_ia32_vfmaddsd3_mask3((__v2df)(__m128d)(W), \
(__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
- (__v2df) __A,
- -(__v2df) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_mask((__v2df)__W,
+ (__v2df)__A,
+ -(__v2df)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fmsub_round_sd(W, U, A, B, R) __extension__ ({\
+#define _mm_fmsub_round_sd(A, B, C, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ -(__v2df)(__m128d)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fmsub_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
(__v2df)(__m128d)(A), \
-(__v2df)(__m128d)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_maskz ( (__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A,
+ (__v2df)__B,
+ -(__v2df)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fmsub_round_sd(U, A, B, C, R) __extension__ ({\
+#define _mm_maskz_fmsub_round_sd(U, A, B, C, R) \
(__m128d)__builtin_ia32_vfmaddsd3_maskz((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
-(__v2df)(__m128d)(C), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmsubsd3_mask3 ((__v2df) __W,
- (__v2df) __X,
- (__v2df) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmsubsd3_mask3((__v2df)__W,
+ (__v2df)__X,
+ (__v2df)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fmsub_round_sd(W, X, Y, U, R) __extension__ ({\
+#define _mm_mask3_fmsub_round_sd(W, X, Y, U, R) \
(__m128d)__builtin_ia32_vfmsubsd3_mask3((__v2df)(__m128d)(W), \
(__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
- -(__v2df) __A,
- (__v2df) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_mask((__v2df)__W,
+ -(__v2df)__A,
+ (__v2df)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fnmadd_round_sd(W, U, A, B, R) __extension__ ({\
+#define _mm_fnmadd_round_sd(A, B, C, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \
+ -(__v2df)(__m128d)(B), \
+ (__v2df)(__m128d)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fnmadd_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
-(__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fnmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_maskz ( -(__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A,
+ -(__v2df)__B,
+ (__v2df)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fnmadd_round_sd(U, A, B, C, R) __extension__ ({\
- (__m128d)__builtin_ia32_vfmaddsd3_maskz(-(__v2df)(__m128d)(A), \
- (__v2df)(__m128d)(B), \
+#define _mm_maskz_fnmadd_round_sd(U, A, B, C, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_maskz((__v2df)(__m128d)(A), \
+ -(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(C), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fnmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask3 (-(__v2df) __W,
- (__v2df) __X,
- (__v2df) __Y,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_mask3((__v2df)__W,
+ -(__v2df)__X,
+ (__v2df)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fnmadd_round_sd(W, X, Y, U, R) __extension__({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask3(-(__v2df)(__m128d)(W), \
- (__v2df)(__m128d)(X), \
+#define _mm_mask3_fnmadd_round_sd(W, X, Y, U, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask3((__v2df)(__m128d)(W), \
+ -(__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
- -(__v2df) __A,
- -(__v2df) __B,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_mask((__v2df)__W,
+ -(__v2df)__A,
+ -(__v2df)__B,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask_fnmsub_round_sd(W, U, A, B, R) __extension__ ({\
+#define _mm_fnmsub_round_sd(A, B, C, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \
+ -(__v2df)(__m128d)(B), \
+ -(__v2df)(__m128d)(C), (__mmask8)-1, \
+ (int)(R))
+
+#define _mm_mask_fnmsub_round_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
-(__v2df)(__m128d)(A), \
-(__v2df)(__m128d)(B), (__mmask8)(U), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_maskz ( -(__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A,
+ -(__v2df)__B,
+ -(__v2df)__C,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_maskz_fnmsub_round_sd(U, A, B, C, R) __extension__ ({\
- (__m128d)__builtin_ia32_vfmaddsd3_maskz(-(__v2df)(__m128d)(A), \
- (__v2df)(__m128d)(B), \
+#define _mm_maskz_fnmsub_round_sd(U, A, B, C, R) \
+ (__m128d)__builtin_ia32_vfmaddsd3_maskz((__v2df)(__m128d)(A), \
+ -(__v2df)(__m128d)(B), \
-(__v2df)(__m128d)(C), \
(__mmask8)(U), \
- _MM_FROUND_CUR_DIRECTION); })
+ (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfnmsubsd3_mask3 ((__v2df) (__W),
- (__v2df) __X,
- (__v2df) (__Y),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_vfmsubsd3_mask3((__v2df)__W,
+ -(__v2df)__X,
+ (__v2df)__Y,
+ (__mmask8)__U,
+ _MM_FROUND_CUR_DIRECTION);
}
-#define _mm_mask3_fnmsub_round_sd(W, X, Y, U, R) __extension__({\
- (__m128d)__builtin_ia32_vfnmsubsd3_mask3((__v2df)(__m128d)(W), \
- (__v2df)(__m128d)(X), \
+#define _mm_mask3_fnmsub_round_sd(W, X, Y, U, R) \
+ (__m128d)__builtin_ia32_vfmsubsd3_mask3((__v2df)(__m128d)(W), \
+ -(__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), \
- (__mmask8)(U), (int)(R)); })
-
-#define _mm512_permutex_pd(X, C) __extension__ ({ \
- (__m512d)__builtin_shufflevector((__v8df)(__m512d)(X), \
- (__v8df)_mm512_undefined_pd(), \
- 0 + (((C) >> 0) & 0x3), \
- 0 + (((C) >> 2) & 0x3), \
- 0 + (((C) >> 4) & 0x3), \
- 0 + (((C) >> 6) & 0x3), \
- 4 + (((C) >> 0) & 0x3), \
- 4 + (((C) >> 2) & 0x3), \
- 4 + (((C) >> 4) & 0x3), \
- 4 + (((C) >> 6) & 0x3)); })
-
-#define _mm512_mask_permutex_pd(W, U, X, C) __extension__ ({ \
+ (__mmask8)(U), (int)(R))
+
+#define _mm512_permutex_pd(X, C) \
+ (__m512d)__builtin_ia32_permdf512((__v8df)(__m512d)(X), (int)(C))
+
+#define _mm512_mask_permutex_pd(W, U, X, C) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_permutex_pd((X), (C)), \
- (__v8df)(__m512d)(W)); })
+ (__v8df)(__m512d)(W))
-#define _mm512_maskz_permutex_pd(U, X, C) __extension__ ({ \
+#define _mm512_maskz_permutex_pd(U, X, C) \
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
(__v8df)_mm512_permutex_pd((X), (C)), \
- (__v8df)_mm512_setzero_pd()); })
-
-#define _mm512_permutex_epi64(X, C) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v8di)(__m512i)(X), \
- (__v8di)_mm512_undefined_epi32(), \
- 0 + (((C) >> 0) & 0x3), \
- 0 + (((C) >> 2) & 0x3), \
- 0 + (((C) >> 4) & 0x3), \
- 0 + (((C) >> 6) & 0x3), \
- 4 + (((C) >> 0) & 0x3), \
- 4 + (((C) >> 2) & 0x3), \
- 4 + (((C) >> 4) & 0x3), \
- 4 + (((C) >> 6) & 0x3)); })
-
-#define _mm512_mask_permutex_epi64(W, U, X, C) __extension__ ({ \
+ (__v8df)_mm512_setzero_pd())
+
+#define _mm512_permutex_epi64(X, C) \
+ (__m512i)__builtin_ia32_permdi512((__v8di)(__m512i)(X), (int)(C))
+
+#define _mm512_mask_permutex_epi64(W, U, X, C) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_permutex_epi64((X), (C)), \
- (__v8di)(__m512i)(W)); })
+ (__v8di)(__m512i)(W))
-#define _mm512_maskz_permutex_epi64(U, X, C) __extension__ ({ \
+#define _mm512_maskz_permutex_epi64(U, X, C) \
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
(__v8di)_mm512_permutex_epi64((X), (C)), \
- (__v8di)_mm512_setzero_si512()); })
+ (__v8di)_mm512_setzero_si512())
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_permutexvar_pd (__m512i __X, __m512d __Y)
{
- return (__m512d) __builtin_ia32_permvardf512_mask ((__v8df) __Y,
- (__v8di) __X,
- (__v8df) _mm512_undefined_pd (),
- (__mmask8) -1);
+ return (__m512d)__builtin_ia32_permvardf512((__v8df) __Y, (__v8di) __X);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_permutexvar_pd (__m512d __W, __mmask8 __U, __m512i __X, __m512d __Y)
{
- return (__m512d) __builtin_ia32_permvardf512_mask ((__v8df) __Y,
- (__v8di) __X,
- (__v8df) __W,
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_permutexvar_pd(__X, __Y),
+ (__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_permutexvar_pd (__mmask8 __U, __m512i __X, __m512d __Y)
{
- return (__m512d) __builtin_ia32_permvardf512_mask ((__v8df) __Y,
- (__v8di) __X,
- (__v8df) _mm512_setzero_pd (),
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_permutexvar_pd(__X, __Y),
+ (__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_permutexvar_epi64 (__mmask8 __M, __m512i __X, __m512i __Y)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_permutexvar_epi64 (__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_permvardi512_mask ((__v8di) __Y,
- (__v8di) __X,
- (__v8di) _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_permvardi512((__v8di)__Y, (__v8di)__X);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_permutexvar_epi64 (__m512i __X, __m512i __Y)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_maskz_permutexvar_epi64 (__mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_permvardi512_mask ((__v8di) __Y,
- (__v8di) __X,
- (__v8di) _mm512_undefined_epi32 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_permutexvar_epi64(__X, __Y),
+ (__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_permutexvar_epi64 (__m512i __W, __mmask8 __M, __m512i __X,
__m512i __Y)
{
- return (__m512i) __builtin_ia32_permvardi512_mask ((__v8di) __Y,
- (__v8di) __X,
- (__v8di) __W,
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_permutexvar_epi64(__X, __Y),
+ (__v8di)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_permutexvar_ps (__m512i __X, __m512 __Y)
{
- return (__m512) __builtin_ia32_permvarsf512_mask ((__v16sf) __Y,
- (__v16si) __X,
- (__v16sf) _mm512_undefined_ps (),
- (__mmask16) -1);
+ return (__m512)__builtin_ia32_permvarsf512((__v16sf)__Y, (__v16si)__X);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_permutexvar_ps (__m512 __W, __mmask16 __U, __m512i __X, __m512 __Y)
{
- return (__m512) __builtin_ia32_permvarsf512_mask ((__v16sf) __Y,
- (__v16si) __X,
- (__v16sf) __W,
- (__mmask16) __U);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_permutexvar_ps(__X, __Y),
+ (__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_permutexvar_ps (__mmask16 __U, __m512i __X, __m512 __Y)
{
- return (__m512) __builtin_ia32_permvarsf512_mask ((__v16sf) __Y,
- (__v16si) __X,
- (__v16sf) _mm512_setzero_ps (),
- (__mmask16) __U);
-}
-
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_permutexvar_epi32 (__mmask16 __M, __m512i __X, __m512i __Y)
-{
- return (__m512i) __builtin_ia32_permvarsi512_mask ((__v16si) __Y,
- (__v16si) __X,
- (__v16si) _mm512_setzero_si512 (),
- __M);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_permutexvar_ps(__X, __Y),
+ (__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_permutexvar_epi32 (__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_permvarsi512_mask ((__v16si) __Y,
- (__v16si) __X,
- (__v16si) _mm512_undefined_epi32 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_permvarsi512((__v16si)__Y, (__v16si)__X);
}
#define _mm512_permutevar_epi32 _mm512_permutexvar_epi32
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_maskz_permutexvar_epi32 (__mmask16 __M, __m512i __X, __m512i __Y)
+{
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_permutexvar_epi32(__X, __Y),
+ (__v16si)_mm512_setzero_si512());
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_permutexvar_epi32 (__m512i __W, __mmask16 __M, __m512i __X,
__m512i __Y)
{
- return (__m512i) __builtin_ia32_permvarsi512_mask ((__v16si) __Y,
- (__v16si) __X,
- (__v16si) __W,
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_permutexvar_epi32(__X, __Y),
+ (__v16si)__W);
}
#define _mm512_mask_permutevar_epi32 _mm512_mask_permutexvar_epi32
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kand (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kandhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kandn (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kandnhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kor (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_korhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_kortestc (__mmask16 __A, __mmask16 __B)
{
return __builtin_ia32_kortestchi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_kortestz (__mmask16 __A, __mmask16 __B)
{
return __builtin_ia32_kortestzhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kunpackb (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kxnor (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kxnorhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_kxor (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kxorhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_stream_si512 (__m512i * __P, __m512i __A)
{
typedef __v8di __v8di_aligned __attribute__((aligned(64)));
__builtin_nontemporal_store((__v8di_aligned)__A, (__v8di_aligned*)__P);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_stream_load_si512 (void const *__P)
{
typedef __v8di __v8di_aligned __attribute__((aligned(64)));
return (__m512i) __builtin_nontemporal_load((const __v8di_aligned *)__P);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_stream_pd (double *__P, __m512d __A)
{
typedef __v8df __v8df_aligned __attribute__((aligned(64)));
__builtin_nontemporal_store((__v8df_aligned)__A, (__v8df_aligned*)__P);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_stream_ps (float *__P, __m512 __A)
{
typedef __v16sf __v16sf_aligned __attribute__((aligned(64)));
__builtin_nontemporal_store((__v16sf_aligned)__A, (__v16sf_aligned*)__P);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_compress_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_compressdf512_mask ((__v8df) __A,
@@ -8838,7 +8404,7 @@ _mm512_mask_compress_pd (__m512d __W, __mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_compress_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_compressdf512_mask ((__v8df) __A,
@@ -8847,7 +8413,7 @@ _mm512_maskz_compress_pd (__mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_compress_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_compressdi512_mask ((__v8di) __A,
@@ -8855,7 +8421,7 @@ _mm512_mask_compress_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_compress_epi64 (__mmask8 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_compressdi512_mask ((__v8di) __A,
@@ -8864,7 +8430,7 @@ _mm512_maskz_compress_epi64 (__mmask8 __U, __m512i __A)
(__mmask8) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_compress_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_compresssf512_mask ((__v16sf) __A,
@@ -8872,7 +8438,7 @@ _mm512_mask_compress_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_compress_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_compresssf512_mask ((__v16sf) __A,
@@ -8881,7 +8447,7 @@ _mm512_maskz_compress_ps (__mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_compress_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_compresssi512_mask ((__v16si) __A,
@@ -8889,7 +8455,7 @@ _mm512_mask_compress_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_compresssi512_mask ((__v16si) __A,
@@ -8898,116 +8464,116 @@ _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A)
(__mmask16) __U);
}
-#define _mm_cmp_round_ss_mask(X, Y, P, R) __extension__ ({ \
+#define _mm_cmp_round_ss_mask(X, Y, P, R) \
(__mmask8)__builtin_ia32_cmpss_mask((__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (int)(P), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_cmp_round_ss_mask(M, X, Y, P, R) __extension__ ({ \
+#define _mm_mask_cmp_round_ss_mask(M, X, Y, P, R) \
(__mmask8)__builtin_ia32_cmpss_mask((__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (int)(P), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
-#define _mm_cmp_ss_mask(X, Y, P) __extension__ ({ \
+#define _mm_cmp_ss_mask(X, Y, P) \
(__mmask8)__builtin_ia32_cmpss_mask((__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (int)(P), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_cmp_ss_mask(M, X, Y, P) __extension__ ({ \
+#define _mm_mask_cmp_ss_mask(M, X, Y, P) \
(__mmask8)__builtin_ia32_cmpss_mask((__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), (int)(P), \
(__mmask8)(M), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_cmp_round_sd_mask(X, Y, P, R) __extension__ ({ \
+#define _mm_cmp_round_sd_mask(X, Y, P, R) \
(__mmask8)__builtin_ia32_cmpsd_mask((__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), (int)(P), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_cmp_round_sd_mask(M, X, Y, P, R) __extension__ ({ \
+#define _mm_mask_cmp_round_sd_mask(M, X, Y, P, R) \
(__mmask8)__builtin_ia32_cmpsd_mask((__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), (int)(P), \
- (__mmask8)(M), (int)(R)); })
+ (__mmask8)(M), (int)(R))
-#define _mm_cmp_sd_mask(X, Y, P) __extension__ ({ \
+#define _mm_cmp_sd_mask(X, Y, P) \
(__mmask8)__builtin_ia32_cmpsd_mask((__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), (int)(P), \
(__mmask8)-1, \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
-#define _mm_mask_cmp_sd_mask(M, X, Y, P) __extension__ ({ \
+#define _mm_mask_cmp_sd_mask(M, X, Y, P) \
(__mmask8)__builtin_ia32_cmpsd_mask((__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), (int)(P), \
(__mmask8)(M), \
- _MM_FROUND_CUR_DIRECTION); })
+ _MM_FROUND_CUR_DIRECTION)
/* Bit Test */
-static __inline __mmask16 __DEFAULT_FN_ATTRS
+static __inline __mmask16 __DEFAULT_FN_ATTRS512
_mm512_test_epi32_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpneq_epi32_mask (_mm512_and_epi32(__A, __B),
- _mm512_setzero_epi32());
+ _mm512_setzero_si512());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_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());
+ _mm512_setzero_si512());
}
-static __inline __mmask8 __DEFAULT_FN_ATTRS
+static __inline __mmask8 __DEFAULT_FN_ATTRS512
_mm512_test_epi64_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpneq_epi64_mask (_mm512_and_epi32 (__A, __B),
- _mm512_setzero_epi32());
+ _mm512_setzero_si512());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS512
_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());
+ _mm512_setzero_si512());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_testn_epi32_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpeq_epi32_mask (_mm512_and_epi32 (__A, __B),
- _mm512_setzero_epi32());
+ _mm512_setzero_si512());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_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());
+ _mm512_setzero_si512());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS512
_mm512_testn_epi64_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpeq_epi64_mask (_mm512_and_epi32 (__A, __B),
- _mm512_setzero_epi32());
+ _mm512_setzero_si512());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS512
_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());
+ _mm512_setzero_si512());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_movehdup_ps (__m512 __A)
{
return (__m512)__builtin_shufflevector((__v16sf)__A, (__v16sf)__A,
1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_movehdup_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
@@ -9015,7 +8581,7 @@ _mm512_mask_movehdup_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_movehdup_ps (__mmask16 __U, __m512 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
@@ -9023,14 +8589,14 @@ _mm512_maskz_movehdup_ps (__mmask16 __U, __m512 __A)
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_moveldup_ps (__m512 __A)
{
return (__m512)__builtin_shufflevector((__v16sf)__A, (__v16sf)__A,
0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_moveldup_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
@@ -9038,7 +8604,7 @@ _mm512_mask_moveldup_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
@@ -9046,132 +8612,94 @@ _mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A)
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- __m128 res = __A;
- res[0] = (__U & 1) ? __B[0] : __W[0];
- return res;
+ return __builtin_ia32_selectss_128(__U, _mm_move_ss(__A, __B), __W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
- __m128 res = __A;
- res[0] = (__U & 1) ? __B[0] : 0;
- return res;
+ return __builtin_ia32_selectss_128(__U, _mm_move_ss(__A, __B),
+ _mm_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- __m128d res = __A;
- res[0] = (__U & 1) ? __B[0] : __W[0];
- return res;
+ return __builtin_ia32_selectsd_128(__U, _mm_move_sd(__A, __B), __W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
- __m128d res = __A;
- res[0] = (__U & 1) ? __B[0] : 0;
- return res;
+ return __builtin_ia32_selectsd_128(__U, _mm_move_sd(__A, __B),
+ _mm_setzero_pd());
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_ss (float * __W, __mmask8 __U, __m128 __A)
{
- __builtin_ia32_storess128_mask ((__v16sf *)__W,
- (__v16sf) _mm512_castps128_ps512(__A),
- (__mmask16) __U & (__mmask16)1);
+ __builtin_ia32_storess128_mask ((__v4sf *)__W, __A, __U & 1);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_sd (double * __W, __mmask8 __U, __m128d __A)
{
- __builtin_ia32_storesd128_mask ((__v8df *)__W,
- (__v8df) _mm512_castpd128_pd512(__A),
- (__mmask8) __U & 1);
+ __builtin_ia32_storesd128_mask ((__v2df *)__W, __A, __U & 1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_load_ss (__m128 __W, __mmask8 __U, const float* __A)
{
__m128 src = (__v4sf) __builtin_shufflevector((__v4sf) __W,
- (__v4sf) {0.0, 0.0, 0.0, 0.0},
+ (__v4sf)_mm_setzero_ps(),
0, 4, 4, 4);
- return (__m128) __builtin_shufflevector(
- __builtin_ia32_loadss128_mask ((__v16sf *) __A,
- (__v16sf) _mm512_castps128_ps512(src),
- (__mmask16) __U & 1),
- _mm512_undefined_ps(), 0, 1, 2, 3);
+ return (__m128) __builtin_ia32_loadss128_mask ((__v4sf *) __A, src, __U & 1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_load_ss (__mmask8 __U, const float* __A)
{
- return (__m128) __builtin_shufflevector(
- __builtin_ia32_loadss128_mask ((__v16sf *) __A,
- (__v16sf) _mm512_setzero_ps(),
- (__mmask16) __U & 1),
- _mm512_undefined_ps(), 0, 1, 2, 3);
+ return (__m128)__builtin_ia32_loadss128_mask ((__v4sf *) __A,
+ (__v4sf) _mm_setzero_ps(),
+ __U & 1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_load_sd (__m128d __W, __mmask8 __U, const double* __A)
{
__m128d src = (__v2df) __builtin_shufflevector((__v2df) __W,
- (__v2df) {0.0, 0.0}, 0, 2);
+ (__v2df)_mm_setzero_pd(),
+ 0, 2);
- return (__m128d) __builtin_shufflevector(
- __builtin_ia32_loadsd128_mask ((__v8df *) __A,
- (__v8df) _mm512_castpd128_pd512(src),
- (__mmask8) __U & 1),
- _mm512_undefined_pd(), 0, 1);
+ return (__m128d) __builtin_ia32_loadsd128_mask ((__v2df *) __A, src, __U & 1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_load_sd (__mmask8 __U, const double* __A)
{
- return (__m128d) __builtin_shufflevector(
- __builtin_ia32_loadsd128_mask ((__v8df *) __A,
- (__v8df) _mm512_setzero_pd(),
- (__mmask8) __U & 1),
- _mm512_undefined_pd(), 0, 1);
-}
-
-#define _mm512_shuffle_epi32(A, I) __extension__ ({ \
- (__m512i)__builtin_shufflevector((__v16si)(__m512i)(A), \
- (__v16si)_mm512_undefined_epi32(), \
- 0 + (((I) >> 0) & 0x3), \
- 0 + (((I) >> 2) & 0x3), \
- 0 + (((I) >> 4) & 0x3), \
- 0 + (((I) >> 6) & 0x3), \
- 4 + (((I) >> 0) & 0x3), \
- 4 + (((I) >> 2) & 0x3), \
- 4 + (((I) >> 4) & 0x3), \
- 4 + (((I) >> 6) & 0x3), \
- 8 + (((I) >> 0) & 0x3), \
- 8 + (((I) >> 2) & 0x3), \
- 8 + (((I) >> 4) & 0x3), \
- 8 + (((I) >> 6) & 0x3), \
- 12 + (((I) >> 0) & 0x3), \
- 12 + (((I) >> 2) & 0x3), \
- 12 + (((I) >> 4) & 0x3), \
- 12 + (((I) >> 6) & 0x3)); })
-
-#define _mm512_mask_shuffle_epi32(W, U, A, I) __extension__ ({ \
+ return (__m128d) __builtin_ia32_loadsd128_mask ((__v2df *) __A,
+ (__v2df) _mm_setzero_pd(),
+ __U & 1);
+}
+
+#define _mm512_shuffle_epi32(A, I) \
+ (__m512i)__builtin_ia32_pshufd512((__v16si)(__m512i)(A), (int)(I))
+
+#define _mm512_mask_shuffle_epi32(W, U, A, I) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_shuffle_epi32((A), (I)), \
- (__v16si)(__m512i)(W)); })
+ (__v16si)(__m512i)(W))
-#define _mm512_maskz_shuffle_epi32(U, A, I) __extension__ ({ \
+#define _mm512_maskz_shuffle_epi32(U, A, I) \
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
(__v16si)_mm512_shuffle_epi32((A), (I)), \
- (__v16si)_mm512_setzero_si512()); })
+ (__v16si)_mm512_setzero_si512())
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_expand_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_expanddf512_mask ((__v8df) __A,
@@ -9179,7 +8707,7 @@ _mm512_mask_expand_pd (__m512d __W, __mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_expand_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_expanddf512_mask ((__v8df) __A,
@@ -9187,7 +8715,7 @@ _mm512_maskz_expand_pd (__mmask8 __U, __m512d __A)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_expand_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_expanddi512_mask ((__v8di) __A,
@@ -9195,15 +8723,15 @@ _mm512_mask_expand_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_expand_epi64 ( __mmask8 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_expanddi512_mask ((__v8di) __A,
- (__v8di) _mm512_setzero_pd (),
+ (__v8di) _mm512_setzero_si512 (),
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_expandloadu_pd(__m512d __W, __mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_expandloaddf512_mask ((const __v8df *)__P,
@@ -9211,7 +8739,7 @@ _mm512_mask_expandloadu_pd(__m512d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_expandloadu_pd(__mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_expandloaddf512_mask ((const __v8df *)__P,
@@ -9219,7 +8747,7 @@ _mm512_maskz_expandloadu_pd(__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_expandloadu_epi64(__m512i __W, __mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_expandloaddi512_mask ((const __v8di *)__P,
@@ -9227,15 +8755,15 @@ _mm512_mask_expandloadu_epi64(__m512i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_expandloadu_epi64(__mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_expandloaddi512_mask ((const __v8di *)__P,
- (__v8di) _mm512_setzero_pd(),
+ (__v8di) _mm512_setzero_si512(),
(__mmask8) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_expandloadu_ps(__m512 __W, __mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_expandloadsf512_mask ((const __v16sf *)__P,
@@ -9243,7 +8771,7 @@ _mm512_mask_expandloadu_ps(__m512 __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_expandloadu_ps(__mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_expandloadsf512_mask ((const __v16sf *)__P,
@@ -9251,7 +8779,7 @@ _mm512_maskz_expandloadu_ps(__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_expandloadu_epi32(__m512i __W, __mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_expandloadsi512_mask ((const __v16si *)__P,
@@ -9259,15 +8787,15 @@ _mm512_mask_expandloadu_epi32(__m512i __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_expandloadu_epi32(__mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_expandloadsi512_mask ((const __v16si *)__P,
- (__v16si) _mm512_setzero_ps(),
+ (__v16si) _mm512_setzero_si512(),
(__mmask16) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_expand_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_expandsf512_mask ((__v16sf) __A,
@@ -9275,7 +8803,7 @@ _mm512_mask_expand_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_expand_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_expandsf512_mask ((__v16sf) __A,
@@ -9283,7 +8811,7 @@ _mm512_maskz_expand_ps (__mmask16 __U, __m512 __A)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_expand_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_expandsi512_mask ((__v16si) __A,
@@ -9291,71 +8819,64 @@ _mm512_mask_expand_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
(__mmask16) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_expand_epi32 (__mmask16 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_expandsi512_mask ((__v16si) __A,
- (__v16si) _mm512_setzero_ps(),
+ (__v16si) _mm512_setzero_si512(),
(__mmask16) __U);
}
-#define _mm512_cvt_roundps_pd(A, R) __extension__ ({ \
+#define _mm512_cvt_roundps_pd(A, R) \
(__m512d)__builtin_ia32_cvtps2pd512_mask((__v8sf)(__m256)(A), \
(__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm512_mask_cvt_roundps_pd(W, U, A, R) __extension__ ({ \
+#define _mm512_mask_cvt_roundps_pd(W, U, A, R) \
(__m512d)__builtin_ia32_cvtps2pd512_mask((__v8sf)(__m256)(A), \
(__v8df)(__m512d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm512_maskz_cvt_roundps_pd(U, A, R) __extension__ ({ \
+#define _mm512_maskz_cvt_roundps_pd(U, A, R) \
(__m512d)__builtin_ia32_cvtps2pd512_mask((__v8sf)(__m256)(A), \
(__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtps_pd (__m256 __A)
{
- return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A,
- (__v8df)
- _mm512_undefined_pd (),
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_convertvector((__v8sf)__A, __v8df);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtps_pd (__m512d __W, __mmask8 __U, __m256 __A)
{
- return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_cvtps_pd(__A),
+ (__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtps_pd (__mmask8 __U, __m256 __A)
{
- return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_cvtps_pd(__A),
+ (__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtpslo_pd (__m512 __A)
{
- return (__m512) _mm512_cvtps_pd(_mm512_castps512_ps256(__A));
+ return (__m512d) _mm512_cvtps_pd(_mm512_castps512_ps256(__A));
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpslo_pd (__m512d __W, __mmask8 __U, __m512 __A)
{
- return (__m512) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A));
+ return (__m512d) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A));
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
@@ -9363,7 +8884,7 @@ _mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A)
(__v8df) __W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
@@ -9371,7 +8892,7 @@ _mm512_maskz_mov_pd (__mmask8 __U, __m512d __A)
(__v8df) _mm512_setzero_pd ());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
@@ -9379,7 +8900,7 @@ _mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A)
(__v16sf) __W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
@@ -9387,68 +8908,68 @@ _mm512_maskz_mov_ps (__mmask16 __U, __m512 __A)
(__v16sf) _mm512_setzero_ps ());
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m512d __A)
{
__builtin_ia32_compressstoredf512_mask ((__v8df *) __P, (__v8df) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m512i __A)
{
__builtin_ia32_compressstoredi512_mask ((__v8di *) __P, (__v8di) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_compressstoreu_ps (void *__P, __mmask16 __U, __m512 __A)
{
__builtin_ia32_compressstoresf512_mask ((__v16sf *) __P, (__v16sf) __A,
(__mmask16) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_compressstoreu_epi32 (void *__P, __mmask16 __U, __m512i __A)
{
__builtin_ia32_compressstoresi512_mask ((__v16si *) __P, (__v16si) __A,
(__mmask16) __U);
}
-#define _mm_cvt_roundsd_ss(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundsd_ss(A, B, R) \
(__m128)__builtin_ia32_cvtsd2ss_round_mask((__v4sf)(__m128)(A), \
(__v2df)(__m128d)(B), \
(__v4sf)_mm_undefined_ps(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_cvt_roundsd_ss(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_cvt_roundsd_ss(W, U, A, B, R) \
(__m128)__builtin_ia32_cvtsd2ss_round_mask((__v4sf)(__m128)(A), \
(__v2df)(__m128d)(B), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_cvt_roundsd_ss(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_cvt_roundsd_ss(U, A, B, R) \
(__m128)__builtin_ia32_cvtsd2ss_round_mask((__v4sf)(__m128)(A), \
(__v2df)(__m128d)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtsd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128d __B)
{
- return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)(__A),
- (__v2df)(__B),
- (__v4sf)(__W),
- (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)__A,
+ (__v2df)__B,
+ (__v4sf)__W,
+ (__mmask8)__U, _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B)
{
- return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)(__A),
- (__v2df)(__B),
+ return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)__A,
+ (__v2df)__B,
(__v4sf)_mm_setzero_ps(),
- (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION);
+ (__mmask8)__U, _MM_FROUND_CUR_DIRECTION);
}
#define _mm_cvtss_i32 _mm_cvtss_si32
@@ -9463,111 +8984,112 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B)
#endif
#ifdef __x86_64__
-#define _mm_cvt_roundi64_sd(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundi64_sd(A, B, R) \
(__m128d)__builtin_ia32_cvtsi2sd64((__v2df)(__m128d)(A), (long long)(B), \
- (int)(R)); })
+ (int)(R))
-#define _mm_cvt_roundsi64_sd(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundsi64_sd(A, B, R) \
(__m128d)__builtin_ia32_cvtsi2sd64((__v2df)(__m128d)(A), (long long)(B), \
- (int)(R)); })
+ (int)(R))
#endif
-#define _mm_cvt_roundsi32_ss(A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_cvtsi2ss32((__v4sf)(__m128)(A), (int)(B), (int)(R)); })
+#define _mm_cvt_roundsi32_ss(A, B, R) \
+ (__m128)__builtin_ia32_cvtsi2ss32((__v4sf)(__m128)(A), (int)(B), (int)(R))
-#define _mm_cvt_roundi32_ss(A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_cvtsi2ss32((__v4sf)(__m128)(A), (int)(B), (int)(R)); })
+#define _mm_cvt_roundi32_ss(A, B, R) \
+ (__m128)__builtin_ia32_cvtsi2ss32((__v4sf)(__m128)(A), (int)(B), (int)(R))
#ifdef __x86_64__
-#define _mm_cvt_roundsi64_ss(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundsi64_ss(A, B, R) \
(__m128)__builtin_ia32_cvtsi2ss64((__v4sf)(__m128)(A), (long long)(B), \
- (int)(R)); })
+ (int)(R))
-#define _mm_cvt_roundi64_ss(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundi64_ss(A, B, R) \
(__m128)__builtin_ia32_cvtsi2ss64((__v4sf)(__m128)(A), (long long)(B), \
- (int)(R)); })
+ (int)(R))
#endif
-#define _mm_cvt_roundss_sd(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundss_sd(A, B, R) \
(__m128d)__builtin_ia32_cvtss2sd_round_mask((__v2df)(__m128d)(A), \
(__v4sf)(__m128)(B), \
(__v2df)_mm_undefined_pd(), \
- (__mmask8)-1, (int)(R)); })
+ (__mmask8)-1, (int)(R))
-#define _mm_mask_cvt_roundss_sd(W, U, A, B, R) __extension__ ({ \
+#define _mm_mask_cvt_roundss_sd(W, U, A, B, R) \
(__m128d)__builtin_ia32_cvtss2sd_round_mask((__v2df)(__m128d)(A), \
(__v4sf)(__m128)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-#define _mm_maskz_cvt_roundss_sd(U, A, B, R) __extension__ ({ \
+#define _mm_maskz_cvt_roundss_sd(U, A, B, R) \
(__m128d)__builtin_ia32_cvtss2sd_round_mask((__v2df)(__m128d)(A), \
(__v4sf)(__m128)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U), (int)(R)); })
+ (__mmask8)(U), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_cvtss_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128 __B)
{
- return __builtin_ia32_cvtss2sd_round_mask((__v2df)(__A),
- (__v4sf)(__B),
- (__v2df)(__W),
- (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_cvtss2sd_round_mask((__v2df)__A,
+ (__v4sf)__B,
+ (__v2df)__W,
+ (__mmask8)__U, _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_cvtss_sd (__mmask8 __U, __m128d __A, __m128 __B)
{
- return __builtin_ia32_cvtss2sd_round_mask((__v2df)(__A),
- (__v4sf)(__B),
- (__v2df)_mm_setzero_pd(),
- (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION);
+ return __builtin_ia32_cvtss2sd_round_mask((__v2df)__A,
+ (__v4sf)__B,
+ (__v2df)_mm_setzero_pd(),
+ (__mmask8)__U, _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_cvtu32_sd (__m128d __A, unsigned __B)
{
- return (__m128d) __builtin_ia32_cvtusi2sd32 ((__v2df) __A, __B);
+ __A[0] = __B;
+ return __A;
}
#ifdef __x86_64__
-#define _mm_cvt_roundu64_sd(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundu64_sd(A, B, R) \
(__m128d)__builtin_ia32_cvtusi2sd64((__v2df)(__m128d)(A), \
- (unsigned long long)(B), (int)(R)); })
+ (unsigned long long)(B), (int)(R))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_cvtu64_sd (__m128d __A, unsigned long long __B)
{
- return (__m128d) __builtin_ia32_cvtusi2sd64 ((__v2df) __A, __B,
- _MM_FROUND_CUR_DIRECTION);
+ __A[0] = __B;
+ return __A;
}
#endif
-#define _mm_cvt_roundu32_ss(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundu32_ss(A, B, R) \
(__m128)__builtin_ia32_cvtusi2ss32((__v4sf)(__m128)(A), (unsigned int)(B), \
- (int)(R)); })
+ (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_cvtu32_ss (__m128 __A, unsigned __B)
{
- return (__m128) __builtin_ia32_cvtusi2ss32 ((__v4sf) __A, __B,
- _MM_FROUND_CUR_DIRECTION);
+ __A[0] = __B;
+ return __A;
}
#ifdef __x86_64__
-#define _mm_cvt_roundu64_ss(A, B, R) __extension__ ({ \
+#define _mm_cvt_roundu64_ss(A, B, R) \
(__m128)__builtin_ia32_cvtusi2ss64((__v4sf)(__m128)(A), \
- (unsigned long long)(B), (int)(R)); })
+ (unsigned long long)(B), (int)(R))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_cvtu64_ss (__m128 __A, unsigned long long __B)
{
- return (__m128) __builtin_ia32_cvtusi2ss64 ((__v4sf) __A, __B,
- _MM_FROUND_CUR_DIRECTION);
+ __A[0] = __B;
+ return __A;
}
#endif
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A)
{
return (__m512i) __builtin_ia32_selectd_512(__M,
@@ -9575,17 +9097,15 @@ _mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A)
(__v16si) __O);
}
-#ifdef __x86_64__
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A)
{
return (__m512i) __builtin_ia32_selectq_512(__M,
(__v8di) _mm512_set1_epi64(__A),
(__v8di) __O);
}
-#endif
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set_epi8 (char __e63, char __e62, char __e61, char __e60, char __e59,
char __e58, char __e57, char __e56, char __e55, char __e54, char __e53,
char __e52, char __e51, char __e50, char __e49, char __e48, char __e47,
@@ -9609,7 +9129,7 @@ _mm512_set_epi8 (char __e63, char __e62, char __e61, char __e60, char __e59,
__e56, __e57, __e58, __e59, __e60, __e61, __e62, __e63};
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set_epi16(short __e31, short __e30, short __e29, short __e28,
short __e27, short __e26, short __e25, short __e24, short __e23,
short __e22, short __e21, short __e20, short __e19, short __e18,
@@ -9624,7 +9144,7 @@ _mm512_set_epi16(short __e31, short __e30, short __e29, short __e28,
__e24, __e25, __e26, __e27, __e28, __e29, __e30, __e31 };
}
-static __inline __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_set_epi32 (int __A, int __B, int __C, int __D,
int __E, int __F, int __G, int __H,
int __I, int __J, int __K, int __L,
@@ -9640,7 +9160,7 @@ _mm512_set_epi32 (int __A, int __B, int __C, int __D,
_mm512_set_epi32((e15),(e14),(e13),(e12),(e11),(e10),(e9),(e8),(e7),(e6), \
(e5),(e4),(e3),(e2),(e1),(e0))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_set_epi64 (long long __A, long long __B, long long __C,
long long __D, long long __E, long long __F,
long long __G, long long __H)
@@ -9652,7 +9172,7 @@ _mm512_set_epi64 (long long __A, long long __B, long long __C,
#define _mm512_setr_epi64(e0,e1,e2,e3,e4,e5,e6,e7) \
_mm512_set_epi64((e7),(e6),(e5),(e4),(e3),(e2),(e1),(e0))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_set_pd (double __A, double __B, double __C, double __D,
double __E, double __F, double __G, double __H)
{
@@ -9663,7 +9183,7 @@ _mm512_set_pd (double __A, double __B, double __C, double __D,
#define _mm512_setr_pd(e0,e1,e2,e3,e4,e5,e6,e7) \
_mm512_set_pd((e7),(e6),(e5),(e4),(e3),(e2),(e1),(e0))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_set_ps (float __A, float __B, float __C, float __D,
float __E, float __F, float __G, float __H,
float __I, float __J, float __K, float __L,
@@ -9678,556 +9198,401 @@ _mm512_set_ps (float __A, float __B, float __C, float __D,
_mm512_set_ps((e15),(e14),(e13),(e12),(e11),(e10),(e9),(e8),(e7),(e6),(e5), \
(e4),(e3),(e2),(e1),(e0))
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_abs_ps(__m512 __A)
{
return (__m512)_mm512_and_epi32(_mm512_set1_epi32(0x7FFFFFFF),(__m512i)__A) ;
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_abs_ps(__m512 __W, __mmask16 __K, __m512 __A)
{
return (__m512)_mm512_mask_and_epi32((__m512i)__W, __K, _mm512_set1_epi32(0x7FFFFFFF),(__m512i)__A) ;
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_abs_pd(__m512d __A)
{
return (__m512d)_mm512_and_epi64(_mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),(__v8di)__A) ;
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_abs_pd(__m512d __W, __mmask8 __K, __m512d __A)
{
return (__m512d)_mm512_mask_and_epi64((__v8di)__W, __K, _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),(__v8di)__A);
}
-// Vector-reduction arithmetic accepts vectors as inputs and produces scalars as
-// outputs. This class of vector operation forms the basis of many scientific
-// computations. In vector-reduction arithmetic, the evaluation off is
-// independent of the order of the input elements of V.
-
-// Used bisection method. At each step, we partition the vector with previous
-// step in half, and the operation is performed on its two halves.
-// This takes log2(n) steps where n is the number of elements in the vector.
-
-// Vec512 - Vector with size 512.
-// Operator - Can be one of following: +,*,&,|
-// T2 - Can get 'i' for int and 'f' for float.
-// T1 - Can get 'i' for int and 'd' for double.
-
-#define _mm512_reduce_operator_64bit(Vec512, Operator, T2, T1) \
- __extension__({ \
- __m256##T1 Vec256 = __builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 0, 1, 2, 3) \
- Operator \
- __builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 4, 5, 6, 7); \
- __m128##T1 Vec128 = __builtin_shufflevector( \
- (__v4d##T2)Vec256, \
- (__v4d##T2)Vec256, \
- 0, 1) \
- Operator \
- __builtin_shufflevector( \
- (__v4d##T2)Vec256, \
- (__v4d##T2)Vec256, \
- 2, 3); \
- Vec128 = __builtin_shufflevector((__v2d##T2)Vec128, \
- (__v2d##T2)Vec128, 0, -1) \
- Operator \
- __builtin_shufflevector((__v2d##T2)Vec128, \
- (__v2d##T2)Vec128, 1, -1); \
- return Vec128[0]; \
- })
-
-static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_add_epi64(__m512i __W) {
- _mm512_reduce_operator_64bit(__W, +, i, i);
-}
-
-static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_mul_epi64(__m512i __W) {
- _mm512_reduce_operator_64bit(__W, *, i, i);
-}
-
-static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_and_epi64(__m512i __W) {
- _mm512_reduce_operator_64bit(__W, &, i, i);
-}
-
-static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_or_epi64(__m512i __W) {
- _mm512_reduce_operator_64bit(__W, |, i, i);
-}
-
-static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_add_pd(__m512d __W) {
- _mm512_reduce_operator_64bit(__W, +, f, d);
-}
-
-static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_mul_pd(__m512d __W) {
- _mm512_reduce_operator_64bit(__W, *, f, d);
-}
-
-// Vec512 - Vector with size 512.
-// Vec512Neutral - All vector elements set to the identity element.
-// Identity element: {+,0},{*,1},{&,0xFFFFFFFFFFFFFFFF},{|,0}
-// Operator - Can be one of following: +,*,&,|
-// Mask - Intrinsic Mask
-// T2 - Can get 'i' for int and 'f' for float.
-// T1 - Can get 'i' for int and 'd' for packed double-precision.
-// T3 - Can be Pd for packed double or q for q-word.
-
-#define _mm512_mask_reduce_operator_64bit(Vec512, Vec512Neutral, Operator, \
- Mask, T2, T1, T3) \
- __extension__({ \
- Vec512 = __builtin_ia32_select##T3##_512( \
- (__mmask8)Mask, \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512Neutral); \
- _mm512_reduce_operator_64bit(Vec512, Operator, T2, T1); \
- })
-
-static __inline__ long long __DEFAULT_FN_ATTRS
+/* Vector-reduction arithmetic accepts vectors as inputs and produces scalars as
+ * outputs. This class of vector operation forms the basis of many scientific
+ * computations. In vector-reduction arithmetic, the evaluation off is
+ * independent of the order of the input elements of V.
+
+ * Used bisection method. At each step, we partition the vector with previous
+ * step in half, and the operation is performed on its two halves.
+ * This takes log2(n) steps where n is the number of elements in the vector.
+ */
+
+#define _mm512_mask_reduce_operator(op) \
+ __v4du __t1 = (__v4du)_mm512_extracti64x4_epi64(__W, 0); \
+ __v4du __t2 = (__v4du)_mm512_extracti64x4_epi64(__W, 1); \
+ __m256i __t3 = (__m256i)(__t1 op __t2); \
+ __v2du __t4 = (__v2du)_mm256_extracti128_si256(__t3, 0); \
+ __v2du __t5 = (__v2du)_mm256_extracti128_si256(__t3, 1); \
+ __v2du __t6 = __t4 op __t5; \
+ __v2du __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \
+ __v2du __t8 = __t6 op __t7; \
+ return __t8[0];
+
+static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_add_epi64(__m512i __W) {
+ _mm512_mask_reduce_operator(+);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_epi64(__m512i __W) {
+ _mm512_mask_reduce_operator(*);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_and_epi64(__m512i __W) {
+ _mm512_mask_reduce_operator(&);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_or_epi64(__m512i __W) {
+ _mm512_mask_reduce_operator(|);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W) {
- _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), +, __M, i, i, q);
+ __W = _mm512_maskz_mov_epi64(__M, __W);
+ _mm512_mask_reduce_operator(+);
}
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W) {
- _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(1), *, __M, i, i, q);
+ __W = _mm512_mask_mov_epi64(_mm512_set1_epi64(1), __M, __W);
+ _mm512_mask_reduce_operator(*);
}
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W) {
- _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF),
- &, __M, i, i, q);
+ __W = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __W);
+ _mm512_mask_reduce_operator(&);
}
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) {
- _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), |, __M,
- i, i, q);
+ __W = _mm512_maskz_mov_epi64(__M, __W);
+ _mm512_mask_reduce_operator(|);
+}
+#undef _mm512_mask_reduce_operator
+
+#define _mm512_mask_reduce_operator(op) \
+ __m256d __t1 = _mm512_extractf64x4_pd(__W, 0); \
+ __m256d __t2 = _mm512_extractf64x4_pd(__W, 1); \
+ __m256d __t3 = __t1 op __t2; \
+ __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \
+ __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \
+ __m128d __t6 = __t4 op __t5; \
+ __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \
+ __m128d __t8 = __t6 op __t7; \
+ return __t8[0];
+
+static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_add_pd(__m512d __W) {
+ _mm512_mask_reduce_operator(+);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_pd(__m512d __W) {
+ _mm512_mask_reduce_operator(*);
}
-static __inline__ double __DEFAULT_FN_ATTRS
+static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) {
- _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(0), +, __M,
- f, d, pd);
+ __W = _mm512_maskz_mov_pd(__M, __W);
+ _mm512_mask_reduce_operator(+);
}
-static __inline__ double __DEFAULT_FN_ATTRS
+static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W) {
- _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(1), *, __M,
- f, d, pd);
-}
-
-// Vec512 - Vector with size 512.
-// Operator - Can be one of following: +,*,&,|
-// T2 - Can get 'i' for int and ' ' for packed single.
-// T1 - Can get 'i' for int and 'f' for float.
-
-#define _mm512_reduce_operator_32bit(Vec512, Operator, T2, T1) __extension__({ \
- __m256##T1 Vec256 = \
- (__m256##T1)(__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 0, 1, 2, 3, 4, 5, 6, 7) \
- Operator \
- __builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 8, 9, 10, 11, 12, 13, 14, 15)); \
- __m128##T1 Vec128 = \
- (__m128##T1)(__builtin_shufflevector( \
- (__v8s##T2)Vec256, \
- (__v8s##T2)Vec256, \
- 0, 1, 2, 3) \
- Operator \
- __builtin_shufflevector( \
- (__v8s##T2)Vec256, \
- (__v8s##T2)Vec256, \
- 4, 5, 6, 7)); \
- Vec128 = (__m128##T1)(__builtin_shufflevector( \
- (__v4s##T2)Vec128, \
- (__v4s##T2)Vec128, \
- 0, 1, -1, -1) \
- Operator \
- __builtin_shufflevector( \
- (__v4s##T2)Vec128, \
- (__v4s##T2)Vec128, \
- 2, 3, -1, -1)); \
- Vec128 = (__m128##T1)(__builtin_shufflevector( \
- (__v4s##T2)Vec128, \
- (__v4s##T2)Vec128, \
- 0, -1, -1, -1) \
- Operator \
- __builtin_shufflevector( \
- (__v4s##T2)Vec128, \
- (__v4s##T2)Vec128, \
- 1, -1, -1, -1)); \
- return Vec128[0]; \
- })
-
-static __inline__ int __DEFAULT_FN_ATTRS
+ __W = _mm512_mask_mov_pd(_mm512_set1_pd(1.0), __M, __W);
+ _mm512_mask_reduce_operator(*);
+}
+#undef _mm512_mask_reduce_operator
+
+#define _mm512_mask_reduce_operator(op) \
+ __v8su __t1 = (__v8su)_mm512_extracti64x4_epi64(__W, 0); \
+ __v8su __t2 = (__v8su)_mm512_extracti64x4_epi64(__W, 1); \
+ __m256i __t3 = (__m256i)(__t1 op __t2); \
+ __v4su __t4 = (__v4su)_mm256_extracti128_si256(__t3, 0); \
+ __v4su __t5 = (__v4su)_mm256_extracti128_si256(__t3, 1); \
+ __v4su __t6 = __t4 op __t5; \
+ __v4su __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \
+ __v4su __t8 = __t6 op __t7; \
+ __v4su __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \
+ __v4su __t10 = __t8 op __t9; \
+ return __t10[0];
+
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_reduce_add_epi32(__m512i __W) {
- _mm512_reduce_operator_32bit(__W, +, i, i);
+ _mm512_mask_reduce_operator(+);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_reduce_mul_epi32(__m512i __W) {
- _mm512_reduce_operator_32bit(__W, *, i, i);
+ _mm512_mask_reduce_operator(*);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_reduce_and_epi32(__m512i __W) {
- _mm512_reduce_operator_32bit(__W, &, i, i);
+ _mm512_mask_reduce_operator(&);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_reduce_or_epi32(__m512i __W) {
- _mm512_reduce_operator_32bit(__W, |, i, i);
+ _mm512_mask_reduce_operator(|);
}
-static __inline__ float __DEFAULT_FN_ATTRS
-_mm512_reduce_add_ps(__m512 __W) {
- _mm512_reduce_operator_32bit(__W, +, f, );
-}
-
-static __inline__ float __DEFAULT_FN_ATTRS
-_mm512_reduce_mul_ps(__m512 __W) {
- _mm512_reduce_operator_32bit(__W, *, f, );
-}
-
-// Vec512 - Vector with size 512.
-// Vec512Neutral - All vector elements set to the identity element.
-// Identity element: {+,0},{*,1},{&,0xFFFFFFFF},{|,0}
-// Operator - Can be one of following: +,*,&,|
-// Mask - Intrinsic Mask
-// T2 - Can get 'i' for int and 'f' for float.
-// T1 - Can get 'i' for int and 'd' for double.
-// T3 - Can be Ps for packed single or d for d-word.
-
-#define _mm512_mask_reduce_operator_32bit(Vec512, Vec512Neutral, Operator, \
- Mask, T2, T1, T3) \
- __extension__({ \
- Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \
- (__mmask16)Mask, \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512Neutral); \
- _mm512_reduce_operator_32bit(Vec512, Operator, T2, T1); \
- })
-
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_add_epi32( __mmask16 __M, __m512i __W) {
- _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0), +, __M, i, i, d);
+ __W = _mm512_maskz_mov_epi32(__M, __W);
+ _mm512_mask_reduce_operator(+);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_mul_epi32( __mmask16 __M, __m512i __W) {
- _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(1), *, __M, i, i, d);
+ __W = _mm512_mask_mov_epi32(_mm512_set1_epi32(1), __M, __W);
+ _mm512_mask_reduce_operator(*);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_and_epi32( __mmask16 __M, __m512i __W) {
- _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0xFFFFFFFF), &, __M,
- i, i, d);
+ __W = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __W);
+ _mm512_mask_reduce_operator(&);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) {
- _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0), |, __M, i, i, d);
+ __W = _mm512_maskz_mov_epi32(__M, __W);
+ _mm512_mask_reduce_operator(|);
+}
+#undef _mm512_mask_reduce_operator
+
+#define _mm512_mask_reduce_operator(op) \
+ __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__W, 0); \
+ __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__W, 1); \
+ __m256 __t3 = __t1 op __t2; \
+ __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \
+ __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \
+ __m128 __t6 = __t4 op __t5; \
+ __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \
+ __m128 __t8 = __t6 op __t7; \
+ __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \
+ __m128 __t10 = __t8 op __t9; \
+ return __t10[0];
+
+static __inline__ float __DEFAULT_FN_ATTRS512
+_mm512_reduce_add_ps(__m512 __W) {
+ _mm512_mask_reduce_operator(+);
+}
+
+static __inline__ float __DEFAULT_FN_ATTRS512
+_mm512_reduce_mul_ps(__m512 __W) {
+ _mm512_mask_reduce_operator(*);
}
-static __inline__ float __DEFAULT_FN_ATTRS
+static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W) {
- _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_ps(0), +, __M, f, , ps);
+ __W = _mm512_maskz_mov_ps(__M, __W);
+ _mm512_mask_reduce_operator(+);
}
-static __inline__ float __DEFAULT_FN_ATTRS
+static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) {
- _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_ps(1), *, __M, f, , ps);
-}
-
-// Used bisection method. At each step, we partition the vector with previous
-// step in half, and the operation is performed on its two halves.
-// This takes log2(n) steps where n is the number of elements in the vector.
-// This macro uses only intrinsics from the AVX512F feature.
-
-// Vec512 - Vector with size of 512.
-// IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example:
-// __mm512_max_epi64
-// T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}]
-// T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}]
-
-#define _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2) __extension__({ \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 0, 1, 2, 3, -1, -1, -1, -1), \
- (__m512##T1)__builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 4, 5, 6, 7, -1, -1, -1, -1)); \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 0, 1, -1, -1, -1, -1, -1, -1),\
- (__m512##T1)__builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 2, 3, -1, -1, -1, -1, -1, \
- -1)); \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 0, -1, -1, -1, -1, -1, -1, -1),\
- (__m512##T1)__builtin_shufflevector( \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512, \
- 1, -1, -1, -1, -1, -1, -1, -1))\
- ; \
- return Vec512[0]; \
- })
-
-static __inline__ long long __DEFAULT_FN_ATTRS
-_mm512_reduce_max_epi64(__m512i __V) {
- _mm512_reduce_maxMin_64bit(__V, max_epi64, i, i);
+ __W = _mm512_mask_mov_ps(_mm512_set1_ps(1.0f), __M, __W);
+ _mm512_mask_reduce_operator(*);
}
+#undef _mm512_mask_reduce_operator
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
-_mm512_reduce_max_epu64(__m512i __V) {
- _mm512_reduce_maxMin_64bit(__V, max_epu64, i, i);
+#define _mm512_mask_reduce_operator(op) \
+ __m512i __t1 = (__m512i)__builtin_shufflevector((__v8di)__V, (__v8di)__V, 4, 5, 6, 7, 0, 1, 2, 3); \
+ __m512i __t2 = _mm512_##op(__V, __t1); \
+ __m512i __t3 = (__m512i)__builtin_shufflevector((__v8di)__t2, (__v8di)__t2, 2, 3, 0, 1, 6, 7, 4, 5); \
+ __m512i __t4 = _mm512_##op(__t2, __t3); \
+ __m512i __t5 = (__m512i)__builtin_shufflevector((__v8di)__t4, (__v8di)__t4, 1, 0, 3, 2, 5, 4, 7, 6); \
+ __v8di __t6 = (__v8di)_mm512_##op(__t4, __t5); \
+ return __t6[0];
+
+static __inline__ long long __DEFAULT_FN_ATTRS512
+_mm512_reduce_max_epi64(__m512i __V) {
+ _mm512_mask_reduce_operator(max_epi64);
}
-static __inline__ double __DEFAULT_FN_ATTRS
-_mm512_reduce_max_pd(__m512d __V) {
- _mm512_reduce_maxMin_64bit(__V, max_pd, d, f);
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS512
+_mm512_reduce_max_epu64(__m512i __V) {
+ _mm512_mask_reduce_operator(max_epu64);
}
-static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epi64
-(__m512i __V) {
- _mm512_reduce_maxMin_64bit(__V, min_epi64, i, i);
+static __inline__ long long __DEFAULT_FN_ATTRS512
+_mm512_reduce_min_epi64(__m512i __V) {
+ _mm512_mask_reduce_operator(min_epi64);
}
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS512
_mm512_reduce_min_epu64(__m512i __V) {
- _mm512_reduce_maxMin_64bit(__V, min_epu64, i, i);
+ _mm512_mask_reduce_operator(min_epu64);
}
-static __inline__ double __DEFAULT_FN_ATTRS
-_mm512_reduce_min_pd(__m512d __V) {
- _mm512_reduce_maxMin_64bit(__V, min_pd, d, f);
-}
-
-// Vec512 - Vector with size 512.
-// Vec512Neutral - A 512 length vector with elements set to the identity element
-// Identity element: {max_epi,0x8000000000000000}
-// {max_epu,0x0000000000000000}
-// {max_pd, 0xFFF0000000000000}
-// {min_epi,0x7FFFFFFFFFFFFFFF}
-// {min_epu,0xFFFFFFFFFFFFFFFF}
-// {min_pd, 0x7FF0000000000000}
-//
-// IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example:
-// __mm512_max_epi64
-// T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}]
-// T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}]
-// T3 - Can get 'q' q word and 'pd' for packed double.
-// [__builtin_ia32_select{q|pd}_512]
-// Mask - Intrinsic Mask
-
-#define _mm512_mask_reduce_maxMin_64bit(Vec512, Vec512Neutral, IntrinName, T1, \
- T2, T3, Mask) \
- __extension__({ \
- Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \
- (__mmask8)Mask, \
- (__v8d##T2)Vec512, \
- (__v8d##T2)Vec512Neutral); \
- _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2); \
- })
-
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x8000000000000000),
- max_epi64, i, i, q, __M);
+ __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(-__LONG_LONG_MAX__ - 1LL), __M, __V);
+ _mm512_mask_reduce_operator(max_epi64);
}
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x0000000000000000),
- max_epu64, i, i, q, __M);
-}
-
-static __inline__ double __DEFAULT_FN_ATTRS
-_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) {
- _mm512_mask_reduce_maxMin_64bit(__V, -_mm512_set1_pd(__builtin_inf()),
- max_pd, d, f, pd, __M);
+ __V = _mm512_maskz_mov_epi64(__M, __V);
+ _mm512_mask_reduce_operator(max_epu64);
}
-static __inline__ long long __DEFAULT_FN_ATTRS
+static __inline__ long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),
- min_epi64, i, i, q, __M);
+ __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(__LONG_LONG_MAX__), __M, __V);
+ _mm512_mask_reduce_operator(min_epi64);
}
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF),
- min_epu64, i, i, q, __M);
+ __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __V);
+ _mm512_mask_reduce_operator(min_epu64);
}
+#undef _mm512_mask_reduce_operator
-static __inline__ double __DEFAULT_FN_ATTRS
-_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) {
- _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(__builtin_inf()),
- min_pd, d, f, pd, __M);
-}
-
-// Vec512 - Vector with size 512.
-// IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example:
-// __mm512_max_epi32
-// T1 - Can get 'i' for int and ' ' .[__m512{i|}]
-// T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}]
-
-#define _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2) __extension__({ \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 0, 1, 2, 3, 4, 5, 6, 7, \
- -1, -1, -1, -1, -1, -1, -1, -1), \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 8, 9, 10, 11, 12, 13, 14, 15, \
- -1, -1, -1, -1, -1, -1, -1, -1)); \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 0, 1, 2, 3, -1, -1, -1, -1, \
- -1, -1, -1, -1, -1, -1, -1, -1), \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 4, 5, 6, 7, -1, -1, -1, -1, \
- -1, -1, -1, -1, -1, -1, -1, -1)); \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 0, 1, -1, -1, -1, -1, -1, -1, \
- -1, -1, -1, -1, -1, -1, -1, -1), \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 2, 3, -1, -1, -1, -1, -1, -1, \
- -1, -1, -1, -1, -1, -1, -1, -1)); \
- Vec512 = _mm512_##IntrinName( \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 0, -1, -1, -1, -1, -1, -1, -1, \
- -1, -1, -1, -1, -1, -1, -1, -1), \
- (__m512##T1)__builtin_shufflevector( \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512, \
- 1, -1, -1, -1, -1, -1, -1, -1, \
- -1, -1, -1, -1, -1, -1, -1, -1)); \
- return Vec512[0]; \
- })
-
-static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_max_epi32(__m512i a) {
- _mm512_reduce_maxMin_32bit(a, max_epi32, i, i);
-}
-
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-_mm512_reduce_max_epu32(__m512i a) {
- _mm512_reduce_maxMin_32bit(a, max_epu32, i, i);
-}
-
-static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_max_ps(__m512 a) {
- _mm512_reduce_maxMin_32bit(a, max_ps, , f);
-}
-
-static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_min_epi32(__m512i a) {
- _mm512_reduce_maxMin_32bit(a, min_epi32, i, i);
-}
-
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-_mm512_reduce_min_epu32(__m512i a) {
- _mm512_reduce_maxMin_32bit(a, min_epu32, i, i);
-}
-
-static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_min_ps(__m512 a) {
- _mm512_reduce_maxMin_32bit(a, min_ps, , f);
-}
-
-// Vec512 - Vector with size 512.
-// Vec512Neutral - A 512 length vector with elements set to the identity element
-// Identity element: {max_epi,0x80000000}
-// {max_epu,0x00000000}
-// {max_ps, 0xFF800000}
-// {min_epi,0x7FFFFFFF}
-// {min_epu,0xFFFFFFFF}
-// {min_ps, 0x7F800000}
-//
-// IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example:
-// __mm512_max_epi32
-// T1 - Can get 'i' for int and ' ' .[__m512{i|}]
-// T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}]
-// T3 - Can get 'q' q word and 'pd' for packed double.
-// [__builtin_ia32_select{q|pd}_512]
-// Mask - Intrinsic Mask
-
-#define _mm512_mask_reduce_maxMin_32bit(Vec512, Vec512Neutral, IntrinName, T1, \
- T2, T3, Mask) \
- __extension__({ \
- Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \
- (__mmask16)Mask, \
- (__v16s##T2)Vec512, \
- (__v16s##T2)Vec512Neutral); \
- _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2); \
- })
-
-static __inline__ int __DEFAULT_FN_ATTRS
-_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x80000000), max_epi32,
- i, i, d, __M);
+#define _mm512_mask_reduce_operator(op) \
+ __m256i __t1 = _mm512_extracti64x4_epi64(__V, 0); \
+ __m256i __t2 = _mm512_extracti64x4_epi64(__V, 1); \
+ __m256i __t3 = _mm256_##op(__t1, __t2); \
+ __m128i __t4 = _mm256_extracti128_si256(__t3, 0); \
+ __m128i __t5 = _mm256_extracti128_si256(__t3, 1); \
+ __m128i __t6 = _mm_##op(__t4, __t5); \
+ __m128i __t7 = (__m128i)__builtin_shufflevector((__v4si)__t6, (__v4si)__t6, 2, 3, 0, 1); \
+ __m128i __t8 = _mm_##op(__t6, __t7); \
+ __m128i __t9 = (__m128i)__builtin_shufflevector((__v4si)__t8, (__v4si)__t8, 1, 0, 3, 2); \
+ __v4si __t10 = (__v4si)_mm_##op(__t8, __t9); \
+ return __t10[0];
+
+static __inline__ int __DEFAULT_FN_ATTRS512
+_mm512_reduce_max_epi32(__m512i __V) {
+ _mm512_mask_reduce_operator(max_epi32);
}
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x00000000), max_epu32,
- i, i, d, __M);
+static __inline__ unsigned int __DEFAULT_FN_ATTRS512
+_mm512_reduce_max_epu32(__m512i __V) {
+ _mm512_mask_reduce_operator(max_epu32);
}
-static __inline__ float __DEFAULT_FN_ATTRS
-_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) {
- _mm512_mask_reduce_maxMin_32bit(__V,-_mm512_set1_ps(__builtin_inff()), max_ps, , f,
- ps, __M);
+static __inline__ int __DEFAULT_FN_ATTRS512
+_mm512_reduce_min_epi32(__m512i __V) {
+ _mm512_mask_reduce_operator(min_epi32);
}
-static __inline__ int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS512
+_mm512_reduce_min_epu32(__m512i __V) {
+ _mm512_mask_reduce_operator(min_epu32);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS512
+_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) {
+ __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(-__INT_MAX__ - 1), __M, __V);
+ _mm512_mask_reduce_operator(max_epi32);
+}
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS512
+_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) {
+ __V = _mm512_maskz_mov_epi32(__M, __V);
+ _mm512_mask_reduce_operator(max_epu32);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x7FFFFFFF), min_epi32,
- i, i, d, __M);
+ __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(__INT_MAX__), __M, __V);
+ _mm512_mask_reduce_operator(min_epi32);
}
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) {
- _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0xFFFFFFFF), min_epu32,
- i, i, d, __M);
+ __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __V);
+ _mm512_mask_reduce_operator(min_epu32);
+}
+#undef _mm512_mask_reduce_operator
+
+#define _mm512_mask_reduce_operator(op) \
+ __m256d __t1 = _mm512_extractf64x4_pd(__V, 0); \
+ __m256d __t2 = _mm512_extractf64x4_pd(__V, 1); \
+ __m256d __t3 = _mm256_##op(__t1, __t2); \
+ __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \
+ __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \
+ __m128d __t6 = _mm_##op(__t4, __t5); \
+ __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \
+ __m128d __t8 = _mm_##op(__t6, __t7); \
+ return __t8[0];
+
+static __inline__ double __DEFAULT_FN_ATTRS512
+_mm512_reduce_max_pd(__m512d __V) {
+ _mm512_mask_reduce_operator(max_pd);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS512
+_mm512_reduce_min_pd(__m512d __V) {
+ _mm512_mask_reduce_operator(min_pd);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS512
+_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) {
+ __V = _mm512_mask_mov_pd(_mm512_set1_pd(-__builtin_inf()), __M, __V);
+ _mm512_mask_reduce_operator(max_pd);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS512
+_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) {
+ __V = _mm512_mask_mov_pd(_mm512_set1_pd(__builtin_inf()), __M, __V);
+ _mm512_mask_reduce_operator(min_pd);
+}
+#undef _mm512_mask_reduce_operator
+
+#define _mm512_mask_reduce_operator(op) \
+ __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 0); \
+ __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 1); \
+ __m256 __t3 = _mm256_##op(__t1, __t2); \
+ __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \
+ __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \
+ __m128 __t6 = _mm_##op(__t4, __t5); \
+ __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \
+ __m128 __t8 = _mm_##op(__t6, __t7); \
+ __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \
+ __m128 __t10 = _mm_##op(__t8, __t9); \
+ return __t10[0];
+
+static __inline__ float __DEFAULT_FN_ATTRS512
+_mm512_reduce_max_ps(__m512 __V) {
+ _mm512_mask_reduce_operator(max_ps);
+}
+
+static __inline__ float __DEFAULT_FN_ATTRS512
+_mm512_reduce_min_ps(__m512 __V) {
+ _mm512_mask_reduce_operator(min_ps);
+}
+
+static __inline__ float __DEFAULT_FN_ATTRS512
+_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) {
+ __V = _mm512_mask_mov_ps(_mm512_set1_ps(-__builtin_inff()), __M, __V);
+ _mm512_mask_reduce_operator(max_ps);
}
-static __inline__ float __DEFAULT_FN_ATTRS
+static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) {
- _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_ps(__builtin_inff()), min_ps, , f,
- ps, __M);
+ __V = _mm512_mask_mov_ps(_mm512_set1_ps(__builtin_inff()), __M, __V);
+ _mm512_mask_reduce_operator(min_ps);
}
+#undef _mm512_mask_reduce_operator
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS512
+#undef __DEFAULT_FN_ATTRS128
-#endif // __AVX512FINTRIN_H
+#endif /* __AVX512FINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512ifmaintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512ifmaintrin.h
index 5defbaea8bcc..159713049c1a 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512ifmaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512ifmaintrin.h
@@ -29,62 +29,52 @@
#define __IFMAINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_madd52hi_epu64 (__m512i __X, __m512i __Y, __m512i __Z)
{
- return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __Z,
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_vpmadd52huq512((__v8di) __X, (__v8di) __Y,
+ (__v8di) __Z);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_madd52hi_epu64 (__m512i __W, __mmask8 __M, __m512i __X,
- __m512i __Y)
+_mm512_mask_madd52hi_epu64 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __W,
- (__v8di) __X,
- (__v8di) __Y,
- (__mmask8) __M);
+ return (__m512i)__builtin_ia32_selectq_512(__M,
+ (__v8di)_mm512_madd52hi_epu64(__W, __X, __Y),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_madd52hi_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z)
{
- return (__m512i) __builtin_ia32_vpmadd52huq512_maskz ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __Z,
- (__mmask8) __M);
+ return (__m512i)__builtin_ia32_selectq_512(__M,
+ (__v8di)_mm512_madd52hi_epu64(__X, __Y, __Z),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_madd52lo_epu64 (__m512i __X, __m512i __Y, __m512i __Z)
{
- return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __Z,
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_vpmadd52luq512((__v8di) __X, (__v8di) __Y,
+ (__v8di) __Z);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_madd52lo_epu64 (__m512i __W, __mmask8 __M, __m512i __X,
- __m512i __Y)
+_mm512_mask_madd52lo_epu64 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __W,
- (__v8di) __X,
- (__v8di) __Y,
- (__mmask8) __M);
+ return (__m512i)__builtin_ia32_selectq_512(__M,
+ (__v8di)_mm512_madd52lo_epu64(__W, __X, __Y),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_madd52lo_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z)
{
- return (__m512i) __builtin_ia32_vpmadd52luq512_maskz ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __Z,
- (__mmask8) __M);
+ return (__m512i)__builtin_ia32_selectq_512(__M,
+ (__v8di)_mm512_madd52lo_epu64(__X, __Y, __Z),
+ (__v8di)_mm512_setzero_si512());
}
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512ifmavlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512ifmavlintrin.h
index 131ee5cb4f88..afdea888c55b 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512ifmavlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512ifmavlintrin.h
@@ -29,121 +29,105 @@
#define __IFMAVLINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma,avx512vl")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma,avx512vl"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma,avx512vl"), __min_vector_width__(256)))
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_madd52hi_epu64 (__m128i __X, __m128i __Y, __m128i __Z)
{
- return (__m128i) __builtin_ia32_vpmadd52huq128_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __Z,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_vpmadd52huq128((__v2di) __X, (__v2di) __Y,
+ (__v2di) __Z);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_madd52hi_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_vpmadd52huq128_mask ((__v2di) __W,
- (__v2di) __X,
- (__v2di) __Y,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectq_128(__M,
+ (__v2di)_mm_madd52hi_epu64(__W, __X, __Y),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_madd52hi_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z)
{
- return (__m128i) __builtin_ia32_vpmadd52huq128_maskz ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __Z,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectq_128(__M,
+ (__v2di)_mm_madd52hi_epu64(__X, __Y, __Z),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_madd52hi_epu64 (__m256i __X, __m256i __Y, __m256i __Z)
{
- return (__m256i) __builtin_ia32_vpmadd52huq256_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __Z,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_vpmadd52huq256((__v4di)__X, (__v4di)__Y,
+ (__v4di)__Z);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X,
- __m256i __Y)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_vpmadd52huq256_mask ((__v4di) __W,
- (__v4di) __X,
- (__v4di) __Y,
- (__mmask8) __M);
+ return (__m256i)__builtin_ia32_selectq_256(__M,
+ (__v4di)_mm256_madd52hi_epu64(__W, __X, __Y),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_madd52hi_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z)
{
- return (__m256i) __builtin_ia32_vpmadd52huq256_maskz ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __Z,
- (__mmask8) __M);
+ return (__m256i)__builtin_ia32_selectq_256(__M,
+ (__v4di)_mm256_madd52hi_epu64(__X, __Y, __Z),
+ (__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_madd52lo_epu64 (__m128i __X, __m128i __Y, __m128i __Z)
{
- return (__m128i) __builtin_ia32_vpmadd52luq128_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __Z,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_vpmadd52luq128((__v2di)__X, (__v2di)__Y,
+ (__v2di)__Z);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_madd52lo_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_vpmadd52luq128_mask ((__v2di) __W,
- (__v2di) __X,
- (__v2di) __Y,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectq_128(__M,
+ (__v2di)_mm_madd52lo_epu64(__W, __X, __Y),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_madd52lo_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z)
{
- return (__m128i) __builtin_ia32_vpmadd52luq128_maskz ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __Z,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectq_128(__M,
+ (__v2di)_mm_madd52lo_epu64(__X, __Y, __Z),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_madd52lo_epu64 (__m256i __X, __m256i __Y, __m256i __Z)
{
- return (__m256i) __builtin_ia32_vpmadd52luq256_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __Z,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_vpmadd52luq256((__v4di)__X, (__v4di)__Y,
+ (__v4di)__Z);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X,
- __m256i __Y)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_vpmadd52luq256_mask ((__v4di) __W,
- (__v4di) __X,
- (__v4di) __Y,
- (__mmask8) __M);
+ return (__m256i)__builtin_ia32_selectq_256(__M,
+ (__v4di)_mm256_madd52lo_epu64(__W, __X, __Y),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_madd52lo_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z)
{
- return (__m256i) __builtin_ia32_vpmadd52luq256_maskz ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __Z,
- (__mmask8) __M);
+ return (__m256i)__builtin_ia32_selectq_256(__M,
+ (__v4di)_mm256_madd52lo_epu64(__X, __Y, __Z),
+ (__v4di)_mm256_setzero_si256());
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512pfintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512pfintrin.h
index c7fa3cf313e3..5b8260b77c63 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512pfintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512pfintrin.h
@@ -1,4 +1,4 @@
-/*===------------- avx512pfintrin.h - PF intrinsics ------------------===
+/*===------------- avx512pfintrin.h - PF intrinsics ------------------------===
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -31,80 +31,80 @@
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512pf")))
-#define _mm512_mask_prefetch_i32gather_pd(index, mask, addr, scale, hint) __extension__ ({\
+#define _mm512_mask_prefetch_i32gather_pd(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfdpd((__mmask8)(mask), (__v8si)(__m256i)(index), \
(long long const *)(addr), (int)(scale), \
- (int)(hint)); })
-
-#define _mm512_prefetch_i32gather_pd(index, addr, scale, hint) __extension__ ({\
+ (int)(hint))
+
+#define _mm512_prefetch_i32gather_pd(index, addr, scale, hint) \
__builtin_ia32_gatherpfdpd((__mmask8) -1, (__v8si)(__m256i)(index), \
(long long const *)(addr), (int)(scale), \
- (int)(hint)); })
+ (int)(hint))
-#define _mm512_mask_prefetch_i32gather_ps(index, mask, addr, scale, hint) ({\
+#define _mm512_mask_prefetch_i32gather_ps(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfdps((__mmask16)(mask), \
(__v16si)(__m512i)(index), (int const *)(addr), \
- (int)(scale), (int)(hint)); })
+ (int)(scale), (int)(hint))
-#define _mm512_prefetch_i32gather_ps(index, addr, scale, hint) ({\
+#define _mm512_prefetch_i32gather_ps(index, addr, scale, hint) \
__builtin_ia32_gatherpfdps((__mmask16) -1, \
(__v16si)(__m512i)(index), (int const *)(addr), \
- (int)(scale), (int)(hint)); })
+ (int)(scale), (int)(hint))
-#define _mm512_mask_prefetch_i64gather_pd(index, mask, addr, scale, hint) __extension__ ({\
+#define _mm512_mask_prefetch_i64gather_pd(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfqpd((__mmask8)(mask), (__v8di)(__m512i)(index), \
(long long const *)(addr), (int)(scale), \
- (int)(hint)); })
+ (int)(hint))
-#define _mm512_prefetch_i64gather_pd(index, addr, scale, hint) __extension__ ({\
+#define _mm512_prefetch_i64gather_pd(index, addr, scale, hint) \
__builtin_ia32_gatherpfqpd((__mmask8) -1, (__v8di)(__m512i)(index), \
(long long const *)(addr), (int)(scale), \
- (int)(hint)); })
-
-#define _mm512_mask_prefetch_i64gather_ps(index, mask, addr, scale, hint) ({\
+ (int)(hint))
+
+#define _mm512_mask_prefetch_i64gather_ps(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfqps((__mmask8)(mask), (__v8di)(__m512i)(index), \
- (int const *)(addr), (int)(scale), (int)(hint)); })
+ (int const *)(addr), (int)(scale), (int)(hint))
-#define _mm512_prefetch_i64gather_ps(index, addr, scale, hint) ({\
+#define _mm512_prefetch_i64gather_ps(index, addr, scale, hint) \
__builtin_ia32_gatherpfqps((__mmask8) -1, (__v8di)(__m512i)(index), \
- (int const *)(addr), (int)(scale), (int)(hint)); })
+ (int const *)(addr), (int)(scale), (int)(hint))
-#define _mm512_prefetch_i32scatter_pd(addr, index, scale, hint) __extension__ ({\
+#define _mm512_prefetch_i32scatter_pd(addr, index, scale, hint) \
__builtin_ia32_scatterpfdpd((__mmask8)-1, (__v8si)(__m256i)(index), \
(long long *)(addr), (int)(scale), \
- (int)(hint)); })
+ (int)(hint))
-#define _mm512_mask_prefetch_i32scatter_pd(addr, mask, index, scale, hint) __extension__ ({\
+#define _mm512_mask_prefetch_i32scatter_pd(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfdpd((__mmask8)(mask), (__v8si)(__m256i)(index), \
(long long *)(addr), (int)(scale), \
- (int)(hint)); })
+ (int)(hint))
-#define _mm512_prefetch_i32scatter_ps(addr, index, scale, hint) __extension__ ({\
+#define _mm512_prefetch_i32scatter_ps(addr, index, scale, hint) \
__builtin_ia32_scatterpfdps((__mmask16)-1, (__v16si)(__m512i)(index), \
- (int *)(addr), (int)(scale), (int)(hint)); })
+ (int *)(addr), (int)(scale), (int)(hint))
-#define _mm512_mask_prefetch_i32scatter_ps(addr, mask, index, scale, hint) __extension__ ({\
+#define _mm512_mask_prefetch_i32scatter_ps(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfdps((__mmask16)(mask), \
(__v16si)(__m512i)(index), (int *)(addr), \
- (int)(scale), (int)(hint)); })
+ (int)(scale), (int)(hint))
-#define _mm512_prefetch_i64scatter_pd(addr, index, scale, hint) __extension__ ({\
+#define _mm512_prefetch_i64scatter_pd(addr, index, scale, hint) \
__builtin_ia32_scatterpfqpd((__mmask8)-1, (__v8di)(__m512i)(index), \
(long long *)(addr), (int)(scale), \
- (int)(hint)); })
+ (int)(hint))
-#define _mm512_mask_prefetch_i64scatter_pd(addr, mask, index, scale, hint) __extension__ ({\
+#define _mm512_mask_prefetch_i64scatter_pd(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfqpd((__mmask8)(mask), (__v8di)(__m512i)(index), \
(long long *)(addr), (int)(scale), \
- (int)(hint)); })
+ (int)(hint))
-#define _mm512_prefetch_i64scatter_ps(addr, index, scale, hint) __extension__ ({\
+#define _mm512_prefetch_i64scatter_ps(addr, index, scale, hint) \
__builtin_ia32_scatterpfqps((__mmask8)-1, (__v8di)(__m512i)(index), \
- (int *)(addr), (int)(scale), (int)(hint)); })
+ (int *)(addr), (int)(scale), (int)(hint))
-#define _mm512_mask_prefetch_i64scatter_ps(addr, mask, index, scale, hint) __extension__ ({\
+#define _mm512_mask_prefetch_i64scatter_ps(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfqps((__mmask8)(mask), (__v8di)(__m512i)(index), \
- (int *)(addr), (int)(scale), (int)(hint)); })
+ (int *)(addr), (int)(scale), (int)(hint))
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vbmi2intrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vbmi2intrin.h
index 43e97b40a098..d2a58094fd07 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vbmi2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vbmi2intrin.h
@@ -29,7 +29,7 @@
#define __AVX512VBMI2INTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi2")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi2"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -44,7 +44,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_compress_epi16(__mmask32 __U, __m512i __D)
{
return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi) __D,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
__U);
}
@@ -60,7 +60,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_compress_epi8(__mmask64 __U, __m512i __D)
{
return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi) __D,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
__U);
}
@@ -90,7 +90,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_expand_epi16(__mmask32 __U, __m512i __D)
{
return (__m512i) __builtin_ia32_expandhi512_mask ((__v32hi) __D,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
__U);
}
@@ -106,7 +106,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_expand_epi8(__mmask64 __U, __m512i __D)
{
return (__m512i) __builtin_ia32_expandqi512_mask ((__v64qi) __D,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
__U);
}
@@ -122,7 +122,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_expandloadu_epi16(__mmask32 __U, void const *__P)
{
return (__m512i) __builtin_ia32_expandloadhi512_mask ((const __v32hi *)__P,
- (__v32hi) _mm512_setzero_hi(),
+ (__v32hi) _mm512_setzero_si512(),
__U);
}
@@ -138,87 +138,93 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_expandloadu_epi8(__mmask64 __U, void const *__P)
{
return (__m512i) __builtin_ia32_expandloadqi512_mask ((const __v64qi *)__P,
- (__v64qi) _mm512_setzero_qi(),
+ (__v64qi) _mm512_setzero_si512(),
__U);
}
-#define _mm512_mask_shldi_epi64(S, U, A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_vpshldq512_mask((__v8di)(A), \
- (__v8di)(B), \
- (int)(I), \
- (__v8di)(S), \
- (__mmask8)(U)); })
+#define _mm512_shldi_epi64(A, B, I) \
+ (__m512i)__builtin_ia32_vpshldq512((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), (int)(I))
+
+#define _mm512_mask_shldi_epi64(S, U, A, B, I) \
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_shldi_epi64((A), (B), (I)), \
+ (__v8di)(__m512i)(S))
#define _mm512_maskz_shldi_epi64(U, A, B, I) \
- _mm512_mask_shldi_epi64(_mm512_setzero_hi(), (U), (A), (B), (I))
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_shldi_epi64((A), (B), (I)), \
+ (__v8di)_mm512_setzero_si512())
-#define _mm512_shldi_epi64(A, B, I) \
- _mm512_mask_shldi_epi64(_mm512_undefined(), (__mmask8)(-1), (A), (B), (I))
+#define _mm512_shldi_epi32(A, B, I) \
+ (__m512i)__builtin_ia32_vpshldd512((__v16si)(__m512i)(A), \
+ (__v16si)(__m512i)(B), (int)(I))
-#define _mm512_mask_shldi_epi32(S, U, A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_vpshldd512_mask((__v16si)(A), \
- (__v16si)(B), \
- (int)(I), \
- (__v16si)(S), \
- (__mmask16)(U)); })
+#define _mm512_mask_shldi_epi32(S, U, A, B, I) \
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_shldi_epi32((A), (B), (I)), \
+ (__v16si)(__m512i)(S))
#define _mm512_maskz_shldi_epi32(U, A, B, I) \
- _mm512_mask_shldi_epi32(_mm512_setzero_hi(), (U), (A), (B), (I))
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_shldi_epi32((A), (B), (I)), \
+ (__v16si)_mm512_setzero_si512())
-#define _mm512_shldi_epi32(A, B, I) \
- _mm512_mask_shldi_epi32(_mm512_undefined(), (__mmask16)(-1), (A), (B), (I))
+#define _mm512_shldi_epi16(A, B, I) \
+ (__m512i)__builtin_ia32_vpshldw512((__v32hi)(__m512i)(A), \
+ (__v32hi)(__m512i)(B), (int)(I))
-#define _mm512_mask_shldi_epi16(S, U, A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_vpshldw512_mask((__v32hi)(A), \
- (__v32hi)(B), \
- (int)(I), \
- (__v32hi)(S), \
- (__mmask32)(U)); })
+#define _mm512_mask_shldi_epi16(S, U, A, B, I) \
+ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
+ (__v32hi)_mm512_shldi_epi16((A), (B), (I)), \
+ (__v32hi)(__m512i)(S))
#define _mm512_maskz_shldi_epi16(U, A, B, I) \
- _mm512_mask_shldi_epi16(_mm512_setzero_hi(), (U), (A), (B), (I))
+ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
+ (__v32hi)_mm512_shldi_epi16((A), (B), (I)), \
+ (__v32hi)_mm512_setzero_si512())
-#define _mm512_shldi_epi16(A, B, I) \
- _mm512_mask_shldi_epi16(_mm512_undefined(), (__mmask32)(-1), (A), (B), (I))
+#define _mm512_shrdi_epi64(A, B, I) \
+ (__m512i)__builtin_ia32_vpshrdq512((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), (int)(I))
-#define _mm512_mask_shrdi_epi64(S, U, A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_vpshrdq512_mask((__v8di)(A), \
- (__v8di)(B), \
- (int)(I), \
- (__v8di)(S), \
- (__mmask8)(U)); })
+#define _mm512_mask_shrdi_epi64(S, U, A, B, I) \
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_shrdi_epi64((A), (B), (I)), \
+ (__v8di)(__m512i)(S))
#define _mm512_maskz_shrdi_epi64(U, A, B, I) \
- _mm512_mask_shrdi_epi64(_mm512_setzero_hi(), (U), (A), (B), (I))
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_shrdi_epi64((A), (B), (I)), \
+ (__v8di)_mm512_setzero_si512())
-#define _mm512_shrdi_epi64(A, B, I) \
- _mm512_mask_shrdi_epi64(_mm512_undefined(), (__mmask8)(-1), (A), (B), (I))
+#define _mm512_shrdi_epi32(A, B, I) \
+ (__m512i)__builtin_ia32_vpshrdd512((__v16si)(__m512i)(A), \
+ (__v16si)(__m512i)(B), (int)(I))
-#define _mm512_mask_shrdi_epi32(S, U, A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_vpshrdd512_mask((__v16si)(A), \
- (__v16si)(B), \
- (int)(I), \
- (__v16si)(S), \
- (__mmask16)(U)); })
+#define _mm512_mask_shrdi_epi32(S, U, A, B, I) \
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_shrdi_epi32((A), (B), (I)), \
+ (__v16si)(__m512i)(S))
#define _mm512_maskz_shrdi_epi32(U, A, B, I) \
- _mm512_mask_shrdi_epi32(_mm512_setzero_hi(), (U), (A), (B), (I))
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_shrdi_epi32((A), (B), (I)), \
+ (__v16si)_mm512_setzero_si512())
-#define _mm512_shrdi_epi32(A, B, I) \
- _mm512_mask_shrdi_epi32(_mm512_undefined(), (__mmask16)(-1), (A), (B), (I))
+#define _mm512_shrdi_epi16(A, B, I) \
+ (__m512i)__builtin_ia32_vpshrdw512((__v32hi)(__m512i)(A), \
+ (__v32hi)(__m512i)(B), (int)(I))
-#define _mm512_mask_shrdi_epi16(S, U, A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_vpshrdw512_mask((__v32hi)(A), \
- (__v32hi)(B), \
- (int)(I), \
- (__v32hi)(S), \
- (__mmask32)(U)); })
+#define _mm512_mask_shrdi_epi16(S, U, A, B, I) \
+ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
+ (__v32hi)_mm512_shrdi_epi16((A), (B), (I)), \
+ (__v32hi)(__m512i)(S))
#define _mm512_maskz_shrdi_epi16(U, A, B, I) \
- _mm512_mask_shrdi_epi16(_mm512_setzero_hi(), (U), (A), (B), (I))
-
-#define _mm512_shrdi_epi16(A, B, I) \
- _mm512_mask_shrdi_epi16(_mm512_undefined(), (__mmask32)(-1), (A), (B), (I))
+ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \
+ (__v32hi)_mm512_shrdi_epi16((A), (B), (I)), \
+ (__v32hi)_mm512_setzero_si512())
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_shldv_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B)
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vbmiintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vbmiintrin.h
index 837238eda97f..b6e93c285871 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vbmiintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vbmiintrin.h
@@ -29,79 +29,65 @@
#define __VBMIINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask2_permutex2var_epi8 (__m512i __A, __m512i __I,
- __mmask64 __U, __m512i __B)
+_mm512_permutex2var_epi8(__m512i __A, __m512i __I, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermi2varqi512_mask ((__v64qi) __A,
- (__v64qi) __I
- /* idx */ ,
- (__v64qi) __B,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_vpermi2varqi512((__v64qi)__A, (__v64qi)__I,
+ (__v64qi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_permutex2var_epi8 (__m512i __A, __m512i __I, __m512i __B)
+_mm512_mask_permutex2var_epi8(__m512i __A, __mmask64 __U, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I
- /* idx */ ,
- (__v64qi) __A,
- (__v64qi) __B,
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_selectb_512(__U,
+ (__v64qi)_mm512_permutex2var_epi8(__A, __I, __B),
+ (__v64qi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_permutex2var_epi8 (__m512i __A, __mmask64 __U,
- __m512i __I, __m512i __B)
+_mm512_mask2_permutex2var_epi8(__m512i __A, __m512i __I, __mmask64 __U,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I
- /* idx */ ,
- (__v64qi) __A,
- (__v64qi) __B,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512(__U,
+ (__v64qi)_mm512_permutex2var_epi8(__A, __I, __B),
+ (__v64qi)__I);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_permutex2var_epi8 (__mmask64 __U, __m512i __A,
- __m512i __I, __m512i __B)
+_mm512_maskz_permutex2var_epi8(__mmask64 __U, __m512i __A, __m512i __I,
+ __m512i __B)
{
- return (__m512i) __builtin_ia32_vpermt2varqi512_maskz ((__v64qi) __I
- /* idx */ ,
- (__v64qi) __A,
- (__v64qi) __B,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512(__U,
+ (__v64qi)_mm512_permutex2var_epi8(__A, __I, __B),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_permutexvar_epi8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
- (__v64qi) __A,
- (__v64qi) _mm512_undefined_epi32 (),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_permvarqi512((__v64qi) __B, (__v64qi) __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_permutexvar_epi8 (__mmask64 __M, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
- (__v64qi) __A,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_permutexvar_epi8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_permutexvar_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
- (__v64qi) __A,
- (__v64qi) __W,
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_permutexvar_epi8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vbmivlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vbmivlintrin.h
index 105c6d142fa6..9a0400b2b5d5 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vbmivlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vbmivlintrin.h
@@ -29,161 +29,127 @@
#define __VBMIVLINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi,avx512vl")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi,avx512vl"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi,avx512vl"), __min_vector_width__(256)))
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask2_permutex2var_epi8 (__m128i __A, __m128i __I, __mmask16 __U,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_permutex2var_epi8(__m128i __A, __m128i __I, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpermi2varqi128_mask ((__v16qi) __A,
- (__v16qi) __I
- /* idx */ ,
- (__v16qi) __B,
- (__mmask16)
- __U);
+ return (__m128i)__builtin_ia32_vpermi2varqi128((__v16qi)__A,
+ (__v16qi)__I,
+ (__v16qi)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask2_permutex2var_epi8 (__m256i __A, __m256i __I,
- __mmask32 __U, __m256i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_permutex2var_epi8(__m128i __A, __mmask16 __U, __m128i __I,
+ __m128i __B)
{
- return (__m256i) __builtin_ia32_vpermi2varqi256_mask ((__v32qi) __A,
- (__v32qi) __I
- /* idx */ ,
- (__v32qi) __B,
- (__mmask32)
- __U);
+ return (__m128i)__builtin_ia32_selectb_128(__U,
+ (__v16qi)_mm_permutex2var_epi8(__A, __I, __B),
+ (__v16qi)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_permutex2var_epi8 (__m128i __A, __m128i __I, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask2_permutex2var_epi8(__m128i __A, __m128i __I, __mmask16 __U,
+ __m128i __B)
{
- return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I
- /* idx */ ,
- (__v16qi) __A,
- (__v16qi) __B,
- (__mmask16) -
- 1);
+ return (__m128i)__builtin_ia32_selectb_128(__U,
+ (__v16qi)_mm_permutex2var_epi8(__A, __I, __B),
+ (__v16qi)__I);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_permutex2var_epi8 (__m128i __A, __mmask16 __U, __m128i __I,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_permutex2var_epi8(__mmask16 __U, __m128i __A, __m128i __I,
+ __m128i __B)
{
- return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I
- /* idx */ ,
- (__v16qi) __A,
- (__v16qi) __B,
- (__mmask16)
- __U);
+ return (__m128i)__builtin_ia32_selectb_128(__U,
+ (__v16qi)_mm_permutex2var_epi8(__A, __I, __B),
+ (__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_permutex2var_epi8 (__mmask16 __U, __m128i __A, __m128i __I,
- __m128i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_permutex2var_epi8(__m256i __A, __m256i __I, __m256i __B)
{
- return (__m128i) __builtin_ia32_vpermt2varqi128_maskz ((__v16qi) __I
- /* idx */ ,
- (__v16qi) __A,
- (__v16qi) __B,
- (__mmask16)
- __U);
+ return (__m256i)__builtin_ia32_vpermi2varqi256((__v32qi)__A, (__v32qi)__I,
+ (__v32qi)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_permutex2var_epi8 (__m256i __A, __m256i __I, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_permutex2var_epi8(__m256i __A, __mmask32 __U, __m256i __I,
+ __m256i __B)
{
- return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I
- /* idx */ ,
- (__v32qi) __A,
- (__v32qi) __B,
- (__mmask32) -
- 1);
+ return (__m256i)__builtin_ia32_selectb_256(__U,
+ (__v32qi)_mm256_permutex2var_epi8(__A, __I, __B),
+ (__v32qi)__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_permutex2var_epi8 (__m256i __A, __mmask32 __U,
- __m256i __I, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask2_permutex2var_epi8(__m256i __A, __m256i __I, __mmask32 __U,
+ __m256i __B)
{
- return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I
- /* idx */ ,
- (__v32qi) __A,
- (__v32qi) __B,
- (__mmask32)
- __U);
+ return (__m256i)__builtin_ia32_selectb_256(__U,
+ (__v32qi)_mm256_permutex2var_epi8(__A, __I, __B),
+ (__v32qi)__I);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_permutex2var_epi8 (__mmask32 __U, __m256i __A,
- __m256i __I, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_maskz_permutex2var_epi8(__mmask32 __U, __m256i __A, __m256i __I,
+ __m256i __B)
{
- return (__m256i) __builtin_ia32_vpermt2varqi256_maskz ((__v32qi) __I
- /* idx */ ,
- (__v32qi) __A,
- (__v32qi) __B,
- (__mmask32)
- __U);
+ return (__m256i)__builtin_ia32_selectb_256(__U,
+ (__v32qi)_mm256_permutex2var_epi8(__A, __I, __B),
+ (__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_permutexvar_epi8 (__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
- (__v16qi) __A,
- (__v16qi) _mm_undefined_si128 (),
- (__mmask16) -1);
+ return (__m128i)__builtin_ia32_permvarqi128((__v16qi)__B, (__v16qi)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_permutexvar_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
- (__v16qi) __A,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_permutexvar_epi8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_permutexvar_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
__m128i __B)
{
- return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
- (__v16qi) __A,
- (__v16qi) __W,
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_permutexvar_epi8(__A, __B),
+ (__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_permutexvar_epi8 (__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
- (__v32qi) __A,
- (__v32qi) _mm256_undefined_si256 (),
- (__mmask32) -1);
+ return (__m256i)__builtin_ia32_permvarqi256((__v32qi) __B, (__v32qi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_permutexvar_epi8 (__mmask32 __M, __m256i __A,
__m256i __B)
{
- return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
- (__v32qi) __A,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_permutexvar_epi8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
__m256i __B)
{
- return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
- (__v32qi) __A,
- (__v32qi) __W,
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_permutexvar_epi8(__A, __B),
+ (__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y)
{
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
@@ -192,7 +158,7 @@ _mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i
(__mmask16) __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y)
{
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
@@ -202,7 +168,7 @@ _mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y)
(__mmask16) __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y)
{
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
@@ -212,7 +178,7 @@ _mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y)
(__mmask16) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y)
{
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
@@ -221,7 +187,7 @@ _mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m2
(__mmask32) __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y)
{
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
@@ -231,7 +197,7 @@ _mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y)
(__mmask32) __M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y)
{
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
@@ -242,6 +208,7 @@ _mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y)
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlbitalgintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlbitalgintrin.h
index beb0a0e4779a..64860b29254f 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlbitalgintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlbitalgintrin.h
@@ -1,4 +1,4 @@
-/*===------------- avx512vlbitalgintrin.h - BITALG intrinsics ------------------===
+/*===---- avx512vlbitalgintrin.h - BITALG intrinsics -----------------------===
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,15 +29,16 @@
#define __AVX512VLBITALGINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bitalg")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bitalg"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bitalg"), __min_vector_width__(256)))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_popcnt_epi16(__m256i __A)
{
return (__m256i) __builtin_ia32_vpopcntw_256((__v16hi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B)
{
return (__m256i) __builtin_ia32_selectw_256((__mmask16) __U,
@@ -45,7 +46,7 @@ _mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B)
(__v16hi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B)
{
return _mm256_mask_popcnt_epi16((__m256i) _mm256_setzero_si256(),
@@ -53,13 +54,13 @@ _mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B)
__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_popcnt_epi16(__m128i __A)
{
return (__m128i) __builtin_ia32_vpopcntw_128((__v8hi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B)
{
return (__m128i) __builtin_ia32_selectw_128((__mmask8) __U,
@@ -67,7 +68,7 @@ _mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B)
(__v8hi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B)
{
return _mm_mask_popcnt_epi16((__m128i) _mm_setzero_si128(),
@@ -75,13 +76,13 @@ _mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B)
__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_popcnt_epi8(__m256i __A)
{
return (__m256i) __builtin_ia32_vpopcntb_256((__v32qi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B)
{
return (__m256i) __builtin_ia32_selectb_256((__mmask32) __U,
@@ -89,7 +90,7 @@ _mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B)
(__v32qi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B)
{
return _mm256_mask_popcnt_epi8((__m256i) _mm256_setzero_si256(),
@@ -97,13 +98,13 @@ _mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B)
__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_popcnt_epi8(__m128i __A)
{
return (__m128i) __builtin_ia32_vpopcntb_128((__v16qi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B)
{
return (__m128i) __builtin_ia32_selectb_128((__mmask16) __U,
@@ -111,7 +112,7 @@ _mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B)
(__v16qi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B)
{
return _mm_mask_popcnt_epi8((__m128i) _mm_setzero_si128(),
@@ -119,7 +120,7 @@ _mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B)
__B);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask((__v32qi) __A,
@@ -127,7 +128,7 @@ _mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B)
{
return _mm256_mask_bitshuffle_epi64_mask((__mmask32) -1,
@@ -135,7 +136,7 @@ _mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B)
__B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_mask_bitshuffle_epi64_mask(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask((__v16qi) __A,
@@ -143,7 +144,7 @@ _mm_mask_bitshuffle_epi64_mask(__mmask16 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B)
{
return _mm_mask_bitshuffle_epi64_mask((__mmask16) -1,
@@ -152,6 +153,7 @@ _mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B)
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
index e940e2b68533..1b038dd04df6 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
@@ -29,94 +29,90 @@
#define __AVX512VLBWINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw")))
-
-static __inline __m128i __DEFAULT_FN_ATTRS
-_mm_setzero_hi(void){
- return (__m128i)(__v8hi){ 0, 0, 0, 0, 0, 0, 0, 0 };
-}
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw"), __min_vector_width__(256)))
/* Integer compare */
-#define _mm_cmp_epi8_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epi8_mask(a, b, p) \
(__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
(__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epi8_mask(m, a, b, p) \
(__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
(__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)(m)); })
+ (__mmask16)(m))
-#define _mm_cmp_epu8_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epu8_mask(a, b, p) \
(__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
(__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epu8_mask(m, a, b, p) \
(__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
(__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)(m)); })
+ (__mmask16)(m))
-#define _mm256_cmp_epi8_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epi8_mask(a, b, p) \
(__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
(__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)-1); })
+ (__mmask32)-1)
-#define _mm256_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epi8_mask(m, a, b, p) \
(__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
(__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)(m)); })
+ (__mmask32)(m))
-#define _mm256_cmp_epu8_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epu8_mask(a, b, p) \
(__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
(__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)-1); })
+ (__mmask32)-1)
-#define _mm256_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epu8_mask(m, a, b, p) \
(__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
(__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)(m)); })
+ (__mmask32)(m))
-#define _mm_cmp_epi16_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epi16_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
(__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epi16_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
(__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm_cmp_epu16_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epu16_mask(a, b, p) \
(__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
(__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epu16_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
(__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_epi16_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epi16_mask(a, b, p) \
(__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
(__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm256_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epi16_mask(m, a, b, p) \
(__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
(__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)(m)); })
+ (__mmask16)(m))
-#define _mm256_cmp_epu16_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epu16_mask(a, b, p) \
(__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
(__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)-1); })
+ (__mmask16)-1)
-#define _mm256_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epu16_mask(m, a, b, p) \
(__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
(__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)(m)); })
+ (__mmask16)(m))
#define _mm_cmpeq_epi8_mask(A, B) \
_mm_cmp_epi8_mask((A), (B), _MM_CMPINT_EQ)
@@ -318,147 +314,147 @@ _mm_setzero_hi(void){
#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
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_add_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B){
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_add_epi8(__A, __B),
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_add_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_add_epi8(__A, __B),
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_add_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_add_epi16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_add_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_add_epi16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sub_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_sub_epi8(__A, __B),
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sub_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_sub_epi8(__A, __B),
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sub_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_sub_epi16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sub_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_sub_epi16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_add_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_add_epi8(__A, __B),
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_add_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_add_epi8(__A, __B),
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_add_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_add_epi16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_add_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_add_epi16(__A, __B),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sub_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_sub_epi8(__A, __B),
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sub_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_sub_epi8(__A, __B),
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sub_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_sub_epi16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sub_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_sub_epi16(__A, __B),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mullo_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mullo_epi16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mullo_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mullo_epi16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mullo_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mullo_epi16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mullo_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mullo_epi16(__A, __B),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_blend_epi8 (__mmask16 __U, __m128i __A, __m128i __W)
{
return (__m128i) __builtin_ia32_selectb_128 ((__mmask16) __U,
@@ -466,7 +462,7 @@ _mm_mask_blend_epi8 (__mmask16 __U, __m128i __A, __m128i __W)
(__v16qi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_blend_epi8 (__mmask32 __U, __m256i __A, __m256i __W)
{
return (__m256i) __builtin_ia32_selectb_256 ((__mmask32) __U,
@@ -474,7 +470,7 @@ _mm256_mask_blend_epi8 (__mmask32 __U, __m256i __A, __m256i __W)
(__v32qi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_blend_epi16 (__mmask8 __U, __m128i __A, __m128i __W)
{
return (__m128i) __builtin_ia32_selectw_128 ((__mmask8) __U,
@@ -482,7 +478,7 @@ _mm_mask_blend_epi16 (__mmask8 __U, __m128i __A, __m128i __W)
(__v8hi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W)
{
return (__m256i) __builtin_ia32_selectw_256 ((__mmask16) __U,
@@ -490,7 +486,7 @@ _mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W)
(__v16hi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_abs_epi8(__m128i __W, __mmask16 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -498,7 +494,7 @@ _mm_mask_abs_epi8(__m128i __W, __mmask16 __U, __m128i __A)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_abs_epi8(__mmask16 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -506,7 +502,7 @@ _mm_maskz_abs_epi8(__mmask16 __U, __m128i __A)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_abs_epi8(__m256i __W, __mmask32 __U, __m256i __A)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -514,7 +510,7 @@ _mm256_mask_abs_epi8(__m256i __W, __mmask32 __U, __m256i __A)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -522,7 +518,7 @@ _mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_abs_epi16(__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -530,7 +526,7 @@ _mm_mask_abs_epi16(__m128i __W, __mmask8 __U, __m128i __A)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_abs_epi16(__mmask8 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -538,7 +534,7 @@ _mm_maskz_abs_epi16(__mmask8 __U, __m128i __A)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_abs_epi16(__m256i __W, __mmask16 __U, __m256i __A)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -546,7 +542,7 @@ _mm256_mask_abs_epi16(__m256i __W, __mmask16 __U, __m256i __A)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_abs_epi16(__mmask16 __U, __m256i __A)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -554,22 +550,22 @@ _mm256_maskz_abs_epi16(__mmask16 __U, __m256i __A)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_packs_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
(__v8hi)_mm_packs_epi32(__A, __B),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_packs_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_packs_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
(__v8hi)_mm_packs_epi32(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -577,7 +573,7 @@ _mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -585,7 +581,7 @@ _mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -593,7 +589,7 @@ _mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -601,7 +597,7 @@ _mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -609,7 +605,7 @@ _mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -617,7 +613,7 @@ _mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -625,15 +621,15 @@ _mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_packus_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_packus_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
(__v8hi)_mm_packus_epi32(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -641,7 +637,7 @@ _mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -649,7 +645,7 @@ _mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -657,7 +653,7 @@ _mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -665,7 +661,7 @@ _mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -673,7 +669,7 @@ _mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -681,7 +677,7 @@ _mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -689,7 +685,7 @@ _mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -697,7 +693,7 @@ _mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -705,7 +701,7 @@ _mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -713,7 +709,7 @@ _mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -721,7 +717,7 @@ _mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -729,7 +725,7 @@ _mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -737,7 +733,7 @@ _mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -745,7 +741,7 @@ _mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -753,7 +749,7 @@ _mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -761,7 +757,7 @@ _mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -769,7 +765,7 @@ _mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -777,7 +773,7 @@ _mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -785,7 +781,7 @@ _mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -793,7 +789,7 @@ _mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -801,7 +797,7 @@ _mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -809,7 +805,7 @@ _mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -817,7 +813,7 @@ _mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -825,7 +821,7 @@ _mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -833,7 +829,7 @@ _mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -841,7 +837,7 @@ _mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -849,7 +845,7 @@ _mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -857,7 +853,7 @@ _mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -865,7 +861,7 @@ _mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_avg_epu16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -873,7 +869,7 @@ _mm256_maskz_avg_epu16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -881,7 +877,7 @@ _mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -889,7 +885,7 @@ _mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -897,7 +893,7 @@ _mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -905,7 +901,7 @@ _mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -913,7 +909,7 @@ _mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -921,7 +917,7 @@ _mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -929,7 +925,7 @@ _mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -937,7 +933,7 @@ _mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -945,7 +941,7 @@ _mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -953,7 +949,7 @@ _mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -961,7 +957,7 @@ _mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -969,7 +965,7 @@ _mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -977,7 +973,7 @@ _mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -985,7 +981,7 @@ _mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -993,7 +989,7 @@ _mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -1001,7 +997,7 @@ _mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -1009,7 +1005,7 @@ _mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -1017,7 +1013,7 @@ _mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -1025,7 +1021,7 @@ _mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -1033,7 +1029,7 @@ _mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -1041,7 +1037,7 @@ _mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -1049,7 +1045,7 @@ _mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -1057,7 +1053,7 @@ _mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -1065,7 +1061,7 @@ _mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -1073,7 +1069,7 @@ _mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
@@ -1081,7 +1077,7 @@ _mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -1089,7 +1085,7 @@ _mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
@@ -1097,7 +1093,7 @@ _mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -1105,7 +1101,7 @@ _mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
@@ -1113,7 +1109,7 @@ _mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -1121,7 +1117,7 @@ _mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
@@ -1129,7 +1125,7 @@ _mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -1137,7 +1133,7 @@ _mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -1145,7 +1141,7 @@ _mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -1153,7 +1149,7 @@ _mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -1161,7 +1157,7 @@ _mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -1169,7 +1165,7 @@ _mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -1177,7 +1173,7 @@ _mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -1185,7 +1181,7 @@ _mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -1193,7 +1189,7 @@ _mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1201,7 +1197,7 @@ _mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1209,7 +1205,7 @@ _mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1217,7 +1213,7 @@ _mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1225,7 +1221,7 @@ _mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -1233,7 +1229,7 @@ _mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
@@ -1241,7 +1237,7 @@ _mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B)
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -1249,7 +1245,7 @@ _mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
@@ -1257,7 +1253,7 @@ _mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B)
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1265,7 +1261,7 @@ _mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1273,7 +1269,7 @@ _mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A,
__m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1281,7 +1277,7 @@ _mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A,
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1289,99 +1285,89 @@ _mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask2_permutex2var_epi16 (__m128i __A, __m128i __I, __mmask8 __U,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_permutex2var_epi16(__m128i __A, __m128i __I, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpermi2varhi128_mask ((__v8hi) __A,
- (__v8hi) __I /* idx */ ,
- (__v8hi) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_vpermi2varhi128((__v8hi)__A, (__v8hi)__I,
+ (__v8hi) __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask2_permutex2var_epi16 (__m256i __A, __m256i __I,
- __mmask16 __U, __m256i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I,
+ __m128i __B)
{
- return (__m256i) __builtin_ia32_vpermi2varhi256_mask ((__v16hi) __A,
- (__v16hi) __I /* idx */ ,
- (__v16hi) __B,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_permutex2var_epi16(__A, __I, __B),
+ (__v8hi)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_permutex2var_epi16 (__m128i __A, __m128i __I, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U,
+ __m128i __B)
{
- return (__m128i) __builtin_ia32_vpermt2varhi128_mask ((__v8hi) __I/* idx */,
- (__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_permutex2var_epi16(__A, __I, __B),
+ (__v8hi)__I);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_permutex2var_epi16 (__m128i __A, __mmask8 __U, __m128i __I,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_permutex2var_epi16 (__mmask8 __U, __m128i __A, __m128i __I,
+ __m128i __B)
{
- return (__m128i) __builtin_ia32_vpermt2varhi128_mask ((__v8hi) __I/* idx */,
- (__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_permutex2var_epi16(__A, __I, __B),
+ (__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_permutex2var_epi16 (__mmask8 __U, __m128i __A, __m128i __I,
- __m128i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_permutex2var_epi16(__m256i __A, __m256i __I, __m256i __B)
{
- return (__m128i) __builtin_ia32_vpermt2varhi128_maskz ((__v8hi) __I/* idx */,
- (__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_vpermi2varhi256((__v16hi)__A, (__v16hi)__I,
+ (__v16hi)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_permutex2var_epi16 (__m256i __A, __m256i __I, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I,
+ __m256i __B)
{
- return (__m256i) __builtin_ia32_vpermt2varhi256_mask ((__v16hi) __I/* idx */,
- (__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_permutex2var_epi16(__A, __I, __B),
+ (__v16hi)__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_permutex2var_epi16 (__m256i __A, __mmask16 __U,
- __m256i __I, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U,
+ __m256i __B)
{
- return (__m256i) __builtin_ia32_vpermt2varhi256_mask ((__v16hi) __I/* idx */,
- (__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_permutex2var_epi16(__A, __I, __B),
+ (__v16hi)__I);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A,
- __m256i __I, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A, __m256i __I,
+ __m256i __B)
{
- return (__m256i) __builtin_ia32_vpermt2varhi256_maskz ((__v16hi) __I/* idx */,
- (__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_permutex2var_epi16(__A, __I, __B),
+ (__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_maddubs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_maddubs_epi16(__X, __Y),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_maddubs_epi16(__mmask8 __U, __m128i __X, __m128i __Y) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_maddubs_epi16(__X, __Y),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_maddubs_epi16(__m256i __W, __mmask16 __U, __m256i __X,
__m256i __Y) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1389,402 +1375,400 @@ _mm256_mask_maddubs_epi16(__m256i __W, __mmask16 __U, __m256i __X,
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_maddubs_epi16(__mmask16 __U, __m256i __X, __m256i __Y) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_maddubs_epi16(__X, __Y),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_madd_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
(__v4si)_mm_madd_epi16(__A, __B),
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_madd_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
(__v4si)_mm_madd_epi16(__A, __B),
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_madd_epi16(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
(__v8si)_mm256_madd_epi16(__A, __B),
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_madd_epi16(__mmask8 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
(__v8si)_mm256_madd_epi16(__A, __B),
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtsepi16_epi8 (__m128i __A) {
return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A,
(__v16qi) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) {
return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A,
(__v16qi) __O,
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsepi16_epi8 (__mmask8 __M, __m128i __A) {
return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A,
(__v16qi) _mm_setzero_si128(),
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtsepi16_epi8 (__m256i __A) {
return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A,
(__v16qi) _mm_setzero_si128(),
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) {
return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A,
(__v16qi) __O,
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtsepi16_epi8 (__mmask16 __M, __m256i __A) {
return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A,
(__v16qi) _mm_setzero_si128(),
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtusepi16_epi8 (__m128i __A) {
return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A,
(__v16qi) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) {
return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A,
(__v16qi) __O,
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtusepi16_epi8 (__mmask8 __M, __m128i __A) {
return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A,
(__v16qi) _mm_setzero_si128(),
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtusepi16_epi8 (__m256i __A) {
return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A,
(__v16qi) _mm_setzero_si128(),
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) {
return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A,
(__v16qi) __O,
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtusepi16_epi8 (__mmask16 __M, __m256i __A) {
return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A,
(__v16qi) _mm_setzero_si128(),
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtepi16_epi8 (__m128i __A) {
-
- return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A,
- (__v16qi) _mm_setzero_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v8hi)__A, __v8qi),
+ (__v8qi){0, 0, 0, 0, 0, 0, 0, 0}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) {
return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A,
(__v16qi) __O,
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi16_epi8 (__mmask8 __M, __m128i __A) {
return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A,
(__v16qi) _mm_setzero_si128(),
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi16_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovwb128mem_mask ((__v16qi *) __P, (__v8hi) __A, __M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovswb128mem_mask ((__v16qi *) __P, (__v8hi) __A, __M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovuswb128mem_mask ((__v16qi *) __P, (__v8hi) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtepi16_epi8 (__m256i __A) {
- return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A,
- (__v16qi) _mm_setzero_si128(),
- (__mmask16) -1);
+ return (__m128i)__builtin_convertvector((__v16hi) __A, __v16qi);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) {
- return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A,
- (__v16qi) __O,
- __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm256_cvtepi16_epi8(__A),
+ (__v16qi)__O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi16_epi8 (__mmask16 __M, __m256i __A) {
- return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A,
- (__v16qi) _mm_setzero_si128(),
- __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm256_cvtepi16_epi8(__A),
+ (__v16qi)_mm_setzero_si128());
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A)
{
__builtin_ia32_pmovwb256mem_mask ((__v16qi *) __P, (__v16hi) __A, __M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A)
{
__builtin_ia32_pmovswb256mem_mask ((__v16qi *) __P, (__v16hi) __A, __M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
+static __inline__ void __DEFAULT_FN_ATTRS256
+_mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A)
{
__builtin_ia32_pmovuswb256mem_mask ((__v16qi*) __P, (__v16hi) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mulhrs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mulhrs_epi16(__X, __Y),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mulhrs_epi16(__mmask8 __U, __m128i __X, __m128i __Y) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mulhrs_epi16(__X, __Y),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mulhrs_epi16(__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mulhrs_epi16(__X, __Y),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mulhrs_epi16(__mmask16 __U, __m256i __X, __m256i __Y) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mulhrs_epi16(__X, __Y),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mulhi_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mulhi_epu16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mulhi_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mulhi_epu16(__A, __B),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mulhi_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mulhi_epu16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mulhi_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mulhi_epu16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mulhi_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mulhi_epi16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mulhi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_mulhi_epi16(__A, __B),
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mulhi_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mulhi_epi16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mulhi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_mulhi_epi16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpackhi_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_unpackhi_epi8(__A, __B),
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpackhi_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_unpackhi_epi8(__A, __B),
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpackhi_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_unpackhi_epi8(__A, __B),
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpackhi_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_unpackhi_epi8(__A, __B),
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpackhi_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_unpackhi_epi16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpackhi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_unpackhi_epi16(__A, __B),
(__v8hi) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpackhi_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_unpackhi_epi16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpackhi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_unpackhi_epi16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpacklo_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_unpacklo_epi8(__A, __B),
(__v16qi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpacklo_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
(__v16qi)_mm_unpacklo_epi8(__A, __B),
(__v16qi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpacklo_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_unpacklo_epi8(__A, __B),
(__v32qi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpacklo_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
(__v32qi)_mm256_unpacklo_epi8(__A, __B),
(__v32qi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpacklo_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_unpacklo_epi16(__A, __B),
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpacklo_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
(__v8hi)_mm_unpacklo_epi16(__A, __B),
(__v8hi) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpacklo_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_unpacklo_epi16(__A, __B),
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpacklo_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
(__v16hi)_mm256_unpacklo_epi16(__A, __B),
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1792,7 +1776,7 @@ _mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1800,7 +1784,7 @@ _mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1808,7 +1792,7 @@ _mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1817,7 +1801,7 @@ _mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A)
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1825,7 +1809,7 @@ _mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1833,7 +1817,7 @@ _mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1841,7 +1825,7 @@ _mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1850,55 +1834,55 @@ _mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A)
}
-#define _mm_mask_shufflehi_epi16(W, U, A, imm) __extension__ ({ \
+#define _mm_mask_shufflehi_epi16(W, U, A, imm) \
(__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
(__v8hi)_mm_shufflehi_epi16((A), (imm)), \
- (__v8hi)(__m128i)(W)); })
+ (__v8hi)(__m128i)(W))
-#define _mm_maskz_shufflehi_epi16(U, A, imm) __extension__ ({ \
+#define _mm_maskz_shufflehi_epi16(U, A, imm) \
(__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
(__v8hi)_mm_shufflehi_epi16((A), (imm)), \
- (__v8hi)_mm_setzero_hi()); })
+ (__v8hi)_mm_setzero_si128())
-#define _mm256_mask_shufflehi_epi16(W, U, A, imm) __extension__ ({ \
+#define _mm256_mask_shufflehi_epi16(W, U, A, imm) \
(__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
(__v16hi)_mm256_shufflehi_epi16((A), (imm)), \
- (__v16hi)(__m256i)(W)); })
+ (__v16hi)(__m256i)(W))
-#define _mm256_maskz_shufflehi_epi16(U, A, imm) __extension__ ({ \
+#define _mm256_maskz_shufflehi_epi16(U, A, imm) \
(__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
(__v16hi)_mm256_shufflehi_epi16((A), (imm)), \
- (__v16hi)_mm256_setzero_si256()); })
+ (__v16hi)_mm256_setzero_si256())
-#define _mm_mask_shufflelo_epi16(W, U, A, imm) __extension__ ({ \
+#define _mm_mask_shufflelo_epi16(W, U, A, imm) \
(__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
(__v8hi)_mm_shufflelo_epi16((A), (imm)), \
- (__v8hi)(__m128i)(W)); })
+ (__v8hi)(__m128i)(W))
-#define _mm_maskz_shufflelo_epi16(U, A, imm) __extension__ ({ \
+#define _mm_maskz_shufflelo_epi16(U, A, imm) \
(__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
(__v8hi)_mm_shufflelo_epi16((A), (imm)), \
- (__v8hi)_mm_setzero_hi()); })
+ (__v8hi)_mm_setzero_si128())
-#define _mm256_mask_shufflelo_epi16(W, U, A, imm) __extension__ ({ \
+#define _mm256_mask_shufflelo_epi16(W, U, A, imm) \
(__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
(__v16hi)_mm256_shufflelo_epi16((A), \
(imm)), \
- (__v16hi)(__m256i)(W)); })
+ (__v16hi)(__m256i)(W))
-#define _mm256_maskz_shufflelo_epi16(U, A, imm) __extension__ ({ \
+#define _mm256_maskz_shufflelo_epi16(U, A, imm) \
(__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
(__v16hi)_mm256_shufflelo_epi16((A), \
(imm)), \
- (__v16hi)_mm256_setzero_si256()); })
+ (__v16hi)_mm256_setzero_si256())
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sllv_epi16(__m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_psllv16hi((__v16hi)__A, (__v16hi)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sllv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1906,7 +1890,7 @@ _mm256_mask_sllv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sllv_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1914,13 +1898,13 @@ _mm256_maskz_sllv_epi16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_sllv_epi16(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psllv8hi((__v8hi)__A, (__v8hi)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sllv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1928,7 +1912,7 @@ _mm_mask_sllv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sllv_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1936,7 +1920,7 @@ _mm_maskz_sllv_epi16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sll_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1944,7 +1928,7 @@ _mm_mask_sll_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sll_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1952,7 +1936,7 @@ _mm_maskz_sll_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sll_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1960,7 +1944,7 @@ _mm256_mask_sll_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sll_epi16(__mmask16 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1968,7 +1952,7 @@ _mm256_maskz_sll_epi16(__mmask16 __U, __m256i __A, __m128i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1976,7 +1960,7 @@ _mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -1984,7 +1968,7 @@ _mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -1992,7 +1976,7 @@ _mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2000,13 +1984,13 @@ _mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A, int __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srlv_epi16(__m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_psrlv16hi((__v16hi)__A, (__v16hi)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srlv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2014,7 +1998,7 @@ _mm256_mask_srlv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srlv_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2022,13 +2006,13 @@ _mm256_maskz_srlv_epi16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srlv_epi16(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psrlv8hi((__v8hi)__A, (__v8hi)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srlv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2036,7 +2020,7 @@ _mm_mask_srlv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srlv_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2044,13 +2028,13 @@ _mm_maskz_srlv_epi16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srav_epi16(__m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_psrav16hi((__v16hi)__A, (__v16hi)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srav_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2058,7 +2042,7 @@ _mm256_mask_srav_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srav_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2066,13 +2050,13 @@ _mm256_maskz_srav_epi16(__mmask16 __U, __m256i __A, __m256i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srav_epi16(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psrav8hi((__v8hi)__A, (__v8hi)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srav_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2080,7 +2064,7 @@ _mm_mask_srav_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srav_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2088,7 +2072,7 @@ _mm_maskz_srav_epi16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sra_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2096,7 +2080,7 @@ _mm_mask_sra_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sra_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2104,7 +2088,7 @@ _mm_maskz_sra_epi16(__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sra_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2112,7 +2096,7 @@ _mm256_mask_sra_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sra_epi16(__mmask16 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2120,7 +2104,7 @@ _mm256_maskz_sra_epi16(__mmask16 __U, __m256i __A, __m128i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2128,7 +2112,7 @@ _mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srai_epi16(__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2136,7 +2120,7 @@ _mm_maskz_srai_epi16(__mmask8 __U, __m128i __A, int __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2144,7 +2128,7 @@ _mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2152,7 +2136,7 @@ _mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A, int __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srl_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2160,7 +2144,7 @@ _mm_mask_srl_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srl_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2168,7 +2152,7 @@ _mm_maskz_srl_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srl_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2176,7 +2160,7 @@ _mm256_mask_srl_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srl_epi16(__mmask16 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2184,7 +2168,7 @@ _mm256_maskz_srl_epi16(__mmask16 __U, __m256i __A, __m128i __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2192,7 +2176,7 @@ _mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v8hi)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srli_epi16 (__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
@@ -2200,7 +2184,7 @@ _mm_maskz_srli_epi16 (__mmask8 __U, __m128i __A, int __B)
(__v8hi)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2208,7 +2192,7 @@ _mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
(__v16hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
@@ -2216,7 +2200,7 @@ _mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A, int __B)
(__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mov_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectw_128 ((__mmask8) __U,
@@ -2224,15 +2208,15 @@ _mm_mask_mov_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
(__v8hi) __W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mov_epi16 (__mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectw_128 ((__mmask8) __U,
(__v8hi) __A,
- (__v8hi) _mm_setzero_hi ());
+ (__v8hi) _mm_setzero_si128 ());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mov_epi16 (__m256i __W, __mmask16 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectw_256 ((__mmask16) __U,
@@ -2240,7 +2224,7 @@ _mm256_mask_mov_epi16 (__m256i __W, __mmask16 __U, __m256i __A)
(__v16hi) __W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_epi16 (__mmask16 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectw_256 ((__mmask16) __U,
@@ -2248,7 +2232,7 @@ _mm256_maskz_mov_epi16 (__mmask16 __U, __m256i __A)
(__v16hi) _mm256_setzero_si256 ());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mov_epi8 (__m128i __W, __mmask16 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectb_128 ((__mmask16) __U,
@@ -2256,15 +2240,15 @@ _mm_mask_mov_epi8 (__m128i __W, __mmask16 __U, __m128i __A)
(__v16qi) __W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mov_epi8 (__mmask16 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectb_128 ((__mmask16) __U,
(__v16qi) __A,
- (__v16qi) _mm_setzero_hi ());
+ (__v16qi) _mm_setzero_si128 ());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mov_epi8 (__m256i __W, __mmask32 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectb_256 ((__mmask32) __U,
@@ -2272,7 +2256,7 @@ _mm256_mask_mov_epi8 (__m256i __W, __mmask32 __U, __m256i __A)
(__v32qi) __W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_epi8 (__mmask32 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectb_256 ((__mmask32) __U,
@@ -2281,7 +2265,7 @@ _mm256_maskz_mov_epi8 (__mmask32 __U, __m256i __A)
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_set1_epi8 (__m128i __O, __mmask16 __M, char __A)
{
return (__m128i) __builtin_ia32_selectb_128(__M,
@@ -2289,7 +2273,7 @@ _mm_mask_set1_epi8 (__m128i __O, __mmask16 __M, char __A)
(__v16qi) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_set1_epi8 (__mmask16 __M, char __A)
{
return (__m128i) __builtin_ia32_selectb_128(__M,
@@ -2297,7 +2281,7 @@ _mm_maskz_set1_epi8 (__mmask16 __M, char __A)
(__v16qi) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_set1_epi8 (__m256i __O, __mmask32 __M, char __A)
{
return (__m256i) __builtin_ia32_selectb_256(__M,
@@ -2305,7 +2289,7 @@ _mm256_mask_set1_epi8 (__m256i __O, __mmask32 __M, char __A)
(__v32qi) __O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_set1_epi8 (__mmask32 __M, char __A)
{
return (__m256i) __builtin_ia32_selectb_256(__M,
@@ -2313,7 +2297,7 @@ _mm256_maskz_set1_epi8 (__mmask32 __M, char __A)
(__v32qi) _mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi16 (__m128i __W, __mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddquhi128_mask ((__v8hi *) __P,
@@ -2321,16 +2305,16 @@ _mm_mask_loadu_epi16 (__m128i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_loadu_epi16 (__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddquhi128_mask ((__v8hi *) __P,
(__v8hi)
- _mm_setzero_hi (),
+ _mm_setzero_si128 (),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi16 (__m256i __W, __mmask16 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddquhi256_mask ((__v16hi *) __P,
@@ -2338,7 +2322,7 @@ _mm256_mask_loadu_epi16 (__m256i __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_loadu_epi16 (__mmask16 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddquhi256_mask ((__v16hi *) __P,
@@ -2347,7 +2331,7 @@ _mm256_maskz_loadu_epi16 (__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi8 (__m128i __W, __mmask16 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddquqi128_mask ((__v16qi *) __P,
@@ -2355,7 +2339,7 @@ _mm_mask_loadu_epi8 (__m128i __W, __mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_loadu_epi8 (__mmask16 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddquqi128_mask ((__v16qi *) __P,
@@ -2364,7 +2348,7 @@ _mm_maskz_loadu_epi8 (__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi8 (__m256i __W, __mmask32 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddquqi256_mask ((__v32qi *) __P,
@@ -2372,7 +2356,7 @@ _mm256_mask_loadu_epi8 (__m256i __W, __mmask32 __U, void const *__P)
(__mmask32) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_loadu_epi8 (__mmask32 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddquqi256_mask ((__v32qi *) __P,
@@ -2380,7 +2364,7 @@ _mm256_maskz_loadu_epi8 (__mmask32 __U, void const *__P)
_mm256_setzero_si256 (),
(__mmask32) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A)
{
__builtin_ia32_storedquhi128_mask ((__v8hi *) __P,
@@ -2388,7 +2372,7 @@ _mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A)
{
__builtin_ia32_storedquhi256_mask ((__v16hi *) __P,
@@ -2396,7 +2380,7 @@ _mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A)
(__mmask16) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A)
{
__builtin_ia32_storedquqi128_mask ((__v16qi *) __P,
@@ -2404,7 +2388,7 @@ _mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A)
(__mmask16) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A)
{
__builtin_ia32_storedquqi256_mask ((__v32qi *) __P,
@@ -2412,162 +2396,162 @@ _mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A)
(__mmask32) __U);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_test_epi8_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpneq_epi8_mask (_mm_and_si128(__A, __B), _mm_setzero_hi());
+ return _mm_cmpneq_epi8_mask (_mm_and_si128(__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_mask_test_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpneq_epi8_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_hi());
+ _mm_setzero_si128());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_test_epi8_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpneq_epi8_mask (_mm256_and_si256(__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_mask_test_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpneq_epi8_mask (__U, _mm256_and_si256(__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_test_epi16_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpneq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_hi());
+ return _mm_cmpneq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_mask_test_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpneq_epi16_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_hi());
+ _mm_setzero_si128());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS256
_mm256_test_epi16_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpneq_epi16_mask (_mm256_and_si256 (__A, __B),
_mm256_setzero_si256 ());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS256
_mm256_mask_test_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpneq_epi16_mask (__U, _mm256_and_si256(__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_testn_epi8_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpeq_epi8_mask (_mm_and_si128 (__A, __B), _mm_setzero_hi());
+ return _mm_cmpeq_epi8_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_mask_testn_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpeq_epi8_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_hi());
+ _mm_setzero_si128());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_testn_epi8_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpeq_epi8_mask (_mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_mask_testn_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpeq_epi8_mask (__U, _mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_testn_epi16_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpeq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_hi());
+ return _mm_cmpeq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_mask_testn_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return _mm_mask_cmpeq_epi16_mask (__U, _mm_and_si128(__A, __B), _mm_setzero_hi());
+ return _mm_mask_cmpeq_epi16_mask (__U, _mm_and_si128(__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS256
_mm256_testn_epi16_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpeq_epi16_mask (_mm256_and_si256(__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS256
_mm256_mask_testn_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpeq_epi16_mask (__U, _mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
_mm_movepi8_mask (__m128i __A)
{
return (__mmask16) __builtin_ia32_cvtb2mask128 ((__v16qi) __A);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
_mm256_movepi8_mask (__m256i __A)
{
return (__mmask32) __builtin_ia32_cvtb2mask256 ((__v32qi) __A);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_movepi16_mask (__m128i __A)
{
return (__mmask8) __builtin_ia32_cvtw2mask128 ((__v8hi) __A);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS256
_mm256_movepi16_mask (__m256i __A)
{
return (__mmask16) __builtin_ia32_cvtw2mask256 ((__v16hi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_movm_epi8 (__mmask16 __A)
{
return (__m128i) __builtin_ia32_cvtmask2b128 (__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_movm_epi8 (__mmask32 __A)
{
return (__m256i) __builtin_ia32_cvtmask2b256 (__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_movm_epi16 (__mmask8 __A)
{
return (__m128i) __builtin_ia32_cvtmask2w128 (__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_movm_epi16 (__mmask16 __A)
{
return (__m256i) __builtin_ia32_cvtmask2w256 (__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_broadcastb_epi8 (__m128i __O, __mmask16 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectb_128(__M,
@@ -2575,7 +2559,7 @@ _mm_mask_broadcastb_epi8 (__m128i __O, __mmask16 __M, __m128i __A)
(__v16qi) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_broadcastb_epi8 (__mmask16 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectb_128(__M,
@@ -2583,7 +2567,7 @@ _mm_maskz_broadcastb_epi8 (__mmask16 __M, __m128i __A)
(__v16qi) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcastb_epi8 (__m256i __O, __mmask32 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectb_256(__M,
@@ -2591,7 +2575,7 @@ _mm256_mask_broadcastb_epi8 (__m256i __O, __mmask32 __M, __m128i __A)
(__v32qi) __O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcastb_epi8 (__mmask32 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectb_256(__M,
@@ -2599,7 +2583,7 @@ _mm256_maskz_broadcastb_epi8 (__mmask32 __M, __m128i __A)
(__v32qi) _mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_broadcastw_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128(__M,
@@ -2607,7 +2591,7 @@ _mm_mask_broadcastw_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
(__v8hi) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_broadcastw_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectw_128(__M,
@@ -2615,7 +2599,7 @@ _mm_maskz_broadcastw_epi16 (__mmask8 __M, __m128i __A)
(__v8hi) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcastw_epi16 (__m256i __O, __mmask16 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectw_256(__M,
@@ -2623,7 +2607,7 @@ _mm256_mask_broadcastw_epi16 (__m256i __O, __mmask16 __M, __m128i __A)
(__v16hi) __O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcastw_epi16 (__mmask16 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectw_256(__M,
@@ -2631,7 +2615,7 @@ _mm256_maskz_broadcastw_epi16 (__mmask16 __M, __m128i __A)
(__v16hi) _mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_set1_epi16 (__m256i __O, __mmask16 __M, short __A)
{
return (__m256i) __builtin_ia32_selectw_256 (__M,
@@ -2639,7 +2623,7 @@ _mm256_mask_set1_epi16 (__m256i __O, __mmask16 __M, short __A)
(__v16hi) __O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_set1_epi16 (__mmask16 __M, short __A)
{
return (__m256i) __builtin_ia32_selectw_256(__M,
@@ -2647,7 +2631,7 @@ _mm256_maskz_set1_epi16 (__mmask16 __M, short __A)
(__v16hi) _mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_set1_epi16 (__m128i __O, __mmask8 __M, short __A)
{
return (__m128i) __builtin_ia32_selectw_128(__M,
@@ -2655,7 +2639,7 @@ _mm_mask_set1_epi16 (__m128i __O, __mmask8 __M, short __A)
(__v8hi) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_set1_epi16 (__mmask8 __M, short __A)
{
return (__m128i) __builtin_ia32_selectw_128(__M,
@@ -2663,119 +2647,102 @@ _mm_maskz_set1_epi16 (__mmask8 __M, short __A)
(__v8hi) _mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_permutexvar_epi16 (__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_permvarhi128_mask ((__v8hi) __B,
- (__v8hi) __A,
- (__v8hi) _mm_undefined_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_permvarhi128((__v8hi) __B, (__v8hi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_permutexvar_epi16 (__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_permvarhi128_mask ((__v8hi) __B,
- (__v8hi) __A,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_permutexvar_epi16(__A, __B),
+ (__v8hi) _mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_permutexvar_epi16 (__m128i __W, __mmask8 __M, __m128i __A,
__m128i __B)
{
- return (__m128i) __builtin_ia32_permvarhi128_mask ((__v8hi) __B,
- (__v8hi) __A,
- (__v8hi) __W,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_permutexvar_epi16(__A, __B),
+ (__v8hi)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_permutexvar_epi16 (__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_permvarhi256_mask ((__v16hi) __B,
- (__v16hi) __A,
- (__v16hi) _mm256_undefined_si256 (),
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_permvarhi256((__v16hi) __B, (__v16hi) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_permutexvar_epi16 (__mmask16 __M, __m256i __A,
__m256i __B)
{
- return (__m256i) __builtin_ia32_permvarhi256_mask ((__v16hi) __B,
- (__v16hi) __A,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_permutexvar_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_permutexvar_epi16 (__m256i __W, __mmask16 __M, __m256i __A,
__m256i __B)
{
- return (__m256i) __builtin_ia32_permvarhi256_mask ((__v16hi) __B,
- (__v16hi) __A,
- (__v16hi) __W,
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_permutexvar_epi16(__A, __B),
+ (__v16hi)__W);
}
-#define _mm_mask_alignr_epi8(W, U, A, B, N) __extension__ ({ \
+#define _mm_mask_alignr_epi8(W, U, A, B, N) \
(__m128i)__builtin_ia32_selectb_128((__mmask16)(U), \
(__v16qi)_mm_alignr_epi8((A), (B), (int)(N)), \
- (__v16qi)(__m128i)(W)); })
+ (__v16qi)(__m128i)(W))
-#define _mm_maskz_alignr_epi8(U, A, B, N) __extension__ ({ \
+#define _mm_maskz_alignr_epi8(U, A, B, N) \
(__m128i)__builtin_ia32_selectb_128((__mmask16)(U), \
(__v16qi)_mm_alignr_epi8((A), (B), (int)(N)), \
- (__v16qi)_mm_setzero_si128()); })
+ (__v16qi)_mm_setzero_si128())
-#define _mm256_mask_alignr_epi8(W, U, A, B, N) __extension__ ({ \
+#define _mm256_mask_alignr_epi8(W, U, A, B, N) \
(__m256i)__builtin_ia32_selectb_256((__mmask32)(U), \
(__v32qi)_mm256_alignr_epi8((A), (B), (int)(N)), \
- (__v32qi)(__m256i)(W)); })
+ (__v32qi)(__m256i)(W))
-#define _mm256_maskz_alignr_epi8(U, A, B, N) __extension__ ({ \
+#define _mm256_maskz_alignr_epi8(U, A, B, N) \
(__m256i)__builtin_ia32_selectb_256((__mmask32)(U), \
(__v32qi)_mm256_alignr_epi8((A), (B), (int)(N)), \
- (__v32qi)_mm256_setzero_si256()); })
-
-#define _mm_dbsad_epu8(A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_dbpsadbw128_mask((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (int)(imm), \
- (__v8hi)_mm_setzero_hi(), \
- (__mmask8)-1); })
-
-#define _mm_mask_dbsad_epu8(W, U, A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_dbpsadbw128_mask((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (int)(imm), \
- (__v8hi)(__m128i)(W), \
- (__mmask8)(U)); })
-
-#define _mm_maskz_dbsad_epu8(U, A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_dbpsadbw128_mask((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (int)(imm), \
- (__v8hi)_mm_setzero_si128(), \
- (__mmask8)(U)); })
-
-#define _mm256_dbsad_epu8(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_dbpsadbw256_mask((__v32qi)(__m256i)(A), \
- (__v32qi)(__m256i)(B), (int)(imm), \
- (__v16hi)_mm256_setzero_si256(), \
- (__mmask16)-1); })
-
-#define _mm256_mask_dbsad_epu8(W, U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_dbpsadbw256_mask((__v32qi)(__m256i)(A), \
- (__v32qi)(__m256i)(B), (int)(imm), \
- (__v16hi)(__m256i)(W), \
- (__mmask16)(U)); })
-
-#define _mm256_maskz_dbsad_epu8(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_dbpsadbw256_mask((__v32qi)(__m256i)(A), \
- (__v32qi)(__m256i)(B), (int)(imm), \
- (__v16hi)_mm256_setzero_si256(), \
- (__mmask16)(U)); })
-
-#undef __DEFAULT_FN_ATTRS
+ (__v32qi)_mm256_setzero_si256())
+
+#define _mm_dbsad_epu8(A, B, imm) \
+ (__m128i)__builtin_ia32_dbpsadbw128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(imm))
+
+#define _mm_mask_dbsad_epu8(W, U, A, B, imm) \
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_dbsad_epu8((A), (B), (imm)), \
+ (__v8hi)(__m128i)(W))
+
+#define _mm_maskz_dbsad_epu8(U, A, B, imm) \
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_dbsad_epu8((A), (B), (imm)), \
+ (__v8hi)_mm_setzero_si128())
+
+#define _mm256_dbsad_epu8(A, B, imm) \
+ (__m256i)__builtin_ia32_dbpsadbw256((__v32qi)(__m256i)(A), \
+ (__v32qi)(__m256i)(B), (int)(imm))
+
+#define _mm256_mask_dbsad_epu8(W, U, A, B, imm) \
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_dbsad_epu8((A), (B), (imm)), \
+ (__v16hi)(__m256i)(W))
+
+#define _mm256_maskz_dbsad_epu8(U, A, B, imm) \
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_dbsad_epu8((A), (B), (imm)), \
+ (__v16hi)_mm256_setzero_si256())
+
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif /* __AVX512VLBWINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h
index 8f1cd25f0b50..903a7c25493f 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h
@@ -1,4 +1,4 @@
-/*===---- avx512vlcdintrin.h - AVX512VL and AVX512CD intrinsics ---------------------------===
+/*===---- avx512vlcdintrin.h - AVX512VL and AVX512CD 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
@@ -28,35 +28,36 @@
#define __AVX512VLCDINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512cd")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512cd"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512cd"), __min_vector_width__(256)))
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcastmb_epi64 (__mmask8 __A)
-{
+{
return (__m128i) _mm_set1_epi64x((long long) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastmb_epi64 (__mmask8 __A)
{
return (__m256i) _mm256_set1_epi64x((long long)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcastmw_epi32 (__mmask16 __A)
{
return (__m128i) _mm_set1_epi32((int)__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcastmw_epi32 (__mmask16 __A)
{
return (__m256i) _mm256_set1_epi32((int)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_conflict_epi64 (__m128i __A)
{
return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A,
@@ -64,7 +65,7 @@ _mm_conflict_epi64 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_conflict_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A,
@@ -72,16 +73,16 @@ _mm_mask_conflict_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_conflict_epi64 (__mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A,
(__v2di)
- _mm_setzero_di (),
+ _mm_setzero_si128 (),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_conflict_epi64 (__m256i __A)
{
return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A,
@@ -89,7 +90,7 @@ _mm256_conflict_epi64 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_conflict_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A,
@@ -97,7 +98,7 @@ _mm256_mask_conflict_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_conflict_epi64 (__mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A,
@@ -105,7 +106,7 @@ _mm256_maskz_conflict_epi64 (__mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_conflict_epi32 (__m128i __A)
{
return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A,
@@ -113,7 +114,7 @@ _mm_conflict_epi32 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_conflict_epi32 (__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A,
@@ -121,7 +122,7 @@ _mm_mask_conflict_epi32 (__m128i __W, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_conflict_epi32 (__mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A,
@@ -129,7 +130,7 @@ _mm_maskz_conflict_epi32 (__mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_conflict_epi32 (__m256i __A)
{
return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A,
@@ -137,7 +138,7 @@ _mm256_conflict_epi32 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_conflict_epi32 (__m256i __W, __mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A,
@@ -145,7 +146,7 @@ _mm256_mask_conflict_epi32 (__m256i __W, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_conflict_epi32 (__mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A,
@@ -154,110 +155,95 @@ _mm256_maskz_conflict_epi32 (__mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_lzcnt_epi32 (__m128i __A)
{
- return (__m128i) __builtin_ia32_vplzcntd_128_mask ((__v4si) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i) __builtin_ia32_vplzcntd_128 ((__v4si) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_lzcnt_epi32 (__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_vplzcntd_128_mask ((__v4si) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_lzcnt_epi32(__A),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_lzcnt_epi32 (__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_vplzcntd_128_mask ((__v4si) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_lzcnt_epi32(__A),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_lzcnt_epi32 (__m256i __A)
{
- return (__m256i) __builtin_ia32_vplzcntd_256_mask ((__v8si) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i) __builtin_ia32_vplzcntd_256 ((__v8si) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_lzcnt_epi32 (__m256i __W, __mmask8 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_vplzcntd_256_mask ((__v8si) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_lzcnt_epi32(__A),
+ (__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_lzcnt_epi32 (__mmask8 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_vplzcntd_256_mask ((__v8si) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_lzcnt_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_lzcnt_epi64 (__m128i __A)
{
- return (__m128i) __builtin_ia32_vplzcntq_128_mask ((__v2di) __A,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) -1);
+ return (__m128i) __builtin_ia32_vplzcntq_128 ((__v2di) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_lzcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_vplzcntq_128_mask ((__v2di) __A,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_lzcnt_epi64(__A),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_lzcnt_epi64 (__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_vplzcntq_128_mask ((__v2di) __A,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_lzcnt_epi64(__A),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_lzcnt_epi64 (__m256i __A)
{
- return (__m256i) __builtin_ia32_vplzcntq_256_mask ((__v4di) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i) __builtin_ia32_vplzcntq_256 ((__v4di) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_lzcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_vplzcntq_256_mask ((__v4di) __A,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_lzcnt_epi64(__A),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_lzcnt_epi64 (__mmask8 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_vplzcntq_256_mask ((__v4di) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_lzcnt_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif /* __AVX512VLCDINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
index d80df9eaffea..9d13846e8964 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
@@ -29,961 +29,953 @@
#define __AVX512VLDQINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq"), __min_vector_width__(256)))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mullo_epi64 (__m256i __A, __m256i __B) {
return (__m256i) ((__v4du) __A * (__v4du) __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mullo_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
(__v4di)_mm256_mullo_epi64(__A, __B),
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mullo_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
(__v4di)_mm256_mullo_epi64(__A, __B),
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mullo_epi64 (__m128i __A, __m128i __B) {
return (__m128i) ((__v2du) __A * (__v2du) __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mullo_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_mullo_epi64(__A, __B),
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mullo_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_mullo_epi64(__A, __B),
(__v2di)_mm_setzero_si128());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_andnot_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_andnot_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_andnot_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_andnot_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_andnot_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_andnot_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_andnot_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_andnot_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_andnot_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_andnot_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_andnot_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_andnot_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_andnot_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_andnot_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_andnot_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_andnot_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_and_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_and_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_and_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_and_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_and_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_and_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_and_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_and_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_and_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_and_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_and_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_and_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_and_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_and_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_and_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_and_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_xor_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_xor_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_xor_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_xor_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_xor_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_xor_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_xor_pd (__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_xor_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_xor_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_xor_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_xor_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_xor_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_xor_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_xor_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_xor_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_xor_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_or_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_or_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_or_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_or_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_or_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_or_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_or_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_or_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_or_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_or_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_or_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_or_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_or_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_or_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_or_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_or_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtpd_epi64 (__m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtpd_epi64 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtpd_epi64 (__m256d __A) {
return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtpd_epi64 (__mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtpd_epu64 (__m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtpd_epu64 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtpd_epu64 (__m256d __A) {
return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtpd_epu64 (__mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtps_epi64 (__m128 __A) {
return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtps_epi64 (__m128 __A) {
return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtps_epu64 (__m128 __A) {
return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtps_epu64 (__m128 __A) {
return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_cvtepi64_pd (__m128i __A) {
- return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A,
- (__v2df) _mm_setzero_pd(),
- (__mmask8) -1);
+ return (__m128d)__builtin_convertvector((__v2di)__A, __v2df);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_pd (__m128d __W, __mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A,
- (__v2df) __W,
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_cvtepi64_pd(__A),
+ (__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi64_pd (__mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A,
- (__v2df) _mm_setzero_pd(),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_cvtepi64_pd(__A),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_cvtepi64_pd (__m256i __A) {
- return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A,
- (__v4df) _mm256_setzero_pd(),
- (__mmask8) -1);
+ return (__m256d)__builtin_convertvector((__v4di)__A, __v4df);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_pd (__m256d __W, __mmask8 __U, __m256i __A) {
- return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A,
- (__v4df) __W,
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_cvtepi64_pd(__A),
+ (__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi64_pd (__mmask8 __U, __m256i __A) {
- return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A,
- (__v4df) _mm256_setzero_pd(),
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_cvtepi64_pd(__A),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_cvtepi64_ps (__m128i __A) {
return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m128i __A) {
return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi64_ps (__mmask8 __U, __m128i __A) {
return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_cvtepi64_ps (__m256i __A) {
return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m256i __A) {
return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi64_ps (__mmask8 __U, __m256i __A) {
return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvttpd_epi64 (__m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttpd_epi64 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvttpd_epi64 (__m256d __A) {
return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttpd_epi64 (__mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvttpd_epu64 (__m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttpd_epu64 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvttpd_epu64 (__m256d __A) {
return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttpd_epu64 (__mmask8 __U, __m256d __A) {
return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvttps_epi64 (__m128 __A) {
return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvttps_epi64 (__m128 __A) {
return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvttps_epu64 (__m128 __A) {
return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvttps_epu64 (__m128 __A) {
return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) {
return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A,
(__v4di) _mm256_setzero_si256(),
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_cvtepu64_pd (__m128i __A) {
- return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A,
- (__v2df) _mm_setzero_pd(),
- (__mmask8) -1);
+ return (__m128d)__builtin_convertvector((__v2du)__A, __v2df);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_cvtepu64_pd (__m128d __W, __mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A,
- (__v2df) __W,
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_cvtepu64_pd(__A),
+ (__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepu64_pd (__mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A,
- (__v2df) _mm_setzero_pd(),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_cvtepu64_pd(__A),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_cvtepu64_pd (__m256i __A) {
- return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A,
- (__v4df) _mm256_setzero_pd(),
- (__mmask8) -1);
+ return (__m256d)__builtin_convertvector((__v4du)__A, __v4df);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepu64_pd (__m256d __W, __mmask8 __U, __m256i __A) {
- return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A,
- (__v4df) __W,
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_cvtepu64_pd(__A),
+ (__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepu64_pd (__mmask8 __U, __m256i __A) {
- return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A,
- (__v4df) _mm256_setzero_pd(),
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_cvtepu64_pd(__A),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_cvtepu64_ps (__m128i __A) {
return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m128i __A) {
return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepu64_ps (__mmask8 __U, __m128i __A) {
return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_cvtepu64_ps (__m256i __A) {
return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m256i __A) {
return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepu64_ps (__mmask8 __U, __m256i __A) {
return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A,
(__v4sf) _mm_setzero_ps(),
(__mmask8) __U);
}
-#define _mm_range_pd(A, B, C) __extension__ ({ \
+#define _mm_range_pd(A, B, C) \
(__m128d)__builtin_ia32_rangepd128_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), (int)(C), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_range_pd(W, U, A, B, C) __extension__ ({ \
+#define _mm_mask_range_pd(W, U, A, B, C) \
(__m128d)__builtin_ia32_rangepd128_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), (int)(C), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_range_pd(U, A, B, C) __extension__ ({ \
+#define _mm_maskz_range_pd(U, A, B, C) \
(__m128d)__builtin_ia32_rangepd128_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), (int)(C), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_range_pd(A, B, C) __extension__ ({ \
+#define _mm256_range_pd(A, B, C) \
(__m256d)__builtin_ia32_rangepd256_mask((__v4df)(__m256d)(A), \
(__v4df)(__m256d)(B), (int)(C), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_range_pd(W, U, A, B, C) __extension__ ({ \
+#define _mm256_mask_range_pd(W, U, A, B, C) \
(__m256d)__builtin_ia32_rangepd256_mask((__v4df)(__m256d)(A), \
(__v4df)(__m256d)(B), (int)(C), \
(__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_range_pd(U, A, B, C) __extension__ ({ \
+#define _mm256_maskz_range_pd(U, A, B, C) \
(__m256d)__builtin_ia32_rangepd256_mask((__v4df)(__m256d)(A), \
(__v4df)(__m256d)(B), (int)(C), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_range_ps(A, B, C) __extension__ ({ \
+#define _mm_range_ps(A, B, C) \
(__m128)__builtin_ia32_rangeps128_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), (int)(C), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_range_ps(W, U, A, B, C) __extension__ ({ \
+#define _mm_mask_range_ps(W, U, A, B, C) \
(__m128)__builtin_ia32_rangeps128_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), (int)(C), \
- (__v4sf)(__m128)(W), (__mmask8)(U)); })
+ (__v4sf)(__m128)(W), (__mmask8)(U))
-#define _mm_maskz_range_ps(U, A, B, C) __extension__ ({ \
+#define _mm_maskz_range_ps(U, A, B, C) \
(__m128)__builtin_ia32_rangeps128_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), (int)(C), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_range_ps(A, B, C) __extension__ ({ \
+#define _mm256_range_ps(A, B, C) \
(__m256)__builtin_ia32_rangeps256_mask((__v8sf)(__m256)(A), \
(__v8sf)(__m256)(B), (int)(C), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_range_ps(W, U, A, B, C) __extension__ ({ \
+#define _mm256_mask_range_ps(W, U, A, B, C) \
(__m256)__builtin_ia32_rangeps256_mask((__v8sf)(__m256)(A), \
(__v8sf)(__m256)(B), (int)(C), \
- (__v8sf)(__m256)(W), (__mmask8)(U)); })
+ (__v8sf)(__m256)(W), (__mmask8)(U))
-#define _mm256_maskz_range_ps(U, A, B, C) __extension__ ({ \
+#define _mm256_maskz_range_ps(U, A, B, C) \
(__m256)__builtin_ia32_rangeps256_mask((__v8sf)(__m256)(A), \
(__v8sf)(__m256)(B), (int)(C), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_reduce_pd(A, B) __extension__ ({ \
+#define _mm_reduce_pd(A, B) \
(__m128d)__builtin_ia32_reducepd128_mask((__v2df)(__m128d)(A), (int)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_reduce_pd(W, U, A, B) __extension__ ({ \
+#define _mm_mask_reduce_pd(W, U, A, B) \
(__m128d)__builtin_ia32_reducepd128_mask((__v2df)(__m128d)(A), (int)(B), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_reduce_pd(U, A, B) __extension__ ({ \
+#define _mm_maskz_reduce_pd(U, A, B) \
(__m128d)__builtin_ia32_reducepd128_mask((__v2df)(__m128d)(A), (int)(B), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_reduce_pd(A, B) __extension__ ({ \
+#define _mm256_reduce_pd(A, B) \
(__m256d)__builtin_ia32_reducepd256_mask((__v4df)(__m256d)(A), (int)(B), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_reduce_pd(W, U, A, B) __extension__ ({ \
+#define _mm256_mask_reduce_pd(W, U, A, B) \
(__m256d)__builtin_ia32_reducepd256_mask((__v4df)(__m256d)(A), (int)(B), \
(__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_reduce_pd(U, A, B) __extension__ ({ \
+#define _mm256_maskz_reduce_pd(U, A, B) \
(__m256d)__builtin_ia32_reducepd256_mask((__v4df)(__m256d)(A), (int)(B), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_reduce_ps(A, B) __extension__ ({ \
+#define _mm_reduce_ps(A, B) \
(__m128)__builtin_ia32_reduceps128_mask((__v4sf)(__m128)(A), (int)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_reduce_ps(W, U, A, B) __extension__ ({ \
+#define _mm_mask_reduce_ps(W, U, A, B) \
(__m128)__builtin_ia32_reduceps128_mask((__v4sf)(__m128)(A), (int)(B), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_reduce_ps(U, A, B) __extension__ ({ \
+#define _mm_maskz_reduce_ps(U, A, B) \
(__m128)__builtin_ia32_reduceps128_mask((__v4sf)(__m128)(A), (int)(B), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_reduce_ps(A, B) __extension__ ({ \
+#define _mm256_reduce_ps(A, B) \
(__m256)__builtin_ia32_reduceps256_mask((__v8sf)(__m256)(A), (int)(B), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_reduce_ps(W, U, A, B) __extension__ ({ \
+#define _mm256_mask_reduce_ps(W, U, A, B) \
(__m256)__builtin_ia32_reduceps256_mask((__v8sf)(__m256)(A), (int)(B), \
(__v8sf)(__m256)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_reduce_ps(U, A, B) __extension__ ({ \
+#define _mm256_maskz_reduce_ps(U, A, B) \
(__m256)__builtin_ia32_reduceps256_mask((__v8sf)(__m256)(A), (int)(B), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_movepi32_mask (__m128i __A)
{
return (__mmask8) __builtin_ia32_cvtd2mask128 ((__v4si) __A);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_movepi32_mask (__m256i __A)
{
return (__mmask8) __builtin_ia32_cvtd2mask256 ((__v8si) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_movm_epi32 (__mmask8 __A)
{
return (__m128i) __builtin_ia32_cvtmask2d128 (__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_movm_epi32 (__mmask8 __A)
{
return (__m256i) __builtin_ia32_cvtmask2d256 (__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_movm_epi64 (__mmask8 __A)
{
return (__m128i) __builtin_ia32_cvtmask2q128 (__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_movm_epi64 (__mmask8 __A)
{
return (__m256i) __builtin_ia32_cvtmask2q256 (__A);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_movepi64_mask (__m128i __A)
{
return (__mmask8) __builtin_ia32_cvtq2mask128 ((__v2di) __A);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_movepi64_mask (__m256i __A)
{
return (__mmask8) __builtin_ia32_cvtq2mask256 ((__v4di) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_broadcast_f32x2 (__m128 __A)
{
- return (__m256)__builtin_shufflevector((__v4sf)__A,
- (__v4sf)_mm_undefined_ps(),
+ return (__m256)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A,
0, 1, 0, 1, 0, 1, 0, 1);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_broadcast_f32x2 (__m256 __O, __mmask8 __M, __m128 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__M,
@@ -991,7 +983,7 @@ _mm256_mask_broadcast_f32x2 (__m256 __O, __mmask8 __M, __m128 __A)
(__v8sf)__O);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcast_f32x2 (__mmask8 __M, __m128 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__M,
@@ -999,14 +991,14 @@ _mm256_maskz_broadcast_f32x2 (__mmask8 __M, __m128 __A)
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_broadcast_f64x2(__m128d __A)
{
return (__m256d)__builtin_shufflevector((__v2df)__A, (__v2df)__A,
0, 1, 0, 1);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_broadcast_f64x2(__m256d __O, __mmask8 __M, __m128d __A)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__M,
@@ -1014,7 +1006,7 @@ _mm256_mask_broadcast_f64x2(__m256d __O, __mmask8 __M, __m128d __A)
(__v4df)__O);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__M,
@@ -1022,15 +1014,14 @@ _mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A)
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_broadcast_i32x2 (__m128i __A)
{
- return (__m128i)__builtin_shufflevector((__v4si)__A,
- (__v4si)_mm_undefined_si128(),
+ return (__m128i)__builtin_shufflevector((__v4si)__A, (__v4si)__A,
0, 1, 0, 1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_broadcast_i32x2 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
@@ -1038,7 +1029,7 @@ _mm_mask_broadcast_i32x2 (__m128i __O, __mmask8 __M, __m128i __A)
(__v4si)__O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
@@ -1046,15 +1037,14 @@ _mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcast_i32x2 (__m128i __A)
{
- return (__m256i)__builtin_shufflevector((__v4si)__A,
- (__v4si)_mm_undefined_si128(),
+ return (__m256i)__builtin_shufflevector((__v4si)__A, (__v4si)__A,
0, 1, 0, 1, 0, 1, 0, 1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcast_i32x2 (__m256i __O, __mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
@@ -1062,7 +1052,7 @@ _mm256_mask_broadcast_i32x2 (__m256i __O, __mmask8 __M, __m128i __A)
(__v8si)__O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
@@ -1070,14 +1060,14 @@ _mm256_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcast_i64x2(__m128i __A)
{
return (__m256i)__builtin_shufflevector((__v2di)__A, (__v2di)__A,
0, 1, 0, 1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcast_i64x2(__m256i __O, __mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
@@ -1085,7 +1075,7 @@ _mm256_mask_broadcast_i64x2(__m256i __O, __mmask8 __M, __m128i __A)
(__v4di)__O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
@@ -1093,106 +1083,103 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A)
(__v4di)_mm256_setzero_si256());
}
-#define _mm256_extractf64x2_pd(A, imm) __extension__ ({ \
- (__m128d)__builtin_shufflevector((__v4df)(__m256d)(A), \
- (__v4df)_mm256_undefined_pd(), \
- ((imm) & 1) ? 2 : 0, \
- ((imm) & 1) ? 3 : 1); })
-
-#define _mm256_mask_extractf64x2_pd(W, U, A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
- (__v2df)_mm256_extractf64x2_pd((A), (imm)), \
- (__v2df)(W)); })
-
-#define _mm256_maskz_extractf64x2_pd(U, A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
- (__v2df)_mm256_extractf64x2_pd((A), (imm)), \
- (__v2df)_mm_setzero_pd()); })
-
-#define _mm256_extracti64x2_epi64(A, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v4di)(__m256i)(A), \
- (__v4di)_mm256_undefined_si256(), \
- ((imm) & 1) ? 2 : 0, \
- ((imm) & 1) ? 3 : 1); })
-
-#define _mm256_mask_extracti64x2_epi64(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
- (__v2di)_mm256_extracti64x2_epi64((A), (imm)), \
- (__v2di)(W)); })
-
-#define _mm256_maskz_extracti64x2_epi64(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
- (__v2di)_mm256_extracti64x2_epi64((A), (imm)), \
- (__v2di)_mm_setzero_di()); })
-
-#define _mm256_insertf64x2(A, B, imm) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v4df)(A), \
- (__v4df)_mm256_castpd128_pd256((__m128d)(B)), \
- ((imm) & 0x1) ? 0 : 4, \
- ((imm) & 0x1) ? 1 : 5, \
- ((imm) & 0x1) ? 4 : 2, \
- ((imm) & 0x1) ? 5 : 3); })
-
-#define _mm256_mask_insertf64x2(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_extractf64x2_pd(A, imm) \
+ (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \
+ (int)(imm), \
+ (__v2df)_mm_undefined_pd(), \
+ (__mmask8)-1)
+
+#define _mm256_mask_extractf64x2_pd(W, U, A, imm) \
+ (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \
+ (int)(imm), \
+ (__v2df)(__m128d)(W), \
+ (__mmask8)(U))
+
+#define _mm256_maskz_extractf64x2_pd(U, A, imm) \
+ (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \
+ (int)(imm), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)(U))
+
+#define _mm256_extracti64x2_epi64(A, imm) \
+ (__m128i)__builtin_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \
+ (int)(imm), \
+ (__v2di)_mm_undefined_si128(), \
+ (__mmask8)-1)
+
+#define _mm256_mask_extracti64x2_epi64(W, U, A, imm) \
+ (__m128i)__builtin_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \
+ (int)(imm), \
+ (__v2di)(__m128i)(W), \
+ (__mmask8)(U))
+
+#define _mm256_maskz_extracti64x2_epi64(U, A, imm) \
+ (__m128i)__builtin_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \
+ (int)(imm), \
+ (__v2di)_mm_setzero_si128(), \
+ (__mmask8)(U))
+
+#define _mm256_insertf64x2(A, B, imm) \
+ (__m256d)__builtin_ia32_insertf64x2_256((__v4df)(__m256d)(A), \
+ (__v2df)(__m128d)(B), (int)(imm))
+
+#define _mm256_mask_insertf64x2(W, U, A, B, imm) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_insertf64x2((A), (B), (imm)), \
- (__v4df)(W)); })
+ (__v4df)(__m256d)(W))
-#define _mm256_maskz_insertf64x2(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_insertf64x2(U, A, B, imm) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_insertf64x2((A), (B), (imm)), \
- (__v4df)_mm256_setzero_pd()); })
+ (__v4df)_mm256_setzero_pd())
-#define _mm256_inserti64x2(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v4di)(A), \
- (__v4di)_mm256_castsi128_si256((__m128i)(B)), \
- ((imm) & 0x1) ? 0 : 4, \
- ((imm) & 0x1) ? 1 : 5, \
- ((imm) & 0x1) ? 4 : 2, \
- ((imm) & 0x1) ? 5 : 3); })
+#define _mm256_inserti64x2(A, B, imm) \
+ (__m256i)__builtin_ia32_inserti64x2_256((__v4di)(__m256i)(A), \
+ (__v2di)(__m128i)(B), (int)(imm))
-#define _mm256_mask_inserti64x2(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_mask_inserti64x2(W, U, A, B, imm) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_inserti64x2((A), (B), (imm)), \
- (__v4di)(W)); })
+ (__v4di)(__m256i)(W))
-#define _mm256_maskz_inserti64x2(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_inserti64x2(U, A, B, imm) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_inserti64x2((A), (B), (imm)), \
- (__v4di)_mm256_setzero_si256()); })
+ (__v4di)_mm256_setzero_si256())
-#define _mm_mask_fpclass_pd_mask(U, A, imm) __extension__ ({ \
+#define _mm_mask_fpclass_pd_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclasspd128_mask((__v2df)(__m128d)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_fpclass_pd_mask(A, imm) __extension__ ({ \
+#define _mm_fpclass_pd_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclasspd128_mask((__v2df)(__m128d)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_fpclass_pd_mask(U, A, imm) __extension__ ({ \
+#define _mm256_mask_fpclass_pd_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclasspd256_mask((__v4df)(__m256d)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_fpclass_pd_mask(A, imm) __extension__ ({ \
+#define _mm256_fpclass_pd_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclasspd256_mask((__v4df)(__m256d)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_fpclass_ps_mask(U, A, imm) __extension__ ({ \
+#define _mm_mask_fpclass_ps_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclassps128_mask((__v4sf)(__m128)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_fpclass_ps_mask(A, imm) __extension__ ({ \
+#define _mm_fpclass_ps_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclassps128_mask((__v4sf)(__m128)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_fpclass_ps_mask(U, A, imm) __extension__ ({ \
+#define _mm256_mask_fpclass_ps_mask(U, A, imm) \
(__mmask8)__builtin_ia32_fpclassps256_mask((__v8sf)(__m256)(A), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_fpclass_ps_mask(A, imm) __extension__ ({ \
+#define _mm256_fpclass_ps_mask(A, imm) \
(__mmask8)__builtin_ia32_fpclassps256_mask((__v8sf)(__m256)(A), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
index fb8056e3f8d8..0ee1d00ef4d2 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
@@ -28,13 +28,12 @@
#ifndef __AVX512VLINTRIN_H
#define __AVX512VLINTRIN_H
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"), __min_vector_width__(256)))
-/* Doesn't require avx512vl, used in avx512dqintrin.h */
-static __inline __m128i __attribute__((__always_inline__, __nodebug__, __target__("avx512f")))
-_mm_setzero_di(void) {
- return (__m128i)(__v2di){ 0LL, 0LL};
-}
+typedef short __v2hi __attribute__((__vector_size__(4)));
+typedef char __v4qi __attribute__((__vector_size__(4)));
+typedef char __v2qi __attribute__((__vector_size__(2)));
/* Integer compare */
@@ -238,7 +237,7 @@ _mm_setzero_di(void) {
#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
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_add_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -246,7 +245,7 @@ _mm256_mask_add_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_add_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -254,7 +253,7 @@ _mm256_maskz_add_epi32(__mmask8 __U, __m256i __A, __m256i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_add_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -262,7 +261,7 @@ _mm256_mask_add_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_add_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -270,7 +269,7 @@ _mm256_maskz_add_epi64(__mmask8 __U, __m256i __A, __m256i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sub_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -278,7 +277,7 @@ _mm256_mask_sub_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sub_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -286,7 +285,7 @@ _mm256_maskz_sub_epi32(__mmask8 __U, __m256i __A, __m256i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sub_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -294,7 +293,7 @@ _mm256_mask_sub_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sub_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -302,7 +301,7 @@ _mm256_maskz_sub_epi64(__mmask8 __U, __m256i __A, __m256i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_add_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -310,7 +309,7 @@ _mm_mask_add_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_add_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -318,7 +317,7 @@ _mm_maskz_add_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_add_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -326,7 +325,7 @@ _mm_mask_add_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_add_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -334,7 +333,7 @@ _mm_maskz_add_epi64(__mmask8 __U, __m128i __A, __m128i __B)
(__v2di)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sub_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -342,7 +341,7 @@ _mm_mask_sub_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sub_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -350,7 +349,7 @@ _mm_maskz_sub_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sub_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -358,7 +357,7 @@ _mm_mask_sub_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sub_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -366,7 +365,7 @@ _mm_maskz_sub_epi64(__mmask8 __U, __m128i __A, __m128i __B)
(__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mul_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
@@ -374,7 +373,7 @@ _mm256_mask_mul_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mul_epi32(__mmask8 __M, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
@@ -382,7 +381,7 @@ _mm256_maskz_mul_epi32(__mmask8 __M, __m256i __X, __m256i __Y)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mul_epi32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
@@ -390,7 +389,7 @@ _mm_mask_mul_epi32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mul_epi32(__mmask8 __M, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
@@ -398,7 +397,7 @@ _mm_maskz_mul_epi32(__mmask8 __M, __m128i __X, __m128i __Y)
(__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mul_epu32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
@@ -406,7 +405,7 @@ _mm256_mask_mul_epu32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mul_epu32(__mmask8 __M, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
@@ -414,7 +413,7 @@ _mm256_maskz_mul_epu32(__mmask8 __M, __m256i __X, __m256i __Y)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mul_epu32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
@@ -422,7 +421,7 @@ _mm_mask_mul_epu32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mul_epu32(__mmask8 __M, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
@@ -430,7 +429,7 @@ _mm_maskz_mul_epu32(__mmask8 __M, __m128i __X, __m128i __Y)
(__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mullo_epi32(__mmask8 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
@@ -438,7 +437,7 @@ _mm256_maskz_mullo_epi32(__mmask8 __M, __m256i __A, __m256i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mullo_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
@@ -446,7 +445,7 @@ _mm256_mask_mullo_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mullo_epi32(__mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
@@ -454,7 +453,7 @@ _mm_maskz_mullo_epi32(__mmask8 __M, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mullo_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
@@ -462,7 +461,7 @@ _mm_mask_mullo_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_and_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -470,13 +469,13 @@ _mm256_mask_and_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_and_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_and_epi32(_mm256_setzero_si256(), __U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_and_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -484,13 +483,13 @@ _mm_mask_and_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_and_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_and_epi32(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_andnot_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -498,14 +497,14 @@ _mm256_mask_andnot_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_andnot_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_andnot_epi32(_mm256_setzero_si256(),
__U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_andnot_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -513,13 +512,13 @@ _mm_mask_andnot_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_andnot_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_andnot_epi32(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -527,13 +526,13 @@ _mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_or_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_or_epi32(_mm256_setzero_si256(), __U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_or_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -541,13 +540,13 @@ _mm_mask_or_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_or_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_or_epi32(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_xor_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -555,13 +554,13 @@ _mm256_mask_xor_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_xor_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_xor_epi32(_mm256_setzero_si256(), __U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_xor_epi32(__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B)
{
@@ -570,13 +569,13 @@ _mm_mask_xor_epi32(__m128i __W, __mmask8 __U, __m128i __A,
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_xor_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_xor_epi32(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_and_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -584,13 +583,13 @@ _mm256_mask_and_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_and_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_and_epi64(_mm256_setzero_si256(), __U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_and_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -598,13 +597,13 @@ _mm_mask_and_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_and_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_and_epi64(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_andnot_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -612,14 +611,14 @@ _mm256_mask_andnot_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_andnot_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_andnot_epi64(_mm256_setzero_si256(),
__U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_andnot_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -627,13 +626,13 @@ _mm_mask_andnot_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_andnot_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_andnot_epi64(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_or_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -641,13 +640,13 @@ _mm256_mask_or_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_or_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_or_epi64(_mm256_setzero_si256(), __U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_or_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -655,13 +654,13 @@ _mm_mask_or_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_or_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_or_epi64(_mm_setzero_si128(), __U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_xor_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -669,13 +668,13 @@ _mm256_mask_xor_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_xor_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)_mm256_mask_xor_epi64(_mm256_setzero_si256(), __U, __A, __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_xor_epi64(__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B)
{
@@ -684,909 +683,973 @@ _mm_mask_xor_epi64(__m128i __W, __mmask8 __U, __m128i __A,
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_xor_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_xor_epi64(_mm_setzero_si128(), __U, __A, __B);
}
-#define _mm_cmp_epi32_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epi32_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpd128_mask((__v4si)(__m128i)(a), \
(__v4si)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epi32_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpd128_mask((__v4si)(__m128i)(a), \
(__v4si)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm_cmp_epu32_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epu32_mask(a, b, p) \
(__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)(__m128i)(a), \
(__v4si)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epu32_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)(__m128i)(a), \
(__v4si)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_epi32_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epi32_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpd256_mask((__v8si)(__m256i)(a), \
(__v8si)(__m256i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epi32_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpd256_mask((__v8si)(__m256i)(a), \
(__v8si)(__m256i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_epu32_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epu32_mask(a, b, p) \
(__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)(__m256i)(a), \
(__v8si)(__m256i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epu32_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)(__m256i)(a), \
(__v8si)(__m256i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm_cmp_epi64_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epi64_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpq128_mask((__v2di)(__m128i)(a), \
(__v2di)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epi64_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpq128_mask((__v2di)(__m128i)(a), \
(__v2di)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm_cmp_epu64_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_epu64_mask(a, b, p) \
(__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)(__m128i)(a), \
(__v2di)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_epu64_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)(__m128i)(a), \
(__v2di)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_epi64_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epi64_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpq256_mask((__v4di)(__m256i)(a), \
(__v4di)(__m256i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epi64_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpq256_mask((__v4di)(__m256i)(a), \
(__v4di)(__m256i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_epu64_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_epu64_mask(a, b, p) \
(__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)(__m256i)(a), \
(__v4di)(__m256i)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_epu64_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)(__m256i)(a), \
(__v4di)(__m256i)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_ps_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_ps_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpps256_mask((__v8sf)(__m256)(a), \
(__v8sf)(__m256)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_cmp_ps_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_ps_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpps256_mask((__v8sf)(__m256)(a), \
(__v8sf)(__m256)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm256_cmp_pd_mask(a, b, p) __extension__ ({ \
+#define _mm256_cmp_pd_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmppd256_mask((__v4df)(__m256d)(a), \
(__v4df)(__m256d)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_cmp_pd_mask(m, a, b, p) __extension__ ({ \
+#define _mm256_mask_cmp_pd_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmppd256_mask((__v4df)(__m256d)(a), \
(__v4df)(__m256d)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm_cmp_ps_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_ps_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmpps128_mask((__v4sf)(__m128)(a), \
(__v4sf)(__m128)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_ps_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_ps_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmpps128_mask((__v4sf)(__m128)(a), \
(__v4sf)(__m128)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-#define _mm_cmp_pd_mask(a, b, p) __extension__ ({ \
+#define _mm_cmp_pd_mask(a, b, p) \
(__mmask8)__builtin_ia32_cmppd128_mask((__v2df)(__m128d)(a), \
(__v2df)(__m128d)(b), (int)(p), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_cmp_pd_mask(m, a, b, p) __extension__ ({ \
+#define _mm_mask_cmp_pd_mask(m, a, b, p) \
(__mmask8)__builtin_ia32_cmppd128_mask((__v2df)(__m128d)(a), \
(__v2df)(__m128d)(b), (int)(p), \
- (__mmask8)(m)); })
+ (__mmask8)(m))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_mask3 ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df) __C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_maskz ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_mask ((__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_maskz ((__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_mask3 (-(__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd (-(__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df) __C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fnmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_maskz (-(__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd (-(__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fnmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddpd128_maskz (-(__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd (-(__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_fmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask3_fmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_mask3 ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df) __C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_fmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_maskz ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_fmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_mask ((__v4df) __A,
- (__v4df) __B,
- -(__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_fmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_maskz ((__v4df) __A,
- (__v4df) __B,
- -(__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask3_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_mask3 (-(__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 (-(__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df) __C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_fnmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_maskz (-(__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 (-(__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_fnmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddpd256_maskz (-(__v4df) __A,
- (__v4df) __B,
- -(__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 (-(__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddps128_mask3 ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf) __C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddps128_maskz ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddps128_maskz ((__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddps128_mask3 (-(__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps (-(__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf) __C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fnmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddps128_maskz (-(__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps (-(__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fnmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddps128_maskz (-(__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps (-(__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_fmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask3_fmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
{
- return (__m256) __builtin_ia32_vfmaddps256_mask3 ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf) __C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_fmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddps256_maskz ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_fmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- -(__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_fmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddps256_maskz ((__v8sf) __A,
- (__v8sf) __B,
- -(__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask3_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
{
- return (__m256) __builtin_ia32_vfmaddps256_mask3 (-(__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 (-(__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf) __C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_fnmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddps256_maskz (-(__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 (-(__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddps256_maskz (-(__v8sf) __A,
- (__v8sf) __B,
- -(__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 (-(__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsubpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddsubpd128_mask3 ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8)
- __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df) __C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsubpd128_maskz ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8)
- __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsubpd128_mask ((__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfmaddsubpd128_maskz ((__v2df) __A,
- (__v2df) __B,
- -(__v2df) __C,
- (__mmask8)
- __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddsubpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd256 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
{
- return (__m256d) __builtin_ia32_vfmaddsubpd256_mask3 ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8)
- __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd256 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df) __C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddsubpd256_maskz ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8)
- __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd256 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddsubpd256_mask ((__v4df) __A,
- (__v4df) __B,
- -(__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd256 ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfmaddsubpd256_maskz ((__v4df) __A,
- (__v4df) __B,
- -(__v4df) __C,
- (__mmask8)
- __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd256 ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddsubps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddsubps128_mask3 ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf) __C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddsubps128_maskz ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddsubps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfmaddsubps128_maskz ((__v4sf) __A,
- (__v4sf) __B,
- -(__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B,
__m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddsubps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
{
- return (__m256) __builtin_ia32_vfmaddsubps256_mask3 ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf) __C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddsubps256_maskz ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddsubps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- -(__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfmaddsubps256_maskz ((__v8sf) __A,
- (__v8sf) __B,
- -(__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmsubpd128_mask3 ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df) __C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask3_fmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
{
- return (__m256d) __builtin_ia32_vfmsubpd256_mask3 ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df) __C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmsubps128_mask3 ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf) __C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
{
- return (__m256) __builtin_ia32_vfmsubps256_mask3 ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf) __C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmsubaddpd128_mask3 ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8)
- __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C),
+ (__v2df) __C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
{
- return (__m256d) __builtin_ia32_vfmsubaddpd256_mask3 ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8)
- __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubpd256 ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C),
+ (__v4df) __C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmsubaddps128_mask3 ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf) __C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
{
- return (__m256) __builtin_ia32_vfmsubaddps256_mask3 ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddsubps256 ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf) __C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fnmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfnmaddpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ -(__v2df) __B,
+ (__v2df) __C),
+ (__v2df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_fnmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfnmaddpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ -(__v4df) __B,
+ (__v4df) __C),
+ (__v4df) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fnmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfnmaddps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ -(__v4sf) __B,
+ (__v4sf) __C),
+ (__v4sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_fnmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfnmaddps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ -(__v8sf) __B,
+ (__v8sf) __C),
+ (__v8sf) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_fnmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
{
- return (__m128d) __builtin_ia32_vfnmsubpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ -(__v2df) __B,
+ -(__v2df) __C),
+ (__v2df) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask3_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfnmsubpd128_mask3 ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __C,
- (__mmask8) __U);
+ return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U,
+ __builtin_ia32_vfmaddpd ((__v2df) __A,
+ -(__v2df) __B,
+ -(__v2df) __C),
+ (__v2df) __C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_fnmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
{
- return (__m256d) __builtin_ia32_vfnmsubpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ -(__v4df) __B,
+ -(__v4df) __C),
+ (__v4df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask3_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
{
- return (__m256d) __builtin_ia32_vfnmsubpd256_mask3 ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __C,
- (__mmask8) __U);
+ return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U,
+ __builtin_ia32_vfmaddpd256 ((__v4df) __A,
+ -(__v4df) __B,
+ -(__v4df) __C),
+ (__v4df) __C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_fnmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
{
- return (__m128) __builtin_ia32_vfnmsubps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ -(__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask3_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfnmsubps128_mask3 ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __C,
- (__mmask8) __U);
+ return (__m128) __builtin_ia32_selectps_128((__mmask8) __U,
+ __builtin_ia32_vfmaddps ((__v4sf) __A,
+ -(__v4sf) __B,
+ -(__v4sf) __C),
+ (__v4sf) __C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_fnmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
{
- return (__m256) __builtin_ia32_vfnmsubps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ -(__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
{
- return (__m256) __builtin_ia32_vfnmsubps256_mask3 ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __C,
- (__mmask8) __U);
+ return (__m256) __builtin_ia32_selectps_256((__mmask8) __U,
+ __builtin_ia32_vfmaddps256 ((__v8sf) __A,
+ -(__v8sf) __B,
+ -(__v8sf) __C),
+ (__v8sf) __C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_add_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_add_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_add_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_add_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_add_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_add_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_add_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_add_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_add_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_add_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_add_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_add_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_add_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_add_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_add_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_add_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_blend_epi32 (__mmask8 __U, __m128i __A, __m128i __W) {
return (__m128i) __builtin_ia32_selectd_128 ((__mmask8) __U,
(__v4si) __W,
(__v4si) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_blend_epi32 (__mmask8 __U, __m256i __A, __m256i __W) {
return (__m256i) __builtin_ia32_selectd_256 ((__mmask8) __U,
(__v8si) __W,
(__v8si) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_blend_pd (__mmask8 __U, __m128d __A, __m128d __W) {
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
(__v2df) __W,
(__v2df) __A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_blend_pd (__mmask8 __U, __m256d __A, __m256d __W) {
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
(__v4df) __W,
(__v4df) __A);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_blend_ps (__mmask8 __U, __m128 __A, __m128 __W) {
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
(__v4sf) __W,
(__v4sf) __A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_blend_ps (__mmask8 __U, __m256 __A, __m256 __W) {
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
(__v8sf) __W,
(__v8sf) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_blend_epi64 (__mmask8 __U, __m128i __A, __m128i __W) {
return (__m128i) __builtin_ia32_selectq_128 ((__mmask8) __U,
(__v2di) __W,
(__v2di) __A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_blend_epi64 (__mmask8 __U, __m256i __A, __m256i __W) {
return (__m256i) __builtin_ia32_selectq_256 ((__mmask8) __U,
(__v4di) __W,
(__v4di) __A);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_compress_pd (__m128d __W, __mmask8 __U, __m128d __A) {
return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A,
(__v2df) __W,
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_compress_pd (__mmask8 __U, __m128d __A) {
return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A,
(__v2df)
@@ -1594,14 +1657,14 @@ _mm_maskz_compress_pd (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_compress_pd (__m256d __W, __mmask8 __U, __m256d __A) {
return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A,
(__v4df) __W,
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_compress_pd (__mmask8 __U, __m256d __A) {
return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A,
(__v4df)
@@ -1609,14 +1672,14 @@ _mm256_maskz_compress_pd (__mmask8 __U, __m256d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_compress_epi64 (__m128i __W, __mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_compress_epi64 (__mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A,
(__v2di)
@@ -1624,14 +1687,14 @@ _mm_maskz_compress_epi64 (__mmask8 __U, __m128i __A) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_compress_epi64 (__m256i __W, __mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_compress_epi64 (__mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A,
(__v4di)
@@ -1639,14 +1702,14 @@ _mm256_maskz_compress_epi64 (__mmask8 __U, __m256i __A) {
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_compress_ps (__m128 __W, __mmask8 __U, __m128 __A) {
return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_compress_ps (__mmask8 __U, __m128 __A) {
return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A,
(__v4sf)
@@ -1654,14 +1717,14 @@ _mm_maskz_compress_ps (__mmask8 __U, __m128 __A) {
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_compress_ps (__m256 __W, __mmask8 __U, __m256 __A) {
return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A,
(__v8sf) __W,
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_compress_ps (__mmask8 __U, __m256 __A) {
return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A,
(__v8sf)
@@ -1669,14 +1732,14 @@ _mm256_maskz_compress_ps (__mmask8 __U, __m256 __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_compress_epi32 (__m128i __W, __mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_compress_epi32 (__mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A,
(__v4si)
@@ -1684,14 +1747,14 @@ _mm_maskz_compress_epi32 (__mmask8 __U, __m128i __A) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_compress_epi32 (__m256i __W, __mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A,
(__v8si) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_compress_epi32 (__mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A,
(__v8si)
@@ -1699,128 +1762,126 @@ _mm256_maskz_compress_epi32 (__mmask8 __U, __m256i __A) {
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m128d __A) {
__builtin_ia32_compressstoredf128_mask ((__v2df *) __P,
(__v2df) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m256d __A) {
__builtin_ia32_compressstoredf256_mask ((__v4df *) __P,
(__v4df) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m128i __A) {
__builtin_ia32_compressstoredi128_mask ((__v2di *) __P,
(__v2di) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m256i __A) {
__builtin_ia32_compressstoredi256_mask ((__v4di *) __P,
(__v4di) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m128 __A) {
__builtin_ia32_compressstoresf128_mask ((__v4sf *) __P,
(__v4sf) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m256 __A) {
__builtin_ia32_compressstoresf256_mask ((__v8sf *) __P,
(__v8sf) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m128i __A) {
__builtin_ia32_compressstoresi128_mask ((__v4si *) __P,
(__v4si) __A,
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m256i __A) {
__builtin_ia32_compressstoresi256_mask ((__v8si *) __P,
(__v8si) __A,
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi32_pd (__m128d __W, __mmask8 __U, __m128i __A) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
(__v2df)_mm_cvtepi32_pd(__A),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
(__v2df)_mm_cvtepi32_pd(__A),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi32_pd (__m256d __W, __mmask8 __U, __m128i __A) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
(__v4df)_mm256_cvtepi32_pd(__A),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
(__v4df)_mm256_cvtepi32_pd(__A),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi32_ps (__m128 __W, __mmask8 __U, __m128i __A) {
- return (__m128) __builtin_ia32_cvtdq2ps128_mask ((__v4si) __A,
- (__v4sf) __W,
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_cvtepi32_ps(__A),
+ (__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi32_ps (__mmask16 __U, __m128i __A) {
- return (__m128) __builtin_ia32_cvtdq2ps128_mask ((__v4si) __A,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
+_mm_maskz_cvtepi32_ps (__mmask8 __U, __m128i __A) {
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_cvtepi32_ps(__A),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi32_ps (__m256 __W, __mmask8 __U, __m256i __A) {
- return (__m256) __builtin_ia32_cvtdq2ps256_mask ((__v8si) __A,
- (__v8sf) __W,
- (__mmask8) __U);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_cvtepi32_ps(__A),
+ (__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi32_ps (__mmask16 __U, __m256i __A) {
- return (__m256) __builtin_ia32_cvtdq2ps256_mask ((__v8si) __A,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
+_mm256_maskz_cvtepi32_ps (__mmask8 __U, __m256i __A) {
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_cvtepi32_ps(__A),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtpd_epi32 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A,
(__v4si)
@@ -1828,29 +1889,28 @@ _mm_maskz_cvtpd_epi32 (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) {
- return (__m128i) __builtin_ia32_cvtpd2dq256_mask ((__v4df) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm256_cvtpd_epi32(__A),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtpd_epi32 (__mmask8 __U, __m256d __A) {
- return (__m128i) __builtin_ia32_cvtpd2dq256_mask ((__v4df) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm256_cvtpd_epi32(__A),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m128d __A) {
return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_cvtpd_ps (__mmask8 __U, __m128d __A) {
return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A,
(__v4sf)
@@ -1858,22 +1918,21 @@ _mm_maskz_cvtpd_ps (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m256d __A) {
- return (__m128) __builtin_ia32_cvtpd2ps256_mask ((__v4df) __A,
- (__v4sf) __W,
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm256_cvtpd_ps(__A),
+ (__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtpd_ps (__mmask8 __U, __m256d __A) {
- return (__m128) __builtin_ia32_cvtpd2ps256_mask ((__v4df) __A,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm256_cvtpd_ps(__A),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtpd_epu32 (__m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A,
(__v4si)
@@ -1881,14 +1940,14 @@ _mm_cvtpd_epu32 (__m128d __A) {
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtpd_epu32 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A,
(__v4si)
@@ -1896,7 +1955,7 @@ _mm_maskz_cvtpd_epu32 (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtpd_epu32 (__m256d __A) {
return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A,
(__v4si)
@@ -1904,14 +1963,14 @@ _mm256_cvtpd_epu32 (__m256d __A) {
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) {
return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtpd_epu32 (__mmask8 __U, __m256d __A) {
return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A,
(__v4si)
@@ -1919,67 +1978,63 @@ _mm256_maskz_cvtpd_epu32 (__mmask8 __U, __m256d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) {
- return (__m128i) __builtin_ia32_cvtps2dq128_mask ((__v4sf) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtps_epi32(__A),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtps_epi32 (__mmask8 __U, __m128 __A) {
- return (__m128i) __builtin_ia32_cvtps2dq128_mask ((__v4sf) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtps_epi32(__A),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) {
- return (__m256i) __builtin_ia32_cvtps2dq256_mask ((__v8sf) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtps_epi32(__A),
+ (__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtps_epi32 (__mmask8 __U, __m256 __A) {
- return (__m256i) __builtin_ia32_cvtps2dq256_mask ((__v8sf) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtps_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_cvtps_pd (__m128d __W, __mmask8 __U, __m128 __A) {
- return (__m128d) __builtin_ia32_cvtps2pd128_mask ((__v4sf) __A,
- (__v2df) __W,
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_cvtps_pd(__A),
+ (__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_cvtps_pd (__mmask8 __U, __m128 __A) {
- return (__m128d) __builtin_ia32_cvtps2pd128_mask ((__v4sf) __A,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_cvtps_pd(__A),
+ (__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_cvtps_pd (__m256d __W, __mmask8 __U, __m128 __A) {
- return (__m256d) __builtin_ia32_cvtps2pd256_mask ((__v4sf) __A,
- (__v4df) __W,
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_cvtps_pd(__A),
+ (__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtps_pd (__mmask8 __U, __m128 __A) {
- return (__m256d) __builtin_ia32_cvtps2pd256_mask ((__v4sf) __A,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_cvtps_pd(__A),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtps_epu32 (__m128 __A) {
return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A,
(__v4si)
@@ -1987,14 +2042,14 @@ _mm_cvtps_epu32 (__m128 __A) {
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtps_epu32 (__mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A,
(__v4si)
@@ -2002,7 +2057,7 @@ _mm_maskz_cvtps_epu32 (__mmask8 __U, __m128 __A) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvtps_epu32 (__m256 __A) {
return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A,
(__v8si)
@@ -2010,14 +2065,14 @@ _mm256_cvtps_epu32 (__m256 __A) {
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) {
return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A,
(__v8si) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtps_epu32 (__mmask8 __U, __m256 __A) {
return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A,
(__v8si)
@@ -2025,14 +2080,14 @@ _mm256_maskz_cvtps_epu32 (__mmask8 __U, __m256 __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttpd_epi32 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A,
(__v4si)
@@ -2040,22 +2095,21 @@ _mm_maskz_cvttpd_epi32 (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) {
- return (__m128i) __builtin_ia32_cvttpd2dq256_mask ((__v4df) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm256_cvttpd_epi32(__A),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttpd_epi32 (__mmask8 __U, __m256d __A) {
- return (__m128i) __builtin_ia32_cvttpd2dq256_mask ((__v4df) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm256_cvttpd_epi32(__A),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvttpd_epu32 (__m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A,
(__v4si)
@@ -2063,14 +2117,14 @@ _mm_cvttpd_epu32 (__m128d __A) {
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttpd_epu32 (__mmask8 __U, __m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A,
(__v4si)
@@ -2078,7 +2132,7 @@ _mm_maskz_cvttpd_epu32 (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvttpd_epu32 (__m256d __A) {
return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A,
(__v4si)
@@ -2086,14 +2140,14 @@ _mm256_cvttpd_epu32 (__m256d __A) {
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) {
return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttpd_epu32 (__mmask8 __U, __m256d __A) {
return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A,
(__v4si)
@@ -2101,37 +2155,35 @@ _mm256_maskz_cvttpd_epu32 (__mmask8 __U, __m256d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) {
- return (__m128i) __builtin_ia32_cvttps2dq128_mask ((__v4sf) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvttps_epi32(__A),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttps_epi32 (__mmask8 __U, __m128 __A) {
- return (__m128i) __builtin_ia32_cvttps2dq128_mask ((__v4sf) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvttps_epi32(__A),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) {
- return (__m256i) __builtin_ia32_cvttps2dq256_mask ((__v8sf) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvttps_epi32(__A),
+ (__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttps_epi32 (__mmask8 __U, __m256 __A) {
- return (__m256i) __builtin_ia32_cvttps2dq256_mask ((__v8sf) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvttps_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvttps_epu32 (__m128 __A) {
return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A,
(__v4si)
@@ -2139,14 +2191,14 @@ _mm_cvttps_epu32 (__m128 __A) {
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvttps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvttps_epu32 (__mmask8 __U, __m128 __A) {
return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A,
(__v4si)
@@ -2154,7 +2206,7 @@ _mm_maskz_cvttps_epu32 (__mmask8 __U, __m128 __A) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cvttps_epu32 (__m256 __A) {
return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A,
(__v8si)
@@ -2162,14 +2214,14 @@ _mm256_cvttps_epu32 (__m256 __A) {
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_cvttps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) {
return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A,
(__v8si) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) {
return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A,
(__v8si)
@@ -2177,155 +2229,147 @@ _mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) {
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_cvtepu32_pd (__m128i __A) {
return (__m128d) __builtin_convertvector(
__builtin_shufflevector((__v4su)__A, (__v4su)__A, 0, 1), __v2df);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_cvtepu32_pd (__m128d __W, __mmask8 __U, __m128i __A) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
(__v2df)_mm_cvtepu32_pd(__A),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
(__v2df)_mm_cvtepu32_pd(__A),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_cvtepu32_pd (__m128i __A) {
return (__m256d)__builtin_convertvector((__v4su)__A, __v4df);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepu32_pd (__m256d __W, __mmask8 __U, __m128i __A) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
(__v4df)_mm256_cvtepu32_pd(__A),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
(__v4df)_mm256_cvtepu32_pd(__A),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_cvtepu32_ps (__m128i __A) {
- return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) -1);
+ return (__m128)__builtin_convertvector((__v4su)__A, __v4sf);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtepu32_ps (__m128 __W, __mmask8 __U, __m128i __A) {
- return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A,
- (__v4sf) __W,
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_cvtepu32_ps(__A),
+ (__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepu32_ps (__mmask8 __U, __m128i __A) {
- return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_cvtepu32_ps(__A),
+ (__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_cvtepu32_ps (__m256i __A) {
- return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) -1);
+ return (__m256)__builtin_convertvector((__v8su)__A, __v8sf);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepu32_ps (__m256 __W, __mmask8 __U, __m256i __A) {
- return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A,
- (__v8sf) __W,
- (__mmask8) __U);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_cvtepu32_ps(__A),
+ (__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepu32_ps (__mmask8 __U, __m256i __A) {
- return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_cvtepu32_ps(__A),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_div_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_div_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_div_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_div_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_div_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_div_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_div_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_div_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_div_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_div_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_div_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_div_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_div_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_div_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_div_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_div_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_expand_pd (__m128d __W, __mmask8 __U, __m128d __A) {
return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A,
(__v2df) __W,
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_expand_pd (__mmask8 __U, __m128d __A) {
return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A,
(__v2df)
@@ -2333,14 +2377,14 @@ _mm_maskz_expand_pd (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_expand_pd (__m256d __W, __mmask8 __U, __m256d __A) {
return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A,
(__v4df) __W,
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_expand_pd (__mmask8 __U, __m256d __A) {
return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A,
(__v4df)
@@ -2348,14 +2392,14 @@ _mm256_maskz_expand_pd (__mmask8 __U, __m256d __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expand_epi64 (__m128i __W, __mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A,
(__v2di) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expand_epi64 (__mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A,
(__v2di)
@@ -2363,14 +2407,14 @@ _mm_maskz_expand_epi64 (__mmask8 __U, __m128i __A) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expand_epi64 (__m256i __W, __mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A,
(__v4di) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expand_epi64 (__mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A,
(__v4di)
@@ -2378,7 +2422,7 @@ _mm256_maskz_expand_epi64 (__mmask8 __U, __m256i __A) {
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_expandloadu_pd (__m128d __W, __mmask8 __U, void const *__P) {
return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P,
(__v2df) __W,
@@ -2386,7 +2430,7 @@ _mm_mask_expandloadu_pd (__m128d __W, __mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_expandloadu_pd (__mmask8 __U, void const *__P) {
return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P,
(__v2df)
@@ -2395,7 +2439,7 @@ _mm_maskz_expandloadu_pd (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_expandloadu_pd (__m256d __W, __mmask8 __U, void const *__P) {
return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P,
(__v4df) __W,
@@ -2403,7 +2447,7 @@ _mm256_mask_expandloadu_pd (__m256d __W, __mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_expandloadu_pd (__mmask8 __U, void const *__P) {
return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P,
(__v4df)
@@ -2412,7 +2456,7 @@ _mm256_maskz_expandloadu_pd (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expandloadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) {
return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P,
(__v2di) __W,
@@ -2420,7 +2464,7 @@ _mm_mask_expandloadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) {
return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P,
(__v2di)
@@ -2429,7 +2473,7 @@ _mm_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expandloadu_epi64 (__m256i __W, __mmask8 __U,
void const *__P) {
return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P,
@@ -2438,7 +2482,7 @@ _mm256_mask_expandloadu_epi64 (__m256i __W, __mmask8 __U,
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) {
return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P,
(__v4di)
@@ -2447,14 +2491,14 @@ _mm256_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_expandloadu_ps (__m128 __W, __mmask8 __U, void const *__P) {
return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_expandloadu_ps (__mmask8 __U, void const *__P) {
return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P,
(__v4sf)
@@ -2463,14 +2507,14 @@ _mm_maskz_expandloadu_ps (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_expandloadu_ps (__m256 __W, __mmask8 __U, void const *__P) {
return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P,
(__v8sf) __W,
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_expandloadu_ps (__mmask8 __U, void const *__P) {
return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P,
(__v8sf)
@@ -2479,7 +2523,7 @@ _mm256_maskz_expandloadu_ps (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expandloadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) {
return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P,
(__v4si) __W,
@@ -2487,7 +2531,7 @@ _mm_mask_expandloadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) {
return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P,
(__v4si)
@@ -2495,7 +2539,7 @@ _mm_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expandloadu_epi32 (__m256i __W, __mmask8 __U,
void const *__P) {
return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P,
@@ -2504,7 +2548,7 @@ _mm256_mask_expandloadu_epi32 (__m256i __W, __mmask8 __U,
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) {
return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P,
(__v8si)
@@ -2513,14 +2557,14 @@ _mm256_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) {
__U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_expand_ps (__m128 __W, __mmask8 __U, __m128 __A) {
return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_expand_ps (__mmask8 __U, __m128 __A) {
return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A,
(__v4sf)
@@ -2528,14 +2572,14 @@ _mm_maskz_expand_ps (__mmask8 __U, __m128 __A) {
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_expand_ps (__m256 __W, __mmask8 __U, __m256 __A) {
return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A,
(__v8sf) __W,
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_expand_ps (__mmask8 __U, __m256 __A) {
return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A,
(__v8sf)
@@ -2543,14 +2587,14 @@ _mm256_maskz_expand_ps (__mmask8 __U, __m256 __A) {
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expand_epi32 (__m128i __W, __mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A,
(__v4si) __W,
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expand_epi32 (__mmask8 __U, __m128i __A) {
return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A,
(__v4si)
@@ -2558,14 +2602,14 @@ _mm_maskz_expand_epi32 (__mmask8 __U, __m128i __A) {
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expand_epi32 (__m256i __W, __mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A,
(__v8si) __W,
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expand_epi32 (__mmask8 __U, __m256i __A) {
return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A,
(__v8si)
@@ -2573,7 +2617,7 @@ _mm256_maskz_expand_epi32 (__mmask8 __U, __m256i __A) {
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_getexp_pd (__m128d __A) {
return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A,
(__v2df)
@@ -2581,14 +2625,14 @@ _mm_getexp_pd (__m128d __A) {
(__mmask8) -1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_getexp_pd (__m128d __W, __mmask8 __U, __m128d __A) {
return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A,
(__v2df) __W,
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_getexp_pd (__mmask8 __U, __m128d __A) {
return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A,
(__v2df)
@@ -2596,7 +2640,7 @@ _mm_maskz_getexp_pd (__mmask8 __U, __m128d __A) {
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_getexp_pd (__m256d __A) {
return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A,
(__v4df)
@@ -2604,14 +2648,14 @@ _mm256_getexp_pd (__m256d __A) {
(__mmask8) -1);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_getexp_pd (__m256d __W, __mmask8 __U, __m256d __A) {
return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A,
(__v4df) __W,
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_getexp_pd (__mmask8 __U, __m256d __A) {
return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A,
(__v4df)
@@ -2619,7 +2663,7 @@ _mm256_maskz_getexp_pd (__mmask8 __U, __m256d __A) {
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_getexp_ps (__m128 __A) {
return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A,
(__v4sf)
@@ -2627,14 +2671,14 @@ _mm_getexp_ps (__m128 __A) {
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_getexp_ps (__m128 __W, __mmask8 __U, __m128 __A) {
return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A,
(__v4sf) __W,
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_getexp_ps (__mmask8 __U, __m128 __A) {
return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A,
(__v4sf)
@@ -2642,7 +2686,7 @@ _mm_maskz_getexp_ps (__mmask8 __U, __m128 __A) {
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_getexp_ps (__m256 __A) {
return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A,
(__v8sf)
@@ -2650,14 +2694,14 @@ _mm256_getexp_ps (__m256 __A) {
(__mmask8) -1);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_getexp_ps (__m256 __W, __mmask8 __U, __m256 __A) {
return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A,
(__v8sf) __W,
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) {
return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A,
(__v8sf)
@@ -2665,643 +2709,579 @@ _mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) {
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_max_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_max_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_max_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_max_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_max_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_max_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_max_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_max_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_max_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_max_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_max_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_max_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_max_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_max_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_max_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_max_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_min_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_min_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_min_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_min_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_min_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_min_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_min_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_min_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_min_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_min_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_min_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_min_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_min_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_min_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_min_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_min_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_mul_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_mul_pd(__A, __B),
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_mul_pd(__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
(__v2df)_mm_mul_pd(__A, __B),
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_mul_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_mul_pd(__A, __B),
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_mul_pd(__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
(__v4df)_mm256_mul_pd(__A, __B),
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_mul_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_mul_ps(__A, __B),
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_mul_ps(__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
(__v4sf)_mm_mul_ps(__A, __B),
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_mul_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_mul_ps(__A, __B),
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_mul_ps(__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
(__v8sf)_mm256_mul_ps(__A, __B),
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_abs_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
(__v4si)_mm_abs_epi32(__A),
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_abs_epi32(__mmask8 __U, __m128i __A) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
(__v4si)_mm_abs_epi32(__A),
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_abs_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
- return (__m256i)__builtin_ia32_selectd_256((__mmask16)__U,
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
(__v8si)_mm256_abs_epi32(__A),
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_abs_epi32(__mmask8 __U, __m256i __A) {
- return (__m256i)__builtin_ia32_selectd_256((__mmask16)__U,
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
(__v8si)_mm256_abs_epi32(__A),
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_abs_epi64 (__m128i __A) {
- return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_pabsq128((__v2di)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_abs_epi64 (__m128i __W, __mmask8 __U, __m128i __A) {
- return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_abs_epi64(__A),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_abs_epi64 (__mmask8 __U, __m128i __A) {
- return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_abs_epi64(__A),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_abs_epi64 (__m256i __A) {
- return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_pabsq256 ((__v4di)__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_abs_epi64 (__m256i __W, __mmask8 __U, __m256i __A) {
- return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_abs_epi64(__A),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_abs_epi64 (__mmask8 __U, __m256i __A) {
- return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_abs_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_max_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_max_epi32(__A, __B),
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_max_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_max_epi32(__A, __B),
(__v4si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_max_epi32(__mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_max_epi32(__A, __B),
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_max_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_max_epi32(__A, __B),
(__v8si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epi64 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_max_epi64 (__m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_pmaxsq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_max_epi64 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W, __M);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_max_epi64 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_max_epi64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_max_epi64 (__m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_max_epi64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_max_epi64(__A, __B),
+ (__v2di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_max_epi64 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_max_epi64 (__m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_pmaxsq256((__v4di)__A, (__v4di)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_max_epi64 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W, __M);
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_maskz_max_epi64 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_max_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_max_epi64 (__m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_max_epi64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_max_epi64(__A, __B),
+ (__v4di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_max_epu32(__mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_max_epu32(__A, __B),
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_max_epu32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_max_epu32(__A, __B),
(__v4si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_max_epu32(__mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_max_epu32(__A, __B),
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_max_epu32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_max_epu32(__A, __B),
(__v8si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epu64 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_max_epu64 (__m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_pmaxuq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_max_epu64 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W, __M);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_max_epu64 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_max_epu64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_max_epu64 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_max_epu64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_max_epu64(__A, __B),
+ (__v2di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_max_epu64 (__m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_pmaxuq256((__v4di)__A, (__v4di)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_max_epu64 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W, __M);
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_maskz_max_epu64 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_max_epu64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_max_epu64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_max_epu64(__A, __B),
+ (__v4di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_min_epi32(__A, __B),
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_min_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_min_epi32(__A, __B),
(__v4si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epi32(__mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_min_epi32(__A, __B),
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_min_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_min_epi32(__A, __B),
(__v8si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_min_epi64 (__m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_pminsq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_min_epi64 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W, __M);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_min_epi64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_min_epi64(__A, __B),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epi64 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_min_epi64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epi64 (__m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_pminsq256((__v4di)__A, (__v4di)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_min_epi64 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W, __M);
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_min_epi64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_min_epi64(__A, __B),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epi64 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_min_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epu32(__mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_min_epu32(__A, __B),
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_min_epu32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
(__v4si)_mm_min_epu32(__A, __B),
(__v4si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epu32(__mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_min_epu32(__A, __B),
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_min_epu32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
(__v8si)_mm256_min_epu32(__A, __B),
(__v8si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_min_epu64 (__m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_pminuq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_min_epu64 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W, __M);
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_min_epu64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_min_epu64(__A, __B),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_min_epu64 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_min_epu64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_min_epu64 (__m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_pminuq256((__v4di)__A, (__v4di)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_min_epu64 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W, __M);
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_min_epu64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_min_epu64(__A, __B),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_min_epu64 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_min_epu64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-#define _mm_roundscale_pd(A, imm) __extension__ ({ \
+#define _mm_roundscale_pd(A, imm) \
(__m128d)__builtin_ia32_rndscalepd_128_mask((__v2df)(__m128d)(A), \
(int)(imm), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_roundscale_pd(W, U, A, imm) __extension__ ({ \
+#define _mm_mask_roundscale_pd(W, U, A, imm) \
(__m128d)__builtin_ia32_rndscalepd_128_mask((__v2df)(__m128d)(A), \
(int)(imm), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_roundscale_pd(U, A, imm) __extension__ ({ \
+#define _mm_maskz_roundscale_pd(U, A, imm) \
(__m128d)__builtin_ia32_rndscalepd_128_mask((__v2df)(__m128d)(A), \
(int)(imm), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_roundscale_pd(A, imm) __extension__ ({ \
+#define _mm256_roundscale_pd(A, imm) \
(__m256d)__builtin_ia32_rndscalepd_256_mask((__v4df)(__m256d)(A), \
(int)(imm), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_roundscale_pd(W, U, A, imm) __extension__ ({ \
+#define _mm256_mask_roundscale_pd(W, U, A, imm) \
(__m256d)__builtin_ia32_rndscalepd_256_mask((__v4df)(__m256d)(A), \
(int)(imm), \
(__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_roundscale_pd(U, A, imm) __extension__ ({ \
+#define _mm256_maskz_roundscale_pd(U, A, imm) \
(__m256d)__builtin_ia32_rndscalepd_256_mask((__v4df)(__m256d)(A), \
(int)(imm), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_roundscale_ps(A, imm) __extension__ ({ \
+#define _mm_roundscale_ps(A, imm) \
(__m128)__builtin_ia32_rndscaleps_128_mask((__v4sf)(__m128)(A), (int)(imm), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_roundscale_ps(W, U, A, imm) __extension__ ({ \
+#define _mm_mask_roundscale_ps(W, U, A, imm) \
(__m128)__builtin_ia32_rndscaleps_128_mask((__v4sf)(__m128)(A), (int)(imm), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_roundscale_ps(U, A, imm) __extension__ ({ \
+#define _mm_maskz_roundscale_ps(U, A, imm) \
(__m128)__builtin_ia32_rndscaleps_128_mask((__v4sf)(__m128)(A), (int)(imm), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_roundscale_ps(A, imm) __extension__ ({ \
+#define _mm256_roundscale_ps(A, imm) \
(__m256)__builtin_ia32_rndscaleps_256_mask((__v8sf)(__m256)(A), (int)(imm), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_roundscale_ps(W, U, A, imm) __extension__ ({ \
+#define _mm256_mask_roundscale_ps(W, U, A, imm) \
(__m256)__builtin_ia32_rndscaleps_256_mask((__v8sf)(__m256)(A), (int)(imm), \
(__v8sf)(__m256)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_roundscale_ps(U, A, imm) __extension__ ({ \
+#define _mm256_maskz_roundscale_ps(U, A, imm) \
(__m256)__builtin_ia32_rndscaleps_256_mask((__v8sf)(__m256)(A), (int)(imm), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_scalef_pd (__m128d __A, __m128d __B) {
return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A,
(__v2df) __B,
@@ -3310,7 +3290,7 @@ _mm_scalef_pd (__m128d __A, __m128d __B) {
(__mmask8) -1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_scalef_pd (__m128d __W, __mmask8 __U, __m128d __A,
__m128d __B) {
return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A,
@@ -3319,7 +3299,7 @@ _mm_mask_scalef_pd (__m128d __W, __mmask8 __U, __m128d __A,
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_scalef_pd (__mmask8 __U, __m128d __A, __m128d __B) {
return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A,
(__v2df) __B,
@@ -3328,7 +3308,7 @@ _mm_maskz_scalef_pd (__mmask8 __U, __m128d __A, __m128d __B) {
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_scalef_pd (__m256d __A, __m256d __B) {
return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A,
(__v4df) __B,
@@ -3337,7 +3317,7 @@ _mm256_scalef_pd (__m256d __A, __m256d __B) {
(__mmask8) -1);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_scalef_pd (__m256d __W, __mmask8 __U, __m256d __A,
__m256d __B) {
return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A,
@@ -3346,7 +3326,7 @@ _mm256_mask_scalef_pd (__m256d __W, __mmask8 __U, __m256d __A,
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_scalef_pd (__mmask8 __U, __m256d __A, __m256d __B) {
return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A,
(__v4df) __B,
@@ -3355,7 +3335,7 @@ _mm256_maskz_scalef_pd (__mmask8 __U, __m256d __A, __m256d __B) {
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_scalef_ps (__m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -3364,7 +3344,7 @@ _mm_scalef_ps (__m128 __A, __m128 __B) {
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_scalef_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -3372,7 +3352,7 @@ _mm_mask_scalef_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_scalef_ps (__mmask8 __U, __m128 __A, __m128 __B) {
return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A,
(__v4sf) __B,
@@ -3381,7 +3361,7 @@ _mm_maskz_scalef_ps (__mmask8 __U, __m128 __A, __m128 __B) {
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_scalef_ps (__m256 __A, __m256 __B) {
return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A,
(__v8sf) __B,
@@ -3390,7 +3370,7 @@ _mm256_scalef_ps (__m256 __A, __m256 __B) {
(__mmask8) -1);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_scalef_ps (__m256 __W, __mmask8 __U, __m256 __A,
__m256 __B) {
return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A,
@@ -3399,7 +3379,7 @@ _mm256_mask_scalef_ps (__m256 __W, __mmask8 __U, __m256 __A,
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) {
return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A,
(__v8sf) __B,
@@ -3408,1160 +3388,1027 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) {
(__mmask8) __U);
}
-#define _mm_i64scatter_pd(addr, index, v1, scale) __extension__ ({ \
+#define _mm_i64scatter_pd(addr, index, v1, scale) \
__builtin_ia32_scatterdiv2df((double *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), \
- (__v2df)(__m128d)(v1), (int)(scale)); })
+ (__v2df)(__m128d)(v1), (int)(scale))
-#define _mm_mask_i64scatter_pd(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm_mask_i64scatter_pd(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv2df((double *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), \
- (__v2df)(__m128d)(v1), (int)(scale)); })
+ (__v2df)(__m128d)(v1), (int)(scale))
-#define _mm_i64scatter_epi64(addr, index, v1, scale) __extension__ ({ \
+#define _mm_i64scatter_epi64(addr, index, v1, scale) \
__builtin_ia32_scatterdiv2di((long long *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), \
- (__v2di)(__m128i)(v1), (int)(scale)); })
+ (__v2di)(__m128i)(v1), (int)(scale))
-#define _mm_mask_i64scatter_epi64(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm_mask_i64scatter_epi64(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv2di((long long *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), \
- (__v2di)(__m128i)(v1), (int)(scale)); })
+ (__v2di)(__m128i)(v1), (int)(scale))
-#define _mm256_i64scatter_pd(addr, index, v1, scale) __extension__ ({ \
+#define _mm256_i64scatter_pd(addr, index, v1, scale) \
__builtin_ia32_scatterdiv4df((double *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), \
- (__v4df)(__m256d)(v1), (int)(scale)); })
+ (__v4df)(__m256d)(v1), (int)(scale))
-#define _mm256_mask_i64scatter_pd(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm256_mask_i64scatter_pd(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv4df((double *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), \
- (__v4df)(__m256d)(v1), (int)(scale)); })
+ (__v4df)(__m256d)(v1), (int)(scale))
-#define _mm256_i64scatter_epi64(addr, index, v1, scale) __extension__ ({ \
+#define _mm256_i64scatter_epi64(addr, index, v1, scale) \
__builtin_ia32_scatterdiv4di((long long *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), \
- (__v4di)(__m256i)(v1), (int)(scale)); })
+ (__v4di)(__m256i)(v1), (int)(scale))
-#define _mm256_mask_i64scatter_epi64(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm256_mask_i64scatter_epi64(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv4di((long long *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), \
- (__v4di)(__m256i)(v1), (int)(scale)); })
+ (__v4di)(__m256i)(v1), (int)(scale))
-#define _mm_i64scatter_ps(addr, index, v1, scale) __extension__ ({ \
+#define _mm_i64scatter_ps(addr, index, v1, scale) \
__builtin_ia32_scatterdiv4sf((float *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), (__v4sf)(__m128)(v1), \
- (int)(scale)); })
+ (int)(scale))
-#define _mm_mask_i64scatter_ps(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm_mask_i64scatter_ps(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv4sf((float *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), (__v4sf)(__m128)(v1), \
- (int)(scale)); })
+ (int)(scale))
-#define _mm_i64scatter_epi32(addr, index, v1, scale) __extension__ ({ \
+#define _mm_i64scatter_epi32(addr, index, v1, scale) \
__builtin_ia32_scatterdiv4si((int *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), \
- (__v4si)(__m128i)(v1), (int)(scale)); })
+ (__v4si)(__m128i)(v1), (int)(scale))
-#define _mm_mask_i64scatter_epi32(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm_mask_i64scatter_epi32(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv4si((int *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), \
- (__v4si)(__m128i)(v1), (int)(scale)); })
+ (__v4si)(__m128i)(v1), (int)(scale))
-#define _mm256_i64scatter_ps(addr, index, v1, scale) __extension__ ({ \
+#define _mm256_i64scatter_ps(addr, index, v1, scale) \
__builtin_ia32_scatterdiv8sf((float *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), (__v4sf)(__m128)(v1), \
- (int)(scale)); })
+ (int)(scale))
-#define _mm256_mask_i64scatter_ps(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm256_mask_i64scatter_ps(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv8sf((float *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), (__v4sf)(__m128)(v1), \
- (int)(scale)); })
+ (int)(scale))
-#define _mm256_i64scatter_epi32(addr, index, v1, scale) __extension__ ({ \
+#define _mm256_i64scatter_epi32(addr, index, v1, scale) \
__builtin_ia32_scatterdiv8si((int *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), \
- (__v4si)(__m128i)(v1), (int)(scale)); })
+ (__v4si)(__m128i)(v1), (int)(scale))
-#define _mm256_mask_i64scatter_epi32(addr, mask, index, v1, scale) __extension__ ({ \
+#define _mm256_mask_i64scatter_epi32(addr, mask, index, v1, scale) \
__builtin_ia32_scatterdiv8si((int *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), \
- (__v4si)(__m128i)(v1), (int)(scale)); })
+ (__v4si)(__m128i)(v1), (int)(scale))
-#define _mm_i32scatter_pd(addr, index, v1, scale) __extension__ ({ \
+#define _mm_i32scatter_pd(addr, index, v1, scale) \
__builtin_ia32_scattersiv2df((double *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), \
- (__v2df)(__m128d)(v1), (int)(scale)); })
-
-#define _mm_mask_i32scatter_pd(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv2df((double *)(addr), (__mmask8)(mask), \
- (__v4si)(__m128i)(index), \
- (__v2df)(__m128d)(v1), (int)(scale)); })
-
-#define _mm_i32scatter_epi64(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv2di((long long *)(addr), (__mmask8)-1, \
- (__v4si)(__m128i)(index), \
- (__v2di)(__m128i)(v1), (int)(scale)); })
-
-#define _mm_mask_i32scatter_epi64(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv2di((long long *)(addr), (__mmask8)(mask), \
- (__v4si)(__m128i)(index), \
- (__v2di)(__m128i)(v1), (int)(scale)); })
-
-#define _mm256_i32scatter_pd(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4df((double *)(addr), (__mmask8)-1, \
- (__v4si)(__m128i)(index), \
- (__v4df)(__m256d)(v1), (int)(scale)); })
-
-#define _mm256_mask_i32scatter_pd(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4df((double *)(addr), (__mmask8)(mask), \
- (__v4si)(__m128i)(index), \
- (__v4df)(__m256d)(v1), (int)(scale)); })
-
-#define _mm256_i32scatter_epi64(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4di((long long *)(addr), (__mmask8)-1, \
- (__v4si)(__m128i)(index), \
- (__v4di)(__m256i)(v1), (int)(scale)); })
-
-#define _mm256_mask_i32scatter_epi64(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4di((long long *)(addr), (__mmask8)(mask), \
- (__v4si)(__m128i)(index), \
- (__v4di)(__m256i)(v1), (int)(scale)); })
-
-#define _mm_i32scatter_ps(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4sf((float *)(addr), (__mmask8)-1, \
- (__v4si)(__m128i)(index), (__v4sf)(__m128)(v1), \
- (int)(scale)); })
-
-#define _mm_mask_i32scatter_ps(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4sf((float *)(addr), (__mmask8)(mask), \
- (__v4si)(__m128i)(index), (__v4sf)(__m128)(v1), \
- (int)(scale)); })
-
-#define _mm_i32scatter_epi32(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4si((int *)(addr), (__mmask8)-1, \
- (__v4si)(__m128i)(index), \
- (__v4si)(__m128i)(v1), (int)(scale)); })
-
-#define _mm_mask_i32scatter_epi32(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv4si((int *)(addr), (__mmask8)(mask), \
- (__v4si)(__m128i)(index), \
- (__v4si)(__m128i)(v1), (int)(scale)); })
-
-#define _mm256_i32scatter_ps(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv8sf((float *)(addr), (__mmask8)-1, \
- (__v8si)(__m256i)(index), (__v8sf)(__m256)(v1), \
- (int)(scale)); })
-
-#define _mm256_mask_i32scatter_ps(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv8sf((float *)(addr), (__mmask8)(mask), \
- (__v8si)(__m256i)(index), (__v8sf)(__m256)(v1), \
- (int)(scale)); })
-
-#define _mm256_i32scatter_epi32(addr, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv8si((int *)(addr), (__mmask8)-1, \
- (__v8si)(__m256i)(index), \
- (__v8si)(__m256i)(v1), (int)(scale)); })
-
-#define _mm256_mask_i32scatter_epi32(addr, mask, index, v1, scale) __extension__ ({ \
- __builtin_ia32_scattersiv8si((int *)(addr), (__mmask8)(mask), \
- (__v8si)(__m256i)(index), \
- (__v8si)(__m256i)(v1), (int)(scale)); })
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_sqrt_pd(__m128d __W, __mmask8 __U, __m128d __A) {
- return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
- (__v2df)_mm_sqrt_pd(__A),
- (__v2df)__W);
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_maskz_sqrt_pd(__mmask8 __U, __m128d __A) {
- return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
- (__v2df)_mm_sqrt_pd(__A),
- (__v2df)_mm_setzero_pd());
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_mask_sqrt_pd(__m256d __W, __mmask8 __U, __m256d __A) {
- return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
- (__v4df)_mm256_sqrt_pd(__A),
- (__v4df)__W);
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_maskz_sqrt_pd(__mmask8 __U, __m256d __A) {
- return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
- (__v4df)_mm256_sqrt_pd(__A),
- (__v4df)_mm256_setzero_pd());
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_mask_sqrt_ps(__m128 __W, __mmask8 __U, __m128 __A) {
- return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
- (__v4sf)_mm_sqrt_ps(__A),
- (__v4sf)__W);
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_maskz_sqrt_ps(__mmask8 __U, __m128 __A) {
- return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
- (__v4sf)_mm_sqrt_ps(__A),
- (__v4sf)_mm_setzero_pd());
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask_sqrt_ps(__m256 __W, __mmask8 __U, __m256 __A) {
- return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
- (__v8sf)_mm256_sqrt_ps(__A),
- (__v8sf)__W);
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_maskz_sqrt_ps(__mmask8 __U, __m256 __A) {
- return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
- (__v8sf)_mm256_sqrt_ps(__A),
- (__v8sf)_mm256_setzero_ps());
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_sub_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
- (__v2df)_mm_sub_pd(__A, __B),
- (__v2df)__W);
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_maskz_sub_pd(__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
- (__v2df)_mm_sub_pd(__A, __B),
- (__v2df)_mm_setzero_pd());
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_mask_sub_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
- (__v4df)_mm256_sub_pd(__A, __B),
- (__v4df)__W);
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_maskz_sub_pd(__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
- (__v4df)_mm256_sub_pd(__A, __B),
- (__v4df)_mm256_setzero_pd());
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_mask_sub_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
- (__v4sf)_mm_sub_ps(__A, __B),
- (__v4sf)__W);
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_maskz_sub_ps(__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
- (__v4sf)_mm_sub_ps(__A, __B),
- (__v4sf)_mm_setzero_ps());
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask_sub_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
- (__v8sf)_mm256_sub_ps(__A, __B),
- (__v8sf)__W);
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_maskz_sub_ps(__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
- (__v8sf)_mm256_sub_ps(__A, __B),
- (__v8sf)_mm256_setzero_ps());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask2_permutex2var_epi32 (__m128i __A, __m128i __I, __mmask8 __U,
- __m128i __B) {
- return (__m128i) __builtin_ia32_vpermi2vard128_mask ((__v4si) __A,
- (__v4si) __I
- /* idx */ ,
- (__v4si) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask2_permutex2var_epi32 (__m256i __A, __m256i __I,
- __mmask8 __U, __m256i __B) {
- return (__m256i) __builtin_ia32_vpermi2vard256_mask ((__v8si) __A,
- (__v8si) __I
- /* idx */ ,
- (__v8si) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask2_permutex2var_pd (__m128d __A, __m128i __I, __mmask8 __U,
- __m128d __B) {
- return (__m128d) __builtin_ia32_vpermi2varpd128_mask ((__v2df) __A,
- (__v2di) __I
- /* idx */ ,
- (__v2df) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_mask2_permutex2var_pd (__m256d __A, __m256i __I, __mmask8 __U,
- __m256d __B) {
- return (__m256d) __builtin_ia32_vpermi2varpd256_mask ((__v4df) __A,
- (__v4di) __I
- /* idx */ ,
- (__v4df) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_mask2_permutex2var_ps (__m128 __A, __m128i __I, __mmask8 __U,
- __m128 __B) {
- return (__m128) __builtin_ia32_vpermi2varps128_mask ((__v4sf) __A,
- (__v4si) __I
- /* idx */ ,
- (__v4sf) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask2_permutex2var_ps (__m256 __A, __m256i __I, __mmask8 __U,
- __m256 __B) {
- return (__m256) __builtin_ia32_vpermi2varps256_mask ((__v8sf) __A,
- (__v8si) __I
- /* idx */ ,
- (__v8sf) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask2_permutex2var_epi64 (__m128i __A, __m128i __I, __mmask8 __U,
- __m128i __B) {
- return (__m128i) __builtin_ia32_vpermi2varq128_mask ((__v2di) __A,
- (__v2di) __I
- /* idx */ ,
- (__v2di) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask2_permutex2var_epi64 (__m256i __A, __m256i __I,
- __mmask8 __U, __m256i __B) {
- return (__m256i) __builtin_ia32_vpermi2varq256_mask ((__v4di) __A,
- (__v4di) __I
- /* idx */ ,
- (__v4di) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_permutex2var_epi32 (__m128i __A, __m128i __I, __m128i __B) {
- return (__m128i) __builtin_ia32_vpermt2vard128_mask ((__v4si) __I
- /* idx */ ,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_permutex2var_epi32 (__m128i __A, __mmask8 __U, __m128i __I,
- __m128i __B) {
- return (__m128i) __builtin_ia32_vpermt2vard128_mask ((__v4si) __I
- /* idx */ ,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_permutex2var_epi32 (__mmask8 __U, __m128i __A, __m128i __I,
- __m128i __B) {
- return (__m128i) __builtin_ia32_vpermt2vard128_maskz ((__v4si) __I
- /* idx */ ,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_permutex2var_epi32 (__m256i __A, __m256i __I, __m256i __B) {
- return (__m256i) __builtin_ia32_vpermt2vard256_mask ((__v8si) __I
- /* idx */ ,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_permutex2var_epi32 (__m256i __A, __mmask8 __U, __m256i __I,
- __m256i __B) {
- return (__m256i) __builtin_ia32_vpermt2vard256_mask ((__v8si) __I
- /* idx */ ,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_permutex2var_epi32 (__mmask8 __U, __m256i __A,
- __m256i __I, __m256i __B) {
- return (__m256i) __builtin_ia32_vpermt2vard256_maskz ((__v8si) __I
- /* idx */ ,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_permutex2var_pd (__m128d __A, __m128i __I, __m128d __B) {
- return (__m128d) __builtin_ia32_vpermt2varpd128_mask ((__v2di) __I
- /* idx */ ,
- (__v2df) __A,
- (__v2df) __B,
- (__mmask8) -
- 1);
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_permutex2var_pd (__m128d __A, __mmask8 __U, __m128i __I,
- __m128d __B) {
- return (__m128d) __builtin_ia32_vpermt2varpd128_mask ((__v2di) __I
- /* idx */ ,
- (__v2df) __A,
- (__v2df) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_maskz_permutex2var_pd (__mmask8 __U, __m128d __A, __m128i __I,
- __m128d __B) {
- return (__m128d) __builtin_ia32_vpermt2varpd128_maskz ((__v2di) __I
- /* idx */ ,
- (__v2df) __A,
- (__v2df) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_permutex2var_pd (__m256d __A, __m256i __I, __m256d __B) {
- return (__m256d) __builtin_ia32_vpermt2varpd256_mask ((__v4di) __I
- /* idx */ ,
- (__v4df) __A,
- (__v4df) __B,
- (__mmask8) -
- 1);
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_mask_permutex2var_pd (__m256d __A, __mmask8 __U, __m256i __I,
- __m256d __B) {
- return (__m256d) __builtin_ia32_vpermt2varpd256_mask ((__v4di) __I
- /* idx */ ,
- (__v4df) __A,
- (__v4df) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_maskz_permutex2var_pd (__mmask8 __U, __m256d __A, __m256i __I,
- __m256d __B) {
- return (__m256d) __builtin_ia32_vpermt2varpd256_maskz ((__v4di) __I
- /* idx */ ,
- (__v4df) __A,
- (__v4df) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_permutex2var_ps (__m128 __A, __m128i __I, __m128 __B) {
- return (__m128) __builtin_ia32_vpermt2varps128_mask ((__v4si) __I
- /* idx */ ,
- (__v4sf) __A,
- (__v4sf) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_mask_permutex2var_ps (__m128 __A, __mmask8 __U, __m128i __I,
- __m128 __B) {
- return (__m128) __builtin_ia32_vpermt2varps128_mask ((__v4si) __I
- /* idx */ ,
- (__v4sf) __A,
- (__v4sf) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_maskz_permutex2var_ps (__mmask8 __U, __m128 __A, __m128i __I,
- __m128 __B) {
- return (__m128) __builtin_ia32_vpermt2varps128_maskz ((__v4si) __I
- /* idx */ ,
- (__v4sf) __A,
- (__v4sf) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_permutex2var_ps (__m256 __A, __m256i __I, __m256 __B) {
- return (__m256) __builtin_ia32_vpermt2varps256_mask ((__v8si) __I
- /* idx */ ,
- (__v8sf) __A,
- (__v8sf) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask_permutex2var_ps (__m256 __A, __mmask8 __U, __m256i __I,
- __m256 __B) {
- return (__m256) __builtin_ia32_vpermt2varps256_mask ((__v8si) __I
- /* idx */ ,
- (__v8sf) __A,
- (__v8sf) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_maskz_permutex2var_ps (__mmask8 __U, __m256 __A, __m256i __I,
- __m256 __B) {
- return (__m256) __builtin_ia32_vpermt2varps256_maskz ((__v8si) __I
- /* idx */ ,
- (__v8sf) __A,
- (__v8sf) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_permutex2var_epi64 (__m128i __A, __m128i __I, __m128i __B) {
- return (__m128i) __builtin_ia32_vpermt2varq128_mask ((__v2di) __I
- /* idx */ ,
- (__v2di) __A,
- (__v2di) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_permutex2var_epi64 (__m128i __A, __mmask8 __U, __m128i __I,
- __m128i __B) {
- return (__m128i) __builtin_ia32_vpermt2varq128_mask ((__v2di) __I
- /* idx */ ,
- (__v2di) __A,
- (__v2di) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_permutex2var_epi64 (__mmask8 __U, __m128i __A, __m128i __I,
- __m128i __B) {
- return (__m128i) __builtin_ia32_vpermt2varq128_maskz ((__v2di) __I
- /* idx */ ,
- (__v2di) __A,
- (__v2di) __B,
- (__mmask8)
- __U);
-}
-
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_permutex2var_epi64 (__m256i __A, __m256i __I, __m256i __B) {
- return (__m256i) __builtin_ia32_vpermt2varq256_mask ((__v4di) __I
- /* idx */ ,
- (__v4di) __A,
- (__v4di) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_permutex2var_epi64 (__m256i __A, __mmask8 __U, __m256i __I,
- __m256i __B) {
- return (__m256i) __builtin_ia32_vpermt2varq256_mask ((__v4di) __I
- /* idx */ ,
- (__v4di) __A,
- (__v4di) __B,
- (__mmask8) __U);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_permutex2var_epi64 (__mmask8 __U, __m256i __A,
- __m256i __I, __m256i __B) {
- return (__m256i) __builtin_ia32_vpermt2varq256_maskz ((__v4di) __I
- /* idx */ ,
- (__v4di) __A,
- (__v4di) __B,
- (__mmask8)
- __U);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi8_epi32(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepi8_epi32(__A),
- (__v4si)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi8_epi32(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepi8_epi32(__A),
- (__v4si)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepi8_epi32 (__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepi8_epi32(__A),
- (__v8si)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi8_epi32 (__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepi8_epi32(__A),
- (__v8si)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi8_epi64(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepi8_epi64(__A),
- (__v2di)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepi8_epi64(__A),
- (__v2di)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepi8_epi64(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepi8_epi64(__A),
- (__v4di)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepi8_epi64(__A),
- (__v4di)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi32_epi64(__m128i __W, __mmask8 __U, __m128i __X)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepi32_epi64(__X),
- (__v2di)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepi32_epi64(__X),
- (__v2di)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepi32_epi64(__m256i __W, __mmask8 __U, __m128i __X)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepi32_epi64(__X),
- (__v4di)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepi32_epi64(__X),
- (__v4di)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi16_epi32(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepi16_epi32(__A),
- (__v4si)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi16_epi32(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepi16_epi32(__A),
- (__v4si)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepi16_epi32(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepi16_epi32(__A),
- (__v8si)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi16_epi32 (__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepi16_epi32(__A),
- (__v8si)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi16_epi64(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepi16_epi64(__A),
- (__v2di)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepi16_epi64(__A),
- (__v2di)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepi16_epi64(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepi16_epi64(__A),
- (__v4di)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepi16_epi64(__A),
- (__v4di)_mm256_setzero_si256());
-}
-
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepu8_epi32(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepu8_epi32(__A),
- (__v4si)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepu8_epi32(__A),
- (__v4si)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepu8_epi32(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepu8_epi32(__A),
- (__v8si)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepu8_epi32(__A),
- (__v8si)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepu8_epi64(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepu8_epi64(__A),
- (__v2di)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepu8_epi64(__A),
- (__v2di)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepu8_epi64(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepu8_epi64(__A),
- (__v4di)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepu8_epi64(__A),
- (__v4di)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepu32_epi64(__m128i __W, __mmask8 __U, __m128i __X)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepu32_epi64(__X),
- (__v2di)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepu32_epi64(__X),
- (__v2di)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepu32_epi64(__m256i __W, __mmask8 __U, __m128i __X)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepu32_epi64(__X),
- (__v4di)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepu32_epi64(__X),
- (__v4di)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepu16_epi32(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepu16_epi32(__A),
- (__v4si)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_cvtepu16_epi32(__A),
- (__v4si)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepu16_epi32(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepu16_epi32(__A),
- (__v8si)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_cvtepu16_epi32(__A),
- (__v8si)_mm256_setzero_si256());
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepu16_epi64(__m128i __W, __mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepu16_epi64(__A),
- (__v2di)__W);
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_cvtepu16_epi64(__A),
- (__v2di)_mm_setzero_si128());
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepu16_epi64(__m256i __W, __mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepu16_epi64(__A),
- (__v4di)__W);
-}
-
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
-{
- return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_cvtepu16_epi64(__A),
- (__v4di)_mm256_setzero_si256());
-}
-
-
-#define _mm_rol_epi32(a, b) __extension__ ({\
- (__m128i)__builtin_ia32_prold128_mask((__v4si)(__m128i)(a), (int)(b), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)-1); })
-
-#define _mm_mask_rol_epi32(w, u, a, b) __extension__ ({\
- (__m128i)__builtin_ia32_prold128_mask((__v4si)(__m128i)(a), (int)(b), \
- (__v4si)(__m128i)(w), (__mmask8)(u)); })
-
-#define _mm_maskz_rol_epi32(u, a, b) __extension__ ({\
- (__m128i)__builtin_ia32_prold128_mask((__v4si)(__m128i)(a), (int)(b), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(u)); })
-
-#define _mm256_rol_epi32(a, b) __extension__ ({\
- (__m256i)__builtin_ia32_prold256_mask((__v8si)(__m256i)(a), (int)(b), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1); })
-
-#define _mm256_mask_rol_epi32(w, u, a, b) __extension__ ({\
- (__m256i)__builtin_ia32_prold256_mask((__v8si)(__m256i)(a), (int)(b), \
- (__v8si)(__m256i)(w), (__mmask8)(u)); })
-
-#define _mm256_maskz_rol_epi32(u, a, b) __extension__ ({\
- (__m256i)__builtin_ia32_prold256_mask((__v8si)(__m256i)(a), (int)(b), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(u)); })
-
-#define _mm_rol_epi64(a, b) __extension__ ({\
- (__m128i)__builtin_ia32_prolq128_mask((__v2di)(__m128i)(a), (int)(b), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)-1); })
-
-#define _mm_mask_rol_epi64(w, u, a, b) __extension__ ({\
- (__m128i)__builtin_ia32_prolq128_mask((__v2di)(__m128i)(a), (int)(b), \
- (__v2di)(__m128i)(w), (__mmask8)(u)); })
-
-#define _mm_maskz_rol_epi64(u, a, b) __extension__ ({\
- (__m128i)__builtin_ia32_prolq128_mask((__v2di)(__m128i)(a), (int)(b), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)(u)); })
-
-#define _mm256_rol_epi64(a, b) __extension__ ({\
- (__m256i)__builtin_ia32_prolq256_mask((__v4di)(__m256i)(a), (int)(b), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)-1); })
-
-#define _mm256_mask_rol_epi64(w, u, a, b) __extension__ ({\
- (__m256i)__builtin_ia32_prolq256_mask((__v4di)(__m256i)(a), (int)(b), \
- (__v4di)(__m256i)(w), (__mmask8)(u)); })
-
-#define _mm256_maskz_rol_epi64(u, a, b) __extension__ ({\
- (__m256i)__builtin_ia32_prolq256_mask((__v4di)(__m256i)(a), (int)(b), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(u)); })
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+ (__v2df)(__m128d)(v1), (int)(scale))
+
+#define _mm_mask_i32scatter_pd(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv2df((double *)(addr), (__mmask8)(mask), \
+ (__v4si)(__m128i)(index), \
+ (__v2df)(__m128d)(v1), (int)(scale))
+
+#define _mm_i32scatter_epi64(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv2di((long long *)(addr), (__mmask8)-1, \
+ (__v4si)(__m128i)(index), \
+ (__v2di)(__m128i)(v1), (int)(scale))
+
+#define _mm_mask_i32scatter_epi64(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv2di((long long *)(addr), (__mmask8)(mask), \
+ (__v4si)(__m128i)(index), \
+ (__v2di)(__m128i)(v1), (int)(scale))
+
+#define _mm256_i32scatter_pd(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv4df((double *)(addr), (__mmask8)-1, \
+ (__v4si)(__m128i)(index), \
+ (__v4df)(__m256d)(v1), (int)(scale))
+
+#define _mm256_mask_i32scatter_pd(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv4df((double *)(addr), (__mmask8)(mask), \
+ (__v4si)(__m128i)(index), \
+ (__v4df)(__m256d)(v1), (int)(scale))
+
+#define _mm256_i32scatter_epi64(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv4di((long long *)(addr), (__mmask8)-1, \
+ (__v4si)(__m128i)(index), \
+ (__v4di)(__m256i)(v1), (int)(scale))
+
+#define _mm256_mask_i32scatter_epi64(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv4di((long long *)(addr), (__mmask8)(mask), \
+ (__v4si)(__m128i)(index), \
+ (__v4di)(__m256i)(v1), (int)(scale))
+
+#define _mm_i32scatter_ps(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv4sf((float *)(addr), (__mmask8)-1, \
+ (__v4si)(__m128i)(index), (__v4sf)(__m128)(v1), \
+ (int)(scale))
+
+#define _mm_mask_i32scatter_ps(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv4sf((float *)(addr), (__mmask8)(mask), \
+ (__v4si)(__m128i)(index), (__v4sf)(__m128)(v1), \
+ (int)(scale))
+
+#define _mm_i32scatter_epi32(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv4si((int *)(addr), (__mmask8)-1, \
+ (__v4si)(__m128i)(index), \
+ (__v4si)(__m128i)(v1), (int)(scale))
+
+#define _mm_mask_i32scatter_epi32(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv4si((int *)(addr), (__mmask8)(mask), \
+ (__v4si)(__m128i)(index), \
+ (__v4si)(__m128i)(v1), (int)(scale))
+
+#define _mm256_i32scatter_ps(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv8sf((float *)(addr), (__mmask8)-1, \
+ (__v8si)(__m256i)(index), (__v8sf)(__m256)(v1), \
+ (int)(scale))
+
+#define _mm256_mask_i32scatter_ps(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv8sf((float *)(addr), (__mmask8)(mask), \
+ (__v8si)(__m256i)(index), (__v8sf)(__m256)(v1), \
+ (int)(scale))
+
+#define _mm256_i32scatter_epi32(addr, index, v1, scale) \
+ __builtin_ia32_scattersiv8si((int *)(addr), (__mmask8)-1, \
+ (__v8si)(__m256i)(index), \
+ (__v8si)(__m256i)(v1), (int)(scale))
+
+#define _mm256_mask_i32scatter_epi32(addr, mask, index, v1, scale) \
+ __builtin_ia32_scattersiv8si((int *)(addr), (__mmask8)(mask), \
+ (__v8si)(__m256i)(index), \
+ (__v8si)(__m256i)(v1), (int)(scale))
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_mask_sqrt_pd(__m128d __W, __mmask8 __U, __m128d __A) {
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_sqrt_pd(__A),
+ (__v2df)__W);
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_maskz_sqrt_pd(__mmask8 __U, __m128d __A) {
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_sqrt_pd(__A),
+ (__v2df)_mm_setzero_pd());
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_mask_sqrt_pd(__m256d __W, __mmask8 __U, __m256d __A) {
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_sqrt_pd(__A),
+ (__v4df)__W);
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_maskz_sqrt_pd(__mmask8 __U, __m256d __A) {
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_sqrt_pd(__A),
+ (__v4df)_mm256_setzero_pd());
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_mask_sqrt_ps(__m128 __W, __mmask8 __U, __m128 __A) {
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_sqrt_ps(__A),
+ (__v4sf)__W);
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_maskz_sqrt_ps(__mmask8 __U, __m128 __A) {
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_sqrt_ps(__A),
+ (__v4sf)_mm_setzero_ps());
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_mask_sqrt_ps(__m256 __W, __mmask8 __U, __m256 __A) {
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_sqrt_ps(__A),
+ (__v8sf)__W);
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_maskz_sqrt_ps(__mmask8 __U, __m256 __A) {
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_sqrt_ps(__A),
+ (__v8sf)_mm256_setzero_ps());
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_mask_sub_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_sub_pd(__A, __B),
+ (__v2df)__W);
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_maskz_sub_pd(__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_sub_pd(__A, __B),
+ (__v2df)_mm_setzero_pd());
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_mask_sub_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_sub_pd(__A, __B),
+ (__v4df)__W);
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_maskz_sub_pd(__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_sub_pd(__A, __B),
+ (__v4df)_mm256_setzero_pd());
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_mask_sub_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_sub_ps(__A, __B),
+ (__v4sf)__W);
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_maskz_sub_ps(__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_sub_ps(__A, __B),
+ (__v4sf)_mm_setzero_ps());
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_mask_sub_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_sub_ps(__A, __B),
+ (__v8sf)__W);
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_maskz_sub_ps(__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_sub_ps(__A, __B),
+ (__v8sf)_mm256_setzero_ps());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_permutex2var_epi32(__m128i __A, __m128i __I, __m128i __B) {
+ return (__m128i)__builtin_ia32_vpermi2vard128((__v4si) __A, (__v4si)__I,
+ (__v4si)__B);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_permutex2var_epi32(__m128i __A, __mmask8 __U, __m128i __I,
+ __m128i __B) {
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_permutex2var_epi32(__A, __I, __B),
+ (__v4si)__A);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask2_permutex2var_epi32(__m128i __A, __m128i __I, __mmask8 __U,
+ __m128i __B) {
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_permutex2var_epi32(__A, __I, __B),
+ (__v4si)__I);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_permutex2var_epi32(__mmask8 __U, __m128i __A, __m128i __I,
+ __m128i __B) {
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_permutex2var_epi32(__A, __I, __B),
+ (__v4si)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_permutex2var_epi32(__m256i __A, __m256i __I, __m256i __B) {
+ return (__m256i)__builtin_ia32_vpermi2vard256((__v8si)__A, (__v8si) __I,
+ (__v8si) __B);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_permutex2var_epi32(__m256i __A, __mmask8 __U, __m256i __I,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_permutex2var_epi32(__A, __I, __B),
+ (__v8si)__A);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask2_permutex2var_epi32(__m256i __A, __m256i __I, __mmask8 __U,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_permutex2var_epi32(__A, __I, __B),
+ (__v8si)__I);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_permutex2var_epi32(__mmask8 __U, __m256i __A, __m256i __I,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_permutex2var_epi32(__A, __I, __B),
+ (__v8si)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_permutex2var_pd(__m128d __A, __m128i __I, __m128d __B) {
+ return (__m128d)__builtin_ia32_vpermi2varpd128((__v2df)__A, (__v2di)__I,
+ (__v2df)__B);
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_mask_permutex2var_pd(__m128d __A, __mmask8 __U, __m128i __I, __m128d __B) {
+ return (__m128d)__builtin_ia32_selectpd_128(__U,
+ (__v2df)_mm_permutex2var_pd(__A, __I, __B),
+ (__v2df)__A);
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_mask2_permutex2var_pd(__m128d __A, __m128i __I, __mmask8 __U, __m128d __B) {
+ return (__m128d)__builtin_ia32_selectpd_128(__U,
+ (__v2df)_mm_permutex2var_pd(__A, __I, __B),
+ (__v2df)(__m128d)__I);
+ }
+
+ static __inline__ __m128d __DEFAULT_FN_ATTRS128
+ _mm_maskz_permutex2var_pd(__mmask8 __U, __m128d __A, __m128i __I, __m128d __B) {
+ return (__m128d)__builtin_ia32_selectpd_128(__U,
+ (__v2df)_mm_permutex2var_pd(__A, __I, __B),
+ (__v2df)_mm_setzero_pd());
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_permutex2var_pd(__m256d __A, __m256i __I, __m256d __B) {
+ return (__m256d)__builtin_ia32_vpermi2varpd256((__v4df)__A, (__v4di)__I,
+ (__v4df)__B);
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_mask_permutex2var_pd(__m256d __A, __mmask8 __U, __m256i __I,
+ __m256d __B) {
+ return (__m256d)__builtin_ia32_selectpd_256(__U,
+ (__v4df)_mm256_permutex2var_pd(__A, __I, __B),
+ (__v4df)__A);
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_mask2_permutex2var_pd(__m256d __A, __m256i __I, __mmask8 __U,
+ __m256d __B) {
+ return (__m256d)__builtin_ia32_selectpd_256(__U,
+ (__v4df)_mm256_permutex2var_pd(__A, __I, __B),
+ (__v4df)(__m256d)__I);
+ }
+
+ static __inline__ __m256d __DEFAULT_FN_ATTRS256
+ _mm256_maskz_permutex2var_pd(__mmask8 __U, __m256d __A, __m256i __I,
+ __m256d __B) {
+ return (__m256d)__builtin_ia32_selectpd_256(__U,
+ (__v4df)_mm256_permutex2var_pd(__A, __I, __B),
+ (__v4df)_mm256_setzero_pd());
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_permutex2var_ps(__m128 __A, __m128i __I, __m128 __B) {
+ return (__m128)__builtin_ia32_vpermi2varps128((__v4sf)__A, (__v4si)__I,
+ (__v4sf)__B);
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_mask_permutex2var_ps(__m128 __A, __mmask8 __U, __m128i __I, __m128 __B) {
+ return (__m128)__builtin_ia32_selectps_128(__U,
+ (__v4sf)_mm_permutex2var_ps(__A, __I, __B),
+ (__v4sf)__A);
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_mask2_permutex2var_ps(__m128 __A, __m128i __I, __mmask8 __U, __m128 __B) {
+ return (__m128)__builtin_ia32_selectps_128(__U,
+ (__v4sf)_mm_permutex2var_ps(__A, __I, __B),
+ (__v4sf)(__m128)__I);
+ }
+
+ static __inline__ __m128 __DEFAULT_FN_ATTRS128
+ _mm_maskz_permutex2var_ps(__mmask8 __U, __m128 __A, __m128i __I, __m128 __B) {
+ return (__m128)__builtin_ia32_selectps_128(__U,
+ (__v4sf)_mm_permutex2var_ps(__A, __I, __B),
+ (__v4sf)_mm_setzero_ps());
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_permutex2var_ps(__m256 __A, __m256i __I, __m256 __B) {
+ return (__m256)__builtin_ia32_vpermi2varps256((__v8sf)__A, (__v8si)__I,
+ (__v8sf) __B);
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_mask_permutex2var_ps(__m256 __A, __mmask8 __U, __m256i __I, __m256 __B) {
+ return (__m256)__builtin_ia32_selectps_256(__U,
+ (__v8sf)_mm256_permutex2var_ps(__A, __I, __B),
+ (__v8sf)__A);
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_mask2_permutex2var_ps(__m256 __A, __m256i __I, __mmask8 __U,
+ __m256 __B) {
+ return (__m256)__builtin_ia32_selectps_256(__U,
+ (__v8sf)_mm256_permutex2var_ps(__A, __I, __B),
+ (__v8sf)(__m256)__I);
+ }
+
+ static __inline__ __m256 __DEFAULT_FN_ATTRS256
+ _mm256_maskz_permutex2var_ps(__mmask8 __U, __m256 __A, __m256i __I,
+ __m256 __B) {
+ return (__m256)__builtin_ia32_selectps_256(__U,
+ (__v8sf)_mm256_permutex2var_ps(__A, __I, __B),
+ (__v8sf)_mm256_setzero_ps());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_permutex2var_epi64(__m128i __A, __m128i __I, __m128i __B) {
+ return (__m128i)__builtin_ia32_vpermi2varq128((__v2di)__A, (__v2di)__I,
+ (__v2di)__B);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_permutex2var_epi64(__m128i __A, __mmask8 __U, __m128i __I,
+ __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_permutex2var_epi64(__A, __I, __B),
+ (__v2di)__A);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask2_permutex2var_epi64(__m128i __A, __m128i __I, __mmask8 __U,
+ __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_permutex2var_epi64(__A, __I, __B),
+ (__v2di)__I);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_permutex2var_epi64(__mmask8 __U, __m128i __A, __m128i __I,
+ __m128i __B) {
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_permutex2var_epi64(__A, __I, __B),
+ (__v2di)_mm_setzero_si128());
+ }
+
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_permutex2var_epi64(__m256i __A, __m256i __I, __m256i __B) {
+ return (__m256i)__builtin_ia32_vpermi2varq256((__v4di)__A, (__v4di) __I,
+ (__v4di) __B);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_permutex2var_epi64(__m256i __A, __mmask8 __U, __m256i __I,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_permutex2var_epi64(__A, __I, __B),
+ (__v4di)__A);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask2_permutex2var_epi64(__m256i __A, __m256i __I, __mmask8 __U,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_permutex2var_epi64(__A, __I, __B),
+ (__v4di)__I);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_permutex2var_epi64(__mmask8 __U, __m256i __A, __m256i __I,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_permutex2var_epi64(__A, __I, __B),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepi8_epi32(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepi8_epi32(__A),
+ (__v4si)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepi8_epi32(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepi8_epi32(__A),
+ (__v4si)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepi8_epi32 (__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepi8_epi32(__A),
+ (__v8si)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepi8_epi32 (__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepi8_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepi8_epi64(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepi8_epi64(__A),
+ (__v2di)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepi8_epi64(__A),
+ (__v2di)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepi8_epi64(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepi8_epi64(__A),
+ (__v4di)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepi8_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepi32_epi64(__m128i __W, __mmask8 __U, __m128i __X)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepi32_epi64(__X),
+ (__v2di)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepi32_epi64(__X),
+ (__v2di)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepi32_epi64(__m256i __W, __mmask8 __U, __m128i __X)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepi32_epi64(__X),
+ (__v4di)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepi32_epi64(__X),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepi16_epi32(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepi16_epi32(__A),
+ (__v4si)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepi16_epi32(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepi16_epi32(__A),
+ (__v4si)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepi16_epi32(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepi16_epi32(__A),
+ (__v8si)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepi16_epi32 (__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepi16_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepi16_epi64(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepi16_epi64(__A),
+ (__v2di)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepi16_epi64(__A),
+ (__v2di)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepi16_epi64(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepi16_epi64(__A),
+ (__v4di)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepi16_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepu8_epi32(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepu8_epi32(__A),
+ (__v4si)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepu8_epi32(__A),
+ (__v4si)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepu8_epi32(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepu8_epi32(__A),
+ (__v8si)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepu8_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepu8_epi64(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepu8_epi64(__A),
+ (__v2di)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepu8_epi64(__A),
+ (__v2di)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepu8_epi64(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu8_epi64(__A),
+ (__v4di)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu8_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepu32_epi64(__m128i __W, __mmask8 __U, __m128i __X)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepu32_epi64(__X),
+ (__v2di)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepu32_epi64(__X),
+ (__v2di)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepu32_epi64(__m256i __W, __mmask8 __U, __m128i __X)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu32_epi64(__X),
+ (__v4di)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu32_epi64(__X),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepu16_epi32(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepu16_epi32(__A),
+ (__v4si)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_cvtepu16_epi32(__A),
+ (__v4si)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepu16_epi32(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepu16_epi32(__A),
+ (__v8si)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_cvtepu16_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_mask_cvtepu16_epi64(__m128i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepu16_epi64(__A),
+ (__v2di)__W);
+ }
+
+ static __inline__ __m128i __DEFAULT_FN_ATTRS128
+ _mm_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_cvtepu16_epi64(__A),
+ (__v2di)_mm_setzero_si128());
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_mask_cvtepu16_epi64(__m256i __W, __mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu16_epi64(__A),
+ (__v4di)__W);
+ }
+
+ static __inline__ __m256i __DEFAULT_FN_ATTRS256
+ _mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
+ {
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu16_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
+ }
+
+
+#define _mm_rol_epi32(a, b) \
+ (__m128i)__builtin_ia32_prold128((__v4si)(__m128i)(a), (int)(b))
+
+#define _mm_mask_rol_epi32(w, u, a, b) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \
+ (__v4si)_mm_rol_epi32((a), (b)), \
+ (__v4si)(__m128i)(w))
+
+#define _mm_maskz_rol_epi32(u, a, b) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \
+ (__v4si)_mm_rol_epi32((a), (b)), \
+ (__v4si)_mm_setzero_si128())
+
+#define _mm256_rol_epi32(a, b) \
+ (__m256i)__builtin_ia32_prold256((__v8si)(__m256i)(a), (int)(b))
+
+#define _mm256_mask_rol_epi32(w, u, a, b) \
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \
+ (__v8si)_mm256_rol_epi32((a), (b)), \
+ (__v8si)(__m256i)(w))
+
+#define _mm256_maskz_rol_epi32(u, a, b) \
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \
+ (__v8si)_mm256_rol_epi32((a), (b)), \
+ (__v8si)_mm256_setzero_si256())
+
+#define _mm_rol_epi64(a, b) \
+ (__m128i)__builtin_ia32_prolq128((__v2di)(__m128i)(a), (int)(b))
+
+#define _mm_mask_rol_epi64(w, u, a, b) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \
+ (__v2di)_mm_rol_epi64((a), (b)), \
+ (__v2di)(__m128i)(w))
+
+#define _mm_maskz_rol_epi64(u, a, b) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \
+ (__v2di)_mm_rol_epi64((a), (b)), \
+ (__v2di)_mm_setzero_si128())
+
+#define _mm256_rol_epi64(a, b) \
+ (__m256i)__builtin_ia32_prolq256((__v4di)(__m256i)(a), (int)(b))
+
+#define _mm256_mask_rol_epi64(w, u, a, b) \
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \
+ (__v4di)_mm256_rol_epi64((a), (b)), \
+ (__v4di)(__m256i)(w))
+
+#define _mm256_maskz_rol_epi64(u, a, b) \
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \
+ (__v4di)_mm256_rol_epi64((a), (b)), \
+ (__v4di)_mm256_setzero_si256())
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_rolv_epi32 (__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_prolvd128((__v4si)__A, (__v4si)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_rolv_epi32(__A, __B),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_rolv_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_rolv_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_rolv_epi32 (__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_prolvd256((__v8si)__A, (__v8si)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_rolv_epi32(__A, __B),
+ (__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_rolv_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_rolv_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_rolv_epi64 (__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_prolvq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_rolv_epi64(__A, __B),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_rolv_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_rolv_epi64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_rolv_epi64 (__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_prolvq256((__v4di)__A, (__v4di)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_rolv_epi64(__A, __B),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_rolv_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_rolv_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-#define _mm_ror_epi32(A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_prord128_mask((__v4si)(__m128i)(A), (int)(B), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)-1); })
+#define _mm_ror_epi32(a, b) \
+ (__m128i)__builtin_ia32_prord128((__v4si)(__m128i)(a), (int)(b))
-#define _mm_mask_ror_epi32(W, U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_prord128_mask((__v4si)(__m128i)(A), (int)(B), \
- (__v4si)(__m128i)(W), (__mmask8)(U)); })
+#define _mm_mask_ror_epi32(w, u, a, b) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \
+ (__v4si)_mm_ror_epi32((a), (b)), \
+ (__v4si)(__m128i)(w))
-#define _mm_maskz_ror_epi32(U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_prord128_mask((__v4si)(__m128i)(A), (int)(B), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+#define _mm_maskz_ror_epi32(u, a, b) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \
+ (__v4si)_mm_ror_epi32((a), (b)), \
+ (__v4si)_mm_setzero_si128())
-#define _mm256_ror_epi32(A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_prord256_mask((__v8si)(__m256i)(A), (int)(B), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+#define _mm256_ror_epi32(a, b) \
+ (__m256i)__builtin_ia32_prord256((__v8si)(__m256i)(a), (int)(b))
-#define _mm256_mask_ror_epi32(W, U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_prord256_mask((__v8si)(__m256i)(A), (int)(B), \
- (__v8si)(__m256i)(W), (__mmask8)(U)); })
+#define _mm256_mask_ror_epi32(w, u, a, b) \
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \
+ (__v8si)_mm256_ror_epi32((a), (b)), \
+ (__v8si)(__m256i)(w))
-#define _mm256_maskz_ror_epi32(U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_prord256_mask((__v8si)(__m256i)(A), (int)(B), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+#define _mm256_maskz_ror_epi32(u, a, b) \
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \
+ (__v8si)_mm256_ror_epi32((a), (b)), \
+ (__v8si)_mm256_setzero_si256())
-#define _mm_ror_epi64(A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_prorq128_mask((__v2di)(__m128i)(A), (int)(B), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)-1); })
+#define _mm_ror_epi64(a, b) \
+ (__m128i)__builtin_ia32_prorq128((__v2di)(__m128i)(a), (int)(b))
-#define _mm_mask_ror_epi64(W, U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_prorq128_mask((__v2di)(__m128i)(A), (int)(B), \
- (__v2di)(__m128i)(W), (__mmask8)(U)); })
+#define _mm_mask_ror_epi64(w, u, a, b) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \
+ (__v2di)_mm_ror_epi64((a), (b)), \
+ (__v2di)(__m128i)(w))
-#define _mm_maskz_ror_epi64(U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_prorq128_mask((__v2di)(__m128i)(A), (int)(B), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)(U)); })
+#define _mm_maskz_ror_epi64(u, a, b) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \
+ (__v2di)_mm_ror_epi64((a), (b)), \
+ (__v2di)_mm_setzero_si128())
-#define _mm256_ror_epi64(A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_prorq256_mask((__v4di)(__m256i)(A), (int)(B), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+#define _mm256_ror_epi64(a, b) \
+ (__m256i)__builtin_ia32_prorq256((__v4di)(__m256i)(a), (int)(b))
-#define _mm256_mask_ror_epi64(W, U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_prorq256_mask((__v4di)(__m256i)(A), (int)(B), \
- (__v4di)(__m256i)(W), (__mmask8)(U)); })
+#define _mm256_mask_ror_epi64(w, u, a, b) \
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \
+ (__v4di)_mm256_ror_epi64((a), (b)), \
+ (__v4di)(__m256i)(w))
-#define _mm256_maskz_ror_epi64(U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_prorq256_mask((__v4di)(__m256i)(A), (int)(B), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+#define _mm256_maskz_ror_epi64(u, a, b) \
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \
+ (__v4di)_mm256_ror_epi64((a), (b)), \
+ (__v4di)_mm256_setzero_si256())
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4569,7 +4416,7 @@ _mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sll_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4577,7 +4424,7 @@ _mm_maskz_sll_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sll_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4585,7 +4432,7 @@ _mm256_mask_sll_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sll_epi32(__mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4593,7 +4440,7 @@ _mm256_maskz_sll_epi32(__mmask8 __U, __m256i __A, __m128i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4601,7 +4448,7 @@ _mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_slli_epi32(__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4609,7 +4456,7 @@ _mm_maskz_slli_epi32(__mmask8 __U, __m128i __A, int __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4617,7 +4464,7 @@ _mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4625,7 +4472,7 @@ _mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A, int __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -4633,15 +4480,15 @@ _mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sll_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_sll_epi64(__A, __B),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sll_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4649,7 +4496,7 @@ _mm256_mask_sll_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sll_epi64(__mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4657,7 +4504,7 @@ _mm256_maskz_sll_epi64(__mmask8 __U, __m256i __A, __m128i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -4665,15 +4512,15 @@ _mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_slli_epi64(__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_slli_epi64(__A, __B),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4681,7 +4528,7 @@ _mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4689,127 +4536,95 @@ _mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A, int __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_rorv_epi32 (__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_prorvd128((__v4si)__A, (__v4si)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_rorv_epi32(__A, __B),
+ (__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_rorv_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_rorv_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_rorv_epi32 (__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_prorvd256((__v8si)__A, (__v8si)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_rorv_epi32(__A, __B),
+ (__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_rorv_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_rorv_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_rorv_epi64 (__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_prorvq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_rorv_epi64(__A, __B),
+ (__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_rorv_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_rorv_epi64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_rorv_epi64 (__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_prorvq256((__v4di)__A, (__v4di)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_rorv_epi64(__A, __B),
+ (__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_rorv_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_rorv_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sllv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -4817,15 +4632,15 @@ _mm_mask_sllv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sllv_epi64(__mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_sllv_epi64(__X, __Y),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sllv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4833,7 +4648,7 @@ _mm256_mask_sllv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sllv_epi64(__mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4841,7 +4656,7 @@ _mm256_maskz_sllv_epi64(__mmask8 __U, __m256i __X, __m256i __Y)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sllv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4849,7 +4664,7 @@ _mm_mask_sllv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sllv_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4857,7 +4672,7 @@ _mm_maskz_sllv_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sllv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4865,7 +4680,7 @@ _mm256_mask_sllv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sllv_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4873,7 +4688,7 @@ _mm256_maskz_sllv_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srlv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -4881,15 +4696,15 @@ _mm_mask_srlv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srlv_epi64(__mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_srlv_epi64(__X, __Y),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srlv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4897,7 +4712,7 @@ _mm256_mask_srlv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srlv_epi64(__mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -4905,7 +4720,7 @@ _mm256_maskz_srlv_epi64(__mmask8 __U, __m256i __X, __m256i __Y)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srlv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4913,7 +4728,7 @@ _mm_mask_srlv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srlv_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4921,7 +4736,7 @@ _mm_maskz_srlv_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srlv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4929,7 +4744,7 @@ _mm256_mask_srlv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srlv_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4937,7 +4752,7 @@ _mm256_maskz_srlv_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srl_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4945,7 +4760,7 @@ _mm_mask_srl_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srl_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4953,7 +4768,7 @@ _mm_maskz_srl_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srl_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4961,7 +4776,7 @@ _mm256_mask_srl_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srl_epi32(__mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4969,7 +4784,7 @@ _mm256_maskz_srl_epi32(__mmask8 __U, __m256i __A, __m128i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4977,7 +4792,7 @@ _mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srli_epi32(__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -4985,7 +4800,7 @@ _mm_maskz_srli_epi32(__mmask8 __U, __m128i __A, int __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -4993,7 +4808,7 @@ _mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -5001,7 +4816,7 @@ _mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A, int __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -5009,15 +4824,15 @@ _mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srl_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_srl_epi64(__A, __B),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srl_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -5025,7 +4840,7 @@ _mm256_mask_srl_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srl_epi64(__mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -5033,7 +4848,7 @@ _mm256_maskz_srl_epi64(__mmask8 __U, __m256i __A, __m128i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -5041,15 +4856,15 @@ _mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srli_epi64(__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_srli_epi64(__A, __B),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -5057,7 +4872,7 @@ _mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -5065,7 +4880,7 @@ _mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A, int __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -5073,7 +4888,7 @@ _mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srav_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -5081,7 +4896,7 @@ _mm_maskz_srav_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srav_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -5089,7 +4904,7 @@ _mm256_mask_srav_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srav_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -5097,13 +4912,13 @@ _mm256_maskz_srav_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srav_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psravq128((__v2di)__X, (__v2di)__Y);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srav_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -5111,21 +4926,21 @@ _mm_mask_srav_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srav_epi64(__mmask8 __U, __m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_srav_epi64(__X, __Y),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srav_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psravq256((__v4di)__X, (__v4di) __Y);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srav_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -5133,7 +4948,7 @@ _mm256_mask_srav_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srav_epi64 (__mmask8 __U, __m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -5141,7 +4956,7 @@ _mm256_maskz_srav_epi64 (__mmask8 __U, __m256i __X, __m256i __Y)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mov_epi32 (__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectd_128 ((__mmask8) __U,
@@ -5149,7 +4964,7 @@ _mm_mask_mov_epi32 (__m128i __W, __mmask8 __U, __m128i __A)
(__v4si) __W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mov_epi32 (__mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectd_128 ((__mmask8) __U,
@@ -5158,7 +4973,7 @@ _mm_maskz_mov_epi32 (__mmask8 __U, __m128i __A)
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mov_epi32 (__m256i __W, __mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectd_256 ((__mmask8) __U,
@@ -5166,7 +4981,7 @@ _mm256_mask_mov_epi32 (__m256i __W, __mmask8 __U, __m256i __A)
(__v8si) __W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_epi32 (__mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectd_256 ((__mmask8) __U,
@@ -5174,7 +4989,7 @@ _mm256_maskz_mov_epi32 (__mmask8 __U, __m256i __A)
(__v8si) _mm256_setzero_si256 ());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_load_epi32 (__m128i __W, __mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_movdqa32load128_mask ((__v4si *) __P,
@@ -5183,7 +4998,7 @@ _mm_mask_load_epi32 (__m128i __W, __mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_load_epi32 (__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_movdqa32load128_mask ((__v4si *) __P,
@@ -5193,7 +5008,7 @@ _mm_maskz_load_epi32 (__mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_load_epi32 (__m256i __W, __mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_movdqa32load256_mask ((__v8si *) __P,
@@ -5202,7 +5017,7 @@ _mm256_mask_load_epi32 (__m256i __W, __mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_load_epi32 (__mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_movdqa32load256_mask ((__v8si *) __P,
@@ -5212,7 +5027,7 @@ _mm256_maskz_load_epi32 (__mmask8 __U, void const *__P)
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A)
{
__builtin_ia32_movdqa32store128_mask ((__v4si *) __P,
@@ -5220,7 +5035,7 @@ _mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_store_epi32 (void *__P, __mmask8 __U, __m256i __A)
{
__builtin_ia32_movdqa32store256_mask ((__v8si *) __P,
@@ -5228,7 +5043,7 @@ _mm256_mask_store_epi32 (void *__P, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_mov_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectq_128 ((__mmask8) __U,
@@ -5236,15 +5051,15 @@ _mm_mask_mov_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
(__v2di) __W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_mov_epi64 (__mmask8 __U, __m128i __A)
{
return (__m128i) __builtin_ia32_selectq_128 ((__mmask8) __U,
(__v2di) __A,
- (__v2di) _mm_setzero_di ());
+ (__v2di) _mm_setzero_si128 ());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_mov_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectq_256 ((__mmask8) __U,
@@ -5252,7 +5067,7 @@ _mm256_mask_mov_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
(__v4di) __W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_epi64 (__mmask8 __U, __m256i __A)
{
return (__m256i) __builtin_ia32_selectq_256 ((__mmask8) __U,
@@ -5260,7 +5075,7 @@ _mm256_maskz_mov_epi64 (__mmask8 __U, __m256i __A)
(__v4di) _mm256_setzero_si256 ());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_load_epi64 (__m128i __W, __mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_movdqa64load128_mask ((__v2di *) __P,
@@ -5269,17 +5084,17 @@ _mm_mask_load_epi64 (__m128i __W, __mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_load_epi64 (__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_movdqa64load128_mask ((__v2di *) __P,
(__v2di)
- _mm_setzero_di (),
+ _mm_setzero_si128 (),
(__mmask8)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_load_epi64 (__m256i __W, __mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_movdqa64load256_mask ((__v4di *) __P,
@@ -5288,7 +5103,7 @@ _mm256_mask_load_epi64 (__m256i __W, __mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_load_epi64 (__mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_movdqa64load256_mask ((__v4di *) __P,
@@ -5298,7 +5113,7 @@ _mm256_maskz_load_epi64 (__mmask8 __U, void const *__P)
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A)
{
__builtin_ia32_movdqa64store128_mask ((__v2di *) __P,
@@ -5306,7 +5121,7 @@ _mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_store_epi64 (void *__P, __mmask8 __U, __m256i __A)
{
__builtin_ia32_movdqa64store256_mask ((__v4di *) __P,
@@ -5314,7 +5129,7 @@ _mm256_mask_store_epi64 (void *__P, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_movedup_pd (__m128d __W, __mmask8 __U, __m128d __A)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -5322,7 +5137,7 @@ _mm_mask_movedup_pd (__m128d __W, __mmask8 __U, __m128d __A)
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_movedup_pd (__mmask8 __U, __m128d __A)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -5330,7 +5145,7 @@ _mm_maskz_movedup_pd (__mmask8 __U, __m128d __A)
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_movedup_pd (__m256d __W, __mmask8 __U, __m256d __A)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -5338,7 +5153,7 @@ _mm256_mask_movedup_pd (__m256d __W, __mmask8 __U, __m256d __A)
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -5346,7 +5161,7 @@ _mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A)
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_set1_epi32(__m128i __O, __mmask8 __M, int __A)
{
return (__m128i)__builtin_ia32_selectd_128(__M,
@@ -5354,7 +5169,7 @@ _mm_mask_set1_epi32(__m128i __O, __mmask8 __M, int __A)
(__v4si)__O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_set1_epi32( __mmask8 __M, int __A)
{
return (__m128i)__builtin_ia32_selectd_128(__M,
@@ -5362,7 +5177,7 @@ _mm_maskz_set1_epi32( __mmask8 __M, int __A)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_set1_epi32(__m256i __O, __mmask8 __M, int __A)
{
return (__m256i)__builtin_ia32_selectd_256(__M,
@@ -5370,7 +5185,7 @@ _mm256_mask_set1_epi32(__m256i __O, __mmask8 __M, int __A)
(__v8si)__O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_set1_epi32( __mmask8 __M, int __A)
{
return (__m256i)__builtin_ia32_selectd_256(__M,
@@ -5379,8 +5194,7 @@ _mm256_maskz_set1_epi32( __mmask8 __M, int __A)
}
-#ifdef __x86_64__
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A)
{
return (__m128i) __builtin_ia32_selectq_128(__M,
@@ -5388,7 +5202,7 @@ _mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A)
(__v2di) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_set1_epi64 (__mmask8 __M, long long __A)
{
return (__m128i) __builtin_ia32_selectq_128(__M,
@@ -5396,7 +5210,7 @@ _mm_maskz_set1_epi64 (__mmask8 __M, long long __A)
(__v2di) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_set1_epi64 (__m256i __O, __mmask8 __M, long long __A)
{
return (__m256i) __builtin_ia32_selectq_256(__M,
@@ -5404,89 +5218,87 @@ _mm256_mask_set1_epi64 (__m256i __O, __mmask8 __M, long long __A)
(__v4di) __O) ;
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_set1_epi64 (__mmask8 __M, long long __A)
{
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__ ({ \
+#define _mm_fixupimm_pd(A, B, C, imm) \
(__m128d)__builtin_ia32_fixupimmpd128_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_fixupimm_pd(A, U, B, C, imm) __extension__ ({ \
+#define _mm_mask_fixupimm_pd(A, U, B, C, imm) \
(__m128d)__builtin_ia32_fixupimmpd128_mask((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_fixupimm_pd(U, A, B, C, imm) __extension__ ({ \
+#define _mm_maskz_fixupimm_pd(U, A, B, C, imm) \
(__m128d)__builtin_ia32_fixupimmpd128_maskz((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2di)(__m128i)(C), \
- (int)(imm), (__mmask8)(U)); })
+ (int)(imm), (__mmask8)(U))
-#define _mm256_fixupimm_pd(A, B, C, imm) __extension__ ({ \
+#define _mm256_fixupimm_pd(A, B, C, imm) \
(__m256d)__builtin_ia32_fixupimmpd256_mask((__v4df)(__m256d)(A), \
(__v4df)(__m256d)(B), \
(__v4di)(__m256i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_fixupimm_pd(A, U, B, C, imm) __extension__ ({ \
+#define _mm256_mask_fixupimm_pd(A, U, B, C, imm) \
(__m256d)__builtin_ia32_fixupimmpd256_mask((__v4df)(__m256d)(A), \
(__v4df)(__m256d)(B), \
(__v4di)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_fixupimm_pd(U, A, B, C, imm) __extension__ ({ \
+#define _mm256_maskz_fixupimm_pd(U, A, B, C, imm) \
(__m256d)__builtin_ia32_fixupimmpd256_maskz((__v4df)(__m256d)(A), \
(__v4df)(__m256d)(B), \
(__v4di)(__m256i)(C), \
- (int)(imm), (__mmask8)(U)); })
+ (int)(imm), (__mmask8)(U))
-#define _mm_fixupimm_ps(A, B, C, imm) __extension__ ({ \
+#define _mm_fixupimm_ps(A, B, C, imm) \
(__m128)__builtin_ia32_fixupimmps128_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_fixupimm_ps(A, U, B, C, imm) __extension__ ({ \
+#define _mm_mask_fixupimm_ps(A, U, B, C, imm) \
(__m128)__builtin_ia32_fixupimmps128_mask((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_fixupimm_ps(U, A, B, C, imm) __extension__ ({ \
+#define _mm_maskz_fixupimm_ps(U, A, B, C, imm) \
(__m128)__builtin_ia32_fixupimmps128_maskz((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_fixupimm_ps(A, B, C, imm) __extension__ ({ \
+#define _mm256_fixupimm_ps(A, B, C, imm) \
(__m256)__builtin_ia32_fixupimmps256_mask((__v8sf)(__m256)(A), \
(__v8sf)(__m256)(B), \
(__v8si)(__m256i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_fixupimm_ps(A, U, B, C, imm) __extension__ ({ \
+#define _mm256_mask_fixupimm_ps(A, U, B, C, imm) \
(__m256)__builtin_ia32_fixupimmps256_mask((__v8sf)(__m256)(A), \
(__v8sf)(__m256)(B), \
(__v8si)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_fixupimm_ps(U, A, B, C, imm) __extension__ ({ \
+#define _mm256_maskz_fixupimm_ps(U, A, B, C, imm) \
(__m256)__builtin_ia32_fixupimmps256_maskz((__v8sf)(__m256)(A), \
(__v8sf)(__m256)(B), \
(__v8si)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_load_pd (__m128d __W, __mmask8 __U, void const *__P)
{
return (__m128d) __builtin_ia32_loadapd128_mask ((__v2df *) __P,
@@ -5494,7 +5306,7 @@ _mm_mask_load_pd (__m128d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_load_pd (__mmask8 __U, void const *__P)
{
return (__m128d) __builtin_ia32_loadapd128_mask ((__v2df *) __P,
@@ -5503,7 +5315,7 @@ _mm_maskz_load_pd (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_load_pd (__m256d __W, __mmask8 __U, void const *__P)
{
return (__m256d) __builtin_ia32_loadapd256_mask ((__v4df *) __P,
@@ -5511,7 +5323,7 @@ _mm256_mask_load_pd (__m256d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_load_pd (__mmask8 __U, void const *__P)
{
return (__m256d) __builtin_ia32_loadapd256_mask ((__v4df *) __P,
@@ -5520,7 +5332,7 @@ _mm256_maskz_load_pd (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_load_ps (__m128 __W, __mmask8 __U, void const *__P)
{
return (__m128) __builtin_ia32_loadaps128_mask ((__v4sf *) __P,
@@ -5528,7 +5340,7 @@ _mm_mask_load_ps (__m128 __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_load_ps (__mmask8 __U, void const *__P)
{
return (__m128) __builtin_ia32_loadaps128_mask ((__v4sf *) __P,
@@ -5537,7 +5349,7 @@ _mm_maskz_load_ps (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_load_ps (__m256 __W, __mmask8 __U, void const *__P)
{
return (__m256) __builtin_ia32_loadaps256_mask ((__v8sf *) __P,
@@ -5545,7 +5357,7 @@ _mm256_mask_load_ps (__m256 __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_load_ps (__mmask8 __U, void const *__P)
{
return (__m256) __builtin_ia32_loadaps256_mask ((__v8sf *) __P,
@@ -5554,7 +5366,7 @@ _mm256_maskz_load_ps (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi64 (__m128i __W, __mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddqudi128_mask ((__v2di *) __P,
@@ -5562,7 +5374,7 @@ _mm_mask_loadu_epi64 (__m128i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddqudi128_mask ((__v2di *) __P,
@@ -5571,7 +5383,7 @@ _mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi64 (__m256i __W, __mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddqudi256_mask ((__v4di *) __P,
@@ -5579,7 +5391,7 @@ _mm256_mask_loadu_epi64 (__m256i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_loadu_epi64 (__mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddqudi256_mask ((__v4di *) __P,
@@ -5588,7 +5400,7 @@ _mm256_maskz_loadu_epi64 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi32 (__m128i __W, __mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddqusi128_mask ((__v4si *) __P,
@@ -5596,7 +5408,7 @@ _mm_mask_loadu_epi32 (__m128i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_loaddqusi128_mask ((__v4si *) __P,
@@ -5605,7 +5417,7 @@ _mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi32 (__m256i __W, __mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddqusi256_mask ((__v8si *) __P,
@@ -5613,7 +5425,7 @@ _mm256_mask_loadu_epi32 (__m256i __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_loadu_epi32 (__mmask8 __U, void const *__P)
{
return (__m256i) __builtin_ia32_loaddqusi256_mask ((__v8si *) __P,
@@ -5622,7 +5434,7 @@ _mm256_maskz_loadu_epi32 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_loadu_pd (__m128d __W, __mmask8 __U, void const *__P)
{
return (__m128d) __builtin_ia32_loadupd128_mask ((__v2df *) __P,
@@ -5630,7 +5442,7 @@ _mm_mask_loadu_pd (__m128d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_loadu_pd (__mmask8 __U, void const *__P)
{
return (__m128d) __builtin_ia32_loadupd128_mask ((__v2df *) __P,
@@ -5639,7 +5451,7 @@ _mm_maskz_loadu_pd (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P)
{
return (__m256d) __builtin_ia32_loadupd256_mask ((__v4df *) __P,
@@ -5647,7 +5459,7 @@ _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_loadu_pd (__mmask8 __U, void const *__P)
{
return (__m256d) __builtin_ia32_loadupd256_mask ((__v4df *) __P,
@@ -5656,7 +5468,7 @@ _mm256_maskz_loadu_pd (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_loadu_ps (__m128 __W, __mmask8 __U, void const *__P)
{
return (__m128) __builtin_ia32_loadups128_mask ((__v4sf *) __P,
@@ -5664,7 +5476,7 @@ _mm_mask_loadu_ps (__m128 __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_loadu_ps (__mmask8 __U, void const *__P)
{
return (__m128) __builtin_ia32_loadups128_mask ((__v4sf *) __P,
@@ -5673,7 +5485,7 @@ _mm_maskz_loadu_ps (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_ps (__m256 __W, __mmask8 __U, void const *__P)
{
return (__m256) __builtin_ia32_loadups256_mask ((__v8sf *) __P,
@@ -5681,7 +5493,7 @@ _mm256_mask_loadu_ps (__m256 __W, __mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_loadu_ps (__mmask8 __U, void const *__P)
{
return (__m256) __builtin_ia32_loadups256_mask ((__v8sf *) __P,
@@ -5690,7 +5502,7 @@ _mm256_maskz_loadu_ps (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_pd (void *__P, __mmask8 __U, __m128d __A)
{
__builtin_ia32_storeapd128_mask ((__v2df *) __P,
@@ -5698,7 +5510,7 @@ _mm_mask_store_pd (void *__P, __mmask8 __U, __m128d __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_store_pd (void *__P, __mmask8 __U, __m256d __A)
{
__builtin_ia32_storeapd256_mask ((__v4df *) __P,
@@ -5706,7 +5518,7 @@ _mm256_mask_store_pd (void *__P, __mmask8 __U, __m256d __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_ps (void *__P, __mmask8 __U, __m128 __A)
{
__builtin_ia32_storeaps128_mask ((__v4sf *) __P,
@@ -5714,7 +5526,7 @@ _mm_mask_store_ps (void *__P, __mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_store_ps (void *__P, __mmask8 __U, __m256 __A)
{
__builtin_ia32_storeaps256_mask ((__v8sf *) __P,
@@ -5722,7 +5534,7 @@ _mm256_mask_store_ps (void *__P, __mmask8 __U, __m256 __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A)
{
__builtin_ia32_storedqudi128_mask ((__v2di *) __P,
@@ -5730,7 +5542,7 @@ _mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A)
{
__builtin_ia32_storedqudi256_mask ((__v4di *) __P,
@@ -5738,7 +5550,7 @@ _mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A)
{
__builtin_ia32_storedqusi128_mask ((__v4si *) __P,
@@ -5746,7 +5558,7 @@ _mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A)
{
__builtin_ia32_storedqusi256_mask ((__v8si *) __P,
@@ -5754,7 +5566,7 @@ _mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_pd (void *__P, __mmask8 __U, __m128d __A)
{
__builtin_ia32_storeupd128_mask ((__v2df *) __P,
@@ -5762,7 +5574,7 @@ _mm_mask_storeu_pd (void *__P, __mmask8 __U, __m128d __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_pd (void *__P, __mmask8 __U, __m256d __A)
{
__builtin_ia32_storeupd256_mask ((__v4df *) __P,
@@ -5770,7 +5582,7 @@ _mm256_mask_storeu_pd (void *__P, __mmask8 __U, __m256d __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_ps (void *__P, __mmask8 __U, __m128 __A)
{
__builtin_ia32_storeups128_mask ((__v4sf *) __P,
@@ -5778,7 +5590,7 @@ _mm_mask_storeu_ps (void *__P, __mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_ps (void *__P, __mmask8 __U, __m256 __A)
{
__builtin_ia32_storeups256_mask ((__v8sf *) __P,
@@ -5787,7 +5599,7 @@ _mm256_mask_storeu_ps (void *__P, __mmask8 __U, __m256 __A)
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_unpackhi_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -5795,7 +5607,7 @@ _mm_mask_unpackhi_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_unpackhi_pd(__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -5803,7 +5615,7 @@ _mm_maskz_unpackhi_pd(__mmask8 __U, __m128d __A, __m128d __B)
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_unpackhi_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -5811,7 +5623,7 @@ _mm256_mask_unpackhi_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B)
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_unpackhi_pd(__mmask8 __U, __m256d __A, __m256d __B)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -5819,7 +5631,7 @@ _mm256_maskz_unpackhi_pd(__mmask8 __U, __m256d __A, __m256d __B)
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_unpackhi_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -5827,7 +5639,7 @@ _mm_mask_unpackhi_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_unpackhi_ps(__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -5835,7 +5647,7 @@ _mm_maskz_unpackhi_ps(__mmask8 __U, __m128 __A, __m128 __B)
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_unpackhi_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -5843,7 +5655,7 @@ _mm256_mask_unpackhi_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B)
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_unpackhi_ps(__mmask8 __U, __m256 __A, __m256 __B)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -5851,7 +5663,7 @@ _mm256_maskz_unpackhi_ps(__mmask8 __U, __m256 __A, __m256 __B)
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_unpacklo_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -5859,7 +5671,7 @@ _mm_mask_unpacklo_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_unpacklo_pd(__mmask8 __U, __m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -5867,7 +5679,7 @@ _mm_maskz_unpacklo_pd(__mmask8 __U, __m128d __A, __m128d __B)
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_unpacklo_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -5875,7 +5687,7 @@ _mm256_mask_unpacklo_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B)
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_unpacklo_pd(__mmask8 __U, __m256d __A, __m256d __B)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -5883,7 +5695,7 @@ _mm256_maskz_unpacklo_pd(__mmask8 __U, __m256d __A, __m256d __B)
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_unpacklo_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -5891,7 +5703,7 @@ _mm_mask_unpacklo_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_unpacklo_ps(__mmask8 __U, __m128 __A, __m128 __B)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -5899,7 +5711,7 @@ _mm_maskz_unpacklo_ps(__mmask8 __U, __m128 __A, __m128 __B)
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_unpacklo_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -5907,7 +5719,7 @@ _mm256_mask_unpacklo_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B)
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_unpacklo_ps(__mmask8 __U, __m256 __A, __m256 __B)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -5915,7 +5727,7 @@ _mm256_maskz_unpacklo_ps(__mmask8 __U, __m256 __A, __m256 __B)
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_rcp14_pd (__m128d __A)
{
return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A,
@@ -5924,7 +5736,7 @@ _mm_rcp14_pd (__m128d __A)
(__mmask8) -1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_rcp14_pd (__m128d __W, __mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A,
@@ -5932,7 +5744,7 @@ _mm_mask_rcp14_pd (__m128d __W, __mmask8 __U, __m128d __A)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_rcp14_pd (__mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A,
@@ -5941,7 +5753,7 @@ _mm_maskz_rcp14_pd (__mmask8 __U, __m128d __A)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_rcp14_pd (__m256d __A)
{
return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A,
@@ -5950,7 +5762,7 @@ _mm256_rcp14_pd (__m256d __A)
(__mmask8) -1);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_rcp14_pd (__m256d __W, __mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A,
@@ -5958,7 +5770,7 @@ _mm256_mask_rcp14_pd (__m256d __W, __mmask8 __U, __m256d __A)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_rcp14_pd (__mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A,
@@ -5967,7 +5779,7 @@ _mm256_maskz_rcp14_pd (__mmask8 __U, __m256d __A)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_rcp14_ps (__m128 __A)
{
return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A,
@@ -5976,7 +5788,7 @@ _mm_rcp14_ps (__m128 __A)
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_rcp14_ps (__m128 __W, __mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A,
@@ -5984,7 +5796,7 @@ _mm_mask_rcp14_ps (__m128 __W, __mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_rcp14_ps (__mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A,
@@ -5993,7 +5805,7 @@ _mm_maskz_rcp14_ps (__mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_rcp14_ps (__m256 __A)
{
return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A,
@@ -6002,7 +5814,7 @@ _mm256_rcp14_ps (__m256 __A)
(__mmask8) -1);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_rcp14_ps (__m256 __W, __mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A,
@@ -6010,7 +5822,7 @@ _mm256_mask_rcp14_ps (__m256 __W, __mmask8 __U, __m256 __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_rcp14_ps (__mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A,
@@ -6019,47 +5831,47 @@ _mm256_maskz_rcp14_ps (__mmask8 __U, __m256 __A)
(__mmask8) __U);
}
-#define _mm_mask_permute_pd(W, U, X, C) __extension__ ({ \
+#define _mm_mask_permute_pd(W, U, X, C) \
(__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
(__v2df)_mm_permute_pd((X), (C)), \
- (__v2df)(__m128d)(W)); })
+ (__v2df)(__m128d)(W))
-#define _mm_maskz_permute_pd(U, X, C) __extension__ ({ \
+#define _mm_maskz_permute_pd(U, X, C) \
(__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
(__v2df)_mm_permute_pd((X), (C)), \
- (__v2df)_mm_setzero_pd()); })
+ (__v2df)_mm_setzero_pd())
-#define _mm256_mask_permute_pd(W, U, X, C) __extension__ ({ \
+#define _mm256_mask_permute_pd(W, U, X, C) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_permute_pd((X), (C)), \
- (__v4df)(__m256d)(W)); })
+ (__v4df)(__m256d)(W))
-#define _mm256_maskz_permute_pd(U, X, C) __extension__ ({ \
+#define _mm256_maskz_permute_pd(U, X, C) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_permute_pd((X), (C)), \
- (__v4df)_mm256_setzero_pd()); })
+ (__v4df)_mm256_setzero_pd())
-#define _mm_mask_permute_ps(W, U, X, C) __extension__ ({ \
+#define _mm_mask_permute_ps(W, U, X, C) \
(__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
(__v4sf)_mm_permute_ps((X), (C)), \
- (__v4sf)(__m128)(W)); })
+ (__v4sf)(__m128)(W))
-#define _mm_maskz_permute_ps(U, X, C) __extension__ ({ \
+#define _mm_maskz_permute_ps(U, X, C) \
(__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
(__v4sf)_mm_permute_ps((X), (C)), \
- (__v4sf)_mm_setzero_ps()); })
+ (__v4sf)_mm_setzero_ps())
-#define _mm256_mask_permute_ps(W, U, X, C) __extension__ ({ \
+#define _mm256_mask_permute_ps(W, U, X, C) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_permute_ps((X), (C)), \
- (__v8sf)(__m256)(W)); })
+ (__v8sf)(__m256)(W))
-#define _mm256_maskz_permute_ps(U, X, C) __extension__ ({ \
+#define _mm256_maskz_permute_ps(U, X, C) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_permute_ps((X), (C)), \
- (__v8sf)_mm256_setzero_ps()); })
+ (__v8sf)_mm256_setzero_ps())
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_permutevar_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128i __C)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -6067,7 +5879,7 @@ _mm_mask_permutevar_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128i __C)
(__v2df)__W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_permutevar_pd(__mmask8 __U, __m128d __A, __m128i __C)
{
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
@@ -6075,7 +5887,7 @@ _mm_maskz_permutevar_pd(__mmask8 __U, __m128d __A, __m128i __C)
(__v2df)_mm_setzero_pd());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_permutevar_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256i __C)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -6083,7 +5895,7 @@ _mm256_mask_permutevar_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256i __C)
(__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_permutevar_pd(__mmask8 __U, __m256d __A, __m256i __C)
{
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
@@ -6091,7 +5903,7 @@ _mm256_maskz_permutevar_pd(__mmask8 __U, __m256d __A, __m256i __C)
(__v4df)_mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_permutevar_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128i __C)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -6099,7 +5911,7 @@ _mm_mask_permutevar_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128i __C)
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_permutevar_ps(__mmask8 __U, __m128 __A, __m128i __C)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -6107,7 +5919,7 @@ _mm_maskz_permutevar_ps(__mmask8 __U, __m128 __A, __m128i __C)
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_permutevar_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256i __C)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -6115,7 +5927,7 @@ _mm256_mask_permutevar_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256i __C)
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -6123,115 +5935,115 @@ _mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C)
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_test_epi32_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpneq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
+ return _mm_cmpneq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_mask_test_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpneq_epi32_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_di());
+ _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_test_epi32_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpneq_epi32_mask (_mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_mask_test_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpneq_epi32_mask (__U, _mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_test_epi64_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpneq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
+ return _mm_cmpneq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_mask_test_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpneq_epi64_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_di());
+ _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_test_epi64_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpneq_epi64_mask (_mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_mask_test_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpneq_epi64_mask (__U, _mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_testn_epi32_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpeq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
+ return _mm_cmpeq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_mask_testn_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpeq_epi32_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_di());
+ _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_testn_epi32_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpeq_epi32_mask (_mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_mask_testn_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpeq_epi32_mask (__U, _mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_testn_epi64_mask (__m128i __A, __m128i __B)
{
- return _mm_cmpeq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
+ return _mm_cmpeq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS128
_mm_mask_testn_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
return _mm_mask_cmpeq_epi64_mask (__U, _mm_and_si128 (__A, __B),
- _mm_setzero_di());
+ _mm_setzero_si128());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_testn_epi64_mask (__m256i __A, __m256i __B)
{
return _mm256_cmpeq_epi64_mask (_mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS256
_mm256_mask_testn_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_cmpeq_epi64_mask (__U, _mm256_and_si256 (__A, __B),
_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpackhi_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6239,7 +6051,7 @@ _mm_mask_unpackhi_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpackhi_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6247,7 +6059,7 @@ _mm_maskz_unpackhi_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpackhi_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6255,7 +6067,7 @@ _mm256_mask_unpackhi_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpackhi_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6263,7 +6075,7 @@ _mm256_maskz_unpackhi_epi32(__mmask8 __U, __m256i __A, __m256i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpackhi_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -6271,15 +6083,15 @@ _mm_mask_unpackhi_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpackhi_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_unpackhi_epi64(__A, __B),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpackhi_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -6287,7 +6099,7 @@ _mm256_mask_unpackhi_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpackhi_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -6295,7 +6107,7 @@ _mm256_maskz_unpackhi_epi64(__mmask8 __U, __m256i __A, __m256i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpacklo_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6303,7 +6115,7 @@ _mm_mask_unpacklo_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpacklo_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6311,7 +6123,7 @@ _mm_maskz_unpacklo_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpacklo_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6319,7 +6131,7 @@ _mm256_mask_unpacklo_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpacklo_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6327,7 +6139,7 @@ _mm256_maskz_unpacklo_epi32(__mmask8 __U, __m256i __A, __m256i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_unpacklo_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
@@ -6335,15 +6147,15 @@ _mm_mask_unpacklo_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_unpacklo_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
(__v2di)_mm_unpacklo_epi64(__A, __B),
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_unpacklo_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -6351,7 +6163,7 @@ _mm256_mask_unpacklo_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_unpacklo_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
@@ -6359,7 +6171,7 @@ _mm256_maskz_unpacklo_epi64(__mmask8 __U, __m256i __A, __m256i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sra_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6367,7 +6179,7 @@ _mm_mask_sra_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sra_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6375,7 +6187,7 @@ _mm_maskz_sra_epi32(__mmask8 __U, __m128i __A, __m128i __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sra_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6383,7 +6195,7 @@ _mm256_mask_sra_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sra_epi32(__mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6391,7 +6203,7 @@ _mm256_maskz_sra_epi32(__mmask8 __U, __m256i __A, __m128i __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6399,7 +6211,7 @@ _mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
(__v4si)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srai_epi32(__mmask8 __U, __m128i __A, int __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
@@ -6407,7 +6219,7 @@ _mm_maskz_srai_epi32(__mmask8 __U, __m128i __A, int __B)
(__v4si)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6415,7 +6227,7 @@ _mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
(__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A, int __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
@@ -6423,13 +6235,13 @@ _mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A, int __B)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_sra_epi64(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psraq128((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_sra_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
@@ -6437,21 +6249,21 @@ _mm_mask_sra_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_sra_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
(__v2di)_mm_sra_epi64(__A, __B), \
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sra_epi64(__m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_psraq256((__v4di) __A, (__v2di) __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_sra_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
@@ -6459,7 +6271,7 @@ _mm256_mask_sra_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_sra_epi64(__mmask8 __U, __m256i __A, __m128i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
@@ -6467,13 +6279,13 @@ _mm256_maskz_sra_epi64(__mmask8 __U, __m256i __A, __m128i __B)
(__v4di)_mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srai_epi64(__m128i __A, int __imm)
{
return (__m128i)__builtin_ia32_psraqi128((__v2di)__A, __imm);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __imm)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
@@ -6481,21 +6293,21 @@ _mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __imm)
(__v2di)__W);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_srai_epi64(__mmask8 __U, __m128i __A, int __imm)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
(__v2di)_mm_srai_epi64(__A, __imm), \
- (__v2di)_mm_setzero_di());
+ (__v2di)_mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srai_epi64(__m256i __A, int __imm)
{
return (__m256i)__builtin_ia32_psraqi256((__v4di)__A, __imm);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __imm)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
@@ -6503,7 +6315,7 @@ _mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __imm)
(__v4di)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
@@ -6511,198 +6323,178 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm)
(__v4di)_mm256_setzero_si256());
}
-#define _mm_ternarylogic_epi32(A, B, C, imm) __extension__ ({ \
+#define _mm_ternarylogic_epi32(A, B, C, imm) \
(__m128i)__builtin_ia32_pternlogd128_mask((__v4si)(__m128i)(A), \
(__v4si)(__m128i)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_ternarylogic_epi32(A, U, B, C, imm) __extension__ ({ \
+#define _mm_mask_ternarylogic_epi32(A, U, B, C, imm) \
(__m128i)__builtin_ia32_pternlogd128_mask((__v4si)(__m128i)(A), \
(__v4si)(__m128i)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_ternarylogic_epi32(U, A, B, C, imm) __extension__ ({ \
+#define _mm_maskz_ternarylogic_epi32(U, A, B, C, imm) \
(__m128i)__builtin_ia32_pternlogd128_maskz((__v4si)(__m128i)(A), \
(__v4si)(__m128i)(B), \
(__v4si)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_ternarylogic_epi32(A, B, C, imm) __extension__ ({ \
+#define _mm256_ternarylogic_epi32(A, B, C, imm) \
(__m256i)__builtin_ia32_pternlogd256_mask((__v8si)(__m256i)(A), \
(__v8si)(__m256i)(B), \
(__v8si)(__m256i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_ternarylogic_epi32(A, U, B, C, imm) __extension__ ({ \
+#define _mm256_mask_ternarylogic_epi32(A, U, B, C, imm) \
(__m256i)__builtin_ia32_pternlogd256_mask((__v8si)(__m256i)(A), \
(__v8si)(__m256i)(B), \
(__v8si)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_ternarylogic_epi32(U, A, B, C, imm) __extension__ ({ \
+#define _mm256_maskz_ternarylogic_epi32(U, A, B, C, imm) \
(__m256i)__builtin_ia32_pternlogd256_maskz((__v8si)(__m256i)(A), \
(__v8si)(__m256i)(B), \
(__v8si)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_ternarylogic_epi64(A, B, C, imm) __extension__ ({ \
+#define _mm_ternarylogic_epi64(A, B, C, imm) \
(__m128i)__builtin_ia32_pternlogq128_mask((__v2di)(__m128i)(A), \
(__v2di)(__m128i)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_ternarylogic_epi64(A, U, B, C, imm) __extension__ ({ \
+#define _mm_mask_ternarylogic_epi64(A, U, B, C, imm) \
(__m128i)__builtin_ia32_pternlogq128_mask((__v2di)(__m128i)(A), \
(__v2di)(__m128i)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_ternarylogic_epi64(U, A, B, C, imm) __extension__ ({ \
+#define _mm_maskz_ternarylogic_epi64(U, A, B, C, imm) \
(__m128i)__builtin_ia32_pternlogq128_maskz((__v2di)(__m128i)(A), \
(__v2di)(__m128i)(B), \
(__v2di)(__m128i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_ternarylogic_epi64(A, B, C, imm) __extension__ ({ \
+#define _mm256_ternarylogic_epi64(A, B, C, imm) \
(__m256i)__builtin_ia32_pternlogq256_mask((__v4di)(__m256i)(A), \
(__v4di)(__m256i)(B), \
(__v4di)(__m256i)(C), (int)(imm), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_ternarylogic_epi64(A, U, B, C, imm) __extension__ ({ \
+#define _mm256_mask_ternarylogic_epi64(A, U, B, C, imm) \
(__m256i)__builtin_ia32_pternlogq256_mask((__v4di)(__m256i)(A), \
(__v4di)(__m256i)(B), \
(__v4di)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_ternarylogic_epi64(U, A, B, C, imm) __extension__ ({ \
+#define _mm256_maskz_ternarylogic_epi64(U, A, B, C, imm) \
(__m256i)__builtin_ia32_pternlogq256_maskz((__v4di)(__m256i)(A), \
(__v4di)(__m256i)(B), \
(__v4di)(__m256i)(C), (int)(imm), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_shuffle_f32x4(A, B, imm) __extension__ ({ \
- (__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_shuffle_f32x4(A, B, imm) \
+ (__m256)__builtin_ia32_shuf_f32x4_256((__v8sf)(__m256)(A), \
+ (__v8sf)(__m256)(B), (int)(imm))
-#define _mm256_mask_shuffle_f32x4(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_mask_shuffle_f32x4(W, U, A, B, imm) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_shuffle_f32x4((A), (B), (imm)), \
- (__v8sf)(__m256)(W)); })
+ (__v8sf)(__m256)(W))
-#define _mm256_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_shuffle_f32x4(U, A, B, imm) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_shuffle_f32x4((A), (B), (imm)), \
- (__v8sf)_mm256_setzero_ps()); })
+ (__v8sf)_mm256_setzero_ps())
-#define _mm256_shuffle_f64x2(A, B, imm) __extension__ ({ \
- (__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_shuffle_f64x2(A, B, imm) \
+ (__m256d)__builtin_ia32_shuf_f64x2_256((__v4df)(__m256d)(A), \
+ (__v4df)(__m256d)(B), (int)(imm))
-#define _mm256_mask_shuffle_f64x2(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_mask_shuffle_f64x2(W, U, A, B, imm) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_shuffle_f64x2((A), (B), (imm)), \
- (__v4df)(__m256)(W)); })
+ (__v4df)(__m256d)(W))
-#define _mm256_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_shuffle_f64x2(U, A, B, imm) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_shuffle_f64x2((A), (B), (imm)), \
- (__v4df)_mm256_setzero_pd()); })
+ (__v4df)_mm256_setzero_pd())
-#define _mm256_shuffle_i32x4(A, B, imm) __extension__ ({ \
- (__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_shuffle_i32x4(A, B, imm) \
+ (__m256i)__builtin_ia32_shuf_i32x4_256((__v8si)(__m256i)(A), \
+ (__v8si)(__m256i)(B), (int)(imm))
-#define _mm256_mask_shuffle_i32x4(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_mask_shuffle_i32x4(W, U, A, B, imm) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_shuffle_i32x4((A), (B), (imm)), \
- (__v8si)(__m256)(W)); })
+ (__v8si)(__m256i)(W))
-#define _mm256_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_shuffle_i32x4(U, A, B, imm) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_shuffle_i32x4((A), (B), (imm)), \
- (__v8si)_mm256_setzero_si256()); })
+ (__v8si)_mm256_setzero_si256())
-#define _mm256_shuffle_i64x2(A, B, imm) __extension__ ({ \
- (__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_shuffle_i64x2(A, B, imm) \
+ (__m256i)__builtin_ia32_shuf_i64x2_256((__v4di)(__m256i)(A), \
+ (__v4di)(__m256i)(B), (int)(imm))
-#define _mm256_mask_shuffle_i64x2(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_mask_shuffle_i64x2(W, U, A, B, imm) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_shuffle_i64x2((A), (B), (imm)), \
- (__v4di)(__m256)(W)); })
+ (__v4di)(__m256i)(W))
-#define _mm256_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_shuffle_i64x2(U, A, B, imm) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_shuffle_i64x2((A), (B), (imm)), \
- (__v4di)_mm256_setzero_si256()); })
+ (__v4di)_mm256_setzero_si256())
-#define _mm_mask_shuffle_pd(W, U, A, B, M) __extension__ ({ \
+#define _mm_mask_shuffle_pd(W, U, A, B, M) \
(__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
(__v2df)_mm_shuffle_pd((A), (B), (M)), \
- (__v2df)(__m128d)(W)); })
+ (__v2df)(__m128d)(W))
-#define _mm_maskz_shuffle_pd(U, A, B, M) __extension__ ({ \
+#define _mm_maskz_shuffle_pd(U, A, B, M) \
(__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
(__v2df)_mm_shuffle_pd((A), (B), (M)), \
- (__v2df)_mm_setzero_pd()); })
+ (__v2df)_mm_setzero_pd())
-#define _mm256_mask_shuffle_pd(W, U, A, B, M) __extension__ ({ \
+#define _mm256_mask_shuffle_pd(W, U, A, B, M) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_shuffle_pd((A), (B), (M)), \
- (__v4df)(__m256d)(W)); })
+ (__v4df)(__m256d)(W))
-#define _mm256_maskz_shuffle_pd(U, A, B, M) __extension__ ({ \
+#define _mm256_maskz_shuffle_pd(U, A, B, M) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_shuffle_pd((A), (B), (M)), \
- (__v4df)_mm256_setzero_pd()); })
+ (__v4df)_mm256_setzero_pd())
-#define _mm_mask_shuffle_ps(W, U, A, B, M) __extension__ ({ \
+#define _mm_mask_shuffle_ps(W, U, A, B, M) \
(__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
(__v4sf)_mm_shuffle_ps((A), (B), (M)), \
- (__v4sf)(__m128)(W)); })
+ (__v4sf)(__m128)(W))
-#define _mm_maskz_shuffle_ps(U, A, B, M) __extension__ ({ \
+#define _mm_maskz_shuffle_ps(U, A, B, M) \
(__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
(__v4sf)_mm_shuffle_ps((A), (B), (M)), \
- (__v4sf)_mm_setzero_ps()); })
+ (__v4sf)_mm_setzero_ps())
-#define _mm256_mask_shuffle_ps(W, U, A, B, M) __extension__ ({ \
+#define _mm256_mask_shuffle_ps(W, U, A, B, M) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_shuffle_ps((A), (B), (M)), \
- (__v8sf)(__m256)(W)); })
+ (__v8sf)(__m256)(W))
-#define _mm256_maskz_shuffle_ps(U, A, B, M) __extension__ ({ \
+#define _mm256_maskz_shuffle_ps(U, A, B, M) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_shuffle_ps((A), (B), (M)), \
- (__v8sf)_mm256_setzero_ps()); })
+ (__v8sf)_mm256_setzero_ps())
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_rsqrt14_pd (__m128d __A)
{
return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A,
@@ -6711,7 +6503,7 @@ _mm_rsqrt14_pd (__m128d __A)
(__mmask8) -1);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_rsqrt14_pd (__m128d __W, __mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A,
@@ -6719,7 +6511,7 @@ _mm_mask_rsqrt14_pd (__m128d __W, __mmask8 __U, __m128d __A)
(__mmask8) __U);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_rsqrt14_pd (__mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A,
@@ -6728,7 +6520,7 @@ _mm_maskz_rsqrt14_pd (__mmask8 __U, __m128d __A)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_rsqrt14_pd (__m256d __A)
{
return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A,
@@ -6737,7 +6529,7 @@ _mm256_rsqrt14_pd (__m256d __A)
(__mmask8) -1);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_rsqrt14_pd (__m256d __W, __mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A,
@@ -6745,7 +6537,7 @@ _mm256_mask_rsqrt14_pd (__m256d __W, __mmask8 __U, __m256d __A)
(__mmask8) __U);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_rsqrt14_pd (__mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A,
@@ -6754,7 +6546,7 @@ _mm256_maskz_rsqrt14_pd (__mmask8 __U, __m256d __A)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_rsqrt14_ps (__m128 __A)
{
return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A,
@@ -6763,7 +6555,7 @@ _mm_rsqrt14_ps (__m128 __A)
(__mmask8) -1);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_rsqrt14_ps (__m128 __W, __mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A,
@@ -6771,7 +6563,7 @@ _mm_mask_rsqrt14_ps (__m128 __W, __mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_rsqrt14_ps (__mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A,
@@ -6780,7 +6572,7 @@ _mm_maskz_rsqrt14_ps (__mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_rsqrt14_ps (__m256 __A)
{
return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A,
@@ -6789,7 +6581,7 @@ _mm256_rsqrt14_ps (__m256 __A)
(__mmask8) -1);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_rsqrt14_ps (__m256 __W, __mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A,
@@ -6797,7 +6589,7 @@ _mm256_mask_rsqrt14_ps (__m256 __W, __mmask8 __U, __m256 __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_rsqrt14_ps (__mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A,
@@ -6806,14 +6598,14 @@ _mm256_maskz_rsqrt14_ps (__mmask8 __U, __m256 __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_broadcast_f32x4(__m128 __A)
{
return (__m256)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A,
0, 1, 2, 3, 0, 1, 2, 3);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_broadcast_f32x4(__m256 __O, __mmask8 __M, __m128 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__M,
@@ -6821,7 +6613,7 @@ _mm256_mask_broadcast_f32x4(__m256 __O, __mmask8 __M, __m128 __A)
(__v8sf)__O);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcast_f32x4 (__mmask8 __M, __m128 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__M,
@@ -6829,14 +6621,14 @@ _mm256_maskz_broadcast_f32x4 (__mmask8 __M, __m128 __A)
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_broadcast_i32x4(__m128i __A)
{
return (__m256i)__builtin_shufflevector((__v4si)__A, (__v4si)__A,
0, 1, 2, 3, 0, 1, 2, 3);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcast_i32x4(__m256i __O, __mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
@@ -6844,7 +6636,7 @@ _mm256_mask_broadcast_i32x4(__m256i __O, __mmask8 __M, __m128i __A)
(__v8si)__O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcast_i32x4(__mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
@@ -6852,7 +6644,7 @@ _mm256_maskz_broadcast_i32x4(__mmask8 __M, __m128i __A)
(__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_broadcastsd_pd (__m256d __O, __mmask8 __M, __m128d __A)
{
return (__m256d)__builtin_ia32_selectpd_256(__M,
@@ -6860,7 +6652,7 @@ _mm256_mask_broadcastsd_pd (__m256d __O, __mmask8 __M, __m128d __A)
(__v4df) __O);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A)
{
return (__m256d)__builtin_ia32_selectpd_256(__M,
@@ -6868,7 +6660,7 @@ _mm256_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A)
(__v4df) _mm256_setzero_pd());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_broadcastss_ps (__m128 __O, __mmask8 __M, __m128 __A)
{
return (__m128)__builtin_ia32_selectps_128(__M,
@@ -6876,7 +6668,7 @@ _mm_mask_broadcastss_ps (__m128 __O, __mmask8 __M, __m128 __A)
(__v4sf) __O);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_broadcastss_ps (__mmask8 __M, __m128 __A)
{
return (__m128)__builtin_ia32_selectps_128(__M,
@@ -6884,7 +6676,7 @@ _mm_maskz_broadcastss_ps (__mmask8 __M, __m128 __A)
(__v4sf) _mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_broadcastss_ps (__m256 __O, __mmask8 __M, __m128 __A)
{
return (__m256)__builtin_ia32_selectps_256(__M,
@@ -6892,7 +6684,7 @@ _mm256_mask_broadcastss_ps (__m256 __O, __mmask8 __M, __m128 __A)
(__v8sf) __O);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcastss_ps (__mmask8 __M, __m128 __A)
{
return (__m256)__builtin_ia32_selectps_256(__M,
@@ -6900,7 +6692,7 @@ _mm256_maskz_broadcastss_ps (__mmask8 __M, __m128 __A)
(__v8sf) _mm256_setzero_ps());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_broadcastd_epi32 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectd_128(__M,
@@ -6908,7 +6700,7 @@ _mm_mask_broadcastd_epi32 (__m128i __O, __mmask8 __M, __m128i __A)
(__v4si) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectd_128(__M,
@@ -6916,7 +6708,7 @@ _mm_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A)
(__v4si) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcastd_epi32 (__m256i __O, __mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectd_256(__M,
@@ -6924,7 +6716,7 @@ _mm256_mask_broadcastd_epi32 (__m256i __O, __mmask8 __M, __m128i __A)
(__v8si) __O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectd_256(__M,
@@ -6932,7 +6724,7 @@ _mm256_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A)
(__v8si) _mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_broadcastq_epi64 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectq_128(__M,
@@ -6940,7 +6732,7 @@ _mm_mask_broadcastq_epi64 (__m128i __O, __mmask8 __M, __m128i __A)
(__v2di) __O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
{
return (__m128i)__builtin_ia32_selectq_128(__M,
@@ -6948,7 +6740,7 @@ _mm_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
(__v2di) _mm_setzero_si128());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_broadcastq_epi64 (__m256i __O, __mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectq_256(__M,
@@ -6956,7 +6748,7 @@ _mm256_mask_broadcastq_epi64 (__m256i __O, __mmask8 __M, __m128i __A)
(__v4di) __O);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
{
return (__m256i)__builtin_ia32_selectq_256(__M,
@@ -6964,7 +6756,7 @@ _mm256_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
(__v4di) _mm256_setzero_si256());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtsepi32_epi8 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A,
@@ -6972,14 +6764,14 @@ _mm_cvtsepi32_epi8 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsepi32_epi8 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A,
@@ -6987,13 +6779,13 @@ _mm_maskz_cvtsepi32_epi8 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovsdb128mem_mask ((__v16qi *) __P, (__v4si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm256_cvtsepi32_epi8 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A,
@@ -7001,14 +6793,14 @@ _mm256_cvtsepi32_epi8 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtsepi32_epi8 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A,
@@ -7016,13 +6808,13 @@ _mm256_maskz_cvtsepi32_epi8 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm256_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovsdb256mem_mask ((__v16qi *) __P, (__v8si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtsepi32_epi16 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A,
@@ -7030,7 +6822,7 @@ _mm_cvtsepi32_epi16 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A,
@@ -7038,7 +6830,7 @@ _mm_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsepi32_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A,
@@ -7046,13 +6838,13 @@ _mm_maskz_cvtsepi32_epi16 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovsdw128mem_mask ((__v8hi *) __P, (__v4si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtsepi32_epi16 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A,
@@ -7060,14 +6852,14 @@ _mm256_cvtsepi32_epi16 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtsepi32_epi16 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A,
@@ -7075,13 +6867,13 @@ _mm256_maskz_cvtsepi32_epi16 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovsdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtsepi64_epi8 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A,
@@ -7089,14 +6881,14 @@ _mm_cvtsepi64_epi8 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsepi64_epi8 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A,
@@ -7104,13 +6896,13 @@ _mm_maskz_cvtsepi64_epi8 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovsqb128mem_mask ((__v16qi *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtsepi64_epi8 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A,
@@ -7118,14 +6910,14 @@ _mm256_cvtsepi64_epi8 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtsepi64_epi8 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A,
@@ -7133,13 +6925,13 @@ _mm256_maskz_cvtsepi64_epi8 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovsqb256mem_mask ((__v16qi *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtsepi64_epi32 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A,
@@ -7147,14 +6939,14 @@ _mm_cvtsepi64_epi32 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A,
(__v4si) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsepi64_epi32 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A,
@@ -7162,13 +6954,13 @@ _mm_maskz_cvtsepi64_epi32 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovsqd128mem_mask ((__v4si *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtsepi64_epi32 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A,
@@ -7176,7 +6968,7 @@ _mm256_cvtsepi64_epi32 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A,
@@ -7184,7 +6976,7 @@ _mm256_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtsepi64_epi32 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A,
@@ -7192,13 +6984,13 @@ _mm256_maskz_cvtsepi64_epi32 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovsqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtsepi64_epi16 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A,
@@ -7206,14 +6998,14 @@ _mm_cvtsepi64_epi16 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtsepi64_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A,
@@ -7221,13 +7013,13 @@ _mm_maskz_cvtsepi64_epi16 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovsqw128mem_mask ((__v8hi *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtsepi64_epi16 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A,
@@ -7235,14 +7027,14 @@ _mm256_cvtsepi64_epi16 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtsepi64_epi16 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A,
@@ -7250,13 +7042,13 @@ _mm256_maskz_cvtsepi64_epi16 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovsqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtusepi32_epi8 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A,
@@ -7264,7 +7056,7 @@ _mm_cvtusepi32_epi8 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A,
@@ -7272,7 +7064,7 @@ _mm_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtusepi32_epi8 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A,
@@ -7280,13 +7072,13 @@ _mm_maskz_cvtusepi32_epi8 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovusdb128mem_mask ((__v16qi *) __P, (__v4si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtusepi32_epi8 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A,
@@ -7294,7 +7086,7 @@ _mm256_cvtusepi32_epi8 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A,
@@ -7302,7 +7094,7 @@ _mm256_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtusepi32_epi8 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A,
@@ -7310,13 +7102,13 @@ _mm256_maskz_cvtusepi32_epi8 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovusdb256mem_mask ((__v16qi*) __P, (__v8si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtusepi32_epi16 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A,
@@ -7324,14 +7116,14 @@ _mm_cvtusepi32_epi16 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtusepi32_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A,
@@ -7339,13 +7131,13 @@ _mm_maskz_cvtusepi32_epi16 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovusdw128mem_mask ((__v8hi *) __P, (__v4si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtusepi32_epi16 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A,
@@ -7353,14 +7145,14 @@ _mm256_cvtusepi32_epi16 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtusepi32_epi16 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A,
@@ -7368,13 +7160,13 @@ _mm256_maskz_cvtusepi32_epi16 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovusdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtusepi64_epi8 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A,
@@ -7382,7 +7174,7 @@ _mm_cvtusepi64_epi8 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A,
@@ -7390,7 +7182,7 @@ _mm_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtusepi64_epi8 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A,
@@ -7398,13 +7190,13 @@ _mm_maskz_cvtusepi64_epi8 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovusqb128mem_mask ((__v16qi *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtusepi64_epi8 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A,
@@ -7412,7 +7204,7 @@ _mm256_cvtusepi64_epi8 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A,
@@ -7420,7 +7212,7 @@ _mm256_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtusepi64_epi8 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A,
@@ -7428,13 +7220,13 @@ _mm256_maskz_cvtusepi64_epi8 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovusqb256mem_mask ((__v16qi *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtusepi64_epi32 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A,
@@ -7442,14 +7234,14 @@ _mm_cvtusepi64_epi32 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A,
(__v4si) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtusepi64_epi32 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A,
@@ -7457,13 +7249,13 @@ _mm_maskz_cvtusepi64_epi32 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovusqd128mem_mask ((__v4si *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtusepi64_epi32 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A,
@@ -7471,14 +7263,14 @@ _mm256_cvtusepi64_epi32 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A,
(__v4si) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtusepi64_epi32 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A,
@@ -7486,13 +7278,13 @@ _mm256_maskz_cvtusepi64_epi32 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovusqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtusepi64_epi16 (__m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A,
@@ -7500,14 +7292,14 @@ _mm_cvtusepi64_epi16 (__m128i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtusepi64_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A,
@@ -7515,13 +7307,13 @@ _mm_maskz_cvtusepi64_epi16 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovusqw128mem_mask ((__v8hi *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtusepi64_epi16 (__m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A,
@@ -7529,14 +7321,14 @@ _mm256_cvtusepi64_epi16 (__m256i __A)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtusepi64_epi16 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A,
@@ -7544,28 +7336,28 @@ _mm256_maskz_cvtusepi64_epi16 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
{
- return __builtin_ia32_pmovusqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M);
+ __builtin_ia32_pmovusqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtepi32_epi8 (__m128i __A)
{
- return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A,
- (__v16qi)_mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v4si)__A, __v4qi), (__v4qi){0, 0, 0, 0}, 0, 1,
+ 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi32_epi8 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A,
@@ -7574,28 +7366,29 @@ _mm_maskz_cvtepi32_epi8 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovdb128mem_mask ((__v16qi *) __P, (__v4si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtepi32_epi8 (__m256i __A)
{
- return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A,
- (__v16qi)_mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v8si)__A, __v8qi),
+ (__v8qi){0, 0, 0, 0, 0, 0, 0, 0}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi32_epi8 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A,
@@ -7603,28 +7396,28 @@ _mm256_maskz_cvtepi32_epi8 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovdb256mem_mask ((__v16qi *) __P, (__v8si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtepi32_epi16 (__m128i __A)
{
- return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v4si)__A, __v4hi), (__v4hi){0, 0, 0, 0}, 0, 1,
+ 2, 3, 4, 5, 6, 7);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi32_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A,
@@ -7632,28 +7425,26 @@ _mm_maskz_cvtepi32_epi16 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovdw128mem_mask ((__v8hi *) __P, (__v4si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtepi32_epi16 (__m256i __A)
{
- return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A,
- (__v8hi)_mm_setzero_si128 (),
- (__mmask8) -1);
+ return (__m128i)__builtin_convertvector((__v8si)__A, __v8hi);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi32_epi16 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A,
@@ -7661,28 +7452,28 @@ _mm256_maskz_cvtepi32_epi16 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtepi64_epi8 (__m128i __A)
{
- return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A,
- (__v16qi) _mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v2di)__A, __v2qi), (__v2qi){0, 0}, 0, 1, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi64_epi8 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A,
@@ -7690,28 +7481,28 @@ _mm_maskz_cvtepi64_epi8 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovqb128mem_mask ((__v16qi *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtepi64_epi8 (__m256i __A)
{
- return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A,
- (__v16qi) _mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v4di)__A, __v4qi), (__v4qi){0, 0, 0, 0}, 0, 1,
+ 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A,
(__v16qi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi64_epi8 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A,
@@ -7719,28 +7510,27 @@ _mm256_maskz_cvtepi64_epi8 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovqb256mem_mask ((__v16qi *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtepi64_epi32 (__m128i __A)
{
- return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A,
- (__v4si)_mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v2di)__A, __v2si), (__v2si){0, 0}, 0, 1, 2, 3);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A,
(__v4si) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi64_epi32 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A,
@@ -7748,50 +7538,49 @@ _mm_maskz_cvtepi64_epi32 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovqd128mem_mask ((__v4si *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtepi64_epi32 (__m256i __A)
{
- return (__m128i) __builtin_ia32_pmovqd256_mask ((__v4di) __A,
- (__v4si) _mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_convertvector((__v4di)__A, __v4si);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A)
{
- return (__m128i) __builtin_ia32_pmovqd256_mask ((__v4di) __A,
- (__v4si) __O, __M);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
+ (__v4si)_mm256_cvtepi64_epi32(__A),
+ (__v4si)__O);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi64_epi32 (__mmask8 __M, __m256i __A)
{
- return (__m128i) __builtin_ia32_pmovqd256_mask ((__v4di) __A,
- (__v4si) _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
+ (__v4si)_mm256_cvtepi64_epi32(__A),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_cvtepi64_epi16 (__m128i __A)
{
- return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A,
- (__v8hi) _mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v2di)__A, __v2hi), (__v2hi){0, 0}, 0, 1, 2, 3,
+ 3, 3, 3, 3);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A,
@@ -7799,7 +7588,7 @@ _mm_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A)
__M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtepi64_epi16 (__mmask8 __M, __m128i __A)
{
return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A,
@@ -7807,28 +7596,28 @@ _mm_maskz_cvtepi64_epi16 (__mmask8 __M, __m128i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A)
{
__builtin_ia32_pmovqw128mem_mask ((__v8hi *) __P, (__v2di) __A, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_cvtepi64_epi16 (__m256i __A)
{
- return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A,
- (__v8hi)_mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector(
+ __builtin_convertvector((__v4di)__A, __v4hi), (__v4hi){0, 0, 0, 0}, 0, 1,
+ 2, 3, 4, 5, 6, 7);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A,
(__v8hi) __O, __M);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtepi64_epi16 (__mmask8 __M, __m256i __A)
{
return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A,
@@ -7836,479 +7625,410 @@ _mm256_maskz_cvtepi64_epi16 (__mmask8 __M, __m256i __A)
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M);
}
-#define _mm256_extractf32x4_ps(A, imm) __extension__ ({ \
- (__m128)__builtin_shufflevector((__v8sf)(__m256)(A), \
- (__v8sf)_mm256_undefined_ps(), \
- ((imm) & 1) ? 4 : 0, \
- ((imm) & 1) ? 5 : 1, \
- ((imm) & 1) ? 6 : 2, \
- ((imm) & 1) ? 7 : 3); })
-
-#define _mm256_mask_extractf32x4_ps(W, U, A, imm) __extension__ ({ \
- (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
- (__v4sf)_mm256_extractf32x4_ps((A), (imm)), \
- (__v4sf)(W)); })
-
-#define _mm256_maskz_extractf32x4_ps(U, A, imm) __extension__ ({ \
- (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
- (__v4sf)_mm256_extractf32x4_ps((A), (imm)), \
- (__v4sf)_mm_setzero_ps()); })
-
-#define _mm256_extracti32x4_epi32(A, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v8si)(__m256)(A), \
- (__v8si)_mm256_undefined_si256(), \
- ((imm) & 1) ? 4 : 0, \
- ((imm) & 1) ? 5 : 1, \
- ((imm) & 1) ? 6 : 2, \
- ((imm) & 1) ? 7 : 3); })
-
-#define _mm256_mask_extracti32x4_epi32(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
- (__v4si)_mm256_extracti32x4_epi32((A), (imm)), \
- (__v4si)(W)); })
-
-#define _mm256_maskz_extracti32x4_epi32(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
- (__v4si)_mm256_extracti32x4_epi32((A), (imm)), \
- (__v4si)_mm_setzero_si128()); })
-
-#define _mm256_insertf32x4(A, B, imm) __extension__ ({ \
- (__m256)__builtin_shufflevector((__v8sf)(A), \
- (__v8sf)_mm256_castps128_ps256((__m128)(B)), \
- ((imm) & 0x1) ? 0 : 8, \
- ((imm) & 0x1) ? 1 : 9, \
- ((imm) & 0x1) ? 2 : 10, \
- ((imm) & 0x1) ? 3 : 11, \
- ((imm) & 0x1) ? 8 : 4, \
- ((imm) & 0x1) ? 9 : 5, \
- ((imm) & 0x1) ? 10 : 6, \
- ((imm) & 0x1) ? 11 : 7); })
-
-#define _mm256_mask_insertf32x4(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_extractf32x4_ps(A, imm) \
+ (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \
+ (int)(imm), \
+ (__v4sf)_mm_undefined_ps(), \
+ (__mmask8)-1)
+
+#define _mm256_mask_extractf32x4_ps(W, U, A, imm) \
+ (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \
+ (int)(imm), \
+ (__v4sf)(__m128)(W), \
+ (__mmask8)(U))
+
+#define _mm256_maskz_extractf32x4_ps(U, A, imm) \
+ (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \
+ (int)(imm), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)(U))
+
+#define _mm256_extracti32x4_epi32(A, imm) \
+ (__m128i)__builtin_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \
+ (int)(imm), \
+ (__v4si)_mm_undefined_si128(), \
+ (__mmask8)-1)
+
+#define _mm256_mask_extracti32x4_epi32(W, U, A, imm) \
+ (__m128i)__builtin_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \
+ (int)(imm), \
+ (__v4si)(__m128i)(W), \
+ (__mmask8)(U))
+
+#define _mm256_maskz_extracti32x4_epi32(U, A, imm) \
+ (__m128i)__builtin_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \
+ (int)(imm), \
+ (__v4si)_mm_setzero_si128(), \
+ (__mmask8)(U))
+
+#define _mm256_insertf32x4(A, B, imm) \
+ (__m256)__builtin_ia32_insertf32x4_256((__v8sf)(__m256)(A), \
+ (__v4sf)(__m128)(B), (int)(imm))
+
+#define _mm256_mask_insertf32x4(W, U, A, B, imm) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_insertf32x4((A), (B), (imm)), \
- (__v8sf)(W)); })
+ (__v8sf)(__m256)(W))
-#define _mm256_maskz_insertf32x4(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_insertf32x4(U, A, B, imm) \
(__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
(__v8sf)_mm256_insertf32x4((A), (B), (imm)), \
- (__v8sf)_mm256_setzero_ps()); })
-
-#define _mm256_inserti32x4(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v8si)(A), \
- (__v8si)_mm256_castsi128_si256((__m128i)(B)), \
- ((imm) & 0x1) ? 0 : 8, \
- ((imm) & 0x1) ? 1 : 9, \
- ((imm) & 0x1) ? 2 : 10, \
- ((imm) & 0x1) ? 3 : 11, \
- ((imm) & 0x1) ? 8 : 4, \
- ((imm) & 0x1) ? 9 : 5, \
- ((imm) & 0x1) ? 10 : 6, \
- ((imm) & 0x1) ? 11 : 7); })
-
-#define _mm256_mask_inserti32x4(W, U, A, B, imm) __extension__ ({ \
+ (__v8sf)_mm256_setzero_ps())
+
+#define _mm256_inserti32x4(A, B, imm) \
+ (__m256i)__builtin_ia32_inserti32x4_256((__v8si)(__m256i)(A), \
+ (__v4si)(__m128i)(B), (int)(imm))
+
+#define _mm256_mask_inserti32x4(W, U, A, B, imm) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_inserti32x4((A), (B), (imm)), \
- (__v8si)(W)); })
+ (__v8si)(__m256i)(W))
-#define _mm256_maskz_inserti32x4(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_inserti32x4(U, A, B, imm) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_inserti32x4((A), (B), (imm)), \
- (__v8si)_mm256_setzero_si256()); })
+ (__v8si)_mm256_setzero_si256())
-#define _mm_getmant_pd(A, B, C) __extension__({\
+#define _mm_getmant_pd(A, B, C) \
(__m128d)__builtin_ia32_getmantpd128_mask((__v2df)(__m128d)(A), \
(int)(((C)<<2) | (B)), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_getmant_pd(W, U, A, B, C) __extension__({\
+#define _mm_mask_getmant_pd(W, U, A, B, C) \
(__m128d)__builtin_ia32_getmantpd128_mask((__v2df)(__m128d)(A), \
(int)(((C)<<2) | (B)), \
(__v2df)(__m128d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_getmant_pd(U, A, B, C) __extension__({\
+#define _mm_maskz_getmant_pd(U, A, B, C) \
(__m128d)__builtin_ia32_getmantpd128_mask((__v2df)(__m128d)(A), \
(int)(((C)<<2) | (B)), \
(__v2df)_mm_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_getmant_pd(A, B, C) __extension__ ({ \
+#define _mm256_getmant_pd(A, B, C) \
(__m256d)__builtin_ia32_getmantpd256_mask((__v4df)(__m256d)(A), \
(int)(((C)<<2) | (B)), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_getmant_pd(W, U, A, B, C) __extension__ ({ \
+#define _mm256_mask_getmant_pd(W, U, A, B, C) \
(__m256d)__builtin_ia32_getmantpd256_mask((__v4df)(__m256d)(A), \
(int)(((C)<<2) | (B)), \
(__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_getmant_pd(U, A, B, C) __extension__ ({ \
+#define _mm256_maskz_getmant_pd(U, A, B, C) \
(__m256d)__builtin_ia32_getmantpd256_mask((__v4df)(__m256d)(A), \
(int)(((C)<<2) | (B)), \
(__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_getmant_ps(A, B, C) __extension__ ({ \
+#define _mm_getmant_ps(A, B, C) \
(__m128)__builtin_ia32_getmantps128_mask((__v4sf)(__m128)(A), \
(int)(((C)<<2) | (B)), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm_mask_getmant_ps(W, U, A, B, C) __extension__ ({ \
+#define _mm_mask_getmant_ps(W, U, A, B, C) \
(__m128)__builtin_ia32_getmantps128_mask((__v4sf)(__m128)(A), \
(int)(((C)<<2) | (B)), \
(__v4sf)(__m128)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_getmant_ps(U, A, B, C) __extension__ ({ \
+#define _mm_maskz_getmant_ps(U, A, B, C) \
(__m128)__builtin_ia32_getmantps128_mask((__v4sf)(__m128)(A), \
(int)(((C)<<2) | (B)), \
(__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_getmant_ps(A, B, C) __extension__ ({ \
+#define _mm256_getmant_ps(A, B, C) \
(__m256)__builtin_ia32_getmantps256_mask((__v8sf)(__m256)(A), \
(int)(((C)<<2) | (B)), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__mmask8)-1)
-#define _mm256_mask_getmant_ps(W, U, A, B, C) __extension__ ({ \
+#define _mm256_mask_getmant_ps(W, U, A, B, C) \
(__m256)__builtin_ia32_getmantps256_mask((__v8sf)(__m256)(A), \
(int)(((C)<<2) | (B)), \
(__v8sf)(__m256)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_getmant_ps(U, A, B, C) __extension__ ({ \
+#define _mm256_maskz_getmant_ps(U, A, B, C) \
(__m256)__builtin_ia32_getmantps256_mask((__v8sf)(__m256)(A), \
(int)(((C)<<2) | (B)), \
(__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_mmask_i64gather_pd(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i64gather_pd(v1_old, mask, index, addr, scale) \
(__m128d)__builtin_ia32_gather3div2df((__v2df)(__m128d)(v1_old), \
(double const *)(addr), \
(__v2di)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i64gather_epi64(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i64gather_epi64(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3div2di((__v2di)(__m128i)(v1_old), \
(long long const *)(addr), \
(__v2di)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i64gather_pd(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i64gather_pd(v1_old, mask, index, addr, scale) \
(__m256d)__builtin_ia32_gather3div4df((__v4df)(__m256d)(v1_old), \
(double const *)(addr), \
(__v4di)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i64gather_epi64(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i64gather_epi64(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gather3div4di((__v4di)(__m256i)(v1_old), \
(long long const *)(addr), \
(__v4di)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i64gather_ps(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i64gather_ps(v1_old, mask, index, addr, scale) \
(__m128)__builtin_ia32_gather3div4sf((__v4sf)(__m128)(v1_old), \
(float const *)(addr), \
(__v2di)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i64gather_epi32(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i64gather_epi32(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3div4si((__v4si)(__m128i)(v1_old), \
(int const *)(addr), \
(__v2di)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i64gather_ps(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i64gather_ps(v1_old, mask, index, addr, scale) \
(__m128)__builtin_ia32_gather3div8sf((__v4sf)(__m128)(v1_old), \
(float const *)(addr), \
(__v4di)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i64gather_epi32(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i64gather_epi32(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3div8si((__v4si)(__m128i)(v1_old), \
(int const *)(addr), \
(__v4di)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i32gather_pd(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i32gather_pd(v1_old, mask, index, addr, scale) \
(__m128d)__builtin_ia32_gather3siv2df((__v2df)(__m128d)(v1_old), \
(double const *)(addr), \
(__v4si)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i32gather_epi64(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i32gather_epi64(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3siv2di((__v2di)(__m128i)(v1_old), \
(long long const *)(addr), \
(__v4si)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i32gather_pd(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i32gather_pd(v1_old, mask, index, addr, scale) \
(__m256d)__builtin_ia32_gather3siv4df((__v4df)(__m256d)(v1_old), \
(double const *)(addr), \
(__v4si)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i32gather_epi64(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i32gather_epi64(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gather3siv4di((__v4di)(__m256i)(v1_old), \
(long long const *)(addr), \
(__v4si)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i32gather_ps(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i32gather_ps(v1_old, mask, index, addr, scale) \
(__m128)__builtin_ia32_gather3siv4sf((__v4sf)(__m128)(v1_old), \
(float const *)(addr), \
(__v4si)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm_mmask_i32gather_epi32(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm_mmask_i32gather_epi32(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3siv4si((__v4si)(__m128i)(v1_old), \
(int const *)(addr), \
(__v4si)(__m128i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i32gather_ps(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i32gather_ps(v1_old, mask, index, addr, scale) \
(__m256)__builtin_ia32_gather3siv8sf((__v8sf)(__m256)(v1_old), \
(float const *)(addr), \
(__v8si)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_mmask_i32gather_epi32(v1_old, mask, index, addr, scale) __extension__ ({\
+#define _mm256_mmask_i32gather_epi32(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gather3siv8si((__v8si)(__m256i)(v1_old), \
(int const *)(addr), \
(__v8si)(__m256i)(index), \
- (__mmask8)(mask), (int)(scale)); })
+ (__mmask8)(mask), (int)(scale))
-#define _mm256_permutex_pd(X, C) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v4df)(__m256d)(X), \
- (__v4df)_mm256_undefined_pd(), \
- ((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \
- ((C) >> 4) & 0x3, ((C) >> 6) & 0x3); })
+#define _mm256_permutex_pd(X, C) \
+ (__m256d)__builtin_ia32_permdf256((__v4df)(__m256d)(X), (int)(C))
-#define _mm256_mask_permutex_pd(W, U, X, C) __extension__ ({ \
+#define _mm256_mask_permutex_pd(W, U, X, C) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_permutex_pd((X), (C)), \
- (__v4df)(__m256d)(W)); })
+ (__v4df)(__m256d)(W))
-#define _mm256_maskz_permutex_pd(U, X, C) __extension__ ({ \
+#define _mm256_maskz_permutex_pd(U, X, C) \
(__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
(__v4df)_mm256_permutex_pd((X), (C)), \
- (__v4df)_mm256_setzero_pd()); })
+ (__v4df)_mm256_setzero_pd())
-#define _mm256_permutex_epi64(X, C) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v4di)(__m256i)(X), \
- (__v4di)_mm256_undefined_si256(), \
- ((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \
- ((C) >> 4) & 0x3, ((C) >> 6) & 0x3); })
+#define _mm256_permutex_epi64(X, C) \
+ (__m256i)__builtin_ia32_permdi256((__v4di)(__m256i)(X), (int)(C))
-#define _mm256_mask_permutex_epi64(W, U, X, C) __extension__ ({ \
+#define _mm256_mask_permutex_epi64(W, U, X, C) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_permutex_epi64((X), (C)), \
- (__v4di)(__m256i)(W)); })
+ (__v4di)(__m256i)(W))
-#define _mm256_maskz_permutex_epi64(U, X, C) __extension__ ({ \
+#define _mm256_maskz_permutex_epi64(U, X, C) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_permutex_epi64((X), (C)), \
- (__v4di)_mm256_setzero_si256()); })
+ (__v4di)_mm256_setzero_si256())
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_permutexvar_pd (__m256i __X, __m256d __Y)
{
- return (__m256d) __builtin_ia32_permvardf256_mask ((__v4df) __Y,
- (__v4di) __X,
- (__v4df) _mm256_undefined_si256 (),
- (__mmask8) -1);
+ return (__m256d)__builtin_ia32_permvardf256((__v4df)__Y, (__v4di)__X);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_permutexvar_pd (__m256d __W, __mmask8 __U, __m256i __X,
__m256d __Y)
{
- return (__m256d) __builtin_ia32_permvardf256_mask ((__v4df) __Y,
- (__v4di) __X,
- (__v4df) __W,
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_permutexvar_pd(__X, __Y),
+ (__v4df)__W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_permutexvar_pd (__mmask8 __U, __m256i __X, __m256d __Y)
{
- return (__m256d) __builtin_ia32_permvardf256_mask ((__v4df) __Y,
- (__v4di) __X,
- (__v4df) _mm256_setzero_pd (),
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_permutexvar_pd(__X, __Y),
+ (__v4df)_mm256_setzero_pd());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_permutexvar_epi64 (__mmask8 __M, __m256i __X, __m256i __Y)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_permutexvar_epi64 ( __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y,
- (__v4di) __X,
- (__v4di) _mm256_setzero_si256 (),
- (__mmask8) __M);
+ return (__m256i)__builtin_ia32_permvardi256((__v4di) __Y, (__v4di) __X);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_permutexvar_epi64 ( __m256i __X, __m256i __Y)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_maskz_permutexvar_epi64 (__mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y,
- (__v4di) __X,
- (__v4di) _mm256_undefined_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_permutexvar_epi64(__X, __Y),
+ (__v4di)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_permutexvar_epi64 (__m256i __W, __mmask8 __M, __m256i __X,
__m256i __Y)
{
- return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y,
- (__v4di) __X,
- (__v4di) __W,
- __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_permutexvar_epi64(__X, __Y),
+ (__v4di)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask_permutexvar_ps (__m256 __W, __mmask8 __U, __m256i __X,
- __m256 __Y)
-{
- return (__m256) __builtin_ia32_permvarsf256_mask ((__v8sf) __Y,
- (__v8si) __X,
- (__v8sf) __W,
- (__mmask8) __U);
-}
+#define _mm256_permutexvar_ps(A, B) _mm256_permutevar8x32_ps((B), (A))
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_maskz_permutexvar_ps (__mmask8 __U, __m256i __X, __m256 __Y)
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
+_mm256_mask_permutexvar_ps(__m256 __W, __mmask8 __U, __m256i __X, __m256 __Y)
{
- return (__m256) __builtin_ia32_permvarsf256_mask ((__v8sf) __Y,
- (__v8si) __X,
- (__v8sf) _mm256_setzero_ps (),
- (__mmask8) __U);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_permutexvar_ps(__X, __Y),
+ (__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_permutexvar_ps (__m256i __X, __m256 __Y)
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
+_mm256_maskz_permutexvar_ps(__mmask8 __U, __m256i __X, __m256 __Y)
{
- return (__m256) __builtin_ia32_permvarsf256_mask ((__v8sf) __Y,
- (__v8si) __X,
- (__v8sf) _mm256_undefined_si256 (),
- (__mmask8) -1);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_permutexvar_ps(__X, __Y),
+ (__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_permutexvar_epi32 (__mmask8 __M, __m256i __X, __m256i __Y)
-{
- return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y,
- (__v8si) __X,
- (__v8si) _mm256_setzero_si256 (),
- __M);
-}
+#define _mm256_permutexvar_epi32(A, B) _mm256_permutevar8x32_epi32((B), (A))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_permutexvar_epi32 (__m256i __W, __mmask8 __M, __m256i __X,
- __m256i __Y)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_mask_permutexvar_epi32(__m256i __W, __mmask8 __M, __m256i __X,
+ __m256i __Y)
{
- return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y,
- (__v8si) __X,
- (__v8si) __W,
- (__mmask8) __M);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
+ (__v8si)_mm256_permutexvar_epi32(__X, __Y),
+ (__v8si)__W);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_permutexvar_epi32 (__m256i __X, __m256i __Y)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y,
- (__v8si) __X,
- (__v8si) _mm256_undefined_si256(),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
+ (__v8si)_mm256_permutexvar_epi32(__X, __Y),
+ (__v8si)_mm256_setzero_si256());
}
-#define _mm_alignr_epi32(A, B, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v4si)(__m128i)(B), \
- (__v4si)(__m128i)(A), \
- ((int)(imm) & 0x3) + 0, \
- ((int)(imm) & 0x3) + 1, \
- ((int)(imm) & 0x3) + 2, \
- ((int)(imm) & 0x3) + 3); })
+#define _mm_alignr_epi32(A, B, imm) \
+ (__m128i)__builtin_ia32_alignd128((__v4si)(__m128i)(A), \
+ (__v4si)(__m128i)(B), (int)(imm))
-#define _mm_mask_alignr_epi32(W, U, A, B, imm) __extension__ ({ \
+#define _mm_mask_alignr_epi32(W, U, A, B, imm) \
(__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
(__v4si)_mm_alignr_epi32((A), (B), (imm)), \
- (__v4si)(__m128i)(W)); })
+ (__v4si)(__m128i)(W))
-#define _mm_maskz_alignr_epi32(U, A, B, imm) __extension__ ({ \
+#define _mm_maskz_alignr_epi32(U, A, B, imm) \
(__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
(__v4si)_mm_alignr_epi32((A), (B), (imm)), \
- (__v4si)_mm_setzero_si128()); })
-
-#define _mm256_alignr_epi32(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v8si)(__m256i)(B), \
- (__v8si)(__m256i)(A), \
- ((int)(imm) & 0x7) + 0, \
- ((int)(imm) & 0x7) + 1, \
- ((int)(imm) & 0x7) + 2, \
- ((int)(imm) & 0x7) + 3, \
- ((int)(imm) & 0x7) + 4, \
- ((int)(imm) & 0x7) + 5, \
- ((int)(imm) & 0x7) + 6, \
- ((int)(imm) & 0x7) + 7); })
-
-#define _mm256_mask_alignr_epi32(W, U, A, B, imm) __extension__ ({ \
+ (__v4si)_mm_setzero_si128())
+
+#define _mm256_alignr_epi32(A, B, imm) \
+ (__m256i)__builtin_ia32_alignd256((__v8si)(__m256i)(A), \
+ (__v8si)(__m256i)(B), (int)(imm))
+
+#define _mm256_mask_alignr_epi32(W, U, A, B, imm) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_alignr_epi32((A), (B), (imm)), \
- (__v8si)(__m256i)(W)); })
+ (__v8si)(__m256i)(W))
-#define _mm256_maskz_alignr_epi32(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_alignr_epi32(U, A, B, imm) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_alignr_epi32((A), (B), (imm)), \
- (__v8si)_mm256_setzero_si256()); })
+ (__v8si)_mm256_setzero_si256())
-#define _mm_alignr_epi64(A, B, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v2di)(__m128i)(B), \
- (__v2di)(__m128i)(A), \
- ((int)(imm) & 0x1) + 0, \
- ((int)(imm) & 0x1) + 1); })
+#define _mm_alignr_epi64(A, B, imm) \
+ (__m128i)__builtin_ia32_alignq128((__v2di)(__m128i)(A), \
+ (__v2di)(__m128i)(B), (int)(imm))
-#define _mm_mask_alignr_epi64(W, U, A, B, imm) __extension__ ({ \
+#define _mm_mask_alignr_epi64(W, U, A, B, imm) \
(__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
(__v2di)_mm_alignr_epi64((A), (B), (imm)), \
- (__v2di)(__m128i)(W)); })
+ (__v2di)(__m128i)(W))
-#define _mm_maskz_alignr_epi64(U, A, B, imm) __extension__ ({ \
+#define _mm_maskz_alignr_epi64(U, A, B, imm) \
(__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
(__v2di)_mm_alignr_epi64((A), (B), (imm)), \
- (__v2di)_mm_setzero_di()); })
+ (__v2di)_mm_setzero_si128())
-#define _mm256_alignr_epi64(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_shufflevector((__v4di)(__m256i)(B), \
- (__v4di)(__m256i)(A), \
- ((int)(imm) & 0x3) + 0, \
- ((int)(imm) & 0x3) + 1, \
- ((int)(imm) & 0x3) + 2, \
- ((int)(imm) & 0x3) + 3); })
+#define _mm256_alignr_epi64(A, B, imm) \
+ (__m256i)__builtin_ia32_alignq256((__v4di)(__m256i)(A), \
+ (__v4di)(__m256i)(B), (int)(imm))
-#define _mm256_mask_alignr_epi64(W, U, A, B, imm) __extension__ ({ \
+#define _mm256_mask_alignr_epi64(W, U, A, B, imm) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_alignr_epi64((A), (B), (imm)), \
- (__v4di)(__m256i)(W)); })
+ (__v4di)(__m256i)(W))
-#define _mm256_maskz_alignr_epi64(U, A, B, imm) __extension__ ({ \
+#define _mm256_maskz_alignr_epi64(U, A, B, imm) \
(__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
(__v4di)_mm256_alignr_epi64((A), (B), (imm)), \
- (__v4di)_mm256_setzero_si256()); })
+ (__v4di)_mm256_setzero_si256())
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_movehdup_ps (__m128 __W, __mmask8 __U, __m128 __A)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -8316,7 +8036,7 @@ _mm_mask_movehdup_ps (__m128 __W, __mmask8 __U, __m128 __A)
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_movehdup_ps (__mmask8 __U, __m128 __A)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -8324,7 +8044,7 @@ _mm_maskz_movehdup_ps (__mmask8 __U, __m128 __A)
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_movehdup_ps (__m256 __W, __mmask8 __U, __m256 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -8332,7 +8052,7 @@ _mm256_mask_movehdup_ps (__m256 __W, __mmask8 __U, __m256 __A)
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_movehdup_ps (__mmask8 __U, __m256 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -8340,7 +8060,7 @@ _mm256_maskz_movehdup_ps (__mmask8 __U, __m256 __A)
(__v8sf)_mm256_setzero_ps());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_moveldup_ps (__m128 __W, __mmask8 __U, __m128 __A)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -8348,7 +8068,7 @@ _mm_mask_moveldup_ps (__m128 __W, __mmask8 __U, __m128 __A)
(__v4sf)__W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_moveldup_ps (__mmask8 __U, __m128 __A)
{
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
@@ -8356,7 +8076,7 @@ _mm_maskz_moveldup_ps (__mmask8 __U, __m128 __A)
(__v4sf)_mm_setzero_ps());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_moveldup_ps (__m256 __W, __mmask8 __U, __m256 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -8364,7 +8084,7 @@ _mm256_mask_moveldup_ps (__m256 __W, __mmask8 __U, __m256 __A)
(__v8sf)__W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A)
{
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
@@ -8372,27 +8092,27 @@ _mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A)
(__v8sf)_mm256_setzero_ps());
}
-#define _mm256_mask_shuffle_epi32(W, U, A, I) __extension__({\
+#define _mm256_mask_shuffle_epi32(W, U, A, I) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_shuffle_epi32((A), (I)), \
- (__v8si)(__m256i)(W)); })
+ (__v8si)(__m256i)(W))
-#define _mm256_maskz_shuffle_epi32(U, A, I) __extension__({\
+#define _mm256_maskz_shuffle_epi32(U, A, I) \
(__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
(__v8si)_mm256_shuffle_epi32((A), (I)), \
- (__v8si)_mm256_setzero_si256()); })
+ (__v8si)_mm256_setzero_si256())
-#define _mm_mask_shuffle_epi32(W, U, A, I) __extension__({\
+#define _mm_mask_shuffle_epi32(W, U, A, I) \
(__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
(__v4si)_mm_shuffle_epi32((A), (I)), \
- (__v4si)(__m128i)(W)); })
+ (__v4si)(__m128i)(W))
-#define _mm_maskz_shuffle_epi32(U, A, I) __extension__({\
+#define _mm_maskz_shuffle_epi32(U, A, I) \
(__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
(__v4si)_mm_shuffle_epi32((A), (I)), \
- (__v4si)_mm_setzero_si128()); })
+ (__v4si)_mm_setzero_si128())
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
@@ -8400,7 +8120,7 @@ _mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A)
(__v2df) __W);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_mov_pd (__mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
@@ -8408,7 +8128,7 @@ _mm_maskz_mov_pd (__mmask8 __U, __m128d __A)
(__v2df) _mm_setzero_pd ());
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
@@ -8416,7 +8136,7 @@ _mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A)
(__v4df) __W);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_pd (__mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
@@ -8424,7 +8144,7 @@ _mm256_maskz_mov_pd (__mmask8 __U, __m256d __A)
(__v4df) _mm256_setzero_pd ());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
@@ -8432,7 +8152,7 @@ _mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A)
(__v4sf) __W);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_mov_ps (__mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
@@ -8440,7 +8160,7 @@ _mm_maskz_mov_ps (__mmask8 __U, __m128 __A)
(__v4sf) _mm_setzero_ps ());
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
@@ -8448,7 +8168,7 @@ _mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A)
(__v8sf) __W);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_ps (__mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
@@ -8456,7 +8176,7 @@ _mm256_maskz_mov_ps (__mmask8 __U, __m256 __A)
(__v8sf) _mm256_setzero_ps ());
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_cvtph_ps (__m128 __W, __mmask8 __U, __m128i __A)
{
return (__m128) __builtin_ia32_vcvtph2ps_mask ((__v8hi) __A,
@@ -8464,7 +8184,7 @@ _mm_mask_cvtph_ps (__m128 __W, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_cvtph_ps (__mmask8 __U, __m128i __A)
{
return (__m128) __builtin_ia32_vcvtph2ps_mask ((__v8hi) __A,
@@ -8473,7 +8193,7 @@ _mm_maskz_cvtph_ps (__mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_cvtph_ps (__m256 __W, __mmask8 __U, __m128i __A)
{
return (__m256) __builtin_ia32_vcvtph2ps256_mask ((__v8hi) __A,
@@ -8481,7 +8201,7 @@ _mm256_mask_cvtph_ps (__m256 __W, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A)
{
return (__m256) __builtin_ia32_vcvtph2ps256_mask ((__v8hi) __A,
@@ -8490,7 +8210,7 @@ _mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A)
(__mmask8) __U);
}
-static __inline __m128i __DEFAULT_FN_ATTRS
+static __inline __m128i __DEFAULT_FN_ATTRS128
_mm_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m128 __A)
{
return (__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf) __A, _MM_FROUND_CUR_DIRECTION,
@@ -8498,7 +8218,7 @@ _mm_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-static __inline __m128i __DEFAULT_FN_ATTRS
+static __inline __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_cvtps_ph (__mmask8 __U, __m128 __A)
{
return (__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf) __A, _MM_FROUND_CUR_DIRECTION,
@@ -8506,17 +8226,17 @@ _mm_maskz_cvtps_ph (__mmask8 __U, __m128 __A)
(__mmask8) __U);
}
-#define _mm_mask_cvt_roundps_ph(W, U, A, I) __extension__ ({ \
+#define _mm_mask_cvt_roundps_ph(W, U, A, I) \
(__m128i)__builtin_ia32_vcvtps2ph_mask((__v4sf)(__m128)(A), (int)(I), \
(__v8hi)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm_maskz_cvt_roundps_ph(U, A, I) __extension__ ({ \
+#define _mm_maskz_cvt_roundps_ph(U, A, I) \
(__m128i)__builtin_ia32_vcvtps2ph_mask((__v4sf)(__m128)(A), (int)(I), \
(__v8hi)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-static __inline __m128i __DEFAULT_FN_ATTRS
+static __inline __m128i __DEFAULT_FN_ATTRS256
_mm256_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m256 __A)
{
return (__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf) __A, _MM_FROUND_CUR_DIRECTION,
@@ -8524,24 +8244,25 @@ _mm256_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m256 __A)
(__mmask8) __U);
}
-static __inline __m128i __DEFAULT_FN_ATTRS
+static __inline __m128i __DEFAULT_FN_ATTRS256
_mm256_maskz_cvtps_ph ( __mmask8 __U, __m256 __A)
{
return (__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf) __A, _MM_FROUND_CUR_DIRECTION,
(__v8hi) _mm_setzero_si128(),
(__mmask8) __U);
}
-#define _mm256_mask_cvt_roundps_ph(W, U, A, I) __extension__ ({ \
+#define _mm256_mask_cvt_roundps_ph(W, U, A, I) \
(__m128i)__builtin_ia32_vcvtps2ph256_mask((__v8sf)(__m256)(A), (int)(I), \
(__v8hi)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#define _mm256_maskz_cvt_roundps_ph(U, A, I) __extension__ ({ \
+#define _mm256_maskz_cvt_roundps_ph(U, A, I) \
(__m128i)__builtin_ia32_vcvtps2ph256_mask((__v8sf)(__m256)(A), (int)(I), \
(__v8hi)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+ (__mmask8)(U))
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif /* __AVX512VLINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlvbmi2intrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlvbmi2intrin.h
index 5b05376fc4b2..baaf5654631c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlvbmi2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlvbmi2intrin.h
@@ -29,9 +29,10 @@
#define __AVX512VLVBMI2INTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vbmi2")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vbmi2"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vbmi2"), __min_vector_width__(256)))
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __D,
@@ -39,7 +40,7 @@ _mm_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_compress_epi16(__mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __D,
@@ -47,7 +48,7 @@ _mm_maskz_compress_epi16(__mmask8 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __D,
@@ -55,7 +56,7 @@ _mm_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_compress_epi8(__mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __D,
@@ -63,21 +64,21 @@ _mm_maskz_compress_epi8(__mmask16 __U, __m128i __D)
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_compressstoreu_epi16(void *__P, __mmask8 __U, __m128i __D)
{
__builtin_ia32_compressstorehi128_mask ((__v8hi *) __P, (__v8hi) __D,
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_compressstoreu_epi8(void *__P, __mmask16 __U, __m128i __D)
{
__builtin_ia32_compressstoreqi128_mask ((__v16qi *) __P, (__v16qi) __D,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __D,
@@ -85,7 +86,7 @@ _mm_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expand_epi16(__mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __D,
@@ -93,7 +94,7 @@ _mm_maskz_expand_epi16(__mmask8 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __D,
@@ -101,7 +102,7 @@ _mm_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expand_epi8(__mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __D,
@@ -109,7 +110,7 @@ _mm_maskz_expand_epi8(__mmask16 __U, __m128i __D)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_expandloadhi128_mask ((const __v8hi *)__P,
@@ -117,7 +118,7 @@ _mm_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expandloadu_epi16(__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_expandloadhi128_mask ((const __v8hi *)__P,
@@ -125,7 +126,7 @@ _mm_maskz_expandloadu_epi16(__mmask8 __U, void const *__P)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const *__P)
{
return (__m128i) __builtin_ia32_expandloadqi128_mask ((const __v16qi *)__P,
@@ -133,7 +134,7 @@ _mm_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const *__P)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_expandloadu_epi8(__mmask16 __U, void const *__P)
{
return (__m128i) __builtin_ia32_expandloadqi128_mask ((const __v16qi *)__P,
@@ -141,7 +142,7 @@ _mm_maskz_expandloadu_epi8(__mmask16 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_compress_epi16(__m256i __S, __mmask16 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi) __D,
@@ -149,7 +150,7 @@ _mm256_mask_compress_epi16(__m256i __S, __mmask16 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_compress_epi16(__mmask16 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi) __D,
@@ -157,7 +158,7 @@ _mm256_maskz_compress_epi16(__mmask16 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_compress_epi8(__m256i __S, __mmask32 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_compressqi256_mask ((__v32qi) __D,
@@ -165,7 +166,7 @@ _mm256_mask_compress_epi8(__m256i __S, __mmask32 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_compress_epi8(__mmask32 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_compressqi256_mask ((__v32qi) __D,
@@ -173,21 +174,21 @@ _mm256_maskz_compress_epi8(__mmask32 __U, __m256i __D)
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_compressstoreu_epi16(void *__P, __mmask16 __U, __m256i __D)
{
__builtin_ia32_compressstorehi256_mask ((__v16hi *) __P, (__v16hi) __D,
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_compressstoreu_epi8(void *__P, __mmask32 __U, __m256i __D)
{
__builtin_ia32_compressstoreqi256_mask ((__v32qi *) __P, (__v32qi) __D,
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expand_epi16(__m256i __S, __mmask16 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_expandhi256_mask ((__v16hi) __D,
@@ -195,7 +196,7 @@ _mm256_mask_expand_epi16(__m256i __S, __mmask16 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expand_epi16(__mmask16 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_expandhi256_mask ((__v16hi) __D,
@@ -203,7 +204,7 @@ _mm256_maskz_expand_epi16(__mmask16 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expand_epi8(__m256i __S, __mmask32 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_expandqi256_mask ((__v32qi) __D,
@@ -211,7 +212,7 @@ _mm256_mask_expand_epi8(__m256i __S, __mmask32 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expand_epi8(__mmask32 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_expandqi256_mask ((__v32qi) __D,
@@ -219,7 +220,7 @@ _mm256_maskz_expand_epi8(__mmask32 __U, __m256i __D)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expandloadu_epi16(__m256i __S, __mmask16 __U, void const *__P)
{
return (__m256i) __builtin_ia32_expandloadhi256_mask ((const __v16hi *)__P,
@@ -227,7 +228,7 @@ _mm256_mask_expandloadu_epi16(__m256i __S, __mmask16 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expandloadu_epi16(__mmask16 __U, void const *__P)
{
return (__m256i) __builtin_ia32_expandloadhi256_mask ((const __v16hi *)__P,
@@ -235,7 +236,7 @@ _mm256_maskz_expandloadu_epi16(__mmask16 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_expandloadu_epi8(__m256i __S, __mmask32 __U, void const *__P)
{
return (__m256i) __builtin_ia32_expandloadqi256_mask ((const __v32qi *)__P,
@@ -243,7 +244,7 @@ _mm256_mask_expandloadu_epi8(__m256i __S, __mmask32 __U, void const *__P)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_expandloadu_epi8(__mmask32 __U, void const *__P)
{
return (__m256i) __builtin_ia32_expandloadqi256_mask ((const __v32qi *)__P,
@@ -251,163 +252,175 @@ _mm256_maskz_expandloadu_epi8(__mmask32 __U, void const *__P)
__U);
}
-#define _mm256_mask_shldi_epi64(S, U, A, B, I) __extension__ ({ \
- (__m256i)__builtin_ia32_vpshldq256_mask((__v4di)(A), \
- (__v4di)(B), \
- (int)(I), \
- (__v4di)(S), \
- (__mmask8)(U)); })
+#define _mm256_shldi_epi64(A, B, I) \
+ (__m256i)__builtin_ia32_vpshldq256((__v4di)(__m256i)(A), \
+ (__v4di)(__m256i)(B), (int)(I))
+
+#define _mm256_mask_shldi_epi64(S, U, A, B, I) \
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_shldi_epi64((A), (B), (I)), \
+ (__v4di)(__m256i)(S))
#define _mm256_maskz_shldi_epi64(U, A, B, I) \
- _mm256_mask_shldi_epi64(_mm256_setzero_si256(), (U), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_shldi_epi64((A), (B), (I)), \
+ (__v4di)_mm256_setzero_si256())
-#define _mm256_shldi_epi64(A, B, I) \
- _mm256_mask_shldi_epi64(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_shldi_epi64(A, B, I) \
+ (__m128i)__builtin_ia32_vpshldq128((__v2di)(__m128i)(A), \
+ (__v2di)(__m128i)(B), (int)(I))
-#define _mm_mask_shldi_epi64(S, U, A, B, I) __extension__ ({ \
- (__m128i)__builtin_ia32_vpshldq128_mask((__v2di)(A), \
- (__v2di)(B), \
- (int)(I), \
- (__v2di)(S), \
- (__mmask8)(U)); })
+#define _mm_mask_shldi_epi64(S, U, A, B, I) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_shldi_epi64((A), (B), (I)), \
+ (__v2di)(__m128i)(S))
#define _mm_maskz_shldi_epi64(U, A, B, I) \
- _mm_mask_shldi_epi64(_mm_setzero_si128(), (U), (A), (B), (I))
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_shldi_epi64((A), (B), (I)), \
+ (__v2di)_mm_setzero_si128())
-#define _mm_shldi_epi64(A, B, I) \
- _mm_mask_shldi_epi64(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+#define _mm256_shldi_epi32(A, B, I) \
+ (__m256i)__builtin_ia32_vpshldd256((__v8si)(__m256i)(A), \
+ (__v8si)(__m256i)(B), (int)(I))
-#define _mm256_mask_shldi_epi32(S, U, A, B, I) __extension__ ({ \
- (__m256i)__builtin_ia32_vpshldd256_mask((__v8si)(A), \
- (__v8si)(B), \
- (int)(I), \
- (__v8si)(S), \
- (__mmask8)(U)); })
+#define _mm256_mask_shldi_epi32(S, U, A, B, I) \
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_shldi_epi32((A), (B), (I)), \
+ (__v8si)(__m256i)(S))
#define _mm256_maskz_shldi_epi32(U, A, B, I) \
- _mm256_mask_shldi_epi32(_mm256_setzero_si256(), (U), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_shldi_epi32((A), (B), (I)), \
+ (__v8si)_mm256_setzero_si256())
-#define _mm256_shldi_epi32(A, B, I) \
- _mm256_mask_shldi_epi32(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_shldi_epi32(A, B, I) \
+ (__m128i)__builtin_ia32_vpshldd128((__v4si)(__m128i)(A), \
+ (__v4si)(__m128i)(B), (int)(I))
-#define _mm_mask_shldi_epi32(S, U, A, B, I) __extension__ ({ \
- (__m128i)__builtin_ia32_vpshldd128_mask((__v4si)(A), \
- (__v4si)(B), \
- (int)(I), \
- (__v4si)(S), \
- (__mmask8)(U)); })
+#define _mm_mask_shldi_epi32(S, U, A, B, I) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_shldi_epi32((A), (B), (I)), \
+ (__v4si)(__m128i)(S))
#define _mm_maskz_shldi_epi32(U, A, B, I) \
- _mm_mask_shldi_epi32(_mm_setzero_si128(), (U), (A), (B), (I))
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_shldi_epi32((A), (B), (I)), \
+ (__v4si)_mm_setzero_si128())
-#define _mm_shldi_epi32(A, B, I) \
- _mm_mask_shldi_epi32(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+#define _mm256_shldi_epi16(A, B, I) \
+ (__m256i)__builtin_ia32_vpshldw256((__v16hi)(__m256i)(A), \
+ (__v16hi)(__m256i)(B), (int)(I))
-#define _mm256_mask_shldi_epi16(S, U, A, B, I) __extension__ ({ \
- (__m256i)__builtin_ia32_vpshldw256_mask((__v16hi)(A), \
- (__v16hi)(B), \
- (int)(I), \
- (__v16hi)(S), \
- (__mmask16)(U)); })
+#define _mm256_mask_shldi_epi16(S, U, A, B, I) \
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_shldi_epi16((A), (B), (I)), \
+ (__v16hi)(__m256i)(S))
#define _mm256_maskz_shldi_epi16(U, A, B, I) \
- _mm256_mask_shldi_epi16(_mm256_setzero_si256(), (U), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_shldi_epi16((A), (B), (I)), \
+ (__v16hi)_mm256_setzero_si256())
-#define _mm256_shldi_epi16(A, B, I) \
- _mm256_mask_shldi_epi16(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_shldi_epi16(A, B, I) \
+ (__m128i)__builtin_ia32_vpshldw128((__v8hi)(__m128i)(A), \
+ (__v8hi)(__m128i)(B), (int)(I))
-#define _mm_mask_shldi_epi16(S, U, A, B, I) __extension__ ({ \
- (__m128i)__builtin_ia32_vpshldw128_mask((__v8hi)(A), \
- (__v8hi)(B), \
- (int)(I), \
- (__v8hi)(S), \
- (__mmask8)(U)); })
+#define _mm_mask_shldi_epi16(S, U, A, B, I) \
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_shldi_epi16((A), (B), (I)), \
+ (__v8hi)(__m128i)(S))
#define _mm_maskz_shldi_epi16(U, A, B, I) \
- _mm_mask_shldi_epi16(_mm_setzero_si128(), (U), (A), (B), (I))
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_shldi_epi16((A), (B), (I)), \
+ (__v8hi)_mm_setzero_si128())
-#define _mm_shldi_epi16(A, B, I) \
- _mm_mask_shldi_epi16(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+#define _mm256_shrdi_epi64(A, B, I) \
+ (__m256i)__builtin_ia32_vpshrdq256((__v4di)(__m256i)(A), \
+ (__v4di)(__m256i)(B), (int)(I))
-#define _mm256_mask_shrdi_epi64(S, U, A, B, I) __extension__ ({ \
- (__m256i)__builtin_ia32_vpshrdq256_mask((__v4di)(A), \
- (__v4di)(B), \
- (int)(I), \
- (__v4di)(S), \
- (__mmask8)(U)); })
+#define _mm256_mask_shrdi_epi64(S, U, A, B, I) \
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_shrdi_epi64((A), (B), (I)), \
+ (__v4di)(__m256i)(S))
#define _mm256_maskz_shrdi_epi64(U, A, B, I) \
- _mm256_mask_shrdi_epi64(_mm256_setzero_si256(), (U), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_shrdi_epi64((A), (B), (I)), \
+ (__v4di)_mm256_setzero_si256())
-#define _mm256_shrdi_epi64(A, B, I) \
- _mm256_mask_shrdi_epi64(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_shrdi_epi64(A, B, I) \
+ (__m128i)__builtin_ia32_vpshrdq128((__v2di)(__m128i)(A), \
+ (__v2di)(__m128i)(B), (int)(I))
-#define _mm_mask_shrdi_epi64(S, U, A, B, I) __extension__ ({ \
- (__m128i)__builtin_ia32_vpshrdq128_mask((__v2di)(A), \
- (__v2di)(B), \
- (int)(I), \
- (__v2di)(S), \
- (__mmask8)(U)); })
+#define _mm_mask_shrdi_epi64(S, U, A, B, I) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_shrdi_epi64((A), (B), (I)), \
+ (__v2di)(__m128i)(S))
#define _mm_maskz_shrdi_epi64(U, A, B, I) \
- _mm_mask_shrdi_epi64(_mm_setzero_si128(), (U), (A), (B), (I))
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_shrdi_epi64((A), (B), (I)), \
+ (__v2di)_mm_setzero_si128())
-#define _mm_shrdi_epi64(A, B, I) \
- _mm_mask_shrdi_epi64(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+#define _mm256_shrdi_epi32(A, B, I) \
+ (__m256i)__builtin_ia32_vpshrdd256((__v8si)(__m256i)(A), \
+ (__v8si)(__m256i)(B), (int)(I))
-#define _mm256_mask_shrdi_epi32(S, U, A, B, I) __extension__ ({ \
- (__m256i)__builtin_ia32_vpshrdd256_mask((__v8si)(A), \
- (__v8si)(B), \
- (int)(I), \
- (__v8si)(S), \
- (__mmask8)(U)); })
+#define _mm256_mask_shrdi_epi32(S, U, A, B, I) \
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_shrdi_epi32((A), (B), (I)), \
+ (__v8si)(__m256i)(S))
#define _mm256_maskz_shrdi_epi32(U, A, B, I) \
- _mm256_mask_shrdi_epi32(_mm256_setzero_si256(), (U), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_shrdi_epi32((A), (B), (I)), \
+ (__v8si)_mm256_setzero_si256())
-#define _mm256_shrdi_epi32(A, B, I) \
- _mm256_mask_shrdi_epi32(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_shrdi_epi32(A, B, I) \
+ (__m128i)__builtin_ia32_vpshrdd128((__v4si)(__m128i)(A), \
+ (__v4si)(__m128i)(B), (int)(I))
-#define _mm_mask_shrdi_epi32(S, U, A, B, I) __extension__ ({ \
- (__m128i)__builtin_ia32_vpshrdd128_mask((__v4si)(A), \
- (__v4si)(B), \
- (int)(I), \
- (__v4si)(S), \
- (__mmask8)(U)); })
+#define _mm_mask_shrdi_epi32(S, U, A, B, I) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_shrdi_epi32((A), (B), (I)), \
+ (__v4si)(__m128i)(S))
#define _mm_maskz_shrdi_epi32(U, A, B, I) \
- _mm_mask_shrdi_epi32(_mm_setzero_si128(), (U), (A), (B), (I))
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_shrdi_epi32((A), (B), (I)), \
+ (__v4si)_mm_setzero_si128())
-#define _mm_shrdi_epi32(A, B, I) \
- _mm_mask_shrdi_epi32(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+#define _mm256_shrdi_epi16(A, B, I) \
+ (__m256i)__builtin_ia32_vpshrdw256((__v16hi)(__m256i)(A), \
+ (__v16hi)(__m256i)(B), (int)(I))
-#define _mm256_mask_shrdi_epi16(S, U, A, B, I) __extension__ ({ \
- (__m256i)__builtin_ia32_vpshrdw256_mask((__v16hi)(A), \
- (__v16hi)(B), \
- (int)(I), \
- (__v16hi)(S), \
- (__mmask16)(U)); })
+#define _mm256_mask_shrdi_epi16(S, U, A, B, I) \
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_shrdi_epi16((A), (B), (I)), \
+ (__v16hi)(__m256i)(S))
#define _mm256_maskz_shrdi_epi16(U, A, B, I) \
- _mm256_mask_shrdi_epi16(_mm256_setzero_si256(), (U), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_shrdi_epi16((A), (B), (I)), \
+ (__v16hi)_mm256_setzero_si256())
-#define _mm256_shrdi_epi16(A, B, I) \
- _mm256_mask_shrdi_epi16(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_shrdi_epi16(A, B, I) \
+ (__m128i)__builtin_ia32_vpshrdw128((__v8hi)(__m128i)(A), \
+ (__v8hi)(__m128i)(B), (int)(I))
-#define _mm_mask_shrdi_epi16(S, U, A, B, I) __extension__ ({ \
- (__m128i)__builtin_ia32_vpshrdw128_mask((__v8hi)(A), \
- (__v8hi)(B), \
- (int)(I), \
- (__v8hi)(S), \
- (__mmask8)(U)); })
+#define _mm_mask_shrdi_epi16(S, U, A, B, I) \
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_shrdi_epi16((A), (B), (I)), \
+ (__v8hi)(__m128i)(S))
#define _mm_maskz_shrdi_epi16(U, A, B, I) \
- _mm_mask_shrdi_epi16(_mm_setzero_si128(), (U), (A), (B), (I))
-
-#define _mm_shrdi_epi16(A, B, I) \
- _mm_mask_shrdi_epi16(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_shrdi_epi16((A), (B), (I)), \
+ (__v8hi)_mm_setzero_si128())
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvq256_mask ((__v4di) __S,
@@ -416,7 +429,7 @@ _mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvq256_maskz ((__v4di) __S,
@@ -425,7 +438,7 @@ _mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvq256_mask ((__v4di) __S,
@@ -434,7 +447,7 @@ _mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S,
@@ -443,7 +456,7 @@ _mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvq128_maskz ((__v2di) __S,
@@ -452,7 +465,7 @@ _mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S,
@@ -461,7 +474,7 @@ _mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvd256_mask ((__v8si) __S,
@@ -470,7 +483,7 @@ _mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvd256_maskz ((__v8si) __S,
@@ -479,7 +492,7 @@ _mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvd256_mask ((__v8si) __S,
@@ -488,7 +501,7 @@ _mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S,
@@ -497,7 +510,7 @@ _mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvd128_maskz ((__v4si) __S,
@@ -506,7 +519,7 @@ _mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S,
@@ -515,7 +528,7 @@ _mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvw256_mask ((__v16hi) __S,
@@ -524,7 +537,7 @@ _mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvw256_maskz ((__v16hi) __S,
@@ -533,7 +546,7 @@ _mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshldvw256_mask ((__v16hi) __S,
@@ -542,7 +555,7 @@ _mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S,
@@ -551,7 +564,7 @@ _mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvw128_maskz ((__v8hi) __S,
@@ -560,7 +573,7 @@ _mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S,
@@ -569,7 +582,7 @@ _mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvq256_mask ((__v4di) __S,
@@ -578,7 +591,7 @@ _mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvq256_maskz ((__v4di) __S,
@@ -587,7 +600,7 @@ _mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvq256_mask ((__v4di) __S,
@@ -596,7 +609,7 @@ _mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S,
@@ -605,7 +618,7 @@ _mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvq128_maskz ((__v2di) __S,
@@ -614,7 +627,7 @@ _mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S,
@@ -623,7 +636,7 @@ _mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvd256_mask ((__v8si) __S,
@@ -632,7 +645,7 @@ _mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvd256_maskz ((__v8si) __S,
@@ -641,7 +654,7 @@ _mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvd256_mask ((__v8si) __S,
@@ -650,7 +663,7 @@ _mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S,
@@ -659,7 +672,7 @@ _mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvd128_maskz ((__v4si) __S,
@@ -668,7 +681,7 @@ _mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S,
@@ -677,7 +690,7 @@ _mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B)
(__mmask8) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvw256_mask ((__v16hi) __S,
@@ -686,7 +699,7 @@ _mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvw256_maskz ((__v16hi) __S,
@@ -695,7 +708,7 @@ _mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B)
__U);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vpshrdvw256_mask ((__v16hi) __S,
@@ -704,7 +717,7 @@ _mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S,
@@ -713,7 +726,7 @@ _mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvw128_maskz ((__v8hi) __S,
@@ -722,7 +735,7 @@ _mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S,
@@ -732,6 +745,7 @@ _mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B)
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlvnniintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlvnniintrin.h
index 40cbbf29964d..62382268ec9f 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlvnniintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlvnniintrin.h
@@ -29,226 +29,195 @@
#define __AVX512VLVNNIINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vnni")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vnni"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vnni"), __min_vector_width__(256)))
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_dpbusd_epi32(__m256i __S, __m256i __A, __m256i __B)
+{
+ return (__m256i)__builtin_ia32_vpdpbusd256((__v8si)__S, (__v8si)__A,
+ (__v8si)__B);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_dpbusd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpbusd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpbusd_epi32(__S, __A, __B),
+ (__v8si)__S);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpbusd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpbusd256_maskz ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpbusd_epi32(__S, __A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_dpbusd_epi32(__m256i __S, __m256i __A, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_dpbusds_epi32(__m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpbusd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_vpdpbusds256((__v8si)__S, (__v8si)__A,
+ (__v8si)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_dpbusds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpbusds256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpbusds_epi32(__S, __A, __B),
+ (__v8si)__S);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpbusds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpbusds256_maskz ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpbusds_epi32(__S, __A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_dpbusds_epi32(__m256i __S, __m256i __A, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_dpwssd_epi32(__m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpbusds256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_vpdpwssd256((__v8si)__S, (__v8si)__A,
+ (__v8si)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_dpwssd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpwssd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpwssd_epi32(__S, __A, __B),
+ (__v8si)__S);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpwssd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpwssd256_maskz ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpwssd_epi32(__S, __A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_dpwssd_epi32(__m256i __S, __m256i __A, __m256i __B)
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_dpwssds_epi32(__m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpwssd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_vpdpwssds256((__v8si)__S, (__v8si)__A,
+ (__v8si)__B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_dpwssds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpwssds256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpwssds_epi32(__S, __A, __B),
+ (__v8si)__S);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpwssds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_vpdpwssds256_maskz ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_dpwssds_epi32(__S, __A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_dpwssds_epi32(__m256i __S, __m256i __A, __m256i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_dpbusd_epi32(__m128i __S, __m128i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_vpdpwssds256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_vpdpbusd128((__v4si)__S, (__v4si)__A,
+ (__v4si)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_dpbusd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpbusd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpbusd_epi32(__S, __A, __B),
+ (__v4si)__S);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpbusd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpbusd128_maskz ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpbusd_epi32(__S, __A, __B),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_dpbusd_epi32(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_dpbusds_epi32(__m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpbusd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_vpdpbusds128((__v4si)__S, (__v4si)__A,
+ (__v4si)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_dpbusds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpbusds128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpbusds_epi32(__S, __A, __B),
+ (__v4si)__S);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpbusds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpbusds128_maskz ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpbusds_epi32(__S, __A, __B),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_dpbusds_epi32(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_dpwssd_epi32(__m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpbusds128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_vpdpwssd128((__v4si)__S, (__v4si)__A,
+ (__v4si)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_dpwssd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpwssd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpwssd_epi32(__S, __A, __B),
+ (__v4si)__S);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwssd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpwssd128_maskz ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpwssd_epi32(__S, __A, __B),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_dpwssd_epi32(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_dpwssds_epi32(__m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpwssd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_vpdpwssds128((__v4si)__S, (__v4si)__A,
+ (__v4si)__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_dpwssds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpwssds128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpwssds_epi32(__S, __A, __B),
+ (__v4si)__S);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwssds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_vpdpwssds128_maskz ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_dpwssds_epi32(__S, __A, __B),
+ (__v4si)_mm_setzero_si128());
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_dpwssds_epi32(__m128i __S, __m128i __A, __m128i __B)
-{
- return (__m128i) __builtin_ia32_vpdpwssds128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
-}
-
-
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vnniintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vnniintrin.h
index 0c6badd231aa..620ef5a78959 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vnniintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vnniintrin.h
@@ -29,118 +29,101 @@
#define __AVX512VNNIINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_dpbusd_epi32(__m512i __S, __m512i __A, __m512i __B)
+{
+ return (__m512i)__builtin_ia32_vpdpbusd512((__v16si)__S, (__v16si)__A,
+ (__v16si)__B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_dpbusd_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpbusd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpbusd_epi32(__S, __A, __B),
+ (__v16si)__S);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_dpbusd_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpbusd512_maskz ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpbusd_epi32(__S, __A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_dpbusd_epi32(__m512i __S, __m512i __A, __m512i __B)
+_mm512_dpbusds_epi32(__m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpbusd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_vpdpbusds512((__v16si)__S, (__v16si)__A,
+ (__v16si)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_dpbusds_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpbusds512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpbusds_epi32(__S, __A, __B),
+ (__v16si)__S);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_dpbusds_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpbusds512_maskz ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpbusds_epi32(__S, __A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_dpbusds_epi32(__m512i __S, __m512i __A, __m512i __B)
+_mm512_dpwssd_epi32(__m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpbusds512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_vpdpwssd512((__v16si)__S, (__v16si)__A,
+ (__v16si)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_dpwssd_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpwssd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpwssd_epi32(__S, __A, __B),
+ (__v16si)__S);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_dpwssd_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpwssd512_maskz ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpwssd_epi32(__S, __A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_dpwssd_epi32(__m512i __S, __m512i __A, __m512i __B)
+_mm512_dpwssds_epi32(__m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpwssd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_vpdpwssds512((__v16si)__S, (__v16si)__A,
+ (__v16si)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_dpwssds_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpwssds512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpwssds_epi32(__S, __A, __B),
+ (__v16si)__S);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_dpwssds_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_vpdpwssds512_maskz ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) __U);
-}
-
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_dpwssds_epi32(__m512i __S, __m512i __A, __m512i __B)
-{
- return (__m512i) __builtin_ia32_vpdpwssds512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_dpwssds_epi32(__S, __A, __B),
+ (__v16si)_mm512_setzero_si512());
}
-
#undef __DEFAULT_FN_ATTRS
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqintrin.h
index 34ab84932e7a..c99f5945699e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqintrin.h
@@ -1,5 +1,4 @@
-/*===------------- avx512vpopcntdqintrin.h - AVX512VPOPCNTDQ intrinsics
- *------------------===
+/*===----- avx512vpopcntdqintrin.h - AVX512VPOPCNTDQ intrinsics-------------===
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,8 +31,7 @@
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS \
- __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntd" \
- "q")))
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq"), __min_vector_width__(512)))
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi64(__m512i __A) {
return (__m512i)__builtin_ia32_vpopcntq_512((__v8di)__A);
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h
index c2058a8f5154..681a75fa07cd 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h
@@ -1,5 +1,4 @@
-/*===------------- avx512vpopcntdqintrin.h - AVX512VPOPCNTDQ intrinsics
- *------------------===
+/*===---- avx512vpopcntdqintrin.h - AVX512VPOPCNTDQ intrinsics -------------===
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -31,69 +30,76 @@
#define __AVX512VPOPCNTDQVLINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS \
- __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl")))
+#define __DEFAULT_FN_ATTRS128 \
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 \
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl"), __min_vector_width__(256)))
-static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_popcnt_epi64(__m128i __A) {
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_popcnt_epi64(__m128i __A) {
return (__m128i)__builtin_ia32_vpopcntq_128((__v2di)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_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
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_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) {
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_popcnt_epi32(__m128i __A) {
return (__m128i)__builtin_ia32_vpopcntd_128((__v4si)__A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_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
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_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) {
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_popcnt_epi64(__m256i __A) {
return (__m256i)__builtin_ia32_vpopcntq_256((__v4di)__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_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
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_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) {
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_popcnt_epi32(__m256i __A) {
return (__m256i)__builtin_ia32_vpopcntd_256((__v8si)__A);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_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
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_popcnt_epi32(__mmask8 __U, __m256i __A) {
return _mm256_mask_popcnt_epi32((__m256i)_mm256_setzero_si256(), __U, __A);
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
index dff5897b6bb6..cb15396b3faf 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
@@ -50,10 +50,11 @@ typedef double __m256d __attribute__((__vector_size__(32)));
typedef long long __m256i __attribute__((__vector_size__(32)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx"), __min_vector_width__(256)))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx"), __min_vector_width__(128)))
/* Arithmetic */
-/// \brief Adds two 256-bit vectors of [4 x double].
+/// Adds two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -71,7 +72,7 @@ _mm256_add_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4df)__a+(__v4df)__b);
}
-/// \brief Adds two 256-bit vectors of [8 x float].
+/// Adds two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -89,7 +90,7 @@ _mm256_add_ps(__m256 __a, __m256 __b)
return (__m256)((__v8sf)__a+(__v8sf)__b);
}
-/// \brief Subtracts two 256-bit vectors of [4 x double].
+/// Subtracts two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -107,7 +108,7 @@ _mm256_sub_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4df)__a-(__v4df)__b);
}
-/// \brief Subtracts two 256-bit vectors of [8 x float].
+/// Subtracts two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -125,7 +126,7 @@ _mm256_sub_ps(__m256 __a, __m256 __b)
return (__m256)((__v8sf)__a-(__v8sf)__b);
}
-/// \brief Adds the even-indexed values and subtracts the odd-indexed values of
+/// Adds the even-indexed values and subtracts the odd-indexed values of
/// two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -144,7 +145,7 @@ _mm256_addsub_pd(__m256d __a, __m256d __b)
return (__m256d)__builtin_ia32_addsubpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Adds the even-indexed values and subtracts the odd-indexed values of
+/// Adds the even-indexed values and subtracts the odd-indexed values of
/// two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -163,7 +164,7 @@ _mm256_addsub_ps(__m256 __a, __m256 __b)
return (__m256)__builtin_ia32_addsubps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Divides two 256-bit vectors of [4 x double].
+/// Divides two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -181,7 +182,7 @@ _mm256_div_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4df)__a/(__v4df)__b);
}
-/// \brief Divides two 256-bit vectors of [8 x float].
+/// Divides two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -199,7 +200,7 @@ _mm256_div_ps(__m256 __a, __m256 __b)
return (__m256)((__v8sf)__a/(__v8sf)__b);
}
-/// \brief Compares two 256-bit vectors of [4 x double] and returns the greater
+/// Compares two 256-bit vectors of [4 x double] and returns the greater
/// of each pair of values.
///
/// \headerfile <x86intrin.h>
@@ -218,7 +219,7 @@ _mm256_max_pd(__m256d __a, __m256d __b)
return (__m256d)__builtin_ia32_maxpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Compares two 256-bit vectors of [8 x float] and returns the greater
+/// Compares two 256-bit vectors of [8 x float] and returns the greater
/// of each pair of values.
///
/// \headerfile <x86intrin.h>
@@ -237,7 +238,7 @@ _mm256_max_ps(__m256 __a, __m256 __b)
return (__m256)__builtin_ia32_maxps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Compares two 256-bit vectors of [4 x double] and returns the lesser
+/// Compares two 256-bit vectors of [4 x double] and returns the lesser
/// of each pair of values.
///
/// \headerfile <x86intrin.h>
@@ -256,7 +257,7 @@ _mm256_min_pd(__m256d __a, __m256d __b)
return (__m256d)__builtin_ia32_minpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Compares two 256-bit vectors of [8 x float] and returns the lesser
+/// Compares two 256-bit vectors of [8 x float] and returns the lesser
/// of each pair of values.
///
/// \headerfile <x86intrin.h>
@@ -275,7 +276,7 @@ _mm256_min_ps(__m256 __a, __m256 __b)
return (__m256)__builtin_ia32_minps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Multiplies two 256-bit vectors of [4 x double].
+/// Multiplies two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -293,7 +294,7 @@ _mm256_mul_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4df)__a * (__v4df)__b);
}
-/// \brief Multiplies two 256-bit vectors of [8 x float].
+/// Multiplies two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -311,7 +312,7 @@ _mm256_mul_ps(__m256 __a, __m256 __b)
return (__m256)((__v8sf)__a * (__v8sf)__b);
}
-/// \brief Calculates the square roots of the values in a 256-bit vector of
+/// Calculates the square roots of the values in a 256-bit vector of
/// [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -328,7 +329,7 @@ _mm256_sqrt_pd(__m256d __a)
return (__m256d)__builtin_ia32_sqrtpd256((__v4df)__a);
}
-/// \brief Calculates the square roots of the values in a 256-bit vector of
+/// Calculates the square roots of the values in a 256-bit vector of
/// [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -345,7 +346,7 @@ _mm256_sqrt_ps(__m256 __a)
return (__m256)__builtin_ia32_sqrtps256((__v8sf)__a);
}
-/// \brief Calculates the reciprocal square roots of the values in a 256-bit
+/// Calculates the reciprocal square roots of the values in a 256-bit
/// vector of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -362,7 +363,7 @@ _mm256_rsqrt_ps(__m256 __a)
return (__m256)__builtin_ia32_rsqrtps256((__v8sf)__a);
}
-/// \brief Calculates the reciprocals of the values in a 256-bit vector of
+/// Calculates the reciprocals of the values in a 256-bit vector of
/// [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -379,7 +380,7 @@ _mm256_rcp_ps(__m256 __a)
return (__m256)__builtin_ia32_rcpps256((__v8sf)__a);
}
-/// \brief Rounds the values in a 256-bit vector of [4 x double] as specified
+/// Rounds the values in a 256-bit vector of [4 x double] as specified
/// by the byte operand. The source values are rounded to integer values and
/// returned as 64-bit double-precision floating-point values.
///
@@ -408,10 +409,10 @@ _mm256_rcp_ps(__m256 __a)
/// 10: Upward (toward positive infinity). \n
/// 11: Truncated.
/// \returns A 256-bit vector of [4 x double] containing the rounded values.
-#define _mm256_round_pd(V, M) __extension__ ({ \
- (__m256d)__builtin_ia32_roundpd256((__v4df)(__m256d)(V), (M)); })
+#define _mm256_round_pd(V, M) \
+ (__m256d)__builtin_ia32_roundpd256((__v4df)(__m256d)(V), (M))
-/// \brief Rounds the values stored in a 256-bit vector of [8 x float] as
+/// Rounds the values stored in a 256-bit vector of [8 x float] as
/// specified by the byte operand. The source values are rounded to integer
/// values and returned as floating-point values.
///
@@ -440,10 +441,10 @@ _mm256_rcp_ps(__m256 __a)
/// 10: Upward (toward positive infinity). \n
/// 11: Truncated.
/// \returns A 256-bit vector of [8 x float] containing the rounded values.
-#define _mm256_round_ps(V, M) __extension__ ({ \
- (__m256)__builtin_ia32_roundps256((__v8sf)(__m256)(V), (M)); })
+#define _mm256_round_ps(V, M) \
+ (__m256)__builtin_ia32_roundps256((__v8sf)(__m256)(V), (M))
-/// \brief Rounds up the values stored in a 256-bit vector of [4 x double]. The
+/// Rounds up the values stored in a 256-bit vector of [4 x double]. The
/// source values are rounded up to integer values and returned as 64-bit
/// double-precision floating-point values.
///
@@ -460,7 +461,7 @@ _mm256_rcp_ps(__m256 __a)
/// \returns A 256-bit vector of [4 x double] containing the rounded up values.
#define _mm256_ceil_pd(V) _mm256_round_pd((V), _MM_FROUND_CEIL)
-/// \brief Rounds down the values stored in a 256-bit vector of [4 x double].
+/// Rounds down the values stored in a 256-bit vector of [4 x double].
/// The source values are rounded down to integer values and returned as
/// 64-bit double-precision floating-point values.
///
@@ -478,7 +479,7 @@ _mm256_rcp_ps(__m256 __a)
/// values.
#define _mm256_floor_pd(V) _mm256_round_pd((V), _MM_FROUND_FLOOR)
-/// \brief Rounds up the values stored in a 256-bit vector of [8 x float]. The
+/// Rounds up the values stored in a 256-bit vector of [8 x float]. The
/// source values are rounded up to integer values and returned as
/// floating-point values.
///
@@ -495,7 +496,7 @@ _mm256_rcp_ps(__m256 __a)
/// \returns A 256-bit vector of [8 x float] containing the rounded up values.
#define _mm256_ceil_ps(V) _mm256_round_ps((V), _MM_FROUND_CEIL)
-/// \brief Rounds down the values stored in a 256-bit vector of [8 x float]. The
+/// Rounds down the values stored in a 256-bit vector of [8 x float]. The
/// source values are rounded down to integer values and returned as
/// floating-point values.
///
@@ -513,7 +514,7 @@ _mm256_rcp_ps(__m256 __a)
#define _mm256_floor_ps(V) _mm256_round_ps((V), _MM_FROUND_FLOOR)
/* Logical */
-/// \brief Performs a bitwise AND of two 256-bit vectors of [4 x double].
+/// Performs a bitwise AND of two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -531,7 +532,7 @@ _mm256_and_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4du)__a & (__v4du)__b);
}
-/// \brief Performs a bitwise AND of two 256-bit vectors of [8 x float].
+/// Performs a bitwise AND of two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -549,7 +550,7 @@ _mm256_and_ps(__m256 __a, __m256 __b)
return (__m256)((__v8su)__a & (__v8su)__b);
}
-/// \brief Performs a bitwise AND of two 256-bit vectors of [4 x double], using
+/// Performs a bitwise AND of two 256-bit vectors of [4 x double], using
/// the one's complement of the values contained in the first source operand.
///
/// \headerfile <x86intrin.h>
@@ -570,7 +571,7 @@ _mm256_andnot_pd(__m256d __a, __m256d __b)
return (__m256d)(~(__v4du)__a & (__v4du)__b);
}
-/// \brief Performs a bitwise AND of two 256-bit vectors of [8 x float], using
+/// Performs a bitwise AND of two 256-bit vectors of [8 x float], using
/// the one's complement of the values contained in the first source operand.
///
/// \headerfile <x86intrin.h>
@@ -591,7 +592,7 @@ _mm256_andnot_ps(__m256 __a, __m256 __b)
return (__m256)(~(__v8su)__a & (__v8su)__b);
}
-/// \brief Performs a bitwise OR of two 256-bit vectors of [4 x double].
+/// Performs a bitwise OR of two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -609,7 +610,7 @@ _mm256_or_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4du)__a | (__v4du)__b);
}
-/// \brief Performs a bitwise OR of two 256-bit vectors of [8 x float].
+/// Performs a bitwise OR of two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -627,7 +628,7 @@ _mm256_or_ps(__m256 __a, __m256 __b)
return (__m256)((__v8su)__a | (__v8su)__b);
}
-/// \brief Performs a bitwise XOR of two 256-bit vectors of [4 x double].
+/// Performs a bitwise XOR of two 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -645,7 +646,7 @@ _mm256_xor_pd(__m256d __a, __m256d __b)
return (__m256d)((__v4du)__a ^ (__v4du)__b);
}
-/// \brief Performs a bitwise XOR of two 256-bit vectors of [8 x float].
+/// Performs a bitwise XOR of two 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -664,7 +665,7 @@ _mm256_xor_ps(__m256 __a, __m256 __b)
}
/* Horizontal arithmetic */
-/// \brief Horizontally adds the adjacent pairs of values contained in two
+/// Horizontally adds the adjacent pairs of values contained in two
/// 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -687,7 +688,7 @@ _mm256_hadd_pd(__m256d __a, __m256d __b)
return (__m256d)__builtin_ia32_haddpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in two
+/// Horizontally adds the adjacent pairs of values contained in two
/// 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -710,7 +711,7 @@ _mm256_hadd_ps(__m256 __a, __m256 __b)
return (__m256)__builtin_ia32_haddps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in two
+/// Horizontally subtracts the adjacent pairs of values contained in two
/// 256-bit vectors of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -733,7 +734,7 @@ _mm256_hsub_pd(__m256d __a, __m256d __b)
return (__m256d)__builtin_ia32_hsubpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in two
+/// Horizontally subtracts the adjacent pairs of values contained in two
/// 256-bit vectors of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -757,7 +758,7 @@ _mm256_hsub_ps(__m256 __a, __m256 __b)
}
/* Vector permutations */
-/// \brief Copies the values in a 128-bit vector of [2 x double] as specified
+/// Copies the values in a 128-bit vector of [2 x double] as specified
/// by the 128-bit integer vector operand.
///
/// \headerfile <x86intrin.h>
@@ -780,13 +781,13 @@ _mm256_hsub_ps(__m256 __a, __m256 __b)
/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
/// returned vector.
/// \returns A 128-bit vector of [2 x double] containing the copied values.
-static __inline __m128d __DEFAULT_FN_ATTRS
+static __inline __m128d __DEFAULT_FN_ATTRS128
_mm_permutevar_pd(__m128d __a, __m128i __c)
{
return (__m128d)__builtin_ia32_vpermilvarpd((__v2df)__a, (__v2di)__c);
}
-/// \brief Copies the values in a 256-bit vector of [4 x double] as specified
+/// Copies the values in a 256-bit vector of [4 x double] as specified
/// by the 256-bit integer vector operand.
///
/// \headerfile <x86intrin.h>
@@ -825,7 +826,7 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c)
return (__m256d)__builtin_ia32_vpermilvarpd256((__v4df)__a, (__v4di)__c);
}
-/// \brief Copies the values stored in a 128-bit vector of [4 x float] as
+/// Copies the values stored in a 128-bit vector of [4 x float] as
/// specified by the 128-bit integer vector operand.
/// \headerfile <x86intrin.h>
///
@@ -873,13 +874,13 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c)
/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
/// returned vector.
/// \returns A 128-bit vector of [4 x float] containing the copied values.
-static __inline __m128 __DEFAULT_FN_ATTRS
+static __inline __m128 __DEFAULT_FN_ATTRS128
_mm_permutevar_ps(__m128 __a, __m128i __c)
{
return (__m128)__builtin_ia32_vpermilvarps((__v4sf)__a, (__v4si)__c);
}
-/// \brief Copies the values stored in a 256-bit vector of [8 x float] as
+/// Copies the values stored in a 256-bit vector of [8 x float] as
/// specified by the 256-bit integer vector operand.
///
/// \headerfile <x86intrin.h>
@@ -970,7 +971,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
return (__m256)__builtin_ia32_vpermilvarps256((__v8sf)__a, (__v8si)__c);
}
-/// \brief Copies the values in a 128-bit vector of [2 x double] as specified
+/// Copies the values in a 128-bit vector of [2 x double] as specified
/// by the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -997,12 +998,10 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
/// returned vector.
/// \returns A 128-bit vector of [2 x double] containing the copied values.
-#define _mm_permute_pd(A, C) __extension__ ({ \
- (__m128d)__builtin_shufflevector((__v2df)(__m128d)(A), \
- (__v2df)_mm_undefined_pd(), \
- ((C) >> 0) & 0x1, ((C) >> 1) & 0x1); })
+#define _mm_permute_pd(A, C) \
+ (__m128d)__builtin_ia32_vpermilpd((__v2df)(__m128d)(A), (int)(C))
-/// \brief Copies the values in a 256-bit vector of [4 x double] as specified by
+/// Copies the values in a 256-bit vector of [4 x double] as specified by
/// the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -1039,15 +1038,10 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 1: Bits [255:192] of the source are copied to bits [255:192] of the
/// returned vector.
/// \returns A 256-bit vector of [4 x double] containing the copied values.
-#define _mm256_permute_pd(A, C) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v4df)(__m256d)(A), \
- (__v4df)_mm256_undefined_pd(), \
- 0 + (((C) >> 0) & 0x1), \
- 0 + (((C) >> 1) & 0x1), \
- 2 + (((C) >> 2) & 0x1), \
- 2 + (((C) >> 3) & 0x1)); })
-
-/// \brief Copies the values in a 128-bit vector of [4 x float] as specified by
+#define _mm256_permute_pd(A, C) \
+ (__m256d)__builtin_ia32_vpermilpd256((__v4df)(__m256d)(A), (int)(C))
+
+/// Copies the values in a 128-bit vector of [4 x float] as specified by
/// the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -1100,13 +1094,10 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
/// returned vector.
/// \returns A 128-bit vector of [4 x float] containing the copied values.
-#define _mm_permute_ps(A, C) __extension__ ({ \
- (__m128)__builtin_shufflevector((__v4sf)(__m128)(A), \
- (__v4sf)_mm_undefined_ps(), \
- ((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \
- ((C) >> 4) & 0x3, ((C) >> 6) & 0x3); })
+#define _mm_permute_ps(A, C) \
+ (__m128)__builtin_ia32_vpermilps((__v4sf)(__m128)(A), (int)(C))
-/// \brief Copies the values in a 256-bit vector of [8 x float] as specified by
+/// Copies the values in a 256-bit vector of [8 x float] as specified by
/// the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -1120,7 +1111,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// \param A
/// A 256-bit vector of [8 x float].
/// \param C
-/// An immediate integer operand specifying how the values are to be \n
+/// An immediate integer operand specifying how the values are to be
/// copied. \n
/// Bits [1:0]: \n
/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
@@ -1150,7 +1141,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
/// returned vector. \n
/// Bits [7:6]: \n
-/// 00: Bits [31:qq0] of the source are copied to bits [127:96] of the
+/// 00: Bits [31:0] of the source are copied to bits [127:96] of the
/// returned vector. \n
/// 01: Bits [63:32] of the source are copied to bits [127:96] of the
/// returned vector. \n
@@ -1195,19 +1186,10 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 11: Bits [255:224] of the source are copied to bits [255:224] of the
/// returned vector.
/// \returns A 256-bit vector of [8 x float] containing the copied values.
-#define _mm256_permute_ps(A, C) __extension__ ({ \
- (__m256)__builtin_shufflevector((__v8sf)(__m256)(A), \
- (__v8sf)_mm256_undefined_ps(), \
- 0 + (((C) >> 0) & 0x3), \
- 0 + (((C) >> 2) & 0x3), \
- 0 + (((C) >> 4) & 0x3), \
- 0 + (((C) >> 6) & 0x3), \
- 4 + (((C) >> 0) & 0x3), \
- 4 + (((C) >> 2) & 0x3), \
- 4 + (((C) >> 4) & 0x3), \
- 4 + (((C) >> 6) & 0x3)); })
-
-/// \brief Permutes 128-bit data values stored in two 256-bit vectors of
+#define _mm256_permute_ps(A, C) \
+ (__m256)__builtin_ia32_vpermilps256((__v8sf)(__m256)(A), (int)(C))
+
+/// Permutes 128-bit data values stored in two 256-bit vectors of
/// [4 x double], as specified by the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -1244,11 +1226,11 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 11: Bits [255:128] of operand \a V2 are copied to bits [255:128] of the
/// destination.
/// \returns A 256-bit vector of [4 x double] containing the copied values.
-#define _mm256_permute2f128_pd(V1, V2, M) __extension__ ({ \
+#define _mm256_permute2f128_pd(V1, V2, M) \
(__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)(__m256d)(V1), \
- (__v4df)(__m256d)(V2), (M)); })
+ (__v4df)(__m256d)(V2), (int)(M))
-/// \brief Permutes 128-bit data values stored in two 256-bit vectors of
+/// Permutes 128-bit data values stored in two 256-bit vectors of
/// [8 x float], as specified by the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -1285,11 +1267,11 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 11: Bits [255:128] of operand \a V2 are copied to bits [255:128] of the
/// destination.
/// \returns A 256-bit vector of [8 x float] containing the copied values.
-#define _mm256_permute2f128_ps(V1, V2, M) __extension__ ({ \
+#define _mm256_permute2f128_ps(V1, V2, M) \
(__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)(__m256)(V1), \
- (__v8sf)(__m256)(V2), (M)); })
+ (__v8sf)(__m256)(V2), (int)(M))
-/// \brief Permutes 128-bit data values stored in two 256-bit integer vectors,
+/// Permutes 128-bit data values stored in two 256-bit integer vectors,
/// as specified by the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -1325,12 +1307,12 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// 11: Bits [255:128] of operand \a V2 are copied to bits [255:128] of the
/// destination.
/// \returns A 256-bit integer vector containing the copied values.
-#define _mm256_permute2f128_si256(V1, V2, M) __extension__ ({ \
+#define _mm256_permute2f128_si256(V1, V2, M) \
(__m256i)__builtin_ia32_vperm2f128_si256((__v8si)(__m256i)(V1), \
- (__v8si)(__m256i)(V2), (M)); })
+ (__v8si)(__m256i)(V2), (int)(M))
/* Vector Blend */
-/// \brief Merges 64-bit double-precision data values stored in either of the
+/// Merges 64-bit double-precision data values stored in either of the
/// two 256-bit vectors of [4 x double], as specified by the immediate
/// integer operand.
///
@@ -1354,15 +1336,11 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// destination. When a mask bit is 1, the corresponding 64-bit element in
/// operand \a V2 is copied to the same position in the destination.
/// \returns A 256-bit vector of [4 x double] containing the copied values.
-#define _mm256_blend_pd(V1, V2, M) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v4df)(__m256d)(V1), \
- (__v4df)(__m256d)(V2), \
- (((M) & 0x01) ? 4 : 0), \
- (((M) & 0x02) ? 5 : 1), \
- (((M) & 0x04) ? 6 : 2), \
- (((M) & 0x08) ? 7 : 3)); })
-
-/// \brief Merges 32-bit single-precision data values stored in either of the
+#define _mm256_blend_pd(V1, V2, M) \
+ (__m256d)__builtin_ia32_blendpd256((__v4df)(__m256d)(V1), \
+ (__v4df)(__m256d)(V2), (int)(M))
+
+/// Merges 32-bit single-precision data values stored in either of the
/// two 256-bit vectors of [8 x float], as specified by the immediate
/// integer operand.
///
@@ -1386,19 +1364,11 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// destination. When a mask bit is 1, the corresponding 32-bit element in
/// operand \a V2 is copied to the same position in the destination.
/// \returns A 256-bit vector of [8 x float] containing the copied values.
-#define _mm256_blend_ps(V1, V2, M) __extension__ ({ \
- (__m256)__builtin_shufflevector((__v8sf)(__m256)(V1), \
- (__v8sf)(__m256)(V2), \
- (((M) & 0x01) ? 8 : 0), \
- (((M) & 0x02) ? 9 : 1), \
- (((M) & 0x04) ? 10 : 2), \
- (((M) & 0x08) ? 11 : 3), \
- (((M) & 0x10) ? 12 : 4), \
- (((M) & 0x20) ? 13 : 5), \
- (((M) & 0x40) ? 14 : 6), \
- (((M) & 0x80) ? 15 : 7)); })
-
-/// \brief Merges 64-bit double-precision data values stored in either of the
+#define _mm256_blend_ps(V1, V2, M) \
+ (__m256)__builtin_ia32_blendps256((__v8sf)(__m256)(V1), \
+ (__v8sf)(__m256)(V2), (int)(M))
+
+/// Merges 64-bit double-precision data values stored in either of the
/// two 256-bit vectors of [4 x double], as specified by the 256-bit vector
/// operand.
///
@@ -1426,7 +1396,7 @@ _mm256_blendv_pd(__m256d __a, __m256d __b, __m256d __c)
(__v4df)__a, (__v4df)__b, (__v4df)__c);
}
-/// \brief Merges 32-bit single-precision data values stored in either of the
+/// Merges 32-bit single-precision data values stored in either of the
/// two 256-bit vectors of [8 x float], as specified by the 256-bit vector
/// operand.
///
@@ -1455,7 +1425,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
}
/* Vector Dot Product */
-/// \brief Computes two dot products in parallel, using the lower and upper
+/// Computes two dot products in parallel, using the lower and upper
/// halves of two [8 x float] vectors as input to the two computations, and
/// returning the two dot products in the lower and upper halves of the
/// [8 x float] result.
@@ -1492,12 +1462,12 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// is set to zero. The bitmask is applied in the same way to each of the
/// two parallel dot product computations.
/// \returns A 256-bit vector of [8 x float] containing the two dot products.
-#define _mm256_dp_ps(V1, V2, M) __extension__ ({ \
+#define _mm256_dp_ps(V1, V2, M) \
(__m256)__builtin_ia32_dpps256((__v8sf)(__m256)(V1), \
- (__v8sf)(__m256)(V2), (M)); })
+ (__v8sf)(__m256)(V2), (M))
/* Vector shuffle */
-/// \brief Selects 8 float values from the 256-bit operands of [8 x float], as
+/// Selects 8 float values from the 256-bit operands of [8 x float], as
/// specified by the immediate value operand.
///
/// The four selected elements in each operand are copied to the destination
@@ -1546,19 +1516,11 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// 10: Bits [95:64] and [223:192] are copied from the selected operand. \n
/// 11: Bits [127:96] and [255:224] are copied from the selected operand.
/// \returns A 256-bit vector of [8 x float] containing the shuffled values.
-#define _mm256_shuffle_ps(a, b, mask) __extension__ ({ \
- (__m256)__builtin_shufflevector((__v8sf)(__m256)(a), \
- (__v8sf)(__m256)(b), \
- 0 + (((mask) >> 0) & 0x3), \
- 0 + (((mask) >> 2) & 0x3), \
- 8 + (((mask) >> 4) & 0x3), \
- 8 + (((mask) >> 6) & 0x3), \
- 4 + (((mask) >> 0) & 0x3), \
- 4 + (((mask) >> 2) & 0x3), \
- 12 + (((mask) >> 4) & 0x3), \
- 12 + (((mask) >> 6) & 0x3)); })
-
-/// \brief Selects four double-precision values from the 256-bit operands of
+#define _mm256_shuffle_ps(a, b, mask) \
+ (__m256)__builtin_ia32_shufps256((__v8sf)(__m256)(a), \
+ (__v8sf)(__m256)(b), (int)(mask))
+
+/// Selects four double-precision values from the 256-bit operands of
/// [4 x double], as specified by the immediate value operand.
///
/// The selected elements from the first 256-bit operand are copied to bits
@@ -1600,13 +1562,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// Bit [3]=1: Bits [255:192] are copied from \a b to bits [255:192] of the
/// destination.
/// \returns A 256-bit vector of [4 x double] containing the shuffled values.
-#define _mm256_shuffle_pd(a, b, mask) __extension__ ({ \
- (__m256d)__builtin_shufflevector((__v4df)(__m256d)(a), \
- (__v4df)(__m256d)(b), \
- 0 + (((mask) >> 0) & 0x1), \
- 4 + (((mask) >> 1) & 0x1), \
- 2 + (((mask) >> 2) & 0x1), \
- 6 + (((mask) >> 3) & 0x1)); })
+#define _mm256_shuffle_pd(a, b, mask) \
+ (__m256d)__builtin_ia32_shufpd256((__v4df)(__m256d)(a), \
+ (__v4df)(__m256d)(b), (int)(mask))
/* Compare */
#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */
@@ -1642,7 +1600,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
#define _CMP_GT_OQ 0x1e /* Greater-than (ordered, non-signaling) */
#define _CMP_TRUE_US 0x1f /* True (unordered, signaling) */
-/// \brief Compares each of the corresponding double-precision values of two
+/// Compares each of the corresponding double-precision values of two
/// 128-bit vectors of [2 x double], using the operation specified by the
/// immediate integer operand.
///
@@ -1665,44 +1623,44 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
/// operation to use: \n
-/// 0x00 : Equal (ordered, non-signaling)
-/// 0x01 : Less-than (ordered, signaling)
-/// 0x02 : Less-than-or-equal (ordered, signaling)
-/// 0x03 : Unordered (non-signaling)
-/// 0x04 : Not-equal (unordered, non-signaling)
-/// 0x05 : Not-less-than (unordered, signaling)
-/// 0x06 : Not-less-than-or-equal (unordered, signaling)
-/// 0x07 : Ordered (non-signaling)
-/// 0x08 : Equal (unordered, non-signaling)
-/// 0x09 : Not-greater-than-or-equal (unordered, signaling)
-/// 0x0a : Not-greater-than (unordered, signaling)
-/// 0x0b : False (ordered, non-signaling)
-/// 0x0c : Not-equal (ordered, non-signaling)
-/// 0x0d : Greater-than-or-equal (ordered, signaling)
-/// 0x0e : Greater-than (ordered, signaling)
-/// 0x0f : True (unordered, non-signaling)
-/// 0x10 : Equal (ordered, signaling)
-/// 0x11 : Less-than (ordered, non-signaling)
-/// 0x12 : Less-than-or-equal (ordered, non-signaling)
-/// 0x13 : Unordered (signaling)
-/// 0x14 : Not-equal (unordered, signaling)
-/// 0x15 : Not-less-than (unordered, non-signaling)
-/// 0x16 : Not-less-than-or-equal (unordered, non-signaling)
-/// 0x17 : Ordered (signaling)
-/// 0x18 : Equal (unordered, signaling)
-/// 0x19 : Not-greater-than-or-equal (unordered, non-signaling)
-/// 0x1a : Not-greater-than (unordered, non-signaling)
-/// 0x1b : False (ordered, signaling)
-/// 0x1c : Not-equal (ordered, signaling)
-/// 0x1d : Greater-than-or-equal (ordered, non-signaling)
-/// 0x1e : Greater-than (ordered, non-signaling)
-/// 0x1f : True (unordered, signaling)
+/// 0x00: Equal (ordered, non-signaling) \n
+/// 0x01: Less-than (ordered, signaling) \n
+/// 0x02: Less-than-or-equal (ordered, signaling) \n
+/// 0x03: Unordered (non-signaling) \n
+/// 0x04: Not-equal (unordered, non-signaling) \n
+/// 0x05: Not-less-than (unordered, signaling) \n
+/// 0x06: Not-less-than-or-equal (unordered, signaling) \n
+/// 0x07: Ordered (non-signaling) \n
+/// 0x08: Equal (unordered, non-signaling) \n
+/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n
+/// 0x0A: Not-greater-than (unordered, signaling) \n
+/// 0x0B: False (ordered, non-signaling) \n
+/// 0x0C: Not-equal (ordered, non-signaling) \n
+/// 0x0D: Greater-than-or-equal (ordered, signaling) \n
+/// 0x0E: Greater-than (ordered, signaling) \n
+/// 0x0F: True (unordered, non-signaling) \n
+/// 0x10: Equal (ordered, signaling) \n
+/// 0x11: Less-than (ordered, non-signaling) \n
+/// 0x12: Less-than-or-equal (ordered, non-signaling) \n
+/// 0x13: Unordered (signaling) \n
+/// 0x14: Not-equal (unordered, signaling) \n
+/// 0x15: Not-less-than (unordered, non-signaling) \n
+/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n
+/// 0x17: Ordered (signaling) \n
+/// 0x18: Equal (unordered, signaling) \n
+/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n
+/// 0x1A: Not-greater-than (unordered, non-signaling) \n
+/// 0x1B: False (ordered, signaling) \n
+/// 0x1C: Not-equal (ordered, signaling) \n
+/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n
+/// 0x1E: Greater-than (ordered, non-signaling) \n
+/// 0x1F: True (unordered, signaling)
/// \returns A 128-bit vector of [2 x double] containing the comparison results.
-#define _mm_cmp_pd(a, b, c) __extension__ ({ \
+#define _mm_cmp_pd(a, b, c) \
(__m128d)__builtin_ia32_cmppd((__v2df)(__m128d)(a), \
- (__v2df)(__m128d)(b), (c)); })
+ (__v2df)(__m128d)(b), (c))
-/// \brief Compares each of the corresponding values of two 128-bit vectors of
+/// Compares each of the corresponding values of two 128-bit vectors of
/// [4 x float], using the operation specified by the immediate integer
/// operand.
///
@@ -1725,44 +1683,44 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
/// operation to use: \n
-/// 0x00 : Equal (ordered, non-signaling)
-/// 0x01 : Less-than (ordered, signaling)
-/// 0x02 : Less-than-or-equal (ordered, signaling)
-/// 0x03 : Unordered (non-signaling)
-/// 0x04 : Not-equal (unordered, non-signaling)
-/// 0x05 : Not-less-than (unordered, signaling)
-/// 0x06 : Not-less-than-or-equal (unordered, signaling)
-/// 0x07 : Ordered (non-signaling)
-/// 0x08 : Equal (unordered, non-signaling)
-/// 0x09 : Not-greater-than-or-equal (unordered, signaling)
-/// 0x0a : Not-greater-than (unordered, signaling)
-/// 0x0b : False (ordered, non-signaling)
-/// 0x0c : Not-equal (ordered, non-signaling)
-/// 0x0d : Greater-than-or-equal (ordered, signaling)
-/// 0x0e : Greater-than (ordered, signaling)
-/// 0x0f : True (unordered, non-signaling)
-/// 0x10 : Equal (ordered, signaling)
-/// 0x11 : Less-than (ordered, non-signaling)
-/// 0x12 : Less-than-or-equal (ordered, non-signaling)
-/// 0x13 : Unordered (signaling)
-/// 0x14 : Not-equal (unordered, signaling)
-/// 0x15 : Not-less-than (unordered, non-signaling)
-/// 0x16 : Not-less-than-or-equal (unordered, non-signaling)
-/// 0x17 : Ordered (signaling)
-/// 0x18 : Equal (unordered, signaling)
-/// 0x19 : Not-greater-than-or-equal (unordered, non-signaling)
-/// 0x1a : Not-greater-than (unordered, non-signaling)
-/// 0x1b : False (ordered, signaling)
-/// 0x1c : Not-equal (ordered, signaling)
-/// 0x1d : Greater-than-or-equal (ordered, non-signaling)
-/// 0x1e : Greater-than (ordered, non-signaling)
-/// 0x1f : True (unordered, signaling)
+/// 0x00: Equal (ordered, non-signaling) \n
+/// 0x01: Less-than (ordered, signaling) \n
+/// 0x02: Less-than-or-equal (ordered, signaling) \n
+/// 0x03: Unordered (non-signaling) \n
+/// 0x04: Not-equal (unordered, non-signaling) \n
+/// 0x05: Not-less-than (unordered, signaling) \n
+/// 0x06: Not-less-than-or-equal (unordered, signaling) \n
+/// 0x07: Ordered (non-signaling) \n
+/// 0x08: Equal (unordered, non-signaling) \n
+/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n
+/// 0x0A: Not-greater-than (unordered, signaling) \n
+/// 0x0B: False (ordered, non-signaling) \n
+/// 0x0C: Not-equal (ordered, non-signaling) \n
+/// 0x0D: Greater-than-or-equal (ordered, signaling) \n
+/// 0x0E: Greater-than (ordered, signaling) \n
+/// 0x0F: True (unordered, non-signaling) \n
+/// 0x10: Equal (ordered, signaling) \n
+/// 0x11: Less-than (ordered, non-signaling) \n
+/// 0x12: Less-than-or-equal (ordered, non-signaling) \n
+/// 0x13: Unordered (signaling) \n
+/// 0x14: Not-equal (unordered, signaling) \n
+/// 0x15: Not-less-than (unordered, non-signaling) \n
+/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n
+/// 0x17: Ordered (signaling) \n
+/// 0x18: Equal (unordered, signaling) \n
+/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n
+/// 0x1A: Not-greater-than (unordered, non-signaling) \n
+/// 0x1B: False (ordered, signaling) \n
+/// 0x1C: Not-equal (ordered, signaling) \n
+/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n
+/// 0x1E: Greater-than (ordered, non-signaling) \n
+/// 0x1F: True (unordered, signaling)
/// \returns A 128-bit vector of [4 x float] containing the comparison results.
-#define _mm_cmp_ps(a, b, c) __extension__ ({ \
+#define _mm_cmp_ps(a, b, c) \
(__m128)__builtin_ia32_cmpps((__v4sf)(__m128)(a), \
- (__v4sf)(__m128)(b), (c)); })
+ (__v4sf)(__m128)(b), (c))
-/// \brief Compares each of the corresponding double-precision values of two
+/// Compares each of the corresponding double-precision values of two
/// 256-bit vectors of [4 x double], using the operation specified by the
/// immediate integer operand.
///
@@ -1785,44 +1743,44 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
/// operation to use: \n
-/// 0x00 : Equal (ordered, non-signaling)
-/// 0x01 : Less-than (ordered, signaling)
-/// 0x02 : Less-than-or-equal (ordered, signaling)
-/// 0x03 : Unordered (non-signaling)
-/// 0x04 : Not-equal (unordered, non-signaling)
-/// 0x05 : Not-less-than (unordered, signaling)
-/// 0x06 : Not-less-than-or-equal (unordered, signaling)
-/// 0x07 : Ordered (non-signaling)
-/// 0x08 : Equal (unordered, non-signaling)
-/// 0x09 : Not-greater-than-or-equal (unordered, signaling)
-/// 0x0a : Not-greater-than (unordered, signaling)
-/// 0x0b : False (ordered, non-signaling)
-/// 0x0c : Not-equal (ordered, non-signaling)
-/// 0x0d : Greater-than-or-equal (ordered, signaling)
-/// 0x0e : Greater-than (ordered, signaling)
-/// 0x0f : True (unordered, non-signaling)
-/// 0x10 : Equal (ordered, signaling)
-/// 0x11 : Less-than (ordered, non-signaling)
-/// 0x12 : Less-than-or-equal (ordered, non-signaling)
-/// 0x13 : Unordered (signaling)
-/// 0x14 : Not-equal (unordered, signaling)
-/// 0x15 : Not-less-than (unordered, non-signaling)
-/// 0x16 : Not-less-than-or-equal (unordered, non-signaling)
-/// 0x17 : Ordered (signaling)
-/// 0x18 : Equal (unordered, signaling)
-/// 0x19 : Not-greater-than-or-equal (unordered, non-signaling)
-/// 0x1a : Not-greater-than (unordered, non-signaling)
-/// 0x1b : False (ordered, signaling)
-/// 0x1c : Not-equal (ordered, signaling)
-/// 0x1d : Greater-than-or-equal (ordered, non-signaling)
-/// 0x1e : Greater-than (ordered, non-signaling)
-/// 0x1f : True (unordered, signaling)
+/// 0x00: Equal (ordered, non-signaling) \n
+/// 0x01: Less-than (ordered, signaling) \n
+/// 0x02: Less-than-or-equal (ordered, signaling) \n
+/// 0x03: Unordered (non-signaling) \n
+/// 0x04: Not-equal (unordered, non-signaling) \n
+/// 0x05: Not-less-than (unordered, signaling) \n
+/// 0x06: Not-less-than-or-equal (unordered, signaling) \n
+/// 0x07: Ordered (non-signaling) \n
+/// 0x08: Equal (unordered, non-signaling) \n
+/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n
+/// 0x0A: Not-greater-than (unordered, signaling) \n
+/// 0x0B: False (ordered, non-signaling) \n
+/// 0x0C: Not-equal (ordered, non-signaling) \n
+/// 0x0D: Greater-than-or-equal (ordered, signaling) \n
+/// 0x0E: Greater-than (ordered, signaling) \n
+/// 0x0F: True (unordered, non-signaling) \n
+/// 0x10: Equal (ordered, signaling) \n
+/// 0x11: Less-than (ordered, non-signaling) \n
+/// 0x12: Less-than-or-equal (ordered, non-signaling) \n
+/// 0x13: Unordered (signaling) \n
+/// 0x14: Not-equal (unordered, signaling) \n
+/// 0x15: Not-less-than (unordered, non-signaling) \n
+/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n
+/// 0x17: Ordered (signaling) \n
+/// 0x18: Equal (unordered, signaling) \n
+/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n
+/// 0x1A: Not-greater-than (unordered, non-signaling) \n
+/// 0x1B: False (ordered, signaling) \n
+/// 0x1C: Not-equal (ordered, signaling) \n
+/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n
+/// 0x1E: Greater-than (ordered, non-signaling) \n
+/// 0x1F: True (unordered, signaling)
/// \returns A 256-bit vector of [4 x double] containing the comparison results.
-#define _mm256_cmp_pd(a, b, c) __extension__ ({ \
+#define _mm256_cmp_pd(a, b, c) \
(__m256d)__builtin_ia32_cmppd256((__v4df)(__m256d)(a), \
- (__v4df)(__m256d)(b), (c)); })
+ (__v4df)(__m256d)(b), (c))
-/// \brief Compares each of the corresponding values of two 256-bit vectors of
+/// Compares each of the corresponding values of two 256-bit vectors of
/// [8 x float], using the operation specified by the immediate integer
/// operand.
///
@@ -1845,44 +1803,44 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
/// operation to use: \n
-/// 0x00 : Equal (ordered, non-signaling)
-/// 0x01 : Less-than (ordered, signaling)
-/// 0x02 : Less-than-or-equal (ordered, signaling)
-/// 0x03 : Unordered (non-signaling)
-/// 0x04 : Not-equal (unordered, non-signaling)
-/// 0x05 : Not-less-than (unordered, signaling)
-/// 0x06 : Not-less-than-or-equal (unordered, signaling)
-/// 0x07 : Ordered (non-signaling)
-/// 0x08 : Equal (unordered, non-signaling)
-/// 0x09 : Not-greater-than-or-equal (unordered, signaling)
-/// 0x0a : Not-greater-than (unordered, signaling)
-/// 0x0b : False (ordered, non-signaling)
-/// 0x0c : Not-equal (ordered, non-signaling)
-/// 0x0d : Greater-than-or-equal (ordered, signaling)
-/// 0x0e : Greater-than (ordered, signaling)
-/// 0x0f : True (unordered, non-signaling)
-/// 0x10 : Equal (ordered, signaling)
-/// 0x11 : Less-than (ordered, non-signaling)
-/// 0x12 : Less-than-or-equal (ordered, non-signaling)
-/// 0x13 : Unordered (signaling)
-/// 0x14 : Not-equal (unordered, signaling)
-/// 0x15 : Not-less-than (unordered, non-signaling)
-/// 0x16 : Not-less-than-or-equal (unordered, non-signaling)
-/// 0x17 : Ordered (signaling)
-/// 0x18 : Equal (unordered, signaling)
-/// 0x19 : Not-greater-than-or-equal (unordered, non-signaling)
-/// 0x1a : Not-greater-than (unordered, non-signaling)
-/// 0x1b : False (ordered, signaling)
-/// 0x1c : Not-equal (ordered, signaling)
-/// 0x1d : Greater-than-or-equal (ordered, non-signaling)
-/// 0x1e : Greater-than (ordered, non-signaling)
-/// 0x1f : True (unordered, signaling)
+/// 0x00: Equal (ordered, non-signaling) \n
+/// 0x01: Less-than (ordered, signaling) \n
+/// 0x02: Less-than-or-equal (ordered, signaling) \n
+/// 0x03: Unordered (non-signaling) \n
+/// 0x04: Not-equal (unordered, non-signaling) \n
+/// 0x05: Not-less-than (unordered, signaling) \n
+/// 0x06: Not-less-than-or-equal (unordered, signaling) \n
+/// 0x07: Ordered (non-signaling) \n
+/// 0x08: Equal (unordered, non-signaling) \n
+/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n
+/// 0x0A: Not-greater-than (unordered, signaling) \n
+/// 0x0B: False (ordered, non-signaling) \n
+/// 0x0C: Not-equal (ordered, non-signaling) \n
+/// 0x0D: Greater-than-or-equal (ordered, signaling) \n
+/// 0x0E: Greater-than (ordered, signaling) \n
+/// 0x0F: True (unordered, non-signaling) \n
+/// 0x10: Equal (ordered, signaling) \n
+/// 0x11: Less-than (ordered, non-signaling) \n
+/// 0x12: Less-than-or-equal (ordered, non-signaling) \n
+/// 0x13: Unordered (signaling) \n
+/// 0x14: Not-equal (unordered, signaling) \n
+/// 0x15: Not-less-than (unordered, non-signaling) \n
+/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n
+/// 0x17: Ordered (signaling) \n
+/// 0x18: Equal (unordered, signaling) \n
+/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n
+/// 0x1A: Not-greater-than (unordered, non-signaling) \n
+/// 0x1B: False (ordered, signaling) \n
+/// 0x1C: Not-equal (ordered, signaling) \n
+/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n
+/// 0x1E: Greater-than (ordered, non-signaling) \n
+/// 0x1F: True (unordered, signaling)
/// \returns A 256-bit vector of [8 x float] containing the comparison results.
-#define _mm256_cmp_ps(a, b, c) __extension__ ({ \
+#define _mm256_cmp_ps(a, b, c) \
(__m256)__builtin_ia32_cmpps256((__v8sf)(__m256)(a), \
- (__v8sf)(__m256)(b), (c)); })
+ (__v8sf)(__m256)(b), (c))
-/// \brief Compares each of the corresponding scalar double-precision values of
+/// Compares each of the corresponding scalar double-precision values of
/// two 128-bit vectors of [2 x double], using the operation specified by the
/// immediate integer operand.
///
@@ -1904,44 +1862,44 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
/// operation to use: \n
-/// 0x00 : Equal (ordered, non-signaling)
-/// 0x01 : Less-than (ordered, signaling)
-/// 0x02 : Less-than-or-equal (ordered, signaling)
-/// 0x03 : Unordered (non-signaling)
-/// 0x04 : Not-equal (unordered, non-signaling)
-/// 0x05 : Not-less-than (unordered, signaling)
-/// 0x06 : Not-less-than-or-equal (unordered, signaling)
-/// 0x07 : Ordered (non-signaling)
-/// 0x08 : Equal (unordered, non-signaling)
-/// 0x09 : Not-greater-than-or-equal (unordered, signaling)
-/// 0x0a : Not-greater-than (unordered, signaling)
-/// 0x0b : False (ordered, non-signaling)
-/// 0x0c : Not-equal (ordered, non-signaling)
-/// 0x0d : Greater-than-or-equal (ordered, signaling)
-/// 0x0e : Greater-than (ordered, signaling)
-/// 0x0f : True (unordered, non-signaling)
-/// 0x10 : Equal (ordered, signaling)
-/// 0x11 : Less-than (ordered, non-signaling)
-/// 0x12 : Less-than-or-equal (ordered, non-signaling)
-/// 0x13 : Unordered (signaling)
-/// 0x14 : Not-equal (unordered, signaling)
-/// 0x15 : Not-less-than (unordered, non-signaling)
-/// 0x16 : Not-less-than-or-equal (unordered, non-signaling)
-/// 0x17 : Ordered (signaling)
-/// 0x18 : Equal (unordered, signaling)
-/// 0x19 : Not-greater-than-or-equal (unordered, non-signaling)
-/// 0x1a : Not-greater-than (unordered, non-signaling)
-/// 0x1b : False (ordered, signaling)
-/// 0x1c : Not-equal (ordered, signaling)
-/// 0x1d : Greater-than-or-equal (ordered, non-signaling)
-/// 0x1e : Greater-than (ordered, non-signaling)
-/// 0x1f : True (unordered, signaling)
+/// 0x00: Equal (ordered, non-signaling) \n
+/// 0x01: Less-than (ordered, signaling) \n
+/// 0x02: Less-than-or-equal (ordered, signaling) \n
+/// 0x03: Unordered (non-signaling) \n
+/// 0x04: Not-equal (unordered, non-signaling) \n
+/// 0x05: Not-less-than (unordered, signaling) \n
+/// 0x06: Not-less-than-or-equal (unordered, signaling) \n
+/// 0x07: Ordered (non-signaling) \n
+/// 0x08: Equal (unordered, non-signaling) \n
+/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n
+/// 0x0A: Not-greater-than (unordered, signaling) \n
+/// 0x0B: False (ordered, non-signaling) \n
+/// 0x0C: Not-equal (ordered, non-signaling) \n
+/// 0x0D: Greater-than-or-equal (ordered, signaling) \n
+/// 0x0E: Greater-than (ordered, signaling) \n
+/// 0x0F: True (unordered, non-signaling) \n
+/// 0x10: Equal (ordered, signaling) \n
+/// 0x11: Less-than (ordered, non-signaling) \n
+/// 0x12: Less-than-or-equal (ordered, non-signaling) \n
+/// 0x13: Unordered (signaling) \n
+/// 0x14: Not-equal (unordered, signaling) \n
+/// 0x15: Not-less-than (unordered, non-signaling) \n
+/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n
+/// 0x17: Ordered (signaling) \n
+/// 0x18: Equal (unordered, signaling) \n
+/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n
+/// 0x1A: Not-greater-than (unordered, non-signaling) \n
+/// 0x1B: False (ordered, signaling) \n
+/// 0x1C: Not-equal (ordered, signaling) \n
+/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n
+/// 0x1E: Greater-than (ordered, non-signaling) \n
+/// 0x1F: True (unordered, signaling)
/// \returns A 128-bit vector of [2 x double] containing the comparison results.
-#define _mm_cmp_sd(a, b, c) __extension__ ({ \
+#define _mm_cmp_sd(a, b, c) \
(__m128d)__builtin_ia32_cmpsd((__v2df)(__m128d)(a), \
- (__v2df)(__m128d)(b), (c)); })
+ (__v2df)(__m128d)(b), (c))
-/// \brief Compares each of the corresponding scalar values of two 128-bit
+/// Compares each of the corresponding scalar values of two 128-bit
/// vectors of [4 x float], using the operation specified by the immediate
/// integer operand.
///
@@ -1963,44 +1921,44 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
/// operation to use: \n
-/// 0x00 : Equal (ordered, non-signaling)
-/// 0x01 : Less-than (ordered, signaling)
-/// 0x02 : Less-than-or-equal (ordered, signaling)
-/// 0x03 : Unordered (non-signaling)
-/// 0x04 : Not-equal (unordered, non-signaling)
-/// 0x05 : Not-less-than (unordered, signaling)
-/// 0x06 : Not-less-than-or-equal (unordered, signaling)
-/// 0x07 : Ordered (non-signaling)
-/// 0x08 : Equal (unordered, non-signaling)
-/// 0x09 : Not-greater-than-or-equal (unordered, signaling)
-/// 0x0a : Not-greater-than (unordered, signaling)
-/// 0x0b : False (ordered, non-signaling)
-/// 0x0c : Not-equal (ordered, non-signaling)
-/// 0x0d : Greater-than-or-equal (ordered, signaling)
-/// 0x0e : Greater-than (ordered, signaling)
-/// 0x0f : True (unordered, non-signaling)
-/// 0x10 : Equal (ordered, signaling)
-/// 0x11 : Less-than (ordered, non-signaling)
-/// 0x12 : Less-than-or-equal (ordered, non-signaling)
-/// 0x13 : Unordered (signaling)
-/// 0x14 : Not-equal (unordered, signaling)
-/// 0x15 : Not-less-than (unordered, non-signaling)
-/// 0x16 : Not-less-than-or-equal (unordered, non-signaling)
-/// 0x17 : Ordered (signaling)
-/// 0x18 : Equal (unordered, signaling)
-/// 0x19 : Not-greater-than-or-equal (unordered, non-signaling)
-/// 0x1a : Not-greater-than (unordered, non-signaling)
-/// 0x1b : False (ordered, signaling)
-/// 0x1c : Not-equal (ordered, signaling)
-/// 0x1d : Greater-than-or-equal (ordered, non-signaling)
-/// 0x1e : Greater-than (ordered, non-signaling)
-/// 0x1f : True (unordered, signaling)
+/// 0x00: Equal (ordered, non-signaling) \n
+/// 0x01: Less-than (ordered, signaling) \n
+/// 0x02: Less-than-or-equal (ordered, signaling) \n
+/// 0x03: Unordered (non-signaling) \n
+/// 0x04: Not-equal (unordered, non-signaling) \n
+/// 0x05: Not-less-than (unordered, signaling) \n
+/// 0x06: Not-less-than-or-equal (unordered, signaling) \n
+/// 0x07: Ordered (non-signaling) \n
+/// 0x08: Equal (unordered, non-signaling) \n
+/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n
+/// 0x0A: Not-greater-than (unordered, signaling) \n
+/// 0x0B: False (ordered, non-signaling) \n
+/// 0x0C: Not-equal (ordered, non-signaling) \n
+/// 0x0D: Greater-than-or-equal (ordered, signaling) \n
+/// 0x0E: Greater-than (ordered, signaling) \n
+/// 0x0F: True (unordered, non-signaling) \n
+/// 0x10: Equal (ordered, signaling) \n
+/// 0x11: Less-than (ordered, non-signaling) \n
+/// 0x12: Less-than-or-equal (ordered, non-signaling) \n
+/// 0x13: Unordered (signaling) \n
+/// 0x14: Not-equal (unordered, signaling) \n
+/// 0x15: Not-less-than (unordered, non-signaling) \n
+/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n
+/// 0x17: Ordered (signaling) \n
+/// 0x18: Equal (unordered, signaling) \n
+/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n
+/// 0x1A: Not-greater-than (unordered, non-signaling) \n
+/// 0x1B: False (ordered, signaling) \n
+/// 0x1C: Not-equal (ordered, signaling) \n
+/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n
+/// 0x1E: Greater-than (ordered, non-signaling) \n
+/// 0x1F: True (unordered, signaling)
/// \returns A 128-bit vector of [4 x float] containing the comparison results.
-#define _mm_cmp_ss(a, b, c) __extension__ ({ \
+#define _mm_cmp_ss(a, b, c) \
(__m128)__builtin_ia32_cmpss((__v4sf)(__m128)(a), \
- (__v4sf)(__m128)(b), (c)); })
+ (__v4sf)(__m128)(b), (c))
-/// \brief Takes a [8 x i32] vector and returns the vector element value
+/// Takes a [8 x i32] vector and returns the vector element value
/// indexed by the immediate constant operand.
///
/// \headerfile <x86intrin.h>
@@ -2015,14 +1973,10 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// element is extracted and returned.
/// \returns A 32-bit integer containing the extracted 32 bits of extended
/// packed data.
-static __inline int __DEFAULT_FN_ATTRS
-_mm256_extract_epi32(__m256i __a, const int __imm)
-{
- __v8si __b = (__v8si)__a;
- return __b[__imm & 7];
-}
+#define _mm256_extract_epi32(X, N) \
+ (int)__builtin_ia32_vec_ext_v8si((__v8si)(__m256i)(X), (int)(N))
-/// \brief Takes a [16 x i16] vector and returns the vector element value
+/// Takes a [16 x i16] vector and returns the vector element value
/// indexed by the immediate constant operand.
///
/// \headerfile <x86intrin.h>
@@ -2037,14 +1991,11 @@ _mm256_extract_epi32(__m256i __a, const int __imm)
/// element is extracted and returned.
/// \returns A 32-bit integer containing the extracted 16 bits of zero extended
/// packed data.
-static __inline int __DEFAULT_FN_ATTRS
-_mm256_extract_epi16(__m256i __a, const int __imm)
-{
- __v16hi __b = (__v16hi)__a;
- return (unsigned short)__b[__imm & 15];
-}
+#define _mm256_extract_epi16(X, N) \
+ (int)(unsigned short)__builtin_ia32_vec_ext_v16hi((__v16hi)(__m256i)(X), \
+ (int)(N))
-/// \brief Takes a [32 x i8] vector and returns the vector element value
+/// Takes a [32 x i8] vector and returns the vector element value
/// indexed by the immediate constant operand.
///
/// \headerfile <x86intrin.h>
@@ -2059,15 +2010,12 @@ _mm256_extract_epi16(__m256i __a, const int __imm)
/// element is extracted and returned.
/// \returns A 32-bit integer containing the extracted 8 bits of zero extended
/// packed data.
-static __inline int __DEFAULT_FN_ATTRS
-_mm256_extract_epi8(__m256i __a, const int __imm)
-{
- __v32qi __b = (__v32qi)__a;
- return (unsigned char)__b[__imm & 31];
-}
+#define _mm256_extract_epi8(X, N) \
+ (int)(unsigned char)__builtin_ia32_vec_ext_v32qi((__v32qi)(__m256i)(X), \
+ (int)(N))
#ifdef __x86_64__
-/// \brief Takes a [4 x i64] vector and returns the vector element value
+/// Takes a [4 x i64] vector and returns the vector element value
/// indexed by the immediate constant operand.
///
/// \headerfile <x86intrin.h>
@@ -2082,15 +2030,11 @@ _mm256_extract_epi8(__m256i __a, const int __imm)
/// element is extracted and returned.
/// \returns A 64-bit integer containing the extracted 64 bits of extended
/// packed data.
-static __inline long long __DEFAULT_FN_ATTRS
-_mm256_extract_epi64(__m256i __a, const int __imm)
-{
- __v4di __b = (__v4di)__a;
- return __b[__imm & 3];
-}
+#define _mm256_extract_epi64(X, N) \
+ (long long)__builtin_ia32_vec_ext_v4di((__v4di)(__m256i)(X), (int)(N))
#endif
-/// \brief Takes a [8 x i32] vector and replaces the vector element value
+/// Takes a [8 x i32] vector and replaces the vector element value
/// indexed by the immediate constant operand by a new value. Returns the
/// modified vector.
///
@@ -2108,16 +2052,12 @@ _mm256_extract_epi64(__m256i __a, const int __imm)
/// replaced.
/// \returns A copy of vector \a __a, after replacing its element indexed by
/// \a __imm with \a __b.
-static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_insert_epi32(__m256i __a, int __b, int const __imm)
-{
- __v8si __c = (__v8si)__a;
- __c[__imm & 7] = __b;
- return (__m256i)__c;
-}
+#define _mm256_insert_epi32(X, I, N) \
+ (__m256i)__builtin_ia32_vec_set_v8si((__v8si)(__m256i)(X), \
+ (int)(I), (int)(N))
-/// \brief Takes a [16 x i16] vector and replaces the vector element value
+/// Takes a [16 x i16] vector and replaces the vector element value
/// indexed by the immediate constant operand with a new value. Returns the
/// modified vector.
///
@@ -2135,15 +2075,11 @@ _mm256_insert_epi32(__m256i __a, int __b, int const __imm)
/// replaced.
/// \returns A copy of vector \a __a, after replacing its element indexed by
/// \a __imm with \a __b.
-static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_insert_epi16(__m256i __a, int __b, int const __imm)
-{
- __v16hi __c = (__v16hi)__a;
- __c[__imm & 15] = __b;
- return (__m256i)__c;
-}
+#define _mm256_insert_epi16(X, I, N) \
+ (__m256i)__builtin_ia32_vec_set_v16hi((__v16hi)(__m256i)(X), \
+ (int)(I), (int)(N))
-/// \brief Takes a [32 x i8] vector and replaces the vector element value
+/// Takes a [32 x i8] vector and replaces the vector element value
/// indexed by the immediate constant operand with a new value. Returns the
/// modified vector.
///
@@ -2161,16 +2097,12 @@ _mm256_insert_epi16(__m256i __a, int __b, int const __imm)
/// replaced.
/// \returns A copy of vector \a __a, after replacing its element indexed by
/// \a __imm with \a __b.
-static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_insert_epi8(__m256i __a, int __b, int const __imm)
-{
- __v32qi __c = (__v32qi)__a;
- __c[__imm & 31] = __b;
- return (__m256i)__c;
-}
+#define _mm256_insert_epi8(X, I, N) \
+ (__m256i)__builtin_ia32_vec_set_v32qi((__v32qi)(__m256i)(X), \
+ (int)(I), (int)(N))
#ifdef __x86_64__
-/// \brief Takes a [4 x i64] vector and replaces the vector element value
+/// Takes a [4 x i64] vector and replaces the vector element value
/// indexed by the immediate constant operand with a new value. Returns the
/// modified vector.
///
@@ -2188,17 +2120,13 @@ _mm256_insert_epi8(__m256i __a, int __b, int const __imm)
/// replaced.
/// \returns A copy of vector \a __a, after replacing its element indexed by
/// \a __imm with \a __b.
-static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_insert_epi64(__m256i __a, long long __b, int const __imm)
-{
- __v4di __c = (__v4di)__a;
- __c[__imm & 3] = __b;
- return (__m256i)__c;
-}
+#define _mm256_insert_epi64(X, I, N) \
+ (__m256i)__builtin_ia32_vec_set_v4di((__v4di)(__m256i)(X), \
+ (long long)(I), (int)(N))
#endif
/* Conversion */
-/// \brief Converts a vector of [4 x i32] into a vector of [4 x double].
+/// Converts a vector of [4 x i32] into a vector of [4 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -2213,7 +2141,7 @@ _mm256_cvtepi32_pd(__m128i __a)
return (__m256d)__builtin_convertvector((__v4si)__a, __v4df);
}
-/// \brief Converts a vector of [8 x i32] into a vector of [8 x float].
+/// Converts a vector of [8 x i32] into a vector of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -2225,10 +2153,10 @@ _mm256_cvtepi32_pd(__m128i __a)
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_cvtepi32_ps(__m256i __a)
{
- return (__m256)__builtin_ia32_cvtdq2ps256((__v8si) __a);
+ return (__m256)__builtin_convertvector((__v8si)__a, __v8sf);
}
-/// \brief Converts a 256-bit vector of [4 x double] into a 128-bit vector of
+/// Converts a 256-bit vector of [4 x double] into a 128-bit vector of
/// [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2244,7 +2172,7 @@ _mm256_cvtpd_ps(__m256d __a)
return (__m128)__builtin_ia32_cvtpd2ps256((__v4df) __a);
}
-/// \brief Converts a vector of [8 x float] into a vector of [8 x i32].
+/// Converts a vector of [8 x float] into a vector of [8 x i32].
///
/// \headerfile <x86intrin.h>
///
@@ -2259,7 +2187,7 @@ _mm256_cvtps_epi32(__m256 __a)
return (__m256i)__builtin_ia32_cvtps2dq256((__v8sf) __a);
}
-/// \brief Converts a 128-bit vector of [4 x float] into a 256-bit vector of [4
+/// Converts a 128-bit vector of [4 x float] into a 256-bit vector of [4
/// x double].
///
/// \headerfile <x86intrin.h>
@@ -2275,7 +2203,7 @@ _mm256_cvtps_pd(__m128 __a)
return (__m256d)__builtin_convertvector((__v4sf)__a, __v4df);
}
-/// \brief Converts a 256-bit vector of [4 x double] into a 128-bit vector of [4
+/// Converts a 256-bit vector of [4 x double] into a 128-bit vector of [4
/// x i32], truncating the result by rounding towards zero when it is
/// inexact.
///
@@ -2292,7 +2220,7 @@ _mm256_cvttpd_epi32(__m256d __a)
return (__m128i)__builtin_ia32_cvttpd2dq256((__v4df) __a);
}
-/// \brief Converts a 256-bit vector of [4 x double] into a 128-bit vector of [4
+/// Converts a 256-bit vector of [4 x double] into a 128-bit vector of [4
/// x i32]. When a conversion is inexact, the value returned is rounded
/// according to the rounding control bits in the MXCSR register.
///
@@ -2309,7 +2237,7 @@ _mm256_cvtpd_epi32(__m256d __a)
return (__m128i)__builtin_ia32_cvtpd2dq256((__v4df) __a);
}
-/// \brief Converts a vector of [8 x float] into a vector of [8 x i32],
+/// Converts a vector of [8 x float] into a vector of [8 x i32],
/// truncating the result by rounding towards zero when it is inexact.
///
/// \headerfile <x86intrin.h>
@@ -2325,7 +2253,7 @@ _mm256_cvttps_epi32(__m256 __a)
return (__m256i)__builtin_ia32_cvttps2dq256((__v8sf) __a);
}
-/// \brief Returns the first element of the input vector of [4 x double].
+/// Returns the first element of the input vector of [4 x double].
///
/// \headerfile <avxintrin.h>
///
@@ -2341,7 +2269,7 @@ _mm256_cvtsd_f64(__m256d __a)
return __a[0];
}
-/// \brief Returns the first element of the input vector of [8 x i32].
+/// Returns the first element of the input vector of [8 x i32].
///
/// \headerfile <avxintrin.h>
///
@@ -2358,7 +2286,7 @@ _mm256_cvtsi256_si32(__m256i __a)
return __b[0];
}
-/// \brief Returns the first element of the input vector of [8 x float].
+/// Returns the first element of the input vector of [8 x float].
///
/// \headerfile <avxintrin.h>
///
@@ -2375,9 +2303,8 @@ _mm256_cvtss_f32(__m256 __a)
}
/* Vector replicate */
-/// \brief Moves and duplicates high-order (odd-indexed) values from a 256-bit
-/// vector of [8 x float] to float values in a 256-bit vector of
-/// [8 x float].
+/// Moves and duplicates odd-indexed values from a 256-bit vector of
+/// [8 x float] to float values in a 256-bit vector of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -2401,8 +2328,8 @@ _mm256_movehdup_ps(__m256 __a)
return __builtin_shufflevector((__v8sf)__a, (__v8sf)__a, 1, 1, 3, 3, 5, 5, 7, 7);
}
-/// \brief Moves and duplicates low-order (even-indexed) values from a 256-bit
-/// vector of [8 x float] to float values in a 256-bit vector of [8 x float].
+/// Moves and duplicates even-indexed values from a 256-bit vector of
+/// [8 x float] to float values in a 256-bit vector of [8 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -2426,7 +2353,7 @@ _mm256_moveldup_ps(__m256 __a)
return __builtin_shufflevector((__v8sf)__a, (__v8sf)__a, 0, 0, 2, 2, 4, 4, 6, 6);
}
-/// \brief Moves and duplicates double-precision floating point values from a
+/// Moves and duplicates double-precision floating point values from a
/// 256-bit vector of [4 x double] to double-precision values in a 256-bit
/// vector of [4 x double].
///
@@ -2449,7 +2376,7 @@ _mm256_movedup_pd(__m256d __a)
}
/* Unpack and Interleave */
-/// \brief Unpacks the odd-indexed vector elements from two 256-bit vectors of
+/// Unpacks the odd-indexed vector elements from two 256-bit vectors of
/// [4 x double] and interleaves them into a 256-bit vector of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -2471,7 +2398,7 @@ _mm256_unpackhi_pd(__m256d __a, __m256d __b)
return __builtin_shufflevector((__v4df)__a, (__v4df)__b, 1, 5, 1+2, 5+2);
}
-/// \brief Unpacks the even-indexed vector elements from two 256-bit vectors of
+/// Unpacks the even-indexed vector elements from two 256-bit vectors of
/// [4 x double] and interleaves them into a 256-bit vector of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -2493,7 +2420,7 @@ _mm256_unpacklo_pd(__m256d __a, __m256d __b)
return __builtin_shufflevector((__v4df)__a, (__v4df)__b, 0, 4, 0+2, 4+2);
}
-/// \brief Unpacks the 32-bit vector elements 2, 3, 6 and 7 from each of the
+/// Unpacks the 32-bit vector elements 2, 3, 6 and 7 from each of the
/// two 256-bit vectors of [8 x float] and interleaves them into a 256-bit
/// vector of [8 x float].
///
@@ -2520,7 +2447,7 @@ _mm256_unpackhi_ps(__m256 __a, __m256 __b)
return __builtin_shufflevector((__v8sf)__a, (__v8sf)__b, 2, 10, 2+1, 10+1, 6, 14, 6+1, 14+1);
}
-/// \brief Unpacks the 32-bit vector elements 0, 1, 4 and 5 from each of the
+/// Unpacks the 32-bit vector elements 0, 1, 4 and 5 from each of the
/// two 256-bit vectors of [8 x float] and interleaves them into a 256-bit
/// vector of [8 x float].
///
@@ -2548,7 +2475,7 @@ _mm256_unpacklo_ps(__m256 __a, __m256 __b)
}
/* Bit Test */
-/// \brief Given two 128-bit floating-point vectors of [2 x double], perform an
+/// Given two 128-bit floating-point vectors of [2 x double], perform an
/// element-by-element comparison of the double-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2571,13 +2498,13 @@ _mm256_unpacklo_ps(__m256 __a, __m256 __b)
/// \param __b
/// A 128-bit vector of [2 x double].
/// \returns the ZF flag in the EFLAGS register.
-static __inline int __DEFAULT_FN_ATTRS
+static __inline int __DEFAULT_FN_ATTRS128
_mm_testz_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_vtestzpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Given two 128-bit floating-point vectors of [2 x double], perform an
+/// Given two 128-bit floating-point vectors of [2 x double], perform an
/// element-by-element comparison of the double-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2600,13 +2527,13 @@ _mm_testz_pd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double].
/// \returns the CF flag in the EFLAGS register.
-static __inline int __DEFAULT_FN_ATTRS
+static __inline int __DEFAULT_FN_ATTRS128
_mm_testc_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_vtestcpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Given two 128-bit floating-point vectors of [2 x double], perform an
+/// Given two 128-bit floating-point vectors of [2 x double], perform an
/// element-by-element comparison of the double-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2630,13 +2557,13 @@ _mm_testc_pd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double].
/// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0.
-static __inline int __DEFAULT_FN_ATTRS
+static __inline int __DEFAULT_FN_ATTRS128
_mm_testnzc_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_vtestnzcpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Given two 128-bit floating-point vectors of [4 x float], perform an
+/// Given two 128-bit floating-point vectors of [4 x float], perform an
/// element-by-element comparison of the single-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2659,13 +2586,13 @@ _mm_testnzc_pd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [4 x float].
/// \returns the ZF flag.
-static __inline int __DEFAULT_FN_ATTRS
+static __inline int __DEFAULT_FN_ATTRS128
_mm_testz_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_vtestzps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Given two 128-bit floating-point vectors of [4 x float], perform an
+/// Given two 128-bit floating-point vectors of [4 x float], perform an
/// element-by-element comparison of the single-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2688,13 +2615,13 @@ _mm_testz_ps(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float].
/// \returns the CF flag.
-static __inline int __DEFAULT_FN_ATTRS
+static __inline int __DEFAULT_FN_ATTRS128
_mm_testc_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_vtestcps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Given two 128-bit floating-point vectors of [4 x float], perform an
+/// Given two 128-bit floating-point vectors of [4 x float], perform an
/// element-by-element comparison of the single-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2718,13 +2645,13 @@ _mm_testc_ps(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float].
/// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0.
-static __inline int __DEFAULT_FN_ATTRS
+static __inline int __DEFAULT_FN_ATTRS128
_mm_testnzc_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_vtestnzcps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Given two 256-bit floating-point vectors of [4 x double], perform an
+/// Given two 256-bit floating-point vectors of [4 x double], perform an
/// element-by-element comparison of the double-precision elements in the
/// first source vector and the corresponding elements in the second source
/// vector.
@@ -2753,7 +2680,7 @@ _mm256_testz_pd(__m256d __a, __m256d __b)
return __builtin_ia32_vtestzpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Given two 256-bit floating-point vectors of [4 x double], perform an
+/// Given two 256-bit floating-point vectors of [4 x double], perform an
/// element-by-element comparison of the double-precision elements in the
/// first source vector and the corresponding elements in the second source
/// vector.
@@ -2782,7 +2709,7 @@ _mm256_testc_pd(__m256d __a, __m256d __b)
return __builtin_ia32_vtestcpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Given two 256-bit floating-point vectors of [4 x double], perform an
+/// Given two 256-bit floating-point vectors of [4 x double], perform an
/// element-by-element comparison of the double-precision elements in the
/// first source vector and the corresponding elements in the second source
/// vector.
@@ -2812,7 +2739,7 @@ _mm256_testnzc_pd(__m256d __a, __m256d __b)
return __builtin_ia32_vtestnzcpd256((__v4df)__a, (__v4df)__b);
}
-/// \brief Given two 256-bit floating-point vectors of [8 x float], perform an
+/// Given two 256-bit floating-point vectors of [8 x float], perform an
/// element-by-element comparison of the single-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2841,7 +2768,7 @@ _mm256_testz_ps(__m256 __a, __m256 __b)
return __builtin_ia32_vtestzps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Given two 256-bit floating-point vectors of [8 x float], perform an
+/// Given two 256-bit floating-point vectors of [8 x float], perform an
/// element-by-element comparison of the single-precision element in the
/// first source vector and the corresponding element in the second source
/// vector.
@@ -2870,7 +2797,7 @@ _mm256_testc_ps(__m256 __a, __m256 __b)
return __builtin_ia32_vtestcps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Given two 256-bit floating-point vectors of [8 x float], perform an
+/// Given two 256-bit floating-point vectors of [8 x float], perform an
/// element-by-element comparison of the single-precision elements in the
/// first source vector and the corresponding elements in the second source
/// vector.
@@ -2900,7 +2827,7 @@ _mm256_testnzc_ps(__m256 __a, __m256 __b)
return __builtin_ia32_vtestnzcps256((__v8sf)__a, (__v8sf)__b);
}
-/// \brief Given two 256-bit integer vectors, perform a bit-by-bit comparison
+/// Given two 256-bit integer vectors, perform a bit-by-bit comparison
/// of the two source vectors.
///
/// The EFLAGS register is updated as follows: \n
@@ -2926,7 +2853,7 @@ _mm256_testz_si256(__m256i __a, __m256i __b)
return __builtin_ia32_ptestz256((__v4di)__a, (__v4di)__b);
}
-/// \brief Given two 256-bit integer vectors, perform a bit-by-bit comparison
+/// Given two 256-bit integer vectors, perform a bit-by-bit comparison
/// of the two source vectors.
///
/// The EFLAGS register is updated as follows: \n
@@ -2952,7 +2879,7 @@ _mm256_testc_si256(__m256i __a, __m256i __b)
return __builtin_ia32_ptestc256((__v4di)__a, (__v4di)__b);
}
-/// \brief Given two 256-bit integer vectors, perform a bit-by-bit comparison
+/// Given two 256-bit integer vectors, perform a bit-by-bit comparison
/// of the two source vectors.
///
/// The EFLAGS register is updated as follows: \n
@@ -2980,7 +2907,7 @@ _mm256_testnzc_si256(__m256i __a, __m256i __b)
}
/* Vector extract sign mask */
-/// \brief Extracts the sign bits of double-precision floating point elements
+/// Extracts the sign bits of double-precision floating point elements
/// in a 256-bit vector of [4 x double] and writes them to the lower order
/// bits of the return value.
///
@@ -2998,7 +2925,7 @@ _mm256_movemask_pd(__m256d __a)
return __builtin_ia32_movmskpd256((__v4df)__a);
}
-/// \brief Extracts the sign bits of double-precision floating point elements
+/// Extracts the sign bits of single-precision floating point elements
/// in a 256-bit vector of [8 x float] and writes them to the lower order
/// bits of the return value.
///
@@ -3007,7 +2934,7 @@ _mm256_movemask_pd(__m256d __a)
/// This intrinsic corresponds to the <c> VMOVMSKPS </c> instruction.
///
/// \param __a
-/// A 256-bit vector of [8 x float] containing the double-precision floating
+/// A 256-bit vector of [8 x float] containing the single-precision floating
/// point values with sign bits to be extracted.
/// \returns The sign bits from the operand, written to bits [7:0].
static __inline int __DEFAULT_FN_ATTRS
@@ -3017,30 +2944,30 @@ _mm256_movemask_ps(__m256 __a)
}
/* Vector __zero */
-/// \brief Zeroes the contents of all XMM or YMM registers.
+/// Zeroes the contents of all XMM or YMM registers.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VZEROALL </c> instruction.
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __attribute__((__always_inline__, __nodebug__, __target__("avx")))
_mm256_zeroall(void)
{
__builtin_ia32_vzeroall();
}
-/// \brief Zeroes the upper 128 bits (bits 255:128) of all YMM registers.
+/// Zeroes the upper 128 bits (bits 255:128) of all YMM registers.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VZEROUPPER </c> instruction.
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __attribute__((__always_inline__, __nodebug__, __target__("avx")))
_mm256_zeroupper(void)
{
__builtin_ia32_vzeroupper();
}
/* Vector load with broadcast */
-/// \brief Loads a scalar single-precision floating point value from the
+/// Loads a scalar single-precision floating point value from the
/// specified address pointed to by \a __a and broadcasts it to the elements
/// of a [4 x float] vector.
///
@@ -3052,14 +2979,14 @@ _mm256_zeroupper(void)
/// The single-precision floating point value to be broadcast.
/// \returns A 128-bit vector of [4 x float] whose 32-bit elements are set
/// equal to the broadcast value.
-static __inline __m128 __DEFAULT_FN_ATTRS
+static __inline __m128 __DEFAULT_FN_ATTRS128
_mm_broadcast_ss(float const *__a)
{
float __f = *__a;
- return (__m128)(__v4sf){ __f, __f, __f, __f };
+ return __extension__ (__m128)(__v4sf){ __f, __f, __f, __f };
}
-/// \brief Loads a scalar double-precision floating point value from the
+/// Loads a scalar double-precision floating point value from the
/// specified address pointed to by \a __a and broadcasts it to the elements
/// of a [4 x double] vector.
///
@@ -3075,10 +3002,10 @@ static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_broadcast_sd(double const *__a)
{
double __d = *__a;
- return (__m256d)(__v4df){ __d, __d, __d, __d };
+ return __extension__ (__m256d)(__v4df){ __d, __d, __d, __d };
}
-/// \brief Loads a scalar single-precision floating point value from the
+/// Loads a scalar single-precision floating point value from the
/// specified address pointed to by \a __a and broadcasts it to the elements
/// of a [8 x float] vector.
///
@@ -3094,10 +3021,10 @@ static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_ss(float const *__a)
{
float __f = *__a;
- return (__m256)(__v8sf){ __f, __f, __f, __f, __f, __f, __f, __f };
+ return __extension__ (__m256)(__v8sf){ __f, __f, __f, __f, __f, __f, __f, __f };
}
-/// \brief Loads the data from a 128-bit vector of [2 x double] from the
+/// Loads the data from a 128-bit vector of [2 x double] from the
/// specified address pointed to by \a __a and broadcasts it to 128-bit
/// elements in a 256-bit vector of [4 x double].
///
@@ -3112,10 +3039,12 @@ _mm256_broadcast_ss(float const *__a)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_broadcast_pd(__m128d const *__a)
{
- return (__m256d)__builtin_ia32_vbroadcastf128_pd256((__v2df const *)__a);
+ __m128d __b = _mm_loadu_pd((const double *)__a);
+ return (__m256d)__builtin_shufflevector((__v2df)__b, (__v2df)__b,
+ 0, 1, 0, 1);
}
-/// \brief Loads the data from a 128-bit vector of [4 x float] from the
+/// Loads the data from a 128-bit vector of [4 x float] from the
/// specified address pointed to by \a __a and broadcasts it to 128-bit
/// elements in a 256-bit vector of [8 x float].
///
@@ -3130,11 +3059,13 @@ _mm256_broadcast_pd(__m128d const *__a)
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_ps(__m128 const *__a)
{
- return (__m256)__builtin_ia32_vbroadcastf128_ps256((__v4sf const *)__a);
+ __m128 __b = _mm_loadu_ps((const float *)__a);
+ return (__m256)__builtin_shufflevector((__v4sf)__b, (__v4sf)__b,
+ 0, 1, 2, 3, 0, 1, 2, 3);
}
/* SIMD load ops */
-/// \brief Loads 4 double-precision floating point values from a 32-byte aligned
+/// Loads 4 double-precision floating point values from a 32-byte aligned
/// memory location pointed to by \a __p into a vector of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -3151,7 +3082,7 @@ _mm256_load_pd(double const *__p)
return *(__m256d *)__p;
}
-/// \brief Loads 8 single-precision floating point values from a 32-byte aligned
+/// Loads 8 single-precision floating point values from a 32-byte aligned
/// memory location pointed to by \a __p into a vector of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -3167,7 +3098,7 @@ _mm256_load_ps(float const *__p)
return *(__m256 *)__p;
}
-/// \brief Loads 4 double-precision floating point values from an unaligned
+/// Loads 4 double-precision floating point values from an unaligned
/// memory location pointed to by \a __p into a vector of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -3187,7 +3118,7 @@ _mm256_loadu_pd(double const *__p)
return ((struct __loadu_pd*)__p)->__v;
}
-/// \brief Loads 8 single-precision floating point values from an unaligned
+/// Loads 8 single-precision floating point values from an unaligned
/// memory location pointed to by \a __p into a vector of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -3207,7 +3138,7 @@ _mm256_loadu_ps(float const *__p)
return ((struct __loadu_ps*)__p)->__v;
}
-/// \brief Loads 256 bits of integer data from a 32-byte aligned memory
+/// Loads 256 bits of integer data from a 32-byte aligned memory
/// location pointed to by \a __p into elements of a 256-bit integer vector.
///
/// \headerfile <x86intrin.h>
@@ -3224,7 +3155,7 @@ _mm256_load_si256(__m256i const *__p)
return *__p;
}
-/// \brief Loads 256 bits of integer data from an unaligned memory location
+/// Loads 256 bits of integer data from an unaligned memory location
/// pointed to by \a __p into a 256-bit integer vector.
///
/// \headerfile <x86intrin.h>
@@ -3243,7 +3174,7 @@ _mm256_loadu_si256(__m256i const *__p)
return ((struct __loadu_si256*)__p)->__v;
}
-/// \brief Loads 256 bits of integer data from an unaligned memory location
+/// Loads 256 bits of integer data from an unaligned memory location
/// pointed to by \a __p into a 256-bit integer vector. This intrinsic may
/// perform better than \c _mm256_loadu_si256 when the data crosses a cache
/// line boundary.
@@ -3262,7 +3193,7 @@ _mm256_lddqu_si256(__m256i const *__p)
}
/* SIMD store ops */
-/// \brief Stores double-precision floating point values from a 256-bit vector
+/// Stores double-precision floating point values from a 256-bit vector
/// of [4 x double] to a 32-byte aligned memory location pointed to by
/// \a __p.
///
@@ -3281,7 +3212,7 @@ _mm256_store_pd(double *__p, __m256d __a)
*(__m256d *)__p = __a;
}
-/// \brief Stores single-precision floating point values from a 256-bit vector
+/// Stores single-precision floating point values from a 256-bit vector
/// of [8 x float] to a 32-byte aligned memory location pointed to by \a __p.
///
/// \headerfile <x86intrin.h>
@@ -3299,7 +3230,7 @@ _mm256_store_ps(float *__p, __m256 __a)
*(__m256 *)__p = __a;
}
-/// \brief Stores double-precision floating point values from a 256-bit vector
+/// Stores double-precision floating point values from a 256-bit vector
/// of [4 x double] to an unaligned memory location pointed to by \a __p.
///
/// \headerfile <x86intrin.h>
@@ -3320,7 +3251,7 @@ _mm256_storeu_pd(double *__p, __m256d __a)
((struct __storeu_pd*)__p)->__v = __a;
}
-/// \brief Stores single-precision floating point values from a 256-bit vector
+/// Stores single-precision floating point values from a 256-bit vector
/// of [8 x float] to an unaligned memory location pointed to by \a __p.
///
/// \headerfile <x86intrin.h>
@@ -3340,7 +3271,7 @@ _mm256_storeu_ps(float *__p, __m256 __a)
((struct __storeu_ps*)__p)->__v = __a;
}
-/// \brief Stores integer values from a 256-bit integer vector to a 32-byte
+/// Stores integer values from a 256-bit integer vector to a 32-byte
/// aligned memory location pointed to by \a __p.
///
/// \headerfile <x86intrin.h>
@@ -3358,7 +3289,7 @@ _mm256_store_si256(__m256i *__p, __m256i __a)
*__p = __a;
}
-/// \brief Stores integer values from a 256-bit integer vector to an unaligned
+/// Stores integer values from a 256-bit integer vector to an unaligned
/// memory location pointed to by \a __p.
///
/// \headerfile <x86intrin.h>
@@ -3379,7 +3310,7 @@ _mm256_storeu_si256(__m256i *__p, __m256i __a)
}
/* Conditional load ops */
-/// \brief Conditionally loads double-precision floating point elements from a
+/// Conditionally loads double-precision floating point elements from a
/// memory location pointed to by \a __p into a 128-bit vector of
/// [2 x double], depending on the mask bits associated with each data
/// element.
@@ -3397,13 +3328,13 @@ _mm256_storeu_si256(__m256i *__p, __m256i __a)
/// corresponding value in the memory location is not loaded and the
/// corresponding field in the return value is set to zero.
/// \returns A 128-bit vector of [2 x double] containing the loaded values.
-static __inline __m128d __DEFAULT_FN_ATTRS
+static __inline __m128d __DEFAULT_FN_ATTRS128
_mm_maskload_pd(double const *__p, __m128i __m)
{
return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)__p, (__v2di)__m);
}
-/// \brief Conditionally loads double-precision floating point elements from a
+/// Conditionally loads double-precision floating point elements from a
/// memory location pointed to by \a __p into a 256-bit vector of
/// [4 x double], depending on the mask bits associated with each data
/// element.
@@ -3428,7 +3359,7 @@ _mm256_maskload_pd(double const *__p, __m256i __m)
(__v4di)__m);
}
-/// \brief Conditionally loads single-precision floating point elements from a
+/// Conditionally loads single-precision floating point elements from a
/// memory location pointed to by \a __p into a 128-bit vector of
/// [4 x float], depending on the mask bits associated with each data
/// element.
@@ -3446,13 +3377,13 @@ _mm256_maskload_pd(double const *__p, __m256i __m)
/// corresponding value in the memory location is not loaded and the
/// corresponding field in the return value is set to zero.
/// \returns A 128-bit vector of [4 x float] containing the loaded values.
-static __inline __m128 __DEFAULT_FN_ATTRS
+static __inline __m128 __DEFAULT_FN_ATTRS128
_mm_maskload_ps(float const *__p, __m128i __m)
{
return (__m128)__builtin_ia32_maskloadps((const __v4sf *)__p, (__v4si)__m);
}
-/// \brief Conditionally loads single-precision floating point elements from a
+/// Conditionally loads single-precision floating point elements from a
/// memory location pointed to by \a __p into a 256-bit vector of
/// [8 x float], depending on the mask bits associated with each data
/// element.
@@ -3477,7 +3408,7 @@ _mm256_maskload_ps(float const *__p, __m256i __m)
}
/* Conditional store ops */
-/// \brief Moves single-precision floating point values from a 256-bit vector
+/// Moves single-precision floating point values from a 256-bit vector
/// of [8 x float] to a memory location pointed to by \a __p, according to
/// the specified mask.
///
@@ -3501,7 +3432,7 @@ _mm256_maskstore_ps(float *__p, __m256i __m, __m256 __a)
__builtin_ia32_maskstoreps256((__v8sf *)__p, (__v8si)__m, (__v8sf)__a);
}
-/// \brief Moves double-precision values from a 128-bit vector of [2 x double]
+/// Moves double-precision values from a 128-bit vector of [2 x double]
/// to a memory location pointed to by \a __p, according to the specified
/// mask.
///
@@ -3519,13 +3450,13 @@ _mm256_maskstore_ps(float *__p, __m256i __m, __m256 __a)
/// changed.
/// \param __a
/// A 128-bit vector of [2 x double] containing the values to be stored.
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS128
_mm_maskstore_pd(double *__p, __m128i __m, __m128d __a)
{
__builtin_ia32_maskstorepd((__v2df *)__p, (__v2di)__m, (__v2df)__a);
}
-/// \brief Moves double-precision values from a 256-bit vector of [4 x double]
+/// Moves double-precision values from a 256-bit vector of [4 x double]
/// to a memory location pointed to by \a __p, according to the specified
/// mask.
///
@@ -3549,7 +3480,7 @@ _mm256_maskstore_pd(double *__p, __m256i __m, __m256d __a)
__builtin_ia32_maskstorepd256((__v4df *)__p, (__v4di)__m, (__v4df)__a);
}
-/// \brief Moves single-precision floating point values from a 128-bit vector
+/// Moves single-precision floating point values from a 128-bit vector
/// of [4 x float] to a memory location pointed to by \a __p, according to
/// the specified mask.
///
@@ -3567,14 +3498,14 @@ _mm256_maskstore_pd(double *__p, __m256i __m, __m256d __a)
/// changed.
/// \param __a
/// A 128-bit vector of [4 x float] containing the values to be stored.
-static __inline void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS128
_mm_maskstore_ps(float *__p, __m128i __m, __m128 __a)
{
__builtin_ia32_maskstoreps((__v4sf *)__p, (__v4si)__m, (__v4sf)__a);
}
/* Cacheability support ops */
-/// \brief Moves integer data from a 256-bit integer vector to a 32-byte
+/// Moves integer data from a 256-bit integer vector to a 32-byte
/// aligned memory location. To minimize caching, the data is flagged as
/// non-temporal (unlikely to be used again soon).
///
@@ -3594,7 +3525,7 @@ _mm256_stream_si256(__m256i *__a, __m256i __b)
__builtin_nontemporal_store((__v4di_aligned)__b, (__v4di_aligned*)__a);
}
-/// \brief Moves double-precision values from a 256-bit vector of [4 x double]
+/// Moves double-precision values from a 256-bit vector of [4 x double]
/// to a 32-byte aligned memory location. To minimize caching, the data is
/// flagged as non-temporal (unlikely to be used again soon).
///
@@ -3614,7 +3545,7 @@ _mm256_stream_pd(double *__a, __m256d __b)
__builtin_nontemporal_store((__v4df_aligned)__b, (__v4df_aligned*)__a);
}
-/// \brief Moves single-precision floating point values from a 256-bit vector
+/// Moves single-precision floating point values from a 256-bit vector
/// of [8 x float] to a 32-byte aligned memory location. To minimize
/// caching, the data is flagged as non-temporal (unlikely to be used again
/// soon).
@@ -3636,7 +3567,7 @@ _mm256_stream_ps(float *__p, __m256 __a)
}
/* Create vectors */
-/// \brief Create a 256-bit vector of [4 x double] with undefined values.
+/// Create a 256-bit vector of [4 x double] with undefined values.
///
/// \headerfile <x86intrin.h>
///
@@ -3649,7 +3580,7 @@ _mm256_undefined_pd(void)
return (__m256d)__builtin_ia32_undef256();
}
-/// \brief Create a 256-bit vector of [8 x float] with undefined values.
+/// Create a 256-bit vector of [8 x float] with undefined values.
///
/// \headerfile <x86intrin.h>
///
@@ -3662,7 +3593,7 @@ _mm256_undefined_ps(void)
return (__m256)__builtin_ia32_undef256();
}
-/// \brief Create a 256-bit integer vector with undefined values.
+/// Create a 256-bit integer vector with undefined values.
///
/// \headerfile <x86intrin.h>
///
@@ -3675,7 +3606,7 @@ _mm256_undefined_si256(void)
return (__m256i)__builtin_ia32_undef256();
}
-/// \brief Constructs a 256-bit floating-point vector of [4 x double]
+/// Constructs a 256-bit floating-point vector of [4 x double]
/// initialized with the specified double-precision floating-point values.
///
/// \headerfile <x86intrin.h>
@@ -3699,10 +3630,10 @@ _mm256_undefined_si256(void)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set_pd(double __a, double __b, double __c, double __d)
{
- return (__m256d){ __d, __c, __b, __a };
+ return __extension__ (__m256d){ __d, __c, __b, __a };
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float] initialized
+/// Constructs a 256-bit floating-point vector of [8 x float] initialized
/// with the specified single-precision floating-point values.
///
/// \headerfile <x86intrin.h>
@@ -3739,10 +3670,10 @@ static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_set_ps(float __a, float __b, float __c, float __d,
float __e, float __f, float __g, float __h)
{
- return (__m256){ __h, __g, __f, __e, __d, __c, __b, __a };
+ return __extension__ (__m256){ __h, __g, __f, __e, __d, __c, __b, __a };
}
-/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// Constructs a 256-bit integer vector initialized with the specified
/// 32-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3771,10 +3702,10 @@ static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi32(int __i0, int __i1, int __i2, int __i3,
int __i4, int __i5, int __i6, int __i7)
{
- return (__m256i)(__v8si){ __i7, __i6, __i5, __i4, __i3, __i2, __i1, __i0 };
+ return __extension__ (__m256i)(__v8si){ __i7, __i6, __i5, __i4, __i3, __i2, __i1, __i0 };
}
-/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// Constructs a 256-bit integer vector initialized with the specified
/// 16-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3821,11 +3752,11 @@ _mm256_set_epi16(short __w15, short __w14, short __w13, short __w12,
short __w07, short __w06, short __w05, short __w04,
short __w03, short __w02, short __w01, short __w00)
{
- return (__m256i)(__v16hi){ __w00, __w01, __w02, __w03, __w04, __w05, __w06,
+ return __extension__ (__m256i)(__v16hi){ __w00, __w01, __w02, __w03, __w04, __w05, __w06,
__w07, __w08, __w09, __w10, __w11, __w12, __w13, __w14, __w15 };
}
-/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// Constructs a 256-bit integer vector initialized with the specified
/// 8-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3908,7 +3839,7 @@ _mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
char __b07, char __b06, char __b05, char __b04,
char __b03, char __b02, char __b01, char __b00)
{
- return (__m256i)(__v32qi){
+ return __extension__ (__m256i)(__v32qi){
__b00, __b01, __b02, __b03, __b04, __b05, __b06, __b07,
__b08, __b09, __b10, __b11, __b12, __b13, __b14, __b15,
__b16, __b17, __b18, __b19, __b20, __b21, __b22, __b23,
@@ -3916,7 +3847,7 @@ _mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
};
}
-/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// Constructs a 256-bit integer vector initialized with the specified
/// 64-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3936,11 +3867,11 @@ _mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi64x(long long __a, long long __b, long long __c, long long __d)
{
- return (__m256i)(__v4di){ __d, __c, __b, __a };
+ return __extension__ (__m256i)(__v4di){ __d, __c, __b, __a };
}
/* Create vectors with elements in reverse order */
-/// \brief Constructs a 256-bit floating-point vector of [4 x double],
+/// Constructs a 256-bit floating-point vector of [4 x double],
/// initialized in reverse order with the specified double-precision
/// floating-point values.
///
@@ -3965,10 +3896,10 @@ _mm256_set_epi64x(long long __a, long long __b, long long __c, long long __d)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setr_pd(double __a, double __b, double __c, double __d)
{
- return (__m256d){ __a, __b, __c, __d };
+ return _mm256_set_pd(__d, __c, __b, __a);
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float],
+/// Constructs a 256-bit floating-point vector of [8 x float],
/// initialized in reverse order with the specified single-precision
/// float-point values.
///
@@ -4006,10 +3937,10 @@ static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_setr_ps(float __a, float __b, float __c, float __d,
float __e, float __f, float __g, float __h)
{
- return (__m256){ __a, __b, __c, __d, __e, __f, __g, __h };
+ return _mm256_set_ps(__h, __g, __f, __e, __d, __c, __b, __a);
}
-/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// Constructs a 256-bit integer vector, initialized in reverse order
/// with the specified 32-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -4038,10 +3969,10 @@ static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi32(int __i0, int __i1, int __i2, int __i3,
int __i4, int __i5, int __i6, int __i7)
{
- return (__m256i)(__v8si){ __i0, __i1, __i2, __i3, __i4, __i5, __i6, __i7 };
+ return _mm256_set_epi32(__i7, __i6, __i5, __i4, __i3, __i2, __i1, __i0);
}
-/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// Constructs a 256-bit integer vector, initialized in reverse order
/// with the specified 16-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -4088,11 +4019,13 @@ _mm256_setr_epi16(short __w15, short __w14, short __w13, short __w12,
short __w07, short __w06, short __w05, short __w04,
short __w03, short __w02, short __w01, short __w00)
{
- return (__m256i)(__v16hi){ __w15, __w14, __w13, __w12, __w11, __w10, __w09,
- __w08, __w07, __w06, __w05, __w04, __w03, __w02, __w01, __w00 };
+ return _mm256_set_epi16(__w00, __w01, __w02, __w03,
+ __w04, __w05, __w06, __w07,
+ __w08, __w09, __w10, __w11,
+ __w12, __w13, __w14, __w15);
}
-/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// Constructs a 256-bit integer vector, initialized in reverse order
/// with the specified 8-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -4175,14 +4108,13 @@ _mm256_setr_epi8(char __b31, char __b30, char __b29, char __b28,
char __b07, char __b06, char __b05, char __b04,
char __b03, char __b02, char __b01, char __b00)
{
- return (__m256i)(__v32qi){
- __b31, __b30, __b29, __b28, __b27, __b26, __b25, __b24,
- __b23, __b22, __b21, __b20, __b19, __b18, __b17, __b16,
- __b15, __b14, __b13, __b12, __b11, __b10, __b09, __b08,
- __b07, __b06, __b05, __b04, __b03, __b02, __b01, __b00 };
+ return _mm256_set_epi8(__b00, __b01, __b02, __b03, __b04, __b05, __b06, __b07,
+ __b08, __b09, __b10, __b11, __b12, __b13, __b14, __b15,
+ __b16, __b17, __b18, __b19, __b20, __b21, __b22, __b23,
+ __b24, __b25, __b26, __b27, __b28, __b29, __b30, __b31);
}
-/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// Constructs a 256-bit integer vector, initialized in reverse order
/// with the specified 64-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -4202,11 +4134,11 @@ _mm256_setr_epi8(char __b31, char __b30, char __b29, char __b28,
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi64x(long long __a, long long __b, long long __c, long long __d)
{
- return (__m256i)(__v4di){ __a, __b, __c, __d };
+ return _mm256_set_epi64x(__d, __c, __b, __a);
}
/* Create vectors with repeated elements */
-/// \brief Constructs a 256-bit floating-point vector of [4 x double], with each
+/// Constructs a 256-bit floating-point vector of [4 x double], with each
/// of the four double-precision floating-point vector elements set to the
/// specified double-precision floating-point value.
///
@@ -4221,10 +4153,10 @@ _mm256_setr_epi64x(long long __a, long long __b, long long __c, long long __d)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set1_pd(double __w)
{
- return (__m256d){ __w, __w, __w, __w };
+ return _mm256_set_pd(__w, __w, __w, __w);
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float], with each
+/// Constructs a 256-bit floating-point vector of [8 x float], with each
/// of the eight single-precision floating-point vector elements set to the
/// specified single-precision floating-point value.
///
@@ -4240,10 +4172,10 @@ _mm256_set1_pd(double __w)
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_set1_ps(float __w)
{
- return (__m256){ __w, __w, __w, __w, __w, __w, __w, __w };
+ return _mm256_set_ps(__w, __w, __w, __w, __w, __w, __w, __w);
}
-/// \brief Constructs a 256-bit integer vector of [8 x i32], with each of the
+/// Constructs a 256-bit integer vector of [8 x i32], with each of the
/// 32-bit integral vector elements set to the specified 32-bit integral
/// value.
///
@@ -4259,10 +4191,10 @@ _mm256_set1_ps(float __w)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi32(int __i)
{
- return (__m256i)(__v8si){ __i, __i, __i, __i, __i, __i, __i, __i };
+ return _mm256_set_epi32(__i, __i, __i, __i, __i, __i, __i, __i);
}
-/// \brief Constructs a 256-bit integer vector of [16 x i16], with each of the
+/// Constructs a 256-bit integer vector of [16 x i16], with each of the
/// 16-bit integral vector elements set to the specified 16-bit integral
/// value.
///
@@ -4277,11 +4209,11 @@ _mm256_set1_epi32(int __i)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi16(short __w)
{
- return (__m256i)(__v16hi){ __w, __w, __w, __w, __w, __w, __w, __w, __w, __w,
- __w, __w, __w, __w, __w, __w };
+ return _mm256_set_epi16(__w, __w, __w, __w, __w, __w, __w, __w,
+ __w, __w, __w, __w, __w, __w, __w, __w);
}
-/// \brief Constructs a 256-bit integer vector of [32 x i8], with each of the
+/// Constructs a 256-bit integer vector of [32 x i8], with each of the
/// 8-bit integral vector elements set to the specified 8-bit integral value.
///
/// \headerfile <x86intrin.h>
@@ -4295,12 +4227,13 @@ _mm256_set1_epi16(short __w)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi8(char __b)
{
- return (__m256i)(__v32qi){ __b, __b, __b, __b, __b, __b, __b, __b, __b, __b,
- __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b,
- __b, __b, __b, __b, __b, __b, __b };
+ return _mm256_set_epi8(__b, __b, __b, __b, __b, __b, __b, __b,
+ __b, __b, __b, __b, __b, __b, __b, __b,
+ __b, __b, __b, __b, __b, __b, __b, __b,
+ __b, __b, __b, __b, __b, __b, __b, __b);
}
-/// \brief Constructs a 256-bit integer vector of [4 x i64], with each of the
+/// Constructs a 256-bit integer vector of [4 x i64], with each of the
/// 64-bit integral vector elements set to the specified 64-bit integral
/// value.
///
@@ -4315,11 +4248,11 @@ _mm256_set1_epi8(char __b)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi64x(long long __q)
{
- return (__m256i)(__v4di){ __q, __q, __q, __q };
+ return _mm256_set_epi64x(__q, __q, __q, __q);
}
/* Create __zeroed vectors */
-/// \brief Constructs a 256-bit floating-point vector of [4 x double] with all
+/// Constructs a 256-bit floating-point vector of [4 x double] with all
/// vector elements initialized to zero.
///
/// \headerfile <x86intrin.h>
@@ -4330,10 +4263,10 @@ _mm256_set1_epi64x(long long __q)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setzero_pd(void)
{
- return (__m256d){ 0, 0, 0, 0 };
+ return __extension__ (__m256d){ 0, 0, 0, 0 };
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float] with all
+/// Constructs a 256-bit floating-point vector of [8 x float] with all
/// vector elements initialized to zero.
///
/// \headerfile <x86intrin.h>
@@ -4344,10 +4277,10 @@ _mm256_setzero_pd(void)
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_setzero_ps(void)
{
- return (__m256){ 0, 0, 0, 0, 0, 0, 0, 0 };
+ return __extension__ (__m256){ 0, 0, 0, 0, 0, 0, 0, 0 };
}
-/// \brief Constructs a 256-bit integer vector initialized to zero.
+/// Constructs a 256-bit integer vector initialized to zero.
///
/// \headerfile <x86intrin.h>
///
@@ -4357,11 +4290,11 @@ _mm256_setzero_ps(void)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setzero_si256(void)
{
- return (__m256i){ 0LL, 0LL, 0LL, 0LL };
+ return __extension__ (__m256i)(__v4di){ 0, 0, 0, 0 };
}
/* Cast between vector types */
-/// \brief Casts a 256-bit floating-point vector of [4 x double] into a 256-bit
+/// Casts a 256-bit floating-point vector of [4 x double] into a 256-bit
/// floating-point vector of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -4378,7 +4311,7 @@ _mm256_castpd_ps(__m256d __a)
return (__m256)__a;
}
-/// \brief Casts a 256-bit floating-point vector of [4 x double] into a 256-bit
+/// Casts a 256-bit floating-point vector of [4 x double] into a 256-bit
/// integer vector.
///
/// \headerfile <x86intrin.h>
@@ -4395,7 +4328,7 @@ _mm256_castpd_si256(__m256d __a)
return (__m256i)__a;
}
-/// \brief Casts a 256-bit floating-point vector of [8 x float] into a 256-bit
+/// Casts a 256-bit floating-point vector of [8 x float] into a 256-bit
/// floating-point vector of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -4412,7 +4345,7 @@ _mm256_castps_pd(__m256 __a)
return (__m256d)__a;
}
-/// \brief Casts a 256-bit floating-point vector of [8 x float] into a 256-bit
+/// Casts a 256-bit floating-point vector of [8 x float] into a 256-bit
/// integer vector.
///
/// \headerfile <x86intrin.h>
@@ -4429,7 +4362,7 @@ _mm256_castps_si256(__m256 __a)
return (__m256i)__a;
}
-/// \brief Casts a 256-bit integer vector into a 256-bit floating-point vector
+/// Casts a 256-bit integer vector into a 256-bit floating-point vector
/// of [8 x float].
///
/// \headerfile <x86intrin.h>
@@ -4446,7 +4379,7 @@ _mm256_castsi256_ps(__m256i __a)
return (__m256)__a;
}
-/// \brief Casts a 256-bit integer vector into a 256-bit floating-point vector
+/// Casts a 256-bit integer vector into a 256-bit floating-point vector
/// of [4 x double].
///
/// \headerfile <x86intrin.h>
@@ -4463,7 +4396,7 @@ _mm256_castsi256_pd(__m256i __a)
return (__m256d)__a;
}
-/// \brief Returns the lower 128 bits of a 256-bit floating-point vector of
+/// Returns the lower 128 bits of a 256-bit floating-point vector of
/// [4 x double] as a 128-bit floating-point vector of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -4480,7 +4413,7 @@ _mm256_castpd256_pd128(__m256d __a)
return __builtin_shufflevector((__v4df)__a, (__v4df)__a, 0, 1);
}
-/// \brief Returns the lower 128 bits of a 256-bit floating-point vector of
+/// Returns the lower 128 bits of a 256-bit floating-point vector of
/// [8 x float] as a 128-bit floating-point vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -4497,7 +4430,7 @@ _mm256_castps256_ps128(__m256 __a)
return __builtin_shufflevector((__v8sf)__a, (__v8sf)__a, 0, 1, 2, 3);
}
-/// \brief Truncates a 256-bit integer vector into a 128-bit integer vector.
+/// Truncates a 256-bit integer vector into a 128-bit integer vector.
///
/// \headerfile <x86intrin.h>
///
@@ -4513,7 +4446,7 @@ _mm256_castsi256_si128(__m256i __a)
return __builtin_shufflevector((__v4di)__a, (__v4di)__a, 0, 1);
}
-/// \brief Constructs a 256-bit floating-point vector of [4 x double] from a
+/// Constructs a 256-bit floating-point vector of [4 x double] from a
/// 128-bit floating-point vector of [2 x double].
///
/// The lower 128 bits contain the value of the source vector. The contents
@@ -4534,7 +4467,7 @@ _mm256_castpd128_pd256(__m128d __a)
return __builtin_shufflevector((__v2df)__a, (__v2df)__a, 0, 1, -1, -1);
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float] from a
+/// Constructs a 256-bit floating-point vector of [8 x float] from a
/// 128-bit floating-point vector of [4 x float].
///
/// The lower 128 bits contain the value of the source vector. The contents
@@ -4555,7 +4488,7 @@ _mm256_castps128_ps256(__m128 __a)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 0, 1, 2, 3, -1, -1, -1, -1);
}
-/// \brief Constructs a 256-bit integer vector from a 128-bit integer vector.
+/// Constructs a 256-bit integer vector from a 128-bit integer vector.
///
/// The lower 128 bits contain the value of the source vector. The contents
/// of the upper 128 bits are undefined.
@@ -4574,7 +4507,7 @@ _mm256_castsi128_si256(__m128i __a)
return __builtin_shufflevector((__v2di)__a, (__v2di)__a, 0, 1, -1, -1);
}
-/// \brief Constructs a 256-bit floating-point vector of [4 x double] from a
+/// Constructs a 256-bit floating-point vector of [4 x double] from a
/// 128-bit floating-point vector of [2 x double]. The lower 128 bits
/// contain the value of the source vector. The upper 128 bits are set
/// to zero.
@@ -4593,7 +4526,7 @@ _mm256_zextpd128_pd256(__m128d __a)
return __builtin_shufflevector((__v2df)__a, (__v2df)_mm_setzero_pd(), 0, 1, 2, 3);
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float] from a
+/// Constructs a 256-bit floating-point vector of [8 x float] from a
/// 128-bit floating-point vector of [4 x float]. The lower 128 bits contain
/// the value of the source vector. The upper 128 bits are set to zero.
///
@@ -4611,7 +4544,7 @@ _mm256_zextps128_ps256(__m128 __a)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)_mm_setzero_ps(), 0, 1, 2, 3, 4, 5, 6, 7);
}
-/// \brief Constructs a 256-bit integer vector from a 128-bit integer vector.
+/// Constructs a 256-bit integer vector from a 128-bit integer vector.
/// The lower 128 bits contain the value of the source vector. The upper
/// 128 bits are set to zero.
///
@@ -4634,7 +4567,7 @@ _mm256_zextsi128_si256(__m128i __a)
We use macros rather than inlines because we only want to accept
invocations where the immediate M is a constant expression.
*/
-/// \brief Constructs a new 256-bit vector of [8 x float] by first duplicating
+/// Constructs a new 256-bit vector of [8 x float] by first duplicating
/// a 256-bit vector of [8 x float] given in the first parameter, and then
/// replacing either the upper or the lower 128 bits with the contents of a
/// 128-bit vector of [4 x float] in the second parameter.
@@ -4668,20 +4601,11 @@ _mm256_zextsi128_si256(__m128i __a)
/// result, and bits [127:0] of \a V1 are copied to bits [127:0] of the
/// result.
/// \returns A 256-bit vector of [8 x float] containing the interleaved values.
-#define _mm256_insertf128_ps(V1, V2, M) __extension__ ({ \
- (__m256)__builtin_shufflevector( \
- (__v8sf)(__m256)(V1), \
- (__v8sf)_mm256_castps128_ps256((__m128)(V2)), \
- (((M) & 1) ? 0 : 8), \
- (((M) & 1) ? 1 : 9), \
- (((M) & 1) ? 2 : 10), \
- (((M) & 1) ? 3 : 11), \
- (((M) & 1) ? 8 : 4), \
- (((M) & 1) ? 9 : 5), \
- (((M) & 1) ? 10 : 6), \
- (((M) & 1) ? 11 : 7) );})
-
-/// \brief Constructs a new 256-bit vector of [4 x double] by first duplicating
+#define _mm256_insertf128_ps(V1, V2, M) \
+ (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)(__m256)(V1), \
+ (__v4sf)(__m128)(V2), (int)(M))
+
+/// Constructs a new 256-bit vector of [4 x double] by first duplicating
/// a 256-bit vector of [4 x double] given in the first parameter, and then
/// replacing either the upper or the lower 128 bits with the contents of a
/// 128-bit vector of [2 x double] in the second parameter.
@@ -4715,16 +4639,11 @@ _mm256_zextsi128_si256(__m128i __a)
/// result, and bits [127:0] of \a V1 are copied to bits [127:0] of the
/// result.
/// \returns A 256-bit vector of [4 x double] containing the interleaved values.
-#define _mm256_insertf128_pd(V1, V2, M) __extension__ ({ \
- (__m256d)__builtin_shufflevector( \
- (__v4df)(__m256d)(V1), \
- (__v4df)_mm256_castpd128_pd256((__m128d)(V2)), \
- (((M) & 1) ? 0 : 4), \
- (((M) & 1) ? 1 : 5), \
- (((M) & 1) ? 4 : 2), \
- (((M) & 1) ? 5 : 3) );})
-
-/// \brief Constructs a new 256-bit integer vector by first duplicating a
+#define _mm256_insertf128_pd(V1, V2, M) \
+ (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)(__m256d)(V1), \
+ (__v2df)(__m128d)(V2), (int)(M))
+
+/// Constructs a new 256-bit integer vector by first duplicating a
/// 256-bit integer vector given in the first parameter, and then replacing
/// either the upper or the lower 128 bits with the contents of a 128-bit
/// integer vector in the second parameter.
@@ -4758,21 +4677,16 @@ _mm256_zextsi128_si256(__m128i __a)
/// result, and bits [127:0] of \a V1 are copied to bits [127:0] of the
/// result.
/// \returns A 256-bit integer vector containing the interleaved values.
-#define _mm256_insertf128_si256(V1, V2, M) __extension__ ({ \
- (__m256i)__builtin_shufflevector( \
- (__v4di)(__m256i)(V1), \
- (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
- (((M) & 1) ? 0 : 4), \
- (((M) & 1) ? 1 : 5), \
- (((M) & 1) ? 4 : 2), \
- (((M) & 1) ? 5 : 3) );})
+#define _mm256_insertf128_si256(V1, V2, M) \
+ (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)(__m256i)(V1), \
+ (__v4si)(__m128i)(V2), (int)(M))
/*
Vector extract.
We use macros rather than inlines because we only want to accept
invocations where the immediate M is a constant expression.
*/
-/// \brief Extracts either the upper or the lower 128 bits from a 256-bit vector
+/// Extracts either the upper or the lower 128 bits from a 256-bit vector
/// of [8 x float], as determined by the immediate integer parameter, and
/// returns the extracted bits as a 128-bit vector of [4 x float].
///
@@ -4793,16 +4707,10 @@ _mm256_zextsi128_si256(__m128i __a)
/// result. \n
/// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result.
/// \returns A 128-bit vector of [4 x float] containing the extracted bits.
-#define _mm256_extractf128_ps(V, M) __extension__ ({ \
- (__m128)__builtin_shufflevector( \
- (__v8sf)(__m256)(V), \
- (__v8sf)(_mm256_undefined_ps()), \
- (((M) & 1) ? 4 : 0), \
- (((M) & 1) ? 5 : 1), \
- (((M) & 1) ? 6 : 2), \
- (((M) & 1) ? 7 : 3) );})
-
-/// \brief Extracts either the upper or the lower 128 bits from a 256-bit vector
+#define _mm256_extractf128_ps(V, M) \
+ (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)(__m256)(V), (int)(M))
+
+/// Extracts either the upper or the lower 128 bits from a 256-bit vector
/// of [4 x double], as determined by the immediate integer parameter, and
/// returns the extracted bits as a 128-bit vector of [2 x double].
///
@@ -4823,14 +4731,10 @@ _mm256_zextsi128_si256(__m128i __a)
/// result. \n
/// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result.
/// \returns A 128-bit vector of [2 x double] containing the extracted bits.
-#define _mm256_extractf128_pd(V, M) __extension__ ({ \
- (__m128d)__builtin_shufflevector( \
- (__v4df)(__m256d)(V), \
- (__v4df)(_mm256_undefined_pd()), \
- (((M) & 1) ? 2 : 0), \
- (((M) & 1) ? 3 : 1) );})
-
-/// \brief Extracts either the upper or the lower 128 bits from a 256-bit
+#define _mm256_extractf128_pd(V, M) \
+ (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)(__m256d)(V), (int)(M))
+
+/// Extracts either the upper or the lower 128 bits from a 256-bit
/// integer vector, as determined by the immediate integer parameter, and
/// returns the extracted bits as a 128-bit integer vector.
///
@@ -4851,15 +4755,11 @@ _mm256_zextsi128_si256(__m128i __a)
/// result. \n
/// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result.
/// \returns A 128-bit integer vector containing the extracted bits.
-#define _mm256_extractf128_si256(V, M) __extension__ ({ \
- (__m128i)__builtin_shufflevector( \
- (__v4di)(__m256i)(V), \
- (__v4di)(_mm256_undefined_si256()), \
- (((M) & 1) ? 2 : 0), \
- (((M) & 1) ? 3 : 1) );})
+#define _mm256_extractf128_si256(V, M) \
+ (__m128i)__builtin_ia32_vextractf128_si256((__v8si)(__m256i)(V), (int)(M))
/* SIMD load ops (unaligned) */
-/// \brief Loads two 128-bit floating-point vectors of [4 x float] from
+/// Loads two 128-bit floating-point vectors of [4 x float] from
/// unaligned memory locations and constructs a 256-bit floating-point vector
/// of [8 x float] by concatenating the two 128-bit vectors.
///
@@ -4887,7 +4787,7 @@ _mm256_loadu2_m128(float const *__addr_hi, float const *__addr_lo)
return _mm256_insertf128_ps(__v256, _mm_loadu_ps(__addr_hi), 1);
}
-/// \brief Loads two 128-bit floating-point vectors of [2 x double] from
+/// Loads two 128-bit floating-point vectors of [2 x double] from
/// unaligned memory locations and constructs a 256-bit floating-point vector
/// of [4 x double] by concatenating the two 128-bit vectors.
///
@@ -4915,7 +4815,7 @@ _mm256_loadu2_m128d(double const *__addr_hi, double const *__addr_lo)
return _mm256_insertf128_pd(__v256, _mm_loadu_pd(__addr_hi), 1);
}
-/// \brief Loads two 128-bit integer vectors from unaligned memory locations and
+/// Loads two 128-bit integer vectors from unaligned memory locations and
/// constructs a 256-bit integer vector by concatenating the two 128-bit
/// vectors.
///
@@ -4941,7 +4841,7 @@ _mm256_loadu2_m128i(__m128i const *__addr_hi, __m128i const *__addr_lo)
}
/* SIMD store ops (unaligned) */
-/// \brief Stores the upper and lower 128 bits of a 256-bit floating-point
+/// Stores the upper and lower 128 bits of a 256-bit floating-point
/// vector of [8 x float] into two different unaligned memory locations.
///
/// \headerfile <x86intrin.h>
@@ -4970,7 +4870,7 @@ _mm256_storeu2_m128(float *__addr_hi, float *__addr_lo, __m256 __a)
_mm_storeu_ps(__addr_hi, __v128);
}
-/// \brief Stores the upper and lower 128 bits of a 256-bit floating-point
+/// Stores the upper and lower 128 bits of a 256-bit floating-point
/// vector of [4 x double] into two different unaligned memory locations.
///
/// \headerfile <x86intrin.h>
@@ -4999,7 +4899,7 @@ _mm256_storeu2_m128d(double *__addr_hi, double *__addr_lo, __m256d __a)
_mm_storeu_pd(__addr_hi, __v128);
}
-/// \brief Stores the upper and lower 128 bits of a 256-bit integer vector into
+/// Stores the upper and lower 128 bits of a 256-bit integer vector into
/// two different unaligned memory locations.
///
/// \headerfile <x86intrin.h>
@@ -5028,7 +4928,7 @@ _mm256_storeu2_m128i(__m128i *__addr_hi, __m128i *__addr_lo, __m256i __a)
_mm_storeu_si128(__addr_hi, __v128);
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float] by
+/// Constructs a 256-bit floating-point vector of [8 x float] by
/// concatenating two 128-bit floating-point vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -5049,7 +4949,7 @@ _mm256_set_m128 (__m128 __hi, __m128 __lo)
return (__m256) __builtin_shufflevector((__v4sf)__lo, (__v4sf)__hi, 0, 1, 2, 3, 4, 5, 6, 7);
}
-/// \brief Constructs a 256-bit floating-point vector of [4 x double] by
+/// Constructs a 256-bit floating-point vector of [4 x double] by
/// concatenating two 128-bit floating-point vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -5067,10 +4967,10 @@ _mm256_set_m128 (__m128 __hi, __m128 __lo)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set_m128d (__m128d __hi, __m128d __lo)
{
- return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+ return (__m256d) __builtin_shufflevector((__v2df)__lo, (__v2df)__hi, 0, 1, 2, 3);
}
-/// \brief Constructs a 256-bit integer vector by concatenating two 128-bit
+/// Constructs a 256-bit integer vector by concatenating two 128-bit
/// integer vectors.
///
/// \headerfile <x86intrin.h>
@@ -5087,10 +4987,10 @@ _mm256_set_m128d (__m128d __hi, __m128d __lo)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_m128i (__m128i __hi, __m128i __lo)
{
- return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+ return (__m256i) __builtin_shufflevector((__v2di)__lo, (__v2di)__hi, 0, 1, 2, 3);
}
-/// \brief Constructs a 256-bit floating-point vector of [8 x float] by
+/// Constructs a 256-bit floating-point vector of [8 x float] by
/// concatenating two 128-bit floating-point vectors of [4 x float]. This is
/// similar to _mm256_set_m128, but the order of the input parameters is
/// swapped.
@@ -5113,7 +5013,7 @@ _mm256_setr_m128 (__m128 __lo, __m128 __hi)
return _mm256_set_m128(__hi, __lo);
}
-/// \brief Constructs a 256-bit floating-point vector of [4 x double] by
+/// Constructs a 256-bit floating-point vector of [4 x double] by
/// concatenating two 128-bit floating-point vectors of [2 x double]. This is
/// similar to _mm256_set_m128d, but the order of the input parameters is
/// swapped.
@@ -5133,10 +5033,10 @@ _mm256_setr_m128 (__m128 __lo, __m128 __hi)
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setr_m128d (__m128d __lo, __m128d __hi)
{
- return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+ return (__m256d)_mm256_set_m128d(__hi, __lo);
}
-/// \brief Constructs a 256-bit integer vector by concatenating two 128-bit
+/// Constructs a 256-bit integer vector by concatenating two 128-bit
/// integer vectors. This is similar to _mm256_set_m128i, but the order of
/// the input parameters is swapped.
///
@@ -5154,9 +5054,10 @@ _mm256_setr_m128d (__m128d __lo, __m128d __hi)
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_m128i (__m128i __lo, __m128i __hi)
{
- return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+ return (__m256i)_mm256_set_m128i(__hi, __lo);
}
#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
#endif /* __AVXINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h b/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
index e812a1632b91..d03bef442a28 100644
--- a/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
@@ -49,7 +49,7 @@
to use it as a potentially faster version of BSF. */
#define __RELAXED_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
-/// \brief Counts the number of trailing zero bits in the operand.
+/// Counts the number of trailing zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -65,7 +65,7 @@ __tzcnt_u16(unsigned short __X)
return __X ? __builtin_ctzs(__X) : 16;
}
-/// \brief Performs a bitwise AND of the second operand with the one's
+/// Performs a bitwise AND of the second operand with the one's
/// complement of the first operand.
///
/// \headerfile <x86intrin.h>
@@ -85,7 +85,7 @@ __andn_u32(unsigned int __X, unsigned int __Y)
}
/* AMD-specified, double-leading-underscore version of BEXTR */
-/// \brief Extracts the specified bits from the first operand and returns them
+/// Extracts the specified bits from the first operand and returns them
/// in the least significant bits of the result.
///
/// \headerfile <x86intrin.h>
@@ -100,6 +100,7 @@ __andn_u32(unsigned int __X, unsigned int __Y)
/// number of bits to be extracted.
/// \returns An unsigned integer whose least significant bits contain the
/// extracted bits.
+/// \see _bextr_u32
static __inline__ unsigned int __DEFAULT_FN_ATTRS
__bextr_u32(unsigned int __X, unsigned int __Y)
{
@@ -107,7 +108,7 @@ __bextr_u32(unsigned int __X, unsigned int __Y)
}
/* Intel-specified, single-leading-underscore version of BEXTR */
-/// \brief Extracts the specified bits from the first operand and returns them
+/// Extracts the specified bits from the first operand and returns them
/// in the least significant bits of the result.
///
/// \headerfile <x86intrin.h>
@@ -124,13 +125,14 @@ __bextr_u32(unsigned int __X, unsigned int __Y)
/// Bits [7:0] specify the number of bits.
/// \returns An unsigned integer whose least significant bits contain the
/// extracted bits.
+/// \see __bextr_u32
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_bextr_u32(unsigned int __X, unsigned int __Y, unsigned int __Z)
{
return __builtin_ia32_bextr_u32 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
}
-/// \brief Clears all bits in the source except for the least significant bit
+/// Clears all bits in the source except for the least significant bit
/// containing a value of 1 and returns the result.
///
/// \headerfile <x86intrin.h>
@@ -147,7 +149,7 @@ __blsi_u32(unsigned int __X)
return __X & -__X;
}
-/// \brief Creates a mask whose bits are set to 1, using bit 0 up to and
+/// Creates a mask whose bits are set to 1, using bit 0 up to and
/// including the least significant bit that is set to 1 in the source
/// operand and returns the result.
///
@@ -164,7 +166,7 @@ __blsmsk_u32(unsigned int __X)
return __X ^ (__X - 1);
}
-/// \brief Clears the least significant bit that is set to 1 in the source
+/// Clears the least significant bit that is set to 1 in the source
/// operand and returns the result.
///
/// \headerfile <x86intrin.h>
@@ -181,7 +183,7 @@ __blsr_u32(unsigned int __X)
return __X & (__X - 1);
}
-/// \brief Counts the number of trailing zero bits in the operand.
+/// Counts the number of trailing zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -197,7 +199,7 @@ __tzcnt_u32(unsigned int __X)
return __X ? __builtin_ctz(__X) : 32;
}
-/// \brief Counts the number of trailing zero bits in the operand.
+/// Counts the number of trailing zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -226,7 +228,7 @@ _mm_tzcnt_32(unsigned int __X)
#define _tzcnt_u64(a) (__tzcnt_u64((a)))
-/// \brief Performs a bitwise AND of the second operand with the one's
+/// Performs a bitwise AND of the second operand with the one's
/// complement of the first operand.
///
/// \headerfile <x86intrin.h>
@@ -246,7 +248,7 @@ __andn_u64 (unsigned long long __X, unsigned long long __Y)
}
/* AMD-specified, double-leading-underscore version of BEXTR */
-/// \brief Extracts the specified bits from the first operand and returns them
+/// Extracts the specified bits from the first operand and returns them
/// in the least significant bits of the result.
///
/// \headerfile <x86intrin.h>
@@ -261,6 +263,7 @@ __andn_u64 (unsigned long long __X, unsigned long long __Y)
/// the number of bits to be extracted.
/// \returns An unsigned 64-bit integer whose least significant bits contain the
/// extracted bits.
+/// \see _bextr_u64
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__bextr_u64(unsigned long long __X, unsigned long long __Y)
{
@@ -268,7 +271,7 @@ __bextr_u64(unsigned long long __X, unsigned long long __Y)
}
/* Intel-specified, single-leading-underscore version of BEXTR */
-/// \brief Extracts the specified bits from the first operand and returns them
+/// Extracts the specified bits from the first operand and returns them
/// in the least significant bits of the result.
///
/// \headerfile <x86intrin.h>
@@ -285,13 +288,14 @@ __bextr_u64(unsigned long long __X, unsigned long long __Y)
/// Bits [7:0] specify the number of bits.
/// \returns An unsigned 64-bit integer whose least significant bits contain the
/// extracted bits.
+/// \see __bextr_u64
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_bextr_u64(unsigned long long __X, unsigned int __Y, unsigned int __Z)
{
return __builtin_ia32_bextr_u64 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
}
-/// \brief Clears all bits in the source except for the least significant bit
+/// Clears all bits in the source except for the least significant bit
/// containing a value of 1 and returns the result.
///
/// \headerfile <x86intrin.h>
@@ -308,7 +312,7 @@ __blsi_u64(unsigned long long __X)
return __X & -__X;
}
-/// \brief Creates a mask whose bits are set to 1, using bit 0 up to and
+/// Creates a mask whose bits are set to 1, using bit 0 up to and
/// including the least significant bit that is set to 1 in the source
/// operand and returns the result.
///
@@ -325,7 +329,7 @@ __blsmsk_u64(unsigned long long __X)
return __X ^ (__X - 1);
}
-/// \brief Clears the least significant bit that is set to 1 in the source
+/// Clears the least significant bit that is set to 1 in the source
/// operand and returns the result.
///
/// \headerfile <x86intrin.h>
@@ -342,7 +346,7 @@ __blsr_u64(unsigned long long __X)
return __X & (__X - 1);
}
-/// \brief Counts the number of trailing zero bits in the operand.
+/// Counts the number of trailing zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -358,7 +362,7 @@ __tzcnt_u64(unsigned long long __X)
return __X ? __builtin_ctzll(__X) : 64;
}
-/// \brief Counts the number of trailing zero bits in the operand.
+/// Counts the number of trailing zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
diff --git a/contrib/llvm/tools/clang/lib/Headers/cetintrin.h b/contrib/llvm/tools/clang/lib/Headers/cetintrin.h
index 1256a3f63a16..120c95424da1 100644
--- a/contrib/llvm/tools/clang/lib/Headers/cetintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/cetintrin.h
@@ -1,4 +1,4 @@
-/*===---- cetintrin.h - CET intrinsic ------------------------------------===
+/*===---- 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
@@ -42,6 +42,16 @@ static __inline__ void __DEFAULT_FN_ATTRS _incsspq(unsigned long long __a) {
}
#endif /* __x86_64__ */
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS _inc_ssp(unsigned int __a) {
+ __builtin_ia32_incsspq(__a);
+}
+#else /* __x86_64__ */
+static __inline__ void __DEFAULT_FN_ATTRS _inc_ssp(unsigned int __a) {
+ __builtin_ia32_incsspd((int)__a);
+}
+#endif /* __x86_64__ */
+
static __inline__ unsigned int __DEFAULT_FN_ATTRS _rdsspd(unsigned int __a) {
return __builtin_ia32_rdsspd(__a);
}
@@ -52,6 +62,16 @@ static __inline__ unsigned long long __DEFAULT_FN_ATTRS _rdsspq(unsigned long lo
}
#endif /* __x86_64__ */
+#ifdef __x86_64__
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS _get_ssp(void) {
+ return __builtin_ia32_rdsspq(0);
+}
+#else /* __x86_64__ */
+static __inline__ unsigned int __DEFAULT_FN_ATTRS _get_ssp(void) {
+ return __builtin_ia32_rdsspd(0);
+}
+#endif /* __x86_64__ */
+
static __inline__ void __DEFAULT_FN_ATTRS _saveprevssp() {
__builtin_ia32_saveprevssp();
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/cldemoteintrin.h b/contrib/llvm/tools/clang/lib/Headers/cldemoteintrin.h
new file mode 100644
index 000000000000..fa78148ebf02
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/cldemoteintrin.h
@@ -0,0 +1,42 @@
+/*===---- cldemoteintrin.h - CLDEMOTE 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <cldemoteintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __CLDEMOTEINTRIN_H
+#define __CLDEMOTEINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("cldemote")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_cldemote(const void * __P) {
+ __builtin_ia32_cldemote(__P);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h b/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h
index f1f133023441..79bb4589fc75 100644
--- a/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h
@@ -1,4 +1,4 @@
-/*===---- clflushoptintrin.h - CLFLUSHOPT intrinsic ------------------------------------===
+/*===---- clflushoptintrin.h - CLFLUSHOPT 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
diff --git a/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h b/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h
index 2594a6c38756..c09286ba6748 100644
--- a/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h
@@ -31,7 +31,7 @@
/* 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
+/// 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
///
diff --git a/contrib/llvm/tools/clang/lib/Headers/clzerointrin.h b/contrib/llvm/tools/clang/lib/Headers/clzerointrin.h
index ed7478ff87ea..f4e920839bee 100644
--- a/contrib/llvm/tools/clang/lib/Headers/clzerointrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/clzerointrin.h
@@ -20,18 +20,18 @@
*
*===-----------------------------------------------------------------------===
*/
-#ifndef __X86INTRIN_H
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
#error "Never use <clzerointrin.h> directly; include <x86intrin.h> instead."
#endif
-#ifndef _CLZEROINTRIN_H
-#define _CLZEROINTRIN_H
+#ifndef __CLZEROINTRIN_H
+#define __CLZEROINTRIN_H
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("clzero")))
-/// \brief Loads the cache line address and zero's out the cacheline
+/// Loads the cache line address and zero's out the cacheline
///
/// \headerfile <clzerointrin.h>
///
@@ -45,6 +45,6 @@ _mm_clzero (void * __line)
__builtin_ia32_clzero ((void *)__line);
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS
-#endif /* _CLZEROINTRIN_H */
+#endif /* __CLZEROINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/cpuid.h b/contrib/llvm/tools/clang/lib/Headers/cpuid.h
index 3ae90de0b91f..fce6af52dd3f 100644
--- a/contrib/llvm/tools/clang/lib/Headers/cpuid.h
+++ b/contrib/llvm/tools/clang/lib/Headers/cpuid.h
@@ -156,6 +156,7 @@
#define bit_SMEP 0x00000080
#define bit_BMI2 0x00000100
#define bit_ENH_MOVSB 0x00000200
+#define bit_INVPCID 0x00000400
#define bit_RTM 0x00000800
#define bit_MPX 0x00004000
#define bit_AVX512F 0x00010000
@@ -166,7 +167,7 @@
#define bit_CLFLUSHOPT 0x00800000
#define bit_CLWB 0x01000000
#define bit_AVX512PF 0x04000000
-#define bit_AVX51SER 0x08000000
+#define bit_AVX512ER 0x08000000
#define bit_AVX512CD 0x10000000
#define bit_SHA 0x20000000
#define bit_AVX512BW 0x40000000
@@ -177,6 +178,7 @@
#define bit_AVX512VBMI 0x00000002
#define bit_PKU 0x00000004
#define bit_OSPKE 0x00000010
+#define bit_WAITPKG 0x00000020
#define bit_AVX512VBMI2 0x00000040
#define bit_SHSTK 0x00000080
#define bit_GFNI 0x00000100
@@ -186,10 +188,14 @@
#define bit_AVX512BITALG 0x00001000
#define bit_AVX512VPOPCNTDQ 0x00004000
#define bit_RDPID 0x00400000
+#define bit_CLDEMOTE 0x02000000
+#define bit_MOVDIRI 0x08000000
+#define bit_MOVDIR64B 0x10000000
/* Features in %edx for leaf 7 sub-leaf 0 */
#define bit_AVX5124VNNIW 0x00000004
#define bit_AVX5124FMAPS 0x00000008
+#define bit_PCONFIG 0x00040000
#define bit_IBT 0x00100000
/* Features in %eax for leaf 13 sub-leaf 1 */
@@ -197,6 +203,9 @@
#define bit_XSAVEC 0x00000002
#define bit_XSAVES 0x00000008
+/* Features in %eax for leaf 0x14 sub-leaf 0 */
+#define bit_PTWRITE 0x00000010
+
/* Features in %ecx for leaf 0x80000001 */
#define bit_LAHF_LM 0x00000001
#define bit_ABM 0x00000020
@@ -215,8 +224,9 @@
#define bit_3DNOWP 0x40000000
#define bit_3DNOW 0x80000000
-/* Features in %ebx for leaf 0x80000001 */
+/* Features in %ebx for leaf 0x80000008 */
#define bit_CLZERO 0x00000001
+#define bit_WBNOINVD 0x00000200
#if __i386__
diff --git a/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm b/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm
index cedd70762c48..01af18360d8d 100644
--- a/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm
+++ b/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm
@@ -24,28 +24,36 @@
#ifndef __CLANG_CUDA_WRAPPERS_ALGORITHM
#define __CLANG_CUDA_WRAPPERS_ALGORITHM
-// This header defines __device__ overloads of std::min/max, but only if we're
-// <= C++11. In C++14, these functions are constexpr, and so are implicitly
-// __host__ __device__.
+// This header defines __device__ overloads of std::min/max.
//
-// We don't support the initializer_list overloads because
-// initializer_list::begin() and end() are not __host__ __device__ functions.
+// Ideally we'd declare these functions only if we're <= C++11. In C++14,
+// these functions are constexpr, and so are implicitly __host__ __device__.
//
-// When compiling in C++14 mode, we could force std::min/max to have different
-// implementations for host and device, by declaring the device overloads
-// before the constexpr overloads appear. We choose not to do this because
-
-// a) why write our own implementation when we can use one from the standard
-// library? and
-// b) libstdc++ is evil and declares min/max inside a header that is included
-// *before* we include <algorithm>. So we'd have to unconditionally
-// declare our __device__ overloads of min/max, but that would pollute
-// things for people who choose not to include <algorithm>.
+// However, the compiler being in C++14 mode does not imply that the standard
+// library supports C++14. There is no macro we can test to check that the
+// stdlib has constexpr std::min/max. Thus we have to unconditionally define
+// our device overloads.
+//
+// A host+device function cannot be overloaded, and a constexpr function
+// implicitly become host device if there's no explicitly host or device
+// overload preceding it. So the simple thing to do would be to declare our
+// device min/max overloads, and then #include_next <algorithm>. This way our
+// device overloads would come first, and so if we have a C++14 stdlib, its
+// min/max won't become host+device and conflict with our device overloads.
+//
+// But that also doesn't work. libstdc++ is evil and declares std::min/max in
+// an internal header that is included *before* <algorithm>. Thus by the time
+// we're inside of this file, std::min/max may already have been declared, and
+// thus we can't prevent them from becoming host+device if they're constexpr.
+//
+// Therefore we perpetrate the following hack: We mark our __device__ overloads
+// with __attribute__((enable_if(true, ""))). This causes the signature of the
+// function to change without changing anything else about it. (Except that
+// overload resolution will prefer it over the __host__ __device__ version
+// rather than considering them equally good).
#include_next <algorithm>
-#if __cplusplus <= 201103L
-
// 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
@@ -59,30 +67,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
#endif
+#pragma push_macro("_CPP14_CONSTEXPR")
+#if __cplusplus >= 201402L
+#define _CPP14_CONSTEXPR constexpr
+#else
+#define _CPP14_CONSTEXPR
+#endif
+
template <class __T, class __Cmp>
-inline __device__ const __T &
+__attribute__((enable_if(true, "")))
+inline _CPP14_CONSTEXPR __host__ __device__ const __T &
max(const __T &__a, const __T &__b, __Cmp __cmp) {
return __cmp(__a, __b) ? __b : __a;
}
template <class __T>
-inline __device__ const __T &
+__attribute__((enable_if(true, "")))
+inline _CPP14_CONSTEXPR __host__ __device__ const __T &
max(const __T &__a, const __T &__b) {
return __a < __b ? __b : __a;
}
template <class __T, class __Cmp>
-inline __device__ const __T &
+__attribute__((enable_if(true, "")))
+inline _CPP14_CONSTEXPR __host__ __device__ const __T &
min(const __T &__a, const __T &__b, __Cmp __cmp) {
return __cmp(__b, __a) ? __b : __a;
}
template <class __T>
-inline __device__ const __T &
+__attribute__((enable_if(true, "")))
+inline _CPP14_CONSTEXPR __host__ __device__ const __T &
min(const __T &__a, const __T &__b) {
return __a < __b ? __a : __b;
}
+#pragma pop_macro("_CPP14_CONSTEXPR")
+
#ifdef _LIBCPP_END_NAMESPACE_STD
_LIBCPP_END_NAMESPACE_STD
#else
@@ -92,5 +113,4 @@ _GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
-#endif // __cplusplus <= 201103L
#endif // __CLANG_CUDA_WRAPPERS_ALGORITHM
diff --git a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
index b332eeec205a..f0ea7cd05c63 100644
--- a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
@@ -44,12 +44,11 @@ typedef unsigned char __v16qu __attribute__((__vector_size__(16)));
* appear in the interface though. */
typedef signed char __v16qs __attribute__((__vector_size__(16)));
-#include <f16cintrin.h>
-
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse2"), __min_vector_width__(64)))
-/// \brief Adds lower double-precision values in both operands and returns the
+/// Adds lower double-precision values in both operands and returns the
/// sum in the lower 64 bits of the result. The upper 64 bits of the result
/// are copied from the upper double-precision value of the first operand.
///
@@ -71,7 +70,7 @@ _mm_add_sd(__m128d __a, __m128d __b)
return __a;
}
-/// \brief Adds two 128-bit vectors of [2 x double].
+/// Adds two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -89,7 +88,7 @@ _mm_add_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2df)__a + (__v2df)__b);
}
-/// \brief Subtracts the lower double-precision value of the second operand
+/// Subtracts the lower double-precision value of the second operand
/// from the lower double-precision value of the first operand and returns
/// the difference in the lower 64 bits of the result. The upper 64 bits of
/// the result are copied from the upper double-precision value of the first
@@ -113,7 +112,7 @@ _mm_sub_sd(__m128d __a, __m128d __b)
return __a;
}
-/// \brief Subtracts two 128-bit vectors of [2 x double].
+/// Subtracts two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -131,7 +130,7 @@ _mm_sub_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2df)__a - (__v2df)__b);
}
-/// \brief Multiplies lower double-precision values in both operands and returns
+/// Multiplies lower double-precision values in both operands and returns
/// the product in the lower 64 bits of the result. The upper 64 bits of the
/// result are copied from the upper double-precision value of the first
/// operand.
@@ -154,7 +153,7 @@ _mm_mul_sd(__m128d __a, __m128d __b)
return __a;
}
-/// \brief Multiplies two 128-bit vectors of [2 x double].
+/// Multiplies two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -172,7 +171,7 @@ _mm_mul_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2df)__a * (__v2df)__b);
}
-/// \brief Divides the lower double-precision value of the first operand by the
+/// Divides the lower double-precision value of the first operand by the
/// lower double-precision value of the second operand and returns the
/// quotient in the lower 64 bits of the result. The upper 64 bits of the
/// result are copied from the upper double-precision value of the first
@@ -196,7 +195,7 @@ _mm_div_sd(__m128d __a, __m128d __b)
return __a;
}
-/// \brief Performs an element-by-element division of two 128-bit vectors of
+/// Performs an element-by-element division of two 128-bit vectors of
/// [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -215,7 +214,7 @@ _mm_div_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2df)__a / (__v2df)__b);
}
-/// \brief Calculates the square root of the lower double-precision value of
+/// Calculates the square root of the lower double-precision value of
/// the second operand and returns it in the lower 64 bits of the result.
/// The upper 64 bits of the result are copied from the upper
/// double-precision value of the first operand.
@@ -238,10 +237,10 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sqrt_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_sqrtsd((__v2df)__b);
- return (__m128d) { __c[0], __a[1] };
+ return __extension__ (__m128d) { __c[0], __a[1] };
}
-/// \brief Calculates the square root of the each of two values stored in a
+/// Calculates the square root of the each of two values stored in a
/// 128-bit vector of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -258,7 +257,7 @@ _mm_sqrt_pd(__m128d __a)
return __builtin_ia32_sqrtpd((__v2df)__a);
}
-/// \brief Compares lower 64-bit double-precision values of both operands, and
+/// Compares lower 64-bit double-precision values of both operands, and
/// returns the lesser of the pair of values in the lower 64-bits of the
/// result. The upper 64 bits of the result are copied from the upper
/// double-precision value of the first operand.
@@ -282,7 +281,7 @@ _mm_min_sd(__m128d __a, __m128d __b)
return __builtin_ia32_minsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Performs element-by-element comparison of the two 128-bit vectors of
+/// Performs element-by-element comparison of the two 128-bit vectors of
/// [2 x double] and returns the vector containing the lesser of each pair of
/// values.
///
@@ -302,7 +301,7 @@ _mm_min_pd(__m128d __a, __m128d __b)
return __builtin_ia32_minpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares lower 64-bit double-precision values of both operands, and
+/// Compares lower 64-bit double-precision values of both operands, and
/// returns the greater of the pair of values in the lower 64-bits of the
/// result. The upper 64 bits of the result are copied from the upper
/// double-precision value of the first operand.
@@ -326,7 +325,7 @@ _mm_max_sd(__m128d __a, __m128d __b)
return __builtin_ia32_maxsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Performs element-by-element comparison of the two 128-bit vectors of
+/// Performs element-by-element comparison of the two 128-bit vectors of
/// [2 x double] and returns the vector containing the greater of each pair
/// of values.
///
@@ -346,7 +345,7 @@ _mm_max_pd(__m128d __a, __m128d __b)
return __builtin_ia32_maxpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Performs a bitwise AND of two 128-bit vectors of [2 x double].
+/// Performs a bitwise AND of two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -364,7 +363,7 @@ _mm_and_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2du)__a & (__v2du)__b);
}
-/// \brief Performs a bitwise AND of two 128-bit vectors of [2 x double], using
+/// Performs a bitwise AND of two 128-bit vectors of [2 x double], using
/// the one's complement of the values contained in the first source operand.
///
/// \headerfile <x86intrin.h>
@@ -385,7 +384,7 @@ _mm_andnot_pd(__m128d __a, __m128d __b)
return (__m128d)(~(__v2du)__a & (__v2du)__b);
}
-/// \brief Performs a bitwise OR of two 128-bit vectors of [2 x double].
+/// Performs a bitwise OR of two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -403,7 +402,7 @@ _mm_or_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2du)__a | (__v2du)__b);
}
-/// \brief Performs a bitwise XOR of two 128-bit vectors of [2 x double].
+/// Performs a bitwise XOR of two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
///
@@ -421,9 +420,9 @@ _mm_xor_pd(__m128d __a, __m128d __b)
return (__m128d)((__v2du)__a ^ (__v2du)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
-/// 128-bit vectors of [2 x double] for equality. Each comparison yields 0h
-/// for false, FFFFFFFFFFFFFFFFh for true.
+/// Compares each of the corresponding double-precision values of the
+/// 128-bit vectors of [2 x double] for equality. Each comparison yields 0x0
+/// for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -440,10 +439,10 @@ _mm_cmpeq_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpeqpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are less than those in the second operand. Each comparison
-/// yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -460,11 +459,11 @@ _mm_cmplt_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpltpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are less than or equal to those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -481,11 +480,11 @@ _mm_cmple_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmplepd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are greater than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -502,11 +501,11 @@ _mm_cmpgt_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpltpd((__v2df)__b, (__v2df)__a);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are greater than or equal to those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -523,13 +522,13 @@ _mm_cmpge_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmplepd((__v2df)__b, (__v2df)__a);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are ordered with respect to those in the second operand.
///
/// A pair of double-precision values are "ordered" with respect to each
-/// other if neither value is a NaN. Each comparison yields 0h for false,
-/// FFFFFFFFFFFFFFFFh for true.
+/// other if neither value is a NaN. Each comparison yields 0x0 for false,
+/// 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -546,13 +545,13 @@ _mm_cmpord_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpordpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are unordered with respect to those in the second operand.
///
/// A pair of double-precision values are "unordered" with respect to each
-/// other if one or both values are NaN. Each comparison yields 0h for false,
-/// FFFFFFFFFFFFFFFFh for true.
+/// other if one or both values are NaN. Each comparison yields 0x0 for
+/// false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -570,11 +569,11 @@ _mm_cmpunord_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpunordpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are unequal to those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -591,11 +590,11 @@ _mm_cmpneq_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpneqpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are not less than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -612,11 +611,11 @@ _mm_cmpnlt_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpnltpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are not less than or equal to those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -633,11 +632,11 @@ _mm_cmpnle_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpnlepd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are not greater than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -654,11 +653,11 @@ _mm_cmpngt_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpnltpd((__v2df)__b, (__v2df)__a);
}
-/// \brief Compares each of the corresponding double-precision values of the
+/// Compares each of the corresponding double-precision values of the
/// 128-bit vectors of [2 x double] to determine if the values in the first
/// operand are not greater than or equal to those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -675,10 +674,10 @@ _mm_cmpnge_pd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpnlepd((__v2df)__b, (__v2df)__a);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] for equality.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -698,12 +697,12 @@ _mm_cmpeq_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpeqsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is less than the corresponding value in
/// the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -723,12 +722,12 @@ _mm_cmplt_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpltsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is less than or equal to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -748,12 +747,12 @@ _mm_cmple_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmplesd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is greater than the corresponding value
/// in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -771,15 +770,15 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpgt_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmpltsd((__v2df)__b, (__v2df)__a);
- return (__m128d) { __c[0], __a[1] };
+ return __extension__ (__m128d) { __c[0], __a[1] };
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is greater than or equal to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -797,16 +796,16 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpge_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmplesd((__v2df)__b, (__v2df)__a);
- return (__m128d) { __c[0], __a[1] };
+ return __extension__ (__m128d) { __c[0], __a[1] };
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is "ordered" with respect to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. A pair of
-/// double-precision values are "ordered" with respect to each other if
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. A pair
+/// of double-precision values are "ordered" with respect to each other if
/// neither value is a NaN.
///
/// \headerfile <x86intrin.h>
@@ -827,14 +826,14 @@ _mm_cmpord_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpordsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is "unordered" with respect to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true. A pair of
-/// double-precision values are "unordered" with respect to each other if one
-/// or both values are NaN.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. A pair
+/// of double-precision values are "unordered" with respect to each other if
+/// one or both values are NaN.
///
/// \headerfile <x86intrin.h>
///
@@ -855,12 +854,12 @@ _mm_cmpunord_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpunordsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is unequal to the corresponding value in
/// the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -880,12 +879,12 @@ _mm_cmpneq_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpneqsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is not less than the corresponding
/// value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -905,12 +904,12 @@ _mm_cmpnlt_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpnltsd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is not less than or equal to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -930,12 +929,12 @@ _mm_cmpnle_sd(__m128d __a, __m128d __b)
return (__m128d)__builtin_ia32_cmpnlesd((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is not greater than the corresponding
/// value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -953,15 +952,15 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpngt_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmpnltsd((__v2df)__b, (__v2df)__a);
- return (__m128d) { __c[0], __a[1] };
+ return __extension__ (__m128d) { __c[0], __a[1] };
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is not greater than or equal to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -979,10 +978,10 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnge_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmpnlesd((__v2df)__b, (__v2df)__a);
- return (__m128d) { __c[0], __a[1] };
+ return __extension__ (__m128d) { __c[0], __a[1] };
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] for equality.
///
/// The comparison yields 0 for false, 1 for true. If either of the two
@@ -1006,7 +1005,7 @@ _mm_comieq_sd(__m128d __a, __m128d __b)
return __builtin_ia32_comisdeq((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is less than the corresponding value in
/// the second parameter.
@@ -1032,7 +1031,7 @@ _mm_comilt_sd(__m128d __a, __m128d __b)
return __builtin_ia32_comisdlt((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is less than or equal to the
/// corresponding value in the second parameter.
@@ -1058,7 +1057,7 @@ _mm_comile_sd(__m128d __a, __m128d __b)
return __builtin_ia32_comisdle((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is greater than the corresponding value
/// in the second parameter.
@@ -1084,7 +1083,7 @@ _mm_comigt_sd(__m128d __a, __m128d __b)
return __builtin_ia32_comisdgt((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is greater than or equal to the
/// corresponding value in the second parameter.
@@ -1110,7 +1109,7 @@ _mm_comige_sd(__m128d __a, __m128d __b)
return __builtin_ia32_comisdge((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is unequal to the corresponding value in
/// the second parameter.
@@ -1136,7 +1135,7 @@ _mm_comineq_sd(__m128d __a, __m128d __b)
return __builtin_ia32_comisdneq((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] for equality. The
/// comparison yields 0 for false, 1 for true.
///
@@ -1160,7 +1159,7 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b)
return __builtin_ia32_ucomisdeq((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is less than the corresponding value in
/// the second parameter.
@@ -1186,7 +1185,7 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b)
return __builtin_ia32_ucomisdlt((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is less than or equal to the
/// corresponding value in the second parameter.
@@ -1212,7 +1211,7 @@ _mm_ucomile_sd(__m128d __a, __m128d __b)
return __builtin_ia32_ucomisdle((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is greater than the corresponding value
/// in the second parameter.
@@ -1238,7 +1237,7 @@ _mm_ucomigt_sd(__m128d __a, __m128d __b)
return __builtin_ia32_ucomisdgt((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is greater than or equal to the
/// corresponding value in the second parameter.
@@ -1264,7 +1263,7 @@ _mm_ucomige_sd(__m128d __a, __m128d __b)
return __builtin_ia32_ucomisdge((__v2df)__a, (__v2df)__b);
}
-/// \brief Compares the lower double-precision floating-point values in each of
+/// Compares the lower double-precision floating-point values in each of
/// the two 128-bit floating-point vectors of [2 x double] to determine if
/// the value in the first parameter is unequal to the corresponding value in
/// the second parameter.
@@ -1290,7 +1289,7 @@ _mm_ucomineq_sd(__m128d __a, __m128d __b)
return __builtin_ia32_ucomisdneq((__v2df)__a, (__v2df)__b);
}
-/// \brief Converts the two double-precision floating-point elements of a
+/// Converts the two double-precision floating-point elements of a
/// 128-bit vector of [2 x double] into two single-precision floating-point
/// values, returned in the lower 64 bits of a 128-bit vector of [4 x float].
/// The upper 64 bits of the result vector are set to zero.
@@ -1309,7 +1308,7 @@ _mm_cvtpd_ps(__m128d __a)
return __builtin_ia32_cvtpd2ps((__v2df)__a);
}
-/// \brief Converts the lower two single-precision floating-point elements of a
+/// Converts the lower two single-precision floating-point elements of a
/// 128-bit vector of [4 x float] into two double-precision floating-point
/// values, returned in a 128-bit vector of [2 x double]. The upper two
/// elements of the input vector are unused.
@@ -1330,7 +1329,7 @@ _mm_cvtps_pd(__m128 __a)
__builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 0, 1), __v2df);
}
-/// \brief Converts the lower two integer elements of a 128-bit vector of
+/// Converts the lower two integer elements of a 128-bit vector of
/// [4 x i32] into two double-precision floating-point values, returned in a
/// 128-bit vector of [2 x double].
///
@@ -1353,7 +1352,7 @@ _mm_cvtepi32_pd(__m128i __a)
__builtin_shufflevector((__v4si)__a, (__v4si)__a, 0, 1), __v2df);
}
-/// \brief Converts the two double-precision floating-point elements of a
+/// Converts the two double-precision floating-point elements of a
/// 128-bit vector of [2 x double] into two signed 32-bit integer values,
/// returned in the lower 64 bits of a 128-bit vector of [4 x i32]. The upper
/// 64 bits of the result vector are set to zero.
@@ -1372,7 +1371,7 @@ _mm_cvtpd_epi32(__m128d __a)
return __builtin_ia32_cvtpd2dq((__v2df)__a);
}
-/// \brief Converts the low-order element of a 128-bit vector of [2 x double]
+/// Converts the low-order element of a 128-bit vector of [2 x double]
/// into a 32-bit signed integer value.
///
/// \headerfile <x86intrin.h>
@@ -1389,7 +1388,7 @@ _mm_cvtsd_si32(__m128d __a)
return __builtin_ia32_cvtsd2si((__v2df)__a);
}
-/// \brief Converts the lower double-precision floating-point element of a
+/// Converts the lower double-precision floating-point element of a
/// 128-bit vector of [2 x double], in the second parameter, into a
/// single-precision floating-point value, returned in the lower 32 bits of a
/// 128-bit vector of [4 x float]. The upper 96 bits of the result vector are
@@ -1414,7 +1413,7 @@ _mm_cvtsd_ss(__m128 __a, __m128d __b)
return (__m128)__builtin_ia32_cvtsd2ss((__v4sf)__a, (__v2df)__b);
}
-/// \brief Converts a 32-bit signed integer value, in the second parameter, into
+/// Converts a 32-bit signed integer value, in the second parameter, into
/// a double-precision floating-point value, returned in the lower 64 bits of
/// a 128-bit vector of [2 x double]. The upper 64 bits of the result vector
/// are copied from the upper 64 bits of the first parameter.
@@ -1438,7 +1437,7 @@ _mm_cvtsi32_sd(__m128d __a, int __b)
return __a;
}
-/// \brief Converts the lower single-precision floating-point element of a
+/// Converts the lower single-precision floating-point element of a
/// 128-bit vector of [4 x float], in the second parameter, into a
/// double-precision floating-point value, returned in the lower 64 bits of
/// a 128-bit vector of [2 x double]. The upper 64 bits of the result vector
@@ -1464,7 +1463,7 @@ _mm_cvtss_sd(__m128d __a, __m128 __b)
return __a;
}
-/// \brief Converts the two double-precision floating-point elements of a
+/// Converts the two double-precision floating-point elements of a
/// 128-bit vector of [2 x double] into two signed 32-bit integer values,
/// returned in the lower 64 bits of a 128-bit vector of [4 x i32].
///
@@ -1487,7 +1486,7 @@ _mm_cvttpd_epi32(__m128d __a)
return (__m128i)__builtin_ia32_cvttpd2dq((__v2df)__a);
}
-/// \brief Converts the low-order element of a [2 x double] vector into a 32-bit
+/// Converts the low-order element of a [2 x double] vector into a 32-bit
/// signed integer value, truncating the result when it is inexact.
///
/// \headerfile <x86intrin.h>
@@ -1505,7 +1504,7 @@ _mm_cvttsd_si32(__m128d __a)
return __builtin_ia32_cvttsd2si((__v2df)__a);
}
-/// \brief Converts the two double-precision floating-point elements of a
+/// Converts the two double-precision floating-point elements of a
/// 128-bit vector of [2 x double] into two signed 32-bit integer values,
/// returned in a 64-bit vector of [2 x i32].
///
@@ -1516,13 +1515,13 @@ _mm_cvttsd_si32(__m128d __a)
/// \param __a
/// A 128-bit vector of [2 x double].
/// \returns A 64-bit vector of [2 x i32] containing the converted values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpd_pi32(__m128d __a)
{
return (__m64)__builtin_ia32_cvtpd2pi((__v2df)__a);
}
-/// \brief Converts the two double-precision floating-point elements of a
+/// Converts the two double-precision floating-point elements of a
/// 128-bit vector of [2 x double] into two signed 32-bit integer values,
/// returned in a 64-bit vector of [2 x i32].
///
@@ -1536,13 +1535,13 @@ _mm_cvtpd_pi32(__m128d __a)
/// \param __a
/// A 128-bit vector of [2 x double].
/// \returns A 64-bit vector of [2 x i32] containing the converted values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvttpd_pi32(__m128d __a)
{
return (__m64)__builtin_ia32_cvttpd2pi((__v2df)__a);
}
-/// \brief Converts the two signed 32-bit integer elements of a 64-bit vector of
+/// Converts the two signed 32-bit integer elements of a 64-bit vector of
/// [2 x i32] into two double-precision floating-point values, returned in a
/// 128-bit vector of [2 x double].
///
@@ -1553,13 +1552,13 @@ _mm_cvttpd_pi32(__m128d __a)
/// \param __a
/// A 64-bit vector of [2 x i32].
/// \returns A 128-bit vector of [2 x double] containing the converted values.
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS_MMX
_mm_cvtpi32_pd(__m64 __a)
{
return __builtin_ia32_cvtpi2pd((__v2si)__a);
}
-/// \brief Returns the low-order element of a 128-bit vector of [2 x double] as
+/// Returns the low-order element of a 128-bit vector of [2 x double] as
/// a double-precision floating-point value.
///
/// \headerfile <x86intrin.h>
@@ -1576,7 +1575,7 @@ _mm_cvtsd_f64(__m128d __a)
return __a[0];
}
-/// \brief Loads a 128-bit floating-point vector of [2 x double] from an aligned
+/// Loads a 128-bit floating-point vector of [2 x double] from an aligned
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -1593,7 +1592,7 @@ _mm_load_pd(double const *__dp)
return *(__m128d*)__dp;
}
-/// \brief Loads a double-precision floating-point value from a specified memory
+/// Loads a double-precision floating-point value from a specified memory
/// location and duplicates it to both vector elements of a 128-bit vector of
/// [2 x double].
///
@@ -1612,12 +1611,12 @@ _mm_load1_pd(double const *__dp)
double __u;
} __attribute__((__packed__, __may_alias__));
double __u = ((struct __mm_load1_pd_struct*)__dp)->__u;
- return (__m128d){ __u, __u };
+ return __extension__ (__m128d){ __u, __u };
}
#define _mm_load_pd1(dp) _mm_load1_pd(dp)
-/// \brief Loads two double-precision values, in reverse order, from an aligned
+/// Loads two double-precision values, in reverse order, from an aligned
/// memory location into a 128-bit vector of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -1638,7 +1637,7 @@ _mm_loadr_pd(double const *__dp)
return __builtin_shufflevector((__v2df)__u, (__v2df)__u, 1, 0);
}
-/// \brief Loads a 128-bit floating-point vector of [2 x double] from an
+/// Loads a 128-bit floating-point vector of [2 x double] from an
/// unaligned memory location.
///
/// \headerfile <x86intrin.h>
@@ -1658,7 +1657,7 @@ _mm_loadu_pd(double const *__dp)
return ((struct __loadu_pd*)__dp)->__v;
}
-/// \brief Loads a 64-bit integer value to the low element of a 128-bit integer
+/// Loads a 64-bit integer value to the low element of a 128-bit integer
/// vector and clears the upper element.
///
/// \headerfile <x86intrin.h>
@@ -1676,10 +1675,10 @@ _mm_loadu_si64(void const *__a)
long long __v;
} __attribute__((__packed__, __may_alias__));
long long __u = ((struct __loadu_si64*)__a)->__v;
- return (__m128i){__u, 0L};
+ return __extension__ (__m128i)(__v2di){__u, 0L};
}
-/// \brief Loads a 64-bit double-precision value to the low element of a
+/// Loads a 64-bit double-precision value to the low element of a
/// 128-bit integer vector and clears the upper element.
///
/// \headerfile <x86intrin.h>
@@ -1697,10 +1696,10 @@ _mm_load_sd(double const *__dp)
double __u;
} __attribute__((__packed__, __may_alias__));
double __u = ((struct __mm_load_sd_struct*)__dp)->__u;
- return (__m128d){ __u, 0 };
+ return __extension__ (__m128d){ __u, 0 };
}
-/// \brief Loads a double-precision value into the high-order bits of a 128-bit
+/// Loads a double-precision value into the high-order bits of a 128-bit
/// vector of [2 x double]. The low-order bits are copied from the low-order
/// bits of the first operand.
///
@@ -1724,10 +1723,10 @@ _mm_loadh_pd(__m128d __a, double const *__dp)
double __u;
} __attribute__((__packed__, __may_alias__));
double __u = ((struct __mm_loadh_pd_struct*)__dp)->__u;
- return (__m128d){ __a[0], __u };
+ return __extension__ (__m128d){ __a[0], __u };
}
-/// \brief Loads a double-precision value into the low-order bits of a 128-bit
+/// Loads a double-precision value into the low-order bits of a 128-bit
/// vector of [2 x double]. The high-order bits are copied from the
/// high-order bits of the first operand.
///
@@ -1751,10 +1750,10 @@ _mm_loadl_pd(__m128d __a, double const *__dp)
double __u;
} __attribute__((__packed__, __may_alias__));
double __u = ((struct __mm_loadl_pd_struct*)__dp)->__u;
- return (__m128d){ __u, __a[1] };
+ return __extension__ (__m128d){ __u, __a[1] };
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double] with
+/// Constructs a 128-bit floating-point vector of [2 x double] with
/// unspecified content. This could be used as an argument to another
/// intrinsic function where the argument is required but the value is not
/// actually used.
@@ -1771,7 +1770,7 @@ _mm_undefined_pd(void)
return (__m128d)__builtin_ia32_undef128();
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double]. The lower
+/// Constructs a 128-bit floating-point vector of [2 x double]. The lower
/// 64 bits of the vector are initialized with the specified double-precision
/// floating-point value. The upper 64 bits are set to zero.
///
@@ -1788,10 +1787,10 @@ _mm_undefined_pd(void)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_sd(double __w)
{
- return (__m128d){ __w, 0 };
+ return __extension__ (__m128d){ __w, 0 };
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double], with each
+/// Constructs a 128-bit floating-point vector of [2 x double], with each
/// of the two double-precision floating-point vector elements set to the
/// specified double-precision floating-point value.
///
@@ -1806,10 +1805,10 @@ _mm_set_sd(double __w)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set1_pd(double __w)
{
- return (__m128d){ __w, __w };
+ return __extension__ (__m128d){ __w, __w };
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double], with each
+/// Constructs a 128-bit floating-point vector of [2 x double], with each
/// of the two double-precision floating-point vector elements set to the
/// specified double-precision floating-point value.
///
@@ -1827,7 +1826,7 @@ _mm_set_pd1(double __w)
return _mm_set1_pd(__w);
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double]
+/// Constructs a 128-bit floating-point vector of [2 x double]
/// initialized with the specified double-precision floating-point values.
///
/// \headerfile <x86intrin.h>
@@ -1844,10 +1843,10 @@ _mm_set_pd1(double __w)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_pd(double __w, double __x)
{
- return (__m128d){ __x, __w };
+ return __extension__ (__m128d){ __x, __w };
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double],
+/// Constructs a 128-bit floating-point vector of [2 x double],
/// initialized in reverse order with the specified double-precision
/// floating-point values.
///
@@ -1865,10 +1864,10 @@ _mm_set_pd(double __w, double __x)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_setr_pd(double __w, double __x)
{
- return (__m128d){ __w, __x };
+ return __extension__ (__m128d){ __w, __x };
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double]
+/// Constructs a 128-bit floating-point vector of [2 x double]
/// initialized to zero.
///
/// \headerfile <x86intrin.h>
@@ -1880,10 +1879,10 @@ _mm_setr_pd(double __w, double __x)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_setzero_pd(void)
{
- return (__m128d){ 0, 0 };
+ return __extension__ (__m128d){ 0, 0 };
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double]. The lower
+/// Constructs a 128-bit floating-point vector of [2 x double]. The lower
/// 64 bits are set to the lower 64 bits of the second parameter. The upper
/// 64 bits are set to the upper 64 bits of the first parameter.
///
@@ -1901,10 +1900,11 @@ _mm_setzero_pd(void)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_move_sd(__m128d __a, __m128d __b)
{
- return (__m128d){ __b[0], __a[1] };
+ __a[0] = __b[0];
+ return __a;
}
-/// \brief Stores the lower 64 bits of a 128-bit vector of [2 x double] to a
+/// Stores the lower 64 bits of a 128-bit vector of [2 x double] to a
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -1924,7 +1924,7 @@ _mm_store_sd(double *__dp, __m128d __a)
((struct __mm_store_sd_struct*)__dp)->__u = __a[0];
}
-/// \brief Moves packed double-precision values from a 128-bit vector of
+/// Moves packed double-precision values from a 128-bit vector of
/// [2 x double] to a memory location.
///
/// \headerfile <x86intrin.h>
@@ -1943,7 +1943,7 @@ _mm_store_pd(double *__dp, __m128d __a)
*(__m128d*)__dp = __a;
}
-/// \brief Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
+/// Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
/// the upper and lower 64 bits of a memory location.
///
/// \headerfile <x86intrin.h>
@@ -1964,7 +1964,7 @@ _mm_store1_pd(double *__dp, __m128d __a)
_mm_store_pd(__dp, __a);
}
-/// \brief Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
+/// Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
/// the upper and lower 64 bits of a memory location.
///
/// \headerfile <x86intrin.h>
@@ -1981,10 +1981,10 @@ _mm_store1_pd(double *__dp, __m128d __a)
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_pd1(double *__dp, __m128d __a)
{
- return _mm_store1_pd(__dp, __a);
+ _mm_store1_pd(__dp, __a);
}
-/// \brief Stores a 128-bit vector of [2 x double] into an unaligned memory
+/// Stores a 128-bit vector of [2 x double] into an unaligned memory
/// location.
///
/// \headerfile <x86intrin.h>
@@ -2005,7 +2005,7 @@ _mm_storeu_pd(double *__dp, __m128d __a)
((struct __storeu_pd*)__dp)->__v = __a;
}
-/// \brief Stores two double-precision values, in reverse order, from a 128-bit
+/// Stores two double-precision values, in reverse order, from a 128-bit
/// vector of [2 x double] to a 16-byte aligned memory location.
///
/// \headerfile <x86intrin.h>
@@ -2026,7 +2026,7 @@ _mm_storer_pd(double *__dp, __m128d __a)
*(__m128d *)__dp = __a;
}
-/// \brief Stores the upper 64 bits of a 128-bit vector of [2 x double] to a
+/// Stores the upper 64 bits of a 128-bit vector of [2 x double] to a
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -2046,7 +2046,7 @@ _mm_storeh_pd(double *__dp, __m128d __a)
((struct __mm_storeh_pd_struct*)__dp)->__u = __a[1];
}
-/// \brief Stores the lower 64 bits of a 128-bit vector of [2 x double] to a
+/// Stores the lower 64 bits of a 128-bit vector of [2 x double] to a
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -2066,7 +2066,7 @@ _mm_storel_pd(double *__dp, __m128d __a)
((struct __mm_storeh_pd_struct*)__dp)->__u = __a[0];
}
-/// \brief Adds the corresponding elements of two 128-bit vectors of [16 x i8],
+/// Adds the corresponding elements of two 128-bit vectors of [16 x i8],
/// saving the lower 8 bits of each sum in the corresponding element of a
/// 128-bit result vector of [16 x i8].
///
@@ -2088,7 +2088,7 @@ _mm_add_epi8(__m128i __a, __m128i __b)
return (__m128i)((__v16qu)__a + (__v16qu)__b);
}
-/// \brief Adds the corresponding elements of two 128-bit vectors of [8 x i16],
+/// Adds the corresponding elements of two 128-bit vectors of [8 x i16],
/// saving the lower 16 bits of each sum in the corresponding element of a
/// 128-bit result vector of [8 x i16].
///
@@ -2110,7 +2110,7 @@ _mm_add_epi16(__m128i __a, __m128i __b)
return (__m128i)((__v8hu)__a + (__v8hu)__b);
}
-/// \brief Adds the corresponding elements of two 128-bit vectors of [4 x i32],
+/// Adds the corresponding elements of two 128-bit vectors of [4 x i32],
/// saving the lower 32 bits of each sum in the corresponding element of a
/// 128-bit result vector of [4 x i32].
///
@@ -2132,7 +2132,7 @@ _mm_add_epi32(__m128i __a, __m128i __b)
return (__m128i)((__v4su)__a + (__v4su)__b);
}
-/// \brief Adds two signed or unsigned 64-bit integer values, returning the
+/// Adds two signed or unsigned 64-bit integer values, returning the
/// lower 64 bits of the sum.
///
/// \headerfile <x86intrin.h>
@@ -2144,13 +2144,13 @@ _mm_add_epi32(__m128i __a, __m128i __b)
/// \param __b
/// A 64-bit integer.
/// \returns A 64-bit integer containing the sum of both parameters.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_add_si64(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_paddq((__v1di)__a, (__v1di)__b);
}
-/// \brief Adds the corresponding elements of two 128-bit vectors of [2 x i64],
+/// Adds the corresponding elements of two 128-bit vectors of [2 x i64],
/// saving the lower 64 bits of each sum in the corresponding element of a
/// 128-bit result vector of [2 x i64].
///
@@ -2172,10 +2172,10 @@ _mm_add_epi64(__m128i __a, __m128i __b)
return (__m128i)((__v2du)__a + (__v2du)__b);
}
-/// \brief Adds, with saturation, the corresponding elements of two 128-bit
+/// Adds, with saturation, the corresponding elements of two 128-bit
/// signed [16 x i8] vectors, saving each sum in the corresponding element of
-/// a 128-bit result vector of [16 x i8]. Positive sums greater than 7Fh are
-/// saturated to 7Fh. Negative sums less than 80h are saturated to 80h.
+/// a 128-bit result vector of [16 x i8]. Positive sums greater than 0x7F are
+/// saturated to 0x7F. Negative sums less than 0x80 are saturated to 0x80.
///
/// \headerfile <x86intrin.h>
///
@@ -2193,11 +2193,11 @@ _mm_adds_epi8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_paddsb128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Adds, with saturation, the corresponding elements of two 128-bit
+/// Adds, with saturation, the corresponding elements of two 128-bit
/// signed [8 x i16] vectors, saving each sum in the corresponding element of
-/// a 128-bit result vector of [8 x i16]. Positive sums greater than 7FFFh
-/// are saturated to 7FFFh. Negative sums less than 8000h are saturated to
-/// 8000h.
+/// a 128-bit result vector of [8 x i16]. Positive sums greater than 0x7FFF
+/// are saturated to 0x7FFF. Negative sums less than 0x8000 are saturated to
+/// 0x8000.
///
/// \headerfile <x86intrin.h>
///
@@ -2215,10 +2215,10 @@ _mm_adds_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_paddsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Adds, with saturation, the corresponding elements of two 128-bit
+/// Adds, with saturation, the corresponding elements of two 128-bit
/// unsigned [16 x i8] vectors, saving each sum in the corresponding element
-/// of a 128-bit result vector of [16 x i8]. Positive sums greater than FFh
-/// are saturated to FFh. Negative sums are saturated to 00h.
+/// of a 128-bit result vector of [16 x i8]. Positive sums greater than 0xFF
+/// are saturated to 0xFF. Negative sums are saturated to 0x00.
///
/// \headerfile <x86intrin.h>
///
@@ -2236,10 +2236,10 @@ _mm_adds_epu8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_paddusb128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Adds, with saturation, the corresponding elements of two 128-bit
+/// Adds, with saturation, the corresponding elements of two 128-bit
/// unsigned [8 x i16] vectors, saving each sum in the corresponding element
-/// of a 128-bit result vector of [8 x i16]. Positive sums greater than FFFFh
-/// are saturated to FFFFh. Negative sums are saturated to 0000h.
+/// of a 128-bit result vector of [8 x i16]. Positive sums greater than
+/// 0xFFFF are saturated to 0xFFFF. Negative sums are saturated to 0x0000.
///
/// \headerfile <x86intrin.h>
///
@@ -2257,7 +2257,7 @@ _mm_adds_epu16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_paddusw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Computes the rounded avarages of corresponding elements of two
+/// Computes the rounded avarages of corresponding elements of two
/// 128-bit unsigned [16 x i8] vectors, saving each result in the
/// corresponding element of a 128-bit result vector of [16 x i8].
///
@@ -2281,7 +2281,7 @@ _mm_avg_epu8(__m128i __a, __m128i __b)
>> 1, __v16qu);
}
-/// \brief Computes the rounded avarages of corresponding elements of two
+/// Computes the rounded avarages of corresponding elements of two
/// 128-bit unsigned [8 x i16] vectors, saving each result in the
/// corresponding element of a 128-bit result vector of [8 x i16].
///
@@ -2305,7 +2305,7 @@ _mm_avg_epu16(__m128i __a, __m128i __b)
>> 1, __v8hu);
}
-/// \brief Multiplies the corresponding elements of two 128-bit signed [8 x i16]
+/// Multiplies the corresponding elements of two 128-bit signed [8 x i16]
/// vectors, producing eight intermediate 32-bit signed integer products, and
/// adds the consecutive pairs of 32-bit products to form a 128-bit signed
/// [4 x i32] vector.
@@ -2331,7 +2331,7 @@ _mm_madd_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmaddwd128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Compares corresponding elements of two 128-bit signed [8 x i16]
+/// Compares corresponding elements of two 128-bit signed [8 x i16]
/// vectors, saving the greater value from each comparison in the
/// corresponding element of a 128-bit result vector of [8 x i16].
///
@@ -2351,7 +2351,7 @@ _mm_max_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmaxsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Compares corresponding elements of two 128-bit unsigned [16 x i8]
+/// Compares corresponding elements of two 128-bit unsigned [16 x i8]
/// vectors, saving the greater value from each comparison in the
/// corresponding element of a 128-bit result vector of [16 x i8].
///
@@ -2371,7 +2371,7 @@ _mm_max_epu8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmaxub128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Compares corresponding elements of two 128-bit signed [8 x i16]
+/// Compares corresponding elements of two 128-bit signed [8 x i16]
/// vectors, saving the smaller value from each comparison in the
/// corresponding element of a 128-bit result vector of [8 x i16].
///
@@ -2391,7 +2391,7 @@ _mm_min_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pminsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Compares corresponding elements of two 128-bit unsigned [16 x i8]
+/// Compares corresponding elements of two 128-bit unsigned [16 x i8]
/// vectors, saving the smaller value from each comparison in the
/// corresponding element of a 128-bit result vector of [16 x i8].
///
@@ -2411,7 +2411,7 @@ _mm_min_epu8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pminub128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Multiplies the corresponding elements of two signed [8 x i16]
+/// Multiplies the corresponding elements of two signed [8 x i16]
/// vectors, saving the upper 16 bits of each 32-bit product in the
/// corresponding element of a 128-bit signed [8 x i16] result vector.
///
@@ -2431,7 +2431,7 @@ _mm_mulhi_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmulhw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Multiplies the corresponding elements of two unsigned [8 x i16]
+/// Multiplies the corresponding elements of two unsigned [8 x i16]
/// vectors, saving the upper 16 bits of each 32-bit product in the
/// corresponding element of a 128-bit unsigned [8 x i16] result vector.
///
@@ -2451,7 +2451,7 @@ _mm_mulhi_epu16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmulhuw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Multiplies the corresponding elements of two signed [8 x i16]
+/// Multiplies the corresponding elements of two signed [8 x i16]
/// vectors, saving the lower 16 bits of each 32-bit product in the
/// corresponding element of a 128-bit signed [8 x i16] result vector.
///
@@ -2471,7 +2471,7 @@ _mm_mullo_epi16(__m128i __a, __m128i __b)
return (__m128i)((__v8hu)__a * (__v8hu)__b);
}
-/// \brief Multiplies 32-bit unsigned integer values contained in the lower bits
+/// Multiplies 32-bit unsigned integer values contained in the lower bits
/// of the two 64-bit integer vectors and returns the 64-bit unsigned
/// product.
///
@@ -2484,13 +2484,13 @@ _mm_mullo_epi16(__m128i __a, __m128i __b)
/// \param __b
/// A 64-bit integer containing one of the source operands.
/// \returns A 64-bit integer vector containing the product of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_mul_su32(__m64 __a, __m64 __b)
{
return __builtin_ia32_pmuludq((__v2si)__a, (__v2si)__b);
}
-/// \brief Multiplies 32-bit unsigned integer values contained in the lower
+/// Multiplies 32-bit unsigned integer values contained in the lower
/// bits of the corresponding elements of two [2 x i64] vectors, and returns
/// the 64-bit products in the corresponding elements of a [2 x i64] vector.
///
@@ -2509,7 +2509,7 @@ _mm_mul_epu32(__m128i __a, __m128i __b)
return __builtin_ia32_pmuludq128((__v4si)__a, (__v4si)__b);
}
-/// \brief Computes the absolute differences of corresponding 8-bit integer
+/// Computes the absolute differences of corresponding 8-bit integer
/// values in two 128-bit vectors. Sums the first 8 absolute differences, and
/// separately sums the second 8 absolute differences. Packs these two
/// unsigned 16-bit integer sums into the upper and lower elements of a
@@ -2531,7 +2531,7 @@ _mm_sad_epu8(__m128i __a, __m128i __b)
return __builtin_ia32_psadbw128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Subtracts the corresponding 8-bit integer values in the operands.
+/// Subtracts the corresponding 8-bit integer values in the operands.
///
/// \headerfile <x86intrin.h>
///
@@ -2549,7 +2549,7 @@ _mm_sub_epi8(__m128i __a, __m128i __b)
return (__m128i)((__v16qu)__a - (__v16qu)__b);
}
-/// \brief Subtracts the corresponding 16-bit integer values in the operands.
+/// Subtracts the corresponding 16-bit integer values in the operands.
///
/// \headerfile <x86intrin.h>
///
@@ -2567,7 +2567,7 @@ _mm_sub_epi16(__m128i __a, __m128i __b)
return (__m128i)((__v8hu)__a - (__v8hu)__b);
}
-/// \brief Subtracts the corresponding 32-bit integer values in the operands.
+/// Subtracts the corresponding 32-bit integer values in the operands.
///
/// \headerfile <x86intrin.h>
///
@@ -2585,7 +2585,7 @@ _mm_sub_epi32(__m128i __a, __m128i __b)
return (__m128i)((__v4su)__a - (__v4su)__b);
}
-/// \brief Subtracts signed or unsigned 64-bit integer values and writes the
+/// Subtracts signed or unsigned 64-bit integer values and writes the
/// difference to the corresponding bits in the destination.
///
/// \headerfile <x86intrin.h>
@@ -2598,13 +2598,13 @@ _mm_sub_epi32(__m128i __a, __m128i __b)
/// A 64-bit integer vector containing the subtrahend.
/// \returns A 64-bit integer vector containing the difference of the values in
/// the operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_sub_si64(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psubq((__v1di)__a, (__v1di)__b);
}
-/// \brief Subtracts the corresponding elements of two [2 x i64] vectors.
+/// Subtracts the corresponding elements of two [2 x i64] vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -2622,10 +2622,10 @@ _mm_sub_epi64(__m128i __a, __m128i __b)
return (__m128i)((__v2du)__a - (__v2du)__b);
}
-/// \brief Subtracts corresponding 8-bit signed integer values in the input and
+/// Subtracts corresponding 8-bit signed integer values in the input and
/// returns the differences in the corresponding bytes in the destination.
-/// Differences greater than 7Fh are saturated to 7Fh, and differences less
-/// than 80h are saturated to 80h.
+/// Differences greater than 0x7F are saturated to 0x7F, and differences less
+/// than 0x80 are saturated to 0x80.
///
/// \headerfile <x86intrin.h>
///
@@ -2643,10 +2643,10 @@ _mm_subs_epi8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psubsb128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Subtracts corresponding 16-bit signed integer values in the input and
+/// Subtracts corresponding 16-bit signed integer values in the input and
/// returns the differences in the corresponding bytes in the destination.
-/// Differences greater than 7FFFh are saturated to 7FFFh, and values less
-/// than 8000h are saturated to 8000h.
+/// Differences greater than 0x7FFF are saturated to 0x7FFF, and values less
+/// than 0x8000 are saturated to 0x8000.
///
/// \headerfile <x86intrin.h>
///
@@ -2664,9 +2664,9 @@ _mm_subs_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psubsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Subtracts corresponding 8-bit unsigned integer values in the input
+/// Subtracts corresponding 8-bit unsigned integer values in the input
/// and returns the differences in the corresponding bytes in the
-/// destination. Differences less than 00h are saturated to 00h.
+/// destination. Differences less than 0x00 are saturated to 0x00.
///
/// \headerfile <x86intrin.h>
///
@@ -2684,9 +2684,9 @@ _mm_subs_epu8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psubusb128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Subtracts corresponding 16-bit unsigned integer values in the input
+/// Subtracts corresponding 16-bit unsigned integer values in the input
/// and returns the differences in the corresponding bytes in the
-/// destination. Differences less than 0000h are saturated to 0000h.
+/// destination. Differences less than 0x0000 are saturated to 0x0000.
///
/// \headerfile <x86intrin.h>
///
@@ -2704,7 +2704,7 @@ _mm_subs_epu16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psubusw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Performs a bitwise AND of two 128-bit integer vectors.
+/// Performs a bitwise AND of two 128-bit integer vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -2722,7 +2722,7 @@ _mm_and_si128(__m128i __a, __m128i __b)
return (__m128i)((__v2du)__a & (__v2du)__b);
}
-/// \brief Performs a bitwise AND of two 128-bit integer vectors, using the
+/// Performs a bitwise AND of two 128-bit integer vectors, using the
/// one's complement of the values contained in the first source operand.
///
/// \headerfile <x86intrin.h>
@@ -2741,7 +2741,7 @@ _mm_andnot_si128(__m128i __a, __m128i __b)
{
return (__m128i)(~(__v2du)__a & (__v2du)__b);
}
-/// \brief Performs a bitwise OR of two 128-bit integer vectors.
+/// Performs a bitwise OR of two 128-bit integer vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -2759,7 +2759,7 @@ _mm_or_si128(__m128i __a, __m128i __b)
return (__m128i)((__v2du)__a | (__v2du)__b);
}
-/// \brief Performs a bitwise exclusive OR of two 128-bit integer vectors.
+/// Performs a bitwise exclusive OR of two 128-bit integer vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -2777,7 +2777,7 @@ _mm_xor_si128(__m128i __a, __m128i __b)
return (__m128i)((__v2du)__a ^ (__v2du)__b);
}
-/// \brief Left-shifts the 128-bit integer vector operand by the specified
+/// Left-shifts the 128-bit integer vector operand by the specified
/// number of bytes. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2794,31 +2794,13 @@ _mm_xor_si128(__m128i __a, __m128i __b)
/// An immediate value specifying the number of bytes to left-shift operand
/// \a a.
/// \returns A 128-bit integer vector containing the left-shifted value.
-#define _mm_slli_si128(a, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector( \
- (__v16qi)_mm_setzero_si128(), \
- (__v16qi)(__m128i)(a), \
- ((char)(imm)&0xF0) ? 0 : 16 - (char)(imm), \
- ((char)(imm)&0xF0) ? 1 : 17 - (char)(imm), \
- ((char)(imm)&0xF0) ? 2 : 18 - (char)(imm), \
- ((char)(imm)&0xF0) ? 3 : 19 - (char)(imm), \
- ((char)(imm)&0xF0) ? 4 : 20 - (char)(imm), \
- ((char)(imm)&0xF0) ? 5 : 21 - (char)(imm), \
- ((char)(imm)&0xF0) ? 6 : 22 - (char)(imm), \
- ((char)(imm)&0xF0) ? 7 : 23 - (char)(imm), \
- ((char)(imm)&0xF0) ? 8 : 24 - (char)(imm), \
- ((char)(imm)&0xF0) ? 9 : 25 - (char)(imm), \
- ((char)(imm)&0xF0) ? 10 : 26 - (char)(imm), \
- ((char)(imm)&0xF0) ? 11 : 27 - (char)(imm), \
- ((char)(imm)&0xF0) ? 12 : 28 - (char)(imm), \
- ((char)(imm)&0xF0) ? 13 : 29 - (char)(imm), \
- ((char)(imm)&0xF0) ? 14 : 30 - (char)(imm), \
- ((char)(imm)&0xF0) ? 15 : 31 - (char)(imm)); })
+#define _mm_slli_si128(a, imm) \
+ (__m128i)__builtin_ia32_pslldqi128_byteshift((__v2di)(__m128i)(a), (int)(imm))
#define _mm_bslli_si128(a, imm) \
- _mm_slli_si128((a), (imm))
+ (__m128i)__builtin_ia32_pslldqi128_byteshift((__v2di)(__m128i)(a), (int)(imm))
-/// \brief Left-shifts each 16-bit value in the 128-bit integer vector operand
+/// Left-shifts each 16-bit value in the 128-bit integer vector operand
/// by the specified number of bits. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2837,7 +2819,7 @@ _mm_slli_epi16(__m128i __a, int __count)
return (__m128i)__builtin_ia32_psllwi128((__v8hi)__a, __count);
}
-/// \brief Left-shifts each 16-bit value in the 128-bit integer vector operand
+/// Left-shifts each 16-bit value in the 128-bit integer vector operand
/// by the specified number of bits. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2856,7 +2838,7 @@ _mm_sll_epi16(__m128i __a, __m128i __count)
return (__m128i)__builtin_ia32_psllw128((__v8hi)__a, (__v8hi)__count);
}
-/// \brief Left-shifts each 32-bit value in the 128-bit integer vector operand
+/// Left-shifts each 32-bit value in the 128-bit integer vector operand
/// by the specified number of bits. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2875,7 +2857,7 @@ _mm_slli_epi32(__m128i __a, int __count)
return (__m128i)__builtin_ia32_pslldi128((__v4si)__a, __count);
}
-/// \brief Left-shifts each 32-bit value in the 128-bit integer vector operand
+/// Left-shifts each 32-bit value in the 128-bit integer vector operand
/// by the specified number of bits. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2894,7 +2876,7 @@ _mm_sll_epi32(__m128i __a, __m128i __count)
return (__m128i)__builtin_ia32_pslld128((__v4si)__a, (__v4si)__count);
}
-/// \brief Left-shifts each 64-bit value in the 128-bit integer vector operand
+/// Left-shifts each 64-bit value in the 128-bit integer vector operand
/// by the specified number of bits. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2913,7 +2895,7 @@ _mm_slli_epi64(__m128i __a, int __count)
return __builtin_ia32_psllqi128((__v2di)__a, __count);
}
-/// \brief Left-shifts each 64-bit value in the 128-bit integer vector operand
+/// Left-shifts each 64-bit value in the 128-bit integer vector operand
/// by the specified number of bits. Low-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -2932,7 +2914,7 @@ _mm_sll_epi64(__m128i __a, __m128i __count)
return __builtin_ia32_psllq128((__v2di)__a, (__v2di)__count);
}
-/// \brief Right-shifts each 16-bit value in the 128-bit integer vector operand
+/// Right-shifts each 16-bit value in the 128-bit integer vector operand
/// by the specified number of bits. High-order bits are filled with the sign
/// bit of the initial value.
///
@@ -2952,7 +2934,7 @@ _mm_srai_epi16(__m128i __a, int __count)
return (__m128i)__builtin_ia32_psrawi128((__v8hi)__a, __count);
}
-/// \brief Right-shifts each 16-bit value in the 128-bit integer vector operand
+/// Right-shifts each 16-bit value in the 128-bit integer vector operand
/// by the specified number of bits. High-order bits are filled with the sign
/// bit of the initial value.
///
@@ -2972,7 +2954,7 @@ _mm_sra_epi16(__m128i __a, __m128i __count)
return (__m128i)__builtin_ia32_psraw128((__v8hi)__a, (__v8hi)__count);
}
-/// \brief Right-shifts each 32-bit value in the 128-bit integer vector operand
+/// Right-shifts each 32-bit value in the 128-bit integer vector operand
/// by the specified number of bits. High-order bits are filled with the sign
/// bit of the initial value.
///
@@ -2992,7 +2974,7 @@ _mm_srai_epi32(__m128i __a, int __count)
return (__m128i)__builtin_ia32_psradi128((__v4si)__a, __count);
}
-/// \brief Right-shifts each 32-bit value in the 128-bit integer vector operand
+/// Right-shifts each 32-bit value in the 128-bit integer vector operand
/// by the specified number of bits. High-order bits are filled with the sign
/// bit of the initial value.
///
@@ -3012,7 +2994,7 @@ _mm_sra_epi32(__m128i __a, __m128i __count)
return (__m128i)__builtin_ia32_psrad128((__v4si)__a, (__v4si)__count);
}
-/// \brief Right-shifts the 128-bit integer vector operand by the specified
+/// Right-shifts the 128-bit integer vector operand by the specified
/// number of bytes. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3029,31 +3011,13 @@ _mm_sra_epi32(__m128i __a, __m128i __count)
/// An immediate value specifying the number of bytes to right-shift operand
/// \a a.
/// \returns A 128-bit integer vector containing the right-shifted value.
-#define _mm_srli_si128(a, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector( \
- (__v16qi)(__m128i)(a), \
- (__v16qi)_mm_setzero_si128(), \
- ((char)(imm)&0xF0) ? 16 : (char)(imm) + 0, \
- ((char)(imm)&0xF0) ? 17 : (char)(imm) + 1, \
- ((char)(imm)&0xF0) ? 18 : (char)(imm) + 2, \
- ((char)(imm)&0xF0) ? 19 : (char)(imm) + 3, \
- ((char)(imm)&0xF0) ? 20 : (char)(imm) + 4, \
- ((char)(imm)&0xF0) ? 21 : (char)(imm) + 5, \
- ((char)(imm)&0xF0) ? 22 : (char)(imm) + 6, \
- ((char)(imm)&0xF0) ? 23 : (char)(imm) + 7, \
- ((char)(imm)&0xF0) ? 24 : (char)(imm) + 8, \
- ((char)(imm)&0xF0) ? 25 : (char)(imm) + 9, \
- ((char)(imm)&0xF0) ? 26 : (char)(imm) + 10, \
- ((char)(imm)&0xF0) ? 27 : (char)(imm) + 11, \
- ((char)(imm)&0xF0) ? 28 : (char)(imm) + 12, \
- ((char)(imm)&0xF0) ? 29 : (char)(imm) + 13, \
- ((char)(imm)&0xF0) ? 30 : (char)(imm) + 14, \
- ((char)(imm)&0xF0) ? 31 : (char)(imm) + 15); })
+#define _mm_srli_si128(a, imm) \
+ (__m128i)__builtin_ia32_psrldqi128_byteshift((__v2di)(__m128i)(a), (int)(imm))
#define _mm_bsrli_si128(a, imm) \
- _mm_srli_si128((a), (imm))
+ (__m128i)__builtin_ia32_psrldqi128_byteshift((__v2di)(__m128i)(a), (int)(imm))
-/// \brief Right-shifts each of 16-bit values in the 128-bit integer vector
+/// Right-shifts each of 16-bit values in the 128-bit integer vector
/// operand by the specified number of bits. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3072,7 +3036,7 @@ _mm_srli_epi16(__m128i __a, int __count)
return (__m128i)__builtin_ia32_psrlwi128((__v8hi)__a, __count);
}
-/// \brief Right-shifts each of 16-bit values in the 128-bit integer vector
+/// Right-shifts each of 16-bit values in the 128-bit integer vector
/// operand by the specified number of bits. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3091,7 +3055,7 @@ _mm_srl_epi16(__m128i __a, __m128i __count)
return (__m128i)__builtin_ia32_psrlw128((__v8hi)__a, (__v8hi)__count);
}
-/// \brief Right-shifts each of 32-bit values in the 128-bit integer vector
+/// Right-shifts each of 32-bit values in the 128-bit integer vector
/// operand by the specified number of bits. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3110,7 +3074,7 @@ _mm_srli_epi32(__m128i __a, int __count)
return (__m128i)__builtin_ia32_psrldi128((__v4si)__a, __count);
}
-/// \brief Right-shifts each of 32-bit values in the 128-bit integer vector
+/// Right-shifts each of 32-bit values in the 128-bit integer vector
/// operand by the specified number of bits. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3129,7 +3093,7 @@ _mm_srl_epi32(__m128i __a, __m128i __count)
return (__m128i)__builtin_ia32_psrld128((__v4si)__a, (__v4si)__count);
}
-/// \brief Right-shifts each of 64-bit values in the 128-bit integer vector
+/// Right-shifts each of 64-bit values in the 128-bit integer vector
/// operand by the specified number of bits. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3148,7 +3112,7 @@ _mm_srli_epi64(__m128i __a, int __count)
return __builtin_ia32_psrlqi128((__v2di)__a, __count);
}
-/// \brief Right-shifts each of 64-bit values in the 128-bit integer vector
+/// Right-shifts each of 64-bit values in the 128-bit integer vector
/// operand by the specified number of bits. High-order bits are cleared.
///
/// \headerfile <x86intrin.h>
@@ -3167,8 +3131,8 @@ _mm_srl_epi64(__m128i __a, __m128i __count)
return __builtin_ia32_psrlq128((__v2di)__a, (__v2di)__count);
}
-/// \brief Compares each of the corresponding 8-bit values of the 128-bit
-/// integer vectors for equality. Each comparison yields 0h for false, FFh
+/// Compares each of the corresponding 8-bit values of the 128-bit
+/// integer vectors for equality. Each comparison yields 0x0 for false, 0xFF
/// for true.
///
/// \headerfile <x86intrin.h>
@@ -3186,9 +3150,9 @@ _mm_cmpeq_epi8(__m128i __a, __m128i __b)
return (__m128i)((__v16qi)__a == (__v16qi)__b);
}
-/// \brief Compares each of the corresponding 16-bit values of the 128-bit
-/// integer vectors for equality. Each comparison yields 0h for false, FFFFh
-/// for true.
+/// Compares each of the corresponding 16-bit values of the 128-bit
+/// integer vectors for equality. Each comparison yields 0x0 for false,
+/// 0xFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3205,9 +3169,9 @@ _mm_cmpeq_epi16(__m128i __a, __m128i __b)
return (__m128i)((__v8hi)__a == (__v8hi)__b);
}
-/// \brief Compares each of the corresponding 32-bit values of the 128-bit
-/// integer vectors for equality. Each comparison yields 0h for false,
-/// FFFFFFFFh for true.
+/// Compares each of the corresponding 32-bit values of the 128-bit
+/// integer vectors for equality. Each comparison yields 0x0 for false,
+/// 0xFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3224,10 +3188,10 @@ _mm_cmpeq_epi32(__m128i __a, __m128i __b)
return (__m128i)((__v4si)__a == (__v4si)__b);
}
-/// \brief Compares each of the corresponding signed 8-bit values of the 128-bit
+/// Compares each of the corresponding signed 8-bit values of the 128-bit
/// integer vectors to determine if the values in the first operand are
-/// greater than those in the second operand. Each comparison yields 0h for
-/// false, FFh for true.
+/// greater than those in the second operand. Each comparison yields 0x0 for
+/// false, 0xFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3246,11 +3210,11 @@ _mm_cmpgt_epi8(__m128i __a, __m128i __b)
return (__m128i)((__v16qs)__a > (__v16qs)__b);
}
-/// \brief Compares each of the corresponding signed 16-bit values of the
+/// Compares each of the corresponding signed 16-bit values of the
/// 128-bit integer vectors to determine if the values in the first operand
/// are greater than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3267,11 +3231,11 @@ _mm_cmpgt_epi16(__m128i __a, __m128i __b)
return (__m128i)((__v8hi)__a > (__v8hi)__b);
}
-/// \brief Compares each of the corresponding signed 32-bit values of the
+/// Compares each of the corresponding signed 32-bit values of the
/// 128-bit integer vectors to determine if the values in the first operand
/// are greater than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3288,11 +3252,11 @@ _mm_cmpgt_epi32(__m128i __a, __m128i __b)
return (__m128i)((__v4si)__a > (__v4si)__b);
}
-/// \brief Compares each of the corresponding signed 8-bit values of the 128-bit
+/// Compares each of the corresponding signed 8-bit values of the 128-bit
/// integer vectors to determine if the values in the first operand are less
/// than those in the second operand.
///
-/// Each comparison yields 0h for false, FFh for true.
+/// Each comparison yields 0x0 for false, 0xFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3309,11 +3273,11 @@ _mm_cmplt_epi8(__m128i __a, __m128i __b)
return _mm_cmpgt_epi8(__b, __a);
}
-/// \brief Compares each of the corresponding signed 16-bit values of the
+/// Compares each of the corresponding signed 16-bit values of the
/// 128-bit integer vectors to determine if the values in the first operand
/// are less than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3330,11 +3294,11 @@ _mm_cmplt_epi16(__m128i __a, __m128i __b)
return _mm_cmpgt_epi16(__b, __a);
}
-/// \brief Compares each of the corresponding signed 32-bit values of the
+/// Compares each of the corresponding signed 32-bit values of the
/// 128-bit integer vectors to determine if the values in the first operand
/// are less than those in the second operand.
///
-/// Each comparison yields 0h for false, FFFFFFFFh for true.
+/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
///
/// \headerfile <x86intrin.h>
///
@@ -3352,7 +3316,7 @@ _mm_cmplt_epi32(__m128i __a, __m128i __b)
}
#ifdef __x86_64__
-/// \brief Converts a 64-bit signed integer value from the second operand into a
+/// Converts a 64-bit signed integer value from the second operand into a
/// double-precision value and returns it in the lower element of a [2 x
/// double] vector; the upper element of the returned vector is copied from
/// the upper element of the first operand.
@@ -3376,7 +3340,7 @@ _mm_cvtsi64_sd(__m128d __a, long long __b)
return __a;
}
-/// \brief Converts the first (lower) element of a vector of [2 x double] into a
+/// Converts the first (lower) element of a vector of [2 x double] into a
/// 64-bit signed integer value, according to the current rounding mode.
///
/// \headerfile <x86intrin.h>
@@ -3393,7 +3357,7 @@ _mm_cvtsd_si64(__m128d __a)
return __builtin_ia32_cvtsd2si64((__v2df)__a);
}
-/// \brief Converts the first (lower) element of a vector of [2 x double] into a
+/// Converts the first (lower) element of a vector of [2 x double] into a
/// 64-bit signed integer value, truncating the result when it is inexact.
///
/// \headerfile <x86intrin.h>
@@ -3412,7 +3376,7 @@ _mm_cvttsd_si64(__m128d __a)
}
#endif
-/// \brief Converts a vector of [4 x i32] into a vector of [4 x float].
+/// Converts a vector of [4 x i32] into a vector of [4 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -3424,10 +3388,10 @@ _mm_cvttsd_si64(__m128d __a)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtepi32_ps(__m128i __a)
{
- return __builtin_ia32_cvtdq2ps((__v4si)__a);
+ return (__m128)__builtin_convertvector((__v4si)__a, __v4sf);
}
-/// \brief Converts a vector of [4 x float] into a vector of [4 x i32].
+/// Converts a vector of [4 x float] into a vector of [4 x i32].
///
/// \headerfile <x86intrin.h>
///
@@ -3443,7 +3407,7 @@ _mm_cvtps_epi32(__m128 __a)
return (__m128i)__builtin_ia32_cvtps2dq((__v4sf)__a);
}
-/// \brief Converts a vector of [4 x float] into a vector of [4 x i32],
+/// Converts a vector of [4 x float] into a vector of [4 x i32],
/// truncating the result when it is inexact.
///
/// \headerfile <x86intrin.h>
@@ -3460,7 +3424,7 @@ _mm_cvttps_epi32(__m128 __a)
return (__m128i)__builtin_ia32_cvttps2dq((__v4sf)__a);
}
-/// \brief Returns a vector of [4 x i32] where the lowest element is the input
+/// Returns a vector of [4 x i32] where the lowest element is the input
/// operand and the remaining elements are zero.
///
/// \headerfile <x86intrin.h>
@@ -3473,11 +3437,11 @@ _mm_cvttps_epi32(__m128 __a)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtsi32_si128(int __a)
{
- return (__m128i)(__v4si){ __a, 0, 0, 0 };
+ return __extension__ (__m128i)(__v4si){ __a, 0, 0, 0 };
}
#ifdef __x86_64__
-/// \brief Returns a vector of [2 x i64] where the lower element is the input
+/// Returns a vector of [2 x i64] where the lower element is the input
/// operand and the upper element is zero.
///
/// \headerfile <x86intrin.h>
@@ -3490,11 +3454,11 @@ _mm_cvtsi32_si128(int __a)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtsi64_si128(long long __a)
{
- return (__m128i){ __a, 0 };
+ return __extension__ (__m128i)(__v2di){ __a, 0 };
}
#endif
-/// \brief Moves the least significant 32 bits of a vector of [4 x i32] to a
+/// Moves the least significant 32 bits of a vector of [4 x i32] to a
/// 32-bit signed integer value.
///
/// \headerfile <x86intrin.h>
@@ -3513,7 +3477,7 @@ _mm_cvtsi128_si32(__m128i __a)
}
#ifdef __x86_64__
-/// \brief Moves the least significant 64 bits of a vector of [2 x i64] to a
+/// Moves the least significant 64 bits of a vector of [2 x i64] to a
/// 64-bit signed integer value.
///
/// \headerfile <x86intrin.h>
@@ -3531,7 +3495,7 @@ _mm_cvtsi128_si64(__m128i __a)
}
#endif
-/// \brief Moves packed integer values from an aligned 128-bit memory location
+/// Moves packed integer values from an aligned 128-bit memory location
/// to elements in a 128-bit integer vector.
///
/// \headerfile <x86intrin.h>
@@ -3547,7 +3511,7 @@ _mm_load_si128(__m128i const *__p)
return *__p;
}
-/// \brief Moves packed integer values from an unaligned 128-bit memory location
+/// Moves packed integer values from an unaligned 128-bit memory location
/// to elements in a 128-bit integer vector.
///
/// \headerfile <x86intrin.h>
@@ -3566,7 +3530,7 @@ _mm_loadu_si128(__m128i const *__p)
return ((struct __loadu_si128*)__p)->__v;
}
-/// \brief Returns a vector of [2 x i64] where the lower element is taken from
+/// Returns a vector of [2 x i64] where the lower element is taken from
/// the lower element of the operand, and the upper element is zero.
///
/// \headerfile <x86intrin.h>
@@ -3584,10 +3548,10 @@ _mm_loadl_epi64(__m128i const *__p)
struct __mm_loadl_epi64_struct {
long long __u;
} __attribute__((__packed__, __may_alias__));
- return (__m128i) { ((struct __mm_loadl_epi64_struct*)__p)->__u, 0};
+ return __extension__ (__m128i) { ((struct __mm_loadl_epi64_struct*)__p)->__u, 0};
}
-/// \brief Generates a 128-bit vector of [4 x i32] with unspecified content.
+/// Generates a 128-bit vector of [4 x i32] with unspecified content.
/// This could be used as an argument to another intrinsic function where the
/// argument is required but the value is not actually used.
///
@@ -3602,7 +3566,7 @@ _mm_undefined_si128(void)
return (__m128i)__builtin_ia32_undef128();
}
-/// \brief Initializes both 64-bit values in a 128-bit vector of [2 x i64] with
+/// Initializes both 64-bit values in a 128-bit vector of [2 x i64] with
/// the specified 64-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -3621,10 +3585,10 @@ _mm_undefined_si128(void)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi64x(long long __q1, long long __q0)
{
- return (__m128i){ __q0, __q1 };
+ return __extension__ (__m128i)(__v2di){ __q0, __q1 };
}
-/// \brief Initializes both 64-bit values in a 128-bit vector of [2 x i64] with
+/// Initializes both 64-bit values in a 128-bit vector of [2 x i64] with
/// the specified 64-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -3643,10 +3607,10 @@ _mm_set_epi64x(long long __q1, long long __q0)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi64(__m64 __q1, __m64 __q0)
{
- return (__m128i){ (long long)__q0, (long long)__q1 };
+ return _mm_set_epi64x((long long)__q1, (long long)__q0);
}
-/// \brief Initializes the 32-bit values in a 128-bit vector of [4 x i32] with
+/// Initializes the 32-bit values in a 128-bit vector of [4 x i32] with
/// the specified 32-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -3671,10 +3635,10 @@ _mm_set_epi64(__m64 __q1, __m64 __q0)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi32(int __i3, int __i2, int __i1, int __i0)
{
- return (__m128i)(__v4si){ __i0, __i1, __i2, __i3};
+ return __extension__ (__m128i)(__v4si){ __i0, __i1, __i2, __i3};
}
-/// \brief Initializes the 16-bit values in a 128-bit vector of [8 x i16] with
+/// Initializes the 16-bit values in a 128-bit vector of [8 x i16] with
/// the specified 16-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -3711,10 +3675,10 @@ _mm_set_epi32(int __i3, int __i2, int __i1, int __i0)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3, short __w2, short __w1, short __w0)
{
- return (__m128i)(__v8hi){ __w0, __w1, __w2, __w3, __w4, __w5, __w6, __w7 };
+ return __extension__ (__m128i)(__v8hi){ __w0, __w1, __w2, __w3, __w4, __w5, __w6, __w7 };
}
-/// \brief Initializes the 8-bit values in a 128-bit vector of [16 x i8] with
+/// Initializes the 8-bit values in a 128-bit vector of [16 x i8] with
/// the specified 8-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -3759,10 +3723,10 @@ _mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3, short
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi8(char __b15, char __b14, char __b13, char __b12, char __b11, char __b10, char __b9, char __b8, char __b7, char __b6, char __b5, char __b4, char __b3, char __b2, char __b1, char __b0)
{
- return (__m128i)(__v16qi){ __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7, __b8, __b9, __b10, __b11, __b12, __b13, __b14, __b15 };
+ return __extension__ (__m128i)(__v16qi){ __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7, __b8, __b9, __b10, __b11, __b12, __b13, __b14, __b15 };
}
-/// \brief Initializes both values in a 128-bit integer vector with the
+/// Initializes both values in a 128-bit integer vector with the
/// specified 64-bit integer value.
///
/// \headerfile <x86intrin.h>
@@ -3778,10 +3742,10 @@ _mm_set_epi8(char __b15, char __b14, char __b13, char __b12, char __b11, char __
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi64x(long long __q)
{
- return (__m128i){ __q, __q };
+ return _mm_set_epi64x(__q, __q);
}
-/// \brief Initializes both values in a 128-bit vector of [2 x i64] with the
+/// Initializes both values in a 128-bit vector of [2 x i64] with the
/// specified 64-bit value.
///
/// \headerfile <x86intrin.h>
@@ -3797,10 +3761,10 @@ _mm_set1_epi64x(long long __q)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi64(__m64 __q)
{
- return (__m128i){ (long long)__q, (long long)__q };
+ return _mm_set_epi64(__q, __q);
}
-/// \brief Initializes all values in a 128-bit vector of [4 x i32] with the
+/// Initializes all values in a 128-bit vector of [4 x i32] with the
/// specified 32-bit value.
///
/// \headerfile <x86intrin.h>
@@ -3816,10 +3780,10 @@ _mm_set1_epi64(__m64 __q)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi32(int __i)
{
- return (__m128i)(__v4si){ __i, __i, __i, __i };
+ return _mm_set_epi32(__i, __i, __i, __i);
}
-/// \brief Initializes all values in a 128-bit vector of [8 x i16] with the
+/// Initializes all values in a 128-bit vector of [8 x i16] with the
/// specified 16-bit value.
///
/// \headerfile <x86intrin.h>
@@ -3835,10 +3799,10 @@ _mm_set1_epi32(int __i)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi16(short __w)
{
- return (__m128i)(__v8hi){ __w, __w, __w, __w, __w, __w, __w, __w };
+ return _mm_set_epi16(__w, __w, __w, __w, __w, __w, __w, __w);
}
-/// \brief Initializes all values in a 128-bit vector of [16 x i8] with the
+/// Initializes all values in a 128-bit vector of [16 x i8] with the
/// specified 8-bit value.
///
/// \headerfile <x86intrin.h>
@@ -3854,10 +3818,10 @@ _mm_set1_epi16(short __w)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi8(char __b)
{
- return (__m128i)(__v16qi){ __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b };
+ return _mm_set_epi8(__b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b);
}
-/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// Constructs a 128-bit integer vector, initialized in reverse order
/// with the specified 64-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3874,10 +3838,10 @@ _mm_set1_epi8(char __b)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi64(__m64 __q0, __m64 __q1)
{
- return (__m128i){ (long long)__q0, (long long)__q1 };
+ return _mm_set_epi64(__q1, __q0);
}
-/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// Constructs a 128-bit integer vector, initialized in reverse order
/// with the specified 32-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3897,10 +3861,10 @@ _mm_setr_epi64(__m64 __q0, __m64 __q1)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi32(int __i0, int __i1, int __i2, int __i3)
{
- return (__m128i)(__v4si){ __i0, __i1, __i2, __i3};
+ return _mm_set_epi32(__i3, __i2, __i1, __i0);
}
-/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// Constructs a 128-bit integer vector, initialized in reverse order
/// with the specified 16-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3928,10 +3892,10 @@ _mm_setr_epi32(int __i0, int __i1, int __i2, int __i3)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi16(short __w0, short __w1, short __w2, short __w3, short __w4, short __w5, short __w6, short __w7)
{
- return (__m128i)(__v8hi){ __w0, __w1, __w2, __w3, __w4, __w5, __w6, __w7 };
+ return _mm_set_epi16(__w7, __w6, __w5, __w4, __w3, __w2, __w1, __w0);
}
-/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// Constructs a 128-bit integer vector, initialized in reverse order
/// with the specified 8-bit integral values.
///
/// \headerfile <x86intrin.h>
@@ -3975,10 +3939,10 @@ _mm_setr_epi16(short __w0, short __w1, short __w2, short __w3, short __w4, short
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5, char __b6, char __b7, char __b8, char __b9, char __b10, char __b11, char __b12, char __b13, char __b14, char __b15)
{
- return (__m128i)(__v16qi){ __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7, __b8, __b9, __b10, __b11, __b12, __b13, __b14, __b15 };
+ return _mm_set_epi8(__b15, __b14, __b13, __b12, __b11, __b10, __b9, __b8, __b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0);
}
-/// \brief Creates a 128-bit integer vector initialized to zero.
+/// Creates a 128-bit integer vector initialized to zero.
///
/// \headerfile <x86intrin.h>
///
@@ -3989,10 +3953,10 @@ _mm_setr_epi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5,
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setzero_si128(void)
{
- return (__m128i){ 0LL, 0LL };
+ return __extension__ (__m128i)(__v2di){ 0LL, 0LL };
}
-/// \brief Stores a 128-bit integer vector to a memory location aligned on a
+/// Stores a 128-bit integer vector to a memory location aligned on a
/// 128-bit boundary.
///
/// \headerfile <x86intrin.h>
@@ -4010,7 +3974,7 @@ _mm_store_si128(__m128i *__p, __m128i __b)
*__p = __b;
}
-/// \brief Stores a 128-bit integer vector to an unaligned memory location.
+/// Stores a 128-bit integer vector to an unaligned memory location.
///
/// \headerfile <x86intrin.h>
///
@@ -4029,7 +3993,7 @@ _mm_storeu_si128(__m128i *__p, __m128i __b)
((struct __storeu_si128*)__p)->__v = __b;
}
-/// \brief Moves bytes selected by the mask from the first operand to the
+/// Moves bytes selected by the mask from the first operand to the
/// specified unaligned memory location. When a mask bit is 1, the
/// corresponding byte is written, otherwise it is not written.
///
@@ -4056,7 +4020,7 @@ _mm_maskmoveu_si128(__m128i __d, __m128i __n, char *__p)
__builtin_ia32_maskmovdqu((__v16qi)__d, (__v16qi)__n, __p);
}
-/// \brief Stores the lower 64 bits of a 128-bit integer vector of [2 x i64] to
+/// Stores the lower 64 bits of a 128-bit integer vector of [2 x i64] to
/// a memory location.
///
/// \headerfile <x86intrin.h>
@@ -4078,7 +4042,7 @@ _mm_storel_epi64(__m128i *__p, __m128i __a)
((struct __mm_storel_epi64_struct*)__p)->__u = __a[0];
}
-/// \brief Stores a 128-bit floating point vector of [2 x double] to a 128-bit
+/// Stores a 128-bit floating point vector of [2 x double] to a 128-bit
/// aligned memory location.
///
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
@@ -4098,7 +4062,7 @@ _mm_stream_pd(double *__p, __m128d __a)
__builtin_nontemporal_store((__v2df)__a, (__v2df*)__p);
}
-/// \brief Stores a 128-bit integer vector to a 128-bit aligned memory location.
+/// Stores a 128-bit integer vector to a 128-bit aligned memory location.
///
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon).
@@ -4117,7 +4081,7 @@ _mm_stream_si128(__m128i *__p, __m128i __a)
__builtin_nontemporal_store((__v2di)__a, (__v2di*)__p);
}
-/// \brief Stores a 32-bit integer value in the specified memory location.
+/// Stores a 32-bit integer value in the specified memory location.
///
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon).
@@ -4130,14 +4094,14 @@ _mm_stream_si128(__m128i *__p, __m128i __a)
/// A pointer to the 32-bit memory location used to store the value.
/// \param __a
/// A 32-bit integer containing the value to be stored.
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
_mm_stream_si32(int *__p, int __a)
{
__builtin_ia32_movnti(__p, __a);
}
#ifdef __x86_64__
-/// \brief Stores a 64-bit integer value in the specified memory location.
+/// Stores a 64-bit integer value in the specified memory location.
///
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon).
@@ -4150,7 +4114,7 @@ _mm_stream_si32(int *__p, int __a)
/// A pointer to the 64-bit memory location used to store the value.
/// \param __a
/// A 64-bit integer containing the value to be stored.
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
_mm_stream_si64(long long *__p, long long __a)
{
__builtin_ia32_movnti64(__p, __a);
@@ -4161,7 +4125,7 @@ _mm_stream_si64(long long *__p, long long __a)
extern "C" {
#endif
-/// \brief The cache line containing \a __p is flushed and invalidated from all
+/// The cache line containing \a __p is flushed and invalidated from all
/// caches in the coherency domain.
///
/// \headerfile <x86intrin.h>
@@ -4173,7 +4137,7 @@ extern "C" {
/// flushed.
void _mm_clflush(void const * __p);
-/// \brief Forces strong memory ordering (serialization) between load
+/// Forces strong memory ordering (serialization) between load
/// instructions preceding this instruction and load instructions following
/// this instruction, ensuring the system completes all previous loads before
/// executing subsequent loads.
@@ -4184,7 +4148,7 @@ void _mm_clflush(void const * __p);
///
void _mm_lfence(void);
-/// \brief Forces strong memory ordering (serialization) between load and store
+/// Forces strong memory ordering (serialization) between load and store
/// instructions preceding this instruction and load and store instructions
/// following this instruction, ensuring that the system completes all
/// previous memory accesses before executing subsequent memory accesses.
@@ -4199,7 +4163,7 @@ void _mm_mfence(void);
} // extern "C"
#endif
-/// \brief Converts 16-bit signed integers from both 128-bit integer vector
+/// Converts 16-bit signed integers from both 128-bit integer vector
/// operands into 8-bit signed integers, and packs the results into the
/// destination. Positive values greater than 0x7F are saturated to 0x7F.
/// Negative values less than 0x80 are saturated to 0x80.
@@ -4227,7 +4191,7 @@ _mm_packs_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_packsswb128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Converts 32-bit signed integers from both 128-bit integer vector
+/// Converts 32-bit signed integers from both 128-bit integer vector
/// operands into 16-bit signed integers, and packs the results into the
/// destination. Positive values greater than 0x7FFF are saturated to 0x7FFF.
/// Negative values less than 0x8000 are saturated to 0x8000.
@@ -4255,7 +4219,7 @@ _mm_packs_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_packssdw128((__v4si)__a, (__v4si)__b);
}
-/// \brief Converts 16-bit signed integers from both 128-bit integer vector
+/// Converts 16-bit signed integers from both 128-bit integer vector
/// operands into 8-bit unsigned integers, and packs the results into the
/// destination. Values greater than 0xFF are saturated to 0xFF. Values less
/// than 0x00 are saturated to 0x00.
@@ -4283,7 +4247,7 @@ _mm_packus_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_packuswb128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Extracts 16 bits from a 128-bit integer vector of [8 x i16], using
+/// Extracts 16 bits from a 128-bit integer vector of [8 x i16], using
/// the immediate-value parameter as a selector.
///
/// \headerfile <x86intrin.h>
@@ -4305,14 +4269,11 @@ _mm_packus_epi16(__m128i __a, __m128i __b)
/// 111: assign values from bits [127:112] of \a __a.
/// \returns An integer, whose lower 16 bits are selected from the 128-bit
/// integer vector parameter and the remaining bits are assigned zeros.
-static __inline__ int __DEFAULT_FN_ATTRS
-_mm_extract_epi16(__m128i __a, int __imm)
-{
- __v8hi __b = (__v8hi)__a;
- return (unsigned short)__b[__imm & 7];
-}
+#define _mm_extract_epi16(a, imm) \
+ (int)(unsigned short)__builtin_ia32_vec_ext_v8hi((__v8hi)(__m128i)(a), \
+ (int)(imm))
-/// \brief Constructs a 128-bit integer vector by first making a copy of the
+/// Constructs a 128-bit integer vector by first making a copy of the
/// 128-bit integer vector parameter, and then inserting the lower 16 bits
/// of an integer parameter into an offset specified by the immediate-value
/// parameter.
@@ -4332,15 +4293,11 @@ _mm_extract_epi16(__m128i __a, int __imm)
/// An immediate value specifying the bit offset in the result at which the
/// lower 16 bits of \a __b are written.
/// \returns A 128-bit integer vector containing the constructed values.
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_insert_epi16(__m128i __a, int __b, int __imm)
-{
- __v8hi __c = (__v8hi)__a;
- __c[__imm & 7] = __b;
- return (__m128i)__c;
-}
+#define _mm_insert_epi16(a, b, imm) \
+ (__m128i)__builtin_ia32_vec_set_v8hi((__v8hi)(__m128i)(a), (int)(b), \
+ (int)(imm))
-/// \brief Copies the values of the most significant bits from each 8-bit
+/// Copies the values of the most significant bits from each 8-bit
/// element in a 128-bit integer vector of [16 x i8] to create a 16-bit mask
/// value, zero-extends the value, and writes it to the destination.
///
@@ -4358,7 +4315,7 @@ _mm_movemask_epi8(__m128i __a)
return __builtin_ia32_pmovmskb128((__v16qi)__a);
}
-/// \brief Constructs a 128-bit integer vector by shuffling four 32-bit
+/// Constructs a 128-bit integer vector by shuffling four 32-bit
/// elements of a 128-bit integer vector parameter, using the immediate-value
/// parameter as a specifier.
///
@@ -4386,13 +4343,10 @@ _mm_movemask_epi8(__m128i __a)
/// 10: assign values from bits [95:64] of \a a. \n
/// 11: assign values from bits [127:96] of \a a.
/// \returns A 128-bit integer vector containing the shuffled values.
-#define _mm_shuffle_epi32(a, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v4si)(__m128i)(a), \
- (__v4si)_mm_undefined_si128(), \
- ((imm) >> 0) & 0x3, ((imm) >> 2) & 0x3, \
- ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); })
+#define _mm_shuffle_epi32(a, imm) \
+ (__m128i)__builtin_ia32_pshufd((__v4si)(__m128i)(a), (int)(imm))
-/// \brief Constructs a 128-bit integer vector by shuffling four lower 16-bit
+/// Constructs a 128-bit integer vector by shuffling four lower 16-bit
/// elements of a 128-bit integer vector of [8 x i16], using the immediate
/// value parameter as a specifier.
///
@@ -4419,14 +4373,10 @@ _mm_movemask_epi8(__m128i __a)
/// 10: assign values from bits [47:32] of \a a. \n
/// 11: assign values from bits [63:48] of \a a. \n
/// \returns A 128-bit integer vector containing the shuffled values.
-#define _mm_shufflelo_epi16(a, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \
- (__v8hi)_mm_undefined_si128(), \
- ((imm) >> 0) & 0x3, ((imm) >> 2) & 0x3, \
- ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3, \
- 4, 5, 6, 7); })
-
-/// \brief Constructs a 128-bit integer vector by shuffling four upper 16-bit
+#define _mm_shufflelo_epi16(a, imm) \
+ (__m128i)__builtin_ia32_pshuflw((__v8hi)(__m128i)(a), (int)(imm))
+
+/// Constructs a 128-bit integer vector by shuffling four upper 16-bit
/// elements of a 128-bit integer vector of [8 x i16], using the immediate
/// value parameter as a specifier.
///
@@ -4453,16 +4403,10 @@ _mm_movemask_epi8(__m128i __a)
/// 10: assign values from bits [111:96] of \a a. \n
/// 11: assign values from bits [127:112] of \a a. \n
/// \returns A 128-bit integer vector containing the shuffled values.
-#define _mm_shufflehi_epi16(a, imm) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \
- (__v8hi)_mm_undefined_si128(), \
- 0, 1, 2, 3, \
- 4 + (((imm) >> 0) & 0x3), \
- 4 + (((imm) >> 2) & 0x3), \
- 4 + (((imm) >> 4) & 0x3), \
- 4 + (((imm) >> 6) & 0x3)); })
-
-/// \brief Unpacks the high-order (index 8-15) values from two 128-bit vectors
+#define _mm_shufflehi_epi16(a, imm) \
+ (__m128i)__builtin_ia32_pshufhw((__v8hi)(__m128i)(a), (int)(imm))
+
+/// Unpacks the high-order (index 8-15) values from two 128-bit vectors
/// of [16 x i8] and interleaves them into a 128-bit vector of [16 x i8].
///
/// \headerfile <x86intrin.h>
@@ -4497,7 +4441,7 @@ _mm_unpackhi_epi8(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v16qi)__a, (__v16qi)__b, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15);
}
-/// \brief Unpacks the high-order (index 4-7) values from two 128-bit vectors of
+/// Unpacks the high-order (index 4-7) values from two 128-bit vectors of
/// [8 x i16] and interleaves them into a 128-bit vector of [8 x i16].
///
/// \headerfile <x86intrin.h>
@@ -4524,7 +4468,7 @@ _mm_unpackhi_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi)__b, 4, 8+4, 5, 8+5, 6, 8+6, 7, 8+7);
}
-/// \brief Unpacks the high-order (index 2,3) values from two 128-bit vectors of
+/// Unpacks the high-order (index 2,3) values from two 128-bit vectors of
/// [4 x i32] and interleaves them into a 128-bit vector of [4 x i32].
///
/// \headerfile <x86intrin.h>
@@ -4547,7 +4491,7 @@ _mm_unpackhi_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b, 2, 4+2, 3, 4+3);
}
-/// \brief Unpacks the high-order 64-bit elements from two 128-bit vectors of
+/// Unpacks the high-order 64-bit elements from two 128-bit vectors of
/// [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
///
/// \headerfile <x86intrin.h>
@@ -4568,7 +4512,7 @@ _mm_unpackhi_epi64(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v2di)__a, (__v2di)__b, 1, 2+1);
}
-/// \brief Unpacks the low-order (index 0-7) values from two 128-bit vectors of
+/// Unpacks the low-order (index 0-7) values from two 128-bit vectors of
/// [16 x i8] and interleaves them into a 128-bit vector of [16 x i8].
///
/// \headerfile <x86intrin.h>
@@ -4603,7 +4547,7 @@ _mm_unpacklo_epi8(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v16qi)__a, (__v16qi)__b, 0, 16+0, 1, 16+1, 2, 16+2, 3, 16+3, 4, 16+4, 5, 16+5, 6, 16+6, 7, 16+7);
}
-/// \brief Unpacks the low-order (index 0-3) values from each of the two 128-bit
+/// Unpacks the low-order (index 0-3) values from each of the two 128-bit
/// vectors of [8 x i16] and interleaves them into a 128-bit vector of
/// [8 x i16].
///
@@ -4631,7 +4575,7 @@ _mm_unpacklo_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi)__b, 0, 8+0, 1, 8+1, 2, 8+2, 3, 8+3);
}
-/// \brief Unpacks the low-order (index 0,1) values from two 128-bit vectors of
+/// Unpacks the low-order (index 0,1) values from two 128-bit vectors of
/// [4 x i32] and interleaves them into a 128-bit vector of [4 x i32].
///
/// \headerfile <x86intrin.h>
@@ -4654,7 +4598,7 @@ _mm_unpacklo_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b, 0, 4+0, 1, 4+1);
}
-/// \brief Unpacks the low-order 64-bit elements from two 128-bit vectors of
+/// Unpacks the low-order 64-bit elements from two 128-bit vectors of
/// [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
///
/// \headerfile <x86intrin.h>
@@ -4675,7 +4619,7 @@ _mm_unpacklo_epi64(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v2di)__a, (__v2di)__b, 0, 2+0);
}
-/// \brief Returns the lower 64 bits of a 128-bit integer vector as a 64-bit
+/// Returns the lower 64 bits of a 128-bit integer vector as a 64-bit
/// integer.
///
/// \headerfile <x86intrin.h>
@@ -4692,7 +4636,7 @@ _mm_movepi64_pi64(__m128i __a)
return (__m64)__a[0];
}
-/// \brief Moves the 64-bit operand to a 128-bit integer vector, zeroing the
+/// Moves the 64-bit operand to a 128-bit integer vector, zeroing the
/// upper bits.
///
/// \headerfile <x86intrin.h>
@@ -4706,10 +4650,10 @@ _mm_movepi64_pi64(__m128i __a)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_movpi64_epi64(__m64 __a)
{
- return (__m128i){ (long long)__a, 0 };
+ return __extension__ (__m128i)(__v2di){ (long long)__a, 0 };
}
-/// \brief Moves the lower 64 bits of a 128-bit integer vector to a 128-bit
+/// Moves the lower 64 bits of a 128-bit integer vector to a 128-bit
/// integer vector, zeroing the upper bits.
///
/// \headerfile <x86intrin.h>
@@ -4724,10 +4668,10 @@ _mm_movpi64_epi64(__m64 __a)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_move_epi64(__m128i __a)
{
- return __builtin_shufflevector((__v2di)__a, (__m128i){ 0 }, 0, 2);
+ return __builtin_shufflevector((__v2di)__a, _mm_setzero_si128(), 0, 2);
}
-/// \brief Unpacks the high-order 64-bit elements from two 128-bit vectors of
+/// Unpacks the high-order 64-bit elements from two 128-bit vectors of
/// [2 x double] and interleaves them into a 128-bit vector of [2 x
/// double].
///
@@ -4748,7 +4692,7 @@ _mm_unpackhi_pd(__m128d __a, __m128d __b)
return __builtin_shufflevector((__v2df)__a, (__v2df)__b, 1, 2+1);
}
-/// \brief Unpacks the low-order 64-bit elements from two 128-bit vectors
+/// Unpacks the low-order 64-bit elements from two 128-bit vectors
/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
/// double].
///
@@ -4769,7 +4713,7 @@ _mm_unpacklo_pd(__m128d __a, __m128d __b)
return __builtin_shufflevector((__v2df)__a, (__v2df)__b, 0, 2+0);
}
-/// \brief Extracts the sign bits of the double-precision values in the 128-bit
+/// Extracts the sign bits of the double-precision values in the 128-bit
/// vector of [2 x double], zero-extends the value, and writes it to the
/// low-order bits of the destination.
///
@@ -4789,7 +4733,7 @@ _mm_movemask_pd(__m128d __a)
}
-/// \brief Constructs a 128-bit floating-point vector of [2 x double] from two
+/// Constructs a 128-bit floating-point vector of [2 x double] from two
/// 128-bit vector parameters of [2 x double], using the immediate-value
/// parameter as a specifier.
///
@@ -4813,12 +4757,11 @@ _mm_movemask_pd(__m128d __a)
/// Bit[1] = 0: lower element of \a b copied to upper element of result. \n
/// Bit[1] = 1: upper element of \a b copied to upper element of result. \n
/// \returns A 128-bit vector of [2 x double] containing the shuffled values.
-#define _mm_shuffle_pd(a, b, i) __extension__ ({ \
- (__m128d)__builtin_shufflevector((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \
- 0 + (((i) >> 0) & 0x1), \
- 2 + (((i) >> 1) & 0x1)); })
+#define _mm_shuffle_pd(a, b, i) \
+ (__m128d)__builtin_ia32_shufpd((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \
+ (int)(i))
-/// \brief Casts a 128-bit floating-point vector of [2 x double] into a 128-bit
+/// Casts a 128-bit floating-point vector of [2 x double] into a 128-bit
/// floating-point vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -4835,7 +4778,7 @@ _mm_castpd_ps(__m128d __a)
return (__m128)__a;
}
-/// \brief Casts a 128-bit floating-point vector of [2 x double] into a 128-bit
+/// Casts a 128-bit floating-point vector of [2 x double] into a 128-bit
/// integer vector.
///
/// \headerfile <x86intrin.h>
@@ -4852,7 +4795,7 @@ _mm_castpd_si128(__m128d __a)
return (__m128i)__a;
}
-/// \brief Casts a 128-bit floating-point vector of [4 x float] into a 128-bit
+/// Casts a 128-bit floating-point vector of [4 x float] into a 128-bit
/// floating-point vector of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -4869,7 +4812,7 @@ _mm_castps_pd(__m128 __a)
return (__m128d)__a;
}
-/// \brief Casts a 128-bit floating-point vector of [4 x float] into a 128-bit
+/// Casts a 128-bit floating-point vector of [4 x float] into a 128-bit
/// integer vector.
///
/// \headerfile <x86intrin.h>
@@ -4886,7 +4829,7 @@ _mm_castps_si128(__m128 __a)
return (__m128i)__a;
}
-/// \brief Casts a 128-bit integer vector into a 128-bit floating-point vector
+/// Casts a 128-bit integer vector into a 128-bit floating-point vector
/// of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -4903,7 +4846,7 @@ _mm_castsi128_ps(__m128i __a)
return (__m128)__a;
}
-/// \brief Casts a 128-bit integer vector into a 128-bit floating-point vector
+/// Casts a 128-bit integer vector into a 128-bit floating-point vector
/// of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -4924,7 +4867,7 @@ _mm_castsi128_pd(__m128i __a)
extern "C" {
#endif
-/// \brief Indicates that a spin loop is being executed for the purposes of
+/// Indicates that a spin loop is being executed for the purposes of
/// optimizing power consumption during the loop.
///
/// \headerfile <x86intrin.h>
@@ -4937,6 +4880,7 @@ void _mm_pause(void);
} // extern "C"
#endif
#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS_MMX
#define _MM_SHUFFLE2(x, y) (((x) << 1) | (y))
diff --git a/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h b/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
index b796cc84316f..3d35f28eb356 100644
--- a/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
@@ -21,18 +21,25 @@
*===-----------------------------------------------------------------------===
*/
-#if !defined __X86INTRIN_H && !defined __EMMINTRIN_H && !defined __IMMINTRIN_H
-#error "Never use <f16cintrin.h> directly; include <emmintrin.h> instead."
+#if !defined __IMMINTRIN_H
+#error "Never use <f16cintrin.h> directly; include <immintrin.h> instead."
#endif
#ifndef __F16CINTRIN_H
#define __F16CINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS \
- __attribute__((__always_inline__, __nodebug__, __target__("f16c")))
+#define __DEFAULT_FN_ATTRS128 \
+ __attribute__((__always_inline__, __nodebug__, __target__("f16c"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 \
+ __attribute__((__always_inline__, __nodebug__, __target__("f16c"), __min_vector_width__(256)))
-/// \brief Converts a 16-bit half-precision float value into a 32-bit float
+/* NOTE: Intel documents the 128-bit versions of these as being in emmintrin.h,
+ * but that's because icc can emulate these without f16c using a library call.
+ * Since we don't do that let's leave these in f16cintrin.h.
+ */
+
+/// Converts a 16-bit half-precision float value into a 32-bit float
/// value.
///
/// \headerfile <x86intrin.h>
@@ -42,7 +49,7 @@
/// \param __a
/// A 16-bit half-precision float value.
/// \returns The converted 32-bit float value.
-static __inline float __DEFAULT_FN_ATTRS
+static __inline float __DEFAULT_FN_ATTRS128
_cvtsh_ss(unsigned short __a)
{
__v8hi v = {(short)__a, 0, 0, 0, 0, 0, 0, 0};
@@ -50,7 +57,7 @@ _cvtsh_ss(unsigned short __a)
return r[0];
}
-/// \brief Converts a 32-bit single-precision float value to a 16-bit
+/// Converts a 32-bit single-precision float value to a 16-bit
/// half-precision float value.
///
/// \headerfile <x86intrin.h>
@@ -72,11 +79,11 @@ _cvtsh_ss(unsigned short __a)
/// 011: Truncate \n
/// 1XX: Use MXCSR.RC for rounding
/// \returns The converted 16-bit half-precision float value.
-#define _cvtss_sh(a, imm) __extension__ ({ \
+#define _cvtss_sh(a, imm) \
(unsigned short)(((__v8hi)__builtin_ia32_vcvtps2ph((__v4sf){a, 0, 0, 0}, \
- (imm)))[0]); })
+ (imm)))[0])
-/// \brief Converts a 128-bit vector containing 32-bit float values into a
+/// Converts a 128-bit vector containing 32-bit float values into a
/// 128-bit vector containing 16-bit half-precision float values.
///
/// \headerfile <x86intrin.h>
@@ -99,10 +106,10 @@ _cvtsh_ss(unsigned short __a)
/// \returns A 128-bit vector containing converted 16-bit half-precision float
/// values. The lower 64 bits are used to store the converted 16-bit
/// half-precision floating-point values.
-#define _mm_cvtps_ph(a, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_vcvtps2ph((__v4sf)(__m128)(a), (imm)); })
+#define _mm_cvtps_ph(a, imm) \
+ (__m128i)__builtin_ia32_vcvtps2ph((__v4sf)(__m128)(a), (imm))
-/// \brief Converts a 128-bit vector containing 16-bit half-precision float
+/// Converts a 128-bit vector containing 16-bit half-precision float
/// values into a 128-bit vector containing 32-bit float values.
///
/// \headerfile <x86intrin.h>
@@ -113,12 +120,57 @@ _cvtsh_ss(unsigned short __a)
/// A 128-bit vector containing 16-bit half-precision float values. The lower
/// 64 bits are used in the conversion.
/// \returns A 128-bit vector of [4 x float] containing converted float values.
-static __inline __m128 __DEFAULT_FN_ATTRS
+static __inline __m128 __DEFAULT_FN_ATTRS128
_mm_cvtph_ps(__m128i __a)
{
return (__m128)__builtin_ia32_vcvtph2ps((__v8hi)__a);
}
-#undef __DEFAULT_FN_ATTRS
+/// Converts a 256-bit vector of [8 x float] into a 128-bit vector
+/// containing 16-bit half-precision float values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm256_cvtps_ph(__m256 a, const int imm);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VCVTPS2PH </c> instruction.
+///
+/// \param a
+/// A 256-bit vector containing 32-bit single-precision float values to be
+/// converted to 16-bit half-precision float values.
+/// \param imm
+/// An immediate value controlling rounding using bits [2:0]: \n
+/// 000: Nearest \n
+/// 001: Down \n
+/// 010: Up \n
+/// 011: Truncate \n
+/// 1XX: Use MXCSR.RC for rounding
+/// \returns A 128-bit vector containing the converted 16-bit half-precision
+/// float values.
+#define _mm256_cvtps_ph(a, imm) \
+ (__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)(__m256)(a), (imm))
+
+/// Converts a 128-bit vector containing 16-bit half-precision float
+/// values into a 256-bit vector of [8 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTPH2PS </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector containing 16-bit half-precision float values to be
+/// converted to 32-bit single-precision float values.
+/// \returns A vector of [8 x float] containing the converted 32-bit
+/// single-precision float values.
+static __inline __m256 __DEFAULT_FN_ATTRS256
+_mm256_cvtph_ps(__m128i __a)
+{
+ return (__m256)__builtin_ia32_vcvtph2ps256((__v8hi)__a);
+}
+
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif /* __F16CINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
index 962b1a60a258..7bae2f4a3155 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
@@ -31,200 +31,202 @@
#include <pmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fma4")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("fma4"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("fma4"), __min_vector_width__(256)))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_macc_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_macc_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_macc_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_macc_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_msub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_msub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_msub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_msub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_nmacc_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_nmacc_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_nmacc_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_nmacc_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd(-(__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_nmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_nmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_nmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_nmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maddsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maddsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_msubadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_msubadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_macc_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_macc_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_msub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_msub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_nmacc_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_nmacc_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, (__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_nmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_nmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maddsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maddsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_msubadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_msubadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif /* __FMA4INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
index 478a0ac81cf2..094d13afea09 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
@@ -1,4 +1,4 @@
-/*===---- fma4intrin.h - FMA4 intrinsics -----------------------------------===
+/*===---- fmaintrin.h - FMA 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
@@ -29,200 +29,202 @@
#define __FMAINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fma")))
+#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("fma"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("fma"), __min_vector_width__(256)))
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fmadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fmadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fmadd_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fmadd_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fnmadd_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, -(__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fnmadd_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, -(__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fnmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, -(__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fnmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, -(__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
-static __inline__ __m128d __DEFAULT_FN_ATTRS
+static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_fmadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_fmadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_fmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_fmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, (__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif /* __FMAINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h b/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
index 786081ca8eab..704b5ad60aa5 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
@@ -30,7 +30,7 @@
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fxsr")))
-/// \brief Saves the XMM, MMX, MXCSR and x87 FPU registers into a 512-byte
+/// Saves the XMM, MMX, MXCSR and x87 FPU registers into a 512-byte
/// memory region pointed to by the input parameter \a __p.
///
/// \headerfile <x86intrin.h>
@@ -43,10 +43,10 @@
static __inline__ void __DEFAULT_FN_ATTRS
_fxsave(void *__p)
{
- return __builtin_ia32_fxsave(__p);
+ __builtin_ia32_fxsave(__p);
}
-/// \brief Restores the XMM, MMX, MXCSR and x87 FPU registers from the 512-byte
+/// Restores the XMM, MMX, MXCSR and x87 FPU registers from the 512-byte
/// memory region pointed to by the input parameter \a __p. The contents of
/// this memory region should have been written to by a previous \c _fxsave
/// or \c _fxsave64 intrinsic.
@@ -61,11 +61,11 @@ _fxsave(void *__p)
static __inline__ void __DEFAULT_FN_ATTRS
_fxrstor(void *__p)
{
- return __builtin_ia32_fxrstor(__p);
+ __builtin_ia32_fxrstor(__p);
}
#ifdef __x86_64__
-/// \brief Saves the XMM, MMX, MXCSR and x87 FPU registers into a 512-byte
+/// Saves the XMM, MMX, MXCSR and x87 FPU registers into a 512-byte
/// memory region pointed to by the input parameter \a __p.
///
/// \headerfile <x86intrin.h>
@@ -78,10 +78,10 @@ _fxrstor(void *__p)
static __inline__ void __DEFAULT_FN_ATTRS
_fxsave64(void *__p)
{
- return __builtin_ia32_fxsave64(__p);
+ __builtin_ia32_fxsave64(__p);
}
-/// \brief Restores the XMM, MMX, MXCSR and x87 FPU registers from the 512-byte
+/// Restores the XMM, MMX, MXCSR and x87 FPU registers from the 512-byte
/// memory region pointed to by the input parameter \a __p. The contents of
/// this memory region should have been written to by a previous \c _fxsave
/// or \c _fxsave64 intrinsic.
@@ -96,7 +96,7 @@ _fxsave64(void *__p)
static __inline__ void __DEFAULT_FN_ATTRS
_fxrstor64(void *__p)
{
- return __builtin_ia32_fxrstor64(__p);
+ __builtin_ia32_fxrstor64(__p);
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/gfniintrin.h b/contrib/llvm/tools/clang/lib/Headers/gfniintrin.h
index 20fadccfaaed..804d4f3d068c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/gfniintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/gfniintrin.h
@@ -29,104 +29,108 @@
#define __GFNIINTRIN_H
-#define _mm_gf2p8affineinv_epi64_epi8(A, B, I) __extension__ ({ \
+#define _mm_gf2p8affineinv_epi64_epi8(A, B, I) \
(__m128i)__builtin_ia32_vgf2p8affineinvqb_v16qi((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm_mask_gf2p8affineinv_epi64_epi8(S, U, A, B, I) __extension__ ({ \
+#define _mm_mask_gf2p8affineinv_epi64_epi8(S, U, A, B, I) \
(__m128i)__builtin_ia32_selectb_128((__mmask16)(U), \
(__v16qi)_mm_gf2p8affineinv_epi64_epi8(A, B, I), \
- (__v16qi)(__m128i)(S)); })
+ (__v16qi)(__m128i)(S))
-#define _mm_maskz_gf2p8affineinv_epi64_epi8(U, A, B, I) __extension__ ({ \
+#define _mm_maskz_gf2p8affineinv_epi64_epi8(U, A, B, I) \
(__m128i)_mm_mask_gf2p8affineinv_epi64_epi8((__m128i)_mm_setzero_si128(), \
- U, A, B, I); })
+ U, A, B, I)
-#define _mm256_gf2p8affineinv_epi64_epi8(A, B, I) __extension__ ({ \
+#define _mm256_gf2p8affineinv_epi64_epi8(A, B, I) \
(__m256i)__builtin_ia32_vgf2p8affineinvqb_v32qi((__v32qi)(__m256i)(A), \
(__v32qi)(__m256i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm256_mask_gf2p8affineinv_epi64_epi8(S, U, A, B, I) __extension__ ({ \
+#define _mm256_mask_gf2p8affineinv_epi64_epi8(S, U, A, B, I) \
(__m256i)__builtin_ia32_selectb_256((__mmask32)(U), \
(__v32qi)_mm256_gf2p8affineinv_epi64_epi8(A, B, I), \
- (__v32qi)(__m256i)(S)); })
+ (__v32qi)(__m256i)(S))
-#define _mm256_maskz_gf2p8affineinv_epi64_epi8(U, A, B, I) __extension__ ({ \
+#define _mm256_maskz_gf2p8affineinv_epi64_epi8(U, A, B, I) \
(__m256i)_mm256_mask_gf2p8affineinv_epi64_epi8((__m256i)_mm256_setzero_si256(), \
- U, A, B, I); })
+ U, A, B, I)
-#define _mm512_gf2p8affineinv_epi64_epi8(A, B, I) __extension__ ({ \
+#define _mm512_gf2p8affineinv_epi64_epi8(A, B, I) \
(__m512i)__builtin_ia32_vgf2p8affineinvqb_v64qi((__v64qi)(__m512i)(A), \
(__v64qi)(__m512i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm512_mask_gf2p8affineinv_epi64_epi8(S, U, A, B, I) __extension__ ({ \
+#define _mm512_mask_gf2p8affineinv_epi64_epi8(S, U, A, B, I) \
(__m512i)__builtin_ia32_selectb_512((__mmask64)(U), \
(__v64qi)_mm512_gf2p8affineinv_epi64_epi8(A, B, I), \
- (__v64qi)(__m512i)(S)); })
+ (__v64qi)(__m512i)(S))
-#define _mm512_maskz_gf2p8affineinv_epi64_epi8(U, A, B, I) __extension__ ({ \
- (__m512i)_mm512_mask_gf2p8affineinv_epi64_epi8((__m512i)_mm512_setzero_qi(), \
- U, A, B, I); })
+#define _mm512_maskz_gf2p8affineinv_epi64_epi8(U, A, B, I) \
+ (__m512i)_mm512_mask_gf2p8affineinv_epi64_epi8((__m512i)_mm512_setzero_si512(), \
+ U, A, B, I)
-#define _mm_gf2p8affine_epi64_epi8(A, B, I) __extension__ ({ \
+#define _mm_gf2p8affine_epi64_epi8(A, B, I) \
(__m128i)__builtin_ia32_vgf2p8affineqb_v16qi((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm_mask_gf2p8affine_epi64_epi8(S, U, A, B, I) __extension__ ({ \
+#define _mm_mask_gf2p8affine_epi64_epi8(S, U, A, B, I) \
(__m128i)__builtin_ia32_selectb_128((__mmask16)(U), \
(__v16qi)_mm_gf2p8affine_epi64_epi8(A, B, I), \
- (__v16qi)(__m128i)(S)); })
+ (__v16qi)(__m128i)(S))
-#define _mm_maskz_gf2p8affine_epi64_epi8(U, A, B, I) __extension__ ({ \
+#define _mm_maskz_gf2p8affine_epi64_epi8(U, A, B, I) \
(__m128i)_mm_mask_gf2p8affine_epi64_epi8((__m128i)_mm_setzero_si128(), \
- U, A, B, I); })
+ U, A, B, I)
-#define _mm256_gf2p8affine_epi64_epi8(A, B, I) __extension__ ({ \
+#define _mm256_gf2p8affine_epi64_epi8(A, B, I) \
(__m256i)__builtin_ia32_vgf2p8affineqb_v32qi((__v32qi)(__m256i)(A), \
(__v32qi)(__m256i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm256_mask_gf2p8affine_epi64_epi8(S, U, A, B, I) __extension__ ({ \
+#define _mm256_mask_gf2p8affine_epi64_epi8(S, U, A, B, I) \
(__m256i)__builtin_ia32_selectb_256((__mmask32)(U), \
(__v32qi)_mm256_gf2p8affine_epi64_epi8(A, B, I), \
- (__v32qi)(__m256i)(S)); })
+ (__v32qi)(__m256i)(S))
-#define _mm256_maskz_gf2p8affine_epi64_epi8(U, A, B, I) __extension__ ({ \
+#define _mm256_maskz_gf2p8affine_epi64_epi8(U, A, B, I) \
(__m256i)_mm256_mask_gf2p8affine_epi64_epi8((__m256i)_mm256_setzero_si256(), \
- U, A, B, I); })
+ U, A, B, I)
-#define _mm512_gf2p8affine_epi64_epi8(A, B, I) __extension__ ({ \
+#define _mm512_gf2p8affine_epi64_epi8(A, B, I) \
(__m512i)__builtin_ia32_vgf2p8affineqb_v64qi((__v64qi)(__m512i)(A), \
(__v64qi)(__m512i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm512_mask_gf2p8affine_epi64_epi8(S, U, A, B, I) __extension__ ({ \
+#define _mm512_mask_gf2p8affine_epi64_epi8(S, U, A, B, I) \
(__m512i)__builtin_ia32_selectb_512((__mmask64)(U), \
(__v64qi)_mm512_gf2p8affine_epi64_epi8(A, B, I), \
- (__v64qi)(__m512i)(S)); })
+ (__v64qi)(__m512i)(S))
-#define _mm512_maskz_gf2p8affine_epi64_epi8(U, A, B, I) __extension__ ({ \
- (__m512i)_mm512_mask_gf2p8affine_epi64_epi8((__m512i)_mm512_setzero_qi(), \
- U, A, B, I); })
+#define _mm512_maskz_gf2p8affine_epi64_epi8(U, A, B, I) \
+ (__m512i)_mm512_mask_gf2p8affine_epi64_epi8((__m512i)_mm512_setzero_si512(), \
+ U, A, B, I)
/* Default attributes for simple form (no masking). */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("gfni")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("gfni"), __min_vector_width__(128)))
+
+/* Default attributes for YMM unmasked form. */
+#define __DEFAULT_FN_ATTRS_Y __attribute__((__always_inline__, __nodebug__, __target__("avx,gfni"), __min_vector_width__(256)))
/* Default attributes for ZMM forms. */
-#define __DEFAULT_FN_ATTRS_F __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,gfni")))
+#define __DEFAULT_FN_ATTRS_Z __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,gfni"), __min_vector_width__(512)))
/* Default attributes for VLX forms. */
-#define __DEFAULT_FN_ATTRS_VL __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,avx512vl,gfni")))
+#define __DEFAULT_FN_ATTRS_VL128 __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,avx512vl,gfni"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS_VL256 __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,avx512vl,gfni"), __min_vector_width__(256)))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_gf2p8mul_epi8(__m128i __A, __m128i __B)
@@ -135,7 +139,7 @@ _mm_gf2p8mul_epi8(__m128i __A, __m128i __B)
(__v16qi) __B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS_VL
+static __inline__ __m128i __DEFAULT_FN_ATTRS_VL128
_mm_mask_gf2p8mul_epi8(__m128i __S, __mmask16 __U, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_selectb_128(__U,
@@ -143,21 +147,21 @@ _mm_mask_gf2p8mul_epi8(__m128i __S, __mmask16 __U, __m128i __A, __m128i __B)
(__v16qi) __S);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS_VL
+static __inline__ __m128i __DEFAULT_FN_ATTRS_VL128
_mm_maskz_gf2p8mul_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
return _mm_mask_gf2p8mul_epi8((__m128i)_mm_setzero_si128(),
__U, __A, __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS_Y
_mm256_gf2p8mul_epi8(__m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_vgf2p8mulb_v32qi((__v32qi) __A,
(__v32qi) __B);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS_VL
+static __inline__ __m256i __DEFAULT_FN_ATTRS_VL256
_mm256_mask_gf2p8mul_epi8(__m256i __S, __mmask32 __U, __m256i __A, __m256i __B)
{
return (__m256i) __builtin_ia32_selectb_256(__U,
@@ -165,21 +169,21 @@ _mm256_mask_gf2p8mul_epi8(__m256i __S, __mmask32 __U, __m256i __A, __m256i __B)
(__v32qi) __S);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS_VL
+static __inline__ __m256i __DEFAULT_FN_ATTRS_VL256
_mm256_maskz_gf2p8mul_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
return _mm256_mask_gf2p8mul_epi8((__m256i)_mm256_setzero_si256(),
__U, __A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS_F
+static __inline__ __m512i __DEFAULT_FN_ATTRS_Z
_mm512_gf2p8mul_epi8(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_vgf2p8mulb_v64qi((__v64qi) __A,
(__v64qi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS_F
+static __inline__ __m512i __DEFAULT_FN_ATTRS_Z
_mm512_mask_gf2p8mul_epi8(__m512i __S, __mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_selectb_512(__U,
@@ -187,16 +191,18 @@ _mm512_mask_gf2p8mul_epi8(__m512i __S, __mmask64 __U, __m512i __A, __m512i __B)
(__v64qi) __S);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS_F
+static __inline__ __m512i __DEFAULT_FN_ATTRS_Z
_mm512_maskz_gf2p8mul_epi8(__mmask64 __U, __m512i __A, __m512i __B)
{
- return _mm512_mask_gf2p8mul_epi8((__m512i)_mm512_setzero_qi(),
+ return _mm512_mask_gf2p8mul_epi8((__m512i)_mm512_setzero_si512(),
__U, __A, __B);
}
#undef __DEFAULT_FN_ATTRS
-#undef __DEFAULT_FN_ATTRS_F
-#undef __DEFAULT_FN_ATTRS_VL
+#undef __DEFAULT_FN_ATTRS_Y
+#undef __DEFAULT_FN_ATTRS_Z
+#undef __DEFAULT_FN_ATTRS_VL128
+#undef __DEFAULT_FN_ATTRS_VL256
-#endif // __GFNIINTRIN_H
+#endif /* __GFNIINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h b/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
index 28f7d025bb30..049dbd61df75 100644
--- a/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
@@ -214,7 +214,7 @@ __TM_failure_code(void* const __TM_buff)
/* These intrinsics are being made available for compatibility with
the IBM XL compiler. For documentation please see the "z/OS XL
- C/C++ Programming Guide" publically available on the web. */
+ C/C++ Programming Guide" publicly available on the web. */
static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_simple_begin ()
diff --git a/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h b/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h
index 4928300103ad..f8972e3053a3 100644
--- a/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h
@@ -70,4 +70,9 @@ __rdtscp(unsigned int *__A) {
#define _rdpmc(A) __rdpmc(A)
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_wbinvd(void) {
+ __builtin_ia32_wbinvd();
+}
+
#endif /* __IA32INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/immintrin.h b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
index d3421dc86c99..e7bfbf964d56 100644
--- a/contrib/llvm/tools/clang/lib/Headers/immintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
@@ -68,55 +68,11 @@
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX2__)
#include <avx2intrin.h>
+#endif
-/* The 256-bit versions of functions in f16cintrin.h.
- Intel documents these as being in immintrin.h, and
- they depend on typedefs from avxintrin.h. */
-
-/// \brief Converts a 256-bit vector of [8 x float] into a 128-bit vector
-/// containing 16-bit half-precision float values.
-///
-/// \headerfile <x86intrin.h>
-///
-/// \code
-/// __m128i _mm256_cvtps_ph(__m256 a, const int imm);
-/// \endcode
-///
-/// This intrinsic corresponds to the <c> VCVTPS2PH </c> instruction.
-///
-/// \param a
-/// A 256-bit vector containing 32-bit single-precision float values to be
-/// converted to 16-bit half-precision float values.
-/// \param imm
-/// An immediate value controlling rounding using bits [2:0]: \n
-/// 000: Nearest \n
-/// 001: Down \n
-/// 010: Up \n
-/// 011: Truncate \n
-/// 1XX: Use MXCSR.RC for rounding
-/// \returns A 128-bit vector containing the converted 16-bit half-precision
-/// float values.
-#define _mm256_cvtps_ph(a, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)(__m256)(a), (imm)); })
-
-/// \brief Converts a 128-bit vector containing 16-bit half-precision float
-/// values into a 256-bit vector of [8 x float].
-///
-/// \headerfile <x86intrin.h>
-///
-/// This intrinsic corresponds to the <c> VCVTPH2PS </c> instruction.
-///
-/// \param __a
-/// A 128-bit vector containing 16-bit half-precision float values to be
-/// converted to 32-bit single-precision float values.
-/// \returns A vector of [8 x float] containing the converted 32-bit
-/// single-precision float values.
-static __inline __m256 __attribute__((__always_inline__, __nodebug__, __target__("f16c")))
-_mm256_cvtph_ps(__m128i __a)
-{
- return (__m256)__builtin_ia32_vcvtph2ps256((__v8hi)__a);
-}
-#endif /* __AVX2__ */
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__F16C__)
+#include <f16cintrin.h>
+#endif
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__VPCLMULQDQ__)
#include <vpclmulqdqintrin.h>
@@ -134,6 +90,10 @@ _mm256_cvtph_ps(__m128i __a)
#include <lzcntintrin.h>
#endif
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__POPCNT__)
+#include <popcntintrin.h>
+#endif
+
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__FMA__)
#include <fmaintrin.h>
#endif
@@ -247,6 +207,18 @@ _mm256_cvtph_ps(__m128i __a)
#include <gfniintrin.h>
#endif
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__RDPID__)
+/// Returns the value of the IA32_TSC_AUX MSR (0xc0000103).
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> RDPID </c> instruction.
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__, __target__("rdpid")))
+_rdpid_u32(void) {
+ return __builtin_ia32_rdpid();
+}
+#endif // __RDPID__
+
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__RDRND__)
static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("rdrnd")))
_rdrand16_step(unsigned short *__p)
@@ -310,25 +282,25 @@ _readgsbase_u64(void)
static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writefsbase_u32(unsigned int __V)
{
- return __builtin_ia32_wrfsbase32(__V);
+ __builtin_ia32_wrfsbase32(__V);
}
static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writefsbase_u64(unsigned long long __V)
{
- return __builtin_ia32_wrfsbase64(__V);
+ __builtin_ia32_wrfsbase64(__V);
}
static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writegsbase_u32(unsigned int __V)
{
- return __builtin_ia32_wrgsbase32(__V);
+ __builtin_ia32_wrgsbase32(__V);
}
static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writegsbase_u64(unsigned long long __V)
{
- return __builtin_ia32_wrgsbase64(__V);
+ __builtin_ia32_wrgsbase64(__V);
}
#endif
@@ -371,4 +343,125 @@ _writegsbase_u64(unsigned long long __V)
* whereas others are also available at all times. */
#include <adxintrin.h>
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__RDSEED__)
+#include <rdseedintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__WBNOINVD__)
+#include <wbnoinvdintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__CLDEMOTE__)
+#include <cldemoteintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__WAITPKG__)
+#include <waitpkgintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || \
+ defined(__MOVDIRI__) || defined(__MOVDIR64B__)
+#include <movdirintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__PCONFIG__)
+#include <pconfigintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__SGX__)
+#include <sgxintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__PTWRITE__)
+#include <ptwriteintrin.h>
+#endif
+
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__INVPCID__)
+#include <invpcidintrin.h>
+#endif
+
+#ifdef _MSC_VER
+/* Define the default attributes for these intrinsics */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*----------------------------------------------------------------------------*\
+|* Interlocked Exchange HLE
+\*----------------------------------------------------------------------------*/
+#if defined(__i386__) || defined(__x86_64__)
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchange_HLEAcquire(long volatile *_Target, long _Value) {
+ __asm__ __volatile__(".byte 0xf2 ; lock ; xchg %0, %1"
+ : "+r" (_Value), "+m" (*_Target) :: "memory");
+ return _Value;
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchange_HLERelease(long volatile *_Target, long _Value) {
+ __asm__ __volatile__(".byte 0xf3 ; lock ; xchg %0, %1"
+ : "+r" (_Value), "+m" (*_Target) :: "memory");
+ return _Value;
+}
+#endif
+#if defined(__x86_64__)
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedExchange64_HLEAcquire(__int64 volatile *_Target, __int64 _Value) {
+ __asm__ __volatile__(".byte 0xf2 ; lock ; xchg %0, %1"
+ : "+r" (_Value), "+m" (*_Target) :: "memory");
+ return _Value;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedExchange64_HLERelease(__int64 volatile *_Target, __int64 _Value) {
+ __asm__ __volatile__(".byte 0xf3 ; lock ; xchg %0, %1"
+ : "+r" (_Value), "+m" (*_Target) :: "memory");
+ return _Value;
+}
+#endif
+/*----------------------------------------------------------------------------*\
+|* Interlocked Compare Exchange HLE
+\*----------------------------------------------------------------------------*/
+#if defined(__i386__) || defined(__x86_64__)
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange_HLEAcquire(long volatile *_Destination,
+ long _Exchange, long _Comparand) {
+ __asm__ __volatile__(".byte 0xf2 ; lock ; cmpxchg %2, %1"
+ : "+a" (_Comparand), "+m" (*_Destination)
+ : "r" (_Exchange) : "memory");
+ return _Comparand;
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange_HLERelease(long volatile *_Destination,
+ long _Exchange, long _Comparand) {
+ __asm__ __volatile__(".byte 0xf3 ; lock ; cmpxchg %2, %1"
+ : "+a" (_Comparand), "+m" (*_Destination)
+ : "r" (_Exchange) : "memory");
+ return _Comparand;
+}
+#endif
+#if defined(__x86_64__)
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange64_HLEAcquire(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand) {
+ __asm__ __volatile__(".byte 0xf2 ; lock ; cmpxchg %2, %1"
+ : "+a" (_Comparand), "+m" (*_Destination)
+ : "r" (_Exchange) : "memory");
+ return _Comparand;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange64_HLERelease(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand) {
+ __asm__ __volatile__(".byte 0xf3 ; lock ; cmpxchg %2, %1"
+ : "+a" (_Comparand), "+m" (*_Destination)
+ : "r" (_Exchange) : "memory");
+ return _Comparand;
+}
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif /* _MSC_VER */
+
#endif /* __IMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/intrin.h b/contrib/llvm/tools/clang/lib/Headers/intrin.h
index b30aa215a452..91914214e299 100644
--- a/contrib/llvm/tools/clang/lib/Headers/intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/intrin.h
@@ -38,7 +38,7 @@
#include <armintr.h>
#endif
-#if defined(_M_ARM64)
+#if defined(__aarch64__)
#include <arm64intr.h>
#endif
@@ -83,6 +83,7 @@ void __incfsdword(unsigned long);
void __incfsword(unsigned long);
unsigned long __indword(unsigned short);
void __indwordstring(unsigned short, unsigned long *, unsigned long);
+void __int2c(void);
void __invlpg(void *);
unsigned short __inword(unsigned short);
void __inwordstring(unsigned short, unsigned short *, unsigned long);
@@ -140,6 +141,7 @@ void __svm_stgi(void);
void __svm_vmload(size_t);
void __svm_vmrun(size_t);
void __svm_vmsave(size_t);
+void __ud2(void);
unsigned __int64 __ull_rshift(unsigned __int64, int);
void __vmx_off(void);
void __vmx_vmptrst(unsigned __int64 *);
@@ -161,25 +163,15 @@ static __inline__
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
static __inline__
unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
-static __inline__
unsigned char _bittest(long const *, long);
-static __inline__
unsigned char _bittestandcomplement(long *, long);
-static __inline__
unsigned char _bittestandreset(long *, long);
-static __inline__
unsigned char _bittestandset(long *, long);
void __cdecl _disable(void);
void __cdecl _enable(void);
long _InterlockedAddLargeStatistic(__int64 volatile *_Addend, long _Value);
unsigned char _interlockedbittestandreset(long volatile *, long);
unsigned char _interlockedbittestandset(long volatile *, long);
-long _InterlockedCompareExchange_HLEAcquire(long volatile *, long, long);
-long _InterlockedCompareExchange_HLERelease(long volatile *, long, long);
-__int64 _InterlockedcompareExchange64_HLEAcquire(__int64 volatile *, __int64,
- __int64);
-__int64 _InterlockedCompareExchange64_HLERelease(__int64 volatile *, __int64,
- __int64);
void *_InterlockedCompareExchangePointer_HLEAcquire(void *volatile *, void *,
void *);
void *_InterlockedCompareExchangePointer_HLERelease(void *volatile *, void *,
@@ -256,24 +248,15 @@ void __writegsbyte(unsigned long, unsigned char);
void __writegsdword(unsigned long, unsigned long);
void __writegsqword(unsigned long, unsigned __int64);
void __writegsword(unsigned long, unsigned short);
-static __inline__
-unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
-static __inline__
-unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
-static __inline__
unsigned char _bittest64(__int64 const *, __int64);
-static __inline__
unsigned char _bittestandcomplement64(__int64 *, __int64);
-static __inline__
unsigned char _bittestandreset64(__int64 *, __int64);
-static __inline__
unsigned char _bittestandset64(__int64 *, __int64);
long _InterlockedAnd_np(long volatile *_Value, long _Mask);
short _InterlockedAnd16_np(short volatile *_Value, short _Mask);
__int64 _InterlockedAnd64_np(__int64 volatile *_Value, __int64 _Mask);
char _InterlockedAnd8_np(char volatile *_Value, char _Mask);
unsigned char _interlockedbittestandreset64(__int64 volatile *, __int64);
-static __inline__
unsigned char _interlockedbittestandset64(__int64 volatile *, __int64);
long _InterlockedCompareExchange_np(long volatile *_Destination, long _Exchange,
long _Comparand);
@@ -287,10 +270,6 @@ unsigned char _InterlockedCompareExchange128_np(__int64 volatile *_Destination,
__int64 *_ComparandResult);
short _InterlockedCompareExchange16_np(short volatile *_Destination,
short _Exchange, short _Comparand);
-__int64 _InterlockedCompareExchange64_HLEAcquire(__int64 volatile *, __int64,
- __int64);
-__int64 _InterlockedCompareExchange64_HLERelease(__int64 volatile *, __int64,
- __int64);
__int64 _InterlockedCompareExchange64_np(__int64 volatile *_Destination,
__int64 _Exchange, __int64 _Comparand);
void *_InterlockedCompareExchangePointer_np(void *volatile *_Destination,
@@ -320,7 +299,12 @@ unsigned __int64 _umul128(unsigned __int64,
#endif /* __x86_64__ */
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+
+static __inline__
+unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
+static __inline__
+unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
static __inline__
__int64 _InterlockedDecrement64(__int64 volatile *_Addend);
@@ -342,78 +326,6 @@ __int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask);
#endif
/*----------------------------------------------------------------------------*\
-|* Bit Counting and Testing
-\*----------------------------------------------------------------------------*/
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittest(long const *_BitBase, long _BitPos) {
- return (*_BitBase >> _BitPos) & 1;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittestandcomplement(long *_BitBase, long _BitPos) {
- unsigned char _Res = (*_BitBase >> _BitPos) & 1;
- *_BitBase = *_BitBase ^ (1 << _BitPos);
- return _Res;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittestandreset(long *_BitBase, long _BitPos) {
- unsigned char _Res = (*_BitBase >> _BitPos) & 1;
- *_BitBase = *_BitBase & ~(1 << _BitPos);
- return _Res;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittestandset(long *_BitBase, long _BitPos) {
- unsigned char _Res = (*_BitBase >> _BitPos) & 1;
- *_BitBase = *_BitBase | (1 << _BitPos);
- return _Res;
-}
-#if defined(__arm__) || defined(__aarch64__)
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_interlockedbittestandset_acq(long volatile *_BitBase, long _BitPos) {
- long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_ACQUIRE);
- return (_PrevVal >> _BitPos) & 1;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_interlockedbittestandset_nf(long volatile *_BitBase, long _BitPos) {
- long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELAXED);
- return (_PrevVal >> _BitPos) & 1;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_interlockedbittestandset_rel(long volatile *_BitBase, long _BitPos) {
- long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELEASE);
- return (_PrevVal >> _BitPos) & 1;
-}
-#endif
-#ifdef __x86_64__
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittest64(__int64 const *_BitBase, __int64 _BitPos) {
- return (*_BitBase >> _BitPos) & 1;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittestandcomplement64(__int64 *_BitBase, __int64 _BitPos) {
- unsigned char _Res = (*_BitBase >> _BitPos) & 1;
- *_BitBase = *_BitBase ^ (1ll << _BitPos);
- return _Res;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittestandreset64(__int64 *_BitBase, __int64 _BitPos) {
- unsigned char _Res = (*_BitBase >> _BitPos) & 1;
- *_BitBase = *_BitBase & ~(1ll << _BitPos);
- return _Res;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_bittestandset64(__int64 *_BitBase, __int64 _BitPos) {
- unsigned char _Res = (*_BitBase >> _BitPos) & 1;
- *_BitBase = *_BitBase | (1ll << _BitPos);
- return _Res;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_interlockedbittestandset64(__int64 volatile *_BitBase, __int64 _BitPos) {
- long long _PrevVal =
- __atomic_fetch_or(_BitBase, 1ll << _BitPos, __ATOMIC_SEQ_CST);
- return (_PrevVal >> _BitPos) & 1;
-}
-#endif
-/*----------------------------------------------------------------------------*\
|* Interlocked Exchange Add
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
@@ -602,6 +514,23 @@ _InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask) {
}
#endif
/*----------------------------------------------------------------------------*\
+|* Bit Counting and Testing
+\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
+unsigned char _interlockedbittestandset_acq(long volatile *_BitBase,
+ long _BitPos);
+unsigned char _interlockedbittestandset_nf(long volatile *_BitBase,
+ long _BitPos);
+unsigned char _interlockedbittestandset_rel(long volatile *_BitBase,
+ long _BitPos);
+unsigned char _interlockedbittestandreset_acq(long volatile *_BitBase,
+ long _BitPos);
+unsigned char _interlockedbittestandreset_nf(long volatile *_BitBase,
+ long _BitPos);
+unsigned char _interlockedbittestandreset_rel(long volatile *_BitBase,
+ long _BitPos);
+#endif
+/*----------------------------------------------------------------------------*\
|* Interlocked Or
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
@@ -868,33 +797,40 @@ _InterlockedCompareExchange64_rel(__int64 volatile *_Destination,
#if defined(__i386__) || defined(__x86_64__)
static __inline__ void __DEFAULT_FN_ATTRS
__movsb(unsigned char *__dst, unsigned char const *__src, size_t __n) {
- __asm__("rep movsb" : : "D"(__dst), "S"(__src), "c"(__n));
+ __asm__ __volatile__("rep movsb" : "+D"(__dst), "+S"(__src), "+c"(__n)
+ : : "memory");
}
static __inline__ void __DEFAULT_FN_ATTRS
__movsd(unsigned long *__dst, unsigned long const *__src, size_t __n) {
- __asm__("rep movsl" : : "D"(__dst), "S"(__src), "c"(__n));
+ __asm__ __volatile__("rep movsl" : "+D"(__dst), "+S"(__src), "+c"(__n)
+ : : "memory");
}
static __inline__ void __DEFAULT_FN_ATTRS
__movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) {
- __asm__("rep movsw" : : "D"(__dst), "S"(__src), "c"(__n));
+ __asm__ __volatile__("rep movsw" : "+D"(__dst), "+S"(__src), "+c"(__n)
+ : : "memory");
}
static __inline__ void __DEFAULT_FN_ATTRS
__stosd(unsigned long *__dst, unsigned long __x, size_t __n) {
- __asm__("rep stosl" : : "D"(__dst), "a"(__x), "c"(__n));
+ __asm__ __volatile__("rep stosl" : "+D"(__dst), "+c"(__n) : "a"(__x)
+ : "memory");
}
static __inline__ void __DEFAULT_FN_ATTRS
__stosw(unsigned short *__dst, unsigned short __x, size_t __n) {
- __asm__("rep stosw" : : "D"(__dst), "a"(__x), "c"(__n));
+ __asm__ __volatile__("rep stosw" : "+D"(__dst), "+c"(__n) : "a"(__x)
+ : "memory");
}
#endif
#ifdef __x86_64__
static __inline__ void __DEFAULT_FN_ATTRS
__movsq(unsigned long long *__dst, unsigned long long const *__src, size_t __n) {
- __asm__("rep movsq" : : "D"(__dst), "S"(__src), "c"(__n));
+ __asm__ __volatile__("rep movsq" : "+D"(__dst), "+S"(__src), "+c"(__n)
+ : : "memory");
}
static __inline__ void __DEFAULT_FN_ATTRS
__stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) {
- __asm__("rep stosq" : : "D"(__dst), "a"(__x), "c"(__n));
+ __asm__ __volatile__("rep stosq" : "+D"(__dst), "+c"(__n) : "a"(__x)
+ : "memory");
}
#endif
@@ -927,6 +863,20 @@ __nop(void) {
__asm__ volatile ("nop");
}
#endif
+#if defined(__x86_64__)
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
+__shiftleft128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) {
+ unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l;
+ unsigned __int128 __res = __val << (__d & 63);
+ return (unsigned __int64)(__res >> 64);
+}
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
+__shiftright128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) {
+ unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l;
+ unsigned __int128 __res = __val >> (__d & 63);
+ return (unsigned __int64)__res;
+}
+#endif
/*----------------------------------------------------------------------------*\
|* Privileged intrinsics
diff --git a/contrib/llvm/tools/clang/lib/Headers/invpcidintrin.h b/contrib/llvm/tools/clang/lib/Headers/invpcidintrin.h
new file mode 100644
index 000000000000..c30a19fa3d22
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/invpcidintrin.h
@@ -0,0 +1,37 @@
+/*===------------- invpcidintrin.h - INVPCID 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 <invpcidintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __INVPCIDINTRIN_H
+#define __INVPCIDINTRIN_H
+
+static __inline__ void
+ __attribute__((__always_inline__, __nodebug__, __target__("invpcid")))
+_invpcid(unsigned int __type, void *__descriptor) {
+ __builtin_ia32_invpcid(__type, __descriptor);
+}
+
+#endif /* __INVPCIDINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/lwpintrin.h b/contrib/llvm/tools/clang/lib/Headers/lwpintrin.h
index c95fdd9a201a..0b28d7358295 100644
--- a/contrib/llvm/tools/clang/lib/Headers/lwpintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/lwpintrin.h
@@ -31,7 +31,7 @@
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lwp")))
-/// \brief Parses the LWPCB at the specified address and enables
+/// Parses the LWPCB at the specified address and enables
/// profiling if valid.
///
/// \headerfile <x86intrin.h>
@@ -48,7 +48,7 @@ __llwpcb (void *__addr)
__builtin_ia32_llwpcb(__addr);
}
-/// \brief Flushes the LWP state to memory and returns the address of the LWPCB.
+/// Flushes the LWP state to memory and returns the address of the LWPCB.
///
/// \headerfile <x86intrin.h>
///
@@ -58,12 +58,12 @@ __llwpcb (void *__addr)
/// Address to the current Lightweight Profiling Control Block (LWPCB).
/// If LWP is not currently enabled, returns NULL.
static __inline__ void* __DEFAULT_FN_ATTRS
-__slwpcb ()
+__slwpcb (void)
{
return __builtin_ia32_slwpcb();
}
-/// \brief Inserts programmed event record into the LWP event ring buffer
+/// Inserts programmed event record into the LWP event ring buffer
/// and advances the ring buffer pointer.
///
/// \headerfile <x86intrin.h>
@@ -84,7 +84,7 @@ __slwpcb ()
(__builtin_ia32_lwpins32((unsigned int) (DATA2), (unsigned int) (DATA1), \
(unsigned int) (FLAGS)))
-/// \brief Decrements the LWP programmed value sample event counter. If the result is
+/// Decrements the LWP programmed value sample event counter. If the result is
/// negative, inserts an event record into the LWP event ring buffer in memory
/// and advances the ring buffer pointer.
///
@@ -104,7 +104,7 @@ __slwpcb ()
#ifdef __x86_64__
-/// \brief Inserts programmed event record into the LWP event ring buffer
+/// Inserts programmed event record into the LWP event ring buffer
/// and advances the ring buffer pointer.
///
/// \headerfile <x86intrin.h>
@@ -125,7 +125,7 @@ __slwpcb ()
(__builtin_ia32_lwpins64((unsigned long long) (DATA2), (unsigned int) (DATA1), \
(unsigned int) (FLAGS)))
-/// \brief Decrements the LWP programmed value sample event counter. If the result is
+/// Decrements the LWP programmed value sample event counter. If the result is
/// negative, inserts an event record into the LWP event ring buffer in memory
/// and advances the ring buffer pointer.
///
diff --git a/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h b/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
index 3d2769da3bae..558f1828f0e7 100644
--- a/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
@@ -31,7 +31,7 @@
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lzcnt")))
-/// \brief Counts the number of leading zero bits in the operand.
+/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -47,7 +47,7 @@ __lzcnt16(unsigned short __X)
return __X ? __builtin_clzs(__X) : 16;
}
-/// \brief Counts the number of leading zero bits in the operand.
+/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -57,13 +57,14 @@ __lzcnt16(unsigned short __X)
/// An unsigned 32-bit integer whose leading zeros are to be counted.
/// \returns An unsigned 32-bit integer containing the number of leading zero
/// bits in the operand.
+/// \see _lzcnt_u32
static __inline__ unsigned int __DEFAULT_FN_ATTRS
__lzcnt32(unsigned int __X)
{
return __X ? __builtin_clz(__X) : 32;
}
-/// \brief Counts the number of leading zero bits in the operand.
+/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -73,6 +74,7 @@ __lzcnt32(unsigned int __X)
/// An unsigned 32-bit integer whose leading zeros are to be counted.
/// \returns An unsigned 32-bit integer containing the number of leading zero
/// bits in the operand.
+/// \see __lzcnt32
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_lzcnt_u32(unsigned int __X)
{
@@ -80,7 +82,7 @@ _lzcnt_u32(unsigned int __X)
}
#ifdef __x86_64__
-/// \brief Counts the number of leading zero bits in the operand.
+/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -90,13 +92,14 @@ _lzcnt_u32(unsigned int __X)
/// An unsigned 64-bit integer whose leading zeros are to be counted.
/// \returns An unsigned 64-bit integer containing the number of leading zero
/// bits in the operand.
+/// \see _lzcnt_u64
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__lzcnt64(unsigned long long __X)
{
return __X ? __builtin_clzll(__X) : 64;
}
-/// \brief Counts the number of leading zero bits in the operand.
+/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
///
@@ -106,6 +109,7 @@ __lzcnt64(unsigned long long __X)
/// An unsigned 64-bit integer whose leading zeros are to be counted.
/// \returns An unsigned 64-bit integer containing the number of leading zero
/// bits in the operand.
+/// \see __lzcnt64
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_lzcnt_u64(unsigned long long __X)
{
diff --git a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
index 294866c1dc0d..b0288757a396 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
@@ -30,9 +30,9 @@
typedef float __v2sf __attribute__((__vector_size__(8)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnow")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnow"), __min_vector_width__(64)))
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("3dnow")))
_m_femms(void) {
__builtin_ia32_femms();
}
@@ -134,7 +134,7 @@ _m_pmulhrw(__m64 __m1, __m64 __m2) {
/* Handle the 3dnowa instructions here. */
#undef __DEFAULT_FN_ATTRS
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnowa")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnowa"), __min_vector_width__(64)))
static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pf2iw(__m64 __m) {
diff --git a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
index 4b38d51713d8..a73539942a92 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
@@ -32,27 +32,27 @@ typedef short __v4hi __attribute__((__vector_size__(8)));
typedef char __v8qi __attribute__((__vector_size__(8)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("mmx")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("mmx"), __min_vector_width__(64)))
-/// \brief Clears the MMX state by setting the state of the x87 stack registers
+/// Clears the MMX state by setting the state of the x87 stack registers
/// to empty.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> EMMS </c> instruction.
///
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("mmx")))
_mm_empty(void)
{
__builtin_ia32_emms();
}
-/// \brief Constructs a 64-bit integer vector, setting the lower 32 bits to the
+/// Constructs a 64-bit integer vector, setting the lower 32 bits to the
/// value of the 32-bit integer parameter and setting the upper 32 bits to 0.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVD </c> instruction.
///
/// \param __i
/// A 32-bit integer value.
@@ -64,12 +64,12 @@ _mm_cvtsi32_si64(int __i)
return (__m64)__builtin_ia32_vec_init_v2si(__i, 0);
}
-/// \brief Returns the lower 32 bits of a 64-bit integer vector as a 32-bit
+/// Returns the lower 32 bits of a 64-bit integer vector as a 32-bit
/// signed integer.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector.
@@ -81,11 +81,11 @@ _mm_cvtsi64_si32(__m64 __m)
return __builtin_ia32_vec_ext_v2si((__v2si)__m, 0);
}
-/// \brief Casts a 64-bit signed integer value into a 64-bit integer vector.
+/// Casts a 64-bit signed integer value into a 64-bit integer vector.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVQ / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVQ </c> instruction.
///
/// \param __i
/// A 64-bit signed integer.
@@ -97,11 +97,11 @@ _mm_cvtsi64_m64(long long __i)
return (__m64)__i;
}
-/// \brief Casts a 64-bit integer vector into a 64-bit signed integer value.
+/// Casts a 64-bit integer vector into a 64-bit signed integer value.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVQ / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVQ </c> instruction.
///
/// \param __m
/// A 64-bit integer vector.
@@ -113,7 +113,7 @@ _mm_cvtm64_si64(__m64 __m)
return (long long)__m;
}
-/// \brief Converts 16-bit signed integers from both 64-bit integer vector
+/// Converts 16-bit signed integers from both 64-bit integer vector
/// parameters of [4 x i16] into 8-bit signed integer values, and constructs
/// a 64-bit integer vector of [8 x i8] as the result. Positive values
/// greater than 0x7F are saturated to 0x7F. Negative values less than 0x80
@@ -143,7 +143,7 @@ _mm_packs_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_packsswb((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Converts 32-bit signed integers from both 64-bit integer vector
+/// Converts 32-bit signed integers from both 64-bit integer vector
/// parameters of [2 x i32] into 16-bit signed integer values, and constructs
/// a 64-bit integer vector of [4 x i16] as the result. Positive values
/// greater than 0x7FFF are saturated to 0x7FFF. Negative values less than
@@ -173,7 +173,7 @@ _mm_packs_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_packssdw((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Converts 16-bit signed integers from both 64-bit integer vector
+/// Converts 16-bit signed integers from both 64-bit integer vector
/// parameters of [4 x i16] into 8-bit unsigned integer values, and
/// constructs a 64-bit integer vector of [8 x i8] as the result. Values
/// greater than 0xFF are saturated to 0xFF. Values less than 0 are saturated
@@ -203,7 +203,7 @@ _mm_packs_pu16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_packuswb((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Unpacks the upper 32 bits from two 64-bit integer vectors of [8 x i8]
+/// Unpacks the upper 32 bits from two 64-bit integer vectors of [8 x i8]
/// and interleaves them into a 64-bit integer vector of [8 x i8].
///
/// \headerfile <x86intrin.h>
@@ -230,7 +230,7 @@ _mm_unpackhi_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_punpckhbw((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Unpacks the upper 32 bits from two 64-bit integer vectors of
+/// Unpacks the upper 32 bits from two 64-bit integer vectors of
/// [4 x i16] and interleaves them into a 64-bit integer vector of [4 x i16].
///
/// \headerfile <x86intrin.h>
@@ -253,7 +253,7 @@ _mm_unpackhi_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_punpckhwd((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Unpacks the upper 32 bits from two 64-bit integer vectors of
+/// Unpacks the upper 32 bits from two 64-bit integer vectors of
/// [2 x i32] and interleaves them into a 64-bit integer vector of [2 x i32].
///
/// \headerfile <x86intrin.h>
@@ -274,7 +274,7 @@ _mm_unpackhi_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_punpckhdq((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Unpacks the lower 32 bits from two 64-bit integer vectors of [8 x i8]
+/// Unpacks the lower 32 bits from two 64-bit integer vectors of [8 x i8]
/// and interleaves them into a 64-bit integer vector of [8 x i8].
///
/// \headerfile <x86intrin.h>
@@ -301,7 +301,7 @@ _mm_unpacklo_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_punpcklbw((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Unpacks the lower 32 bits from two 64-bit integer vectors of
+/// Unpacks the lower 32 bits from two 64-bit integer vectors of
/// [4 x i16] and interleaves them into a 64-bit integer vector of [4 x i16].
///
/// \headerfile <x86intrin.h>
@@ -324,7 +324,7 @@ _mm_unpacklo_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_punpcklwd((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Unpacks the lower 32 bits from two 64-bit integer vectors of
+/// Unpacks the lower 32 bits from two 64-bit integer vectors of
/// [2 x i32] and interleaves them into a 64-bit integer vector of [2 x i32].
///
/// \headerfile <x86intrin.h>
@@ -345,7 +345,7 @@ _mm_unpacklo_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_punpckldq((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Adds each 8-bit integer element of the first 64-bit integer vector
+/// Adds each 8-bit integer element of the first 64-bit integer vector
/// of [8 x i8] to the corresponding 8-bit integer element of the second
/// 64-bit integer vector of [8 x i8]. The lower 8 bits of the results are
/// packed into a 64-bit integer vector of [8 x i8].
@@ -366,7 +366,7 @@ _mm_add_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Adds each 16-bit integer element of the first 64-bit integer vector
+/// Adds each 16-bit integer element of the first 64-bit integer vector
/// of [4 x i16] to the corresponding 16-bit integer element of the second
/// 64-bit integer vector of [4 x i16]. The lower 16 bits of the results are
/// packed into a 64-bit integer vector of [4 x i16].
@@ -387,7 +387,7 @@ _mm_add_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Adds each 32-bit integer element of the first 64-bit integer vector
+/// Adds each 32-bit integer element of the first 64-bit integer vector
/// of [2 x i32] to the corresponding 32-bit integer element of the second
/// 64-bit integer vector of [2 x i32]. The lower 32 bits of the results are
/// packed into a 64-bit integer vector of [2 x i32].
@@ -408,7 +408,7 @@ _mm_add_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddd((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Adds each 8-bit signed integer element of the first 64-bit integer
+/// Adds each 8-bit signed integer element of the first 64-bit integer
/// vector of [8 x i8] to the corresponding 8-bit signed integer element of
/// the second 64-bit integer vector of [8 x i8]. Positive sums greater than
/// 0x7F are saturated to 0x7F. Negative sums less than 0x80 are saturated to
@@ -430,7 +430,7 @@ _mm_adds_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddsb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Adds each 16-bit signed integer element of the first 64-bit integer
+/// Adds each 16-bit signed integer element of the first 64-bit integer
/// vector of [4 x i16] to the corresponding 16-bit signed integer element of
/// the second 64-bit integer vector of [4 x i16]. Positive sums greater than
/// 0x7FFF are saturated to 0x7FFF. Negative sums less than 0x8000 are
@@ -453,7 +453,7 @@ _mm_adds_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Adds each 8-bit unsigned integer element of the first 64-bit integer
+/// Adds each 8-bit unsigned integer element of the first 64-bit integer
/// vector of [8 x i8] to the corresponding 8-bit unsigned integer element of
/// the second 64-bit integer vector of [8 x i8]. Sums greater than 0xFF are
/// saturated to 0xFF. The results are packed into a 64-bit integer vector of
@@ -475,7 +475,7 @@ _mm_adds_pu8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddusb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Adds each 16-bit unsigned integer element of the first 64-bit integer
+/// Adds each 16-bit unsigned integer element of the first 64-bit integer
/// vector of [4 x i16] to the corresponding 16-bit unsigned integer element
/// of the second 64-bit integer vector of [4 x i16]. Sums greater than
/// 0xFFFF are saturated to 0xFFFF. The results are packed into a 64-bit
@@ -497,7 +497,7 @@ _mm_adds_pu16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_paddusw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Subtracts each 8-bit integer element of the second 64-bit integer
+/// Subtracts each 8-bit integer element of the second 64-bit integer
/// vector of [8 x i8] from the corresponding 8-bit integer element of the
/// first 64-bit integer vector of [8 x i8]. The lower 8 bits of the results
/// are packed into a 64-bit integer vector of [8 x i8].
@@ -518,7 +518,7 @@ _mm_sub_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Subtracts each 16-bit integer element of the second 64-bit integer
+/// Subtracts each 16-bit integer element of the second 64-bit integer
/// vector of [4 x i16] from the corresponding 16-bit integer element of the
/// first 64-bit integer vector of [4 x i16]. The lower 16 bits of the
/// results are packed into a 64-bit integer vector of [4 x i16].
@@ -539,7 +539,7 @@ _mm_sub_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Subtracts each 32-bit integer element of the second 64-bit integer
+/// Subtracts each 32-bit integer element of the second 64-bit integer
/// vector of [2 x i32] from the corresponding 32-bit integer element of the
/// first 64-bit integer vector of [2 x i32]. The lower 32 bits of the
/// results are packed into a 64-bit integer vector of [2 x i32].
@@ -560,7 +560,7 @@ _mm_sub_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubd((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Subtracts each 8-bit signed integer element of the second 64-bit
+/// Subtracts each 8-bit signed integer element of the second 64-bit
/// integer vector of [8 x i8] from the corresponding 8-bit signed integer
/// element of the first 64-bit integer vector of [8 x i8]. Positive results
/// greater than 0x7F are saturated to 0x7F. Negative results less than 0x80
@@ -583,7 +583,7 @@ _mm_subs_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubsb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Subtracts each 16-bit signed integer element of the second 64-bit
+/// Subtracts each 16-bit signed integer element of the second 64-bit
/// integer vector of [4 x i16] from the corresponding 16-bit signed integer
/// element of the first 64-bit integer vector of [4 x i16]. Positive results
/// greater than 0x7FFF are saturated to 0x7FFF. Negative results less than
@@ -606,7 +606,7 @@ _mm_subs_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubsw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Subtracts each 8-bit unsigned integer element of the second 64-bit
+/// Subtracts each 8-bit unsigned integer element of the second 64-bit
/// integer vector of [8 x i8] from the corresponding 8-bit unsigned integer
/// element of the first 64-bit integer vector of [8 x i8].
///
@@ -630,7 +630,7 @@ _mm_subs_pu8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubusb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Subtracts each 16-bit unsigned integer element of the second 64-bit
+/// Subtracts each 16-bit unsigned integer element of the second 64-bit
/// integer vector of [4 x i16] from the corresponding 16-bit unsigned
/// integer element of the first 64-bit integer vector of [4 x i16].
///
@@ -654,7 +654,7 @@ _mm_subs_pu16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_psubusw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Multiplies each 16-bit signed integer element of the first 64-bit
+/// Multiplies each 16-bit signed integer element of the first 64-bit
/// integer vector of [4 x i16] by the corresponding 16-bit signed integer
/// element of the second 64-bit integer vector of [4 x i16] and get four
/// 32-bit products. Adds adjacent pairs of products to get two 32-bit sums.
@@ -681,7 +681,7 @@ _mm_madd_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pmaddwd((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Multiplies each 16-bit signed integer element of the first 64-bit
+/// Multiplies each 16-bit signed integer element of the first 64-bit
/// integer vector of [4 x i16] by the corresponding 16-bit signed integer
/// element of the second 64-bit integer vector of [4 x i16]. Packs the upper
/// 16 bits of the 32-bit products into a 64-bit integer vector of [4 x i16].
@@ -702,7 +702,7 @@ _mm_mulhi_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pmulhw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Multiplies each 16-bit signed integer element of the first 64-bit
+/// Multiplies each 16-bit signed integer element of the first 64-bit
/// integer vector of [4 x i16] by the corresponding 16-bit signed integer
/// element of the second 64-bit integer vector of [4 x i16]. Packs the lower
/// 16 bits of the 32-bit products into a 64-bit integer vector of [4 x i16].
@@ -723,7 +723,7 @@ _mm_mullo_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pmullw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Left-shifts each 16-bit signed integer element of the first
+/// Left-shifts each 16-bit signed integer element of the first
/// parameter, which is a 64-bit integer vector of [4 x i16], by the number
/// of bits specified by the second parameter, which is a 64-bit integer. The
/// lower 16 bits of the results are packed into a 64-bit integer vector of
@@ -746,7 +746,7 @@ _mm_sll_pi16(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psllw((__v4hi)__m, __count);
}
-/// \brief Left-shifts each 16-bit signed integer element of a 64-bit integer
+/// Left-shifts each 16-bit signed integer element of a 64-bit integer
/// vector of [4 x i16] by the number of bits specified by a 32-bit integer.
/// The lower 16 bits of the results are packed into a 64-bit integer vector
/// of [4 x i16].
@@ -768,7 +768,7 @@ _mm_slli_pi16(__m64 __m, int __count)
return (__m64)__builtin_ia32_psllwi((__v4hi)__m, __count);
}
-/// \brief Left-shifts each 32-bit signed integer element of the first
+/// Left-shifts each 32-bit signed integer element of the first
/// parameter, which is a 64-bit integer vector of [2 x i32], by the number
/// of bits specified by the second parameter, which is a 64-bit integer. The
/// lower 32 bits of the results are packed into a 64-bit integer vector of
@@ -791,7 +791,7 @@ _mm_sll_pi32(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_pslld((__v2si)__m, __count);
}
-/// \brief Left-shifts each 32-bit signed integer element of a 64-bit integer
+/// Left-shifts each 32-bit signed integer element of a 64-bit integer
/// vector of [2 x i32] by the number of bits specified by a 32-bit integer.
/// The lower 32 bits of the results are packed into a 64-bit integer vector
/// of [2 x i32].
@@ -813,7 +813,7 @@ _mm_slli_pi32(__m64 __m, int __count)
return (__m64)__builtin_ia32_pslldi((__v2si)__m, __count);
}
-/// \brief Left-shifts the first 64-bit integer parameter by the number of bits
+/// Left-shifts the first 64-bit integer parameter by the number of bits
/// specified by the second 64-bit integer parameter. The lower 64 bits of
/// result are returned.
///
@@ -833,7 +833,7 @@ _mm_sll_si64(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psllq((__v1di)__m, __count);
}
-/// \brief Left-shifts the first parameter, which is a 64-bit integer, by the
+/// Left-shifts the first parameter, which is a 64-bit integer, by the
/// number of bits specified by the second parameter, which is a 32-bit
/// integer. The lower 64 bits of result are returned.
///
@@ -853,7 +853,7 @@ _mm_slli_si64(__m64 __m, int __count)
return (__m64)__builtin_ia32_psllqi((__v1di)__m, __count);
}
-/// \brief Right-shifts each 16-bit integer element of the first parameter,
+/// Right-shifts each 16-bit integer element of the first parameter,
/// which is a 64-bit integer vector of [4 x i16], by the number of bits
/// specified by the second parameter, which is a 64-bit integer.
///
@@ -877,7 +877,7 @@ _mm_sra_pi16(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psraw((__v4hi)__m, __count);
}
-/// \brief Right-shifts each 16-bit integer element of a 64-bit integer vector
+/// Right-shifts each 16-bit integer element of a 64-bit integer vector
/// of [4 x i16] by the number of bits specified by a 32-bit integer.
///
/// High-order bits are filled with the sign bit of the initial value of each
@@ -900,7 +900,7 @@ _mm_srai_pi16(__m64 __m, int __count)
return (__m64)__builtin_ia32_psrawi((__v4hi)__m, __count);
}
-/// \brief Right-shifts each 32-bit integer element of the first parameter,
+/// Right-shifts each 32-bit integer element of the first parameter,
/// which is a 64-bit integer vector of [2 x i32], by the number of bits
/// specified by the second parameter, which is a 64-bit integer.
///
@@ -924,7 +924,7 @@ _mm_sra_pi32(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psrad((__v2si)__m, __count);
}
-/// \brief Right-shifts each 32-bit integer element of a 64-bit integer vector
+/// Right-shifts each 32-bit integer element of a 64-bit integer vector
/// of [2 x i32] by the number of bits specified by a 32-bit integer.
///
/// High-order bits are filled with the sign bit of the initial value of each
@@ -947,7 +947,7 @@ _mm_srai_pi32(__m64 __m, int __count)
return (__m64)__builtin_ia32_psradi((__v2si)__m, __count);
}
-/// \brief Right-shifts each 16-bit integer element of the first parameter,
+/// Right-shifts each 16-bit integer element of the first parameter,
/// which is a 64-bit integer vector of [4 x i16], by the number of bits
/// specified by the second parameter, which is a 64-bit integer.
///
@@ -970,7 +970,7 @@ _mm_srl_pi16(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psrlw((__v4hi)__m, __count);
}
-/// \brief Right-shifts each 16-bit integer element of a 64-bit integer vector
+/// Right-shifts each 16-bit integer element of a 64-bit integer vector
/// of [4 x i16] by the number of bits specified by a 32-bit integer.
///
/// High-order bits are cleared. The 16-bit results are packed into a 64-bit
@@ -992,7 +992,7 @@ _mm_srli_pi16(__m64 __m, int __count)
return (__m64)__builtin_ia32_psrlwi((__v4hi)__m, __count);
}
-/// \brief Right-shifts each 32-bit integer element of the first parameter,
+/// Right-shifts each 32-bit integer element of the first parameter,
/// which is a 64-bit integer vector of [2 x i32], by the number of bits
/// specified by the second parameter, which is a 64-bit integer.
///
@@ -1015,7 +1015,7 @@ _mm_srl_pi32(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psrld((__v2si)__m, __count);
}
-/// \brief Right-shifts each 32-bit integer element of a 64-bit integer vector
+/// Right-shifts each 32-bit integer element of a 64-bit integer vector
/// of [2 x i32] by the number of bits specified by a 32-bit integer.
///
/// High-order bits are cleared. The 32-bit results are packed into a 64-bit
@@ -1037,7 +1037,7 @@ _mm_srli_pi32(__m64 __m, int __count)
return (__m64)__builtin_ia32_psrldi((__v2si)__m, __count);
}
-/// \brief Right-shifts the first 64-bit integer parameter by the number of bits
+/// Right-shifts the first 64-bit integer parameter by the number of bits
/// specified by the second 64-bit integer parameter.
///
/// High-order bits are cleared.
@@ -1057,7 +1057,7 @@ _mm_srl_si64(__m64 __m, __m64 __count)
return (__m64)__builtin_ia32_psrlq((__v1di)__m, __count);
}
-/// \brief Right-shifts the first parameter, which is a 64-bit integer, by the
+/// Right-shifts the first parameter, which is a 64-bit integer, by the
/// number of bits specified by the second parameter, which is a 32-bit
/// integer.
///
@@ -1078,7 +1078,7 @@ _mm_srli_si64(__m64 __m, int __count)
return (__m64)__builtin_ia32_psrlqi((__v1di)__m, __count);
}
-/// \brief Performs a bitwise AND of two 64-bit integer vectors.
+/// Performs a bitwise AND of two 64-bit integer vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -1096,7 +1096,7 @@ _mm_and_si64(__m64 __m1, __m64 __m2)
return __builtin_ia32_pand((__v1di)__m1, (__v1di)__m2);
}
-/// \brief Performs a bitwise NOT of the first 64-bit integer vector, and then
+/// Performs a bitwise NOT of the first 64-bit integer vector, and then
/// performs a bitwise AND of the intermediate result and the second 64-bit
/// integer vector.
///
@@ -1117,7 +1117,7 @@ _mm_andnot_si64(__m64 __m1, __m64 __m2)
return __builtin_ia32_pandn((__v1di)__m1, (__v1di)__m2);
}
-/// \brief Performs a bitwise OR of two 64-bit integer vectors.
+/// Performs a bitwise OR of two 64-bit integer vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -1135,7 +1135,7 @@ _mm_or_si64(__m64 __m1, __m64 __m2)
return __builtin_ia32_por((__v1di)__m1, (__v1di)__m2);
}
-/// \brief Performs a bitwise exclusive OR of two 64-bit integer vectors.
+/// Performs a bitwise exclusive OR of two 64-bit integer vectors.
///
/// \headerfile <x86intrin.h>
///
@@ -1153,7 +1153,7 @@ _mm_xor_si64(__m64 __m1, __m64 __m2)
return __builtin_ia32_pxor((__v1di)__m1, (__v1di)__m2);
}
-/// \brief Compares the 8-bit integer elements of two 64-bit integer vectors of
+/// Compares the 8-bit integer elements of two 64-bit integer vectors of
/// [8 x i8] to determine if the element of the first vector is equal to the
/// corresponding element of the second vector.
///
@@ -1175,7 +1175,7 @@ _mm_cmpeq_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pcmpeqb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Compares the 16-bit integer elements of two 64-bit integer vectors of
+/// Compares the 16-bit integer elements of two 64-bit integer vectors of
/// [4 x i16] to determine if the element of the first vector is equal to the
/// corresponding element of the second vector.
///
@@ -1197,7 +1197,7 @@ _mm_cmpeq_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pcmpeqw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Compares the 32-bit integer elements of two 64-bit integer vectors of
+/// Compares the 32-bit integer elements of two 64-bit integer vectors of
/// [2 x i32] to determine if the element of the first vector is equal to the
/// corresponding element of the second vector.
///
@@ -1219,7 +1219,7 @@ _mm_cmpeq_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pcmpeqd((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Compares the 8-bit integer elements of two 64-bit integer vectors of
+/// Compares the 8-bit integer elements of two 64-bit integer vectors of
/// [8 x i8] to determine if the element of the first vector is greater than
/// the corresponding element of the second vector.
///
@@ -1241,7 +1241,7 @@ _mm_cmpgt_pi8(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pcmpgtb((__v8qi)__m1, (__v8qi)__m2);
}
-/// \brief Compares the 16-bit integer elements of two 64-bit integer vectors of
+/// Compares the 16-bit integer elements of two 64-bit integer vectors of
/// [4 x i16] to determine if the element of the first vector is greater than
/// the corresponding element of the second vector.
///
@@ -1263,7 +1263,7 @@ _mm_cmpgt_pi16(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pcmpgtw((__v4hi)__m1, (__v4hi)__m2);
}
-/// \brief Compares the 32-bit integer elements of two 64-bit integer vectors of
+/// Compares the 32-bit integer elements of two 64-bit integer vectors of
/// [2 x i32] to determine if the element of the first vector is greater than
/// the corresponding element of the second vector.
///
@@ -1285,20 +1285,20 @@ _mm_cmpgt_pi32(__m64 __m1, __m64 __m2)
return (__m64)__builtin_ia32_pcmpgtd((__v2si)__m1, (__v2si)__m2);
}
-/// \brief Constructs a 64-bit integer vector initialized to zero.
+/// Constructs a 64-bit integer vector initialized to zero.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VXORPS / XORPS </c> instruction.
+/// This intrinsic corresponds to the <c> PXOR </c> instruction.
///
/// \returns An initialized 64-bit integer vector with all elements set to zero.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_setzero_si64(void)
{
- return (__m64){ 0LL };
+ return __extension__ (__m64){ 0LL };
}
-/// \brief Constructs a 64-bit integer vector initialized with the specified
+/// Constructs a 64-bit integer vector initialized with the specified
/// 32-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -1319,7 +1319,7 @@ _mm_set_pi32(int __i1, int __i0)
return (__m64)__builtin_ia32_vec_init_v2si(__i0, __i1);
}
-/// \brief Constructs a 64-bit integer vector initialized with the specified
+/// Constructs a 64-bit integer vector initialized with the specified
/// 16-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -1342,7 +1342,7 @@ _mm_set_pi16(short __s3, short __s2, short __s1, short __s0)
return (__m64)__builtin_ia32_vec_init_v4hi(__s0, __s1, __s2, __s3);
}
-/// \brief Constructs a 64-bit integer vector initialized with the specified
+/// Constructs a 64-bit integer vector initialized with the specified
/// 8-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -1375,13 +1375,14 @@ _mm_set_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
__b4, __b5, __b6, __b7);
}
-/// \brief Constructs a 64-bit integer vector of [2 x i32], with each of the
+/// Constructs a 64-bit integer vector of [2 x i32], with each of the
/// 32-bit integer vector elements set to the specified 32-bit integer
/// value.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPSHUFD / PSHUFD </c> instruction.
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
///
/// \param __i
/// A 32-bit integer value used to initialize each vector element of the
@@ -1393,13 +1394,14 @@ _mm_set1_pi32(int __i)
return _mm_set_pi32(__i, __i);
}
-/// \brief Constructs a 64-bit integer vector of [4 x i16], with each of the
+/// Constructs a 64-bit integer vector of [4 x i16], with each of the
/// 16-bit integer vector elements set to the specified 16-bit integer
/// value.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPSHUFLW / PSHUFLW </c> instruction.
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
///
/// \param __w
/// A 16-bit integer value used to initialize each vector element of the
@@ -1411,13 +1413,13 @@ _mm_set1_pi16(short __w)
return _mm_set_pi16(__w, __w, __w, __w);
}
-/// \brief Constructs a 64-bit integer vector of [8 x i8], with each of the
+/// Constructs a 64-bit integer vector of [8 x i8], with each of the
/// 8-bit integer vector elements set to the specified 8-bit integer value.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPUNPCKLBW + VPSHUFLW / PUNPCKLBW +
-/// PSHUFLW </c> instruction.
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
///
/// \param __b
/// An 8-bit integer value used to initialize each vector element of the
@@ -1429,7 +1431,7 @@ _mm_set1_pi8(char __b)
return _mm_set_pi8(__b, __b, __b, __b, __b, __b, __b, __b);
}
-/// \brief Constructs a 64-bit integer vector, initialized in reverse order with
+/// Constructs a 64-bit integer vector, initialized in reverse order with
/// the specified 32-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -1450,7 +1452,7 @@ _mm_setr_pi32(int __i0, int __i1)
return _mm_set_pi32(__i1, __i0);
}
-/// \brief Constructs a 64-bit integer vector, initialized in reverse order with
+/// Constructs a 64-bit integer vector, initialized in reverse order with
/// the specified 16-bit integer values.
///
/// \headerfile <x86intrin.h>
@@ -1473,7 +1475,7 @@ _mm_setr_pi16(short __w0, short __w1, short __w2, short __w3)
return _mm_set_pi16(__w3, __w2, __w1, __w0);
}
-/// \brief Constructs a 64-bit integer vector, initialized in reverse order with
+/// Constructs a 64-bit integer vector, initialized in reverse order with
/// the specified 8-bit integer values.
///
/// \headerfile <x86intrin.h>
diff --git a/contrib/llvm/tools/clang/lib/Headers/module.modulemap b/contrib/llvm/tools/clang/lib/Headers/module.modulemap
index 95d26cefa6f7..1d1af57fd030 100644
--- a/contrib/llvm/tools/clang/lib/Headers/module.modulemap
+++ b/contrib/llvm/tools/clang/lib/Headers/module.modulemap
@@ -38,6 +38,7 @@ module _Builtin_intrinsics [system] [extern_c] {
explicit module neon {
requires neon
header "arm_neon.h"
+ header "arm_fp16.h"
export *
}
}
@@ -62,6 +63,17 @@ module _Builtin_intrinsics [system] [extern_c] {
textual header "fma4intrin.h"
textual header "mwaitxintrin.h"
textual header "clzerointrin.h"
+ textual header "wbnoinvdintrin.h"
+ textual header "cldemoteintrin.h"
+ textual header "waitpkgintrin.h"
+ textual header "movdirintrin.h"
+ textual header "pconfigintrin.h"
+ textual header "sgxintrin.h"
+ textual header "ptwriteintrin.h"
+ textual header "invpcidintrin.h"
+
+ textual header "__wmmintrin_aes.h"
+ textual header "__wmmintrin_pclmul.h"
explicit module mm_malloc {
requires !freestanding
@@ -128,14 +140,6 @@ module _Builtin_intrinsics [system] [extern_c] {
export aes
export pclmul
}
-
- explicit module aes {
- header "__wmmintrin_aes.h"
- }
-
- explicit module pclmul {
- header "__wmmintrin_pclmul.h"
- }
}
explicit module systemz {
diff --git a/contrib/llvm/tools/clang/lib/Headers/movdirintrin.h b/contrib/llvm/tools/clang/lib/Headers/movdirintrin.h
new file mode 100644
index 000000000000..ec20c53709bc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/movdirintrin.h
@@ -0,0 +1,63 @@
+/*===------------------------- movdirintrin.h ------------------------------===
+ *
+ * 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <movdirintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _MOVDIRINTRIN_H
+#define _MOVDIRINTRIN_H
+
+/* Move doubleword as direct store */
+static __inline__ void
+__attribute__((__always_inline__, __nodebug__, __target__("movdiri")))
+_directstoreu_u32 (void *__dst, unsigned int __value)
+{
+ __builtin_ia32_directstore_u32((unsigned int *)__dst, (unsigned int)__value);
+}
+
+#ifdef __x86_64__
+
+/* Move quadword as direct store */
+static __inline__ void
+__attribute__((__always_inline__, __nodebug__, __target__("movdiri")))
+_directstoreu_u64 (void *__dst, unsigned long __value)
+{
+ __builtin_ia32_directstore_u64((unsigned long *)__dst, __value);
+}
+
+#endif /* __x86_64__ */
+
+/*
+ * movdir64b - Move 64 bytes as direct store.
+ * The destination must be 64 byte aligned, and the store is atomic.
+ * The source address has no alignment requirement, and the load from
+ * the source address is not atomic.
+ */
+static __inline__ void
+__attribute__((__always_inline__, __nodebug__, __target__("movdir64b")))
+_movdir64b (void *__dst __attribute__((align_value(64))), const void *__src)
+{
+ __builtin_ia32_movdir64b(__dst, __src);
+}
+
+#endif /* _MOVDIRINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/mwaitxintrin.h b/contrib/llvm/tools/clang/lib/Headers/mwaitxintrin.h
index 635f2ac6cab5..2921eadfa540 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mwaitxintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mwaitxintrin.h
@@ -25,8 +25,8 @@
#error "Never use <mwaitxintrin.h> directly; include <x86intrin.h> instead."
#endif
-#ifndef _MWAITXINTRIN_H
-#define _MWAITXINTRIN_H
+#ifndef __MWAITXINTRIN_H
+#define __MWAITXINTRIN_H
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("mwaitx")))
@@ -44,4 +44,4 @@ _mm_mwaitx(unsigned __extensions, unsigned __hints, unsigned __clock)
#undef __DEFAULT_FN_ATTRS
-#endif /* _MWAITXINTRIN_H */
+#endif /* __MWAITXINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
index 57fec15963d1..348fb8c7c18f 100644
--- a/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
@@ -21,10 +21,10 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef _NMMINTRIN_H
-#define _NMMINTRIN_H
+#ifndef __NMMINTRIN_H
+#define __NMMINTRIN_H
/* To match expectations of gcc we put the sse4.2 definitions into smmintrin.h,
just include it now then. */
#include <smmintrin.h>
-#endif /* _NMMINTRIN_H */
+#endif /* __NMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/opencl-c.h b/contrib/llvm/tools/clang/lib/Headers/opencl-c.h
index ce204b04c030..e481c792df71 100644
--- a/contrib/llvm/tools/clang/lib/Headers/opencl-c.h
+++ b/contrib/llvm/tools/clang/lib/Headers/opencl-c.h
@@ -11540,7 +11540,7 @@ half16 __ovld __cnfn select(half16 a, half16 b, ushort16 c);
*
* vstoren write sizeof (gentypen) bytes given by data to address (p + (offset * n)).
*
- * The address computed as (p + (offset * n)) must be
+ * The address computed as (p + (offset * n)) must be
* 8-bit aligned if gentype is char, uchar;
* 16-bit aligned if gentype is short, ushort, half;
* 32-bit aligned if gentype is int, uint, float;
@@ -12862,7 +12862,7 @@ void __ovld mem_fence(cl_mem_fence_flags flags);
* Read memory barrier that orders only
* loads.
* The flags argument specifies the memory
- * address space and can be set to to a
+ * address space and can be set to a
* combination of the following literal
* values:
* CLK_LOCAL_MEM_FENCE
@@ -12874,7 +12874,7 @@ void __ovld read_mem_fence(cl_mem_fence_flags flags);
* Write memory barrier that orders only
* stores.
* The flags argument specifies the memory
- * address space and can be set to to a
+ * address space and can be set to a
* combination of the following literal
* values:
* CLK_LOCAL_MEM_FENCE
@@ -12888,7 +12888,7 @@ void __ovld write_mem_fence(cl_mem_fence_flags flags);
cl_mem_fence_flags __ovld get_fence(const void *ptr);
cl_mem_fence_flags __ovld get_fence(void *ptr);
-/**
+/**
* Builtin functions to_global, to_local, and to_private need to be declared as Clang builtin functions
* and checked in Sema since they should be declared as
* addr gentype* to_addr (gentype*);
@@ -13773,7 +13773,7 @@ ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, long opera
// add/sub: atomic type argument can be uintptr_t/intptr_t, value type argument can be ptrdiff_t.
// or/xor/and/min/max: atomic type argument can be intptr_t/uintptr_t, value type argument can be intptr_t/uintptr_t.
-#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
uintptr_t __ovld atomic_fetch_add(volatile atomic_uintptr_t *object, ptrdiff_t operand);
uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope);
@@ -14571,7 +14571,7 @@ int printf(__constant const char* st, ...);
* only. The filter_mode specified in sampler
* must be set to CLK_FILTER_NEAREST; otherwise
* the values returned are undefined.
-
+
* The read_image{f|i|ui} calls that take
* integer coordinates must use a sampler with
* normalized coordinates set to
@@ -15421,8 +15421,8 @@ int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_msaa_dept
#define CLK_DEPTH_STENCIL 0x10BE
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#define CLK_sRGB 0x10BF
-#define CLK_sRGBA 0x10C1
#define CLK_sRGBx 0x10C0
+#define CLK_sRGBA 0x10C1
#define CLK_sBGRA 0x10C2
#define CLK_ABGR 0x10C3
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
diff --git a/contrib/llvm/tools/clang/lib/Headers/pconfigintrin.h b/contrib/llvm/tools/clang/lib/Headers/pconfigintrin.h
new file mode 100644
index 000000000000..fee3cad38854
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/pconfigintrin.h
@@ -0,0 +1,50 @@
+/*===---- pconfigintrin.h - X86 platform configuration ---------------------===
+ *
+ * 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <pconfigintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __PCONFIGINTRIN_H
+#define __PCONFIGINTRIN_H
+
+#define __PCONFIG_KEY_PROGRAM 0x00000001
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("pconfig")))
+
+static __inline unsigned int __DEFAULT_FN_ATTRS
+_pconfig_u32(unsigned int __leaf, __SIZE_TYPE__ __d[])
+{
+ unsigned int __result;
+ __asm__ ("pconfig"
+ : "=a" (__result), "=b" (__d[0]), "=c" (__d[1]), "=d" (__d[2])
+ : "a" (__leaf), "b" (__d[0]), "c" (__d[1]), "d" (__d[2])
+ : "cc");
+ return __result;
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h b/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h
index 9e5459450b62..6976924d829e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h
@@ -1,4 +1,4 @@
-/*===------------- pkuintrin.h - PKU intrinsics ------------------===
+/*===---- pkuintrin.h - PKU intrinsics -------------------------------------===
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -40,7 +40,7 @@ _rdpkru_u32(void)
static __inline__ void __DEFAULT_FN_ATTRS
_wrpkru(unsigned int __val)
{
- return __builtin_ia32_wrpkru(__val);
+ __builtin_ia32_wrpkru(__val);
}
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
index 7ec08a1bcbb3..7e1a9eae59f6 100644
--- a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
@@ -28,9 +28,9 @@
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS \
- __attribute__((__always_inline__, __nodebug__, __target__("sse3")))
+ __attribute__((__always_inline__, __nodebug__, __target__("sse3"), __min_vector_width__(128)))
-/// \brief Loads data from an unaligned memory location to elements in a 128-bit
+/// Loads data from an unaligned memory location to elements in a 128-bit
/// vector.
///
/// If the address of the data is not 16-byte aligned, the instruction may
@@ -50,7 +50,7 @@ _mm_lddqu_si128(__m128i const *__p)
return (__m128i)__builtin_ia32_lddqu((char const *)__p);
}
-/// \brief Adds the even-indexed values and subtracts the odd-indexed values of
+/// Adds the even-indexed values and subtracts the odd-indexed values of
/// two 128-bit vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -69,7 +69,7 @@ _mm_addsub_ps(__m128 __a, __m128 __b)
return __builtin_ia32_addsubps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in two
+/// Horizontally adds the adjacent pairs of values contained in two
/// 128-bit vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -92,7 +92,7 @@ _mm_hadd_ps(__m128 __a, __m128 __b)
return __builtin_ia32_haddps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in two
+/// Horizontally subtracts the adjacent pairs of values contained in two
/// 128-bit vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -115,7 +115,7 @@ _mm_hsub_ps(__m128 __a, __m128 __b)
return __builtin_ia32_hsubps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Moves and duplicates odd-indexed values from a 128-bit vector
+/// Moves and duplicates odd-indexed values from a 128-bit vector
/// of [4 x float] to float values stored in a 128-bit vector of
/// [4 x float].
///
@@ -137,7 +137,7 @@ _mm_movehdup_ps(__m128 __a)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 1, 1, 3, 3);
}
-/// \brief Duplicates even-indexed values from a 128-bit vector of
+/// Duplicates even-indexed values from a 128-bit vector of
/// [4 x float] to float values stored in a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -158,7 +158,7 @@ _mm_moveldup_ps(__m128 __a)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 0, 0, 2, 2);
}
-/// \brief Adds the even-indexed values and subtracts the odd-indexed values of
+/// Adds the even-indexed values and subtracts the odd-indexed values of
/// two 128-bit vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -177,7 +177,7 @@ _mm_addsub_pd(__m128d __a, __m128d __b)
return __builtin_ia32_addsubpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Horizontally adds the pairs of values contained in two 128-bit
+/// Horizontally adds the pairs of values contained in two 128-bit
/// vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -200,7 +200,7 @@ _mm_hadd_pd(__m128d __a, __m128d __b)
return __builtin_ia32_haddpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Horizontally subtracts the pairs of values contained in two 128-bit
+/// Horizontally subtracts the pairs of values contained in two 128-bit
/// vectors of [2 x double].
///
/// \headerfile <x86intrin.h>
@@ -223,13 +223,13 @@ _mm_hsub_pd(__m128d __a, __m128d __b)
return __builtin_ia32_hsubpd((__v2df)__a, (__v2df)__b);
}
-/// \brief Moves and duplicates one double-precision value to double-precision
+/// Moves and duplicates one double-precision value to double-precision
/// values stored in a 128-bit vector of [2 x double].
///
/// \headerfile <x86intrin.h>
///
/// \code
-/// __m128d _mm_loaddup_pd(double const * dp);
+/// __m128d _mm_loaddup_pd(double const *dp);
/// \endcode
///
/// This intrinsic corresponds to the <c> VMOVDDUP </c> instruction.
@@ -240,7 +240,7 @@ _mm_hsub_pd(__m128d __a, __m128d __b)
/// duplicated values.
#define _mm_loaddup_pd(dp) _mm_load1_pd(dp)
-/// \brief Moves and duplicates the double-precision value in the lower bits of
+/// Moves and duplicates the double-precision value in the lower bits of
/// a 128-bit vector of [2 x double] to double-precision values stored in a
/// 128-bit vector of [2 x double].
///
@@ -259,7 +259,7 @@ _mm_movedup_pd(__m128d __a)
return __builtin_shufflevector((__v2df)__a, (__v2df)__a, 0, 0);
}
-/// \brief Establishes a linear address memory range to be monitored and puts
+/// Establishes a linear address memory range to be monitored and puts
/// the processor in the monitor event pending state. Data stored in the
/// monitored address range causes the processor to exit the pending state.
///
@@ -280,7 +280,7 @@ _mm_monitor(void const *__p, unsigned __extensions, unsigned __hints)
__builtin_ia32_monitor((void *)__p, __extensions, __hints);
}
-/// \brief Used with the MONITOR instruction to wait while the processor is in
+/// Used with the MONITOR instruction to wait while the processor is in
/// the monitor event pending state. Data stored in the monitored address
/// range causes the processor to exit the pending state.
///
diff --git a/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h b/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
index 0b4793e58bcb..75ceab9e150b 100644
--- a/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
@@ -21,13 +21,13 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef _POPCNTINTRIN_H
-#define _POPCNTINTRIN_H
+#ifndef __POPCNTINTRIN_H
+#define __POPCNTINTRIN_H
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("popcnt")))
-/// \brief Counts the number of bits in the source operand having a value of 1.
+/// Counts the number of bits in the source operand having a value of 1.
///
/// \headerfile <x86intrin.h>
///
@@ -43,7 +43,7 @@ _mm_popcnt_u32(unsigned int __A)
return __builtin_popcount(__A);
}
-/// \brief Counts the number of bits in the source operand having a value of 1.
+/// Counts the number of bits in the source operand having a value of 1.
///
/// \headerfile <x86intrin.h>
///
@@ -60,7 +60,7 @@ _popcnt32(int __A)
}
#ifdef __x86_64__
-/// \brief Counts the number of bits in the source operand having a value of 1.
+/// Counts the number of bits in the source operand having a value of 1.
///
/// \headerfile <x86intrin.h>
///
@@ -76,7 +76,7 @@ _mm_popcnt_u64(unsigned long long __A)
return __builtin_popcountll(__A);
}
-/// \brief Counts the number of bits in the source operand having a value of 1.
+/// Counts the number of bits in the source operand having a value of 1.
///
/// \headerfile <x86intrin.h>
///
@@ -95,4 +95,4 @@ _popcnt64(long long __A)
#undef __DEFAULT_FN_ATTRS
-#endif /* _POPCNTINTRIN_H */
+#endif /* __POPCNTINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h b/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h
index b52f31da2706..70851396f48e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h
@@ -28,8 +28,7 @@
#ifndef __PRFCHWINTRIN_H
#define __PRFCHWINTRIN_H
-#if defined(__PRFCHW__) || defined(__3dNOW__)
-/// \brief Loads a memory sequence containing the specified memory address into
+/// Loads a memory sequence containing the specified memory address into
/// all data cache levels. The cache-coherency state is set to exclusive.
/// Data can be read from and written to the cache line without additional
/// delay.
@@ -46,7 +45,7 @@ _m_prefetch(void *__P)
__builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
}
-/// \brief Loads a memory sequence containing the specified memory address into
+/// Loads a memory sequence containing the specified memory address into
/// the L1 data cache and sets the cache-coherency to modified. This
/// provides a hint to the processor that the cache line will be modified.
/// It is intended for use when the cache line will be written to shortly
@@ -66,6 +65,5 @@ _m_prefetchw(void *__P)
{
__builtin_prefetch (__P, 1, 3 /* _MM_HINT_T0 */);
}
-#endif
#endif /* __PRFCHWINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/ptwriteintrin.h b/contrib/llvm/tools/clang/lib/Headers/ptwriteintrin.h
new file mode 100644
index 000000000000..1bb1df0a2edf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/ptwriteintrin.h
@@ -0,0 +1,51 @@
+/*===------------ ptwriteintrin.h - PTWRITE 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <ptwriteintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __PTWRITEINTRIN_H
+#define __PTWRITEINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("ptwrite")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_ptwrite32(unsigned int __value) {
+ __builtin_ia32_ptwrite32(__value);
+}
+
+#ifdef __x86_64__
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_ptwrite64(unsigned long long __value) {
+ __builtin_ia32_ptwrite64(__value);
+}
+
+#endif /* __x86_64__ */
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif /* __PTWRITEINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h b/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
index 421f4ea48702..419466932cf5 100644
--- a/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
@@ -21,7 +21,7 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef __X86INTRIN_H
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
#error "Never use <rdseedintrin.h> directly; include <x86intrin.h> instead."
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/sgxintrin.h b/contrib/llvm/tools/clang/lib/Headers/sgxintrin.h
new file mode 100644
index 000000000000..20aee766103c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/sgxintrin.h
@@ -0,0 +1,70 @@
+/*===---- sgxintrin.h - X86 SGX intrinsics configuration -------------------===
+ *
+ * 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <sgxintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __SGXINTRIN_H
+#define __SGXINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("sgx")))
+
+static __inline unsigned int __DEFAULT_FN_ATTRS
+_enclu_u32(unsigned int __leaf, __SIZE_TYPE__ __d[])
+{
+ unsigned int __result;
+ __asm__ ("enclu"
+ : "=a" (__result), "=b" (__d[0]), "=c" (__d[1]), "=d" (__d[2])
+ : "a" (__leaf), "b" (__d[0]), "c" (__d[1]), "d" (__d[2])
+ : "cc");
+ return __result;
+}
+
+static __inline unsigned int __DEFAULT_FN_ATTRS
+_encls_u32(unsigned int __leaf, __SIZE_TYPE__ __d[])
+{
+ unsigned int __result;
+ __asm__ ("encls"
+ : "=a" (__result), "=b" (__d[0]), "=c" (__d[1]), "=d" (__d[2])
+ : "a" (__leaf), "b" (__d[0]), "c" (__d[1]), "d" (__d[2])
+ : "cc");
+ return __result;
+}
+
+static __inline unsigned int __DEFAULT_FN_ATTRS
+_enclv_u32(unsigned int __leaf, __SIZE_TYPE__ __d[])
+{
+ unsigned int __result;
+ __asm__ ("enclv"
+ : "=a" (__result), "=b" (__d[0]), "=c" (__d[1]), "=d" (__d[2])
+ : "a" (__leaf), "b" (__d[0]), "c" (__d[1]), "d" (__d[2])
+ : "cc");
+ return __result;
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/shaintrin.h b/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
index 9b5d21800819..3df4718ced4d 100644
--- a/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
@@ -29,10 +29,10 @@
#define __SHAINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sha")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sha"), __min_vector_width__(128)))
-#define _mm_sha1rnds4_epu32(V1, V2, M) __extension__ ({ \
- __builtin_ia32_sha1rnds4((__v4si)(__m128i)(V1), (__v4si)(__m128i)(V2), (M)); })
+#define _mm_sha1rnds4_epu32(V1, V2, M) \
+ __builtin_ia32_sha1rnds4((__v4si)(__m128i)(V1), (__v4si)(__m128i)(V2), (M))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha1nexte_epu32(__m128i __X, __m128i __Y)
diff --git a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
index e02775cea358..4806b3e4e150 100644
--- a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
@@ -21,13 +21,13 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef _SMMINTRIN_H
-#define _SMMINTRIN_H
+#ifndef __SMMINTRIN_H
+#define __SMMINTRIN_H
#include <tmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.1")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.1"), __min_vector_width__(128)))
/* SSE4 Rounding macros. */
#define _MM_FROUND_TO_NEAREST_INT 0x00
@@ -46,7 +46,7 @@
#define _MM_FROUND_RINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION)
#define _MM_FROUND_NEARBYINT (_MM_FROUND_NO_EXC | _MM_FROUND_CUR_DIRECTION)
-/// \brief Rounds up each element of the 128-bit vector of [4 x float] to an
+/// Rounds up each element of the 128-bit vector of [4 x float] to an
/// integer and returns the rounded values in a 128-bit vector of
/// [4 x float].
///
@@ -63,7 +63,7 @@
/// \returns A 128-bit vector of [4 x float] containing the rounded values.
#define _mm_ceil_ps(X) _mm_round_ps((X), _MM_FROUND_CEIL)
-/// \brief Rounds up each element of the 128-bit vector of [2 x double] to an
+/// Rounds up each element of the 128-bit vector of [2 x double] to an
/// integer and returns the rounded values in a 128-bit vector of
/// [2 x double].
///
@@ -80,7 +80,7 @@
/// \returns A 128-bit vector of [2 x double] containing the rounded values.
#define _mm_ceil_pd(X) _mm_round_pd((X), _MM_FROUND_CEIL)
-/// \brief Copies three upper elements of the first 128-bit vector operand to
+/// Copies three upper elements of the first 128-bit vector operand to
/// the corresponding three upper elements of the 128-bit result vector of
/// [4 x float]. Rounds up the lowest element of the second 128-bit vector
/// operand to an integer and copies it to the lowest element of the 128-bit
@@ -105,7 +105,7 @@
/// values.
#define _mm_ceil_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_CEIL)
-/// \brief Copies the upper element of the first 128-bit vector operand to the
+/// Copies the upper element of the first 128-bit vector operand to the
/// corresponding upper element of the 128-bit result vector of [2 x double].
/// Rounds up the lower element of the second 128-bit vector operand to an
/// integer and copies it to the lower element of the 128-bit result vector
@@ -130,7 +130,7 @@
/// values.
#define _mm_ceil_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_CEIL)
-/// \brief Rounds down each element of the 128-bit vector of [4 x float] to an
+/// Rounds down each element of the 128-bit vector of [4 x float] to an
/// an integer and returns the rounded values in a 128-bit vector of
/// [4 x float].
///
@@ -147,7 +147,7 @@
/// \returns A 128-bit vector of [4 x float] containing the rounded values.
#define _mm_floor_ps(X) _mm_round_ps((X), _MM_FROUND_FLOOR)
-/// \brief Rounds down each element of the 128-bit vector of [2 x double] to an
+/// Rounds down each element of the 128-bit vector of [2 x double] to an
/// integer and returns the rounded values in a 128-bit vector of
/// [2 x double].
///
@@ -164,7 +164,7 @@
/// \returns A 128-bit vector of [2 x double] containing the rounded values.
#define _mm_floor_pd(X) _mm_round_pd((X), _MM_FROUND_FLOOR)
-/// \brief Copies three upper elements of the first 128-bit vector operand to
+/// Copies three upper elements of the first 128-bit vector operand to
/// the corresponding three upper elements of the 128-bit result vector of
/// [4 x float]. Rounds down the lowest element of the second 128-bit vector
/// operand to an integer and copies it to the lowest element of the 128-bit
@@ -189,7 +189,7 @@
/// values.
#define _mm_floor_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_FLOOR)
-/// \brief Copies the upper element of the first 128-bit vector operand to the
+/// Copies the upper element of the first 128-bit vector operand to the
/// corresponding upper element of the 128-bit result vector of [2 x double].
/// Rounds down the lower element of the second 128-bit vector operand to an
/// integer and copies it to the lower element of the 128-bit result vector
@@ -214,7 +214,7 @@
/// values.
#define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR)
-/// \brief Rounds each element of the 128-bit vector of [4 x float] to an
+/// Rounds each element of the 128-bit vector of [4 x float] to an
/// integer value according to the rounding control specified by the second
/// argument and returns the rounded values in a 128-bit vector of
/// [4 x float].
@@ -244,10 +244,10 @@
/// 10: Upward (toward positive infinity) \n
/// 11: Truncated
/// \returns A 128-bit vector of [4 x float] containing the rounded values.
-#define _mm_round_ps(X, M) __extension__ ({ \
- (__m128)__builtin_ia32_roundps((__v4sf)(__m128)(X), (M)); })
+#define _mm_round_ps(X, M) \
+ (__m128)__builtin_ia32_roundps((__v4sf)(__m128)(X), (M))
-/// \brief Copies three upper elements of the first 128-bit vector operand to
+/// Copies three upper elements of the first 128-bit vector operand to
/// the corresponding three upper elements of the 128-bit result vector of
/// [4 x float]. Rounds the lowest element of the second 128-bit vector
/// operand to an integer value according to the rounding control specified
@@ -285,11 +285,11 @@
/// 11: Truncated
/// \returns A 128-bit vector of [4 x float] containing the copied and rounded
/// values.
-#define _mm_round_ss(X, Y, M) __extension__ ({ \
+#define _mm_round_ss(X, Y, M) \
(__m128)__builtin_ia32_roundss((__v4sf)(__m128)(X), \
- (__v4sf)(__m128)(Y), (M)); })
+ (__v4sf)(__m128)(Y), (M))
-/// \brief Rounds each element of the 128-bit vector of [2 x double] to an
+/// Rounds each element of the 128-bit vector of [2 x double] to an
/// integer value according to the rounding control specified by the second
/// argument and returns the rounded values in a 128-bit vector of
/// [2 x double].
@@ -319,10 +319,10 @@
/// 10: Upward (toward positive infinity) \n
/// 11: Truncated
/// \returns A 128-bit vector of [2 x double] containing the rounded values.
-#define _mm_round_pd(X, M) __extension__ ({ \
- (__m128d)__builtin_ia32_roundpd((__v2df)(__m128d)(X), (M)); })
+#define _mm_round_pd(X, M) \
+ (__m128d)__builtin_ia32_roundpd((__v2df)(__m128d)(X), (M))
-/// \brief Copies the upper element of the first 128-bit vector operand to the
+/// Copies the upper element of the first 128-bit vector operand to the
/// corresponding upper element of the 128-bit result vector of [2 x double].
/// Rounds the lower element of the second 128-bit vector operand to an
/// integer value according to the rounding control specified by the third
@@ -360,12 +360,12 @@
/// 11: Truncated
/// \returns A 128-bit vector of [2 x double] containing the copied and rounded
/// values.
-#define _mm_round_sd(X, Y, M) __extension__ ({ \
+#define _mm_round_sd(X, Y, M) \
(__m128d)__builtin_ia32_roundsd((__v2df)(__m128d)(X), \
- (__v2df)(__m128d)(Y), (M)); })
+ (__v2df)(__m128d)(Y), (M))
/* SSE4 Packed Blending Intrinsics. */
-/// \brief Returns a 128-bit vector of [2 x double] where the values are
+/// Returns a 128-bit vector of [2 x double] where the values are
/// selected from either the first or second operand as specified by the
/// third operand, the control mask.
///
@@ -389,13 +389,11 @@
/// When a mask bit is 1, the corresponding 64-bit element in operand \a V2
/// is copied to the same position in the result.
/// \returns A 128-bit vector of [2 x double] containing the copied values.
-#define _mm_blend_pd(V1, V2, M) __extension__ ({ \
- (__m128d)__builtin_shufflevector((__v2df)(__m128d)(V1), \
- (__v2df)(__m128d)(V2), \
- (((M) & 0x01) ? 2 : 0), \
- (((M) & 0x02) ? 3 : 1)); })
+#define _mm_blend_pd(V1, V2, M) \
+ (__m128d) __builtin_ia32_blendpd ((__v2df)(__m128d)(V1), \
+ (__v2df)(__m128d)(V2), (int)(M))
-/// \brief Returns a 128-bit vector of [4 x float] where the values are selected
+/// Returns a 128-bit vector of [4 x float] where the values are selected
/// from either the first or second operand as specified by the third
/// operand, the control mask.
///
@@ -419,14 +417,11 @@
/// When a mask bit is 1, the corresponding 32-bit element in operand \a V2
/// is copied to the same position in the result.
/// \returns A 128-bit vector of [4 x float] containing the copied values.
-#define _mm_blend_ps(V1, V2, M) __extension__ ({ \
- (__m128)__builtin_shufflevector((__v4sf)(__m128)(V1), (__v4sf)(__m128)(V2), \
- (((M) & 0x01) ? 4 : 0), \
- (((M) & 0x02) ? 5 : 1), \
- (((M) & 0x04) ? 6 : 2), \
- (((M) & 0x08) ? 7 : 3)); })
-
-/// \brief Returns a 128-bit vector of [2 x double] where the values are
+#define _mm_blend_ps(V1, V2, M) \
+ (__m128) __builtin_ia32_blendps ((__v4sf)(__m128)(V1), \
+ (__v4sf)(__m128)(V2), (int)(M))
+
+/// Returns a 128-bit vector of [2 x double] where the values are
/// selected from either the first or second operand as specified by the
/// third operand, the control mask.
///
@@ -453,7 +448,7 @@ _mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M)
(__v2df)__M);
}
-/// \brief Returns a 128-bit vector of [4 x float] where the values are
+/// Returns a 128-bit vector of [4 x float] where the values are
/// selected from either the first or second operand as specified by the
/// third operand, the control mask.
///
@@ -480,7 +475,7 @@ _mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M)
(__v4sf)__M);
}
-/// \brief Returns a 128-bit vector of [16 x i8] where the values are selected
+/// Returns a 128-bit vector of [16 x i8] where the values are selected
/// from either of the first or second operand as specified by the third
/// operand, the control mask.
///
@@ -493,7 +488,7 @@ _mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M)
/// \param __V2
/// A 128-bit vector of [16 x i8].
/// \param __M
-/// A 128-bit vector operand, with mask bits 127, 119, 111 ... 7 specifying
+/// A 128-bit vector operand, with mask bits 127, 119, 111...7 specifying
/// how the values are to be copied. The position of the mask bit corresponds
/// to the most significant bit of a copied value. When a mask bit is 0, the
/// corresponding 8-bit element in operand \a __V1 is copied to the same
@@ -507,7 +502,7 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
(__v16qi)__M);
}
-/// \brief Returns a 128-bit vector of [8 x i16] where the values are selected
+/// Returns a 128-bit vector of [8 x i16] where the values are selected
/// from either of the first or second operand as specified by the third
/// operand, the control mask.
///
@@ -531,20 +526,12 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
/// When a mask bit is 1, the corresponding 16-bit element in operand \a V2
/// is copied to the same position in the result.
/// \returns A 128-bit vector of [8 x i16] containing the copied values.
-#define _mm_blend_epi16(V1, V2, M) __extension__ ({ \
- (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(V1), \
- (__v8hi)(__m128i)(V2), \
- (((M) & 0x01) ? 8 : 0), \
- (((M) & 0x02) ? 9 : 1), \
- (((M) & 0x04) ? 10 : 2), \
- (((M) & 0x08) ? 11 : 3), \
- (((M) & 0x10) ? 12 : 4), \
- (((M) & 0x20) ? 13 : 5), \
- (((M) & 0x40) ? 14 : 6), \
- (((M) & 0x80) ? 15 : 7)); })
+#define _mm_blend_epi16(V1, V2, M) \
+ (__m128i) __builtin_ia32_pblendw128 ((__v8hi)(__m128i)(V1), \
+ (__v8hi)(__m128i)(V2), (int)(M))
/* SSE4 Dword Multiply Instructions. */
-/// \brief Multiples corresponding elements of two 128-bit vectors of [4 x i32]
+/// Multiples corresponding elements of two 128-bit vectors of [4 x i32]
/// and returns the lower 32 bits of the each product in a 128-bit vector of
/// [4 x i32].
///
@@ -563,7 +550,7 @@ _mm_mullo_epi32 (__m128i __V1, __m128i __V2)
return (__m128i) ((__v4su)__V1 * (__v4su)__V2);
}
-/// \brief Multiplies corresponding even-indexed elements of two 128-bit
+/// Multiplies corresponding even-indexed elements of two 128-bit
/// vectors of [4 x i32] and returns a 128-bit vector of [2 x i64]
/// containing the products.
///
@@ -584,7 +571,7 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
}
/* SSE4 Floating Point Dot Product Instructions. */
-/// \brief Computes the dot product of the two 128-bit vectors of [4 x float]
+/// Computes the dot product of the two 128-bit vectors of [4 x float]
/// and returns it in the elements of the 128-bit result vector of
/// [4 x float].
///
@@ -616,11 +603,11 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/// each [4 x float] subvector. If a bit is set, the dot product is returned
/// in the corresponding element; otherwise that element is set to zero.
/// \returns A 128-bit vector of [4 x float] containing the dot product.
-#define _mm_dp_ps(X, Y, M) __extension__ ({ \
+#define _mm_dp_ps(X, Y, M) \
(__m128) __builtin_ia32_dpps((__v4sf)(__m128)(X), \
- (__v4sf)(__m128)(Y), (M)); })
+ (__v4sf)(__m128)(Y), (M))
-/// \brief Computes the dot product of the two 128-bit vectors of [2 x double]
+/// Computes the dot product of the two 128-bit vectors of [2 x double]
/// and returns it in the elements of the 128-bit result vector of
/// [2 x double].
///
@@ -651,12 +638,12 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/// to the lowest element and bit [1] corresponding to the highest element of
/// each [2 x double] vector. If a bit is set, the dot product is returned in
/// the corresponding element; otherwise that element is set to zero.
-#define _mm_dp_pd(X, Y, M) __extension__ ({\
+#define _mm_dp_pd(X, Y, M) \
(__m128d) __builtin_ia32_dppd((__v2df)(__m128d)(X), \
- (__v2df)(__m128d)(Y), (M)); })
+ (__v2df)(__m128d)(Y), (M))
/* SSE4 Streaming Load Hint Instruction. */
-/// \brief Loads integer values from a 128-bit aligned memory location to a
+/// Loads integer values from a 128-bit aligned memory location to a
/// 128-bit integer vector.
///
/// \headerfile <x86intrin.h>
@@ -675,7 +662,7 @@ _mm_stream_load_si128 (__m128i const *__V)
}
/* SSE4 Packed Integer Min/Max Instructions. */
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [16 x i8] and returns a 128-bit vector of [16 x i8] containing the lesser
/// of the two values.
///
@@ -694,7 +681,7 @@ _mm_min_epi8 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pminsb128 ((__v16qi) __V1, (__v16qi) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [16 x i8] and returns a 128-bit vector of [16 x i8] containing the
/// greater value of the two.
///
@@ -713,7 +700,7 @@ _mm_max_epi8 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi) __V1, (__v16qi) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [8 x u16] and returns a 128-bit vector of [8 x u16] containing the lesser
/// value of the two.
///
@@ -732,7 +719,7 @@ _mm_min_epu16 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pminuw128 ((__v8hi) __V1, (__v8hi) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [8 x u16] and returns a 128-bit vector of [8 x u16] containing the
/// greater value of the two.
///
@@ -751,7 +738,7 @@ _mm_max_epu16 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi) __V1, (__v8hi) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [4 x i32] and returns a 128-bit vector of [4 x i32] containing the lesser
/// value of the two.
///
@@ -770,7 +757,7 @@ _mm_min_epi32 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pminsd128 ((__v4si) __V1, (__v4si) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [4 x i32] and returns a 128-bit vector of [4 x i32] containing the
/// greater value of the two.
///
@@ -789,7 +776,7 @@ _mm_max_epi32 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pmaxsd128 ((__v4si) __V1, (__v4si) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [4 x u32] and returns a 128-bit vector of [4 x u32] containing the lesser
/// value of the two.
///
@@ -808,7 +795,7 @@ _mm_min_epu32 (__m128i __V1, __m128i __V2)
return (__m128i) __builtin_ia32_pminud128((__v4si) __V1, (__v4si) __V2);
}
-/// \brief Compares the corresponding elements of two 128-bit vectors of
+/// Compares the corresponding elements of two 128-bit vectors of
/// [4 x u32] and returns a 128-bit vector of [4 x u32] containing the
/// greater value of the two.
///
@@ -828,7 +815,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
}
/* SSE4 Insertion and Extraction from XMM Register Instructions. */
-/// \brief Takes the first argument \a X and inserts an element from the second
+/// Takes the first argument \a X and inserts an element from the second
/// argument \a Y as selected by the third argument \a N. That result then
/// has elements zeroed out also as selected by the third argument \a N. The
/// resulting 128-bit vector of [4 x float] is then returned.
@@ -870,7 +857,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// single-precision floating point elements from the operands.
#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N))
-/// \brief Extracts a 32-bit integer from a 128-bit vector of [4 x float] and
+/// Extracts a 32-bit integer from a 128-bit vector of [4 x float] and
/// returns it, using the immediate value parameter \a N as a selector.
///
/// \headerfile <x86intrin.h>
@@ -893,15 +880,14 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 11: Bits [127:96] of parameter \a X are returned.
/// \returns A 32-bit integer containing the extracted 32 bits of float data.
#define _mm_extract_ps(X, N) (__extension__ \
- ({ union { int __i; float __f; } __t; \
- __v4sf __a = (__v4sf)(__m128)(X); \
- __t.__f = __a[(N) & 3]; \
- __t.__i;}))
+ ({ union { int __i; float __f; } __t; \
+ __t.__f = __builtin_ia32_vec_ext_v4sf((__v4sf)(__m128)(X), (int)(N)); \
+ __t.__i;}))
/* Miscellaneous insert and extract macros. */
/* Extract a single-precision float from X at index N into D. */
-#define _MM_EXTRACT_FLOAT(D, X, N) (__extension__ ({ __v4sf __a = (__v4sf)(X); \
- (D) = __a[N]; }))
+#define _MM_EXTRACT_FLOAT(D, X, N) \
+ { (D) = __builtin_ia32_vec_ext_v4sf((__v4sf)(__m128)(X), (int)(N)); }
/* Or together 2 sets of indexes (X and Y) with the zeroing bits (Z) to create
an index suitable for _mm_insert_ps. */
@@ -912,7 +898,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
_MM_MK_INSERTPS_NDX((N), 0, 0x0e))
/* Insert int into packed integer array at index. */
-/// \brief Constructs a 128-bit vector of [16 x i8] by first making a copy of
+/// Constructs a 128-bit vector of [16 x i8] by first making a copy of
/// the 128-bit integer vector parameter, and then inserting the lower 8 bits
/// of an integer parameter \a I into an offset specified by the immediate
/// value parameter \a N.
@@ -952,12 +938,11 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 1110: Bits [119:112] of the result are used for insertion. \n
/// 1111: Bits [127:120] of the result are used for insertion.
/// \returns A 128-bit integer vector containing the constructed values.
-#define _mm_insert_epi8(X, I, N) (__extension__ \
- ({ __v16qi __a = (__v16qi)(__m128i)(X); \
- __a[(N) & 15] = (I); \
- (__m128i)__a;}))
+#define _mm_insert_epi8(X, I, N) \
+ (__m128i)__builtin_ia32_vec_set_v16qi((__v16qi)(__m128i)(X), \
+ (int)(I), (int)(N))
-/// \brief Constructs a 128-bit vector of [4 x i32] by first making a copy of
+/// Constructs a 128-bit vector of [4 x i32] by first making a copy of
/// the 128-bit integer vector parameter, and then inserting the 32-bit
/// integer parameter \a I at the offset specified by the immediate value
/// parameter \a N.
@@ -985,13 +970,12 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 10: Bits [95:64] of the result are used for insertion. \n
/// 11: Bits [127:96] of the result are used for insertion.
/// \returns A 128-bit integer vector containing the constructed values.
-#define _mm_insert_epi32(X, I, N) (__extension__ \
- ({ __v4si __a = (__v4si)(__m128i)(X); \
- __a[(N) & 3] = (I); \
- (__m128i)__a;}))
+#define _mm_insert_epi32(X, I, N) \
+ (__m128i)__builtin_ia32_vec_set_v4si((__v4si)(__m128i)(X), \
+ (int)(I), (int)(N))
#ifdef __x86_64__
-/// \brief Constructs a 128-bit vector of [2 x i64] by first making a copy of
+/// Constructs a 128-bit vector of [2 x i64] by first making a copy of
/// the 128-bit integer vector parameter, and then inserting the 64-bit
/// integer parameter \a I, using the immediate value parameter \a N as an
/// insertion location selector.
@@ -1017,16 +1001,15 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 0: Bits [63:0] of the result are used for insertion. \n
/// 1: Bits [127:64] of the result are used for insertion. \n
/// \returns A 128-bit integer vector containing the constructed values.
-#define _mm_insert_epi64(X, I, N) (__extension__ \
- ({ __v2di __a = (__v2di)(__m128i)(X); \
- __a[(N) & 1] = (I); \
- (__m128i)__a;}))
+#define _mm_insert_epi64(X, I, N) \
+ (__m128i)__builtin_ia32_vec_set_v2di((__v2di)(__m128i)(X), \
+ (long long)(I), (int)(N))
#endif /* __x86_64__ */
/* Extract int from packed integer array at index. This returns the element
* as a zero extended value, so it is unsigned.
*/
-/// \brief Extracts an 8-bit element from the 128-bit integer vector of
+/// Extracts an 8-bit element from the 128-bit integer vector of
/// [16 x i8], using the immediate value parameter \a N as a selector.
///
/// \headerfile <x86intrin.h>
@@ -1061,11 +1044,11 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// \returns An unsigned integer, whose lower 8 bits are selected from the
/// 128-bit integer vector parameter and the remaining bits are assigned
/// zeros.
-#define _mm_extract_epi8(X, N) (__extension__ \
- ({ __v16qi __a = (__v16qi)(__m128i)(X); \
- (int)(unsigned char) __a[(N) & 15];}))
+#define _mm_extract_epi8(X, N) \
+ (int)(unsigned char)__builtin_ia32_vec_ext_v16qi((__v16qi)(__m128i)(X), \
+ (int)(N))
-/// \brief Extracts a 32-bit element from the 128-bit integer vector of
+/// Extracts a 32-bit element from the 128-bit integer vector of
/// [4 x i32], using the immediate value parameter \a N as a selector.
///
/// \headerfile <x86intrin.h>
@@ -1087,12 +1070,11 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 11: Bits [127:96] of the parameter \a X are exracted.
/// \returns An integer, whose lower 32 bits are selected from the 128-bit
/// integer vector parameter and the remaining bits are assigned zeros.
-#define _mm_extract_epi32(X, N) (__extension__ \
- ({ __v4si __a = (__v4si)(__m128i)(X); \
- (int)__a[(N) & 3];}))
+#define _mm_extract_epi32(X, N) \
+ (int)__builtin_ia32_vec_ext_v4si((__v4si)(__m128i)(X), (int)(N))
#ifdef __x86_64__
-/// \brief Extracts a 64-bit element from the 128-bit integer vector of
+/// Extracts a 64-bit element from the 128-bit integer vector of
/// [2 x i64], using the immediate value parameter \a N as a selector.
///
/// \headerfile <x86intrin.h>
@@ -1111,13 +1093,12 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 0: Bits [63:0] are returned. \n
/// 1: Bits [127:64] are returned. \n
/// \returns A 64-bit integer.
-#define _mm_extract_epi64(X, N) (__extension__ \
- ({ __v2di __a = (__v2di)(__m128i)(X); \
- (long long)__a[(N) & 1];}))
+#define _mm_extract_epi64(X, N) \
+ (long long)__builtin_ia32_vec_ext_v2di((__v2di)(__m128i)(X), (int)(N))
#endif /* __x86_64 */
/* SSE4 128-bit Packed Integer Comparisons. */
-/// \brief Tests whether the specified bits in a 128-bit integer vector are all
+/// Tests whether the specified bits in a 128-bit integer vector are all
/// zeros.
///
/// \headerfile <x86intrin.h>
@@ -1135,7 +1116,7 @@ _mm_testz_si128(__m128i __M, __m128i __V)
return __builtin_ia32_ptestz128((__v2di)__M, (__v2di)__V);
}
-/// \brief Tests whether the specified bits in a 128-bit integer vector are all
+/// Tests whether the specified bits in a 128-bit integer vector are all
/// ones.
///
/// \headerfile <x86intrin.h>
@@ -1153,7 +1134,7 @@ _mm_testc_si128(__m128i __M, __m128i __V)
return __builtin_ia32_ptestc128((__v2di)__M, (__v2di)__V);
}
-/// \brief Tests whether the specified bits in a 128-bit integer vector are
+/// Tests whether the specified bits in a 128-bit integer vector are
/// neither all zeros nor all ones.
///
/// \headerfile <x86intrin.h>
@@ -1172,7 +1153,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
return __builtin_ia32_ptestnzc128((__v2di)__M, (__v2di)__V);
}
-/// \brief Tests whether the specified bits in a 128-bit integer vector are all
+/// Tests whether the specified bits in a 128-bit integer vector are all
/// ones.
///
/// \headerfile <x86intrin.h>
@@ -1189,7 +1170,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
/// otherwise.
#define _mm_test_all_ones(V) _mm_testc_si128((V), _mm_cmpeq_epi32((V), (V)))
-/// \brief Tests whether the specified bits in a 128-bit integer vector are
+/// Tests whether the specified bits in a 128-bit integer vector are
/// neither all zeros nor all ones.
///
/// \headerfile <x86intrin.h>
@@ -1208,7 +1189,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
/// FALSE otherwise.
#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128((M), (V))
-/// \brief Tests whether the specified bits in a 128-bit integer vector are all
+/// Tests whether the specified bits in a 128-bit integer vector are all
/// zeros.
///
/// \headerfile <x86intrin.h>
@@ -1227,7 +1208,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((M), (V))
/* SSE4 64-bit Packed Integer Comparisons. */
-/// \brief Compares each of the corresponding 64-bit values of the 128-bit
+/// Compares each of the corresponding 64-bit values of the 128-bit
/// integer vectors for equality.
///
/// \headerfile <x86intrin.h>
@@ -1246,7 +1227,7 @@ _mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
}
/* SSE4 Packed Integer Sign-Extension. */
-/// \brief Sign-extends each of the lower eight 8-bit integer elements of a
+/// Sign-extends each of the lower eight 8-bit integer elements of a
/// 128-bit vector of [16 x i8] to 16-bit values and returns them in a
/// 128-bit vector of [8 x i16]. The upper eight elements of the input vector
/// are unused.
@@ -1267,7 +1248,7 @@ _mm_cvtepi8_epi16(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8hi);
}
-/// \brief Sign-extends each of the lower four 8-bit integer elements of a
+/// Sign-extends each of the lower four 8-bit integer elements of a
/// 128-bit vector of [16 x i8] to 32-bit values and returns them in a
/// 128-bit vector of [4 x i32]. The upper twelve elements of the input
/// vector are unused.
@@ -1277,8 +1258,8 @@ _mm_cvtepi8_epi16(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVSXBD / PMOVSXBD </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [16 x i8]. The lower four 8-bit elements are sign-
-/// extended to 32-bit values.
+/// A 128-bit vector of [16 x i8]. The lower four 8-bit elements are
+/// sign-extended to 32-bit values.
/// \returns A 128-bit vector of [4 x i32] containing the sign-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi32(__m128i __V)
@@ -1288,7 +1269,7 @@ _mm_cvtepi8_epi32(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3), __v4si);
}
-/// \brief Sign-extends each of the lower two 8-bit integer elements of a
+/// Sign-extends each of the lower two 8-bit integer elements of a
/// 128-bit integer vector of [16 x i8] to 64-bit values and returns them in
/// a 128-bit vector of [2 x i64]. The upper fourteen elements of the input
/// vector are unused.
@@ -1298,8 +1279,8 @@ _mm_cvtepi8_epi32(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVSXBQ / PMOVSXBQ </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [16 x i8]. The lower two 8-bit elements are sign-
-/// extended to 64-bit values.
+/// A 128-bit vector of [16 x i8]. The lower two 8-bit elements are
+/// sign-extended to 64-bit values.
/// \returns A 128-bit vector of [2 x i64] containing the sign-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi64(__m128i __V)
@@ -1309,7 +1290,7 @@ _mm_cvtepi8_epi64(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1), __v2di);
}
-/// \brief Sign-extends each of the lower four 16-bit integer elements of a
+/// Sign-extends each of the lower four 16-bit integer elements of a
/// 128-bit integer vector of [8 x i16] to 32-bit values and returns them in
/// a 128-bit vector of [4 x i32]. The upper four elements of the input
/// vector are unused.
@@ -1319,8 +1300,8 @@ _mm_cvtepi8_epi64(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVSXWD / PMOVSXWD </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [8 x i16]. The lower four 16-bit elements are sign-
-/// extended to 32-bit values.
+/// A 128-bit vector of [8 x i16]. The lower four 16-bit elements are
+/// sign-extended to 32-bit values.
/// \returns A 128-bit vector of [4 x i32] containing the sign-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi16_epi32(__m128i __V)
@@ -1328,7 +1309,7 @@ _mm_cvtepi16_epi32(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1, 2, 3), __v4si);
}
-/// \brief Sign-extends each of the lower two 16-bit integer elements of a
+/// Sign-extends each of the lower two 16-bit integer elements of a
/// 128-bit integer vector of [8 x i16] to 64-bit values and returns them in
/// a 128-bit vector of [2 x i64]. The upper six elements of the input
/// vector are unused.
@@ -1338,8 +1319,8 @@ _mm_cvtepi16_epi32(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVSXWQ / PMOVSXWQ </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [8 x i16]. The lower two 16-bit elements are sign-
-/// extended to 64-bit values.
+/// A 128-bit vector of [8 x i16]. The lower two 16-bit elements are
+/// sign-extended to 64-bit values.
/// \returns A 128-bit vector of [2 x i64] containing the sign-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi16_epi64(__m128i __V)
@@ -1347,7 +1328,7 @@ _mm_cvtepi16_epi64(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1), __v2di);
}
-/// \brief Sign-extends each of the lower two 32-bit integer elements of a
+/// Sign-extends each of the lower two 32-bit integer elements of a
/// 128-bit integer vector of [4 x i32] to 64-bit values and returns them in
/// a 128-bit vector of [2 x i64]. The upper two elements of the input vector
/// are unused.
@@ -1357,8 +1338,8 @@ _mm_cvtepi16_epi64(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVSXDQ / PMOVSXDQ </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [4 x i32]. The lower two 32-bit elements are sign-
-/// extended to 64-bit values.
+/// A 128-bit vector of [4 x i32]. The lower two 32-bit elements are
+/// sign-extended to 64-bit values.
/// \returns A 128-bit vector of [2 x i64] containing the sign-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi32_epi64(__m128i __V)
@@ -1367,7 +1348,7 @@ _mm_cvtepi32_epi64(__m128i __V)
}
/* SSE4 Packed Integer Zero-Extension. */
-/// \brief Zero-extends each of the lower eight 8-bit integer elements of a
+/// Zero-extends each of the lower eight 8-bit integer elements of a
/// 128-bit vector of [16 x i8] to 16-bit values and returns them in a
/// 128-bit vector of [8 x i16]. The upper eight elements of the input vector
/// are unused.
@@ -1377,8 +1358,8 @@ _mm_cvtepi32_epi64(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVZXBW / PMOVZXBW </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [16 x i8]. The lower eight 8-bit elements are zero-
-/// extended to 16-bit values.
+/// A 128-bit vector of [16 x i8]. The lower eight 8-bit elements are
+/// zero-extended to 16-bit values.
/// \returns A 128-bit vector of [8 x i16] containing the zero-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu8_epi16(__m128i __V)
@@ -1386,7 +1367,7 @@ _mm_cvtepu8_epi16(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8hi);
}
-/// \brief Zero-extends each of the lower four 8-bit integer elements of a
+/// Zero-extends each of the lower four 8-bit integer elements of a
/// 128-bit vector of [16 x i8] to 32-bit values and returns them in a
/// 128-bit vector of [4 x i32]. The upper twelve elements of the input
/// vector are unused.
@@ -1396,8 +1377,8 @@ _mm_cvtepu8_epi16(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVZXBD / PMOVZXBD </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [16 x i8]. The lower four 8-bit elements are zero-
-/// extended to 32-bit values.
+/// A 128-bit vector of [16 x i8]. The lower four 8-bit elements are
+/// zero-extended to 32-bit values.
/// \returns A 128-bit vector of [4 x i32] containing the zero-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu8_epi32(__m128i __V)
@@ -1405,7 +1386,7 @@ _mm_cvtepu8_epi32(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1, 2, 3), __v4si);
}
-/// \brief Zero-extends each of the lower two 8-bit integer elements of a
+/// Zero-extends each of the lower two 8-bit integer elements of a
/// 128-bit integer vector of [16 x i8] to 64-bit values and returns them in
/// a 128-bit vector of [2 x i64]. The upper fourteen elements of the input
/// vector are unused.
@@ -1415,8 +1396,8 @@ _mm_cvtepu8_epi32(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVZXBQ / PMOVZXBQ </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [16 x i8]. The lower two 8-bit elements are zero-
-/// extended to 64-bit values.
+/// A 128-bit vector of [16 x i8]. The lower two 8-bit elements are
+/// zero-extended to 64-bit values.
/// \returns A 128-bit vector of [2 x i64] containing the zero-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu8_epi64(__m128i __V)
@@ -1424,7 +1405,7 @@ _mm_cvtepu8_epi64(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1), __v2di);
}
-/// \brief Zero-extends each of the lower four 16-bit integer elements of a
+/// Zero-extends each of the lower four 16-bit integer elements of a
/// 128-bit integer vector of [8 x i16] to 32-bit values and returns them in
/// a 128-bit vector of [4 x i32]. The upper four elements of the input
/// vector are unused.
@@ -1434,8 +1415,8 @@ _mm_cvtepu8_epi64(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVZXWD / PMOVZXWD </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [8 x i16]. The lower four 16-bit elements are zero-
-/// extended to 32-bit values.
+/// A 128-bit vector of [8 x i16]. The lower four 16-bit elements are
+/// zero-extended to 32-bit values.
/// \returns A 128-bit vector of [4 x i32] containing the zero-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu16_epi32(__m128i __V)
@@ -1443,7 +1424,7 @@ _mm_cvtepu16_epi32(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hu)__V, (__v8hu)__V, 0, 1, 2, 3), __v4si);
}
-/// \brief Zero-extends each of the lower two 16-bit integer elements of a
+/// Zero-extends each of the lower two 16-bit integer elements of a
/// 128-bit integer vector of [8 x i16] to 64-bit values and returns them in
/// a 128-bit vector of [2 x i64]. The upper six elements of the input vector
/// are unused.
@@ -1453,8 +1434,8 @@ _mm_cvtepu16_epi32(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVZXWQ / PMOVZXWQ </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [8 x i16]. The lower two 16-bit elements are zero-
-/// extended to 64-bit values.
+/// A 128-bit vector of [8 x i16]. The lower two 16-bit elements are
+/// zero-extended to 64-bit values.
/// \returns A 128-bit vector of [2 x i64] containing the zero-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu16_epi64(__m128i __V)
@@ -1462,7 +1443,7 @@ _mm_cvtepu16_epi64(__m128i __V)
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hu)__V, (__v8hu)__V, 0, 1), __v2di);
}
-/// \brief Zero-extends each of the lower two 32-bit integer elements of a
+/// Zero-extends each of the lower two 32-bit integer elements of a
/// 128-bit integer vector of [4 x i32] to 64-bit values and returns them in
/// a 128-bit vector of [2 x i64]. The upper two elements of the input vector
/// are unused.
@@ -1472,8 +1453,8 @@ _mm_cvtepu16_epi64(__m128i __V)
/// This intrinsic corresponds to the <c> VPMOVZXDQ / PMOVZXDQ </c> instruction.
///
/// \param __V
-/// A 128-bit vector of [4 x i32]. The lower two 32-bit elements are zero-
-/// extended to 64-bit values.
+/// A 128-bit vector of [4 x i32]. The lower two 32-bit elements are
+/// zero-extended to 64-bit values.
/// \returns A 128-bit vector of [2 x i64] containing the zero-extended values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu32_epi64(__m128i __V)
@@ -1482,7 +1463,7 @@ _mm_cvtepu32_epi64(__m128i __V)
}
/* SSE4 Pack with Unsigned Saturation. */
-/// \brief Converts 32-bit signed integers from both 128-bit integer vector
+/// Converts 32-bit signed integers from both 128-bit integer vector
/// operands into 16-bit unsigned integers, and returns the packed result.
/// Values greater than 0xFFFF are saturated to 0xFFFF. Values less than
/// 0x0000 are saturated to 0x0000.
@@ -1511,7 +1492,7 @@ _mm_packus_epi32(__m128i __V1, __m128i __V2)
}
/* SSE4 Multiple Packed Sums of Absolute Difference. */
-/// \brief Subtracts 8-bit unsigned integer values and computes the absolute
+/// Subtracts 8-bit unsigned integer values and computes the absolute
/// values of the differences to the corresponding bits in the destination.
/// Then sums of the absolute differences are returned according to the bit
/// fields in the immediate operand.
@@ -1534,23 +1515,23 @@ _mm_packus_epi32(__m128i __V1, __m128i __V2)
/// \code
/// // M2 represents bit 2 of the immediate operand
/// // M10 represents bits [1:0] of the immediate operand
-/// i = M2 * 4
-/// j = M10 * 4
+/// i = M2 * 4;
+/// j = M10 * 4;
/// for (k = 0; k < 8; k = k + 1) {
-/// d0 = abs(X[i + k + 0] - Y[j + 0])
-/// d1 = abs(X[i + k + 1] - Y[j + 1])
-/// d2 = abs(X[i + k + 2] - Y[j + 2])
-/// d3 = abs(X[i + k + 3] - Y[j + 3])
-/// r[k] = d0 + d1 + d2 + d3
+/// d0 = abs(X[i + k + 0] - Y[j + 0]);
+/// d1 = abs(X[i + k + 1] - Y[j + 1]);
+/// d2 = abs(X[i + k + 2] - Y[j + 2]);
+/// d3 = abs(X[i + k + 3] - Y[j + 3]);
+/// r[k] = d0 + d1 + d2 + d3;
/// }
/// \endcode
/// \returns A 128-bit integer vector containing the sums of the sets of
/// absolute differences between both operands.
-#define _mm_mpsadbw_epu8(X, Y, M) __extension__ ({ \
+#define _mm_mpsadbw_epu8(X, Y, M) \
(__m128i) __builtin_ia32_mpsadbw128((__v16qi)(__m128i)(X), \
- (__v16qi)(__m128i)(Y), (M)); })
+ (__v16qi)(__m128i)(Y), (M))
-/// \brief Finds the minimum unsigned 16-bit element in the input 128-bit
+/// Finds the minimum unsigned 16-bit element in the input 128-bit
/// vector of [8 x u16] and returns it and along with its index.
///
/// \headerfile <x86intrin.h>
@@ -1604,7 +1585,7 @@ _mm_minpos_epu16(__m128i __V)
#define _SIDD_UNIT_MASK 0x40
/* SSE4.2 Packed Comparison Intrinsics. */
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns a 128-bit integer vector representing the result
/// mask of the comparison.
@@ -1660,7 +1641,7 @@ _mm_minpos_epu16(__m128i __V)
(__m128i)__builtin_ia32_pcmpistrm128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns an integer representing the result index of the
/// comparison.
@@ -1714,7 +1695,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpistri128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns a 128-bit integer vector representing the result
/// mask of the comparison.
@@ -1775,7 +1756,7 @@ _mm_minpos_epu16(__m128i __V)
(__v16qi)(__m128i)(B), (int)(LB), \
(int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns an integer representing the result index of the
/// comparison.
@@ -1835,7 +1816,7 @@ _mm_minpos_epu16(__m128i __V)
(int)(M))
/* SSE4.2 Packed Comparison Intrinsics and EFlag Reading. */
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the bit mask is zero and the length of the
/// string in \a B is the maximum, otherwise, returns 0.
@@ -1885,7 +1866,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpistria128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the bit mask is non-zero, otherwise, returns
/// 0.
@@ -1934,7 +1915,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpistric128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns bit 0 of the resulting bit mask.
///
@@ -1982,7 +1963,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpistrio128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the length of the string in \a A is less than
/// the maximum, otherwise, returns 0.
@@ -2032,7 +2013,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpistris128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with implicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the length of the string in \a B is less than
/// the maximum, otherwise, returns 0.
@@ -2082,7 +2063,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpistriz128((__v16qi)(__m128i)(A), \
(__v16qi)(__m128i)(B), (int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the bit mask is zero and the length of the
/// string in \a B is the maximum, otherwise, returns 0.
@@ -2137,7 +2118,7 @@ _mm_minpos_epu16(__m128i __V)
(__v16qi)(__m128i)(B), (int)(LB), \
(int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the resulting mask is non-zero, otherwise,
/// returns 0.
@@ -2191,7 +2172,7 @@ _mm_minpos_epu16(__m128i __V)
(__v16qi)(__m128i)(B), (int)(LB), \
(int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns bit 0 of the resulting bit mask.
///
@@ -2244,7 +2225,7 @@ _mm_minpos_epu16(__m128i __V)
(__v16qi)(__m128i)(B), (int)(LB), \
(int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the length of the string in \a A is less than
/// the maximum, otherwise, returns 0.
@@ -2299,7 +2280,7 @@ _mm_minpos_epu16(__m128i __V)
(__v16qi)(__m128i)(B), (int)(LB), \
(int)(M))
-/// \brief Uses the immediate operand \a M to perform a comparison of string
+/// Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns 1 if the length of the string in \a B is less than
/// the maximum, otherwise, returns 0.
@@ -2354,7 +2335,7 @@ _mm_minpos_epu16(__m128i __V)
(int)(M))
/* SSE4.2 Compare Packed Data -- Greater Than. */
-/// \brief Compares each of the corresponding 64-bit values of the 128-bit
+/// Compares each of the corresponding 64-bit values of the 128-bit
/// integer vectors to determine if the values in the first operand are
/// greater than those in the second operand.
///
@@ -2374,7 +2355,7 @@ _mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
}
/* SSE4.2 Accumulate CRC32. */
-/// \brief Adds the unsigned integer operand to the CRC-32C checksum of the
+/// Adds the unsigned integer operand to the CRC-32C checksum of the
/// unsigned char operand.
///
/// \headerfile <x86intrin.h>
@@ -2394,7 +2375,7 @@ _mm_crc32_u8(unsigned int __C, unsigned char __D)
return __builtin_ia32_crc32qi(__C, __D);
}
-/// \brief Adds the unsigned integer operand to the CRC-32C checksum of the
+/// Adds the unsigned integer operand to the CRC-32C checksum of the
/// unsigned short operand.
///
/// \headerfile <x86intrin.h>
@@ -2414,7 +2395,7 @@ _mm_crc32_u16(unsigned int __C, unsigned short __D)
return __builtin_ia32_crc32hi(__C, __D);
}
-/// \brief Adds the first unsigned integer operand to the CRC-32C checksum of
+/// Adds the first unsigned integer operand to the CRC-32C checksum of
/// the second unsigned integer operand.
///
/// \headerfile <x86intrin.h>
@@ -2435,7 +2416,7 @@ _mm_crc32_u32(unsigned int __C, unsigned int __D)
}
#ifdef __x86_64__
-/// \brief Adds the unsigned integer operand to the CRC-32C checksum of the
+/// Adds the unsigned integer operand to the CRC-32C checksum of the
/// unsigned 64-bit integer operand.
///
/// \headerfile <x86intrin.h>
@@ -2458,8 +2439,6 @@ _mm_crc32_u64(unsigned long long __C, unsigned long long __D)
#undef __DEFAULT_FN_ATTRS
-#ifdef __POPCNT__
#include <popcntintrin.h>
-#endif
-#endif /* _SMMINTRIN_H */
+#endif /* __SMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdint.h b/contrib/llvm/tools/clang/lib/Headers/stdint.h
index c48815314b51..0afcca3a9daa 100644
--- a/contrib/llvm/tools/clang/lib/Headers/stdint.h
+++ b/contrib/llvm/tools/clang/lib/Headers/stdint.h
@@ -88,7 +88,7 @@
*
* To accommodate targets that are missing types that are exactly 8, 16, 32, or
* 64 bits wide, this implementation takes an approach of cascading
- * redefintions, redefining __int_leastN_t to successively smaller exact-width
+ * redefinitions, redefining __int_leastN_t to successively smaller exact-width
* types. It is therefore important that the types are defined in order of
* descending widths.
*
@@ -461,7 +461,7 @@ typedef __UINTMAX_TYPE__ uintmax_t;
* As in the type definitions, this section takes an approach of
* successive-shrinking to determine which limits to use for the standard (8,
* 16, 32, 64) bit widths when they don't have exact representations. It is
- * therefore important that the defintions be kept in order of decending
+ * therefore important that the definitions be kept in order of decending
* widths.
*
* Note that C++ should not check __STDC_LIMIT_MACROS here, contrary to the
diff --git a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
index 042bfc7e3b0d..734cd391be60 100644
--- a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
@@ -27,9 +27,10 @@
#include <pmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("ssse3")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("ssse3"), __min_vector_width__(64)))
+#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,ssse3"), __min_vector_width__(64)))
-/// \brief Computes the absolute value of each of the packed 8-bit signed
+/// Computes the absolute value of each of the packed 8-bit signed
/// integers in the source operand and stores the 8-bit unsigned integer
/// results in the destination.
///
@@ -41,13 +42,13 @@
/// A 64-bit vector of [8 x i8].
/// \returns A 64-bit integer vector containing the absolute values of the
/// elements in the operand.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_abs_pi8(__m64 __a)
{
return (__m64)__builtin_ia32_pabsb((__v8qi)__a);
}
-/// \brief Computes the absolute value of each of the packed 8-bit signed
+/// Computes the absolute value of each of the packed 8-bit signed
/// integers in the source operand and stores the 8-bit unsigned integer
/// results in the destination.
///
@@ -65,7 +66,7 @@ _mm_abs_epi8(__m128i __a)
return (__m128i)__builtin_ia32_pabsb128((__v16qi)__a);
}
-/// \brief Computes the absolute value of each of the packed 16-bit signed
+/// Computes the absolute value of each of the packed 16-bit signed
/// integers in the source operand and stores the 16-bit unsigned integer
/// results in the destination.
///
@@ -77,13 +78,13 @@ _mm_abs_epi8(__m128i __a)
/// A 64-bit vector of [4 x i16].
/// \returns A 64-bit integer vector containing the absolute values of the
/// elements in the operand.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_abs_pi16(__m64 __a)
{
return (__m64)__builtin_ia32_pabsw((__v4hi)__a);
}
-/// \brief Computes the absolute value of each of the packed 16-bit signed
+/// Computes the absolute value of each of the packed 16-bit signed
/// integers in the source operand and stores the 16-bit unsigned integer
/// results in the destination.
///
@@ -101,7 +102,7 @@ _mm_abs_epi16(__m128i __a)
return (__m128i)__builtin_ia32_pabsw128((__v8hi)__a);
}
-/// \brief Computes the absolute value of each of the packed 32-bit signed
+/// Computes the absolute value of each of the packed 32-bit signed
/// integers in the source operand and stores the 32-bit unsigned integer
/// results in the destination.
///
@@ -113,13 +114,13 @@ _mm_abs_epi16(__m128i __a)
/// A 64-bit vector of [2 x i32].
/// \returns A 64-bit integer vector containing the absolute values of the
/// elements in the operand.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_abs_pi32(__m64 __a)
{
return (__m64)__builtin_ia32_pabsd((__v2si)__a);
}
-/// \brief Computes the absolute value of each of the packed 32-bit signed
+/// Computes the absolute value of each of the packed 32-bit signed
/// integers in the source operand and stores the 32-bit unsigned integer
/// results in the destination.
///
@@ -137,7 +138,7 @@ _mm_abs_epi32(__m128i __a)
return (__m128i)__builtin_ia32_pabsd128((__v4si)__a);
}
-/// \brief Concatenates the two 128-bit integer vector operands, and
+/// Concatenates the two 128-bit integer vector operands, and
/// right-shifts the result by the number of bytes specified in the immediate
/// operand.
///
@@ -157,11 +158,11 @@ _mm_abs_epi32(__m128i __a)
/// An immediate operand specifying how many bytes to right-shift the result.
/// \returns A 128-bit integer vector containing the concatenated right-shifted
/// value.
-#define _mm_alignr_epi8(a, b, n) __extension__ ({ \
+#define _mm_alignr_epi8(a, b, n) \
(__m128i)__builtin_ia32_palignr128((__v16qi)(__m128i)(a), \
- (__v16qi)(__m128i)(b), (n)); })
+ (__v16qi)(__m128i)(b), (n))
-/// \brief Concatenates the two 64-bit integer vector operands, and right-shifts
+/// Concatenates the two 64-bit integer vector operands, and right-shifts
/// the result by the number of bytes specified in the immediate operand.
///
/// \headerfile <x86intrin.h>
@@ -180,10 +181,10 @@ _mm_abs_epi32(__m128i __a)
/// An immediate operand specifying how many bytes to right-shift the result.
/// \returns A 64-bit integer vector containing the concatenated right-shifted
/// value.
-#define _mm_alignr_pi8(a, b, n) __extension__ ({ \
- (__m64)__builtin_ia32_palignr((__v8qi)(__m64)(a), (__v8qi)(__m64)(b), (n)); })
+#define _mm_alignr_pi8(a, b, n) \
+ (__m64)__builtin_ia32_palignr((__v8qi)(__m64)(a), (__v8qi)(__m64)(b), (n))
-/// \brief Horizontally adds the adjacent pairs of values contained in 2 packed
+/// Horizontally adds the adjacent pairs of values contained in 2 packed
/// 128-bit vectors of [8 x i16].
///
/// \headerfile <x86intrin.h>
@@ -206,7 +207,7 @@ _mm_hadd_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_phaddw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in 2 packed
+/// Horizontally adds the adjacent pairs of values contained in 2 packed
/// 128-bit vectors of [4 x i32].
///
/// \headerfile <x86intrin.h>
@@ -229,7 +230,7 @@ _mm_hadd_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_phaddd128((__v4si)__a, (__v4si)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in 2 packed
+/// Horizontally adds the adjacent pairs of values contained in 2 packed
/// 64-bit vectors of [4 x i16].
///
/// \headerfile <x86intrin.h>
@@ -246,13 +247,13 @@ _mm_hadd_epi32(__m128i __a, __m128i __b)
/// destination.
/// \returns A 64-bit vector of [4 x i16] containing the horizontal sums of both
/// operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_hadd_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phaddw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in 2 packed
+/// Horizontally adds the adjacent pairs of values contained in 2 packed
/// 64-bit vectors of [2 x i32].
///
/// \headerfile <x86intrin.h>
@@ -269,15 +270,16 @@ _mm_hadd_pi16(__m64 __a, __m64 __b)
/// destination.
/// \returns A 64-bit vector of [2 x i32] containing the horizontal sums of both
/// operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_hadd_pi32(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phaddd((__v2si)__a, (__v2si)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in 2 packed
-/// 128-bit vectors of [8 x i16]. Positive sums greater than 7FFFh are
-/// saturated to 7FFFh. Negative sums less than 8000h are saturated to 8000h.
+/// Horizontally adds the adjacent pairs of values contained in 2 packed
+/// 128-bit vectors of [8 x i16]. Positive sums greater than 0x7FFF are
+/// saturated to 0x7FFF. Negative sums less than 0x8000 are saturated to
+/// 0x8000.
///
/// \headerfile <x86intrin.h>
///
@@ -299,9 +301,10 @@ _mm_hadds_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_phaddsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Horizontally adds the adjacent pairs of values contained in 2 packed
-/// 64-bit vectors of [4 x i16]. Positive sums greater than 7FFFh are
-/// saturated to 7FFFh. Negative sums less than 8000h are saturated to 8000h.
+/// Horizontally adds the adjacent pairs of values contained in 2 packed
+/// 64-bit vectors of [4 x i16]. Positive sums greater than 0x7FFF are
+/// saturated to 0x7FFF. Negative sums less than 0x8000 are saturated to
+/// 0x8000.
///
/// \headerfile <x86intrin.h>
///
@@ -317,13 +320,13 @@ _mm_hadds_epi16(__m128i __a, __m128i __b)
/// destination.
/// \returns A 64-bit vector of [4 x i16] containing the horizontal saturated
/// sums of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_hadds_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phaddsw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in 2
+/// Horizontally subtracts the adjacent pairs of values contained in 2
/// packed 128-bit vectors of [8 x i16].
///
/// \headerfile <x86intrin.h>
@@ -346,7 +349,7 @@ _mm_hsub_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_phsubw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in 2
+/// Horizontally subtracts the adjacent pairs of values contained in 2
/// packed 128-bit vectors of [4 x i32].
///
/// \headerfile <x86intrin.h>
@@ -369,7 +372,7 @@ _mm_hsub_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_phsubd128((__v4si)__a, (__v4si)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in 2
+/// Horizontally subtracts the adjacent pairs of values contained in 2
/// packed 64-bit vectors of [4 x i16].
///
/// \headerfile <x86intrin.h>
@@ -386,13 +389,13 @@ _mm_hsub_epi32(__m128i __a, __m128i __b)
/// the destination.
/// \returns A 64-bit vector of [4 x i16] containing the horizontal differences
/// of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_hsub_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phsubw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in 2
+/// Horizontally subtracts the adjacent pairs of values contained in 2
/// packed 64-bit vectors of [2 x i32].
///
/// \headerfile <x86intrin.h>
@@ -409,16 +412,16 @@ _mm_hsub_pi16(__m64 __a, __m64 __b)
/// the destination.
/// \returns A 64-bit vector of [2 x i32] containing the horizontal differences
/// of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_hsub_pi32(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phsubd((__v2si)__a, (__v2si)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in 2
+/// Horizontally subtracts the adjacent pairs of values contained in 2
/// packed 128-bit vectors of [8 x i16]. Positive differences greater than
-/// 7FFFh are saturated to 7FFFh. Negative differences less than 8000h are
-/// saturated to 8000h.
+/// 0x7FFF are saturated to 0x7FFF. Negative differences less than 0x8000 are
+/// saturated to 0x8000.
///
/// \headerfile <x86intrin.h>
///
@@ -440,10 +443,10 @@ _mm_hsubs_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_phsubsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Horizontally subtracts the adjacent pairs of values contained in 2
+/// Horizontally subtracts the adjacent pairs of values contained in 2
/// packed 64-bit vectors of [4 x i16]. Positive differences greater than
-/// 7FFFh are saturated to 7FFFh. Negative differences less than 8000h are
-/// saturated to 8000h.
+/// 0x7FFF are saturated to 0x7FFF. Negative differences less than 0x8000 are
+/// saturated to 0x8000.
///
/// \headerfile <x86intrin.h>
///
@@ -459,13 +462,13 @@ _mm_hsubs_epi16(__m128i __a, __m128i __b)
/// the destination.
/// \returns A 64-bit vector of [4 x i16] containing the horizontal saturated
/// differences of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_hsubs_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phsubsw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Multiplies corresponding pairs of packed 8-bit unsigned integer
+/// Multiplies corresponding pairs of packed 8-bit unsigned integer
/// values contained in the first source operand and packed 8-bit signed
/// integer values contained in the second source operand, adds pairs of
/// contiguous products with signed saturation, and writes the 16-bit sums to
@@ -499,7 +502,7 @@ _mm_maddubs_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmaddubsw128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Multiplies corresponding pairs of packed 8-bit unsigned integer
+/// Multiplies corresponding pairs of packed 8-bit unsigned integer
/// values contained in the first source operand and packed 8-bit signed
/// integer values contained in the second source operand, adds pairs of
/// contiguous products with signed saturation, and writes the 16-bit sums to
@@ -523,13 +526,13 @@ _mm_maddubs_epi16(__m128i __a, __m128i __b)
/// \a R1 := (\a __a2 * \a __b2) + (\a __a3 * \a __b3) \n
/// \a R2 := (\a __a4 * \a __b4) + (\a __a5 * \a __b5) \n
/// \a R3 := (\a __a6 * \a __b6) + (\a __a7 * \a __b7)
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_maddubs_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmaddubsw((__v8qi)__a, (__v8qi)__b);
}
-/// \brief Multiplies packed 16-bit signed integer values, truncates the 32-bit
+/// Multiplies packed 16-bit signed integer values, truncates the 32-bit
/// products to the 18 most significant bits by right-shifting, rounds the
/// truncated value by adding 1, and writes bits [16:1] to the destination.
///
@@ -549,7 +552,7 @@ _mm_mulhrs_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pmulhrsw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Multiplies packed 16-bit signed integer values, truncates the 32-bit
+/// Multiplies packed 16-bit signed integer values, truncates the 32-bit
/// products to the 18 most significant bits by right-shifting, rounds the
/// truncated value by adding 1, and writes bits [16:1] to the destination.
///
@@ -563,13 +566,13 @@ _mm_mulhrs_epi16(__m128i __a, __m128i __b)
/// A 64-bit vector of [4 x i16] containing one of the source operands.
/// \returns A 64-bit vector of [4 x i16] containing the rounded and scaled
/// products of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_mulhrs_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmulhrsw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Copies the 8-bit integers from a 128-bit integer vector to the
+/// Copies the 8-bit integers from a 128-bit integer vector to the
/// destination or clears 8-bit values in the destination, as specified by
/// the second source operand.
///
@@ -595,7 +598,7 @@ _mm_shuffle_epi8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_pshufb128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief Copies the 8-bit integers from a 64-bit integer vector to the
+/// Copies the 8-bit integers from a 64-bit integer vector to the
/// destination or clears 8-bit values in the destination, as specified by
/// the second source operand.
///
@@ -614,13 +617,13 @@ _mm_shuffle_epi8(__m128i __a, __m128i __b)
/// destination. \n
/// Bits [3:0] select the source byte to be copied.
/// \returns A 64-bit integer vector containing the copied or cleared values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_shuffle_pi8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pshufb((__v8qi)__a, (__v8qi)__b);
}
-/// \brief For each 8-bit integer in the first source operand, perform one of
+/// For each 8-bit integer in the first source operand, perform one of
/// the following actions as specified by the second source operand.
///
/// If the byte in the second source is negative, calculate the two's
@@ -646,7 +649,7 @@ _mm_sign_epi8(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psignb128((__v16qi)__a, (__v16qi)__b);
}
-/// \brief For each 16-bit integer in the first source operand, perform one of
+/// For each 16-bit integer in the first source operand, perform one of
/// the following actions as specified by the second source operand.
///
/// If the word in the second source is negative, calculate the two's
@@ -672,7 +675,7 @@ _mm_sign_epi16(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psignw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief For each 32-bit integer in the first source operand, perform one of
+/// For each 32-bit integer in the first source operand, perform one of
/// the following actions as specified by the second source operand.
///
/// If the doubleword in the second source is negative, calculate the two's
@@ -698,7 +701,7 @@ _mm_sign_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_ia32_psignd128((__v4si)__a, (__v4si)__b);
}
-/// \brief For each 8-bit integer in the first source operand, perform one of
+/// For each 8-bit integer in the first source operand, perform one of
/// the following actions as specified by the second source operand.
///
/// If the byte in the second source is negative, calculate the two's
@@ -718,13 +721,13 @@ _mm_sign_epi32(__m128i __a, __m128i __b)
/// A 64-bit integer vector containing control bytes corresponding to
/// positions in the destination.
/// \returns A 64-bit integer vector containing the resultant values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_sign_pi8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psignb((__v8qi)__a, (__v8qi)__b);
}
-/// \brief For each 16-bit integer in the first source operand, perform one of
+/// For each 16-bit integer in the first source operand, perform one of
/// the following actions as specified by the second source operand.
///
/// If the word in the second source is negative, calculate the two's
@@ -744,13 +747,13 @@ _mm_sign_pi8(__m64 __a, __m64 __b)
/// A 64-bit integer vector containing control words corresponding to
/// positions in the destination.
/// \returns A 64-bit integer vector containing the resultant values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_sign_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psignw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief For each 32-bit integer in the first source operand, perform one of
+/// For each 32-bit integer in the first source operand, perform one of
/// the following actions as specified by the second source operand.
///
/// If the doubleword in the second source is negative, calculate the two's
@@ -770,12 +773,13 @@ _mm_sign_pi16(__m64 __a, __m64 __b)
/// A 64-bit integer vector containing two control doublewords corresponding
/// to positions in the destination.
/// \returns A 64-bit integer vector containing the resultant values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_sign_pi32(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psignd((__v2si)__a, (__v2si)__b);
}
#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS_MMX
#endif /* __TMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/unwind.h b/contrib/llvm/tools/clang/lib/Headers/unwind.h
index 345fa4d0c193..0e8317e5b9d9 100644
--- a/contrib/llvm/tools/clang/lib/Headers/unwind.h
+++ b/contrib/llvm/tools/clang/lib/Headers/unwind.h
@@ -154,8 +154,12 @@ struct _Unwind_Control_Block {
struct _Unwind_Exception {
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
+#if !defined (__USING_SJLJ_EXCEPTIONS__) && defined (__SEH__)
+ _Unwind_Word private_[6];
+#else
_Unwind_Word private_1;
_Unwind_Word private_2;
+#endif
/* The Itanium ABI requires that _Unwind_Exception objects are "double-word
* aligned". GCC has interpreted this to mean "use the maximum useful
* alignment for the target"; so do we. */
diff --git a/contrib/llvm/tools/clang/lib/Headers/vaesintrin.h b/contrib/llvm/tools/clang/lib/Headers/vaesintrin.h
index efbb8a565292..e4174bb82ff0 100644
--- a/contrib/llvm/tools/clang/lib/Headers/vaesintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/vaesintrin.h
@@ -29,10 +29,10 @@
#define __VAESINTRIN_H
/* Default attributes for YMM forms. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("vaes")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("vaes"), __min_vector_width__(256)))
/* Default attributes for ZMM forms. */
-#define __DEFAULT_FN_ATTRS_F __attribute__((__always_inline__, __nodebug__, __target__("avx512f,vaes")))
+#define __DEFAULT_FN_ATTRS_F __attribute__((__always_inline__, __nodebug__, __target__("avx512f,vaes"), __min_vector_width__(512)))
static __inline__ __m256i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/vpclmulqdqintrin.h b/contrib/llvm/tools/clang/lib/Headers/vpclmulqdqintrin.h
index 21cda2221007..86174a457e11 100644
--- a/contrib/llvm/tools/clang/lib/Headers/vpclmulqdqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/vpclmulqdqintrin.h
@@ -28,15 +28,15 @@
#ifndef __VPCLMULQDQINTRIN_H
#define __VPCLMULQDQINTRIN_H
-#define _mm256_clmulepi64_epi128(A, B, I) __extension__ ({ \
+#define _mm256_clmulepi64_epi128(A, B, I) \
(__m256i)__builtin_ia32_pclmulqdq256((__v4di)(__m256i)(A), \
(__v4di)(__m256i)(B), \
- (char)(I)); })
+ (char)(I))
-#define _mm512_clmulepi64_epi128(A, B, I) __extension__ ({ \
+#define _mm512_clmulepi64_epi128(A, B, I) \
(__m512i)__builtin_ia32_pclmulqdq512((__v8di)(__m512i)(A), \
(__v8di)(__m512i)(B), \
- (char)(I)); })
+ (char)(I))
-#endif // __VPCLMULQDQINTRIN_H
+#endif /* __VPCLMULQDQINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/waitpkgintrin.h b/contrib/llvm/tools/clang/lib/Headers/waitpkgintrin.h
new file mode 100644
index 000000000000..e29d6cfa5a51
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/waitpkgintrin.h
@@ -0,0 +1,56 @@
+/*===----------------------- waitpkgintrin.h - WAITPKG --------------------===
+ *
+ * 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <waitpkgintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __WAITPKGINTRIN_H
+#define __WAITPKGINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("waitpkg")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_umonitor (void * __address)
+{
+ __builtin_ia32_umonitor (__address);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_umwait (unsigned int __control, unsigned long long __counter)
+{
+ return __builtin_ia32_umwait (__control,
+ (unsigned int)(__counter >> 32), (unsigned int)__counter);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_tpause (unsigned int __control, unsigned long long __counter)
+{
+ return __builtin_ia32_tpause (__control,
+ (unsigned int)(__counter >> 32), (unsigned int)__counter);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif /* __WAITPKGINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/wbnoinvdintrin.h b/contrib/llvm/tools/clang/lib/Headers/wbnoinvdintrin.h
new file mode 100644
index 000000000000..cad83368dbe7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/wbnoinvdintrin.h
@@ -0,0 +1,38 @@
+/*===-------------- wbnoinvdintrin.h - wbnoinvd 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.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <wbnoinvdintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __WBNOINVDINTRIN_H
+#define __WBNOINVDINTRIN_H
+
+static __inline__ void
+ __attribute__((__always_inline__, __nodebug__, __target__("wbnoinvd")))
+_wbnoinvd (void)
+{
+ __builtin_ia32_wbnoinvd ();
+}
+
+#endif /* __WBNOINVDINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
index a2d931010aea..569a8d838dad 100644
--- a/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
@@ -21,8 +21,8 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef _WMMINTRIN_H
-#define _WMMINTRIN_H
+#ifndef __WMMINTRIN_H
+#define __WMMINTRIN_H
#include <emmintrin.h>
@@ -30,4 +30,4 @@
#include <__wmmintrin_pclmul.h>
-#endif /* _WMMINTRIN_H */
+#endif /* __WMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/x86intrin.h b/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
index 31ee7b82dd53..728c58c3ebbc 100644
--- a/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
@@ -32,26 +32,6 @@
#include <mm3dnow.h>
#endif
-#if !defined(_MSC_VER) || __has_feature(modules) || defined(__BMI__)
-#include <bmiintrin.h>
-#endif
-
-#if !defined(_MSC_VER) || __has_feature(modules) || defined(__BMI2__)
-#include <bmi2intrin.h>
-#endif
-
-#if !defined(_MSC_VER) || __has_feature(modules) || defined(__LZCNT__)
-#include <lzcntintrin.h>
-#endif
-
-#if !defined(_MSC_VER) || __has_feature(modules) || defined(__POPCNT__)
-#include <popcntintrin.h>
-#endif
-
-#if !defined(_MSC_VER) || __has_feature(modules) || defined(__RDSEED__)
-#include <rdseedintrin.h>
-#endif
-
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__PRFCHW__)
#include <prfchwintrin.h>
#endif
@@ -76,10 +56,6 @@
#include <lwpintrin.h>
#endif
-#if !defined(_MSC_VER) || __has_feature(modules) || defined(__F16C__)
-#include <f16cintrin.h>
-#endif
-
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__MWAITX__)
#include <mwaitxintrin.h>
#endif
@@ -88,4 +64,5 @@
#include <clzerointrin.h>
#endif
+
#endif /* __X86INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
index 279c0275d93f..17af17267c83 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
@@ -40,9 +40,10 @@ typedef unsigned int __v4su __attribute__((__vector_size__(16)));
#endif
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse"), __min_vector_width__(64)))
-/// \brief Adds the 32-bit float values in the low-order bits of the operands.
+/// Adds the 32-bit float values in the low-order bits of the operands.
///
/// \headerfile <x86intrin.h>
///
@@ -64,7 +65,7 @@ _mm_add_ss(__m128 __a, __m128 __b)
return __a;
}
-/// \brief Adds two 128-bit vectors of [4 x float], and returns the results of
+/// Adds two 128-bit vectors of [4 x float], and returns the results of
/// the addition.
///
/// \headerfile <x86intrin.h>
@@ -83,7 +84,7 @@ _mm_add_ps(__m128 __a, __m128 __b)
return (__m128)((__v4sf)__a + (__v4sf)__b);
}
-/// \brief Subtracts the 32-bit float value in the low-order bits of the second
+/// Subtracts the 32-bit float value in the low-order bits of the second
/// operand from the corresponding value in the first operand.
///
/// \headerfile <x86intrin.h>
@@ -106,7 +107,7 @@ _mm_sub_ss(__m128 __a, __m128 __b)
return __a;
}
-/// \brief Subtracts each of the values of the second operand from the first
+/// Subtracts each of the values of the second operand from the first
/// operand, both of which are 128-bit vectors of [4 x float] and returns
/// the results of the subtraction.
///
@@ -126,7 +127,7 @@ _mm_sub_ps(__m128 __a, __m128 __b)
return (__m128)((__v4sf)__a - (__v4sf)__b);
}
-/// \brief Multiplies two 32-bit float values in the low-order bits of the
+/// Multiplies two 32-bit float values in the low-order bits of the
/// operands.
///
/// \headerfile <x86intrin.h>
@@ -149,7 +150,7 @@ _mm_mul_ss(__m128 __a, __m128 __b)
return __a;
}
-/// \brief Multiplies two 128-bit vectors of [4 x float] and returns the
+/// Multiplies two 128-bit vectors of [4 x float] and returns the
/// results of the multiplication.
///
/// \headerfile <x86intrin.h>
@@ -168,7 +169,7 @@ _mm_mul_ps(__m128 __a, __m128 __b)
return (__m128)((__v4sf)__a * (__v4sf)__b);
}
-/// \brief Divides the value in the low-order 32 bits of the first operand by
+/// Divides the value in the low-order 32 bits of the first operand by
/// the corresponding value in the second operand.
///
/// \headerfile <x86intrin.h>
@@ -191,7 +192,7 @@ _mm_div_ss(__m128 __a, __m128 __b)
return __a;
}
-/// \brief Divides two 128-bit vectors of [4 x float].
+/// Divides two 128-bit vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -209,7 +210,7 @@ _mm_div_ps(__m128 __a, __m128 __b)
return (__m128)((__v4sf)__a / (__v4sf)__b);
}
-/// \brief Calculates the square root of the value stored in the low-order bits
+/// Calculates the square root of the value stored in the low-order bits
/// of a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -224,11 +225,10 @@ _mm_div_ps(__m128 __a, __m128 __b)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sqrt_ss(__m128 __a)
{
- __m128 __c = __builtin_ia32_sqrtss((__v4sf)__a);
- return (__m128) { __c[0], __a[1], __a[2], __a[3] };
+ return (__m128)__builtin_ia32_sqrtss((__v4sf)__a);
}
-/// \brief Calculates the square roots of the values stored in a 128-bit vector
+/// Calculates the square roots of the values stored in a 128-bit vector
/// of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -245,7 +245,7 @@ _mm_sqrt_ps(__m128 __a)
return __builtin_ia32_sqrtps((__v4sf)__a);
}
-/// \brief Calculates the approximate reciprocal of the value stored in the
+/// Calculates the approximate reciprocal of the value stored in the
/// low-order bits of a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -260,11 +260,10 @@ _mm_sqrt_ps(__m128 __a)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rcp_ss(__m128 __a)
{
- __m128 __c = __builtin_ia32_rcpss((__v4sf)__a);
- return (__m128) { __c[0], __a[1], __a[2], __a[3] };
+ return (__m128)__builtin_ia32_rcpss((__v4sf)__a);
}
-/// \brief Calculates the approximate reciprocals of the values stored in a
+/// Calculates the approximate reciprocals of the values stored in a
/// 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -278,10 +277,10 @@ _mm_rcp_ss(__m128 __a)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rcp_ps(__m128 __a)
{
- return __builtin_ia32_rcpps((__v4sf)__a);
+ return (__m128)__builtin_ia32_rcpps((__v4sf)__a);
}
-/// \brief Calculates the approximate reciprocal of the square root of the value
+/// Calculates the approximate reciprocal of the square root of the value
/// stored in the low-order bits of a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -297,11 +296,10 @@ _mm_rcp_ps(__m128 __a)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rsqrt_ss(__m128 __a)
{
- __m128 __c = __builtin_ia32_rsqrtss((__v4sf)__a);
- return (__m128) { __c[0], __a[1], __a[2], __a[3] };
+ return __builtin_ia32_rsqrtss((__v4sf)__a);
}
-/// \brief Calculates the approximate reciprocals of the square roots of the
+/// Calculates the approximate reciprocals of the square roots of the
/// values stored in a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -318,7 +316,7 @@ _mm_rsqrt_ps(__m128 __a)
return __builtin_ia32_rsqrtps((__v4sf)__a);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands and returns the lesser value in the low-order bits of the
/// vector of [4 x float].
///
@@ -341,7 +339,7 @@ _mm_min_ss(__m128 __a, __m128 __b)
return __builtin_ia32_minss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 128-bit vectors of [4 x float] and returns the lesser
+/// Compares two 128-bit vectors of [4 x float] and returns the lesser
/// of each pair of values.
///
/// \headerfile <x86intrin.h>
@@ -360,7 +358,7 @@ _mm_min_ps(__m128 __a, __m128 __b)
return __builtin_ia32_minps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands and returns the greater value in the low-order bits of a 128-bit
/// vector of [4 x float].
///
@@ -383,7 +381,7 @@ _mm_max_ss(__m128 __a, __m128 __b)
return __builtin_ia32_maxss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 128-bit vectors of [4 x float] and returns the greater
+/// Compares two 128-bit vectors of [4 x float] and returns the greater
/// of each pair of values.
///
/// \headerfile <x86intrin.h>
@@ -402,7 +400,7 @@ _mm_max_ps(__m128 __a, __m128 __b)
return __builtin_ia32_maxps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs a bitwise AND of two 128-bit vectors of [4 x float].
+/// Performs a bitwise AND of two 128-bit vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -420,7 +418,7 @@ _mm_and_ps(__m128 __a, __m128 __b)
return (__m128)((__v4su)__a & (__v4su)__b);
}
-/// \brief Performs a bitwise AND of two 128-bit vectors of [4 x float], using
+/// Performs a bitwise AND of two 128-bit vectors of [4 x float], using
/// the one's complement of the values contained in the first source
/// operand.
///
@@ -442,7 +440,7 @@ _mm_andnot_ps(__m128 __a, __m128 __b)
return (__m128)(~(__v4su)__a & (__v4su)__b);
}
-/// \brief Performs a bitwise OR of two 128-bit vectors of [4 x float].
+/// Performs a bitwise OR of two 128-bit vectors of [4 x float].
///
/// \headerfile <x86intrin.h>
///
@@ -460,7 +458,7 @@ _mm_or_ps(__m128 __a, __m128 __b)
return (__m128)((__v4su)__a | (__v4su)__b);
}
-/// \brief Performs a bitwise exclusive OR of two 128-bit vectors of
+/// Performs a bitwise exclusive OR of two 128-bit vectors of
/// [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -479,7 +477,7 @@ _mm_xor_ps(__m128 __a, __m128 __b)
return (__m128)((__v4su)__a ^ (__v4su)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands for equality and returns the result of the comparison in the
/// low-order bits of a vector [4 x float].
///
@@ -501,7 +499,7 @@ _mm_cmpeq_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpeqss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] for equality.
///
/// \headerfile <x86intrin.h>
@@ -519,7 +517,7 @@ _mm_cmpeq_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpeqps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is less than the
/// corresponding value in the second operand and returns the result of the
/// comparison in the low-order bits of a vector of [4 x float].
@@ -542,7 +540,7 @@ _mm_cmplt_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpltss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are less than those in the second operand.
///
@@ -561,7 +559,7 @@ _mm_cmplt_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpltps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is less than or
/// equal to the corresponding value in the second operand and returns the
/// result of the comparison in the low-order bits of a vector of
@@ -585,7 +583,7 @@ _mm_cmple_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpless((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are less than or equal to those in the second operand.
///
@@ -604,7 +602,7 @@ _mm_cmple_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpleps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is greater than
/// the corresponding value in the second operand and returns the result of
/// the comparison in the low-order bits of a vector of [4 x float].
@@ -629,7 +627,7 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are greater than those in the second operand.
///
@@ -648,7 +646,7 @@ _mm_cmpgt_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpltps((__v4sf)__b, (__v4sf)__a);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is greater than
/// or equal to the corresponding value in the second operand and returns
/// the result of the comparison in the low-order bits of a vector of
@@ -674,7 +672,7 @@ _mm_cmpge_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are greater than or equal to those in the second operand.
///
@@ -693,7 +691,7 @@ _mm_cmpge_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpleps((__v4sf)__b, (__v4sf)__a);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands for inequality and returns the result of the comparison in the
/// low-order bits of a vector of [4 x float].
///
@@ -716,7 +714,7 @@ _mm_cmpneq_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpneqss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] for inequality.
///
/// \headerfile <x86intrin.h>
@@ -735,7 +733,7 @@ _mm_cmpneq_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpneqps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is not less than
/// the corresponding value in the second operand and returns the result of
/// the comparison in the low-order bits of a vector of [4 x float].
@@ -759,7 +757,7 @@ _mm_cmpnlt_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpnltss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are not less than those in the second operand.
///
@@ -779,7 +777,7 @@ _mm_cmpnlt_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpnltps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is not less than
/// or equal to the corresponding value in the second operand and returns
/// the result of the comparison in the low-order bits of a vector of
@@ -804,7 +802,7 @@ _mm_cmpnle_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpnless((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are not less than or equal to those in the second operand.
///
@@ -824,7 +822,7 @@ _mm_cmpnle_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpnleps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is not greater
/// than the corresponding value in the second operand and returns the
/// result of the comparison in the low-order bits of a vector of
@@ -851,7 +849,7 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are not greater than those in the second operand.
///
@@ -871,7 +869,7 @@ _mm_cmpngt_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpnltps((__v4sf)__b, (__v4sf)__a);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is not greater
/// than or equal to the corresponding value in the second operand and
/// returns the result of the comparison in the low-order bits of a vector
@@ -898,7 +896,7 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are not greater than or equal to those in the second operand.
///
@@ -918,7 +916,7 @@ _mm_cmpnge_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpnleps((__v4sf)__b, (__v4sf)__a);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is ordered with
/// respect to the corresponding value in the second operand and returns the
/// result of the comparison in the low-order bits of a vector of
@@ -943,7 +941,7 @@ _mm_cmpord_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpordss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are ordered with respect to those in the second operand.
///
@@ -963,7 +961,7 @@ _mm_cmpord_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpordps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the value in the first operand is unordered
/// with respect to the corresponding value in the second operand and
/// returns the result of the comparison in the low-order bits of a vector
@@ -988,7 +986,7 @@ _mm_cmpunord_ss(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpunordss((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares each of the corresponding 32-bit float values of the
+/// Compares each of the corresponding 32-bit float values of the
/// 128-bit vectors of [4 x float] to determine if the values in the first
/// operand are unordered with respect to those in the second operand.
///
@@ -1008,9 +1006,11 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b)
return (__m128)__builtin_ia32_cmpunordps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands for equality and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c>
@@ -1022,17 +1022,20 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the
+/// two lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comieq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comieq((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the first operand is less than the second
/// operand and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c>
@@ -1044,17 +1047,20 @@ _mm_comieq_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comilt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comilt((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the first operand is less than or equal to the
/// second operand and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
@@ -1065,17 +1071,20 @@ _mm_comilt_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comile_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comile((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the first operand is greater than the second
/// operand and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
@@ -1086,17 +1095,20 @@ _mm_comile_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the
+/// two lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comigt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comigt((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the first operand is greater than or equal to
/// the second operand and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
@@ -1107,17 +1119,20 @@ _mm_comigt_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comige_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comige((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Compares two 32-bit float values in the low-order bits of both
+/// Compares two 32-bit float values in the low-order bits of both
/// operands to determine if the first operand is not equal to the second
/// operand and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 1 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
@@ -1128,17 +1143,20 @@ _mm_comige_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the
+/// two lower 32-bit values is NaN, 1 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comineq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comineq((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs an unordered comparison of two 32-bit float values using
+/// Performs an unordered comparison of two 32-bit float values using
/// the low-order bits of both operands to determine equality and returns
/// the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
@@ -1149,17 +1167,20 @@ _mm_comineq_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomieq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomieq((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs an unordered comparison of two 32-bit float values using
+/// Performs an unordered comparison of two 32-bit float values using
/// the low-order bits of both operands to determine if the first operand is
/// less than the second operand and returns the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
@@ -1170,18 +1191,21 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomilt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomilt((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs an unordered comparison of two 32-bit float values using
+/// Performs an unordered comparison of two 32-bit float values using
/// the low-order bits of both operands to determine if the first operand is
/// less than or equal to the second operand and returns the result of the
/// comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
@@ -1192,18 +1216,21 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomile_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomile((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs an unordered comparison of two 32-bit float values using
+/// Performs an unordered comparison of two 32-bit float values using
/// the low-order bits of both operands to determine if the first operand is
/// greater than the second operand and returns the result of the
/// comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
@@ -1214,18 +1241,21 @@ _mm_ucomile_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomigt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomigt((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs an unordered comparison of two 32-bit float values using
+/// Performs an unordered comparison of two 32-bit float values using
/// the low-order bits of both operands to determine if the first operand is
/// greater than or equal to the second operand and returns the result of
/// the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 0 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
@@ -1236,17 +1266,20 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomige_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomige((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Performs an unordered comparison of two 32-bit float values using
+/// Performs an unordered comparison of two 32-bit float values using
/// the low-order bits of both operands to determine inequality and returns
/// the result of the comparison.
///
+/// If either of the two lower 32-bit values is NaN, 1 is returned.
+///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
@@ -1257,14 +1290,15 @@ _mm_ucomige_ss(__m128 __a, __m128 __b)
/// \param __b
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the comparison.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower 32-bit values is NaN, 1 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomineq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomineq((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Converts a float value contained in the lower 32 bits of a vector of
+/// Converts a float value contained in the lower 32 bits of a vector of
/// [4 x float] into a 32-bit integer.
///
/// \headerfile <x86intrin.h>
@@ -1282,7 +1316,7 @@ _mm_cvtss_si32(__m128 __a)
return __builtin_ia32_cvtss2si((__v4sf)__a);
}
-/// \brief Converts a float value contained in the lower 32 bits of a vector of
+/// Converts a float value contained in the lower 32 bits of a vector of
/// [4 x float] into a 32-bit integer.
///
/// \headerfile <x86intrin.h>
@@ -1302,7 +1336,7 @@ _mm_cvt_ss2si(__m128 __a)
#ifdef __x86_64__
-/// \brief Converts a float value contained in the lower 32 bits of a vector of
+/// Converts a float value contained in the lower 32 bits of a vector of
/// [4 x float] into a 64-bit integer.
///
/// \headerfile <x86intrin.h>
@@ -1322,7 +1356,7 @@ _mm_cvtss_si64(__m128 __a)
#endif
-/// \brief Converts two low-order float values in a 128-bit vector of
+/// Converts two low-order float values in a 128-bit vector of
/// [4 x float] into a 64-bit vector of [2 x i32].
///
/// \headerfile <x86intrin.h>
@@ -1332,13 +1366,13 @@ _mm_cvtss_si64(__m128 __a)
/// \param __a
/// A 128-bit vector of [4 x float].
/// \returns A 64-bit integer vector containing the converted values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvtps_pi32(__m128 __a)
{
return (__m64)__builtin_ia32_cvtps2pi((__v4sf)__a);
}
-/// \brief Converts two low-order float values in a 128-bit vector of
+/// Converts two low-order float values in a 128-bit vector of
/// [4 x float] into a 64-bit vector of [2 x i32].
///
/// \headerfile <x86intrin.h>
@@ -1348,13 +1382,13 @@ _mm_cvtps_pi32(__m128 __a)
/// \param __a
/// A 128-bit vector of [4 x float].
/// \returns A 64-bit integer vector containing the converted values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvt_ps2pi(__m128 __a)
{
return _mm_cvtps_pi32(__a);
}
-/// \brief Converts a float value contained in the lower 32 bits of a vector of
+/// Converts a float value contained in the lower 32 bits of a vector of
/// [4 x float] into a 32-bit integer, truncating the result when it is
/// inexact.
///
@@ -1373,7 +1407,7 @@ _mm_cvttss_si32(__m128 __a)
return __builtin_ia32_cvttss2si((__v4sf)__a);
}
-/// \brief Converts a float value contained in the lower 32 bits of a vector of
+/// Converts a float value contained in the lower 32 bits of a vector of
/// [4 x float] into a 32-bit integer, truncating the result when it is
/// inexact.
///
@@ -1393,7 +1427,7 @@ _mm_cvtt_ss2si(__m128 __a)
}
#ifdef __x86_64__
-/// \brief Converts a float value contained in the lower 32 bits of a vector of
+/// Converts a float value contained in the lower 32 bits of a vector of
/// [4 x float] into a 64-bit integer, truncating the result when it is
/// inexact.
///
@@ -1413,7 +1447,7 @@ _mm_cvttss_si64(__m128 __a)
}
#endif
-/// \brief Converts two low-order float values in a 128-bit vector of
+/// Converts two low-order float values in a 128-bit vector of
/// [4 x float] into a 64-bit vector of [2 x i32], truncating the result
/// when it is inexact.
///
@@ -1425,13 +1459,13 @@ _mm_cvttss_si64(__m128 __a)
/// \param __a
/// A 128-bit vector of [4 x float].
/// \returns A 64-bit integer vector containing the converted values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvttps_pi32(__m128 __a)
{
return (__m64)__builtin_ia32_cvttps2pi((__v4sf)__a);
}
-/// \brief Converts two low-order float values in a 128-bit vector of [4 x
+/// Converts two low-order float values in a 128-bit vector of [4 x
/// float] into a 64-bit vector of [2 x i32], truncating the result when it
/// is inexact.
///
@@ -1442,13 +1476,13 @@ _mm_cvttps_pi32(__m128 __a)
/// \param __a
/// A 128-bit vector of [4 x float].
/// \returns A 64-bit integer vector containing the converted values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvtt_ps2pi(__m128 __a)
{
return _mm_cvttps_pi32(__a);
}
-/// \brief Converts a 32-bit signed integer value into a floating point value
+/// Converts a 32-bit signed integer value into a floating point value
/// and writes it to the lower 32 bits of the destination. The remaining
/// higher order elements of the destination vector are copied from the
/// corresponding elements in the first operand.
@@ -1471,7 +1505,7 @@ _mm_cvtsi32_ss(__m128 __a, int __b)
return __a;
}
-/// \brief Converts a 32-bit signed integer value into a floating point value
+/// Converts a 32-bit signed integer value into a floating point value
/// and writes it to the lower 32 bits of the destination. The remaining
/// higher order elements of the destination are copied from the
/// corresponding elements in the first operand.
@@ -1495,7 +1529,7 @@ _mm_cvt_si2ss(__m128 __a, int __b)
#ifdef __x86_64__
-/// \brief Converts a 64-bit signed integer value into a floating point value
+/// Converts a 64-bit signed integer value into a floating point value
/// and writes it to the lower 32 bits of the destination. The remaining
/// higher order elements of the destination are copied from the
/// corresponding elements in the first operand.
@@ -1520,7 +1554,7 @@ _mm_cvtsi64_ss(__m128 __a, long long __b)
#endif
-/// \brief Converts two elements of a 64-bit vector of [2 x i32] into two
+/// Converts two elements of a 64-bit vector of [2 x i32] into two
/// floating point values and writes them to the lower 64-bits of the
/// destination. The remaining higher order elements of the destination are
/// copied from the corresponding elements in the first operand.
@@ -1537,13 +1571,13 @@ _mm_cvtsi64_ss(__m128 __a, long long __b)
/// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the
/// converted value of the second operand. The upper 64 bits are copied from
/// the upper 64 bits of the first operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpi32_ps(__m128 __a, __m64 __b)
{
return __builtin_ia32_cvtpi2ps((__v4sf)__a, (__v2si)__b);
}
-/// \brief Converts two elements of a 64-bit vector of [2 x i32] into two
+/// Converts two elements of a 64-bit vector of [2 x i32] into two
/// floating point values and writes them to the lower 64-bits of the
/// destination. The remaining higher order elements of the destination are
/// copied from the corresponding elements in the first operand.
@@ -1560,18 +1594,18 @@ _mm_cvtpi32_ps(__m128 __a, __m64 __b)
/// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the
/// converted value from the second operand. The upper 64 bits are copied
/// from the upper 64 bits of the first operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvt_pi2ps(__m128 __a, __m64 __b)
{
return _mm_cvtpi32_ps(__a, __b);
}
-/// \brief Extracts a float value contained in the lower 32 bits of a vector of
+/// Extracts a float value contained in the lower 32 bits of a vector of
/// [4 x float].
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
+/// This intrinsic has no corresponding instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1583,7 +1617,7 @@ _mm_cvtss_f32(__m128 __a)
return __a[0];
}
-/// \brief Loads two packed float values from the address \a __p into the
+/// Loads two packed float values from the address \a __p into the
/// high-order bits of a 128-bit vector of [4 x float]. The low-order bits
/// are copied from the low-order bits of the first operand.
///
@@ -1610,7 +1644,7 @@ _mm_loadh_pi(__m128 __a, const __m64 *__p)
return __builtin_shufflevector(__a, __bb, 0, 1, 4, 5);
}
-/// \brief Loads two packed float values from the address \a __p into the
+/// Loads two packed float values from the address \a __p into the
/// low-order bits of a 128-bit vector of [4 x float]. The high-order bits
/// are copied from the high-order bits of the first operand.
///
@@ -1637,7 +1671,7 @@ _mm_loadl_pi(__m128 __a, const __m64 *__p)
return __builtin_shufflevector(__a, __bb, 4, 5, 2, 3);
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float]. The lower
+/// Constructs a 128-bit floating-point vector of [4 x float]. The lower
/// 32 bits of the vector are initialized with the single-precision
/// floating-point value loaded from a specified memory location. The upper
/// 96 bits are set to zero.
@@ -1659,15 +1693,15 @@ _mm_load_ss(const float *__p)
float __u;
} __attribute__((__packed__, __may_alias__));
float __u = ((struct __mm_load_ss_struct*)__p)->__u;
- return (__m128){ __u, 0, 0, 0 };
+ return __extension__ (__m128){ __u, 0, 0, 0 };
}
-/// \brief Loads a 32-bit float value and duplicates it to all four vector
+/// Loads a 32-bit float value and duplicates it to all four vector
/// elements of a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVSS / MOVSS + shuffling </c>
+/// This intrinsic corresponds to the <c> VBROADCASTSS / MOVSS + shuffling </c>
/// instruction.
///
/// \param __p
@@ -1681,12 +1715,12 @@ _mm_load1_ps(const float *__p)
float __u;
} __attribute__((__packed__, __may_alias__));
float __u = ((struct __mm_load1_ps_struct*)__p)->__u;
- return (__m128){ __u, __u, __u, __u };
+ return __extension__ (__m128){ __u, __u, __u, __u };
}
#define _mm_load_ps1(p) _mm_load1_ps(p)
-/// \brief Loads a 128-bit floating-point vector of [4 x float] from an aligned
+/// Loads a 128-bit floating-point vector of [4 x float] from an aligned
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -1696,14 +1730,14 @@ _mm_load1_ps(const float *__p)
/// \param __p
/// A pointer to a 128-bit memory location. The address of the memory
/// location has to be 128-bit aligned.
-/// \returns A 128-bit vector of [4 x float] containing the loaded valus.
+/// \returns A 128-bit vector of [4 x float] containing the loaded values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_load_ps(const float *__p)
{
return *(__m128*)__p;
}
-/// \brief Loads a 128-bit floating-point vector of [4 x float] from an
+/// Loads a 128-bit floating-point vector of [4 x float] from an
/// unaligned memory location.
///
/// \headerfile <x86intrin.h>
@@ -1723,7 +1757,7 @@ _mm_loadu_ps(const float *__p)
return ((struct __loadu_ps*)__p)->__v;
}
-/// \brief Loads four packed float values, in reverse order, from an aligned
+/// Loads four packed float values, in reverse order, from an aligned
/// memory location to 32-bit elements in a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -1743,7 +1777,7 @@ _mm_loadr_ps(const float *__p)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 3, 2, 1, 0);
}
-/// \brief Create a 128-bit vector of [4 x float] with undefined values.
+/// Create a 128-bit vector of [4 x float] with undefined values.
///
/// \headerfile <x86intrin.h>
///
@@ -1756,7 +1790,7 @@ _mm_undefined_ps(void)
return (__m128)__builtin_ia32_undef128();
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float]. The lower
+/// Constructs a 128-bit floating-point vector of [4 x float]. The lower
/// 32 bits of the vector are initialized with the specified single-precision
/// floating-point value. The upper 96 bits are set to zero.
///
@@ -1773,10 +1807,10 @@ _mm_undefined_ps(void)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ss(float __w)
{
- return (__m128){ __w, 0, 0, 0 };
+ return __extension__ (__m128){ __w, 0, 0, 0 };
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float], with each
+/// Constructs a 128-bit floating-point vector of [4 x float], with each
/// of the four single-precision floating-point vector elements set to the
/// specified single-precision floating-point value.
///
@@ -1791,11 +1825,11 @@ _mm_set_ss(float __w)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set1_ps(float __w)
{
- return (__m128){ __w, __w, __w, __w };
+ return __extension__ (__m128){ __w, __w, __w, __w };
}
/* Microsoft specific. */
-/// \brief Constructs a 128-bit floating-point vector of [4 x float], with each
+/// Constructs a 128-bit floating-point vector of [4 x float], with each
/// of the four single-precision floating-point vector elements set to the
/// specified single-precision floating-point value.
///
@@ -1813,7 +1847,7 @@ _mm_set_ps1(float __w)
return _mm_set1_ps(__w);
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float]
+/// Constructs a 128-bit floating-point vector of [4 x float]
/// initialized with the specified single-precision floating-point values.
///
/// \headerfile <x86intrin.h>
@@ -1837,10 +1871,10 @@ _mm_set_ps1(float __w)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ps(float __z, float __y, float __x, float __w)
{
- return (__m128){ __w, __x, __y, __z };
+ return __extension__ (__m128){ __w, __x, __y, __z };
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float],
+/// Constructs a 128-bit floating-point vector of [4 x float],
/// initialized in reverse order with the specified 32-bit single-precision
/// float-point values.
///
@@ -1865,10 +1899,10 @@ _mm_set_ps(float __z, float __y, float __x, float __w)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_setr_ps(float __z, float __y, float __x, float __w)
{
- return (__m128){ __z, __y, __x, __w };
+ return __extension__ (__m128){ __z, __y, __x, __w };
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float] initialized
+/// Constructs a 128-bit floating-point vector of [4 x float] initialized
/// to zero.
///
/// \headerfile <x86intrin.h>
@@ -1880,15 +1914,15 @@ _mm_setr_ps(float __z, float __y, float __x, float __w)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_setzero_ps(void)
{
- return (__m128){ 0, 0, 0, 0 };
+ return __extension__ (__m128){ 0, 0, 0, 0 };
}
-/// \brief Stores the upper 64 bits of a 128-bit vector of [4 x float] to a
+/// Stores the upper 64 bits of a 128-bit vector of [4 x float] to a
/// memory location.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPEXTRQ / MOVQ </c> instruction.
+/// This intrinsic corresponds to the <c> VPEXTRQ / PEXTRQ </c> instruction.
///
/// \param __p
/// A pointer to a 64-bit memory location.
@@ -1900,7 +1934,7 @@ _mm_storeh_pi(__m64 *__p, __m128 __a)
__builtin_ia32_storehps((__v2si *)__p, (__v4sf)__a);
}
-/// \brief Stores the lower 64 bits of a 128-bit vector of [4 x float] to a
+/// Stores the lower 64 bits of a 128-bit vector of [4 x float] to a
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -1917,7 +1951,7 @@ _mm_storel_pi(__m64 *__p, __m128 __a)
__builtin_ia32_storelps((__v2si *)__p, (__v4sf)__a);
}
-/// \brief Stores the lower 32 bits of a 128-bit vector of [4 x float] to a
+/// Stores the lower 32 bits of a 128-bit vector of [4 x float] to a
/// memory location.
///
/// \headerfile <x86intrin.h>
@@ -1937,7 +1971,7 @@ _mm_store_ss(float *__p, __m128 __a)
((struct __mm_store_ss_struct*)__p)->__u = __a[0];
}
-/// \brief Stores a 128-bit vector of [4 x float] to an unaligned memory
+/// Stores a 128-bit vector of [4 x float] to an unaligned memory
/// location.
///
/// \headerfile <x86intrin.h>
@@ -1958,7 +1992,7 @@ _mm_storeu_ps(float *__p, __m128 __a)
((struct __storeu_ps*)__p)->__v = __a;
}
-/// \brief Stores a 128-bit vector of [4 x float] into an aligned memory
+/// Stores a 128-bit vector of [4 x float] into an aligned memory
/// location.
///
/// \headerfile <x86intrin.h>
@@ -1976,7 +2010,7 @@ _mm_store_ps(float *__p, __m128 __a)
*(__m128*)__p = __a;
}
-/// \brief Stores the lower 32 bits of a 128-bit vector of [4 x float] into
+/// Stores the lower 32 bits of a 128-bit vector of [4 x float] into
/// four contiguous elements in an aligned memory location.
///
/// \headerfile <x86intrin.h>
@@ -1996,7 +2030,7 @@ _mm_store1_ps(float *__p, __m128 __a)
_mm_store_ps(__p, __a);
}
-/// \brief Stores the lower 32 bits of a 128-bit vector of [4 x float] into
+/// Stores the lower 32 bits of a 128-bit vector of [4 x float] into
/// four contiguous elements in an aligned memory location.
///
/// \headerfile <x86intrin.h>
@@ -2012,10 +2046,10 @@ _mm_store1_ps(float *__p, __m128 __a)
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_ps1(float *__p, __m128 __a)
{
- return _mm_store1_ps(__p, __a);
+ _mm_store1_ps(__p, __a);
}
-/// \brief Stores float values from a 128-bit vector of [4 x float] to an
+/// Stores float values from a 128-bit vector of [4 x float] to an
/// aligned memory location in reverse order.
///
/// \headerfile <x86intrin.h>
@@ -2046,7 +2080,7 @@ _mm_storer_ps(float *__p, __m128 __a)
/* FIXME: We have to #define this because "sel" must be a constant integer, and
Sema doesn't do any form of constant propagation yet. */
-/// \brief Loads one cache line of data from the specified address to a location
+/// Loads one cache line of data from the specified address to a location
/// closer to the processor.
///
/// \headerfile <x86intrin.h>
@@ -2074,7 +2108,7 @@ _mm_storer_ps(float *__p, __m128 __a)
((sel) >> 2) & 1, (sel) & 0x3))
#endif
-/// \brief Stores a 64-bit integer in the specified aligned memory location. To
+/// Stores a 64-bit integer in the specified aligned memory location. To
/// minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon).
///
@@ -2086,13 +2120,13 @@ _mm_storer_ps(float *__p, __m128 __a)
/// A pointer to an aligned memory location used to store the register value.
/// \param __a
/// A 64-bit integer containing the value to be stored.
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS_MMX
_mm_stream_pi(__m64 *__p, __m64 __a)
{
__builtin_ia32_movntq(__p, __a);
}
-/// \brief Moves packed float values from a 128-bit vector of [4 x float] to a
+/// Moves packed float values from a 128-bit vector of [4 x float] to a
/// 128-bit aligned memory location. To minimize caching, the data is flagged
/// as non-temporal (unlikely to be used again soon).
///
@@ -2115,7 +2149,7 @@ _mm_stream_ps(float *__p, __m128 __a)
extern "C" {
#endif
-/// \brief Forces strong memory ordering (serialization) between store
+/// Forces strong memory ordering (serialization) between store
/// instructions preceding this instruction and store instructions following
/// this instruction, ensuring the system completes all previous stores
/// before executing subsequent stores.
@@ -2130,7 +2164,7 @@ void _mm_sfence(void);
} // extern "C"
#endif
-/// \brief Extracts 16-bit element from a 64-bit vector of [4 x i16] and
+/// Extracts 16-bit element from a 64-bit vector of [4 x i16] and
/// returns it, as specified by the immediate integer operand.
///
/// \headerfile <x86intrin.h>
@@ -2150,10 +2184,10 @@ void _mm_sfence(void);
/// 2: Bits [47:32] are copied to the destination. \n
/// 3: Bits [63:48] are copied to the destination.
/// \returns A 16-bit integer containing the extracted 16 bits of packed data.
-#define _mm_extract_pi16(a, n) __extension__ ({ \
- (int)__builtin_ia32_vec_ext_v4hi((__m64)a, (int)n); })
+#define _mm_extract_pi16(a, n) \
+ (int)__builtin_ia32_vec_ext_v4hi((__m64)a, (int)n)
-/// \brief Copies data from the 64-bit vector of [4 x i16] to the destination,
+/// Copies data from the 64-bit vector of [4 x i16] to the destination,
/// and inserts the lower 16-bits of an integer operand at the 16-bit offset
/// specified by the immediate operand \a n.
///
@@ -2163,7 +2197,7 @@ void _mm_sfence(void);
/// __m64 _mm_insert_pi16(__m64 a, int d, int n);
/// \endcode
///
-/// This intrinsic corresponds to the <c> VPINSRW / PINSRW </c> instruction.
+/// This intrinsic corresponds to the <c> PINSRW </c> instruction.
///
/// \param a
/// A 64-bit vector of [4 x i16].
@@ -2181,10 +2215,10 @@ void _mm_sfence(void);
/// bits in operand \a a.
/// \returns A 64-bit integer vector containing the copied packed data from the
/// operands.
-#define _mm_insert_pi16(a, d, n) __extension__ ({ \
- (__m64)__builtin_ia32_vec_set_v4hi((__m64)a, (int)d, (int)n); })
+#define _mm_insert_pi16(a, d, n) \
+ (__m64)__builtin_ia32_vec_set_v4hi((__m64)a, (int)d, (int)n)
-/// \brief Compares each of the corresponding packed 16-bit integer values of
+/// Compares each of the corresponding packed 16-bit integer values of
/// the 64-bit integer vectors, and writes the greater value to the
/// corresponding bits in the destination.
///
@@ -2197,13 +2231,13 @@ void _mm_sfence(void);
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the comparison results.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_max_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmaxsw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Compares each of the corresponding packed 8-bit unsigned integer
+/// Compares each of the corresponding packed 8-bit unsigned integer
/// values of the 64-bit integer vectors, and writes the greater value to the
/// corresponding bits in the destination.
///
@@ -2216,13 +2250,13 @@ _mm_max_pi16(__m64 __a, __m64 __b)
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the comparison results.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_max_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmaxub((__v8qi)__a, (__v8qi)__b);
}
-/// \brief Compares each of the corresponding packed 16-bit integer values of
+/// Compares each of the corresponding packed 16-bit integer values of
/// the 64-bit integer vectors, and writes the lesser value to the
/// corresponding bits in the destination.
///
@@ -2235,13 +2269,13 @@ _mm_max_pu8(__m64 __a, __m64 __b)
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the comparison results.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_min_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pminsw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Compares each of the corresponding packed 8-bit unsigned integer
+/// Compares each of the corresponding packed 8-bit unsigned integer
/// values of the 64-bit integer vectors, and writes the lesser value to the
/// corresponding bits in the destination.
///
@@ -2254,14 +2288,14 @@ _mm_min_pi16(__m64 __a, __m64 __b)
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the comparison results.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_min_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pminub((__v8qi)__a, (__v8qi)__b);
}
-/// \brief Takes the most significant bit from each 8-bit element in a 64-bit
-/// integer vector to create a 16-bit mask value. Zero-extends the value to
+/// Takes the most significant bit from each 8-bit element in a 64-bit
+/// integer vector to create an 8-bit mask value. Zero-extends the value to
/// 32-bit integer and writes it to the destination.
///
/// \headerfile <x86intrin.h>
@@ -2270,15 +2304,15 @@ _mm_min_pu8(__m64 __a, __m64 __b)
///
/// \param __a
/// A 64-bit integer vector containing the values with bits to be extracted.
-/// \returns The most significant bit from each 8-bit element in the operand,
-/// written to bits [15:0].
-static __inline__ int __DEFAULT_FN_ATTRS
+/// \returns The most significant bit from each 8-bit element in \a __a,
+/// written to bits [7:0].
+static __inline__ int __DEFAULT_FN_ATTRS_MMX
_mm_movemask_pi8(__m64 __a)
{
return __builtin_ia32_pmovmskb((__v8qi)__a);
}
-/// \brief Multiplies packed 16-bit unsigned integer values and writes the
+/// Multiplies packed 16-bit unsigned integer values and writes the
/// high-order 16 bits of each 32-bit product to the corresponding bits in
/// the destination.
///
@@ -2291,13 +2325,13 @@ _mm_movemask_pi8(__m64 __a)
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the products of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_mulhi_pu16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmulhuw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Shuffles the 4 16-bit integers from a 64-bit integer vector to the
+/// Shuffles the 4 16-bit integers from a 64-bit integer vector to the
/// destination, as specified by the immediate value operand.
///
/// \headerfile <x86intrin.h>
@@ -2328,10 +2362,10 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b)
/// 10: assigned from bits [47:32] of \a a. \n
/// 11: assigned from bits [63:48] of \a a.
/// \returns A 64-bit integer vector containing the shuffled values.
-#define _mm_shuffle_pi16(a, n) __extension__ ({ \
- (__m64)__builtin_ia32_pshufw((__v4hi)(__m64)(a), (n)); })
+#define _mm_shuffle_pi16(a, n) \
+ (__m64)__builtin_ia32_pshufw((__v4hi)(__m64)(a), (n))
-/// \brief Conditionally copies the values from each 8-bit element in the first
+/// Conditionally copies the values from each 8-bit element in the first
/// 64-bit integer vector operand to the specified memory location, as
/// specified by the most significant bit in the corresponding element in the
/// second 64-bit integer vector operand.
@@ -2354,13 +2388,13 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b)
/// A pointer to a 64-bit memory location that will receive the conditionally
/// copied integer values. The address of the memory location does not have
/// to be aligned.
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS_MMX
_mm_maskmove_si64(__m64 __d, __m64 __n, char *__p)
{
__builtin_ia32_maskmovq((__v8qi)__d, (__v8qi)__n, __p);
}
-/// \brief Computes the rounded averages of the packed unsigned 8-bit integer
+/// Computes the rounded averages of the packed unsigned 8-bit integer
/// values and writes the averages to the corresponding bits in the
/// destination.
///
@@ -2373,13 +2407,13 @@ _mm_maskmove_si64(__m64 __d, __m64 __n, char *__p)
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the averages of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_avg_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pavgb((__v8qi)__a, (__v8qi)__b);
}
-/// \brief Computes the rounded averages of the packed unsigned 16-bit integer
+/// Computes the rounded averages of the packed unsigned 16-bit integer
/// values and writes the averages to the corresponding bits in the
/// destination.
///
@@ -2392,13 +2426,13 @@ _mm_avg_pu8(__m64 __a, __m64 __b)
/// \param __b
/// A 64-bit integer vector containing one of the source operands.
/// \returns A 64-bit integer vector containing the averages of both operands.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_avg_pu16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pavgw((__v4hi)__a, (__v4hi)__b);
}
-/// \brief Subtracts the corresponding 8-bit unsigned integer values of the two
+/// Subtracts the corresponding 8-bit unsigned integer values of the two
/// 64-bit vector operands and computes the absolute value for each of the
/// difference. Then sum of the 8 absolute differences is written to the
/// bits [15:0] of the destination; the remaining bits [63:16] are cleared.
@@ -2414,7 +2448,7 @@ _mm_avg_pu16(__m64 __a, __m64 __b)
/// \returns A 64-bit integer vector whose lower 16 bits contain the sums of the
/// sets of absolute differences between both operands. The upper bits are
/// cleared.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_sad_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psadbw((__v8qi)__a, (__v8qi)__b);
@@ -2424,7 +2458,7 @@ _mm_sad_pu8(__m64 __a, __m64 __b)
extern "C" {
#endif
-/// \brief Returns the contents of the MXCSR register as a 32-bit unsigned
+/// Returns the contents of the MXCSR register as a 32-bit unsigned
/// integer value.
///
/// There are several groups of macros associated with this
@@ -2444,7 +2478,7 @@ extern "C" {
/// <li>
/// For checking rounding modes: _MM_ROUND_NEAREST, _MM_ROUND_DOWN,
/// _MM_ROUND_UP, _MM_ROUND_TOWARD_ZERO. There is a convenience wrapper
-/// _MM_GET_ROUNDING_MODE(x) where x is one of these macros.
+/// _MM_GET_ROUNDING_MODE().
/// </li>
/// <li>
/// For checking flush-to-zero mode: _MM_FLUSH_ZERO_ON, _MM_FLUSH_ZERO_OFF.
@@ -2457,12 +2491,16 @@ extern "C" {
/// </li>
/// </ul>
///
-/// For example, the expression below checks if an overflow exception has
+/// For example, the following expression checks if an overflow exception has
/// occurred:
+/// \code
/// ( _mm_getcsr() & _MM_EXCEPT_OVERFLOW )
+/// \endcode
///
-/// The following example gets the current rounding mode:
+/// The following expression gets the current rounding mode:
+/// \code
/// _MM_GET_ROUNDING_MODE()
+/// \endcode
///
/// \headerfile <x86intrin.h>
///
@@ -2472,7 +2510,7 @@ extern "C" {
/// register.
unsigned int _mm_getcsr(void);
-/// \brief Sets the MXCSR register with the 32-bit unsigned integer value.
+/// Sets the MXCSR register with the 32-bit unsigned integer value.
///
/// There are several groups of macros associated with this intrinsic,
/// including:
@@ -2511,10 +2549,12 @@ unsigned int _mm_getcsr(void);
/// _mm_setcsr(_mm_getcsr() | _MM_ROUND_UP)
///
/// The following example sets the DAZ and FTZ flags:
-/// void setFlags() {
-/// _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON)
-/// _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON)
-/// }
+/// \code
+/// void setFlags() {
+/// _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
+/// _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
+/// }
+/// \endcode
///
/// \headerfile <x86intrin.h>
///
@@ -2528,7 +2568,7 @@ void _mm_setcsr(unsigned int __i);
} // extern "C"
#endif
-/// \brief Selects 4 float values from the 128-bit operands of [4 x float], as
+/// Selects 4 float values from the 128-bit operands of [4 x float], as
/// specified by the immediate value operand.
///
/// \headerfile <x86intrin.h>
@@ -2564,14 +2604,11 @@ void _mm_setcsr(unsigned int __i);
/// 10: Bits [95:64] copied from the specified operand. \n
/// 11: Bits [127:96] copied from the specified operand.
/// \returns A 128-bit vector of [4 x float] containing the shuffled values.
-#define _mm_shuffle_ps(a, b, mask) __extension__ ({ \
- (__m128)__builtin_shufflevector((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), \
- 0 + (((mask) >> 0) & 0x3), \
- 0 + (((mask) >> 2) & 0x3), \
- 4 + (((mask) >> 4) & 0x3), \
- 4 + (((mask) >> 6) & 0x3)); })
-
-/// \brief Unpacks the high-order (index 2,3) values from two 128-bit vectors of
+#define _mm_shuffle_ps(a, b, mask) \
+ (__m128)__builtin_ia32_shufps((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), \
+ (int)(mask))
+
+/// Unpacks the high-order (index 2,3) values from two 128-bit vectors of
/// [4 x float] and interleaves them into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2593,7 +2630,7 @@ _mm_unpackhi_ps(__m128 __a, __m128 __b)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 2, 6, 3, 7);
}
-/// \brief Unpacks the low-order (index 0,1) values from two 128-bit vectors of
+/// Unpacks the low-order (index 0,1) values from two 128-bit vectors of
/// [4 x float] and interleaves them into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2615,13 +2652,14 @@ _mm_unpacklo_ps(__m128 __a, __m128 __b)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 0, 4, 1, 5);
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float]. The lower
+/// Constructs a 128-bit floating-point vector of [4 x float]. The lower
/// 32 bits are set to the lower 32 bits of the second parameter. The upper
/// 96 bits are set to the upper 96 bits of the first parameter.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
+/// This intrinsic corresponds to the <c> VBLENDPS / BLENDPS / MOVSS </c>
+/// instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float]. The upper 96 bits are
@@ -2633,10 +2671,11 @@ _mm_unpacklo_ps(__m128 __a, __m128 __b)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_move_ss(__m128 __a, __m128 __b)
{
- return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 4, 1, 2, 3);
+ __a[0] = __b[0];
+ return __a;
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float]. The lower
+/// Constructs a 128-bit floating-point vector of [4 x float]. The lower
/// 64 bits are set to the upper 64 bits of the second parameter. The upper
/// 64 bits are set to the upper 64 bits of the first parameter.
///
@@ -2657,7 +2696,7 @@ _mm_movehl_ps(__m128 __a, __m128 __b)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 6, 7, 2, 3);
}
-/// \brief Constructs a 128-bit floating-point vector of [4 x float]. The lower
+/// Constructs a 128-bit floating-point vector of [4 x float]. The lower
/// 64 bits are set to the lower 64 bits of the first parameter. The upper
/// 64 bits are set to the lower 64 bits of the second parameter.
///
@@ -2678,7 +2717,7 @@ _mm_movelh_ps(__m128 __a, __m128 __b)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 0, 1, 4, 5);
}
-/// \brief Converts a 64-bit vector of [4 x i16] into a 128-bit vector of [4 x
+/// Converts a 64-bit vector of [4 x i16] into a 128-bit vector of [4 x
/// float].
///
/// \headerfile <x86intrin.h>
@@ -2690,7 +2729,7 @@ _mm_movelh_ps(__m128 __a, __m128 __b)
/// from the corresponding elements in this operand.
/// \returns A 128-bit vector of [4 x float] containing the copied and converted
/// values from the operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpi16_ps(__m64 __a)
{
__m64 __b, __c;
@@ -2708,7 +2747,7 @@ _mm_cvtpi16_ps(__m64 __a)
return __r;
}
-/// \brief Converts a 64-bit vector of 16-bit unsigned integer values into a
+/// Converts a 64-bit vector of 16-bit unsigned integer values into a
/// 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2720,7 +2759,7 @@ _mm_cvtpi16_ps(__m64 __a)
/// destination are copied from the corresponding elements in this operand.
/// \returns A 128-bit vector of [4 x float] containing the copied and converted
/// values from the operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpu16_ps(__m64 __a)
{
__m64 __b, __c;
@@ -2737,7 +2776,7 @@ _mm_cvtpu16_ps(__m64 __a)
return __r;
}
-/// \brief Converts the lower four 8-bit values from a 64-bit vector of [8 x i8]
+/// Converts the lower four 8-bit values from a 64-bit vector of [8 x i8]
/// into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2749,7 +2788,7 @@ _mm_cvtpu16_ps(__m64 __a)
/// from the corresponding lower 4 elements in this operand.
/// \returns A 128-bit vector of [4 x float] containing the copied and converted
/// values from the operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpi8_ps(__m64 __a)
{
__m64 __b;
@@ -2761,7 +2800,7 @@ _mm_cvtpi8_ps(__m64 __a)
return _mm_cvtpi16_ps(__b);
}
-/// \brief Converts the lower four unsigned 8-bit integer values from a 64-bit
+/// Converts the lower four unsigned 8-bit integer values from a 64-bit
/// vector of [8 x u8] into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2774,7 +2813,7 @@ _mm_cvtpi8_ps(__m64 __a)
/// operand.
/// \returns A 128-bit vector of [4 x float] containing the copied and converted
/// values from the source operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpu8_ps(__m64 __a)
{
__m64 __b;
@@ -2785,7 +2824,7 @@ _mm_cvtpu8_ps(__m64 __a)
return _mm_cvtpi16_ps(__b);
}
-/// \brief Converts the two 32-bit signed integer values from each 64-bit vector
+/// Converts the two 32-bit signed integer values from each 64-bit vector
/// operand of [2 x i32] into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -2801,7 +2840,7 @@ _mm_cvtpu8_ps(__m64 __a)
/// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the
/// copied and converted values from the first operand. The upper 64 bits
/// contain the copied and converted values from the second operand.
-static __inline__ __m128 __DEFAULT_FN_ATTRS
+static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX
_mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
{
__m128 __c;
@@ -2813,7 +2852,7 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
return _mm_cvtpi32_ps(__c, __a);
}
-/// \brief Converts each single-precision floating-point element of a 128-bit
+/// Converts each single-precision floating-point element of a 128-bit
/// floating-point vector of [4 x float] into a 16-bit signed integer, and
/// packs the results into a 64-bit integer vector of [4 x i16].
///
@@ -2830,7 +2869,7 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
/// A 128-bit floating-point vector of [4 x float].
/// \returns A 64-bit integer vector of [4 x i16] containing the converted
/// values.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvtps_pi16(__m128 __a)
{
__m64 __b, __c;
@@ -2842,7 +2881,7 @@ _mm_cvtps_pi16(__m128 __a)
return _mm_packs_pi32(__b, __c);
}
-/// \brief Converts each single-precision floating-point element of a 128-bit
+/// Converts each single-precision floating-point element of a 128-bit
/// floating-point vector of [4 x float] into an 8-bit signed integer, and
/// packs the results into the lower 32 bits of a 64-bit integer vector of
/// [8 x i8]. The upper 32 bits of the vector are set to 0.
@@ -2860,7 +2899,7 @@ _mm_cvtps_pi16(__m128 __a)
/// 128-bit floating-point vector of [4 x float].
/// \returns A 64-bit integer vector of [8 x i8]. The lower 32 bits contain the
/// converted values and the uppper 32 bits are set to zero.
-static __inline__ __m64 __DEFAULT_FN_ATTRS
+static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX
_mm_cvtps_pi8(__m128 __a)
{
__m64 __b, __c;
@@ -2871,7 +2910,7 @@ _mm_cvtps_pi8(__m128 __a)
return _mm_packs_pi16(__b, __c);
}
-/// \brief Extracts the sign bits from each single-precision floating-point
+/// Extracts the sign bits from each single-precision floating-point
/// element of a 128-bit floating-point vector of [4 x float] and returns the
/// sign bits in bits [0:3] of the result. Bits [31:4] of the result are set
/// to zero.
@@ -2963,6 +3002,7 @@ do { \
#define _m_ _mm_
#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS_MMX
/* Ugly hack for backwards-compatibility (compatible with gcc) */
#if defined(__SSE2__) && !__building_module(_Builtin_intrinsics)
diff --git a/contrib/llvm/tools/clang/lib/Headers/xopintrin.h b/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
index 4a34f770d58d..9d540a2abdbe 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
@@ -31,7 +31,8 @@
#include <fma4intrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xop")))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xop"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("xop"), __min_vector_width__(256)))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C)
@@ -201,7 +202,7 @@ _mm_cmov_si128(__m128i __A, __m128i __B, __m128i __C)
return (__m128i)(((__v2du)__A & (__v2du)__C) | ((__v2du)__B & ~(__v2du)__C));
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_cmov_si256(__m256i __A, __m256i __B, __m256i __C)
{
return (__m256i)(((__v4du)__A & (__v4du)__C) | ((__v4du)__B & ~(__v4du)__C));
@@ -237,17 +238,17 @@ _mm_rot_epi64(__m128i __A, __m128i __B)
return (__m128i)__builtin_ia32_vprotq((__v2di)__A, (__v2di)__B);
}
-#define _mm_roti_epi8(A, N) __extension__ ({ \
- (__m128i)__builtin_ia32_vprotbi((__v16qi)(__m128i)(A), (N)); })
+#define _mm_roti_epi8(A, N) \
+ (__m128i)__builtin_ia32_vprotbi((__v16qi)(__m128i)(A), (N))
-#define _mm_roti_epi16(A, N) __extension__ ({ \
- (__m128i)__builtin_ia32_vprotwi((__v8hi)(__m128i)(A), (N)); })
+#define _mm_roti_epi16(A, N) \
+ (__m128i)__builtin_ia32_vprotwi((__v8hi)(__m128i)(A), (N))
-#define _mm_roti_epi32(A, N) __extension__ ({ \
- (__m128i)__builtin_ia32_vprotdi((__v4si)(__m128i)(A), (N)); })
+#define _mm_roti_epi32(A, N) \
+ (__m128i)__builtin_ia32_vprotdi((__v4si)(__m128i)(A), (N))
-#define _mm_roti_epi64(A, N) __extension__ ({ \
- (__m128i)__builtin_ia32_vprotqi((__v2di)(__m128i)(A), (N)); })
+#define _mm_roti_epi64(A, N) \
+ (__m128i)__builtin_ia32_vprotqi((__v2di)(__m128i)(A), (N))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shl_epi8(__m128i __A, __m128i __B)
@@ -297,37 +298,37 @@ _mm_sha_epi64(__m128i __A, __m128i __B)
return (__m128i)__builtin_ia32_vpshaq((__v2di)__A, (__v2di)__B);
}
-#define _mm_com_epu8(A, B, N) __extension__ ({ \
+#define _mm_com_epu8(A, B, N) \
(__m128i)__builtin_ia32_vpcomub((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (N)); })
+ (__v16qi)(__m128i)(B), (N))
-#define _mm_com_epu16(A, B, N) __extension__ ({ \
+#define _mm_com_epu16(A, B, N) \
(__m128i)__builtin_ia32_vpcomuw((__v8hi)(__m128i)(A), \
- (__v8hi)(__m128i)(B), (N)); })
+ (__v8hi)(__m128i)(B), (N))
-#define _mm_com_epu32(A, B, N) __extension__ ({ \
+#define _mm_com_epu32(A, B, N) \
(__m128i)__builtin_ia32_vpcomud((__v4si)(__m128i)(A), \
- (__v4si)(__m128i)(B), (N)); })
+ (__v4si)(__m128i)(B), (N))
-#define _mm_com_epu64(A, B, N) __extension__ ({ \
+#define _mm_com_epu64(A, B, N) \
(__m128i)__builtin_ia32_vpcomuq((__v2di)(__m128i)(A), \
- (__v2di)(__m128i)(B), (N)); })
+ (__v2di)(__m128i)(B), (N))
-#define _mm_com_epi8(A, B, N) __extension__ ({ \
+#define _mm_com_epi8(A, B, N) \
(__m128i)__builtin_ia32_vpcomb((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (N)); })
+ (__v16qi)(__m128i)(B), (N))
-#define _mm_com_epi16(A, B, N) __extension__ ({ \
+#define _mm_com_epi16(A, B, N) \
(__m128i)__builtin_ia32_vpcomw((__v8hi)(__m128i)(A), \
- (__v8hi)(__m128i)(B), (N)); })
+ (__v8hi)(__m128i)(B), (N))
-#define _mm_com_epi32(A, B, N) __extension__ ({ \
+#define _mm_com_epi32(A, B, N) \
(__m128i)__builtin_ia32_vpcomd((__v4si)(__m128i)(A), \
- (__v4si)(__m128i)(B), (N)); })
+ (__v4si)(__m128i)(B), (N))
-#define _mm_com_epi64(A, B, N) __extension__ ({ \
+#define _mm_com_epi64(A, B, N) \
(__m128i)__builtin_ia32_vpcomq((__v2di)(__m128i)(A), \
- (__v2di)(__m128i)(B), (N)); })
+ (__v2di)(__m128i)(B), (N))
#define _MM_PCOMCTRL_LT 0
#define _MM_PCOMCTRL_LE 1
@@ -722,24 +723,24 @@ _mm_comtrue_epi64(__m128i __A, __m128i __B)
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_TRUE);
}
-#define _mm_permute2_pd(X, Y, C, I) __extension__ ({ \
+#define _mm_permute2_pd(X, Y, C, I) \
(__m128d)__builtin_ia32_vpermil2pd((__v2df)(__m128d)(X), \
(__v2df)(__m128d)(Y), \
- (__v2di)(__m128i)(C), (I)); })
+ (__v2di)(__m128i)(C), (I))
-#define _mm256_permute2_pd(X, Y, C, I) __extension__ ({ \
+#define _mm256_permute2_pd(X, Y, C, I) \
(__m256d)__builtin_ia32_vpermil2pd256((__v4df)(__m256d)(X), \
(__v4df)(__m256d)(Y), \
- (__v4di)(__m256i)(C), (I)); })
+ (__v4di)(__m256i)(C), (I))
-#define _mm_permute2_ps(X, Y, C, I) __extension__ ({ \
+#define _mm_permute2_ps(X, Y, C, I) \
(__m128)__builtin_ia32_vpermil2ps((__v4sf)(__m128)(X), (__v4sf)(__m128)(Y), \
- (__v4si)(__m128i)(C), (I)); })
+ (__v4si)(__m128i)(C), (I))
-#define _mm256_permute2_ps(X, Y, C, I) __extension__ ({ \
+#define _mm256_permute2_ps(X, Y, C, I) \
(__m256)__builtin_ia32_vpermil2ps256((__v8sf)(__m256)(X), \
(__v8sf)(__m256)(Y), \
- (__v8si)(__m256i)(C), (I)); })
+ (__v8si)(__m256i)(C), (I))
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_frcz_ss(__m128 __A)
@@ -765,18 +766,19 @@ _mm_frcz_pd(__m128d __A)
return (__m128d)__builtin_ia32_vfrczpd((__v2df)__A);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_frcz_ps(__m256 __A)
{
return (__m256)__builtin_ia32_vfrczps256((__v8sf)__A);
}
-static __inline__ __m256d __DEFAULT_FN_ATTRS
+static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_frcz_pd(__m256d __A)
{
return (__m256d)__builtin_ia32_vfrczpd256((__v4df)__A);
}
#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS256
#endif /* __XOPINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h
index 598470a682e2..25577a95fc9a 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h
@@ -1,4 +1,4 @@
-/*===---- xsavecintrin.h - XSAVEC intrinsic ------------------------------------===
+/*===---- xsavecintrin.h - XSAVEC 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
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h
index a2e6b2e742ff..16f3a78d3f5b 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h
@@ -1,4 +1,4 @@
-/*===---- xsaveintrin.h - XSAVE intrinsic ------------------------------------===
+/*===---- xsaveintrin.h - XSAVE 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
@@ -33,23 +33,23 @@
static __inline__ void __DEFAULT_FN_ATTRS
_xsave(void *__p, unsigned long long __m) {
- return __builtin_ia32_xsave(__p, __m);
+ __builtin_ia32_xsave(__p, __m);
}
static __inline__ void __DEFAULT_FN_ATTRS
_xrstor(void *__p, unsigned long long __m) {
- return __builtin_ia32_xrstor(__p, __m);
+ __builtin_ia32_xrstor(__p, __m);
}
#ifdef __x86_64__
static __inline__ void __DEFAULT_FN_ATTRS
_xsave64(void *__p, unsigned long long __m) {
- return __builtin_ia32_xsave64(__p, __m);
+ __builtin_ia32_xsave64(__p, __m);
}
static __inline__ void __DEFAULT_FN_ATTRS
_xrstor64(void *__p, unsigned long long __m) {
- return __builtin_ia32_xrstor64(__p, __m);
+ __builtin_ia32_xrstor64(__p, __m);
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h
index d3faae78be4f..792cf92d46e8 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h
@@ -1,4 +1,4 @@
-/*===---- xsaveoptintrin.h - XSAVEOPT intrinsic ------------------------------------===
+/*===---- xsaveoptintrin.h - XSAVEOPT 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
@@ -33,13 +33,13 @@
static __inline__ void __DEFAULT_FN_ATTRS
_xsaveopt(void *__p, unsigned long long __m) {
- return __builtin_ia32_xsaveopt(__p, __m);
+ __builtin_ia32_xsaveopt(__p, __m);
}
#ifdef __x86_64__
static __inline__ void __DEFAULT_FN_ATTRS
_xsaveopt64(void *__p, unsigned long long __m) {
- return __builtin_ia32_xsaveopt64(__p, __m);
+ __builtin_ia32_xsaveopt64(__p, __m);
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h
index c5e540a86edb..fe2bc4b93b22 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h
@@ -1,4 +1,4 @@
-/*===---- xsavesintrin.h - XSAVES intrinsic ------------------------------------===
+/*===---- xsavesintrin.h - XSAVES 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
diff --git a/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h b/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h
index 9d3378fd1eea..924424386b94 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h
@@ -1,4 +1,4 @@
-/*===---- xtestintrin.h - XTEST intrinsic ---------------------------------===
+/*===---- xtestintrin.h - XTEST 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
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
index ac34956b2484..786563a44a4d 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
@@ -30,7 +30,7 @@ public:
BodyIndexer(IndexingContext &indexCtx,
const NamedDecl *Parent, const DeclContext *DC)
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
-
+
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool dataTraverseStmtPre(Stmt *S) {
@@ -322,7 +322,7 @@ public:
}
return true;
}
-
+
bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
return passObjCLiteralMethodCall(MD, E);
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
index e14750e046eb..01ad3a277216 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
@@ -43,7 +43,7 @@ public:
return true;
}
- /// \brief Returns true if the given method has been defined explicitly by the
+ /// Returns true if the given method has been defined explicitly by the
/// user.
static bool hasUserDefined(const ObjCMethodDecl *D,
const ObjCImplDecl *Container) {
@@ -664,8 +664,11 @@ public:
bool VisitTemplateDecl(const TemplateDecl *D) {
- // Index the default values for the template parameters.
const NamedDecl *Parent = D->getTemplatedDecl();
+ if (!Parent)
+ return true;
+
+ // Index the default values for the template parameters.
if (D->getTemplateParameters() &&
shouldIndexTemplateParameterDefaultValue(Parent)) {
const TemplateParameterList *Params = D->getTemplateParameters();
@@ -684,7 +687,7 @@ public:
}
}
- return Visit(D->getTemplatedDecl());
+ return Visit(Parent);
}
bool VisitFriendDecl(const FriendDecl *D) {
@@ -723,7 +726,7 @@ bool IndexingContext::indexDecl(const Decl *D) {
if (D->isImplicit() && shouldIgnoreIfImplicit(D))
return true;
- if (isTemplateImplicitInstantiation(D))
+ if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
return true;
IndexingDeclVisitor Visitor(*this);
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
index 733d4dbc2f94..03b55ffe8a4e 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/Lex/MacroInfo.h"
using namespace clang;
using namespace clang::index;
@@ -348,6 +349,15 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
return Info;
}
+SymbolInfo index::getSymbolInfoForMacro(const MacroInfo &) {
+ SymbolInfo Info;
+ Info.Kind = SymbolKind::Macro;
+ Info.SubKind = SymbolSubKind::None;
+ Info.Properties = SymbolPropertySet();
+ Info.Lang = SymbolLanguage::C;
+ return Info;
+}
+
bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
llvm::function_ref<bool(SymbolRole)> Fn) {
#define APPLY_FOR_ROLE(Role) \
@@ -364,6 +374,7 @@ bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
APPLY_FOR_ROLE(Dynamic);
APPLY_FOR_ROLE(AddressOf);
APPLY_FOR_ROLE(Implicit);
+ APPLY_FOR_ROLE(Undefinition);
APPLY_FOR_ROLE(RelationChildOf);
APPLY_FOR_ROLE(RelationBaseOf);
APPLY_FOR_ROLE(RelationOverrideOf);
@@ -405,6 +416,7 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
case SymbolRole::Dynamic: OS << "Dyn"; break;
case SymbolRole::AddressOf: OS << "Addr"; break;
case SymbolRole::Implicit: OS << "Impl"; break;
+ case SymbolRole::Undefinition: OS << "Undef"; break;
case SymbolRole::RelationChildOf: OS << "RelChild"; break;
case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
index c8ff3d72d4be..4b6bfbc67eff 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -37,7 +37,7 @@ public:
Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
}
}
-
+
bool shouldWalkTypesOfTypeLocs() const { return false; }
#define TRY_TO(CALL_EXPR) \
@@ -129,7 +129,7 @@ public:
template<typename TypeLocType>
bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) {
if (const auto *T = TL.getTypePtr()) {
- if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
+ if (IndexCtx.shouldIndexImplicitInstantiation()) {
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
Parent, ParentDC, SymbolRoleSet(), Relations);
@@ -193,7 +193,7 @@ void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
bool isIBType) {
if (!TInfo || TInfo->getTypeLoc().isNull())
return;
-
+
indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
index 411657bf3dcd..16f6c21745ef 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
@@ -13,30 +13,32 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
+#include "llvm/ADT/STLExtras.h"
+#include <memory>
using namespace clang;
using namespace clang::index;
-void IndexDataConsumer::_anchor() {}
-
bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
- FileID FID, unsigned Offset,
+ SourceLocation Loc,
ASTNodeInfo ASTNode) {
return true;
}
bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
- const MacroInfo *MI, SymbolRoleSet Roles,
- FileID FID, unsigned Offset) {
+ const MacroInfo *MI,
+ SymbolRoleSet Roles,
+ SourceLocation Loc) {
return true;
}
bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
SymbolRoleSet Roles,
- FileID FID, unsigned Offset) {
+ SourceLocation Loc) {
return true;
}
@@ -44,21 +46,22 @@ namespace {
class IndexASTConsumer : public ASTConsumer {
std::shared_ptr<Preprocessor> PP;
- IndexingContext &IndexCtx;
+ std::shared_ptr<IndexingContext> IndexCtx;
public:
- IndexASTConsumer(std::shared_ptr<Preprocessor> PP, IndexingContext &IndexCtx)
- : PP(std::move(PP)), IndexCtx(IndexCtx) {}
+ IndexASTConsumer(std::shared_ptr<Preprocessor> PP,
+ std::shared_ptr<IndexingContext> IndexCtx)
+ : PP(std::move(PP)), IndexCtx(std::move(IndexCtx)) {}
protected:
void Initialize(ASTContext &Context) override {
- IndexCtx.setASTContext(Context);
- IndexCtx.getDataConsumer().initialize(Context);
- IndexCtx.getDataConsumer().setPreprocessor(PP);
+ IndexCtx->setASTContext(Context);
+ IndexCtx->getDataConsumer().initialize(Context);
+ IndexCtx->getDataConsumer().setPreprocessor(PP);
}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
- return IndexCtx.indexDeclGroupRef(DG);
+ return IndexCtx->indexDeclGroupRef(DG);
}
void HandleInterestingDecl(DeclGroupRef DG) override {
@@ -66,22 +69,52 @@ protected:
}
void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
- IndexCtx.indexDeclGroupRef(DG);
+ IndexCtx->indexDeclGroupRef(DG);
}
void HandleTranslationUnit(ASTContext &Ctx) override {
}
};
+class IndexPPCallbacks : public PPCallbacks {
+ std::shared_ptr<IndexingContext> IndexCtx;
+
+public:
+ IndexPPCallbacks(std::shared_ptr<IndexingContext> IndexCtx)
+ : IndexCtx(std::move(IndexCtx)) {}
+
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override {
+ IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
+ Range.getBegin(), *MD.getMacroInfo());
+ }
+
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override {
+ IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD->getMacroInfo());
+ }
+
+ void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
+ const MacroDirective *Undef) override {
+ if (!MD.getMacroInfo()) // Ignore noop #undef.
+ return;
+ IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD.getMacroInfo());
+ }
+};
+
class IndexActionBase {
protected:
std::shared_ptr<IndexDataConsumer> DataConsumer;
- IndexingContext IndexCtx;
+ std::shared_ptr<IndexingContext> IndexCtx;
IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
IndexingOptions Opts)
- : DataConsumer(std::move(dataConsumer)),
- IndexCtx(Opts, *DataConsumer) {}
+ : DataConsumer(std::move(dataConsumer)),
+ IndexCtx(new IndexingContext(Opts, *DataConsumer)) {}
std::unique_ptr<IndexASTConsumer>
createIndexASTConsumer(CompilerInstance &CI) {
@@ -89,6 +122,10 @@ protected:
IndexCtx);
}
+ std::unique_ptr<PPCallbacks> createIndexPPCallbacks() {
+ return llvm::make_unique<IndexPPCallbacks>(IndexCtx);
+ }
+
void finish() {
DataConsumer->finish();
}
@@ -106,6 +143,11 @@ protected:
return createIndexASTConsumer(CI);
}
+ bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
+ CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
+ return true;
+ }
+
void EndSourceFileAction() override {
FrontendAction::EndSourceFileAction();
finish();
@@ -124,32 +166,34 @@ public:
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
- void EndSourceFileAction() override;
-};
-
-} // anonymous namespace
+ StringRef InFile) override {
+ auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+ if (!OtherConsumer) {
+ IndexActionFailed = true;
+ return nullptr;
+ }
+
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.push_back(std::move(OtherConsumer));
+ Consumers.push_back(createIndexASTConsumer(CI));
+ return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
+ }
-void WrappingIndexAction::EndSourceFileAction() {
- // Invoke wrapped action's method.
- WrapperFrontendAction::EndSourceFileAction();
- if (!IndexActionFailed)
- finish();
-}
+ bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
+ WrapperFrontendAction::BeginSourceFileAction(CI);
+ CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
+ return true;
+ }
-std::unique_ptr<ASTConsumer>
-WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
- if (!OtherConsumer) {
- IndexActionFailed = true;
- return nullptr;
+ void EndSourceFileAction() override {
+ // Invoke wrapped action's method.
+ WrapperFrontendAction::EndSourceFileAction();
+ if (!IndexActionFailed)
+ finish();
}
+};
- std::vector<std::unique_ptr<ASTConsumer>> Consumers;
- Consumers.push_back(std::move(OtherConsumer));
- Consumers.push_back(createIndexASTConsumer(CI));
- return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
-}
+} // anonymous namespace
std::unique_ptr<FrontendAction>
index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
@@ -162,7 +206,6 @@ index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
}
-
static bool topLevelDeclVisitor(void *context, const Decl *D) {
IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
return IndexCtx.indexTopLevelDecl(D);
@@ -172,40 +215,44 @@ static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
}
-void index::indexASTUnit(ASTUnit &Unit,
- std::shared_ptr<IndexDataConsumer> DataConsumer,
+void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
IndexingOptions Opts) {
- IndexingContext IndexCtx(Opts, *DataConsumer);
+ IndexingContext IndexCtx(Opts, DataConsumer);
IndexCtx.setASTContext(Unit.getASTContext());
- DataConsumer->initialize(Unit.getASTContext());
- DataConsumer->setPreprocessor(Unit.getPreprocessorPtr());
+ DataConsumer.initialize(Unit.getASTContext());
+ DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());
indexTranslationUnit(Unit, IndexCtx);
- DataConsumer->finish();
+ DataConsumer.finish();
}
void index::indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls,
- std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexDataConsumer &DataConsumer,
IndexingOptions Opts) {
- IndexingContext IndexCtx(Opts, *DataConsumer);
+ IndexingContext IndexCtx(Opts, DataConsumer);
IndexCtx.setASTContext(Ctx);
- DataConsumer->initialize(Ctx);
+ DataConsumer.initialize(Ctx);
for (const Decl *D : Decls)
IndexCtx.indexTopLevelDecl(D);
- DataConsumer->finish();
+ DataConsumer.finish();
+}
+
+std::unique_ptr<PPCallbacks>
+index::indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts) {
+ return llvm::make_unique<IndexPPCallbacks>(
+ std::make_shared<IndexingContext>(Opts, Consumer));
}
-void index::indexModuleFile(serialization::ModuleFile &Mod,
- ASTReader &Reader,
- std::shared_ptr<IndexDataConsumer> DataConsumer,
+void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,
+ IndexDataConsumer &DataConsumer,
IndexingOptions Opts) {
ASTContext &Ctx = Reader.getContext();
- IndexingContext IndexCtx(Opts, *DataConsumer);
+ IndexingContext IndexCtx(Opts, DataConsumer);
IndexCtx.setASTContext(Ctx);
- DataConsumer->initialize(Ctx);
+ DataConsumer.initialize(Ctx);
for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
IndexCtx.indexTopLevelDecl(D);
}
- DataConsumer->finish();
+ DataConsumer.finish();
}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
index de9fe39df031..333f9dc3091b 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "IndexingContext.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Index/IndexDataConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
@@ -36,6 +37,10 @@ bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
return IndexOpts.IndexFunctionLocals;
}
+bool IndexingContext::shouldIndexImplicitInstantiation() const {
+ return IndexOpts.IndexImplicitInstantiation;
+}
+
bool IndexingContext::handleDecl(const Decl *D,
SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations) {
@@ -70,7 +75,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
return true;
-
+
return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
RefE, RefD, DC);
}
@@ -82,14 +87,9 @@ bool IndexingContext::importedModule(const ImportDecl *ImportD) {
Loc = IdLocs.front();
else
Loc = ImportD->getLocation();
- SourceManager &SM = Ctx->getSourceManager();
- Loc = SM.getFileLoc(Loc);
- if (Loc.isInvalid())
- return true;
- FileID FID;
- unsigned Offset;
- std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+ SourceManager &SM = Ctx->getSourceManager();
+ FileID FID = SM.getFileID(SM.getFileLoc(Loc));
if (FID.isInvalid())
return true;
@@ -112,7 +112,7 @@ bool IndexingContext::importedModule(const ImportDecl *ImportD) {
if (ImportD->isImplicit())
Roles |= (unsigned)SymbolRole::Implicit;
- return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
+ return DataConsumer.handleModuleOccurence(ImportD, Roles, Loc);
}
bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
@@ -295,6 +295,7 @@ static bool shouldReportOccurrenceForSystemDeclOnlyMode(
case SymbolRole::Dynamic:
case SymbolRole::AddressOf:
case SymbolRole::Implicit:
+ case SymbolRole::Undefinition:
case SymbolRole::RelationReceivedBy:
case SymbolRole::RelationCalledBy:
case SymbolRole::RelationContainedBy:
@@ -327,13 +328,7 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
return true;
SourceManager &SM = Ctx->getSourceManager();
- Loc = SM.getFileLoc(Loc);
- if (Loc.isInvalid())
- return true;
-
- FileID FID;
- unsigned Offset;
- std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+ FileID FID = SM.getFileID(SM.getFileLoc(Loc));
if (FID.isInvalid())
return true;
@@ -355,6 +350,9 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
}
}
+ if (!OrigD)
+ OrigD = D;
+
if (isTemplateImplicitInstantiation(D)) {
if (!IsRef)
return true;
@@ -364,9 +362,6 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
assert(!isTemplateImplicitInstantiation(D));
}
- if (!OrigD)
- OrigD = D;
-
if (IsRef)
Roles |= (unsigned)SymbolRole::Reference;
else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
@@ -414,7 +409,27 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
Rel.RelatedSymbol->getCanonicalDecl()));
}
- IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
- return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
- Node);
+ IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
+ return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node);
+}
+
+void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
+ SourceLocation Loc,
+ const MacroInfo &MI) {
+ SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
+ DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
+}
+
+void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
+ SourceLocation Loc,
+ const MacroInfo &MI) {
+ SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
+ DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
+}
+
+void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
+ SourceLocation Loc,
+ const MacroInfo &MI) {
+ SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
+ DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.h b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h
index 566651c83a75..04960086d092 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexingContext.h
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h
@@ -10,9 +10,11 @@
#ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
#define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Index/IndexSymbol.h"
#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/MacroInfo.h"
#include "llvm/ADT/ArrayRef.h"
namespace clang {
@@ -58,9 +60,7 @@ public:
bool shouldIndexFunctionLocalSymbols() const;
- bool shouldIndexImplicitTemplateInsts() const {
- return false;
- }
+ bool shouldIndexImplicitInstantiation() const;
static bool isTemplateImplicitInstantiation(const Decl *D);
@@ -80,6 +80,15 @@ public:
const Expr *RefE = nullptr,
const Decl *RefD = nullptr);
+ void handleMacroDefined(const IdentifierInfo &Name, SourceLocation Loc,
+ const MacroInfo &MI);
+
+ void handleMacroUndefined(const IdentifierInfo &Name, SourceLocation Loc,
+ const MacroInfo &MI);
+
+ void handleMacroReference(const IdentifierInfo &Name, SourceLocation Loc,
+ const MacroInfo &MD);
+
bool importedModule(const ImportDecl *ImportD);
bool indexDecl(const Decl *D);
diff --git a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
index 2c26e4d82e08..9c6d29bec329 100644
--- a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
+++ b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
@@ -9,7 +9,7 @@
//
/// \file
///
-/// \brief Defines a utility class for use of clang-format in libclang
+/// Defines a utility class for use of clang-format in libclang
//
//===----------------------------------------------------------------------===//
@@ -29,7 +29,7 @@
namespace clang {
namespace index {
-/// \brief A small class to be used by libclang clients to format
+/// A small class to be used by libclang clients to format
/// a declaration string in memory. This object is instantiated once
/// and used each time a formatting is needed.
class SimpleFormatContext {
diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
index 3a06554b256c..b128b69931a3 100644
--- a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
@@ -62,9 +62,9 @@ class USRGenerator : public ConstDeclVisitor<USRGenerator> {
bool IgnoreResults;
ASTContext *Context;
bool generatedLoc;
-
+
llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
-
+
public:
explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
: Buf(Buf),
@@ -103,7 +103,7 @@ public:
void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
- IgnoreResults = true;
+ IgnoreResults = true; // No USRs for linkage specs themselves.
}
void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
@@ -159,7 +159,7 @@ public:
void VisitTemplateParameterList(const TemplateParameterList *Params);
void VisitTemplateName(TemplateName Name);
void VisitTemplateArgument(const TemplateArgument &Arg);
-
+
/// Emit a Decl's name using NamedDecl::printName() and return true if
/// the decl had no name.
bool EmitDeclName(const NamedDecl *D);
@@ -192,6 +192,8 @@ bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
void USRGenerator::VisitDeclContext(const DeclContext *DC) {
if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
Visit(D);
+ else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.
+ VisitDeclContext(DC->getParent());
}
void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
@@ -364,7 +366,7 @@ void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
VisitDeclContext(D->getDeclContext());
if (!IgnoreResults)
- Out << "@NA@" << D->getName();
+ Out << "@NA@" << D->getName();
}
void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
@@ -491,7 +493,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) {
if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
AlreadyStarted = true;
-
+
switch (D->getTagKind()) {
case TTK_Interface:
case TTK_Class:
@@ -503,18 +505,18 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) {
} else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
AlreadyStarted = true;
-
+
switch (D->getTagKind()) {
case TTK_Interface:
case TTK_Class:
case TTK_Struct: Out << "@SP"; break;
case TTK_Union: Out << "@UP"; break;
case TTK_Enum: llvm_unreachable("enum partial specialization");
- }
+ }
VisitTemplateParameterList(PartialSpec->getTemplateParameters());
}
}
-
+
if (!AlreadyStarted) {
switch (D->getTagKind()) {
case TTK_Interface:
@@ -524,7 +526,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) {
case TTK_Enum: Out << "@E"; break;
}
}
-
+
Out << '@';
assert(Buf.size() > 0);
const unsigned off = Buf.size() - 1;
@@ -549,7 +551,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) {
}
}
}
-
+
// For a class template specialization, mangle the template arguments.
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(D)) {
@@ -638,7 +640,7 @@ void USRGenerator::VisitType(QualType T) {
Out << 'P';
T = Expansion->getPattern();
}
-
+
if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
unsigned char c = '\0';
switch (BT->getKind()) {
@@ -648,6 +650,8 @@ void USRGenerator::VisitType(QualType T) {
c = 'b'; break;
case BuiltinType::UChar:
c = 'c'; break;
+ case BuiltinType::Char8:
+ c = 'u'; break; // FIXME: Check this doesn't collide
case BuiltinType::Char16:
c = 'q'; break;
case BuiltinType::Char32:
@@ -705,6 +709,30 @@ void USRGenerator::VisitType(QualType T) {
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
case BuiltinType::OCLSampler:
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
IgnoreResults = true;
return;
case BuiltinType::ObjCId:
@@ -730,7 +758,7 @@ void USRGenerator::VisitType(QualType T) {
unsigned Number = TypeSubstitutions.size();
TypeSubstitutions[T.getTypePtr()] = Number;
}
-
+
if (const PointerType *PT = T->getAs<PointerType>()) {
Out << '*';
T = PT->getPointeeType();
@@ -861,7 +889,7 @@ void USRGenerator::VisitTemplateParameterList(
Out << 'T';
continue;
}
-
+
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
if (NTTP->isParameterPack())
Out << 'p';
@@ -869,7 +897,7 @@ void USRGenerator::VisitTemplateParameterList(
VisitType(NTTP->getType());
continue;
}
-
+
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
if (TTP->isParameterPack())
Out << 'p';
@@ -885,11 +913,11 @@ void USRGenerator::VisitTemplateName(TemplateName Name) {
Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
return;
}
-
+
Visit(Template);
return;
}
-
+
// FIXME: Visit dependent template names.
}
@@ -911,21 +939,21 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
case TemplateArgument::Template:
VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
-
+
case TemplateArgument::Expression:
// FIXME: Visit expressions.
break;
-
+
case TemplateArgument::Pack:
Out << 'p' << Arg.pack_size();
for (const auto &P : Arg.pack_elements())
VisitTemplateArgument(P);
break;
-
+
case TemplateArgument::Type:
VisitType(Arg.getAsType());
break;
-
+
case TemplateArgument::Integral:
Out << 'V';
VisitType(Arg.getIntegralType());
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
index 6976294a2eaf..fbfa54b2fffd 100644
--- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
@@ -124,7 +124,7 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
return nullptr;
}
-/// \brief Get filenames for all registered header maps.
+/// Get filenames for all registered header maps.
void HeaderSearch::getHeaderMapFileNames(
SmallVectorImpl<std::string> &Names) const {
for (auto &HM : HeaderMaps)
@@ -198,31 +198,33 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName,
return Result.str().str();
}
-Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
+Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch,
+ bool AllowExtraModuleMapSearch) {
// Look in the module map to determine if there is a module by this name.
Module *Module = ModMap.findModule(ModuleName);
if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
return Module;
StringRef SearchName = ModuleName;
- Module = lookupModule(ModuleName, SearchName);
+ Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch);
// The facility for "private modules" -- adjacent, optional module maps named
// module.private.modulemap that are supposed to define private submodules --
// may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.
//
- // Foo.Private is now depracated in favor of Foo_Private. Users of FooPrivate
+ // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate
// should also rename to Foo_Private. Representing private as submodules
// could force building unwanted dependencies into the parent module and cause
// dependency cycles.
if (!Module && SearchName.consume_back("_Private"))
- Module = lookupModule(ModuleName, SearchName);
+ Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch);
if (!Module && SearchName.consume_back("Private"))
- Module = lookupModule(ModuleName, SearchName);
+ Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch);
return Module;
}
-Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) {
+Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
+ bool AllowExtraModuleMapSearch) {
Module *Module = nullptr;
// Look through the various header search paths to load any available module
@@ -244,9 +246,9 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) {
break;
}
}
-
+
// FIXME: Figure out how header maps and module maps will work together.
-
+
// Only deal with normal search directories.
if (!SearchDirs[Idx].isNormalDir())
continue;
@@ -261,7 +263,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) {
if (Module)
break;
}
-
+
// Search for a module map in a subdirectory with the same name as the
// module.
SmallString<128> NestedModuleMapDirName;
@@ -281,8 +283,9 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) {
continue;
// Load all module maps in the immediate subdirectories of this search
- // directory.
- loadSubdirectoryModuleMaps(SearchDirs[Idx]);
+ // directory if ModuleName was from @import.
+ if (AllowExtraModuleMapSearch)
+ loadSubdirectoryModuleMaps(SearchDirs[Idx]);
// Look again for the module.
Module = ModMap.findModule(ModuleName);
@@ -404,7 +407,7 @@ const FileEntry *DirectoryLookup::LookupFile(
return Result;
}
-/// \brief Given a framework directory, find the top-most framework directory.
+/// Given a framework directory, find the top-most framework directory.
///
/// \param FileMgr The file manager to use for directory lookups.
/// \param DirName The name of the framework directory.
@@ -527,7 +530,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
RelativePath->clear();
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
}
-
+
// Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
unsigned OrigSize = FrameworkName.size();
@@ -600,7 +603,7 @@ void HeaderSearch::setTarget(const TargetInfo &Target) {
// Header File Location.
//===----------------------------------------------------------------------===//
-/// \brief Return true with a diagnostic if the file that MSVC would have found
+/// Return true with a diagnostic if the file that MSVC would have found
/// fails to match the one that Clang would have found with MSVC header search
/// disabled.
static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,
@@ -621,6 +624,74 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
return CopyStr;
}
+static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,
+ SmallVectorImpl<char> &FrameworkName) {
+ using namespace llvm::sys;
+ path::const_iterator I = path::begin(Path);
+ path::const_iterator E = path::end(Path);
+ IsPrivateHeader = false;
+
+ // Detect different types of framework style paths:
+ //
+ // ...Foo.framework/{Headers,PrivateHeaders}
+ // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders}
+ // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders}
+ // ...<other variations with 'Versions' like in the above path>
+ //
+ // and some other variations among these lines.
+ int FoundComp = 0;
+ while (I != E) {
+ if (*I == "Headers")
+ ++FoundComp;
+ if (I->endswith(".framework")) {
+ FrameworkName.append(I->begin(), I->end());
+ ++FoundComp;
+ }
+ if (*I == "PrivateHeaders") {
+ ++FoundComp;
+ IsPrivateHeader = true;
+ }
+ ++I;
+ }
+
+ return FoundComp >= 2;
+}
+
+static void
+diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
+ StringRef Includer, StringRef IncludeFilename,
+ const FileEntry *IncludeFE, bool isAngled = false,
+ bool FoundByHeaderMap = false) {
+ bool IsIncluderPrivateHeader = false;
+ SmallString<128> FromFramework, ToFramework;
+ if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework))
+ return;
+ bool IsIncludeePrivateHeader = false;
+ bool IsIncludeeInFramework = isFrameworkStylePath(
+ IncludeFE->getName(), IsIncludeePrivateHeader, ToFramework);
+
+ if (!isAngled && !FoundByHeaderMap) {
+ SmallString<128> NewInclude("<");
+ if (IsIncludeeInFramework) {
+ NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework
+ NewInclude += "/";
+ }
+ NewInclude += IncludeFilename;
+ NewInclude += ">";
+ Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
+ << IncludeFilename
+ << FixItHint::CreateReplacement(IncludeLoc, NewInclude);
+ }
+
+ // Headers in Foo.framework/Headers should not include headers
+ // from Foo.framework/PrivateHeaders, since this violates public/private
+ // API boundaries and can cause modular dependency cycles.
+ if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
+ IsIncludeePrivateHeader && FromFramework == ToFramework)
+ Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)
+ << IncludeFilename;
+}
+
/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// for system \#include's or not (i.e. using <> instead of ""). Includers, if
@@ -638,7 +709,7 @@ const FileEntry *HeaderSearch::LookupFile(
if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader();
-
+
// If 'Filename' is absolute, check to see if it exists and no searching.
if (llvm::sys::path::is_absolute(Filename)) {
CurDir = nullptr;
@@ -722,8 +793,12 @@ const FileEntry *HeaderSearch::LookupFile(
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
- if (First)
+ if (First) {
+ diagnoseFrameworkInclude(Diags, IncludeLoc,
+ IncluderAndDir.second->getName(), Filename,
+ FE);
return FE;
+ }
// Otherwise, we found the path via MSVC header search rules. If
// -Wmsvc-include is enabled, we have to keep searching to see if we
@@ -823,7 +898,7 @@ const FileEntry *HeaderSearch::LookupFile(
size_t SlashPos = Filename.find('/');
if (SlashPos != StringRef::npos) {
HFI.IndexHeaderMapHeader = 1;
- HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(),
+ HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(),
SlashPos));
}
}
@@ -834,6 +909,12 @@ const FileEntry *HeaderSearch::LookupFile(
return MSFE;
}
+ bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
+ if (!Includers.empty())
+ diagnoseFrameworkInclude(Diags, IncludeLoc,
+ Includers.front().second->getName(), Filename,
+ FE, isAngled, FoundByHeaderMap);
+
// Remember this location for the next lookup we do.
CacheLookup.HitIdx = i;
return FE;
@@ -996,9 +1077,9 @@ LookupSubframeworkHeader(StringRef Filename,
// File Info Management.
//===----------------------------------------------------------------------===//
-/// \brief Merge the header file info provided by \p OtherHFI into the current
+/// Merge the header file info provided by \p OtherHFI into the current
/// header file info (\p HFI)
-static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
+static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
const HeaderFileInfo &OtherHFI) {
assert(OtherHFI.External && "expected to merge external HFI");
@@ -1020,7 +1101,7 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
if (HFI.Framework.empty())
HFI.Framework = OtherHFI.Framework;
}
-
+
/// getFileInfo - Return the HeaderFileInfo structure for the specified
/// FileEntry.
HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
@@ -1204,14 +1285,14 @@ StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
return FrameworkNames.insert(Framework).first->first();
}
-bool HeaderSearch::hasModuleMap(StringRef FileName,
+bool HeaderSearch::hasModuleMap(StringRef FileName,
const DirectoryEntry *Root,
bool IsSystem) {
if (!HSOpts->ImplicitModuleMaps)
return false;
SmallVector<const DirectoryEntry *, 2> FixUpDirectories;
-
+
StringRef DirName = FileName;
do {
// Get the parent directory name.
@@ -1244,7 +1325,7 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,
// If we hit the top of our search, we're done.
if (Dir == Root)
return false;
-
+
// Keep track of all of the directories we checked, so we can mark them as
// having module maps if we eventually do find a module map.
FixUpDirectories.push_back(Dir);
@@ -1304,7 +1385,7 @@ bool HeaderSearch::findUsableModuleForFrameworkHeader(
SmallVector<std::string, 4> SubmodulePath;
const DirectoryEntry *TopFrameworkDir
= ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
-
+
// Determine the name of the top-level framework.
StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
@@ -1451,16 +1532,16 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name,
return ModMap.findModule(Name);
}
-HeaderSearch::LoadModuleMapResult
+HeaderSearch::LoadModuleMapResult
HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem,
bool IsFramework) {
if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName))
return loadModuleMapFile(Dir, IsSystem, IsFramework);
-
+
return LMM_NoDirectory;
}
-HeaderSearch::LoadModuleMapResult
+HeaderSearch::LoadModuleMapResult
HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem,
bool IsFramework) {
auto KnownDir = DirectoryHasModuleMap.find(Dir);
@@ -1529,7 +1610,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
}
// Populate the list of modules.
- for (ModuleMap::module_iterator M = ModMap.module_begin(),
+ for (ModuleMap::module_iterator M = ModMap.module_begin(),
MEnd = ModMap.module_end();
M != MEnd; ++M) {
Modules.push_back(M->getValue());
@@ -1580,9 +1661,15 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
bool *IsSystem) {
// FIXME: We assume that the path name currently cached in the FileEntry is
- // the most appropriate one for this analysis (and that it's spelled the same
- // way as the corresponding header search path).
- StringRef Name = File->getName();
+ // the most appropriate one for this analysis (and that it's spelled the
+ // same way as the corresponding header search path).
+ return suggestPathToFileForDiagnostics(File->getName(), /*BuildDir=*/"",
+ IsSystem);
+}
+
+std::string HeaderSearch::suggestPathToFileForDiagnostics(
+ llvm::StringRef File, llvm::StringRef WorkingDir, bool *IsSystem) {
+ using namespace llvm::sys;
unsigned BestPrefixLength = 0;
unsigned BestSearchDir;
@@ -1593,12 +1680,17 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
continue;
StringRef Dir = SearchDirs[I].getDir()->getName();
- for (auto NI = llvm::sys::path::begin(Name),
- NE = llvm::sys::path::end(Name),
- DI = llvm::sys::path::begin(Dir),
- DE = llvm::sys::path::end(Dir);
+ llvm::SmallString<32> DirPath(Dir.begin(), Dir.end());
+ if (!WorkingDir.empty() && !path::is_absolute(Dir)) {
+ auto err = fs::make_absolute(WorkingDir, DirPath);
+ if (!err)
+ path::remove_dots(DirPath, /*remove_dot_dot=*/true);
+ Dir = DirPath;
+ }
+ for (auto NI = path::begin(File), NE = path::end(File),
+ DI = path::begin(Dir), DE = path::end(Dir);
/*termination condition in loop*/; ++NI, ++DI) {
- // '.' components in Name are ignored.
+ // '.' components in File are ignored.
while (NI != NE && *NI == ".")
++NI;
if (NI == NE)
@@ -1608,9 +1700,9 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
while (DI != DE && *DI == ".")
++DI;
if (DI == DE) {
- // Dir is a prefix of Name, up to '.' components and choice of path
+ // Dir is a prefix of File, up to '.' components and choice of path
// separators.
- unsigned PrefixLength = NI - llvm::sys::path::begin(Name);
+ unsigned PrefixLength = NI - path::begin(File);
if (PrefixLength > BestPrefixLength) {
BestPrefixLength = PrefixLength;
BestSearchDir = I;
@@ -1625,5 +1717,5 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
if (IsSystem)
*IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false;
- return Name.drop_front(BestPrefixLength);
+ return File.drop_front(BestPrefixLength);
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
index 8bd4ab0ff9ca..e8588a771a43 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
@@ -257,7 +257,7 @@ void Lexer::Stringify(SmallVectorImpl<char> &Str) { StringifyImpl(Str, '"'); }
// Token Spelling
//===----------------------------------------------------------------------===//
-/// \brief Slow case of getSpelling. Extract the characters comprising the
+/// Slow case of getSpelling. Extract the characters comprising the
/// spelling of this token from the provided input buffer.
static size_t getSpellingSlow(const Token &Tok, const char *BufPtr,
const LangOptions &LangOpts, char *Spelling) {
@@ -442,7 +442,7 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc,
return TheTok.getLength();
}
-/// \brief Relex the token at the specified location.
+/// Relex the token at the specified location.
/// \returns true if there was a failure, false on success.
bool Lexer::getRawToken(SourceLocation Loc, Token &Result,
const SourceManager &SM,
@@ -708,12 +708,9 @@ PreambleBounds Lexer::ComputePreamble(StringRef Buffer,
TheTok.isAtStartOfLine());
}
-/// AdvanceToTokenCharacter - Given a location that specifies the start of a
-/// token, return a new location that specifies a character within the token.
-SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
- unsigned CharNo,
- const SourceManager &SM,
- const LangOptions &LangOpts) {
+unsigned Lexer::getTokenPrefixLength(SourceLocation TokStart, unsigned CharNo,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
// Figure out how many physical characters away the specified expansion
// character is. This needs to take into consideration newlines and
// trigraphs.
@@ -722,7 +719,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
// If they request the first char of the token, we're trivially done.
if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr)))
- return TokStart;
+ return 0;
unsigned PhysOffset = 0;
@@ -731,7 +728,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
// chars, this method is extremely fast.
while (Lexer::isObviouslySimpleCharacter(*TokPtr)) {
if (CharNo == 0)
- return TokStart.getLocWithOffset(PhysOffset);
+ return PhysOffset;
++TokPtr;
--CharNo;
++PhysOffset;
@@ -753,10 +750,10 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
if (!Lexer::isObviouslySimpleCharacter(*TokPtr))
PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr;
- return TokStart.getLocWithOffset(PhysOffset);
+ return PhysOffset;
}
-/// \brief Computes the source location just past the end of the
+/// Computes the source location just past the end of the
/// token at this source location.
///
/// This routine can be used to produce a source location that
@@ -791,7 +788,7 @@ SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
return Loc.getLocWithOffset(Len);
}
-/// \brief Returns true if the given MacroID location points at the first
+/// Returns true if the given MacroID location points at the first
/// token of the macro expansion.
bool Lexer::isAtStartOfMacroExpansion(SourceLocation loc,
const SourceManager &SM,
@@ -813,7 +810,7 @@ bool Lexer::isAtStartOfMacroExpansion(SourceLocation loc,
return isAtStartOfMacroExpansion(expansionLoc, SM, LangOpts, MacroBegin);
}
-/// \brief Returns true if the given MacroID location points at the last
+/// Returns true if the given MacroID location points at the last
/// token of the macro expansion.
bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc,
const SourceManager &SM,
@@ -971,7 +968,7 @@ StringRef Lexer::getSourceText(CharSourceRange Range,
StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
const SourceManager &SM,
const LangOptions &LangOpts) {
- assert(Loc.isMacroID() && "Only reasonble to call this on macros");
+ assert(Loc.isMacroID() && "Only reasonable to call this on macros");
// Find the location of the immediate macro expansion.
while (true) {
@@ -987,7 +984,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
// Loc points to the argument id of the macro definition, move to the
// macro expansion.
- Loc = SM.getImmediateExpansionRange(Loc).first;
+ Loc = SM.getImmediateExpansionRange(Loc).getBegin();
SourceLocation SpellLoc = Expansion.getSpellingLoc();
if (SpellLoc.isFileID())
break; // No inner macro.
@@ -1017,10 +1014,10 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
StringRef Lexer::getImmediateMacroNameForDiagnostics(
SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) {
- assert(Loc.isMacroID() && "Only reasonble to call this on macros");
+ assert(Loc.isMacroID() && "Only reasonable to call this on macros");
// Walk past macro argument expanions.
while (SM.isMacroArgExpansion(Loc))
- Loc = SM.getImmediateExpansionRange(Loc).first;
+ Loc = SM.getImmediateExpansionRange(Loc).getBegin();
// 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.
@@ -1030,7 +1027,7 @@ StringRef Lexer::getImmediateMacroNameForDiagnostics(
// 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
// expanding this macro.
- Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
+ Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).getBegin());
// Dig out the buffer where the macro name was spelled and the extents of the
// name so that we can render it into the expansion note.
@@ -1112,10 +1109,9 @@ static SourceLocation GetMappedTokenLoc(Preprocessor &PP,
// Figure out the expansion loc range, which is the range covered by the
// original _Pragma(...) sequence.
- std::pair<SourceLocation,SourceLocation> II =
- SM.getImmediateExpansionRange(FileLoc);
+ CharSourceRange II = SM.getImmediateExpansionRange(FileLoc);
- return SM.createExpansionLoc(SpellingLoc, II.first, II.second, TokLen);
+ return SM.createExpansionLoc(SpellingLoc, II.getBegin(), II.getEnd(), TokLen);
}
/// getSourceLocation - Return a source location identifier for the specified
@@ -1260,7 +1256,7 @@ Optional<Token> Lexer::findNextToken(SourceLocation Loc,
return Tok;
}
-/// \brief Checks that the given token is the first token that occurs after the
+/// 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.
@@ -1413,7 +1409,7 @@ Slash:
// Helper methods for lexing.
//===----------------------------------------------------------------------===//
-/// \brief Routine that indiscriminately sets the offset into the source file.
+/// Routine that indiscriminately sets the offset into the source file.
void Lexer::SetByteOffset(unsigned Offset, bool StartOfLine) {
BufferPtr = BufferStart + Offset;
if (BufferPtr > BufferEnd)
@@ -1645,20 +1641,38 @@ FinishIdentifier:
// Fill in Result.IdentifierInfo and update the token kind,
// looking up the identifier in the identifier table.
IdentifierInfo *II = PP->LookUpIdentifierInfo(Result);
+ // Note that we have to call PP->LookUpIdentifierInfo() even for code
+ // completion, it writes IdentifierInfo into Result, and callers rely on it.
+
+ // If the completion point is at the end of an identifier, we want to treat
+ // the identifier as incomplete even if it resolves to a macro or a keyword.
+ // This allows e.g. 'class^' to complete to 'classifier'.
+ if (isCodeCompletionPoint(CurPtr)) {
+ // Return the code-completion token.
+ Result.setKind(tok::code_completion);
+ // Skip the code-completion char and all immediate identifier characters.
+ // This ensures we get consistent behavior when completing at any point in
+ // an identifier (i.e. at the start, in the middle, at the end). Note that
+ // only simple cases (i.e. [a-zA-Z0-9_]) are supported to keep the code
+ // simpler.
+ assert(*CurPtr == 0 && "Completion character must be 0");
+ ++CurPtr;
+ // Note that code completion token is not added as a separate character
+ // when the completion point is at the end of the buffer. Therefore, we need
+ // to check if the buffer has ended.
+ if (CurPtr < BufferEnd) {
+ while (isIdentifierBody(*CurPtr))
+ ++CurPtr;
+ }
+ BufferPtr = CurPtr;
+ return true;
+ }
// Finally, now that we know we have an identifier, pass this off to the
// preprocessor, which may macro expand it or something.
if (II->isHandleIdentifierCase())
return PP->HandleIdentifier(Result);
- if (II->getTokenID() == tok::identifier && isCodeCompletionPoint(CurPtr)
- && II->getPPKeywordID() == tok::pp_not_keyword
- && II->getObjCKeywordID() == tok::objc_not_keyword) {
- // Return the code-completion token.
- Result.setKind(tok::code_completion);
- cutOffLexing();
- return true;
- }
return true;
}
@@ -2163,7 +2177,7 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr,
}
/// We have just read the // characters from input. Skip until we find the
-/// newline character thats terminate the comment. Then update BufferPtr and
+/// newline character that terminates the comment. Then update BufferPtr and
/// return.
///
/// If we're in KeepCommentMode or any CommentHandler has inserted
@@ -2741,7 +2755,7 @@ unsigned Lexer::isNextPPTokenLParen() {
return Tok.is(tok::l_paren);
}
-/// \brief Find the end of a version control conflict marker.
+/// Find the end of a version control conflict marker.
static const char *FindConflictEnd(const char *CurPtr, const char *BufferEnd,
ConflictMarkerKind CMK) {
const char *Terminator = CMK == CMK_Perforce ? "<<<<\n" : ">>>>>>>";
@@ -3512,7 +3526,7 @@ LexNextToken:
// want to lex this as a comment. There is one problem with this though,
// that in one particular corner case, this can change the behavior of the
// resultant program. For example, In "foo //**/ bar", C89 would lex
- // this as "foo / bar" and langauges with Line comments would lex it as
+ // this as "foo / bar" and languages with Line comments would lex it as
// "foo". Check to see if the character after the second slash is a '*'.
// If so, we will lex that as a "/" instead of the start of a comment.
// However, we never do this if we are just preprocessing.
diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
index ec342ee3ae2a..3f2af1a74e5a 100644
--- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
@@ -30,7 +30,7 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
-#include <cstdint>
+#include <cstdint>
#include <cstring>
#include <string>
@@ -70,7 +70,7 @@ static CharSourceRange MakeCharSourceRange(const LangOptions &Features,
return CharSourceRange::getCharRange(Begin, End);
}
-/// \brief Produce a diagnostic highlighting some portion of a literal.
+/// Produce a diagnostic highlighting some portion of a literal.
///
/// Emits the diagnostic \p DiagID, highlighting the range of characters from
/// \p TokRangeBegin (inclusive) to \p TokRangeEnd (exclusive), which must be
@@ -274,7 +274,7 @@ void clang::expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input) {
static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd,
uint32_t &UcnVal, unsigned short &UcnLen,
- FullSourceLoc Loc, DiagnosticsEngine *Diags,
+ FullSourceLoc Loc, DiagnosticsEngine *Diags,
const LangOptions &Features,
bool in_char_string_literal = false) {
const char *UcnBegin = ThisTokBuf;
@@ -538,6 +538,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
saw_exponent = false;
saw_period = false;
saw_ud_suffix = false;
+ saw_fixed_point_suffix = false;
isLong = false;
isUnsigned = false;
isLongLong = false;
@@ -547,6 +548,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isFloat16 = false;
isFloat128 = false;
MicrosoftInteger = 0;
+ isFract = false;
+ isAccum = false;
hadError = false;
if (*s == '0') { // parse radix
@@ -568,6 +571,16 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
SuffixBegin = s;
checkSeparator(TokLoc, s, CSK_AfterDigits);
+ // Initial scan to lookahead for fixed point suffix.
+ if (PP.getLangOpts().FixedPoint) {
+ for (const char *c = s; c != ThisTokEnd; ++c) {
+ if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') {
+ saw_fixed_point_suffix = true;
+ break;
+ }
+ }
+ }
+
// Parse the suffix. At this point we can classify whether we have an FP or
// integer constant.
bool isFPConstant = isFloatingLiteral();
@@ -576,11 +589,25 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// we break out of the loop.
for (; s != ThisTokEnd; ++s) {
switch (*s) {
+ case 'R':
+ case 'r':
+ if (!PP.getLangOpts().FixedPoint) break;
+ if (isFract || isAccum) break;
+ if (!(saw_period || saw_exponent)) break;
+ isFract = true;
+ continue;
+ case 'K':
+ case 'k':
+ if (!PP.getLangOpts().FixedPoint) break;
+ if (isFract || isAccum) break;
+ if (!(saw_period || saw_exponent)) break;
+ isAccum = true;
+ continue;
case 'h': // FP Suffix for "half".
case 'H':
// OpenCL Extension v1.2 s9.5 - h or H suffix for half type.
- if (!PP.getLangOpts().Half) break;
- if (!isFPConstant) break; // Error for integer constant.
+ if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break;
+ if (isIntegerLiteral()) break; // Error for integer constant.
if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
isHalf = true;
continue; // Success.
@@ -693,6 +720,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isHalf = false;
isImaginary = false;
MicrosoftInteger = 0;
+ saw_fixed_point_suffix = false;
+ isFract = false;
+ isAccum = false;
}
saw_ud_suffix = true;
@@ -707,6 +737,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
hadError = true;
}
}
+
+ if (!hadError && saw_fixed_point_suffix) {
+ assert(isFract || isAccum);
+ }
}
/// ParseDecimalOrOctalCommon - This method is called for decimal or octal
@@ -717,7 +751,8 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){
// If we have a hex digit other than 'e' (which denotes a FP exponent) then
// the code is using an incorrect base.
- if (isHexDigit(*s) && *s != 'e' && *s != 'E') {
+ if (isHexDigit(*s) && *s != 'e' && *s != 'E' &&
+ !isValidUDSuffix(PP.getLangOpts(), StringRef(s, ThisTokEnd - s))) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0);
hadError = true;
@@ -770,12 +805,14 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
if (!LangOpts.CPlusPlus14)
return false;
- // In C++1y, "s", "h", "min", "ms", "us", and "ns" are used in the library.
+ // In C++14, "s", "h", "min", "ms", "us", and "ns" are used in the library.
// Per tweaked N3660, "il", "i", and "if" are also used in the library.
+ // In C++2a "d" and "y" are used in the library.
return llvm::StringSwitch<bool>(Suffix)
.Cases("h", "min", "s", true)
.Cases("ms", "us", "ns", true)
.Cases("il", "i", "if", true)
+ .Cases("d", "y", LangOpts.CPlusPlus2a)
.Default(false);
}
@@ -888,7 +925,9 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
s = SkipBinaryDigits(s);
if (s == ThisTokEnd) {
// Done.
- } else if (isHexDigit(*s)) {
+ } else if (isHexDigit(*s) &&
+ !isValidUDSuffix(PP.getLangOpts(),
+ StringRef(s, ThisTokEnd - s))) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
diag::err_invalid_digit) << StringRef(s, 1) << 2;
hadError = true;
@@ -1012,6 +1051,126 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
return Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
}
+static inline bool IsExponentPart(char c) {
+ return c == 'p' || c == 'P' || c == 'e' || c == 'E';
+}
+
+bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) {
+ assert(radix == 16 || radix == 10);
+
+ // Find how many digits are needed to store the whole literal.
+ unsigned NumDigits = SuffixBegin - DigitsBegin;
+ if (saw_period) --NumDigits;
+
+ // Initial scan of the exponent if it exists
+ bool ExpOverflowOccurred = false;
+ bool NegativeExponent = false;
+ const char *ExponentBegin;
+ uint64_t Exponent = 0;
+ int64_t BaseShift = 0;
+ if (saw_exponent) {
+ const char *Ptr = DigitsBegin;
+
+ while (!IsExponentPart(*Ptr)) ++Ptr;
+ ExponentBegin = Ptr;
+ ++Ptr;
+ NegativeExponent = *Ptr == '-';
+ if (NegativeExponent) ++Ptr;
+
+ unsigned NumExpDigits = SuffixBegin - Ptr;
+ if (alwaysFitsInto64Bits(radix, NumExpDigits)) {
+ llvm::StringRef ExpStr(Ptr, NumExpDigits);
+ llvm::APInt ExpInt(/*numBits=*/64, ExpStr, /*radix=*/10);
+ Exponent = ExpInt.getZExtValue();
+ } else {
+ ExpOverflowOccurred = true;
+ }
+
+ if (NegativeExponent) BaseShift -= Exponent;
+ else BaseShift += Exponent;
+ }
+
+ // Number of bits needed for decimal literal is
+ // ceil(NumDigits * log2(10)) Integral part
+ // + Scale Fractional part
+ // + ceil(Exponent * log2(10)) Exponent
+ // --------------------------------------------------
+ // ceil((NumDigits + Exponent) * log2(10)) + Scale
+ //
+ // But for simplicity in handling integers, we can round up log2(10) to 4,
+ // making:
+ // 4 * (NumDigits + Exponent) + Scale
+ //
+ // Number of digits needed for hexadecimal literal is
+ // 4 * NumDigits Integral part
+ // + Scale Fractional part
+ // + Exponent Exponent
+ // --------------------------------------------------
+ // (4 * NumDigits) + Scale + Exponent
+ uint64_t NumBitsNeeded;
+ if (radix == 10)
+ NumBitsNeeded = 4 * (NumDigits + Exponent) + Scale;
+ else
+ NumBitsNeeded = 4 * NumDigits + Exponent + Scale;
+
+ if (NumBitsNeeded > std::numeric_limits<unsigned>::max())
+ ExpOverflowOccurred = true;
+ llvm::APInt Val(static_cast<unsigned>(NumBitsNeeded), 0, /*isSigned=*/false);
+
+ bool FoundDecimal = false;
+
+ int64_t FractBaseShift = 0;
+ const char *End = saw_exponent ? ExponentBegin : SuffixBegin;
+ for (const char *Ptr = DigitsBegin; Ptr < End; ++Ptr) {
+ if (*Ptr == '.') {
+ FoundDecimal = true;
+ continue;
+ }
+
+ // Normal reading of an integer
+ unsigned C = llvm::hexDigitValue(*Ptr);
+ assert(C < radix && "NumericLiteralParser ctor should have rejected this");
+
+ Val *= radix;
+ Val += C;
+
+ if (FoundDecimal)
+ // Keep track of how much we will need to adjust this value by from the
+ // number of digits past the radix point.
+ --FractBaseShift;
+ }
+
+ // For a radix of 16, we will be multiplying by 2 instead of 16.
+ if (radix == 16) FractBaseShift *= 4;
+ BaseShift += FractBaseShift;
+
+ Val <<= Scale;
+
+ uint64_t Base = (radix == 16) ? 2 : 10;
+ if (BaseShift > 0) {
+ for (int64_t i = 0; i < BaseShift; ++i) {
+ Val *= Base;
+ }
+ } else if (BaseShift < 0) {
+ for (int64_t i = BaseShift; i < 0 && !Val.isNullValue(); ++i)
+ Val = Val.udiv(Base);
+ }
+
+ bool IntOverflowOccurred = false;
+ auto MaxVal = llvm::APInt::getMaxValue(StoreVal.getBitWidth());
+ if (Val.getBitWidth() > StoreVal.getBitWidth()) {
+ IntOverflowOccurred |= Val.ugt(MaxVal.zext(Val.getBitWidth()));
+ StoreVal = Val.trunc(StoreVal.getBitWidth());
+ } else if (Val.getBitWidth() < StoreVal.getBitWidth()) {
+ IntOverflowOccurred |= Val.zext(MaxVal.getBitWidth()).ugt(MaxVal);
+ StoreVal = Val.zext(StoreVal.getBitWidth());
+ } else {
+ StoreVal = Val;
+ }
+
+ return IntOverflowOccurred || ExpOverflowOccurred;
+}
+
/// \verbatim
/// user-defined-character-literal: [C++11 lex.ext]
/// character-literal ud-suffix
@@ -1380,7 +1539,7 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){
// that ThisTokBuf points to a buffer that is big enough for the whole token
// and 'spelled' tokens can only shrink.
bool StringInvalid = false;
- unsigned ThisTokLen =
+ unsigned ThisTokLen =
Lexer::getSpelling(StringToks[i], ThisTokBuf, SM, Features,
&StringInvalid);
if (StringInvalid)
@@ -1591,7 +1750,7 @@ static const char *resyncUTF8(const char *Err, const char *End) {
return Err;
}
-/// \brief This function copies from Fragment, which is a sequence of bytes
+/// This function copies from Fragment, which is a sequence of bytes
/// within Tok's contents (which begin at TokBegin) into ResultPtr.
/// Performs widening for multi-byte characters.
bool StringLiteralParser::CopyStringFragment(const Token &Tok,
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
index 5c0f0623c3e1..dc2ba3074a8b 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
@@ -29,7 +29,7 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
"Can't have args for an object-like macro!");
MacroArgs **ResultEnt = nullptr;
unsigned ClosestMatch = ~0U;
-
+
// See if we have an entry with a big enough argument list to reuse on the
// free list. If so, reuse it.
for (MacroArgs **Entry = &PP.MacroArgCache; *Entry;
@@ -37,7 +37,7 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
if ((*Entry)->NumUnexpArgTokens >= UnexpArgTokens.size() &&
(*Entry)->NumUnexpArgTokens < ClosestMatch) {
ResultEnt = Entry;
-
+
// If we have an exact match, use it.
if ((*Entry)->NumUnexpArgTokens == UnexpArgTokens.size())
break;
@@ -49,7 +49,8 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
if (!ResultEnt) {
// 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())))
+ Result = new (
+ llvm::safe_malloc(totalSizeToAlloc<Token>(UnexpArgTokens.size())))
MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumParams());
} else {
Result = *ResultEnt;
@@ -82,7 +83,7 @@ void MacroArgs::destroy(Preprocessor &PP) {
// would deallocate the element vectors.
for (unsigned i = 0, e = PreExpArgTokens.size(); i != e; ++i)
PreExpArgTokens[i].clear();
-
+
// Add this to the preprocessor's free list.
ArgCache = PP.MacroArgCache;
PP.MacroArgCache = this;
@@ -92,14 +93,14 @@ void MacroArgs::destroy(Preprocessor &PP) {
/// its freelist.
MacroArgs *MacroArgs::deallocate() {
MacroArgs *Next = ArgCache;
-
+
// 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;
}
@@ -124,7 +125,7 @@ const Token *MacroArgs::getUnexpArgument(unsigned Arg) const {
// in memory.
const Token *Start = getTrailingObjects<Token>();
const Token *Result = Start;
-
+
// Scan to find Arg.
for (; Arg; ++Result) {
assert(Result < Start+NumUnexpArgTokens && "Invalid arg #");
@@ -170,7 +171,7 @@ const std::vector<Token> &MacroArgs::getPreExpArgument(unsigned Arg,
// If we have already computed this, return it.
if (PreExpArgTokens.size() < getNumMacroArguments())
PreExpArgTokens.resize(getNumMacroArguments());
-
+
std::vector<Token> &Result = PreExpArgTokens[Arg];
if (!Result.empty()) return Result;
@@ -272,7 +273,7 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks,
// If the last character of the string is a \, and if it isn't escaped, this
// is an invalid string literal, diagnose it as specified in C99.
if (Result.back() == '\\') {
- // Count the number of consequtive \ characters. If even, then they are
+ // Count the number of consecutive \ characters. If even, then they are
// just escaped backslashes, otherwise it's an error.
unsigned FirstNonSlash = Result.size()-2;
// Guaranteed to find the starting " if nothing else.
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
index b13767aa1d67..4ed69ecc465d 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
@@ -65,7 +65,7 @@ unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const {
return DefinitionLength;
}
-/// \brief Return true if the specified macro definition is equal to
+/// Return true if the specified macro definition is equal to
/// this macro in spelling, arguments, and whitespace.
///
/// \param Syntactically if true, the macro definitions can be identical even
diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
index b3ac10c5c5ae..87749f74734c 100644
--- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
@@ -54,6 +54,24 @@
using namespace clang;
+void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
+ auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
+ if (PendingLinkAs != PendingLinkAsModule.end()) {
+ for (auto &Name : PendingLinkAs->second) {
+ auto *M = findModule(Name.getKey());
+ if (M)
+ M->UseExportAsModuleLinkName = true;
+ }
+ }
+}
+
+void ModuleMap::addLinkAsDependency(Module *Mod) {
+ if (findModule(Mod->ExportAsModule))
+ Mod->UseExportAsModuleLinkName = true;
+ else
+ PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
+}
+
Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
switch ((int)Role) {
default: llvm_unreachable("unknown header role");
@@ -85,8 +103,8 @@ ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
llvm_unreachable("unknown header kind");
}
-Module::ExportDecl
-ModuleMap::resolveExport(Module *Mod,
+Module::ExportDecl
+ModuleMap::resolveExport(Module *Mod,
const Module::UnresolvedExportDecl &Unresolved,
bool Complain) const {
// We may have just a wildcard.
@@ -94,7 +112,7 @@ ModuleMap::resolveExport(Module *Mod,
assert(Unresolved.Wildcard && "Invalid unresolved export");
return Module::ExportDecl(nullptr, true);
}
-
+
// Resolve the module-id.
Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
if (!Context)
@@ -133,7 +151,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context;
}
-/// \brief Append to \p Paths the set of paths needed to get to the
+/// Append to \p Paths the set of paths needed to get to the
/// subframework in which the given module lives.
static void appendSubframeworkPaths(Module *Mod,
SmallVectorImpl<char> &Path) {
@@ -143,19 +161,22 @@ static void appendSubframeworkPaths(Module *Mod,
if (Mod->IsFramework)
Paths.push_back(Mod->Name);
}
-
+
if (Paths.empty())
return;
-
+
// Add Frameworks/Name.framework for each subframework.
for (unsigned I = Paths.size() - 1; I != 0; --I)
llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
}
-const FileEntry *
-ModuleMap::findHeader(Module *M,
- const Module::UnresolvedHeaderDirective &Header,
- SmallVectorImpl<char> &RelativePathName) {
+const FileEntry *ModuleMap::findHeader(
+ Module *M, const Module::UnresolvedHeaderDirective &Header,
+ SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
+ // Search for the header file within the module's home directory.
+ auto *Directory = M->Directory;
+ SmallString<128> FullPathName(Directory->getName());
+
auto GetFile = [&](StringRef Filename) -> const FileEntry * {
auto *File = SourceMgr.getFileManager().getFile(Filename);
if (!File ||
@@ -165,18 +186,8 @@ ModuleMap::findHeader(Module *M,
return File;
};
- if (llvm::sys::path::is_absolute(Header.FileName)) {
- RelativePathName.clear();
- RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
- return GetFile(Header.FileName);
- }
-
- // Search for the header file within the module's home directory.
- auto *Directory = M->Directory;
- SmallString<128> FullPathName(Directory->getName());
- unsigned FullPathLength = FullPathName.size();
-
- if (M->isPartOfFramework()) {
+ auto GetFrameworkFile = [&]() -> const FileEntry * {
+ unsigned FullPathLength = FullPathName.size();
appendSubframeworkPaths(M, RelativePathName);
unsigned RelativePathLength = RelativePathName.size();
@@ -201,18 +212,46 @@ ModuleMap::findHeader(Module *M,
Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
return GetFile(FullPathName);
+ };
+
+ if (llvm::sys::path::is_absolute(Header.FileName)) {
+ RelativePathName.clear();
+ RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
+ return GetFile(Header.FileName);
}
+ if (M->isPartOfFramework())
+ return GetFrameworkFile();
+
// Lookup for normal headers.
llvm::sys::path::append(RelativePathName, Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
- return GetFile(FullPathName);
+ auto *NormalHdrFile = GetFile(FullPathName);
+
+ if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
+ // The lack of 'framework' keyword in a module declaration it's a simple
+ // mistake we can diagnose when the header exists within the proper
+ // framework style path.
+ FullPathName.assign(Directory->getName());
+ RelativePathName.clear();
+ if (GetFrameworkFile()) {
+ Diags.Report(Header.FileNameLoc,
+ diag::warn_mmap_incomplete_framework_module_declaration)
+ << Header.FileName << M->getFullModuleName();
+ NeedsFramework = true;
+ }
+ return nullptr;
+ }
+
+ return NormalHdrFile;
}
void ModuleMap::resolveHeader(Module *Mod,
- const Module::UnresolvedHeaderDirective &Header) {
+ const Module::UnresolvedHeaderDirective &Header,
+ bool &NeedsFramework) {
SmallString<128> RelativePathName;
- if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
+ if (const FileEntry *File =
+ findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
if (Header.IsUmbrella) {
const DirectoryEntry *UmbrellaDir = File->getDir();
if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
@@ -281,15 +320,17 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
ModuleMap::~ModuleMap() {
for (auto &M : Modules)
delete M.getValue();
+ for (auto *M : ShadowModules)
+ delete M;
}
void ModuleMap::setTarget(const TargetInfo &Target) {
- assert((!this->Target || this->Target == &Target) &&
+ assert((!this->Target || this->Target == &Target) &&
"Improper target override");
this->Target = &Target;
}
-/// \brief "Sanitize" a filename so that it can be used as an identifier.
+/// "Sanitize" a filename so that it can be used as an identifier.
static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
SmallVectorImpl<char> &Buffer) {
if (Name.empty())
@@ -326,7 +367,7 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
return Name;
}
-/// \brief Determine whether the given file name is the name of a builtin
+/// Determine whether the given file name is the name of a builtin
/// header, supplied by Clang to replace, override, or augment existing system
/// headers.
bool ModuleMap::isBuiltinHeader(StringRef FileName) {
@@ -473,7 +514,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
// We have found a module, but we don't use it.
if (NotUsed) {
Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
- << RequestingModule->getFullModuleName() << Filename;
+ << RequestingModule->getTopLevelModule()->Name << Filename;
return;
}
@@ -484,10 +525,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
if (LangOpts.ModulesStrictDeclUse) {
Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
- << RequestingModule->getFullModuleName() << Filename;
+ << RequestingModule->getTopLevelModule()->Name << Filename;
} else if (RequestingModule && RequestingModuleIsModuleInterface &&
LangOpts.isCompilingModule()) {
- // Do not diagnose when we are not compiling a module.
+ // Do not diagnose when we are not compiling a module.
diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
diag::warn_non_modular_include_in_framework_module :
diag::warn_non_modular_include_in_module;
@@ -691,7 +732,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
if (IsUnavailable(Found))
return true;
}
-
+
// Infer a submodule with the same name as this header file.
SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier(
@@ -704,18 +745,18 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
return IsUnavailable(Found);
}
-
+
SkippedDirs.push_back(Dir);
-
+
// Retrieve our parent path.
DirName = llvm::sys::path::parent_path(DirName);
if (DirName.empty())
break;
-
+
// Resolve the parent path to a directory entry.
Dir = SourceMgr.getFileManager().getDirectory(DirName);
} while (Dir);
-
+
return false;
}
@@ -733,14 +774,14 @@ Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
if (Module *Sub = lookupModuleQualified(Name, Context))
return Sub;
}
-
+
return findModule(Name);
}
Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
if (!Context)
return findModule(Name);
-
+
return Context->findSubmodule(Name);
}
@@ -751,7 +792,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
// Try to find an existing module with this name.
if (Module *Sub = lookupModuleQualified(Name, Parent))
return std::make_pair(Sub, false);
-
+
// Create a new module with this name.
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
IsExplicit, NumCreatedModules++);
@@ -759,6 +800,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
if (LangOpts.CurrentModule == Name)
SourceModule = Result;
Modules[Name] = Result;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
}
return std::make_pair(Result, true);
}
@@ -799,7 +841,7 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
return Result;
}
-/// \brief For a framework module, infer the framework against which we
+/// For a framework module, infer the framework against which we
/// should link.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
FileManager &FileMgr) {
@@ -850,7 +892,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
// Check whether we've already found this module.
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
return Mod;
-
+
FileManager &FileMgr = SourceMgr.getFileManager();
// If the framework has a parent path from which we're allowed to infer
@@ -911,7 +953,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
-
+
// FIXME: If there's no umbrella header, we could probably scan the
// framework to load *everything*. But, it's not clear that this is a good
// idea.
@@ -927,6 +969,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
if (LangOpts.CurrentModule == ModuleName)
SourceModule = Result;
Modules[ModuleName] = Result;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
}
Result->IsSystem |= Attrs.IsSystem;
@@ -940,14 +983,14 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
// The "Headers/" component of the name is implied because this is
// a framework module.
setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
-
+
// export *
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
// module * { export * }
Result->InferSubmodules = true;
Result->InferExportWildcard = true;
-
+
// Look for subframeworks.
std::error_code EC;
SmallString<128> SubframeworksDirName
@@ -999,6 +1042,21 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
return Result;
}
+Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
+ Module *ShadowingModule) {
+
+ // Create a new module with this name.
+ Module *Result =
+ new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
+ /*IsExplicit=*/false, NumCreatedModules++);
+ Result->ShadowingModule = ShadowingModule;
+ Result->IsAvailable = false;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
+ ShadowModules.push_back(Result);
+
+ return Result;
+}
+
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
Twine NameAsWritten) {
Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
@@ -1019,7 +1077,8 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
}
void ModuleMap::addUnresolvedHeader(Module *Mod,
- Module::UnresolvedHeaderDirective Header) {
+ Module::UnresolvedHeaderDirective Header,
+ bool &NeedsFramework) {
// If there is a builtin counterpart to this file, add it now so it can
// wrap the system header.
if (resolveAsBuiltinHeader(Mod, Header)) {
@@ -1050,7 +1109,7 @@ void ModuleMap::addUnresolvedHeader(Module *Mod,
// We don't have stat information or can't defer looking this file up.
// Perform the lookup now.
- resolveHeader(Mod, Header);
+ resolveHeader(Mod, Header, NeedsFramework);
}
void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
@@ -1070,10 +1129,11 @@ void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
}
void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
+ bool NeedsFramework = false;
for (auto &Header : Mod->UnresolvedHeaders)
// This operation is logically const; we're just changing how we represent
// the header information for this file.
- const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header);
+ const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
Mod->UnresolvedHeaders.clear();
}
@@ -1140,11 +1200,11 @@ void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
LLVM_DUMP_METHOD void ModuleMap::dump() {
llvm::errs() << "Modules:";
- for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
- MEnd = Modules.end();
+ for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
+ MEnd = Modules.end();
M != MEnd; ++M)
M->getValue()->print(llvm::errs(), 2);
-
+
llvm::errs() << "Headers:";
for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
H != HEnd; ++H) {
@@ -1207,7 +1267,7 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
namespace clang {
- /// \brief A token in a module map file.
+ /// A token in a module map file.
struct MMToken {
enum TokenKind {
Comma,
@@ -1239,7 +1299,7 @@ namespace clang {
LSquare,
RSquare
} Kind;
-
+
unsigned Location;
unsigned StringLength;
union {
@@ -1249,16 +1309,16 @@ namespace clang {
// If Kind == IntegerLiteral.
uint64_t IntegerValue;
};
-
+
void clear() {
Kind = EndOfFile;
Location = 0;
StringLength = 0;
StringData = nullptr;
}
-
+
bool is(TokenKind K) const { return Kind == K; }
-
+
SourceLocation getLocation() const {
return SourceLocation::getFromRawEncoding(Location);
}
@@ -1266,7 +1326,7 @@ namespace clang {
uint64_t getInteger() const {
return Kind == IntegerLiteral ? IntegerValue : 0;
}
-
+
StringRef getString() const {
return Kind == IntegerLiteral ? StringRef()
: StringRef(StringData, StringLength);
@@ -1277,37 +1337,40 @@ namespace clang {
Lexer &L;
SourceManager &SourceMgr;
- /// \brief Default target information, used only for string literal
+ /// Default target information, used only for string literal
/// parsing.
const TargetInfo *Target;
DiagnosticsEngine &Diags;
ModuleMap &Map;
- /// \brief The current module map file.
+ /// The current module map file.
const FileEntry *ModuleMapFile;
-
- /// \brief The directory that file names in this module map file should
+
+ /// Source location of most recent parsed module declaration
+ SourceLocation CurrModuleDeclLoc;
+
+ /// The directory that file names in this module map file should
/// be resolved relative to.
const DirectoryEntry *Directory;
- /// \brief Whether this module map is in a system header directory.
+ /// Whether this module map is in a system header directory.
bool IsSystem;
-
- /// \brief Whether an error occurred.
+
+ /// Whether an error occurred.
bool HadError = false;
-
- /// \brief Stores string data for the various string literals referenced
+
+ /// Stores string data for the various string literals referenced
/// during parsing.
llvm::BumpPtrAllocator StringData;
-
- /// \brief The current token.
+
+ /// The current token.
MMToken Tok;
-
- /// \brief The active module.
+
+ /// The active module.
Module *ActiveModule = nullptr;
- /// \brief Whether a module uses the 'requires excluded' hack to mark its
+ /// Whether a module uses the 'requires excluded' hack to mark its
/// contents as 'textual'.
///
/// On older Darwin SDK versions, 'requires excluded' is used to mark the
@@ -1317,10 +1380,10 @@ namespace clang {
/// 'textual' to match the original intent.
llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
- /// \brief Consume the current token and return its location.
+ /// Consume the current token and return its location.
SourceLocation consumeToken();
-
- /// \brief Skip tokens until we reach the a token with the given kind
+
+ /// Skip tokens until we reach the a token with the given kind
/// (or the end of the file).
void skipUntil(MMToken::TokenKind K);
@@ -1340,25 +1403,29 @@ namespace clang {
void parseConflict();
void parseInferredModuleDecl(bool Framework, bool Explicit);
+ /// Private modules are canonicalized as Foo_Private. Clang provides extra
+ /// module map search logic to find the appropriate private module when PCH
+ /// is used with implicit module maps. Warn when private modules are written
+ /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
+ void diagnosePrivateModules(SourceLocation ExplicitLoc,
+ SourceLocation FrameworkLoc);
+
using Attributes = ModuleMap::Attributes;
bool parseOptionalAttributes(Attributes &Attrs);
-
+
public:
- explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
- const TargetInfo *Target,
- DiagnosticsEngine &Diags,
- ModuleMap &Map,
- const FileEntry *ModuleMapFile,
- const DirectoryEntry *Directory,
- bool IsSystem)
+ explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
+ const TargetInfo *Target, DiagnosticsEngine &Diags,
+ ModuleMap &Map, const FileEntry *ModuleMapFile,
+ const DirectoryEntry *Directory, bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
ModuleMapFile(ModuleMapFile), Directory(Directory),
IsSystem(IsSystem) {
Tok.clear();
consumeToken();
}
-
+
bool parseModuleMapFile();
bool terminatedByDirective() { return false; }
@@ -1408,7 +1475,7 @@ retry:
case tok::eof:
Tok.Kind = MMToken::EndOfFile;
break;
-
+
case tok::l_brace:
Tok.Kind = MMToken::LBrace;
break;
@@ -1416,27 +1483,27 @@ retry:
case tok::l_square:
Tok.Kind = MMToken::LSquare;
break;
-
+
case tok::period:
Tok.Kind = MMToken::Period;
break;
-
+
case tok::r_brace:
Tok.Kind = MMToken::RBrace;
break;
-
+
case tok::r_square:
Tok.Kind = MMToken::RSquare;
break;
-
+
case tok::star:
Tok.Kind = MMToken::Star;
break;
-
+
case tok::exclaim:
Tok.Kind = MMToken::Exclaim;
break;
-
+
case tok::string_literal: {
if (LToken.hasUDSuffix()) {
Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
@@ -1449,13 +1516,13 @@ retry:
StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
if (StringLiteral.hadError)
goto retry;
-
+
// Copy the string literal into our string data allocator.
unsigned Length = StringLiteral.GetStringLength();
char *Saved = StringData.Allocate<char>(Length + 1);
memcpy(Saved, StringLiteral.GetString().data(), Length);
Saved[Length] = 0;
-
+
// Form the token.
Tok.Kind = MMToken::StringLiteral;
Tok.StringData = Saved;
@@ -1481,7 +1548,7 @@ retry:
Tok.IntegerValue = Value;
break;
}
-
+
case tok::comment:
goto retry;
@@ -1509,7 +1576,7 @@ retry:
HadError = true;
goto retry;
}
-
+
return Result;
}
@@ -1524,14 +1591,14 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
case MMToken::LBrace:
if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
return;
-
+
++braceDepth;
break;
case MMToken::LSquare:
if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
return;
-
+
++squareDepth;
break;
@@ -1554,12 +1621,12 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
return;
break;
}
-
+
consumeToken();
} while (true);
}
-/// \brief Parse a module-id.
+/// Parse a module-id.
///
/// module-id:
/// identifier
@@ -1576,33 +1643,33 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
return true;
}
-
+
if (!Tok.is(MMToken::Period))
break;
-
+
consumeToken();
} while (true);
-
+
return false;
}
namespace {
- /// \brief Enumerates the known attributes.
+ /// Enumerates the known attributes.
enum AttributeKind {
- /// \brief An unknown attribute.
+ /// An unknown attribute.
AT_unknown,
- /// \brief The 'system' attribute.
+ /// The 'system' attribute.
AT_system,
- /// \brief The 'extern_c' attribute.
+ /// The 'extern_c' attribute.
AT_extern_c,
- /// \brief The 'exhaustive' attribute.
+ /// The 'exhaustive' attribute.
AT_exhaustive,
- /// \brief The 'no_undeclared_includes' attribute.
+ /// The 'no_undeclared_includes' attribute.
AT_no_undeclared_includes
};
@@ -1612,16 +1679,14 @@ namespace {
/// module map search logic to find the appropriate private module when PCH
/// is used with implicit module maps. Warn when private modules are written
/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
-static void diagnosePrivateModules(const ModuleMap &Map,
- DiagnosticsEngine &Diags,
- const Module *ActiveModule) {
-
+void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
+ SourceLocation FrameworkLoc) {
auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
- const Module *M) {
+ const Module *M, SourceRange ReplLoc) {
auto D = Diags.Report(ActiveModule->DefinitionLoc,
diag::note_mmap_rename_top_level_private_module);
D << BadName << M->Name;
- D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical);
+ D << FixItHint::CreateReplacement(ReplLoc, Canonical);
};
for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
@@ -1632,6 +1697,7 @@ static void diagnosePrivateModules(const ModuleMap &Map,
SmallString<128> FullName(ActiveModule->getFullModuleName());
if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
continue;
+ SmallString<128> FixedPrivModDecl;
SmallString<128> Canonical(M->Name);
Canonical.append("_Private");
@@ -1641,7 +1707,20 @@ static void diagnosePrivateModules(const ModuleMap &Map,
Diags.Report(ActiveModule->DefinitionLoc,
diag::warn_mmap_mismatched_private_submodule)
<< FullName;
- GenNoteAndFixIt(FullName, Canonical, M);
+
+ SourceLocation FixItInitBegin = CurrModuleDeclLoc;
+ if (FrameworkLoc.isValid())
+ FixItInitBegin = FrameworkLoc;
+ if (ExplicitLoc.isValid())
+ FixItInitBegin = ExplicitLoc;
+
+ if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
+ FixedPrivModDecl.append("framework ");
+ FixedPrivModDecl.append("module ");
+ FixedPrivModDecl.append(Canonical);
+
+ GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
+ SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
continue;
}
@@ -1651,16 +1730,17 @@ static void diagnosePrivateModules(const ModuleMap &Map,
Diags.Report(ActiveModule->DefinitionLoc,
diag::warn_mmap_mismatched_private_module_name)
<< ActiveModule->Name;
- GenNoteAndFixIt(ActiveModule->Name, Canonical, M);
+ GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
+ SourceRange(ActiveModule->DefinitionLoc));
}
}
}
-/// \brief Parse a module declaration.
+/// Parse a module declaration.
///
/// module-declaration:
/// 'extern' 'module' module-id string-literal
-/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
+/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
/// { module-member* }
///
/// module-member:
@@ -1684,6 +1764,7 @@ void ModuleMapParser::parseModuleDecl() {
// Parse 'explicit' or 'framework' keyword, if present.
SourceLocation ExplicitLoc;
+ SourceLocation FrameworkLoc;
bool Explicit = false;
bool Framework = false;
@@ -1695,10 +1776,10 @@ void ModuleMapParser::parseModuleDecl() {
// Parse 'framework' keyword, if present.
if (Tok.is(MMToken::FrameworkKeyword)) {
- consumeToken();
+ FrameworkLoc = consumeToken();
Framework = true;
- }
-
+ }
+
// Parse 'module' keyword.
if (!Tok.is(MMToken::ModuleKeyword)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
@@ -1706,13 +1787,13 @@ void ModuleMapParser::parseModuleDecl() {
HadError = true;
return;
}
- consumeToken(); // 'module' keyword
+ CurrModuleDeclLoc = consumeToken(); // 'module' keyword
// If we have a wildcard for the module name, this is an inferred submodule.
- // Parse it.
+ // Parse it.
if (Tok.is(MMToken::Star))
return parseInferredModuleDecl(Framework, Explicit);
-
+
// Parse the module name.
ModuleId Id;
if (parseModuleId(Id)) {
@@ -1724,7 +1805,7 @@ void ModuleMapParser::parseModuleDecl() {
if (Id.size() > 1) {
Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
<< SourceRange(Id.front().second, Id.back().second);
-
+
HadError = true;
return;
}
@@ -1735,8 +1816,8 @@ void ModuleMapParser::parseModuleDecl() {
ExplicitLoc = SourceLocation();
HadError = true;
}
-
- Module *PreviousActiveModule = ActiveModule;
+
+ Module *PreviousActiveModule = ActiveModule;
if (Id.size() > 1) {
// This module map defines a submodule. Go find the module of which it
// is a submodule.
@@ -1749,7 +1830,7 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule = Next;
continue;
}
-
+
if (ActiveModule) {
Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
<< Id[I].first
@@ -1768,10 +1849,10 @@ void ModuleMapParser::parseModuleDecl() {
Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
}
}
-
+
StringRef ModuleName = Id.back().first;
SourceLocation ModuleNameLoc = Id.back().second;
-
+
// Parse the optional attribute list.
Attributes Attrs;
if (parseOptionalAttributes(Attrs))
@@ -1783,10 +1864,11 @@ void ModuleMapParser::parseModuleDecl() {
<< ModuleName;
HadError = true;
return;
- }
+ }
SourceLocation LBraceLoc = consumeToken();
-
+
// Determine whether this (sub)module has already been defined.
+ Module *ShadowingModule = nullptr;
if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
// We might see a (re)definition of a module that we already have a
// definition for in two cases:
@@ -1808,27 +1890,39 @@ void ModuleMapParser::parseModuleDecl() {
else {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
- HadError = true;
+ HadError = true;
}
return;
}
-
- Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
- << ModuleName;
- Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
-
- // Skip the module definition.
- skipUntil(MMToken::RBrace);
- if (Tok.is(MMToken::RBrace))
- consumeToken();
-
- HadError = true;
- return;
+
+ if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
+ ShadowingModule = Existing;
+ } else {
+ // This is not a shawdowed module decl, it is an illegal redefinition.
+ Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
+ << ModuleName;
+ Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
+
+ // Skip the module definition.
+ skipUntil(MMToken::RBrace);
+ if (Tok.is(MMToken::RBrace))
+ consumeToken();
+
+ HadError = true;
+ return;
+ }
}
// Start defining this module.
- ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
- Explicit).first;
+ if (ShadowingModule) {
+ ActiveModule =
+ Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
+ } else {
+ ActiveModule =
+ Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
+ .first;
+ }
+
ActiveModule->DefinitionLoc = ModuleNameLoc;
if (Attrs.IsSystem || IsSystem)
ActiveModule->IsSystem = true;
@@ -1839,21 +1933,24 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule->NoUndeclaredIncludes = true;
ActiveModule->Directory = Directory;
+ StringRef MapFileName(ModuleMapFile->getName());
+ if (MapFileName.endswith("module.private.modulemap") ||
+ MapFileName.endswith("module_private.map")) {
+ ActiveModule->ModuleMapIsPrivate = true;
+ }
// Private modules named as FooPrivate, Foo.Private or similar are likely a
// user error; provide warnings, notes and fixits to direct users to use
// Foo_Private instead.
SourceLocation StartLoc =
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
- StringRef MapFileName(ModuleMapFile->getName());
if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
!Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
StartLoc) &&
!Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
StartLoc) &&
- (MapFileName.endswith("module.private.modulemap") ||
- MapFileName.endswith("module_private.map")))
- diagnosePrivateModules(Map, Diags, ActiveModule);
+ ActiveModule->ModuleMapIsPrivate)
+ diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
bool Done = false;
do {
@@ -1889,7 +1986,7 @@ void ModuleMapParser::parseModuleDecl() {
case MMToken::UseKeyword:
parseUseDecl();
break;
-
+
case MMToken::RequiresKeyword:
parseRequiresDecl();
break;
@@ -1926,7 +2023,7 @@ void ModuleMapParser::parseModuleDecl() {
default:
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
consumeToken();
- break;
+ break;
}
} while (!Done);
@@ -1958,7 +2055,7 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule = PreviousActiveModule;
}
-/// \brief Parse an extern module declaration.
+/// Parse an extern module declaration.
///
/// extern module-declaration:
/// 'extern' 'module' module-id string-literal
@@ -2036,7 +2133,7 @@ static bool shouldAddRequirement(Module *M, StringRef Feature,
return true;
}
-/// \brief Parse a requires declaration.
+/// Parse a requires declaration.
///
/// requires-declaration:
/// 'requires' feature-list
@@ -2092,7 +2189,7 @@ void ModuleMapParser::parseRequiresDecl() {
} while (true);
}
-/// \brief Parse a header declaration.
+/// Parse a header declaration.
///
/// header-declaration:
/// 'textual'[opt] 'header' string-literal
@@ -2136,7 +2233,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// Parse the header name.
if (!Tok.is(MMToken::StringLiteral)) {
- Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
<< "header";
HadError = true;
return;
@@ -2212,7 +2309,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
}
}
- Map.addUnresolvedHeader(ActiveModule, std::move(Header));
+ bool NeedsFramework = false;
+ Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
+
+ if (NeedsFramework && ActiveModule)
+ Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
+ << ActiveModule->getFullModuleName()
+ << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
}
static int compareModuleHeaders(const Module::Header *A,
@@ -2220,14 +2323,14 @@ static int compareModuleHeaders(const Module::Header *A,
return A->NameAsWritten.compare(B->NameAsWritten);
}
-/// \brief Parse an umbrella directory declaration.
+/// Parse an umbrella directory declaration.
///
/// umbrella-dir-declaration:
/// umbrella string-literal
void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
// Parse the directory name.
if (!Tok.is(MMToken::StringLiteral)) {
- Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
<< "umbrella";
HadError = true;
return;
@@ -2235,7 +2338,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
std::string DirName = Tok.getString();
SourceLocation DirNameLoc = consumeToken();
-
+
// Check whether we already have an umbrella.
if (ActiveModule->Umbrella) {
Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
@@ -2254,7 +2357,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
llvm::sys::path::append(PathName, DirName);
Dir = SourceMgr.getFileManager().getDirectory(PathName);
}
-
+
if (!Dir) {
Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
<< DirName;
@@ -2298,7 +2401,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
Map.setUmbrellaDir(ActiveModule, Dir, DirName);
}
-/// \brief Parse a module export declaration.
+/// Parse a module export declaration.
///
/// export-declaration:
/// 'export' wildcard-module-id
@@ -2310,43 +2413,43 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
void ModuleMapParser::parseExportDecl() {
assert(Tok.is(MMToken::ExportKeyword));
SourceLocation ExportLoc = consumeToken();
-
+
// Parse the module-id with an optional wildcard at the end.
ModuleId ParsedModuleId;
bool Wildcard = false;
do {
// FIXME: Support string-literal module names here.
if (Tok.is(MMToken::Identifier)) {
- ParsedModuleId.push_back(std::make_pair(Tok.getString(),
+ ParsedModuleId.push_back(std::make_pair(Tok.getString(),
Tok.getLocation()));
consumeToken();
-
+
if (Tok.is(MMToken::Period)) {
consumeToken();
continue;
- }
-
+ }
+
break;
}
-
+
if(Tok.is(MMToken::Star)) {
Wildcard = true;
consumeToken();
break;
}
-
+
Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
HadError = true;
return;
} while (true);
-
- Module::UnresolvedExportDecl Unresolved = {
- ExportLoc, ParsedModuleId, Wildcard
+
+ Module::UnresolvedExportDecl Unresolved = {
+ ExportLoc, ParsedModuleId, Wildcard
};
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
-/// \brief Parse a module export_as declaration.
+/// Parse a module export_as declaration.
///
/// export-as-declaration:
/// 'export_as' identifier
@@ -2365,7 +2468,7 @@ void ModuleMapParser::parseExportAsDecl() {
consumeToken();
return;
}
-
+
if (!ActiveModule->ExportAsModule.empty()) {
if (ActiveModule->ExportAsModule == Tok.getString()) {
Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
@@ -2376,12 +2479,14 @@ void ModuleMapParser::parseExportAsDecl() {
<< Tok.getString();
}
}
-
+
ActiveModule->ExportAsModule = Tok.getString();
+ Map.addLinkAsDependency(ActiveModule);
+
consumeToken();
}
-/// \brief Parse a module use declaration.
+/// Parse a module use declaration.
///
/// use-declaration:
/// 'use' wildcard-module-id
@@ -2398,7 +2503,7 @@ void ModuleMapParser::parseUseDecl() {
ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
}
-/// \brief Parse a link declaration.
+/// Parse a link declaration.
///
/// module-declaration:
/// 'link' 'framework'[opt] string-literal
@@ -2427,7 +2532,7 @@ void ModuleMapParser::parseLinkDecl() {
IsFramework));
}
-/// \brief Parse a configuration macro declaration.
+/// Parse a configuration macro declaration.
///
/// module-declaration:
/// 'config_macros' attributes[opt] config-macro-list?
@@ -2484,7 +2589,7 @@ void ModuleMapParser::parseConfigMacros() {
} while (true);
}
-/// \brief Format a module-id into a string.
+/// Format a module-id into a string.
static std::string formatModuleId(const ModuleId &Id) {
std::string result;
{
@@ -2500,7 +2605,7 @@ static std::string formatModuleId(const ModuleId &Id) {
return result;
}
-/// \brief Parse a conflict declaration.
+/// Parse a conflict declaration.
///
/// module-declaration:
/// 'conflict' module-id ',' string-literal
@@ -2534,7 +2639,7 @@ void ModuleMapParser::parseConflict() {
ActiveModule->UnresolvedConflicts.push_back(Conflict);
}
-/// \brief Parse an inferred module declaration (wildcard modules).
+/// Parse an inferred module declaration (wildcard modules).
///
/// module-declaration:
/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
@@ -2561,7 +2666,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
Failed = true;
}
-
+
// Check for redefinition of an inferred module.
if (!Failed && ActiveModule->InferSubmodules) {
Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
@@ -2616,7 +2721,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
HadError = true;
return;
- }
+ }
SourceLocation LBraceLoc = consumeToken();
// Parse the body of the inferred submodule.
@@ -2657,10 +2762,10 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
}
consumeToken();
- if (Tok.is(MMToken::Star))
+ if (Tok.is(MMToken::Star))
ActiveModule->InferExportWildcard = true;
else
- Diags.Report(Tok.getLocation(),
+ Diags.Report(Tok.getLocation(),
diag::err_mmap_expected_export_wildcard);
consumeToken();
break;
@@ -2674,10 +2779,10 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
<< (ActiveModule != nullptr);
consumeToken();
- break;
+ break;
}
} while (!Done);
-
+
if (Tok.is(MMToken::RBrace))
consumeToken();
else {
@@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
}
}
-/// \brief Parse optional attributes.
+/// Parse optional attributes.
///
/// attributes:
/// attribute attributes
@@ -2701,7 +2806,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
/// \returns true if an error occurred, false otherwise.
bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
bool HadError = false;
-
+
while (Tok.is(MMToken::LSquare)) {
// Consume the '['.
SourceLocation LSquareLoc = consumeToken();
@@ -2762,7 +2867,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
return HadError;
}
-/// \brief Parse a module map file.
+/// Parse a module map file.
///
/// module-map-file:
/// module-declaration*
@@ -2771,7 +2876,7 @@ bool ModuleMapParser::parseModuleMapFile() {
switch (Tok.Kind) {
case MMToken::EndOfFile:
return HadError;
-
+
case MMToken::ExplicitKeyword:
case MMToken::ExternKeyword:
case MMToken::ModuleKeyword:
@@ -2854,5 +2959,6 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
// Notify callbacks that we parsed it.
for (const auto &Cb : Callbacks)
Cb->moduleMapFileRead(Start, *File, IsSystem);
+
return Result;
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
index ca3e70fd1060..66a9faa6e60a 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements # directive processing for the Preprocessor.
+/// Implements # directive processing for the Preprocessor.
///
//===----------------------------------------------------------------------===//
@@ -78,7 +78,7 @@ Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc,
return new (BP) VisibilityMacroDirective(Loc, isPublic);
}
-/// \brief Read and discard all tokens remaining on the current line until
+/// Read and discard all tokens remaining on the current line until
/// the tok::eod token is found.
void Preprocessor::DiscardUntilEndOfDirective() {
Token Tmp;
@@ -88,14 +88,14 @@ void Preprocessor::DiscardUntilEndOfDirective() {
} while (Tmp.isNot(tok::eod));
}
-/// \brief Enumerates possible cases of #define/#undef a reserved identifier.
+/// Enumerates possible cases of #define/#undef a reserved identifier.
enum MacroDiag {
MD_NoWarn, //> Not a reserved identifier
MD_KeywordDef, //> Macro hides keyword, enabled by default
MD_ReservedMacro //> #define of #undef reserved id, disabled by default
};
-/// \brief Checks if the specified identifier is reserved in the specified
+/// Checks if the specified identifier is reserved in the specified
/// language.
/// This function does not check if the identifier is a keyword.
static bool isReservedId(StringRef Text, const LangOptions &Lang) {
@@ -115,6 +115,25 @@ static bool isReservedId(StringRef Text, const LangOptions &Lang) {
return false;
}
+// The -fmodule-name option tells the compiler to textually include headers in
+// the specified module, meaning clang won't build the specified module. This is
+// useful in a number of situations, for instance, when building a library that
+// vends a module map, one might want to avoid hitting intermediate build
+// products containig the the module map or avoid finding the system installed
+// modulemap for that library.
+static bool isForModuleBuilding(Module *M, StringRef CurrentModule,
+ StringRef ModuleName) {
+ StringRef TopLevelName = M->getTopLevelModuleName();
+
+ // When building framework Foo, we wanna make sure that Foo *and* Foo_Private
+ // are textually included and no modules are built for both.
+ if (M->getTopLevelModule()->IsFramework && CurrentModule == ModuleName &&
+ !CurrentModule.endswith("_Private") && TopLevelName.endswith("_Private"))
+ TopLevelName = TopLevelName.drop_back(8);
+
+ return TopLevelName == CurrentModule;
+}
+
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
const LangOptions &Lang = PP.getLangOpts();
StringRef Text = II->getName();
@@ -277,7 +296,7 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
return false;
}
-/// \brief Lex and validate a macro name, which occurs after a
+/// Lex and validate a macro name, which occurs after a
/// \#define or \#undef.
///
/// This sets the token kind to eod and discards the rest of the macro line if
@@ -309,7 +328,7 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
}
}
-/// \brief Ensure that the next token is a tok::eod token.
+/// Ensure that the next token is a tok::eod token.
///
/// If not, emit a diagnostic and consume up until the eod. If EnableMacros is
/// true, then we consider macros that expand to zero tokens as being ok.
@@ -558,7 +577,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
// the #if block.
CurPPLexer->LexingRawMode = false;
- if (Callbacks)
+ // The last skipped range isn't actually skipped yet if it's truncated
+ // by the end of the preamble; we'll resume parsing after the preamble.
+ if (Callbacks && (Tok.isNot(tok::eof) || !isRecordingPreamble()))
Callbacks->SourceRangeSkipped(
SourceRange(HashTokenLoc, CurPPLexer->getSourceLocation()),
Tok.getLocation());
@@ -866,6 +887,22 @@ private:
bool save;
};
+/// Process a directive while looking for the through header.
+/// Only #include (to check if it is the through header) and #define (to warn
+/// about macros that don't match the PCH) are handled. All other directives
+/// are completely discarded.
+void Preprocessor::HandleSkippedThroughHeaderDirective(Token &Result,
+ SourceLocation HashLoc) {
+ if (const IdentifierInfo *II = Result.getIdentifierInfo()) {
+ if (II->getPPKeywordID() == tok::pp_include)
+ return HandleIncludeDirective(HashLoc, Result);
+ if (II->getPPKeywordID() == tok::pp_define)
+ return HandleDefineDirective(Result,
+ /*ImmediatelyAfterHeaderGuard=*/false);
+ }
+ DiscardUntilEndOfDirective();
+}
+
/// HandleDirective - This callback is invoked when the lexer sees a # token
/// at the start of a line. This consumes the directive, modifies the
/// lexer/preprocessor state, and advances the lexer(s) so that the next token
@@ -927,6 +964,9 @@ void Preprocessor::HandleDirective(Token &Result) {
// and reset to previous state when returning from this function.
ResetMacroExpansionHelper helper(this);
+ if (SkippingUntilPCHThroughHeader)
+ return HandleSkippedThroughHeaderDirective(Result, SavedHash.getLocation());
+
switch (Result.getKind()) {
case tok::eod:
return; // null directive.
@@ -1107,7 +1147,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val,
return false;
}
-/// \brief Handle a \#line directive: C99 6.10.4.
+/// Handle a \#line directive: C99 6.10.4.
///
/// The two acceptable forms are:
/// \verbatim
@@ -1343,7 +1383,7 @@ void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
// Read the rest of the line raw. We do this because we don't want macros
// to be expanded and we don't require that the tokens be valid preprocessing
// tokens. For example, this is allowed: "#warning ` 'foo". GCC does
- // collapse multiple consequtive white space between tokens, but this isn't
+ // collapse multiple consecutive white space between tokens, but this isn't
// specified by the standard.
SmallString<128> Message;
CurLexer->ReadToEndOfLine(&Message);
@@ -1393,7 +1433,7 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
}
}
-/// \brief Handle a #public directive.
+/// Handle a #public directive.
void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
Token MacroNameTok;
ReadMacroName(MacroNameTok, MU_Undef);
@@ -1420,7 +1460,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
MacroNameTok.getLocation(), /*IsPublic=*/true));
}
-/// \brief Handle a #private directive.
+/// Handle a #private directive.
void Preprocessor::HandleMacroPrivateDirective() {
Token MacroNameTok;
ReadMacroName(MacroNameTok, MU_Undef);
@@ -1496,7 +1536,7 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
return isAngled;
}
-// \brief Handle cases where the \#include name is expanded from a macro
+// Handle cases where the \#include name is expanded from a macro
// as multiple tokens, which need to be glued together.
//
// This occurs for code like:
@@ -1557,7 +1597,7 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
return true;
}
-/// \brief Push a token onto the token stream containing an annotation.
+/// Push a token onto the token stream containing an annotation.
void Preprocessor::EnterAnnotationToken(SourceRange Range,
tok::TokenKind Kind,
void *AnnotationVal) {
@@ -1572,7 +1612,7 @@ void Preprocessor::EnterAnnotationToken(SourceRange Range,
EnterTokenStream(std::move(Tok), 1, true);
}
-/// \brief Produce a diagnostic informing the user that a #include or similar
+/// Produce a diagnostic informing the user that a #include or similar
/// was implicitly treated as a module import.
static void diagnoseAutoModuleImport(
Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok,
@@ -1655,12 +1695,18 @@ bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts,
DiagnosticsEngine &Diags, Module *M) {
Module::Requirement Requirement;
Module::UnresolvedHeaderDirective MissingHeader;
- if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader))
+ Module *ShadowingModule = nullptr;
+ if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader,
+ ShadowingModule))
return false;
if (MissingHeader.FileNameLoc.isValid()) {
Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
<< MissingHeader.IsUmbrella << MissingHeader.FileName;
+ } else if (ShadowingModule) {
+ Diags.Report(M->DefinitionLoc, diag::err_module_shadowed) << M->Name;
+ Diags.Report(ShadowingModule->DefinitionLoc,
+ diag::note_previous_definition);
} else {
// FIXME: Track the location at which the requirement was specified, and
// use it here.
@@ -1779,7 +1825,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
SmallString<128> NormalizedPath;
if (LangOpts.MSVCCompat) {
NormalizedPath = Filename.str();
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
llvm::sys::path::native(NormalizedPath);
#endif
}
@@ -1835,6 +1881,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
}
}
+ if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
+ if (isPCHThroughHeader(File))
+ SkippingUntilPCHThroughHeader = false;
+ return;
+ }
+
// Should we enter the source file? Set to false if either the source file is
// known to have no effect beyond its effect on module visibility -- that is,
// if it's got an include guard that is already defined or is a modular header
@@ -1844,12 +1896,19 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (PPOpts->SingleFileParseMode)
ShouldEnter = false;
+ // Any diagnostics after the fatal error will not be visible. As the
+ // compilation failed already and errors in subsequently included files won't
+ // be visible, avoid preprocessing those files.
+ if (ShouldEnter && Diags->hasFatalErrorOccurred())
+ ShouldEnter = false;
+
// Determine whether we should try to import the module for this #include, if
// there is one. Don't do so if precompiled module support is disabled or we
// are processing this module textually (because we're building the module).
if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules &&
- SuggestedModule.getModule()->getTopLevelModuleName() !=
- getLangOpts().CurrentModule) {
+ !isForModuleBuilding(SuggestedModule.getModule(),
+ getLangOpts().CurrentModule,
+ getLangOpts().ModuleName)) {
// If this include corresponds to a module but that module is
// unavailable, diagnose the situation and bail out.
// FIXME: Remove this; loadModule does the same check (but produces
@@ -1940,7 +1999,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
HashLoc, IncludeTok,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
FilenameRange, File, SearchPath, RelativePath,
- ShouldEnter ? nullptr : SuggestedModule.getModule());
+ ShouldEnter ? nullptr : SuggestedModule.getModule(), FileCharacter);
if (SkipHeader && !SuggestedModule.getModule())
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
}
@@ -1996,7 +2055,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// ShouldEnter is false because we are skipping the header. In that
// case, We are not importing the specified module.
if (SkipHeader && getLangOpts().CompilingPCH &&
- M->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ isForModuleBuilding(M, getLangOpts().CurrentModule,
+ getLangOpts().ModuleName))
return;
makeModuleVisible(M, HashLoc);
@@ -2014,7 +2074,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// If the filename string was the result of macro expansions, set the include
// position on the file where it will be included and after the expansions.
if (IncludePos.isMacroID())
- IncludePos = SourceMgr.getExpansionRange(IncludePos).second;
+ IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd();
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
assert(FID.isValid() && "Expected valid file ID");
@@ -2024,11 +2084,21 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Determine if we're switching to building a new submodule, and which one.
if (auto *M = SuggestedModule.getModule()) {
+ if (M->getTopLevelModule()->ShadowingModule) {
+ // We are building a submodule that belongs to a shadowed module. This
+ // means we find header files in the shadowed module.
+ Diag(M->DefinitionLoc, diag::err_module_build_shadowed_submodule)
+ << M->getFullModuleName();
+ Diag(M->getTopLevelModule()->ShadowingModule->DefinitionLoc,
+ diag::note_previous_definition);
+ return;
+ }
// When building a pch, -fmodule-name tells the compiler to textually
// include headers in the specified module. We are not building the
// specified module.
if (getLangOpts().CompilingPCH &&
- M->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ isForModuleBuilding(M, getLangOpts().CurrentModule,
+ getLangOpts().ModuleName))
return;
assert(!CurLexerSubmodule && "should not have marked this as a module yet");
@@ -2527,13 +2597,13 @@ void Preprocessor::HandleDefineDirective(
MacroInfo *const MI = ReadOptionalMacroParameterListAndBody(
MacroNameTok, ImmediatelyAfterHeaderGuard);
-
+
if (!MI) return;
if (MacroShadowsKeyword &&
!isConfigurationPattern(MacroNameTok, MI, getLangOpts())) {
Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
- }
+ }
// Check that there is no paste (##) operator at the beginning or end of the
// replacement list.
unsigned NumTokens = MI->getNumTokens();
@@ -2548,7 +2618,15 @@ void Preprocessor::HandleDefineDirective(
}
}
-
+ // When skipping just warn about macros that do not match.
+ if (SkippingUntilPCHThroughHeader) {
+ const MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo());
+ if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this,
+ /*Syntactic=*/LangOpts.MicrosoftExt))
+ Diag(MI->getDefinitionLoc(), diag::warn_pp_macro_def_mismatch_with_pch)
+ << MacroNameTok.getIdentifierInfo();
+ return;
+ }
// Finally, if this identifier already had a macro defined for it, verify that
// the macro bodies are identical, and issue diagnostics if they are not.
@@ -2638,7 +2716,7 @@ void Preprocessor::HandleUndefDirective() {
auto *II = MacroNameTok.getIdentifierInfo();
auto MD = getMacroDefinition(II);
UndefMacroDirective *Undef = nullptr;
-
+
// If the macro is not defined, this is a noop undef.
if (const MacroInfo *MI = MD.getMacroInfo()) {
if (!MI->isUsed() && MI->isWarnIfUnused())
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
index d8431827e9cd..ac01efad9bf6 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
@@ -273,7 +273,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
case tok::numeric_constant: {
SmallString<64> IntegerBuffer;
bool NumberInvalid = false;
- StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
+ StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
&NumberInvalid);
if (NumberInvalid)
return true; // a diagnostic was already reported
@@ -363,7 +363,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
NumBits = TI.getChar16Width();
else if (Literal.isUTF32())
NumBits = TI.getChar32Width();
- else
+ else // char or char8_t
NumBits = TI.getCharWidth();
// Set the width.
@@ -832,11 +832,11 @@ Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// expression.
bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
DisableMacroExpansion = false;
-
+
// Peek ahead one token.
Token Tok;
LexNonComment(Tok);
-
+
// C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
@@ -846,7 +846,7 @@ Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Parse error, skip the rest of the macro line.
if (Tok.isNot(tok::eod))
DiscardUntilEndOfDirective();
-
+
// Restore 'DisableMacroExpansion'.
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return {false, DT.IncludedUndefinedIds};
@@ -873,7 +873,7 @@ Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Parse error, skip the rest of the macro line.
if (Tok.isNot(tok::eod))
DiscardUntilEndOfDirective();
-
+
// Restore 'DisableMacroExpansion'.
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return {false, DT.IncludedUndefinedIds};
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
index f21787338b37..6631b13b1583 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
@@ -81,10 +82,10 @@ bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
return false;
}
}
-
+
// Get the MemoryBuffer for this FID, if it fails, we fail.
bool Invalid = false;
- const llvm::MemoryBuffer *InputFile =
+ const llvm::MemoryBuffer *InputFile =
getSourceManager().getBuffer(FID, Loc, &Invalid);
if (Invalid) {
SourceLocation FileStart = SourceMgr.getLocForStartOfFile(FID);
@@ -144,7 +145,7 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
CurLexerSubmodule = nullptr;
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_PTHLexer;
-
+
// Notify the client, if desired, that we are in a new source file.
if (Callbacks) {
FileID FID = CurPPLexer->getFileID();
@@ -226,7 +227,7 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
CurLexerKind = CLK_TokenLexer;
}
-/// \brief Compute the relative path that names the given file relative to
+/// Compute the relative path that names the given file relative to
/// the given directory.
static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
const FileEntry *File,
@@ -239,15 +240,15 @@ static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) {
if (CurDir == Dir) {
Result = FilePath.substr(Path.size());
- llvm::sys::path::append(Result,
+ llvm::sys::path::append(Result,
llvm::sys::path::filename(File->getName()));
return;
}
}
-
+
Path = llvm::sys::path::parent_path(Path);
}
-
+
Result = File->getName();
}
@@ -264,7 +265,7 @@ void Preprocessor::PropagateLineStartLeadingSpaceInfo(Token &Result) {
// but it might if they're empty?
}
-/// \brief Determine the location to use as the end of the buffer for a lexer.
+/// Determine the location to use as the end of the buffer for a lexer.
///
/// If the file ends with a newline, form the EOF token on the newline itself,
/// rather than "on the line following it", which doesn't exist. This makes
@@ -425,6 +426,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
PragmaAssumeNonNullLoc = SourceLocation();
}
+ bool LeavingPCHThroughHeader = false;
+
// If this is a #include'd file, pop it off the include stack and continue
// lexing the #includer file.
if (!IncludeMacroStack.empty()) {
@@ -481,6 +484,12 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
Result.setAnnotationValue(M);
}
+ bool FoundPCHThroughHeader = false;
+ if (CurPPLexer && creatingPCHWithThroughHeader() &&
+ isPCHThroughHeader(
+ SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
+ FoundPCHThroughHeader = true;
+
// We're done with the #included file.
RemoveTopOfLexerStack();
@@ -500,8 +509,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
if (ExitedFromPredefinesFile)
replayPreambleConditionalStack();
- // Client should lex another token unless we generated an EOM.
- return LeavingSubmodule;
+ if (!isEndOfMacro && CurPPLexer && FoundPCHThroughHeader &&
+ (isInPrimaryFile() ||
+ CurPPLexer->getFileID() == getPredefinesFileID())) {
+ // Leaving the through header. Continue directly to end of main file
+ // processing.
+ LeavingPCHThroughHeader = true;
+ } else {
+ // Client should lex another token unless we generated an EOM.
+ return LeavingSubmodule;
+ }
}
// If this is the end of the main file, form an EOF token.
@@ -522,6 +539,12 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
Result.setLocation(Result.getLocation().getLocWithOffset(-1));
}
+ if (creatingPCHWithThroughHeader() && !LeavingPCHThroughHeader) {
+ // Reached the end of the compilation without finding the through header.
+ Diag(CurLexer->getFileLoc(), diag::err_pp_through_header_not_seen)
+ << PPOpts->PCHThroughHeader << 0;
+ }
+
if (!isIncrementalProcessingEnabled())
// We're done with lexing.
CurLexer.reset();
@@ -530,7 +553,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
CurPTHLexer->getEOF(Result);
CurPTHLexer.reset();
}
-
+
if (!isIncrementalProcessingEnabled())
CurPPLexer = nullptr;
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
index 41633f90c34d..346dd947c028 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
@@ -41,7 +41,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
@@ -1016,7 +1015,7 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName,
return MacroArgs::create(MI, ArgTokens, isVarargsElided, *this);
}
-/// \brief Keeps macro expanded tokens for TokenLexers.
+/// Keeps macro expanded tokens for TokenLexers.
//
/// Works like a stack; a TokenLexer adds the macro expanded tokens that is
/// going to lex in the cache and when it finishes the tokens are removed
@@ -1100,183 +1099,11 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
if (Feature.startswith("__") && Feature.endswith("__") && Feature.size() >= 4)
Feature = Feature.substr(2, Feature.size() - 4);
+#define FEATURE(Name, Predicate) .Case(#Name, Predicate)
return llvm::StringSwitch<bool>(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)
- .Case("attribute_availability_with_message", true)
- .Case("attribute_availability_app_extension", true)
- .Case("attribute_availability_with_version_underscores", true)
- .Case("attribute_availability_tvos", true)
- .Case("attribute_availability_watchos", true)
- .Case("attribute_availability_with_strict", true)
- .Case("attribute_availability_with_replacement", true)
- .Case("attribute_availability_in_templates", true)
- .Case("attribute_cf_returns_not_retained", true)
- .Case("attribute_cf_returns_retained", true)
- .Case("attribute_cf_returns_on_parameters", true)
- .Case("attribute_deprecated_with_message", true)
- .Case("attribute_deprecated_with_replacement", true)
- .Case("attribute_ext_vector_type", true)
- .Case("attribute_ns_returns_not_retained", true)
- .Case("attribute_ns_returns_retained", true)
- .Case("attribute_ns_consumes_self", true)
- .Case("attribute_ns_consumed", true)
- .Case("attribute_cf_consumed", true)
- .Case("attribute_objc_ivar_unused", true)
- .Case("attribute_objc_method_family", true)
- .Case("attribute_overloadable", true)
- .Case("attribute_unavailable_with_message", true)
- .Case("attribute_unused_on_fields", true)
- .Case("attribute_diagnose_if_objc", true)
- .Case("blocks", LangOpts.Blocks)
- .Case("c_thread_safety_attributes", true)
- .Case("cxx_exceptions", LangOpts.CXXExceptions)
- .Case("cxx_rtti", LangOpts.RTTI && LangOpts.RTTIData)
- .Case("enumerator_attributes", true)
- .Case("nullability", true)
- .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("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)
- .Case("objc_arc_weak", LangOpts.ObjCWeak)
- .Case("objc_default_synthesize_properties", LangOpts.ObjC2)
- .Case("objc_fixed_enum", LangOpts.ObjC2)
- .Case("objc_instancetype", LangOpts.ObjC2)
- .Case("objc_kindof", LangOpts.ObjC2)
- .Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules)
- .Case("objc_nonfragile_abi", LangOpts.ObjCRuntime.isNonFragile())
- .Case("objc_property_explicit_atomic",
- true) // Does clang support explicit "atomic" keyword?
- .Case("objc_protocol_qualifier_mangling", true)
- .Case("objc_weak_class", LangOpts.ObjCRuntime.hasWeakClassImport())
- .Case("ownership_holds", true)
- .Case("ownership_returns", true)
- .Case("ownership_takes", true)
- .Case("objc_bool", true)
- .Case("objc_subscripting", LangOpts.ObjCRuntime.isNonFragile())
- .Case("objc_array_literals", LangOpts.ObjC2)
- .Case("objc_dictionary_literals", LangOpts.ObjC2)
- .Case("objc_boxed_expressions", LangOpts.ObjC2)
- .Case("objc_boxed_nsvalue_expressions", LangOpts.ObjC2)
- .Case("arc_cf_code_audited", true)
- .Case("objc_bridge_id", true)
- .Case("objc_bridge_id_on_typedefs", true)
- .Case("objc_generics", LangOpts.ObjC2)
- .Case("objc_generics_variance", LangOpts.ObjC2)
- .Case("objc_class_property", LangOpts.ObjC2)
- // C11 features
- .Case("c_alignas", LangOpts.C11)
- .Case("c_alignof", LangOpts.C11)
- .Case("c_atomic", LangOpts.C11)
- .Case("c_generic_selections", LangOpts.C11)
- .Case("c_static_assert", LangOpts.C11)
- .Case("c_thread_local",
- LangOpts.C11 && PP.getTargetInfo().isTLSSupported())
- // C++11 features
- .Case("cxx_access_control_sfinae", LangOpts.CPlusPlus11)
- .Case("cxx_alias_templates", LangOpts.CPlusPlus11)
- .Case("cxx_alignas", LangOpts.CPlusPlus11)
- .Case("cxx_alignof", LangOpts.CPlusPlus11)
- .Case("cxx_atomic", LangOpts.CPlusPlus11)
- .Case("cxx_attributes", LangOpts.CPlusPlus11)
- .Case("cxx_auto_type", LangOpts.CPlusPlus11)
- .Case("cxx_constexpr", LangOpts.CPlusPlus11)
- .Case("cxx_constexpr_string_builtins", LangOpts.CPlusPlus11)
- .Case("cxx_decltype", LangOpts.CPlusPlus11)
- .Case("cxx_decltype_incomplete_return_types", LangOpts.CPlusPlus11)
- .Case("cxx_default_function_template_args", LangOpts.CPlusPlus11)
- .Case("cxx_defaulted_functions", LangOpts.CPlusPlus11)
- .Case("cxx_delegating_constructors", LangOpts.CPlusPlus11)
- .Case("cxx_deleted_functions", LangOpts.CPlusPlus11)
- .Case("cxx_explicit_conversions", LangOpts.CPlusPlus11)
- .Case("cxx_generalized_initializers", LangOpts.CPlusPlus11)
- .Case("cxx_implicit_moves", LangOpts.CPlusPlus11)
- .Case("cxx_inheriting_constructors", LangOpts.CPlusPlus11)
- .Case("cxx_inline_namespaces", LangOpts.CPlusPlus11)
- .Case("cxx_lambdas", LangOpts.CPlusPlus11)
- .Case("cxx_local_type_template_args", LangOpts.CPlusPlus11)
- .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus11)
- .Case("cxx_noexcept", LangOpts.CPlusPlus11)
- .Case("cxx_nullptr", LangOpts.CPlusPlus11)
- .Case("cxx_override_control", LangOpts.CPlusPlus11)
- .Case("cxx_range_for", LangOpts.CPlusPlus11)
- .Case("cxx_raw_string_literals", LangOpts.CPlusPlus11)
- .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus11)
- .Case("cxx_rvalue_references", LangOpts.CPlusPlus11)
- .Case("cxx_strong_enums", LangOpts.CPlusPlus11)
- .Case("cxx_static_assert", LangOpts.CPlusPlus11)
- .Case("cxx_thread_local",
- LangOpts.CPlusPlus11 && PP.getTargetInfo().isTLSSupported())
- .Case("cxx_trailing_return", LangOpts.CPlusPlus11)
- .Case("cxx_unicode_literals", LangOpts.CPlusPlus11)
- .Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11)
- .Case("cxx_user_literals", LangOpts.CPlusPlus11)
- .Case("cxx_variadic_templates", LangOpts.CPlusPlus11)
- // C++14 features
- .Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14)
- .Case("cxx_binary_literals", LangOpts.CPlusPlus14)
- .Case("cxx_contextual_conversions", LangOpts.CPlusPlus14)
- .Case("cxx_decltype_auto", LangOpts.CPlusPlus14)
- .Case("cxx_generic_lambdas", LangOpts.CPlusPlus14)
- .Case("cxx_init_captures", LangOpts.CPlusPlus14)
- .Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14)
- .Case("cxx_return_type_deduction", LangOpts.CPlusPlus14)
- .Case("cxx_variable_templates", LangOpts.CPlusPlus14)
- // NOTE: For features covered by SD-6, it is preferable to provide *only*
- // the SD-6 macro and not a __has_feature check.
-
- // C++ TSes
- //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays)
- //.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts)
- // FIXME: Should this be __has_feature or __has_extension?
- //.Case("raw_invocation_type", LangOpts.CPlusPlus)
- // Type traits
- // N.B. Additional type traits should not be added to the following list.
- // Instead, they should be detected by has_extension.
- .Case("has_nothrow_assign", LangOpts.CPlusPlus)
- .Case("has_nothrow_copy", LangOpts.CPlusPlus)
- .Case("has_nothrow_constructor", LangOpts.CPlusPlus)
- .Case("has_trivial_assign", LangOpts.CPlusPlus)
- .Case("has_trivial_copy", LangOpts.CPlusPlus)
- .Case("has_trivial_constructor", LangOpts.CPlusPlus)
- .Case("has_trivial_destructor", LangOpts.CPlusPlus)
- .Case("has_virtual_destructor", LangOpts.CPlusPlus)
- .Case("is_abstract", LangOpts.CPlusPlus)
- .Case("is_base_of", LangOpts.CPlusPlus)
- .Case("is_class", LangOpts.CPlusPlus)
- .Case("is_constructible", LangOpts.CPlusPlus)
- .Case("is_convertible_to", LangOpts.CPlusPlus)
- .Case("is_empty", LangOpts.CPlusPlus)
- .Case("is_enum", LangOpts.CPlusPlus)
- .Case("is_final", LangOpts.CPlusPlus)
- .Case("is_literal", LangOpts.CPlusPlus)
- .Case("is_standard_layout", LangOpts.CPlusPlus)
- .Case("is_pod", LangOpts.CPlusPlus)
- .Case("is_polymorphic", LangOpts.CPlusPlus)
- .Case("is_sealed", LangOpts.CPlusPlus && LangOpts.MicrosoftExt)
- .Case("is_trivial", LangOpts.CPlusPlus)
- .Case("is_trivially_assignable", LangOpts.CPlusPlus)
- .Case("is_trivially_constructible", LangOpts.CPlusPlus)
- .Case("is_trivially_copyable", LangOpts.CPlusPlus)
- .Case("is_union", LangOpts.CPlusPlus)
- .Case("modules", LangOpts.Modules)
- .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack))
- .Case("tls", PP.getTargetInfo().isTLSSupported())
- .Case("underlying_type", LangOpts.CPlusPlus)
+#include "clang/Basic/Features.def"
.Default(false);
+#undef FEATURE
}
/// HasExtension - Return true if we recognize and implement the feature
@@ -1299,35 +1126,13 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) {
Extension.size() >= 4)
Extension = Extension.substr(2, Extension.size() - 4);
- // Because we inherit the feature list from HasFeature, this string switch
- // must be less restrictive than HasFeature's.
+ // Because we inherit the feature list from HasFeature, this string switch
+ // must be less restrictive than HasFeature's.
+#define EXTENSION(Name, Predicate) .Case(#Name, Predicate)
return llvm::StringSwitch<bool>(Extension)
- // C11 features supported by other languages as extensions.
- .Case("c_alignas", true)
- .Case("c_alignof", true)
- .Case("c_atomic", true)
- .Case("c_generic_selections", true)
- .Case("c_static_assert", true)
- .Case("c_thread_local", PP.getTargetInfo().isTLSSupported())
- // C++11 features supported by other languages as extensions.
- .Case("cxx_atomic", LangOpts.CPlusPlus)
- .Case("cxx_deleted_functions", LangOpts.CPlusPlus)
- .Case("cxx_explicit_conversions", LangOpts.CPlusPlus)
- .Case("cxx_inline_namespaces", LangOpts.CPlusPlus)
- .Case("cxx_local_type_template_args", LangOpts.CPlusPlus)
- .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus)
- .Case("cxx_override_control", LangOpts.CPlusPlus)
- .Case("cxx_range_for", LangOpts.CPlusPlus)
- .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus)
- .Case("cxx_rvalue_references", LangOpts.CPlusPlus)
- .Case("cxx_variadic_templates", LangOpts.CPlusPlus)
- // C++14 features supported by other languages as extensions.
- .Case("cxx_binary_literals", true)
- .Case("cxx_init_captures", LangOpts.CPlusPlus11)
- .Case("cxx_variable_templates", LangOpts.CPlusPlus)
- // Miscellaneous language extensions
- .Case("overloadable_unmarked", true)
- .Default(false);
+#include "clang/Basic/Features.def"
+ .Default(false);
+#undef EXTENSION
}
/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
@@ -1343,7 +1148,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
// These expressions are only allowed within a preprocessor directive.
if (!PP.isParsingIfOrElifDirective()) {
- PP.Diag(LParenLoc, diag::err_pp_directive_required) << II->getName();
+ PP.Diag(LParenLoc, diag::err_pp_directive_required) << II;
// Return a valid identifier token.
assert(Tok.is(tok::identifier));
Tok.setIdentifierInfo(II);
@@ -1381,7 +1186,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
SmallString<128> FilenameBuffer;
StringRef Filename;
SourceLocation EndLoc;
-
+
switch (Tok.getKind()) {
case tok::eod:
// If the token kind is EOD, the error has already been diagnosed.
@@ -1455,7 +1260,7 @@ static bool EvaluateHasIncludeNext(Token &Tok,
// __has_include_next is like __has_include, except that we start
// searching after the current found directory. If we can't do this,
// issue a diagnostic.
- // FIXME: Factor out duplication with
+ // FIXME: Factor out duplication with
// Preprocessor::HandleIncludeNextDirective.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
const FileEntry *LookupFromFile = nullptr;
@@ -1482,7 +1287,7 @@ static bool EvaluateHasIncludeNext(Token &Tok,
return EvaluateHasIncludeCommon(Tok, II, PP, Lookup, LookupFromFile);
}
-/// \brief Process single-argument builtin feature-like macros that return
+/// Process single-argument builtin feature-like macros that return
/// integer values.
static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream& OS,
Token &Tok, IdentifierInfo *II,
@@ -1585,7 +1390,7 @@ already_lexed:
}
}
-/// \brief Helper function to return the IdentifierInfo structure of a Token
+/// Helper function to return the IdentifierInfo structure of a Token
/// or generate a diagnostic if none available.
static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok,
Preprocessor &PP,
@@ -1686,7 +1491,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
// can matter for a function-like macro that expands to contain __LINE__.
// Skip down through expansion points until we find a file loc for the
// end of the expansion history.
- Loc = SourceMgr.getExpansionRange(Loc).second;
+ Loc = SourceMgr.getExpansionRange(Loc).getEnd();
PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc);
// __LINE__ expands to a simple numeric value.
@@ -1705,7 +1510,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
PLoc = SourceMgr.getPresumedLoc(NextLoc);
if (PLoc.isInvalid())
break;
-
+
NextLoc = PLoc.getIncludeLoc();
}
}
@@ -1800,12 +1605,21 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
[this](Token &Tok, bool &HasLexedNextToken) -> int {
IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
diag::err_feature_check_malformed);
+ const LangOptions &LangOpts = getLangOpts();
if (!II)
return false;
- else if (II->getBuiltinID() != 0)
+ else if (II->getBuiltinID() != 0) {
+ switch (II->getBuiltinID()) {
+ case Builtin::BI__builtin_operator_new:
+ case Builtin::BI__builtin_operator_delete:
+ // denotes date of behavior change to support calling arbitrary
+ // usual allocation and deallocation functions. Required by libc++
+ return 201802;
+ default:
+ return true;
+ }
return true;
- else {
- const LangOptions &LangOpts = getLangOpts();
+ } else {
return llvm::StringSwitch<bool>(II->getName())
.Case("__make_integer_seq", LangOpts.CPlusPlus)
.Case("__type_pack_element", LangOpts.CPlusPlus)
diff --git a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
index d6c20a13d27b..45cff56dcaa1 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
@@ -23,8 +23,8 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -145,7 +145,7 @@ bool PTHLexer::LexEndOfFile(Token &Result) {
ParsingPreprocessorDirective = false; // Done parsing the "line".
return true; // Have a token.
}
-
+
assert(!LexingRawMode);
// If we are in a #if directive, emit an error.
@@ -215,7 +215,7 @@ bool PTHLexer::SkipBlock() {
// Compute the actual memory address of the '#' token data for this entry.
HashEntryI = TokBuf + Offset;
- // Optmization: "Sibling jumping". #if...#else...#endif blocks can
+ // Optimization: "Sibling jumping". #if...#else...#endif blocks can
// contain nested blocks. In the side-table we can jump over these
// nested blocks instead of doing a linear search if the next "sibling"
// entry is not at a location greater than LastHashTokPtr.
@@ -336,7 +336,7 @@ public:
using offset_type = unsigned;
static hash_value_type ComputeHash(internal_key_type x) {
- return llvm::HashString(x.second);
+ return llvm::djbHash(x.second);
}
static std::pair<unsigned, unsigned>
@@ -396,7 +396,7 @@ public:
}
static hash_value_type ComputeHash(const internal_key_type& a) {
- return llvm::HashString(StringRef(a.first, a.second));
+ return llvm::djbHash(StringRef(a.first, a.second));
}
// This hopefully will just get inlined and removed by the optimizer.
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
index b8acd92521fb..37c0a23646c5 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -64,7 +64,7 @@ PragmaHandler::~PragmaHandler() = default;
EmptyPragmaHandler::EmptyPragmaHandler(StringRef Name) : PragmaHandler(Name) {}
-void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
+void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &FirstToken) {}
@@ -99,7 +99,7 @@ void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
Handlers.erase(Handler->getName());
}
-void PragmaNamespace::HandlePragma(Preprocessor &PP,
+void PragmaNamespace::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &Tok) {
// Read the 'namespace' that the directive is in, e.g. STDC. Do not macro
@@ -141,14 +141,14 @@ void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc,
PragmaHandlers->HandlePragma(*this, Introducer, Tok);
// If the pragma handler didn't read the rest of the line, consume it now.
- if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
+ if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
|| (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective))
DiscardUntilEndOfDirective();
}
namespace {
-/// \brief Helper class for \see Preprocessor::Handle_Pragma.
+/// Helper class for \see Preprocessor::Handle_Pragma.
class LexingFor_PragmaRAII {
Preprocessor &PP;
bool InMacroArgPreExpansion;
@@ -468,7 +468,7 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
if (PLoc.isInvalid())
return;
-
+
unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename());
// Notify the client, if desired, that we are in a new source file.
@@ -588,7 +588,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
return LookUpIdentifierInfo(MacroTok);
}
-/// \brief Handle \#pragma push_macro.
+/// Handle \#pragma push_macro.
///
/// The syntax is:
/// \code
@@ -601,7 +601,7 @@ void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) {
// Get the MacroInfo associated with IdentInfo.
MacroInfo *MI = getMacroInfo(IdentInfo);
-
+
if (MI) {
// Allow the original MacroInfo to be redefined later.
MI->setIsAllowRedefinitionsWithoutWarning(true);
@@ -611,7 +611,7 @@ void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) {
PragmaPushMacroInfo[IdentInfo].push_back(MI);
}
-/// \brief Handle \#pragma pop_macro.
+/// Handle \#pragma pop_macro.
///
/// The syntax is:
/// \code
@@ -653,7 +653,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
}
void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
- // We will either get a quoted filename or a bracketed filename, and we
+ // We will either get a quoted filename or a bracketed filename, and we
// have to track which we got. The first filename is the source name,
// and the second name is the mapped filename. If the first is quoted,
// the second must be as well (cannot mix and match quotes and brackets).
@@ -675,7 +675,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
StringRef SourceFileName;
SmallString<128> FileNameBuffer;
- if (SourceFilenameTok.is(tok::string_literal) ||
+ if (SourceFilenameTok.is(tok::string_literal) ||
SourceFilenameTok.is(tok::angle_string_literal)) {
SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer);
} else if (SourceFilenameTok.is(tok::less)) {
@@ -706,7 +706,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
}
StringRef ReplaceFileName;
- if (ReplaceFilenameTok.is(tok::string_literal) ||
+ if (ReplaceFilenameTok.is(tok::string_literal) ||
ReplaceFilenameTok.is(tok::angle_string_literal)) {
ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer);
} else if (ReplaceFilenameTok.is(tok::less)) {
@@ -732,8 +732,8 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
// they're both of the same type (angled vs non-angled)
StringRef OriginalSource = SourceFileName;
- bool SourceIsAngled =
- GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
+ bool SourceIsAngled =
+ GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
SourceFileName);
bool ReplaceIsAngled =
GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(),
@@ -747,7 +747,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
DiagID = diag::warn_pragma_include_alias_mismatch_quote;
Diag(SourceFilenameTok.getLocation(), DiagID)
- << SourceFileName
+ << SourceFileName
<< ReplaceFileName;
return;
@@ -1053,6 +1053,20 @@ struct PragmaDebugHandler : public PragmaHandler {
PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument)
<< II->getName();
}
+ } else if (II->isStr("diag_mapping")) {
+ Token DiagName;
+ PP.LexUnexpandedToken(DiagName);
+ if (DiagName.is(tok::eod))
+ PP.getDiagnostics().dump();
+ else if (DiagName.is(tok::string_literal) && !DiagName.hasUDSuffix()) {
+ StringLiteralParser Literal(DiagName, PP);
+ if (Literal.hadError)
+ return;
+ PP.getDiagnostics().dump(Literal.GetString());
+ } else {
+ PP.Diag(DiagName, diag::warn_pragma_debug_missing_argument)
+ << II->getName();
+ }
} else if (II->isStr("llvm_fatal_error")) {
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
} else if (II->isStr("llvm_unreachable")) {
@@ -1601,45 +1615,7 @@ struct PragmaPopMacroHandler : public PragmaHandler {
}
};
-// Pragma STDC implementations.
-
-/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
-struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
- PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
-
- void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &Tok) override {
- tok::OnOffSwitch OOS;
- if (PP.LexOnOffSwitch(OOS))
- return;
- if (OOS == tok::OOS_ON)
- PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
- }
-};
-
-/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
-struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
- PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
-
- void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &Tok) override {
- tok::OnOffSwitch OOS;
- PP.LexOnOffSwitch(OOS);
- }
-};
-
-/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
-struct PragmaSTDC_UnknownHandler : public PragmaHandler {
- PragmaSTDC_UnknownHandler() = default;
-
- void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &UnknownTok) override {
- // C99 6.10.6p2, unknown forms are not allowed.
- PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
- }
-};
-
-/// PragmaARCCFCodeAuditedHandler -
+/// PragmaARCCFCodeAuditedHandler -
/// \#pragma clang arc_cf_code_audited begin/end
struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {}
@@ -1754,7 +1730,7 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
}
};
-/// \brief Handle "\#pragma region [...]"
+/// Handle "\#pragma region [...]"
///
/// The syntax is
/// \code
@@ -1815,16 +1791,14 @@ void Preprocessor::RegisterBuiltinPragmas() {
ModuleHandler->AddPragma(new PragmaModuleBuildHandler());
ModuleHandler->AddPragma(new PragmaModuleLoadHandler());
- AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
- AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler());
- AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
+ // Add region pragmas.
+ AddPragmaHandler(new PragmaRegionHandler("region"));
+ AddPragmaHandler(new PragmaRegionHandler("endregion"));
// MS extensions.
if (LangOpts.MicrosoftExt) {
AddPragmaHandler(new PragmaWarningHandler());
AddPragmaHandler(new PragmaIncludeAliasHandler());
- AddPragmaHandler(new PragmaRegionHandler("region"));
- AddPragmaHandler(new PragmaRegionHandler("endregion"));
}
// Pragmas added by plugins
@@ -1843,17 +1817,4 @@ void Preprocessor::IgnorePragmas() {
// in Preprocessor::RegisterBuiltinPragmas().
AddPragmaHandler("GCC", new EmptyPragmaHandler());
AddPragmaHandler("clang", new EmptyPragmaHandler());
- if (PragmaHandler *NS = PragmaHandlers->FindHandler("STDC")) {
- // Preprocessor::RegisterBuiltinPragmas() already registers
- // PragmaSTDC_UnknownHandler as the empty handler, so remove it first,
- // otherwise there will be an assert about a duplicate handler.
- PragmaNamespace *STDCNamespace = NS->getIfNamespace();
- assert(STDCNamespace &&
- "Invalid namespace, registered as a regular pragma handler!");
- if (PragmaHandler *Existing = STDCNamespace->FindHandler("", false)) {
- RemovePragmaHandler("STDC", Existing);
- delete Existing;
- }
- }
- AddPragmaHandler("STDC", new EmptyPragmaHandler());
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
index af439dbfa584..b37a8cf1ced4 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
@@ -54,7 +54,7 @@ InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
-/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
+/// Returns a pair of [Begin, End) iterators of preprocessed entities
/// that source range \p Range encompasses.
llvm::iterator_range<PreprocessingRecord::iterator>
PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
@@ -67,7 +67,7 @@ PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
}
std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
-
+
CachedRangeQuery.Range = Range;
CachedRangeQuery.Result = Res;
@@ -88,7 +88,7 @@ static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
return SM.isInFileID(SM.getFileLoc(Loc), FID);
}
-/// \brief Returns true if the preprocessed entity that \arg PPEI iterator
+/// Returns true if the preprocessed entity that \arg PPEI iterator
/// points to is coming from the file \arg FID.
///
/// Can be used to avoid implicit deserializations of preallocated
@@ -132,34 +132,34 @@ bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
FID, SourceMgr);
}
-/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
+/// Returns a pair of [Begin, End) iterators of preprocessed entities
/// that source range \arg R encompasses.
std::pair<int, int>
PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
assert(Range.isValid());
assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
-
+
std::pair<unsigned, unsigned>
Local = findLocalPreprocessedEntitiesInRange(Range);
-
+
// Check if range spans local entities.
if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
return std::make_pair(Local.first, Local.second);
-
+
std::pair<unsigned, unsigned>
Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
-
+
// Check if range spans local entities.
if (Loaded.first == Loaded.second)
return std::make_pair(Local.first, Local.second);
-
+
unsigned TotalLoaded = LoadedPreprocessedEntities.size();
-
+
// Check if range spans loaded entities.
if (Local.first == Local.second)
return std::make_pair(int(Loaded.first)-TotalLoaded,
int(Loaded.second)-TotalLoaded);
-
+
// Range spands loaded and local entities.
return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
}
@@ -324,17 +324,34 @@ void PreprocessingRecord::SetExternalSource(
unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
unsigned Result = LoadedPreprocessedEntities.size();
- LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
+ LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
+ NumEntities);
return Result;
}
+unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
+ unsigned Result = SkippedRanges.size();
+ SkippedRanges.resize(SkippedRanges.size() + NumRanges);
+ SkippedRangesAllLoaded = false;
+ return Result;
+}
+
+void PreprocessingRecord::ensureSkippedRangesLoaded() {
+ if (SkippedRangesAllLoaded || !ExternalSource)
+ return;
+ for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
+ if (SkippedRanges[Index].isInvalid())
+ SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
+ }
+ SkippedRangesAllLoaded = true;
+}
+
void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
MacroDefinitionRecord *Def) {
MacroDefinitions[Macro] = Def;
}
-/// \brief Retrieve the preprocessed entity at the given ID.
+/// Retrieve the preprocessed entity at the given ID.
PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
if (PPID.ID < 0) {
unsigned Index = -PPID.ID - 1;
@@ -351,10 +368,10 @@ PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
return PreprocessedEntities[Index];
}
-/// \brief Retrieve the loaded preprocessed entity at the given index.
+/// Retrieve the loaded preprocessed entity at the given index.
PreprocessedEntity *
PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
- assert(Index < LoadedPreprocessedEntities.size() &&
+ assert(Index < LoadedPreprocessedEntities.size() &&
"Out-of bounds loaded preprocessed entity");
assert(ExternalSource && "No external source to load from");
PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
@@ -418,6 +435,7 @@ void PreprocessingRecord::Defined(const Token &MacroNameTok,
void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
SourceLocation EndifLoc) {
+ assert(Range.isValid());
SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
}
@@ -453,26 +471,27 @@ void PreprocessingRecord::InclusionDirective(
const FileEntry *File,
StringRef SearchPath,
StringRef RelativePath,
- const Module *Imported) {
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
-
+
switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
- case tok::pp_include:
- Kind = InclusionDirective::Include;
+ case tok::pp_include:
+ Kind = InclusionDirective::Include;
break;
-
- case tok::pp_import:
- Kind = InclusionDirective::Import;
+
+ case tok::pp_import:
+ Kind = InclusionDirective::Import;
break;
-
- case tok::pp_include_next:
- Kind = InclusionDirective::IncludeNext;
+
+ case tok::pp_include_next:
+ Kind = InclusionDirective::IncludeNext;
break;
-
- case tok::pp___include_macros:
+
+ case tok::pp___include_macros:
Kind = InclusionDirective::IncludeMacros;
break;
-
+
default:
llvm_unreachable("Unknown include directive kind");
}
@@ -497,5 +516,6 @@ size_t PreprocessingRecord::getTotalMemory() const {
return BumpAlloc.getTotalMemory()
+ llvm::capacity_in_bytes(MacroDefinitions)
+ llvm::capacity_in_bytes(PreprocessedEntities)
- + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
+ + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
+ + llvm::capacity_in_bytes(SkippedRanges);
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
index 7d789e780113..def47b2f1095 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
@@ -85,20 +85,22 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
IdentifierInfoLookup *IILookup, bool OwnsHeaders,
TranslationUnitKind TUKind)
: 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())), TUKind(TUKind),
- SkipMainFilePreamble(0, true),
+ FileMgr(Headers.getFileMgr()), SourceMgr(SM), PCMCache(PCMCache),
+ ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers),
+ TheModuleLoader(TheModuleLoader), ExternalSource(nullptr),
+ // As the language options may have not been loaded yet (when
+ // deserializing an ASTUnit), adding keywords to the identifier table is
+ // deferred to Preprocessor::Initialize().
+ Identifiers(IILookup), PragmaHandlers(new PragmaNamespace(StringRef())),
+ TUKind(TUKind), SkipMainFilePreamble(0, true),
CurSubmoduleState(&NullSubmoduleState) {
OwnsHeaderSearch = OwnsHeaders;
-
+
// Default to discarding comments.
KeepComments = false;
KeepMacroComments = false;
SuppressIncludeNotFoundError = false;
-
+
// Macro expansion is enabled.
DisableMacroExpansion = false;
MacroExpansionInDirectivesOverride = false;
@@ -125,10 +127,10 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
// Initialize the pragma handlers.
RegisterBuiltinPragmas();
-
+
// Initialize builtin macros like __LINE__ and friends.
RegisterBuiltinMacros();
-
+
if(LangOpts.Borland) {
Ident__exception_info = getIdentifierInfo("_exception_info");
Ident___exception_info = getIdentifierInfo("__exception_info");
@@ -147,6 +149,11 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
Ident_AbnormalTermination = nullptr;
}
+ // If using a PCH with a through header, start skipping tokens.
+ if (!this->PPOpts->PCHThroughHeader.empty() &&
+ !this->PPOpts->ImplicitPCHInclude.empty())
+ SkippingUntilPCHThroughHeader = true;
+
if (this->PPOpts->GeneratePreamble)
PreambleConditionalStack.startRecording();
}
@@ -190,6 +197,9 @@ void Preprocessor::Initialize(const TargetInfo &Target,
// Initialize information about built-ins.
BuiltinInfo.InitializeTarget(Target, AuxTarget);
HeaderInfo.setTarget(Target);
+
+ // Populate the identifier table with info about keywords for the current language.
+ Identifiers.AddKeywords(LangOpts);
}
void Preprocessor::InitializeForModelFile() {
@@ -328,7 +338,7 @@ Preprocessor::macro_end(bool IncludeExternalMacros) const {
return CurSubmoduleState->Macros.end();
}
-/// \brief Compares macro tokens with a specified token value sequence.
+/// Compares macro tokens with a specified token value sequence.
static bool MacroDefinitionEquals(const MacroInfo *MI,
ArrayRef<TokenValue> Tokens) {
return Tokens.size() == MI->getNumTokens() &&
@@ -369,7 +379,7 @@ void Preprocessor::recomputeCurLexerKind() {
CurLexerKind = CLK_PTHLexer;
else if (CurTokenLexer)
CurLexerKind = CLK_TokenLexer;
- else
+ else
CurLexerKind = CLK_CachingLexer;
}
@@ -482,6 +492,22 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok,
Tok.setLiteralData(DestPtr);
}
+SourceLocation Preprocessor::SplitToken(SourceLocation Loc, unsigned Length) {
+ auto &SM = getSourceManager();
+ SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellingLoc);
+ bool Invalid = false;
+ StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return SourceLocation();
+
+ // FIXME: We could consider re-using spelling for tokens we see repeatedly.
+ const char *DestPtr;
+ SourceLocation Spelling =
+ ScratchBuf->getToken(Buffer.data() + LocInfo.second, Length, DestPtr);
+ return SM.createTokenSplitLoc(Spelling, Loc, Loc.getLocWithOffset(Length));
+}
+
Module *Preprocessor::getCurrentModule() {
if (!getLangOpts().isCompilingModule())
return nullptr;
@@ -530,6 +556,72 @@ void Preprocessor::EnterMainSourceFile() {
// Start parsing the predefines.
EnterSourceFile(FID, nullptr, SourceLocation());
+
+ if (!PPOpts->PCHThroughHeader.empty()) {
+ // Lookup and save the FileID for the through header. If it isn't found
+ // in the search path, it's a fatal error.
+ const DirectoryLookup *CurDir;
+ const FileEntry *File = LookupFile(
+ SourceLocation(), PPOpts->PCHThroughHeader,
+ /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir,
+ /*SearchPath=*/nullptr, /*RelativePath=*/nullptr,
+ /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr);
+ if (!File) {
+ Diag(SourceLocation(), diag::err_pp_through_header_not_found)
+ << PPOpts->PCHThroughHeader;
+ return;
+ }
+ setPCHThroughHeaderFileID(
+ SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User));
+ }
+
+ // Skip tokens from the Predefines and if needed the main file.
+ if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader)
+ SkipTokensUntilPCHThroughHeader();
+}
+
+void Preprocessor::setPCHThroughHeaderFileID(FileID FID) {
+ assert(PCHThroughHeaderFileID.isInvalid() &&
+ "PCHThroughHeaderFileID already set!");
+ PCHThroughHeaderFileID = FID;
+}
+
+bool Preprocessor::isPCHThroughHeader(const FileEntry *FE) {
+ assert(PCHThroughHeaderFileID.isValid() &&
+ "Invalid PCH through header FileID");
+ return FE == SourceMgr.getFileEntryForID(PCHThroughHeaderFileID);
+}
+
+bool Preprocessor::creatingPCHWithThroughHeader() {
+ return TUKind == TU_Prefix && !PPOpts->PCHThroughHeader.empty() &&
+ PCHThroughHeaderFileID.isValid();
+}
+
+bool Preprocessor::usingPCHWithThroughHeader() {
+ return TUKind != TU_Prefix && !PPOpts->PCHThroughHeader.empty() &&
+ PCHThroughHeaderFileID.isValid();
+}
+
+/// Skip tokens until after the #include of the through header.
+/// Tokens in the predefines file and the main file may be skipped. If the end
+/// of the predefines file is reached, skipping continues into the main file.
+/// If the end of the main file is reached, it's a fatal error.
+void Preprocessor::SkipTokensUntilPCHThroughHeader() {
+ bool ReachedMainFileEOF = false;
+ Token Tok;
+ while (true) {
+ bool InPredefines = (CurLexer->getFileID() == getPredefinesFileID());
+ CurLexer->Lex(Tok);
+ if (Tok.is(tok::eof) && !InPredefines) {
+ ReachedMainFileEOF = true;
+ break;
+ }
+ if (!SkippingUntilPCHThroughHeader)
+ break;
+ }
+ if (ReachedMainFileEOF)
+ Diag(SourceLocation(), diag::err_pp_through_header_not_seen)
+ << PPOpts->PCHThroughHeader << 1;
}
void Preprocessor::replayPreambleConditionalStack() {
@@ -624,7 +716,7 @@ void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) {
Diag(Identifier,it->second) << Identifier.getIdentifierInfo();
}
-/// \brief Returns a diagnostic message kind for reporting a future keyword as
+/// Returns a diagnostic message kind for reporting a future keyword as
/// appropriate for the identifier and specified language.
static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
const LangOptions &LangOpts) {
@@ -680,7 +772,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
if (IsSpecialVariadicMacro)
II.setIsPoisoned(CurrentIsPoisoned);
}
-
+
// If this identifier was poisoned, and if it was not produced from a macro
// expansion, emit an error.
if (II.isPoisoned() && CurPPLexer) {
@@ -726,7 +818,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
// like "#define TY typeof", "TY(1) x".
if (II.isExtensionToken() && !DisableMacroExpansion)
Diag(Identifier, diag::ext_token_used);
-
+
// If this is the 'import' contextual keyword following an '@', note
// that the next token indicates a module name.
//
@@ -773,26 +865,31 @@ void Preprocessor::Lex(Token &Result) {
}
} while (!ReturnedToken);
- if (Result.is(tok::code_completion))
+ if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
+ // Remember the identifier before code completion token.
setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+ // Set IdenfitierInfo to null to avoid confusing code that handles both
+ // identifiers and completion tokens.
+ Result.setIdentifierInfo(nullptr);
+ }
LastTokenWasAt = Result.is(tok::at);
}
-/// \brief Lex a token following the 'import' contextual keyword.
+/// Lex a token following the 'import' contextual keyword.
///
void Preprocessor::LexAfterModuleImport(Token &Result) {
// Figure out what kind of lexer we actually have.
recomputeCurLexerKind();
-
+
// Lex the next token.
Lex(Result);
- // The token sequence
+ // The token sequence
//
// import identifier (. identifier)*
//
- // indicates a module import directive. We already saw the 'import'
+ // indicates a module import directive. We already saw the 'import'
// contextual keyword, so now we're looking for the identifiers.
if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) {
// We expected to see an identifier here, and we did; continue handling
@@ -803,7 +900,7 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
CurLexerKind = CLK_LexAfterModuleImport;
return;
}
-
+
// If we're expecting a '.' or a ';', and we got a '.', then wait until we
// see the next identifier. (We can also see a '[[' that begins an
// attribute-specifier-seq here under the C++ Modules TS.)
@@ -959,7 +1056,7 @@ CodeCompletionHandler::~CodeCompletionHandler() = default;
void Preprocessor::createPreprocessingRecord() {
if (Record)
return;
-
+
Record = new PreprocessingRecord(getSourceManager());
addPPCallbacks(std::unique_ptr<PPCallbacks>(Record));
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
index 2e85f46f52c5..9f930c3a3c6a 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
@@ -28,7 +28,7 @@ PreprocessorLexer::PreprocessorLexer(Preprocessor *pp, FileID fid)
InitialNumSLocEntries = pp->getSourceManager().local_sloc_entry_size();
}
-/// \brief After the preprocessor has parsed a \#include, lex and
+/// After the preprocessor has parsed a \#include, lex and
/// (potentially) macro expand the filename.
void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) {
assert(ParsingPreprocessorDirective &&
diff --git a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
index e0f3966fce48..dc03e16daa8b 100644
--- a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
@@ -74,11 +74,11 @@ void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
// Get scratch buffer. Zero-initialize it so it can be dumped into a PCH file
// deterministically.
- std::unique_ptr<llvm::MemoryBuffer> OwnBuf =
- llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
- llvm::MemoryBuffer &Buf = *OwnBuf;
+ std::unique_ptr<llvm::WritableMemoryBuffer> OwnBuf =
+ llvm::WritableMemoryBuffer::getNewMemBuffer(RequestLen,
+ "<scratch space>");
+ CurBuffer = OwnBuf->getBufferStart();
FileID FID = SourceMgr.createFileID(std::move(OwnBuf));
BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
- CurBuffer = const_cast<char*>(Buf.getBufferStart());
BytesUsed = 0;
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index d7f1c7a93fda..608e0dedebb7 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -248,7 +248,7 @@ void TokenLexer::ExpandFunctionArguments() {
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
@@ -268,7 +268,7 @@ void TokenLexer::ExpandFunctionArguments() {
++I; // Skip the l_paren
VCtx.sawVAOptFollowedByOpeningParens(CurTok.getLocation(),
ResultToks.size());
-
+
continue;
}
@@ -336,14 +336,14 @@ void TokenLexer::ExpandFunctionArguments() {
}
// If we found the stringify operator, get the argument stringified. The
- // preprocessor already verified that the following token is a macro
+ // 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,
@@ -483,7 +483,7 @@ void TokenLexer::ExpandFunctionArguments() {
bool VaArgsPseudoPaste = false;
// If this is the GNU ", ## __VA_ARGS__" extension, and we just learned
// that __VA_ARGS__ expands to multiple tokens, avoid a pasting error when
- // the expander trys to paste ',' with the first token of the __VA_ARGS__
+ // the expander tries to paste ',' with the first token of the __VA_ARGS__
// expansion.
if (NonEmptyPasteBefore && ResultToks.size() >= 2 &&
ResultToks[ResultToks.size()-2].is(tok::comma) &&
@@ -574,7 +574,7 @@ void TokenLexer::ExpandFunctionArguments() {
}
}
-/// \brief Checks if two tokens form wide string literal.
+/// Checks if two tokens form wide string literal.
static bool isWideStringLiteralFromMacro(const Token &FirstTok,
const Token &SecondTok) {
return FirstTok.is(tok::identifier) &&
@@ -706,7 +706,7 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
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 = LHSTok.getLocation();
@@ -845,7 +845,7 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
// Transfer properties of the LHS over the Result.
Result.setFlagValue(Token::StartOfLine , LHSTok.isAtStartOfLine());
Result.setFlagValue(Token::LeadingSpace, LHSTok.hasLeadingSpace());
-
+
// Finally, replace LHS with the result, consume the RHS, and iterate.
++CurIdx;
LHSTok = Result;
@@ -865,10 +865,10 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
EndLoc = getExpansionLocForMacroDefLoc(EndLoc);
FileID MacroFID = SM.getFileID(MacroExpansionStart);
while (SM.getFileID(StartLoc) != MacroFID)
- StartLoc = SM.getImmediateExpansionRange(StartLoc).first;
+ StartLoc = SM.getImmediateExpansionRange(StartLoc).getBegin();
while (SM.getFileID(EndLoc) != MacroFID)
- EndLoc = SM.getImmediateExpansionRange(EndLoc).second;
-
+ EndLoc = SM.getImmediateExpansionRange(EndLoc).getEnd();
+
LHSTok.setLocation(SM.createExpansionLoc(LHSTok.getLocation(), StartLoc, EndLoc,
LHSTok.getLength()));
@@ -918,7 +918,7 @@ void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc) {
PP.HandleMicrosoftCommentPaste(Tok);
}
-/// \brief If \arg loc is a file ID and points inside the current macro
+/// If \arg loc is a file ID and points inside the current macro
/// definition, returns the appropriate source location pointing at the
/// macro expansion source location entry, otherwise it returns an invalid
/// SourceLocation.
@@ -927,7 +927,7 @@ TokenLexer::getExpansionLocForMacroDefLoc(SourceLocation loc) const {
assert(ExpandLocStart.isValid() && MacroExpansionStart.isValid() &&
"Not appropriate for token streams");
assert(loc.isValid() && loc.isFileID());
-
+
SourceManager &SM = PP.getSourceManager();
assert(SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength) &&
"Expected loc to come from the macro definition");
@@ -937,7 +937,7 @@ TokenLexer::getExpansionLocForMacroDefLoc(SourceLocation loc) const {
return MacroExpansionStart.getLocWithOffset(relativeOffset);
}
-/// \brief Finds the tokens that are consecutive (from the same FileID)
+/// Finds the tokens that are consecutive (from the same FileID)
/// creates a single SLocEntry, and assigns SourceLocations to each token that
/// point to that SLocEntry. e.g for
/// assert(foo == bar);
@@ -1007,7 +1007,7 @@ static void updateConsecutiveMacroArgTokens(SourceManager &SM,
}
}
-/// \brief Creates SLocEntries and updates the locations of macro argument
+/// Creates SLocEntries and updates the locations of macro argument
/// tokens to their new expanded locations.
///
/// \param ArgIdSpellLoc the location of the macro argument id inside the macro
@@ -1019,7 +1019,7 @@ void TokenLexer::updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,
SourceLocation InstLoc =
getExpansionLocForMacroDefLoc(ArgIdSpellLoc);
-
+
while (begin_tokens < end_tokens) {
// If there's only one token just create a SLocEntry for it.
if (end_tokens - begin_tokens == 1) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
index d018d4c08ed9..e71b5a9d1e6d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
@@ -21,6 +21,7 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
#include <memory>
@@ -106,7 +107,7 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
-
+
ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
}
@@ -121,6 +122,10 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
bool OldCollectStats = PrintStats;
std::swap(OldCollectStats, S.CollectStats);
+ // Initialize the template instantiation observer chain.
+ // FIXME: See note on "finalize" below.
+ initialize(S.TemplateInstCallbacks, S);
+
ASTConsumer *Consumer = &S.getASTConsumer();
std::unique_ptr<Parser> ParseOP(
@@ -136,6 +141,12 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
CleanupParser(ParseOP.get());
S.getPreprocessor().EnterMainSourceFile();
+ if (!S.getPreprocessor().getCurrentLexer()) {
+ // If a PCH through header is specified that does not have an include in
+ // the source, there won't be any tokens or a Lexer.
+ return;
+ }
+
P.Initialize();
Parser::DeclGroupPtrTy ADecl;
@@ -155,9 +166,16 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
// Process any TopLevelDecls generated by #pragma weak.
for (Decl *D : S.WeakTopLevelDecls())
Consumer->HandleTopLevelDecl(DeclGroupRef(D));
-
+
Consumer->HandleTranslationUnit(S.getASTContext());
+ // Finalize the template instantiation observer chain.
+ // FIXME: This (and init.) should be done in the Sema class, but because
+ // Sema does not have a reliable "Finalize" function (it has a
+ // destructor, but it is not guaranteed to be called ("-disable-free")).
+ // So, do the initialization above and do the finalization here:
+ finalize(S.TemplateInstCallbacks, S);
+
std::swap(OldCollectStats, S.CollectStats);
if (PrintStats) {
llvm::errs() << "\nSTATISTICS:\n";
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 2b3d4ba85bd8..5898120cab46 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -22,12 +22,10 @@ using namespace clang;
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
-NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
- AttributeList *AccessAttrs,
- ParsingDeclarator &D,
- const ParsedTemplateInfo &TemplateInfo,
- const VirtSpecifiers& VS,
- SourceLocation PureSpecLoc) {
+NamedDecl *Parser::ParseCXXInlineMethodDef(
+ AccessSpecifier AS, ParsedAttributes &AccessAttrs, ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers &VS,
+ SourceLocation PureSpecLoc) {
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) &&
"Current token not a '{', ':', '=', or 'try'!");
@@ -312,6 +310,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param);
std::unique_ptr<CachedTokens> Toks = std::move(LM.DefaultArgs[I].Toks);
if (Toks) {
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
// Mark the end of the default argument so that we know when to stop when
// we parse it later on.
Token LastDefaultArgToken = Toks->back();
@@ -384,6 +384,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// Parse a delayed exception-specification, if there is one.
if (CachedTokens *Toks = LM.ExceptionSpecTokens) {
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
// Add the 'stop' token.
Token LastExceptionSpecToken = Toks->back();
Token ExceptionSpecEnd;
@@ -489,6 +491,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
++CurTemplateDepthTracker;
}
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
assert(!LM.Toks.empty() && "Empty body!");
Token LastBodyToken = LM.Toks.back();
Token BodyEnd;
@@ -586,9 +590,9 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
if (!Class.LateParsedDeclarations.empty()) {
// C++11 [expr.prim.general]p4:
- // Otherwise, if a member-declarator declares a non-static data member
+ // Otherwise, if a member-declarator declares a non-static data member
// (9.2) of a class X, the expression this is a prvalue of type "pointer
- // to X" within the optional brace-or-equal-initializer. It shall not
+ // to X" within the optional brace-or-equal-initializer. It shall not
// appear elsewhere in the member-declarator.
Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
/*TypeQuals=*/(unsigned)0);
@@ -597,7 +601,7 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
}
}
-
+
if (!AlreadyHasClassScope)
Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
@@ -609,6 +613,8 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
if (!MI.Field || MI.Field->isInvalidDecl())
return;
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
// Append the current token at the end of the new token stream so that it
// doesn't get lost.
MI.Toks.push_back(Tok);
@@ -621,7 +627,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
Actions.ActOnStartCXXInClassMemberInitializer();
- ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
+ ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
EqualLoc);
Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc,
@@ -733,7 +739,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
}
}
-/// \brief Consume tokens and store them in the passed token container until
+/// Consume tokens and store them in the passed token container until
/// we've passed the try keyword and constructor initializers and have consumed
/// the opening brace of the function body. The opening brace will be consumed
/// if and only if there was no error.
@@ -937,7 +943,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
}
}
-/// \brief Consume and store tokens from the '?' to the ':' in a conditional
+/// Consume and store tokens from the '?' to the ':' in a conditional
/// expression.
bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) {
// Consume '?'.
@@ -962,7 +968,7 @@ bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) {
return true;
}
-/// \brief A tentative parsing action that can also revert token annotations.
+/// A tentative parsing action that can also revert token annotations.
class Parser::UnannotatedTentativeParsingAction : public TentativeParsingAction {
public:
explicit UnannotatedTentativeParsingAction(Parser &Self,
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 127e18439b8e..6e57c7bbba91 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
@@ -22,14 +23,12 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/ScopedPrinter.h"
using namespace clang;
@@ -54,7 +53,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
// Parse the common declaration-specifiers piece.
DeclSpec DS(AttrFactory);
if (Attrs)
- DS.addAttributes(Attrs->getList());
+ DS.addAttributes(*Attrs);
ParseSpecifierQualifierList(DS, AS, DSC);
if (OwnedType)
*OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;
@@ -71,7 +70,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
-/// \brief Normalizes an attribute name by dropping prefixed and suffixed __.
+/// Normalizes an attribute name by dropping prefixed and suffixed __.
static StringRef normalizeAttrName(StringRef Name) {
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
return Name.drop_front(2).drop_back(2);
@@ -163,14 +162,14 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
if (Tok.isNot(tok::l_paren)) {
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_GNU);
+ ParsedAttr::AS_GNU);
continue;
}
// Handle "parameterized" attributes
if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr,
- SourceLocation(), AttributeList::AS_GNU, D);
+ SourceLocation(), ParsedAttr::AS_GNU, D);
continue;
}
@@ -207,7 +206,7 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
}
}
-/// \brief Determine whether the given attribute has an identifier argument.
+/// Determine whether the given attribute has an identifier argument.
static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
#define CLANG_ATTR_IDENTIFIER_ARG_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
@@ -216,7 +215,16 @@ static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
#undef CLANG_ATTR_IDENTIFIER_ARG_LIST
}
-/// \brief Determine whether the given attribute parses a type argument.
+/// Determine whether the given attribute has a variadic identifier argument.
+static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) {
+#define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
+#include "clang/Parse/AttrParserStringSwitches.inc"
+ .Default(false);
+#undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
+}
+
+/// Determine whether the given attribute parses a type argument.
static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
#define CLANG_ATTR_TYPE_ARG_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
@@ -225,7 +233,7 @@ static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
#undef CLANG_ATTR_TYPE_ARG_LIST
}
-/// \brief Determine whether the given attribute requires parsing its arguments
+/// Determine whether the given attribute requires parsing its arguments
/// in an unevaluated context or not.
static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {
#define CLANG_ATTR_ARG_CONTEXT_LIST
@@ -250,7 +258,7 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax) {
+ ParsedAttr::Syntax Syntax) {
BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();
@@ -276,21 +284,22 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
unsigned Parser::ParseAttributeArgsCommon(
IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
// Ignore the left paren location for now.
ConsumeParen();
ArgsVector ArgExprs;
if (Tok.is(tok::identifier)) {
// If this attribute wants an 'identifier' argument, make it so.
- bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName);
- AttributeList::Kind AttrKind =
- AttributeList::getKind(AttrName, ScopeName, Syntax);
+ bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) ||
+ attributeHasVariadicIdentifierArg(*AttrName);
+ ParsedAttr::Kind AttrKind =
+ ParsedAttr::getKind(AttrName, ScopeName, Syntax);
// If we don't know how to parse this attribute, but this is the only
// token in this argument, assume it's meant to be an identifier.
- if (AttrKind == AttributeList::UnknownAttribute ||
- AttrKind == AttributeList::IgnoredAttribute) {
+ if (AttrKind == ParsedAttr::UnknownAttribute ||
+ AttrKind == ParsedAttr::IgnoredAttribute) {
const Token &Next = NextToken();
IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);
}
@@ -306,21 +315,25 @@ unsigned Parser::ParseAttributeArgsCommon(
// Parse the non-empty comma-separated list of expressions.
do {
- bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
- EnterExpressionEvaluationContext Unevaluated(
- Actions,
- Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
- : Sema::ExpressionEvaluationContext::ConstantEvaluated,
- /*LambdaContextDecl=*/nullptr,
- /*IsDecltype=*/false);
-
- ExprResult ArgExpr(
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
- if (ArgExpr.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return 0;
+ ExprResult ArgExpr;
+ if (Tok.is(tok::identifier) &&
+ attributeHasVariadicIdentifierArg(*AttrName)) {
+ ArgExprs.push_back(ParseIdentifierLoc());
+ } else {
+ bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions,
+ Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
+ : Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ ExprResult ArgExpr(
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+ if (ArgExpr.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return 0;
+ }
+ ArgExprs.push_back(ArgExpr.get());
}
- ArgExprs.push_back(ArgExpr.get());
// Eat the comma, move to the next argument
} while (TryConsumeToken(tok::comma));
}
@@ -346,27 +359,27 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax,
+ ParsedAttr::Syntax Syntax,
Declarator *D) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
- AttributeList::Kind AttrKind =
- AttributeList::getKind(AttrName, ScopeName, Syntax);
+ ParsedAttr::Kind AttrKind =
+ ParsedAttr::getKind(AttrName, ScopeName, Syntax);
- if (AttrKind == AttributeList::AT_Availability) {
+ if (AttrKind == ParsedAttr::AT_Availability) {
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Syntax);
return;
- } else if (AttrKind == AttributeList::AT_ExternalSourceSymbol) {
+ } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) {
ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
return;
- } else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) {
+ } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) {
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
return;
- } else if (AttrKind == AttributeList::AT_TypeTagForDatatype) {
+ } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
return;
@@ -398,20 +411,34 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
unsigned Parser::ParseClangAttributeArgs(
IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
- AttributeList::Kind AttrKind =
- AttributeList::getKind(AttrName, ScopeName, Syntax);
+ ParsedAttr::Kind AttrKind =
+ ParsedAttr::getKind(AttrName, ScopeName, Syntax);
- if (AttrKind == AttributeList::AT_ExternalSourceSymbol) {
+ switch (AttrKind) {
+ default:
+ return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ case ParsedAttr::AT_ExternalSourceSymbol:
ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
- return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0;
+ break;
+ case ParsedAttr::AT_Availability:
+ ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, Syntax);
+ break;
+ case ParsedAttr::AT_ObjCBridgeRelated:
+ ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ break;
+ case ParsedAttr::AT_TypeTagForDatatype:
+ ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ break;
}
-
- return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
- ScopeName, ScopeLoc, Syntax);
+ return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;
}
bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
@@ -538,19 +565,18 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
if (!HasInvalidAccessor)
Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),
AccessorNames[AK_Get], AccessorNames[AK_Put],
- AttributeList::AS_Declspec);
+ ParsedAttr::AS_Declspec);
T.skipToEnd();
return !HasInvalidAccessor;
}
unsigned NumArgs =
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
- SourceLocation(), AttributeList::AS_Declspec);
+ SourceLocation(), ParsedAttr::AS_Declspec);
// If this attribute's args were parsed, and it was expected to have
// arguments but none were provided, emit a diagnostic.
- const AttributeList *Attr = Attrs.getList();
- if (Attr && Attr->getMaxArgs() && !NumArgs) {
+ if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) {
Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;
return false;
}
@@ -621,7 +647,7 @@ void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
if (!AttrHandled)
Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Declspec);
+ ParsedAttr::AS_Declspec);
}
T.consumeClose();
if (End)
@@ -647,7 +673,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ ParsedAttr::AS_Keyword);
break;
}
default:
@@ -698,7 +724,7 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ ParsedAttr::AS_Keyword);
}
}
@@ -708,7 +734,7 @@ void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ ParsedAttr::AS_Keyword);
}
}
@@ -716,7 +742,7 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = Tok.getLocation();
Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ ParsedAttr::AS_Keyword);
}
void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
@@ -731,8 +757,8 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
if (!getLangOpts().ObjC1)
Diag(AttrNameLoc, diag::ext_nullability)
<< AttrName;
- attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ ParsedAttr::AS_Keyword);
break;
}
default:
@@ -745,12 +771,14 @@ static bool VersionNumberSeparator(const char Separator) {
return (Separator == '.' || Separator == '_');
}
-/// \brief Parse a version number.
+/// Parse a version number.
///
/// version:
/// simple-integer
-/// simple-integer ',' simple-integer
-/// simple-integer ',' simple-integer ',' simple-integer
+/// simple-integer '.' simple-integer
+/// simple-integer '_' simple-integer
+/// simple-integer '.' simple-integer '.' simple-integer
+/// simple-integer '_' simple-integer '_' simple-integer
VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
Range = SourceRange(Tok.getLocation(), Tok.getEndLoc());
@@ -828,7 +856,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
return VersionTuple();
}
- return VersionTuple(Major, Minor, (AfterMajorSeparator == '_'));
+ return VersionTuple(Major, Minor);
}
const char AfterMinorSeparator = ThisTokBegin[AfterMinor];
@@ -839,7 +867,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
return VersionTuple();
}
-
+
// Warn if separators, be it '.' or '_', do not match.
if (AfterMajorSeparator != AfterMinorSeparator)
Diag(Tok, diag::warn_expected_consistent_version_separator);
@@ -859,10 +887,10 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
return VersionTuple();
}
ConsumeToken();
- return VersionTuple(Major, Minor, Subminor, (AfterMajorSeparator == '_'));
+ return VersionTuple(Major, Minor, Subminor);
}
-/// \brief Parse the contents of the "availability" attribute.
+/// Parse the contents of the "availability" attribute.
///
/// availability-attribute:
/// 'availability' '(' platform ',' opt-strict version-arg-list,
@@ -893,7 +921,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax) {
+ ParsedAttr::Syntax Syntax) {
enum { Introduced, Deprecated, Obsoleted, Unknown };
AvailabilityChange Changes[Unknown];
ExprResult MessageExpr, ReplacementExpr;
@@ -1019,7 +1047,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
continue;
}
}
-
+
SourceRange VersionRange;
VersionTuple Version = ParseVersionTuple(VersionRange);
@@ -1094,7 +1122,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
Syntax, StrictLoc, ReplacementExpr.get());
}
-/// \brief Parse the contents of the "external_source_symbol" attribute.
+/// Parse the contents of the "external_source_symbol" attribute.
///
/// external-source-symbol-attribute:
/// 'external_source_symbol' '(' keyword-arg-list ')'
@@ -1110,7 +1138,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
void Parser::ParseExternalSourceSymbolAttribute(
IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
// Opening '('.
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.expectAndConsume())
@@ -1207,7 +1235,7 @@ void Parser::ParseExternalSourceSymbolAttribute(
ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
}
-/// \brief Parse the contents of the "objc_bridge_related" attribute.
+/// Parse the contents of the "objc_bridge_related" attribute.
/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
/// related_class:
/// Identifier
@@ -1224,14 +1252,14 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax) {
+ ParsedAttr::Syntax Syntax) {
// Opening '('.
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
Diag(Tok, diag::err_expected) << tok::l_paren;
return;
}
-
+
// Parse the related class name.
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_objcbridge_related_expected_related_class);
@@ -1244,7 +1272,9 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
return;
}
- // Parse optional class method name.
+ // Parse class method name. It's non-optional in the sense that a trailing
+ // comma is required, but it can be the empty string, and then we record a
+ // nullptr.
IdentifierLoc *ClassMethod = nullptr;
if (Tok.is(tok::identifier)) {
ClassMethod = ParseIdentifierLoc();
@@ -1262,8 +1292,9 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
SkipUntil(tok::r_paren, StopAtSemi);
return;
}
-
- // Parse optional instance method name.
+
+ // Parse instance method name. Also non-optional but empty string is
+ // permitted.
IdentifierLoc *InstanceMethod = nullptr;
if (Tok.is(tok::identifier))
InstanceMethod = ParseIdentifierLoc();
@@ -1272,14 +1303,14 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
SkipUntil(tok::r_paren, StopAtSemi);
return;
}
-
+
// Closing ')'.
if (T.consumeClose())
return;
-
+
if (endLoc)
*endLoc = T.getCloseLocation();
-
+
// Record this attribute
attrs.addNew(&ObjCBridgeRelated,
SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
@@ -1335,7 +1366,7 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) {
Class.TagOrTemplate);
}
-/// \brief Parse all attributes in LAs, and attach them to Decl D.
+/// Parse all attributes in LAs, and attach them to Decl D.
void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
bool EnterScope, bool OnDefinition) {
assert(LAs.parseSoon() &&
@@ -1349,7 +1380,7 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
LAs.clear();
}
-/// \brief Finish parsing an attribute for which parsing was delayed.
+/// Finish parsing an attribute for which parsing was delayed.
/// This will be called at the end of parsing a class declaration
/// for each LateParsedAttribute. We consume the saved tokens and
/// create an attribute with the arguments filled in. We add this
@@ -1400,7 +1431,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- nullptr, SourceLocation(), AttributeList::AS_GNU,
+ nullptr, SourceLocation(), ParsedAttr::AS_GNU,
nullptr);
if (HasFunScope) {
@@ -1414,16 +1445,15 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
// If there are multiple decls, then the decl cannot be within the
// function scope.
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- nullptr, SourceLocation(), AttributeList::AS_GNU,
+ nullptr, SourceLocation(), ParsedAttr::AS_GNU,
nullptr);
}
} else {
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
}
- const AttributeList *AL = Attrs.getList();
- if (OnDefinition && AL && !AL->isCXX11Attribute() &&
- AL->isKnownToGCC())
+ if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() &&
+ Attrs.begin()->isKnownToGCC())
Diag(Tok, diag::warn_attribute_on_function_definition)
<< &LA.AttrName;
@@ -1445,7 +1475,7 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax) {
+ ParsedAttr::Syntax Syntax) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1535,7 +1565,7 @@ bool Parser::DiagnoseProhibitedCXX11Attribute() {
llvm_unreachable("All cases handled above.");
}
-/// \brief We have found the opening square brackets of a C++11
+/// We have found the opening square brackets of a C++11
/// attribute-specifier in a location where an attribute is not permitted, but
/// we know where the attributes ought to be written. Parse them anyway, and
/// provide a fixit moving them to the right place.
@@ -1554,29 +1584,27 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
<< FixItHint::CreateRemoval(AttrRange);
}
-void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs,
- const SourceLocation CorrectLocation) {
+void Parser::DiagnoseProhibitedAttributes(
+ const SourceRange &Range, const SourceLocation CorrectLocation) {
if (CorrectLocation.isValid()) {
- CharSourceRange AttrRange(attrs.Range, true);
+ CharSourceRange AttrRange(Range, true);
Diag(CorrectLocation, diag::err_attributes_misplaced)
<< FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
<< FixItHint::CreateRemoval(AttrRange);
} else
- Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range;
+ Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range;
}
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
unsigned DiagID) {
- for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) {
- if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute())
+ for (const ParsedAttr &AL : Attrs) {
+ if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
continue;
- if (Attr->getKind() == AttributeList::UnknownAttribute)
- Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored)
- << Attr->getName();
+ if (AL.getKind() == ParsedAttr::UnknownAttribute)
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
else {
- Diag(Attr->getLoc(), DiagID)
- << Attr->getName();
- Attr->setInvalid();
+ Diag(AL.getLoc(), DiagID) << AL.getName();
+ AL.setInvalid();
}
}
}
@@ -1594,47 +1622,19 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
if (TUK == Sema::TUK_Reference)
return;
- ParsedAttributes &PA = DS.getAttributes();
- AttributeList *AL = PA.getList();
- AttributeList *Prev = nullptr;
- AttributeList *TypeAttrHead = nullptr;
- AttributeList *TypeAttrTail = nullptr;
- while (AL) {
- AttributeList *Next = AL->getNext();
-
- if ((AL->getKind() == AttributeList::AT_Aligned &&
- AL->isDeclspecAttribute()) ||
- AL->isMicrosoftAttribute()) {
- // Stitch the attribute into the tag's attribute list.
- if (TypeAttrTail)
- TypeAttrTail->setNext(AL);
- else
- TypeAttrHead = AL;
- TypeAttrTail = AL;
- TypeAttrTail->setNext(nullptr);
-
- // Remove the attribute from the variable's attribute list.
- if (Prev) {
- // Set the last variable attribute's next attribute to be the attribute
- // after the current one.
- Prev->setNext(Next);
- } else {
- // Removing the head of the list requires us to reset the head to the
- // next attribute.
- PA.set(Next);
- }
- } else {
- Prev = AL;
- }
+ llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;
- AL = Next;
+ for (ParsedAttr &AL : DS.getAttributes()) {
+ if ((AL.getKind() == ParsedAttr::AT_Aligned &&
+ AL.isDeclspecAttribute()) ||
+ AL.isMicrosoftAttribute())
+ ToBeMoved.push_back(&AL);
}
- // Find end of type attributes Attrs and add NewTypeAttributes in the same
- // order they were in originally. (Remember, in AttributeList things earlier
- // in source order are later in the list, since new attributes are added to
- // the front of the list.)
- Attrs.addAllAtEnd(TypeAttrHead);
+ for (ParsedAttr *AL : ToBeMoved) {
+ DS.getAttributes().remove(AL);
+ Attrs.addAtEnd(AL);
+ }
}
/// ParseDeclaration - Parse a full 'declaration', which consists of
@@ -1666,7 +1666,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
case tok::kw_template:
case tok::kw_export:
ProhibitAttributes(attrs);
- SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
+ SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs);
break;
case tok::kw_inline:
// Could be the start of an inline namespace. Allowed as an ext in C++03.
@@ -2010,8 +2010,13 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}
Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
- if (IsForRangeLoop)
+ if (IsForRangeLoop) {
Actions.ActOnCXXForRangeDecl(ThisDecl);
+ } else {
+ // Obj-C for loop
+ if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl))
+ VD->setObjCForDecl(true);
+ }
Actions.FinalizeDeclaration(ThisDecl);
D.complete(ThisDecl);
return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);
@@ -2027,7 +2032,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
DeclsInGroup.push_back(FirstDecl);
bool ExpectSemi = Context != DeclaratorContext::ForContext;
-
+
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
SourceLocation CommaLoc;
@@ -2107,7 +2112,7 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
return false;
}
-/// \brief Parse 'declaration' after parsing 'declaration-specifiers
+/// Parse 'declaration' after parsing 'declaration-specifiers
/// declarator'. This method parses the remainder of the declaration
/// (including any attributes or initializer, among other things) and
/// finalizes the declaration.
@@ -2446,7 +2451,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
SourceLocation Loc = Tok.getLocation();
// If we see an identifier that is not a type name, we normally would
- // parse it as the identifer being declared. However, when a typename
+ // parse it as the identifier being declared. However, when a typename
// is typo'd or the definition is not included, this will incorrectly
// parse the typename as the identifier name and fall over misparsing
// later parts of the diagnostic.
@@ -2656,7 +2661,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
return false;
}
-/// \brief Determine the declaration specifier context from the declarator
+/// Determine the declaration specifier context from the declarator
/// context.
///
/// \param Context the declarator context, which is one of the
@@ -2669,9 +2674,11 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
return DeclSpecContext::DSC_top_level;
if (Context == DeclaratorContext::TemplateParamContext)
return DeclSpecContext::DSC_template_param;
- if (Context == DeclaratorContext::TemplateTypeArgContext)
+ if (Context == DeclaratorContext::TemplateArgContext ||
+ Context == DeclaratorContext::TemplateTypeArgContext)
return DeclSpecContext::DSC_template_type_arg;
- if (Context == DeclaratorContext::TrailingReturnContext)
+ if (Context == DeclaratorContext::TrailingReturnContext ||
+ Context == DeclaratorContext::TrailingReturnVarContext)
return DeclSpecContext::DSC_trailing;
if (Context == DeclaratorContext::AliasDeclContext ||
Context == DeclaratorContext::AliasTemplateContext)
@@ -2740,7 +2747,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
ArgsVector ArgExprs;
ArgExprs.push_back(ArgExpr.get());
Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1,
- AttributeList::AS_Keyword, EllipsisLoc);
+ ParsedAttr::AS_Keyword, EllipsisLoc);
}
/// Determine whether we're looking at something that might be a declarator
@@ -2851,6 +2858,17 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
return false;
}
+// Choose the apprpriate diagnostic error for why fixed point types are
+// disabled, set the previous specifier, and mark as invalid.
+static void SetupFixedPointError(const LangOptions &LangOpts,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid) {
+ assert(!LangOpts.FixedPoint);
+ DiagID = diag::err_fixed_point_not_enabled;
+ PrevSpec = ""; // Not used by diagnostic
+ isInvalid = true;
+}
+
/// ParseDeclarationSpecifiers
/// declaration-specifiers: [C99 6.7]
/// storage-class-specifier declaration-specifiers[opt]
@@ -3216,6 +3234,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
continue;
}
+ // If we're in a context where the identifier could be a class name,
+ // check whether this is a constructor declaration.
+ if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
+ Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
+ isConstructorDeclarator(/*Unqualified*/true))
+ goto DoneWithDeclSpec;
+
ParsedType TypeRep = Actions.getTypeName(
*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,
false, false, nullptr, false, false,
@@ -3235,13 +3260,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
}
- // If we're in a context where the identifier could be a class name,
- // check whether this is a constructor declaration.
- if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
- Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
- isConstructorDeclarator(/*Unqualified*/true))
- goto DoneWithDeclSpec;
-
// Likewise, if this is a context where the identifier could be a template
// name, check whether this is a deduction guide declaration.
if (getLangOpts().CPlusPlus17 &&
@@ -3319,7 +3337,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = Tok.getLocation();
DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,
- nullptr, 0, AttributeList::AS_Keyword);
+ nullptr, 0, ParsedAttr::AS_Keyword);
break;
}
@@ -3362,7 +3380,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Objective-C 'kindof' types.
case tok::kw___kindof:
DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
- nullptr, 0, AttributeList::AS_Keyword);
+ nullptr, 0, ParsedAttr::AS_Keyword);
(void)ConsumeToken();
continue;
@@ -3430,6 +3448,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw_thread_local:
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc,
PrevSpec, DiagID);
+ isStorageClass = true;
break;
case tok::kw__Thread_local:
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
@@ -3442,7 +3461,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);
break;
case tok::kw_virtual:
- isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
+ // OpenCL C++ v1.0 s2.9: the virtual function qualifier is not supported.
+ if (getLangOpts().OpenCLCPlusPlus) {
+ DiagID = diag::err_openclcxx_virtual_function;
+ PrevSpec = Tok.getIdentifierInfo()->getNameStart();
+ isInvalid = true;
+ }
+ else {
+ isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
+ }
break;
case tok::kw_explicit:
isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID);
@@ -3546,6 +3573,29 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,
DiagID, Policy);
break;
+ case tok::kw__Accum:
+ if (!getLangOpts().FixedPoint) {
+ SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
+ } else {
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec,
+ DiagID, Policy);
+ }
+ break;
+ case tok::kw__Fract:
+ if (!getLangOpts().FixedPoint) {
+ SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
+ } else {
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec,
+ DiagID, Policy);
+ }
+ break;
+ case tok::kw__Sat:
+ if (!getLangOpts().FixedPoint) {
+ SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
+ } else {
+ isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID);
+ }
+ break;
case tok::kw___float128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
DiagID, Policy);
@@ -3554,6 +3604,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
DiagID, Policy);
break;
+ case tok::kw_char8_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec,
+ DiagID, Policy);
+ break;
case tok::kw_char16_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
DiagID, Policy);
@@ -3714,11 +3768,25 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
getLangOpts());
break;
- // OpenCL qualifiers:
+ // OpenCL access qualifiers:
+ case tok::kw___read_only:
+ case tok::kw___write_only:
+ case tok::kw___read_write:
+ // OpenCL C++ 1.0 s2.2: access qualifiers are reserved keywords.
+ if (Actions.getLangOpts().OpenCLCPlusPlus) {
+ DiagID = diag::err_openclcxx_reserved;
+ PrevSpec = Tok.getIdentifierInfo()->getNameStart();
+ isInvalid = true;
+ }
+ ParseOpenCLQualifiers(DS.getAttributes());
+ break;
+
+ // OpenCL address space qualifiers:
case tok::kw___generic:
// generic address space is introduced only in OpenCL v2.0
// see OpenCL C Spec v2.0 s6.5.5
- if (Actions.getLangOpts().OpenCLVersion < 200) {
+ if (Actions.getLangOpts().OpenCLVersion < 200 &&
+ !Actions.getLangOpts().OpenCLCPlusPlus) {
DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
isInvalid = true;
@@ -3729,9 +3797,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___global:
case tok::kw___local:
case tok::kw___constant:
- case tok::kw___read_only:
- case tok::kw___write_only:
- case tok::kw___read_write:
ParseOpenCLQualifiers(DS.getAttributes());
break;
@@ -3750,7 +3815,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
PrevSpec, DiagID, Type.get(),
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
-
+
DS.SetRangeEnd(EndLoc);
} else {
DS.SetTypeSpecError();
@@ -3769,18 +3834,17 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
Diag(Tok, DiagID)
<< PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());
else if (DiagID == diag::err_opencl_unknown_type_specifier) {
- const int OpenCLVer = getLangOpts().OpenCLVersion;
- std::string VerSpec = llvm::to_string(OpenCLVer / 100) +
- std::string (".") +
- llvm::to_string((OpenCLVer % 100) / 10);
- Diag(Tok, DiagID) << VerSpec << PrevSpec << isStorageClass;
+ Diag(Tok, DiagID) << getLangOpts().OpenCLCPlusPlus
+ << getLangOpts().getOpenCLVersionTuple().getAsString()
+ << PrevSpec << isStorageClass;
} else
Diag(Tok, DiagID) << PrevSpec;
}
DS.SetRangeEnd(Tok.getLocation());
if (DiagID != diag::err_bool_redeclaration)
- ConsumeToken();
+ // After an error the next token can be an annotation token.
+ ConsumeAnyToken();
AttrsLastTime = false;
}
@@ -3889,7 +3953,7 @@ void Parser::ParseStructDeclaration(
///
void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
unsigned TagType, Decl *TagDecl) {
- PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
"parsing struct/union body");
assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
@@ -3995,10 +4059,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// If attributes exist after struct contents, parse them.
MaybeParseGNUAttributes(attrs);
- Actions.ActOnFields(getCurScope(),
- RecordLoc, TagDecl, FieldDecls,
- T.getOpenLocation(), T.getCloseLocation(),
- attrs.getList());
+ Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls,
+ T.getOpenLocation(), T.getCloseLocation(), attrs);
StructScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());
}
@@ -4309,8 +4371,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
unsigned DiagID;
Decl *TagDecl = Actions.ActOnTag(
getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc,
- attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned,
- IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType,
+ attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,
+ ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType,
DSC == DeclSpecContext::DSC_type_specifier,
DSC == DeclSpecContext::DSC_template_param ||
DSC == DeclSpecContext::DSC_template_type_arg,
@@ -4451,8 +4513,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// Install the enumerator constant into EnumDecl.
Decl *EnumConstDecl = Actions.ActOnEnumConstant(
- getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident,
- attrs.getList(), EqualLoc, AssignedVal.get());
+ getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs,
+ EqualLoc, AssignedVal.get());
EnumAvailabilityDiags.back().done();
EnumConstantDecls.push_back(EnumConstDecl);
@@ -4504,10 +4566,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
ParsedAttributes attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
- Actions.ActOnEnumBody(StartLoc, T.getRange(),
- EnumDecl, EnumConstantDecls,
- getCurScope(),
- attrs.getList());
+ Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls,
+ getCurScope(), attrs);
// Now handle enum constant availability diagnostics.
assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());
@@ -4551,12 +4611,15 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
case tok::kw_void:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_int:
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Accum:
+ case tok::kw__Fract:
case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_bool:
@@ -4627,12 +4690,15 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw_void:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_int:
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Accum:
+ case tok::kw__Fract:
case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_bool:
@@ -4656,6 +4722,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
+ case tok::kw__Sat:
// Debugger support.
case tok::kw___unknown_anytype:
@@ -4783,6 +4850,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw_void:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
@@ -4790,6 +4858,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Accum:
+ case tok::kw__Fract:
case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_bool:
@@ -4811,6 +4881,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
+ case tok::kw__Sat:
// function-specifier
case tok::kw_inline:
@@ -5100,7 +5171,7 @@ void Parser::ParseTypeQualifierListOpt(
getLangOpts());
break;
case tok::kw___uptr:
- // GNU libc headers in C mode use '__uptr' as an identifer which conflicts
+ // GNU libc headers in C mode use '__uptr' as an identifier which conflicts
// with the MS modifier keyword.
if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus &&
IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) {
@@ -5140,7 +5211,7 @@ void Parser::ParseTypeQualifierListOpt(
// Objective-C 'kindof' types.
case tok::kw___kindof:
DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
- nullptr, 0, AttributeList::AS_Keyword);
+ nullptr, 0, ParsedAttr::AS_Keyword);
(void)ConsumeToken();
continue;
@@ -5291,10 +5362,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Sema will have to catch (syntactically invalid) pointers into global
// scope. It has to catch pointers into namespace scope anyway.
- D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(),
- DS.getLocEnd()),
- DS.getAttributes(),
- /* Don't replace range end. */SourceLocation());
+ D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
+ SS, DS.getTypeQualifiers(), DS.getLocEnd()),
+ std::move(DS.getAttributes()),
+ /* Don't replace range end. */ SourceLocation());
return;
}
}
@@ -5307,7 +5378,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
D.AddTypeInfo(
DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
- DS.getAttributes(), SourceLocation());
+ std::move(DS.getAttributes()), SourceLocation());
}
// Not a pointer, C++ reference, or block.
@@ -5339,20 +5410,16 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
ParseDeclaratorInternal(D, DirectDeclParser);
if (Kind == tok::star)
// Remember that we parsed a pointer type, and remember the type-quals.
- D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
- DS.getConstSpecLoc(),
- DS.getVolatileSpecLoc(),
- DS.getRestrictSpecLoc(),
- DS.getAtomicSpecLoc(),
- DS.getUnalignedSpecLoc()),
- DS.getAttributes(),
- SourceLocation());
+ D.AddTypeInfo(DeclaratorChunk::getPointer(
+ DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(),
+ DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(),
+ DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()),
+ std::move(DS.getAttributes()), SourceLocation());
else
// Remember that we parsed a Block type, and remember the type-quals.
- D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
- Loc),
- DS.getAttributes(),
- SourceLocation());
+ D.AddTypeInfo(
+ DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc),
+ std::move(DS.getAttributes()), SourceLocation());
} else {
// Is a reference
DeclSpec DS(AttrFactory);
@@ -5407,8 +5474,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Remember that we parsed a reference type.
D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
Kind == tok::amp),
- DS.getAttributes(),
- SourceLocation());
+ std::move(DS.getAttributes()), SourceLocation());
}
}
@@ -5561,17 +5627,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
} else {
AllowConstructorName =
(D.getContext() == DeclaratorContext::MemberContext);
- AllowDeductionGuide =
+ AllowDeductionGuide =
(D.getContext() == DeclaratorContext::FileContext ||
D.getContext() == DeclaratorContext::MemberContext);
}
- SourceLocation TemplateKWLoc;
bool HadScope = D.getCXXScopeSpec().isValid();
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*EnteringContext=*/true,
/*AllowDestructorName=*/true, AllowConstructorName,
- AllowDeductionGuide, nullptr, TemplateKWLoc,
+ AllowDeductionGuide, nullptr, nullptr,
D.getName()) ||
// Once we're past the identifier, if the scope was bad, mark the
// whole declarator bad.
@@ -5619,7 +5684,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// An identifier within parens is unlikely to be intended to be anything
// other than a name being "declared".
DiagnoseIdentifier = true;
- else if (D.getContext() == DeclaratorContext::TemplateTypeArgContext)
+ else if (D.getContext() == DeclaratorContext::TemplateArgContext)
// T<int N> is an accidental identifier; T<int N indicates a missing '>'.
DiagnoseIdentifier =
NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
@@ -5627,7 +5692,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
D.getContext() == DeclaratorContext::AliasTemplateContext)
// The most likely error is that the ';' was forgotten.
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
- else if (D.getContext() == DeclaratorContext::TrailingReturnContext &&
+ else if ((D.getContext() == DeclaratorContext::TrailingReturnContext ||
+ D.getContext() == DeclaratorContext::TrailingReturnVarContext) &&
!isCXX11VirtSpecifier(Tok))
DiagnoseIdentifier = NextToken().isOneOf(
tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
@@ -5641,6 +5707,18 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}
if (Tok.is(tok::l_paren)) {
+ // If this might be an abstract-declarator followed by a direct-initializer,
+ // check whether this is a valid declarator chunk. If it can't be, assume
+ // that it's an initializer instead.
+ if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
+ RevertingTentativeParsingAction PA(*this);
+ if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) ==
+ TPResult::False) {
+ D.SetIdentifier(nullptr, Tok.getLocation());
+ goto PastIdentifier;
+ }
+ }
+
// direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')'
// Example: 'char (*X)' or 'int (*XX)(void)'
@@ -5904,9 +5982,9 @@ void Parser::ParseParenDeclarator(Declarator &D) {
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
// Match the ')'.
T.consumeClose();
- D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(),
- T.getCloseLocation()),
- attrs, T.getCloseLocation());
+ D.AddTypeInfo(
+ DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()),
+ std::move(attrs), T.getCloseLocation());
D.setGroupingParens(hadGroupingParens);
@@ -6004,13 +6082,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
LocalEndLoc = RParenLoc;
EndLoc = RParenLoc;
- // If there are attributes following the identifier list, parse them and
+ // 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,
+ ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
EllipsisLoc);
else if (RequiresArg)
Diag(Tok, diag::err_argument_required_after_attribute);
@@ -6111,7 +6189,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
StartLoc = D.getDeclSpec().getTypeSpecTypeLoc();
LocalEndLoc = Tok.getLocation();
SourceRange Range;
- TrailingReturnType = ParseTrailingReturnType(Range);
+ TrailingReturnType =
+ ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit());
EndLoc = Range.getEnd();
}
} else if (standardAttributesAllowed()) {
@@ -6135,28 +6214,19 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
}
// Remember that we parsed a function type, and remember the attributes.
- D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto,
- IsAmbiguous,
- LParenLoc,
- ParamInfo.data(), ParamInfo.size(),
- EllipsisLoc, RParenLoc,
- DS.getTypeQualifiers(),
- RefQualifierIsLValueRef,
- RefQualifierLoc, ConstQualifierLoc,
- VolatileQualifierLoc,
- RestrictQualifierLoc,
- /*MutableLoc=*/SourceLocation(),
- ESpecType, ESpecRange,
- DynamicExceptions.data(),
- DynamicExceptionRanges.data(),
- DynamicExceptions.size(),
- NoexceptExpr.isUsable() ?
- NoexceptExpr.get() : nullptr,
- ExceptionSpecTokens,
- DeclsInPrototype,
- StartLoc, LocalEndLoc, D,
- TrailingReturnType),
- FnAttrs, EndLoc);
+ D.AddTypeInfo(DeclaratorChunk::getFunction(
+ HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(),
+ ParamInfo.size(), EllipsisLoc, RParenLoc,
+ DS.getTypeQualifiers(), RefQualifierIsLValueRef,
+ RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc,
+ RestrictQualifierLoc,
+ /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange,
+ DynamicExceptions.data(), DynamicExceptionRanges.data(),
+ DynamicExceptions.size(),
+ NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
+ ExceptionSpecTokens, DeclsInPrototype, StartLoc,
+ LocalEndLoc, D, TrailingReturnType),
+ std::move(FnAttrs), EndLoc);
}
/// ParseRefQualifier - Parses a member function ref-qualifier. Returns
@@ -6321,8 +6391,8 @@ void Parser::ParseParameterDeclarationClause(
ParseDeclarationSpecifiers(DS);
- // Parse the declarator. This is "PrototypeContext" or
- // "LambdaExprParameterContext", because we must accept either
+ // Parse the declarator. This is "PrototypeContext" or
+ // "LambdaExprParameterContext", because we must accept either
// 'declarator' or 'abstract-declarator' here.
Declarator ParmDeclarator(
DS, D.getContext() == DeclaratorContext::LambdaExprContext
@@ -6414,7 +6484,7 @@ void Parser::ParseParameterDeclarationClause(
}
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDeclarator.getIdentifierLoc(),
+ ParmDeclarator.getIdentifierLoc(),
Param, std::move(DefArgToks)));
}
@@ -6478,7 +6548,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
T.getOpenLocation(),
T.getCloseLocation()),
- attrs, T.getCloseLocation());
+ std::move(attrs), T.getCloseLocation());
return;
} else if (Tok.getKind() == tok::numeric_constant &&
GetLookAheadToken(1).is(tok::r_square)) {
@@ -6491,11 +6561,10 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
MaybeParseCXX11Attributes(attrs);
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false,
- ExprRes.get(),
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(),
T.getOpenLocation(),
T.getCloseLocation()),
- attrs, T.getCloseLocation());
+ std::move(attrs), T.getCloseLocation());
return;
} else if (Tok.getKind() == tok::code_completion) {
Actions.CodeCompleteBracketDeclarator(getCurScope());
@@ -6568,12 +6637,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
MaybeParseCXX11Attributes(DS.getAttributes());
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
- StaticLoc.isValid(), isStar,
- NumElements.get(),
- T.getOpenLocation(),
- T.getCloseLocation()),
- DS.getAttributes(), T.getCloseLocation());
+ D.AddTypeInfo(
+ DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(),
+ isStar, NumElements.get(), T.getOpenLocation(),
+ T.getCloseLocation()),
+ std::move(DS.getAttributes()), T.getCloseLocation());
}
/// Diagnose brackets before an identifier.
@@ -6625,18 +6693,15 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
if (NeedParens) {
// Create a DeclaratorChunk for the inserted parens.
- ParsedAttributes attrs(AttrFactory);
SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd());
- D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), attrs,
+ D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc),
SourceLocation());
}
// Adding back the bracket info to the end of the Declarator.
for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {
const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);
- ParsedAttributes attrs(AttrFactory);
- attrs.set(Chunk.Common.AttrList);
- D.AddTypeInfo(Chunk, attrs, SourceLocation());
+ D.AddTypeInfo(Chunk, SourceLocation());
}
// The missing identifier would have been diagnosed in ParseDirectDeclarator.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
index 68b73ca1d25f..9ba44d07aba8 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/OperatorKinds.h"
@@ -22,7 +23,6 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
@@ -61,7 +61,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
ObjCDeclContextSwitch ObjCDC(*this);
-
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(getCurScope());
cutOffParsing();
@@ -130,8 +130,8 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
return nullptr;
}
- if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
- getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||
+ if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
+ getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||
getCurScope()->getFnParent()) {
Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace);
@@ -183,15 +183,14 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
ParseScope NamespaceScope(this, Scope::DeclScope);
UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
- Decl *NamespcDecl =
- Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc,
- IdentLoc, Ident, T.getOpenLocation(),
- attrs.getList(), ImplicitUsingDirectiveDecl);
+ Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
+ getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident,
+ T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl);
- PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
- "parsing namespace");
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl,
+ NamespaceLoc, "parsing namespace");
- // Parse the contents of the namespace. This includes parsing recovery on
+ // Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
InlineLoc, attrs, T);
@@ -201,8 +200,8 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
DeclEnd = T.getCloseLocation();
Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);
-
- return Actions.ConvertDeclToDeclGroup(NamespcDecl,
+
+ return Actions.ConvertDeclToDeclGroup(NamespcDecl,
ImplicitUsingDirectiveDecl);
}
@@ -233,12 +232,11 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
// desugaring it here.
ParseScope NamespaceScope(this, Scope::DeclScope);
UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
- Decl *NamespcDecl =
- Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(),
- NamespaceLoc[index], IdentLoc[index],
- Ident[index], Tracker.getOpenLocation(),
- attrs.getList(), ImplicitUsingDirectiveDecl);
- assert(!ImplicitUsingDirectiveDecl &&
+ Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
+ getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index],
+ Ident[index], Tracker.getOpenLocation(), attrs,
+ ImplicitUsingDirectiveDecl);
+ assert(!ImplicitUsingDirectiveDecl &&
"nested namespace definition cannot define anonymous namespace");
ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
@@ -440,7 +438,7 @@ Parser::ParseUsingDirectiveOrDeclaration(DeclaratorContext Context,
ParsedAttributesWithRange &attrs) {
assert(Tok.is(tok::kw_using) && "Not using token");
ObjCDeclContextSwitch ObjCDC(*this);
-
+
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
@@ -543,7 +541,7 @@ Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
SkipUntil(tok::semi);
return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
- IdentLoc, NamespcName, attrs.getList());
+ IdentLoc, NamespcName, attrs);
}
/// Parse a using-declarator (or the identifier in a C++11 alias-declaration).
@@ -602,7 +600,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
/*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
NextToken().is(tok::equal)),
/*AllowDeductionGuide=*/false,
- nullptr, D.TemplateKWLoc, D.Name))
+ nullptr, nullptr, D.Name))
return true;
}
@@ -711,7 +709,7 @@ Parser::ParseUsingDeclaration(DeclaratorContext Context,
Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc,
D.TypenameLoc, D.SS, D.Name,
- D.EllipsisLoc, Attrs.getList());
+ D.EllipsisLoc, Attrs);
if (UD)
DeclsInGroup.push_back(UD);
}
@@ -813,8 +811,8 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
TemplateParams ? TemplateParams->data() : nullptr,
TemplateParams ? TemplateParams->size() : 0);
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
- UsingLoc, D.Name, Attrs.getList(),
- TypeAlias, DeclFromDeclSpec);
+ UsingLoc, D.Name, Attrs, TypeAlias,
+ DeclFromDeclSpec);
}
/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
@@ -898,7 +896,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)
&& "Not a decltype specifier");
-
+
ExprResult Result;
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc;
@@ -942,7 +940,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
- /*IsDecltype=*/true);
+ Sema::ExpressionEvaluationContextRecord::EK_Decltype);
Result =
Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
return E->hasPlaceholderType() ? ExprError() : E;
@@ -1001,7 +999,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
return EndLoc;
}
-void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS,
+void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS,
SourceLocation StartLoc,
SourceLocation EndLoc) {
// make sure we have a token we can turn into an annotation token
@@ -1052,9 +1050,9 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
}
/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
-/// class name or decltype-specifier. Note that we only check that the result
-/// names a type; semantic analysis will need to verify that the type names a
-/// class. The result is either a type or null, depending on whether a type
+/// class name or decltype-specifier. Note that we only check that the result
+/// names a type; semantic analysis will need to verify that the type names a
+/// class. The result is either a type or null, depending on whether a type
/// name was found.
///
/// base-type-specifier: [C++11 class.derived]
@@ -1085,7 +1083,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
BaseLoc = Tok.getLocation();
// Parse decltype-specifier
- // tok == kw_decltype is just error recovery, it can only happen when SS
+ // tok == kw_decltype is just error recovery, it can only happen when SS
// isn't empty
if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {
if (SS.isNotEmpty())
@@ -1208,7 +1206,7 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ ParsedAttr::AS_Keyword);
}
}
@@ -1350,8 +1348,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
SourceLocation StartLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
- AccessSpecifier AS,
- bool EnteringContext, DeclSpecContext DSC,
+ AccessSpecifier AS,
+ bool EnteringContext, DeclSpecContext DSC,
ParsedAttributesWithRange &Attributes) {
DeclSpec::TST TagType;
if (TagTokKind == tok::kw_struct)
@@ -1752,24 +1750,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// This is an explicit instantiation of a class template.
ProhibitAttributes(attrs);
- TagOrTempResult
- = Actions.ActOnExplicitInstantiation(getCurScope(),
- TemplateInfo.ExternLoc,
- TemplateInfo.TemplateLoc,
- TagType,
- StartLoc,
- SS,
- TemplateId->Template,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc,
- attrs.getList());
-
- // Friend template-ids are treated as references unless
- // they have template headers, in which case they're ill-formed
- // (FIXME: "template <class T> friend class A<T>::B<int>;").
- // We diagnose this error in ActOnClassTemplateSpecialization.
+ TagOrTempResult = Actions.ActOnExplicitInstantiation(
+ getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,
+ TagType, StartLoc, SS, TemplateId->Template,
+ TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr,
+ TemplateId->RAngleLoc, attrs);
+
+ // Friend template-ids are treated as references unless
+ // they have template headers, in which case they're ill-formed
+ // (FIXME: "template <class T> friend class A<T>::B<int>;").
+ // We diagnose this error in ActOnClassTemplateSpecialization.
} else if (TUK == Sema::TUK_Reference ||
(TUK == Sema::TUK_Friend &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
@@ -1825,7 +1815,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Build the class template specialization.
TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
- *TemplateId, attrs.getList(),
+ *TemplateId, attrs,
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
: nullptr,
TemplateParams ? TemplateParams->size() : 0),
@@ -1840,24 +1830,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
//
ProhibitAttributes(attrs);
- TagOrTempResult
- = Actions.ActOnExplicitInstantiation(getCurScope(),
- TemplateInfo.ExternLoc,
- TemplateInfo.TemplateLoc,
- TagType, StartLoc, SS, Name,
- NameLoc, attrs.getList());
+ TagOrTempResult = Actions.ActOnExplicitInstantiation(
+ getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,
+ TagType, StartLoc, SS, Name, NameLoc, attrs);
} else if (TUK == Sema::TUK_Friend &&
TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
ProhibitAttributes(attrs);
- TagOrTempResult =
- Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(),
- TagType, StartLoc, SS,
- Name, NameLoc, attrs.getList(),
- MultiTemplateParamsArg(
- TemplateParams? &(*TemplateParams)[0]
- : nullptr,
- TemplateParams? TemplateParams->size() : 0));
+ TagOrTempResult = Actions.ActOnTemplatedFriendTag(
+ getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name,
+ NameLoc, attrs,
+ MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr,
+ TemplateParams ? TemplateParams->size() : 0));
} else {
if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
ProhibitAttributes(attrs);
@@ -1885,9 +1869,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(
- getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc,
- attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned,
- IsDependent, SourceLocation(), false, clang::TypeResult(),
+ getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS,
+ DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,
+ SourceLocation(), false, clang::TypeResult(),
DSC == DeclSpecContext::DSC_type_specifier,
DSC == DeclSpecContext::DSC_template_param ||
DSC == DeclSpecContext::DSC_template_type_arg,
@@ -1929,7 +1913,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (!TagOrTempResult.isInvalid())
// Delayed processing of attributes.
- Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList());
+ Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs);
const char *PrevSpec = nullptr;
unsigned DiagID;
@@ -2077,7 +2061,7 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
if (BaseType.isInvalid())
return true;
- // Parse the optional ellipsis (for a pack expansion). The ellipsis is
+ // Parse the optional ellipsis (for a pack expansion). The ellipsis is
// actually part of the base-specifier-list grammar productions, but we
// parse it here for convenience.
SourceLocation EllipsisLoc;
@@ -2109,7 +2093,7 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
}
}
-/// \brief If the given declarator has any parts for which parsing has to be
+/// If the given declarator has any parts for which parsing has to be
/// delayed, e.g., default arguments or an exception-specification, create a
/// late-parsed method declaration record to handle the parsing at the end of
/// the class definition.
@@ -2245,11 +2229,11 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
bool Parser::isCXX11FinalKeyword() const {
VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
return Specifier == VirtSpecifiers::VS_Final ||
- Specifier == VirtSpecifiers::VS_GNU_Final ||
+ Specifier == VirtSpecifiers::VS_GNU_Final ||
Specifier == VirtSpecifiers::VS_Sealed;
}
-/// \brief Parse a C++ member-declarator up to, but not including, the optional
+/// Parse a C++ member-declarator up to, but not including, the optional
/// brace-or-equal-initializer or pure-specifier.
bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
@@ -2300,12 +2284,10 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
if (!VS.isUnset()) {
// If we saw any GNU-style attributes that are known to GCC followed by a
// virt-specifier, issue a GCC-compat warning.
- const AttributeList *Attr = DeclaratorInfo.getAttributes();
- while (Attr) {
- if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute())
- Diag(Attr->getLoc(), diag::warn_gcc_attribute_location);
- Attr = Attr->getNext();
- }
+ for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())
+ if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
+ Diag(AL.getLoc(), diag::warn_gcc_attribute_location);
+
MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
}
}
@@ -2320,7 +2302,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
return false;
}
-/// \brief Look for declaration specifiers possibly occurring after C++11
+/// Look for declaration specifiers possibly occurring after C++11
/// virt-specifier-seq and diagnose them.
void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
Declarator &D,
@@ -2415,7 +2397,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
/// override
/// final
/// [MS] sealed
-///
+///
/// pure-specifier:
/// '= 0'
///
@@ -2424,7 +2406,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
///
Parser::DeclGroupPtrTy
Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- AttributeList *AccessAttrs,
+ ParsedAttributes &AccessAttrs,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject *TemplateDiags) {
if (Tok.is(tok::at)) {
@@ -2476,7 +2458,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
if (ParseUnqualifiedId(SS, false, true, true, false, nullptr,
- TemplateKWLoc, Name)) {
+ &TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
return nullptr;
}
@@ -2488,10 +2470,12 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return nullptr;
}
+ // FIXME: We should do something with the 'template' keyword here.
return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration(
getCurScope(), AS, /*UsingLoc*/ SourceLocation(),
/*TypenameLoc*/ SourceLocation(), SS, Name,
- /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr)));
+ /*EllipsisLoc*/ SourceLocation(),
+ /*AttrList*/ ParsedAttributesView())));
}
}
@@ -2511,7 +2495,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation DeclEnd;
return DeclGroupPtrTy::make(
DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
- DeclaratorContext::MemberContext, DeclEnd, AS, AccessAttrs)));
+ DeclaratorContext::MemberContext, DeclEnd, AccessAttrs, AS)));
}
// Handle: member-declaration ::= '__extension__' member-declaration
@@ -2524,12 +2508,12 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
ParsedAttributesWithRange attrs(AttrFactory);
- ParsedAttributesWithRange FnAttrs(AttrFactory);
+ ParsedAttributesViewWithRange FnAttrs;
// Optional C++11 attribute-specifier
MaybeParseCXX11Attributes(attrs);
// We need to keep these attributes for future diagnostic
// before they are taken over by declaration specifier.
- FnAttrs.addAll(attrs.getList());
+ FnAttrs.addAll(attrs.begin(), attrs.end());
FnAttrs.Range = attrs.Range;
MaybeParseMicrosoftAttributes(attrs);
@@ -2664,9 +2648,9 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);
- // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
+ // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
- if (DeclaratorInfo.isFunctionDeclarator() &&
+ if (DeclaratorInfo.isFunctionDeclarator() &&
DefinitionKind != FDK_Definition && DS.isFriendSpecified()) {
// Diagnose attributes that appear before decl specifier:
// [[]] friend int foo();
@@ -2776,7 +2760,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// initialize it.
ThisDecl = VT->getTemplatedDecl();
- if (ThisDecl && AccessAttrs)
+ if (ThisDecl)
Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);
}
@@ -3008,10 +2992,12 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
DeclSpec::TST TagType, Decl *TagDecl) {
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
switch (Tok.getKind()) {
case tok::kw___if_exists:
case tok::kw___if_not_exists:
- ParseMicrosoftIfExistsClassDeclaration(TagType, AS);
+ ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS);
return nullptr;
case tok::semi:
@@ -3077,8 +3063,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected);
}
- if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc,
- AccessAttrs.getList())) {
+ if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) {
// found another attribute than only annotations
AccessAttrs.clear();
}
@@ -3091,7 +3076,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
TagDecl);
default:
- return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
+ return ParseCXXClassMemberDeclaration(AS, AccessAttrs);
}
}
@@ -3110,7 +3095,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
TagType == DeclSpec::TST_union ||
TagType == DeclSpec::TST_class) && "Invalid TagType!");
- PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
"parsing struct/union/class body");
// Determine whether this is a non-nested class. Note that local
@@ -3157,7 +3142,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
assert((Specifier == VirtSpecifiers::VS_Final ||
- Specifier == VirtSpecifiers::VS_GNU_Final ||
+ Specifier == VirtSpecifiers::VS_GNU_Final ||
Specifier == VirtSpecifiers::VS_Sealed) &&
"not a class definition");
FinalLoc = ConsumeToken();
@@ -3279,9 +3264,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (TagDecl)
Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,
- T.getOpenLocation(),
- T.getCloseLocation(),
- attrs.getList());
+ T.getOpenLocation(),
+ T.getCloseLocation(), attrs);
// C++11 [class.mem]p2:
// Within the class member-specification, the class is regarded as complete
@@ -3473,7 +3457,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
TryConsumeToken(tok::ellipsis, EllipsisLoc);
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
- TemplateTypeTy, DS, IdLoc,
+ TemplateTypeTy, DS, IdLoc,
InitList.get(), EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -3504,7 +3488,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
return Diag(Tok, diag::err_expected) << tok::l_paren;
}
-/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]).
+/// Parse a C++ exception-specification if present (C++0x [except.spec]).
///
/// exception-specification:
/// dynamic-exception-specification
@@ -3522,7 +3506,7 @@ Parser::tryParseExceptionSpecification(bool Delayed,
CachedTokens *&ExceptionSpecTokens) {
ExceptionSpecificationType Result = EST_None;
ExceptionSpecTokens = nullptr;
-
+
// Handle delayed parsing of exception-specifications.
if (Delayed) {
if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept))
@@ -3541,11 +3525,11 @@ Parser::tryParseExceptionSpecification(bool Delayed,
NoexceptExpr = nullptr;
return EST_BasicNoexcept;
}
-
+
Diag(Tok, diag::err_expected_lparen_after) << "throw";
return EST_DynamicNone;
}
-
+
// Cache the tokens for the exception-specification.
ExceptionSpecTokens = new CachedTokens;
ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept'
@@ -3559,7 +3543,7 @@ Parser::tryParseExceptionSpecification(bool Delayed,
return EST_Unparsed;
}
-
+
// See if there's a dynamic specification.
if (Tok.is(tok::kw_throw)) {
Result = ParseDynamicExceptionSpecification(SpecificationRange,
@@ -3585,15 +3569,11 @@ Parser::tryParseExceptionSpecification(bool Delayed,
// There is an argument.
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
- NoexceptType = EST_ComputedNoexcept;
NoexceptExpr = ParseConstantExpression();
T.consumeClose();
- // The argument must be contextually convertible to bool. We use
- // CheckBooleanCondition for this purpose.
- // FIXME: Add a proper Sema entry point for this.
if (!NoexceptExpr.isInvalid()) {
- NoexceptExpr =
- Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get());
+ NoexceptExpr = Actions.ActOnNoexceptSpec(KeywordLoc, NoexceptExpr.get(),
+ NoexceptType);
NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
} else {
NoexceptType = EST_BasicNoexcept;
@@ -3680,7 +3660,7 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
if (Tok.is(tok::ellipsis)) {
// C++0x [temp.variadic]p5:
- // - In a dynamic-exception-specification (15.4); the pattern is a
+ // - In a dynamic-exception-specification (15.4); the pattern is a
// type-id.
SourceLocation Ellipsis = ConsumeToken();
Range.setEnd(Ellipsis);
@@ -3706,15 +3686,18 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
/// ParseTrailingReturnType - Parse a trailing return type on a new-style
/// function declaration.
-TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) {
+TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,
+ bool MayBeFollowedByDirectInit) {
assert(Tok.is(tok::arrow) && "expected arrow");
ConsumeToken();
- return ParseTypeName(&Range, DeclaratorContext::TrailingReturnContext);
+ return ParseTypeName(&Range, MayBeFollowedByDirectInit
+ ? DeclaratorContext::TrailingReturnVarContext
+ : DeclaratorContext::TrailingReturnContext);
}
-/// \brief We have just started parsing the definition of a new class,
+/// We have just started parsing the definition of a new class,
/// so push that class onto our stack of classes that is currently
/// being parsed.
Sema::ParsingClassState
@@ -3726,7 +3709,7 @@ Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass,
return Actions.PushParsingClass();
}
-/// \brief Deallocate the given parsed class and all of its nested
+/// Deallocate the given parsed class and all of its nested
/// classes.
void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)
@@ -3734,7 +3717,7 @@ void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
delete Class;
}
-/// \brief Pop the top class of the stack of classes that are
+/// Pop the top class of the stack of classes that are
/// currently being parsed.
///
/// This routine should be called when we have finished parsing the
@@ -3772,7 +3755,7 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) {
Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
}
-/// \brief Try to parse an 'identifier' which appears within an attribute-token.
+/// Try to parse an 'identifier' which appears within an attribute-token.
///
/// \return the parsed identifier on success, and 0 if the next token is not an
/// attribute-token.
@@ -3820,16 +3803,15 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
IdentifierInfo *ScopeName) {
- switch (AttributeList::getKind(AttrName, ScopeName,
- AttributeList::AS_CXX11)) {
- case AttributeList::AT_CarriesDependency:
- case AttributeList::AT_Deprecated:
- case AttributeList::AT_FallThrough:
- case AttributeList::AT_CXX11NoReturn:
+ switch (ParsedAttr::getKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) {
+ case ParsedAttr::AT_CarriesDependency:
+ case ParsedAttr::AT_Deprecated:
+ case ParsedAttr::AT_FallThrough:
+ case ParsedAttr::AT_CXX11NoReturn:
return true;
- case AttributeList::AT_WarnUnusedResult:
+ case ParsedAttr::AT_WarnUnusedResult:
return !ScopeName && AttrName->getName().equals("nodiscard");
- case AttributeList::AT_Unused:
+ case ParsedAttr::AT_Unused:
return !ScopeName && AttrName->getName().equals("maybe_unused");
default:
return false;
@@ -3859,8 +3841,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
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;
+ ParsedAttr::Syntax Syntax =
+ LO.CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x;
// If the attribute isn't known, we will not attempt to parse any
// arguments.
@@ -3891,25 +3873,26 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
- const AttributeList *Attr = Attrs.getList();
- if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
+ if (!Attrs.empty() &&
+ IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
+ ParsedAttr &Attr = *Attrs.begin();
// If the attribute is a standard or built-in attribute and we are
// parsing an argument list, we need to determine whether this attribute
// was allowed to have an argument list (such as [[deprecated]]), and how
// many arguments were parsed (so we can diagnose on [[deprecated()]]).
- if (Attr->getMaxArgs() && !NumArgs) {
+ if (Attr.getMaxArgs() && !NumArgs) {
// The attribute was allowed to have arguments, but none were provided
// even though the attribute parsed successfully. This is an error.
Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
- Attr->setInvalid(true);
- } else if (!Attr->getMaxArgs()) {
+ Attr.setInvalid(true);
+ } else if (!Attr.getMaxArgs()) {
// The attribute parsed successfully, but was not allowed to have any
// arguments. It doesn't matter whether any were provided -- the
// presence of the argument list (even if empty) is diagnosed.
Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
<< AttrName
<< FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
- Attr->setInvalid(true);
+ Attr.setInvalid(true);
}
}
return true;
@@ -4028,12 +4011,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
AttrName,
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc),
ScopeName, ScopeLoc, nullptr, 0,
- getLangOpts().CPlusPlus ? AttributeList::AS_CXX11
- : AttributeList::AS_C2x);
+ getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x);
if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
- << AttrName->getName();
+ << AttrName;
}
if (ExpectAndConsume(tok::r_square))
@@ -4181,7 +4163,7 @@ void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {
if (!T.consumeClose()) {
Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr,
SourceLocation(), ArgExprs.data(), ArgExprs.size(),
- AttributeList::AS_Microsoft);
+ ParsedAttr::AS_Microsoft);
}
}
@@ -4219,12 +4201,13 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
} while (Tok.is(tok::l_square));
}
-void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
- AccessSpecifier& CurAS) {
+void Parser::ParseMicrosoftIfExistsClassDeclaration(
+ DeclSpec::TST TagType, ParsedAttributes &AccessAttrs,
+ AccessSpecifier &CurAS) {
IfExistsCondition Result;
if (ParseMicrosoftIfExistsCondition(Result))
return;
-
+
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
Diag(Tok, diag::err_expected) << tok::l_brace;
@@ -4235,13 +4218,13 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
case IEB_Parse:
// Parse the declarations below.
break;
-
+
case IEB_Dependent:
Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
<< Result.IsIfExists;
// Fall through to skip.
LLVM_FALLTHROUGH;
-
+
case IEB_Skip:
Braces.skipToEnd();
return;
@@ -4250,7 +4233,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// __if_exists, __if_not_exists can nest.
if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {
- ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
+ ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType,
+ AccessAttrs, CurAS);
continue;
}
@@ -4267,7 +4251,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
SourceLocation ASLoc = Tok.getLocation();
ConsumeToken();
if (Tok.is(tok::colon))
- Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation());
+ Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(),
+ ParsedAttributesView{});
else
Diag(Tok, diag::err_expected) << tok::colon;
ConsumeToken();
@@ -4275,8 +4260,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
}
// Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS, nullptr);
+ ParseCXXClassMemberDeclaration(CurAS, AccessAttrs);
}
-
+
Braces.consumeClose();
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
index 1b8865edb79a..2a65eec8a0f6 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides the Expression parsing implementation.
+/// Provides the Expression parsing implementation.
///
/// Expressions in C99 basically consist of a bunch of binary operators with
/// unary operators and other random stuff at the leaves.
@@ -32,7 +32,7 @@
#include "llvm/ADT/SmallVector.h"
using namespace clang;
-/// \brief Simple precedence-based parser for binary/ternary operators.
+/// Simple precedence-based parser for binary/ternary operators.
///
/// Note: we diverge from the C99 grammar when parsing the assignment-expression
/// production. C99 specifies that the LHS of an assignment operator should be
@@ -156,7 +156,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
return ParseRHSOfBinaryExpression(LHS, prec::Comma);
}
-/// \brief Parse an expr that doesn't include (top-level) commas.
+/// Parse an expr that doesn't include (top-level) commas.
ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
@@ -175,7 +175,7 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
}
-/// \brief Parse an assignment expression where part of an Objective-C message
+/// Parse an assignment expression where part of an Objective-C message
/// send has already been parsed.
///
/// In this case \p LBracLoc indicates the location of the '[' of the message
@@ -217,7 +217,15 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
return ParseConstantExpressionInExprEvalContext(isTypeCast);
}
-/// \brief Parse a constraint-expression.
+ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
+ EnterExpressionEvaluationContext ConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ return Actions.ActOnCaseExpr(CaseLoc, Res);
+}
+
+/// Parse a constraint-expression.
///
/// \verbatim
/// constraint-expression: [Concepts TS temp.constr.decl p1]
@@ -246,30 +254,6 @@ bool Parser::isNotExpressionStart() {
return isKnownToBeDeclarationSpecifier();
}
-/// We've parsed something that could plausibly be intended to be a template
-/// name (\p LHS) followed by a '<' token, and the following code can't possibly
-/// be an expression. Determine if this is likely to be a template-id and if so,
-/// diagnose it.
-bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) {
- TentativeParsingAction TPA(*this);
- // FIXME: We could look at the token sequence in a lot more detail here.
- if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater,
- StopAtSemi | StopBeforeMatch)) {
- TPA.Commit();
-
- SourceLocation Greater;
- ParseGreaterThanInTemplateList(Greater, true, false);
- Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS,
- Less, Greater);
- return true;
- }
-
- // There's no matching '>' token, this probably isn't supposed to be
- // interpreted as a template-id. Parse it as an (ill-formed) comparison.
- TPA.Revert();
- return false;
-}
-
bool Parser::isFoldOperator(prec::Level Level) const {
return Level > prec::Unknown && Level != prec::Conditional &&
Level != prec::Spaceship;
@@ -279,7 +263,7 @@ 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
+/// Parse a binary expression that starts with \p LHS and has a
/// precedence of at least \p MinPrec.
ExprResult
Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
@@ -302,6 +286,14 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
if (OpToken.is(tok::caretcaret)) {
return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or));
}
+
+ // If we're potentially in a template-id, we may now be able to determine
+ // whether we're actually in one or not.
+ if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater,
+ tok::greatergreatergreater) &&
+ checkPotentialAngleBracketDelimiter(OpToken))
+ return ExprError();
+
// Bail out when encountering a comma followed by a token which can't
// possibly be the start of an expression. For instance:
// int f() { return 1, }
@@ -313,16 +305,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
return LHS;
}
- // If a '<' token is followed by a type that can be a template argument and
- // cannot be an expression, then this is ill-formed, but might be intended
- // to be a template-id.
- if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) &&
- (isKnownToBeDeclarationSpecifier() ||
- Tok.isOneOf(tok::greater, tok::greatergreater,
- tok::greatergreatergreater)) &&
- diagnoseUnknownTemplateId(LHS, OpToken.getLocation()))
- return ExprError();
-
// If the next token is an ellipsis, then this is a fold-expression. Leave
// it alone so we can handle it in the paren expression.
if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) {
@@ -336,7 +318,17 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// Special case handling for the ternary operator.
ExprResult TernaryMiddle(true);
if (NextTokPrec == prec::Conditional) {
- if (Tok.isNot(tok::colon)) {
+ if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
+ // Parse a braced-init-list here for error recovery purposes.
+ SourceLocation BraceLoc = Tok.getLocation();
+ TernaryMiddle = ParseBraceInitializer();
+ if (!TernaryMiddle.isInvalid()) {
+ Diag(BraceLoc, diag::err_init_list_bin_op)
+ << /*RHS*/ 1 << PP.getSpelling(OpToken)
+ << Actions.getExprRange(TernaryMiddle.get());
+ TernaryMiddle = ExprError();
+ }
+ } else if (Tok.isNot(tok::colon)) {
// Don't parse FOO:BAR as if it were a typo for FOO::BAR.
ColonProtectionRAIIObject X(*this);
@@ -345,11 +337,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// In particular, the RHS of the '?' is 'expression', not
// 'logical-OR-expression' as we might expect.
TernaryMiddle = ParseExpression();
- if (TernaryMiddle.isInvalid()) {
- Actions.CorrectDelayedTyposInExpr(LHS);
- LHS = ExprError();
- TernaryMiddle = nullptr;
- }
} else {
// Special case handling of "X ? Y : Z" where Y is empty:
// logical-OR-expression '?' ':' conditional-expression [GNU]
@@ -357,6 +344,12 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
Diag(Tok, diag::ext_gnu_conditional_expr);
}
+ if (TernaryMiddle.isInvalid()) {
+ Actions.CorrectDelayedTyposInExpr(LHS);
+ LHS = ExprError();
+ TernaryMiddle = nullptr;
+ }
+
if (!TryConsumeToken(tok::colon, ColonLoc)) {
// Otherwise, we're missing a ':'. Assume that this was a typo that
// the user forgot. If we're not in a macro expansion, we can suggest
@@ -448,7 +441,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// is okay, to bind exactly as tightly. For example, compile A=B=C=D as
// A=(B=(C=D)), where each paren is a level of recursion here.
// The function takes ownership of the RHS.
- RHS = ParseRHSOfBinaryExpression(RHS,
+ RHS = ParseRHSOfBinaryExpression(RHS,
static_cast<prec::Level>(ThisPrec + !isRightAssoc));
RHSIsInitList = false;
@@ -469,6 +462,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
if (ThisPrec == prec::Assignment) {
Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists)
<< Actions.getExprRange(RHS.get());
+ } else if (ColonLoc.isValid()) {
+ Diag(ColonLoc, diag::err_init_list_bin_op)
+ << /*RHS*/1 << ":"
+ << Actions.getExprRange(RHS.get());
+ LHS = ExprError();
} else {
Diag(OpToken, diag::err_init_list_bin_op)
<< /*RHS*/1 << PP.getSpelling(OpToken)
@@ -513,7 +511,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
}
}
-/// \brief Parse a cast-expression, or, if \p isUnaryExpression is true,
+/// Parse a cast-expression, or, if \p isUnaryExpression is true,
/// parse a unary-expression.
///
/// \p isAddressOfOperand exists because an id-expression that is the
@@ -570,7 +568,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
};
}
-/// \brief Parse a cast-expression, or, if \pisUnaryExpression is true, parse
+/// Parse a cast-expression, or, if \pisUnaryExpression is true, parse
/// a unary-expression.
///
/// \p isAddressOfOperand exists because an id-expression that is the operand
@@ -619,6 +617,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// [GNU] '__FUNCTION__'
/// [MS] '__FUNCDNAME__'
/// [MS] 'L__FUNCTION__'
+/// [MS] '__FUNCSIG__'
+/// [MS] 'L__FUNCSIG__'
/// [GNU] '__PRETTY_FUNCTION__'
/// [GNU] '(' compound-statement ')'
/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
@@ -656,14 +656,14 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
///
/// id-expression: [C++ 5.1]
/// unqualified-id
-/// qualified-id
+/// qualified-id
///
/// unqualified-id: [C++ 5.1]
/// identifier
/// operator-function-id
/// conversion-function-id
-/// '~' class-name
-/// template-id
+/// '~' class-name
+/// template-id
///
/// new-expression: [C++ 5.3.4]
/// '::'[opt] 'new' new-placement[opt] new-type-id
@@ -729,7 +729,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// '__trivially_copyable'
///
/// binary-type-trait:
-/// [GNU] '__is_base_of'
+/// [GNU] '__is_base_of'
/// [MS] '__is_convertible_to'
/// '__is_convertible'
/// '__is_same'
@@ -789,6 +789,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// We have parsed the cast-expression and no postfix-expr pieces are
// following.
return Res;
+ case FoldExpr:
+ // We only parsed a fold-expression. There might be postfix-expr pieces
+ // afterwards; parse them now.
+ break;
}
break;
@@ -807,7 +811,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_false:
Res = ParseCXXBoolLiteral();
break;
-
+
case tok::kw___objc_yes:
case tok::kw___objc_no:
return ParseObjCBoolLiteral();
@@ -820,6 +824,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
assert(Res.get() == nullptr && "Stray primary-expression annotation?");
Res = getExprAnnotation(Tok);
ConsumeAnnotationToken();
+ if (!Res.isInvalid() && Tok.is(tok::less))
+ checkPotentialAngleBracket(Res);
break;
case tok::kw___super:
@@ -829,7 +835,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
-
+
case tok::identifier: { // primary-expression: identifier
// unqualified-id: identifier
// constant: enumeration-constant
@@ -951,14 +957,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
}
// Allow either an identifier or the keyword 'class' (in C++).
- if (Tok.isNot(tok::identifier) &&
+ if (Tok.isNot(tok::identifier) &&
!(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) {
Diag(Tok, diag::err_expected_property_name);
return ExprError();
}
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
SourceLocation PropertyLoc = ConsumeToken();
-
+
Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
ILoc, PropertyLoc);
break;
@@ -967,7 +973,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// In an Objective-C method, if we have "super" followed by an identifier,
// the token sequence is ill-formed. However, if there's a ':' or ']' after
// that identifier, this is probably a message send with a missing open
- // bracket. Treat it as such.
+ // bracket. Treat it as such.
if (getLangOpts().ObjC1 && &II == Ident_super && !InMessageExpression &&
getCurScope()->isInObjcMethodScope() &&
((Tok.is(tok::identifier) &&
@@ -977,17 +983,17 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
nullptr);
break;
}
-
+
// If we have an Objective-C class name followed by an identifier
// and either ':' or ']', this is an Objective-C class message
// send that's missing the opening '['. Recovery
// appropriately. Also take this path if we're performing code
// completion after an Objective-C class name.
- if (getLangOpts().ObjC1 &&
- ((Tok.is(tok::identifier) && !InMessageExpression) ||
+ if (getLangOpts().ObjC1 &&
+ ((Tok.is(tok::identifier) && !InMessageExpression) ||
Tok.is(tok::code_completion))) {
const Token& Next = NextToken();
- if (Tok.is(tok::code_completion) ||
+ if (Tok.is(tok::code_completion) ||
Next.is(tok::colon) || Next.is(tok::r_square))
if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))
if (Typ.get()->isObjCObjectOrInterfaceType()) {
@@ -999,24 +1005,24 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
Actions.getASTContext().getPrintingPolicy());
-
+
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
- TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
DeclaratorInfo);
if (Ty.isInvalid())
break;
- Res = ParseObjCMessageExpressionBody(SourceLocation(),
- SourceLocation(),
+ Res = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
Ty.get(), nullptr);
break;
}
}
-
+
// Make sure to pass down the right value for isAddressOfOperand.
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
isAddressOfOperand = false;
-
+
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
// not.
@@ -1039,11 +1045,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
isAddressOfOperand, std::move(Validator),
/*IsInlineAsmIdentifier=*/false,
Tok.is(tok::r_paren) ? nullptr : &Replacement);
- if (!Res.isInvalid() && !Res.get()) {
+ if (!Res.isInvalid() && Res.isUnset()) {
UnconsumeToken(Replacement);
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, isTypeCast);
}
+ if (!Res.isInvalid() && Tok.is(tok::less))
+ checkPotentialAngleBracket(Res);
break;
}
case tok::char_constant: // constant: character-constant
@@ -1059,6 +1067,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]
case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
+ case tok::kw_L__FUNCSIG__: // primary-expression: L__FUNCSIG__ [MS]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
ConsumeToken();
@@ -1170,7 +1179,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (getCurScope()->getFnParent() == nullptr)
return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
-
+
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
Tok.getLocation());
@@ -1224,6 +1233,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::annot_decltype:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_bool:
@@ -1374,7 +1384,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
T.consumeClose();
if (!Result.isInvalid())
- Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
+ Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
Result.get(), T.getCloseLocation());
return Result;
}
@@ -1383,7 +1393,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def"
return ParseTypeTrait();
-
+
case tok::kw___array_rank:
case tok::kw___array_extent:
return ParseArrayTypeTrait();
@@ -1391,7 +1401,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___is_lvalue_expr:
case tok::kw___is_rvalue_expr:
return ParseExpressionTrait();
-
+
case tok::at: {
SourceLocation AtLoc = ConsumeToken();
return ParseObjCAtExpression(AtLoc);
@@ -1449,7 +1459,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return Res;
}
-/// \brief Once the leading part of a postfix-expression is parsed, this
+/// Once the leading part of a postfix-expression is parsed, this
/// method parses any suffixes that apply.
///
/// \verbatim
@@ -1479,16 +1489,16 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
case tok::code_completion:
if (InMessageExpression)
return LHS;
-
+
Actions.CodeCompletePostfixExpression(getCurScope(), LHS);
cutOffParsing();
return ExprError();
-
+
case tok::identifier:
// If we see identifier: after an expression, and we're not already in a
// message send, then this is probably a message send with a missing
// opening bracket '['.
- if (getLangOpts().ObjC1 && !InMessageExpression &&
+ if (getLangOpts().ObjC1 && !InMessageExpression &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
nullptr, LHS.get());
@@ -1610,8 +1620,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (!LHS.isInvalid()) {
ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
- OpenLoc,
- ExecConfigExprs,
+ OpenLoc,
+ ExecConfigExprs,
CloseLoc);
if (ECResult.isInvalid())
LHS = ExprError();
@@ -1625,7 +1635,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
-
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCall(getCurScope(), LHS.get(), None);
cutOffParsing();
@@ -1665,7 +1675,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
PT.consumeClose();
LHS = ExprError();
} else {
- assert((ArgExprs.size() == 0 ||
+ assert((ArgExprs.size() == 0 ||
ArgExprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc,
@@ -1686,8 +1696,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
CXXScopeSpec SS;
ParsedType ObjectType;
bool MayBePseudoDestructor = false;
+ Expr* OrigLHS = !LHS.isInvalid() ? LHS.get() : nullptr;
+
if (getLangOpts().CPlusPlus && !LHS.isInvalid()) {
- Expr *Base = LHS.get();
+ Expr *Base = OrigLHS;
const Type* BaseType = Base->getType().getTypePtrOrNull();
if (BaseType && Tok.is(tok::l_paren) &&
(BaseType->isFunctionType() ||
@@ -1704,7 +1716,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType,
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType,
/*EnteringContext=*/false,
&MayBePseudoDestructor);
if (SS.isNotEmpty())
@@ -1712,18 +1724,32 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (Tok.is(tok::code_completion)) {
+ tok::TokenKind CorrectedOpKind =
+ OpKind == tok::arrow ? tok::period : tok::arrow;
+ ExprResult CorrectedLHS(/*IsInvalid=*/true);
+ if (getLangOpts().CPlusPlus && OrigLHS) {
+ const bool DiagsAreSuppressed = Diags.getSuppressAllDiagnostics();
+ Diags.setSuppressAllDiagnostics(true);
+ CorrectedLHS = Actions.ActOnStartCXXMemberReference(
+ getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType,
+ MayBePseudoDestructor);
+ Diags.setSuppressAllDiagnostics(DiagsAreSuppressed);
+ }
+
+ Expr *Base = LHS.get();
+ Expr *CorrectedBase = CorrectedLHS.get();
+
// Code completion for a member access expression.
- if (Expr *Base = LHS.get())
- Actions.CodeCompleteMemberReferenceExpr(
- getCurScope(), Base, OpLoc, OpKind == tok::arrow,
- ExprStatementTokLoc == Base->getLocStart());
+ Actions.CodeCompleteMemberReferenceExpr(
+ getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,
+ Base && ExprStatementTokLoc == Base->getLocStart());
cutOffParsing();
return ExprError();
}
if (MayBePseudoDestructor && !LHS.isInvalid()) {
- LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
+ LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
ObjectType);
break;
}
@@ -1744,27 +1770,29 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// 'class' as if it were an identifier.
//
// This hack allows property access to the 'class' method because it is
- // such a common method name. For other C++ keywords that are
+ // such a common method name. For other C++ keywords that are
// Objective-C method names, one must use the message send syntax.
IdentifierInfo *Id = Tok.getIdentifierInfo();
SourceLocation Loc = ConsumeToken();
Name.setIdentifier(Id, Loc);
- } else if (ParseUnqualifiedId(SS,
- /*EnteringContext=*/false,
+ } else if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/
- getLangOpts().MicrosoftExt,
+ getLangOpts().MicrosoftExt,
/*AllowDeductionGuide=*/false,
- ObjectType, TemplateKWLoc, Name)) {
+ ObjectType, &TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
-
+
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
+ LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
: nullptr);
+ if (!LHS.isInvalid() && Tok.is(tok::less))
+ checkPotentialAngleBracket(LHS);
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
@@ -1854,7 +1882,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
- Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
+ Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
false, CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
@@ -1868,7 +1896,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
// GNU typeof in C requires the expression to be parenthesized. Not so for
// sizeof/alignof or in C++. Therefore, the parenthesized expression is
- // the start of a unary-expression, but doesn't include any postfix
+ // the start of a unary-expression, but doesn't include any postfix
// pieces. Parse these now if present.
if (!Operand.isInvalid())
Operand = ParsePostfixExpressionSuffix(Operand.get());
@@ -1881,7 +1909,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
}
-/// \brief Parse a sizeof or alignof expression.
+/// Parse a sizeof or alignof expression.
///
/// \verbatim
/// unary-expression: [C99 6.5.3]
@@ -1934,7 +1962,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
} else {
Diag(Tok, diag::err_sizeof_parameter_pack);
}
-
+
if (!Name)
return ExprError();
@@ -1943,7 +1971,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
Sema::ReuseLambdaContextDecl);
return Actions.ActOnSizeofParameterPackExpr(getCurScope(),
- OpTok.getLocation(),
+ OpTok.getLocation(),
*Name, NameLoc,
RParenLoc);
}
@@ -2178,15 +2206,15 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
return ExprError();
-
+
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,
+
+ Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,
ConsumeParen());
break;
}
@@ -2207,15 +2235,15 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
return ExprError();
-
+
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,
+
+ Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,
ConsumeParen());
break;
}
@@ -2270,7 +2298,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
CastTy = nullptr;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(),
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression
: Sema::PCC_Expression);
cutOffParsing();
@@ -2294,7 +2322,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
}
BridgeCast = false;
}
-
+
// None of these cases should fall through with an invalid Result
// unless they've already reported an error.
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
@@ -2348,16 +2376,16 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
<< FixItHint::CreateReplacement(BridgeKeywordLoc,
"__bridge_retained");
}
-
+
TypeResult Ty = ParseTypeName();
T.consumeClose();
ColonProtection.restore();
RParenLoc = T.getCloseLocation();
ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
-
+
if (Ty.isInvalid() || SubExpr.isInvalid())
return ExprError();
-
+
return Actions.ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind,
BridgeKeywordLoc, Ty.get(),
RParenLoc, SubExpr.get());
@@ -2383,8 +2411,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
-
- // If our type is followed by an identifier and either ':' or ']', then
+
+ // If our type is followed by an identifier and either ':' or ']', then
// this is probably an Objective-C message send where the leading '[' is
// missing. Recover as if that were the case.
if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&
@@ -2395,10 +2423,10 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
InMessageExpressionRAIIObject InMessage(*this, false);
Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
- Result = ParseObjCMessageExpressionBody(SourceLocation(),
- SourceLocation(),
+ Result = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
Ty.get(), nullptr);
- } else {
+ } else {
// Match the ')'.
T.consumeClose();
ColonProtection.restore();
@@ -2475,7 +2503,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Reject the cast of super idiom in ObjC.
if (Tok.is(tok::identifier) && getLangOpts().ObjC1 &&
- Tok.getIdentifierInfo() == Ident_super &&
+ Tok.getIdentifierInfo() == Ident_super &&
getCurScope()->isInObjcMethodScope() &&
GetLookAheadToken(1).isNot(tok::period)) {
Diag(Tok.getLocation(), diag::err_illegal_super_cast)
@@ -2490,7 +2518,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
/*isTypeCast=*/IsTypeCast);
if (!Result.isInvalid()) {
Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
- DeclaratorInfo, CastTy,
+ DeclaratorInfo, CastTy,
RParenLoc, Result.get());
}
return Result;
@@ -2499,8 +2527,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
return ExprError();
}
- } else if (Tok.is(tok::ellipsis) &&
+ } else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
isFoldOperator(NextToken().getKind())) {
+ ExprType = FoldExpr;
return ParseFoldExpression(ExprResult(), T);
} else if (isTypeCast) {
// Parse the expression-list.
@@ -2512,9 +2541,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
// FIXME: If we ever support comma expressions as operands to
// fold-expressions, we'll need to allow multiple ArgExprs here.
- if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
- NextToken().is(tok::ellipsis))
+ if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&
+ isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+ ExprType = FoldExpr;
return ParseFoldExpression(ArgExprs[0], T);
+ }
ExprType = SimpleExpr;
Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2529,10 +2560,13 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// expressions are parsed correctly.
Result = Actions.CorrectDelayedTyposInExpr(Result);
}
- ExprType = SimpleExpr;
- if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+ if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
+ NextToken().is(tok::ellipsis)) {
+ ExprType = FoldExpr;
return ParseFoldExpression(Result, T);
+ }
+ ExprType = SimpleExpr;
// Don't build a paren expression unless we actually match a ')'.
if (!Result.isInvalid() && Tok.is(tok::r_paren))
@@ -2688,13 +2722,13 @@ ExprResult Parser::ParseGenericSelectionExpression() {
if (T.getCloseLocation().isInvalid())
return ExprError();
- return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
+ return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
T.getCloseLocation(),
ControllingExpr.get(),
Types, Exprs);
}
-/// \brief Parse A C++1z fold-expression after the opening paren and optional
+/// Parse A C++1z fold-expression after the opening paren and optional
/// left-hand-side expression.
///
/// \verbatim
@@ -2791,7 +2825,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
Expr = ParseAssignmentExpression();
if (Tok.is(tok::ellipsis))
- Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
+ Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
if (Expr.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch);
SawError = true;
@@ -2802,7 +2836,10 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
if (Tok.isNot(tok::comma))
break;
// Move to the next argument, remember where the comma was.
+ Token Comma = Tok;
CommaLocs.push_back(ConsumeToken());
+
+ checkPotentialAngleBracketDelimiter(Comma);
}
if (SawError) {
// Ensure typos get diagnosed when errors were encountered while parsing the
@@ -2837,7 +2874,10 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
return false;
// Move to the next argument, remember where the comma was.
+ Token Comma = Tok;
CommaLocs.push_back(ConsumeToken());
+
+ checkPotentialAngleBracketDelimiter(Comma);
}
}
@@ -2852,7 +2892,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
return cutOffParsing();
}
-
+
// Parse the specifier-qualifier-list piece.
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
@@ -2929,33 +2969,31 @@ ExprResult Parser::ParseBlockLiteralExpression() {
ParseBlockId(CaretLoc);
} else {
// Otherwise, pretend we saw (void).
- ParsedAttributes attrs(AttrFactory);
SourceLocation NoLoc;
- ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true,
- /*IsAmbiguous=*/false,
- /*RParenLoc=*/NoLoc,
- /*ArgInfo=*/nullptr,
- /*NumArgs=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc,
- EST_None,
- /*ESpecRange=*/SourceRange(),
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- /*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- CaretLoc, CaretLoc,
- ParamInfo),
- attrs, CaretLoc);
+ ParamInfo.AddTypeInfo(
+ DeclaratorChunk::getFunction(/*HasProto=*/true,
+ /*IsAmbiguous=*/false,
+ /*RParenLoc=*/NoLoc,
+ /*ArgInfo=*/nullptr,
+ /*NumArgs=*/0,
+ /*EllipsisLoc=*/NoLoc,
+ /*RParenLoc=*/NoLoc,
+ /*TypeQuals=*/0,
+ /*RefQualifierIsLvalueRef=*/true,
+ /*RefQualifierLoc=*/NoLoc,
+ /*ConstQualifierLoc=*/NoLoc,
+ /*VolatileQualifierLoc=*/NoLoc,
+ /*RestrictQualifierLoc=*/NoLoc,
+ /*MutableLoc=*/NoLoc, EST_None,
+ /*ESpecRange=*/SourceRange(),
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
+ /*NumExceptions=*/0,
+ /*NoexceptExpr=*/nullptr,
+ /*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None, CaretLoc,
+ CaretLoc, ParamInfo),
+ CaretLoc);
MaybeParseGNUAttributes(ParamInfo);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index 554ab24b02e1..663c397ee049 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -100,7 +100,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
/*AtDigraph*/false);
}
-/// \brief Parse global scope or nested-name-specifier if present.
+/// Parse global scope or nested-name-specifier if present.
///
/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
/// may be preceded by '::'). Note that this routine will not parse ::new or
@@ -306,13 +306,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
}
// If the next token is not '<', we have a qualified-id that refers
- // to a template name, such as T::template apply, but is not a
+ // to a template name, such as T::template apply, but is not a
// template-id.
if (Tok.isNot(tok::less)) {
TPA.Revert();
break;
- }
-
+ }
+
// Commit to parsing the template-id.
TPA.Commit();
TemplateTy Template;
@@ -366,7 +366,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TemplateId->RAngleLoc,
CCLoc,
EnteringContext)) {
- SourceLocation StartLoc
+ SourceLocation StartLoc
= SS.getBeginLoc().isValid()? SS.getBeginLoc()
: TemplateId->TemplateNameLoc;
SS.SetInvalid(SourceRange(StartLoc, CCLoc));
@@ -480,7 +480,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&II, Tok.getLocation());
bool MemberOfUnknownSpecialization;
- if (TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
+ if (TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
/*hasTemplateKeyword=*/false,
TemplateName,
ObjectType,
@@ -500,22 +500,22 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
continue;
}
- if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&
+ if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&
(IsTypename || IsTemplateArgumentList(1))) {
- // We have something like t::getAs<T>, where getAs is a
+ // We have something like t::getAs<T>, where getAs is a
// member of an unknown specialization. However, this will only
// parse correctly as a template, so suggest the keyword 'template'
// before 'getAs' and treat this as a dependent template name.
unsigned DiagID = diag::err_missing_dependent_template_keyword;
if (getLangOpts().MicrosoftExt)
DiagID = diag::warn_missing_dependent_template_keyword;
-
+
Diag(Tok.getLocation(), DiagID)
<< II.getName()
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(
- getCurScope(), SS, SourceLocation(), TemplateName, ObjectType,
+ getCurScope(), SS, Tok.getLocation(), TemplateName, ObjectType,
EnteringContext, Template, /*AllowInjectedClassName*/ true)) {
// Consume the identifier.
ConsumeToken();
@@ -524,9 +524,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
return true;
}
else
- return true;
-
- continue;
+ return true;
+
+ continue;
}
}
@@ -553,7 +553,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
/*AllowDeductionGuide=*/false,
- /*ObjectType=*/nullptr, TemplateKWLoc, Name))
+ /*ObjectType=*/nullptr, &TemplateKWLoc, Name))
return ExprError();
// This is only the direct operand of an & operator if it is not
@@ -561,10 +561,13 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
isAddressOfOperand = false;
- return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name,
- Tok.is(tok::l_paren), isAddressOfOperand,
- nullptr, /*IsInlineAsmIdentifier=*/false,
- &Replacement);
+ ExprResult E = Actions.ActOnIdExpression(
+ getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren),
+ isAddressOfOperand, nullptr, /*IsInlineAsmIdentifier=*/false,
+ &Replacement);
+ if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less))
+ checkPotentialAngleBracket(E);
+ return E;
}
/// ParseCXXIdExpression - Handle id-expression.
@@ -716,7 +719,7 @@ ExprResult Parser::TryParseLambdaExpression() {
if (Next.is(tok::identifier) && After.is(tok::identifier)) {
return ExprEmpty();
}
-
+
// Here, we're stuck: lambda introducers and Objective-C message sends are
// unambiguous, but it requires arbitrary lookhead. [a,b,c,d,e,f,g] is a
// lambda, and [a,b,c,d,e,f,g h] is a Objective-C message send. Instead of
@@ -730,7 +733,7 @@ ExprResult Parser::TryParseLambdaExpression() {
return ParseLambdaExpressionAfterIntroducer(Intro);
}
-/// \brief Parse a lambda introducer.
+/// Parse a lambda introducer.
/// \param Intro A LambdaIntroducer filled in with information about the
/// contents of the lambda-introducer.
/// \param SkippedInits If non-null, we are disambiguating between an Obj-C
@@ -773,7 +776,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
if (Tok.is(tok::code_completion) &&
!(getLangOpts().ObjC1 && Intro.Default == LCD_None &&
!Intro.Captures.empty())) {
- Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
+ Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
cutOffParsing();
break;
@@ -790,14 +793,14 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
if (getLangOpts().ObjC1 && first)
Actions.CodeCompleteObjCMessageReceiver(getCurScope());
else
- Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
+ Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
cutOffParsing();
break;
}
first = false;
-
+
// Parse capture.
LambdaCaptureKind Kind = LCK_ByCopy;
LambdaCaptureInitKind InitKind = LambdaCaptureInitKind::NoInit;
@@ -805,12 +808,13 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
IdentifierInfo *Id = nullptr;
SourceLocation EllipsisLoc;
ExprResult Init;
+ SourceLocation LocStart = Tok.getLocation();
if (Tok.is(tok::star)) {
- Loc = ConsumeToken();
+ Loc = ConsumeToken();
if (Tok.is(tok::kw_this)) {
- ConsumeToken();
- Kind = LCK_StarThis;
+ ConsumeToken();
+ Kind = LCK_StarThis;
} else {
return DiagResult(diag::err_expected_star_this_capture);
}
@@ -823,7 +827,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
ConsumeToken();
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
+ Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/true);
cutOffParsing();
break;
@@ -978,8 +982,11 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
Loc, Kind == LCK_ByRef, Id, InitKind, InitExpr);
Init = InitExpr;
}
+
+ SourceLocation LocEnd = PrevTokLocation;
+
Intro.addCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
- InitCaptureType);
+ InitCaptureType, SourceRange(LocStart, LocEnd));
}
T.consumeClose();
@@ -1083,7 +1090,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
"lambda expression parsing");
-
+
// FIXME: Call into Actions to add any init-capture declarations to the
// scope while parsing the lambda-declarator and compound-statement.
@@ -1106,12 +1113,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// after '(...)'. nvcc doesn't accept this.
auto WarnIfHasCUDATargetAttr = [&] {
if (getLangOpts().CUDA)
- for (auto *A = Attr.getList(); A != nullptr; A = A->getNext())
- if (A->getKind() == AttributeList::AT_CUDADevice ||
- A->getKind() == AttributeList::AT_CUDAHost ||
- A->getKind() == AttributeList::AT_CUDAGlobal)
- Diag(A->getLoc(), diag::warn_cuda_attr_lambda_position)
- << A->getName()->getName();
+ for (const ParsedAttr &A : Attr)
+ if (A.getKind() == ParsedAttr::AT_CUDADevice ||
+ A.getKind() == ParsedAttr::AT_CUDAHost ||
+ A.getKind() == ParsedAttr::AT_CUDAGlobal)
+ Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position)
+ << A.getName()->getName();
};
TypeResult TrailingReturnType;
@@ -1128,13 +1135,13 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// Parse parameter-declaration-clause.
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
SourceLocation EllipsisLoc;
-
+
if (Tok.isNot(tok::r_paren)) {
Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
- // For a generic lambda, each 'auto' within the parameter declaration
+ // For a generic lambda, each 'auto' within the parameter declaration
// clause creates a template type parameter, so increment the depth.
- if (Actions.getCurGenericLambda())
+ if (Actions.getCurGenericLambda())
++CurTemplateDepthTracker;
}
T.consumeClose();
@@ -1154,7 +1161,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
SourceLocation ConstexprLoc;
tryConsumeMutableOrConstexprToken(*this, MutableLoc, ConstexprLoc,
DeclEndLoc);
-
+
addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
// Parse exception-specification[opt].
@@ -1183,7 +1190,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
if (Tok.is(tok::arrow)) {
FunLocalRangeEnd = Tok.getLocation();
SourceRange Range;
- TrailingReturnType = ParseTrailingReturnType(Range);
+ TrailingReturnType =
+ ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
if (Range.getEnd().isValid())
DeclEndLoc = Range.getEnd();
}
@@ -1193,29 +1201,23 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
WarnIfHasCUDATargetAttr();
SourceLocation NoLoc;
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
- /*isAmbiguous=*/false,
- LParenLoc,
- ParamInfo.data(), ParamInfo.size(),
- EllipsisLoc, RParenLoc,
- DS.getTypeQualifiers(),
- /*RefQualifierIsLValueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
- MutableLoc,
- ESpecType, ESpecRange,
- DynamicExceptions.data(),
- DynamicExceptionRanges.data(),
- DynamicExceptions.size(),
- NoexceptExpr.isUsable() ?
- NoexceptExpr.get() : nullptr,
- /*ExceptionSpecTokens*/nullptr,
- /*DeclsInPrototype=*/None,
- LParenLoc, FunLocalRangeEnd, D,
- TrailingReturnType),
- Attr, DeclEndLoc);
+ D.AddTypeInfo(DeclaratorChunk::getFunction(
+ /*hasProto=*/true,
+ /*isAmbiguous=*/false, LParenLoc, ParamInfo.data(),
+ ParamInfo.size(), EllipsisLoc, RParenLoc,
+ DS.getTypeQualifiers(),
+ /*RefQualifierIsLValueRef=*/true,
+ /*RefQualifierLoc=*/NoLoc,
+ /*ConstQualifierLoc=*/NoLoc,
+ /*VolatileQualifierLoc=*/NoLoc,
+ /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType,
+ ESpecRange, DynamicExceptions.data(),
+ DynamicExceptionRanges.data(), DynamicExceptions.size(),
+ NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
+ /*ExceptionSpecTokens*/ nullptr,
+ /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
+ TrailingReturnType),
+ std::move(Attr), DeclEndLoc);
} else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
tok::kw_constexpr) ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
@@ -1253,7 +1255,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// Parse the return type, if there is one.
if (Tok.is(tok::arrow)) {
SourceRange Range;
- TrailingReturnType = ParseTrailingReturnType(Range);
+ TrailingReturnType =
+ ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
if (Range.getEnd().isValid())
DeclEndLoc = Range.getEnd();
}
@@ -1261,31 +1264,29 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
WarnIfHasCUDATargetAttr();
SourceLocation NoLoc;
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
- /*isAmbiguous=*/false,
- /*LParenLoc=*/NoLoc,
- /*Params=*/nullptr,
- /*NumParams=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
- /*RefQualifierIsLValueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
- MutableLoc,
- EST_None,
- /*ESpecRange=*/SourceRange(),
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- /*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- DeclLoc, DeclEndLoc, D,
- TrailingReturnType),
- Attr, DeclEndLoc);
+ D.AddTypeInfo(DeclaratorChunk::getFunction(
+ /*hasProto=*/true,
+ /*isAmbiguous=*/false,
+ /*LParenLoc=*/NoLoc,
+ /*Params=*/nullptr,
+ /*NumParams=*/0,
+ /*EllipsisLoc=*/NoLoc,
+ /*RParenLoc=*/NoLoc,
+ /*TypeQuals=*/0,
+ /*RefQualifierIsLValueRef=*/true,
+ /*RefQualifierLoc=*/NoLoc,
+ /*ConstQualifierLoc=*/NoLoc,
+ /*VolatileQualifierLoc=*/NoLoc,
+ /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None,
+ /*ESpecRange=*/SourceRange(),
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
+ /*NumExceptions=*/0,
+ /*NoexceptExpr=*/nullptr,
+ /*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D,
+ TrailingReturnType),
+ std::move(Attr), DeclEndLoc);
}
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
@@ -1375,7 +1376,7 @@ ExprResult Parser::ParseCXXCasts() {
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
LAngleBracketLoc, DeclaratorInfo,
RAngleBracketLoc,
- T.getOpenLocation(), Result.get(),
+ T.getOpenLocation(), Result.get(),
T.getCloseLocation());
return Result;
@@ -1476,7 +1477,7 @@ ExprResult Parser::ParseCXXUuidof() {
return ExprError();
Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(), /*isType=*/true,
- Ty.get().getAsOpaquePtr(),
+ Ty.get().getAsOpaquePtr(),
T.getCloseLocation());
} else {
EnterExpressionEvaluationContext Unevaluated(
@@ -1498,7 +1499,7 @@ ExprResult Parser::ParseCXXUuidof() {
return Result;
}
-/// \brief Parse a C++ pseudo-destructor expression after the base,
+/// Parse a C++ pseudo-destructor expression after the base,
/// . or -> operator, and nested-name-specifier have already been
/// parsed.
///
@@ -1506,13 +1507,13 @@ ExprResult Parser::ParseCXXUuidof() {
/// postfix-expression . pseudo-destructor-name
/// postfix-expression -> pseudo-destructor-name
///
-/// pseudo-destructor-name:
-/// ::[opt] nested-name-specifier[opt] type-name :: ~type-name
-/// ::[opt] nested-name-specifier template simple-template-id ::
-/// ~type-name
+/// pseudo-destructor-name:
+/// ::[opt] nested-name-specifier[opt] type-name :: ~type-name
+/// ::[opt] nested-name-specifier template simple-template-id ::
+/// ~type-name
/// ::[opt] nested-name-specifier[opt] ~type-name
-///
-ExprResult
+///
+ExprResult
Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
@@ -1561,13 +1562,13 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
Diag(Tok, diag::err_destructor_tilde_identifier);
return ExprError();
}
-
+
// Parse the second type.
UnqualifiedId SecondTypeName;
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = ConsumeToken();
SecondTypeName.setIdentifier(Name, NameLoc);
-
+
// If there is a '<', the second type name is a template-id. Parse
// it as such.
if (Tok.is(tok::less) &&
@@ -1619,7 +1620,7 @@ ExprResult Parser::ParseThrowExpression() {
}
}
-/// \brief Parse the C++ Coroutines co_yield expression.
+/// Parse the C++ Coroutines co_yield expression.
///
/// co_yield-expression:
/// 'co_yield' assignment-expression[opt]
@@ -1672,9 +1673,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
if (Init.isInvalid())
return Init;
Expr *InitList = Init.get();
- return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(),
- MultiExprArg(&InitList, 1),
- SourceLocation());
+ return Actions.ActOnCXXTypeConstructExpr(
+ TypeRep, InitList->getLocStart(), MultiExprArg(&InitList, 1),
+ InitList->getLocEnd(), /*ListInitialization=*/true);
} else {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -1702,9 +1703,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
- return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(),
- Exprs,
- T.getCloseLocation());
+ return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(),
+ Exprs, T.getCloseLocation(),
+ /*ListInitialization=*/false);
}
}
@@ -1733,6 +1734,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
Sema::ConditionKind CK) {
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
cutOffParsing();
@@ -1742,17 +1745,34 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
+ const auto WarnOnInit = [this, &CK] {
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+ ? diag::warn_cxx14_compat_init_statement
+ : diag::ext_init_statement)
+ << (CK == Sema::ConditionKind::Switch);
+ };
+
// Determine what kind of thing we have.
switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) {
case ConditionOrInitStatement::Expression: {
ProhibitAttributes(attrs);
+ // We can have an empty expression here.
+ // if (; true);
+ if (InitStmt && Tok.is(tok::semi)) {
+ WarnOnInit();
+ SourceLocation SemiLoc = ConsumeToken();
+ *InitStmt = Actions.ActOnNullStmt(SemiLoc);
+ return ParseCXXCondition(nullptr, Loc, CK);
+ }
+
// Parse the expression.
ExprResult Expr = ParseExpression(); // expression
if (Expr.isInvalid())
return Sema::ConditionError();
if (InitStmt && Tok.is(tok::semi)) {
+ WarnOnInit();
*InitStmt = Actions.ActOnExprStmt(Expr.get());
ConsumeToken();
return ParseCXXCondition(nullptr, Loc, CK);
@@ -1762,10 +1782,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
}
case ConditionOrInitStatement::InitStmtDecl: {
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
- ? diag::warn_cxx14_compat_init_statement
- : diag::ext_init_statement)
- << (CK == Sema::ConditionKind::Switch);
+ WarnOnInit();
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG =
ParseSimpleDeclaration(DeclaratorContext::InitStmtContext, DeclEnd,
@@ -1804,7 +1821,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
MaybeParseGNUAttributes(DeclaratorInfo);
// Type-check the declaration itself.
- DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
+ DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
DeclaratorInfo);
if (Dcl.isInvalid())
return Sema::ConditionError();
@@ -1892,10 +1909,10 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
getTypeAnnotation(Tok), Policy);
else
DS.SetTypeSpecError();
-
+
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeAnnotationToken();
-
+
DS.Finish(Actions, Policy);
return;
}
@@ -1946,6 +1963,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
case tok::kw_wchar_t:
DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy);
break;
+ case tok::kw_char8_t:
+ DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec, DiagID, Policy);
+ break;
case tok::kw_char16_t:
DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy);
break;
@@ -1988,8 +2008,8 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
return false;
}
-/// \brief Finish parsing a C++ unqualified-id that is a template-id of
-/// some form.
+/// Finish parsing a C++ unqualified-id that is a template-id of
+/// some form.
///
/// This routine is invoked when a '<' is encountered after an identifier or
/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
@@ -2003,10 +2023,10 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
/// \param Name for constructor and destructor names, this is the actual
/// identifier that may be a template-name.
///
-/// \param NameLoc the location of the class-name in a constructor or
+/// \param NameLoc the location of the class-name in a constructor or
/// destructor.
///
-/// \param EnteringContext whether we're entering the scope of the
+/// \param EnteringContext whether we're entering the scope of the
/// nested-name-specifier.
///
/// \param ObjectType if this unqualified-id occurs within a member access
@@ -2015,9 +2035,9 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
/// \param Id as input, describes the template-name or operator-function-id
/// that precedes the '<'. If template arguments were parsed successfully,
/// will be updated with the template-id.
-///
+///
/// \param AssumeTemplateId When true, this routine will assume that the name
-/// refers to a template without performing name lookup to verify.
+/// refers to a template without performing name lookup to verify.
///
/// \returns true if a parse error occurred, false otherwise.
bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
@@ -2028,9 +2048,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
ParsedType ObjectType,
UnqualifiedId &Id,
bool AssumeTemplateId) {
- assert((AssumeTemplateId || Tok.is(tok::less)) &&
- "Expected '<' to finish parsing a template-id");
-
+ assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
+
TemplateTy Template;
TemplateNameKind TNK = TNK_Non_template;
switch (Id.getKind()) {
@@ -2051,10 +2070,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateKWLoc.isValid(), Id,
ObjectType, EnteringContext, Template,
MemberOfUnknownSpecialization);
-
+
if (TNK == TNK_Non_template && MemberOfUnknownSpecialization &&
ObjectType && IsTemplateArgumentList()) {
- // We have something like t->getAs<T>(), where getAs is a
+ // We have something like t->getAs<T>(), where getAs is a
// member of an unknown specialization. However, this will only
// parse correctly as a template, so suggest the keyword 'template'
// before 'getAs' and treat this as a dependent template name.
@@ -2075,22 +2094,22 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
- return true;
+ return true;
}
}
break;
-
+
case UnqualifiedIdKind::IK_ConstructorName: {
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
- TemplateName, ObjectType,
+ TemplateName, ObjectType,
EnteringContext, Template,
MemberOfUnknownSpecialization);
break;
}
-
+
case UnqualifiedIdKind::IK_DestructorName: {
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
@@ -2103,33 +2122,33 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
return true;
} else {
TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
- TemplateName, ObjectType,
+ TemplateName, ObjectType,
EnteringContext, Template,
MemberOfUnknownSpecialization);
-
+
if (TNK == TNK_Non_template && !Id.DestructorName.get()) {
Diag(NameLoc, diag::err_destructor_template_id)
<< Name << SS.getRange();
- return true;
+ return true;
}
}
break;
}
-
+
default:
return false;
}
-
+
if (TNK == TNK_Non_template)
return false;
-
+
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
- if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName(
- true, LAngleLoc, TemplateArgs, RAngleLoc))
+ if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs,
+ RAngleLoc))
return true;
-
+
if (Id.getKind() == UnqualifiedIdKind::IK_Identifier ||
Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
Id.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) {
@@ -2164,16 +2183,16 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
/*IsCtorOrDtorName=*/true);
if (Type.isInvalid())
return true;
-
+
if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
else
Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
-
+
return false;
}
-/// \brief Parse an operator-function-id or conversion-function-id as part
+/// Parse an operator-function-id or conversion-function-id as part
/// of a C++ unqualified-id.
///
/// This routine is responsible only for parsing the operator-function-id or
@@ -2204,7 +2223,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
/// \param SS The nested-name-specifier that preceded this unqualified-id. If
/// non-empty, then we are parsing the unqualified-id of a qualified-id.
///
-/// \param EnteringContext whether we are entering the scope of the
+/// \param EnteringContext whether we are entering the scope of the
/// nested-name-specifier.
///
/// \param ObjectType if this unqualified-id occurs within a member access
@@ -2217,10 +2236,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
ParsedType ObjectType,
UnqualifiedId &Result) {
assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
-
+
// Consume the 'operator' keyword.
SourceLocation KeywordLoc = ConsumeToken();
-
+
// Determine what kind of operator name we have.
unsigned SymbolIdx = 0;
SourceLocation SymbolLocations[3];
@@ -2240,7 +2259,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
-
+
SymbolLocations[SymbolIdx++] = T.getOpenLocation();
SymbolLocations[SymbolIdx++] = T.getCloseLocation();
Op = isNew? OO_Array_New : OO_Array_Delete;
@@ -2249,7 +2268,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
}
break;
}
-
+
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
case tok::Token: \
SymbolLocations[SymbolIdx++] = ConsumeToken(); \
@@ -2257,7 +2276,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
break;
#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
#include "clang/Basic/OperatorKinds.def"
-
+
case tok::l_paren: {
// Consume the '(' and ')'.
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -2265,13 +2284,13 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
-
+
SymbolLocations[SymbolIdx++] = T.getOpenLocation();
SymbolLocations[SymbolIdx++] = T.getCloseLocation();
Op = OO_Call;
break;
}
-
+
case tok::l_square: {
// Consume the '[' and ']'.
BalancedDelimiterTracker T(*this, tok::l_square);
@@ -2279,25 +2298,25 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
-
+
SymbolLocations[SymbolIdx++] = T.getOpenLocation();
SymbolLocations[SymbolIdx++] = T.getCloseLocation();
Op = OO_Subscript;
break;
}
-
+
case tok::code_completion: {
// Code completion for the operator name.
Actions.CodeCompleteOperatorName(getCurScope());
- cutOffParsing();
+ cutOffParsing();
// Don't try to parse any further.
return true;
}
-
+
default:
break;
}
-
+
if (Op != OO_None) {
// We have parsed an operator-function-id.
Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
@@ -2390,12 +2409,12 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
//
// conversion-declarator:
// ptr-operator conversion-declarator[opt]
-
+
// Parse the type-specifier-seq.
DeclSpec DS(AttrFactory);
if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
return true;
-
+
// Parse the conversion-declarator, which is merely a sequence of
// ptr-operators.
Declarator D(DS, DeclaratorContext::ConversionIdContext);
@@ -2405,14 +2424,14 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D);
if (Ty.isInvalid())
return true;
-
+
// Note that this is a conversion-function-id.
- Result.setConversionFunctionId(KeywordLoc, Ty.get(),
+ Result.setConversionFunctionId(KeywordLoc, Ty.get(),
D.getSourceRange().getEnd());
- return false;
+ return false;
}
-/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
+/// Parse a C++ unqualified-id (or a C identifier), which describes the
/// name of an entity.
///
/// \code
@@ -2429,7 +2448,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
/// \param SS The nested-name-specifier that preceded this unqualified-id. If
/// non-empty, then we are parsing the unqualified-id of a qualified-id.
///
-/// \param EnteringContext whether we are entering the scope of the
+/// \param EnteringContext whether we are entering the scope of the
/// nested-name-specifier.
///
/// \param AllowDestructorName whether we allow parsing of a destructor name.
@@ -2449,16 +2468,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowConstructorName,
bool AllowDeductionGuide,
ParsedType ObjectType,
- SourceLocation& TemplateKWLoc,
+ SourceLocation *TemplateKWLoc,
UnqualifiedId &Result) {
+ if (TemplateKWLoc)
+ *TemplateKWLoc = SourceLocation();
// Handle 'A::template B'. This is for template-ids which have not
// already been annotated by ParseOptionalCXXScopeSpecifier().
bool TemplateSpecified = false;
- if (getLangOpts().CPlusPlus && Tok.is(tok::kw_template) &&
- (ObjectType || SS.isSet())) {
- TemplateSpecified = true;
- TemplateKWLoc = ConsumeToken();
+ if (Tok.is(tok::kw_template)) {
+ if (TemplateKWLoc && (ObjectType || SS.isSet())) {
+ TemplateSpecified = true;
+ *TemplateKWLoc = ConsumeToken();
+ } else {
+ SourceLocation TemplateLoc = ConsumeToken();
+ Diag(TemplateLoc, diag::err_unexpected_template_in_unqualified_id)
+ << FixItHint::CreateRemoval(TemplateLoc);
+ }
}
// unqualified-id:
@@ -2477,13 +2503,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
ParsedTemplateTy TemplateName;
- if (AllowConstructorName &&
+ if (AllowConstructorName &&
Actions.isCurrentClassName(*Id, getCurScope(), &SS)) {
// We have parsed a constructor name.
- ParsedType Ty = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, false,
- false, nullptr,
- /*IsCtorOrDtorName=*/true,
- /*NonTrivialTypeSourceInfo=*/true);
+ ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS,
+ EnteringContext);
+ if (!Ty)
+ return true;
Result.setConstructorName(Ty, IdLoc, IdLoc);
} else if (getLangOpts().CPlusPlus17 &&
AllowDeductionGuide && SS.isEmpty() &&
@@ -2493,24 +2519,31 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
Result.setDeductionGuideName(TemplateName, IdLoc);
} else {
// We have parsed an identifier.
- Result.setIdentifier(Id, IdLoc);
+ Result.setIdentifier(Id, IdLoc);
}
// If the next token is a '<', we may have a template.
- if (TemplateSpecified || Tok.is(tok::less))
- return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, Id, IdLoc,
- EnteringContext, ObjectType,
- Result, TemplateSpecified);
-
+ TemplateTy Template;
+ if (Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(
+ SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc,
+ EnteringContext, ObjectType, Result, TemplateSpecified);
+ else if (TemplateSpecified &&
+ Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
+ EnteringContext, Template,
+ /*AllowInjectedClassName*/ true) == TNK_Non_template)
+ return true;
+
return false;
}
-
+
// unqualified-id:
// template-id (already parsed and annotated)
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- // If the template-name names the current class, then this is a constructor
+ // If the template-name names the current class, then this is a constructor
if (AllowConstructorName && TemplateId->Name &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
if (SS.isSet()) {
@@ -2518,16 +2551,16 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
// is taken as the constructor name where a constructor can be
// declared. Thus, the template arguments are extraneous, so
// complain about them and remove them entirely.
- Diag(TemplateId->TemplateNameLoc,
+ Diag(TemplateId->TemplateNameLoc,
diag::err_out_of_line_constructor_template_id)
<< TemplateId->Name
<< FixItHint::CreateRemoval(
SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc));
- ParsedType Ty =
- Actions.getTypeName(*TemplateId->Name, TemplateId->TemplateNameLoc,
- getCurScope(), &SS, false, false, nullptr,
- /*IsCtorOrDtorName=*/true,
- /*NontrivialTypeSourceInfo=*/true);
+ ParsedType Ty = Actions.getConstructorName(
+ *TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS,
+ EnteringContext);
+ if (!Ty)
+ return true;
Result.setConstructorName(Ty, TemplateId->TemplateNameLoc,
TemplateId->RAngleLoc);
ConsumeAnnotationToken();
@@ -2542,41 +2575,55 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
// We have already parsed a template-id; consume the annotation token as
// our unqualified-id.
Result.setTemplateId(TemplateId);
- TemplateKWLoc = TemplateId->TemplateKWLoc;
+ SourceLocation TemplateLoc = TemplateId->TemplateKWLoc;
+ if (TemplateLoc.isValid()) {
+ if (TemplateKWLoc && (ObjectType || SS.isSet()))
+ *TemplateKWLoc = TemplateLoc;
+ else
+ Diag(TemplateLoc, diag::err_unexpected_template_in_unqualified_id)
+ << FixItHint::CreateRemoval(TemplateLoc);
+ }
ConsumeAnnotationToken();
return false;
}
-
+
// unqualified-id:
// operator-function-id
// conversion-function-id
if (Tok.is(tok::kw_operator)) {
if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
return true;
-
+
// If we have an operator-function-id or a literal-operator-id and the next
// token is a '<', we may have a
- //
+ //
// template-id:
// operator-function-id < template-argument-list[opt] >
+ TemplateTy Template;
if ((Result.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
Result.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) &&
- (TemplateSpecified || Tok.is(tok::less)))
- return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
- nullptr, SourceLocation(),
- EnteringContext, ObjectType,
- Result, TemplateSpecified);
+ Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(
+ SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), nullptr,
+ SourceLocation(), EnteringContext, ObjectType, Result,
+ TemplateSpecified);
+ else if (TemplateSpecified &&
+ Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
+ EnteringContext, Template,
+ /*AllowInjectedClassName*/ true) == TNK_Non_template)
+ return true;
return false;
}
-
- if (getLangOpts().CPlusPlus &&
+
+ if (getLangOpts().CPlusPlus &&
(AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
// C++ [expr.unary.op]p10:
- // There is an ambiguity in the unary-expression ~X(), where X is a
- // class-name. The ambiguity is resolved in favor of treating ~ as a
+ // There is an ambiguity in the unary-expression ~X(), where X is a
+ // class-name. The ambiguity is resolved in favor of treating ~ as a
// unary complement rather than treating ~X as referring to a destructor.
-
+
// Parse the '~'.
SourceLocation TildeLoc = ConsumeToken();
@@ -2590,7 +2637,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
return true;
}
-
+
// Parse the class-name.
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_destructor_tilde_identifier);
@@ -2633,16 +2680,15 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
IdentifierInfo *ClassName = Tok.getIdentifierInfo();
SourceLocation ClassNameLoc = ConsumeToken();
- if (TemplateSpecified || Tok.is(tok::less)) {
+ if (Tok.is(tok::less)) {
Result.setDestructorName(TildeLoc, nullptr, ClassNameLoc);
- return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
- ClassName, ClassNameLoc,
- EnteringContext, ObjectType,
- Result, TemplateSpecified);
+ return ParseUnqualifiedIdTemplateId(
+ SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), ClassName,
+ ClassNameLoc, EnteringContext, ObjectType, Result, TemplateSpecified);
}
// Note that this is a destructor name.
- ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName,
+ ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName,
ClassNameLoc, getCurScope(),
SS, ObjectType,
EnteringContext);
@@ -2652,7 +2698,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
return false;
}
-
+
Diag(Tok, diag::err_expected_unqualified_id)
<< getLangOpts().CPlusPlus;
return true;
@@ -2839,10 +2885,9 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
D.AddTypeInfo(DeclaratorChunk::getArray(0,
/*static=*/false, /*star=*/false,
- Size.get(),
- T.getOpenLocation(),
+ Size.get(), T.getOpenLocation(),
T.getCloseLocation()),
- Attrs, T.getCloseLocation());
+ std::move(Attrs), T.getCloseLocation());
if (T.getCloseLocation().isInvalid())
return;
@@ -2957,7 +3002,7 @@ static unsigned TypeTraitArity(tok::TokenKind kind) {
}
}
-/// \brief Parse the built-in type-trait pseudo-functions that allow
+/// Parse the built-in type-trait pseudo-functions that allow
/// implementation of the TR1/C++11 type traits templates.
///
/// primary-expression:
@@ -2973,7 +3018,7 @@ ExprResult Parser::ParseTypeTrait() {
unsigned Arity = TypeTraitArity(Kind);
SourceLocation Loc = ConsumeToken();
-
+
BalancedDelimiterTracker Parens(*this, tok::l_paren);
if (Parens.expectAndConsume())
return ExprError();
@@ -2995,7 +3040,7 @@ ExprResult Parser::ParseTypeTrait() {
return ExprError();
}
}
-
+
// Add this type to the list of arguments.
Args.push_back(Ty.get());
} while (TryConsumeToken(tok::comma));
@@ -3221,7 +3266,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ExprType = SimpleExpr;
Result = ParseExpression();
if (!Result.isInvalid() && Tok.is(tok::r_paren))
- Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(),
+ Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(),
Tok.getLocation(), Result.get());
// Match the ')'.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
index 90f3561cb963..0cd550bc6a47 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
@@ -20,21 +20,21 @@
using namespace clang;
-/// MayBeDesignationStart - Return true if the current token might be the start
-/// of a designator. If we can tell it is impossible that it is a designator,
+/// MayBeDesignationStart - Return true if the current token might be the start
+/// of a designator. If we can tell it is impossible that it is a designator,
/// return false.
bool Parser::MayBeDesignationStart() {
switch (Tok.getKind()) {
- default:
+ default:
return false;
-
+
case tok::period: // designator: '.' identifier
return true;
-
+
case tok::l_square: { // designator: array-designator
if (!PP.getLangOpts().CPlusPlus11)
return true;
-
+
// C++11 lambda expressions and C99 designators can be ambiguous all the
// way through the closing ']' and to the next character. Handle the easy
// cases here, and fall back to tentative parsing if those fail.
@@ -43,28 +43,28 @@ bool Parser::MayBeDesignationStart() {
case tok::r_square:
// Definitely starts a lambda expression.
return false;
-
+
case tok::amp:
case tok::kw_this:
case tok::identifier:
// We have to do additional analysis, because these could be the
// start of a constant expression or a lambda capture list.
break;
-
+
default:
- // Anything not mentioned above cannot occur following a '[' in a
+ // Anything not mentioned above cannot occur following a '[' in a
// lambda expression.
- return true;
+ return true;
}
-
+
// Handle the complicated case below.
- break;
+ break;
}
case tok::identifier: // designation: identifier ':'
return PP.LookAhead(0).is(tok::colon);
}
-
- // Parse up to (at most) the token after the closing ']' to determine
+
+ // Parse up to (at most) the token after the closing ']' to determine
// whether this is a C99 designator or a lambda.
TentativeParsingAction Tentative(*this);
@@ -198,7 +198,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
// it will be rejected because a constant-expression cannot begin with a
// lambda-expression.
InMessageExpressionRAIIObject InMessage(*this, true);
-
+
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
SourceLocation StartLoc = T.getOpenLocation();
@@ -212,7 +212,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus) {
// Send to 'super'.
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
- NextToken().isNot(tok::period) &&
+ NextToken().isNot(tok::period) &&
getCurScope()->isInObjcMethodScope()) {
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
return ParseAssignmentExprWithObjCMessageExprStart(
@@ -226,13 +226,13 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
SkipUntil(tok::r_square, StopAtSemi);
return ExprError();
}
-
+
// If the receiver was a type, we have a class message; parse
// the rest of it.
if (!IsExpr) {
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
- return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
- SourceLocation(),
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ SourceLocation(),
ParsedType::getFromOpaquePtr(TypeOrExpr),
nullptr);
}
@@ -281,8 +281,8 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
}
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
- SourceLocation(),
- ReceiverType,
+ SourceLocation(),
+ ReceiverType,
nullptr);
case Sema::ObjCInstanceMessage:
@@ -387,7 +387,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
///
ExprResult Parser::ParseBraceInitializer() {
InMessageExpressionRAIIObject InMessage(*this, false);
-
+
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
SourceLocation LBraceLoc = T.getOpenLocation();
@@ -485,7 +485,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
IfExistsCondition Result;
if (ParseMicrosoftIfExistsCondition(Result))
return false;
-
+
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
Diag(Tok, diag::err_expected) << tok::l_brace;
@@ -496,7 +496,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
case IEB_Parse:
// Parse the declarations below.
break;
-
+
case IEB_Dependent:
Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
<< Result.IsIfExists;
@@ -520,7 +520,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
if (Tok.is(tok::ellipsis))
SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
-
+
// If we couldn't parse the subelement, bail out.
if (!SubElt.isInvalid())
InitExprs.push_back(SubElt.get());
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
index 688376ca28e6..99e5edb9d4a3 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
@@ -13,11 +13,11 @@
#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -45,7 +45,8 @@ void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
/// [OBJC] objc-protocol-definition
/// [OBJC] objc-method-definition
/// [OBJC] '@' 'end'
-Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
+Parser::DeclGroupPtrTy
+Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
@@ -58,15 +59,11 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
- case tok::objc_interface: {
- ParsedAttributes attrs(AttrFactory);
- SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
+ case tok::objc_interface:
+ SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs);
break;
- }
- case tok::objc_protocol: {
- ParsedAttributes attrs(AttrFactory);
- return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
- }
+ case tok::objc_protocol:
+ return ParseObjCAtProtocolDeclaration(AtLoc, Attrs);
case tok::objc_implementation:
return ParseObjCAtImplementationDeclaration(AtLoc);
case tok::objc_end:
@@ -250,7 +247,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::l_paren) &&
!isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
-
+
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -261,7 +258,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
cutOffParsing();
return nullptr;
}
-
+
// For ObjC2, the category name is optional (not an error).
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
@@ -272,11 +269,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
<< tok::identifier; // missing category name.
return nullptr;
}
-
+
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return nullptr;
-
+
// Next, we need to check for any protocol references.
assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");
SmallVector<Decl *, 8> ProtocolRefs;
@@ -290,11 +287,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
Decl *CategoryType = Actions.ActOnStartCategoryInterface(
AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc,
ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(),
- EndProtoLoc, attrs.getList());
+ EndProtoLoc, attrs);
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
-
+
ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
return CategoryType;
@@ -356,17 +353,12 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
if (Tok.isNot(tok::less))
Actions.ActOnTypedefedProtocols(protocols, protocolLocs,
superClassId, superClassLoc);
-
- Decl *ClsType =
- Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc,
- typeParameterList, superClassId,
- superClassLoc,
- typeArgs,
- SourceRange(typeArgsLAngleLoc,
- typeArgsRAngleLoc),
- protocols.data(), protocols.size(),
- protocolLocs.data(),
- EndProtoLoc, attrs.getList());
+
+ Decl *ClsType = Actions.ActOnStartClassInterface(
+ getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId,
+ superClassLoc, typeArgs,
+ SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(),
+ protocols.size(), protocolLocs.data(), EndProtoLoc, attrs);
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
@@ -384,25 +376,21 @@ static void addContextSensitiveTypeNullability(Parser &P,
SourceLocation nullabilityLoc,
bool &addedToDeclSpec) {
// Create the attribute.
- auto getNullabilityAttr = [&]() -> AttributeList * {
- return D.getAttributePool().create(
- P.getNullabilityKeyword(nullability),
- SourceRange(nullabilityLoc),
- nullptr, SourceLocation(),
- nullptr, 0,
- AttributeList::AS_ContextSensitiveKeyword);
+ auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * {
+ return Pool.create(P.getNullabilityKeyword(nullability),
+ SourceRange(nullabilityLoc), nullptr, SourceLocation(),
+ nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword);
};
if (D.getNumTypeObjects() > 0) {
// Add the attribute to the declarator chunk nearest the declarator.
- auto nullabilityAttr = getNullabilityAttr();
- DeclaratorChunk &chunk = D.getTypeObject(0);
- nullabilityAttr->setNext(chunk.getAttrListRef());
- chunk.getAttrListRef() = nullabilityAttr;
+ D.getTypeObject(0).getAttrs().addAtStart(
+ getNullabilityAttr(D.getAttributePool()));
} else if (!addedToDeclSpec) {
// Otherwise, just put it on the declaration specifiers (if one
// isn't there already).
- D.getMutableDeclSpec().addAttributes(getNullabilityAttr());
+ D.getMutableDeclSpec().getAttributes().addAtStart(
+ getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool()));
addedToDeclSpec = true;
}
}
@@ -604,14 +592,14 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() {
/// @required
/// @optional
///
-void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
+void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
Decl *CDecl) {
SmallVector<Decl *, 32> allMethods;
SmallVector<DeclGroupPtrTy, 8> allTUVariables;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
SourceRange AtEnd;
-
+
while (1) {
// If this is a method prototype, parse it.
if (Tok.isOneOf(tok::minus, tok::plus)) {
@@ -630,8 +618,8 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
}
if (Tok.is(tok::l_paren)) {
Diag(Tok, diag::err_expected_minus_or_plus);
- ParseObjCMethodDecl(Tok.getLocation(),
- tok::minus,
+ ParseObjCMethodDecl(Tok.getLocation(),
+ tok::minus,
MethodImplKind, false);
continue;
}
@@ -647,12 +635,12 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
// Code completion within an Objective-C interface.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(),
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
CurParsedObjCImpl? Sema::PCC_ObjCImplementation
: Sema::PCC_ObjCInterface);
return cutOffParsing();
}
-
+
// If we don't have an @ directive, parse it as a function definition.
if (Tok.isNot(tok::at)) {
// The code below does not consume '}'s because it is afraid of eating the
@@ -697,7 +685,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
// Skip until we see an '@' or '}' or ';'.
SkipUntil(tok::r_brace, tok::at, StopAtSemi);
break;
-
+
case tok::objc_implementation:
case tok::objc_interface:
Diag(AtLoc, diag::err_objc_missing_end)
@@ -706,7 +694,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
<< (int) Actions.getObjCContainerKind();
ConsumeToken();
break;
-
+
case tok::objc_required:
case tok::objc_optional:
// This is only valid on protocols.
@@ -1033,7 +1021,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
}
return nullptr;
}
-
+
case tok::identifier:
case tok::kw_asm:
case tok::kw_auto:
@@ -1146,11 +1134,11 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
while (1) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
+ Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
Context == DeclaratorContext::ObjCParameterContext);
return cutOffParsing();
}
-
+
if (Tok.isNot(tok::identifier))
return;
@@ -1172,17 +1160,17 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break;
- case objc_nonnull:
+ case objc_nonnull:
Qual = ObjCDeclSpec::DQ_CSNullability;
Nullability = NullabilityKind::NonNull;
break;
- case objc_nullable:
+ case objc_nullable:
Qual = ObjCDeclSpec::DQ_CSNullability;
Nullability = NullabilityKind::Nullable;
break;
- case objc_null_unspecified:
+ case objc_null_unspecified:
Qual = ObjCDeclSpec::DQ_CSNullability;
Nullability = NullabilityKind::Unspecified;
break;
@@ -1205,18 +1193,12 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
/// Take all the decl attributes out of the given list and add
/// them to the given attribute set.
-static void takeDeclAttributes(ParsedAttributes &attrs,
- AttributeList *list) {
- while (list) {
- AttributeList *cur = list;
- list = cur->getNext();
-
- if (!cur->isUsedAsTypeAttr()) {
- // Clear out the next pointer. We're really completely
- // destroying the internal invariants of the declarator here,
- // but it doesn't matter because we're done with it.
- cur->setNext(nullptr);
- attrs.add(cur);
+static void takeDeclAttributes(ParsedAttributesView &attrs,
+ ParsedAttributesView &from) {
+ for (auto &AL : llvm::reverse(from)) {
+ if (!AL.isUsedAsTypeAttr()) {
+ from.remove(&AL);
+ attrs.addAtStart(&AL);
}
}
}
@@ -1230,18 +1212,17 @@ static void takeDeclAttributes(ParsedAttributes &attrs,
attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());
// Now actually move the attributes over.
- takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList());
+ takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes());
takeDeclAttributes(attrs, D.getAttributes());
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
- takeDeclAttributes(attrs,
- const_cast<AttributeList*>(D.getTypeObject(i).getAttrs()));
+ takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs());
}
/// objc-type-name:
/// '(' objc-type-qualifiers[opt] type-name ')'
/// '(' objc-type-qualifiers[opt] ')'
///
-ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
+ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
DeclaratorContext context,
ParsedAttributes *paramAttrs) {
assert(context == DeclaratorContext::ObjCParameterContext ||
@@ -1359,9 +1340,10 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ParsedAttributes methodAttrs(AttrFactory);
if (getLangOpts().ObjC2)
MaybeParseGNUAttributes(methodAttrs);
+ MaybeParseCXX11Attributes(methodAttrs);
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
+ Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
ReturnType);
cutOffParsing();
return nullptr;
@@ -1385,15 +1367,13 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// If attributes exist after the method, parse them.
if (getLangOpts().ObjC2)
MaybeParseGNUAttributes(methodAttrs);
+ MaybeParseCXX11Attributes(methodAttrs);
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
- Decl *Result
- = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
- mType, DSRet, ReturnType,
- selLoc, Sel, nullptr,
- CParamInfo.data(), CParamInfo.size(),
- methodAttrs.getList(), MethodImplKind,
- false, MethodDefinition);
+ Decl *Result = Actions.ActOnMethodDeclaration(
+ getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType,
+ selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs,
+ MethodImplKind, false, MethodDefinition);
PD.complete(Result);
return Result;
}
@@ -1421,16 +1401,15 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// If attributes exist before the argument name, parse them.
// Regardless, collect all the attributes we've parsed so far.
- ArgInfo.ArgAttrs = nullptr;
- if (getLangOpts().ObjC2) {
+ if (getLangOpts().ObjC2)
MaybeParseGNUAttributes(paramAttrs);
- ArgInfo.ArgAttrs = paramAttrs.getList();
- }
+ MaybeParseCXX11Attributes(paramAttrs);
+ ArgInfo.ArgAttrs = paramAttrs;
// Code completion for the next piece of the selector.
if (Tok.is(tok::code_completion)) {
KeyIdents.push_back(SelIdent);
- Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
+ Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
mType == tok::minus,
/*AtParameterName=*/true,
ReturnType, KeyIdents);
@@ -1454,14 +1433,14 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// Code completion for the next piece of the selector.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
+ Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
mType == tok::minus,
/*AtParameterName=*/false,
ReturnType, KeyIdents);
cutOffParsing();
return nullptr;
}
-
+
// Check for another keyword selector.
SelIdent = ParseObjCSelectorPiece(selLoc);
if (!SelIdent && Tok.isNot(tok::colon))
@@ -1499,7 +1478,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDecl.getIdentifierLoc(),
+ ParmDecl.getIdentifierLoc(),
Param,
nullptr));
}
@@ -1508,20 +1487,18 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// If attributes exist after the method, parse them.
if (getLangOpts().ObjC2)
MaybeParseGNUAttributes(methodAttrs);
-
+ MaybeParseCXX11Attributes(methodAttrs);
+
if (KeyIdents.size() == 0)
return nullptr;
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]);
- Decl *Result
- = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
- mType, DSRet, ReturnType,
- KeyLocs, Sel, &ArgInfos[0],
- CParamInfo.data(), CParamInfo.size(),
- methodAttrs.getList(),
- MethodImplKind, isVariadic, MethodDefinition);
-
+ Decl *Result = Actions.ActOnMethodDeclaration(
+ getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs,
+ Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs,
+ MethodImplKind, isVariadic, MethodDefinition);
+
PD.complete(Result);
return Result;
}
@@ -1637,7 +1614,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers(
// FIXME: Also include types here.
SmallVector<IdentifierLocPair, 4> identifierLocPairs;
for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
- identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
+ identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
identifierLocs[i]));
}
@@ -1823,10 +1800,10 @@ void Parser::parseObjCTypeArgsAndProtocolQualifiers(
<< SourceRange(protocolLAngleLoc, protocolRAngleLoc);
SkipUntil(tok::greater, tok::greatergreater, skipFlags);
} else {
- ParseObjCProtocolReferences(protocols, protocolLocs,
+ ParseObjCProtocolReferences(protocols, protocolLocs,
/*WarnOnDeclarations=*/false,
/*ForObjCContainer=*/false,
- protocolLAngleLoc, protocolRAngleLoc,
+ protocolLAngleLoc, protocolRAngleLoc,
consumeLastToken);
}
}
@@ -1880,15 +1857,15 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio
bool RBraceMissing) {
if (!RBraceMissing)
T.consumeClose();
-
+
Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
Actions.ActOnObjCContainerFinishDefinition();
// Call ActOnFields() even if we don't have any decls. This is useful
// for code rewriting tools that need to be aware of the empty list.
- Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
- AllIvarDecls,
- T.getOpenLocation(), T.getCloseLocation(), nullptr);
+ Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls,
+ T.getOpenLocation(), T.getCloseLocation(),
+ ParsedAttributesView());
}
/// objc-class-instance-variables:
@@ -1916,7 +1893,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {");
SmallVector<Decl *, 32> AllIvarDecls;
-
+
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
ObjCDeclContextSwitch ObjCDC(*this);
@@ -1938,7 +1915,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
Actions.CodeCompleteObjCAtVisibility(getCurScope());
return cutOffParsing();
}
-
+
switch (Tok.getObjCKeywordID()) {
case tok::objc_private:
case tok::objc_public:
@@ -1957,7 +1934,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
T, AllIvarDecls, true);
return;
-
+
default:
Diag(Tok, diag::err_objc_illegal_visibility_spec);
continue;
@@ -1965,7 +1942,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
}
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(),
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
Sema::PCC_ObjCInstanceVariableList);
return cutOffParsing();
}
@@ -2015,7 +1992,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
/// "\@protocol identifier ;" should be resolved as "\@protocol
/// identifier-list ;": objc-interface-decl-list may not start with a
/// semicolon in the first alternative if objc-protocol-refs are omitted.
-Parser::DeclGroupPtrTy
+Parser::DeclGroupPtrTy
Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
ParsedAttributes &attrs) {
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
@@ -2038,8 +2015,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
- return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo,
- attrs.getList());
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs);
}
CheckNestedObjCContexts(AtLoc);
@@ -2066,8 +2042,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
return nullptr;
- return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs,
- attrs.getList());
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs);
}
// Last, and definitely not least, parse a protocol declaration.
@@ -2081,12 +2056,9 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
/*consumeLastToken=*/true))
return nullptr;
- Decl *ProtoType =
- Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
- ProtocolRefs.data(),
- ProtocolRefs.size(),
- ProtocolLocs.data(),
- EndProtoLoc, attrs.getList());
+ Decl *ProtoType = Actions.ActOnStartProtocolInterface(
+ AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(),
+ ProtocolLocs.data(), EndProtoLoc, attrs);
ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
return Actions.ConvertDeclToDeclGroup(ProtoType);
@@ -2153,7 +2125,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
cutOffParsing();
return nullptr;
}
-
+
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
@@ -2173,7 +2145,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
SourceLocation protocolLAngleLoc, protocolRAngleLoc;
SmallVector<Decl *, 4> protocols;
SmallVector<SourceLocation, 4> protocolLocs;
- (void)ParseObjCProtocolReferences(protocols, protocolLocs,
+ (void)ParseObjCProtocolReferences(protocols, protocolLocs,
/*warnOnIncompleteProtocols=*/false,
/*ForObjCContainer=*/false,
protocolLAngleLoc, protocolRAngleLoc,
@@ -2197,7 +2169,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
ObjCImpDecl = Actions.ActOnStartClassImplementation(
AtLoc, nameId, nameLoc,
superClassId, superClassLoc);
-
+
if (Tok.is(tok::l_brace)) // we have ivars
ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
@@ -2206,7 +2178,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
SourceLocation protocolLAngleLoc, protocolRAngleLoc;
SmallVector<Decl *, 4> protocols;
SmallVector<SourceLocation, 4> protocolLocs;
- (void)ParseObjCProtocolReferences(protocols, protocolLocs,
+ (void)ParseObjCProtocolReferences(protocols, protocolLocs,
/*warnOnIncompleteProtocols=*/false,
/*ForObjCContainer=*/false,
protocolLAngleLoc, protocolRAngleLoc,
@@ -2263,17 +2235,17 @@ void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
assert(!Finished);
P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl, AtEnd.getBegin());
for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
- P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
+ P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
true/*Methods*/);
P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd);
if (HasCFunction)
for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
- P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
+ P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
false/*c-functions*/);
-
- /// \brief Clear and free the cached objc methods.
+
+ /// Clear and free the cached objc methods.
for (LateParsedObjCMethodContainer::iterator
I = LateParsedObjCMethods.begin(),
E = LateParsedObjCMethods.end(); I != E; ++I)
@@ -2325,7 +2297,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
cutOffParsing();
return nullptr;
}
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_synthesized_property_name);
SkipUntil(tok::semi);
@@ -2408,7 +2380,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
SkipUntil(tok::semi);
return nullptr;
}
-
+
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
Actions.ActOnPropertyImplDecl(
@@ -2566,14 +2538,14 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
Diag(Tok, diag::err_expected) << tok::l_brace;
if (CatchBody.isInvalid())
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
-
+
StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
- RParenLoc,
- FirstPart,
+ RParenLoc,
+ FirstPart,
CatchBody.get());
if (!Catch.isInvalid())
CatchStmts.push_back(Catch.get());
-
+
} else {
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
<< "@catch clause";
@@ -2586,13 +2558,26 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
ParseScope FinallyScope(this,
Scope::DeclScope | Scope::CompoundStmtScope);
+ bool ShouldCapture =
+ getTargetInfo().getTriple().isWindowsMSVCEnvironment();
+ if (ShouldCapture)
+ Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(),
+ CR_ObjCAtFinally, 1);
+
StmtResult FinallyBody(true);
if (Tok.is(tok::l_brace))
FinallyBody = ParseCompoundStatementBody();
else
Diag(Tok, diag::err_expected) << tok::l_brace;
- if (FinallyBody.isInvalid())
+
+ if (FinallyBody.isInvalid()) {
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
+ if (ShouldCapture)
+ Actions.ActOnCapturedRegionError();
+ } else if (ShouldCapture) {
+ FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get());
+ }
+
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
FinallyBody.get());
catch_or_finally_seen = true;
@@ -2603,8 +2588,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
Diag(atLoc, diag::err_missing_catch_finally);
return StmtError();
}
-
- return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(),
+
+ return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(),
CatchStmts,
FinallyStmt.get());
}
@@ -2628,11 +2613,11 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
BodyScope.Exit();
if (AutoreleasePoolBody.isInvalid())
AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
- return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
+ return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
AutoreleasePoolBody.get());
}
-/// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them
+/// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them
/// for later parsing.
void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
@@ -2681,7 +2666,7 @@ void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
Decl *Parser::ParseObjCMethodDefinition() {
Decl *MDecl = ParseObjCMethodPrototype();
- PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(),
"parsing Objective-C method");
// parse optional ';'
@@ -2713,7 +2698,7 @@ Decl *Parser::ParseObjCMethodDefinition() {
// Allow the rest of sema to find private method decl implementations.
Actions.AddAnyMethodToGlobalPool(MDecl);
- assert (CurParsedObjCImpl
+ assert (CurParsedObjCImpl
&& "ParseObjCMethodDefinition - Method out of @implementation");
// Consume the tokens and store them for later parsing.
StashAwayMethodOrFunctionBodyTokens(MDecl);
@@ -2726,13 +2711,13 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
cutOffParsing();
return StmtError();
}
-
+
if (Tok.isObjCAtKeyword(tok::objc_try))
return ParseObjCTryStmt(AtLoc);
-
+
if (Tok.isObjCAtKeyword(tok::objc_throw))
return ParseObjCThrowStmt(AtLoc);
-
+
if (Tok.isObjCAtKeyword(tok::objc_synchronized))
return ParseObjCSynchronizedStmt(AtLoc);
@@ -2754,7 +2739,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
SkipUntil(tok::semi);
return StmtError();
}
-
+
// Otherwise, eat the semicolon.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
return Actions.ActOnExprStmt(Res);
@@ -2804,7 +2789,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
case tok::char_constant:
return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));
-
+
case tok::numeric_constant:
return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));
@@ -2814,19 +2799,19 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
case tok::kw_false: // Objective-C++, etc.
case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));
-
+
case tok::l_square:
// Objective-C array literal
return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));
-
+
case tok::l_brace:
// Objective-C dictionary literal
return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
-
+
case tok::l_paren:
// Objective-C boxed expression
return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
-
+
default:
if (Tok.getIdentifierInfo() == nullptr)
return ExprError(Diag(AtLoc, diag::err_unexpected_at));
@@ -2848,14 +2833,14 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
if (GetLookAheadToken(1).is(tok::l_brace) &&
ExprStatementTokLoc == AtLoc) {
char ch = Tok.getIdentifierInfo()->getNameStart()[0];
- str =
- ch == 't' ? "try"
- : (ch == 'f' ? "finally"
+ str =
+ ch == 't' ? "try"
+ : (ch == 'f' ? "finally"
: (ch == 'a' ? "autoreleasepool" : nullptr));
}
if (str) {
SourceLocation kwLoc = Tok.getLocation();
- return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
+ return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
FixItHint::CreateReplacement(kwLoc, str));
}
else
@@ -2865,13 +2850,13 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
}
}
-/// \brief Parse the receiver of an Objective-C++ message send.
+/// Parse the receiver of an Objective-C++ message send.
///
/// This routine parses the receiver of a message send in
/// Objective-C++ either as a type or as an expression. Note that this
/// routine must not be called to parse a send to 'super', since it
/// has no way to return such a result.
-///
+///
/// \param IsExpr Whether the receiver was parsed as an expression.
///
/// \param TypeOrExpr If the receiver was parsed as an expression (\c
@@ -2915,7 +2900,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
// expression (that starts with one of the above)
DeclSpec DS(AttrFactory);
ParseCXXSimpleTypeSpecifier(DS);
-
+
if (Tok.is(tok::l_paren)) {
// If we see an opening parentheses at this point, we are
// actually parsing an expression that starts with a
@@ -2941,7 +2926,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
TypeOrExpr = Receiver.get();
return false;
}
-
+
// We have a class message. Turn the simple-type-specifier or
// typename-specifier we parsed into a type and parse the
// remainder of the class message.
@@ -2955,7 +2940,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
return false;
}
-/// \brief Determine whether the parser is currently referring to a an
+/// Determine whether the parser is currently referring to a an
/// Objective-C message send, using a simplified heuristic to avoid overhead.
///
/// This routine will only return true for a subset of valid message-send
@@ -2968,26 +2953,26 @@ bool Parser::isSimpleObjCMessageExpression() {
}
bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
- if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) ||
+ if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) ||
InMessageExpression)
return false;
-
+
ParsedType Type;
- if (Tok.is(tok::annot_typename))
+ if (Tok.is(tok::annot_typename))
Type = getTypeAnnotation(Tok);
else if (Tok.is(tok::identifier))
- Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
+ Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
getCurScope());
else
return false;
-
+
if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
const Token &AfterNext = GetLookAheadToken(2);
if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
if (Tok.is(tok::identifier))
TryAnnotateTypeOrScopeToken();
-
+
return Tok.is(tok::annot_typename);
}
}
@@ -3013,14 +2998,14 @@ ExprResult Parser::ParseObjCMessageExpression() {
cutOffParsing();
return ExprError();
}
-
+
InMessageExpressionRAIIObject InMessage(*this, true);
-
+
if (getLangOpts().CPlusPlus) {
// We completely separate the C and C++ cases because C++ requires
- // more complicated (read: slower) parsing.
-
- // Handle send to super.
+ // more complicated (read: slower) parsing.
+
+ // Handle send to super.
// FIXME: This doesn't benefit from the same typo-correction we
// get in Objective-C.
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
@@ -3040,11 +3025,11 @@ ExprResult Parser::ParseObjCMessageExpression() {
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
static_cast<Expr *>(TypeOrExpr));
- return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
ParsedType::getFromOpaquePtr(TypeOrExpr),
nullptr);
}
-
+
if (Tok.is(tok::identifier)) {
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = Tok.getLocation();
@@ -3080,7 +3065,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
ReceiverType = NewReceiverType.get();
}
- return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
ReceiverType, nullptr);
case Sema::ObjCInstanceMessage:
@@ -3088,7 +3073,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
break;
}
}
-
+
// Otherwise, an arbitrary expression can be the receiver of a send.
ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
if (Res.isInvalid()) {
@@ -3100,7 +3085,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
Res.get());
}
-/// \brief Parse the remainder of an Objective-C message following the
+/// Parse the remainder of an Objective-C message following the
/// '[' objc-receiver.
///
/// This routine handles sends to super, class messages (sent to a
@@ -3158,11 +3143,11 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
cutOffParsing();
return ExprError();
}
-
+
// Parse objc-selector
SourceLocation Loc;
IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
-
+
SmallVector<IdentifierInfo *, 12> KeyIdents;
SmallVector<SourceLocation, 12> KeyLocs;
ExprVector KeyExprs;
@@ -3182,10 +3167,10 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
}
/// Parse the expression after ':'
-
+
if (Tok.is(tok::code_completion)) {
if (SuperLoc.isValid())
- Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
+ Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
KeyIdents,
/*AtArgumentEpression=*/true);
else if (ReceiverType)
@@ -3200,14 +3185,14 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
cutOffParsing();
return ExprError();
}
-
+
ExprResult Expr;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
Expr = ParseBraceInitializer();
} else
Expr = ParseAssignmentExpression();
-
+
ExprResult Res(Expr);
if (Res.isInvalid()) {
// We must manually skip to a ']', otherwise the expression skipper will
@@ -3223,7 +3208,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
// Code completion after each argument.
if (Tok.is(tok::code_completion)) {
if (SuperLoc.isValid())
- Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
+ Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
KeyIdents,
/*AtArgumentEpression=*/false);
else if (ReceiverType)
@@ -3237,7 +3222,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
cutOffParsing();
return ExprError();
}
-
+
// Check for another keyword selector.
selIdent = ParseObjCSelectorPiece(Loc);
if (!selIdent && Tok.isNot(tok::colon))
@@ -3275,7 +3260,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
SkipUntil(tok::r_square, StopAtSemi);
return ExprError();
}
-
+
if (Tok.isNot(tok::r_square)) {
Diag(Tok, diag::err_expected)
<< (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
@@ -3285,7 +3270,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
SkipUntil(tok::r_square, StopAtSemi);
return ExprError();
}
-
+
SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
unsigned nKeys = KeyIdents.size();
@@ -3339,7 +3324,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
/// ;
/// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
/// ;
-ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
+ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
bool ArgValue) {
SourceLocation EndLoc = ConsumeToken(); // consume the keyword.
return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
@@ -3410,15 +3395,15 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
// the enclosing expression.
SkipUntil(tok::r_square, StopAtSemi);
return Res;
- }
-
+ }
+
Res = Actions.CorrectDelayedTyposInExpr(Res.get());
if (Res.isInvalid())
HasInvalidEltExpr = true;
// Parse the ellipsis that indicates a pack expansion.
if (Tok.is(tok::ellipsis))
- Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
+ Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
if (Res.isInvalid())
HasInvalidEltExpr = true;
@@ -3462,7 +3447,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
SkipUntil(tok::r_brace, StopAtSemi);
return ExprError();
}
-
+
ExprResult ValueExpr(ParseAssignmentExpression());
if (ValueExpr.isInvalid()) {
// We must manually skip to a '}', otherwise the expression skipper will
@@ -3471,7 +3456,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
SkipUntil(tok::r_brace, StopAtSemi);
return ValueExpr;
}
-
+
// Check the key and value for possible typos
KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
@@ -3487,8 +3472,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
// We have a valid expression. Collect it in a vector so we can
// build the argument list.
- ObjCDictionaryElement Element = {
- KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
+ ObjCDictionaryElement Element = {
+ KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
};
Elements.push_back(Element);
@@ -3500,7 +3485,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
if (HasInvalidEltExpr)
return ExprError();
-
+
// Create the ObjCDictionaryLiteral.
return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
Elements);
@@ -3566,26 +3551,26 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
SmallVector<IdentifierInfo *, 12> KeyIdents;
SourceLocation sLoc;
-
+
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
bool HasOptionalParen = Tok.is(tok::l_paren);
if (HasOptionalParen)
ConsumeParen();
-
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
cutOffParsing();
return ExprError();
}
-
+
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
if (!SelIdent && // missing selector name.
Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
KeyIdents.push_back(SelIdent);
-
+
unsigned nColons = 0;
if (Tok.isNot(tok::r_paren)) {
while (1) {
@@ -3598,7 +3583,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
if (Tok.is(tok::r_paren))
break;
-
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
cutOffParsing();
@@ -3626,12 +3611,12 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
// MCDecl might be null due to error in method or c-function prototype, etc.
Decl *MCDecl = LM.D;
- bool skip = MCDecl &&
+ bool skip = MCDecl &&
((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) ||
(!parseMethod && Actions.isObjCMethodDecl(MCDecl)));
if (skip)
return;
-
+
// Save the current token position.
SourceLocation OrigLoc = Tok.getLocation();
@@ -3651,15 +3636,15 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
-
- assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
+
+ 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 : 0) |
Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
- // Tell the actions module that we have entered a method or c-function definition
+ // Tell the actions module that we have entered a method or c-function definition
// with the specified Declarator for the method/function.
if (parseMethod)
Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
index 628c1f134ac5..a413e96a91e7 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements parsing of all OpenMP directives and clauses.
+/// This file implements parsing of all OpenMP directives and clauses.
///
//===----------------------------------------------------------------------===//
@@ -80,51 +80,56 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) {
.Default(OMPD_unknown);
}
-static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
+static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
// Array of foldings: F[i][0] F[i][1] ===> F[i][2].
// E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
// TODO: add other combined directives in topological order.
static const unsigned F[][3] = {
- { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
- { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
- { OMPD_declare, OMPD_simd, OMPD_declare_simd },
- { OMPD_declare, OMPD_target, OMPD_declare_target },
- { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
- { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
- { OMPD_distribute_parallel_for, OMPD_simd,
- OMPD_distribute_parallel_for_simd },
- { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
- { OMPD_end, OMPD_declare, OMPD_end_declare },
- { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
- { OMPD_target, OMPD_data, OMPD_target_data },
- { OMPD_target, OMPD_enter, OMPD_target_enter },
- { OMPD_target, OMPD_exit, OMPD_target_exit },
- { OMPD_target, OMPD_update, OMPD_target_update },
- { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
- { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
- { OMPD_for, OMPD_simd, OMPD_for_simd },
- { OMPD_parallel, OMPD_for, OMPD_parallel_for },
- { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
- { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
- { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
- { OMPD_target, OMPD_parallel, OMPD_target_parallel },
- { OMPD_target, OMPD_simd, OMPD_target_simd },
- { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
- { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
- { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
- { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
- { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
- { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
- { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
- { OMPD_target, OMPD_teams, OMPD_target_teams },
- { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
- { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
- { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
- { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
- { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
- };
+ {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
+ {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
+ {OMPD_declare, OMPD_simd, OMPD_declare_simd},
+ {OMPD_declare, OMPD_target, OMPD_declare_target},
+ {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
+ {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
+ {OMPD_distribute_parallel_for, OMPD_simd,
+ OMPD_distribute_parallel_for_simd},
+ {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
+ {OMPD_end, OMPD_declare, OMPD_end_declare},
+ {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
+ {OMPD_target, OMPD_data, OMPD_target_data},
+ {OMPD_target, OMPD_enter, OMPD_target_enter},
+ {OMPD_target, OMPD_exit, OMPD_target_exit},
+ {OMPD_target, OMPD_update, OMPD_target_update},
+ {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
+ {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
+ {OMPD_for, OMPD_simd, OMPD_for_simd},
+ {OMPD_parallel, OMPD_for, OMPD_parallel_for},
+ {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
+ {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
+ {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
+ {OMPD_target, OMPD_parallel, OMPD_target_parallel},
+ {OMPD_target, OMPD_simd, OMPD_target_simd},
+ {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
+ {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
+ {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
+ {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
+ {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
+ {OMPD_teams_distribute_parallel, OMPD_for,
+ OMPD_teams_distribute_parallel_for},
+ {OMPD_teams_distribute_parallel_for, OMPD_simd,
+ OMPD_teams_distribute_parallel_for_simd},
+ {OMPD_target, OMPD_teams, OMPD_target_teams},
+ {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
+ {OMPD_target_teams_distribute, OMPD_parallel,
+ OMPD_target_teams_distribute_parallel},
+ {OMPD_target_teams_distribute, OMPD_simd,
+ OMPD_target_teams_distribute_simd},
+ {OMPD_target_teams_distribute_parallel, OMPD_for,
+ OMPD_target_teams_distribute_parallel_for},
+ {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
+ OMPD_target_teams_distribute_parallel_for_simd}};
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
- auto Tok = P.getCurToken();
+ Token Tok = P.getCurToken();
unsigned DKind =
Tok.isAnnotation()
? static_cast<unsigned>(OMPD_unknown)
@@ -132,8 +137,8 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
if (DKind == OMPD_unknown)
return OMPD_unknown;
- for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
- if (DKind != F[i][0])
+ for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
+ if (DKind != F[I][0])
continue;
Tok = P.getPreprocessor().LookAhead(0);
@@ -144,9 +149,9 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
if (SDKind == OMPD_unknown)
continue;
- if (SDKind == F[i][1]) {
+ if (SDKind == F[I][1]) {
P.ConsumeToken();
- DKind = F[i][2];
+ DKind = F[I][2];
}
}
return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
@@ -205,7 +210,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) {
: DeclNames.getCXXOperatorName(OOK);
}
-/// \brief Parse 'omp declare reduction' construct.
+/// Parse 'omp declare reduction' construct.
///
/// declare-reduction-directive:
/// annot_pragma_openmp 'declare' 'reduction'
@@ -253,7 +258,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
TypeResult TR =
ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
if (TR.isUsable()) {
- auto ReductionType =
+ QualType ReductionType =
Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
if (!ReductionType.isNull()) {
ReductionTypes.push_back(
@@ -300,7 +305,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
// Parse <combiner> expression and then parse initializer if any for each
// correct type.
unsigned I = 0, E = ReductionTypes.size();
- for (auto *D : DRD.get()) {
+ for (Decl *D : DRD.get()) {
TentativeParsingAction TPA(*this);
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope |
@@ -323,9 +328,9 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
// Parse <initializer> expression.
if (Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo()->isStr("initializer"))
+ Tok.getIdentifierInfo()->isStr("initializer")) {
ConsumeToken();
- else {
+ } else {
Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
TPA.Commit();
IsCorrect = false;
@@ -419,13 +424,15 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
} else {
// Match the ')'.
- T.consumeClose();
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
"Unexpected number of commas!");
- ExprResult Initializer = Actions.ActOnParenListExpr(
- T.getOpenLocation(), T.getCloseLocation(), Exprs);
+ ExprResult Initializer =
+ Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
/*DirectInit=*/true);
}
@@ -551,7 +558,7 @@ static bool parseDeclareSimdClauses(
if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
CKind == OMPC_linear) {
Parser::OpenMPVarListDataTy Data;
- auto *Vars = &Uniforms;
+ SmallVectorImpl<Expr *> *Vars = &Uniforms;
if (CKind == OMPC_aligned)
Vars = &Aligneds;
else if (CKind == OMPC_linear)
@@ -561,9 +568,9 @@ static bool parseDeclareSimdClauses(
if (P.ParseOpenMPVarList(OMPD_declare_simd,
getOpenMPClauseKind(ClauseName), *Vars, Data))
IsError = true;
- if (CKind == OMPC_aligned)
+ if (CKind == OMPC_aligned) {
Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
- else if (CKind == OMPC_linear) {
+ } else if (CKind == OMPC_linear) {
if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
Data.DepLinMapLoc))
Data.LinKind = OMPC_LINEAR_val;
@@ -613,15 +620,14 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
}
// Skip the last annot_pragma_openmp_end.
SourceLocation EndLoc = ConsumeAnnotationToken();
- if (!IsError) {
- return Actions.ActOnOpenMPDeclareSimdDirective(
- Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
- LinModifiers, Steps, SourceRange(Loc, EndLoc));
- }
- return Ptr;
+ if (IsError)
+ return Ptr;
+ return Actions.ActOnOpenMPDeclareSimdDirective(
+ Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
+ LinModifiers, Steps, SourceRange(Loc, EndLoc));
}
-/// \brief Parsing of declarative OpenMP directives.
+/// Parsing of declarative OpenMP directives.
///
/// threadprivate-directive:
/// annot_pragma_openmp 'threadprivate' simple-variable-list
@@ -643,7 +649,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SourceLocation Loc = ConsumeAnnotationToken();
- auto DKind = ParseOpenMPDirectiveKind(*this);
+ OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
switch (DKind) {
case OMPD_threadprivate: {
@@ -666,7 +672,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
case OMPD_declare_reduction:
ConsumeToken();
- if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
+ if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -695,9 +701,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ConsumeAnyToken();
DeclGroupPtrTy Ptr;
- if (Tok.is(tok::annot_pragma_openmp))
+ if (Tok.is(tok::annot_pragma_openmp)) {
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
- else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+ } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Here we expect to see some function declaration.
if (AS == AS_none) {
assert(TagType == DeclSpec::TST_unspecified);
@@ -719,7 +725,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
SourceLocation DTLoc = ConsumeAnyToken();
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
// OpenMP 4.5 syntax with list of entities.
- llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
+ Sema::NamedDeclSetType SameDirectiveDecls;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT =
OMPDeclareTargetDeclAttr::MT_To;
@@ -735,12 +741,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
ConsumeToken();
}
- auto Callback = [this, MT, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
+ auto &&Callback = [this, MT, &SameDirectiveDecls](
+ CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
SameDirectiveDecls);
};
- if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
+ if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
+ /*AllowScopeSpecifier=*/true))
break;
// Consume optional ','.
@@ -749,7 +756,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
ConsumeAnyToken();
- return DeclGroupPtrTy();
+ SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
+ SameDirectiveDecls.end());
+ if (Decls.empty())
+ return DeclGroupPtrTy();
+ return Actions.BuildDeclaratorGroup(Decls);
}
// Skip the last annot_pragma_openmp_end.
@@ -758,7 +769,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
return DeclGroupPtrTy();
- DKind = ParseOpenMPDirectiveKind(*this);
+ llvm::SmallVector<Decl *, 4> Decls;
+ DKind = parseOpenMPDirectiveKind(*this);
while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
DeclGroupPtrTy Ptr;
@@ -772,10 +784,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
Ptr =
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
}
+ if (Ptr) {
+ DeclGroupRef Ref = Ptr.get();
+ Decls.append(Ref.begin(), Ref.end());
+ }
if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
TentativeParsingAction TPA(*this);
ConsumeAnnotationToken();
- DKind = ParseOpenMPDirectiveKind(*this);
+ DKind = parseOpenMPDirectiveKind(*this);
if (DKind != OMPD_end_declare_target)
TPA.Revert();
else
@@ -797,7 +813,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
}
Actions.ActOnFinishOpenMPDeclareTargetDirective();
- return DeclGroupPtrTy();
+ return Actions.BuildDeclaratorGroup(Decls);
}
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
@@ -851,7 +867,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(DKind);
+ << 1 << getOpenMPDirectiveName(DKind);
break;
}
while (Tok.isNot(tok::annot_pragma_openmp_end))
@@ -860,7 +876,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
return nullptr;
}
-/// \brief Parsing of declarative or executable OpenMP directives.
+/// Parsing of declarative or executable OpenMP directives.
///
/// threadprivate-directive:
/// annot_pragma_openmp 'threadprivate' simple-variable-list
@@ -903,7 +919,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
- auto DKind = ParseOpenMPDirectiveKind(*this);
+ OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
// Name of critical directive.
DeclarationNameInfo DirName;
@@ -936,7 +952,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
}
case OMPD_declare_reduction:
ConsumeToken();
- if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
+ if (DeclGroupPtrTy Res =
+ ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -947,8 +964,9 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
}
ConsumeAnyToken();
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
- } else
+ } else {
SkipUntil(tok::annot_pragma_openmp_end);
+ }
break;
case OMPD_flush:
if (PP.LookAhead(0).is(tok::l_paren)) {
@@ -1027,7 +1045,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
T.consumeClose();
}
} else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
- CancelRegion = ParseOpenMPDirectiveKind(*this);
+ CancelRegion = parseOpenMPDirectiveKind(*this);
if (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeToken();
}
@@ -1080,21 +1098,18 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
StmtResult AssociatedStmt;
if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
- Sema::CompoundScopeRAII CompoundScope(Actions);
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
- Actions.ActOnStartOfCompoundStmt();
- // Parse statement
- AssociatedStmt = ParseStatement();
- Actions.ActOnFinishOfCompoundStmt();
+ // FIXME: We create a bogus CompoundStmt scope to hold the contents of
+ // the captured region. Code elsewhere assumes that any FunctionScopeInfo
+ // should have at least one compound statement scope within it.
+ AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
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 = (Sema::CompoundScopeRAII(Actions),
+ Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
+ /*isStmtExpr=*/false));
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
}
Directive = Actions.ActOnOpenMPExecutableDirective(
@@ -1110,7 +1125,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
case OMPD_declare_target:
case OMPD_end_declare_target:
Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(DKind);
+ << 1 << getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
break;
case OMPD_unknown:
@@ -1141,7 +1156,6 @@ bool Parser::ParseOpenMPSimpleVarList(
// Read tokens while ')' or annot_pragma_openmp_end is not found.
while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
UnqualifiedId Name;
// Read var name.
Token PrevTok = Tok;
@@ -1153,7 +1167,7 @@ bool Parser::ParseOpenMPSimpleVarList(
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
} else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
- TemplateKWLoc, Name)) {
+ nullptr, Name)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@@ -1185,7 +1199,7 @@ bool Parser::ParseOpenMPSimpleVarList(
return !IsCorrect;
}
-/// \brief Parsing of OpenMP clauses.
+/// Parsing of OpenMP clauses.
///
/// clause:
/// if-clause | final-clause | num_threads-clause | safelen-clause |
@@ -1205,11 +1219,13 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
OMPClause *Clause = nullptr;
bool ErrorFound = false;
+ bool WrongDirective = false;
// Check if clause is allowed for the given directive.
if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
<< getOpenMPDirectiveName(DKind);
ErrorFound = true;
+ WrongDirective = true;
}
switch (CKind) {
@@ -1253,9 +1269,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
}
if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
- Clause = ParseOpenMPClause(CKind);
+ Clause = ParseOpenMPClause(CKind, WrongDirective);
else
- Clause = ParseOpenMPSingleExprClause(CKind);
+ Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
break;
case OMPC_default:
case OMPC_proc_bind:
@@ -1270,7 +1286,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
ErrorFound = true;
}
- Clause = ParseOpenMPSimpleClause(CKind);
+ Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
break;
case OMPC_schedule:
case OMPC_dist_schedule:
@@ -1287,7 +1303,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
LLVM_FALLTHROUGH;
case OMPC_if:
- Clause = ParseOpenMPSingleExprWithArgClause(CKind);
+ Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
break;
case OMPC_nowait:
case OMPC_untied:
@@ -1310,7 +1326,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
ErrorFound = true;
}
- Clause = ParseOpenMPClause(CKind);
+ Clause = ParseOpenMPClause(CKind, WrongDirective);
break;
case OMPC_private:
case OMPC_firstprivate:
@@ -1330,7 +1346,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
- Clause = ParseOpenMPVarListClause(DKind, CKind);
+ Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
case OMPC_unknown:
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
@@ -1339,8 +1355,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
break;
case OMPC_threadprivate:
case OMPC_uniform:
- Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
- << getOpenMPDirectiveName(DKind);
+ if (!WrongDirective)
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
}
@@ -1363,13 +1380,14 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
// Parse ')'.
- T.consumeClose();
+ RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
- RLoc = T.getCloseLocation();
return Val;
}
-/// \brief Parsing of OpenMP clauses with single expressions like 'final',
+/// Parsing of OpenMP clauses with single expressions like 'final',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
///
@@ -1400,7 +1418,8 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
/// hint-clause:
/// 'hint' '(' expression ')'
///
-OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
+OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ bool ParseOnly) {
SourceLocation Loc = ConsumeToken();
SourceLocation LLoc = Tok.getLocation();
SourceLocation RLoc;
@@ -1410,10 +1429,12 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
if (Val.isInvalid())
return nullptr;
+ if (ParseOnly)
+ return nullptr;
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
}
-/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
+/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
/// 'default' '(' 'none' | 'shared' ')
@@ -1421,7 +1442,8 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
/// proc_bind-clause:
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
///
-OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
+OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
+ bool ParseOnly) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
// Parse '('.
@@ -1438,13 +1460,16 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
ConsumeAnyToken();
// Parse ')'.
- T.consumeClose();
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
- return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
- Tok.getLocation());
+ if (ParseOnly)
+ return nullptr;
+ return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
}
-/// \brief Parsing of OpenMP clauses like 'ordered'.
+/// Parsing of OpenMP clauses like 'ordered'.
///
/// ordered-clause:
/// 'ordered'
@@ -1470,15 +1495,17 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
/// nogroup-clause:
/// 'nogroup'
///
-OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
+OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
SourceLocation Loc = Tok.getLocation();
ConsumeAnyToken();
+ if (ParseOnly)
+ return nullptr;
return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
}
-/// \brief Parsing of OpenMP clauses with single expressions and some additional
+/// Parsing of OpenMP clauses with single expressions and some additional
/// argument like 'schedule' or 'dist_schedule'.
///
/// schedule-clause:
@@ -1491,7 +1518,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
/// defaultmap:
/// 'defaultmap' '(' modifier ':' kind ')'
///
-OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
+OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
+ bool ParseOnly) {
SourceLocation Loc = ConsumeToken();
SourceLocation DelimLoc;
// Parse '('.
@@ -1510,7 +1538,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
- auto KindModifier = getOpenMPSimpleClauseType(
+ unsigned KindModifier = getOpenMPSimpleClauseType(
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
if (KindModifier > OMPC_SCHEDULE_unknown) {
// Parse 'modifier'
@@ -1583,7 +1611,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation());
TentativeParsingAction TPA(*this);
- Arg.push_back(ParseOpenMPDirectiveKind(*this));
+ Arg.push_back(parseOpenMPDirectiveKind(*this));
if (Arg.back() != OMPD_unknown) {
ConsumeToken();
if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
@@ -1593,8 +1621,9 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
TPA.Revert();
Arg.back() = OMPD_unknown;
}
- } else
+ } else {
TPA.Revert();
+ }
}
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
@@ -1608,19 +1637,21 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
}
// Parse ')'.
- T.consumeClose();
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
if (NeedAnExpression && Val.isInvalid())
return nullptr;
+ if (ParseOnly)
+ return nullptr;
return Actions.ActOnOpenMPSingleExprWithArgClause(
- Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
- T.getCloseLocation());
+ Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
}
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
UnqualifiedId &ReductionId) {
- SourceLocation TemplateKWLoc;
if (ReductionIdScopeSpec.isEmpty()) {
auto OOK = OO_None;
switch (P.getCurToken().getKind()) {
@@ -1662,7 +1693,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/*AllowDestructorName*/ false,
/*AllowConstructorName*/ false,
/*AllowDeductionGuide*/ false,
- nullptr, TemplateKWLoc, ReductionId);
+ nullptr, nullptr, ReductionId);
}
/// Parses clauses with list.
@@ -1724,9 +1755,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
return false;
}
}
- if (Tok.is(tok::colon))
+ if (Tok.is(tok::colon)) {
Data.ColonLoc = ConsumeToken();
- else {
+ } else {
Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
: diag::warn_pragma_expected_colon)
<< "dependency type";
@@ -1775,8 +1806,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Data.MapTypeModifier != OMPC_MAP_always) {
Diag(Tok, diag::err_omp_unknown_map_type_modifier);
Data.MapTypeModifier = OMPC_MAP_unknown;
- } else
+ } else {
MapTypeModifierSpecified = true;
+ }
ConsumeToken();
ConsumeToken();
@@ -1800,8 +1832,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Data.MapTypeModifier != OMPC_MAP_always) {
Diag(Tok, diag::err_omp_unknown_map_type_modifier);
Data.MapTypeModifier = OMPC_MAP_unknown;
- } else
+ } else {
MapTypeModifierSpecified = true;
+ }
ConsumeToken();
@@ -1848,9 +1881,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// Parse variable
ExprResult VarExpr =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
- if (VarExpr.isUsable())
+ if (VarExpr.isUsable()) {
Vars.push_back(VarExpr.get());
- else {
+ } else {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
}
@@ -1886,16 +1919,16 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
// Parse ')'.
- T.consumeClose();
- if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
- Vars.empty()) ||
- (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
- (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
- return true;
- return false;
+ Data.RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ Data.RLoc = T.getCloseLocation();
+ return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
+ Vars.empty()) ||
+ (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
+ (MustHaveTail && !Data.TailExpr) || InvalidReductionId;
}
-/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
+/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
/// 'in_reduction'.
///
@@ -1940,7 +1973,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// modifier(list)
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
- OpenMPClauseKind Kind) {
+ OpenMPClauseKind Kind,
+ bool ParseOnly) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
SmallVector<Expr *, 4> Vars;
@@ -1949,8 +1983,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
return nullptr;
+ if (ParseOnly)
+ return nullptr;
return Actions.ActOnOpenMPVarListClause(
- Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
+ Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc,
Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
Data.DepLinMapLoc);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
index 198d5c6e9cb0..07f48e0779dc 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -95,6 +95,44 @@ struct PragmaFPContractHandler : public PragmaHandler {
Token &FirstToken) override;
};
+// Pragma STDC implementations.
+
+/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
+struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
+ PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) override {
+ tok::OnOffSwitch OOS;
+ if (PP.LexOnOffSwitch(OOS))
+ return;
+ if (OOS == tok::OOS_ON)
+ PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
+ }
+};
+
+/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
+struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
+ PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) override {
+ tok::OnOffSwitch OOS;
+ PP.LexOnOffSwitch(OOS);
+ }
+};
+
+/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
+struct PragmaSTDC_UnknownHandler : public PragmaHandler {
+ PragmaSTDC_UnknownHandler() = default;
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &UnknownTok) override {
+ // C99 6.10.6p2, unknown forms are not allowed.
+ PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
+ }
+};
+
struct PragmaFPHandler : public PragmaHandler {
PragmaFPHandler() : PragmaHandler("fp") {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
@@ -182,6 +220,12 @@ struct PragmaMSIntrinsicHandler : public PragmaHandler {
Token &FirstToken) override;
};
+struct PragmaMSOptimizeHandler : public PragmaHandler {
+ PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler(Sema &Actions)
: PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
@@ -233,6 +277,15 @@ void Parser::initializePragmaHandlers() {
FPContractHandler.reset(new PragmaFPContractHandler());
PP.AddPragmaHandler("STDC", FPContractHandler.get());
+ STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler());
+ PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
+
+ STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler());
+ PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
+
+ STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler());
+ PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
+
PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
PP.AddPragmaHandler("clang", PCSectionHandler.get());
@@ -248,7 +301,8 @@ void Parser::initializePragmaHandlers() {
OpenMPHandler.reset(new PragmaNoOpenMPHandler());
PP.AddPragmaHandler(OpenMPHandler.get());
- if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
+ if (getLangOpts().MicrosoftExt ||
+ getTargetInfo().getTriple().isOSBinFormatELF()) {
MSCommentHandler.reset(new PragmaCommentHandler(Actions));
PP.AddPragmaHandler(MSCommentHandler.get());
}
@@ -276,6 +330,8 @@ void Parser::initializePragmaHandlers() {
PP.AddPragmaHandler(MSRuntimeChecks.get());
MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
PP.AddPragmaHandler(MSIntrinsic.get());
+ MSOptimize.reset(new PragmaMSOptimizeHandler());
+ PP.AddPragmaHandler(MSOptimize.get());
}
if (getLangOpts().CUDA) {
@@ -330,7 +386,8 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler(OpenMPHandler.get());
OpenMPHandler.reset();
- if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
+ if (getLangOpts().MicrosoftExt ||
+ getTargetInfo().getTriple().isOSBinFormatELF()) {
PP.RemovePragmaHandler(MSCommentHandler.get());
MSCommentHandler.reset();
}
@@ -361,6 +418,8 @@ void Parser::resetPragmaHandlers() {
MSRuntimeChecks.reset();
PP.RemovePragmaHandler(MSIntrinsic.get());
MSIntrinsic.reset();
+ PP.RemovePragmaHandler(MSOptimize.get());
+ MSOptimize.reset();
}
if (getLangOpts().CUDA) {
@@ -371,6 +430,15 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
FPContractHandler.reset();
+ PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
+ STDCFENVHandler.reset();
+
+ PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
+ STDCCXLIMITHandler.reset();
+
+ PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
+ STDCUnknownHandler.reset();
+
PP.RemovePragmaHandler("clang", OptimizeHandler.get());
OptimizeHandler.reset();
@@ -390,7 +458,7 @@ void Parser::resetPragmaHandlers() {
AttributePragmaHandler.reset();
}
-/// \brief Handle the annotation token produced for #pragma unused(...)
+/// Handle the annotation token produced for #pragma unused(...)
///
/// Each annot_pragma_unused is followed by the argument token so e.g.
/// "#pragma unused(x,y)" becomes:
@@ -451,8 +519,10 @@ void Parser::HandlePragmaAlign() {
Sema::PragmaOptionsAlignKind Kind =
static_cast<Sema::PragmaOptionsAlignKind>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
+ Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
+ // Consume the token after processing the pragma to enable pragma-specific
+ // #include warnings.
+ ConsumeAnnotationToken();
}
void Parser::HandlePragmaDump() {
@@ -1175,7 +1245,7 @@ bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
namespace {
-/// Describes the stage at which attribute subject rule parsing was interruped.
+/// Describes the stage at which attribute subject rule parsing was interrupted.
enum class MissingAttributeSubjectRulesRecoveryPoint {
Comma,
ApplyTo,
@@ -1201,7 +1271,7 @@ getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
/// suggests the possible attribute subject rules in a fix-it together with
/// any other missing tokens.
DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
- unsigned DiagID, AttributeList &Attribute,
+ unsigned DiagID, ParsedAttr &Attribute,
MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
SourceLocation Loc = PRef.getEndOfPreviousToken();
if (Loc.isInvalid())
@@ -1301,12 +1371,11 @@ void Parser::HandlePragmaAttribute() {
if (Tok.isNot(tok::l_paren))
Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_GNU);
+ ParsedAttr::AS_GNU);
else
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
/*ScopeName=*/nullptr,
- /*ScopeLoc=*/SourceLocation(),
- AttributeList::AS_GNU,
+ /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
/*Declarator=*/nullptr);
if (ExpectAndConsume(tok::r_paren))
@@ -1320,9 +1389,9 @@ void Parser::HandlePragmaAttribute() {
if (Tok.getIdentifierInfo()) {
// If we suspect that this is an attribute suggest the use of
// '__attribute__'.
- if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
- AttributeList::AS_GNU) !=
- AttributeList::UnknownAttribute) {
+ if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
+ ParsedAttr::AS_GNU) !=
+ ParsedAttr::UnknownAttribute) {
SourceLocation InsertStartLoc = Tok.getLocation();
ConsumeToken();
if (Tok.is(tok::l_paren)) {
@@ -1340,26 +1409,26 @@ void Parser::HandlePragmaAttribute() {
return;
}
- if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
+ if (Attrs.empty() || Attrs.begin()->isInvalid()) {
SkipToEnd();
return;
}
// Ensure that we don't have more than one attribute.
- if (Attrs.getList()->getNext()) {
- SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
+ if (Attrs.size() > 1) {
+ SourceLocation Loc = Attrs[1].getLoc();
Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
SkipToEnd();
return;
}
- if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
+ ParsedAttr &Attribute = *Attrs.begin();
+ if (!Attribute.isSupportedByPragmaAttribute()) {
Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
- << Attrs.getList()->getName();
+ << Attribute.getName();
SkipToEnd();
return;
}
- AttributeList &Attribute = *Attrs.getList();
// Parse the subject-list.
if (!TryConsumeToken(tok::comma)) {
@@ -1423,7 +1492,7 @@ void Parser::HandlePragmaAttribute() {
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
// 'pop'
-void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
+void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &VisTok) {
SourceLocation VisLoc = VisTok.getLocation();
@@ -1483,7 +1552,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
// pack '(' [integer] ')'
// pack '(' 'show' ')'
// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
-void PragmaPackHandler::HandlePragma(Preprocessor &PP,
+void PragmaPackHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &PackTok) {
SourceLocation PackLoc = PackTok.getLocation();
@@ -1594,7 +1663,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
// #pragma ms_struct on
// #pragma ms_struct off
-void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
+void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &MSStructTok) {
PragmaMSStructKind Kind = PMSST_OFF;
@@ -1617,7 +1686,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
return;
}
-
+
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< "ms_struct";
@@ -1748,20 +1817,20 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
}
-void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
+void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &AlignTok) {
ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
}
-void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
+void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &OptionsTok) {
ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
}
// #pragma unused(identifier)
-void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
+void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &UnusedTok) {
// FIXME: Should we be expanding macros here? My guess is no.
@@ -1842,7 +1911,7 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
// #pragma weak identifier
// #pragma weak identifier '=' identifier
-void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
+void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &WeakTok) {
SourceLocation WeakLoc = WeakTok.getLocation();
@@ -1901,7 +1970,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
}
// #pragma redefine_extname identifier identifier
-void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
+void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &RedefToken) {
SourceLocation RedefLoc = RedefToken.getLocation();
@@ -1946,7 +2015,7 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
void
-PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
+PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &Tok) {
tok::OnOffSwitch OOS;
@@ -1964,8 +2033,8 @@ PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
}
-void
-PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
+void
+PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &Tok) {
PP.LexUnexpandedToken(Tok);
@@ -2026,11 +2095,11 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
if (PP.getPPCallbacks())
- PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
+ PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
StateLoc, State);
}
-/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
+/// Handle '#pragma omp ...' when OpenMP is disabled.
///
void
PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
@@ -2045,7 +2114,7 @@ PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
PP.DiscardUntilEndOfDirective();
}
-/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
+/// Handle '#pragma omp ...' when OpenMP is enabled.
///
void
PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
@@ -2057,9 +2126,21 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
Tok.setKind(tok::annot_pragma_openmp);
Tok.setLocation(FirstTok.getLocation());
- while (Tok.isNot(tok::eod)) {
+ while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Pragma.push_back(Tok);
PP.Lex(Tok);
+ if (Tok.is(tok::annot_pragma_openmp)) {
+ PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
+ unsigned InnerPragmaCnt = 1;
+ while (InnerPragmaCnt != 0) {
+ PP.Lex(Tok);
+ if (Tok.is(tok::annot_pragma_openmp))
+ ++InnerPragmaCnt;
+ else if (Tok.is(tok::annot_pragma_openmp_end))
+ --InnerPragmaCnt;
+ }
+ PP.Lex(Tok);
+ }
}
SourceLocation EodLoc = Tok.getLocation();
Tok.startToken();
@@ -2073,7 +2154,7 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
/*DisableMacroExpansion=*/false);
}
-/// \brief Handle '#pragma pointers_to_members'
+/// Handle '#pragma pointers_to_members'
// The grammar for this pragma is as follows:
//
// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
@@ -2171,7 +2252,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
PP.EnterToken(AnnotTok);
}
-/// \brief Handle '#pragma vtordisp'
+/// Handle '#pragma vtordisp'
// The grammar for this pragma is as follows:
//
// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
@@ -2264,7 +2345,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
PP.EnterToken(AnnotTok);
}
-/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
+/// Handle all MS pragmas. Simply forwards the tokens after inserting
/// an annotation token.
void PragmaMSPragma::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
@@ -2282,7 +2363,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
TokenVector.push_back(Tok);
AnnotTok.setAnnotationEndLoc(Tok.getLocation());
}
- // Add a sentinal EoF token to the end of the list.
+ // Add a sentinel EoF token to the end of the list.
TokenVector.push_back(EoF);
// We must allocate this array with new because EnterTokenStream is going to
// delete it later.
@@ -2295,7 +2376,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
PP.EnterToken(AnnotTok);
}
-/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
+/// Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
/// \code
@@ -2352,7 +2433,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
}
-/// \brief Handle the microsoft \#pragma comment extension.
+/// Handle the microsoft \#pragma comment extension.
///
/// The syntax is:
/// \code
@@ -2393,6 +2474,12 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
return;
}
+ if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
+ << II->getName();
+ return;
+ }
+
// On PS4, issue a warning about any pragma comments other than
// #pragma comment lib.
if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
@@ -2436,7 +2523,7 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
// #pragma clang optimize off
// #pragma clang optimize on
-void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
+void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &FirstToken) {
Token Tok;
@@ -2462,7 +2549,7 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
return;
}
PP.Lex(Tok);
-
+
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
<< PP.getSpelling(Tok);
@@ -2595,7 +2682,7 @@ void Parser::HandlePragmaFP() {
ConsumeAnnotationToken();
}
-/// \brief Parses loop or unroll pragma hint value and fills in Info.
+/// Parses loop or unroll pragma hint value and fills in Info.
static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
Token Option, bool ValueInParens,
PragmaLoopHintInfo &Info) {
@@ -2637,7 +2724,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
return false;
}
-/// \brief Handle the \#pragma clang loop directive.
+/// Handle the \#pragma clang loop directive.
/// #pragma clang 'loop' loop-hints
///
/// loop-hints:
@@ -2752,7 +2839,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
/*DisableMacroExpansion=*/false);
}
-/// \brief Handle the loop unroll optimization pragmas.
+/// Handle the loop unroll optimization pragmas.
/// #pragma unroll
/// #pragma unroll unroll-hint-value
/// #pragma unroll '(' unroll-hint-value ')'
@@ -2822,7 +2909,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
/*DisableMacroExpansion=*/false);
}
-/// \brief Handle the Microsoft \#pragma intrinsic extension.
+/// Handle the Microsoft \#pragma intrinsic extension.
///
/// The syntax is:
/// \code
@@ -2871,6 +2958,61 @@ void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< "intrinsic";
}
+
+// #pragma optimize("gsty", on|off)
+void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation StartLoc = Tok.getLocation();
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::string_literal)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
+ return;
+ }
+ // We could syntax check the string but it's probably not worth the effort.
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::comma)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
+ << "optimize" << /*Expected=*/true << "'on' or 'off'";
+ return;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (!II || (!II->isStr("on") && !II->isStr("off"))) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
+ << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
+ << "'on' or 'off'";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "optimize";
+ return;
+ }
+ PP.Diag(StartLoc, diag::warn_pragma_optimize);
+}
+
void PragmaForceCUDAHostDeviceHandler::HandlePragma(
Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
Token FirstTok = Tok;
@@ -2895,7 +3037,7 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma(
diag::warn_pragma_force_cuda_host_device_bad_arg);
}
-/// \brief Handle the #pragma clang attribute directive.
+/// Handle the #pragma clang attribute directive.
///
/// The syntax is:
/// \code
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
index 09ae9d7f22f6..deb10af4b17b 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
@@ -12,13 +12,13 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/LoopHint.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
using namespace clang;
@@ -27,7 +27,7 @@ using namespace clang;
// C99 6.8: Statements and Blocks.
//===----------------------------------------------------------------------===//
-/// \brief Parse a standalone statement (for instance, as the body of an 'if',
+/// Parse a standalone statement (for instance, as the body of an 'if',
/// 'while', or 'for').
StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
bool AllowOpenMPStandalone) {
@@ -116,7 +116,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
if (Attrs.empty() || Res.isInvalid())
return Res;
- return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range);
+ return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range);
}
namespace {
@@ -402,7 +402,7 @@ Retry:
return Res;
}
-/// \brief Parse an expression statement.
+/// Parse an expression statement.
StmtResult Parser::ParseExprStatement() {
// If a case keyword is missing, this is where it should be inserted.
Token OldToken = Tok;
@@ -610,8 +610,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr,
TempAttrs);
if (!TempAttrs.empty() && !SubStmt.isInvalid())
- SubStmt = Actions.ProcessStmtAttributes(
- SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
+ SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs,
+ TempAttrs.Range);
} else {
Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
}
@@ -627,10 +627,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
IdentTok.getLocation());
- if (AttributeList *Attrs = attrs.getList()) {
- Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
- attrs.clear();
- }
+ Actions.ProcessDeclAttributeList(Actions.CurScope, LD, attrs);
+ attrs.clear();
return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
SubStmt.get());
@@ -687,20 +685,12 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
ExprResult LHS;
if (!MissingCase) {
- LHS = ParseConstantExpression();
- if (!getLangOpts().CPlusPlus11) {
- LHS = Actions.CorrectDelayedTyposInExpr(LHS, [this](class Expr *E) {
- return Actions.VerifyIntegerConstantExpression(E);
- });
- }
+ LHS = ParseCaseExpression(CaseLoc);
if (LHS.isInvalid()) {
// If constant-expression is parsed unsuccessfully, recover by skipping
// current case statement (moving to the colon that ends it).
- if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
- TryConsumeToken(tok::colon, ColonLoc);
- continue;
- }
- return StmtError();
+ if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
+ return StmtError();
}
} else {
LHS = Expr;
@@ -712,13 +702,10 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
ExprResult RHS;
if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
Diag(DotDotDotLoc, diag::ext_gnu_case_range);
- RHS = ParseConstantExpression();
+ RHS = ParseCaseExpression(CaseLoc);
if (RHS.isInvalid()) {
- if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
- TryConsumeToken(tok::colon, ColonLoc);
- continue;
- }
- return StmtError();
+ if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
+ return StmtError();
}
}
@@ -740,8 +727,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
}
StmtResult Case =
- Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc,
- RHS.get(), ColonLoc);
+ Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
// If we had a sema error parsing this case, then just ignore it and
// continue parsing the sub-stmt.
@@ -954,7 +940,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
if (T.consumeOpen())
return StmtError();
- Sema::CompoundScopeRAII CompoundScope(Actions);
+ Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
// Parse any pragmas at the beginning of the compound statement.
ParseCompoundStatementLeadingPragmas();
@@ -1196,7 +1182,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
{
EnterExpressionEvaluationContext PotentiallyDiscarded(
Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr,
- false,
+ Sema::ExpressionEvaluationContextRecord::EK_Other,
/*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition);
ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
}
@@ -1230,7 +1216,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
EnterExpressionEvaluationContext PotentiallyDiscarded(
Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr,
- false,
+ Sema::ExpressionEvaluationContextRecord::EK_Other,
/*ShouldEnter=*/ConstexprCondition && *ConstexprCondition);
ElseStmt = ParseStatement();
@@ -1621,9 +1607,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
attrs, attrs.Range.getEnd());
ForRange = true;
} else if (isForInitDeclaration()) { // for (int X = 4;
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
// Parse declaration, which eats the ';'.
- if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
+ if (!C99orCXXorObjC) { // Use of C99-style for loops in C90 mode?
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
+ Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
+ }
// In C++0x, "for (T NS:a" might not be a typo for ::
bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
@@ -1940,7 +1930,7 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
ArgsUnion(Hint.ValueExpr)};
TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr,
Hint.PragmaNameLoc->Loc, ArgHints, 4,
- AttributeList::AS_Pragma);
+ ParsedAttr::AS_Pragma);
}
// Get the next statement.
@@ -1957,7 +1947,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
- PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
"parsing function body");
// Save and reset current vtordisp stack if we have entered a C++ method body.
@@ -1990,7 +1980,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
- PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, TryLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
"parsing function try block");
// Constructor initializer list?
@@ -2265,7 +2255,7 @@ bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
if (Attrs.empty())
return true;
- if (Attrs.getList()->getKind() != AttributeList::AT_OpenCLUnrollHint)
+ if (Attrs.begin()->getKind() != ParsedAttr::AT_OpenCLUnrollHint)
return true;
if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
index d81029e27974..9b96c5150e56 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements parsing for GCC and Microsoft inline assembly.
+// This file implements parsing for GCC and Microsoft inline assembly.
//
//===----------------------------------------------------------------------===//
@@ -239,7 +239,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
/*AllowDeductionGuide=*/false,
- /*ObjectType=*/nullptr, TemplateKWLoc, Id);
+ /*ObjectType=*/nullptr, &TemplateKWLoc, Id);
// Perform the lookup.
Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id,
IsUnevaluatedContext);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 611c0779b160..063f7ccea320 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -21,27 +21,22 @@
#include "clang/Sema/Scope.h"
using namespace clang;
-/// \brief Parse a template declaration, explicit instantiation, or
+/// Parse a template declaration, explicit instantiation, or
/// explicit specialization.
-Decl *
-Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
- SourceLocation &DeclEnd,
- AccessSpecifier AS,
- AttributeList *AccessAttrs) {
+Decl *Parser::ParseDeclarationStartingWithTemplate(
+ DeclaratorContext Context, SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
ObjCDeclContextSwitch ObjCDC(*this);
-
+
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
- return ParseExplicitInstantiation(Context,
- SourceLocation(), ConsumeToken(),
- DeclEnd, AS);
+ return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(),
+ DeclEnd, AccessAttrs, AS);
}
- return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
- AccessAttrs);
+ return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs,
+ AS);
}
-
-
-/// \brief Parse a template declaration or an explicit specialization.
+/// Parse a template declaration or an explicit specialization.
///
/// Template declarations include one or more template parameter lists
/// and either the function or class template declaration. Explicit
@@ -56,11 +51,9 @@ Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
///
/// explicit-specialization: [ C++ temp.expl.spec]
/// 'template' '<' '>' declaration
-Decl *
-Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
- SourceLocation &DeclEnd,
- AccessSpecifier AS,
- AttributeList *AccessAttrs) {
+Decl *Parser::ParseTemplateDeclarationOrSpecialization(
+ DeclaratorContext Context, SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&
"Token does not start a template declaration.");
@@ -149,15 +142,13 @@ Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization);
// Parse the actual template declaration.
- return ParseSingleDeclarationAfterTemplate(Context,
- ParsedTemplateInfo(&ParamLists,
- isSpecialization,
- LastParamListWasEmpty),
- ParsingTemplateParams,
- DeclEnd, AS, AccessAttrs);
+ return ParseSingleDeclarationAfterTemplate(
+ Context,
+ ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty),
+ ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
}
-/// \brief Parse a single declaration that declares a template,
+/// Parse a single declaration that declares a template,
/// template specialization, or explicit instantiation of a template.
///
/// \param DeclEnd will receive the source location of the last token
@@ -167,14 +158,10 @@ Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
/// declaration. Will be AS_none for namespace-scope declarations.
///
/// \returns the new declaration.
-Decl *
-Parser::ParseSingleDeclarationAfterTemplate(
- DeclaratorContext Context,
- const ParsedTemplateInfo &TemplateInfo,
- ParsingDeclRAIIObject &DiagsFromTParams,
- SourceLocation &DeclEnd,
- AccessSpecifier AS,
- AttributeList *AccessAttrs) {
+Decl *Parser::ParseSingleDeclarationAfterTemplate(
+ DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
"Template information required");
@@ -373,7 +360,7 @@ bool
Parser::ParseTemplateParameterList(const unsigned Depth,
SmallVectorImpl<NamedDecl*> &TemplateParams) {
while (1) {
-
+
if (NamedDecl *TmpParam
= ParseTemplateParameter(Depth, TemplateParams.size())) {
TemplateParams.push_back(TmpParam);
@@ -403,7 +390,7 @@ Parser::ParseTemplateParameterList(const unsigned Depth,
return true;
}
-/// \brief Determine whether the parser is at the start of a template
+/// Determine whether the parser is at the start of a template
/// type parameter.
bool Parser::isStartOfTemplateTypeParameter() {
if (Tok.is(tok::kw_class)) {
@@ -416,23 +403,23 @@ bool Parser::isStartOfTemplateTypeParameter() {
case tok::greatergreater:
case tok::ellipsis:
return true;
-
+
case tok::identifier:
- // This may be either a type-parameter or an elaborated-type-specifier.
+ // This may be either a type-parameter or an elaborated-type-specifier.
// We have to look further.
break;
-
+
default:
return false;
}
-
+
switch (GetLookAheadToken(2).getKind()) {
case tok::equal:
case tok::comma:
case tok::greater:
case tok::greatergreater:
return true;
-
+
default:
return false;
}
@@ -477,7 +464,7 @@ bool Parser::isStartOfTemplateTypeParameter() {
/// 'class' identifier[opt] '=' type-id
/// 'typename' ...[opt] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
-/// 'template' '<' template-parameter-list '>'
+/// 'template' '<' template-parameter-list '>'
/// 'class' ...[opt] identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// = id-expression
@@ -488,6 +475,20 @@ NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
if (Tok.is(tok::kw_template))
return ParseTemplateTemplateParameter(Depth, Position);
+ // Is there just a typo in the input code? ('typedef' instead of 'typename')
+ if (Tok.is(tok::kw_typedef)) {
+ Diag(Tok.getLocation(), diag::err_expected_template_parameter);
+
+ Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
+ << FixItHint::CreateReplacement(CharSourceRange::getCharRange(
+ Tok.getLocation(), Tok.getEndLoc()),
+ "typename");
+
+ Tok.setKind(tok::kw_typename);
+
+ return ParseTypeParameter(Depth, Position);
+ }
+
// If it's none of the above, then it must be a parameter declaration.
// NOTE: This will pick up errors in the closure of the template parameter
// list (e.g., template < ; Check here to implement >> style closures.
@@ -616,7 +617,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
-
+
// Get the identifier, if given.
SourceLocation NameLoc;
IdentifierInfo *ParamName = nullptr;
@@ -651,16 +652,16 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
if (TryConsumeToken(tok::equal, EqualLoc)) {
DefaultArg = ParseTemplateTemplateArgument();
if (DefaultArg.isInvalid()) {
- Diag(Tok.getLocation(),
+ Diag(Tok.getLocation(),
diag::err_default_template_template_parameter_not_template);
SkipUntil(tok::comma, tok::greater, tok::greatergreater,
StopAtSemi | StopBeforeMatch);
}
}
-
+
return Actions.ActOnTemplateTemplateParameter(getCurScope(), TemplateLoc,
- ParamList, EllipsisLoc,
- ParamName, NameLoc, Depth,
+ ParamList, EllipsisLoc,
+ ParamName, NameLoc, Depth,
Position, EqualLoc, DefaultArg);
}
@@ -713,8 +714,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
}
// Create the parameter.
- return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,
- Depth, Position, EqualLoc,
+ return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,
+ Depth, Position, EqualLoc,
DefaultArg.get());
}
@@ -740,7 +741,7 @@ void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,
AlreadyHasEllipsis, D.hasName());
}
-/// \brief Parses a '>' at the end of a template list.
+/// Parses a '>' at the end of a template list.
///
/// If this function encounters '>>', '>>>', '>=', or '>>=', it tries
/// to determine if these tokens were supposed to be a '>' followed by
@@ -761,6 +762,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
// What will be left once we've consumed the '>'.
tok::TokenKind RemainingToken;
const char *ReplacementStr = "> >";
+ bool MergeWithNextToken = false;
switch (Tok.getKind()) {
default:
@@ -786,6 +788,15 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
case tok::greaterequal:
RemainingToken = tok::equal;
ReplacementStr = "> =";
+
+ // Join two adjacent '=' tokens into one, for cases like:
+ // void (*p)() = f<int>;
+ // return f<int>==p;
+ if (NextToken().is(tok::equal) &&
+ areTokensAdjacent(Tok, NextToken())) {
+ RemainingToken = tok::equalequal;
+ MergeWithNextToken = true;
+ }
break;
case tok::greatergreaterequal:
@@ -793,22 +804,35 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
break;
}
- // This template-id is terminated by a token which starts with a '>'. Outside
- // C++11, this is now error recovery, and in C++11, this is error recovery if
- // the token isn't '>>' or '>>>'.
- // '>>>' is for CUDA, where this sequence of characters is parsed into
- // tok::greatergreatergreater, rather than two separate tokens.
+ // This template-id is terminated by a token that starts with a '>'.
+ // Outside C++11 and Objective-C, this is now error recovery.
+ //
+ // C++11 allows this when the token is '>>', and in CUDA + C++11 mode, we
+ // extend that treatment to also apply to the '>>>' token.
//
- // We always allow this for Objective-C type parameter and type argument
- // lists.
- RAngleLoc = Tok.getLocation();
+ // Objective-C allows this in its type parameter / argument lists.
+
+ SourceLocation TokBeforeGreaterLoc = PrevTokLocation;
+ SourceLocation TokLoc = Tok.getLocation();
Token Next = NextToken();
+
+ // Whether splitting the current token after the '>' would undesirably result
+ // in the remaining token pasting with the token after it. This excludes the
+ // MergeWithNextToken cases, which we've already handled.
+ bool PreventMergeWithNextToken =
+ (RemainingToken == tok::greater ||
+ RemainingToken == tok::greatergreater) &&
+ (Next.isOneOf(tok::greater, tok::greatergreater,
+ tok::greatergreatergreater, tok::equal, tok::greaterequal,
+ tok::greatergreaterequal, tok::equalequal)) &&
+ areTokensAdjacent(Tok, Next);
+
+ // Diagnose this situation as appropriate.
if (!ObjCGenericList) {
- // The source range of the '>>' or '>=' at the start of the token.
- CharSourceRange ReplacementRange =
- CharSourceRange::getCharRange(RAngleLoc,
- Lexer::AdvanceToTokenCharacter(RAngleLoc, 2, PP.getSourceManager(),
- getLangOpts()));
+ // The source range of the replaced token(s).
+ CharSourceRange ReplacementRange = CharSourceRange::getCharRange(
+ TokLoc, Lexer::AdvanceToTokenCharacter(TokLoc, 2, PP.getSourceManager(),
+ getLangOpts()));
// A hint to put a space between the '>>'s. In order to make the hint as
// clear as possible, we include the characters either side of the space in
@@ -819,13 +843,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
// A hint to put another space after the token, if it would otherwise be
// lexed differently.
FixItHint Hint2;
- if ((RemainingToken == tok::greater ||
- RemainingToken == tok::greatergreater) &&
- (Next.isOneOf(tok::greater, tok::greatergreater,
- tok::greatergreatergreater, tok::equal,
- tok::greaterequal, tok::greatergreaterequal,
- tok::equalequal)) &&
- areTokensAdjacent(Tok, Next))
+ if (PreventMergeWithNextToken)
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
@@ -834,55 +852,68 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
else if (Tok.is(tok::greaterequal))
DiagId = diag::err_right_angle_bracket_equal_needs_space;
- Diag(Tok.getLocation(), DiagId) << Hint1 << Hint2;
+ Diag(TokLoc, DiagId) << Hint1 << Hint2;
}
+ // Find the "length" of the resulting '>' token. This is not always 1, as it
+ // can contain escaped newlines.
+ unsigned GreaterLength = Lexer::getTokenPrefixLength(
+ TokLoc, 1, PP.getSourceManager(), getLangOpts());
+
+ // Annotate the source buffer to indicate that we split the token after the
+ // '>'. This allows us to properly find the end of, and extract the spelling
+ // of, the '>' token later.
+ RAngleLoc = PP.SplitToken(TokLoc, GreaterLength);
+
// Strip the initial '>' from the token.
- Token PrevTok = Tok;
- if (RemainingToken == tok::equal && Next.is(tok::equal) &&
- areTokensAdjacent(Tok, Next)) {
- // Join two adjacent '=' tokens into one, for cases like:
- // void (*p)() = f<int>;
- // return f<int>==p;
+ bool CachingTokens = PP.IsPreviousCachedToken(Tok);
+
+ Token Greater = Tok;
+ Greater.setLocation(RAngleLoc);
+ Greater.setKind(tok::greater);
+ Greater.setLength(GreaterLength);
+
+ unsigned OldLength = Tok.getLength();
+ if (MergeWithNextToken) {
ConsumeToken();
- Tok.setKind(tok::equalequal);
- Tok.setLength(Tok.getLength() + 1);
- } else {
- Tok.setKind(RemainingToken);
- Tok.setLength(Tok.getLength() - 1);
+ OldLength += Tok.getLength();
}
- Tok.setLocation(Lexer::AdvanceToTokenCharacter(RAngleLoc, 1,
- PP.getSourceManager(),
- getLangOpts()));
-
- // The advance from '>>' to '>' in a ObjectiveC template argument list needs
- // to be properly reflected in the token cache to allow correct interaction
- // between annotation and backtracking.
- if (ObjCGenericList && PrevTok.getKind() == tok::greatergreater &&
- RemainingToken == tok::greater && PP.IsPreviousCachedToken(PrevTok)) {
- PrevTok.setKind(RemainingToken);
- PrevTok.setLength(1);
- // Break tok::greatergreater into two tok::greater but only add the second
- // one in case the client asks to consume the last token.
+
+ Tok.setKind(RemainingToken);
+ Tok.setLength(OldLength - GreaterLength);
+
+ // Split the second token if lexing it normally would lex a different token
+ // (eg, the fifth token in 'A<B>>>' should re-lex as '>', not '>>').
+ SourceLocation AfterGreaterLoc = TokLoc.getLocWithOffset(GreaterLength);
+ if (PreventMergeWithNextToken)
+ AfterGreaterLoc = PP.SplitToken(AfterGreaterLoc, Tok.getLength());
+ Tok.setLocation(AfterGreaterLoc);
+
+ // Update the token cache to match what we just did if necessary.
+ if (CachingTokens) {
+ // If the previous cached token is being merged, delete it.
+ if (MergeWithNextToken)
+ PP.ReplacePreviousCachedToken({});
+
if (ConsumeLastToken)
- PP.ReplacePreviousCachedToken({PrevTok, Tok});
+ PP.ReplacePreviousCachedToken({Greater, Tok});
else
- PP.ReplacePreviousCachedToken({PrevTok});
+ PP.ReplacePreviousCachedToken({Greater});
}
- if (!ConsumeLastToken) {
- // Since we're not supposed to consume the '>' token, we need to push
- // this token and revert the current token back to the '>'.
+ if (ConsumeLastToken) {
+ PrevTokLocation = RAngleLoc;
+ } else {
+ PrevTokLocation = TokBeforeGreaterLoc;
PP.EnterToken(Tok);
- Tok.setKind(tok::greater);
- Tok.setLength(1);
- Tok.setLocation(RAngleLoc);
+ Tok = Greater;
}
+
return false;
}
-/// \brief Parses a template-id that after the template name has
+/// Parses a template-id that after the template name has
/// already been parsed.
///
/// This routine takes care of parsing the enclosed template argument
@@ -924,7 +955,7 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,
/*ObjCGenericList=*/false);
}
-/// \brief Replace the tokens that form a simple-template-id with an
+/// Replace the tokens that form a simple-template-id with an
/// annotation token containing the complete template-id.
///
/// The first token in the stream must be the name of a template that
@@ -1014,7 +1045,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build a template-id annotation token that can be processed
// later.
Tok.setKind(tok::annot_template_id);
-
+
IdentifierInfo *TemplateII =
TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
? TemplateName.Identifier
@@ -1028,7 +1059,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
-
+
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
@@ -1045,7 +1076,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
return false;
}
-/// \brief Replaces a template-id annotation token with a type
+/// Replaces a template-id annotation token with a type
/// annotation token.
///
/// If there was a failure when forming the type from the template-id,
@@ -1090,12 +1121,12 @@ void Parser::AnnotateTemplateIdTokenAsType(bool IsClassName) {
PP.AnnotateCachedTokens(Tok);
}
-/// \brief Determine whether the given token can end a template argument.
+/// Determine whether the given token can end a template argument.
static bool isEndOfTemplateArgument(Token Tok) {
return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater);
}
-/// \brief Parse a C++ template template argument.
+/// Parse a C++ template template argument.
ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
!Tok.is(tok::annot_cxxscope))
@@ -1104,13 +1135,13 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
// C++0x [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be the name
// of a class template or an alias template, expressed as id-expression.
- //
+ //
// We parse an id-expression that refers to a class template or alias
// template. The grammar we parse is:
//
// nested-name-specifier[opt] template[opt] identifier ...[opt]
//
- // followed by a token that terminates a template argument, such as ',',
+ // followed by a token that terminates a template argument, such as ',',
// '>', or (in some cases) '>>'.
CXXScopeSpec SS; // nested-name-specifier, if present
ParseOptionalCXXScopeSpecifier(SS, nullptr,
@@ -1119,10 +1150,10 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
ParsedTemplateArgument Result;
SourceLocation EllipsisLoc;
if (SS.isSet() && Tok.is(tok::kw_template)) {
- // Parse the optional 'template' keyword following the
+ // Parse the optional 'template' keyword following the
// nested-name-specifier.
SourceLocation TemplateKWLoc = ConsumeToken();
-
+
if (Tok.is(tok::identifier)) {
// We appear to have a dependent template name.
UnqualifiedId Name;
@@ -1160,16 +1191,16 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
/*EnteringContext=*/false, Template, MemberOfUnknownSpecialization);
if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
// We have an id-expression that refers to a class template or
- // (C++0x) alias template.
+ // (C++0x) alias template.
Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
}
}
-
+
// If this is a pack expansion, build it as such.
if (EllipsisLoc.isValid() && !Result.isInvalid())
Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);
-
+
return Result;
}
@@ -1191,19 +1222,15 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
// argument before trying to disambiguate.
EnterExpressionEvaluationContext EnterConstantEvaluated(
- Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated,
+ /*LambdaContextDecl=*/nullptr,
+ /*ExprContext=*/Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
- SourceLocation Loc = Tok.getLocation();
TypeResult TypeArg = ParseTypeName(
- /*Range=*/nullptr, DeclaratorContext::TemplateTypeArgContext);
- if (TypeArg.isInvalid())
- return ParsedTemplateArgument();
-
- return ParsedTemplateArgument(ParsedTemplateArgument::Type,
- TypeArg.get().getAsOpaquePtr(),
- Loc);
+ /*Range=*/nullptr, DeclaratorContext::TemplateArgContext);
+ return Actions.ActOnTemplateTypeArgument(TypeArg);
}
-
+
// Try to parse a template template argument.
{
TentativeParsingAction TPA(*this);
@@ -1214,35 +1241,35 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
TPA.Commit();
return TemplateTemplateArgument;
}
-
+
// Revert this tentative parse to parse a non-type template argument.
TPA.Revert();
}
-
- // Parse a non-type template argument.
+
+ // Parse a non-type template argument.
SourceLocation Loc = Tok.getLocation();
ExprResult ExprArg = ParseConstantExpressionInExprEvalContext(MaybeTypeCast);
if (ExprArg.isInvalid() || !ExprArg.get())
return ParsedTemplateArgument();
- return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
+ return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
ExprArg.get(), Loc);
}
-/// \brief Determine whether the current tokens can only be parsed as a
-/// template argument list (starting with the '<') and never as a '<'
+/// Determine whether the current tokens can only be parsed as a
+/// template argument list (starting with the '<') and never as a '<'
/// expression.
bool Parser::IsTemplateArgumentList(unsigned Skip) {
struct AlwaysRevertAction : TentativeParsingAction {
AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }
~AlwaysRevertAction() { Revert(); }
} Tentative(*this);
-
+
while (Skip) {
ConsumeAnyToken();
--Skip;
}
-
+
// '<'
if (!TryConsumeToken(tok::less))
return false;
@@ -1250,11 +1277,11 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
// An empty template argument list.
if (Tok.is(tok::greater))
return true;
-
+
// See whether we have declaration specifiers, which indicate a type.
while (isCXXDeclarationSpecifier() == TPResult::True)
ConsumeAnyToken();
-
+
// If we have a '>' or a ',' then this is a template argument list.
return Tok.isOneOf(tok::greater, tok::comma);
}
@@ -1267,7 +1294,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
/// template-argument-list ',' template-argument
bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
-
+
ColonProtectionRAIIObject ColonProtection(*this, false);
do {
@@ -1283,7 +1310,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
// Save this template argument.
TemplateArgs.push_back(Arg);
-
+
// If the next token is a comma, consume it and keep reading
// arguments.
} while (TryConsumeToken(tok::comma));
@@ -1291,7 +1318,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
return false;
}
-/// \brief Parse a C++ explicit template instantiation
+/// Parse a C++ explicit template instantiation
/// (C++ [temp.explicit]).
///
/// explicit-instantiation:
@@ -1302,16 +1329,15 @@ Decl *Parser::ParseExplicitInstantiation(DeclaratorContext Context,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
AccessSpecifier AS) {
// This isn't really required here.
ParsingDeclRAIIObject
ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
- return ParseSingleDeclarationAfterTemplate(Context,
- ParsedTemplateInfo(ExternLoc,
- TemplateLoc),
- ParsingTemplateParams,
- DeclEnd, AS);
+ return ParseSingleDeclarationAfterTemplate(
+ Context, ParsedTemplateInfo(ExternLoc, TemplateLoc),
+ ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
}
SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {
@@ -1329,7 +1355,7 @@ void Parser::LateTemplateParserCallback(void *P, LateParsedTemplate &LPT) {
((Parser *)P)->ParseLateTemplatedFuncDef(LPT);
}
-/// \brief Late parse a C++ function template in Microsoft mode.
+/// Late parse a C++ function template in Microsoft mode.
void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
if (!LPT.D)
return;
@@ -1420,7 +1446,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
delete *I;
}
-/// \brief Lex a delayed template function for late parsing.
+/// Lex a delayed template function for late parsing.
void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {
tok::TokenKind kind = Tok.getKind();
if (!ConsumeAndStoreFunctionPrologue(Toks)) {
@@ -1436,3 +1462,111 @@ void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {
}
}
}
+
+/// We've parsed something that could plausibly be intended to be a template
+/// name (\p LHS) followed by a '<' token, and the following code can't possibly
+/// be an expression. Determine if this is likely to be a template-id and if so,
+/// diagnose it.
+bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) {
+ TentativeParsingAction TPA(*this);
+ // FIXME: We could look at the token sequence in a lot more detail here.
+ if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater,
+ StopAtSemi | StopBeforeMatch)) {
+ TPA.Commit();
+
+ SourceLocation Greater;
+ ParseGreaterThanInTemplateList(Greater, true, false);
+ Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS,
+ Less, Greater);
+ return true;
+ }
+
+ // There's no matching '>' token, this probably isn't supposed to be
+ // interpreted as a template-id. Parse it as an (ill-formed) comparison.
+ TPA.Revert();
+ return false;
+}
+
+void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) {
+ assert(Tok.is(tok::less) && "not at a potential angle bracket");
+
+ bool DependentTemplateName = false;
+ if (!Actions.mightBeIntendedToBeTemplateName(PotentialTemplateName,
+ DependentTemplateName))
+ return;
+
+ // OK, this might be a name that the user intended to be parsed as a
+ // template-name, followed by a '<' token. Check for some easy cases.
+
+ // If we have potential_template<>, then it's supposed to be a template-name.
+ if (NextToken().is(tok::greater) ||
+ (getLangOpts().CPlusPlus11 &&
+ NextToken().isOneOf(tok::greatergreater, tok::greatergreatergreater))) {
+ SourceLocation Less = ConsumeToken();
+ SourceLocation Greater;
+ ParseGreaterThanInTemplateList(Greater, true, false);
+ Actions.diagnoseExprIntendedAsTemplateName(
+ getCurScope(), PotentialTemplateName, Less, Greater);
+ // FIXME: Perform error recovery.
+ PotentialTemplateName = ExprError();
+ return;
+ }
+
+ // If we have 'potential_template<type-id', assume it's supposed to be a
+ // template-name if there's a matching '>' later on.
+ {
+ // FIXME: Avoid the tentative parse when NextToken() can't begin a type.
+ TentativeParsingAction TPA(*this);
+ SourceLocation Less = ConsumeToken();
+ if (isTypeIdUnambiguously() &&
+ diagnoseUnknownTemplateId(PotentialTemplateName, Less)) {
+ TPA.Commit();
+ // FIXME: Perform error recovery.
+ PotentialTemplateName = ExprError();
+ return;
+ }
+ TPA.Revert();
+ }
+
+ // Otherwise, remember that we saw this in case we see a potentially-matching
+ // '>' token later on.
+ AngleBracketTracker::Priority Priority =
+ (DependentTemplateName ? AngleBracketTracker::DependentName
+ : AngleBracketTracker::PotentialTypo) |
+ (Tok.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess
+ : AngleBracketTracker::NoSpaceBeforeLess);
+ AngleBrackets.add(*this, PotentialTemplateName.get(), Tok.getLocation(),
+ Priority);
+}
+
+bool Parser::checkPotentialAngleBracketDelimiter(
+ const AngleBracketTracker::Loc &LAngle, const Token &OpToken) {
+ // If a comma in an expression context is followed by a type that can be a
+ // template argument and cannot be an expression, then this is ill-formed,
+ // but might be intended to be part of a template-id.
+ if (OpToken.is(tok::comma) && isTypeIdUnambiguously() &&
+ diagnoseUnknownTemplateId(LAngle.TemplateName, LAngle.LessLoc)) {
+ AngleBrackets.clear(*this);
+ return true;
+ }
+
+ // If a context that looks like a template-id is followed by '()', then
+ // this is ill-formed, but might be intended to be a template-id
+ // followed by '()'.
+ if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) &&
+ NextToken().is(tok::r_paren)) {
+ Actions.diagnoseExprIntendedAsTemplateName(
+ getCurScope(), LAngle.TemplateName, LAngle.LessLoc,
+ OpToken.getLocation());
+ AngleBrackets.clear(*this);
+ return true;
+ }
+
+ // After a '>' (etc), we're no longer potentially in a construct that's
+ // intended to be treated as a template-id.
+ if (OpToken.is(tok::greater) ||
+ (getLangOpts().CPlusPlus11 &&
+ OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater)))
+ AngleBrackets.clear(*this);
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
index 5c206f4eab90..dfd1f8c3b2e6 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
@@ -80,10 +80,10 @@ bool Parser::isCXXDeclarationStatement() {
/// (if AllowForRangeDecl specified)
/// for ( for-range-declaration : for-range-initializer ) statement
///
-/// for-range-declaration:
+/// for-range-declaration:
/// decl-specifier-seq declarator
/// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
-///
+///
/// In any of the above cases there can be a preceding attribute-specifier-seq,
/// but the caller is expected to handle that.
bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
@@ -132,7 +132,7 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
// Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
// or an identifier which doesn't resolve as anything. We need tentative
// parsing...
-
+
{
RevertingTentativeParsingAction PA(*this);
TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
@@ -236,7 +236,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
///
/// (if AllowForRangeDecl specified)
/// for ( for-range-declaration : for-range-initializer ) statement
-/// for-range-declaration:
+/// for-range-declaration:
/// attribute-specifier-seqopt type-specifier-seq declarator
///
Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
@@ -401,7 +401,7 @@ struct Parser::ConditionDeclarationOrInitStatementState {
}
};
-/// \brief Disambiguates between a declaration in a condition, a
+/// Disambiguates between a declaration in a condition, a
/// simple-declaration in an init-statement, and an expression for
/// a condition of a if/switch statement.
///
@@ -472,7 +472,7 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) {
return ConditionOrInitStatement::Expression;
}
- /// \brief Determine whether the next set of tokens contains a type-id.
+ /// Determine whether the next set of tokens contains a type-id.
///
/// The context parameter states what context we're parsing right
/// now, which affects how this routine copes with the token
@@ -553,7 +553,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
return TPR == TPResult::True;
}
-/// \brief Returns true if this is a C++11 attribute-specifier. Per
+/// Returns true if this is a C++11 attribute-specifier. Per
/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
/// always introduce an attribute. In Objective-C++11, this rule does not
/// apply if either '[' begins a message-send.
@@ -873,7 +873,8 @@ Parser::TPResult Parser::TryParseOperatorId() {
/// template-id [TODO]
///
Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
- bool mayHaveIdentifier) {
+ bool mayHaveIdentifier,
+ bool mayHaveDirectInit) {
// declarator:
// direct-declarator
// ptr-operator declarator
@@ -930,6 +931,9 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
return TPResult::False;
}
+ if (mayHaveDirectInit)
+ return TPResult::Ambiguous;
+
while (1) {
TPResult TPR(TPResult::Ambiguous);
@@ -960,7 +964,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
return TPResult::Ambiguous;
}
-Parser::TPResult
+Parser::TPResult
Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
switch (Kind) {
// Obviously starts an expression.
@@ -1015,13 +1019,14 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___FUNCDNAME__:
case tok::kw___FUNCSIG__:
case tok::kw_L__FUNCTION__:
+ case tok::kw_L__FUNCSIG__:
case tok::kw___PRETTY_FUNCTION__:
case tok::kw___uuidof:
#define TYPE_TRAIT(N,Spelling,K) \
case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def"
return TPResult::True;
-
+
// Obviously starts a type-specifier-seq:
case tok::kw_char:
case tok::kw_const:
@@ -1048,6 +1053,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw_class:
case tok::kw_typename:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw__Decimal32:
@@ -1078,7 +1084,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
default:
break;
}
-
+
return TPResult::Ambiguous;
}
@@ -1242,6 +1248,17 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case ANK_TentativeDecl:
return TPResult::False;
case ANK_TemplateName:
+ // In C++17, this could be a type template for class template argument
+ // deduction. Try to form a type annotation for it. If we're in a
+ // template template argument, we'll undo this when checking the
+ // validity of the argument.
+ if (getLangOpts().CPlusPlus17) {
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error;
+ if (Tok.isNot(tok::identifier))
+ break;
+ }
+
// A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type.
return GreaterThanIsOperator ? TPResult::True : TPResult::False;
@@ -1321,7 +1338,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Debugger support
case tok::kw___unknown_anytype:
-
+
// type-specifier:
// simple-type-specifier
// class-specifier
@@ -1341,6 +1358,11 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// cv-qualifier
case tok::kw_const:
case tok::kw_volatile:
+ case tok::kw___private:
+ case tok::kw___local:
+ case tok::kw___global:
+ case tok::kw___constant:
+ case tok::kw___generic:
// GNU
case tok::kw_restrict:
@@ -1373,7 +1395,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Borland
case tok::kw___pascal:
return TPResult::True;
-
+
// AltiVec
case tok::kw___vector:
return TPResult::True;
@@ -1420,8 +1442,6 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
*HasMissingTypename = true;
return TPResult::Ambiguous;
}
-
- // FIXME: Fails to either revert or commit the tentative parse!
} else {
// Try to resolve the name. If it doesn't exist, assume it was
// intended to name a type and keep disambiguating.
@@ -1431,19 +1451,33 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case ANK_TentativeDecl:
return TPResult::False;
case ANK_TemplateName:
+ // In C++17, this could be a type template for class template
+ // argument deduction.
+ if (getLangOpts().CPlusPlus17) {
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error;
+ if (Tok.isNot(tok::identifier))
+ break;
+ }
+
// A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type.
- return GreaterThanIsOperator ? TPResult::True : TPResult::False;
+ // In C++17, this could be class template argument deduction.
+ return (getLangOpts().CPlusPlus17 || GreaterThanIsOperator)
+ ? TPResult::True
+ : TPResult::False;
case ANK_Unresolved:
return HasMissingTypename ? TPResult::Ambiguous
: TPResult::False;
case ANK_Success:
- // Annotated it, check again.
- assert(Tok.isNot(tok::annot_cxxscope) ||
- NextToken().isNot(tok::identifier));
- return isCXXDeclarationSpecifier(BracedCastResult,
- HasMissingTypename);
+ break;
}
+
+ // Annotated it, check again.
+ assert(Tok.isNot(tok::annot_cxxscope) ||
+ NextToken().isNot(tok::identifier));
+ return isCXXDeclarationSpecifier(BracedCastResult,
+ HasMissingTypename);
}
}
return TPResult::False;
@@ -1476,26 +1510,27 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Tentatively parse the protocol qualifiers.
RevertingTentativeParsingAction PA(*this);
ConsumeAnyToken(); // The type token
-
+
TPResult TPR = TryParseProtocolQualifiers();
bool isFollowedByParen = Tok.is(tok::l_paren);
bool isFollowedByBrace = Tok.is(tok::l_brace);
-
+
if (TPR == TPResult::Error)
return TPResult::Error;
-
+
if (isFollowedByParen)
return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult;
-
+
return TPResult::True;
}
LLVM_FALLTHROUGH;
-
+
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_bool:
@@ -1527,7 +1562,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
if (isStartOfObjCClassMessageMissingOpenBracket())
return TPResult::False;
-
+
return TPResult::True;
// GNU typeof support.
@@ -1587,6 +1622,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
// simple-type-specifier
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_bool:
@@ -1645,18 +1681,18 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() {
if (Tok.isNot(tok::identifier))
return TPResult::Error;
ConsumeToken();
-
+
if (Tok.is(tok::comma)) {
ConsumeToken();
continue;
}
-
+
if (Tok.is(tok::greater)) {
ConsumeToken();
return TPResult::Ambiguous;
}
} while (false);
-
+
return TPResult::Error;
}
@@ -1867,13 +1903,14 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
return TPResult::Error;
// cv-qualifier-seq
- while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict))
+ while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned,
+ tok::kw_restrict))
ConsumeToken();
// ref-qualifier[opt]
if (Tok.isOneOf(tok::amp, tok::ampamp))
ConsumeToken();
-
+
// exception-specification
if (Tok.is(tok::kw_throw)) {
ConsumeToken();
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index a6f966eda1b9..c3085654f529 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -20,11 +20,12 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
+#include "llvm/Support/Path.h"
using namespace clang;
namespace {
-/// \brief A comment handler that passes comments found by the preprocessor
+/// A comment handler that passes comments found by the preprocessor
/// to the parser action.
class ActionCommentHandler : public CommentHandler {
Sema &S;
@@ -40,7 +41,7 @@ public:
} // end anonymous namespace
IdentifierInfo *Parser::getSEHExceptKeyword() {
- // __except is accepted as a (contextual) keyword
+ // __except is accepted as a (contextual) keyword
if (!Ident__except && (getLangOpts().MicrosoftExt || getLangOpts().Borland))
Ident__except = PP.getIdentifierInfo("__except");
@@ -49,7 +50,7 @@ IdentifierInfo *Parser::getSEHExceptKeyword() {
Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
: PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true), ColonIsSacred(false),
+ GreaterThanIsOperator(true), ColonIsSacred(false),
InMessageExpression(false), TemplateParameterDepth(0),
ParsingInObjCContainer(false) {
SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
@@ -77,7 +78,7 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {
return Diag(Tok.getLocation(), DiagID);
}
-/// \brief Emits a diagnostic suggesting parentheses surrounding a
+/// Emits a diagnostic suggesting parentheses surrounding a
/// given range.
///
/// \param Loc The location where we'll emit the diagnostic.
@@ -160,8 +161,8 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
handleUnexpectedCodeCompletionToken();
return false;
}
-
- if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) &&
+
+ if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) &&
NextToken().is(tok::semi)) {
Diag(Tok, diag::err_extraneous_token_before_semi)
<< PP.getSpelling(Tok)
@@ -170,7 +171,7 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
ConsumeToken(); // The ';'.
return false;
}
-
+
return ExpectAndConsume(tok::semi, DiagID);
}
@@ -290,7 +291,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
if (!HasFlagsSet(Flags, StopAtCodeCompletion))
handleUnexpectedCodeCompletionToken();
return false;
-
+
case tok::l_paren:
// Recursively skip properly-nested parens.
ConsumeParen();
@@ -697,9 +698,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
return nullptr;
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
- SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
- attrs.getList(),
- Tok.getLocation());
+ SingleDecl =
+ Actions.ActOnEmptyDeclaration(getCurScope(), attrs, Tok.getLocation());
ConsumeExtraSemi(OutsideFunction);
break;
case tok::r_brace:
@@ -741,7 +741,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
break;
}
case tok::at:
- return ParseObjCAtDirectives();
+ return ParseObjCAtDirectives(attrs);
case tok::minus:
case tok::plus:
if (!getLangOpts().ObjC1) {
@@ -796,17 +796,17 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
goto dont_know;
-
+
case tok::kw_inline:
if (getLangOpts().CPlusPlus) {
tok::TokenKind NextKind = NextToken().getKind();
-
+
// Inline namespaces. Allowed as an extension even in C++03.
if (NextKind == tok::kw_namespace) {
SourceLocation DeclEnd;
return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
-
+
// Parse (then ignore) 'inline' prior to a template instantiation. This is
// a GCC extension that we intentionally do not support.
if (NextKind == tok::kw_template) {
@@ -828,8 +828,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc);
SourceLocation DeclEnd;
return Actions.ConvertDeclToDeclGroup(
- ParseExplicitInstantiation(DeclaratorContext::FileContext,
- ExternLoc, TemplateLoc, DeclEnd));
+ ParseExplicitInstantiation(DeclaratorContext::FileContext, ExternLoc,
+ TemplateLoc, DeclEnd, attrs));
}
goto dont_know;
@@ -858,7 +858,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
return Actions.ConvertDeclToDeclGroup(SingleDecl);
}
-/// \brief Determine whether the current token, if it occurs after a
+/// Determine whether the current token, if it occurs after a
/// declarator, continues a declaration or declaration list.
bool Parser::isDeclarationAfterDeclarator() {
// Check for '= delete' or '= default'
@@ -867,7 +867,7 @@ bool Parser::isDeclarationAfterDeclarator() {
if (KW.is(tok::kw_default) || KW.is(tok::kw_delete))
return false;
}
-
+
return Tok.is(tok::equal) || // int X()= -> not a function def
Tok.is(tok::comma) || // int X(), -> not a function def
Tok.is(tok::semi) || // int X(); -> not a function def
@@ -877,23 +877,23 @@ bool Parser::isDeclarationAfterDeclarator() {
Tok.is(tok::l_paren)); // int X(0) -> not a function def [C++]
}
-/// \brief Determine whether the current token, if it occurs after a
+/// Determine whether the current token, if it occurs after a
/// declarator, indicates the start of a function definition.
bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator");
if (Tok.is(tok::l_brace)) // int X() {}
return true;
-
+
// Handle K&R C argument lists: int X(f) int f; {}
if (!getLangOpts().CPlusPlus &&
- Declarator.getFunctionTypeInfo().isKNRPrototype())
+ Declarator.getFunctionTypeInfo().isKNRPrototype())
return isDeclarationSpecifier();
if (getLangOpts().CPlusPlus && Tok.is(tok::equal)) {
const Token &KW = NextToken();
return KW.is(tok::kw_default) || KW.is(tok::kw_delete);
}
-
+
return Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
Tok.is(tok::kw_try); // X() try { ... }
}
@@ -947,7 +947,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
default:
llvm_unreachable("we only expect to get the length of the class/struct/union/enum");
}
-
+
};
// Suggest correct location to fix '[[attrib]] struct' to 'struct [[attrib]]'
SourceLocation CorrectLocationForAttributes =
@@ -1072,7 +1072,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// We should have either an opening brace or, in a C++ constructor,
// we may have a colon.
- if (Tok.isNot(tok::l_brace) &&
+ if (Tok.isNot(tok::l_brace) &&
(!getLangOpts().CPlusPlus ||
(Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try) &&
Tok.isNot(tok::equal)))) {
@@ -1089,15 +1089,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Check to make sure that any normal attributes are allowed to be on
// a definition. Late parsed attributes are checked at the end.
if (Tok.isNot(tok::equal)) {
- AttributeList *DtorAttrs = D.getAttributes();
- while (DtorAttrs) {
- if (DtorAttrs->isKnownToGCC() &&
- !DtorAttrs->isCXX11Attribute()) {
- Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
- << DtorAttrs->getName();
- }
- DtorAttrs = DtorAttrs->getNext();
- }
+ for (const ParsedAttr &AL : D.getAttributes())
+ if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
+ Diag(AL.getLoc(), diag::warn_attribute_on_function_definition)
+ << AL.getName();
}
// In delayed template parsing mode, for function template we consume the
@@ -1133,10 +1128,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
}
return DP;
}
- else if (CurParsedObjCImpl &&
+ else if (CurParsedObjCImpl &&
!TemplateInfo.TemplateParams &&
(Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
- Tok.is(tok::colon)) &&
+ Tok.is(tok::colon)) &&
Actions.CurContext->isTranslationUnit()) {
ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
@@ -1176,7 +1171,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Break out of the ParsingDeclarator context before we parse the body.
D.complete(Res);
-
+
// Break out of the ParsingDeclSpec context, too. This const_cast is
// safe because we're always the sole owner.
D.getMutableDeclSpec().abort();
@@ -1451,7 +1446,7 @@ ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
return Result;
}
-/// \brief Get the TemplateIdAnnotation from the token and put it in the
+/// Get the TemplateIdAnnotation from the token and put it in the
/// cleanup pool so that it gets destroyed when parsing the current top level
/// declaration is finished.
TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) {
@@ -1479,7 +1474,7 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) {
PP.AnnotateCachedTokens(Tok);
}
-/// \brief Attempt to classify the name at the current token position. This may
+/// Attempt to classify the name at the current token position. This may
/// form a type, scope or primary expression annotation, or replace the token
/// with a typo-corrected keyword. This is only appropriate when the current
/// name must refer to an entity which has already been declared.
@@ -1715,7 +1710,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
TypeResult Ty;
if (Tok.is(tok::identifier)) {
// FIXME: check whether the next token is '<', first!
- Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
+ Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
*Tok.getIdentifierInfo(),
Tok.getLocation());
} else if (Tok.is(tok::annot_template_id)) {
@@ -1764,7 +1759,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation);
}
-/// \brief Try to annotate a type or scope token, having already parsed an
+/// Try to annotate a type or scope token, having already parsed an
/// optional scope specifier. \p IsNewScope should be \c true unless the scope
/// specifier was extracted from an existing tok::annot_cxxscope annotation.
bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
@@ -1775,8 +1770,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS,
false, NextToken().is(tok::period), nullptr,
/*IsCtorOrDtorName=*/false,
- /*NonTrivialTypeSourceInfo*/ true,
- /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) {
+ /*NonTrivialTypeSourceInfo*/true,
+ /*IsClassTemplateDeductionContext*/true)) {
SourceLocation BeginLoc = Tok.getLocation();
if (SS.isNotEmpty()) // it was a C++ qualified type name.
BeginLoc = SS.getBeginLoc();
@@ -1931,14 +1926,14 @@ SourceLocation Parser::handleUnexpectedCodeCompletionToken() {
cutOffParsing();
return PrevTokLocation;
}
-
+
if (S->getFlags() & Scope::ClassScope) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class);
cutOffParsing();
return PrevTokLocation;
}
}
-
+
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace);
cutOffParsing();
return PrevTokLocation;
@@ -1958,7 +1953,7 @@ void Parser::CodeCompleteMacroName(bool IsDefinition) {
Actions.CodeCompletePreprocessorMacroName(IsDefinition);
}
-void Parser::CodeCompletePreprocessorExpression() {
+void Parser::CodeCompletePreprocessorExpression() {
Actions.CodeCompletePreprocessorExpression();
}
@@ -1981,11 +1976,11 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
- Diag(Tok, diag::err_expected_lparen_after)
+ Diag(Tok, diag::err_expected_lparen_after)
<< (Result.IsIfExists? "__if_exists" : "__if_not_exists");
return true;
}
-
+
// Parse nested-name-specifier.
if (getLangOpts().CPlusPlus)
ParseOptionalCXXScopeSpecifier(Result.SS, nullptr,
@@ -2002,14 +1997,14 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
if (ParseUnqualifiedId(
Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true,
/*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr,
- TemplateKWLoc, Result.Name)) {
+ &TemplateKWLoc, Result.Name)) {
T.skipToEnd();
return true;
}
if (T.consumeClose())
return true;
-
+
// Check if the symbol exists.
switch (Actions.CheckMicrosoftIfExistsSymbol(getCurScope(), Result.KeywordLoc,
Result.IsIfExists, Result.SS,
@@ -2025,7 +2020,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
case Sema::IER_Dependent:
Result.Behavior = IEB_Dependent;
break;
-
+
case Sema::IER_Error:
return true;
}
@@ -2037,7 +2032,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
IfExistsCondition Result;
if (ParseMicrosoftIfExistsCondition(Result))
return;
-
+
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
Diag(Tok, diag::err_expected) << tok::l_brace;
@@ -2048,10 +2043,10 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
case IEB_Parse:
// Parse declarations below.
break;
-
+
case IEB_Dependent:
llvm_unreachable("Cannot have a dependent external declaration");
-
+
case IEB_Skip:
Braces.skipToEnd();
return;
@@ -2114,7 +2109,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
/// Parse a module import declaration. This is essentially the same for
/// Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC)
/// and the trailing optional attributes (in C++).
-///
+///
/// [ObjC] @import declaration:
/// '@' 'import' module-name ';'
/// [ModTS] module-import-declaration:
@@ -2123,9 +2118,10 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) {
assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
: Tok.isObjCAtKeyword(tok::objc_import)) &&
"Improper start to module import");
+ bool IsObjCAtImport = Tok.isObjCAtKeyword(tok::objc_import);
SourceLocation ImportLoc = ConsumeToken();
SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc;
-
+
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
if (ParseModuleName(ImportLoc, Path, /*IsImport*/true))
return nullptr;
@@ -2146,6 +2142,16 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) {
if (Import.isInvalid())
return nullptr;
+ // Using '@import' in framework headers requires modules to be enabled so that
+ // the header is parseable. Emit a warning to make the user aware.
+ if (IsObjCAtImport && AtLoc.isValid()) {
+ auto &SrcMgr = PP.getSourceManager();
+ auto *FE = SrcMgr.getFileEntryForID(SrcMgr.getFileID(AtLoc));
+ if (FE && llvm::sys::path::parent_path(FE->getDir()->getName())
+ .endswith(".framework"))
+ Diags.Report(AtLoc, diag::warn_atimport_in_framework_header);
+ }
+
return Import.get();
}
@@ -2168,12 +2174,12 @@ bool Parser::ParseModuleName(
cutOffParsing();
return true;
}
-
+
Diag(Tok, diag::err_module_expected_ident) << IsImport;
SkipUntil(tok::semi);
return true;
}
-
+
// Record this part of the module path.
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
ConsumeToken();
@@ -2185,7 +2191,7 @@ bool Parser::ParseModuleName(
}
}
-/// \brief Try recover parser when module annotation appears where it must not
+/// Try recover parser when module annotation appears where it must not
/// be found.
/// \returns false if the recover was successful and parsing may be continued, or
/// true if parser must bail out to top level and handle the token there.
@@ -2250,9 +2256,9 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
return true;
}
- if (getDepth() < MaxDepth)
+ if (getDepth() < P.getLangOpts().BracketDepth)
return false;
-
+
return diagnoseOverflow();
}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp b/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp
index 352fab077a2e..06f3b4fb4a66 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp
@@ -1,4 +1,4 @@
-//===--- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ----------------===//
+//===- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,8 +13,10 @@
#include "clang/Rewrite/Core/DeltaTree.h"
#include "clang/Basic/LLVM.h"
-#include <cstdio>
+#include "llvm/Support/Casting.h"
+#include <cassert>
#include <cstring>
+
using namespace clang;
/// The DeltaTree class is a multiway search tree (BTree) structure with some
@@ -33,6 +35,7 @@ using namespace clang;
/// full delta implied by a whole subtree in constant time.
namespace {
+
/// SourceDelta - As code in the original input buffer is added and deleted,
/// SourceDelta records are used to keep track of how the input SourceLocation
/// object is mapped into the output buffer.
@@ -47,7 +50,7 @@ namespace {
return Delta;
}
};
-
+
/// DeltaTreeNode - The common part of all nodes.
///
class DeltaTreeNode {
@@ -56,7 +59,7 @@ namespace {
DeltaTreeNode *LHS, *RHS;
SourceDelta Split;
};
-
+
private:
friend class DeltaTreeInteriorNode;
@@ -67,12 +70,11 @@ namespace {
enum { WidthFactor = 8 };
/// Values - This tracks the SourceDelta's currently in this node.
- ///
SourceDelta Values[2*WidthFactor-1];
/// NumValuesUsed - This tracks the number of values this node currently
/// holds.
- unsigned char NumValuesUsed;
+ unsigned char NumValuesUsed = 0;
/// IsLeaf - This is true if this is a leaf of the btree. If false, this is
/// an interior node, and is actually an instance of DeltaTreeInteriorNode.
@@ -80,20 +82,22 @@ namespace {
/// FullDelta - This is the full delta of all the values in this node and
/// all children nodes.
- int FullDelta;
+ int FullDelta = 0;
+
public:
- DeltaTreeNode(bool isLeaf = true)
- : NumValuesUsed(0), IsLeaf(isLeaf), FullDelta(0) {}
+ DeltaTreeNode(bool isLeaf = true) : IsLeaf(isLeaf) {}
bool isLeaf() const { return IsLeaf; }
int getFullDelta() const { return FullDelta; }
bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
unsigned getNumValuesUsed() const { return NumValuesUsed; }
+
const SourceDelta &getValue(unsigned i) const {
assert(i < NumValuesUsed && "Invalid value #");
return Values[i];
}
+
SourceDelta &getValue(unsigned i) {
assert(i < NumValuesUsed && "Invalid value #");
return Values[i];
@@ -114,23 +118,24 @@ namespace {
void Destroy();
};
-} // end anonymous namespace
-namespace {
/// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
/// This class tracks them.
class DeltaTreeInteriorNode : public DeltaTreeNode {
+ friend class DeltaTreeNode;
+
DeltaTreeNode *Children[2*WidthFactor];
+
~DeltaTreeInteriorNode() {
for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
Children[i]->Destroy();
}
- friend class DeltaTreeNode;
+
public:
DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
DeltaTreeInteriorNode(const InsertResult &IR)
- : DeltaTreeNode(false /*nonleaf*/) {
+ : DeltaTreeNode(false /*nonleaf*/) {
Children[0] = IR.LHS;
Children[1] = IR.RHS;
Values[0] = IR.Split;
@@ -142,15 +147,16 @@ namespace {
assert(i < getNumValuesUsed()+1 && "Invalid child");
return Children[i];
}
+
DeltaTreeNode *getChild(unsigned i) {
assert(i < getNumValuesUsed()+1 && "Invalid child");
return Children[i];
}
- static inline bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
+ static bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
};
-}
+} // namespace
/// Destroy - A 'virtual' destructor.
void DeltaTreeNode::Destroy() {
@@ -166,7 +172,7 @@ void DeltaTreeNode::RecomputeFullDeltaLocally() {
int NewFullDelta = 0;
for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
NewFullDelta += Values[i].Delta;
- if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this))
+ if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this))
for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
NewFullDelta += IN->getChild(i)->getFullDelta();
FullDelta = NewFullDelta;
@@ -223,7 +229,7 @@ bool DeltaTreeNode::DoInsertion(unsigned FileIndex, int Delta,
}
// Otherwise, this is an interior node. Send the request down the tree.
- DeltaTreeInteriorNode *IN = cast<DeltaTreeInteriorNode>(this);
+ auto *IN = cast<DeltaTreeInteriorNode>(this);
if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
return false; // If there was space in the child, just return.
@@ -300,7 +306,7 @@ void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
// Create the new child node.
DeltaTreeNode *NewNode;
- if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
+ if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
// If this is an interior node, also move over 'WidthFactor' children
// into the new node.
DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode();
@@ -328,8 +334,6 @@ void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
InsertRes.Split = Values[WidthFactor-1];
}
-
-
//===----------------------------------------------------------------------===//
// DeltaTree Implementation
//===----------------------------------------------------------------------===//
@@ -340,7 +344,7 @@ void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
/// VerifyTree - Walk the btree performing assertions on various properties to
/// verify consistency. This is useful for debugging new changes to the tree.
static void VerifyTree(const DeltaTreeNode *N) {
- const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(N);
+ const auto *IN = dyn_cast<DeltaTreeInteriorNode>(N);
if (IN == 0) {
// Verify leaves, just ensure that FullDelta matches up and the elements
// are in proper order.
@@ -387,6 +391,7 @@ static DeltaTreeNode *getRoot(void *Root) {
DeltaTree::DeltaTree() {
Root = new DeltaTreeNode();
}
+
DeltaTree::DeltaTree(const DeltaTree &RHS) {
// Currently we only support copying when the RHS is empty.
assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
@@ -407,7 +412,7 @@ int DeltaTree::getDeltaAt(unsigned FileIndex) const {
int Result = 0;
// Walk down the tree.
- while (1) {
+ while (true) {
// For all nodes, include any local deltas before the specified file
// index by summing them up directly. Keep track of how many were
// included.
@@ -423,7 +428,7 @@ int DeltaTree::getDeltaAt(unsigned FileIndex) const {
// If we have an interior node, include information about children and
// recurse. Otherwise, if we have a leaf, we're done.
- const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
+ const auto *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
if (!IN) return Result;
// Include any children to the left of the values we skipped, all of
@@ -461,4 +466,3 @@ void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
VerifyTree(MyRoot);
#endif
}
-
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
index 618c0179f100..12d7a16a2fc8 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
@@ -30,7 +30,8 @@ using namespace clang;
/// start/end tags are placed at the start/end of each line if the range is
/// multiline.
void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
- const char *StartTag, const char *EndTag) {
+ const char *StartTag, const char *EndTag,
+ bool IsTokenRange) {
SourceManager &SM = R.getSourceMgr();
B = SM.getExpansionLoc(B);
E = SM.getExpansionLoc(E);
@@ -41,13 +42,14 @@ void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
unsigned EOffset = SM.getFileOffset(E);
// Include the whole end token in the range.
- EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
+ if (IsTokenRange)
+ EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
bool Invalid = false;
const char *BufferStart = SM.getBufferData(FID, &Invalid).data();
if (Invalid)
return;
-
+
HighlightRange(R.getEditBuffer(FID), BOffset, EOffset,
BufferStart, StartTag, EndTag);
}
@@ -210,9 +212,9 @@ static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo,
SmallString<256> Str;
llvm::raw_svector_ostream OS(Str);
- OS << "<tr><td class=\"num\" id=\"LN"
- << LineNo << "\">"
- << LineNo << "</td><td class=\"line\">";
+ OS << "<tr class=\"codeline\" data-linenumber=\"" << LineNo << "\">"
+ << "<td class=\"num\" id=\"LN" << LineNo << "\">" << LineNo
+ << "</td><td class=\"line\">";
if (B == E) { // Handle empty lines.
OS << " </td></tr>";
@@ -263,7 +265,10 @@ void html::AddLineNumbers(Rewriter& R, FileID FID) {
}
// Add one big table tag that surrounds all of the code.
- RB.InsertTextBefore(0, "<table class=\"code\">\n");
+ std::string s;
+ llvm::raw_string_ostream os(s);
+ os << "<table class=\"code\" data-fileid=\"" << FID.getHashValue() << "\">\n";
+ RB.InsertTextBefore(0, os.str());
RB.InsertTextAfter(FileEnd - FileBeg, "</table>");
}
@@ -285,78 +290,128 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID,
if (!title.empty())
os << "<title>" << html::EscapeText(title) << "</title>\n";
- os << "<style type=\"text/css\">\n"
- " body { color:#000000; background-color:#ffffff }\n"
- " body { font-family:Helvetica, sans-serif; font-size:10pt }\n"
- " h1 { font-size:14pt }\n"
- " .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"
- " .comment { color: green; font-style: oblique }\n"
- " .keyword { color: blue }\n"
- " .string_literal { color: red }\n"
- " .directive { color: darkmagenta }\n"
- // Macro expansions.
- " .expansion { display: none; }\n"
- " .macro:hover .expansion { display: block; border: 2px solid #FF0000; "
- "padding: 2px; background-color:#FFF0F0; font-weight: normal; "
- " -webkit-border-radius:5px; -webkit-box-shadow:1px 1px 7px #000; "
- " border-radius:5px; box-shadow:1px 1px 7px #000; "
- "position: absolute; top: -1em; left:10em; z-index: 1 } \n"
- " .macro { color: darkmagenta; background-color:LemonChiffon;"
- // Macros are position: relative to provide base for expansions.
- " position: relative }\n"
- " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n"
- " .num { text-align:right; font-size:8pt }\n"
- " .num { color:#444444 }\n"
- " .line { padding-left: 1ex; border-left: 3px solid #ccc }\n"
- " .line { white-space: pre }\n"
- " .msg { -webkit-box-shadow:1px 1px 7px #000 }\n"
- " .msg { box-shadow:1px 1px 7px #000 }\n"
- " .msg { -webkit-border-radius:5px }\n"
- " .msg { border-radius:5px }\n"
- " .msg { font-family:Helvetica, sans-serif; font-size:8pt }\n"
- " .msg { float:left }\n"
- " .msg { padding:0.25em 1ex 0.25em 1ex }\n"
- " .msg { margin-top:10px; margin-bottom:10px }\n"
- " .msg { font-weight:bold }\n"
- " .msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }\n"
- " .msgT { padding:0x; spacing:0x }\n"
- " .msgEvent { background-color:#fff8b4; color:#000000 }\n"
- " .msgControl { background-color:#bbbbbb; color:#000000 }\n"
- " .msgNote { background-color:#ddeeff; color:#000000 }\n"
- " .mrange { background-color:#dfddf3 }\n"
- " .mrange { border-bottom:1px solid #6F9DBE }\n"
- " .PathIndex { font-weight: bold; padding:0px 5px; "
- "margin-right:5px; }\n"
- " .PathIndex { -webkit-border-radius:8px }\n"
- " .PathIndex { border-radius:8px }\n"
- " .PathIndexEvent { background-color:#bfba87 }\n"
- " .PathIndexControl { background-color:#8c8c8c }\n"
- " .PathNav a { text-decoration:none; font-size: larger }\n"
- " .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }\n"
- " .CodeRemovalHint { background-color:#de1010 }\n"
- " .CodeRemovalHint { border-bottom:1px solid #6F9DBE }\n"
- " .selected{ background-color:orange !important; }\n"
- " table.simpletable {\n"
- " padding: 5px;\n"
- " font-size:12pt;\n"
- " margin:20px;\n"
- " border-collapse: collapse; border-spacing: 0px;\n"
- " }\n"
- " td.rowname {\n"
- " text-align: right;\n"
- " vertical-align: top;\n"
- " font-weight: bold;\n"
- " color:#444444;\n"
- " padding-right:2ex;\n"
- " }\n"
- "</style>\n</head>\n<body>";
+ os << R"<<<(
+<style type="text/css">
+body { color:#000000; background-color:#ffffff }
+body { font-family:Helvetica, sans-serif; font-size:10pt }
+h1 { font-size:14pt }
+.FileName { margin-top: 5px; margin-bottom: 5px; display: inline; }
+.FileNav { margin-left: 5px; margin-right: 5px; display: inline; }
+.FileNav a { text-decoration:none; font-size: larger; }
+.divider { margin-top: 30px; margin-bottom: 30px; height: 15px; }
+.divider { background-color: gray; }
+.code { border-collapse:collapse; width:100%; }
+.code { font-family: "Monospace", monospace; font-size:10pt }
+.code { line-height: 1.2em }
+.comment { color: green; font-style: oblique }
+.keyword { color: blue }
+.string_literal { color: red }
+.directive { color: darkmagenta }
+/* Macro expansions. */
+.expansion { display: none; }
+.macro:hover .expansion {
+ display: block;
+ border: 2px solid #FF0000;
+ padding: 2px;
+ background-color:#FFF0F0;
+ font-weight: normal;
+ -webkit-border-radius:5px;
+ -webkit-box-shadow:1px 1px 7px #000;
+ border-radius:5px;
+ box-shadow:1px 1px 7px #000;
+ position: absolute;
+ top: -1em;
+ left:10em;
+ z-index: 1
+}
+
+#tooltiphint {
+ position: fixed;
+ width: 50em;
+ margin-left: -25em;
+ left: 50%;
+ padding: 10px;
+ border: 1px solid #b0b0b0;
+ border-radius: 2px;
+ box-shadow: 1px 1px 7px black;
+ background-color: #c0c0c0;
+ z-index: 2;
+}
+.macro {
+ color: darkmagenta;
+ background-color:LemonChiffon;
+ /* Macros are position: relative to provide base for expansions. */
+ position: relative;
+}
+
+.num { width:2.5em; padding-right:2ex; background-color:#eeeeee }
+.num { text-align:right; font-size:8pt }
+.num { color:#444444 }
+.line { padding-left: 1ex; border-left: 3px solid #ccc }
+.line { white-space: pre }
+.msg { -webkit-box-shadow:1px 1px 7px #000 }
+.msg { box-shadow:1px 1px 7px #000 }
+.msg { -webkit-border-radius:5px }
+.msg { border-radius:5px }
+.msg { font-family:Helvetica, sans-serif; font-size:8pt }
+.msg { float:left }
+.msg { padding:0.25em 1ex 0.25em 1ex }
+.msg { margin-top:10px; margin-bottom:10px }
+.msg { font-weight:bold }
+.msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }
+.msgT { padding:0x; spacing:0x }
+.msgEvent { background-color:#fff8b4; color:#000000 }
+.msgControl { background-color:#bbbbbb; color:#000000 }
+.msgNote { background-color:#ddeeff; color:#000000 }
+.mrange { background-color:#dfddf3 }
+.mrange { border-bottom:1px solid #6F9DBE }
+.PathIndex { font-weight: bold; padding:0px 5px; margin-right:5px; }
+.PathIndex { -webkit-border-radius:8px }
+.PathIndex { border-radius:8px }
+.PathIndexEvent { background-color:#bfba87 }
+.PathIndexControl { background-color:#8c8c8c }
+.PathNav a { text-decoration:none; font-size: larger }
+.CodeInsertionHint { font-weight: bold; background-color: #10dd10 }
+.CodeRemovalHint { background-color:#de1010 }
+.CodeRemovalHint { border-bottom:1px solid #6F9DBE }
+.selected{ background-color:orange !important; }
+
+table.simpletable {
+ padding: 5px;
+ font-size:12pt;
+ margin:20px;
+ border-collapse: collapse; border-spacing: 0px;
+}
+td.rowname {
+ text-align: right;
+ vertical-align: top;
+ font-weight: bold;
+ color:#444444;
+ padding-right:2ex;
+}
+
+/* Hidden text. */
+input.spoilerhider + label {
+ cursor: pointer;
+ text-decoration: underline;
+ display: block;
+}
+input.spoilerhider {
+ display: none;
+}
+input.spoilerhider ~ .spoiler {
+ overflow: hidden;
+ margin: 10px auto 0;
+ height: 0;
+ opacity: 0;
+}
+input.spoilerhider:checked + label + .spoiler{
+ height: auto;
+ opacity: 1;
+}
+</style>
+</head>
+<body>)<<<";
// Generate header
R.InsertTextBefore(StartLoc, os.str());
@@ -535,16 +590,15 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// Okay, we have the first token of a macro expansion: highlight the
// expansion by inserting a start tag before the macro expansion and
// end tag after it.
- std::pair<SourceLocation, SourceLocation> LLoc =
- SM.getExpansionRange(Tok.getLocation());
+ CharSourceRange LLoc = SM.getExpansionRange(Tok.getLocation());
// Ignore tokens whose instantiation location was not the main file.
- if (SM.getFileID(LLoc.first) != FID) {
+ if (SM.getFileID(LLoc.getBegin()) != FID) {
TmpPP.Lex(Tok);
continue;
}
- assert(SM.getFileID(LLoc.second) == FID &&
+ assert(SM.getFileID(LLoc.getEnd()) == FID &&
"Start and end of expansion must be in the same ultimate file!");
std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
@@ -559,7 +613,7 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// instantiation. It would be really nice to pop up a window with all the
// spelling of the tokens or something.
while (!Tok.is(tok::eof) &&
- SM.getExpansionLoc(Tok.getLocation()) == LLoc.first) {
+ SM.getExpansionLoc(Tok.getLocation()) == LLoc.getBegin()) {
// Insert a newline if the macro expansion is getting large.
if (LineLen > 60) {
Expansion += "<br>";
@@ -588,8 +642,8 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// highlighted.
Expansion = "<span class='expansion'>" + Expansion + "</span></span>";
- HighlightRange(R, LLoc.first, LLoc.second,
- "<span class='macro'>", Expansion.c_str());
+ HighlightRange(R, LLoc.getBegin(), LLoc.getEnd(), "<span class='macro'>",
+ Expansion.c_str(), LLoc.isTokenRange());
}
// Restore the preprocessor's old state.
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
index 030ab7732fc3..5bc79f3eddc9 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
@@ -1,4 +1,4 @@
-//===--- RewriteRope.cpp - Rope specialized for rewriter --------*- C++ -*-===//
+//===- RewriteRope.cpp - Rope specialized for rewriter --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,11 @@
#include "clang/Rewrite/Core/RewriteRope.h"
#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
#include <algorithm>
+#include <cassert>
+#include <cstring>
+
using namespace clang;
/// RewriteRope is a "strong" string class, designed to make insertions and
@@ -59,12 +63,12 @@ using namespace clang;
/// RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
/// up to '2*WidthFactor' other nodes in the tree.
+namespace {
//===----------------------------------------------------------------------===//
// RopePieceBTreeNode Class
//===----------------------------------------------------------------------===//
-namespace {
/// RopePieceBTreeNode - Common base class of RopePieceBTreeLeaf and
/// RopePieceBTreeInterior. This provides some 'virtual' dispatching methods
/// and a flag that determines which subclass the instance is. Also
@@ -82,13 +86,13 @@ namespace {
/// Size - This is the number of bytes of file this node (including any
/// potential children) covers.
- unsigned Size;
+ unsigned Size = 0;
/// IsLeaf - True if this is an instance of RopePieceBTreeLeaf, false if it
/// is an instance of RopePieceBTreeInterior.
bool IsLeaf;
- RopePieceBTreeNode(bool isLeaf) : Size(0), IsLeaf(isLeaf) {}
+ RopePieceBTreeNode(bool isLeaf) : IsLeaf(isLeaf) {}
~RopePieceBTreeNode() = default;
public:
@@ -116,15 +120,12 @@ namespace {
/// erase - Remove NumBytes from this node at the specified offset. We are
/// guaranteed that there is a split at Offset.
void erase(unsigned Offset, unsigned NumBytes);
-
};
-} // end anonymous namespace
//===----------------------------------------------------------------------===//
// RopePieceBTreeLeaf Class
//===----------------------------------------------------------------------===//
-namespace {
/// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
/// nodes. This directly represents a chunk of the string with those
/// RopePieces contatenated. Since this is a B+Tree, all values (in this case
@@ -135,18 +136,19 @@ namespace {
class RopePieceBTreeLeaf : public RopePieceBTreeNode {
/// NumPieces - This holds the number of rope pieces currently active in the
/// Pieces array.
- unsigned char NumPieces;
+ unsigned char NumPieces = 0;
/// Pieces - This tracks the file chunks currently in this leaf.
- ///
RopePiece Pieces[2*WidthFactor];
/// NextLeaf - This is a pointer to the next leaf in the tree, allowing
/// efficient in-order forward iteration of the tree without traversal.
- RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
+ RopePieceBTreeLeaf **PrevLeaf = nullptr;
+ RopePieceBTreeLeaf *NextLeaf = nullptr;
+
public:
- RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
- PrevLeaf(nullptr), NextLeaf(nullptr) {}
+ RopePieceBTreeLeaf() : RopePieceBTreeNode(true) {}
+
~RopePieceBTreeLeaf() {
if (PrevLeaf || NextLeaf)
removeFromLeafInOrder();
@@ -170,6 +172,7 @@ namespace {
}
const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
+
void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
assert(!PrevLeaf && !NextLeaf && "Already in ordering");
@@ -214,16 +217,16 @@ namespace {
/// node is returned and must be inserted into a parent.
RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
-
/// erase - Remove NumBytes from this node at the specified offset. We are
/// guaranteed that there is a split at Offset.
void erase(unsigned Offset, unsigned NumBytes);
- static inline bool classof(const RopePieceBTreeNode *N) {
+ static bool classof(const RopePieceBTreeNode *N) {
return N->isLeaf();
}
};
-} // end anonymous namespace
+
+} // namespace
/// split - Split the range containing the specified offset so that we are
/// guaranteed that there is a place to do an insertion at the specified
@@ -266,7 +269,6 @@ RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
return insert(Offset, Tail);
}
-
/// insert - Insert the specified RopePiece into this tree node at the
/// specified offset. The offset is relative, so "0" is the start of the node.
///
@@ -388,18 +390,21 @@ void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
//===----------------------------------------------------------------------===//
namespace {
+
/// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
/// which holds up to 2*WidthFactor pointers to child nodes.
class RopePieceBTreeInterior : public RopePieceBTreeNode {
/// NumChildren - This holds the number of children currently active in the
/// Children array.
- unsigned char NumChildren;
+ unsigned char NumChildren = 0;
+
RopePieceBTreeNode *Children[2*WidthFactor];
+
public:
- RopePieceBTreeInterior() : RopePieceBTreeNode(false), NumChildren(0) {}
+ RopePieceBTreeInterior() : RopePieceBTreeNode(false) {}
RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
- : RopePieceBTreeNode(false) {
+ : RopePieceBTreeNode(false) {
Children[0] = LHS;
Children[1] = RHS;
NumChildren = 2;
@@ -414,10 +419,12 @@ namespace {
bool isFull() const { return NumChildren == 2*WidthFactor; }
unsigned getNumChildren() const { return NumChildren; }
+
const RopePieceBTreeNode *getChild(unsigned i) const {
assert(i < NumChildren && "invalid child #");
return Children[i];
}
+
RopePieceBTreeNode *getChild(unsigned i) {
assert(i < NumChildren && "invalid child #");
return Children[i];
@@ -431,7 +438,6 @@ namespace {
Size += getChild(i)->size();
}
-
/// split - Split the range containing the specified offset so that we are
/// guaranteed that there is a place to do an insertion at the specified
/// offset. The offset is relative, so "0" is the start of the node.
@@ -440,7 +446,6 @@ namespace {
/// node is returned and must be inserted into a parent.
RopePieceBTreeNode *split(unsigned Offset);
-
/// insert - Insert the specified ropepiece into this tree node at the
/// specified offset. The offset is relative, so "0" is the start of the
/// node.
@@ -457,11 +462,12 @@ namespace {
/// guaranteed that there is a split at Offset.
void erase(unsigned Offset, unsigned NumBytes);
- static inline bool classof(const RopePieceBTreeNode *N) {
+ static bool classof(const RopePieceBTreeNode *N) {
return !N->isLeaf();
}
};
-} // end anonymous namespace
+
+} // namespace
/// split - Split the range containing the specified offset so that we are
/// guaranteed that there is a place to do an insertion at the specified
@@ -613,7 +619,7 @@ void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) {
//===----------------------------------------------------------------------===//
void RopePieceBTreeNode::Destroy() {
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
delete Leaf;
else
delete cast<RopePieceBTreeInterior>(this);
@@ -627,7 +633,7 @@ void RopePieceBTreeNode::Destroy() {
/// node is returned and must be inserted into a parent.
RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
assert(Offset <= size() && "Invalid offset to split!");
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
return Leaf->split(Offset);
return cast<RopePieceBTreeInterior>(this)->split(Offset);
}
@@ -641,7 +647,7 @@ RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
const RopePiece &R) {
assert(Offset <= size() && "Invalid offset to insert!");
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
return Leaf->insert(Offset, R);
return cast<RopePieceBTreeInterior>(this)->insert(Offset, R);
}
@@ -650,12 +656,11 @@ RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
/// guaranteed that there is a split at Offset.
void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
assert(Offset+NumBytes <= size() && "Invalid offset to erase!");
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
return Leaf->erase(Offset, NumBytes);
return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes);
}
-
//===----------------------------------------------------------------------===//
// RopePieceBTreeIterator Implementation
//===----------------------------------------------------------------------===//
@@ -666,10 +671,10 @@ static const RopePieceBTreeLeaf *getCN(const void *P) {
// begin iterator.
RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) {
- const RopePieceBTreeNode *N = static_cast<const RopePieceBTreeNode*>(n);
+ const auto *N = static_cast<const RopePieceBTreeNode *>(n);
// Walk down the left side of the tree until we get to a leaf.
- while (const RopePieceBTreeInterior *IN = dyn_cast<RopePieceBTreeInterior>(N))
+ while (const auto *IN = dyn_cast<RopePieceBTreeInterior>(N))
N = IN->getChild(0);
// We must have at least one leaf.
@@ -717,10 +722,12 @@ static RopePieceBTreeNode *getRoot(void *P) {
RopePieceBTree::RopePieceBTree() {
Root = new RopePieceBTreeLeaf();
}
+
RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) {
assert(RHS.empty() && "Can't copy non-empty tree yet");
Root = new RopePieceBTreeLeaf();
}
+
RopePieceBTree::~RopePieceBTree() {
getRoot(Root)->Destroy();
}
@@ -730,7 +737,7 @@ unsigned RopePieceBTree::size() const {
}
void RopePieceBTree::clear() {
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
Leaf->clear();
else {
getRoot(Root)->Destroy();
@@ -780,8 +787,7 @@ RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
// just allocate a new rope piece for it alone.
if (Len > AllocChunkSize) {
unsigned Size = End-Start+sizeof(RopeRefCountString)-1;
- RopeRefCountString *Res =
- reinterpret_cast<RopeRefCountString *>(new char[Size]);
+ auto *Res = reinterpret_cast<RopeRefCountString *>(new char[Size]);
Res->RefCount = 0;
memcpy(Res->Data, Start, End-Start);
return RopePiece(Res, 0, End-Start);
@@ -791,8 +797,7 @@ RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
// Make a new chunk and share it with later allocations.
unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
- RopeRefCountString *Res =
- reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
+ auto *Res = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
Res->RefCount = 0;
memcpy(Res->Data, Start, Len);
AllocBuffer = Res;
@@ -800,5 +805,3 @@ RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
return RopePiece(AllocBuffer, 0, Len);
}
-
-
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
index ae41decc64a3..a5421ec807b7 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
@@ -1,4 +1,4 @@
-//===--- Rewriter.cpp - Code rewriting interface --------------------------===//
+//===- Rewriter.cpp - Code rewriting interface ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,24 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
+#include "clang/Rewrite/Core/RewriteRope.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <iterator>
+#include <map>
+#include <memory>
+#include <system_error>
+#include <utility>
+
using namespace clang;
raw_ostream &RewriteBuffer::write(raw_ostream &os) const {
@@ -31,7 +44,7 @@ raw_ostream &RewriteBuffer::write(raw_ostream &os) const {
return os;
}
-/// \brief Return true if this character is non-new-line whitespace:
+/// Return true if this character is non-new-line whitespace:
/// ' ', '\\t', '\\f', '\\v', '\\r'.
static inline bool isWhitespaceExceptNL(unsigned char c) {
switch (c) {
@@ -75,7 +88,7 @@ void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
}
++posI;
}
-
+
unsigned lineSize = 0;
posI = curLineStart;
while (posI != end() && isWhitespaceExceptNL(*posI)) {
@@ -91,7 +104,6 @@ void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
void RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str,
bool InsertAfter) {
-
// Nothing to insert, exit early.
if (Str.empty()) return;
@@ -114,7 +126,6 @@ void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
}
-
//===----------------------------------------------------------------------===//
// Rewriter class
//===----------------------------------------------------------------------===//
@@ -127,10 +138,8 @@ int Rewriter::getRangeSize(const CharSourceRange &Range,
!isRewritable(Range.getEnd())) return -1;
FileID StartFileID, EndFileID;
- unsigned StartOff, EndOff;
-
- StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
- EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
+ unsigned StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
+ unsigned EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
if (StartFileID != EndFileID)
return -1;
@@ -145,7 +154,6 @@ int Rewriter::getRangeSize(const CharSourceRange &Range,
StartOff = RB.getMappedOffset(StartOff, !opts.IncludeInsertsAtBeginOfRange);
}
-
// Adjust the end offset to the end of the last token, instead of being the
// start of the last token if this is a token range.
if (Range.isTokenRange())
@@ -158,17 +166,15 @@ int Rewriter::getRangeSize(SourceRange Range, RewriteOptions opts) const {
return getRangeSize(CharSourceRange::getTokenRange(Range), opts);
}
-
/// getRewrittenText - Return the rewritten form of the text in the specified
/// range. If the start or end of the range was unrewritable or if they are
/// in different buffers, this returns an empty string.
///
/// Note that this method is not particularly efficient.
-///
std::string Rewriter::getRewrittenText(SourceRange Range) const {
if (!isRewritable(Range.getBegin()) ||
!isRewritable(Range.getEnd()))
- return "";
+ return {};
FileID StartFileID, EndFileID;
unsigned StartOff, EndOff;
@@ -176,7 +182,7 @@ std::string Rewriter::getRewrittenText(SourceRange Range) const {
EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
if (StartFileID != EndFileID)
- return ""; // Start and end in different buffers.
+ return {}; // Start and end in different buffers.
// If edits have been made to this buffer, the delta between the range may
// have changed.
@@ -212,14 +218,12 @@ std::string Rewriter::getRewrittenText(SourceRange Range) const {
unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
FileID &FID) const {
assert(Loc.isValid() && "Invalid location");
- std::pair<FileID,unsigned> V = SourceMgr->getDecomposedLoc(Loc);
+ std::pair<FileID, unsigned> V = SourceMgr->getDecomposedLoc(Loc);
FID = V.first;
return V.second;
}
-
/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
-///
RewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
std::map<FileID, RewriteBuffer>::iterator I =
RewriteBuffers.lower_bound(FID);
@@ -349,10 +353,10 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1;
unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1;
unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1;
-
+
const SrcMgr::ContentCache *
Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache();
-
+
// Find where the lines start.
unsigned parentLineOffs = Content->SourceLineCache[parentLineNo];
unsigned startLineOffs = Content->SourceLineCache[startLineNo];
@@ -393,6 +397,7 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
}
namespace {
+
// A wrapper for a file stream that atomically overwrites the target.
//
// Creates a file output stream for a temporary file in the constructor,
@@ -403,7 +408,7 @@ class AtomicallyMovedFile {
public:
AtomicallyMovedFile(DiagnosticsEngine &Diagnostics, StringRef Filename,
bool &AllWritten)
- : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
+ : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
TempFilename = Filename;
TempFilename += "-%%%%%%%%";
int FD;
@@ -441,7 +446,8 @@ private:
std::unique_ptr<llvm::raw_fd_ostream> FileStream;
bool &AllWritten;
};
-} // end anonymous namespace
+
+} // namespace
bool Rewriter::overwriteChangedFiles() {
bool AllWritten = true;
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp
index 494defdedaa9..1f5dec499c92 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp
@@ -1,4 +1,4 @@
-//===--- TokenRewriter.cpp - Token-based code rewriting interface ---------===//
+//===- TokenRewriter.cpp - Token-based code rewriting interface -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,6 +16,12 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/ScratchBuffer.h"
+#include "clang/Lex/Token.h"
+#include <cassert>
+#include <cstring>
+#include <map>
+#include <utility>
+
using namespace clang;
TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM,
@@ -46,9 +52,7 @@ TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM,
}
}
-TokenRewriter::~TokenRewriter() {
-}
-
+TokenRewriter::~TokenRewriter() = default;
/// RemapIterator - Convert from token_iterator (a const iterator) to
/// TokenRefTy (a non-const iterator).
@@ -63,7 +67,6 @@ TokenRewriter::TokenRefTy TokenRewriter::RemapIterator(token_iterator I) {
return MapIt->second;
}
-
/// AddToken - Add the specified token into the Rewriter before the other
/// position.
TokenRewriter::TokenRefTy
@@ -77,7 +80,6 @@ TokenRewriter::AddToken(const Token &T, TokenRefTy Where) {
return Where;
}
-
TokenRewriter::token_iterator
TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) {
unsigned Len = strlen(Val);
@@ -96,4 +98,3 @@ TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) {
return AddToken(Tok, RemapIterator(I));
}
-
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 0033edf326ac..ed240f4ed292 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -90,7 +90,7 @@ namespace {
}
S.Diag(L, diag) << R1 << R2;
-
+
SourceLocation Open = SilenceableCondVal.getBegin();
if (Open.isValid()) {
SourceLocation Close = SilenceableCondVal.getEnd();
@@ -122,7 +122,7 @@ static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
}
namespace {
-/// \brief Warn on logical operator errors in CFGBuilder
+/// Warn on logical operator errors in CFGBuilder
class LogicalErrorHandler : public CFGCallback {
Sema &S;
@@ -200,60 +200,41 @@ static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
return false;
}
-// All blocks are in one of three states. States are ordered so that blocks
-// can only move to higher states.
-enum RecursiveState {
- FoundNoPath,
- FoundPath,
- FoundPathWithNoRecursiveCall
-};
-
-// Returns true if there exists a path to the exit block and every path
-// to the exit block passes through a call to FD.
+// Returns true if every path from the entry block passes through a call to FD.
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
+ llvm::SmallPtrSet<CFGBlock *, 16> Visited;
+ llvm::SmallVector<CFGBlock *, 16> WorkList;
+ // Keep track of whether we found at least one recursive path.
+ bool foundRecursion = false;
const unsigned ExitID = cfg->getExit().getBlockID();
- // Mark all nodes as FoundNoPath, then set the status of the entry block.
- SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath);
- States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall;
+ // Seed the work list with the entry block.
+ WorkList.push_back(&cfg->getEntry());
- // Make the processing stack and seed it with the entry block.
- SmallVector<CFGBlock *, 16> Stack;
- Stack.push_back(&cfg->getEntry());
+ while (!WorkList.empty()) {
+ CFGBlock *Block = WorkList.pop_back_val();
- while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.back();
- Stack.pop_back();
-
- unsigned ID = CurBlock->getBlockID();
- RecursiveState CurState = States[ID];
-
- if (CurState == FoundPathWithNoRecursiveCall) {
- // Found a path to the exit node without a recursive call.
- if (ExitID == ID)
- return false;
+ for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
+ if (CFGBlock *SuccBlock = *I) {
+ if (!Visited.insert(SuccBlock).second)
+ continue;
- // Only change state if the block has a recursive call.
- if (hasRecursiveCallInPath(FD, *CurBlock))
- CurState = FoundPath;
- }
+ // Found a path to the exit node without a recursive call.
+ if (ExitID == SuccBlock->getBlockID())
+ return false;
- // Loop over successor blocks and add them to the Stack if their state
- // changes.
- for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
- if (*I) {
- unsigned next_ID = (*I)->getBlockID();
- if (States[next_ID] < CurState) {
- States[next_ID] = CurState;
- Stack.push_back(*I);
+ // If the successor block contains a recursive call, end analysis there.
+ if (hasRecursiveCallInPath(FD, *SuccBlock)) {
+ foundRecursion = true;
+ continue;
}
+
+ WorkList.push_back(SuccBlock);
}
+ }
}
-
- // Return true if the exit node is reachable, and only reachable through
- // a recursive call.
- return States[ExitID] == FoundPath;
+ return foundRecursion;
}
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
@@ -269,10 +250,6 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
CFG *cfg = AC.getCFG();
if (!cfg) return;
- // If the exit block is unreachable, skip processing the function.
- if (cfg->getExit().pred_empty())
- return;
-
// Emit diagnostic if a recursive function call is detected for all paths.
if (checkForRecursiveFunctionCall(FD, cfg))
S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
@@ -281,114 +258,62 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
//===----------------------------------------------------------------------===//
// Check for throw in a non-throwing function.
//===----------------------------------------------------------------------===//
-enum ThrowState {
- FoundNoPathForThrow,
- FoundPathForThrow,
- FoundPathWithNoThrowOutFunction,
-};
-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;
- if (ThrowType->isReferenceType())
- ThrowType = ThrowType->castAs<ReferenceType>()
- ->getPointeeType()
- ->getUnqualifiedDesugaredType();
- if (CaughtType->isReferenceType())
- CaughtType = CaughtType->castAs<ReferenceType>()
- ->getPointeeType()
- ->getUnqualifiedDesugaredType();
- if (ThrowType->isPointerType() && CaughtType->isPointerType()) {
- ThrowType = ThrowType->getPointeeType()->getUnqualifiedDesugaredType();
- CaughtType = CaughtType->getPointeeType()->getUnqualifiedDesugaredType();
- }
- if (CaughtType == ThrowType)
- return true;
- const CXXRecordDecl *CaughtAsRecordType =
- CaughtType->getAsCXXRecordDecl();
- const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl();
- if (CaughtAsRecordType && ThrowTypeAsRecordType)
- return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType);
- return false;
-}
+/// Determine whether an exception thrown by E, unwinding from ThrowBlock,
+/// can reach ExitBlock.
+static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock,
+ CFG *Body) {
+ SmallVector<CFGBlock *, 16> Stack;
+ llvm::BitVector Queued(Body->getNumBlockIDs());
-static bool isThrowCaughtByHandlers(const CXXThrowExpr *CE,
- const CXXTryStmt *TryStmt) {
- for (unsigned H = 0, E = TryStmt->getNumHandlers(); H < E; ++H) {
- if (isThrowCaught(CE, TryStmt->getHandler(H)))
- return true;
- }
- return false;
-}
+ Stack.push_back(&ThrowBlock);
+ Queued[ThrowBlock.getBlockID()] = true;
-static bool doesThrowEscapePath(CFGBlock Block, SourceLocation &OpLoc) {
- for (const auto &B : Block) {
- if (B.getKind() != CFGElement::Statement)
- continue;
- const auto *CE = dyn_cast<CXXThrowExpr>(B.getAs<CFGStmt>()->getStmt());
- if (!CE)
- continue;
+ while (!Stack.empty()) {
+ CFGBlock &UnwindBlock = *Stack.back();
+ Stack.pop_back();
- OpLoc = CE->getThrowLoc();
- for (const auto &I : Block.succs()) {
- if (!I.isReachable())
+ for (auto &Succ : UnwindBlock.succs()) {
+ if (!Succ.isReachable() || Queued[Succ->getBlockID()])
continue;
- if (const auto *Terminator =
- dyn_cast_or_null<CXXTryStmt>(I->getTerminator()))
- if (isThrowCaughtByHandlers(CE, Terminator))
- return false;
+
+ if (Succ->getBlockID() == Body->getExit().getBlockID())
+ return true;
+
+ if (auto *Catch =
+ dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
+ QualType Caught = Catch->getCaughtType();
+ if (Caught.isNull() || // catch (...) catches everything
+ !E->getSubExpr() || // throw; is considered cuaght by any handler
+ S.handlerCanCatch(Caught, E->getSubExpr()->getType()))
+ // Exception doesn't escape via this path.
+ break;
+ } else {
+ Stack.push_back(Succ);
+ Queued[Succ->getBlockID()] = true;
+ }
}
- return true;
}
+
return false;
}
-static bool hasThrowOutNonThrowingFunc(SourceLocation &OpLoc, CFG *BodyCFG) {
-
- unsigned ExitID = BodyCFG->getExit().getBlockID();
-
- SmallVector<ThrowState, 16> States(BodyCFG->getNumBlockIDs(),
- FoundNoPathForThrow);
- States[BodyCFG->getEntry().getBlockID()] = FoundPathWithNoThrowOutFunction;
-
- SmallVector<CFGBlock *, 16> Stack;
- Stack.push_back(&BodyCFG->getEntry());
- while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.pop_back_val();
-
- unsigned ID = CurBlock->getBlockID();
- ThrowState CurState = States[ID];
- if (CurState == FoundPathWithNoThrowOutFunction) {
- if (ExitID == ID)
+static void visitReachableThrows(
+ CFG *BodyCFG,
+ llvm::function_ref<void(const CXXThrowExpr *, CFGBlock &)> Visit) {
+ llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());
+ clang::reachable_code::ScanReachableFromBlock(&BodyCFG->getEntry(), Reachable);
+ for (CFGBlock *B : *BodyCFG) {
+ if (!Reachable[B->getBlockID()])
+ continue;
+ for (CFGElement &E : *B) {
+ Optional<CFGStmt> S = E.getAs<CFGStmt>();
+ if (!S)
continue;
-
- if (doesThrowEscapePath(*CurBlock, OpLoc))
- CurState = FoundPathForThrow;
+ if (auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
+ Visit(Throw, *B);
}
-
- // Loop over successor blocks and add them to the Stack if their state
- // changes.
- for (const auto &I : CurBlock->succs())
- if (I.isReachable()) {
- unsigned NextID = I->getBlockID();
- if (NextID == ExitID && CurState == FoundPathForThrow) {
- States[NextID] = CurState;
- } else if (States[NextID] < CurState) {
- States[NextID] = CurState;
- Stack.push_back(I);
- }
- }
}
- // Return true if the exit node is reachable, and only reachable through
- // a throw expression.
- return States[ExitID] == FoundPathForThrow;
}
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc,
@@ -405,7 +330,7 @@ static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc,
S.Diag(FD->getLocation(), diag::note_throw_in_dtor)
<< !isa<CXXDestructorDecl>(FD) << !Ty->hasExceptionSpec()
<< FD->getExceptionSpecSourceRange();
- } else
+ } else
S.Diag(FD->getLocation(), diag::note_throw_in_function)
<< FD->getExceptionSpecSourceRange();
}
@@ -418,14 +343,15 @@ static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD,
return;
if (BodyCFG->getExit().pred_empty())
return;
- SourceLocation OpLoc;
- if (hasThrowOutNonThrowingFunc(OpLoc, BodyCFG))
- EmitDiagForCXXThrowInNonThrowingFunc(S, OpLoc, FD);
+ visitReachableThrows(BodyCFG, [&](const CXXThrowExpr *Throw, CFGBlock &Block) {
+ if (throwEscapes(S, Throw, Block, BodyCFG))
+ EmitDiagForCXXThrowInNonThrowingFunc(S, Throw->getThrowLoc(), FD);
+ });
}
static bool isNoexcept(const FunctionDecl *FD) {
const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (FPT->isNothrow(FD->getASTContext()) || FD->hasAttr<NoThrowAttr>())
+ if (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>())
return true;
return false;
}
@@ -491,9 +417,10 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
CFGBlock::FilterOptions FO;
FO.IgnoreDefaultsWithCoveredEnums = 1;
- for (CFGBlock::filtered_pred_iterator
- I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
- const CFGBlock& B = **I;
+ for (CFGBlock::filtered_pred_iterator I =
+ cfg->getExit().filtered_pred_start_end(FO);
+ I.hasMore(); ++I) {
+ const CFGBlock &B = **I;
if (!live[B.getBlockID()])
continue;
@@ -598,18 +525,18 @@ struct CheckFallThroughDiagnostics {
bool isVirtualMethod = false;
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
isVirtualMethod = Method->isVirtual();
-
+
// Don't suggest that template instantiations be marked "noreturn"
bool isTemplateInstantiation = false;
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
isTemplateInstantiation = Function->isTemplateInstantiation();
-
+
if (!isVirtualMethod && !isTemplateInstantiation)
D.diag_NeverFallThroughOrReturn =
diag::warn_suggest_noreturn_function;
else
D.diag_NeverFallThroughOrReturn = 0;
-
+
D.funMode = Function;
return D;
}
@@ -683,18 +610,19 @@ struct CheckFallThroughDiagnostics {
} // anonymous namespace
-/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// CheckFallThroughForBody - Check that we don't fall off the end of a
/// function that should return a value. Check that we don't fall off the end
/// of a noreturn function. We assume that functions and blocks not marked
/// noreturn will return.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
const BlockExpr *blkExpr,
- const CheckFallThroughDiagnostics& CD,
- AnalysisDeclContext &AC) {
+ const CheckFallThroughDiagnostics &CD,
+ AnalysisDeclContext &AC,
+ sema::FunctionScopeInfo *FSI) {
bool ReturnsVoid = false;
bool HasNoReturn = false;
- bool IsCoroutine = S.getCurFunction() && S.getCurFunction()->isCoroutine();
+ bool IsCoroutine = FSI->isCoroutine();
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -726,10 +654,15 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
if (IsCoroutine)
- S.Diag(Loc, DiagID) << S.getCurFunction()->CoroutinePromise->getType();
+ S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
else
S.Diag(Loc, DiagID);
};
+
+ // cpu_dispatch functions permit empty function bodies for ICC compatibility.
+ if (D->getAsFunction() && D->getAsFunction()->isCPUDispatchMultiVersion())
+ return;
+
// Either in a function body compound statement, or a function-try-block.
switch (CheckFallThrough(AC)) {
case UnknownFallThrough:
@@ -1293,7 +1226,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
bool PerFunction) {
// 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
+ // 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.
//
@@ -1461,8 +1394,8 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
// Sort by first use so that we emit the warnings in a deterministic order.
SourceManager &SM = S.getSourceManager();
- std::sort(UsesByStmt.begin(), UsesByStmt.end(),
- [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
+ llvm::sort(UsesByStmt.begin(), UsesByStmt.end(),
+ [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
RHS.first->getLocStart());
});
@@ -1559,7 +1492,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
// order of diagnostics when calling flushDiagnostics().
typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
UsesMap uses;
-
+
public:
UninitValsDiagReporter(Sema &S) : S(S) {}
~UninitValsDiagReporter() override { flushDiagnostics(); }
@@ -1575,11 +1508,11 @@ public:
const UninitUse &use) override {
getUses(vd).getPointer()->push_back(use);
}
-
+
void handleSelfInit(const VarDecl *vd) override {
getUses(vd).setInt(true);
}
-
+
void flushDiagnostics() {
for (const auto &P : uses) {
const VarDecl *vd = P.first;
@@ -1588,7 +1521,7 @@ public:
UsesVec *vec = V.getPointer();
bool hasSelfInit = V.getInt();
- // Specially handle the case where we have uses of an uninitialized
+ // Specially handle the case where we have uses of an uninitialized
// variable, but the root cause is an idiomatic self-init. We want
// to report the diagnostic at the self-init since that is the root cause.
if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
@@ -1600,8 +1533,8 @@ public:
// Sort the uses by their SourceLocations. While not strictly
// guaranteed to produce them in line/column order, this will provide
// a stable ordering.
- std::sort(vec->begin(), vec->end(),
- [](const UninitUse &a, const UninitUse &b) {
+ llvm::sort(vec->begin(), vec->end(),
+ [](const UninitUse &a, const UninitUse &b) {
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
@@ -1618,7 +1551,7 @@ public:
break;
}
}
-
+
// Release the uses vector.
delete vec;
}
@@ -1674,7 +1607,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
return OptionalNotes(1, FNote);
}
return OptionalNotes();
@@ -1685,7 +1618,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
ONS.push_back(std::move(FNote));
}
return ONS;
@@ -1699,7 +1632,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
ONS.push_back(std::move(FNote));
}
return ONS;
@@ -1723,7 +1656,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
void setVerbose(bool b) { Verbose = b; }
- /// \brief Emit all buffered diagnostics in order of sourcelocation.
+ /// Emit all buffered diagnostics in order of sourcelocation.
/// We need to output diagnostics produced while iterating through
/// the lockset in deterministic order, so this function orders diagnostics
/// and outputs them.
@@ -1815,7 +1748,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
diag::warn_variable_requires_any_lock:
diag::warn_var_deref_requires_any_lock;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << getLockKindFromAccessKind(AK));
+ << D << getLockKindFromAccessKind(AK));
Warnings.emplace_back(std::move(Warning), getNotes());
}
@@ -1843,7 +1776,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
- << D->getNameAsString()
+ << D
<< LockName << LK);
PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
<< *PossibleMatch);
@@ -1873,12 +1806,11 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
- << D->getNameAsString()
+ << D
<< LockName << LK);
if (Verbose && POK == POK_VarAccess) {
PartialDiagnosticAt Note(D->getLocation(),
- S.PDiag(diag::note_guarded_by_declared_here)
- << D->getNameAsString());
+ S.PDiag(diag::note_guarded_by_declared_here));
Warnings.emplace_back(std::move(Warning), getNotes(Note));
} else
Warnings.emplace_back(std::move(Warning), getNotes());
@@ -1933,10 +1865,10 @@ namespace clang {
namespace consumed {
namespace {
class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
-
+
Sema &S;
DiagList Warnings;
-
+
public:
ConsumedWarningsHandler(Sema &S) : S(S) {}
@@ -1957,28 +1889,28 @@ public:
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
-
+
void warnParamReturnTypestateMismatch(SourceLocation Loc,
StringRef VariableName,
StringRef ExpectedState,
StringRef ObservedState) override {
-
+
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_return_typestate_mismatch) << VariableName <<
ExpectedState << ObservedState);
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
-
+
void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
StringRef ObservedState) override {
-
+
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
-
+
void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
StringRef TypeName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
@@ -1986,28 +1918,28 @@ public:
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
-
+
void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
StringRef ObservedState) override {
-
+
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
-
+
void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
SourceLocation Loc) override {
-
+
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
-
+
void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
StringRef State, SourceLocation Loc) override {
-
+
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
MethodName << VariableName << State);
@@ -2095,7 +2027,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
flushDiagnostics(S, fscope);
return;
}
-
+
const Stmt *Body = D->getBody();
assert(Body);
@@ -2181,7 +2113,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (!analyzed)
flushDiagnostics(S, fscope);
}
-
+
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
const CheckFallThroughDiagnostics &CD =
@@ -2194,7 +2126,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
: (fscope->isCoroutine()
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
: CheckFallThroughDiagnostics::MakeForFunction(D)));
- CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
+ CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC, fscope);
}
// Warning: check for unreachable code
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index 3431ddcf70a2..8af54b993932 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -1,4 +1,4 @@
-//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
+//===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,21 +10,30 @@
// This file implements the CodeCompleteConsumer class.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang-c/Index.h"
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Sema/Scope.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Sema/Sema.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.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 <cstring>
-#include <functional>
+#include <cassert>
+#include <cstdint>
+#include <string>
using namespace clang;
@@ -33,14 +42,14 @@ using namespace clang;
//===----------------------------------------------------------------------===//
bool CodeCompletionContext::wantConstructorResults() const {
- switch (Kind) {
+ switch (CCKind) {
case CCC_Recovery:
case CCC_Statement:
case CCC_Expression:
case CCC_ObjCMessageReceiver:
case CCC_ParenthesizedExpression:
return true;
-
+
case CCC_TopLevel:
case CCC_ObjCInterface:
case CCC_ObjCImplementation:
@@ -76,12 +85,87 @@ bool CodeCompletionContext::wantConstructorResults() const {
llvm_unreachable("Invalid CodeCompletionContext::Kind!");
}
+StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) {
+ using CCKind = CodeCompletionContext::Kind;
+ switch (Kind) {
+ case CCKind::CCC_Other:
+ return "Other";
+ case CCKind::CCC_OtherWithMacros:
+ return "OtherWithMacros";
+ case CCKind::CCC_TopLevel:
+ return "TopLevel";
+ case CCKind::CCC_ObjCInterface:
+ return "ObjCInterface";
+ case CCKind::CCC_ObjCImplementation:
+ return "ObjCImplementation";
+ case CCKind::CCC_ObjCIvarList:
+ return "ObjCIvarList";
+ case CCKind::CCC_ClassStructUnion:
+ return "ClassStructUnion";
+ case CCKind::CCC_Statement:
+ return "Statement";
+ case CCKind::CCC_Expression:
+ return "Expression";
+ case CCKind::CCC_ObjCMessageReceiver:
+ return "ObjCMessageReceiver";
+ case CCKind::CCC_DotMemberAccess:
+ return "DotMemberAccess";
+ case CCKind::CCC_ArrowMemberAccess:
+ return "ArrowMemberAccess";
+ case CCKind::CCC_ObjCPropertyAccess:
+ return "ObjCPropertyAccess";
+ case CCKind::CCC_EnumTag:
+ return "EnumTag";
+ case CCKind::CCC_UnionTag:
+ return "UnionTag";
+ case CCKind::CCC_ClassOrStructTag:
+ return "ClassOrStructTag";
+ case CCKind::CCC_ObjCProtocolName:
+ return "ObjCProtocolName";
+ case CCKind::CCC_Namespace:
+ return "Namespace";
+ case CCKind::CCC_Type:
+ return "Type";
+ case CCKind::CCC_Name:
+ return "Name";
+ case CCKind::CCC_PotentiallyQualifiedName:
+ return "PotentiallyQualifiedName";
+ case CCKind::CCC_MacroName:
+ return "MacroName";
+ case CCKind::CCC_MacroNameUse:
+ return "MacroNameUse";
+ case CCKind::CCC_PreprocessorExpression:
+ return "PreprocessorExpression";
+ case CCKind::CCC_PreprocessorDirective:
+ return "PreprocessorDirective";
+ case CCKind::CCC_NaturalLanguage:
+ return "NaturalLanguage";
+ case CCKind::CCC_SelectorName:
+ return "SelectorName";
+ case CCKind::CCC_TypeQualifiers:
+ return "TypeQualifiers";
+ case CCKind::CCC_ParenthesizedExpression:
+ return "ParenthesizedExpression";
+ case CCKind::CCC_ObjCInstanceMessage:
+ return "ObjCInstanceMessage";
+ case CCKind::CCC_ObjCClassMessage:
+ return "ObjCClassMessage";
+ case CCKind::CCC_ObjCInterfaceName:
+ return "ObjCInterfaceName";
+ case CCKind::CCC_ObjCCategoryName:
+ return "ObjCCategoryName";
+ case CCKind::CCC_Recovery:
+ return "Recovery";
+ }
+ llvm_unreachable("Invalid CodeCompletionContext::Kind!");
+}
+
//===----------------------------------------------------------------------===//
// Code completion string implementation
//===----------------------------------------------------------------------===//
-CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
- : Kind(Kind), Text("")
-{
+
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
+ : Kind(Kind), Text("") {
switch (Kind) {
case CK_TypedText:
case CK_Text:
@@ -94,7 +178,7 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
case CK_Optional:
llvm_unreachable("Optional strings cannot be created from text");
-
+
case CK_LeftParen:
this->Text = "(";
break;
@@ -106,11 +190,11 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
case CK_LeftBracket:
this->Text = "[";
break;
-
+
case CK_RightBracket:
this->Text = "]";
break;
-
+
case CK_LeftBrace:
this->Text = "{";
break;
@@ -122,11 +206,11 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
case CK_LeftAngle:
this->Text = "<";
break;
-
+
case CK_RightAngle:
this->Text = ">";
break;
-
+
case CK_Comma:
this->Text = ", ";
break;
@@ -158,7 +242,7 @@ CodeCompletionString::Chunk::CreateText(const char *Text) {
return Chunk(CK_Text, Text);
}
-CodeCompletionString::Chunk
+CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
Chunk Result;
Result.Kind = CK_Optional;
@@ -166,39 +250,38 @@ CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
return Result;
}
-CodeCompletionString::Chunk
+CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
return Chunk(CK_Placeholder, Placeholder);
}
-CodeCompletionString::Chunk
+CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
return Chunk(CK_Informative, Informative);
}
-CodeCompletionString::Chunk
+CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
return Chunk(CK_ResultType, ResultType);
}
-CodeCompletionString::Chunk
+CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateCurrentParameter(
const char *CurrentParameter) {
return Chunk(CK_CurrentParameter, CurrentParameter);
}
-CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
+CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
unsigned NumChunks,
- unsigned Priority,
+ unsigned Priority,
CXAvailabilityKind Availability,
const char **Annotations,
unsigned NumAnnotations,
StringRef ParentName,
const char *BriefComment)
- : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
- Priority(Priority), Availability(Availability),
- ParentName(ParentName), BriefComment(BriefComment)
-{
+ : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
+ Priority(Priority), Availability(Availability),
+ ParentName(ParentName), BriefComment(BriefComment) {
assert(NumChunks <= 0xffff);
assert(NumAnnotations <= 0xffff);
@@ -222,21 +305,20 @@ const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
return nullptr;
}
-
std::string CodeCompletionString::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
-
+
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
switch (C->Kind) {
case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
-
- case CK_Informative:
+
+ case CK_Informative:
case CK_ResultType:
- OS << "[#" << C->Text << "#]";
+ OS << "[#" << C->Text << "#]";
break;
-
+
case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
default: OS << C->Text; break;
}
@@ -267,8 +349,8 @@ const char *CodeCompletionAllocator::CopyString(const Twine &String) {
StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
if (!ND)
- return StringRef();
-
+ return {};
+
// Check whether we've already cached the parent name.
StringRef &CachedParentName = ParentNames[DC];
if (!CachedParentName.empty())
@@ -277,7 +359,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
// If we already processed this DeclContext and assigned empty to it, the
// data pointer will be non-null.
if (CachedParentName.data() != nullptr)
- return StringRef();
+ return {};
// Find the interesting names.
SmallVector<const DeclContext *, 2> Contexts;
@@ -286,7 +368,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
if (ND->getIdentifier())
Contexts.push_back(DC);
}
-
+
DC = DC->getParent();
}
@@ -300,26 +382,26 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
else {
OS << "::";
}
-
+
const DeclContext *CurDC = Contexts[I-1];
if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
CurDC = CatImpl->getCategoryDecl();
-
+
if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
const ObjCInterfaceDecl *Interface = Cat->getClassInterface();
if (!Interface) {
// Assign an empty StringRef but with non-null data to distinguish
// between empty because we didn't process the DeclContext yet.
CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0);
- return StringRef();
+ return {};
}
-
+
OS << Interface->getName() << '(' << Cat->getName() << ')';
} else {
OS << cast<NamedDecl>(CurDC)->getName();
}
}
-
+
CachedParentName = AllocatorRef->CopyString(OS.str());
}
@@ -331,7 +413,7 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() {
sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() +
sizeof(const char *) * Annotations.size(),
alignof(CodeCompletionString));
- CodeCompletionString *Result
+ CodeCompletionString *Result
= new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
Priority, Availability,
Annotations.data(), Annotations.size(),
@@ -375,17 +457,16 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
}
void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
- if (DC->isTranslationUnit()) {
+ if (DC->isTranslationUnit())
return;
- }
-
+
if (DC->isFunctionOrMethod())
return;
-
+
const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
if (!ND)
return;
-
+
ParentName = getCodeCompletionTUInfo().getParentName(DC);
}
@@ -411,11 +492,11 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
switch (Kind) {
case CK_Function:
return Function->getType()->getAs<FunctionType>();
-
+
case CK_FunctionTemplate:
return FunctionTemplate->getTemplatedDecl()->getType()
->getAs<FunctionType>();
-
+
case CK_FunctionType:
return Type;
}
@@ -427,35 +508,31 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
// Code completion consumer implementation
//===----------------------------------------------------------------------===//
-CodeCompleteConsumer::~CodeCompleteConsumer() { }
+CodeCompleteConsumer::~CodeCompleteConsumer() = default;
bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter,
CodeCompletionResult Result) {
switch (Result.Kind) {
- case CodeCompletionResult::RK_Declaration: {
+ case CodeCompletionResult::RK_Declaration:
return !(Result.Declaration->getIdentifier() &&
Result.Declaration->getIdentifier()->getName().startswith(Filter));
- }
- case CodeCompletionResult::RK_Keyword: {
+ case CodeCompletionResult::RK_Keyword:
return !StringRef(Result.Keyword).startswith(Filter);
- }
- case CodeCompletionResult::RK_Macro: {
+ case CodeCompletionResult::RK_Macro:
return !Result.Macro->getName().startswith(Filter);
- }
- case CodeCompletionResult::RK_Pattern: {
+ case CodeCompletionResult::RK_Pattern:
return !StringRef(Result.Pattern->getAsString()).startswith(Filter);
}
- }
llvm_unreachable("Unknown code completion result Kind.");
}
-void
+void
PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
CodeCompletionContext Context,
CodeCompletionResult *Results,
unsigned NumResults) {
std::stable_sort(Results, Results + NumResults);
-
+
StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
// Print the results.
@@ -468,7 +545,7 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << *Results[I].Declaration;
if (Results[I].Hidden)
OS << " (Hidden)";
- if (CodeCompletionString *CCS
+ if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef, Context,
getAllocator(),
CCTUInfo,
@@ -477,17 +554,34 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
if (const char *BriefComment = CCS->getBriefComment())
OS << " : " << BriefComment;
}
-
+ for (const FixItHint &FixIt : Results[I].FixIts) {
+ const SourceLocation BLoc = FixIt.RemoveRange.getBegin();
+ const SourceLocation ELoc = FixIt.RemoveRange.getEnd();
+
+ SourceManager &SM = SemaRef.SourceMgr;
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
+ std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
+ // Adjust for token ranges.
+ if (FixIt.RemoveRange.isTokenRange())
+ EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts);
+
+ OS << " (requires fix-it:"
+ << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
+ << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
+ << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
+ << SM.getColumnNumber(EInfo.first, EInfo.second) << "}"
+ << " to \"" << FixIt.CodeToInsert << "\")";
+ }
OS << '\n';
break;
-
+
case CodeCompletionResult::RK_Keyword:
OS << Results[I].Keyword << '\n';
break;
-
- case CodeCompletionResult::RK_Macro: {
+
+ case CodeCompletionResult::RK_Macro:
OS << Results[I].Macro->getName();
- if (CodeCompletionString *CCS
+ if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef, Context,
getAllocator(),
CCTUInfo,
@@ -496,14 +590,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
}
OS << '\n';
break;
- }
-
- case CodeCompletionResult::RK_Pattern: {
- OS << "Pattern : "
+
+ case CodeCompletionResult::RK_Pattern:
+ OS << "Pattern : "
<< Results[I].Pattern->getAsString() << '\n';
break;
}
- }
}
}
@@ -532,7 +624,7 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
return OS.str();
}
-void
+void
PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
unsigned CurrentArg,
OverloadCandidate *Candidates,
@@ -547,7 +639,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
}
}
-/// \brief Retrieve the effective availability of the given declaration.
+/// Retrieve the effective availability of the given declaration.
static AvailabilityResult getDeclAvailability(const Decl *D) {
AvailabilityResult AR = D->getAvailability();
if (isa<EnumConstantDecl>(D))
@@ -563,19 +655,19 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
break;
}
LLVM_FALLTHROUGH;
-
+
case RK_Declaration: {
// Set the availability based on attributes.
switch (getDeclAvailability(Declaration)) {
case AR_Available:
case AR_NotYetIntroduced:
- Availability = CXAvailability_Available;
+ Availability = CXAvailability_Available;
break;
-
+
case AR_Deprecated:
Availability = CXAvailability_Deprecated;
break;
-
+
case AR_Unavailable:
Availability = CXAvailability_NotAvailable;
break;
@@ -584,11 +676,11 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
if (Function->isDeleted())
Availability = CXAvailability_NotAvailable;
-
+
CursorKind = getCursorKindForDecl(Declaration);
if (CursorKind == CXCursor_UnexposedDecl) {
- // FIXME: Forward declarations of Objective-C classes and protocols
- // are not directly exposed, but we want code completion to treat them
+ // FIXME: Forward declarations of Objective-C classes and protocols
+ // are not directly exposed, but we want code completion to treat them
// like a definition.
if (isa<ObjCInterfaceDecl>(Declaration))
CursorKind = CXCursor_ObjCInterfaceDecl;
@@ -609,7 +701,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
Availability = CXAvailability_NotAccessible;
}
-/// \brief Retrieve the name that should be used to order a result.
+/// 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.
@@ -625,9 +717,9 @@ StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
// Handle declarations below.
break;
}
-
+
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.
if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
@@ -636,12 +728,12 @@ StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
if (IdentifierInfo *Id
= Name.getObjCSelector().getIdentifierInfoForSlot(0))
return Id->getName();
-
+
Saved = Name.getAsString();
return Saved;
}
-
-bool clang::operator<(const CodeCompletionResult &X,
+
+bool clang::operator<(const CodeCompletionResult &X,
const CodeCompletionResult &Y) {
std::string XSaved, YSaved;
StringRef XStr = X.getOrderedName(XSaved);
@@ -649,11 +741,11 @@ bool clang::operator<(const CodeCompletionResult &X,
int cmp = XStr.compare_lower(YStr);
if (cmp)
return cmp < 0;
-
+
// If case-insensitive comparison fails, try case-sensitive comparison.
cmp = XStr.compare(YStr);
if (cmp)
return cmp < 0;
-
+
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h b/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h
index 33a368d92ff4..d15cf0b756e7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h
@@ -33,16 +33,16 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs {
CXXRecordDecl *PromiseRecordDecl = nullptr;
public:
- /// \brief Construct a CoroutineStmtBuilder and initialize the promise
+ /// Construct a CoroutineStmtBuilder and initialize the promise
/// statement and initial/final suspends from the FunctionScopeInfo.
CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn,
Stmt *Body);
- /// \brief Build the coroutine body statements, including the
+ /// Build the coroutine body statements, including the
/// "promise dependent" statements when the promise type is not dependent.
bool buildStatements();
- /// \brief Build the coroutine body statements that require a non-dependent
+ /// Build the coroutine body statements that require a non-dependent
/// promise type in order to construct.
///
/// For example different new/delete overloads are selected depending on
@@ -51,9 +51,6 @@ public:
/// name lookup.
bool buildDependentStatements();
- /// \brief Build just parameter moves. To use for rebuilding in TreeTransform.
- bool buildParameterMoves();
-
bool isInvalid() const { return !this->IsValid; }
private:
@@ -65,7 +62,6 @@ private:
bool makeReturnObject();
bool makeGroDeclAndReturnStmt();
bool makeReturnOnAllocFailure();
- bool makeParamMoves();
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index 2fad5a18ba6b..b22eea2b3642 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -44,7 +44,7 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
EndLocation = TemplateId->RAngleLoc;
}
-void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
+void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
TypeLoc TL, SourceLocation ColonColonLoc) {
Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc);
if (Range.getBegin().isInvalid())
@@ -56,23 +56,23 @@ void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
}
void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc,
+ SourceLocation IdentifierLoc,
SourceLocation ColonColonLoc) {
Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
-
+
if (Range.getBegin().isInvalid())
Range.setBegin(IdentifierLoc);
Range.setEnd(ColonColonLoc);
-
+
assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
- SourceLocation NamespaceLoc,
+ SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc);
-
+
if (Range.getBegin().isInvalid())
Range.setBegin(NamespaceLoc);
Range.setEnd(ColonColonLoc);
@@ -82,10 +82,10 @@ void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
}
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
- SourceLocation AliasLoc,
+ SourceLocation AliasLoc,
SourceLocation ColonColonLoc) {
Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc);
-
+
if (Range.getBegin().isInvalid())
Range.setBegin(AliasLoc);
Range.setEnd(ColonColonLoc);
@@ -94,12 +94,12 @@ void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
"NestedNameSpecifierLoc range computation incorrect");
}
-void CXXScopeSpec::MakeGlobal(ASTContext &Context,
+void CXXScopeSpec::MakeGlobal(ASTContext &Context,
SourceLocation ColonColonLoc) {
Builder.MakeGlobal(Context, ColonColonLoc);
-
+
Range = SourceRange(ColonColonLoc);
-
+
assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
@@ -116,7 +116,7 @@ void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
"NestedNameSpecifierLoc range computation incorrect");
}
-void CXXScopeSpec::MakeTrivial(ASTContext &Context,
+void CXXScopeSpec::MakeTrivial(ASTContext &Context,
NestedNameSpecifier *Qualifier, SourceRange R) {
Builder.MakeTrivial(Context, Qualifier, R);
Range = R;
@@ -139,11 +139,11 @@ SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const {
return Builder.getTemporary().getLocalBeginLoc();
}
-NestedNameSpecifierLoc
+NestedNameSpecifierLoc
CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
if (!Builder.getRepresentation())
return NestedNameSpecifierLoc();
-
+
return Builder.getWithLocInContext(Context);
}
@@ -186,7 +186,6 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Kind = Function;
I.Loc = LocalRangeBegin;
I.EndLoc = LocalRangeEnd;
- I.Fun.AttrList = nullptr;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = EllipsisLoc.isValid();
I.Fun.isAmbiguous = isAmbiguous;
@@ -233,7 +232,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.DeleteParams = true;
}
for (unsigned i = 0; i < NumParams; i++)
- I.Fun.Params[i] = std::move(Params[i]);
+ I.Fun.Params[i] = std::move(Params[i]);
}
// Check what exception specification information we should actually store.
@@ -251,7 +250,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
}
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
I.Fun.NoexceptExpr = NoexceptExpr;
break;
@@ -322,13 +323,14 @@ bool Declarator::isDeclarationOfFunction() const {
}
llvm_unreachable("Invalid type chunk");
}
-
+
switch (DS.getTypeSpecType()) {
case TST_atomic:
case TST_auto:
case TST_auto_type:
case TST_bool:
case TST_char:
+ case TST_char8:
case TST_char16:
case TST_char32:
case TST_class:
@@ -336,6 +338,8 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_decimal32:
case TST_decimal64:
case TST_double:
+ case TST_Accum:
+ case TST_Fract:
case TST_Float16:
case TST_float128:
case TST_enum:
@@ -365,20 +369,20 @@ bool Declarator::isDeclarationOfFunction() const {
if (Expr *E = DS.getRepAsExpr())
return E->getType()->isFunctionType();
return false;
-
+
case TST_underlyingType:
case TST_typename:
case TST_typeofType: {
QualType QT = DS.getRepAsType().get();
if (QT.isNull())
return false;
-
+
if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT))
QT = LIT->getType();
if (QT.isNull())
return false;
-
+
return QT->isFunctionType();
}
}
@@ -434,8 +438,8 @@ template <class T> static bool BadSpecifier(T TNew, T TPrev,
if (TNew != TPrev)
DiagID = diag::err_invalid_decl_spec_combination;
else
- DiagID = IsExtension ? diag::ext_duplicate_declspec :
- diag::warn_duplicate_declspec;
+ DiagID = IsExtension ? diag::ext_duplicate_declspec :
+ diag::warn_duplicate_declspec;
return true;
}
@@ -499,6 +503,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_void: return "void";
case DeclSpec::TST_char: return "char";
case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t";
+ case DeclSpec::TST_char8: return "char8_t";
case DeclSpec::TST_char16: return "char16_t";
case DeclSpec::TST_char32: return "char32_t";
case DeclSpec::TST_int: return "int";
@@ -506,6 +511,8 @@ 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_accum: return "_Accum";
+ case DeclSpec::TST_fract: return "_Fract";
case DeclSpec::TST_float16: return "_Float16";
case DeclSpec::TST_float128: return "__float128";
case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
@@ -761,6 +768,19 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
return false;
}
+bool DeclSpec::SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // Cannot set twice
+ if (TypeSpecSat) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "_Sat";
+ return true;
+ }
+ TypeSpecSat = true;
+ TSSatLoc = Loc;
+ return false;
+}
+
bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy) {
@@ -950,7 +970,7 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
DiagID = diag::ext_duplicate_declspec;
return true;
}
-
+
ModulePrivateLoc = Loc;
return false;
}
@@ -974,15 +994,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
writtenBS.Width = getTypeSpecWidth();
writtenBS.Type = getTypeSpecType();
// Search the list of attributes for the presence of a mode attribute.
- writtenBS.ModeAttr = false;
- AttributeList* attrs = getAttributes().getList();
- while (attrs) {
- if (attrs->getKind() == AttributeList::AT_Mode) {
- writtenBS.ModeAttr = true;
- break;
- }
- attrs = attrs->getNext();
- }
+ writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode);
}
/// Finish - This does final analysis of the declspec, rejecting things like
@@ -1096,12 +1108,16 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
}
}
- // signed/unsigned are only valid with int/char/wchar_t.
+ bool IsFixedPointType =
+ TypeSpecType == TST_accum || TypeSpecType == TST_fract;
+
+ // signed/unsigned are only valid with int/char/wchar_t/_Accum.
if (TypeSpecSign != TSS_unspecified) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
- else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
- TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
+ else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
+ TypeSpecType != TST_char && TypeSpecType != TST_wchar &&
+ !IsFixedPointType) {
S.Diag(TSSLoc, diag::err_invalid_sign_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
@@ -1116,20 +1132,24 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
case TSW_longlong: // long long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
- else if (TypeSpecType != TST_int) {
+ else if (!(TypeSpecType == TST_int ||
+ (IsFixedPointType && TypeSpecWidth != TSW_longlong))) {
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
+ TypeSpecSat = false;
TypeSpecOwned = false;
}
break;
case TSW_long: // long double, long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
- else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
+ else if (TypeSpecType != TST_int && TypeSpecType != TST_double &&
+ !IsFixedPointType) {
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
+ TypeSpecSat = false;
TypeSpecOwned = false;
}
break;
@@ -1202,7 +1222,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
StorageClassSpec == SCS_auto)
S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class)
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
- if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
+ if (TypeSpecType == TST_char8)
+ S.Diag(TSTLoc, diag::warn_cxx17_compat_unicode_type);
+ else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
if (Constexpr_specified)
@@ -1278,7 +1300,7 @@ bool DeclSpec::isMissingDeclaratorOk() {
StorageClassSpec != DeclSpec::SCS_typedef;
}
-void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
SourceLocation SymbolLocations[3]) {
Kind = UnqualifiedIdKind::IK_OperatorFunctionId;
@@ -1287,7 +1309,7 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
OperatorFunctionId.Operator = Op;
for (unsigned I = 0; I != 3; ++I) {
OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
-
+
if (SymbolLocations[I].isValid())
EndLocation = SymbolLocations[I];
}
@@ -1299,7 +1321,7 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
FirstLocation = Loc;
LastLocation = Loc;
LastSpecifier = VS;
-
+
if (Specifiers & VS) {
PrevSpec = getSpecifierName(VS);
return true;
diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
index 3d321d561e60..a064e492c098 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -1,4 +1,4 @@
-//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- C++ -*-===//
+//===- DelayedDiagnostic.cpp - Delayed declarator diagnostics -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,36 +14,44 @@
// This file also defines AccessedEntity.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Sema/DelayedDiagnostic.h"
-#include <string.h>
+#include <cstring>
+
using namespace clang;
using namespace sema;
DelayedDiagnostic
DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
- SourceLocation Loc,
+ ArrayRef<SourceLocation> Locs,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
StringRef Msg,
bool ObjCPropertyAccess) {
+ assert(!Locs.empty());
DelayedDiagnostic DD;
DD.Kind = Availability;
DD.Triggered = false;
- DD.Loc = Loc;
+ DD.Loc = Locs.front();
DD.AvailabilityData.ReferringDecl = ReferringDecl;
DD.AvailabilityData.OffendingDecl = OffendingDecl;
DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
DD.AvailabilityData.ObjCProperty = ObjCProperty;
char *MessageData = nullptr;
- if (Msg.size()) {
+ if (!Msg.empty()) {
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
}
-
DD.AvailabilityData.Message = MessageData;
DD.AvailabilityData.MessageLen = Msg.size();
+
+ DD.AvailabilityData.SelectorLocs = new SourceLocation[Locs.size()];
+ memcpy(DD.AvailabilityData.SelectorLocs, Locs.data(),
+ sizeof(SourceLocation) * Locs.size());
+ DD.AvailabilityData.NumSelectorLocs = Locs.size();
+
DD.AvailabilityData.AR = AR;
DD.AvailabilityData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
@@ -51,12 +59,13 @@ DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
void DelayedDiagnostic::Destroy() {
switch (Kind) {
- case Access:
- getAccessData().~AccessedEntity();
+ case Access:
+ getAccessData().~AccessedEntity();
break;
case Availability:
delete[] AvailabilityData.Message;
+ delete[] AvailabilityData.SelectorLocs;
break;
case ForbiddenType:
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
index 0bdb19490bc5..dba56931d49c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -1,4 +1,4 @@
-//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
+//===- IdentifierResolver.cpp - Lexical Scope Name lookup -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,10 +14,16 @@
#include "clang/Sema/IdentifierResolver.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Scope.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstdint>
using namespace clang;
@@ -35,17 +41,17 @@ class IdentifierResolver::IdDeclInfoMap {
/// impossible to add something to a pre-C++0x STL container without
/// a completely unnecessary copy.
struct IdDeclInfoPool {
- IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
-
IdDeclInfoPool *Next;
IdDeclInfo Pool[POOL_SIZE];
+
+ IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
};
-
- IdDeclInfoPool *CurPool;
- unsigned int CurIndex;
+
+ IdDeclInfoPool *CurPool = nullptr;
+ unsigned int CurIndex = POOL_SIZE;
public:
- IdDeclInfoMap() : CurPool(nullptr), CurIndex(POOL_SIZE) {}
+ IdDeclInfoMap() = default;
~IdDeclInfoMap() {
IdDeclInfoPool *Cur = CurPool;
@@ -60,7 +66,6 @@ public:
IdDeclInfo &operator[](DeclarationName Name);
};
-
//===----------------------------------------------------------------------===//
// IdDeclInfo Implementation
//===----------------------------------------------------------------------===//
@@ -83,9 +88,7 @@ void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
//===----------------------------------------------------------------------===//
IdentifierResolver::IdentifierResolver(Preprocessor &PP)
- : LangOpt(PP.getLangOpts()), PP(PP),
- IdDeclInfos(new IdDeclInfoMap) {
-}
+ : LangOpt(PP.getLangOpts()), PP(PP), IdDeclInfos(new IdDeclInfoMap) {}
IdentifierResolver::~IdentifierResolver() {
delete IdDeclInfos;
@@ -168,9 +171,9 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
DeclarationName Name = D->getDeclName();
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
-
+
void *Ptr = Name.getFETokenInfo<void>();
-
+
if (!Ptr) {
AddDecl(D);
return;
@@ -193,7 +196,7 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
return;
}
- // General case: insert the declaration at the appropriate point in the
+ // General case: insert the declaration at the appropriate point in the
// list, which already has at least two elements.
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
if (Pos.isIterator()) {
@@ -228,7 +231,7 @@ IdentifierResolver::iterator
IdentifierResolver::begin(DeclarationName Name) {
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
readingIdentifier(*II);
-
+
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) return end();
@@ -245,15 +248,17 @@ IdentifierResolver::begin(DeclarationName Name) {
}
namespace {
- enum DeclMatchKind {
- DMK_Different,
- DMK_Replace,
- DMK_Ignore
- };
-}
-/// \brief Compare two declarations to see whether they are different or,
-/// if they are the same, whether the new declaration should replace the
+enum DeclMatchKind {
+ DMK_Different,
+ DMK_Replace,
+ DMK_Ignore
+};
+
+} // namespace
+
+/// Compare two declarations to see whether they are different or,
+/// if they are the same, whether the new declaration should replace the
/// existing declaration.
static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
// If the declarations are identical, ignore the new one.
@@ -284,40 +289,40 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
for (auto RD : New->redecls()) {
if (RD == Existing)
return DMK_Replace;
-
+
if (RD->isCanonicalDecl())
break;
}
-
+
return DMK_Ignore;
}
-
+
return DMK_Different;
}
bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
readingIdentifier(*II);
-
+
void *Ptr = Name.getFETokenInfo<void>();
-
+
if (!Ptr) {
Name.setFETokenInfo(D);
return true;
}
-
+
IdDeclInfo *IDI;
-
+
if (isDeclPtr(Ptr)) {
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
-
+
switch (compareDeclarations(PrevD, D)) {
case DMK_Different:
break;
-
+
case DMK_Ignore:
return false;
-
+
case DMK_Replace:
Name.setFETokenInfo(D);
return true;
@@ -325,7 +330,7 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
Name.setFETokenInfo(nullptr);
IDI = &(*IdDeclInfos)[Name];
-
+
// If the existing declaration is not visible in translation unit scope,
// then add the new top-level declaration first.
if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
@@ -336,28 +341,28 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
IDI->AddDecl(D);
}
return true;
- }
-
+ }
+
IDI = toIdDeclInfo(Ptr);
// See whether this declaration is identical to any existing declarations.
// If not, find the right place to insert it.
- for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),
+ for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),
IEnd = IDI->decls_end();
I != IEnd; ++I) {
-
+
switch (compareDeclarations(*I, D)) {
case DMK_Different:
break;
-
+
case DMK_Ignore:
return false;
-
+
case DMK_Replace:
*I = D;
return true;
}
-
+
if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
// We've found a declaration that is not visible from the translation
// unit (it's in an inner scope). Insert our declaration here.
@@ -365,7 +370,7 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
return true;
}
}
-
+
// Add the declaration to the end.
IDI->AddDecl(D);
return true;
@@ -373,13 +378,13 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {
if (II.isOutOfDate())
- PP.getExternalSource()->updateOutOfDateIdentifier(II);
+ PP.getExternalSource()->updateOutOfDateIdentifier(II);
}
void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
if (II.isOutOfDate())
PP.getExternalSource()->updateOutOfDateIdentifier(II);
-
+
if (II.isFromAST())
II.setFETokenInfoChangedSinceDeserialization();
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index 64fa2c34b238..58a7862370cc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -154,6 +154,10 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
return ScopePair(diag::note_protected_by_objc_weak_init,
diag::note_exits_objc_weak);
+ case QualType::DK_nontrivial_c_struct:
+ return ScopePair(diag::note_protected_by_non_trivial_c_struct_init,
+ diag::note_exits_dtor);
+
case QualType::DK_cxx_destructor:
OutDiag = diag::note_exits_dtor;
break;
@@ -212,7 +216,7 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
return ScopePair(0U, 0U);
}
-/// \brief Build scope information for a declaration that is part of a DeclStmt.
+/// Build scope information for a declaration that is part of a DeclStmt.
void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
// If this decl causes a new scope, push and switch to it.
std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S, D);
@@ -229,7 +233,7 @@ void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
BuildScopeInformation(Init, ParentScope);
}
-/// \brief Build scope information for a captured block literal variables.
+/// Build scope information for a captured block literal variables.
void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
const BlockDecl *BDecl,
unsigned &ParentScope) {
@@ -254,6 +258,10 @@ void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
Diags = ScopePair(diag::note_enters_block_captures_weak,
diag::note_exits_block_captures_weak);
break;
+ case QualType::DK_nontrivial_c_struct:
+ Diags = ScopePair(diag::note_enters_block_captures_non_trivial_c_struct,
+ diag::note_exits_block_captures_non_trivial_c_struct);
+ break;
case QualType::DK_none:
llvm_unreachable("non-lifetime captured variable");
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 77ace0cfa579..50808effe007 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -16,7 +16,7 @@
using namespace clang;
-///\brief Constructs a new multiplexing external sema source and appends the
+///Constructs a new multiplexing external sema source and appends the
/// given element to it.
///
MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1,
@@ -28,7 +28,7 @@ MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1,
// pin the vtable here.
MultiplexExternalSemaSource::~MultiplexExternalSemaSource() {}
-///\brief Appends new source to the source list.
+///Appends new source to the source list.
///
///\param[in] source - An ExternalSemaSource.
///
@@ -121,7 +121,7 @@ void MultiplexExternalSemaSource::FindExternalLexicalDecls(
Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
}
-void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File,
+void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File,
unsigned Offset,
unsigned Length,
SmallVectorImpl<Decl *> &Decls){
@@ -164,14 +164,28 @@ void MultiplexExternalSemaSource::PrintStats() {
Sources[i]->PrintStats();
}
+Module *MultiplexExternalSemaSource::getModule(unsigned ID) {
+ for (size_t i = 0; i < Sources.size(); ++i)
+ if (auto M = Sources[i]->getModule(ID))
+ return M;
+ return nullptr;
+}
+
+bool MultiplexExternalSemaSource::DeclIsFromPCHWithObjectFile(const Decl *D) {
+ for (auto *S : Sources)
+ if (S->DeclIsFromPCHWithObjectFile(D))
+ return true;
+ return false;
+}
+
bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record,
- uint64_t &Size,
+ uint64_t &Size,
uint64_t &Alignment,
llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets){
for(size_t i = 0; i < Sources.size(); ++i)
- if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets,
+ if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets,
BaseOffsets, VirtualBaseOffsets))
return true;
return false;
@@ -229,10 +243,10 @@ void MultiplexExternalSemaSource::ReadMismatchingDeleteExpressions(
Source->ReadMismatchingDeleteExpressions(Exprs);
}
-bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){
+bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->LookupUnqualified(R, S);
-
+
return !R.empty();
}
@@ -241,13 +255,13 @@ void MultiplexExternalSemaSource::ReadTentativeDefinitions(
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadTentativeDefinitions(TentativeDefs);
}
-
+
void MultiplexExternalSemaSource::ReadUnusedFileScopedDecls(
SmallVectorImpl<const DeclaratorDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadUnusedFileScopedDecls(Decls);
}
-
+
void MultiplexExternalSemaSource::ReadDelegatingConstructors(
SmallVectorImpl<CXXConstructorDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp
index 14d334746f1f..6509df9985ef 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp
@@ -1,4 +1,4 @@
-//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
+//======- ParsedAttr.cpp --------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,20 +7,23 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AttributeList class implementation
+// This file defines the ParsedAttr class implementation
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/ParsedAttr.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
+
using namespace clang;
IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
@@ -31,91 +34,79 @@ IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
return Result;
}
-size_t AttributeList::allocated_size() const {
+size_t ParsedAttr::allocated_size() const {
if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
else if (IsTypeTagForDatatype)
return AttributeFactory::TypeTagForDatatypeAllocSize;
else if (IsProperty)
return AttributeFactory::PropertyAllocSize;
- return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
+ else if (HasParsedType)
+ return sizeof(ParsedAttr) + sizeof(void *);
+ return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion));
}
AttributeFactory::AttributeFactory() {
// Go ahead and configure all the inline capacity. This is just a memset.
FreeLists.resize(InlineFreeListsCapacity);
}
-AttributeFactory::~AttributeFactory() {}
+AttributeFactory::~AttributeFactory() = default;
static size_t getFreeListIndexForSize(size_t size) {
- assert(size >= sizeof(AttributeList));
+ assert(size >= sizeof(ParsedAttr));
assert((size % sizeof(void*)) == 0);
- return ((size - sizeof(AttributeList)) / sizeof(void*));
+ return ((size - sizeof(ParsedAttr)) / sizeof(void *));
}
void *AttributeFactory::allocate(size_t size) {
// Check for a previously reclaimed attribute.
size_t index = getFreeListIndexForSize(size);
- if (index < FreeLists.size()) {
- if (AttributeList *attr = FreeLists[index]) {
- FreeLists[index] = attr->NextInPool;
- return attr;
- }
+ if (index < FreeLists.size() && !FreeLists[index].empty()) {
+ ParsedAttr *attr = FreeLists[index].back();
+ FreeLists[index].pop_back();
+ return attr;
}
// Otherwise, allocate something new.
return Alloc.Allocate(size, alignof(AttributeFactory));
}
-void AttributeFactory::reclaimPool(AttributeList *cur) {
- assert(cur && "reclaiming empty pool!");
- do {
- // Read this here, because we're going to overwrite NextInPool
- // when we toss 'cur' into the appropriate queue.
- AttributeList *next = cur->NextInPool;
+void AttributeFactory::deallocate(ParsedAttr *Attr) {
+ size_t size = Attr->allocated_size();
+ size_t freeListIndex = getFreeListIndexForSize(size);
- size_t size = cur->allocated_size();
- size_t freeListIndex = getFreeListIndexForSize(size);
+ // Expand FreeLists to the appropriate size, if required.
+ if (freeListIndex >= FreeLists.size())
+ FreeLists.resize(freeListIndex + 1);
- // Expand FreeLists to the appropriate size, if required.
- if (freeListIndex >= FreeLists.size())
- FreeLists.resize(freeListIndex+1);
+#if !NDEBUG
+ // In debug mode, zero out the attribute to help find memory overwriting.
+ memset(Attr, 0, size);
+#endif
- // Add 'cur' to the appropriate free-list.
- cur->NextInPool = FreeLists[freeListIndex];
- FreeLists[freeListIndex] = cur;
-
- cur = next;
- } while (cur);
+ // Add 'Attr' to the appropriate free-list.
+ FreeLists[freeListIndex].push_back(Attr);
}
-void AttributePool::takePool(AttributeList *pool) {
- assert(pool);
-
- // Fast path: this pool is empty.
- if (!Head) {
- Head = pool;
- return;
- }
+void AttributeFactory::reclaimPool(AttributePool &cur) {
+ for (ParsedAttr *AL : cur.Attrs)
+ deallocate(AL);
+}
- // Reverse the pool onto the current head. This optimizes for the
- // pattern of pulling a lot of pools into a single pool.
- do {
- AttributeList *next = pool->NextInPool;
- pool->NextInPool = Head;
- Head = pool;
- pool = next;
- } while (pool);
+void AttributePool::takePool(AttributePool &pool) {
+ Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
+ pool.Attrs.clear();
}
#include "clang/Sema/AttrParsedAttrKinds.inc"
static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
- AttributeList::Syntax SyntaxUsed) {
+ ParsedAttr::Syntax SyntaxUsed) {
// Normalize the attribute name, __foo__ becomes foo. This is only allowable
// for GNU attributes.
- bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
- ((SyntaxUsed == AttributeList::AS_CXX11 ||
- SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu");
+ bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
+ ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
+ SyntaxUsed == ParsedAttr::AS_C2x) &&
+ ScopeName == "gnu");
if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
AttrName.endswith("__"))
AttrName = AttrName.slice(2, AttrName.size() - 2);
@@ -123,9 +114,9 @@ static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
return AttrName;
}
-AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
- const IdentifierInfo *ScopeName,
- Syntax SyntaxUsed) {
+ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
+ const IdentifierInfo *ScopeName,
+ Syntax SyntaxUsed) {
StringRef AttrName = Name->getName();
SmallString<64> FullName;
@@ -143,12 +134,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
return ::getAttrKind(FullName, SyntaxUsed);
}
-unsigned AttributeList::getAttributeSpellingListIndex() const {
+unsigned ParsedAttr::getAttributeSpellingListIndex() const {
// Both variables will be used in tablegen generated
// attribute spell list index matching code.
StringRef Scope = ScopeName ? ScopeName->getName() : "";
StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
- (AttributeList::Syntax)SyntaxUsed);
+ (ParsedAttr::Syntax)SyntaxUsed);
#include "clang/Sema/AttrSpellingListIndex.inc"
@@ -164,85 +155,78 @@ struct ParsedAttrInfo {
unsigned IsKnownToGCC : 1;
unsigned IsSupportedByPragmaAttribute : 1;
- bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
- const Decl *);
- bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
+ bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
+ bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
bool (*ExistsInTarget)(const TargetInfo &Target);
- unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
+ unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
void (*GetPragmaAttributeMatchRules)(
llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
const LangOptions &LangOpts);
};
namespace {
- #include "clang/Sema/AttrParsedAttrImpl.inc"
-}
-static const ParsedAttrInfo &getInfo(const AttributeList &A) {
+#include "clang/Sema/AttrParsedAttrImpl.inc"
+
+} // namespace
+
+static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
return AttrInfoMap[A.getKind()];
}
-unsigned AttributeList::getMinArgs() const {
- return getInfo(*this).NumArgs;
-}
+unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
-unsigned AttributeList::getMaxArgs() const {
+unsigned ParsedAttr::getMaxArgs() const {
return getMinArgs() + getInfo(*this).OptArgs;
}
-bool AttributeList::hasCustomParsing() const {
+bool ParsedAttr::hasCustomParsing() const {
return getInfo(*this).HasCustomParsing;
}
-bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
+bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
}
-bool AttributeList::appliesToDecl(const Decl *D,
- attr::SubjectMatchRule MatchRule) const {
+bool ParsedAttr::appliesToDecl(const Decl *D,
+ attr::SubjectMatchRule MatchRule) const {
return checkAttributeMatchRuleAppliesTo(D, MatchRule);
}
-void AttributeList::getMatchRules(
+void ParsedAttr::getMatchRules(
const LangOptions &LangOpts,
SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
const {
return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
}
-bool AttributeList::diagnoseLangOpts(Sema &S) const {
+bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
return getInfo(*this).DiagLangOpts(S, *this);
}
-bool AttributeList::isTargetSpecificAttr() const {
+bool ParsedAttr::isTargetSpecificAttr() const {
return getInfo(*this).IsTargetSpecific;
}
-bool AttributeList::isTypeAttr() const {
- return getInfo(*this).IsType;
-}
+bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
-bool AttributeList::isStmtAttr() const {
- return getInfo(*this).IsStmt;
-}
+bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
-bool AttributeList::existsInTarget(const TargetInfo &Target) const {
+bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
return getInfo(*this).ExistsInTarget(Target);
}
-bool AttributeList::isKnownToGCC() const {
- return getInfo(*this).IsKnownToGCC;
-}
+bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
-bool AttributeList::isSupportedByPragmaAttribute() const {
+bool ParsedAttr::isSupportedByPragmaAttribute() const {
return getInfo(*this).IsSupportedByPragmaAttribute;
}
-unsigned AttributeList::getSemanticSpelling() const {
+unsigned ParsedAttr::getSemanticSpelling() const {
return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
}
-bool AttributeList::hasVariadicArg() const {
+bool ParsedAttr::hasVariadicArg() const {
// If the attribute has the maximum number of optional arguments, we will
// claim that as being variadic. If we someday get an attribute that
// legitimately bumps up against that maximum, we can use another bit to track
diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
index b309a36a30a3..62a83ccb70aa 100644
--- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
@@ -43,6 +43,7 @@ void FunctionScopeInfo::Clear() {
// Coroutine state
FirstCoroutineStmtLoc = SourceLocation();
CoroutinePromise = nullptr;
+ CoroutineParameterMoves.clear();
NeedsCoroutineSuspends = true;
CoroutineSuspends.first = nullptr;
CoroutineSuspends.second = nullptr;
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 4e57e5ef81c6..49f3decc1151 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -31,12 +32,12 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -51,8 +52,8 @@ ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
- // Our printing policy is copied over the ASTContext printing policy whenever
- // a diagnostic is emitted, so recompute it.
+ // In diagnostics, we print _Bool as bool if the latter is defined as the
+ // former.
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
@@ -130,16 +131,19 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
- CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr),
- NSValueDecl(nullptr), NSStringDecl(nullptr),
- StringWithUTF8StringMethod(nullptr),
+ StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr),
+ MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr),
+ NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
- TUKind(TUKind), NumSFINAEErrors(0), AccessCheckingSFINAE(false),
- InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
- ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
- DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
+ TUKind(TUKind), NumSFINAEErrors(0),
+ FullyCheckedComparisonCategories(
+ static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
+ AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
+ NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
+ CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
+ TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
TUScope = nullptr;
@@ -159,9 +163,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ExprEvalContexts.emplace_back(
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
- nullptr, false);
+ nullptr, ExpressionEvaluationContextRecord::EK_Other);
- FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+ PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
// Initilization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
@@ -331,11 +335,11 @@ void Sema::Initialize() {
Sema::~Sema() {
if (VisContext) FreeVisContext();
+
// Kill all the active scopes.
- for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
- delete FunctionScopes[I];
- if (FunctionScopes.size() == 1)
- delete FunctionScopes[0];
+ for (sema::FunctionScopeInfo *FSI : FunctionScopes)
+ if (FSI != PreallocatedFunctionScope.get())
+ delete FSI;
// Tell the SemaConsumer to forget about us; we're going out of scope.
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
@@ -391,7 +395,7 @@ ASTMutationListener *Sema::getASTMutationListener() const {
return getASTConsumer().GetASTMutationListener();
}
-///\brief Registers an external source. If an external source already exists,
+///Registers an external source. If an external source already exists,
/// creates a multiplex external source and appends to it.
///
///\param[in] E - A non-null external sema source.
@@ -412,7 +416,7 @@ void Sema::addExternalSource(ExternalSemaSource *E) {
}
}
-/// \brief Print out statistics about the semantic analysis.
+/// Print out statistics about the semantic analysis.
void Sema::PrintStats() const {
llvm::errs() << "\n*** Semantic Analysis Stats:\n";
llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
@@ -477,6 +481,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_ToVoid:
+ case CK_NonAtomicToAtomic:
break;
}
}
@@ -532,7 +537,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
llvm_unreachable("unknown scalar type kind");
}
-/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+/// Used to prune the decls of Sema's UnusedFileScopedDecls vector.
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (D->getMostRecentDecl()->isUsed())
return true;
@@ -641,6 +646,8 @@ void Sema::getUndefinedButUsed(
!isExternalWithNoLinkageType(FD) &&
!FD->getMostRecentDecl()->isInlined())
continue;
+ if (FD->getBuiltinID())
+ continue;
} else {
auto *VD = cast<VarDecl>(ND);
if (VD->hasDefinition() != VarDecl::DeclarationOnly)
@@ -649,6 +656,11 @@ void Sema::getUndefinedButUsed(
!isExternalWithNoLinkageType(VD) &&
!VD->getMostRecentDecl()->isInline())
continue;
+
+ // Skip VarDecls that lack formal definitions but which we know are in
+ // fact defined somewhere.
+ if (VD->isKnownToBeDefined())
+ continue;
}
Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
@@ -720,7 +732,7 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;
-/// \brief Returns true, if all methods and nested classes of the given
+/// Returns true, if all methods and nested classes of the given
/// CXXRecordDecl are defined in this translation unit.
///
/// Should only be called from ActOnEndOfTranslationUnit so that all
@@ -760,7 +772,7 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
return Complete;
}
-/// \brief Returns true, if the given CXXRecordDecl is fully defined in this
+/// Returns true, if the given CXXRecordDecl is fully defined in this
/// translation unit, i.e. all methods are defined or pure virtual and all
/// friends, friend functions and nested classes are fully defined in this
/// translation unit.
@@ -849,6 +861,20 @@ void Sema::ActOnEndOfTranslationUnit() {
if (PP.isCodeCompletionEnabled())
return;
+ // Transfer late parsed template instantiations over to the pending template
+ // instantiation list. During normal compliation, the late template parser
+ // will be installed and instantiating these templates will succeed.
+ //
+ // If we are building a TU prefix for serialization, it is also safe to
+ // transfer these over, even though they are not parsed. The end of the TU
+ // should be outside of any eager template instantiation scope, so when this
+ // AST is deserialized, these templates will not be parsed until the end of
+ // the combined TU.
+ PendingInstantiations.insert(PendingInstantiations.end(),
+ LateParsedInstantiations.begin(),
+ LateParsedInstantiations.end());
+ LateParsedInstantiations.clear();
+
// Complete translation units and modules define vtables and perform implicit
// instantiations. PCH files do not.
if (TUKind != TU_Prefix) {
@@ -878,8 +904,13 @@ void Sema::ActOnEndOfTranslationUnit() {
PendingInstantiations.insert(PendingInstantiations.begin(),
Pending.begin(), Pending.end());
}
+
PerformPendingInstantiations();
+ assert(LateParsedInstantiations.empty() &&
+ "end of TU template instantiation should not create more "
+ "late-parsed templates");
+
if (LateTemplateParserCleanup)
LateTemplateParserCleanup(OpaqueParser);
@@ -980,11 +1011,6 @@ void Sema::ActOnEndOfTranslationUnit() {
// Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
// modules when they are built, not every time they are used.
emitAndClearUnusedLocalTypedefWarnings();
-
- // Modules don't need any of the checking below.
- if (!PP.isIncrementalProcessingEnabled())
- TUScope = nullptr;
- return;
}
// C99 6.9.2p2:
@@ -1002,8 +1028,7 @@ void Sema::ActOnEndOfTranslationUnit() {
for (TentativeDefinitionsType::iterator
T = TentativeDefinitions.begin(ExternalSource),
TEnd = TentativeDefinitions.end();
- T != TEnd; ++T)
- {
+ T != TEnd; ++T) {
VarDecl *VD = (*T)->getActingDefinition();
// If the tentative definition was completed, getActingDefinition() returns
@@ -1030,12 +1055,13 @@ void Sema::ActOnEndOfTranslationUnit() {
// Notify the consumer that we've completed a tentative definition.
if (!VD->isInvalidDecl())
Consumer.CompleteTentativeDefinition(VD);
-
}
// If there were errors, disable 'unused' warnings since they will mostly be
- // noise.
- if (!Diags.hasErrorOccurred()) {
+ // noise. Don't warn for a use from a module: either we should warn on all
+ // file-scope declarations in modules or not at all, but whether the
+ // declaration is used is immaterial.
+ if (!Diags.hasErrorOccurred() && TUKind != TU_Module) {
// Output warning for unused file scoped decls.
for (UnusedFileScopedDeclsType::iterator
I = UnusedFileScopedDecls.begin(ExternalSource),
@@ -1103,6 +1129,8 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
+ // FIXME: Load additional unused private field candidates from the external
+ // source.
RecordCompleteMap RecordsComplete;
RecordCompleteMap MNCComplete;
for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(),
@@ -1264,7 +1292,8 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
}
}
- // Set up the context's printing policy based on our current state.
+ // Copy the diagnostic printing policy over the ASTContext printing policy.
+ // TODO: Stop doing that. See: https://reviews.llvm.org/D45093#1090292
Context.setPrintingPolicy(getPrintingPolicy());
// Emit the diagnostic.
@@ -1287,7 +1316,7 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
return Builder;
}
-/// \brief Looks through the macro-expansion chain for the given
+/// Looks through the macro-expansion chain for the given
/// location, looking for a macro expansion with the given name.
/// If one is found, returns true and sets the location to that
/// expansion loc.
@@ -1308,7 +1337,7 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
return false;
}
-/// \brief Determines the active Scope associated with the given declaration
+/// Determines the active Scope associated with the given declaration
/// context.
///
/// This routine maps a declaration context to the active Scope object that
@@ -1337,19 +1366,15 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
return nullptr;
}
-/// \brief Enter a new function scope
+/// Enter a new function scope
void Sema::PushFunctionScope() {
- if (FunctionScopes.size() == 1) {
- // Use the "top" function scope rather than having to allocate
- // memory for a new scope.
- FunctionScopes.back()->Clear();
- FunctionScopes.push_back(FunctionScopes.back());
- if (LangOpts.OpenMP)
- pushOpenMPFunctionRegion();
- return;
+ if (FunctionScopes.empty()) {
+ // Use PreallocatedFunctionScope to avoid allocating memory when possible.
+ PreallocatedFunctionScope->Clear();
+ FunctionScopes.push_back(PreallocatedFunctionScope.get());
+ } else {
+ FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
}
-
- FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
if (LangOpts.OpenMP)
pushOpenMPFunctionRegion();
}
@@ -1369,15 +1394,15 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
if (LambdaScopeInfo *const LSI = getCurLambda()) {
LSI->AutoTemplateParameterDepth = Depth;
return;
- }
- llvm_unreachable(
+ }
+ llvm_unreachable(
"Remove assertion if intentionally called in a non-lambda context.");
}
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
if (LangOpts.OpenMP)
popOpenMPFunctionRegion(Scope);
@@ -1389,12 +1414,13 @@ void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
for (const auto &PUD : Scope->PossiblyUnreachableDiags)
Diag(PUD.Loc, PUD.PD);
- if (FunctionScopes.back() != Scope)
+ // Delete the scope unless its our preallocated scope.
+ if (Scope != PreallocatedFunctionScope.get())
delete Scope;
}
-void Sema::PushCompoundScope() {
- getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo());
+void Sema::PushCompoundScope(bool IsStmtExpr) {
+ getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo(IsStmtExpr));
}
void Sema::PopCompoundScope() {
@@ -1404,12 +1430,27 @@ void Sema::PopCompoundScope() {
CurFunction->CompoundScopes.pop_back();
}
-/// \brief Determine whether any errors occurred within this function/method/
+/// Determine whether any errors occurred within this function/method/
/// block.
bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
}
+void Sema::setFunctionHasBranchIntoScope() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasBranchIntoScope();
+}
+
+void Sema::setFunctionHasBranchProtectedScope() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasBranchProtectedScope();
+}
+
+void Sema::setFunctionHasIndirectGoto() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasIndirectGoto();
+}
+
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return nullptr;
@@ -1425,6 +1466,18 @@ BlockScopeInfo *Sema::getCurBlock() {
return CurBSI;
}
+FunctionScopeInfo *Sema::getEnclosingFunction() const {
+ if (FunctionScopes.empty())
+ return nullptr;
+
+ for (int e = FunctionScopes.size() - 1; e >= 0; --e) {
+ if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
+ continue;
+ return FunctionScopes[e];
+ }
+ return nullptr;
+}
+
LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
if (FunctionScopes.empty())
return nullptr;
@@ -1447,7 +1500,7 @@ LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
return CurLSI;
}
-// We have a generic lambda if we parsed auto parameters, or we have
+// We have a generic lambda if we parsed auto parameters, or we have
// an associated template parameter list.
LambdaScopeInfo *Sema::getCurGenericLambda() {
if (LambdaScopeInfo *LSI = getCurLambda()) {
@@ -1462,8 +1515,7 @@ void Sema::ActOnComment(SourceRange Comment) {
if (!LangOpts.RetainCommentsFromSystemHeaders &&
SourceMgr.isInSystemHeader(Comment.getBegin()))
return;
- RawComment RC(SourceMgr, Comment, false,
- LangOpts.CommentOpts.ParseAllComments);
+ RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false);
if (RC.isAlmostTrailingComment()) {
SourceRange MagicMarkerRange(Comment.getBegin(),
Comment.getBegin().getLocWithOffset(3));
@@ -1501,25 +1553,7 @@ void ExternalSemaSource::ReadUndefinedButUsed(
void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
-void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
- SourceLocation Loc = this->Loc;
- if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
- if (Loc.isValid()) {
- Loc.print(OS, S.getSourceManager());
- OS << ": ";
- }
- OS << Message;
-
- if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
- OS << " '";
- ND->getNameForDiagnostic(OS, ND->getASTContext().getPrintingPolicy(), true);
- OS << "'";
- }
-
- OS << '\n';
-}
-
-/// \brief Figure out if an expression could be turned into a call.
+/// Figure out if an expression could be turned into a call.
///
/// Use this when trying to recover from an error where the programmer may have
/// written just the name of a function instead of actually calling it.
@@ -1551,6 +1585,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
}
bool Ambiguous = false;
+ bool IsMV = false;
if (Overloads) {
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
@@ -1564,11 +1599,16 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
if (const FunctionDecl *OverloadDecl
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
if (OverloadDecl->getMinRequiredArguments() == 0) {
- if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) {
+ if (!ZeroArgCallReturnTy.isNull() && !Ambiguous &&
+ (!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() ||
+ OverloadDecl->isCPUSpecificMultiVersion()))) {
ZeroArgCallReturnTy = QualType();
Ambiguous = true;
- } else
+ } else {
ZeroArgCallReturnTy = OverloadDecl->getReturnType();
+ IsMV = OverloadDecl->isCPUDispatchMultiVersion() ||
+ OverloadDecl->isCPUSpecificMultiVersion();
+ }
}
}
}
@@ -1621,7 +1661,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
return false;
}
-/// \brief Give notes for a set of overloads.
+/// Give notes for a set of overloads.
///
/// A companion to tryExprAsCall. In cases when the name that the programmer
/// wrote was an overloaded function, we may be able to make some guesses about
@@ -1647,6 +1687,12 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
}
NamedDecl *Fn = (*It)->getUnderlyingDecl();
+ // Don't print overloads for non-default multiversioned functions.
+ if (const auto *FD = Fn->getAsFunction()) {
+ if (FD->isMultiVersion() && FD->hasAttr<TargetAttr>() &&
+ !FD->getAttr<TargetAttr>()->isDefaultVersion())
+ continue;
+ }
S.Diag(Fn->getLocation(), diag::note_possible_target_of_call);
++ShownOverloads;
}
@@ -1685,6 +1731,21 @@ static bool IsCallableWithAppend(Expr *E) {
!isa<CXXOperatorCallExpr>(E));
}
+static bool IsCPUDispatchCPUSpecificMultiVersion(const Expr *E) {
+ if (const auto *UO = dyn_cast<UnaryOperator>(E))
+ E = UO->getSubExpr();
+
+ if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ if (ULE->getNumDecls() == 0)
+ return false;
+
+ const NamedDecl *ND = *ULE->decls_begin();
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
+ return FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion();
+ }
+ return false;
+}
+
bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
bool ForceComplain,
bool (*IsPlausibleResult)(QualType)) {
@@ -1701,12 +1762,13 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// so we can emit a fixit and carry on pretending that E was
// actually a CallExpr.
SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
- Diag(Loc, PD)
- << /*zero-arg*/ 1 << Range
- << (IsCallableWithAppend(E.get())
- ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
- : FixItHint());
- notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+ bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+ Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
+ << (IsCallableWithAppend(E.get())
+ ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
+ : FixItHint());
+ if (!IsMV)
+ notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
// FIXME: Try this before emitting the fixit, and suppress diagnostics
// while doing so.
@@ -1717,8 +1779,10 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
if (!ForceComplain) return false;
- Diag(Loc, PD) << /*not zero-arg*/ 0 << Range;
- notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+ bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+ Diag(Loc, PD) << /*not zero-arg*/ 0 << IsMV << Range;
+ if (!IsMV)
+ notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
E = ExprError();
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 98a918bd7d63..e06792cae78b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -151,8 +152,8 @@ struct AccessTarget : public AccessedEntity {
: AccessedEntity(Entity) {
initialize();
}
-
- AccessTarget(ASTContext &Context,
+
+ AccessTarget(ASTContext &Context,
MemberNonce _,
CXXRecordDecl *NamingClass,
DeclAccessPair FoundDecl,
@@ -162,7 +163,7 @@ struct AccessTarget : public AccessedEntity {
initialize();
}
- AccessTarget(ASTContext &Context,
+ AccessTarget(ASTContext &Context,
BaseNonce _,
CXXRecordDecl *BaseClass,
CXXRecordDecl *DerivedClass,
@@ -776,7 +777,7 @@ static AccessResult HasAccess(Sema &S,
// We interpret this as a restriction on [M3].
// In this part of the code, 'C' is just our context class ECRecord.
-
+
// These rules are different if we don't have an instance context.
if (!Target.hasInstanceContext()) {
// If it's not an instance member, these restrictions don't apply.
@@ -1271,8 +1272,8 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
DiagnoseAccessPath(S, EC, Entity);
}
-/// MSVC has a bug where if during an using declaration name lookup,
-/// the declaration found is unaccessible (private) and that declaration
+/// MSVC has a bug where if during an using declaration name lookup,
+/// the declaration found is unaccessible (private) and that declaration
/// was bring into scope via another using declaration whose target
/// declaration is accessible (public) then no error is generated.
/// Example:
@@ -1289,15 +1290,15 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
/// using B::f;
/// };
///
-/// Here, B::f is private so this should fail in Standard C++, but
+/// Here, B::f is private so this should fail in Standard C++, but
/// because B::f refers to A::f which is public MSVC accepts it.
-static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
+static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
SourceLocation AccessLoc,
AccessTarget &Entity) {
if (UsingShadowDecl *Shadow =
dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
- if (Entity.getTargetDecl()->getAccess() == AS_private &&
+ if (Entity.getTargetDecl()->getAccess() == AS_private &&
(OrigDecl->getAccess() == AS_public ||
OrigDecl->getAccess() == AS_protected)) {
S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
@@ -1535,7 +1536,7 @@ Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
Found.getAccess() == AS_public)
return AR_accessible;
- AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
+ AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
Found, QualType());
Entity.setDiag(diag::err_access) << E->getSourceRange();
@@ -1690,7 +1691,7 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
AccessEntity.setDiag(PD);
return CheckAccess(*this, UseLoc, AccessEntity);
-}
+}
/// Checks access to an overloaded operator new or delete.
Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
@@ -1712,7 +1713,7 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
return CheckAccess(*this, OpLoc, Entity);
}
-/// \brief Checks access to a member.
+/// Checks access to a member.
Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
CXXRecordDecl *NamingClass,
DeclAccessPair Found) {
@@ -1822,7 +1823,7 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
- AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
+ AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
Path.Access);
if (DiagID)
Entity.setDiag(DiagID) << Derived << Base;
@@ -1856,29 +1857,31 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
}
}
-/// Checks access to Decl from the given class. The check will take access
+/// Checks access to Target from the given class. The check will take access
/// specifiers into account, but no member access expressions and such.
///
-/// \param Decl the declaration to check if it can be accessed
+/// \param Target the declaration to check if it can be accessed
/// \param Ctx the class/context from which to start the search
-/// \return true if the Decl is accessible from the Class, false otherwise.
-bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
+/// \return true if the Target is accessible from the Class, false otherwise.
+bool Sema::IsSimplyAccessible(NamedDecl *Target, DeclContext *Ctx) {
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) {
- if (!Decl->isCXXClassMember())
+ if (!Target->isCXXClassMember())
return true;
+ if (Target->getAccess() == AS_public)
+ return true;
QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
+ // The unprivileged access is AS_none as we don't know how the member was
+ // accessed, which is described by the access in DeclAccessPair.
+ // `IsAccessible` will examine the actual access of Target (i.e.
+ // Decl->getAccess()) when calculating the access.
AccessTarget Entity(Context, AccessedEntity::Member, Class,
- DeclAccessPair::make(Decl, Decl->getAccess()),
- qType);
- if (Entity.getAccess() == AS_public)
- return true;
-
+ DeclAccessPair::make(Target, AS_none), qType);
EffectiveContext EC(CurContext);
return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
}
-
- if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) {
+
+ if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Target)) {
// @public and @package ivars are always accessible.
if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
@@ -1890,7 +1893,7 @@ bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
if (ObjCMethodDecl *MD = getCurMethodDecl())
ClassOfMethodDecl = MD->getClassInterface();
else if (FunctionDecl *FD = getCurFunctionDecl()) {
- if (ObjCImplDecl *Impl
+ if (ObjCImplDecl *Impl
= dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {
if (ObjCImplementationDecl *IMPD
= dyn_cast<ObjCImplementationDecl>(Impl))
@@ -1900,21 +1903,21 @@ bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
ClassOfMethodDecl = CatImplClass->getClassInterface();
}
}
-
+
// If we're not in an interface, this ivar is inaccessible.
if (!ClassOfMethodDecl)
return false;
-
+
// If we're inside the same interface that owns the ivar, we're fine.
if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
return true;
-
+
// If the ivar is private, it's inaccessible.
if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private)
return false;
-
+
return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
}
-
+
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index 4ba2a317e1f9..1a8a00075306 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -205,7 +205,7 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
// "#pragma pack(pop, identifier, n) is undefined"
if (Action & Sema::PSK_Pop) {
if (Alignment && !SlotLabel.empty())
- Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
+ Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment);
if (PackStack.Stack.empty())
Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
}
@@ -268,7 +268,7 @@ void Sema::DiagnoseUnterminatedPragmaPack() {
}
}
-void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
+void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
MSStructPragmaOn = (Kind == PMSST_ON);
}
@@ -330,7 +330,7 @@ void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
Stack.erase(std::prev(I.base()), Stack.end());
}
} else if (!Stack.empty()) {
- // We don't have a label, just pop the last entry.
+ // We do not have a label, just pop the last entry.
CurrentValue = Stack.back().Value;
CurrentPragmaLocation = Stack.back().PragmaLocation;
Stack.pop_back();
@@ -389,7 +389,7 @@ bool Sema::UnifySection(StringRef SectionName,
return false;
}
-/// \brief Called on well formed \#pragma bss_seg().
+/// Called on well formed \#pragma bss_seg().
void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
PragmaMsStackAction Action,
llvm::StringRef StackSlotLabel,
@@ -410,7 +410,7 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
}
-/// \brief Called on well formed \#pragma bss_seg().
+/// Called on well formed \#pragma bss_seg().
void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
int SectionFlags, StringLiteral *SegmentName) {
UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
@@ -520,7 +520,7 @@ attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
} // end anonymous namespace
-void Sema::ActOnPragmaAttributePush(AttributeList &Attribute,
+void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute,
SourceLocation PragmaLoc,
attr::ParsedSubjectMatchRuleSet Rules) {
SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
@@ -645,7 +645,7 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (PragmaAttributeStack.empty())
return;
for (auto &Entry : PragmaAttributeStack) {
- const AttributeList *Attribute = Entry.Attribute;
+ ParsedAttr *Attribute = Entry.Attribute;
assert(Attribute && "Expected an attribute");
// Ensure that the attribute can be applied to the given declaration.
@@ -659,9 +659,10 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (!Applies)
continue;
Entry.IsUsed = true;
- assert(!Attribute->getNext() && "Expected just one attribute");
PragmaAttributeCurrentTargetDecl = D;
- ProcessDeclAttributeList(S, D, Attribute);
+ ParsedAttributesView Attrs;
+ Attrs.addAtStart(Attribute);
+ ProcessDeclAttributeList(S, D, Attrs);
PragmaAttributeCurrentTargetDecl = nullptr;
}
}
@@ -692,7 +693,7 @@ void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
}
-void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
+void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
SourceLocation Loc) {
// Don't add a conflicting attribute. No diagnostic is needed.
if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
index cac5f682275e..13dd8d936fd2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements semantic analysis for CUDA constructs.
+/// This file implements semantic analysis for CUDA constructs.
///
//===----------------------------------------------------------------------===//
@@ -42,8 +42,9 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
SourceLocation GGGLoc) {
FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
if (!ConfigDecl)
- return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
- << "cudaConfigureCall");
+ return ExprError(
+ Diag(LLLLoc, diag::err_undeclared_var_use)
+ << (getLangOpts().HIP ? "hipConfigureCall" : "cudaConfigureCall"));
QualType ConfigQTy = ConfigDecl->getType();
DeclRefExpr *ConfigDR = new (Context)
@@ -54,30 +55,31 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
/*IsExecConfig=*/true);
}
-Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) {
+Sema::CUDAFunctionTarget
+Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) {
bool HasHostAttr = false;
bool HasDeviceAttr = false;
bool HasGlobalAttr = false;
bool HasInvalidTargetAttr = false;
- while (Attr) {
- switch(Attr->getKind()){
- case AttributeList::AT_CUDAGlobal:
+ for (const ParsedAttr &AL : Attrs) {
+ switch (AL.getKind()) {
+ case ParsedAttr::AT_CUDAGlobal:
HasGlobalAttr = true;
break;
- case AttributeList::AT_CUDAHost:
+ case ParsedAttr::AT_CUDAHost:
HasHostAttr = true;
break;
- case AttributeList::AT_CUDADevice:
+ case ParsedAttr::AT_CUDADevice:
HasDeviceAttr = true;
break;
- case AttributeList::AT_CUDAInvalidTarget:
+ case ParsedAttr::AT_CUDAInvalidTarget:
HasInvalidTargetAttr = true;
break;
default:
break;
}
- Attr = Attr->getNext();
}
+
if (HasInvalidTargetAttr)
return CFT_InvalidTarget;
@@ -471,6 +473,59 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) {
return true;
}
+void Sema::checkAllowedCUDAInitializer(VarDecl *VD) {
+ if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage())
+ return;
+ const Expr *Init = VD->getInit();
+ if (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() ||
+ VD->hasAttr<CUDASharedAttr>()) {
+ assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>());
+ bool AllowedInit = false;
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
+ AllowedInit =
+ isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
+ // We'll allow constant initializers even if it's a non-empty
+ // constructor according to CUDA rules. This deviates from NVCC,
+ // but allows us to handle things like constexpr constructors.
+ if (!AllowedInit &&
+ (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
+ AllowedInit = VD->getInit()->isConstantInitializer(
+ Context, VD->getType()->isReferenceType());
+
+ // Also make sure that destructor, if there is one, is empty.
+ if (AllowedInit)
+ if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl())
+ AllowedInit =
+ isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor());
+
+ if (!AllowedInit) {
+ Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>()
+ ? diag::err_shared_var_init
+ : diag::err_dynamic_var_init)
+ << Init->getSourceRange();
+ VD->setInvalidDecl();
+ }
+ } else {
+ // This is a host-side global variable. Check that the initializer is
+ // callable from the host side.
+ const FunctionDecl *InitFn = nullptr;
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) {
+ InitFn = CE->getConstructor();
+ } else if (const CallExpr *CE = dyn_cast<CallExpr>(Init)) {
+ InitFn = CE->getDirectCallee();
+ }
+ if (InitFn) {
+ CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn);
+ if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) {
+ Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
+ << InitFnTarget << InitFn;
+ Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
+ VD->setInvalidDecl();
+ }
+ }
+ }
+}
+
// With -fcuda-host-device-constexpr, an unattributed constexpr function is
// treated as implicitly __host__ __device__, unless:
// * it is a variadic function (device-side variadic functions are not
@@ -521,7 +576,7 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD,
if (!getSourceManager().isInSystemHeader(Match->getLocation())) {
Diag(NewD->getLocation(),
diag::err_cuda_unattributed_constexpr_cannot_overload_device)
- << NewD->getName();
+ << NewD;
Diag(Match->getLocation(),
diag::note_cuda_conflicting_device_function_declared_here);
}
@@ -790,9 +845,12 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
// If the caller is known-emitted, mark the callee as known-emitted.
// Otherwise, mark the call in our call graph so we can traverse it later.
bool CallerKnownEmitted = IsKnownEmitted(*this, Caller);
- if (CallerKnownEmitted)
- MarkKnownEmitted(*this, Caller, Callee, Loc);
- else {
+ if (CallerKnownEmitted) {
+ // Host-side references to a __global__ function refer to the stub, so the
+ // function itself is never emitted and therefore should not be marked.
+ if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global)
+ MarkKnownEmitted(*this, Caller, Callee, Loc);
+ } else {
// If we have
// host fn calls kernel fn calls host+device,
// the HD function does not get instantiated on the host. We model this by
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 6da4d2a26191..4e39d0675471 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -24,7 +24,7 @@
#include "llvm/ADT/STLExtras.h"
using namespace clang;
-/// \brief Find the current instantiation that associated with the given type.
+/// Find the current instantiation that associated with the given type.
static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull())
@@ -44,7 +44,7 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
return nullptr;
}
-/// \brief Compute the DeclContext that is associated with the given type.
+/// Compute the DeclContext that is associated with the given type.
///
/// \param T the type for which we are attempting to find a DeclContext.
///
@@ -59,7 +59,7 @@ DeclContext *Sema::computeDeclContext(QualType T) {
return ::getCurrentInstantiationOf(T, CurContext);
}
-/// \brief Compute the DeclContext that is associated with the given
+/// Compute the DeclContext that is associated with the given
/// scope specifier.
///
/// \param SS the C++ scope specifier as it appears in the source
@@ -172,7 +172,7 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
return SS.getScopeRep()->isDependent();
}
-/// \brief If the given nested name specifier refers to the current
+/// If the given nested name specifier refers to the current
/// instantiation, return the declaration that corresponds to that
/// current instantiation (C++0x [temp.dep.type]p1).
///
@@ -188,7 +188,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
return ::getCurrentInstantiationOf(T, CurContext);
}
-/// \brief Require that the context specified by SS be complete.
+/// Require that the context specified by SS be complete.
///
/// If SS refers to a type, this routine checks whether the type is
/// complete enough (or can be made complete enough) for name lookup
@@ -305,7 +305,7 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
return false;
}
-/// \brief Determines whether the given declaration is an valid acceptable
+/// Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
/// \param SD Declaration checked for nested-name-specifier.
/// \param IsExtension If not null and the declaration is accepted as an
@@ -350,7 +350,7 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
return false;
}
-/// \brief If the given nested-name-specifier begins with a bare identifier
+/// If the given nested-name-specifier begins with a bare identifier
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of that
/// name lookup.
@@ -401,18 +401,18 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
isDependent = isDependentScopeSpecifier(SS);
Found.setContextRange(SS.getRange());
}
-
+
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
// expression or the declaration context associated with a prior
// nested-name-specifier.
-
+
// The declaration context must be complete.
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(SS, LookupCtx))
return false;
-
+
LookupQualifiedName(Found, LookupCtx);
} else if (isDependent) {
return false;
@@ -420,7 +420,7 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
LookupName(Found, S);
}
Found.suppressDiagnostics();
-
+
return Found.getAsSingle<NamespaceDecl>();
}
@@ -443,7 +443,7 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
}
-/// \brief Build a new nested-name-specifier for "identifier::", as described
+/// Build a new nested-name-specifier for "identifier::", as described
/// by ActOnCXXNestedNameSpecifier.
///
/// \param S Scope in which the nested-name-specifier occurs.
@@ -739,7 +739,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
= TLB.push<UnresolvedUsingTypeLoc>(T);
UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<SubstTemplateTypeParmType>(T)) {
- SubstTemplateTypeParmTypeLoc TL
+ SubstTemplateTypeParmTypeLoc TL
= TLB.push<SubstTemplateTypeParmTypeLoc>(T);
TL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<SubstTemplateTypeParmPackType>(T)) {
@@ -772,11 +772,11 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
}
// In Microsoft mode, if we are within a templated function and we can't
- // resolve Identifier, then extend the SS with Identifier. This will have
- // the effect of resolving Identifier during template instantiation.
+ // resolve Identifier, then extend the SS with Identifier. This will have
+ // the effect of resolving Identifier during template instantiation.
// The goal is to be able to resolve a function call whose
// nested-name-specifier is located inside a dependent base class.
- // Example:
+ // Example:
//
// class C {
// public:
@@ -846,8 +846,11 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+ if (T.isNull())
+ return true;
+
if (!T->isDependentType() && !T->getAs<TagType>()) {
- Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
<< T << getLangOpts().CPlusPlus;
return true;
}
@@ -888,7 +891,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
bool EnteringContext) {
if (SS.isInvalid())
return true;
-
+
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
@@ -902,7 +905,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
-
+
// Create source-location information for this type.
TypeLocBuilder Builder;
DependentTemplateSpecializationTypeLoc SpecTL
@@ -915,7 +918,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
-
+
SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
CCLoc);
return false;
@@ -934,7 +937,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
return true;
}
- // We were able to resolve the template name to an actual template.
+ // We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
QualType T =
CheckTemplateIdType(Template.get(), TemplateNameLoc, TemplateArgs);
@@ -967,8 +970,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
}
namespace {
- /// \brief A structure that stores a nested-name-specifier annotation,
- /// including both the nested-name-specifier
+ /// A structure that stores a nested-name-specifier annotation,
+ /// including both the nested-name-specifier
struct NestedNameSpecifierAnnotation {
NestedNameSpecifier *NNS;
};
@@ -988,14 +991,14 @@ void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
return Annotation;
}
-void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
+void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
SourceRange AnnotationRange,
CXXScopeSpec &SS) {
if (!AnnotationPtr) {
SS.SetInvalid(AnnotationRange);
return;
}
-
+
NestedNameSpecifierAnnotation *Annotation
= static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr);
SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1));
@@ -1062,7 +1065,7 @@ bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) {
// it is a complete declaration context.
if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC))
return true;
-
+
EnterDeclaratorContext(S, DC);
// Rebuild the nested name specifier for the new scope.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index ad6348685b64..57aac80f5ad2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -33,10 +33,16 @@ using namespace clang;
enum TryCastResult {
TC_NotApplicable, ///< The cast method is not applicable.
TC_Success, ///< The cast method is appropriate and successful.
+ TC_Extension, ///< The cast method is appropriate and accepted as a
+ ///< language extension.
TC_Failed ///< The cast method is appropriate, but failed. A
///< diagnostic has been emitted.
};
+static bool isValidCast(TryCastResult TCR) {
+ return TCR == TC_Success || TCR == TC_Extension;
+}
+
enum CastType {
CT_Const, ///< const_cast
CT_Static, ///< static_cast
@@ -83,6 +89,14 @@ namespace {
void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
void CheckCStyleCast();
+ void updatePartOfExplicitCastFlags(CastExpr *CE) {
+ // Walk down from the CE to the OrigSrcExpr, and mark all immediate
+ // ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE
+ // (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched.
+ for (; auto *ICE = dyn_cast<ImplicitCastExpr>(CE->getSubExpr()); CE = ICE)
+ ICE->setIsPartOfExplicitCast(true);
+ }
+
/// Complete an apparently-successful cast operation that yields
/// the given expression.
ExprResult complete(CastExpr *castExpr) {
@@ -94,6 +108,7 @@ namespace {
CK_Dependent, castExpr, nullptr,
castExpr->getValueKind());
}
+ updatePartOfExplicitCastFlags(castExpr);
return castExpr;
}
@@ -190,13 +205,13 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExp
CXXCastPath &BasePath);
static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
- QualType DestType,
+ QualType DestType,
Sema::CheckedConversionKind CCK,
SourceRange OpRange,
unsigned &msg, CastKind &Kind,
bool ListInitialization);
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
- QualType DestType,
+ QualType DestType,
Sema::CheckedConversionKind CCK,
SourceRange OpRange,
unsigned &msg, CastKind &Kind,
@@ -267,6 +282,12 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
AngleBrackets));
case tok::kw_dynamic_cast: {
+ // OpenCL C++ 1.0 s2.9: dynamic_cast is not supported.
+ if (getLangOpts().OpenCLCPlusPlus) {
+ return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported)
+ << "dynamic_cast");
+ }
+
if (!TypeDependent) {
Op.CheckDynamicCast();
if (Op.SrcExpr.isInvalid())
@@ -298,7 +319,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return ExprError();
DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
-
+
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
&Op.BasePath, DestTInfo,
@@ -425,95 +446,114 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
}
}
-/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
-/// this removes one level of indirection from both types, provided that they're
-/// the same kind of pointer (plain or to-member). Unlike the Sema function,
-/// this one doesn't care if the two pointers-to-member don't point into the
-/// same class. This is because CastsAwayConstness doesn't care.
-/// And additionally, it handles C++ references. If both the types are
-/// references, then their pointee types are returned,
-/// else if only one of them is reference, it's pointee type is returned,
-/// and the other type is returned as-is.
-static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
- const PointerType *T1PtrType = T1->getAs<PointerType>(),
- *T2PtrType = T2->getAs<PointerType>();
- if (T1PtrType && T2PtrType) {
- T1 = T1PtrType->getPointeeType();
- T2 = T2PtrType->getPointeeType();
- return true;
- }
- const ObjCObjectPointerType *T1ObjCPtrType =
- T1->getAs<ObjCObjectPointerType>(),
- *T2ObjCPtrType =
- T2->getAs<ObjCObjectPointerType>();
- if (T1ObjCPtrType) {
- if (T2ObjCPtrType) {
- T1 = T1ObjCPtrType->getPointeeType();
- T2 = T2ObjCPtrType->getPointeeType();
- return true;
- }
- else if (T2PtrType) {
- T1 = T1ObjCPtrType->getPointeeType();
- T2 = T2PtrType->getPointeeType();
- return true;
- }
- }
- else if (T2ObjCPtrType) {
- if (T1PtrType) {
- T2 = T2ObjCPtrType->getPointeeType();
- T1 = T1PtrType->getPointeeType();
- return true;
- }
- }
-
- const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
- *T2MPType = T2->getAs<MemberPointerType>();
- if (T1MPType && T2MPType) {
- T1 = T1MPType->getPointeeType();
- T2 = T2MPType->getPointeeType();
- return true;
- }
-
- const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(),
- *T2BPType = T2->getAs<BlockPointerType>();
- if (T1BPType && T2BPType) {
- T1 = T1BPType->getPointeeType();
- T2 = T2BPType->getPointeeType();
- return true;
- }
-
- const LValueReferenceType *T1RefType = T1->getAs<LValueReferenceType>(),
- *T2RefType = T2->getAs<LValueReferenceType>();
- if (T1RefType && T2RefType) {
- T1 = T1RefType->getPointeeType();
- T2 = T2RefType->getPointeeType();
- return true;
- }
+namespace {
+/// The kind of unwrapping we did when determining whether a conversion casts
+/// away constness.
+enum CastAwayConstnessKind {
+ /// The conversion does not cast away constness.
+ CACK_None = 0,
+ /// We unwrapped similar types.
+ CACK_Similar = 1,
+ /// We unwrapped dissimilar types with similar representations (eg, a pointer
+ /// versus an Objective-C object pointer).
+ CACK_SimilarKind = 2,
+ /// We unwrapped representationally-unrelated types, such as a pointer versus
+ /// a pointer-to-member.
+ CACK_Incoherent = 3,
+};
+}
- if (T1RefType) {
- T1 = T1RefType->getPointeeType();
- // T2 = T2;
- return true;
+/// Unwrap one level of types for CastsAwayConstness.
+///
+/// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from
+/// both types, provided that they're both pointer-like or array-like. Unlike
+/// the Sema function, doesn't care if the unwrapped pieces are related.
+///
+/// This function may remove additional levels as necessary for correctness:
+/// the resulting T1 is unwrapped sufficiently that it is never an array type,
+/// so that its qualifiers can be directly compared to those of T2 (which will
+/// have the combined set of qualifiers from all indermediate levels of T2),
+/// as (effectively) required by [expr.const.cast]p7 replacing T1's qualifiers
+/// with those from T2.
+static CastAwayConstnessKind
+unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) {
+ enum { None, Ptr, MemPtr, BlockPtr, Array };
+ auto Classify = [](QualType T) {
+ if (T->isAnyPointerType()) return Ptr;
+ if (T->isMemberPointerType()) return MemPtr;
+ if (T->isBlockPointerType()) return BlockPtr;
+ // We somewhat-arbitrarily don't look through VLA types here. This is at
+ // least consistent with the behavior of UnwrapSimilarTypes.
+ if (T->isConstantArrayType() || T->isIncompleteArrayType()) return Array;
+ return None;
+ };
+
+ auto Unwrap = [&](QualType T) {
+ if (auto *AT = Context.getAsArrayType(T))
+ return AT->getElementType();
+ return T->getPointeeType();
+ };
+
+ CastAwayConstnessKind Kind;
+
+ if (T2->isReferenceType()) {
+ // Special case: if the destination type is a reference type, unwrap it as
+ // the first level. (The source will have been an lvalue expression in this
+ // case, so there is no corresponding "reference to" in T1 to remove.) This
+ // simulates removing a "pointer to" from both sides.
+ T2 = T2->getPointeeType();
+ Kind = CastAwayConstnessKind::CACK_Similar;
+ } else if (Context.UnwrapSimilarTypes(T1, T2)) {
+ Kind = CastAwayConstnessKind::CACK_Similar;
+ } else {
+ // Try unwrapping mismatching levels.
+ int T1Class = Classify(T1);
+ if (T1Class == None)
+ return CastAwayConstnessKind::CACK_None;
+
+ int T2Class = Classify(T2);
+ if (T2Class == None)
+ return CastAwayConstnessKind::CACK_None;
+
+ T1 = Unwrap(T1);
+ T2 = Unwrap(T2);
+ Kind = T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind
+ : CastAwayConstnessKind::CACK_Incoherent;
}
- if (T2RefType) {
- // T1 = T1;
- T2 = T2RefType->getPointeeType();
- return true;
+ // We've unwrapped at least one level. If the resulting T1 is a (possibly
+ // multidimensional) array type, any qualifier on any matching layer of
+ // T2 is considered to correspond to T1. Decompose down to the element
+ // type of T1 so that we can compare properly.
+ while (true) {
+ Context.UnwrapSimilarArrayTypes(T1, T2);
+
+ if (Classify(T1) != Array)
+ break;
+
+ auto T2Class = Classify(T2);
+ if (T2Class == None)
+ break;
+
+ if (T2Class != Array)
+ Kind = CastAwayConstnessKind::CACK_Incoherent;
+ else if (Kind != CastAwayConstnessKind::CACK_Incoherent)
+ Kind = CastAwayConstnessKind::CACK_SimilarKind;
+
+ T1 = Unwrap(T1);
+ T2 = Unwrap(T2).withCVRQualifiers(T2.getCVRQualifiers());
}
- return false;
+ return Kind;
}
-/// CastsAwayConstness - Check if the pointer conversion from SrcType to
-/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
-/// the cast checkers. Both arguments must denote pointer (possibly to member)
-/// types.
+/// Check if the pointer conversion from SrcType to DestType casts away
+/// constness as defined in C++ [expr.const.cast]. This is used by the cast
+/// checkers. Both arguments must denote pointer (possibly to member) types.
///
/// \param CheckCVR Whether to check for const/volatile/restrict qualifiers.
-///
/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers.
-static bool
+static CastAwayConstnessKind
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
bool CheckCVR, bool CheckObjCLifetime,
QualType *TheOffendingSrcType = nullptr,
@@ -521,33 +561,35 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
Qualifiers *CastAwayQualifiers = nullptr) {
// If the only checking we care about is for Objective-C lifetime qualifiers,
// and we're not in ObjC mode, there's nothing to check.
- if (!CheckCVR && CheckObjCLifetime &&
- !Self.Context.getLangOpts().ObjC1)
- return false;
-
- // Casting away constness is defined in C++ 5.2.11p8 with reference to
- // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
- // the rules are non-trivial. So first we construct Tcv *...cv* as described
- // in C++ 5.2.11p8.
- assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
- SrcType->isBlockPointerType() ||
- DestType->isLValueReferenceType()) &&
- "Source type is not pointer or pointer to member.");
- assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
- DestType->isBlockPointerType() ||
- DestType->isLValueReferenceType()) &&
- "Destination type is not pointer or pointer to member, or reference.");
-
- QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
+ if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC1)
+ return CastAwayConstnessKind::CACK_None;
+
+ if (!DestType->isReferenceType()) {
+ assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
+ SrcType->isBlockPointerType()) &&
+ "Source type is not pointer or pointer to member.");
+ assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
+ DestType->isBlockPointerType()) &&
+ "Destination type is not pointer or pointer to member.");
+ }
+
+ QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
UnwrappedDestType = Self.Context.getCanonicalType(DestType);
- SmallVector<Qualifiers, 8> cv1, cv2;
- // Find the qualifiers. We only care about cvr-qualifiers for the
- // purpose of this check, because other qualifiers (address spaces,
+ // Find the qualifiers. We only care about cvr-qualifiers for the
+ // purpose of this check, because other qualifiers (address spaces,
// Objective-C GC, etc.) are part of the type's identity.
QualType PrevUnwrappedSrcType = UnwrappedSrcType;
QualType PrevUnwrappedDestType = UnwrappedDestType;
- while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
+ auto WorstKind = CastAwayConstnessKind::CACK_Similar;
+ bool AllConstSoFar = true;
+ while (auto Kind = unwrapCastAwayConstnessLevel(
+ Self.Context, UnwrappedSrcType, UnwrappedDestType)) {
+ // Track the worst kind of unwrap we needed to do before we found a
+ // problem.
+ if (Kind > WorstKind)
+ WorstKind = Kind;
+
// Determine the relevant qualifiers at this level.
Qualifiers SrcQuals, DestQuals;
Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
@@ -560,51 +602,71 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
UnwrappedDestType->isObjCObjectType())
SrcQuals.removeConst();
- Qualifiers RetainedSrcQuals, RetainedDestQuals;
if (CheckCVR) {
- RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
- RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers());
+ Qualifiers SrcCvrQuals =
+ Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers());
+ Qualifiers DestCvrQuals =
+ Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers());
+
+ if (SrcCvrQuals != DestCvrQuals) {
+ if (CastAwayQualifiers)
+ *CastAwayQualifiers = SrcCvrQuals - DestCvrQuals;
+
+ // If we removed a cvr-qualifier, this is casting away 'constness'.
+ if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals)) {
+ if (TheOffendingSrcType)
+ *TheOffendingSrcType = PrevUnwrappedSrcType;
+ if (TheOffendingDestType)
+ *TheOffendingDestType = PrevUnwrappedDestType;
+ return WorstKind;
+ }
- if (RetainedSrcQuals != RetainedDestQuals && TheOffendingSrcType &&
- TheOffendingDestType && CastAwayQualifiers) {
- *TheOffendingSrcType = PrevUnwrappedSrcType;
- *TheOffendingDestType = PrevUnwrappedDestType;
- *CastAwayQualifiers = RetainedSrcQuals - RetainedDestQuals;
+ // If any prior level was not 'const', this is also casting away
+ // 'constness'. We noted the outermost type missing a 'const' already.
+ if (!AllConstSoFar)
+ return WorstKind;
}
}
-
+
if (CheckObjCLifetime &&
!DestQuals.compatiblyIncludesObjCLifetime(SrcQuals))
- return true;
-
- cv1.push_back(RetainedSrcQuals);
- cv2.push_back(RetainedDestQuals);
+ return WorstKind;
+
+ // If we found our first non-const-qualified type, this may be the place
+ // where things start to go wrong.
+ if (AllConstSoFar && !DestQuals.hasConst()) {
+ AllConstSoFar = false;
+ if (TheOffendingSrcType)
+ *TheOffendingSrcType = PrevUnwrappedSrcType;
+ if (TheOffendingDestType)
+ *TheOffendingDestType = PrevUnwrappedDestType;
+ }
PrevUnwrappedSrcType = UnwrappedSrcType;
PrevUnwrappedDestType = UnwrappedDestType;
}
- if (cv1.empty())
- return false;
- // Construct void pointers with those qualifiers (in reverse order of
- // unwrapping, of course).
- QualType SrcConstruct = Self.Context.VoidTy;
- QualType DestConstruct = Self.Context.VoidTy;
- ASTContext &Context = Self.Context;
- for (SmallVectorImpl<Qualifiers>::reverse_iterator i1 = cv1.rbegin(),
- i2 = cv2.rbegin();
- i1 != cv1.rend(); ++i1, ++i2) {
- SrcConstruct
- = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
- DestConstruct
- = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
- }
-
- // Test if they're compatible.
- bool ObjCLifetimeConversion;
- return SrcConstruct != DestConstruct &&
- !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false,
- ObjCLifetimeConversion);
+ return CastAwayConstnessKind::CACK_None;
+}
+
+static TryCastResult getCastAwayConstnessCastKind(CastAwayConstnessKind CACK,
+ unsigned &DiagID) {
+ switch (CACK) {
+ case CastAwayConstnessKind::CACK_None:
+ llvm_unreachable("did not cast away constness");
+
+ case CastAwayConstnessKind::CACK_Similar:
+ // FIXME: Accept these as an extension too?
+ case CastAwayConstnessKind::CACK_SimilarKind:
+ DiagID = diag::err_bad_cxx_cast_qualifiers_away;
+ return TC_Failed;
+
+ case CastAwayConstnessKind::CACK_Incoherent:
+ DiagID = diag::ext_bad_cxx_cast_qualifiers_away_incoherent;
+ return TC_Extension;
+ }
+
+ llvm_unreachable("unexpected cast away constness kind");
}
/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
@@ -657,7 +719,7 @@ void CastOperation::CheckDynamicCast() {
// C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
// complete class type, [...]. If T is an lvalue reference type, v shall be
- // an lvalue of a complete class type, [...]. If T is an rvalue reference
+ // an lvalue of a complete class type, [...]. If T is an rvalue reference
// type, v shall be an expression having a complete class type, [...]
QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
QualType SrcPointee;
@@ -726,7 +788,7 @@ void CastOperation::CheckDynamicCast() {
if (DestRecord &&
Self.IsDerivedFrom(OpRange.getBegin(), SrcPointee, DestPointee)) {
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
- OpRange.getBegin(), OpRange,
+ OpRange.getBegin(), OpRange,
&BasePath)) {
SrcExpr = ExprError();
return;
@@ -772,12 +834,13 @@ void CastOperation::CheckConstCast() {
return;
unsigned msg = diag::err_bad_cxx_cast_generic;
- if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
- && msg != 0) {
+ auto TCR = TryConstCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg);
+ if (TCR != TC_Success && msg != 0) {
Self.Diag(OpRange.getBegin(), msg) << CT_Const
<< SrcExpr.get()->getType() << DestType << OpRange;
- SrcExpr = ExprError();
}
+ if (!isValidCast(TCR))
+ SrcExpr = ExprError();
}
/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
@@ -887,16 +950,15 @@ void CastOperation::CheckReinterpretCast() {
return;
unsigned msg = diag::err_bad_cxx_cast_generic;
- TryCastResult tcr =
- TryReinterpretCast(Self, SrcExpr, DestType,
+ TryCastResult tcr =
+ TryReinterpretCast(Self, SrcExpr, DestType,
/*CStyle*/false, OpRange, msg, Kind);
- if (tcr != TC_Success && msg != 0)
- {
+ if (tcr != TC_Success && msg != 0) {
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
return;
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
- //FIXME: &f<int>; is overloaded and resolvable
- Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
+ //FIXME: &f<int>; is overloaded and resolvable
+ Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
<< OverloadExpr::find(SrcExpr.get()).Expression->getName()
<< DestType << OpRange;
Self.NoteAllOverloadCandidates(SrcExpr.get());
@@ -905,11 +967,14 @@ void CastOperation::CheckReinterpretCast() {
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
DestType, /*listInitialization=*/false);
}
- SrcExpr = ExprError();
- } else if (tcr == TC_Success) {
+ }
+
+ if (isValidCast(tcr)) {
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
checkObjCConversion(Sema::CCK_OtherCast);
DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
+ } else {
+ SrcExpr = ExprError();
}
}
@@ -931,8 +996,8 @@ void CastOperation::CheckStaticCast() {
Kind = CK_ToVoid;
if (claimPlaceholder(BuiltinType::Overload)) {
- Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr,
- false, // Decay Function to ptr
+ Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr,
+ false, // Decay Function to ptr
true, // Complain
OpRange, DestType, diag::err_bad_static_cast_overload);
if (SrcExpr.isInvalid())
@@ -960,21 +1025,22 @@ void CastOperation::CheckStaticCast() {
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression;
Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
- << oe->getName() << DestType << OpRange
+ << oe->getName() << DestType << OpRange
<< oe->getQualifierLoc().getSourceRange();
Self.NoteAllOverloadCandidates(SrcExpr.get());
} else {
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
/*listInitialization=*/false);
}
- SrcExpr = ExprError();
- } else if (tcr == TC_Success) {
+ }
+
+ if (isValidCast(tcr)) {
if (Kind == CK_BitCast)
checkCastAlign();
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
checkObjCConversion(Sema::CCK_OtherCast);
- } else if (Kind == CK_BitCast) {
- checkCastAlign();
+ } else {
+ SrcExpr = ExprError();
}
}
@@ -982,15 +1048,15 @@ void CastOperation::CheckStaticCast() {
/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
/// and casting away constness.
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
- QualType DestType,
+ QualType DestType,
Sema::CheckedConversionKind CCK,
SourceRange OpRange, unsigned &msg,
CastKind &Kind, CXXCastPath &BasePath,
bool ListInitialization) {
// Determine whether we have the semantics of a C-style cast.
- bool CStyle
+ bool CStyle
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
-
+
// The order the tests is not entirely arbitrary. There is one conversion
// that can be handled in two different ways. Given:
// struct A {};
@@ -1016,7 +1082,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
if (tcr != TC_NotApplicable)
return tcr;
- // C++11 [expr.static.cast]p3:
+ // C++11 [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
@@ -1032,7 +1098,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
return TC_Failed;
if (tcr != TC_NotApplicable)
return tcr;
-
+
// C++ 5.2.9p6: May apply the reverse of any standard conversion, except
// lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean
// conversions, subject to further restrictions.
@@ -1060,7 +1126,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
}
}
}
-
+
// Reverse integral promotion/conversion. All such conversions are themselves
// again integral promotions or conversions and are thus already handled by
// p2 (TryDirectInitialization above).
@@ -1133,7 +1199,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
}
}
else if (DestType->isObjCObjectPointerType()) {
- // allow both c-style cast and static_cast of objective-c pointers as
+ // allow both c-style cast and static_cast of objective-c pointers as
// they are pervasive.
Kind = CK_CPointerToObjCPointerCast;
return TC_Success;
@@ -1145,7 +1211,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
}
}
}
- // Allow arbitray objective-c pointer conversion with static casts.
+ // Allow arbitrary objective-c pointer conversion with static casts.
if (SrcType->isObjCObjectPointerType() &&
DestType->isObjCObjectPointerType()) {
Kind = CK_BitCast;
@@ -1164,7 +1230,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
if (SrcPointer->getPointeeType()->getAs<RecordType>() &&
DestPointer->getPointeeType()->getAs<RecordType>())
msg = diag::err_bad_cxx_cast_unrelated_class;
-
+
// We tried everything. Everything! Nothing works! :-(
return TC_NotApplicable;
}
@@ -1218,11 +1284,11 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
if (!Self.IsDerivedFrom(SrcExpr->getLocStart(), SrcExpr->getType(),
R->getPointeeType(), Paths))
return TC_NotApplicable;
-
+
Self.BuildBasePathArray(Paths, BasePath);
} else
Kind = CK_NoOp;
-
+
return TC_Success;
}
@@ -1257,8 +1323,8 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
// FIXME: If the source is a prvalue, we should issue a warning (because the
// cast always has undefined behavior), and for AST consistency, we should
// materialize a temporary.
- return TryStaticDowncast(Self,
- Self.Context.getCanonicalType(SrcExpr->getType()),
+ return TryStaticDowncast(Self,
+ Self.Context.getCanonicalType(SrcExpr->getType()),
Self.Context.getCanonicalType(DestPointee), CStyle,
OpRange, SrcExpr->getType(), DestType, msg, Kind,
BasePath);
@@ -1289,9 +1355,9 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
return TC_NotApplicable;
}
- return TryStaticDowncast(Self,
+ return TryStaticDowncast(Self,
Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
- Self.Context.getCanonicalType(DestPointer->getPointeeType()),
+ Self.Context.getCanonicalType(DestPointer->getPointeeType()),
CStyle, OpRange, SrcType, DestType, msg, Kind,
BasePath);
}
@@ -1302,7 +1368,7 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
TryCastResult
TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
bool CStyle, SourceRange OpRange, QualType OrigSrcType,
- QualType OrigDestType, unsigned &msg,
+ QualType OrigDestType, unsigned &msg,
CastKind &Kind, CXXCastPath &BasePath) {
// We can only work with complete types. But don't complain if it doesn't work
if (!Self.isCompleteType(OpRange.getBegin(), SrcType) ||
@@ -1368,7 +1434,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
}
Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast)
- << QualType(SrcType).getUnqualifiedType()
+ << QualType(SrcType).getUnqualifiedType()
<< QualType(DestType).getUnqualifiedType()
<< PathDisplayStr << OpRange;
msg = 0;
@@ -1412,8 +1478,8 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
/// where B is a base class of D [...].
///
TryCastResult
-TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
- QualType DestType, bool CStyle,
+TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
+ QualType DestType, bool CStyle,
SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
@@ -1433,7 +1499,7 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
WasOverloadedFunction = true;
}
}
-
+
const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
if (!SrcMemPtr) {
msg = diag::err_bad_static_cast_member_pointer_nonmp;
@@ -1503,8 +1569,8 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
if (WasOverloadedFunction) {
// Resolve the address of the overloaded function again, this time
// allowing complaints if something goes wrong.
- FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
- DestType,
+ FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
+ DestType,
true,
FoundOverload);
if (!Fn) {
@@ -1531,7 +1597,7 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
/// @c static_cast if the declaration "T t(e);" is well-formed [...].
TryCastResult
TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
- Sema::CheckedConversionKind CCK,
+ Sema::CheckedConversionKind CCK,
SourceRange OpRange, unsigned &msg,
CastKind &Kind, bool ListInitialization) {
if (DestType->isRecordType()) {
@@ -1559,26 +1625,26 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
InitializationSequence InitSeq(Self, Entity, InitKind, SrcExprRaw);
// At this point of CheckStaticCast, if the destination is a reference,
- // or the expression is an overload expression this has to work.
+ // or the expression is an overload expression this has to work.
// There is no other way that works.
// On the other hand, if we're checking a C-style cast, we've still got
// the reinterpret_cast way.
- bool CStyle
+ bool CStyle
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType()))
return TC_NotApplicable;
-
+
ExprResult Result = InitSeq.Perform(Self, Entity, InitKind, SrcExprRaw);
if (Result.isInvalid()) {
msg = 0;
return TC_Failed;
}
-
+
if (InitSeq.isConstructorInitialization())
Kind = CK_ConstructorConversion;
else
Kind = CK_NoOp;
-
+
SrcExpr = Result;
return TC_Success;
}
@@ -1663,29 +1729,14 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
msg = diag::err_bad_const_cast_dest;
return TC_NotApplicable;
}
- SrcType = Self.Context.getCanonicalType(SrcType);
- // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
- // completely equal.
- // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
- // in multi-level pointers may change, but the level count must be the same,
- // as must be the final pointee type.
- while (SrcType != DestType &&
- Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
- Qualifiers SrcQuals, DestQuals;
- SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals);
- DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals);
-
- // const_cast is permitted to strip cvr-qualifiers, only. Make sure that
- // the other qualifiers (e.g., address spaces) are identical.
- SrcQuals.removeCVRQualifiers();
- DestQuals.removeCVRQualifiers();
- if (SrcQuals != DestQuals)
- return TC_NotApplicable;
- }
-
- // Since we're dealing in canonical types, the remainder must be the same.
- if (SrcType != DestType)
+ // C++ [expr.const.cast]p3:
+ // "For two similar types T1 and T2, [...]"
+ //
+ // We only allow a const_cast to change cvr-qualifiers, not other kinds of
+ // type qualifiers. (Likewise, we ignore other changes when determining
+ // whether a cast casts away constness.)
+ if (!Self.Context.hasCvrSimilarType(SrcType, DestType))
return TC_NotApplicable;
if (NeedToMaterializeTemporary)
@@ -1913,13 +1964,19 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType,
return Result.isUsable();
}
+static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
+ return SrcType->isPointerType() && DestType->isPointerType() &&
+ SrcType->getAs<PointerType>()->getPointeeType().getAddressSpace() !=
+ DestType->getAs<PointerType>()->getPointeeType().getAddressSpace();
+}
+
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
SourceRange OpRange,
unsigned &msg,
CastKind &Kind) {
bool IsLValueCast = false;
-
+
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr.get()->getType();
@@ -1962,7 +2019,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// FIXME: Use a specific diagnostic for the rest of these cases.
case OK_VectorComponent: inappropriate = "vector element"; break;
case OK_ObjCProperty: inappropriate = "property expression"; break;
- case OK_ObjCSubscript: inappropriate = "container subscripting expression";
+ case OK_ObjCSubscript: inappropriate = "container subscripting expression";
break;
}
if (inappropriate) {
@@ -1976,7 +2033,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// This code does this transformation for the checked types.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
-
+
IsLValueCast = true;
}
@@ -1994,16 +2051,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
SrcMemPtr->isMemberFunctionPointer())
return TC_NotApplicable;
- // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
- // constness.
- // A reinterpret_cast followed by a const_cast can, though, so in C-style,
- // we accept it.
- if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
- /*CheckObjCLifetime=*/CStyle)) {
- msg = diag::err_bad_cxx_cast_qualifiers_away;
- return TC_Failed;
- }
-
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// We need to determine the inheritance model that the class will use if
// haven't yet.
@@ -2018,6 +2065,15 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_Failed;
}
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
+ // constness.
+ // A reinterpret_cast followed by a const_cast can, though, so in C-style,
+ // we accept it.
+ if (auto CACK =
+ CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+ /*CheckObjCLifetime=*/CStyle))
+ return getCastAwayConstnessCastKind(CACK, msg);
+
// A valid member pointer cast.
assert(!IsLValueCast);
Kind = CK_ReinterpretMemberPointer;
@@ -2065,18 +2121,18 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
else
msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
-
+
return TC_Failed;
}
if (SrcType == DestType) {
// C++ 5.2.10p2 has a note that mentions that, subject to all other
// restrictions, a cast to the same type is allowed so long as it does not
- // cast away constness. In C++98, the intent was not entirely clear here,
+ // cast away constness. In C++98, the intent was not entirely clear here,
// since all other paragraphs explicitly forbid casts to the same type.
// C++11 clarifies this case with p2.
//
- // The only allowed types are: integral, enumeration, pointer, or
+ // The only allowed types are: integral, enumeration, pointer, or
// pointer-to-member types. We also won't restrict Obj-C pointers either.
Kind = CK_NoOp;
TryCastResult Result = TC_NotApplicable;
@@ -2134,19 +2190,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_NotApplicable;
}
- // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
- // The C-style cast operator can.
- if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
- /*CheckObjCLifetime=*/CStyle)) {
- msg = diag::err_bad_cxx_cast_qualifiers_away;
- return TC_Failed;
- }
-
// Cannot convert between block pointers and Objective-C object pointers.
if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) ||
(DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType()))
return TC_NotApplicable;
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
+ // The C-style cast operator can.
+ TryCastResult SuccessResult = TC_Success;
+ if (auto CACK =
+ CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+ /*CheckObjCLifetime=*/CStyle))
+ SuccessResult = getCastAwayConstnessCastKind(CACK, msg);
+
if (IsLValueCast) {
Kind = CK_LValueBitCast;
} else if (DestType->isObjCObjectPointerType()) {
@@ -2157,6 +2213,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
} else {
Kind = CK_BitCast;
}
+ } else if (IsAddressSpaceConversion(SrcType, DestType)) {
+ Kind = CK_AddressSpaceConversion;
} else {
Kind = CK_BitCast;
}
@@ -2164,7 +2222,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// Any pointer can be cast to an Objective-C pointer type with a C-style
// cast.
if (CStyle && DestType->isObjCObjectPointerType()) {
- return TC_Success;
+ return SuccessResult;
}
if (CStyle)
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
@@ -2178,7 +2236,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
if (DestType->isFunctionPointerType()) {
// C++ 5.2.10p6: A pointer to a function can be explicitly converted to
// a pointer to a function of a different type.
- return TC_Success;
+ return SuccessResult;
}
// C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
@@ -2191,7 +2249,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
Self.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
<< OpRange;
- return TC_Success;
+ return SuccessResult;
}
if (DestType->isFunctionPointerType()) {
@@ -2200,16 +2258,16 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
Self.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
<< OpRange;
- return TC_Success;
+ return SuccessResult;
}
-
+
// C++ 5.2.10p7: A pointer to an object can be explicitly converted to
// a pointer to an object of different type.
// Void pointers are not specified, but supported by every compiler out there.
// So we finish by allowing everything that remains - it's got to be two
// object pointers.
- return TC_Success;
-}
+ return SuccessResult;
+}
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
bool ListInitialization) {
@@ -2238,7 +2296,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
if (claimPlaceholder(BuiltinType::Overload)) {
Self.ResolveAndFixSingleFunctionTemplateSpecialization(
- SrcExpr, /* Decay Function to ptr */ false,
+ SrcExpr, /* Decay Function to ptr */ false,
/* Complain */ true, DestRange, DestType,
diag::err_bad_cstyle_cast_overload);
if (SrcExpr.isInvalid())
@@ -2289,7 +2347,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
/*CStyle*/true, msg);
if (SrcExpr.isInvalid())
return;
- if (tcr == TC_Success)
+ if (isValidCast(tcr))
Kind = CK_NoOp;
Sema::CheckedConversionKind CCK
@@ -2312,7 +2370,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
}
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
- tcr == TC_Success)
+ isValidCast(tcr))
checkObjCConversion(CCK);
if (tcr != TC_Success && msg != 0) {
@@ -2336,16 +2394,17 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
OpRange, SrcExpr.get(), DestType, ListInitialization);
}
- } else if (Kind == CK_BitCast) {
- checkCastAlign();
}
- // Clear out SrcExpr if there was a fatal error.
- if (tcr != TC_Success)
+ if (isValidCast(tcr)) {
+ if (Kind == CK_BitCast)
+ checkCastAlign();
+ } else {
SrcExpr = ExprError();
+ }
}
-/// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a
+/// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a
/// non-matching type. Such as enum function call to int, int call to
/// pointer; etc. Cast to 'void' is an exception.
static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr,
@@ -2353,10 +2412,10 @@ static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr,
if (Self.Diags.isIgnored(diag::warn_bad_function_cast,
SrcExpr.get()->getExprLoc()))
return;
-
+
if (!isa<CallExpr>(SrcExpr.get()))
return;
-
+
QualType SrcType = SrcExpr.get()->getType();
if (DestType.getUnqualifiedType()->isVoidType())
return;
@@ -2375,7 +2434,7 @@ static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr,
return;
if (SrcType->isComplexIntegerType() && DestType->isComplexIntegerType())
return;
-
+
Self.Diag(SrcExpr.get()->getExprLoc(),
diag::warn_bad_function_cast)
<< SrcType << DestType << SrcExpr.get()->getSourceRange();
@@ -2582,26 +2641,26 @@ void CastOperation::CheckCStyleCast() {
if (const PointerType *ExprPtr = SrcType->getAs<PointerType>()) {
Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers();
Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers();
- if (CastPtr->getPointeeType()->isObjCLifetimeType() &&
+ if (CastPtr->getPointeeType()->isObjCLifetimeType() &&
ExprPtr->getPointeeType()->isObjCLifetimeType() &&
!CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) {
- Self.Diag(SrcExpr.get()->getLocStart(),
+ Self.Diag(SrcExpr.get()->getLocStart(),
diag::err_typecheck_incompatible_ownership)
<< SrcType << DestType << Sema::AA_Casting
<< SrcExpr.get()->getSourceRange();
return;
}
}
- }
+ }
else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) {
- Self.Diag(SrcExpr.get()->getLocStart(),
+ Self.Diag(SrcExpr.get()->getLocStart(),
diag::err_arc_convesion_of_weak_unavailable)
<< 1 << SrcType << DestType << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
}
-
+
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange);
DiagnoseBadFunctionCast(Self, SrcExpr, DestType);
@@ -2627,11 +2686,13 @@ static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr,
QualType TheOffendingSrcType, TheOffendingDestType;
Qualifiers CastAwayQualifiers;
- if (!CastsAwayConstness(Self, SrcType, DestType, true, false,
- &TheOffendingSrcType, &TheOffendingDestType,
- &CastAwayQualifiers))
+ if (CastsAwayConstness(Self, SrcType, DestType, true, false,
+ &TheOffendingSrcType, &TheOffendingDestType,
+ &CastAwayQualifiers) !=
+ CastAwayConstnessKind::CACK_Similar)
return;
+ // FIXME: 'restrict' is not properly handled here.
int qualifiers = -1;
if (CastAwayQualifiers.hasConst() && CastAwayQualifiers.hasVolatile()) {
qualifiers = 0;
@@ -2653,7 +2714,7 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
TypeSourceInfo *CastTypeInfo,
SourceLocation RPLoc,
Expr *CastExpr) {
- CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
+ CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 57af6b86bf80..93dbeab5b034 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -28,6 +28,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/NSAPI.h"
+#include "clang/AST/NonTrivialTypeVisitor.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
@@ -118,7 +119,7 @@ static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
// Highlight all the excess arguments.
SourceRange range(call->getArg(desiredArgCount)->getLocStart(),
call->getArg(argCount - 1)->getLocEnd());
-
+
return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args)
<< 0 /*function call*/ << desiredArgCount << argCount
<< call->getArg(1)->getSourceRange();
@@ -196,35 +197,47 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
// First two arguments should be integers.
for (unsigned I = 0; I < 2; ++I) {
- Expr *Arg = TheCall->getArg(I);
- QualType Ty = Arg->getType();
+ ExprResult Arg = TheCall->getArg(I);
+ QualType Ty = Arg.get()->getType();
if (!Ty->isIntegerType()) {
- S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int)
- << Ty << Arg->getSourceRange();
+ S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int)
+ << Ty << Arg.get()->getSourceRange();
return true;
}
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ S.getASTContext(), Ty, /*consume*/ false);
+ Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return true;
+ TheCall->setArg(I, Arg.get());
}
// Third argument should be a pointer to a non-const integer.
// IRGen correctly handles volatile, restrict, and address spaces, and
// the other qualifiers aren't possible.
{
- Expr *Arg = TheCall->getArg(2);
- QualType Ty = Arg->getType();
+ ExprResult Arg = TheCall->getArg(2);
+ QualType Ty = Arg.get()->getType();
const auto *PtrTy = Ty->getAs<PointerType>();
if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() &&
!PtrTy->getPointeeType().isConstQualified())) {
- S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int)
- << Ty << Arg->getSourceRange();
+ S.Diag(Arg.get()->getLocStart(),
+ diag::err_overflow_builtin_must_be_ptr_int)
+ << Ty << Arg.get()->getSourceRange();
return true;
}
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ S.getASTContext(), Ty, /*consume*/ false);
+ Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return true;
+ TheCall->setArg(2, Arg.get());
}
-
return false;
}
static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
- CallExpr *TheCall, unsigned SizeIdx,
+ CallExpr *TheCall, unsigned SizeIdx,
unsigned DstSizeIdx) {
if (TheCall->getNumArgs() <= SizeIdx ||
TheCall->getNumArgs() <= DstSizeIdx)
@@ -683,7 +696,7 @@ static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
return false;
}
-// \brief Performs semantic analysis for the read/write_pipe call.
+// Performs semantic analysis for the read/write_pipe call.
// \param S Reference to the semantic analyzer.
// \param Call A pointer to the builtin call.
// \return True if a semantic error has been found, false otherwise.
@@ -737,7 +750,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
return false;
}
-// \brief Performs a semantic analysis on the {work_group_/sub_group_
+// Performs a semantic analysis on the {work_group_/sub_group_
// /_}reserve_{read/write}_pipe
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
@@ -766,7 +779,7 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {
return false;
}
-// \brief Performs a semantic analysis on {work_group_/sub_group_
+// Performs a semantic analysis on {work_group_/sub_group_
// /_}commit_{read/write}_pipe
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
@@ -789,7 +802,7 @@ static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {
return false;
}
-// \brief Performs a semantic analysis on the call to built-in Pipe
+// Performs a semantic analysis on the call to built-in Pipe
// Query Functions.
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
@@ -807,8 +820,8 @@ 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.
+// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
+// Performs semantic analysis for the to_global/local/private call.
// \param S Reference to the semantic analyzer.
// \param BuiltinID ID of the builtin function.
// \param Call A pointer to the builtin call.
@@ -850,6 +863,20 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
return false;
}
+// Emit an error and return true if the current architecture is not in the list
+// of supported architectures.
+static bool
+CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall,
+ ArrayRef<llvm::Triple::ArchType> SupportedArchs) {
+ llvm::Triple::ArchType CurArch =
+ S.getASTContext().getTargetInfo().getTriple().getArch();
+ if (llvm::is_contained(SupportedArchs, CurArch))
+ return false;
+ S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported)
+ << TheCall->getSourceRange();
+ return true;
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
CallExpr *TheCall) {
@@ -861,18 +888,18 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
Context.GetBuiltinType(BuiltinID, Error, &ICEArguments);
if (Error != ASTContext::GE_None)
ICEArguments = 0; // Don't diagnose previously diagnosed errors.
-
+
// If any arguments are required to be ICE's, check and diagnose.
for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) {
// Skip arguments not required to be ICE's.
if ((ICEArguments & (1 << ArgNo)) == 0) continue;
-
+
llvm::APSInt Result;
if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
return true;
ICEArguments &= ~(1 << ArgNo);
}
-
+
switch (BuiltinID) {
case Builtin::BI__builtin___CFStringMakeConstantString:
assert(TheCall->getNumArgs() == 1 &&
@@ -900,6 +927,33 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
}
break;
}
+
+ // The acquire, release, and no fence variants are ARM and AArch64 only.
+ case Builtin::BI_interlockedbittestandset_acq:
+ case Builtin::BI_interlockedbittestandset_rel:
+ case Builtin::BI_interlockedbittestandset_nf:
+ case Builtin::BI_interlockedbittestandreset_acq:
+ case Builtin::BI_interlockedbittestandreset_rel:
+ case Builtin::BI_interlockedbittestandreset_nf:
+ if (CheckBuiltinTargetSupport(
+ *this, BuiltinID, TheCall,
+ {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64}))
+ return ExprError();
+ break;
+
+ // The 64-bit bittest variants are x64, ARM, and AArch64 only.
+ case Builtin::BI_bittest64:
+ case Builtin::BI_bittestandcomplement64:
+ case Builtin::BI_bittestandreset64:
+ case Builtin::BI_bittestandset64:
+ case Builtin::BI_interlockedbittestandreset64:
+ case Builtin::BI_interlockedbittestandset64:
+ if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall,
+ {llvm::Triple::x86_64, llvm::Triple::arm,
+ llvm::Triple::thumb, llvm::Triple::aarch64}))
+ return ExprError();
+ break;
+
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_isless:
@@ -918,6 +972,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_isinf_sign:
case Builtin::BI__builtin_isnan:
case Builtin::BI__builtin_isnormal:
+ case Builtin::BI__builtin_signbit:
+ case Builtin::BI__builtin_signbitf:
+ case Builtin::BI__builtin_signbitl:
if (SemaBuiltinFPClassification(TheCall, 1))
return ExprError();
break;
@@ -1097,19 +1154,70 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
return ExprError();
break;
case Builtin::BI__builtin_operator_new:
- case Builtin::BI__builtin_operator_delete:
- if (!getLangOpts().CPlusPlus) {
- Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
- << (BuiltinID == Builtin::BI__builtin_operator_new
- ? "__builtin_operator_new"
- : "__builtin_operator_delete")
- << "C++";
+ case Builtin::BI__builtin_operator_delete: {
+ bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
+ ExprResult Res =
+ SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
+ if (Res.isInvalid())
+ CorrectDelayedTyposInExpr(TheCallResult.get());
+ return Res;
+ }
+ case Builtin::BI__builtin_dump_struct: {
+ // We first want to ensure we are called with 2 arguments
+ if (checkArgCount(*this, TheCall, 2))
+ return ExprError();
+ // Ensure that the first argument is of type 'struct XX *'
+ const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts();
+ const QualType PtrArgType = PtrArg->getType();
+ if (!PtrArgType->isPointerType() ||
+ !PtrArgType->getPointeeType()->isRecordType()) {
+ Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType
+ << "structure pointer";
+ return ExprError();
+ }
+
+ // Ensure that the second argument is of type 'FunctionType'
+ const Expr *FnPtrArg = TheCall->getArg(1)->IgnoreImpCasts();
+ const QualType FnPtrArgType = FnPtrArg->getType();
+ if (!FnPtrArgType->isPointerType()) {
+ Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
+ << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
return ExprError();
}
- // CodeGen assumes it can find the global new and delete to call,
- // so ensure that they are declared.
- DeclareGlobalNewDelete();
+
+ const auto *FuncType =
+ FnPtrArgType->getPointeeType()->getAs<FunctionType>();
+
+ if (!FuncType) {
+ Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
+ << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ return ExprError();
+ }
+
+ if (const auto *FT = dyn_cast<FunctionProtoType>(FuncType)) {
+ if (!FT->getNumParams()) {
+ Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
+ << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ return ExprError();
+ }
+ QualType PT = FT->getParamType(0);
+ if (!FT->isVariadic() || FT->getReturnType() != Context.IntTy ||
+ !PT->isPointerType() || !PT->getPointeeType()->isCharType() ||
+ !PT->getPointeeType().isConstQualified()) {
+ Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
+ << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ return ExprError();
+ }
+ }
+
+ TheCall->setType(Context.IntTy);
break;
+ }
// check secure string manipulation functions where overflows
// are detectable at compile time
@@ -1215,7 +1323,6 @@ 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))
@@ -1244,6 +1351,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::hexagon:
+ if (CheckHexagonBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -1353,6 +1464,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
#define GET_NEON_OVERLOAD_CHECK
#include "clang/Basic/arm_neon.inc"
+#include "clang/Basic/arm_fp16.inc"
#undef GET_NEON_OVERLOAD_CHECK
}
@@ -1402,9 +1514,10 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
default:
return false;
-#define GET_NEON_IMMEDIATE_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_IMMEDIATE_CHECK
+ #define GET_NEON_IMMEDIATE_CHECK
+ #include "clang/Basic/arm_neon.inc"
+ #include "clang/Basic/arm_fp16.inc"
+ #undef GET_NEON_IMMEDIATE_CHECK
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
@@ -1618,6 +1731,1015 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
+bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) {
+ static const std::map<unsigned, std::vector<StringRef>> ValidCPU = {
+ { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, {"v62", "v65"} },
+ };
+
+ static const std::map<unsigned, std::vector<StringRef>> ValidHVX = {
+ { Hexagon::BI__builtin_HEXAGON_V6_extractw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_hi, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lo, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_not, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vand, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassign, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassignp, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgb, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguw, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcombine, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vd0, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdd0, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdelta, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlut4, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminb, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmux, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmux_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgb, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgb_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamth, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamth_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnot, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnot_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackob, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackob_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackoh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackoh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrdelta, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrdelta_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B, {"v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vror, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vror_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsathub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsathub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatwh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatwh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufeh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufeh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffob, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffob_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv_128B, {"v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vswap, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vswap_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackob, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackob_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackub, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackub_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vxor, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vxor_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzb, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzb_128B, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzh, {"v60", "v62", "v65"} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzh_128B, {"v60", "v62", "v65"} },
+ };
+
+ const TargetInfo &TI = Context.getTargetInfo();
+
+ auto FC = ValidCPU.find(BuiltinID);
+ if (FC != ValidCPU.end()) {
+ const TargetOptions &Opts = TI.getTargetOpts();
+ StringRef CPU = Opts.CPU;
+ if (!CPU.empty()) {
+ assert(CPU.startswith("hexagon") && "Unexpected CPU name");
+ CPU.consume_front("hexagon");
+ if (llvm::none_of(FC->second, [CPU](StringRef S) { return S == CPU; }))
+ return Diag(TheCall->getLocStart(),
+ diag::err_hexagon_builtin_unsupported_cpu);
+ }
+ }
+
+ auto FH = ValidHVX.find(BuiltinID);
+ if (FH != ValidHVX.end()) {
+ if (!TI.hasFeature("hvx"))
+ return Diag(TheCall->getLocStart(),
+ diag::err_hexagon_builtin_requires_hvx);
+
+ bool IsValid = llvm::any_of(FH->second,
+ [&TI] (StringRef V) {
+ std::string F = "hvx" + V.str();
+ return TI.hasFeature(F);
+ });
+ if (!IsValid)
+ return Diag(TheCall->getLocStart(),
+ diag::err_hexagon_builtin_unsupported_hvx);
+ }
+
+ return false;
+}
+
+bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
+ struct ArgInfo {
+ ArgInfo(unsigned O, bool S, unsigned W, unsigned A)
+ : OpNum(O), IsSigned(S), BitWidth(W), Align(A) {}
+ unsigned OpNum = 0;
+ bool IsSigned = false;
+ unsigned BitWidth = 0;
+ unsigned Align = 0;
+ };
+
+ static const std::map<unsigned, std::vector<ArgInfo>> Infos = {
+ { Hexagon::BI__builtin_circ_ldd, {{ 3, true, 4, 3 }} },
+ { Hexagon::BI__builtin_circ_ldw, {{ 3, true, 4, 2 }} },
+ { Hexagon::BI__builtin_circ_ldh, {{ 3, true, 4, 1 }} },
+ { Hexagon::BI__builtin_circ_lduh, {{ 3, true, 4, 0 }} },
+ { Hexagon::BI__builtin_circ_ldb, {{ 3, true, 4, 0 }} },
+ { Hexagon::BI__builtin_circ_ldub, {{ 3, true, 4, 0 }} },
+ { Hexagon::BI__builtin_circ_std, {{ 3, true, 4, 3 }} },
+ { Hexagon::BI__builtin_circ_stw, {{ 3, true, 4, 2 }} },
+ { Hexagon::BI__builtin_circ_sth, {{ 3, true, 4, 1 }} },
+ { Hexagon::BI__builtin_circ_sthhi, {{ 3, true, 4, 1 }} },
+ { Hexagon::BI__builtin_circ_stb, {{ 3, true, 4, 0 }} },
+
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci, {{ 1, true, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci, {{ 1, true, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadri_pci, {{ 1, true, 4, 2 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci, {{ 1, true, 4, 3 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerb_pci, {{ 1, true, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerh_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerf_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storeri_pci, {{ 1, true, 4, 2 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerd_pci, {{ 1, true, 4, 3 }} },
+
+ { Hexagon::BI__builtin_HEXAGON_A2_combineii, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A2_tfrih, {{ 1, false, 16, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A2_tfril, {{ 1, false, 16, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A2_tfrpi, {{ 0, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_bitspliti, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_cmpbeqi, {{ 1, false, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_cmpbgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_cround_ri, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_round_ri, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_round_ri_sat, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpbeqi, {{ 1, false, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpbgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpbgtui, {{ 1, false, 7, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpheqi, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmphgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmphgtui, {{ 1, false, 7, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpweqi, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpwgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpwgtui, {{ 1, false, 7, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_C2_bitsclri, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_C2_muxii, {{ 2, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_C4_nbitsclri, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfclass, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfimm_n, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfimm_p, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_sfclass, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_sfimm_n, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_sfimm_p, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_M4_mpyri_addi, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_M4_mpyri_addr_u2, {{ 1, false, 6, 2 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_addasl_rrri, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_xacc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_sat, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_xacc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_vh, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_vw, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,
+ {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_rnd, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,
+ {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_rnd, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_svw_trun, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_vh, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_vw, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_clrbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_extractu, {{ 1, false, 5, 0 },
+ { 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_extractup, {{ 1, false, 6, 0 },
+ { 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_insert, {{ 2, false, 5, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_insertp, {{ 2, false, 6, 0 },
+ { 3, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_xacc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_xacc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_vh, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_vw, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_setbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxb_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxd_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxh_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxw_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_togglebit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tstbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_valignib, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_vspliceib, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_addi_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_addi_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_andi_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_andi_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_clbaddi, {{ 1, true , 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_clbpaddi, {{ 1, true, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_extract, {{ 1, false, 5, 0 },
+ { 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_extractp, {{ 1, false, 6, 0 },
+ { 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_lsli, {{ 0, true, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_ntstbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_ori_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_ori_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_subi_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_subi_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_vrcrotate_acc, {{ 3, false, 2, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_vrcrotate, {{ 2, false, 2, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,
+ {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S5_asrhub_sat, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,
+ {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B,
+ {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B,
+ {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B,
+ {{ 3, false, 1, 0 }} },
+ };
+
+ auto F = Infos.find(BuiltinID);
+ if (F == Infos.end())
+ return false;
+
+ bool Error = false;
+
+ for (const ArgInfo &A : F->second) {
+ int32_t Min = A.IsSigned ? -(1 << (A.BitWidth-1)) : 0;
+ int32_t Max = (1 << (A.IsSigned ? A.BitWidth-1 : A.BitWidth)) - 1;
+ if (!A.Align) {
+ Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max);
+ } else {
+ unsigned M = 1 << A.Align;
+ Min *= M;
+ Max *= M;
+ Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max) |
+ SemaBuiltinConstantArgMultiple(TheCall, A.OpNum, M);
+ }
+ }
+ return Error;
+}
+
+bool Sema::CheckHexagonBuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ return CheckHexagonBuiltinCpu(BuiltinID, TheCall) ||
+ CheckHexagonBuiltinArgument(BuiltinID, TheCall);
+}
+
+
// CheckMipsBuiltinFunctionCall - Checks the constant value passed to the
// intrinsic is correct. The switch statement is ordered by DSP, MSA. The
// ordering for DSP is unspecified. MSA is ordered by the data format used
@@ -1666,7 +2788,7 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Mips::BI__builtin_msa_srlri_h: i = 1; l = 0; u = 15; break;
case Mips::BI__builtin_msa_binsli_h:
case Mips::BI__builtin_msa_binsri_h: i = 2; l = 0; u = 15; break;
- // These intrinsics take an unsigned 5 bit immedate.
+ // These intrinsics take an unsigned 5 bit immediate.
// The first block of intrinsics actually have an unsigned 5 bit field,
// not a df/n field.
case Mips::BI__builtin_msa_clei_u_b:
@@ -1966,6 +3088,12 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vcvttss2usi64:
ArgNum = 1;
break;
+ case X86::BI__builtin_ia32_maxpd512:
+ case X86::BI__builtin_ia32_maxps512:
+ case X86::BI__builtin_ia32_minpd512:
+ case X86::BI__builtin_ia32_minps512:
+ ArgNum = 2;
+ break;
case X86::BI__builtin_ia32_cvtps2pd512_mask:
case X86::BI__builtin_ia32_cvttpd2dq512_mask:
case X86::BI__builtin_ia32_cvttpd2qq512_mask:
@@ -1995,12 +3123,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtss2sd_round_mask:
case X86::BI__builtin_ia32_getexpsd128_round_mask:
case X86::BI__builtin_ia32_getexpss128_round_mask:
- case X86::BI__builtin_ia32_maxpd512_mask:
- case X86::BI__builtin_ia32_maxps512_mask:
case X86::BI__builtin_ia32_maxsd_round_mask:
case X86::BI__builtin_ia32_maxss_round_mask:
- case X86::BI__builtin_ia32_minpd512_mask:
- case X86::BI__builtin_ia32_minps512_mask:
case X86::BI__builtin_ia32_minsd_round_mask:
case X86::BI__builtin_ia32_minss_round_mask:
case X86::BI__builtin_ia32_rcp28sd_round_mask:
@@ -2039,9 +3163,19 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vcvtss2si64:
case X86::BI__builtin_ia32_vcvtss2usi32:
case X86::BI__builtin_ia32_vcvtss2usi64:
+ case X86::BI__builtin_ia32_sqrtpd512:
+ case X86::BI__builtin_ia32_sqrtps512:
ArgNum = 1;
HasRC = true;
break;
+ case X86::BI__builtin_ia32_addpd512:
+ case X86::BI__builtin_ia32_addps512:
+ case X86::BI__builtin_ia32_divpd512:
+ case X86::BI__builtin_ia32_divps512:
+ case X86::BI__builtin_ia32_mulpd512:
+ case X86::BI__builtin_ia32_mulps512:
+ case X86::BI__builtin_ia32_subpd512:
+ case X86::BI__builtin_ia32_subps512:
case X86::BI__builtin_ia32_cvtsi2sd64:
case X86::BI__builtin_ia32_cvtsi2ss32:
case X86::BI__builtin_ia32_cvtsi2ss64:
@@ -2062,19 +3196,9 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtqq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
- case X86::BI__builtin_ia32_sqrtpd512_mask:
- case X86::BI__builtin_ia32_sqrtps512_mask:
ArgNum = 3;
HasRC = true;
break;
- case X86::BI__builtin_ia32_addpd512_mask:
- case X86::BI__builtin_ia32_addps512_mask:
- case X86::BI__builtin_ia32_divpd512_mask:
- case X86::BI__builtin_ia32_divps512_mask:
- case X86::BI__builtin_ia32_mulpd512_mask:
- case X86::BI__builtin_ia32_mulps512_mask:
- case X86::BI__builtin_ia32_subpd512_mask:
- case X86::BI__builtin_ia32_subps512_mask:
case X86::BI__builtin_ia32_addss_round_mask:
case X86::BI__builtin_ia32_addsd_round_mask:
case X86::BI__builtin_ia32_divss_round_mask:
@@ -2092,34 +3216,28 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
case X86::BI__builtin_ia32_sqrtsd_round_mask:
case X86::BI__builtin_ia32_sqrtss_round_mask:
+ case X86::BI__builtin_ia32_vfmaddsd3_mask:
+ case X86::BI__builtin_ia32_vfmaddsd3_maskz:
+ case X86::BI__builtin_ia32_vfmaddsd3_mask3:
+ case X86::BI__builtin_ia32_vfmaddss3_mask:
+ case X86::BI__builtin_ia32_vfmaddss3_maskz:
+ case X86::BI__builtin_ia32_vfmaddss3_mask3:
case X86::BI__builtin_ia32_vfmaddpd512_mask:
- case X86::BI__builtin_ia32_vfmaddpd512_mask3:
case X86::BI__builtin_ia32_vfmaddpd512_maskz:
+ case X86::BI__builtin_ia32_vfmaddpd512_mask3:
+ case X86::BI__builtin_ia32_vfmsubpd512_mask3:
case X86::BI__builtin_ia32_vfmaddps512_mask:
- case X86::BI__builtin_ia32_vfmaddps512_mask3:
case X86::BI__builtin_ia32_vfmaddps512_maskz:
+ case X86::BI__builtin_ia32_vfmaddps512_mask3:
+ case X86::BI__builtin_ia32_vfmsubps512_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask:
- case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
+ case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
case X86::BI__builtin_ia32_vfmaddsubps512_mask:
- case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
- case X86::BI__builtin_ia32_vfmsubpd512_mask3:
- case X86::BI__builtin_ia32_vfmsubps512_mask3:
- case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
+ case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case X86::BI__builtin_ia32_vfmsubaddps512_mask3:
- case X86::BI__builtin_ia32_vfnmaddpd512_mask:
- case X86::BI__builtin_ia32_vfnmaddps512_mask:
- case X86::BI__builtin_ia32_vfnmsubpd512_mask:
- case X86::BI__builtin_ia32_vfnmsubpd512_mask3:
- case X86::BI__builtin_ia32_vfnmsubps512_mask:
- case X86::BI__builtin_ia32_vfnmsubps512_mask3:
- case X86::BI__builtin_ia32_vfmaddsd3_mask:
- case X86::BI__builtin_ia32_vfmaddsd3_maskz:
- case X86::BI__builtin_ia32_vfmaddsd3_mask3:
- case X86::BI__builtin_ia32_vfmaddss3_mask:
- case X86::BI__builtin_ia32_vfmaddss3_maskz:
- case X86::BI__builtin_ia32_vfmaddss3_mask3:
ArgNum = 4;
HasRC = true;
break;
@@ -2256,6 +3374,17 @@ bool Sema::CheckX86BuiltinGatherScatterScale(unsigned BuiltinID,
<< Arg->getSourceRange();
}
+static bool isX86_32Builtin(unsigned BuiltinID) {
+ // These builtins only work on x86-32 targets.
+ switch (BuiltinID) {
+ case X86::BI__builtin_ia32_readeflags_u32:
+ case X86::BI__builtin_ia32_writeeflags_u32:
+ return true;
+ }
+
+ return false;
+}
+
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (BuiltinID == X86::BI__builtin_cpu_supports)
return SemaBuiltinCpuSupports(*this, TheCall);
@@ -2263,6 +3392,12 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (BuiltinID == X86::BI__builtin_cpu_is)
return SemaBuiltinCpuIs(*this, TheCall);
+ // Check for 32-bit only builtins on a 64-bit target.
+ const llvm::Triple &TT = Context.getTargetInfo().getTriple();
+ if (TT.getArch() != llvm::Triple::x86 && isX86_32Builtin(BuiltinID))
+ return Diag(TheCall->getCallee()->getLocStart(),
+ diag::err_32_bit_builtin_64_bit_tgt);
+
// If the intrinsic has rounding or SAE make sure its valid.
if (CheckX86BuiltinRoundingOrSAE(BuiltinID, TheCall))
return true;
@@ -2277,14 +3412,67 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
default:
return false;
+ case X86::BI__builtin_ia32_vec_ext_v2si:
+ case X86::BI__builtin_ia32_vec_ext_v2di:
+ case X86::BI__builtin_ia32_vextractf128_pd256:
+ case X86::BI__builtin_ia32_vextractf128_ps256:
+ case X86::BI__builtin_ia32_vextractf128_si256:
+ case X86::BI__builtin_ia32_extract128i256:
+ case X86::BI__builtin_ia32_extractf64x4_mask:
+ case X86::BI__builtin_ia32_extracti64x4_mask:
+ case X86::BI__builtin_ia32_extractf32x8_mask:
+ case X86::BI__builtin_ia32_extracti32x8_mask:
+ case X86::BI__builtin_ia32_extractf64x2_256_mask:
+ case X86::BI__builtin_ia32_extracti64x2_256_mask:
+ case X86::BI__builtin_ia32_extractf32x4_256_mask:
+ case X86::BI__builtin_ia32_extracti32x4_256_mask:
+ i = 1; l = 0; u = 1;
+ break;
+ case X86::BI__builtin_ia32_vec_set_v2di:
+ case X86::BI__builtin_ia32_vinsertf128_pd256:
+ case X86::BI__builtin_ia32_vinsertf128_ps256:
+ case X86::BI__builtin_ia32_vinsertf128_si256:
+ case X86::BI__builtin_ia32_insert128i256:
+ case X86::BI__builtin_ia32_insertf32x8:
+ case X86::BI__builtin_ia32_inserti32x8:
+ case X86::BI__builtin_ia32_insertf64x4:
+ case X86::BI__builtin_ia32_inserti64x4:
+ case X86::BI__builtin_ia32_insertf64x2_256:
+ case X86::BI__builtin_ia32_inserti64x2_256:
+ case X86::BI__builtin_ia32_insertf32x4_256:
+ case X86::BI__builtin_ia32_inserti32x4_256:
+ i = 2; l = 0; u = 1;
+ break;
+ case X86::BI__builtin_ia32_vpermilpd:
+ case X86::BI__builtin_ia32_vec_ext_v4hi:
+ case X86::BI__builtin_ia32_vec_ext_v4si:
+ case X86::BI__builtin_ia32_vec_ext_v4sf:
+ case X86::BI__builtin_ia32_vec_ext_v4di:
+ case X86::BI__builtin_ia32_extractf32x4_mask:
+ case X86::BI__builtin_ia32_extracti32x4_mask:
+ case X86::BI__builtin_ia32_extractf64x2_512_mask:
+ case X86::BI__builtin_ia32_extracti64x2_512_mask:
+ i = 1; l = 0; u = 3;
+ break;
case X86::BI_mm_prefetch:
+ case X86::BI__builtin_ia32_vec_ext_v8hi:
+ case X86::BI__builtin_ia32_vec_ext_v8si:
i = 1; l = 0; u = 7;
break;
case X86::BI__builtin_ia32_sha1rnds4:
- case X86::BI__builtin_ia32_shuf_f32x4_256_mask:
- case X86::BI__builtin_ia32_shuf_f64x2_256_mask:
- case X86::BI__builtin_ia32_shuf_i32x4_256_mask:
- case X86::BI__builtin_ia32_shuf_i64x2_256_mask:
+ case X86::BI__builtin_ia32_blendpd:
+ case X86::BI__builtin_ia32_shufpd:
+ case X86::BI__builtin_ia32_vec_set_v4hi:
+ case X86::BI__builtin_ia32_vec_set_v4si:
+ case X86::BI__builtin_ia32_vec_set_v4di:
+ case X86::BI__builtin_ia32_shuf_f32x4_256:
+ case X86::BI__builtin_ia32_shuf_f64x2_256:
+ case X86::BI__builtin_ia32_shuf_i32x4_256:
+ case X86::BI__builtin_ia32_shuf_i64x2_256:
+ case X86::BI__builtin_ia32_insertf64x2_512:
+ case X86::BI__builtin_ia32_inserti64x2_512:
+ case X86::BI__builtin_ia32_insertf32x4:
+ case X86::BI__builtin_ia32_inserti32x4:
i = 2; l = 0; u = 3;
break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -2325,14 +3513,29 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vpcomw:
case X86::BI__builtin_ia32_vpcomd:
case X86::BI__builtin_ia32_vpcomq:
+ case X86::BI__builtin_ia32_vec_set_v8hi:
+ case X86::BI__builtin_ia32_vec_set_v8si:
i = 2; l = 0; u = 7;
break;
+ case X86::BI__builtin_ia32_vpermilpd256:
case X86::BI__builtin_ia32_roundps:
case X86::BI__builtin_ia32_roundpd:
case X86::BI__builtin_ia32_roundps256:
case X86::BI__builtin_ia32_roundpd256:
+ case X86::BI__builtin_ia32_getmantpd128_mask:
+ case X86::BI__builtin_ia32_getmantpd256_mask:
+ case X86::BI__builtin_ia32_getmantps128_mask:
+ case X86::BI__builtin_ia32_getmantps256_mask:
+ case X86::BI__builtin_ia32_getmantpd512_mask:
+ case X86::BI__builtin_ia32_getmantps512_mask:
+ case X86::BI__builtin_ia32_vec_ext_v16qi:
+ case X86::BI__builtin_ia32_vec_ext_v16hi:
i = 1; l = 0; u = 15;
break;
+ case X86::BI__builtin_ia32_pblendd128:
+ case X86::BI__builtin_ia32_blendps:
+ case X86::BI__builtin_ia32_blendpd256:
+ case X86::BI__builtin_ia32_shufpd256:
case X86::BI__builtin_ia32_roundss:
case X86::BI__builtin_ia32_roundsd:
case X86::BI__builtin_ia32_rangepd128_mask:
@@ -2343,8 +3546,13 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_rangeps512_mask:
case X86::BI__builtin_ia32_getmantsd_round_mask:
case X86::BI__builtin_ia32_getmantss_round_mask:
+ case X86::BI__builtin_ia32_vec_set_v16qi:
+ case X86::BI__builtin_ia32_vec_set_v16hi:
i = 2; l = 0; u = 15;
break;
+ case X86::BI__builtin_ia32_vec_ext_v32qi:
+ i = 1; l = 0; u = 31;
+ break;
case X86::BI__builtin_ia32_cmpps:
case X86::BI__builtin_ia32_cmpss:
case X86::BI__builtin_ia32_cmppd:
@@ -2359,15 +3567,26 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cmppd512_mask:
case X86::BI__builtin_ia32_cmpsd_mask:
case X86::BI__builtin_ia32_cmpss_mask:
+ case X86::BI__builtin_ia32_vec_set_v32qi:
i = 2; l = 0; u = 31;
break;
- case X86::BI__builtin_ia32_xabort:
- i = 0; l = -128; u = 255;
- break;
- case X86::BI__builtin_ia32_pshufw:
- case X86::BI__builtin_ia32_aeskeygenassist128:
- i = 1; l = -128; u = 255;
- break;
+ case X86::BI__builtin_ia32_permdf256:
+ case X86::BI__builtin_ia32_permdi256:
+ case X86::BI__builtin_ia32_permdf512:
+ case X86::BI__builtin_ia32_permdi512:
+ case X86::BI__builtin_ia32_vpermilps:
+ case X86::BI__builtin_ia32_vpermilps256:
+ case X86::BI__builtin_ia32_vpermilpd512:
+ case X86::BI__builtin_ia32_vpermilps512:
+ case X86::BI__builtin_ia32_pshufd:
+ case X86::BI__builtin_ia32_pshufd256:
+ case X86::BI__builtin_ia32_pshufd512:
+ case X86::BI__builtin_ia32_pshufhw:
+ case X86::BI__builtin_ia32_pshufhw256:
+ case X86::BI__builtin_ia32_pshufhw512:
+ case X86::BI__builtin_ia32_pshuflw:
+ case X86::BI__builtin_ia32_pshuflw256:
+ case X86::BI__builtin_ia32_pshuflw512:
case X86::BI__builtin_ia32_vcvtps2ph:
case X86::BI__builtin_ia32_vcvtps2ph_mask:
case X86::BI__builtin_ia32_vcvtps2ph256:
@@ -2385,16 +3604,18 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_reduceps128_mask:
case X86::BI__builtin_ia32_reduceps256_mask:
case X86::BI__builtin_ia32_reduceps512_mask:
- case X86::BI__builtin_ia32_prold512_mask:
- case X86::BI__builtin_ia32_prolq512_mask:
- case X86::BI__builtin_ia32_prold128_mask:
- case X86::BI__builtin_ia32_prold256_mask:
- case X86::BI__builtin_ia32_prolq128_mask:
- case X86::BI__builtin_ia32_prolq256_mask:
- case X86::BI__builtin_ia32_prord128_mask:
- case X86::BI__builtin_ia32_prord256_mask:
- case X86::BI__builtin_ia32_prorq128_mask:
- case X86::BI__builtin_ia32_prorq256_mask:
+ case X86::BI__builtin_ia32_prold512:
+ case X86::BI__builtin_ia32_prolq512:
+ case X86::BI__builtin_ia32_prold128:
+ case X86::BI__builtin_ia32_prold256:
+ case X86::BI__builtin_ia32_prolq128:
+ case X86::BI__builtin_ia32_prolq256:
+ case X86::BI__builtin_ia32_prord512:
+ case X86::BI__builtin_ia32_prorq512:
+ case X86::BI__builtin_ia32_prord128:
+ case X86::BI__builtin_ia32_prord256:
+ case X86::BI__builtin_ia32_prorq128:
+ case X86::BI__builtin_ia32_prorq256:
case X86::BI__builtin_ia32_fpclasspd128_mask:
case X86::BI__builtin_ia32_fpclasspd256_mask:
case X86::BI__builtin_ia32_fpclassps128_mask:
@@ -2403,41 +3624,62 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_fpclasspd512_mask:
case X86::BI__builtin_ia32_fpclasssd_mask:
case X86::BI__builtin_ia32_fpclassss_mask:
+ case X86::BI__builtin_ia32_pslldqi128_byteshift:
+ case X86::BI__builtin_ia32_pslldqi256_byteshift:
+ case X86::BI__builtin_ia32_pslldqi512_byteshift:
+ case X86::BI__builtin_ia32_psrldqi128_byteshift:
+ case X86::BI__builtin_ia32_psrldqi256_byteshift:
+ case X86::BI__builtin_ia32_psrldqi512_byteshift:
i = 1; l = 0; u = 255;
break;
- case X86::BI__builtin_ia32_palignr:
- case X86::BI__builtin_ia32_insertps128:
- case X86::BI__builtin_ia32_dpps:
- case X86::BI__builtin_ia32_dppd:
- case X86::BI__builtin_ia32_dpps256:
- case X86::BI__builtin_ia32_mpsadbw128:
- case X86::BI__builtin_ia32_mpsadbw256:
- case X86::BI__builtin_ia32_pcmpistrm128:
- case X86::BI__builtin_ia32_pcmpistri128:
- case X86::BI__builtin_ia32_pcmpistria128:
- case X86::BI__builtin_ia32_pcmpistric128:
- case X86::BI__builtin_ia32_pcmpistrio128:
- case X86::BI__builtin_ia32_pcmpistris128:
- case X86::BI__builtin_ia32_pcmpistriz128:
- case X86::BI__builtin_ia32_pclmulqdq128:
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:
- i = 2; l = -128; u = 255;
- break;
+ case X86::BI__builtin_ia32_pblendw128:
+ case X86::BI__builtin_ia32_pblendw256:
+ case X86::BI__builtin_ia32_blendps256:
+ case X86::BI__builtin_ia32_pblendd256:
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256:
- case X86::BI__builtin_ia32_palignr512_mask:
+ case X86::BI__builtin_ia32_palignr512:
+ case X86::BI__builtin_ia32_alignq512:
+ case X86::BI__builtin_ia32_alignd512:
+ case X86::BI__builtin_ia32_alignd128:
+ case X86::BI__builtin_ia32_alignd256:
+ case X86::BI__builtin_ia32_alignq128:
+ case X86::BI__builtin_ia32_alignq256:
case X86::BI__builtin_ia32_vcomisd:
case X86::BI__builtin_ia32_vcomiss:
- case X86::BI__builtin_ia32_shuf_f32x4_mask:
- case X86::BI__builtin_ia32_shuf_f64x2_mask:
- case X86::BI__builtin_ia32_shuf_i32x4_mask:
- case X86::BI__builtin_ia32_shuf_i64x2_mask:
- case X86::BI__builtin_ia32_dbpsadbw128_mask:
- case X86::BI__builtin_ia32_dbpsadbw256_mask:
- case X86::BI__builtin_ia32_dbpsadbw512_mask:
+ case X86::BI__builtin_ia32_shuf_f32x4:
+ case X86::BI__builtin_ia32_shuf_f64x2:
+ case X86::BI__builtin_ia32_shuf_i32x4:
+ case X86::BI__builtin_ia32_shuf_i64x2:
+ case X86::BI__builtin_ia32_shufpd512:
+ case X86::BI__builtin_ia32_shufps:
+ case X86::BI__builtin_ia32_shufps256:
+ case X86::BI__builtin_ia32_shufps512:
+ case X86::BI__builtin_ia32_dbpsadbw128:
+ case X86::BI__builtin_ia32_dbpsadbw256:
+ case X86::BI__builtin_ia32_dbpsadbw512:
+ case X86::BI__builtin_ia32_vpshldd128:
+ case X86::BI__builtin_ia32_vpshldd256:
+ case X86::BI__builtin_ia32_vpshldd512:
+ case X86::BI__builtin_ia32_vpshldq128:
+ case X86::BI__builtin_ia32_vpshldq256:
+ case X86::BI__builtin_ia32_vpshldq512:
+ case X86::BI__builtin_ia32_vpshldw128:
+ case X86::BI__builtin_ia32_vpshldw256:
+ case X86::BI__builtin_ia32_vpshldw512:
+ case X86::BI__builtin_ia32_vpshrdd128:
+ case X86::BI__builtin_ia32_vpshrdd256:
+ case X86::BI__builtin_ia32_vpshrdd512:
+ case X86::BI__builtin_ia32_vpshrdq128:
+ case X86::BI__builtin_ia32_vpshrdq256:
+ case X86::BI__builtin_ia32_vpshrdq512:
+ case X86::BI__builtin_ia32_vpshrdw128:
+ case X86::BI__builtin_ia32_vpshrdw256:
+ case X86::BI__builtin_ia32_vpshrdw512:
i = 2; l = 0; u = 255;
break;
case X86::BI__builtin_ia32_fixupimmpd512_mask:
@@ -2480,21 +3722,17 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_scatterpfqps:
i = 4; l = 2; u = 3;
break;
- case X86::BI__builtin_ia32_pcmpestrm128:
- case X86::BI__builtin_ia32_pcmpestri128:
- case X86::BI__builtin_ia32_pcmpestria128:
- case X86::BI__builtin_ia32_pcmpestric128:
- case X86::BI__builtin_ia32_pcmpestrio128:
- case X86::BI__builtin_ia32_pcmpestris128:
- case X86::BI__builtin_ia32_pcmpestriz128:
- i = 4; l = -128; u = 255;
- break;
case X86::BI__builtin_ia32_rndscalesd_round_mask:
case X86::BI__builtin_ia32_rndscaless_round_mask:
i = 4; l = 0; u = 255;
break;
}
- return SemaBuiltinConstantArgRange(TheCall, i, l, u);
+
+ // Note that we don't force a hard error on the range check here, allowing
+ // template-generated or macro-generated dead code to potentially have out-of-
+ // range values. These need to code generate, but don't need to necessarily
+ // make any sense. We use a warning that defaults to an error.
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u, /*RangeIsError*/ false);
}
/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
@@ -2522,7 +3760,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
/// Checks if a the given expression evaluates to null.
///
-/// \brief Returns true if the value evaluates to null.
+/// Returns true if the value evaluates to null.
static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
// If the expression has non-null type, it doesn't evaluate to null.
if (auto nullability
@@ -2566,7 +3804,7 @@ bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
return false;
}
-/// \brief Diagnose use of %s directive in an NSString which is being passed
+/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
static void
DiagnoseCStringFormatDirectiveInCFAPI(Sema &S,
@@ -2612,7 +3850,7 @@ DiagnoseCStringFormatDirectiveInCFAPI(Sema &S,
static bool isNonNullType(ASTContext &ctx, QualType type) {
if (auto nullability = type->getNullability(ctx))
return *nullability == NullabilityKind::NonNull;
-
+
return false;
}
@@ -2636,12 +3874,13 @@ static void CheckNonNullArguments(Sema &S,
return;
}
- for (unsigned Val : NonNull->args()) {
- if (Val >= Args.size())
+ for (const ParamIdx &Idx : NonNull->args()) {
+ unsigned IdxAST = Idx.getASTIndex();
+ if (IdxAST >= Args.size())
continue;
if (NonNullArgs.empty())
NonNullArgs.resize(Args.size());
- NonNullArgs.set(Val);
+ NonNullArgs.set(IdxAST);
}
}
}
@@ -2654,12 +3893,12 @@ static void CheckNonNullArguments(Sema &S,
parms = FD->parameters();
else
parms = cast<ObjCMethodDecl>(FDecl)->parameters();
-
+
unsigned ParamIndex = 0;
for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
I != E; ++I, ++ParamIndex) {
const ParmVarDecl *PVD = *I;
- if (PVD->hasAttr<NonNullAttr>() ||
+ if (PVD->hasAttr<NonNullAttr>() ||
isNonNullType(S.Context, PVD->getType())) {
if (NonNullArgs.empty())
NonNullArgs.resize(Args.size());
@@ -2681,7 +3920,7 @@ static void CheckNonNullArguments(Sema &S,
// Dig out the function prototype, if there is one.
Proto = type->getAs<FunctionProtoType>();
- }
+ }
}
// Fill in non-null argument information from the nullability
@@ -2692,17 +3931,17 @@ static void CheckNonNullArguments(Sema &S,
if (isNonNullType(S.Context, paramType)) {
if (NonNullArgs.empty())
NonNullArgs.resize(Args.size());
-
+
NonNullArgs.set(Index);
}
-
+
++Index;
}
}
}
// Check for non-null arguments.
- for (unsigned ArgIndex = 0, ArgIndexEnd = NonNullArgs.size();
+ for (unsigned ArgIndex = 0, ArgIndexEnd = NonNullArgs.size();
ArgIndex != ArgIndexEnd; ++ArgIndex) {
if (NonNullArgs[ArgIndex])
CheckNonNullArgument(S, Args[ArgIndex], CallSiteLoc);
@@ -2835,7 +4074,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
return false;
}
-bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
+bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
ArrayRef<const Expr *> Args) {
VariadicCallType CallType =
Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
@@ -2985,6 +4224,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Op == AtomicExpr::AO__atomic_exchange_n ||
Op == AtomicExpr::AO__atomic_compare_exchange_n;
bool IsAddSub = false;
+ bool IsMinMax = false;
switch (Op) {
case AtomicExpr::AO__c11_atomic_init:
@@ -3038,6 +4278,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Form = Arithmetic;
break;
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_max:
+ IsMinMax = true;
+ Form = Arithmetic;
+ break;
+
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
@@ -3120,12 +4366,21 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
// gcc does not enforce these rules for GNU atomics, but we do so for sanity.
- if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) {
+ if (IsAddSub && !ValType->isIntegerType()
+ && !ValType->isPointerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
- if (!IsAddSub && !ValType->isIntegerType()) {
+ if (IsMinMax) {
+ const BuiltinType *BT = ValType->getAs<BuiltinType>();
+ if (!BT || (BT->getKind() != BuiltinType::Int &&
+ BT->getKind() != BuiltinType::UInt)) {
+ Diag(DRE->getLocStart(), diag::err_atomic_op_needs_int32_or_ptr);
+ return ExprError();
+ }
+ }
+ if (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
@@ -3168,9 +4423,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
- // atomic_fetch_or takes a pointer to a volatile 'A'. We shouldn't let the
- // volatile-ness of the pointee-type inject itself into the result or the
- // other operands. Similarly atomic_load can take a pointer to a const 'A'.
+ // All atomic operations have an overload which takes a pointer to a volatile
+ // 'A'. We shouldn't let the volatile-ness of the pointee-type inject itself
+ // into the result or the other operands. Similarly atomic_load takes a
+ // pointer to a const 'A'.
ValType.removeLocalVolatile();
ValType.removeLocalConst();
QualType ResultType = ValType;
@@ -3183,16 +4439,27 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// The type of a parameter passed 'by value'. In the GNU atomics, such
// arguments are actually passed as pointers.
QualType ByValType = ValType; // 'CP'
- if (!IsC11 && !IsN)
+ bool IsPassedByAddress = false;
+ if (!IsC11 && !IsN) {
ByValType = Ptr->getType();
+ IsPassedByAddress = true;
+ }
- // 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 != TheCall->getNumArgs(); ++i) {
+ // The first argument's non-CV pointer type is used to deduce the type of
+ // subsequent arguments, except for:
+ // - weak flag (always converted to bool)
+ // - memory order (always converted to int)
+ // - scope (always converted to int)
+ for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) {
QualType Ty;
if (i < NumVals[Form] + 1) {
switch (i) {
+ case 0:
+ // The first argument is always a pointer. It has a fixed type.
+ // It is always dereferenced, a nullptr is undefined.
+ CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart());
+ // Nothing else to do: we already know all we want about this pointer.
+ continue;
case 1:
// The second argument is the non-atomic operand. For arithmetic, this
// is always passed by value, and for a compare_exchange it is always
@@ -3201,14 +4468,16 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
assert(Form != Load);
if (Form == Init || (Form == Arithmetic && ValType->isIntegerType()))
Ty = ValType;
- else if (Form == Copy || Form == Xchg)
+ else if (Form == Copy || Form == Xchg) {
+ if (IsPassedByAddress)
+ // The value pointer is always dereferenced, a nullptr is undefined.
+ CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart());
Ty = ByValType;
- else if (Form == Arithmetic)
+ } else if (Form == Arithmetic)
Ty = Context.getPointerDiffType();
else {
Expr *ValArg = TheCall->getArg(i);
- // Treat this argument as _Nonnull as we want to show a warning if
- // NULL is passed into it.
+ // The value pointer is always dereferenced, a nullptr is undefined.
CheckNonNullArgument(*this, ValArg, DRE->getLocStart());
LangAS AS = LangAS::Default;
// Keep address space of non-atomic pointer type.
@@ -3221,8 +4490,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
}
break;
case 2:
- // The third argument to compare_exchange / GNU exchange is a
- // (pointer to a) desired value.
+ // The third argument to compare_exchange / GNU exchange is the desired
+ // value, either by-value (for the C11 and *_n variant) or as a pointer.
+ if (IsPassedByAddress)
+ CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart());
Ty = ByValType;
break;
case 3:
@@ -3306,7 +4577,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
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__opencl_atomic_load ||
@@ -3393,6 +4664,12 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
return ExprError();
}
+ if (ValType.isConstQualified()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_cannot_be_const)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
+
switch (ValType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
@@ -3467,52 +4744,52 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
bool WarnAboutSemanticsChange = false;
switch (BuiltinID) {
default: llvm_unreachable("Unknown overloaded atomic builtin!");
- case Builtin::BI__sync_fetch_and_add:
+ case Builtin::BI__sync_fetch_and_add:
case Builtin::BI__sync_fetch_and_add_1:
case Builtin::BI__sync_fetch_and_add_2:
case Builtin::BI__sync_fetch_and_add_4:
case Builtin::BI__sync_fetch_and_add_8:
case Builtin::BI__sync_fetch_and_add_16:
- BuiltinIndex = 0;
+ BuiltinIndex = 0;
break;
-
- case Builtin::BI__sync_fetch_and_sub:
+
+ case Builtin::BI__sync_fetch_and_sub:
case Builtin::BI__sync_fetch_and_sub_1:
case Builtin::BI__sync_fetch_and_sub_2:
case Builtin::BI__sync_fetch_and_sub_4:
case Builtin::BI__sync_fetch_and_sub_8:
case Builtin::BI__sync_fetch_and_sub_16:
- BuiltinIndex = 1;
+ BuiltinIndex = 1;
break;
-
- case Builtin::BI__sync_fetch_and_or:
+
+ case Builtin::BI__sync_fetch_and_or:
case Builtin::BI__sync_fetch_and_or_1:
case Builtin::BI__sync_fetch_and_or_2:
case Builtin::BI__sync_fetch_and_or_4:
case Builtin::BI__sync_fetch_and_or_8:
case Builtin::BI__sync_fetch_and_or_16:
- BuiltinIndex = 2;
+ BuiltinIndex = 2;
break;
-
- case Builtin::BI__sync_fetch_and_and:
+
+ case Builtin::BI__sync_fetch_and_and:
case Builtin::BI__sync_fetch_and_and_1:
case Builtin::BI__sync_fetch_and_and_2:
case Builtin::BI__sync_fetch_and_and_4:
case Builtin::BI__sync_fetch_and_and_8:
case Builtin::BI__sync_fetch_and_and_16:
- BuiltinIndex = 3;
+ BuiltinIndex = 3;
break;
- case Builtin::BI__sync_fetch_and_xor:
+ case Builtin::BI__sync_fetch_and_xor:
case Builtin::BI__sync_fetch_and_xor_1:
case Builtin::BI__sync_fetch_and_xor_2:
case Builtin::BI__sync_fetch_and_xor_4:
case Builtin::BI__sync_fetch_and_xor_8:
case Builtin::BI__sync_fetch_and_xor_16:
- BuiltinIndex = 4;
+ BuiltinIndex = 4;
break;
- case Builtin::BI__sync_fetch_and_nand:
+ case Builtin::BI__sync_fetch_and_nand:
case Builtin::BI__sync_fetch_and_nand_1:
case Builtin::BI__sync_fetch_and_nand_2:
case Builtin::BI__sync_fetch_and_nand_4:
@@ -3522,43 +4799,43 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
WarnAboutSemanticsChange = true;
break;
- case Builtin::BI__sync_add_and_fetch:
+ case Builtin::BI__sync_add_and_fetch:
case Builtin::BI__sync_add_and_fetch_1:
case Builtin::BI__sync_add_and_fetch_2:
case Builtin::BI__sync_add_and_fetch_4:
case Builtin::BI__sync_add_and_fetch_8:
case Builtin::BI__sync_add_and_fetch_16:
- BuiltinIndex = 6;
+ BuiltinIndex = 6;
break;
-
- case Builtin::BI__sync_sub_and_fetch:
+
+ case Builtin::BI__sync_sub_and_fetch:
case Builtin::BI__sync_sub_and_fetch_1:
case Builtin::BI__sync_sub_and_fetch_2:
case Builtin::BI__sync_sub_and_fetch_4:
case Builtin::BI__sync_sub_and_fetch_8:
case Builtin::BI__sync_sub_and_fetch_16:
- BuiltinIndex = 7;
+ BuiltinIndex = 7;
break;
-
- case Builtin::BI__sync_and_and_fetch:
+
+ case Builtin::BI__sync_and_and_fetch:
case Builtin::BI__sync_and_and_fetch_1:
case Builtin::BI__sync_and_and_fetch_2:
case Builtin::BI__sync_and_and_fetch_4:
case Builtin::BI__sync_and_and_fetch_8:
case Builtin::BI__sync_and_and_fetch_16:
- BuiltinIndex = 8;
+ BuiltinIndex = 8;
break;
-
- case Builtin::BI__sync_or_and_fetch:
+
+ case Builtin::BI__sync_or_and_fetch:
case Builtin::BI__sync_or_and_fetch_1:
case Builtin::BI__sync_or_and_fetch_2:
case Builtin::BI__sync_or_and_fetch_4:
case Builtin::BI__sync_or_and_fetch_8:
case Builtin::BI__sync_or_and_fetch_16:
- BuiltinIndex = 9;
+ BuiltinIndex = 9;
break;
-
- case Builtin::BI__sync_xor_and_fetch:
+
+ case Builtin::BI__sync_xor_and_fetch:
case Builtin::BI__sync_xor_and_fetch_1:
case Builtin::BI__sync_xor_and_fetch_2:
case Builtin::BI__sync_xor_and_fetch_4:
@@ -3567,7 +4844,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
BuiltinIndex = 10;
break;
- case Builtin::BI__sync_nand_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch:
case Builtin::BI__sync_nand_and_fetch_1:
case Builtin::BI__sync_nand_and_fetch_2:
case Builtin::BI__sync_nand_and_fetch_4:
@@ -3586,7 +4863,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
BuiltinIndex = 12;
NumFixed = 2;
break;
-
+
case Builtin::BI__sync_bool_compare_and_swap:
case Builtin::BI__sync_bool_compare_and_swap_1:
case Builtin::BI__sync_bool_compare_and_swap_2:
@@ -3597,16 +4874,16 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
NumFixed = 2;
ResultType = Context.BoolTy;
break;
-
- case Builtin::BI__sync_lock_test_and_set:
+
+ case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_lock_test_and_set_1:
case Builtin::BI__sync_lock_test_and_set_2:
case Builtin::BI__sync_lock_test_and_set_4:
case Builtin::BI__sync_lock_test_and_set_8:
case Builtin::BI__sync_lock_test_and_set_16:
- BuiltinIndex = 14;
+ BuiltinIndex = 14;
break;
-
+
case Builtin::BI__sync_lock_release:
case Builtin::BI__sync_lock_release_1:
case Builtin::BI__sync_lock_release_2:
@@ -3617,14 +4894,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
NumFixed = 0;
ResultType = Context.VoidTy;
break;
-
- case Builtin::BI__sync_swap:
+
+ case Builtin::BI__sync_swap:
case Builtin::BI__sync_swap_1:
case Builtin::BI__sync_swap_2:
case Builtin::BI__sync_swap_4:
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
- BuiltinIndex = 16;
+ BuiltinIndex = 16;
break;
}
@@ -4115,21 +5392,25 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
diag::err_typecheck_call_invalid_unary_fp)
<< OrigArg->getType() << OrigArg->getSourceRange();
- // If this is an implicit conversion from float -> float or double, remove it.
+ // If this is an implicit conversion from float -> float, double, or
+ // long double, remove it.
if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
// Only remove standard FloatCasts, leaving other casts inplace
if (Cast->getCastKind() == CK_FloatingCast) {
Expr *CastArg = Cast->getSubExpr();
if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
- assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) ||
- Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) &&
- "promotion from float to either float or double is the only expected cast here");
+ assert(
+ (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) ||
+ Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+ Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) &&
+ "promotion from float to either float, double, or long double is "
+ "the only expected cast here");
Cast->setSubExpr(nullptr);
TheCall->setArg(NumArgs-1, CastArg);
}
}
}
-
+
return false;
}
@@ -4506,20 +5787,20 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
Expr *Arg = TheCall->getArg(ArgNum);
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
-
+
if (Arg->isTypeDependent() || Arg->isValueDependent()) return false;
-
+
if (!Arg->isIntegerConstantExpr(Result, Context))
return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type)
<< FDecl->getDeclName() << Arg->getSourceRange();
-
+
return false;
}
/// SemaBuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr
/// TheCall is a constant expression in the range [Low, High].
bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
- int Low, int High) {
+ int Low, int High, bool RangeIsError) {
llvm::APSInt Result;
// We can't check the value of a dependent argument.
@@ -4531,9 +5812,18 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
return true;
- if (Result.getSExtValue() < Low || Result.getSExtValue() > High)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << Low << High << Arg->getSourceRange();
+ if (Result.getSExtValue() < Low || Result.getSExtValue() > High) {
+ if (RangeIsError)
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << Result.toString(10) << Low << High << Arg->getSourceRange();
+ else
+ // Defer the warning until we know if the code will be emitted so that
+ // dead code can ignore this.
+ DiagRuntimeBehavior(TheCall->getLocStart(), TheCall,
+ PDiag(diag::warn_argument_invalid_range)
+ << Result.toString(10) << Low << High
+ << Arg->getSourceRange());
+ }
return false;
}
@@ -4674,7 +5964,7 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
// TODO: This is less than ideal. Overload this to take a value.
if (SemaBuiltinConstantArg(TheCall, 1, Result))
return true;
-
+
if (Result != 1)
return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val)
<< SourceRange(Arg->getLocStart(), Arg->getLocEnd());
@@ -4941,7 +6231,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
// cannot contain format specifiers and thus are not a security
// liability.
return SLCT_UncheckedLiteral;
-
+
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
@@ -5018,18 +6308,22 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
case Stmt::CXXMemberCallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
- if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {
- unsigned ArgIndex = FA->getFormatIdx();
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- if (MD->isInstance())
- --ArgIndex;
- const Expr *Arg = CE->getArg(ArgIndex - 1);
-
- return checkFormatStringExpr(S, Arg, Args,
- HasVAListArg, format_idx, firstDataArg,
- Type, CallType, InFunctionCall,
- CheckedVarArgs, UncoveredArg, Offset);
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ bool IsFirst = true;
+ StringLiteralCheckType CommonResult;
+ for (const auto *FA : ND->specific_attrs<FormatArgAttr>()) {
+ const Expr *Arg = CE->getArg(FA->getFormatIdx().getASTIndex());
+ StringLiteralCheckType Result = checkFormatStringExpr(
+ S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,
+ CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset);
+ if (IsFirst) {
+ CommonResult = Result;
+ IsFirst = false;
+ }
+ }
+ if (!IsFirst)
+ return CommonResult;
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
unsigned BuiltinID = FD->getBuiltinID();
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
@@ -5049,8 +6343,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
const auto *ME = cast<ObjCMessageExpr>(E);
if (const auto *ND = ME->getMethodDecl()) {
if (const auto *FA = ND->getAttr<FormatArgAttr>()) {
- unsigned ArgIndex = FA->getFormatIdx();
- const Expr *Arg = ME->getArg(ArgIndex - 1);
+ const Expr *Arg = ME->getArg(FA->getFormatIdx().getASTIndex());
return checkFormatStringExpr(
S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,
CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset);
@@ -5333,14 +6626,14 @@ protected:
void HandlePositionalNonpositionalArgs(SourceLocation Loc,
const char *startSpec,
unsigned specifierLen);
-
+
SourceRange getFormatStringRange();
CharSourceRange getSpecifierRange(const char *startSpecifier,
unsigned specifierLen);
SourceLocation getLocationOfByte(const char *x);
const Expr *getDataArg(unsigned i) const;
-
+
bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS,
const analyze_format_string::ConversionSpecifier &CS,
const char *startSpecifier, unsigned specifierLen,
@@ -5654,7 +6947,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag,
Loc, IsStringLocation, StringRange, FixIt);
}
-/// \brief If the format string is not within the funcion call, emit a note
+/// If the format string is not within the function call, emit a note
/// so that the function call and string are in diagnostic messages.
///
/// \param InFunctionCall if true, the format string is within the function
@@ -5759,7 +7052,7 @@ public:
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
const Expr *E);
-
+
void HandleEmptyObjCModifierFlag(const char *startFlag,
unsigned flagLen) override;
@@ -5768,7 +7061,7 @@ public:
void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
const char *flagsEnd,
- const char *conversionPosition)
+ const char *conversionPosition)
override;
};
@@ -5780,7 +7073,7 @@ bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
unsigned specifierLen) {
const analyze_printf::PrintfConversionSpecifier &CS =
FS.getConversionSpecifier();
-
+
return HandleInvalidConversionSpecifier(FS.getArgIndex(),
getLocationOfByte(CS.getStart()),
startSpecifier, specifierLen,
@@ -6311,11 +7604,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
ExprTy = TET->getUnderlyingExpr()->getType();
}
- analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy);
-
- if (match == analyze_printf::ArgType::Match) {
+ const analyze_printf::ArgType::MatchKind Match =
+ AT.matchesType(S.Context, ExprTy);
+ bool Pedantic = Match == analyze_printf::ArgType::NoMatchPedantic;
+ if (Match == analyze_printf::ArgType::Match)
return true;
- }
// Look through argument promotions for our error message's reported type.
// This includes the integral and floating promotions, but excludes array
@@ -6391,6 +7684,12 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
QualType CastTy;
std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
if (!CastTy.isNull()) {
+ // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int
+ // (long in ASTContext). Only complain to pedants.
+ if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") &&
+ (AT.isSizeT() || AT.isPtrdiffT()) &&
+ AT.matchesType(S.Context, CastTy))
+ Pedantic = true;
IntendedTy = CastTy;
ShouldNotPrintDirectly = true;
}
@@ -6398,10 +7697,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// We may be able to offer a FixItHint if it is a supported type.
PrintfSpecifier fixedFS = FS;
- bool success =
+ bool Success =
fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext());
- if (success) {
+ if (Success) {
// Get the fix string from the fixed format specifier
SmallString<16> buf;
llvm::raw_svector_ostream os(buf);
@@ -6410,13 +7709,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) {
- unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
- if (match == analyze_format_string::ArgType::NoMatchPedantic) {
- diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
- }
+ unsigned Diag =
+ Pedantic
+ ? diag::warn_format_conversion_argument_type_mismatch_pedantic
+ : diag::warn_format_conversion_argument_type_mismatch;
// In this case, the specifier is wrong and should be changed to match
// the argument.
- EmitFormatDiagnostic(S.PDiag(diag)
+ EmitFormatDiagnostic(S.PDiag(Diag)
<< AT.getRepresentativeTypeName(S.Context)
<< IntendedTy << IsEnum << E->getSourceRange(),
E->getLocStart(),
@@ -6437,7 +7736,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CastFix << ")";
SmallVector<FixItHint,4> Hints;
- if (!AT.matchesType(S.Context, IntendedTy) || ShouldNotPrintDirectly)
+ if (!AT.matchesType(S.Context, IntendedTy) || ShouldNotPrintDirectly)
Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str()));
if (const CStyleCastExpr *CCast = dyn_cast<CStyleCastExpr>(E)) {
@@ -6469,14 +7768,16 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
Name = TypedefTy->getDecl()->getName();
else
Name = CastTyName;
- EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
- << Name << IntendedTy << IsEnum
- << E->getSourceRange(),
+ unsigned Diag = Pedantic
+ ? diag::warn_format_argument_needs_cast_pedantic
+ : diag::warn_format_argument_needs_cast;
+ EmitFormatDiagnostic(S.PDiag(Diag) << Name << IntendedTy << IsEnum
+ << E->getSourceRange(),
E->getLocStart(), /*IsStringLocation=*/false,
SpecRange, Hints);
} else {
// In this case, the expression could be printed using a different
- // specifier, but we've decided that the specifier is probably correct
+ // specifier, but we've decided that the specifier is probably correct
// and we should cast instead. Just use the normal warning message.
EmitFormatDiagnostic(
S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
@@ -6495,13 +7796,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
switch (S.isValidVarArgType(ExprTy)) {
case Sema::VAK_Valid:
case Sema::VAK_ValidInCXX11: {
- unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
- if (match == analyze_printf::ArgType::NoMatchPedantic) {
- diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
- }
+ unsigned Diag =
+ Pedantic
+ ? diag::warn_format_conversion_argument_type_mismatch_pedantic
+ : diag::warn_format_conversion_argument_type_mismatch;
EmitFormatDiagnostic(
- S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
<< IsEnum << CSR << E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/ false, CSR);
break;
@@ -6551,7 +7852,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
//===--- CHECK: Scanf format string checking ------------------------------===//
-namespace {
+namespace {
class CheckScanfHandler : public CheckFormatHandler {
public:
@@ -6571,7 +7872,7 @@ public:
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) override;
-
+
bool HandleInvalidScanfConversionSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
@@ -6607,7 +7908,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
const char *startSpecifier,
unsigned specifierLen) {
using namespace analyze_scanf;
- using namespace analyze_format_string;
+ using namespace analyze_format_string;
const ScanfConversionSpecifier &CS = FS.getConversionSpecifier();
@@ -6624,7 +7925,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
return false;
}
}
-
+
// Check if the field with is non-zero.
const OptionalAmount &Amt = FS.getFieldWidth();
if (Amt.getHowSpecified() == OptionalAmount::Constant) {
@@ -6684,29 +7985,28 @@ bool CheckScanfHandler::HandleScanfSpecifier(
return true;
}
- analyze_format_string::ArgType::MatchKind match =
+ analyze_format_string::ArgType::MatchKind Match =
AT.matchesType(S.Context, Ex->getType());
- if (match == analyze_format_string::ArgType::Match) {
+ bool Pedantic = Match == analyze_format_string::ArgType::NoMatchPedantic;
+ if (Match == analyze_format_string::ArgType::Match)
return true;
- }
ScanfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),
+ bool Success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),
S.getLangOpts(), S.Context);
- unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
- if (match == analyze_format_string::ArgType::NoMatchPedantic) {
- diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
- }
+ unsigned Diag =
+ Pedantic ? diag::warn_format_conversion_argument_type_mismatch_pedantic
+ : diag::warn_format_conversion_argument_type_mismatch;
- if (success) {
+ if (Success) {
// Get the fix string from the fixed format specifier.
SmallString<128> buf;
llvm::raw_svector_ostream os(buf);
fixedFS.toString(os);
EmitFormatDiagnostic(
- S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context)
+ S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context)
<< Ex->getType() << false << Ex->getSourceRange(),
Ex->getLocStart(),
/*IsStringLocation*/ false,
@@ -6714,7 +8014,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
FixItHint::CreateReplacement(
getSpecifierRange(startSpecifier, specifierLen), os.str()));
} else {
- EmitFormatDiagnostic(S.PDiag(diag)
+ EmitFormatDiagnostic(S.PDiag(Diag)
<< AT.getRepresentativeTypeName(S.Context)
<< Ex->getType() << false << Ex->getSourceRange(),
Ex->getLocStart(),
@@ -7267,7 +8567,7 @@ void Sema::CheckMaxUnsignedZero(const CallExpr *Call,
//===--- CHECK: Standard memory functions ---------------------------------===//
-/// \brief Takes the expression passed to the size_t parameter of functions
+/// Takes the expression passed to the size_t parameter of functions
/// such as memcmp, strncat, etc and warns if it's a comparison.
///
/// This is to catch typos like `if (memcmp(&a, &b, sizeof(a) > 0))`.
@@ -7298,7 +8598,7 @@ static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
return true;
}
-/// \brief Determine whether the given type is or contains a dynamic class type
+/// Determine whether the given type is or contains a dynamic class type
/// (e.g., whether it has a vtable).
static const CXXRecordDecl *getContainedDynamicClass(QualType T,
bool &IsContained) {
@@ -7329,28 +8629,205 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T,
return nullptr;
}
-/// \brief If E is a sizeof expression, returns its argument expression,
+static const UnaryExprOrTypeTraitExpr *getAsSizeOfExpr(const Expr *E) {
+ if (const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E))
+ if (Unary->getKind() == UETT_SizeOf)
+ return Unary;
+ return nullptr;
+}
+
+/// If E is a sizeof expression, returns its argument expression,
/// otherwise returns NULL.
static const Expr *getSizeOfExprArg(const Expr *E) {
- if (const UnaryExprOrTypeTraitExpr *SizeOf =
- dyn_cast<UnaryExprOrTypeTraitExpr>(E))
- if (SizeOf->getKind() == UETT_SizeOf && !SizeOf->isArgumentType())
+ if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E))
+ if (!SizeOf->isArgumentType())
return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
-
return nullptr;
}
-/// \brief If E is a sizeof expression, returns its argument type.
+/// If E is a sizeof expression, returns its argument type.
static QualType getSizeOfArgType(const Expr *E) {
- if (const UnaryExprOrTypeTraitExpr *SizeOf =
- dyn_cast<UnaryExprOrTypeTraitExpr>(E))
- if (SizeOf->getKind() == UETT_SizeOf)
- return SizeOf->getTypeOfArgument();
-
+ if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E))
+ return SizeOf->getTypeOfArgument();
return QualType();
}
-/// \brief Check for dangerous or invalid arguments to memset().
+namespace {
+
+struct SearchNonTrivialToInitializeField
+ : DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField> {
+ using Super =
+ DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>;
+
+ SearchNonTrivialToInitializeField(const Expr *E, Sema &S) : E(E), S(S) {}
+
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+ SourceLocation SL) {
+ if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+ asDerived().visitArray(PDIK, AT, SL);
+ return;
+ }
+
+ Super::visitWithKind(PDIK, FT, SL);
+ }
+
+ void visitARCStrong(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
+ }
+ void visitARCWeak(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
+ }
+ void visitStruct(QualType FT, SourceLocation SL) {
+ for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+ visit(FD->getType(), FD->getLocation());
+ }
+ void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK,
+ const ArrayType *AT, SourceLocation SL) {
+ visit(getContext().getBaseElementType(AT), SL);
+ }
+ void visitTrivial(QualType FT, SourceLocation SL) {}
+
+ static void diag(QualType RT, const Expr *E, Sema &S) {
+ SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation());
+ }
+
+ ASTContext &getContext() { return S.getASTContext(); }
+
+ const Expr *E;
+ Sema &S;
+};
+
+struct SearchNonTrivialToCopyField
+ : CopiedTypeVisitor<SearchNonTrivialToCopyField, false> {
+ using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>;
+
+ SearchNonTrivialToCopyField(const Expr *E, Sema &S) : E(E), S(S) {}
+
+ void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+ SourceLocation SL) {
+ if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+ asDerived().visitArray(PCK, AT, SL);
+ return;
+ }
+
+ Super::visitWithKind(PCK, FT, SL);
+ }
+
+ void visitARCStrong(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
+ }
+ void visitARCWeak(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
+ }
+ void visitStruct(QualType FT, SourceLocation SL) {
+ for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+ visit(FD->getType(), FD->getLocation());
+ }
+ void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT,
+ SourceLocation SL) {
+ visit(getContext().getBaseElementType(AT), SL);
+ }
+ void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
+ SourceLocation SL) {}
+ void visitTrivial(QualType FT, SourceLocation SL) {}
+ void visitVolatileTrivial(QualType FT, SourceLocation SL) {}
+
+ static void diag(QualType RT, const Expr *E, Sema &S) {
+ SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation());
+ }
+
+ ASTContext &getContext() { return S.getASTContext(); }
+
+ const Expr *E;
+ Sema &S;
+};
+
+}
+
+/// Detect if \c SizeofExpr is likely to calculate the sizeof an object.
+static bool doesExprLikelyComputeSize(const Expr *SizeofExpr) {
+ SizeofExpr = SizeofExpr->IgnoreParenImpCasts();
+
+ if (const auto *BO = dyn_cast<BinaryOperator>(SizeofExpr)) {
+ if (BO->getOpcode() != BO_Mul && BO->getOpcode() != BO_Add)
+ return false;
+
+ return doesExprLikelyComputeSize(BO->getLHS()) ||
+ doesExprLikelyComputeSize(BO->getRHS());
+ }
+
+ return getAsSizeOfExpr(SizeofExpr) != nullptr;
+}
+
+/// Check if the ArgLoc originated from a macro passed to the call at CallLoc.
+///
+/// \code
+/// #define MACRO 0
+/// foo(MACRO);
+/// foo(0);
+/// \endcode
+///
+/// This should return true for the first call to foo, but not for the second
+/// (regardless of whether foo is a macro or function).
+static bool isArgumentExpandedFromMacro(SourceManager &SM,
+ SourceLocation CallLoc,
+ SourceLocation ArgLoc) {
+ if (!CallLoc.isMacroID())
+ return SM.getFileID(CallLoc) != SM.getFileID(ArgLoc);
+
+ return SM.getFileID(SM.getImmediateMacroCallerLoc(CallLoc)) !=
+ SM.getFileID(SM.getImmediateMacroCallerLoc(ArgLoc));
+}
+
+/// Diagnose cases like 'memset(buf, sizeof(buf), 0)', which should have the
+/// last two arguments transposed.
+static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) {
+ if (BId != Builtin::BImemset && BId != Builtin::BIbzero)
+ return;
+
+ const Expr *SizeArg =
+ Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts();
+
+ auto isLiteralZero = [](const Expr *E) {
+ return isa<IntegerLiteral>(E) && cast<IntegerLiteral>(E)->getValue() == 0;
+ };
+
+ // If we're memsetting or bzeroing 0 bytes, then this is likely an error.
+ SourceLocation CallLoc = Call->getRParenLoc();
+ SourceManager &SM = S.getSourceManager();
+ if (isLiteralZero(SizeArg) &&
+ !isArgumentExpandedFromMacro(SM, CallLoc, SizeArg->getExprLoc())) {
+
+ SourceLocation DiagLoc = SizeArg->getExprLoc();
+
+ // Some platforms #define bzero to __builtin_memset. See if this is the
+ // case, and if so, emit a better diagnostic.
+ if (BId == Builtin::BIbzero ||
+ (CallLoc.isMacroID() && Lexer::getImmediateMacroName(
+ CallLoc, SM, S.getLangOpts()) == "bzero")) {
+ S.Diag(DiagLoc, diag::warn_suspicious_bzero_size);
+ S.Diag(DiagLoc, diag::note_suspicious_bzero_size_silence);
+ } else if (!isLiteralZero(Call->getArg(1)->IgnoreImpCasts())) {
+ S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0;
+ S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0;
+ }
+ return;
+ }
+
+ // If the second argument to a memset is a sizeof expression and the third
+ // isn't, this is also likely an error. This should catch
+ // 'memset(buf, sizeof(buf), 0xff)'.
+ if (BId == Builtin::BImemset &&
+ doesExprLikelyComputeSize(Call->getArg(1)) &&
+ !doesExprLikelyComputeSize(Call->getArg(2))) {
+ SourceLocation DiagLoc = Call->getArg(1)->getExprLoc();
+ S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 1;
+ S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 1;
+ return;
+ }
+}
+
+/// Check for dangerous or invalid arguments to memset().
///
/// This issues warnings on known problematic, dangerous or unspecified
/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp'
@@ -7379,6 +8856,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
Call->getLocStart(), Call->getRParenLoc()))
return;
+ // Catch cases like 'memset(buf, sizeof(buf), 0)'.
+ CheckMemaccessSize(*this, BId, Call);
+
// We have special checking when the length is a sizeof expression.
QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
@@ -7501,7 +8981,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
else if (BId == Builtin::BImemcmp)
OperationType = 3;
}
-
+
DiagRuntimeBehavior(
Dest->getExprLoc(), Dest,
PDiag(diag::warn_dyn_class_memaccess)
@@ -7515,7 +8995,23 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
PDiag(diag::warn_arc_object_memaccess)
<< ArgIdx << FnName << PointeeTy
<< Call->getCallee()->getSourceRange());
- else
+ else if (const auto *RT = PointeeTy->getAs<RecordType>()) {
+ if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
+ RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
+ DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_cstruct_memaccess)
+ << ArgIdx << FnName << PointeeTy << 0);
+ SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
+ } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
+ RT->getDecl()->isNonTrivialToPrimitiveCopy()) {
+ DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_cstruct_memaccess)
+ << ArgIdx << FnName << PointeeTy << 1);
+ SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
+ } else {
+ continue;
+ }
+ } else
continue;
DiagRuntimeBehavior(
@@ -7539,7 +9035,7 @@ static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) {
const Expr *RHS = BO->getRHS()->IgnoreParenCasts();
const Expr *LHS = BO->getLHS()->IgnoreParenCasts();
-
+
if (isa<IntegerLiteral>(RHS))
Ex = LHS;
else if (isa<IntegerLiteral>(LHS))
@@ -7581,7 +9077,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
if (CheckMemorySizeofForComparison(*this, SizeArg, FnName,
Call->getLocStart(), Call->getRParenLoc()))
return;
-
+
// Look for 'strlcpy(dst, x, sizeof(x))'
if (const Expr *Ex = getSizeOfExprArg(SizeArg))
CompareWithSrc = Ex;
@@ -7604,16 +9100,16 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
const DeclRefExpr *SrcArgDRE = dyn_cast<DeclRefExpr>(SrcArg);
if (!SrcArgDRE)
return;
-
+
const DeclRefExpr *CompareWithSrcDRE = dyn_cast<DeclRefExpr>(CompareWithSrc);
- if (!CompareWithSrcDRE ||
+ if (!CompareWithSrcDRE ||
SrcArgDRE->getDecl() != CompareWithSrcDRE->getDecl())
return;
-
+
const Expr *OriginalSizeArg = Call->getArg(2);
Diag(CompareWithSrcDRE->getLocStart(), diag::warn_strlcpycat_wrong_size)
<< OriginalSizeArg->getSourceRange() << FnName;
-
+
// Output a FIXIT hint if the destination is an array (rather than a
// pointer to an array). This could be enhanced to handle some
// pointers if we know the actual size, like if DstArg is 'array+2'
@@ -7627,7 +9123,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
OS << "sizeof(";
DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
-
+
Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size)
<< FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(),
OS.str());
@@ -7736,421 +9232,12 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
<< FixItHint::CreateReplacement(SR, OS.str());
}
-//===--- CHECK: Return Address of Stack Variable --------------------------===//
-
-static const Expr *EvalVal(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl);
-static const Expr *EvalAddr(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl);
-
-/// CheckReturnStackAddr - Check if a return statement returns the address
-/// of a stack variable.
-static void
-CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc) {
- const Expr *stackE = nullptr;
- SmallVector<const DeclRefExpr *, 8> refVars;
-
- // Perform checking for returned stack addresses, local blocks,
- // label addresses or references to temporaries.
- if (lhsType->isPointerType() ||
- (!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
- stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/nullptr);
- } else if (lhsType->isReferenceType()) {
- stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/nullptr);
- }
-
- if (!stackE)
- return; // Nothing suspicious was found.
-
- // Parameters are initialized in the calling scope, so taking the address
- // of a parameter reference doesn't need a warning.
- for (auto *DRE : refVars)
- if (isa<ParmVarDecl>(DRE->getDecl()))
- return;
-
- SourceLocation diagLoc;
- SourceRange diagRange;
- if (refVars.empty()) {
- diagLoc = stackE->getLocStart();
- diagRange = stackE->getSourceRange();
- } else {
- // We followed through a reference variable. 'stackE' contains the
- // problematic expression but we will warn at the return statement pointing
- // at the reference variable. We will later display the "trail" of
- // reference variables using notes.
- diagLoc = refVars[0]->getLocStart();
- diagRange = refVars[0]->getSourceRange();
- }
-
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) {
- // address of local var
- S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType()
- << DR->getDecl()->getDeclName() << diagRange;
- } else if (isa<BlockExpr>(stackE)) { // local block.
- S.Diag(diagLoc, diag::err_ret_local_block) << diagRange;
- } else if (isa<AddrLabelExpr>(stackE)) { // address of label.
- S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
- } else { // local temporary.
- // If there is an LValue->RValue conversion, then the value of the
- // reference type is used, not the reference.
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(RetValExp)) {
- if (ICE->getCastKind() == CK_LValueToRValue) {
- return;
- }
- }
- S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref)
- << lhsType->isReferenceType() << diagRange;
- }
-
- // Display the "trail" of reference variables that we followed until we
- // found the problematic expression using notes.
- for (unsigned i = 0, e = refVars.size(); i != e; ++i) {
- const VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
- // If this var binds to another reference var, show the range of the next
- // var, otherwise the var binds to the problematic expression, in which case
- // show the range of the expression.
- SourceRange range = (i < e - 1) ? refVars[i + 1]->getSourceRange()
- : stackE->getSourceRange();
- S.Diag(VD->getLocation(), diag::note_ref_var_local_bind)
- << VD->getDeclName() << range;
- }
-}
-
-/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that
-/// check if the expression in a return statement evaluates to an address
-/// to a location on the stack, a local block, an address of a label, or a
-/// reference to local temporary. The recursion is used to traverse the
-/// AST of the return expression, with recursion backtracking when we
-/// encounter a subexpression that (1) clearly does not lead to one of the
-/// above problematic expressions (2) is something we cannot determine leads to
-/// a problematic expression based on such local checking.
-///
-/// Both EvalAddr and EvalVal follow through reference variables to evaluate
-/// the expression that they point to. Such variables are added to the
-/// 'refVars' vector so that we know what the reference variable "trail" was.
-///
-/// EvalAddr processes expressions that are pointers that are used as
-/// references (and not L-values). EvalVal handles all other values.
-/// At the base case of the recursion is a check for the above problematic
-/// expressions.
-///
-/// This implementation handles:
-///
-/// * pointer-to-pointer casts
-/// * implicit conversions from array references to pointers
-/// * taking the address of fields
-/// * arbitrary interplay between "&" and "*" operators
-/// * pointer arithmetic from an address of a stack variable
-/// * taking the address of an array element where the array is on the stack
-static const Expr *EvalAddr(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl) {
- if (E->isTypeDependent())
- return nullptr;
-
- // We should only be called for evaluating pointer expressions.
- assert((E->getType()->isAnyPointerType() ||
- E->getType()->isBlockPointerType() ||
- E->getType()->isObjCQualifiedIdType()) &&
- "EvalAddr only works on pointers");
-
- E = E->IgnoreParens();
-
- // Our "symbolic interpreter" is just a dispatch off the currently
- // viewed AST node. We then recursively traverse the AST by calling
- // EvalAddr and EvalVal appropriately.
- switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass: {
- const DeclRefExpr *DR = cast<DeclRefExpr>(E);
-
- // If we leave the immediate function, the lifetime isn't about to end.
- if (DR->refersToEnclosingVariableOrCapture())
- return nullptr;
-
- if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
- // If this is a reference variable, follow through to the expression that
- // it points to.
- if (V->hasLocalStorage() &&
- V->getType()->isReferenceType() && V->hasInit()) {
- // Add the reference variable to the "trail".
- refVars.push_back(DR);
- return EvalAddr(V->getInit(), refVars, ParentDecl);
- }
-
- return nullptr;
- }
-
- case Stmt::UnaryOperatorClass: {
- // The only unary operator that make sense to handle here
- // is AddrOf. All others don't make sense as pointers.
- const UnaryOperator *U = cast<UnaryOperator>(E);
-
- if (U->getOpcode() == UO_AddrOf)
- return EvalVal(U->getSubExpr(), refVars, ParentDecl);
- return nullptr;
- }
-
- case Stmt::BinaryOperatorClass: {
- // Handle pointer arithmetic. All other binary operators are not valid
- // in this context.
- const BinaryOperator *B = cast<BinaryOperator>(E);
- BinaryOperatorKind op = B->getOpcode();
-
- if (op != BO_Add && op != BO_Sub)
- return nullptr;
-
- const Expr *Base = B->getLHS();
-
- // Determine which argument is the real pointer base. It could be
- // the RHS argument instead of the LHS.
- if (!Base->getType()->isPointerType())
- Base = B->getRHS();
-
- assert(Base->getType()->isPointerType());
- return EvalAddr(Base, refVars, ParentDecl);
- }
-
- // For conditional operators we need to see if either the LHS or RHS are
- // valid DeclRefExpr*s. If one of them is valid, we return it.
- case Stmt::ConditionalOperatorClass: {
- const ConditionalOperator *C = cast<ConditionalOperator>(E);
-
- // Handle the GNU extension for missing LHS.
- // FIXME: That isn't a ConditionalOperator, so doesn't get here.
- if (const Expr *LHSExpr = C->getLHS()) {
- // In C++, we can have a throw-expression, which has 'void' type.
- if (!LHSExpr->getType()->isVoidType())
- if (const Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
- return LHS;
- }
-
- // In C++, we can have a throw-expression, which has 'void' type.
- if (C->getRHS()->getType()->isVoidType())
- return nullptr;
-
- return EvalAddr(C->getRHS(), refVars, ParentDecl);
- }
-
- case Stmt::BlockExprClass:
- if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
- return E; // local block.
- return nullptr;
-
- case Stmt::AddrLabelExprClass:
- return E; // address of label.
-
- case Stmt::ExprWithCleanupsClass:
- return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
- ParentDecl);
-
- // For casts, we need to handle conversions from arrays to
- // pointer values, and pointer-to-pointer conversions.
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- case Stmt::CXXFunctionalCastExprClass:
- case Stmt::ObjCBridgedCastExprClass:
- case Stmt::CXXStaticCastExprClass:
- case Stmt::CXXDynamicCastExprClass:
- case Stmt::CXXConstCastExprClass:
- case Stmt::CXXReinterpretCastExprClass: {
- const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
- switch (cast<CastExpr>(E)->getCastKind()) {
- case CK_LValueToRValue:
- case CK_NoOp:
- case CK_BaseToDerived:
- case CK_DerivedToBase:
- case CK_UncheckedDerivedToBase:
- case CK_Dynamic:
- case CK_CPointerToObjCPointerCast:
- case CK_BlockPointerToObjCPointerCast:
- case CK_AnyPointerToBlockPointerCast:
- return EvalAddr(SubExpr, refVars, ParentDecl);
-
- case CK_ArrayToPointerDecay:
- return EvalVal(SubExpr, refVars, ParentDecl);
-
- case CK_BitCast:
- if (SubExpr->getType()->isAnyPointerType() ||
- SubExpr->getType()->isBlockPointerType() ||
- SubExpr->getType()->isObjCQualifiedIdType())
- return EvalAddr(SubExpr, refVars, ParentDecl);
- else
- return nullptr;
-
- default:
- return nullptr;
- }
- }
-
- case Stmt::MaterializeTemporaryExprClass:
- if (const Expr *Result =
- EvalAddr(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars, ParentDecl))
- return Result;
- return E;
-
- // Everything else: we simply don't reason about them.
- default:
- return nullptr;
- }
-}
-
-/// EvalVal - This function is complements EvalAddr in the mutual recursion.
-/// See the comments for EvalAddr for more details.
-static const Expr *EvalVal(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl) {
- do {
- // We should only be called for evaluating non-pointer expressions, or
- // expressions with a pointer type that are not used as references but
- // instead
- // are l-values (e.g., DeclRefExpr with a pointer type).
-
- // Our "symbolic interpreter" is just a dispatch off the currently
- // viewed AST node. We then recursively traverse the AST by calling
- // EvalAddr and EvalVal appropriately.
-
- E = E->IgnoreParens();
- switch (E->getStmtClass()) {
- case Stmt::ImplicitCastExprClass: {
- const ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
- if (IE->getValueKind() == VK_LValue) {
- E = IE->getSubExpr();
- continue;
- }
- return nullptr;
- }
-
- case Stmt::ExprWithCleanupsClass:
- return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
- ParentDecl);
-
- case Stmt::DeclRefExprClass: {
- // When we hit a DeclRefExpr we are looking at code that refers to a
- // variable's name. If it's not a reference variable we check if it has
- // local storage within the function, and if so, return the expression.
- const DeclRefExpr *DR = cast<DeclRefExpr>(E);
-
- // If we leave the immediate function, the lifetime isn't about to end.
- if (DR->refersToEnclosingVariableOrCapture())
- return nullptr;
-
- if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
- // Check if it refers to itself, e.g. "int& i = i;".
- if (V == ParentDecl)
- return DR;
-
- if (V->hasLocalStorage()) {
- if (!V->getType()->isReferenceType())
- return DR;
-
- // Reference variable, follow through to the expression that
- // it points to.
- if (V->hasInit()) {
- // Add the reference variable to the "trail".
- refVars.push_back(DR);
- return EvalVal(V->getInit(), refVars, V);
- }
- }
- }
-
- return nullptr;
- }
-
- case Stmt::UnaryOperatorClass: {
- // The only unary operator that make sense to handle here
- // is Deref. All others don't resolve to a "name." This includes
- // handling all sorts of rvalues passed to a unary operator.
- const UnaryOperator *U = cast<UnaryOperator>(E);
-
- if (U->getOpcode() == UO_Deref)
- return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
-
- return nullptr;
- }
-
- case Stmt::ArraySubscriptExprClass: {
- // Array subscripts are potential references to data on the stack. We
- // retrieve the DeclRefExpr* for the array variable if it indeed
- // has local storage.
- const auto *ASE = cast<ArraySubscriptExpr>(E);
- if (ASE->isTypeDependent())
- return nullptr;
- return EvalAddr(ASE->getBase(), refVars, ParentDecl);
- }
-
- case Stmt::OMPArraySectionExprClass: {
- return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
- ParentDecl);
- }
-
- case Stmt::ConditionalOperatorClass: {
- // For conditional operators we need to see if either the LHS or RHS are
- // non-NULL Expr's. If one is non-NULL, we return it.
- const ConditionalOperator *C = cast<ConditionalOperator>(E);
-
- // Handle the GNU extension for missing LHS.
- if (const Expr *LHSExpr = C->getLHS()) {
- // In C++, we can have a throw-expression, which has 'void' type.
- if (!LHSExpr->getType()->isVoidType())
- if (const Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
- return LHS;
- }
-
- // In C++, we can have a throw-expression, which has 'void' type.
- if (C->getRHS()->getType()->isVoidType())
- return nullptr;
-
- return EvalVal(C->getRHS(), refVars, ParentDecl);
- }
-
- // Accesses to members are potential references to data on the stack.
- case Stmt::MemberExprClass: {
- const MemberExpr *M = cast<MemberExpr>(E);
-
- // Check for indirect access. We only want direct field accesses.
- if (M->isArrow())
- return nullptr;
-
- // Check whether the member type is itself a reference, in which case
- // we're not going to refer to the member, but to what the member refers
- // to.
- if (M->getMemberDecl()->getType()->isReferenceType())
- return nullptr;
-
- return EvalVal(M->getBase(), refVars, ParentDecl);
- }
-
- case Stmt::MaterializeTemporaryExprClass:
- if (const Expr *Result =
- EvalVal(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars, ParentDecl))
- return Result;
- return E;
-
- default:
- // Check that we don't return or take the address of a reference to a
- // temporary. This is only useful in C++.
- if (!E->isTypeDependent() && E->isRValue())
- return E;
-
- // Everything else: we simply don't reason about them.
- return nullptr;
- }
- } while (true);
-}
-
void
Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc,
bool isObjCMethod,
const AttrVec *Attrs,
const FunctionDecl *FD) {
- CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc);
-
// Check if the return value is null but should not be.
if (((Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs)) ||
(!isObjCMethod && isNonNullType(Context, lhsType))) &&
@@ -8168,7 +9255,7 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
if (Op == OO_New || Op == OO_Array_New) {
const FunctionProtoType *Proto
= FD->getType()->castAs<FunctionProtoType>();
- if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) &&
+ if (!Proto->isNothrow(/*ResultIfDependent*/true) &&
CheckNonNullExpr(*this, RetValExp))
Diag(ReturnLoc, diag::warn_operator_new_returns_null)
<< FD << getLangOpts().CPlusPlus11;
@@ -8917,7 +10004,7 @@ static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
}
-/// \brief Implements -Wsign-compare.
+/// Implements -Wsign-compare.
///
/// \param E the binary operator to check for warnings
static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
@@ -9184,7 +10271,7 @@ static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
}
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
-static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
SourceLocation CContext, unsigned diag,
bool pruneControlFlow = false) {
if (pruneControlFlow) {
@@ -9205,6 +10292,32 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T,
DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow);
}
+/// Analyze the given compound assignment for the possible losing of
+/// floating-point precision.
+static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) {
+ assert(isa<CompoundAssignOperator>(E) &&
+ "Must be compound assignment operation");
+ // Recurse on the LHS and RHS in here
+ AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+ AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+
+ // Now check the outermost expression
+ const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>();
+ const auto *RBT = cast<CompoundAssignOperator>(E)
+ ->getComputationResultType()
+ ->getAs<BuiltinType>();
+
+ // If both source and target are floating points.
+ if (ResultBT && ResultBT->isFloatingPoint() && RBT && RBT->isFloatingPoint())
+ // Builtin FP kinds are ordered by increasing FP rank.
+ if (ResultBT->getKind() < RBT->getKind())
+ // We don't want to warn for system macro.
+ if (!S.SourceMgr.isInSystemMacro(E->getOperatorLoc()))
+ // warn about dropping FP rank.
+ DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(),
+ E->getOperatorLoc(),
+ diag::warn_impcast_float_result_precision);
+}
/// Diagnose an implicit cast from a floating point value to an integer value.
static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
@@ -9233,14 +10346,24 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
llvm::APSInt IntegerValue(S.Context.getIntWidth(T),
T->hasUnsignedIntegerRepresentation());
- if (Value.convertToInteger(IntegerValue, llvm::APFloat::rmTowardZero,
- &isExact) == llvm::APFloat::opOK &&
- isExact) {
+ llvm::APFloat::opStatus Result = Value.convertToInteger(
+ IntegerValue, llvm::APFloat::rmTowardZero, &isExact);
+
+ if (Result == llvm::APFloat::opOK && isExact) {
if (IsLiteral) return;
return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer,
PruneWarnings);
}
+ // Conversion of a floating-point value to a non-bool integer where the
+ // integral part cannot be represented by the integer type is undefined.
+ if (!IsBool && Result == llvm::APFloat::opInvalidOp)
+ return DiagnoseImpCast(
+ S, E, T, CContext,
+ IsLiteral ? diag::warn_impcast_literal_float_to_integer_out_of_range
+ : diag::warn_impcast_float_to_integer_out_of_range,
+ PruneWarnings);
+
unsigned DiagID = 0;
if (IsLiteral) {
// Warn on floating point literal to integer.
@@ -9374,18 +10497,15 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
// Venture through the macro stacks to get to the source of macro arguments.
// The new location is a better location than the complete location that was
// passed in.
- while (S.SourceMgr.isMacroArgExpansion(Loc))
- Loc = S.SourceMgr.getImmediateMacroCallerLoc(Loc);
-
- while (S.SourceMgr.isMacroArgExpansion(CC))
- CC = S.SourceMgr.getImmediateMacroCallerLoc(CC);
+ Loc = S.SourceMgr.getTopMacroCallerLoc(Loc);
+ CC = S.SourceMgr.getTopMacroCallerLoc(CC);
// __null is usually wrapped in a macro. Go up a macro if that is the case.
if (NullKind == Expr::NPCK_GNUNull && Loc.isMacroID()) {
StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
Loc, S.SourceMgr, S.getLangOpts());
if (MacroName == "NULL")
- Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
+ Loc = S.SourceMgr.getImmediateExpansionRange(Loc).getBegin();
}
// Only warn if the null and context location are in the same macro expansion.
@@ -9575,7 +10695,7 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
return;
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
}
-
+
// If the vector cast is cast between two vectors of the same size, it is
// a bitcast, not a conversion.
if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target))
@@ -9756,7 +10876,7 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
// We also want to warn about it in -Wconversion.
// So if -Wconversion is off, use a completely identical diagnostic
// in the sign-compare group.
- // The conditional-checking code will
+ // The conditional-checking code will
if (ICContext) {
DiagID = diag::warn_impcast_integer_sign_conditional;
*ICContext = true;
@@ -9777,7 +10897,7 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
Source = S.Context.getCanonicalType(SourceType).getTypePtr();
}
}
-
+
if (const EnumType *SourceEnum = Source->getAs<EnumType>())
if (const EnumType *TargetEnum = Target->getAs<EnumType>())
if (SourceEnum->getDecl()->hasNameForLinkage() &&
@@ -9786,7 +10906,7 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
if (S.SourceMgr.isInSystemMacro(CC))
return;
- return DiagnoseImpCast(S, E, SourceType, T, CC,
+ return DiagnoseImpCast(S, E, SourceType, T, CC,
diag::warn_impcast_different_enum_types);
}
}
@@ -9825,7 +10945,7 @@ static void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
// ...then check whether it would have warned about either of the
// candidates for a signedness conversion to the condition type.
if (E->getType() == T) return;
-
+
Suspicious = false;
CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(),
E->getType(), CC, &Suspicious);
@@ -9852,7 +10972,7 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
if (E->isTypeDependent() || E->isValueDependent())
return;
-
+
// For conditional operators, we analyze the arguments as if they
// were being fed directly into the output.
if (isa<ConditionalOperator>(E)) {
@@ -9896,6 +11016,9 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
// And with simple assignments.
if (BO->getOpcode() == BO_Assign)
return AnalyzeAssignment(S, BO);
+ // And with compound assignments.
+ if (BO->isAssignmentOp())
+ return AnalyzeCompoundAssignment(S, BO);
}
// These break the otherwise-useful invariant below. Fortunately,
@@ -9939,7 +11062,7 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
::CheckBoolLikeConversion(S, U->getSubExpr(), CC);
}
-/// Diagnose integer type and any valid implicit convertion to it.
+/// Diagnose integer type and any valid implicit conversion to it.
static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
// Taking into account implicit conversions,
// allow any integer.
@@ -10002,7 +11125,7 @@ static bool IsInAnyMacroBody(const SourceManager &SM, SourceLocation Loc) {
return false;
}
-/// \brief Diagnose pointers that are always non-null.
+/// Diagnose pointers that are always non-null.
/// \param E the expression containing the pointer
/// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is
/// compared to a null pointer
@@ -10106,8 +11229,8 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
return;
}
- for (unsigned ArgNo : NonNull->args()) {
- if (ArgNo == ParamNo) {
+ for (const ParamIdx &ArgNo : NonNull->args()) {
+ if (ArgNo.getASTIndex() == ParamNo) {
ComplainAboutNonnullParamOrCall(NonNull);
return;
}
@@ -10228,29 +11351,33 @@ void Sema::CheckForIntOverflow (Expr *E) {
SmallVector<Expr *, 2> Exprs(1, E);
do {
- Expr *E = Exprs.pop_back_val();
+ Expr *OriginalE = Exprs.pop_back_val();
+ Expr *E = OriginalE->IgnoreParenCasts();
- if (isa<BinaryOperator>(E->IgnoreParenCasts())) {
- E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ if (isa<BinaryOperator>(E)) {
+ E->EvaluateForOverflow(Context);
continue;
}
- if (auto InitList = dyn_cast<InitListExpr>(E))
+ if (auto InitList = dyn_cast<InitListExpr>(OriginalE))
Exprs.append(InitList->inits().begin(), InitList->inits().end());
-
- if (isa<ObjCBoxedExpr>(E))
- E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ else if (isa<ObjCBoxedExpr>(OriginalE))
+ E->EvaluateForOverflow(Context);
+ else if (auto Call = dyn_cast<CallExpr>(E))
+ Exprs.append(Call->arg_begin(), Call->arg_end());
+ else if (auto Message = dyn_cast<ObjCMessageExpr>(E))
+ Exprs.append(Message->arg_begin(), Message->arg_end());
} while (!Exprs.empty());
}
namespace {
-/// \brief Visitor for expressions which looks for unsequenced operations on the
+/// Visitor for expressions which looks for unsequenced operations on the
/// same object.
class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
using Base = EvaluatedExprVisitor<SequenceChecker>;
- /// \brief A tree of sequenced regions within an expression. Two regions are
+ /// 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
/// finish processing an expression with sequencing, such as a comma
/// expression, we fold its tree nodes into its parent, since they are
@@ -10264,7 +11391,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
SmallVector<Value, 8> Values;
public:
- /// \brief A region within an expression which may be sequenced with respect
+ /// A region within an expression which may be sequenced with respect
/// to some other region.
class Seq {
friend class SequenceTree;
@@ -10280,7 +11407,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
SequenceTree() { Values.push_back(Value(0)); }
Seq root() const { return Seq(0); }
- /// \brief Create a new sequence of operations, which is an unsequenced
+ /// Create a new sequence of operations, which is an unsequenced
/// subset of \p Parent. This sequence of operations is sequenced with
/// respect to other children of \p Parent.
Seq allocate(Seq Parent) {
@@ -10288,12 +11415,12 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
return Seq(Values.size() - 1);
}
- /// \brief Merge a sequence of operations into its parent.
+ /// Merge a sequence of operations into its parent.
void merge(Seq S) {
Values[S.Index].Merged = true;
}
- /// \brief Determine whether two operations are unsequenced. This operation
+ /// Determine whether two operations are unsequenced. This operation
/// is asymmetric: \p Cur should be the more recent sequence, and \p Old
/// should have been merged into its parent as appropriate.
bool isUnsequenced(Seq Cur, Seq Old) {
@@ -10308,7 +11435,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
}
private:
- /// \brief Pick a representative for a sequence.
+ /// Pick a representative for a sequence.
unsigned representative(unsigned K) {
if (Values[K].Merged)
// Perform path compression as we go.
@@ -10429,7 +11556,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
bool EvalOK = true;
} *EvalTracker = nullptr;
- /// \brief Find the object which is produced by the specified expression,
+ /// Find the object which is produced by the specified expression,
/// if any.
Object getObject(Expr *E, bool Mod) const {
E = E->IgnoreParenCasts();
@@ -10451,7 +11578,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
return nullptr;
}
- /// \brief Note that an object was modified or used by an expression.
+ /// Note that an object was modified or used by an expression.
void addUsage(UsageInfo &UI, Object O, Expr *Ref, UsageKind UK) {
Usage &U = UI.Uses[UK];
if (!U.Use || !Tree.isUnsequenced(Region, U.Seq)) {
@@ -10462,7 +11589,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
}
}
- /// \brief Check whether a modification or use conflicts with a prior usage.
+ /// Check whether a modification or use conflicts with a prior usage.
void checkUsage(Object O, UsageInfo &UI, Expr *Ref, UsageKind OtherKind,
bool IsModMod) {
if (UI.Diagnosed)
@@ -10841,23 +11968,18 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
// information is added for it.
diagnoseArrayStarInParamType(*this, PType, Param->getLocation());
- // MSVC destroys objects passed by value in the callee. Therefore a
- // function definition which takes such a parameter must be able to call the
- // object's destructor. However, we don't perform any direct access check
- // on the dtor.
- if (getLangOpts().CPlusPlus && Context.getTargetInfo()
- .getCXXABI()
- .areArgsDestroyedLeftToRightInCallee()) {
- if (!Param->isInvalidDecl()) {
- if (const RecordType *RT = Param->getType()->getAs<RecordType>()) {
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (!ClassDecl->isInvalidDecl() &&
- !ClassDecl->hasIrrelevantDestructor() &&
- !ClassDecl->isDependentContext()) {
- CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
- MarkFunctionReferenced(Param->getLocation(), Destructor);
- DiagnoseUseOfDecl(Destructor, Param->getLocation());
- }
+ // If the parameter is a c++ class type and it has to be destructed in the
+ // callee function, declare the destructor so that it can be called by the
+ // callee function. Do not perform any direct access check on the dtor here.
+ if (!Param->isInvalidDecl()) {
+ if (CXXRecordDecl *ClassDecl = Param->getType()->getAsCXXRecordDecl()) {
+ if (!ClassDecl->isInvalidDecl() &&
+ !ClassDecl->hasIrrelevantDestructor() &&
+ !ClassDecl->isDependentContext() &&
+ ClassDecl->isParamDestroyedInCallee()) {
+ CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+ MarkFunctionReferenced(Param->getLocation(), Destructor);
+ DiagnoseUseOfDecl(Destructor, Param->getLocation());
}
}
}
@@ -10940,7 +12062,7 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
<< TRange << Op->getSourceRange();
}
-/// \brief Check whether this array fits the idiom of a size-one tail padded
+/// Check whether this array fits the idiom of a size-one tail padded
/// array member of a struct.
///
/// We avoid emitting out-of-bounds access warnings for such arrays as they are
@@ -11010,9 +12132,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(DRE->getDecl());
+ ND = DRE->getDecl();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+ ND = ME->getMemberDecl();
if (index.isUnsigned() || !index.isNegative()) {
llvm::APInt size = ArrayTy->getSize();
@@ -11095,9 +12217,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
dyn_cast<ArraySubscriptExpr>(BaseExpr))
BaseExpr = ASE->getBase()->IgnoreParenCasts();
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(DRE->getDecl());
+ ND = DRE->getDecl();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+ ND = ME->getMemberDecl();
}
if (ND)
@@ -11115,7 +12237,12 @@ void Sema::CheckArrayAccess(const Expr *expr) {
const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE,
AllowOnePastEnd > 0);
- return;
+ expr = ASE->getBase();
+ break;
+ }
+ case Stmt::MemberExprClass: {
+ expr = cast<MemberExpr>(expr)->getBase();
+ break;
}
case Stmt::OMPArraySectionExprClass: {
const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
@@ -11299,11 +12426,11 @@ namespace {
}
void VisitBlockExpr(BlockExpr *block) {
- // Look inside nested blocks
+ // Look inside nested blocks
if (block->getBlockDecl()->capturesVariable(Variable))
Visit(block->getBlockDecl()->getBody());
}
-
+
void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) {
if (Capturer) return;
if (OVE->getSourceExpr())
@@ -11356,7 +12483,7 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
}
}
}
-
+
BlockExpr *block = dyn_cast<BlockExpr>(e);
if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
return nullptr;
@@ -11525,7 +12652,7 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
if (ArgRE->isObjCSelfExpr()) {
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << ArgRE->getDecl()->getName() << StringRef("super");
+ << ArgRE->getDecl() << StringRef("'super'");
}
}
} else {
@@ -11541,11 +12668,11 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
ValueDecl *Decl = ReceiverRE->getDecl();
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << Decl->getName() << Decl->getName();
+ << Decl << Decl;
if (!ArgRE->isObjCSelfExpr()) {
Diag(Decl->getLocation(),
diag::note_objc_circular_container_declared_here)
- << Decl->getName();
+ << Decl;
}
}
}
@@ -11555,10 +12682,10 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
ObjCIvarDecl *Decl = IvarRE->getDecl();
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << Decl->getName() << Decl->getName();
+ << Decl << Decl;
Diag(Decl->getLocation(),
diag::note_objc_circular_container_declared_here)
- << Decl->getName();
+ << Decl;
}
}
}
@@ -11609,12 +12736,12 @@ void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) {
RetainCycleOwner Owner;
if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner))
return;
-
+
// Because we don't have an expression for the variable, we have to set the
// location explicitly here.
Owner.Loc = Var->getLocation();
Owner.Range = Var->getSourceRange();
-
+
if (Expr *Capturer = findCapturingExpr(*this, Init, Owner))
diagnoseRetainCycle(*this, Capturer, Owner);
}
@@ -11687,7 +12814,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
if (PD)
LHSType = PD->getType();
}
-
+
if (LHSType.isNull())
LHSType = LHS->getType();
@@ -11704,14 +12831,14 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
// FIXME. Check for other life times.
if (LT != Qualifiers::OCL_None)
return;
-
+
if (PRE) {
if (PRE->isImplicitProperty())
return;
const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
if (!PD)
return;
-
+
unsigned Attributes = PD->getPropertyAttributes();
if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) {
// when 'assign' attribute was not explicitly specified
@@ -11721,7 +12848,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
if (!(AsWrittenAttr & ObjCPropertyDecl::OBJC_PR_assign) &&
LHSType->isObjCRetainableType())
return;
-
+
while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
if (cast->getCastKind() == CK_ARCConsumeObject) {
Diag(Loc, diag::warn_arc_retained_property_assign)
@@ -11951,7 +13078,7 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
-/// \brief Check if two enumeration types are layout-compatible.
+/// Check if two enumeration types are layout-compatible.
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
@@ -11960,7 +13087,7 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
C.hasSameType(ED1->getIntegerType(), ED2->getIntegerType());
}
-/// \brief Check if two fields are layout-compatible.
+/// Check if two fields are layout-compatible.
static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
FieldDecl *Field2) {
if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
@@ -11981,7 +13108,7 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
return true;
}
-/// \brief Check if two standard-layout structs are layout-compatible.
+/// Check if two standard-layout structs are layout-compatible.
/// (C++11 [class.mem] p17)
static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
RecordDecl *RD2) {
@@ -12025,7 +13152,7 @@ static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
return true;
}
-/// \brief Check if two standard-layout unions are layout-compatible.
+/// Check if two standard-layout unions are layout-compatible.
/// (C++11 [class.mem] p18)
static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
RecordDecl *RD2) {
@@ -12064,7 +13191,7 @@ static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
return isLayoutCompatibleStruct(C, RD1, RD2);
}
-/// \brief Check if two types are layout-compatible in C++11 sense.
+/// Check if two types are layout-compatible in C++11 sense.
static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
if (T1.isNull() || T2.isNull())
return false;
@@ -12102,7 +13229,7 @@ static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
//===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----//
-/// \brief Given a type tag expression find the type tag itself.
+/// Given a type tag expression find the type tag itself.
///
/// \param TypeExpr Type tag expression, as it appears in user's code.
///
@@ -12173,7 +13300,7 @@ static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
}
}
-/// \brief Retrieve the C type corresponding to type tag TypeExpr.
+/// Retrieve the C type corresponding to type tag TypeExpr.
///
/// \param TypeExpr Expression that specifies a type tag.
///
@@ -12267,13 +13394,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
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.
+ unsigned TypeTagIdxAST = Attr->getTypeTagIdx().getASTIndex();
+ if (TypeTagIdxAST >= ExprArgs.size()) {
Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
- << 0 << Attr->getTypeTagIdx() + 1;
+ << 0 << Attr->getTypeTagIdx().getSourceIndex();
return;
}
- const Expr *TypeTagExpr = ExprArgs[Attr->getTypeTagIdx()];
+ const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];
bool FoundWrongKind;
TypeTagData TypeInfo;
if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context,
@@ -12287,13 +13414,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
}
// Retrieve the argument representing the 'arg_idx'.
- if (Attr->getArgumentIdx() >= ExprArgs.size()) {
- // Add 1 to display the user's specified value.
+ unsigned ArgumentIdxAST = Attr->getArgumentIdx().getASTIndex();
+ if (ArgumentIdxAST >= ExprArgs.size()) {
Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
- << 1 << Attr->getArgumentIdx() + 1;
+ << 1 << Attr->getArgumentIdx().getSourceIndex();
return;
}
- const Expr *ArgumentExpr = ExprArgs[Attr->getArgumentIdx()];
+ const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];
if (IsPointerAttr) {
// Skip implicit cast of pointer to `void *' (as a function argument).
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr))
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index 2acc896d53d7..30af826ef6cc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -40,39 +40,39 @@ using namespace clang;
using namespace sema;
namespace {
- /// \brief A container of code-completion results.
+ /// A container of code-completion results.
class ResultBuilder {
public:
- /// \brief The type of a name-lookup filter, which can be provided to the
+ /// The type of a name-lookup filter, which can be provided to the
/// name-lookup routines to specify which declarations should be included in
/// the result set (when it returns true) and which declarations should be
/// filtered out (returns false).
typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
typedef CodeCompletionResult Result;
-
+
private:
- /// \brief The actual results we have found.
+ /// The actual results we have found.
std::vector<Result> Results;
-
- /// \brief A record of all of the declarations we have found and placed
+
+ /// A record of all of the declarations we have found and placed
/// into the result set, used to ensure that no declaration ever gets into
/// the result set twice.
llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
-
+
typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
- /// \brief An entry in the shadow map, which is optimized to store
+ /// An entry in the shadow map, which is optimized to store
/// a single (declaration, index) mapping (the common case) but
/// can also store a list of (declaration, index) mappings.
class ShadowMapEntry {
typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
- /// \brief Contains either the solitary NamedDecl * or a vector
+ /// Contains either the solitary NamedDecl * or a vector
/// of (declaration, index) pairs.
llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
- /// \brief When the entry contains a single declaration, this is
+ /// When the entry contains a single declaration, this is
/// the index associated with that entry.
unsigned SingleDeclIndex;
@@ -115,72 +115,72 @@ namespace {
iterator end() const;
};
- /// \brief A mapping from declaration names to the declarations that have
+ /// A mapping from declaration names to the declarations that have
/// this name within a particular scope and their index within the list of
/// results.
typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
-
- /// \brief The semantic analysis object for which results are being
+
+ /// The semantic analysis object for which results are being
/// produced.
Sema &SemaRef;
- /// \brief The allocator used to allocate new code-completion strings.
+ /// The allocator used to allocate new code-completion strings.
CodeCompletionAllocator &Allocator;
CodeCompletionTUInfo &CCTUInfo;
-
- /// \brief If non-NULL, a filter function used to remove any code-completion
+
+ /// If non-NULL, a filter function used to remove any code-completion
/// results that are not desirable.
LookupFilter Filter;
- /// \brief Whether we should allow declarations as
+ /// Whether we should allow declarations as
/// nested-name-specifiers that would otherwise be filtered out.
bool AllowNestedNameSpecifiers;
- /// \brief If set, the type that we would prefer our resulting value
+ /// If set, the type that we would prefer our resulting value
/// declarations to have.
///
- /// Closely matching the preferred type gives a boost to a result's
+ /// Closely matching the preferred type gives a boost to a result's
/// priority.
CanQualType PreferredType;
-
- /// \brief A list of shadow maps, which is used to model name hiding at
+
+ /// A list of shadow maps, which is used to model name hiding at
/// different levels of, e.g., the inheritance hierarchy.
std::list<ShadowMap> ShadowMaps;
-
- /// \brief If we're potentially referring to a C++ member function, the set
+
+ /// If we're potentially referring to a C++ member function, the set
/// of qualifiers applied to the object type.
Qualifiers ObjectTypeQualifiers;
-
- /// \brief Whether the \p ObjectTypeQualifiers field is active.
+
+ /// Whether the \p ObjectTypeQualifiers field is active.
bool HasObjectTypeQualifiers;
-
- /// \brief The selector that we prefer.
+
+ /// The selector that we prefer.
Selector PreferredSelector;
-
- /// \brief The completion context in which we are gathering results.
+
+ /// The completion context in which we are gathering results.
CodeCompletionContext CompletionContext;
-
- /// \brief If we are in an instance method definition, the \@implementation
+
+ /// If we are in an instance method definition, the \@implementation
/// object.
ObjCImplementationDecl *ObjCImplementation;
void AdjustResultPriorityForDecl(Result &R);
void MaybeAddConstructorResults(Result R);
-
+
public:
explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
const CodeCompletionContext &CompletionContext,
LookupFilter Filter = nullptr)
: SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
- Filter(Filter),
- AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
+ Filter(Filter),
+ AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
CompletionContext(CompletionContext),
ObjCImplementation(nullptr)
- {
- // If this is an Objective-C instance method definition, dig out the
+ {
+ // If this is an Objective-C instance method definition, dig out the
// corresponding implementation.
switch (CompletionContext.getKind()) {
case CodeCompletionContext::CCC_Expression:
@@ -193,23 +193,23 @@ namespace {
if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
ObjCImplementation = Interface->getImplementation();
break;
-
+
default:
break;
}
}
- /// \brief Determine the priority for a reference to the given declaration.
+ /// Determine the priority for a reference to the given declaration.
unsigned getBasePriority(const NamedDecl *D);
- /// \brief Whether we should include code patterns in the completion
+ /// Whether we should include code patterns in the completion
/// results.
bool includeCodePatterns() const {
- return SemaRef.CodeCompleter &&
+ return SemaRef.CodeCompleter &&
SemaRef.CodeCompleter->includeCodePatterns();
}
-
- /// \brief Set the filter used for code-completion results.
+
+ /// Set the filter used for code-completion results.
void setFilter(LookupFilter Filter) {
this->Filter = Filter;
}
@@ -217,25 +217,25 @@ namespace {
Result *data() { return Results.empty()? nullptr : &Results.front(); }
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
-
- /// \brief Specify the preferred type.
- void setPreferredType(QualType T) {
- PreferredType = SemaRef.Context.getCanonicalType(T);
+
+ /// Specify the preferred type.
+ void setPreferredType(QualType T) {
+ PreferredType = SemaRef.Context.getCanonicalType(T);
}
-
- /// \brief Set the cv-qualifiers on the object type, for us in filtering
+
+ /// Set the cv-qualifiers on the object type, for us in filtering
/// calls to member functions.
///
/// When there are qualifiers in this set, they will be used to filter
- /// out member functions that aren't available (because there will be a
+ /// out member functions that aren't available (because there will be a
/// cv-qualifier mismatch) or prefer functions with an exact qualifier
/// match.
void setObjectTypeQualifiers(Qualifiers Quals) {
ObjectTypeQualifiers = Quals;
HasObjectTypeQualifiers = true;
}
-
- /// \brief Set the preferred selector.
+
+ /// Set the preferred selector.
///
/// When an Objective-C method declaration result is added, and that
/// method's selector matches this preferred selector, we give that method
@@ -243,28 +243,28 @@ namespace {
void setPreferredSelector(Selector Sel) {
PreferredSelector = Sel;
}
-
- /// \brief Retrieve the code-completion context for which results are
+
+ /// Retrieve the code-completion context for which results are
/// being collected.
- const CodeCompletionContext &getCompletionContext() const {
- return CompletionContext;
+ const CodeCompletionContext &getCompletionContext() const {
+ return CompletionContext;
}
-
- /// \brief Specify whether nested-name-specifiers are allowed.
+
+ /// Specify whether nested-name-specifiers are allowed.
void allowNestedNameSpecifiers(bool Allow = true) {
AllowNestedNameSpecifiers = Allow;
}
- /// \brief Return the semantic analysis object for which we are collecting
+ /// Return the semantic analysis object for which we are collecting
/// code completion results.
Sema &getSema() const { return SemaRef; }
-
- /// \brief Retrieve the allocator used to allocate code completion strings.
+
+ /// Retrieve the allocator used to allocate code completion strings.
CodeCompletionAllocator &getAllocator() const { return Allocator; }
CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
-
- /// \brief Determine whether the given declaration is at all interesting
+
+ /// Determine whether the given declaration is at all interesting
/// as a code-completion result.
///
/// \param ND the declaration that we are inspecting.
@@ -273,8 +273,8 @@ namespace {
/// only interesting when it is a nested-name-specifier.
bool isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const;
-
- /// \brief Check whether the result is hidden by the Hiding declaration.
+
+ /// Check whether the result is hidden by the Hiding declaration.
///
/// \returns true if the result is hidden and cannot be found, false if
/// the hidden result could still be found. When false, \p R may be
@@ -282,9 +282,9 @@ namespace {
/// qualification).
bool CheckHiddenResult(Result &R, DeclContext *CurContext,
const NamedDecl *Hiding);
-
- /// \brief Add a new result to this result set (if it isn't already in one
- /// of the shadow maps), or replace an existing result (for, e.g., a
+
+ /// Add a new result to this result set (if it isn't already in one
+ /// of the shadow maps), or replace an existing result (for, e.g., a
/// redeclaration).
///
/// \param R the result to add (if it is unique).
@@ -292,7 +292,7 @@ namespace {
/// \param CurContext the context in which this result will be named.
void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
- /// \brief Add a new result to this result set, where we already know
+ /// Add a new result to this result set, where we already know
/// the hiding declaration (if any).
///
/// \param R the result to add (if it is unique).
@@ -305,24 +305,29 @@ namespace {
/// class of the searched context.
void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
bool InBaseClass);
-
- /// \brief Add a new non-declaration result to this result set.
+
+ /// Add a new non-declaration result to this result set.
void AddResult(Result R);
- /// \brief Enter into a new scope.
+ /// Enter into a new scope.
void EnterNewScope();
-
- /// \brief Exit from the current scope.
+
+ /// Exit from the current scope.
void ExitScope();
-
- /// \brief Ignore this declaration, if it is seen again.
+
+ /// Ignore this declaration, if it is seen again.
void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+ /// Add a visited context.
+ void addVisitedContext(DeclContext *Ctx) {
+ CompletionContext.addVisitedContext(Ctx);
+ }
+
/// \name Name lookup predicates
///
/// These predicates can be passed to the name lookup functions to filter the
/// results of name lookup. All of the predicates have the same type, so that
- ///
+ ///
//@{
bool IsOrdinaryName(const NamedDecl *ND) const;
bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
@@ -341,8 +346,8 @@ namespace {
bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
bool IsObjCCollection(const NamedDecl *ND) const;
bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
- //@}
- };
+ //@}
+ };
}
class ResultBuilder::ShadowMapEntry::iterator {
@@ -354,7 +359,7 @@ public:
typedef value_type reference;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
-
+
class pointer {
DeclIndexPair Value;
@@ -415,7 +420,7 @@ public:
}
};
-ResultBuilder::ShadowMapEntry::iterator
+ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::begin() const {
if (DeclOrVector.isNull())
return iterator();
@@ -426,7 +431,7 @@ ResultBuilder::ShadowMapEntry::begin() const {
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
}
-ResultBuilder::ShadowMapEntry::iterator
+ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::end() const {
if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
return iterator();
@@ -434,7 +439,7 @@ ResultBuilder::ShadowMapEntry::end() const {
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
}
-/// \brief Compute the qualification required to get from the current context
+/// Compute the qualification required to get from the current context
/// (\p CurContext) to the target context (\p TargetContext).
///
/// \param Context the AST context in which the qualification will be used.
@@ -442,7 +447,7 @@ ResultBuilder::ShadowMapEntry::end() const {
/// \param CurContext the context where an entity is being named, which is
/// typically based on the current scope.
///
-/// \param TargetContext the context in which the named entity actually
+/// \param TargetContext the context in which the named entity actually
/// resides.
///
/// \returns a nested name specifier that refers into the target context, or
@@ -452,14 +457,14 @@ getRequiredQualification(ASTContext &Context,
const DeclContext *CurContext,
const DeclContext *TargetContext) {
SmallVector<const DeclContext *, 4> TargetParents;
-
+
for (const DeclContext *CommonAncestor = TargetContext;
CommonAncestor && !CommonAncestor->Encloses(CurContext);
CommonAncestor = CommonAncestor->getLookupParent()) {
if (CommonAncestor->isTransparentContext() ||
CommonAncestor->isFunctionOrMethod())
continue;
-
+
TargetParents.push_back(CommonAncestor);
}
@@ -477,7 +482,7 @@ getRequiredQualification(ASTContext &Context,
Result = NestedNameSpecifier::Create(Context, Result,
false,
Context.getTypeDeclType(TD).getTypePtr());
- }
+ }
return Result;
}
@@ -526,17 +531,17 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
// Skip unnamed entities.
if (!ND->getDeclName())
return false;
-
+
// Friend declarations and declarations introduced due to friends are never
// added as results.
if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
return false;
-
+
// Class template (partial) specializations are never added as results.
if (isa<ClassTemplateSpecializationDecl>(ND) ||
isa<ClassTemplatePartialSpecializationDecl>(ND))
return false;
-
+
// Using declarations themselves are never added as results.
if (isa<UsingDecl>(ND))
return false;
@@ -554,17 +559,17 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
// Filter out any unwanted results.
if (Filter && !(this->*Filter)(Named)) {
// Check whether it is interesting as a nested-name-specifier.
- if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
+ if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
IsNestedNameSpecifier(ND) &&
(Filter != &ResultBuilder::IsMember ||
- (isa<CXXRecordDecl>(ND) &&
+ (isa<CXXRecordDecl>(ND) &&
cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
AsNestedNameSpecifier = true;
return true;
}
return false;
- }
+ }
// ... then it must be interesting!
return true;
}
@@ -576,29 +581,29 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
// name if we introduce the tag type.
if (!SemaRef.getLangOpts().CPlusPlus)
return true;
-
+
const DeclContext *HiddenCtx =
R.Declaration->getDeclContext()->getRedeclContext();
-
+
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
return true;
-
+
if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
return true;
-
+
// We can refer to the result with the appropriate qualification. Do it.
R.Hidden = true;
R.QualifierIsInformative = false;
-
+
if (!R.Qualifier)
- R.Qualifier = getRequiredQualification(SemaRef.Context,
- CurContext,
+ R.Qualifier = getRequiredQualification(SemaRef.Context,
+ CurContext,
R.Declaration->getDeclContext());
return false;
}
-/// \brief A simplified classification of types used to determine whether two
+/// A simplified classification of types used to determine whether two
/// types are "similar enough" when adjusting priorities.
SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (T->getTypeClass()) {
@@ -606,77 +611,77 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (cast<BuiltinType>(T)->getKind()) {
case BuiltinType::Void:
return STC_Void;
-
+
case BuiltinType::NullPtr:
return STC_Pointer;
-
+
case BuiltinType::Overload:
case BuiltinType::Dependent:
return STC_Other;
-
+
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return STC_ObjectiveC;
-
+
default:
return STC_Arithmetic;
}
case Type::Complex:
return STC_Arithmetic;
-
+
case Type::Pointer:
return STC_Pointer;
-
+
case Type::BlockPointer:
return STC_Block;
-
+
case Type::LValueReference:
case Type::RValueReference:
return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
-
+
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
return STC_Array;
-
+
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
return STC_Arithmetic;
-
+
case Type::FunctionProto:
case Type::FunctionNoProto:
return STC_Function;
-
+
case Type::Record:
return STC_Record;
-
+
case Type::Enum:
return STC_Arithmetic;
-
+
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
return STC_ObjectiveC;
-
+
default:
return STC_Other;
}
}
-/// \brief Get the type that a given expression will have if this declaration
+/// Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
-
+ ND = ND->getUnderlyingDecl();
+
if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
return C.getTypeDeclType(Type);
if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
-
+
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getCallResultType();
@@ -721,7 +726,7 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
break;
} while (true);
-
+
return T;
}
@@ -781,7 +786,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
if (PreferredSelector == Method->getSelector())
R.Priority += CCD_SelectorMatch;
-
+
// If we have a preferred type, adjust the priority for results with exactly-
// matching or nearly-matching types.
if (!PreferredType.isNull()) {
@@ -795,16 +800,16 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
else if ((getSimplifiedTypeClass(PreferredType)
== getSimplifiedTypeClass(TC)) &&
!(PreferredType->isEnumeralType() && TC->isEnumeralType()))
- R.Priority /= CCF_SimilarTypeMatch;
+ R.Priority /= CCF_SimilarTypeMatch;
}
- }
+ }
}
void ResultBuilder::MaybeAddConstructorResults(Result R) {
if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
!CompletionContext.wantConstructorResults())
return;
-
+
ASTContext &Context = SemaRef.Context;
const NamedDecl *D = R.Declaration;
const CXXRecordDecl *Record = nullptr;
@@ -818,12 +823,12 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
// There are no constructors here.
return;
}
-
+
Record = Record->getDefinition();
if (!Record)
return;
-
+
QualType RecordTy = Context.getTypeDeclType(Record);
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
@@ -838,9 +843,15 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
}
}
+static bool isConstructor(const Decl *ND) {
+ if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ ND = Tmpl->getTemplatedDecl();
+ return isa<CXXConstructorDecl>(ND);
+}
+
void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
assert(!ShadowMaps.empty() && "Must enter into a results scope");
-
+
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
Results.push_back(R);
@@ -848,24 +859,24 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
}
// Look through using declarations.
- if (const UsingShadowDecl *Using =
- dyn_cast<UsingShadowDecl>(R.Declaration)) {
- MaybeAddResult(Result(Using->getTargetDecl(),
- getBasePriority(Using->getTargetDecl()),
- R.Qualifier),
- CurContext);
+ if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ CodeCompletionResult Result(Using->getTargetDecl(),
+ getBasePriority(Using->getTargetDecl()),
+ R.Qualifier);
+ Result.ShadowDecl = Using;
+ MaybeAddResult(Result, CurContext);
return;
}
-
+
const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
unsigned IDNS = CanonDecl->getIdentifierNamespace();
bool AsNestedNameSpecifier = false;
if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
-
+
// C++ constructors are never found by name lookup.
- if (isa<CXXConstructorDecl>(R.Declaration))
+ if (isConstructor(R.Declaration))
return;
ShadowMap &SMap = ShadowMaps.back();
@@ -882,12 +893,12 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
if (ND->getCanonicalDecl() == CanonDecl) {
// This is a redeclaration. Always pick the newer declaration.
Results[Index].Declaration = R.Declaration;
-
+
// We're done.
return;
}
}
-
+
// This is a new declaration in this scope. However, check whether this
// declaration name is hidden by a similarly-named declaration in an outer
// scope.
@@ -906,21 +917,21 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
continue;
-
+
// Protocols are in distinct namespaces from everything else.
if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
|| (IDNS & Decl::IDNS_ObjCProtocol)) &&
I->first->getIdentifierNamespace() != IDNS)
continue;
-
+
// The newly-added result is hidden by an entry in the shadow map.
if (CheckHiddenResult(R, CurContext, I->first))
return;
-
+
break;
}
}
-
+
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(CanonDecl).second)
return;
@@ -930,9 +941,9 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
- } else
+ } else
AdjustResultPriorityForDecl(R);
-
+
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
@@ -946,17 +957,17 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
else
R.QualifierIsInformative = false;
}
-
+
// Insert this result into the set of results and into the current shadow
// map.
SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Results.push_back(R);
-
+
if (!AsNestedNameSpecifier)
MaybeAddConstructorResults(R);
}
-void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
+void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
NamedDecl *Hiding, bool InBaseClass = false) {
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
@@ -966,19 +977,20 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// Look through using declarations.
if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
- AddResult(Result(Using->getTargetDecl(),
- getBasePriority(Using->getTargetDecl()),
- R.Qualifier),
- CurContext, Hiding);
+ CodeCompletionResult Result(Using->getTargetDecl(),
+ getBasePriority(Using->getTargetDecl()),
+ R.Qualifier);
+ Result.ShadowDecl = Using;
+ AddResult(Result, CurContext, Hiding);
return;
}
-
+
bool AsNestedNameSpecifier = false;
if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
-
+
// C++ constructors are never found by name lookup.
- if (isa<CXXConstructorDecl>(R.Declaration))
+ if (isConstructor(R.Declaration))
return;
if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
@@ -987,16 +999,16 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
return;
-
+
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
- }
- else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
- isa<CXXRecordDecl>(R.Declaration->getDeclContext()
- ->getRedeclContext()))
+ } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
+ InBaseClass &&
+ isa<CXXRecordDecl>(
+ R.Declaration->getDeclContext()->getRedeclContext()))
R.QualifierIsInformative = true;
// If this result is supposed to have an informative qualifier, add one.
@@ -1012,13 +1024,13 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
else
R.QualifierIsInformative = false;
}
-
+
// Adjust the priority if this result comes from a base class.
if (InBaseClass)
R.Priority += CCD_InBaseClass;
-
+
AdjustResultPriorityForDecl(R);
-
+
if (HasObjectTypeQualifiers)
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
if (Method->isInstance()) {
@@ -1027,43 +1039,43 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
if (ObjectTypeQualifiers == MethodQuals)
R.Priority += CCD_ObjectQualifierMatch;
else if (ObjectTypeQualifiers - MethodQuals) {
- // The method cannot be invoked, because doing so would drop
+ // The method cannot be invoked, because doing so would drop
// qualifiers.
return;
}
}
-
+
// Insert this result into the set of results.
Results.push_back(R);
-
+
if (!AsNestedNameSpecifier)
MaybeAddConstructorResults(R);
}
void ResultBuilder::AddResult(Result R) {
- assert(R.Kind != Result::RK_Declaration &&
+ assert(R.Kind != Result::RK_Declaration &&
"Declaration results need more context");
Results.push_back(R);
}
-/// \brief Enter into a new scope.
+/// Enter into a new scope.
void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
-/// \brief Exit from the current scope.
+/// Exit from the current scope.
void ResultBuilder::ExitScope() {
for (ShadowMap::iterator E = ShadowMaps.back().begin(),
EEnd = ShadowMaps.back().end();
E != EEnd;
++E)
E->second.Destroy();
-
+
ShadowMaps.pop_back();
}
-/// \brief Determines whether this given declaration will be found by
+/// Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
// If name lookup finds a local extern declaration, then we are in a
// context where it behaves like an ordinary name.
@@ -1074,14 +1086,14 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
if (isa<ObjCIvarDecl>(ND))
return true;
}
-
+
return ND->getIdentifierNamespace() & IDNS;
}
-/// \brief Determines whether this given declaration will be found by
+/// Determines whether this given declaration will be found by
/// ordinary name lookup but is not a type name.
bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
if (isa<TypeDecl>(ND))
return false;
// Objective-C interfaces names are not filtered by this method because they
@@ -1099,51 +1111,51 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
if (isa<ObjCIvarDecl>(ND))
return true;
}
-
+
return ND->getIdentifierNamespace() & IDNS;
}
bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
if (!IsOrdinaryNonTypeName(ND))
return 0;
-
+
if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
if (VD->getType()->isIntegralOrEnumerationType())
return true;
-
+
return false;
}
-/// \brief Determines whether this given declaration will be found by
+/// Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
-
- return (ND->getIdentifierNamespace() & IDNS) &&
- !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
+
+ return (ND->getIdentifierNamespace() & IDNS) &&
+ !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
!isa<ObjCPropertyDecl>(ND);
}
-/// \brief Determines whether the given declaration is suitable as the
+/// Determines whether the given declaration is suitable as the
/// start of a C++ nested-name-specifier, e.g., a class or namespace.
bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
// Allow us to find class templates, too.
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
-
+
return SemaRef.isAcceptableNestedNameSpecifier(ND);
}
-/// \brief Determines whether the given declaration is an enumeration.
+/// Determines whether the given declaration is an enumeration.
bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
return isa<EnumDecl>(ND);
}
-/// \brief Determines whether the given declaration is a class or struct.
+/// Determines whether the given declaration is a class or struct.
bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
// Allow us to find class templates, too.
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
@@ -1154,40 +1166,40 @@ bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
return RD->getTagKind() == TTK_Class ||
RD->getTagKind() == TTK_Struct ||
RD->getTagKind() == TTK_Interface;
-
+
return false;
}
-/// \brief Determines whether the given declaration is a union.
+/// Determines whether the given declaration is a union.
bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
// Allow us to find class templates, too.
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
-
+
if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Union;
-
+
return false;
}
-/// \brief Determines whether the given declaration is a namespace.
+/// Determines whether the given declaration is a namespace.
bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND);
}
-/// \brief Determines whether the given declaration is a namespace or
+/// Determines whether the given declaration is a namespace or
/// namespace alias.
bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND->getUnderlyingDecl());
}
-/// \brief Determines whether the given declaration is a type.
+/// Determines whether the given declaration is a type.
bool ResultBuilder::IsType(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
}
-/// \brief Determines which members of a class should be visible via
+/// Determines which members of a class should be visible via
/// "." or "->". Only value declarations, nested name specifiers, and
/// using declarations thereof should show up.
bool ResultBuilder::IsMember(const NamedDecl *ND) const {
@@ -1199,31 +1211,31 @@ bool ResultBuilder::IsMember(const NamedDecl *ND) const {
static bool isObjCReceiverType(ASTContext &C, QualType T) {
T = C.getCanonicalType(T);
switch (T->getTypeClass()) {
- case Type::ObjCObject:
+ case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
return true;
-
+
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return true;
-
+
default:
break;
}
return false;
-
+
default:
break;
}
-
+
if (!C.getLangOpts().CPlusPlus)
return false;
- // FIXME: We could perform more analysis here to determine whether a
+ // FIXME: We could perform more analysis here to determine whether a
// particular class type has any conversions to Objective-C types. For now,
// just accept all class types.
return T->isDependentType() || T->isRecordType();
@@ -1233,7 +1245,7 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
-
+
T = SemaRef.Context.getBaseElementType(T);
return isObjCReceiverType(SemaRef.Context, T);
}
@@ -1241,11 +1253,11 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
if (IsObjCMessageReceiver(ND))
return true;
-
+
const VarDecl *Var = dyn_cast<VarDecl>(ND);
if (!Var)
return false;
-
+
return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
}
@@ -1253,14 +1265,14 @@ bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
(!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
return false;
-
+
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
-
+
T = SemaRef.Context.getBaseElementType(T);
return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
- T->isObjCIdType() ||
+ T->isObjCIdType() ||
(SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
}
@@ -1268,37 +1280,43 @@ bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
return false;
}
-/// \brief Determines whether the given declaration is an Objective-C
+/// Determines whether the given declaration is an Objective-C
/// instance variable.
bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
return isa<ObjCIvarDecl>(ND);
}
namespace {
- /// \brief Visible declaration consumer that adds a code-completion result
+ /// Visible declaration consumer that adds a code-completion result
/// for each visible declaration.
class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
ResultBuilder &Results;
DeclContext *CurContext;
-
+ std::vector<FixItHint> FixIts;
+
public:
- CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
- : Results(Results), CurContext(CurContext) { }
+ CodeCompletionDeclConsumer(
+ ResultBuilder &Results, DeclContext *CurContext,
+ std::vector<FixItHint> FixIts = std::vector<FixItHint>())
+ : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {}
void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) override {
bool Accessible = true;
if (Ctx)
Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
-
ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
- false, Accessible);
+ false, Accessible, FixIts);
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
}
+
+ void EnteredContext(DeclContext* Ctx) override {
+ Results.addVisitedContext(Ctx);
+ }
};
}
-/// \brief Add type specifiers for the current language as keyword results.
+/// Add type specifiers for the current language as keyword results.
static void AddTypeSpecifierResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
@@ -1324,16 +1342,16 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Results.AddResult(Result("_Bool", CCP_Type));
Results.AddResult(Result("restrict", CCP_Type));
}
-
+
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (LangOpts.CPlusPlus) {
// C++-specific
- Results.AddResult(Result("bool", CCP_Type +
+ Results.AddResult(Result("bool", CCP_Type +
(LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Results.AddResult(Result("class", CCP_Type));
Results.AddResult(Result("wchar_t", CCP_Type));
-
+
// typename qualified-id
Builder.AddTypedTextChunk("typename");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1341,12 +1359,12 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
-
+
if (LangOpts.CPlusPlus11) {
Results.AddResult(Result("auto", CCP_Type));
Results.AddResult(Result("char16_t", CCP_Type));
Results.AddResult(Result("char32_t", CCP_Type));
-
+
Builder.AddTypedTextChunk("decltype");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
@@ -1356,13 +1374,13 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
} else
Results.AddResult(Result("__auto_type", CCP_Type));
- // GNU extensions
- if (LangOpts.GNUMode) {
+ // GNU keywords
+ if (LangOpts.GNUKeywords) {
// FIXME: Enable when we actually support decimal floating point.
// Results.AddResult(Result("_Decimal32"));
// Results.AddResult(Result("_Decimal64"));
// Results.AddResult(Result("_Decimal128"));
-
+
Builder.AddTypedTextChunk("typeof");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
@@ -1382,7 +1400,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
- const LangOptions &LangOpts,
+ const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
// Note: we don't suggest either "auto" or "register", because both
@@ -1408,7 +1426,7 @@ static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
}
static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
- const LangOptions &LangOpts,
+ const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
switch (CCC) {
@@ -1419,7 +1437,7 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Results.AddResult(Result("friend"));
Results.AddResult(Result("mutable"));
Results.AddResult(Result("virtual"));
- }
+ }
LLVM_FALLTHROUGH;
case Sema::PCC_ObjCInterface:
@@ -1447,7 +1465,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
ResultBuilder &Results,
- bool NeedAt);
+ bool NeedAt);
static void AddObjCImplementationResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt);
@@ -1464,7 +1482,7 @@ static void AddTypedefResult(ResultBuilder &Results) {
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
- Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
@@ -1481,15 +1499,15 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
case Sema::PCC_ParenthesizedExpression:
case Sema::PCC_LocalDeclarationSpecifiers:
return true;
-
+
case Sema::PCC_Expression:
case Sema::PCC_Condition:
return LangOpts.CPlusPlus;
-
+
case Sema::PCC_ObjCInterface:
case Sema::PCC_ObjCImplementation:
return false;
-
+
case Sema::PCC_ForInit:
return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
}
@@ -1507,12 +1525,12 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
return Policy;
}
-/// \brief Retrieve a printing policy suitable for code completion.
+/// Retrieve a printing policy suitable for code completion.
static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
return getCompletionPrintingPolicy(S.Context, S.PP);
}
-/// \brief Retrieve the string representation of the given type as a string
+/// Retrieve the string representation of the given type as a string
/// that has the appropriate lifetime for code completion.
///
/// This routine provides a fast path where we provide constant strings for
@@ -1525,7 +1543,7 @@ static const char *GetCompletionTypeString(QualType T,
// Built-in type names are constant strings.
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
return BT->getNameAsCString(Policy);
-
+
// Anonymous tag types are constant strings.
if (const TagType *TagT = dyn_cast<TagType>(T))
if (TagDecl *Tag = TagT->getDecl())
@@ -1539,24 +1557,24 @@ static const char *GetCompletionTypeString(QualType T,
}
}
}
-
+
// Slow path: format the type as a string.
std::string Result;
T.getAsStringInternal(Result, Policy);
return Allocator.CopyString(Result);
}
-/// \brief Add a completion for "this", if we're in a member function.
+/// Add a completion for "this", if we're in a member function.
static void addThisCompletion(Sema &S, ResultBuilder &Results) {
QualType ThisTy = S.getCurrentThisType();
if (ThisTy.isNull())
return;
-
+
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
- Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
- S.Context,
+ Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
+ S.Context,
Policy,
Allocator));
Builder.AddTypedTextChunk("this");
@@ -1578,14 +1596,14 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
-/// \brief Add language constructs that show up for "ordinary" names.
+/// Add language constructs that show up for "ordinary" names.
static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Scope *S,
Sema &SemaRef,
ResultBuilder &Results) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
-
+
typedef CodeCompletionResult Result;
switch (CCC) {
case Sema::PCC_Namespace:
@@ -1601,7 +1619,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// namespace identifier = identifier ;
Builder.AddTypedTextChunk("namespace");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1618,7 +1636,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("identifier");
Results.AddResult(Result(Builder.TakeString()));
- // asm(string-literal)
+ // asm(string-literal)
Builder.AddTypedTextChunk("asm");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("string-literal");
@@ -1633,10 +1651,10 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result(Builder.TakeString()));
}
}
-
+
if (SemaRef.getLangOpts().ObjC1)
AddObjCTopLevelResults(Results, true);
-
+
AddTypedefResult(Results);
LLVM_FALLTHROUGH;
@@ -1649,7 +1667,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
-
+
// using typename qualifier::name (only in a dependent context)
if (SemaRef.CurContext->isDependentContext()) {
Builder.AddTypedTextChunk("using");
@@ -1710,17 +1728,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
-
+
case Sema::PCC_ObjCImplementation:
AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
-
+
case Sema::PCC_ObjCInstanceVariableList:
AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
break;
-
+
case Sema::PCC_RecoveryInFunction:
case Sema::PCC_Statement: {
AddTypedefResult(Results);
@@ -1744,7 +1762,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
}
if (SemaRef.getLangOpts().ObjC1)
AddObjCStatementResults(Results, true);
-
+
if (Results.includeCodePatterns()) {
// if (condition) { statements }
Builder.AddTypedTextChunk("if");
@@ -1773,7 +1791,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// Switch-specific statements.
if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
// case expression:
@@ -1835,7 +1853,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
if (S->getContinueParent()) {
// continue ;
Builder.AddTypedTextChunk("continue");
@@ -1856,7 +1874,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
else if (ObjCMethodDecl *Method
= dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
isVoid = Method->getReturnType()->isVoidType();
- else if (SemaRef.getCurBlock() &&
+ else if (SemaRef.getCurBlock() &&
!SemaRef.getCurBlock()->ReturnType.isNull())
isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Builder.AddTypedTextChunk("return");
@@ -1870,7 +1888,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddTypedTextChunk("goto");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("label");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// Using directives
Builder.AddTypedTextChunk("using");
@@ -1900,7 +1918,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// (__bridge_transfer <Objective-C type>)<expression>
Builder.AddTypedTextChunk("__bridge_transfer");
@@ -1908,7 +1926,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("Objective-C type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// (__bridge_retained <CF type>)<expression>
Builder.AddTypedTextChunk("__bridge_retained");
@@ -1916,7 +1934,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("CF type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
}
// Fall through
LLVM_FALLTHROUGH;
@@ -1925,12 +1943,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
if (SemaRef.getLangOpts().CPlusPlus) {
// 'this', if we're in a non-static member function.
addThisCompletion(SemaRef, Results);
-
+
// true
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("true");
Results.AddResult(Result(Builder.TakeString()));
-
+
// false
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("false");
@@ -1945,9 +1963,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
}
-
+
// static_cast < type-id > ( expression )
Builder.AddTypedTextChunk("static_cast");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
@@ -1956,7 +1974,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// reinterpret_cast < type-id > ( expression )
Builder.AddTypedTextChunk("reinterpret_cast");
@@ -1966,7 +1984,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// const_cast < type-id > ( expression )
Builder.AddTypedTextChunk("const_cast");
@@ -1976,7 +1994,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
if (SemaRef.getLangOpts().RTTI) {
// typeid ( expression-or-type )
@@ -1985,9 +2003,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression-or-type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
}
-
+
// new T ( ... )
Builder.AddTypedTextChunk("new");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1995,7 +2013,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expressions");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// new T [ ] ( ... )
Builder.AddTypedTextChunk("new");
@@ -2007,14 +2025,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expressions");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// delete expression
Builder.AddResultTypeChunk("void");
Builder.AddTypedTextChunk("delete");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// delete [] expression
Builder.AddResultTypeChunk("void");
@@ -2034,7 +2052,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// FIXME: Rethrow?
if (SemaRef.getLangOpts().CPlusPlus11) {
@@ -2079,7 +2097,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
SuperType = ID->getSuperClass()->getNameAsString();
if (Method->isInstanceMethod())
SuperType += " *";
-
+
Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
Builder.AddTypedTextChunk("super");
Results.AddResult(Result(Builder.TakeString()));
@@ -2111,7 +2129,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result(Builder.TakeString()));
break;
}
-
+
case Sema::PCC_Type:
case Sema::PCC_LocalDeclarationSpecifiers:
break;
@@ -2124,7 +2142,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result("operator"));
}
-/// \brief If the given declaration has an associated type, add it as a result
+/// If the given declaration has an associated type, add it as a result
/// type chunk.
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
@@ -2136,7 +2154,7 @@ static void AddResultTypeChunk(ASTContext &Context,
// Skip constructors and conversion functions, which have their return types
// built into their names.
- if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
+ if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
return;
// Determine the type of the declaration (if it has a type).
@@ -2166,10 +2184,10 @@ static void AddResultTypeChunk(ASTContext &Context,
else
T = Property->getType();
}
-
+
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
return;
-
+
Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Result.getAllocator()));
}
@@ -2188,7 +2206,7 @@ static void MaybeAddSentinel(Preprocessor &PP,
}
}
-static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
+static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
QualType &Type) {
std::string Result;
if (ObjCQuals & Decl::OBJC_TQ_In)
@@ -2223,7 +2241,7 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
return Result;
}
-/// \brief Tries to find the most appropriate type location for an Objective-C
+/// Tries to find the most appropriate type location for an Objective-C
/// block placeholder.
///
/// This function ignores things like typedefs and qualifiers in order to
@@ -2285,13 +2303,13 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
- // The argument for a dependent or non-block parameter is a placeholder
+ // The argument for a dependent or non-block parameter is a placeholder
// containing that parameter's type.
std::string Result;
-
+
if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Result = Param->getIdentifier()->getName();
-
+
QualType Type = Param->getType();
if (ObjCSubsts)
Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
@@ -2332,7 +2350,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Result = Param->getIdentifier()->getName();
QualType Type = Param->getType().getUnqualifiedType();
-
+
if (ObjCMethodParam) {
Result = Type.getAsString(Policy);
std::string Quals =
@@ -2346,7 +2364,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
} else {
Type.getAsStringInternal(Result, Policy);
}
-
+
return Result;
}
@@ -2357,14 +2375,14 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
ObjCSubsts);
}
-/// \brief Returns a placeholder string that corresponds to an Objective-C block
+/// Returns a placeholder string that corresponds to an Objective-C block
/// declaration.
///
/// \param BlockDecl A declaration with an Objective-C block type.
///
/// \param Block The most relevant type location for that block type.
///
-/// \param SuppressBlockName Determines wether or not the name of the block
+/// \param SuppressBlockName Determines whether or not the name of the block
/// declaration is included in the resulting string.
static std::string
formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
@@ -2449,7 +2467,7 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param,
return " " + DefValue;
}
-/// \brief Add function parameter chunks to the given code completion string.
+/// Add function parameter chunks to the given code completion string.
static void AddFunctionParameterChunks(Preprocessor &PP,
const PrintingPolicy &Policy,
const FunctionDecl *Function,
@@ -2457,10 +2475,10 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
unsigned Start = 0,
bool InOptional = false) {
bool FirstParameter = true;
-
+
for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
const ParmVarDecl *Param = Function->getParamDecl(P);
-
+
if (Param->hasDefaultArg() && !InOptional) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
@@ -2472,14 +2490,14 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
Result.AddOptionalChunk(Opt.TakeString());
break;
}
-
+
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
-
+
InOptional = false;
-
+
// Format the placeholder string.
std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
@@ -2492,8 +2510,8 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString(PlaceholderStr));
}
-
- if (const FunctionProtoType *Proto
+
+ if (const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>())
if (Proto->isVariadic()) {
if (Proto->getNumParams() == 0)
@@ -2503,7 +2521,7 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
}
}
-/// \brief Add template parameter chunks to the given code completion string.
+/// Add template parameter chunks to the given code completion string.
static void AddTemplateParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
const TemplateDecl *Template,
@@ -2521,7 +2539,7 @@ static void AddTemplateParameterChunks(ASTContext &Context,
TemplateParameterList::iterator PEnd = Params->end();
if (MaxParameters)
PEnd = Params->begin() + MaxParameters;
- for (TemplateParameterList::iterator P = Params->begin() + Start;
+ for (TemplateParameterList::iterator P = Params->begin() + Start;
P != PEnd; ++P) {
bool HasDefaultArg = false;
std::string PlaceholderStr;
@@ -2530,14 +2548,14 @@ static void AddTemplateParameterChunks(ASTContext &Context,
PlaceholderStr = "typename";
else
PlaceholderStr = "class";
-
+
if (TTP->getIdentifier()) {
PlaceholderStr += ' ';
PlaceholderStr += TTP->getIdentifier()->getName();
}
-
+
HasDefaultArg = TTP->hasDefaultArgument();
- } else if (NonTypeTemplateParmDecl *NTTP
+ } else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
if (NTTP->getIdentifier())
PlaceholderStr = NTTP->getIdentifier()->getName();
@@ -2546,7 +2564,7 @@ static void AddTemplateParameterChunks(ASTContext &Context,
} else {
assert(isa<TemplateTemplateParmDecl>(*P));
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
-
+
// Since putting the template argument list into the placeholder would
// be very, very long, we just use an abbreviation.
PlaceholderStr = "template<...> class";
@@ -2554,10 +2572,10 @@ static void AddTemplateParameterChunks(ASTContext &Context,
PlaceholderStr += ' ';
PlaceholderStr += TTP->getIdentifier()->getName();
}
-
+
HasDefaultArg = TTP->hasDefaultArgument();
}
-
+
if (HasDefaultArg && !InDefaultArg) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
@@ -2570,31 +2588,31 @@ static void AddTemplateParameterChunks(ASTContext &Context,
Result.AddOptionalChunk(Opt.TakeString());
break;
}
-
+
InDefaultArg = false;
-
+
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
-
+
// Add the placeholder string.
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString(PlaceholderStr));
- }
+ }
}
-/// \brief Add a qualifier to the given code-completion string, if the
+/// Add a qualifier to the given code-completion string, if the
/// provided nested-name-specifier is non-NULL.
-static void
-AddQualifierToCompletionString(CodeCompletionBuilder &Result,
- NestedNameSpecifier *Qualifier,
+static void
+AddQualifierToCompletionString(CodeCompletionBuilder &Result,
+ NestedNameSpecifier *Qualifier,
bool QualifierIsInformative,
ASTContext &Context,
const PrintingPolicy &Policy) {
if (!Qualifier)
return;
-
+
std::string PrintedNNS;
{
llvm::raw_string_ostream OS(PrintedNNS);
@@ -2606,7 +2624,7 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
}
-static void
+static void
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
const FunctionDecl *Function) {
const FunctionProtoType *Proto
@@ -2615,7 +2633,7 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
return;
// FIXME: Add ref-qualifier!
-
+
// Handle single qualifiers without copying
if (Proto->getTypeQuals() == Qualifiers::Const) {
Result.AddInformativeChunk(" const");
@@ -2643,29 +2661,29 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
}
-/// \brief Add the name of the given declaration
+/// Add the name of the given declaration
static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
const NamedDecl *ND,
CodeCompletionBuilder &Result) {
DeclarationName Name = ND->getDeclName();
if (!Name)
return;
-
+
switch (Name.getNameKind()) {
case DeclarationName::CXXOperatorName: {
const char *OperatorName = nullptr;
switch (Name.getCXXOverloadedOperator()) {
- case OO_None:
+ case OO_None:
case OO_Conditional:
case NUM_OVERLOADED_OPERATORS:
- OperatorName = "operator";
+ OperatorName = "operator";
break;
-
+
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
case OO_##Name: OperatorName = "operator" Spelling; break;
#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
#include "clang/Basic/OperatorKinds.def"
-
+
case OO_New: OperatorName = "operator new"; break;
case OO_Delete: OperatorName = "operator delete"; break;
case OO_Array_New: OperatorName = "operator new[]"; break;
@@ -2676,7 +2694,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.AddTypedTextChunk(OperatorName);
break;
}
-
+
case DeclarationName::Identifier:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXDestructorName:
@@ -2684,14 +2702,14 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
-
+
case DeclarationName::CXXDeductionGuideName:
case DeclarationName::CXXUsingDirective:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
break;
-
+
case DeclarationName::CXXConstructorName: {
CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
@@ -2705,7 +2723,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
}
-
+
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Record->getNameAsString()));
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
@@ -2727,7 +2745,53 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
CCTUInfo, IncludeBriefComments);
}
-/// \brief If possible, create a new code completion string for the given
+CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
+ Preprocessor &PP, CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo) {
+ assert(Kind == RK_Macro);
+ CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
+ const MacroInfo *MI = PP.getMacroInfo(Macro);
+ Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
+
+ if (!MI || !MI->isFunctionLike())
+ return Result.TakeString();
+
+ // Format a function-like macro with placeholders for the arguments.
+ Result.AddChunk(CodeCompletionString::CK_LeftParen);
+ MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
+
+ // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
+ if (MI->isC99Varargs()) {
+ --AEnd;
+
+ if (A == AEnd) {
+ Result.AddPlaceholderChunk("...");
+ }
+ }
+
+ for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
+ if (A != MI->param_begin())
+ Result.AddChunk(CodeCompletionString::CK_Comma);
+
+ if (MI->isVariadic() && (A + 1) == AEnd) {
+ SmallString<32> Arg = (*A)->getName();
+ if (MI->isC99Varargs())
+ Arg += ", ...";
+ else
+ Arg += "...";
+ Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
+ break;
+ }
+
+ // Non-variadic macros are simple.
+ Result.AddPlaceholderChunk(
+ Result.getAllocator().CopyString((*A)->getName()));
+ }
+ Result.AddChunk(CodeCompletionString::CK_RightParen);
+ return Result.TakeString();
+}
+
+/// If possible, create a new code completion string for the given
/// result.
///
/// \returns Either a new, heap-allocated code completion string describing
@@ -2740,104 +2804,42 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
+ if (Kind == RK_Macro)
+ return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
+
CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
-
+
PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
if (Kind == RK_Pattern) {
Pattern->Priority = Priority;
Pattern->Availability = Availability;
-
+
if (Declaration) {
Result.addParentContext(Declaration->getDeclContext());
Pattern->ParentName = Result.getParentName();
- // Provide code completion comment for self.GetterName where
- // GetterName is the getter method for a property with name
- // different from the property name (declared via a property
- // getter attribute.
- const NamedDecl *ND = Declaration;
- if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
- if (M->isPropertyAccessor())
- if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
- if (PDecl->getGetterName() == M->getSelector() &&
- PDecl->getIdentifier() != M->getIdentifier()) {
- if (const RawComment *RC =
- Ctx.getRawCommentForAnyRedecl(M)) {
- Result.addBriefComment(RC->getBriefText(Ctx));
- Pattern->BriefComment = Result.getBriefComment();
- }
- else if (const RawComment *RC =
- Ctx.getRawCommentForAnyRedecl(PDecl)) {
- Result.addBriefComment(RC->getBriefText(Ctx));
- Pattern->BriefComment = Result.getBriefComment();
- }
- }
- }
-
- return Pattern;
- }
-
- if (Kind == RK_Keyword) {
- Result.AddTypedTextChunk(Keyword);
- return Result.TakeString();
- }
-
- if (Kind == RK_Macro) {
- const MacroInfo *MI = PP.getMacroInfo(Macro);
- Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(Macro->getName()));
-
- if (!MI || !MI->isFunctionLike())
- return Result.TakeString();
-
- // Format a function-like macro with placeholders for the arguments.
- Result.AddChunk(CodeCompletionString::CK_LeftParen);
- MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
-
- // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
- if (MI->isC99Varargs()) {
- --AEnd;
-
- if (A == AEnd) {
- Result.AddPlaceholderChunk("...");
+ if (const RawComment *RC =
+ getPatternCompletionComment(Ctx, Declaration)) {
+ Result.addBriefComment(RC->getBriefText(Ctx));
+ Pattern->BriefComment = Result.getBriefComment();
}
}
-
- for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
- if (A != MI->param_begin())
- Result.AddChunk(CodeCompletionString::CK_Comma);
- if (MI->isVariadic() && (A+1) == AEnd) {
- SmallString<32> Arg = (*A)->getName();
- if (MI->isC99Varargs())
- Arg += ", ...";
- else
- Arg += "...";
- Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
- break;
- }
+ return Pattern;
+ }
- // Non-variadic macros are simple.
- Result.AddPlaceholderChunk(
- Result.getAllocator().CopyString((*A)->getName()));
- }
- Result.AddChunk(CodeCompletionString::CK_RightParen);
+ if (Kind == RK_Keyword) {
+ Result.AddTypedTextChunk(Keyword);
return Result.TakeString();
}
-
assert(Kind == RK_Declaration && "Missed a result kind?");
const NamedDecl *ND = Declaration;
Result.addParentContext(ND->getDeclContext());
if (IncludeBriefComments) {
// Add documentation comment, if it exists.
- if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
+ if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Result.addBriefComment(RC->getBriefText(Ctx));
- }
- else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
- if (OMD->isPropertyAccessor())
- if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
- if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
- Result.addBriefComment(RC->getBriefText(Ctx));
+ }
}
if (StartsNestedNameSpecifier) {
@@ -2851,9 +2853,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
-
+
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
Result.AddChunk(CodeCompletionString::CK_LeftParen);
@@ -2862,9 +2864,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
}
-
+
if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
AddTypedNameChunk(Ctx, Policy, Function, Result);
@@ -2885,30 +2887,30 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
LastDeducibleArgument - 1);
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
HasDefaultArg = TTP->hasDefaultArgument();
- else if (NonTypeTemplateParmDecl *NTTP
+ else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param))
HasDefaultArg = NTTP->hasDefaultArgument();
else {
assert(isa<TemplateTemplateParmDecl>(Param));
- HasDefaultArg
+ HasDefaultArg
= cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
}
-
+
if (!HasDefaultArg)
break;
}
}
-
+
if (LastDeducibleArgument) {
// Some of the function template arguments cannot be deduced from a
// function call, so we introduce an explicit template argument list
// containing all of the arguments up to the first deducible argument.
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
- AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
+ AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
LastDeducibleArgument);
Result.AddChunk(CodeCompletionString::CK_RightAngle);
}
-
+
// Add the function parameters
Result.AddChunk(CodeCompletionString::CK_LeftParen);
AddFunctionParameterChunks(PP, Policy, Function, Result);
@@ -2916,9 +2918,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
}
-
+
if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Template->getNameAsString()));
@@ -2927,7 +2929,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddChunk(CodeCompletionString::CK_RightAngle);
return Result.TakeString();
}
-
+
if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Selector Sel = Method->getSelector();
if (Sel.isUnarySelector()) {
@@ -2942,7 +2944,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
else {
Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
-
+
// If there is only one parameter, and we're past it, add an empty
// typed-text chunk since there is nothing to type.
if (Method->param_size() == 1)
@@ -2961,10 +2963,10 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Keyword += ":";
if (Idx < StartParameter || AllParametersAreInformative)
Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
- else
+ else
Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
}
-
+
// If we're before the starting parameter, skip the placeholder.
if (Idx < StartParameter)
continue;
@@ -2990,10 +2992,10 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
if (DeclaringEntity || AllParametersAreInformative)
Arg += II->getName();
}
-
+
if (Method->isVariadic() && (P + 1) == PEnd)
Arg += ", ...";
-
+
if (DeclaringEntity)
Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
else if (AllParametersAreInformative)
@@ -3011,15 +3013,15 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
else
Result.AddPlaceholderChunk(", ...");
}
-
+
MaybeAddSentinel(PP, Method, Result);
}
-
+
return Result.TakeString();
}
if (Qualifier)
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
@@ -3027,7 +3029,60 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
-/// \brief Add function overload parameter chunks to the given code completion
+const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *ND) {
+ if (!ND)
+ return nullptr;
+ if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
+ return RC;
+
+ // Try to find comment from a property for ObjC methods.
+ const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
+ if (!M)
+ return nullptr;
+ const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
+ if (!PDecl)
+ return nullptr;
+
+ return Ctx.getRawCommentForAnyRedecl(PDecl);
+}
+
+const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *ND) {
+ const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
+ if (!M || !M->isPropertyAccessor())
+ return nullptr;
+
+ // Provide code completion comment for self.GetterName where
+ // GetterName is the getter method for a property with name
+ // different from the property name (declared via a property
+ // getter attribute.
+ const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
+ if (!PDecl)
+ return nullptr;
+ if (PDecl->getGetterName() == M->getSelector() &&
+ PDecl->getIdentifier() != M->getIdentifier()) {
+ if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
+ return RC;
+ if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
+ return RC;
+ }
+ return nullptr;
+}
+
+const RawComment *clang::getParameterComment(
+ const ASTContext &Ctx,
+ const CodeCompleteConsumer::OverloadCandidate &Result,
+ unsigned ArgIndex) {
+ auto FDecl = Result.getFunction();
+ if (!FDecl)
+ return nullptr;
+ if (ArgIndex < FDecl->getNumParams())
+ return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
+ return nullptr;
+}
+
+/// Add function overload parameter chunks to the given code completion
/// string.
static void AddOverloadParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
@@ -3110,7 +3165,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
- // Function without a prototype. Just give the return type and a
+ // Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
@@ -3122,10 +3177,10 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
}
if (FDecl) {
- if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
- if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
- FDecl->getParamDecl(CurrentArg)))
+ if (IncludeBriefComments) {
+ if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Result.addBriefComment(RC->getBriefText(S.getASTContext()));
+ }
AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Result.AddTextChunk(
Result.getAllocator().CopyString(FDecl->getNameAsString()));
@@ -3143,18 +3198,18 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
return Result.TakeString();
}
-unsigned clang::getMacroUsagePriority(StringRef MacroName,
+unsigned clang::getMacroUsagePriority(StringRef MacroName,
const LangOptions &LangOpts,
bool PreferredTypeIsPointer) {
unsigned Priority = CCP_Macro;
-
+
// Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
- if (MacroName.equals("nil") || MacroName.equals("NULL") ||
+ if (MacroName.equals("nil") || MacroName.equals("NULL") ||
MacroName.equals("Nil")) {
Priority = CCP_Constant;
if (PreferredTypeIsPointer)
Priority = Priority / CCF_SimilarTypeMatch;
- }
+ }
// Treat "YES", "NO", "true", and "false" as constants.
else if (MacroName.equals("YES") || MacroName.equals("NO") ||
MacroName.equals("true") || MacroName.equals("false"))
@@ -3162,27 +3217,27 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName,
// Treat "bool" as a type.
else if (MacroName.equals("bool"))
Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
-
-
+
+
return Priority;
}
CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
if (!D)
return CXCursor_UnexposedDecl;
-
+
switch (D->getKind()) {
case Decl::Enum: return CXCursor_EnumDecl;
case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
case Decl::Field: return CXCursor_FieldDecl;
- case Decl::Function:
+ case Decl::Function:
return CXCursor_FunctionDecl;
case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
- case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
+ case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
case Decl::ObjCMethod:
return cast<ObjCMethodDecl>(D)->isInstanceMethod()
? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
@@ -3211,17 +3266,17 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
case Decl::StaticAssert: return CXCursor_StaticAssert;
case Decl::Friend: return CXCursor_FriendDecl;
case Decl::TranslationUnit: return CXCursor_TranslationUnit;
-
+
case Decl::Using:
case Decl::UnresolvedUsingValue:
- case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingTypename:
return CXCursor_UsingDeclaration;
-
+
case Decl::ObjCPropertyImpl:
switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
case ObjCPropertyImplDecl::Dynamic:
return CXCursor_ObjCDynamicDecl;
-
+
case ObjCPropertyImplDecl::Synthesize:
return CXCursor_ObjCSynthesizeDecl;
}
@@ -3242,7 +3297,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
}
}
}
-
+
return CXCursor_UnexposedDecl;
}
@@ -3250,10 +3305,10 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
bool IncludeUndefined,
bool TargetTypeIsPointer = false) {
typedef CodeCompletionResult Result;
-
+
Results.EnterNewScope();
-
- for (Preprocessor::macro_iterator M = PP.macro_begin(),
+
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
auto MD = PP.getMacroDefinition(M->first);
@@ -3268,17 +3323,17 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
TargetTypeIsPointer)));
}
}
-
+
Results.ExitScope();
-
+
}
-static void AddPrettyFunctionResults(const LangOptions &LangOpts,
+static void AddPrettyFunctionResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
-
+
Results.EnterNewScope();
-
+
Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
Results.AddResult(Result("__FUNCTION__", CCP_Constant));
if (LangOpts.C99 || LangOpts.CPlusPlus11)
@@ -3295,24 +3350,24 @@ static void HandleCodeCompleteResults(Sema *S,
CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
}
-static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
+static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Sema::ParserCompletionContext PCC) {
switch (PCC) {
case Sema::PCC_Namespace:
return CodeCompletionContext::CCC_TopLevel;
-
+
case Sema::PCC_Class:
return CodeCompletionContext::CCC_ClassStructUnion;
case Sema::PCC_ObjCInterface:
return CodeCompletionContext::CCC_ObjCInterface;
-
+
case Sema::PCC_ObjCImplementation:
return CodeCompletionContext::CCC_ObjCImplementation;
case Sema::PCC_ObjCInstanceVariableList:
return CodeCompletionContext::CCC_ObjCIvarList;
-
+
case Sema::PCC_Template:
case Sema::PCC_MemberTemplate:
if (S.CurContext->isFileContext())
@@ -3320,7 +3375,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
if (S.CurContext->isRecord())
return CodeCompletionContext::CCC_ClassStructUnion;
return CodeCompletionContext::CCC_Other;
-
+
case Sema::PCC_RecoveryInFunction:
return CodeCompletionContext::CCC_Recovery;
@@ -3334,7 +3389,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
case Sema::PCC_Expression:
case Sema::PCC_Condition:
return CodeCompletionContext::CCC_Expression;
-
+
case Sema::PCC_Statement:
return CodeCompletionContext::CCC_Statement;
@@ -3343,7 +3398,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
case Sema::PCC_ParenthesizedExpression:
return CodeCompletionContext::CCC_ParenthesizedExpression;
-
+
case Sema::PCC_LocalDeclarationSpecifiers:
return CodeCompletionContext::CCC_Type;
}
@@ -3351,27 +3406,27 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
llvm_unreachable("Invalid ParserCompletionContext!");
}
-/// \brief If we're in a C++ virtual member function, add completion results
-/// that invoke the functions we override, since it's common to invoke the
+/// If we're in a C++ virtual member function, add completion results
+/// that invoke the functions we override, since it's common to invoke the
/// overridden function as well as adding new functionality.
///
/// \param S The semantic analysis object for which we are generating results.
///
/// \param InContext This context in which the nested-name-specifier preceding
-/// the code-completion point
+/// the code-completion point
static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
ResultBuilder &Results) {
// Look through blocks.
DeclContext *CurContext = S.CurContext;
while (isa<BlockDecl>(CurContext))
CurContext = CurContext->getParent();
-
-
+
+
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
if (!Method || !Method->isVirtual())
return;
-
- // We need to have names for all of the parameters, if we're going to
+
+ // We need to have names for all of the parameters, if we're going to
// generate a forwarding call.
for (auto P : Method->parameters())
if (!P->getDeclName())
@@ -3383,7 +3438,7 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
Results.getCodeCompletionTUInfo());
if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
continue;
-
+
// If we need a nested-name-specifier, add one now.
if (!InContext) {
NestedNameSpecifier *NNS
@@ -3397,8 +3452,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
}
} else if (!InContext->Equals(Overridden->getDeclContext()))
continue;
-
- Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
+
+ Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Overridden->getNameAsString()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
bool FirstParam = true;
@@ -3421,14 +3476,14 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
}
}
-void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
+void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
ModuleIdPath Path) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
-
+
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
typedef CodeCompletionResult Result;
@@ -3440,7 +3495,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Modules[I]->Name));
Results.AddResult(Result(Builder.TakeString(),
- CCP_Declaration,
+ CCP_Declaration,
CXCursor_ModuleImportDecl,
Modules[I]->isAvailable()
? CXAvailability_Available
@@ -3453,14 +3508,14 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
/*IsInclusionDirective=*/false);
// Enumerate submodules.
if (Mod) {
- for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+ for (Module::submodule_iterator Sub = Mod->submodule_begin(),
SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub) {
-
+
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString((*Sub)->Name));
Results.AddResult(Result(Builder.TakeString(),
- CCP_Declaration,
+ CCP_Declaration,
CXCursor_ModuleImportDecl,
(*Sub)->isAvailable()
? CXAvailability_Available
@@ -3468,18 +3523,18 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
}
}
}
- Results.ExitScope();
+ Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
-void Sema::CodeCompleteOrdinaryName(Scope *S,
+void Sema::CodeCompleteOrdinaryName(Scope *S,
ParserCompletionContext CompletionContext) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
mapCodeCompletionContext(*this, CompletionContext));
Results.EnterNewScope();
-
+
// Determine how to filter results, e.g., so that the names of
// values (functions, enumerators, function templates, etc.) are
// only allowed where we can have an expression.
@@ -3505,11 +3560,11 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
-
+
if (getLangOpts().CPlusPlus)
MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
break;
-
+
case PCC_RecoveryInFunction:
// Unfiltered
break;
@@ -3521,10 +3576,11 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
if (CurMethod->isInstance())
Results.setObjectTypeQualifiers(
Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Results.ExitScope();
@@ -3537,7 +3593,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
break;
-
+
case PCC_Namespace:
case PCC_Class:
case PCC_ObjCInterface:
@@ -3551,15 +3607,15 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
case PCC_LocalDeclarationSpecifiers:
break;
}
-
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
-static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
@@ -3576,7 +3632,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
? CodeCompletionContext::CCC_PotentiallyQualifiedName
: CodeCompletionContext::CCC_Name);
Results.EnterNewScope();
-
+
// Type qualifiers can come after names.
Results.AddResult(Result("const"));
Results.AddResult(Result("volatile"));
@@ -3590,16 +3646,17 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
Results.AddResult("final");
if (AllowNonIdentifiers) {
- Results.AddResult(Result("operator"));
+ Results.AddResult(Result("operator"));
}
-
+
// Add nested-name-specifiers.
if (AllowNestedNameSpecifiers) {
Results.allowNestedNameSpecifiers();
Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
Results.setFilter(nullptr);
}
}
@@ -3618,7 +3675,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
S &&
(S->getFlags() & Scope::DeclScope) != 0 &&
(S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
- Scope::FunctionPrototypeScope |
+ Scope::FunctionPrototypeScope |
Scope::AtCatchScope)) == 0) {
ParsedType T = DS.getRepAsType();
if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
@@ -3628,29 +3685,31 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
// Note that we intentionally suppress macro results here, since we do not
// encourage using macros to produce the names of entities.
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
struct Sema::CodeCompleteExpressionData {
- CodeCompleteExpressionData(QualType PreferredType = QualType())
+ CodeCompleteExpressionData(QualType PreferredType = QualType())
: PreferredType(PreferredType), IntegralConstantExpression(false),
ObjCCollection(false) { }
-
+
QualType PreferredType;
bool IntegralConstantExpression;
bool ObjCCollection;
SmallVector<Decl *, 4> IgnoreDecls;
};
-/// \brief Perform code-completion in an expression context when we know what
+/// Perform code-completion in an expression context when we know what
/// type we're looking for.
-void Sema::CodeCompleteExpression(Scope *S,
+void Sema::CodeCompleteExpression(Scope *S,
const CodeCompleteExpressionData &Data) {
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Expression);
+ ResultBuilder Results(
+ *this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext(CodeCompletionContext::CCC_Expression,
+ Data.PreferredType));
if (Data.ObjCCollection)
Results.setFilter(&ResultBuilder::IsObjCCollection);
else if (Data.IntegralConstantExpression)
@@ -3662,36 +3721,35 @@ void Sema::CodeCompleteExpression(Scope *S,
if (!Data.PreferredType.isNull())
Results.setPreferredType(Data.PreferredType.getNonReferenceType());
-
+
// Ignore any declarations that we were told that we don't care about.
for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
Results.Ignore(Data.IgnoreDecls[I]);
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
Results.EnterNewScope();
AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Results.ExitScope();
-
+
bool PreferredTypeIsPointer = false;
if (!Data.PreferredType.isNull())
PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
- || Data.PreferredType->isMemberPointerType()
+ || Data.PreferredType->isMemberPointerType()
|| Data.PreferredType->isBlockPointerType();
-
- if (S->getFnParent() &&
- !Data.ObjCCollection &&
+
+ if (S->getFnParent() &&
+ !Data.ObjCCollection &&
!Data.IntegralConstantExpression)
AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext(CodeCompletionContext::CCC_Expression,
- Data.PreferredType),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
@@ -3701,29 +3759,29 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
}
-/// \brief The set of properties that have already been added, referenced by
+/// The set of properties that have already been added, referenced by
/// property name.
typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
-/// \brief Retrieve the container definition, if any?
+/// Retrieve the container definition, if any?
static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
if (Interface->hasDefinition())
return Interface->getDefinition();
-
+
return Interface;
}
-
+
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition())
return Protocol->getDefinition();
-
+
return Protocol;
}
return Container;
}
-/// \brief Adds a block invocation code completion result for the given block
+/// Adds a block invocation code completion result for the given block
/// declaration \p BD.
static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder,
@@ -3770,7 +3828,7 @@ static void AddObjCProperties(
// Retrieve the definition.
Container = getContainerDef(Container);
-
+
// Add properties in this container.
const auto AddProperty = [&](const ObjCPropertyDecl *P) {
if (!AddedProperties.insert(P->getIdentifier()).second)
@@ -3889,7 +3947,7 @@ static void AddObjCProperties(
}
}
}
-
+
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
@@ -3929,17 +3987,22 @@ static void AddObjCProperties(
static void AddRecordMembersCompletionResults(Sema &SemaRef,
ResultBuilder &Results, Scope *S,
QualType BaseType,
- RecordDecl *RD) {
+ RecordDecl *RD,
+ Optional<FixItHint> AccessOpFixIt) {
// Indicate that we are performing a member access, and the cv-qualifiers
// for the base object type.
Results.setObjectTypeQualifiers(BaseType.getQualifiers());
// Access to a C/C++ class, struct, or union.
Results.allowNestedNameSpecifiers();
- CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
+ std::vector<FixItHint> FixIts;
+ if (AccessOpFixIt)
+ FixIts.emplace_back(AccessOpFixIt.getValue());
+ CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts));
SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
SemaRef.CodeCompleter->includeGlobals(),
- /*IncludeDependentBases=*/true);
+ /*IncludeDependentBases=*/true,
+ SemaRef.CodeCompleter->loadExternal());
if (SemaRef.getLangOpts().CPlusPlus) {
if (!Results.empty()) {
@@ -3962,106 +4025,138 @@ static void AddRecordMembersCompletionResults(Sema &SemaRef,
}
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+ Expr *OtherOpBase,
SourceLocation OpLoc, bool IsArrow,
bool IsBaseExprStatement) {
if (!Base || !CodeCompleter)
return;
-
+
ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid())
return;
- Base = ConvertedBase.get();
-
- QualType BaseType = Base->getType();
+ QualType ConvertedBaseType = ConvertedBase.get()->getType();
+
+ enum CodeCompletionContext::Kind contextKind;
if (IsArrow) {
- if (const PointerType *Ptr = BaseType->getAs<PointerType>())
- BaseType = Ptr->getPointeeType();
- else if (BaseType->isObjCObjectPointerType())
- /*Do nothing*/ ;
- else
- return;
+ if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
+ ConvertedBaseType = Ptr->getPointeeType();
}
-
- enum CodeCompletionContext::Kind contextKind;
-
+
if (IsArrow) {
contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
- }
- else {
- if (BaseType->isObjCObjectPointerType() ||
- BaseType->isObjCObjectOrInterfaceType()) {
+ } else {
+ if (ConvertedBaseType->isObjCObjectPointerType() ||
+ ConvertedBaseType->isObjCObjectOrInterfaceType()) {
contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
- }
- else {
+ } else {
contextKind = CodeCompletionContext::CCC_DotMemberAccess;
}
}
- CodeCompletionContext CCContext(contextKind, BaseType);
+ CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CCContext,
+ CodeCompleter->getCodeCompletionTUInfo(), CCContext,
&ResultBuilder::IsMember);
- Results.EnterNewScope();
- if (const RecordType *Record = BaseType->getAs<RecordType>()) {
- AddRecordMembersCompletionResults(*this, Results, S, BaseType,
- Record->getDecl());
- } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
- TemplateName TN = TST->getTemplateName();
- if (const auto *TD =
- dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
- CXXRecordDecl *RD = TD->getTemplatedDecl();
- AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
- }
- } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
- if (auto *RD = ICNT->getDecl())
- AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
- } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
- // Objective-C property reference.
- AddedPropertiesSet AddedProperties;
-
- if (const ObjCObjectPointerType *ObjCPtr =
- BaseType->getAsObjCInterfacePointerType()) {
- // Add property results based on our interface.
- assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
- /*AllowNullaryMethods=*/true, CurContext,
- AddedProperties, Results, IsBaseExprStatement);
- }
-
- // Add properties from the protocols in a qualified interface.
- for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
- AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
- CurContext, AddedProperties, Results,
- IsBaseExprStatement);
- } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
- (!IsArrow && BaseType->isObjCObjectType())) {
- // Objective-C instance variable access.
- ObjCInterfaceDecl *Class = nullptr;
- if (const ObjCObjectPointerType *ObjCPtr
- = BaseType->getAs<ObjCObjectPointerType>())
- Class = ObjCPtr->getInterfaceDecl();
- else
- Class = BaseType->getAs<ObjCObjectType>()->getInterface();
-
- // Add all ivars from this class and its superclasses.
- if (Class) {
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
- Results.setFilter(&ResultBuilder::IsObjCIvar);
- LookupVisibleDecls(Class, LookupMemberName, Consumer,
- CodeCompleter->includeGlobals());
+
+ auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
+ if (!Base)
+ return false;
+
+ ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
+ if (ConvertedBase.isInvalid())
+ return false;
+ Base = ConvertedBase.get();
+
+ QualType BaseType = Base->getType();
+
+ if (IsArrow) {
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+ else if (BaseType->isObjCObjectPointerType())
+ /*Do nothing*/;
+ else
+ return false;
+ }
+
+ if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+ AddRecordMembersCompletionResults(*this, Results, S, BaseType,
+ Record->getDecl(),
+ std::move(AccessOpFixIt));
+ } else if (const auto *TST =
+ BaseType->getAs<TemplateSpecializationType>()) {
+ TemplateName TN = TST->getTemplateName();
+ if (const auto *TD =
+ dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
+ CXXRecordDecl *RD = TD->getTemplatedDecl();
+ AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
+ std::move(AccessOpFixIt));
+ }
+ } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
+ if (auto *RD = ICNT->getDecl())
+ AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
+ std::move(AccessOpFixIt));
+ } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
+ // Objective-C property reference.
+ AddedPropertiesSet AddedProperties;
+
+ if (const ObjCObjectPointerType *ObjCPtr =
+ BaseType->getAsObjCInterfacePointerType()) {
+ // Add property results based on our interface.
+ assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+ AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
+ /*AllowNullaryMethods=*/true, CurContext,
+ AddedProperties, Results, IsBaseExprStatement);
+ }
+
+ // Add properties from the protocols in a qualified interface.
+ for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
+ AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement);
+ } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+ (!IsArrow && BaseType->isObjCObjectType())) {
+ // Objective-C instance variable access.
+ ObjCInterfaceDecl *Class = nullptr;
+ if (const ObjCObjectPointerType *ObjCPtr =
+ BaseType->getAs<ObjCObjectPointerType>())
+ Class = ObjCPtr->getInterfaceDecl();
+ else
+ Class = BaseType->getAs<ObjCObjectType>()->getInterface();
+
+ // Add all ivars from this class and its superclasses.
+ if (Class) {
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ Results.setFilter(&ResultBuilder::IsObjCIvar);
+ LookupVisibleDecls(
+ Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
+ /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
+ }
}
+
+ // FIXME: How do we cope with isa?
+ return true;
+ };
+
+ Results.EnterNewScope();
+
+ bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
+ if (CodeCompleter->includeFixIts()) {
+ const CharSourceRange OpRange =
+ CharSourceRange::getTokenRange(OpLoc, OpLoc);
+ CompletionSucceded |= DoCompletion(
+ OtherOpBase, !IsArrow,
+ FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
}
-
- // FIXME: How do we cope with isa?
-
+
Results.ExitScope();
+ if (!CompletionSucceded)
+ return;
+
// Hand off the results found for code completion.
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
@@ -4100,23 +4195,23 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Filter = &ResultBuilder::IsEnum;
ContextKind = CodeCompletionContext::CCC_EnumTag;
break;
-
+
case DeclSpec::TST_union:
Filter = &ResultBuilder::IsUnion;
ContextKind = CodeCompletionContext::CCC_UnionTag;
break;
-
+
case DeclSpec::TST_struct:
case DeclSpec::TST_class:
case DeclSpec::TST_interface:
Filter = &ResultBuilder::IsClassOrStruct;
ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
break;
-
+
default:
llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
}
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
@@ -4124,14 +4219,17 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
// First pass: look for tags.
Results.setFilter(Filter);
LookupVisibleDecls(S, LookupTagName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
if (CodeCompleter->includeGlobals()) {
// Second pass: look for nested name specifiers.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+ LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
}
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4157,7 +4255,7 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Results.EnterNewScope();
AddTypeQualifierResults(DS, Results, LangOpts);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -4192,7 +4290,7 @@ void Sema::CodeCompleteCase(Scope *S) {
if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
return;
- SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
+ SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
QualType type = Switch->getCond()->IgnoreImplicit()->getType();
if (!type->isEnumeralType()) {
CodeCompleteExpressionData Data(type);
@@ -4200,20 +4298,20 @@ void Sema::CodeCompleteCase(Scope *S) {
CodeCompleteExpression(S, Data);
return;
}
-
+
// Code-complete the cases of a switch statement over an enumeration type
- // by providing the list of
+ // by providing the list of
EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
if (EnumDecl *Def = Enum->getDefinition())
Enum = Def;
-
+
// Determine which enumerators we have already seen in the switch statement.
// FIXME: Ideally, we would also be able to look *past* the code-completion
// token, in case we are code-completing in the middle of the switch and not
// at the end. However, we aren't able to do so at the moment.
llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
NestedNameSpecifier *Qualifier = nullptr;
- for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
+ for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
CaseStmt *Case = dyn_cast<CaseStmt>(SC);
if (!Case)
@@ -4221,16 +4319,16 @@ void Sema::CodeCompleteCase(Scope *S) {
Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
- if (EnumConstantDecl *Enumerator
+ if (EnumConstantDecl *Enumerator
= dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
- // We look into the AST of the case statement to determine which
- // enumerator was named. Alternatively, we could compute the value of
+ // We look into the AST of the case statement to determine which
+ // enumerator was named. Alternatively, we could compute the value of
// the integral constant expression, then compare it against the
- // values of each enumerator. However, value-based approach would not
- // work as well with C++ templates where enumerators declared within a
+ // values of each enumerator. However, value-based approach would not
+ // work as well with C++ templates where enumerators declared within a
// template are type- and value-dependent.
EnumeratorsSeen.insert(Enumerator);
-
+
// If this is a qualified-id, keep track of the nested-name-specifier
// so that we can reproduce it as part of code completion, e.g.,
//
@@ -4245,14 +4343,14 @@ void Sema::CodeCompleteCase(Scope *S) {
Qualifier = DRE->getQualifier();
}
}
-
+
if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
- // If there are no prior enumerators in C++, check whether we have to
+ // If there are no prior enumerators in C++, check whether we have to
// qualify the names of the enumerators that we suggest, because they
// may not be visible in this scope.
Qualifier = getRequiredQualification(Context, CurContext, Enum);
}
-
+
// Add any enumerators that have not yet been mentioned.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
@@ -4261,23 +4359,17 @@ void Sema::CodeCompleteCase(Scope *S) {
for (auto *E : Enum->enumerators()) {
if (EnumeratorsSeen.count(E))
continue;
-
+
CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Results.AddResult(R, CurContext, nullptr, false);
}
Results.ExitScope();
- //We need to make sure we're setting the right context,
- //so only say we include macros if the code completer says we do
- enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
if (CodeCompleter->includeMacros()) {
AddMacroResults(PP, Results, false);
- kind = CodeCompletionContext::CCC_OtherWithMacros;
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
- kind,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
static bool anyNullArguments(ArrayRef<Expr *> Args) {
@@ -4316,7 +4408,7 @@ static void mergeCandidatesWithResults(Sema &SemaRef,
}
}
-/// \brief Get the type of the Nth parameter from a given set of overload
+/// Get the type of the Nth parameter from a given set of overload
/// candidates.
static QualType getParamType(Sema &SemaRef,
ArrayRef<ResultCandidate> Candidates,
@@ -4470,10 +4562,8 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
return;
// A complete type is needed to lookup for constructors.
- if (!isCompleteType(Loc, Type))
- return;
-
- CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
+ CXXRecordDecl *RD =
+ isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
if (!RD) {
CodeCompleteExpression(S, Type);
return;
@@ -4511,7 +4601,7 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
CodeCompleteOrdinaryName(S, PCC_Expression);
return;
}
-
+
CodeCompleteExpression(S, VD->getType());
}
@@ -4537,13 +4627,14 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
mapCodeCompletionContext(*this, PCC_Statement));
Results.setFilter(&ResultBuilder::IsOrdinaryName);
Results.EnterNewScope();
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
-
+
// "else" block
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -4580,13 +4671,13 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
Results.AddResult(Builder.TakeString());
Results.ExitScope();
-
+
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
-
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4649,7 +4740,8 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
/*IncludeGlobalScope=*/true,
- /*IncludeDependentBases=*/true);
+ /*IncludeDependentBases=*/true,
+ CodeCompleter->loadExternal());
}
auto CC = Results.getCompletionContext();
@@ -4662,33 +4754,33 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
void Sema::CodeCompleteUsing(Scope *S) {
if (!CodeCompleter)
return;
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PotentiallyQualifiedName,
&ResultBuilder::IsNestedNameSpecifier);
Results.EnterNewScope();
-
+
// If we aren't in class scope, we could see the "namespace" keyword.
if (!S->isClassScope())
Results.AddResult(CodeCompletionResult("namespace"));
-
- // After "using", we can see anything that would start a
+
+ // After "using", we can see anything that would start a
// nested-name-specifier.
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_PotentiallyQualifiedName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteUsingDirective(Scope *S) {
if (!CodeCompleter)
return;
-
+
// After "using namespace", we expect to see a namespace name or namespace
// alias.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -4698,46 +4790,46 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
Results.EnterNewScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Namespace,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (!CodeCompleter)
return;
-
+
DeclContext *Ctx = S->getEntity();
if (!S->getParent())
Ctx = Context.getTranslationUnitDecl();
-
+
bool SuppressedGlobalResults
= Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
SuppressedGlobalResults
? CodeCompletionContext::CCC_Namespace
: CodeCompletionContext::CCC_Other,
&ResultBuilder::IsNamespace);
-
+
if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
// We only want to see those namespaces that have already been defined
// within this scope, because its likely that the user is creating an
- // extended namespace declaration. Keep track of the most recent
+ // extended namespace declaration. Keep track of the most recent
// definition of each namespace.
std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
- for (DeclContext::specific_decl_iterator<NamespaceDecl>
+ for (DeclContext::specific_decl_iterator<NamespaceDecl>
NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
NS != NSEnd; ++NS)
OrigToLatest[NS->getOriginalNamespace()] = *NS;
-
- // Add the most recent definition (or extended definition) of each
+
+ // Add the most recent definition (or extended definition) of each
// namespace to the list of results.
Results.EnterNewScope();
- for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
+ for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
NS = OrigToLatest.begin(),
NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
@@ -4747,8 +4839,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
CurContext, nullptr, false);
Results.ExitScope();
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
+
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4756,7 +4848,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
if (!CodeCompleter)
return;
-
+
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
@@ -4764,8 +4856,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
&ResultBuilder::IsNamespaceOrAlias);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
- HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4780,26 +4873,26 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
CodeCompletionContext::CCC_Type,
&ResultBuilder::IsType);
Results.EnterNewScope();
-
+
// Add the names of overloadable operators.
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
if (std::strcmp(Spelling, "?")) \
Results.AddResult(Result(Spelling));
#include "clang/Basic/OperatorKinds.def"
-
+
// Add any type names visible from the current scope
Results.allowNestedNameSpecifiers();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
// Add any type specifiers
AddTypeSpecifierResults(getLangOpts(), Results);
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Type,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteConstructorInitializer(
@@ -4813,12 +4906,12 @@ void Sema::CodeCompleteConstructorInitializer(
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor)
return;
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PotentiallyQualifiedName);
Results.EnterNewScope();
-
+
// Fill in any already-initialized fields or base classes.
llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
@@ -4830,7 +4923,7 @@ void Sema::CodeCompleteConstructorInitializer(
InitializedFields.insert(cast<FieldDecl>(
Initializers[I]->getAnyMember()));
}
-
+
// Add completions for base classes.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -4841,69 +4934,69 @@ void Sema::CodeCompleteConstructorInitializer(
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
SawLastInitializer
- = !Initializers.empty() &&
+ = !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
Context.hasSameUnqualifiedType(Base.getType(),
QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
-
+
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(
Base.getType().getAsString(Policy)));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
SawLastInitializer? CCP_NextInitializer
: CCP_MemberDeclaration));
SawLastInitializer = false;
}
-
+
// Add completions for virtual base classes.
for (const auto &Base : ClassDecl->vbases()) {
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
SawLastInitializer
- = !Initializers.empty() &&
+ = !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
Context.hasSameUnqualifiedType(Base.getType(),
QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
-
+
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(
Base.getType().getAsString(Policy)));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
SawLastInitializer? CCP_NextInitializer
: CCP_MemberDeclaration));
SawLastInitializer = false;
}
-
+
// Add completions for members.
for (auto *Field : ClassDecl->fields()) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
.second) {
SawLastInitializer
- = !Initializers.empty() &&
+ = !Initializers.empty() &&
Initializers.back()->isAnyMemberInitializer() &&
Initializers.back()->getAnyMember() == Field;
continue;
}
-
+
if (!Field->getDeclName())
continue;
-
+
Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Field->getIdentifier()->getName()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
SawLastInitializer? CCP_NextInitializer
: CCP_MemberDeclaration,
CXCursor_MemberRef,
@@ -4912,12 +5005,12 @@ void Sema::CodeCompleteConstructorInitializer(
SawLastInitializer = false;
}
Results.ExitScope();
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
-/// \brief Determine whether this scope denotes a namespace.
+/// Determine whether this scope denotes a namespace.
static bool isNamespaceScope(Scope *S) {
DeclContext *DC = S->getEntity();
if (!DC)
@@ -4941,10 +5034,10 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
IncludedThis = true;
continue;
}
-
+
Known.insert(C.Id);
}
-
+
// Look for other capturable variables.
for (; S && !isNamespaceScope(S); S = S->getParent()) {
for (const auto *D : S->decls()) {
@@ -4953,7 +5046,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
!Var->hasLocalStorage() ||
Var->hasAttr<BlocksAttr>())
continue;
-
+
if (Known.insert(Var->getIdentifier()).second)
Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
CurContext, nullptr, false);
@@ -4963,9 +5056,9 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
// Add 'this', if it would be valid.
if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
addThisCompletion(*this, Results);
-
+
Results.ExitScope();
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -4980,7 +5073,7 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
typedef CodeCompletionResult Result;
// Since we have an implementation, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
-
+
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (LangOpts.ObjC2) {
@@ -4989,30 +5082,30 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
-
+
// @synthesize
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
- }
+ }
}
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
typedef CodeCompletionResult Result;
-
+
// Since we have an interface or protocol, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
-
+
if (LangOpts.ObjC2) {
// @property
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
-
+
// @required
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
-
+
// @optional
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
}
@@ -5022,35 +5115,35 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
// @class name ;
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
-
+
if (Results.includeCodePatterns()) {
- // @interface name
- // FIXME: Could introduce the whole pattern, including superclasses and
+ // @interface name
+ // FIXME: Could introduce the whole pattern, including superclasses and
// such.
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
-
+
// @protocol name
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("protocol");
Results.AddResult(Result(Builder.TakeString()));
-
+
// @implementation name
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// @compatibility_alias name
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -5080,9 +5173,8 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S) {
else
AddObjCTopLevelResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
@@ -5101,7 +5193,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
Builder.AddPlaceholderChunk("type-name");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
-
+
// @protocol ( protocol-name )
Builder.AddResultTypeChunk("Protocol *");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
@@ -5154,7 +5246,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
if (Results.includeCodePatterns()) {
// @try { statements } @catch ( declaration ) { statements } @finally
// { statements }
@@ -5175,13 +5267,13 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// @throw
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
-
+
if (Results.includeCodePatterns()) {
// @synchronized ( expression ) { statements }
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
@@ -5214,9 +5306,8 @@ void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Results.EnterNewScope();
AddObjCVisibilityResults(getLangOpts(), Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCAtStatement(Scope *S) {
@@ -5227,9 +5318,8 @@ void Sema::CodeCompleteObjCAtStatement(Scope *S) {
AddObjCStatementResults(Results, false);
AddObjCExpressionResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCAtExpression(Scope *S) {
@@ -5239,25 +5329,24 @@ void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Results.EnterNewScope();
AddObjCExpressionResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-/// \brief Determine whether the addition of the given flag to an Objective-C
+/// Determine whether the addition of the given flag to an Objective-C
/// property's attributes will cause a conflict.
static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
// Check if we've already added this flag.
if (Attributes & NewFlag)
return true;
-
+
Attributes |= NewFlag;
-
+
// Check for collisions with "readonly".
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
return true;
-
+
// Check for more than one of { assign, copy, retain, strong, weak }.
unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
ObjCDeclSpec::DQ_PR_unsafe_unretained |
@@ -5273,16 +5362,16 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
return true;
-
+
return false;
}
-void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
+void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
if (!CodeCompleter)
return;
-
+
unsigned Attributes = ODS.getPropertyAttributes();
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
@@ -5335,12 +5424,11 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Results.AddResult(CodeCompletionResult("null_resettable"));
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-/// \brief Describes the kind of Objective-C method that we want to find
+/// Describes the kind of Objective-C method that we want to find
/// via code completion.
enum ObjCMethodKind {
MK_Any, ///< Any kind of method, provided it means other specified criteria.
@@ -5355,20 +5443,20 @@ static bool isAcceptableObjCSelector(Selector Sel,
unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents > Sel.getNumArgs())
return false;
-
+
switch (WantKind) {
case MK_Any: break;
case MK_ZeroArgSelector: return Sel.isUnarySelector();
case MK_OneArgSelector: return Sel.getNumArgs() == 1;
}
-
+
if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
return false;
-
+
for (unsigned I = 0; I != NumSelIdents; ++I)
if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
return false;
-
+
return true;
}
@@ -5381,16 +5469,16 @@ static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
}
namespace {
- /// \brief A set of selectors, which is used to avoid introducing multiple
+ /// A set of selectors, which is used to avoid introducing multiple
/// completions with the same selector into the result set.
typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
}
-/// \brief Add all of the Objective-C methods in the given Objective-C
+/// Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
///
-/// The container will be a class, protocol, category, or implementation of
-/// any of the above. This mether will recurse to include methods from
+/// The container will be a class, protocol, category, or implementation of
+/// any of the above. This mether will recurse to include methods from
/// the superclasses of classes along with their categories, protocols, and
/// implementations.
///
@@ -5422,7 +5510,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
// metaclass.
if (M->isInstanceMethod() == WantInstanceMethods ||
(IsRootClass && !WantInstanceMethods)) {
- // Check whether the selector identifiers we've been given are a
+ // Check whether the selector identifiers we've been given are a
// subset of the identifiers for this particular method.
if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
continue;
@@ -5438,23 +5526,23 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Results.MaybeAddResult(R, CurContext);
}
}
-
+
// Visit the protocols of protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition()) {
const ObjCList<ObjCProtocolDecl> &Protocols
= Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, false, IsRootClass);
}
}
-
+
if (!IFace || !IFace->hasDefinition())
return;
-
+
// Add methods in protocols.
for (auto *I : IFace->protocols())
AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
@@ -5467,7 +5555,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
InOriginalClass, IsRootClass);
// Add a categories protocol methods.
- const ObjCList<ObjCProtocolDecl> &Protocols
+ const ObjCList<ObjCProtocolDecl> &Protocols
= CatDecl->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
@@ -5481,7 +5569,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Selectors, AllowSameLength, Results, InOriginalClass,
IsRootClass);
}
-
+
// Add methods in superclass.
// Avoid passing in IsRootClass since root classes won't have super classes.
if (IFace->getSuperClass())
@@ -5519,9 +5607,8 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
/*AllowSameLength=*/true, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
@@ -5548,9 +5635,8 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Selectors, /*AllowSameLength=*/true, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
@@ -5559,22 +5645,22 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Type);
Results.EnterNewScope();
-
+
// Add context-sensitive, Objective-C parameter-passing keywords.
bool AddedInOut = false;
- if ((DS.getObjCDeclQualifier() &
+ if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
Results.AddResult("in");
Results.AddResult("inout");
AddedInOut = true;
}
- if ((DS.getObjCDeclQualifier() &
+ if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
Results.AddResult("out");
if (!AddedInOut)
Results.AddResult("inout");
}
- if ((DS.getObjCDeclQualifier() &
+ if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
ObjCDeclSpec::DQ_Oneway)) == 0) {
Results.AddResult("bycopy");
@@ -5586,8 +5672,8 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
Results.AddResult("nullable");
Results.AddResult("null_unspecified");
}
-
- // If we're completing the return type of an Objective-C method and the
+
+ // If we're completing the return type of an Objective-C method and the
// identifier IBAction refers to a macro, provide a completion item for
// an action, e.g.,
// IBAction)<#selector#>:(id)sender
@@ -5611,26 +5697,26 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
if (!IsParameter) {
Results.AddResult(CodeCompletionResult("instancetype"));
}
-
+
// Add various builtin type names and specifiers.
AddOrdinaryNameResults(PCC_Type, S, *this, Results);
Results.ExitScope();
-
+
// Add the various type names
Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Type,
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
-/// \brief When we have an expression with type "id", we may assume
+/// When we have an expression with type "id", we may assume
/// that it has some more-specific class type based on knowledge of
/// common uses of Objective-C. This routine returns that class type,
/// or NULL if no better result could be determined.
@@ -5702,7 +5788,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
}
// Add a special completion for a message send to "super", which fills in the
-// most likely case of forwarding all of our arguments to the superclass
+// most likely case of forwarding all of our arguments to the superclass
// function.
///
/// \param S The semantic analysis object.
@@ -5715,7 +5801,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
///
/// \param Results The set of results to augment.
///
-/// \returns the Objective-C method declaration that would be invoked by
+/// \returns the Objective-C method declaration that would be invoked by
/// this "super" completion. If NULL, no completion was added.
static ObjCMethodDecl *AddSuperSendCompletion(
Sema &S, bool NeedSuperKeyword,
@@ -5733,7 +5819,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
ObjCMethodDecl *SuperMethod = nullptr;
while ((Class = Class->getSuperClass()) && !SuperMethod) {
// Check in the class
- SuperMethod = Class->getMethod(CurMethod->getSelector(),
+ SuperMethod = Class->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod());
// Check in categories or class extensions.
@@ -5759,7 +5845,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
SuperP = SuperMethod->param_begin();
CurP != CurPEnd; ++CurP, ++SuperP) {
// Make sure the parameter types are compatible.
- if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
+ if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
(*SuperP)->getType()))
return nullptr;
@@ -5767,11 +5853,11 @@ static ObjCMethodDecl *AddSuperSendCompletion(
if (!(*CurP)->getIdentifier())
return nullptr;
}
-
+
// We have a superclass method. Now, form the send-to-super completion.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
// Give this completion a return type.
AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Results.getCompletionContext().getBaseType(),
@@ -5782,7 +5868,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Builder.AddTypedTextChunk("super");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
}
-
+
Selector Sel = CurMethod->getSelector();
if (Sel.isUnarySelector()) {
if (NeedSuperKeyword)
@@ -5796,7 +5882,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
if (I > SelIdents.size())
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
-
+
if (I < SelIdents.size())
Builder.AddInformativeChunk(
Builder.getAllocator().CopyString(
@@ -5812,16 +5898,16 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Builder.getAllocator().CopyString(
Sel.getNameForSlot(I) + ":"));
Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
- (*CurP)->getIdentifier()->getName()));
+ (*CurP)->getIdentifier()->getName()));
}
}
}
-
+
Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
CCP_SuperCompletion));
return SuperMethod;
}
-
+
void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -5830,32 +5916,33 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
getLangOpts().CPlusPlus11
? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
: &ResultBuilder::IsObjCMessageReceiver);
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.EnterNewScope();
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
// If we are in an Objective-C method inside a class that has a superclass,
// add "super" as an option.
if (ObjCMethodDecl *Method = getCurMethodDecl())
if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
if (Iface->getSuperClass()) {
Results.AddResult(Result("super"));
-
+
AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
}
-
+
if (getLangOpts().CPlusPlus11)
addThisCompletion(*this, Results);
-
+
Results.ExitScope();
-
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
-
+
}
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
@@ -5867,7 +5954,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
CDecl = CurMethod->getClassInterface();
if (!CDecl)
return;
-
+
// Find the superclass of this class.
CDecl = CDecl->getSuperClass();
if (!CDecl)
@@ -5887,7 +5974,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// "super" may be the name of a type or variable. Figure out which
// it is.
IdentifierInfo *Super = getSuperIdentifier();
- NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
+ NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
LookupOrdinaryName);
if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
// "super" names an interface. Use it.
@@ -5916,24 +6003,24 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
ParsedType Receiver;
if (CDecl)
Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
- return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
+ return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
AtArgumentExpression,
/*IsSuper=*/true);
}
-/// \brief Given a set of code-completion results for the argument of a message
+/// Given a set of code-completion results for the argument of a message
/// send, determine the preferred type (if any) for that argument expression.
static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
unsigned NumSelIdents) {
- typedef CodeCompletionResult Result;
+ typedef CodeCompletionResult Result;
ASTContext &Context = Results.getSema().Context;
-
+
QualType PreferredType;
unsigned BestPriority = CCP_Unlikely * 2;
Result *ResultsData = Results.data();
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
Result &R = ResultsData[I];
- if (R.Kind == Result::RK_Declaration &&
+ if (R.Kind == Result::RK_Declaration &&
isa<ObjCMethodDecl>(R.Declaration)) {
if (R.Priority <= BestPriority) {
const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
@@ -5955,7 +6042,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
return PreferredType;
}
-static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
@@ -5968,55 +6055,55 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
// corresponding declaration.
if (Receiver) {
QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
- if (!T.isNull())
+ if (!T.isNull())
if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
CDecl = Interface->getInterface();
}
-
+
// Add all of the factory methods in this Objective-C class, its protocols,
// superclasses, categories, implementation, etc.
Results.EnterNewScope();
-
- // If this is a send-to-super, try to add the special "super" send
+
+ // If this is a send-to-super, try to add the special "super" send
// completion.
if (IsSuper) {
if (ObjCMethodDecl *SuperMethod
= AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
-
+
// If we're inside an Objective-C method definition, prefer its selector to
// others.
if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
-
+
VisitedSelectorSet Selectors;
- if (CDecl)
+ if (CDecl)
AddObjCMethods(CDecl, false, MK_Any, SelIdents,
SemaRef.CurContext, Selectors, AtArgumentExpression,
- Results);
+ Results);
else {
// We're messaging "id" as a type; provide all class/factory methods.
-
+
// If we have an external source, load the entire class method
// pool from the AST file.
if (SemaRef.getExternalSource()) {
- for (uint32_t I = 0,
+ for (uint32_t I = 0,
N = SemaRef.getExternalSource()->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
continue;
-
+
SemaRef.ReadMethodPool(Sel);
}
}
-
+
for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
MEnd = SemaRef.MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.second;
- MethList && MethList->getMethod();
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
@@ -6029,32 +6116,32 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
}
}
}
-
- Results.ExitScope();
+
+ Results.ExitScope();
}
void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper) {
-
+
QualType T = this->GetTypeFromParser(Receiver);
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
T, SelIdents));
-
+
AddClassMessageCompletions(*this, S, Receiver, SelIdents,
AtArgumentExpression, IsSuper, Results);
-
- // If we're actually at the argument expression (rather than prior to the
+
+ // If we're actually at the argument expression (rather than prior to the
// selector), we're actually performing code completion for an expression.
- // Determine whether we have a single, best method. If so, we can
+ // Determine whether we have a single, best method. If so, we can
// code-complete the expression using the corresponding parameter type as
// our preferred type, improving completion results.
if (AtArgumentExpression) {
- QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
+ QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
@@ -6063,7 +6150,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
return;
}
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -6073,9 +6160,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
bool AtArgumentExpression,
ObjCInterfaceDecl *Super) {
typedef CodeCompletionResult Result;
-
+
Expr *RecExpr = static_cast<Expr *>(Receiver);
-
+
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
if (RecExpr) {
@@ -6084,18 +6171,18 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
return;
RecExpr = Conv.get();
}
- QualType ReceiverType = RecExpr? RecExpr->getType()
+ QualType ReceiverType = RecExpr? RecExpr->getType()
: Super? Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(Super))
: Context.getObjCIdType();
-
+
// If we're messaging an expression with type "id" or "Class", check
// whether we know something special about the receiver that allows
// us to assume a more-specific receiver type.
if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
if (ReceiverType->isObjCClassType())
- return CodeCompleteObjCClassMessage(S,
+ return CodeCompleteObjCClassMessage(S,
ParsedType::make(Context.getObjCInterfaceType(IFace)),
SelIdents,
AtArgumentExpression, Super);
@@ -6116,36 +6203,36 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
ReceiverType, SelIdents));
-
+
Results.EnterNewScope();
- // If this is a send-to-super, try to add the special "super" send
+ // If this is a send-to-super, try to add the special "super" send
// completion.
if (Super) {
if (ObjCMethodDecl *SuperMethod
= AddSuperSendCompletion(*this, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
-
+
// If we're inside an Objective-C method definition, prefer its selector to
// others.
if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
-
+
// Keep track of the selectors we've already added.
VisitedSelectorSet Selectors;
-
+
// Handle messages to Class. This really isn't a message to an instance
// method, so we treat it the same way we would treat a message send to a
// class method.
- if (ReceiverType->isObjCClassType() ||
+ if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
CurContext, Selectors, AtArgumentExpression, Results);
}
- }
+ }
// Handle messages to a qualified ID ("id<foo>").
else if (const ObjCObjectPointerType *QualID
= ReceiverType->getAsObjCQualifiedIdType()) {
@@ -6161,7 +6248,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
CurContext, Selectors, AtArgumentExpression,
Results);
-
+
// Search protocols for instance methods.
for (auto *I : IFacePtr->quals())
AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
@@ -6189,11 +6276,11 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.first;
- MethList && MethList->getMethod();
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
-
+
if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
continue;
@@ -6206,15 +6293,15 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
}
}
Results.ExitScope();
-
-
- // If we're actually at the argument expression (rather than prior to the
+
+
+ // If we're actually at the argument expression (rather than prior to the
// selector), we're actually performing code completion for an expression.
- // Determine whether we have a single, best method. If so, we can
+ // Determine whether we have a single, best method. If so, we can
// code-complete the expression using the corresponding parameter type as
// our preferred type, improving completion results.
if (AtArgumentExpression) {
- QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
+ QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
@@ -6222,17 +6309,17 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
CodeCompleteExpression(S, PreferredType);
return;
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
+
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(),Results.size());
}
-void Sema::CodeCompleteObjCForCollection(Scope *S,
+void Sema::CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar) {
CodeCompleteExpressionData Data;
Data.ObjCCollection = true;
-
+
if (IterationVar.getAsOpaquePtr()) {
DeclGroupRef DG = IterationVar.get();
for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
@@ -6240,7 +6327,7 @@ void Sema::CodeCompleteObjCForCollection(Scope *S,
Data.IgnoreDecls.push_back(*I);
}
}
-
+
CodeCompleteExpression(S, Data);
}
@@ -6254,11 +6341,11 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
-
+
ReadMethodPool(Sel);
}
}
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_SelectorName);
@@ -6266,7 +6353,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
-
+
Selector Sel = M->first;
if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
continue;
@@ -6279,7 +6366,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Results.AddResult(Builder.TakeString());
continue;
}
-
+
std::string Accumulator;
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
if (I == SelIdents.size()) {
@@ -6289,7 +6376,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Accumulator.clear();
}
}
-
+
Accumulator += Sel.getNameForSlot(I);
Accumulator += ':';
}
@@ -6297,19 +6384,18 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Results.AddResult(Builder.TakeString());
}
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_SelectorName,
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
-/// \brief Add all of the protocol declarations that we find in the given
+/// Add all of the protocol declarations that we find in the given
/// (translation unit) context.
static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
-
+
for (const auto *D : Ctx->decls()) {
// Record any protocols we find.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
@@ -6324,10 +6410,10 @@ void Sema::CodeCompleteObjCProtocolReferences(
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
-
+
if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
-
+
// Tell the result set to ignore all of the protocols we have
// already seen.
// FIXME: This doesn't work when caching code-completion results.
@@ -6342,40 +6428,38 @@ void Sema::CodeCompleteObjCProtocolReferences(
Results.ExitScope();
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCProtocolName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
-
+
if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
-
+
// Add all protocols.
AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
Results);
Results.ExitScope();
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCProtocolName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-/// \brief Add all of the Objective-C interface declarations that we find in
+/// Add all of the Objective-C interface declarations that we find in
/// the given (translation unit) context.
static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
bool OnlyUnimplemented,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
-
+
for (const auto *D : Ctx->decls()) {
// Record any interfaces we find.
if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
@@ -6386,32 +6470,31 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
}
}
-void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
+void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Other);
+ CodeCompletionContext::CCC_ObjCInterfaceName);
Results.EnterNewScope();
-
+
if (CodeCompleter->includeGlobals()) {
// Add all classes.
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
false, Results);
}
-
+
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCInterfaceName,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
+ SourceLocation ClassNameLoc) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCInterfaceName);
Results.EnterNewScope();
-
+
// Make sure that we ignore the class we're currently defining.
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
@@ -6423,18 +6506,17 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
false, Results);
}
-
+
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCInterfaceName,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
+void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Other);
+ CodeCompletionContext::CCC_ObjCImplementation);
Results.EnterNewScope();
if (CodeCompleter->includeGlobals()) {
@@ -6442,23 +6524,22 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
true, Results);
}
-
+
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCInterfaceName,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
typedef CodeCompletionResult Result;
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCCategoryName);
-
+
// Ignore any categories we find that have already been implemented by this
// interface.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
@@ -6472,24 +6553,23 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
- for (const auto *D : TU->decls())
+ for (const auto *D : TU->decls())
if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()).second)
Results.AddResult(Result(Category, Results.getBasePriority(Category),
nullptr),
CurContext, nullptr, false);
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCCategoryName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
typedef CodeCompletionResult Result;
-
+
// Find the corresponding interface. If we couldn't find the interface, the
// program itself is ill-formed. However, we'll try to be helpful still by
// providing the list of all of the categories we know about.
@@ -6498,12 +6578,12 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
if (!Class)
return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCCategoryName);
-
- // Add all of the categories that have have corresponding interface
+
+ // Add all of the categories that have have corresponding interface
// declarations in this class and any of its superclasses, except for
// already-implemented categories in the class itself.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
@@ -6516,15 +6596,14 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
CurContext, nullptr, false);
}
-
+
Class = Class->getSuperClass();
IgnoreImplemented = false;
}
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCCategoryName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
@@ -6536,38 +6615,37 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
= dyn_cast_or_null<ObjCContainerDecl>(CurContext);
- if (!Container ||
- (!isa<ObjCImplementationDecl>(Container) &&
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
- return;
+ return;
// Ignore any properties that have already been implemented.
Container = getContainerDef(Container);
for (const auto *D : Container->decls())
if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Results.Ignore(PropertyImpl->getPropertyDecl());
-
+
// Add any properties that we find.
AddedPropertiesSet AddedProperties;
Results.EnterNewScope();
if (ObjCImplementationDecl *ClassImpl
= dyn_cast<ObjCImplementationDecl>(Container))
AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
- /*AllowNullaryMethods=*/false, CurContext,
+ /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
else
AddObjCProperties(CCContext,
cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
- false, /*AllowNullaryMethods=*/false, CurContext,
+ false, /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
IdentifierInfo *PropertyName) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -6577,11 +6655,11 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
= dyn_cast_or_null<ObjCContainerDecl>(CurContext);
- if (!Container ||
- (!isa<ObjCImplementationDecl>(Container) &&
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
- return;
-
+ return;
+
// Figure out which interface we're looking into.
ObjCInterfaceDecl *Class = nullptr;
if (ObjCImplementationDecl *ClassImpl
@@ -6596,10 +6674,10 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
if (Class) {
if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
- PropertyType
+ PropertyType
= Property->getType().getNonReferenceType().getUnqualifiedType();
-
- // Give preference to ivars
+
+ // Give preference to ivars
Results.setPreferredType(PropertyType);
}
}
@@ -6613,32 +6691,32 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
std::string NameWithSuffix = PropertyName->getName().str();
NameWithSuffix += '_';
for(; Class; Class = Class->getSuperClass()) {
- for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
+ for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
CurContext, nullptr, false);
- // Determine whether we've seen an ivar with a name similar to the
+ // Determine whether we've seen an ivar with a name similar to the
// property.
if ((PropertyName == Ivar->getIdentifier() ||
NameWithPrefix == Ivar->getName() ||
NameWithSuffix == Ivar->getName())) {
SawSimilarlyNamedIvar = true;
-
+
// Reduce the priority of this result by one, to give it a slight
// advantage over other results whose names don't match so closely.
- if (Results.size() &&
- Results.data()[Results.size() - 1].Kind
+ if (Results.size() &&
+ Results.data()[Results.size() - 1].Kind
== CodeCompletionResult::RK_Declaration &&
Results.data()[Results.size() - 1].Declaration == Ivar)
Results.data()[Results.size() - 1].Priority--;
}
}
}
-
+
if (!SawSimilarlyNamedIvar) {
// Create ivar result _propName, that the user can use to synthesize
- // an ivar of the appropriate type.
+ // an ivar of the appropriate type.
unsigned Priority = CCP_MemberDeclaration + 1;
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
@@ -6649,15 +6727,14 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Policy, Allocator));
Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
- Results.AddResult(Result(Builder.TakeString(), Priority,
+ Results.AddResult(Result(Builder.TakeString(), Priority,
CXCursor_ObjCIvarDecl));
}
-
+
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
// Mapping from selectors to the methods that implement that selector, along
@@ -6665,7 +6742,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
typedef llvm::DenseMap<
Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
-/// \brief Find all of the methods that reside in the given container
+/// Find all of the methods that reside in the given container
/// (and its superclasses, protocols, etc.) that meet the given
/// criteria. Insert those methods into the map of known methods,
/// indexed by selector so they can be easily found.
@@ -6682,11 +6759,11 @@ static void FindImplementableMethods(ASTContext &Context,
IFace = IFace->getDefinition();
Container = IFace;
-
+
const ObjCList<ObjCProtocolDecl> &Protocols
= IFace->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, InOriginalClass);
@@ -6694,12 +6771,12 @@ static void FindImplementableMethods(ASTContext &Context,
// Add methods from any class extensions and categories.
for (auto *Cat : IFace->visible_categories()) {
FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
- KnownMethods, false);
+ KnownMethods, false);
}
// Visit the superclass.
if (IFace->getSuperClass())
- FindImplementableMethods(Context, IFace->getSuperClass(),
+ FindImplementableMethods(Context, IFace->getSuperClass(),
WantInstanceMethods, ReturnType,
KnownMethods, false);
}
@@ -6709,14 +6786,14 @@ static void FindImplementableMethods(ASTContext &Context,
const ObjCList<ObjCProtocolDecl> &Protocols
= Category->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, InOriginalClass);
-
+
// If this category is the original class, jump to the interface.
if (InOriginalClass && Category->getClassInterface())
- FindImplementableMethods(Context, Category->getClassInterface(),
+ FindImplementableMethods(Context, Category->getClassInterface(),
WantInstanceMethods, ReturnType, KnownMethods,
false);
}
@@ -6727,12 +6804,12 @@ static void FindImplementableMethods(ASTContext &Context,
return;
Protocol = Protocol->getDefinition();
Container = Protocol;
-
+
// Recurse into protocols.
const ObjCList<ObjCProtocolDecl> &Protocols
= Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, false);
@@ -6753,7 +6830,7 @@ static void FindImplementableMethods(ASTContext &Context,
}
}
-/// \brief Add the parenthesized return or parameter type chunk to a code
+/// Add the parenthesized return or parameter type chunk to a code
/// completion string.
static void AddObjCPassingTypeChunk(QualType Type,
unsigned ObjCDeclQuals,
@@ -6769,20 +6846,20 @@ static void AddObjCPassingTypeChunk(QualType Type,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-/// \brief Determine whether the given class is or inherits from a class by
+/// Determine whether the given class is or inherits from a class by
/// the given name.
-static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
+static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
StringRef Name) {
if (!Class)
return false;
-
+
if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
return true;
-
+
return InheritsFromClassNamed(Class->getSuperClass(), Name);
}
-
-/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
+
+/// Add code completions for Objective-C Key-Value Coding (KVC) and
/// Key-Value Observing (KVO).
static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
bool IsInstanceMethod,
@@ -6793,17 +6870,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
IdentifierInfo *PropName = Property->getIdentifier();
if (!PropName || PropName->getLength() == 0)
return;
-
+
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
// Builder that will create each code completion.
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
-
+
// The selector table.
SelectorTable &Selectors = Context.Selectors;
-
+
// The property name, copied into the code completion allocation region
// on demand.
struct KeyHolder {
@@ -6817,22 +6894,22 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
operator const char *() {
if (CopiedKey)
return CopiedKey;
-
+
return CopiedKey = Allocator.CopyString(Key);
}
} Key(Allocator, PropName->getName());
-
+
// The uppercased name of the property name.
std::string UpperKey = PropName->getName();
if (!UpperKey.empty())
UpperKey[0] = toUppercase(UpperKey[0]);
-
+
bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
- Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
+ Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Property->getType());
- bool ReturnTypeMatchesVoid
+ bool ReturnTypeMatchesVoid
= ReturnType.isNull() || ReturnType->isVoidType();
-
+
// Add the normal accessor -(type)key.
if (IsInstanceMethod &&
KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
@@ -6840,19 +6917,19 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (ReturnType.isNull())
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
Context, Policy, Builder);
-
+
Builder.AddTypedTextChunk(Key);
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
-
+
// If we have an integral or boolean property (or the user has provided
// an integral or boolean return type), add the accessor -(type)isKey.
if (IsInstanceMethod &&
- ((!ReturnType.isNull() &&
+ ((!ReturnType.isNull() &&
(ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
- (ReturnType.isNull() &&
- (Property->getType()->isIntegerType() ||
+ (ReturnType.isNull() &&
+ (Property->getType()->isIntegerType() ||
Property->getType()->isBooleanType())))) {
std::string SelectorName = (Twine("is") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -6863,16 +6940,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("BOOL");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(
Allocator.CopyString(SelectorId->getName()));
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Add the normal mutator.
- if (IsInstanceMethod && ReturnTypeMatchesVoid &&
+ if (IsInstanceMethod && ReturnTypeMatchesVoid &&
!Property->getSetterMethodDecl()) {
std::string SelectorName = (Twine("set") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -6882,36 +6959,36 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(
Allocator.CopyString(SelectorId->getName()));
Builder.AddTypedTextChunk(":");
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
Context, Policy, Builder);
Builder.AddTextChunk(Key);
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Indexed and unordered accessors
unsigned IndexedGetterPriority = CCP_CodePattern;
unsigned IndexedSetterPriority = CCP_CodePattern;
unsigned UnorderedGetterPriority = CCP_CodePattern;
unsigned UnorderedSetterPriority = CCP_CodePattern;
- if (const ObjCObjectPointerType *ObjCPointer
+ if (const ObjCObjectPointerType *ObjCPointer
= Property->getType()->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
// If this interface type is not provably derived from a known
// collection, penalize the corresponding completions.
if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
- IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
+ IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
if (!InheritsFromClassNamed(IFace, "NSArray"))
IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
}
if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
- UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
+ UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
if (!InheritsFromClassNamed(IFace, "NSSet"))
UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
}
@@ -6922,9 +6999,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
}
-
+
// Add -(NSUInteger)countOf<key>
- if (IsInstanceMethod &&
+ if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isIntegerType())) {
std::string SelectorName = (Twine("countOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -6935,16 +7012,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(
Allocator.CopyString(SelectorId->getName()));
- Results.AddResult(Result(Builder.TakeString(),
- std::min(IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(),
+ std::min(IndexedGetterPriority,
UnorderedGetterPriority),
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Indexed getters
// Add -(id)objectInKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod &&
@@ -6958,20 +7035,20 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
- Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod &&
- (ReturnType.isNull() ||
+ (ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
@@ -6985,17 +7062,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
- Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Add -(void)getKey:(type **)buffer range:(NSRange)inRange
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("get") + UpperKey).str();
@@ -7003,14 +7080,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName),
&Context.Idents.get("range")
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
@@ -7023,13 +7100,13 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSRange");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("inRange");
- Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Mutable indexed accessors
-
+
// - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
@@ -7037,14 +7114,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get("insertObject"),
&Context.Idents.get(SelectorName)
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk("insertObject:");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
@@ -7057,11 +7134,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddPlaceholderChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("insert") + UpperKey).str();
@@ -7069,14 +7146,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName),
&Context.Idents.get("atIndexes")
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSArray *");
@@ -7088,55 +7165,55 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddPlaceholderChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
= (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
- IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
= (Twine("remove") + UpperKey + "AtIndexes").str();
- IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
@@ -7145,14 +7222,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName),
&Context.Idents.get("withObject")
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSUInteger");
@@ -7164,28 +7241,28 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName1
+ std::string SelectorName1
= (Twine("replace") + UpperKey + "AtIndexes").str();
std::string SelectorName2 = (Twine("with") + UpperKey).str();
IdentifierInfo *SelectorIds[2] = {
&Context.Idents.get(SelectorName1),
&Context.Idents.get(SelectorName2)
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSIndexSet *");
@@ -7197,15 +7274,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("array");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// Unordered getters
// - (NSEnumerator *)enumeratorOfKey
- if (IsInstanceMethod &&
- (ReturnType.isNull() ||
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
@@ -7219,15 +7296,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSEnumerator *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
- Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (type *)memberOfKey:(type *)object
- if (IsInstanceMethod &&
+ if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
std::string SelectorName = (Twine("memberOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -7238,24 +7315,24 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (ReturnType.isNull()) {
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
} else {
- Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
+ Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Policy,
Builder.getAllocator()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Mutable unordered accessors
// - (void)addKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
@@ -7268,17 +7345,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
+ }
// - (void)addKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
@@ -7290,17 +7367,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// - (void)removeKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
@@ -7312,18 +7389,18 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// - (void)removeKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("remove") + UpperKey).str();
@@ -7334,16 +7411,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
+ }
// - (void)intersectKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
@@ -7355,26 +7432,26 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// Key-Value Observing
// + (NSSet *)keyPathsForValuesAffectingKey
- if (!IsInstanceMethod &&
- (ReturnType.isNull() ||
+ if (!IsInstanceMethod &&
+ (ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
->getName() == "NSSet"))) {
- std::string SelectorName
+ std::string SelectorName
= (Twine("keyPathsForValuesAffecting") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
@@ -7384,9 +7461,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSSet<NSString *> *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCClassMethodDecl));
}
}
@@ -7394,9 +7471,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// + (BOOL)automaticallyNotifiesObserversForKey
if (!IsInstanceMethod &&
(ReturnType.isNull() ||
- ReturnType->isIntegerType() ||
+ ReturnType->isIntegerType() ||
ReturnType->isBooleanType())) {
- std::string SelectorName
+ std::string SelectorName
= (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
@@ -7406,9 +7483,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("BOOL");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCClassMethodDecl));
}
}
@@ -7422,7 +7499,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Decl *IDecl = nullptr;
if (CurContext->isObjCContainer()) {
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- IDecl = cast<Decl>(OCD);
+ IDecl = OCD;
}
// Determine where we should start searching for methods.
ObjCContainerDecl *SearchDecl = nullptr;
@@ -7431,7 +7508,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
SearchDecl = Impl->getClassInterface();
IsInImplementation = true;
- } else if (ObjCCategoryImplDecl *CatImpl
+ } else if (ObjCCategoryImplDecl *CatImpl
= dyn_cast<ObjCCategoryImplDecl>(D)) {
SearchDecl = CatImpl->getCategoryDecl();
IsInImplementation = true;
@@ -7445,17 +7522,17 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
}
if (!SearchDecl) {
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
nullptr, 0);
return;
}
-
+
// Find all of the methods that we could declare/implement here.
KnownMethodsMap KnownMethods;
- FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
+ FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
ReturnType, KnownMethods);
-
+
// Add declarations or definitions for each of the known methods.
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -7463,7 +7540,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
- for (KnownMethodsMap::iterator M = KnownMethods.begin(),
+ for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M) {
ObjCMethodDecl *Method = M->second.getPointer();
@@ -7494,7 +7571,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
// Add parameters to the pattern.
unsigned I = 0;
- for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
PEnd = Method->param_end();
P != PEnd; (void)++P, ++I) {
// Add the part of the selector name.
@@ -7520,16 +7597,16 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
(*P)->getObjCDeclQualifier(),
Context, Policy,
Builder);
-
+
if (IdentifierInfo *Id = (*P)->getIdentifier())
- Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
+ Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
}
if (Method->isVariadic()) {
if (Method->param_size() > 0)
Builder.AddChunk(CodeCompletionString::CK_Comma);
Builder.AddTextChunk("...");
- }
+ }
if (IsInImplementation && Results.includeCodePatterns()) {
// We will be defining the method here, so add a compound statement.
@@ -7544,7 +7621,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Builder.AddChunk(CodeCompletionString::CK_SemiColon);
} else
Builder.AddPlaceholderChunk("statements");
-
+
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
}
@@ -7552,28 +7629,28 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
unsigned Priority = CCP_CodePattern;
if (!M->second.getInt())
Priority += CCD_InBaseClass;
-
+
Results.AddResult(Result(Builder.TakeString(), Method, Priority));
}
- // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
+ // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
// the properties in this class and its categories.
if (Context.getLangOpts().ObjC2) {
SmallVector<ObjCContainerDecl *, 4> Containers;
Containers.push_back(SearchDecl);
-
+
VisitedSelectorSet KnownSelectors;
- for (KnownMethodsMap::iterator M = KnownMethods.begin(),
+ for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M)
KnownSelectors.insert(M->first);
-
+
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
if (!IFace)
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
IFace = Category->getClassInterface();
-
+
if (IFace)
for (auto *Cat : IFace->visible_categories())
Containers.push_back(Cat);
@@ -7585,15 +7662,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
KnownSelectors, Results);
}
}
-
+
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
+void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
bool AtParameterName,
ParsedType ReturnTy,
@@ -7616,21 +7692,21 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
-
+
if (ReturnTy)
Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
- Results.EnterNewScope();
+ Results.EnterNewScope();
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
&M->second.second;
- MethList && MethList->getMethod();
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
-
+
if (AtParameterName) {
// Suggest parameter names we've seen before.
unsigned NumSelIdents = SelIdents.size();
@@ -7646,7 +7722,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Results.AddResult(Builder.TakeString());
}
}
-
+
continue;
}
@@ -7658,7 +7734,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Results.MaybeAddResult(R, CurContext);
}
}
-
+
Results.ExitScope();
if (!AtParameterName && !SelIdents.empty() &&
@@ -7677,9 +7753,8 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
}
}
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
@@ -7687,7 +7762,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorDirective);
Results.EnterNewScope();
-
+
// #if <condition>
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7695,13 +7770,13 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("condition");
Results.AddResult(Builder.TakeString());
-
+
// #ifdef <macro>
Builder.AddTypedTextChunk("ifdef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
-
+
// #ifndef <macro>
Builder.AddTypedTextChunk("ifndef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7723,7 +7798,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddTypedTextChunk("endif");
Results.AddResult(Builder.TakeString());
}
-
+
// #include "header"
Builder.AddTypedTextChunk("include");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7739,13 +7814,13 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
-
+
// #define <macro>
Builder.AddTypedTextChunk("define");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
-
+
// #define <macro>(<args>)
Builder.AddTypedTextChunk("define");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7754,7 +7829,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Builder.TakeString());
-
+
// #undef <macro>
Builder.AddTypedTextChunk("undef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7766,7 +7841,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("number");
Results.AddResult(Builder.TakeString());
-
+
// #line <number> "filename"
Builder.AddTypedTextChunk("line");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7776,7 +7851,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("filename");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
-
+
// #error <message>
Builder.AddTypedTextChunk("error");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7797,7 +7872,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
-
+
// #import <header>
Builder.AddTypedTextChunk("import");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7806,7 +7881,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
}
-
+
// #include_next "header"
Builder.AddTypedTextChunk("include_next");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7814,7 +7889,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
-
+
// #include_next <header>
Builder.AddTypedTextChunk("include_next");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7835,15 +7910,14 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
// FIXME: we don't support #assert or #unassert, so don't suggest them.
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_PreprocessorDirective,
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
CodeCompleteOrdinaryName(S,
- S->getFnParent()? Sema::PCC_RecoveryInFunction
+ S->getFnParent()? Sema::PCC_RecoveryInFunction
: Sema::PCC_Namespace);
}
@@ -7853,11 +7927,11 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
IsDefinition? CodeCompletionContext::CCC_MacroName
: CodeCompletionContext::CCC_MacroNameUse);
if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
- // Add just the names of macros, not their arguments.
+ // Add just the names of macros, not their arguments.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Results.EnterNewScope();
- for (Preprocessor::macro_iterator M = PP.macro_begin(),
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
@@ -7870,19 +7944,19 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
} else if (IsDefinition) {
// FIXME: Can we detect when the user just wrote an include guard above?
}
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
- Results.data(), Results.size());
+ Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorExpression() {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorExpression);
-
+
if (!CodeCompleter || CodeCompleter->includeMacros())
AddMacroResults(PP, Results, true);
-
+
// defined (<macro>)
Results.EnterNewScope();
CodeCompletionBuilder Builder(Results.getAllocator(),
@@ -7894,10 +7968,9 @@ void Sema::CodeCompletePreprocessorExpression() {
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Builder.TakeString());
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_PreprocessorExpression,
- Results.data(), Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
@@ -7906,7 +7979,7 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
unsigned Argument) {
// FIXME: In the future, we could provide "overload" results, much like we
// do for function calls.
-
+
// Now just ignore this. There will be another code-completion callback
// for the expanded tokens.
}
@@ -7929,9 +8002,8 @@ void Sema::CodeCompleteAvailabilityPlatformName() {
Twine(Platform) + "ApplicationExtension")));
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other, Results.data(),
- Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
@@ -7940,16 +8012,17 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
ResultBuilder Builder(*this, Allocator, CCTUInfo,
CodeCompletionContext::CCC_Recovery);
if (!CodeCompleter || CodeCompleter->includeGlobals()) {
- CodeCompletionDeclConsumer Consumer(Builder,
+ CodeCompletionDeclConsumer Consumer(Builder,
Context.getTranslationUnitDecl());
- LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
- Consumer);
+ LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
+ Consumer,
+ !CodeCompleter || CodeCompleter->loadExternal());
}
-
+
if (!CodeCompleter || CodeCompleter->includeMacros())
AddMacroResults(PP, Builder, true);
-
+
Results.clear();
- Results.insert(Results.end(),
+ Results.insert(Results.end(),
Builder.data(), Builder.data() + Builder.size());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
index e6b640f878c2..1d5454ca778b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
@@ -9,15 +9,20 @@
//
// This file implements semantic analysis for C++ Coroutines.
//
+// This file contains references to sections of the Coroutines TS, which
+// can be found at http://wg21.link/coroutines.
+//
//===----------------------------------------------------------------------===//
#include "CoroutineStmtBuilder.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/Decl.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Overload.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
using namespace clang;
@@ -55,20 +60,8 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
return QualType();
}
- LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
- FuncLoc, Sema::LookupOrdinaryName);
- if (!S.LookupQualifiedName(Result, StdExp)) {
- S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
- << "std::experimental::coroutine_traits";
- return QualType();
- }
-
- ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
+ ClassTemplateDecl *CoroTraits = S.lookupCoroutineTraits(KwLoc, FuncLoc);
if (!CoroTraits) {
- Result.suppressDiagnostics();
- // We found something weird. Complain about the first thing we found.
- NamedDecl *Found = *Result.begin();
- S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
return QualType();
}
@@ -194,13 +187,25 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
StringRef Keyword) {
- // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
+ // 'co_await' and 'co_yield' are not permitted in unevaluated operands,
+ // such as subexpressions of \c sizeof.
+ //
+ // [expr.await]p2, emphasis added: "An await-expression shall appear only in
+ // a *potentially evaluated* expression within the compound-statement of a
+ // function-body outside of a handler [...] A context within a function where
+ // an await-expression can appear is called a suspension context of the
+ // function." And per [expr.yield]p1: "A yield-expression shall appear only
+ // within a suspension context of a function."
if (S.isUnevaluatedContext()) {
S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
return false;
}
- // Any other usage must be within a function.
+ // Per [expr.await]p2, any other usage must be within a function.
+ // FIXME: This also covers [expr.await]p2: "An await-expression shall not
+ // appear in a default argument." But the diagnostic QoI here could be
+ // improved to inform the user that default arguments specifically are not
+ // allowed.
auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
if (!FD) {
S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
@@ -231,22 +236,37 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
// Diagnose when a constructor, destructor, copy/move assignment operator,
// or the function 'main' are declared as a coroutine.
auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ // [class.ctor]p6: "A constructor shall not be a coroutine."
if (MD && isa<CXXConstructorDecl>(MD))
return DiagInvalid(DiagCtor);
+ // [class.dtor]p17: "A destructor shall not be a coroutine."
else if (MD && isa<CXXDestructorDecl>(MD))
return DiagInvalid(DiagDtor);
+ // N4499 [special]p6: "A special member function shall not be a coroutine."
+ // Per C++ [special]p1, special member functions are the "default constructor,
+ // copy constructor and copy assignment operator, move constructor and move
+ // assignment operator, and destructor."
else if (MD && MD->isCopyAssignmentOperator())
return DiagInvalid(DiagCopyAssign);
else if (MD && MD->isMoveAssignmentOperator())
return DiagInvalid(DiagMoveAssign);
+ // [basic.start.main]p3: "The function main shall not be a coroutine."
else if (FD->isMain())
return DiagInvalid(DiagMain);
// Emit a diagnostics for each of the following conditions which is not met.
+ // [expr.const]p2: "An expression e is a core constant expression unless the
+ // evaluation of e [...] would evaluate one of the following expressions:
+ // [...] an await-expression [...] a yield-expression."
if (FD->isConstexpr())
DiagInvalid(DiagConstexpr);
+ // [dcl.spec.auto]p15: "A function declared with a return type that uses a
+ // placeholder type shall not be a coroutine."
if (FD->getReturnType()->isUndeducedType())
DiagInvalid(DiagAutoRet);
+ // [dcl.fct.def.coroutine]p1: "The parameter-declaration-clause of the
+ // coroutine shall not terminate with an ellipsis that is not part of a
+ // parameter-declaration."
if (FD->isVariadic())
DiagInvalid(DiagVarargs);
@@ -360,12 +380,21 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
if (Result.isInvalid())
return ExprError();
+ // We meant exactly what we asked for. No need for typo correction.
+ if (auto *TE = dyn_cast<TypoExpr>(Result.get())) {
+ S.clearDelayedTypo(TE);
+ S.Diag(Loc, diag::err_no_member)
+ << NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
+ << Base->getSourceRange();
+ return ExprError();
+ }
+
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
+// returning await_suspend that results in a guaranteed tail call to the target
// coroutine.
static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
SourceLocation Loc) {
@@ -494,9 +523,72 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
CheckVariableDeclarationType(VD);
if (VD->isInvalidDecl())
return nullptr;
- ActOnUninitializedDecl(VD);
+
+ auto *ScopeInfo = getCurFunction();
+ // Build a list of arguments, based on the coroutine functions arguments,
+ // that will be passed to the promise type's constructor.
+ llvm::SmallVector<Expr *, 4> CtorArgExprs;
+
+ // Add implicit object parameter.
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+ ExprResult ThisExpr = ActOnCXXThis(Loc);
+ if (ThisExpr.isInvalid())
+ return nullptr;
+ ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+ if (ThisExpr.isInvalid())
+ return nullptr;
+ CtorArgExprs.push_back(ThisExpr.get());
+ }
+ }
+
+ auto &Moves = ScopeInfo->CoroutineParameterMoves;
+ for (auto *PD : FD->parameters()) {
+ if (PD->getType()->isDependentType())
+ continue;
+
+ auto RefExpr = ExprEmpty();
+ auto Move = Moves.find(PD);
+ assert(Move != Moves.end() &&
+ "Coroutine function parameter not inserted into move map");
+ // If a reference to the function parameter exists in the coroutine
+ // frame, use that reference.
+ auto *MoveDecl =
+ cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
+ RefExpr =
+ BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
+ ExprValueKind::VK_LValue, FD->getLocation());
+ if (RefExpr.isInvalid())
+ return nullptr;
+ CtorArgExprs.push_back(RefExpr.get());
+ }
+
+ // Create an initialization sequence for the promise type using the
+ // constructor arguments, wrapped in a parenthesized list expression.
+ Expr *PLE = new (Context) ParenListExpr(Context, FD->getLocation(),
+ CtorArgExprs, FD->getLocation());
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
+ InitializationKind Kind = InitializationKind::CreateForInit(
+ VD->getLocation(), /*DirectInit=*/true, PLE);
+ InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
+ /*TopLevelOfInitList=*/false,
+ /*TreatUnavailableAsInvalid=*/false);
+
+ // Attempt to initialize the promise type with the arguments.
+ // If that fails, fall back to the promise type's default constructor.
+ if (InitSeq) {
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
+ if (Result.isInvalid()) {
+ VD->setInvalidDecl();
+ } else if (Result.get()) {
+ VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
+ VD->setInitStyle(VarDecl::CallInit);
+ CheckCompleteVariableDeclaration(VD);
+ }
+ } else
+ ActOnUninitializedDecl(VD);
+
FD->addDecl(VD);
- assert(!VD->isInvalidDecl());
return VD;
}
@@ -518,6 +610,9 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
if (ScopeInfo->CoroutinePromise)
return ScopeInfo;
+ if (!S.buildCoroutineParameterMoves(Loc))
+ return nullptr;
+
ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
if (!ScopeInfo->CoroutinePromise)
return nullptr;
@@ -654,9 +749,14 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
if (E->getValueKind() == VK_RValue)
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
+ // The location of the `co_await` token cannot be used when constructing
+ // the member call expressions since it's before the location of `Expr`, which
+ // is used as the start of the member call expression.
+ SourceLocation CallLoc = E->getExprLoc();
+
// Build the await_ready, await_suspend, await_resume calls.
ReadySuspendResumeResult RSS =
- buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
+ buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E);
if (RSS.IsInvalid)
return ExprError();
@@ -861,6 +961,11 @@ CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
!Fn.CoroutinePromise ||
Fn.CoroutinePromise->getType()->isDependentType()) {
this->Body = Body;
+
+ for (auto KV : Fn.CoroutineParameterMoves)
+ this->ParamMovesVector.push_back(KV.second);
+ this->ParamMoves = this->ParamMovesVector;
+
if (!IsPromiseDependentType) {
PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
assert(PromiseRecordDecl && "Type should have already been checked");
@@ -870,7 +975,7 @@ CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
bool CoroutineStmtBuilder::buildStatements() {
assert(this->IsValid && "coroutine already invalid");
- this->IsValid = makeReturnObject() && makeParamMoves();
+ this->IsValid = makeReturnObject();
if (this->IsValid && !IsPromiseDependentType)
buildDependentStatements();
return this->IsValid;
@@ -886,12 +991,6 @@ bool CoroutineStmtBuilder::buildDependentStatements() {
return this->IsValid;
}
-bool CoroutineStmtBuilder::buildParameterMoves() {
- assert(this->IsValid && "coroutine already invalid");
- assert(this->ParamMoves.empty() && "param moves already built");
- return this->IsValid = makeParamMoves();
-}
-
bool CoroutineStmtBuilder::makePromiseStmt() {
// Form a declaration statement for the promise declaration, so that AST
// visitors can more easily find it.
@@ -990,7 +1089,12 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
- // FIXME: Add support for stateful allocators.
+ // [dcl.fct.def.coroutine]/7
+ // Lookup allocation functions using a parameter list composed of the
+ // requested size of the coroutine state being allocated, followed by
+ // the coroutine function's arguments. If a matching allocation function
+ // exists, use it. Otherwise, use an allocation function that just takes
+ // the requested size.
FunctionDecl *OperatorNew = nullptr;
FunctionDecl *OperatorDelete = nullptr;
@@ -998,10 +1102,73 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
bool PassAlignment = false;
SmallVector<Expr *, 1> PlacementArgs;
- S.FindAllocationFunctions(Loc, SourceRange(),
- /*UseGlobal*/ false, PromiseType,
+ // [dcl.fct.def.coroutine]/7
+ // "The allocation function’s name is looked up in the scope of P.
+ // [...] If the lookup finds an allocation function in the scope of P,
+ // overload resolution is performed on a function call created by assembling
+ // an argument list. The first argument is the amount of space requested,
+ // and has type std::size_t. The lvalues p1 ... pn are the succeeding
+ // arguments."
+ //
+ // ...where "p1 ... pn" are defined earlier as:
+ //
+ // [dcl.fct.def.coroutine]/3
+ // "For a coroutine f that is a non-static member function, let P1 denote the
+ // type of the implicit object parameter (13.3.1) and P2 ... Pn be the types
+ // of the function parameters; otherwise let P1 ... Pn be the types of the
+ // function parameters. Let p1 ... pn be lvalues denoting those objects."
+ if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
+ if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+ ExprResult ThisExpr = S.ActOnCXXThis(Loc);
+ if (ThisExpr.isInvalid())
+ return false;
+ ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+ if (ThisExpr.isInvalid())
+ return false;
+ PlacementArgs.push_back(ThisExpr.get());
+ }
+ }
+ for (auto *PD : FD.parameters()) {
+ if (PD->getType()->isDependentType())
+ continue;
+
+ // Build a reference to the parameter.
+ auto PDLoc = PD->getLocation();
+ ExprResult PDRefExpr =
+ S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
+ ExprValueKind::VK_LValue, PDLoc);
+ if (PDRefExpr.isInvalid())
+ return false;
+
+ PlacementArgs.push_back(PDRefExpr.get());
+ }
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
/*isArray*/ false, PassAlignment, PlacementArgs,
- OperatorNew, UnusedResult);
+ OperatorNew, UnusedResult, /*Diagnose*/ false);
+
+ // [dcl.fct.def.coroutine]/7
+ // "If no matching function is found, overload resolution is performed again
+ // on a function call created by passing just the amount of space required as
+ // an argument of type std::size_t."
+ if (!OperatorNew && !PlacementArgs.empty()) {
+ PlacementArgs.clear();
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
+ /*isArray*/ false, PassAlignment, PlacementArgs,
+ OperatorNew, UnusedResult, /*Diagnose*/ false);
+ }
+
+ // [dcl.fct.def.coroutine]/7
+ // "The allocation function’s name is looked up in the scope of P. If this
+ // lookup fails, the allocation function’s name is looked up in the global
+ // scope."
+ if (!OperatorNew) {
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Global,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
+ /*isArray*/ false, PassAlignment, PlacementArgs,
+ OperatorNew, UnusedResult);
+ }
bool IsGlobalOverload =
OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
@@ -1014,17 +1181,18 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
return false;
PlacementArgs = {StdNoThrow};
OperatorNew = nullptr;
- S.FindAllocationFunctions(Loc, SourceRange(),
- /*UseGlobal*/ true, PromiseType,
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
/*isArray*/ false, PassAlignment, PlacementArgs,
OperatorNew, UnusedResult);
}
- assert(OperatorNew && "expected definition of operator new to be found");
+ if (!OperatorNew)
+ return false;
if (RequiresNoThrowAlloc) {
const auto *FT = OperatorNew->getType()->getAs<FunctionProtoType>();
- if (!FT->isNothrow(S.Context, /*ResultIfDependent*/ false)) {
+ if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
S.Diag(OperatorNew->getLocation(),
diag::err_coroutine_promise_new_requires_nothrow)
<< OperatorNew;
@@ -1256,10 +1424,6 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
if (Res.isInvalid())
return false;
- if (GroType == FnRetType) {
- GroDecl->setNRVOVariable(true);
- }
-
S.AddInitializerToDecl(GroDecl, Res.get(),
/*DirectInit=*/false);
@@ -1283,6 +1447,8 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
+ if (cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
+ GroDecl->setNRVOVariable(true);
this->ReturnStmt = ReturnStmt.get();
return true;
@@ -1304,47 +1470,53 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
.get();
}
-
-/// \brief Build a variable declaration for move parameter.
+/// Build a variable declaration for move parameter.
static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type,
IdentifierInfo *II) {
TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc);
- VarDecl *Decl =
- VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type, TInfo, SC_None);
+ VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
+ TInfo, SC_None);
Decl->setImplicit();
return Decl;
}
-bool CoroutineStmtBuilder::makeParamMoves() {
- for (auto *paramDecl : FD.parameters()) {
- auto Ty = paramDecl->getType();
- if (Ty->isDependentType())
+// Build statements that move coroutine function parameters to the coroutine
+// frame, and store them on the function scope info.
+bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
+ assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
+ auto *FD = cast<FunctionDecl>(CurContext);
+
+ auto *ScopeInfo = getCurFunction();
+ assert(ScopeInfo->CoroutineParameterMoves.empty() &&
+ "Should not build parameter moves twice");
+
+ for (auto *PD : FD->parameters()) {
+ if (PD->getType()->isDependentType())
continue;
- // No need to copy scalars, llvm will take care of them.
- if (Ty->getAsCXXRecordDecl()) {
- ExprResult ParamRef =
- S.BuildDeclRefExpr(paramDecl, paramDecl->getType(),
- ExprValueKind::VK_LValue, Loc); // FIXME: scope?
- if (ParamRef.isInvalid())
- return false;
+ ExprResult PDRefExpr =
+ BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
+ ExprValueKind::VK_LValue, Loc); // FIXME: scope?
+ if (PDRefExpr.isInvalid())
+ return false;
- Expr *RCast = castForMoving(S, ParamRef.get());
+ Expr *CExpr = nullptr;
+ if (PD->getType()->getAsCXXRecordDecl() ||
+ PD->getType()->isRValueReferenceType())
+ CExpr = castForMoving(*this, PDRefExpr.get());
+ else
+ CExpr = PDRefExpr.get();
- auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier());
- S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true);
+ auto D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
+ AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
- // Convert decl to a statement.
- StmtResult Stmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(D), Loc, Loc);
- if (Stmt.isInvalid())
- return false;
+ // Convert decl to a statement.
+ StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc, Loc);
+ if (Stmt.isInvalid())
+ return false;
- ParamMovesVector.push_back(Stmt.get());
- }
+ ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
}
-
- // Convert to ArrayRef in CtorArgs structure that builder inherits from.
- ParamMoves = ParamMovesVector;
return true;
}
@@ -1354,3 +1526,27 @@ StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
return StmtError();
return Res;
}
+
+ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
+ SourceLocation FuncLoc) {
+ if (!StdCoroutineTraitsCache) {
+ if (auto StdExp = lookupStdExperimentalNamespace()) {
+ LookupResult Result(*this,
+ &PP.getIdentifierTable().get("coroutine_traits"),
+ FuncLoc, LookupOrdinaryName);
+ if (!LookupQualifiedName(Result, StdExp)) {
+ Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
+ << "std::experimental::coroutine_traits";
+ return nullptr;
+ }
+ if (!(StdCoroutineTraitsCache =
+ Result.getAsSingle<ClassTemplateDecl>())) {
+ Result.suppressDiagnostics();
+ NamedDecl *Found = *Result.begin();
+ Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
+ return nullptr;
+ }
+ }
+ }
+ return StdCoroutineTraitsCache;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index 0ceaf7c6d691..b92d76ad4204 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -115,7 +115,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
} // end anonymous namespace
-/// \brief Determine whether the token kind starts a simple-type-specifier.
+/// Determine whether the token kind starts a simple-type-specifier.
bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
switch (Kind) {
// FIXME: Take into account the current language when deciding whether a
@@ -148,6 +148,9 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_decltype:
return getLangOpts().CPlusPlus;
+ case tok::kw_char8_t:
+ return getLangOpts().Char8;
+
default:
break;
}
@@ -163,7 +166,7 @@ enum class UnqualifiedTypeNameLookupResult {
};
} // end anonymous namespace
-/// \brief Tries to perform unqualified lookup of the type decls in bases for
+/// Tries to perform unqualified lookup of the type decls in bases for
/// dependent class.
/// \return \a NotFound if no any decls is found, \a FoundNotType if found not a
/// type decl, \a FoundType if only type decls are found.
@@ -263,7 +266,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
-/// \brief If the identifier refers to a type name within this scope,
+/// If the identifier refers to a type name within this scope,
/// return the declaration of that type.
///
/// This routine performs ordinary name lookup of the identifier II
@@ -724,13 +727,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false,
Name, nullptr, true, TemplateResult,
MemberOfUnknownSpecialization) == TNK_Type_template) {
- TemplateName TplName = TemplateResult.get();
- Diag(IILoc, diag::err_template_missing_args)
- << (int)getTemplateNameKindForDiagnostics(TplName) << TplName;
- if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) {
- Diag(TplDecl->getLocation(), diag::note_template_decl_here)
- << TplDecl->getTemplateParameters()->getSourceRange();
- }
+ diagnoseMissingTemplateArguments(TemplateResult.get(), IILoc);
return;
}
}
@@ -763,7 +760,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
}
}
-/// \brief Determine whether the given result set contains either a type name
+/// Determine whether the given result set contains either a type name
/// or
static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus &&
@@ -1318,7 +1315,7 @@ void Sema::ActOnExitFunctionContext() {
assert(CurContext && "Popped translation unit!");
}
-/// \brief Determine whether we allow overloading of the function
+/// Determine whether we allow overloading of the function
/// PrevDecl with another declaration.
///
/// This routine determines whether overloading is possible, not
@@ -1504,7 +1501,7 @@ static void RemoveUsingDecls(LookupResult &R) {
F.done();
}
-/// \brief Check for this common pattern:
+/// Check for this common pattern:
/// @code
/// class S {
/// S(const S&); // DO NOT IMPLEMENT
@@ -1519,9 +1516,7 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
return CD->isCopyConstructor();
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- return Method->isCopyAssignmentOperator();
- return false;
+ return D->isCopyAssignmentOperator();
}
// We need this to handle
@@ -1843,7 +1838,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
}
}
-/// \brief Look for an Objective-C class in the translation unit.
+/// Look for an Objective-C class in the translation unit.
///
/// \param Id The name of the Objective-C class we're looking for. If
/// typo-correction fixes this name, the Id will be updated
@@ -1913,7 +1908,7 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
-/// \brief Looks up the declaration of "struct objc_super" and
+/// Looks up the declaration of "struct objc_super" and
/// saves it for later use in building builtin declaration of
/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such
/// pre-existing declaration exists no action takes place.
@@ -2457,6 +2452,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
AttrSpellingListIndex);
+ else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr))
+ NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(),
+ AttrSpellingListIndex);
else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr))
NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
AttrSpellingListIndex,
@@ -2495,7 +2493,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex,
UA->getGuid());
- else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
+ else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
@@ -2675,6 +2673,15 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
}
}
+ // Redeclaration adds code-seg attribute.
+ const auto *NewCSA = New->getAttr<CodeSegAttr>();
+ if (NewCSA && !Old->hasAttr<CodeSegAttr>() &&
+ !NewCSA->isImplicit() && isa<CXXMethodDecl>(New)) {
+ Diag(New->getLocation(), diag::warn_mismatched_section)
+ << 0 /*codeseg*/;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
+
if (!Old->hasAttrs())
return;
@@ -2875,7 +2882,7 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
template<typename T> static bool isExternC(T *D) { return D->isExternC(); }
static bool isExternC(VarTemplateDecl *) { return false; }
-/// \brief Check whether a redeclaration of an entity introduced by a
+/// Check whether a redeclaration of an entity introduced by a
/// using-declaration is valid, given that we know it's not an overload
/// (nor a hidden tag declaration).
template<typename ExpectedDecl>
@@ -2929,6 +2936,48 @@ static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A,
return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq);
}
+/// If necessary, adjust the semantic declaration context for a qualified
+/// declaration to name the correct inline namespace within the qualifier.
+static void adjustDeclContextForDeclaratorDecl(DeclaratorDecl *NewD,
+ DeclaratorDecl *OldD) {
+ // The only case where we need to update the DeclContext is when
+ // redeclaration lookup for a qualified name finds a declaration
+ // in an inline namespace within the context named by the qualifier:
+ //
+ // inline namespace N { int f(); }
+ // int ::f(); // Sema DC needs adjusting from :: to N::.
+ //
+ // For unqualified declarations, the semantic context *can* change
+ // along the redeclaration chain (for local extern declarations,
+ // extern "C" declarations, and friend declarations in particular).
+ if (!NewD->getQualifier())
+ return;
+
+ // NewD is probably already in the right context.
+ auto *NamedDC = NewD->getDeclContext()->getRedeclContext();
+ auto *SemaDC = OldD->getDeclContext()->getRedeclContext();
+ if (NamedDC->Equals(SemaDC))
+ return;
+
+ assert((NamedDC->InEnclosingNamespaceSetOf(SemaDC) ||
+ NewD->isInvalidDecl() || OldD->isInvalidDecl()) &&
+ "unexpected context for redeclaration");
+
+ auto *LexDC = NewD->getLexicalDeclContext();
+ auto FixSemaDC = [=](NamedDecl *D) {
+ if (!D)
+ return;
+ D->setDeclContext(SemaDC);
+ D->setLexicalDeclContext(LexDC);
+ };
+
+ FixSemaDC(NewD);
+ if (auto *FD = dyn_cast<FunctionDecl>(NewD))
+ FixSemaDC(FD->getDescribedFunctionTemplate());
+ else if (auto *VD = dyn_cast<VarDecl>(NewD))
+ FixSemaDC(VD->getDescribedVarTemplate());
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2971,6 +3020,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
if (Old->isInvalidDecl())
return true;
+ // Disallow redeclaration of some builtins.
+ if (!getASTContext().canBuiltinBeRedeclared(Old)) {
+ Diag(New->getLocation(), diag::err_builtin_redeclare) << Old->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+ << Old << Old->getType();
+ return true;
+ }
+
diag::kind PrevDiag;
SourceLocation OldLocation;
std::tie(PrevDiag, OldLocation) =
@@ -3125,7 +3182,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
if (OldTypeInfo.getNoCallerSavedRegs() !=
NewTypeInfo.getNoCallerSavedRegs()) {
if (NewTypeInfo.getNoCallerSavedRegs()) {
- AnyX86NoCallerSavedRegistersAttr *Attr =
+ AnyX86NoCallerSavedRegistersAttr *Attr =
New->getAttr<AnyX86NoCallerSavedRegistersAttr>();
Diag(New->getLocation(), diag::err_function_attribute_mismatch) << Attr;
Diag(OldLocation, diag::note_previous_declaration);
@@ -3518,7 +3575,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
return true;
}
-/// \brief Completes the merge of two function declarations that are
+/// Completes the merge of two function declarations that are
/// known to be compatible.
///
/// This routine handles the merging of attributes and other
@@ -3581,6 +3638,8 @@ 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) {
@@ -3953,6 +4012,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setPreviousDecl(Old);
if (NewTemplate)
NewTemplate->setPreviousDecl(OldTemplate);
+ adjustDeclContextForDeclaratorDecl(New, Old);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
@@ -4014,7 +4074,8 @@ void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) {
}
// Redefinition coming from different files or couldn't do better above.
- Diag(Old->getLocation(), diag::note_previous_definition);
+ if (Old->getLocation().isValid())
+ Diag(Old->getLocation(), diag::note_previous_definition);
}
/// We've just determined that \p Old and \p New both appear to be definitions
@@ -4398,10 +4459,9 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
TypeSpecType == DeclSpec::TST_interface ||
TypeSpecType == DeclSpec::TST_union ||
TypeSpecType == DeclSpec::TST_enum) {
- for (AttributeList* attrs = DS.getAttributes().getList(); attrs;
- attrs = attrs->getNext())
- Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored)
- << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
+ for (const ParsedAttr &AL : DS.getAttributes())
+ Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
+ << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
}
}
@@ -4593,12 +4653,14 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
unsigned DiagID;
if (Record->isUnion()) {
// C++ [class.union]p6:
+ // C++17 [class.union.anon]p2:
// Anonymous unions declared in a named namespace or in the
// global namespace shall be declared static.
+ DeclContext *OwnerScope = Owner->getRedeclContext();
if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
- (isa<TranslationUnitDecl>(Owner) ||
- (isa<NamespaceDecl>(Owner) &&
- cast<NamespaceDecl>(Owner)->getDeclName()))) {
+ (OwnerScope->isTranslationUnit() ||
+ (OwnerScope->isNamespace() &&
+ !cast<NamespaceDecl>(OwnerScope)->isAnonymousNamespace()))) {
Diag(Record->getLocation(), diag::err_anonymous_union_not_static)
<< FixItHint::CreateInsertion(Record->getLocation(), "static ");
@@ -4889,7 +4951,7 @@ DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
return GetNameFromUnqualifiedId(D.getName());
}
-/// \brief Retrieves the declaration name from a parsed unqualified-id.
+/// Retrieves the declaration name from a parsed unqualified-id.
DeclarationNameInfo
Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
DeclarationNameInfo NameInfo;
@@ -5176,7 +5238,7 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
return false;
}
-/// \brief Diagnose a declaration whose declarator-id has the given
+/// Diagnose a declaration whose declarator-id has the given
/// nested-name-specifier.
///
/// \param SS The nested-name-specifier of the declarator-id.
@@ -5188,10 +5250,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
///
/// \param Loc The location of the name of the entity being declared.
///
+/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus
+/// we're declaring an explicit / partial specialization / instantiation.
+///
/// \returns true if we cannot safely recover from this error, false otherwise.
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc, bool IsTemplateId) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
@@ -5218,8 +5283,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
}
// Check whether the qualifying scope encloses the scope of the original
- // declaration.
- if (!Cur->Encloses(DC)) {
+ // declaration. For a template-id, we perform the checks in
+ // CheckTemplateSpecializationScope.
+ if (!Cur->Encloses(DC) && !IsTemplateId) {
if (Cur->isRecord())
Diag(Loc, diag::err_member_qualification)
<< Name << SS.getRange();
@@ -5331,8 +5397,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
return nullptr;
}
if (!D.getDeclSpec().isFriendSpecified()) {
- if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
- Name, D.getIdentifierLoc())) {
+ if (diagnoseQualifiedDeclaration(
+ D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) {
if (DC->isRecord())
return nullptr;
@@ -5609,7 +5676,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
-/// \brief Register the given locally-scoped extern "C" declaration so
+/// Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations. We include any extern "C"
/// declaration that is not visible in the translation unit here, not just
/// function-scope declarations.
@@ -5630,7 +5697,7 @@ NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
return Result.empty() ? nullptr : *Result.begin();
}
-/// \brief Diagnose function specifiers on a declaration of an identifier that
+/// Diagnose function specifiers on a declaration of an identifier that
/// does not identify a function.
void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) {
// FIXME: We should probably indicate the identifier in question to avoid
@@ -5704,7 +5771,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo();
QualType T = TInfo->getType();
if (T->isVariablyModifiedType()) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S->getFnParent() == nullptr) {
bool SizeIsNegative;
@@ -5772,7 +5839,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
return NewTD;
}
-/// \brief Determines whether the given declaration is an out-of-scope
+/// Determines whether the given declaration is an out-of-scope
/// previous declaration.
///
/// This routine should be invoked when name lookup has found a
@@ -5941,6 +6008,31 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
<< Attr;
ND.dropAttr<NotTailCalledAttr>();
}
+
+ // Check the attributes on the function type, if any.
+ if (const auto *FD = dyn_cast<FunctionDecl>(&ND)) {
+ // Don't declare this variable in the second operand of the for-statement;
+ // GCC miscompiles that by ending its lifetime before evaluating the
+ // third operand. See gcc.gnu.org/PR86769.
+ AttributedTypeLoc ATL;
+ for (TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc();
+ (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
+ TL = ATL.getModifiedLoc()) {
+ // The [[lifetimebound]] attribute can be applied to the implicit object
+ // parameter of a non-static member function (other than a ctor or dtor)
+ // by applying it to the function type.
+ if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {
+ const auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (!MD || MD->isStatic()) {
+ S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param)
+ << !MD << ATL.getLocalSourceRange();
+ } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
+ S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor)
+ << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange();
+ }
+ }
+ }
+ }
}
static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
@@ -6148,29 +6240,21 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) {
llvm_unreachable("Unexpected context");
}
-static bool hasParsedAttr(Scope *S, const AttributeList *AttrList,
- AttributeList::Kind Kind) {
- for (const AttributeList *L = AttrList; L; L = L->getNext())
- if (L->getKind() == Kind)
- return true;
- return false;
-}
-
static bool hasParsedAttr(Scope *S, const Declarator &PD,
- AttributeList::Kind Kind) {
+ ParsedAttr::Kind Kind) {
// Check decl attributes on the DeclSpec.
- if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind))
+ if (PD.getDeclSpec().getAttributes().hasAttribute(Kind))
return true;
// Walk the declarator structure, checking decl attributes that were in a type
// position to the decl itself.
for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) {
- if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind))
+ if (PD.getTypeObject(I).getAttrs().hasAttribute(Kind))
return true;
}
// Finally, check attributes on the decl itself.
- return hasParsedAttr(S, PD.getAttributes(), Kind);
+ return PD.getAttributes().hasAttribute(Kind);
}
/// Adjust the \c DeclContext for a function or variable that might be a
@@ -6197,7 +6281,7 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
return true;
}
-/// \brief Returns true if given declaration has external C language linkage.
+/// Returns true if given declaration has external C language linkage.
static bool isDeclExternC(const Decl *D) {
if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->isExternC();
@@ -6303,6 +6387,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
D.setInvalidType();
}
}
+
+ // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not
+ // supported. OpenCL C does not support thread_local either, and
+ // also reject all other thread storage class specifiers.
+ DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
+ if (TSC != TSCS_unspecified) {
+ bool IsCXX = getLangOpts().OpenCLCPlusPlus;
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_opencl_unknown_type_specifier)
+ << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
+ << DeclSpec::getSpecifierName(TSC) << 1;
+ D.setInvalidType();
+ return nullptr;
+ }
}
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
@@ -6311,8 +6409,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// dllimport globals without explicit storage class are treated as extern. We
// have to change the storage class this early to get the right DeclContext.
if (SC == SC_None && !DC->isRecord() &&
- hasParsedAttr(S, D, AttributeList::AT_DLLImport) &&
- !hasParsedAttr(S, D, AttributeList::AT_DLLExport))
+ hasParsedAttr(S, D, ParsedAttr::AT_DLLImport) &&
+ !hasParsedAttr(S, D, ParsedAttr::AT_DLLExport))
SC = SC_Extern;
DeclContext *OriginalDC = DC;
@@ -6842,9 +6940,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
if (D.isRedeclaration() && !Previous.empty()) {
- checkDLLAttributeRedeclaration(
- *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
- IsMemberSpecialization, D.isFunctionDefinition());
+ NamedDecl *Prev = Previous.getRepresentativeDecl();
+ checkDLLAttributeRedeclaration(*this, Prev, NewVD, IsMemberSpecialization,
+ D.isFunctionDefinition());
}
if (NewTemplate) {
@@ -6887,7 +6985,7 @@ static ShadowedDeclKind computeShadowedDeclKind(const NamedDecl *ShadowedDecl,
/// variable \p VD, or an invalid source location otherwise.
static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
const VarDecl *VD) {
- for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) {
+ for (const Capture &Capture : LSI->Captures) {
if (Capture.isVariableCapture() && Capture.getVariable() == VD)
return Capture.getLocation();
}
@@ -6904,7 +7002,7 @@ static bool shouldWarnIfShadowedDecl(const DiagnosticsEngine &Diags,
return !Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc());
}
-/// \brief Return the declaration shadowed by the given variable \p D, or null
+/// Return the declaration shadowed by the given variable \p D, or null
/// if it doesn't shadow any declaration or shadowing warnings are disabled.
NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
const LookupResult &R) {
@@ -6921,14 +7019,14 @@ NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
: nullptr;
}
-/// \brief Return the declaration shadowed by the given typedef \p D, or null
+/// Return the declaration shadowed by the given typedef \p D, or null
/// if it doesn't shadow any declaration or shadowing warnings are disabled.
NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D,
const LookupResult &R) {
// Don't warn if typedef declaration is part of a class
if (D->getDeclContext()->isRecord())
return nullptr;
-
+
if (!shouldWarnIfShadowedDecl(Diags, R))
return nullptr;
@@ -6936,7 +7034,7 @@ NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D,
return isa<TypedefNameDecl>(ShadowedDecl) ? ShadowedDecl : nullptr;
}
-/// \brief Diagnose variable or built-in function shadowing. Implements
+/// Diagnose variable or built-in function shadowing. Implements
/// -Wshadow.
///
/// This method is called whenever a VarDecl is added to a "useful"
@@ -7067,7 +7165,7 @@ void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) {
}
}
-/// \brief Check -Wshadow without the advantage of a previous lookup.
+/// Check -Wshadow without the advantage of a previous lookup.
void Sema::CheckShadow(Scope *S, VarDecl *D) {
if (Diags.isIgnored(diag::warn_decl_shadow, D->getLocation()))
return;
@@ -7225,8 +7323,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (NewVD->isInvalidDecl())
return;
- TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo();
- QualType T = TInfo->getType();
+ QualType T = NewVD->getType();
// Defer checking an 'auto' type until its initializer is attached.
if (T->isUndeducedType())
@@ -7364,16 +7461,24 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
bool isVM = T->isVariablyModifiedType();
if (isVM || NewVD->hasAttr<CleanupAttr>() ||
NewVD->hasAttr<BlocksAttr>())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if ((isVM && NewVD->hasLinkage()) ||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
bool SizeIsNegative;
llvm::APSInt Oversized;
- TypeSourceInfo *FixedTInfo =
- TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
- SizeIsNegative, Oversized);
- if (!FixedTInfo && T->isVariableArrayType()) {
+ TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(
+ NewVD->getTypeSourceInfo(), Context, SizeIsNegative, Oversized);
+ QualType FixedT;
+ if (FixedTInfo && T == NewVD->getTypeSourceInfo()->getType())
+ FixedT = FixedTInfo->getType();
+ else if (FixedTInfo) {
+ // Type and type-as-written are canonically different. We need to fix up
+ // both types separately.
+ FixedT = TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+ Oversized);
+ }
+ if ((!FixedTInfo || FixedT.isNull()) && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
// FIXME: This won't give the correct result for
// int a[10][n];
@@ -7402,7 +7507,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
- NewVD->setType(FixedTInfo->getType());
+ NewVD->setType(FixedT);
NewVD->setTypeSourceInfo(FixedTInfo);
}
@@ -7437,7 +7542,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
}
-/// \brief Perform semantic checking on a newly-created variable
+/// Perform semantic checking on a newly-created variable
/// declaration.
///
/// This routine performs all of the type-checking required for a
@@ -7508,8 +7613,8 @@ struct FindOverriddenMethod {
enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
} // end anonymous namespace
-/// \brief Report an error regarding overriding, along with any relevant
-/// overriden methods.
+/// Report an error regarding overriding, along with any relevant
+/// overridden methods.
///
/// \param DiagID the primary error to report.
/// \param MD the overriding method.
@@ -7624,7 +7729,7 @@ void Sema::MarkTypoCorrectedFunctionDefinition(const NamedDecl *F) {
TypoCorrectedFunctionDefinitions.insert(F);
}
-/// \brief Generate diagnostics for an invalid function redeclaration.
+/// Generate diagnostics for an invalid function redeclaration.
///
/// This routine handles generating the diagnostic messages for an invalid
/// function redeclaration, including finding possible similar declarations
@@ -7969,6 +8074,29 @@ enum OpenCLParamType {
RecordKernelParam
};
+static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) {
+ // Size dependent types are just typedefs to normal integer types
+ // (e.g. unsigned long), so we cannot distinguish them from other typedefs to
+ // integers other than by their names.
+ StringRef SizeTypeNames[] = {"size_t", "intptr_t", "uintptr_t", "ptrdiff_t"};
+
+ // Remove typedefs one by one until we reach a typedef
+ // for a size dependent type.
+ QualType DesugaredTy = Ty;
+ do {
+ ArrayRef<StringRef> Names(SizeTypeNames);
+ auto Match =
+ std::find(Names.begin(), Names.end(), DesugaredTy.getAsString());
+ if (Names.end() != Match)
+ return true;
+
+ Ty = DesugaredTy;
+ DesugaredTy = Ty.getSingleStepDesugaredType(C);
+ } while (DesugaredTy != Ty);
+
+ return false;
+}
+
static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
@@ -7981,8 +8109,13 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
return PtrKernelParam;
}
- // TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can
- // be used as builtin types.
+ // OpenCL v1.2 s6.9.k:
+ // Arguments to kernel functions in a program cannot be declared with the
+ // built-in scalar types bool, half, size_t, ptrdiff_t, intptr_t, and
+ // uintptr_t or a struct and/or union that contain fields declared to be one
+ // of these built-in scalar types.
+ if (isOpenCLSizeDependentType(S.getASTContext(), PT))
+ return InvalidKernelParam;
if (PT->isImageType())
return PtrKernelParam;
@@ -7999,6 +8132,15 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PT->isRecordType())
return RecordKernelParam;
+ // Look into an array argument to check if it has a forbidden type.
+ if (PT->isArrayType()) {
+ const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
+ // Call ourself to check an underlying type of an array. Since the
+ // getPointeeOrArrayElementType returns an innermost type which is not an
+ // array, this recusive call only happens once.
+ return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
+ }
+
return ValidKernelParam;
}
@@ -8044,8 +8186,20 @@ static void checkIsValidOpenCLKernelParameter(
// of event_t type.
// Do not diagnose half type since it is diagnosed as invalid argument
// type for any function elsewhere.
- if (!PT->isHalfType())
+ if (!PT->isHalfType()) {
S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
+
+ // Explain what typedefs are involved.
+ const TypedefType *Typedef = nullptr;
+ while ((Typedef = PT->getAs<TypedefType>())) {
+ SourceLocation Loc = Typedef->getDecl()->getLocation();
+ // SourceLocation may be invalid for a built-in type.
+ if (Loc.isValid())
+ S.Diag(Loc, diag::note_entity_declared_at) << PT;
+ PT = Typedef->desugar();
+ }
+ }
+
D.setInvalidType();
return;
@@ -8066,9 +8220,14 @@ static void checkIsValidOpenCLKernelParameter(
SmallVector<const FieldDecl *, 4> HistoryStack;
HistoryStack.push_back(nullptr);
- const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
- VisitStack.push_back(PD);
+ // At this point we already handled everything except of a RecordType or
+ // an ArrayType of a RecordType.
+ assert((PT->isArrayType() || PT->isRecordType()) && "Unexpected type.");
+ const RecordType *RecTy =
+ PT->getPointeeOrArrayElementType()->getAs<RecordType>();
+ const RecordDecl *OrigRecDecl = RecTy->getDecl();
+ VisitStack.push_back(RecTy->getDecl());
assert(VisitStack.back() && "First decl null?");
do {
@@ -8087,7 +8246,15 @@ static void checkIsValidOpenCLKernelParameter(
const RecordDecl *RD;
if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) {
HistoryStack.push_back(Field);
- RD = Field->getType()->castAs<RecordType>()->getDecl();
+
+ QualType FieldTy = Field->getType();
+ // Other field types (known to be valid or invalid) are handled while we
+ // walk around RecordDecl::fields().
+ assert((FieldTy->isArrayType() || FieldTy->isRecordType()) &&
+ "Unexpected type.");
+ const Type *FieldRecTy = FieldTy->getPointeeOrArrayElementType();
+
+ RD = FieldRecTy->castAs<RecordType>()->getDecl();
} else {
RD = cast<RecordDecl>(Next);
}
@@ -8124,8 +8291,8 @@ static void checkIsValidOpenCLKernelParameter(
S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
}
- S.Diag(PD->getLocation(), diag::note_within_field_of_type)
- << PD->getDeclName();
+ S.Diag(OrigRecDecl->getLocation(), diag::note_within_field_of_type)
+ << OrigRecDecl->getDeclName();
// We have an error, now let's go back up through history and show where
// the offending field came from
@@ -8176,7 +8343,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool &AddToScope) {
QualType R = TInfo->getType();
- assert(R.getTypePtr()->isFunctionType());
+ assert(R->isFunctionType());
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
@@ -8655,6 +8822,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->dropAttr<SectionAttr>();
}
+ // Apply an implicit CodeSegAttr from class declspec or
+ // apply an implicit SectionAttr from #pragma code_seg if active.
+ if (!NewFD->hasAttr<CodeSegAttr>()) {
+ if (Attr *SAttr = getImplicitCodeSegOrSectionAttrForFunction(NewFD,
+ D.isFunctionDefinition())) {
+ NewFD->addAttr(SAttr);
+ }
+ }
+
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
@@ -8785,10 +8961,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (CurContext->isDependentContext() && CurContext->isRecord()
&& !isFriend) {
isDependentClassScopeExplicitSpecialization = true;
- Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
- diag::ext_function_specialization_in_class :
- diag::err_function_specialization_in_class)
- << NewFD->getDeclName();
} else if (!NewFD->isInvalidDecl() &&
CheckFunctionTemplateSpecialization(
NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
@@ -8994,19 +9166,22 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setRangeEnd(D.getSourceRange().getEnd());
if (D.isRedeclaration() && !Previous.empty()) {
- checkDLLAttributeRedeclaration(
- *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
- isMemberSpecialization || isFunctionTemplateSpecialization,
- D.isFunctionDefinition());
+ NamedDecl *Prev = Previous.getRepresentativeDecl();
+ checkDLLAttributeRedeclaration(*this, Prev, NewFD,
+ isMemberSpecialization ||
+ isFunctionTemplateSpecialization,
+ D.isFunctionDefinition());
}
if (getLangOpts().CUDA) {
IdentifierInfo *II = NewFD->getIdentifier();
- if (II && II->isStr("cudaConfigureCall") && !NewFD->isInvalidDecl() &&
+ if (II &&
+ II->isStr(getLangOpts().HIP ? "hipConfigureCall"
+ : "cudaConfigureCall") &&
+ !NewFD->isInvalidDecl() &&
NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (!R->getAs<FunctionType>()->getReturnType()->isScalarType())
Diag(NewFD->getLocation(), diag::err_config_scalar_return);
-
Context.setcudaConfigureCallDecl(NewFD);
}
@@ -9073,22 +9248,95 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// Here we have an function template explicit specialization at class scope.
- // The actually specialization will be postponed to template instatiation
+ // The actual specialization will be postponed to template instatiation
// time via the ClassScopeFunctionSpecializationDecl node.
if (isDependentClassScopeExplicitSpecialization) {
ClassScopeFunctionSpecializationDecl *NewSpec =
ClassScopeFunctionSpecializationDecl::Create(
- Context, CurContext, SourceLocation(),
+ Context, CurContext, NewFD->getLocation(),
cast<CXXMethodDecl>(NewFD),
HasExplicitTemplateArgs, TemplateArgs);
CurContext->addDecl(NewSpec);
AddToScope = false;
}
+ // Diagnose availability attributes. Availability cannot be used on functions
+ // that are run during load/unload.
+ if (const auto *attr = NewFD->getAttr<AvailabilityAttr>()) {
+ if (NewFD->hasAttr<ConstructorAttr>()) {
+ Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
+ << 1;
+ NewFD->dropAttr<AvailabilityAttr>();
+ }
+ if (NewFD->hasAttr<DestructorAttr>()) {
+ Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
+ << 2;
+ NewFD->dropAttr<AvailabilityAttr>();
+ }
+ }
+
return NewFD;
}
-/// \brief Checks if the new declaration declared in dependent context must be
+/// Return a CodeSegAttr from a containing class. The Microsoft docs say
+/// when __declspec(code_seg) "is applied to a class, all member functions of
+/// the class and nested classes -- this includes compiler-generated special
+/// member functions -- are put in the specified segment."
+/// The actual behavior is a little more complicated. The Microsoft compiler
+/// won't check outer classes if there is an active value from #pragma code_seg.
+/// The CodeSeg is always applied from the direct parent but only from outer
+/// classes when the #pragma code_seg stack is empty. See:
+/// https://reviews.llvm.org/D22931, the Microsoft feedback page is no longer
+/// available since MS has removed the page.
+static Attr *getImplicitCodeSegAttrFromClass(Sema &S, const FunctionDecl *FD) {
+ const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+ if (!Method)
+ return nullptr;
+ const CXXRecordDecl *Parent = Method->getParent();
+ if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) {
+ Attr *NewAttr = SAttr->clone(S.getASTContext());
+ NewAttr->setImplicit(true);
+ return NewAttr;
+ }
+
+ // The Microsoft compiler won't check outer classes for the CodeSeg
+ // when the #pragma code_seg stack is active.
+ if (S.CodeSegStack.CurrentValue)
+ return nullptr;
+
+ while ((Parent = dyn_cast<CXXRecordDecl>(Parent->getParent()))) {
+ if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) {
+ Attr *NewAttr = SAttr->clone(S.getASTContext());
+ NewAttr->setImplicit(true);
+ return NewAttr;
+ }
+ }
+ return nullptr;
+}
+
+/// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a
+/// containing class. Otherwise it will return implicit SectionAttr if the
+/// function is a definition and there is an active value on CodeSegStack
+/// (from the current #pragma code-seg value).
+///
+/// \param FD Function being declared.
+/// \param IsDefinition Whether it is a definition or just a declarartion.
+/// \returns A CodeSegAttr or SectionAttr to apply to the function or
+/// nullptr if no attribute should be added.
+Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD,
+ bool IsDefinition) {
+ if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD))
+ return A;
+ if (!FD->hasAttr<SectionAttr>() && IsDefinition &&
+ CodeSegStack.CurrentValue) {
+ return SectionAttr::CreateImplicit(getASTContext(),
+ SectionAttr::Declspec_allocate,
+ CodeSegStack.CurrentValue->getString(),
+ CodeSegStack.CurrentPragmaLocation);
+ }
+ return nullptr;
+}
+/// Checks if the new declaration declared in dependent context must be
/// put in the same redeclaration chain as the specified declaration.
///
/// \param D Declaration that is checked.
@@ -9114,7 +9362,524 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) {
D->getFriendObjectKind() != Decl::FOK_None);
}
-/// \brief Perform semantic checking of a new function declaration.
+namespace MultiVersioning {
+enum Type { None, Target, CPUSpecific, CPUDispatch};
+} // MultiVersionType
+
+static MultiVersioning::Type
+getMultiVersionType(const FunctionDecl *FD) {
+ if (FD->hasAttr<TargetAttr>())
+ return MultiVersioning::Target;
+ if (FD->hasAttr<CPUDispatchAttr>())
+ return MultiVersioning::CPUDispatch;
+ if (FD->hasAttr<CPUSpecificAttr>())
+ return MultiVersioning::CPUSpecific;
+ return MultiVersioning::None;
+}
+/// Check the target attribute of the function for MultiVersion
+/// validity.
+///
+/// Returns true if there was an error, false otherwise.
+static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
+ const auto *TA = FD->getAttr<TargetAttr>();
+ assert(TA && "MultiVersion Candidate requires a target attribute");
+ TargetAttr::ParsedTargetAttr ParseInfo = TA->parse();
+ const TargetInfo &TargetInfo = S.Context.getTargetInfo();
+ enum ErrType { Feature = 0, Architecture = 1 };
+
+ if (!ParseInfo.Architecture.empty() &&
+ !TargetInfo.validateCpuIs(ParseInfo.Architecture)) {
+ S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
+ << Architecture << ParseInfo.Architecture;
+ return true;
+ }
+
+ for (const auto &Feat : ParseInfo.Features) {
+ auto BareFeat = StringRef{Feat}.substr(1);
+ if (Feat[0] == '-') {
+ S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
+ << Feature << ("no-" + BareFeat).str();
+ return true;
+ }
+
+ if (!TargetInfo.validateCpuSupports(BareFeat) ||
+ !TargetInfo.isValidFeatureName(BareFeat)) {
+ S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
+ << Feature << BareFeat;
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
+ const FunctionDecl *NewFD,
+ bool CausesMV,
+ MultiVersioning::Type MVType) {
+ enum DoesntSupport {
+ FuncTemplates = 0,
+ VirtFuncs = 1,
+ DeducedReturn = 2,
+ Constructors = 3,
+ Destructors = 4,
+ DeletedFuncs = 5,
+ DefaultedFuncs = 6,
+ ConstexprFuncs = 7,
+ };
+ enum Different {
+ CallingConv = 0,
+ ReturnType = 1,
+ ConstexprSpec = 2,
+ InlineSpec = 3,
+ StorageClass = 4,
+ Linkage = 5
+ };
+
+ bool IsCPUSpecificCPUDispatchMVType =
+ MVType == MultiVersioning::CPUDispatch ||
+ MVType == MultiVersioning::CPUSpecific;
+
+ if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) {
+ S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto);
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ }
+
+ if (!NewFD->getType()->getAs<FunctionProtoType>())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto);
+
+ if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
+ if (OldFD)
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ // For now, disallow all other attributes. These should be opt-in, but
+ // an analysis of all of them is a future FIXME.
+ if (CausesMV && OldFD &&
+ std::distance(OldFD->attr_begin(), OldFD->attr_end()) != 1) {
+ S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ }
+
+ if (std::distance(NewFD->attr_begin(), NewFD->attr_end()) != 1)
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+
+ if (NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << FuncTemplates;
+
+ if (const auto *NewCXXFD = dyn_cast<CXXMethodDecl>(NewFD)) {
+ if (NewCXXFD->isVirtual())
+ return S.Diag(NewCXXFD->getLocation(),
+ diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << VirtFuncs;
+
+ if (const auto *NewCXXCtor = dyn_cast<CXXConstructorDecl>(NewFD))
+ return S.Diag(NewCXXCtor->getLocation(),
+ diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << Constructors;
+
+ if (const auto *NewCXXDtor = dyn_cast<CXXDestructorDecl>(NewFD))
+ return S.Diag(NewCXXDtor->getLocation(),
+ diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << Destructors;
+ }
+
+ if (NewFD->isDeleted())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << DeletedFuncs;
+
+ if (NewFD->isDefaulted())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs;
+
+ if (NewFD->isConstexpr() && (MVType == MultiVersioning::CPUDispatch ||
+ MVType == MultiVersioning::CPUSpecific))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << ConstexprFuncs;
+
+ QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType());
+ const auto *NewType = cast<FunctionType>(NewQType);
+ QualType NewReturnType = NewType->getReturnType();
+
+ if (NewReturnType->isUndeducedType())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << DeducedReturn;
+
+ // Only allow transition to MultiVersion if it hasn't been used.
+ if (OldFD && CausesMV && OldFD->isUsed(false))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
+
+ // Ensure the return type is identical.
+ if (OldFD) {
+ QualType OldQType = S.getASTContext().getCanonicalType(OldFD->getType());
+ const auto *OldType = cast<FunctionType>(OldQType);
+ FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
+ FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+
+ if (OldTypeInfo.getCC() != NewTypeInfo.getCC())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << CallingConv;
+
+ QualType OldReturnType = OldType->getReturnType();
+
+ if (OldReturnType != NewReturnType)
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << ReturnType;
+
+ if (OldFD->isConstexpr() != NewFD->isConstexpr())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << ConstexprSpec;
+
+ if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << InlineSpec;
+
+ if (OldFD->getStorageClass() != NewFD->getStorageClass())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << StorageClass;
+
+ if (OldFD->isExternC() != NewFD->isExternC())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << Linkage;
+
+ if (S.CheckEquivalentExceptionSpec(
+ OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
+ NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation()))
+ return true;
+ }
+ return false;
+}
+
+/// Check the validity of a multiversion function declaration that is the
+/// first of its kind. Also sets the multiversion'ness' of the function itself.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+///
+/// Returns true if there was an error, false otherwise.
+static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD,
+ MultiVersioning::Type MVType,
+ const TargetAttr *TA,
+ const CPUDispatchAttr *CPUDisp,
+ const CPUSpecificAttr *CPUSpec) {
+ assert(MVType != MultiVersioning::None &&
+ "Function lacks multiversion attribute");
+
+ // Target only causes MV if it is default, otherwise this is a normal
+ // function.
+ if (MVType == MultiVersioning::Target && !TA->isDefaultVersion())
+ return false;
+
+ if (MVType == MultiVersioning::Target && CheckMultiVersionValue(S, FD)) {
+ FD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionAdditionalRules(S, nullptr, FD, true, MVType)) {
+ FD->setInvalidDecl();
+ return true;
+ }
+
+ FD->setIsMultiVersion();
+ return false;
+}
+
+static bool CheckTargetCausesMultiVersioning(
+ Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA,
+ bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious,
+ LookupResult &Previous) {
+ const auto *OldTA = OldFD->getAttr<TargetAttr>();
+ TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse();
+ // Sort order doesn't matter, it just needs to be consistent.
+ llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end());
+
+ // If the old decl is NOT MultiVersioned yet, and we don't cause that
+ // to change, this is a simple redeclaration.
+ if (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr())
+ return false;
+
+ // Otherwise, this decl causes MultiVersioning.
+ if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true,
+ MultiVersioning::Target)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionValue(S, NewFD)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionValue(S, OldFD)) {
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ TargetAttr::ParsedTargetAttr OldParsed =
+ OldTA->parse(std::less<std::string>());
+
+ if (OldParsed == NewParsed) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate);
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ for (const auto *FD : OldFD->redecls()) {
+ const auto *CurTA = FD->getAttr<TargetAttr>();
+ if (!CurTA || CurTA->isInherited()) {
+ S.Diag(FD->getLocation(), diag::err_multiversion_required_in_redecl)
+ << 0;
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ }
+
+ OldFD->setIsMultiVersion();
+ NewFD->setIsMultiVersion();
+ Redeclaration = false;
+ MergeTypeWithPrevious = false;
+ OldDecl = nullptr;
+ Previous.clear();
+ return false;
+}
+
+/// Check the validity of a new function declaration being added to an existing
+/// multiversioned declaration collection.
+static bool CheckMultiVersionAdditionalDecl(
+ Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD,
+ MultiVersioning::Type NewMVType, const TargetAttr *NewTA,
+ const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec,
+ bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious,
+ LookupResult &Previous) {
+
+ MultiVersioning::Type OldMVType = getMultiVersionType(OldFD);
+ // Disallow mixing of multiversioning types.
+ if ((OldMVType == MultiVersioning::Target &&
+ NewMVType != MultiVersioning::Target) ||
+ (NewMVType == MultiVersioning::Target &&
+ OldMVType != MultiVersioning::Target)) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ TargetAttr::ParsedTargetAttr NewParsed;
+ if (NewTA) {
+ NewParsed = NewTA->parse();
+ llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end());
+ }
+
+ bool UseMemberUsingDeclRules =
+ S.CurContext->isRecord() && !NewFD->getFriendObjectKind();
+
+ // Next, check ALL non-overloads to see if this is a redeclaration of a
+ // previous member of the MultiVersion set.
+ for (NamedDecl *ND : Previous) {
+ FunctionDecl *CurFD = ND->getAsFunction();
+ if (!CurFD)
+ continue;
+ if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules))
+ continue;
+
+ if (NewMVType == MultiVersioning::Target) {
+ const auto *CurTA = CurFD->getAttr<TargetAttr>();
+ if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) {
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = ND;
+ return false;
+ }
+
+ TargetAttr::ParsedTargetAttr CurParsed =
+ CurTA->parse(std::less<std::string>());
+ if (CurParsed == NewParsed) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate);
+ S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ } else {
+ const auto *CurCPUSpec = CurFD->getAttr<CPUSpecificAttr>();
+ const auto *CurCPUDisp = CurFD->getAttr<CPUDispatchAttr>();
+ // Handle CPUDispatch/CPUSpecific versions.
+ // Only 1 CPUDispatch function is allowed, this will make it go through
+ // the redeclaration errors.
+ if (NewMVType == MultiVersioning::CPUDispatch &&
+ CurFD->hasAttr<CPUDispatchAttr>()) {
+ if (CurCPUDisp->cpus_size() == NewCPUDisp->cpus_size() &&
+ std::equal(
+ CurCPUDisp->cpus_begin(), CurCPUDisp->cpus_end(),
+ NewCPUDisp->cpus_begin(),
+ [](const IdentifierInfo *Cur, const IdentifierInfo *New) {
+ return Cur->getName() == New->getName();
+ })) {
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = ND;
+ return false;
+ }
+
+ // If the declarations don't match, this is an error condition.
+ S.Diag(NewFD->getLocation(), diag::err_cpu_dispatch_mismatch);
+ S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ if (NewMVType == MultiVersioning::CPUSpecific && CurCPUSpec) {
+
+ if (CurCPUSpec->cpus_size() == NewCPUSpec->cpus_size() &&
+ std::equal(
+ CurCPUSpec->cpus_begin(), CurCPUSpec->cpus_end(),
+ NewCPUSpec->cpus_begin(),
+ [](const IdentifierInfo *Cur, const IdentifierInfo *New) {
+ return Cur->getName() == New->getName();
+ })) {
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = ND;
+ return false;
+ }
+
+ // Only 1 version of CPUSpecific is allowed for each CPU.
+ for (const IdentifierInfo *CurII : CurCPUSpec->cpus()) {
+ for (const IdentifierInfo *NewII : NewCPUSpec->cpus()) {
+ if (CurII == NewII) {
+ S.Diag(NewFD->getLocation(), diag::err_cpu_specific_multiple_defs)
+ << NewII;
+ S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ }
+ }
+ }
+ // If the two decls aren't the same MVType, there is no possible error
+ // condition.
+ }
+ }
+
+ // Else, this is simply a non-redecl case. Checking the 'value' is only
+ // necessary in the Target case, since The CPUSpecific/Dispatch cases are
+ // handled in the attribute adding step.
+ if (NewMVType == MultiVersioning::Target &&
+ CheckMultiVersionValue(S, NewFD)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false, NewMVType)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ NewFD->setIsMultiVersion();
+ Redeclaration = false;
+ MergeTypeWithPrevious = false;
+ OldDecl = nullptr;
+ Previous.clear();
+ return false;
+}
+
+
+/// Check the validity of a mulitversion function declaration.
+/// Also sets the multiversion'ness' of the function itself.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+///
+/// Returns true if there was an error, false otherwise.
+static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
+ bool &Redeclaration, NamedDecl *&OldDecl,
+ bool &MergeTypeWithPrevious,
+ LookupResult &Previous) {
+ const auto *NewTA = NewFD->getAttr<TargetAttr>();
+ const auto *NewCPUDisp = NewFD->getAttr<CPUDispatchAttr>();
+ const auto *NewCPUSpec = NewFD->getAttr<CPUSpecificAttr>();
+
+ // Mixing Multiversioning types is prohibited.
+ if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) ||
+ (NewCPUDisp && NewCPUSpec)) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ MultiVersioning::Type MVType = getMultiVersionType(NewFD);
+
+ // Main isn't allowed to become a multiversion function, however it IS
+ // permitted to have 'main' be marked with the 'target' optimization hint.
+ if (NewFD->isMain()) {
+ if ((MVType == MultiVersioning::Target && NewTA->isDefaultVersion()) ||
+ MVType == MultiVersioning::CPUDispatch ||
+ MVType == MultiVersioning::CPUSpecific) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ return false;
+ }
+
+ if (!OldDecl || !OldDecl->getAsFunction() ||
+ OldDecl->getDeclContext()->getRedeclContext() !=
+ NewFD->getDeclContext()->getRedeclContext()) {
+ // If there's no previous declaration, AND this isn't attempting to cause
+ // multiversioning, this isn't an error condition.
+ if (MVType == MultiVersioning::None)
+ return false;
+ return CheckMultiVersionFirstFunction(S, NewFD, MVType, NewTA, NewCPUDisp,
+ NewCPUSpec);
+ }
+
+ FunctionDecl *OldFD = OldDecl->getAsFunction();
+
+ if (!OldFD->isMultiVersion() && MVType == MultiVersioning::None)
+ return false;
+
+ if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl)
+ << (getMultiVersionType(OldFD) != MultiVersioning::Target);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ // Handle the target potentially causes multiversioning case.
+ if (!OldFD->isMultiVersion() && MVType == MultiVersioning::Target)
+ return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA,
+ Redeclaration, OldDecl,
+ MergeTypeWithPrevious, Previous);
+ // Previous declarations lack CPUDispatch/CPUSpecific.
+ if (!OldFD->isMultiVersion()) {
+ S.Diag(OldFD->getLocation(), diag::err_multiversion_required_in_redecl)
+ << 1;
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ // At this point, we have a multiversion function decl (in OldFD) AND an
+ // appropriate attribute in the current function decl. Resolve that these are
+ // still compatible with previous declarations.
+ return CheckMultiVersionAdditionalDecl(
+ S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, Redeclaration,
+ OldDecl, MergeTypeWithPrevious, Previous);
+}
+
+/// Perform semantic checking of a new function declaration.
///
/// Performs semantic analysis of the new function declaration
/// NewFD. This routine performs all semantic checking that does not
@@ -9201,6 +9966,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
+ if (CheckMultiVersionFunction(*this, NewFD, Redeclaration, OldDecl,
+ MergeTypeWithPrevious, Previous))
+ return Redeclaration;
+
// C++11 [dcl.constexpr]p8:
// A constexpr specifier for a non-static member function that is not
// a constructor declares that member function to be const.
@@ -9250,15 +10019,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Previous.clear();
Previous.addDecl(OldDecl);
- if (FunctionTemplateDecl *OldTemplateDecl
- = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
- NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ if (FunctionTemplateDecl *OldTemplateDecl =
+ dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+ auto *OldFD = OldTemplateDecl->getTemplatedDecl();
+ NewFD->setPreviousDeclaration(OldFD);
+ adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
FunctionTemplateDecl *NewTemplateDecl
= NewFD->getDescribedFunctionTemplate();
assert(NewTemplateDecl && "Template/non-template mismatch");
- if (CXXMethodDecl *Method
- = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
- Method->setAccess(OldTemplateDecl->getAccess());
+ if (NewFD->isCXXClassMember()) {
+ NewFD->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
}
@@ -9270,22 +10040,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
assert(OldTemplateDecl->isMemberSpecialization());
// Explicit specializations of a member template do not inherit deleted
// status from the parent member template that they are specializing.
- if (OldTemplateDecl->getTemplatedDecl()->isDeleted()) {
- FunctionDecl *const OldTemplatedDecl =
- OldTemplateDecl->getTemplatedDecl();
+ if (OldFD->isDeleted()) {
// FIXME: This assert will not hold in the presence of modules.
- assert(OldTemplatedDecl->getCanonicalDecl() == OldTemplatedDecl);
+ assert(OldFD->getCanonicalDecl() == OldFD);
// FIXME: We need an update record for this AST mutation.
- OldTemplatedDecl->setDeletedAsWritten(false);
+ OldFD->setDeletedAsWritten(false);
}
}
} else {
if (shouldLinkDependentDeclWithPrevious(NewFD, OldDecl)) {
+ auto *OldFD = cast<FunctionDecl>(OldDecl);
// This needs to happen first so that 'inline' propagates.
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
- if (isa<CXXMethodDecl>(NewFD))
- NewFD->setAccess(OldDecl->getAccess());
+ NewFD->setPreviousDeclaration(OldFD);
+ adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
+ if (NewFD->isCXXClassMember())
+ NewFD->setAccess(OldFD->getAccess());
}
}
} else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks &&
@@ -9440,7 +10210,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
else if (auto *MPT = T->getAs<MemberPointerType>())
T = MPT->getPointeeType();
if (auto *FPT = T->getAs<FunctionProtoType>())
- if (FPT->isNothrow(Context))
+ if (FPT->isNothrow())
return true;
return false;
};
@@ -9951,7 +10721,7 @@ namespace {
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
- << DRE->getNameInfo().getName()
+ << DRE->getDecl()
<< OrigDecl->getLocation()
<< DRE->getSourceRange());
}
@@ -10011,12 +10781,22 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
// C++11 [dcl.spec.auto]p3
if (!Init) {
assert(VDecl && "no init for init capture deduction?");
- Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
- << VDecl->getDeclName() << Type;
- return QualType();
+
+ // Except for class argument deduction, and then for an initializing
+ // declaration only, i.e. no static at class scope or extern.
+ if (!isa<DeducedTemplateSpecializationType>(Deduced) ||
+ VDecl->hasExternalStorage() ||
+ VDecl->isStaticDataMember()) {
+ Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
+ << VDecl->getDeclName() << Type;
+ return QualType();
+ }
}
- ArrayRef<Expr*> DeduceInits = Init;
+ ArrayRef<Expr*> DeduceInits;
+ if (Init)
+ DeduceInits = Init;
+
if (DirectInit) {
if (auto *PL = dyn_cast_or_null<ParenListExpr>(Init))
DeduceInits = PL->exprs();
@@ -10027,7 +10807,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
InitializationKind Kind = InitializationKind::CreateForInit(
VDecl->getLocation(), DirectInit, Init);
- // FIXME: Initialization should not be taking a mutable list of inits.
+ // FIXME: Initialization should not be taking a mutable list of inits.
SmallVector<Expr*, 8> InitsCopy(DeduceInits.begin(), DeduceInits.end());
return DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind,
InitsCopy);
@@ -10260,7 +11040,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
}
if (VDecl->hasLocalStorage())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) {
VDecl->setInvalidDecl();
@@ -10360,11 +11140,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// we do not warn to warn spuriously when 'x' and 'y' are on separate
// paths through the function. This should be revisited if
// -Wrepeated-use-of-weak is made flow-sensitive.
- if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
- VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) &&
- !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
- Init->getLocStart()))
- getCurFunction()->markSafeWeakUse(Init);
+ if (FunctionScopeInfo *FSI = getCurFunction())
+ if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
+ VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
+ Init->getLocStart()))
+ FSI->markSafeWeakUse(Init);
}
// The initialization is usually a full-expression.
@@ -10471,6 +11252,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
; // Nothing to check.
else if (Init->isIntegerConstantExpr(Context, &Loc))
; // Ok, it's an ICE!
+ else if (Init->getType()->isScopedEnumeralType() &&
+ Init->isCXX11ConstantExpr(Context))
+ ; // Ok, it is a scoped-enum constant expression.
else if (Init->isEvaluatable(Context)) {
// If we can constant fold the initializer through heroics, accept it,
// but report this as a use of an extension for -pedantic.
@@ -10521,7 +11305,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
} else if (VDecl->isFileVarDecl()) {
// In C, extern is typically used to avoid tentative definitions when
// declaring variables in headers, but adding an intializer makes it a
- // defintion. This is somewhat confusing, so GCC and Clang both warn on it.
+ // definition. This is somewhat confusing, so GCC and Clang both warn on it.
// In C++, extern is often used to give implictly static const variables
// external linkage, so don't warn in that case. If selectany is present,
// this might be header code intended for C and C++ inclusion, so apply the
@@ -10794,11 +11578,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (const RecordType *Record
= Context.getBaseElementType(Type)->getAs<RecordType>()) {
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
- // Mark the function for further checking even if the looser rules of
- // C++11 do not require such checks, so that we can diagnose
- // incompatibilities with C++98.
+ // Mark the function (if we're in one) for further checking even if the
+ // looser rules of C++11 do not require such checks, so that we can
+ // diagnose incompatibilities with C++98.
if (!CXXRecord->isPOD())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
}
}
@@ -10898,8 +11682,8 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
D.takeAttributes(Attrs, AttrEnd);
ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory());
- D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false),
- EmptyAttrs, IdentLoc);
+ D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/ false),
+ IdentLoc);
Decl *Var = ActOnDeclarator(S, D);
cast<VarDecl>(Var)->setCXXForRangeDecl(true);
FinalizeDeclaration(Var);
@@ -10934,11 +11718,15 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
case Qualifiers::OCL_Weak:
case Qualifiers::OCL_Strong:
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
break;
}
}
+ if (var->hasLocalStorage() &&
+ var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
+ setFunctionHasBranchProtectedScope();
+
// Warn about externally-visible variables being defined without a
// prior declaration. We only want to do this for global
// declarations, but we also specifically need to avoid doing it for
@@ -11142,7 +11930,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Context.addModuleInitializer(ModuleScopes.back().Module, var);
}
-/// \brief Determines if a variable's alignment is dependent.
+/// Determines if a variable's alignment is dependent.
static bool hasDependentAlignment(VarDecl *VD) {
if (VD->getType()->isDependentType())
return true;
@@ -11213,14 +12001,25 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
NewAttr->setInherited(true);
VD->addAttr(NewAttr);
}
- // CUDA E.2.9.4: Within the body of a __device__ or __global__
- // function, only __shared__ variables may be declared with
- // static storage class.
- if (getLangOpts().CUDA && !VD->hasAttr<CUDASharedAttr>() &&
- CUDADiagIfDeviceCode(VD->getLocation(),
- diag::err_device_static_local_var)
- << CurrentCUDATarget())
- VD->setInvalidDecl();
+ // CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__
+ // function, only __shared__ variables or variables without any device
+ // memory qualifiers may be declared with static storage class.
+ // Note: It is unclear how a function-scope non-const static variable
+ // without device memory qualifier is implemented, therefore only static
+ // const variable without device memory qualifier is allowed.
+ [&]() {
+ if (!getLangOpts().CUDA)
+ return;
+ if (VD->hasAttr<CUDASharedAttr>())
+ return;
+ if (VD->getType().isConstQualified() &&
+ !(VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
+ return;
+ if (CUDADiagIfDeviceCode(VD->getLocation(),
+ diag::err_device_static_local_var)
+ << CurrentCUDATarget())
+ VD->setInvalidDecl();
+ }();
}
}
@@ -11229,58 +12028,8 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
// 7.5). We must also apply the same checks to all __shared__
// variables whether they are local or not. CUDA also allows
// constant initializers for __constant__ and __device__ variables.
- if (getLangOpts().CUDA) {
- const Expr *Init = VD->getInit();
- if (Init && VD->hasGlobalStorage()) {
- if (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() ||
- VD->hasAttr<CUDASharedAttr>()) {
- assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>());
- bool AllowedInit = false;
- if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
- AllowedInit =
- isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
- // We'll allow constant initializers even if it's a non-empty
- // constructor according to CUDA rules. This deviates from NVCC,
- // but allows us to handle things like constexpr constructors.
- if (!AllowedInit &&
- (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
- AllowedInit = VD->getInit()->isConstantInitializer(
- Context, VD->getType()->isReferenceType());
-
- // Also make sure that destructor, if there is one, is empty.
- if (AllowedInit)
- if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl())
- AllowedInit =
- isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor());
-
- if (!AllowedInit) {
- Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>()
- ? diag::err_shared_var_init
- : diag::err_dynamic_var_init)
- << Init->getSourceRange();
- VD->setInvalidDecl();
- }
- } else {
- // This is a host-side global variable. Check that the initializer is
- // callable from the host side.
- const FunctionDecl *InitFn = nullptr;
- if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) {
- InitFn = CE->getConstructor();
- } else if (const CallExpr *CE = dyn_cast<CallExpr>(Init)) {
- InitFn = CE->getDirectCallee();
- }
- if (InitFn) {
- CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn);
- if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) {
- Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
- << InitFnTarget << InitFn;
- Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
- VD->setInvalidDecl();
- }
- }
- }
- }
- }
+ if (getLangOpts().CUDA)
+ checkAllowedCUDAInitializer(VD);
// Grab the dllimport or dllexport attribute off of the VarDecl.
const InheritableAttr *DLLAttr = getDLLAttr(VD);
@@ -11659,7 +12408,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
return New;
}
-/// \brief Synthesizes a variable for a parameter arising from a
+/// Synthesizes a variable for a parameter arising from a
/// typedef.
ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
@@ -11896,9 +12645,45 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
const FunctionDecl *EffectiveDefinition,
SkipBodyInfo *SkipBody) {
const FunctionDecl *Definition = EffectiveDefinition;
+ if (!Definition && !FD->isDefined(Definition) && !FD->isCXXClassMember()) {
+ // If this is a friend function defined in a class template, it does not
+ // have a body until it is used, nevertheless it is a definition, see
+ // [temp.inst]p2:
+ //
+ // ... for the purpose of determining whether an instantiated redeclaration
+ // is valid according to [basic.def.odr] and [class.mem], a declaration that
+ // corresponds to a definition in the template is considered to be a
+ // definition.
+ //
+ // The following code must produce redefinition error:
+ //
+ // template<typename T> struct C20 { friend void func_20() {} };
+ // C20<int> c20i;
+ // void func_20() {}
+ //
+ for (auto I : FD->redecls()) {
+ if (I != FD && !I->isInvalidDecl() &&
+ I->getFriendObjectKind() != Decl::FOK_None) {
+ if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) {
+ if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) {
+ // A merged copy of the same function, instantiated as a member of
+ // the same class, is OK.
+ if (declaresSameEntity(OrigFD, Original) &&
+ declaresSameEntity(cast<Decl>(I->getLexicalDeclContext()),
+ cast<Decl>(FD->getLexicalDeclContext())))
+ continue;
+ }
+
+ if (Original->isThisDeclarationADefinition()) {
+ Definition = I;
+ break;
+ }
+ }
+ }
+ }
+ }
if (!Definition)
- if (!FD->isDefined(Definition))
- return;
+ return;
if (canRedefineFunction(Definition, getLangOpts()))
return;
@@ -11983,8 +12768,13 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
SkipBodyInfo *SkipBody) {
- if (!D)
+ if (!D) {
+ // Parsing the function declaration failed in some way. Push on a fake scope
+ // anyway so we can try to parse the function body.
+ PushFunctionScope();
return D;
+ }
+
FunctionDecl *FD = nullptr;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
@@ -12121,7 +12911,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
return D;
}
-/// \brief Given the set of return statements within a function body,
+/// Given the set of return statements within a function body,
/// compute the variables that are subject to the named return value
/// optimization.
///
@@ -12174,9 +12964,15 @@ bool Sema::canSkipFunctionBody(Decl *D) {
// rest of the file.
// We cannot skip the body of a function with an undeduced return type,
// because any callers of that function need to know the type.
- if (const FunctionDecl *FD = D->getAsFunction())
- if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType())
+ if (const FunctionDecl *FD = D->getAsFunction()) {
+ if (FD->isConstexpr())
return false;
+ // We can't simply call Type::isUndeducedType here, because inside template
+ // auto can be deduced to a dependent type, which is not considered
+ // "undeduced".
+ if (FD->getReturnType()->getContainedDeducedType())
+ return false;
+ }
return Consumer.shouldSkipFunctionBody(D);
}
@@ -12272,8 +13068,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// Try to apply the named return value optimization. We have to check
// if we can do this here because lambdas keep return statements around
// to deduce an implicit return type.
- if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
- !FD->isDependentContext())
+ if (FD->getReturnType()->isRecordType() &&
+ (!getLangOpts().CPlusPlus || !FD->isDependentContext()))
computeNRVO(Body, getCurFunction());
}
@@ -12316,6 +13112,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
}
+ // Warn on CPUDispatch with an actual body.
+ if (FD->isMultiVersion() && FD->hasAttr<CPUDispatchAttr>() && Body)
+ if (const auto *CmpndBody = dyn_cast<CompoundStmt>(Body))
+ if (!CmpndBody->body_empty())
+ Diag(CmpndBody->body_front()->getLocStart(),
+ diag::warn_dispatch_body_ignored);
+
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
const CXXMethodDecl *KeyFunction;
if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) &&
@@ -12393,6 +13196,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
} else {
+ // Parsing the function declaration failed in some way. Pop the fake scope
+ // we pushed on.
+ PopFunctionScopeInfo(ActivePolicy, dcl);
return nullptr;
}
@@ -12498,7 +13304,7 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
// Always attach attributes to the underlying decl.
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
- ProcessDeclAttributeList(S, D, Attrs.getList());
+ ProcessDeclAttributeList(S, D, Attrs);
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
if (Method->isStatic())
@@ -12600,18 +13406,16 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*ConstQualifierLoc=*/NoLoc,
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc,
- EST_None,
+ /*MutableLoc=*/NoLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- Loc, Loc, D),
- DS.getAttributes(),
- SourceLocation());
+ /*DeclsInPrototype=*/None, Loc,
+ Loc, D),
+ std::move(DS.getAttributes()), SourceLocation());
D.SetIdentifier(&II, Loc);
// Insert this function into the enclosing block scope.
@@ -12623,7 +13427,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
return FD;
}
-/// \brief Adds any function attributes that we know a priori based on
+/// Adds any function attributes that we know a priori based on
/// the declaration of this function.
///
/// These attributes can apply both to implicitly-declared builtins
@@ -12673,11 +13477,11 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
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
+ // We make "fma" on some platforms 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()) &&
+ if ((Trip.isGNUEnvironment() || Trip.isAndroid() || Trip.isOSMSVCRT()) &&
!FD->hasAttr<ConstAttr>()) {
switch (BuiltinID) {
case Builtin::BI__builtin_fma:
@@ -12692,7 +13496,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
break;
}
}
-
+
if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
!FD->hasAttr<ReturnsTwiceAttr>())
FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context,
@@ -12753,7 +13557,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// We already have a __builtin___CFStringMakeConstantString,
// but builds that use -fno-constant-cfstrings don't go through that.
if (!FD->hasAttr<FormatArgAttr>())
- FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1,
+ FD->addAttr(FormatArgAttr::CreateImplicit(Context, ParamIdx(1, FD),
FD->getLocation()));
}
}
@@ -12815,7 +13619,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
return NewTD;
}
-/// \brief Check that this is a valid underlying type for an enum declaration.
+/// Check that this is a valid underlying type for an enum declaration.
bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
QualType T = TI->getType();
@@ -12833,11 +13637,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
/// Check whether this is a valid redeclaration of a previous enumeration.
/// \return true if the redeclaration was invalid.
-bool Sema::CheckEnumRedeclaration(
- SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy,
- bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) {
- bool IsFixed = !EnumUnderlyingTy.isNull();
-
+bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
+ QualType EnumUnderlyingTy, bool IsFixed,
+ const EnumDecl *Prev) {
if (IsScoped != Prev->isScoped()) {
Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch)
<< Prev->isScoped();
@@ -12857,10 +13659,6 @@ bool Sema::CheckEnumRedeclaration(
<< Prev->getIntegerTypeRange();
return true;
}
- } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) {
- ;
- } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) {
- ;
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
@@ -12871,7 +13669,7 @@ bool Sema::CheckEnumRedeclaration(
return false;
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// redeclaration diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -12885,7 +13683,7 @@ static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) {
}
}
-/// \brief Determine if tag kind is a class-key compatible with
+/// Determine if tag kind is a class-key compatible with
/// class for redeclaration (class, struct, or __interface).
///
/// \returns true iff the tag kind is compatible.
@@ -12919,7 +13717,7 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl,
llvm_unreachable("invalid TTK");
}
-/// \brief Determine whether a tag with a given kind is acceptable
+/// Determine whether a tag with a given kind is acceptable
/// as a redeclaration of the given tag declaration.
///
/// \returns true if the new tag kind is acceptable, false otherwise.
@@ -13055,8 +13853,8 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
return FixItHint::CreateInsertion(NameLoc, Insertion);
}
-/// \brief Determine whether a tag originally declared in context \p OldDC can
-/// be redeclared with an unqualfied name in \p NewDC (assuming name lookup
+/// Determine whether a tag originally declared in context \p OldDC can
+/// be redeclared with an unqualified name in \p NewDC (assuming name lookup
/// found a declaration in \p OldDC as a previous decl, perhaps through a
/// using-declaration).
static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
@@ -13076,7 +13874,7 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
return false;
}
-/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the
+/// This is invoked when we see 'struct foo' or 'struct {'. In the
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
/// reference/declaration/definition of a tag.
@@ -13089,13 +13887,12 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
+ const ParsedAttributesView &Attrs, AccessSpecifier AS,
SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
- bool ScopedEnumUsesClassTag,
- TypeResult UnderlyingType,
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
SkipBodyInfo *SkipBody) {
// If this is not a definition, it must have a name.
@@ -13134,14 +13931,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
return nullptr;
OwnedDecl = false;
- DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
- SS, Name, NameLoc, Attr,
- TemplateParams, AS,
- ModulePrivateLoc,
- /*FriendLoc*/SourceLocation(),
- TemplateParameterLists.size()-1,
- TemplateParameterLists.data(),
- SkipBody);
+ DeclResult Result = CheckClassTemplate(
+ S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams,
+ AS, ModulePrivateLoc,
+ /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1,
+ TemplateParameterLists.data(), SkipBody);
return Result.get();
} else {
// The "template<>" header is extraneous.
@@ -13156,14 +13950,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// this early, because it's needed to detect if this is an incompatible
// redeclaration.
llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
- bool EnumUnderlyingIsImplicit = false;
+ bool IsFixed = !UnderlyingType.isUnset() || ScopedEnum;
if (Kind == TTK_Enum) {
- if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
+ if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) {
// No underlying type explicitly specified, or we failed to parse the
// type, default to int.
EnumUnderlying = Context.IntTy.getTypePtr();
- else if (UnderlyingType.get()) {
+ } else if (UnderlyingType.get()) {
// C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an
// integral type; any cv-qualification is ignored.
TypeSourceInfo *TI = nullptr;
@@ -13179,11 +13973,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
EnumUnderlying = Context.IntTy.getTypePtr();
} else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (getLangOpts().MSVCCompat || TUK == TUK_Definition) {
- // Microsoft enums are always of int type.
+ // For MSVC ABI compatibility, unfixed enums must use an underlying type
+ // of 'int'. However, if this is an unfixed forward declaration, don't set
+ // the underlying type unless the user enables -fms-compatibility. This
+ // makes unfixed forward declared enums incomplete and is more conforming.
+ if (TUK == TUK_Definition || getLangOpts().MSVCCompat)
EnumUnderlying = Context.IntTy.getTypePtr();
- EnumUnderlyingIsImplicit = true;
- }
}
}
@@ -13209,8 +14004,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Kind == TTK_Enum) {
New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr,
- ScopedEnum, ScopedEnumUsesClassTag,
- !EnumUnderlying.isNull());
+ ScopedEnum, ScopedEnumUsesClassTag, IsFixed);
// If this is an undefined enum, bail.
if (TUK != TUK_Definition && !Invalid)
return nullptr;
@@ -13589,7 +14383,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// in which case we want the caller to bail out.
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
ScopedEnum, EnumUnderlyingTy,
- EnumUnderlyingIsImplicit, PrevEnum))
+ IsFixed, PrevEnum))
return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}
@@ -13607,7 +14401,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// If this is a use, just return the declaration we found, unless
// we have attributes.
if (TUK == TUK_Reference || TUK == TUK_Friend) {
- if (Attr) {
+ if (!Attrs.empty()) {
// FIXME: Diagnose these attributes. For now, we create a new
// declaration to hold them.
} else if (TUK == TUK_Reference &&
@@ -13799,13 +14593,12 @@ CreateNewDecl:
// PrevDecl.
TagDecl *New;
- bool IsForwardReference = false;
if (Kind == TTK_Enum) {
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
// enum X { A, B, C } D; D should chain to X.
New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name,
cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
- ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
+ ScopedEnumUsesClassTag, IsFixed);
if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit()))
StdAlignValT = cast<EnumDecl>(New);
@@ -13813,8 +14606,7 @@ CreateNewDecl:
// If this is an undefined enum, warn.
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
- if (!EnumUnderlyingIsImplicit &&
- (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
+ if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
cast<EnumDecl>(New)->isFixed()) {
// C++0x: 7.2p2: opaque-enum-declaration.
// Conflicts are diagnosed above. Do nothing.
@@ -13830,12 +14622,6 @@ CreateNewDecl:
else if (getLangOpts().CPlusPlus)
DiagID = diag::err_forward_ref_enum;
Diag(Loc, DiagID);
-
- // If this is a forward-declared reference to an enumeration, make a
- // note of it; we won't actually be introducing the declaration into
- // the declaration context.
- if (TUK == TUK_Reference)
- IsForwardReference = true;
}
}
@@ -13846,6 +14632,7 @@ CreateNewDecl:
else
ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0));
ED->setPromotionType(ED->getIntegerType());
+ assert(ED->isComplete() && "enum with type should be complete");
}
} else {
// struct/union/class
@@ -13884,13 +14671,10 @@ CreateNewDecl:
if (SS.isNotEmpty()) {
if (SS.isSet()) {
// If this is either a declaration or a definition, check the
- // nested-name-specifier against the current context. We don't do this
- // for explicit specializations, because they have similar checking
- // (with more specific diagnostics) in the call to
- // CheckMemberSpecialization, below.
- if (!isMemberSpecialization &&
- (TUK == TUK_Definition || TUK == TUK_Declaration) &&
- diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc))
+ // nested-name-specifier against the current context.
+ if ((TUK == TUK_Definition || TUK == TUK_Declaration) &&
+ diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc,
+ isMemberSpecialization))
Invalid = true;
New->setQualifierInfo(SS.getWithLocInContext(Context));
@@ -13977,8 +14761,7 @@ CreateNewDecl:
if (TUK == TUK_Definition)
New->startDefinition();
- if (Attr)
- ProcessDeclAttributeList(S, New, Attr);
+ ProcessDeclAttributeList(S, New, Attrs);
AddPragmaAttributes(S, New);
// If this has an identifier, add it to the scope stack.
@@ -13995,9 +14778,7 @@ CreateNewDecl:
PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
} else if (Name) {
S = getNonFieldDeclScope(S);
- PushOnScopeChains(New, S, !IsForwardReference);
- if (IsForwardReference)
- SearchDC->makeDeclVisibleInContext(New);
+ PushOnScopeChains(New, S, true);
} else {
CurContext->addDecl(New);
}
@@ -14381,7 +15162,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
return NewFD;
}
-/// \brief Build a new FieldDecl and check its well-formedness.
+/// Build a new FieldDecl and check its well-formedness.
///
/// This routine builds a new FieldDecl given the fields name, type,
/// record, etc. \p PrevDecl should refer to any previous declaration
@@ -14432,6 +15213,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
InvalidDecl = true;
}
+ // Anonymous bit-fields cannot be cv-qualified (CWG 2229).
+ if (!InvalidDecl && getLangOpts().CPlusPlus && !II && BitWidth &&
+ T.hasQualifiers()) {
+ InvalidDecl = true;
+ Diag(Loc, diag::err_anon_bitfield_qualifiers);
+ }
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
@@ -14764,7 +15552,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
- if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0)
+ if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context))
return;
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext);
if (!ID) {
@@ -14792,7 +15580,8 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
ArrayRef<Decl *> Fields, SourceLocation LBrac,
- SourceLocation RBrac, AttributeList *Attr) {
+ SourceLocation RBrac,
+ const ParsedAttributesView &Attrs) {
assert(EnclosingDecl && "missing record or interface decl");
// If this is an Objective-C @implementation or category and we have
@@ -14975,8 +15764,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
- Record && !ObjCFieldLifetimeErrReported &&
- (!getLangOpts().CPlusPlus || Record->isUnion())) {
+ Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) {
// It's an error in ARC or Weak if a field has lifetime.
// We don't want to report this in a system header, though,
// so we just make the field unavailable.
@@ -15012,6 +15800,27 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Record->setHasObjectMember(true);
}
}
+
+ if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
+ QualType FT = FD->getType();
+ if (FT.isNonTrivialToPrimitiveDefaultInitialize())
+ Record->setNonTrivialToPrimitiveDefaultInitialize(true);
+ QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy();
+ if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)
+ Record->setNonTrivialToPrimitiveCopy(true);
+ if (FT.isDestructedType()) {
+ Record->setNonTrivialToPrimitiveDestroy(true);
+ Record->setParamDestroyedInCallee(true);
+ }
+
+ if (const auto *RT = FT->getAs<RecordType>()) {
+ if (RT->getDecl()->getArgPassingRestrictions() ==
+ RecordDecl::APK_CanNeverPassInRegs)
+ Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+ } else if (FT.getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak)
+ Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+ }
+
if (Record && FD->getType().isVolatileQualified())
Record->setHasVolatileMember(true);
// Keep track of the number of named members.
@@ -15039,10 +15848,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
CXXRecord->getDestructor());
}
- if (!CXXRecord->isInvalidDecl()) {
- // Add any implicitly-declared members to this class.
- AddImplicitlyDeclaredMembersToClass(CXXRecord);
+ // Add any implicitly-declared members to this class.
+ AddImplicitlyDeclaredMembersToClass(CXXRecord);
+ if (!CXXRecord->isInvalidDecl()) {
// If we have virtual base classes, we may end up finding multiple
// final overriders for a given virtual function. Check for this
// problem now.
@@ -15057,7 +15866,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
SOEnd = M->second.end();
SO != SOEnd; ++SO) {
assert(SO->second.size() > 0 &&
- "Virtual function without overridding functions?");
+ "Virtual function without overriding functions?");
if (SO->second.size() == 1)
continue;
@@ -15089,6 +15898,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (!Completed)
Record->completeDefinition();
+ // Handle attributes before checking the layout.
+ ProcessDeclAttributeList(S, Record, Attrs);
+
// We may have deferred checking for a deleted destructor. Check now.
if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
auto *Dtor = CXXRecord->getDestructor();
@@ -15131,7 +15943,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
(NonBitFields == 0 || ZeroSize) && I != E; ++I) {
IsEmpty = false;
if (I->isUnnamedBitfield()) {
- if (I->getBitWidthValue(Context) > 0)
+ if (!I->isZeroLengthBitField(Context))
ZeroSize = false;
} else {
++NonBitFields;
@@ -15219,12 +16031,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
CDecl->setIvarRBraceLoc(RBrac);
}
}
-
- if (Attr)
- ProcessDeclAttributeList(S, Record, Attr);
}
-/// \brief Determine whether the given integral value is representable within
+/// Determine whether the given integral value is representable within
/// the given type T.
static bool isRepresentableIntegerValue(ASTContext &Context,
llvm::APSInt &Value,
@@ -15241,7 +16050,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context,
return Value.getMinSignedBits() <= BitWidth;
}
-// \brief Given an integral type, return the next larger integral type
+// Given an integral type, return the next larger integral type
// (or a NULL type of no such type exists).
static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
// FIXME: Int128/UInt128 support, which also needs to be introduced into
@@ -15304,7 +16113,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
&EnumVal).get())) {
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
} else {
- if (Enum->isFixed()) {
+ if (Enum->isComplete()) {
EltTy = Enum->getIntegerType();
// In Obj-C and Microsoft mode, require the enumeration value to be
@@ -15468,7 +16277,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
- AttributeList *Attr,
+ const ParsedAttributesView &Attrs,
SourceLocation EqualLoc, Expr *Val) {
EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
EnumConstantDecl *LastEnumConst =
@@ -15519,7 +16328,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
}
// Process attributes.
- if (Attr) ProcessDeclAttributeList(S, New, Attr);
+ ProcessDeclAttributeList(S, New, Attrs);
AddPragmaAttributes(S, New);
// Register this decl in the current scope stack.
@@ -15571,39 +16380,10 @@ static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
return false;
}
-namespace {
-struct DupKey {
- int64_t val;
- bool isTombstoneOrEmptyKey;
- DupKey(int64_t val, bool isTombstoneOrEmptyKey)
- : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {}
-};
-
-static DupKey GetDupKey(const llvm::APSInt& Val) {
- return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(),
- false);
-}
-
-struct DenseMapInfoDupKey {
- static DupKey getEmptyKey() { return DupKey(0, true); }
- static DupKey getTombstoneKey() { return DupKey(1, true); }
- static unsigned getHashValue(const DupKey Key) {
- return (unsigned)(Key.val * 37);
- }
- static bool isEqual(const DupKey& LHS, const DupKey& RHS) {
- return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey &&
- LHS.val == RHS.val;
- }
-};
-} // end anonymous namespace
-
// Emits a warning when an element is implicitly set a value that
// a previous element has already been set to.
static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
- EnumDecl *Enum,
- QualType EnumType) {
- if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
- return;
+ EnumDecl *Enum, QualType EnumType) {
// Avoid anonymous enums
if (!Enum->getIdentifier())
return;
@@ -15612,20 +16392,28 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64)
return;
+ if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
+ return;
+
typedef SmallVector<EnumConstantDecl *, 3> ECDVector;
- typedef SmallVector<ECDVector *, 3> DuplicatesVector;
+ typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector;
typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
- typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey>
- ValueToVectorMap;
+ typedef llvm::DenseMap<int64_t, DeclOrVector> ValueToVectorMap;
+
+ // Use int64_t as a key to avoid needing special handling for DenseMap keys.
+ auto EnumConstantToKey = [](const EnumConstantDecl *D) {
+ llvm::APSInt Val = D->getInitVal();
+ return Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue();
+ };
DuplicatesVector DupVector;
ValueToVectorMap EnumMap;
// Populate the EnumMap with all values represented by enum constants without
- // an initialier.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+ // an initializer.
+ for (auto *Element : Elements) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Element);
// Null EnumConstantDecl means a previous diagnostic has been emitted for
// this constant. Skip this enum since it may be ill-formed.
@@ -15633,45 +16421,45 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
return;
}
+ // Constants with initalizers are handled in the next loop.
if (ECD->getInitExpr())
continue;
- DupKey Key = GetDupKey(ECD->getInitVal());
- DeclOrVector &Entry = EnumMap[Key];
-
- // First time encountering this value.
- if (Entry.isNull())
- Entry = ECD;
+ // Duplicate values are handled in the next loop.
+ EnumMap.insert({EnumConstantToKey(ECD), ECD});
}
+ if (EnumMap.size() == 0)
+ return;
+
// Create vectors for any values that has duplicates.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+ for (auto *Element : Elements) {
+ // The last loop returned if any constant was null.
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Element);
if (!ValidDuplicateEnum(ECD, Enum))
continue;
- DupKey Key = GetDupKey(ECD->getInitVal());
-
- DeclOrVector& Entry = EnumMap[Key];
- if (Entry.isNull())
+ auto Iter = EnumMap.find(EnumConstantToKey(ECD));
+ if (Iter == EnumMap.end())
continue;
+ DeclOrVector& Entry = Iter->second;
if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) {
// Ensure constants are different.
if (D == ECD)
continue;
// Create new vector and push values onto it.
- ECDVector *Vec = new ECDVector();
+ auto Vec = llvm::make_unique<ECDVector>();
Vec->push_back(D);
Vec->push_back(ECD);
// Update entry to point to the duplicates vector.
- Entry = Vec;
+ Entry = Vec.get();
// Store the vector somewhere we can consult later for quick emission of
// diagnostics.
- DupVector.push_back(Vec);
+ DupVector.emplace_back(std::move(Vec));
continue;
}
@@ -15684,26 +16472,21 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
}
// Emit diagnostics.
- for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(),
- DupVectorEnd = DupVector.end();
- DupVectorIter != DupVectorEnd; ++DupVectorIter) {
- ECDVector *Vec = *DupVectorIter;
+ for (const auto &Vec : DupVector) {
assert(Vec->size() > 1 && "ECDVector should have at least 2 elements.");
// Emit warning for one enum constant.
- ECDVector::iterator I = Vec->begin();
- S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values)
- << (*I)->getName() << (*I)->getInitVal().toString(10)
- << (*I)->getSourceRange();
- ++I;
+ auto *FirstECD = Vec->front();
+ S.Diag(FirstECD->getLocation(), diag::warn_duplicate_enum_values)
+ << FirstECD << FirstECD->getInitVal().toString(10)
+ << FirstECD->getSourceRange();
// Emit one note for each of the remaining enum constants with
// the same value.
- for (ECDVector::iterator E = Vec->end(); I != E; ++I)
- S.Diag((*I)->getLocation(), diag::note_duplicate_element)
- << (*I)->getName() << (*I)->getInitVal().toString(10)
- << (*I)->getSourceRange();
- delete Vec;
+ for (auto *ECD : llvm::make_range(Vec->begin() + 1, Vec->end()))
+ S.Diag(ECD->getLocation(), diag::note_duplicate_element)
+ << ECD << ECD->getInitVal().toString(10)
+ << ECD->getSourceRange();
}
}
@@ -15737,14 +16520,12 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
}
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
- Decl *EnumDeclX,
- ArrayRef<Decl *> Elements,
- Scope *S, AttributeList *Attr) {
+ Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S,
+ const ParsedAttributesView &Attrs) {
EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
QualType EnumType = Context.getTypeDeclType(Enum);
- if (Attr)
- ProcessDeclAttributeList(S, Enum, Attr);
+ ProcessDeclAttributeList(S, Enum, Attrs);
if (Enum->isDependentType()) {
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
@@ -15815,7 +16596,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
if (LangOpts.ShortEnums)
Packed = true;
- if (Enum->isFixed()) {
+ // If the enum already has a type because it is fixed or dictated by the
+ // target, promote that type instead of analyzing the enumerators.
+ if (Enum->isComplete()) {
BestType = Enum->getIntegerType();
if (BestType->isPromotableIntegerType())
BestPromotionType = Context.getPromotedIntegerType(BestType);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 21fe46ad9dd1..77deed6047f4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -31,6 +31,7 @@
#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/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -58,7 +59,7 @@ static bool isFunctionOrMethod(const Decl *D) {
return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
}
-/// \brief Return true if the given decl has function type (function or
+/// Return true if the given decl has function type (function or
/// function-typed variable) or an Objective-C method or a block.
static bool isFunctionOrMethodOrBlock(const Decl *D) {
return isFunctionOrMethod(D) || isa<BlockDecl>(D);
@@ -87,7 +88,7 @@ static bool hasFunctionProto(const Decl *D) {
static unsigned getFunctionOrMethodNumParams(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getNumParams();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getNumParams();
return cast<ObjCMethodDecl>(D)->param_size();
}
@@ -95,7 +96,7 @@ static unsigned getFunctionOrMethodNumParams(const Decl *D) {
static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getParamDecl(Idx)->getType();
return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
@@ -113,7 +114,7 @@ static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
static QualType getFunctionOrMethodResultType(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
- return cast<FunctionType>(FnTy)->getReturnType();
+ return FnTy->getReturnType();
return cast<ObjCMethodDecl>(D)->getReturnType();
}
@@ -126,24 +127,21 @@ static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
}
static bool isFunctionOrMethodVariadic(const Decl *D) {
- if (const FunctionType *FnTy = D->getFunctionType()) {
- const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
- return proto->isVariadic();
- }
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const FunctionType *FnTy = D->getFunctionType())
+ return cast<FunctionProtoType>(FnTy)->isVariadic();
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->isVariadic();
-
return cast<ObjCMethodDecl>(D)->isVariadic();
}
static bool isInstanceMethod(const Decl *D) {
- if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D))
+ if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
return MethodDecl->isInstance();
return false;
}
static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
- const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
+ const auto *PT = T->getAs<ObjCObjectPointerType>();
if (!PT)
return false;
@@ -159,11 +157,11 @@ static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
}
static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
- const PointerType *PT = T->getAs<PointerType>();
+ const auto *PT = T->getAs<PointerType>();
if (!PT)
return false;
- const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
+ const auto *RT = PT->getPointeeType()->getAs<RecordType>();
if (!RT)
return false;
@@ -174,89 +172,86 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
}
-static unsigned getNumAttributeArgs(const AttributeList &Attr) {
+static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
// FIXME: Include the type in the argument list.
- return Attr.getNumArgs() + Attr.hasParsedType();
+ return AL.getNumArgs() + AL.hasParsedType();
}
template <typename Compare>
-static bool checkAttributeNumArgsImpl(Sema &S, const AttributeList &Attr,
+static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
unsigned Num, unsigned Diag,
Compare Comp) {
- if (Comp(getNumAttributeArgs(Attr), Num)) {
- S.Diag(Attr.getLoc(), Diag) << Attr.getName() << Num;
+ if (Comp(getNumAttributeArgs(AL), Num)) {
+ S.Diag(AL.getLoc(), Diag) << AL.getName() << Num;
return false;
}
return true;
}
-/// \brief Check if the attribute has exactly as many args as Num. May
+/// Check if the attribute has exactly as many args as Num. May
/// output an error.
-static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, Attr, Num,
+static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) {
+ return checkAttributeNumArgsImpl(S, AL, Num,
diag::err_attribute_wrong_number_arguments,
std::not_equal_to<unsigned>());
}
-/// \brief Check if the attribute has at least as many args as Num. May
+/// Check if the attribute has at least as many args as Num. May
/// output an error.
-static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
+static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL,
unsigned Num) {
- return checkAttributeNumArgsImpl(S, Attr, Num,
+ return checkAttributeNumArgsImpl(S, AL, Num,
diag::err_attribute_too_few_arguments,
std::less<unsigned>());
}
-/// \brief Check if the attribute has at most as many args as Num. May
+/// Check if the attribute has at most as many args as Num. May
/// output an error.
-static bool checkAttributeAtMostNumArgs(Sema &S, const AttributeList &Attr,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, Attr, Num,
+static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL,
+ unsigned Num) {
+ return checkAttributeNumArgsImpl(S, AL, Num,
diag::err_attribute_too_many_arguments,
std::greater<unsigned>());
}
-/// \brief A helper function to provide Attribute Location for the Attr types
-/// AND the AttributeList.
+/// A helper function to provide Attribute Location for the Attr types
+/// AND the ParsedAttr.
template <typename AttrInfo>
-static typename std::enable_if<std::is_base_of<clang::Attr, AttrInfo>::value,
+static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value,
SourceLocation>::type
-getAttrLoc(const AttrInfo &Attr) {
- return Attr.getLocation();
-}
-static SourceLocation getAttrLoc(const clang::AttributeList &Attr) {
- return Attr.getLoc();
+getAttrLoc(const AttrInfo &AL) {
+ return AL.getLocation();
}
+static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
-/// \brief A helper function to provide Attribute Name for the Attr types
-/// AND the AttributeList.
+/// A helper function to provide Attribute Name for the Attr types
+/// AND the ParsedAttr.
template <typename AttrInfo>
-static typename std::enable_if<std::is_base_of<clang::Attr, AttrInfo>::value,
+static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value,
const AttrInfo *>::type
-getAttrName(const AttrInfo &Attr) {
- return &Attr;
+getAttrName(const AttrInfo &AL) {
+ return &AL;
}
-static const IdentifierInfo *getAttrName(const clang::AttributeList &Attr) {
- return Attr.getName();
+static const IdentifierInfo *getAttrName(const ParsedAttr &AL) {
+ return AL.getName();
}
-/// \brief If Expr is a valid integer constant, get the value of the integer
+/// If Expr is a valid integer constant, get the value of the integer
/// expression and return success or failure. May output an error.
-template<typename AttrInfo>
-static bool checkUInt32Argument(Sema &S, const AttrInfo& Attr, const Expr *Expr,
+template <typename AttrInfo>
+static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
uint32_t &Val, unsigned Idx = UINT_MAX) {
llvm::APSInt I(32);
if (Expr->isTypeDependent() || Expr->isValueDependent() ||
!Expr->isIntegerConstantExpr(I, S.Context)) {
if (Idx != UINT_MAX)
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_n_type)
- << getAttrName(Attr) << Idx << AANT_ArgumentIntegerConstant
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+ << getAttrName(AI) << Idx << AANT_ArgumentIntegerConstant
<< Expr->getSourceRange();
else
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_type)
- << getAttrName(Attr) << AANT_ArgumentIntegerConstant
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
+ << getAttrName(AI) << AANT_ArgumentIntegerConstant
<< Expr->getSourceRange();
return false;
}
@@ -271,14 +266,14 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo& Attr, const Expr *Expr,
return true;
}
-/// \brief Wrapper around checkUInt32Argument, with an extra check to be sure
+/// Wrapper around checkUInt32Argument, with an extra check to be sure
/// that the result will fit into a regular (signed) int. All args have the same
/// purpose as they do in checkUInt32Argument.
-template<typename AttrInfo>
-static bool checkPositiveIntArgument(Sema &S, const AttrInfo& Attr, const Expr *Expr,
+template <typename AttrInfo>
+static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr,
int &Val, unsigned Idx = UINT_MAX) {
uint32_t UVal;
- if (!checkUInt32Argument(S, Attr, Expr, UVal, Idx))
+ if (!checkUInt32Argument(S, AI, Expr, UVal, Idx))
return false;
if (UVal > (uint32_t)std::numeric_limits<int>::max()) {
@@ -293,12 +288,12 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo& Attr, const Expr *
return true;
}
-/// \brief Diagnose mutually exclusive attributes when present on a given
+/// Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
IdentifierInfo *Ident) {
- if (AttrTy *A = D->getAttr<AttrTy>()) {
+ if (const auto *A = D->getAttr<AttrTy>()) {
S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident
<< A;
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
@@ -307,14 +302,14 @@ static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
return false;
}
-/// \brief Check if IdxExpr is a valid parameter index for a function or
+/// Check if IdxExpr is a valid parameter index for a function or
/// instance method D. May output an error.
///
/// \returns true if IdxExpr is a valid index.
template <typename AttrInfo>
static bool checkFunctionOrMethodParameterIndex(
- Sema &S, const Decl *D, const AttrInfo &Attr, unsigned AttrArgNum,
- const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) {
+ Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,
+ const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) {
assert(isFunctionOrMethodOrBlock(D));
// In C++ the implicit 'this' function parameter also counts.
@@ -328,44 +323,43 @@ static bool checkFunctionOrMethodParameterIndex(
llvm::APSInt IdxInt;
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_n_type)
- << getAttrName(Attr) << AttrArgNum << AANT_ArgumentIntegerConstant
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+ << getAttrName(AI) << AttrArgNum << AANT_ArgumentIntegerConstant
<< IdxExpr->getSourceRange();
return false;
}
- Idx = IdxInt.getLimitedValue();
- if (Idx < 1 || (!IV && Idx > NumParams)) {
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_out_of_bounds)
- << getAttrName(Attr) << AttrArgNum << IdxExpr->getSourceRange();
+ unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX);
+ if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
+ << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange();
return false;
}
- Idx--; // Convert to zero-based.
- if (HasImplicitThisParam && !AllowImplicitThis) {
- if (Idx == 0) {
- S.Diag(getAttrLoc(Attr),
+ if (HasImplicitThisParam && !CanIndexImplicitThis) {
+ if (IdxSource == 1) {
+ S.Diag(getAttrLoc(AI),
diag::err_attribute_invalid_implicit_this_argument)
- << getAttrName(Attr) << IdxExpr->getSourceRange();
+ << getAttrName(AI) << IdxExpr->getSourceRange();
return false;
}
- --Idx;
}
+ Idx = ParamIdx(IdxSource, D);
return true;
}
-/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
+/// Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
/// If not emit an error and return false. If the argument is an identifier it
/// will emit an error with a fixit hint and treat it as if it was a string
/// literal.
-bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
- unsigned ArgNum, StringRef &Str,
+bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
+ StringRef &Str,
SourceLocation *ArgLocation) {
// Look for identifiers. If we have one emit a hint to fix it to a literal.
- if (Attr.isArgIdent(ArgNum)) {
- IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum);
+ if (AL.isArgIdent(ArgNum)) {
+ IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum);
Diag(Loc->Loc, diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentString
+ << AL.getName() << AANT_ArgumentString
<< FixItHint::CreateInsertion(Loc->Loc, "\"")
<< FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
Str = Loc->Ident->getName();
@@ -375,14 +369,14 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
}
// Now check for an actual string literal.
- Expr *ArgExpr = Attr.getArgAsExpr(ArgNum);
- StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
+ Expr *ArgExpr = AL.getArgAsExpr(ArgNum);
+ const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
if (ArgLocation)
*ArgLocation = ArgExpr->getLocStart();
if (!Literal || !Literal->isAscii()) {
Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentString;
+ << AL.getName() << AANT_ArgumentString;
return false;
}
@@ -390,35 +384,34 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
return true;
}
-/// \brief Applies the given attribute to the Decl without performing any
+/// Applies the given attribute to the Decl without performing any
/// additional semantic checking.
template <typename AttrType>
-static void handleSimpleAttribute(Sema &S, Decl *D,
- const AttributeList &Attr) {
- D->addAttr(::new (S.Context) AttrType(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+static void handleSimpleAttribute(Sema &S, Decl *D, const ParsedAttr &AL) {
+ D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
template <typename AttrType>
static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const AttributeList &Attr) {
- handleSimpleAttribute<AttrType>(S, D, Attr);
+ const ParsedAttr &AL) {
+ handleSimpleAttribute<AttrType>(S, D, AL);
}
-/// \brief Applies the given attribute to the Decl so long as the Decl doesn't
+/// Applies the given attribute to the Decl so long as the Decl doesn't
/// already have one of the given incompatible attributes.
template <typename AttrType, typename IncompatibleAttrType,
typename... IncompatibleAttrTypes>
static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, Attr.getRange(),
- Attr.getName()))
+ const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL.getRange(),
+ AL.getName()))
return;
handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D,
- Attr);
+ AL);
}
-/// \brief Check if the passed-in expression is of type int or bool.
+/// Check if the passed-in expression is of type int or bool.
static bool isIntOrBool(Expr *Exp) {
QualType QT = Exp->getType();
return QT->isBooleanType() || QT->isIntegerType();
@@ -441,17 +434,17 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
return true;
}
-/// \brief Check if passed in Decl is a pointer type.
+/// Check if passed in Decl is a pointer type.
/// Note that this function may produce an error message.
/// \return true if the Decl is a pointer type; false otherwise
static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
- const AttributeList &Attr) {
- const ValueDecl *vd = cast<ValueDecl>(D);
- QualType QT = vd->getType();
+ const ParsedAttr &AL) {
+ const auto *VD = cast<ValueDecl>(D);
+ QualType QT = VD->getType();
if (QT->isAnyPointerType())
return true;
- if (const RecordType *RT = QT->getAs<RecordType>()) {
+ if (const auto *RT = QT->getAs<RecordType>()) {
// If it's an incomplete type, it could be a smart pointer; skip it.
// (We don't want to force template instantiation if we can avoid it,
// since that would alter the order in which templates are instantiated.)
@@ -462,19 +455,19 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
return true;
}
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
- << Attr.getName() << QT;
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
+ << AL.getName() << QT;
return false;
}
-/// \brief Checks that the passed in QualType either is of RecordType or points
+/// Checks that the passed in QualType either is of RecordType or points
/// to RecordType. Returns the relevant RecordType, null if it does not exit.
static const RecordType *getRecordType(QualType QT) {
- if (const RecordType *RT = QT->getAs<RecordType>())
+ if (const auto *RT = QT->getAs<RecordType>())
return RT;
// Now check if we point to record type.
- if (const PointerType *PT = QT->getAs<PointerType>())
+ if (const auto *PT = QT->getAs<PointerType>())
return PT->getPointeeType()->getAs<RecordType>();
return nullptr;
@@ -501,7 +494,7 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
return true;
// Else check if any base classes have a capability.
- if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
CXXBasePaths BPaths(false, false);
if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) {
const auto *Type = BS->getType()->getAs<RecordType>();
@@ -559,18 +552,18 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
return typeHasCapability(S, Ex->getType());
}
-/// \brief Checks that all attribute arguments, starting from Sidx, resolve to
+/// Checks that all attribute arguments, starting from Sidx, resolve to
/// a capability object.
/// \param Sidx The attribute argument index to start checking with.
/// \param ParamIdxOk Whether an argument can be indexing into a function
/// parameter list.
static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
- const AttributeList &Attr,
+ const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args,
int Sidx = 0,
bool ParamIdxOk = false) {
- for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
- Expr *ArgExp = Attr.getArgAsExpr(Idx);
+ for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) {
+ Expr *ArgExp = AL.getArgAsExpr(Idx);
if (ArgExp->isTypeDependent()) {
// FIXME -- need to check this again on template instantiation
@@ -578,7 +571,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
continue;
}
- if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
+ if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
if (StrLit->getLength() == 0 ||
(StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
// Pass empty strings to the analyzer without warnings.
@@ -589,8 +582,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// We allow constant strings to be used as a placeholder for expressions
// that are not valid C++ syntax, but warn that they are ignored.
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) <<
- Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL.getName();
Args.push_back(ArgExp);
continue;
}
@@ -599,9 +591,9 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// A pointer to member expression of the form &MyClass::mu is treated
// specially -- we need to look at the type of the member.
- if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(ArgExp))
+ if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp))
if (UOp->getOpcode() == UO_AddrOf)
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
if (DRE->getDecl()->isCXXInstanceMember())
ArgTy = DRE->getDecl()->getType();
@@ -610,16 +602,16 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// Now check if we index into a record type function param.
if(!RT && ParamIdxOk) {
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp);
+ const auto *FD = dyn_cast<FunctionDecl>(D);
+ const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
if(FD && IL) {
unsigned int NumParams = FD->getNumParams();
llvm::APInt ArgValue = IL->getValue();
uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
- if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range)
- << Attr.getName() << Idx + 1 << NumParams;
+ if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
+ << AL.getName() << Idx + 1 << NumParams;
continue;
}
ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
@@ -631,8 +623,8 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// capability may be on the type, and the expression is a capability
// boolean logic expression. Eg) requires_capability(A || B && !C)
if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << Attr.getName() << ArgTy;
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
+ << AL.getName() << ArgTy;
Args.push_back(ArgExp);
}
@@ -642,22 +634,20 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// Attribute Implementations
//===----------------------------------------------------------------------===//
-static void handlePtGuardedVarAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!threadSafetyCheckIsPointer(S, D, Attr))
+static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!threadSafetyCheckIsPointer(S, D, AL))
return;
D->addAttr(::new (S.Context)
- PtGuardedVarAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ PtGuardedVarAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
- Expr* &Arg) {
- SmallVector<Expr*, 1> Args;
+static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
+ Expr *&Arg) {
+ SmallVector<Expr *, 1> Args;
// check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
unsigned Size = Args.size();
if (Size != 1)
return false;
@@ -667,273 +657,239 @@ static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
return true;
}
-static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Expr *Arg = nullptr;
- if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
+ if (!checkGuardedByAttrCommon(S, D, AL, Arg))
return;
- D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) GuardedByAttr(
+ AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex()));
}
-static void handlePtGuardedByAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Expr *Arg = nullptr;
- if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
+ if (!checkGuardedByAttrCommon(S, D, AL, Arg))
return;
- if (!threadSafetyCheckIsPointer(S, D, Attr))
+ if (!threadSafetyCheckIsPointer(S, D, AL))
return;
- D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
- S.Context, Arg,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) PtGuardedByAttr(
+ AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex()));
}
-static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return false;
// Check that this attribute only applies to lockable types.
QualType QT = cast<ValueDecl>(D)->getType();
if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
+ << AL.getName();
return false;
}
// Check that all arguments are lockable objects.
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
if (Args.empty())
return false;
return true;
}
-static void handleAcquiredAfterAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkAcquireOrderAttrCommon(S, D, Attr, Args))
+static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- AcquiredAfterAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AcquiredAfterAttr(
+ AL.getRange(), S.Context, StartArg, Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAcquiredBeforeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkAcquireOrderAttrCommon(S, D, Attr, Args))
+static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- AcquiredBeforeAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AcquiredBeforeAttr(
+ AL.getRange(), S.Context, StartArg, Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkLockFunAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
// zero or more arguments ok
// check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true);
return true;
}
-static void handleAssertSharedLockAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? nullptr : &Args[0];
D->addAttr(::new (S.Context)
- AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
+ AssertSharedLockAttr(AL.getRange(), S.Context, StartArg, Size,
+ AL.getAttributeSpellingListIndex()));
}
static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? nullptr : &Args[0];
- D->addAttr(::new (S.Context)
- AssertExclusiveLockAttr(Attr.getRange(), S.Context,
- StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AssertExclusiveLockAttr(
+ AL.getRange(), S.Context, StartArg, Size,
+ AL.getAttributeSpellingListIndex()));
}
-/// \brief Checks to be sure that the given parameter number is in bounds, and is
-/// an integral type. Will emit appropriate diagnostics if this returns
+/// Checks to be sure that the given parameter number is in bounds, and
+/// is an integral type. Will emit appropriate diagnostics if this returns
/// false.
///
-/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used
-/// to actually retrieve the argument, so it's base-0.
+/// AttrArgNo is used to actually retrieve the argument, so it's base-0.
template <typename AttrInfo>
static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttrInfo &Attr, Expr *AttrArg,
- unsigned FuncParamNo, unsigned AttrArgNo,
- bool AllowDependentType = false) {
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, FD, Attr, FuncParamNo, AttrArg,
+ const AttrInfo &AI, unsigned AttrArgNo) {
+ assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");
+ Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);
+ ParamIdx Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg,
Idx))
return false;
- const ParmVarDecl *Param = FD->getParamDecl(Idx);
- if (AllowDependentType && Param->getType()->isDependentType())
- return true;
+ const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex());
if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
SourceLocation SrcLoc = AttrArg->getLocStart();
S.Diag(SrcLoc, diag::err_attribute_integers_only)
- << getAttrName(Attr) << Param->getSourceRange();
+ << getAttrName(AI) << Param->getSourceRange();
return false;
}
return true;
}
-/// \brief Checks to be sure that the given parameter number is in bounds, and is
-/// an integral type. Will emit appropriate diagnostics if this returns false.
-///
-/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used
-/// to actually retrieve the argument, so it's base-0.
-static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttributeList &Attr,
- unsigned FuncParamNo, unsigned AttrArgNo,
- bool AllowDependentType = false) {
- assert(Attr.isArgExpr(AttrArgNo) && "Expected expression argument");
- return checkParamIsIntegerType(S, FD, Attr, Attr.getArgAsExpr(AttrArgNo),
- FuncParamNo, AttrArgNo, AllowDependentType);
-}
-
-static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
- !checkAttributeAtMostNumArgs(S, Attr, 2))
+static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
+ !checkAttributeAtMostNumArgs(S, AL, 2))
return;
const auto *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isPointerType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
+ << AL.getName();
return;
}
- const Expr *SizeExpr = Attr.getArgAsExpr(0);
- int SizeArgNo;
+ const Expr *SizeExpr = AL.getArgAsExpr(0);
+ int SizeArgNoVal;
// Parameter indices are 1-indexed, hence Index=1
- if (!checkPositiveIntArgument(S, Attr, SizeExpr, SizeArgNo, /*Index=*/1))
+ if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Index=*/1))
return;
-
- if (!checkParamIsIntegerType(S, FD, Attr, SizeArgNo, /*AttrArgNo=*/0))
+ if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0))
return;
+ ParamIdx SizeArgNo(SizeArgNoVal, D);
- // Args are 1-indexed, so 0 implies that the arg was not present
- int NumberArgNo = 0;
- if (Attr.getNumArgs() == 2) {
- const Expr *NumberExpr = Attr.getArgAsExpr(1);
+ ParamIdx NumberArgNo;
+ if (AL.getNumArgs() == 2) {
+ const Expr *NumberExpr = AL.getArgAsExpr(1);
+ int Val;
// Parameter indices are 1-based, hence Index=2
- if (!checkPositiveIntArgument(S, Attr, NumberExpr, NumberArgNo,
- /*Index=*/2))
+ if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Index=*/2))
return;
-
- if (!checkParamIsIntegerType(S, FD, Attr, NumberArgNo, /*AttrArgNo=*/1))
+ if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1))
return;
+ NumberArgNo = ParamIdx(Val, D);
}
- D->addAttr(::new (S.Context) AllocSizeAttr(
- Attr.getRange(), S.Context, SizeArgNo, NumberArgNo,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context)
+ AllocSizeAttr(AL.getRange(), S.Context, SizeArgNo, NumberArgNo,
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return false;
- if (!isIntOrBool(Attr.getArgAsExpr(0))) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIntOrBool;
+ if (!isIntOrBool(AL.getArgAsExpr(0))) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIntOrBool;
return false;
}
// check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 1);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1);
return true;
}
static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkTryLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context)
- SharedTrylockFunctionAttr(Attr.getRange(), S.Context,
- Attr.getArgAsExpr(0),
- Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(
+ AL.getRange(), S.Context, AL.getArgAsExpr(0), Args.data(), Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkTryLockFunAttrCommon(S, D, AL, Args))
return;
D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
- Attr.getRange(), S.Context, Attr.getArgAsExpr(0), Args.data(),
- Args.size(), Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getArgAsExpr(0), Args.data(),
+ Args.size(), AL.getAttributeSpellingListIndex()));
}
-static void handleLockReturnedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// check that the argument is lockable object
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
D->addAttr(::new (S.Context)
- LockReturnedAttr(Attr.getRange(), S.Context, Args[0],
- Attr.getAttributeSpellingListIndex()));
+ LockReturnedAttr(AL.getRange(), S.Context, Args[0],
+ AL.getAttributeSpellingListIndex()));
}
-static void handleLocksExcludedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
Expr **StartArg = &Args[0];
D->addAttr(::new (S.Context)
- LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
+ LocksExcludedAttr(AL.getRange(), S.Context, StartArg, Size,
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkFunctionConditionAttr(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL,
Expr *&Cond, StringRef &Msg) {
- Cond = Attr.getArgAsExpr(0);
+ Cond = AL.getArgAsExpr(0);
if (!Cond->isTypeDependent()) {
ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
if (Converted.isInvalid())
@@ -941,7 +897,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
Cond = Converted.get();
}
- if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg))
+ if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg))
return false;
if (Msg.empty())
@@ -951,8 +907,8 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
!Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
Diags)) {
- S.Diag(Attr.getLoc(), diag::err_attr_cond_never_constant_expr)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr)
+ << AL.getName();
for (const PartialDiagnosticAt &PDiag : Diags)
S.Diag(PDiag.first, PDiag.second);
return false;
@@ -960,15 +916,15 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
return true;
}
-static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- S.Diag(Attr.getLoc(), diag::ext_clang_enable_if);
+static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.Diag(AL.getLoc(), diag::ext_clang_enable_if);
Expr *Cond;
StringRef Msg;
- if (checkFunctionConditionAttr(S, D, Attr, Cond, Msg))
+ if (checkFunctionConditionAttr(S, D, AL, Cond, Msg))
D->addAttr(::new (S.Context)
- EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg,
- Attr.getAttributeSpellingListIndex()));
+ EnableIfAttr(AL.getRange(), S.Context, Cond, Msg,
+ AL.getAttributeSpellingListIndex()));
}
namespace {
@@ -1017,21 +973,21 @@ public:
};
}
-static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- S.Diag(Attr.getLoc(), diag::ext_clang_diagnose_if);
+static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if);
Expr *Cond;
StringRef Msg;
- if (!checkFunctionConditionAttr(S, D, Attr, Cond, Msg))
+ if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg))
return;
StringRef DiagTypeStr;
- if (!S.checkStringLiteralArgumentAttr(Attr, 2, DiagTypeStr))
+ if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr))
return;
DiagnoseIfAttr::DiagnosticType DiagType;
if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) {
- S.Diag(Attr.getArgAsExpr(2)->getLocStart(),
+ S.Diag(AL.getArgAsExpr(2)->getLocStart(),
diag::err_diagnose_if_invalid_diagnostic_type);
return;
}
@@ -1040,21 +996,20 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const auto *FD = dyn_cast<FunctionDecl>(D))
ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
D->addAttr(::new (S.Context) DiagnoseIfAttr(
- Attr.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D),
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent,
+ cast<NamedDecl>(D), AL.getAttributeSpellingListIndex()));
}
-static void handlePassObjectSizeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->hasAttr<PassObjectSizeAttr>()) {
S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter)
- << Attr.getName();
+ << AL.getName();
return;
}
- Expr *E = Attr.getArgAsExpr(0);
+ Expr *E = AL.getArgAsExpr(0);
uint32_t Type;
- if (!checkUInt32Argument(S, Attr, E, Type, /*Idx=*/1))
+ if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1))
return;
// pass_object_size's argument is passed in as the second argument of
@@ -1062,7 +1017,7 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D,
// argument; namely, it must be in the range [0, 3].
if (Type > 3) {
S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range)
- << Attr.getName() << 0 << 3 << E->getSourceRange();
+ << AL.getName() << 0 << 3 << E->getSourceRange();
return;
}
@@ -1072,112 +1027,109 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D,
// definition, so we defer the constness check until later.
if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
S.Diag(D->getLocStart(), diag::err_attribute_pointers_only)
- << Attr.getName() << 1;
+ << AL.getName() << 1;
return;
}
- D->addAttr(::new (S.Context)
- PassObjectSizeAttr(Attr.getRange(), S.Context, (int)Type,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) PassObjectSizeAttr(
+ AL.getRange(), S.Context, (int)Type, AL.getAttributeSpellingListIndex()));
}
-static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ConsumableAttr::ConsumedState DefaultState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *IL = AL.getArgAsIdent(0);
if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
DefaultState)) {
S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << IL->Ident;
+ << AL.getName() << IL->Ident;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL.getName() << AANT_ArgumentIdentifier;
return;
}
-
+
D->addAttr(::new (S.Context)
- ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
- Attr.getAttributeSpellingListIndex()));
+ ConsumableAttr(AL.getRange(), S.Context, DefaultState,
+ AL.getAttributeSpellingListIndex()));
}
static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
ASTContext &CurrContext = S.getASTContext();
QualType ThisType = MD->getThisType(CurrContext)->getPointeeType();
-
+
if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
if (!RD->hasAttr<ConsumableAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) <<
+ S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) <<
RD->getNameAsString();
-
+
return false;
}
}
-
+
return true;
}
-static void handleCallableWhenAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
-
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
return;
-
+
SmallVector<CallableWhenAttr::ConsumedState, 3> States;
- for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
+ for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) {
CallableWhenAttr::ConsumedState CallableState;
-
+
StringRef StateString;
SourceLocation Loc;
- if (Attr.isArgIdent(ArgIndex)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(ArgIndex);
+ if (AL.isArgIdent(ArgIndex)) {
+ IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex);
StateString = Ident->Ident->getName();
Loc = Ident->Loc;
} else {
- if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc))
+ if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc))
return;
}
if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
CallableState)) {
S.Diag(Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << StateString;
+ << AL.getName() << StateString;
return;
}
-
+
States.push_back(CallableState);
}
-
+
D->addAttr(::new (S.Context)
- CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
- States.size(), Attr.getAttributeSpellingListIndex()));
+ CallableWhenAttr(AL.getRange(), S.Context, States.data(),
+ States.size(), AL.getAttributeSpellingListIndex()));
}
-static void handleParamTypestateAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ParamTypestateAttr::ConsumedState ParamState;
-
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *Ident = AL.getArgAsIdent(0);
StringRef StateString = Ident->Ident->getName();
if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
ParamState)) {
S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << StateString;
+ << AL.getName() << StateString;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
-
+
// FIXME: This check is currently being done in the analysis. It can be
// enabled here only after the parser propagates attributes at
// template specialization definition, not declaration.
@@ -1185,34 +1137,33 @@ static void handleParamTypestateAttr(Sema &S, Decl *D,
//const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
//
//if (!RD || !RD->hasAttr<ConsumableAttr>()) {
- // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
+ // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
// ReturnType.getAsString();
// return;
//}
-
+
D->addAttr(::new (S.Context)
- ParamTypestateAttr(Attr.getRange(), S.Context, ParamState,
- Attr.getAttributeSpellingListIndex()));
+ ParamTypestateAttr(AL.getRange(), S.Context, ParamState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleReturnTypestateAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ReturnTypestateAttr::ConsumedState ReturnState;
-
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *IL = Attr.getArgAsIdent(0);
+
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *IL = AL.getArgAsIdent(0);
if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
ReturnState)) {
S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << IL->Ident;
+ << AL.getName() << IL->Ident;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
-
+
// FIXME: This check is currently being done in the analysis. It can be
// enabled here only after the parser propagates attributes at
// template specialization definition, not declaration.
@@ -1224,9 +1175,9 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
//} else if (const CXXConstructorDecl *Constructor =
// dyn_cast<CXXConstructorDecl>(D)) {
// ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType();
- //
+ //
//} else {
- //
+ //
// ReturnType = cast<FunctionDecl>(D)->getCallResultType();
//}
//
@@ -1237,72 +1188,70 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
// ReturnType.getAsString();
// return;
//}
-
+
D->addAttr(::new (S.Context)
- ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState,
- Attr.getAttributeSpellingListIndex()));
+ ReturnTypestateAttr(AL.getRange(), S.Context, ReturnState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
return;
-
+
SetTypestateAttr::ConsumedState NewState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *Ident = AL.getArgAsIdent(0);
StringRef Param = Ident->Ident->getName();
if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << Param;
+ << AL.getName() << Param;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
-
+
D->addAttr(::new (S.Context)
- SetTypestateAttr(Attr.getRange(), S.Context, NewState,
- Attr.getAttributeSpellingListIndex()));
+ SetTypestateAttr(AL.getRange(), S.Context, NewState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleTestTypestateAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
return;
-
- TestTypestateAttr::ConsumedState TestState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+
+ TestTypestateAttr::ConsumedState TestState;
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *Ident = AL.getArgAsIdent(0);
StringRef Param = Ident->Ident->getName();
if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << Param;
+ << AL.getName() << Param;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
-
+
D->addAttr(::new (S.Context)
- TestTypestateAttr(Attr.getRange(), S.Context, TestState,
- Attr.getAttributeSpellingListIndex()));
+ TestTypestateAttr(AL.getRange(), S.Context, TestState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr) {
+static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Remember this typedef decl, we will need it later for diagnostics.
S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
}
-static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (TagDecl *TD = dyn_cast<TagDecl>(D))
- TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (auto *TD = dyn_cast<TagDecl>(D))
+ TD->addAttr(::new (S.Context) PackedAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
+ else if (auto *FD = dyn_cast<FieldDecl>(D)) {
bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
!FD->getType()->isIncompleteType() &&
FD->isBitField() &&
@@ -1311,81 +1260,80 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
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();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
+ << AL.getName() << FD->getType();
else
FD->addAttr(::new (S.Context) PackedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
} else {
// Report warning about changed offset in the newer compiler versions.
if (BitfieldByteAligned)
- S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield);
+ S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield);
FD->addAttr(::new (S.Context) PackedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
} else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName();
}
-static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
+static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
// The IBOutlet/IBOutletCollection attributes only apply to instance
// variables or properties of Objective-C classes. The outlet must also
// have an object reference type.
- if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) {
+ if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
- S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
- << Attr.getName() << VD->getType() << 0;
+ S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
+ << AL.getName() << VD->getType() << 0;
return false;
}
}
- else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+ else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
- S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
- << Attr.getName() << PD->getType() << 1;
+ S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
+ << AL.getName() << PD->getType() << 1;
return false;
}
}
else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL.getName();
return false;
}
return true;
}
-static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkIBOutletCommon(S, D, Attr))
+static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkIBOutletCommon(S, D, AL))
return;
D->addAttr(::new (S.Context)
- IBOutletAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ IBOutletAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleIBOutletCollection(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) {
// The iboutletcollection attribute can have zero or one arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
- if (!checkIBOutletCommon(S, D, Attr))
+ if (!checkIBOutletCommon(S, D, AL))
return;
ParsedType PT;
- if (Attr.hasParsedType())
- PT = Attr.getTypeArg();
+ if (AL.hasParsedType())
+ PT = AL.getTypeArg();
else {
- PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(),
+ PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(),
S.getScopeForContext(D->getDeclContext()->getParent()));
if (!PT) {
- S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
+ S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
return;
}
}
@@ -1393,22 +1341,22 @@ static void handleIBOutletCollection(Sema &S, Decl *D,
TypeSourceInfo *QTLoc = nullptr;
QualType QT = S.GetTypeFromParser(PT, &QTLoc);
if (!QTLoc)
- QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc());
+ QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc());
// Diagnose use of non-object type in iboutletcollection attribute.
// FIXME. Gnu attribute extension ignores use of builtin types in
// attributes. So, __attribute__((iboutletcollection(char))) will be
// treated as __attribute__((iboutletcollection())).
if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
: diag::err_iboutletcollection_type) << QT;
return;
}
D->addAttr(::new (S.Context)
- IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc,
- Attr.getAttributeSpellingListIndex()));
+ IBOutletCollectionAttr(AL.getRange(), S.Context, QTLoc,
+ AL.getAttributeSpellingListIndex()));
}
bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
@@ -1435,35 +1383,36 @@ bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
return T->isAnyPointerType() || T->isBlockPointerType();
}
-static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
+static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL,
SourceRange AttrParmRange,
SourceRange TypeRange,
bool isReturnValue = false) {
if (!S.isValidPointerAttrType(T)) {
if (isReturnValue)
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName() << AttrParmRange << TypeRange;
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
+ << AL.getName() << AttrParmRange << TypeRange;
else
- S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
- << Attr.getName() << AttrParmRange << TypeRange << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
+ << AL.getName() << AttrParmRange << TypeRange << 0;
return false;
}
return true;
}
-static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- SmallVector<unsigned, 8> NonNullArgs;
- for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {
- Expr *Ex = Attr.getArgAsExpr(I);
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, I + 1, Ex, Idx))
+static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<ParamIdx, 8> NonNullArgs;
+ for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
+ Expr *Ex = AL.getArgAsExpr(I);
+ ParamIdx Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx))
return;
// Is the function argument a pointer type?
- if (Idx < getFunctionOrMethodNumParams(D) &&
- !attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
- Ex->getSourceRange(),
- getFunctionOrMethodParamRange(D, Idx)))
+ if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) &&
+ !attrNonNullArgCheck(
+ S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL,
+ Ex->getSourceRange(),
+ getFunctionOrMethodParamRange(D, Idx.getASTIndex())))
continue;
NonNullArgs.push_back(Idx);
@@ -1473,7 +1422,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// arguments have a nonnull attribute; warn if there aren't any. Skip this
// check if the attribute came from a macro expansion or a template
// instantiation.
- if (NonNullArgs.empty() && Attr.getLoc().isFileID() &&
+ if (NonNullArgs.empty() && AL.getLoc().isFileID() &&
!S.inTemplateInstantiation()) {
bool AnyPointers = isFunctionOrMethodVariadic(D);
for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
@@ -1484,80 +1433,77 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
if (!AnyPointers)
- S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
+ S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers);
}
- unsigned *Start = NonNullArgs.data();
+ ParamIdx *Start = NonNullArgs.data();
unsigned Size = NonNullArgs.size();
llvm::array_pod_sort(Start, Start + Size);
D->addAttr(::new (S.Context)
- NonNullAttr(Attr.getRange(), S.Context, Start, Size,
- Attr.getAttributeSpellingListIndex()));
+ NonNullAttr(AL.getRange(), S.Context, Start, Size,
+ AL.getAttributeSpellingListIndex()));
}
static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
- const AttributeList &Attr) {
- if (Attr.getNumArgs() > 0) {
+ const ParsedAttr &AL) {
+ if (AL.getNumArgs() > 0) {
if (D->getFunctionType()) {
- handleNonNullAttr(S, D, Attr);
+ handleNonNullAttr(S, D, AL);
} else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
+ S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
<< D->getSourceRange();
}
return;
}
// Is the argument a pointer type?
- if (!attrNonNullArgCheck(S, D->getType(), Attr, SourceRange(),
+ if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(),
D->getSourceRange()))
return;
D->addAttr(::new (S.Context)
- NonNullAttr(Attr.getRange(), S.Context, nullptr, 0,
- Attr.getAttributeSpellingListIndex()));
+ NonNullAttr(AL.getRange(), S.Context, nullptr, 0,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleReturnsNonNullAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
QualType ResultType = getFunctionOrMethodResultType(D);
SourceRange SR = getFunctionOrMethodResultSourceRange(D);
- if (!attrNonNullArgCheck(S, ResultType, Attr, SourceRange(), SR,
+ if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR,
/* isReturnValue */ true))
return;
D->addAttr(::new (S.Context)
- ReturnsNonNullAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ReturnsNonNullAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleNoEscapeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
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;
+ S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
+ << AL.getName() << AL.getRange() << 0;
return;
}
D->addAttr(::new (S.Context) NoEscapeAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleAssumeAlignedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- Expr *E = Attr.getArgAsExpr(0),
- *OE = Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr;
- S.AddAssumeAlignedAttr(Attr.getRange(), D, E, OE,
- Attr.getAttributeSpellingListIndex());
+static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *E = AL.getArgAsExpr(0),
+ *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr;
+ S.AddAssumeAlignedAttr(AL.getRange(), D, E, OE,
+ AL.getAttributeSpellingListIndex());
}
-static void handleAllocAlignAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- S.AddAllocAlignAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
- Attr.getAttributeSpellingListIndex());
+static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.AddAllocAlignAttr(AL.getRange(), D, AL.getArgAsExpr(0),
+ AL.getAttributeSpellingListIndex());
}
void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
@@ -1615,7 +1561,7 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
unsigned SpellingListIndex) {
QualType ResultType = getFunctionOrMethodResultType(D);
- AllocAlignAttr TmpAttr(AttrRange, Context, 0, SpellingListIndex);
+ AllocAlignAttr TmpAttr(AttrRange, Context, ParamIdx(), SpellingListIndex);
SourceLocation AttrLoc = AttrRange.getBegin();
if (!ResultType->isDependentType() &&
@@ -1625,28 +1571,22 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
return;
}
- uint64_t IndexVal;
+ ParamIdx Idx;
const auto *FuncDecl = cast<FunctionDecl>(D);
if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr,
- /*AttrArgNo=*/1, ParamExpr,
- IndexVal))
+ /*AttrArgNo=*/1, ParamExpr, Idx))
return;
- QualType Ty = getFunctionOrMethodParamType(D, IndexVal);
+ QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) {
Diag(ParamExpr->getLocStart(), diag::err_attribute_integers_only)
- << &TmpAttr << FuncDecl->getParamDecl(IndexVal)->getSourceRange();
+ << &TmpAttr
+ << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
return;
}
- // We cannot use the Idx returned from checkFunctionOrMethodParameterIndex
- // because that has corrected for the implicit this parameter, and is zero-
- // based. The attribute expects what the user wrote explicitly.
- llvm::APSInt Val;
- ParamExpr->EvaluateAsInt(Val, Context);
-
- D->addAttr(::new (Context) AllocAlignAttr(
- AttrRange, Context, Val.getZExtValue(), SpellingListIndex));
+ D->addAttr(::new (Context)
+ AllocAlignAttr(AttrRange, Context, Idx, SpellingListIndex));
}
/// Normalize the attribute, __foo__ becomes foo.
@@ -1660,7 +1600,7 @@ static bool normalizeName(StringRef &AttrName) {
return false;
}
-static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
+static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This attribute must be applied to a function declaration. The first
// argument to the attribute must be an identifier, the name of the resource,
// for example: malloc. The following arguments must be argument indexes, the
@@ -1706,15 +1646,15 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
Module = &S.PP.getIdentifierTable().get(ModuleName);
}
- SmallVector<unsigned, 8> OwnershipArgs;
+ SmallVector<ParamIdx, 8> OwnershipArgs;
for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
Expr *Ex = AL.getArgAsExpr(i);
- uint64_t Idx;
+ ParamIdx Idx;
if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodParamType(D, Idx);
+ QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex());
int Err = -1; // No error
switch (K) {
case OwnershipAttr::Takes:
@@ -1745,14 +1685,13 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
} else if (K == OwnershipAttr::Returns &&
I->getOwnKind() == OwnershipAttr::Returns) {
// A returns attribute conflicts with any other returns attribute using
- // a different index. Note, diagnostic reporting is 1-based, but stored
- // argument indexes are 0-based.
+ // a different index.
if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
- << *(I->args_begin()) + 1;
+ << I->args_begin()->getSourceIndex();
if (I->args_size())
S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
- << (unsigned)Idx + 1 << Ex->getSourceRange();
+ << Idx.getSourceIndex() << Ex->getSourceRange();
return;
}
}
@@ -1760,25 +1699,22 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
OwnershipArgs.push_back(Idx);
}
- unsigned* start = OwnershipArgs.data();
- unsigned size = OwnershipArgs.size();
- llvm::array_pod_sort(start, start + size);
-
+ ParamIdx *Start = OwnershipArgs.data();
+ unsigned Size = OwnershipArgs.size();
+ llvm::array_pod_sort(Start, Start + Size);
D->addAttr(::new (S.Context)
- OwnershipAttr(AL.getLoc(), S.Context, Module, start, size,
- AL.getAttributeSpellingListIndex()));
+ OwnershipAttr(AL.getLoc(), S.Context, Module, Start, Size,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
- NamedDecl *nd = cast<NamedDecl>(D);
-
// gcc rejects
// class c {
// static int a __attribute__((weakref ("v2")));
@@ -1791,8 +1727,8 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// we reject them
const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
if (!Ctx->isFileContext()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context)
- << nd;
+ S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context)
+ << cast<NamedDecl>(D);
return;
}
@@ -1822,88 +1758,71 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// of transforming it into an AliasAttr. The WeakRefAttr never uses the
// StringRef parameter it was given anyway.
StringRef Str;
- if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str))
// GCC will accept anything as the argument of weakref. Should we
// check for an existing decl?
- D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
D->addAttr(::new (S.Context)
- WeakRefAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ WeakRefAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleIFuncAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
// Aliases should be on declarations, not definitions.
const auto *FD = cast<FunctionDecl>(D);
if (FD->isThisDeclarationADefinition()) {
- S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 1;
+ S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1;
return;
}
- D->addAttr(::new (S.Context) IFuncAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) IFuncAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
+ S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin);
return;
}
if (S.Context.getTargetInfo().getTriple().isNVPTX()) {
- S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_nvptx);
+ S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx);
}
// Aliases should be on declarations, not definitions.
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isThisDeclarationADefinition()) {
- S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 0;
+ S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0;
return;
}
} else {
const auto *VD = cast<VarDecl>(D);
if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) {
- S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD << 0;
+ S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0;
return;
}
}
// FIXME: check if target symbol exists in current file
- D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<HotAttr>(S, D, Attr.getRange(), Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr.getRange(), Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleTLSModelAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Model;
SourceLocation LiteralLoc;
// Check that it is a string.
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc))
return;
// Check that the value.
@@ -1914,60 +1833,101 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context)
- TLSModelAttr(Attr.getRange(), S.Context, Model,
- Attr.getAttributeSpellingListIndex()));
+ TLSModelAttr(AL.getRange(), S.Context, Model,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
QualType ResultType = getFunctionOrMethodResultType(D);
if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
D->addAttr(::new (S.Context) RestrictAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
}
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName() << getFunctionOrMethodResultSourceRange(D);
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
+ << AL.getName() << getFunctionOrMethodResultSourceRange(D);
+}
+
+static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ return;
+
+ SmallVector<IdentifierInfo *, 8> CPUs;
+ for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) {
+ if (!AL.isArgIdent(ArgNo)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo);
+ StringRef CPUName = CPUArg->Ident->getName().trim();
+
+ if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) {
+ S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value)
+ << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch);
+ return;
+ }
+
+ const TargetInfo &Target = S.Context.getTargetInfo();
+ if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) {
+ return Target.CPUSpecificManglingCharacter(CPUName) ==
+ Target.CPUSpecificManglingCharacter(Cur->getName());
+ })) {
+ S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries);
+ return;
+ }
+ CPUs.push_back(CPUArg->Ident);
+ }
+
+ FD->setIsMultiVersion(true);
+ if (AL.getKind() == ParsedAttr::AT_CPUSpecific)
+ D->addAttr(::new (S.Context) CPUSpecificAttr(
+ AL.getRange(), S.Context, CPUs.data(), CPUs.size(),
+ AL.getAttributeSpellingListIndex()));
+ else
+ D->addAttr(::new (S.Context) CPUDispatchAttr(
+ AL.getRange(), S.Context, CPUs.data(), CPUs.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::Cpp;
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << AL.getName() << AttributeLangSupport::Cpp;
return;
}
- if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), Attr.getName(),
- Attr.getAttributeSpellingListIndex()))
+ if (CommonAttr *CA = S.mergeCommonAttr(D, AL.getRange(), AL.getName(),
+ AL.getAttributeSpellingListIndex()))
D->addAttr(CA);
}
-static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
- if (Attr.isDeclspecAttribute()) {
+ if (AL.isDeclspecAttribute()) {
const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
const auto &Arch = Triple.getArch();
if (Arch != llvm::Triple::x86 &&
(Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_on_arch)
- << Attr.getName() << Triple.getArchName();
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch)
+ << AL.getName() << Triple.getArchName();
return;
}
}
- D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) NakedAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
+static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
if (hasDeclarator(D)) return;
- if (S.CheckNoReturnAttr(Attrs))
- return;
-
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attrs.getName() << ExpectedFunctionOrMethod;
@@ -1978,16 +1938,14 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
-static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (S.CheckNoCallerSavedRegsAttr(Attr))
- return;
-
- D->addAttr(::new (S.Context) AnyX86NoCallerSavedRegistersAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
+ if (!S.getLangOpts().CFProtectionBranch)
+ S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
+ else
+ handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs);
}
-bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
+bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
if (!checkAttributeNumArgs(*this, Attrs, 0)) {
Attrs.setInvalid();
return true;
@@ -1996,221 +1954,167 @@ bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
return false;
}
-bool Sema::CheckNoCallerSavedRegsAttr(const AttributeList &Attr) {
+bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
// Check whether the attribute is valid on the current target.
- if (!Attr.existsInTarget(Context.getTargetInfo())) {
- Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) << Attr.getName();
- Attr.setInvalid();
- return true;
- }
-
- if (!checkAttributeNumArgs(*this, Attr, 0)) {
- Attr.setInvalid();
+ if (!AL.existsInTarget(Context.getTargetInfo())) {
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
+ AL.setInvalid();
return true;
}
return false;
}
-static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
-
+static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+
// The checking path for 'noreturn' and 'analyzer_noreturn' are different
// because 'analyzer_noreturn' does not impact the type.
if (!isFunctionOrMethodOrBlock(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || (!VD->getType()->isBlockPointerType() &&
!VD->getType()->isFunctionPointerType())) {
- S.Diag(Attr.getLoc(),
- Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
+ S.Diag(AL.getLoc(),
+ AL.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrBlock;
+ << AL.getName() << ExpectedFunctionMethodOrBlock;
return;
}
}
-
+
D->addAttr(::new (S.Context)
- AnalyzerNoReturnAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ AnalyzerNoReturnAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
// PS3 PPU-specific.
-static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-/*
- Returning a Vector Class in Registers
-
- According to the PPU ABI specifications, a class with a single member of
- vector type is returned in memory when used as the return value of a function.
- This results in inefficient code when implementing vector classes. To return
- the value in a single vector register, add the vecreturn attribute to the
- class definition. This attribute is also applicable to struct types.
-
- Example:
-
- struct Vector
- {
- __vector float xyzw;
- } __attribute__((vecreturn));
-
- Vector Add(Vector lhs, Vector rhs)
- {
- Vector result;
- result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
- return result; // This will be returned in a register
- }
-*/
+static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ /*
+ Returning a Vector Class in Registers
+
+ According to the PPU ABI specifications, a class with a single member of
+ vector type is returned in memory when used as the return value of a
+ function.
+ This results in inefficient code when implementing vector classes. To return
+ the value in a single vector register, add the vecreturn attribute to the
+ class definition. This attribute is also applicable to struct types.
+
+ Example:
+
+ struct Vector
+ {
+ __vector float xyzw;
+ } __attribute__((vecreturn));
+
+ Vector Add(Vector lhs, Vector rhs)
+ {
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will be returned in a register
+ }
+ */
if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << A;
+ S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A;
return;
}
- RecordDecl *record = cast<RecordDecl>(D);
+ const auto *R = cast<RecordDecl>(D);
int count = 0;
- if (!isa<CXXRecordDecl>(record)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+ if (!isa<CXXRecordDecl>(R)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
return;
}
- if (!cast<CXXRecordDecl>(record)->isPOD()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
+ if (!cast<CXXRecordDecl>(R)->isPOD()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
return;
}
- for (const auto *I : record->fields()) {
+ for (const auto *I : R->fields()) {
if ((count == 1) || !I->getType()->isVectorType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+ S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
return;
}
count++;
}
- D->addAttr(::new (S.Context)
- VecReturnAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) VecReturnAttr(
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
if (isa<ParmVarDecl>(D)) {
// [[carries_dependency]] can only be applied to a parameter if it is a
// parameter of a function declaration or lambda.
if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::err_carries_dependency_param_not_function_decl);
return;
}
}
D->addAttr(::new (S.Context) CarriesDependencyAttr(
- Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleNotTailCalledAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) NotTailCalledAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleDisableTailCallsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<NakedAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) DisableTailCallsAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
- } else if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- UsedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- bool IsCXX17Attr = Attr.isCXX11Attribute() && !Attr.getScopeName();
-
- 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)
- << Attr.getName() << ExpectedForMaybeUnused;
- return;
- }
- }
+static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName();
// 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().CPlusPlus17 && IsCXX17Attr)
- S.Diag(Attr.getLoc(), diag::ext_cxx17_attr) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName();
D->addAttr(::new (S.Context) UnusedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t priority = ConstructorAttr::DefaultPriority;
- if (Attr.getNumArgs() &&
- !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
+ if (AL.getNumArgs() &&
+ !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
return;
D->addAttr(::new (S.Context)
- ConstructorAttr(Attr.getRange(), S.Context, priority,
- Attr.getAttributeSpellingListIndex()));
+ ConstructorAttr(AL.getRange(), S.Context, priority,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t priority = DestructorAttr::DefaultPriority;
- if (Attr.getNumArgs() &&
- !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
+ if (AL.getNumArgs() &&
+ !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
return;
D->addAttr(::new (S.Context)
- DestructorAttr(Attr.getRange(), S.Context, priority,
- Attr.getAttributeSpellingListIndex()));
+ DestructorAttr(AL.getRange(), S.Context, priority,
+ AL.getAttributeSpellingListIndex()));
}
template <typename AttrTy>
-static void handleAttrWithMessage(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) {
// Handle the case where the attribute has a text message.
StringRef Str;
- if (Attr.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
- D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AttrTy(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
- S.Diag(Attr.getLoc(), diag::err_objc_attr_protocol_requires_definition)
- << Attr.getName() << Attr.getRange();
+ S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
+ << AL.getName() << AL.getRange();
return;
}
D->addAttr(::new (S.Context)
- ObjCExplicitProtocolImplAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCExplicitProtocolImplAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
@@ -2252,7 +2156,7 @@ static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
return false;
}
-/// \brief Check whether the two versions match.
+/// Check whether the two versions match.
///
/// If either version tuple is empty, then they are assumed to match. If
/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
@@ -2302,7 +2206,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
for (unsigned i = 0, e = Attrs.size(); i != e;) {
- const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
+ const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
if (!OldAA) {
++i;
continue;
@@ -2434,37 +2338,34 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
return nullptr;
}
-static void handleAvailabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
+static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeNumArgs(S, AL, 1))
return;
- IdentifierLoc *Platform = Attr.getArgAsIdent(0);
- unsigned Index = Attr.getAttributeSpellingListIndex();
-
+ IdentifierLoc *Platform = AL.getArgAsIdent(0);
+ unsigned Index = AL.getAttributeSpellingListIndex();
+
IdentifierInfo *II = Platform->Ident;
if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
<< Platform->Ident;
- NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ auto *ND = dyn_cast<NamedDecl>(D);
if (!ND) // We warned about this already, so just return.
return;
- AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
- AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
- AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
- bool IsUnavailable = Attr.getUnavailableLoc().isValid();
- bool IsStrict = Attr.getStrictLoc().isValid();
+ AvailabilityChange Introduced = AL.getAvailabilityIntroduced();
+ AvailabilityChange Deprecated = AL.getAvailabilityDeprecated();
+ AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted();
+ bool IsUnavailable = AL.getUnavailableLoc().isValid();
+ bool IsStrict = AL.getStrictLoc().isValid();
StringRef Str;
- if (const StringLiteral *SE =
- dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr()))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr()))
Str = SE->getString();
StringRef Replacement;
- if (const StringLiteral *SE =
- dyn_cast_or_null<StringLiteral>(Attr.getReplacementExpr()))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr()))
Replacement = SE->getString();
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II,
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II,
false/*Implicit*/,
Introduced.Version,
Deprecated.Version,
@@ -2509,7 +2410,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
- Attr.getRange(),
+ AL.getRange(),
NewII,
true/*Implicit*/,
NewIntroduced,
@@ -2534,7 +2435,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
if (NewII) {
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
- Attr.getRange(),
+ AL.getRange(),
NewII,
true/*Implicit*/,
Introduced.Version,
@@ -2552,23 +2453,23 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
}
static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
- assert(checkAttributeAtMostNumArgs(S, Attr, 3) &&
+ assert(checkAttributeAtMostNumArgs(S, AL, 3) &&
"Invalid number of arguments in an external_source_symbol attribute");
StringRef Language;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(0)))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0)))
Language = SE->getString();
StringRef DefinedIn;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(1)))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1)))
DefinedIn = SE->getString();
- bool IsGeneratedDeclaration = Attr.getArgAsIdent(2) != nullptr;
+ bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr;
D->addAttr(::new (S.Context) ExternalSourceSymbolAttr(
- Attr.getRange(), S.Context, Language, DefinedIn, IsGeneratedDeclaration,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Language, DefinedIn, IsGeneratedDeclaration,
+ AL.getAttributeSpellingListIndex()));
}
template <class T>
@@ -2601,12 +2502,12 @@ TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
-static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
+static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
bool isTypeVisibility) {
// Visibility attributes don't mean anything on a typedef.
if (isa<TypedefNameDecl>(D)) {
- S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored)
- << Attr.getName();
+ S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored)
+ << AL.getName();
return;
}
@@ -2615,84 +2516,82 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
!(isa<TagDecl>(D) ||
isa<ObjCInterfaceDecl>(D) ||
isa<NamespaceDecl>(D))) {
- S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedTypeOrNamespace;
+ S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedTypeOrNamespace;
return;
}
// Check that the argument is a string literal.
StringRef TypeStr;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc))
return;
VisibilityAttr::VisibilityType type;
if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << TypeStr;
+ << AL.getName() << TypeStr;
return;
}
-
+
// Complain about attempts to use protected visibility on targets
// (like Darwin) that don't support it.
if (type == VisibilityAttr::Protected &&
!S.Context.getTargetInfo().hasProtectedVisibility()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
+ S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility);
type = VisibilityAttr::Default;
}
- unsigned Index = Attr.getAttributeSpellingListIndex();
- clang::Attr *newAttr;
+ unsigned Index = AL.getAttributeSpellingListIndex();
+ Attr *newAttr;
if (isTypeVisibility) {
- newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(),
+ newAttr = S.mergeTypeVisibilityAttr(D, AL.getRange(),
(TypeVisibilityAttr::VisibilityType) type,
Index);
} else {
- newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index);
+ newAttr = S.mergeVisibilityAttr(D, AL.getRange(), type, Index);
}
if (newAttr)
D->addAttr(newAttr);
}
-static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
- const AttributeList &Attr) {
- ObjCMethodDecl *method = cast<ObjCMethodDecl>(decl);
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ const auto *M = cast<ObjCMethodDecl>(D);
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
- IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ IdentifierLoc *IL = AL.getArgAsIdent(0);
ObjCMethodFamilyAttr::FamilyKind F;
if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName()
- << IL->Ident;
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
+ << AL.getName() << IL->Ident;
return;
}
if (F == ObjCMethodFamilyAttr::OMF_init &&
- !method->getReturnType()->isObjCObjectPointerType()) {
- S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
- << method->getReturnType();
+ !M->getReturnType()->isObjCObjectPointerType()) {
+ S.Diag(M->getLocation(), diag::err_init_method_bad_return_type)
+ << M->getReturnType();
// Ignore the attribute.
return;
}
- method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
- S.Context, F,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(new (S.Context) ObjCMethodFamilyAttr(
+ AL.getRange(), S.Context, F, AL.getAttributeSpellingListIndex()));
}
-static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isCARCBridgableType()) {
S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
return;
}
}
- else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+ else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
QualType T = PD->getType();
if (!T->isCARCBridgableType()) {
S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
@@ -2705,16 +2604,16 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
// @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
//
// In this case it follows tradition and suppresses an error in the above
- // case.
+ // case.
S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
}
D->addAttr(::new (S.Context)
- ObjCNSObjectAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCNSObjectAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &Attr) {
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isObjCObjectPointerType()) {
S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
@@ -2725,45 +2624,45 @@ static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &At
return;
}
D->addAttr(::new (S.Context)
- ObjCIndependentClassAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCIndependentClassAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
- IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
BlocksAttr::BlockType type;
if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << II;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << II;
return;
}
D->addAttr(::new (S.Context)
- BlocksAttr(Attr.getRange(), S.Context, type,
- Attr.getAttributeSpellingListIndex()));
+ BlocksAttr(AL.getRange(), S.Context, type,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
- if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.getArgAsExpr(0);
+ if (AL.getNumArgs() > 0) {
+ Expr *E = AL.getArgAsExpr(0);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
return;
}
if (Idx.isSigned() && Idx.isNegative()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
+ S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
<< E->getSourceRange();
return;
}
@@ -2772,13 +2671,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
- if (Attr.getNumArgs() > 1) {
- Expr *E = Attr.getArgAsExpr(1);
+ if (AL.getNumArgs() > 1) {
+ Expr *E = AL.getArgAsExpr(1);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 2 << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
return;
}
@@ -2787,34 +2686,34 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) {
// FIXME: This error message could be improved, it would be nice
// to say what the bounds actually are.
- S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
+ S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
<< E->getSourceRange();
return;
}
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
const FunctionType *FT = FD->getType()->castAs<FunctionType>();
if (isa<FunctionNoProtoType>(FT)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments);
return;
}
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
return;
}
- } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (!MD->isVariadic()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
return;
}
- } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
if (!BD->isVariadic()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
return;
}
- } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
+ } else if (const auto *V = dyn_cast<VarDecl>(D)) {
QualType Ty = V->getType();
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
const FunctionType *FT = Ty->isFunctionPointerType()
@@ -2822,84 +2721,83 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
: Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
int m = Ty->isFunctionPointerType() ? 0 : 1;
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrBlock;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionMethodOrBlock;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrBlock;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionMethodOrBlock;
return;
}
D->addAttr(::new (S.Context)
- SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos,
- Attr.getAttributeSpellingListIndex()));
+ SentinelAttr(AL.getRange(), S.Context, sentinel, nullPos,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->getFunctionType() &&
D->getFunctionType()->getReturnType()->isVoidType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
- << Attr.getName() << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method)
+ << AL.getName() << 0;
return;
}
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
if (MD->getReturnType()->isVoidType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
- << Attr.getName() << 1;
+ S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method)
+ << AL.getName() << 1;
return;
}
-
+
// 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().CPlusPlus17 && Attr.isCXX11Attribute() &&
- !Attr.getScopeName())
- S.Diag(Attr.getLoc(), diag::ext_cxx17_attr) << Attr.getName();
+ if (!S.getLangOpts().CPlusPlus17 && AL.isCXX11Attribute() &&
+ !AL.getScopeName())
+ S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName();
- D->addAttr(::new (S.Context)
- WarnUnusedResultAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context)
+ WarnUnusedResultAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// weak_import only applies to variable & function declarations.
bool isDef = false;
if (!D->canBeWeakImported(isDef)) {
if (isDef)
- S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition)
+ S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition)
<< "weak_import";
else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
(S.Context.getTargetInfo().getTriple().isOSDarwin() &&
(isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
// Nothing to warn about here.
} else
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedVariableOrFunction;
return;
}
D->addAttr(::new (S.Context)
- WeakImportAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ WeakImportAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
// Handles reqd_work_group_size and work_group_size_hint.
template <typename WorkGroupAttr>
-static void handleWorkGroupSize(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t WGSize[3];
for (unsigned i = 0; i < 3; ++i) {
- const Expr *E = Attr.getArgAsExpr(i);
- if (!checkUInt32Argument(S, Attr, E, WGSize[i], i))
+ const Expr *E = AL.getArgAsExpr(i);
+ if (!checkUInt32Argument(S, AL, E, WGSize[i], i))
return;
if (WGSize[i] == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
- << Attr.getName() << E->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
+ << AL.getName() << E->getSourceRange();
return;
}
}
@@ -2908,73 +2806,81 @@ static void handleWorkGroupSize(Sema &S, Decl *D,
if (Existing && !(Existing->getXDim() == WGSize[0] &&
Existing->getYDim() == WGSize[1] &&
Existing->getZDim() == WGSize[2]))
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
- D->addAttr(::new (S.Context) WorkGroupAttr(Attr.getRange(), S.Context,
+ D->addAttr(::new (S.Context) WorkGroupAttr(AL.getRange(), S.Context,
WGSize[0], WGSize[1], WGSize[2],
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
// Handles intel_reqd_sub_group_size.
-static void handleSubGroupSize(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t SGSize;
- const Expr *E = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, E, SGSize))
+ const Expr *E = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, E, SGSize))
return;
if (SGSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
- << Attr.getName() << E->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
+ << AL.getName() << E->getSourceRange();
return;
}
OpenCLIntelReqdSubGroupSizeAttr *Existing =
D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
if (Existing && Existing->getSubGroupSize() != SGSize)
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
D->addAttr(::new (S.Context) OpenCLIntelReqdSubGroupSizeAttr(
- Attr.getRange(), S.Context, SGSize,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, SGSize,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.hasParsedType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.hasParsedType()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
TypeSourceInfo *ParmTSI = nullptr;
- QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI);
+ QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
assert(ParmTSI && "no type source info for attribute argument");
if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
(ParmType->isBooleanType() ||
!ParmType->isIntegralType(S.getASTContext()))) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint)
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_vec_type_hint)
<< ParmType;
return;
}
if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
return;
}
}
- D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
+ D->addAttr(::new (S.Context) VecTypeHintAttr(AL.getLoc(), S.Context,
ParmTSI,
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
StringRef Name,
unsigned AttrSpellingListIndex) {
+ // Explicit or partial specializations do not inherit
+ // the section attribute from the primary template.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (AttrSpellingListIndex == SectionAttr::Declspec_allocate &&
+ FD->isFunctionTemplateSpecialization())
+ return nullptr;
+ }
if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
if (ExistingAttr->getName() == Name)
return nullptr;
- Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section);
+ Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
+ << 1 /*section*/;
Diag(Range.getBegin(), diag::note_previous_attribute);
return nullptr;
}
@@ -2985,18 +2891,19 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
if (!Error.empty()) {
- Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error;
+ Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
+ << 1 /*'section'*/;
return false;
}
return true;
}
-static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Make sure that there is a string literal as the sections's single
// argument.
StringRef Str;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
return;
if (!S.checkSectionName(LiteralLoc, Str))
@@ -3010,12 +2917,65 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- unsigned Index = Attr.getAttributeSpellingListIndex();
- SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
+ unsigned Index = AL.getAttributeSpellingListIndex();
+ SectionAttr *NewAttr = S.mergeSectionAttr(D, AL.getRange(), Str, Index);
if (NewAttr)
D->addAttr(NewAttr);
}
+static bool checkCodeSegName(Sema&S, SourceLocation LiteralLoc, StringRef CodeSegName) {
+ std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName);
+ if (!Error.empty()) {
+ S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
+ << 0 /*'code-seg'*/;
+ return false;
+ }
+ return true;
+}
+
+CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, SourceRange Range,
+ StringRef Name,
+ unsigned AttrSpellingListIndex) {
+ // Explicit or partial specializations do not inherit
+ // the code_seg attribute from the primary template.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isFunctionTemplateSpecialization())
+ return nullptr;
+ }
+ if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
+ if (ExistingAttr->getName() == Name)
+ return nullptr;
+ Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
+ << 0 /*codeseg*/;
+ Diag(Range.getBegin(), diag::note_previous_attribute);
+ return nullptr;
+ }
+ return ::new (Context) CodeSegAttr(Range, Context, Name,
+ AttrSpellingListIndex);
+}
+
+static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Str;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
+ return;
+ if (!checkCodeSegName(S, LiteralLoc, Str))
+ return;
+ if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
+ if (!ExistingAttr->isImplicit()) {
+ S.Diag(AL.getLoc(),
+ ExistingAttr->getName() == Str
+ ? diag::warn_duplicate_codeseg_attribute
+ : diag::err_conflicting_codeseg_attribute);
+ return;
+ }
+ D->dropAttr<CodeSegAttr>();
+ }
+ if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL.getRange(), Str,
+ AL.getAttributeSpellingListIndex()))
+ D->addAttr(CSA);
+}
+
// 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) {
@@ -3044,30 +3004,50 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
<< Unsupported << None << CurFeature;
}
- return true;
+ return false;
}
-static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc) ||
- !S.checkTargetAttr(LiteralLoc, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
+ S.checkTargetAttr(LiteralLoc, Str))
return;
- unsigned Index = Attr.getAttributeSpellingListIndex();
+
+ unsigned Index = AL.getAttributeSpellingListIndex();
TargetAttr *NewAttr =
- ::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index);
+ ::new (S.Context) TargetAttr(AL.getRange(), S.Context, Str, Index);
D->addAttr(NewAttr);
}
-static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- Expr *E = Attr.getArgAsExpr(0);
+static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *E = AL.getArgAsExpr(0);
+ uint32_t VecWidth;
+ if (!checkUInt32Argument(S, AL, E, VecWidth)) {
+ AL.setInvalid();
+ return;
+ }
+
+ MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>();
+ if (Existing && Existing->getVectorWidth() != VecWidth) {
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ MinVectorWidthAttr(AL.getRange(), S.Context, VecWidth,
+ AL.getAttributeSpellingListIndex()));
+}
+
+static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *E = AL.getArgAsExpr(0);
SourceLocation Loc = E->getExprLoc();
FunctionDecl *FD = nullptr;
DeclarationNameInfo NI;
// gcc only allows for simple identifiers. Since we support more than gcc, we
// will warn the user.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
if (DRE->hasQualifier())
S.Diag(Loc, diag::warn_cleanup_ext);
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
@@ -3077,7 +3057,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
<< NI.getName();
return;
}
- } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
if (ULE->hasExplicitTemplateArgs())
S.Diag(Loc, diag::warn_cleanup_ext);
FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
@@ -3112,49 +3092,49 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
D->addAttr(::new (S.Context)
- CleanupAttr(Attr.getRange(), S.Context, FD,
- Attr.getAttributeSpellingListIndex()));
+ CleanupAttr(AL.getRange(), S.Context, FD,
+ AL.getAttributeSpellingListIndex()));
}
static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 0 << AANT_ArgumentIdentifier;
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 0 << AANT_ArgumentIdentifier;
return;
}
EnumExtensibilityAttr::Kind ExtensibilityKind;
- IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(),
ExtensibilityKind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << II;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << II;
return;
}
D->addAttr(::new (S.Context) EnumExtensibilityAttr(
- Attr.getRange(), S.Context, ExtensibilityKind,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, ExtensibilityKind,
+ AL.getAttributeSpellingListIndex()));
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
-static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- Expr *IdxExpr = Attr.getArgAsExpr(0);
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
+static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *IdxExpr = AL.getArgAsExpr(0);
+ ParamIdx Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx))
return;
// Make sure the format string is really a string.
- QualType Ty = getFunctionOrMethodParamType(D, Idx);
+ QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
bool NotNSStringTy = !isNSStringType(Ty, S.Context);
if (NotNSStringTy &&
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "a string type" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, 0);
return;
@@ -3164,21 +3144,14 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_result_not)
<< (NotNSStringTy ? "string type" : "NSString")
<< IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
return;
}
- // We cannot use the Idx returned from checkFunctionOrMethodParameterIndex
- // because that has corrected for the implicit this parameter, and is zero-
- // based. The attribute expects what the user wrote explicitly.
- llvm::APSInt Val;
- IdxExpr->EvaluateAsInt(Val, S.Context);
-
- D->addAttr(::new (S.Context)
- FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) FormatArgAttr(
+ AL.getRange(), S.Context, Idx, AL.getAttributeSpellingListIndex()));
}
enum FormatAttrKind {
@@ -3213,43 +3186,42 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) {
/// Handle __attribute__((init_priority(priority))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
-static void handleInitPriorityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.getLangOpts().CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName();
return;
}
-
+
if (S.getCurFunctionOrMethodDecl()) {
- S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
- Attr.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
+ AL.setInvalid();
return;
}
QualType T = cast<VarDecl>(D)->getType();
if (S.Context.getAsArrayType(T))
T = S.Context.getBaseElementType(T);
if (!T->getAs<RecordType>()) {
- S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
- Attr.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
+ AL.setInvalid();
return;
}
- Expr *E = Attr.getArgAsExpr(0);
+ Expr *E = AL.getArgAsExpr(0);
uint32_t prioritynum;
- if (!checkUInt32Argument(S, Attr, E, prioritynum)) {
- Attr.setInvalid();
+ if (!checkUInt32Argument(S, AL, E, prioritynum)) {
+ AL.setInvalid();
return;
}
if (prioritynum < 101 || prioritynum > 65535) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
- << E->getSourceRange() << Attr.getName() << 101 << 65535;
- Attr.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_outof_range)
+ << E->getSourceRange() << AL.getName() << 101 << 65535;
+ AL.setInvalid();
return;
}
D->addAttr(::new (S.Context)
- InitPriorityAttr(Attr.getRange(), S.Context, prioritynum,
- Attr.getAttributeSpellingListIndex()));
+ InitPriorityAttr(AL.getRange(), S.Context, prioritynum,
+ AL.getAttributeSpellingListIndex()));
}
FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
@@ -3275,10 +3247,10 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
-static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
@@ -3287,7 +3259,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
bool HasImplicitThisParam = isInstanceMethod(D);
unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
- IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
StringRef Format = II->getName();
if (normalizeName(Format)) {
@@ -3297,25 +3269,25 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Check for supported formats.
FormatAttrKind Kind = getFormatAttrKind(Format);
-
+
if (Kind == IgnoredFormat)
return;
-
+
if (Kind == InvalidFormat) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << II->getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << II->getName();
return;
}
// checks for the 2nd argument
- Expr *IdxExpr = Attr.getArgAsExpr(1);
+ Expr *IdxExpr = AL.getArgAsExpr(1);
uint32_t Idx;
- if (!checkUInt32Argument(S, Attr, IdxExpr, Idx, 2))
+ if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2))
return;
if (Idx < 1 || Idx > NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << 2 << IdxExpr->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << 2 << IdxExpr->getSourceRange();
return;
}
@@ -3324,7 +3296,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (HasImplicitThisParam) {
if (ArgIdx == 0) {
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::err_format_attribute_implicit_this_format_string)
<< IdxExpr->getSourceRange();
return;
@@ -3337,7 +3309,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "a CFString" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
return;
@@ -3346,23 +3318,23 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// FIXME: do we need to check if the type is NSString*? What are the
// semantics?
if (!isNSStringType(Ty, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "an NSString" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
} else if (!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "a string type" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
// check the 3rd argument
- Expr *FirstArgExpr = Attr.getArgAsExpr(2);
+ Expr *FirstArgExpr = AL.getArgAsExpr(2);
uint32_t FirstArg;
- if (!checkUInt32Argument(S, Attr, FirstArgExpr, FirstArg, 3))
+ if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3))
return;
// check if the function is variadic if the 3rd argument non-zero
@@ -3379,43 +3351,42 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// variable the input is just the current time + the format string.
if (Kind == StrftimeFormat) {
if (FirstArg != 0) {
- S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
+ S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter)
<< FirstArgExpr->getSourceRange();
return;
}
// if 0 it disables parameter checking (to use with e.g. va_list)
} else if (FirstArg != 0 && FirstArg != NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << 3 << FirstArgExpr->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << 3 << FirstArgExpr->getSourceRange();
return;
}
- FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,
+ FormatAttr *NewAttr = S.mergeFormatAttr(D, AL.getRange(), II,
Idx, FirstArg,
- Attr.getAttributeSpellingListIndex());
+ AL.getAttributeSpellingListIndex());
if (NewAttr)
D->addAttr(NewAttr);
}
-static void handleTransparentUnionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Try to find the underlying union declaration.
RecordDecl *RD = nullptr;
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ const auto *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && TD->getUnderlyingType()->isUnionType())
RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
else
RD = dyn_cast<RecordDecl>(D);
if (!RD || !RD->isUnion()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedUnion;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedUnion;
return;
}
if (!RD->isCompleteDefinition()) {
if (!RD->isBeingDefined())
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::warn_transparent_union_attribute_not_definition);
return;
}
@@ -3423,7 +3394,7 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end();
if (Field == FieldEnd) {
- S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
+ S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
return;
}
@@ -3467,15 +3438,15 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
}
RD->addAttr(::new (S.Context)
- TransparentUnionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ TransparentUnionAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Make sure that there is a string literal as the annotation's single
// argument.
StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
// Don't duplicate annotations that are already set.
@@ -3483,16 +3454,15 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (I->getAnnotation() == Str)
return;
}
-
+
D->addAttr(::new (S.Context)
- AnnotateAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ AnnotateAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAlignValueAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- S.AddAlignValueAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
- Attr.getAttributeSpellingListIndex());
+static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.AddAlignValueAttr(AL.getRange(), D, AL.getArgAsExpr(0),
+ AL.getAttributeSpellingListIndex());
}
void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
@@ -3501,9 +3471,9 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
SourceLocation AttrLoc = AttrRange.getBegin();
QualType T;
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
T = TD->getUnderlyingType();
- else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ else if (const auto *VD = dyn_cast<ValueDecl>(D))
T = VD->getType();
else
llvm_unreachable("Unknown decl type for align_value");
@@ -3540,42 +3510,32 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
D->addAttr(::new (Context) AlignValueAttr(TmpAttr));
}
-static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
- if (Attr.getNumArgs() == 0) {
- D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
- true, nullptr, Attr.getAttributeSpellingListIndex()));
+ if (AL.getNumArgs() == 0) {
+ D->addAttr(::new (S.Context) AlignedAttr(AL.getRange(), S.Context,
+ true, nullptr, AL.getAttributeSpellingListIndex()));
return;
}
- Expr *E = Attr.getArgAsExpr(0);
- if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
- S.Diag(Attr.getEllipsisLoc(),
+ Expr *E = AL.getArgAsExpr(0);
+ if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
+ S.Diag(AL.getEllipsisLoc(),
diag::err_pack_expansion_without_parameter_packs);
return;
}
- if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
+ if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
return;
- if (E->isValueDependent()) {
- if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
- if (!TND->getUnderlyingType()->isDependentType()) {
- S.Diag(Attr.getLoc(), diag::err_alignment_dependent_typedef_name)
- << E->getSourceRange();
- return;
- }
- }
- }
-
- S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(),
- Attr.isPackExpansion());
+ S.AddAlignedAttr(AL.getRange(), D, E, AL.getAttributeSpellingListIndex(),
+ AL.isPackExpansion());
}
void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
@@ -3599,12 +3559,12 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
int DiagKind = -1;
if (isa<ParmVarDecl>(D)) {
DiagKind = 0;
- } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->getStorageClass() == SC_Register)
DiagKind = 1;
if (VD->isExceptionVariable())
DiagKind = 2;
- } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
if (FD->isBitField())
DiagKind = 3;
} else if (!isa<TagDecl>(D)) {
@@ -3620,7 +3580,18 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
}
}
- if (E->isTypeDependent() || E->isValueDependent()) {
+ if (E->isValueDependent()) {
+ // We can't support a dependent alignment on a non-dependent type,
+ // because we have no way to model that a type is "alignment-dependent"
+ // but not dependent in any other way.
+ if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
+ if (!TND->getUnderlyingType()->isDependentType()) {
+ Diag(AttrLoc, diag::err_alignment_dependent_typedef_name)
+ << E->getSourceRange();
+ return;
+ }
+ }
+
// Save dependent expressions in the AST to be instantiated.
AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr);
AA->setPackExpansion(IsPackExpansion);
@@ -3628,7 +3599,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
return;
}
- // FIXME: Cache the number on the Attr object?
+ // FIXME: Cache the number on the AL object?
llvm::APSInt Alignment;
ExprResult ICE
= VerifyIntegerConstantExpression(E, &Alignment,
@@ -3666,7 +3637,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
unsigned MaxTLSAlign =
Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
.getQuantity();
- auto *VD = dyn_cast<VarDecl>(D);
+ const auto *VD = dyn_cast<VarDecl>(D);
if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
VD->getTLSKind() != VarDecl::TLS_None) {
Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
@@ -3683,7 +3654,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
unsigned SpellingListIndex, bool IsPackExpansion) {
- // FIXME: Cache the number on the Attr object if non-dependent?
+ // FIXME: Cache the number on the AL object if non-dependent?
// FIXME: Perform checking of type validity
AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS,
SpellingListIndex);
@@ -3695,11 +3666,11 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
assert(D->hasAttrs() && "no attributes on decl");
QualType UnderlyingTy, DiagTy;
- if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ if (const auto *VD = dyn_cast<ValueDecl>(D)) {
UnderlyingTy = DiagTy = VD->getType();
} else {
UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
- if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
+ if (const auto *ED = dyn_cast<EnumDecl>(D))
UnderlyingTy = ED->getIntegerType();
}
if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
@@ -3819,18 +3790,18 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
/// Despite what would be logical, the mode attribute is a decl attribute, not a
/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
/// HImode, not an intermediate pointer.
-static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This attribute isn't documented, but glibc uses it. It changes
// the width of an int or unsigned int to the specified size.
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName()
<< AANT_ArgumentIdentifier;
return;
}
- IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident;
- S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
+ S.AddModeAttr(AL.getRange(), D, Name, AL.getAttributeSpellingListIndex());
}
void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
@@ -3876,9 +3847,9 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
}
QualType OldTy;
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
OldTy = TD->getUnderlyingType();
- else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
// Try to get type from enum declaration, default to int.
OldTy = ED->getIntegerType();
@@ -3896,7 +3867,7 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
// Base type can also be a vector type (see PR17453).
// Distinguish between base type and base element type.
QualType OldElemTy = OldTy;
- if (const VectorType *VT = OldTy->getAs<VectorType>())
+ if (const auto *VT = OldTy->getAs<VectorType>())
OldElemTy = VT->getElementType();
// GCC allows 'mode' attribute on enumeration types (even incomplete), except
@@ -3945,7 +3916,7 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
if (VectorSize.getBoolValue()) {
NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
VectorType::GenericVector);
- } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
+ } else if (const auto *OldVT = OldTy->getAs<VectorType>()) {
// Complex machine mode does not support base vector types.
if (ComplexMode) {
Diag(AttrLoc, diag::err_complex_mode_vector_type);
@@ -3964,9 +3935,9 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
}
// Install the new type.
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ if (auto *TD = dyn_cast<TypedefNameDecl>(D))
TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
- else if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
+ else if (auto *ED = dyn_cast<EnumDecl>(D))
ED->setIntegerType(NewTy);
else
cast<ValueDecl>(D)->setType(NewTy);
@@ -3975,10 +3946,10 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
ModeAttr(AttrRange, Context, Name, SpellingListIndex));
}
-static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context)
- NoDebugAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ NoDebugAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
@@ -4010,7 +3981,7 @@ InternalLinkageAttr *
Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range,
IdentifierInfo *Ident,
unsigned AttrSpellingListIndex) {
- if (auto VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
// Attribute applies to Var but not any subclass of it (like ParmVar,
// ImplicitParm or VarTemplateSpecialization).
if (VD->getKind() != Decl::Var) {
@@ -4067,71 +4038,70 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
-static void handleAlwaysInlineAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
- D, Attr.getRange(), Attr.getName(),
- Attr.getAttributeSpellingListIndex()))
+ D, AL.getRange(), AL.getName(),
+ AL.getAttributeSpellingListIndex()))
D->addAttr(Inline);
}
-static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(
- D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
+ D, AL.getRange(), AL.getAttributeSpellingListIndex()))
D->addAttr(MinSize);
}
-static void handleOptimizeNoneAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(
- D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
+ D, AL.getRange(), AL.getAttributeSpellingListIndex()))
D->addAttr(Optnone);
}
-static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
- auto *VD = cast<VarDecl>(D);
+ const auto *VD = cast<VarDecl>(D);
if (!VD->hasGlobalStorage()) {
- S.Diag(Attr.getLoc(), diag::err_cuda_nonglobal_constant);
+ S.Diag(AL.getLoc(), diag::err_cuda_nonglobal_constant);
return;
}
D->addAttr(::new (S.Context) CUDAConstantAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
- auto *VD = cast<VarDecl>(D);
+ const auto *VD = cast<VarDecl>(D);
// extern __shared__ is only allowed on arrays with no length (e.g.
// "int x[]").
- if (VD->hasExternalStorage() && !isa<IncompleteArrayType>(VD->getType())) {
- S.Diag(Attr.getLoc(), diag::err_cuda_extern_shared) << VD;
+ if (!S.getLangOpts().CUDARelocatableDeviceCode && VD->hasExternalStorage() &&
+ !isa<IncompleteArrayType>(VD->getType())) {
+ S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD;
return;
}
if (S.getLangOpts().CUDA && VD->hasLocalStorage() &&
- S.CUDADiagIfHostCode(Attr.getLoc(), diag::err_cuda_host_shared)
+ S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared)
<< S.CurrentCUDATarget())
return;
D->addAttr(::new (S.Context) CUDASharedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, Attr.getRange(),
- Attr.getName()) ||
- checkAttrMutualExclusion<CUDAHostAttr>(S, D, Attr.getRange(),
- Attr.getName())) {
+static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL.getRange(),
+ AL.getName()) ||
+ checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL.getRange(),
+ AL.getName())) {
return;
}
- FunctionDecl *FD = cast<FunctionDecl>(D);
+ const auto *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isVoidType()) {
SourceRange RTRange = FD->getReturnTypeSourceRange();
S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
@@ -4153,88 +4123,88 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(FD->getLocStart(), diag::warn_kern_is_inline) << FD;
D->addAttr(::new (S.Context)
- CUDAGlobalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ CUDAGlobalAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- FunctionDecl *Fn = cast<FunctionDecl>(D);
+static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ const auto *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
+ S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
}
D->addAttr(::new (S.Context)
- GNUInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ GNUInlineAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (hasDeclarator(D)) return;
- // Diagnostic is emitted elsewhere: here we store the (valid) Attr
+ // Diagnostic is emitted elsewhere: here we store the (valid) AL
// in the Decl node for syntactic reasoning, e.g., pretty-printing.
CallingConv CC;
- if (S.CheckCallingConvAttr(Attr, CC, /*FD*/nullptr))
+ if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr))
return;
if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionOrMethod;
return;
}
- switch (Attr.getKind()) {
- case AttributeList::AT_FastCall:
+ switch (AL.getKind()) {
+ case ParsedAttr::AT_FastCall:
D->addAttr(::new (S.Context)
- FastCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ FastCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_StdCall:
+ case ParsedAttr::AT_StdCall:
D->addAttr(::new (S.Context)
- StdCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ StdCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_ThisCall:
+ case ParsedAttr::AT_ThisCall:
D->addAttr(::new (S.Context)
- ThisCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ThisCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_CDecl:
+ case ParsedAttr::AT_CDecl:
D->addAttr(::new (S.Context)
- CDeclAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ CDeclAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_Pascal:
+ case ParsedAttr::AT_Pascal:
D->addAttr(::new (S.Context)
- PascalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ PascalAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_SwiftCall:
+ case ParsedAttr::AT_SwiftCall:
D->addAttr(::new (S.Context)
- SwiftCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ SwiftCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_VectorCall:
+ case ParsedAttr::AT_VectorCall:
D->addAttr(::new (S.Context)
- VectorCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ VectorCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_MSABI:
+ case ParsedAttr::AT_MSABI:
D->addAttr(::new (S.Context)
- MSABIAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ MSABIAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_SysVABI:
+ case ParsedAttr::AT_SysVABI:
D->addAttr(::new (S.Context)
- SysVABIAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ SysVABIAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_RegCall:
+ case ParsedAttr::AT_RegCall:
D->addAttr(::new (S.Context) RegCallAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_Pcs: {
+ case ParsedAttr::AT_Pcs: {
PcsAttr::PCSType PCS;
switch (CC) {
case CC_AAPCS:
@@ -4248,37 +4218,37 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
D->addAttr(::new (S.Context)
- PcsAttr(Attr.getRange(), S.Context, PCS,
- Attr.getAttributeSpellingListIndex()));
+ PcsAttr(AL.getRange(), S.Context, PCS,
+ AL.getAttributeSpellingListIndex()));
return;
}
- case AttributeList::AT_IntelOclBicc:
+ case ParsedAttr::AT_IntelOclBicc:
D->addAttr(::new (S.Context)
- IntelOclBiccAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ IntelOclBiccAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_PreserveMost:
+ case ParsedAttr::AT_PreserveMost:
D->addAttr(::new (S.Context) PreserveMostAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_PreserveAll:
+ case ParsedAttr::AT_PreserveAll:
D->addAttr(::new (S.Context) PreserveAllAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
default:
llvm_unreachable("unexpected attribute kind");
}
}
-static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
std::vector<StringRef> DiagnosticIdentifiers;
- for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef RuleName;
- if (!S.checkStringLiteralArgumentAttr(Attr, I, RuleName, nullptr))
+ if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr))
return;
// FIXME: Warn if the rule name is unknown. This is tricky because only
@@ -4286,11 +4256,11 @@ static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &Attr) {
DiagnosticIdentifiers.push_back(RuleName);
}
D->addAttr(::new (S.Context) SuppressAttr(
- Attr.getRange(), S.Context, DiagnosticIdentifiers.data(),
- DiagnosticIdentifiers.size(), Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, DiagnosticIdentifiers.data(),
+ DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex()));
}
-bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
+bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
const FunctionDecl *FD) {
if (Attrs.isInvalid())
return true;
@@ -4300,7 +4270,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
return false;
}
- unsigned ReqArgs = Attrs.getKind() == AttributeList::AT_Pcs ? 1 : 0;
+ unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) {
Attrs.setInvalid();
return true;
@@ -4308,23 +4278,39 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
// TODO: diagnose uses of these conventions on the wrong target.
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;
- case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break;
- case AttributeList::AT_Pascal: CC = CC_X86Pascal; break;
- case AttributeList::AT_SwiftCall: CC = CC_Swift; break;
- case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break;
- case AttributeList::AT_RegCall: CC = CC_X86RegCall; break;
- case AttributeList::AT_MSABI:
+ case ParsedAttr::AT_CDecl:
+ CC = CC_C;
+ break;
+ case ParsedAttr::AT_FastCall:
+ CC = CC_X86FastCall;
+ break;
+ case ParsedAttr::AT_StdCall:
+ CC = CC_X86StdCall;
+ break;
+ case ParsedAttr::AT_ThisCall:
+ CC = CC_X86ThisCall;
+ break;
+ case ParsedAttr::AT_Pascal:
+ CC = CC_X86Pascal;
+ break;
+ case ParsedAttr::AT_SwiftCall:
+ CC = CC_Swift;
+ break;
+ case ParsedAttr::AT_VectorCall:
+ CC = CC_X86VectorCall;
+ break;
+ case ParsedAttr::AT_RegCall:
+ CC = CC_X86RegCall;
+ break;
+ case ParsedAttr::AT_MSABI:
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
CC_Win64;
break;
- case AttributeList::AT_SysVABI:
+ case ParsedAttr::AT_SysVABI:
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
CC_C;
break;
- case AttributeList::AT_Pcs: {
+ case ParsedAttr::AT_Pcs: {
StringRef StrRef;
if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) {
Attrs.setInvalid();
@@ -4342,9 +4328,15 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
Diag(Attrs.getLoc(), diag::err_invalid_pcs);
return true;
}
- case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break;
- case AttributeList::AT_PreserveMost: CC = CC_PreserveMost; break;
- case AttributeList::AT_PreserveAll: CC = CC_PreserveAll; break;
+ case ParsedAttr::AT_IntelOclBicc:
+ CC = CC_IntelOclBicc;
+ break;
+ case ParsedAttr::AT_PreserveMost:
+ CC = CC_PreserveMost;
+ break;
+ case ParsedAttr::AT_PreserveAll:
+ CC = CC_PreserveAll;
+ break;
default: llvm_unreachable("unexpected attribute kind");
}
@@ -4369,39 +4361,39 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
}
/// Pointer-like types in the default address space.
-static bool isValidSwiftContextType(QualType type) {
- if (!type->hasPointerRepresentation())
- return type->isDependentType();
- return type->getPointeeType().getAddressSpace() == LangAS::Default;
+static bool isValidSwiftContextType(QualType Ty) {
+ if (!Ty->hasPointerRepresentation())
+ return Ty->isDependentType();
+ return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
}
/// Pointers and references in the default address space.
-static bool isValidSwiftIndirectResultType(QualType type) {
- if (auto ptrType = type->getAs<PointerType>()) {
- type = ptrType->getPointeeType();
- } else if (auto refType = type->getAs<ReferenceType>()) {
- type = refType->getPointeeType();
+static bool isValidSwiftIndirectResultType(QualType Ty) {
+ if (const auto *PtrType = Ty->getAs<PointerType>()) {
+ Ty = PtrType->getPointeeType();
+ } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
+ Ty = RefType->getPointeeType();
} else {
- return type->isDependentType();
+ return Ty->isDependentType();
}
- return type.getAddressSpace() == LangAS::Default;
+ return Ty.getAddressSpace() == LangAS::Default;
}
/// Pointers and references to pointers in the default address space.
-static bool isValidSwiftErrorResultType(QualType type) {
- if (auto ptrType = type->getAs<PointerType>()) {
- type = ptrType->getPointeeType();
- } else if (auto refType = type->getAs<ReferenceType>()) {
- type = refType->getPointeeType();
+static bool isValidSwiftErrorResultType(QualType Ty) {
+ if (const auto *PtrType = Ty->getAs<PointerType>()) {
+ Ty = PtrType->getPointeeType();
+ } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
+ Ty = RefType->getPointeeType();
} else {
- return type->isDependentType();
+ return Ty->isDependentType();
}
- if (!type.getQualifiers().empty())
+ if (!Ty.getQualifiers().empty())
return false;
- return isValidSwiftContextType(type);
+ return isValidSwiftContextType(Ty);
}
-static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &Attrs,
+static void handleParameterABIAttr(Sema &S, Decl *D, const ParsedAttr &Attrs,
ParameterABI Abi) {
S.AddParameterABIAttr(Attrs.getRange(), D, Abi,
Attrs.getAttributeSpellingListIndex());
@@ -4460,34 +4452,34 @@ void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi,
/// Checks a regparm attribute, returning true if it is ill-formed and
/// otherwise setting numParams to the appropriate value.
-bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
- if (Attr.isInvalid())
+bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) {
+ if (AL.isInvalid())
return true;
- if (!checkAttributeNumArgs(*this, Attr, 1)) {
- Attr.setInvalid();
+ if (!checkAttributeNumArgs(*this, AL, 1)) {
+ AL.setInvalid();
return true;
}
uint32_t NP;
- Expr *NumParamsExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(*this, Attr, NumParamsExpr, NP)) {
- Attr.setInvalid();
+ Expr *NumParamsExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) {
+ AL.setInvalid();
return true;
}
if (Context.getTargetInfo().getRegParmMax() == 0) {
- Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
+ Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform)
<< NumParamsExpr->getSourceRange();
- Attr.setInvalid();
+ AL.setInvalid();
return true;
}
numParams = NP;
if (numParams > Context.getTargetInfo().getRegParmMax()) {
- Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
+ Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number)
<< Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
- Attr.setInvalid();
+ AL.setInvalid();
return true;
}
@@ -4499,7 +4491,7 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
// non-nullptr Expr result on success. Otherwise, it returns nullptr
// and may output an error.
static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
- const CUDALaunchBoundsAttr &Attr,
+ const CUDALaunchBoundsAttr &AL,
const unsigned Idx) {
if (S.DiagnoseUnexpandedParameterPack(E))
return nullptr;
@@ -4512,7 +4504,7 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
llvm::APSInt I(64);
if (!E->isIntegerConstantExpr(I, S.Context)) {
S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
- << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
+ << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
return nullptr;
}
// Make sure we can fit it in 32 bits.
@@ -4523,7 +4515,7 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
}
if (I < 0)
S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
- << &Attr << Idx << E->getSourceRange();
+ << &AL << Idx << E->getSourceRange();
// We may need to perform implicit conversion of the argument.
InitializedEntity Entity = InitializedEntity::InitializeParameter(
@@ -4553,253 +4545,232 @@ void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex));
}
-static void handleLaunchBoundsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
- !checkAttributeAtMostNumArgs(S, Attr, 2))
+static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
+ !checkAttributeAtMostNumArgs(S, AL, 2))
return;
- S.AddLaunchBoundsAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
- Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr,
- Attr.getAttributeSpellingListIndex());
+ S.AddLaunchBoundsAttr(AL.getRange(), D, AL.getArgAsExpr(0),
+ AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr,
+ AL.getAttributeSpellingListIndex());
}
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
- return;
- }
-
- if (!checkAttributeNumArgs(S, Attr, 3))
- return;
-
- IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;
-
- if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
return;
}
- uint64_t ArgumentIdx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 2, Attr.getArgAsExpr(1),
+ ParamIdx ArgumentIdx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1),
ArgumentIdx))
return;
- uint64_t TypeTagIdx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 3, Attr.getArgAsExpr(2),
+ ParamIdx TypeTagIdx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2),
TypeTagIdx))
return;
- bool IsPointer = (Attr.getName()->getName() == "pointer_with_type_tag");
+ bool IsPointer = AL.getName()->getName() == "pointer_with_type_tag";
if (IsPointer) {
// Ensure that buffer has a pointer type.
- QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
- if (!BufferTy->isPointerType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << Attr.getName() << 0;
- }
+ unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();
+ if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) ||
+ !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType())
+ S.Diag(AL.getLoc(), diag::err_attribute_pointers_only)
+ << AL.getName() << 0;
}
- D->addAttr(::new (S.Context)
- ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind,
- ArgumentIdx, TypeTagIdx, IsPointer,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
+ AL.getRange(), S.Context, AL.getArgAsIdent(0)->Ident, ArgumentIdx,
+ TypeTagIdx, IsPointer, AL.getAttributeSpellingListIndex()));
}
static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
-
- if (!checkAttributeNumArgs(S, Attr, 1))
+
+ if (!checkAttributeNumArgs(S, AL, 1))
return;
if (!isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedVariable;
return;
}
- IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident;
TypeSourceInfo *MatchingCTypeLoc = nullptr;
- S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
+ S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc);
assert(MatchingCTypeLoc && "no type source info for attribute argument");
D->addAttr(::new (S.Context)
- TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind,
+ TypeTagForDatatypeAttr(AL.getRange(), S.Context, PointerKind,
MatchingCTypeLoc,
- Attr.getLayoutCompatible(),
- Attr.getMustBeNull(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getLayoutCompatible(),
+ AL.getMustBeNull(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleXRayLogArgsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- uint64_t ArgCount;
+static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ ParamIdx ArgCount;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, Attr.getArgAsExpr(0),
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0),
ArgCount,
- true /* AllowImplicitThis*/))
+ true /* CanIndexImplicitThis */))
return;
- // ArgCount isn't a parameter index [0;n), it's a count [1;n] - hence + 1.
- D->addAttr(::new (S.Context)
- XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount,
- Attr.getAttributeSpellingListIndex()));
+ // ArgCount isn't a parameter index [0;n), it's a count [1;n]
+ D->addAttr(::new (S.Context) XRayLogArgsAttr(
+ AL.getRange(), S.Context, ArgCount.getSourceIndex(),
+ AL.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
-static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType type) {
- return type->isDependentType() ||
- type->isObjCRetainableType();
+static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
+ return QT->isDependentType() || QT->isObjCRetainableType();
}
-static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
- return type->isDependentType() ||
- type->isObjCObjectPointerType() ||
- S.Context.isObjCNSObjectType(type);
+static bool isValidSubjectOfNSAttribute(Sema &S, QualType QT) {
+ return QT->isDependentType() || QT->isObjCObjectPointerType() ||
+ S.Context.isObjCNSObjectType(QT);
}
-static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
- return type->isDependentType() ||
- type->isPointerType() ||
- isValidSubjectOfNSAttribute(S, type);
+static bool isValidSubjectOfCFAttribute(Sema &S, QualType QT) {
+ return QT->isDependentType() || QT->isPointerType() ||
+ isValidSubjectOfNSAttribute(S, QT);
}
-static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- S.AddNSConsumedAttr(Attr.getRange(), D, Attr.getAttributeSpellingListIndex(),
- Attr.getKind() == AttributeList::AT_NSConsumed,
+static void handleNSConsumedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.AddNSConsumedAttr(AL.getRange(), D, AL.getAttributeSpellingListIndex(),
+ AL.getKind() == ParsedAttr::AT_NSConsumed,
/*template instantiation*/ false);
}
-void Sema::AddNSConsumedAttr(SourceRange attrRange, Decl *D,
- unsigned spellingIndex, bool isNSConsumed,
- bool isTemplateInstantiation) {
- ParmVarDecl *param = cast<ParmVarDecl>(D);
- bool typeOK;
+void Sema::AddNSConsumedAttr(SourceRange AttrRange, Decl *D,
+ unsigned SpellingIndex, bool IsNSConsumed,
+ bool IsTemplateInstantiation) {
+ const auto *Param = cast<ParmVarDecl>(D);
+ bool TypeOK;
- if (isNSConsumed) {
- typeOK = isValidSubjectOfNSAttribute(*this, param->getType());
- } else {
- typeOK = isValidSubjectOfCFAttribute(*this, param->getType());
- }
+ if (IsNSConsumed)
+ TypeOK = isValidSubjectOfNSAttribute(*this, Param->getType());
+ else
+ TypeOK = isValidSubjectOfCFAttribute(*this, Param->getType());
- if (!typeOK) {
+ if (!TypeOK) {
// These attributes are normally just advisory, but in ARC, ns_consumed
// is significant. Allow non-dependent code to contain inappropriate
// attributes even in ARC, but require template instantiations to be
// set up correctly.
- Diag(D->getLocStart(),
- (isTemplateInstantiation && isNSConsumed &&
- getLangOpts().ObjCAutoRefCount
- ? diag::err_ns_attribute_wrong_parameter_type
- : diag::warn_ns_attribute_wrong_parameter_type))
- << attrRange
- << (isNSConsumed ? "ns_consumed" : "cf_consumed")
- << (isNSConsumed ? /*objc pointers*/ 0 : /*cf pointers*/ 1);
+ Diag(D->getLocStart(), (IsTemplateInstantiation && IsNSConsumed &&
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_ns_attribute_wrong_parameter_type
+ : diag::warn_ns_attribute_wrong_parameter_type))
+ << AttrRange << (IsNSConsumed ? "ns_consumed" : "cf_consumed")
+ << (IsNSConsumed ? /*objc pointers*/ 0 : /*cf pointers*/ 1);
return;
}
- if (isNSConsumed)
- param->addAttr(::new (Context)
- NSConsumedAttr(attrRange, Context, spellingIndex));
+ if (IsNSConsumed)
+ D->addAttr(::new (Context)
+ NSConsumedAttr(AttrRange, Context, SpellingIndex));
else
- param->addAttr(::new (Context)
- CFConsumedAttr(attrRange, Context, spellingIndex));
+ D->addAttr(::new (Context)
+ CFConsumedAttr(AttrRange, Context, SpellingIndex));
}
-bool Sema::checkNSReturnsRetainedReturnType(SourceLocation loc,
- QualType type) {
- if (isValidSubjectOfNSReturnsRetainedAttribute(type))
+bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
+ if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
return false;
- Diag(loc, diag::warn_ns_attribute_wrong_return_type)
- << "'ns_returns_retained'" << 0 << 0;
+ Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
+ << "'ns_returns_retained'" << 0 << 0;
return true;
}
static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- QualType returnType;
+ const ParsedAttr &AL) {
+ QualType ReturnType;
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- returnType = MD->getReturnType();
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ ReturnType = MD->getReturnType();
else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
- (Attr.getKind() == AttributeList::AT_NSReturnsRetained))
+ (AL.getKind() == ParsedAttr::AT_NSReturnsRetained))
return; // ignore: was handled as a type attribute
- else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
- returnType = PD->getType();
- else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- returnType = FD->getReturnType();
- else if (auto *Param = dyn_cast<ParmVarDecl>(D)) {
- returnType = Param->getType()->getPointeeType();
- if (returnType.isNull()) {
+ else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D))
+ ReturnType = PD->getType();
+ else if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ ReturnType = FD->getReturnType();
+ else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
+ ReturnType = Param->getType()->getPointeeType();
+ if (ReturnType.isNull()) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
- << Attr.getName() << /*pointer-to-CF*/2
- << Attr.getRange();
+ << AL.getName() << /*pointer-to-CF*/2
+ << AL.getRange();
return;
}
- } else if (Attr.isUsedAsTypeAttr()) {
+ } else if (AL.isUsedAsTypeAttr()) {
return;
} else {
AttributeDeclKind ExpectedDeclKind;
- switch (Attr.getKind()) {
+ switch (AL.getKind()) {
default: llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsRetained:
- case AttributeList::AT_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsRetained:
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsNotRetained:
ExpectedDeclKind = ExpectedFunctionOrMethod;
break;
- case AttributeList::AT_CFReturnsRetained:
- case AttributeList::AT_CFReturnsNotRetained:
+ case ParsedAttr::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
break;
}
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedDeclKind;
+ << AL.getRange() << AL.getName() << ExpectedDeclKind;
return;
}
- bool typeOK;
- bool cf;
- switch (Attr.getKind()) {
+ bool TypeOK;
+ bool Cf;
+ switch (AL.getKind()) {
default: llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsRetained:
- typeOK = isValidSubjectOfNSReturnsRetainedAttribute(returnType);
- cf = false;
+ case ParsedAttr::AT_NSReturnsRetained:
+ TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
+ Cf = false;
break;
-
- case AttributeList::AT_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
- typeOK = isValidSubjectOfNSAttribute(S, returnType);
- cf = false;
+
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsNotRetained:
+ TypeOK = isValidSubjectOfNSAttribute(S, ReturnType);
+ Cf = false;
break;
- case AttributeList::AT_CFReturnsRetained:
- case AttributeList::AT_CFReturnsNotRetained:
- typeOK = isValidSubjectOfCFAttribute(S, returnType);
- cf = true;
+ case ParsedAttr::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
+ TypeOK = isValidSubjectOfCFAttribute(S, ReturnType);
+ Cf = true;
break;
}
- if (!typeOK) {
- if (Attr.isUsedAsTypeAttr())
+ if (!TypeOK) {
+ if (AL.isUsedAsTypeAttr())
return;
if (isa<ParmVarDecl>(D)) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
- << Attr.getName() << /*pointer-to-CF*/2
- << Attr.getRange();
+ << AL.getName() << /*pointer-to-CF*/2
+ << AL.getRange();
} else {
// Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
enum : unsigned {
@@ -4812,43 +4783,43 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
else if (isa<ObjCPropertyDecl>(D))
SubjectKind = Property;
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
- << Attr.getName() << SubjectKind << cf
- << Attr.getRange();
+ << AL.getName() << SubjectKind << Cf
+ << AL.getRange();
}
return;
}
- switch (Attr.getKind()) {
+ switch (AL.getKind()) {
default:
llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsAutoreleased:
D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_CFReturnsNotRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsNotRetained:
D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsRetained:
D->addAttr(::new (S.Context) CFReturnsRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_NSReturnsRetained:
+ case ParsedAttr::AT_NSReturnsRetained:
D->addAttr(::new (S.Context) NSReturnsRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
};
}
static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
- const AttributeList &Attrs) {
+ const ParsedAttr &Attrs) {
const int EP_ObjCMethod = 1;
const int EP_ObjCProperty = 2;
-
+
SourceLocation loc = Attrs.getLoc();
QualType resultType;
if (isa<ObjCMethodDecl>(D))
@@ -4873,116 +4844,91 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
}
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
- const AttributeList &Attrs) {
- ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
-
- DeclContext *DC = method->getDeclContext();
- if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
+ const ParsedAttr &Attrs) {
+ const auto *Method = cast<ObjCMethodDecl>(D);
+
+ const DeclContext *DC = Method->getDeclContext();
+ if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << Attrs.getName() << 0;
+ << Attrs.getName() << 0;
S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
return;
}
- if (method->getMethodFamily() == OMF_dealloc) {
+ if (Method->getMethodFamily() == OMF_dealloc) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << Attrs.getName() << 1;
+ << Attrs.getName() << 1;
return;
}
-
- method->addAttr(::new (S.Context)
- ObjCRequiresSuperAttr(Attrs.getRange(), S.Context,
- Attrs.getAttributeSpellingListIndex()));
-}
-static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context)
- CFAuditedTransferAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context)
- CFUnknownTransferAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(
+ Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
- IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
if (!Parm) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
return;
}
// Typedefs only allow objc_bridge(id) and have some additional checking.
- if (auto TD = dyn_cast<TypedefNameDecl>(D)) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
if (!Parm->Ident->isStr("id")) {
- S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_id)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id)
+ << AL.getName();
return;
}
// Only allow 'cv void *'.
QualType T = TD->getUnderlyingType();
if (!T->isVoidPointerType()) {
- S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
+ S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
return;
}
}
-
+
D->addAttr(::new (S.Context)
- ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
- Attr.getAttributeSpellingListIndex()));
+ ObjCBridgeAttr(AL.getRange(), S.Context, Parm->Ident,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
- IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+static void handleObjCBridgeMutableAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
if (!Parm) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
return;
}
-
+
D->addAttr(::new (S.Context)
- ObjCBridgeMutableAttr(Attr.getRange(), S.Context, Parm->Ident,
- Attr.getAttributeSpellingListIndex()));
+ ObjCBridgeMutableAttr(AL.getRange(), S.Context, Parm->Ident,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
IdentifierInfo *RelatedClass =
- Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : nullptr;
+ AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
if (!RelatedClass) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
return;
}
IdentifierInfo *ClassMethod =
- Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : nullptr;
+ AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
IdentifierInfo *InstanceMethod =
- Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : nullptr;
+ AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
D->addAttr(::new (S.Context)
- ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
+ ObjCBridgeRelatedAttr(AL.getRange(), S.Context, RelatedClass,
ClassMethod, InstanceMethod,
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
ObjCInterfaceDecl *IFace;
- if (ObjCCategoryDecl *CatDecl =
- dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
+ if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
IFace = CatDecl->getClassInterface();
else
IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
@@ -4992,29 +4938,28 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
IFace->setHasDesignatedInitializers();
D->addAttr(::new (S.Context)
- ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCDesignatedInitializerAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCRuntimeName(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef MetaDataName;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, MetaDataName))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
return;
D->addAttr(::new (S.Context)
- ObjCRuntimeNameAttr(Attr.getRange(), S.Context,
+ ObjCRuntimeNameAttr(AL.getRange(), S.Context,
MetaDataName,
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
// When a user wants to use objc_boxable with a union or struct
// but they don't have access to the declaration (legacy/third-party code)
// then they can 'enable' this feature with a typedef:
// typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
-static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) {
bool notify = false;
- RecordDecl *RD = dyn_cast<RecordDecl>(D);
+ auto *RD = dyn_cast<RecordDecl>(D);
if (RD && RD->getDefinition()) {
RD = RD->getDefinition();
notify = true;
@@ -5022,8 +4967,8 @@ static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
if (RD) {
ObjCBoxableAttr *BoxableAttr = ::new (S.Context)
- ObjCBoxableAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex());
+ ObjCBoxableAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex());
RD->addAttr(BoxableAttr);
if (notify) {
// we need to notify ASTReader/ASTWriter about
@@ -5034,36 +4979,35 @@ static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
-static void handleObjCOwnershipAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (hasDeclarator(D)) return;
S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedVariable;
+ << AL.getRange() << AL.getName() << ExpectedVariable;
}
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- ValueDecl *vd = cast<ValueDecl>(D);
- QualType type = vd->getType();
+ const ParsedAttr &AL) {
+ const auto *VD = cast<ValueDecl>(D);
+ QualType QT = VD->getType();
- if (!type->isDependentType() &&
- !type->isObjCLifetimeType()) {
- S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type)
- << type;
+ if (!QT->isDependentType() &&
+ !QT->isObjCLifetimeType()) {
+ S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type)
+ << QT;
return;
}
- Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
+ Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();
// If we have no lifetime yet, check the lifetime we're presumably
// going to infer.
- if (lifetime == Qualifiers::OCL_None && !type->isDependentType())
- lifetime = type->getObjCARCImplicitLifetime();
+ if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
+ Lifetime = QT->getObjCARCImplicitLifetime();
- switch (lifetime) {
+ switch (Lifetime) {
case Qualifiers::OCL_None:
- assert(type->isDependentType() &&
+ assert(QT->isDependentType() &&
"didn't infer lifetime for non-dependent type?");
break;
@@ -5073,14 +5017,14 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
- S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
- << (lifetime == Qualifiers::OCL_Autoreleasing);
+ S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
+ << (Lifetime == Qualifiers::OCL_Autoreleasing);
break;
}
D->addAttr(::new (S.Context)
- ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCPreciseLifetimeAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
@@ -5100,16 +5044,16 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range,
return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex);
}
-static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::C;
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << AL.getName() << AttributeLangSupport::C;
return;
}
StringRef StrRef;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, StrRef, &LiteralLoc))
return;
// GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
@@ -5141,162 +5085,158 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// separating attributes nor of the [ and the ] are in the AST.
// Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc"
// on cfe-dev.
- if (Attr.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
- S.Diag(Attr.getLoc(), diag::warn_atl_uuid_deprecated);
+ if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
+ S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated);
- UuidAttr *UA = S.mergeUuidAttr(D, Attr.getRange(),
- Attr.getAttributeSpellingListIndex(), StrRef);
+ UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(),
+ AL.getAttributeSpellingListIndex(), StrRef);
if (UA)
D->addAttr(UA);
}
-static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::C;
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << AL.getName() << AttributeLangSupport::C;
return;
}
MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
- D, Attr.getRange(), /*BestCase=*/true,
- Attr.getAttributeSpellingListIndex(),
- (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling());
+ D, AL.getRange(), /*BestCase=*/true,
+ AL.getAttributeSpellingListIndex(),
+ (MSInheritanceAttr::Spelling)AL.getSemanticSpelling());
if (IA) {
D->addAttr(IA);
S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D));
}
}
-static void handleDeclspecThreadAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- VarDecl *VD = cast<VarDecl>(D);
+static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ const auto *VD = cast<VarDecl>(D);
if (!S.Context.getTargetInfo().isTLSSupported()) {
- S.Diag(Attr.getLoc(), diag::err_thread_unsupported);
+ S.Diag(AL.getLoc(), diag::err_thread_unsupported);
return;
}
if (VD->getTSCSpec() != TSCS_unspecified) {
- S.Diag(Attr.getLoc(), diag::err_declspec_thread_on_thread_variable);
+ S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable);
return;
}
if (VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
+ S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
return;
}
- VD->addAttr(::new (S.Context) ThreadAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ThreadAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SmallVector<StringRef, 4> Tags;
- for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef Tag;
- if (!S.checkStringLiteralArgumentAttr(Attr, I, Tag))
+ if (!S.checkStringLiteralArgumentAttr(AL, I, Tag))
return;
Tags.push_back(Tag);
}
if (const auto *NS = dyn_cast<NamespaceDecl>(D)) {
if (!NS->isInline()) {
- S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
+ S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
return;
}
if (NS->isAnonymousNamespace()) {
- S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
+ S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
return;
}
- if (Attr.getNumArgs() == 0)
+ if (AL.getNumArgs() == 0)
Tags.push_back(NS->getName());
- } else if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ } else if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
// Store tags sorted and without duplicates.
- std::sort(Tags.begin(), Tags.end());
+ llvm::sort(Tags.begin(), Tags.end());
Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
D->addAttr(::new (S.Context)
- AbiTagAttr(Attr.getRange(), S.Context, Tags.data(), Tags.size(),
- Attr.getAttributeSpellingListIndex()));
+ AbiTagAttr(AL.getRange(), S.Context, Tags.data(), Tags.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleARMInterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
+ << AL.getName() << 1;
return;
}
StringRef Str;
SourceLocation ArgLoc;
- if (Attr.getNumArgs() == 0)
+ if (AL.getNumArgs() == 0)
Str = "";
- else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;
ARMInterruptAttr::InterruptType Kind;
if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << Str << ArgLoc;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << Str << ArgLoc;
return;
}
- unsigned Index = Attr.getAttributeSpellingListIndex();
+ unsigned Index = AL.getAttributeSpellingListIndex();
D->addAttr(::new (S.Context)
- ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
+ ARMInterruptAttr(AL.getLoc(), S.Context, Kind, Index));
}
-static void handleMSP430InterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
+static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeNumArgs(S, AL, 1))
return;
- if (!Attr.isArgExpr(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ if (!AL.isArgExpr(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName()
<< AANT_ArgumentIntegerConstant;
- return;
+ return;
}
// FIXME: Check for decl - it should be void ()(void).
- Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+ Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
llvm::APSInt NumParams(32);
if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL.getName() << AANT_ArgumentIntegerConstant
<< NumParamsExpr->getSourceRange();
return;
}
unsigned Num = NumParams.getLimitedValue(255);
if ((Num & 1) || Num > 30) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << (int)NumParams.getSExtValue()
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << (int)NumParams.getSExtValue()
<< NumParamsExpr->getSourceRange();
return;
}
D->addAttr(::new (S.Context)
- MSP430InterruptAttr(Attr.getLoc(), S.Context, Num,
- Attr.getAttributeSpellingListIndex()));
+ MSP430InterruptAttr(AL.getLoc(), S.Context, Num,
+ AL.getAttributeSpellingListIndex()));
D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
-static void handleMipsInterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Only one optional argument permitted.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
+ << AL.getName() << 1;
return;
}
StringRef Str;
SourceLocation ArgLoc;
- if (Attr.getNumArgs() == 0)
+ if (AL.getNumArgs() == 0)
Str = "";
- else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;
// Semantic checks for a function with the 'interrupt' attribute for MIPS:
@@ -5326,23 +5266,22 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D,
return;
}
- if (checkAttrMutualExclusion<Mips16Attr>(S, D, Attr.getRange(),
- Attr.getName()))
+ if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL.getRange(),
+ AL.getName()))
return;
MipsInterruptAttr::InterruptType Kind;
if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << "'" + std::string(Str) + "'";
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << "'" + std::string(Str) + "'";
return;
}
D->addAttr(::new (S.Context) MipsInterruptAttr(
- Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex()));
+ AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
}
-static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Semantic checks for a function with the 'interrupt' attribute.
// a) Must be a function.
// b) Must have the 'void' return type.
@@ -5352,8 +5291,8 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) ||
CXXMethodDecl::isStaticOverloadedOperator(
cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionWithProtoType;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionWithProtoType;
return;
}
// Interrupt handler must have void return type.
@@ -5403,182 +5342,241 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
return;
}
D->addAttr(::new (S.Context) AnyX86InterruptAttr(
- Attr.getLoc(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getLoc(), S.Context, AL.getAttributeSpellingListIndex()));
D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
-static void handleAVRInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'interrupt'" << ExpectedFunction;
return;
}
- if (!checkAttributeNumArgs(S, Attr, 0))
+ if (!checkAttributeNumArgs(S, AL, 0))
return;
- handleSimpleAttribute<AVRInterruptAttr>(S, D, Attr);
+ handleSimpleAttribute<AVRInterruptAttr>(S, D, AL);
}
-static void handleAVRSignalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'signal'" << ExpectedFunction;
return;
}
- if (!checkAttributeNumArgs(S, Attr, 0))
+ if (!checkAttributeNumArgs(S, AL, 0))
return;
- handleSimpleAttribute<AVRSignalAttr>(S, D, Attr);
+ handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
}
-static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+
+static void handleRISCVInterruptAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ // Warn about repeated attributes.
+ if (const auto *A = D->getAttr<RISCVInterruptAttr>()) {
+ S.Diag(AL.getRange().getBegin(),
+ diag::warn_riscv_repeated_interrupt_attribute);
+ S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
+ return;
+ }
+
+ // Check the attribute argument. Argument is optional.
+ if (!checkAttributeAtMostNumArgs(S, AL, 1))
+ return;
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ // 'machine'is the default interrupt mode.
+ if (AL.getNumArgs() == 0)
+ Str = "machine";
+ else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
+ return;
+
+ // Semantic checks for a function with the 'interrupt' attribute:
+ // - Must be a function.
+ // - Must have no parameters.
+ // - Must have the 'void' return type.
+ // - The attribute itself must either have no argument or one of the
+ // valid interrupt types, see [RISCVInterruptDocs].
+
+ if (D->getFunctionType() == nullptr) {
+ S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+ << "'interrupt'" << ExpectedFunction;
+ return;
+ }
+
+ if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
+ S.Diag(D->getLocation(), diag::warn_riscv_interrupt_attribute) << 0;
+ return;
+ }
+
+ if (!getFunctionOrMethodResultType(D)->isVoidType()) {
+ S.Diag(D->getLocation(), diag::warn_riscv_interrupt_attribute) << 1;
+ return;
+ }
+
+ RISCVInterruptAttr::InterruptType Kind;
+ if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << Str << ArgLoc;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) RISCVInterruptAttr(
+ AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
+}
+
+static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Dispatch the interrupt attribute based on the current target.
switch (S.Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::msp430:
- handleMSP430InterruptAttr(S, D, Attr);
+ handleMSP430InterruptAttr(S, D, AL);
break;
case llvm::Triple::mipsel:
case llvm::Triple::mips:
- handleMipsInterruptAttr(S, D, Attr);
+ handleMipsInterruptAttr(S, D, AL);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- handleAnyX86InterruptAttr(S, D, Attr);
+ handleAnyX86InterruptAttr(S, D, AL);
break;
case llvm::Triple::avr:
- handleAVRInterruptAttr(S, D, Attr);
+ handleAVRInterruptAttr(S, D, AL);
+ break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ handleRISCVInterruptAttr(S, D, AL);
break;
default:
- handleARMInterruptAttr(S, D, Attr);
+ handleARMInterruptAttr(S, D, AL);
break;
}
}
static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
uint32_t Min = 0;
- Expr *MinExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, MinExpr, Min))
+ Expr *MinExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, MinExpr, Min))
return;
uint32_t Max = 0;
- Expr *MaxExpr = Attr.getArgAsExpr(1);
- if (!checkUInt32Argument(S, Attr, MaxExpr, Max))
+ Expr *MaxExpr = AL.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, AL, MaxExpr, Max))
return;
if (Min == 0 && Max != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 0;
return;
}
if (Min > Max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 1;
return;
}
D->addAttr(::new (S.Context)
- AMDGPUFlatWorkGroupSizeAttr(Attr.getLoc(), S.Context, Min, Max,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUFlatWorkGroupSizeAttr(AL.getLoc(), S.Context, Min, Max,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t Min = 0;
- Expr *MinExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, MinExpr, Min))
+ Expr *MinExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, MinExpr, Min))
return;
uint32_t Max = 0;
- if (Attr.getNumArgs() == 2) {
- Expr *MaxExpr = Attr.getArgAsExpr(1);
- if (!checkUInt32Argument(S, Attr, MaxExpr, Max))
+ if (AL.getNumArgs() == 2) {
+ Expr *MaxExpr = AL.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, AL, MaxExpr, Max))
return;
}
if (Min == 0 && Max != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 0;
return;
}
if (Max != 0 && Min > Max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 1;
return;
}
D->addAttr(::new (S.Context)
- AMDGPUWavesPerEUAttr(Attr.getLoc(), S.Context, Min, Max,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUWavesPerEUAttr(AL.getLoc(), S.Context, Min, Max,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t NumSGPR = 0;
- Expr *NumSGPRExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, NumSGPRExpr, NumSGPR))
+ Expr *NumSGPRExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR))
return;
D->addAttr(::new (S.Context)
- AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, NumSGPR,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUNumSGPRAttr(AL.getLoc(), S.Context, NumSGPR,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t NumVGPR = 0;
- Expr *NumVGPRExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, NumVGPRExpr, NumVGPR))
+ Expr *NumVGPRExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR))
return;
D->addAttr(::new (S.Context)
- AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, NumVGPR,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUNumVGPRAttr(AL.getLoc(), S.Context, NumVGPR,
+ AL.getAttributeSpellingListIndex()));
}
static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
- const AttributeList& Attr) {
+ const ParsedAttr &AL) {
// If we try to apply it to a function pointer, don't warn, but don't
// do anything, either. It doesn't matter anyway, because there's nothing
// special about calling a force_align_arg_pointer function.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ const auto *VD = dyn_cast<ValueDecl>(D);
if (VD && VD->getType()->isFunctionPointerType())
return;
// Also don't warn on function pointer typedefs.
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ const auto *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
TD->getUnderlyingType()->isFunctionType()))
return;
// Attribute can only be applied to function types.
if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
- X86ForceAlignArgPointerAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ X86ForceAlignArgPointerAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleLayoutVersion(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t Version;
- Expr *VersionExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), Version))
+ Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
+ if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version))
return;
// TODO: Investigate what happens with the next major version of MSVC.
if (Version != LangOptions::MSVC2015) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << Version << VersionExpr->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << Version << VersionExpr->getSourceRange();
return;
}
D->addAttr(::new (S.Context)
- LayoutVersionAttr(Attr.getRange(), S.Context, Version,
- Attr.getAttributeSpellingListIndex()));
+ LayoutVersionAttr(AL.getRange(), S.Context, Version,
+ AL.getAttributeSpellingListIndex()));
}
DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
@@ -5607,7 +5605,7 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
}
-static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
+static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored)
@@ -5615,8 +5613,8 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
return;
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isInlined() && A.getKind() == AttributeList::AT_DLLImport &&
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// MinGW doesn't allow dllimport on inline functions.
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
@@ -5625,7 +5623,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
}
}
- if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
MD->getParent()->isLambda()) {
S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName();
@@ -5634,7 +5632,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
}
unsigned Index = A.getAttributeSpellingListIndex();
- Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
+ Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport
? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
: (Attr *)S.mergeDLLImportAttr(D, A.getRange(), Index);
if (NewAttr)
@@ -5654,7 +5652,7 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
D->dropAttr<MSInheritanceAttr>();
}
- CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ auto *RD = cast<CXXRecordDecl>(D);
if (RD->hasDefinition()) {
if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
SemanticSpelling)) {
@@ -5677,7 +5675,7 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
}
-static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// The capability attributes take a single string parameter for the name of
// the capability they represent. The lockable attribute does not take any
// parameters. However, semantically, both attributes represent the same
@@ -5688,8 +5686,8 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// literal will be considered a "mutex."
StringRef N("mutex");
SourceLocation LiteralLoc;
- if (Attr.getKind() == AttributeList::AT_Capability &&
- !S.checkStringLiteralArgumentAttr(Attr, 0, N, &LiteralLoc))
+ if (AL.getKind() == ParsedAttr::AT_Capability &&
+ !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc))
return;
// Currently, there are only two names allowed for a capability: role and
@@ -5697,80 +5695,79 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!N.equals_lower("mutex") && !N.equals_lower("role"))
S.Diag(LiteralLoc, diag::warn_invalid_capability_name) << N;
- D->addAttr(::new (S.Context) CapabilityAttr(Attr.getRange(), S.Context, N,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) CapabilityAttr(AL.getRange(), S.Context, N,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAssertCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
+ D->addAttr(::new (S.Context) AssertCapabilityAttr(AL.getRange(), S.Context,
Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
+ D->addAttr(::new (S.Context) AcquireCapabilityAttr(AL.getRange(),
S.Context,
Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkTryLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(Attr.getRange(),
+ D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(AL.getRange(),
S.Context,
- Attr.getArgAsExpr(0),
+ AL.getArgAsExpr(0),
Args.data(),
Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
// Check that all arguments are lockable objects.
SmallVector<Expr *, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, true);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true);
D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
- Attr.getRange(), S.Context, Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Args.data(), Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
if (Args.empty())
return;
RequiresCapabilityAttr *RCA = ::new (S.Context)
- RequiresCapabilityAttr(Attr.getRange(), S.Context, Args.data(),
- Args.size(), Attr.getAttributeSpellingListIndex());
+ RequiresCapabilityAttr(AL.getRange(), S.Context, Args.data(),
+ Args.size(), AL.getAttributeSpellingListIndex());
D->addAttr(RCA);
}
-static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
+static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) {
if (NSD->isAnonymousNamespace()) {
- S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace);
+ S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace);
// Do not want to attach the attribute to the namespace because that will
// cause confusing diagnostic reports for uses of declarations within the
// namespace.
@@ -5780,25 +5777,25 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Handle the cases where the attribute has a text message.
StringRef Str, Replacement;
- if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) &&
- !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (AL.isArgExpr(0) && AL.getArgAsExpr(0) &&
+ !S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
// Only support a single optional message for Declspec and CXX11.
- if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute())
- checkAttributeAtMostNumArgs(S, Attr, 1);
- else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) &&
- !S.checkStringLiteralArgumentAttr(Attr, 1, Replacement))
+ if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
+ checkAttributeAtMostNumArgs(S, AL, 1);
+ else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
+ !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
return;
if (!S.getLangOpts().CPlusPlus14)
- if (Attr.isCXX11Attribute() &&
- !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu")))
- S.Diag(Attr.getLoc(), diag::ext_cxx14_attr) << Attr.getName();
+ if (AL.isCXX11Attribute() &&
+ !(AL.hasScope() && AL.getScopeName()->isStr("gnu")))
+ S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL.getName();
D->addAttr(::new (S.Context)
- DeprecatedAttr(Attr.getRange(), S.Context, Str, Replacement,
- Attr.getAttributeSpellingListIndex()));
+ DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
+ AL.getAttributeSpellingListIndex()));
}
static bool isGlobalVar(const Decl *D) {
@@ -5807,35 +5804,35 @@ static bool isGlobalVar(const Decl *D) {
return false;
}
-static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
std::vector<StringRef> Sanitizers;
- for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef SanitizerName;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, I, SanitizerName, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc))
return;
if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0)
S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
else if (isGlobalVar(D) && SanitizerName != "address")
S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ << AL.getName() << ExpectedFunctionOrMethod;
Sanitizers.push_back(SanitizerName);
}
D->addAttr(::new (S.Context) NoSanitizeAttr(
- Attr.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
+ AL.getAttributeSpellingListIndex()));
}
static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- StringRef AttrName = Attr.getName()->getName();
+ const ParsedAttr &AL) {
+ StringRef AttrName = AL.getName()->getName();
normalizeName(AttrName);
StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName)
.Case("no_address_safety_analysis", "address")
@@ -5844,77 +5841,78 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
.Case("no_sanitize_memory", "memory");
if (isGlobalVar(D) && SanitizerName != "address")
S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ << AL.getName() << ExpectedFunction;
D->addAttr(::new (S.Context)
- NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1,
- Attr.getAttributeSpellingListIndex()));
+ NoSanitizeAttr(AL.getRange(), S.Context, &SanitizerName, 1,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleInternalLinkageAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (InternalLinkageAttr *Internal =
- S.mergeInternalLinkageAttr(D, Attr.getRange(), Attr.getName(),
- Attr.getAttributeSpellingListIndex()))
+ S.mergeInternalLinkageAttr(D, AL.getRange(), AL.getName(),
+ AL.getAttributeSpellingListIndex()))
D->addAttr(Internal);
}
-static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.OpenCLVersion != 200)
- S.Diag(Attr.getLoc(), diag::err_attribute_requires_opencl_version)
- << Attr.getName() << "2.0" << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
+ << AL.getName() << "2.0" << 0;
else
- S.Diag(Attr.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
- << Attr.getName() << "2.0";
+ S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
+ << AL.getName() << "2.0";
}
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
-static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr) {
+static bool handleCommonAttributeFeatures(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
// Several attributes carry different semantics than the parsing requires, so
// those are opted out of the common argument checks.
//
// We also bail on unknown and ignored attributes because those are handled
// as part of the target-specific handling logic.
- if (Attr.getKind() == AttributeList::UnknownAttribute)
+ if (AL.getKind() == ParsedAttr::UnknownAttribute)
return false;
// Check whether the attribute requires specific language extensions to be
// enabled.
- if (!Attr.diagnoseLangOpts(S))
+ if (!AL.diagnoseLangOpts(S))
return true;
// Check whether the attribute appertains to the given subject.
- if (!Attr.diagnoseAppertainsTo(S, D))
+ if (!AL.diagnoseAppertainsTo(S, D))
return true;
- if (Attr.hasCustomParsing())
+ if (AL.hasCustomParsing())
return false;
- if (Attr.getMinArgs() == Attr.getMaxArgs()) {
+ if (AL.getMinArgs() == AL.getMaxArgs()) {
// If there are no optional arguments, then checking for the argument count
// is trivial.
- if (!checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
+ if (!checkAttributeNumArgs(S, AL, AL.getMinArgs()))
return true;
} else {
// There are optional arguments, so checking is slightly more involved.
- if (Attr.getMinArgs() &&
- !checkAttributeAtLeastNumArgs(S, Attr, Attr.getMinArgs()))
+ if (AL.getMinArgs() &&
+ !checkAttributeAtLeastNumArgs(S, AL, AL.getMinArgs()))
return true;
- else if (!Attr.hasVariadicArg() && Attr.getMaxArgs() &&
- !checkAttributeAtMostNumArgs(S, Attr, Attr.getMaxArgs()))
+ else if (!AL.hasVariadicArg() && AL.getMaxArgs() &&
+ !checkAttributeAtMostNumArgs(S, AL, AL.getMaxArgs()))
return true;
}
+ if (S.CheckAttrTarget(AL))
+ return true;
+
return false;
}
-static void handleOpenCLAccessAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->isInvalidDecl())
return;
// Check if there is only one access qualifier.
if (D->hasAttr<OpenCLAccessAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers)
+ S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
<< D->getSourceRange();
D->setInvalidDecl(true);
return;
@@ -5925,12 +5923,12 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D,
// OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
// object. Using the read_write (or __read_write) qualifier with the pipe
// qualifier is a compilation error.
- if (const ParmVarDecl *PDecl = dyn_cast<ParmVarDecl>(D)) {
+ if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
- if (Attr.getName()->getName().find("read_write") != StringRef::npos) {
+ if (AL.getName()->getName().find("read_write") != StringRef::npos) {
if (S.getLangOpts().OpenCLVersion < 200 || DeclTy->isPipeType()) {
- S.Diag(Attr.getLoc(), diag::err_opencl_invalid_read_write)
- << Attr.getName() << PDecl->getType() << DeclTy->isImageType();
+ S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
+ << AL.getName() << PDecl->getType() << DeclTy->isImageType();
D->setInvalidDecl(true);
return;
}
@@ -5938,7 +5936,7 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context) OpenCLAccessAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
@@ -5949,633 +5947,662 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D,
/// the attribute applies to decls. If the attribute is a type attribute, just
/// silently ignore it if a GNU attribute.
static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr,
+ const ParsedAttr &AL,
bool IncludeCXX11Attributes) {
- if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute)
+ if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
return;
// Ignore C++11 attributes on declarator chunks: they appertain to the type
// instead.
- if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
+ if (AL.isCXX11Attribute() && !IncludeCXX11Attributes)
return;
// Unknown attributes are automatically warned on. Target-specific attributes
// which do not apply to the current target architecture are treated as
// though they were unknown attributes.
- if (Attr.getKind() == AttributeList::UnknownAttribute ||
- !Attr.existsInTarget(S.Context.getTargetInfo())) {
- S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
- ? diag::warn_unhandled_ms_attribute_ignored
- : diag::warn_unknown_attribute_ignored)
- << Attr.getName();
+ if (AL.getKind() == ParsedAttr::UnknownAttribute ||
+ !AL.existsInTarget(S.Context.getTargetInfo())) {
+ S.Diag(AL.getLoc(), AL.isDeclspecAttribute()
+ ? diag::warn_unhandled_ms_attribute_ignored
+ : diag::warn_unknown_attribute_ignored)
+ << AL.getName();
return;
}
- if (handleCommonAttributeFeatures(S, scope, D, Attr))
+ if (handleCommonAttributeFeatures(S, D, AL))
return;
- switch (Attr.getKind()) {
+ switch (AL.getKind()) {
default:
- if (!Attr.isStmtAttr()) {
+ if (!AL.isStmtAttr()) {
// Type attributes are handled elsewhere; silently move on.
- assert(Attr.isTypeAttr() && "Non-type attribute not handled");
+ assert(AL.isTypeAttr() && "Non-type attribute not handled");
break;
}
- S.Diag(Attr.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
- << Attr.getName() << D->getLocation();
+ S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
+ << AL.getName() << D->getLocation();
break;
- case AttributeList::AT_Interrupt:
- handleInterruptAttr(S, D, Attr);
+ case ParsedAttr::AT_Interrupt:
+ handleInterruptAttr(S, D, AL);
break;
- case AttributeList::AT_X86ForceAlignArgPointer:
- handleX86ForceAlignArgPointerAttr(S, D, Attr);
+ case ParsedAttr::AT_X86ForceAlignArgPointer:
+ handleX86ForceAlignArgPointerAttr(S, D, AL);
break;
- case AttributeList::AT_DLLExport:
- case AttributeList::AT_DLLImport:
- handleDLLAttr(S, D, Attr);
+ case ParsedAttr::AT_DLLExport:
+ case ParsedAttr::AT_DLLImport:
+ handleDLLAttr(S, D, AL);
break;
- case AttributeList::AT_Mips16:
+ case ParsedAttr::AT_Mips16:
handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr,
- MipsInterruptAttr>(S, D, Attr);
+ MipsInterruptAttr>(S, D, AL);
break;
- case AttributeList::AT_NoMips16:
- handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
+ case ParsedAttr::AT_NoMips16:
+ handleSimpleAttribute<NoMips16Attr>(S, D, AL);
break;
- case AttributeList::AT_MicroMips:
- handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, Attr);
+ case ParsedAttr::AT_MicroMips:
+ handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL);
break;
- case AttributeList::AT_NoMicroMips:
- handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoMicroMips:
+ handleSimpleAttribute<NoMicroMipsAttr>(S, D, AL);
break;
- case AttributeList::AT_MipsLongCall:
+ case ParsedAttr::AT_MipsLongCall:
handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
- S, D, Attr);
+ S, D, AL);
break;
- case AttributeList::AT_MipsShortCall:
+ case ParsedAttr::AT_MipsShortCall:
handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>(
- S, D, Attr);
+ S, D, AL);
+ break;
+ case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
+ handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_AMDGPUWavesPerEU:
+ handleAMDGPUWavesPerEUAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUFlatWorkGroupSize:
- handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_AMDGPUNumSGPR:
+ handleAMDGPUNumSGPRAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUWavesPerEU:
- handleAMDGPUWavesPerEUAttr(S, D, Attr);
+ case ParsedAttr::AT_AMDGPUNumVGPR:
+ handleAMDGPUNumVGPRAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUNumSGPR:
- handleAMDGPUNumSGPRAttr(S, D, Attr);
+ case ParsedAttr::AT_AVRSignal:
+ handleAVRSignalAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUNumVGPR:
- handleAMDGPUNumVGPRAttr(S, D, Attr);
+ case ParsedAttr::AT_IBAction:
+ handleSimpleAttribute<IBActionAttr>(S, D, AL);
break;
- case AttributeList::AT_AVRSignal:
- handleAVRSignalAttr(S, D, Attr);
+ case ParsedAttr::AT_IBOutlet:
+ handleIBOutlet(S, D, AL);
break;
- case AttributeList::AT_IBAction:
- handleSimpleAttribute<IBActionAttr>(S, D, Attr);
+ case ParsedAttr::AT_IBOutletCollection:
+ handleIBOutletCollection(S, D, AL);
break;
- case AttributeList::AT_IBOutlet:
- handleIBOutlet(S, D, Attr);
+ case ParsedAttr::AT_IFunc:
+ handleIFuncAttr(S, D, AL);
break;
- case AttributeList::AT_IBOutletCollection:
- handleIBOutletCollection(S, D, Attr);
+ case ParsedAttr::AT_Alias:
+ handleAliasAttr(S, D, AL);
break;
- case AttributeList::AT_IFunc:
- handleIFuncAttr(S, D, Attr);
+ case ParsedAttr::AT_Aligned:
+ handleAlignedAttr(S, D, AL);
break;
- case AttributeList::AT_Alias:
- handleAliasAttr(S, D, Attr);
+ case ParsedAttr::AT_AlignValue:
+ handleAlignValueAttr(S, D, AL);
break;
- case AttributeList::AT_Aligned:
- handleAlignedAttr(S, D, Attr);
+ case ParsedAttr::AT_AllocSize:
+ handleAllocSizeAttr(S, D, AL);
break;
- case AttributeList::AT_AlignValue:
- handleAlignValueAttr(S, D, Attr);
+ case ParsedAttr::AT_AlwaysInline:
+ handleAlwaysInlineAttr(S, D, AL);
break;
- case AttributeList::AT_AllocSize:
- handleAllocSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_Artificial:
+ handleSimpleAttribute<ArtificialAttr>(S, D, AL);
break;
- case AttributeList::AT_AlwaysInline:
- handleAlwaysInlineAttr(S, D, Attr);
+ case ParsedAttr::AT_AnalyzerNoReturn:
+ handleAnalyzerNoReturnAttr(S, D, AL);
break;
- case AttributeList::AT_AnalyzerNoReturn:
- handleAnalyzerNoReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_TLSModel:
+ handleTLSModelAttr(S, D, AL);
break;
- case AttributeList::AT_TLSModel:
- handleTLSModelAttr(S, D, Attr);
+ case ParsedAttr::AT_Annotate:
+ handleAnnotateAttr(S, D, AL);
break;
- case AttributeList::AT_Annotate:
- handleAnnotateAttr(S, D, Attr);
+ case ParsedAttr::AT_Availability:
+ handleAvailabilityAttr(S, D, AL);
break;
- case AttributeList::AT_Availability:
- handleAvailabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_CarriesDependency:
+ handleDependencyAttr(S, scope, D, AL);
break;
- case AttributeList::AT_CarriesDependency:
- handleDependencyAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_CPUDispatch:
+ case ParsedAttr::AT_CPUSpecific:
+ handleCPUSpecificAttr(S, D, AL);
break;
- case AttributeList::AT_Common:
- handleCommonAttr(S, D, Attr);
+ case ParsedAttr::AT_Common:
+ handleCommonAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAConstant:
- handleConstantAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDAConstant:
+ handleConstantAttr(S, D, AL);
break;
- case AttributeList::AT_PassObjectSize:
- handlePassObjectSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_PassObjectSize:
+ handlePassObjectSizeAttr(S, D, AL);
break;
- case AttributeList::AT_Constructor:
- handleConstructorAttr(S, D, Attr);
+ case ParsedAttr::AT_Constructor:
+ handleConstructorAttr(S, D, AL);
break;
- case AttributeList::AT_CXX11NoReturn:
- handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
+ case ParsedAttr::AT_CXX11NoReturn:
+ handleSimpleAttribute<CXX11NoReturnAttr>(S, D, AL);
break;
- case AttributeList::AT_Deprecated:
- handleDeprecatedAttr(S, D, Attr);
+ case ParsedAttr::AT_Deprecated:
+ handleDeprecatedAttr(S, D, AL);
break;
- case AttributeList::AT_Destructor:
- handleDestructorAttr(S, D, Attr);
+ case ParsedAttr::AT_Destructor:
+ handleDestructorAttr(S, D, AL);
break;
- case AttributeList::AT_EnableIf:
- handleEnableIfAttr(S, D, Attr);
+ case ParsedAttr::AT_EnableIf:
+ handleEnableIfAttr(S, D, AL);
break;
- case AttributeList::AT_DiagnoseIf:
- handleDiagnoseIfAttr(S, D, Attr);
+ case ParsedAttr::AT_DiagnoseIf:
+ handleDiagnoseIfAttr(S, D, AL);
break;
- case AttributeList::AT_ExtVectorType:
- handleExtVectorTypeAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ExtVectorType:
+ handleExtVectorTypeAttr(S, D, AL);
break;
- case AttributeList::AT_ExternalSourceSymbol:
- handleExternalSourceSymbolAttr(S, D, Attr);
+ case ParsedAttr::AT_ExternalSourceSymbol:
+ handleExternalSourceSymbolAttr(S, D, AL);
break;
- case AttributeList::AT_MinSize:
- handleMinSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_MinSize:
+ handleMinSizeAttr(S, D, AL);
break;
- case AttributeList::AT_OptimizeNone:
- handleOptimizeNoneAttr(S, D, Attr);
+ case ParsedAttr::AT_OptimizeNone:
+ handleOptimizeNoneAttr(S, D, AL);
break;
- case AttributeList::AT_FlagEnum:
- handleSimpleAttribute<FlagEnumAttr>(S, D, Attr);
+ case ParsedAttr::AT_FlagEnum:
+ handleSimpleAttribute<FlagEnumAttr>(S, D, AL);
break;
- case AttributeList::AT_EnumExtensibility:
- handleEnumExtensibilityAttr(S, D, Attr);
+ case ParsedAttr::AT_EnumExtensibility:
+ handleEnumExtensibilityAttr(S, D, AL);
break;
- case AttributeList::AT_Flatten:
- handleSimpleAttribute<FlattenAttr>(S, D, Attr);
+ case ParsedAttr::AT_Flatten:
+ handleSimpleAttribute<FlattenAttr>(S, D, AL);
break;
- case AttributeList::AT_Format:
- handleFormatAttr(S, D, Attr);
+ case ParsedAttr::AT_Format:
+ handleFormatAttr(S, D, AL);
break;
- case AttributeList::AT_FormatArg:
- handleFormatArgAttr(S, D, Attr);
+ case ParsedAttr::AT_FormatArg:
+ handleFormatArgAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAGlobal:
- handleGlobalAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDAGlobal:
+ handleGlobalAttr(S, D, AL);
break;
- case AttributeList::AT_CUDADevice:
+ case ParsedAttr::AT_CUDADevice:
handleSimpleAttributeWithExclusions<CUDADeviceAttr, CUDAGlobalAttr>(S, D,
- Attr);
+ AL);
break;
- case AttributeList::AT_CUDAHost:
- handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D,
- Attr);
+ case ParsedAttr::AT_CUDAHost:
+ handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL);
break;
- case AttributeList::AT_GNUInline:
- handleGNUInlineAttr(S, D, Attr);
+ case ParsedAttr::AT_GNUInline:
+ handleGNUInlineAttr(S, D, AL);
break;
- case AttributeList::AT_CUDALaunchBounds:
- handleLaunchBoundsAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDALaunchBounds:
+ handleLaunchBoundsAttr(S, D, AL);
break;
- case AttributeList::AT_Restrict:
- handleRestrictAttr(S, D, Attr);
+ case ParsedAttr::AT_Restrict:
+ handleRestrictAttr(S, D, AL);
break;
- case AttributeList::AT_MayAlias:
- handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
+ case ParsedAttr::AT_LifetimeBound:
+ handleSimpleAttribute<LifetimeBoundAttr>(S, D, AL);
break;
- case AttributeList::AT_Mode:
- handleModeAttr(S, D, Attr);
+ case ParsedAttr::AT_MayAlias:
+ handleSimpleAttribute<MayAliasAttr>(S, D, AL);
break;
- case AttributeList::AT_NoAlias:
- handleSimpleAttribute<NoAliasAttr>(S, D, Attr);
+ case ParsedAttr::AT_Mode:
+ handleModeAttr(S, D, AL);
break;
- case AttributeList::AT_NoCommon:
- handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoAlias:
+ handleSimpleAttribute<NoAliasAttr>(S, D, AL);
break;
- case AttributeList::AT_NoSplitStack:
- handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoCommon:
+ handleSimpleAttribute<NoCommonAttr>(S, D, AL);
break;
- case AttributeList::AT_NonNull:
- if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
- handleNonNullAttrParameter(S, PVD, Attr);
+ case ParsedAttr::AT_NoSplitStack:
+ handleSimpleAttribute<NoSplitStackAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_NonNull:
+ if (auto *PVD = dyn_cast<ParmVarDecl>(D))
+ handleNonNullAttrParameter(S, PVD, AL);
else
- handleNonNullAttr(S, D, Attr);
+ handleNonNullAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_ReturnsNonNull:
+ handleReturnsNonNullAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_NoEscape:
+ handleNoEscapeAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_AssumeAligned:
+ handleAssumeAlignedAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_AllocAlign:
+ handleAllocAlignAttr(S, D, AL);
break;
- case AttributeList::AT_ReturnsNonNull:
- handleReturnsNonNullAttr(S, D, Attr);
+ case ParsedAttr::AT_Overloadable:
+ handleSimpleAttribute<OverloadableAttr>(S, D, AL);
break;
- case AttributeList::AT_NoEscape:
- handleNoEscapeAttr(S, D, Attr);
+ case ParsedAttr::AT_Ownership:
+ handleOwnershipAttr(S, D, AL);
break;
- case AttributeList::AT_AssumeAligned:
- handleAssumeAlignedAttr(S, D, Attr);
+ case ParsedAttr::AT_Cold:
+ handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL);
break;
- case AttributeList::AT_AllocAlign:
- handleAllocAlignAttr(S, D, Attr);
+ case ParsedAttr::AT_Hot:
+ handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL);
break;
- case AttributeList::AT_Overloadable:
- handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
+ case ParsedAttr::AT_Naked:
+ handleNakedAttr(S, D, AL);
break;
- case AttributeList::AT_Ownership:
- handleOwnershipAttr(S, D, Attr);
+ case ParsedAttr::AT_NoReturn:
+ handleNoReturnAttr(S, D, AL);
break;
- case AttributeList::AT_Cold:
- handleColdAttr(S, D, Attr);
+ case ParsedAttr::AT_AnyX86NoCfCheck:
+ handleNoCfCheckAttr(S, D, AL);
break;
- case AttributeList::AT_Hot:
- handleHotAttr(S, D, Attr);
+ case ParsedAttr::AT_NoThrow:
+ handleSimpleAttribute<NoThrowAttr>(S, D, AL);
break;
- case AttributeList::AT_Naked:
- handleNakedAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDAShared:
+ handleSharedAttr(S, D, AL);
break;
- case AttributeList::AT_NoReturn:
- handleNoReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_VecReturn:
+ handleVecReturnAttr(S, D, AL);
break;
- case AttributeList::AT_NoThrow:
- handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCOwnership:
+ handleObjCOwnershipAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAShared:
- handleSharedAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCPreciseLifetime:
+ handleObjCPreciseLifetimeAttr(S, D, AL);
break;
- case AttributeList::AT_VecReturn:
- handleVecReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCReturnsInnerPointer:
+ handleObjCReturnsInnerPointerAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCOwnership:
- handleObjCOwnershipAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCRequiresSuper:
+ handleObjCRequiresSuperAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCPreciseLifetime:
- handleObjCPreciseLifetimeAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCBridge:
+ handleObjCBridgeAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCReturnsInnerPointer:
- handleObjCReturnsInnerPointerAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCBridgeMutable:
+ handleObjCBridgeMutableAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCRequiresSuper:
- handleObjCRequiresSuperAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCBridgeRelated:
+ handleObjCBridgeRelatedAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridge:
- handleObjCBridgeAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCDesignatedInitializer:
+ handleObjCDesignatedInitializer(S, D, AL);
break;
- case AttributeList::AT_ObjCBridgeMutable:
- handleObjCBridgeMutableAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCRuntimeName:
+ handleObjCRuntimeName(S, D, AL);
break;
- case AttributeList::AT_ObjCBridgeRelated:
- handleObjCBridgeRelatedAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCRuntimeVisible:
+ handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCDesignatedInitializer:
- handleObjCDesignatedInitializer(S, D, Attr);
+ case ParsedAttr::AT_ObjCBoxable:
+ handleObjCBoxable(S, D, AL);
break;
- case AttributeList::AT_ObjCRuntimeName:
- handleObjCRuntimeName(S, D, Attr);
+ case ParsedAttr::AT_CFAuditedTransfer:
+ handleSimpleAttributeWithExclusions<CFAuditedTransferAttr,
+ CFUnknownTransferAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRuntimeVisible:
- handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, Attr);
+ case ParsedAttr::AT_CFUnknownTransfer:
+ handleSimpleAttributeWithExclusions<CFUnknownTransferAttr,
+ CFAuditedTransferAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCBoxable:
- handleObjCBoxable(S, D, Attr);
+ case ParsedAttr::AT_CFConsumed:
+ case ParsedAttr::AT_NSConsumed:
+ handleNSConsumedAttr(S, D, AL);
break;
- case AttributeList::AT_CFAuditedTransfer:
- handleCFAuditedTransferAttr(S, D, Attr);
+ case ParsedAttr::AT_NSConsumesSelf:
+ handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL);
break;
- case AttributeList::AT_CFUnknownTransfer:
- handleCFUnknownTransferAttr(S, D, Attr);
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsRetained:
+ case ParsedAttr::AT_CFReturnsRetained:
+ handleNSReturnsRetainedAttr(S, D, AL);
break;
- case AttributeList::AT_CFConsumed:
- case AttributeList::AT_NSConsumed:
- handleNSConsumedAttr(S, D, Attr);
+ case ParsedAttr::AT_WorkGroupSizeHint:
+ handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
break;
- case AttributeList::AT_NSConsumesSelf:
- handleSimpleAttribute<NSConsumesSelfAttr>(S, D, Attr);
+ case ParsedAttr::AT_ReqdWorkGroupSize:
+ handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
break;
- case AttributeList::AT_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
- case AttributeList::AT_CFReturnsNotRetained:
- case AttributeList::AT_NSReturnsRetained:
- case AttributeList::AT_CFReturnsRetained:
- handleNSReturnsRetainedAttr(S, D, Attr);
+ case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize:
+ handleSubGroupSize(S, D, AL);
break;
- case AttributeList::AT_WorkGroupSizeHint:
- handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, Attr);
+ case ParsedAttr::AT_VecTypeHint:
+ handleVecTypeHint(S, D, AL);
break;
- case AttributeList::AT_ReqdWorkGroupSize:
- handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr);
+ case ParsedAttr::AT_RequireConstantInit:
+ handleSimpleAttribute<RequireConstantInitAttr>(S, D, AL);
break;
- case AttributeList::AT_OpenCLIntelReqdSubGroupSize:
- handleSubGroupSize(S, D, Attr);
+ case ParsedAttr::AT_InitPriority:
+ handleInitPriorityAttr(S, D, AL);
break;
- case AttributeList::AT_VecTypeHint:
- handleVecTypeHint(S, D, Attr);
+ case ParsedAttr::AT_Packed:
+ handlePackedAttr(S, D, AL);
break;
- case AttributeList::AT_RequireConstantInit:
- handleSimpleAttribute<RequireConstantInitAttr>(S, D, Attr);
+ case ParsedAttr::AT_Section:
+ handleSectionAttr(S, D, AL);
break;
- case AttributeList::AT_InitPriority:
- handleInitPriorityAttr(S, D, Attr);
+ case ParsedAttr::AT_CodeSeg:
+ handleCodeSegAttr(S, D, AL);
break;
- case AttributeList::AT_Packed:
- handlePackedAttr(S, D, Attr);
+ case ParsedAttr::AT_Target:
+ handleTargetAttr(S, D, AL);
break;
- case AttributeList::AT_Section:
- handleSectionAttr(S, D, Attr);
+ case ParsedAttr::AT_MinVectorWidth:
+ handleMinVectorWidthAttr(S, D, AL);
break;
- case AttributeList::AT_Target:
- handleTargetAttr(S, D, Attr);
+ case ParsedAttr::AT_Unavailable:
+ handleAttrWithMessage<UnavailableAttr>(S, D, AL);
break;
- case AttributeList::AT_Unavailable:
- handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
+ case ParsedAttr::AT_ArcWeakrefUnavailable:
+ handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, AL);
break;
- case AttributeList::AT_ArcWeakrefUnavailable:
- handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCRootClass:
+ handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRootClass:
- handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCSubclassingRestricted:
+ handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCSubclassingRestricted:
- handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCExplicitProtocolImpl:
+ handleObjCSuppresProtocolAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCExplicitProtocolImpl:
- handleObjCSuppresProtocolAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCRequiresPropertyDefs:
+ handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRequiresPropertyDefs:
- handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr);
+ case ParsedAttr::AT_Unused:
+ handleUnusedAttr(S, D, AL);
break;
- case AttributeList::AT_Unused:
- handleUnusedAttr(S, D, Attr);
+ case ParsedAttr::AT_ReturnsTwice:
+ handleSimpleAttribute<ReturnsTwiceAttr>(S, D, AL);
break;
- case AttributeList::AT_ReturnsTwice:
- handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
+ case ParsedAttr::AT_NotTailCalled:
+ handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>(
+ S, D, AL);
break;
- case AttributeList::AT_NotTailCalled:
- handleNotTailCalledAttr(S, D, Attr);
+ case ParsedAttr::AT_DisableTailCalls:
+ handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
+ AL);
break;
- case AttributeList::AT_DisableTailCalls:
- handleDisableTailCallsAttr(S, D, Attr);
+ case ParsedAttr::AT_Used:
+ handleSimpleAttribute<UsedAttr>(S, D, AL);
break;
- case AttributeList::AT_Used:
- handleUsedAttr(S, D, Attr);
+ case ParsedAttr::AT_Visibility:
+ handleVisibilityAttr(S, D, AL, false);
break;
- case AttributeList::AT_Visibility:
- handleVisibilityAttr(S, D, Attr, false);
+ case ParsedAttr::AT_TypeVisibility:
+ handleVisibilityAttr(S, D, AL, true);
break;
- case AttributeList::AT_TypeVisibility:
- handleVisibilityAttr(S, D, Attr, true);
+ case ParsedAttr::AT_WarnUnused:
+ handleSimpleAttribute<WarnUnusedAttr>(S, D, AL);
break;
- case AttributeList::AT_WarnUnused:
- handleSimpleAttribute<WarnUnusedAttr>(S, D, Attr);
+ case ParsedAttr::AT_WarnUnusedResult:
+ handleWarnUnusedResult(S, D, AL);
break;
- case AttributeList::AT_WarnUnusedResult:
- handleWarnUnusedResult(S, D, Attr);
+ case ParsedAttr::AT_Weak:
+ handleSimpleAttribute<WeakAttr>(S, D, AL);
break;
- case AttributeList::AT_Weak:
- handleSimpleAttribute<WeakAttr>(S, D, Attr);
+ case ParsedAttr::AT_WeakRef:
+ handleWeakRefAttr(S, D, AL);
break;
- case AttributeList::AT_WeakRef:
- handleWeakRefAttr(S, D, Attr);
+ case ParsedAttr::AT_WeakImport:
+ handleWeakImportAttr(S, D, AL);
break;
- case AttributeList::AT_WeakImport:
- handleWeakImportAttr(S, D, Attr);
+ case ParsedAttr::AT_TransparentUnion:
+ handleTransparentUnionAttr(S, D, AL);
break;
- case AttributeList::AT_TransparentUnion:
- handleTransparentUnionAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCException:
+ handleSimpleAttribute<ObjCExceptionAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCException:
- handleSimpleAttribute<ObjCExceptionAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCMethodFamily:
+ handleObjCMethodFamilyAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCMethodFamily:
- handleObjCMethodFamilyAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCNSObject:
+ handleObjCNSObject(S, D, AL);
break;
- case AttributeList::AT_ObjCNSObject:
- handleObjCNSObject(S, D, Attr);
+ case ParsedAttr::AT_ObjCIndependentClass:
+ handleObjCIndependentClass(S, D, AL);
break;
- case AttributeList::AT_ObjCIndependentClass:
- handleObjCIndependentClass(S, D, Attr);
+ case ParsedAttr::AT_Blocks:
+ handleBlocksAttr(S, D, AL);
break;
- case AttributeList::AT_Blocks:
- handleBlocksAttr(S, D, Attr);
+ case ParsedAttr::AT_Sentinel:
+ handleSentinelAttr(S, D, AL);
break;
- case AttributeList::AT_Sentinel:
- handleSentinelAttr(S, D, Attr);
+ case ParsedAttr::AT_Const:
+ handleSimpleAttribute<ConstAttr>(S, D, AL);
break;
- case AttributeList::AT_Const:
- handleSimpleAttribute<ConstAttr>(S, D, Attr);
+ case ParsedAttr::AT_Pure:
+ handleSimpleAttribute<PureAttr>(S, D, AL);
break;
- case AttributeList::AT_Pure:
- handleSimpleAttribute<PureAttr>(S, D, Attr);
+ case ParsedAttr::AT_Cleanup:
+ handleCleanupAttr(S, D, AL);
break;
- case AttributeList::AT_Cleanup:
- handleCleanupAttr(S, D, Attr);
+ case ParsedAttr::AT_NoDebug:
+ handleNoDebugAttr(S, D, AL);
break;
- case AttributeList::AT_NoDebug:
- handleNoDebugAttr(S, D, Attr);
+ case ParsedAttr::AT_NoDuplicate:
+ handleSimpleAttribute<NoDuplicateAttr>(S, D, AL);
break;
- case AttributeList::AT_NoDuplicate:
- handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
+ case ParsedAttr::AT_Convergent:
+ handleSimpleAttribute<ConvergentAttr>(S, D, AL);
break;
- case AttributeList::AT_Convergent:
- handleSimpleAttribute<ConvergentAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoInline:
+ handleSimpleAttribute<NoInlineAttr>(S, D, AL);
break;
- case AttributeList::AT_NoInline:
- handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoInstrumentFunction: // Interacts with -pg.
+ handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, AL);
break;
- case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
- handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoStackProtector:
+ // Interacts with -fstack-protector options.
+ handleSimpleAttribute<NoStackProtectorAttr>(S, D, AL);
break;
- case AttributeList::AT_StdCall:
- case AttributeList::AT_CDecl:
- case AttributeList::AT_FastCall:
- case AttributeList::AT_ThisCall:
- case AttributeList::AT_Pascal:
- case AttributeList::AT_RegCall:
- case AttributeList::AT_SwiftCall:
- case AttributeList::AT_VectorCall:
- case AttributeList::AT_MSABI:
- case AttributeList::AT_SysVABI:
- case AttributeList::AT_Pcs:
- case AttributeList::AT_IntelOclBicc:
- case AttributeList::AT_PreserveMost:
- case AttributeList::AT_PreserveAll:
- handleCallConvAttr(S, D, Attr);
+ case ParsedAttr::AT_StdCall:
+ case ParsedAttr::AT_CDecl:
+ case ParsedAttr::AT_FastCall:
+ case ParsedAttr::AT_ThisCall:
+ case ParsedAttr::AT_Pascal:
+ case ParsedAttr::AT_RegCall:
+ case ParsedAttr::AT_SwiftCall:
+ case ParsedAttr::AT_VectorCall:
+ case ParsedAttr::AT_MSABI:
+ case ParsedAttr::AT_SysVABI:
+ case ParsedAttr::AT_Pcs:
+ case ParsedAttr::AT_IntelOclBicc:
+ case ParsedAttr::AT_PreserveMost:
+ case ParsedAttr::AT_PreserveAll:
+ handleCallConvAttr(S, D, AL);
break;
- case AttributeList::AT_Suppress:
- handleSuppressAttr(S, D, Attr);
+ case ParsedAttr::AT_Suppress:
+ handleSuppressAttr(S, D, AL);
break;
- case AttributeList::AT_OpenCLKernel:
- handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr);
+ case ParsedAttr::AT_OpenCLKernel:
+ handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
break;
- case AttributeList::AT_OpenCLAccess:
- handleOpenCLAccessAttr(S, D, Attr);
+ case ParsedAttr::AT_OpenCLAccess:
+ handleOpenCLAccessAttr(S, D, AL);
break;
- case AttributeList::AT_OpenCLNoSVM:
- handleOpenCLNoSVMAttr(S, D, Attr);
+ case ParsedAttr::AT_OpenCLNoSVM:
+ handleOpenCLNoSVMAttr(S, D, AL);
break;
- case AttributeList::AT_SwiftContext:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftContext);
+ case ParsedAttr::AT_SwiftContext:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftContext);
break;
- case AttributeList::AT_SwiftErrorResult:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftErrorResult);
+ case ParsedAttr::AT_SwiftErrorResult:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftErrorResult);
break;
- case AttributeList::AT_SwiftIndirectResult:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftIndirectResult);
+ case ParsedAttr::AT_SwiftIndirectResult:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftIndirectResult);
break;
- case AttributeList::AT_InternalLinkage:
- handleInternalLinkageAttr(S, D, Attr);
+ case ParsedAttr::AT_InternalLinkage:
+ handleInternalLinkageAttr(S, D, AL);
break;
- case AttributeList::AT_LTOVisibilityPublic:
- handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr);
+ case ParsedAttr::AT_LTOVisibilityPublic:
+ handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);
break;
// Microsoft attributes:
- case AttributeList::AT_EmptyBases:
- handleSimpleAttribute<EmptyBasesAttr>(S, D, Attr);
+ case ParsedAttr::AT_EmptyBases:
+ handleSimpleAttribute<EmptyBasesAttr>(S, D, AL);
break;
- case AttributeList::AT_LayoutVersion:
- handleLayoutVersion(S, D, Attr);
+ case ParsedAttr::AT_LayoutVersion:
+ handleLayoutVersion(S, D, AL);
break;
- case AttributeList::AT_MSNoVTable:
- handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr);
+ case ParsedAttr::AT_TrivialABI:
+ handleSimpleAttribute<TrivialABIAttr>(S, D, AL);
break;
- case AttributeList::AT_MSStruct:
- handleSimpleAttribute<MSStructAttr>(S, D, Attr);
+ case ParsedAttr::AT_MSNoVTable:
+ handleSimpleAttribute<MSNoVTableAttr>(S, D, AL);
break;
- case AttributeList::AT_Uuid:
- handleUuidAttr(S, D, Attr);
+ case ParsedAttr::AT_MSStruct:
+ handleSimpleAttribute<MSStructAttr>(S, D, AL);
break;
- case AttributeList::AT_MSInheritance:
- handleMSInheritanceAttr(S, D, Attr);
+ case ParsedAttr::AT_Uuid:
+ handleUuidAttr(S, D, AL);
break;
- case AttributeList::AT_SelectAny:
- handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
+ case ParsedAttr::AT_MSInheritance:
+ handleMSInheritanceAttr(S, D, AL);
break;
- case AttributeList::AT_Thread:
- handleDeclspecThreadAttr(S, D, Attr);
+ case ParsedAttr::AT_SelectAny:
+ handleSimpleAttribute<SelectAnyAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_Thread:
+ handleDeclspecThreadAttr(S, D, AL);
break;
- case AttributeList::AT_AbiTag:
- handleAbiTagAttr(S, D, Attr);
+ case ParsedAttr::AT_AbiTag:
+ handleAbiTagAttr(S, D, AL);
break;
// Thread safety attributes:
- case AttributeList::AT_AssertExclusiveLock:
- handleAssertExclusiveLockAttr(S, D, Attr);
+ case ParsedAttr::AT_AssertExclusiveLock:
+ handleAssertExclusiveLockAttr(S, D, AL);
break;
- case AttributeList::AT_AssertSharedLock:
- handleAssertSharedLockAttr(S, D, Attr);
+ case ParsedAttr::AT_AssertSharedLock:
+ handleAssertSharedLockAttr(S, D, AL);
break;
- case AttributeList::AT_GuardedVar:
- handleSimpleAttribute<GuardedVarAttr>(S, D, Attr);
+ case ParsedAttr::AT_GuardedVar:
+ handleSimpleAttribute<GuardedVarAttr>(S, D, AL);
break;
- case AttributeList::AT_PtGuardedVar:
- handlePtGuardedVarAttr(S, D, Attr);
+ case ParsedAttr::AT_PtGuardedVar:
+ handlePtGuardedVarAttr(S, D, AL);
break;
- case AttributeList::AT_ScopedLockable:
- handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
+ case ParsedAttr::AT_ScopedLockable:
+ handleSimpleAttribute<ScopedLockableAttr>(S, D, AL);
break;
- case AttributeList::AT_NoSanitize:
- handleNoSanitizeAttr(S, D, Attr);
+ case ParsedAttr::AT_NoSanitize:
+ handleNoSanitizeAttr(S, D, AL);
break;
- case AttributeList::AT_NoSanitizeSpecific:
- handleNoSanitizeSpecificAttr(S, D, Attr);
+ case ParsedAttr::AT_NoSanitizeSpecific:
+ handleNoSanitizeSpecificAttr(S, D, AL);
break;
- case AttributeList::AT_NoThreadSafetyAnalysis:
- handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoThreadSafetyAnalysis:
+ handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, AL);
break;
- case AttributeList::AT_GuardedBy:
- handleGuardedByAttr(S, D, Attr);
+ case ParsedAttr::AT_GuardedBy:
+ handleGuardedByAttr(S, D, AL);
break;
- case AttributeList::AT_PtGuardedBy:
- handlePtGuardedByAttr(S, D, Attr);
+ case ParsedAttr::AT_PtGuardedBy:
+ handlePtGuardedByAttr(S, D, AL);
break;
- case AttributeList::AT_ExclusiveTrylockFunction:
- handleExclusiveTrylockFunctionAttr(S, D, Attr);
+ case ParsedAttr::AT_ExclusiveTrylockFunction:
+ handleExclusiveTrylockFunctionAttr(S, D, AL);
break;
- case AttributeList::AT_LockReturned:
- handleLockReturnedAttr(S, D, Attr);
+ case ParsedAttr::AT_LockReturned:
+ handleLockReturnedAttr(S, D, AL);
break;
- case AttributeList::AT_LocksExcluded:
- handleLocksExcludedAttr(S, D, Attr);
+ case ParsedAttr::AT_LocksExcluded:
+ handleLocksExcludedAttr(S, D, AL);
break;
- case AttributeList::AT_SharedTrylockFunction:
- handleSharedTrylockFunctionAttr(S, D, Attr);
+ case ParsedAttr::AT_SharedTrylockFunction:
+ handleSharedTrylockFunctionAttr(S, D, AL);
break;
- case AttributeList::AT_AcquiredBefore:
- handleAcquiredBeforeAttr(S, D, Attr);
+ case ParsedAttr::AT_AcquiredBefore:
+ handleAcquiredBeforeAttr(S, D, AL);
break;
- case AttributeList::AT_AcquiredAfter:
- handleAcquiredAfterAttr(S, D, Attr);
+ case ParsedAttr::AT_AcquiredAfter:
+ handleAcquiredAfterAttr(S, D, AL);
break;
// Capability analysis attributes.
- case AttributeList::AT_Capability:
- case AttributeList::AT_Lockable:
- handleCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_Capability:
+ case ParsedAttr::AT_Lockable:
+ handleCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_RequiresCapability:
- handleRequiresCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_RequiresCapability:
+ handleRequiresCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_AssertCapability:
- handleAssertCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_AssertCapability:
+ handleAssertCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_AcquireCapability:
- handleAcquireCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_AcquireCapability:
+ handleAcquireCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_ReleaseCapability:
- handleReleaseCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_ReleaseCapability:
+ handleReleaseCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_TryAcquireCapability:
- handleTryAcquireCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_TryAcquireCapability:
+ handleTryAcquireCapabilityAttr(S, D, AL);
break;
// Consumed analysis attributes.
- case AttributeList::AT_Consumable:
- handleConsumableAttr(S, D, Attr);
+ case ParsedAttr::AT_Consumable:
+ handleConsumableAttr(S, D, AL);
break;
- case AttributeList::AT_ConsumableAutoCast:
- handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, Attr);
+ case ParsedAttr::AT_ConsumableAutoCast:
+ handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, AL);
break;
- case AttributeList::AT_ConsumableSetOnRead:
- handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, Attr);
+ case ParsedAttr::AT_ConsumableSetOnRead:
+ handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, AL);
break;
- case AttributeList::AT_CallableWhen:
- handleCallableWhenAttr(S, D, Attr);
+ case ParsedAttr::AT_CallableWhen:
+ handleCallableWhenAttr(S, D, AL);
break;
- case AttributeList::AT_ParamTypestate:
- handleParamTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_ParamTypestate:
+ handleParamTypestateAttr(S, D, AL);
break;
- case AttributeList::AT_ReturnTypestate:
- handleReturnTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_ReturnTypestate:
+ handleReturnTypestateAttr(S, D, AL);
break;
- case AttributeList::AT_SetTypestate:
- handleSetTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_SetTypestate:
+ handleSetTypestateAttr(S, D, AL);
break;
- case AttributeList::AT_TestTypestate:
- handleTestTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_TestTypestate:
+ handleTestTypestateAttr(S, D, AL);
break;
// Type safety attributes.
- case AttributeList::AT_ArgumentWithTypeTag:
- handleArgumentWithTypeTagAttr(S, D, Attr);
+ case ParsedAttr::AT_ArgumentWithTypeTag:
+ handleArgumentWithTypeTagAttr(S, D, AL);
break;
- case AttributeList::AT_TypeTagForDatatype:
- handleTypeTagForDatatypeAttr(S, D, Attr);
+ case ParsedAttr::AT_TypeTagForDatatype:
+ handleTypeTagForDatatypeAttr(S, D, AL);
break;
- case AttributeList::AT_AnyX86NoCallerSavedRegisters:
- handleNoCallerSavedRegsAttr(S, D, Attr);
+ case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:
+ handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);
break;
- case AttributeList::AT_RenderScriptKernel:
- handleSimpleAttribute<RenderScriptKernelAttr>(S, D, Attr);
+ case ParsedAttr::AT_RenderScriptKernel:
+ handleSimpleAttribute<RenderScriptKernelAttr>(S, D, AL);
break;
// XRay attributes.
- case AttributeList::AT_XRayInstrument:
- handleSimpleAttribute<XRayInstrumentAttr>(S, D, Attr);
+ case ParsedAttr::AT_XRayInstrument:
+ handleSimpleAttribute<XRayInstrumentAttr>(S, D, AL);
break;
- case AttributeList::AT_XRayLogArgs:
- handleXRayLogArgsAttr(S, D, Attr);
+ case ParsedAttr::AT_XRayLogArgs:
+ handleXRayLogArgsAttr(S, D, AL);
break;
}
}
@@ -6583,18 +6610,21 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
/// attribute list to the specified decl, ignoring any type attributes.
void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
- const AttributeList *AttrList,
+ const ParsedAttributesView &AttrList,
bool IncludeCXX11Attributes) {
- for (const AttributeList* l = AttrList; l; l = l->getNext())
- ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes);
+ if (AttrList.empty())
+ return;
+
+ for (const ParsedAttr &AL : AttrList)
+ ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes);
// FIXME: We should be able to handle these cases in TableGen.
// GCC accepts
// static int a9 __attribute__((weakref));
// but that looks really pointless. We reject it.
if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
- Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias)
- << cast<NamedDecl>(D);
+ Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias)
+ << cast<NamedDecl>(D);
D->dropAttr<WeakRefAttr>();
return;
}
@@ -6605,79 +6635,83 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
// attribute must never appear as a group" for attributes like cold and hot.
if (!D->hasAttr<OpenCLKernelAttr>()) {
// These attributes cannot be applied to a non-kernel function.
- if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
+ if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
// FIXME: This emits a different error message than
// diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
+ } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
+ } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
+ } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
+ } else if (!D->hasAttr<CUDAGlobalAttr>()) {
+ if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ }
}
}
}
// Helper for delayed processing TransparentUnion attribute.
-void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) {
- for (const AttributeList *Attr = AttrList; Attr; Attr = Attr->getNext())
- if (Attr->getKind() == AttributeList::AT_TransparentUnion) {
- handleTransparentUnionAttr(*this, D, *Attr);
+void Sema::ProcessDeclAttributeDelayed(Decl *D,
+ const ParsedAttributesView &AttrList) {
+ for (const ParsedAttr &AL : AttrList)
+ if (AL.getKind() == ParsedAttr::AT_TransparentUnion) {
+ handleTransparentUnionAttr(*this, D, AL);
break;
}
}
// Annotation attributes are the only attributes allowed after an access
// specifier.
-bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
- const AttributeList *AttrList) {
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (l->getKind() == AttributeList::AT_Annotate) {
- ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute());
+bool Sema::ProcessAccessDeclAttributeList(
+ AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) {
+ for (const ParsedAttr &AL : AttrList) {
+ if (AL.getKind() == ParsedAttr::AT_Annotate) {
+ ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute());
} else {
- Diag(l->getLoc(), diag::err_only_annotate_after_access_spec);
+ Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec);
return true;
}
}
-
return false;
}
/// checkUnusedDeclAttributes - Check a list of attributes to see if it
/// contains any decl attributes that we should warn about.
-static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
- for ( ; A; A = A->getNext()) {
+static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) {
+ for (const ParsedAttr &AL : A) {
// Only warn if the attribute is an unignored, non-type attribute.
- if (A->isUsedAsTypeAttr() || A->isInvalid()) continue;
- if (A->getKind() == AttributeList::IgnoredAttribute) continue;
+ if (AL.isUsedAsTypeAttr() || AL.isInvalid())
+ continue;
+ if (AL.getKind() == ParsedAttr::IgnoredAttribute)
+ continue;
- if (A->getKind() == AttributeList::UnknownAttribute) {
- S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored)
- << A->getName() << A->getRange();
+ if (AL.getKind() == ParsedAttr::UnknownAttribute) {
+ S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
+ << AL.getName() << AL.getRange();
} else {
- S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl)
- << A->getName() << A->getRange();
+ S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl)
+ << AL.getName() << AL.getRange();
}
}
}
@@ -6686,7 +6720,7 @@ static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
/// used to build a declaration, complain about any decl attributes
/// which might be lying around on it.
void Sema::checkUnusedDeclAttributes(Declarator &D) {
- ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList());
+ ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes());
::checkUnusedDeclAttributes(*this, D.getAttributes());
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
@@ -6698,7 +6732,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
SourceLocation Loc) {
assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
NamedDecl *NewD = nullptr;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
FunctionDecl *NewFD;
// FIXME: Missing call to CheckFunctionDeclaration().
// FIXME: Mangling?
@@ -6718,7 +6752,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
// Fake up parameter variables; they are declared as if this were
// a typedef.
QualType FDTy = FD->getType();
- if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
+ if (const auto *FT = FDTy->getAs<FunctionProtoType>()) {
SmallVector<ParmVarDecl*, 16> Params;
for (const auto &AI : FT->param_types()) {
ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
@@ -6727,15 +6761,13 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
}
NewFD->setParams(Params);
}
- } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ } else if (auto *VD = dyn_cast<VarDecl>(ND)) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
VD->getInnerLocStart(), VD->getLocation(), II,
VD->getType(), VD->getTypeSourceInfo(),
VD->getStorageClass());
- if (VD->getQualifier()) {
- VarDecl *NewVD = cast<VarDecl>(NewD);
- NewVD->setQualifierInfo(VD->getQualifierLoc());
- }
+ if (VD->getQualifier())
+ cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc());
}
return NewD;
}
@@ -6771,10 +6803,10 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
LoadExternalWeakUndeclaredIdentifiers();
if (!WeakUndeclaredIdentifiers.empty()) {
NamedDecl *ND = nullptr;
- if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (auto *VD = dyn_cast<VarDecl>(D))
if (VD->isExternC())
ND = VD;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
if (FD->isExternC())
ND = FD;
if (ND) {
@@ -6795,20 +6827,19 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
/// specified in many different places, and we need to find and apply them all.
void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Apply decl attributes from the DeclSpec if present.
- if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
- ProcessDeclAttributeList(S, D, Attrs);
+ if (!PD.getDeclSpec().getAttributes().empty())
+ ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes());
// Walk the declarator structure, applying decl attributes that were in a type
// position to the decl itself. This handles cases like:
// int *__attr__(x)** D;
// when X is a decl attribute.
for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
- if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
- ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false);
+ ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(),
+ /*IncludeCXX11Attributes=*/false);
// Finally, apply any attributes on the decl itself.
- if (const AttributeList *Attrs = PD.getAttributes())
- ProcessDeclAttributeList(S, D, Attrs);
+ ProcessDeclAttributeList(S, D, PD.getAttributes());
// Apply additional attributes specified by '#pragma clang attribute'.
AddPragmaAttributes(S, D);
@@ -6817,14 +6848,14 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
/// Is the given declaration allowed to use a forbidden type?
/// If so, it'll still be annotated with an attribute that makes it
/// illegal to actually use.
-static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
+static bool isForbiddenTypeAllowed(Sema &S, Decl *D,
const DelayedDiagnostic &diag,
UnavailableAttr::ImplicitReason &reason) {
// Private ivars are always okay. Unfortunately, people don't
// always properly make their ivars private, even in system headers.
// Plus we need to make fields okay, too.
- if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) &&
- !isa<FunctionDecl>(decl))
+ if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) &&
+ !isa<FunctionDecl>(D))
return false;
// Silently accept unsupported uses of __weak in both user and system
@@ -6832,7 +6863,7 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
// -fno-objc-arc files. We do have to take some care against attempts
// to define such things; for now, we've only done that for ivars
// and properties.
- if ((isa<ObjCIvarDecl>(decl) || isa<ObjCPropertyDecl>(decl))) {
+ if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) {
if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
reason = UnavailableAttr::IR_ForbiddenWeak;
@@ -6841,7 +6872,7 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
}
// Allow all sorts of things in system headers.
- if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) {
+ if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) {
// Currently, all the failures dealt with this way are due to ARC
// restrictions.
reason = UnavailableAttr::IR_ARCForbiddenType;
@@ -6852,30 +6883,29 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
}
/// Handle a delayed forbidden-type diagnostic.
-static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
- Decl *decl) {
- auto reason = UnavailableAttr::IR_None;
- if (decl && isForbiddenTypeAllowed(S, decl, diag, reason)) {
- assert(reason && "didn't set reason?");
- decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", reason,
- diag.Loc));
+static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD,
+ Decl *D) {
+ auto Reason = UnavailableAttr::IR_None;
+ if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) {
+ assert(Reason && "didn't set reason?");
+ D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc));
return;
}
if (S.getLangOpts().ObjCAutoRefCount)
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// FIXME: we may want to suppress diagnostics for all
- // kind of forbidden type messages on unavailable functions.
+ // kind of forbidden type messages on unavailable functions.
if (FD->hasAttr<UnavailableAttr>() &&
- diag.getForbiddenTypeDiagnostic() ==
- diag::err_arc_array_param_no_ownership) {
- diag.Triggered = true;
+ DD.getForbiddenTypeDiagnostic() ==
+ diag::err_arc_array_param_no_ownership) {
+ DD.Triggered = true;
return;
}
}
- S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
- << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument();
- diag.Triggered = true;
+ S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic())
+ << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument();
+ DD.Triggered = true;
}
static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
@@ -6918,9 +6948,9 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
// For typedefs, if the typedef declaration appears available look
// to the underlying type to see if it is more restrictive.
- while (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ while (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
if (Result == AR_Available) {
- if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+ if (const auto *TT = TD->getUnderlyingType()->getAs<TagType>()) {
D = TT->getDecl();
Result = D->getAvailability(Message);
continue;
@@ -6930,7 +6960,7 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
}
// Forward class declarations get their attributes from their definition.
- if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
+ if (const auto *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
if (IDecl->getDefinition()) {
D = IDecl->getDefinition();
Result = D->getAvailability(Message);
@@ -6950,7 +6980,7 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
}
-/// \brief whether we should emit a diagnostic for \c K and \c DeclVersion in
+/// whether we should emit a diagnostic for \c K and \c DeclVersion in
/// the context of \c Ctx. For example, we should emit an unavailable diagnostic
/// in a deprecated context, but not the other way around.
static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
@@ -6973,40 +7003,24 @@ static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
return false;
};
- // FIXME: This is a temporary workaround! Some existing Apple headers depends
- // on nested declarations in an @interface having the availability of the
- // interface when they really shouldn't: they are members of the enclosing
- // context, and can referenced from there.
- if (S.OriginalLexicalContext && cast<Decl>(S.OriginalLexicalContext) != Ctx) {
- auto *OrigCtx = cast<Decl>(S.OriginalLexicalContext);
- if (CheckContext(OrigCtx))
- return false;
-
- // An implementation implicitly has the availability of the interface.
- if (auto *CatOrImpl = dyn_cast<ObjCImplDecl>(OrigCtx)) {
- if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface())
- if (CheckContext(Interface))
- return false;
- }
- // A category implicitly has the availability of the interface.
- else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(OrigCtx))
- if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
- if (CheckContext(Interface))
- return false;
- }
-
do {
if (CheckContext(Ctx))
return false;
// An implementation implicitly has the availability of the interface.
- if (auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) {
+ // Unless it is "+load" method.
+ if (const auto *MethodD = dyn_cast<ObjCMethodDecl>(Ctx))
+ if (MethodD->isClassMethod() &&
+ MethodD->getSelector().getAsString() == "load")
+ return true;
+
+ if (const auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) {
if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface())
if (CheckContext(Interface))
return false;
}
// A category implicitly has the availability of the interface.
- else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx))
+ else if (const auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx))
if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
if (CheckContext(Interface))
return false;
@@ -7076,6 +7090,45 @@ struct AttributeInsertion {
} // end anonymous namespace
+/// Tries to parse a string as ObjC method name.
+///
+/// \param Name The string to parse. Expected to originate from availability
+/// attribute argument.
+/// \param SlotNames The vector that will be populated with slot names. In case
+/// of unsuccessful parsing can contain invalid data.
+/// \returns A number of method parameters if parsing was successful, None
+/// otherwise.
+static Optional<unsigned>
+tryParseObjCMethodName(StringRef Name, SmallVectorImpl<StringRef> &SlotNames,
+ const LangOptions &LangOpts) {
+ // Accept replacements starting with - or + as valid ObjC method names.
+ if (!Name.empty() && (Name.front() == '-' || Name.front() == '+'))
+ Name = Name.drop_front(1);
+ if (Name.empty())
+ return None;
+ Name.split(SlotNames, ':');
+ unsigned NumParams;
+ if (Name.back() == ':') {
+ // Remove an empty string at the end that doesn't represent any slot.
+ SlotNames.pop_back();
+ NumParams = SlotNames.size();
+ } else {
+ if (SlotNames.size() != 1)
+ // Not a valid method name, just a colon-separated string.
+ return None;
+ NumParams = 0;
+ }
+ // Verify all slot names are valid.
+ bool AllowDollar = LangOpts.DollarIdents;
+ for (StringRef S : SlotNames) {
+ if (S.empty())
+ continue;
+ if (!isValidIdentifier(S, AllowDollar))
+ return None;
+ }
+ return NumParams;
+}
+
/// Returns a source location in which it's appropriate to insert a new
/// attribute for the given declaration \D.
static Optional<AttributeInsertion>
@@ -7105,14 +7158,15 @@ createAttributeInsertion(const NamedDecl *D, const SourceManager &SM,
/// \param Ctx The context that the reference occurred in
/// \param ReferringDecl The exact declaration that was referenced.
/// \param OffendingDecl A related decl to \c ReferringDecl that has an
-/// availability attribute corrisponding to \c K attached to it. Note that this
+/// availability attribute corresponding to \c K attached to it. Note that this
/// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated and
/// we refer to a member EnumConstantDecl, ReferringDecl is the EnumConstantDecl
/// and OffendingDecl is the EnumDecl.
static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
Decl *Ctx, const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
- StringRef Message, SourceLocation Loc,
+ StringRef Message,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
@@ -7134,6 +7188,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
return;
+ SourceLocation Loc = Locs.front();
+
// The declaration can have multiple availability attributes, we are looking
// at one of them.
const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
@@ -7177,7 +7233,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
<< OffendingDecl << /* partial */ 3;
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
- if (auto *TD = dyn_cast<TagDecl>(Enclosing))
+ if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
if (TD->getDeclName().isEmpty()) {
S.Diag(TD->getLocation(),
diag::note_decl_unguarded_availability_silence)
@@ -7218,8 +7274,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 *AL = OffendingDecl->getAttr<DeprecatedAttr>())
+ NoteLocation = AL->getLocation();
break;
case AR_Unavailable:
@@ -7230,8 +7286,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 AL = OffendingDecl->getAttr<UnavailableAttr>()) {
+ if (AL->isImplicit() && AL->getImplicitReason()) {
// Most of these failures are due to extra restrictions in ARC;
// reflect that in the primary diagnostic when applicable.
auto flagARCError = [&] {
@@ -7241,7 +7297,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
diag = diag::err_unavailable_in_arc;
};
- switch (Attr->getImplicitReason()) {
+ switch (AL->getImplicitReason()) {
case UnavailableAttr::IR_None: break;
case UnavailableAttr::IR_ARCForbiddenType:
@@ -7279,37 +7335,55 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
llvm_unreachable("Warning for availability of available declaration?");
}
- CharSourceRange UseRange;
- StringRef Replacement;
+ SmallVector<FixItHint, 12> FixIts;
if (K == AR_Deprecated) {
- if (auto Attr = OffendingDecl->getAttr<DeprecatedAttr>())
- Replacement = Attr->getReplacement();
- if (auto Attr = getAttrForPlatform(S.Context, OffendingDecl))
- Replacement = Attr->getReplacement();
+ StringRef Replacement;
+ if (auto AL = OffendingDecl->getAttr<DeprecatedAttr>())
+ Replacement = AL->getReplacement();
+ if (auto AL = getAttrForPlatform(S.Context, OffendingDecl))
+ Replacement = AL->getReplacement();
+ CharSourceRange UseRange;
if (!Replacement.empty())
UseRange =
CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+ if (UseRange.isValid()) {
+ if (const auto *MethodDecl = dyn_cast<ObjCMethodDecl>(ReferringDecl)) {
+ Selector Sel = MethodDecl->getSelector();
+ SmallVector<StringRef, 12> SelectorSlotNames;
+ Optional<unsigned> NumParams = tryParseObjCMethodName(
+ Replacement, SelectorSlotNames, S.getLangOpts());
+ if (NumParams && NumParams.getValue() == Sel.getNumArgs()) {
+ assert(SelectorSlotNames.size() == Locs.size());
+ for (unsigned I = 0; I < Locs.size(); ++I) {
+ if (!Sel.getNameForSlot(I).empty()) {
+ CharSourceRange NameRange = CharSourceRange::getCharRange(
+ Locs[I], S.getLocForEndOfToken(Locs[I]));
+ FixIts.push_back(FixItHint::CreateReplacement(
+ NameRange, SelectorSlotNames[I]));
+ } else
+ FixIts.push_back(
+ FixItHint::CreateInsertion(Locs[I], SelectorSlotNames[I]));
+ }
+ } else
+ FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
+ } else
+ FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
+ }
}
if (!Message.empty()) {
- S.Diag(Loc, diag_message) << ReferringDecl << Message
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag_message) << ReferringDecl << Message << FixIts;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
<< ObjCProperty->getDeclName() << property_note_select;
} else if (!UnknownObjCClass) {
- S.Diag(Loc, diag) << ReferringDecl
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag) << ReferringDecl << FixIts;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
<< ObjCProperty->getDeclName() << property_note_select;
} else {
- S.Diag(Loc, diag_fwdclass_message) << ReferringDecl
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag_fwdclass_message) << ReferringDecl << FixIts;
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
@@ -7325,8 +7399,9 @@ static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
DD.Triggered = true;
DoEmitAvailabilityWarning(
S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl(),
- DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(), DD.Loc,
- DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
+ DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(),
+ DD.getAvailabilitySelectorLocs(), DD.getUnknownObjCClass(),
+ DD.getObjCProperty(), false);
}
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -7387,7 +7462,8 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
- StringRef Message, SourceLocation Loc,
+ StringRef Message,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
@@ -7395,14 +7471,14 @@ static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
DelayedDiagnostic::makeAvailability(
- AR, Loc, ReferringDecl, OffendingDecl, UnknownObjCClass,
+ AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass,
ObjCProperty, Message, ObjCPropertyAccess));
return;
}
Decl *Ctx = cast<Decl>(S.getCurLexicalContext());
DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl,
- Message, Loc, UnknownObjCClass, ObjCProperty,
+ Message, Locs, UnknownObjCClass, ObjCProperty,
ObjCPropertyAccess);
}
@@ -7471,7 +7547,7 @@ public:
}
};
-/// \brief This class implements -Wunguarded-availability.
+/// This class implements -Wunguarded-availability.
///
/// This is done with a traversal of the AST of a function that makes reference
/// to a partially available declaration. Whenever we encounter an \c if of the
@@ -7642,7 +7718,7 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
SourceLocation StmtEndLoc =
SM.getExpansionRange(
(LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd())
- .second;
+ .getEnd();
if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
return;
@@ -7681,11 +7757,11 @@ bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) {
if (Range.isInvalid())
return true;
- if (const TagType *TT = dyn_cast<TagType>(TyPtr)) {
+ if (const auto *TT = dyn_cast<TagType>(TyPtr)) {
TagDecl *TD = TT->getDecl();
DiagnoseDeclAvailability(TD, Range);
- } else if (const TypedefType *TD = dyn_cast<TypedefType>(TyPtr)) {
+ } else if (const auto *TD = dyn_cast<TypedefType>(TyPtr)) {
TypedefNameDecl *D = TD->getDecl();
DiagnoseDeclAvailability(D, Range);
@@ -7740,7 +7816,8 @@ void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) {
DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body);
}
-void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
+void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks) {
@@ -7769,7 +7846,7 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
}
const ObjCPropertyDecl *ObjCPDecl = nullptr;
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
if (PDeclResult == Result)
@@ -7777,6 +7854,6 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
}
}
- EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Loc,
+ EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Locs,
UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index 5e24649c71be..4cf3abdf5745 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -170,43 +171,40 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
if (EST == EST_None && Method->hasAttr<NoThrowAttr>())
EST = EST_BasicNoexcept;
- switch(EST) {
+ switch (EST) {
+ case EST_Unparsed:
+ case EST_Uninstantiated:
+ case EST_Unevaluated:
+ llvm_unreachable("should not see unresolved exception specs here");
+
// If this function can throw any exceptions, make a note of that.
case EST_MSAny:
case EST_None:
+ // FIXME: Whichever we see last of MSAny and None determines our result.
+ // We should make a consistent, order-independent choice here.
ClearExceptions();
ComputedEST = EST;
return;
+ case EST_NoexceptFalse:
+ ClearExceptions();
+ ComputedEST = EST_None;
+ return;
// FIXME: If the call to this decl is using any of its default arguments, we
// need to search them for potentially-throwing calls.
// If this function has a basic noexcept, it doesn't affect the outcome.
case EST_BasicNoexcept:
+ case EST_NoexceptTrue:
return;
- // If we're still at noexcept(true) and there's a nothrow() callee,
+ // If we're still at noexcept(true) and there's a throw() callee,
// change to that specification.
case EST_DynamicNone:
if (ComputedEST == EST_BasicNoexcept)
ComputedEST = EST_DynamicNone;
return;
- // Check out noexcept specs.
- case EST_ComputedNoexcept:
- {
- FunctionProtoType::NoexceptResult NR =
- Proto->getNoexceptSpec(Self->Context);
- assert(NR != FunctionProtoType::NR_NoNoexcept &&
- "Must have noexcept result for EST_ComputedNoexcept.");
- assert(NR != FunctionProtoType::NR_Dependent &&
- "Should not generate implicit declarations for dependent cases, "
- "and don't know how to handle them anyway.");
- // noexcept(false) -> no spec on the new function
- if (NR == FunctionProtoType::NR_Throw) {
- ClearExceptions();
- ComputedEST = EST_None;
- }
- // noexcept(true) won't change anything either.
- return;
- }
- default:
+ case EST_DependentNoexcept:
+ llvm_unreachable(
+ "should not generate implicit declarations for dependent cases");
+ case EST_Dynamic:
break;
}
assert(EST == EST_Dynamic && "EST case not considered earlier.");
@@ -1459,7 +1457,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
DD->setInvalidDecl();
}
-/// \brief Merge the exception specifications of two variable declarations.
+/// Merge the exception specifications of two variable declarations.
///
/// This is called when there's a redeclaration of a VarDecl. The function
/// checks if the redeclaration might have an exception specification and
@@ -1575,7 +1573,7 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
return true;
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// record diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -2061,27 +2059,39 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
return true;
}
+/// Get the class that is directly named by the current context. This is the
+/// class for which an unqualified-id in this scope could name a constructor
+/// or destructor.
+///
+/// If the scope specifier denotes a class, this will be that class.
+/// If the scope specifier is empty, this will be the class whose
+/// member-specification we are currently within. Otherwise, there
+/// is no such class.
+CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) {
+ assert(getLangOpts().CPlusPlus && "No class names in C!");
+
+ if (SS && SS->isInvalid())
+ return nullptr;
+
+ if (SS && SS->isNotEmpty()) {
+ DeclContext *DC = computeDeclContext(*SS, true);
+ return dyn_cast_or_null<CXXRecordDecl>(DC);
+ }
+
+ return dyn_cast_or_null<CXXRecordDecl>(CurContext);
+}
+
/// isCurrentClassName - Determine whether the identifier II is the
/// name of the class type currently being defined. In the case of
/// nested classes, this will only return true if II is the name of
/// the innermost class.
-bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
+bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
- assert(getLangOpts().CPlusPlus && "No class names in C!");
-
- CXXRecordDecl *CurDecl;
- if (SS && SS->isSet() && !SS->isInvalid()) {
- DeclContext *DC = computeDeclContext(*SS, true);
- CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
- } else
- CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
-
- if (CurDecl && CurDecl->getIdentifier())
- return &II == CurDecl->getIdentifier();
- return false;
+ CXXRecordDecl *CurDecl = getCurrentClass(S, SS);
+ return CurDecl && &II == CurDecl->getIdentifier();
}
-/// \brief Determine whether the identifier II is a typo for the name of
+/// Determine whether the identifier II is a typo for the name of
/// the class type currently being defined. If so, update it to the identifier
/// that should have been used.
bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
@@ -2107,7 +2117,7 @@ bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
return false;
}
-/// \brief Determine whether the given class is a base class of the given
+/// Determine whether the given class is a base class of the given
/// class, including looking at dependent bases.
static bool findCircularInheritance(const CXXRecordDecl *Class,
const CXXRecordDecl *Current) {
@@ -2139,7 +2149,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
return false;
}
-/// \brief Check the validity of a C++ base class specifier.
+/// Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
/// and returns NULL otherwise.
@@ -2233,6 +2243,19 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
+ // Microsoft docs say:
+ // "If a base-class has a code_seg attribute, derived classes must have the
+ // same attribute."
+ const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>();
+ const auto *DerivedCSA = Class->getAttr<CodeSegAttr>();
+ if ((DerivedCSA || BaseCSA) &&
+ (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) {
+ Diag(Class->getLocation(), diag::err_mismatched_code_seg_base);
+ Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here)
+ << CXXBaseDecl;
+ return nullptr;
+ }
+
// A class which contains a flexible array member is not suitable for use as a
// base class:
// - If the layout determines that a base comes before another base,
@@ -2290,18 +2313,13 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
// We do not support any C++11 attributes on base-specifiers yet.
// Diagnose any attributes we see.
- if (!Attributes.empty()) {
- for (AttributeList *Attr = Attributes.getList(); Attr;
- Attr = Attr->getNext()) {
- if (Attr->isInvalid() ||
- Attr->getKind() == AttributeList::IgnoredAttribute)
- continue;
- Diag(Attr->getLoc(),
- Attr->getKind() == AttributeList::UnknownAttribute
- ? diag::warn_unknown_attribute_ignored
- : diag::err_base_specifier_attribute)
- << Attr->getName();
- }
+ for (const ParsedAttr &AL : Attributes) {
+ if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
+ continue;
+ Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
+ ? diag::warn_unknown_attribute_ignored
+ : diag::err_base_specifier_attribute)
+ << AL.getName();
}
TypeSourceInfo *TInfo = nullptr;
@@ -2326,7 +2344,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
/// locally, there's no need to abstract the small size parameter.
typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
-/// \brief Recursively add the bases of Type. Don't add Type itself.
+/// Recursively add the bases of Type. Don't add Type itself.
static void
NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
const QualType &Type)
@@ -2347,7 +2365,7 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
}
}
-/// \brief Performs the actual work of attaching the given base class
+/// Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
MutableArrayRef<CXXBaseSpecifier *> Bases) {
@@ -2404,7 +2422,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// The Microsoft extension __interface does not permit bases that
// are not themselves public interfaces.
Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
- << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName()
+ << getRecordDiagFromTagKind(RD->getTagKind()) << RD
<< RD->getSourceRange();
Invalid = true;
}
@@ -2417,9 +2435,16 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases.data(), NumGoodBases);
+ // Check that the only base classes that are duplicate are virtual.
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
QualType BaseType = Bases[idx]->getType();
+
+ // Skip all dependent types in templates being used as base specifiers.
+ // Checks below assume that the base specifier is a CXXRecord.
+ if (BaseType->isDependentType())
+ continue;
+
CanQualType CanonicalBase = Context.getCanonicalType(BaseType)
.getUnqualifiedType();
@@ -2459,7 +2484,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}
-/// \brief Determine whether the type \p Derived is a C++ class that is
+/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
if (!getLangOpts().CPlusPlus)
@@ -2486,7 +2511,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
return DerivedRD->isDerivedFrom(BaseRD);
}
-/// \brief Determine whether the type \p Derived is a C++ class that is
+/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
CXXBasePaths &Paths) {
@@ -2638,7 +2663,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
}
-/// @brief Builds a string representing ambiguous paths from a
+/// Builds a string representing ambiguous paths from a
/// specific derived class to different subobjects of the same base
/// class.
///
@@ -2674,10 +2699,9 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
//===----------------------------------------------------------------------===//
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
-bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
- SourceLocation ASLoc,
+bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
SourceLocation ColonLoc,
- AttributeList *Attrs) {
+ const ParsedAttributesView &Attrs) {
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
ASLoc, ColonLoc);
@@ -2764,7 +2788,7 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
SourceLocation Loc = MD->getLocation();
SourceLocation SpellingLoc = Loc;
if (getSourceManager().isMacroArgExpansion(Loc))
- SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first;
+ SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin();
SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
return;
@@ -2805,10 +2829,13 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) {
return false;
}
-static AttributeList *getMSPropertyAttr(AttributeList *list) {
- for (AttributeList *it = list; it != nullptr; it = it->getNext())
- if (it->isDeclspecPropertyAttribute())
- return it;
+static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) {
+ ParsedAttributesView::const_iterator Itr =
+ llvm::find_if(list, [](const ParsedAttr &AL) {
+ return AL.isDeclspecPropertyAttribute();
+ });
+ if (Itr != list.end())
+ return &*Itr;
return nullptr;
}
@@ -2855,7 +2882,7 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
if (AS_none !=
CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
Diag(Loc, diag::warn_shadow_field)
- << FieldName.getAsString() << RD->getName() << Base->getName();
+ << FieldName << RD << Base;
Diag(BaseField->getLocation(), diag::note_shadow_field);
Bases.erase(It);
}
@@ -2887,8 +2914,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert(!DS.isFriendSpecified());
bool isFunc = D.isDeclarationOfFunction();
- AttributeList *MSPropertyAttr =
- getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
+ const ParsedAttr *MSPropertyAttr =
+ getMSPropertyAttr(D.getDeclSpec().getAttributes());
if (cast<CXXRecordDecl>(CurContext)->isInterface()) {
// The Microsoft extension __interface only permits public member functions
@@ -3044,7 +3071,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// int X::member;
// };
if (DeclContext *DC = computeDeclContext(SS, false))
- diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc());
+ diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() ==
+ UnqualifiedIdKind::IK_TemplateId);
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
@@ -3054,7 +3083,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
- BitWidth, InitStyle, AS, MSPropertyAttr);
+ BitWidth, InitStyle, AS, *MSPropertyAttr);
if (!Member)
return nullptr;
isInstField = false;
@@ -3096,14 +3125,38 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member->setInvalidDecl();
}
+ NamedDecl *NonTemplateMember = Member;
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+ NonTemplateMember = FunTmpl->getTemplatedDecl();
+ else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
+ NonTemplateMember = VarTmpl->getTemplatedDecl();
+
Member->setAccess(AS);
// If we have declared a member function template or static data member
// template, set the access of the templated declaration as well.
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
- FunTmpl->getTemplatedDecl()->setAccess(AS);
- else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
- VarTmpl->getTemplatedDecl()->setAccess(AS);
+ if (NonTemplateMember != Member)
+ NonTemplateMember->setAccess(AS);
+
+ // C++ [temp.deduct.guide]p3:
+ // A deduction guide [...] for a member class template [shall be
+ // declared] with the same access [as the template].
+ if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) {
+ auto *TD = DG->getDeducedTemplate();
+ if (AS != TD->getAccess()) {
+ Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access);
+ Diag(TD->getLocStart(), diag::note_deduction_guide_template_access)
+ << TD->getAccess();
+ const AccessSpecDecl *LastAccessSpec = nullptr;
+ for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) {
+ if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D))
+ LastAccessSpec = AccessSpec;
+ }
+ assert(LastAccessSpec && "differing access with no access specifier");
+ Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access)
+ << AS;
+ }
+ }
}
if (VS.isOverrideSpecified())
@@ -3544,7 +3597,7 @@ namespace {
}
} // namespace
-/// \brief Enter a new C++ default initializer scope. After calling this, the
+/// Enter a new C++ default initializer scope. After calling this, the
/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
/// parsing or instantiating the initializer failed.
void Sema::ActOnStartCXXInClassMemberInitializer() {
@@ -3553,7 +3606,7 @@ void Sema::ActOnStartCXXInClassMemberInitializer() {
PushFunctionScope();
}
-/// \brief This is invoked after parsing an in-class initializer for a
+/// This is invoked after parsing an in-class initializer for a
/// non-static C++ class member, and after instantiating an in-class initializer
/// in a class template. Such actions are deferred until the class is complete.
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
@@ -3581,10 +3634,14 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
- InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
- InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
- ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
- : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
+ InitializedEntity Entity =
+ InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
+ InitializationKind Kind =
+ FD->getInClassInitStyle() == ICIS_ListInit
+ ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
+ InitExpr->getLocStart(),
+ InitExpr->getLocEnd())
+ : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
InitializationSequence Seq(*this, Entity, Kind, InitExpr);
Init = Seq.Perform(*this, Entity, Kind, InitExpr);
if (Init.isInvalid()) {
@@ -3607,7 +3664,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
FD->setInClassInitializer(InitExpr);
}
-/// \brief Find the direct and/or virtual base specifiers that
+/// 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,
@@ -3651,7 +3708,7 @@ static bool FindBaseInitializer(Sema &SemaRef,
return DirectBaseSpec || VirtualBaseSpec;
}
-/// \brief Handle a C++ member initializer using braced-init-list syntax.
+/// Handle a C++ member initializer using braced-init-list syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3667,7 +3724,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
EllipsisLoc);
}
-/// \brief Handle a C++ member initializer using parentheses syntax.
+/// Handle a C++ member initializer using parentheses syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3710,7 +3767,7 @@ private:
}
-/// \brief Handle a C++ member initializer.
+/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3889,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}
-/// Checks a member initializer expression for cases where reference (or
-/// pointer) members are bound to by-value parameters (or their addresses).
-static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
- Expr *Init,
- SourceLocation IdLoc) {
- QualType MemberTy = Member->getType();
-
- // We only handle pointers and references currently.
- // FIXME: Would this be relevant for ObjC object pointers? Or block pointers?
- if (!MemberTy->isReferenceType() && !MemberTy->isPointerType())
- return;
-
- const bool IsPointer = MemberTy->isPointerType();
- if (IsPointer) {
- if (const UnaryOperator *Op
- = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
- // The only case we're worried about with pointers requires taking the
- // address.
- if (Op->getOpcode() != UO_AddrOf)
- return;
-
- Init = Op->getSubExpr();
- } else {
- // We only handle address-of expression initializers for pointers.
- return;
- }
- }
-
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
- // We only warn when referring to a non-reference parameter declaration.
- const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
- if (!Parameter || Parameter->getType()->isReferenceType())
- return;
-
- S.Diag(Init->getExprLoc(),
- IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
- : diag::warn_bind_ref_member_to_parameter)
- << Member << Parameter << Init->getSourceRange();
- } else {
- // Other initializers are fine.
- return;
- }
-
- S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
- << (unsigned)IsPointer;
-}
-
MemInitResult
Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc) {
@@ -3979,9 +3989,10 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
: InitializedEntity::InitializeMember(IndirectMember,
nullptr);
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(IdLoc)
- : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(
+ IdLoc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
@@ -3989,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (MemberInit.isInvalid())
return true;
- CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc);
-
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
@@ -4033,9 +4042,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(NameLoc)
- : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(
+ NameLoc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
Args, nullptr);
@@ -4167,9 +4177,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(BaseLoc)
- : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(BaseLoc)
+ : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
if (BaseInit.isInvalid())
@@ -4321,7 +4331,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ParamType = Param->getType().getNonReferenceType();
// Suppress copying zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
+ if (Field->isZeroLengthBitField(SemaRef.Context))
return false;
Expr *MemberExprBase =
@@ -4536,7 +4546,7 @@ struct BaseAndFieldInfo {
return !FieldRD->hasInClassInitializer();
}
- /// \brief Determine whether the given field is, or is within, a union member
+ /// Determine whether the given field is, or is within, a union member
/// that is inactive (because there was an initializer given for a different
/// member of the union, or because the union was not initialized at all).
bool isWithinInactiveUnionMember(FieldDecl *Field,
@@ -4554,7 +4564,7 @@ struct BaseAndFieldInfo {
};
}
-/// \brief Determine whether the given type is an incomplete or zero-lenfgth
+/// Determine whether the given type is an incomplete or zero-lenfgth
/// array type.
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
if (T->isIncompleteArrayType())
@@ -4601,6 +4611,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
if (DIE.isInvalid())
return true;
+
+ auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
+ SemaRef.checkInitializerLifetime(Entity, DIE.get());
+
CXXCtorInitializer *Init;
if (Indirect)
Init = new (SemaRef.Context)
@@ -5464,7 +5478,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
}
-static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
+static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
if (!ClassAttr)
return;
@@ -5479,6 +5493,14 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
return;
for (Decl *Member : Class->decls()) {
+ // Defined static variables that are members of an exported base
+ // class must be marked export too.
+ auto *VD = dyn_cast<VarDecl>(Member);
+ if (VD && Member->getAttr<DLLExportAttr>() &&
+ VD->getStorageClass() == SC_Static &&
+ TSK == TSK_ImplicitInstantiation)
+ S.MarkVariableReferenced(VD->getLocation(), VD);
+
auto *MD = dyn_cast<CXXMethodDecl>(Member);
if (!MD)
continue;
@@ -5506,7 +5528,7 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
S.MarkFunctionReferenced(Class->getLocation(), MD);
if (Trap.hasErrorOccurred()) {
S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ << Class << !S.getLangOpts().CPlusPlus11;
break;
}
@@ -5556,7 +5578,17 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S,
}
}
-/// \brief Check class-level dllimport/dllexport attribute.
+void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) {
+ // Mark any compiler-generated routines with the implicit code_seg attribute.
+ for (auto *Method : Class->methods()) {
+ if (Method->isUserProvided())
+ continue;
+ if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+ Method->addAttr(A);
+ }
+}
+
+/// Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
@@ -5606,6 +5638,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
// The class is either imported or exported.
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
+ // Check if this was a dllimport attribute propagated from a derived class to
+ // a base class template specialization. We don't apply these attributes to
+ // static data members.
+ const bool PropagatedImport =
+ !ClassExported &&
+ cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate();
+
TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
// Ignore explicit dllexport on explicit class template instantiation declarations.
@@ -5657,6 +5696,11 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
}
}
+ // Don't apply dllimport attributes to static data members of class template
+ // instantiations when the attribute is propagated from a derived class.
+ if (VD && PropagatedImport)
+ continue;
+
if (!cast<NamedDecl>(Member)->isExternallyVisible())
continue;
@@ -5665,6 +5709,21 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
+
+ if (MD) {
+ // Propagate DLLAttr to friend re-declarations of MD that have already
+ // been constructed.
+ for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
+ FD = FD->getPreviousDecl()) {
+ if (FD->getFriendObjectKind() == Decl::FOK_None)
+ continue;
+ assert(!getDLLAttr(FD) &&
+ "friend re-decl should not already have a DLLAttr");
+ NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ FD->addAttr(NewAttr);
+ }
+ }
}
}
@@ -5672,7 +5731,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
DelayedDllExportClasses.push_back(Class);
}
-/// \brief Perform propagation of DLL attributes from a derived class to a
+/// Perform propagation of DLL attributes from a derived class to a
/// templated base class for MS compatibility.
void Sema::propagateDLLAttrToBaseClassTemplate(
CXXRecordDecl *Class, Attr *ClassAttr,
@@ -5694,6 +5753,11 @@ void Sema::propagateDLLAttrToBaseClassTemplate(
NewAttr->setInherited(true);
BaseTemplateSpec->addAttr(NewAttr);
+ // If this was an import, mark that we propagated it from a derived class to
+ // a base class template specialization.
+ if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr))
+ ImportAttr->setPropagatedToBaseTemplate();
+
// If the template is already instantiated, checkDLLAttributeRedeclaration()
// needs to be run again to work see the new attribute. Otherwise this will
// get run whenever the template is instantiated.
@@ -5756,10 +5820,74 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
/// Determine whether a type is permitted to be passed or returned in
/// registers, per C++ [class.temporary]p3.
-static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
+static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
+ TargetInfo::CallingConvKind CCK) {
if (D->isDependentType() || D->isInvalidDecl())
return false;
+ // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
+ // The PS4 platform ABI follows the behavior of Clang 3.2.
+ if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
+ return !D->hasNonTrivialDestructorForCall() &&
+ !D->hasNonTrivialCopyConstructorForCall();
+
+ if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+ bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
+ bool DtorIsTrivialForCall = false;
+
+ // If a class has at least one non-deleted, trivial copy constructor, it
+ // is passed according to the C ABI. Otherwise, it is passed indirectly.
+ //
+ // Note: This permits classes with non-trivial copy or move ctors to be
+ // passed in registers, so long as they *also* have a trivial copy ctor,
+ // which is non-conforming.
+ if (D->needsImplicitCopyConstructor()) {
+ if (!D->defaultedCopyConstructorIsDeleted()) {
+ if (D->hasTrivialCopyConstructor())
+ CopyCtorIsTrivial = true;
+ if (D->hasTrivialCopyConstructorForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ } else {
+ for (const CXXConstructorDecl *CD : D->ctors()) {
+ if (CD->isCopyConstructor() && !CD->isDeleted()) {
+ if (CD->isTrivial())
+ CopyCtorIsTrivial = true;
+ if (CD->isTrivialForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ }
+ }
+
+ if (D->needsImplicitDestructor()) {
+ if (!D->defaultedDestructorIsDeleted() &&
+ D->hasTrivialDestructorForCall())
+ DtorIsTrivialForCall = true;
+ } else if (const auto *DD = D->getDestructor()) {
+ if (!DD->isDeleted() && DD->isTrivialForCall())
+ DtorIsTrivialForCall = true;
+ }
+
+ // If the copy ctor and dtor are both trivial-for-calls, pass direct.
+ if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+ return true;
+
+ // If a class has a destructor, we'd really like to pass it indirectly
+ // because it allows us to elide copies. Unfortunately, MSVC makes that
+ // impossible for small types, which it will pass in a single register or
+ // stack slot. Most objects with dtors are large-ish, so handle that early.
+ // We can't call out all large objects as being indirect because there are
+ // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
+ // how we pass large POD types.
+
+ // Note: This permits small classes with nontrivial destructors to be
+ // passed in registers, which is non-conforming.
+ if (CopyCtorIsTrivial &&
+ S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
+ return true;
+ return false;
+ }
+
// Per C++ [class.temporary]p3, the relevant condition is:
// each copy constructor, move constructor, and destructor of X is
// either trivial or deleted, and X has at least one non-deleted copy
@@ -5768,20 +5896,20 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
if (D->needsImplicitCopyConstructor() &&
!D->defaultedCopyConstructorIsDeleted()) {
- if (!D->hasTrivialCopyConstructor())
+ if (!D->hasTrivialCopyConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
!D->defaultedMoveConstructorIsDeleted()) {
- if (!D->hasTrivialMoveConstructor())
+ if (!D->hasTrivialMoveConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
- !D->hasTrivialDestructor())
+ !D->hasTrivialDestructorForCall())
return false;
for (const CXXMethodDecl *MD : D->methods()) {
@@ -5794,14 +5922,14 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
else if (!isa<CXXDestructorDecl>(MD))
continue;
- if (!MD->isTrivial())
+ if (!MD->isTrivialForCall())
return false;
}
return HasNonDeletedCopyOrMove;
}
-/// \brief Perform semantic checks on a class definition that has been
+/// Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
@@ -5851,10 +5979,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I) {
- NamedDecl *D = *I;
- if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) &&
+ Record->hasUserDeclaredConstructor()) ||
isa<IndirectFieldDecl>(D)) {
- Diag(D->getLocation(), diag::err_member_name_of_class)
+ Diag((*I)->getLocation(), diag::err_member_name_of_class)
<< D->getDeclName();
break;
}
@@ -5878,6 +6007,17 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ // See if trivial_abi has to be dropped.
+ if (Record->hasAttr<TrivialABIAttr>())
+ checkIllFormedTrivialABIStruct(*Record);
+
+ // Set HasTrivialSpecialMemberForCall if the record has attribute
+ // "trivial_abi".
+ bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>();
+
+ if (HasTrivialABI)
+ Record->setHasTrivialSpecialMemberForCall();
+
bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
@@ -5900,12 +6040,23 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!M->isImplicit() && !M->isUserProvided()) {
if (CSM != CXXInvalid) {
M->setTrivial(SpecialMemberIsTrivial(M, CSM));
-
// Inform the class that we've finished declaring this member.
Record->finishedDefaultedOrDeletedMember(M);
+ M->setTrivialForCall(
+ HasTrivialABI ||
+ SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI));
+ Record->setTrivialForCallFlags(M);
}
}
+ // Set triviality for the purpose of calls if this is a user-provided
+ // copy/move constructor or destructor.
+ if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
+ CSM == CXXDestructor) && M->isUserProvided()) {
+ M->setTrivialForCall(HasTrivialABI);
+ Record->setTrivialForCallFlags(M);
+ }
+
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
M->hasAttr<DLLExportAttr>()) {
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
@@ -5945,8 +6096,35 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
checkClassLevelDLLAttribute(Record);
+ checkClassLevelCodeSegAttribute(Record);
- Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
+ bool ClangABICompat4 =
+ Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
+ TargetInfo::CallingConvKind CCK =
+ Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
+ bool CanPass = canPassInRegisters(*this, Record, CCK);
+
+ // Do not change ArgPassingRestrictions if it has already been set to
+ // APK_CanNeverPassInRegs.
+ if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs)
+ Record->setArgPassingRestrictions(CanPass
+ ? RecordDecl::APK_CanPassInRegs
+ : RecordDecl::APK_CannotPassInRegs);
+
+ // If canPassInRegisters returns true despite the record having a non-trivial
+ // destructor, the record is destructed in the callee. This happens only when
+ // the record or one of its subobjects has a field annotated with trivial_abi
+ // or a field qualified with ObjC __strong/__weak.
+ if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee())
+ Record->setParamDestroyedInCallee(true);
+ else if (Record->hasNonTrivialDestructor())
+ Record->setParamDestroyedInCallee(CanPass);
+
+ if (getLangOpts().ForceEmitVTables) {
+ // If we want to emit all the vtables, we need to mark it as used. This
+ // is especially required for cases like vtable assumption loads.
+ MarkVTableUsed(Record->getInnerLocStart(), Record);
+ }
}
/// Look up the special member function that would be called by a special
@@ -7017,9 +7195,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
///
/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
/// member that was most likely to be intended to be trivial, if any.
+///
+/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to
+/// determine whether the special member is trivial.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
- bool ConstRHS, CXXMethodDecl **Selected) {
+ bool ConstRHS,
+ Sema::TrivialABIHandling TAH,
+ CXXMethodDecl **Selected) {
if (Selected)
*Selected = nullptr;
@@ -7060,7 +7243,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.dtor]p5:
// A destructor is trivial if:
// - all the direct [subobjects] have trivial destructors
- if (RD->hasTrivialDestructor())
+ if (RD->hasTrivialDestructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialDestructorForCall()))
return true;
if (Selected) {
@@ -7075,7 +7260,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.copy]p12:
// A copy constructor is trivial if:
// - the constructor selected to copy each direct [subobject] is trivial
- if (RD->hasTrivialCopyConstructor()) {
+ if (RD->hasTrivialCopyConstructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialCopyConstructorForCall())) {
if (Quals == Qualifiers::Const)
// We must either select the trivial copy constructor or reach an
// ambiguity; no need to actually perform overload resolution.
@@ -7128,6 +7315,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// not supposed to!
if (Selected)
*Selected = SMOR.getMethod();
+
+ if (TAH == Sema::TAH_ConsiderTrivialABI &&
+ (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor))
+ return SMOR.getMethod()->isTrivialForCall();
return SMOR.getMethod()->isTrivial();
}
@@ -7166,14 +7357,14 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
- bool Diagnose) {
+ Sema::TrivialABIHandling TAH, bool Diagnose) {
CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
if (!SubRD)
return true;
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- ConstRHS, Diagnose ? &Selected : nullptr))
+ ConstRHS, TAH, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
@@ -7203,7 +7394,8 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
<< Kind << SubType.getUnqualifiedType() << CSM;
// Explain why the defaulted or deleted special member isn't trivial.
- S.SpecialMemberIsTrivial(Selected, CSM, Diagnose);
+ S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI,
+ Diagnose);
}
}
@@ -7214,7 +7406,9 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
/// trivial.
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
- bool ConstArg, bool Diagnose) {
+ bool ConstArg,
+ Sema::TrivialABIHandling TAH,
+ bool Diagnose) {
for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
@@ -7224,7 +7418,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// Pretend anonymous struct or union members are members of this class.
if (FI->isAnonymousStructOrUnion()) {
if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
- CSM, ConstArg, Diagnose))
+ CSM, ConstArg, TAH, Diagnose))
return false;
continue;
}
@@ -7252,7 +7446,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
bool ConstRHS = ConstArg && !FI->isMutable();
if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
- CSM, TSK_Field, Diagnose))
+ CSM, TSK_Field, TAH, Diagnose))
return false;
}
@@ -7266,14 +7460,15 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
- TSK_CompleteObject, /*Diagnose*/true);
+ TSK_CompleteObject, TAH_IgnoreTrivialABI,
+ /*Diagnose*/true);
}
/// Determine whether a defaulted or deleted special member function is trivial,
/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
- bool Diagnose) {
+ TrivialABIHandling TAH, bool Diagnose) {
assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");
CXXRecordDecl *RD = MD->getParent();
@@ -7350,7 +7545,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// destructors]
for (const auto &BI : RD->bases())
if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
- ConstArg, CSM, TSK_BaseClass, Diagnose))
+ ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
@@ -7365,7 +7560,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// -- for all of the non-static data members of its class that are of class
// type (or array thereof), each such class has a trivial [default
// constructor or destructor]
- if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose))
+ if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose))
return false;
// C++11 [class.dtor]p5:
@@ -7477,7 +7672,7 @@ public:
};
} // end anonymous namespace
-/// \brief Add the most overriden methods from MD to Methods
+/// Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
@@ -7487,7 +7682,7 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
AddMostOverridenMethods(O, Methods);
}
-/// \brief Check if a method overloads virtual methods in a base class without
+/// Check if a method overloads virtual methods in a base class without
/// overriding any.
void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
@@ -7528,7 +7723,7 @@ void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
}
}
-/// \brief Diagnose methods which overload virtual methods in a base class
+/// Diagnose methods which overload virtual methods in a base class
/// without overriding any.
void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
if (MD->isInvalidDecl())
@@ -7547,22 +7742,64 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
}
}
-void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- Decl *TagDecl,
- SourceLocation LBrac,
- SourceLocation RBrac,
- AttributeList *AttrList) {
+void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
+ auto PrintDiagAndRemoveAttr = [&]() {
+ // No diagnostics if this is a template instantiation.
+ if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
+ Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
+ diag::ext_cannot_use_trivial_abi) << &RD;
+ RD.dropAttr<TrivialABIAttr>();
+ };
+
+ // Ill-formed if the struct has virtual functions.
+ if (RD.isPolymorphic()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ for (const auto &B : RD.bases()) {
+ // Ill-formed if the base class is non-trivial for the purpose of calls or a
+ // virtual base.
+ if ((!B.getType()->isDependentType() &&
+ !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
+ B.isVirtual()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+
+ for (const auto *FD : RD.fields()) {
+ // Ill-formed if the field is an ObjectiveC pointer or of a type that is
+ // non-trivial for the purpose of calls.
+ QualType FT = FD->getType();
+ if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (!RT->isDependentType() &&
+ !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+}
+
+void Sema::ActOnFinishCXXMemberSpecification(
+ Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
+ SourceLocation RBrac, const ParsedAttributesView &AttrList) {
if (!TagDecl)
return;
AdjustDeclIfTemplate(TagDecl);
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (l->getKind() != AttributeList::AT_Visibility)
+ for (const ParsedAttr &AL : AttrList) {
+ if (AL.getKind() != ParsedAttr::AT_Visibility)
continue;
- l->setInvalid();
- Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) <<
- l->getName();
+ AL.setInvalid();
+ Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored)
+ << AL.getName();
}
ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
@@ -7570,7 +7807,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
- CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
+ CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl));
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
@@ -8108,7 +8345,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
QualType ConvType =
GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI);
- if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+ const DeclSpec &DS = D.getDeclSpec();
+ if (DS.hasTypeSpecifier() && !D.isInvalidType()) {
// Conversion functions don't have return types, but the parser will
// happily parse something like:
//
@@ -8118,9 +8356,18 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
//
// The return type will be changed later anyway.
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
- << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(DS.getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
+ } else if (DS.getTypeQualifiers() && !D.isInvalidType()) {
+ // It's also plausible that the user writes type qualifiers in the wrong
+ // place, such as:
+ // struct S { const operator int(); };
+ // FIXME: we could provide a fixit to move the qualifiers onto the
+ // conversion type.
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
+ << SourceRange(D.getIdentifierLoc()) << 0;
+ D.setInvalidType();
}
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
@@ -8233,12 +8480,12 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo());
// C++0x explicit conversion operators.
- if (D.getDeclSpec().isExplicitSpecified())
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
- getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_explicit_conversion_functions :
- diag::ext_explicit_conversion_functions)
- << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(),
+ getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_explicit_conversion_functions
+ : diag::ext_explicit_conversion_functions)
+ << SourceRange(DS.getExplicitSpecLoc());
}
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
@@ -8437,7 +8684,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
// Namespace Handling
//===----------------------------------------------------------------------===//
-/// \brief Diagnose a mismatch in 'inline' qualifiers when a namespace is
+/// Diagnose a mismatch in 'inline' qualifiers when a namespace is
/// reopened.
static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
SourceLocation Loc,
@@ -8479,14 +8726,10 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
-Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
- SourceLocation InlineLoc,
- SourceLocation NamespaceLoc,
- SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation LBrace,
- AttributeList *AttrList,
- UsingDirectiveDecl *&UD) {
+Decl *Sema::ActOnStartNamespaceDef(
+ Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc,
+ SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace,
+ const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
@@ -8673,7 +8916,137 @@ NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
return StdExperimentalNamespaceCache;
}
-/// \brief Retrieve the special "std" namespace, which may require us to
+namespace {
+
+enum UnsupportedSTLSelect {
+ USS_InvalidMember,
+ USS_MissingMember,
+ USS_NonTrivial,
+ USS_Other
+};
+
+struct InvalidSTLDiagnoser {
+ Sema &S;
+ SourceLocation Loc;
+ QualType TyForDiags;
+
+ QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "",
+ const VarDecl *VD = nullptr) {
+ {
+ auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported)
+ << TyForDiags << ((int)Sel);
+ if (Sel == USS_InvalidMember || Sel == USS_MissingMember) {
+ assert(!Name.empty());
+ D << Name;
+ }
+ }
+ if (Sel == USS_InvalidMember) {
+ S.Diag(VD->getLocation(), diag::note_var_declared_here)
+ << VD << VD->getSourceRange();
+ }
+ return QualType();
+ }
+};
+} // namespace
+
+QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
+ SourceLocation Loc) {
+ assert(getLangOpts().CPlusPlus &&
+ "Looking for comparison category type outside of C++.");
+
+ // Check if we've already successfully checked the comparison category type
+ // before. If so, skip checking it again.
+ ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind);
+ if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)])
+ return Info->getType();
+
+ // If lookup failed
+ if (!Info) {
+ std::string NameForDiags = "std::";
+ NameForDiags += ComparisonCategories::getCategoryString(Kind);
+ Diag(Loc, diag::err_implied_comparison_category_type_not_found)
+ << NameForDiags;
+ return QualType();
+ }
+
+ assert(Info->Kind == Kind);
+ assert(Info->Record);
+
+ // Update the Record decl in case we encountered a forward declaration on our
+ // first pass. FIXME: This is a bit of a hack.
+ if (Info->Record->hasDefinition())
+ Info->Record = Info->Record->getDefinition();
+
+ // Use an elaborated type for diagnostics which has a name containing the
+ // prepended 'std' namespace but not any inline namespace names.
+ QualType TyForDiags = [&]() {
+ auto *NNS =
+ NestedNameSpecifier::Create(Context, nullptr, getStdNamespace());
+ return Context.getElaboratedType(ETK_None, NNS, Info->getType());
+ }();
+
+ if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type))
+ return QualType();
+
+ InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags};
+
+ if (!Info->Record->isTriviallyCopyable())
+ return UnsupportedSTLError(USS_NonTrivial);
+
+ for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) {
+ CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+ // Tolerate empty base classes.
+ if (Base->isEmpty())
+ continue;
+ // Reject STL implementations which have at least one non-empty base.
+ return UnsupportedSTLError();
+ }
+
+ // Check that the STL has implemented the types using a single integer field.
+ // This expectation allows better codegen for builtin operators. We require:
+ // (1) The class has exactly one field.
+ // (2) The field is an integral or enumeration type.
+ auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end();
+ if (std::distance(FIt, FEnd) != 1 ||
+ !FIt->getType()->isIntegralOrEnumerationType()) {
+ return UnsupportedSTLError();
+ }
+
+ // Build each of the require values and store them in Info.
+ for (ComparisonCategoryResult CCR :
+ ComparisonCategories::getPossibleResultsForType(Kind)) {
+ StringRef MemName = ComparisonCategories::getResultString(CCR);
+ ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR);
+
+ if (!ValInfo)
+ return UnsupportedSTLError(USS_MissingMember, MemName);
+
+ VarDecl *VD = ValInfo->VD;
+ assert(VD && "should not be null!");
+
+ // Attempt to diagnose reasons why the STL definition of this type
+ // might be foobar, including it failing to be a constant expression.
+ // TODO Handle more ways the lookup or result can be invalid.
+ if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
+ !VD->checkInitIsICE())
+ return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
+
+ // Attempt to evaluate the var decl as a constant expression and extract
+ // the value of its first field as a ICE. If this fails, the STL
+ // implementation is not supported.
+ if (!ValInfo->hasValidIntValue())
+ return UnsupportedSTLError();
+
+ MarkVariableReferenced(Loc, VD);
+ }
+
+ // We've successfully built the required types and expressions. Update
+ // the cache and return the newly cached value.
+ FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true;
+ return Info->getType();
+}
+
+/// Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
@@ -8816,7 +9189,7 @@ bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {
return isStdInitializerList(ArgType, nullptr);
}
-/// \brief Determine whether a using statement is in a context where it will be
+/// Determine whether a using statement is in a context where it will be
/// apply in all contexts.
static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
switch (CurContext->getDeclKind()) {
@@ -8871,13 +9244,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
return false;
}
-Decl *Sema::ActOnUsingDirective(Scope *S,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList) {
+Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc, CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ const ParsedAttributesView &AttrList) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(NamespcName && "Invalid NamespcName.");
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
@@ -8932,7 +9303,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
// Find enclosing context containing both using-directive and
// nominated namespace.
- DeclContext *CommonAncestor = cast<DeclContext>(NS);
+ DeclContext *CommonAncestor = NS;
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
CommonAncestor = CommonAncestor->getParent();
@@ -8969,15 +9340,12 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
S->PushUsingDirective(UDir);
}
-
-Decl *Sema::ActOnUsingDeclaration(Scope *S,
- AccessSpecifier AS,
+Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
+ SourceLocation TypenameLoc, CXXScopeSpec &SS,
UnqualifiedId &Name,
SourceLocation EllipsisLoc,
- AttributeList *AttrList) {
+ const ParsedAttributesView &AttrList) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
if (SS.isEmpty()) {
@@ -9056,7 +9424,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return UD;
}
-/// \brief Determine whether a using declaration considers the given
+/// Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
static bool
@@ -9149,6 +9517,19 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
continue;
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ // C++ [class.mem]p19:
+ // If T is the name of a class, then [every named member other than
+ // a non-static data member] shall have a name different from T
+ if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) &&
+ !isa<IndirectFieldDecl>(Target) &&
+ !isa<UnresolvedUsingValueDecl>(Target) &&
+ DiagnoseClassNameShadow(
+ CurContext,
+ DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
+ return true;
+ }
+
if (IsEquivalentForUsingDecl(Context, D, Target)) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
PrevShadow = Shadow;
@@ -9421,15 +9802,11 @@ private:
/// \param IsInstantiation - Whether this call arises from an
/// instantiation of an unresolved using declaration. We treat
/// the lookup differently for these declarations.
-NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
- SourceLocation UsingLoc,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
- DeclarationNameInfo NameInfo,
- SourceLocation EllipsisLoc,
- AttributeList *AttrList,
- bool IsInstantiation) {
+NamedDecl *Sema::BuildUsingDeclaration(
+ Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
+ bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
+ const ParsedAttributesView &AttrList, bool IsInstantiation) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
@@ -9995,14 +10372,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
-Decl *Sema::ActOnAliasDeclaration(Scope *S,
- AccessSpecifier AS,
+Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParamLists,
- SourceLocation UsingLoc,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- TypeResult Type,
- Decl *DeclFromDeclSpec) {
+ SourceLocation UsingLoc, UnqualifiedId &Name,
+ const ParsedAttributesView &AttrList,
+ TypeResult Type, Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
while (S->isTemplateParamScope())
S = S->getParent();
@@ -10378,7 +10752,7 @@ struct DeclaringSpecialMember {
}
}
- /// \brief Are we already trying to declare this special member?
+ /// Are we already trying to declare this special member?
bool isAlreadyBeingDeclared() const {
return WasAlreadyBeingDeclared;
}
@@ -10720,6 +11094,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+ Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() ||
+ ClassDecl->hasTrivialDestructorForCall());
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
@@ -10784,7 +11160,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
}
}
-/// \brief Perform any semantic analysis which needs to be delayed until all
+/// Perform any semantic analysis which needs to be delayed until all
/// pending class member declarations have been parsed.
void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
@@ -10804,12 +11180,12 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
void Sema::referenceDLLExportedClassMethods() {
if (!DelayedDllExportClasses.empty()) {
- // Calling ReferenceDllExportedMethods might cause the current function to
+ // Calling ReferenceDllExportedMembers might cause the current function to
// be called again, so use a local copy of DelayedDllExportClasses.
SmallVector<CXXRecordDecl *, 4> WorkList;
std::swap(DelayedDllExportClasses, WorkList);
for (CXXRecordDecl *Class : WorkList)
- ReferenceDllExportedMethods(*this, Class);
+ ReferenceDllExportedMembers(*this, Class);
}
}
@@ -10843,7 +11219,7 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
}
namespace {
-/// \brief An abstract base class for all helper classes used in building the
+/// An abstract base class for all helper classes used in building the
// copy/move operators. These classes serve as factory functions and help us
// avoid using the same Expr* in the AST twice.
class ExprBuilder {
@@ -10990,11 +11366,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
Expr *From = FromB.build(S, Loc);
From = new (S.Context) UnaryOperator(From, UO_AddrOf,
S.Context.getPointerType(From->getType()),
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
Expr *To = ToB.build(S, Loc);
To = new (S.Context) UnaryOperator(To, UO_AddrOf,
S.Context.getPointerType(To->getType()),
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
const Type *E = T->getBaseElementTypeUnsafe();
bool NeedsCollectableMemCpy =
@@ -11028,7 +11404,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
return Call.getAs<Stmt>();
}
-/// \brief Builds a statement that copies/moves the given entity from \p From to
+/// Builds a statement that copies/moves the given entity from \p From to
/// \c To.
///
/// This routine is used to copy/move the members of a class with an
@@ -11233,10 +11609,12 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, FPOptions());
- // Create the pre-increment of the iteration variable.
- Expr *Increment
- = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc,
- SizeType, VK_LValue, OK_Ordinary, Loc);
+ // Create the pre-increment of the iteration variable. We can determine
+ // whether the increment will overflow based on the value of the array
+ // bound.
+ Expr *Increment = new (S.Context)
+ UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType,
+ VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue());
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(
@@ -11525,7 +11903,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -11892,7 +12270,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -12021,9 +12399,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForCopyConstructor()
- ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
- : ClassDecl->hasTrivialCopyConstructor());
+ ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
+ : ClassDecl->hasTrivialCopyConstructor());
+
+ CopyConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialCopyConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
@@ -12144,9 +12529,16 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForMoveConstructor()
- ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
- : ClassDecl->hasTrivialMoveConstructor());
+ ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
+ : ClassDecl->hasTrivialMoveConstructor());
+
+ MoveConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialMoveConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitMoveConstructorsDeclared;
@@ -12321,7 +12713,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
}
}
-/// \brief Determine whether the given list arguments contains exactly one
+/// Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
switch (Args.size()) {
@@ -12532,7 +12924,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
Diag(VD->getLocation(), diag::warn_global_destructor);
}
-/// \brief Given a constructor and the set of arguments provided for the
+/// Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
///
@@ -12599,6 +12991,13 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
return false;
}
+static QualType
+RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) {
+ QualType QTy = PtrTy->getPointeeType();
+ QTy = SemaRef.Context.removeAddrSpaceQualType(QTy);
+ return SemaRef.Context.getPointerType(QTy);
+}
+
static inline bool
CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
CanQualType ExpectedResultType,
@@ -12614,6 +13013,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
diag::err_operator_new_delete_dependent_result_type)
<< FnDecl->getDeclName() << ExpectedResultType;
+ // OpenCL C++: the operator is valid on any address space.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ if (auto *PtrTy = ResultType->getAs<PointerType>()) {
+ ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
+
// Check that the result type is what we expect.
if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
return SemaRef.Diag(FnDecl->getLocation(),
@@ -12639,6 +13045,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
<< FnDecl->getDeclName() << ExpectedFirstParamType;
// Check that the first parameter type is what we expect.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ // OpenCL C++: the operator is valid on any address space.
+ if (auto *PtrTy =
+ FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) {
+ FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
@@ -12948,6 +13361,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) ||
Context.hasSameType(ParamType, Context.CharTy) ||
Context.hasSameType(ParamType, Context.WideCharTy) ||
+ Context.hasSameType(ParamType, Context.Char8Ty) ||
Context.hasSameType(ParamType, Context.Char16Ty) ||
Context.hasSameType(ParamType, Context.Char32Ty)) {
} else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) {
@@ -13008,10 +13422,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
}
QualType InnerType = PointeeType.getUnqualifiedType();
- // Only const char *, const wchar_t*, const char16_t*, and const char32_t*
- // are allowed as the first parameter to a two-parameter function
+ // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and
+ // const char32_t* are allowed as the first parameter to a two-parameter
+ // function
if (!(Context.hasSameType(InnerType, Context.CharTy) ||
Context.hasSameType(InnerType, Context.WideCharTy) ||
+ Context.hasSameType(InnerType, Context.Char8Ty) ||
Context.hasSameType(InnerType, Context.Char16Ty) ||
Context.hasSameType(InnerType, Context.Char32Ty))) {
Diag((*Param)->getSourceRange().getBegin(),
@@ -13118,19 +13534,18 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
}
Decl *Sema::ActOnEmptyDeclaration(Scope *S,
- AttributeList *AttrList,
+ const ParsedAttributesView &AttrList,
SourceLocation SemiLoc) {
Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
// Attribute declarations appertain to empty declaration so we handle
// them here.
- if (AttrList)
- ProcessDeclAttributeList(S, ED, AttrList);
+ ProcessDeclAttributeList(S, ED, AttrList);
CurContext->addDecl(ED);
return ED;
}
-/// \brief Perform semantic analysis for the variable declaration that
+/// Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
@@ -13386,7 +13801,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
return Decl;
}
-/// \brief Perform semantic analysis of the given friend type declaration.
+/// Perform semantic analysis of the given friend type declaration.
///
/// \returns A friend declaration that.
FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
@@ -13463,10 +13878,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
/// templated.
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation NameLoc,
- AttributeList *Attr,
+ const ParsedAttributesView &Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
@@ -13579,7 +13993,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
return Friend;
}
-
/// Handle a friend type declaration. This works in tandem with
/// ActOnTag.
///
@@ -14151,6 +14564,16 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
}
}
+ // Virtual overrides must have the same code_seg.
+ const auto *OldCSA = Old->getAttr<CodeSegAttr>();
+ const auto *NewCSA = New->getAttr<CodeSegAttr>();
+ if ((NewCSA || OldCSA) &&
+ (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) {
+ Diag(New->getLocation(), diag::err_mismatched_code_seg_override);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();
// If the calling conventions match, everything is fine
@@ -14277,7 +14700,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return false;
}
-/// \brief Mark the given method pure.
+/// Mark the given method pure.
///
/// \param Method the method to be marked pure.
///
@@ -14307,7 +14730,7 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
Diag(D->getLocation(), diag::err_illegal_initializer);
}
-/// \brief Determine whether the given declaration is a global variable or
+/// 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))
@@ -14414,7 +14837,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
// Try to insert this class into the map.
LoadExternalVTableUses();
- Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ Class = Class->getCanonicalDecl();
std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
if (!Pos.second) {
@@ -14526,7 +14949,7 @@ bool Sema::DefineUsedVTables() {
// vtable for this class is required.
DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
- CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ CXXRecordDecl *Canonical = Class->getCanonicalDecl();
if (VTablesUsed[Canonical])
Consumer.HandleVTable(Class);
@@ -14649,9 +15072,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
static
void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Valid,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current,
Sema &S) {
if (Ctor->isInvalidDecl())
return;
@@ -14713,7 +15136,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
void Sema::CheckDelegatingCtorCycles() {
- llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
@@ -14721,14 +15144,12 @@ void Sema::CheckDelegatingCtorCycles() {
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
- for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(),
- CE = Invalid.end();
- CI != CE; ++CI)
+ for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
(*CI)->setInvalidDecl();
}
namespace {
- /// \brief AST visitor that finds references to the 'this' expression.
+ /// AST visitor that finds references to the 'this' expression.
class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
Sema &S;
@@ -14798,7 +15219,9 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
case EST_None:
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
return true;
LLVM_FALLTHROUGH;
@@ -14895,31 +15318,17 @@ void Sema::checkExceptionSpecification(
return;
}
- if (EST == EST_ComputedNoexcept) {
- // If an error occurred, there's no expression here.
- if (NoexceptExpr) {
- assert((NoexceptExpr->isTypeDependent() ||
- NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
- Context.BoolTy) &&
- "Parser should have made sure that the expression is boolean");
- if (IsTopLevel && NoexceptExpr &&
- DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
- ESI.Type = EST_BasicNoexcept;
- return;
- }
-
- 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;
+ if (isComputedNoexcept(EST)) {
+ assert((NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+ Context.BoolTy) &&
+ "Parser should have made sure that the expression is boolean");
+ if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+ ESI.Type = EST_BasicNoexcept;
+ return;
}
+
+ ESI.NoexceptExpr = NoexceptExpr;
return;
}
}
@@ -14964,11 +15373,11 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
///
MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
- SourceLocation DeclStart,
- Declarator &D, Expr *BitWidth,
+ SourceLocation DeclStart, Declarator &D,
+ Expr *BitWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS,
- AttributeList *MSPropertyAttr) {
+ const ParsedAttr &MSPropertyAttr) {
IdentifierInfo *II = D.getIdentifier();
if (!II) {
Diag(DeclStart, diag::err_anonymous_property);
@@ -15031,7 +15440,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
PrevDecl = nullptr;
SourceLocation TSSL = D.getLocStart();
- const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
+ const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData();
MSPropertyDecl *NewPD = MSPropertyDecl::Create(
Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
ProcessDeclAttributes(TUScope, NewPD, D);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index ff3c07e938a8..595cc76cd4a3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -109,9 +109,33 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
return true;
}
-void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
+/// Issue a warning if the parameter of the overridden method is non-escaping
+/// but the parameter of the overriding method is not.
+static bool diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,
+ Sema &S) {
+ if (OldD->hasAttr<NoEscapeAttr>() && !NewD->hasAttr<NoEscapeAttr>()) {
+ S.Diag(NewD->getLocation(), diag::warn_overriding_method_missing_noescape);
+ S.Diag(OldD->getLocation(), diag::note_overridden_marked_noescape);
+ return false;
+ }
+
+ return true;
+}
+
+/// Produce additional diagnostics if a category conforms to a protocol that
+/// defines a method taking a non-escaping parameter.
+static void diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,
+ const ObjCCategoryDecl *CD,
+ const ObjCProtocolDecl *PD, Sema &S) {
+ if (!diagnoseNoescape(NewD, OldD, S))
+ S.Diag(CD->getLocation(), diag::note_cat_conform_to_noescape_prot)
+ << CD->IsClassExtension() << PD
+ << cast<ObjCMethodDecl>(NewD->getDeclContext());
+}
+
+void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
const ObjCMethodDecl *Overridden) {
- if (Overridden->hasRelatedResultType() &&
+ if (Overridden->hasRelatedResultType() &&
!NewMethod->hasRelatedResultType()) {
// This can only happen when the method follows a naming convention that
// implies a related result type, and the original (overridden) method has
@@ -119,9 +143,9 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
// a suitable return type.
QualType ResultType = NewMethod->getReturnType();
SourceRange ResultTypeRange = NewMethod->getReturnTypeSourceRange();
-
+
// Figure out which class this method is part of, if any.
- ObjCInterfaceDecl *CurrentClass
+ ObjCInterfaceDecl *CurrentClass
= dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext());
if (!CurrentClass) {
DeclContext *DC = NewMethod->getDeclContext();
@@ -133,46 +157,46 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
= dyn_cast<ObjCCategoryImplDecl>(DC))
CurrentClass = CatImpl->getClassInterface();
}
-
+
if (CurrentClass) {
- Diag(NewMethod->getLocation(),
+ Diag(NewMethod->getLocation(),
diag::warn_related_result_type_compatibility_class)
<< Context.getObjCInterfaceType(CurrentClass)
<< ResultType
<< ResultTypeRange;
} else {
- Diag(NewMethod->getLocation(),
+ Diag(NewMethod->getLocation(),
diag::warn_related_result_type_compatibility_protocol)
<< ResultType
<< ResultTypeRange;
}
-
+
if (ObjCMethodFamily Family = Overridden->getMethodFamily())
- Diag(Overridden->getLocation(),
+ Diag(Overridden->getLocation(),
diag::note_related_result_type_family)
<< /*overridden method*/ 0
<< Family;
else
- Diag(Overridden->getLocation(),
+ Diag(Overridden->getLocation(),
diag::note_related_result_type_overridden);
}
- if (getLangOpts().ObjCAutoRefCount) {
- 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;
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_nsreturns_retained_attribute_mismatch
+ : 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;
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_nsreturns_retained_attribute_mismatch
+ : diag::warn_nsreturns_retained_attribute_mismatch)
+ << 0;
Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
}
@@ -185,21 +209,18 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
ParmVarDecl *newDecl = (*ni);
if (newDecl->hasAttr<NSConsumedAttr>() !=
oldDecl->hasAttr<NSConsumedAttr>()) {
- Diag(newDecl->getLocation(), diag::warn_nsconsumed_attribute_mismatch);
+ Diag(newDecl->getLocation(),
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_nsconsumed_attribute_mismatch
+ : diag::warn_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);
- }
+ diagnoseNoescape(newDecl, oldDecl, *this);
}
}
-/// \brief Check a method declaration for compatibility with the Objective-C
+/// Check a method declaration for compatibility with the Objective-C
/// ARC conventions.
bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
ObjCMethodFamily family = method->getMethodFamily();
@@ -229,7 +250,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
return true;
}
return false;
-
+
case OMF_init:
// If the method doesn't obey the init rules, don't bother annotating it.
if (checkInitMethod(method, QualType()))
@@ -263,12 +284,20 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND,
if (!ND)
return;
bool IsCategory = false;
- AvailabilityResult Availability = ND->getAvailability();
+ StringRef RealizedPlatform;
+ AvailabilityResult Availability = ND->getAvailability(
+ /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(),
+ &RealizedPlatform);
if (Availability != AR_Deprecated) {
if (isa<ObjCMethodDecl>(ND)) {
if (Availability != AR_Unavailable)
return;
- // Warn about implementing unavailable methods.
+ if (RealizedPlatform.empty())
+ RealizedPlatform = S.Context.getTargetInfo().getPlatformName();
+ // Warn about implementing unavailable methods, unless the unavailable
+ // is for an app extension.
+ if (RealizedPlatform.endswith("_app_extension"))
+ return;
S.Diag(ImplLoc, diag::warn_unavailable_def);
S.Diag(ND->getLocation(), diag::note_method_declared_at)
<< ND->getDeclName();
@@ -299,7 +328,7 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND,
/// pool.
void Sema::AddAnyMethodToGlobalPool(Decl *D) {
ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
-
+
// If we don't have a valid method decl, simply return.
if (!MDecl)
return;
@@ -314,7 +343,7 @@ void Sema::AddAnyMethodToGlobalPool(Decl *D) {
static bool
HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {
QualType T = Param->getType();
-
+
if (const PointerType *PT = T->getAs<PointerType>()) {
T = PT->getPointeeType();
} else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
@@ -322,8 +351,8 @@ HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {
} else {
return true;
}
-
- // If we have a lifetime qualifier, but it's local, we must have
+
+ // If we have a lifetime qualifier, but it's local, we must have
// inferred it. So, it is implicit.
return !T.getLocalQualifiers().hasObjCLifetime();
}
@@ -333,15 +362,22 @@ HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {
void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
assert((getCurMethodDecl() == nullptr) && "Methodparsing confused");
ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
-
+
// If we don't have a valid method decl, simply return.
if (!MDecl)
return;
+ QualType ResultType = MDecl->getReturnType();
+ if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
+ !MDecl->isInvalidDecl() &&
+ RequireCompleteType(MDecl->getLocation(), ResultType,
+ diag::err_func_def_incomplete_result))
+ MDecl->setInvalidDecl();
+
// Allow all of Sema to see that we are entering a method definition.
PushDeclContext(FnBodyScope, MDecl);
PushFunctionScope();
-
+
// Create Decl objects for each parameter, entrring them in the scope for
// binding to their use.
@@ -362,7 +398,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
!HasExplicitOwnershipAttr(*this, Param))
Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<
Param->getType();
-
+
if (Param->getIdentifier())
PushOnScopeChains(Param, FnBodyScope);
}
@@ -396,13 +432,13 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
// Warn on deprecated methods under -Wdeprecated-implementations,
// and prepare for warning on missing super calls.
if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {
- ObjCMethodDecl *IMD =
+ ObjCMethodDecl *IMD =
IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());
-
+
if (IMD) {
- ObjCImplDecl *ImplDeclOfMethodDef =
+ ObjCImplDecl *ImplDeclOfMethodDef =
dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());
- ObjCContainerDecl *ContDeclOfMethodDecl =
+ ObjCContainerDecl *ContDeclOfMethodDecl =
dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());
ObjCImplDecl *ImplDeclOfMethodDecl = nullptr;
if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))
@@ -445,12 +481,12 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
} else if (Family == OMF_finalize) {
if (Context.getLangOpts().getGC() != LangOptions::NonGC)
getCurFunction()->ObjCShouldCallSuper = true;
-
+
} else {
const ObjCMethodDecl *SuperMethod =
SuperClass->lookupMethod(MDecl->getSelector(),
MDecl->isInstanceMethod());
- getCurFunction()->ObjCShouldCallSuper =
+ getCurFunction()->ObjCShouldCallSuper =
(SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
}
}
@@ -591,11 +627,11 @@ ActOnSuperClassOfClassInterface(Scope *S,
// Handle type arguments on the superclass.
TypeSourceInfo *SuperClassTInfo = nullptr;
- if (!SuperTypeArgs.empty()) {
+ if (!SuperTypeArgs.empty()) {
TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers(
S,
SuperLoc,
- CreateParsedType(SuperClassType,
+ CreateParsedType(SuperClassType,
nullptr),
SuperTypeArgsRange.getBegin(),
SuperTypeArgs,
@@ -607,12 +643,12 @@ ActOnSuperClassOfClassInterface(Scope *S,
if (!fullSuperClassType.isUsable())
return;
- SuperClassType = GetTypeFromParser(fullSuperClassType.get(),
+ SuperClassType = GetTypeFromParser(fullSuperClassType.get(),
&SuperClassTInfo);
}
if (!SuperClassTInfo) {
- SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,
+ SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,
SuperLoc);
}
@@ -816,7 +852,7 @@ static bool checkTypeParamListConsistency(Sema &S,
// When the new type parameter is invariant and is not part
// of the definition, just propagate the variance.
newTypeParam->setVariance(prevTypeParam->getVariance());
- } else if (prevTypeParam->getVariance()
+ } else if (prevTypeParam->getVariance()
== ObjCTypeParamVariance::Invariant &&
!(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) &&
cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext())
@@ -930,16 +966,14 @@ static bool checkTypeParamListConsistency(Sema &S,
return false;
}
-Decl *Sema::
-ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName, SourceLocation ClassLoc,
- ObjCTypeParamList *typeParamList,
- IdentifierInfo *SuperName, SourceLocation SuperLoc,
- ArrayRef<ParsedType> SuperTypeArgs,
- SourceRange SuperTypeArgsRange,
- Decl * const *ProtoRefs, unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc, AttributeList *AttrList) {
+Decl *Sema::ActOnStartClassInterface(
+ Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+ SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+ IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
+ Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList) {
assert(ClassName && "Missing class identifier");
// Check for another declaration kind with the same name.
@@ -977,7 +1011,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) {
if (typeParamList) {
// Both have type parameter lists; check for consistency.
- if (checkTypeParamListConsistency(*this, prevTypeParamList,
+ if (checkTypeParamListConsistency(*this, prevTypeParamList,
typeParamList,
TypeParamListContext::Definition)) {
typeParamList = nullptr;
@@ -1004,7 +1038,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
Context.getTrivialTypeSourceInfo(typeParam->getUnderlyingType())));
}
- typeParamList = ObjCTypeParamList::create(Context,
+ typeParamList = ObjCTypeParamList::create(Context,
SourceLocation(),
clonedTypeParams,
SourceLocation());
@@ -1024,24 +1058,23 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
IDecl->setInvalidDecl();
}
}
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
AddPragmaAttributes(TUScope, IDecl);
PushOnScopeChains(IDecl, TUScope);
- // Start the definition of this class. If we're in a redefinition case, there
+ // Start the definition of this class. If we're in a redefinition case, there
// may already be a definition, so we'll end up adding to it.
if (!IDecl->hasDefinition())
IDecl->startDefinition();
-
+
if (SuperName) {
// Diagnose availability in the context of the @interface.
ContextRAII SavedContext(*this, IDecl);
- ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,
- ClassName, ClassLoc,
- SuperName, SuperLoc, SuperTypeArgs,
+ ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,
+ ClassName, ClassLoc,
+ SuperName, SuperLoc, SuperTypeArgs,
SuperTypeArgsRange);
} else { // we have a root class.
IDecl->setEndOfDefinitionLoc(ClassLoc);
@@ -1073,7 +1106,7 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
LookupOrdinaryName);
if (!IDecl)
return;
-
+
if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType())
@@ -1142,7 +1175,7 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency(
IdentifierInfo *PName,
SourceLocation &Ploc, SourceLocation PrevLoc,
const ObjCList<ObjCProtocolDecl> &PList) {
-
+
bool res = false;
for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),
E = PList.end(); I != E; ++I) {
@@ -1153,10 +1186,10 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency(
Diag(PrevLoc, diag::note_previous_definition);
res = true;
}
-
+
if (!PDecl->hasDefinition())
continue;
-
+
if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,
PDecl->getLocation(), PDecl->getReferencedProtocols()))
res = true;
@@ -1165,15 +1198,11 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency(
return res;
}
-Decl *
-Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
- IdentifierInfo *ProtocolName,
- SourceLocation ProtocolLoc,
- Decl * const *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
+Decl *Sema::ActOnStartProtocolInterface(
+ SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
+ SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList) {
bool err = false;
// FIXME: Deal with AttrList.
assert(ProtocolName && "Missing protocol identifier");
@@ -1192,6 +1221,11 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
/*PrevDecl=*/nullptr);
+
+ // If we are using modules, add the decl to the context in order to
+ // serialize something meaningful.
+ if (getLangOpts().Modules)
+ PushOnScopeChains(PDecl, TUScope);
PDecl->startDefinition();
} else {
if (PrevDecl) {
@@ -1207,13 +1241,12 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
/*PrevDecl=*/PrevDecl);
-
+
PushOnScopeChains(PDecl, TUScope);
PDecl->startDefinition();
}
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+
+ ProcessDeclAttributeList(TUScope, PDecl, AttrList);
AddPragmaAttributes(TUScope, PDecl);
// Merge attributes from previous declarations.
@@ -1238,7 +1271,7 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
UndefinedProtocol = PDecl;
return true;
}
-
+
for (auto *PI : PDecl->protocols())
if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) {
UndefinedProtocol = PI;
@@ -1285,7 +1318,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
// case, do it.
// FIXME: Recover nicely in the hidden case.
ObjCProtocolDecl *UndefinedProtocol;
-
+
if (WarnOnDeclarations &&
NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {
Diag(Pair.second, diag::warn_undef_protocolref) << Pair.first;
@@ -1378,7 +1411,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
unsigned numProtocolsResolved = 0;
auto resolvedAsProtocols = [&] {
assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");
-
+
// Determine whether the base type is a parameterized class, in
// which case we want to warn about typos such as
// "NSArray<NSObject>" (that should be NSArray<NSObject *>).
@@ -1401,7 +1434,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
}
for (unsigned i = 0, n = protocols.size(); i != n; ++i) {
- ObjCProtocolDecl *&proto
+ ObjCProtocolDecl *&proto
= reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]);
// For an objc container, delay protocol reference checking until after we
// can set the objc decl as the availability context, otherwise check now.
@@ -1443,7 +1476,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
}
}
}
-
+
// All of the protocols listed also have type names, and at least
// one is an Objective-C class name. Check whether all of the
// protocol conformances are declared by the base class itself, in
@@ -1518,7 +1551,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
// Local function that forms a reference to the given type or
// Objective-C class declaration.
- auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)
+ auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)
-> TypeResult {
// Form declaration specifiers. They simply refer to the type.
DeclSpec DS(attrFactory);
@@ -1544,14 +1577,12 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
// add the '*'.
if (type->getAs<ObjCInterfaceType>()) {
SourceLocation starLoc = getLocForEndOfToken(loc);
- ParsedAttributes parsedAttrs(attrFactory);
D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation()),
- parsedAttrs,
starLoc);
// Diagnose the missing '*'.
@@ -1729,22 +1760,21 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
Sema::DeclGroupPtrTy
Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
ArrayRef<IdentifierLocPair> IdentList,
- AttributeList *attrList) {
+ const ParsedAttributesView &attrList) {
SmallVector<Decl *, 8> DeclsInGroup;
for (const IdentifierLocPair &IdentPair : IdentList) {
IdentifierInfo *Ident = IdentPair.first;
ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second,
forRedeclarationInCurContext());
ObjCProtocolDecl *PDecl
- = ObjCProtocolDecl::Create(Context, CurContext, Ident,
+ = ObjCProtocolDecl::Create(Context, CurContext, Ident,
IdentPair.second, AtProtocolLoc,
PrevDecl);
-
+
PushOnScopeChains(PDecl, TUScope);
CheckObjCDeclScope(PDecl);
-
- if (attrList)
- ProcessDeclAttributeList(TUScope, PDecl, attrList);
+
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
AddPragmaAttributes(TUScope, PDecl);
if (PrevDecl)
@@ -1756,23 +1786,19 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
return BuildDeclaratorGroup(DeclsInGroup);
}
-Decl *Sema::
-ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName, SourceLocation ClassLoc,
- ObjCTypeParamList *typeParamList,
- IdentifierInfo *CategoryName,
- SourceLocation CategoryLoc,
- Decl * const *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
+Decl *Sema::ActOnStartCategoryInterface(
+ SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+ SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+ IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+ Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList) {
ObjCCategoryDecl *CDecl;
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
/// Check that class of this category is already completely declared.
- if (!IDecl
+ if (!IDecl
|| RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
diag::err_category_forward_interface,
CategoryName == nullptr)) {
@@ -1784,7 +1810,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
IDecl, typeParamList);
CDecl->setInvalidDecl();
CurContext->addDecl(CDecl);
-
+
if (!IDecl)
Diag(ClassLoc, diag::err_undef_interface) << ClassName;
return ActOnObjCContainerStartDefinition(CDecl);
@@ -1792,7 +1818,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
if (!CategoryName && IDecl->getImplementation()) {
Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
- Diag(IDecl->getImplementation()->getLocation(),
+ Diag(IDecl->getImplementation()->getLocation(),
diag::note_implementation_declared);
}
@@ -1832,6 +1858,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
+ // Process the attributes before looking at protocols to ensure that the
+ // availability attribute is attached to the category to provide availability
+ // checking for protocol uses.
+ ProcessDeclAttributeList(TUScope, CDecl, AttrList);
+ AddPragmaAttributes(TUScope, CDecl);
+
if (NumProtoRefs) {
diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs,
NumProtoRefs, ProtoLocs);
@@ -1839,14 +1871,10 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
ProtoLocs, Context);
// Protocols in the class extension belong to the class.
if (CDecl->IsClassExtension())
- IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs,
- NumProtoRefs, Context);
+ IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs,
+ NumProtoRefs, Context);
}
- if (AttrList)
- ProcessDeclAttributeList(TUScope, CDecl, AttrList);
- AddPragmaAttributes(TUScope, CDecl);
-
CheckObjCDeclScope(CDecl);
return ActOnObjCContainerStartDefinition(CDecl);
}
@@ -1905,7 +1933,7 @@ Decl *Sema::ActOnStartCategoryImplementation(
CDecl->setInvalidDecl();
} else {
CatIDecl->setImplementation(CDecl);
- // Warn on implementating category of deprecated class under
+ // Warn on implementating category of deprecated class under
// -Wdeprecated-implementations flag.
DiagnoseObjCImplementedDeprecations(*this, CatIDecl,
CDecl->getLocation());
@@ -1999,7 +2027,7 @@ Decl *Sema::ActOnStartClassImplementation(
} else {
IDecl->setEndOfDefinitionLoc(ClassLoc);
}
-
+
PushOnScopeChains(IDecl, TUScope);
} else {
// Mark the interface as being completed, even if it was just as
@@ -2026,7 +2054,7 @@ Decl *Sema::ActOnStartClassImplementation(
} else { // add it to the list.
IDecl->setImplementation(IMPDecl);
PushOnScopeChains(IMPDecl, TUScope);
- // Warn on implementating deprecated class under
+ // Warn on implementating deprecated class under
// -Wdeprecated-implementations flag.
DiagnoseObjCImplementedDeprecations(*this, IDecl, IMPDecl->getLocation());
}
@@ -2080,7 +2108,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
IDecl->makeDeclVisibleInContext(ivars[i]);
ImpDecl->addDecl(ivars[i]);
}
-
+
return;
}
// If implementation has empty ivar list, just return.
@@ -2093,17 +2121,17 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use);
for (unsigned i = 0; i < numIvars; i++) {
ObjCIvarDecl* ImplIvar = ivars[i];
- if (const ObjCIvarDecl *ClsIvar =
+ if (const ObjCIvarDecl *ClsIvar =
IDecl->getIvarDecl(ImplIvar->getIdentifier())) {
- Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
+ Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
// Check class extensions (unnamed categories) for duplicate ivars.
for (const auto *CDecl : IDecl->visible_extensions()) {
- if (const ObjCIvarDecl *ClsExtIvar =
+ if (const ObjCIvarDecl *ClsExtIvar =
CDecl->getIvarDecl(ImplIvar->getIdentifier())) {
- Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
+ Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
continue;
}
@@ -2162,17 +2190,9 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
unsigned DiagID,
NamedDecl *NeededFor = nullptr) {
// No point warning no definition of method which is 'unavailable'.
- switch (method->getAvailability()) {
- case AR_Available:
- case AR_Deprecated:
- break;
-
- // Don't warn about unavailable or not-yet-introduced methods.
- case AR_NotYetIntroduced:
- case AR_Unavailable:
+ if (method->getAvailability() == AR_Unavailable)
return;
- }
-
+
// FIXME: For now ignore 'IncompleteImpl'.
// Previously we grouped all unimplemented methods under a single
// warning, but some users strongly voiced that they would prefer
@@ -2192,8 +2212,8 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
}
/// Determines if type B can be substituted for type A. Returns true if we can
-/// guarantee that anything that the user will do to an object of type A can
-/// also be done to an object of type B. This is trivially true if the two
+/// guarantee that anything that the user will do to an object of type A can
+/// also be done to an object of type B. This is trivially true if the two
/// types are the same, or if B is a subclass of A. It becomes more complex
/// in cases where protocols are involved.
///
@@ -2202,12 +2222,12 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
/// example, if A is a subclass of B, then B* may refer to an instance of A.
/// The principle of substitutability means that we may use an instance of A
/// anywhere that we may use an instance of B - it will implement all of the
-/// ivars of B and all of the methods of B.
+/// ivars of B and all of the methods of B.
///
-/// This substitutability is important when type checking methods, because
+/// This substitutability is important when type checking methods, because
/// the implementation may have stricter type definitions than the interface.
/// The interface specifies minimum requirements, but the implementation may
-/// have more accurate ones. For example, a method may privately accept
+/// have more accurate ones. For example, a method may privately accept
/// instances of B, but only publish that it accepts instances of A. Any
/// object passed to it will be type checked against B, and so will implicitly
/// by a valid A*. Similarly, a method may return a subclass of the class that
@@ -2223,7 +2243,7 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
/// advertises, but it may be specified more accurately. This avoids the need
/// for explicit down-casting by callers.
///
-/// Note: This is a stricter requirement than for assignment.
+/// Note: This is a stricter requirement than for assignment.
static bool isObjCTypeSubstitutable(ASTContext &Context,
const ObjCObjectPointerType *A,
const ObjCObjectPointerType *B,
@@ -2312,15 +2332,15 @@ static bool CheckMethodOverrideReturn(Sema &S,
!= 0));
S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
-
+
if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),
MethodDecl->getReturnType()))
return true;
if (!Warn)
return false;
- unsigned DiagID =
- IsOverridingMode ? diag::warn_conflicting_overriding_ret_types
+ unsigned DiagID =
+ IsOverridingMode ? diag::warn_conflicting_overriding_ret_types
: diag::warn_conflicting_ret_types;
// Mismatches between ObjC pointers go into a different warning
@@ -2336,8 +2356,8 @@ static bool CheckMethodOverrideReturn(Sema &S,
if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))
return false;
- DiagID =
- IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types
+ DiagID =
+ IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types
: diag::warn_non_covariant_ret_types;
}
}
@@ -2366,21 +2386,21 @@ static bool CheckMethodOverrideParam(Sema &S,
IfaceVar->getObjCDeclQualifier())) {
if (Warn) {
if (IsOverridingMode)
- S.Diag(ImplVar->getLocation(),
+ S.Diag(ImplVar->getLocation(),
diag::warn_conflicting_overriding_param_modifiers)
<< getTypeRange(ImplVar->getTypeSourceInfo())
<< MethodImpl->getDeclName();
- else S.Diag(ImplVar->getLocation(),
+ else S.Diag(ImplVar->getLocation(),
diag::warn_conflicting_param_modifiers)
<< getTypeRange(ImplVar->getTypeSourceInfo())
<< MethodImpl->getDeclName();
S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
- << getTypeRange(IfaceVar->getTypeSourceInfo());
+ << getTypeRange(IfaceVar->getTypeSourceInfo());
}
else
return false;
}
-
+
QualType ImplTy = ImplVar->getType();
QualType IfaceTy = IfaceVar->getType();
if (Warn && IsOverridingMode &&
@@ -2403,8 +2423,8 @@ static bool CheckMethodOverrideParam(Sema &S,
if (!Warn)
return false;
- unsigned DiagID =
- IsOverridingMode ? diag::warn_conflicting_overriding_param_types
+ unsigned DiagID =
+ IsOverridingMode ? diag::warn_conflicting_overriding_param_types
: diag::warn_conflicting_param_types;
// Mismatches between ObjC pointers go into a different warning
@@ -2420,8 +2440,8 @@ static bool CheckMethodOverrideParam(Sema &S,
if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))
return false;
- DiagID =
- IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types
+ DiagID =
+ IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types
: diag::warn_non_contravariant_param_types;
}
}
@@ -2429,8 +2449,8 @@ static bool CheckMethodOverrideParam(Sema &S,
S.Diag(ImplVar->getLocation(), DiagID)
<< getTypeRange(ImplVar->getTypeSourceInfo())
<< MethodImpl->getDeclName() << IfaceTy << ImplTy;
- S.Diag(IfaceVar->getLocation(),
- (IsOverridingMode ? diag::note_previous_declaration
+ S.Diag(IfaceVar->getLocation(),
+ (IsOverridingMode ? diag::note_previous_declaration
: diag::note_previous_definition))
<< getTypeRange(IfaceVar->getTypeSourceInfo());
return false;
@@ -2515,8 +2535,8 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl))
return;
- CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
- IsProtocolMethodDecl, false,
+ CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
+ IsProtocolMethodDecl, false,
true);
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
@@ -2528,7 +2548,7 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
}
if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
- Diag(ImpMethodDecl->getLocation(),
+ Diag(ImpMethodDecl->getLocation(),
diag::warn_conflicting_variadic);
Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
@@ -2537,11 +2557,11 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
ObjCMethodDecl *Overridden,
bool IsProtocolMethodDecl) {
-
- CheckMethodOverrideReturn(*this, Method, Overridden,
- IsProtocolMethodDecl, true,
+
+ CheckMethodOverrideReturn(*this, Method, Overridden,
+ IsProtocolMethodDecl, true,
true);
-
+
for (ObjCMethodDecl::param_iterator IM = Method->param_begin(),
IF = Overridden->param_begin(), EM = Method->param_end(),
EF = Overridden->param_end();
@@ -2549,9 +2569,9 @@ void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
CheckMethodOverrideParam(*this, Method, Overridden, *IM, *IF,
IsProtocolMethodDecl, true, true);
}
-
+
if (Method->isVariadic() != Overridden->isVariadic()) {
- Diag(Method->getLocation(),
+ Diag(Method->getLocation(),
diag::warn_conflicting_overriding_variadic);
Diag(Overridden->getLocation(), diag::note_previous_declaration);
}
@@ -2567,20 +2587,20 @@ void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,
// to implement it.
if (MethodDecl->getImplementationControl() == ObjCMethodDecl::Optional)
return;
- // don't issue warning when primary class's method is
+ // don't issue warning when primary class's method is
// depecated/unavailable.
if (MethodDecl->hasAttr<UnavailableAttr>() ||
MethodDecl->hasAttr<DeprecatedAttr>())
return;
-
- bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
+
+ bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
IsProtocolMethodDecl, false, false);
if (match)
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),
EF = MethodDecl->param_end();
IM != EM && IF != EF; ++IM, ++IF) {
- match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl,
+ match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl,
*IM, *IF,
IsProtocolMethodDecl, false, false);
if (!match)
@@ -2591,9 +2611,9 @@ void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,
if (match)
match = !(MethodDecl->isClassMethod() &&
MethodDecl->getSelector() == GetNullarySelector("load", Context));
-
+
if (match) {
- Diag(ImpMethodDecl->getLocation(),
+ Diag(ImpMethodDecl->getLocation(),
diag::warn_category_method_impl_match);
Diag(MethodDecl->getLocation(), diag::note_method_declared_at)
<< MethodDecl->getDeclName();
@@ -2642,10 +2662,10 @@ static void CheckProtocolMethodDefs(Sema &S,
ObjCContainerDecl *CDecl,
LazyProtocolNameSet &ProtocolsExplictImpl) {
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
- ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()
+ ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()
: dyn_cast<ObjCInterfaceDecl>(CDecl);
assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");
-
+
ObjCInterfaceDecl *Super = IDecl->getSuperClass();
ObjCInterfaceDecl *NSIDecl = nullptr;
@@ -2694,7 +2714,7 @@ static void CheckProtocolMethodDefs(Sema &S,
if (!PDecl->isThisDeclarationADefinition() &&
PDecl->getDefinition())
PDecl = PDecl->getDefinition();
-
+
// If a method lookup fails locally we still need to look and see if
// the method was implemented by a base class or an inherited
// protocol. This lookup is slow, but occurs rarely in correct code
@@ -2713,11 +2733,11 @@ static void CheckProtocolMethodDefs(Sema &S,
nullptr /* category */))) {
// If a method is not implemented in the category implementation but
// has been declared in its primary class, superclass,
- // or in one of their protocols, no need to issue the warning.
- // This is because method will be implemented in the primary class
+ // or in one of their protocols, no need to issue the warning.
+ // This is because method will be implemented in the primary class
// or one of its super class implementation.
-
- // Ugly, but necessary. Method declared in protcol might have
+
+ // Ugly, but necessary. Method declared in protocol might have
// have been synthesized due to a property declared in the class which
// uses the protocol.
if (ObjCMethodDecl *MethodInClass =
@@ -2826,7 +2846,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
}
}
}
-
+
if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) {
// Also, check for methods declared in protocols inherited by
// this protocol.
@@ -2835,7 +2855,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
}
-
+
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
// when checking that methods in implementation match their declaration,
// i.e. when WarnCategoryMethodImpl is false, check declarations in class
@@ -2860,8 +2880,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
- // FIXME. For now, we are not checking for extact match of methods
- // in category implementation and its primary class's super class.
+ // FIXME. For now, we are not checking for extact match of methods
+ // in category implementation and its primary class's super class.
if (!WarnCategoryMethodImpl && I->getSuperClass())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
@@ -2871,7 +2891,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
/// category matches with those implemented in its primary class and
-/// warns each time an exact match is found.
+/// warns each time an exact match is found.
void Sema::CheckCategoryVsClassMethodMatches(
ObjCCategoryImplDecl *CatIMPDecl) {
// Get category's primary class.
@@ -2883,7 +2903,7 @@ void Sema::CheckCategoryVsClassMethodMatches(
return;
ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();
SelectorSet InsMap, ClsMap;
-
+
for (const auto *I : CatIMPDecl->instance_methods()) {
Selector Sel = I->getSelector();
// When checking for methods implemented in the category, skip over
@@ -2893,7 +2913,7 @@ void Sema::CheckCategoryVsClassMethodMatches(
continue;
InsMap.insert(Sel);
}
-
+
for (const auto *I : CatIMPDecl->class_methods()) {
Selector Sel = I->getSelector();
if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))
@@ -2902,12 +2922,12 @@ void Sema::CheckCategoryVsClassMethodMatches(
}
if (InsMap.empty() && ClsMap.empty())
return;
-
+
SelectorSet InsMapSeen, ClsMapSeen;
bool IncompleteImpl = false;
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
CatIMPDecl, IDecl,
- IncompleteImpl, false,
+ IncompleteImpl, false,
true /*WarnCategoryMethodImpl*/);
}
@@ -2957,10 +2977,10 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl, CDecl,
IncompleteImpl, true);
-
+
// check all methods implemented in category against those declared
// in its primary class.
- if (ObjCCategoryImplDecl *CatDecl =
+ if (ObjCCategoryImplDecl *CatDecl =
dyn_cast<ObjCCategoryImplDecl>(IMPDecl))
CheckCategoryVsClassMethodMatches(CatDecl);
@@ -2985,7 +3005,7 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
ExplicitImplProtocols);
DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,
/*SynthesizeProperties=*/false);
- }
+ }
} else
llvm_unreachable("invalid ObjCContainerDecl type.");
}
@@ -3000,7 +3020,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
for (unsigned i = 0; i != NumElts; ++i) {
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
- = LookupSingleName(TUScope, IdentList[i], IdentLocs[i],
+ = LookupSingleName(TUScope, IdentList[i], IdentLocs[i],
LookupOrdinaryName, forRedeclarationInCurContext());
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
// GCC apparently allows the following idiom:
@@ -3027,7 +3047,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
}
}
}
-
+
// Create a declaration to describe this forward declaration.
ObjCInterfaceDecl *PrevIDecl
= dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
@@ -3118,7 +3138,7 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy,
// Consider all the kinds of non-dependent canonical types:
// - functions and arrays aren't possible as return and parameter types
-
+
// - vector types of equal size can be arbitrarily mixed
if (isa<VectorType>(left)) return isa<VectorType>(right);
if (isa<VectorType>(right)) return false;
@@ -3345,7 +3365,7 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List,
Previous->setNext(new (Mem) ObjCMethodList(Method));
}
-/// \brief Read the contents of the method pool for a given selector from
+/// Read the contents of the method pool for a given selector from
/// external storage.
void Sema::ReadMethodPool(Selector Sel) {
assert(ExternalSource && "We need an external AST source");
@@ -3366,14 +3386,14 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
if (ExternalSource)
ReadMethodPool(Method->getSelector());
-
+
GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector());
if (Pos == MethodPool.end())
Pos = MethodPool.insert(std::make_pair(Method->getSelector(),
GlobalMethods())).first;
Method->setDefined(impl);
-
+
ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
addMethodToGlobalList(&Entry, Method);
}
@@ -3427,7 +3447,7 @@ static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method,
MethodInterface->isSuperClassOf(BoundInterface) ||
BoundInterface->isSuperClassOf(MethodInterface);
}
- llvm_unreachable("unknow method context");
+ llvm_unreachable("unknown method context");
}
/// We first select the type of the method: Instance or Factory, then collect
@@ -3501,7 +3521,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
bool instance) {
if (ExternalSource)
ReadMethodPool(Sel);
-
+
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
if (Pos == MethodPool.end())
return nullptr;
@@ -3551,7 +3571,7 @@ void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &
break;
}
}
-
+
if (issueDiagnostic) {
if (issueError)
Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
@@ -3559,7 +3579,7 @@ void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &
Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
else
Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
-
+
Diag(Methods[0]->getLocStart(),
issueError ? diag::note_possibility : diag::note_using)
<< Methods[0]->getSourceRange();
@@ -3582,7 +3602,7 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
(Method->getMethod()->isDefined() ||
Method->getMethod()->isPropertyAccessor()))
return Method->getMethod();
-
+
for (const ObjCMethodList *Method = &Methods.second; Method;
Method = Method->getNext())
if (Method->getMethod() &&
@@ -3599,7 +3619,7 @@ HelperSelectorsForTypoCorrection(
const unsigned MaxEditDistance = 1;
unsigned BestEditDistance = MaxEditDistance + 1;
std::string MethodName = Method->getSelector().getAsString();
-
+
unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size());
if (MinPossibleEditDistance > 0 &&
Typo.size() / MinPossibleEditDistance < 1)
@@ -3674,7 +3694,7 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
Methods.push_back(M->getMethod());
}
}
-
+
SmallVector<const ObjCMethodDecl *, 8> SelectedMethods;
for (unsigned i = 0, e = Methods.size(); i < e; i++) {
HelperSelectorsForTypoCorrection(SelectedMethods,
@@ -3684,11 +3704,11 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
}
/// DiagnoseDuplicateIvars -
-/// Check for duplicate ivars in the entire class at the start of
+/// Check for duplicate ivars in the entire class at the start of
/// \@implementation. This becomes necesssary because class extension can
/// add ivars to a class in random order which will not be known until
/// class's \@implementation is seen.
-void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
+void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
ObjCInterfaceDecl *SID) {
for (auto *Ivar : ID->ivars()) {
if (Ivar->isInvalidDecl())
@@ -3859,9 +3879,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
assert(AtEnd.isValid() && "Invalid location for '@end'");
- ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- Decl *ClassDecl = cast<Decl>(OCD);
-
+ auto *OCD = cast<ObjCContainerDecl>(CurContext);
+ Decl *ClassDecl = OCD;
+
bool isInterfaceDeclKind =
isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
|| isa<ObjCProtocolDecl>(ClassDecl);
@@ -3960,7 +3980,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
if (const ObjCPropertyImplDecl *PIDecl
= IC->FindPropertyImplDecl(Property->getIdentifier(),
Property->getQueryKind()))
- if (PIDecl->getPropertyImplementation()
+ if (PIDecl->getPropertyImplementation()
== ObjCPropertyImplDecl::Dynamic)
continue;
@@ -4084,15 +4104,15 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
}
-/// \brief Check whether the declared result type of the given Objective-C
+/// Check whether the declared result type of the given Objective-C
/// method declaration is compatible with the method's class.
///
-static Sema::ResultTypeCompatibilityKind
+static Sema::ResultTypeCompatibilityKind
CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,
ObjCInterfaceDecl *CurrentClass) {
QualType ResultType = Method->getReturnType();
- // If an Objective-C method inherits its related result type, then its
+ // If an Objective-C method inherits its related result type, then its
// declared result type must be compatible with its own class type. The
// declared result type is compatible if:
if (const ObjCObjectPointerType *ResultObjectType
@@ -4101,25 +4121,25 @@ CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,
if (ResultObjectType->isObjCIdType() ||
ResultObjectType->isObjCQualifiedIdType())
return Sema::RTC_Compatible;
-
+
if (CurrentClass) {
- if (ObjCInterfaceDecl *ResultClass
+ if (ObjCInterfaceDecl *ResultClass
= ResultObjectType->getInterfaceDecl()) {
// - it is the same as the method's class type, or
if (declaresSameEntity(CurrentClass, ResultClass))
return Sema::RTC_Compatible;
-
+
// - it is a superclass of the method's class type
if (ResultClass->isSuperClassOf(CurrentClass))
return Sema::RTC_Compatible;
- }
+ }
} else {
// Any Objective-C pointer type might be acceptable for a protocol
// method; we just don't know.
return Sema::RTC_Unknown;
}
}
-
+
return Sema::RTC_Incompatible;
}
@@ -4130,7 +4150,7 @@ class OverrideSearch {
public:
Sema &S;
ObjCMethodDecl *Method;
- llvm::SmallPtrSet<ObjCMethodDecl*, 4> Overridden;
+ llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden;
bool Recursive;
public:
@@ -4143,7 +4163,7 @@ public:
if (it == S.MethodPool.end()) {
if (!S.getExternalSource()) return;
S.ReadMethodPool(selector);
-
+
it = S.MethodPool.find(selector);
if (it == S.MethodPool.end())
return;
@@ -4167,7 +4187,7 @@ public:
}
}
- typedef llvm::SmallPtrSetImpl<ObjCMethodDecl*>::iterator iterator;
+ typedef decltype(Overridden)::iterator iterator;
iterator begin() const { return Overridden.begin(); }
iterator end() const { return Overridden.end(); }
@@ -4191,7 +4211,7 @@ private:
void searchFrom(ObjCProtocolDecl *protocol) {
if (!protocol->hasDefinition())
return;
-
+
// A method in a protocol declaration overrides declarations from
// referenced ("parent") protocols.
search(protocol->getReferencedProtocols());
@@ -4223,7 +4243,7 @@ private:
// A method in a class declaration overrides declarations from
if (!iface->hasDefinition())
return;
-
+
// - categories,
for (auto *Cat : iface->known_categories())
search(Cat);
@@ -4335,20 +4355,16 @@ 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.
// Check for overriding methods
- if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) ||
+ if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) ||
isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext()))
CheckConflictingOverridingMethod(ObjCMethod, overridden,
isa<ObjCProtocolDecl>(overridden->getDeclContext()));
-
+
if (CurrentClass && overridden->getDeclContext() != CurrentClass &&
isa<ObjCInterfaceDecl>(overridden->getDeclContext()) &&
!overridden->isImplicit() /* not meant for properties */) {
@@ -4502,25 +4518,21 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef,
}
Decl *Sema::ActOnMethodDeclaration(
- Scope *S,
- SourceLocation MethodLoc, SourceLocation EndLoc,
- tok::TokenKind MethodType,
- ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
- ArrayRef<SourceLocation> SelectorLocs,
- Selector Sel,
+ Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc,
+ tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
// optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs().
- ObjCArgInfo *ArgInfo,
- DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
- AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
+ ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
+ unsigned CNumArgs, // c-style args
+ const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind,
bool isVariadic, bool MethodDefinition) {
// Make sure we can establish a context for the method.
if (!CurContext->isObjCContainer()) {
Diag(MethodLoc, diag::err_missing_method_context);
return nullptr;
}
- ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- Decl *ClassDecl = cast<Decl>(OCD);
+ Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
QualType resultDeclType;
bool HasRelatedResultType = false;
@@ -4562,17 +4574,17 @@ Decl *Sema::ActOnMethodDeclaration(
ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
}
- LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc,
+ LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc,
LookupOrdinaryName, forRedeclarationInCurContext());
LookupName(R, S);
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
if (S->isDeclScope(PrevDecl)) {
- Diag(ArgInfo[i].NameLoc,
- (MethodDefinition ? diag::warn_method_param_redefinition
- : diag::warn_method_param_declaration))
+ Diag(ArgInfo[i].NameLoc,
+ (MethodDefinition ? diag::warn_method_param_redefinition
+ : diag::warn_method_param_declaration))
<< ArgInfo[i].Name;
- Diag(PrevDecl->getLocation(),
+ Diag(PrevDecl->getLocation(),
diag::note_previous_declaration);
}
}
@@ -4603,7 +4615,7 @@ Decl *Sema::ActOnMethodDeclaration(
Params.push_back(Param);
}
-
+
for (unsigned i = 0, e = CNumArgs; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);
QualType ArgType = Param->getType();
@@ -4616,13 +4628,12 @@ Decl *Sema::ActOnMethodDeclaration(
Param->setDeclContext(ObjCMethod);
Params.push_back(Param);
}
-
+
ObjCMethod->setMethodParams(Context, Params, SelectorLocs);
ObjCMethod->setObjCDeclQualifier(
CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
- if (AttrList)
- ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+ ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
AddPragmaAttributes(TUScope, ObjCMethod);
// Add the method now.
@@ -4650,6 +4661,22 @@ Decl *Sema::ActOnMethodDeclaration(
<< ObjCMethod->getDeclName();
}
}
+
+ // Warn if a method declared in a protocol to which a category or
+ // extension conforms is non-escaping and the implementation's method is
+ // escaping.
+ for (auto *C : IDecl->visible_categories())
+ for (auto &P : C->protocols())
+ if (auto *IMD = P->lookupMethod(ObjCMethod->getSelector(),
+ ObjCMethod->isInstanceMethod())) {
+ assert(ObjCMethod->parameters().size() ==
+ IMD->parameters().size() &&
+ "Methods have different number of parameters");
+ auto OI = IMD->param_begin(), OE = IMD->param_end();
+ auto NI = ObjCMethod->param_begin();
+ for (; OI != OE; ++OI, ++NI)
+ diagnoseNoescape(*NI, *OI, C, P, *this);
+ }
}
} else {
cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
@@ -4703,12 +4730,12 @@ Decl *Sema::ActOnMethodDeclaration(
case OMF_initialize:
case OMF_performSelector:
break;
-
+
case OMF_alloc:
case OMF_new:
InferRelatedResultType = ObjCMethod->isClassMethod();
break;
-
+
case OMF_init:
case OMF_autorelease:
case OMF_retain:
@@ -4716,7 +4743,7 @@ Decl *Sema::ActOnMethodDeclaration(
InferRelatedResultType = ObjCMethod->isInstanceMethod();
break;
}
-
+
if (InferRelatedResultType &&
!ObjCMethod->getReturnType()->isObjCIndependentClassType())
ObjCMethod->SetRelatedResultType();
@@ -4726,6 +4753,17 @@ Decl *Sema::ActOnMethodDeclaration(
Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
checkObjCMethodX86VectorTypes(*this, ObjCMethod);
+ // + load method cannot have availability attributes. It get called on
+ // startup, so it has to have the availability of the deployment target.
+ if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) {
+ if (ObjCMethod->isClassMethod() &&
+ ObjCMethod->getSelector().getAsString() == "load") {
+ Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
+ << 0;
+ ObjCMethod->dropAttr<AvailabilityAttr>();
+ }
+ }
+
ActOnDocumentableDecl(ObjCMethod);
return ObjCMethod;
@@ -4741,7 +4779,7 @@ bool Sema::CheckObjCDeclScope(Decl *D) {
// an objc container, it means the parser missed emitting an error.
if (isa<TranslationUnitDecl>(getCurLexicalContext()->getRedeclContext()))
return false;
-
+
Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
D->setInvalidDecl();
@@ -4769,7 +4807,7 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
Context.DeepCollectObjCIvars(Class, true, Ivars);
// For each ivar, create a fresh ObjCAtDefsFieldDecl.
for (unsigned i = 0; i < Ivars.size(); i++) {
- const FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
+ const FieldDecl* ID = Ivars[i];
RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,
/*FIXME: StartL=*/ID->getLocation(),
@@ -4784,19 +4822,19 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
D != Decls.end(); ++D) {
FieldDecl *FD = cast<FieldDecl>(*D);
if (getLangOpts().CPlusPlus)
- PushOnScopeChains(cast<FieldDecl>(FD), S);
+ PushOnScopeChains(FD, S);
else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))
Record->addDecl(FD);
}
}
-/// \brief Build a type-check a new Objective-C exception variable declaration.
+/// Build a type-check a new Objective-C exception variable declaration.
VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
SourceLocation StartLoc,
SourceLocation IdLoc,
IdentifierInfo *Id,
bool Invalid) {
- // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
+ // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
// duration shall not be qualified by an address-space qualifier."
// Since all parameters have automatic store duration, they can not have
// an address space.
@@ -4804,25 +4842,30 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
Diag(IdLoc, diag::err_arg_with_address_space);
Invalid = true;
}
-
+
// An @catch parameter must be an unqualified object pointer type;
// FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?
if (Invalid) {
// Don't do any further checking.
} else if (T->isDependentType()) {
// Okay: we don't know what this type will instantiate to.
- } else if (!T->isObjCObjectPointerType()) {
- Invalid = true;
- Diag(IdLoc ,diag::err_catch_param_not_objc_type);
} else if (T->isObjCQualifiedIdType()) {
Invalid = true;
Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);
+ } else if (T->isObjCIdType()) {
+ // Okay: we don't know what this type will instantiate to.
+ } else if (!T->isObjCObjectPointerType()) {
+ Invalid = true;
+ Diag(IdLoc, diag::err_catch_param_not_objc_type);
+ } else if (!T->getAs<ObjCObjectPointerType>()->getInterfaceType()) {
+ Invalid = true;
+ Diag(IdLoc, diag::err_catch_param_not_objc_type);
}
-
+
VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id,
T, TInfo, SC_None);
New->setExceptionVariable(true);
-
+
// In ARC, infer 'retaining' for variables of retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New))
Invalid = true;
@@ -4834,7 +4877,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
-
+
// We allow the "register" storage class on exception variables because
// GCC did, but we drop it completely. Any other storage class is an error.
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
@@ -4854,12 +4897,12 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
D.getMutableDeclSpec().ClearStorageClassSpecs();
DiagnoseFunctionSpecifiers(D.getDeclSpec());
-
+
// Check that there are no default arguments inside the type of this
// exception object (C++ only).
if (getLangOpts().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
-
+
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType ExceptionType = TInfo->getType();
@@ -4868,21 +4911,21 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
D.getIdentifierLoc(),
D.getIdentifier(),
D.isInvalidType());
-
+
// Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)
<< D.getCXXScopeSpec().getRange();
New->setInvalidDecl();
}
-
+
// Add the parameter declaration into this scope.
S->AddDecl(New);
if (D.getIdentifier())
IdResolver.AddDecl(New);
-
+
ProcessDeclAttributes(S, New, D);
-
+
if (New->hasAttr<BlocksAttr>())
Diag(New->getLocation(), diag::err_block_on_nonlocal);
return New;
@@ -4892,7 +4935,7 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
/// initialization.
void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
- for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;
+ for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;
Iv= Iv->getNextIvar()) {
QualType QT = Context.getBaseElementType(Iv->getType());
if (QT->isRecordType())
@@ -4908,11 +4951,11 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
for (unsigned I = 0, N = Sels.size(); I != N; ++I)
ReferencedSelectors[Sels[I].first] = Sels[I].second;
}
-
+
// Warning will be issued only when selector table is
// generated (which means there is at lease one implementation
// in the TU). This is to match gcc's behavior.
- if (ReferencedSelectors.empty() ||
+ if (ReferencedSelectors.empty() ||
!Context.AnyObjCImplementation())
return;
for (auto &SelectorAndLocation : ReferencedSelectors) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 67d1b02d1fca..134c76ef28c6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -76,6 +76,29 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
.Default(false);
}
+ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc,
+ Expr *NoexceptExpr,
+ ExceptionSpecificationType &EST) {
+ // FIXME: This is bogus, a noexcept expression is not a condition.
+ ExprResult Converted = CheckBooleanCondition(NoexceptLoc, NoexceptExpr);
+ if (Converted.isInvalid())
+ return Converted;
+
+ if (Converted.get()->isValueDependent()) {
+ EST = EST_DependentNoexcept;
+ return Converted;
+ }
+
+ llvm::APSInt Result;
+ Converted = VerifyIntegerConstantExpression(
+ Converted.get(), &Result,
+ diag::err_noexcept_needs_constant_expression,
+ /*AllowFold*/ false);
+ if (!Converted.isInvalid())
+ EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
+ return Converted;
+}
+
/// CheckSpecifiedExceptionType - Check if the given type is valid in an
/// exception specification. Incomplete types, or pointers to incomplete types
/// other than void are not allowed.
@@ -203,8 +226,8 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD,
if (auto *Listener = getASTMutationListener())
Listener->ResolvedExceptionSpec(FD);
- for (auto *Redecl : FD->redecls())
- Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
+ for (FunctionDecl *Redecl : FD->redecls())
+ Context.adjustExceptionSpec(Redecl, ESI);
}
static bool CheckEquivalentExceptionSpecImpl(
@@ -309,13 +332,19 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
if (ESI.Type == EST_Dynamic) {
+ // FIXME: What if the exceptions are described in terms of the old
+ // prototype's parameters?
ESI.Exceptions = OldProto->exceptions();
}
- if (ESI.Type == EST_ComputedNoexcept) {
- // For computed noexcept, we can't just take the expression from the old
- // prototype. It likely contains references to the old prototype's
- // parameters.
+ if (ESI.Type == EST_NoexceptFalse)
+ ESI.Type = EST_None;
+ if (ESI.Type == EST_NoexceptTrue)
+ ESI.Type = EST_BasicNoexcept;
+
+ // For dependent noexcept, we can't just take the expression from the old
+ // prototype. It likely contains references to the old prototype's parameters.
+ if (ESI.Type == EST_DependentNoexcept) {
New->setInvalidDecl();
} else {
// Update the type of the function with the appropriate exception
@@ -325,12 +354,12 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
}
- if (getLangOpts().MicrosoftExt && ESI.Type != EST_ComputedNoexcept) {
+ if (getLangOpts().MicrosoftExt && ESI.Type != EST_DependentNoexcept) {
// Allow missing exception specifications in redeclarations as an extension.
DiagID = diag::ext_ms_missing_exception_specification;
ReturnValueOnError = false;
} else if (New->isReplaceableGlobalAllocationFunction() &&
- ESI.Type != EST_ComputedNoexcept) {
+ ESI.Type != EST_DependentNoexcept) {
// Allow missing exception specifications in redeclarations as an extension,
// when declaring a replaceable global allocation function.
DiagID = diag::ext_missing_exception_specification;
@@ -356,7 +385,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
OnFirstException = false;
else
OS << ", ";
-
+
OS << E.getAsString(getPrintingPolicy());
}
OS << ")";
@@ -367,7 +396,9 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
OS << "noexcept";
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
OS << "noexcept(";
assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr");
OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
@@ -478,63 +509,62 @@ static bool CheckEquivalentExceptionSpecImpl(
!isUnresolvedExceptionSpec(NewEST) &&
"Shouldn't see unknown exception specifications here");
- // Shortcut the case where both have no spec.
- if (OldEST == EST_None && NewEST == EST_None)
- return false;
+ CanThrowResult OldCanThrow = Old->canThrow();
+ CanThrowResult NewCanThrow = New->canThrow();
- FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(S.Context);
- FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(S.Context);
- if (OldNR == FunctionProtoType::NR_BadNoexcept ||
- NewNR == FunctionProtoType::NR_BadNoexcept)
+ // Any non-throwing specifications are compatible.
+ if (OldCanThrow == CT_Cannot && NewCanThrow == CT_Cannot)
return false;
- // Dependent noexcept specifiers are compatible with each other, but nothing
- // else.
- // One noexcept is compatible with another if the argument is the same
- if (OldNR == NewNR &&
- OldNR != FunctionProtoType::NR_NoNoexcept &&
- NewNR != FunctionProtoType::NR_NoNoexcept)
- return false;
- if (OldNR != NewNR &&
- OldNR != FunctionProtoType::NR_NoNoexcept &&
- NewNR != FunctionProtoType::NR_NoNoexcept) {
- S.Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- S.Diag(OldLoc, NoteID);
- return true;
+ // Any throws-anything specifications are usually compatible.
+ if (OldCanThrow == CT_Can && OldEST != EST_Dynamic &&
+ NewCanThrow == CT_Can && NewEST != EST_Dynamic) {
+ // The exception is that the absence of an exception specification only
+ // matches noexcept(false) for functions, as described above.
+ if (!AllowNoexceptAllMatchWithNoSpec &&
+ ((OldEST == EST_None && NewEST == EST_NoexceptFalse) ||
+ (OldEST == EST_NoexceptFalse && NewEST == EST_None))) {
+ // This is the disallowed case.
+ } else {
+ return false;
+ }
}
- // The MS extension throw(...) is compatible with itself.
- if (OldEST == EST_MSAny && NewEST == EST_MSAny)
- return false;
-
- // It's also compatible with no spec.
- if ((OldEST == EST_None && NewEST == EST_MSAny) ||
- (OldEST == EST_MSAny && NewEST == EST_None))
- return false;
+ // C++14 [except.spec]p3:
+ // Two exception-specifications are compatible if [...] both have the form
+ // noexcept(constant-expression) and the constant-expressions are equivalent
+ if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) {
+ llvm::FoldingSetNodeID OldFSN, NewFSN;
+ Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true);
+ New->getNoexceptExpr()->Profile(NewFSN, S.Context, true);
+ if (OldFSN == NewFSN)
+ return false;
+ }
- // It's also compatible with noexcept(false).
- if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw)
- return false;
- if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw)
- return false;
+ // Dynamic exception specifications with the same set of adjusted types
+ // are compatible.
+ if (OldEST == EST_Dynamic && NewEST == EST_Dynamic) {
+ bool Success = true;
+ // Both have a dynamic exception spec. Collect the first set, then compare
+ // to the second.
+ llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
+ for (const auto &I : Old->exceptions())
+ OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
+
+ for (const auto &I : New->exceptions()) {
+ CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
+ if (OldTypes.count(TypePtr))
+ NewTypes.insert(TypePtr);
+ else {
+ Success = false;
+ break;
+ }
+ }
- // As described above, noexcept(false) matches no spec only for functions.
- if (AllowNoexceptAllMatchWithNoSpec) {
- if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw)
- return false;
- if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw)
+ if (Success && OldTypes.size() == NewTypes.size())
return false;
}
- // Any non-throwing specifications are compatible.
- bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow ||
- OldEST == EST_DynamicNone;
- bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow ||
- NewEST == EST_DynamicNone;
- if (OldNonThrowing && NewNonThrowing)
- return false;
-
// As a special compatibility feature, under C++0x we accept no spec and
// throw(std::bad_alloc) as equivalent for operator new and operator new[].
// This is because the implicit declaration changed, but old code would break.
@@ -560,54 +590,24 @@ static bool CheckEquivalentExceptionSpecImpl(
}
}
- // At this point, the only remaining valid case is two matching dynamic
- // specifications. We return here unless both specifications are dynamic.
- if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {
- if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
- !New->hasExceptionSpec()) {
- // The old type has an exception specification of some sort, but
- // the new type does not.
- *MissingExceptionSpecification = true;
-
- if (MissingEmptyExceptionSpecification && OldNonThrowing) {
- // The old type has a throw() or noexcept(true) exception specification
- // and the new type has no exception specification, and the caller asked
- // to handle this itself.
- *MissingEmptyExceptionSpecification = true;
- }
-
- return true;
+ // If the caller wants to handle the case that the new function is
+ // incompatible due to a missing exception specification, let it.
+ if (MissingExceptionSpecification && OldEST != EST_None &&
+ NewEST == EST_None) {
+ // The old type has an exception specification of some sort, but
+ // the new type does not.
+ *MissingExceptionSpecification = true;
+
+ if (MissingEmptyExceptionSpecification && OldCanThrow == CT_Cannot) {
+ // The old type has a throw() or noexcept(true) exception specification
+ // and the new type has no exception specification, and the caller asked
+ // to handle this itself.
+ *MissingEmptyExceptionSpecification = true;
}
- S.Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- S.Diag(OldLoc, NoteID);
return true;
}
- assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic &&
- "Exception compatibility logic error: non-dynamic spec slipped through.");
-
- bool Success = true;
- // Both have a dynamic exception spec. Collect the first set, then compare
- // to the second.
- llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
- for (const auto &I : Old->exceptions())
- OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
-
- for (const auto &I : New->exceptions()) {
- CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
- if (OldTypes.count(TypePtr))
- NewTypes.insert(TypePtr);
- else
- Success = false;
- }
-
- Success = Success && OldTypes.size() == NewTypes.size();
-
- if (Success) {
- return false;
- }
S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
S.Diag(OldLoc, NoteID);
@@ -626,6 +626,90 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
New, NewLoc);
}
+bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
+ // [except.handle]p3:
+ // A handler is a match for an exception object of type E if:
+
+ // HandlerType must be ExceptionType or derived from it, or pointer or
+ // reference to such types.
+ const ReferenceType *RefTy = HandlerType->getAs<ReferenceType>();
+ if (RefTy)
+ HandlerType = RefTy->getPointeeType();
+
+ // -- the handler is of type cv T or cv T& and E and T are the same type
+ if (Context.hasSameUnqualifiedType(ExceptionType, HandlerType))
+ return true;
+
+ // FIXME: ObjC pointer types?
+ if (HandlerType->isPointerType() || HandlerType->isMemberPointerType()) {
+ if (RefTy && (!HandlerType.isConstQualified() ||
+ HandlerType.isVolatileQualified()))
+ return false;
+
+ // -- the handler is of type cv T or const T& where T is a pointer or
+ // pointer to member type and E is std::nullptr_t
+ if (ExceptionType->isNullPtrType())
+ return true;
+
+ // -- the handler is of type cv T or const T& where T is a pointer or
+ // pointer to member type and E is a pointer or pointer to member type
+ // that can be converted to T by one or more of
+ // -- a qualification conversion
+ // -- a function pointer conversion
+ bool LifetimeConv;
+ QualType Result;
+ // FIXME: Should we treat the exception as catchable if a lifetime
+ // conversion is required?
+ if (IsQualificationConversion(ExceptionType, HandlerType, false,
+ LifetimeConv) ||
+ IsFunctionConversion(ExceptionType, HandlerType, Result))
+ return true;
+
+ // -- a standard pointer conversion [...]
+ if (!ExceptionType->isPointerType() || !HandlerType->isPointerType())
+ return false;
+
+ // Handle the "qualification conversion" portion.
+ Qualifiers EQuals, HQuals;
+ ExceptionType = Context.getUnqualifiedArrayType(
+ ExceptionType->getPointeeType(), EQuals);
+ HandlerType = Context.getUnqualifiedArrayType(
+ HandlerType->getPointeeType(), HQuals);
+ if (!HQuals.compatiblyIncludes(EQuals))
+ return false;
+
+ if (HandlerType->isVoidType() && ExceptionType->isObjectType())
+ return true;
+
+ // The only remaining case is a derived-to-base conversion.
+ }
+
+ // -- the handler is of type cg T or cv T& and T is an unambiguous public
+ // base class of E
+ if (!ExceptionType->isRecordType() || !HandlerType->isRecordType())
+ return false;
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (!IsDerivedFrom(SourceLocation(), ExceptionType, HandlerType, Paths) ||
+ Paths.isAmbiguous(Context.getCanonicalType(HandlerType)))
+ return false;
+
+ // Do this check from a context without privileges.
+ switch (CheckBaseClassAccess(SourceLocation(), HandlerType, ExceptionType,
+ Paths.front(),
+ /*Diagnostic*/ 0,
+ /*ForceCheck*/ true,
+ /*ForceUnprivileged*/ true)) {
+ case AR_accessible: return true;
+ case AR_inaccessible: return false;
+ case AR_dependent:
+ llvm_unreachable("access check dependent for unprivileged context");
+ case AR_delayed:
+ llvm_unreachable("access check delayed in non-declaration");
+ }
+ llvm_unreachable("unexpected access check result");
+}
+
/// CheckExceptionSpecSubset - Check whether the second function type's
/// exception specification is a subset (or equivalent) of the first function
/// type. This is used by override and pointer assignment checks.
@@ -656,62 +740,32 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
return false;
ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
-
- // If superset contains everything, we're done.
- if (SuperEST == EST_None || SuperEST == EST_MSAny)
- return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
- Subset, SubLoc);
-
- // If there are dependent noexcept specs, assume everything is fine. Unlike
- // with the equivalency check, this is safe in this case, because we don't
- // want to merge declarations. Checks after instantiation will catch any
- // omissions we make here.
- // We also shortcut checking if a noexcept expression was bad.
-
- FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context);
- if (SuperNR == FunctionProtoType::NR_BadNoexcept ||
- SuperNR == FunctionProtoType::NR_Dependent)
- return false;
-
- // Another case of the superset containing everything.
- if (SuperNR == FunctionProtoType::NR_Throw)
- return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
- Subset, SubLoc);
-
ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
-
assert(!isUnresolvedExceptionSpec(SuperEST) &&
!isUnresolvedExceptionSpec(SubEST) &&
"Shouldn't see unknown exception specifications here");
- // It does not. If the subset contains everything, we've failed.
- if (SubEST == EST_None || SubEST == EST_MSAny) {
- Diag(SubLoc, DiagID);
- if (NoteID.getDiagID() != 0)
- Diag(SuperLoc, NoteID);
- return true;
- }
-
- FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context);
- if (SubNR == FunctionProtoType::NR_BadNoexcept ||
- SubNR == FunctionProtoType::NR_Dependent)
+ // If there are dependent noexcept specs, assume everything is fine. Unlike
+ // with the equivalency check, this is safe in this case, because we don't
+ // want to merge declarations. Checks after instantiation will catch any
+ // omissions we make here.
+ if (SuperEST == EST_DependentNoexcept || SubEST == EST_DependentNoexcept)
return false;
- // Another case of the subset containing everything.
- if (SubNR == FunctionProtoType::NR_Throw) {
- Diag(SubLoc, DiagID);
- if (NoteID.getDiagID() != 0)
- Diag(SuperLoc, NoteID);
- return true;
- }
+ CanThrowResult SuperCanThrow = Superset->canThrow();
+ CanThrowResult SubCanThrow = Subset->canThrow();
- // If the subset contains nothing, we're done.
- if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow)
+ // If the superset contains everything or the subset contains nothing, we're
+ // done.
+ if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) ||
+ SubCanThrow == CT_Cannot)
return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
Subset, SubLoc);
- // Otherwise, if the superset contains nothing, we've failed.
- if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) {
+ // If the subset contains everything or the superset contains nothing, we've
+ // failed.
+ if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) ||
+ SuperCanThrow == CT_Cannot) {
Diag(SubLoc, DiagID);
if (NoteID.getDiagID() != 0)
Diag(SuperLoc, NoteID);
@@ -722,75 +776,23 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
"Exception spec subset: non-dynamic case slipped through.");
// Neither contains everything or nothing. Do a proper comparison.
- for (const auto &SubI : Subset->exceptions()) {
- // Take one type from the subset.
- QualType CanonicalSubT = Context.getCanonicalType(SubI);
- // Unwrap pointers and references so that we can do checks within a class
- // hierarchy. Don't unwrap member pointers; they don't have hierarchy
- // conversions on the pointee.
- bool SubIsPointer = false;
- if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
- CanonicalSubT = RefTy->getPointeeType();
- if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
- CanonicalSubT = PtrTy->getPointeeType();
- SubIsPointer = true;
- }
- bool SubIsClass = CanonicalSubT->isRecordType();
- CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
+ for (QualType SubI : Subset->exceptions()) {
+ if (const ReferenceType *RefTy = SubI->getAs<ReferenceType>())
+ SubI = RefTy->getPointeeType();
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
-
- bool Contained = false;
// Make sure it's in the superset.
- for (const auto &SuperI : Superset->exceptions()) {
- QualType CanonicalSuperT = Context.getCanonicalType(SuperI);
- // SubT must be SuperT or derived from it, or pointer or reference to
- // such types.
- if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
- CanonicalSuperT = RefTy->getPointeeType();
- if (SubIsPointer) {
- if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
- CanonicalSuperT = PtrTy->getPointeeType();
- else {
- continue;
- }
- }
- CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
- // If the types are the same, move on to the next type in the subset.
- if (CanonicalSubT == CanonicalSuperT) {
+ bool Contained = false;
+ for (QualType SuperI : Superset->exceptions()) {
+ // [except.spec]p5:
+ // the target entity shall allow at least the exceptions allowed by the
+ // source
+ //
+ // We interpret this as meaning that a handler for some target type would
+ // catch an exception of each source type.
+ if (handlerCanCatch(SuperI, SubI)) {
Contained = true;
break;
}
-
- // Otherwise we need to check the inheritance.
- if (!SubIsClass || !CanonicalSuperT->isRecordType())
- continue;
-
- Paths.clear();
- if (!IsDerivedFrom(SubLoc, CanonicalSubT, CanonicalSuperT, Paths))
- continue;
-
- if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
- continue;
-
- // Do this check from a context without privileges.
- switch (CheckBaseClassAccess(SourceLocation(),
- CanonicalSuperT, CanonicalSubT,
- Paths.front(),
- /*Diagnostic*/ 0,
- /*ForceCheck*/ true,
- /*ForceUnprivileged*/ true)) {
- case AR_accessible: break;
- case AR_inaccessible: continue;
- case AR_dependent:
- llvm_unreachable("access check dependent for unprivileged context");
- case AR_delayed:
- llvm_unreachable("access check delayed in non-declaration");
- }
-
- Contained = true;
- break;
}
if (!Contained) {
Diag(SubLoc, DiagID);
@@ -994,7 +996,7 @@ static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
if (!FT)
return CT_Can;
- return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
+ return FT->canThrow();
}
static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
@@ -1262,6 +1264,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ImaginaryLiteralClass:
case Expr::ImplicitValueInitExprClass:
case Expr::IntegerLiteralClass:
+ case Expr::FixedPointLiteralClass:
case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ObjCEncodeExprClass:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index a6e43765e106..3dc6fb151cb7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -37,6 +37,7 @@
#include "clang/Sema/Designator.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
@@ -47,7 +48,7 @@
using namespace clang;
using namespace sema;
-/// \brief Determine whether the use of this declaration is valid, without
+/// Determine whether the use of this declaration is valid, without
/// emitting diagnostics.
bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) {
// See if this is an auto-typed variable whose initializer we are parsing.
@@ -88,7 +89,7 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
}
}
-/// \brief Emit a note explaining that this function is deleted.
+/// Emit a note explaining that this function is deleted.
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
assert(Decl->isDeleted());
@@ -116,7 +117,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
<< Decl << true;
}
-/// \brief Determine whether a FunctionDecl was ever declared with an
+/// Determine whether a FunctionDecl was ever declared with an
/// explicit storage class.
static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
for (auto I : D->redecls()) {
@@ -126,7 +127,7 @@ static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
return false;
}
-/// \brief Check whether we're in an extern inline function and referring to a
+/// Check whether we're in an extern inline function and referring to a
/// variable or function with internal linkage (C11 6.7.4p3).
///
/// This is only a warning because we used to silently accept this code, but
@@ -189,7 +190,7 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
}
}
-/// \brief Determine whether the use of this declaration is valid, and
+/// Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
///
/// This routine diagnoses various problems with referencing
@@ -201,10 +202,11 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
-bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks) {
+ SourceLocation Loc = Locs.front();
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
@@ -246,7 +248,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
Diag(Loc, diag::err_deleted_inherited_ctor_use)
<< Ctor->getParent()
<< Ctor->getInheritedConstructor().getConstructor()->getParent();
- else
+ else
Diag(Loc, diag::err_deleted_function_use);
NoteDeletedFunction(FD);
return true;
@@ -288,7 +290,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return true;
}
- DiagnoseAvailabilityOfDecl(D, Loc, UnknownObjCClass, ObjCPropertyAccess,
+ DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
AvoidPartialAvailabilityChecks);
DiagnoseUnusedOfDecl(*this, D, Loc);
@@ -298,7 +300,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return false;
}
-/// \brief Retrieve the message suffix that should be added to a
+/// Retrieve the message suffix that should be added to a
/// diagnostic complaining about the given function being deleted or
/// unavailable.
std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
@@ -399,7 +401,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
if (MissingNilLoc.isInvalid())
Diag(Loc, diag::warn_missing_sentinel) << int(calleeType);
else
- Diag(MissingNilLoc, diag::warn_missing_sentinel)
+ Diag(MissingNilLoc, diag::warn_missing_sentinel)
<< int(calleeType)
<< FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue);
Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
@@ -421,7 +423,7 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
if (result.isInvalid()) return ExprError();
E = result.get();
}
-
+
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
@@ -477,12 +479,12 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
const ObjCIvarDecl *IV = OIRE->getDecl();
if (!IV)
return;
-
+
DeclarationName MemberName = IV->getDeclName();
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
if (!Member || !Member->isStr("isa"))
return;
-
+
const Expr *Base = OIRE->getBase();
QualType BaseType = Base->getType();
if (OIRE->isArrow())
@@ -534,7 +536,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (result.isInvalid()) return ExprError();
E = result.get();
}
-
+
// C++ [conv.lval]p1:
// A glvalue of a non-function, non-array type T can be
// converted to a prvalue.
@@ -602,8 +604,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
(void)isCompleteType(E->getExprLoc(), T);
UpdateMarkingForLValueToRValue(E);
-
- // Loading a __weak object implicitly retains the value, so we need a cleanup to
+
+ // Loading a __weak object implicitly retains the value, so we need a cleanup to
// balance that.
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
@@ -612,14 +614,14 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
nullptr, VK_RValue);
// C11 6.3.2.1p2:
- // ... if the lvalue has atomic type, the value has the non-atomic version
+ // ... if the lvalue has atomic type, the value has the non-atomic version
// of the type of the lvalue ...
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(),
nullptr, VK_RValue);
}
-
+
return Res;
}
@@ -776,6 +778,9 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
return VAK_Valid;
}
+ if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
+ return VAK_Invalid;
+
if (Ty.isCXX98PODType(Context))
return VAK_Valid;
@@ -837,7 +842,10 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
break;
case VAK_Invalid:
- if (Ty->isObjCObjectType())
+ if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
+ Diag(E->getLocStart(),
+ diag::err_cannot_pass_non_trivial_c_struct_to_vararg) << Ty << CT;
+ else if (Ty->isObjCObjectType())
DiagRuntimeBehavior(
E->getLocStart(), nullptr,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
@@ -868,7 +876,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
E = ExprRes.get();
}
}
-
+
ExprResult ExprRes = DefaultArgumentPromotion(E);
if (ExprRes.isInvalid())
return ExprError();
@@ -909,7 +917,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
return E;
}
-/// \brief Converts an integer to complex float type. Helper function of
+/// Converts an integer to complex float type. Helper function of
/// UsualArithmeticConversions()
///
/// \return false if the integer expression is an integer type and is
@@ -934,7 +942,7 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
return false;
}
-/// \brief Handle arithmetic conversion with complex types. Helper function of
+/// Handle arithmetic conversion with complex types. Helper function of
/// UsualArithmeticConversions()
static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
@@ -990,7 +998,7 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
return ResultType;
}
-/// \brief Handle arithmetic conversion from integer to float. Helper function
+/// Handle arithmetic conversion from integer to float. Helper function
/// of UsualArithmeticConversions()
static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
ExprResult &IntExpr,
@@ -1003,7 +1011,7 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
CK_IntegralToFloating);
return FloatTy;
}
-
+
// Convert both sides to the appropriate complex float.
assert(IntTy->isComplexIntegerType());
QualType result = S.Context.getComplexType(FloatTy);
@@ -1021,7 +1029,7 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
return result;
}
-/// \brief Handle arithmethic conversion with floating point types. Helper
+/// Handle arithmethic conversion with floating point types. Helper
/// function of UsualArithmeticConversions()
static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
@@ -1059,7 +1067,7 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
/*convertFloat=*/!IsCompAssign);
}
-/// \brief Diagnose attempts to convert between __float128 and long double if
+/// Diagnose attempts to convert between __float128 and long double if
/// there is no support for such conversion. Helper function of
/// UsualArithmeticConversions().
static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
@@ -1092,13 +1100,12 @@ static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy &&
RHSElemType == S.Context.Float128Ty);
- /* We've handled the situation where __float128 and long double have the same
- representation. The only other allowable conversion is if long double is
- really just double.
- */
+ // We've handled the situation where __float128 and long double have the same
+ // representation. We allow all conversions for all possible long double types
+ // except PPC's double double.
return Float128AndLongDouble &&
- (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble());
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
+ &llvm::APFloat::PPCDoubleDouble());
}
typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
@@ -1116,7 +1123,7 @@ ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) {
}
}
-/// \brief Handle integer arithmetic conversions. Helper function of
+/// Handle integer arithmetic conversions. Helper function of
/// UsualArithmeticConversions()
template <PerformCastFn doLHSCast, PerformCastFn doRHSCast>
static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
@@ -1167,7 +1174,7 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
}
}
-/// \brief Handle conversions with GCC complex int extension. Helper function
+/// Handle conversions with GCC complex int extension. Helper function
/// of UsualArithmeticConversions()
static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
@@ -1194,7 +1201,7 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
QualType ComplexType = S.Context.getComplexType(ScalarType);
RHS = S.ImpCastExprToType(RHS.get(), ComplexType,
CK_IntegralRealToComplex);
-
+
return ComplexType;
}
@@ -1205,7 +1212,7 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
handleIntegerConversion<doIntegralCast, doComplexIntegralCast>
(S, LHS, RHS, LHSType, RHSEltType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
-
+
if (!IsCompAssign)
LHS = S.ImpCastExprToType(LHS.get(), ComplexType,
CK_IntegralRealToComplex);
@@ -1529,6 +1536,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
CharTy = Context.getWideCharType();
Kind = StringLiteral::Wide;
} else if (Literal.isUTF8()) {
+ if (getLangOpts().Char8)
+ CharTy = Context.Char8Ty;
Kind = StringLiteral::UTF8;
} else if (Literal.isUTF16()) {
CharTy = Context.Char16Ty;
@@ -1545,17 +1554,14 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
CharTyConst.addConst();
+ CharTyConst = Context.adjustStringLiteralBaseType(CharTyConst);
+
// Get an array type for the string, according to C99 6.4.5. This includes
// the nul terminator character as well as the string length for pascal
// strings.
- QualType StrTy = Context.getConstantArrayType(CharTyConst,
- llvm::APInt(32, Literal.GetNumStringChars()+1),
- ArrayType::Normal, 0);
-
- // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
- if (getLangOpts().OpenCL) {
- StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant);
- }
+ QualType StrTy = Context.getConstantArrayType(
+ CharTyConst, llvm::APInt(32, Literal.GetNumStringChars() + 1),
+ ArrayType::Normal, 0);
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
@@ -1674,9 +1680,9 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
- Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
+ Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
- recordUseOfEvaluatedWeak(E);
+ getCurFunction()->recordUseOfWeak(E);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D))
@@ -2074,16 +2080,17 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
(Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
? LookupObjCImplicitSelfParam
: LookupOrdinaryName);
- if (TemplateArgs) {
+ if (TemplateKWLoc.isValid() || TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
// lookup to determine that it was a template name in the first place. If
// this becomes a performance hit, we can work harder to preserve those
// results until we get here but it's likely not worth it.
bool MemberOfUnknownSpecialization;
- LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
- MemberOfUnknownSpecialization);
-
+ if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
+ MemberOfUnknownSpecialization, TemplateKWLoc))
+ return ExprError();
+
if (MemberOfUnknownSpecialization ||
(R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
@@ -2092,7 +2099,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
- // If the result might be in a dependent base class, this is a dependent
+ // If the result might be in a dependent base class, this is a dependent
// id-expression.
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
@@ -2149,6 +2156,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (SS.isValid())
CCC->setTypoNNS(SS.getScopeRep());
}
+ // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
+ // a template name, but we happen to have always already looked up the name
+ // before we get here if it must be a template name.
if (DiagnoseEmptyLookup(S, SS, R,
CCC ? std::move(CCC) : std::move(DefaultValidator),
nullptr, None, &TE)) {
@@ -2347,7 +2357,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
ObjCMethodDecl *CurMethod = getCurMethodDecl();
-
+
// Check for error condition which is already reported.
if (!CurMethod)
return ExprError();
@@ -2426,15 +2436,16 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IV->getLocation(), SelfExpr.get(), true, true);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
- recordUseOfEvaluatedWeak(Result);
+ if (!isUnevaluatedContext() &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
+ getCurFunction()->recordUseOfWeak(Result);
}
if (getLangOpts().ObjCAutoRefCount) {
if (CurContext->isClosure())
Diag(Loc, diag::warn_implicitly_retains_self)
<< FixItHint::CreateInsertion(Loc, "self->");
}
-
+
return Result;
}
} else if (CurMethod->isInstanceMethod()) {
@@ -2471,7 +2482,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
return ExprResult((Expr *)nullptr);
}
-/// \brief Cast a base object to a member's actual type.
+/// Cast a base object to a member's actual type.
///
/// Logically this happens in three phases:
///
@@ -2717,12 +2728,23 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
return false;
}
+// Certain multiversion types should be treated as overloaded even when there is
+// only one result.
+static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) {
+ assert(R.isSingleResult() && "Expected only a single result");
+ const auto *FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
+ return FD &&
+ (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion());
+}
+
ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
LookupResult &R, bool NeedsADL,
bool AcceptInvalidDecl) {
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
- if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
+ if (!NeedsADL && R.isSingleResult() &&
+ !R.getAsSingle<FunctionTemplateDecl>() &&
+ !ShouldLookupResultBeMultiVersionOverload(R))
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
R.getRepresentativeDecl(), nullptr,
AcceptInvalidDecl);
@@ -2730,7 +2752,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// We only need to check the declaration if there's exactly one
// result, because in the overloaded case the results can only be
// functions and function templates.
- if (R.isSingleResult() &&
+ if (R.isSingleResult() && !ShouldLookupResultBeMultiVersionOverload(R) &&
CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
return ExprError();
@@ -2753,7 +2775,7 @@ static void
diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
ValueDecl *var, DeclContext *DC);
-/// \brief Complete semantic analysis for a reference to the given declaration.
+/// Complete semantic analysis for a reference to the given declaration.
ExprResult Sema::BuildDeclarationNameExpr(
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
@@ -2769,9 +2791,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
- Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0)
- << Template << SS.getRange();
- Diag(Template->getLocation(), diag::note_template_decl_here);
+ diagnoseMissingTemplateArguments(TemplateName(Template), Loc);
return ExprError();
}
@@ -2898,7 +2918,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
if (!CapturedType.isNull())
type = CapturedType;
}
-
+
break;
}
@@ -2914,7 +2934,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
diagnoseUncapturableValueReference(*this, Loc, BD, CurContext);
break;
}
-
+
case Decl::Function: {
if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
@@ -2939,7 +2959,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
valueKind = VK_LValue;
break;
}
-
+
// C99 DR 316 says that, if a function type comes from a
// function definition (without a prototype), that type is only
// used for checking compatibility. Therefore, when referencing
@@ -3034,8 +3054,9 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
unsigned Length = Str.length();
llvm::APInt LengthI(32, Length + 1);
- if (IT == PredefinedExpr::LFunction) {
- ResTy = Context.WideCharTy.withConst();
+ if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) {
+ ResTy =
+ Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst());
SmallString<32> RawChars;
ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
Str, RawChars);
@@ -3044,7 +3065,7 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
/*Pascal*/ false, ResTy, Loc);
} else {
- ResTy = Context.CharTy.withConst();
+ ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
/*IndexTypeQuals*/ 0);
SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
@@ -3064,7 +3085,8 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS]
- case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
+ case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; // [MS]
+ case tok::kw_L__FUNCSIG__: IT = PredefinedExpr::LFuncSig; break; // [MS]
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
}
@@ -3086,6 +3108,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
QualType Ty;
if (Literal.isWide())
Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++.
+ else if (Literal.isUTF8() && getLangOpts().Char8)
+ Ty = Context.Char8Ty; // u8'x' -> char8_t when it exists.
else if (Literal.isUTF16())
Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
else if (Literal.isUTF32())
@@ -3281,8 +3305,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// operator "" X ("n")
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
- Context.CharTy.withConst(), llvm::APInt(32, Length + 1),
- ArrayType::Normal, 0);
+ Context.adjustStringLiteralBaseType(Context.CharTy.withConst()),
+ llvm::APInt(32, Length + 1), ArrayType::Normal, 0);
Expr *Lit = StringLiteral::Create(
Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii,
/*Pascal*/false, StrTy, &TokLoc, 1);
@@ -3314,7 +3338,52 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Expr *Res;
- if (Literal.isFloatingLiteral()) {
+ if (Literal.isFixedPointLiteral()) {
+ QualType Ty;
+
+ if (Literal.isAccum) {
+ if (Literal.isHalf) {
+ Ty = Context.ShortAccumTy;
+ } else if (Literal.isLong) {
+ Ty = Context.LongAccumTy;
+ } else {
+ Ty = Context.AccumTy;
+ }
+ } else if (Literal.isFract) {
+ if (Literal.isHalf) {
+ Ty = Context.ShortFractTy;
+ } else if (Literal.isLong) {
+ Ty = Context.LongFractTy;
+ } else {
+ Ty = Context.FractTy;
+ }
+ }
+
+ if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty);
+
+ bool isSigned = !Literal.isUnsigned;
+ unsigned scale = Context.getFixedPointScale(Ty);
+ unsigned ibits = Context.getFixedPointIBits(Ty);
+ unsigned bit_width = Context.getTypeInfo(Ty).Width;
+
+ llvm::APInt Val(bit_width, 0, isSigned);
+ bool Overflowed = Literal.GetFixedPointValue(Val, scale);
+
+ // Do not use bit_width since some types may have padding like _Fract or
+ // unsigned _Accums if PaddingOnUnsignedFixedPoint is set.
+ auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width);
+ if (Literal.isFract && Val == MaxVal + 1)
+ // Clause 6.4.4 - The value of a constant shall be in the range of
+ // representable values for its type, with exception for constants of a
+ // fract type with a value of exactly 1; such a constant shall denote
+ // the maximal value for the type.
+ --Val;
+ else if (Val.ugt(MaxVal) || Overflowed)
+ Diag(Tok.getLocation(), diag::err_too_large_for_fixed_point);
+
+ Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty,
+ Tok.getLocation(), scale);
+ } else if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
@@ -3554,7 +3623,7 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T,
return false;
}
-/// \brief Check whether E is a pointer from a decayed array type (the decayed
+/// Check whether E is a pointer from a decayed array type (the decayed
/// pointer type is equal to T) and emit a warning if it is.
static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
Expr *E) {
@@ -3572,7 +3641,7 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
<< ICE->getSubExpr()->getType();
}
-/// \brief Check the constraints on expression operands to unary type expression
+/// Check the constraints on expression operands to unary type expression
/// and type traits.
///
/// Completes any types necessary and validates the constraints on the operand
@@ -3656,7 +3725,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
return false;
}
-/// \brief Check the constraints on operands to unary expression and type
+/// Check the constraints on operands to unary expression and type
/// traits.
///
/// This will complete any types necessary, and validate the various constraints
@@ -3910,7 +3979,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
} while (!T.isNull() && T->isVariablyModifiedType());
}
-/// \brief Build a sizeof or alignof expression given a type operand.
+/// Build a sizeof or alignof expression given a type operand.
ExprResult
Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
@@ -3954,17 +4023,17 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
}
-/// \brief Build a sizeof or alignof expression given an expression
+/// Build a sizeof or alignof expression given an expression
/// operand.
ExprResult
Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind) {
ExprResult PE = CheckPlaceholderExpr(E);
- if (PE.isInvalid())
+ if (PE.isInvalid())
return ExprError();
E = PE.get();
-
+
// Verify that the operand is valid.
bool isInvalid = false;
if (E->isTypeDependent()) {
@@ -4072,7 +4141,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
-/// \brief Diagnose if arithmetic on the given ObjC pointer is illegal.
+/// Diagnose if arithmetic on the given ObjC pointer is illegal.
///
/// \return true on error
static bool checkArithmeticOnObjCPointer(Sema &S,
@@ -4328,10 +4397,13 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// Per C++ core issue 1213, the result is an xvalue if either operand is
// a non-lvalue array, and an lvalue otherwise.
- if (getLangOpts().CPlusPlus11 &&
- ((LHSExp->getType()->isArrayType() && !LHSExp->isLValue()) ||
- (RHSExp->getType()->isArrayType() && !RHSExp->isLValue())))
- VK = VK_XValue;
+ if (getLangOpts().CPlusPlus11) {
+ for (auto *Op : {LHSExp, RHSExp}) {
+ Op = Op->IgnoreImplicit();
+ if (Op->getType()->isArrayType() && !Op->isLValue())
+ VK = VK_XValue;
+ }
+ }
// Perform default conversions.
if (!LHSExp->getType()->getAs<VectorType>()) {
@@ -4392,12 +4464,24 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
} else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
+ // We apply C++ DR1213 to vector subscripting too.
+ if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) {
+ ExprResult Materialized = TemporaryMaterializationConversion(LHSExp);
+ if (Materialized.isInvalid())
+ return ExprError();
+ LHSExp = Materialized.get();
+ }
VK = LHSExp->getValueKind();
if (VK != VK_RValue)
OK = OK_VectorComponent;
- // FIXME: need to deal with const...
ResultType = VTy->getElementType();
+ QualType BaseType = BaseExpr->getType();
+ Qualifiers BaseQuals = BaseType.getQualifiers();
+ Qualifiers MemberQuals = ResultType.getQualifiers();
+ Qualifiers Combined = BaseQuals + MemberQuals;
+ if (Combined != MemberQuals)
+ ResultType = Context.getQualifiedType(ResultType, Combined);
} else if (LHSTy->isArrayType()) {
// If we see an array that wasn't promoted by
// DefaultFunctionArrayLvalueConversion, it must be an array that
@@ -4478,7 +4562,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
diag::note_default_argument_declared_here);
return true;
}
-
+
if (Param->hasUninstantiatedDefaultArg()) {
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
@@ -4580,7 +4664,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
"default argument expression has capturing blocks?");
}
- // We already type-checked the argument, so we know it works.
+ // We already type-checked the argument, so we know it works.
// Just mark all of the declarations in this potentially-evaluated expression
// as being "referenced".
MarkDeclarationsReferencedInExpr(Param->getDefaultArg(),
@@ -4777,7 +4861,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;
-
+
// This deletes the extra arguments.
Call->setNumArgs(Context, NumParams);
return true;
@@ -4785,7 +4869,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
}
SmallVector<Expr *, 8> AllArgs;
VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
-
+
Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
Proto, 0, Args, AllArgs, CallType);
if (Invalid)
@@ -4831,6 +4915,10 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
+ if (Proto->getExtParameterInfo(i).isNoEscape())
+ if (auto *BE = dyn_cast<BlockExpr>(Arg->IgnoreParenNoopCasts(Context)))
+ BE->getBlockDecl()->setDoesNotEscape();
+
InitializedEntity Entity =
Param ? InitializedEntity::InitializeParameter(Context, Param,
ProtoArgType)
@@ -5187,11 +5275,11 @@ tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
// 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.
@@ -5496,7 +5584,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// CUDA: Kernel calls must be to global functions
if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
- << FDecl->getName() << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
if (!FuncT->getReturnType()->isVoidType())
@@ -5506,7 +5594,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// CUDA: Calls to global functions must be configured
if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc, diag::err_global_call_not_config)
- << FDecl->getName() << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
}
}
@@ -5537,7 +5625,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
<< (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange();
}
-
+
// If the function we're calling isn't a function prototype, but we have
// a function prototype from a prior declaratiom, use that prototype.
if (!FDecl->hasPrototype())
@@ -5555,7 +5643,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
PerformCopyInitialization(Entity, SourceLocation(), Arg);
if (ArgE.isInvalid())
return true;
-
+
Arg = ArgE.getAs<Expr>();
} else {
@@ -5566,7 +5654,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
Arg = ArgE.getAs<Expr>();
}
-
+
if (RequireCompleteType(Arg->getLocStart(),
Arg->getType(),
diag::err_call_incomplete_argument, Arg))
@@ -5640,7 +5728,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
InitializedEntity Entity
= InitializedEntity::InitializeCompoundLiteralInit(TInfo);
InitializationKind Kind
- = InitializationKind::CreateCStyleCast(LParenLoc,
+ = InitializationKind::CreateCStyleCast(LParenLoc,
SourceRange(LParenLoc, RParenLoc),
/*InitList=*/true);
InitializationSequence InitSeq(*this, Entity, Kind, LiteralExpr);
@@ -5705,7 +5793,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
}
// Semantic analysis for initializers is done by ActOnDeclarator() and
- // CheckInitializer() - it requires knowledge of the object being intialized.
+ // CheckInitializer() - it requires knowledge of the object being initialized.
InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList,
RBraceLoc);
@@ -5919,11 +6007,11 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
assert(eltType->isScalarType());
return true;
}
-
+
// We allow lax conversion to and from non-vector types, but only if
// they're real types (i.e. non-complex, non-pointer scalar types).
if (!type->isRealType()) return false;
-
+
len = 1;
eltType = type;
return true;
@@ -5938,7 +6026,7 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
/// vector nor a real type.
bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
-
+
// Disallow lax conversions between scalars and ExtVectors (these
// conversions are allowed for other vector types because common headers
// depend on them). Most scalar OP ExtVector cases are handled by the
@@ -5951,13 +6039,13 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
QualType srcEltTy, destEltTy;
if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
+
// ASTContext::getTypeSize will return the size rounded up to a
// power of 2, so instead of using that, we need to use the raw
// element size multiplied by the element count.
uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
+
return (srcLen * srcEltSize == destLen * destEltSize);
}
@@ -5965,7 +6053,7 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
/// known to be a vector type?
bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
-
+
if (!Context.getLangOpts().LaxVectorConversions)
return false;
return areLaxCompatibleVectorTypes(srcTy, destTy);
@@ -6123,9 +6211,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
if (getLangOpts().CPlusPlus && !castType->isVoidType() &&
!getSourceManager().isInSystemMacro(LParenLoc))
Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange();
-
+
CheckTollFreeBridgeCast(castType, CastExpr);
-
+
CheckObjCBridgeRelatedCast(castType, CastExpr);
DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr);
@@ -6162,7 +6250,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
SmallVector<Expr *, 8> initExprs;
const VectorType *VTy = Ty->getAs<VectorType>();
unsigned numElems = Ty->getAs<VectorType>()->getNumElements();
-
+
// '(...)' form of vector initialization in AltiVec: the number of
// initializers must be one or must match the size of the vector.
// If a single value is specified in the initializer then it will be
@@ -6202,7 +6290,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
PrepareScalarCast(Literal, ElemTy));
return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get());
}
-
+
initExprs.append(exprs, exprs + numExprs);
}
// FIXME: This means that pretty-printing the final AST will produce curly
@@ -6239,7 +6327,7 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L,
return expr;
}
-/// \brief Emit a specialized diagnostic when one expression is a null pointer
+/// Emit a specialized diagnostic when one expression is a null pointer
/// constant and the other is not a pointer. Returns true if a diagnostic is
/// emitted.
bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
@@ -6280,7 +6368,7 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
return true;
}
-/// \brief Return false if the condition expression is valid, true otherwise.
+/// Return false if the condition expression is valid, true otherwise.
static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) {
QualType CondTy = Cond->getType();
@@ -6299,7 +6387,7 @@ static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) {
return true;
}
-/// \brief Handle when one or both operands are void type.
+/// Handle when one or both operands are void type.
static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
ExprResult &RHS) {
Expr *LHSExpr = LHS.get();
@@ -6316,7 +6404,7 @@ static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
return S.Context.VoidTy;
}
-/// \brief Return false if the NullExpr can be promoted to PointerTy,
+/// Return false if the NullExpr can be promoted to PointerTy,
/// true otherwise.
static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
QualType PointerTy) {
@@ -6329,7 +6417,7 @@ static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
return false;
}
-/// \brief Checks compatibility between two pointers and return the resulting
+/// Checks compatibility between two pointers and return the resulting
/// type.
static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
ExprResult &RHS,
@@ -6463,7 +6551,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
return ResultTy;
}
-/// \brief Return the resulting type when the operands are both block pointers.
+/// Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
ExprResult &RHS,
@@ -6488,7 +6576,7 @@ static QualType checkConditionalBlockPointerCompatibility(Sema &S,
return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
}
-/// \brief Return the resulting type when the operands are both pointers.
+/// Return the resulting type when the operands are both pointers.
static QualType
checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
ExprResult &RHS,
@@ -6527,7 +6615,7 @@ checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
}
-/// \brief Return false if the first expression is not an integer and the second
+/// Return false if the first expression is not an integer and the second
/// expression is not a pointer, true otherwise.
static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
Expr* PointerExpr, SourceLocation Loc,
@@ -6547,7 +6635,7 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
return true;
}
-/// \brief Simple conversion between integer and floating point types.
+/// Simple conversion between integer and floating point types.
///
/// Used when handling the OpenCL conditional operator where the
/// condition is a vector while the other operands are scalar.
@@ -6602,7 +6690,7 @@ static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
(S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false);
}
-/// \brief Convert scalar operands to a vector that matches the
+/// Convert scalar operands to a vector that matches the
/// condition in length.
///
/// Used when handling the OpenCL conditional operator where the
@@ -6647,7 +6735,7 @@ OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS,
return VectorTy;
}
-/// \brief Return false if this is a valid OpenCL condition vector
+/// Return false if this is a valid OpenCL condition vector
static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
SourceLocation QuestionLoc) {
// OpenCL v1.1 s6.11.6 says the elements of the vector must be of
@@ -6662,7 +6750,7 @@ static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
return true;
}
-/// \brief Return false if the vector condition type and the vector
+/// Return false if the vector condition type and the vector
/// result type are compatible.
///
/// OpenCL v1.1 s6.11.6 requires that both vector types have the same
@@ -6692,14 +6780,14 @@ static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy,
return false;
}
-/// \brief Return the resulting type for the conditional operator in
+/// Return the resulting type for the conditional operator in
/// OpenCL (aka "ternary selection operator", OpenCL v1.1
/// s6.3.i) when the condition is a vector type.
static QualType
OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
- Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get());
+ Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get());
if (Cond.isInvalid())
return QualType();
QualType CondTy = Cond.get()->getType();
@@ -6727,7 +6815,7 @@ OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc);
}
-/// \brief Return true if the Expr is block type
+/// Return true if the Expr is block type
static bool checkBlockType(Sema &S, const Expr *E) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
QualType Ty = CE->getCallee()->getType();
@@ -7050,6 +7138,10 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
E = E->IgnoreImpCasts();
E = E->IgnoreConversionOperator();
E = E->IgnoreImpCasts();
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = MTE->GetTemporaryExpr();
+ E = E->IgnoreImpCasts();
+ }
// Built-in binary operator.
if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) {
@@ -7097,6 +7189,8 @@ static bool ExprLooksBoolean(Expr *E) {
return OP->getOpcode() == UO_LNot;
if (E->getType()->isPointerType())
return true;
+ // FIXME: What about overloaded operator calls returning "unspecified boolean
+ // type"s (commonly pointer-to-members)?
return false;
}
@@ -7265,7 +7359,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr;
- QualType result = CheckConditionalOperands(Cond, LHS, RHS,
+ QualType result = CheckConditionalOperands(Cond, LHS, RHS,
VK, OK, QuestionLoc);
if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() ||
RHS.isInvalid())
@@ -7337,7 +7431,7 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
// Treat lifetime mismatches as fatal.
else if (lhq.getObjCLifetime() != rhq.getObjCLifetime())
ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
-
+
// For GCC/MS compatibility, other qualifier mismatches are treated
// as still compatible in C.
else ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
@@ -7684,7 +7778,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// - conversions from 'Class' to the redefinition type
if (RHSType->isObjCClassType() &&
- Context.hasSameType(LHSType,
+ Context.hasSameType(LHSType,
Context.getObjCClassRedefinitionType())) {
Kind = CK_BitCast;
return Compatible;
@@ -7751,10 +7845,10 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// A* -> B*
if (RHSType->isObjCObjectPointerType()) {
Kind = CK_BitCast;
- Sema::AssignConvertType result =
+ Sema::AssignConvertType result =
checkObjCPointerTypesForAssignment(*this, LHSType, RHSType);
if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
- result == Compatible &&
+ result == Compatible &&
!CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType))
result = IncompatibleObjCWeakRef;
return result;
@@ -7778,7 +7872,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// - conversions to 'Class' from its redefinition type
if (LHSType->isObjCClassType() &&
- Context.hasSameType(RHSType,
+ Context.hasSameType(RHSType,
Context.getObjCClassRedefinitionType())) {
return Compatible;
}
@@ -7787,7 +7881,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
// Only under strict condition T^ is compatible with an Objective-C pointer.
- if (RHSType->isBlockPointerType() &&
+ if (RHSType->isBlockPointerType() &&
LHSType->isBlockCompatibleObjCPointerType(Context)) {
if (ConvertRHS)
maybeExtendBlockObject(RHS);
@@ -7848,7 +7942,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return Incompatible;
}
-/// \brief Constructs a transparent union from an expression that is
+/// Constructs a transparent union from an expression that is
/// used to initialize the transparent union.
static void ConstructTransparentUnion(Sema &S, ASTContext &C,
ExprResult &EResult, QualType UnionType,
@@ -8015,11 +8109,11 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
if (Diagnose && isa<ObjCProtocolExpr>(PRE)) {
ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol();
if (PDecl && !PDecl->hasDefinition()) {
- Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName();
+ Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl;
Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
}
}
-
+
CastKind Kind;
Sema::AssignConvertType result =
CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS);
@@ -8054,18 +8148,57 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
RHS = E;
return Compatible;
}
-
+
if (ConvertRHS)
RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
}
+namespace {
+/// The original operand to an operator, prior to the application of the usual
+/// arithmetic conversions and converting the arguments of a builtin operator
+/// candidate.
+struct OriginalOperand {
+ explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) {
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Op))
+ Op = MTE->GetTemporaryExpr();
+ if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op))
+ Op = BTE->getSubExpr();
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) {
+ Orig = ICE->getSubExprAsWritten();
+ Conversion = ICE->getConversionFunction();
+ }
+ }
+
+ QualType getType() const { return Orig->getType(); }
+
+ Expr *Orig;
+ NamedDecl *Conversion;
+};
+}
+
QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,
ExprResult &RHS) {
+ OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
+
Diag(Loc, diag::err_typecheck_invalid_operands)
- << LHS.get()->getType() << RHS.get()->getType()
+ << OrigLHS.getType() << OrigRHS.getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+
+ // If a user-defined conversion was applied to either of the operands prior
+ // to applying the built-in operator rules, tell the user about it.
+ if (OrigLHS.Conversion) {
+ Diag(OrigLHS.Conversion->getLocation(),
+ diag::note_typecheck_invalid_operands_converted)
+ << 0 << LHS.get()->getType();
+ }
+ if (OrigRHS.Conversion) {
+ Diag(OrigRHS.Conversion->getLocation(),
+ diag::note_typecheck_invalid_operands_converted)
+ << 1 << RHS.get()->getType();
+ }
+
return QualType();
}
@@ -8116,7 +8249,7 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
// The conversion to apply to the scalar before splatting it,
// if necessary.
CastKind scalarCast = CK_NoOp;
-
+
if (vectorEltTy->isIntegralType(S.Context)) {
if (S.getLangOpts().OpenCL && (scalarTy->isRealFloatingType() ||
(scalarTy->isIntegerType() &&
@@ -8216,7 +8349,7 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
QualType IntTy = Int->get()->getType().getUnqualifiedType();
// Determine if the integer constant can be expressed as a floating point
- // number of the appropiate type.
+ // number of the appropriate type.
llvm::APSInt Result;
bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context);
uint64_t Bits = 0;
@@ -8576,7 +8709,7 @@ QualType Sema::CheckRemainderOperands(
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
- if (LHS.get()->getType()->hasIntegerRepresentation() &&
+ if (LHS.get()->getType()->hasIntegerRepresentation() &&
RHS.get()->getType()->hasIntegerRepresentation())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
/*AllowBothBool*/getLangOpts().AltiVec,
@@ -8594,7 +8727,7 @@ QualType Sema::CheckRemainderOperands(
return compType;
}
-/// \brief Diagnose invalid arithmetic on two void pointers.
+/// Diagnose invalid arithmetic on two void pointers.
static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
@@ -8604,7 +8737,7 @@ static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
<< RHSExpr->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on a void pointer.
+/// Diagnose invalid arithmetic on a void pointer.
static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
@@ -8613,7 +8746,7 @@ static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
<< 0 /* one pointer */ << Pointer->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on a null pointer.
+/// 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.
@@ -8628,7 +8761,7 @@ static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc,
<< S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on two function pointers.
+/// Diagnose invalid arithmetic on two function pointers.
static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS) {
assert(LHS->getType()->isAnyPointerType());
@@ -8644,7 +8777,7 @@ static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
<< LHS->getSourceRange() << RHS->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on a function pointer.
+/// Diagnose invalid arithmetic on a function pointer.
static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
assert(Pointer->getType()->isAnyPointerType());
@@ -8656,7 +8789,7 @@ static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
<< Pointer->getSourceRange();
}
-/// \brief Emit error if Operand is incomplete pointer type
+/// Emit error if Operand is incomplete pointer type
///
/// \returns True if pointer has incomplete type
static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
@@ -8672,7 +8805,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
PointeeTy, Operand->getSourceRange());
}
-/// \brief Check the validity of an arithmetic pointer operand.
+/// Check the validity of an arithmetic pointer operand.
///
/// If the operand has pointer type, this code will check for pointer types
/// which are invalid in arithmetic operations. These will be diagnosed
@@ -8703,7 +8836,7 @@ static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
return true;
}
-/// \brief Check the validity of a binary arithmetic operation w.r.t. pointer
+/// Check the validity of a binary arithmetic operation w.r.t. pointer
/// operands.
///
/// This routine will diagnose any invalid arithmetic on pointer operands much
@@ -8805,7 +8938,7 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
}
-/// \brief Emit a warning when adding a char literal to a string.
+/// Emit a warning when adding a char literal to a string.
static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
const Expr *StringRefExpr = LHSExpr;
@@ -8856,7 +8989,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
}
}
-/// \brief Emit error when two pointers are incompatible.
+/// Emit error when two pointers are incompatible.
static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
assert(LHSExpr->getType()->isAnyPointerType());
@@ -8928,7 +9061,7 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
// In C++ adding zero to a null pointer is defined.
llvm::APSInt KnownVal;
if (!getLangOpts().CPlusPlus ||
- (!IExp->isValueDependent() &&
+ (!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(
@@ -9005,7 +9138,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
llvm::APSInt KnownVal;
- if (!getLangOpts().CPlusPlus ||
+ if (!getLangOpts().CPlusPlus ||
(!RHS.get()->isValueDependent() &&
(!RHS.get()->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) {
diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
@@ -9154,7 +9287,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
-/// \brief Return the resulting type when a vector is shifted
+/// Return the resulting type when a vector is shifted
/// by a scalar or vector shift amount.
static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign) {
@@ -9300,16 +9433,6 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
return LHSType;
}
-static bool IsWithinTemplateSpecialization(Decl *D) {
- if (DeclContext *DC = D->getDeclContext()) {
- if (isa<ClassTemplateSpecializationDecl>(DC))
- return true;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
- return FD->isFunctionTemplateSpecialization();
- }
- return false;
-}
-
/// If two different enums are compared, raise a warning.
static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
Expr *RHS) {
@@ -9339,7 +9462,7 @@ static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
<< LHS->getSourceRange() << RHS->getSourceRange();
}
-/// \brief Diagnose bad pointer comparisons.
+/// Diagnose bad pointer comparisons.
static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS,
bool IsError) {
@@ -9349,7 +9472,7 @@ static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
-/// \brief Returns false if the pointers are converted to a composite type,
+/// Returns false if the pointers are converted to a composite type,
/// true otherwise.
static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS) {
@@ -9587,137 +9710,368 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
// Get the decl for a simple expression: a reference to a variable,
// an implicit C++ field reference, or an implicit ObjC ivar reference.
static ValueDecl *getCompareDecl(Expr *E) {
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
+ if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
return DR->getDecl();
- if (ObjCIvarRefExpr* Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
+ if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
if (Ivar->isFreeIvar())
return Ivar->getDecl();
}
- if (MemberExpr* Mem = dyn_cast<MemberExpr>(E)) {
+ if (MemberExpr *Mem = dyn_cast<MemberExpr>(E)) {
if (Mem->isImplicitAccess())
return Mem->getMemberDecl();
}
return nullptr;
}
-// C99 6.5.8, C++ [expr.rel]
-QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, BinaryOperatorKind Opc,
- bool IsRelational) {
- checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
+/// Diagnose some forms of syntactically-obvious tautological comparison.
+static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
+ Expr *LHS, Expr *RHS,
+ BinaryOperatorKind Opc) {
+ Expr *LHSStripped = LHS->IgnoreParenImpCasts();
+ Expr *RHSStripped = RHS->IgnoreParenImpCasts();
+
+ QualType LHSType = LHS->getType();
+ QualType RHSType = RHS->getType();
+ if (LHSType->hasFloatingRepresentation() ||
+ (LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) ||
+ LHS->getLocStart().isMacroID() || RHS->getLocStart().isMacroID() ||
+ S.inTemplateInstantiation())
+ return;
- // Handle vector comparisons separately.
- if (LHS.get()->getType()->isVectorType() ||
- RHS.get()->getType()->isVectorType())
- return CheckVectorCompareOperands(LHS, RHS, Loc, IsRelational);
+ // Comparisons between two array types are ill-formed for operator<=>, so
+ // we shouldn't emit any additional warnings about it.
+ if (Opc == BO_Cmp && LHSType->isArrayType() && RHSType->isArrayType())
+ return;
+
+ // For non-floating point types, check for self-comparisons of the form
+ // x == x, x != x, x < x, etc. These always evaluate to a constant, and
+ // often indicate logic errors in the program.
+ //
+ // NOTE: Don't warn about comparison expressions resulting from macro
+ // expansion. Also don't warn about comparisons which are only self
+ // comparisons within a template instantiation. The warnings should catch
+ // obvious cases in the definition of the template anyways. The idea is to
+ // warn when the typed comparison operator will always evaluate to the same
+ // result.
+ ValueDecl *DL = getCompareDecl(LHSStripped);
+ ValueDecl *DR = getCompareDecl(RHSStripped);
+ if (DL && DR && declaresSameEntity(DL, DR)) {
+ StringRef Result;
+ switch (Opc) {
+ case BO_EQ: case BO_LE: case BO_GE:
+ Result = "true";
+ break;
+ case BO_NE: case BO_LT: case BO_GT:
+ Result = "false";
+ break;
+ case BO_Cmp:
+ Result = "'std::strong_ordering::equal'";
+ break;
+ default:
+ break;
+ }
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_comparison_always)
+ << 0 /*self-comparison*/ << !Result.empty()
+ << Result);
+ } else if (DL && DR &&
+ DL->getType()->isArrayType() && DR->getType()->isArrayType() &&
+ !DL->isWeak() && !DR->isWeak()) {
+ // What is it always going to evaluate to?
+ StringRef Result;
+ switch(Opc) {
+ case BO_EQ: // e.g. array1 == array2
+ Result = "false";
+ break;
+ case BO_NE: // e.g. array1 != array2
+ Result = "true";
+ break;
+ default: // e.g. array1 <= array2
+ // The best we can say is 'a constant'
+ break;
+ }
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_comparison_always)
+ << 1 /*array comparison*/
+ << !Result.empty() << Result);
+ }
+
+ if (isa<CastExpr>(LHSStripped))
+ LHSStripped = LHSStripped->IgnoreParenCasts();
+ if (isa<CastExpr>(RHSStripped))
+ RHSStripped = RHSStripped->IgnoreParenCasts();
+
+ // Warn about comparisons against a string constant (unless the other
+ // operand is null); the user probably wants strcmp.
+ Expr *LiteralString = nullptr;
+ Expr *LiteralStringStripped = nullptr;
+ if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
+ !RHSStripped->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ LiteralString = LHS;
+ LiteralStringStripped = LHSStripped;
+ } else if ((isa<StringLiteral>(RHSStripped) ||
+ isa<ObjCEncodeExpr>(RHSStripped)) &&
+ !LHSStripped->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ LiteralString = RHS;
+ LiteralStringStripped = RHSStripped;
+ }
+
+ if (LiteralString) {
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_stringcompare)
+ << isa<ObjCEncodeExpr>(LiteralStringStripped)
+ << LiteralString->getSourceRange());
+ }
+}
+
+static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) {
+ switch (CK) {
+ default: {
+#ifndef NDEBUG
+ llvm::errs() << "unhandled cast kind: " << CastExpr::getCastKindName(CK)
+ << "\n";
+#endif
+ llvm_unreachable("unhandled cast kind");
+ }
+ case CK_UserDefinedConversion:
+ return ICK_Identity;
+ case CK_LValueToRValue:
+ return ICK_Lvalue_To_Rvalue;
+ case CK_ArrayToPointerDecay:
+ return ICK_Array_To_Pointer;
+ case CK_FunctionToPointerDecay:
+ return ICK_Function_To_Pointer;
+ case CK_IntegralCast:
+ return ICK_Integral_Conversion;
+ case CK_FloatingCast:
+ return ICK_Floating_Conversion;
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ return ICK_Floating_Integral;
+ case CK_IntegralComplexCast:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralComplexToFloatingComplex:
+ return ICK_Complex_Conversion;
+ case CK_FloatingComplexToReal:
+ case CK_FloatingRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralRealToComplex:
+ return ICK_Complex_Real;
+ }
+}
+
+static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E,
+ QualType FromType,
+ SourceLocation Loc) {
+ // Check for a narrowing implicit conversion.
+ StandardConversionSequence SCS;
+ SCS.setAsIdentityConversion();
+ SCS.setToType(0, FromType);
+ SCS.setToType(1, ToType);
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ SCS.Second = castKindToImplicitConversionKind(ICE->getCastKind());
+
+ APValue PreNarrowingValue;
+ QualType PreNarrowingType;
+ switch (SCS.getNarrowingKind(S.Context, E, PreNarrowingValue,
+ PreNarrowingType,
+ /*IgnoreFloatToIntegralConversion*/ true)) {
+ case NK_Dependent_Narrowing:
+ // Implicit conversion to a narrower type, but the expression is
+ // value-dependent so we can't tell whether it's actually narrowing.
+ case NK_Not_Narrowing:
+ return false;
+
+ case NK_Constant_Narrowing:
+ // Implicit conversion to a narrower type, and the value is not a constant
+ // expression.
+ S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing)
+ << /*Constant*/ 1
+ << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << ToType;
+ return true;
+
+ case NK_Variable_Narrowing:
+ // Implicit conversion to a narrower type, and the value is not a constant
+ // expression.
+ case NK_Type_Narrowing:
+ S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing)
+ << /*Constant*/ 0 << FromType << ToType;
+ // TODO: It's not a constant expression, but what if the user intended it
+ // to be? Can we produce notes to help them figure out why it isn't?
+ return true;
+ }
+ llvm_unreachable("unhandled case in switch");
+}
+
+static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
+ ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc) {
+ using CCT = ComparisonCategoryType;
QualType LHSType = LHS.get()->getType();
QualType RHSType = RHS.get()->getType();
+ // Dig out the original argument type and expression before implicit casts
+ // were applied. These are the types/expressions we need to check the
+ // [expr.spaceship] requirements against.
+ ExprResult LHSStripped = LHS.get()->IgnoreParenImpCasts();
+ ExprResult RHSStripped = RHS.get()->IgnoreParenImpCasts();
+ QualType LHSStrippedType = LHSStripped.get()->getType();
+ QualType RHSStrippedType = RHSStripped.get()->getType();
+
+ // C++2a [expr.spaceship]p3: If one of the operands is of type bool and the
+ // other is not, the program is ill-formed.
+ if (LHSStrippedType->isBooleanType() != RHSStrippedType->isBooleanType()) {
+ S.InvalidOperands(Loc, LHSStripped, RHSStripped);
+ return QualType();
+ }
- Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts();
- Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
+ int NumEnumArgs = (int)LHSStrippedType->isEnumeralType() +
+ RHSStrippedType->isEnumeralType();
+ if (NumEnumArgs == 1) {
+ bool LHSIsEnum = LHSStrippedType->isEnumeralType();
+ QualType OtherTy = LHSIsEnum ? RHSStrippedType : LHSStrippedType;
+ if (OtherTy->hasFloatingRepresentation()) {
+ S.InvalidOperands(Loc, LHSStripped, RHSStripped);
+ return QualType();
+ }
+ }
+ if (NumEnumArgs == 2) {
+ // C++2a [expr.spaceship]p5: If both operands have the same enumeration
+ // type E, the operator yields the result of converting the operands
+ // to the underlying type of E and applying <=> to the converted operands.
+ if (!S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
+ S.InvalidOperands(Loc, LHS, RHS);
+ return QualType();
+ }
+ QualType IntType =
+ LHSStrippedType->getAs<EnumType>()->getDecl()->getIntegerType();
+ assert(IntType->isArithmeticType());
- checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
- diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
+ // We can't use `CK_IntegralCast` when the underlying type is 'bool', so we
+ // promote the boolean type, and all other promotable integer types, to
+ // avoid this.
+ if (IntType->isPromotableIntegerType())
+ IntType = S.Context.getPromotedIntegerType(IntType);
- if (!LHSType->hasFloatingRepresentation() &&
- !(LHSType->isBlockPointerType() && IsRelational) &&
- !LHS.get()->getLocStart().isMacroID() &&
- !RHS.get()->getLocStart().isMacroID() &&
- !inTemplateInstantiation()) {
- // For non-floating point types, check for self-comparisons of the form
- // x == x, x != x, x < x, etc. These always evaluate to a constant, and
- // often indicate logic errors in the program.
- //
- // NOTE: Don't warn about comparison expressions resulting from macro
- // expansion. Also don't warn about comparisons which are only self
- // comparisons within a template specialization. The warnings should catch
- // obvious cases in the definition of the template anyways. The idea is to
- // warn when the typed comparison operator will always evaluate to the same
- // result.
- ValueDecl *DL = getCompareDecl(LHSStripped);
- ValueDecl *DR = getCompareDecl(RHSStripped);
- if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) {
- DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
- << 0 // self-
- << (Opc == BO_EQ
- || Opc == BO_LE
- || Opc == BO_GE));
- } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() &&
- !DL->getType()->isReferenceType() &&
- !DR->getType()->isReferenceType()) {
- // what is it always going to eval to?
- char always_evals_to;
- switch(Opc) {
- case BO_EQ: // e.g. array1 == array2
- always_evals_to = 0; // false
- break;
- case BO_NE: // e.g. array1 != array2
- always_evals_to = 1; // true
- break;
- default:
- // best we can say is 'a constant'
- always_evals_to = 2; // e.g. array1 <= array2
- break;
- }
- DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
- << 1 // array
- << always_evals_to);
- }
+ LHS = S.ImpCastExprToType(LHS.get(), IntType, CK_IntegralCast);
+ RHS = S.ImpCastExprToType(RHS.get(), IntType, CK_IntegralCast);
+ LHSType = RHSType = IntType;
+ }
- if (isa<CastExpr>(LHSStripped))
- LHSStripped = LHSStripped->IgnoreParenCasts();
- if (isa<CastExpr>(RHSStripped))
- RHSStripped = RHSStripped->IgnoreParenCasts();
+ // C++2a [expr.spaceship]p4: If both operands have arithmetic types, the
+ // usual arithmetic conversions are applied to the operands.
+ QualType Type = S.UsualArithmeticConversions(LHS, RHS);
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
+ if (Type.isNull())
+ return S.InvalidOperands(Loc, LHS, RHS);
+ assert(Type->isArithmeticType() || Type->isEnumeralType());
+
+ bool HasNarrowing = checkThreeWayNarrowingConversion(
+ S, Type, LHS.get(), LHSType, LHS.get()->getLocStart());
+ HasNarrowing |= checkThreeWayNarrowingConversion(
+ S, Type, RHS.get(), RHSType, RHS.get()->getLocStart());
+ if (HasNarrowing)
+ return QualType();
- // Warn about comparisons against a string constant (unless the other
- // operand is null), the user probably wants strcmp.
- Expr *literalString = nullptr;
- Expr *literalStringStripped = nullptr;
- if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
- !RHSStripped->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull)) {
- literalString = LHS.get();
- literalStringStripped = LHSStripped;
- } else if ((isa<StringLiteral>(RHSStripped) ||
- isa<ObjCEncodeExpr>(RHSStripped)) &&
- !LHSStripped->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull)) {
- literalString = RHS.get();
- literalStringStripped = RHSStripped;
- }
+ assert(!Type.isNull() && "composite type for <=> has not been set");
- if (literalString) {
- DiagRuntimeBehavior(Loc, nullptr,
- PDiag(diag::warn_stringcompare)
- << isa<ObjCEncodeExpr>(literalStringStripped)
- << literalString->getSourceRange());
+ auto TypeKind = [&]() {
+ if (const ComplexType *CT = Type->getAs<ComplexType>()) {
+ if (CT->getElementType()->hasFloatingRepresentation())
+ return CCT::WeakEquality;
+ return CCT::StrongEquality;
}
- }
+ if (Type->isIntegralOrEnumerationType())
+ return CCT::StrongOrdering;
+ if (Type->hasFloatingRepresentation())
+ return CCT::PartialOrdering;
+ llvm_unreachable("other types are unimplemented");
+ }();
+
+ return S.CheckComparisonCategoryType(TypeKind, Loc);
+}
+
+static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
+ if (Opc == BO_Cmp)
+ return checkArithmeticOrEnumeralThreeWayCompare(S, LHS, RHS, Loc);
// C99 6.5.8p3 / C99 6.5.9p4
- UsualArithmeticConversions(LHS, RHS);
+ QualType Type = S.UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
+ if (Type.isNull())
+ return S.InvalidOperands(Loc, LHS, RHS);
+ assert(Type->isArithmeticType() || Type->isEnumeralType());
+
+ checkEnumComparison(S, Loc, LHS.get(), RHS.get());
- LHSType = LHS.get()->getType();
- RHSType = RHS.get()->getType();
+ if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
+ return S.InvalidOperands(Loc, LHS, RHS);
+
+ // Check for comparisons of floating point operands using != and ==.
+ if (Type->hasFloatingRepresentation() && BinaryOperator::isEqualityOp(Opc))
+ S.CheckFloatComparison(Loc, LHS.get(), RHS.get());
// The result of comparisons is 'bool' in C++, 'int' in C.
- QualType ResultTy = Context.getLogicalOperationType();
+ return S.Context.getLogicalOperationType();
+}
- if (IsRelational) {
- if (LHSType->isRealType() && RHSType->isRealType())
- return ResultTy;
- } else {
- // Check for comparisons of floating point operands using != and ==.
- if (LHSType->hasFloatingRepresentation())
- CheckFloatComparison(Loc, LHS.get(), RHS.get());
+// C99 6.5.8, C++ [expr.rel]
+QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
+ bool IsRelational = BinaryOperator::isRelationalOp(Opc);
+ bool IsThreeWay = Opc == BO_Cmp;
+ auto IsAnyPointerType = [](ExprResult E) {
+ QualType Ty = E.get()->getType();
+ return Ty->isPointerType() || Ty->isMemberPointerType();
+ };
- if (LHSType->isArithmeticType() && RHSType->isArithmeticType())
- return ResultTy;
+ // C++2a [expr.spaceship]p6: If at least one of the operands is of pointer
+ // type, array-to-pointer, ..., conversions are performed on both operands to
+ // bring them to their composite type.
+ // Otherwise, all comparisons expect an rvalue, so convert to rvalue before
+ // any type-related checks.
+ if (!IsThreeWay || IsAnyPointerType(LHS) || IsAnyPointerType(RHS)) {
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
+ } else {
+ LHS = DefaultLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ RHS = DefaultLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
}
+ checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
+
+ // Handle vector comparisons separately.
+ if (LHS.get()->getType()->isVectorType() ||
+ RHS.get()->getType()->isVectorType())
+ return CheckVectorCompareOperands(LHS, RHS, Loc, Opc);
+
+ diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
+ diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
+
+ QualType LHSType = LHS.get()->getType();
+ QualType RHSType = RHS.get()->getType();
+ if ((LHSType->isArithmeticType() || LHSType->isEnumeralType()) &&
+ (RHSType->isArithmeticType() || RHSType->isEnumeralType()))
+ return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc);
+
const Expr::NullPointerConstantKind LHSNullKind =
LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
const Expr::NullPointerConstantKind RHSNullKind =
@@ -9725,6 +10079,44 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
bool LHSIsNull = LHSNullKind != Expr::NPCK_NotNull;
bool RHSIsNull = RHSNullKind != Expr::NPCK_NotNull;
+ auto computeResultTy = [&]() {
+ if (Opc != BO_Cmp)
+ return Context.getLogicalOperationType();
+ assert(getLangOpts().CPlusPlus);
+ assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType()));
+
+ QualType CompositeTy = LHS.get()->getType();
+ assert(!CompositeTy->isReferenceType());
+
+ auto buildResultTy = [&](ComparisonCategoryType Kind) {
+ return CheckComparisonCategoryType(Kind, Loc);
+ };
+
+ // C++2a [expr.spaceship]p7: If the composite pointer type is a function
+ // pointer type, a pointer-to-member type, or std::nullptr_t, the
+ // result is of type std::strong_equality
+ if (CompositeTy->isFunctionPointerType() ||
+ CompositeTy->isMemberPointerType() || CompositeTy->isNullPtrType())
+ // FIXME: consider making the function pointer case produce
+ // strong_ordering not strong_equality, per P0946R0-Jax18 discussion
+ // and direction polls
+ return buildResultTy(ComparisonCategoryType::StrongEquality);
+
+ // C++2a [expr.spaceship]p8: If the composite pointer type is an object
+ // pointer type, p <=> q is of type std::strong_ordering.
+ if (CompositeTy->isPointerType()) {
+ // P0946R0: Comparisons between a null pointer constant and an object
+ // pointer result in std::strong_equality
+ if (LHSIsNull != RHSIsNull)
+ return buildResultTy(ComparisonCategoryType::StrongEquality);
+ return buildResultTy(ComparisonCategoryType::StrongOrdering);
+ }
+ // C++2a [expr.spaceship]p9: Otherwise, the program is ill-formed.
+ // TODO: Extend support for operator<=> to ObjC types.
+ return InvalidOperands(Loc, LHS, RHS);
+ };
+
+
if (!IsRelational && LHSIsNull != RHSIsNull) {
bool IsEquality = Opc == BO_EQ;
if (RHSIsNull)
@@ -9752,29 +10144,30 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// conformance with the C++ standard.
diagnoseFunctionPointerToVoidComparison(
*this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext());
-
+
if (isSFINAEContext())
return QualType();
-
+
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
+ return computeResultTy();
}
// C++ [expr.eq]p2:
// If at least one operand is a pointer [...] bring them to their
// composite pointer type.
+ // C++ [expr.spaceship]p6
+ // If at least one of the operands is of pointer type, [...] bring them
+ // to their composite pointer type.
// C++ [expr.rel]p2:
// If both operands are pointers, [...] bring them to their composite
// pointer type.
if ((int)LHSType->isPointerType() + (int)RHSType->isPointerType() >=
(IsRelational ? 2 : 1) &&
- (!LangOpts.ObjCAutoRefCount ||
- !(LHSType->isObjCObjectPointerType() ||
- RHSType->isObjCObjectPointerType()))) {
+ (!LangOpts.ObjCAutoRefCount || !(LHSType->isObjCObjectPointerType() ||
+ RHSType->isObjCObjectPointerType()))) {
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
- else
- return ResultTy;
+ return computeResultTy();
}
} else if (LHSType->isPointerType() &&
RHSType->isPointerType()) { // C99 6.5.8p2
@@ -9825,7 +10218,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
else
RHS = ImpCastExprToType(RHS.get(), LHSType, Kind);
}
- return ResultTy;
+ return computeResultTy();
}
if (getLangOpts().CPlusPlus) {
@@ -9835,11 +10228,11 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (!IsRelational && LHSIsNull && RHSIsNull) {
if (LHSType->isNullPtrType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (RHSType->isNullPtrType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
}
@@ -9848,12 +10241,12 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (!IsRelational && RHSType->isNullPtrType() &&
(LHSType->isObjCObjectPointerType() || LHSType->isBlockPointerType())) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (!IsRelational && LHSType->isNullPtrType() &&
(RHSType->isObjCObjectPointerType() || RHSType->isBlockPointerType())) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (IsRelational &&
@@ -9876,7 +10269,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
else
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
}
}
@@ -9889,15 +10282,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
else
- return ResultTy;
+ return computeResultTy();
}
-
- // Handle scoped enumeration types specifically, since they don't promote
- // to integers.
- if (LHS.get()->getType()->isEnumeralType() &&
- Context.hasSameUnqualifiedType(LHS.get()->getType(),
- RHS.get()->getType()))
- return ResultTy;
}
// Handle block pointer types.
@@ -9913,7 +10299,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
+ return computeResultTy();
}
// Allow block pointers to be compared with null pointer constants.
@@ -9937,7 +10323,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS = ImpCastExprToType(RHS.get(), LHSType,
LHSType->isPointerType() ? CK_BitCast
: CK_AnyPointerToBlockPointerCast);
- return ResultTy;
+ return computeResultTy();
}
if (LHSType->isObjCObjectPointerType() ||
@@ -9970,7 +10356,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS = ImpCastExprToType(E, LHSType,
LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
- return ResultTy;
+ return computeResultTy();
}
if (LHSType->isObjCObjectPointerType() &&
RHSType->isObjCObjectPointerType()) {
@@ -9984,7 +10370,20 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
else
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
+ return computeResultTy();
+ }
+
+ if (!IsRelational && LHSType->isBlockPointerType() &&
+ RHSType->isBlockCompatibleObjCPointerType(Context)) {
+ LHS = ImpCastExprToType(LHS.get(), RHSType,
+ CK_BlockPointerToObjCPointerCast);
+ return computeResultTy();
+ } else if (!IsRelational &&
+ LHSType->isBlockCompatibleObjCPointerType(Context) &&
+ RHSType->isBlockPointerType()) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType,
+ CK_BlockPointerToObjCPointerCast);
+ return computeResultTy();
}
}
if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) ||
@@ -10017,37 +10416,37 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (isError)
return QualType();
}
-
+
if (LHSType->isIntegerType())
LHS = ImpCastExprToType(LHS.get(), RHSType,
LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
else
RHS = ImpCastExprToType(RHS.get(), LHSType,
RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
- return ResultTy;
+ return computeResultTy();
}
-
+
// Handle block pointers.
if (!IsRelational && RHSIsNull
&& LHSType->isBlockPointerType() && RHSType->isIntegerType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (!IsRelational && LHSIsNull
&& LHSType->isIntegerType() && RHSType->isBlockPointerType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (getLangOpts().OpenCLVersion >= 200) {
if (LHSIsNull && RHSType->isQueueT()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (LHSType->isQueueT() && RHSIsNull) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
}
@@ -10101,7 +10500,7 @@ QualType Sema::GetSignedVectorType(QualType V) {
/// types.
QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
- bool IsRelational) {
+ BinaryOperatorKind Opc) {
// Check to make sure we're operating on vectors of the same type and width,
// Allowing one side to be a scalar of element type.
QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false,
@@ -10121,22 +10520,12 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
- if (!LHSType->hasFloatingRepresentation() && !inTemplateInstantiation()) {
- if (DeclRefExpr* DRL
- = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts()))
- if (DeclRefExpr* DRR
- = dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts()))
- if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc, nullptr,
- PDiag(diag::warn_comparison_always)
- << 0 // self-
- << 2 // "a constant"
- );
- }
+ diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
// Check for comparisons of floating point operands using != and ==.
- if (!IsRelational && LHSType->hasFloatingRepresentation()) {
- assert (RHS.get()->getType()->hasFloatingRepresentation());
+ if (BinaryOperator::isEqualityOp(Opc) &&
+ LHSType->hasFloatingRepresentation()) {
+ assert(RHS.get()->getType()->hasFloatingRepresentation());
CheckFloatComparison(Loc, LHS.get(), RHS.get());
}
@@ -10207,7 +10596,7 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
// Check vector operands differently.
if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
return CheckVectorLogicalOperands(LHS, RHS, Loc);
-
+
// Diagnose cases where the user write a logical and/or but probably meant a
// bitwise one. We do this when the LHS is a non-bool integer and the RHS
// is a constant.
@@ -10418,8 +10807,16 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
// Static fields do not inherit constness from parents.
break;
}
- break;
- } // End MemberExpr
+ break; // End MemberExpr
+ } else if (const ArraySubscriptExpr *ASE =
+ dyn_cast<ArraySubscriptExpr>(E)) {
+ E = ASE->getBase()->IgnoreParenImpCasts();
+ continue;
+ } else if (const ExtVectorElementExpr *EVE =
+ dyn_cast<ExtVectorElementExpr>(E)) {
+ E = EVE->getBase()->IgnoreParenImpCasts();
+ continue;
+ }
break;
}
@@ -10660,12 +11057,34 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
static void CheckIdentityFieldAssignment(Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc,
Sema &Sema) {
+ if (Sema.inTemplateInstantiation())
+ return;
+ if (Sema.isUnevaluatedContext())
+ return;
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return;
+ if (LHSExpr->getExprLoc().isMacroID() || RHSExpr->getExprLoc().isMacroID())
+ return;
+
// C / C++ fields
MemberExpr *ML = dyn_cast<MemberExpr>(LHSExpr);
MemberExpr *MR = dyn_cast<MemberExpr>(RHSExpr);
- if (ML && MR && ML->getMemberDecl() == MR->getMemberDecl()) {
- if (isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase()))
- Sema.Diag(Loc, diag::warn_identity_field_assign) << 0;
+ if (ML && MR) {
+ if (!(isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase())))
+ return;
+ const ValueDecl *LHSDecl =
+ cast<ValueDecl>(ML->getMemberDecl()->getCanonicalDecl());
+ const ValueDecl *RHSDecl =
+ cast<ValueDecl>(MR->getMemberDecl()->getCanonicalDecl());
+ if (LHSDecl != RHSDecl)
+ return;
+ if (LHSDecl->getType().isVolatileQualified())
+ return;
+ if (const ReferenceType *RefTy = LHSDecl->getType()->getAs<ReferenceType>())
+ if (RefTy->getPointeeType().isVolatileQualified())
+ return;
+
+ Sema.Diag(Loc, diag::warn_identity_field_assign) << 0;
}
// Objective-C instance variables
@@ -10701,7 +11120,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
<< LHSType.getUnqualifiedType();
return QualType();
}
-
+
AssignConvertType ConvTy;
if (CompoundType.isNull()) {
Expr *RHSCheck = RHS.get();
@@ -10938,7 +11357,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
// Otherwise, we just need a complete type.
if (checkArithmeticIncompletePointerType(S, OpLoc, Op) ||
checkArithmeticOnObjCPointer(S, OpLoc, Op))
- return QualType();
+ return QualType();
} else if (ResType->isAnyComplexType()) {
// C99 does not support ++/-- on complex types, we allow as an extension.
S.Diag(OpLoc, diag::ext_integer_increment_complex)
@@ -10978,7 +11397,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
return ResType.getUnqualifiedType();
}
}
-
+
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
/// This routine allows us to typecheck complex/recursive expressions
@@ -11046,7 +11465,7 @@ namespace {
AO_No_Error = 4
};
}
-/// \brief Diagnose invalid operand for address of operations.
+/// Diagnose invalid operand for address of operations.
///
/// \param Type The type of operand which cannot have its address taken.
static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
@@ -11138,7 +11557,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
Expr::LValueClassification lval = op->ClassifyLValue(Context);
unsigned AddressOfError = AO_No_Error;
- if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
+ if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
bool sfinae = (bool)isSFINAEContext();
Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary
: diag::ext_typecheck_addrof_temporary)
@@ -11353,7 +11772,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
// ...except that certain expressions are never l-values in C.
if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType())
VK = VK_RValue;
-
+
return Result;
}
@@ -11419,12 +11838,13 @@ static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
}
/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself.
-/// This warning is only emitted for builtin assignment operations. It is also
-/// suppressed in the event of macro expansions.
+/// This warning suppressed in the event of macro expansions.
static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
- SourceLocation OpLoc) {
+ SourceLocation OpLoc, bool IsBuiltin) {
if (S.inTemplateInstantiation())
return;
+ if (S.isUnevaluatedContext())
+ return;
if (OpLoc.isInvalid() || OpLoc.isMacroID())
return;
LHSExpr = LHSExpr->IgnoreParenImpCasts();
@@ -11447,9 +11867,10 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
if (RefTy->getPointeeType().isVolatileQualified())
return;
- S.Diag(OpLoc, diag::warn_self_assignment)
- << LHSDeclRef->getType()
- << LHSExpr->getSourceRange() << RHSExpr->getSourceRange();
+ S.Diag(OpLoc, IsBuiltin ? diag::warn_self_assignment_builtin
+ : diag::warn_self_assignment_overloaded)
+ << LHSDeclRef->getType() << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
}
/// Check if a bitwise-& is performed on an Objective-C pointer. This
@@ -11489,7 +11910,7 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
if (SelArg0.startswith("performSelector"))
Diag = diag::warn_objc_pointer_masking_performSelector;
}
-
+
S.Diag(OpLoc, Diag)
<< ObjCPointerExpr->getSourceRange();
}
@@ -11584,8 +12005,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// C++11 5.17p9:
// The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning
// of x = {} is x = T().
- InitializationKind Kind =
- InitializationKind::CreateDirectList(RHSExpr->getLocStart());
+ InitializationKind Kind = InitializationKind::CreateDirectList(
+ RHSExpr->getLocStart(), RHSExpr->getLocStart(), RHSExpr->getLocEnd());
InitializedEntity Entity =
InitializedEntity::InitializeTemporary(LHSExpr->getType());
InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr);
@@ -11642,7 +12063,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
OK = LHS.get()->getObjectKind();
}
if (!ResultTy.isNull()) {
- DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true);
DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc);
}
RecordModifiableNonNullParam(*this, LHS.get());
@@ -11678,19 +12099,17 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
case BO_GE:
case BO_GT:
ConvertHalfVec = true;
- ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true);
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_EQ:
case BO_NE:
ConvertHalfVec = true;
- ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false);
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
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;
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
+ assert(ResultTy.isNull() || ResultTy->getAsCXXRecordDecl());
break;
case BO_And:
checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc);
@@ -11740,7 +12159,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_AndAssign:
case BO_OrAssign: // fallthrough
- DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true);
LLVM_FALLTHROUGH;
case BO_XorAssign:
CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc);
@@ -11790,7 +12209,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get());
-
+
// Opc is not a compound assignment if CompResultTy is null.
if (CompResultTy.isNull()) {
if (ConvertHalfVec)
@@ -11858,7 +12277,7 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
ParensRange);
}
-/// \brief It accepts a '&&' expr that is inside a '||' one.
+/// It accepts a '&&' expr that is inside a '||' one.
/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
/// in parentheses.
static void
@@ -11873,7 +12292,7 @@ EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
Bop->getSourceRange());
}
-/// \brief Returns true if the given expression can be evaluated as a constant
+/// Returns true if the given expression can be evaluated as a constant
/// 'true'.
static bool EvaluatesAsTrue(Sema &S, Expr *E) {
bool Res;
@@ -11881,7 +12300,7 @@ static bool EvaluatesAsTrue(Sema &S, Expr *E) {
E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res;
}
-/// \brief Returns true if the given expression can be evaluated as a constant
+/// Returns true if the given expression can be evaluated as a constant
/// 'false'.
static bool EvaluatesAsFalse(Sema &S, Expr *E) {
bool Res;
@@ -11889,7 +12308,7 @@ static bool EvaluatesAsFalse(Sema &S, Expr *E) {
E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res;
}
-/// \brief Look for '&&' in the left hand of a '||' expr.
+/// Look for '&&' in the left hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(LHSExpr)) {
@@ -11911,7 +12330,7 @@ static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
}
}
-/// \brief Look for '&&' in the right hand of a '||' expr.
+/// Look for '&&' in the right hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(RHSExpr)) {
@@ -11926,7 +12345,7 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
}
}
-/// \brief Look for bitwise op in the left or right hand of a bitwise op with
+/// Look for bitwise op in the left or right hand of a bitwise op with
/// lower precedence and emit a diagnostic together with a fixit hint that wraps
/// the '&' expression in parentheses.
static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc,
@@ -12039,6 +12458,21 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHS, Expr *RHS) {
+ switch (Opc) {
+ case BO_Assign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_SubAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ DiagnoseSelfAssignment(S, LHS, RHS, OpLoc, false);
+ CheckIdentityFieldAssignment(LHS, RHS, OpLoc, S);
+ break;
+ default:
+ break;
+ }
+
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
@@ -12115,7 +12549,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
return ExprError();
}
}
-
+
ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
if (LHS.isInvalid()) return ExprError();
LHSExpr = LHS.get();
@@ -12161,6 +12595,16 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
}
+static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) {
+ if (T.isNull() || T->isDependentType())
+ return false;
+
+ if (!T->isPromotableIntegerType())
+ return true;
+
+ return Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy);
+}
+
ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
Expr *InputExpr) {
@@ -12168,6 +12612,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
+ bool CanOverflow = false;
+
bool ConvertHalfVec = false;
if (getLangOpts().OpenCL) {
QualType Ty = InputExpr->getType();
@@ -12193,6 +12639,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
Opc == UO_PostInc,
Opc == UO_PreInc ||
Opc == UO_PreDec);
+ CanOverflow = isOverflowingIntegerType(Context, resultType);
break;
case UO_AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
@@ -12206,6 +12653,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
}
case UO_Plus:
case UO_Minus:
+ CanOverflow = Opc == UO_Minus &&
+ isOverflowingIntegerType(Context, Input.get()->getType());
Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid()) return ExprError();
// Unary plus and minus require promoting an operand of half vector to a
@@ -12242,6 +12691,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (Input.isInvalid())
return ExprError();
resultType = Input.get()->getType();
+
if (resultType->isDependentType())
break;
// C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
@@ -12312,7 +12762,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
-
+
// LNot always has type int. C99 6.5.3.3p5.
// In C++, it's bool. C++ 5.3.1p8
resultType = Context.getLogicalOperationType();
@@ -12338,7 +12788,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
OK = Input.get()->getObjectKind();
break;
case UO_Coawait:
- // It's unnessesary to represent the pass-through operator co_await in the
+ // It's unnecessary to represent the pass-through operator co_await in the
// AST; just return the input expression instead.
assert(!Input.get()->getType()->isDependentType() &&
"the co_await expression must be non-dependant before "
@@ -12356,37 +12806,37 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
CheckArrayAccess(Input.get());
auto *UO = new (Context)
- UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc);
+ UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow);
// 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
+/// Determine whether the given expression is a qualified member
/// access expression, of a form that could be turned into a pointer to member
/// with the address-of operator.
-static bool isQualifiedMemberAccess(Expr *E) {
+bool Sema::isQualifiedMemberAccess(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (!DRE->getQualifier())
return false;
-
+
ValueDecl *VD = DRE->getDecl();
if (!VD->isCXXClassMember())
return false;
-
+
if (isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD))
return true;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(VD))
return Method->isInstance();
-
+
return false;
}
-
+
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
if (!ULE->getQualifier())
return false;
-
+
for (NamedDecl *D : ULE->decls()) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isInstance())
@@ -12396,10 +12846,10 @@ static bool isQualifiedMemberAccess(Expr *E) {
break;
}
}
-
+
return false;
}
-
+
return false;
}
@@ -12549,11 +12999,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
LastExpr = rebuiltLastStmt;
} else {
LastExpr = PerformCopyInitialization(
- InitializedEntity::InitializeResult(LPLoc,
- Ty,
- false),
- SourceLocation(),
- LastExpr);
+ InitializedEntity::InitializeStmtExprResult(LPLoc, Ty),
+ SourceLocation(), LastExpr);
}
if (LastExpr.isInvalid())
@@ -12584,17 +13031,17 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
QualType ArgTy = TInfo->getType();
bool Dependent = ArgTy->isDependentType();
SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange();
-
+
// We must have at least one component that refers to the type, and the first
// one is known to be a field designator. Verify that the ArgTy represents
// a struct/union/class.
if (!Dependent && !ArgTy->isRecordType())
- return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type)
+ return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type)
<< ArgTy << TypeRange);
-
+
// Type must be complete per C99 7.17p3 because a declaring a variable
// with an incomplete type would be ill-formed.
- if (!Dependent
+ if (!Dependent
&& RequireCompleteType(BuiltinLoc, ArgTy,
diag::err_offsetof_incomplete_type, TypeRange))
return ExprError();
@@ -12614,7 +13061,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
CurrentType = AT->getElementType();
} else
CurrentType = Context.DependentTy;
-
+
ExprResult IdxRval = DefaultLvalueConversion(static_cast<Expr*>(OC.U.E));
if (IdxRval.isInvalid())
return ExprError();
@@ -12633,7 +13080,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
Exprs.push_back(Idx);
continue;
}
-
+
// Offset of a field.
if (CurrentType->isDependentType()) {
// We have the offset of a field, but we can't look into the dependent
@@ -12642,19 +13089,19 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
CurrentType = Context.DependentTy;
continue;
}
-
+
// We need to have a complete type to look into.
if (RequireCompleteType(OC.LocStart, CurrentType,
diag::err_offsetof_incomplete_type))
return ExprError();
-
+
// Look for the designated field.
const RecordType *RC = CurrentType->getAs<RecordType>();
- if (!RC)
+ if (!RC)
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
<< CurrentType);
RecordDecl *RD = RC->getDecl();
-
+
// C++ [lib.support.types]p5:
// The macro offsetof accepts a restricted set of type arguments in this
// International Standard. type shall be a POD structure or a POD union
@@ -12675,7 +13122,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
<< CurrentType))
DidWarnAboutNonPOD = true;
}
-
+
// Look for the field.
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
LookupQualifiedName(R, RD);
@@ -12688,9 +13135,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
if (!MemberDecl)
return ExprError(Diag(BuiltinLoc, diag::err_no_member)
- << OC.U.IdentInfo << RD << SourceRange(OC.LocStart,
+ << OC.U.IdentInfo << RD << SourceRange(OC.LocStart,
OC.LocEnd));
-
+
// C99 7.17p3:
// (If the specified member is a bit-field, the behavior is undefined.)
//
@@ -12733,9 +13180,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
} else
Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
- CurrentType = MemberDecl->getType().getNonReferenceType();
+ CurrentType = MemberDecl->getType().getNonReferenceType();
}
-
+
return OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, TInfo,
Comps, Exprs, RParenLoc);
}
@@ -12746,7 +13193,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
ParsedType ParsedArgTy,
ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
-
+
TypeSourceInfo *ArgTInfo;
QualType ArgTy = GetTypeFromParser(ParsedArgTy, &ArgTInfo);
if (ArgTy.isNull())
@@ -12784,7 +13231,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
CondExpr = CondICE.get();
CondIsTrue = condEval.getZExtValue();
- // If the condition is > zero, then the AST type is the same as the LSHExpr.
+ // If the condition is > zero, then the AST type is the same as the LHSExpr.
Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
@@ -12851,7 +13298,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
T = Context.getFunctionType(Context.DependentTy, None, EPI);
Sig = Context.getTrivialTypeSourceInfo(T);
}
-
+
// GetTypeForDeclarator always produces a function type for a block
// literal signature. Furthermore, it is always a FunctionProtoType
// unless the function was written with a typedef.
@@ -12929,7 +13376,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
CheckParmsForFunctionDef(CurBlock->TheDecl->parameters(),
/*CheckParameterNames=*/false);
}
-
+
// Finally we can process decl attributes.
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
@@ -12990,7 +13437,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// Set the captured variables on the block.
// FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
SmallVector<BlockDecl::Capture, 4> Captures;
- for (CapturingScopeInfo::Capture &Cap : BSI->Captures) {
+ for (Capture &Cap : BSI->Captures) {
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
@@ -13005,7 +13452,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
FunctionType::ExtInfo Ext = FTy->getExtInfo();
if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
-
+
// Turn protoless block types into nullary block types.
if (isa<FunctionNoProtoType>(FTy)) {
FunctionProtoType::ExtProtoInfo EPI;
@@ -13053,7 +13500,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
!BSI->TheDecl->isDependentContext())
computeNRVO(Body, BSI);
-
+
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
@@ -13070,7 +13517,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
for (const auto &CI : Result->getBlockDecl()->captures()) {
const VarDecl *var = CI.getVariable();
if (var->getType().isDestructedType() != QualType::DK_none) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
break;
}
}
@@ -13227,7 +13674,7 @@ bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
if (!ID || !ID->getIdentifier()->isStr("NSString"))
return false;
}
-
+
// Ignore any parens, implicit casts (should only be
// array-to-pointer decays), and not-so-opaque values. The last is
// important for making this trigger for property assignments.
@@ -13336,7 +13783,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::err_typecheck_incompatible_address_space;
break;
-
} else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) {
DiagKind = diag::err_typecheck_incompatible_ownership;
break;
@@ -13460,8 +13906,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (DiagKind == diag::warn_incompatible_qualified_id &&
PDecl && IFace && !IFace->hasDefinition())
Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
- << IFace->getName() << PDecl->getName();
-
+ << IFace << PDecl;
+
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
FirstType, /*TakingAddress=*/true);
@@ -13471,7 +13917,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (Action == AA_Returning && ConvTy == IncompatiblePointer)
EmitRelatedResultTypeNoteForReturn(DstType);
-
+
if (Complained)
*Complained = true;
return isInvalid;
@@ -13485,7 +13931,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR;
}
} Diagnoser;
-
+
return VerifyIntegerConstantExpression(E, Result, Diagnoser);
}
@@ -13495,16 +13941,16 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
bool AllowFold) {
class IDDiagnoser : public VerifyICEDiagnoser {
unsigned DiagID;
-
+
public:
IDDiagnoser(unsigned DiagID)
: VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { }
-
+
void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, DiagID) << SR;
}
} Diagnoser(DiagID);
-
+
return VerifyIntegerConstantExpression(E, Result, Diagnoser, AllowFold);
}
@@ -13701,22 +14147,22 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) {
}
void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- Decl *LambdaContextDecl,
- bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
+ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
- LambdaContextDecl, IsDecltype);
+ LambdaContextDecl, ExprContext);
Cleanup.reset();
if (!MaybeODRUseExprs.empty())
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
}
void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- ReuseLambdaContextDecl_t,
- bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
- PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+ PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
}
void Sema::PopExpressionEvaluationContext() {
@@ -13724,30 +14170,30 @@ void Sema::PopExpressionEvaluationContext() {
unsigned NumTypos = Rec.NumTypos;
if (!Rec.Lambdas.empty()) {
- if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+ using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
+ if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() ||
+ (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) {
unsigned D;
if (Rec.isUnevaluated()) {
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
D = diag::err_lambda_unevaluated_operand;
- } else {
+ } else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17) {
// C++1y [expr.const]p2:
// A conditional-expression e is a core constant expression unless the
// evaluation of e, following the rules of the abstract machine, would
// evaluate [...] a lambda-expression.
D = diag::err_lambda_in_constant_expression;
- }
+ } else if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument) {
+ // C++17 [expr.prim.lamda]p2:
+ // A lambda-expression shall not appear [...] in a template-argument.
+ D = diag::err_lambda_in_invalid_context;
+ } else
+ llvm_unreachable("Couldn't infer lambda error message.");
- // C++1z allows lambda expressions as core constant expressions.
- // FIXME: In C++1z, reinstate the restrictions on lambda expressions (CWG
- // 1607) from appearing within template-arguments and array-bounds that
- // 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().CPlusPlus17)
- for (const auto *L : Rec.Lambdas)
- Diag(L->getLocStart(), D);
+ for (const auto *L : Rec.Lambdas)
+ Diag(L->getLocStart(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
@@ -13806,13 +14252,13 @@ static bool isEvaluatableContext(Sema &SemaRef) {
switch (SemaRef.ExprEvalContexts.back().Context) {
case Sema::ExpressionEvaluationContext::Unevaluated:
case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
- case Sema::ExpressionEvaluationContext::DiscardedStatement:
// Expressions in this context are never evaluated.
return false;
case Sema::ExpressionEvaluationContext::UnevaluatedList:
case Sema::ExpressionEvaluationContext::ConstantEvaluated:
case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
+ case Sema::ExpressionEvaluationContext::DiscardedStatement:
// Expressions in this context could be evaluated.
return true;
@@ -13856,7 +14302,7 @@ static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) {
(Func->isImplicitlyInstantiable() || (MD && !MD->isUserProvided()));
}
-/// \brief Mark a function referenced, and check whether it is odr-used
+/// Mark a function referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3)
void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
bool MightBeOdrUse) {
@@ -14070,26 +14516,26 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
// capture.
}
-
-static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var,
+
+static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var,
bool &SubCapturesAreNested,
- QualType &CaptureType,
+ QualType &CaptureType,
QualType &DeclRefType) {
// Check whether we've already captured it.
if (CSI->CaptureMap.count(Var)) {
// If we found a capture, any subcaptures are nested.
SubCapturesAreNested = true;
-
+
// Retrieve the capture type for this variable.
CaptureType = CSI->getCapture(Var).getCaptureType();
-
+
// Compute the type of an expression that refers to this variable.
DeclRefType = CaptureType.getNonReferenceType();
// Similarly to mutable captures in lambda, all the OpenMP captures by copy
// are mutable in the sense that user can change their value - they are
// private instances of the captured declarations.
- const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+ const Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
!(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) &&
!(isa<CapturedRegionScopeInfo>(CSI) &&
@@ -14102,8 +14548,8 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
-static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,
- SourceLocation Loc,
+static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,
+ SourceLocation Loc,
const bool Diagnose, Sema &S) {
if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))
return getLambdaAwareParentOfDeclContext(DC);
@@ -14114,11 +14560,11 @@ static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *
return nullptr;
}
-// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
// certain types of variables (unnamed, variably modified types etc.)
// so check for eligibility.
-static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
- SourceLocation Loc,
+static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
+ SourceLocation Loc,
const bool Diagnose, Sema &S) {
bool IsBlock = isa<BlockScopeInfo>(CSI);
@@ -14140,7 +14586,7 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
if (Var->getType()->isVariablyModifiedType() && IsBlock) {
if (Diagnose) {
S.Diag(Loc, diag::err_ref_vm_type);
- S.Diag(Var->getLocation(), diag::note_previous_decl)
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
@@ -14185,21 +14631,21 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
}
// Returns true if the capture by block was successful.
-static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
- SourceLocation Loc,
- const bool BuildAndDiagnose,
+static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType,
+ QualType &DeclRefType,
const bool Nested,
Sema &S) {
Expr *CopyExpr = nullptr;
bool ByRef = false;
-
+
// Blocks are not allowed to capture arrays.
if (CaptureType->isArrayType()) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_ref_array_type);
- S.Diag(Var->getLocation(), diag::note_previous_decl)
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
@@ -14242,30 +14688,6 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
if (BuildAndDiagnose) {
SourceLocation VarLoc = Var->getLocation();
S.Diag(Loc, diag::warn_block_capture_autoreleasing);
- {
- auto AddAutoreleaseNote =
- S.Diag(VarLoc, diag::note_declare_parameter_autoreleasing);
- // Provide a fix-it for the '__autoreleasing' keyword at the
- // appropriate location in the variable's type.
- if (const auto *TSI = Var->getTypeSourceInfo()) {
- PointerTypeLoc PTL =
- TSI->getTypeLoc().getAsAdjusted<PointerTypeLoc>();
- if (PTL) {
- SourceLocation Loc = PTL.getPointeeLoc().getEndLoc();
- Loc = Lexer::getLocForEndOfToken(Loc, 0, S.getSourceManager(),
- S.getLangOpts());
- if (Loc.isValid()) {
- StringRef CharAtLoc = Lexer::getSourceText(
- CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(1)),
- S.getSourceManager(), S.getLangOpts());
- AddAutoreleaseNote << FixItHint::CreateInsertion(
- Loc, CharAtLoc.empty() || !isWhitespace(CharAtLoc[0])
- ? " __autoreleasing "
- : " __autoreleasing");
- }
- }
- }
- }
S.Diag(VarLoc, diag::note_declare_parameter_strong);
}
}
@@ -14273,7 +14695,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
if (HasBlocksAttr || CaptureType->isReferenceType() ||
- (S.getLangOpts().OpenMP && S.IsOpenMPCapturedDecl(Var))) {
+ (S.getLangOpts().OpenMP && S.isOpenMPCapturedDecl(Var))) {
// Block capture by reference does not change the capture or
// declaration reference types.
ByRef = true;
@@ -14281,7 +14703,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
// Block capture by copy introduces 'const'.
CaptureType = CaptureType.getNonReferenceType().withConst();
DeclRefType = CaptureType;
-
+
if (S.getLangOpts().CPlusPlus && BuildAndDiagnose) {
if (const RecordType *Record = DeclRefType->getAs<RecordType>()) {
// The capture logic needs the destructor, so make sure we mark it.
@@ -14301,15 +14723,15 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
// the stack requires a const copy constructor. This is not true
// of the copy/move done to move a __block variable to the heap.
Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested,
- DeclRefType.withConst(),
+ DeclRefType.withConst(),
VK_LValue, Loc);
-
+
ExprResult Result
= S.PerformCopyInitialization(
InitializedEntity::InitializeBlock(Var->getLocation(),
CaptureType, false),
Loc, DeclRef);
-
+
// Build a full-expression copy expression if initialization
// succeeded and used a non-trivial constructor. Recover from
// errors by pretending that the copy isn't necessary.
@@ -14325,7 +14747,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
// Actually capture the variable.
if (BuildAndDiagnose)
- BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
+ BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
SourceLocation(), CaptureType, CopyExpr);
return true;
@@ -14333,27 +14755,27 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
}
-/// \brief Capture the given variable in the captured region.
+/// Capture the given variable in the captured region.
static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
- VarDecl *Var,
- SourceLocation Loc,
- const bool BuildAndDiagnose,
+ VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType,
+ QualType &DeclRefType,
const bool RefersToCapturedVariable,
Sema &S) {
// By default, capture variables by reference.
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);
+ ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
}
if (ByRef)
@@ -14377,7 +14799,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
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);
Var->setReferenced(true);
@@ -14388,14 +14810,14 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
if (BuildAndDiagnose)
RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToCapturedVariable, Loc,
SourceLocation(), CaptureType, CopyExpr);
-
-
+
+
return true;
}
-/// \brief Create a field within the lambda class for the variable
+/// Create a field within the lambda class for the variable
/// being captured.
-static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
+static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
QualType FieldType, QualType DeclRefType,
SourceLocation Loc,
bool RefersToCapturedVariable) {
@@ -14411,15 +14833,15 @@ static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
Lambda->addDecl(Field);
}
-/// \brief Capture the given variable in the lambda.
+/// Capture the given variable in the lambda.
static bool captureInLambda(LambdaScopeInfo *LSI,
- VarDecl *Var,
- SourceLocation Loc,
- const bool BuildAndDiagnose,
+ VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType,
+ QualType &DeclRefType,
const bool RefersToCapturedVariable,
- const Sema::TryCaptureKind Kind,
+ const Sema::TryCaptureKind Kind,
SourceLocation EllipsisLoc,
const bool IsTopScope,
Sema &S) {
@@ -14431,7 +14853,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
} else {
ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
}
-
+
// Compute the type of the field that will capture this variable.
if (ByRef) {
// C++11 [expr.prim.lambda]p15:
@@ -14443,7 +14865,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
//
// FIXME: It is not clear whether we want to build an lvalue reference
// to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
- // to do the former, while EDG does the latter. Core issue 1249 will
+ // to do the former, while EDG does the latter. Core issue 1249 will
// clarify, but for now we follow GCC because it's a more permissive and
// easily defensible position.
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
@@ -14491,26 +14913,26 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
if (BuildAndDiagnose)
addAsFieldToClosureType(S, LSI, CaptureType, DeclRefType, Loc,
RefersToCapturedVariable);
-
+
// Compute the type of a reference to this captured variable.
if (ByRef)
DeclRefType = CaptureType.getNonReferenceType();
else {
// C++ [expr.prim.lambda]p5:
- // The closure type for a lambda-expression has a public inline
- // function call operator [...]. This function call operator is
- // declared const (9.3.1) if and only if the lambda-expression's
+ // The closure type for a lambda-expression has a public inline
+ // function call operator [...]. This function call operator is
+ // declared const (9.3.1) if and only if the lambda-expression's
// parameter-declaration-clause is not followed by mutable.
DeclRefType = CaptureType.getNonReferenceType();
if (!LSI->Mutable && !CaptureType->isReferenceType())
- DeclRefType.addConst();
+ DeclRefType.addConst();
}
-
+
// Add the capture.
if (BuildAndDiagnose)
- LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable,
+ LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable,
Loc, EllipsisLoc, CaptureType, /*CopyExpr=*/nullptr);
-
+
return true;
}
@@ -14523,10 +14945,10 @@ bool Sema::tryCaptureVariable(
DeclContext *VarDC = Var->getDeclContext();
if (Var->isInitCapture())
VarDC = VarDC->getParent();
-
+
DeclContext *DC = CurContext;
- const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
- ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
// We need to sync up the Declaration Context with the
// FunctionScopeIndexToStopAt
if (FunctionScopeIndexToStopAt) {
@@ -14537,7 +14959,7 @@ bool Sema::tryCaptureVariable(
}
}
-
+
// If the variable is declared in the current context, there is no need to
// capture it.
if (VarDC == DC) return true;
@@ -14545,7 +14967,7 @@ bool Sema::tryCaptureVariable(
// Capture global variables if it is required to use private copy of this
// variable.
bool IsGlobal = !Var->hasLocalStorage();
- if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedDecl(Var)))
+ if (IsGlobal && !(LangOpts.OpenMP && isOpenMPCapturedDecl(Var)))
return true;
Var = Var->getCanonicalDecl();
@@ -14553,7 +14975,7 @@ bool Sema::tryCaptureVariable(
// performing the "simple" checks that don't depend on type. We stop when
// we've either hit the declared scope of the variable or find an existing
// capture of that variable. We start from the innermost capturing-entity
- // (the DC) and ensure that all intervening capturing-entities
+ // (the DC) and ensure that all intervening capturing-entities
// (blocks/lambdas etc.) between the innermost capturer and the variable`s
// declcontext can either capture the variable or have already captured
// the variable.
@@ -14565,8 +14987,8 @@ bool Sema::tryCaptureVariable(
do {
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
- DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var,
- ExprLoc,
+ DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var,
+ ExprLoc,
BuildAndDiagnose,
*this);
// We need to check for the parent *first* because, if we *have*
@@ -14585,29 +15007,29 @@ bool Sema::tryCaptureVariable(
// Check whether we've already captured it.
- if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
+ if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
DeclRefType)) {
CSI->getCapture(Var).markUsed(BuildAndDiagnose);
break;
}
- // If we are instantiating a generic lambda call operator body,
+ // If we are instantiating a generic lambda call operator body,
// we do not want to capture new variables. What was captured
// during either a lambdas transformation or initial parsing
- // should be used.
+ // should be used.
if (isGenericLambdaCallOperatorSpecialization(DC)) {
if (BuildAndDiagnose) {
- LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
+ Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
- Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl);
+ Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl);
} else
diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
}
return true;
}
- // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+ // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
// certain types of variables (unnamed, variably modified types etc.)
// so check for eligibility.
if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this))
@@ -14648,11 +15070,11 @@ bool Sema::tryCaptureVariable(
}
}
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
- // No capture-default, and this is not an explicit capture
- // so cannot capture this variable.
+ // No capture-default, and this is not an explicit capture
+ // so cannot capture this variable.
if (BuildAndDiagnose) {
Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
+ Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
if (cast<LambdaScopeInfo>(CSI)->Lambda)
Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(),
@@ -14661,12 +15083,12 @@ bool Sema::tryCaptureVariable(
// capture a variable that an inner lambda explicitly captures, we
// should have the inner lambda do the explicit capture - because
// it makes for cleaner diagnostics later. This would purely be done
- // so that the diagnostic does not misleadingly claim that a variable
- // can not be captured by a lambda implicitly even though it is captured
+ // so that the diagnostic does not misleadingly claim that a variable
+ // can not be captured by a lambda implicitly even though it is captured
// explicitly. Suggestion:
- // - create const bool VariableCaptureWasInitiallyExplicit = Explicit
+ // - create const bool VariableCaptureWasInitiallyExplicit = Explicit
// at the function head
- // - cache the StartingDeclContext - this must be a lambda
+ // - cache the StartingDeclContext - this must be a lambda
// - captureInLambda in the innermost lambda the variable.
}
return true;
@@ -14678,31 +15100,31 @@ bool Sema::tryCaptureVariable(
} while (!VarDC->Equals(DC));
// Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
- // computing the type of the capture at each step, checking type-specific
- // requirements, and adding captures if requested.
- // If the variable had already been captured previously, we start capturing
- // at the lambda nested within that one.
- for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N;
+ // computing the type of the capture at each step, checking type-specific
+ // requirements, and adding captures if requested.
+ // If the variable had already been captured previously, we start capturing
+ // at the lambda nested within that one.
+ for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N;
++I) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]);
-
+
if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) {
- if (!captureInBlock(BSI, Var, ExprLoc,
- BuildAndDiagnose, CaptureType,
+ if (!captureInBlock(BSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
DeclRefType, Nested, *this))
return true;
Nested = true;
} else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
- if (!captureInCapturedRegion(RSI, Var, ExprLoc,
- BuildAndDiagnose, CaptureType,
+ if (!captureInCapturedRegion(RSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
DeclRefType, Nested, *this))
return true;
Nested = true;
} else {
LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
- if (!captureInLambda(LSI, Var, ExprLoc,
- BuildAndDiagnose, CaptureType,
- DeclRefType, Nested, Kind, EllipsisLoc,
+ if (!captureInLambda(LSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, Kind, EllipsisLoc,
/*IsTopScope*/I == N - 1, *this))
return true;
Nested = true;
@@ -14712,7 +15134,7 @@ bool Sema::tryCaptureVariable(
}
bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
- TryCaptureKind Kind, SourceLocation EllipsisLoc) {
+ TryCaptureKind Kind, SourceLocation EllipsisLoc) {
QualType CaptureType;
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
@@ -14731,10 +15153,10 @@ bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) {
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
QualType CaptureType;
QualType DeclRefType;
-
+
// Determine whether we can capture this variable.
if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
- /*BuildAndDiagnose=*/false, CaptureType,
+ /*BuildAndDiagnose=*/false, CaptureType,
DeclRefType, nullptr))
return QualType();
@@ -14743,49 +15165,49 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
-// If either the type of the variable or the initializer is dependent,
+// If either the type of the variable or the initializer is dependent,
// return false. Otherwise, determine whether the variable is a constant
// expression. Use this if you need to know if a variable that might or
// might not be dependent is truly a constant expression.
-static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
+static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
ASTContext &Context) {
-
- if (Var->getType()->isDependentType())
+
+ if (Var->getType()->isDependentType())
return false;
const VarDecl *DefVD = nullptr;
Var->getAnyInitializer(DefVD);
- if (!DefVD)
+ if (!DefVD)
return false;
EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();
Expr *Init = cast<Expr>(Eval->Value);
- if (Init->isValueDependent())
+ if (Init->isValueDependent())
return false;
- return IsVariableAConstantExpression(Var, Context);
+ return IsVariableAConstantExpression(Var, Context);
}
void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
- // Per C++11 [basic.def.odr], a variable is odr-used "unless it is
+ // Per C++11 [basic.def.odr], a variable is odr-used "unless it is
// an object that satisfies the requirements for appearing in a
// constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
// is immediately applied." This function handles the lvalue-to-rvalue
// conversion part.
MaybeODRUseExprs.erase(E->IgnoreParens());
-
+
// If we are in a lambda, check if this DeclRefExpr or MemberExpr refers
// to a variable that is a constant expression, and if so, identify it as
- // a reference to a variable that does not involve an odr-use of that
- // variable.
+ // a reference to a variable that does not involve an odr-use of that
+ // variable.
if (LambdaScopeInfo *LSI = getCurLambda()) {
Expr *SansParensExpr = E->IgnoreParens();
VarDecl *Var = nullptr;
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
Var = dyn_cast<VarDecl>(ME->getMemberDecl());
-
- if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context))
- LSI->markVariableExprAsNonODRUsed(SansParensExpr);
+
+ if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context))
+ LSI->markVariableExprAsNonODRUsed(SansParensExpr);
}
}
@@ -14910,7 +15332,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// A reference initialized by a constant expression can never be
// odr-used, so simply ignore it.
if (!Var->getType()->isReferenceType() ||
- (SemaRef.LangOpts.OpenMP && SemaRef.IsOpenMPCapturedDecl(Var)))
+ (SemaRef.LangOpts.OpenMP && SemaRef.isOpenMPCapturedDecl(Var)))
SemaRef.MaybeODRUseExprs.insert(E);
} else if (OdrUseContext) {
MarkVarDeclODRUsed(Var, Loc, SemaRef,
@@ -14945,7 +15367,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
}
}
-/// \brief Mark a variable referenced, and check whether it is odr-used
+/// Mark a variable referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be
/// used directly for normal expressions referring to VarDecl.
void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
@@ -14986,7 +15408,7 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse);
}
-/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
+/// Perform reference-marking and odr-use handling for a DeclRefExpr.
void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
// TODO: update this with DR# once a defect report is filed.
// C++11 defect. The address of a pure member should not be an ODR use, even
@@ -14999,7 +15421,7 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
}
-/// \brief Perform reference-marking and odr-use handling for a MemberExpr.
+/// Perform reference-marking and odr-use handling for a MemberExpr.
void Sema::MarkMemberReferenced(MemberExpr *E) {
// C++11 [basic.def.odr]p2:
// A non-overloaded function whose name appears as a potentially-evaluated
@@ -15018,7 +15440,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse);
}
-/// \brief Perform marking for a reference to an arbitrary declaration. It
+/// Perform marking for a reference to an arbitrary declaration. It
/// marks the declaration referenced, and performs odr-use checking for
/// functions and variables. This method should not be used when building a
/// normal expression which refers to a variable.
@@ -15081,18 +15503,18 @@ void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
}
namespace {
- /// \brief Helper class that marks all of the declarations referenced by
+ /// Helper class that marks all of the declarations referenced by
/// potentially-evaluated subexpressions as "referenced".
class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> {
Sema &S;
bool SkipLocalVariables;
-
+
public:
typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited;
-
- EvaluatedExprMarker(Sema &S, bool SkipLocalVariables)
+
+ EvaluatedExprMarker(Sema &S, bool SkipLocalVariables)
: Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { }
-
+
void VisitDeclRefExpr(DeclRefExpr *E) {
// If we were asked not to visit local variables, don't.
if (SkipLocalVariables) {
@@ -15100,7 +15522,7 @@ namespace {
if (VD->hasLocalStorage())
return;
}
-
+
S.MarkDeclRefReferenced(E);
}
@@ -15108,13 +15530,13 @@ namespace {
S.MarkMemberReferenced(E);
Inherited::VisitMemberExpr(E);
}
-
+
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
S.MarkFunctionReferenced(E->getLocStart(),
const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor()));
Visit(E->getSubExpr());
}
-
+
void VisitCXXNewExpr(CXXNewExpr *E) {
if (E->getOperatorNew())
S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew());
@@ -15129,18 +15551,18 @@ namespace {
QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- S.MarkFunctionReferenced(E->getLocStart(),
+ S.MarkFunctionReferenced(E->getLocStart(),
S.LookupDestructor(Record));
}
-
+
Inherited::VisitCXXDeleteExpr(E);
}
-
+
void VisitCXXConstructExpr(CXXConstructExpr *E) {
S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor());
Inherited::VisitCXXConstructExpr(E);
}
-
+
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
Visit(E->getExpr());
}
@@ -15154,17 +15576,17 @@ namespace {
};
}
-/// \brief Mark any declarations that appear within this expression or any
+/// Mark any declarations that appear within this expression or any
/// potentially-evaluated subexpressions as "referenced".
///
-/// \param SkipLocalVariables If true, don't mark local variables as
+/// \param SkipLocalVariables If true, don't mark local variables as
/// 'referenced'.
-void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
+void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
bool SkipLocalVariables) {
EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E);
}
-/// \brief Emit a diagnostic that describes an effect on the run-time behavior
+/// Emit a diagnostic that describes an effect on the run-time behavior
/// of the program being compiled.
///
/// This routine emits the given diagnostic when the code currently being
@@ -15230,7 +15652,8 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
// If we're inside a decltype's expression, don't check for a valid return
// type or construct temporaries until we know whether this is the last call.
- if (ExprEvalContexts.back().IsDecltype) {
+ if (ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype) {
ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE);
return false;
}
@@ -15238,7 +15661,7 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
class CallReturnIncompleteDiagnoser : public TypeDiagnoser {
FunctionDecl *FD;
CallExpr *CE;
-
+
public:
CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE)
: FD(FD), CE(CE) { }
@@ -15249,14 +15672,14 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
<< T << CE->getSourceRange();
return;
}
-
+
S.Diag(Loc, diag::err_call_function_incomplete_return)
<< CE->getSourceRange() << FD->getDeclName() << T;
S.Diag(FD->getLocation(), diag::note_entity_declared_at)
<< FD->getDeclName();
}
} Diagnoser(FD, CE);
-
+
if (RequireCompleteType(Loc, ReturnType, Diagnoser))
return true;
@@ -15321,7 +15744,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
<< FixItHint::CreateReplacement(Loc, "==");
}
-/// \brief Redundant parentheses over an equality comparison can indicate
+/// Redundant parentheses over an equality comparison can indicate
/// that the user intended an assignment used as condition.
void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
// Don't warn if the parens came from a macro.
@@ -15339,7 +15762,7 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context)
== Expr::MLV_Valid) {
SourceLocation Loc = opE->getOperatorLoc();
-
+
Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange();
SourceRange ParenERange = ParenE->getSourceRange();
Diag(Loc, diag::note_equality_comparison_silence)
@@ -15676,7 +16099,7 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
}
// Rebuild the appropriate pointer-to-function type.
- switch (Kind) {
+ switch (Kind) {
case FK_MemberFunction:
// Nothing to do.
break;
@@ -15725,15 +16148,15 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_FunctionToPointerDecay) {
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
-
+
E->setType(DestType);
-
+
// Rebuild the sub-expression as the pointee (function) type.
DestType = DestType->castAs<PointerType>()->getPointeeType();
-
+
ExprResult Result = Visit(E->getSubExpr());
if (!Result.isUsable()) return ExprError();
-
+
E->setSubExpr(Result.get());
return E;
} else if (E->getCastKind() == CK_LValueToRValue) {
@@ -15795,7 +16218,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
SC_None, false/*isInlineSpecified*/,
FD->hasPrototype(),
false/*isConstexprSpecified*/);
-
+
if (FD->getQualifier())
NewFD->setQualifierInfo(FD->getQualifierLoc());
@@ -16063,7 +16486,7 @@ Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
Sema::LookupOrdinaryName);
if (LookupName(Result, getCurScope()) && Result.isSingleResult()) {
NamedDecl *ND = Result.getFoundDecl();
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))
Context.setBOOLDecl(TD);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 89055aecd4b6..c851a81af464 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements semantic analysis for C++ expressions.
+/// Implements semantic analysis for C++ expressions.
///
//===----------------------------------------------------------------------===//
@@ -42,7 +42,7 @@
using namespace clang;
using namespace sema;
-/// \brief Handle the result of the special case name lookup for inheriting
+/// Handle the result of the special case name lookup for inheriting
/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as
/// constructor names in member using declarations, even if 'X' is not the
/// name of the corresponding type.
@@ -80,6 +80,56 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
Context.getTrivialTypeSourceInfo(Type, NameLoc));
}
+ParsedType Sema::getConstructorName(IdentifierInfo &II,
+ SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext) {
+ CXXRecordDecl *CurClass = getCurrentClass(S, &SS);
+ assert(CurClass && &II == CurClass->getIdentifier() &&
+ "not a constructor name");
+
+ // When naming a constructor as a member of a dependent context (eg, in a
+ // friend declaration or an inherited constructor declaration), form an
+ // unresolved "typename" type.
+ if (CurClass->isDependentContext() && !EnteringContext) {
+ QualType T = Context.getDependentNameType(ETK_None, SS.getScopeRep(), &II);
+ return ParsedType::make(T);
+ }
+
+ if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass))
+ return ParsedType();
+
+ // Find the injected-class-name declaration. Note that we make no attempt to
+ // diagnose cases where the injected-class-name is shadowed: the only
+ // declaration that can validly shadow the injected-class-name is a
+ // non-static data member, and if the class contains both a non-static data
+ // member and a constructor then it is ill-formed (we check that in
+ // CheckCompletedCXXClass).
+ CXXRecordDecl *InjectedClassName = nullptr;
+ for (NamedDecl *ND : CurClass->lookup(&II)) {
+ auto *RD = dyn_cast<CXXRecordDecl>(ND);
+ if (RD && RD->isInjectedClassName()) {
+ InjectedClassName = RD;
+ break;
+ }
+ }
+ if (!InjectedClassName) {
+ if (!CurClass->isInvalidDecl()) {
+ // FIXME: RequireCompleteDeclContext doesn't check dependent contexts
+ // properly. Work around it here for now.
+ Diag(SS.getLastQualifierNameLoc(),
+ diag::err_incomplete_nested_name_spec) << CurClass << SS.getRange();
+ }
+ return ParsedType();
+ }
+
+ QualType T = Context.getTypeDeclType(InjectedClassName);
+ DiagnoseUseOfDecl(InjectedClassName, NameLoc);
+ MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false);
+
+ return ParsedType::make(T);
+}
+
ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
IdentifierInfo &II,
SourceLocation NameLoc,
@@ -383,7 +433,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
llvm_unreachable("unknown nested name specifier kind");
}
-/// \brief Build a C++ typeid expression with a type operand.
+/// Build a C++ typeid expression with a type operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
@@ -408,7 +458,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceRange(TypeidLoc, RParenLoc));
}
-/// \brief Build a C++ typeid expression with an expression operand.
+/// Build a C++ typeid expression with an expression operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
@@ -480,6 +530,12 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
ExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+ // OpenCL C++ 1.0 s2.9: typeid is not supported.
+ if (getLangOpts().OpenCLCPlusPlus) {
+ return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported)
+ << "typeid");
+ }
+
// Find the std::type_info type.
if (!getStdNamespace())
return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
@@ -560,7 +616,7 @@ getUuidAttrOfType(Sema &SemaRef, QualType QT,
}
}
-/// \brief Build a Microsoft __uuidof expression with a type operand.
+/// Build a Microsoft __uuidof expression with a type operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
@@ -580,7 +636,7 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceRange(TypeidLoc, RParenLoc));
}
-/// \brief Build a Microsoft __uuidof expression with an expression operand.
+/// Build a Microsoft __uuidof expression with an expression operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
@@ -695,7 +751,11 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
bool IsThrownVarInScope) {
// Don't report an error if 'throw' is used in system headers.
if (!getLangOpts().CXXExceptions &&
- !getSourceManager().isInSystemHeader(OpLoc))
+ !getSourceManager().isInSystemHeader(OpLoc) &&
+ (!getLangOpts().OpenMPIsDevice ||
+ !getLangOpts().OpenMPHostCXXExceptions ||
+ isInOpenMPTargetExecutionDirective() ||
+ isInOpenMPDeclareTargetContext()))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
// Exceptions aren't allowed in CUDA device code.
@@ -728,7 +788,7 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
// exception object
const VarDecl *NRVOVariable = nullptr;
if (IsThrownVarInScope)
- NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false);
+ NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeException(
OpLoc, ExceptionObjectTy,
@@ -1114,8 +1174,9 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value");
- const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?
- *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt
+ : FunctionScopes.size() - 1;
// Check that we can capture the *enclosing object* (referred to by '*this')
// by the capturing-entity/closure (lambda/block/etc) at
@@ -1141,7 +1202,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
unsigned NumCapturingClosures = 0;
- for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {
+ for (int idx = MaxFunctionScopesIndex; idx >= 0; idx--) {
if (CapturingScopeInfo *CSI =
dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {
if (CSI->CXXThisCaptureIndex != 0) {
@@ -1196,8 +1257,8 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
// FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
// contexts.
QualType ThisTy = getCurrentThisType();
- for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures;
- --idx, --NumCapturingClosures) {
+ for (int idx = MaxFunctionScopesIndex; NumCapturingClosures;
+ --idx, --NumCapturingClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
Expr *ThisExpr = nullptr;
@@ -1244,11 +1305,16 @@ bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
return Class && Class->isBeingDefined();
}
+/// Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
ExprResult
Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg exprs,
- SourceLocation RParenLoc) {
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization) {
if (!TypeRep)
return ExprError();
@@ -1257,7 +1323,8 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
- auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
+ auto Result = BuildCXXTypeConstructExpr(TInfo, LParenOrBraceLoc, exprs,
+ RParenOrBraceLoc, ListInitialization);
// Avoid creating a non-type-dependent expression that contains typos.
// Non-type-dependent expressions are liable to be discarded without
// checking for embedded typos.
@@ -1267,38 +1334,40 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
return Result;
}
-/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
-/// Can be interpreted either as function-style casting ("int(x)")
-/// or class type construction ("ClassType(x,y,z)")
-/// or creation of a value-initialized type ("int()").
ExprResult
Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg Exprs,
- SourceLocation RParenLoc) {
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization) {
QualType Ty = TInfo->getType();
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
- return CXXUnresolvedConstructExpr::Create(Context, TInfo, LParenLoc, Exprs,
- RParenLoc);
+ // FIXME: CXXUnresolvedConstructExpr does not model list-initialization
+ // directly. We work around this by dropping the locations of the braces.
+ SourceRange Locs = ListInitialization
+ ? SourceRange()
+ : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
+ return CXXUnresolvedConstructExpr::Create(Context, TInfo, Locs.getBegin(),
+ Exprs, Locs.getEnd());
}
- bool ListInitialization = LParenLoc.isInvalid();
assert((!ListInitialization ||
(Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) &&
"List initialization must have initializer list as expression.");
- SourceRange FullRange = SourceRange(TyBeginLoc,
- ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
+ SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc);
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
InitializationKind Kind =
Exprs.size()
? ListInitialization
- ? InitializationKind::CreateDirectList(TyBeginLoc)
- : InitializationKind::CreateDirect(TyBeginLoc, LParenLoc,
- RParenLoc)
- : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc);
+ ? InitializationKind::CreateDirectList(
+ TyBeginLoc, LParenOrBraceLoc, RParenOrBraceLoc)
+ : InitializationKind::CreateDirect(TyBeginLoc, LParenOrBraceLoc,
+ RParenOrBraceLoc)
+ : InitializationKind::CreateValue(TyBeginLoc, LParenOrBraceLoc,
+ RParenOrBraceLoc);
// C++1z [expr.type.conv]p1:
// If the type is a placeholder for a deduced class type, [...perform class
@@ -1319,7 +1388,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
if (Exprs.size() == 1 && !ListInitialization &&
!isa<InitListExpr>(Exprs[0])) {
Expr *Arg = Exprs[0];
- return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, RParenLoc);
+ return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenOrBraceLoc, Arg,
+ RParenOrBraceLoc);
}
// For an expression of the form T(), T shall not be an array type.
@@ -1367,15 +1437,18 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
// CXXTemporaryObjectExpr. It's also weird that the functional cast
// is sometimes handled by initialization and sometimes not.
QualType ResultType = Result.get()->getType();
+ SourceRange Locs = ListInitialization
+ ? SourceRange()
+ : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
Result = CXXFunctionalCastExpr::Create(
- Context, ResultType, Expr::getValueKindForType(Ty), TInfo,
- CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc);
+ Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp,
+ Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd());
}
return Result;
}
-/// \brief Determine whether the given function is a non-placement
+/// Determine whether the given function is a non-placement
/// deallocation function.
static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
@@ -1430,7 +1503,7 @@ namespace {
CUDAPref = S.IdentifyCUDAPreference(Caller, FD);
}
- operator bool() const { return FD; }
+ explicit operator bool() const { return FD; }
bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize,
bool WantAlign) const {
@@ -1543,7 +1616,7 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
return Best && Best.HasSizeT;
}
-/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
+/// Parsed a C++ 'new' expression (C++ 5.3.4).
///
/// E.g.:
/// @code new (memory) int[size][4] @endcode
@@ -1593,9 +1666,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (Expr *NumElts = (Expr *)Array.NumElts) {
if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) {
if (getLangOpts().CPlusPlus14) {
- // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
- // shall be a converted constant expression (5.19) of type std::size_t
- // and shall evaluate to a strictly positive value.
+ // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
+ // shall be a converted constant expression (5.19) of type std::size_t
+ // and shall evaluate to a strictly positive value.
unsigned IntWidth = Context.getTargetInfo().getIntWidth();
assert(IntWidth && "Builtin type of size 0?");
llvm::APSInt Value(IntWidth);
@@ -1674,9 +1747,9 @@ static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling(
S.getASTContext().getTargetInfo().getPlatformName());
- S.Diag(Loc, diag::warn_aligned_allocation_unavailable)
- << IsDelete << FD.getType().getAsString() << OSName
- << alignedAllocMinVersion(T.getOS()).getAsString();
+ S.Diag(Loc, diag::err_aligned_allocation_unavailable)
+ << IsDelete << FD.getType().getAsString() << OSName
+ << alignedAllocMinVersion(T.getOS()).getAsString();
S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable);
}
}
@@ -1728,7 +1801,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// - Otherwise, the new-initializer is interpreted according to the
// initialization rules of 8.5 for direct-initialization.
: initStyle == CXXNewExpr::ListInit
- ? InitializationKind::CreateDirectList(TypeRange.getBegin())
+ ? InitializationKind::CreateDirectList(TypeRange.getBegin(),
+ Initializer->getLocStart(),
+ Initializer->getLocEnd())
: InitializationKind::CreateDirect(TypeRange.getBegin(),
DirectInitRange.getBegin(),
DirectInitRange.getEnd());
@@ -1795,13 +1870,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
return ExprError();
- if (initStyle == CXXNewExpr::ListInit &&
- isStdInitializerList(AllocType, nullptr)) {
- Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
- diag::warn_dangling_std_initializer_list)
- << /*at end of FE*/0 << Inits[0]->getSourceRange();
- }
-
// In ARC, infer 'retaining' for the allocated
if (getLangOpts().ObjCAutoRefCount &&
AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -1831,7 +1899,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?");
ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
- AA_Converting);
+ AA_Converting);
if (!ConvertedSize.isInvalid() &&
ArraySize->getType()->getAs<RecordType>())
@@ -1960,11 +2028,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
bool PassAlignment = getLangOpts().AlignedAllocation &&
Alignment > NewAlignment;
+ AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both;
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
FindAllocationFunctions(StartLoc,
SourceRange(PlacementLParen, PlacementRParen),
- UseGlobal, AllocType, ArraySize, PassAlignment,
+ Scope, Scope, AllocType, ArraySize, PassAlignment,
PlacementArgs, OperatorNew, OperatorDelete))
return ExprError();
@@ -2099,7 +2168,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
Range, DirectInitRange);
}
-/// \brief Checks that a type is suitable as the allocated type
+/// Checks that a type is suitable as the allocated type
/// in a new-expression.
bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
SourceRange R) {
@@ -2120,7 +2189,8 @@ 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() != LangAS::Default)
+ else if (AllocType.getAddressSpace() != LangAS::Default &&
+ !getLangOpts().OpenCLCPlusPlus)
return Diag(Loc, diag::err_address_space_qualified_new)
<< AllocType.getUnqualifiedType()
<< AllocType.getQualifiers().getAddressSpaceAttributePrintValue();
@@ -2137,12 +2207,10 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
return false;
}
-static bool
-resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
- SmallVectorImpl<Expr *> &Args, bool &PassAlignment,
- FunctionDecl *&Operator,
- OverloadCandidateSet *AlignedCandidates = nullptr,
- Expr *AlignArg = nullptr) {
+static bool resolveAllocationOverload(
+ Sema &S, LookupResult &R, SourceRange Range, SmallVectorImpl<Expr *> &Args,
+ bool &PassAlignment, FunctionDecl *&Operator,
+ OverloadCandidateSet *AlignedCandidates, Expr *AlignArg, bool Diagnose) {
OverloadCandidateSet Candidates(R.getNameLoc(),
OverloadCandidateSet::CSK_Normal);
for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
@@ -2188,7 +2256,8 @@ resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
AlignArg = Args[1];
Args.erase(Args.begin() + 1);
return resolveAllocationOverload(S, R, Range, Args, PassAlignment,
- Operator, &Candidates, AlignArg);
+ Operator, &Candidates, AlignArg,
+ Diagnose);
}
// MSVC will fall back on trying to find a matching global operator new
@@ -2204,67 +2273,72 @@ resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl());
// FIXME: This will give bad diagnostics pointing at the wrong functions.
return resolveAllocationOverload(S, R, Range, Args, PassAlignment,
- Operator, nullptr);
+ Operator, /*Candidates=*/nullptr,
+ /*AlignArg=*/nullptr, Diagnose);
}
- S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
- << R.getLookupName() << Range;
-
- // If we have aligned candidates, only note the align_val_t candidates
- // from AlignedCandidates and the non-align_val_t candidates from
- // Candidates.
- if (AlignedCandidates) {
- auto IsAligned = [](OverloadCandidate &C) {
- return C.Function->getNumParams() > 1 &&
- C.Function->getParamDecl(1)->getType()->isAlignValT();
- };
- auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };
-
- // This was an overaligned allocation, so list the aligned candidates
- // first.
- Args.insert(Args.begin() + 1, AlignArg);
- AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "",
- R.getNameLoc(), IsAligned);
- Args.erase(Args.begin() + 1);
- Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(),
- IsUnaligned);
- } else {
- Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ if (Diagnose) {
+ S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
+ << R.getLookupName() << Range;
+
+ // If we have aligned candidates, only note the align_val_t candidates
+ // from AlignedCandidates and the non-align_val_t candidates from
+ // Candidates.
+ if (AlignedCandidates) {
+ auto IsAligned = [](OverloadCandidate &C) {
+ return C.Function->getNumParams() > 1 &&
+ C.Function->getParamDecl(1)->getType()->isAlignValT();
+ };
+ auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };
+
+ // This was an overaligned allocation, so list the aligned candidates
+ // first.
+ Args.insert(Args.begin() + 1, AlignArg);
+ AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "",
+ R.getNameLoc(), IsAligned);
+ Args.erase(Args.begin() + 1);
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(),
+ IsUnaligned);
+ } else {
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ }
}
return true;
case OR_Ambiguous:
- S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
- << R.getLookupName() << Range;
- Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ if (Diagnose) {
+ S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ }
return true;
case OR_Deleted: {
- S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
- << Best->Function->isDeleted()
- << R.getLookupName()
- << S.getDeletedOrUnavailableSuffix(Best->Function)
- << Range;
- Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ if (Diagnose) {
+ S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted() << R.getLookupName()
+ << S.getDeletedOrUnavailableSuffix(Best->Function) << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ }
return true;
}
}
llvm_unreachable("Unreachable, bad result from BestViableFunction");
}
-
-/// FindAllocationFunctions - Finds the overloads of operator new and delete
-/// that are appropriate for the allocation.
bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
- bool UseGlobal, QualType AllocType,
- bool IsArray, bool &PassAlignment,
- MultiExprArg PlaceArgs,
+ AllocationFunctionScope NewScope,
+ AllocationFunctionScope DeleteScope,
+ QualType AllocType, bool IsArray,
+ bool &PassAlignment, MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
- FunctionDecl *&OperatorDelete) {
+ FunctionDecl *&OperatorDelete,
+ bool Diagnose) {
// --- Choosing an allocation function ---
// C++ 5.3.4p8 - 14 & 18
- // 1) If UseGlobal is true, only look in the global scope. Else, also look
- // in the scope of the allocated class.
+ // 1) If looking in AFS_Global scope for allocation functions, only look in
+ // the global scope. Else, if AFS_Class, only look in the scope of the
+ // allocated class. If AFS_Both, look in both.
// 2) If an array size is given, look for operator new[], else look for
// operator new.
// 3) The first argument is always size_t. Append the arguments from the
@@ -2314,7 +2388,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// function's name is looked up in the global scope. Otherwise, if the
// allocated type is a class type T or array thereof, the allocation
// function's name is looked up in the scope of T.
- if (AllocElemType->isRecordType() && !UseGlobal)
+ if (AllocElemType->isRecordType() && NewScope != AFS_Global)
LookupQualifiedName(R, AllocElemType->getAsCXXRecordDecl());
// We can see ambiguity here if the allocation function is found in
@@ -2325,8 +2399,17 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// If this lookup fails to find the name, or if the allocated type is not
// a class type, the allocation function's name is looked up in the
// global scope.
- if (R.empty())
+ if (R.empty()) {
+ if (NewScope == AFS_Class)
+ return true;
+
LookupQualifiedName(R, Context.getTranslationUnitDecl());
+ }
+
+ if (getLangOpts().OpenCLCPlusPlus && R.empty()) {
+ Diag(StartLoc, diag::err_openclcxx_not_supported) << "default new";
+ return true;
+ }
assert(!R.empty() && "implicitly declared allocation functions not found");
assert(!R.isAmbiguous() && "global allocation functions are ambiguous");
@@ -2335,7 +2418,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
R.suppressDiagnostics();
if (resolveAllocationOverload(*this, R, Range, AllocArgs, PassAlignment,
- OperatorNew))
+ OperatorNew, /*Candidates=*/nullptr,
+ /*AlignArg=*/nullptr, Diagnose))
return true;
}
@@ -2362,7 +2446,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// the allocated type is not a class type or array thereof, the
// deallocation function's name is looked up in the global scope.
LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
- if (AllocElemType->isRecordType() && !UseGlobal) {
+ if (AllocElemType->isRecordType() && DeleteScope != AFS_Global) {
CXXRecordDecl *RD
= cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
LookupQualifiedName(FoundDelete, RD);
@@ -2372,6 +2456,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
bool FoundGlobalDelete = FoundDelete.empty();
if (FoundDelete.empty()) {
+ if (DeleteScope == AFS_Class)
+ return true;
+
DeclareGlobalNewDelete();
LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
}
@@ -2559,6 +2646,11 @@ void Sema::DeclareGlobalNewDelete() {
if (GlobalNewDeleteDeclared)
return;
+ // OpenCL C++ 1.0 s2.9: the implicitly declared new and delete operators
+ // are not supported.
+ if (getLangOpts().OpenCLCPlusPlus)
+ return;
+
// C++ [basic.std.dynamic]p2:
// [...] The following allocation and deallocation functions (18.4) are
// implicitly declared in global scope in each translation unit of a
@@ -2845,7 +2937,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
}
namespace {
-/// \brief Checks whether delete-expression, and new-expression used for
+/// Checks whether delete-expression, and new-expression used for
/// initializing deletee have the same array form.
class MismatchingNewDeleteDetector {
public:
@@ -2868,7 +2960,7 @@ public:
: Field(nullptr), IsArrayForm(false), EndOfTU(EndOfTU),
HasUndefinedConstructors(false) {}
- /// \brief Checks whether pointee of a delete-expression is initialized with
+ /// Checks whether pointee of a delete-expression is initialized with
/// matching form of new-expression.
///
/// If return value is \c VarInitMismatches or \c MemberInitMismatches at the
@@ -2879,7 +2971,7 @@ public:
/// couldn't be analyzed. If at least one constructor initializes the member
/// with matching type of new, the return value is \c NoMismatch.
MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE);
- /// \brief Analyzes a class member.
+ /// Analyzes a class member.
/// \param Field Class member to analyze.
/// \param DeleteWasArrayForm Array form-ness of the delete-expression used
/// for deleting the \p Field.
@@ -2892,13 +2984,13 @@ public:
private:
const bool EndOfTU;
- /// \brief Indicates that there is at least one constructor without body.
+ /// Indicates that there is at least one constructor without body.
bool HasUndefinedConstructors;
- /// \brief Returns \c CXXNewExpr from given initialization expression.
+ /// Returns \c CXXNewExpr from given initialization expression.
/// \param E Expression used for initializing pointee in delete-expression.
/// E can be a single-element \c InitListExpr consisting of new-expression.
const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E);
- /// \brief Returns whether member is initialized with mismatching form of
+ /// Returns whether member is initialized with mismatching form of
/// \c new either by the member initializer or in-class initialization.
///
/// If bodies of all constructors are not visible at the end of translation
@@ -2906,7 +2998,7 @@ private:
/// form of \c new, mismatch cannot be proven, and this function will return
/// \c NoMismatch.
MismatchResult analyzeMemberExpr(const MemberExpr *ME);
- /// \brief Returns whether variable is initialized with mismatching form of
+ /// Returns whether variable is initialized with mismatching form of
/// \c new.
///
/// If variable is initialized with matching form of \c new or variable is not
@@ -2914,7 +3006,7 @@ private:
/// If variable is initialized with mismatching form of \c new, returns false.
/// \param D Variable to analyze.
bool hasMatchingVarInit(const DeclRefExpr *D);
- /// \brief Checks whether the constructor initializes pointee with mismatching
+ /// Checks whether the constructor initializes pointee with mismatching
/// form of \c new.
///
/// Returns true, if member is initialized with matching form of \c new in
@@ -2923,7 +3015,7 @@ private:
/// constructor isn't defined at the point where delete-expression is seen, or
/// member isn't initialized by the constructor.
bool hasMatchingNewInCtor(const CXXConstructorDecl *CD);
- /// \brief Checks whether member is initialized with matching form of
+ /// Checks whether member is initialized with matching form of
/// \c new in member initializer list.
bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI);
/// Checks whether member is initialized with mismatching form of \c new by
@@ -3192,7 +3284,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
QualType PointeeElem = Context.getBaseElementType(Pointee);
- if (Pointee.getAddressSpace() != LangAS::Default)
+ if (Pointee.getAddressSpace() != LangAS::Default &&
+ !getLangOpts().OpenCLCPlusPlus)
return Diag(Ex.get()->getLocStart(),
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType()
@@ -3267,6 +3360,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
if (!OperatorDelete) {
+ if (getLangOpts().OpenCLCPlusPlus) {
+ Diag(StartLoc, diag::err_openclcxx_not_supported) << "default delete";
+ return ExprError();
+ }
+
bool IsComplete = isCompleteType(StartLoc, Pointee);
bool CanProvideSize =
IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize ||
@@ -3322,6 +3420,128 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return Result;
}
+static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
+ bool IsDelete,
+ FunctionDecl *&Operator) {
+
+ DeclarationName NewName = S.Context.DeclarationNames.getCXXOperatorName(
+ IsDelete ? OO_Delete : OO_New);
+
+ LookupResult R(S, NewName, TheCall->getLocStart(), Sema::LookupOrdinaryName);
+ S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl());
+ assert(!R.empty() && "implicitly declared allocation functions not found");
+ assert(!R.isAmbiguous() && "global allocation functions are ambiguous");
+
+ // We do our own custom access checks below.
+ R.suppressDiagnostics();
+
+ SmallVector<Expr *, 8> Args(TheCall->arg_begin(), TheCall->arg_end());
+ OverloadCandidateSet Candidates(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
+ for (LookupResult::iterator FnOvl = R.begin(), FnOvlEnd = R.end();
+ FnOvl != FnOvlEnd; ++FnOvl) {
+ // Even member operator new/delete are implicitly treated as
+ // static, so don't use AddMemberCandidate.
+ NamedDecl *D = (*FnOvl)->getUnderlyingDecl();
+
+ if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
+ S.AddTemplateOverloadCandidate(FnTemplate, FnOvl.getPair(),
+ /*ExplicitTemplateArgs=*/nullptr, Args,
+ Candidates,
+ /*SuppressUserConversions=*/false);
+ continue;
+ }
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ S.AddOverloadCandidate(Fn, FnOvl.getPair(), Args, Candidates,
+ /*SuppressUserConversions=*/false);
+ }
+
+ SourceRange Range = TheCall->getSourceRange();
+
+ // Do the resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) {
+ case OR_Success: {
+ // Got one!
+ FunctionDecl *FnDecl = Best->Function;
+ assert(R.getNamingClass() == nullptr &&
+ "class members should not be considered");
+
+ if (!FnDecl->isReplaceableGlobalAllocationFunction()) {
+ S.Diag(R.getNameLoc(), diag::err_builtin_operator_new_delete_not_usual)
+ << (IsDelete ? 1 : 0) << Range;
+ S.Diag(FnDecl->getLocation(), diag::note_non_usual_function_declared_here)
+ << R.getLookupName() << FnDecl->getSourceRange();
+ return true;
+ }
+
+ Operator = FnDecl;
+ return false;
+ }
+
+ case OR_No_Viable_Function:
+ S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ return true;
+
+ case OR_Ambiguous:
+ S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ return true;
+
+ case OR_Deleted: {
+ S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted() << R.getLookupName()
+ << S.getDeletedOrUnavailableSuffix(Best->Function) << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ return true;
+ }
+ }
+ llvm_unreachable("Unreachable, bad result from BestViableFunction");
+}
+
+ExprResult
+Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+ bool IsDelete) {
+ CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
+ if (!getLangOpts().CPlusPlus) {
+ Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
+ << (IsDelete ? "__builtin_operator_delete" : "__builtin_operator_new")
+ << "C++";
+ return ExprError();
+ }
+ // CodeGen assumes it can find the global new and delete to call,
+ // so ensure that they are declared.
+ DeclareGlobalNewDelete();
+
+ FunctionDecl *OperatorNewOrDelete = nullptr;
+ if (resolveBuiltinNewDeleteOverload(*this, TheCall, IsDelete,
+ OperatorNewOrDelete))
+ return ExprError();
+ assert(OperatorNewOrDelete && "should be found");
+
+ TheCall->setType(OperatorNewOrDelete->getReturnType());
+ for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) {
+ QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType();
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(Context, ParamTy, false);
+ ExprResult Arg = PerformCopyInitialization(
+ Entity, TheCall->getArg(i)->getLocStart(), TheCall->getArg(i));
+ if (Arg.isInvalid())
+ return ExprError();
+ TheCall->setArg(i, Arg.get());
+ }
+ auto Callee = dyn_cast<ImplicitCastExpr>(TheCall->getCallee());
+ assert(Callee && Callee->getCastKind() == CK_BuiltinFnToFnPtr &&
+ "Callee expected to be implicit cast to a builtin function pointer");
+ Callee->setType(OperatorNewOrDelete->getType());
+
+ return TheCallResult;
+}
+
void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
bool IsDelete, bool CallCanBeVirtual,
bool WarnOnNonAbstractTypes,
@@ -3378,7 +3598,7 @@ Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar,
CK == ConditionKind::ConstexprIf);
}
-/// \brief Check the use of the given variable as a C++ condition in an if,
+/// Check the use of the given variable as a C++ condition in an if,
/// while, do-while, or switch statement.
ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
SourceLocation StmtLoc,
@@ -3548,6 +3768,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const ImplicitConversionSequence &ICS,
AssignmentAction Action,
CheckedConversionKind CCK) {
+ // C++ [over.match.oper]p7: [...] operands of class type are converted [...]
+ if (CCK == CCK_ForBuiltinOverloadedOp && !From->getType()->isRecordType())
+ return From;
+
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion: {
ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard,
@@ -3607,6 +3831,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From = CastArg.get();
+ // C++ [over.match.oper]p7:
+ // [...] the second standard conversion sequence of a user-defined
+ // conversion sequence is not applied.
+ if (CCK == CCK_ForBuiltinOverloadedOp)
+ return From;
+
return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
AA_Converting, CCK);
}
@@ -4070,14 +4300,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// If this conversion sequence succeeded and involved implicitly converting a
// _Nullable type to a _Nonnull one, complain.
- if (CCK == CCK_ImplicitConversion)
+ if (!isCast(CCK))
diagnoseNullableToNonnullConversion(ToType, InitialFromType,
From->getLocStart());
return From;
}
-/// \brief Check the completeness of a type in a unary type trait.
+/// Check the completeness of a type in a unary type trait.
///
/// If the particular type trait requires a complete type, tries to complete
/// it. If completing the type fails, a diagnostic is emitted and false
@@ -4227,7 +4457,7 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
const FunctionProtoType *CPT =
Operator->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT || !CPT->isNothrow(C))
+ if (!CPT || !CPT->isNothrow())
return false;
}
}
@@ -4475,7 +4705,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
const FunctionProtoType *CPT =
Destructor->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT || !CPT->isNothrow(C))
+ if (!CPT || !CPT->isNothrow())
return false;
}
}
@@ -4568,7 +4798,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
+ if (!CPT->isNothrow() || CPT->getNumParams() > 1)
return false;
}
}
@@ -4607,7 +4837,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(C) || CPT->getNumParams() > 0)
+ if (!CPT->isNothrow() || CPT->getNumParams() > 0)
return false;
}
}
@@ -4645,11 +4875,14 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (Kind <= UTT_Last)
return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
- if (Kind <= BTT_Last)
+ // Evaluate BTT_ReferenceBindsToTemporary alongside the IsConstructible
+ // traits to avoid duplication.
+ if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary)
return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(),
Args[1]->getType(), RParenLoc);
switch (Kind) {
+ case clang::BTT_ReferenceBindsToTemporary:
case clang::TT_IsConstructible:
case clang::TT_IsNothrowConstructible:
case clang::TT_IsTriviallyConstructible: {
@@ -4726,6 +4959,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (Kind == clang::TT_IsConstructible)
return true;
+ if (Kind == clang::BTT_ReferenceBindsToTemporary) {
+ if (!T->isReferenceType())
+ return false;
+
+ return !Init.isDirectReferenceBinding();
+ }
+
if (Kind == clang::TT_IsNothrowConstructible)
return S.canThrow(Result.get()) == CT_Cannot;
@@ -5231,8 +5471,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
case RQ_LValue:
if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) {
- // C++2a allows functions with ref-qualifier & if they are also 'const'.
- if (Proto->isConst())
+ // C++2a allows functions with ref-qualifier & if their cv-qualifier-seq
+ // is (exactly) 'const'.
+ if (Proto->isConst() && !Proto->isVolatile())
Diag(Loc, getLangOpts().CPlusPlus2a
? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue
: diag::ext_pointer_to_const_ref_member_on_rvalue);
@@ -5269,7 +5510,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
return Result;
}
-/// \brief Try to convert a type to another according to C++11 5.16p3.
+/// Try to convert a type to another according to C++11 5.16p3.
///
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, the two operands are attempted to be
@@ -5294,7 +5535,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
// constraint that in the conversion the reference must bind directly to
// an lvalue.
// -- If E2 is an xvalue: E1 can be converted to match E2 if E1 can be
- // implicitly conveted to the type "rvalue reference to R2", subject to
+ // implicitly converted to the type "rvalue reference to R2", subject to
// the constraint that the reference must bind directly.
if (To->isLValue() || To->isXValue()) {
QualType T = To->isLValue() ? Self.Context.getLValueReferenceType(ToType)
@@ -5363,7 +5604,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
return false;
}
-/// \brief Try to find a common type for two according to C++0x 5.16p5.
+/// Try to find a common type for two according to C++0x 5.16p5.
///
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, overload resolution is used to find a
@@ -5425,7 +5666,7 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS
return true;
}
-/// \brief Perform an "extended" implicit conversion as returned by
+/// Perform an "extended" implicit conversion as returned by
/// TryClassUnification.
static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
@@ -5441,7 +5682,7 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
return false;
}
-/// \brief Check the operands of ?: under C++ semantics.
+/// Check the operands of ?: under C++ semantics.
///
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
@@ -5745,27 +5986,23 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
if (EST2 == EST_None) return ESI2;
if (EST1 == EST_MSAny) return ESI1;
if (EST2 == EST_MSAny) return ESI2;
+ if (EST1 == EST_NoexceptFalse) return ESI1;
+ if (EST2 == EST_NoexceptFalse) return ESI2;
// If either of them is non-throwing, the result is the other.
if (EST1 == EST_DynamicNone) return ESI2;
if (EST2 == EST_DynamicNone) return ESI1;
if (EST1 == EST_BasicNoexcept) return ESI2;
if (EST2 == EST_BasicNoexcept) return ESI1;
+ if (EST1 == EST_NoexceptTrue) return ESI2;
+ if (EST2 == EST_NoexceptTrue) return ESI1;
- // If either of them is a non-value-dependent computed noexcept, that
- // determines the result.
- if (EST2 == EST_ComputedNoexcept && ESI2.NoexceptExpr &&
- !ESI2.NoexceptExpr->isValueDependent())
- return !ESI2.NoexceptExpr->EvaluateKnownConstInt(S.Context) ? ESI2 : ESI1;
- if (EST1 == EST_ComputedNoexcept && ESI1.NoexceptExpr &&
- !ESI1.NoexceptExpr->isValueDependent())
- return !ESI1.NoexceptExpr->EvaluateKnownConstInt(S.Context) ? ESI1 : ESI2;
// If we're left with value-dependent computed noexcept expressions, we're
// stuck. Before C++17, we can just drop the exception specification entirely,
// since it's not actually part of the canonical type. And this should never
// 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) {
+ if (EST1 == EST_DependentNoexcept || EST2 == EST_DependentNoexcept) {
assert(!S.getLangOpts().CPlusPlus17 &&
"computing composite pointer type of dependent types");
return FunctionProtoType::ExceptionSpecInfo();
@@ -5778,7 +6015,9 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
case EST_DynamicNone:
case EST_MSAny:
case EST_BasicNoexcept:
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
llvm_unreachable("handled above");
case EST_Dynamic: {
@@ -5805,7 +6044,7 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
llvm_unreachable("invalid ExceptionSpecificationType");
}
-/// \brief Find a merged pointer type and convert the two expressions to it.
+/// Find a merged pointer type and convert the two expressions to it.
///
/// This finds the composite pointer type (or member pointer type) for @p E1
/// and @p E2 according to C++1z 5p14. It converts both expressions to this
@@ -6195,7 +6434,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (RD->isInvalidDecl() || RD->isDependentContext())
return E;
- bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+ bool IsDecltype = ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype;
CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
if (Destructor) {
@@ -6277,7 +6517,9 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
/// are omitted for the 'topmost' call in the decltype expression. If the
/// topmost call bound a temporary, strip that temporary off the expression.
ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
- assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+ assert(ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype &&
+ "not in a decltype expression");
// C++11 [expr.call]p11:
// If a function call is a prvalue of object type,
@@ -6319,7 +6561,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
TopBind = nullptr;
// Disable the special decltype handling now.
- ExprEvalContexts.back().IsDecltype = false;
+ ExprEvalContexts.back().ExprContext =
+ ExpressionEvaluationContextRecord::EK_Other;
// In MS mode, don't perform any extra checking of call return types within a
// decltype expression.
@@ -6572,7 +6815,7 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
return false;
}
-/// \brief Check if it's ok to try and recover dot pseudo destructor calls on
+/// Check if it's ok to try and recover dot pseudo destructor calls on
/// pointer objects.
static bool
canRecoverDotPseudoDestructorCallsOnPointerObjects(Sema &SemaRef,
@@ -6877,10 +7120,17 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
CXXConversionDecl *Method,
bool HadMultipleCandidates) {
+ // Convert the expression to match the conversion function's implicit object
+ // parameter.
+ ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
+ FoundDecl, Method);
+ if (Exp.isInvalid())
+ return true;
+
if (Method->getParent()->isLambda() &&
Method->getConversionType()->isBlockPointerType()) {
// This is a lambda coversion to block pointer; check if the argument
- // is a LambdaExpr.
+ // was a LambdaExpr.
Expr *SubE = E;
CastExpr *CE = dyn_cast<CastExpr>(SubE);
if (CE && CE->getCastKind() == CK_NoOp)
@@ -6897,22 +7147,16 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
DiagnosticErrorTrap Trap(Diags);
PushExpressionEvaluationContext(
ExpressionEvaluationContext::PotentiallyEvaluated);
- ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(),
- E->getExprLoc(),
- Method, E);
+ ExprResult BlockExp = BuildBlockForLambdaConversion(
+ Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get());
PopExpressionEvaluationContext();
- if (Exp.isInvalid())
- Diag(E->getExprLoc(), diag::note_lambda_to_block_conv);
- return Exp;
+ if (BlockExp.isInvalid())
+ Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv);
+ return BlockExp;
}
}
- ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
- FoundDecl, Method);
- if (Exp.isInvalid())
- return true;
-
MemberExpr *ME = new (Context) MemberExpr(
Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(),
Context.BoundMemberTy, VK_RValue, OK_Ordinary);
@@ -7123,7 +7367,7 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
return !IsVariableAConstantExpression(Var, Context);
}
-/// \brief Check if the current lambda has any potential captures
+/// Check if the current lambda has any potential captures
/// that must be captured by any of its enclosing lambdas that are ready to
/// capture. If there is a lambda that can capture a nested
/// potential-capture, go ahead and do so. Also, check to see if any
@@ -7146,9 +7390,6 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
- ArrayRef<const FunctionScopeInfo *> FunctionScopesArrayRef(
- S.FunctionScopes.data(), S.FunctionScopes.size());
-
// All the potentially captureable variables in the current nested
// lambda (within a generic outer lambda), must be captured by an
// outer lambda that is enclosed within a non-dependent context.
@@ -7177,7 +7418,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
// capture the variable in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, Var, S)) {
+ S.FunctionScopes, Var, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
&FunctionScopeIndexOfCapturableLambda);
@@ -7213,7 +7454,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
// 'this' in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) {
+ S.FunctionScopes, /*0 is 'this'*/ nullptr, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
/*Explicit*/ false, /*BuildAndDiagnose*/ true,
@@ -7306,13 +7547,12 @@ class TransformTypos : public TreeTransform<TransformTypos> {
llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache;
llvm::SmallDenseMap<OverloadExpr *, Expr *, 4> OverloadResolution;
- /// \brief Emit diagnostics for all of the TypoExprs encountered.
+ /// Emit diagnostics for all of the TypoExprs encountered.
/// If the TypoExprs were successfully corrected, then the diagnostics should
/// suggest the corrections. Otherwise the diagnostics will not suggest
/// anything (having been passed an empty TypoCorrection).
void EmitAllDiagnostics() {
- for (auto E : TypoExprs) {
- TypoExpr *TE = cast<TypoExpr>(E);
+ for (TypoExpr *TE : TypoExprs) {
auto &State = SemaRef.getTypoExprState(TE);
if (State.DiagHandler) {
TypoCorrection TC = State.Consumer->getCurrentCorrection();
@@ -7333,7 +7573,7 @@ class TransformTypos : public TreeTransform<TransformTypos> {
}
}
- /// \brief If corrections for the first TypoExpr have been exhausted for a
+ /// If corrections for the first TypoExpr have been exhausted for a
/// given combination of the other TypoExprs, retry those corrections against
/// the next combination of substitutions for the other TypoExprs by advancing
/// to the next potential correction of the second TypoExpr. For the second
@@ -7504,12 +7744,8 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl,
if (E && !ExprEvalContexts.empty() && ExprEvalContexts.back().NumTypos &&
(E->isTypeDependent() || E->isValueDependent() ||
E->isInstantiationDependent())) {
- auto TyposInContext = ExprEvalContexts.back().NumTypos;
- assert(TyposInContext < ~0U && "Recursive call of CorrectDelayedTyposInExpr");
- ExprEvalContexts.back().NumTypos = ~0U;
auto TyposResolved = DelayedTypos.size();
auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E);
- ExprEvalContexts.back().NumTypos = TyposInContext;
TyposResolved -= DelayedTypos.size();
if (Result.isInvalid() || Result.get() != E) {
ExprEvalContexts.back().NumTypos -= TyposResolved;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index f57f79e62efe..e6d2b5068fd5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -120,7 +120,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
// member reference.
if (Classes.empty())
return IMA_Static;
-
+
// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
@@ -166,7 +166,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
else
contextClass = cast<CXXRecordDecl>(DC);
- // [class.mfct.non-static]p3:
+ // [class.mfct.non-static]p3:
// ...is used in the body of a non-static member function of class X,
// if name lookup (3.4.1) resolves the name in the id-expression to a
// non-static non-type member of some class C [...]
@@ -417,14 +417,14 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
// Now look up the TypeDefDecl from the vector type. Without this,
// diagostics look bad. We want extended vector types to appear built-in.
- for (Sema::ExtVectorDeclsType::iterator
+ for (Sema::ExtVectorDeclsType::iterator
I = S.ExtVectorDecls.begin(S.getExternalSource()),
- E = S.ExtVectorDecls.end();
+ E = S.ExtVectorDecls.end();
I != E; ++I) {
if ((*I)->getUnderlyingType() == VT)
return S.Context.getTypedefType(*I);
}
-
+
return VT; // should never get here (a typedef type should always be found).
}
@@ -640,6 +640,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
const RecordType *RTy,
SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, bool HasTemplateArgs,
+ SourceLocation TemplateKWLoc,
TypoExpr *&TE) {
SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
RecordDecl *RDecl = RTy->getDecl();
@@ -649,13 +650,13 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
BaseRange))
return true;
- if (HasTemplateArgs) {
+ if (HasTemplateArgs || TemplateKWLoc.isValid()) {
// LookupTemplateName doesn't expect these both to exist simultaneously.
QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
bool MOUS;
- SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS);
- return false;
+ return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS,
+ TemplateKWLoc);
}
DeclContext *DC = RDecl;
@@ -733,7 +734,8 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
ExprResult &BaseExpr, bool &IsArrow,
SourceLocation OpLoc, CXXScopeSpec &SS,
- Decl *ObjCImpDecl, bool HasTemplateArgs);
+ Decl *ObjCImpDecl, bool HasTemplateArgs,
+ SourceLocation TemplateKWLoc);
ExprResult
Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
@@ -759,9 +761,9 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
- if (LookupMemberExprInRecord(*this, R, nullptr,
- RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
- SS, TemplateArgs != nullptr, TE))
+ if (LookupMemberExprInRecord(
+ *this, R, nullptr, RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
+ SS, TemplateArgs != nullptr, TemplateKWLoc, TE))
return ExprError();
if (TE)
return TE;
@@ -769,10 +771,10 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
// Explicit member accesses.
} else {
ExprResult BaseResult = Base;
- ExprResult Result = LookupMemberExpr(
- *this, R, BaseResult, IsArrow, OpLoc, SS,
- ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
- TemplateArgs != nullptr);
+ ExprResult Result =
+ LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,
+ ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
+ TemplateArgs != nullptr, TemplateKWLoc);
if (BaseResult.isInvalid())
return ExprError();
@@ -802,95 +804,61 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
Expr *baseObjectExpr,
SourceLocation opLoc) {
// First, build the expression that refers to the base object.
-
- bool baseObjectIsPointer = false;
- Qualifiers baseQuals;
-
+
// Case 1: the base of the indirect field is not a field.
VarDecl *baseVariable = indirectField->getVarDecl();
CXXScopeSpec EmptySS;
if (baseVariable) {
assert(baseVariable->getType()->isRecordType());
-
+
// In principle we could have a member access expression that
// accesses an anonymous struct/union that's a static member of
// the base object's class. However, under the current standard,
// static data members cannot be anonymous structs or unions.
// Supporting this is as easy as building a MemberExpr here.
assert(!baseObjectExpr && "anonymous struct/union is static data member?");
-
+
DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
-
- ExprResult result
+
+ ExprResult result
= BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
if (result.isInvalid()) return ExprError();
-
- baseObjectExpr = result.get();
- baseObjectIsPointer = false;
- baseQuals = baseObjectExpr->getType().getQualifiers();
-
- // Case 2: the base of the indirect field is a field and the user
- // wrote a member expression.
- } else if (baseObjectExpr) {
- // The caller provided the base object expression. Determine
- // whether its a pointer and whether it adds any qualifiers to the
- // anonymous struct/union fields we're looking into.
- QualType objectType = baseObjectExpr->getType();
-
- if (const PointerType *ptr = objectType->getAs<PointerType>()) {
- baseObjectIsPointer = true;
- objectType = ptr->getPointeeType();
- } else {
- baseObjectIsPointer = false;
- }
- baseQuals = objectType.getQualifiers();
-
- // Case 3: the base of the indirect field is a field and we should
- // build an implicit member access.
- } else {
- // We've found a member of an anonymous struct/union that is
- // inside a non-anonymous struct/union, so in a well-formed
- // program our base object expression is "this".
- QualType ThisTy = getCurrentThisType();
- if (ThisTy.isNull()) {
- Diag(loc, diag::err_invalid_member_use_in_static_method)
- << indirectField->getDeclName();
- return ExprError();
- }
-
- // Our base object expression is "this".
- CheckCXXThisCapture(loc);
- baseObjectExpr
- = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
- baseObjectIsPointer = true;
- baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
+
+ baseObjectExpr = result.get();
}
-
+
+ assert((baseVariable || baseObjectExpr) &&
+ "referencing anonymous struct/union without a base variable or "
+ "expression");
+
// Build the implicit member references to the field of the
// anonymous struct/union.
Expr *result = baseObjectExpr;
IndirectFieldDecl::chain_iterator
FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
-
- // Build the first member access in the chain with full information.
+
+ // Case 2: the base of the indirect field is a field and the user
+ // wrote a member expression.
if (!baseVariable) {
FieldDecl *field = cast<FieldDecl>(*FI);
-
+
+ bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();
+
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
- result = BuildFieldReferenceExpr(result, baseObjectIsPointer,
- SourceLocation(), EmptySS, field,
- foundDecl, memberNameInfo).get();
+ // Build the first member access in the chain with full information.
+ result =
+ BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),
+ SS, field, foundDecl, memberNameInfo)
+ .get();
if (!result)
return ExprError();
-
- // FIXME: check qualified member access
}
-
+
// In all cases, we should now skip the first declaration in the chain.
++FI;
-
+
while (FI != FEnd) {
FieldDecl *field = cast<FieldDecl>(*FI++);
@@ -905,7 +873,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
fakeFoundDecl, memberNameInfo)
.get();
}
-
+
return result;
}
@@ -922,7 +890,7 @@ BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
NameInfo.getLoc());
}
-/// \brief Build a MemberExpr AST node.
+/// Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(
Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
SourceLocation OpLoc, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
@@ -937,7 +905,7 @@ static MemberExpr *BuildMemberExpr(
return E;
}
-/// \brief Determine if the given scope is within a function-try-block handler.
+/// Determine if the given scope is within a function-try-block handler.
static bool IsInFnTryBlockHandler(const Scope *S) {
// Walk the scope stack until finding a FnTryCatchScope, or leave the
// function scope. If a FnTryCatchScope is found, check whether the TryScope
@@ -954,16 +922,12 @@ getVarTemplateSpecialization(Sema &S, VarTemplateDecl *VarTempl,
const TemplateArgumentListInfo *TemplateArgs,
const DeclarationNameInfo &MemberNameInfo,
SourceLocation TemplateKWLoc) {
-
if (!TemplateArgs) {
- S.Diag(MemberNameInfo.getBeginLoc(), diag::err_template_decl_ref)
- << /*Variable template*/ 1 << MemberNameInfo.getName()
- << MemberNameInfo.getSourceRange();
-
- S.Diag(VarTempl->getLocation(), diag::note_template_decl_here);
-
+ S.diagnoseMissingTemplateArguments(TemplateName(VarTempl),
+ MemberNameInfo.getBeginLoc());
return nullptr;
}
+
DeclResult VDecl = S.CheckVarTemplateId(
VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), *TemplateArgs);
if (VDecl.isInvalid())
@@ -1001,8 +965,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
return ExprError();
BaseExpr = Converted.get();
}
-
-
+
+
const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
DeclarationName MemberName = MemberNameInfo.getName();
SourceLocation MemberLoc = MemberNameInfo.getLoc();
@@ -1071,7 +1035,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
!SuppressQualifierCheck &&
CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
return ExprError();
-
+
// Construct an unresolved result if we in fact got an unresolved
// result.
if (R.isOverloadedResult() || R.isUnresolvableResult()) {
@@ -1264,7 +1228,8 @@ Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
ExprResult &BaseExpr, bool &IsArrow,
SourceLocation OpLoc, CXXScopeSpec &SS,
- Decl *ObjCImpDecl, bool HasTemplateArgs) {
+ Decl *ObjCImpDecl, bool HasTemplateArgs,
+ SourceLocation TemplateKWLoc) {
assert(BaseExpr.get() && "no base expression");
// Perform default conversions.
@@ -1314,8 +1279,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
TypoExpr *TE = nullptr;
- if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy,
- OpLoc, IsArrow, SS, HasTemplateArgs, TE))
+ if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS,
+ HasTemplateArgs, TemplateKWLoc, TE))
return ExprError();
// Returning valid-but-null is how we indicate to the caller that
@@ -1353,7 +1318,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
OpLoc, S.Context.getObjCClassType());
if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
goto fail;
}
@@ -1456,7 +1421,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))
if (UO->getOpcode() == UO_Deref)
BaseExp = UO->getSubExpr()->IgnoreParenCasts();
-
+
if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))
if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);
@@ -1466,7 +1431,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (warn) {
if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {
ObjCMethodFamily MF = MD->getMethodFamily();
- warn = (MF != OMF_init && MF != OMF_dealloc &&
+ warn = (MF != OMF_init && MF != OMF_dealloc &&
MF != OMF_finalize &&
!S.IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
}
@@ -1479,8 +1444,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
IsArrow);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
- S.recordUseOfEvaluatedWeak(Result);
+ if (!S.isUnevaluatedContext() &&
+ !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
+ S.getCurFunction()->recordUseOfWeak(Result);
}
return Result;
@@ -1524,9 +1490,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
}
if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
- // Check the use of this method.
- if (S.DiagnoseUseOfDecl(OMD, MemberLoc))
- return ExprError();
Selector SetterSel =
SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
S.PP.getSelectorTable(),
@@ -1546,7 +1509,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// use the 'id' redefinition in this case.
if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
@@ -1559,7 +1522,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (!MD) {
if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
goto fail;
}
@@ -1567,6 +1530,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Also must look for a getter name which uses property syntax.
Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
ObjCInterfaceDecl *IFace = MD->getClassInterface();
+ if (!IFace)
+ goto fail;
+
ObjCMethodDecl *Getter;
if ((Getter = IFace->lookupClassMethod(Sel))) {
// Check the use of this method.
@@ -1598,7 +1564,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
@@ -1623,10 +1589,14 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
else
VK = BaseExpr.get()->getValueKind();
}
+
QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
Member, MemberLoc);
if (ret.isNull())
return ExprError();
+ Qualifiers BaseQ =
+ S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers();
+ ret = S.Context.getQualifiedType(ret, BaseQ);
return new (S.Context)
ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);
@@ -1639,7 +1609,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
BaseExpr = S.ImpCastExprToType(
BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
}
// Failure cases.
@@ -1662,7 +1632,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Recurse as an -> access.
IsArrow = true;
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
}
}
@@ -1676,7 +1646,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
return ExprError();
BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
}
S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
@@ -1762,7 +1732,7 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
}
if (VK != VK_RValue && Field->isBitField())
OK = OK_BitField;
-
+
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
QualType MemberType = Field->getType();
if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
@@ -1805,7 +1775,7 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
if (getLangOpts().OpenMP && IsArrow &&
!CurContext->isDependentContext() &&
isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
- if (auto *PrivateCopy = IsOpenMPCapturedDecl(Field)) {
+ if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) {
return getOpenMPCapturedExpr(PrivateCopy, VK, OK,
MemberNameInfo.getLoc());
}
@@ -1827,7 +1797,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
const TemplateArgumentListInfo *TemplateArgs,
bool IsKnownInstance, const Scope *S) {
assert(!R.empty() && !R.isAmbiguous());
-
+
SourceLocation loc = R.getNameLoc();
// If this is known to be an instance access, go ahead and build an
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index cd0c2c47ae4c..b291fc8691d5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -73,7 +73,7 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
/*Pascal=*/false, StrTy, &StrLocs[0],
StrLocs.size());
}
-
+
return BuildObjCStringLiteral(AtLocs[0], S);
}
@@ -92,12 +92,12 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
} else if (getLangOpts().NoConstantCFStrings) {
IdentifierInfo *NSIdent=nullptr;
std::string StringClass(getLangOpts().ObjCConstantStringClass);
-
+
if (StringClass.empty())
NSIdent = &Context.Idents.get("NSConstantString");
else
NSIdent = &Context.Idents.get(StringClass);
-
+
NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
LookupOrdinaryName);
if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
@@ -126,10 +126,10 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
// being an 'id' type.
Ty = Context.getObjCNSStringType();
if (Ty.isNull()) {
- ObjCInterfaceDecl *NSStringIDecl =
- ObjCInterfaceDecl::Create (Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(), NSIdent,
+ ObjCInterfaceDecl *NSStringIDecl =
+ ObjCInterfaceDecl::Create (Context,
+ Context.getTranslationUnitDecl(),
+ SourceLocation(), NSIdent,
nullptr, nullptr, SourceLocation());
Ty = Context.getObjCInterfaceType(NSStringIDecl);
Context.setObjCNSStringType(Ty);
@@ -141,7 +141,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
}
-/// \brief Emits an error if the given method does not exist, or if the return
+/// Emits an error if the given method does not exist, or if the return
/// type is not an Objective-C object.
static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
const ObjCInterfaceDecl *Class,
@@ -165,7 +165,7 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
return true;
}
-/// \brief Maps ObjCLiteralKind to NSClassIdKindKind
+/// Maps ObjCLiteralKind to NSClassIdKindKind
static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
Sema::ObjCLiteralKind LiteralKind) {
switch (LiteralKind) {
@@ -189,7 +189,7 @@ static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
llvm_unreachable("LiteralKind can't be converted into a ClassKind");
}
-/// \brief Validates ObjCInterfaceDecl availability.
+/// Validates ObjCInterfaceDecl availability.
/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
/// if clang not in a debugger mode.
static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
@@ -211,7 +211,7 @@ static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
return true;
}
-/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
+/// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
/// Used to create ObjC literals, such as NSDictionary (@{}),
/// NSArray (@[]) and Boxed Expressions (@())
static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
@@ -236,7 +236,7 @@ static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
return ID;
}
-/// \brief Retrieve the NSNumber factory method that should be used to create
+/// Retrieve the NSNumber factory method that should be used to create
/// an Objective-C literal for the given type.
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
QualType NumberType,
@@ -252,16 +252,16 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
}
return nullptr;
}
-
+
// If we already looked up this method, we're done.
if (S.NSNumberLiteralMethods[*Kind])
return S.NSNumberLiteralMethods[*Kind];
-
+
Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,
/*Instance=*/false);
-
+
ASTContext &CX = S.Context;
-
+
// Look up the NSNumber class, if we haven't done so already. It's cached
// in the Sema instance.
if (!S.NSNumberDecl) {
@@ -277,7 +277,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);
S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject);
}
-
+
// Look for the appropriate method within NSNumber.
ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
@@ -304,7 +304,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
// Note: if the parameter type is out-of-line, we'll catch it later in the
// implicit conversion.
-
+
S.NSNumberLiteralMethods[*Kind] = Method;
return Method;
}
@@ -322,21 +322,21 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
case CharacterLiteral::UTF8:
NumberType = Context.CharTy;
break;
-
+
case CharacterLiteral::Wide:
NumberType = Context.getWideCharType();
break;
-
+
case CharacterLiteral::UTF16:
NumberType = Context.Char16Ty;
break;
-
+
case CharacterLiteral::UTF32:
NumberType = Context.Char32Ty;
break;
}
}
-
+
// Look for the appropriate method within NSNumber.
// Construct the literal.
SourceRange NR(Number->getSourceRange());
@@ -355,33 +355,33 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
if (ConvertedNumber.isInvalid())
return ExprError();
Number = ConvertedNumber.get();
-
+
// Use the effective source range of the literal, including the leading '@'.
return MaybeBindToTemporary(
new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method,
SourceRange(AtLoc, NR.getEnd())));
}
-ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
+ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
SourceLocation ValueLoc,
bool Value) {
ExprResult Inner;
if (getLangOpts().CPlusPlus) {
Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false);
} else {
- // C doesn't actually have a way to represent literal values of type
+ // C doesn't actually have a way to represent literal values of type
// _Bool. So, we'll use 0/1 and implicit cast to _Bool.
Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0);
- Inner = ImpCastExprToType(Inner.get(), Context.BoolTy,
+ Inner = ImpCastExprToType(Inner.get(), Context.BoolTy,
CK_IntegralToBoolean);
}
-
+
return BuildObjCNumericLiteral(AtLoc, Inner.get());
}
-/// \brief Check that the given expression is a valid element of an Objective-C
+/// Check that the given expression is a valid element of an Objective-C
/// collection literal.
-static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
+static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
QualType T,
bool ArrayLiteral = false) {
// If the expression is type-dependent, there's nothing for us to do.
@@ -393,7 +393,7 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
return ExprError();
Element = Result.get();
- // In C++, check for an implicit conversion to an Objective-C object pointer
+ // In C++, check for an implicit conversion to an Objective-C object pointer
// type.
if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {
InitializedEntity Entity
@@ -413,15 +413,15 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
Result = S.DefaultLvalueConversion(Element);
if (Result.isInvalid())
return ExprError();
- Element = Result.get();
+ Element = Result.get();
// Make sure that we have an Objective-C pointer type or block.
if (!Element->getType()->isObjCObjectPointerType() &&
!Element->getType()->isBlockPointerType()) {
bool Recovered = false;
-
+
// If this is potentially an Objective-C numeric literal, add the '@'.
- if (isa<IntegerLiteral>(OrigElement) ||
+ if (isa<IntegerLiteral>(OrigElement) ||
isa<CharacterLiteral>(OrigElement) ||
isa<FloatingLiteral>(OrigElement) ||
isa<ObjCBoolLiteralExpr>(OrigElement) ||
@@ -431,16 +431,16 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
: (isa<CXXBoolLiteralExpr>(OrigElement) ||
isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2
: 3;
-
+
S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
<< Which << OrigElement->getSourceRange()
<< FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
-
+
Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(),
OrigElement);
if (Result.isInvalid())
return ExprError();
-
+
Element = Result.get();
Recovered = true;
}
@@ -455,12 +455,12 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String);
if (Result.isInvalid())
return ExprError();
-
+
Element = Result.get();
Recovered = true;
}
}
-
+
if (!Recovered) {
S.Diag(Element->getLocStart(), diag::err_invalid_collection_element)
<< Element->getType();
@@ -488,17 +488,17 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
}
}
- // Make sure that the element has the type that the container factory
- // function expects.
+ // Make sure that the element has the type that the container factory
+ // function expects.
return S.PerformCopyInitialization(
- InitializedEntity::InitializeParameter(S.Context, T,
+ InitializedEntity::InitializeParameter(S.Context, T,
/*Consumed=*/false),
Element->getLocStart(), Element);
}
ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (ValueExpr->isTypeDependent()) {
- ObjCBoxedExpr *BoxedExpr =
+ ObjCBoxedExpr *BoxedExpr =
new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR);
return BoxedExpr;
}
@@ -525,7 +525,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);
NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);
}
-
+
if (!StringWithUTF8StringMethod) {
IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");
Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);
@@ -561,7 +561,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
StringWithUTF8StringMethod = BoxingMethod;
}
-
+
BoxingMethod = StringWithUTF8StringMethod;
BoxedType = NSStringPointer;
// Transfer the nullability from method's return type.
@@ -588,22 +588,22 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
case CharacterLiteral::UTF8:
ValueType = Context.CharTy;
break;
-
+
case CharacterLiteral::Wide:
ValueType = Context.getWideCharType();
break;
-
+
case CharacterLiteral::UTF16:
ValueType = Context.Char16Ty;
break;
-
+
case CharacterLiteral::UTF32:
ValueType = Context.Char32Ty;
break;
}
}
// FIXME: Do I need to do anything special with BoolTy expressions?
-
+
// Look for the appropriate method within NSNumber.
BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);
BoxedType = NSNumberPointer;
@@ -620,7 +620,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
} else if (ValueType->isObjCBoxableRecordType()) {
// Support for structure types, that marked as objc_boxable
// struct __attribute__((objc_boxable)) s { ... };
-
+
// Look up the NSValue class, if we haven't done so already. It's cached
// in the Sema instance.
if (!NSValueDecl) {
@@ -634,14 +634,14 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
}
-
+
if (!ValueWithBytesObjCTypeMethod) {
IdentifierInfo *II[] = {
&Context.Idents.get("valueWithBytes"),
&Context.Idents.get("objCType")
};
Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II);
-
+
// Look for the appropriate method within NSValue.
BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType);
if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
@@ -662,9 +662,9 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
/*isDefined=*/false,
ObjCMethodDecl::Required,
/*HasRelatedResultType=*/false);
-
+
SmallVector<ParmVarDecl *, 2> Params;
-
+
ParmVarDecl *bytes =
ParmVarDecl::Create(Context, M,
SourceLocation(), SourceLocation(),
@@ -673,7 +673,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
/*TInfo=*/nullptr,
SC_None, nullptr);
Params.push_back(bytes);
-
+
QualType ConstCharType = Context.CharTy.withConst();
ParmVarDecl *type =
ParmVarDecl::Create(Context, M,
@@ -683,18 +683,18 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
/*TInfo=*/nullptr,
SC_None, nullptr);
Params.push_back(type);
-
+
M->setMethodParams(Context, Params, None);
BoxingMethod = M;
}
-
+
if (!validateBoxingMethod(*this, Loc, NSValueDecl,
ValueWithBytesObjCType, BoxingMethod))
return ExprError();
-
+
ValueWithBytesObjCTypeMethod = BoxingMethod;
}
-
+
if (!ValueType.isTriviallyCopyableType(Context)) {
Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
@@ -710,13 +710,13 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
-
+
DiagnoseUseOfDecl(BoxingMethod, Loc);
ExprResult ConvertedValueExpr;
if (ValueType->isObjCBoxableRecordType()) {
InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType);
- ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(),
+ ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(),
ValueExpr);
} else {
// Convert the expression to the type that the parameter requires.
@@ -726,12 +726,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
ConvertedValueExpr = PerformCopyInitialization(IE, SourceLocation(),
ValueExpr);
}
-
+
if (ConvertedValueExpr.isInvalid())
return ExprError();
ValueExpr = ConvertedValueExpr.get();
-
- ObjCBoxedExpr *BoxedExpr =
+
+ ObjCBoxedExpr *BoxedExpr =
new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,
BoxingMethod, SR);
return MaybeBindToTemporary(BoxedExpr);
@@ -756,7 +756,7 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
if (Result.isInvalid())
return ExprError();
IndexExpr = Result.get();
-
+
// Perform lvalue-to-rvalue conversion on the base.
Result = DefaultLvalueConversion(BaseExpr);
if (Result.isInvalid())
@@ -821,24 +821,24 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
// Dig out the type that all elements should be converted to.
QualType T = Method->parameters()[0]->getType();
const PointerType *PtrT = T->getAs<PointerType>();
- if (!PtrT ||
+ if (!PtrT ||
!Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
Diag(Method->parameters()[0]->getLocation(),
diag::note_objc_literal_method_param)
- << 0 << T
+ << 0 << T
<< Context.getPointerType(IdT.withConst());
return ExprError();
}
-
+
// Check that the 'count' parameter is integral.
if (!Method->parameters()[1]->getType()->isIntegerType()) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
Diag(Method->parameters()[1]->getLocation(),
diag::note_objc_literal_method_param)
- << 1
+ << 1
<< Method->parameters()[1]->getType()
<< "integral";
return ExprError();
@@ -860,11 +860,11 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
RequiredType, true);
if (Converted.isInvalid())
return ExprError();
-
+
ElementsBuffer[I] = Converted.get();
}
-
- QualType Ty
+
+ QualType Ty
= Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(NSArrayDecl));
@@ -893,7 +893,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
if (!Method && getLangOpts().DebuggerObjCLiteral) {
- Method = ObjCMethodDecl::Create(Context,
+ Method = ObjCMethodDecl::Create(Context,
SourceLocation(), SourceLocation(), Sel,
IdT,
nullptr /*TypeSourceInfo */,
@@ -938,7 +938,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
// Dig out the type that all values should be converted to.
QualType ValueT = Method->parameters()[0]->getType();
const PointerType *PtrValue = ValueT->getAs<PointerType>();
- if (!PtrValue ||
+ if (!PtrValue ||
!Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
@@ -952,7 +952,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
// Dig out the type that all keys should be converted to.
QualType KeyT = Method->parameters()[1]->getType();
const PointerType *PtrKey = KeyT->getAs<PointerType>();
- if (!PtrKey ||
+ if (!PtrKey ||
!Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
IdT)) {
bool err = true;
@@ -962,7 +962,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
if (ObjCProtocolDecl *NSCopyingPDecl =
LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
- QIDNSCopying =
+ QIDNSCopying =
Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { },
llvm::makeArrayRef(
(ObjCProtocolDecl**) PQ,
@@ -975,7 +975,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
QIDNSCopying);
}
-
+
if (err) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
@@ -1008,7 +1008,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType();
QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();
- // Check that each of the keys and values provided is valid in a collection
+ // Check that each of the keys and values provided is valid in a collection
// literal, performing conversions as necessary.
bool HasPackExpansions = false;
for (ObjCDictionaryElement &Element : Elements) {
@@ -1017,19 +1017,19 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
KeyT);
if (Key.isInvalid())
return ExprError();
-
+
// Check the value.
ExprResult Value
= CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT);
if (Value.isInvalid())
return ExprError();
-
+
Element.Key = Key.get();
Element.Value = Value.get();
-
+
if (Element.EllipsisLoc.isInvalid())
continue;
-
+
if (!Element.Key->containsUnexpandedParameterPack() &&
!Element.Value->containsUnexpandedParameterPack()) {
Diag(Element.EllipsisLoc,
@@ -1038,10 +1038,10 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
Element.Value->getLocEnd());
return ExprError();
}
-
+
HasPackExpansions = true;
}
-
+
QualType Ty
= Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(NSDictionaryDecl));
@@ -1147,7 +1147,7 @@ static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
Method, InstMethList))
Warned = true;
-
+
// second, class methods
ObjCMethodList &ClsMethList = b->second.second;
if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
@@ -1175,7 +1175,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
Diag(SelLoc, diag::warn_undeclared_selector_with_typo)
<< Sel << MatchedSel
<< FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
-
+
} else
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
} else
@@ -1187,7 +1187,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
!getSourceManager().isInSystemHeader(Method->getLocation()))
ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));
- // In ARC, forbid the user from using @selector for
+ // In ARC, forbid the user from using @selector for
// retain/release/autorelease/dealloc/retainCount.
if (getLangOpts().ObjCAutoRefCount) {
switch (Sel.getMethodFamily()) {
@@ -1196,7 +1196,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
case OMF_autorelease:
case OMF_retainCount:
case OMF_dealloc:
- Diag(AtLoc, diag::err_arc_illegal_selector) <<
+ Diag(AtLoc, diag::err_arc_illegal_selector) <<
Sel << SourceRange(LParenLoc, RParenLoc);
break;
@@ -1269,7 +1269,7 @@ static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {
if (T == Context.getObjCInstanceType())
return Context.getObjCIdType();
-
+
return origType;
}
@@ -1313,7 +1313,7 @@ static QualType getBaseMessageSendResultType(Sema &S,
// was a class message send, T is the declared return type of the method
// found
if (Method->isInstanceMethod() && isClassMessage)
- return stripObjCInstanceType(Context,
+ return stripObjCInstanceType(Context,
Method->getSendResultType(ReceiverType));
// - if the receiver is super, T is a pointer to the class of the
@@ -1334,7 +1334,7 @@ static QualType getBaseMessageSendResultType(Sema &S,
// T is the declared return type of the method.
if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType())
- return stripObjCInstanceType(Context,
+ return stripObjCInstanceType(Context,
Method->getSendResultType(ReceiverType));
// - if the receiver is id, qualified id, Class, or qualified Class, T
@@ -1357,6 +1357,11 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
if (isClassMessage)
return resultType;
+ // There is nothing left to do if the result type cannot have a nullability
+ // specifier.
+ if (!resultType->canHaveNullability())
+ return resultType;
+
// Map the nullability of the result into a table index.
unsigned receiverNullabilityIdx = 0;
if (auto nullability = ReceiverType->getNullability(Context))
@@ -1419,14 +1424,14 @@ findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
if (const ObjCImplDecl *impl =
dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {
const ObjCContainerDecl *iface;
- if (const ObjCCategoryImplDecl *catImpl =
+ if (const ObjCCategoryImplDecl *catImpl =
dyn_cast<ObjCCategoryImplDecl>(impl)) {
iface = catImpl->getCategoryDecl();
} else {
iface = impl->getClassInterface();
}
- const ObjCMethodDecl *ifaceMD =
+ const ObjCMethodDecl *ifaceMD =
iface->getMethod(MD->getSelector(), MD->isInstanceMethod());
if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);
}
@@ -1476,11 +1481,11 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) {
const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
if (!MsgSend)
return;
-
+
const ObjCMethodDecl *Method = MsgSend->getMethodDecl();
if (!Method)
return;
-
+
if (!Method->hasRelatedResultType())
return;
@@ -1491,7 +1496,7 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) {
if (!Context.hasSameUnqualifiedType(Method->getReturnType(),
Context.getObjCInstanceType()))
return;
-
+
Diag(Method->getLocation(), diag::note_related_result_type_inferred)
<< Method->isInstanceMethod() << Method->getSelector()
<< MsgSend->getType();
@@ -1555,7 +1560,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
}
else
Diag(SelLoc, DiagID)
- << Sel << isClassMessage << SourceRange(SelectorLocs.front(),
+ << Sel << isClassMessage << SourceRange(SelectorLocs.front(),
SelectorLocs.back());
// Find the class to which we are sending this message.
if (ReceiverType->isObjCObjectPointerType()) {
@@ -1582,7 +1587,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
return false;
}
- ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
+ ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
isSuperMessage);
VK = Expr::getValueKindForType(Method->getReturnType());
@@ -1613,6 +1618,11 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
ParmVarDecl *param = Method->parameters()[i];
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
+ if (param->hasAttr<NoEscapeAttr>())
+ if (auto *BE = dyn_cast<BlockExpr>(
+ argExpr->IgnoreParenNoopCasts(Context)))
+ BE->getBlockDecl()->setDoesNotEscape();
+
// Strip the unbridged-cast placeholder expression off unless it's
// a consumed argument.
if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
@@ -1741,7 +1751,7 @@ ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
return nullptr;
}
-/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
+/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
/// list of a qualified objective pointer type.
ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
const ObjCObjectPointerType *OPT,
@@ -1775,14 +1785,14 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
}
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
-
+
SourceRange BaseRange = Super? SourceRange(SuperLoc)
: BaseExpr->getSourceRange();
- if (RequireCompleteType(MemberLoc, OPT->getPointeeType(),
+ if (RequireCompleteType(MemberLoc, OPT->getPointeeType(),
diag::err_property_not_found_forward_class,
MemberName, BaseRange))
return ExprError();
-
+
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(
Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
// Check whether we can reference this property.
@@ -1822,7 +1832,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
-
+
// May be found in property's qualified list.
if (!Getter)
Getter = LookupMethodInQualifiedType(Sel, OPT, true);
@@ -1842,17 +1852,17 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
PP.getSelectorTable(), Member);
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
-
+
// May be found in property's qualified list.
if (!Setter)
Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);
-
+
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
Setter = IFace->lookupPrivateMethod(SetterSel);
}
-
+
if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
return ExprError();
@@ -1916,23 +1926,23 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
}
}
ObjCInterfaceDecl *ClassDeclared;
- if (ObjCIvarDecl *Ivar =
+ if (ObjCIvarDecl *Ivar =
IFace->lookupInstanceVariable(Member, ClassDeclared)) {
QualType T = Ivar->getType();
- if (const ObjCObjectPointerType * OBJPT =
+ if (const ObjCObjectPointerType * OBJPT =
T->getAsObjCInterfacePointerType()) {
- if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),
+ if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),
diag::err_property_not_as_forward_class,
MemberName, BaseExpr))
return ExprError();
}
- Diag(MemberLoc,
+ Diag(MemberLoc,
diag::err_ivar_access_using_property_syntax_suggest)
<< MemberName << QualType(OPT, 0) << Ivar->getDeclName()
<< FixItHint::CreateReplacement(OpLoc, "->");
return ExprError();
}
-
+
Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << QualType(OPT, 0);
if (Setter)
@@ -2076,10 +2086,10 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
// trailing dot, it's an instance message.
if (IsSuper && S->isInObjcMethodScope())
return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;
-
+
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
LookupName(Result, S);
-
+
switch (Result.getResultKind()) {
case LookupResult::NotFound:
// Normal name lookup didn't find anything. If we're in an
@@ -2093,11 +2103,11 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
}
ObjCInterfaceDecl *ClassDeclared;
- if (Method->getClassInterface()->lookupInstanceVariable(Name,
+ if (Method->getClassInterface()->lookupInstanceVariable(Name,
ClassDeclared))
return ObjCInstanceMessage;
}
-
+
// Break out; we'll perform typo correction below.
break;
@@ -2161,7 +2171,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
return ObjCInstanceMessage;
}
-ExprResult Sema::ActOnSuperMessage(Scope *S,
+ExprResult Sema::ActOnSuperMessage(Scope *S,
SourceLocation SuperLoc,
Selector Sel,
SourceLocation LBracLoc,
@@ -2203,7 +2213,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
-
+
// Since we are in a class method, this is a class message to
// the superclass.
return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
@@ -2319,7 +2329,7 @@ static void checkFoundationAPI(Sema &S, SourceLocation Loc,
}
}
-/// \brief Diagnose use of %s directive in an NSString which is being passed
+/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
static void
DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
@@ -2343,7 +2353,7 @@ DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
}
if (!Format || NumArgs <= Idx)
return;
-
+
Expr *FormatExpr = Args[Idx];
if (ObjCStringLiteral *OSL =
dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) {
@@ -2358,7 +2368,7 @@ DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
}
}
-/// \brief Build an Objective-C class message expression.
+/// Build an Objective-C class message expression.
///
/// This routine takes care of both normal class messages and
/// class messages to the superclass.
@@ -2391,7 +2401,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
SourceLocation SuperLoc,
Selector Sel,
ObjCMethodDecl *Method,
- SourceLocation LBracLoc,
+ SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
SourceLocation RBracLoc,
MultiExprArg ArgsIn,
@@ -2403,11 +2413,12 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
<< FixItHint::CreateInsertion(Loc, "[");
LBracLoc = Loc;
}
- SourceLocation SelLoc;
+ ArrayRef<SourceLocation> SelectorSlotLocs;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
- SelLoc = SelectorLocs.front();
+ SelectorSlotLocs = SelectorLocs;
else
- SelLoc = Loc;
+ SelectorSlotLocs = Loc;
+ SourceLocation SelLoc = SelectorSlotLocs.front();
if (ReceiverType->isDependentType()) {
// If the receiver type is dependent, we can't type-check anything
@@ -2420,7 +2431,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), RBracLoc,
isImplicit);
}
-
+
// Find the class to which we are sending this message.
ObjCInterfaceDecl *Class = nullptr;
const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
@@ -2432,10 +2443,10 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
assert(Class && "We don't know which class we're messaging?");
// objc++ diagnoses during typename annotation.
if (!getLangOpts().CPlusPlus)
- (void)DiagnoseUseOfDecl(Class, SelLoc);
+ (void)DiagnoseUseOfDecl(Class, SelectorSlotLocs);
// Find the method we are messaging.
if (!Method) {
- SourceRange TypeRange
+ SourceRange TypeRange
= SuperLoc.isValid()? SourceRange(SuperLoc)
: ReceiverTypeInfo->getTypeLoc().getSourceRange();
if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),
@@ -2444,7 +2455,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
: diag::warn_receiver_forward_class),
TypeRange)) {
// A forward class used in messaging is treated as a 'Class'
- Method = LookupFactoryMethodInGlobalPool(Sel,
+ Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
if (Method && !getLangOpts().ObjCAutoRefCount)
Diag(Method->getLocation(), diag::note_method_sent_forward_class)
@@ -2457,7 +2468,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
if (!Method)
Method = Class->lookupPrivateClassMethod(Sel);
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
}
@@ -2479,7 +2490,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
RequireCompleteType(LBracLoc, Method->getReturnType(),
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
-
+
// Warn about explicit call of +initialize on its own class. But not on 'super'.
if (Method && Method->getMethodFamily() == OMF_initialize) {
if (!SuperLoc.isValid()) {
@@ -2502,19 +2513,19 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
}
}
}
-
+
DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs);
-
+
// Construct the appropriate ObjCMessageExpr.
ObjCMessageExpr *Result;
if (SuperLoc.isValid())
- Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
- SuperLoc, /*IsInstanceSuper=*/false,
+ Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+ SuperLoc, /*IsInstanceSuper=*/false,
ReceiverType, Sel, SelectorLocs,
Method, makeArrayRef(Args, NumArgs),
RBracLoc, isImplicit);
else {
- Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+ Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
ReceiverTypeInfo, Sel, SelectorLocs,
Method, makeArrayRef(Args, NumArgs),
RBracLoc, isImplicit);
@@ -2530,7 +2541,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
-ExprResult Sema::ActOnClassMessage(Scope *S,
+ExprResult Sema::ActOnClassMessage(Scope *S,
ParsedType Receiver,
Selector Sel,
SourceLocation LBracLoc,
@@ -2545,7 +2556,7 @@ ExprResult Sema::ActOnClassMessage(Scope *S,
if (!ReceiverTypeInfo)
ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
- return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
+ return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
/*SuperLoc=*/SourceLocation(), Sel,
/*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,
Args);
@@ -2581,7 +2592,7 @@ static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {
return false;
}
-/// \brief Build an Objective-C instance message expression.
+/// Build an Objective-C instance message expression.
///
/// This routine takes care of both normal instance messages and
/// instance messages to the superclass instance.
@@ -2614,7 +2625,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
SourceLocation SuperLoc,
Selector Sel,
ObjCMethodDecl *Method,
- SourceLocation LBracLoc,
+ SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
SourceLocation RBracLoc,
MultiExprArg ArgsIn,
@@ -2627,11 +2638,12 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
SourceRange RecRange =
SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
- SourceLocation SelLoc;
+ ArrayRef<SourceLocation> SelectorSlotLocs;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
- SelLoc = SelectorLocs.front();
+ SelectorSlotLocs = SelectorLocs;
else
- SelLoc = Loc;
+ SelectorSlotLocs = Loc;
+ SourceLocation SelLoc = SelectorSlotLocs.front();
if (LBracLoc.isInvalid()) {
Diag(Loc, diag::err_missing_open_square_message_send)
@@ -2679,15 +2691,15 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// do nothing
} else if (!getLangOpts().ObjCAutoRefCount &&
!Context.getObjCIdType().isNull() &&
- (ReceiverType->isPointerType() ||
+ (ReceiverType->isPointerType() ||
ReceiverType->isIntegerType())) {
// Implicitly convert integers and pointers to 'id' but emit a warning.
// But not in ARC.
Diag(Loc, diag::warn_bad_receiver_type)
- << ReceiverType
+ << ReceiverType
<< Receiver->getSourceRange();
if (ReceiverType->isPointerType()) {
- Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
CK_CPointerToObjCPointerCast).get();
} else {
// TODO: specialized warning on null receivers?
@@ -2743,7 +2755,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!AreMultipleMethodsInGlobalPool(Sel, Method,
SourceRange(LBracLoc, RBracLoc),
receiverIsIdLike, Methods))
- DiagnoseUseOfDecl(Method, SelLoc);
+ DiagnoseUseOfDecl(Method, SelectorSlotLocs);
}
} else if (ReceiverType->isObjCClassOrClassKindOfType() ||
ReceiverType->isObjCQualifiedClassType()) {
@@ -2775,7 +2787,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!Method)
Method = ClassDecl->lookupPrivateClassMethod(Sel);
}
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
}
if (!Method) {
@@ -2792,7 +2804,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// to select a better one.
Method = Methods[0];
- // If we find an instance method, emit waring.
+ // If we find an instance method, emit warning.
if (Method->isInstanceMethod()) {
if (const ObjCInterfaceDecl *ID =
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
@@ -2816,13 +2828,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
// long as one of the protocols implements the selector (if not, warn).
// And as long as message is not deprecated/unavailable (warn if it is).
- if (const ObjCObjectPointerType *QIdTy
+ if (const ObjCObjectPointerType *QIdTy
= ReceiverType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
if (!Method)
Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
} else if (const ObjCObjectPointerType *OCIType
= ReceiverType->getAsObjCInterfacePointerType()) {
@@ -2842,9 +2854,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
: SourceRange(SuperLoc))) {
if (getLangOpts().ObjCAutoRefCount)
return ExprError();
-
+
forwardClass = OCIType->getInterfaceDecl();
- Diag(Receiver ? Receiver->getLocStart()
+ Diag(Receiver ? Receiver->getLocStart()
: SuperLoc, diag::note_receiver_is_id);
Method = nullptr;
} else {
@@ -2854,7 +2866,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!Method)
// Search protocol qualifiers.
Method = LookupMethodInQualifiedType(Sel, OCIType, true);
-
+
if (!Method) {
// If we have implementations in scope, check "private" methods.
Method = ClassDecl->lookupPrivateMethod(Sel);
@@ -2897,7 +2909,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
}
- if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass))
return ExprError();
} else {
// Reject other random receiver types (e.g. structs).
@@ -2963,7 +2975,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ReceiverType->isObjCQualifiedClassType());
if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
Sel, SelectorLocs, Method,
- ClassMessage, SuperLoc.isValid(),
+ ClassMessage, SuperLoc.isValid(),
LBracLoc, RBracLoc, RecRange, ReturnType, VK))
return ExprError();
@@ -2972,7 +2984,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
- // In ARC, forbid the user from sending messages to
+ // In ARC, forbid the user from sending messages to
// retain/release/autorelease/dealloc/retainCount explicitly.
if (getLangOpts().ObjCAutoRefCount) {
ObjCMethodFamily family =
@@ -3001,13 +3013,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Diag(SelLoc, diag::err_arc_illegal_explicit_message)
<< Sel << RecRange;
break;
-
+
case OMF_performSelector:
if (Method && NumArgs >= 1) {
if (const auto *SelExp =
dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens())) {
Selector ArgSel = SelExp->getSelector();
- ObjCMethodDecl *SelMethod =
+ ObjCMethodDecl *SelMethod =
LookupInstanceMethodInGlobalPool(ArgSel,
SelExp->getSourceRange());
if (!SelMethod)
@@ -3024,8 +3036,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
case OMF_init:
// Issue error, unless ns_returns_not_retained.
if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
- // selector names a +1 method
- Diag(SelLoc,
+ // selector names a +1 method
+ Diag(SelLoc,
diag::err_arc_perform_selector_retains);
Diag(SelMethod->getLocation(), diag::note_method_declared_at)
<< SelMethod->getDeclName();
@@ -3035,7 +3047,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// +0 call. OK. unless ns_returns_retained.
if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {
// selector names a +1 method
- Diag(SelLoc,
+ Diag(SelLoc,
diag::err_arc_perform_selector_retains);
Diag(SelMethod->getLocation(), diag::note_method_declared_at)
<< SelMethod->getDeclName();
@@ -3054,13 +3066,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs);
-
+
// Construct the appropriate ObjCMessageExpr instance.
ObjCMessageExpr *Result;
if (SuperLoc.isValid())
Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
SuperLoc, /*IsInstanceSuper=*/true,
- ReceiverType, Sel, SelectorLocs, Method,
+ ReceiverType, Sel, SelectorLocs, Method,
makeArrayRef(Args, NumArgs), RBracLoc,
isImplicit);
else {
@@ -3146,7 +3158,7 @@ static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
ExprResult Sema::ActOnInstanceMessage(Scope *S,
- Expr *Receiver,
+ Expr *Receiver,
Selector Sel,
SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3161,7 +3173,7 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S,
if (Result.isInvalid()) return ExprError();
Receiver = Result.get();
}
-
+
if (RespondsToSelectorSel.isNull()) {
IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");
RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId);
@@ -3206,13 +3218,13 @@ static bool isAnyCLike(ARCConversionTypeClass ACTC) {
static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {
bool isIndirect = false;
-
+
// Ignore an outermost reference type.
if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
type = ref->getPointeeType();
isIndirect = true;
}
-
+
// Drill through pointers and arrays recursively.
while (true) {
if (const PointerType *ptr = type->getAs<PointerType>()) {
@@ -3230,7 +3242,7 @@ static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {
}
isIndirect = true;
}
-
+
if (isIndirect) {
if (type->isObjCARCBridgableType())
return ACTC_indirectRetainable;
@@ -3310,7 +3322,7 @@ namespace {
return ACC_invalid;
}
-
+
/// Look through certain implicit and explicit casts.
ACCResult VisitCastExpr(CastExpr *e) {
switch (e->getCastKind()) {
@@ -3416,10 +3428,10 @@ namespace {
// Otherwise, don't do anything implicit with an unaudited function.
if (!fn->hasAttr<CFAuditedTransferAttr>())
return ACC_invalid;
-
+
// Otherwise, it's +0 unless it follows the create convention.
if (ento::coreFoundation::followsCreateRule(fn))
- return Diagnose ? ACC_plusOne
+ return Diagnose ? ACC_plusOne
: ACC_invalid; // ACC_plusOne if we start accepting this
return ACC_plusZero;
@@ -3446,7 +3458,7 @@ namespace {
// return type is CF.
if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType()))
return ACC_invalid;
-
+
// If the method is explicitly marked not-retained, it's +0.
if (method->hasAttr<CFReturnsNotRetainedAttr>())
return ACC_plusZero;
@@ -3491,6 +3503,7 @@ static void addFixitForObjCARCConversion(Sema &S,
// We handle C-style and implicit casts here.
switch (CCK) {
case Sema::CCK_ImplicitConversion:
+ case Sema::CCK_ForBuiltinOverloadedOp:
case Sema::CCK_CStyleCast:
case Sema::CCK_OtherCast:
break;
@@ -3504,12 +3517,12 @@ static void addFixitForObjCARCConversion(Sema &S,
SourceRange range(NCE->getOperatorLoc(),
NCE->getAngleBrackets().getEnd());
SmallString<32> BridgeCall;
-
+
SourceManager &SM = S.getSourceManager();
char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts()))
BridgeCall += ' ';
-
+
BridgeCall += CFBridgeName;
DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));
}
@@ -3610,7 +3623,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
Sema::CheckedConversionKind CCK) {
SourceLocation loc =
(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
-
+
if (S.makeUnavailableInSystemHeader(loc,
UnavailableAttr::IR_ARCForbiddenConversion))
return;
@@ -3624,7 +3637,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
(exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))
return;
-
+
unsigned srcKind = 0;
switch (exprACTC) {
case ACTC_none:
@@ -3639,16 +3652,18 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
srcKind = 4;
break;
}
-
+
// Check whether this could be fixed with a bridge cast.
SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());
SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
+ unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1;
+
// Bridge from an ARC type to a CF type.
if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {
S.Diag(loc, diag::err_arc_cast_requires_bridge)
- << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+ << convKindForDiag
<< 2 // of C pointer type
<< castExprType
<< unsigned(castType->isBlockPointerType()) // to ObjC|block type
@@ -3656,12 +3671,12 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
<< castRange
<< castExpr->getSourceRange();
bool br = S.isKnownName("CFBridgingRelease");
- ACCResult CreateRule =
+ ACCResult CreateRule =
ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
if (CreateRule != ACC_plusOne)
{
- DiagnosticBuilder DiagB =
+ DiagnosticBuilder DiagB =
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
@@ -3685,19 +3700,19 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
return;
}
-
+
// Bridge from a CF type to an ARC type.
if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
bool br = S.isKnownName("CFBridgingRetain");
S.Diag(loc, diag::err_arc_cast_requires_bridge)
- << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+ << convKindForDiag
<< unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
<< castExprType
<< 2 // to C pointer type
<< castType
<< castRange
<< castExpr->getSourceRange();
- ACCResult CreateRule =
+ ACCResult CreateRule =
ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
if (CreateRule != ACC_plusOne)
@@ -3725,9 +3740,9 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
return;
}
-
+
S.Diag(loc, diag::err_arc_mismatched_cast)
- << (CCK != Sema::CCK_ImplicitConversion)
+ << !convKindForDiag
<< srcKind << castExprType << castType
<< castRange << castExpr->getSourceRange();
}
@@ -3744,7 +3759,7 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
HadTheAttribute = true;
if (Parm->isStr("id"))
return true;
-
+
NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
@@ -3882,7 +3897,7 @@ void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
HasObjCBridgeMutableAttr, false);
if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
return;
-
+
if (HasObjCBridgeAttr)
CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
true);
@@ -3903,7 +3918,7 @@ void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
HasObjCBridgeMutableAttr, false);
if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
return;
-
+
if (HasObjCBridgeAttr)
CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
true);
@@ -3925,7 +3940,7 @@ void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {
SrcType = Getter->getReturnType();
}
}
-
+
ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType);
ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType);
if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)
@@ -3962,7 +3977,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);
if (!ObjCBAttr)
return false;
-
+
IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
@@ -3993,7 +4008,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
}
return false;
}
-
+
// Check for an existing class method with the given selector name.
if (CfToNs && CMId) {
Selector Sel = Context.Selectors.getUnarySelector(CMId);
@@ -4007,7 +4022,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
return false;
}
}
-
+
// Check for an existing instance method with the given selector name.
if (!CfToNs && IMId) {
Selector Sel = Context.Selectors.getNullarySelector(IMId);
@@ -4034,7 +4049,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
if (!CfToNs && !NsToCf)
return false;
-
+
ObjCInterfaceDecl *RelatedClass;
ObjCMethodDecl *ClassMethod = nullptr;
ObjCMethodDecl *InstanceMethod = nullptr;
@@ -4043,7 +4058,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
ClassMethod, InstanceMethod, TDNDecl,
CfToNs, Diagnose))
return false;
-
+
if (CfToNs) {
// Implicit conversion from CF to ObjC object is needed.
if (ClassMethod) {
@@ -4060,7 +4075,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
<< FixItHint::CreateInsertion(SrcExprEndLoc, "]");
Diag(RelatedClass->getLocStart(), diag::note_declared_at);
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
-
+
QualType receiverType = Context.getObjCInterfaceType(RelatedClass);
// Argument.
Expr *args[] = { SrcExpr };
@@ -4103,7 +4118,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
}
Diag(RelatedClass->getLocStart(), diag::note_declared_at);
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
-
+
ExprResult msg =
BuildInstanceMessageImplicit(SrcExpr, SrcType,
InstanceMethod->getLocation(),
@@ -4129,7 +4144,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
QualType effCastType = castType;
if (const ReferenceType *ref = castType->getAs<ReferenceType>())
effCastType = ref->getPointeeType();
-
+
ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);
ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);
if (exprACTC == castACTC) {
@@ -4152,7 +4167,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
if (QDT != castType &&
QDT.getObjCLifetime() != Qualifiers::OCL_None) {
if (Diagnose) {
- SourceLocation loc = (castRange.isValid() ? castRange.getBegin()
+ SourceLocation loc = (castRange.isValid() ? castRange.getBegin()
: castExpr->getExprLoc());
Diag(loc, diag::err_arc_nolifetime_behavior);
}
@@ -4173,14 +4188,14 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
// vice-versa).
if (castACTC == ACTC_none && castType->isIntegralType(Context))
return ACR_okay;
-
+
// Allow casts between pointers to lifetime types (e.g., __strong id*)
// and pointers to void (e.g., cv void *). Casting from void* to lifetime*
// must be explicit.
if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr)
return ACR_okay;
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
- CCK != CCK_ImplicitConversion)
+ isCast(CCK))
return ACR_okay;
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
@@ -4205,8 +4220,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
// If this is a non-implicit cast from id or block type to a
// CoreFoundation type, delay complaining in case the cast is used
// in an acceptable context.
- if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&
- CCK != CCK_ImplicitConversion)
+ if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && isCast(CCK))
return ACR_unbridged;
// Issue a diagnostic about a missing @-sign when implicit casting a cstring
@@ -4215,7 +4229,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&
ConversionToObjCStringLiteralCheck(castType, castExpr, Diagnose))
return ACR_error;
-
+
// Do not issue "bridge cast" diagnostic when implicit casting
// a retainable object to a CF type parameter belonging to an audited
// CF API function. Let caller issue a normal type mismatched diagnostic
@@ -4276,9 +4290,9 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) {
} else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
assert(uo->getOpcode() == UO_Extension);
Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
- return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(),
- sub->getValueKind(), sub->getObjectKind(),
- uo->getOperatorLoc());
+ return new (Context)
+ UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(),
+ sub->getObjectKind(), uo->getOperatorLoc(), false);
} else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
assert(!gse->isResultDependent());
@@ -4308,9 +4322,9 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) {
bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
QualType exprType) {
- QualType canCastType =
+ QualType canCastType =
Context.getCanonicalType(castType).getUnqualifiedType();
- QualType canExprType =
+ QualType canExprType =
Context.getCanonicalType(exprType).getUnqualifiedType();
if (isa<ObjCObjectPointerType>(canCastType) &&
castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
@@ -4385,7 +4399,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
switch (Kind) {
case OBC_Bridge:
break;
-
+
case OBC_BridgeRetained: {
bool br = isKnownName("CFBridgingRelease");
Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
@@ -4399,14 +4413,14 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge");
Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer)
<< FromType << br
- << FixItHint::CreateReplacement(BridgeKeywordLoc,
- br ? "CFBridgingRelease "
+ << FixItHint::CreateReplacement(BridgeKeywordLoc,
+ br ? "CFBridgingRelease "
: "__bridge_transfer ");
Kind = OBC_Bridge;
break;
}
-
+
case OBC_BridgeTransfer:
// We must consume the Objective-C object produced by the cast.
MustConsume = true;
@@ -4421,14 +4435,14 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
// is very dangerous, so we don't do it.
SubExpr = maybeUndoReclaimObject(SubExpr);
break;
-
- case OBC_BridgeRetained:
+
+ case OBC_BridgeRetained:
// Produce the object before casting it.
SubExpr = ImplicitCastExpr::Create(Context, FromType,
CK_ARCProduceObject,
SubExpr, nullptr, VK_RValue);
break;
-
+
case OBC_BridgeTransfer: {
bool br = isKnownName("CFBridgingRetain");
Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
@@ -4438,14 +4452,14 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
<< T
<< SubExpr->getSourceRange()
<< Kind;
-
+
Diag(BridgeKeywordLoc, diag::note_arc_bridge)
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge ");
Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained)
<< T << br
- << FixItHint::CreateReplacement(BridgeKeywordLoc,
+ << FixItHint::CreateReplacement(BridgeKeywordLoc,
br ? "CFBridgingRetain " : "__bridge_retained");
-
+
Kind = OBC_Bridge;
break;
}
@@ -4461,13 +4475,13 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,
BridgeKeywordLoc,
TSInfo, SubExpr);
-
+
if (MustConsume) {
Cleanup.setExprNeedsCleanups(true);
- Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
+ Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
nullptr, VK_RValue);
}
-
+
return Result;
}
@@ -4484,6 +4498,6 @@ ExprResult Sema::ActOnObjCBridgedCast(Scope *S,
CheckTollFreeBridgeCast(T, SubExpr);
if (!TSInfo)
TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);
- return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
+ return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
SubExpr);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index df64a33954fa..01ef86c656bb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Designator.h"
@@ -32,7 +33,7 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
-/// \brief Check whether T is compatible with a wide character type (wchar_t,
+/// Check whether T is compatible with a wide character type (wchar_t,
/// char16_t or char32_t).
static bool IsWideCharCompatible(QualType T, ASTContext &Context) {
if (Context.typesAreCompatible(Context.getWideCharType(), T))
@@ -49,10 +50,12 @@ enum StringInitFailureKind {
SIF_NarrowStringIntoWideChar,
SIF_WideStringIntoChar,
SIF_IncompatWideStringIntoWideChar,
+ SIF_UTF8StringIntoPlainChar,
+ SIF_PlainStringIntoUTF8Char,
SIF_Other
};
-/// \brief Check whether the array of type AT can be initialized by the Init
+/// Check whether the array of type AT can be initialized by the Init
/// expression by means of string initialization. Returns SIF_None if so,
/// otherwise returns a StringInitFailureKind that describes why the
/// initialization would not work.
@@ -77,12 +80,21 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
Context.getCanonicalType(AT->getElementType()).getUnqualifiedType();
switch (SL->getKind()) {
- case StringLiteral::Ascii:
case StringLiteral::UTF8:
+ // char8_t array can be initialized with a UTF-8 string.
+ if (ElemTy->isChar8Type())
+ return SIF_None;
+ LLVM_FALLTHROUGH;
+ case StringLiteral::Ascii:
// char array can be initialized with a narrow string.
// Only allow char x[] = "foo"; not char x[] = L"foo";
if (ElemTy->isCharType())
- return SIF_None;
+ return (SL->getKind() == StringLiteral::UTF8 &&
+ Context.getLangOpts().Char8)
+ ? SIF_UTF8StringIntoPlainChar
+ : SIF_None;
+ if (ElemTy->isChar8Type())
+ return SIF_PlainStringIntoUTF8Char;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_NarrowStringIntoWideChar;
return SIF_Other;
@@ -94,7 +106,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
case StringLiteral::UTF16:
if (Context.typesAreCompatible(Context.Char16Ty, ElemTy))
return SIF_None;
- if (ElemTy->isCharType())
+ if (ElemTy->isCharType() || ElemTy->isChar8Type())
return SIF_WideStringIntoChar;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_IncompatWideStringIntoWideChar;
@@ -102,7 +114,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
case StringLiteral::UTF32:
if (Context.typesAreCompatible(Context.Char32Ty, ElemTy))
return SIF_None;
- if (ElemTy->isCharType())
+ if (ElemTy->isCharType() || ElemTy->isChar8Type())
return SIF_WideStringIntoChar;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_IncompatWideStringIntoWideChar;
@@ -110,7 +122,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
case StringLiteral::Wide:
if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy))
return SIF_None;
- if (ElemTy->isCharType())
+ if (ElemTy->isCharType() || ElemTy->isChar8Type())
return SIF_WideStringIntoChar;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_IncompatWideStringIntoWideChar;
@@ -179,7 +191,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
if (SL->isPascal())
StrLength--;
}
-
+
// [dcl.init.string]p2
if (StrLength > CAT->getSize().getZExtValue())
S.Diag(Str->getLocStart(),
@@ -206,7 +218,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
namespace {
-/// @brief Semantic checking for initializer lists.
+/// Semantic checking for initializer lists.
///
/// The InitListChecker class contains a set of routines that each
/// handle the initialization of a certain kind of entity, e.g.,
@@ -366,7 +378,7 @@ public:
bool TreatUnavailableAsInvalid);
bool HadError() { return hadError; }
- // @brief Retrieves the fully-structured initializer list used for
+ // Retrieves the fully-structured initializer list used for
// semantic analysis and code generation.
InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
};
@@ -438,7 +450,7 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
IsInStd = true;
}
- if (IsInStd && llvm::StringSwitch<bool>(R->getName())
+ if (IsInStd && llvm::StringSwitch<bool>(R->getName())
.Cases("basic_string", "deque", "forward_list", true)
.Cases("list", "map", "multimap", "multiset", true)
.Cases("priority_queue", "queue", "set", "stack", true)
@@ -561,6 +573,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
hadError = true;
return;
}
+ SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
if (Init < NumInits)
ILE->setInit(Init, DIE.get());
else {
@@ -740,6 +753,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
ElementEntity.setElementIndex(Init);
+ if (Init >= NumInits && ILE->hasArrayFiller())
+ return;
+
Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
if (!InitExpr && Init < NumInits && ILE->hasArrayFiller())
ILE->setInit(Init, ILE->getArrayFiller());
@@ -1005,6 +1021,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_Binding:
+ case InitializedEntity::EK_StmtExprResult:
llvm_unreachable("unexpected braced scalar init");
}
@@ -1561,7 +1578,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
T->getVectorKind() == VectorType::NeonPolyVector)) {
// The ability to use vector initializer lists is a GNU vector extension
// and is unrelated to the NEON intrinsics in arm_neon.h. On little
- // endian machines it works fine, however on big endian machines it
+ // endian machines it works fine, however on big endian machines it
// exhibits surprising behaviour:
//
// uint32x2_t x = {42, 64};
@@ -2014,7 +2031,7 @@ void InitListChecker::CheckStructUnionTypes(
StructuredList, StructuredIndex);
}
-/// \brief Expand a field designator that refers to a member of an
+/// Expand a field designator that refers to a member of an
/// anonymous struct or union into a series of field designators that
/// refers to the field within the appropriate subobject.
///
@@ -2078,7 +2095,7 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
} // end anonymous namespace
-/// @brief Check the well-formedness of a C99 designated initializer.
+/// Check the well-formedness of a C99 designated initializer.
///
/// Determines whether the designated initializer @p DIE, which
/// resides at the given @p Index within the initializer list @p
@@ -2208,7 +2225,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
SemaRef.Diag(D->getLocStart(),
diag::warn_subobject_initializer_overrides)
<< SourceRange(D->getLocStart(), DIE->getLocEnd());
-
+
SemaRef.Diag(ExistingInit->getLocStart(),
diag::note_previous_initializer)
<< /*FIXME:has side effects=*/0
@@ -2983,8 +3000,9 @@ DeclarationName InitializedEntity::getName() const {
case EK_LambdaCapture:
return DeclarationName(Capture.VarID);
-
+
case EK_Result:
+ case EK_StmtExprResult:
case EK_Exception:
case EK_New:
case EK_Temporary:
@@ -3015,6 +3033,7 @@ ValueDecl *InitializedEntity::getDecl() const {
return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
case EK_Result:
+ case EK_StmtExprResult:
case EK_Exception:
case EK_New:
case EK_Temporary:
@@ -3040,6 +3059,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Exception:
return LocAndNRVO.NRVO;
+ case EK_StmtExprResult:
case EK_Variable:
case EK_Parameter:
case EK_Parameter_CF_Audited:
@@ -3075,6 +3095,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_Parameter_CF_Audited: OS << "CF audited function Parameter";
break;
case EK_Result: OS << "Result"; break;
+ case EK_StmtExprResult: OS << "StmtExprResult"; break;
case EK_Exception: OS << "Exception"; break;
case EK_Member: OS << "Member"; break;
case EK_Binding: OS << "Binding"; break;
@@ -3185,6 +3206,8 @@ bool InitializationSequence::isAmbiguous() const {
case FK_NarrowStringIntoWideCharArray:
case FK_WideStringIntoCharArray:
case FK_IncompatWideStringIntoWideChar:
+ case FK_PlainStringIntoUTF8Char:
+ case FK_UTF8StringIntoPlainChar:
case FK_AddressOfOverloadFailed: // FIXME: Could do better
case FK_NonConstLValueReferenceBindingToTemporary:
case FK_NonConstLValueReferenceBindingToBitfield:
@@ -3517,7 +3540,8 @@ static void MaybeProduceObjCObject(Sema &S,
/// retainable type, then returns need to immediately retain the
/// object. If an autorelease is required, it will be done at the
/// last instant.
- } else if (Entity.getKind() == InitializedEntity::EK_Result) {
+ } else if (Entity.getKind() == InitializedEntity::EK_Result ||
+ Entity.getKind() == InitializedEntity::EK_StmtExprResult) {
if (!Entity.getType()->isObjCRetainableType())
return;
@@ -3532,7 +3556,7 @@ static void TryListInitialization(Sema &S,
InitializationSequence &Sequence,
bool TreatUnavailableAsInvalid);
-/// \brief When initializing from init list via constructor, handle
+/// When initializing from init list via constructor, handle
/// initialization of an object of type std::initializer_list<T>.
///
/// \return true if we have handled initialization of an object of type
@@ -3558,8 +3582,8 @@ static bool TryInitializerListConstruction(Sema &S,
clang::ArrayType::Normal, 0);
InitializedEntity HiddenArray =
InitializedEntity::InitializeTemporary(ArrayType);
- InitializationKind Kind =
- InitializationKind::CreateDirectList(List->getExprLoc());
+ InitializationKind Kind = InitializationKind::CreateDirectList(
+ List->getExprLoc(), List->getLocStart(), List->getLocEnd());
TryListInitialization(S, HiddenArray, Kind, List, Sequence,
TreatUnavailableAsInvalid);
if (Sequence)
@@ -3629,13 +3653,13 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
CandidateSet, SuppressUserConversions);
else {
// C++ [over.match.copy]p1:
- // - When initializing a temporary to be bound to the first parameter
+ // - When initializing a temporary to be bound to the first parameter
// of a constructor [for type T] that takes a reference to possibly
// cv-qualified T as its first argument, called with a single
// argument in the context of direct-initialization, explicit
// conversion functions are also considered.
// FIXME: What if a constructor template instantiates to such a signature?
- bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
+ bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
Args.size() == 1 &&
hasCopyOrMoveCtorParam(S.Context, Info);
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
@@ -3693,7 +3717,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
return CandidateSet.BestViableFunction(S, DeclLoc, Best);
}
-/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
/// \param DestType The destination class type.
@@ -3910,7 +3934,7 @@ static void TryValueInitialization(Sema &S,
InitializationSequence &Sequence,
InitListExpr *InitList = nullptr);
-/// \brief Attempt list initialization of a reference.
+/// Attempt list initialization of a reference.
static void TryReferenceListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3984,7 +4008,7 @@ static void TryReferenceListInitialization(Sema &S,
}
}
-/// \brief Attempt list initialization (C++0x [dcl.init.list])
+/// Attempt list initialization (C++0x [dcl.init.list])
static void TryListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4179,7 +4203,7 @@ static void TryListInitialization(Sema &S,
Sequence.AddListInitializationStep(DestType);
}
-/// \brief Try a reference initialization that involves calling a conversion
+/// Try a reference initialization that involves calling a conversion
/// function.
static OverloadingResult TryRefInitWithConversionFunction(
Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
@@ -4202,15 +4226,17 @@ static OverloadingResult TryRefInitWithConversionFunction(
(void)DerivedToBase;
(void)ObjCConversion;
(void)ObjCLifetimeConversion;
-
+
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
- // Determine whether we are allowed to call explicit constructors or
- // explicit conversion operators.
- bool AllowExplicit = Kind.AllowExplicit();
+ // Determine whether we are allowed to call explicit conversion operators.
+ // Note that none of [over.match.copy], [over.match.conv], nor
+ // [over.match.ref] permit an explicit constructor to be chosen when
+ // initializing a reference, not even for direct-initialization.
+ bool AllowExplicitCtors = false;
bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding();
const RecordType *T1RecordType = nullptr;
@@ -4226,7 +4252,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
continue;
if (!Info.Constructor->isInvalidDecl() &&
- Info.Constructor->isConvertingConstructor(AllowExplicit)) {
+ Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) {
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr,
@@ -4369,7 +4395,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
const InitializedEntity &Entity,
Expr *CurInitExpr);
-/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
+/// Attempt reference initialization (C++0x [dcl.init.ref])
static void TryReferenceInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4396,13 +4422,13 @@ static void TryReferenceInitialization(Sema &S,
}
/// Determine whether an expression is a non-referenceable glvalue (one to
-/// which a reference can never bind). Attemting to bind a reference to
+/// which a reference can never bind). Attempting to bind a reference to
/// such a glvalue will always create a temporary.
static bool isNonReferenceableGLValue(Expr *E) {
return E->refersToBitField() || E->refersToVectorElement();
}
-/// \brief Reference initialization without resolving overloaded functions.
+/// Reference initialization without resolving overloaded functions.
static void TryReferenceInitializationCore(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4620,7 +4646,7 @@ static void TryReferenceInitializationCore(Sema &S,
/*FIXME:InOverloadResolution=*/false,
/*CStyle=*/Kind.isCStyleOrFunctionalCast(),
/*AllowObjCWritebackConversion=*/false);
-
+
if (ICS.isBad()) {
// FIXME: Use the conversion function set stored in ICS to turn
// this into an overloading ambiguity diagnostic. However, we need
@@ -4662,7 +4688,7 @@ static void TryReferenceInitializationCore(Sema &S,
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
}
-/// \brief Attempt character array initialization from a string literal
+/// Attempt character array initialization from a string literal
/// (C++ [dcl.init.string], C99 6.7.8).
static void TryStringLiteralInitialization(Sema &S,
const InitializedEntity &Entity,
@@ -4672,7 +4698,7 @@ static void TryStringLiteralInitialization(Sema &S,
Sequence.AddStringInitStep(Entity.getType());
}
-/// \brief Attempt value initialization (C++ [dcl.init]p7).
+/// Attempt value initialization (C++ [dcl.init]p7).
static void TryValueInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4750,7 +4776,7 @@ static void TryValueInitialization(Sema &S,
Sequence.AddZeroInitializationStep(Entity.getType());
}
-/// \brief Attempt default initialization (C++ [dcl.init]p6).
+/// Attempt default initialization (C++ [dcl.init]p6).
static void TryDefaultInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4761,7 +4787,7 @@ static void TryDefaultInitialization(Sema &S,
// To default-initialize an object of type T means:
// - if T is an array type, each element is default-initialized;
QualType DestType = S.Context.getBaseElementType(Entity.getType());
-
+
// - if T is a (possibly cv-qualified) class type (Clause 9), the default
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
@@ -4789,7 +4815,7 @@ static void TryDefaultInitialization(Sema &S,
}
}
-/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
+/// Attempt a user-defined conversion between two types (C++ [dcl.init]),
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
static void TryUserDefinedConversion(Sema &S,
@@ -5017,11 +5043,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
// If we have a declaration reference, it had better be a local variable.
} else if (isa<DeclRefExpr>(e)) {
- // set isWeakAccess to true, to mean that there will be an implicit
+ // set isWeakAccess to true, to mean that there will be an implicit
// load which requires a cleanup.
if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
isWeakAccess = true;
-
+
if (!isAddressOf) return IIK_nonlocal;
VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
@@ -5056,7 +5082,7 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
assert(src->isRValue());
bool isWeakAccess = false;
InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess);
- // If isWeakAccess to true, there will be an implicit
+ // If isWeakAccess to true, there will be an implicit
// load which requires a cleanup.
if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess)
S.Cleanup.setExprNeedsCleanups(true);
@@ -5068,7 +5094,7 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
<< src->getSourceRange();
}
-/// \brief Determine whether we have compatible array types for the
+/// Determine whether we have compatible array types for the
/// purposes of GNU by-copy array initialization.
static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest,
const ArrayType *Source) {
@@ -5098,7 +5124,7 @@ static bool tryObjCWritebackConversion(Sema &S,
ArgPointee = ArgArrayType->getElementType();
ArgType = S.Context.getPointerType(ArgPointee);
}
-
+
// Handle write-back conversion.
QualType ConvertedArgType;
if (!S.isObjCWritebackConversion(ArgType, Entity.getType(),
@@ -5125,10 +5151,10 @@ static bool tryObjCWritebackConversion(Sema &S,
ICS.Standard.First = ICK_Lvalue_To_Rvalue;
ResultType = Initializer->getType().getNonLValueExprType(S.Context);
}
-
+
Sequence.AddConversionSequenceStep(ICS, ResultType);
}
-
+
Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
return true;
}
@@ -5362,6 +5388,12 @@ void InitializationSequence::InitializeFrom(Sema &S,
case SIF_IncompatWideStringIntoWideChar:
SetFailed(FK_IncompatWideStringIntoWideChar);
return;
+ case SIF_PlainStringIntoUTF8Char:
+ SetFailed(FK_PlainStringIntoUTF8Char);
+ return;
+ case SIF_UTF8StringIntoPlainChar:
+ SetFailed(FK_UTF8StringIntoPlainChar);
+ return;
case SIF_Other:
break;
}
@@ -5535,13 +5567,13 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (ICS.isStandard() &&
ICS.Standard.Second == ICK_Writeback_Conversion) {
// Objective-C ARC writeback conversion.
-
+
// We should copy unless we're passing to an argument explicitly
// marked 'out'.
bool ShouldCopy = true;
if (ParmVarDecl *Param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
-
+
// If there was an lvalue adjustment, add it as a separate conversion.
if (ICS.Standard.First == ICK_Array_To_Pointer ||
ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
@@ -5552,7 +5584,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
LvalueICS.Standard.First = ICS.Standard.First;
AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
}
-
+
AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy);
} else if (ICS.isBad()) {
DeclAccessPair dap;
@@ -5603,10 +5635,11 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
if (Entity.getDecl() &&
isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
return Sema::AA_Sending;
-
+
return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited;
-
+
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right.
return Sema::AA_Returning;
case InitializedEntity::EK_Temporary:
@@ -5629,13 +5662,14 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
llvm_unreachable("Invalid EntityKind!");
}
-/// \brief Whether we should bind a created object as a temporary when
+/// Whether we should bind a created object as a temporary when
/// initializing the given entity.
static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
@@ -5660,11 +5694,12 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Whether the given entity, when initialized with an object
+/// Whether the given entity, when initialized with an object
/// created for that initialization, requires destruction.
static bool shouldDestroyEntity(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
@@ -5691,11 +5726,12 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Get the location at which initialization diagnostics should appear.
+/// Get the location at which initialization diagnostics should appear.
static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
Expr *Initializer) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult:
return Entity.getReturnLoc();
case InitializedEntity::EK_Exception:
@@ -5707,7 +5743,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_LambdaCapture:
return Entity.getCaptureLoc();
-
+
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Parameter:
@@ -5727,7 +5763,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Make a (potentially elidable) temporary copy of the object
+/// Make a (potentially elidable) temporary copy of the object
/// provided by the given initializer by calling the appropriate copy
/// constructor.
///
@@ -5892,7 +5928,7 @@ static ExprResult CopyObject(Sema &S,
return CurInit;
}
-/// \brief Check whether elidable copy construction for binding a reference to
+/// Check whether elidable copy construction for binding a reference to
/// a temporary would have succeeded if we were building in C++98 mode, for
/// -Wc++98-compat.
static void CheckCXX98CompatAccessibleCopy(Sema &S,
@@ -6029,9 +6065,9 @@ PerformConstructorInitialization(Sema &S,
ExprResult CurInit((Expr *)nullptr);
// C++ [over.match.copy]p1:
- // - When initializing a temporary to be bound to the first parameter
- // of a constructor that takes a reference to possibly cv-qualified
- // T as its first argument, called with a single argument in the
+ // - When initializing a temporary to be bound to the first parameter
+ // of a constructor that takes a reference to possibly cv-qualified
+ // T as its first argument, called with a single argument in the
// context of direct-initialization, explicit conversion functions
// are also considered.
bool AllowExplicitConv =
@@ -6056,10 +6092,7 @@ PerformConstructorInitialization(Sema &S,
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo)
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
- SourceRange ParenOrBraceRange =
- (Kind.getKind() == InitializationKind::IK_DirectList)
- ? SourceRange(LBraceLoc, RBraceLoc)
- : Kind.getParenRange();
+ SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange();
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
Step.Function.FoundDecl.getDecl())) {
@@ -6093,7 +6126,7 @@ PerformConstructorInitialization(Sema &S,
if (IsListInitialization)
ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc);
else if (Kind.getKind() == InitializationKind::IK_Direct)
- ParenOrBraceRange = Kind.getParenRange();
+ ParenOrBraceRange = Kind.getParenOrBraceRange();
// If the entity allows NRVO, mark the construction as elidable
// unconditionally.
@@ -6134,90 +6167,96 @@ PerformConstructorInitialization(Sema &S,
return CurInit;
}
-/// Determine whether the specified InitializedEntity definitely has a lifetime
-/// longer than the current full-expression. Conservatively returns false if
-/// it's unclear.
-static bool
-InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
- const InitializedEntity *Top = &Entity;
- while (Top->getParent())
- Top = Top->getParent();
-
- switch (Top->getKind()) {
- case InitializedEntity::EK_Variable:
- case InitializedEntity::EK_Result:
- case InitializedEntity::EK_Exception:
- case InitializedEntity::EK_Member:
- case InitializedEntity::EK_Binding:
- case InitializedEntity::EK_New:
- case InitializedEntity::EK_Base:
- case InitializedEntity::EK_Delegating:
- return true;
-
- case InitializedEntity::EK_ArrayElement:
- case InitializedEntity::EK_VectorElement:
- case InitializedEntity::EK_BlockElement:
- case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
- case InitializedEntity::EK_ComplexElement:
- // Could not determine what the full initialization is. Assume it might not
- // outlive the full-expression.
- return false;
-
- case InitializedEntity::EK_Parameter:
- case InitializedEntity::EK_Parameter_CF_Audited:
- case InitializedEntity::EK_Temporary:
- case InitializedEntity::EK_LambdaCapture:
- case InitializedEntity::EK_CompoundLiteralInit:
- case InitializedEntity::EK_RelatedResult:
- // The entity being initialized might not outlive the full-expression.
- return false;
- }
-
- llvm_unreachable("unknown entity kind");
+namespace {
+enum LifetimeKind {
+ /// The lifetime of a temporary bound to this entity ends at the end of the
+ /// full-expression, and that's (probably) fine.
+ LK_FullExpression,
+
+ /// The lifetime of a temporary bound to this entity is extended to the
+ /// lifeitme of the entity itself.
+ LK_Extended,
+
+ /// The lifetime of a temporary bound to this entity probably ends too soon,
+ /// because the entity is allocated in a new-expression.
+ LK_New,
+
+ /// The lifetime of a temporary bound to this entity ends too soon, because
+ /// the entity is a return object.
+ LK_Return,
+
+ /// The lifetime of a temporary bound to this entity ends too soon, because
+ /// the entity is the result of a statement expression.
+ LK_StmtExprResult,
+
+ /// This is a mem-initializer: if it would extend a temporary (other than via
+ /// a default member initializer), the program is ill-formed.
+ LK_MemInitializer,
+};
+using LifetimeResult =
+ llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
}
/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
-static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+static LifetimeResult getEntityLifetime(
const InitializedEntity *Entity,
- const InitializedEntity *FallbackDecl = nullptr) {
+ const InitializedEntity *InitField = nullptr) {
// C++11 [class.temporary]p5:
switch (Entity->getKind()) {
case InitializedEntity::EK_Variable:
// The temporary [...] persists for the lifetime of the reference
- return Entity;
+ return {Entity, LK_Extended};
case InitializedEntity::EK_Member:
// For subobjects, we look at the complete object.
if (Entity->getParent())
- return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
- Entity);
+ return getEntityLifetime(Entity->getParent(), Entity);
// except:
- // -- A temporary bound to a reference member in a constructor's
- // ctor-initializer persists until the constructor exits.
- return Entity;
+ // C++17 [class.base.init]p8:
+ // A temporary expression bound to a reference member in a
+ // mem-initializer is ill-formed.
+ // C++17 [class.base.init]p11:
+ // A temporary expression bound to a reference member from a
+ // default member initializer is ill-formed.
+ //
+ // The context of p11 and its example suggest that it's only the use of a
+ // default member initializer from a constructor that makes the program
+ // ill-formed, not its mere existence, and that it can even be used by
+ // aggregate initialization.
+ return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
+ : LK_MemInitializer};
case InitializedEntity::EK_Binding:
// Per [dcl.decomp]p3, the binding is treated as a variable of reference
// type.
- return Entity;
+ return {Entity, LK_Extended};
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
// -- A temporary bound to a reference parameter in a function call
// persists until the completion of the full-expression containing
// the call.
+ return {nullptr, LK_FullExpression};
+
case InitializedEntity::EK_Result:
// -- The lifetime of a temporary bound to the returned value in a
// function return statement is not extended; the temporary is
// destroyed at the end of the full-expression in the return statement.
+ return {nullptr, LK_Return};
+
+ case InitializedEntity::EK_StmtExprResult:
+ // FIXME: Should we lifetime-extend through the result of a statement
+ // expression?
+ return {nullptr, LK_StmtExprResult};
+
case InitializedEntity::EK_New:
// -- A temporary bound to a reference in a new-initializer persists
// until the completion of the full-expression containing the
// new-initializer.
- return nullptr;
+ return {nullptr, LK_New};
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
@@ -6225,56 +6264,190 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
// We don't yet know the storage duration of the surrounding temporary.
// Assume it's got full-expression duration for now, it will patch up our
// storage duration if that's not correct.
- return nullptr;
+ return {nullptr, LK_FullExpression};
case InitializedEntity::EK_ArrayElement:
// For subobjects, we look at the complete object.
- return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
- FallbackDecl);
+ return getEntityLifetime(Entity->getParent(), InitField);
case InitializedEntity::EK_Base:
// For subobjects, we look at the complete object.
if (Entity->getParent())
- return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
- Entity);
- LLVM_FALLTHROUGH;
+ return getEntityLifetime(Entity->getParent(), InitField);
+ return {InitField, LK_MemInitializer};
+
case InitializedEntity::EK_Delegating:
// We can reach this case for aggregate initialization in a constructor:
// struct A { int &&r; };
// struct B : A { B() : A{0} {} };
- // In this case, use the innermost field decl as the context.
- return FallbackDecl;
+ // In this case, use the outermost field decl as the context.
+ return {InitField, LK_MemInitializer};
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_LambdaCapture:
- case InitializedEntity::EK_Exception:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_ComplexElement:
- return nullptr;
+ return {nullptr, LK_FullExpression};
+
+ case InitializedEntity::EK_Exception:
+ // FIXME: Can we diagnose lifetime problems with exceptions?
+ return {nullptr, LK_FullExpression};
}
llvm_unreachable("unknown entity kind");
}
-static void performLifetimeExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity);
+namespace {
+enum ReferenceKind {
+ /// Lifetime would be extended by a reference binding to a temporary.
+ RK_ReferenceBinding,
+ /// Lifetime would be extended by a std::initializer_list object binding to
+ /// its backing array.
+ RK_StdInitializerList,
+};
+
+/// A temporary or local variable. This will be one of:
+/// * A MaterializeTemporaryExpr.
+/// * A DeclRefExpr whose declaration is a local.
+/// * An AddrLabelExpr.
+/// * A BlockExpr for a block with captures.
+using Local = Expr*;
+
+/// Expressions we stepped over when looking for the local state. Any steps
+/// that would inhibit lifetime extension or take us out of subexpressions of
+/// the initializer are included.
+struct IndirectLocalPathEntry {
+ enum EntryKind {
+ DefaultInit,
+ AddressOf,
+ VarInit,
+ LValToRVal,
+ LifetimeBoundCall,
+ } Kind;
+ Expr *E;
+ const Decl *D = nullptr;
+ IndirectLocalPathEntry() {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
+ : Kind(K), E(E), D(D) {}
+};
+
+using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
+
+struct RevertToOldSizeRAII {
+ IndirectLocalPath &Path;
+ unsigned OldSize = Path.size();
+ RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
+ ~RevertToOldSizeRAII() { Path.resize(OldSize); }
+};
+
+using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
+ ReferenceKind RK)>;
+}
+
+static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
+ for (auto E : Path)
+ if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
+ return true;
+ return false;
+}
+
+static bool pathContainsInit(IndirectLocalPath &Path) {
+ return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) {
+ return E.Kind == IndirectLocalPathEntry::DefaultInit ||
+ E.Kind == IndirectLocalPathEntry::VarInit;
+ });
+}
+
+static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
+ Expr *Init, LocalVisitor Visit,
+ bool RevisitSubinits);
+
+static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
+ Expr *Init, ReferenceKind RK,
+ LocalVisitor Visit);
+
+static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
+ const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
+ if (!TSI)
+ return false;
+ // Don't declare this variable in the second operand of the for-statement;
+ // GCC miscompiles that by ending its lifetime before evaluating the
+ // third operand. See gcc.gnu.org/PR86769.
+ AttributedTypeLoc ATL;
+ for (TypeLoc TL = TSI->getTypeLoc();
+ (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
+ TL = ATL.getModifiedLoc()) {
+ if (ATL.getAttrKind() == AttributedType::attr_lifetimebound)
+ return true;
+ }
+ return false;
+}
+
+static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
+ LocalVisitor Visit) {
+ const FunctionDecl *Callee;
+ ArrayRef<Expr*> Args;
+
+ if (auto *CE = dyn_cast<CallExpr>(Call)) {
+ Callee = CE->getDirectCallee();
+ Args = llvm::makeArrayRef(CE->getArgs(), CE->getNumArgs());
+ } else {
+ auto *CCE = cast<CXXConstructExpr>(Call);
+ Callee = CCE->getConstructor();
+ Args = llvm::makeArrayRef(CCE->getArgs(), CCE->getNumArgs());
+ }
+ if (!Callee)
+ return;
+
+ Expr *ObjectArg = nullptr;
+ if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
+ ObjectArg = Args[0];
+ Args = Args.slice(1);
+ } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
+ ObjectArg = MCE->getImplicitObjectArgument();
+ }
+
+ auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
+ Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
+ if (Arg->isGLValue())
+ visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
+ Visit);
+ else
+ visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
+ Path.pop_back();
+ };
+
+ if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
+ VisitLifetimeBoundArg(Callee, ObjectArg);
+
+ for (unsigned I = 0,
+ N = std::min<unsigned>(Callee->getNumParams(), Args.size());
+ I != N; ++I) {
+ if (Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
+ VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
+ }
+}
+
+/// Visit the locals that would be reachable through a reference bound to the
+/// glvalue expression \c Init.
+static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
+ Expr *Init, ReferenceKind RK,
+ LocalVisitor Visit) {
+ RevertToOldSizeRAII RAII(Path);
-/// Update a glvalue expression that is used as the initializer of a reference
-/// to note that its lifetime is extended.
-/// \return \c true if any temporary had its lifetime extended.
-static bool
-performReferenceExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity) {
// Walk past any constructs which we can lifetime-extend across.
Expr *Old;
do {
Old = Init;
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
+ Init = EWC->getSubExpr();
+
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
- if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
- // This is just redundant braces around an initializer. Step over it.
+ // If this is just redundant braces around an initializer, step over it.
+ if (ILE->isTransparent())
Init = ILE->getInit(0);
- }
}
// Step over any subobject adjustments; we may have a materialized
@@ -6288,43 +6461,206 @@ performReferenceExtension(Expr *Init,
Init = CE->getSubExpr();
// Per the current approach for DR1299, look through array element access
- // when performing lifetime extension.
- if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init))
+ // on array glvalues when performing lifetime extension.
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
Init = ASE->getBase();
+ auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
+ if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
+ Init = ICE->getSubExpr();
+ else
+ // We can't lifetime extend through this but we might still find some
+ // retained temporaries.
+ return visitLocalsRetainedByInitializer(Path, Init, Visit, true);
+ }
+
+ // Step into CXXDefaultInitExprs so we can diagnose cases where a
+ // constructor inherits one as an implicit mem-initializer.
+ if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
+ Path.push_back(
+ {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
+ Init = DIE->getExpr();
+ }
} while (Init != Old);
- if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
- // Update the storage duration of the materialized temporary.
- // FIXME: Rebuild the expression instead of mutating it.
- ME->setExtendingDecl(ExtendingEntity->getDecl(),
- ExtendingEntity->allocateManglingNumber());
- performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
- return true;
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
+ if (Visit(Path, Local(MTE), RK))
+ visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit,
+ true);
+ }
+
+ if (isa<CallExpr>(Init))
+ return visitLifetimeBoundArguments(Path, Init, Visit);
+
+ switch (Init->getStmtClass()) {
+ case Stmt::DeclRefExprClass: {
+ // If we find the name of a local non-reference parameter, we could have a
+ // lifetime problem.
+ auto *DRE = cast<DeclRefExpr>(Init);
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (VD && VD->hasLocalStorage() &&
+ !DRE->refersToEnclosingVariableOrCapture()) {
+ if (!VD->getType()->isReferenceType()) {
+ Visit(Path, Local(DRE), RK);
+ } else if (isa<ParmVarDecl>(DRE->getDecl())) {
+ // The lifetime of a reference parameter is unknown; assume it's OK
+ // for now.
+ break;
+ } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
+ Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
+ visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
+ RK_ReferenceBinding, Visit);
+ }
+ }
+ break;
}
- return false;
-}
+ case Stmt::UnaryOperatorClass: {
+ // The only unary operator that make sense to handle here
+ // is Deref. All others don't resolve to a "name." This includes
+ // handling all sorts of rvalues passed to a unary operator.
+ const UnaryOperator *U = cast<UnaryOperator>(Init);
+ if (U->getOpcode() == UO_Deref)
+ visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true);
+ break;
+ }
-/// Update a prvalue expression that is going to be materialized as a
-/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity) {
- // Dig out the expression which constructs the extended temporary.
- Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
+ case Stmt::OMPArraySectionExprClass: {
+ visitLocalsRetainedByInitializer(
+ Path, cast<OMPArraySectionExpr>(Init)->getBase(), Visit, true);
+ break;
+ }
- if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
- Init = BTE->getSubExpr();
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::BinaryConditionalOperatorClass: {
+ auto *C = cast<AbstractConditionalOperator>(Init);
+ if (!C->getTrueExpr()->getType()->isVoidType())
+ visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit);
+ if (!C->getFalseExpr()->getType()->isVoidType())
+ visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit);
+ break;
+ }
- if (CXXStdInitializerListExpr *ILE =
- dyn_cast<CXXStdInitializerListExpr>(Init)) {
- performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
- return;
+ // FIXME: Visit the left-hand side of an -> or ->*.
+
+ default:
+ break;
}
+}
+
+/// Visit the locals that would be reachable through an object initialized by
+/// the prvalue expression \c Init.
+static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
+ Expr *Init, LocalVisitor Visit,
+ bool RevisitSubinits) {
+ RevertToOldSizeRAII RAII(Path);
+
+ Expr *Old;
+ do {
+ Old = Init;
+
+ // Step into CXXDefaultInitExprs so we can diagnose cases where a
+ // constructor inherits one as an implicit mem-initializer.
+ if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
+ Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
+ Init = DIE->getExpr();
+ }
+
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
+ Init = EWC->getSubExpr();
+
+ // Dig out the expression which constructs the extended temporary.
+ Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
+
+ if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
+ Init = BTE->getSubExpr();
+
+ Init = Init->IgnoreParens();
+
+ // Step over value-preserving rvalue casts.
+ if (auto *CE = dyn_cast<CastExpr>(Init)) {
+ switch (CE->getCastKind()) {
+ case CK_LValueToRValue:
+ // If we can match the lvalue to a const object, we can look at its
+ // initializer.
+ Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
+ return visitLocalsRetainedByReferenceBinding(
+ Path, Init, RK_ReferenceBinding,
+ [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (VD && VD->getType().isConstQualified() && VD->getInit() &&
+ !isVarOnPath(Path, VD)) {
+ Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
+ visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true);
+ }
+ } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
+ if (MTE->getType().isConstQualified())
+ visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(),
+ Visit, true);
+ }
+ return false;
+ });
+
+ // We assume that objects can be retained by pointers cast to integers,
+ // but not if the integer is cast to floating-point type or to _Complex.
+ // We assume that casts to 'bool' do not preserve enough information to
+ // retain a local object.
+ case CK_NoOp:
+ case CK_BitCast:
+ case CK_BaseToDerived:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_UserDefinedConversion:
+ case CK_ConstructorConversion:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_AddressSpaceConversion:
+ break;
+
+ case CK_ArrayToPointerDecay:
+ // Model array-to-pointer decay as taking the address of the array
+ // lvalue.
+ Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
+ return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
+ RK_ReferenceBinding, Visit);
+
+ default:
+ return;
+ }
+
+ Init = CE->getSubExpr();
+ }
+ } while (Old != Init);
+
+ // C++17 [dcl.init.list]p6:
+ // initializing an initializer_list object from the array extends the
+ // lifetime of the array exactly like binding a reference to a temporary.
+ if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
+ return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
+ RK_StdInitializerList, Visit);
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ // We already visited the elements of this initializer list while
+ // performing the initialization. Don't visit them again unless we've
+ // changed the lifetime of the initialized entity.
+ if (!RevisitSubinits)
+ return;
+
+ if (ILE->isTransparent())
+ return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
+ RevisitSubinits);
+
if (ILE->getType()->isArrayType()) {
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
- performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
+ visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
+ RevisitSubinits);
return;
}
@@ -6336,7 +6672,8 @@ static void performLifetimeExtension(Expr *Init,
// bound to temporaries, those temporaries are also lifetime-extended.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
- performReferenceExtension(ILE->getInit(0), ExtendingEntity);
+ visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
+ RK_ReferenceBinding, Visit);
else {
unsigned Index = 0;
for (const auto *I : RD->fields()) {
@@ -6346,51 +6683,315 @@ static void performLifetimeExtension(Expr *Init,
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
- performReferenceExtension(SubInit, ExtendingEntity);
- else if (isa<InitListExpr>(SubInit) ||
- isa<CXXStdInitializerListExpr>(SubInit))
- // This may be either aggregate-initialization of a member or
- // initialization of a std::initializer_list object. Either way,
+ visitLocalsRetainedByReferenceBinding(Path, SubInit,
+ RK_ReferenceBinding, Visit);
+ else
+ // This might be either aggregate-initialization of a member or
+ // initialization of a std::initializer_list object. Regardless,
// we should recursively lifetime-extend that initializer.
- performLifetimeExtension(SubInit, ExtendingEntity);
+ visitLocalsRetainedByInitializer(Path, SubInit, Visit,
+ RevisitSubinits);
++Index;
}
}
}
+ return;
+ }
+
+ if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init))
+ return visitLifetimeBoundArguments(Path, Init, Visit);
+
+ switch (Init->getStmtClass()) {
+ case Stmt::UnaryOperatorClass: {
+ auto *UO = cast<UnaryOperator>(Init);
+ // If the initializer is the address of a local, we could have a lifetime
+ // problem.
+ if (UO->getOpcode() == UO_AddrOf) {
+ // If this is &rvalue, then it's ill-formed and we have already diagnosed
+ // it. Don't produce a redundant warning about the lifetime of the
+ // temporary.
+ if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
+ return;
+
+ Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
+ visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
+ RK_ReferenceBinding, Visit);
+ }
+ break;
+ }
+
+ case Stmt::BinaryOperatorClass: {
+ // Handle pointer arithmetic.
+ auto *BO = cast<BinaryOperator>(Init);
+ BinaryOperatorKind BOK = BO->getOpcode();
+ if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
+ break;
+
+ if (BO->getLHS()->getType()->isPointerType())
+ visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true);
+ else if (BO->getRHS()->getType()->isPointerType())
+ visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true);
+ break;
+ }
+
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::BinaryConditionalOperatorClass: {
+ auto *C = cast<AbstractConditionalOperator>(Init);
+ // In C++, we can have a throw-expression operand, which has 'void' type
+ // and isn't interesting from a lifetime perspective.
+ if (!C->getTrueExpr()->getType()->isVoidType())
+ visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true);
+ if (!C->getFalseExpr()->getType()->isVoidType())
+ visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true);
+ break;
+ }
+
+ case Stmt::BlockExprClass:
+ if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
+ // This is a local block, whose lifetime is that of the function.
+ Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
+ }
+ break;
+
+ case Stmt::AddrLabelExprClass:
+ // We want to warn if the address of a label would escape the function.
+ Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
+ break;
+
+ default:
+ break;
}
}
-static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,
- const Expr *Init, bool IsInitializerList,
- const ValueDecl *ExtendingDecl) {
- // Warn if a field lifetime-extends a temporary.
- if (isa<FieldDecl>(ExtendingDecl)) {
- if (IsInitializerList) {
- S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
- << /*at end of constructor*/true;
- return;
+/// Determine whether this is an indirect path to a temporary that we are
+/// supposed to lifetime-extend along (but don't).
+static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
+ for (auto Elem : Path) {
+ if (Elem.Kind != IndirectLocalPathEntry::DefaultInit)
+ return false;
+ }
+ return true;
+}
+
+/// Find the range for the first interesting entry in the path at or after I.
+static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
+ Expr *E) {
+ for (unsigned N = Path.size(); I != N; ++I) {
+ switch (Path[I].Kind) {
+ case IndirectLocalPathEntry::AddressOf:
+ case IndirectLocalPathEntry::LValToRVal:
+ case IndirectLocalPathEntry::LifetimeBoundCall:
+ // These exist primarily to mark the path as not permitting or
+ // supporting lifetime extension.
+ break;
+
+ case IndirectLocalPathEntry::DefaultInit:
+ case IndirectLocalPathEntry::VarInit:
+ return Path[I].E->getSourceRange();
+ }
+ }
+ return E->getSourceRange();
+}
+
+void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
+ Expr *Init) {
+ LifetimeResult LR = getEntityLifetime(&Entity);
+ LifetimeKind LK = LR.getInt();
+ const InitializedEntity *ExtendingEntity = LR.getPointer();
+
+ // If this entity doesn't have an interesting lifetime, don't bother looking
+ // for temporaries within its initializer.
+ if (LK == LK_FullExpression)
+ return;
+
+ auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
+ ReferenceKind RK) -> bool {
+ SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
+ SourceLocation DiagLoc = DiagRange.getBegin();
+
+ switch (LK) {
+ case LK_FullExpression:
+ llvm_unreachable("already handled this");
+
+ case LK_Extended: {
+ auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
+ if (!MTE) {
+ // The initialized entity has lifetime beyond the full-expression,
+ // and the local entity does too, so don't warn.
+ //
+ // FIXME: We should consider warning if a static / thread storage
+ // duration variable retains an automatic storage duration local.
+ return false;
+ }
+
+ // Lifetime-extend the temporary.
+ if (Path.empty()) {
+ // Update the storage duration of the materialized temporary.
+ // FIXME: Rebuild the expression instead of mutating it.
+ MTE->setExtendingDecl(ExtendingEntity->getDecl(),
+ ExtendingEntity->allocateManglingNumber());
+ // Also visit the temporaries lifetime-extended by this initializer.
+ return true;
+ }
+
+ if (shouldLifetimeExtendThroughPath(Path)) {
+ // We're supposed to lifetime-extend the temporary along this path (per
+ // the resolution of DR1815), but we don't support that yet.
+ //
+ // FIXME: Properly handle this situation. Perhaps the easiest approach
+ // would be to clone the initializer expression on each use that would
+ // lifetime extend its temporaries.
+ Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
+ << RK << DiagRange;
+ } else {
+ // If the path goes through the initialization of a variable or field,
+ // it can't possibly reach a temporary created in this full-expression.
+ // We will have already diagnosed any problems with the initializer.
+ if (pathContainsInit(Path))
+ return false;
+
+ Diag(DiagLoc, diag::warn_dangling_variable)
+ << RK << !Entity.getParent()
+ << ExtendingEntity->getDecl()->isImplicit()
+ << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
+ }
+ break;
}
- bool IsSubobjectMember = false;
- for (const InitializedEntity *Ent = Entity.getParent(); Ent;
- Ent = Ent->getParent()) {
- if (Ent->getKind() != InitializedEntity::EK_Base) {
- IsSubobjectMember = true;
+ case LK_MemInitializer: {
+ if (isa<MaterializeTemporaryExpr>(L)) {
+ // Under C++ DR1696, if a mem-initializer (or a default member
+ // initializer used by the absence of one) would lifetime-extend a
+ // temporary, the program is ill-formed.
+ if (auto *ExtendingDecl =
+ ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
+ bool IsSubobjectMember = ExtendingEntity != &Entity;
+ Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path)
+ ? diag::err_dangling_member
+ : diag::warn_dangling_member)
+ << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
+ // Don't bother adding a note pointing to the field if we're inside
+ // its default member initializer; our primary diagnostic points to
+ // the same place in that case.
+ if (Path.empty() ||
+ Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
+ Diag(ExtendingDecl->getLocation(),
+ diag::note_lifetime_extending_member_declared_here)
+ << RK << IsSubobjectMember;
+ }
+ } else {
+ // We have a mem-initializer but no particular field within it; this
+ // is either a base class or a delegating initializer directly
+ // initializing the base-class from something that doesn't live long
+ // enough.
+ //
+ // FIXME: Warn on this.
+ return false;
+ }
+ } else {
+ // Paths via a default initializer can only occur during error recovery
+ // (there's no other way that a default initializer can refer to a
+ // local). Don't produce a bogus warning on those cases.
+ if (pathContainsInit(Path))
+ return false;
+
+ auto *DRE = dyn_cast<DeclRefExpr>(L);
+ auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
+ if (!VD) {
+ // A member was initialized to a local block.
+ // FIXME: Warn on this.
+ return false;
+ }
+
+ if (auto *Member =
+ ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
+ bool IsPointer = Member->getType()->isAnyPointerType();
+ Diag(DiagLoc, IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
+ : diag::warn_bind_ref_member_to_parameter)
+ << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
+ Diag(Member->getLocation(),
+ diag::note_ref_or_ptr_member_declared_here)
+ << (unsigned)IsPointer;
+ }
+ }
+ break;
+ }
+
+ case LK_New:
+ if (isa<MaterializeTemporaryExpr>(L)) {
+ Diag(DiagLoc, RK == RK_ReferenceBinding
+ ? diag::warn_new_dangling_reference
+ : diag::warn_new_dangling_initializer_list)
+ << !Entity.getParent() << DiagRange;
+ } else {
+ // We can't determine if the allocation outlives the local declaration.
+ return false;
+ }
+ break;
+
+ case LK_Return:
+ case LK_StmtExprResult:
+ if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
+ // We can't determine if the local variable outlives the statement
+ // expression.
+ if (LK == LK_StmtExprResult)
+ return false;
+ Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
+ << Entity.getType()->isReferenceType() << DRE->getDecl()
+ << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
+ } else if (isa<BlockExpr>(L)) {
+ Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
+ } else if (isa<AddrLabelExpr>(L)) {
+ Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
+ } else {
+ Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
+ << Entity.getType()->isReferenceType() << DiagRange;
+ }
+ break;
+ }
+
+ for (unsigned I = 0; I != Path.size(); ++I) {
+ auto Elem = Path[I];
+
+ switch (Elem.Kind) {
+ case IndirectLocalPathEntry::AddressOf:
+ case IndirectLocalPathEntry::LValToRVal:
+ // These exist primarily to mark the path as not permitting or
+ // supporting lifetime extension.
+ break;
+
+ case IndirectLocalPathEntry::LifetimeBoundCall:
+ // FIXME: Consider adding a note for this.
+ break;
+
+ case IndirectLocalPathEntry::DefaultInit: {
+ auto *FD = cast<FieldDecl>(Elem.D);
+ Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer)
+ << FD << nextPathEntryRange(Path, I + 1, L);
+ break;
+ }
+
+ case IndirectLocalPathEntry::VarInit:
+ const VarDecl *VD = cast<VarDecl>(Elem.D);
+ Diag(VD->getLocation(), diag::note_local_var_initializer)
+ << VD->getType()->isReferenceType()
+ << VD->isImplicit() << VD->getDeclName()
+ << nextPathEntryRange(Path, I + 1, L);
break;
}
}
- S.Diag(Init->getExprLoc(),
- diag::warn_bind_ref_member_to_temporary)
- << ExtendingDecl << Init->getSourceRange()
- << IsSubobjectMember << IsInitializerList;
- if (IsSubobjectMember)
- S.Diag(ExtendingDecl->getLocation(),
- diag::note_ref_subobject_of_member_declared_here);
- else
- S.Diag(ExtendingDecl->getLocation(),
- diag::note_ref_or_ptr_member_declared_here)
- << /*is pointer*/false;
- }
+
+ // We didn't lifetime-extend, so don't go any further; we don't need more
+ // warnings or errors on inner temporaries within this one's initializer.
+ return false;
+ };
+
+ llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
+ if (Init->isGLValue())
+ visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
+ TemporaryVisitor);
+ else
+ visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false);
}
static void DiagnoseNarrowingInInitList(Sema &S,
@@ -6427,13 +7028,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
// Find the std::move call and get the argument.
const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens());
- if (!CE || CE->getNumArgs() != 1)
- return;
-
- const FunctionDecl *MoveFunction = CE->getDirectCallee();
- if (!MoveFunction || !MoveFunction->isInStdNamespace() ||
- !MoveFunction->getIdentifier() ||
- !MoveFunction->getIdentifier()->isStr("move"))
+ if (!CE || !CE->isCallToStdMove())
return;
const Expr *Arg = CE->getArg(0)->IgnoreImplicit();
@@ -6490,7 +7085,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
// macro only if it is at the beginning of the macro.
while (ArgLoc.isMacroID() &&
S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
- ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first;
+ ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).getBegin();
}
if (LParen.isMacroID())
@@ -6619,12 +7214,12 @@ InitializationSequence::Perform(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Direct &&
!Kind.isExplicitCast()) {
// Rebuild the ParenListExpr.
- SourceRange ParenRange = Kind.getParenRange();
+ SourceRange ParenRange = Kind.getParenOrBraceRange();
return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(),
Args);
}
assert(Kind.getKind() == InitializationKind::IK_Copy ||
- Kind.isExplicitCast() ||
+ Kind.isExplicitCast() ||
Kind.getKind() == InitializationKind::IK_DirectList);
return ExprResult(Args[0]);
}
@@ -6658,20 +7253,6 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
}
- // Diagnose cases where we initialize a pointer to an array temporary, and the
- // pointer obviously outlives the temporary.
- if (Args.size() == 1 && Args[0]->getType()->isArrayType() &&
- Entity.getType()->isPointerType() &&
- InitializedEntityOutlivesFullExpression(Entity)) {
- const Expr *Init = Args[0]->skipRValueSubobjectAdjustments();
- if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
- Init = MTE->GetTemporaryExpr();
- Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context);
- if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary)
- S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay)
- << Init->getSourceRange();
- }
-
QualType DestType = Entity.getType().getNonReferenceType();
// FIXME: Ugly hack around the fact that Entity.getType() is not
// the same as Entity.getDecl()->getType() in cases involving type merging,
@@ -6822,16 +7403,6 @@ InitializationSequence::Perform(Sema &S,
}
}
- // Even though we didn't materialize a temporary, the binding may still
- // extend the lifetime of a temporary. This happens if we bind a reference
- // to the result of a cast to reference type.
- if (const InitializedEntity *ExtendingEntity =
- getEntityForTemporaryLifetimeExtension(&Entity))
- if (performReferenceExtension(CurInit.get(), ExtendingEntity))
- warnOnLifetimeExtension(S, Entity, CurInit.get(),
- /*IsInitializerList=*/false,
- ExtendingEntity->getDecl());
-
CheckForNullPointerDereference(S, CurInit.get());
break;
@@ -6846,23 +7417,13 @@ InitializationSequence::Perform(Sema &S,
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
-
- // Maybe lifetime-extend the temporary's subobjects to match the
- // entity's lifetime.
- if (const InitializedEntity *ExtendingEntity =
- getEntityForTemporaryLifetimeExtension(&Entity))
- if (performReferenceExtension(MTE, ExtendingEntity))
- warnOnLifetimeExtension(S, Entity, CurInit.get(),
- /*IsInitializerList=*/false,
- ExtendingEntity->getDecl());
+ CurInit = MTE;
// If we're extending this temporary to automatic storage duration -- we
// need to register its cleanup during the full-expression's cleanups.
if (MTE->getStorageDuration() == SD_Automatic &&
MTE->getType().isDestructedType())
S.Cleanup.setExprNeedsCleanups(true);
-
- CurInit = MTE;
break;
}
@@ -6935,16 +7496,6 @@ InitializationSequence::Perform(Sema &S,
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
- // FIXME: Should we move this initialization into a separate
- // derived-to-base conversion? I believe the answer is "no", because
- // we don't want to turn off access control here for c-style casts.
- CurInit = S.PerformObjectArgumentInitialization(CurInit.get(),
- /*Qualifier=*/nullptr,
- FoundFn, Conversion);
- if (CurInit.isInvalid())
- return ExprError();
-
- // Build the actual call to the conversion function.
CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
HadMultipleCandidates);
if (CurInit.isInvalid())
@@ -7139,14 +7690,17 @@ InitializationSequence::Perform(Sema &S,
bool IsStdInitListInit =
Step->Kind == SK_StdInitializerListConstructorCall;
Expr *Source = CurInit.get();
+ SourceRange Range = Kind.hasParenOrBraceRange()
+ ? Kind.getParenOrBraceRange()
+ : SourceRange();
CurInit = PerformConstructorInitialization(
S, UseTemporary ? TempEntity : Entity, Kind,
Source ? MultiExprArg(Source) : Args, *Step,
ConstructorInitRequiresZeroInit,
/*IsListInitialization*/ IsStdInitListInit,
/*IsStdInitListInitialization*/ IsStdInitListInit,
- /*LBraceLoc*/ SourceLocation(),
- /*RBraceLoc*/ SourceLocation());
+ /*LBraceLoc*/ Range.getBegin(),
+ /*RBraceLoc*/ Range.getEnd());
break;
}
@@ -7302,15 +7856,6 @@ InitializationSequence::Perform(Sema &S,
CurInit.get()->getType(), CurInit.get(),
/*BoundToLvalueReference=*/false);
- // Maybe lifetime-extend the array temporary's subobjects to match the
- // entity's lifetime.
- if (const InitializedEntity *ExtendingEntity =
- getEntityForTemporaryLifetimeExtension(&Entity))
- if (performReferenceExtension(MTE, ExtendingEntity))
- warnOnLifetimeExtension(S, Entity, CurInit.get(),
- /*IsInitializerList=*/true,
- ExtendingEntity->getDecl());
-
// Wrap it in a construction of a std::initializer_list<T>.
CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
@@ -7376,7 +7921,7 @@ InitializationSequence::Perform(Sema &S,
// this has already been done when parsing the variable declaration.
if (!Init->isConstantInitializer(S.Context, false))
break;
-
+
if (!SourceType->isIntegerType() ||
32 != S.Context.getIntWidth(SourceType)) {
S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer)
@@ -7412,7 +7957,7 @@ InitializationSequence::Perform(Sema &S,
break;
}
case SK_OCLZeroEvent: {
- assert(Step->Type->isEventT() &&
+ assert(Step->Type->isEventT() &&
"Event initialization on non-event type.");
CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
@@ -7432,6 +7977,11 @@ InitializationSequence::Perform(Sema &S,
}
}
+ // Check whether the initializer has a shorter lifetime than the initialized
+ // entity, and if not, either lifetime-extend or warn as appropriate.
+ if (auto *Init = CurInit.get())
+ S.checkInitializerLifetime(Entity, Init);
+
// Diagnose non-fatal problems with the completed initialization.
if (Entity.getKind() == InitializedEntity::EK_Member &&
cast<FieldDecl>(Entity.getDecl())->isBitField())
@@ -7549,6 +8099,19 @@ bool InitializationSequence::Diagnose(Sema &S,
if (!Failed())
return false;
+ // When we want to diagnose only one element of a braced-init-list,
+ // we need to factor it out.
+ Expr *OnlyArg;
+ if (Args.size() == 1) {
+ auto *List = dyn_cast<InitListExpr>(Args[0]);
+ if (List && List->getNumInits() == 1)
+ OnlyArg = List->getInit(0);
+ else
+ OnlyArg = Args[0];
+ }
+ else
+ OnlyArg = nullptr;
+
QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
@@ -7591,6 +8154,17 @@ bool InitializationSequence::Diagnose(Sema &S,
S.Diag(Kind.getLocation(),
diag::err_array_init_incompat_wide_string_into_wchar);
break;
+ case FK_PlainStringIntoUTF8Char:
+ S.Diag(Kind.getLocation(),
+ diag::err_array_init_plain_string_into_char8_t);
+ S.Diag(Args.front()->getLocStart(),
+ diag::note_array_init_plain_string_into_char8_t)
+ << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8");
+ break;
+ case FK_UTF8StringIntoPlainChar:
+ S.Diag(Kind.getLocation(),
+ diag::err_array_init_utf8_string_into_char);
+ break;
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
S.Diag(Kind.getLocation(),
@@ -7598,7 +8172,7 @@ bool InitializationSequence::Diagnose(Sema &S,
? diag::err_array_init_different_type
: diag::err_array_init_non_constant_array))
<< DestType.getNonReferenceType()
- << Args[0]->getType()
+ << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
@@ -7609,7 +8183,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
- S.ResolveAddressOfOverloadedFunction(Args[0],
+ S.ResolveAddressOfOverloadedFunction(OnlyArg,
DestType.getNonReferenceType(),
true,
Found);
@@ -7617,9 +8191,9 @@ bool InitializationSequence::Diagnose(Sema &S,
}
case FK_AddressOfUnaddressableFunction: {
- auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl());
+ auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
- Args[0]->getLocStart());
+ OnlyArg->getLocStart());
break;
}
@@ -7629,11 +8203,11 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Ambiguous:
if (Failure == FK_UserConversionOverloadFailed)
S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
- << Args[0]->getType() << DestType
+ << OnlyArg->getType() << DestType
<< Args[0]->getSourceRange();
else
S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
- << DestType << Args[0]->getType()
+ << DestType << OnlyArg->getType()
<< Args[0]->getSourceRange();
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@@ -7643,10 +8217,10 @@ bool InitializationSequence::Diagnose(Sema &S,
if (!S.RequireCompleteType(Kind.getLocation(),
DestType.getNonReferenceType(),
diag::err_typecheck_nonviable_condition_incomplete,
- Args[0]->getType(), Args[0]->getSourceRange()))
+ OnlyArg->getType(), Args[0]->getSourceRange()))
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
<< (Entity.getKind() == InitializedEntity::EK_Result)
- << Args[0]->getType() << Args[0]->getSourceRange()
+ << OnlyArg->getType() << Args[0]->getSourceRange()
<< DestType.getNonReferenceType();
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
@@ -7654,7 +8228,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
- << Args[0]->getType() << DestType.getNonReferenceType()
+ << OnlyArg->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
@@ -7690,7 +8264,7 @@ bool InitializationSequence::Diagnose(Sema &S,
: diag::err_lvalue_reference_bind_to_unrelated)
<< DestType.getNonReferenceType().isVolatileQualified()
<< DestType.getNonReferenceType()
- << Args[0]->getType()
+ << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
@@ -7715,12 +8289,12 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_RValueReferenceBindingToLValue:
S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
- << DestType.getNonReferenceType() << Args[0]->getType()
+ << DestType.getNonReferenceType() << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
case FK_ReferenceInitDropsQualifiers: {
- QualType SourceType = Args[0]->getType();
+ QualType SourceType = OnlyArg->getType();
QualType NonRefType = DestType.getNonReferenceType();
Qualifiers DroppedQualifiers =
SourceType.getQualifiers() - NonRefType.getQualifiers();
@@ -7736,18 +8310,18 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
<< DestType.getNonReferenceType()
- << Args[0]->isLValue()
- << Args[0]->getType()
+ << OnlyArg->isLValue()
+ << OnlyArg->getType()
<< Args[0]->getSourceRange();
emitBadConversionNotes(S, Entity, Args[0]);
break;
case FK_ConversionFailed: {
- QualType FromType = Args[0]->getType();
+ QualType FromType = OnlyArg->getType();
PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
<< (int)Entity.getKind()
<< DestType
- << Args[0]->isLValue()
+ << OnlyArg->isLValue()
<< FromType
<< Args[0]->getSourceRange();
S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
@@ -7880,7 +8454,7 @@ bool InitializationSequence::Diagnose(Sema &S,
llvm_unreachable("Inconsistent overload resolution?");
break;
}
-
+
// If this is a defaulted or implicitly-declared function, then
// it was implicitly deleted. Make it clear that the deletion was
// implicit.
@@ -8000,6 +8574,14 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "incompatible wide string into wide char array";
break;
+ case FK_PlainStringIntoUTF8Char:
+ OS << "plain string literal into char8_t array";
+ break;
+
+ case FK_UTF8StringIntoPlainChar:
+ OS << "u8 string literal into char array";
+ break;
+
case FK_ArrayTypeMismatch:
OS << "array type mismatch";
break;
@@ -8290,6 +8872,11 @@ void InitializationSequence::dump() const {
dump(llvm::errs());
}
+static bool NarrowingErrs(const LangOptions &L) {
+ return L.CPlusPlus11 &&
+ (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015));
+}
+
static void DiagnoseNarrowingInInitList(Sema &S,
const ImplicitConversionSequence &ICS,
QualType PreNarrowingType,
@@ -8323,35 +8910,34 @@ static void DiagnoseNarrowingInInitList(Sema &S,
// This was a floating-to-integer conversion, which is always considered a
// narrowing conversion even if the value is a constant and can be
// represented exactly as an integer.
- S.Diag(PostInit->getLocStart(),
- (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
- ? diag::warn_init_list_type_narrowing
- : diag::ext_init_list_type_narrowing)
- << PostInit->getSourceRange()
- << PreNarrowingType.getLocalUnqualifiedType()
- << EntityType.getLocalUnqualifiedType();
+ S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts())
+ ? diag::ext_init_list_type_narrowing
+ : diag::warn_init_list_type_narrowing)
+ << PostInit->getSourceRange()
+ << PreNarrowingType.getLocalUnqualifiedType()
+ << EntityType.getLocalUnqualifiedType();
break;
case NK_Constant_Narrowing:
// A constant value was narrowed.
S.Diag(PostInit->getLocStart(),
- (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
- ? diag::warn_init_list_constant_narrowing
- : diag::ext_init_list_constant_narrowing)
- << PostInit->getSourceRange()
- << ConstantValue.getAsString(S.getASTContext(), ConstantType)
- << EntityType.getLocalUnqualifiedType();
+ NarrowingErrs(S.getLangOpts())
+ ? diag::ext_init_list_constant_narrowing
+ : diag::warn_init_list_constant_narrowing)
+ << PostInit->getSourceRange()
+ << ConstantValue.getAsString(S.getASTContext(), ConstantType)
+ << EntityType.getLocalUnqualifiedType();
break;
case NK_Variable_Narrowing:
// A variable's value may have been narrowed.
S.Diag(PostInit->getLocStart(),
- (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
- ? diag::warn_init_list_variable_narrowing
- : diag::ext_init_list_variable_narrowing)
- << PostInit->getSourceRange()
- << PreNarrowingType.getLocalUnqualifiedType()
- << EntityType.getLocalUnqualifiedType();
+ NarrowingErrs(S.getLangOpts())
+ ? diag::ext_init_list_variable_narrowing
+ : diag::warn_init_list_variable_narrowing)
+ << PostInit->getSourceRange()
+ << PreNarrowingType.getLocalUnqualifiedType()
+ << EntityType.getLocalUnqualifiedType();
break;
}
@@ -8624,6 +9210,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
Expr *E = ListInit->getInit(0);
auto *RD = E->getType()->getAsCXXRecordDecl();
if (!isa<InitListExpr>(E) && RD &&
+ isCompleteType(Kind.getLocation(), E->getType()) &&
isOrIsDerivedFromSpecializationOf(RD, Template))
TryListConstructors = false;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index 19d2de719728..440567e032e4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -24,29 +24,29 @@
using namespace clang;
using namespace sema;
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
-/// enclosing lambda (to the current lambda) that is 'capture-ready' for
+/// Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-ready' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
/// of the capture-ready lambda's LambdaScopeInfo.
-///
-/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
+///
+/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
/// lambda - is on top) to determine the index of the nearest enclosing/outer
-/// lambda that is ready to capture the \p VarToCapture being referenced in
-/// the current lambda.
+/// lambda that is ready to capture the \p VarToCapture being referenced in
+/// the current lambda.
/// As we climb down the stack, we want the index of the first such lambda -
-/// that is the lambda with the highest index that is 'capture-ready'.
-///
+/// that is the lambda with the highest index that is 'capture-ready'.
+///
/// A lambda 'L' is capture-ready for 'V' (var or this) if:
/// - its enclosing context is non-dependent
/// - and if the chain of lambdas between L and the lambda in which
-/// V is potentially used (i.e. the lambda at the top of the scope info
+/// V is potentially used (i.e. the lambda at the top of the scope info
/// stack), can all capture or have already captured V.
/// If \p VarToCapture is 'null' then we are trying to capture 'this'.
-///
+///
/// Note that a lambda that is deemed 'capture-ready' still needs to be checked
/// for whether it is 'capture-capable' (see
-/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
+/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
/// capture.
///
/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
@@ -120,7 +120,7 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
return NoLambdaIsCaptureReady;
}
EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);
-
+
assert(CurScopeIndex);
--CurScopeIndex;
} while (!EnclosingDC->isTranslationUnit() &&
@@ -135,14 +135,14 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
return NoLambdaIsCaptureReady;
}
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
-/// enclosing lambda (to the current lambda) that is 'capture-capable' for
+/// Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-capable' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
/// of the capture-capable lambda's LambdaScopeInfo.
///
/// Given the current stack of lambdas being processed by Sema and
-/// the variable of interest, to identify the nearest enclosing lambda (to the
+/// the variable of interest, to identify the nearest enclosing lambda (to the
/// current lambda at the top of the stack) that can truly capture
/// a variable, it has to have the following two properties:
/// a) 'capture-ready' - be the innermost lambda that is 'capture-ready':
@@ -175,7 +175,7 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
VarDecl *VarToCapture, Sema &S) {
const Optional<unsigned> NoLambdaIsCaptureCapable;
-
+
const Optional<unsigned> OptionalStackIndex =
getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes,
VarToCapture);
@@ -190,7 +190,7 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]);
-
+
// If VarToCapture is null, we are attempting to capture 'this'
const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
@@ -220,7 +220,7 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
&IndexOfCaptureReadyLambda);
if (!CanCaptureThis)
return NoLambdaIsCaptureCapable;
- }
+ }
return IndexOfCaptureReadyLambda;
}
@@ -245,35 +245,35 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent,
+ bool KnownDependent,
LambdaCaptureDefault CaptureDefault) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
- *this);
+ *this);
// Start constructing the lambda class.
CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
IntroducerRange.getBegin(),
- KnownDependent,
- IsGenericLambda,
+ KnownDependent,
+ IsGenericLambda,
CaptureDefault);
DC->addDecl(Class);
return Class;
}
-/// \brief Determine whether the given context is or is enclosed in an inline
+/// Determine whether the given context is or is enclosed in an inline
/// function.
static bool isInInlineFunction(const DeclContext *DC) {
while (!DC->isFileContext()) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
if (FD->isInlined())
return true;
-
+
DC = DC->getLexicalParent();
}
-
+
return false;
}
@@ -379,10 +379,10 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
ArrayRef<ParmVarDecl *> Params,
const bool IsConstexprSpecified) {
QualType MethodType = MethodTypeInfo->getType();
- TemplateParameterList *TemplateParams =
+ TemplateParameterList *TemplateParams =
getGenericLambdaTemplateParameterList(getCurLambda(), *this);
// If a lambda appears in a dependent context or is a generic lambda (has
- // template parameters) and has an 'auto' return type, deduce it to a
+ // template parameters) and has an 'auto' return type, deduce it to a
// dependent type.
if (Class->isDependentContext() || TemplateParams) {
const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
@@ -395,9 +395,9 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
}
// C++11 [expr.prim.lambda]p5:
- // The closure type for a lambda-expression has a public inline function
+ // The closure type for a lambda-expression has a public inline function
// call operator (13.5.4) whose parameters and return type are described by
- // the lambda-expression's parameter-declaration-clause and
+ // the lambda-expression's parameter-declaration-clause and
// trailing-return-type respectively.
DeclarationName MethodName
= Context.DeclarationNames.getCXXOperatorName(OO_Call);
@@ -408,7 +408,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
= IntroducerRange.getEnd().getRawEncoding();
CXXMethodDecl *Method
= CXXMethodDecl::Create(Context, Class, EndLoc,
- DeclarationNameInfo(MethodName,
+ DeclarationNameInfo(MethodName,
IntroducerRange.getBegin(),
MethodNameLoc),
MethodType, MethodTypeInfo,
@@ -417,14 +417,14 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
IsConstexprSpecified,
EndLoc);
Method->setAccess(AS_public);
-
+
// Temporarily set the lexical declaration context to the current
// context, so that the Scope stack matches the lexical nesting.
- Method->setLexicalDeclContext(CurContext);
+ Method->setLexicalDeclContext(CurContext);
// Create a function template if we have a template parameter list
FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
FunctionTemplateDecl::Create(Context, Class,
- Method->getLocation(), MethodName,
+ Method->getLocation(), MethodName,
TemplateParams,
Method) : nullptr;
if (TemplateMethod) {
@@ -432,7 +432,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
TemplateMethod->setAccess(AS_public);
Method->setDescribedFunctionTemplate(TemplateMethod);
}
-
+
// Add parameters.
if (!Params.empty()) {
Method->setParams(Params);
@@ -493,16 +493,16 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
LSI->finishedExplicitCaptures();
}
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
// Introduce our parameters into the function scope
- for (unsigned p = 0, NumParams = CallOperator->getNumParams();
+ for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
ParmVarDecl *Param = CallOperator->getParamDecl(p);
-
+
// If this has an identifier, add it to the scope stack.
if (CurScope && Param->getIdentifier()) {
CheckShadow(CurScope, Param);
-
+
PushOnScopeChains(Param, CurScope);
}
}
@@ -637,7 +637,7 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(CSI.HasImplicitReturnType);
// If it was ever a placeholder, it had to been deduced to DependentTy.
- assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
+ assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
assert((!isa<LambdaScopeInfo>(CSI) || !getLangOpts().CPlusPlus14) &&
"lambda expressions use auto deduction in C++14 onwards");
@@ -692,9 +692,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
}
// Third case: only one return statement. Don't bother doing extra work!
- SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
- E = CSI.Returns.end();
- if (I+1 == E)
+ if (CSI.Returns.size() == 1)
return;
// General case: many return statements.
@@ -703,15 +701,22 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// We require the return types to strictly match here.
// Note that we've already done the required promotions as part of
// processing the return statement.
- for (; I != E; ++I) {
- const ReturnStmt *RS = *I;
+ for (const ReturnStmt *RS : CSI.Returns) {
const Expr *RetE = RS->getRetValue();
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
if (Context.getCanonicalFunctionResultType(ReturnType) ==
- Context.getCanonicalFunctionResultType(CSI.ReturnType))
+ Context.getCanonicalFunctionResultType(CSI.ReturnType)) {
+ // Use the return type with the strictest possible nullability annotation.
+ auto RetTyNullability = ReturnType->getNullability(Ctx);
+ auto BlockNullability = CSI.ReturnType->getNullability(Ctx);
+ if (BlockNullability &&
+ (!RetTyNullability ||
+ hasWeakerNullability(*RetTyNullability, *BlockNullability)))
+ CSI.ReturnType = ReturnType;
continue;
+ }
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.
// TODO: It's possible that the *first* return is the divergent one.
@@ -846,7 +851,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
SmallVector<ParmVarDecl *, 8> Params;
if (ParamInfo.getNumTypeObjects() == 0) {
// C++11 [expr.prim.lambda]p4:
- // If a lambda-expression does not include a lambda-declarator, it is as
+ // If a lambda-expression does not include a lambda-declarator, it is as
// if the lambda-declarator were ().
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
@@ -873,8 +878,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
// C++11 [expr.prim.lambda]p5:
- // This function call operator is declared const (9.3.1) if and only if
- // the lambda-expression's parameter-declaration-clause is not followed
+ // This function call operator is declared const (9.3.1) if and only if
+ // the lambda-expression's parameter-declaration-clause is not followed
// by mutable. It is neither virtual nor declared volatile. [...]
if (!FTI.hasMutableQualifier())
FTI.TypeQuals |= DeclSpec::TQ_const;
@@ -904,8 +909,16 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
-
- // Attributes on the lambda apply to the method.
+
+ // This represents the function body for the lambda function, check if we
+ // have to apply optnone due to a pragma.
+ AddRangeBasedOptnone(Method);
+
+ // code_seg attribute on lambda apply to the method.
+ if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+ Method->addAttr(A);
+
+ // Attributes on the lambda apply to the method.
ProcessDeclAttributes(CurScope, Method, ParamInfo);
// CUDA lambdas get implicit attributes based on the scope in which they're
@@ -915,7 +928,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
-
+
// Build the lambda scope.
buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc,
ExplicitParams, ExplicitResultType, !Method->isConst());
@@ -946,13 +959,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This || C->Kind == LCK_StarThis) {
- if (C->Kind == LCK_StarThis)
+ if (C->Kind == LCK_StarThis)
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:
- // An identifier or this shall not appear more than once in a
+ // An identifier or this shall not appear more than once in a
// lambda-capture.
if (LSI->isCXXThisCaptured()) {
Diag(C->Loc, diag::err_capture_more_than_once)
@@ -980,10 +993,12 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
Diag(C->Loc, diag::err_this_capture) << true;
continue;
}
-
+
CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
/*FunctionScopeIndexToStopAtPtr*/ nullptr,
C->Kind == LCK_StarThis);
+ if (!LSI->Captures.empty())
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
continue;
}
@@ -1003,9 +1018,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// If the initializer expression is usable, but the InitCaptureType
// is not, then an error has occurred - so ignore the capture for now.
// for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
- // FIXME: we should create the init capture variable and mark it invalid
+ // FIXME: we should create the init capture variable and mark it invalid
// in this case.
- if (C->InitCaptureType.get().isNull())
+ if (C->InitCaptureType.get().isNull())
continue;
unsigned InitStyle;
@@ -1035,7 +1050,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
"init capture has valid but null init?");
// C++11 [expr.prim.lambda]p8:
- // If a lambda-capture includes a capture-default that is &, the
+ // If a lambda-capture includes a capture-default that is &, the
// identifiers in the lambda-capture shall not be preceded by &.
// If a lambda-capture includes a capture-default that is =, [...]
// each identifier it contains shall be preceded by &.
@@ -1116,7 +1131,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
} else {
Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< SourceRange(C->Loc);
-
+
// Just ignore the ellipsis.
}
} else if (Var->isParameterPack()) {
@@ -1130,6 +1145,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
TryCapture_ExplicitByVal;
tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
}
+ if (!LSI->Captures.empty())
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
}
finishLambdaExplicitCaptures(LSI);
@@ -1161,7 +1178,7 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
Class->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
@@ -1172,20 +1189,20 @@ QualType Sema::getLambdaConversionFunctionResultType(
// The function type inside the pointer type is the same as the call
// operator with some tweaks. The calling convention is the default free
// function convention, and the type qualifications are lost.
- const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
- CallOpProto->getExtProtoInfo();
+ const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
+ CallOpProto->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
CallingConv CC = Context.getDefaultCallingConvention(
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
InvokerExtInfo.TypeQuals = 0;
- assert(InvokerExtInfo.RefQualifier == RQ_None &&
+ assert(InvokerExtInfo.RefQualifier == RQ_None &&
"Lambda's call operator should not have a reference qualifier");
return Context.getFunctionType(CallOpProto->getReturnType(),
CallOpProto->getParamTypes(), InvokerExtInfo);
}
-/// \brief Add a lambda's conversion to function pointer, as described in
+/// Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
@@ -1210,7 +1227,7 @@ static void addFunctionPointerConversion(Sema &S,
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
// The conversion function is always const.
ConvExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy =
+ QualType ConvTy =
S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
SourceLocation Loc = IntroducerRange.getBegin();
@@ -1219,8 +1236,8 @@ static void addFunctionPointerConversion(Sema &S,
S.Context.getCanonicalType(PtrToFunctionTy));
DeclarationNameLoc ConvNameLoc;
// Construct a TypeSourceInfo for the conversion function, and wire
- // all the parameters appropriately for the FunctionProtoTypeLoc
- // so that everything works during transformation/instantiation of
+ // all the parameters appropriately for the FunctionProtoTypeLoc
+ // so that everything works during transformation/instantiation of
// generic lambdas.
// The main reason for wiring up the parameters of the conversion
// function with that of the call operator is so that constructs
@@ -1230,46 +1247,46 @@ static void addFunctionPointerConversion(Sema &S,
// return a;
// };
// };
- // int (*fp)(int) = L(5);
+ // int (*fp)(int) = L(5);
// Because the trailing return type can contain DeclRefExprs that refer
- // to the original call operator's variables, we hijack the call
+ // to the original call operator's variables, we hijack the call
// operators ParmVarDecls below.
- TypeSourceInfo *ConvNamePtrToFunctionTSI =
+ TypeSourceInfo *ConvNamePtrToFunctionTSI =
S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc);
ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI;
// The conversion function is a conversion to a pointer-to-function.
TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc);
- FunctionProtoTypeLoc ConvTL =
+ FunctionProtoTypeLoc ConvTL =
ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
// Get the result of the conversion function which is a pointer-to-function.
- PointerTypeLoc PtrToFunctionTL =
+ PointerTypeLoc PtrToFunctionTL =
ConvTL.getReturnLoc().getAs<PointerTypeLoc>();
// Do the same for the TypeSourceInfo that is used to name the conversion
// operator.
- PointerTypeLoc ConvNamePtrToFunctionTL =
+ PointerTypeLoc ConvNamePtrToFunctionTL =
ConvNamePtrToFunctionTSI->getTypeLoc().getAs<PointerTypeLoc>();
-
+
// Get the underlying function types that the conversion function will
// be converting to (should match the type of the call operator).
- FunctionProtoTypeLoc CallOpConvTL =
+ FunctionProtoTypeLoc CallOpConvTL =
PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
- FunctionProtoTypeLoc CallOpConvNameTL =
+ FunctionProtoTypeLoc CallOpConvNameTL =
ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
-
+
// Wire up the FunctionProtoTypeLocs with the call operator's parameters.
// These parameter's are essentially used to transform the name and
// the type of the conversion operator. By using the same parameters
// as the call operator's we don't have to fix any back references that
- // the trailing return type of the call operator's uses (such as
+ // the trailing return type of the call operator's uses (such as
// decltype(some_type<decltype(a)>::type{} + decltype(a){}) etc.)
- // - we can simply use the return type of the call operator, and
- // everything should work.
+ // - we can simply use the return type of the call operator, and
+ // everything should work.
SmallVector<ParmVarDecl *, 4> InvokerParams;
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
ParmVarDecl *From = CallOperator->getParamDecl(I);
- InvokerParams.push_back(ParmVarDecl::Create(S.Context,
+ InvokerParams.push_back(ParmVarDecl::Create(S.Context,
// Temporarily add to the TU. This is set to the invoker below.
S.Context.getTranslationUnitDecl(),
From->getLocStart(),
@@ -1283,14 +1300,14 @@ static void addFunctionPointerConversion(Sema &S,
CallOpConvNameTL.setParam(I, From);
}
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(ConversionName,
+ CXXConversionDecl *Conversion
+ = CXXConversionDecl::Create(S.Context, Class, Loc,
+ DeclarationNameInfo(ConversionName,
Loc, ConvNameLoc),
- ConvTy,
+ ConvTy,
ConvTSI,
/*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
+ /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
@@ -1298,7 +1315,7 @@ static void addFunctionPointerConversion(Sema &S,
if (Class->isGenericLambda()) {
// Create a template version of the conversion operator, using the template
// parameter list of the function call operator.
- FunctionTemplateDecl *TemplateCallOperator =
+ FunctionTemplateDecl *TemplateCallOperator =
CallOperator->getDescribedFunctionTemplate();
FunctionTemplateDecl *ConversionTemplate =
FunctionTemplateDecl::Create(S.Context, Class,
@@ -1320,19 +1337,19 @@ static void addFunctionPointerConversion(Sema &S,
// using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc
// then rewire the parameters accordingly, by hoisting up the InvokeParams
// loop below and then use its Params to set Invoke->setParams(...) below.
- // This would avoid the 'const' qualifier of the calloperator from
- // contaminating the type of the invoker, which is currently adjusted
+ // This would avoid the 'const' qualifier of the calloperator from
+ // contaminating the type of the invoker, which is currently adjusted
// in SemaTemplateDeduction.cpp:DeduceTemplateArguments. Fixing the
// trailing return type of the invoker would require a visitor to rebuild
// the trailing return type and adjusting all back DeclRefExpr's to refer
// to the new static invoker parameters - not the call operator's.
CXXMethodDecl *Invoke
- = CXXMethodDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(InvokerName, Loc),
+ = CXXMethodDecl::Create(S.Context, Class, Loc,
+ DeclarationNameInfo(InvokerName, Loc),
InvokerFunctionTy,
- CallOperator->getTypeSourceInfo(),
+ CallOperator->getTypeSourceInfo(),
SC_Static, /*IsInline=*/true,
- /*IsConstexpr=*/false,
+ /*IsConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
InvokerParams[I]->setOwningFunction(Invoke);
@@ -1340,7 +1357,7 @@ static void addFunctionPointerConversion(Sema &S,
Invoke->setAccess(AS_private);
Invoke->setImplicit(true);
if (Class->isGenericLambda()) {
- FunctionTemplateDecl *TemplateCallOperator =
+ FunctionTemplateDecl *TemplateCallOperator =
CallOperator->getDescribedFunctionTemplate();
FunctionTemplateDecl *StaticInvokerTemplate = FunctionTemplateDecl::Create(
S.Context, Class, Loc, InvokerName,
@@ -1354,8 +1371,8 @@ static void addFunctionPointerConversion(Sema &S,
Class->addDecl(Invoke);
}
-/// \brief Add a lambda's conversion to block pointer.
-static void addBlockPointerConversion(Sema &S,
+/// Add a lambda's conversion to block pointer.
+static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
@@ -1375,21 +1392,22 @@ static void addBlockPointerConversion(Sema &S,
S.Context.getCanonicalType(BlockPtrTy));
DeclarationNameLoc NameLoc;
NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc);
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(S.Context, Class, Loc,
+ CXXConversionDecl *Conversion
+ = CXXConversionDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc, NameLoc),
- ConvTy,
+ ConvTy,
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
/*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/false,
+ /*isConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
}
-static ExprResult performLambdaVarCaptureInitialization(
- Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
+static ExprResult performLambdaVarCaptureInitialization(Sema &S,
+ const Capture &Capture,
+ FieldDecl *Field) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
@@ -1403,7 +1421,7 @@ static ExprResult performLambdaVarCaptureInitialization(
// direct-initialized in increasing subscript order.) These
// initializations are performed in the (unspecified) order in
// which the non-static data members are declared.
-
+
// C++ [expr.prim.lambda]p12:
// An entity captured by a lambda-expression is odr-used (3.2) in
// the scope containing the lambda-expression.
@@ -1419,8 +1437,8 @@ static ExprResult performLambdaVarCaptureInitialization(
InitializationSequence Init(S, Entity, InitKind, Ref);
return Init.Perform(S, Entity, InitKind, Ref);
}
-
-ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
+
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope) {
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
ActOnFinishFunctionBody(LSI.CallOperator, Body);
@@ -1443,7 +1461,7 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
llvm_unreachable("Unknown implicit capture style");
}
-bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
+bool Sema::CaptureHasSideEffects(const Capture &From) {
if (!From.isVLATypeCapture()) {
Expr *Init = From.getInitExpr();
if (Init && Init->HasSideEffects(Context))
@@ -1468,12 +1486,13 @@ bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
return false;
}
-void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+ const Capture &From) {
if (CaptureHasSideEffects(From))
- return;
+ return false;
if (From.isVLATypeCapture())
- return;
+ return false;
auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
if (From.isThisCapture())
@@ -1481,6 +1500,8 @@ void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
else
diag << From.getVariable();
diag << From.isNonODRUsed();
+ diag << FixItHint::CreateRemoval(CaptureRange);
+ return true;
}
ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -1510,9 +1531,9 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
IsGenericLambda = Class->isGenericLambda();
CallOperator->setLexicalDeclContext(Class);
- Decl *TemplateOrNonTemplateCallOperatorDecl =
- CallOperator->getDescribedFunctionTemplate()
- ? CallOperator->getDescribedFunctionTemplate()
+ Decl *TemplateOrNonTemplateCallOperatorDecl =
+ CallOperator->getDescribedFunctionTemplate()
+ ? CallOperator->getDescribedFunctionTemplate()
: cast<Decl>(CallOperator);
TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
@@ -1522,22 +1543,64 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Translate captures.
auto CurField = Class->field_begin();
+ // True if the current capture has a used capture or default before it.
+ bool CurHasPreviousCapture = CaptureDefault != LCD_None;
+ SourceLocation PrevCaptureLoc = CurHasPreviousCapture ?
+ CaptureDefaultLoc : IntroducerRange.getBegin();
+
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {
- const LambdaScopeInfo::Capture &From = LSI->Captures[I];
+ const Capture &From = LSI->Captures[I];
+
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
+ // Use source ranges of explicit captures for fixits where available.
+ SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I];
+
// Warn about unused explicit captures.
+ bool IsCaptureUsed = true;
if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) {
// Initialized captures that are non-ODR used may not be eliminated.
bool NonODRUsedInitCapture =
IsGenericLambda && From.isNonODRUsed() && From.getInitExpr();
- if (!NonODRUsedInitCapture)
- DiagnoseUnusedLambdaCapture(From);
+ if (!NonODRUsedInitCapture) {
+ bool IsLast = (I + 1) == LSI->NumExplicitCaptures;
+ SourceRange FixItRange;
+ if (CaptureRange.isValid()) {
+ if (!CurHasPreviousCapture && !IsLast) {
+ // If there are no captures preceding this capture, remove the
+ // following comma.
+ FixItRange = SourceRange(CaptureRange.getBegin(),
+ getLocForEndOfToken(CaptureRange.getEnd()));
+ } else {
+ // Otherwise, remove the comma since the last used capture.
+ FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc),
+ CaptureRange.getEnd());
+ }
+ }
+
+ IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From);
+ }
+ }
+
+ if (CaptureRange.isValid()) {
+ CurHasPreviousCapture |= IsCaptureUsed;
+ PrevCaptureLoc = CaptureRange.getEnd();
}
// Handle 'this' capture.
if (From.isThisCapture()) {
+ // Capturing 'this' implicitly with a default of '[=]' is deprecated,
+ // because it results in a reference capture. Don't warn prior to
+ // C++2a; there's nothing that can be done about it before then.
+ if (getLangOpts().CPlusPlus2a && IsImplicit &&
+ CaptureDefault == LCD_ByCopy) {
+ Diag(From.getLocation(), diag::warn_deprecated_this_capture);
+ Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture)
+ << FixItHint::CreateInsertion(
+ getLocForEndOfToken(CaptureDefaultLoc), ", this");
+ }
+
Captures.push_back(
LambdaCapture(From.getLocation(), IsImplicit,
From.isCopyCapture() ? LCK_StarThis : LCK_This));
@@ -1583,19 +1646,19 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// FIXME: Fix generic lambda to block conversions.
if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda)
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
-
+
// Finalize the lambda class.
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
}
Cleanup.mergeFrom(LambdaCleanup);
- LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
+ LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
CaptureDefault, CaptureDefaultLoc,
- Captures,
+ Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, EndLoc,
ContainsUnexpandedParameterPack);
@@ -1655,7 +1718,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
Expr *Src) {
// Make sure that the lambda call operator is marked used.
CXXRecordDecl *Lambda = Conv->getParent();
- CXXMethodDecl *CallOperator
+ CXXMethodDecl *CallOperator
= cast<CXXMethodDecl>(
Lambda->lookup(
Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
@@ -1668,10 +1731,10 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
CurrentLocation, Src);
if (!Init.isInvalid())
Init = ActOnFinishFullExpr(Init.get());
-
+
if (Init.isInvalid())
return ExprError();
-
+
// Create the new block to be returned.
BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index a9db973851df..0ab70e9dca37 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -187,7 +187,7 @@ namespace {
}
void done() {
- std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+ llvm::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
}
typedef ListTy::const_iterator const_iterator;
@@ -356,7 +356,7 @@ static DeclContext *getContextForScopeMatching(Decl *D) {
return D->getDeclContext()->getRedeclContext();
}
-/// \brief Determine whether \p D is a better lookup result than \p Existing,
+/// Determine whether \p D is a better lookup result than \p Existing,
/// given that they declare the same entity.
static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
NamedDecl *D, NamedDecl *Existing) {
@@ -669,7 +669,7 @@ LLVM_DUMP_METHOD void LookupResult::dump() {
D->dump();
}
-/// \brief Lookup a builtin function, when name lookup would otherwise
+/// Lookup a builtin function, when name lookup would otherwise
/// fail.
static bool LookupBuiltin(Sema &S, LookupResult &R) {
Sema::LookupNameKind NameKind = R.getLookupKind();
@@ -713,7 +713,7 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
return false;
}
-/// \brief Determine whether we can declare a special member function within
+/// Determine whether we can declare a special member function within
/// the class at this point.
static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) {
// We need to have a definition for the class.
@@ -755,7 +755,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
DeclareImplicitDestructor(Class);
}
-/// \brief Determine whether this is the name of an implicitly-declared
+/// Determine whether this is the name of an implicitly-declared
/// special member function.
static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
switch (Name.getNameKind()) {
@@ -773,7 +773,7 @@ static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
return false;
}
-/// \brief If there are any implicit member functions with the given name
+/// If there are any implicit member functions with the given name
/// that need to be declared in the given declaration context, do so.
static void DeclareImplicitMemberFunctionsWithName(Sema &S,
DeclarationName Name,
@@ -1354,7 +1354,7 @@ void Sema::makeMergedDefinitionVisible(NamedDecl *ND) {
makeMergedDefinitionVisible(Param);
}
-/// \brief Find the module in which the given declaration was defined.
+/// Find the module in which the given declaration was defined.
static Module *getDefiningModule(Sema &S, Decl *Entity) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) {
// If this function was instantiated from a template, the defining module is
@@ -1452,6 +1452,8 @@ template<typename Filter>
static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
llvm::SmallVectorImpl<Module *> *Modules,
Filter F) {
+ bool HasFilteredRedecls = false;
+
for (auto *Redecl : D->redecls()) {
auto *R = cast<NamedDecl>(Redecl);
if (!F(R))
@@ -1460,6 +1462,8 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
if (S.isVisible(R))
return true;
+ HasFilteredRedecls = true;
+
if (Modules) {
Modules->push_back(R->getOwningModule());
const auto &Merged = S.Context.getModulesWithMergedDefinition(R);
@@ -1467,7 +1471,11 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
}
}
- return false;
+ // Only return false if there is at least one redecl that is not filtered out.
+ if (HasFilteredRedecls)
+ return false;
+
+ return true;
}
bool Sema::hasVisibleExplicitSpecialization(
@@ -1497,11 +1505,9 @@ bool Sema::hasVisibleMemberSpecialization(
// class definition?
return D->getLexicalDeclContext()->isFileContext();
});
-
- return false;
}
-/// \brief Determine whether a declaration is visible to name lookup.
+/// Determine whether a declaration is visible to name lookup.
///
/// This routine determines whether the declaration D is visible in the current
/// lookup context, taking into account the current template instantiation
@@ -1615,7 +1621,7 @@ 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:
@@ -1648,7 +1654,7 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
return New->isExternallyDeclarable();
}
-/// \brief Retrieve the visible declaration corresponding to D, if any.
+/// Retrieve the visible declaration corresponding to D, if any.
///
/// This routine determines whether the declaration D is visible in the current
/// module, with the current imports. If not, it checks whether any
@@ -1656,7 +1662,8 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
///
/// \returns D, or a visible previous declaration of D, whichever is more recent
/// and visible. If no declaration of D is visible, returns null.
-static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
+static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D,
+ unsigned IDNS) {
assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
for (auto RD : D->redecls()) {
@@ -1668,7 +1675,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
// FIXME: This is wrong in the case where the previous declaration is not
// visible in the same scope as D. This needs to be done much more
// carefully.
- if (LookupResult::isVisible(SemaRef, ND))
+ if (ND->isInIdentifierNamespace(IDNS) &&
+ LookupResult::isVisible(SemaRef, ND))
return ND;
}
@@ -1693,17 +1701,18 @@ NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
auto *Key = ND->getCanonicalDecl();
if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key))
return Acceptable;
- auto *Acceptable =
- isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key);
+ auto *Acceptable = isVisible(getSema(), Key)
+ ? Key
+ : findAcceptableDecl(getSema(), Key, IDNS);
if (Acceptable)
getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable));
return Acceptable;
}
- return findAcceptableDecl(getSema(), D);
+ return findAcceptableDecl(getSema(), D, IDNS);
}
-/// @brief Perform unqualified name lookup starting from a given
+/// Perform unqualified name lookup starting from a given
/// scope.
///
/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
@@ -1786,7 +1795,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// actually exists in a Scope).
while (S && !S->isDeclScope(D))
S = S->getParent();
-
+
// If the scope containing the declaration is the translation unit,
// then we'll need to perform our checks based on the matching
// DeclContexts rather than matching scopes.
@@ -1797,7 +1806,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
DeclContext *DC = nullptr;
if (!S)
DC = (*I)->getDeclContext()->getRedeclContext();
-
+
IdentifierResolver::iterator LastI = I;
for (++LastI; LastI != IEnd; ++LastI) {
if (S) {
@@ -1806,7 +1815,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
break;
} else {
// Match based on DeclContext.
- DeclContext *LastDC
+ DeclContext *LastDC
= (*LastI)->getDeclContext()->getRedeclContext();
if (!LastDC->Equals(DC))
break;
@@ -1834,14 +1843,14 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (AllowBuiltinCreation && LookupBuiltin(*this, R))
return true;
- // If we didn't find a use of this identifier, the ExternalSource
- // may be able to handle the situation.
+ // If we didn't find a use of this identifier, the ExternalSource
+ // may be able to handle the situation.
// Note: some lookup failures are expected!
// See e.g. R.isForRedeclaration().
return (ExternalSource && ExternalSource->LookupUnqualified(R, S));
}
-/// @brief Perform qualified name lookup in the namespaces nominated by
+/// Perform qualified name lookup in the namespaces nominated by
/// using directives by the given context.
///
/// C++98 [namespace.qual]p2:
@@ -1947,7 +1956,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
return Found;
}
-/// \brief Callback that looks for any member of a class with the given name.
+/// Callback that looks for any member of a class with the given name.
static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
@@ -1956,7 +1965,7 @@ static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
return !Path.Decls.empty();
}
-/// \brief Determine whether the given set of member declarations contains only
+/// Determine whether the given set of member declarations contains only
/// static members, nested types, and enumerators.
template<typename InputIterator>
static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
@@ -1988,7 +1997,7 @@ static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
return false;
}
-/// \brief Perform qualified name lookup into a given context.
+/// Perform qualified name lookup into a given context.
///
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
/// names when the context of those names is explicit specified, e.g.,
@@ -2028,11 +2037,11 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
bool oldVal;
DeclContext *Context;
// Set flag in DeclContext informing debugger that we're looking for qualified name
- QualifiedLookupInScope(DeclContext *ctx) : Context(ctx) {
- oldVal = ctx->setUseQualifiedLookup();
+ QualifiedLookupInScope(DeclContext *ctx) : Context(ctx) {
+ oldVal = ctx->setUseQualifiedLookup();
}
- ~QualifiedLookupInScope() {
- Context->setUseQualifiedLookup(oldVal);
+ ~QualifiedLookupInScope() {
+ Context->setUseQualifiedLookup(oldVal);
}
} QL(LookupCtx);
@@ -2212,7 +2221,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
return true;
}
-/// \brief Performs qualified name lookup or special type of lookup for
+/// Performs qualified name lookup or special type of lookup for
/// "__super::" scope specifier.
///
/// This routine is a convenience overload meant to be called from contexts
@@ -2237,7 +2246,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
return LookupQualifiedName(R, LookupCtx);
}
-/// @brief Performs name lookup for a name that was parsed in the
+/// Performs name lookup for a name that was parsed in the
/// source code, and may contain a C++ scope specifier.
///
/// This routine is a convenience routine meant to be called from
@@ -2291,7 +2300,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
return LookupName(R, S, AllowBuiltinCreation);
}
-/// \brief Perform qualified name lookup into all base classes of the given
+/// Perform qualified name lookup into all base classes of the given
/// class.
///
/// \param R captures both the lookup criteria and any lookup results found.
@@ -2309,7 +2318,7 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(
BaseSpec.getType()->castAs<RecordType>()->getDecl());
LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
- Result.setBaseObjectType(Context.getRecordType(Class));
+ Result.setBaseObjectType(Context.getRecordType(Class));
LookupQualifiedName(Result, RD);
// Copy the lookup results into the target, merging the base's access into
@@ -2329,7 +2338,7 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
return !R.empty();
}
-/// \brief Produce a diagnostic describing the ambiguity that resulted
+/// Produce a diagnostic describing the ambiguity that resulted
/// from name lookup.
///
/// \param Result The result of the ambiguous lookup to be diagnosed.
@@ -2445,7 +2454,7 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
Namespaces.insert(Ctx->getPrimaryContext());
}
-// \brief Add the associated classes and namespaces for argument-dependent
+// Add the associated classes and namespaces for argument-dependent
// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
@@ -2495,7 +2504,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
}
-// \brief Add the associated classes and namespaces for
+// Add the associated classes and namespaces for
// argument-dependent lookup with an argument of class type
// (C++ [basic.lookup.koenig]p2).
static void
@@ -2590,7 +2599,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
}
-// \brief Add the associated classes and namespaces for
+// Add the associated classes and namespaces for
// argument-dependent lookup with an argument of type T
// (C++ [basic.lookup.koenig]p2).
static void
@@ -2729,7 +2738,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
case Type::DeducedTemplateSpecialization:
break;
- // If T is an Objective-C object or interface type, or a pointer to an
+ // If T is an Objective-C object or interface type, or a pointer to an
// object or interface type, the associated namespace is the global
// namespace.
case Type::ObjCObject:
@@ -2754,7 +2763,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
}
}
-/// \brief Find the associated classes and namespaces for
+/// Find the associated classes and namespaces for
/// argument-dependent lookup for a call with the given set of
/// arguments.
///
@@ -2821,7 +2830,7 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
return R.getAsSingle<NamedDecl>();
}
-/// \brief Find the protocol with the given name, if any.
+/// Find the protocol with the given name, if any.
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
SourceLocation IdLoc,
RedeclarationKind Redecl) {
@@ -3048,7 +3057,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD,
return *Result;
}
-/// \brief Look up the default constructor for the given class.
+/// Look up the default constructor for the given class.
CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {
SpecialMemberOverloadResult Result =
LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false,
@@ -3057,7 +3066,7 @@ CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {
return cast_or_null<CXXConstructorDecl>(Result.getMethod());
}
-/// \brief Look up the copying constructor for the given class.
+/// Look up the copying constructor for the given class.
CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,
unsigned Quals) {
assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
@@ -3069,7 +3078,7 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,
return cast_or_null<CXXConstructorDecl>(Result.getMethod());
}
-/// \brief Look up the moving constructor for the given class.
+/// Look up the moving constructor for the given class.
CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class,
unsigned Quals) {
SpecialMemberOverloadResult Result =
@@ -3079,7 +3088,7 @@ CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class,
return cast_or_null<CXXConstructorDecl>(Result.getMethod());
}
-/// \brief Look up the constructors for the given class.
+/// Look up the constructors for the given class.
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
// If the implicit constructors have not yet been declared, do so now.
if (CanDeclareSpecialMemberFunction(Class)) {
@@ -3096,7 +3105,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
return Class->lookup(Name);
}
-/// \brief Look up the copying assignment operator for the given class.
+/// Look up the copying assignment operator for the given class.
CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,
unsigned Quals, bool RValueThis,
unsigned ThisQuals) {
@@ -3113,7 +3122,7 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,
return Result.getMethod();
}
-/// \brief Look up the moving assignment operator for the given class.
+/// Look up the moving assignment operator for the given class.
CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class,
unsigned Quals,
bool RValueThis,
@@ -3129,7 +3138,7 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class,
return Result.getMethod();
}
-/// \brief Look for the destructor of the given class.
+/// Look for the destructor of the given class.
///
/// During semantic analysis, this routine should be used in lieu of
/// CXXRecordDecl::getDestructor().
@@ -3329,6 +3338,23 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
// lookup (11.4).
DeclContext::lookup_result R = NS->lookup(Name);
for (auto *D : R) {
+ auto *Underlying = D;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+
+ if (!isa<FunctionDecl>(Underlying) &&
+ !isa<FunctionTemplateDecl>(Underlying))
+ continue;
+
+ if (!isVisible(D)) {
+ D = findAcceptableDecl(
+ *this, D, (Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend));
+ if (!D)
+ continue;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+ }
+
// If the only declaration here is an ordinary friend, consider
// it only if it was declared in an associated classes.
if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) {
@@ -3350,22 +3376,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
continue;
}
- auto *Underlying = D;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
-
- if (!isa<FunctionDecl>(Underlying) &&
- !isa<FunctionTemplateDecl>(Underlying))
- continue;
-
- if (!isVisible(D)) {
- D = findAcceptableDecl(*this, D);
- if (!D)
- continue;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
- }
-
// FIXME: Preserve D as the FoundDecl.
Result.insert(Underlying);
}
@@ -3385,26 +3395,26 @@ class ShadowContextRAII;
class VisibleDeclsRecord {
public:
- /// \brief An entry in the shadow map, which is optimized to store a
+ /// An entry in the shadow map, which is optimized to store a
/// single declaration (the common case) but can also store a list
/// of declarations.
typedef llvm::TinyPtrVector<NamedDecl*> ShadowMapEntry;
private:
- /// \brief A mapping from declaration names to the declarations that have
+ /// A mapping from declaration names to the declarations that have
/// this name within a particular scope.
typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
- /// \brief A list of shadow maps, which is used to model name hiding.
+ /// A list of shadow maps, which is used to model name hiding.
std::list<ShadowMap> ShadowMaps;
- /// \brief The declaration contexts we have already visited.
+ /// The declaration contexts we have already visited.
llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts;
friend class ShadowContextRAII;
public:
- /// \brief Determine whether we have already visited this context
+ /// Determine whether we have already visited this context
/// (and, if not, note that we are going to visit that context now).
bool visitedContext(DeclContext *Ctx) {
return !VisitedContexts.insert(Ctx).second;
@@ -3414,20 +3424,20 @@ public:
return VisitedContexts.count(Ctx);
}
- /// \brief Determine whether the given declaration is hidden in the
+ /// Determine whether the given declaration is hidden in the
/// current scope.
///
/// \returns the declaration that hides the given declaration, or
/// NULL if no such declaration exists.
NamedDecl *checkHidden(NamedDecl *ND);
- /// \brief Add a declaration to the current shadow map.
+ /// Add a declaration to the current shadow map.
void add(NamedDecl *ND) {
ShadowMaps.back()[ND->getDeclName()].push_back(ND);
}
};
-/// \brief RAII object that records when we've entered a shadow context.
+/// RAII object that records when we've entered a shadow context.
class ShadowContextRAII {
VisibleDeclsRecord &Visible;
@@ -3494,7 +3504,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
bool InBaseClass,
VisibleDeclConsumer &Consumer,
VisibleDeclsRecord &Visited,
- bool IncludeDependentBases = false) {
+ bool IncludeDependentBases,
+ bool LoadExternal) {
if (!Ctx)
return;
@@ -3502,6 +3513,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
+ Consumer.EnteredContext(Ctx);
+
// Outside C++, lookup results for the TU live on identifiers.
if (isa<TranslationUnitDecl>(Ctx) &&
!Result.getSema().getLangOpts().CPlusPlus) {
@@ -3509,11 +3522,12 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
auto &Idents = S.Context.Idents;
// Ensure all external identifiers are in the identifier table.
- if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) {
- std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
- for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next())
- Idents.get(Name);
- }
+ if (LoadExternal)
+ if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) {
+ std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
+ for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next())
+ Idents.get(Name);
+ }
// Walk all lookup results in the TU for each identifier.
for (const auto &Ident : Idents) {
@@ -3535,8 +3549,13 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+ // We sometimes skip loading namespace-level results (they tend to be huge).
+ bool Load = LoadExternal ||
+ !(isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx));
// Enumerate all of the results in this context.
- for (DeclContextLookupResult R : Ctx->lookups()) {
+ for (DeclContextLookupResult R :
+ Load ? Ctx->lookups()
+ : Ctx->noload_lookups(/*PreserveInternalState=*/false)) {
for (auto *D : R) {
if (auto *ND = Result.getAcceptableDecl(D)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
@@ -3553,7 +3572,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
continue;
LookupVisibleDecls(I->getNominatedNamespace(), Result,
QualifiedNameLookup, InBaseClass, Consumer, Visited,
- IncludeDependentBases);
+ IncludeDependentBases, LoadExternal);
}
}
@@ -3610,7 +3629,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Find results in this base class (and its bases).
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer,
- Visited, IncludeDependentBases);
+ Visited, IncludeDependentBases, LoadExternal);
}
}
@@ -3619,22 +3638,23 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse categories.
for (auto *Cat : IFace->visible_categories()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false,
- Consumer, Visited);
+ LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false, Consumer,
+ Visited, IncludeDependentBases, LoadExternal);
}
// Traverse protocols.
for (auto *I : IFace->all_referenced_protocols()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
- Visited);
+ Visited, IncludeDependentBases, LoadExternal);
}
// Traverse the superclass.
if (IFace->getSuperClass()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
- true, Consumer, Visited);
+ true, Consumer, Visited, IncludeDependentBases,
+ LoadExternal);
}
// If there is an implementation, traverse it. We do this to find
@@ -3642,26 +3662,28 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (IFace->getImplementation()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(IFace->getImplementation(), Result,
- QualifiedNameLookup, InBaseClass, Consumer, Visited);
+ QualifiedNameLookup, InBaseClass, Consumer, Visited,
+ IncludeDependentBases, LoadExternal);
}
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
for (auto *I : Protocol->protocols()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
- Visited);
+ Visited, IncludeDependentBases, LoadExternal);
}
} else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
for (auto *I : Category->protocols()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
- Visited);
+ Visited, IncludeDependentBases, LoadExternal);
}
// If there is an implementation, traverse it.
if (Category->getImplementation()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(Category->getImplementation(), Result,
- QualifiedNameLookup, true, Consumer, Visited);
+ QualifiedNameLookup, true, Consumer, Visited,
+ IncludeDependentBases, LoadExternal);
}
}
}
@@ -3669,7 +3691,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
static void LookupVisibleDecls(Scope *S, LookupResult &Result,
UnqualUsingDirectiveSet &UDirs,
VisibleDeclConsumer &Consumer,
- VisibleDeclsRecord &Visited) {
+ VisibleDeclsRecord &Visited,
+ bool LoadExternal) {
if (!S)
return;
@@ -3708,7 +3731,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
Result.getNameLoc(), Sema::LookupMemberName);
if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
}
@@ -3722,7 +3746,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
continue;
LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
} else if (!S->getParent()) {
// Look into the translation unit scope. We walk through the translation
@@ -3736,7 +3761,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// in DeclContexts unless we have to" optimization), we can eliminate this.
Entity = Result.getSema().Context.getTranslationUnitDecl();
LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
if (Entity) {
@@ -3745,17 +3771,19 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity))
LookupVisibleDecls(const_cast<DeclContext *>(UUE.getNominatedNamespace()),
Result, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
// Lookup names in the parent scope.
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited);
+ LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited,
+ LoadExternal);
}
void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
- bool IncludeGlobalScope) {
+ bool IncludeGlobalScope, bool LoadExternal) {
// Determine the set of using directives available during
// unqualified name lookup.
Scope *Initial = S;
@@ -3776,13 +3804,13 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
if (!IncludeGlobalScope)
Visited.visitedContext(Context.getTranslationUnitDecl());
ShadowContextRAII Shadow(Visited);
- ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
+ ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited, LoadExternal);
}
void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
bool IncludeGlobalScope,
- bool IncludeDependentBases) {
+ bool IncludeDependentBases, bool LoadExternal) {
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
Result.setAllowHidden(Consumer.includeHiddenDecls());
VisibleDeclsRecord Visited;
@@ -3791,7 +3819,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
ShadowContextRAII Shadow(Visited);
::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true,
/*InBaseClass=*/false, Consumer, Visited,
- IncludeDependentBases);
+ IncludeDependentBases, LoadExternal);
}
/// LookupOrCreateLabel - Do a name lookup of a label with the specified name.
@@ -3846,7 +3874,7 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
bool isObjCIvarLookup,
bool FindHidden);
-/// \brief Check whether the declarations found for a typo correction are
+/// Check whether the declarations found for a typo correction are
/// visible. Set the correction's RequiresImport flag to true if none of the
/// declarations are visible, false otherwise.
static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
@@ -3865,17 +3893,13 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
bool AnyVisibleDecls = !NewDecls.empty();
for (/**/; DI != DE; ++DI) {
- NamedDecl *VisibleDecl = *DI;
- if (!LookupResult::isVisible(SemaRef, *DI))
- VisibleDecl = findAcceptableDecl(SemaRef, *DI);
-
- if (VisibleDecl) {
+ if (LookupResult::isVisible(SemaRef, *DI)) {
if (!AnyVisibleDecls) {
// Found a visible decl, discard all hidden ones.
AnyVisibleDecls = true;
NewDecls.clear();
}
- NewDecls.push_back(VisibleDecl);
+ NewDecls.push_back(*DI);
} else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
NewDecls.push_back(*DI);
}
@@ -3945,8 +3969,7 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
// Only consider visible declarations and declarations from modules with
// names that exactly match.
- if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo &&
- !findAcceptableDecl(SemaRef, ND))
+ if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo)
return;
FoundName(Name->getName());
@@ -4337,7 +4360,7 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
DistanceMap[NumSpecifiers].push_back(SI);
}
-/// \brief Perform name lookup for a possible result for typo correction.
+/// Perform name lookup for a possible result for typo correction.
static void LookupPotentialTypoResult(Sema &SemaRef,
LookupResult &Res,
IdentifierInfo *Name,
@@ -4391,7 +4414,7 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
}
}
-/// \brief Add keywords to the consumer as possible typo corrections.
+/// Add keywords to the consumer as possible typo corrections.
static void AddKeywordsToConsumer(Sema &SemaRef,
TypoCorrectionConsumer &Consumer,
Scope *S, CorrectionCandidateCallback &CCC,
@@ -4411,7 +4434,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
// Add type-specifier keywords to the set of results.
static const char *const CTypeSpecs[] = {
"char", "const", "double", "enum", "float", "int", "long", "short",
- "signed", "struct", "union", "unsigned", "void", "volatile",
+ "signed", "struct", "union", "unsigned", "void", "volatile",
"_Complex", "_Imaginary",
// storage-specifiers as well
"extern", "inline", "static", "typedef"
@@ -4427,7 +4450,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
Consumer.addKeywordResult("bool");
else if (SemaRef.getLangOpts().C99)
Consumer.addKeywordResult("_Bool");
-
+
if (SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("class");
Consumer.addKeywordResult("typename");
@@ -4442,7 +4465,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
- if (SemaRef.getLangOpts().GNUMode)
+ if (SemaRef.getLangOpts().GNUKeywords)
Consumer.addKeywordResult("typeof");
} else if (CCC.WantFunctionLikeCasts) {
static const char *const CastableTypeSpecs[] = {
@@ -4512,7 +4535,8 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
if (S && S->getContinueParent())
Consumer.addKeywordResult("continue");
- if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+ if (SemaRef.getCurFunction() &&
+ !SemaRef.getCurFunction()->SwitchStack.empty()) {
Consumer.addKeywordResult("case");
Consumer.addKeywordResult("default");
}
@@ -4681,7 +4705,7 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
return Consumer;
}
-/// \brief Try to "correct" a typo in the source code by finding
+/// Try to "correct" a typo in the source code by finding
/// visible declarations whose names are similar to the name that was
/// present in the source code.
///
@@ -4810,7 +4834,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC);
}
-/// \brief Try to "correct" a typo in the source code by finding
+/// Try to "correct" a typo in the source code by finding
/// visible declarations whose names are similar to the name that was
/// present in the source code.
///
@@ -4966,6 +4990,8 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) {
// determine if it is a pointer or reference to a function. If so,
// check against the number of arguments expected for the pointee.
QualType ValType = cast<ValueDecl>(ND)->getType();
+ if (ValType.isNull())
+ continue;
if (ValType->isAnyPointerType() || ValType->isReferenceType())
ValType = ValType->getPointeeType();
if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
@@ -5047,7 +5073,7 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
Recover);
}
-/// \brief Get a "quoted.h" or <angled.h> include path to use in a diagnostic
+/// Get a "quoted.h" or <angled.h> include path to use in a diagnostic
/// suggesting the addition of a #include of the specified file.
static std::string getIncludeStringForHeader(Preprocessor &PP,
const FileEntry *E) {
@@ -5126,7 +5152,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]);
}
-/// \brief Diagnose a successfully-corrected typo. Separated from the correction
+/// Diagnose a successfully-corrected typo. Separated from the correction
/// itself to allow external validation of the result, etc.
///
/// \param Correction The result of performing typo correction.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index ea5b1da46f32..3e55cf003fce 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -104,7 +104,7 @@ static void checkPropertyDeclWithOwnership(Sema &S,
<< propertyLifetime;
}
-/// \brief Check this Objective-C property against a property declared in the
+/// Check this Objective-C property against a property declared in the
/// given protocol.
static void
CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
@@ -307,15 +307,15 @@ makePropertyAttributesAsWritten(unsigned Attributes) {
attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic;
if (Attributes & ObjCDeclSpec::DQ_PR_class)
attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_class;
-
+
return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten;
}
-static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
+static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
SourceLocation LParenLoc, SourceLocation &Loc) {
if (LParenLoc.isMacroID())
return false;
-
+
SourceManager &SM = Context.getSourceManager();
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc);
// Try to load the file buffer.
@@ -324,7 +324,7 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
if (invalidTemp)
return false;
const char *tokenBegin = file.data() + locInfo.second;
-
+
// Lex from the start of the given location.
Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
Context.getLangOpts(),
@@ -365,7 +365,7 @@ static void checkAtomicPropertyMismatch(Sema &S,
if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) return false;
// Was 'atomic' specified directly?
- if (Property->getPropertyAttributesAsWritten() &
+ if (Property->getPropertyAttributesAsWritten() &
ObjCPropertyDecl::OBJC_PR_atomic)
return false;
@@ -382,7 +382,7 @@ static void checkAtomicPropertyMismatch(Sema &S,
Attrs = Attrs & ~AtomicityMask;
if (OldIsAtomic)
Attrs |= ObjCPropertyDecl::OBJC_PR_atomic;
- else
+ else
Attrs |= ObjCPropertyDecl::OBJC_PR_nonatomic;
NewProperty->overwritePropertyAttributes(Attrs);
@@ -429,7 +429,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
DeclContext *DC = CurContext;
IdentifierInfo *PropertyId = FD.D.getIdentifier();
ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
-
+
// We need to look in the @interface to see if the @property was
// already declared.
if (!CCPrimary) {
@@ -445,7 +445,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass(
PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty));
- // If we found a property in an extension, complain.
+ // If we found a property in an extension, complain.
if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
Diag(AtLoc, diag::err_duplicate_property);
Diag(PIDecl->getLocation(), diag::note_property_declare);
@@ -482,7 +482,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
<< PIDecl->getGetterName() << GetterSel;
Diag(PIDecl->getLocation(), diag::note_property_declare);
}
-
+
// Always adopt the getter from the original declaration.
GetterSel = PIDecl->getGetterName();
Attributes |= ObjCDeclSpec::DQ_PR_getter;
@@ -503,7 +503,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership;
}
- // If the redeclaration is 'weak' but the original property is not,
+ // If the redeclaration is 'weak' but the original property is not,
if ((Attributes & ObjCPropertyDecl::OBJC_PR_weak) &&
!(PIDecl->getPropertyAttributesAsWritten()
& ObjCPropertyDecl::OBJC_PR_weak) &&
@@ -511,7 +511,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) {
Diag(AtLoc, diag::warn_property_implicitly_mismatched);
Diag(PIDecl->getLocation(), diag::note_property_declare);
- }
+ }
}
// Create a new ObjCPropertyDecl with the DeclContext being
@@ -546,13 +546,13 @@ Sema::HandlePropertyInClassExtension(Scope *S,
(!isObjCPointerConversion(ClassExtPropertyT, PrimaryClassPropertyT,
ConvertedType, IncompatibleObjC))
|| IncompatibleObjC) {
- Diag(AtLoc,
+ Diag(AtLoc,
diag::err_type_mismatch_continuation_class) << PDecl->getType();
Diag(PIDecl->getLocation(), diag::note_property_declare);
return nullptr;
}
}
-
+
// Check that atomicity of property in class extension matches the previous
// declaration.
checkAtomicPropertyMismatch(*this, PIDecl, PDecl, true);
@@ -618,10 +618,10 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
}
- DeclContext *DC = cast<DeclContext>(CDecl);
+ DeclContext *DC = CDecl;
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
FD.D.getIdentifierLoc(),
- PropertyId, AtLoc,
+ PropertyId, AtLoc,
LParenLoc, T, TInfo);
bool isClassProperty = (AttributesAsWritten & ObjCDeclSpec::DQ_PR_class) ||
@@ -770,7 +770,7 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
<< property->getDeclName()
<< ivar->getDeclName()
- << ((property->getPropertyAttributesAsWritten()
+ << ((property->getPropertyAttributesAsWritten()
& ObjCPropertyDecl::OBJC_PR_assign) != 0);
break;
@@ -794,12 +794,12 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
/// life-time is assumed 'strong'.
static void setImpliedPropertyAttributeForReadOnlyProperty(
ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
- Qualifiers::ObjCLifetime propertyLifetime =
+ Qualifiers::ObjCLifetime propertyLifetime =
getImpliedARCOwnership(property->getPropertyAttributes(),
property->getType());
if (propertyLifetime != Qualifiers::OCL_None)
return;
-
+
if (!ivar) {
// if no backing ivar, make property 'strong'.
property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
@@ -897,14 +897,24 @@ SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
: HasUnexpectedAttribute;
Mismatches.push_back({Prop, Kind, AttributeName});
};
- if (isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
+ // The ownership might be incompatible unless the property has no explicit
+ // ownership.
+ bool HasOwnership = (Attr & (ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_strong |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
+ ObjCPropertyDecl::OBJC_PR_weak)) != 0;
+ if (HasOwnership &&
+ isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
ObjCPropertyDecl::OBJC_PR_copy)) {
Diag(OriginalAttributes & ObjCPropertyDecl::OBJC_PR_copy, "copy");
continue;
}
- if (areIncompatiblePropertyAttributes(
- OriginalAttributes, Attr, ObjCPropertyDecl::OBJC_PR_retain |
- ObjCPropertyDecl::OBJC_PR_strong)) {
+ if (HasOwnership && areIncompatiblePropertyAttributes(
+ OriginalAttributes, Attr,
+ ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_strong)) {
Diag(OriginalAttributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_strong),
"retain (or strong)");
@@ -1084,7 +1094,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
Diag(property->getLocation(), diag::note_property_declare);
}
-
+
if (const ObjCCategoryDecl *CD =
dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
if (!CD->IsClassExtension()) {
@@ -1111,17 +1121,17 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
}
}
}
-
+
if (!ReadWriteProperty) {
Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
<< property;
SourceLocation readonlyLoc;
- if (LocPropertyAttribute(Context, "readonly",
+ if (LocPropertyAttribute(Context, "readonly",
property->getLParenLoc(), readonlyLoc)) {
- SourceLocation endLoc =
+ SourceLocation endLoc =
readonlyLoc.getLocWithOffset(strlen("readonly")-1);
SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
- Diag(property->getLocation(),
+ Diag(property->getLocation(),
diag::note_auto_readonly_iboutlet_fixup_suggest) <<
FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
}
@@ -1184,10 +1194,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
(property->getPropertyAttributesAsWritten() &
ObjCPropertyDecl::OBJC_PR_readonly) &&
PropertyIvarType->isObjCRetainableType()) {
- setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);
+ setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);
}
-
- ObjCPropertyDecl::PropertyAttributeKind kind
+
+ ObjCPropertyDecl::PropertyAttributeKind kind
= property->getPropertyAttributes();
bool isARCWeak = false;
@@ -1234,16 +1244,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
}
if (AtLoc.isInvalid()) {
- // Check when default synthesizing a property that there is
+ // Check when default synthesizing a property that there is
// an ivar matching property name and issue warning; since this
// is the most common case of not using an ivar used for backing
// property in non-default synthesis case.
ObjCInterfaceDecl *ClassDeclared=nullptr;
- ObjCIvarDecl *originalIvar =
- IDecl->lookupInstanceVariable(property->getIdentifier(),
+ ObjCIvarDecl *originalIvar =
+ IDecl->lookupInstanceVariable(property->getIdentifier(),
ClassDeclared);
if (originalIvar) {
- Diag(PropertyDiagLoc,
+ Diag(PropertyDiagLoc,
diag::warn_autosynthesis_property_ivar_match)
<< PropertyId << (Ivar == nullptr) << PropertyIvar
<< originalIvar->getIdentifier();
@@ -1251,7 +1261,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Diag(originalIvar->getLocation(), diag::note_ivar_decl);
}
}
-
+
if (!Ivar) {
// In ARC, give the ivar a lifetime qualifier based on the
// property attributes.
@@ -1270,10 +1280,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Qualifiers::ObjCLifetime lifetime =
getImpliedARCOwnership(kind, PropertyIvarType);
assert(lifetime && "no lifetime for property?");
-
+
Qualifiers qs;
qs.addObjCLifetime(lifetime);
- PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
+ PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
}
}
@@ -1323,7 +1333,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Check that type of property and its ivar are type compatible.
if (!Context.hasSameType(PropertyIvarType, IvarType)) {
- if (isa<ObjCObjectPointerType>(PropertyIvarType)
+ if (isa<ObjCObjectPointerType>(PropertyIvarType)
&& isa<ObjCObjectPointerType>(IvarType))
compat =
Context.canAssignObjCInterfaces(
@@ -1380,7 +1390,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
} else if (PropertyIvar)
// @dynamic
Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl);
-
+
assert (property && "ActOnPropertyImplDecl - property declaration missing");
ObjCPropertyImplDecl *PIDecl =
ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
@@ -1402,7 +1412,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// FIXME. Eventually we want to do this for Objective-C as well.
SynthesizedFunctionScope Scope(*this, getterMethod);
ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
- DeclRefExpr *SelfExpr =
+ DeclRefExpr *SelfExpr =
new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
@@ -1430,7 +1440,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
}
if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
!getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
- Diag(getterMethod->getLocation(),
+ Diag(getterMethod->getLocation(),
diag::warn_property_getter_owning_mismatch);
Diag(property->getLocation(), diag::note_property_declare);
}
@@ -1454,7 +1464,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// FIXME. Eventually we want to do this for Objective-C as well.
SynthesizedFunctionScope Scope(*this, setterMethod);
ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
- DeclRefExpr *SelfExpr =
+ DeclRefExpr *SelfExpr =
new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
@@ -1474,27 +1484,27 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T,
VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(rhs);
- ExprResult Res = BuildBinOp(S, PropertyDiagLoc,
+ ExprResult Res = BuildBinOp(S, PropertyDiagLoc,
BO_Assign, lhs, rhs);
- if (property->getPropertyAttributes() &
+ if (property->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_atomic) {
Expr *callExpr = Res.getAs<Expr>();
- if (const CXXOperatorCallExpr *CXXCE =
+ if (const CXXOperatorCallExpr *CXXCE =
dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
if (!FuncDecl->isTrivial())
if (property->getType()->isReferenceType()) {
- Diag(PropertyDiagLoc,
+ Diag(PropertyDiagLoc,
diag::err_atomic_property_nontrivial_assign_op)
<< property->getType();
- Diag(FuncDecl->getLocStart(),
+ Diag(FuncDecl->getLocStart(),
diag::note_callee_decl) << FuncDecl;
}
}
PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
}
}
-
+
if (IC) {
if (Synthesize)
if (ObjCPropertyImplDecl *PPIDecl =
@@ -1527,9 +1537,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
}
// Issue diagnostics only if Ivar belongs to current class.
- if (Ivar && Ivar->getSynthesize() &&
+ if (Ivar && Ivar->getSynthesize() &&
declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
- Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
+ Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
<< PropertyId;
Ivar->setInvalidDecl();
}
@@ -1572,7 +1582,7 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
Property->getPropertyAttributes();
ObjCPropertyDecl::PropertyAttributeKind SAttr =
SuperProperty->getPropertyAttributes();
-
+
// We allow readonly properties without an explicit ownership
// (assign/unsafe_unretained/weak/retain/strong/copy) in super class
// to be overridden by a property with any explicit ownership in the subclass.
@@ -1632,7 +1642,7 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
// FIXME. For future support of covariant property types, revisit this.
bool IncompatibleObjC = false;
QualType ConvertedType;
- if (!isObjCPointerConversion(RHSType, LHSType,
+ if (!isObjCPointerConversion(RHSType, LHSType,
ConvertedType, IncompatibleObjC) ||
IncompatibleObjC) {
Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
@@ -1673,7 +1683,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
compat = false;
}
}
-
+
if (!compat) {
Diag(Loc, diag::warn_accessor_property_type_mismatch)
<< property->getDeclName()
@@ -1734,9 +1744,9 @@ CollectImmediateProperties(ObjCContainerDecl *CDecl,
ObjCPropertyDecl *PropertyFromSuper =
SuperPropMap[std::make_pair(Prop->getIdentifier(),
Prop->isClassProperty())];
- // Exclude property for protocols which conform to class's super-class,
+ // Exclude property for protocols which conform to class's super-class,
// as super-class has to implement the property.
- if (!PropertyFromSuper ||
+ if (!PropertyFromSuper ||
PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
ObjCPropertyDecl *&PropEntry =
PropMap[std::make_pair(Prop->getIdentifier(),
@@ -1778,7 +1788,7 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
Method->isInstanceMethod());
if (!IMD || !IMD->isPropertyAccessor())
return false;
-
+
// look up a property declaration whose one of its accessors is implemented
// by this method.
for (const auto *Property : IFace->instance_properties()) {
@@ -1819,7 +1829,7 @@ static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
return false;
}
-/// \brief Default synthesizes all properties which must be synthesized
+/// Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
ObjCInterfaceDecl *IDecl,
@@ -1831,7 +1841,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
return;
ObjCInterfaceDecl::PropertyMap SuperPropMap;
CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
-
+
for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) {
ObjCPropertyDecl *Prop = PropertyOrder[i];
// Is there a matching property synthesize/dynamic?
@@ -1987,7 +1997,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
if (IDecl)
CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
-
+
// When SynthesizeProperties is true, we only check class properties.
CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap,
SynthesizeProperties/*CollectClassPropsOnly*/);
@@ -2038,7 +2048,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
// Collect property accessors implemented in current implementation.
for (const auto *I : IMPDecl->methods())
InsMap.insert(I);
-
+
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
ObjCInterfaceDecl *PrimaryClass = nullptr;
if (C && !C->IsClassExtension())
@@ -2111,7 +2121,7 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
for (const auto *Ext : IDecl->known_extensions())
for (auto *Prop : Ext->properties())
PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
-
+
for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
I != E; ++I) {
const ObjCPropertyDecl *Property = I->second;
@@ -2181,7 +2191,7 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
<< FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
} else if (Property->getLParenLoc().isInvalid()) {
//@property id etc.
- SourceLocation startLoc =
+ SourceLocation startLoc =
Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
Diag(Property->getLocation(),
diag::note_atomic_property_fixup_suggest)
@@ -2291,8 +2301,8 @@ static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
ObjCPropertyDecl *Property) {
// Should we just clone all attributes over?
for (const auto *A : Property->attrs()) {
- if (isa<DeprecatedAttr>(A) ||
- isa<UnavailableAttr>(A) ||
+ if (isa<DeprecatedAttr>(A) ||
+ isa<UnavailableAttr>(A) ||
isa<AvailabilityAttr>(A))
PropertyMethod->addAttr(A->clone(S.Context));
}
@@ -2322,7 +2332,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
getClassMethod(property->getGetterName()) :
CatDecl->getClassInterface()->
getInstanceMethod(property->getGetterName());
-
+
SetterMethod = IsClassProperty ?
CD->getClassMethod(property->getSetterName()) :
CD->getInstanceMethod(property->getSetterName());
@@ -2342,7 +2352,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
if (SetterMethod->param_size() != 1 ||
!Context.hasSameUnqualifiedType(
- (*SetterMethod->param_begin())->getType().getNonReferenceType(),
+ (*SetterMethod->param_begin())->getType().getNonReferenceType(),
property->getType().getNonReferenceType())) {
Diag(property->getLocation(),
diag::warn_accessor_property_type_mismatch)
@@ -2396,11 +2406,11 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
Loc));
-
+
if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
GetterMethod->addAttr(
ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
-
+
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
GetterMethod->addAttr(
SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
@@ -2525,12 +2535,12 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
// FIXME: Improve the reported location.
if (!PDecl || PDecl->isInvalidDecl())
return;
-
+
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
<< "readonly" << "readwrite";
-
+
ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
QualType PropertyTy = PropertyDecl->getType();
@@ -2646,19 +2656,19 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
// do nothing
} else if (getLangOpts().ObjCAutoRefCount) {
- // With arc, @property definitions should default to strong when
+ // With arc, @property definitions should default to strong when
// not specified.
PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
} else if (PropertyTy->isObjCObjectPointerType()) {
- bool isAnyClassTy =
- (PropertyTy->isObjCClassType() ||
+ bool isAnyClassTy =
+ (PropertyTy->isObjCClassType() ||
PropertyTy->isObjCQualifiedClassType());
// In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
// issue any warning.
if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
;
else if (propertyInPrimaryClass) {
- // Don't issue warning on property with no life time in class
+ // Don't issue warning on property with no life time in class
// extension as it is inherited from property in primary class.
// Skip this warning in gc-only mode.
if (getLangOpts().getGC() != LangOptions::GCOnly)
@@ -2686,7 +2696,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
!(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
PropertyTy->isBlockPointerType())
Diag(Loc, diag::warn_objc_property_retain_of_block);
-
+
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
(Attributes & ObjCDeclSpec::DQ_PR_setter))
Diag(Loc, diag::warn_objc_readonly_property_has_setter);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index 24b58e8fd12b..6060e5b75c22 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements semantic analysis for OpenMP directives and
+/// This file implements semantic analysis for OpenMP directives and
/// clauses.
///
//===----------------------------------------------------------------------===//
@@ -35,17 +35,17 @@ using namespace clang;
// Stack of data-sharing attributes for variables
//===----------------------------------------------------------------------===//
-static Expr *CheckMapClauseExpressionBase(
+static const 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.
+/// 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_unspecified = 0, /// Data sharing attribute not specified.
+ DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
+ DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
};
/// Attributes of the defaultmap clause.
@@ -54,51 +54,53 @@ enum DefaultMapAttributes {
DMA_tofrom_scalar, /// Default mapping is 'tofrom:scalar'.
};
-/// \brief Stack for tracking declarations used in OpenMP directives and
+/// Stack for tracking declarations used in OpenMP directives and
/// clauses and their data-sharing attributes.
-class DSAStackTy final {
+class DSAStackTy {
public:
- struct DSAVarData final {
+ struct DSAVarData {
OpenMPDirectiveKind DKind = OMPD_unknown;
OpenMPClauseKind CKind = OMPC_unknown;
- Expr *RefExpr = nullptr;
+ const Expr *RefExpr = nullptr;
DeclRefExpr *PrivateCopy = nullptr;
SourceLocation ImplicitDSALoc;
DSAVarData() = default;
- DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, Expr *RefExpr,
- DeclRefExpr *PrivateCopy, SourceLocation ImplicitDSALoc)
+ DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
+ const 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;
+ using OperatorOffsetTy =
+ llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
+ using DoacrossDependMapTy =
+ llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
private:
- struct DSAInfo final {
+ struct DSAInfo {
OpenMPClauseKind Attributes = OMPC_unknown;
/// Pointer to a reference expression and a flag which shows that the
/// variable is marked as lastprivate(true) or not (false).
- llvm::PointerIntPair<Expr *, 1, bool> RefExpr;
+ llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
DeclRefExpr *PrivateCopy = nullptr;
};
- typedef llvm::DenseMap<ValueDecl *, DSAInfo> DeclSAMapTy;
- typedef llvm::DenseMap<ValueDecl *, Expr *> AlignedMapTy;
- typedef std::pair<unsigned, VarDecl *> LCDeclInfo;
- typedef llvm::DenseMap<ValueDecl *, LCDeclInfo> LoopControlVariablesMapTy;
+ using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
+ using AlignedMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
+ using LCDeclInfo = std::pair<unsigned, VarDecl *>;
+ using LoopControlVariablesMapTy =
+ llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
/// Struct that associates a component with the clause kind where they are
/// found.
struct MappedExprComponentTy {
OMPClauseMappableExprCommon::MappableExprComponentLists Components;
OpenMPClauseKind Kind = OMPC_unknown;
};
- typedef llvm::DenseMap<ValueDecl *, MappedExprComponentTy>
- MappedExprComponentsTy;
- typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
- CriticalsWithHintsTy;
- typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
- DoacrossDependMapTy;
+ using MappedExprComponentsTy =
+ llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
+ using CriticalsWithHintsTy =
+ llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
struct ReductionData {
- typedef llvm::PointerEmbeddedInt<BinaryOperatorKind, 16> BOKPtrType;
+ using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
SourceRange ReductionRange;
llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
ReductionData() = default;
@@ -111,9 +113,10 @@ private:
ReductionOp = RefExpr;
}
};
- typedef llvm::DenseMap<ValueDecl *, ReductionData> DeclReductionMapTy;
+ using DeclReductionMapTy =
+ llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
- struct SharingMapTy final {
+ struct SharingMapTy {
DeclSAMapTy SharingMap;
DeclReductionMapTy ReductionMap;
AlignedMapTy AlignedMap;
@@ -131,10 +134,10 @@ private:
/// get the data (loop counters etc.) about enclosing loop-based construct.
/// This data is required during codegen.
DoacrossDependMapTy DoacrossDepends;
- /// \brief first argument (Expr *) contains optional argument of the
+ /// first argument (Expr *) contains optional argument of the
/// 'ordered' clause, the second one is true if the regions has 'ordered'
/// clause, false otherwise.
- llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion;
+ llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
bool NowaitRegion = false;
bool CancelRegion = false;
unsigned AssociatedLoops = 1;
@@ -148,25 +151,25 @@ private:
SharingMapTy() = default;
};
- typedef SmallVector<SharingMapTy, 4> StackTy;
+ using StackTy = SmallVector<SharingMapTy, 4>;
- /// \brief Stack of used declaration and their data-sharing attributes.
+ /// Stack of used declaration and their data-sharing attributes.
DeclSAMapTy Threadprivates;
const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
- /// \brief true, if check for DSA must be from parent directive, false, if
+ /// true, if check for DSA must be from parent directive, false, if
/// from current directive.
OpenMPClauseKind ClauseKindMode = OMPC_unknown;
Sema &SemaRef;
bool ForceCapturing = false;
CriticalsWithHintsTy Criticals;
- typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
+ using iterator = StackTy::const_reverse_iterator;
- DSAVarData getDSA(StackTy::reverse_iterator &Iter, ValueDecl *D);
+ DSAVarData getDSA(iterator &Iter, ValueDecl *D) const;
- /// \brief Checks if the variable is a local for OpenMP region.
- bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
+ /// Checks if the variable is a local for OpenMP region.
+ bool isOpenMPLocal(VarDecl *D, iterator Iter) const;
bool isStackEmpty() const {
return Stack.empty() ||
@@ -223,59 +226,61 @@ public:
}
}
- void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) {
- Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint);
+ void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
+ Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
}
- const std::pair<OMPCriticalDirective *, llvm::APSInt>
+ const std::pair<const OMPCriticalDirective *, llvm::APSInt>
getCriticalWithHint(const DeclarationNameInfo &Name) const {
auto I = Criticals.find(Name.getAsString());
if (I != Criticals.end())
return I->second;
return std::make_pair(nullptr, llvm::APSInt());
}
- /// \brief If 'aligned' declaration for given variable \a D was not seen yet,
+ /// If 'aligned' declaration for given variable \a D was not seen yet,
/// add it and return NULL; otherwise return previous occurrence's expression
/// for diagnostics.
- Expr *addUniqueAligned(ValueDecl *D, Expr *NewDE);
+ const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
- /// \brief Register specified variable as loop control variable.
- void addLoopControlVariable(ValueDecl *D, VarDecl *Capture);
- /// \brief Check if the specified variable is a loop control variable for
+ /// Register specified variable as loop control variable.
+ void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
+ /// Check if the specified variable is a loop control variable for
/// current region.
/// \return The index of the loop control variable in the list of associated
/// for-loops (from outer to inner).
- LCDeclInfo isLoopControlVariable(ValueDecl *D);
- /// \brief Check if the specified variable is a loop control variable for
+ const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
+ /// Check if the specified variable is a loop control variable for
/// parent region.
/// \return The index of the loop control variable in the list of associated
/// for-loops (from outer to inner).
- LCDeclInfo isParentLoopControlVariable(ValueDecl *D);
- /// \brief Get the loop control variable for the I-th loop (or nullptr) in
+ const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
+ /// Get the loop control variable for the I-th loop (or nullptr) in
/// parent directive.
- ValueDecl *getParentLoopControlVariable(unsigned I);
+ const ValueDecl *getParentLoopControlVariable(unsigned I) const;
- /// \brief Adds explicit data sharing attribute to the specified declaration.
- void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
+ /// Adds explicit data sharing attribute to the specified declaration.
+ void addDSA(const ValueDecl *D, const 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,
+ void addTaskgroupReductionData(const 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,
+ void addTaskgroupReductionData(const 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);
+ const DSAVarData
+ getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
+ BinaryOperatorKind &BOK,
+ Expr *&TaskgroupDescriptor) const;
/// 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);
+ const DSAVarData
+ getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
+ const Expr *&ReductionRef,
+ Expr *&TaskgroupDescriptor) const;
/// Return reduction reference expression for the current taskgroup.
Expr *getTaskgroupReductionRef() const {
assert(Stack.back().first.back().Directive == OMPD_taskgroup &&
@@ -285,74 +290,75 @@ public:
}
/// 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 {
+ bool isTaskgroupReductionRef(const 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
+ /// Returns data sharing attributes from top of the stack for the
/// specified declaration.
- DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
- /// \brief Returns data-sharing attributes for the specified declaration.
- DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent);
- /// \brief Checks if the specified variables has data-sharing attributes which
+ const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
+ /// Returns data-sharing attributes for the specified declaration.
+ const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
+ /// Checks if the specified variables has data-sharing attributes which
/// match specified \a CPred predicate in any directive which matches \a DPred
/// predicate.
- DSAVarData hasDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent);
- /// \brief Checks if the specified variables has data-sharing attributes which
+ const DSAVarData
+ hasDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const;
+ /// Checks if the specified variables has data-sharing attributes which
/// match specified \a CPred predicate in any innermost directive which
/// matches \a DPred predicate.
- DSAVarData
+ const DSAVarData
hasInnermostDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent);
- /// \brief Checks if the specified variables has explicit data-sharing
+ const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const;
+ /// Checks if the specified variables has explicit data-sharing
/// attributes which match specified \a CPred predicate at the specified
/// OpenMP region.
- bool hasExplicitDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- unsigned Level, bool NotLastprivate = false);
+ bool hasExplicitDSA(const ValueDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ unsigned Level, bool NotLastprivate = false) const;
- /// \brief Returns true if the directive at level \Level matches in the
+ /// Returns true if the directive at level \Level matches in the
/// specified \a DPred predicate.
bool hasExplicitDirective(
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- unsigned Level);
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ unsigned Level) const;
- /// \brief Finds a directive which matches specified \a DPred predicate.
- bool hasDirective(const llvm::function_ref<bool(OpenMPDirectiveKind,
- const DeclarationNameInfo &,
- SourceLocation)> &DPred,
- bool FromParent);
+ /// Finds a directive which matches specified \a DPred predicate.
+ bool hasDirective(
+ const llvm::function_ref<bool(
+ OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
+ DPred,
+ bool FromParent) const;
- /// \brief Returns currently analyzed directive.
+ /// Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return isStackEmpty() ? OMPD_unknown : Stack.back().first.back().Directive;
}
- /// \brief Returns directive kind at specified level.
+ /// 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.
+ /// Returns parent directive.
OpenMPDirectiveKind getParentDirective() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return OMPD_unknown;
return std::next(Stack.back().first.rbegin())->Directive;
}
- /// \brief Set default data sharing attribute to none.
+ /// Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultAttr = DSA_none;
Stack.back().first.back().DefaultAttrLoc = Loc;
}
- /// \brief Set default data sharing attribute to shared.
+ /// Set default data sharing attribute to shared.
void setDefaultDSAShared(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultAttr = DSA_shared;
@@ -385,66 +391,85 @@ public:
: Stack.back().first.back().DefaultMapAttrLoc;
}
- /// \brief Checks if the specified variable is a threadprivate.
+ /// Checks if the specified variable is a threadprivate.
bool isThreadPrivate(VarDecl *D) {
- DSAVarData DVar = getTopDSA(D, false);
+ const DSAVarData DVar = getTopDSA(D, false);
return isOpenMPThreadPrivate(DVar.CKind);
}
- /// \brief Marks current region as ordered (it has an 'ordered' clause).
- void setOrderedRegion(bool IsOrdered, Expr *Param) {
+ /// Marks current region as ordered (it has an 'ordered' clause).
+ void setOrderedRegion(bool IsOrdered, const Expr *Param,
+ OMPOrderedClause *Clause) {
assert(!isStackEmpty());
- Stack.back().first.back().OrderedRegion.setInt(IsOrdered);
- Stack.back().first.back().OrderedRegion.setPointer(Param);
+ if (IsOrdered)
+ Stack.back().first.back().OrderedRegion.emplace(Param, Clause);
+ else
+ Stack.back().first.back().OrderedRegion.reset();
+ }
+ /// Returns true, if region is ordered (has associated 'ordered' clause),
+ /// false - otherwise.
+ bool isOrderedRegion() const {
+ if (isStackEmpty())
+ return false;
+ return Stack.back().first.rbegin()->OrderedRegion.hasValue();
+ }
+ /// Returns optional parameter for the ordered region.
+ std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
+ if (isStackEmpty() ||
+ !Stack.back().first.rbegin()->OrderedRegion.hasValue())
+ return std::make_pair(nullptr, nullptr);
+ return Stack.back().first.rbegin()->OrderedRegion.getValue();
}
- /// \brief Returns true, if parent region is ordered (has associated
+ /// Returns true, if parent region is ordered (has associated
/// 'ordered' clause), false - otherwise.
bool isParentOrderedRegion() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return false;
- return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt();
+ return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue();
}
- /// \brief Returns optional parameter for the ordered region.
- Expr *getParentOrderedRegionParam() const {
- if (isStackEmpty() || Stack.back().first.size() == 1)
- return nullptr;
- return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer();
+ /// Returns optional parameter for the ordered region.
+ std::pair<const Expr *, OMPOrderedClause *>
+ getParentOrderedRegionParam() const {
+ if (isStackEmpty() || Stack.back().first.size() == 1 ||
+ !std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue())
+ return std::make_pair(nullptr, nullptr);
+ return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue();
}
- /// \brief Marks current region as nowait (it has a 'nowait' clause).
+ /// Marks current region as nowait (it has a 'nowait' clause).
void setNowaitRegion(bool IsNowait = true) {
assert(!isStackEmpty());
Stack.back().first.back().NowaitRegion = IsNowait;
}
- /// \brief Returns true, if parent region is nowait (has associated
+ /// Returns true, if parent region is nowait (has associated
/// 'nowait' clause), false - otherwise.
bool isParentNowaitRegion() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return false;
return std::next(Stack.back().first.rbegin())->NowaitRegion;
}
- /// \brief Marks parent region as cancel region.
+ /// Marks parent region as cancel region.
void setParentCancelRegion(bool Cancel = true) {
if (!isStackEmpty() && Stack.back().first.size() > 1) {
auto &StackElemRef = *std::next(Stack.back().first.rbegin());
StackElemRef.CancelRegion |= StackElemRef.CancelRegion || Cancel;
}
}
- /// \brief Return true if current region has inner cancel construct.
+ /// Return true if current region has inner cancel construct.
bool isCancelRegion() const {
return isStackEmpty() ? false : Stack.back().first.back().CancelRegion;
}
- /// \brief Set collapse value for the region.
+ /// Set collapse value for the region.
void setAssociatedLoops(unsigned Val) {
assert(!isStackEmpty());
Stack.back().first.back().AssociatedLoops = Val;
}
- /// \brief Return collapse value for region.
+ /// Return collapse value for region.
unsigned getAssociatedLoops() const {
return isStackEmpty() ? 0 : Stack.back().first.back().AssociatedLoops;
}
- /// \brief Marks current target region as one with closely nested teams
+ /// Marks current target region as one with closely nested teams
/// region.
void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
if (!isStackEmpty() && Stack.back().first.size() > 1) {
@@ -452,11 +477,11 @@ public:
TeamsRegionLoc;
}
}
- /// \brief Returns true, if current region has closely nested teams region.
+ /// Returns true, if current region has closely nested teams region.
bool hasInnerTeamsRegion() const {
return getInnerTeamsRegionLoc().isValid();
}
- /// \brief Returns location of the nested teams region (if any).
+ /// Returns location of the nested teams region (if any).
SourceLocation getInnerTeamsRegionLoc() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().InnerTeamsRegionLoc;
@@ -465,10 +490,7 @@ public:
Scope *getCurScope() const {
return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope;
}
- Scope *getCurScope() {
- return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope;
- }
- SourceLocation getConstructLoc() {
+ SourceLocation getConstructLoc() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().ConstructLoc;
}
@@ -476,10 +498,11 @@ public:
/// Do the check specified in \a Check to all component lists and return true
/// if any issue is found.
bool checkMappableExprComponentListsForDecl(
- ValueDecl *VD, bool CurrentRegionOnly,
+ const ValueDecl *VD, bool CurrentRegionOnly,
const llvm::function_ref<
bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
- OpenMPClauseKind)> &Check) {
+ OpenMPClauseKind)>
+ Check) const {
if (isStackEmpty())
return false;
auto SI = Stack.back().first.rbegin();
@@ -488,16 +511,16 @@ public:
if (SI == SE)
return false;
- if (CurrentRegionOnly) {
+ if (CurrentRegionOnly)
SE = std::next(SI);
- } else {
- ++SI;
- }
+ else
+ std::advance(SI, 1);
for (; SI != SE; ++SI) {
auto MI = SI->MappedExprComponents.find(VD);
if (MI != SI->MappedExprComponents.end())
- for (auto &L : MI->second.Components)
+ for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
+ MI->second.Components)
if (Check(L, MI->second.Kind))
return true;
}
@@ -507,10 +530,11 @@ public:
/// Do the check specified in \a Check to all component lists at a given level
/// and return true if any issue is found.
bool checkMappableExprComponentListsForDeclAtLevel(
- ValueDecl *VD, unsigned Level,
+ const ValueDecl *VD, unsigned Level,
const llvm::function_ref<
bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
- OpenMPClauseKind)> &Check) {
+ OpenMPClauseKind)>
+ Check) const {
if (isStackEmpty())
return false;
@@ -522,7 +546,8 @@ public:
auto MI = StartI->MappedExprComponents.find(VD);
if (MI != StartI->MappedExprComponents.end())
- for (auto &L : MI->second.Components)
+ for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
+ MI->second.Components)
if (Check(L, MI->second.Kind))
return true;
return false;
@@ -531,12 +556,13 @@ public:
/// Create a new mappable expression component list associated with a given
/// declaration and initialize it with the provided list of components.
void addMappableExpressionComponents(
- ValueDecl *VD,
+ const ValueDecl *VD,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPClauseKind WhereFoundClauseKind) {
assert(!isStackEmpty() &&
"Not expecting to retrieve components from a empty stack!");
- auto &MEC = Stack.back().first.back().MappedExprComponents[VD];
+ MappedExprComponentTy &MEC =
+ Stack.back().first.back().MappedExprComponents[VD];
// Create new entry and append the new components there.
MEC.Components.resize(MEC.Components.size() + 1);
MEC.Components.back().append(Components.begin(), Components.end());
@@ -547,18 +573,19 @@ public:
assert(!isStackEmpty());
return Stack.back().first.size() - 1;
}
- void addDoacrossDependClause(OMPDependClause *C, OperatorOffsetTy &OpsOffs) {
+ void addDoacrossDependClause(OMPDependClause *C,
+ const OperatorOffsetTy &OpsOffs) {
assert(!isStackEmpty() && Stack.back().first.size() > 1);
- auto &StackElem = *std::next(Stack.back().first.rbegin());
+ SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
assert(isOpenMPWorksharingDirective(StackElem.Directive));
- StackElem.DoacrossDepends.insert({C, OpsOffs});
+ StackElem.DoacrossDepends.try_emplace(C, OpsOffs);
}
llvm::iterator_range<DoacrossDependMapTy::const_iterator>
getDoacrossDependClauses() const {
assert(!isStackEmpty());
- auto &StackElem = Stack.back().first.back();
+ const SharingMapTy &StackElem = Stack.back().first.back();
if (isOpenMPWorksharingDirective(StackElem.Directive)) {
- auto &Ref = StackElem.DoacrossDepends;
+ const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
return llvm::make_range(Ref.begin(), Ref.end());
}
return llvm::make_range(StackElem.DoacrossDepends.end(),
@@ -569,29 +596,34 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
return isOpenMPParallelDirective(DKind) || isOpenMPTaskingDirective(DKind) ||
isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
}
+
} // namespace
-static Expr *getExprAsWritten(Expr *E) {
- if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
+static const Expr *getExprAsWritten(const Expr *E) {
+ if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
E = ExprTemp->getSubExpr();
- if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
E = MTE->GetTemporaryExpr();
- while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+ while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
E = Binder->getSubExpr();
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ if (const 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())))
+static Expr *getExprAsWritten(Expr *E) {
+ return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
+}
+
+static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
+ if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
+ if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
D = ME->getMemberDecl();
- auto *VD = dyn_cast<VarDecl>(D);
- auto *FD = dyn_cast<FieldDecl>(D);
+ const auto *VD = dyn_cast<VarDecl>(D);
+ const auto *FD = dyn_cast<FieldDecl>(D);
if (VD != nullptr) {
VD = VD->getCanonicalDecl();
D = VD;
@@ -603,11 +635,16 @@ static ValueDecl *getCanonicalDecl(ValueDecl *D) {
return D;
}
-DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
- ValueDecl *D) {
+static ValueDecl *getCanonicalDecl(ValueDecl *D) {
+ return const_cast<ValueDecl *>(
+ getCanonicalDecl(const_cast<const ValueDecl *>(D)));
+}
+
+DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter,
+ ValueDecl *D) const {
D = getCanonicalDecl(D);
auto *VD = dyn_cast<VarDecl>(D);
- auto *FD = dyn_cast<FieldDecl>(D);
+ const auto *FD = dyn_cast<FieldDecl>(D);
DSAVarData DVar;
if (isStackEmpty() || Iter == Stack.back().first.rend()) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -615,7 +652,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// File-scope or namespace-scope variables referenced in called routines
// in the region are shared unless they appear in a threadprivate
// directive.
- if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(D))
+ if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
DVar.CKind = OMPC_shared;
// OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
@@ -646,9 +683,10 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// Explicitly specified attributes and local variables with predetermined
// attributes.
if (Iter->SharingMap.count(D)) {
- DVar.RefExpr = Iter->SharingMap[D].RefExpr.getPointer();
- DVar.PrivateCopy = Iter->SharingMap[D].PrivateCopy;
- DVar.CKind = Iter->SharingMap[D].Attributes;
+ const DSAInfo &Data = Iter->SharingMap.lookup(D);
+ DVar.RefExpr = Data.RefExpr.getPointer();
+ DVar.PrivateCopy = Data.PrivateCopy;
+ DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
return DVar;
}
@@ -683,7 +721,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// bound to the current team is shared.
if (isOpenMPTaskingDirective(DVar.DKind)) {
DSAVarData DVarTemp;
- auto I = Iter, E = Stack.back().first.rend();
+ iterator I = Iter, E = Stack.back().first.rend();
do {
++I;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
@@ -711,74 +749,75 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
return getDSA(++Iter, D);
}
-Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) {
+const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
+ const Expr *NewDE) {
assert(!isStackEmpty() && "Data sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = Stack.back().first.back();
+ SharingMapTy &StackElem = Stack.back().first.back();
auto It = StackElem.AlignedMap.find(D);
if (It == StackElem.AlignedMap.end()) {
assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
StackElem.AlignedMap[D] = NewDE;
return nullptr;
- } else {
- assert(It->second && "Unexpected nullptr expr in the aligned map");
- return It->second;
}
- return nullptr;
+ assert(It->second && "Unexpected nullptr expr in the aligned map");
+ return It->second;
}
-void DSAStackTy::addLoopControlVariable(ValueDecl *D, VarDecl *Capture) {
+void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = Stack.back().first.back();
- StackElem.LCVMap.insert(
- {D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture)});
+ SharingMapTy &StackElem = Stack.back().first.back();
+ StackElem.LCVMap.try_emplace(
+ D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
}
-DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(ValueDecl *D) {
+const DSAStackTy::LCDeclInfo
+DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = Stack.back().first.back();
+ const SharingMapTy &StackElem = Stack.back().first.back();
auto It = StackElem.LCVMap.find(D);
if (It != StackElem.LCVMap.end())
return It->second;
return {0, nullptr};
}
-DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
+const DSAStackTy::LCDeclInfo
+DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
"Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = *std::next(Stack.back().first.rbegin());
+ const SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
auto It = StackElem.LCVMap.find(D);
if (It != StackElem.LCVMap.end())
return It->second;
return {0, nullptr};
}
-ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
+const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
"Data-sharing attributes stack is empty");
- auto &StackElem = *std::next(Stack.back().first.rbegin());
+ const SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
if (StackElem.LCVMap.size() < I)
return nullptr;
- for (auto &Pair : StackElem.LCVMap)
+ for (const auto &Pair : StackElem.LCVMap)
if (Pair.second.first == I)
return Pair.first;
return nullptr;
}
-void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
+void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy) {
D = getCanonicalDecl(D);
if (A == OMPC_threadprivate) {
- auto &Data = Threadprivates[D];
+ DSAInfo &Data = Threadprivates[D];
Data.Attributes = A;
Data.RefExpr.setPointer(E);
Data.PrivateCopy = nullptr;
} else {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
- auto &Data = Stack.back().first.back().SharingMap[D];
+ DSAInfo &Data = Stack.back().first.back().SharingMap[D];
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
@@ -793,7 +832,8 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
Data.RefExpr.setPointerAndInt(E, IsLastprivate);
Data.PrivateCopy = PrivateCopy;
if (PrivateCopy) {
- auto &Data = Stack.back().first.back().SharingMap[PrivateCopy->getDecl()];
+ DSAInfo &Data =
+ Stack.back().first.back().SharingMap[PrivateCopy->getDecl()];
Data.Attributes = A;
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
Data.PrivateCopy = nullptr;
@@ -801,13 +841,14 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
}
}
-/// \brief Build a variable declaration for OpenMP loop iteration variable.
+/// Build a variable declaration for OpenMP loop iteration variable.
static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
- StringRef Name, const AttrVec *Attrs = nullptr) {
+ StringRef Name, const AttrVec *Attrs = nullptr,
+ DeclRefExpr *OrigRef = nullptr) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
- VarDecl *Decl =
+ auto *Decl =
VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
if (Attrs) {
for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
@@ -815,6 +856,10 @@ static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
Decl->addAttr(*I);
}
Decl->setImplicit();
+ if (OrigRef) {
+ Decl->addAttr(
+ OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
+ }
return Decl;
}
@@ -828,14 +873,14 @@ static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
VK_LValue);
}
-void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+void DSAStackTy::addTaskgroupReductionData(const 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];
+ ReductionData &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 "
@@ -844,21 +889,21 @@ void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
Expr *&TaskgroupReductionRef =
Stack.back().first.back().TaskgroupReductionRef;
if (!TaskgroupReductionRef) {
- auto *VD = buildVarDecl(SemaRef, SR.getBegin(),
- SemaRef.Context.VoidPtrTy, ".task_red.");
+ VarDecl *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,
+void DSAStackTy::addTaskgroupReductionData(const 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];
+ ReductionData &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 "
@@ -867,28 +912,27 @@ void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
Expr *&TaskgroupReductionRef =
Stack.back().first.back().TaskgroupReductionRef;
if (!TaskgroupReductionRef) {
- auto *VD = buildVarDecl(SemaRef, SR.getBegin(), SemaRef.Context.VoidPtrTy,
- ".task_red.");
+ VarDecl *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) {
+const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
+ const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
+ Expr *&TaskgroupDescriptor) const {
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();
+ for (iterator I = std::next(Stack.back().first.rbegin(), 1),
+ E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
- auto &Data = I->SharingMap[D];
+ const DSAInfo &Data = I->SharingMap.lookup(D);
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
- auto &ReductionData = I->ReductionMap[D];
+ const ReductionData &ReductionData = I->ReductionMap.lookup(D);
if (!ReductionData.ReductionOp ||
ReductionData.ReductionOp.is<const Expr *>())
return DSAVarData();
@@ -904,21 +948,20 @@ DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
return DSAVarData();
}
-DSAStackTy::DSAVarData
-DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
- const Expr *&ReductionRef,
- Expr *&TaskgroupDescriptor) {
+const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
+ const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
+ Expr *&TaskgroupDescriptor) const {
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();
+ for (iterator I = std::next(Stack.back().first.rbegin(), 1),
+ E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
- auto &Data = I->SharingMap[D];
+ const DSAInfo &Data = I->SharingMap.lookup(D);
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
- auto &ReductionData = I->ReductionMap[D];
+ const ReductionData &ReductionData = I->ReductionMap.lookup(D);
if (!ReductionData.ReductionOp ||
!ReductionData.ReductionOp.is<const Expr *>())
return DSAVarData();
@@ -934,12 +977,13 @@ DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
return DSAVarData();
}
-bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const {
D = D->getCanonicalDecl();
- if (!isStackEmpty() && Stack.back().first.size() > 1) {
- reverse_iterator I = Iter, E = Stack.back().first.rend();
+ if (!isStackEmpty()) {
+ iterator I = Iter, E = Stack.back().first.rend();
Scope *TopScope = nullptr;
- while (I != E && !isParallelOrTaskRegion(I->Directive))
+ while (I != E && !isParallelOrTaskRegion(I->Directive) &&
+ !isOpenMPTargetExecutionDirective(I->Directive))
++I;
if (I == E)
return false;
@@ -952,35 +996,80 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
return false;
}
-DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
+const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
+ bool FromParent) {
D = getCanonicalDecl(D);
DSAVarData DVar;
+ auto *VD = dyn_cast<VarDecl>(D);
+ auto TI = Threadprivates.find(D);
+ if (TI != Threadprivates.end()) {
+ DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ 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);
+ return DVar;
+ }
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.1]
// Variables appearing in threadprivate directives are threadprivate.
- auto *VD = dyn_cast<VarDecl>(D);
if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
!(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
SemaRef.getLangOpts().OpenMPUseTLS &&
SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
(VD && VD->getStorageClass() == SC_Register &&
VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
- addDSA(D, buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
- D->getLocation()),
- OMPC_threadprivate);
- }
- auto TI = Threadprivates.find(D);
- if (TI != Threadprivates.end()) {
- 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());
+ SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
DVar.CKind = OMPC_threadprivate;
addDSA(D, DVar.RefExpr, OMPC_threadprivate);
+ return DVar;
+ }
+ if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
+ VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
+ !isLoopControlVariable(D).first) {
+ iterator IterTarget =
+ std::find_if(Stack.back().first.rbegin(), Stack.back().first.rend(),
+ [](const SharingMapTy &Data) {
+ return isOpenMPTargetExecutionDirective(Data.Directive);
+ });
+ if (IterTarget != Stack.back().first.rend()) {
+ iterator ParentIterTarget = std::next(IterTarget, 1);
+ for (iterator Iter = Stack.back().first.rbegin();
+ Iter != ParentIterTarget; std::advance(Iter, 1)) {
+ if (isOpenMPLocal(VD, Iter)) {
+ DVar.RefExpr =
+ buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
+ D->getLocation());
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ }
+ if (!isClauseParsingMode() || IterTarget != Stack.back().first.rbegin()) {
+ auto DSAIter = IterTarget->SharingMap.find(D);
+ if (DSAIter != IterTarget->SharingMap.end() &&
+ isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
+ DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ iterator End = Stack.back().first.rend();
+ if (!SemaRef.isOpenMPCapturedByRef(
+ D, std::distance(ParentIterTarget, End))) {
+ DVar.RefExpr =
+ buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
+ IterTarget->ConstructLoc);
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ }
+ }
}
if (isStackEmpty())
@@ -994,7 +1083,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// in a Construct, C/C++, predetermined, p.7]
// Variables with static storage duration that are declared in a scope
// inside the construct are shared.
- auto &&MatchesAlways = [](OpenMPDirectiveKind) -> bool { return true; };
+ auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
if (VD && VD->isStaticDataMember()) {
DSAVarData DVarTemp = hasDSA(D, isOpenMPPrivate, MatchesAlways, FromParent);
if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
@@ -1011,21 +1100,21 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// in a Construct, C/C++, predetermined, p.6]
// Variables with const qualified type having no mutable member are
// shared.
- CXXRecordDecl *RD =
+ const CXXRecordDecl *RD =
SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
- if (auto *CTD = CTSD->getSpecializedTemplate())
+ if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
+ if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
RD = CTD->getTemplatedDecl();
if (IsConstant &&
!(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasDefinition() &&
RD->hasMutableFields())) {
// Variables with const-qualified type having no mutable member may be
// listed in a firstprivate clause, even if they are static data members.
- DSAVarData DVarTemp = hasDSA(
- D, [](OpenMPClauseKind C) -> bool { return C == OMPC_firstprivate; },
- MatchesAlways, FromParent);
+ DSAVarData DVarTemp =
+ hasDSA(D, [](OpenMPClauseKind C) { return C == OMPC_firstprivate; },
+ MatchesAlways, FromParent);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
- return DVar;
+ return DVarTemp;
DVar.CKind = OMPC_shared;
return DVar;
@@ -1033,14 +1122,16 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
- auto I = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator I = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
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;
+ auto It = I->SharingMap.find(D);
+ if (It != I->SharingMap.end()) {
+ const DSAInfo &Data = It->getSecond();
+ DVar.RefExpr = Data.RefExpr.getPointer();
+ DVar.PrivateCopy = Data.PrivateCopy;
+ DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
DVar.DKind = I->Directive;
}
@@ -1048,36 +1139,36 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
return DVar;
}
-DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
- bool FromParent) {
+const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
+ bool FromParent) const {
if (isStackEmpty()) {
- StackTy::reverse_iterator I;
+ iterator I;
return getDSA(I, D);
}
D = getCanonicalDecl(D);
- auto StartI = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator StartI = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
std::advance(StartI, 1);
return getDSA(StartI, D);
}
-DSAStackTy::DSAVarData
+const DSAStackTy::DSAVarData
DSAStackTy::hasDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent) {
+ const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const {
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
- auto I = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator I = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && I != EndI)
std::advance(I, 1);
for (; I != EndI; std::advance(I, 1)) {
if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
continue;
- auto NewI = I;
+ iterator NewI = I;
DSAVarData DVar = getDSA(NewI, D);
if (I == NewI && CPred(DVar.CKind))
return DVar;
@@ -1085,27 +1176,27 @@ DSAStackTy::hasDSA(ValueDecl *D,
return {};
}
-DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
- ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent) {
+const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
+ ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const {
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
- auto StartI = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator StartI = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
std::advance(StartI, 1);
if (StartI == EndI || !DPred(StartI->Directive))
return {};
- auto NewI = StartI;
+ iterator 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) {
+ const ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ unsigned Level, bool NotLastprivate) const {
if (isStackEmpty())
return false;
D = getCanonicalDecl(D);
@@ -1114,15 +1205,16 @@ bool DSAStackTy::hasExplicitDSA(
if (std::distance(StartI, EndI) <= (int)Level)
return false;
std::advance(StartI, Level);
- return (StartI->SharingMap.count(D) > 0) &&
- StartI->SharingMap[D].RefExpr.getPointer() &&
- CPred(StartI->SharingMap[D].Attributes) &&
- (!NotLastprivate || !StartI->SharingMap[D].RefExpr.getInt());
+ auto I = StartI->SharingMap.find(D);
+ return (I != StartI->SharingMap.end()) &&
+ I->getSecond().RefExpr.getPointer() &&
+ CPred(I->getSecond().Attributes) &&
+ (!NotLastprivate || !I->getSecond().RefExpr.getInt());
}
bool DSAStackTy::hasExplicitDirective(
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- unsigned Level) {
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ unsigned Level) const {
if (isStackEmpty())
return false;
auto StartI = Stack.back().first.begin();
@@ -1136,8 +1228,8 @@ bool DSAStackTy::hasExplicitDirective(
bool DSAStackTy::hasDirective(
const llvm::function_ref<bool(OpenMPDirectiveKind,
const DeclarationNameInfo &, SourceLocation)>
- &DPred,
- bool FromParent) {
+ DPred,
+ bool FromParent) const {
// We look only in the enclosing region.
if (isStackEmpty())
return false;
@@ -1166,15 +1258,15 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
DSAStack->popFunction(OldFSI);
}
-bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
+bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
- auto &Ctx = getASTContext();
+ ASTContext &Ctx = getASTContext();
bool IsByRef = true;
// Find the directive that is associated with the provided scope.
D = cast<ValueDecl>(D->getCanonicalDecl());
- auto Ty = D->getType();
+ QualType Ty = D->getType();
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
// This table summarizes how a given variable should be passed to the device
@@ -1241,7 +1333,9 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
bool IsVariableAssociatedWithSection = false;
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
- D, Level, [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ D, Level,
+ [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection, D](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef
MapExprComponents,
OpenMPClauseKind WhereFoundClauseKind) {
// Only the map clause information influences how a variable is
@@ -1331,20 +1425,22 @@ bool Sema::isInOpenMPTargetExecutionDirective() const {
false);
}
-VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
+VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
// If we are attempting to capture a global variable in a directive with
// 'target' we return true so that this global is also mapped to the device.
//
- // FIXME: If the declaration is enclosed in a 'declare target' directive,
- // then it should not be captured. Therefore, an extra check has to be
- // inserted here once support for 'declare target' is added.
- //
auto *VD = dyn_cast<VarDecl>(D);
- if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective())
+ if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) {
+ // If the declaration is enclosed in a 'declare target' directive,
+ // then it should not be captured.
+ //
+ if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ return nullptr;
return VD;
+ }
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
@@ -1355,12 +1451,13 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
isParallelOrTaskRegion(DSAStack->getCurrentDirective())) ||
(VD && DSAStack->isForceVarCapturing()))
return VD ? VD : Info.second;
- auto DVarPrivate = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
+ DSAStackTy::DSAVarData DVarPrivate =
+ DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
- DVarPrivate = DSAStack->hasDSA(
- D, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; },
- DSAStack->isClauseParsingMode());
+ DVarPrivate = DSAStack->hasDSA(D, isOpenMPPrivate,
+ [](OpenMPDirectiveKind) { return true; },
+ DSAStack->isClauseParsingMode());
if (DVarPrivate.CKind != OMPC_unknown)
return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
}
@@ -1374,11 +1471,10 @@ void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
FunctionScopesIndex -= Regions.size();
}
-bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
+bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
return DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; },
- Level) ||
+ D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) ||
(DSAStack->isClauseParsingMode() &&
DSAStack->getClauseParsingMode() == OMPC_private) ||
// Consider taskgroup reduction descriptor variable a private to avoid
@@ -1389,7 +1485,8 @@ bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
DSAStack->isTaskgroupReductionRef(D, Level));
}
-void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
+void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
+ unsigned Level) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
OpenMPClauseKind OMPC = OMPC_unknown;
@@ -1414,7 +1511,11 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
}
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
NewLevel)) {
- OMPC = OMPC_firstprivate;
+ OMPC = OMPC_map;
+ if (D->getType()->isScalarType() &&
+ DSAStack->getDefaultDMAAtLevel(NewLevel) !=
+ DefaultMapAttributes::DMA_tofrom_scalar)
+ OMPC = OMPC_firstprivate;
break;
}
}
@@ -1422,11 +1523,12 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, OMPC));
}
-bool Sema::isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level) {
+bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D,
+ unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
// Return true if the current level is no longer enclosed in a target region.
- auto *VD = dyn_cast<VarDecl>(D);
+ const auto *VD = dyn_cast<VarDecl>(D);
return VD && !VD->hasLocalStorage() &&
DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
Level);
@@ -1456,28 +1558,29 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// clause requires an accessible, unambiguous default constructor for the
// class type, unless the list item is also specified in a firstprivate
// clause.
- if (auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
- for (auto *C : D->clauses()) {
+ if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
+ for (OMPClause *C : D->clauses()) {
if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
SmallVector<Expr *, 8> PrivateCopies;
- for (auto *DE : Clause->varlists()) {
+ for (Expr *DE : Clause->varlists()) {
if (DE->isValueDependent() || DE->isTypeDependent()) {
PrivateCopies.push_back(nullptr);
continue;
}
auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
- VarDecl *VD = cast<VarDecl>(DRE->getDecl());
+ auto *VD = cast<VarDecl>(DRE->getDecl());
QualType Type = VD->getType().getNonReferenceType();
- auto DVar = DSAStack->getTopDSA(VD, false);
+ const DSAStackTy::DSAVarData DVar =
+ DSAStack->getTopDSA(VD, /*FromParent=*/false);
if (DVar.CKind == OMPC_lastprivate) {
// Generate helper private variable and initialize it with the
// default value. The address of the original variable is replaced
// by the address of the new private variable in CodeGen. This new
// variable is not added to IdResolver, so the code in the OpenMP
// region uses original variable for proper diagnostics.
- auto *VDPrivate = buildVarDecl(
+ VarDecl *VDPrivate = buildVarDecl(
*this, DE->getExprLoc(), Type.getUnqualifiedType(),
- VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
@@ -1507,7 +1610,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
namespace {
-class VarDeclFilterCCC : public CorrectionCandidateCallback {
+class VarDeclFilterCCC final : public CorrectionCandidateCallback {
private:
Sema &SemaRef;
@@ -1515,7 +1618,7 @@ public:
explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
- if (auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
+ if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
return VD->hasGlobalStorage() &&
SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
SemaRef.getCurScope());
@@ -1524,7 +1627,7 @@ public:
}
};
-class VarOrFuncDeclFilterCCC : public CorrectionCandidateCallback {
+class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
private:
Sema &SemaRef;
@@ -1568,12 +1671,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
<< Id.getName();
return ExprError();
}
- } else {
- if (!(VD = Lookup.getAsSingle<VarDecl>())) {
- Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
- Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
- return ExprError();
- }
+ } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
+ Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
+ return ExprError();
}
Lookup.suppressDiagnostics();
@@ -1591,7 +1692,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
}
VarDecl *CanonicalVD = VD->getCanonicalDecl();
- NamedDecl *ND = cast<NamedDecl>(CanonicalVD);
+ NamedDecl *ND = CanonicalVD;
// OpenMP [2.9.2, Restrictions, C/C++, p.2]
// A threadprivate directive for file-scope variables must appear outside
// any definition or declaration.
@@ -1679,12 +1780,13 @@ Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
}
namespace {
-class LocalVarRefChecker : public ConstStmtVisitor<LocalVarRefChecker, bool> {
+class LocalVarRefChecker final
+ : public ConstStmtVisitor<LocalVarRefChecker, bool> {
Sema &SemaRef;
public:
bool VisitDeclRefExpr(const DeclRefExpr *E) {
- if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
if (VD->hasLocalStorage()) {
SemaRef.Diag(E->getLocStart(),
diag::err_omp_local_var_in_threadprivate_init)
@@ -1697,7 +1799,7 @@ public:
return false;
}
bool VisitStmt(const Stmt *S) {
- for (auto Child : S->children()) {
+ for (const Stmt *Child : S->children()) {
if (Child && Visit(Child))
return true;
}
@@ -1710,9 +1812,9 @@ public:
OMPThreadPrivateDecl *
Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
- DeclRefExpr *DE = cast<DeclRefExpr>(RefExpr);
- VarDecl *VD = cast<VarDecl>(DE->getDecl());
+ for (Expr *RefExpr : VarList) {
+ auto *DE = cast<DeclRefExpr>(RefExpr);
+ auto *VD = cast<VarDecl>(DE->getDecl());
SourceLocation ILoc = DE->getExprLoc();
// Mark variable as used.
@@ -1766,7 +1868,7 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
// Check if initial value of threadprivate variable reference variable with
// local storage (it is not supported by runtime).
- if (auto Init = VD->getAnyInitializer()) {
+ if (const Expr *Init = VD->getAnyInitializer()) {
LocalVarRefChecker Checker(*this);
if (Checker.Visit(Init))
continue;
@@ -1776,7 +1878,7 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
DSAStack->addDSA(VD, DE, OMPC_threadprivate);
VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
Context, SourceRange(Loc, Loc)));
- if (auto *ML = Context.getASTMutationListener())
+ if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPThreadPrivate(VD);
}
OMPThreadPrivateDecl *D = nullptr;
@@ -1788,8 +1890,9 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
return D;
}
-static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
- const ValueDecl *D, DSAStackTy::DSAVarData DVar,
+static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
+ const ValueDecl *D,
+ const DSAStackTy::DSAVarData &DVar,
bool IsLoopIterVar = false) {
if (DVar.RefExpr) {
SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
@@ -1845,15 +1948,15 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
}
namespace {
-class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
+class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
DSAStackTy *Stack;
Sema &SemaRef;
- bool ErrorFound;
- CapturedStmt *CS;
- llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
- llvm::SmallVector<Expr *, 8> ImplicitMap;
- llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
- llvm::DenseSet<ValueDecl *> ImplicitDeclarations;
+ bool ErrorFound = false;
+ CapturedStmt *CS = nullptr;
+ llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
+ llvm::SmallVector<Expr *, 4> ImplicitMap;
+ Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
+ llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
@@ -1866,17 +1969,20 @@ public:
if (VD->hasLocalStorage() && !CS->capturesVariable(VD))
return;
- auto DVar = Stack->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
// Check if the variable has explicit DSA set and stop analysis if it so.
if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
return;
// Skip internally declared static variables.
- if (VD->hasGlobalStorage() && !CS->capturesVariable(VD))
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) &&
+ (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link))
return;
- auto ELoc = E->getExprLoc();
- auto DKind = Stack->getCurrentDirective();
+ SourceLocation ELoc = E->getExprLoc();
+ OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
// The default(none) clause requires that each variable that is referenced
// in the construct, and does not have a predetermined data-sharing
// attribute, must have its data-sharing attribute explicitly determined
@@ -1919,7 +2025,7 @@ public:
IsFirstprivate =
IsFirstprivate ||
(VD->getType().getNonReferenceType()->isScalarType() &&
- Stack->getDefaultDMA() != DMA_tofrom_scalar);
+ Stack->getDefaultDMA() != DMA_tofrom_scalar && !Res);
if (IsFirstprivate)
ImplicitFirstprivate.emplace_back(E);
else
@@ -1933,8 +2039,8 @@ public:
// enclosing worksharing or parallel construct may not be accessed in an
// explicit task.
DVar = Stack->hasInnermostDSA(
- VD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
+ VD, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
},
@@ -1942,12 +2048,12 @@ public:
if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
ErrorFound = true;
SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
- ReportOriginalDSA(SemaRef, Stack, VD, DVar);
+ reportOriginalDsa(SemaRef, Stack, VD, DVar);
return;
}
// Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(VD, false);
+ DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
!Stack->isLoopControlVariable(VD).first)
ImplicitFirstprivate.push_back(E);
@@ -1962,7 +2068,7 @@ public:
if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
if (!FD)
return;
- auto DVar = Stack->getTopDSA(FD, false);
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
// Check if the variable has explicit DSA set and stop analysis if it
// so.
if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
@@ -1990,14 +2096,14 @@ public:
return;
}
- auto ELoc = E->getExprLoc();
+ SourceLocation 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 {
+ FD, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
},
@@ -2005,12 +2111,12 @@ public:
if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
ErrorFound = true;
SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
- ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+ reportOriginalDsa(SemaRef, Stack, FD, DVar);
return;
}
// Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(FD, false);
+ DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
!Stack->isLoopControlVariable(FD).first)
ImplicitFirstprivate.push_back(E);
@@ -2018,10 +2124,10 @@ public:
}
if (isOpenMPTargetExecutionDirective(DKind)) {
OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
- if (!CheckMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
+ if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
/*NoDiagnose=*/true))
return;
- auto *VD = cast<ValueDecl>(
+ const auto *VD = cast<ValueDecl>(
CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
if (!Stack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
@@ -2041,8 +2147,8 @@ public:
CCI->getAssociatedExpression())))
return false;
- Decl *CCD = CCI->getAssociatedDeclaration();
- Decl *SCD = SC.getAssociatedDeclaration();
+ const Decl *CCD = CCI->getAssociatedDeclaration();
+ const Decl *SCD = SC.getAssociatedDeclaration();
CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
if (SCD != CCD)
@@ -2055,18 +2161,19 @@ public:
})) {
Visit(E->getBase());
}
- } else
+ } else {
Visit(E->getBase());
+ }
}
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
- for (auto *C : S->clauses()) {
+ for (OMPClause *C : S->clauses()) {
// Skip analysis of arguments of implicitly defined firstprivate clause
// 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()) {
+ for (Stmt *CC : C->children()) {
if (CC)
Visit(CC);
}
@@ -2074,18 +2181,18 @@ public:
}
}
void VisitStmt(Stmt *S) {
- for (auto *C : S->children()) {
+ for (Stmt *C : S->children()) {
if (C && !isa<OMPExecutableDirective>(C))
Visit(C);
}
}
- bool isErrorFound() { return ErrorFound; }
+ bool isErrorFound() const { return ErrorFound; }
ArrayRef<Expr *> getImplicitFirstprivate() const {
return ImplicitFirstprivate;
}
ArrayRef<Expr *> getImplicitMap() const { return ImplicitMap; }
- llvm::DenseMap<ValueDecl *, Expr *> &getVarsWithInheritedDSA() {
+ const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
return VarsWithInheritedDSA;
}
@@ -2103,7 +2210,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_teams:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
@@ -2121,15 +2228,37 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
+ 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.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
+ 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));
Sema::CapturedParamNameType ParamsTarget[] = {
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,
ParamsTarget);
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy =
- Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -2141,6 +2270,37 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
ParamsTeamsOrParallel);
break;
}
+ case OMPD_target:
+ case OMPD_target_simd: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
+ 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.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
+ 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));
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ std::make_pair(StringRef(), QualType()));
+ break;
+ }
case OMPD_simd:
case OMPD_for:
case OMPD_for_simd:
@@ -2154,9 +2314,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_distribute_simd:
case OMPD_ordered:
case OMPD_atomic:
- case OMPD_target_data:
- case OMPD_target:
- case OMPD_target_simd: {
+ case OMPD_target_data: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -2165,17 +2323,21 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_task: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
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(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -2185,35 +2347,40 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
// function directly.
getCurCapturedRegion()->TheCapturedDecl->addAttr(
AlwaysInlineAttr::CreateImplicit(
- Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ Context, AlwaysInlineAttr::Keyword_forceinline));
break;
}
case OMPD_taskloop:
case OMPD_taskloop_simd: {
QualType KmpInt32Ty =
- Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
+ .withConst();
QualType KmpUInt64Ty =
- Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
+ Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
+ .withConst();
QualType KmpInt64Ty =
- Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
- QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
+ .withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
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().withRestrict()),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
std::make_pair(
".copy_fn.",
Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
std::make_pair(".lb.", KmpUInt64Ty),
- std::make_pair(".ub.", KmpUInt64Ty), std::make_pair(".st.", KmpInt64Ty),
+ std::make_pair(".ub.", KmpUInt64Ty),
+ std::make_pair(".st.", KmpInt64Ty),
std::make_pair(".liter.", KmpInt32Ty),
- std::make_pair(".reductions.",
- Context.VoidPtrTy.withConst().withRestrict()),
+ std::make_pair(".reductions.", VoidPtrTy),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
@@ -2222,30 +2389,86 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
// function directly.
getCurCapturedRegion()->TheCapturedDecl->addAttr(
AlwaysInlineAttr::CreateImplicit(
- Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ Context, AlwaysInlineAttr::Keyword_forceinline));
break;
}
case OMPD_distribute_parallel_for_simd:
- case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
+ std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+
+ QualType Args[] = {VoidPtrTy};
+ 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.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
+ 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));
+ Sema::CapturedParamNameType ParamsTarget[] = {
+ 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,
+ ParamsTarget);
+
+ Sema::CapturedParamNameType ParamsTeams[] = {
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 'target' with no implicit parameters.
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
- Params);
+ ParamsTeams);
+
+ Sema::CapturedParamNameType ParamsParallel[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
+ std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
+ 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_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -2261,8 +2484,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
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(".previous.lb.", Context.getSizeType().withConst()),
+ std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
// Start a captured region for 'teams' or 'parallel'. Both regions have
@@ -2274,17 +2497,21 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
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()};
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
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(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -2294,7 +2521,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
// function directly.
getCurCapturedRegion()->TheCapturedDecl->addAttr(
AlwaysInlineAttr::CreateImplicit(
- Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ Context, AlwaysInlineAttr::Keyword_forceinline));
break;
}
case OMPD_threadprivate:
@@ -2343,7 +2570,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty,
CaptureExpr->getLocStart());
if (!WithInit)
- CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
+ CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
S.CurContext->addHiddenDecl(CED);
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
return CED;
@@ -2352,12 +2579,11 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
bool WithInit) {
OMPCapturedExprDecl *CD;
- if (auto *VD = S.IsOpenMPCapturedDecl(D)) {
+ if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
CD = cast<OMPCapturedExprDecl>(VD);
- } else {
+ else
CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
/*AsExpression=*/false);
- }
return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
CaptureExpr->getExprLoc());
}
@@ -2395,7 +2621,7 @@ class CaptureRegionUnwinderRAII {
private:
Sema &S;
bool &ErrorFound;
- OpenMPDirectiveKind DKind;
+ OpenMPDirectiveKind DKind = OMPD_unknown;
public:
CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
@@ -2425,16 +2651,16 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
OMPOrderedClause *OC = nullptr;
OMPScheduleClause *SC = nullptr;
- SmallVector<OMPLinearClause *, 4> LCs;
- SmallVector<OMPClauseWithPreInit *, 8> PICs;
+ SmallVector<const OMPLinearClause *, 4> LCs;
+ SmallVector<const OMPClauseWithPreInit *, 4> PICs;
// This is required for proper codegen.
- for (auto *Clause : Clauses) {
+ for (OMPClause *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())
+ for (Expr *E : IRC->taskgroup_descriptors())
if (E)
MarkDeclarationsReferencedInExpr(E);
}
@@ -2445,7 +2671,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
Clause->getClauseKind() == OMPC_copyin)) {
DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
// Mark all variables in private list clauses as used in inner region.
- for (auto *VarRef : Clause->children()) {
+ for (Stmt *VarRef : Clause->children()) {
if (auto *E = cast_or_null<Expr>(VarRef)) {
MarkDeclarationsReferencedInExpr(E);
}
@@ -2456,7 +2682,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
if (auto *C = OMPClauseWithPreInit::get(Clause))
PICs.push_back(C);
if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
- if (auto *E = C->getPostUpdateExpr())
+ if (Expr *E = C->getPostUpdateExpr())
MarkDeclarationsReferencedInExpr(E);
}
}
@@ -2483,7 +2709,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
ErrorFound = true;
}
if (!LCs.empty() && OC && OC->getNumForLoops()) {
- for (auto *C : LCs) {
+ for (const OMPLinearClause *C : LCs) {
Diag(C->getLocStart(), diag::err_omp_linear_ordered)
<< SourceRange(OC->getLocStart(), OC->getLocEnd());
}
@@ -2505,7 +2731,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
// Required for proper codegen of combined directives.
// TODO: add processing for other clauses.
if (ThisCaptureRegion != OMPD_unknown) {
- for (auto *C : PICs) {
+ for (const clang::OMPClauseWithPreInit *C : PICs) {
OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
// Find the particular capture region for the clause if the
// directive is a combined one with multiple capture regions.
@@ -2515,7 +2741,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
if (CaptureRegion == ThisCaptureRegion ||
CaptureRegion == OMPD_unknown) {
if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
- for (auto *D : DS->decls())
+ for (Decl *D : DS->decls())
MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
}
}
@@ -2542,14 +2768,14 @@ static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
return true;
}
-static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
+static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
OpenMPDirectiveKind CurrentRegion,
const DeclarationNameInfo &CurrentName,
OpenMPDirectiveKind CancelRegion,
SourceLocation StartLoc) {
if (Stack->getCurScope()) {
- auto ParentRegion = Stack->getParentDirective();
- auto OffendingRegion = ParentRegion;
+ OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
+ OpenMPDirectiveKind OffendingRegion = ParentRegion;
bool NestingProhibited = false;
bool CloseNesting = true;
bool OrphanSeen = false;
@@ -2642,12 +2868,12 @@ static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
bool DeadLock = Stack->hasDirective(
[CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
const DeclarationNameInfo &DNI,
- SourceLocation Loc) -> bool {
+ SourceLocation Loc) {
if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
PreviousCriticalLoc = Loc;
return true;
- } else
- return false;
+ }
+ return false;
},
false /* skip top directive */);
if (DeadLock) {
@@ -2732,12 +2958,12 @@ static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// target region, the behavior is unspecified.
NestingProhibited = Stack->hasDirective(
[&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
- SourceLocation) -> bool {
+ SourceLocation) {
if (isOpenMPTargetExecutionDirective(K)) {
OffendingRegion = K;
return true;
- } else
- return false;
+ }
+ return false;
},
false /* don't skip top directive */);
CloseNesting = false;
@@ -2765,7 +2991,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers(
OMPD_unknown + 1);
SmallVector<SourceLocation, 4> NameModifierLoc;
- for (const auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
// At most one if clause without a directive-name-modifier can appear on
// the directive.
@@ -2831,7 +3057,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
diag::err_omp_unnamed_if_clause)
<< (TotalAllowedNum > 1) << Values;
}
- for (auto Loc : NameModifierLoc) {
+ for (SourceLocation Loc : NameModifierLoc) {
S.Diag(Loc, diag::note_omp_previous_named_if_clause);
}
ErrorFound = true;
@@ -2851,7 +3077,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
return StmtError();
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
- llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
+ VarsWithInheritedDSAType VarsWithInheritedDSA;
bool ErrorFound = false;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (AStmt && !CurContext->isDependentContext()) {
@@ -2875,9 +3101,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
SmallVector<Expr *, 4> ImplicitMaps(DSAChecker.getImplicitMap().begin(),
DSAChecker.getImplicitMap().end());
// Mark taskgroup task_reduction descriptors as implicitly firstprivate.
- for (auto *C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
- for (auto *E : IRC->taskgroup_descriptors())
+ for (Expr *E : IRC->taskgroup_descriptors())
if (E)
ImplicitFirstprivates.emplace_back(E);
}
@@ -2889,8 +3115,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ClausesWithImplicit.push_back(Implicit);
ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
ImplicitFirstprivates.size();
- } else
+ } else {
ErrorFound = true;
+ }
}
if (!ImplicitMaps.empty()) {
if (OMPClause *Implicit = ActOnOpenMPMapClause(
@@ -2900,8 +3127,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ClausesWithImplicit.emplace_back(Implicit);
ErrorFound |=
cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size();
- } else
+ } else {
ErrorFound = true;
+ }
}
}
@@ -3153,7 +3381,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
llvm_unreachable("Unknown OpenMP directive");
}
- for (auto P : VarsWithInheritedDSA) {
+ for (const auto &P : VarsWithInheritedDSA) {
Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
<< P.first << P.second->getSourceRange();
}
@@ -3183,7 +3411,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd);
return DG;
}
- auto *ADecl = DG.get().getSingleDecl();
+ Decl *ADecl = DG.get().getSingleDecl();
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
ADecl = FTD->getTemplatedDecl();
@@ -3205,16 +3433,16 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// The uniform clause declares one or more arguments to have an invariant
// value for all concurrent invocations of the function in the execution of a
// single SIMD loop.
- llvm::DenseMap<Decl *, Expr *> UniformedArgs;
- Expr *UniformedLinearThis = nullptr;
- for (auto *E : Uniforms) {
+ llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
+ const Expr *UniformedLinearThis = nullptr;
+ for (const Expr *E : Uniforms) {
E = E->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == PVD->getCanonicalDecl()) {
- UniformedArgs.insert(std::make_pair(PVD->getCanonicalDecl(), E));
+ UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
continue;
}
if (isa<CXXThisExpr>(E)) {
@@ -3232,13 +3460,13 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// function in any of the linear, aligned, or uniform clauses.
// The type of list items appearing in the aligned clause must be array,
// pointer, reference to array, or reference to pointer.
- llvm::DenseMap<Decl *, Expr *> AlignedArgs;
- Expr *AlignedThis = nullptr;
- for (auto *E : Aligneds) {
+ llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
+ const Expr *AlignedThis = nullptr;
+ for (const Expr *E : Aligneds) {
E = E->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- auto *CanonPVD = PVD->getCanonicalDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == CanonPVD) {
@@ -3283,8 +3511,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// positive integer expression. If no optional parameter is specified,
// implementation-defined default alignments for SIMD instructions on the
// target platforms are assumed.
- SmallVector<Expr *, 4> NewAligns;
- for (auto *E : Alignments) {
+ SmallVector<const Expr *, 4> NewAligns;
+ for (Expr *E : Alignments) {
ExprResult Align;
if (E)
Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
@@ -3299,16 +3527,16 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// When a linear-step expression is specified in a linear clause it must be
// either a constant integer expression or an integer-typed parameter that is
// specified in a uniform clause on the directive.
- llvm::DenseMap<Decl *, Expr *> LinearArgs;
+ llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
const bool IsUniformedThis = UniformedLinearThis != nullptr;
auto MI = LinModifiers.begin();
- for (auto *E : Linears) {
+ for (const Expr *E : Linears) {
auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
++MI;
E = E->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- auto *CanonPVD = PVD->getCanonicalDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == CanonPVD) {
@@ -3368,25 +3596,25 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
Expr *Step = nullptr;
Expr *NewStep = nullptr;
SmallVector<Expr *, 4> NewSteps;
- for (auto *E : Steps) {
+ for (Expr *E : Steps) {
// Skip the same step expression, it was checked already.
if (Step == E || !E) {
NewSteps.push_back(E ? NewStep : nullptr);
continue;
}
Step = E;
- if (auto *DRE = dyn_cast<DeclRefExpr>(Step))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- auto *CanonPVD = PVD->getCanonicalDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (UniformedArgs.count(CanonPVD) == 0) {
Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
<< Step->getSourceRange();
} else if (E->isValueDependent() || E->isTypeDependent() ||
E->isInstantiationDependent() ||
E->containsUnexpandedParameterPack() ||
- CanonPVD->getType()->hasIntegerRepresentation())
+ CanonPVD->getType()->hasIntegerRepresentation()) {
NewSteps.push_back(Step);
- else {
+ } else {
Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
<< Step->getSourceRange();
}
@@ -3421,7 +3649,7 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -3429,108 +3657,117 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
}
namespace {
-/// \brief Helper class for checking canonical form of the OpenMP loops and
+/// Helper class for checking canonical form of the OpenMP loops and
/// extracting iteration space of each loop in the loop nest, that will be used
/// for IR generation.
class OpenMPIterationSpaceChecker {
- /// \brief Reference to Sema.
+ /// Reference to Sema.
Sema &SemaRef;
- /// \brief A location for diagnostics (when there is no some better location).
+ /// A location for diagnostics (when there is no some better location).
SourceLocation DefaultLoc;
- /// \brief A location for diagnostics (when increment is not compatible).
+ /// A location for diagnostics (when increment is not compatible).
SourceLocation ConditionLoc;
- /// \brief A source location for referring to loop init later.
+ /// A source location for referring to loop init later.
SourceRange InitSrcRange;
- /// \brief A source location for referring to condition later.
+ /// A source location for referring to condition later.
SourceRange ConditionSrcRange;
- /// \brief A source location for referring to increment later.
+ /// A source location for referring to increment later.
SourceRange IncrementSrcRange;
- /// \brief Loop variable.
+ /// Loop variable.
ValueDecl *LCDecl = nullptr;
- /// \brief Reference to loop variable.
+ /// Reference to loop variable.
Expr *LCRef = nullptr;
- /// \brief Lower bound (initializer for the var).
+ /// Lower bound (initializer for the var).
Expr *LB = nullptr;
- /// \brief Upper bound.
+ /// Upper bound.
Expr *UB = nullptr;
- /// \brief Loop step (increment).
+ /// Loop step (increment).
Expr *Step = nullptr;
- /// \brief This flag is true when condition is one of:
+ /// This flag is true when condition is one of:
/// Var < UB
/// Var <= UB
/// UB > Var
/// UB >= Var
bool TestIsLessOp = false;
- /// \brief This flag is true when condition is strict ( < or > ).
+ /// This flag is true when condition is strict ( < or > ).
bool TestIsStrictOp = false;
- /// \brief This flag is true when step is subtracted on each iteration.
+ /// This flag is true when step is subtracted on each iteration.
bool SubtractStep = false;
public:
OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc)
: SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
- /// \brief Check init-expr for canonical loop form and save loop counter
+ /// Check init-expr for canonical loop form and save loop counter
/// variable - #Var and its initialization value - #LB.
- bool CheckInit(Stmt *S, bool EmitDiags = true);
- /// \brief Check test-expr for canonical form, save upper-bound (#UB), flags
+ bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
+ /// Check test-expr for canonical form, save upper-bound (#UB), flags
/// for less/greater and for strict/non-strict comparison.
- bool CheckCond(Expr *S);
- /// \brief Check incr-expr for canonical loop form and return true if it
+ bool checkAndSetCond(Expr *S);
+ /// Check incr-expr for canonical loop form and return true if it
/// does not conform, otherwise save loop step (#Step).
- bool CheckInc(Expr *S);
- /// \brief Return the loop counter variable.
- ValueDecl *GetLoopDecl() const { return LCDecl; }
- /// \brief Return the reference expression to loop counter variable.
- Expr *GetLoopDeclRefExpr() const { return LCRef; }
- /// \brief Source range of the loop init.
- SourceRange GetInitSrcRange() const { return InitSrcRange; }
- /// \brief Source range of the loop condition.
- SourceRange GetConditionSrcRange() const { return ConditionSrcRange; }
- /// \brief Source range of the loop increment.
- SourceRange GetIncrementSrcRange() const { return IncrementSrcRange; }
- /// \brief True if the step should be subtracted.
- bool ShouldSubtractStep() const { return SubtractStep; }
- /// \brief Build the expression to calculate the number of iterations.
+ bool checkAndSetInc(Expr *S);
+ /// Return the loop counter variable.
+ ValueDecl *getLoopDecl() const { return LCDecl; }
+ /// Return the reference expression to loop counter variable.
+ Expr *getLoopDeclRefExpr() const { return LCRef; }
+ /// Source range of the loop init.
+ SourceRange getInitSrcRange() const { return InitSrcRange; }
+ /// Source range of the loop condition.
+ SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
+ /// Source range of the loop increment.
+ SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
+ /// True if the step should be subtracted.
+ bool shouldSubtractStep() const { return SubtractStep; }
+ /// Build the expression to calculate the number of iterations.
+ Expr *buildNumIterations(
+ Scope *S, const bool LimitedType,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
+ /// Build the precondition expression for the loops.
Expr *
- BuildNumIterations(Scope *S, const bool LimitedType,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const;
- /// \brief Build the precondition expression for the loops.
- Expr *BuildPreCond(Scope *S, Expr *Cond,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const;
- /// \brief Build reference expression to the counter be used for codegen.
- DeclRefExpr *BuildCounterVar(llvm::MapVector<Expr *, DeclRefExpr *> &Captures,
- DSAStackTy &DSA) const;
- /// \brief Build reference expression to the private counter be used for
+ buildPreCond(Scope *S, Expr *Cond,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
+ /// Build reference expression to the counter be used for codegen.
+ DeclRefExpr *
+ buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
+ DSAStackTy &DSA) const;
+ /// Build reference expression to the private counter be used for
/// codegen.
- Expr *BuildPrivateCounterVar() const;
- /// \brief Build initialization of the counter be used for codegen.
- Expr *BuildCounterInit() const;
- /// \brief Build step of the counter be used for codegen.
- Expr *BuildCounterStep() const;
- /// \brief Return true if any expression is dependent.
- bool Dependent() const;
+ Expr *buildPrivateCounterVar() const;
+ /// Build initialization of the counter be used for codegen.
+ Expr *buildCounterInit() const;
+ /// Build step of the counter be used for codegen.
+ Expr *buildCounterStep() const;
+ /// Build loop data with counter value for depend clauses in ordered
+ /// directives.
+ Expr *
+ buildOrderedLoopData(Scope *S, Expr *Counter,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
+ SourceLocation Loc, Expr *Inc = nullptr,
+ OverloadedOperatorKind OOK = OO_Amp);
+ /// Return true if any expression is dependent.
+ bool dependent() const;
private:
- /// \brief Check the right-hand side of an assignment in the increment
+ /// Check the right-hand side of an assignment in the increment
/// expression.
- bool CheckIncRHS(Expr *RHS);
- /// \brief Helper to set loop counter variable and its initializer.
- bool SetLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB);
- /// \brief Helper to set upper bound.
- bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
+ bool checkAndSetIncRHS(Expr *RHS);
+ /// Helper to set loop counter variable and its initializer.
+ bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB);
+ /// Helper to set upper bound.
+ bool setUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
SourceLocation SL);
- /// \brief Helper to set loop increment.
- bool SetStep(Expr *NewStep, bool Subtract);
+ /// Helper to set loop increment.
+ bool setStep(Expr *NewStep, bool Subtract);
};
-bool OpenMPIterationSpaceChecker::Dependent() const {
+bool OpenMPIterationSpaceChecker::dependent() const {
if (!LCDecl) {
assert(!LB && !UB && !Step);
return false;
@@ -3540,7 +3777,7 @@ bool OpenMPIterationSpaceChecker::Dependent() const {
(Step && Step->isValueDependent());
}
-bool OpenMPIterationSpaceChecker::SetLCDeclAndLB(ValueDecl *NewLCDecl,
+bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
Expr *NewLCRefExpr,
Expr *NewLB) {
// State consistency checking to ensure correct usage.
@@ -3560,7 +3797,7 @@ bool OpenMPIterationSpaceChecker::SetLCDeclAndLB(ValueDecl *NewLCDecl,
return false;
}
-bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
+bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, bool LessOp, bool StrictOp,
SourceRange SR, SourceLocation SL) {
// State consistency checking to ensure correct usage.
assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
@@ -3575,7 +3812,7 @@ bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
return false;
}
-bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
+bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
// State consistency checking to ensure correct usage.
assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
if (!NewStep)
@@ -3632,7 +3869,7 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
return false;
}
-bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
+bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
// Check init-expr for canonical loop form and save loop counter
// variable - #Var and its initialization value - #LB.
// OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
@@ -3656,17 +3893,17 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
S = E->IgnoreParens();
if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->getOpcode() == BO_Assign) {
- auto *LHS = BO->getLHS()->IgnoreParens();
+ Expr *LHS = BO->getLHS()->IgnoreParens();
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
- return SetLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS());
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS());
}
if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
}
}
} else if (auto *DS = dyn_cast<DeclStmt>(S)) {
@@ -3678,28 +3915,33 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
SemaRef.Diag(S->getLocStart(),
diag::ext_omp_loop_not_canonical_init)
<< S->getSourceRange();
- return SetLCDeclAndLB(Var, nullptr, Var->getInit());
+ return setLCDeclAndLB(
+ Var,
+ buildDeclRefExpr(SemaRef, Var,
+ Var->getType().getNonReferenceType(),
+ DS->getLocStart()),
+ Var->getInit());
}
}
}
} else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
if (CE->getOperator() == OO_Equal) {
- auto *LHS = CE->getArg(0);
+ Expr *LHS = CE->getArg(0);
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
- return SetLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1));
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1));
}
if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
}
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
if (EmitDiags) {
SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
@@ -3708,29 +3950,29 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
return true;
}
-/// \brief Ignore parenthesizes, implicit casts, copy constructor and return the
+/// Ignore parenthesizes, implicit casts, copy constructor and return the
/// variable (which may be the loop variable) if possible.
-static const ValueDecl *GetInitLCDecl(Expr *E) {
+static const ValueDecl *getInitLCDecl(const Expr *E) {
if (!E)
return nullptr;
E = getExprAsWritten(E);
- if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
+ if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
if (const CXXConstructorDecl *Ctor = CE->getConstructor())
if ((Ctor->isCopyOrMoveConstructor() ||
Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
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 (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
return getCanonicalDecl(VD);
}
- if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
+ if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
return getCanonicalDecl(ME->getMemberDecl());
return nullptr;
}
-bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
+bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
// Check test-expr for canonical form, save upper-bound UB, flags for
// less/greater and for strict/non-strict comparison.
// OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
@@ -3745,13 +3987,13 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
SourceLocation CondLoc = S->getLocStart();
if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->isRelationalOp()) {
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return SetUB(BO->getRHS(),
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return setUB(BO->getRHS(),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_LE),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
BO->getSourceRange(), BO->getOperatorLoc());
- if (GetInitLCDecl(BO->getRHS()) == LCDecl)
- return SetUB(BO->getLHS(),
+ if (getInitLCDecl(BO->getRHS()) == LCDecl)
+ return setUB(BO->getLHS(),
(BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
BO->getSourceRange(), BO->getOperatorLoc());
@@ -3764,12 +4006,12 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
case OO_GreaterEqual:
case OO_Less:
case OO_LessEqual:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
CE->getOperatorLoc());
- if (GetInitLCDecl(CE->getArg(1)) == LCDecl)
- return SetUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
+ if (getInitLCDecl(CE->getArg(1)) == LCDecl)
+ return setUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
CE->getOperatorLoc());
break;
@@ -3778,14 +4020,14 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
}
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
<< S->getSourceRange() << LCDecl;
return true;
}
-bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
+bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
// RHS of canonical loop form increment can be:
// var + incr
// incr + var
@@ -3795,28 +4037,28 @@ bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
if (BO->isAdditiveOp()) {
bool IsAdd = BO->getOpcode() == BO_Add;
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return SetStep(BO->getRHS(), !IsAdd);
- if (IsAdd && GetInitLCDecl(BO->getRHS()) == LCDecl)
- return SetStep(BO->getLHS(), false);
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return setStep(BO->getRHS(), !IsAdd);
+ if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
+ return setStep(BO->getLHS(), /*Subtract=*/false);
}
} else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
bool IsAdd = CE->getOperator() == OO_Plus;
if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(CE->getArg(1), !IsAdd);
- if (IsAdd && GetInitLCDecl(CE->getArg(1)) == LCDecl)
- return SetStep(CE->getArg(0), false);
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setStep(CE->getArg(1), !IsAdd);
+ if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
+ return setStep(CE->getArg(0), /*Subtract=*/false);
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr)
<< RHS->getSourceRange() << LCDecl;
return true;
}
-bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
+bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
// Check incr-expr for canonical loop form and return true if it
// does not conform.
// OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
@@ -3842,22 +4084,22 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
S = S->IgnoreParens();
if (auto *UO = dyn_cast<UnaryOperator>(S)) {
if (UO->isIncrementDecrementOp() &&
- GetInitLCDecl(UO->getSubExpr()) == LCDecl)
- return SetStep(SemaRef
+ getInitLCDecl(UO->getSubExpr()) == LCDecl)
+ return setStep(SemaRef
.ActOnIntegerConstant(UO->getLocStart(),
(UO->isDecrementOp() ? -1 : 1))
.get(),
- false);
+ /*Subtract=*/false);
} else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
switch (BO->getOpcode()) {
case BO_AddAssign:
case BO_SubAssign:
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return SetStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
break;
case BO_Assign:
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return CheckIncRHS(BO->getRHS());
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return checkAndSetIncRHS(BO->getRHS());
break;
default:
break;
@@ -3866,28 +4108,28 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
switch (CE->getOperator()) {
case OO_PlusPlus:
case OO_MinusMinus:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(SemaRef
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setStep(SemaRef
.ActOnIntegerConstant(
CE->getLocStart(),
((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
.get(),
- false);
+ /*Subtract=*/false);
break;
case OO_PlusEqual:
case OO_MinusEqual:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
break;
case OO_Equal:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return CheckIncRHS(CE->getArg(1));
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return checkAndSetIncRHS(CE->getArg(1));
break;
default:
break;
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr)
<< S->getSourceRange() << LCDecl;
@@ -3896,7 +4138,7 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
static ExprResult
tryBuildCapture(Sema &SemaRef, Expr *Capture,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
if (SemaRef.CurContext->isDependentContext())
return ExprResult(Capture);
if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
@@ -3912,17 +4154,17 @@ tryBuildCapture(Sema &SemaRef, Expr *Capture,
return Res;
}
-/// \brief Build the expression to calculate the number of iterations.
-Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
+/// Build the expression to calculate the number of iterations.
+Expr *OpenMPIterationSpaceChecker::buildNumIterations(
Scope *S, const bool LimitedType,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
ExprResult Diff;
- auto VarType = LCDecl->getType().getNonReferenceType();
+ QualType VarType = LCDecl->getType().getNonReferenceType();
if (VarType->isIntegerType() || VarType->isPointerType() ||
SemaRef.getLangOpts().CPlusPlus) {
// Upper - Lower
- auto *UBExpr = TestIsLessOp ? UB : LB;
- auto *LBExpr = TestIsLessOp ? LB : UB;
+ Expr *UBExpr = TestIsLessOp ? UB : LB;
+ Expr *LBExpr = TestIsLessOp ? LB : UB;
Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
if (!Upper || !Lower)
@@ -3951,7 +4193,7 @@ Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
return nullptr;
// Upper - Lower [- 1] + Step
- auto NewStep = tryBuildCapture(SemaRef, Step, Captures);
+ ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
if (!NewStep.isUsable())
return nullptr;
Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
@@ -3970,7 +4212,7 @@ Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
// OpenMP runtime requires 32-bit or 64-bit loop variables.
QualType Type = Diff.get()->getType();
- auto &C = SemaRef.Context;
+ ASTContext &C = SemaRef.Context;
bool UseVarType = VarType->hasIntegerRepresentation() &&
C.getTypeSize(Type) > C.getTypeSize(VarType);
if (!Type->isIntegerType() || UseVarType) {
@@ -4009,22 +4251,23 @@ Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
return Diff.get();
}
-Expr *OpenMPIterationSpaceChecker::BuildPreCond(
+Expr *OpenMPIterationSpaceChecker::buildPreCond(
Scope *S, Expr *Cond,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
// Try to build LB <op> UB, where <op> is <, >, <=, or >=.
bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics();
SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
- auto NewLB = tryBuildCapture(SemaRef, LB, Captures);
- auto NewUB = tryBuildCapture(SemaRef, UB, Captures);
+ ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
+ ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
if (!NewLB.isUsable() || !NewUB.isUsable())
return nullptr;
- auto CondExpr = SemaRef.BuildBinOp(
- S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
- : (TestIsStrictOp ? BO_GT : BO_GE),
- NewLB.get(), NewUB.get());
+ ExprResult CondExpr =
+ SemaRef.BuildBinOp(S, DefaultLoc,
+ TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
+ : (TestIsStrictOp ? BO_GT : BO_GE),
+ NewLB.get(), NewUB.get());
if (CondExpr.isUsable()) {
if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
SemaRef.Context.BoolTy))
@@ -4037,15 +4280,17 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(
return CondExpr.isUsable() ? CondExpr.get() : Cond;
}
-/// \brief Build reference expression to the counter be used for codegen.
-DeclRefExpr *OpenMPIterationSpaceChecker::BuildCounterVar(
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const {
+/// Build reference expression to the counter be used for codegen.
+DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
+ DSAStackTy &DSA) const {
auto *VD = dyn_cast<VarDecl>(LCDecl);
if (!VD) {
- VD = SemaRef.IsOpenMPCapturedDecl(LCDecl);
- auto *Ref = buildDeclRefExpr(
+ VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
+ DeclRefExpr *Ref = buildDeclRefExpr(
SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
- DSAStackTy::DSAVarData Data = DSA.getTopDSA(LCDecl, /*FromParent=*/false);
+ const DSAStackTy::DSAVarData Data =
+ DSA.getTopDSA(LCDecl, /*FromParent=*/false);
// If the loop control decl is explicitly marked as private, do not mark it
// as captured again.
if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
@@ -4056,12 +4301,15 @@ DeclRefExpr *OpenMPIterationSpaceChecker::BuildCounterVar(
DefaultLoc);
}
-Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
+Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
if (LCDecl && !LCDecl->isInvalidDecl()) {
- auto Type = LCDecl->getType().getNonReferenceType();
- auto *PrivateVar =
- buildVarDecl(SemaRef, DefaultLoc, Type, LCDecl->getName(),
- LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr);
+ QualType Type = LCDecl->getType().getNonReferenceType();
+ VarDecl *PrivateVar = buildVarDecl(
+ SemaRef, DefaultLoc, Type, LCDecl->getName(),
+ LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
+ isa<VarDecl>(LCDecl)
+ ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
+ : nullptr);
if (PrivateVar->isInvalidDecl())
return nullptr;
return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
@@ -4069,35 +4317,92 @@ Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
return nullptr;
}
-/// \brief Build initialization of the counter to be used for codegen.
-Expr *OpenMPIterationSpaceChecker::BuildCounterInit() const { return LB; }
+/// Build initialization of the counter to be used for codegen.
+Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
+
+/// Build step of the counter be used for codegen.
+Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
+
+Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
+ Scope *S, Expr *Counter,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
+ Expr *Inc, OverloadedOperatorKind OOK) {
+ Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
+ if (!Cnt)
+ return nullptr;
+ if (Inc) {
+ assert((OOK == OO_Plus || OOK == OO_Minus) &&
+ "Expected only + or - operations for depend clauses.");
+ BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
+ Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
+ if (!Cnt)
+ return nullptr;
+ }
+ ExprResult Diff;
+ QualType VarType = LCDecl->getType().getNonReferenceType();
+ if (VarType->isIntegerType() || VarType->isPointerType() ||
+ SemaRef.getLangOpts().CPlusPlus) {
+ // Upper - Lower
+ Expr *Upper =
+ TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get();
+ Expr *Lower =
+ TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
+ if (!Upper || !Lower)
+ return nullptr;
+
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
+
+ if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) {
+ // BuildBinOp already emitted error, this one is to point user to upper
+ // and lower bound, and to tell what is passed to 'operator-'.
+ SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx)
+ << Upper->getSourceRange() << Lower->getSourceRange();
+ return nullptr;
+ }
+ }
-/// \brief Build step of the counter be used for codegen.
-Expr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; }
+ if (!Diff.isUsable())
+ return nullptr;
-/// \brief Iteration space of a single for loop.
+ // Parentheses (for dumping/debugging purposes only).
+ Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
+ if (!NewStep.isUsable())
+ return nullptr;
+ // (Upper - Lower) / Step
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ return Diff.get();
+}
+
+/// Iteration space of a single for loop.
struct LoopIterationSpace final {
- /// \brief Condition of the loop.
+ /// Condition of the loop.
Expr *PreCond = nullptr;
- /// \brief This expression calculates the number of iterations in the loop.
+ /// This expression calculates the number of iterations in the loop.
/// It is always possible to calculate it before starting the loop.
Expr *NumIterations = nullptr;
- /// \brief The loop counter variable.
+ /// The loop counter variable.
Expr *CounterVar = nullptr;
- /// \brief Private loop counter variable.
+ /// Private loop counter variable.
Expr *PrivateCounterVar = nullptr;
- /// \brief This is initializer for the initial value of #CounterVar.
+ /// This is initializer for the initial value of #CounterVar.
Expr *CounterInit = nullptr;
- /// \brief This is step for the #CounterVar used to generate its update:
+ /// This is step for the #CounterVar used to generate its update:
/// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
Expr *CounterStep = nullptr;
- /// \brief Should step be subtracted?
+ /// Should step be subtracted?
bool Subtract = false;
- /// \brief Source range of the loop init.
+ /// Source range of the loop init.
SourceRange InitSrcRange;
- /// \brief Source range of the loop condition.
+ /// Source range of the loop condition.
SourceRange CondSrcRange;
- /// \brief Source range of the loop increment.
+ /// Source range of the loop increment.
SourceRange IncSrcRange;
};
@@ -4110,15 +4415,15 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
OpenMPIterationSpaceChecker ISC(*this, ForLoc);
- if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) {
- if (auto *D = ISC.GetLoopDecl()) {
+ if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
+ if (ValueDecl *D = ISC.getLoopDecl()) {
auto *VD = dyn_cast<VarDecl>(D);
if (!VD) {
- if (auto *Private = IsOpenMPCapturedDecl(D))
+ if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
VD = Private;
- else {
- auto *Ref = buildCapture(*this, D, ISC.GetLoopDeclRefExpr(),
- /*WithInit=*/false);
+ } else {
+ DeclRefExpr *Ref = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
+ /*WithInit=*/false);
VD = cast<VarDecl>(Ref->getDecl());
}
}
@@ -4129,24 +4434,25 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
}
}
-/// \brief Called on a for stmt to check and extract its iteration space
+/// Called on a for stmt to check and extract its iteration space
/// for further processing (such as collapsing).
-static bool CheckOpenMPIterationSpace(
+static bool checkOpenMPIterationSpace(
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
- Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA,
+ unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
+ Expr *OrderedLoopCountExpr,
+ Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
LoopIterationSpace &ResultIterSpace,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
// OpenMP [2.6, Canonical Loop Form]
// for (init-expr; test-expr; incr-expr) structured-block
auto *For = dyn_cast_or_null<ForStmt>(S);
if (!For) {
SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
<< (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
- << getOpenMPDirectiveName(DKind) << NestedLoopCount
+ << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
<< (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
- if (NestedLoopCount > 1) {
+ if (TotalNestedLoopCount > 1) {
if (CollapseLoopCountExpr && OrderedLoopCountExpr)
SemaRef.Diag(DSA.getConstructLoc(),
diag::note_omp_collapse_ordered_expr)
@@ -4168,22 +4474,22 @@ static bool CheckOpenMPIterationSpace(
OpenMPIterationSpaceChecker ISC(SemaRef, For->getForLoc());
// Check init.
- auto Init = For->getInit();
- if (ISC.CheckInit(Init))
+ Stmt *Init = For->getInit();
+ if (ISC.checkAndSetInit(Init))
return true;
bool HasErrors = false;
// Check loop variable's type.
- if (auto *LCDecl = ISC.GetLoopDecl()) {
- auto *LoopDeclRefExpr = ISC.GetLoopDeclRefExpr();
+ if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
+ Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
// OpenMP [2.6, Canonical Loop Form]
// Var is one of the following:
// A variable of signed or unsigned integer type.
// For C++, a variable of a random access iterator type.
// For C, a variable of a pointer type.
- auto VarType = LCDecl->getType().getNonReferenceType();
+ QualType VarType = LCDecl->getType().getNonReferenceType();
if (!VarType->isDependentType() && !VarType->isIntegerType() &&
!VarType->isPointerType() &&
!(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
@@ -4214,7 +4520,7 @@ static bool CheckOpenMPIterationSpace(
DSAStackTy::DSAVarData DVar = DSA.getTopDSA(LCDecl, false);
// If LoopVarRefExpr is nullptr it means the corresponding loop variable is
// declared in the loop and it is predetermined as a private.
- auto PredeterminedCKind =
+ OpenMPClauseKind PredeterminedCKind =
isOpenMPSimdDirective(DKind)
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
: OMPC_private;
@@ -4230,7 +4536,7 @@ static bool CheckOpenMPIterationSpace(
<< getOpenMPClauseName(PredeterminedCKind);
if (DVar.RefExpr == nullptr)
DVar.CKind = PredeterminedCKind;
- ReportOriginalDSA(SemaRef, &DSA, LCDecl, DVar, /*IsLoopIterVar=*/true);
+ reportOriginalDsa(SemaRef, &DSA, LCDecl, DVar, /*IsLoopIterVar=*/true);
HasErrors = true;
} else if (LoopDeclRefExpr != nullptr) {
// Make the loop iteration variable private (for worksharing constructs),
@@ -4247,31 +4553,31 @@ static bool CheckOpenMPIterationSpace(
assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
// Check test-expr.
- HasErrors |= ISC.CheckCond(For->getCond());
+ HasErrors |= ISC.checkAndSetCond(For->getCond());
// Check incr-expr.
- HasErrors |= ISC.CheckInc(For->getInc());
+ HasErrors |= ISC.checkAndSetInc(For->getInc());
}
- if (ISC.Dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
+ if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
return HasErrors;
// Build the loop's iteration space representation.
ResultIterSpace.PreCond =
- ISC.BuildPreCond(DSA.getCurScope(), For->getCond(), Captures);
- ResultIterSpace.NumIterations = ISC.BuildNumIterations(
+ ISC.buildPreCond(DSA.getCurScope(), For->getCond(), Captures);
+ ResultIterSpace.NumIterations = ISC.buildNumIterations(
DSA.getCurScope(),
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)),
Captures);
- ResultIterSpace.CounterVar = ISC.BuildCounterVar(Captures, DSA);
- ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar();
- ResultIterSpace.CounterInit = ISC.BuildCounterInit();
- ResultIterSpace.CounterStep = ISC.BuildCounterStep();
- ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange();
- ResultIterSpace.CondSrcRange = ISC.GetConditionSrcRange();
- ResultIterSpace.IncSrcRange = ISC.GetIncrementSrcRange();
- ResultIterSpace.Subtract = ISC.ShouldSubtractStep();
+ ResultIterSpace.CounterVar = ISC.buildCounterVar(Captures, DSA);
+ ResultIterSpace.PrivateCounterVar = ISC.buildPrivateCounterVar();
+ ResultIterSpace.CounterInit = ISC.buildCounterInit();
+ ResultIterSpace.CounterStep = ISC.buildCounterStep();
+ ResultIterSpace.InitSrcRange = ISC.getInitSrcRange();
+ ResultIterSpace.CondSrcRange = ISC.getConditionSrcRange();
+ ResultIterSpace.IncSrcRange = ISC.getIncrementSrcRange();
+ ResultIterSpace.Subtract = ISC.shouldSubtractStep();
HasErrors |= (ResultIterSpace.PreCond == nullptr ||
ResultIterSpace.NumIterations == nullptr ||
@@ -4279,17 +4585,52 @@ static bool CheckOpenMPIterationSpace(
ResultIterSpace.PrivateCounterVar == nullptr ||
ResultIterSpace.CounterInit == nullptr ||
ResultIterSpace.CounterStep == nullptr);
+ if (!HasErrors && DSA.isOrderedRegion()) {
+ if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
+ if (CurrentNestedLoopCount <
+ DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
+ DSA.getOrderedRegionParam().second->setLoopNumIterations(
+ CurrentNestedLoopCount, ResultIterSpace.NumIterations);
+ DSA.getOrderedRegionParam().second->setLoopCounter(
+ CurrentNestedLoopCount, ResultIterSpace.CounterVar);
+ }
+ }
+ for (auto &Pair : DSA.getDoacrossDependClauses()) {
+ if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
+ // Erroneous case - clause has some problems.
+ continue;
+ }
+ if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
+ Pair.second.size() <= CurrentNestedLoopCount) {
+ // Erroneous case - clause has some problems.
+ Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
+ continue;
+ }
+ Expr *CntValue;
+ if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
+ CntValue = ISC.buildOrderedLoopData(
+ DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
+ Pair.first->getDependencyLoc());
+ else
+ CntValue = ISC.buildOrderedLoopData(
+ DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
+ Pair.first->getDependencyLoc(),
+ Pair.second[CurrentNestedLoopCount].first,
+ Pair.second[CurrentNestedLoopCount].second);
+ Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
+ }
+ }
return HasErrors;
}
-/// \brief Build 'VarRef = Start.
+/// Build 'VarRef = Start.
static ExprResult
-BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
+buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
ExprResult Start,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
// Build 'VarRef = Start.
- auto NewStart = tryBuildCapture(SemaRef, Start.get(), Captures);
+ ExprResult NewStart = tryBuildCapture(SemaRef, Start.get(), Captures);
if (!NewStart.isUsable())
return ExprError();
if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
@@ -4301,17 +4642,16 @@ BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
return ExprError();
}
- auto Init =
+ ExprResult Init =
SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
return Init;
}
-/// \brief Build 'VarRef = Start + Iter * Step'.
-static ExprResult
-BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc,
- ExprResult VarRef, ExprResult Start, ExprResult Iter,
- ExprResult Step, bool Subtract,
- llvm::MapVector<Expr *, DeclRefExpr *> *Captures = nullptr) {
+/// Build 'VarRef = Start + Iter * Step'.
+static ExprResult buildCounterUpdate(
+ Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
+ ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
+ llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
// Add parentheses (for debugging purposes only).
Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
@@ -4378,12 +4718,12 @@ BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc,
return Update;
}
-/// \brief Convert integer expression \a E to make it have at least \a Bits
+/// Convert integer expression \a E to make it have at least \a Bits
/// bits.
-static ExprResult WidenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
+static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
if (E == nullptr)
return ExprError();
- auto &C = SemaRef.Context;
+ ASTContext &C = SemaRef.Context;
QualType OldType = E->getType();
unsigned HasBits = C.getTypeSize(OldType);
if (HasBits >= Bits)
@@ -4394,9 +4734,9 @@ static ExprResult WidenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
true);
}
-/// \brief Check if the given expression \a E is a constant integer that fits
+/// Check if the given expression \a E is a constant integer that fits
/// into \a Bits bits.
-static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {
+static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
if (E == nullptr)
return false;
llvm::APSInt Result;
@@ -4419,10 +4759,10 @@ static Stmt *buildPreInits(ASTContext &Context,
/// Build preinits statement for the given declarations.
static Stmt *
buildPreInits(ASTContext &Context,
- const llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
if (!Captures.empty()) {
SmallVector<Decl *, 16> PreInits;
- for (auto &Pair : Captures)
+ for (const auto &Pair : Captures)
PreInits.push_back(Pair.second->getDecl());
return buildPreInits(Context, PreInits);
}
@@ -4433,7 +4773,7 @@ buildPreInits(ASTContext &Context,
static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
Expr *PostUpdate = nullptr;
if (!PostUpdates.empty()) {
- for (auto *E : PostUpdates) {
+ for (Expr *E : PostUpdates) {
Expr *ConvE = S.BuildCStyleCastExpr(
E->getExprLoc(),
S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
@@ -4449,14 +4789,14 @@ static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
return PostUpdate;
}
-/// \brief Called on a for stmt to check itself and nested loops (if any).
+/// Called on a for stmt to check itself and nested loops (if any).
/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
/// number of collapsed loops otherwise.
static unsigned
-CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
+checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
DSAStackTy &DSA,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA,
+ Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
OMPLoopDirective::HelperExprs &Built) {
unsigned NestedLoopCount = 1;
if (CollapseLoopCountExpr) {
@@ -4465,6 +4805,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
NestedLoopCount = Result.getLimitedValue();
}
+ unsigned OrderedLoopCount = 1;
if (OrderedLoopCountExpr) {
// Found 'ordered' clause - calculate collapse number.
llvm::APSInt Result;
@@ -4477,20 +4818,21 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
diag::note_collapse_loop_count)
<< CollapseLoopCountExpr->getSourceRange();
}
- NestedLoopCount = Result.getLimitedValue();
+ OrderedLoopCount = Result.getLimitedValue();
}
}
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
SmallVector<LoopIterationSpace, 4> IterSpaces;
- IterSpaces.resize(NestedLoopCount);
+ IterSpaces.resize(std::max(OrderedLoopCount, NestedLoopCount));
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
- if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
- NestedLoopCount, CollapseLoopCountExpr,
- OrderedLoopCountExpr, VarsWithImplicitDSA,
- IterSpaces[Cnt], Captures))
+ if (checkOpenMPIterationSpace(
+ DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
+ std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
+ OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
+ Captures))
return 0;
// Move on to the next nested for loop, or to the loop body.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -4499,6 +4841,27 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// any two loops.
CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
}
+ for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) {
+ if (checkOpenMPIterationSpace(
+ DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
+ std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
+ OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
+ Captures))
+ return 0;
+ if (Cnt > 0 && IterSpaces[Cnt].CounterVar) {
+ // Handle initialization of captured loop iterator variables.
+ auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
+ if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
+ Captures[DRE] = DRE;
+ }
+ }
+ // Move on to the next nested for loop, or to the loop body.
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // All loops associated with the construct must be perfectly nested; that
+ // is, there must be no intervening code nor any OpenMP directive between
+ // any two loops.
+ CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
+ }
Built.clear(/* size */ NestedLoopCount);
@@ -4537,26 +4900,28 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Precondition tests if there is at least one iteration (all conditions are
// true).
auto PreCond = ExprResult(IterSpaces[0].PreCond);
- auto N0 = IterSpaces[0].NumIterations;
- ExprResult LastIteration32 = WidenIterationCount(
- 32 /* Bits */, SemaRef
- .PerformImplicitConversion(
- N0->IgnoreImpCasts(), N0->getType(),
- Sema::AA_Converting, /*AllowExplicit=*/true)
- .get(),
- SemaRef);
- ExprResult LastIteration64 = WidenIterationCount(
- 64 /* Bits */, SemaRef
- .PerformImplicitConversion(
- N0->IgnoreImpCasts(), N0->getType(),
- Sema::AA_Converting, /*AllowExplicit=*/true)
- .get(),
+ Expr *N0 = IterSpaces[0].NumIterations;
+ ExprResult LastIteration32 =
+ widenIterationCount(/*Bits=*/32,
+ SemaRef
+ .PerformImplicitConversion(
+ N0->IgnoreImpCasts(), N0->getType(),
+ Sema::AA_Converting, /*AllowExplicit=*/true)
+ .get(),
+ SemaRef);
+ ExprResult LastIteration64 = widenIterationCount(
+ /*Bits=*/64,
+ SemaRef
+ .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
+ Sema::AA_Converting,
+ /*AllowExplicit=*/true)
+ .get(),
SemaRef);
if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
return NestedLoopCount;
- auto &C = SemaRef.Context;
+ ASTContext &C = SemaRef.Context;
bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
Scope *CurScope = DSA.getCurScope();
@@ -4566,7 +4931,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
PreCond.get(), IterSpaces[Cnt].PreCond);
}
- auto N = IterSpaces[Cnt].NumIterations;
+ Expr *N = IterSpaces[Cnt].NumIterations;
SourceLocation Loc = N->getExprLoc();
AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
if (LastIteration32.isUsable())
@@ -4592,8 +4957,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
if (LastIteration32.isUsable() &&
C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
(AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
- FitsInto(
- 32 /* Bits */,
+ fitsInto(
+ /*Bits=*/32,
LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
LastIteration64.get(), SemaRef)))
LastIteration = LastIteration32;
@@ -4681,7 +5046,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
UB.get(), LastIteration.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
- InitLoc, InitLoc, IsUBGreater.get(), LastIteration.get(), UB.get());
+ LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
+ LastIteration.get(), UB.get());
EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
CondOp.get());
EUB = SemaRef.ActOnFinishFullExpr(EUB.get());
@@ -4691,7 +5057,6 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// enclosing region. E.g. in 'distribute parallel for' the bounds obtained
// by scheduling 'distribute' have to be passed to the schedule of 'for'.
if (isOpenMPLoopBoundSharingDirective(DKind)) {
-
// Lower bound variable, initialized with zero.
VarDecl *CombLBDecl =
buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
@@ -4716,7 +5081,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
CombCondOp.get());
CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get());
- auto *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
+ const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
// We expect to have at least 2 more parameters than the 'parallel'
// directive does - the lower and upper bounds of the previous schedule.
assert(CD->getNumParams() >= 4 &&
@@ -4724,8 +5089,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Set the proper type for the bounds given what we learned from the
// enclosed loops.
- auto *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
- auto *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
+ ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
+ ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
// Previous lower and upper bounds are obtained from the region
// parameters.
@@ -4764,7 +5129,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
// Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
- SourceLocation CondLoc;
+ SourceLocation CondLoc = AStmt->getLocStart();
ExprResult Cond =
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
@@ -4777,7 +5142,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get());
}
// Loop increment (IV = IV + 1)
- SourceLocation IncLoc;
+ SourceLocation IncLoc = AStmt->getLocStart();
ExprResult Inc =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
@@ -4844,7 +5209,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// directive with for as IV = IV + ST; ensure upper bound expression based
// on PrevUB instead of NumIterations - used to implement 'for' when found
// in combination with 'distribute', like in 'distribute parallel for'
- SourceLocation DistIncLoc;
+ SourceLocation DistIncLoc = AStmt->getLocStart();
ExprResult DistCond, DistInc, PrevEUB;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
DistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get());
@@ -4860,7 +5225,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Build expression: UB = min(UB, prevUB) for #for in composite or combined
// construct
- SourceLocation DistEUBLoc;
+ SourceLocation DistEUBLoc = AStmt->getLocStart();
ExprResult IsUBGreater =
SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
@@ -4876,7 +5241,6 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.Inits.resize(NestedLoopCount);
Built.Updates.resize(NestedLoopCount);
Built.Finals.resize(NestedLoopCount);
- SmallVector<Expr *, 4> LoopMultipliers;
{
ExprResult Div;
// Go from inner nested loop to outer.
@@ -4905,16 +5269,16 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
- auto *CounterVar = buildDeclRefExpr(SemaRef, VD, IS.CounterVar->getType(),
- IS.CounterVar->getExprLoc(),
- /*RefersToCapture=*/true);
- ExprResult Init = BuildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
+ DeclRefExpr *CounterVar = buildDeclRefExpr(
+ SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
+ /*RefersToCapture=*/true);
+ ExprResult Init = buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
IS.CounterInit, Captures);
if (!Init.isUsable()) {
HasErrors = true;
break;
}
- ExprResult Update = BuildCounterUpdate(
+ ExprResult Update = buildCounterUpdate(
SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
IS.CounterStep, IS.Subtract, &Captures);
if (!Update.isUsable()) {
@@ -4923,7 +5287,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
// Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
- ExprResult Final = BuildCounterUpdate(
+ ExprResult Final = buildCounterUpdate(
SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
IS.NumIterations, IS.CounterStep, IS.Subtract, &Captures);
if (!Final.isUsable()) {
@@ -4946,7 +5310,6 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
HasErrors = true;
break;
}
- LoopMultipliers.push_back(Div.get());
}
if (!Update.isUsable() || !Final.isUsable()) {
HasErrors = true;
@@ -4994,55 +5357,6 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.DistCombinedFields.NLB = CombNextLB.get();
Built.DistCombinedFields.NUB = CombNextUB.get();
- Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get();
- // Fill data for doacross depend clauses.
- for (auto Pair : DSA.getDoacrossDependClauses()) {
- if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
- Pair.first->setCounterValue(CounterVal);
- else {
- if (NestedLoopCount != Pair.second.size() ||
- NestedLoopCount != LoopMultipliers.size() + 1) {
- // Erroneous case - clause has some problems.
- Pair.first->setCounterValue(CounterVal);
- continue;
- }
- assert(Pair.first->getDependencyKind() == OMPC_DEPEND_sink);
- auto I = Pair.second.rbegin();
- auto IS = IterSpaces.rbegin();
- auto ILM = LoopMultipliers.rbegin();
- Expr *UpCounterVal = CounterVal;
- Expr *Multiplier = nullptr;
- for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) {
- if (I->first) {
- assert(IS->CounterStep);
- Expr *NormalizedOffset =
- SemaRef
- .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Div,
- I->first, IS->CounterStep)
- .get();
- if (Multiplier) {
- NormalizedOffset =
- SemaRef
- .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Mul,
- NormalizedOffset, Multiplier)
- .get();
- }
- assert(I->second == OO_Plus || I->second == OO_Minus);
- BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub;
- UpCounterVal = SemaRef
- .BuildBinOp(CurScope, I->first->getExprLoc(), BOK,
- UpCounterVal, NormalizedOffset)
- .get();
- }
- Multiplier = *ILM;
- ++I;
- ++IS;
- ++ILM;
- }
- Pair.first->setCounterValue(UpCounterVal);
- }
- }
-
return NestedLoopCount;
}
@@ -5064,10 +5378,10 @@ static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
static bool checkSimdlenSafelenSpecified(Sema &S,
const ArrayRef<OMPClause *> Clauses) {
- OMPSafelenClause *Safelen = nullptr;
- OMPSimdlenClause *Simdlen = nullptr;
+ const OMPSafelenClause *Safelen = nullptr;
+ const OMPSimdlenClause *Simdlen = nullptr;
- for (auto *Clause : Clauses) {
+ for (const OMPClause *Clause : Clauses) {
if (Clause->getClauseKind() == OMPC_safelen)
Safelen = cast<OMPSafelenClause>(Clause);
else if (Clause->getClauseKind() == OMPC_simdlen)
@@ -5078,8 +5392,8 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
if (Simdlen && Safelen) {
llvm::APSInt SimdlenRes, SafelenRes;
- auto SimdlenLength = Simdlen->getSimdlen();
- auto SafelenLength = Safelen->getSafelen();
+ const Expr *SimdlenLength = Simdlen->getSimdlen();
+ const Expr *SafelenLength = Safelen->getSafelen();
if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
SimdlenLength->isInstantiationDependent() ||
SimdlenLength->containsUnexpandedParameterPack())
@@ -5104,10 +5418,10 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
return false;
}
-StmtResult Sema::ActOnOpenMPSimdDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+StmtResult
+Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -5115,7 +5429,7 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5126,7 +5440,7 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5138,15 +5452,15 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
}
-StmtResult Sema::ActOnOpenMPForDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+StmtResult
+Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -5154,7 +5468,7 @@ StmtResult Sema::ActOnOpenMPForDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5165,7 +5479,7 @@ StmtResult Sema::ActOnOpenMPForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5174,15 +5488,14 @@ StmtResult Sema::ActOnOpenMPForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B, DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -5191,7 +5504,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5202,7 +5515,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5214,7 +5527,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
}
@@ -5251,7 +5564,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5265,7 +5578,7 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
@@ -5281,13 +5594,13 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
// OpenMP [2.7.3, single Construct, Restrictions]
// The copyprivate clause must not be used with the nowait clause.
- OMPClause *Nowait = nullptr;
- OMPClause *Copyprivate = nullptr;
- for (auto *Clause : Clauses) {
+ const OMPClause *Nowait = nullptr;
+ const OMPClause *Copyprivate = nullptr;
+ for (const OMPClause *Clause : Clauses) {
if (Clause->getClauseKind() == OMPC_nowait)
Nowait = Clause;
else if (Clause->getClauseKind() == OMPC_copyprivate)
@@ -5311,7 +5624,7 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
@@ -5328,7 +5641,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
llvm::APSInt Hint;
SourceLocation HintLoc;
bool DependentHint = false;
- for (auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_hint) {
if (!DirName.getName()) {
Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name);
@@ -5336,9 +5649,9 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
}
Expr *E = cast<OMPHintClause>(C)->getHint();
if (E->isTypeDependent() || E->isValueDependent() ||
- E->isInstantiationDependent())
+ E->isInstantiationDependent()) {
DependentHint = true;
- else {
+ } else {
Hint = E->EvaluateKnownConstInt(Context);
HintLoc = C->getLocStart();
}
@@ -5346,26 +5659,27 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
}
if (ErrorFound)
return StmtError();
- auto Pair = DSAStack->getCriticalWithHint(DirName);
+ const auto Pair = DSAStack->getCriticalWithHint(DirName);
if (Pair.first && DirName.getName() && !DependentHint) {
if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
Diag(StartLoc, diag::err_omp_critical_with_hint);
- if (HintLoc.isValid()) {
+ if (HintLoc.isValid())
Diag(HintLoc, diag::note_omp_critical_hint_here)
<< 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false);
- } else
+ else
Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
- if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
+ if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
Diag(C->getLocStart(), diag::note_omp_critical_hint_here)
<< 1
<< C->getHint()->EvaluateKnownConstInt(Context).toString(
/*Radix=*/10, /*Signed=*/false);
- } else
+ } else {
Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1;
+ }
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
Clauses, AStmt);
@@ -5376,12 +5690,11 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -5393,7 +5706,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5404,7 +5717,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5413,7 +5726,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -5421,12 +5734,11 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -5438,7 +5750,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5446,7 +5758,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5458,7 +5770,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -5496,7 +5808,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelSectionsDirective::Create(
Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
@@ -5516,7 +5828,7 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5546,7 +5858,7 @@ StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt,
@@ -5564,13 +5876,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- OMPClause *DependFound = nullptr;
- OMPClause *DependSourceClause = nullptr;
- OMPClause *DependSinkClause = nullptr;
+ const OMPClause *DependFound = nullptr;
+ const OMPClause *DependSourceClause = nullptr;
+ const OMPClause *DependSinkClause = nullptr;
bool ErrorFound = false;
- OMPThreadsClause *TC = nullptr;
- OMPSIMDClause *SC = nullptr;
- for (auto *C : Clauses) {
+ const OMPThreadsClause *TC = nullptr;
+ const OMPSIMDClause *SC = nullptr;
+ for (const OMPClause *C : Clauses) {
if (auto *DC = dyn_cast<OMPDependClause>(C)) {
DependFound = C;
if (DC->getDependencyKind() == OMPC_DEPEND_source) {
@@ -5579,8 +5891,9 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
<< getOpenMPDirectiveName(OMPD_ordered)
<< getOpenMPClauseName(OMPC_depend) << 2;
ErrorFound = true;
- } else
+ } else {
DependSourceClause = C;
+ }
if (DependSinkClause) {
Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
<< 0;
@@ -5594,10 +5907,11 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
}
DependSinkClause = C;
}
- } else if (C->getClauseKind() == OMPC_threads)
+ } else if (C->getClauseKind() == OMPC_threads) {
TC = cast<OMPThreadsClause>(C);
- else if (C->getClauseKind() == OMPC_simd)
+ } else if (C->getClauseKind() == OMPC_simd) {
SC = cast<OMPSIMDClause>(C);
+ }
}
if (!ErrorFound && !SC &&
isOpenMPSimdDirective(DSAStack->getParentDirective())) {
@@ -5610,12 +5924,12 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd)
<< getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
ErrorFound = true;
- } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) {
+ } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
Diag(DependFound->getLocStart(),
diag::err_omp_ordered_directive_without_param);
ErrorFound = true;
} else if (TC || Clauses.empty()) {
- if (auto *Param = DSAStack->getParentOrderedRegionParam()) {
+ if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
<< (TC != nullptr);
@@ -5629,57 +5943,57 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
if (AStmt) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
}
return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
namespace {
-/// \brief Helper class for checking expression in 'omp atomic [update]'
+/// Helper class for checking expression in 'omp atomic [update]'
/// construct.
class OpenMPAtomicUpdateChecker {
- /// \brief Error results for atomic update expressions.
+ /// Error results for atomic update expressions.
enum ExprAnalysisErrorCode {
- /// \brief A statement is not an expression statement.
+ /// A statement is not an expression statement.
NotAnExpression,
- /// \brief Expression is not builtin binary or unary operation.
+ /// Expression is not builtin binary or unary operation.
NotABinaryOrUnaryExpression,
- /// \brief Unary operation is not post-/pre- increment/decrement operation.
+ /// Unary operation is not post-/pre- increment/decrement operation.
NotAnUnaryIncDecExpression,
- /// \brief An expression is not of scalar type.
+ /// An expression is not of scalar type.
NotAScalarType,
- /// \brief A binary operation is not an assignment operation.
+ /// A binary operation is not an assignment operation.
NotAnAssignmentOp,
- /// \brief RHS part of the binary operation is not a binary expression.
+ /// RHS part of the binary operation is not a binary expression.
NotABinaryExpression,
- /// \brief RHS part is not additive/multiplicative/shift/biwise binary
+ /// RHS part is not additive/multiplicative/shift/biwise binary
/// expression.
NotABinaryOperator,
- /// \brief RHS binary operation does not have reference to the updated LHS
+ /// RHS binary operation does not have reference to the updated LHS
/// part.
NotAnUpdateExpression,
- /// \brief No errors is found.
+ /// No errors is found.
NoError
};
- /// \brief Reference to Sema.
+ /// Reference to Sema.
Sema &SemaRef;
- /// \brief A location for note diagnostics (when error is found).
+ /// A location for note diagnostics (when error is found).
SourceLocation NoteLoc;
- /// \brief 'x' lvalue part of the source atomic expression.
+ /// 'x' lvalue part of the source atomic expression.
Expr *X;
- /// \brief 'expr' rvalue part of the source atomic expression.
+ /// 'expr' rvalue part of the source atomic expression.
Expr *E;
- /// \brief Helper expression of the form
+ /// Helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *UpdateExpr;
- /// \brief Is 'x' a LHS in a RHS part of full update expression. It is
+ /// Is 'x' a LHS in a RHS part of full update expression. It is
/// important for non-associative operations.
bool IsXLHSInRHSPart;
BinaryOperatorKind Op;
SourceLocation OpLoc;
- /// \brief true if the source expression is a postfix unary operation, false
+ /// true if the source expression is a postfix unary operation, false
/// if it is a prefix unary operation.
bool IsPostfixUpdate;
@@ -5687,7 +6001,7 @@ public:
OpenMPAtomicUpdateChecker(Sema &SemaRef)
: SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
- /// \brief Check specified statement that it is suitable for 'atomic update'
+ /// Check specified statement that it is suitable for 'atomic update'
/// constructs and extract 'x', 'expr' and Operation from the original
/// expression. If DiagId and NoteId == 0, then only check is performed
/// without error notification.
@@ -5695,19 +6009,19 @@ public:
/// \param NoteId Diagnostic note for the main error message.
/// \return true if statement is not an update expression, false otherwise.
bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
- /// \brief Return the 'x' lvalue part of the source atomic expression.
+ /// Return the 'x' lvalue part of the source atomic expression.
Expr *getX() const { return X; }
- /// \brief Return the 'expr' rvalue part of the source atomic expression.
+ /// Return the 'expr' rvalue part of the source atomic expression.
Expr *getExpr() const { return E; }
- /// \brief Return the update expression used in calculation of the updated
+ /// Return the update expression used in calculation of the updated
/// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *getUpdateExpr() const { return UpdateExpr; }
- /// \brief Return true if 'x' is LHS in RHS part of full update expression,
+ /// Return true if 'x' is LHS in RHS part of full update expression,
/// false otherwise.
bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
- /// \brief true if the source expression is a postfix unary operation, false
+ /// true if the source expression is a postfix unary operation, false
/// if it is a prefix unary operation.
bool isPostfixUpdate() const { return IsPostfixUpdate; }
@@ -5727,15 +6041,15 @@ bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
// x = expr binop x;
if (AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getLHS();
- if (auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
+ if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
if (AtomicInnerBinOp->isMultiplicativeOp() ||
AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
AtomicInnerBinOp->isBitwiseOp()) {
Op = AtomicInnerBinOp->getOpcode();
OpLoc = AtomicInnerBinOp->getOperatorLoc();
- auto *LHS = AtomicInnerBinOp->getLHS();
- auto *RHS = AtomicInnerBinOp->getRHS();
+ Expr *LHS = AtomicInnerBinOp->getLHS();
+ Expr *RHS = AtomicInnerBinOp->getRHS();
llvm::FoldingSetNodeID XId, LHSId, RHSId;
X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
/*Canonical=*/true);
@@ -5779,7 +6093,8 @@ bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
return true;
- } else if (SemaRef.CurContext->isDependentContext())
+ }
+ if (SemaRef.CurContext->isDependentContext())
E = X = UpdateExpr = nullptr;
return ErrorFound != NoError;
}
@@ -5801,7 +6116,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
AtomicBody = AtomicBody->IgnoreParenImpCasts();
if (AtomicBody->getType()->isScalarType() ||
AtomicBody->isInstantiationDependent()) {
- if (auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
+ if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Compound Assignment Operation
Op = BinaryOperator::getOpForCompoundAssignment(
@@ -5815,7 +6130,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
// Check for Binary Operation
if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
return true;
- } else if (auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
+ } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Unary Operation
if (AtomicUnaryOp->isIncrementDecrementOp()) {
@@ -5851,7 +6166,8 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
return true;
- } else if (SemaRef.CurContext->isDependentContext())
+ }
+ if (SemaRef.CurContext->isDependentContext())
E = X = UpdateExpr = nullptr;
if (ErrorFound == NoError && E && X) {
// Build an update expression of form 'OpaqueValueExpr(x) binop
@@ -5861,7 +6177,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue);
auto *OVEExpr = new (SemaRef.getASTContext())
OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue);
- auto Update =
+ ExprResult Update =
SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
IsXLHSInRHSPart ? OVEExpr : OVEX);
if (Update.isInvalid())
@@ -5890,7 +6206,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
OpenMPClauseKind AtomicKind = OMPC_unknown;
SourceLocation AtomicKindLoc;
- for (auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_read || C->getClauseKind() == OMPC_write ||
C->getClauseKind() == OMPC_update ||
C->getClauseKind() == OMPC_capture) {
@@ -5906,7 +6222,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
}
- auto Body = CS->getCapturedStmt();
+ Stmt *Body = CS->getCapturedStmt();
if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
Body = EWC->getSubExpr();
@@ -5950,8 +6266,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SourceRange ErrorRange, NoteRange;
// If clause is read:
// v = x;
- if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
- auto *AtomicBinOp =
+ if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ const auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
@@ -5959,7 +6275,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
(V->isInstantiationDependent() || V->getType()->isScalarType())) {
if (!X->isLValue() || !V->isLValue()) {
- auto NotLValueExpr = X->isLValue() ? V : X;
+ const Expr *NotLValueExpr = X->isLValue() ? V : X;
ErrorFound = NotAnLValue;
ErrorLoc = AtomicBinOp->getExprLoc();
ErrorRange = AtomicBinOp->getSourceRange();
@@ -5968,7 +6284,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
} else if (!X->isInstantiationDependent() ||
!V->isInstantiationDependent()) {
- auto NotScalarExpr =
+ const Expr *NotScalarExpr =
(X->isInstantiationDependent() || X->getType()->isScalarType())
? V
: X;
@@ -5998,7 +6314,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
<< NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext())
+ }
+ if (CurContext->isDependentContext())
V = X = nullptr;
} else if (AtomicKind == OMPC_write) {
enum {
@@ -6012,8 +6329,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SourceRange ErrorRange, NoteRange;
// If clause is write:
// x = expr;
- if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
- auto *AtomicBinOp =
+ if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ const auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getLHS();
@@ -6029,7 +6346,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
} else if (!X->isInstantiationDependent() ||
!E->isInstantiationDependent()) {
- auto NotScalarExpr =
+ const Expr *NotScalarExpr =
(X->isInstantiationDependent() || X->getType()->isScalarType())
? E
: X;
@@ -6059,7 +6376,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
<< NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext())
+ }
+ if (CurContext->isDependentContext())
E = X = nullptr;
} else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
// If clause is update:
@@ -6093,7 +6411,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
} ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
- if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
// If clause is a capture:
// v = x++;
// v = x--;
@@ -6102,7 +6420,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// v = x binop= expr;
// v = x = x binop expr;
// v = x = expr binop x;
- auto *AtomicBinOp =
+ const auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
V = AtomicBinOp->getLHS();
@@ -6131,9 +6449,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
<< ErrorRange;
Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext()) {
- UE = V = E = X = nullptr;
}
+ if (CurContext->isDependentContext())
+ UE = V = E = X = nullptr;
} else {
// If clause is a capture:
// { v = x; x = expr; }
@@ -6154,8 +6472,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
// Check that this is { expr1; expr2; }
if (CS->size() == 2) {
- auto *First = CS->body_front();
- auto *Second = CS->body_back();
+ Stmt *First = CS->body_front();
+ Stmt *Second = CS->body_back();
if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
First = EWC->getSubExpr()->IgnoreParenImpCasts();
if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
@@ -6177,7 +6495,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// { v = x; x = x binop expr; }
// { v = x; x = expr binop x; }
// Check that the first expression has form v = x.
- auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
llvm::FoldingSetNodeID XId, PossibleXId;
Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
@@ -6207,7 +6525,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// { x = x binop expr; v = x; }
// { x = expr binop x; v = x; }
// Check that the second expression has form v = x.
- auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
llvm::FoldingSetNodeID XId, PossibleXId;
Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
@@ -6248,9 +6566,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SecondBinOp ? SecondBinOp->getSourceRange()
: SourceRange(ErrorLoc, ErrorLoc);
} else {
- auto *PossibleXRHSInFirst =
+ Expr *PossibleXRHSInFirst =
FirstBinOp->getRHS()->IgnoreParenImpCasts();
- auto *PossibleXLHSInSecond =
+ Expr *PossibleXLHSInSecond =
SecondBinOp->getLHS()->IgnoreParenImpCasts();
llvm::FoldingSetNodeID X1Id, X2Id;
PossibleXRHSInFirst->Profile(X1Id, Context,
@@ -6293,13 +6611,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
<< ErrorRange;
Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext()) {
- UE = V = E = X = nullptr;
}
+ if (CurContext->isDependentContext())
+ UE = V = E = X = nullptr;
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
X, V, E, UE, IsXLHSInRHSPart,
@@ -6313,25 +6631,35 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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);
+ 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.16, Nesting of Regions]
// If specified, a teams construct must be contained within a target
// construct. That target construct must contain no statements or directives
// outside of the teams construct.
if (DSAStack->hasInnerTeamsRegion()) {
- auto S = AStmt->IgnoreContainers(/*IgnoreCaptured*/ true);
+ const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
bool OMPTeamsFound = true;
- if (auto *CS = dyn_cast<CompoundStmt>(S)) {
+ if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
auto I = CS->body_begin();
while (I != CS->body_end()) {
- auto *OED = dyn_cast<OMPExecutableDirective>(*I);
+ const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind())) {
OMPTeamsFound = false;
break;
@@ -6341,7 +6669,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
assert(I != CS->body_end() && "Not found statement");
S = *I;
} else {
- auto *OED = dyn_cast<OMPExecutableDirective>(S);
+ const auto *OED = dyn_cast<OMPExecutableDirective>(S);
OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
}
if (!OMPTeamsFound) {
@@ -6354,7 +6682,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
@@ -6366,15 +6694,25 @@ Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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_parallel);
+ 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();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6382,12 +6720,11 @@ Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6409,7 +6746,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
// 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),
+ checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6420,7 +6757,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6429,7 +6766,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt,
B, DSAStack->isCancelRegion());
@@ -6466,7 +6803,7 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6479,7 +6816,7 @@ Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6516,7 +6853,7 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6553,7 +6890,7 @@ StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6585,7 +6922,7 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6593,7 +6930,7 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -6635,9 +6972,9 @@ StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
static bool checkGrainsizeNumTasksClauses(Sema &S,
ArrayRef<OMPClause *> Clauses) {
- OMPClause *PrevClause = nullptr;
+ const OMPClause *PrevClause = nullptr;
bool ErrorFound = false;
- for (auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_grainsize ||
C->getClauseKind() == OMPC_num_tasks) {
if (!PrevClause)
@@ -6659,9 +6996,9 @@ static bool checkGrainsizeNumTasksClauses(Sema &S,
static bool checkReductionClauseWithNogroup(Sema &S,
ArrayRef<OMPClause *> Clauses) {
- OMPClause *ReductionClause = nullptr;
- OMPClause *NogroupClause = nullptr;
- for (auto *C : Clauses) {
+ const OMPClause *ReductionClause = nullptr;
+ const OMPClause *NogroupClause = nullptr;
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_reduction) {
ReductionClause = C;
if (NogroupClause)
@@ -6686,8 +7023,7 @@ static bool checkReductionClauseWithNogroup(Sema &S,
StmtResult Sema::ActOnOpenMPTaskLoopDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -6696,7 +7032,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
/*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6716,15 +7052,14 @@ StmtResult Sema::ActOnOpenMPTaskLoopDirective(
if (checkReductionClauseWithNogroup(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -6733,7 +7068,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
/*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6744,7 +7079,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6766,15 +7101,14 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -6783,7 +7117,7 @@ StmtResult Sema::ActOnOpenMPDistributeDirective(
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, AStmt,
*this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6792,19 +7126,18 @@ StmtResult Sema::ActOnOpenMPDistributeDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6826,7 +7159,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -6836,7 +7169,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeParallelForDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -6844,12 +7177,11 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6871,7 +7203,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -6883,7 +7215,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6895,19 +7227,18 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6929,7 +7260,7 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this,
*DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6940,7 +7271,7 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6952,19 +7283,18 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -6985,7 +7315,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -6997,7 +7327,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7008,19 +7338,18 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7042,7 +7371,7 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
// In presence of clause 'collapse' with number of loops, it will define the
// nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -7053,7 +7382,7 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7065,19 +7394,18 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7099,7 +7427,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this,
*DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -7108,7 +7436,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp teams distribute loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7118,12 +7446,11 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7146,7 +7473,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7159,7 +7486,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7171,7 +7498,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7181,12 +7508,11 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7209,7 +7535,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7222,7 +7548,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7234,7 +7560,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7244,12 +7570,11 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7272,7 +7597,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7283,7 +7608,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7299,7 +7624,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7317,7 +7642,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -7325,12 +7650,11 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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.
@@ -7352,7 +7676,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7362,33 +7686,42 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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_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.
- auto NestedLoopCount = CheckOpenMPLoop(
- OMPD_target_teams_distribute_parallel_for,
- getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ unsigned NestedLoopCount = checkOpenMPLoop(
+ OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -7396,7 +7729,18 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute parallel for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (OMPClause *C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -7404,27 +7748,37 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *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_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_target_teams_distribute_parallel_for_simd,
- getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
- VarsWithImplicitDSA, B);
+ unsigned NestedLoopCount =
+ checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
+ getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, CS, *this,
+ *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -7434,7 +7788,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7446,15 +7800,14 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -7480,7 +7833,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7492,7 +7845,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7504,7 +7857,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -7612,13 +7965,18 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
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_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 'teams' region, otherwise do not capture.
+ if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
+ CaptureRegion = OMPD_teams;
+ break;
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_teams;
@@ -7682,12 +8040,12 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
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_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_teams;
break;
case OMPD_parallel:
@@ -7870,20 +8228,16 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
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:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ 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_parallel;
break;
case OMPD_for:
@@ -7941,18 +8295,14 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
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;
+ CaptureRegion = OMPD_teams;
break;
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.
@@ -8007,19 +8357,19 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_update:
case OMPD_target_enter_data:
case OMPD_target_exit_data:
- CaptureRegion = OMPD_task;
- break;
+ case OMPD_target:
+ case OMPD_target_simd:
case OMPD_target_teams:
+ case OMPD_target_parallel:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
+ 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_task;
+ break;
case OMPD_target_data:
- 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:
@@ -8137,7 +8487,7 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -8209,7 +8559,7 @@ ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
}
-static bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef,
+static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef,
OpenMPClauseKind CKind,
bool StrictlyPositive) {
if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
@@ -8245,7 +8595,7 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
// OpenMP [2.5, Restrictions]
// The num_threads expression must evaluate to a positive integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
/*StrictlyPositive=*/true))
return nullptr;
@@ -8254,7 +8604,7 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -8352,11 +8702,14 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
if (NumForLoopsResult.isInvalid())
return nullptr;
NumForLoops = NumForLoopsResult.get();
- } else
+ } else {
NumForLoops = nullptr;
- DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops);
- return new (Context)
- OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc);
+ }
+ auto *Clause = OMPOrderedClause::Create(
+ Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
+ StartLoc, LParenLoc, EndLoc);
+ DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
+ return Clause;
}
OMPClause *Sema::ActOnOpenMPSimpleClause(
@@ -8431,24 +8784,23 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
static std::string
getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
ArrayRef<unsigned> Exclude = llvm::None) {
- std::string Values;
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
unsigned Bound = Last >= 2 ? Last - 2 : 0;
unsigned Skipped = Exclude.size();
auto S = Exclude.begin(), E = Exclude.end();
- for (unsigned i = First; i < Last; ++i) {
- if (std::find(S, E, i) != E) {
+ for (unsigned I = First; I < Last; ++I) {
+ if (std::find(S, E, I) != E) {
--Skipped;
continue;
}
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(K, i);
- Values += "'";
- if (i == Bound - Skipped)
- Values += " or ";
- else if (i != Bound + 1 - Skipped)
- Values += ", ";
+ Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
+ if (I == Bound - Skipped)
+ Out << " or ";
+ else if (I != Bound + 1 - Skipped)
+ Out << ", ";
}
- return Values;
+ return Out.str();
}
OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
@@ -8682,7 +9034,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
OMPD_unknown &&
!CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -8986,13 +9338,13 @@ getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
} IsArrayExpr = NoArrayExpr;
if (AllowArraySection) {
if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
- auto *Base = ASE->getBase()->IgnoreParenImpCasts();
+ Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Base = TempASE->getBase()->IgnoreParenImpCasts();
RefExpr = Base;
IsArrayExpr = ArraySubscript;
} else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
- auto *Base = OASE->getBase()->IgnoreParenImpCasts();
+ Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Base = TempOASE->getBase()->IgnoreParenImpCasts();
while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
@@ -9010,10 +9362,10 @@ getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
(S.getCurrentThisType().isNull() || !ME ||
!isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
!isa<FieldDecl>(ME->getMemberDecl()))) {
- if (IsArrayExpr != NoArrayExpr)
+ if (IsArrayExpr != NoArrayExpr) {
S.Diag(ELoc, diag::err_omp_expected_base_var_name) << IsArrayExpr
<< ERange;
- else {
+ } else {
S.Diag(ELoc,
AllowArraySection
? diag::err_omp_expected_var_name_member_expr_or_array_item
@@ -9032,7 +9384,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
SmallVector<Expr *, 8> PrivateCopies;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP private clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9064,15 +9416,15 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// listed below. For these exceptions only, listing a predetermined
// variable in a data-sharing attribute clause is allowed and overrides
// the variable's predetermined data-sharing attributes.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_private);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
- auto CurrDir = DSAStack->getCurrentDirective();
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// Variably modified types are not supported for tasks.
if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
isOpenMPTaskingDirective(CurrDir)) {
@@ -9091,14 +9443,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// 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,
@@ -9111,7 +9456,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
<< getOpenMPClauseName(OMPC_private)
<< getOpenMPClauseName(ConflictKind)
<< getOpenMPDirectiveName(CurrDir);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9126,12 +9471,14 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// IdResolver, so the code in the OpenMP region uses original variable for
// proper diagnostics.
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
- auto VDPrivateRefExpr = buildDeclRefExpr(
+ DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
*this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
DeclRefExpr *Ref = nullptr;
@@ -9156,7 +9503,7 @@ class DiagsUninitializedSeveretyRAII {
private:
DiagnosticsEngine &Diags;
SourceLocation SavedLoc;
- bool IsIgnored;
+ bool IsIgnored = false;
public:
DiagsUninitializedSeveretyRAII(DiagnosticsEngine &Diags, SourceLocation Loc,
@@ -9184,9 +9531,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Decl *, 4> ExprCaptures;
bool IsImplicitClause =
StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
- auto ImplicitClauseLoc = DSAStack->getConstructLoc();
+ SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9218,12 +9565,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a private
// clause requires an accessible, unambiguous copy constructor for the
// class type.
- auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
+ QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
// If an implicit firstprivate variable found it was checked already.
DSAStackTy::DSAVarData TopDVar;
if (!IsImplicitClause) {
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar =
+ DSAStack->getTopDSA(D, /*FromParent=*/false);
TopDVar = DVar;
OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
bool IsConstant = ElemType.isConstant(Context);
@@ -9241,7 +9589,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_firstprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -9261,7 +9609,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_firstprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -9292,7 +9640,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_firstprivate)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9309,8 +9657,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// from the worksharing construct.
if (isOpenMPTaskingDirective(CurrDir)) {
DVar = DSAStack->hasInnermostDSA(
- D, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
+ D, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) ||
isOpenMPTeamsDirective(K);
@@ -9322,7 +9670,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
isOpenMPTeamsDirective(DVar.DKind))) {
Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
<< getOpenMPDirectiveName(DVar.DKind);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9334,8 +9682,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
- OpenMPClauseKind WhereFoundClauseKind) -> bool {
+ [&ConflictKind](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind WhereFoundClauseKind) {
ConflictKind = WhereFoundClauseKind;
return true;
})) {
@@ -9343,7 +9692,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
<< getOpenMPClauseName(OMPC_firstprivate)
<< getOpenMPClauseName(ConflictKind)
<< getOpenMPDirectiveName(DSAStack->getCurrentDirective());
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9365,8 +9714,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -9376,13 +9727,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// For arrays generate initializer for single element and replace it by the
// original array element in CodeGen.
if (Type->isArrayType()) {
- auto VDInit =
+ VarDecl *VDInit =
buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
- auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
+ Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
ElemType = ElemType.getUnqualifiedType();
- auto *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
- ".firstprivate.temp");
+ VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
+ ".firstprivate.temp");
InitializedEntity Entity =
InitializedEntity::InitializeVariable(VDInitTemp);
InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
@@ -9396,8 +9747,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// Remove temp variable declaration.
Context.Deallocate(VDInitTemp);
} else {
- auto *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
- ".firstprivate.temp");
+ VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
+ ".firstprivate.temp");
VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
RefExpr->getExprLoc());
AddInitializerToDecl(VDPrivate,
@@ -9412,16 +9763,16 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr = buildDeclRefExpr(
+ DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
*this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
RefExpr->getExprLoc());
DeclRefExpr *Ref = nullptr;
if (!VD && !CurContext->isDependentContext()) {
- if (TopDVar.CKind == OMPC_lastprivate)
+ if (TopDVar.CKind == OMPC_lastprivate) {
Ref = TopDVar.PrivateCopy;
- else {
+ } else {
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
- if (!IsOpenMPCapturedDecl(D))
+ if (!isOpenMPCapturedDecl(D))
ExprCaptures.push_back(Ref->getDecl());
}
}
@@ -9451,7 +9802,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> AssignmentOps;
SmallVector<Decl *, 4> ExprCaptures;
SmallVector<Expr *, 4> ExprPostUpdates;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9488,7 +9839,7 @@ 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.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
(isOpenMPDistributeDirective(CurrDir) ||
DVar.CKind != OMPC_firstprivate) &&
@@ -9496,7 +9847,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_lastprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -9515,7 +9866,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_lastprivate)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9529,19 +9880,19 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// lastprivate clause requires an accessible, unambiguous copy assignment
// operator for the class type.
Type = Context.getBaseElementType(Type).getNonReferenceType();
- auto *SrcVD = buildVarDecl(*this, ERange.getBegin(),
- Type.getUnqualifiedType(), ".lastprivate.src",
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoSrcExpr =
+ VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
+ Type.getUnqualifiedType(), ".lastprivate.src",
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ DeclRefExpr *PseudoSrcExpr =
buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
- auto *DstVD =
+ VarDecl *DstVD =
buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
+ DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
// For arrays generate assignment operation for single element and replace
// it by the original array element in CodeGen.
- auto AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
- PseudoDstExpr, PseudoSrcExpr);
+ ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
@@ -9551,15 +9902,15 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
DeclRefExpr *Ref = nullptr;
if (!VD && !CurContext->isDependentContext()) {
- if (TopDVar.CKind == OMPC_firstprivate)
+ if (TopDVar.CKind == OMPC_firstprivate) {
Ref = TopDVar.PrivateCopy;
- else {
+ } else {
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
- if (!IsOpenMPCapturedDecl(D))
+ if (!isOpenMPCapturedDecl(D))
ExprCaptures.push_back(Ref->getDecl());
}
if (TopDVar.CKind == OMPC_firstprivate ||
- (!IsOpenMPCapturedDecl(D) &&
+ (!isOpenMPCapturedDecl(D) &&
Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
if (!RefRes.isUsable())
@@ -9596,7 +9947,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9618,17 +9969,17 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
// listed below. For these exceptions only, listing a predetermined
// variable in a data-sharing attribute clause is allowed and overrides
// the variable's predetermined data-sharing attributes.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
DeclRefExpr *Ref = nullptr;
- if (!VD && IsOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
+ if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
Vars.push_back((VD || !Ref || CurContext->isDependentContext())
@@ -9648,23 +9999,21 @@ class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
public:
bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
- DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false);
+ if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
return false;
if (DVar.CKind != OMPC_unknown)
return true;
DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
- VD, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; },
+ VD, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; },
/*FromParent=*/true);
- if (DVarPrivate.CKind != OMPC_unknown)
- return true;
- return false;
+ return DVarPrivate.CKind != OMPC_unknown;
}
return false;
}
bool VisitStmt(Stmt *S) {
- for (auto Child : S->children()) {
+ for (Stmt *Child : S->children()) {
if (Child && Visit(Child))
return true;
}
@@ -9679,8 +10028,8 @@ namespace {
// DeclRefExpr to specified OMPCapturedExprDecl.
class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
typedef TreeTransform<TransformExprToCaptures> BaseTransform;
- ValueDecl *Field;
- DeclRefExpr *CapturedExpr;
+ ValueDecl *Field = nullptr;
+ DeclRefExpr *CapturedExpr = nullptr;
public:
TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
@@ -9698,12 +10047,12 @@ public:
};
} // namespace
-template <typename T>
-static T filterLookupForUDR(SmallVectorImpl<UnresolvedSet<8>> &Lookups,
- const llvm::function_ref<T(ValueDecl *)> &Gen) {
- for (auto &Set : Lookups) {
+template <typename T, typename U>
+static T filterLookupForUDR(SmallVectorImpl<U> &Lookups,
+ const llvm::function_ref<T(ValueDecl *)> Gen) {
+ for (U &Set : Lookups) {
for (auto *D : Set) {
- if (auto Res = Gen(cast<ValueDecl>(D)))
+ if (T Res = Gen(cast<ValueDecl>(D)))
return Res;
}
}
@@ -9722,7 +10071,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
Lookup.suppressDiagnostics();
while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
- auto *D = Lookup.getRepresentativeDecl();
+ NamedDecl *D = Lookup.getRepresentativeDecl();
do {
S = S->getParent();
} while (S && !S->isDeclScope(D));
@@ -9736,7 +10085,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
Lookups.push_back(UnresolvedSet<8>());
Decl *PrevD = nullptr;
- for (auto *D : ULE->decls()) {
+ for (NamedDecl *D : ULE->decls()) {
if (D == PrevD)
Lookups.push_back(UnresolvedSet<8>());
else if (auto *DRD = cast<OMPDeclareReductionDecl>(D))
@@ -9747,14 +10096,14 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
Ty->isInstantiationDependentType() ||
Ty->containsUnexpandedParameterPack() ||
- filterLookupForUDR<bool>(Lookups, [](ValueDecl *D) -> bool {
+ filterLookupForUDR<bool>(Lookups, [](ValueDecl *D) {
return !D->isInvalidDecl() &&
(D->getType()->isDependentType() ||
D->getType()->isInstantiationDependentType() ||
D->getType()->containsUnexpandedParameterPack());
})) {
UnresolvedSet<8> ResSet;
- for (auto &Set : Lookups) {
+ for (const UnresolvedSet<8> &Set : Lookups) {
ResSet.append(Set.begin(), Set.end());
// The last item marks the end of all declarations at the specified scope.
ResSet.addDecl(Set[Set.size() - 1]);
@@ -9856,7 +10205,7 @@ struct ReductionData {
};
} // namespace
-static bool CheckOMPArraySectionConstantForReduction(
+static bool checkOMPArraySectionConstantForReduction(
ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
SmallVectorImpl<llvm::APSInt> &ArraySizes) {
const Expr *Length = OASE->getLength();
@@ -9918,14 +10267,14 @@ static bool CheckOMPArraySectionConstantForReduction(
return true;
}
-static bool ActOnOMPReductionKindClause(
+static bool actOnOMPReductionKindClause(
Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
- auto DN = ReductionId.getName();
- auto OOK = DN.getCXXOverloadedOperator();
+ DeclarationName DN = ReductionId.getName();
+ OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
BinaryOperatorKind BOK = BO_Comma;
ASTContext &Context = S.Context;
@@ -9999,7 +10348,7 @@ static bool ActOnOMPReductionKindClause(
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Unexpected reduction identifier");
case OO_None:
- if (auto *II = DN.getAsIdentifierInfo()) {
+ if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
if (II->isStr("max"))
BOK = BO_GT;
else if (II->isStr("min"))
@@ -10016,7 +10365,7 @@ static bool ActOnOMPReductionKindClause(
auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
bool FirstIter = true;
- for (auto RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
// OpenMP [2.1, C/C++]
// A list item is a variable or array section, subject to the restrictions
@@ -10057,23 +10406,25 @@ static bool ActOnOMPReductionKindClause(
QualType Type;
auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
- if (ASE)
+ if (ASE) {
Type = ASE->getType().getNonReferenceType();
- else if (OASE) {
- auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
- if (auto *ATy = BaseType->getAsArrayTypeUnsafe())
+ } else if (OASE) {
+ QualType BaseType =
+ OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
Type = ATy->getElementType();
else
Type = BaseType->getPointeeType();
Type = Type.getNonReferenceType();
- } else
+ } else {
Type = Context.getBaseElementType(D->getType().getNonReferenceType());
+ }
auto *VD = dyn_cast<VarDecl>(D);
// OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
// A variable that appears in a private clause must not have an incomplete
// type or a reference type.
- if (S.RequireCompleteType(ELoc, Type,
+ if (S.RequireCompleteType(ELoc, D->getType(),
diag::err_omp_reduction_incomplete_type))
continue;
// OpenMP [2.14.3.6, reduction clause, Restrictions]
@@ -10117,19 +10468,19 @@ static bool ActOnOMPReductionKindClause(
// Any number of reduction clauses can be specified on the directive,
// but a list item can appear only once in the reduction clauses for that
// directive.
- DSAStackTy::DSAVarData DVar;
- DVar = Stack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind == OMPC_reduction) {
S.Diag(ELoc, diag::err_omp_once_referenced)
<< getOpenMPClauseName(ClauseKind);
if (DVar.RefExpr)
S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
continue;
- } else if (DVar.CKind != OMPC_unknown) {
+ }
+ if (DVar.CKind != OMPC_unknown) {
S.Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_reduction);
- ReportOriginalDSA(S, Stack, D, DVar);
+ reportOriginalDsa(S, Stack, D, DVar);
continue;
}
@@ -10146,7 +10497,7 @@ static bool ActOnOMPReductionKindClause(
S.Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_reduction)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(S, Stack, D, DVar);
+ reportOriginalDsa(S, Stack, D, DVar);
continue;
}
}
@@ -10212,11 +10563,11 @@ static bool ActOnOMPReductionKindClause(
}
Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
- auto *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto PrivateTy = Type;
+ VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ QualType PrivateTy = Type;
// Try if we can determine constant lengths for all array sections and avoid
// the VLA.
@@ -10224,15 +10575,14 @@ static bool ActOnOMPReductionKindClause(
if (OASE) {
bool SingleElement;
llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
- ConstantLengthOASE = CheckOMPArraySectionConstantForReduction(
+ 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) {
+ for (llvm::APSInt &Size : ArraySizes)
PrivateTy = Context.getConstantArrayType(
PrivateTy, Size, ArrayType::Normal, /*IndexTypeQuals=*/0);
- }
}
}
@@ -10255,15 +10605,18 @@ static bool ActOnOMPReductionKindClause(
new (Context) OpaqueValueExpr(ELoc, Context.getSizeType(), VK_RValue),
ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
} else if (!ASE && !OASE &&
- Context.getAsArrayType(D->getType().getNonReferenceType()))
+ Context.getAsArrayType(D->getType().getNonReferenceType())) {
PrivateTy = D->getType().getNonReferenceType();
+ }
// Private copy.
- auto *PrivateVD = buildVarDecl(S, ELoc, PrivateTy, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *PrivateVD =
+ buildVarDecl(S, ELoc, PrivateTy, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
// Add initializer for private variable.
Expr *Init = nullptr;
- auto *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
- auto *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
+ DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
+ DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
if (DeclareReductionRef.isUsable()) {
auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
@@ -10301,7 +10654,7 @@ static bool ActOnOMPReductionKindClause(
Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
Type, ELoc);
} else if (Type->isScalarType()) {
- auto Size = Context.getTypeSize(Type);
+ uint64_t Size = Context.getTypeSize(Type);
QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size);
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
@@ -10322,7 +10675,7 @@ static bool ActOnOMPReductionKindClause(
// the reduction list item type'.
if (Type->isIntegerType() || Type->isPointerType()) {
bool IsSigned = Type->hasSignedIntegerRepresentation();
- auto Size = Context.getTypeSize(Type);
+ uint64_t Size = Context.getTypeSize(Type);
QualType IntTy =
Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
llvm::APInt InitValue =
@@ -10333,7 +10686,7 @@ static bool ActOnOMPReductionKindClause(
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
if (Type->isPointerType()) {
// Cast to pointer type.
- auto CastExpr = S.BuildCStyleCastExpr(
+ ExprResult CastExpr = S.BuildCStyleCastExpr(
ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
if (CastExpr.isInvalid())
continue;
@@ -10394,7 +10747,7 @@ static bool ActOnOMPReductionKindClause(
// codegen.
PrivateVD->setInit(RHSVD->getInit());
PrivateVD->setInitStyle(RHSVD->getInitStyle());
- auto *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
+ DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
ExprResult ReductionOp;
if (DeclareReductionRef.isUsable()) {
QualType RedTy = DeclareReductionRef.get()->getType();
@@ -10506,7 +10859,7 @@ static bool ActOnOMPReductionKindClause(
} else {
VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
}
- if (!S.IsOpenMPCapturedDecl(D)) {
+ if (!S.isOpenMPCapturedDecl(D)) {
RD.ExprCaptures.emplace_back(Ref->getDecl());
if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
ExprResult RefRes = S.DefaultLvalueConversion(Ref);
@@ -10551,8 +10904,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions) {
ReductionData RD(VarList.size());
-
- if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
+ if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
StartLoc, LParenLoc, ColonLoc, EndLoc,
ReductionIdScopeSpec, ReductionId,
UnresolvedReductions, RD))
@@ -10572,10 +10924,9 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause(
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions) {
ReductionData RD(VarList.size());
-
- if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction,
- VarList, StartLoc, LParenLoc, ColonLoc,
- EndLoc, ReductionIdScopeSpec, ReductionId,
+ if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
+ StartLoc, LParenLoc, ColonLoc, EndLoc,
+ ReductionIdScopeSpec, ReductionId,
UnresolvedReductions, RD))
return nullptr;
@@ -10593,8 +10944,7 @@ OMPClause *Sema::ActOnOpenMPInReductionClause(
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions) {
ReductionData RD(VarList.size());
-
- if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
+ if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
StartLoc, LParenLoc, ColonLoc, EndLoc,
ReductionIdScopeSpec, ReductionId,
UnresolvedReductions, RD))
@@ -10618,10 +10968,10 @@ bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
return false;
}
-bool Sema::CheckOpenMPLinearDecl(ValueDecl *D, SourceLocation ELoc,
+bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
OpenMPLinearClauseKind LinKind,
QualType Type) {
- auto *VD = dyn_cast_or_null<VarDecl>(D);
+ const auto *VD = dyn_cast_or_null<VarDecl>(D);
// A variable must not have an incomplete type or a reference type.
if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
return true;
@@ -10678,7 +11028,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
SmallVector<Expr *, 4> ExprPostUpdates;
if (CheckOpenMPLinearModifier(LinKind, LinLoc))
LinKind = OMPC_LINEAR_val;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -10702,11 +11052,11 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
// A list-item cannot appear in more than one linear clause.
// A list-item that appears in a linear clause cannot appear in any
// other data-sharing attribute clause.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_linear);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -10715,16 +11065,18 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
// Build private copy of original var.
- auto *Private = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
+ VarDecl *Private =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
+ DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
// Build var to save initial value.
VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
Expr *InitExpr;
DeclRefExpr *Ref = nullptr;
if (!VD && !CurContext->isDependentContext()) {
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
- if (!IsOpenMPCapturedDecl(D)) {
+ if (!isOpenMPCapturedDecl(D)) {
ExprCaptures.push_back(Ref->getDecl());
if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
@@ -10746,7 +11098,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
InitExpr = VD ? SimpleRefExpr : Ref;
AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
/*DirectInit=*/false);
- auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
+ DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
Vars.push_back((VD || CurContext->isDependentContext())
@@ -10810,16 +11162,15 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Expr *CalcStep = Clause.getCalcStep();
// OpenMP [2.14.3.7, linear clause]
// If linear-step is not specified it is assumed to be 1.
- if (Step == nullptr)
+ if (!Step)
Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
- else if (CalcStep) {
+ else if (CalcStep)
Step = cast<BinaryOperator>(CalcStep)->getLHS();
- }
bool HasErrors = false;
auto CurInit = Clause.inits().begin();
auto CurPrivate = Clause.privates().begin();
- auto LinKind = Clause.getModifier();
- for (auto &RefExpr : Clause.varlists()) {
+ OpenMPLinearClauseKind LinKind = Clause.getModifier();
+ for (Expr *RefExpr : Clause.varlists()) {
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -10860,22 +11211,22 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
// Build update: Var = InitExpr + IV * Step
ExprResult Update;
- if (!Info.first) {
+ if (!Info.first)
Update =
- BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
+ buildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
InitExpr, IV, Step, /* Subtract */ false);
- } else
+ else
Update = *CurPrivate;
Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(),
/*DiscardedValue=*/true);
// Build final: Var = InitExpr + NumIterations * Step
ExprResult Final;
- if (!Info.first) {
- Final = BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
- InitExpr, NumIterations, Step,
- /* Subtract */ false);
- } else
+ if (!Info.first)
+ Final =
+ buildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
+ InitExpr, NumIterations, Step, /*Subtract=*/false);
+ else
Final = *CurPrivate;
Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(),
/*DiscardedValue=*/true);
@@ -10899,9 +11250,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
OMPClause *Sema::ActOnOpenMPAlignedClause(
ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
-
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -10938,7 +11288,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause(
// OpenMP [2.8.1, simd construct, Restrictions]
// A list-item cannot appear in more than one aligned clause.
- if (Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
+ if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange;
Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
<< getOpenMPClauseName(OMPC_aligned);
@@ -10946,7 +11296,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause(
}
DeclRefExpr *Ref = nullptr;
- if (!VD && IsOpenMPCapturedDecl(D))
+ if (!VD && isOpenMPCapturedDecl(D))
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
Vars.push_back(DefaultFunctionArrayConversion(
(VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
@@ -10980,7 +11330,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> SrcExprs;
SmallVector<Expr *, 8> DstExprs;
SmallVector<Expr *, 8> AssignmentOps;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP copyin clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
@@ -10996,7 +11346,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// A list item is a variable name.
// OpenMP [2.14.4.1, Restrictions, p.1]
// A list item that appears in a copyin clause must be threadprivate.
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
<< 0 << RefExpr->getSourceRange();
@@ -11004,7 +11354,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
}
Decl *D = DE->getDecl();
- VarDecl *VD = cast<VarDecl>(D);
+ auto *VD = cast<VarDecl>(D);
QualType Type = VD->getType();
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
@@ -11029,21 +11379,22 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
- auto *SrcVD =
+ QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
+ VarDecl *SrcVD =
buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(),
".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
- auto *PseudoSrcExpr = buildDeclRefExpr(
+ DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
- auto *DstVD =
+ VarDecl *DstVD =
buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst",
VD->hasAttrs() ? &VD->getAttrs() : nullptr);
- auto *PseudoDstExpr =
+ DeclRefExpr *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
// For arrays generate assignment operation for single element and replace
// it by the original array element in CodeGen.
- auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
- PseudoDstExpr, PseudoSrcExpr);
+ ExprResult AssignmentOp =
+ BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
+ PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
@@ -11073,7 +11424,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> SrcExprs;
SmallVector<Expr *, 8> DstExprs;
SmallVector<Expr *, 8> AssignmentOps;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -11098,13 +11449,14 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// A list item that appears in a copyprivate clause may not appear in a
// private or firstprivate clause on the single construct.
if (!VD || !DSAStack->isThreadPrivate(VD)) {
- auto DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar =
+ DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_copyprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -11117,7 +11469,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_copyprivate)
<< "threadprivate or private in the enclosing context";
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -11143,16 +11495,16 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// operator for the class type.
Type = Context.getBaseElementType(Type.getNonReferenceType())
.getUnqualifiedType();
- auto *SrcVD =
+ VarDecl *SrcVD =
buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.src",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
- auto *DstVD =
+ DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
+ VarDecl *DstVD =
buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
- auto AssignmentOp = BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
- PseudoDstExpr, PseudoSrcExpr);
+ DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
+ ExprResult AssignmentOp = BuildBinOp(
+ DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
@@ -11162,7 +11514,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// No need to mark vars as copyprivate, they are already threadprivate or
// implicitly private.
- assert(VD || IsOpenMPCapturedDecl(D));
+ assert(VD || isOpenMPCapturedDecl(D));
Vars.push_back(
VD ? RefExpr->IgnoreParens()
: buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
@@ -11213,144 +11565,142 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
DSAStackTy::OperatorOffsetTy OpsOffs;
llvm::APSInt DepCounter(/*BitWidth=*/32);
llvm::APSInt TotalDepCount(/*BitWidth=*/32);
- if (DepKind == OMPC_DEPEND_sink) {
- if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
+ if (const Expr *OrderedCountExpr =
+ DSAStack->getParentOrderedRegionParam().first) {
TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
TotalDepCount.setIsUnsigned(/*Val=*/true);
}
}
- if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) ||
- DSAStack->getParentOrderedRegionParam()) {
- for (auto &RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ for (Expr *RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (DSAStack->getParentOrderedRegionParam().first &&
+ DepCounter >= TotalDepCount) {
+ Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
+ continue;
+ }
+ ++DepCounter;
+ // OpenMP [2.13.9, Summary]
+ // depend(dependence-type : vec), where dependence-type is:
+ // 'sink' and where vec is the iteration vector, which has the form:
+ // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
+ // where n is the value specified by the ordered clause in the loop
+ // directive, xi denotes the loop iteration variable of the i-th nested
+ // loop associated with the loop directive, and di is a constant
+ // non-negative integer.
+ if (CurContext->isDependentContext()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
continue;
}
+ SimpleExpr = SimpleExpr->IgnoreImplicit();
+ OverloadedOperatorKind OOK = OO_None;
+ SourceLocation OOLoc;
+ Expr *LHS = SimpleExpr;
+ Expr *RHS = nullptr;
+ if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
+ OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
+ OOLoc = BO->getOperatorLoc();
+ LHS = BO->getLHS()->IgnoreParenImpCasts();
+ RHS = BO->getRHS()->IgnoreParenImpCasts();
+ } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
+ OOK = OCE->getOperator();
+ OOLoc = OCE->getOperatorLoc();
+ LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
+ } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
+ OOK = MCE->getMethodDecl()
+ ->getNameInfo()
+ .getName()
+ .getCXXOverloadedOperator();
+ OOLoc = MCE->getCallee()->getExprLoc();
+ LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
+ RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ }
+ SourceLocation ELoc;
+ SourceRange ERange;
+ auto Res = getPrivateItem(*this, LHS, ELoc, ERange,
+ /*AllowArraySection=*/false);
+ if (Res.second) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ }
+ ValueDecl *D = Res.first;
+ if (!D)
+ continue;
- SourceLocation ELoc = RefExpr->getExprLoc();
- auto *SimpleExpr = RefExpr->IgnoreParenCasts();
- if (DepKind == OMPC_DEPEND_sink) {
- if (DepCounter >= TotalDepCount) {
- Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
- continue;
- }
- ++DepCounter;
- // OpenMP [2.13.9, Summary]
- // depend(dependence-type : vec), where dependence-type is:
- // 'sink' and where vec is the iteration vector, which has the form:
- // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
- // where n is the value specified by the ordered clause in the loop
- // directive, xi denotes the loop iteration variable of the i-th nested
- // loop associated with the loop directive, and di is a constant
- // non-negative integer.
- if (CurContext->isDependentContext()) {
- // It will be analyzed later.
- Vars.push_back(RefExpr);
- continue;
- }
- SimpleExpr = SimpleExpr->IgnoreImplicit();
- OverloadedOperatorKind OOK = OO_None;
- SourceLocation OOLoc;
- Expr *LHS = SimpleExpr;
- Expr *RHS = nullptr;
- if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
- OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
- OOLoc = BO->getOperatorLoc();
- LHS = BO->getLHS()->IgnoreParenImpCasts();
- RHS = BO->getRHS()->IgnoreParenImpCasts();
- } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
- OOK = OCE->getOperator();
- OOLoc = OCE->getOperatorLoc();
- LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
- RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
- } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
- OOK = MCE->getMethodDecl()
- ->getNameInfo()
- .getName()
- .getCXXOverloadedOperator();
- OOLoc = MCE->getCallee()->getExprLoc();
- LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
- RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
- }
- SourceLocation ELoc;
- SourceRange ERange;
- auto Res = getPrivateItem(*this, LHS, ELoc, ERange,
- /*AllowArraySection=*/false);
- if (Res.second) {
- // It will be analyzed later.
- Vars.push_back(RefExpr);
- }
- ValueDecl *D = Res.first;
- if (!D)
- continue;
-
- if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
- Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
- continue;
- }
- if (RHS) {
- ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
- RHS, OMPC_depend, /*StrictlyPositive=*/false);
- if (RHSRes.isInvalid())
- continue;
- }
- if (!CurContext->isDependentContext() &&
- DSAStack->getParentOrderedRegionParam() &&
- DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
- ValueDecl* VD = DSAStack->getParentLoopControlVariable(
- DepCounter.getZExtValue());
- if (VD) {
- Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
- << 1 << VD;
- } else {
- Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
- }
- continue;
- }
- OpsOffs.push_back({RHS, OOK});
- } else {
- auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
- (ASE &&
- !ASE->getBase()
- ->getType()
- .getNonReferenceType()
- ->isPointerType() &&
- !ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
- 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();
+ if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
+ Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
+ continue;
+ }
+ if (RHS) {
+ ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
+ RHS, OMPC_depend, /*StrictlyPositive=*/false);
+ if (RHSRes.isInvalid())
continue;
- }
}
- Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ if (!CurContext->isDependentContext() &&
+ DSAStack->getParentOrderedRegionParam().first &&
+ DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
+ const ValueDecl *VD =
+ DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
+ if (VD)
+ Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << 1 << VD;
+ else
+ Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
+ continue;
+ }
+ OpsOffs.emplace_back(RHS, OOK);
+ } else {
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (ASE &&
+ !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
+ !ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
+ 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;
+ }
}
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
- if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
- TotalDepCount > VarList.size() &&
- DSAStack->getParentOrderedRegionParam() &&
- DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
- Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) << 1
- << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
- }
- if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
- Vars.empty())
- return nullptr;
+ if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
+ TotalDepCount > VarList.size() &&
+ DSAStack->getParentOrderedRegionParam().first &&
+ DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
+ Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
}
+ if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
+ Vars.empty())
+ return nullptr;
+
auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- DepKind, DepLoc, ColonLoc, Vars);
- if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source)
+ DepKind, DepLoc, ColonLoc, Vars,
+ TotalDepCount.getZExtValue());
+ if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
+ DSAStack->isParentOrderedRegion())
DSAStack->addDoacrossDependClause(C, OpsOffs);
return C;
}
@@ -11363,7 +11713,7 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
// OpenMP [2.9.1, Restrictions]
// The device expression must evaluate to a non-negative integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
/*StrictlyPositive=*/false))
return nullptr;
@@ -11372,46 +11722,50 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
getOpenMPCaptureRegionForClause(DKind, OMPC_device);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
- return new (Context)
- OMPDeviceClause(ValExpr, HelperValStmt, StartLoc, LParenLoc, EndLoc);
+ return new (Context) OMPDeviceClause(ValExpr, HelperValStmt, CaptureRegion,
+ StartLoc, LParenLoc, EndLoc);
}
-static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
- DSAStackTy *Stack, QualType QTy) {
+static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
+ DSAStackTy *Stack, QualType QTy,
+ bool FullCheck = true) {
NamedDecl *ND;
if (QTy->isIncompleteType(&ND)) {
SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR;
return false;
}
+ if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
+ !QTy.isTrivialType(SemaRef.Context))
+ SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
return true;
}
-/// \brief Return true if it can be proven that the provided array expression
+/// Return true if it can be proven that the provided array expression
/// (array section or array subscript) does NOT specify the whole size of the
/// array whose base type is \a BaseQTy.
-static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
+static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
const Expr *E,
QualType BaseQTy) {
- auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
// If this is an array subscript, it refers to the whole size if the size of
// the dimension is constant and equals 1. Also, an array section assumes the
// format of an array subscript if no colon is used.
if (isa<ArraySubscriptExpr>(E) || (OASE && OASE->getColonLoc().isInvalid())) {
- if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
+ if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
// Size can't be evaluated statically.
return false;
}
assert(OASE && "Expecting array section if not an array subscript.");
- auto *LowerBound = OASE->getLowerBound();
- auto *Length = OASE->getLength();
+ const Expr *LowerBound = OASE->getLowerBound();
+ const Expr *Length = OASE->getLength();
// If there is a lower bound that does not evaluates to zero, we are not
// covering the whole dimension.
@@ -11434,7 +11788,7 @@ static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// We can only check if the length is the same as the size of the dimension
// if we have a constant array.
- auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
+ const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
if (!CATy)
return false;
@@ -11448,10 +11802,10 @@ static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// Return true if it can be proven that the provided array expression (array
// section or array subscript) does NOT specify a single element of the array
// whose base type is \a BaseQTy.
-static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
+static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
const Expr *E,
QualType BaseQTy) {
- auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
// An array subscript always refer to a single element. Also, an array section
// assumes the format of an array subscript if no colon is used.
@@ -11459,13 +11813,13 @@ static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
return false;
assert(OASE && "Expecting array section if not an array subscript.");
- auto *Length = OASE->getLength();
+ const Expr *Length = OASE->getLength();
// If we don't have a length we have to check if the array has unitary size
// for this dimension. Also, we should always expect a length if the base type
// is pointer.
if (!Length) {
- if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
+ if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
// We cannot assume anything.
return false;
@@ -11483,7 +11837,7 @@ static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
// cannot be determined and do all the necessary checks to see if the expression
// is valid as a standalone mappable expression. In the process, record all the
// components of the expression.
-static Expr *CheckMapClauseExpressionBase(
+static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
OpenMPClauseKind CKind, bool NoDiagnose) {
@@ -11509,7 +11863,7 @@ static Expr *CheckMapClauseExpressionBase(
//
// We want to retrieve the member expression 'this->S';
- Expr *RelevantExpr = nullptr;
+ const Expr *RelevantExpr = nullptr;
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.2]
// If a list item is an array section, it must specify contiguous storage.
@@ -11548,7 +11902,7 @@ static Expr *CheckMapClauseExpressionBase(
// Record the component.
CurComponents.emplace_back(CurE, CurE->getDecl());
} else if (auto *CurE = dyn_cast<MemberExpr>(E)) {
- auto *BaseE = CurE->getBase()->IgnoreParenImpCasts();
+ Expr *BaseE = CurE->getBase()->IgnoreParenImpCasts();
if (isa<CXXThisExpr>(BaseE))
// We found a base expression: this->Val.
@@ -11592,15 +11946,13 @@ 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 (RT->isUnionType()) {
- if (!NoDiagnose) {
- SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
- << CurE->getSourceRange();
- return nullptr;
- }
- continue;
+ if (CurType->isUnionType()) {
+ 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
@@ -11630,7 +11982,7 @@ static Expr *CheckMapClauseExpressionBase(
// If we got an array subscript that express the whole dimension we
// can have any array expressions before. If it only expressing part of
// the dimension, we can only have unitary-size array expressions.
- if (CheckArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE,
+ if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE,
E->getType()))
AllowWholeSizeArraySection = false;
@@ -11658,9 +12010,9 @@ static Expr *CheckMapClauseExpressionBase(
}
bool NotWhole =
- CheckArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE, CurType);
+ checkArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE, CurType);
bool NotUnity =
- CheckArrayExpressionDoesNotReferToUnitySize(SemaRef, CurE, CurType);
+ checkArrayExpressionDoesNotReferToUnitySize(SemaRef, CurE, CurType);
if (AllowWholeSizeArraySection) {
// Any array section is currently allowed. Allowing a whole size array
@@ -11698,8 +12050,8 @@ static Expr *CheckMapClauseExpressionBase(
// Return true if expression E associated with value VD has conflicts with other
// map information.
-static bool CheckMapConflicts(
- Sema &SemaRef, DSAStackTy *DSAS, ValueDecl *VD, Expr *E,
+static bool checkMapConflicts(
+ Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
bool CurrentRegionOnly,
OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
OpenMPClauseKind CKind) {
@@ -11721,17 +12073,19 @@ static bool CheckMapConflicts(
bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
VD, CurrentRegionOnly,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
- StackComponents,
- OpenMPClauseKind) -> bool {
-
+ [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
+ ERange, CKind, &EnclosingExpr,
+ CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
assert(!StackComponents.empty() &&
"Map clause expression with no components!");
assert(StackComponents.back().getAssociatedDeclaration() == VD &&
"Map clause expression with unexpected base!");
+ (void)VD;
// The whole expression in the stack.
- auto *RE = StackComponents.front().getAssociatedExpression();
+ const Expr *RE = StackComponents.front().getAssociatedExpression();
// Expressions must start from the same base. Here we detect at which
// point both expressions diverge from each other and see if we can
@@ -11774,17 +12128,17 @@ static bool CheckMapConflicts(
// If they are, the maps completely overlap, which is legal.
for (; SI != SE; ++SI) {
QualType Type;
- if (auto *ASE =
+ if (const auto *ASE =
dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
- } else if (auto *OASE = dyn_cast<OMPArraySectionExpr>(
+ } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
SI->getAssociatedExpression())) {
- auto *E = OASE->getBase()->IgnoreParenImpCasts();
+ const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
Type =
OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
}
if (Type.isNull() || Type->isAnyPointerType() ||
- CheckArrayExpressionDoesNotReferToWholeSize(
+ checkArrayExpressionDoesNotReferToWholeSize(
SemaRef, SI->getAssociatedExpression(), Type))
break;
}
@@ -11797,9 +12151,9 @@ static bool CheckMapConflicts(
// other, it means they are sharing storage.
if (CI == CE && SI == SE) {
if (CurrentRegionOnly) {
- if (CKind == OMPC_map)
+ if (CKind == OMPC_map) {
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
- else {
+ } else {
assert(CKind == OMPC_to || CKind == OMPC_from);
SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
<< ERange;
@@ -11807,12 +12161,11 @@ static bool CheckMapConflicts(
SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
<< RE->getSourceRange();
return true;
- } else {
- // If we find the same expression in the enclosing data environment,
- // that is legal.
- IsEnclosedByDataEnvironmentExpr = true;
- return false;
}
+ // If we find the same expression in the enclosing data environment,
+ // that is legal.
+ IsEnclosedByDataEnvironmentExpr = true;
+ return false;
}
QualType DerivedType =
@@ -11842,14 +12195,21 @@ static bool CheckMapConflicts(
DerivedLoc,
diag::err_omp_pointer_mapped_along_with_derived_section)
<< DerivedLoc;
- } else {
+ SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
+ << RE->getSourceRange();
+ return true;
+ }
+ if (CI->getAssociatedExpression()->getStmtClass() !=
+ SI->getAssociatedExpression()->getStmtClass() ||
+ CI->getAssociatedDeclaration()->getCanonicalDecl() ==
+ SI->getAssociatedDeclaration()->getCanonicalDecl()) {
assert(CI != CE && SI != SE);
- SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_derreferenced)
+ SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
<< DerivedLoc;
+ SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
+ << RE->getSourceRange();
+ return true;
}
- SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
- << RE->getSourceRange();
- return true;
}
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
@@ -11858,9 +12218,9 @@ static bool CheckMapConflicts(
//
// An expression is a subset of the other.
if (CurrentRegionOnly && (CI == CE || SI == SE)) {
- if (CKind == OMPC_map)
+ if (CKind == OMPC_map) {
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
- else {
+ } else {
assert(CKind == OMPC_to || CKind == OMPC_from);
SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
<< ERange;
@@ -11912,7 +12272,7 @@ static bool CheckMapConflicts(
namespace {
// Utility struct that gathers all the related lists associated with a mappable
// expression.
-struct MappableVarListInfo final {
+struct MappableVarListInfo {
// The list of expressions.
ArrayRef<Expr *> VarList;
// The list of processed expressions.
@@ -11952,11 +12312,11 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// In the end we should have the same amount of declarations and component
// lists.
- for (auto &RE : MVLI.VarList) {
+ for (Expr *RE : MVLI.VarList) {
assert(RE && "Null expr in omp to/from/map clause");
SourceLocation ELoc = RE->getExprLoc();
- auto *VE = RE->IgnoreParenLValueCasts();
+ const Expr *VE = RE->IgnoreParenLValueCasts();
if (VE->isValueDependent() || VE->isTypeDependent() ||
VE->isInstantiationDependent() ||
@@ -11967,7 +12327,7 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
continue;
}
- auto *SimpleExpr = RE->IgnoreParenCasts();
+ Expr *SimpleExpr = RE->IgnoreParenCasts();
if (!RE->IgnoreParenImpCasts()->isLValue()) {
SemaRef.Diag(ELoc,
@@ -11981,8 +12341,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, /*NoDiagnose=*/false);
+ const Expr *BE = checkMapClauseExpressionBase(
+ SemaRef, SimpleExpr, CurComponents, CKind, /*NoDiagnose=*/false);
if (!BE)
continue;
@@ -11999,7 +12359,7 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
"Expecting components to have associated only canonical declarations.");
auto *VD = dyn_cast<VarDecl>(CurDeclaration);
- auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
+ const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
assert((VD || FD) && "Only variables or fields are expected here!");
(void)FD;
@@ -12009,10 +12369,10 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// OpenMP 4.5 [2.10.5, target update Construct]
// threadprivate variables cannot appear in a from clause.
if (VD && DSAS->isThreadPrivate(VD)) {
- auto DVar = DSAS->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
<< getOpenMPClauseName(CKind);
- ReportOriginalDSA(SemaRef, DSAS, VD, DVar);
+ reportOriginalDsa(SemaRef, DSAS, VD, DVar);
continue;
}
@@ -12024,11 +12384,11 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// with the current construct separately from the enclosing data
// environment, because the restrictions are different. We only have to
// check conflicts across regions for the map clauses.
- if (CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
+ if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
/*CurrentRegionOnly=*/true, CurComponents, CKind))
break;
if (CKind == OMPC_map &&
- CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
+ checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
/*CurrentRegionOnly=*/false, CurComponents, CKind))
break;
@@ -12036,13 +12396,20 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
// If the type of a list item is a reference to a type T then the type will
// be considered to be T for all purposes of this clause.
- QualType Type = CurDeclaration->getType().getNonReferenceType();
+ auto I = llvm::find_if(
+ CurComponents,
+ [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
+ return MC.getAssociatedDeclaration();
+ });
+ assert(I != CurComponents.end() && "Null decl on map clause.");
+ QualType Type =
+ I->getAssociatedDeclaration()->getType().getNonReferenceType();
// OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
// A list item in a to or from clause must have a mappable type.
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
// A list item must have a mappable type.
- if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
+ if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
DSAS, Type))
continue;
@@ -12078,18 +12445,14 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// 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 ((DKind == OMPD_target || DKind == OMPD_target_teams ||
- DKind == OMPD_target_teams_distribute ||
- DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd) && VD) {
- auto DVar = DSAS->getTopDSA(VD, false);
+ if (VD && isOpenMPTargetExecutionDirective(DKind)) {
+ DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
if (isOpenMPPrivate(DVar.CKind)) {
SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_map)
<< getOpenMPDirectiveName(DSAS->getCurrentDirective());
- ReportOriginalDSA(SemaRef, DSAS, CurDeclaration, DVar);
+ reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
continue;
}
}
@@ -12190,14 +12553,14 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
/*AllowInlineNamespace=*/false);
llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
- auto Filter = Lookup.makeFilter();
+ LookupResult::Filter Filter = Lookup.makeFilter();
while (Filter.hasNext()) {
auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
if (InCompoundScope) {
auto I = UsedAsPrevious.find(PrevDecl);
if (I == UsedAsPrevious.end())
UsedAsPrevious[PrevDecl] = false;
- if (auto *D = PrevDecl->getPrevDeclInScope())
+ if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
UsedAsPrevious[D] = true;
}
PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
@@ -12205,7 +12568,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
}
Filter.done();
if (InCompoundScope) {
- for (auto &PrevData : UsedAsPrevious) {
+ for (const auto &PrevData : UsedAsPrevious) {
if (!PrevData.second) {
PrevDRD = PrevData.first;
break;
@@ -12221,8 +12584,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
} while (PrevDRDInScope != nullptr);
}
- for (auto &TyData : ReductionTypes) {
- auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
+ for (const auto &TyData : ReductionTypes) {
+ const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
bool Invalid = false;
if (I != PreviousRedeclTypes.end()) {
Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
@@ -12251,7 +12614,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
getCurFunction()->setHasOMPDeclareReductionCombiner();
if (S != nullptr)
@@ -12269,7 +12632,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_in;' variable.
- auto *OmpInParm =
+ VarDecl *OmpInParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
// Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
// be replaced by '*omp_parm' during codegen. This required because 'omp_out'
@@ -12277,7 +12640,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_out;' variable.
- auto *OmpOutParm =
+ VarDecl *OmpOutParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
if (S != nullptr) {
PushOnScopeChains(OmpInParm, S);
@@ -12307,7 +12670,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S != nullptr)
PushDeclContext(S, DRD);
@@ -12324,7 +12687,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_priv;' variable.
- auto *OmpPrivParm =
+ VarDecl *OmpPrivParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
// Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
// be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
@@ -12332,7 +12695,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_orig;' variable.
- auto *OmpOrigParm =
+ VarDecl *OmpOrigParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
if (S != nullptr) {
PushOnScopeChains(OmpPrivParm, S);
@@ -12367,13 +12730,14 @@ void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
- for (auto *D : DeclReductions.get()) {
+ for (Decl *D : DeclReductions.get()) {
if (IsValid) {
- auto *DRD = cast<OMPDeclareReductionDecl>(D);
- if (S != nullptr)
- PushOnScopeChains(DRD, S, /*AddToContext=*/false);
- } else
+ if (S)
+ PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
+ /*AddToContext=*/false);
+ } else {
D->setInvalidDecl();
+ }
}
return DeclReductions;
}
@@ -12387,7 +12751,7 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
// OpenMP [teams Constrcut, Restrictions]
// The num_teams expression must evaluate to a positive integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12396,7 +12760,7 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -12414,7 +12778,7 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
// OpenMP [teams Constrcut, Restrictions]
// The thread_limit expression must evaluate to a positive integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12423,7 +12787,7 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -12440,7 +12804,7 @@ OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
// OpenMP [2.9.1, task Constrcut]
// The priority-value is a non-negative numerical scalar expression.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_priority,
/*StrictlyPositive=*/false))
return nullptr;
@@ -12456,7 +12820,7 @@ OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize,
// OpenMP [2.9.2, taskloop Constrcut]
// The parameter of the grainsize clause must be a positive integer
// expression.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12472,7 +12836,7 @@ OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
// OpenMP [2.9.2, taskloop Constrcut]
// The parameter of the num_tasks clause must be a positive integer
// expression.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12534,7 +12898,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause(
OMPD_unknown &&
!CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -12599,7 +12963,6 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
assert(IsInOpenMPDeclareTargetContext &&
"Unexpected ActOnFinishOpenMPDeclareTargetDirective");
-
IsInOpenMPDeclareTargetContext = false;
}
@@ -12634,9 +12997,8 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl())))
Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName();
-
if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
ND->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
@@ -12645,15 +13007,16 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link)
<< Id.getName();
}
- } else
+ } else {
Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
+ }
}
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
Sema &SemaRef, Decl *D) {
if (!D)
return;
- Decl *LD = nullptr;
+ const Decl *LD = nullptr;
if (isa<TagDecl>(D)) {
LD = cast<TagDecl>(D)->getDefinition();
} else if (isa<VarDecl>(D)) {
@@ -12662,56 +13025,63 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
// If this is an implicit variable that is legal and we do not need to do
// anything.
if (cast<VarDecl>(D)->isImplicit()) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
D->addAttr(A);
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
return;
}
-
- } else if (isa<FunctionDecl>(D)) {
+ } else if (const auto *F = dyn_cast<FunctionDecl>(D)) {
const FunctionDecl *FD = nullptr;
- if (cast<FunctionDecl>(D)->hasBody(FD))
- LD = const_cast<FunctionDecl *>(FD);
-
- // If the definition is associated with the current declaration in the
- // target region (it can be e.g. a lambda) that is legal and we do not need
- // to do anything else.
- if (LD == D) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
- D->addAttr(A);
- if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
- return;
+ if (cast<FunctionDecl>(D)->hasBody(FD)) {
+ LD = FD;
+ // If the definition is associated with the current declaration in the
+ // target region (it can be e.g. a lambda) that is legal and we do not
+ // need to do anything else.
+ if (LD == D) {
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
+ D->addAttr(A);
+ if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
+ ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
+ return;
+ }
+ } else if (F->isFunctionTemplateSpecialization() &&
+ F->getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation) {
+ // Check if the function is implicitly instantiated from the template
+ // defined in the declare target region.
+ const FunctionTemplateDecl *FTD = F->getPrimaryTemplate();
+ if (FTD && FTD->hasAttr<OMPDeclareTargetDeclAttr>())
+ return;
}
}
if (!LD)
LD = D;
if (LD && !LD->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (isa<VarDecl>(LD) || isa<FunctionDecl>(LD))) {
+ ((isa<VarDecl>(LD) && !isa<ParmVarDecl>(LD)) || isa<FunctionDecl>(LD))) {
// Outlined declaration is not declared target.
- if (LD->isOutOfLine()) {
- SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
- SemaRef.Diag(SL, diag::note_used_here) << SR;
- } else {
- DeclContext *DC = LD->getDeclContext();
- while (DC) {
- if (isa<FunctionDecl>(DC) &&
- cast<FunctionDecl>(DC)->hasAttr<OMPDeclareTargetDeclAttr>())
- break;
- DC = DC->getParent();
- }
- if (DC)
- return;
+ if (!isa<FunctionDecl>(LD)) {
+ if (LD->isOutOfLine()) {
+ SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
+ SemaRef.Diag(SL, diag::note_used_here) << SR;
+ } else {
+ const DeclContext *DC = LD->getDeclContext();
+ while (DC &&
+ (!isa<FunctionDecl>(DC) ||
+ !cast<FunctionDecl>(DC)->hasAttr<OMPDeclareTargetDeclAttr>()))
+ DC = DC->getParent();
+ if (DC)
+ return;
- // Is not declared in target context.
- SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
- SemaRef.Diag(SL, diag::note_used_here) << SR;
+ // Is not declared in target context.
+ SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
+ SemaRef.Diag(SL, diag::note_used_here) << SR;
+ }
}
// Mark decl as declared target to prevent further diagnostic.
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
D->addAttr(A);
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
@@ -12722,11 +13092,9 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
Sema &SemaRef, DSAStackTy *Stack,
ValueDecl *VD) {
- if (VD->hasAttr<OMPDeclareTargetDeclAttr>())
- return true;
- if (!CheckTypeMappable(SL, SR, SemaRef, Stack, VD->getType()))
- return false;
- return true;
+ return VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
+ checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
+ /*FullCheck=*/false);
}
void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
@@ -12735,22 +13103,27 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
SourceLocation SL = E ? E->getLocStart() : D->getLocation();
- // 2.10.6: threadprivate variable cannot appear in a declare target directive.
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ // Only global variables can be marked as declare target.
+ if (VD->isLocalVarDeclOrParm())
+ return;
+ // 2.10.6: threadprivate variable cannot appear in a declare target
+ // directive.
if (DSAStack->isThreadPrivate(VD)) {
Diag(SL, diag::err_omp_threadprivate_in_target);
- ReportOriginalDSA(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
+ reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
return;
}
}
- if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
// Problem if any with var declared with incomplete type will be reported
// as normal, so no need to check it here.
if ((E || !VD->getType()->isIncompleteType()) &&
!checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) {
// Mark decl as declared target to prevent further diagnostic.
- if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD)) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD) ||
+ isa<FunctionTemplateDecl>(VD)) {
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
Context, OMPDeclareTargetDeclAttr::MT_To);
VD->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
@@ -12759,7 +13132,9 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ D = FTD->getTemplatedDecl();
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
(FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
OMPDeclareTargetDeclAttr::MT_Link)) {
@@ -12772,8 +13147,9 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
if (!E) {
// Checking declaration inside declare target region.
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (isa<VarDecl>(D) || isa<FunctionDecl>(D))) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
+ isa<FunctionTemplateDecl>(D))) {
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
Context, OMPDeclareTargetDeclAttr::MT_To);
D->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
@@ -12820,7 +13196,7 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> PrivateCopies;
SmallVector<Expr *, 8> Inits;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -12849,20 +13225,22 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
}
// Build the private variable and the expression that refers to it.
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
if (VDPrivate->isInvalidDecl())
continue;
CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr = buildDeclRefExpr(
+ DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
*this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
// Add temporary variable to initialize the private copy of the pointer.
- auto *VDInit =
+ VarDecl *VDInit =
buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
- auto *VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
- RefExpr->getExprLoc());
+ DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
+ *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
AddInitializerToDecl(VDPrivate,
DefaultLvalueConversion(VDInitRefExpr).get(),
/*DirectInit=*/false);
@@ -12902,7 +13280,7 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
MappableVarListInfo MVLI(VarList);
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -12927,17 +13305,17 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
// Check if the declaration in the clause does not show up in any data
// sharing attribute.
- auto DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (isOpenMPPrivate(DVar.CKind)) {
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_is_device_ptr)
<< getOpenMPDirectiveName(DSAStack->getCurrentDirective());
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
- Expr *ConflictExpr;
+ const Expr *ConflictExpr;
if (DSAStack->checkMappableExprComponentListsForDecl(
D, /*CurrentRegionOnly=*/true,
[&ConflictExpr](
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index f2b1963df1ed..08af485ef4c7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -223,6 +223,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
// a pointer.
if (getToType(1)->isBooleanType() &&
(getFromType()->isPointerType() ||
+ getFromType()->isMemberPointerType() ||
getFromType()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
getFromType()->isNullPtrType() ||
@@ -288,11 +289,11 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
/// value of the expression prior to the narrowing conversion.
/// \param ConstantType If this is an NK_Constant_Narrowing conversion, the
/// type of the expression prior to the narrowing conversion.
-NarrowingKind
-StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
- const Expr *Converted,
- APValue &ConstantValue,
- QualType &ConstantType) const {
+/// \param IgnoreFloatToIntegralConversion If true type-narrowing conversions
+/// from floating point types to integral types should be ignored.
+NarrowingKind StandardConversionSequence::getNarrowingKind(
+ ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue,
+ QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const {
assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
// C++11 [dcl.init.list]p7:
@@ -327,7 +328,10 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
FloatingIntegralConversion:
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
return NK_Type_Narrowing;
- } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
+ } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
+ ToType->isRealFloatingType()) {
+ if (IgnoreFloatToIntegralConversion)
+ return NK_Not_Narrowing;
llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
assert(Initializer && "Unknown conversion expression");
@@ -580,7 +584,7 @@ namespace {
};
}
-/// \brief Convert from Sema's representation of template deduction information
+/// Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
DeductionFailureInfo
clang::MakeDeductionFailureInfo(ASTContext &Context,
@@ -625,6 +629,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
break;
}
+ case Sema::TDK_IncompletePack:
+ // FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
@@ -667,6 +673,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_NonDependentConversionFailure:
break;
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
@@ -716,6 +723,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
@@ -736,6 +744,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -773,6 +782,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
@@ -794,6 +804,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
@@ -997,6 +1008,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
Match = *I;
return Ovl_Match;
}
+
+ // Builtins that have custom typechecking or have a reference should
+ // not be overloadable or redeclarable.
+ if (!getASTContext().canBuiltinBeRedeclared(OldF)) {
+ Match = *I;
+ return Ovl_NonFunction;
+ }
} else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
// We can overload with these, which can show up when doing
// redeclaration checks for UsingDecls.
@@ -1182,7 +1200,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return false;
}
-/// \brief Checks availability of the function depending on the current
+/// Checks availability of the function depending on the current
/// function context. Inside an unavailable function, unavailability is ignored.
///
/// \returns true if \arg FD is unavailable and current context is inside
@@ -1200,7 +1218,7 @@ bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) {
return true;
}
-/// \brief Tries a user-defined conversion from From to ToType.
+/// Tries a user-defined conversion from From to ToType.
///
/// Produces an implicit conversion sequence for when a standard conversion
/// is not an option. See TryImplicitConversion for more information.
@@ -1412,7 +1430,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return PerformImplicitConversion(From, ToType, ICS, Action);
}
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// Determine whether the conversion from FromType to ToType is a valid
/// conversion that strips "noexcept" or "noreturn" off the nested function
/// type.
bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
@@ -1473,12 +1491,10 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
// Drop 'noexcept' if not present in target type.
if (const auto *FromFPT = dyn_cast<FunctionProtoType>(FromFn)) {
const auto *ToFPT = cast<FunctionProtoType>(ToFn);
- if (FromFPT->isNothrow(Context) && !ToFPT->isNothrow(Context)) {
+ if (FromFPT->isNothrow() && !ToFPT->isNothrow()) {
FromFn = cast<FunctionType>(
- Context.getFunctionType(FromFPT->getReturnType(),
- FromFPT->getParamTypes(),
- FromFPT->getExtProtoInfo().withExceptionSpec(
- FunctionProtoType::ExceptionSpecInfo()))
+ Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0),
+ EST_None)
.getTypePtr());
Changed = true;
}
@@ -1511,7 +1527,7 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
return true;
}
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// Determine whether the conversion from FromType to ToType is a valid
/// vector conversion.
///
/// \param ICK Will be set to the vector conversion kind, if this is a vector
@@ -1766,8 +1782,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
(FromType == S.Context.LongDoubleTy &&
ToType == S.Context.Float128Ty));
if (Float128AndLongDouble &&
- (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble()))
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
+ &llvm::APFloat::PPCDoubleDouble()))
return false;
}
// Floating point conversions (C++ 4.8).
@@ -1998,6 +2014,14 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
isCompleteType(From->getLocStart(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
+
+ // C++ [conv.prom]p5:
+ // If the bit-field has an enumerated type, it is treated as any other
+ // value of that type for promotion purposes.
+ //
+ // ... so do not fall through into the bit-field checks below in C++.
+ if (getLangOpts().CPlusPlus)
+ return false;
}
// C++0x [conv.prom]p2:
@@ -2045,6 +2069,11 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// other value of that type for promotion purposes (C++ 4.5p3).
// FIXME: We should delay checking of bit-fields until we actually perform the
// conversion.
+ //
+ // FIXME: In C, only bit-fields of types _Bool, int, or unsigned int may be
+ // promoted, per C11 6.3.1.1/2. We promote all bit-fields (including enum
+ // bit-fields and those whose underlying type is larger than int) for GCC
+ // compatibility.
if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
llvm::APSInt BitWidth;
@@ -2111,7 +2140,7 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
return false;
}
-/// \brief Determine if a conversion is a complex promotion.
+/// Determine if a conversion is a complex promotion.
///
/// A complex promotion is defined as a complex -> complex conversion
/// where the conversion between the underlying real types is a
@@ -2345,7 +2374,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
return false;
}
-/// \brief Adopt the given qualifiers for the given type.
+/// Adopt the given qualifiers for the given type.
static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
Qualifiers TQs = T.getQualifiers();
@@ -2533,7 +2562,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return false;
}
-/// \brief Determine whether this is an Objective-C writeback conversion,
+/// Determine whether this is an Objective-C writeback conversion,
/// used for parameter passing when performing automatic reference counting.
///
/// \param FromType The type we're converting form.
@@ -2593,7 +2622,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
IncompatibleObjC))
return false;
- /// \brief Construct the type we're converting to, which is a pointer to
+ /// Construct the type we're converting to, which is a pointer to
/// __autoreleasing pointee.
FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
ConvertedType = Context.getPointerType(FromPointee);
@@ -2803,9 +2832,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
// Handle exception specification differences on canonical type (in C++17
// onwards).
if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified())
- ->isNothrow(Context) !=
+ ->isNothrow() !=
cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified())
- ->isNothrow(Context)) {
+ ->isNothrow()) {
PDiag << ft_noexcept;
return;
}
@@ -3065,7 +3094,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
// in multi-level pointers, subject to the following rules: [...]
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
- while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) {
+ while (Context.UnwrapSimilarTypes(FromType, ToType)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -3121,6 +3150,15 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
= PreviousToQualsIncludeConst && ToQuals.hasConst();
}
+ // Allows address space promotion by language rules implemented in
+ // Type::Qualifiers::isAddressSpaceSupersetOf.
+ Qualifiers FromQuals = FromType.getQualifiers();
+ Qualifiers ToQuals = ToType.getQualifiers();
+ if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
+ !FromQuals.isAddressSpaceSupersetOf(ToQuals)) {
+ return false;
+ }
+
// We are left with FromType and ToType being the pointee types
// after unwrapping the original FromType and ToType the same number
// of types. If we unwrapped any pointers, and if FromType and
@@ -3129,7 +3167,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
}
-/// \brief - Determine whether this is a conversion from a scalar type to an
+/// - Determine whether this is a conversion from a scalar type to an
/// atomic type.
///
/// If successful, updates \c SCS's second and third steps in the conversion
@@ -3472,7 +3510,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
return true;
}
-/// \brief Compare the user-defined conversion functions or constructors
+/// Compare the user-defined conversion functions or constructors
/// of two user-defined conversion sequences to determine whether any ordering
/// is possible.
static ImplicitConversionSequence::CompareKind
@@ -3620,16 +3658,6 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc,
return Result;
}
-static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
- while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
- Qualifiers Quals;
- T1 = Context.getUnqualifiedArrayType(T1, Quals);
- T2 = Context.getUnqualifiedArrayType(T2, Quals);
- }
-
- return Context.hasSameUnqualifiedType(T1, T2);
-}
-
// Per 13.3.3.2p3, compare the given standard conversion sequences to
// determine if one is a proper subset of the other.
static ImplicitConversionSequence::CompareKind
@@ -3653,7 +3681,7 @@ compareStandardConversionSubsets(ASTContext &Context,
Result = ImplicitConversionSequence::Worse;
else
return ImplicitConversionSequence::Indistinguishable;
- } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1)))
+ } else if (!Context.hasSimilarType(SCS1.getToType(1), SCS2.getToType(1)))
return ImplicitConversionSequence::Indistinguishable;
if (SCS1.Third == SCS2.Third) {
@@ -3674,7 +3702,7 @@ compareStandardConversionSubsets(ASTContext &Context,
return ImplicitConversionSequence::Indistinguishable;
}
-/// \brief Determine whether one of the given reference bindings is better
+/// Determine whether one of the given reference bindings is better
/// than the other based on what kind of bindings they are.
static bool
isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
@@ -3927,7 +3955,7 @@ CompareQualificationConversions(Sema &S,
: ImplicitConversionSequence::Better;
}
- while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ while (S.Context.UnwrapSimilarTypes(T1, T2)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -4199,7 +4227,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
return ImplicitConversionSequence::Indistinguishable;
}
-/// \brief Determine whether the given type is valid, e.g., it is not an invalid
+/// Determine whether the given type is valid, e.g., it is not an invalid
/// C++ class.
static bool isTypeValid(QualType T) {
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
@@ -4302,7 +4330,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
return Ref_Related;
}
-/// \brief Look for a user-defined conversion to a value reference-compatible
+/// Look for a user-defined conversion to a value reference-compatible
/// with DeclType. Return true if something definite is found.
static bool
FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
@@ -4429,7 +4457,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
llvm_unreachable("Invalid OverloadResult!");
}
-/// \brief Compute an implicit conversion sequence for reference
+/// Compute an implicit conversion sequence for reference
/// initialization.
static ImplicitConversionSequence
TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
@@ -5137,6 +5165,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
FromRecordType = From->getType();
DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context);
+
+ // When performing member access on an rvalue, materialize a temporary.
+ if (From->isRValue()) {
+ From = CreateMaterializeTemporaryExpr(FromRecordType, From,
+ Method->getRefQualifier() !=
+ RefQualifierKind::RQ_RValue);
+ }
}
// Note that we always use the true parent context when performing
@@ -5399,10 +5434,11 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
+ Expr::ConstExprUsage Usage = CCE == Sema::CCEK_TemplateArg
+ ? Expr::EvaluateForMangling
+ : Expr::EvaluateForCodeGen;
- if ((T->isReferenceType()
- ? !Result.get()->EvaluateAsLValue(Eval, S.Context)
- : !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
+ if (!Result.get()->EvaluateAsConstantExpr(Eval, Usage, S.Context) ||
(RequireInt && !Eval.Val.isInt())) {
// The expression can't be folded, so we can't keep it at this position in
// the AST.
@@ -5641,7 +5677,7 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType,
}
}
-/// \brief Attempt to convert the given expression to a type which is accepted
+/// Attempt to convert the given expression to a type which is accepted
/// by the given converter.
///
/// This routine will attempt to convert an expression of class type to a
@@ -5959,6 +5995,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
+ if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
+ !Function->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ return;
+ }
+
if (Constructor) {
// C++ [class.copy]p3:
// A member function template is never instantiated to perform the copy
@@ -6239,12 +6282,17 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
ParmVarDecl *P = Function->getParamDecl(i);
- ExprResult R = S.PerformCopyInitialization(
- InitializedEntity::InitializeParameter(S.Context,
- Function->getParamDecl(i)),
- SourceLocation(),
- P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg()
- : P->getDefaultArg());
+ Expr *DefArg = P->hasUninstantiatedDefaultArg()
+ ? P->getUninstantiatedDefaultArg()
+ : P->getDefaultArg();
+ // This can only happen in code completion, i.e. when PartialOverloading
+ // is true.
+ if (!DefArg)
+ return false;
+ ExprResult R =
+ S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ S.Context, Function->getParamDecl(i)),
+ SourceLocation(), DefArg);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
@@ -6355,67 +6403,65 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
});
}
-/// \brief Add all of the function declarations in the given function set to
+/// Add all of the function declarations in the given function set to
/// the overload candidate set.
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
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 (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, FunctionArgs, CandidateSet,
- SuppressUserConversions, PartialOverloading);
- } else {
- // 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 {
- FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
- if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
- !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) {
- QualType ObjectType;
- Expr::Classification ObjectClassification;
+ ArrayRef<Expr *> FunctionArgs = Args;
+
+ FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ FunctionDecl *FD =
+ FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D);
+
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
+ QualType ObjectType;
+ Expr::Classification ObjectClassification;
+ if (Args.size() > 0) {
if (Expr *E = Args[0]) {
- // Use the explit base to restrict the lookup:
+ // Use the explicit base to restrict the lookup:
ObjectType = E->getType();
ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
+ } // .. else there is an implicit base.
+ FunctionArgs = Args.slice(1);
+ }
+ if (FunTmpl) {
AddMethodTemplateCandidate(
FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
ExplicitTemplateArgs, ObjectType, ObjectClassification,
- Args.slice(1), CandidateSet, SuppressUserConversions,
+ FunctionArgs, CandidateSet, SuppressUserConversions,
PartialOverloading);
} else {
- AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
- ExplicitTemplateArgs, Args,
- CandidateSet, SuppressUserConversions,
- PartialOverloading);
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+ cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
+ ObjectClassification, FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
+ }
+ } else {
+ // This branch handles both standalone functions and static methods.
+
+ // 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);
+ }
+ if (FunTmpl) {
+ AddTemplateOverloadCandidate(
+ FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs,
+ CandidateSet, SuppressUserConversions, PartialOverloading);
+ } else {
+ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
}
}
}
@@ -6583,9 +6629,15 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (Method->isMultiVersion() && Method->hasAttr<TargetAttr>() &&
+ !Method->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ }
}
-/// \brief Add a C++ member function template as a candidate to the candidate
+/// Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member
/// function template specialization.
void
@@ -6653,7 +6705,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
Conversions);
}
-/// \brief Add a C++ function template specialization as a candidate
+/// Add a C++ function template specialization as a candidate
/// in the candidate set, using template argument deduction to produce
/// an appropriate function template specialization.
void
@@ -6986,9 +7038,15 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (Conversion->isMultiVersion() && Conversion->hasAttr<TargetAttr>() &&
+ !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ }
}
-/// \brief Adds a conversion function template specialization
+/// Adds a conversion function template specialization
/// candidate to the overload set, using template argument deduction
/// to deduce the template arguments of the conversion function
/// template from the type that we are converting to (C++
@@ -7143,7 +7201,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
}
-/// \brief Add overload candidates for overloaded operators that are
+/// Add overload candidates for overloaded operators that are
/// member functions.
///
/// Add the overloaded operator candidates that are member functions
@@ -7279,18 +7337,18 @@ class BuiltinCandidateTypeSet {
/// used in the built-in candidates.
TypeSet EnumerationTypes;
- /// \brief The set of vector types that will be used in the built-in
+ /// The set of vector types that will be used in the built-in
/// candidates.
TypeSet VectorTypes;
- /// \brief A flag indicating non-record types are viable candidates
+ /// A flag indicating non-record types are viable candidates
bool HasNonRecordTypes;
- /// \brief A flag indicating whether either arithmetic or enumeration types
+ /// A flag indicating whether either arithmetic or enumeration types
/// were present in the candidate set.
bool HasArithmeticOrEnumeralTypes;
- /// \brief A flag indicating whether the nullptr type was present in the
+ /// A flag indicating whether the nullptr type was present in the
/// candidate set.
bool HasNullPtrType;
@@ -7543,7 +7601,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
}
}
-/// \brief Helper function for AddBuiltinOperatorCandidates() that adds
+/// Helper function for AddBuiltinOperatorCandidates() that adds
/// the volatile- and non-volatile-qualified assignment operators for the
/// given type to the candidate set.
static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
@@ -7621,7 +7679,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
namespace {
-/// \brief Helper class to manage the addition of builtin operator overload
+/// Helper class to manage the addition of builtin operator overload
/// candidates. It provides shared state and utility methods used throughout
/// the process, as well as a helper method to add each group of builtin
/// operator overloads from the standard to a candidate set.
@@ -7677,6 +7735,8 @@ class BuiltinOperatorOverloadBuilder {
ArithmeticTypes.push_back(S.Context.BoolTy);
ArithmeticTypes.push_back(S.Context.CharTy);
ArithmeticTypes.push_back(S.Context.WCharTy);
+ if (S.Context.getLangOpts().Char8)
+ ArithmeticTypes.push_back(S.Context.Char8Ty);
ArithmeticTypes.push_back(S.Context.Char16Ty);
ArithmeticTypes.push_back(S.Context.Char32Ty);
ArithmeticTypes.push_back(S.Context.SignedCharTy);
@@ -7692,7 +7752,7 @@ class BuiltinOperatorOverloadBuilder {
"Enough inline storage for all arithmetic types.");
}
- /// \brief Helper method to factor out the common pattern of adding overloads
+ /// Helper method to factor out the common pattern of adding overloads
/// for '++' and '--' builtin operators.
void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
bool HasVolatile,
@@ -7752,11 +7812,13 @@ public:
InitArithmeticTypes();
}
+ // Increment is deprecated for bool since C++17.
+ //
// C++ [over.built]p3:
//
- // For every pair (T, VQ), where T is an arithmetic type, and VQ
- // is either volatile or empty, there exist candidate operator
- // functions of the form
+ // For every pair (T, VQ), where T is an arithmetic type other
+ // than bool, and VQ is either volatile or empty, there exist
+ // candidate operator functions of the form
//
// VQ T& operator++(VQ T&);
// T operator++(VQ T&, int);
@@ -7773,10 +7835,16 @@ public:
if (!HasArithmeticOrEnumeralCandidateType)
return;
- for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
- Arith < NumArithmeticTypes; ++Arith) {
+ for (unsigned Arith = 0; Arith < NumArithmeticTypes; ++Arith) {
+ const auto TypeOfT = ArithmeticTypes[Arith];
+ if (TypeOfT == S.Context.BoolTy) {
+ if (Op == OO_MinusMinus)
+ continue;
+ if (Op == OO_PlusPlus && S.getLangOpts().CPlusPlus17)
+ continue;
+ }
addPlusPlusMinusMinusStyleOverloads(
- ArithmeticTypes[Arith],
+ TypeOfT,
VisibleTypeConversionsQuals.hasVolatile(),
VisibleTypeConversionsQuals.hasRestrict());
}
@@ -7948,7 +8016,8 @@ public:
// bool operator>=(T, T);
// bool operator==(T, T);
// bool operator!=(T, T);
- void addRelationalPointerOrEnumeralOverloads() {
+ // R operator<=>(T, T)
+ void addGenericBinaryPointerOrEnumeralOverloads() {
// C++ [over.match.oper]p3:
// [...]the built-in candidates include all of the candidate operator
// functions defined in 13.6 that, compared to the given operator, [...]
@@ -8021,7 +8090,6 @@ public:
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
-
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
@@ -8139,6 +8207,41 @@ public:
}
}
+ // C++2a [over.built]p14:
+ //
+ // For every integral type T there exists a candidate operator function
+ // of the form
+ //
+ // std::strong_ordering operator<=>(T, T)
+ //
+ // C++2a [over.built]p15:
+ //
+ // For every pair of floating-point types L and R, there exists a candidate
+ // operator function of the form
+ //
+ // std::partial_ordering operator<=>(L, R);
+ //
+ // FIXME: The current specification for integral types doesn't play nice with
+ // the direction of p0946r0, which allows mixed integral and unscoped-enum
+ // comparisons. Under the current spec this can lead to ambiguity during
+ // overload resolution. For example:
+ //
+ // enum A : int {a};
+ // auto x = (a <=> (long)42);
+ //
+ // error: call is ambiguous for arguments 'A' and 'long'.
+ // note: candidate operator<=>(int, int)
+ // note: candidate operator<=>(long, long)
+ //
+ // To avoid this error, this function deviates from the specification and adds
+ // the mixed overloads `operator<=>(L, R)` where L and R are promoted
+ // arithmetic types (the same as the generic relational overloads).
+ //
+ // For now this function acts as a placeholder.
+ void addThreeWayArithmeticOverloads() {
+ addGenericBinaryArithmeticOverloads();
+ }
+
// C++ [over.built]p17:
//
// For every pair of promoted integral types L and R, there
@@ -8707,12 +8810,14 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Greater:
case OO_LessEqual:
case OO_GreaterEqual:
- OpBuilder.addRelationalPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_Spaceship:
- llvm_unreachable("<=> expressions not supported yet");
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+ OpBuilder.addThreeWayArithmeticOverloads();
+ break;
case OO_Percent:
case OO_Caret:
@@ -8783,7 +8888,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
}
}
-/// \brief Add function candidates found via argument-dependent lookup
+/// Add function candidates found via argument-dependent lookup
/// to the set of overloading candidates.
///
/// This routine performs argument-dependent name lookup based on the
@@ -8889,6 +8994,47 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better;
}
+static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2) {
+ if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function ||
+ !Cand2.Function->isMultiVersion())
+ return false;
+
+ // If this is a cpu_dispatch/cpu_specific multiversion situation, prefer
+ // cpu_dispatch, else arbitrarily based on the identifiers.
+ bool Cand1CPUDisp = Cand1.Function->hasAttr<CPUDispatchAttr>();
+ bool Cand2CPUDisp = Cand2.Function->hasAttr<CPUDispatchAttr>();
+ const auto *Cand1CPUSpec = Cand1.Function->getAttr<CPUSpecificAttr>();
+ const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>();
+
+ if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec)
+ return false;
+
+ if (Cand1CPUDisp && !Cand2CPUDisp)
+ return true;
+ if (Cand2CPUDisp && !Cand1CPUDisp)
+ return false;
+
+ if (Cand1CPUSpec && Cand2CPUSpec) {
+ if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size())
+ return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size();
+
+ std::pair<CPUSpecificAttr::cpus_iterator, CPUSpecificAttr::cpus_iterator>
+ FirstDiff = std::mismatch(
+ Cand1CPUSpec->cpus_begin(), Cand1CPUSpec->cpus_end(),
+ Cand2CPUSpec->cpus_begin(),
+ [](const IdentifierInfo *LHS, const IdentifierInfo *RHS) {
+ return LHS->getName() == RHS->getName();
+ });
+
+ assert(FirstDiff.first != Cand1CPUSpec->cpus_end() &&
+ "Two different cpu-specific versions should not have the same "
+ "identifier list, otherwise they'd be the same decl!");
+ return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName();
+ }
+ llvm_unreachable("No way to get here unless both had cpu_dispatch");
+}
+
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool clang::isBetterOverloadCandidate(
@@ -9086,7 +9232,10 @@ bool clang::isBetterOverloadCandidate(
functionHasPassObjectSizeParams(Cand1.Function);
bool HasPS2 = Cand2.Function != nullptr &&
functionHasPassObjectSizeParams(Cand2.Function);
- return HasPS1 != HasPS2 && HasPS1;
+ if (HasPS1 != HasPS2 && HasPS1)
+ return true;
+
+ return isBetterMultiversionCandidate(Cand1, Cand2);
}
/// Determine whether two declarations are "equivalent" for the purposes of
@@ -9156,7 +9305,7 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
}
}
-/// \brief Computes the best viable function (C++ 13.3.3)
+/// Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
/// \param Loc The location of the function name (or operator symbol) for
@@ -9247,66 +9396,77 @@ enum OverloadCandidateKind {
oc_function,
oc_method,
oc_constructor,
- oc_function_template,
- oc_method_template,
- oc_constructor_template,
oc_implicit_default_constructor,
oc_implicit_copy_constructor,
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
- oc_inherited_constructor,
- oc_inherited_constructor_template
+ oc_inherited_constructor
+};
+
+enum OverloadCandidateSelect {
+ ocs_non_template,
+ ocs_template,
+ ocs_described_template,
};
-static OverloadCandidateKind
+static std::pair<OverloadCandidateKind, OverloadCandidateSelect>
ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn,
std::string &Description) {
- bool isTemplate = false;
+ bool isTemplate = Fn->isTemplateDecl() || Found->isTemplateDecl();
if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
isTemplate = true;
Description = S.getTemplateArgumentBindingsText(
- FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
+ FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
}
- if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
- if (!Ctor->isImplicit()) {
- if (isa<ConstructorUsingShadowDecl>(Found))
- return isTemplate ? oc_inherited_constructor_template
- : oc_inherited_constructor;
- else
- return isTemplate ? oc_constructor_template : oc_constructor;
- }
+ OverloadCandidateSelect Select = [&]() {
+ if (!Description.empty())
+ return ocs_described_template;
+ return isTemplate ? ocs_template : ocs_non_template;
+ }();
- if (Ctor->isDefaultConstructor())
- return oc_implicit_default_constructor;
+ OverloadCandidateKind Kind = [&]() {
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+ if (!Ctor->isImplicit()) {
+ if (isa<ConstructorUsingShadowDecl>(Found))
+ return oc_inherited_constructor;
+ else
+ return oc_constructor;
+ }
- if (Ctor->isMoveConstructor())
- return oc_implicit_move_constructor;
+ if (Ctor->isDefaultConstructor())
+ return oc_implicit_default_constructor;
- assert(Ctor->isCopyConstructor() &&
- "unexpected sort of implicit constructor");
- return oc_implicit_copy_constructor;
- }
+ if (Ctor->isMoveConstructor())
+ return oc_implicit_move_constructor;
- if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
- // This actually gets spelled 'candidate function' for now, but
- // it doesn't hurt to split it out.
- if (!Meth->isImplicit())
- return isTemplate ? oc_method_template : oc_method;
+ assert(Ctor->isCopyConstructor() &&
+ "unexpected sort of implicit constructor");
+ return oc_implicit_copy_constructor;
+ }
- if (Meth->isMoveAssignmentOperator())
- return oc_implicit_move_assignment;
+ if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
+ // This actually gets spelled 'candidate function' for now, but
+ // it doesn't hurt to split it out.
+ if (!Meth->isImplicit())
+ return oc_method;
- if (Meth->isCopyAssignmentOperator())
- return oc_implicit_copy_assignment;
+ if (Meth->isMoveAssignmentOperator())
+ return oc_implicit_move_assignment;
- assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
- return oc_method;
- }
+ if (Meth->isCopyAssignmentOperator())
+ return oc_implicit_copy_assignment;
- return isTemplate ? oc_function_template : oc_function;
+ assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
+ return oc_method;
+ }
+
+ return oc_function;
+ }();
+
+ return std::make_pair(Kind, Select);
}
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
@@ -9332,7 +9492,7 @@ static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
return true;
}
-/// \brief Returns true if we can take the address of the function.
+/// Returns true if we can take the address of the function.
///
/// \param Complain - If true, we'll emit a diagnostic
/// \param InOverloadResolution - For the purposes of emitting a diagnostic, are
@@ -9394,11 +9554,16 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
QualType DestType, bool TakingAddress) {
if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
return;
+ if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
+ !Fn->getAttr<TargetAttr>()->isDefaultVersion())
+ return;
std::string FnDesc;
- OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair =
+ ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
- << (unsigned) K << Fn << FnDesc;
+ << (unsigned)KSPair.first << (unsigned)KSPair.second
+ << Fn << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
@@ -9472,7 +9637,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
}
std::string FnDesc;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
@@ -9487,9 +9652,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
DeclarationName Name = cast<OverloadExpr>(E)->getName();
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << ToTy << Name << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy
+ << Name << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9516,43 +9681,38 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getAddressSpaceAttributePrintValue()
- << ToQs.getAddressSpaceAttributePrintValue()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
+ << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
+ << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.hasUnaligned() != ToQs.hasUnaligned()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_unaligned)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << FromQs.hasUnaligned() << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.hasUnaligned() << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9562,14 +9722,14 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (isObjectArgument) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << (CVR - 1);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << (CVR - 1);
} else {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << (CVR - 1) << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << (CVR - 1) << I + 1;
}
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
@@ -9579,9 +9739,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
// telling the user that it has type void is not useful.
if (FromExpr && isa<InitListExpr>(FromExpr)) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9595,10 +9755,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (TempFromTy->isIncompleteType()) {
// Emit the generic diagnostic and, optionally, add the hints to it.
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1
- << (unsigned) (Cand->Fix.Kind);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1
+ << (unsigned)(Cand->Fix.Kind);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
@@ -9636,21 +9796,19 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
ToTy.getNonReferenceType().getCanonicalType() ==
FromTy.getNonReferenceType().getCanonicalType()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << (unsigned) isObjectArgument << I + 1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (unsigned)isObjectArgument << I + 1
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange());
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
}
if (BaseToDerivedConversion) {
- S.Diag(Fn->getLocation(),
- diag::note_ovl_candidate_bad_base_to_derived_conv)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << (BaseToDerivedConversion - 1)
- << FromTy << ToTy << I+1;
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv)
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << (BaseToDerivedConversion - 1) << FromTy << ToTy << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9661,9 +9819,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
Qualifiers ToQs = CToTy.getQualifiers();
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9675,10 +9833,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
// Emit the generic diagnostic and, optionally, add the hints to it.
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
- FDiag << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I + 1
- << (unsigned) (Cand->Fix.Kind);
+ FDiag << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1
+ << (unsigned)(Cand->Fix.Kind);
// If we can fix the conversion, suggest the FixIts.
for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
@@ -9751,17 +9909,18 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
}
std::string Description;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Found, Fn, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
- << mode << Fn->getParamDecl(0) << NumFormalArgs;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << Description << mode << Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
- << mode << modeCount << NumFormalArgs;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << Description << mode << modeCount << NumFormalArgs;
+
MaybeEmitInheritedConstructorNote(S, Found);
}
@@ -9802,6 +9961,17 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
return;
}
+ case Sema::TDK_IncompletePack: {
+ assert(ParamD && "no parameter found for incomplete deduction result");
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_incomplete_deduction_pack)
+ << ParamD->getDeclName()
+ << (DeductionFailure.getFirstArg()->pack_size() + 1)
+ << *DeductionFailure.getFirstArg();
+ MaybeEmitInheritedConstructorNote(S, Found);
+ return;
+ }
+
case Sema::TDK_Underqualified: {
assert(ParamD && "no parameter found for bad qualifiers deduction result");
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
@@ -10036,11 +10206,13 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
- << (unsigned)FnKind << CalleeTarget << CallerTarget;
+ << (unsigned)FnKindPair.first << (unsigned)ocs_non_template
+ << FnDesc /* Ignored */
+ << CalleeTarget << CallerTarget;
// This could be an implicit constructor for which we could not infer the
// target due to a collsion. Diagnose that case.
@@ -10049,7 +10221,7 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CXXRecordDecl *ParentClass = Meth->getParent();
Sema::CXXSpecialMember CSM;
- switch (FnKind) {
+ switch (FnKindPair.first) {
default:
return;
case oc_implicit_default_constructor:
@@ -10121,12 +10293,12 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
if (Cand->Viable) {
if (Fn->isDeleted() || S.isFunctionConsideredUnavailable(Fn)) {
std::string FnDesc;
- OverloadCandidateKind FnKind =
- ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
- << FnKind << FnDesc
- << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -10195,6 +10367,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
assert(!Available);
break;
}
+ case ovl_non_default_multiversion_function:
+ // Do nothing, these should simply be ignored.
+ break;
}
}
@@ -10276,6 +10451,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
case Sema::TDK_Invalid:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
return 1;
case Sema::TDK_Underqualified:
@@ -10512,9 +10688,8 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
}
-/// PrintOverloadCandidates - When overload resolution fails, prints
-/// diagnostic messages containing the candidates in the candidate
-/// set.
+/// When overload resolution fails, prints diagnostic messages containing the
+/// candidates in the candidate set.
void OverloadCandidateSet::NoteCandidates(
Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
StringRef Opc, SourceLocation OpLoc,
@@ -10661,8 +10836,8 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
// in general, want to list every possible builtin candidate.
}
- std::sort(Cands.begin(), Cands.end(),
- CompareTemplateSpecCandidatesForDisplay(S));
+ llvm::sort(Cands.begin(), Cands.end(),
+ CompareTemplateSpecCandidatesForDisplay(S));
// FIXME: Perhaps rename OverloadsShown and getShowOverloads()
// for generalization purposes (?).
@@ -10931,6 +11106,11 @@ private:
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext))
if (!Caller->isImplicit() && !S.IsAllowedCUDACall(Caller, FunDecl))
return false;
+ if (FunDecl->isMultiVersion()) {
+ const auto *TA = FunDecl->getAttr<TargetAttr>();
+ if (TA && !TA->isDefaultVersion())
+ return false;
+ }
// If any candidate has a placeholder return type, trigger its deduction
// now.
@@ -11012,9 +11192,9 @@ private:
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
SourceExpr->getLocStart(), S.PDiag(),
S.PDiag(diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName(),
+ << Matches[0].second->getDeclName(),
S.PDiag(diag::note_ovl_candidate)
- << (unsigned)oc_function_template,
+ << (unsigned)oc_function << (unsigned)ocs_described_template,
Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
@@ -11176,7 +11356,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
return Fn;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// Given an expression that refers to an overloaded function, try to
/// resolve that function to a single function that can have its address taken.
/// This will modify `Pair` iff it returns non-null.
///
@@ -11212,7 +11392,7 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
return Result;
}
-/// \brief Given an overloaded function, tries to turn it into a non-overloaded
+/// Given an overloaded function, tries to turn it into a non-overloaded
/// function reference using resolveAddressOfOnlyViableOverloadCandidate. This
/// will perform access checks, diagnose the use of the resultant decl, and, if
/// requested, potentially perform a function-to-pointer decay.
@@ -11226,7 +11406,8 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
DeclAccessPair DAP;
FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP);
- if (!Found)
+ if (!Found || Found->isCPUDispatchMultiVersion() ||
+ Found->isCPUSpecificMultiVersion())
return false;
// Emitting multiple diagnostics for a function that is both inaccessible and
@@ -11242,7 +11423,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
return true;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// Given an expression that refers to an overloaded function, try to
/// resolve that overloaded function expression down to a single function.
///
/// This routine can only resolve template-ids that refer to a single function
@@ -11411,7 +11592,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
return true;
}
-/// \brief Add a single candidate to the overload set.
+/// Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
@@ -11450,7 +11631,7 @@ static void AddOverloadedCallCandidate(Sema &S,
assert(!KnownValid && "unhandled case in overloaded call candidate");
}
-/// \brief Add the overload candidates named by callee and/or found by argument
+/// Add the overload candidates named by callee and/or found by argument
/// dependent lookup to the given overload set.
void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
ArrayRef<Expr *> Args,
@@ -11742,7 +11923,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
RParenLoc);
}
-/// \brief Constructs and populates an OverloadedCandidateSet from
+/// Constructs and populates an OverloadedCandidateSet from
/// the given function.
/// \returns true when an the ExprResult output parameter has been set.
bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
@@ -11882,7 +12063,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
<< Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
- // We emitted an error for the unvailable/deleted function call but keep
+ // We emitted an error for the unavailable/deleted function call but keep
// the call in the AST.
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
@@ -11948,7 +12129,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
(Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
}
-/// \brief Create a unary operation that may resolve to an overloaded
+/// Create a unary operation that may resolve to an overloaded
/// operator.
///
/// \param OpLoc The location of the operator itself (e.g., '*').
@@ -11994,7 +12175,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Input->isTypeDependent()) {
if (Fns.empty())
return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc);
+ VK_RValue, OK_Ordinary, OpLoc, false);
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn
@@ -12093,7 +12274,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
// break out so that we will build the appropriate built-in
// operator node.
ExprResult InputRes = PerformImplicitConversion(
- Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing);
+ Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing,
+ CCK_ForBuiltinOverloadedOp);
if (InputRes.isInvalid())
return ExprError();
Input = InputRes.get();
@@ -12139,7 +12321,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
-/// \brief Create a binary operation that may resolve to an overloaded
+/// Create a binary operation that may resolve to an overloaded
/// operator.
///
/// \param OpLoc The location of the operator itself (e.g., '+').
@@ -12337,16 +12519,16 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- ExprResult ArgsRes0 =
- PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
- Best->Conversions[0], AA_Passing);
+ ExprResult ArgsRes0 = PerformImplicitConversion(
+ Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
- ExprResult ArgsRes1 =
- PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
- Best->Conversions[1], AA_Passing);
+ ExprResult ArgsRes1 = PerformImplicitConversion(
+ Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
@@ -12362,7 +12544,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Comma)
break;
- // For class as left operand for assignment or compound assigment
+ // For class as left operand for assignment or compound assignment
// operator do not fall through to handling in built-in, but report that
// no overloaded assignment operator found
ExprResult Result = ExprError();
@@ -12549,16 +12731,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- ExprResult ArgsRes0 =
- PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
- Best->Conversions[0], AA_Passing);
+ ExprResult ArgsRes0 = PerformImplicitConversion(
+ Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
- ExprResult ArgsRes1 =
- PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
- Best->Conversions[1], AA_Passing);
+ ExprResult ArgsRes1 = PerformImplicitConversion(
+ Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
@@ -13524,7 +13706,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc());
+ UnOp->getOperatorLoc(), false);
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -13535,7 +13717,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
Context.getPointerType(SubExpr->getType()),
VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc());
+ UnOp->getOperatorLoc(), false);
}
// C++ [except.spec]p17:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index 58980be64a30..a8af75d87c8d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -132,7 +132,8 @@ namespace {
uop->getType(),
uop->getValueKind(),
uop->getObjectKind(),
- uop->getOperatorLoc());
+ uop->getOperatorLoc(),
+ uop->canOverflow());
}
if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
@@ -189,11 +190,12 @@ namespace {
Sema &S;
unsigned ResultIndex;
SourceLocation GenericLoc;
+ bool IsUnique;
SmallVector<Expr *, 4> Semantics;
- PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
+ PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
: S(S), ResultIndex(PseudoObjectExpr::NoResult),
- GenericLoc(genericLoc) {}
+ GenericLoc(genericLoc), IsUnique(IsUnique) {}
virtual ~PseudoOpBuilder() {}
@@ -207,6 +209,9 @@ namespace {
assert(ResultIndex == PseudoObjectExpr::NoResult);
ResultIndex = Semantics.size();
Semantics.push_back(resultExpr);
+ // An OVE is not unique if it is used as the result expression.
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+ OVE->setIsUnique(false);
}
ExprResult buildRValueOperation(Expr *op);
@@ -226,6 +231,9 @@ namespace {
void setResultToLastSemantic() {
assert(ResultIndex == PseudoObjectExpr::NoResult);
ResultIndex = Semantics.size() - 1;
+ // An OVE is not unique if it is used as the result expression.
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+ OVE->setIsUnique(false);
}
/// Return true if assignments have a non-void result.
@@ -245,7 +253,7 @@ namespace {
virtual ExprResult buildGet() = 0;
virtual ExprResult buildSet(Expr *, SourceLocation,
bool captureSetValueAsResult) = 0;
- /// \brief Should the result of an assignment be the formal result of the
+ /// Should the result of an assignment be the formal result of the
/// setter call or the value that was passed to the setter?
///
/// Different pseudo-object language features use different language rules
@@ -273,10 +281,10 @@ namespace {
Selector GetterSelector;
public:
- ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
- SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
- Setter(nullptr) {
+ ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),
+ RefExpr(refExpr), SyntacticRefExpr(nullptr),
+ InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {
}
ExprResult buildRValueOperation(Expr *op);
@@ -308,16 +316,15 @@ namespace {
OpaqueValueExpr *InstanceKey;
ObjCMethodDecl *AtIndexGetter;
Selector AtIndexGetterSelector;
-
+
ObjCMethodDecl *AtIndexSetter;
Selector AtIndexSetterSelector;
-
+
public:
- ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr),
- InstanceBase(nullptr), InstanceKey(nullptr),
- AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
+ ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+ RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),
+ AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
ExprResult buildRValueOperation(Expr *op);
ExprResult buildAssignmentOperation(Scope *Sc,
@@ -341,11 +348,11 @@ namespace {
MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
public:
- MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr), InstanceBase(nullptr) {}
- MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
- : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+ MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+ RefExpr(refExpr), InstanceBase(nullptr) {}
+ MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
InstanceBase(nullptr) {
RefExpr = getBaseMSProperty(refExpr);
}
@@ -360,11 +367,13 @@ namespace {
/// Capture the given expression in an OpaqueValueExpr.
OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
// Make a new OVE whose source is the given expression.
- OpaqueValueExpr *captured =
+ OpaqueValueExpr *captured =
new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
e->getValueKind(), e->getObjectKind(),
e);
-
+ if (IsUnique)
+ captured->setIsUnique(true);
+
// Make sure we bind that in the semantics.
addSemanticExpr(captured);
return captured;
@@ -380,7 +389,7 @@ OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
assert(ResultIndex == PseudoObjectExpr::NoResult);
// If the expression hasn't already been captured, just capture it
- // and set the new semantic
+ // and set the new semantic
if (!isa<OpaqueValueExpr>(e)) {
OpaqueValueExpr *cap = capture(e);
setResultToLastSemantic();
@@ -396,6 +405,8 @@ OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
if (e == Semantics[index]) break;
}
ResultIndex = index;
+ // An OVE is not unique if it is used as the result expression.
+ cast<OpaqueValueExpr>(e)->setIsUnique(false);
return cast<OpaqueValueExpr>(e);
}
@@ -527,9 +538,12 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
(result.get()->isTypeDependent() || CanCaptureValue(result.get())))
setResultToLastSemantic();
- UnaryOperator *syntactic =
- new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
- VK_LValue, OK_Ordinary, opcLoc);
+ UnaryOperator *syntactic = new (S.Context) UnaryOperator(
+ syntacticOp, opcode, resultType, VK_LValue, OK_Ordinary, opcLoc,
+ !resultType->isDependentType()
+ ? S.Context.getTypeSize(resultType) >=
+ S.Context.getTypeSize(S.Context.IntTy)
+ : false);
return complete(syntactic);
}
@@ -604,11 +618,11 @@ bool ObjCPropertyOpBuilder::findGetter() {
// Must build the getter selector the hard way.
ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
assert(setter && "both setter and getter are null - cannot happen");
- IdentifierInfo *setterName =
+ IdentifierInfo *setterName =
setter->getSelector().getIdentifierInfoForSlot(0);
IdentifierInfo *getterName =
&S.Context.Idents.get(setterName->getName().substr(3));
- GetterSelector =
+ GetterSelector =
S.PP.getSelectorTable().getNullarySelector(getterName);
return false;
}
@@ -622,7 +636,7 @@ bool ObjCPropertyOpBuilder::findGetter() {
/// Try to find the most accurate setter declaration for the property
/// reference.
///
-/// \return true if a setter was found, in which case Setter
+/// \return true if a setter was found, in which case Setter
bool ObjCPropertyOpBuilder::findSetter(bool warn) {
// For implicit properties, just trust the lookup we already did.
if (RefExpr->isImplicitProperty()) {
@@ -961,11 +975,11 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
}
ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
- if (isWeakProperty() &&
+ if (isWeakProperty() && !S.isUnevaluatedContext() &&
!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
SyntacticForm->getLocStart()))
- S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
- SyntacticRefExpr->isMessagingGetter());
+ S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
+ SyntacticRefExpr->isMessagingGetter());
return PseudoOpBuilder::complete(SyntacticForm);
}
@@ -973,9 +987,9 @@ ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
// ObjCSubscript build stuff.
//
-/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
+/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
/// conversion.
-/// FIXME. Remove this routine if it is proven that no additional
+/// FIXME. Remove this routine if it is proven that no additional
/// specifity is needed.
ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
@@ -993,21 +1007,21 @@ ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
// There must be a method to do the Index'ed assignment.
if (!findAtIndexSetter())
return ExprError();
-
+
// Verify that we can do a compound assignment.
if (opcode != BO_Assign && !findAtIndexGetter())
return ExprError();
-
+
ExprResult result =
PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
if (result.isInvalid()) return ExprError();
-
+
// Various warnings about objc Index'ed assignments in ARC.
if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
}
-
+
return result;
}
@@ -1035,15 +1049,15 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
return syntacticBase;
}
-/// CheckSubscriptingKind - This routine decide what type
+/// CheckSubscriptingKind - This routine decide what type
/// of indexing represented by "FromE" is being done.
-Sema::ObjCSubscriptKind
+Sema::ObjCSubscriptKind
Sema::CheckSubscriptingKind(Expr *FromE) {
// If the expression already has integral or enumeration type, we're golden.
QualType T = FromE->getType();
if (T->isIntegralOrEnumerationType())
return OS_Array;
-
+
// If we don't have a class type in C++, there's no way we can get an
// expression of integral or enumeration type.
const RecordType *RecordTy = T->getAs<RecordType>();
@@ -1052,7 +1066,7 @@ Sema::ObjCSubscriptKind
// All other scalar cases are assumed to be dictionary indexing which
// caller handles, with diagnostics if needed.
return OS_Dictionary;
- if (!getLangOpts().CPlusPlus ||
+ if (!getLangOpts().CPlusPlus ||
!RecordTy || RecordTy->isIncompleteType()) {
// No indexing can be done. Issue diagnostics and quit.
const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
@@ -1064,12 +1078,12 @@ Sema::ObjCSubscriptKind
<< T;
return OS_Error;
}
-
+
// We must have a complete class type.
- if (RequireCompleteType(FromE->getExprLoc(), T,
+ if (RequireCompleteType(FromE->getExprLoc(), T,
diag::err_objc_index_incomplete_class_type, FromE))
return OS_Error;
-
+
// Look for a conversion to an integral, enumeration type, or
// objective-C pointer type.
int NoIntegrals=0, NoObjCIdPointers=0;
@@ -1111,17 +1125,17 @@ Sema::ObjCSubscriptKind
/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
/// objects used as dictionary subscript key objects.
-static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
+static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
Expr *Key) {
if (ContainerT.isNull())
return;
// dictionary subscripting.
// - (id)objectForKeyedSubscript:(id)key;
IdentifierInfo *KeyIdents[] = {
- &S.Context.Idents.get("objectForKeyedSubscript")
+ &S.Context.Idents.get("objectForKeyedSubscript")
};
Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
- ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
+ ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
true /*instance*/);
if (!Getter)
return;
@@ -1133,25 +1147,25 @@ static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
if (AtIndexGetter)
return true;
-
+
Expr *BaseExpr = RefExpr->getBaseExpr();
QualType BaseT = BaseExpr->getType();
-
+
QualType ResultType;
if (const ObjCObjectPointerType *PTy =
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
}
- Sema::ObjCSubscriptKind Res =
+ Sema::ObjCSubscriptKind Res =
S.CheckSubscriptingKind(RefExpr->getKeyExpr());
if (Res == Sema::OS_Error) {
if (S.getLangOpts().ObjCAutoRefCount)
- CheckKeyForObjCARCConversion(S, ResultType,
+ CheckKeyForObjCARCConversion(S, ResultType,
RefExpr->getKeyExpr());
return false;
}
bool arrayRef = (Res == Sema::OS_Array);
-
+
if (ResultType.isNull()) {
S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
<< BaseExpr->getType() << arrayRef;
@@ -1161,24 +1175,24 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
// dictionary subscripting.
// - (id)objectForKeyedSubscript:(id)key;
IdentifierInfo *KeyIdents[] = {
- &S.Context.Idents.get("objectForKeyedSubscript")
+ &S.Context.Idents.get("objectForKeyedSubscript")
};
AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
}
else {
// - (id)objectAtIndexedSubscript:(size_t)index;
IdentifierInfo *KeyIdents[] = {
- &S.Context.Idents.get("objectAtIndexedSubscript")
+ &S.Context.Idents.get("objectAtIndexedSubscript")
};
-
+
AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
}
-
- AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
+
+ AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
true /*instance*/);
-
+
if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
- AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
+ AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
SourceLocation(), AtIndexGetterSelector,
S.Context.getObjCIdType() /*ReturnType*/,
nullptr /*TypeSourceInfo */,
@@ -1206,20 +1220,20 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
<< BaseExpr->getType() << 0 << arrayRef;
return false;
}
- AtIndexGetter =
- S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
- RefExpr->getSourceRange(),
+ AtIndexGetter =
+ S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
+ RefExpr->getSourceRange(),
true);
}
-
+
if (AtIndexGetter) {
QualType T = AtIndexGetter->parameters()[0]->getType();
if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
(!arrayRef && !T->isObjCObjectPointerType())) {
- S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
+ S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
arrayRef ? diag::err_objc_subscript_index_type
: diag::err_objc_subscript_key_type) << T;
- S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
+ S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
diag::note_parameter_type) << T;
return false;
}
@@ -1237,32 +1251,32 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
if (AtIndexSetter)
return true;
-
+
Expr *BaseExpr = RefExpr->getBaseExpr();
QualType BaseT = BaseExpr->getType();
-
+
QualType ResultType;
if (const ObjCObjectPointerType *PTy =
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
}
-
- Sema::ObjCSubscriptKind Res =
+
+ Sema::ObjCSubscriptKind Res =
S.CheckSubscriptingKind(RefExpr->getKeyExpr());
if (Res == Sema::OS_Error) {
if (S.getLangOpts().ObjCAutoRefCount)
- CheckKeyForObjCARCConversion(S, ResultType,
+ CheckKeyForObjCARCConversion(S, ResultType,
RefExpr->getKeyExpr());
return false;
}
bool arrayRef = (Res == Sema::OS_Array);
-
+
if (ResultType.isNull()) {
S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
<< BaseExpr->getType() << arrayRef;
return false;
}
-
+
if (!arrayRef) {
// dictionary subscripting.
// - (void)setObject:(id)object forKeyedSubscript:(id)key;
@@ -1280,7 +1294,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
};
AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
}
- AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
+ AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
true /*instance*/);
if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
@@ -1314,35 +1328,35 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
Params.push_back(key);
AtIndexSetter->setMethodParams(S.Context, Params, None);
}
-
+
if (!AtIndexSetter) {
if (!BaseT->isObjCIdType()) {
- S.Diag(BaseExpr->getExprLoc(),
+ S.Diag(BaseExpr->getExprLoc(),
diag::err_objc_subscript_method_not_found)
<< BaseExpr->getType() << 1 << arrayRef;
return false;
}
- AtIndexSetter =
- S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
- RefExpr->getSourceRange(),
+ AtIndexSetter =
+ S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
+ RefExpr->getSourceRange(),
true);
}
-
+
bool err = false;
if (AtIndexSetter && arrayRef) {
QualType T = AtIndexSetter->parameters()[1]->getType();
if (!T->isIntegralOrEnumerationType()) {
- S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
+ S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
diag::err_objc_subscript_index_type) << T;
- S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
+ S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
diag::note_parameter_type) << T;
err = true;
}
T = AtIndexSetter->parameters()[0]->getType();
if (!T->isObjCObjectPointerType()) {
- S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
+ S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
diag::err_objc_subscript_object_type) << T << arrayRef;
- S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
+ S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
diag::note_parameter_type) << T;
err = true;
}
@@ -1357,7 +1371,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
else
S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
diag::err_objc_subscript_dic_object_type) << T;
- S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
+ S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
diag::note_parameter_type) << T;
err = true;
}
@@ -1371,13 +1385,13 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
ExprResult ObjCSubscriptOpBuilder::buildGet() {
if (!findAtIndexGetter())
return ExprError();
-
+
QualType receiverType = InstanceBase->getType();
-
+
// Build a message-send.
ExprResult msg;
Expr *Index = InstanceKey;
-
+
// Arguments.
Expr *args[] = { Index };
assert(InstanceBase);
@@ -1403,17 +1417,17 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);
QualType receiverType = InstanceBase->getType();
Expr *Index = InstanceKey;
-
+
// Arguments.
Expr *args[] = { op, Index };
-
+
// Build a message-send.
ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
GenericLoc,
AtIndexSetterSelector,
AtIndexSetter,
MultiExprArg(args, 2));
-
+
if (!msg.isInvalid() && captureSetValueAsResult) {
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
@@ -1421,7 +1435,7 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
if (CanCaptureValue(arg))
msgExpr->setArg(0, captureValueAsResult(arg));
}
-
+
return msg;
}
@@ -1524,20 +1538,20 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
Expr *opaqueRef = E->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
}
else if (ObjCSubscriptRefExpr *refExpr
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- ObjCSubscriptOpBuilder builder(*this, refExpr);
+ ObjCSubscriptOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
} else if (MSPropertySubscriptExpr *RefExpr =
dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, true);
return Builder.buildRValueOperation(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1550,24 +1564,24 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
// Do nothing if the operand is dependent.
if (op->isTypeDependent())
return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
- VK_RValue, OK_Ordinary, opcLoc);
+ VK_RValue, OK_Ordinary, opcLoc, false);
assert(UnaryOperator::isIncrementDecrementOp(opcode));
Expr *opaqueRef = op->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, false);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
Diag(opcLoc, diag::err_illegal_container_subscripting_op);
return ExprError();
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, false);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else if (MSPropertySubscriptExpr *RefExpr
= dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, false);
return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1590,22 +1604,23 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
RHS = result.get();
}
+ bool IsSimpleAssign = opcode == BO_Assign;
Expr *opaqueRef = LHS->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (ObjCSubscriptRefExpr *refExpr
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- ObjCSubscriptOpBuilder builder(*this, refExpr);
+ ObjCSubscriptOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertySubscriptExpr *RefExpr
= dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, IsSimpleAssign);
return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1633,9 +1648,9 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
Expr *syntax = E->getSyntacticForm();
if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
- return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
- uop->getValueKind(), uop->getObjectKind(),
- uop->getOperatorLoc());
+ return new (Context) UnaryOperator(
+ op, uop->getOpcode(), uop->getType(), uop->getValueKind(),
+ uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow());
} else if (CompoundAssignOperator *cop
= dyn_cast<CompoundAssignOperator>(syntax)) {
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 1ebc36716a88..377e2c4dfa23 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -121,7 +121,7 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
}
}
-/// \brief Diagnose unused comparisons, both builtin and overloaded operators.
+/// Diagnose unused comparisons, both builtin and overloaded operators.
/// For '==' and '!=', suggest fixits for '=' or '|='.
///
/// Adding a cast to void (or other expression wrappers) will prevent the
@@ -216,7 +216,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// expression is a call to a function with the warn_unused_result attribute,
// we warn no matter the location. Because of the order in which the various
// checks need to happen, we factor out the macro-related test here.
- bool ShouldSuppress =
+ bool ShouldSuppress =
SourceMgr.isMacroBodyExpansion(ExprLoc) ||
SourceMgr.isInSystemMacro(ExprLoc);
@@ -337,8 +337,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2);
}
-void Sema::ActOnStartOfCompoundStmt() {
- PushCompoundScope();
+void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) {
+ PushCompoundScope(IsStmtExpr);
}
void Sema::ActOnFinishOfCompoundStmt() {
@@ -392,65 +392,79 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
return CompoundStmt::Create(Context, Elts, L, R);
}
+ExprResult
+Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
+ if (!Val.get())
+ return Val;
+
+ if (DiagnoseUnexpandedParameterPack(Val.get()))
+ return ExprError();
+
+ // If we're not inside a switch, let the 'case' statement handling diagnose
+ // this. Just clean up after the expression as best we can.
+ if (!getCurFunction()->SwitchStack.empty()) {
+ Expr *CondExpr =
+ getCurFunction()->SwitchStack.back().getPointer()->getCond();
+ if (!CondExpr)
+ return ExprError();
+ QualType CondType = CondExpr->getType();
+
+ auto CheckAndFinish = [&](Expr *E) {
+ if (CondType->isDependentType() || E->isTypeDependent())
+ return ExprResult(E);
+
+ if (getLangOpts().CPlusPlus11) {
+ // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+ // constant expression of the promoted type of the switch condition.
+ llvm::APSInt TempVal;
+ return CheckConvertedConstantExpression(E, CondType, TempVal,
+ CCEK_CaseValue);
+ }
+
+ ExprResult ER = E;
+ if (!E->isValueDependent())
+ ER = VerifyIntegerConstantExpression(E);
+ if (!ER.isInvalid())
+ ER = DefaultLvalueConversion(ER.get());
+ if (!ER.isInvalid())
+ ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
+ return ER;
+ };
+
+ ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
+ if (Converted.get() == Val.get())
+ Converted = CheckAndFinish(Val.get());
+ if (Converted.isInvalid())
+ return ExprError();
+ Val = Converted;
+ }
+
+ return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
+ getLangOpts().CPlusPlus11);
+}
+
StmtResult
-Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
- SourceLocation DotDotDotLoc, Expr *RHSVal,
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
+ SourceLocation DotDotDotLoc, ExprResult RHSVal,
SourceLocation ColonLoc) {
- assert(LHSVal && "missing expression in case statement");
+ assert((LHSVal.isInvalid() || LHSVal.get()) && "missing LHS value");
+ assert((DotDotDotLoc.isInvalid() ? RHSVal.isUnset()
+ : RHSVal.isInvalid() || RHSVal.get()) &&
+ "missing RHS value");
if (getCurFunction()->SwitchStack.empty()) {
Diag(CaseLoc, diag::err_case_not_in_switch);
return StmtError();
}
- ExprResult LHS =
- CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) {
- if (!getLangOpts().CPlusPlus11)
- return VerifyIntegerConstantExpression(E);
- if (Expr *CondExpr =
- getCurFunction()->SwitchStack.back()->getCond()) {
- QualType CondType = CondExpr->getType();
- llvm::APSInt TempVal;
- return CheckConvertedConstantExpression(E, CondType, TempVal,
- CCEK_CaseValue);
- }
- return ExprError();
- });
- if (LHS.isInvalid())
+ if (LHSVal.isInvalid() || RHSVal.isInvalid()) {
+ getCurFunction()->SwitchStack.back().setInt(true);
return StmtError();
- LHSVal = LHS.get();
-
- if (!getLangOpts().CPlusPlus11) {
- // C99 6.8.4.2p3: The expression shall be an integer constant.
- // However, GCC allows any evaluatable integer expression.
- if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) {
- LHSVal = VerifyIntegerConstantExpression(LHSVal).get();
- if (!LHSVal)
- return StmtError();
- }
-
- // GCC extension: The expression shall be an integer constant.
-
- if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) {
- RHSVal = VerifyIntegerConstantExpression(RHSVal).get();
- // Recover from an error by just forgetting about it.
- }
}
- LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11);
- if (LHS.isInvalid())
- return StmtError();
-
- auto RHS = RHSVal ? ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11)
- : ExprResult();
- if (RHS.isInvalid())
- return StmtError();
-
CaseStmt *CS = new (Context)
- CaseStmt(LHS.get(), RHS.get(), CaseLoc, DotDotDotLoc, ColonLoc);
- getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
+ CaseStmt(LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc);
+ getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
return CS;
}
@@ -473,7 +487,7 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
}
DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
- getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
+ getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(DS);
return DS;
}
@@ -557,7 +571,7 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
return StmtError();
if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DiagnoseUnusedExprResult(thenStmt);
DiagnoseUnusedExprResult(elseStmt);
@@ -679,20 +693,44 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {
if (CondResult.isInvalid())
return ExprError();
+ // FIXME: PerformContextualImplicitConversion doesn't always tell us if it
+ // failed and produced a diagnostic.
+ Cond = CondResult.get();
+ if (!Cond->isTypeDependent() &&
+ !Cond->getType()->isIntegralOrEnumerationType())
+ return ExprError();
+
// C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
- return UsualUnaryConversions(CondResult.get());
+ return UsualUnaryConversions(Cond);
}
StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
Stmt *InitStmt, ConditionResult Cond) {
- if (Cond.isInvalid())
- return StmtError();
+ Expr *CondExpr = Cond.get().second;
+ assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
- getCurFunction()->setHasBranchIntoScope();
+ if (CondExpr && !CondExpr->isTypeDependent()) {
+ // We have already converted the expression to an integral or enumeration
+ // type, when we parsed the switch condition. If we don't have an
+ // appropriate type now, enter the switch scope but remember that it's
+ // invalid.
+ assert(CondExpr->getType()->isIntegralOrEnumerationType() &&
+ "invalid condition type");
+ if (CondExpr->isKnownToHaveBooleanValue()) {
+ // switch(bool_expr) {...} is often a programmer error, e.g.
+ // switch(n && mask) { ... } // Doh - should be "n & mask".
+ // One can always use an if statement instead of switch(bool_expr).
+ Diag(SwitchLoc, diag::warn_bool_switch_condition)
+ << CondExpr->getSourceRange();
+ }
+ }
+
+ setFunctionHasBranchIntoScope();
SwitchStmt *SS = new (Context)
- SwitchStmt(Context, InitStmt, Cond.get().first, Cond.get().second);
- getCurFunction()->SwitchStack.push_back(SS);
+ SwitchStmt(Context, InitStmt, Cond.get().first, CondExpr);
+ getCurFunction()->SwitchStack.push_back(
+ FunctionScopeInfo::SwitchInfo(SS, false));
return SS;
}
@@ -705,6 +743,10 @@ static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
/// type.
static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
unsigned UnpromotedWidth, bool UnpromotedSign) {
+ // In C++11 onwards, this is checked by the language rules.
+ if (S.getLangOpts().CPlusPlus11)
+ return;
+
// If the case value was signed and negative and the switch expression is
// unsigned, don't bother to warn: this is implementation-defined behavior.
// FIXME: Introduce a second, default-ignored warning for this case?
@@ -759,7 +801,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond,
const Expr *Case) {
- QualType CondType = GetTypeBeforeIntegralPromotion(Cond);
+ QualType CondType = Cond->getType();
QualType CaseType = Case->getType();
const EnumType *CondEnumType = CondType->getAs<EnumType>();
@@ -787,7 +829,8 @@ StmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Stmt *BodyStmt) {
SwitchStmt *SS = cast<SwitchStmt>(Switch);
- assert(SS == getCurFunction()->SwitchStack.back() &&
+ bool CaseListIsIncomplete = getCurFunction()->SwitchStack.back().getInt();
+ assert(SS == getCurFunction()->SwitchStack.back().getPointer() &&
"switch stack missing push/pop!");
getCurFunction()->SwitchStack.pop_back();
@@ -800,10 +843,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
QualType CondType = CondExpr->getType();
- const Expr *CondExprBeforePromotion = CondExpr;
- QualType CondTypeBeforePromotion =
- GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
-
// C++ 6.4.2.p2:
// Integral promotions are performed (on the switch condition).
//
@@ -811,21 +850,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// type (before the promotion) doesn't make sense, even when it can
// be represented by the promoted type. Therefore we need to find
// the pre-promotion type of the switch condition.
- if (!CondExpr->isTypeDependent()) {
- // We have already converted the expression to an integral or enumeration
- // type, when we started the switch statement. If we don't have an
- // appropriate type now, just return an error.
- if (!CondType->isIntegralOrEnumerationType())
- return StmtError();
-
- if (CondExpr->isKnownToHaveBooleanValue()) {
- // switch(bool_expr) {...} is often a programmer error, e.g.
- // switch(n && mask) { ... } // Doh - should be "n & mask".
- // One can always use an if statement instead of switch(bool_expr).
- Diag(SwitchLoc, diag::warn_bool_switch_condition)
- << CondExpr->getSourceRange();
- }
- }
+ const Expr *CondExprBeforePromotion = CondExpr;
+ QualType CondTypeBeforePromotion =
+ GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
// Get the bitwidth of the switched-on value after promotions. We must
// convert the integer case values to this width before comparison.
@@ -878,50 +905,32 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Expr *Lo = CS->getLHS();
- if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+ if (Lo->isValueDependent()) {
HasDependentValue = true;
break;
}
- checkEnumTypesInSwitchStmt(*this, CondExpr, Lo);
-
- llvm::APSInt LoVal;
-
- if (getLangOpts().CPlusPlus11) {
- // C++11 [stmt.switch]p2: the constant-expression shall be a converted
- // constant expression of the promoted type of the switch condition.
- ExprResult ConvLo =
- CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue);
- if (ConvLo.isInvalid()) {
- CaseListIsErroneous = true;
- continue;
- }
- Lo = ConvLo.get();
- } else {
- // We already verified that the expression has a i-c-e value (C99
- // 6.8.4.2p3) - get that value now.
- LoVal = Lo->EvaluateKnownConstInt(Context);
-
- // If the LHS is not the same type as the condition, insert an implicit
- // cast.
- Lo = DefaultLvalueConversion(Lo).get();
- Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get();
- }
+ // We already verified that the expression has a constant value;
+ // get that value (prior to conversions).
+ const Expr *LoBeforePromotion = Lo;
+ GetTypeBeforeIntegralPromotion(LoBeforePromotion);
+ llvm::APSInt LoVal = LoBeforePromotion->EvaluateKnownConstInt(Context);
// Check the unconverted value is within the range of possible values of
// the switch expression.
checkCaseValue(*this, Lo->getLocStart(), LoVal,
CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+ // FIXME: This duplicates the check performed for warn_not_in_enum below.
+ checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion,
+ LoBeforePromotion);
+
// Convert the value to the same width/sign as the condition.
AdjustAPSInt(LoVal, CondWidth, CondIsSigned);
- CS->setLHS(Lo);
-
// If this is a case range, remember it in CaseRanges, otherwise CaseVals.
if (CS->getRHS()) {
- if (CS->getRHS()->isTypeDependent() ||
- CS->getRHS()->isValueDependent()) {
+ if (CS->getRHS()->isValueDependent()) {
HasDependentValue = true;
break;
}
@@ -1002,27 +1011,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
llvm::APSInt &LoVal = CaseRanges[i].first;
CaseStmt *CR = CaseRanges[i].second;
Expr *Hi = CR->getRHS();
- llvm::APSInt HiVal;
-
- if (getLangOpts().CPlusPlus11) {
- // C++11 [stmt.switch]p2: the constant-expression shall be a converted
- // constant expression of the promoted type of the switch condition.
- ExprResult ConvHi =
- CheckConvertedConstantExpression(Hi, CondType, HiVal,
- CCEK_CaseValue);
- if (ConvHi.isInvalid()) {
- CaseListIsErroneous = true;
- continue;
- }
- Hi = ConvHi.get();
- } else {
- HiVal = Hi->EvaluateKnownConstInt(Context);
- // If the RHS is not the same type as the condition, insert an
- // implicit cast.
- Hi = DefaultLvalueConversion(Hi).get();
- Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get();
- }
+ const Expr *HiBeforePromotion = Hi;
+ GetTypeBeforeIntegralPromotion(HiBeforePromotion);
+ llvm::APSInt HiVal = HiBeforePromotion->EvaluateKnownConstInt(Context);
// Check the unconverted value is within the range of possible values of
// the switch expression.
@@ -1032,8 +1024,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Convert the value to the same width/sign as the condition.
AdjustAPSInt(HiVal, CondWidth, CondIsSigned);
- CR->setRHS(Hi);
-
// If the low value is bigger than the high value, the case is empty.
if (LoVal > HiVal) {
Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
@@ -1104,7 +1094,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
}
// Complain if we have a constant condition and we didn't find a match.
- if (!CaseListIsErroneous && ShouldCheckConstantCond) {
+ if (!CaseListIsErroneous && !CaseListIsIncomplete &&
+ ShouldCheckConstantCond) {
// TODO: it would be nice if we printed enums as enums, chars as
// chars, etc.
Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)
@@ -1120,8 +1111,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
const EnumType *ET = CondTypeBeforePromotion->getAs<EnumType>();
// If switch has default case, then ignore it.
- if (!CaseListIsErroneous && !HasConstantCond && ET &&
- ET->getDecl()->isCompleteDefinition()) {
+ if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond &&
+ ET && ET->getDecl()->isCompleteDefinition()) {
const EnumDecl *ED = ET->getDecl();
EnumValsTy EnumVals;
@@ -1873,7 +1864,7 @@ StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
ExprResult CollectionExprResult =
CheckObjCForCollectionOperand(ForLoc, collection);
@@ -1888,7 +1879,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl());
if (!D || D->isInvalidDecl())
return StmtError();
-
+
FirstType = D->getType();
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
@@ -2025,7 +2016,7 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
/// Build a variable declaration for a for-range statement.
VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
- QualType Type, const char *Name) {
+ QualType Type, StringRef Name) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2094,10 +2085,12 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
}
// Build auto && __range = range-init
+ // Divide by 2, since the variables are in the inner scope (loop body).
+ const auto DepthStr = std::to_string(S->getDepth() / 2);
SourceLocation RangeLoc = Range->getLocStart();
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
Context.getAutoRRefDeductType(),
- "__range");
+ std::string("__range") + DepthStr);
if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
diag::err_for_range_deduction_failure)) {
LoopVar->setInvalidDecl();
@@ -2119,7 +2112,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
DS, RParenLoc, Kind);
}
-/// \brief Create the initialization, compare, and increment steps for
+/// Create the initialization, compare, and increment steps for
/// the range-based for loop expression.
/// This function does not handle array-based for loops,
/// which are created in Sema::BuildCXXForRangeStmt.
@@ -2340,10 +2333,12 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
return StmtError();
// Build auto __begin = begin-expr, __end = end-expr.
+ // Divide by 2, since the variables are in the inner scope (loop body).
+ const auto DepthStr = std::to_string(S->getDepth() / 2);
VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
- "__begin");
+ std::string("__begin") + DepthStr);
VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
- "__end");
+ std::string("__end") + DepthStr);
// Build begin-expr and end-expr and attach to __begin and __end variables.
ExprResult BeginExpr, EndExpr;
@@ -2378,7 +2373,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// Rather, we need to determine what it was when the array was first
// created - so we resort to using sizeof(vla)/sizeof(element).
// For e.g.
- // void f(int b) {
+ // void f(int b) {
// int vla[b];
// b = -1; <-- This should not affect the num of iterations below
// for (int &c : vla) { .. }
@@ -2387,7 +2382,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// FIXME: This results in codegen generating IR that recalculates the
// run-time number of elements (as opposed to just using the IR Value
// that corresponds to the run-time value of each bound that was
- // generated when the array was created.) If this proves too embarassing
+ // generated when the array was created.) If this proves too embarrassing
// even for unoptimized IR, consider passing a magic-value/cookie to
// codegen that then knows to simply use that initial llvm::Value (that
// corresponds to the bound at time of array creation) within
@@ -2404,7 +2399,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
EndVar->getSourceRange());
if (SizeOfVLAExprR.isInvalid())
return StmtError();
-
+
ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr(
EndVar->getLocation(), UETT_SizeOf,
/*isType=*/true,
@@ -2421,7 +2416,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
SizeOfVLAExprR.get(), SizeOfEachElementExprR.get());
if (BoundExpr.isInvalid())
return StmtError();
-
+
} else {
// Can't be a DependentSizedArrayType or an IncompleteArrayType since
// UnqAT is not incomplete and Range is not type-dependent.
@@ -2657,7 +2652,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
if (ReturnsReference) {
// Loop variable creates a temporary. Suggest either to go with
- // non-reference loop variable to indiciate a copy is made, or
+ // non-reference loop variable to indicate a copy is made, or
// the correct time to bind a const reference.
SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy)
<< VD << VariableType << E->getType();
@@ -2718,7 +2713,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
/// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.
/// 1) for (const foo &x : foos) where foos only returns a copy. Suggest
/// using "const foo x" to show that a copy is made
-/// 2) for (const bar &x : foos) where bar is a temporary intialized by bar.
+/// 2) for (const bar &x : foos) where bar is a temporary initialized by bar.
/// Suggest either "const bar x" to keep the copying or "const foo& x" to
/// prevent the copy.
/// 3) for (const foo x : foos) where x is constructed from a reference foo.
@@ -2780,7 +2775,7 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
- getCurFunction()->setHasBranchIntoScope();
+ setFunctionHasBranchIntoScope();
TheDecl->markUsed(Context);
return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
}
@@ -2807,7 +2802,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return StmtError();
E = ExprRes.get();
- getCurFunction()->setHasIndirectGoto();
+ setFunctionHasIndirectGoto();
return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
@@ -2847,7 +2842,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
return new (Context) BreakStmt(BreakLoc);
}
-/// \brief Determine whether the given expression is a candidate for
+/// Determine whether the given expression is a candidate for
/// copy elision in either a return statement or a throw expression.
///
/// \param ReturnType If we're determining the copy elision candidate for
@@ -2858,7 +2853,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
/// \param E The expression being returned from the function or block, or
/// being thrown.
///
-/// \param AllowParamOrMoveConstructible Whether we allow function parameters or
+/// \param CESK Whether we allow function parameters or
/// id-expressions that could be moved out of the function to be considered NRVO
/// candidates. C++ prohibits these for NRVO itself, but we re-use this logic to
/// determine whether we should try to move as part of a return or throw (which
@@ -2867,10 +2862,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
/// \returns The NRVO candidate variable, if the return statement may use the
/// NRVO, or NULL if there is no such candidate.
VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
- bool AllowParamOrMoveConstructible) {
- if (!getLangOpts().CPlusPlus)
- return nullptr;
-
+ CopyElisionSemanticsKind CESK) {
// - in a return statement in a function [where] ...
// ... the expression is the name of a non-volatile automatic object ...
DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
@@ -2880,13 +2872,13 @@ VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
if (!VD)
return nullptr;
- if (isCopyElisionCandidate(ReturnType, VD, AllowParamOrMoveConstructible))
+ if (isCopyElisionCandidate(ReturnType, VD, CESK))
return VD;
return nullptr;
}
bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
- bool AllowParamOrMoveConstructible) {
+ CopyElisionSemanticsKind CESK) {
QualType VDType = VD->getType();
// - in a return statement in a function with ...
// ... a class return type ...
@@ -2895,16 +2887,17 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
return false;
// ... the same cv-unqualified type as the function return type ...
// When considering moving this expression out, allow dissimilar types.
- if (!AllowParamOrMoveConstructible && !VDType->isDependentType() &&
+ if (!(CESK & CES_AllowDifferentTypes) && !VDType->isDependentType() &&
!Context.hasSameUnqualifiedType(ReturnType, VDType))
return false;
}
// ...object (other than a function or catch-clause parameter)...
if (VD->getKind() != Decl::Var &&
- !(AllowParamOrMoveConstructible && VD->getKind() == Decl::ParmVar))
+ !((CESK & CES_AllowParameters) && VD->getKind() == Decl::ParmVar))
+ return false;
+ if (!(CESK & CES_AllowExceptionVariables) && VD->isExceptionVariable())
return false;
- if (VD->isExceptionVariable()) return false;
// ...automatic...
if (!VD->hasLocalStorage()) return false;
@@ -2914,7 +2907,7 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
// variable will no longer be used.
if (VD->hasAttr<BlocksAttr>()) return false;
- if (AllowParamOrMoveConstructible)
+ if (CESK & CES_AllowDifferentTypes)
return true;
// ...non-volatile...
@@ -2929,7 +2922,95 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
return true;
}
-/// \brief Perform the initialization of a potentially-movable value, which
+/// Try to perform the initialization of a potentially-movable value,
+/// which is the operand to a return or throw statement.
+///
+/// This routine implements C++14 [class.copy]p32, which attempts to treat
+/// returned lvalues as rvalues in certain cases (to prefer move construction),
+/// then falls back to treating them as lvalues if that failed.
+///
+/// \param ConvertingConstructorsOnly If true, follow [class.copy]p32 and reject
+/// resolutions that find non-constructors, such as derived-to-base conversions
+/// or `operator T()&&` member functions. If false, do consider such
+/// conversion sequences.
+///
+/// \param Res We will fill this in if move-initialization was possible.
+/// If move-initialization is not possible, such that we must fall back to
+/// treating the operand as an lvalue, we will leave Res in its original
+/// invalid state.
+static void TryMoveInitialization(Sema& S,
+ const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *&Value,
+ bool ConvertingConstructorsOnly,
+ ExprResult &Res) {
+ ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
+ CK_NoOp, Value, VK_XValue);
+
+ Expr *InitExpr = &AsRvalue;
+
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ Value->getLocStart(), Value->getLocStart());
+
+ InitializationSequence Seq(S, Entity, Kind, InitExpr);
+
+ if (!Seq)
+ return;
+
+ for (const InitializationSequence::Step &Step : Seq.steps()) {
+ if (Step.Kind != InitializationSequence::SK_ConstructorInitialization &&
+ Step.Kind != InitializationSequence::SK_UserConversion)
+ continue;
+
+ FunctionDecl *FD = Step.Function.Function;
+ if (ConvertingConstructorsOnly) {
+ if (isa<CXXConstructorDecl>(FD)) {
+ // C++14 [class.copy]p32:
+ // [...] If the first overload resolution fails or was not performed,
+ // or if the type of the first parameter of the selected constructor
+ // is not an rvalue reference to the object's type (possibly
+ // cv-qualified), overload resolution is performed again, considering
+ // the object as an lvalue.
+ const RValueReferenceType *RRefType =
+ FD->getParamDecl(0)->getType()->getAs<RValueReferenceType>();
+ if (!RRefType)
+ break;
+ if (!S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
+ NRVOCandidate->getType()))
+ break;
+ } else {
+ continue;
+ }
+ } else {
+ if (isa<CXXConstructorDecl>(FD)) {
+ // Check that overload resolution selected a constructor taking an
+ // rvalue reference. If it selected an lvalue reference, then we
+ // didn't need to cast this thing to an rvalue in the first place.
+ if (!isa<RValueReferenceType>(FD->getParamDecl(0)->getType()))
+ break;
+ } else if (isa<CXXMethodDecl>(FD)) {
+ // Check that overload resolution selected a conversion operator
+ // taking an rvalue reference.
+ if (cast<CXXMethodDecl>(FD)->getRefQualifier() != RQ_RValue)
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ // Promote "AsRvalue" to the heap, since we now need this
+ // expression node to persist.
+ Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp,
+ Value, nullptr, VK_XValue);
+
+ // Complete type-checking the initialization of the return type
+ // using the constructor we found.
+ Res = Seq.Perform(S, Entity, Kind, Value);
+ }
+}
+
+/// Perform the initialization of a potentially-movable value, which
/// is the result of return value.
///
/// This routine implements C++14 [class.copy]p32, which attempts to treat
@@ -2952,52 +3033,82 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
// were designated by an rvalue.
ExprResult Res = ExprError();
- if (AllowNRVO && !NRVOCandidate)
- NRVOCandidate = getCopyElisionCandidate(ResultType, Value, true);
-
- if (AllowNRVO && NRVOCandidate) {
- ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
- CK_NoOp, Value, VK_XValue);
-
- Expr *InitExpr = &AsRvalue;
-
- InitializationKind Kind = InitializationKind::CreateCopy(
- Value->getLocStart(), Value->getLocStart());
-
- InitializationSequence Seq(*this, Entity, Kind, InitExpr);
- if (Seq) {
- for (const InitializationSequence::Step &Step : Seq.steps()) {
- if (!(Step.Kind ==
- InitializationSequence::SK_ConstructorInitialization ||
- (Step.Kind == InitializationSequence::SK_UserConversion &&
- isa<CXXConstructorDecl>(Step.Function.Function))))
- continue;
-
- CXXConstructorDecl *Constructor =
- cast<CXXConstructorDecl>(Step.Function.Function);
-
- const RValueReferenceType *RRefType
- = Constructor->getParamDecl(0)->getType()
- ->getAs<RValueReferenceType>();
-
- // [...] If the first overload resolution fails or was not performed, or
- // if the type of the first parameter of the selected constructor is not
- // an rvalue reference to the object's type (possibly cv-qualified),
- // overload resolution is performed again, considering the object as an
- // lvalue.
- if (!RRefType ||
- !Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
- NRVOCandidate->getType()))
- break;
+ if (AllowNRVO) {
+ bool AffectedByCWG1579 = false;
+
+ if (!NRVOCandidate) {
+ NRVOCandidate = getCopyElisionCandidate(ResultType, Value, CES_Default);
+ if (NRVOCandidate &&
+ !getDiagnostics().isIgnored(diag::warn_return_std_move_in_cxx11,
+ Value->getExprLoc())) {
+ const VarDecl *NRVOCandidateInCXX11 =
+ getCopyElisionCandidate(ResultType, Value, CES_FormerDefault);
+ AffectedByCWG1579 = (!NRVOCandidateInCXX11);
+ }
+ }
- // Promote "AsRvalue" to the heap, since we now need this
- // expression node to persist.
- Value = ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp,
- Value, nullptr, VK_XValue);
+ if (NRVOCandidate) {
+ TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value,
+ true, Res);
+ }
- // Complete type-checking the initialization of the return type
- // using the constructor we found.
- Res = Seq.Perform(*this, Entity, Kind, Value);
+ if (!Res.isInvalid() && AffectedByCWG1579) {
+ QualType QT = NRVOCandidate->getType();
+ if (QT.getNonReferenceType()
+ .getUnqualifiedType()
+ .isTriviallyCopyableType(Context)) {
+ // Adding 'std::move' around a trivially copyable variable is probably
+ // pointless. Don't suggest it.
+ } else {
+ // Common cases for this are returning unique_ptr<Derived> from a
+ // function of return type unique_ptr<Base>, or returning T from a
+ // function of return type Expected<T>. This is totally fine in a
+ // post-CWG1579 world, but was not fine before.
+ assert(!ResultType.isNull());
+ SmallString<32> Str;
+ Str += "std::move(";
+ Str += NRVOCandidate->getDeclName().getAsString();
+ Str += ")";
+ Diag(Value->getExprLoc(), diag::warn_return_std_move_in_cxx11)
+ << Value->getSourceRange()
+ << NRVOCandidate->getDeclName() << ResultType << QT;
+ Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11)
+ << FixItHint::CreateReplacement(Value->getSourceRange(), Str);
+ }
+ } else if (Res.isInvalid() &&
+ !getDiagnostics().isIgnored(diag::warn_return_std_move,
+ Value->getExprLoc())) {
+ const VarDecl *FakeNRVOCandidate =
+ getCopyElisionCandidate(QualType(), Value, CES_AsIfByStdMove);
+ if (FakeNRVOCandidate) {
+ QualType QT = FakeNRVOCandidate->getType();
+ if (QT->isLValueReferenceType()) {
+ // Adding 'std::move' around an lvalue reference variable's name is
+ // dangerous. Don't suggest it.
+ } else if (QT.getNonReferenceType()
+ .getUnqualifiedType()
+ .isTriviallyCopyableType(Context)) {
+ // Adding 'std::move' around a trivially copyable variable is probably
+ // pointless. Don't suggest it.
+ } else {
+ ExprResult FakeRes = ExprError();
+ Expr *FakeValue = Value;
+ TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType,
+ FakeValue, false, FakeRes);
+ if (!FakeRes.isInvalid()) {
+ bool IsThrow =
+ (Entity.getKind() == InitializedEntity::EK_Exception);
+ SmallString<32> Str;
+ Str += "std::move(";
+ Str += FakeNRVOCandidate->getDeclName().getAsString();
+ Str += ")";
+ Diag(Value->getExprLoc(), diag::warn_return_std_move)
+ << Value->getSourceRange()
+ << FakeNRVOCandidate->getDeclName() << IsThrow;
+ Diag(Value->getExprLoc(), diag::note_add_std_move)
+ << FixItHint::CreateReplacement(Value->getSourceRange(), Str);
+ }
+ }
}
}
}
@@ -3011,7 +3122,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
return Res;
}
-/// \brief Determine whether the declared return type of the specified function
+/// Determine whether the declared return type of the specified function
/// contains 'auto'.
static bool hasDeducedReturnType(FunctionDecl *FD) {
const FunctionProtoType *FPT =
@@ -3145,7 +3256,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
NRVOCandidate != nullptr);
@@ -3158,7 +3269,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
RetValExp = Res.get();
CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
} else {
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
}
if (RetValExp) {
@@ -3183,7 +3294,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
namespace {
-/// \brief Marks all typedefs in all local classes in a type referenced.
+/// Marks all typedefs in all local classes in a type referenced.
///
/// In a function like
/// auto f() {
@@ -3255,7 +3366,7 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// statement with a non-type-dependent operand.
assert(AT->isDeduced() && "should have deduced to dependent type");
return false;
- }
+ }
if (RetExpr) {
// Otherwise, [...] deduce a value for U using the rules of template
@@ -3528,7 +3639,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization,
// the C version of which boils down to CheckSingleAssignmentConstraints.
if (RetValExp)
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
@@ -3603,7 +3714,7 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
if (!getLangOpts().ObjCExceptions)
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
unsigned NumCatchStmts = CatchStmts.size();
return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
NumCatchStmts, Finally);
@@ -3694,7 +3805,7 @@ StmtResult
Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
Stmt *SyncBody) {
// We can't jump into or indirect-jump out of a @synchronized block.
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
}
@@ -3710,7 +3821,7 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
StmtResult
Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}
@@ -3822,7 +3933,11 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
ArrayRef<Stmt *> Handlers) {
// Don't report an error if 'try' is used in system headers.
if (!getLangOpts().CXXExceptions &&
- !getSourceManager().isInSystemHeader(TryLoc))
+ !getSourceManager().isInSystemHeader(TryLoc) &&
+ (!getLangOpts().OpenMPIsDevice ||
+ !getLangOpts().OpenMPHostCXXExceptions ||
+ isInOpenMPTargetExecutionDirective() ||
+ isInOpenMPDeclareTargetContext()))
Diag(TryLoc, diag::err_exceptions_disabled) << "try";
// Exceptions aren't allowed in CUDA device code.
@@ -4036,32 +4151,29 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc,
return RD;
}
-static void buildCapturedStmtCaptureList(
- SmallVectorImpl<CapturedStmt::Capture> &Captures,
- SmallVectorImpl<Expr *> &CaptureInits,
- ArrayRef<CapturingScopeInfo::Capture> Candidates) {
-
- typedef ArrayRef<CapturingScopeInfo::Capture>::const_iterator CaptureIter;
- for (CaptureIter Cap = Candidates.begin(); Cap != Candidates.end(); ++Cap) {
-
- if (Cap->isThisCapture()) {
- Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
+static void
+buildCapturedStmtCaptureList(SmallVectorImpl<CapturedStmt::Capture> &Captures,
+ SmallVectorImpl<Expr *> &CaptureInits,
+ ArrayRef<sema::Capture> Candidates) {
+ for (const sema::Capture &Cap : Candidates) {
+ if (Cap.isThisCapture()) {
+ Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap->getInitExpr());
+ CaptureInits.push_back(Cap.getInitExpr());
continue;
- } else if (Cap->isVLATypeCapture()) {
+ } else if (Cap.isVLATypeCapture()) {
Captures.push_back(
- CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType));
+ CapturedStmt::Capture(Cap.getLocation(), CapturedStmt::VCK_VLAType));
CaptureInits.push_back(nullptr);
continue;
}
- Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
- Cap->isReferenceCapture()
+ Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
+ Cap.isReferenceCapture()
? CapturedStmt::VCK_ByRef
: CapturedStmt::VCK_ByCopy,
- Cap->getVariable()));
- CaptureInits.push_back(Cap->getInitExpr());
+ Cap.getVariable()));
+ CaptureInits.push_back(Cap.getInitExpr());
}
}
@@ -4111,7 +4223,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
assert(!ContextIsFound &&
"null type has been found already for '__context' parameter");
IdentifierInfo *ParamName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD))
+ .withConst()
+ .withRestrict();
auto *Param =
ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
ImplicitParamDecl::CapturedContext);
@@ -4160,7 +4274,7 @@ void Sema::ActOnCapturedRegionError() {
SmallVector<Decl*, 4> Fields(Record->fields());
ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields,
- SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr);
+ SourceLocation(), SourceLocation(), ParsedAttributesView());
PopDeclContext();
PopFunctionScopeInfo();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index fc1cc7bbe544..0db15ea1f646 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -109,7 +109,7 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
return false;
}
-/// \brief Returns true if given expression is not compatible with inline
+/// Returns true if given expression is not compatible with inline
/// assembly's memory constraint; false otherwise.
static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
TargetInfo::ConstraintInfo &Info,
@@ -603,7 +603,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
Context.getTargetInfo(), Context);
if (ConstraintLoc.isValid())
return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
-
+
return NS;
}
@@ -793,7 +793,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Expr*> Exprs,
SourceLocation EndLoc) {
bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
/*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
index e55e20c2827f..e39a65c6ce0c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
@@ -23,7 +23,7 @@
using namespace clang;
using namespace sema;
-static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
FallThroughAttr Attr(A.getRange(), S.Context,
A.getAttributeSpellingListIndex());
@@ -53,7 +53,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
return ::new (S.Context) auto(Attr);
}
-static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
if (A.getNumArgs() < 1) {
S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments)
@@ -78,7 +78,7 @@ static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A,
DiagnosticIdentifiers.size(), A.getAttributeSpellingListIndex());
}
-static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange) {
IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
@@ -246,7 +246,7 @@ CheckForIncompatibleAttributes(Sema &S,
}
}
-static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
// Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's
// useful for OpenCL 1.x too and doesn't require HW support.
@@ -288,21 +288,21 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor);
}
-static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
switch (A.getKind()) {
- case AttributeList::UnknownAttribute:
+ case ParsedAttr::UnknownAttribute:
S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
diag::warn_unhandled_ms_attribute_ignored :
diag::warn_unknown_attribute_ignored) << A.getName();
return nullptr;
- case AttributeList::AT_FallThrough:
+ case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
- case AttributeList::AT_LoopHint:
+ case ParsedAttr::AT_LoopHint:
return handleLoopHintAttr(S, St, A, Range);
- case AttributeList::AT_OpenCLUnrollHint:
+ case ParsedAttr::AT_OpenCLUnrollHint:
return handleOpenCLUnrollHint(S, St, A, Range);
- case AttributeList::AT_Suppress:
+ case ParsedAttr::AT_Suppress:
return handleSuppressAttr(S, St, A, Range);
default:
// if we're here, then we parsed a known attribute, but didn't recognize
@@ -313,11 +313,12 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
}
}
-StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
+StmtResult Sema::ProcessStmtAttributes(Stmt *S,
+ const ParsedAttributesView &AttrList,
SourceRange Range) {
SmallVector<const Attr*, 8> Attrs;
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
+ for (const ParsedAttr &AL : AttrList) {
+ if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
Attrs.push_back(a);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index 7c6af5793fc5..fa002de3f5f1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -46,7 +46,7 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
}
namespace clang {
-/// \brief [temp.constr.decl]p2: A template's associated constraints are
+/// [temp.constr.decl]p2: A template's associated constraints are
/// defined as a single constraint-expression derived from the introduced
/// constraint-expressions [ ... ].
///
@@ -65,7 +65,7 @@ static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params,
return Params->getRequiresClause();
}
-/// \brief Determine whether the declaration found is acceptable as the name
+/// Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns NULL.
static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
@@ -105,6 +105,12 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
return nullptr;
}
+ // 'using Dependent::foo;' can resolve to a template name.
+ // 'using typename Dependent::foo;' cannot (not even if 'foo' is an
+ // injected-class-name).
+ if (isa<UnresolvedUsingValueDecl>(D))
+ return D;
+
return nullptr;
}
@@ -158,7 +164,7 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
TemplateNameKind Sema::isTemplateName(Scope *S,
CXXScopeSpec &SS,
bool hasTemplateKeyword,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult,
@@ -189,8 +195,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
QualType ObjectType = ObjectTypePtr.get();
LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
- LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
- MemberOfUnknownSpecialization);
+ if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
+ MemberOfUnknownSpecialization))
+ return TNK_Non_template;
if (R.empty()) return TNK_Non_template;
if (R.isAmbiguous()) {
// Suppress diagnostics; we'll redo this lookup later.
@@ -213,6 +220,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// We'll do this lookup again later.
R.suppressDiagnostics();
+ } else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) {
+ // We don't yet know whether this is a template-name or not.
+ MemberOfUnknownSpecialization = true;
+ return TNK_Non_template;
} else {
TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
@@ -252,8 +263,10 @@ bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
// syntactic form of a deduction guide is enough to identify it even
// if we can't look up the template name at all.
LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName);
- LookupTemplateName(R, S, SS, /*ObjectType*/QualType(),
- /*EnteringContext*/false, MemberOfUnknownSpecialization);
+ if (LookupTemplateName(R, S, SS, /*ObjectType*/ QualType(),
+ /*EnteringContext*/ false,
+ MemberOfUnknownSpecialization))
+ return false;
if (R.empty()) return false;
if (R.isAmbiguous()) {
@@ -298,39 +311,40 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
return true;
}
-void Sema::LookupTemplateName(LookupResult &Found,
+bool Sema::LookupTemplateName(LookupResult &Found,
Scope *S, CXXScopeSpec &SS,
QualType ObjectType,
bool EnteringContext,
- bool &MemberOfUnknownSpecialization) {
+ bool &MemberOfUnknownSpecialization,
+ SourceLocation TemplateKWLoc) {
// Determine where to perform name lookup
MemberOfUnknownSpecialization = false;
DeclContext *LookupCtx = nullptr;
- bool isDependent = false;
+ bool IsDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
// x->B::f, and we are looking into the type of the object.
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
- isDependent = ObjectType->isDependentType();
- assert((isDependent || !ObjectType->isIncompleteType() ||
+ IsDependent = !LookupCtx;
+ assert((IsDependent || !ObjectType->isIncompleteType() ||
ObjectType->castAs<TagType>()->isBeingDefined()) &&
"Caller should have completed object type");
// Template names cannot appear inside an Objective-C class or object type.
if (ObjectType->isObjCObjectOrInterfaceType()) {
Found.clear();
- return;
+ return false;
}
} else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
LookupCtx = computeDeclContext(SS, EnteringContext);
- isDependent = isDependentScopeSpecifier(SS);
+ IsDependent = !LookupCtx;
// The declaration context must be complete.
if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
- return;
+ return true;
}
bool ObjectTypeSearchedInScope = false;
@@ -341,34 +355,43 @@ void Sema::LookupTemplateName(LookupResult &Found,
// expression or the declaration context associated with a prior
// nested-name-specifier.
LookupQualifiedName(Found, LookupCtx);
- if (!ObjectType.isNull() && Found.empty()) {
- // C++ [basic.lookup.classref]p1:
- // In a class member access expression (5.2.5), if the . or -> token is
- // immediately followed by an identifier followed by a <, the
- // identifier must be looked up to determine whether the < is the
- // beginning of a template argument list (14.2) or a less-than operator.
- // The identifier is first looked up in the class of the object
- // expression. If the identifier is not found, it is then looked up in
- // the context of the entire postfix-expression and shall name a class
- // or function template.
- if (S) LookupName(Found, S);
- ObjectTypeSearchedInScope = true;
+
+ // FIXME: The C++ standard does not clearly specify what happens in the
+ // case where the object type is dependent, and implementations vary. In
+ // Clang, we treat a name after a . or -> as a template-name if lookup
+ // finds a non-dependent member or member of the current instantiation that
+ // is a type template, or finds no such members and lookup in the context
+ // of the postfix-expression finds a type template. In the latter case, the
+ // name is nonetheless dependent, and we may resolve it to a member of an
+ // unknown specialization when we come to instantiate the template.
+ IsDependent |= Found.wasNotFoundInCurrentInstantiation();
+ }
+
+ if (!SS.isSet() && (ObjectType.isNull() || Found.empty())) {
+ // C++ [basic.lookup.classref]p1:
+ // In a class member access expression (5.2.5), if the . or -> token is
+ // immediately followed by an identifier followed by a <, the
+ // identifier must be looked up to determine whether the < is the
+ // beginning of a template argument list (14.2) or a less-than operator.
+ // The identifier is first looked up in the class of the object
+ // expression. If the identifier is not found, it is then looked up in
+ // the context of the entire postfix-expression and shall name a class
+ // template.
+ if (S)
+ LookupName(Found, S);
+
+ if (!ObjectType.isNull()) {
+ // FIXME: We should filter out all non-type templates here, particularly
+ // variable templates and concepts. But the exclusion of alias templates
+ // and template template parameters is a wording defect.
AllowFunctionTemplatesInLookup = false;
+ ObjectTypeSearchedInScope = true;
}
- } else if (isDependent && (!S || ObjectType.isNull())) {
- // We cannot look into a dependent object type or nested nme
- // specifier.
- MemberOfUnknownSpecialization = true;
- return;
- } else {
- // Perform unqualified name lookup in the current scope.
- LookupName(Found, S);
- if (!ObjectType.isNull())
- AllowFunctionTemplatesInLookup = false;
+ IsDependent |= Found.wasNotFoundInCurrentInstantiation();
}
- if (Found.empty() && !isDependent) {
+ if (Found.empty() && !IsDependent) {
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
Found.clear();
@@ -402,11 +425,27 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
}
+ NamedDecl *ExampleLookupResult =
+ Found.empty() ? nullptr : Found.getRepresentativeDecl();
FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
if (Found.empty()) {
- if (isDependent)
+ if (IsDependent) {
MemberOfUnknownSpecialization = true;
- return;
+ return false;
+ }
+
+ // If a 'template' keyword was used, a lookup that finds only non-template
+ // names is an error.
+ if (ExampleLookupResult && TemplateKWLoc.isValid()) {
+ Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)
+ << Found.getLookupName() << SS.getRange();
+ Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(),
+ diag::note_template_kw_refers_to_non_template)
+ << Found.getLookupName();
+ return true;
+ }
+
+ return false;
}
if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
@@ -453,6 +492,8 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
}
}
+
+ return false;
}
void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
@@ -467,20 +508,41 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
DeclContext *LookupCtx = nullptr;
NamedDecl *Found = nullptr;
+ bool MissingTemplateKeyword = false;
// Figure out what name we looked up.
- if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) {
+ NameInfo = DRE->getNameInfo();
+ SS.Adopt(DRE->getQualifierLoc());
+ LookupKind = LookupOrdinaryName;
+ Found = DRE->getFoundDecl();
+ } else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) {
NameInfo = ME->getMemberNameInfo();
SS.Adopt(ME->getQualifierLoc());
LookupKind = LookupMemberName;
LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl();
Found = ME->getMemberDecl();
+ } else if (auto *DSDRE =
+ dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) {
+ NameInfo = DSDRE->getNameInfo();
+ SS.Adopt(DSDRE->getQualifierLoc());
+ MissingTemplateKeyword = true;
+ } else if (auto *DSME =
+ dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) {
+ NameInfo = DSME->getMemberNameInfo();
+ SS.Adopt(DSME->getQualifierLoc());
+ MissingTemplateKeyword = true;
} else {
- auto *DRE = cast<DeclRefExpr>(TemplateName.get());
- NameInfo = DRE->getNameInfo();
- SS.Adopt(DRE->getQualifierLoc());
- LookupKind = LookupOrdinaryName;
- Found = DRE->getFoundDecl();
+ llvm_unreachable("unexpected kind of potential template name");
+ }
+
+ // If this is a dependent-scope lookup, diagnose that the 'template' keyword
+ // was missing.
+ if (MissingTemplateKeyword) {
+ Diag(NameInfo.getLocStart(), diag::err_template_kw_missing)
+ << "" << NameInfo.getName().getAsString()
+ << SourceRange(Less, Greater);
+ return;
}
// Try to correct the name by looking for templates and C++ named casts.
@@ -765,7 +827,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
llvm_unreachable("Unhandled parsed template argument");
}
-/// \brief Translates template arguments as provided by the parser
+/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
TemplateArgumentListInfo &TemplateArgs) {
@@ -783,6 +845,56 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
}
+/// Convert a parsed type into a parsed template argument. This is mostly
+/// trivial, except that we may have parsed a C++17 deduced class template
+/// specialization type, in which case we should form a template template
+/// argument instead of a type template argument.
+ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
+ TypeSourceInfo *TInfo;
+ QualType T = GetTypeFromParser(ParsedType.get(), &TInfo);
+ if (T.isNull())
+ return ParsedTemplateArgument();
+ assert(TInfo && "template argument with no location");
+
+ // If we might have formed a deduced template specialization type, convert
+ // it to a template template argument.
+ if (getLangOpts().CPlusPlus17) {
+ TypeLoc TL = TInfo->getTypeLoc();
+ SourceLocation EllipsisLoc;
+ if (auto PET = TL.getAs<PackExpansionTypeLoc>()) {
+ EllipsisLoc = PET.getEllipsisLoc();
+ TL = PET.getPatternLoc();
+ }
+
+ CXXScopeSpec SS;
+ if (auto ET = TL.getAs<ElaboratedTypeLoc>()) {
+ SS.Adopt(ET.getQualifierLoc());
+ TL = ET.getNamedTypeLoc();
+ }
+
+ if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) {
+ TemplateName Name = DTST.getTypePtr()->getTemplateName();
+ if (SS.isSet())
+ Name = Context.getQualifiedTemplateName(SS.getScopeRep(),
+ /*HasTemplateKeyword*/ false,
+ Name.getAsTemplateDecl());
+ ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
+ DTST.getTemplateNameLoc());
+ if (EllipsisLoc.isValid())
+ Result = Result.getTemplatePackExpansion(EllipsisLoc);
+ return Result;
+ }
+ }
+
+ // This is a normal type template argument. Note, if the type template
+ // argument is an injected-class-name for a template, it has a dual nature
+ // and can be used as either a type or a template. We handle that in
+ // convertTypeTemplateArgumentToTemplate.
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type,
+ ParsedType.get().getAsOpaquePtr(),
+ TInfo->getTypeLoc().getLocStart());
+}
+
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
@@ -854,7 +966,7 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
return Param;
}
-/// \brief Check that the type of a non-type template parameter is
+/// Check that the type of a non-type template parameter is
/// well-formed.
///
/// \returns the (possibly-promoted) parameter type if valid;
@@ -932,14 +1044,14 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
// Check that we have valid decl-specifiers specified.
auto CheckValidDeclSpecifiers = [this, &D] {
// C++ [temp.param]
- // p1
- // template-parameter:
- // ...
- // parameter-declaration
- // p2
+ // p1
+ // template-parameter:
+ // ...
+ // parameter-declaration
+ // p2
// ... A storage class shall not be specified in a template-parameter
// declaration.
- // [dcl.typedef]p1:
+ // [dcl.typedef]p1:
// The typedef specifier [...] shall not be used in the decl-specifier-seq
// of a parameter-declaration
const DeclSpec &DS = D.getDeclSpec();
@@ -949,22 +1061,22 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
};
if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified)
EmitDiag(DS.getStorageClassSpecLoc());
-
+
if (DS.getThreadStorageClassSpec() != TSCS_unspecified)
EmitDiag(DS.getThreadStorageClassSpecLoc());
-
- // [dcl.inline]p1:
- // The inline specifier can be applied only to the declaration or
+
+ // [dcl.inline]p1:
+ // The inline specifier can be applied only to the declaration or
// definition of a variable or function.
-
+
if (DS.isInlineSpecified())
EmitDiag(DS.getInlineSpecLoc());
-
+
// [dcl.constexpr]p1:
- // The constexpr specifier shall be applied only to the definition of a
- // variable or variable template or the declaration of a function or
+ // The constexpr specifier shall be applied only to the definition of a
+ // variable or variable template or the declaration of a function or
// function template.
-
+
if (DS.isConstexprSpecified())
EmitDiag(DS.getConstexprSpecLoc());
@@ -982,7 +1094,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
};
CheckValidDeclSpecifiers();
-
+
if (TInfo->getType()->isUndeducedType()) {
Diag(D.getIdentifierLoc(),
diag::warn_cxx14_compat_template_nontype_parm_auto_type)
@@ -1151,17 +1263,13 @@ static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
}
-DeclResult
-Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr,
- TemplateParameterList *TemplateParams,
- AccessSpecifier AS, SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc,
- unsigned NumOuterTemplateParamLists,
- TemplateParameterList** OuterTemplateParamLists,
- SkipBodyInfo *SkipBody) {
+DeclResult Sema::CheckClassTemplate(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
+ const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
+ AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
+ TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TUK_Reference && "Can only declare or define class templates");
@@ -1212,7 +1320,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
- diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
+ diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false);
LookupQualifiedName(Previous, SemanticContext);
} else {
@@ -1501,8 +1609,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (TUK == TUK_Definition)
NewClass->startDefinition();
- if (Attr)
- ProcessDeclAttributeList(S, NewClass, Attr);
+ ProcessDeclAttributeList(S, NewClass, Attr);
if (PrevClassTemplate)
mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());
@@ -1552,6 +1659,23 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
namespace {
+/// Tree transform to "extract" a transformed type from a class template's
+/// constructor to a deduction guide.
+class ExtractTypeForDeductionGuide
+ : public TreeTransform<ExtractTypeForDeductionGuide> {
+public:
+ typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
+ ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {}
+
+ TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
+
+ QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
+ return TransformType(
+ TLB,
+ TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc());
+ }
+};
+
/// Transform to convert portions of a constructor declaration into the
/// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
struct ConvertConstructorToDeductionGuideTransform {
@@ -1773,9 +1897,7 @@ private:
MultiLevelTemplateArgumentList &Args) {
TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
TypeSourceInfo *NewDI;
- if (!Args.getNumLevels())
- NewDI = OldDI;
- else if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) {
+ if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) {
// Expand out the one and only element in each inner pack.
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0);
NewDI =
@@ -1791,23 +1913,17 @@ private:
if (!NewDI)
return nullptr;
- // Canonicalize the type. This (for instance) replaces references to
- // typedef members of the current instantiations with the definitions of
- // those typedefs, avoiding triggering instantiation of the deduced type
- // during deduction.
- // FIXME: It would be preferable to retain type sugar and source
- // information here (and handle this in substitution instead).
- NewDI = SemaRef.Context.getTrivialTypeSourceInfo(
- SemaRef.Context.getCanonicalType(NewDI->getType()),
- OldParam->getLocation());
+ // Extract the type. This (for instance) replaces references to typedef
+ // members of the current instantiations with the definitions of those
+ // typedefs, avoiding triggering instantiation of the deduced type during
+ // deduction.
+ NewDI = ExtractTypeForDeductionGuide(SemaRef).transform(NewDI);
// Resolving a wording defect, we also inherit default arguments from the
// constructor.
ExprResult NewDefArg;
if (OldParam->hasDefaultArg()) {
- NewDefArg = Args.getNumLevels()
- ? SemaRef.SubstExpr(OldParam->getDefaultArg(), Args)
- : OldParam->getDefaultArg();
+ NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args);
if (NewDefArg.isInvalid())
return nullptr;
}
@@ -1822,6 +1938,7 @@ private:
NewDefArg.get());
NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
OldParam->getFunctionScopeIndex());
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
return NewParam;
}
@@ -1885,6 +2002,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
// FIXME: Add a kind for this to give more meaningful diagnostics. But can
// this substitution process actually fail?
InstantiatingTemplate BuildingDeductionGuides(*this, Loc, Template);
+ if (BuildingDeductionGuides.isInvalid())
+ return;
// Convert declared constructors into deduction guide templates.
// FIXME: Skip constructors for which deduction must necessarily fail (those
@@ -1925,7 +2044,7 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
->setIsCopyDeductionCandidate();
}
-/// \brief Diagnose the presence of a default template argument on a
+/// Diagnose the presence of a default template argument on a
/// template parameter, which is ill-formed in certain contexts.
///
/// \returns true if the default template argument should be dropped.
@@ -1981,7 +2100,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
llvm_unreachable("Invalid TemplateParamListContext!");
}
-/// \brief Check for unexpanded parameter packs within the template parameters
+/// Check for unexpanded parameter packs within the template parameters
/// of a template template parameter, recursively.
static bool DiagnoseUnexpandedParameterPacks(Sema &S,
TemplateTemplateParmDecl *TTP) {
@@ -2012,7 +2131,7 @@ static bool DiagnoseUnexpandedParameterPacks(Sema &S,
return false;
}
-/// \brief Checks the validity of a template parameter list, possibly
+/// Checks the validity of a template parameter list, possibly
/// considering the template parameter list from a previous
/// declaration.
///
@@ -2379,7 +2498,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
return SourceRange();
}
-/// \brief Match the given template parameter lists to the given scope
+/// Match the given template parameter lists to the given scope
/// specifier, returning the template parameter list that applies to the
/// name.
///
@@ -3476,7 +3595,7 @@ noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams,
const llvm::SmallBitVector &DeducibleParams) {
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
- NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+ NamedDecl *Param = TemplateParams->getParam(I);
if (Param->getDeclName())
S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
<< Param->getDeclName();
@@ -3754,7 +3873,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
}
namespace {
-/// \brief A partial specialization whose template arguments have matched
+/// A partial specialization whose template arguments have matched
/// a given template-id.
struct PartialSpecMatchResult {
VarTemplatePartialSpecializationDecl *Partial;
@@ -3938,6 +4057,16 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
/*FoundD=*/nullptr, TemplateArgs);
}
+void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
+ SourceLocation Loc) {
+ Diag(Loc, diag::err_template_missing_args)
+ << (int)getTemplateNameKindForDiagnostics(Name) << Name;
+ if (TemplateDecl *TD = Name.getAsTemplateDecl()) {
+ Diag(TD->getLocation(), diag::note_template_decl_here)
+ << TD->getTemplateParameters()->getSourceRange();
+ }
+}
+
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -3957,11 +4086,23 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
assert(!R.empty() && "empty lookup results when building templateid");
assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+ // Non-function templates require a template argument list.
+ if (auto *TD = R.getAsSingle<TemplateDecl>()) {
+ if (!TemplateArgs && !isa<FunctionTemplateDecl>(TD)) {
+ diagnoseMissingTemplateArguments(TemplateName(TD), R.getNameLoc());
+ return ExprError();
+ }
+ }
+
+ auto AnyDependentArguments = [&]() -> bool {
+ bool InstantiationDependent;
+ return TemplateArgs &&
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ *TemplateArgs, InstantiationDependent);
+ };
+
// In C++1y, check variable template ids.
- bool InstantiationDependent;
- if (R.getAsSingle<VarTemplateDecl>() &&
- !TemplateSpecializationType::anyDependentTemplateArguments(
- *TemplateArgs, InstantiationDependent)) {
+ if (R.getAsSingle<VarTemplateDecl>() && !AnyDependentArguments()) {
return CheckVarTemplateId(SS, R.getLookupNameInfo(),
R.getAsSingle<VarTemplateDecl>(),
TemplateKWLoc, TemplateArgs);
@@ -3997,15 +4138,17 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
bool MemberOfUnknownSpecialization;
LookupResult R(*this, NameInfo, LookupOrdinaryName);
- LookupTemplateName(R, (Scope*)nullptr, SS, QualType(), /*Entering*/ false,
- MemberOfUnknownSpecialization);
+ if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(),
+ /*Entering*/false, MemberOfUnknownSpecialization,
+ TemplateKWLoc))
+ return ExprError();
if (R.isAmbiguous())
return ExprError();
if (R.empty()) {
- Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template)
- << NameInfo.getName() << SS.getRange();
+ Diag(NameInfo.getLoc(), diag::err_no_member)
+ << NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
@@ -4020,7 +4163,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs);
}
-/// \brief Form a dependent template name.
+/// Form a dependent template name.
///
/// This action forms a dependent template name given the template
/// name and its (presumably dependent) scope specifier. For
@@ -4030,7 +4173,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result,
@@ -4068,17 +4211,20 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
ObjectType, EnteringContext, Result,
MemberOfUnknownSpecialization);
- if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
- isa<CXXRecordDecl>(LookupCtx) &&
- (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
- cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) {
+ if (TNK == TNK_Non_template && MemberOfUnknownSpecialization) {
// This is a dependent template. Handle it below.
} else if (TNK == TNK_Non_template) {
- Diag(Name.getLocStart(),
- diag::err_template_kw_refers_to_non_template)
- << GetNameFromUnqualifiedId(Name).getName()
- << Name.getSourceRange()
- << TemplateKWLoc;
+ // Do the lookup again to determine if this is a "nothing found" case or
+ // a "not a template" case. FIXME: Refactor isTemplateName so we don't
+ // need to do this.
+ DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name);
+ LookupResult R(*this, DNI.getName(), Name.getLocStart(),
+ LookupOrdinaryName);
+ bool MOUS;
+ if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext,
+ MOUS, TemplateKWLoc))
+ Diag(Name.getLocStart(), diag::err_no_member)
+ << DNI.getName() << LookupCtx << SS.getRange();
return TNK_Non_template;
} else {
// We found something; return it.
@@ -4148,16 +4294,13 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
ArgType = Arg.getAsType();
TSI = AL.getTypeSourceInfo();
break;
- case TemplateArgument::Template: {
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
// We have a template type parameter but the template argument
// is a template without any arguments.
SourceRange SR = AL.getSourceRange();
- TemplateName Name = Arg.getAsTemplate();
- Diag(SR.getBegin(), diag::err_template_missing_args)
- << (int)getTemplateNameKindForDiagnostics(Name) << Name << SR;
- if (TemplateDecl *Decl = Name.getAsTemplateDecl())
- Diag(Decl->getLocation(), diag::note_template_decl_here);
-
+ TemplateName Name = Arg.getAsTemplateOrTemplatePattern();
+ diagnoseMissingTemplateArguments(Name, SR.getEnd());
return true;
}
case TemplateArgument::Expression: {
@@ -4250,7 +4393,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return false;
}
-/// \brief Substitute template arguments into the default template argument for
+/// Substitute template arguments into the default template argument for
/// the given template type parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
@@ -4306,7 +4449,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
return ArgType;
}
-/// \brief Substitute template arguments into the default template argument for
+/// Substitute template arguments into the default template argument for
/// the given non-type template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
@@ -4354,7 +4497,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
}
-/// \brief Substitute template arguments into the default template argument for
+/// Substitute template arguments into the default template argument for
/// the given template template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
@@ -4418,7 +4561,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgLists);
}
-/// \brief If the given template parameter has a default template
+/// If the given template parameter has a default template
/// argument, substitute into that default template argument and
/// return the corresponding template argument.
TemplateArgumentLoc
@@ -4519,7 +4662,7 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
return TemplateArgumentLoc();
}
-/// \brief Check that the given template argument corresponds to the given
+/// Check that the given template argument corresponds to the given
/// template parameter.
///
/// \param Param The template parameter against which the argument will be
@@ -4566,6 +4709,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
+ // FIXME: Do we need to substitute into parameters here if they're
+ // instantiation-dependent but not dependent?
if (NTTPType->isDependentType() &&
!isa<TemplateTemplateParmDecl>(Template) &&
!Template->getDeclContext()->isDependentContext()) {
@@ -4597,11 +4742,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::Expression: {
TemplateArgument Result;
+ unsigned CurSFINAEErrors = NumSFINAEErrors;
ExprResult Res =
CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(),
Result, CTAK);
if (Res.isInvalid())
return true;
+ // If the current template argument causes an error, give up now.
+ if (CurSFINAEErrors < NumSFINAEErrors)
+ return true;
// If the resulting expression is new, then use it in place of the
// old expression in the template argument.
@@ -4705,9 +4854,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// Check template template parameters.
TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+ TemplateParameterList *Params = TempParm->getTemplateParameters();
+ if (TempParm->isExpandedParameterPack())
+ Params = TempParm->getExpansionTemplateParameters(ArgumentPackIndex);
+
// Substitute into the template parameter list of the template
// template parameter, since previously-supplied template arguments
// may appear within the template template parameter.
+ //
+ // FIXME: Skip this if the parameters aren't instantiation-dependent.
{
// Set up a template instantiation context.
LocalInstantiationScope Scope(*this);
@@ -4718,10 +4873,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
- TempParm = cast_or_null<TemplateTemplateParmDecl>(
- SubstDecl(TempParm, CurContext,
- MultiLevelTemplateArgumentList(TemplateArgs)));
- if (!TempParm)
+ Params = SubstTemplateParams(Params, CurContext,
+ MultiLevelTemplateArgumentList(TemplateArgs));
+ if (!Params)
return true;
}
@@ -4742,7 +4896,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (CheckTemplateArgument(TempParm, Arg, ArgumentPackIndex))
+ if (CheckTemplateTemplateArgument(Params, Arg))
return true;
Converted.push_back(Arg.getArgument());
@@ -4770,28 +4924,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return false;
}
-/// \brief Diagnose an arity mismatch in the
-static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
- SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs) {
- TemplateParameterList *Params = Template->getTemplateParameters();
- unsigned NumParams = Params->size();
- unsigned NumArgs = TemplateArgs.size();
-
- SourceRange Range;
- if (NumArgs > NumParams)
- Range = SourceRange(TemplateArgs[NumParams].getLocation(),
- TemplateArgs.getRAngleLoc());
- S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
- << (NumArgs > NumParams)
- << (int)S.getTemplateNameKindForDiagnostics(TemplateName(Template))
- << Template << Range;
- S.Diag(Template->getLocation(), diag::note_template_decl_here)
- << Params->getSourceRange();
- return true;
-}
-
-/// \brief Check whether the template parameter is a pack expansion, and if so,
+/// Check whether the template parameter is a pack expansion, and if so,
/// determine the number of parameters produced by that expansion. For instance:
///
/// \code
@@ -4844,10 +4977,18 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
// FIXME: If there's a more recent default argument that *is* visible,
// diagnose that it was declared too late.
- return diagnoseArityMismatch(S, TD, Loc, Args);
+ TemplateParameterList *Params = TD->getTemplateParameters();
+
+ S.Diag(Loc, diag::err_template_arg_list_different_arity)
+ << /*not enough args*/0
+ << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD))
+ << TD;
+ S.Diag(TD->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
}
-/// \brief Check that the given template argument list is well-formed
+/// Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(
TemplateDecl *Template, SourceLocation TemplateLoc,
@@ -4896,7 +5037,7 @@ bool Sema::CheckTemplateArgumentList(
} else if (ArgIdx == NumArgs && !PartialTemplateArgs) {
// Not enough arguments for this parameter pack.
Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
- << false
+ << /*not enough args*/0
<< (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
<< Template;
Diag(Template->getLocation(), diag::note_template_decl_here)
@@ -5091,8 +5232,16 @@ bool Sema::CheckTemplateArgumentList(
// If we have any leftover arguments, then there were too many arguments.
// Complain and fail.
- if (ArgIdx < NumArgs)
- return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs);
+ if (ArgIdx < NumArgs) {
+ Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << /*too many args*/1
+ << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
+ << Template
+ << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc());
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
+ }
// No problems found with the new argument list, propagate changes back
// to caller.
@@ -5197,6 +5346,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
return Visit(T->getElementType());
}
+bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType(
+ const DependentVectorType *T) {
+ return Visit(T->getElementType());
+}
+
bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
return Visit(T->getElementType());
}
@@ -5354,7 +5508,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
-/// \brief Check a template argument against its corresponding
+/// Check a template argument against its corresponding
/// template type parameter.
///
/// This routine implements the semantics of C++ [temp.arg.type]. It
@@ -5392,7 +5546,7 @@ enum NullPointerValueKind {
NPV_Error
};
-/// \brief Determine whether the given template argument is a null pointer
+/// Determine whether the given template argument is a null pointer
/// value of the appropriate type.
static NullPointerValueKind
isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
@@ -5488,7 +5642,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
return NPV_NotNullPointer;
}
-/// \brief Checks whether the given template argument is compatible with its
+/// Checks whether the given template argument is compatible with its
/// template parameter.
static bool CheckTemplateArgumentIsCompatibleWithParameter(
Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
@@ -5545,7 +5699,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter(
return false;
}
-/// \brief Checks whether the given template argument is the address
+/// Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
static bool
CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
@@ -5833,7 +5987,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return false;
}
-/// \brief Checks whether the given template argument is a pointer to
+/// Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
static bool CheckTemplateArgumentPointerToMember(Sema &S,
NonTypeTemplateParmDecl *Param,
@@ -5883,17 +6037,16 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
}
// A constant of pointer-to-member type.
else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
- if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
- if (VD->getType()->isMemberPointerType()) {
- if (isa<NonTypeTemplateParmDecl>(VD)) {
- if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
- } else {
- VD = cast<ValueDecl>(VD->getCanonicalDecl());
- Converted = TemplateArgument(VD, ParamType);
- }
- return Invalid;
+ ValueDecl *VD = DRE->getDecl();
+ if (VD->getType()->isMemberPointerType()) {
+ if (isa<NonTypeTemplateParmDecl>(VD)) {
+ if (Arg->isTypeDependent() || Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ } else {
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ Converted = TemplateArgument(VD, ParamType);
}
+ return Invalid;
}
}
@@ -5963,7 +6116,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
return true;
}
-/// \brief Check a template argument against its corresponding
+/// Check a template argument against its corresponding
/// non-type template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.nontype].
@@ -6118,7 +6271,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- a predefined __func__ variable
if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) {
if (isa<CXXUuidofExpr>(E)) {
- Converted = TemplateArgument(const_cast<Expr*>(E));
+ Converted = TemplateArgument(ArgResult.get());
break;
}
Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
@@ -6481,14 +6634,13 @@ static void DiagnoseTemplateParameterListArityMismatch(
Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);
-/// \brief Check a template argument against its corresponding
+/// Check a template argument against its corresponding
/// template template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.template].
/// It returns true if an error occurred, and false otherwise.
-bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- TemplateArgumentLoc &Arg,
- unsigned ArgumentPackIndex) {
+bool Sema::CheckTemplateTemplateArgument(TemplateParameterList *Params,
+ TemplateArgumentLoc &Arg) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template) {
@@ -6523,10 +6675,6 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
<< Template;
}
- TemplateParameterList *Params = Param->getTemplateParameters();
- if (Param->isExpandedParameterPack())
- Params = Param->getExpansionTemplateParameters(ArgumentPackIndex);
-
// C++1z [temp.arg.template]p3: (DR 150)
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
@@ -6553,7 +6701,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
Arg.getLocation());
}
-/// \brief Given a non-type template argument that refers to a
+/// Given a non-type template argument that refers to a
/// declaration and the type of its corresponding non-type template
/// parameter, produce an expression that properly refers to that
/// declaration.
@@ -6584,7 +6732,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
assert(Arg.getKind() == TemplateArgument::Declaration &&
"Only declaration template arguments permitted here");
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+ ValueDecl *VD = Arg.getAsDecl();
if (VD->getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
@@ -6676,7 +6824,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
return BuildDeclRefExpr(VD, T, VK, Loc);
}
-/// \brief Construct a new expression that refers to the given
+/// Construct a new expression that refers to the given
/// integral template argument with the given source-location
/// information.
///
@@ -6701,11 +6849,11 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
Expr *E;
if (T->isAnyCharacterType()) {
- // This does not need to handle u8 character literals because those are
- // of type char, and so can also be covered by an ASCII character literal.
CharacterLiteral::CharacterKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteral::Wide;
+ else if (T->isChar8Type() && getLangOpts().Char8)
+ Kind = CharacterLiteral::UTF8;
else if (T->isChar16Type())
Kind = CharacterLiteral::UTF16;
else if (T->isChar32Type())
@@ -6736,7 +6884,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
return E;
}
-/// \brief Match two template parameters within template parameter lists.
+/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
bool Complain,
Sema::TemplateParameterListEqualKind Kind,
@@ -6839,7 +6987,7 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
return true;
}
-/// \brief Diagnose a known arity mismatch when comparing template argument
+/// Diagnose a known arity mismatch when comparing template argument
/// lists.
static
void DiagnoseTemplateParameterListArityMismatch(Sema &S,
@@ -6861,7 +7009,7 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S,
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}
-/// \brief Determine whether the given template parameter lists are
+/// Determine whether the given template parameter lists are
/// equivalent.
///
/// \param New The new template parameter list, typically written in the
@@ -6953,7 +7101,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
return true;
}
-/// \brief Check whether a template can be declared within this scope.
+/// Check whether a template can be declared within this scope.
///
/// If the template declaration is valid in this scope, returns
/// false. Otherwise, issues a diagnostic and returns true.
@@ -7002,7 +7150,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
<< TemplateParams->getSourceRange();
}
-/// \brief Determine what kind of template specialization the given declaration
+/// Determine what kind of template specialization the given declaration
/// is.
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
if (!D)
@@ -7018,7 +7166,7 @@ static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
return TSK_Undeclared;
}
-/// \brief Check whether a specialization is well-formed in the current
+/// Check whether a specialization is well-formed in the current
/// context.
///
/// This routine determines whether a template specialization can be declared
@@ -7072,120 +7220,43 @@ static bool CheckTemplateSpecializationScope(Sema &S,
}
// C++ [temp.expl.spec]p2:
- // An explicit specialization shall be declared in the namespace
- // of which the template is a member, or, for member templates, in
- // the namespace of which the enclosing class or enclosing class
- // template is a member. An explicit specialization of a member
- // function, member class or static data member of a class
- // template shall be declared in the namespace of which the class
- // template is a member. Such a declaration may also be a
- // definition. If the declaration is not a definition, the
- // specialization may be defined later in the name- space in which
- // the explicit specialization was declared, or in a namespace
- // that encloses the one in which the explicit specialization was
- // declared.
+ // An explicit specialization may be declared in any scope in which
+ // the corresponding primary template may be defined.
if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
<< Specialized;
return true;
}
- if (S.CurContext->isRecord() && !IsPartialSpecialization) {
- if (S.getLangOpts().MicrosoftExt) {
- // Do not warn for class scope explicit specialization during
- // instantiation, warning was already emitted during pattern
- // semantic analysis.
- if (!S.inTemplateInstantiation())
- S.Diag(Loc, diag::ext_function_specialization_in_class)
- << Specialized;
- } else {
- S.Diag(Loc, diag::err_template_spec_decl_class_scope)
- << Specialized;
- return true;
- }
- }
-
- if (S.CurContext->isRecord() &&
- !S.CurContext->Equals(Specialized->getDeclContext())) {
- // Make sure that we're specializing in the right record context.
- // Otherwise, things can go horribly wrong.
- S.Diag(Loc, diag::err_template_spec_decl_class_scope)
- << Specialized;
- return true;
- }
-
// C++ [temp.class.spec]p6:
- // A class template partial specialization may be declared or redeclared
- // in any namespace scope in which its definition may be defined (14.5.1
- // and 14.5.2).
- DeclContext *SpecializedContext
- = Specialized->getDeclContext()->getEnclosingNamespaceContext();
- DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
-
- // Make sure that this redeclaration (or definition) occurs in an enclosing
- // namespace.
- // Note that HandleDeclarator() performs this check for explicit
- // specializations of function templates, static data members, and member
- // functions, so we skip the check here for those kinds of entities.
- // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
- // Should we refactor that check, so that it occurs later?
- if (!DC->Encloses(SpecializedContext) &&
- !(isa<FunctionTemplateDecl>(Specialized) ||
- isa<FunctionDecl>(Specialized) ||
- isa<VarTemplateDecl>(Specialized) ||
- isa<VarDecl>(Specialized))) {
+ // A class template partial specialization may be declared in any
+ // scope in which the primary template may be defined.
+ DeclContext *SpecializedContext =
+ Specialized->getDeclContext()->getRedeclContext();
+ DeclContext *DC = S.CurContext->getRedeclContext();
+
+ // Make sure that this redeclaration (or definition) occurs in the same
+ // scope or an enclosing namespace.
+ if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext)
+ : DC->Equals(SpecializedContext))) {
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
<< EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext)) {
+ else {
+ auto *ND = cast<NamedDecl>(SpecializedContext);
int Diag = diag::err_template_spec_redecl_out_of_scope;
- if (S.getLangOpts().MicrosoftExt)
+ if (S.getLangOpts().MicrosoftExt && !DC->isRecord())
Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
S.Diag(Loc, Diag) << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
- } else
- llvm_unreachable("unexpected namespace context for specialization");
+ << ND << isa<CXXRecordDecl>(ND);
+ }
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- } else if ((!PrevDecl ||
- getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
- getTemplateSpecializationKind(PrevDecl) ==
- TSK_ImplicitInstantiation)) {
- // C++ [temp.exp.spec]p2:
- // An explicit specialization shall be declared in the namespace of which
- // the template is a member, or, for member templates, in the namespace
- // of which the enclosing class or enclosing class template is a member.
- // An explicit specialization of a member function, member class or
- // static data member of a class template shall be declared in the
- // namespace of which the class template is a member.
- //
- // C++11 [temp.expl.spec]p2:
- // An explicit specialization shall be declared in a namespace enclosing
- // the specialized template.
- // C++11 [temp.explicit]p3:
- // An explicit instantiation shall appear in an enclosing namespace of its
- // template.
- if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
- bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext);
- if (isa<TranslationUnitDecl>(SpecializedContext)) {
- assert(!IsCPlusPlus11Extension &&
- "DC encloses TU but isn't in enclosing namespace set");
- S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
- << EntityKind << Specialized;
- } else if (isa<NamespaceDecl>(SpecializedContext)) {
- int Diag;
- if (!IsCPlusPlus11Extension)
- Diag = diag::err_template_spec_decl_out_of_scope;
- else if (!S.getLangOpts().CPlusPlus11)
- Diag = diag::ext_template_spec_decl_out_of_scope;
- else
- Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
- S.Diag(Loc, Diag)
- << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext);
- }
- S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- }
+ // Don't allow specializing in the wrong class during error recovery.
+ // Otherwise, things can go horribly wrong.
+ if (DC->isRecord())
+ return true;
}
return false;
@@ -7211,7 +7282,7 @@ static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
return Checker.MatchLoc;
}
-/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs
+/// Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
static bool CheckNonTypeTemplatePartialSpecializationArgs(
Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param,
@@ -7299,7 +7370,7 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
return false;
}
-/// \brief Check the non-type template arguments of a class template
+/// Check the non-type template arguments of a class template
/// partial specialization according to C++ [temp.class.spec]p9.
///
/// \param TemplateNameLoc the location of the template name.
@@ -7335,16 +7406,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs(
return false;
}
-DeclResult
-Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
- TagUseKind TUK,
- SourceLocation KWLoc,
- SourceLocation ModulePrivateLoc,
- TemplateIdAnnotation &TemplateId,
- AttributeList *Attr,
- MultiTemplateParamsArg
- TemplateParameterLists,
- SkipBodyInfo *SkipBody) {
+DeclResult Sema::ActOnClassTemplateSpecialization(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId,
+ const ParsedAttributesView &Attr,
+ MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
assert(TUK != TUK_Reference && "References are not specializations");
CXXScopeSpec &SS = TemplateId.SS;
@@ -7586,10 +7652,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
ClassTemplate->AddSpecialization(Specialization, InsertPos);
if (CurContext->isDependentContext()) {
- // -fms-extensions permits specialization of nested classes without
- // fully specializing the outer class(es).
- assert(getLangOpts().MicrosoftExt &&
- "Only possible with -fms-extensions!");
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(
CanonTemplate, Converted);
@@ -7649,8 +7711,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
}
- if (Attr)
- ProcessDeclAttributeList(S, Specialization, Attr);
+ ProcessDeclAttributeList(S, Specialization, Attr);
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
@@ -7717,7 +7778,7 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
return NewDecl;
}
-/// \brief Strips various properties off an implicit instantiation
+/// Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
D->dropAttr<DLLImportAttr>();
@@ -7727,7 +7788,7 @@ static void StripImplicitInstantiation(NamedDecl *D) {
FD->setInlineSpecified(false);
}
-/// \brief Compute the diagnostic location for an explicit instantiation
+/// Compute the diagnostic location for an explicit instantiation
// declaration or definition.
static SourceLocation DiagLocForExplicitInstantiation(
NamedDecl* D, SourceLocation PointOfInstantiation) {
@@ -7744,7 +7805,7 @@ static SourceLocation DiagLocForExplicitInstantiation(
return PrevDiagLoc;
}
-/// \brief Diagnose cases where we have an explicit template specialization
+/// Diagnose cases where we have an explicit template specialization
/// before/after an explicit template instantiation, producing diagnostics
/// for those cases where they are required and determining whether the
/// new specialization/instantiation will have any effect.
@@ -7890,7 +7951,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
return false;
case TSK_ExplicitInstantiationDeclaration:
- // We're explicity instantiating a definition for something for which we
+ // We're explicitly instantiating a definition for something for which we
// were previously asked to suppress instantiations. That's fine.
// C++0x [temp.explicit]p4:
@@ -7929,7 +7990,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
llvm_unreachable("Missing specialization/instantiation case?");
}
-/// \brief Perform semantic analysis for the given dependent function
+/// Perform semantic analysis for the given dependent function
/// template specialization.
///
/// The only possible way to get a dependent function template specialization
@@ -7952,24 +8013,41 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
// the correct context.
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
LookupResult::Filter F = Previous.makeFilter();
+ enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing };
+ SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates;
while (F.hasNext()) {
NamedDecl *D = F.next()->getUnderlyingDecl();
- if (!isa<FunctionTemplateDecl>(D) ||
- !FDLookupContext->InEnclosingNamespaceSetOf(
- D->getDeclContext()->getRedeclContext()))
+ if (!isa<FunctionTemplateDecl>(D)) {
+ F.erase();
+ DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D));
+ continue;
+ }
+
+ if (!FDLookupContext->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext())) {
F.erase();
+ DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D));
+ continue;
+ }
}
F.done();
- // Should this be diagnosed here?
- if (Previous.empty()) return true;
+ if (Previous.empty()) {
+ Diag(FD->getLocation(),
+ diag::err_dependent_function_template_spec_no_match);
+ for (auto &P : DiscardedCandidates)
+ Diag(P.second->getLocation(),
+ diag::note_dependent_function_template_spec_discard_reason)
+ << P.first;
+ return true;
+ }
FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
ExplicitTemplateArgs);
return false;
}
-/// \brief Perform semantic analysis for the given function template
+/// Perform semantic analysis for the given function template
/// specialization.
///
/// This routine performs all of the semantic analysis required for an
@@ -8192,7 +8270,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
return false;
}
-/// \brief Perform semantic analysis for the given non-template member
+/// Perform semantic analysis for the given non-template member
/// specialization.
///
/// This routine performs all of the semantic analysis required for an
@@ -8402,7 +8480,7 @@ void Sema::CompleteMemberSpecialization(NamedDecl *Member,
llvm_unreachable("unknown member specialization kind");
}
-/// \brief Check the scope of an explicit instantiation.
+/// Check the scope of an explicit instantiation.
///
/// \returns true if a serious error occurs, false otherwise.
static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
@@ -8456,7 +8534,7 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
return false;
}
-/// \brief Determine whether the given scope specifier has a template-id in it.
+/// Determine whether the given scope specifier has a template-id in it.
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
if (!SS.isSet())
return false;
@@ -8502,19 +8580,12 @@ static void dllExportImportClassTemplateSpecialization(
}
// Explicit instantiation of a class template specialization
-DeclResult
-Sema::ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- const CXXScopeSpec &SS,
- TemplateTy TemplateD,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc,
- AttributeList *Attr) {
+DeclResult Sema::ActOnExplicitInstantiation(
+ Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
+ unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
+ TemplateTy TemplateD, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc, const ParsedAttributesView &Attr) {
// Find the class template we're specializing
TemplateName Name = TemplateD.get();
TemplateDecl *TD = Name.getAsTemplateDecl();
@@ -8555,11 +8626,11 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (TSK == TSK_ExplicitInstantiationDeclaration) {
// Check for dllexport class template instantiation declarations.
- for (AttributeList *A = Attr; A; A = A->getNext()) {
- if (A->getKind() == AttributeList::AT_DLLExport) {
+ for (const ParsedAttr &AL : Attr) {
+ if (AL.getKind() == ParsedAttr::AT_DLLExport) {
Diag(ExternLoc,
diag::warn_attribute_dllexport_explicit_instantiation_decl);
- Diag(A->getLoc(), diag::note_attribute);
+ Diag(AL.getLoc(), diag::note_attribute);
break;
}
}
@@ -8579,10 +8650,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Check for dllimport class template instantiation definitions.
bool DLLImport =
ClassTemplate->getTemplatedDecl()->getAttr<DLLImportAttr>();
- for (AttributeList *A = Attr; A; A = A->getNext()) {
- if (A->getKind() == AttributeList::AT_DLLImport)
+ for (const ParsedAttr &AL : Attr) {
+ if (AL.getKind() == ParsedAttr::AT_DLLImport)
DLLImport = true;
- if (A->getKind() == AttributeList::AT_DLLExport) {
+ if (AL.getKind() == ParsedAttr::AT_DLLExport) {
// dllexport trumps dllimport here.
DLLImport = false;
break;
@@ -8692,8 +8763,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setBraceRange(SourceRange());
bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>();
- if (Attr)
- ProcessDeclAttributeList(S, Specialization, Attr);
+ ProcessDeclAttributeList(S, Specialization, Attr);
// Add the explicit instantiation into its lexical context. However,
// since explicit instantiations are never found by name lookup, we
@@ -8791,15 +8861,11 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Explicit instantiation of a member class of a class template.
DeclResult
-Sema::ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- AttributeList *Attr) {
+Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+ SourceLocation TemplateLoc, unsigned TagSpec,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ const ParsedAttributesView &Attr) {
bool Owned = false;
bool IsDependent = false;
@@ -9101,8 +9167,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (PrevTemplate) {
// Merge attributes.
- if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList())
- ProcessDeclAttributeList(S, Prev, Attr);
+ ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
}
if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
@@ -9138,7 +9203,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// template.
UnresolvedSet<8> TemplateMatches;
FunctionDecl *NonTemplateMatch = nullptr;
- AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
@@ -9186,7 +9250,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (LangOpts.CUDA &&
IdentifyCUDATarget(Specialization,
/* IgnoreImplicitHDAttributes = */ true) !=
- IdentifyCUDATarget(Attr)) {
+ IdentifyCUDATarget(D.getDeclSpec().getAttributes())) {
FailedCandidates.addCandidate().set(
P.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info));
@@ -9265,8 +9329,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return (Decl*) nullptr;
}
- if (Attr)
- ProcessDeclAttributeList(S, Specialization, Attr);
+ ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes());
// In MSVC mode, dllimported explicit instantiation definitions are treated as
// instantiation declarations.
@@ -9478,8 +9541,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
return false;
- const TemplateSpecializationType *EnableIfTST =
- cast<TemplateSpecializationType>(EnableIfTSTLoc.getTypePtr());
+ const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr();
// ... which names a complete class template declaration...
const TemplateDecl *EnableIfDecl =
@@ -9511,7 +9573,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
return true;
}
-/// \brief Build the type that describes a C++ typename specifier,
+/// Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
@@ -9686,7 +9748,7 @@ namespace {
: TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
Loc(Loc), Entity(Entity) { }
- /// \brief Determine whether the given type \p T has already been
+ /// Determine whether the given type \p T has already been
/// transformed.
///
/// For the purposes of type reconstruction, a type has already been
@@ -9695,14 +9757,14 @@ namespace {
return T.isNull() || !T->isDependentType();
}
- /// \brief Returns the location of the entity whose type is being
+ /// Returns the location of the entity whose type is being
/// rebuilt.
SourceLocation getBaseLocation() { return Loc; }
- /// \brief Returns the name of the entity whose type is being rebuilt.
+ /// Returns the name of the entity whose type is being rebuilt.
DeclarationName getBaseEntity() { return Entity; }
- /// \brief Sets the "base" location and entity when that
+ /// Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
@@ -9716,7 +9778,7 @@ namespace {
};
} // end anonymous namespace
-/// \brief Rebuilds a type within the context of the current instantiation.
+/// Rebuilds a type within the context of the current instantiation.
///
/// The type \p T is part of the type of an out-of-line member definition of
/// a class template (or class template partial specialization) that was parsed
@@ -9774,7 +9836,7 @@ bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
return false;
}
-/// \brief Rebuild the template parameters now that we know we're in a current
+/// Rebuild the template parameters now that we know we're in a current
/// instantiation.
bool Sema::RebuildTemplateParamsInCurrentInstantiation(
TemplateParameterList *Params) {
@@ -9813,7 +9875,7 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation(
return false;
}
-/// \brief Produces a formatted string that describes the binding of
+/// Produces a formatted string that describes the binding of
/// template parameters to template arguments.
std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
@@ -9891,7 +9953,7 @@ bool Sema::IsInsideALocalClassWithinATemplateFunction() {
}
namespace {
-/// \brief Walk the path from which a declaration was instantiated, and check
+/// Walk the path from which a declaration was instantiated, and check
/// that every explicit specialization along that path is visible. This enforces
/// C++ [temp.expl.spec]/6:
///
@@ -10027,7 +10089,7 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec);
}
-/// \brief Check whether a template partial specialization that we've discovered
+/// Check whether a template partial specialization that we've discovered
/// is hidden, and produce suitable diagnostics if so.
void Sema::checkPartialSpecializationVisibility(SourceLocation Loc,
NamedDecl *Spec) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index d09cf9933ecf..df46d6115a20 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1,60 +1,97 @@
-//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
+//===- SemaTemplateDeduction.cpp - Template Argument Deduction ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===/
//
-// This file implements C++ template argument deduction.
+//===----------------------------------------------------------------------===//
//
-//===----------------------------------------------------------------------===/
+// This file implements C++ template argument deduction.
+//
+//===----------------------------------------------------------------------===//
#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
-#include "clang/AST/DeclObjC.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/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeOrdering.h"
-#include "clang/Sema/DeclSpec.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/AST/UnresolvedSet.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.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/Optional.h"
#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
+#include <cassert>
+#include <tuple>
+#include <utility>
namespace clang {
- using namespace sema;
- /// \brief Various flags that control template argument deduction.
+
+ /// Various flags that control template argument deduction.
///
/// These flags can be bitwise-OR'd together.
enum TemplateDeductionFlags {
- /// \brief No template argument deduction flags, which indicates the
+ /// No template argument deduction flags, which indicates the
/// strictest results for template argument deduction (as used for, e.g.,
/// matching class template partial specializations).
TDF_None = 0,
- /// \brief Within template argument deduction from a function call, we are
+
+ /// Within template argument deduction from a function call, we are
/// matching with a parameter type for which the original parameter was
/// a reference.
TDF_ParamWithReferenceType = 0x1,
- /// \brief Within template argument deduction from a function call, we
+
+ /// Within template argument deduction from a function call, we
/// are matching in a case where we ignore cv-qualifiers.
TDF_IgnoreQualifiers = 0x02,
- /// \brief Within template argument deduction from a function call,
+
+ /// Within template argument deduction from a function call,
/// we are matching in a case where we can perform template argument
/// deduction from a template-id of a derived class of the argument type.
TDF_DerivedClass = 0x04,
- /// \brief Allow non-dependent types to differ, e.g., when performing
+
+ /// Allow non-dependent types to differ, e.g., when performing
/// template argument deduction from a function call where conversions
/// may apply.
TDF_SkipNonDependent = 0x08,
- /// \brief Whether we are performing template argument deduction for
+
+ /// Whether we are performing template argument deduction for
/// parameters and arguments in a top-level template argument
TDF_TopLevelParameterTypeList = 0x10,
- /// \brief Within template argument deduction from overload resolution per
+
+ /// Within template argument deduction from overload resolution per
/// C++ [over.over] allow matching function types that are compatible in
/// terms of noreturn and default calling convention adjustments, or
/// similarly matching a declared template specialization against a
@@ -62,12 +99,18 @@ namespace clang {
/// deduction where the parameter is a function type that can be converted
/// to the argument type.
TDF_AllowCompatibleFunctionType = 0x20,
+
+ /// Within template argument deduction for a conversion function, we are
+ /// matching with an argument type for which the original argument was
+ /// a reference.
+ TDF_ArgWithReferenceType = 0x40,
};
}
using namespace clang;
+using namespace sema;
-/// \brief Compare two APSInts, extending and switching the sign as
+/// Compare two APSInts, extending and switching the sign as
/// necessary to compare their values regardless of underlying type.
static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
if (Y.getBitWidth() > X.getBitWidth())
@@ -125,14 +168,14 @@ static void MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced, unsigned Level,
llvm::SmallBitVector &Deduced);
-/// \brief If the given expression is of a form that permits the deduction
+/// If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
static NonTypeTemplateParmDecl *
getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
// If we are within an alias template, the expression may have undergone
// any number of parameter substitutions already.
- while (1) {
+ while (true) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
else if (SubstNonTypeTemplateParmExpr *Subst =
@@ -150,7 +193,7 @@ getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
return nullptr;
}
-/// \brief Determine whether two declaration pointers refer to the same
+/// Determine whether two declaration pointers refer to the same
/// declaration.
static bool isSameDeclaration(Decl *X, Decl *Y) {
if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
@@ -161,7 +204,7 @@ static bool isSameDeclaration(Decl *X, Decl *Y) {
return X->getCanonicalDecl() == Y->getCanonicalDecl();
}
-/// \brief Verify that the given, deduced template arguments are compatible.
+/// Verify that the given, deduced template arguments are compatible.
///
/// \returns The deduced template argument, or a NULL template argument if
/// the deduced template arguments were incompatible.
@@ -270,7 +313,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
return Y;
}
- // If we deduced two declarations, make sure they they refer to the
+ // If we deduced two declarations, make sure that they refer to the
// same declaration.
if (Y.getKind() == TemplateArgument::Declaration &&
isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
@@ -297,7 +340,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
- case TemplateArgument::Pack:
+ case TemplateArgument::Pack: {
if (Y.getKind() != TemplateArgument::Pack ||
X.pack_size() != Y.pack_size())
return DeducedTemplateArgument();
@@ -319,11 +362,12 @@ checkDeducedTemplateArguments(ASTContext &Context,
TemplateArgument::CreatePackCopy(Context, NewPack),
X.wasDeducedFromArrayBound() && Y.wasDeducedFromArrayBound());
}
+ }
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// as the given deduced template argument. All non-type template parameter
/// deduction is funneled through here.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
@@ -371,7 +415,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
/*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound());
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given integral constant.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
@@ -385,7 +429,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
ValueType, Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given null pointer template argument type.
static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
@@ -402,7 +446,7 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Value->getType(), Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
@@ -415,7 +459,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Value->getType(), Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given declaration.
///
/// \returns true if deduction succeeded, false otherwise.
@@ -475,7 +519,7 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
-/// \brief Deduce the template arguments by comparing the template parameter
+/// Deduce the template arguments by comparing the template parameter
/// type (which is a template-id) with the template argument type.
///
/// \param S the Sema
@@ -560,7 +604,7 @@ DeduceTemplateArguments(Sema &S,
Deduced, /*NumberOfArgumentsMustMatch=*/true);
}
-/// \brief Determines whether the given type is an opaque type that
+/// Determines whether the given type is an opaque type that
/// might be more qualified when instantiated.
static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
switch (T->getTypeClass()) {
@@ -584,30 +628,7 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
}
}
-/// \brief Retrieve the depth and index of a template parameter.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(NamedDecl *ND) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
- return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-}
-
-/// \brief Retrieve the depth and index of an unexpanded parameter pack.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(UnexpandedParameterPack UPP) {
- if (const TemplateTypeParmType *TTP
- = UPP.first.dyn_cast<const TemplateTypeParmType *>())
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- return getDepthAndIndex(UPP.first.get<NamedDecl *>());
-}
-
-/// \brief Helper function to build a TemplateParameter when we don't
+/// Helper function to build a TemplateParameter when we don't
/// know its type statically.
static TemplateParameter makeTemplateParameter(Decl *D) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
@@ -618,10 +639,21 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
+/// If \p Param is an expanded parameter pack, get the number of expansions.
+static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ if (NTTP->isExpandedParameterPack())
+ return NTTP->getNumExpansionTypes();
+
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param))
+ if (TTP->isExpandedParameterPack())
+ return TTP->getNumExpansionTemplateParameters();
+
+ return None;
+}
+
/// A pack that we're currently deducing.
struct clang::DeducedPack {
- DeducedPack(unsigned Index) : Index(Index), Outer(nullptr) {}
-
// The index of the pack.
unsigned Index;
@@ -636,17 +668,93 @@ struct clang::DeducedPack {
SmallVector<DeducedTemplateArgument, 4> New;
// The outer deduction for this pack, if any.
- DeducedPack *Outer;
+ DeducedPack *Outer = nullptr;
+
+ DeducedPack(unsigned Index) : Index(Index) {}
};
namespace {
+
/// A scope in which we're performing pack deduction.
class PackDeductionScope {
public:
+ /// Prepare to deduce the packs named within Pattern.
PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info, TemplateArgument Pattern)
: S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ unsigned NumNamedPacks = addPacks(Pattern);
+ finishConstruction(NumNamedPacks);
+ }
+
+ /// Prepare to directly deduce arguments of the parameter with index \p Index.
+ PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info, unsigned Index)
+ : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ addPack(Index);
+ finishConstruction(1);
+ }
+
+private:
+ void addPack(unsigned Index) {
+ // Save the deduced template argument for the parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ DeducedPack Pack(Index);
+ Pack.Saved = Deduced[Index];
+ Deduced[Index] = TemplateArgument();
+
+ // FIXME: What if we encounter multiple packs with different numbers of
+ // pre-expanded expansions? (This should already have been diagnosed
+ // during substitution.)
+ if (Optional<unsigned> ExpandedPackExpansions =
+ getExpandedPackSize(TemplateParams->getParam(Index)))
+ FixedNumExpansions = ExpandedPackExpansions;
+
+ Packs.push_back(Pack);
+ }
+
+ unsigned addPacks(TemplateArgument Pattern) {
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallBitVector SawIndices(TemplateParams->size());
+
+ auto AddPack = [&](unsigned Index) {
+ if (SawIndices[Index])
+ return;
+ SawIndices[Index] = true;
+ addPack(Index);
+ };
+
+ // First look for unexpanded packs in the pattern.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ unsigned Depth, Index;
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ if (Depth == Info.getDeducedDepth())
+ AddPack(Index);
+ }
+ assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
+
+ unsigned NumNamedPacks = Packs.size();
+
+ // We can also have deduced template parameters that do not actually
+ // appear in the pattern, but can be deduced by it (the type of a non-type
+ // template parameter pack, in particular). These won't have prevented us
+ // from partially expanding the pack.
+ llvm::SmallBitVector Used(TemplateParams->size());
+ MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
+ Info.getDeducedDepth(), Used);
+ for (int Index = Used.find_first(); Index != -1;
+ Index = Used.find_next(Index))
+ if (TemplateParams->getParam(Index)->isParameterPack())
+ AddPack(Index);
+
+ return NumNamedPacks;
+ }
+
+ void finishConstruction(unsigned NumNamedPacks) {
// Dig out the partially-substituted pack, if there is one.
const TemplateArgument *PartialPackArgs = nullptr;
unsigned NumPartialPackArgs = 0;
@@ -656,60 +764,29 @@ public:
&PartialPackArgs, &NumPartialPackArgs))
PartialPackDepthIndex = getDepthAndIndex(Partial);
- // Compute the set of template parameter indices that correspond to
- // parameter packs expanded by the pack expansion.
- {
- llvm::SmallBitVector SawIndices(TemplateParams->size());
-
- auto AddPack = [&](unsigned Index) {
- if (SawIndices[Index])
- return;
- SawIndices[Index] = true;
-
- // Save the deduced template argument for the parameter pack expanded
- // by this pack expansion, then clear out the deduction.
- DeducedPack Pack(Index);
- Pack.Saved = Deduced[Index];
- Deduced[Index] = TemplateArgument();
-
- Packs.push_back(Pack);
- };
-
- // First look for unexpanded packs in the pattern.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
- for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- unsigned Depth, Index;
- std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == Info.getDeducedDepth())
- AddPack(Index);
+ // This pack expansion will have been partially or fully expanded if
+ // it only names explicitly-specified parameter packs (including the
+ // partially-substituted one, if any).
+ bool IsExpanded = true;
+ for (unsigned I = 0; I != NumNamedPacks; ++I) {
+ if (Packs[I].Index >= Info.getNumExplicitArgs()) {
+ IsExpanded = false;
+ IsPartiallyExpanded = false;
+ break;
+ }
+ if (PartialPackDepthIndex ==
+ std::make_pair(Info.getDeducedDepth(), Packs[I].Index)) {
+ IsPartiallyExpanded = true;
}
- assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
-
- // This pack expansion will have been partially expanded iff the only
- // unexpanded parameter pack within it is the partially-substituted pack.
- IsPartiallyExpanded =
- Packs.size() == 1 &&
- PartialPackDepthIndex ==
- std::make_pair(Info.getDeducedDepth(), Packs.front().Index);
-
- // Skip over the pack elements that were expanded into separate arguments.
- if (IsPartiallyExpanded)
- PackElements += NumPartialPackArgs;
-
- // We can also have deduced template parameters that do not actually
- // appear in the pattern, but can be deduced by it (the type of a non-type
- // template parameter pack, in particular). These won't have prevented us
- // from partially expanding the pack.
- llvm::SmallBitVector Used(TemplateParams->size());
- MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
- Info.getDeducedDepth(), Used);
- for (int Index = Used.find_first(); Index != -1;
- Index = Used.find_next(Index))
- if (TemplateParams->getParam(Index)->isParameterPack())
- AddPack(Index);
}
+ // Skip over the pack elements that were expanded into separate arguments.
+ // If we partially expanded, this is the number of partial arguments.
+ if (IsPartiallyExpanded)
+ PackElements += NumPartialPackArgs;
+ else if (IsExpanded)
+ PackElements += *FixedNumExpansions;
+
for (auto &Pack : Packs) {
if (Info.PendingDeducedPacks.size() > Pack.Index)
Pack.Outer = Info.PendingDeducedPacks[Pack.Index];
@@ -728,12 +805,13 @@ public:
// FIXME: If we could represent a "depth i, index j, pack elem k"
// parameter, we could substitute the partially-substituted pack
// everywhere and avoid this.
- if (Pack.New.size() > PackElements)
+ if (!IsPartiallyExpanded)
Deduced[Pack.Index] = Pack.New[PackElements];
}
}
}
+public:
~PackDeductionScope() {
for (auto &Pack : Packs)
Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
@@ -743,6 +821,18 @@ public:
/// sequence of (prior) function parameters / template arguments.
bool isPartiallyExpanded() { return IsPartiallyExpanded; }
+ /// Determine whether this pack expansion scope has a known, fixed arity.
+ /// This happens if it involves a pack from an outer template that has
+ /// (notionally) already been expanded.
+ bool hasFixedArity() { return FixedNumExpansions.hasValue(); }
+
+ /// Determine whether the next element of the argument is still part of this
+ /// pack. This is the case unless the pack is already expanded to a fixed
+ /// length.
+ bool hasNextElement() {
+ return !FixedNumExpansions || *FixedNumExpansions > PackElements;
+ }
+
/// Move to deducing the next element in each pack that is being deduced.
void nextPackElement() {
// Capture the deduced template arguments for each parameter pack expanded
@@ -765,16 +855,24 @@ public:
++PackElements;
}
- /// \brief Finish template argument deduction for a set of argument packs,
+ /// Finish template argument deduction for a set of argument packs,
/// producing the argument packs and checking for consistency with prior
/// deductions.
- Sema::TemplateDeductionResult finish() {
+ Sema::TemplateDeductionResult
+ finish(bool TreatNoDeductionsAsNonDeduced = true) {
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
for (auto &Pack : Packs) {
// Put back the old value for this pack.
Deduced[Pack.Index] = Pack.Saved;
+ // If we are deducing the size of this pack even if we didn't deduce any
+ // values for it, then make sure we build a pack of the right size.
+ // FIXME: Should we always deduce the size, even if the pack appears in
+ // a non-deduced context?
+ if (!TreatNoDeductionsAsNonDeduced)
+ Pack.New.resize(PackElements);
+
// Build or find a new value for this pack.
DeducedTemplateArgument NewPack;
if (PackElements && Pack.New.empty()) {
@@ -830,14 +928,24 @@ public:
Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
}
+ NamedDecl *Param = TemplateParams->getParam(Pack.Index);
if (Result.isNull()) {
- Info.Param =
- makeTemplateParameter(TemplateParams->getParam(Pack.Index));
+ Info.Param = makeTemplateParameter(Param);
Info.FirstArg = OldPack;
Info.SecondArg = NewPack;
return Sema::TDK_Inconsistent;
}
+ // If we have a pre-expanded pack and we didn't deduce enough elements
+ // for it, fail deduction.
+ if (Optional<unsigned> Expansions = getExpandedPackSize(Param)) {
+ if (*Expansions != PackElements) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = Result;
+ return Sema::TDK_IncompletePack;
+ }
+ }
+
*Loc = Result;
}
@@ -851,12 +959,15 @@ private:
TemplateDeductionInfo &Info;
unsigned PackElements = 0;
bool IsPartiallyExpanded = false;
+ /// The number of expansions, if we have a fully-expanded pack in this scope.
+ Optional<unsigned> FixedNumExpansions;
SmallVector<DeducedPack, 2> Packs;
};
+
} // namespace
-/// \brief Deduce the template arguments by comparing the list of parameter
+/// Deduce the template arguments by comparing the list of parameter
/// types to the list of argument types, as in the parameter-type-lists of
/// function types (C++ [temp.deduct.type]p10).
///
@@ -895,12 +1006,6 @@ DeduceTemplateArguments(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false) {
- // Fast-path check to see if we have too many/too few arguments.
- if (NumParams != NumArgs &&
- !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
- !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
- return Sema::TDK_MiscellaneousDeductionFailure;
-
// C++0x [temp.deduct.type]p10:
// Similarly, if P has a form that contains (T), then each parameter type
// Pi of the respective parameter-type- list of P is compared with the
@@ -937,13 +1042,6 @@ DeduceTemplateArguments(Sema &S,
continue;
}
- // C++0x [temp.deduct.type]p5:
- // The non-deduced contexts are:
- // - A function parameter pack that does not occur at the end of the
- // parameter-declaration-clause.
- if (ParamIdx + 1 < NumParams)
- return Sema::TDK_Success;
-
// C++0x [temp.deduct.type]p10:
// If the parameter-declaration corresponding to Pi is a function
// parameter pack, then the type of its declarator- id is compared with
@@ -954,15 +1052,43 @@ DeduceTemplateArguments(Sema &S,
QualType Pattern = Expansion->getPattern();
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
- for (; ArgIdx < NumArgs; ++ArgIdx) {
- // Deduce template arguments from the pattern.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
- Args[ArgIdx], Info, Deduced,
- TDF, PartialOrdering))
- return Result;
+ // A pack scope with fixed arity is not really a pack any more, so is not
+ // a non-deduced context.
+ if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity()) {
+ for (; ArgIdx < NumArgs && PackScope.hasNextElement(); ++ArgIdx) {
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
+ Args[ArgIdx], Info, Deduced,
+ TDF, PartialOrdering))
+ return Result;
- PackScope.nextPackElement();
+ PackScope.nextPackElement();
+ }
+ } else {
+ // C++0x [temp.deduct.type]p5:
+ // The non-deduced contexts are:
+ // - A function parameter pack that does not occur at the end of the
+ // parameter-declaration-clause.
+ //
+ // FIXME: There is no wording to say what we should do in this case. We
+ // choose to resolve this by applying the same rule that is applied for a
+ // function call: that is, deduce all contained packs to their
+ // explicitly-specified values (or to <> if there is no such value).
+ //
+ // This is seemingly-arbitrarily different from the case of a template-id
+ // with a non-trailing pack-expansion in its arguments, which renders the
+ // entire template-argument-list a non-deduced context.
+
+ // If the parameter type contains an explicitly-specified pack that we
+ // could not expand, skip the number of parameters notionally created
+ // by the expansion.
+ Optional<unsigned> NumExpansions = Expansion->getNumExpansions();
+ if (NumExpansions && !PackScope.isPartiallyExpanded()) {
+ for (unsigned I = 0; I != *NumExpansions && ArgIdx < NumArgs;
+ ++I, ++ArgIdx)
+ PackScope.nextPackElement();
+ }
}
// Build argument packs for each of the parameter packs expanded by this
@@ -978,8 +1104,10 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_Success;
}
-/// \brief Determine whether the parameter has qualifiers that are either
-/// inconsistent with or a superset of the argument's qualifiers.
+/// Determine whether the parameter has qualifiers that the argument
+/// lacks. Put another way, determine whether there is no way to add
+/// a deduced set of qualifiers to the ParamType that would result in
+/// its qualifiers matching those of the ArgType.
static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
QualType ArgType) {
Qualifiers ParamQs = ParamType.getQualifiers();
@@ -1003,13 +1131,11 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
ParamQs.hasObjCLifetime())
return true;
- // CVR qualifier superset.
- return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
- ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
- == ParamQs.getCVRQualifiers());
+ // CVR qualifiers inconsistent or a superset.
+ return (ParamQs.getCVRQualifiers() & ~ArgQs.getCVRQualifiers()) != 0;
}
-/// \brief Compare types for equality with respect to possibly compatible
+/// Compare types for equality with respect to possibly compatible
/// function types (noreturn adjustment, implicit calling conventions). If any
/// of parameter and argument is not a function, just perform type comparison.
///
@@ -1061,7 +1187,7 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) {
return false;
}
-/// \brief Deduce the template arguments by comparing the parameter type and
+/// Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
/// \param S the semantic analysis object within which we are deducing
@@ -1232,6 +1358,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_Underqualified;
}
+ // Do not match a function type with a cv-qualified type.
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584
+ if (Arg->isFunctionType() && Param.hasQualifiers()) {
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
"saw template type parameter with wrong depth");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
@@ -1307,6 +1439,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (TDF & TDF_ParamWithReferenceType) {
if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
return Sema::TDK_NonDeducedMismatch;
+ } else if (TDF & TDF_ArgWithReferenceType) {
+ // C++ [temp.deduct.conv]p4:
+ // If the original A is a reference type, A can be more cv-qualified
+ // than the deduced A
+ if (!Arg.getQualifiers().compatiblyIncludes(Param.getQualifiers()))
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Strip out all extra qualifiers from the argument to figure out the
+ // type we're converting to, prior to the qualification conversion.
+ Qualifiers Quals;
+ Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
+ Arg = S.Context.getQualifiedType(Arg, Param.getQualifiers());
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
@@ -1357,7 +1501,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Enum:
case Type::ObjCObject:
case Type::ObjCInterface:
- case Type::ObjCObjectPointer: {
+ case Type::ObjCObjectPointer:
if (TDF & TDF_SkipNonDependent)
return Sema::TDK_Success;
@@ -1367,7 +1511,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
- }
// _Complex T [placeholder extension]
case Type::Complex:
@@ -1561,7 +1704,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
"saw non-type template parameter with wrong depth");
llvm::APSInt Noexcept(1);
- switch (FunctionProtoArg->canThrow(S.Context)) {
+ switch (FunctionProtoArg->canThrow()) {
case CT_Cannot:
Noexcept = 1;
LLVM_FALLTHROUGH;
@@ -1582,11 +1725,14 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
}
// FIXME: Detect non-deduced exception specification mismatches?
+ //
+ // Careful about [temp.deduct.call] and [temp.deduct.conv], which allow
+ // top-level differences in noexcept-specifications.
return Sema::TDK_Success;
}
- case Type::InjectedClassName: {
+ case Type::InjectedClassName:
// Treat a template's injected-class-name as if the template
// specialization type had been used.
Param = cast<InjectedClassNameType>(Param)
@@ -1594,7 +1740,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
assert(isa<TemplateSpecializationType>(Param) &&
"injected class name is not a template specialization type");
LLVM_FALLTHROUGH;
- }
// template-name<T> (where template-name refers to a class template)
// template-name<i>
@@ -1792,6 +1937,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
+ case Type::DependentVector: {
+ const auto *VectorParam = cast<DependentVectorType>(Param);
+
+ if (const auto *VectorArg = dyn_cast<VectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, VectorParam->getElementType(),
+ VectorArg->getElementType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+ ArgSize = VectorArg->getNumElements();
+ // Note that we use the "array bound" rules here; just like in that
+ // case, we don't have any particular type for the vector size, but
+ // we can provide one if necessary.
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
+ S.Context.UnsignedIntTy, true,
+ Info, Deduced);
+ }
+
+ if (const auto *VectorArg = dyn_cast<DependentVectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, VectorParam->getElementType(),
+ VectorArg->getElementType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ Info, VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced);
+ }
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
// (clang extension)
//
// T __attribute__(((ext_vector_type(N))))
@@ -1996,7 +2189,7 @@ DeduceTemplateArguments(Sema &S,
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
- case TemplateArgument::Expression: {
+ case TemplateArgument::Expression:
if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
@@ -2025,7 +2218,7 @@ DeduceTemplateArguments(Sema &S,
// Can't deduce anything, but that's okay.
return Sema::TDK_Success;
- }
+
case TemplateArgument::Pack:
llvm_unreachable("Argument packs should be expanded by the caller!");
}
@@ -2033,7 +2226,7 @@ DeduceTemplateArguments(Sema &S,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Determine whether there is a template argument to be used for
+/// Determine whether there is a template argument to be used for
/// deduction.
///
/// This routine "expands" argument packs in-place, overriding its input
@@ -2056,7 +2249,7 @@ static bool hasTemplateArgumentForDeduction(ArrayRef<TemplateArgument> &Args,
return ArgIdx < Args.size();
}
-/// \brief Determine whether the given set of template arguments has a pack
+/// Determine whether the given set of template arguments has a pack
/// expansion that is not the last template argument.
static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
bool FoundPackExpansion = false;
@@ -2067,6 +2260,8 @@ static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
if (A.getKind() == TemplateArgument::Pack)
return hasPackExpansionBeforeEnd(A.pack_elements());
+ // FIXME: If this is a fixed-arity pack expansion from an outer level of
+ // templates, it should not be treated as a pack expansion.
if (A.isPackExpansion())
FoundPackExpansion = true;
}
@@ -2130,17 +2325,15 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// template parameter packs expanded by Pi.
TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
- // FIXME: If there are no remaining arguments, we can bail out early
- // and set any deduced parameter packs to an empty argument pack.
- // The latter part of this is a (minor) correctness issue.
-
// Prepare to deduce the packs within the pattern.
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
- for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) {
+ for (; hasTemplateArgumentForDeduction(Args, ArgIdx) &&
+ PackScope.hasNextElement();
+ ++ArgIdx) {
// Deduce template arguments from the pattern.
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
@@ -2171,7 +2364,7 @@ DeduceTemplateArguments(Sema &S,
/*NumberOfArgumentsMustMatch*/false);
}
-/// \brief Determine whether two template arguments are the same.
+/// Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
TemplateArgument X,
const TemplateArgument &Y,
@@ -2232,7 +2425,7 @@ static bool isSameTemplateArg(ASTContext &Context,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// Allocate a TemplateArgumentLoc where all locations have
/// been initialized to the given location.
///
/// \param Arg The template argument we are producing template argument
@@ -2307,8 +2500,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-
-/// \brief Convert the given deduced template argument and add it to the set of
+/// Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
static bool
ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
@@ -2413,6 +2605,16 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
NamedDecl *Param = TemplateParams->getParam(I);
+ // C++0x [temp.arg.explicit]p3:
+ // A trailing template parameter pack (14.5.3) not otherwise deduced will
+ // be deduced to an empty sequence of template arguments.
+ // FIXME: Where did the word "trailing" come from?
+ if (Deduced[I].isNull() && Param->isTemplateParameterPack()) {
+ if (auto Result = PackDeductionScope(S, TemplateParams, Deduced, Info, I)
+ .finish(/*TreatNoDeductionsAsNonDeduced*/false))
+ return Result;
+ }
+
if (!Deduced[I].isNull()) {
if (I < NumAlreadyConverted) {
// We may have had explicitly-specified template arguments for a
@@ -2447,40 +2649,6 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
continue;
}
- // C++0x [temp.arg.explicit]p3:
- // A trailing template parameter pack (14.5.3) not otherwise deduced will
- // be deduced to an empty sequence of template arguments.
- // FIXME: Where did the word "trailing" come from?
- if (Param->isTemplateParameterPack()) {
- // We may have had explicitly-specified template arguments for this
- // template parameter pack. If so, our empty deduction extends the
- // explicitly-specified set (C++0x [temp.arg.explicit]p9).
- const TemplateArgument *ExplicitArgs;
- unsigned NumExplicitArgs;
- if (CurrentInstantiationScope &&
- CurrentInstantiationScope->getPartiallySubstitutedPack(
- &ExplicitArgs, &NumExplicitArgs) == Param) {
- Builder.push_back(TemplateArgument(
- llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
-
- // Forget the partially-substituted pack; its substitution is now
- // complete.
- CurrentInstantiationScope->ResetPartiallySubstitutedPack();
- } else {
- // Go through the motions of checking the empty argument pack against
- // the parameter pack.
- DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
- if (ConvertDeducedTemplateArgument(S, Param, DeducedPack, Template,
- Info, IsDeduced, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
- return Sema::TDK_SubstitutionFailure;
- }
- }
- continue;
- }
-
// Substitute into the default template argument, if available.
bool HasDefaultArg = false;
TemplateDecl *TD = dyn_cast<TemplateDecl>(Template);
@@ -2663,7 +2831,7 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
}
-/// \brief Perform template argument deduction to determine whether
+/// Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
@@ -2706,7 +2874,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
*this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
-/// \brief Perform template argument deduction to determine whether
+/// Perform template argument deduction to determine whether
/// the given template arguments match the given variable template
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
@@ -2747,7 +2915,7 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
*this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
-/// \brief Determine whether the given type T is a simple-template-id type.
+/// Determine whether the given type T is a simple-template-id type.
static bool isSimpleTemplateIdType(QualType T) {
if (const TemplateSpecializationType *Spec
= T->getAs<TemplateSpecializationType>())
@@ -2767,7 +2935,7 @@ static bool isSimpleTemplateIdType(QualType T) {
return false;
}
-/// \brief Substitute the explicitly-provided template arguments into the
+/// Substitute the explicitly-provided template arguments into the
/// given function template according to C++ [temp.arg.explicit].
///
/// \param FunctionTemplate the function template into which the explicit
@@ -2841,7 +3009,7 @@ Sema::SubstituteExplicitTemplateArguments(
Trap.hasErrorOccurred()) {
unsigned Index = Builder.size();
if (Index >= TemplateParams->size())
- Index = TemplateParams->size() - 1;
+ return TDK_SubstitutionFailure;
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
return TDK_InvalidExplicitArguments;
}
@@ -2850,7 +3018,7 @@ Sema::SubstituteExplicitTemplateArguments(
// template arguments.
TemplateArgumentList *ExplicitArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder);
- Info.reset(ExplicitArgumentList);
+ Info.setExplicitArgs(ExplicitArgumentList);
// Template argument deduction and the final substitution should be
// done in the context of the templated declaration. Explicit
@@ -2862,14 +3030,19 @@ Sema::SubstituteExplicitTemplateArguments(
// note that the template argument pack is partially substituted and record
// the explicit template arguments. They'll be used as part of deduction
// for this template parameter pack.
- for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
- const TemplateArgument &Arg = Builder[I];
+ unsigned PartiallySubstitutedPackIndex = -1u;
+ if (!Builder.empty()) {
+ const TemplateArgument &Arg = Builder.back();
if (Arg.getKind() == TemplateArgument::Pack) {
- CurrentInstantiationScope->SetPartiallySubstitutedPack(
- TemplateParams->getParam(I),
- Arg.pack_begin(),
- Arg.pack_size());
- break;
+ auto *Param = TemplateParams->getParam(Builder.size() - 1);
+ // If this is a fully-saturated fixed-size pack, it should be
+ // fully-substituted, not partially-substituted.
+ Optional<unsigned> Expansions = getExpandedPackSize(Param);
+ if (!Expansions || Arg.pack_size() < *Expansions) {
+ PartiallySubstitutedPackIndex = Builder.size() - 1;
+ CurrentInstantiationScope->SetPartiallySubstitutedPack(
+ Param, Arg.pack_begin(), Arg.pack_size());
+ }
}
}
@@ -2959,13 +3132,13 @@ Sema::SubstituteExplicitTemplateArguments(
// case, the empty template argument list <> itself may also be omitted.
//
// Take all of the explicitly-specified arguments and put them into
- // the set of deduced template arguments. Explicitly-specified
- // parameter packs, however, will be set to NULL since the deduction
- // mechanisms handle explicitly-specified argument packs directly.
+ // the set of deduced template arguments. The partially-substituted
+ // parameter pack, however, will be set to NULL since the deduction
+ // mechanism handles the partially-substituted argument pack directly.
Deduced.reserve(TemplateParams->size());
for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
const TemplateArgument &Arg = ExplicitArgumentList->get(I);
- if (Arg.getKind() == TemplateArgument::Pack)
+ if (I == PartiallySubstitutedPackIndex)
Deduced.push_back(DeducedTemplateArgument());
else
Deduced.push_back(Arg);
@@ -2974,7 +3147,7 @@ Sema::SubstituteExplicitTemplateArguments(
return TDK_Success;
}
-/// \brief Check whether the deduced argument type for a call to a function
+/// 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 Sema::TemplateDeductionResult
CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
@@ -3084,7 +3257,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
return Sema::TDK_Success;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
- S.IsDerivedFrom(SourceLocation(), A, DeducedA))
+ S.IsDerivedFrom(Info.getLocation(), A, DeducedA))
return Sema::TDK_Success;
return Failed();
@@ -3120,7 +3293,7 @@ static unsigned getPackIndexForParam(Sema &S,
llvm_unreachable("parameter index would not be produced from template");
}
-/// \brief Finish template argument deduction for a function template,
+/// Finish template argument deduction for a function template,
/// checking the deduced template arguments for completeness and forming
/// the function template specialization.
///
@@ -3271,13 +3444,14 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
// We may need to deduce the return type of the function now.
if (S.getLangOpts().CPlusPlus14 && Fn->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
- return QualType();
+ return {};
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
if (Method->isInstance()) {
// An instance method that's referenced in a form that doesn't
// look like a member pointer is just invalid.
- if (!R.HasFormOfMemberPointer) return QualType();
+ if (!R.HasFormOfMemberPointer)
+ return {};
return S.Context.getMemberPointerType(Fn->getType(),
S.Context.getTypeDeclType(Method->getParent()).getTypePtr());
@@ -3326,7 +3500,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
S.resolveAddressOfOnlyViableOverloadCandidate(Arg, DAP))
return GetTypeOfFunction(S, R, Viable);
- return QualType();
+ return {};
}
// Gather the explicit template arguments, if any.
@@ -3343,7 +3517,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// function templates, the parameter is treated as a
// non-deduced context.
if (!Ovl->hasExplicitTemplateArgs())
- return QualType();
+ return {};
// Otherwise, see if we can resolve a function type
FunctionDecl *Specialization = nullptr;
@@ -3383,14 +3557,15 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
if (Result) continue;
- if (!Match.isNull()) return QualType();
+ if (!Match.isNull())
+ return {};
Match = ArgType;
}
return Match;
}
-/// \brief Perform the adjustments to the parameter and argument types
+/// Perform the adjustments to the parameter and argument types
/// described in C++ [temp.deduct.call].
///
/// \returns true if the caller should not attempt to perform any template
@@ -3497,7 +3672,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
bool DecomposedParam, unsigned ArgIdx, unsigned TDF);
-/// \brief Attempt template argument deduction from an initializer list
+/// Attempt template argument deduction from an initializer list
/// deemed to be an argument in a function call.
static Sema::TemplateDeductionResult DeduceFromInitializerList(
Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
@@ -3558,7 +3733,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
return Sema::TDK_Success;
}
-/// \brief Perform template argument deduction per [temp.deduct.call] for a
+/// Perform template argument deduction per [temp.deduct.call] for a
/// single parameter / argument pair.
static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex,
@@ -3591,7 +3766,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
ArgType, Info, Deduced, TDF);
}
-/// \brief Perform template argument deduction from a function call
+/// Perform template argument deduction from a function call
/// (C++ [temp.deduct.call]).
///
/// \param FunctionTemplate the function template for which we are performing
@@ -3729,8 +3904,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// the length of the explicitly-specified pack if it's expanded by the
// parameter pack and 0 otherwise, and we treat each deduction as a
// non-deduced context.
- if (ParamIdx + 1 == NumParamTypes) {
- for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) {
+ if (ParamIdx + 1 == NumParamTypes || PackScope.hasFixedArity()) {
+ for (; ArgIdx < Args.size() && PackScope.hasNextElement();
+ PackScope.nextPackElement(), ++ArgIdx) {
ParamTypesForArgChecking.push_back(ParamPattern);
if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx))
return Result;
@@ -3757,10 +3933,16 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return Result;
}
+ // Capture the context in which the function call is made. This is the context
+ // that is needed when the accessibility of template arguments is checked.
+ DeclContext *CallingCtx = CurContext;
+
return FinishTemplateArgumentDeduction(
FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info,
- &OriginalCallArgs, PartialOverloading,
- [&]() { return CheckNonDependent(ParamTypesForArgChecking); });
+ &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() {
+ ContextRAII SavedContext(*this, CallingCtx);
+ return CheckNonDependent(ParamTypesForArgChecking);
+ });
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
@@ -3802,7 +3984,7 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
ArgFunctionTypeP->getParamTypes(), EPI);
}
-/// \brief Deduce template arguments when taking the address of a function
+/// Deduce template arguments when taking the address of a function
/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
/// a template.
///
@@ -3944,7 +4126,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return TDK_Success;
}
-/// \brief Deduce template arguments for a templated conversion
+/// Deduce template arguments for a templated conversion
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
/// conversion function template specialization.
Sema::TemplateDeductionResult
@@ -3973,12 +4155,20 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// C++0x [temp.deduct.conv]p4:
// [...] If A is a reference type, the type referred to by A is used
// for type deduction.
- if (const ReferenceType *ARef = A->getAs<ReferenceType>())
- A = ARef->getPointeeType().getUnqualifiedType();
+ if (const ReferenceType *ARef = A->getAs<ReferenceType>()) {
+ A = ARef->getPointeeType();
+ // We work around a defect in the standard here: cv-qualifiers are also
+ // removed from P and A in this case, unless P was a reference type. This
+ // seems to mostly match what other compilers are doing.
+ if (!FromType->getAs<ReferenceType>()) {
+ A = A.getUnqualifiedType();
+ P = P.getUnqualifiedType();
+ }
+
// C++ [temp.deduct.conv]p3:
//
// If A is not a reference type:
- else {
+ } else {
assert(!A->isReferenceType() && "Reference types were handled above");
// - If P is an array type, the pointer type produced by the
@@ -4027,7 +4217,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// cv-qualified than the deduced A (i.e., the type referred to
// by the reference)
if (ToType->isReferenceType())
- TDF |= TDF_ParamWithReferenceType;
+ TDF |= TDF_ArgWithReferenceType;
// - The deduced A can be another pointer or pointer to member
// type that can be converted to A via a qualification
// conversion.
@@ -4054,7 +4244,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
return Result;
}
-/// \brief Deduce template arguments for a function template when there is
+/// Deduce template arguments for a function template when there is
/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
///
/// \param FunctionTemplate the function template for which we are performing
@@ -4089,12 +4279,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
}
namespace {
+
/// Substitute the 'auto' specifier or deduced template specialization type
/// specifier within a type for a given replacement type.
class SubstituteDeducedTypeTransform :
public TreeTransform<SubstituteDeducedTypeTransform> {
QualType Replacement;
bool UseTypeSugar;
+
public:
SubstituteDeducedTypeTransform(Sema &SemaRef, QualType Replacement,
bool UseTypeSugar = true)
@@ -4156,7 +4348,8 @@ namespace {
return TransformType(TLB, TL);
}
};
-}
+
+} // namespace
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
@@ -4190,7 +4383,7 @@ static bool diagnoseAutoDeductionFailure(Sema &S,
}
}
-/// \brief Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
+/// 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
/// necessary to support partial ordering of templates using 'auto'.)
@@ -4406,7 +4599,7 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
CXXRecordDecl *Lambda = cast<CXXMethodDecl>(FD)->getParent();
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
- // For a generic lambda, instantiate the call operator if needed.
+ // For a generic lambda, instantiate the call operator if needed.
if (auto *Args = FD->getTemplateSpecializationArgs()) {
CallOp = InstantiateFunctionDeclaration(
CallOp->getDescribedFunctionTemplate(), Args, Loc);
@@ -4449,7 +4642,7 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
return StillUndeduced;
}
-/// \brief If this is a non-static member function,
+/// If this is a non-static member function,
static void
AddImplicitObjectParameterType(ASTContext &Context,
CXXMethodDecl *Method,
@@ -4471,7 +4664,7 @@ AddImplicitObjectParameterType(ASTContext &Context,
ArgTypes.push_back(ArgTy);
}
-/// \brief Determine whether the function template \p FT1 is at least as
+/// Determine whether the function template \p FT1 is at least as
/// specialized as \p FT2.
static bool isAtLeastAsSpecializedAs(Sema &S,
SourceLocation Loc,
@@ -4622,7 +4815,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
return true;
}
-/// \brief Determine whether this a function template whose parameter-type-list
+/// Determine whether this a function template whose parameter-type-list
/// ends with a function parameter pack.
static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
@@ -4643,7 +4836,7 @@ static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
return true;
}
-/// \brief Returns the more specialized function template according
+/// Returns the more specialized function template according
/// to the rules of function template partial ordering (C++ [temp.func.order]).
///
/// \param FT1 the first function template
@@ -4690,7 +4883,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
return nullptr;
}
-/// \brief Determine if the two templates are equivalent.
+/// Determine if the two templates are equivalent.
static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
if (T1 == T2)
return true;
@@ -4701,7 +4894,7 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
return T1->getCanonicalDecl() == T2->getCanonicalDecl();
}
-/// \brief Retrieve the most specialized of the given function template
+/// Retrieve the most specialized of the given function template
/// specializations.
///
/// \param SpecBegin the start iterator of the function template
@@ -4860,7 +5053,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
return true;
}
-/// \brief Returns the more specialized class template partial specialization
+/// Returns the more specialized class template partial specialization
/// according to the rules of partial ordering of class template partial
/// specializations (C++ [temp.class.order]).
///
@@ -5015,7 +5208,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// expression.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5029,7 +5222,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
// Skip through any implicit casts we added while type-checking, and any
// substitutions performed by template alias expansion.
- while (1) {
+ while (true) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExpr();
else if (const SubstNonTypeTemplateParmExpr *Subst =
@@ -5059,7 +5252,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// nested name specifier.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5076,7 +5269,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
OnlyDeduced, Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// template name.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5101,7 +5294,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// type.
static void
MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
@@ -5172,6 +5365,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
OnlyDeduced, Depth, Used);
break;
+ case Type::DependentVector: {
+ const auto *VecType = cast<DependentVectorType>(T);
+ MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
+ Depth, Used);
+ MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth,
+ Used);
+ break;
+ }
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);
@@ -5197,9 +5398,24 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth,
Used);
- for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I)
- MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
- Depth, Used);
+ for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) {
+ // C++17 [temp.deduct.type]p5:
+ // The non-deduced contexts are: [...]
+ // -- A function parameter pack that does not occur at the end of the
+ // parameter-declaration-list.
+ if (!OnlyDeduced || I + 1 == N ||
+ !Proto->getParamType(I)->getAs<PackExpansionType>()) {
+ MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
+ Depth, Used);
+ } else {
+ // FIXME: C++17 [temp.deduct.call]p1:
+ // When a function parameter pack appears in a non-deduced context,
+ // the type of that pack is never deduced.
+ //
+ // We should also track a set of "never deduced" parameters, and
+ // subtract that from the list of deduced parameters after marking.
+ }
+ }
if (auto *E = Proto->getNoexceptExpr())
MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used);
break;
@@ -5354,7 +5570,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
}
}
-/// \brief Mark the template parameters that are used by this
+/// Mark the template parameters that are used by this
/// template argument.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5397,7 +5613,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
}
}
-/// \brief Mark which template parameters can be deduced from a given
+/// Mark which template parameters can be deduced from a given
/// template argument list.
///
/// \param TemplateArgs the template argument list from which template
@@ -5423,7 +5639,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
Depth, Used);
}
-/// \brief Marks all of the template parameters that will be deduced by a
+/// Marks all of the template parameters that will be deduced by a
/// call to the given function template.
void Sema::MarkDeducedTemplateParameters(
ASTContext &Ctx, const FunctionTemplateDecl *FunctionTemplate,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a48e2466a84d..1aa69bd35d67 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -18,13 +18,14 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TemplateInstCallback.h"
using namespace clang;
using namespace sema;
@@ -33,7 +34,7 @@ using namespace sema;
// Template Instantiation Support
//===----------------------------------------------------------------------===/
-/// \brief Retrieve the template argument list(s) that should be used to
+/// Retrieve the template argument list(s) that should be used to
/// instantiate the definition of the given declaration.
///
/// \param D the declaration for which we are computing template instantiation
@@ -51,7 +52,7 @@ using namespace sema;
/// used to determine the proper set of template instantiation arguments for
/// friend function template specializations.
MultiLevelTemplateArgumentList
-Sema::getTemplateInstantiationArgs(NamedDecl *D,
+Sema::getTemplateInstantiationArgs(NamedDecl *D,
const TemplateArgumentList *Innermost,
bool RelativeToPrimary,
const FunctionDecl *Pattern) {
@@ -60,7 +61,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (Innermost)
Result.addOuterTemplateArguments(Innermost);
-
+
DeclContext *Ctx = dyn_cast<DeclContext>(D);
if (!Ctx) {
Ctx = D->getDeclContext();
@@ -99,7 +100,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
// use empty template parameter lists for all of the outer templates
// to avoid performing any substitutions.
if (Ctx->isTranslationUnit()) {
- if (TemplateTemplateParmDecl *TTP
+ if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(D)) {
for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
Result.addOuterTemplateArguments(None);
@@ -107,7 +108,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
}
}
}
-
+
while (!Ctx->isFileContext()) {
// Add template arguments from a class template instantiation.
if (ClassTemplateSpecializationDecl *Spec
@@ -118,8 +119,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
break;
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
-
- // If this class template specialization was instantiated from a
+
+ // If this class template specialization was instantiated from a
// specialized member that is a class template, we're done.
assert(Spec->getSpecializedTemplate() && "No class template?");
if (Spec->getSpecializedTemplate()->isMemberSpecialization())
@@ -128,11 +129,11 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
// Add template arguments from a function template specialization.
else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
if (!RelativeToPrimary &&
- (Function->getTemplateSpecializationKind() ==
+ (Function->getTemplateSpecializationKind() ==
TSK_ExplicitSpecialization &&
!Function->getClassScopeSpecializationPattern()))
break;
-
+
if (const TemplateArgumentList *TemplateArgs
= Function->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
@@ -153,7 +154,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
// Add the "injected" template arguments.
Result.addOuterTemplateArguments(FunTmpl->getInjectedTemplateArgs());
}
-
+
// If this is a friend declaration and it declares an entity at
// namespace scope, take arguments from its lexical parent
// instead of its semantic parent, unless of course the pattern we're
@@ -199,6 +200,10 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
return false;
+
+ // This function should never be called when Kind's value is Memoization.
+ case Memoization:
+ break;
}
llvm_unreachable("Invalid SynthesisKind!");
@@ -235,6 +240,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
!SemaRef.InstantiatingSpecializations
.insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
.second;
+ atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
}
@@ -394,8 +400,10 @@ void Sema::InstantiatingTemplate::Clear() {
std::make_pair(Active.Entity, Active.Kind));
}
- SemaRef.popCodeSynthesisContext();
+ atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
+ SemaRef.CodeSynthesisContexts.back());
+ SemaRef.popCodeSynthesisContext();
Invalid = true;
}
}
@@ -405,7 +413,7 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
SourceRange InstantiationRange) {
assert(SemaRef.NonInstantiationEntries <=
SemaRef.CodeSynthesisContexts.size());
- if ((SemaRef.CodeSynthesisContexts.size() -
+ if ((SemaRef.CodeSynthesisContexts.size() -
SemaRef.NonInstantiationEntries)
<= SemaRef.getLangOpts().InstantiationDepth)
return false;
@@ -419,7 +427,7 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
return true;
}
-/// \brief Prints the current instantiation stack through a series of
+/// Prints the current instantiation stack through a series of
/// notes.
void Sema::PrintInstantiationStack() {
// Determine which template instantiations to skip, if any.
@@ -509,9 +517,9 @@ void Sema::PrintInstantiationStack() {
FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity);
Diags.Report(Active->PointOfInstantiation,
diag::note_explicit_template_arg_substitution_here)
- << FnTmpl
- << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
- Active->TemplateArgs,
+ << FnTmpl
+ << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
+ Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
break;
@@ -523,8 +531,8 @@ void Sema::PrintInstantiationStack() {
Diags.Report(Active->PointOfInstantiation,
diag::note_function_template_deduction_instantiation_here)
<< FnTmpl
- << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
- Active->TemplateArgs,
+ << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
+ Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
} else {
@@ -548,7 +556,7 @@ void Sema::PrintInstantiationStack() {
Diags.Report(Active->PointOfInstantiation,
diag::note_deduced_template_arg_substitution_here)
<< IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
- << getTemplateArgumentBindingsText(Params, Active->TemplateArgs,
+ << getTemplateArgumentBindingsText(Params, Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
}
@@ -588,8 +596,8 @@ void Sema::PrintInstantiationStack() {
diag::note_prior_template_arg_substitution)
<< isa<TemplateTemplateParmDecl>(Parm)
<< Name
- << getTemplateArgumentBindingsText(TemplateParams,
- Active->TemplateArgs,
+ << getTemplateArgumentBindingsText(TemplateParams,
+ Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
break;
@@ -606,8 +614,8 @@ void Sema::PrintInstantiationStack() {
Diags.Report(Active->PointOfInstantiation,
diag::note_template_default_arg_checking)
- << getTemplateArgumentBindingsText(TemplateParams,
- Active->TemplateArgs,
+ << getTemplateArgumentBindingsText(TemplateParams,
+ Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
break;
@@ -626,7 +634,7 @@ void Sema::PrintInstantiationStack() {
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break;
- case CodeSynthesisContext::DefiningSynthesizedFunction:
+ case CodeSynthesisContext::DefiningSynthesizedFunction: {
// FIXME: For synthesized members other than special members, produce a note.
auto *MD = dyn_cast<CXXMethodDecl>(Active->Entity);
auto CSM = MD ? getSpecialMember(MD) : CXXInvalid;
@@ -637,6 +645,10 @@ void Sema::PrintInstantiationStack() {
}
break;
}
+
+ case CodeSynthesisContext::Memoization:
+ break;
+ }
}
}
@@ -648,7 +660,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
Active = CodeSynthesisContexts.rbegin(),
ActiveEnd = CodeSynthesisContexts.rend();
Active != ActiveEnd;
- ++Active)
+ ++Active)
{
switch (Active->Kind) {
case CodeSynthesisContext::TemplateInstantiation:
@@ -666,7 +678,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
// A default template argument instantiation and substitution into
- // template parameters with arguments for prior parameters may or may
+ // template parameters with arguments for prior parameters may or may
// not be a SFINAE context; look further up the stack.
break;
@@ -682,6 +694,9 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
// This happens in a context unrelated to template instantiation, so
// there is no SFINAE.
return None;
+
+ case CodeSynthesisContext::Memoization:
+ break;
}
// The inner context was transparent for SFINAE. If it occurred within a
@@ -693,19 +708,6 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return None;
}
-/// \brief Retrieve the depth and index of a parameter pack.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(NamedDecl *ND) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
- return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-}
-
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -725,20 +727,20 @@ namespace {
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
Entity(Entity) { }
- /// \brief Determine whether the given type \p T has already been
+ /// Determine whether the given type \p T has already been
/// transformed.
///
/// For the purposes of template instantiation, a type has already been
/// transformed if it is NULL or if it is not dependent.
bool AlreadyTransformed(QualType T);
- /// \brief Returns the location of the entity being instantiated, if known.
+ /// Returns the location of the entity being instantiated, if known.
SourceLocation getBaseLocation() { return Loc; }
- /// \brief Returns the name of the entity being instantiated, if any.
+ /// Returns the name of the entity being instantiated, if any.
DeclarationName getBaseEntity() { return Entity; }
- /// \brief Sets the "base" location and entity when that
+ /// Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
@@ -750,18 +752,18 @@ namespace {
ArrayRef<UnexpandedParameterPack> Unexpanded,
bool &ShouldExpand, bool &RetainExpansion,
Optional<unsigned> &NumExpansions) {
- return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
+ return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
PatternRange, Unexpanded,
- TemplateArgs,
+ TemplateArgs,
ShouldExpand,
RetainExpansion,
NumExpansions);
}
- void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
+ void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
}
-
+
TemplateArgument ForgetPartiallySubstitutedPack() {
TemplateArgument Result;
if (NamedDecl *PartialPack
@@ -775,14 +777,14 @@ namespace {
TemplateArgs.setArgument(Depth, Index, TemplateArgument());
}
}
-
+
return Result;
}
-
+
void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
if (Arg.isNull())
return;
-
+
if (NamedDecl *PartialPack
= SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
MultiLevelTemplateArgumentList &TemplateArgs
@@ -793,11 +795,11 @@ namespace {
}
}
- /// \brief Transform the given declaration by instantiating a reference to
+ /// Transform the given declaration by instantiating a reference to
/// this declaration.
Decl *TransformDecl(SourceLocation Loc, Decl *D);
- void transformAttrs(Decl *Old, Decl *New) {
+ void transformAttrs(Decl *Old, Decl *New) {
SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
}
@@ -815,7 +817,7 @@ namespace {
NewMD->setInstantiationOfMemberFunction(OldMD,
TSK_ImplicitInstantiation);
}
-
+
SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
// We recreated a local declaration, but not by instantiating it. There
@@ -823,29 +825,29 @@ namespace {
if (auto *DC = dyn_cast<DeclContext>(Old))
SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
}
-
- /// \brief Transform the definition of the given declaration by
+
+ /// Transform the definition of the given declaration by
/// instantiating it.
Decl *TransformDefinition(SourceLocation Loc, Decl *D);
- /// \brief Transform the first qualifier within a scope by instantiating the
+ /// Transform the first qualifier within a scope by instantiating the
/// declaration.
NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
-
- /// \brief Rebuild the exception declaration and register the declaration
+
+ /// Rebuild the exception declaration and register the declaration
/// as an instantiated local.
- VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+ VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
SourceLocation StartLoc,
SourceLocation NameLoc,
IdentifierInfo *Name);
- /// \brief Rebuild the Objective-C exception declaration and register the
+ /// Rebuild the Objective-C exception declaration and register the
/// declaration as an instantiated local.
- VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+ VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo, QualType T);
-
- /// \brief Check for tag mismatches when instantiating an
+
+ /// Check for tag mismatches when instantiating an
/// elaborated type.
QualType RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
@@ -870,14 +872,14 @@ namespace {
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
- /// \brief Rebuild a DeclRefExpr for a ParmVarDecl reference.
+ /// Rebuild a DeclRefExpr for a ParmVarDecl reference.
ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc);
- /// \brief Transform a reference to a function parameter pack.
+ /// Transform a reference to a function parameter pack.
ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E,
ParmVarDecl *PD);
- /// \brief Transform a FunctionParmPackExpr which was built when we couldn't
+ /// Transform a FunctionParmPackExpr which was built when we couldn't
/// expand a function parameter pack reference which refers to an expanded
/// pack.
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
@@ -900,12 +902,12 @@ namespace {
Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
- /// \brief Transforms a template type parameter type by performing
+ /// Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL);
- /// \brief Transforms an already-substituted template type parameter pack
+ /// Transforms an already-substituted template type parameter pack
/// into either itself (if we aren't substituting into its pack expansion)
/// or the appropriate substituted argument.
QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
@@ -919,11 +921,11 @@ namespace {
TemplateParameterList *TransformTemplateParameterList(
TemplateParameterList *OrigTPL) {
if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
-
+
DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
- TemplateDeclInstantiator DeclInstantiator(getSema(),
+ TemplateDeclInstantiator DeclInstantiator(getSema(),
/* DeclContext *Owner */ Owner, TemplateArgs);
- return DeclInstantiator.SubstTemplateParams(OrigTPL);
+ return DeclInstantiator.SubstTemplateParams(OrigTPL);
}
private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
@@ -935,17 +937,17 @@ namespace {
bool TemplateInstantiator::AlreadyTransformed(QualType T) {
if (T.isNull())
return true;
-
+
if (T->isInstantiationDependentType() || T->isVariablyModifiedType())
return false;
-
+
getSema().MarkDeclarationsReferencedInType(Loc, T);
return true;
}
static TemplateArgument
getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
- assert(S.ArgumentPackSubstitutionIndex >= 0);
+ assert(S.ArgumentPackSubstitutionIndex >= 0);
assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex];
if (Arg.isPackExpansion())
@@ -968,9 +970,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
return D;
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
-
+
if (TTP->isParameterPack()) {
- assert(Arg.getKind() == TemplateArgument::Pack &&
+ assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
@@ -998,22 +1000,22 @@ Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
}
NamedDecl *
-TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
+TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
SourceLocation Loc) {
- // If the first part of the nested-name-specifier was a template type
+ // If the first part of the nested-name-specifier was a template type
// parameter, instantiate that type parameter down to a tag type.
if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
- const TemplateTypeParmType *TTP
+ const TemplateTypeParmType *TTP
= cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
-
+
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
// FIXME: This needs testing w/ member access expressions.
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex());
-
+
if (TTP->isParameterPack()) {
- assert(Arg.getKind() == TemplateArgument::Pack &&
+ assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
-
+
if (getSema().ArgumentPackSubstitutionIndex == -1)
return nullptr;
@@ -1023,16 +1025,16 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
QualType T = Arg.getAsType();
if (T.isNull())
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
-
+
if (const TagType *Tag = T->getAs<TagType>())
return Tag->getDecl();
-
+
// The resulting type is not a tag; complain.
getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
return nullptr;
}
}
-
+
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
}
@@ -1049,8 +1051,8 @@ TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
return Var;
}
-VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
- TypeSourceInfo *TSInfo,
+VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *TSInfo,
QualType T) {
VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
if (Var)
@@ -1105,13 +1107,13 @@ TemplateName TemplateInstantiator::TransformTemplateName(
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
TTP->getPosition()))
return Name;
-
+
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
-
+
if (TTP->isParameterPack()) {
- assert(Arg.getKind() == TemplateArgument::Pack &&
+ assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
-
+
if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We have the template argument pack to substitute, but we're not
// actually expanding the enclosing pack expansion yet. So, just
@@ -1121,7 +1123,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
-
+
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
assert(!Template.isNull() && "Null template template argument");
assert(!Template.getAsQualifiedTemplateName() &&
@@ -1131,12 +1133,12 @@ TemplateName TemplateInstantiator::TransformTemplateName(
return Template;
}
}
-
+
if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) {
if (getSema().ArgumentPackSubstitutionIndex == -1)
return Name;
-
+
TemplateArgument Arg = SubstPack->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
return Arg.getAsTemplate().getNameToSubstitute();
@@ -1147,7 +1149,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
AllowInjectedClassName);
}
-ExprResult
+ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
@@ -1185,25 +1187,25 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
}
if (NTTP->isParameterPack()) {
- assert(Arg.getKind() == TemplateArgument::Pack &&
+ assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
-
+
if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We have an argument pack, but we can't select a particular argument
// out of it yet. Therefore, we'll build an expression to hold on to that
// argument pack.
QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
- E->getLocation(),
+ E->getLocation(),
NTTP->getDeclName());
if (TargetType.isNull())
return ExprError();
-
- return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(TargetType,
- NTTP,
- E->getLocation(),
- Arg);
+
+ return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
+ TargetType.getNonLValueExprType(SemaRef.Context),
+ TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP,
+ E->getLocation(), Arg);
}
-
+
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
@@ -1246,7 +1248,7 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
arg.getKind() == TemplateArgument::NullPtr) {
ValueDecl *VD;
if (arg.getKind() == TemplateArgument::Declaration) {
- VD = cast<ValueDecl>(arg.getAsDecl());
+ VD = arg.getAsDecl();
// Find the instantiation of the template argument. This is
// required for nested templates.
@@ -1258,12 +1260,12 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
// Propagate NULL template argument.
VD = nullptr;
}
-
+
// Derive the type we want the substituted decl to have. This had
// better be non-dependent, or these checks will have serious problems.
if (parm->isExpandedParameterPack()) {
type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
- } else if (parm->isParameterPack() &&
+ } else if (parm->isParameterPack() &&
isa<PackExpansionType>(parm->getType())) {
type = SemaRef.SubstType(
cast<PackExpansionType>(parm->getType())->getPattern(),
@@ -1290,8 +1292,8 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
type, resultExpr->getValueKind(), loc, parm, resultExpr);
}
-
-ExprResult
+
+ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
if (getSema().ArgumentPackSubstitutionIndex == -1) {
@@ -1385,7 +1387,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
if (NTTP->getDepth() < TemplateArgs.getNumLevels())
return TransformTemplateParmRefExpr(E, NTTP);
-
+
// We have a non-type template parameter that isn't fully substituted;
// FindInstantiatedDecl will find it in the local instantiation scope.
}
@@ -1404,7 +1406,7 @@ ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
getDescribedFunctionTemplate() &&
"Default arg expressions are never formed in dependent cases.");
return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
- cast<FunctionDecl>(E->getParam()->getDeclContext()),
+ cast<FunctionDecl>(E->getParam()->getDeclContext()),
E->getParam());
}
@@ -1449,11 +1451,11 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
}
TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
-
+
if (T->isParameterPack()) {
- assert(Arg.getKind() == TemplateArgument::Pack &&
+ assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
-
+
if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We have the template argument pack, but we're not expanding the
// enclosing pack expansion yet. Just save the template argument
@@ -1465,10 +1467,10 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
-
+
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
-
+
assert(Arg.getKind() == TemplateArgument::Type &&
"Template argument kind mismatch");
@@ -1500,7 +1502,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
return Result;
}
-QualType
+QualType
TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL) {
@@ -1525,7 +1527,7 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
return Result;
}
-/// \brief Perform substitution on the type T with a given set of template
+/// Perform substitution on the type T with a given set of template
/// arguments.
///
/// This routine substitutes the given template arguments into the
@@ -1563,8 +1565,8 @@ TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
-
- if (!T->getType()->isInstantiationDependentType() &&
+
+ if (!T->getType()->isInstantiationDependentType() &&
!T->getType()->isVariablyModifiedType())
return T;
@@ -1580,11 +1582,11 @@ TypeSourceInfo *Sema::SubstType(TypeLoc TL,
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
-
+
if (TL.getType().isNull())
return nullptr;
- if (!TL.getType()->isInstantiationDependentType() &&
+ if (!TL.getType()->isInstantiationDependentType() &&
!TL.getType()->isVariablyModifiedType()) {
// FIXME: Make a copy of the TypeLoc data here, so that we can
// return a new TypeSourceInfo. Inefficient!
@@ -1714,7 +1716,7 @@ void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
UpdateExceptionSpec(New, ESI);
}
-ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
+ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
Optional<unsigned> NumExpansions,
@@ -1725,9 +1727,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
TypeLoc OldTL = OldDI->getTypeLoc();
if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {
- // We have a function parameter pack. Substitute into the pattern of the
+ // We have a function parameter pack. Substitute into the pattern of the
// expansion.
- NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
+ NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
OldParm->getLocation(), OldParm->getDeclName());
if (!NewDI)
return nullptr;
@@ -1743,16 +1745,16 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
// itself is not a pack expansion type), so complain. This can occur when
// the substitution goes through an alias template that "loses" the
// pack expansion.
- Diag(OldParm->getLocation(),
+ Diag(OldParm->getLocation(),
diag::err_function_parameter_pack_without_parameter_packs)
<< NewDI->getType();
return nullptr;
- }
+ }
} else {
- NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
+ NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
OldParm->getDeclName());
}
-
+
if (!NewDI)
return nullptr;
@@ -1799,15 +1801,15 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
}
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
-
+
if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
// Add the new parameter to the instantiated parameter pack.
CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
} else {
// Introduce an Old -> New mapping
- CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
+ CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
}
-
+
// FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
// can be anything, is this right ?
NewParm->setDeclContext(CurContext);
@@ -1817,10 +1819,10 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
InstantiateAttrs(TemplateArgs, OldParm, NewParm);
- return NewParm;
+ return NewParm;
}
-/// \brief Substitute the given template arguments into the given set of
+/// Substitute the given template arguments into the given set of
/// parameters, producing the set of parameter types that would be generated
/// from such a substitution.
bool Sema::SubstParmTypes(
@@ -1833,14 +1835,14 @@ bool Sema::SubstParmTypes(
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
-
- TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
return Instantiator.TransformFunctionTypeParams(
Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
}
-/// \brief Perform substitution on the base class specifiers of the
+/// Perform substitution on the base class specifiers of the
/// given class template specialization.
///
/// Produces a diagnostic and returns true on error, returns false and
@@ -1873,21 +1875,21 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
bool ShouldExpand = false;
bool RetainExpansion = false;
Optional<unsigned> NumExpansions;
- if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
+ if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
Base.getSourceRange(),
Unexpanded,
- TemplateArgs, ShouldExpand,
+ TemplateArgs, ShouldExpand,
RetainExpansion,
NumExpansions)) {
Invalid = true;
continue;
}
-
+
// If we should expand this pack expansion now, do so.
if (ShouldExpand) {
for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
-
+
TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
Base.getSourceRange().getBegin(),
@@ -1896,7 +1898,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Invalid = true;
continue;
}
-
+
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
Base.getSourceRange(),
@@ -1908,10 +1910,10 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
else
Invalid = true;
}
-
+
continue;
}
-
+
// The resulting base specifier will (still) be a pack expansion.
EllipsisLoc = Base.getEllipsisLoc();
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
@@ -1925,7 +1927,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Base.getSourceRange().getBegin(),
DeclarationName());
}
-
+
if (!BaseTypeLoc) {
Invalid = true;
continue;
@@ -1960,7 +1962,7 @@ namespace clang {
}
}
-/// \brief Instantiate the definition of a class from a given pattern.
+/// Instantiate the definition of a class from a given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
/// source code.
@@ -1996,12 +1998,12 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return true;
Pattern = PatternDef;
- // \brief Record the point of instantiation.
- if (MemberSpecializationInfo *MSInfo
+ // Record the point of instantiation.
+ if (MemberSpecializationInfo *MSInfo
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
- } else if (ClassTemplateSpecializationDecl *Spec
+ } else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(PointOfInstantiation);
@@ -2011,7 +2013,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (Inst.isInvalid())
return true;
assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating class definition");
// Enter the scope of this instantiation. We don't use
@@ -2068,6 +2070,11 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (Member->getDeclContext() != Pattern)
continue;
+ // BlockDecls can appear in a default-member-initializer. They must be the
+ // child of a BlockExpr, so we only know how to instantiate them from there.
+ if (isa<BlockDecl>(Member))
+ continue;
+
if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
@@ -2110,7 +2117,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Finish checking fields.
ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
- SourceLocation(), SourceLocation(), nullptr);
+ SourceLocation(), SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Instantiation);
// Default arguments are parsed, if not instantiated. We can go instantiate
@@ -2196,7 +2203,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return Instantiation->isInvalidDecl();
}
-/// \brief Instantiate the definition of an enum from a given pattern.
+/// Instantiate the definition of an enum from a given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
/// source code.
@@ -2234,7 +2241,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
return true;
if (Inst.isAlreadyInstantiating())
return false;
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating enum definition");
// The instantiation is visible here, even if it was first declared in an
@@ -2262,7 +2269,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
}
-/// \brief Instantiate the definition of a field from the given pattern.
+/// Instantiate the definition of a field from the given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
/// source code.
@@ -2310,7 +2317,7 @@ bool Sema::InstantiateInClassInitializer(
<< Instantiation;
return true;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating default member init");
// Enter the scope of this instantiation. We don't use PushDeclContext because
@@ -2340,7 +2347,7 @@ bool Sema::InstantiateInClassInitializer(
}
namespace {
- /// \brief A partial specialization whose template arguments have matched
+ /// A partial specialization whose template arguments have matched
/// a given template-id.
struct PartialSpecMatchResult {
ClassTemplatePartialSpecializationDecl *Partial;
@@ -2379,127 +2386,137 @@ getPatternForClassTemplateSpecialization(
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return nullptr;
- ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
- CXXRecordDecl *Pattern = nullptr;
-
- // C++ [temp.class.spec.match]p1:
- // When a class template is used in a context that requires an
- // instantiation of the class, it is necessary to determine
- // whether the instantiation is to be generated using the primary
- // template or one of the partial specializations. This is done by
- // matching the template arguments of the class template
- // specialization with the template argument lists of the partial
- // specializations.
- typedef PartialSpecMatchResult MatchResult;
- SmallVector<MatchResult, 4> Matched;
- SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
- Template->getPartialSpecializations(PartialSpecs);
- TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
- for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
- ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
- TemplateDeductionInfo Info(FailedCandidates.getLocation());
- if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
- Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
- // Store the failed-deduction information for use in diagnostics, later.
- // TODO: Actually use the failed-deduction info?
- FailedCandidates.addCandidate().set(
- DeclAccessPair::make(Template, AS_public), Partial,
- MakeDeductionFailureInfo(S.Context, Result, Info));
- (void)Result;
- } else {
- Matched.push_back(PartialSpecMatchResult());
- Matched.back().Partial = Partial;
- Matched.back().Args = Info.take();
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
+ if (!Specialized.is<ClassTemplatePartialSpecializationDecl *>()) {
+ // Find best matching specialization.
+ ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+
+ // C++ [temp.class.spec.match]p1:
+ // When a class template is used in a context that requires an
+ // instantiation of the class, it is necessary to determine
+ // whether the instantiation is to be generated using the primary
+ // template or one of the partial specializations. This is done by
+ // matching the template arguments of the class template
+ // specialization with the template argument lists of the partial
+ // specializations.
+ typedef PartialSpecMatchResult MatchResult;
+ SmallVector<MatchResult, 4> Matched;
+ SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ Template->getPartialSpecializations(PartialSpecs);
+ TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+ ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
+ if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
+ Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
+ // Store the failed-deduction information for use in diagnostics, later.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate().set(
+ DeclAccessPair::make(Template, AS_public), Partial,
+ MakeDeductionFailureInfo(S.Context, Result, Info));
+ (void)Result;
+ } else {
+ Matched.push_back(PartialSpecMatchResult());
+ Matched.back().Partial = Partial;
+ Matched.back().Args = Info.take();
+ }
}
- }
- // If we're dealing with a member template where the template parameters
- // have been instantiated, this provides the original template parameters
- // from which the member template's parameters were instantiated.
+ // If we're dealing with a member template where the template parameters
+ // have been instantiated, this provides the original template parameters
+ // from which the member template's parameters were instantiated.
- if (Matched.size() >= 1) {
- SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
- if (Matched.size() == 1) {
- // -- If exactly one matching specialization is found, the
- // instantiation is generated from that specialization.
- // We don't need to do anything for this.
- } else {
- // -- If more than one matching specialization is found, the
- // partial order rules (14.5.4.2) are used to determine
- // whether one of the specializations is more specialized
- // than the others. If none of the specializations is more
- // specialized than all of the other matching
- // specializations, then the use of the class template is
- // ambiguous and the program is ill-formed.
- for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (S.getMoreSpecializedPartialSpecialization(
- P->Partial, Best->Partial, PointOfInstantiation) == P->Partial)
- Best = P;
- }
-
- // Determine if the best partial specialization is more specialized than
- // the others.
- bool Ambiguous = false;
- for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (P != Best &&
- S.getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
- PointOfInstantiation) !=
- Best->Partial) {
- Ambiguous = true;
- break;
+ if (Matched.size() >= 1) {
+ SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
+ if (Matched.size() == 1) {
+ // -- If exactly one matching specialization is found, the
+ // instantiation is generated from that specialization.
+ // We don't need to do anything for this.
+ } else {
+ // -- If more than one matching specialization is found, the
+ // partial order rules (14.5.4.2) are used to determine
+ // whether one of the specializations is more specialized
+ // than the others. If none of the specializations is more
+ // specialized than all of the other matching
+ // specializations, then the use of the class template is
+ // ambiguous and the program is ill-formed.
+ for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (S.getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial, PointOfInstantiation) ==
+ P->Partial)
+ Best = P;
}
- }
-
- if (Ambiguous) {
- // Partial ordering did not produce a clear winner. Complain.
- Inst.Clear();
- ClassTemplateSpec->setInvalidDecl();
- S.Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
- << ClassTemplateSpec;
-
- // Print the matching partial specializations.
+
+ // Determine if the best partial specialization is more specialized than
+ // the others.
+ bool Ambiguous = false;
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
PEnd = Matched.end();
- P != PEnd; ++P)
- S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
- << S.getTemplateArgumentBindingsText(
- P->Partial->getTemplateParameters(), *P->Args);
+ P != PEnd; ++P) {
+ if (P != Best && S.getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial,
+ PointOfInstantiation) != Best->Partial) {
+ Ambiguous = true;
+ break;
+ }
+ }
- return nullptr;
+ if (Ambiguous) {
+ // Partial ordering did not produce a clear winner. Complain.
+ Inst.Clear();
+ ClassTemplateSpec->setInvalidDecl();
+ S.Diag(PointOfInstantiation,
+ diag::err_partial_spec_ordering_ambiguous)
+ << ClassTemplateSpec;
+
+ // Print the matching partial specializations.
+ for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P)
+ S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+ << S.getTemplateArgumentBindingsText(
+ P->Partial->getTemplateParameters(), *P->Args);
+
+ return nullptr;
+ }
}
+
+ ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+ } else {
+ // -- If no matches are found, the instantiation is generated
+ // from the primary template.
}
-
+ }
+
+ CXXRecordDecl *Pattern = nullptr;
+ Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
+ if (auto *PartialSpec =
+ Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
// Instantiate using the best class template partial specialization.
- ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial;
- while (OrigPartialSpec->getInstantiatedFromMember()) {
+ while (PartialSpec->getInstantiatedFromMember()) {
// If we've found an explicit specialization of this class template,
// stop here and use that as the pattern.
- if (OrigPartialSpec->isMemberSpecialization())
+ if (PartialSpec->isMemberSpecialization())
break;
-
- OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember();
+
+ PartialSpec = PartialSpec->getInstantiatedFromMember();
}
-
- Pattern = OrigPartialSpec;
- ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+ Pattern = PartialSpec;
} else {
- // -- If no matches are found, the instantiation is generated
- // from the primary template.
- ClassTemplateDecl *OrigTemplate = Template;
- while (OrigTemplate->getInstantiatedFromMemberTemplate()) {
+ ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+ while (Template->getInstantiatedFromMemberTemplate()) {
// If we've found an explicit specialization of this class template,
// stop here and use that as the pattern.
- if (OrigTemplate->isMemberSpecialization())
+ if (Template->isMemberSpecialization())
break;
-
- OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+
+ Template = Template->getInstantiatedFromMemberTemplate();
}
-
- Pattern = OrigTemplate->getTemplatedDecl();
+ Pattern = Template->getTemplatedDecl();
}
return Pattern;
@@ -2525,7 +2542,7 @@ bool Sema::InstantiateClassTemplateSpecialization(
Complain);
}
-/// \brief Instantiates the definitions of all of the member
+/// Instantiates the definitions of all of the member
/// of the given class, which is an instantiation of a class template
/// or a member class of a template.
void
@@ -2546,15 +2563,15 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (auto *Function = dyn_cast<FunctionDecl>(D)) {
if (FunctionDecl *Pattern
= Function->getInstantiatedFromMemberFunction()) {
- MemberSpecializationInfo *MSInfo
+ MemberSpecializationInfo *MSInfo
= Function->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
-
- if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
- Function,
+
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Function,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew) ||
@@ -2593,31 +2610,31 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
-
- if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
- Var,
+
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Var,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew) ||
SuppressNew)
continue;
-
+
if (TSK == TSK_ExplicitInstantiationDefinition) {
// C++0x [temp.explicit]p8:
// An explicit instantiation definition that names a class template
- // specialization explicitly instantiates the class template
- // specialization and is only an explicit instantiation definition
- // of members whose definition is visible at the point of
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
// instantiation.
if (!Var->getInstantiatedFromStaticDataMember()->getDefinition())
continue;
-
+
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
InstantiateVariableDefinition(PointOfInstantiation, Var);
} else {
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
- }
+ }
} else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
// Always skip the injected-class-name, along with any
// redeclarations of nested classes, since both would cause us
@@ -2627,10 +2644,10 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (Record->isInjectedClassName() || Record->getPreviousDecl() ||
Record->isLambda())
continue;
-
+
MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
-
+
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
@@ -2643,33 +2660,33 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
continue;
}
- if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
- Record,
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Record,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew) ||
SuppressNew)
continue;
-
+
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
assert(Pattern && "Missing instantiated-from-template information");
-
+
if (!Record->getDefinition()) {
if (!Pattern->getDefinition()) {
// C++0x [temp.explicit]p8:
// An explicit instantiation definition that names a class template
- // specialization explicitly instantiates the class template
- // specialization and is only an explicit instantiation definition
- // of members whose definition is visible at the point of
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
// instantiation.
if (TSK == TSK_ExplicitInstantiationDeclaration) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
-
+
continue;
}
-
+
InstantiateClass(PointOfInstantiation, Record, Pattern,
TemplateArgs,
TSK);
@@ -2681,10 +2698,10 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
MarkVTableUsed(PointOfInstantiation, Record, true);
}
}
-
+
Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (Pattern)
- InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
+ InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
TSK);
} else if (auto *Enum = dyn_cast<EnumDecl>(D)) {
MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
@@ -2732,7 +2749,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
-/// \brief Instantiate the definitions of all of the members of the
+/// Instantiate the definitions of all of the members of the
/// given class template specialization, which was named as part of an
/// explicit instantiation.
void
@@ -2799,16 +2816,16 @@ bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
NestedNameSpecifierLoc
Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!NNS)
return NestedNameSpecifierLoc();
-
+
TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
DeclarationName());
return Instantiator.TransformNestedNameSpecifierLoc(NNS);
}
-/// \brief Do template substitution on declaration name info.
+/// Do template substitution on declaration name info.
DeclarationNameInfo
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -2833,7 +2850,7 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
DeclarationName());
-
+
return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
}
@@ -2867,7 +2884,7 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD);
if (Found != Current->LocalDecls.end())
return &Found->second;
-
+
// If this is a tag declaration, it's possible that we need to look for
// a previous declaration.
if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
@@ -2875,8 +2892,8 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
else
CheckD = nullptr;
} while (CheckD);
-
- // If we aren't combined with our outer scope, we're done.
+
+ // If we aren't combined with our outer scope, we're done.
if (!Current->CombineWithOuterScope)
break;
}
@@ -2948,12 +2965,12 @@ void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
ArgumentPacks.push_back(Pack);
}
-void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
+void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
const TemplateArgument *ExplicitArgs,
unsigned NumExplicitArgs) {
assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
"Already have a partially-substituted pack");
- assert((!PartiallySubstitutedPack
+ assert((!PartiallySubstitutedPack
|| NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
"Wrong number of arguments in partially-substituted pack");
PartiallySubstitutedPack = Pack;
@@ -2968,15 +2985,15 @@ NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
*ExplicitArgs = nullptr;
if (NumExplicitArgs)
*NumExplicitArgs = 0;
-
- for (const LocalInstantiationScope *Current = this; Current;
+
+ for (const LocalInstantiationScope *Current = this; Current;
Current = Current->Outer) {
if (Current->PartiallySubstitutedPack) {
if (ExplicitArgs)
*ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
if (NumExplicitArgs)
*NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
-
+
return Current->PartiallySubstitutedPack;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9163fbc6f7e8..512b00b1008c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -18,11 +18,12 @@
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
using namespace clang;
@@ -175,7 +176,8 @@ static void instantiateDependentAllocAlignAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const AllocAlignAttr *Align, Decl *New) {
Expr *Param = IntegerLiteral::Create(
- S.getASTContext(), llvm::APInt(64, Align->getParamIndex()),
+ S.getASTContext(),
+ llvm::APInt(64, Align->getParamIndex().getSourceIndex()),
S.getASTContext().UnsignedLongLongTy, Align->getLocation());
S.AddAllocAlignAttr(Align->getLocation(), New, Param,
Align->getSpellingListIndex());
@@ -343,14 +345,6 @@ static void instantiateOMPDeclareSimdDeclAttr(
Attr.getRange());
}
-static bool DeclContainsAttr(const Decl *D, const Attr *NewAttr) {
- if (!D->hasAttrs() || NewAttr->duplicatesAllowed())
- return false;
- return llvm::find_if(D->getAttrs(), [NewAttr](const Attr *Attr) {
- return Attr->getKind() == NewAttr->getKind();
- }) != D->getAttrs().end();
-}
-
void Sema::InstantiateAttrsForDecl(
const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl,
Decl *New, LateInstantiatedAttrVec *LateAttrs,
@@ -365,7 +359,7 @@ void Sema::InstantiateAttrsForDecl(
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
TmplAttr, Context, *this, TemplateArgs);
- if (NewAttr && !DeclContainsAttr(New, NewAttr))
+ if (NewAttr)
New->addAttr(NewAttr);
}
}
@@ -470,8 +464,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
*this, TemplateArgs);
-
- if (NewAttr && !DeclContainsAttr(New, NewAttr))
+ if (NewAttr)
New->addAttr(NewAttr);
}
}
@@ -736,7 +729,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
DI, D->getStorageClass());
// In ARC, infer 'retaining' for variables of retainable type.
- if (SemaRef.getLangOpts().ObjCAutoRefCount &&
+ if (SemaRef.getLangOpts().ObjCAutoRefCount &&
SemaRef.inferObjCARCLifetime(Var))
Var->setInvalidDecl();
@@ -749,7 +742,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
if (D->isNRVOVariable()) {
QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
- if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false))
+ if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict))
Var->setNRVOVariable(true);
}
@@ -1049,8 +1042,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
SemaRef.SubstType(TI->getType(), TemplateArgs,
UnderlyingLoc, DeclarationName());
SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
- DefnUnderlying,
- /*EnumUnderlyingIsImplicit=*/false, Enum);
+ DefnUnderlying, /*IsFixed=*/true, Enum);
}
}
@@ -1126,8 +1118,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
}
SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum,
- Enumerators,
- nullptr, nullptr);
+ Enumerators, nullptr, ParsedAttributesView());
}
Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
@@ -1564,7 +1555,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
return Record;
}
-/// \brief Adjust the given function type for an instantiation of the
+/// Adjust the given function type for an instantiation of the
/// given declaration, to cope with modifications to the function's type that
/// aren't reflected in the type-source information.
///
@@ -1661,6 +1652,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
NameInfo, T, TInfo, D->getSourceRange().getEnd());
if (DGuide->isCopyDeductionCandidate())
cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
+ Function->setAccess(D->getAccess());
} else {
Function = FunctionDecl::Create(
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
@@ -1815,45 +1807,24 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
// apply to non-template function declarations and definitions also apply
// to these implicit definitions.
if (D->isThisDeclarationADefinition()) {
- // Check for a function body.
- const FunctionDecl *Definition = nullptr;
- if (Function->isDefined(Definition) &&
- Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
- SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
- << Function->getDeclName();
- SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
- }
- // Check for redefinitions due to other instantiations of this or
- // a similar friend function.
- else for (auto R : Function->redecls()) {
- if (R == Function)
- continue;
-
- // If some prior declaration of this function has been used, we need
- // to instantiate its definition.
- if (!QueuedInstantiation && R->isUsed(false)) {
- if (MemberSpecializationInfo *MSInfo =
- Function->getMemberSpecializationInfo()) {
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- SourceLocation Loc = R->getLocation(); // FIXME
- MSInfo->setPointOfInstantiation(Loc);
- SemaRef.PendingLocalImplicitInstantiations.push_back(
- std::make_pair(Function, Loc));
- QueuedInstantiation = true;
- }
- }
- }
-
- // If some prior declaration of this function was a friend with an
- // uninstantiated definition, reject it.
- if (R->getFriendObjectKind()) {
- if (const FunctionDecl *RPattern =
- R->getTemplateInstantiationPattern()) {
- if (RPattern->isDefined(RPattern)) {
- SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
- << Function->getDeclName();
- SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
- break;
+ SemaRef.CheckForFunctionRedefinition(Function);
+ if (!Function->isInvalidDecl()) {
+ for (auto R : Function->redecls()) {
+ if (R == Function)
+ continue;
+
+ // If some prior declaration of this function has been used, we need
+ // to instantiate its definition.
+ if (!QueuedInstantiation && R->isUsed(false)) {
+ if (MemberSpecializationInfo *MSInfo =
+ Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ SourceLocation Loc = R->getLocation(); // FIXME
+ MSInfo->setPointOfInstantiation(Loc);
+ SemaRef.PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, Loc));
+ QueuedInstantiation = true;
+ }
}
}
}
@@ -2085,7 +2056,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// previous declaration we just found.
if (isFriend && Method->getPreviousDecl())
Method->setAccess(Method->getPreviousDecl()->getAccess());
- else
+ else
Method->setAccess(D->getAccess());
if (FunctionTemplate)
FunctionTemplate->setAccess(Method->getAccess());
@@ -2676,7 +2647,8 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl(
NamedDecl *UD = SemaRef.BuildUsingDeclaration(
/*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(),
- /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr,
+ /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc,
+ ParsedAttributesView(),
/*IsInstantiation*/ true);
if (UD)
SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
@@ -2697,9 +2669,9 @@ Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl(
Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
SmallVector<NamedDecl*, 8> Expansions;
for (auto *UD : D->expansions()) {
- if (auto *NewUD =
+ if (NamedDecl *NewUD =
SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs))
- Expansions.push_back(cast<NamedDecl>(NewUD));
+ Expansions.push_back(NewUD);
else
return nullptr;
}
@@ -2740,6 +2712,8 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
assert(Specialization && "Class scope Specialization is null");
SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD);
+ // FIXME: If this is a definition, check for redefinition errors!
+
return NewFD;
}
@@ -2859,7 +2833,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
Decl *
TemplateDeclInstantiator::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
- return VisitFunctionDecl(D, nullptr);
+ Decl *Inst = VisitFunctionDecl(D, nullptr);
+ if (Inst && !D->getDescribedFunctionTemplate())
+ Owner->addDecl(Inst);
+ return Inst;
}
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -3112,7 +3089,7 @@ Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
return Instantiator.Visit(D);
}
-/// \brief Instantiates a nested template parameter list in the current
+/// Instantiates a nested template parameter list in the current
/// instantiation context.
///
/// \param L The parameter list to instantiate
@@ -3148,7 +3125,14 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
return InstL;
}
-/// \brief Instantiate the declaration of a class template partial
+TemplateParameterList *
+Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
+ return Instantiator.SubstTemplateParams(Params);
+}
+
+/// Instantiate the declaration of a class template partial
/// specialization.
///
/// \param ClassTemplate the (instantiated) class template that is partially
@@ -3282,7 +3266,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
return InstPartialSpec;
}
-/// \brief Instantiate the declaration of a variable template partial
+/// Instantiate the declaration of a variable template partial
/// specialization.
///
/// \param VarTemplate the (instantiated) variable template that is partially
@@ -3433,7 +3417,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
ThisContext = cast<CXXRecordDecl>(Owner);
ThisTypeQuals = Method->getTypeQualifiers();
}
-
+
TypeSourceInfo *NewTInfo
= SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
D->getTypeSpecStartLoc(),
@@ -3624,7 +3608,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
TemplateArgs);
}
-/// \brief Initializes the common fields of an instantiation function
+/// Initializes the common fields of an instantiation function
/// declaration (New) from the corresponding fields of its template (Tmpl).
///
/// \returns true if there was an error
@@ -3657,8 +3641,10 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
"Deduction from the wrong function template?");
(void) FunTmpl;
+ atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = New;
+ atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
}
}
@@ -3710,7 +3696,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
return false;
}
-/// \brief Initializes common fields of an instantiated method
+/// Initializes common fields of an instantiated method
/// declaration (New) from the corresponding fields of its template
/// (Tmpl).
///
@@ -3774,7 +3760,7 @@ static void InstantiateDefaultCtorDefaultArgs(Sema &S,
}
}
-/// \brief Instantiate the definition of the given function from its
+/// Instantiate the definition of the given function from its
/// template.
///
/// \param PointOfInstantiation the point at which the instantiation was
@@ -3854,8 +3840,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl->isLateTemplateParsed() &&
!LateTemplateParser) {
Function->setInstantiationIsPending(true);
- PendingInstantiations.push_back(
- std::make_pair(Function, PointOfInstantiation));
+ LateParsedInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
return;
}
@@ -3912,7 +3898,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Function, SourceLocation(),
"instantiating function definition");
// The instantiation is visible here, even if it was first declared in an
@@ -3957,8 +3943,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
TemplateArgs))
return;
+ StmtResult Body;
if (PatternDecl->hasSkippedBody()) {
ActOnSkippedFunctionBody(Function);
+ Body = nullptr;
} else {
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) {
// If this is a constructor, instantiate the member initializers.
@@ -3974,16 +3962,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
// Instantiate the function body.
- StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+ Body = SubstStmt(Pattern, TemplateArgs);
if (Body.isInvalid())
Function->setInvalidDecl();
-
- // FIXME: finishing the function body while in an expression evaluation
- // context seems wrong. Investigate more.
- ActOnFinishFunctionBody(Function, Body.get(),
- /*IsInstantiation=*/true);
}
+ // FIXME: finishing the function body while in an expression evaluation
+ // context seems wrong. Investigate more.
+ ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true);
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
@@ -4050,7 +4036,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted));
}
-/// \brief Instantiates a variable template specialization by completing it
+/// Instantiates a variable template specialization by completing it
/// with appropriate type information and initializer.
VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
@@ -4100,6 +4086,7 @@ void Sema::BuildVariableInstantiation(
NewVar->setTSCSpec(OldVar->getTSCSpec());
NewVar->setInitStyle(OldVar->getInitStyle());
NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
+ NewVar->setObjCForDecl(OldVar->isObjCForDecl());
NewVar->setConstexpr(OldVar->isConstexpr());
NewVar->setInitCapture(OldVar->isInitCapture());
NewVar->setPreviousDeclInSameBlockScope(
@@ -4173,7 +4160,7 @@ void Sema::BuildVariableInstantiation(
DiagnoseUnusedDecl(NewVar);
}
-/// \brief Instantiate the initializer of a variable.
+/// Instantiate the initializer of a variable.
void Sema::InstantiateVariableInitializer(
VarDecl *Var, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -4219,7 +4206,9 @@ void Sema::InstantiateVariableInitializer(
Var->setInvalidDecl();
}
} else {
- if (Var->isStaticDataMember()) {
+ // `inline` variables are a definition and declaration all in one; we won't
+ // pick up an initializer from anywhere else.
+ if (Var->isStaticDataMember() && !Var->isInline()) {
if (!Var->isOutOfLine())
return;
@@ -4230,14 +4219,17 @@ void Sema::InstantiateVariableInitializer(
}
// We'll add an initializer to a for-range declaration later.
- if (Var->isCXXForRangeDecl())
+ if (Var->isCXXForRangeDecl() || Var->isObjCForDecl())
return;
ActOnUninitializedDecl(Var);
}
+
+ if (getLangOpts().CUDA)
+ checkAllowedCUDAInitializer(Var);
}
-/// \brief Instantiate the definition of the given variable from its
+/// Instantiate the definition of the given variable from its
/// template.
///
/// \param PointOfInstantiation the point at which the instantiation was
@@ -4321,7 +4313,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable initializer");
// The instantiation is visible here, even if it was first declared in an
@@ -4434,7 +4426,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable definition");
// If we're performing recursive template instantiation, create our own
@@ -4856,7 +4848,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
return nullptr;
}
-/// \brief Finds the instantiation of the given declaration context
+/// Finds the instantiation of the given declaration context
/// within the current instantiation.
///
/// \returns NULL if there was an error
@@ -4868,7 +4860,7 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
} else return DC;
}
-/// \brief Find the instantiation of the given declaration within the
+/// Find the instantiation of the given declaration within the
/// current instantiation.
///
/// This routine is intended to be used when \p D is a declaration
@@ -4898,14 +4890,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool FindingInstantiatedContext) {
DeclContext *ParentDC = D->getDeclContext();
- // FIXME: Parmeters of pointer to functions (y below) that are themselves
+ // FIXME: Parmeters of pointer to functions (y below) that are themselves
// parameters (p below) can have their ParentDC set to the translation-unit
- // - thus we can not consistently check if the ParentDC of such a parameter
+ // - thus we can not consistently check if the ParentDC of such a parameter
// is Dependent or/and a FunctionOrMethod.
- // For e.g. this code, during Template argument deduction tries to
+ // For e.g. this code, during Template argument deduction tries to
// find an instantiated decl for (T y) when the ParentDC for y is
- // the translation unit.
- // e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {}
+ // the translation unit.
+ // e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {}
// float baz(float(*)()) { return 0.0; }
// Foo(baz);
// The better fix here is perhaps to ensure that a ParmVarDecl, by the time
@@ -5181,7 +5173,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return D;
}
-/// \brief Performs template instantiation for all implicit template
+/// Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
void Sema::PerformPendingInstantiations(bool LocalOnly) {
while (!PendingLocalImplicitInstantiations.empty() ||
@@ -5200,10 +5192,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
- DefinitionRequired, true);
- if (Function->isDefined())
- Function->setInstantiationIsPending(false);
+ if (Function->isMultiVersion()) {
+ getASTContext().forEachMultiversionedFunctionVersion(
+ Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) {
+ InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true,
+ DefinitionRequired, true);
+ if (CurFD->isDefined())
+ CurFD->setInstantiationIsPending(false);
+ });
+ } else {
+ InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true,
+ DefinitionRequired, true);
+ if (Function->isDefined())
+ Function->setInstantiationIsPending(false);
+ }
continue;
}
@@ -5238,7 +5240,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
break;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable definition");
bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index d81837dad508..6f9dddf5c05e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -26,23 +26,10 @@ 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.
+ /// A class that collects unexpanded parameter packs.
class CollectUnexpandedParameterPacksVisitor :
- public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
+ public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
{
typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
inherited;
@@ -71,7 +58,7 @@ namespace {
if (T->getDepth() < DepthLimit)
Unexpanded.push_back({T, Loc});
}
-
+
public:
explicit CollectUnexpandedParameterPacksVisitor(
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
@@ -83,14 +70,14 @@ namespace {
// Recording occurrences of (unexpanded) parameter packs.
//------------------------------------------------------------------------
- /// \brief Record occurrences of template type parameter packs.
+ /// Record occurrences of template type parameter packs.
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
if (TL.getTypePtr()->isParameterPack())
addUnexpanded(TL.getTypePtr(), TL.getNameLoc());
return true;
}
- /// \brief Record occurrences of template type parameter packs
+ /// Record occurrences of template type parameter packs
/// when we don't have proper source-location information for
/// them.
///
@@ -102,27 +89,27 @@ namespace {
return true;
}
- /// \brief Record occurrences of function and non-type template
+ /// Record occurrences of function and non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (E->getDecl()->isParameterPack())
addUnexpanded(E->getDecl(), E->getLocation());
-
+
return true;
}
-
- /// \brief Record occurrences of template template parameter packs.
+
+ /// Record occurrences of template template parameter packs.
bool TraverseTemplateName(TemplateName Template) {
if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
Template.getAsTemplateDecl())) {
if (TTP->isParameterPack())
addUnexpanded(TTP);
}
-
+
return inherited::TraverseTemplateName(Template);
}
- /// \brief Suppress traversal into Objective-C container literal
+ /// Suppress traversal into Objective-C container literal
/// elements that are pack expansions.
bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
if (!E->containsUnexpandedParameterPack())
@@ -142,9 +129,9 @@ namespace {
// Pruning the search for unexpanded parameter packs.
//------------------------------------------------------------------------
- /// \brief Suppress traversal into statements and expressions that
+ /// Suppress traversal into statements and expressions that
/// do not contain unexpanded parameter packs.
- bool TraverseStmt(Stmt *S) {
+ bool TraverseStmt(Stmt *S) {
Expr *E = dyn_cast_or_null<Expr>(S);
if ((E && E->containsUnexpandedParameterPack()) || InLambda)
return inherited::TraverseStmt(S);
@@ -152,7 +139,7 @@ namespace {
return true;
}
- /// \brief Suppress traversal into types that do not contain
+ /// Suppress traversal into types that do not contain
/// unexpanded parameter packs.
bool TraverseType(QualType T) {
if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda)
@@ -161,10 +148,10 @@ namespace {
return true;
}
- /// \brief Suppress traversal into types with location information
+ /// Suppress traversal into types with location information
/// that do not contain unexpanded parameter packs.
bool TraverseTypeLoc(TypeLoc TL) {
- if ((!TL.getType().isNull() &&
+ if ((!TL.getType().isNull() &&
TL.getType()->containsUnexpandedParameterPack()) ||
InLambda)
return inherited::TraverseTypeLoc(TL);
@@ -172,8 +159,8 @@ namespace {
return true;
}
- /// \brief Suppress traversal of parameter packs.
- bool TraverseDecl(Decl *D) {
+ /// Suppress traversal of parameter packs.
+ bool TraverseDecl(Decl *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.
@@ -183,7 +170,7 @@ namespace {
return inherited::TraverseDecl(D);
}
- /// \brief Suppress traversal of pack-expanded attributes.
+ /// Suppress traversal of pack-expanded attributes.
bool TraverseAttr(Attr *A) {
if (A->isPackExpansion())
return true;
@@ -191,7 +178,7 @@ namespace {
return inherited::TraverseAttr(A);
}
- /// \brief Suppress traversal of pack expansion expressions and types.
+ /// Suppress traversal of pack expansion expressions and types.
///@{
bool TraversePackExpansionType(PackExpansionType *T) { return true; }
bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; }
@@ -200,7 +187,7 @@ namespace {
///@}
- /// \brief Suppress traversal of using-declaration pack expansion.
+ /// Suppress traversal of using-declaration pack expansion.
bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
if (D->isPackExpansion())
return true;
@@ -208,7 +195,7 @@ namespace {
return inherited::TraverseUnresolvedUsingValueDecl(D);
}
- /// \brief Suppress traversal of using-declaration pack expansion.
+ /// Suppress traversal of using-declaration pack expansion.
bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
if (D->isPackExpansion())
return true;
@@ -216,7 +203,7 @@ namespace {
return inherited::TraverseUnresolvedUsingTypenameDecl(D);
}
- /// \brief Suppress traversal of template argument pack expansions.
+ /// Suppress traversal of template argument pack expansions.
bool TraverseTemplateArgument(const TemplateArgument &Arg) {
if (Arg.isPackExpansion())
return true;
@@ -224,15 +211,15 @@ namespace {
return inherited::TraverseTemplateArgument(Arg);
}
- /// \brief Suppress traversal of template argument pack expansions.
+ /// Suppress traversal of template argument pack expansions.
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
if (ArgLoc.getArgument().isPackExpansion())
return true;
-
+
return inherited::TraverseTemplateArgumentLoc(ArgLoc);
}
- /// \brief Suppress traversal of base specifier pack expansions.
+ /// Suppress traversal of base specifier pack expansions.
bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
if (Base.isPackExpansion())
return true;
@@ -240,7 +227,7 @@ namespace {
return inherited::TraverseCXXBaseSpecifier(Base);
}
- /// \brief Suppress traversal of mem-initializer pack expansions.
+ /// Suppress traversal of mem-initializer pack expansions.
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
if (Init->isPackExpansion())
return true;
@@ -248,7 +235,7 @@ namespace {
return inherited::TraverseConstructorInitializer(Init);
}
- /// \brief Note whether we're traversing a lambda containing an unexpanded
+ /// 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
/// lambda, we don't propagate the 'contains unexpanded parameter pack' bit
@@ -284,7 +271,7 @@ namespace {
};
}
-/// \brief Determine whether it's possible for an unexpanded parameter pack to
+/// Determine whether it's possible for an unexpanded parameter pack to
/// be valid in this location. This only happens when we're in a declaration
/// that is nested within an expression that could be expanded, such as a
/// lambda-expression within a function call.
@@ -298,7 +285,7 @@ bool Sema::isUnexpandedParameterPackPermitted() {
return false;
}
-/// \brief Diagnose all of the unexpanded parameter packs in the given
+/// Diagnose all of the unexpanded parameter packs in the given
/// vector.
bool
Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
@@ -314,8 +301,18 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
// later.
SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences;
for (unsigned N = FunctionScopes.size(); N; --N) {
- if (sema::LambdaScopeInfo *LSI =
- dyn_cast<sema::LambdaScopeInfo>(FunctionScopes[N-1])) {
+ sema::FunctionScopeInfo *Func = FunctionScopes[N-1];
+ // We do not permit pack expansion that would duplicate a statement
+ // expression, not even within a lambda.
+ // FIXME: We could probably support this for statement expressions that do
+ // not contain labels, and for pack expansions that expand both the stmt
+ // expr and the enclosing lambda.
+ if (std::any_of(
+ Func->CompoundScopes.begin(), Func->CompoundScopes.end(),
+ [](sema::CompoundScopeInfo &CSI) { return CSI.IsStmtExpr; }))
+ break;
+
+ if (auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Func)) {
if (N == FunctionScopes.size()) {
for (auto &Param : Unexpanded) {
auto *PD = dyn_cast_or_null<ParmVarDecl>(
@@ -338,7 +335,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
return false;
}
}
-
+
SmallVector<SourceLocation, 4> Locations;
SmallVector<IdentifierInfo *, 4> Names;
llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
@@ -368,11 +365,11 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
return true;
}
-bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
TypeSourceInfo *T,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
- // An appearance of a name of a parameter pack that is not expanded is
+ // An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
if (!T->getType()->containsUnexpandedParameterPack())
return false;
@@ -387,7 +384,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
- // An appearance of a name of a parameter pack that is not expanded is
+ // An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
if (!E->containsUnexpandedParameterPack())
return false;
@@ -401,9 +398,9 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
- // An appearance of a name of a parameter pack that is not expanded is
+ // An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
- if (!SS.getScopeRep() ||
+ if (!SS.getScopeRep() ||
!SS.getScopeRep()->containsUnexpandedParameterPack())
return false;
@@ -418,7 +415,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
- // An appearance of a name of a parameter pack that is not expanded is
+ // An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
switch (NameInfo.getName().getNameKind()) {
case DeclarationName::Identifier:
@@ -454,7 +451,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
TemplateName Template,
UnexpandedParameterPackContext UPPC) {
-
+
if (Template.isNull() || !Template.containsUnexpandedParameterPack())
return false;
@@ -467,10 +464,10 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
UnexpandedParameterPackContext UPPC) {
- if (Arg.getArgument().isNull() ||
+ if (Arg.getArgument().isNull() ||
!Arg.getArgument().containsUnexpandedParameterPack())
return false;
-
+
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateArgumentLoc(Arg);
@@ -492,12 +489,12 @@ void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
void Sema::collectUnexpandedParameterPacks(QualType T,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
- CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
-}
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
+}
void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
- CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
}
void Sema::collectUnexpandedParameterPacks(
@@ -515,7 +512,7 @@ void Sema::collectUnexpandedParameterPacks(
}
-ParsedTemplateArgument
+ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) {
if (Arg.isInvalid())
@@ -527,7 +524,7 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
if (Result.isInvalid())
return ParsedTemplateArgument();
- return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
+ return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
Arg.getLocation());
}
@@ -535,11 +532,11 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc);
if (Result.isInvalid())
return ParsedTemplateArgument();
-
- return ParsedTemplateArgument(Arg.getKind(), Result.get(),
+
+ return ParsedTemplateArgument(Arg.getKind(), Result.get(),
Arg.getLocation());
}
-
+
case ParsedTemplateArgument::Template:
if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
SourceRange R(Arg.getLocation());
@@ -549,13 +546,13 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
<< R;
return ParsedTemplateArgument();
}
-
+
return Arg.getTemplatePackExpansion(EllipsisLoc);
}
llvm_unreachable("Unhandled template argument kind?");
}
-TypeResult Sema::ActOnPackExpansion(ParsedType Type,
+TypeResult Sema::ActOnPackExpansion(ParsedType Type,
SourceLocation EllipsisLoc) {
TypeSourceInfo *TSInfo;
GetTypeFromParser(Type, &TSInfo);
@@ -565,7 +562,7 @@ TypeResult Sema::ActOnPackExpansion(ParsedType Type,
TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, None);
if (!TSResult)
return true;
-
+
return CreateParsedType(TSResult->getType(), TSResult);
}
@@ -573,7 +570,7 @@ TypeSourceInfo *
Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions) {
// Create the pack expansion type and source-location information.
- QualType Result = CheckPackExpansion(Pattern->getType(),
+ QualType Result = CheckPackExpansion(Pattern->getType(),
Pattern->getTypeLoc().getSourceRange(),
EllipsisLoc, NumExpansions);
if (Result.isNull())
@@ -611,7 +608,7 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions) {
if (!Pattern)
return ExprError();
-
+
// C++0x [temp.variadic]p5:
// The pattern of a pack expansion shall name one or more
// parameter packs that are not expanded by a nested pack
@@ -621,7 +618,7 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
<< Pattern->getSourceRange();
return ExprError();
}
-
+
// Create the pack expansion expression and source-location information.
return new (Context)
PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions);
@@ -636,7 +633,9 @@ bool Sema::CheckParameterPacksForExpansion(
RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
-
+ Optional<unsigned> NumPartialExpansions;
+ SourceLocation PartiallySubstitutedPackLoc;
+
for (ArrayRef<UnexpandedParameterPack>::iterator i = Unexpanded.begin(),
end = Unexpanded.end();
i != end; ++i) {
@@ -644,7 +643,7 @@ bool Sema::CheckParameterPacksForExpansion(
unsigned Depth = 0, Index = 0;
IdentifierInfo *Name;
bool IsFunctionParameterPack = false;
-
+
if (const TemplateTypeParmType *TTP
= i->first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
@@ -659,13 +658,13 @@ bool Sema::CheckParameterPacksForExpansion(
Name = ND->getIdentifier();
}
-
+
// Determine the size of this argument pack.
- unsigned NewPackSize;
+ unsigned NewPackSize;
if (IsFunctionParameterPack) {
// Figure out whether we're instantiating to an argument pack or not.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
-
+
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
= CurrentInstantiationScope->findInstantiationOf(
i->first.get<NamedDecl *>());
@@ -679,35 +678,40 @@ bool Sema::CheckParameterPacksForExpansion(
continue;
}
} else {
- // If we don't have a template argument at this depth/index, then we
- // cannot expand the pack expansion. Make a note of this, but we still
+ // If we don't have a template argument at this depth/index, then we
+ // cannot expand the pack expansion. Make a note of this, but we still
// want to check any parameter packs we *do* have arguments for.
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index)) {
ShouldExpand = false;
continue;
}
-
+
// Determine the size of the argument pack.
NewPackSize = TemplateArgs(Depth, Index).pack_size();
}
-
+
// C++0x [temp.arg.explicit]p9:
- // Template argument deduction can extend the sequence of template
+ // Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
if (!IsFunctionParameterPack && CurrentInstantiationScope) {
- if (NamedDecl *PartialPack
+ if (NamedDecl *PartialPack
= CurrentInstantiationScope->getPartiallySubstitutedPack()){
unsigned PartialDepth, PartialIndex;
std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
- if (PartialDepth == Depth && PartialIndex == Index)
+ if (PartialDepth == Depth && PartialIndex == Index) {
RetainExpansion = true;
+ // We don't actually know the new pack size yet.
+ NumPartialExpansions = NewPackSize;
+ PartiallySubstitutedPackLoc = i->second;
+ continue;
+ }
}
}
-
+
if (!NumExpansions) {
- // The is the first pack we've seen for which we have an argument.
+ // The is the first pack we've seen for which we have an argument.
// Record it.
NumExpansions = NewPackSize;
FirstPack.first = Name;
@@ -715,10 +719,10 @@ bool Sema::CheckParameterPacksForExpansion(
HaveFirstPack = true;
continue;
}
-
+
if (NewPackSize != *NumExpansions) {
// C++0x [temp.variadic]p5:
- // All of the parameter packs expanded by a pack expansion shall have
+ // All of the parameter packs expanded by a pack expansion shall have
// the same number of arguments specified.
if (HaveFirstPack)
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
@@ -732,6 +736,28 @@ bool Sema::CheckParameterPacksForExpansion(
}
}
+ // If we're performing a partial expansion but we also have a full expansion,
+ // expand to the number of common arguments. For example, given:
+ //
+ // template<typename ...T> struct A {
+ // template<typename ...U> void f(pair<T, U>...);
+ // };
+ //
+ // ... a call to 'A<int, int>().f<int>' should expand the pack once and
+ // retain an expansion.
+ if (NumPartialExpansions) {
+ if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
+ NamedDecl *PartialPack =
+ CurrentInstantiationScope->getPartiallySubstitutedPack();
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
+ << PartialPack << *NumPartialExpansions << *NumExpansions
+ << SourceRange(PartiallySubstitutedPackLoc);
+ return true;
+ }
+
+ NumExpansions = NumPartialExpansions;
+ }
+
return false;
}
@@ -746,17 +772,17 @@ Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
// Compute the depth and index for this parameter pack.
unsigned Depth;
unsigned Index;
-
+
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
- } else {
+ } else {
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
if (isa<ParmVarDecl>(ND)) {
// Function parameter pack.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
-
+
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
= CurrentInstantiationScope->findInstantiationOf(
Unexpanded[I].first.get<NamedDecl *>());
@@ -778,13 +804,13 @@ Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
// The pattern refers to an unknown template argument. We're not ready to
// expand this pack yet.
return None;
-
+
// Determine the size of the argument pack.
unsigned Size = TemplateArgs(Depth, Index).pack_size();
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
}
-
+
return Result;
}
@@ -800,18 +826,19 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
return true;
break;
}
-
+
case TST_typeofExpr:
case TST_decltype:
- if (DS.getRepAsExpr() &&
+ if (DS.getRepAsExpr() &&
DS.getRepAsExpr()->containsUnexpandedParameterPack())
return true;
break;
-
+
case TST_unspecified:
case TST_void:
case TST_char:
case TST_wchar:
+ case TST_char8:
case TST_char16:
case TST_char32:
case TST_int:
@@ -819,6 +846,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_half:
case TST_float:
case TST_double:
+ case TST_Accum:
+ case TST_Fract:
case TST_Float16:
case TST_float128:
case TST_bool:
@@ -850,7 +879,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case DeclaratorChunk::BlockPointer:
// These declarator chunks cannot contain any parameter packs.
break;
-
+
case DeclaratorChunk::Array:
if (Chunk.Arr.NumElts &&
Chunk.Arr.NumElts->containsUnexpandedParameterPack())
@@ -871,14 +900,14 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
->containsUnexpandedParameterPack())
return true;
}
- } else if (Chunk.Fun.getExceptionSpecType() == EST_ComputedNoexcept &&
+ } else if (isComputedNoexcept(Chunk.Fun.getExceptionSpecType()) &&
Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack())
return true;
if (Chunk.Fun.hasTrailingReturnType()) {
QualType T = Chunk.Fun.getTrailingReturnType().get();
- if (!T.isNull() && T->containsUnexpandedParameterPack())
- return true;
+ if (!T.isNull() && T->containsUnexpandedParameterPack())
+ return true;
}
break;
@@ -889,7 +918,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
break;
}
}
-
+
return false;
}
@@ -906,7 +935,7 @@ class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
}
-/// \brief Called when an expression computing the size of a parameter pack
+/// Called when an expression computing the size of a parameter pack
/// is parsed.
///
/// \code
@@ -935,7 +964,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
case LookupResult::Found:
ParameterPack = R.getFoundDecl();
break;
-
+
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (TypoCorrection Corrected =
@@ -951,12 +980,12 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
break;
-
+
case LookupResult::Ambiguous:
DiagnoseAmbiguousLookup(R);
return ExprError();
}
-
+
if (!ParameterPack || !ParameterPack->isParameterPack()) {
Diag(NameLoc, diag::err_sizeof_pack_no_pack_name)
<< &Name;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index af060cf21b5f..284d34b22c04 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -63,13 +64,17 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
/// diagnoseBadTypeAttribute - Diagnoses a type attribute which
/// doesn't apply to the given type.
-static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
+static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
QualType type) {
TypeDiagSelector WhichType;
bool useExpansionLoc = true;
switch (attr.getKind()) {
- case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break;
- case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break;
+ case ParsedAttr::AT_ObjCGC:
+ WhichType = TDS_Pointer;
+ break;
+ case ParsedAttr::AT_ObjCOwnership:
+ WhichType = TDS_ObjCObjOrBlock;
+ break;
default:
// Assume everything else was a function attribute.
WhichType = TDS_Function;
@@ -97,47 +102,48 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
// objc_gc applies to Objective-C pointers or, otherwise, to the
// smallest available pointer type (i.e. 'void*' in 'void**').
-#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_ObjCGC: \
- case AttributeList::AT_ObjCOwnership
+#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_ObjCGC: \
+ case ParsedAttr::AT_ObjCOwnership
// Calling convention attributes.
-#define CALLING_CONV_ATTRS_CASELIST \
- case AttributeList::AT_CDecl: \
- case AttributeList::AT_FastCall: \
- case AttributeList::AT_StdCall: \
- case AttributeList::AT_ThisCall: \
- case AttributeList::AT_RegCall: \
- case AttributeList::AT_Pascal: \
- case AttributeList::AT_SwiftCall: \
- case AttributeList::AT_VectorCall: \
- case AttributeList::AT_MSABI: \
- case AttributeList::AT_SysVABI: \
- case AttributeList::AT_Pcs: \
- case AttributeList::AT_IntelOclBicc: \
- case AttributeList::AT_PreserveMost: \
- case AttributeList::AT_PreserveAll
+#define CALLING_CONV_ATTRS_CASELIST \
+ case ParsedAttr::AT_CDecl: \
+ case ParsedAttr::AT_FastCall: \
+ case ParsedAttr::AT_StdCall: \
+ case ParsedAttr::AT_ThisCall: \
+ case ParsedAttr::AT_RegCall: \
+ case ParsedAttr::AT_Pascal: \
+ case ParsedAttr::AT_SwiftCall: \
+ case ParsedAttr::AT_VectorCall: \
+ case ParsedAttr::AT_MSABI: \
+ case ParsedAttr::AT_SysVABI: \
+ case ParsedAttr::AT_Pcs: \
+ case ParsedAttr::AT_IntelOclBicc: \
+ case ParsedAttr::AT_PreserveMost: \
+ case ParsedAttr::AT_PreserveAll
// Function type attributes.
-#define FUNCTION_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_NSReturnsRetained: \
- case AttributeList::AT_NoReturn: \
- case AttributeList::AT_Regparm: \
- case AttributeList::AT_AnyX86NoCallerSavedRegisters: \
+#define FUNCTION_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_NSReturnsRetained: \
+ case ParsedAttr::AT_NoReturn: \
+ case ParsedAttr::AT_Regparm: \
+ case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: \
+ case ParsedAttr::AT_AnyX86NoCfCheck: \
CALLING_CONV_ATTRS_CASELIST
// Microsoft-specific type qualifiers.
-#define MS_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_Ptr32: \
- case AttributeList::AT_Ptr64: \
- case AttributeList::AT_SPtr: \
- case AttributeList::AT_UPtr
+#define MS_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_Ptr32: \
+ case ParsedAttr::AT_Ptr64: \
+ case ParsedAttr::AT_SPtr: \
+ case ParsedAttr::AT_UPtr
// Nullability qualifiers.
-#define NULLABILITY_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_TypeNonNull: \
- case AttributeList::AT_TypeNullable: \
- case AttributeList::AT_TypeNullUnspecified
+#define NULLABILITY_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_TypeNonNull: \
+ case ParsedAttr::AT_TypeNullable: \
+ case ParsedAttr::AT_TypeNullUnspecified
namespace {
/// An object which stores processing state for the entire
@@ -160,11 +166,11 @@ namespace {
bool hasSavedAttrs;
/// The original set of attributes on the DeclSpec.
- SmallVector<AttributeList*, 2> savedAttrs;
+ SmallVector<ParsedAttr *, 2> savedAttrs;
/// A list of attributes to diagnose the uselessness of when the
/// processing is complete.
- SmallVector<AttributeList*, 2> ignoredTypeAttrs;
+ SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
public:
TypeProcessingState(Sema &sema, Declarator &declarator)
@@ -193,10 +199,10 @@ namespace {
chunkIndex = idx;
}
- AttributeList *&getCurrentAttrListRef() const {
+ ParsedAttributesView &getCurrentAttributes() const {
if (isProcessingDeclSpec())
- return getMutableDeclSpec().getAttributes().getListRef();
- return declarator.getTypeObject(chunkIndex).getAttrListRef();
+ return getMutableDeclSpec().getAttributes();
+ return declarator.getTypeObject(chunkIndex).getAttrs();
}
/// Save the current set of attributes on the DeclSpec.
@@ -205,16 +211,15 @@ namespace {
if (hasSavedAttrs) return;
DeclSpec &spec = getMutableDeclSpec();
- for (AttributeList *attr = spec.getAttributes().getList(); attr;
- attr = attr->getNext())
- savedAttrs.push_back(attr);
+ for (ParsedAttr &AL : spec.getAttributes())
+ savedAttrs.push_back(&AL);
trivial &= savedAttrs.empty();
hasSavedAttrs = true;
}
/// Record that we had nowhere to put the given type attribute.
/// We will diagnose such attributes later.
- void addIgnoredTypeAttr(AttributeList &attr) {
+ void addIgnoredTypeAttr(ParsedAttr &attr) {
ignoredTypeAttrs.push_back(&attr);
}
@@ -239,46 +244,18 @@ namespace {
void restoreDeclSpecAttrs() {
assert(hasSavedAttrs);
- if (savedAttrs.empty()) {
- getMutableDeclSpec().getAttributes().set(nullptr);
- return;
- }
-
- getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
- for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
- savedAttrs[i]->setNext(savedAttrs[i+1]);
- savedAttrs.back()->setNext(nullptr);
+ getMutableDeclSpec().getAttributes().clearListOnly();
+ for (ParsedAttr *AL : savedAttrs)
+ getMutableDeclSpec().getAttributes().addAtStart(AL);
}
};
} // end anonymous namespace
-static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
- attr.setNext(head);
- head = &attr;
-}
-
-static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
- if (head == &attr) {
- head = attr.getNext();
- return;
- }
-
- AttributeList *cur = head;
- while (true) {
- assert(cur && cur->getNext() && "ran out of attrs?");
- if (cur->getNext() == &attr) {
- cur->setNext(attr.getNext());
- return;
- }
- cur = cur->getNext();
- }
-}
-
-static void moveAttrFromListToList(AttributeList &attr,
- AttributeList *&fromList,
- AttributeList *&toList) {
- spliceAttrOutOfList(attr, fromList);
- spliceAttrIntoList(attr, toList);
+static void moveAttrFromListToList(ParsedAttr &attr,
+ ParsedAttributesView &fromList,
+ ParsedAttributesView &toList) {
+ fromList.remove(&attr);
+ toList.addAtStart(&attr);
}
/// The location of a type attribute.
@@ -291,29 +268,26 @@ enum TypeAttrLocation {
TAL_DeclName
};
-static void processTypeAttrs(TypeProcessingState &state,
- QualType &type, TypeAttrLocation TAL,
- AttributeList *attrs);
+static void processTypeAttrs(TypeProcessingState &state, QualType &type,
+ TypeAttrLocation TAL, ParsedAttributesView &attrs);
-static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
+static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type);
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type);
+ ParsedAttr &attr, QualType &type);
-static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
+static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
+ QualType &type);
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
+ ParsedAttr &attr, QualType &type);
static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type) {
- if (attr.getKind() == AttributeList::AT_ObjCGC)
+ ParsedAttr &attr, QualType &type) {
+ if (attr.getKind() == ParsedAttr::AT_ObjCGC)
return handleObjCGCTypeAttr(state, attr, type);
- assert(attr.getKind() == AttributeList::AT_ObjCOwnership);
+ assert(attr.getKind() == ParsedAttr::AT_ObjCOwnership);
return handleObjCOwnershipTypeAttr(state, attr, type);
}
@@ -395,8 +369,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
/// didn't apply in whatever position it was written in, try to move
/// it to a more appropriate position.
static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
+ ParsedAttr &attr, QualType type) {
Declarator &declarator = state.getDeclarator();
// Move it to the outermost normal or block pointer declarator.
@@ -409,13 +382,13 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
// of a block.
DeclaratorChunk *destChunk = nullptr;
if (state.isProcessingDeclSpec() &&
- attr.getKind() == AttributeList::AT_ObjCOwnership)
+ attr.getKind() == ParsedAttr::AT_ObjCOwnership)
destChunk = maybeMovePastReturnType(declarator, i - 1,
/*onlyBlockPointers=*/true);
if (!destChunk) destChunk = &chunk;
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- destChunk->getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ destChunk->getAttrs());
return;
}
@@ -426,12 +399,12 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
// We may be starting at the return type of a block.
case DeclaratorChunk::Function:
if (state.isProcessingDeclSpec() &&
- attr.getKind() == AttributeList::AT_ObjCOwnership) {
+ attr.getKind() == ParsedAttr::AT_ObjCOwnership) {
if (DeclaratorChunk *dest = maybeMovePastReturnType(
declarator, i,
/*onlyBlockPointers=*/true)) {
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- dest->getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ dest->getAttrs());
return;
}
}
@@ -451,10 +424,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
/// Distribute an objc_gc type attribute that was written on the
/// declarator.
-static void
-distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
+static void distributeObjCPointerTypeAttrFromDeclarator(
+ TypeProcessingState &state, ParsedAttr &attr, QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// objc_gc goes on the innermost pointer to something that's not a
@@ -491,8 +462,8 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
// attribute from being applied multiple times and gives
// the source-location-filler something to work with.
state.saveDeclSpecAttrs();
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getMutableDeclSpec().getAttributes().getListRef());
+ moveAttrFromListToList(attr, declarator.getAttributes(),
+ declarator.getMutableDeclSpec().getAttributes());
return;
}
}
@@ -500,13 +471,13 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
// Otherwise, if we found an appropriate chunk, splice the attribute
// into it.
if (innermost != -1U) {
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getTypeObject(innermost).getAttrListRef());
+ moveAttrFromListToList(attr, declarator.getAttributes(),
+ declarator.getTypeObject(innermost).getAttrs());
return;
}
// Otherwise, diagnose when we're done building the type.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
+ declarator.getAttributes().remove(&attr);
state.addIgnoredTypeAttr(attr);
}
@@ -515,8 +486,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
/// that it didn't apply in whatever position it was written in, try
/// to move it to a more appropriate position.
static void distributeFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
+ ParsedAttr &attr, QualType type) {
Declarator &declarator = state.getDeclarator();
// Try to push the attribute from the return type of a function to
@@ -525,8 +495,8 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Function:
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ chunk.getAttrs());
return;
case DeclaratorChunk::Paren:
@@ -546,11 +516,9 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
/// Try to distribute a function type attribute to the innermost
/// function chunk or type. Returns true if the attribute was
/// distributed, false if no location was found.
-static bool
-distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
- AttributeList &attr,
- AttributeList *&attrList,
- QualType &declSpecType) {
+static bool distributeFunctionTypeAttrToInnermost(
+ TypeProcessingState &state, ParsedAttr &attr,
+ ParsedAttributesView &attrList, QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// Put it on the innermost function chunk, if there is one.
@@ -558,7 +526,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
DeclaratorChunk &chunk = declarator.getTypeObject(i);
if (chunk.Kind != DeclaratorChunk::Function) continue;
- moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
+ moveAttrFromListToList(attr, attrList, chunk.getAttrs());
return true;
}
@@ -567,25 +535,23 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
/// A function type attribute was written in the decl spec. Try to
/// apply it somewhere.
-static void
-distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
+static void distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
+ ParsedAttr &attr,
+ QualType &declSpecType) {
state.saveDeclSpecAttrs();
// C++11 attributes before the decl specifiers actually appertain to
// the declarators. Move them straight there. We don't support the
// 'put them wherever you like' semantics we allow for GNU attributes.
if (attr.isCXX11Attribute()) {
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- state.getDeclarator().getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ state.getDeclarator().getAttributes());
return;
}
// Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- state.getCurrentAttrListRef(),
- declSpecType))
+ if (distributeFunctionTypeAttrToInnermost(
+ state, attr, state.getCurrentAttributes(), declSpecType))
return;
// If that failed, diagnose the bad attribute when the declarator is
@@ -595,25 +561,23 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
/// A function type attribute was written on the declarator. Try to
/// apply it somewhere.
-static void
-distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
+static void distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
+ ParsedAttr &attr,
+ QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- declarator.getAttrListRef(),
- declSpecType))
+ if (distributeFunctionTypeAttrToInnermost(
+ state, attr, declarator.getAttributes(), declSpecType))
return;
// If that failed, diagnose the bad attribute when the declarator is
// fully built.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
+ declarator.getAttributes().remove(&attr);
state.addIgnoredTypeAttr(attr);
}
-/// \brief Given that there are attributes written on the declarator
+/// Given that there are attributes written on the declarator
/// itself, try to distribute any type attributes to the appropriate
/// declarator chunk.
///
@@ -625,24 +589,25 @@ distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
QualType &declSpecType) {
// Collect all the type attributes from the declarator itself.
- assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
- AttributeList *attr = state.getDeclarator().getAttributes();
- AttributeList *next;
- do {
- next = attr->getNext();
-
+ assert(!state.getDeclarator().getAttributes().empty() &&
+ "declarator has no attrs!");
+ // The called functions in this loop actually remove things from the current
+ // list, so iterating over the existing list isn't possible. Instead, make a
+ // non-owning copy and iterate over that.
+ ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()};
+ for (ParsedAttr &attr : AttrsCopy) {
// Do not distribute C++11 attributes. They have strict rules for what
// they appertain to.
- if (attr->isCXX11Attribute())
+ if (attr.isCXX11Attribute())
continue;
- switch (attr->getKind()) {
+ switch (attr.getKind()) {
OBJC_POINTER_TYPE_ATTRS_CASELIST:
- distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
+ distributeObjCPointerTypeAttrFromDeclarator(state, attr, declSpecType);
break;
FUNCTION_TYPE_ATTRS_CASELIST:
- distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
+ distributeFunctionTypeAttrFromDeclarator(state, attr, declSpecType);
break;
MS_TYPE_ATTRS_CASELIST:
@@ -653,13 +618,13 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
// Nullability specifiers cannot go after the declarator-id.
// Objective-C __kindof does not get distributed.
- case AttributeList::AT_ObjCKindOf:
+ case ParsedAttr::AT_ObjCKindOf:
continue;
default:
break;
}
- } while ((attr = next));
+ }
}
/// Add a synthetic '()' to a block-literal declarator if it is
@@ -759,28 +724,18 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
return false;
// Warn if we see type attributes for omitted return type on a block literal.
- AttributeList *&attrs =
- declarator.getMutableDeclSpec().getAttributes().getListRef();
- AttributeList *prev = nullptr;
- for (AttributeList *cur = attrs; cur; cur = cur->getNext()) {
- AttributeList &attr = *cur;
- // Skip attributes that were marked to be invalid or non-type
- // attributes.
- if (attr.isInvalid() || !attr.isTypeAttr()) {
- prev = cur;
+ SmallVector<ParsedAttr *, 2> ToBeRemoved;
+ for (ParsedAttr &AL : declarator.getMutableDeclSpec().getAttributes()) {
+ if (AL.isInvalid() || !AL.isTypeAttr())
continue;
- }
- S.Diag(attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::warn_block_literal_attributes_on_omitted_return_type)
- << attr.getName();
- // Remove cur from the list.
- if (prev) {
- prev->setNext(cur->getNext());
- prev = cur;
- } else {
- attrs = cur->getNext();
- }
+ << AL.getName();
+ ToBeRemoved.push_back(&AL);
}
+ // Remove bad attributes from the list.
+ for (ParsedAttr *AL : ToBeRemoved)
+ declarator.getMutableDeclSpec().getAttributes().remove(AL);
// Warn if we see type qualifiers for omitted return type on a block literal.
const DeclSpec &DS = declarator.getDeclSpec();
@@ -1208,22 +1163,15 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
return CreateParsedType(Result, ResultTInfo);
}
-static OpenCLAccessAttr::Spelling getImageAccess(const AttributeList *Attrs) {
- if (Attrs) {
- const AttributeList *Next = Attrs;
- do {
- const AttributeList &Attr = *Next;
- Next = Attr.getNext();
- if (Attr.getKind() == AttributeList::AT_OpenCLAccess) {
- return static_cast<OpenCLAccessAttr::Spelling>(
- Attr.getSemanticSpelling());
- }
- } while (Next);
- }
+static OpenCLAccessAttr::Spelling
+getImageAccess(const ParsedAttributesView &Attrs) {
+ for (const ParsedAttr &AL : Attrs)
+ if (AL.getKind() == ParsedAttr::AT_OpenCLAccess)
+ return static_cast<OpenCLAccessAttr::Spelling>(AL.getSemanticSpelling());
return OpenCLAccessAttr::Keyword_read_only;
}
-/// \brief Convert the specified declspec to the appropriate type
+/// Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
/// to be converted, along with other associated processing state.
@@ -1235,7 +1183,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Sema &S = state.getSema();
Declarator &declarator = state.getDeclarator();
- const DeclSpec &DS = declarator.getDeclSpec();
+ DeclSpec &DS = declarator.getMutableDeclSpec();
SourceLocation DeclLoc = declarator.getIdentifierLoc();
if (DeclLoc.isInvalid())
DeclLoc = DS.getLocStart();
@@ -1275,6 +1223,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.getUnsignedWCharType();
}
break;
+ case DeclSpec::TST_char8:
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char8Ty;
+ break;
case DeclSpec::TST_char16:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
@@ -1384,6 +1337,52 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
}
+ case DeclSpec::TST_accum: {
+ switch (DS.getTypeSpecWidth()) {
+ case DeclSpec::TSW_short:
+ Result = Context.ShortAccumTy;
+ break;
+ case DeclSpec::TSW_unspecified:
+ Result = Context.AccumTy;
+ break;
+ case DeclSpec::TSW_long:
+ Result = Context.LongAccumTy;
+ break;
+ case DeclSpec::TSW_longlong:
+ llvm_unreachable("Unable to specify long long as _Accum width");
+ }
+
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ Result = Context.getCorrespondingUnsignedType(Result);
+
+ if (DS.isTypeSpecSat())
+ Result = Context.getCorrespondingSaturatedType(Result);
+
+ break;
+ }
+ case DeclSpec::TST_fract: {
+ switch (DS.getTypeSpecWidth()) {
+ case DeclSpec::TSW_short:
+ Result = Context.ShortFractTy;
+ break;
+ case DeclSpec::TSW_unspecified:
+ Result = Context.FractTy;
+ break;
+ case DeclSpec::TSW_long:
+ Result = Context.LongFractTy;
+ break;
+ case DeclSpec::TSW_longlong:
+ llvm_unreachable("Unable to specify long long as _Fract width");
+ }
+
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ Result = Context.getCorrespondingUnsignedType(Result);
+
+ if (DS.isTypeSpecSat())
+ Result = Context.getCorrespondingSaturatedType(Result);
+
+ break;
+ }
case DeclSpec::TST_int128:
if (!S.Context.getTargetInfo().hasInt128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
@@ -1422,7 +1421,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_union:
case DeclSpec::TST_struct:
case DeclSpec::TST_interface: {
- TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
+ TagDecl *D = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl());
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
@@ -1442,7 +1441,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// In both C and C++, make an ElaboratedType.
ElaboratedTypeKeyword Keyword
= ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
- Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
+ Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result,
+ DS.isTypeSpecOwned() ? D : nullptr);
break;
}
case DeclSpec::TST_typename: {
@@ -1528,16 +1528,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
-#define GENERIC_IMAGE_TYPE(ImgType, Id) \
- case DeclSpec::TST_##ImgType##_t: \
- switch (getImageAccess(DS.getAttributes().getList())) { \
- case OpenCLAccessAttr::Keyword_write_only: \
- Result = Context.Id##WOTy; break; \
- case OpenCLAccessAttr::Keyword_read_write: \
- Result = Context.Id##RWTy; break; \
- case OpenCLAccessAttr::Keyword_read_only: \
- Result = Context.Id##ROTy; break; \
- } \
+#define GENERIC_IMAGE_TYPE(ImgType, Id) \
+ case DeclSpec::TST_##ImgType##_t: \
+ switch (getImageAccess(DS.getAttributes())) { \
+ case OpenCLAccessAttr::Keyword_write_only: \
+ Result = Context.Id##WOTy; \
+ break; \
+ case OpenCLAccessAttr::Keyword_read_write: \
+ Result = Context.Id##RWTy; \
+ break; \
+ case OpenCLAccessAttr::Keyword_read_only: \
+ Result = Context.Id##ROTy; \
+ break; \
+ } \
break;
#include "clang/Basic/OpenCLImageTypes.def"
@@ -1551,6 +1554,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
declarator.setInvalidType(true);
+ bool IsFixedPointType = DS.getTypeSpecType() == DeclSpec::TST_accum ||
+ DS.getTypeSpecType() == DeclSpec::TST_fract;
+
+ // Only fixed point types can be saturated
+ if (DS.isTypeSpecSat() && !IsFixedPointType)
+ S.Diag(DS.getTypeSpecSatLoc(), diag::err_invalid_saturation_spec)
+ << DS.getSpecifierName(DS.getTypeSpecType(),
+ Context.getPrintingPolicy());
+
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
@@ -1581,7 +1593,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// attributes are pushed around.
// pipe attributes will be handled later ( at GetFullTypeForDeclarator )
if (!DS.isTypeSpecPipe())
- processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
+ processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -1748,7 +1760,7 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
return BuildQualifiedType(T, Loc, Q, DS);
}
-/// \brief Build a paren type including \p T.
+/// Build a paren type including \p T.
QualType Sema::BuildParenType(QualType T) {
return Context.getParenType(T);
}
@@ -1858,7 +1870,7 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
return true;
}
-/// \brief Build a pointer type.
+/// Build a pointer type.
///
/// \param T The type to which we'll be building a pointer.
///
@@ -1898,7 +1910,7 @@ QualType Sema::BuildPointerType(QualType T,
return Context.getPointerType(T);
}
-/// \brief Build a reference type.
+/// Build a reference type.
///
/// \param T The type to which we'll be building a reference.
///
@@ -1960,7 +1972,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return Context.getRValueReferenceType(T);
}
-/// \brief Build a Read-only Pipe type.
+/// Build a Read-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
@@ -1972,7 +1984,7 @@ QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) {
return Context.getReadPipeType(T);
}
-/// \brief Build a Write-only Pipe type.
+/// Build a Write-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
@@ -2006,7 +2018,7 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
S.LangOpts.OpenCL).isInvalid();
}
-/// \brief Build an array type.
+/// Build an array type.
///
/// \param T The type of each element in the array.
///
@@ -2231,7 +2243,59 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return T;
}
-/// \brief Build an ext-vector type.
+QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
+ SourceLocation AttrLoc) {
+ // The base type must be integer (not Boolean or enumeration) or float, and
+ // can't already be a vector.
+ if (!CurType->isDependentType() &&
+ (!CurType->isBuiltinType() || CurType->isBooleanType() ||
+ (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
+ Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
+ return QualType();
+ }
+
+ if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
+ return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
+ VectorType::GenericVector);
+
+ llvm::APSInt VecSize(32);
+ if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_type)
+ << "vector_size" << AANT_ArgumentIntegerConstant
+ << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ if (CurType->isDependentType())
+ return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
+ VectorType::GenericVector);
+
+ unsigned VectorSize = static_cast<unsigned>(VecSize.getZExtValue() * 8);
+ unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
+
+ if (VectorSize == 0) {
+ Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ // vecSize is specified in bytes - convert to bits.
+ if (VectorSize % TypeSize) {
+ Diag(AttrLoc, diag::err_attribute_invalid_size)
+ << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) {
+ Diag(AttrLoc, diag::err_attribute_size_too_large)
+ << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ return Context.getVectorType(CurType, VectorSize / TypeSize,
+ VectorType::GenericVector);
+}
+
+/// Build an ext-vector type.
///
/// Run the required checks for the extended vector type.
QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
@@ -2402,7 +2466,7 @@ QualType Sema::BuildFunctionType(QualType T,
return Context.getFunctionType(T, ParamTypes, EPI);
}
-/// \brief Build a member pointer type \c T Class::*.
+/// Build a member pointer type \c T Class::*.
///
/// \param T the type to which the member pointer refers.
/// \param Class the class type into which the member pointer points.
@@ -2451,7 +2515,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return Context.getMemberPointerType(T, Class.getTypePtr());
}
-/// \brief Build a block pointer type.
+/// Build a block pointer type.
///
/// \param T The type to which we'll be building a block pointer.
///
@@ -2583,9 +2647,8 @@ static void inferARCWriteback(TypeProcessingState &state,
if (chunk.Kind != DeclaratorChunk::Pointer &&
chunk.Kind != DeclaratorChunk::BlockPointer)
return;
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_ObjCOwnership)
+ for (const ParsedAttr &AL : chunk.getAttrs())
+ if (AL.getKind() == ParsedAttr::AT_ObjCOwnership)
return;
transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
@@ -2750,7 +2813,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// "void" instead.
T = SemaRef.Context.VoidTy;
processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
+ D.getMutableDeclSpec().getAttributes());
break;
case UnqualifiedIdKind::IK_DeductionGuideName:
@@ -2767,7 +2830,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
break;
}
- if (D.getAttributes())
+ if (!D.getAttributes().empty())
distributeTypeAttrsFromDeclarator(state, T);
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
@@ -2788,7 +2851,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::ObjCParameterContext:
case DeclaratorContext::ObjCResultContext:
case DeclaratorContext::PrototypeContext:
- Error = 0;
+ Error = 0;
break;
case DeclaratorContext::LambdaExprParameterContext:
// In C++14, generic lambdas allow 'auto' in their parameters.
@@ -2796,7 +2859,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
Error = 16;
else {
- // If auto is mentioned in a lambda parameter context, convert it to a
+ // If auto is mentioned in a lambda parameter context, convert it to a
// template parameter type.
sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
assert(LSI && "No LambdaScopeInfo on the stack!");
@@ -2814,7 +2877,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
TemplateParameterDepth, AutoParameterPosition,
/*Identifier*/nullptr, false, IsParameterPack);
LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
- // Replace the 'auto' in the function parameter with this invented
+ // Replace the 'auto' in the function parameter with this invented
// template type parameter.
// FIXME: Retain some type sugar to indicate that this was written
// as 'auto'.
@@ -2851,6 +2914,14 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::BlockLiteralContext:
Error = 9; // Block literal
break;
+ case DeclaratorContext::TemplateArgContext:
+ // Within a template argument list, a deduced template specialization
+ // type will be reinterpreted as a template template argument.
+ if (isa<DeducedTemplateSpecializationType>(Deduced) &&
+ !D.getNumTypeObjects() &&
+ D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier)
+ break;
+ LLVM_FALLTHROUGH;
case DeclaratorContext::TemplateTypeArgContext:
Error = 10; // Template type argument
break;
@@ -2859,6 +2930,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 12; // Type alias
break;
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
break;
@@ -2945,9 +3017,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
- } else if (!HaveTrailing) {
+ } else if (!HaveTrailing &&
+ D.getContext() != DeclaratorContext::LambdaExprContext) {
// If there was a trailing return type, we already got
// warn_cxx98_compat_trailing_return_type in the parser.
+ // If this was a lambda, we already warned on that too.
SemaRef.Diag(AutoRange.getBegin(),
diag::warn_cxx98_compat_auto_type_specifier)
<< AutoRange;
@@ -2961,6 +3035,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
unsigned DiagID = 0;
switch (D.getContext()) {
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
// Class and enumeration definitions are syntactically not allowed in
// trailing return types.
llvm_unreachable("parser should not have allowed this");
@@ -2988,6 +3063,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::CXXNewContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
DiagID = diag::err_type_defined_in_type_specifier;
break;
@@ -3238,21 +3314,20 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
/// 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
/// type or normal function type.
-static CallingConv
-getCCForDeclaratorChunk(Sema &S, Declarator &D,
- const DeclaratorChunk::FunctionTypeInfo &FTI,
- unsigned ChunkIndex) {
+static CallingConv getCCForDeclaratorChunk(
+ Sema &S, Declarator &D, const ParsedAttributesView &AttrList,
+ const DeclaratorChunk::FunctionTypeInfo &FTI, unsigned ChunkIndex) {
assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
// Check for an explicit CC attribute.
- for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) {
- switch (Attr->getKind()) {
- CALLING_CONV_ATTRS_CASELIST: {
+ for (const ParsedAttr &AL : AttrList) {
+ switch (AL.getKind()) {
+ CALLING_CONV_ATTRS_CASELIST : {
// Ignore attributes that don't validate or can't apply to the
// function type. We'll diagnose the failure to apply them in
// handleFunctionTypeAttr.
CallingConv CC;
- if (!S.CheckCallingConvAttr(*Attr, CC) &&
+ if (!S.CheckCallingConvAttr(AL, CC) &&
(!FTI.isVariadic || supportsVariadicCall(CC))) {
return CC;
}
@@ -3308,9 +3383,8 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
// convention attribute. This is the simplest place to infer
// calling convention for OpenCL kernels.
if (S.getLangOpts().OpenCL) {
- for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_OpenCLKernel) {
+ for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
+ if (AL.getKind() == ParsedAttr::AT_OpenCLKernel) {
CC = CC_OpenCLKernel;
break;
}
@@ -3361,12 +3435,11 @@ IdentifierInfo *Sema::getNSErrorIdent() {
/// Check whether there is a nullability attribute of any kind in the given
/// attribute list.
-static bool hasNullabilityAttr(const AttributeList *attrs) {
- for (const AttributeList *attr = attrs; attr;
- attr = attr->getNext()) {
- if (attr->getKind() == AttributeList::AT_TypeNonNull ||
- attr->getKind() == AttributeList::AT_TypeNullable ||
- attr->getKind() == AttributeList::AT_TypeNullUnspecified)
+static bool hasNullabilityAttr(const ParsedAttributesView &attrs) {
+ for (const ParsedAttr &AL : attrs) {
+ if (AL.getKind() == ParsedAttr::AT_TypeNonNull ||
+ AL.getKind() == ParsedAttr::AT_TypeNullable ||
+ AL.getKind() == ParsedAttr::AT_TypeNullUnspecified)
return true;
}
@@ -3914,6 +3987,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::ObjCResultContext:
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
isFunctionOrMethod = true;
LLVM_FALLTHROUGH;
@@ -3967,19 +4041,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// On pointer-to-pointer parameters marked cf_returns_retained or
// cf_returns_not_retained, if the outer pointer is explicit then
// infer the inner pointer as _Nullable.
- auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
- while (NextAttr) {
- if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
- NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained)
- return true;
- NextAttr = NextAttr->getNext();
- }
- return false;
+ auto hasCFReturnsAttr =
+ [](const ParsedAttributesView &AttrList) -> bool {
+ return AttrList.hasAttribute(ParsedAttr::AT_CFReturnsRetained) ||
+ AttrList.hasAttribute(ParsedAttr::AT_CFReturnsNotRetained);
};
if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) {
if (hasCFReturnsAttr(D.getAttributes()) ||
hasCFReturnsAttr(InnermostChunk->getAttrs()) ||
- hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) {
+ hasCFReturnsAttr(D.getDeclSpec().getAttributes())) {
inferNullability = NullabilityKind::Nullable;
inferNullabilityInnerOnly = true;
}
@@ -4007,6 +4077,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::LambdaExprParameterContext:
case DeclaratorContext::ObjCCatchContext:
case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TypeNameContext:
case DeclaratorContext::FunctionalCastContext:
@@ -4034,10 +4105,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Local function that checks the nullability for a given pointer declarator.
// Returns true if _Nonnull was inferred.
- auto inferPointerNullability = [&](SimplePointerKind pointerKind,
- SourceLocation pointerLoc,
- SourceLocation pointerEndLoc,
- AttributeList *&attrs) -> AttributeList * {
+ auto inferPointerNullability =
+ [&](SimplePointerKind pointerKind, SourceLocation pointerLoc,
+ SourceLocation pointerEndLoc,
+ ParsedAttributesView &attrs) -> ParsedAttr * {
// We've seen a pointer.
if (NumPointersRemaining > 0)
--NumPointersRemaining;
@@ -4048,18 +4119,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// If we're supposed to infer nullability, do so now.
if (inferNullability && !inferNullabilityInnerOnlyComplete) {
- AttributeList::Syntax syntax
- = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
- : AttributeList::AS_Keyword;
- AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool()
- .create(
- S.getNullabilityKeyword(
- *inferNullability),
- SourceRange(pointerLoc),
- nullptr, SourceLocation(),
- nullptr, 0, syntax);
-
- spliceAttrIntoList(*nullabilityAttr, attrs);
+ ParsedAttr::Syntax syntax = inferNullabilityCS
+ ? ParsedAttr::AS_ContextSensitiveKeyword
+ : ParsedAttr::AS_Keyword;
+ ParsedAttr *nullabilityAttr =
+ state.getDeclarator().getAttributePool().create(
+ S.getNullabilityKeyword(*inferNullability),
+ SourceRange(pointerLoc), nullptr, SourceLocation(), nullptr, 0,
+ syntax);
+
+ attrs.addAtStart(nullabilityAttr);
if (inferNullabilityCS) {
state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
@@ -4114,9 +4183,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
pointerKind = SimplePointerKind::MemberPointer;
if (auto *attr = inferPointerNullability(
- pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getDeclSpec().getLocEnd(),
- D.getMutableDeclSpec().getAttributes().getListRef())) {
+ pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getDeclSpec().getLocEnd(),
+ D.getMutableDeclSpec().getAttributes())) {
T = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
attr->setUsedAsTypeAttr();
@@ -4154,7 +4223,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrs());
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
@@ -4176,7 +4245,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability
inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrs());
if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
@@ -4371,7 +4440,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
<< T << 0 /*pointer hint*/;
D.setInvalidType(true);
- }
+ }
} else if (!S.getLangOpts().HalfArgsAndReturns) {
S.Diag(D.getIdentifierLoc(),
diag::err_parameters_retval_cannot_have_fp16_type) << 1;
@@ -4450,20 +4519,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
SourceLocation AttrLoc;
if (chunkIndex + 1 < D.getNumTypeObjects()) {
DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
- for (const AttributeList *Attr = ReturnTypeChunk.getAttrs();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
- AttrLoc = Attr->getLoc();
+ for (const ParsedAttr &AL : ReturnTypeChunk.getAttrs()) {
+ if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) {
+ AttrLoc = AL.getLoc();
break;
}
}
}
if (AttrLoc.isInvalid()) {
- for (const AttributeList *Attr
- = D.getDeclSpec().getAttributes().getList();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
- AttrLoc = Attr->getLoc();
+ for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
+ if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) {
+ AttrLoc = AL.getLoc();
break;
}
}
@@ -4474,7 +4540,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// the predefined
// __strong/__weak/__autoreleasing/__unsafe_unretained.
if (AttrLoc.isMacroID())
- AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
+ AttrLoc =
+ S.SourceMgr.getImmediateExpansionRange(AttrLoc).getBegin();
S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
<< T.getQualifiers().getObjCLifetime();
@@ -4502,7 +4569,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
- FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
+ FunctionType::ExtInfo EI(
+ getCCForDeclaratorChunk(S, D, DeclType.getAttrs(), FTI, chunkIndex));
if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus
&& !LangOpts.OpenCL) {
@@ -4512,19 +4580,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable" attribute. Scan
// for this attribute now.
- if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) {
- bool Overloadable = false;
- for (const AttributeList *Attrs = D.getAttributes();
- Attrs; Attrs = Attrs->getNext()) {
- if (Attrs->getKind() == AttributeList::AT_Overloadable) {
- Overloadable = true;
- break;
- }
- }
-
- if (!Overloadable)
+ if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus)
+ if (!D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable))
S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
- }
if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
@@ -4656,7 +4714,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
}
- } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
+ } else if (isComputedNoexcept(FTI.getExceptionSpecType())) {
NoexceptExpr = FTI.NoexceptExpr;
}
@@ -4679,7 +4737,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrs());
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
@@ -4735,7 +4793,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorChunk::Pipe: {
T = S.BuildReadPipeType(T, DeclType.Loc);
processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
+ D.getMutableDeclSpec().getAttributes());
break;
}
}
@@ -4746,8 +4804,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// See if there are any attributes on this declarator chunk.
- processTypeAttrs(state, T, TAL_DeclChunk,
- const_cast<AttributeList *>(DeclType.getAttrs()));
+ processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs());
}
// GNU warning -Wstrict-prototypes
@@ -4828,6 +4885,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
!(Kind == Member &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
!IsTypedefName &&
+ D.getContext() != DeclaratorContext::TemplateArgContext &&
D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
SourceLocation Loc = D.getLocStart();
SourceRange RemovalRange;
@@ -4845,8 +4903,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
if (!RemovalLocs.empty()) {
- std::sort(RemovalLocs.begin(), RemovalLocs.end(),
- BeforeThanCompare<SourceLocation>(S.getSourceManager()));
+ llvm::sort(RemovalLocs.begin(), RemovalLocs.end(),
+ BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
}
@@ -4954,6 +5012,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
// FIXME: We may want to allow parameter packs in block-literal contexts
// in the future.
@@ -5009,10 +5069,8 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
// Look for an explicit lifetime attribute.
DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_ObjCOwnership)
- return;
+ if (chunk.getAttrs().hasAttribute(ParsedAttr::AT_ObjCOwnership))
+ return;
const char *attrStr = nullptr;
switch (ownership) {
@@ -5031,16 +5089,15 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
// If there wasn't one, add one (with an invalid source location
// so that we don't make an AttributedType for it).
- AttributeList *attr = D.getAttributePool()
- .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
- /*scope*/ nullptr, SourceLocation(),
- /*args*/ &Args, 1, AttributeList::AS_GNU);
- spliceAttrIntoList(*attr, chunk.getAttrListRef());
-
+ ParsedAttr *attr = D.getAttributePool().create(
+ &S.Context.Idents.get("objc_ownership"), SourceLocation(),
+ /*scope*/ nullptr, SourceLocation(),
+ /*args*/ &Args, 1, ParsedAttr::AS_GNU);
+ chunk.getAttrs().addAtStart(attr);
// TODO: mark whether we did this inference?
}
-/// \brief Used for transferring ownership in casts resulting in l-values.
+/// Used for transferring ownership in casts resulting in l-values.
static void transferARCOwnership(TypeProcessingState &state,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
@@ -5107,110 +5164,93 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
}
-/// Map an AttributedType::Kind to an AttributeList::Kind.
-static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
+/// Map an AttributedType::Kind to an ParsedAttr::Kind.
+static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) {
switch (kind) {
case AttributedType::attr_address_space:
- return AttributeList::AT_AddressSpace;
+ return ParsedAttr::AT_AddressSpace;
case AttributedType::attr_regparm:
- return AttributeList::AT_Regparm;
+ return ParsedAttr::AT_Regparm;
case AttributedType::attr_vector_size:
- return AttributeList::AT_VectorSize;
+ return ParsedAttr::AT_VectorSize;
case AttributedType::attr_neon_vector_type:
- return AttributeList::AT_NeonVectorType;
+ return ParsedAttr::AT_NeonVectorType;
case AttributedType::attr_neon_polyvector_type:
- return AttributeList::AT_NeonPolyVectorType;
+ return ParsedAttr::AT_NeonPolyVectorType;
case AttributedType::attr_objc_gc:
- return AttributeList::AT_ObjCGC;
+ return ParsedAttr::AT_ObjCGC;
case AttributedType::attr_objc_ownership:
case AttributedType::attr_objc_inert_unsafe_unretained:
- return AttributeList::AT_ObjCOwnership;
+ return ParsedAttr::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
- return AttributeList::AT_NoReturn;
+ return ParsedAttr::AT_NoReturn;
+ case AttributedType::attr_nocf_check:
+ return ParsedAttr::AT_AnyX86NoCfCheck;
case AttributedType::attr_cdecl:
- return AttributeList::AT_CDecl;
+ return ParsedAttr::AT_CDecl;
case AttributedType::attr_fastcall:
- return AttributeList::AT_FastCall;
+ return ParsedAttr::AT_FastCall;
case AttributedType::attr_stdcall:
- return AttributeList::AT_StdCall;
+ return ParsedAttr::AT_StdCall;
case AttributedType::attr_thiscall:
- return AttributeList::AT_ThisCall;
+ return ParsedAttr::AT_ThisCall;
case AttributedType::attr_regcall:
- return AttributeList::AT_RegCall;
+ return ParsedAttr::AT_RegCall;
case AttributedType::attr_pascal:
- return AttributeList::AT_Pascal;
+ return ParsedAttr::AT_Pascal;
case AttributedType::attr_swiftcall:
- return AttributeList::AT_SwiftCall;
+ return ParsedAttr::AT_SwiftCall;
case AttributedType::attr_vectorcall:
- return AttributeList::AT_VectorCall;
+ return ParsedAttr::AT_VectorCall;
case AttributedType::attr_pcs:
case AttributedType::attr_pcs_vfp:
- return AttributeList::AT_Pcs;
+ return ParsedAttr::AT_Pcs;
case AttributedType::attr_inteloclbicc:
- return AttributeList::AT_IntelOclBicc;
+ return ParsedAttr::AT_IntelOclBicc;
case AttributedType::attr_ms_abi:
- return AttributeList::AT_MSABI;
+ return ParsedAttr::AT_MSABI;
case AttributedType::attr_sysv_abi:
- return AttributeList::AT_SysVABI;
+ return ParsedAttr::AT_SysVABI;
case AttributedType::attr_preserve_most:
- return AttributeList::AT_PreserveMost;
+ return ParsedAttr::AT_PreserveMost;
case AttributedType::attr_preserve_all:
- return AttributeList::AT_PreserveAll;
+ return ParsedAttr::AT_PreserveAll;
case AttributedType::attr_ptr32:
- return AttributeList::AT_Ptr32;
+ return ParsedAttr::AT_Ptr32;
case AttributedType::attr_ptr64:
- return AttributeList::AT_Ptr64;
+ return ParsedAttr::AT_Ptr64;
case AttributedType::attr_sptr:
- return AttributeList::AT_SPtr;
+ return ParsedAttr::AT_SPtr;
case AttributedType::attr_uptr:
- return AttributeList::AT_UPtr;
+ return ParsedAttr::AT_UPtr;
case AttributedType::attr_nonnull:
- return AttributeList::AT_TypeNonNull;
+ return ParsedAttr::AT_TypeNonNull;
case AttributedType::attr_nullable:
- return AttributeList::AT_TypeNullable;
+ return ParsedAttr::AT_TypeNullable;
case AttributedType::attr_null_unspecified:
- return AttributeList::AT_TypeNullUnspecified;
+ return ParsedAttr::AT_TypeNullUnspecified;
case AttributedType::attr_objc_kindof:
- return AttributeList::AT_ObjCKindOf;
+ return ParsedAttr::AT_ObjCKindOf;
case AttributedType::attr_ns_returns_retained:
- return AttributeList::AT_NSReturnsRetained;
+ return ParsedAttr::AT_NSReturnsRetained;
+ case AttributedType::attr_lifetimebound:
+ return ParsedAttr::AT_LifetimeBound;
}
llvm_unreachable("unexpected attribute kind!");
}
-static void fillAttributedTypeLoc(AttributedTypeLoc TL,
- const AttributeList *attrs,
- const AttributeList *DeclAttrs = nullptr) {
- // DeclAttrs and attrs cannot be both empty.
- assert((attrs || DeclAttrs) &&
- "no type attributes in the expected location!");
-
- AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind());
- // Try to search for an attribute of matching kind in attrs list.
- while (attrs && attrs->getKind() != parsedKind)
- attrs = attrs->getNext();
- if (!attrs) {
- // No matching type attribute in attrs list found.
- // Try searching through C++11 attributes in the declarator attribute list.
- while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() ||
- DeclAttrs->getKind() != parsedKind))
- DeclAttrs = DeclAttrs->getNext();
- attrs = DeclAttrs;
- }
-
- assert(attrs && "no matching type attribute in expected location!");
-
- TL.setAttrNameLoc(attrs->getLoc());
+static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) {
+ TL.setAttrNameLoc(attr.getLoc());
if (TL.hasAttrExprOperand()) {
- assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
- TL.setAttrExprOperand(attrs->getArgAsExpr(0));
+ assert(attr.isArgExpr(0) && "mismatched attribute operand kind");
+ TL.setAttrExprOperand(attr.getArgAsExpr(0));
} else if (TL.hasAttrEnumOperand()) {
- assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) &&
+ assert((attr.isArgIdent(0) || attr.isArgExpr(0)) &&
"unexpected attribute operand kind");
- if (attrs->isArgIdent(0))
- TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
+ if (attr.isArgIdent(0))
+ TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc);
else
- TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc());
+ TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc());
}
// FIXME: preserve this information to here.
@@ -5218,6 +5258,25 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
TL.setAttrOperandParensRange(SourceRange());
}
+static void fillAttributedTypeLoc(AttributedTypeLoc TL,
+ const ParsedAttributesView &Attrs,
+ const ParsedAttributesView &DeclAttrs) {
+ // DeclAttrs and Attrs cannot be both empty.
+ assert((!Attrs.empty() || !DeclAttrs.empty()) &&
+ "no type attributes in the expected location!");
+
+ ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind());
+ // Try to search for an attribute of matching kind in Attrs list.
+ for (const ParsedAttr &AL : Attrs)
+ if (AL.getKind() == parsedKind)
+ return setAttributedTypeLoc(TL, AL);
+
+ for (const ParsedAttr &AL : DeclAttrs)
+ if (AL.isCXX11Attribute() || AL.getKind() == parsedKind)
+ return setAttributedTypeLoc(TL, AL);
+ llvm_unreachable("no matching type attribute in expected location!");
+}
+
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
ASTContext &Context;
@@ -5228,7 +5287,7 @@ namespace {
: Context(Context), DS(DS) {}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, DS.getAttributes().getList());
+ fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});
Visit(TL.getModifiedLoc());
}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
@@ -5275,7 +5334,7 @@ namespace {
TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
}
-
+
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
@@ -5400,7 +5459,7 @@ namespace {
}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, Chunk.getAttrs());
+ fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
}
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing
@@ -5533,19 +5592,23 @@ 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();
+static void
+fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
+ const ParsedAttributesView &Attrs) {
+ for (const ParsedAttr &AL : Attrs) {
+ if (AL.getKind() == ParsedAttr::AT_AddressSpace) {
+ DASTL.setAttrNameLoc(AL.getLoc());
+ DASTL.setAttrExprOperand(AL.getArgAsExpr(0));
+ DASTL.setAttrOperandParensRange(SourceRange());
+ return;
+ }
+ }
- assert(Attrs && "no address_space attribute found at the expected location!");
-
- DASTL.setAttrNameLoc(Attrs->getLoc());
- DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0));
- DASTL.setAttrOperandParensRange(SourceRange());
+ llvm_unreachable(
+ "no address_space attribute found at the expected location!");
}
-/// \brief Create and instantiate a TypeSourceInfo with type source information.
+/// Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
///
@@ -5558,7 +5621,6 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo) {
TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
- const AttributeList *DeclAttrs = D.getAttributes();
// Handle parameter packs whose type is a pack expansion.
if (isa<PackExpansionType>(T)) {
@@ -5567,11 +5629,11 @@ 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();
+ CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc();
}
// An AtomicTypeLoc might be produced by an atomic qualifier in this
@@ -5582,7 +5644,8 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
- fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs);
+ fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
+ D.getAttributes());
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -5607,7 +5670,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
return TInfo;
}
-/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
+/// Create a LocInfoType to hold the given QualType and TypeSourceInfo.
ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
// FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
// and Sema during declaration parsing. Try deallocating/caching them when
@@ -5666,21 +5729,13 @@ 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
+/// 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
+/// 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();
- }
+ if (!AddrSpace->isValueDependent()) {
llvm::APSInt addrSpace(32);
if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) {
@@ -5712,12 +5767,26 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
LangAS ASIdx =
getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue()));
+ // If this type is already address space qualified with a different
+ // address space, 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) {
+ if (T.getAddressSpace() != ASIdx) {
+ Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
+ return QualType();
+ } else
+ // Emit a warning if they are identical; it's likely unintended.
+ Diag(AttrLoc,
+ diag::warn_attribute_address_multiple_identical_qualifiers);
+ }
+
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
+ // 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>()) {
@@ -5732,16 +5801,7 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
/// 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() != LangAS::Default) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
- Attr.setInvalid();
- return;
- }
-
+ const ParsedAttr &Attr, Sema &S) {
// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
// qualified by an address-space qualifier."
if (Type->isFunctionType()) {
@@ -5751,7 +5811,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
}
LangAS ASIdx;
- if (Attr.getKind() == AttributeList::AT_AddressSpace) {
+ if (Attr.getKind() == ParsedAttr::AT_AddressSpace) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -5790,20 +5850,35 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
} else {
// The keyword-based type attributes imply which address space to use.
switch (Attr.getKind()) {
- case AttributeList::AT_OpenCLGlobalAddressSpace:
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
ASIdx = LangAS::opencl_global; break;
- case AttributeList::AT_OpenCLLocalAddressSpace:
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
ASIdx = LangAS::opencl_local; break;
- case AttributeList::AT_OpenCLConstantAddressSpace:
+ case ParsedAttr::AT_OpenCLConstantAddressSpace:
ASIdx = LangAS::opencl_constant; break;
- case AttributeList::AT_OpenCLGenericAddressSpace:
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
ASIdx = LangAS::opencl_generic; break;
- case AttributeList::AT_OpenCLPrivateAddressSpace:
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
ASIdx = LangAS::opencl_private; break;
default:
llvm_unreachable("Invalid address space");
}
+ // If this type is already address space qualified with a different
+ // address space, 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() != LangAS::Default) {
+ if (Type.getAddressSpace() != ASIdx) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+ Attr.setInvalid();
+ return;
+ } else
+ // Emit a warning if they are identical; it's likely unintended.
+ S.Diag(Attr.getLoc(),
+ diag::warn_attribute_address_multiple_identical_qualifiers);
+ }
+
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
}
@@ -5843,8 +5918,7 @@ static bool hasDirectOwnershipQualifier(QualType type) {
///
/// Returns 'true' if the attribute was handled.
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
+ ParsedAttr &attr, QualType &type) {
bool NonObjCPointer = false;
if (!type->isDependentType() && !type->isUndeducedType()) {
@@ -5873,7 +5947,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
Sema &S = state.getSema();
SourceLocation AttrLoc = attr.getLoc();
if (AttrLoc.isMacroID())
- AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
+ AttrLoc =
+ S.getSourceManager().getImmediateExpansionRange(AttrLoc).getBegin();
if (!attr.isArgIdent(0)) {
S.Diag(AttrLoc, diag::err_attribute_argument_type)
@@ -6028,8 +6103,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
/// attribute on the specified type. Returns true to indicate that
/// the attribute was handled, false to indicate that the type does
/// not permit the attribute.
-static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
+static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type) {
Sema &S = state.getSema();
@@ -6044,7 +6118,7 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state,
attr.setInvalid();
return true;
}
-
+
// Check the attribute arguments.
if (!attr.isArgIdent(0)) {
S.Diag(attr.getLoc(), diag::err_attribute_argument_type)
@@ -6221,11 +6295,10 @@ namespace {
} // end anonymous namespace
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
- AttributeList &Attr,
- QualType &Type) {
+ ParsedAttr &Attr, QualType &Type) {
Sema &S = State.getSema();
- AttributeList::Kind Kind = Attr.getKind();
+ ParsedAttr::Kind Kind = Attr.getKind();
QualType Desugared = Type;
const AttributedType *AT = dyn_cast<AttributedType>(Type);
while (AT) {
@@ -6242,21 +6315,21 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// You cannot have both __sptr and __uptr on the same type, nor can you
// have __ptr32 and __ptr64.
if ((CurAttrKind == AttributedType::attr_ptr32 &&
- Kind == AttributeList::AT_Ptr64) ||
+ Kind == ParsedAttr::AT_Ptr64) ||
(CurAttrKind == AttributedType::attr_ptr64 &&
- Kind == AttributeList::AT_Ptr32)) {
+ Kind == ParsedAttr::AT_Ptr32)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__ptr32'" << "'__ptr64'";
return true;
} else if ((CurAttrKind == AttributedType::attr_sptr &&
- Kind == AttributeList::AT_UPtr) ||
+ Kind == ParsedAttr::AT_UPtr) ||
(CurAttrKind == AttributedType::attr_uptr &&
- Kind == AttributeList::AT_SPtr)) {
+ Kind == ParsedAttr::AT_SPtr)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__sptr'" << "'__uptr'";
return true;
}
-
+
Desugared = AT->getEquivalentType();
AT = dyn_cast<AttributedType>(Desugared);
}
@@ -6276,10 +6349,18 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
AttributedType::Kind TAK;
switch (Kind) {
default: llvm_unreachable("Unknown attribute kind");
- case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break;
- case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break;
- case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break;
- case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break;
+ case ParsedAttr::AT_Ptr32:
+ TAK = AttributedType::attr_ptr32;
+ break;
+ case ParsedAttr::AT_Ptr64:
+ TAK = AttributedType::attr_ptr64;
+ break;
+ case ParsedAttr::AT_SPtr:
+ TAK = AttributedType::attr_sptr;
+ break;
+ case ParsedAttr::AT_UPtr:
+ TAK = AttributedType::attr_uptr;
+ break;
}
Type = S.Context.getAttributedType(TAK, Type, Type);
@@ -6305,7 +6386,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
<< FixItHint::CreateRemoval(nullabilityLoc);
break;
- }
+ }
// Conflicting nullability.
Diag(nullabilityLoc, diag::err_nullability_conflicting)
@@ -6351,7 +6432,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
return true;
}
-
+
// For the context-sensitive keywords/Objective-C property
// attributes, require that the type be a single-level pointer.
if (isContextSensitive) {
@@ -6393,7 +6474,7 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
// Find out if it's an Objective-C object or object pointer type;
const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
- const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
+ const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
: type->getAs<ObjCObjectType>();
// If not, we can't apply __kindof.
@@ -6422,7 +6503,7 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
}
// Build the attributed type to record where __kindof occurred.
- type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
type,
equivType);
@@ -6430,15 +6511,15 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
}
/// Map a nullability attribute kind to a nullability kind.
-static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
+static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
switch (kind) {
- case AttributeList::AT_TypeNonNull:
+ case ParsedAttr::AT_TypeNonNull:
return NullabilityKind::NonNull;
- case AttributeList::AT_TypeNullable:
+ case ParsedAttr::AT_TypeNullable:
return NullabilityKind::Nullable;
- case AttributeList::AT_TypeNullUnspecified:
+ case ParsedAttr::AT_TypeNullUnspecified:
return NullabilityKind::Unspecified;
default:
@@ -6453,15 +6534,14 @@ static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
/// \returns true if the nullability annotation was distributed, false
/// otherwise.
static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
- QualType type,
- AttributeList &attr) {
+ QualType type, ParsedAttr &attr) {
Declarator &declarator = state.getDeclarator();
/// Attempt to move the attribute to the specified chunk.
auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool {
// If there is already a nullability attribute there, don't add
// one.
- if (hasNullabilityAttr(chunk.getAttrListRef()))
+ if (hasNullabilityAttr(chunk.getAttrs()))
return false;
// Complain about the nullability qualifier being in the wrong
@@ -6494,8 +6574,8 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
" " + attr.getName()->getName().str() + " ");
}
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ chunk.getAttrs());
return true;
};
@@ -6523,7 +6603,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
}
return false;
-
+
// Don't walk through these.
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pipe:
@@ -6534,28 +6614,28 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
return false;
}
-static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
+static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
assert(!Attr.isInvalid());
switch (Attr.getKind()) {
default:
llvm_unreachable("not a calling convention attribute");
- case AttributeList::AT_CDecl:
+ case ParsedAttr::AT_CDecl:
return AttributedType::attr_cdecl;
- case AttributeList::AT_FastCall:
+ case ParsedAttr::AT_FastCall:
return AttributedType::attr_fastcall;
- case AttributeList::AT_StdCall:
+ case ParsedAttr::AT_StdCall:
return AttributedType::attr_stdcall;
- case AttributeList::AT_ThisCall:
+ case ParsedAttr::AT_ThisCall:
return AttributedType::attr_thiscall;
- case AttributeList::AT_RegCall:
+ case ParsedAttr::AT_RegCall:
return AttributedType::attr_regcall;
- case AttributeList::AT_Pascal:
+ case ParsedAttr::AT_Pascal:
return AttributedType::attr_pascal;
- case AttributeList::AT_SwiftCall:
+ case ParsedAttr::AT_SwiftCall:
return AttributedType::attr_swiftcall;
- case AttributeList::AT_VectorCall:
+ case ParsedAttr::AT_VectorCall:
return AttributedType::attr_vectorcall;
- case AttributeList::AT_Pcs: {
+ case ParsedAttr::AT_Pcs: {
// The attribute may have had a fixit applied where we treated an
// identifier as a string literal. The contents of the string are valid,
// but the form may not be.
@@ -6568,15 +6648,15 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
.Case("aapcs", AttributedType::attr_pcs)
.Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
}
- case AttributeList::AT_IntelOclBicc:
+ case ParsedAttr::AT_IntelOclBicc:
return AttributedType::attr_inteloclbicc;
- case AttributeList::AT_MSABI:
+ case ParsedAttr::AT_MSABI:
return AttributedType::attr_ms_abi;
- case AttributeList::AT_SysVABI:
+ case ParsedAttr::AT_SysVABI:
return AttributedType::attr_sysv_abi;
- case AttributeList::AT_PreserveMost:
+ case ParsedAttr::AT_PreserveMost:
return AttributedType::attr_preserve_most;
- case AttributeList::AT_PreserveAll:
+ case ParsedAttr::AT_PreserveAll:
return AttributedType::attr_preserve_all;
}
llvm_unreachable("unexpected attribute kind!");
@@ -6584,15 +6664,14 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
/// Process an individual function attribute. Returns true to
/// indicate that the attribute was handled, false if it wasn't.
-static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
+static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type) {
Sema &S = state.getSema();
FunctionTypeUnwrapper unwrapped(S, type);
- if (attr.getKind() == AttributeList::AT_NoReturn) {
- if (S.CheckNoReturnAttr(attr))
+ if (attr.getKind() == ParsedAttr::AT_NoReturn) {
+ if (S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
@@ -6607,7 +6686,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
// ns_returns_retained is not always a type attribute, but if we got
// here, we're treating it as one right now.
- if (attr.getKind() == AttributeList::AT_NSReturnsRetained) {
+ if (attr.getKind() == ParsedAttr::AT_NSReturnsRetained) {
if (attr.getNumArgs()) return true;
// Delay if this is not a function type.
@@ -6631,8 +6710,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) {
- if (S.CheckNoCallerSavedRegsAttr(attr))
+ if (attr.getKind() == ParsedAttr::AT_AnyX86NoCallerSavedRegisters) {
+ if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
@@ -6645,7 +6724,28 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- if (attr.getKind() == AttributeList::AT_Regparm) {
+ if (attr.getKind() == ParsedAttr::AT_AnyX86NoCfCheck) {
+ if (!S.getLangOpts().CFProtectionBranch) {
+ S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored);
+ attr.setInvalid();
+ return true;
+ }
+
+ if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
+ return true;
+
+ // If this is not a function type, warning will be asserted by subject
+ // check.
+ if (!unwrapped.isFunctionType())
+ return true;
+
+ FunctionType::ExtInfo EI =
+ unwrapped.get()->getExtInfo().withNoCfCheck(true);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+ }
+
+ if (attr.getKind() == ParsedAttr::AT_Regparm) {
unsigned value;
if (S.CheckRegparmAttr(attr, value))
return true;
@@ -6802,7 +6902,7 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
/// The raw attribute should contain precisely 1 argument, the vector size for
/// the variable, measured in bytes. If curType and rawAttr are well formed,
/// this routine will return a new vector type.
-static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
+static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -6811,58 +6911,35 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
Attr.setInvalid();
return;
}
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt vecSize(32);
- if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
- !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // The base type must be integer (not Boolean or enumeration) or float, and
- // can't already be a vector.
- if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
- Attr.setInvalid();
- return;
- }
- unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
- // vecSize is specified in bytes - convert to bits.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
- // the vector size needs to be an integral multiple of the type size.
- if (vectorSize % typeSize) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (vectorSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
+ Expr *SizeExpr;
+ // Special case where the argument is a template id.
+ if (Attr.isArgIdent(0)) {
+ CXXScopeSpec SS;
+ SourceLocation TemplateKWLoc;
+ UnqualifiedId Id;
+ Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
+
+ ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
+ Id, false, false);
+
+ if (Size.isInvalid())
+ return;
+ SizeExpr = Size.get();
+ } else {
+ SizeExpr = Attr.getArgAsExpr(0);
}
- // Success! Instantiate the vector type, the number of elements is > 0, and
- // not required to be a power of 2, unlike GCC.
- CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
- VectorType::GenericVector);
+ QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc());
+ if (!T.isNull())
+ CurType = T;
+ else
+ Attr.setInvalid();
}
-/// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
+/// Process the OpenCL-like ext_vector_type attribute when it occurs on
/// a type.
-static void HandleExtVectorTypeAttr(QualType &CurType,
- const AttributeList &Attr,
+static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -6951,9 +7028,8 @@ static bool isPermittedNeonBaseType(QualType &Ty,
/// the argument to these Neon attributes is the number of vector elements,
/// not the vector size in bytes. The vector width and element type must
/// match one of the standard Neon vector types.
-static void HandleNeonVectorTypeAttr(QualType& CurType,
- const AttributeList &Attr, Sema &S,
- VectorType::VectorKind VecKind) {
+static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
+ Sema &S, VectorType::VectorKind VecKind) {
// Target must have NEON
if (!S.Context.getTargetInfo().hasFeature("neon")) {
S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName();
@@ -6999,7 +7075,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType,
}
/// Handle OpenCL Access Qualifier Attribute.
-static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
+static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
if (!(CurType->isImageType() || CurType->isPipeType())) {
@@ -7039,12 +7115,12 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
// Handle the cases where address space should not be deduced.
//
- // The pointee type of a pointer type is alwasy deduced since a pointer always
+ // The pointee type of a pointer type is always 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
+ // defining 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.
//
@@ -7089,8 +7165,9 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
// 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;
+ if (State.getSema().getLangOpts().OpenCLVersion <= 120 &&
+ !State.getSema().getLangOpts().OpenCLCPlusPlus) {
+ ImpAddr = LangAS::opencl_private;
} else {
// If address space is not set, OpenCL 2.0 defines non private default
// address spaces for some cases:
@@ -7119,17 +7196,31 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
}
+static void HandleLifetimeBoundAttr(QualType &CurType,
+ const ParsedAttr &Attr,
+ Sema &S, Declarator &D) {
+ if (D.isDeclarationOfFunction()) {
+ CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound,
+ CurType, CurType);
+ } else {
+ Attr.diagnoseAppertainsTo(S, nullptr);
+ }
+}
+
+
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
- TypeAttrLocation TAL, AttributeList *attrs) {
+ TypeAttrLocation TAL,
+ ParsedAttributesView &attrs) {
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
- while (attrs) {
- AttributeList &attr = *attrs;
- attrs = attr.getNext(); // reset to the next here due to early loop continue
- // stmts
+ // This loop modifies the list pretty frequently, but we still need to make
+ // sure we visit every element once. Copy the attributes list, and iterate
+ // over that.
+ ParsedAttributesView AttrsCopy{attrs};
+ for (ParsedAttr &attr : AttrsCopy) {
// Skip attributes that were marked to be invalid.
if (attr.isInvalid())
@@ -7137,14 +7228,19 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
if (attr.isCXX11Attribute()) {
// [[gnu::...]] attributes are treated as declaration attributes, so may
- // not appertain to a DeclaratorChunk, even if we handle them as type
- // attributes.
+ // not appertain to a DeclaratorChunk. If we handle them as type
+ // attributes, accept them in that position and diagnose the GCC
+ // incompatibility.
if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
+ bool IsTypeAttr = attr.isTypeAttr();
if (TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(),
- diag::warn_cxx11_gnu_attribute_on_type)
+ IsTypeAttr
+ ? diag::warn_gcc_ignores_type_attr
+ : diag::warn_cxx11_gnu_attribute_on_type)
<< attr.getName();
- continue;
+ if (!IsTypeAttr)
+ continue;
}
} else if (TAL != TAL_DeclChunk) {
// Otherwise, only consider type processing for a C++11 attribute if
@@ -7165,27 +7261,27 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
break;
- case AttributeList::UnknownAttribute:
+ case ParsedAttr::UnknownAttribute:
if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
state.getSema().Diag(attr.getLoc(),
diag::warn_unknown_attribute_ignored)
<< attr.getName();
break;
- case AttributeList::IgnoredAttribute:
+ case ParsedAttr::IgnoredAttribute:
break;
- case AttributeList::AT_MayAlias:
+ case ParsedAttr::AT_MayAlias:
// FIXME: This attribute needs to actually be handled, but if we ignore
// it it breaks large amounts of Linux software.
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_OpenCLPrivateAddressSpace:
- case AttributeList::AT_OpenCLGlobalAddressSpace:
- case AttributeList::AT_OpenCLLocalAddressSpace:
- case AttributeList::AT_OpenCLConstantAddressSpace:
- case AttributeList::AT_OpenCLGenericAddressSpace:
- case AttributeList::AT_AddressSpace:
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
+ case ParsedAttr::AT_OpenCLConstantAddressSpace:
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
+ case ParsedAttr::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
@@ -7194,28 +7290,35 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeObjCPointerTypeAttr(state, attr, type);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_VectorSize:
+ case ParsedAttr::AT_VectorSize:
HandleVectorSizeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_ExtVectorType:
+ case ParsedAttr::AT_ExtVectorType:
HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_NeonVectorType:
+ case ParsedAttr::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_NeonPolyVectorType:
+ case ParsedAttr::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_OpenCLAccess:
+ case ParsedAttr::AT_OpenCLAccess:
HandleOpenCLAccessAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
+ case ParsedAttr::AT_LifetimeBound:
+ if (TAL == TAL_DeclChunk) {
+ HandleLifetimeBoundAttr(type, attr, state.getSema(),
+ state.getDeclarator());
+ attr.setUsedAsTypeAttr();
+ }
+ break;
MS_TYPE_ATTRS_CASELIST:
if (!handleMSPointerTypeQualifierAttr(state, attr, type))
@@ -7251,7 +7354,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
break;
- case AttributeList::AT_ObjCKindOf:
+ case ParsedAttr::AT_ObjCKindOf:
// '__kindof' must be part of the decl-specifiers.
switch (TAL) {
case TAL_DeclSpec:
@@ -7337,7 +7440,7 @@ void Sema::completeExprArrayBound(Expr *E) {
}
}
-/// \brief Ensure that the type of the given expression is complete.
+/// Ensure that the type of the given expression is complete.
///
/// This routine checks whether the expression \p E has a complete type. If the
/// expression refers to an instantiable construct, that instantiation is
@@ -7374,7 +7477,7 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
return RequireCompleteExprType(E, Diagnoser);
}
-/// @brief Ensure that the type T is a complete type.
+/// Ensure that the type T is a complete type.
///
/// This routine checks whether the type @p T is complete in any
/// context where a complete type is required. If @p T is a complete
@@ -7413,12 +7516,13 @@ bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
// and isolate from other C++ specific checks.
StructuralEquivalenceContext Ctx(
D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls,
+ StructuralEquivalenceKind::Default,
false /*StrictTypeSpelling*/, true /*Complain*/,
true /*ErrorOnTagTypeMismatch*/);
- return Ctx.IsStructurallyEquivalent(D, Suggested);
+ return Ctx.IsEquivalent(D, Suggested);
}
-/// \brief Determine whether there is any declaration of \p D that was ever a
+/// Determine whether there is any declaration of \p D that was ever a
/// definition (perhaps before module merging) and is currently visible.
/// \param D The definition of the entity.
/// \param Suggested Filled in with the declaration that should be made visible
@@ -7488,7 +7592,7 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
/// Locks in the inheritance model for the given class and all of its bases.
static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
- RD = RD->getMostRecentDecl();
+ RD = RD->getMostRecentNonInjectedDecl();
if (!RD->hasAttr<MSInheritanceAttr>()) {
MSInheritanceAttr::Spelling IM;
@@ -7518,7 +7622,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
}
}
-/// \brief The implementation of RequireCompleteType
+/// The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser *Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
@@ -7529,11 +7633,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
- // We lock in the inheritance model once somebody has asked us to ensure
- // that a pointer-to-member type is complete.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (!MPTy->getClass()->isDependentType()) {
+ if (getLangOpts().CompleteMemberPointers &&
+ !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
+ RequireCompleteType(Loc, QualType(MPTy->getClass(), 0),
+ diag::err_memptr_incomplete))
+ return true;
+
+ // We lock in the inheritance model once somebody has asked us to ensure
+ // that a pointer-to-member type is complete.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
(void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
@@ -7557,10 +7667,18 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If the user is going to see an error here, recover by making the
// definition visible.
bool TreatAsComplete = Diagnoser && !isSFINAEContext();
- if (Diagnoser)
+ if (Diagnoser && SuggestedDef)
diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
/*Recover*/TreatAsComplete);
return !TreatAsComplete;
+ } else if (Def && !TemplateInstCallbacks.empty()) {
+ CodeSynthesisContext TempInst;
+ TempInst.Kind = CodeSynthesisContext::Memoization;
+ TempInst.Template = Def;
+ TempInst.Entity = Def;
+ TempInst.PointOfInstantiation = Loc;
+ atTemplateBegin(TemplateInstCallbacks, *this, TempInst);
+ atTemplateEnd(TemplateInstCallbacks, *this, TempInst);
}
return false;
@@ -7689,7 +7807,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return RequireCompleteType(Loc, T, Diagnoser);
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// literal type diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -7703,7 +7821,7 @@ static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) {
}
}
-/// @brief Ensure that the type T is a literal type.
+/// Ensure that the type T is a literal type.
///
/// This routine checks whether the type @p T is a literal type. If @p T is an
/// incomplete type, an attempt is made to complete it. If @p T is a literal
@@ -7747,6 +7865,13 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
return true;
+ // [expr.prim.lambda]p3:
+ // This class type is [not] a literal type.
+ if (RD->isLambda() && !getLangOpts().CPlusPlus17) {
+ Diag(RD->getLocation(), diag::note_non_literal_lambda);
+ return true;
+ }
+
// If the class has virtual base classes, then it's not an aggregate, and
// cannot have any constexpr constructors or a trivial default constructor,
// so is non-literal. This is better to diagnose than the resulting absence
@@ -7790,7 +7915,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
diag::note_non_literal_user_provided_dtor :
diag::note_non_literal_nontrivial_dtor) << RD;
if (!Dtor->isUserProvided())
- SpecialMemberIsTrivial(Dtor, CXXDestructor, /*Diagnose*/true);
+ SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI,
+ /*Diagnose*/true);
}
return true;
@@ -7801,10 +7927,12 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
return RequireLiteralType(Loc, T, Diagnoser);
}
-/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
-/// and qualified by the nested-name-specifier contained in SS.
+/// Retrieve a version of the type 'T' that is elaborated by Keyword, qualified
+/// by the nested-name-specifier contained in SS, and that is (re)declared by
+/// OwnedTagDecl, which is nullptr if this is not a (re)declaration.
QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T) {
+ const CXXScopeSpec &SS, QualType T,
+ TagDecl *OwnedTagDecl) {
if (T.isNull())
return T;
NestedNameSpecifier *NNS;
@@ -7815,7 +7943,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
return T;
NNS = nullptr;
}
- return Context.getElaboratedType(Keyword, NNS, T);
+ return Context.getElaboratedType(Keyword, NNS, T, OwnedTagDecl);
}
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
@@ -7851,11 +7979,12 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
//
// We apply the same rules for Objective-C ivar and property references.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
- return VD->getType();
+ const ValueDecl *VD = DRE->getDecl();
+ return VD->getType();
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- return FD->getType();
+ if (const ValueDecl *VD = ME->getMemberDecl())
+ if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
+ return VD->getType();
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
return IR->getDecl()->getType();
} else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
@@ -7864,7 +7993,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
} else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
return PE->getType();
}
-
+
// C++11 [expr.lambda.prim]p18:
// Every occurrence of decltype((x)) where x is a possibly
// parenthesized id-expression that names an entity of automatic
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 96969ea87a13..de962d775d73 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -41,7 +41,7 @@
namespace clang {
using namespace sema;
-/// \brief A semantic tree transformation that allows one to transform one
+/// A semantic tree transformation that allows one to transform one
/// abstract syntax tree into another.
///
/// A new tree transformation is defined by creating a new subclass \c X of
@@ -57,7 +57,7 @@ using namespace sema;
/// subclasses to customize any of its operations. Thus, a subclass can
/// override any of the transformation or rebuild operators by providing an
/// operation with the same signature as the default implementation. The
-/// overridding function should not be virtual.
+/// overriding function should not be virtual.
///
/// Semantic tree transformations are split into two stages, either of which
/// can be replaced by a subclass. The "transform" step transforms an AST node
@@ -94,7 +94,7 @@ using namespace sema;
/// (\c getBaseLocation(), \c getBaseEntity()).
template<typename Derived>
class TreeTransform {
- /// \brief Private RAII object that helps us forget and then re-remember
+ /// Private RAII object that helps us forget and then re-remember
/// the template argument corresponding to a partially-substituted parameter
/// pack.
class ForgetPartiallySubstitutedPackRAII {
@@ -114,19 +114,19 @@ class TreeTransform {
protected:
Sema &SemaRef;
- /// \brief The set of local declarations that have been transformed, for
+ /// The set of local declarations that have been transformed, for
/// cases where we are forced to build new declarations within the transformer
/// rather than in the subclass (e.g., lambda closure types).
llvm::DenseMap<Decl *, Decl *> TransformedLocalDecls;
public:
- /// \brief Initializes a new tree transformer.
+ /// Initializes a new tree transformer.
TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
- /// \brief Retrieves a reference to the derived class.
+ /// Retrieves a reference to the derived class.
Derived &getDerived() { return static_cast<Derived&>(*this); }
- /// \brief Retrieves a reference to the derived class.
+ /// Retrieves a reference to the derived class.
const Derived &getDerived() const {
return static_cast<const Derived&>(*this);
}
@@ -134,11 +134,11 @@ public:
static inline ExprResult Owned(Expr *E) { return E; }
static inline StmtResult Owned(Stmt *S) { return S; }
- /// \brief Retrieves a reference to the semantic analysis object used for
+ /// Retrieves a reference to the semantic analysis object used for
/// this tree transform.
Sema &getSema() const { return SemaRef; }
- /// \brief Whether the transformation should always rebuild AST nodes, even
+ /// Whether the transformation should always rebuild AST nodes, even
/// if none of the children have changed.
///
/// Subclasses may override this function to specify when the transformation
@@ -149,7 +149,7 @@ public:
/// statement node appears at most once in its containing declaration.
bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; }
- /// \brief Returns the location of the entity being transformed, if that
+ /// Returns the location of the entity being transformed, if that
/// information was not available elsewhere in the AST.
///
/// By default, returns no source-location information. Subclasses can
@@ -157,21 +157,21 @@ public:
/// information.
SourceLocation getBaseLocation() { return SourceLocation(); }
- /// \brief Returns the name of the entity being transformed, if that
+ /// Returns the name of the entity being transformed, if that
/// information was not available elsewhere in the AST.
///
/// By default, returns an empty name. Subclasses can provide an alternative
/// implementation with a more precise name.
DeclarationName getBaseEntity() { return DeclarationName(); }
- /// \brief Sets the "base" location and entity when that
+ /// Sets the "base" location and entity when that
/// information is known based on another transformation.
///
/// By default, the source location and entity are ignored. Subclasses can
/// override this function to provide a customized implementation.
void setBase(SourceLocation Loc, DeclarationName Entity) { }
- /// \brief RAII object that temporarily sets the base location and entity
+ /// RAII object that temporarily sets the base location and entity
/// used for reporting diagnostics in types.
class TemporaryBase {
TreeTransform &Self;
@@ -193,7 +193,7 @@ public:
}
};
- /// \brief Determine whether the given type \p T has already been
+ /// Determine whether the given type \p T has already been
/// transformed.
///
/// Subclasses can provide an alternative implementation of this routine
@@ -204,7 +204,7 @@ public:
return T.isNull();
}
- /// \brief Determine whether the given call argument should be dropped, e.g.,
+ /// Determine whether the given call argument should be dropped, e.g.,
/// because it is a default argument.
///
/// Subclasses can provide an alternative implementation of this routine to
@@ -214,7 +214,7 @@ public:
return E->isDefaultArgument();
}
- /// \brief Determine whether we should expand a pack expansion with the
+ /// Determine whether we should expand a pack expansion with the
/// given set of parameter packs into separate arguments by repeatedly
/// transforming the pattern.
///
@@ -261,7 +261,7 @@ public:
return false;
}
- /// \brief "Forget" about the partially-substituted pack template argument,
+ /// "Forget" about the partially-substituted pack template argument,
/// when performing an instantiation that must preserve the parameter pack
/// use.
///
@@ -270,18 +270,18 @@ public:
return TemplateArgument();
}
- /// \brief "Remember" the partially-substituted pack template argument
+ /// "Remember" the partially-substituted pack template argument
/// after performing an instantiation that must preserve the parameter pack
/// use.
///
/// This routine is meant to be overridden by the template instantiator.
void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
- /// \brief Note to the derived class when a function parameter pack is
+ /// Note to the derived class when a function parameter pack is
/// being expanded.
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
- /// \brief Transforms the given type into another type.
+ /// Transforms the given type into another type.
///
/// By default, this routine transforms a type by creating a
/// TypeSourceInfo for it and delegating to the appropriate
@@ -292,7 +292,7 @@ public:
/// \returns the transformed type.
QualType TransformType(QualType T);
- /// \brief Transforms the given type-with-location into a new
+ /// Transforms the given type-with-location into a new
/// type-with-location.
///
/// By default, this routine transforms a type by delegating to the
@@ -302,13 +302,13 @@ public:
/// to alter the transformation.
TypeSourceInfo *TransformType(TypeSourceInfo *DI);
- /// \brief Transform the given type-with-location into a new
+ /// Transform the given type-with-location into a new
/// type, collecting location information in the given builder
/// as necessary.
///
QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
- /// \brief Transform a type that is permitted to produce a
+ /// Transform a type that is permitted to produce a
/// DeducedTemplateSpecializationType.
///
/// This is used in the (relatively rare) contexts where it is acceptable
@@ -319,7 +319,7 @@ public:
TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI);
/// @}
- /// \brief Transform the given statement.
+ /// Transform the given statement.
///
/// By default, this routine transforms a statement by delegating to the
/// appropriate TransformXXXStmt function to transform a specific kind of
@@ -330,7 +330,7 @@ public:
/// \returns the transformed statement.
StmtResult TransformStmt(Stmt *S);
- /// \brief Transform the given statement.
+ /// Transform the given statement.
///
/// By default, this routine transforms a statement by delegating to the
/// appropriate TransformOMPXXXClause function to transform a specific kind
@@ -340,7 +340,7 @@ public:
/// \returns the transformed OpenMP clause.
OMPClause *TransformOMPClause(OMPClause *S);
- /// \brief Transform the given attribute.
+ /// Transform the given attribute.
///
/// By default, this routine transforms a statement by delegating to the
/// appropriate TransformXXXAttr function to transform a specific kind
@@ -350,7 +350,7 @@ public:
/// \returns the transformed attribute
const Attr *TransformAttr(const Attr *S);
-/// \brief Transform the specified attribute.
+/// Transform the specified attribute.
///
/// Subclasses should override the transformation of attributes with a pragma
/// spelling to transform expressions stored within the attribute.
@@ -361,7 +361,7 @@ public:
const X##Attr *Transform##X##Attr(const X##Attr *R) { return R; }
#include "clang/Basic/AttrList.inc"
- /// \brief Transform the given expression.
+ /// Transform the given expression.
///
/// By default, this routine transforms an expression by delegating to the
/// appropriate TransformXXXExpr function to build a new expression.
@@ -371,7 +371,7 @@ public:
/// \returns the transformed expression.
ExprResult TransformExpr(Expr *E);
- /// \brief Transform the given initializer.
+ /// Transform the given initializer.
///
/// By default, this routine transforms an initializer by stripping off the
/// semantic nodes added by initialization, then passing the result to
@@ -380,7 +380,7 @@ public:
/// \returns the transformed initializer.
ExprResult TransformInitializer(Expr *Init, bool NotCopyInit);
- /// \brief Transform the given list of expressions.
+ /// Transform the given list of expressions.
///
/// This routine transforms a list of expressions by invoking
/// \c TransformExpr() for each subexpression. However, it also provides
@@ -407,7 +407,7 @@ public:
SmallVectorImpl<Expr *> &Outputs,
bool *ArgChanged = nullptr);
- /// \brief Transform the given declaration, which is referenced from a type
+ /// Transform the given declaration, which is referenced from a type
/// or expression.
///
/// By default, acts as the identity function on declarations, unless the
@@ -422,7 +422,7 @@ public:
return D;
}
- /// \brief Transform the specified condition.
+ /// Transform the specified condition.
///
/// By default, this transforms the variable and expression and rebuilds
/// the condition.
@@ -430,14 +430,14 @@ public:
Expr *Expr,
Sema::ConditionKind Kind);
- /// \brief Transform the attributes associated with the given declaration and
+ /// Transform the attributes associated with the given declaration and
/// place them on the new declaration.
///
/// By default, this operation does nothing. Subclasses may override this
/// behavior to transform attributes.
void transformAttrs(Decl *Old, Decl *New) { }
- /// \brief Note that a local declaration has been transformed by this
+ /// Note that a local declaration has been transformed by this
/// transformer.
///
/// Local declarations are typically transformed via a call to
@@ -448,7 +448,7 @@ public:
TransformedLocalDecls[Old] = New;
}
- /// \brief Transform the definition of the given declaration.
+ /// Transform the definition of the given declaration.
///
/// By default, invokes TransformDecl() to transform the declaration.
/// Subclasses may override this function to provide alternate behavior.
@@ -456,7 +456,7 @@ public:
return getDerived().TransformDecl(Loc, D);
}
- /// \brief Transform the given declaration, which was the first part of a
+ /// Transform the given declaration, which was the first part of a
/// nested-name-specifier in a member access expression.
///
/// This specific declaration transformation only applies to the first
@@ -473,7 +473,7 @@ public:
bool TransformOverloadExprDecls(OverloadExpr *Old, bool RequiresADL,
LookupResult &R);
- /// \brief Transform the given nested-name-specifier with source-location
+ /// Transform the given nested-name-specifier with source-location
/// information.
///
/// By default, transforms all of the types and declarations within the
@@ -484,7 +484,7 @@ public:
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = nullptr);
- /// \brief Transform the given declaration name.
+ /// Transform the given declaration name.
///
/// By default, transforms the types of conversion function, constructor,
/// and destructor names and then (if needed) rebuilds the declaration name.
@@ -493,7 +493,7 @@ public:
DeclarationNameInfo
TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo);
- /// \brief Transform the given template name.
+ /// Transform the given template name.
///
/// \param SS The nested-name-specifier that qualifies the template
/// name. This nested-name-specifier must already have been transformed.
@@ -520,7 +520,7 @@ public:
NamedDecl *FirstQualifierInScope = nullptr,
bool AllowInjectedClassName = false);
- /// \brief Transform the given template argument.
+ /// Transform the given template argument.
///
/// By default, this operation transforms the type, expression, or
/// declaration stored within the template argument and constructs a
@@ -532,7 +532,7 @@ public:
TemplateArgumentLoc &Output,
bool Uneval = false);
- /// \brief Transform the given set of template arguments.
+ /// Transform the given set of template arguments.
///
/// By default, this operation transforms all of the template arguments
/// in the input set using \c TransformTemplateArgument(), and appends
@@ -558,7 +558,7 @@ public:
Uneval);
}
- /// \brief Transform the given set of template arguments.
+ /// Transform the given set of template arguments.
///
/// By default, this operation transforms all of the template arguments
/// in the input set using \c TransformTemplateArgument(), and appends
@@ -578,11 +578,11 @@ public:
TemplateArgumentListInfo &Outputs,
bool Uneval = false);
- /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+ /// Fakes up a TemplateArgumentLoc for a given TemplateArgument.
void InventTemplateArgumentLoc(const TemplateArgument &Arg,
TemplateArgumentLoc &ArgLoc);
- /// \brief Fakes up a TypeSourceInfo for a type.
+ /// Fakes up a TypeSourceInfo for a type.
TypeSourceInfo *InventTypeSourceInfo(QualType T) {
return SemaRef.Context.getTrivialTypeSourceInfo(T,
getDerived().getBaseLocation());
@@ -622,7 +622,7 @@ public:
TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
NestedNameSpecifierLoc QualifierLoc);
- /// \brief Transforms the parameters of a function type into the
+ /// Transforms the parameters of a function type into the
/// given vectors.
///
/// The result vectors should be kept in sync; null entries in the
@@ -636,7 +636,7 @@ public:
SmallVectorImpl<QualType> &PTypes, SmallVectorImpl<ParmVarDecl *> *PVars,
Sema::ExtParameterInfoBuilder &PInfos);
- /// \brief Transforms a single function-type parameter. Return null
+ /// Transforms a single function-type parameter. Return null
/// on error.
///
/// \param indexAdjustment - A number to add to the parameter's
@@ -684,7 +684,7 @@ public:
OMPClause *Transform ## Class(Class *S);
#include "clang/Basic/OpenMPKinds.def"
- /// \brief Build a new qualified type given its unqualified type and type
+ /// Build a new qualified type given its unqualified type and type
/// qualifiers.
///
/// By default, this routine adds type qualifiers only to types that can
@@ -694,19 +694,19 @@ public:
QualType RebuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Quals);
- /// \brief Build a new pointer type given its pointee type.
+ /// Build a new pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the pointer type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
- /// \brief Build a new block pointer type given its pointee type.
+ /// Build a new block pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the block pointer
/// type. Subclasses may override this routine to provide different behavior.
QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
- /// \brief Build a new reference type given the type it references.
+ /// Build a new reference type given the type it references.
///
/// By default, performs semantic analysis when building the
/// reference type. Subclasses may override this routine to provide
@@ -718,7 +718,7 @@ public:
bool LValue,
SourceLocation Sigil);
- /// \brief Build a new member pointer type given the pointee type and the
+ /// Build a new member pointer type given the pointee type and the
/// class type it refers into.
///
/// By default, performs semantic analysis when building the member pointer
@@ -732,7 +732,7 @@ public:
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc);
- /// \brief Build an Objective-C object type.
+ /// Build an Objective-C object type.
///
/// By default, performs semantic analysis when building the object type.
/// Subclasses may override this routine to provide different behavior.
@@ -746,14 +746,14 @@ public:
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc);
- /// \brief Build a new Objective-C object pointer type given the pointee type.
+ /// Build a new Objective-C object pointer type given the pointee type.
///
/// By default, directly builds the pointer type, with no additional semantic
/// analysis.
QualType RebuildObjCObjectPointerType(QualType PointeeType,
SourceLocation Star);
- /// \brief Build a new array type given the element type, size
+ /// Build a new array type given the element type, size
/// modifier, size of the array (if known), size expression, and index type
/// qualifiers.
///
@@ -767,7 +767,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new constant array type given the element type, size
+ /// Build a new constant array type given the element type, size
/// modifier, (known) size of the array, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -778,7 +778,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new incomplete array type given the element type, size
+ /// Build a new incomplete array type given the element type, size
/// modifier, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -788,7 +788,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new variable-length array type given the element type,
+ /// Build a new variable-length array type given the element type,
/// size modifier, size expression, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -799,7 +799,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new dependent-sized array type given the element type,
+ /// Build a new dependent-sized array type given the element type,
/// size modifier, size expression, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -810,7 +810,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new vector type given the element type and
+ /// Build a new vector type given the element type and
/// number of elements.
///
/// By default, performs semantic analysis when building the vector type.
@@ -818,7 +818,16 @@ public:
QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
VectorType::VectorKind VecKind);
- /// \brief Build a new extended vector type given the element type and
+ /// Build a new potentially dependently-sized extended vector type
+ /// given the element type and number of elements.
+ ///
+ /// By default, performs semantic analysis when building the vector type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr,
+ SourceLocation AttributeLoc,
+ VectorType::VectorKind);
+
+ /// Build a new extended vector type given the element type and
/// number of elements.
///
/// By default, performs semantic analysis when building the vector type.
@@ -826,7 +835,7 @@ public:
QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
SourceLocation AttributeLoc);
- /// \brief Build a new potentially dependently-sized extended vector type
+ /// Build a new potentially dependently-sized extended vector type
/// given the element type and number of elements.
///
/// By default, performs semantic analysis when building the vector type.
@@ -835,7 +844,7 @@ public:
Expr *SizeExpr,
SourceLocation AttributeLoc);
- /// \brief Build a new DependentAddressSpaceType or return the pointee
+ /// 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.
@@ -847,7 +856,7 @@ public:
Expr *AddrSpaceExpr,
SourceLocation AttributeLoc);
- /// \brief Build a new function type.
+ /// Build a new function type.
///
/// By default, performs semantic analysis when building the function type.
/// Subclasses may override this routine to provide different behavior.
@@ -855,51 +864,51 @@ public:
MutableArrayRef<QualType> ParamTypes,
const FunctionProtoType::ExtProtoInfo &EPI);
- /// \brief Build a new unprototyped function type.
+ /// Build a new unprototyped function type.
QualType RebuildFunctionNoProtoType(QualType ResultType);
- /// \brief Rebuild an unresolved typename type, given the decl that
+ /// Rebuild an unresolved typename type, given the decl that
/// the UnresolvedUsingTypenameDecl was transformed to.
QualType RebuildUnresolvedUsingType(SourceLocation NameLoc, Decl *D);
- /// \brief Build a new typedef type.
+ /// Build a new typedef type.
QualType RebuildTypedefType(TypedefNameDecl *Typedef) {
return SemaRef.Context.getTypeDeclType(Typedef);
}
- /// \brief Build a new class/struct/union type.
+ /// Build a new class/struct/union type.
QualType RebuildRecordType(RecordDecl *Record) {
return SemaRef.Context.getTypeDeclType(Record);
}
- /// \brief Build a new Enum type.
+ /// Build a new Enum type.
QualType RebuildEnumType(EnumDecl *Enum) {
return SemaRef.Context.getTypeDeclType(Enum);
}
- /// \brief Build a new typeof(expr) type.
+ /// Build a new typeof(expr) type.
///
/// By default, performs semantic analysis when building the typeof type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc);
- /// \brief Build a new typeof(type) type.
+ /// Build a new typeof(type) type.
///
/// By default, builds a new TypeOfType with the given underlying type.
QualType RebuildTypeOfType(QualType Underlying);
- /// \brief Build a new unary transform type.
+ /// Build a new unary transform type.
QualType RebuildUnaryTransformType(QualType BaseType,
UnaryTransformType::UTTKind UKind,
SourceLocation Loc);
- /// \brief Build a new C++11 decltype type.
+ /// Build a new C++11 decltype type.
///
/// By default, performs semantic analysis when building the decltype type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc);
- /// \brief Build a new C++11 auto type.
+ /// Build a new C++11 auto type.
///
/// By default, builds a new AutoType with the given deduced type.
QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword) {
@@ -918,7 +927,7 @@ public:
Template, Deduced, /*IsDependent*/ false);
}
- /// \brief Build a new template specialization type.
+ /// Build a new template specialization type.
///
/// By default, performs semantic analysis when building the template
/// specialization type. Subclasses may override this routine to provide
@@ -927,7 +936,7 @@ public:
SourceLocation TemplateLoc,
TemplateArgumentListInfo &Args);
- /// \brief Build a new parenthesized type.
+ /// Build a new parenthesized type.
///
/// By default, builds a new ParenType type from the inner type.
/// Subclasses may override this routine to provide different behavior.
@@ -935,7 +944,7 @@ public:
return SemaRef.BuildParenType(InnerType);
}
- /// \brief Build a new qualified name type.
+ /// Build a new qualified name type.
///
/// By default, builds a new ElaboratedType type from the keyword,
/// the nested-name-specifier and the named type.
@@ -949,7 +958,7 @@ public:
Named);
}
- /// \brief Build a new typename type that refers to a template-id.
+ /// Build a new typename type that refers to a template-id.
///
/// By default, builds a new DependentNameType type from the
/// nested-name-specifier and the given type. Subclasses may override
@@ -957,6 +966,7 @@ public:
QualType RebuildDependentTemplateSpecializationType(
ElaboratedTypeKeyword Keyword,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
const IdentifierInfo *Name,
SourceLocation NameLoc,
TemplateArgumentListInfo &Args,
@@ -965,9 +975,9 @@ public:
// TODO: avoid TemplateName abstraction
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- TemplateName InstName
- = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(),
- nullptr, AllowInjectedClassName);
+ TemplateName InstName = getDerived().RebuildTemplateName(
+ SS, TemplateKWLoc, *Name, NameLoc, QualType(), nullptr,
+ AllowInjectedClassName);
if (InstName.isNull())
return QualType();
@@ -993,7 +1003,7 @@ public:
T);
}
- /// \brief Build a new typename type that refers to an identifier.
+ /// Build a new typename type that refers to an identifier.
///
/// By default, performs semantic analysis when building the typename type
/// (or elaborated type). Subclasses may override this routine to provide
@@ -1106,7 +1116,7 @@ public:
T);
}
- /// \brief Build a new pack expansion type.
+ /// Build a new pack expansion type.
///
/// By default, builds a new PackExpansionType type from the given pattern.
/// Subclasses may override this routine to provide different behavior.
@@ -1118,17 +1128,17 @@ public:
NumExpansions);
}
- /// \brief Build a new atomic type given its value type.
+ /// Build a new atomic type given its value type.
///
/// By default, performs semantic analysis when building the atomic type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
- /// \brief Build a new pipe type given its value type.
+ /// Build a new pipe type given its value type.
QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc,
bool isReadPipe);
- /// \brief Build a new template name given a nested name specifier, a flag
+ /// Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
/// that the template name refers to.
///
@@ -1138,7 +1148,7 @@ public:
bool TemplateKW,
TemplateDecl *Template);
- /// \brief Build a new template name given a nested name specifier and the
+ /// Build a new template name given a nested name specifier and the
/// name that is referred to as a template.
///
/// By default, performs semantic analysis to determine whether the name can
@@ -1146,13 +1156,13 @@ public:
/// template name. Subclasses may override this routine to provide different
/// behavior.
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
- SourceLocation NameLoc,
- QualType ObjectType,
+ SourceLocation NameLoc, QualType ObjectType,
NamedDecl *FirstQualifierInScope,
bool AllowInjectedClassName);
- /// \brief Build a new template name given a nested name specifier and the
+ /// Build a new template name given a nested name specifier and the
/// overloaded operator name that is referred to as a template.
///
/// By default, performs semantic analysis to determine whether the name can
@@ -1160,12 +1170,12 @@ public:
/// template name. Subclasses may override this routine to provide different
/// behavior.
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
OverloadedOperatorKind Operator,
- SourceLocation NameLoc,
- QualType ObjectType,
+ SourceLocation NameLoc, QualType ObjectType,
bool AllowInjectedClassName);
- /// \brief Build a new template name given a template template parameter pack
+ /// Build a new template name given a template template parameter pack
/// and the
///
/// By default, performs semantic analysis to determine whether the name can
@@ -1177,7 +1187,7 @@ public:
return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
- /// \brief Build a new compound statement.
+ /// Build a new compound statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1189,7 +1199,7 @@ public:
IsStmtExpr);
}
- /// \brief Build a new case statement.
+ /// Build a new case statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1202,7 +1212,7 @@ public:
ColonLoc);
}
- /// \brief Attach the body to a new case statement.
+ /// Attach the body to a new case statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1211,7 +1221,7 @@ public:
return S;
}
- /// \brief Build a new default statement.
+ /// Build a new default statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1222,7 +1232,7 @@ public:
/*CurScope=*/nullptr);
}
- /// \brief Build a new label statement.
+ /// Build a new label statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1231,7 +1241,7 @@ public:
return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
}
- /// \brief Build a new label statement.
+ /// Build a new label statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1241,7 +1251,7 @@ public:
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
}
- /// \brief Build a new "if" statement.
+ /// Build a new "if" statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1252,7 +1262,7 @@ public:
ElseLoc, Else);
}
- /// \brief Start building a new switch statement.
+ /// Start building a new switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1261,7 +1271,7 @@ public:
return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Init, Cond);
}
- /// \brief Attach the body to the switch statement.
+ /// Attach the body to the switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1270,7 +1280,7 @@ public:
return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body);
}
- /// \brief Build a new while statement.
+ /// Build a new while statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1279,7 +1289,7 @@ public:
return getSema().ActOnWhileStmt(WhileLoc, Cond, Body);
}
- /// \brief Build a new do-while statement.
+ /// Build a new do-while statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1290,7 +1300,7 @@ public:
Cond, RParenLoc);
}
- /// \brief Build a new for statement.
+ /// Build a new for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1302,7 +1312,7 @@ public:
Inc, RParenLoc, Body);
}
- /// \brief Build a new goto statement.
+ /// Build a new goto statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1311,7 +1321,7 @@ public:
return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label);
}
- /// \brief Build a new indirect goto statement.
+ /// Build a new indirect goto statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1321,7 +1331,7 @@ public:
return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target);
}
- /// \brief Build a new return statement.
+ /// Build a new return statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1329,7 +1339,7 @@ public:
return getSema().BuildReturnStmt(ReturnLoc, Result);
}
- /// \brief Build a new declaration statement.
+ /// Build a new declaration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1339,7 +1349,7 @@ public:
return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
}
- /// \brief Build a new inline asm statement.
+ /// Build a new inline asm statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1354,7 +1364,7 @@ public:
AsmString, Clobbers, RParenLoc);
}
- /// \brief Build a new MS style inline asm statement.
+ /// Build a new MS style inline asm statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1371,7 +1381,7 @@ public:
Constraints, Clobbers, Exprs, EndLoc);
}
- /// \brief Build a new co_return statement.
+ /// Build a new co_return statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1380,7 +1390,7 @@ public:
return getSema().BuildCoreturnStmt(CoreturnLoc, Result, IsImplicit);
}
- /// \brief Build a new co_await expression.
+ /// Build a new co_await expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -1389,7 +1399,7 @@ public:
return getSema().BuildResolvedCoawaitExpr(CoawaitLoc, Result, IsImplicit);
}
- /// \brief Build a new co_await expression.
+ /// Build a new co_await expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -1399,7 +1409,7 @@ public:
return getSema().BuildUnresolvedCoawaitExpr(CoawaitLoc, Result, Lookup);
}
- /// \brief Build a new co_yield expression.
+ /// Build a new co_yield expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -1411,7 +1421,7 @@ public:
return getSema().BuildCoroutineBodyStmt(Args);
}
- /// \brief Build a new Objective-C \@try statement.
+ /// Build a new Objective-C \@try statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1423,7 +1433,7 @@ public:
Finally);
}
- /// \brief Rebuild an Objective-C exception declaration.
+ /// Rebuild an Objective-C exception declaration.
///
/// By default, performs semantic analysis to build the new declaration.
/// Subclasses may override this routine to provide different behavior.
@@ -1435,7 +1445,7 @@ public:
ExceptionDecl->getIdentifier());
}
- /// \brief Build a new Objective-C \@catch statement.
+ /// Build a new Objective-C \@catch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1447,7 +1457,7 @@ public:
Var, Body);
}
- /// \brief Build a new Objective-C \@finally statement.
+ /// Build a new Objective-C \@finally statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1456,7 +1466,7 @@ public:
return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body);
}
- /// \brief Build a new Objective-C \@throw statement.
+ /// Build a new Objective-C \@throw statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1465,7 +1475,7 @@ public:
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
- /// \brief Build a new OpenMP executable directive.
+ /// Build a new OpenMP executable directive.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1479,7 +1489,7 @@ public:
Kind, DirName, CancelRegion, Clauses, AStmt, StartLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'if' clause.
+ /// Build a new OpenMP 'if' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1494,7 +1504,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'final' clause.
+ /// Build a new OpenMP 'final' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1505,7 +1515,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'num_threads' clause.
+ /// Build a new OpenMP 'num_threads' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1517,7 +1527,7 @@ public:
LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'safelen' clause.
+ /// Build a new OpenMP 'safelen' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1527,7 +1537,7 @@ public:
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'simdlen' clause.
+ /// Build a new OpenMP 'simdlen' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1537,7 +1547,7 @@ public:
return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'collapse' clause.
+ /// Build a new OpenMP 'collapse' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1548,7 +1558,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'default' clause.
+ /// Build a new OpenMP 'default' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1561,7 +1571,7 @@ public:
StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'proc_bind' clause.
+ /// Build a new OpenMP 'proc_bind' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1574,7 +1584,7 @@ public:
StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'schedule' clause.
+ /// Build a new OpenMP 'schedule' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1588,7 +1598,7 @@ public:
CommaLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'ordered' clause.
+ /// Build a new OpenMP 'ordered' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1598,7 +1608,7 @@ public:
return getSema().ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Num);
}
- /// \brief Build a new OpenMP 'private' clause.
+ /// Build a new OpenMP 'private' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1610,7 +1620,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'firstprivate' clause.
+ /// Build a new OpenMP 'firstprivate' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1622,7 +1632,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'lastprivate' clause.
+ /// Build a new OpenMP 'lastprivate' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1634,7 +1644,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'shared' clause.
+ /// Build a new OpenMP 'shared' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1646,7 +1656,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'reduction' clause.
+ /// Build a new OpenMP 'reduction' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1694,7 +1704,7 @@ public:
ReductionId, UnresolvedReductions);
}
- /// \brief Build a new OpenMP 'linear' clause.
+ /// Build a new OpenMP 'linear' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1710,7 +1720,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'aligned' clause.
+ /// Build a new OpenMP 'aligned' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1723,7 +1733,7 @@ public:
LParenLoc, ColonLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'copyin' clause.
+ /// Build a new OpenMP 'copyin' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1735,7 +1745,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'copyprivate' clause.
+ /// Build a new OpenMP 'copyprivate' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1747,7 +1757,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'flush' pseudo clause.
+ /// Build a new OpenMP 'flush' pseudo clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1759,7 +1769,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'depend' pseudo clause.
+ /// Build a new OpenMP 'depend' pseudo clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1772,7 +1782,7 @@ public:
StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'device' clause.
+ /// Build a new OpenMP 'device' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1783,7 +1793,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'map' clause.
+ /// Build a new OpenMP 'map' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1798,18 +1808,18 @@ public:
VarList, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'num_teams' clause.
+ /// Build a new OpenMP 'num_teams' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
- return getSema().ActOnOpenMPNumTeamsClause(NumTeams, StartLoc, LParenLoc,
+ return getSema().ActOnOpenMPNumTeamsClause(NumTeams, StartLoc, LParenLoc,
EndLoc);
}
- /// \brief Build a new OpenMP 'thread_limit' clause.
+ /// Build a new OpenMP 'thread_limit' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1821,7 +1831,7 @@ public:
LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'priority' clause.
+ /// Build a new OpenMP 'priority' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1832,7 +1842,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'grainsize' clause.
+ /// Build a new OpenMP 'grainsize' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1843,7 +1853,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'num_tasks' clause.
+ /// Build a new OpenMP 'num_tasks' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1854,7 +1864,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'hint' clause.
+ /// Build a new OpenMP 'hint' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1864,7 +1874,7 @@ public:
return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'dist_schedule' clause.
+ /// Build a new OpenMP 'dist_schedule' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1877,7 +1887,7 @@ public:
Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'to' clause.
+ /// Build a new OpenMP 'to' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1888,7 +1898,7 @@ public:
return getSema().ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'from' clause.
+ /// Build a new OpenMP 'from' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1924,7 +1934,7 @@ public:
EndLoc);
}
- /// \brief Rebuild the operand to an Objective-C \@synchronized statement.
+ /// Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1933,7 +1943,7 @@ public:
return getSema().ActOnObjCAtSynchronizedOperand(atLoc, object);
}
- /// \brief Build a new Objective-C \@synchronized statement.
+ /// Build a new Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1942,7 +1952,7 @@ public:
return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body);
}
- /// \brief Build a new Objective-C \@autoreleasepool statement.
+ /// Build a new Objective-C \@autoreleasepool statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1951,7 +1961,7 @@ public:
return getSema().ActOnObjCAutoreleasePoolStmt(AtLoc, Body);
}
- /// \brief Build a new Objective-C fast enumeration statement.
+ /// Build a new Objective-C fast enumeration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1970,7 +1980,7 @@ public:
return getSema().FinishObjCForCollectionStmt(ForEachStmt.get(), Body);
}
- /// \brief Build a new C++ exception declaration.
+ /// Build a new C++ exception declaration.
///
/// By default, performs semantic analysis to build the new decaration.
/// Subclasses may override this routine to provide different behavior.
@@ -1986,7 +1996,7 @@ public:
return Var;
}
- /// \brief Build a new C++ catch statement.
+ /// Build a new C++ catch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1997,7 +2007,7 @@ public:
Handler));
}
- /// \brief Build a new C++ try statement.
+ /// Build a new C++ try statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2006,7 +2016,7 @@ public:
return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, Handlers);
}
- /// \brief Build a new C++0x range-based for statement.
+ /// Build a new C++0x range-based for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2040,7 +2050,7 @@ public:
Sema::BFRK_Rebuild);
}
- /// \brief Build a new C++0x range-based for statement.
+ /// Build a new C++0x range-based for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2053,7 +2063,7 @@ public:
QualifierLoc, NameInfo, Nested);
}
- /// \brief Attach body to a C++0x range-based for statement.
+ /// Attach body to a C++0x range-based for statement.
///
/// By default, performs semantic analysis to finish the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2075,7 +2085,7 @@ public:
return SEHFinallyStmt::Create(getSema().getASTContext(), Loc, Block);
}
- /// \brief Build a new predefined expression.
+ /// Build a new predefined expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2084,7 +2094,7 @@ public:
return getSema().BuildPredefinedExpr(Loc, IT);
}
- /// \brief Build a new expression that references a declaration.
+ /// Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2095,7 +2105,7 @@ public:
}
- /// \brief Build a new expression that references a declaration.
+ /// Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2111,7 +2121,7 @@ public:
return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD);
}
- /// \brief Build a new expression in parentheses.
+ /// Build a new expression in parentheses.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2120,7 +2130,7 @@ public:
return getSema().ActOnParenExpr(LParen, RParen, SubExpr);
}
- /// \brief Build a new pseudo-destructor expression.
+ /// Build a new pseudo-destructor expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2133,7 +2143,7 @@ public:
SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destroyed);
- /// \brief Build a new unary operator expression.
+ /// Build a new unary operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2143,7 +2153,7 @@ public:
return getSema().BuildUnaryOp(/*Scope=*/nullptr, OpLoc, Opc, SubExpr);
}
- /// \brief Build a new builtin offsetof expression.
+ /// Build a new builtin offsetof expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2155,7 +2165,7 @@ public:
RParenLoc);
}
- /// \brief Build a new sizeof, alignof or vec_step expression with a
+ /// Build a new sizeof, alignof or vec_step expression with a
/// type argument.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2167,7 +2177,7 @@ public:
return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R);
}
- /// \brief Build a new sizeof, alignof or vec step expression with an
+ /// Build a new sizeof, alignof or vec step expression with an
/// expression argument.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2183,7 +2193,7 @@ public:
return Result;
}
- /// \brief Build a new array subscript expression.
+ /// Build a new array subscript expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2196,7 +2206,7 @@ public:
RBracketLoc);
}
- /// \brief Build a new array section expression.
+ /// Build a new array section expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2208,7 +2218,7 @@ public:
ColonLoc, Length, RBracketLoc);
}
- /// \brief Build a new call expression.
+ /// Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2220,7 +2230,7 @@ public:
Args, RParenLoc, ExecConfig);
}
- /// \brief Build a new member access expression.
+ /// Build a new member access expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2239,7 +2249,6 @@ public:
// We have a reference to an unnamed field. This is always the
// base of an anonymous struct/union member access, i.e. the
// field is always of record type.
- assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!");
assert(Member->getType()->isRecordType() &&
"unnamed member not of record type?");
@@ -2250,11 +2259,11 @@ public:
if (BaseResult.isInvalid())
return ExprError();
Base = BaseResult.get();
- ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
- MemberExpr *ME = new (getSema().Context)
- MemberExpr(Base, isArrow, OpLoc, Member, MemberNameInfo,
- cast<FieldDecl>(Member)->getType(), VK, OK_Ordinary);
- return ME;
+
+ CXXScopeSpec EmptySS;
+ return getSema().BuildFieldReferenceExpr(
+ Base, isArrow, OpLoc, EmptySS, cast<FieldDecl>(Member),
+ DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), MemberNameInfo);
}
CXXScopeSpec SS;
@@ -2279,7 +2288,7 @@ public:
/*S*/nullptr);
}
- /// \brief Build a new binary operator expression.
+ /// Build a new binary operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2289,7 +2298,7 @@ public:
return getSema().BuildBinOp(/*Scope=*/nullptr, OpLoc, Opc, LHS, RHS);
}
- /// \brief Build a new conditional operator expression.
+ /// Build a new conditional operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2302,7 +2311,7 @@ public:
LHS, RHS);
}
- /// \brief Build a new C-style cast expression.
+ /// Build a new C-style cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2314,7 +2323,7 @@ public:
SubExpr);
}
- /// \brief Build a new compound literal expression.
+ /// Build a new compound literal expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2326,7 +2335,7 @@ public:
Init);
}
- /// \brief Build a new extended vector element access expression.
+ /// Build a new extended vector element access expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2346,27 +2355,17 @@ public:
/*S*/ nullptr);
}
- /// \brief Build a new initializer list expression.
+ /// Build a new initializer list expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildInitList(SourceLocation LBraceLoc,
MultiExprArg Inits,
- SourceLocation RBraceLoc,
- QualType ResultTy) {
- ExprResult Result
- = SemaRef.ActOnInitList(LBraceLoc, Inits, RBraceLoc);
- if (Result.isInvalid() || ResultTy->isDependentType())
- return Result;
-
- // Patch in the result type we were given, which may have been computed
- // when the initial InitListExpr was built.
- InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get());
- ILE->setType(ResultTy);
- return Result;
+ SourceLocation RBraceLoc) {
+ return SemaRef.ActOnInitList(LBraceLoc, Inits, RBraceLoc);
}
- /// \brief Build a new designated initializer expression.
+ /// Build a new designated initializer expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2384,7 +2383,7 @@ public:
return Result;
}
- /// \brief Build a new value-initialized expression.
+ /// Build a new value-initialized expression.
///
/// By default, builds the implicit value initialization without performing
/// any semantic analysis. Subclasses may override this routine to provide
@@ -2393,7 +2392,7 @@ public:
return new (SemaRef.Context) ImplicitValueInitExpr(T);
}
- /// \brief Build a new \c va_arg expression.
+ /// Build a new \c va_arg expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2405,7 +2404,7 @@ public:
RParenLoc);
}
- /// \brief Build a new expression list in parentheses.
+ /// Build a new expression list in parentheses.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2415,7 +2414,7 @@ public:
return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, SubExprs);
}
- /// \brief Build a new address-of-label expression.
+ /// Build a new address-of-label expression.
///
/// By default, performs semantic analysis, using the name of the label
/// rather than attempting to map the label statement itself.
@@ -2425,7 +2424,7 @@ public:
return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label);
}
- /// \brief Build a new GNU statement expression.
+ /// Build a new GNU statement expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2435,7 +2434,7 @@ public:
return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc);
}
- /// \brief Build a new __builtin_choose_expr expression.
+ /// Build a new __builtin_choose_expr expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2447,7 +2446,7 @@ public:
RParenLoc);
}
- /// \brief Build a new generic selection expression.
+ /// Build a new generic selection expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2461,7 +2460,7 @@ public:
ControllingExpr, Types, Exprs);
}
- /// \brief Build a new overloaded operator call expression.
+ /// Build a new overloaded operator call expression.
///
/// By default, performs semantic analysis to build the new expression.
/// The semantic analysis provides the behavior of template instantiation,
@@ -2475,7 +2474,7 @@ public:
Expr *First,
Expr *Second);
- /// \brief Build a new C++ "named" cast expression, such as static_cast or
+ /// Build a new C++ "named" cast expression, such as static_cast or
/// reinterpret_cast.
///
/// By default, this routine dispatches to one of the more-specific routines
@@ -2516,7 +2515,7 @@ public:
}
}
- /// \brief Build a new C++ static_cast expression.
+ /// Build a new C++ static_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2533,7 +2532,7 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ dynamic_cast expression.
+ /// Build a new C++ dynamic_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2550,7 +2549,7 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ reinterpret_cast expression.
+ /// Build a new C++ reinterpret_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2567,7 +2566,7 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ const_cast expression.
+ /// Build a new C++ const_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2584,20 +2583,21 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ functional-style cast expression.
+ /// Build a new C++ functional-style cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
SourceLocation LParenLoc,
Expr *Sub,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ bool ListInitialization) {
return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc,
- MultiExprArg(&Sub, 1),
- RParenLoc);
+ MultiExprArg(&Sub, 1), RParenLoc,
+ ListInitialization);
}
- /// \brief Build a new C++ typeid(type) expression.
+ /// Build a new C++ typeid(type) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2610,7 +2610,7 @@ public:
}
- /// \brief Build a new C++ typeid(expr) expression.
+ /// Build a new C++ typeid(expr) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2622,7 +2622,7 @@ public:
RParenLoc);
}
- /// \brief Build a new C++ __uuidof(type) expression.
+ /// Build a new C++ __uuidof(type) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2634,7 +2634,7 @@ public:
RParenLoc);
}
- /// \brief Build a new C++ __uuidof(expr) expression.
+ /// Build a new C++ __uuidof(expr) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2646,7 +2646,7 @@ public:
RParenLoc);
}
- /// \brief Build a new C++ "this" expression.
+ /// Build a new C++ "this" expression.
///
/// By default, builds a new "this" expression without performing any
/// semantic analysis. Subclasses may override this routine to provide
@@ -2658,7 +2658,7 @@ public:
return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit);
}
- /// \brief Build a new C++ throw expression.
+ /// Build a new C++ throw expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2667,7 +2667,7 @@ public:
return getSema().BuildCXXThrow(ThrowLoc, Sub, IsThrownVariableInScope);
}
- /// \brief Build a new C++ default-argument expression.
+ /// Build a new C++ default-argument expression.
///
/// By default, builds a new default-argument expression, which does not
/// require any semantic analysis. Subclasses may override this routine to
@@ -2677,7 +2677,7 @@ public:
return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param);
}
- /// \brief Build a new C++11 default-initialization expression.
+ /// Build a new C++11 default-initialization expression.
///
/// By default, builds a new default field initialization expression, which
/// does not require any semantic analysis. Subclasses may override this
@@ -2687,18 +2687,18 @@ public:
return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field);
}
- /// \brief Build a new C++ zero-initialization expression.
+ /// Build a new C++ zero-initialization expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXScalarValueInitExpr(TypeSourceInfo *TSInfo,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc,
- None, RParenLoc);
+ return getSema().BuildCXXTypeConstructExpr(
+ TSInfo, LParenLoc, None, RParenLoc, /*ListInitialization=*/false);
}
- /// \brief Build a new C++ "new" expression.
+ /// Build a new C++ "new" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2725,7 +2725,7 @@ public:
Initializer);
}
- /// \brief Build a new C++ "delete" expression.
+ /// Build a new C++ "delete" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2737,7 +2737,7 @@ public:
Operand);
}
- /// \brief Build a new type trait expression.
+ /// Build a new type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2748,7 +2748,7 @@ public:
return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc);
}
- /// \brief Build a new array type trait expression.
+ /// Build a new array type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2760,7 +2760,7 @@ public:
return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc);
}
- /// \brief Build a new expression trait expression.
+ /// Build a new expression trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2771,7 +2771,7 @@ public:
return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc);
}
- /// \brief Build a new (previously unresolved) declaration reference
+ /// Build a new (previously unresolved) declaration reference
/// expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2794,7 +2794,7 @@ public:
SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI);
}
- /// \brief Build a new template-id expression.
+ /// Build a new template-id expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2807,7 +2807,7 @@ public:
TemplateArgs);
}
- /// \brief Build a new object-construction expression.
+ /// Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2837,7 +2837,7 @@ public:
ParenRange);
}
- /// \brief Build a new implicit construction via inherited constructor
+ /// Build a new implicit construction via inherited constructor
/// expression.
ExprResult RebuildCXXInheritedCtorInitExpr(QualType T, SourceLocation Loc,
CXXConstructorDecl *Constructor,
@@ -2847,35 +2847,33 @@ public:
Loc, T, Constructor, ConstructsVBase, InheritedFromVBase);
}
- /// \brief Build a new object-construction expression.
+ /// Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXTemporaryObjectExpr(TypeSourceInfo *TSInfo,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg Args,
- SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeConstructExpr(TSInfo,
- LParenLoc,
- Args,
- RParenLoc);
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization) {
+ return getSema().BuildCXXTypeConstructExpr(
+ TSInfo, LParenOrBraceLoc, Args, RParenOrBraceLoc, ListInitialization);
}
- /// \brief Build a new object-construction expression.
+ /// Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXUnresolvedConstructExpr(TypeSourceInfo *TSInfo,
SourceLocation LParenLoc,
MultiExprArg Args,
- SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeConstructExpr(TSInfo,
- LParenLoc,
- Args,
- RParenLoc);
+ SourceLocation RParenLoc,
+ bool ListInitialization) {
+ return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, Args,
+ RParenLoc, ListInitialization);
}
- /// \brief Build a new member reference expression.
+ /// Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2899,7 +2897,7 @@ public:
TemplateArgs, /*S*/nullptr);
}
- /// \brief Build a new member reference expression.
+ /// Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2921,7 +2919,7 @@ public:
R, TemplateArgs, /*S*/nullptr);
}
- /// \brief Build a new noexcept expression.
+ /// Build a new noexcept expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2929,7 +2927,7 @@ public:
return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd());
}
- /// \brief Build a new expression to compute the length of a parameter pack.
+ /// Build a new expression to compute the length of a parameter pack.
ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc,
NamedDecl *Pack,
SourceLocation PackLoc,
@@ -2940,7 +2938,7 @@ public:
RParenLoc, Length, PartialArgs);
}
- /// \brief Build a new Objective-C boxed expression.
+ /// Build a new Objective-C boxed expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2948,7 +2946,7 @@ public:
return getSema().BuildObjCBoxedExpr(SR, ValueExpr);
}
- /// \brief Build a new Objective-C array literal.
+ /// Build a new Objective-C array literal.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2966,7 +2964,7 @@ public:
getterMethod, setterMethod);
}
- /// \brief Build a new Objective-C dictionary literal.
+ /// Build a new Objective-C dictionary literal.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2975,7 +2973,7 @@ public:
return getSema().BuildObjCDictionaryLiteral(Range, Elements);
}
- /// \brief Build a new Objective-C \@encode expression.
+ /// Build a new Objective-C \@encode expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2985,7 +2983,7 @@ public:
return SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, RParenLoc);
}
- /// \brief Build a new Objective-C class message.
+ /// Build a new Objective-C class message.
ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3000,7 +2998,7 @@ public:
RBracLoc, Args);
}
- /// \brief Build a new Objective-C instance message.
+ /// Build a new Objective-C instance message.
ExprResult RebuildObjCMessageExpr(Expr *Receiver,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3015,7 +3013,7 @@ public:
RBracLoc, Args);
}
- /// \brief Build a new Objective-C instance/class message to 'super'.
+ /// Build a new Objective-C instance/class message to 'super'.
ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3035,10 +3033,10 @@ public:
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);
-
+
}
- /// \brief Build a new Objective-C ivar reference expression.
+ /// Build a new Objective-C ivar reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3058,7 +3056,7 @@ public:
return Result;
}
- /// \brief Build a new Objective-C property reference expression.
+ /// Build a new Objective-C property reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3077,7 +3075,7 @@ public:
/*S=*/nullptr);
}
- /// \brief Build a new Objective-C property reference expression.
+ /// Build a new Objective-C property reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3093,7 +3091,7 @@ public:
PropertyLoc, Base));
}
- /// \brief Build a new Objective-C "isa" expression.
+ /// Build a new Objective-C "isa" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3110,7 +3108,7 @@ public:
/*S=*/nullptr);
}
- /// \brief Build a new shuffle vector expression.
+ /// Build a new shuffle vector expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3142,7 +3140,7 @@ public:
return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get()));
}
- /// \brief Build a new convert vector expression.
+ /// Build a new convert vector expression.
ExprResult RebuildConvertVectorExpr(SourceLocation BuiltinLoc,
Expr *SrcExpr, TypeSourceInfo *DstTInfo,
SourceLocation RParenLoc) {
@@ -3150,7 +3148,7 @@ public:
BuiltinLoc, RParenLoc);
}
- /// \brief Build a new template argument pack expansion.
+ /// Build a new template argument pack expansion.
///
/// By default, performs semantic analysis to build a new pack expansion
/// for a template argument. Subclasses may override this routine to provide
@@ -3198,7 +3196,7 @@ public:
return TemplateArgumentLoc();
}
- /// \brief Build a new expression pack expansion.
+ /// Build a new expression pack expansion.
///
/// By default, performs semantic analysis to build a new pack expansion
/// for an expression. Subclasses may override this routine to provide
@@ -3208,7 +3206,7 @@ public:
return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
}
- /// \brief Build a new C++1z fold-expression.
+ /// Build a new C++1z fold-expression.
///
/// By default, performs semantic analysis in order to build a new fold
/// expression.
@@ -3220,7 +3218,7 @@ public:
RHS, RParenLoc);
}
- /// \brief Build an empty C++1z fold-expression with the given operator.
+ /// Build an empty C++1z fold-expression with the given operator.
///
/// By default, produces the fallback value for the fold-expression, or
/// produce an error if there is no fallback value.
@@ -3229,7 +3227,7 @@ public:
return getSema().BuildEmptyCXXFoldExpr(EllipsisLoc, Operator);
}
- /// \brief Build a new atomic operation expression.
+ /// Build a new atomic operation expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3394,11 +3392,10 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
/*IsCall*/true, NewArgs, &ArgChanged))
return ExprError();
- // If this was list initialization, revert to list form.
+ // If this was list initialization, revert to syntactic list form.
if (Construct->isListInitialization())
return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs,
- Construct->getLocEnd(),
- Construct->getType());
+ Construct->getLocEnd());
// Build a ParenListExpr to represent anything else.
SourceRange Parens = Construct->getParenOrBraceRange();
@@ -3765,8 +3762,12 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
ObjectType.isNull())
return Name;
+ // FIXME: Preserve the location of the "template" keyword.
+ SourceLocation TemplateKWLoc = NameLoc;
+
if (DTN->isIdentifier()) {
return getDerived().RebuildTemplateName(SS,
+ TemplateKWLoc,
*DTN->getIdentifier(),
NameLoc,
ObjectType,
@@ -3774,7 +3775,8 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
AllowInjectedClassName);
}
- return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc,
+ return getDerived().RebuildTemplateName(SS, TemplateKWLoc,
+ DTN->getOperator(), NameLoc,
ObjectType, AllowInjectedClassName);
}
@@ -3866,6 +3868,10 @@ template<typename Derived>
bool TreeTransform<Derived>::TransformTemplateArgument(
const TemplateArgumentLoc &Input,
TemplateArgumentLoc &Output, bool Uneval) {
+ EnterExpressionEvaluationContext EEEC(
+ SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated,
+ /*LambdaContextDecl=*/nullptr, /*ExprContext=*/
+ Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -3933,7 +3939,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
return true;
}
-/// \brief Iterator adaptor that invents template argument location information
+/// Iterator adaptor that invents template argument location information
/// for each of the template arguments in its underlying iterator.
template<typename Derived, typename InputIterator>
class TemplateArgumentLocInventIterator {
@@ -4353,6 +4359,7 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
TemplateName Template
= getDerived().RebuildTemplateName(SS,
+ SpecTL.getTemplateKeywordLoc(),
*SpecTL.getTypePtr()->getIdentifier(),
SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup,
@@ -4752,6 +4759,44 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
return Result;
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentVectorType(
+ TypeLocBuilder &TLB, DependentVectorTypeLoc TL) {
+ const DependentVectorType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(T->getElementType());
+ if (ElementType.isNull())
+ return QualType();
+
+ EnterExpressionEvaluationContext Unevaluated(
+ SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ Size = SemaRef.ActOnConstantExpression(Size);
+ if (Size.isInvalid())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() ||
+ Size.get() != T->getSizeExpr()) {
+ Result = getDerived().RebuildDependentVectorType(
+ ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // Result might be dependent or not.
+ if (isa<DependentVectorType>(Result)) {
+ DependentVectorTypeLoc NewTL =
+ TLB.push<DependentVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ } else {
+ VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ }
+
+ return Result;
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
TypeLocBuilder &TLB,
@@ -5277,30 +5322,23 @@ bool TreeTransform<Derived>::TransformExceptionSpec(
assert(ESI.Type != EST_Uninstantiated && ESI.Type != EST_Unevaluated);
// Instantiate a dynamic noexcept expression, if any.
- if (ESI.Type == EST_ComputedNoexcept) {
+ if (isComputedNoexcept(ESI.Type)) {
EnterExpressionEvaluationContext Unevaluated(
getSema(), Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr);
if (NoexceptExpr.isInvalid())
return true;
- // FIXME: This is bogus, a noexcept expression is not a condition.
- NoexceptExpr = getSema().CheckBooleanCondition(Loc, NoexceptExpr.get());
+ ExceptionSpecificationType EST = ESI.Type;
+ NoexceptExpr =
+ getSema().ActOnNoexceptSpec(Loc, NoexceptExpr.get(), EST);
if (NoexceptExpr.isInvalid())
return true;
- if (!NoexceptExpr.get()->isValueDependent()) {
- NoexceptExpr = getSema().VerifyIntegerConstantExpression(
- NoexceptExpr.get(), nullptr,
- diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/false);
- if (NoexceptExpr.isInvalid())
- return true;
- }
-
- if (ESI.NoexceptExpr != NoexceptExpr.get())
+ if (ESI.NoexceptExpr != NoexceptExpr.get() || EST != ESI.Type)
Changed = true;
ESI.NoexceptExpr = NoexceptExpr.get();
+ ESI.Type = EST;
}
if (ESI.Type != EST_Dynamic)
@@ -5507,7 +5545,7 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
// decltype expressions are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
- /*IsDecltype=*/true);
+ Sema::ExpressionEvaluationContextRecord::EK_Decltype);
ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
@@ -5778,7 +5816,7 @@ QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
return Result;
}
- /// \brief Simple iterator that traverses the template arguments in a
+ /// Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
///
/// This iterator is intended to be used with the iterator form of
@@ -6158,8 +6196,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
return QualType();
QualType Result = getDerived().RebuildDependentTemplateSpecializationType(
- T->getKeyword(), QualifierLoc, T->getIdentifier(),
- TL.getTemplateNameLoc(), NewTemplateArgs,
+ T->getKeyword(), QualifierLoc, TL.getTemplateKeywordLoc(),
+ T->getIdentifier(), TL.getTemplateNameLoc(), NewTemplateArgs,
/*AllowInjectedClassName*/ false);
if (Result.isNull())
return QualType();
@@ -6318,7 +6356,7 @@ TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
TypeLocBuilder TypeArgBuilder;
TypeArgBuilder.reserve(PatternLoc.getFullDataSize());
- QualType NewPatternType = getDerived().TransformType(TypeArgBuilder,
+ QualType NewPatternType = getDerived().TransformType(TypeArgBuilder,
PatternLoc);
if (NewPatternType.isNull())
return QualType();
@@ -6487,13 +6525,13 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
// Transform the left-hand case value.
LHS = getDerived().TransformExpr(S->getLHS());
- LHS = SemaRef.ActOnConstantExpression(LHS);
+ LHS = SemaRef.ActOnCaseExpr(S->getCaseLoc(), LHS);
if (LHS.isInvalid())
return StmtError();
// Transform the right-hand case value (for the GNU case-range extension).
RHS = getDerived().TransformExpr(S->getRHS());
- RHS = SemaRef.ActOnConstantExpression(RHS);
+ RHS = SemaRef.ActOnCaseExpr(S->getCaseLoc(), RHS);
if (RHS.isInvalid())
return StmtError();
}
@@ -6956,6 +6994,8 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
// The new CoroutinePromise object needs to be built and put into the current
// FunctionScopeInfo before any transformations or rebuilding occurs.
+ if (!SemaRef.buildCoroutineParameterMoves(FD->getLocation()))
+ return StmtError();
auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation());
if (!Promise)
return StmtError();
@@ -7046,8 +7086,6 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
Builder.ReturnStmt = Res.get();
}
}
- if (!Builder.buildParameterMoves())
- return StmtError();
return getDerived().RebuildCoroutineBodyStmt(Builder);
}
@@ -7642,11 +7680,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
StmtResult Body;
{
Sema::CompoundScopeRAII CompoundScope(getSema());
- int ThisCaptureLevel =
- Sema::getOpenMPCaptureLevels(D->getDirectiveKind());
- Stmt *CS = D->getAssociatedStmt();
- while (--ThisCaptureLevel >= 0)
- CS = cast<CapturedStmt>(CS)->getCapturedStmt();
+ Stmt *CS = D->getInnermostCapturedStmt()->getCapturedStmt();
Body = getDerived().TransformStmt(CS);
}
AssociatedStmt =
@@ -8905,6 +8939,12 @@ TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
return E;
}
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformFixedPointLiteral(
+ FixedPointLiteral *E) {
+ return E;
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
@@ -8986,7 +9026,7 @@ TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
E->getRParen());
}
-/// \brief The operand of a unary address-of operator has special rules: it's
+/// The operand of a unary address-of operator has special rules: it's
/// allowed to refer to a non-static member of a class even if there's no 'this'
/// object available.
template<typename Derived>
@@ -9517,7 +9557,7 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
}
return getDerived().RebuildInitList(E->getLBraceLoc(), Inits,
- E->getRBraceLoc(), E->getType());
+ E->getRBraceLoc());
}
template<typename Derived>
@@ -9685,7 +9725,7 @@ TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
E->getRParenLoc());
}
-/// \brief Transform an address-of-label expression.
+/// Transform an address-of-label expression.
///
/// By default, the transformation of an address-of-label expression always
/// rebuilds the expression, so that the label identifier can be resolved to
@@ -9951,7 +9991,8 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
return getDerived().RebuildCXXFunctionalCastExpr(Type,
E->getLParenLoc(),
SubExpr.get(),
- E->getRParenLoc());
+ E->getRParenLoc(),
+ E->isListInitialization());
}
template<typename Derived>
@@ -10403,7 +10444,7 @@ bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old,
// the corresponding pack is empty
if (AllEmptyPacks && !RequiresADL) {
getSema().Diag(Old->getNameLoc(), diag::err_using_pack_expansion_empty)
- << isa<UnresolvedMemberExpr>(Old) << Old->getNameInfo().getName();
+ << isa<UnresolvedMemberExpr>(Old) << Old->getName();
return true;
}
@@ -10814,7 +10855,7 @@ ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr(
E->constructsVBase(), E->inheritedFromVBase());
}
-/// \brief Transform a C++ temporary-binding expression.
+/// Transform a C++ temporary-binding expression.
///
/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
/// transform the subexpression and return that.
@@ -10824,7 +10865,7 @@ TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
return getDerived().TransformExpr(E->getSubExpr());
}
-/// \brief Transform a C++ expression that contains cleanups that should
+/// Transform a C++ expression that contains cleanups that should
/// be run after the expression is evaluated.
///
/// Since ExprWithCleanups nodes are implicitly generated, we
@@ -10867,11 +10908,12 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
return SemaRef.MaybeBindToTemporary(E);
}
- // FIXME: Pass in E->isListInitialization().
- return getDerived().RebuildCXXTemporaryObjectExpr(T,
- /*FIXME:*/T->getTypeLoc().getEndLoc(),
- Args,
- E->getLocEnd());
+ // FIXME: We should just pass E->isListInitialization(), but we're not
+ // prepared to handle list-initialization without a child InitListExpr.
+ SourceLocation LParenLoc = T->getTypeLoc().getEndLoc();
+ return getDerived().RebuildCXXTemporaryObjectExpr(
+ T, LParenLoc, Args, E->getLocEnd(),
+ /*ListInitialization=*/LParenLoc.isInvalid());
}
template<typename Derived>
@@ -10921,7 +10963,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
TypeSourceInfo *NewCallOpTSI = nullptr;
{
TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
- FunctionProtoTypeLoc OldCallOpFPTL =
+ FunctionProtoTypeLoc OldCallOpFPTL =
OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
TypeLocBuilder NewCallOpTLBuilder;
@@ -11017,7 +11059,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
// Rebuild init-captures, including the implied field declaration.
if (E->isInitCapture(C)) {
- InitCaptureInfoTy InitExprTypePair =
+ InitCaptureInfoTy InitExprTypePair =
InitCaptureExprsAndTypes[C - E->capture_begin()];
ExprResult Init = InitExprTypePair.first;
QualType InitQualType = InitExprTypePair.second;
@@ -11157,10 +11199,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
return E;
// FIXME: we're faking the locations of the commas
- return getDerived().RebuildCXXUnresolvedConstructExpr(T,
- E->getLParenLoc(),
- Args,
- E->getRParenLoc());
+ return getDerived().RebuildCXXUnresolvedConstructExpr(
+ T, E->getLParenLoc(), Args, E->getRParenLoc(), E->isListInitialization());
}
template<typename Derived>
@@ -11408,8 +11448,10 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
ArgStorage = TemplateArgument(TemplateName(TTPD), None);
} else {
auto *VD = cast<ValueDecl>(Pack);
- ExprResult DRE = getSema().BuildDeclRefExpr(VD, VD->getType(),
- VK_RValue, E->getPackLoc());
+ ExprResult DRE = getSema().BuildDeclRefExpr(
+ VD, VD->getType().getNonLValueExprType(getSema().Context),
+ VD->getType()->isReferenceType() ? VK_LValue : VK_RValue,
+ E->getPackLoc());
if (DRE.isInvalid())
return ExprError();
ArgStorage = new (getSema().Context) PackExpansionExpr(
@@ -12386,6 +12428,13 @@ TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
}
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildDependentVectorType(
+ QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc,
+ VectorType::VectorKind VecKind) {
+ return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc);
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
unsigned NumElements,
@@ -12532,6 +12581,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
SourceLocation NameLoc,
QualType ObjectType,
@@ -12540,7 +12590,6 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
- SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, TemplateName,
ParsedType::make(ObjectType),
@@ -12552,6 +12601,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
OverloadedOperatorKind Operator,
SourceLocation NameLoc,
QualType ObjectType,
@@ -12560,7 +12610,6 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
// FIXME: Bogus location information.
SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc };
Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations);
- SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
Sema::TemplateTy Template;
getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, Name,
@@ -12609,9 +12658,11 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// -> is never a builtin operation.
return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
} else if (Second == nullptr || isPostIncDec) {
- if (!First->getType()->isOverloadableType()) {
- // The argument is not of overloadable type, so try to create a
- // built-in unary operation.
+ if (!First->getType()->isOverloadableType() ||
+ (Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) {
+ // The argument is not of overloadable type, or this is an expression
+ // of the form &Class::member, so try to create a built-in unary
+ // operation.
UnaryOperatorKind Opc
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index 9c77045d2e12..536ea1c07f49 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -37,7 +37,7 @@ class TypeLocBuilder {
/// The last type pushed on this builder.
QualType LastTy;
#endif
-
+
/// The inline buffer.
enum { BufferMaxAlignment = alignof(void *) };
llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
@@ -81,16 +81,16 @@ class TypeLocBuilder {
#endif
Index = Capacity;
NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
- }
+ }
- /// \brief Tell the TypeLocBuilder that the type it is storing has been
+ /// Tell the TypeLocBuilder that the type it is storing has been
/// modified in some safe way that doesn't affect type-location information.
void TypeWasModifiedSafely(QualType T) {
#ifndef NDEBUG
LastTy = T;
#endif
}
-
+
/// Pushes space for a new TypeLoc of the given type. Invalidates
/// any TypeLocs previously retrieved from this builder.
template <class TyLocType> TyLocType push(QualType T) {
@@ -112,13 +112,13 @@ class TypeLocBuilder {
return DI;
}
- /// \brief Copies the type-location information to the given AST context and
+ /// Copies the type-location information to the given AST context and
/// returns a \c TypeLoc referring into the AST context.
TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
#ifndef NDEBUG
assert(T == LastTy && "type doesn't match last type pushed!");
#endif
-
+
size_t FullDataSize = Capacity - Index;
void *Mem = Context.Allocate(FullDataSize);
memcpy(Mem, &Buffer[Index], FullDataSize);
@@ -132,10 +132,10 @@ private:
/// Grow to the given capacity.
void grow(size_t NewCapacity);
- /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
+ /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
/// object.
///
- /// The resulting \c TypeLoc should only be used so long as the
+ /// The resulting \c TypeLoc should only be used so long as the
/// \c TypeLocBuilder is active and has not had more type information
/// pushed into it.
TypeLoc getTemporaryTypeLoc(QualType T) {
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
index 9c6f03cd0bb7..da482717f450 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
@@ -16,7 +16,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Serialization/ASTDeserializationListener.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/DJB.h"
using namespace clang;
@@ -91,6 +91,78 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::LongDouble:
ID = PREDEF_TYPE_LONGDOUBLE_ID;
break;
+ case BuiltinType::ShortAccum:
+ ID = PREDEF_TYPE_SHORT_ACCUM_ID;
+ break;
+ case BuiltinType::Accum:
+ ID = PREDEF_TYPE_ACCUM_ID;
+ break;
+ case BuiltinType::LongAccum:
+ ID = PREDEF_TYPE_LONG_ACCUM_ID;
+ break;
+ case BuiltinType::UShortAccum:
+ ID = PREDEF_TYPE_USHORT_ACCUM_ID;
+ break;
+ case BuiltinType::UAccum:
+ ID = PREDEF_TYPE_UACCUM_ID;
+ break;
+ case BuiltinType::ULongAccum:
+ ID = PREDEF_TYPE_ULONG_ACCUM_ID;
+ break;
+ case BuiltinType::ShortFract:
+ ID = PREDEF_TYPE_SHORT_FRACT_ID;
+ break;
+ case BuiltinType::Fract:
+ ID = PREDEF_TYPE_FRACT_ID;
+ break;
+ case BuiltinType::LongFract:
+ ID = PREDEF_TYPE_LONG_FRACT_ID;
+ break;
+ case BuiltinType::UShortFract:
+ ID = PREDEF_TYPE_USHORT_FRACT_ID;
+ break;
+ case BuiltinType::UFract:
+ ID = PREDEF_TYPE_UFRACT_ID;
+ break;
+ case BuiltinType::ULongFract:
+ ID = PREDEF_TYPE_ULONG_FRACT_ID;
+ break;
+ case BuiltinType::SatShortAccum:
+ ID = PREDEF_TYPE_SAT_SHORT_ACCUM_ID;
+ break;
+ case BuiltinType::SatAccum:
+ ID = PREDEF_TYPE_SAT_ACCUM_ID;
+ break;
+ case BuiltinType::SatLongAccum:
+ ID = PREDEF_TYPE_SAT_LONG_ACCUM_ID;
+ break;
+ case BuiltinType::SatUShortAccum:
+ ID = PREDEF_TYPE_SAT_USHORT_ACCUM_ID;
+ break;
+ case BuiltinType::SatUAccum:
+ ID = PREDEF_TYPE_SAT_UACCUM_ID;
+ break;
+ case BuiltinType::SatULongAccum:
+ ID = PREDEF_TYPE_SAT_ULONG_ACCUM_ID;
+ break;
+ case BuiltinType::SatShortFract:
+ ID = PREDEF_TYPE_SAT_SHORT_FRACT_ID;
+ break;
+ case BuiltinType::SatFract:
+ ID = PREDEF_TYPE_SAT_FRACT_ID;
+ break;
+ case BuiltinType::SatLongFract:
+ ID = PREDEF_TYPE_SAT_LONG_FRACT_ID;
+ break;
+ case BuiltinType::SatUShortFract:
+ ID = PREDEF_TYPE_SAT_USHORT_FRACT_ID;
+ break;
+ case BuiltinType::SatUFract:
+ ID = PREDEF_TYPE_SAT_UFRACT_ID;
+ break;
+ case BuiltinType::SatULongFract:
+ ID = PREDEF_TYPE_SAT_ULONG_FRACT_ID;
+ break;
case BuiltinType::Float16:
ID = PREDEF_TYPE_FLOAT16_ID;
break;
@@ -100,6 +172,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::NullPtr:
ID = PREDEF_TYPE_NULLPTR_ID;
break;
+ case BuiltinType::Char8:
+ ID = PREDEF_TYPE_CHAR8_ID;
+ break;
case BuiltinType::Char16:
ID = PREDEF_TYPE_CHAR16_ID;
break;
@@ -171,7 +246,7 @@ unsigned serialization::ComputeHash(Selector Sel) {
unsigned R = 5381;
for (unsigned I = 0; I != N; ++I)
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
- R = llvm::HashString(II->getName(), R);
+ R = llvm::djbHash(II->getName(), R);
return R;
}
@@ -231,7 +306,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {
default:
llvm_unreachable("Unhandled DeclContext in AST reader");
}
-
+
llvm_unreachable("Unhandled decl kind");
}
@@ -344,9 +419,21 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
return true;
}
- // Otherwise, we only care about anonymous class members.
+ // At block scope, we number everything that we need to deduplicate, since we
+ // can't just use name matching to keep things lined up.
+ // FIXME: This is only necessary for an inline function or a template or
+ // similar.
+ if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
+ if (auto *VD = dyn_cast<VarDecl>(D))
+ return VD->isStaticLocal();
+ // FIXME: What about CapturedDecls (and declarations nested within them)?
+ return isa<TagDecl>(D) || isa<BlockDecl>(D);
+ }
+
+ // Otherwise, we only care about anonymous class members / block-scope decls.
+ // FIXME: We need to handle lambdas and blocks within inline / templated
+ // variables too.
if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext()))
return false;
return isa<TagDecl>(D) || isa<FieldDecl>(D);
}
-
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
index 6aca453bbb89..12e26c1fc2b9 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
@@ -72,7 +72,7 @@ TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) {
unsigned ComputeHash(Selector Sel);
-/// \brief Retrieve the "definitive" declaration that provides all of the
+/// Retrieve the "definitive" declaration that provides all of the
/// visible entries for the given declaration context, if there is one.
///
/// The "definitive" declaration is the only place where we need to look to
@@ -84,14 +84,14 @@ unsigned ComputeHash(Selector Sel);
/// multiple definitions.
const DeclContext *getDefinitiveDeclContext(const DeclContext *DC);
-/// \brief Determine whether the given declaration kind is redeclarable.
+/// Determine whether the given declaration kind is redeclarable.
bool isRedeclarableDeclKind(unsigned Kind);
-/// \brief Determine whether the given declaration needs an anonymous
+/// Determine whether the given declaration needs an anonymous
/// declaration number.
bool needsAnonymousDeclarationNumber(const NamedDecl *D);
-/// \brief Visit each declaration within \c DC that needs an anonymous
+/// Visit each declaration within \c DC that needs an anonymous
/// declaration number and call \p Visit with the declaration and its number.
template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC,
Fn Visit) {
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index 4ed822e04f6c..723839ff62bf 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -61,7 +61,6 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VersionTuple.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
@@ -104,8 +103,9 @@
#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/Compression.h"
+#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
@@ -114,6 +114,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Timer.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -255,7 +256,7 @@ void ChainedASTReaderListener::readModuleFileExtension(
ASTReaderListener::~ASTReaderListener() = default;
-/// \brief Compare the given set of language options against an existing set of
+/// Compare the given set of language options against an existing set of
/// language options.
///
/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
@@ -359,7 +360,7 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
return false;
}
-/// \brief Compare the given set of target options against an existing set of
+/// Compare the given set of target options against an existing set of
/// target options.
///
/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
@@ -395,8 +396,8 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
ExistingTargetOpts.FeaturesAsWritten.end());
SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
TargetOpts.FeaturesAsWritten.end());
- std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
- std::sort(ReadFeatures.begin(), ReadFeatures.end());
+ llvm::sort(ExistingFeatures.begin(), ExistingFeatures.end());
+ llvm::sort(ReadFeatures.begin(), ReadFeatures.end());
// We compute the set difference in both directions explicitly so that we can
// diagnose the differences differently.
@@ -574,7 +575,7 @@ bool PCHValidator::ReadDiagnosticOptions(
Complain);
}
-/// \brief Collect the macro definitions provided by the given preprocessor
+/// Collect the macro definitions provided by the given preprocessor
/// options.
static void
collectMacroDefinitions(const PreprocessorOptions &PPOpts,
@@ -612,7 +613,7 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
}
}
-/// \brief Check the preprocessor options deserialized from the control block
+/// Check the preprocessor options deserialized from the control block
/// against the preprocessor options in an existing preprocessor.
///
/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
@@ -703,6 +704,17 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
// Compute the #include and #include_macros lines we need.
for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {
StringRef File = ExistingPPOpts.Includes[I];
+
+ if (!ExistingPPOpts.ImplicitPCHInclude.empty() &&
+ !ExistingPPOpts.PCHThroughHeader.empty()) {
+ // In case the through header is an include, we must add all the includes
+ // to the predefines so the start point can be determined.
+ SuggestedPredefines += "#include \"";
+ SuggestedPredefines += File;
+ SuggestedPredefines += "\"\n";
+ continue;
+ }
+
if (File == ExistingPPOpts.ImplicitPCHInclude)
continue;
@@ -870,7 +882,7 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
}
unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) {
- return llvm::HashString(a);
+ return llvm::djbHash(a);
}
std::pair<unsigned, unsigned>
@@ -888,7 +900,7 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) {
return StringRef((const char*) d, n-1);
}
-/// \brief Whether the given identifier is "interesting".
+/// Whether the given identifier is "interesting".
static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II,
bool IsModule) {
return II.hadMacroDefinition() ||
@@ -1211,7 +1223,7 @@ void ASTReader::Error(unsigned DiagID,
// Source Manager Deserialization
//===----------------------------------------------------------------------===//
-/// \brief Read the line table in the source manager block.
+/// Read the line table in the source manager block.
/// \returns true if there was an error.
bool ASTReader::ParseLineTable(ModuleFile &F,
const RecordData &Record) {
@@ -1257,7 +1269,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
return false;
}
-/// \brief Read a source manager block
+/// Read a source manager block
bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
using namespace SrcMgr;
@@ -1313,7 +1325,7 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
}
}
-/// \brief If a header file is not found at the path that we expect it to be
+/// If a header file is not found at the path that we expect it to be
/// and the PCH file was moved from its original location, try to resolve the
/// file by assuming that header+PCH were moved together and the header is in
/// the same place relative to the PCH.
@@ -1481,6 +1493,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
SourceMgr.createExpansionLoc(SpellingLoc,
ReadSourceLocation(*F, Record[2]),
ReadSourceLocation(*F, Record[3]),
+ Record[5],
Record[4],
ID,
BaseOffset + Record[0]);
@@ -1510,7 +1523,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
return std::make_pair(M->ImportLoc, StringRef(M->ModuleName));
}
-/// \brief Find the location where the module F is imported.
+/// Find the location where the module F is imported.
SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
if (F->ImportLoc.isValid())
return F->ImportLoc;
@@ -1856,7 +1869,7 @@ void ASTReader::ReadDefinedMacros() {
namespace {
- /// \brief Visitor class used to look up identifirs in an AST file.
+ /// Visitor class used to look up identifirs in an AST file.
class IdentifierLookupVisitor {
StringRef Name;
unsigned NameHash;
@@ -1900,7 +1913,7 @@ namespace {
return true;
}
- // \brief Retrieve the identifier info found within the module
+ // Retrieve the identifier info found within the module
// files.
IdentifierInfo *getIdentifierInfo() const { return Found; }
};
@@ -2136,7 +2149,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
}
// Check if there was a request to override the contents of the file
- // that was part of the precompiled header. Overridding such a file
+ // that was part of the precompiled header. Overriding such a file
// can lead to problems when lexing using the source locations from the
// PCH.
SourceManager &SM = getSourceManager();
@@ -2208,7 +2221,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
return IF;
}
-/// \brief If we are loading a relocatable PCH or module file, and the filename
+/// If we are loading a relocatable PCH or module file, and the filename
/// is not an absolute path, add the system or module root to the beginning of
/// the file name.
void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) {
@@ -2480,7 +2493,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return VersionMismatch;
}
- bool hasErrors = Record[6];
+ bool hasErrors = Record[7];
if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
Diag(diag::err_pch_with_compiler_errors);
return HadErrors;
@@ -2498,6 +2511,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.HasTimestamps = Record[5];
+ F.PCHHasObjectFile = Record[6];
+
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
@@ -2611,11 +2626,15 @@ ASTReader::ReadControlBlock(ModuleFile &F,
"MODULE_DIRECTORY found before MODULE_NAME");
// If we've already loaded a module map file covering this module, we may
// have a better path for it (relative to the current build).
- Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
+ Module *M = PP.getHeaderSearchInfo().lookupModule(
+ F.ModuleName, /*AllowSearch*/ true,
+ /*AllowExtraModuleMapSearch*/ true);
if (M && M->Directory) {
// If we're implicitly loading a module, the base directory can't
// change between the build and use.
- if (F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) {
+ // Don't emit module relocation error if we have -fno-validate-pch
+ if (!PP.getPreprocessorOpts().DisablePCHValidation &&
+ F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) {
const DirectoryEntry *BuildDir =
PP.getFileManager().getDirectory(Blob);
if (!BuildDir || BuildDir != M->Directory) {
@@ -3215,6 +3234,24 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
+ case PPD_SKIPPED_RANGES: {
+ F.PreprocessedSkippedRangeOffsets = (const PPSkippedRange*)Blob.data();
+ assert(Blob.size() % sizeof(PPSkippedRange) == 0);
+ F.NumPreprocessedSkippedRanges = Blob.size() / sizeof(PPSkippedRange);
+
+ if (!PP.getPreprocessingRecord())
+ PP.createPreprocessingRecord();
+ if (!PP.getPreprocessingRecord()->getExternalSource())
+ PP.getPreprocessingRecord()->SetExternalSource(*this);
+ F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord()
+ ->allocateSkippedRanges(F.NumPreprocessedSkippedRanges);
+
+ if (F.NumPreprocessedSkippedRanges > 0)
+ GlobalSkippedRangeMap.insert(
+ std::make_pair(F.BasePreprocessedSkippedRangeID, &F));
+ break;
+ }
+
case DECL_UPDATE_OFFSETS:
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
@@ -3567,7 +3604,8 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
- if (!ModMap) {
+ // Don't emit module relocation error if we have -fno-validate-pch
+ if (!PP.getPreprocessorOpts().DisablePCHValidation && !ModMap) {
assert(ImportedBy && "top-level import should be verified");
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
if (auto *ASTFE = M ? M->getASTFile() : nullptr) {
@@ -3648,7 +3686,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
return Success;
}
-/// \brief Move the given method to the back of the global list of methods.
+/// 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.
Sema::GlobalMethodPool::iterator Known
@@ -3801,7 +3839,7 @@ static void updateModuleTimestamp(ModuleFile &MF) {
OS.clear_error(); // Avoid triggering a fatal error.
}
-/// \brief Given a cursor at the start of an AST file, scan ahead and drop the
+/// Given a cursor at the start of an AST file, scan ahead and drop the
/// cursor into the start of the given block ID, returning false on success and
/// true on failure.
static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
@@ -4068,7 +4106,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
static ASTFileSignature readASTFileSignature(StringRef PCH);
-/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
+/// Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
return Stream.canSkipToPos(4) &&
Stream.Read(8) == 'C' &&
@@ -4559,7 +4597,7 @@ void ASTReader::finalizeForWriting() {
// Nothing to do for now.
}
-/// \brief Reads and return the signature record from \p PCH's control block, or
+/// Reads and return the signature record from \p PCH's control block, or
/// else returns 0.
static ASTFileSignature readASTFileSignature(StringRef PCH) {
BitstreamCursor Stream(PCH);
@@ -4585,7 +4623,7 @@ static ASTFileSignature readASTFileSignature(StringRef PCH) {
}
}
-/// \brief Retrieve the name of the original source file name
+/// Retrieve the name of the original source file name
/// directly from the AST file, without actually loading the AST
/// file.
std::string ASTReader::getOriginalSourceFile(
@@ -4791,7 +4829,8 @@ bool ASTReader::readASTFileControlBlock(
unsigned NumInputFiles = Record[0];
unsigned NumUserFiles = Record[1];
- const uint64_t *InputFileOffs = (const uint64_t *)Blob.data();
+ const llvm::support::unaligned_uint64_t *InputFileOffs =
+ (const llvm::support::unaligned_uint64_t *)Blob.data();
for (unsigned I = 0; I != NumInputFiles; ++I) {
// Go find this input file.
bool isSystemFile = I >= NumUserFiles;
@@ -4961,7 +5000,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SUBMODULE_DEFINITION: {
- if (Record.size() < 8) {
+ if (Record.size() < 12) {
Error("malformed module definition");
return Failure;
}
@@ -4979,6 +5018,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
bool InferExplicitSubmodules = Record[Idx++];
bool InferExportWildcard = Record[Idx++];
bool ConfigMacrosExhaustive = Record[Idx++];
+ bool ModuleMapIsPrivate = Record[Idx++];
Module *ParentModule = nullptr;
if (Parent)
@@ -5002,7 +5042,9 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
if (!ParentModule) {
if (const FileEntry *CurFile = CurrentModule->getASTFile()) {
- if (CurFile != F.File) {
+ // Don't emit module relocation error if we have -fno-validate-pch
+ if (!PP.getPreprocessorOpts().DisablePCHValidation &&
+ CurFile != F.File) {
if (!Diags.isDiagnosticInFlight()) {
Diag(diag::err_module_file_conflict)
<< CurrentModule->getTopLevelModuleName()
@@ -5026,6 +5068,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
CurrentModule->InferExportWildcard = InferExportWildcard;
CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive;
+ CurrentModule->ModuleMapIsPrivate = ModuleMapIsPrivate;
if (DeserializationListener)
DeserializationListener->ModuleRead(GlobalID, CurrentModule);
@@ -5152,6 +5195,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SUBMODULE_LINK_LIBRARY:
+ ModMap.resolveLinkAsDependencies(CurrentModule);
CurrentModule->LinkLibraries.push_back(
Module::LinkLibrary(Blob, Record[0]));
break;
@@ -5184,12 +5228,13 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case SUBMODULE_EXPORT_AS:
CurrentModule->ExportAsModule = Blob.str();
+ ModMap.addLinkAsDependency(CurrentModule);
break;
}
}
}
-/// \brief Parse the record that corresponds to a LangOptions data
+/// Parse the record that corresponds to a LangOptions data
/// structure.
///
/// This routine parses the language options from the AST file and then gives
@@ -5387,6 +5432,20 @@ ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
Mod.FileSortedDecls + Mod.NumFileSortedDecls));
}
+SourceRange ASTReader::ReadSkippedRange(unsigned GlobalIndex) {
+ auto I = GlobalSkippedRangeMap.find(GlobalIndex);
+ assert(I != GlobalSkippedRangeMap.end() &&
+ "Corrupted global skipped range map");
+ ModuleFile *M = I->second;
+ unsigned LocalIndex = GlobalIndex - M->BasePreprocessedSkippedRangeID;
+ assert(LocalIndex < M->NumPreprocessedSkippedRanges);
+ PPSkippedRange RawRange = M->PreprocessedSkippedRangeOffsets[LocalIndex];
+ SourceRange Range(TranslateSourceLocation(*M, RawRange.getBegin()),
+ TranslateSourceLocation(*M, RawRange.getEnd()));
+ assert(Range.isValid());
+ return Range;
+}
+
PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
PreprocessedEntityID PPID = Index+1;
std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
@@ -5474,7 +5533,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
llvm_unreachable("Invalid PreprocessorDetailRecordTypes");
}
-/// \brief Find the next module that contains entities and return the ID
+/// 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
@@ -5577,7 +5636,7 @@ PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc,
return M.BasePreprocessedEntityID + (PPI - pp_begin);
}
-/// \brief Returns a pair of [Begin, End) indices of preallocated
+/// Returns a pair of [Begin, End) indices of preallocated
/// preprocessed entities that \arg Range encompasses.
std::pair<unsigned, unsigned>
ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) {
@@ -5591,7 +5650,7 @@ std::pair<unsigned, unsigned>
return std::make_pair(BeginID, EndID);
}
-/// \brief Optionally returns true or false if the preallocated preprocessed
+/// Optionally returns true or false if the preallocated preprocessed
/// entity with index \arg Index came from file \arg FID.
Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
FileID FID) {
@@ -5615,7 +5674,7 @@ Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
namespace {
- /// \brief Visitor used to search for information about a header file.
+ /// Visitor used to search for information about a header file.
class HeaderFileInfoVisitor {
const FileEntry *FE;
Optional<HeaderFileInfo> HFI;
@@ -5729,6 +5788,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
Initial.ExtBehavior = (diag::Severity)Flags;
FirstState = ReadDiagState(Initial, SourceLocation(), true);
+ assert(F.OriginalSourceFileID.isValid());
+
// Set up the root buffer of the module to start with the initial
// diagnostic state of the module itself, to cover files that contain no
// explicit transitions (for which we did not serialize anything).
@@ -5749,6 +5810,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
"Invalid data, missing pragma diagnostic states");
SourceLocation Loc = ReadSourceLocation(F, Record[Idx++]);
auto IDAndOffset = SourceMgr.getDecomposedLoc(Loc);
+ assert(IDAndOffset.first.isValid() && "invalid FileID for transition");
assert(IDAndOffset.second == 0 && "not a start location for a FileID");
unsigned Transitions = Record[Idx++];
@@ -5792,7 +5854,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
}
}
-/// \brief Get the correct cursor and offset for loading a type.
+/// Get the correct cursor and offset for loading a type.
ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index);
assert(I != GlobalTypeMap.end() && "Corrupted global type map");
@@ -5800,7 +5862,7 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]);
}
-/// \brief Read and return the type with the given index..
+/// Read and return the type with the given index..
///
/// The index is the type ID, shifted and minus the number of predefs. This
/// routine actually reads the record corresponding to the type at the given
@@ -5969,13 +6031,14 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
}
case TYPE_FUNCTION_NO_PROTO: {
- if (Record.size() != 7) {
+ if (Record.size() != 8) {
Error("incorrect encoding of no-proto function type");
return QualType();
}
QualType ResultType = readType(*Loc.F, Record, Idx);
FunctionType::ExtInfo Info(Record[1], Record[2], Record[3],
- (CallingConv)Record[4], Record[5], Record[6]);
+ (CallingConv)Record[4], Record[5], Record[6],
+ Record[7]);
return Context.getFunctionNoProtoType(ResultType, Info);
}
@@ -5988,9 +6051,10 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
/*regparm*/ Record[3],
static_cast<CallingConv>(Record[4]),
/*produces*/ Record[5],
- /*nocallersavedregs*/ Record[6]);
+ /*nocallersavedregs*/ Record[6],
+ /*nocfcheck*/ Record[7]);
- unsigned Idx = 7;
+ unsigned Idx = 8;
EPI.Variadic = Record[Idx++];
EPI.HasTrailingReturn = Record[Idx++];
@@ -6142,7 +6206,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
QualType NamedType = readType(*Loc.F, Record, Idx);
- return Context.getElaboratedType(Keyword, NNS, NamedType);
+ TagDecl *OwnedTagDecl = ReadDeclAs<TagDecl>(*Loc.F, Record, Idx);
+ return Context.getElaboratedType(Keyword, NNS, NamedType, OwnedTagDecl);
}
case TYPE_OBJC_INTERFACE: {
@@ -6311,6 +6376,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return Context.getPipeType(ElementType, ReadOnly);
}
+ case TYPE_DEPENDENT_SIZED_VECTOR: {
+ unsigned Idx = 0;
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ Expr *SizeExpr = ReadExpr(*Loc.F);
+ SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx);
+ unsigned VecKind = Record[Idx];
+
+ return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc,
+ (VectorType::VectorKind)VecKind);
+ }
+
case TYPE_DEPENDENT_SIZED_EXT_VECTOR: {
unsigned Idx = 0;
@@ -6349,7 +6425,7 @@ void ASTReader::readExceptionSpec(ModuleFile &ModuleFile,
for (unsigned I = 0, N = Record[Idx++]; I != N; ++I)
Exceptions.push_back(readType(ModuleFile, Record, Idx));
ESI.Exceptions = Exceptions;
- } else if (EST == EST_ComputedNoexcept) {
+ } else if (isComputedNoexcept(EST)) {
ESI.NoexceptExpr = ReadExpr(ModuleFile);
} else if (EST == EST_Uninstantiated) {
ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
@@ -6491,6 +6567,11 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
+void TypeLocReader::VisitDependentVectorTypeLoc(
+ DependentVectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation());
+}
+
void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
@@ -6686,6 +6767,13 @@ void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
TL.setKWLoc(ReadSourceLocation());
}
+void ASTReader::ReadTypeLoc(ModuleFile &F, const ASTReader::RecordData &Record,
+ unsigned &Idx, TypeLoc TL) {
+ TypeLocReader TLR(F, *this, Record, Idx);
+ for (; !TL.isNull(); TL = TL.getNextTypeLoc())
+ TLR.Visit(TL);
+}
+
TypeSourceInfo *
ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record,
unsigned &Idx) {
@@ -6694,9 +6782,7 @@ ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record,
return nullptr;
TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);
- TypeLocReader TLR(F, *this, Record, Idx);
- for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
- TLR.Visit(TL);
+ ReadTypeLoc(F, Record, Idx, TInfo->getTypeLoc());
return TInfo;
}
@@ -6774,6 +6860,78 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_LONGDOUBLE_ID:
T = Context.LongDoubleTy;
break;
+ case PREDEF_TYPE_SHORT_ACCUM_ID:
+ T = Context.ShortAccumTy;
+ break;
+ case PREDEF_TYPE_ACCUM_ID:
+ T = Context.AccumTy;
+ break;
+ case PREDEF_TYPE_LONG_ACCUM_ID:
+ T = Context.LongAccumTy;
+ break;
+ case PREDEF_TYPE_USHORT_ACCUM_ID:
+ T = Context.UnsignedShortAccumTy;
+ break;
+ case PREDEF_TYPE_UACCUM_ID:
+ T = Context.UnsignedAccumTy;
+ break;
+ case PREDEF_TYPE_ULONG_ACCUM_ID:
+ T = Context.UnsignedLongAccumTy;
+ break;
+ case PREDEF_TYPE_SHORT_FRACT_ID:
+ T = Context.ShortFractTy;
+ break;
+ case PREDEF_TYPE_FRACT_ID:
+ T = Context.FractTy;
+ break;
+ case PREDEF_TYPE_LONG_FRACT_ID:
+ T = Context.LongFractTy;
+ break;
+ case PREDEF_TYPE_USHORT_FRACT_ID:
+ T = Context.UnsignedShortFractTy;
+ break;
+ case PREDEF_TYPE_UFRACT_ID:
+ T = Context.UnsignedFractTy;
+ break;
+ case PREDEF_TYPE_ULONG_FRACT_ID:
+ T = Context.UnsignedLongFractTy;
+ break;
+ case PREDEF_TYPE_SAT_SHORT_ACCUM_ID:
+ T = Context.SatShortAccumTy;
+ break;
+ case PREDEF_TYPE_SAT_ACCUM_ID:
+ T = Context.SatAccumTy;
+ break;
+ case PREDEF_TYPE_SAT_LONG_ACCUM_ID:
+ T = Context.SatLongAccumTy;
+ break;
+ case PREDEF_TYPE_SAT_USHORT_ACCUM_ID:
+ T = Context.SatUnsignedShortAccumTy;
+ break;
+ case PREDEF_TYPE_SAT_UACCUM_ID:
+ T = Context.SatUnsignedAccumTy;
+ break;
+ case PREDEF_TYPE_SAT_ULONG_ACCUM_ID:
+ T = Context.SatUnsignedLongAccumTy;
+ break;
+ case PREDEF_TYPE_SAT_SHORT_FRACT_ID:
+ T = Context.SatShortFractTy;
+ break;
+ case PREDEF_TYPE_SAT_FRACT_ID:
+ T = Context.SatFractTy;
+ break;
+ case PREDEF_TYPE_SAT_LONG_FRACT_ID:
+ T = Context.SatLongFractTy;
+ break;
+ case PREDEF_TYPE_SAT_USHORT_FRACT_ID:
+ T = Context.SatUnsignedShortFractTy;
+ break;
+ case PREDEF_TYPE_SAT_UFRACT_ID:
+ T = Context.SatUnsignedFractTy;
+ break;
+ case PREDEF_TYPE_SAT_ULONG_FRACT_ID:
+ T = Context.SatUnsignedLongFractTy;
+ break;
case PREDEF_TYPE_FLOAT16_ID:
T = Context.Float16Ty;
break;
@@ -6798,6 +6956,9 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_NULLPTR_ID:
T = Context.NullPtrTy;
break;
+ case PREDEF_TYPE_CHAR8_ID:
+ T = Context.Char8Ty;
+ break;
case PREDEF_TYPE_CHAR16_ID:
T = Context.Char16Ty;
break;
@@ -7239,7 +7400,7 @@ serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F,
return getGlobalDeclID(F, Record[Idx++]);
}
-/// \brief Resolve the offset of a statement into a statement.
+/// Resolve the offset of a statement into a statement.
///
/// This operation will read a new statement from the external
/// source each time it is called, and is meant to be used via a
@@ -7432,7 +7593,7 @@ ASTReader::getLoadedLookupTables(DeclContext *Primary) const {
return I == Lookups.end() ? nullptr : &I->second;
}
-/// \brief Under non-PCH compilation the consumer receives the objc methods
+/// Under non-PCH compilation the consumer receives the objc methods
/// before receiving the implementation, and codegen depends on this.
/// We simulate this by deserializing and passing to consumer the methods of the
/// implementation before passing the deserialized implementation decl.
@@ -7735,25 +7896,25 @@ IdentifierInfo *ASTReader::get(StringRef Name) {
namespace clang {
- /// \brief An identifier-lookup iterator that enumerates all of the
+ /// An identifier-lookup iterator that enumerates all of the
/// identifiers stored within a set of AST files.
class ASTIdentifierIterator : public IdentifierIterator {
- /// \brief The AST reader whose identifiers are being enumerated.
+ /// The AST reader whose identifiers are being enumerated.
const ASTReader &Reader;
- /// \brief The current index into the chain of AST files stored in
+ /// The current index into the chain of AST files stored in
/// the AST reader.
unsigned Index;
- /// \brief The current position within the identifier lookup table
+ /// The current position within the identifier lookup table
/// of the current AST file.
ASTIdentifierLookupTable::key_iterator Current;
- /// \brief The end position within the identifier lookup table of
+ /// The end position within the identifier lookup table of
/// the current AST file.
ASTIdentifierLookupTable::key_iterator End;
- /// \brief Whether to skip any modules in the ASTReader.
+ /// Whether to skip any modules in the ASTReader.
bool SkipModules;
public:
@@ -7889,12 +8050,12 @@ namespace serialization {
return true;
}
- /// \brief Retrieve the instance methods found by this visitor.
+ /// Retrieve the instance methods found by this visitor.
ArrayRef<ObjCMethodDecl *> getInstanceMethods() const {
return InstanceMethods;
}
- /// \brief Retrieve the instance methods found by this visitor.
+ /// Retrieve the instance methods found by this visitor.
ArrayRef<ObjCMethodDecl *> getFactoryMethods() const {
return FactoryMethods;
}
@@ -7912,7 +8073,7 @@ namespace serialization {
} // namespace serialization
} // namespace clang
-/// \brief Add the given set of methods to the method list.
+/// Add the given set of methods to the method list.
static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
ObjCMethodList &List) {
for (unsigned I = 0, N = Methods.size(); I != N; ++I) {
@@ -8151,7 +8312,7 @@ void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) {
DeserializationListener->IdentifierRead(ID, II);
}
-/// \brief Set the globally-visible declarations associated with the given
+/// Set the globally-visible declarations associated with the given
/// identifier.
///
/// If the AST reader is currently in a state where the given declaration IDs
@@ -8328,6 +8489,11 @@ Module *ASTReader::getModule(unsigned ID) {
return getSubmodule(ID);
}
+bool ASTReader::DeclIsFromPCHWithObjectFile(const Decl *D) {
+ ModuleFile *MF = getOwningModuleFile(D);
+ return MF && MF->PCHHasObjectFile;
+}
+
ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) {
if (ID & 1) {
// It's a module, look it up by submodule ID.
@@ -8682,7 +8848,7 @@ ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx, Canonicalize));
}
-/// \brief Read a UnresolvedSet structure.
+/// Read a UnresolvedSet structure.
void ASTReader::ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
const RecordData &Record, unsigned &Idx) {
unsigned NumDecls = Record[Idx++];
@@ -8903,7 +9069,7 @@ ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
return SourceRange(beg, end);
}
-/// \brief Read an integral value
+/// Read an integral value
llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
unsigned BitWidth = Record[Idx++];
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
@@ -8912,20 +9078,20 @@ llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
return Result;
}
-/// \brief Read a signed integral value
+/// Read a signed integral value
llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
bool isUnsigned = Record[Idx++];
return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
}
-/// \brief Read a floating-point value
+/// Read a floating-point value
llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record,
const llvm::fltSemantics &Sem,
unsigned &Idx) {
return llvm::APFloat(Sem, ReadAPInt(Record, Idx));
}
-// \brief Read a string
+// Read a string
std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
unsigned Len = Record[Idx++];
std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
@@ -8967,13 +9133,13 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const {
return Diags.Report(Loc, DiagID);
}
-/// \brief Retrieve the identifier table associated with the
+/// Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &ASTReader::getIdentifierTable() {
return PP.getIdentifierTable();
}
-/// \brief Record that the given ID maps to the given switch-case
+/// Record that the given ID maps to the given switch-case
/// statement.
void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
assert((*CurrSwitchCaseStmts)[ID] == nullptr &&
@@ -8981,7 +9147,7 @@ void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
(*CurrSwitchCaseStmts)[ID] = SC;
}
-/// \brief Retrieve the switch-case statement with the given ID.
+/// Retrieve the switch-case statement with the given ID.
SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
assert((*CurrSwitchCaseStmts)[ID] != nullptr && "No SwitchCase with this ID");
return (*CurrSwitchCaseStmts)[ID];
@@ -9032,8 +9198,7 @@ void ASTReader::ReadComments() {
bool IsTrailingComment = Record[Idx++];
bool IsAlmostTrailingComment = Record[Idx++];
Comments.push_back(new (Context) RawComment(
- SR, Kind, IsTrailingComment, IsAlmostTrailingComment,
- Context.getLangOpts().CommentOpts.ParseAllComments));
+ SR, Kind, IsTrailingComment, IsAlmostTrailingComment));
break;
}
}
@@ -9041,8 +9206,8 @@ void ASTReader::ReadComments() {
NextCursor:
// De-serialized SourceLocations get negative FileIDs for other modules,
// potentially invalidating the original order. Sort it again.
- std::sort(Comments.begin(), Comments.end(),
- BeforeThanCompare<RawComment>(SourceMgr));
+ llvm::sort(Comments.begin(), Comments.end(),
+ BeforeThanCompare<RawComment>(SourceMgr));
Context.Comments.addDeserializedComments(Comments);
}
}
@@ -9230,6 +9395,19 @@ void ASTReader::finishPendingActions() {
PBEnd = PendingBodies.end();
PB != PBEnd; ++PB) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
+ // For a function defined inline within a class template, force the
+ // canonical definition to be the one inside the canonical definition of
+ // the template. This ensures that we instantiate from a correct view
+ // of the template.
+ //
+ // Sadly we can't do this more generally: we can't be sure that all
+ // copies of an arbitrary class definition will have the same members
+ // defined (eg, some member functions may not be instantiated, and some
+ // special members may or may not have been implicitly defined).
+ if (auto *RD = dyn_cast<CXXRecordDecl>(FD->getLexicalParent()))
+ if (RD->isDependentContext() && !RD->isThisDeclarationADefinition())
+ continue;
+
// FIXME: Check for =delete/=default?
// FIXME: Complain about ODR violations here?
const FunctionDecl *Defn = nullptr;
@@ -9242,7 +9420,15 @@ void ASTReader::finishPendingActions() {
if (!FD->isLateTemplateParsed() &&
!NonConstDefn->isLateTemplateParsed() &&
FD->getODRHash() != NonConstDefn->getODRHash()) {
- PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
+ if (!isa<CXXMethodDecl>(FD)) {
+ PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
+ } else if (FD->getLexicalParent()->isFileContext() &&
+ NonConstDefn->getLexicalParent()->isFileContext()) {
+ // Only diagnose out-of-line method definitions. If they are
+ // in class definitions, then an error will be generated when
+ // processing the class bodies.
+ PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
+ }
}
}
continue;
@@ -9262,7 +9448,8 @@ void ASTReader::finishPendingActions() {
void ASTReader::diagnoseOdrViolations() {
if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() &&
- PendingFunctionOdrMergeFailures.empty())
+ PendingFunctionOdrMergeFailures.empty() &&
+ PendingEnumOdrMergeFailures.empty())
return;
// Trigger the import of the full definition of each class that had any
@@ -9298,6 +9485,16 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+ // Trigger the import of enums.
+ auto EnumOdrMergeFailures = std::move(PendingEnumOdrMergeFailures);
+ PendingEnumOdrMergeFailures.clear();
+ for (auto &Merge : EnumOdrMergeFailures) {
+ Merge.first->decls_begin();
+ for (auto &Enum : Merge.second) {
+ Enum->decls_begin();
+ }
+ }
+
// For each declaration from a merged context, check that the canonical
// definition of that context also contains a declaration of the same
// entity.
@@ -9380,7 +9577,8 @@ void ASTReader::diagnoseOdrViolations() {
}
}
- if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty())
+ if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty() &&
+ EnumOdrMergeFailures.empty())
return;
// Ensure we don't accidentally recursively enter deserialization while
@@ -9409,6 +9607,20 @@ void ASTReader::diagnoseOdrViolations() {
return Hash.CalculateHash();
};
+ auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) {
+ Hash.clear();
+ Hash.AddTemplateArgument(TA);
+ return Hash.CalculateHash();
+ };
+
+ auto ComputeTemplateParameterListODRHash =
+ [&Hash](const TemplateParameterList *TPL) {
+ assert(TPL);
+ Hash.clear();
+ Hash.AddTemplateParameterList(TPL);
+ return Hash.CalculateHash();
+ };
+
// Issue any pending ODR-failure diagnostics.
for (auto &Merge : OdrMergeFailures) {
// If we've already pointed out a specific problem with this class, don't
@@ -9761,6 +9973,7 @@ void ASTReader::diagnoseOdrViolations() {
TypeDef,
Var,
Friend,
+ FunctionTemplate,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
@@ -9798,6 +10011,8 @@ void ASTReader::diagnoseOdrViolations() {
return Var;
case Decl::Friend:
return Friend;
+ case Decl::FunctionTemplate:
+ return FunctionTemplate;
}
};
@@ -9884,7 +10099,7 @@ void ASTReader::diagnoseOdrViolations() {
// Used with err_module_odr_violation_mismatch_decl_diff and
// note_module_odr_violation_mismatch_decl_diff
- enum ODRDeclDifference{
+ enum ODRDeclDifference {
StaticAssertCondition,
StaticAssertMessage,
StaticAssertOnlyMessage,
@@ -9897,6 +10112,7 @@ void ASTReader::diagnoseOdrViolations() {
FieldDifferentInitializers,
MethodName,
MethodDeleted,
+ MethodDefaulted,
MethodVirtual,
MethodStatic,
MethodVolatile,
@@ -9907,6 +10123,11 @@ void ASTReader::diagnoseOdrViolations() {
MethodParameterName,
MethodParameterSingleDefaultArgument,
MethodParameterDifferentDefaultArgument,
+ MethodNoTemplateArguments,
+ MethodDifferentNumberTemplateArguments,
+ MethodDifferentTemplateArgument,
+ MethodSingleBody,
+ MethodDifferentBody,
TypedefName,
TypedefType,
VarName,
@@ -9917,6 +10138,13 @@ void ASTReader::diagnoseOdrViolations() {
FriendTypeFunction,
FriendType,
FriendFunction,
+ FunctionTemplateDifferentNumberParameters,
+ FunctionTemplateParameterDifferentKind,
+ FunctionTemplateParameterName,
+ FunctionTemplateParameterSingleDefaultArgument,
+ FunctionTemplateParameterDifferentDefaultArgument,
+ FunctionTemplateParameterDifferentType,
+ FunctionTemplatePackParameter,
};
// These lambdas have the common portions of the ODR diagnostics. This
@@ -10133,8 +10361,8 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- const bool FirstDeleted = FirstMethod->isDeleted();
- const bool SecondDeleted = SecondMethod->isDeleted();
+ const bool FirstDeleted = FirstMethod->isDeletedAsWritten();
+ const bool SecondDeleted = SecondMethod->isDeletedAsWritten();
if (FirstDeleted != SecondDeleted) {
ODRDiagError(FirstMethod->getLocation(),
FirstMethod->getSourceRange(), MethodDeleted)
@@ -10147,6 +10375,20 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
+ const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted();
+ const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted();
+ if (FirstDefaulted != SecondDefaulted) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(), MethodDefaulted)
+ << FirstMethodType << FirstName << FirstDefaulted;
+
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(), MethodDefaulted)
+ << SecondMethodType << SecondName << SecondDefaulted;
+ Diagnosed = true;
+ break;
+ }
+
const bool FirstVirtual = FirstMethod->isVirtualAsWritten();
const bool SecondVirtual = SecondMethod->isVirtualAsWritten();
const bool FirstPure = FirstMethod->isPure();
@@ -10329,6 +10571,127 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
+ const auto *FirstTemplateArgs =
+ FirstMethod->getTemplateSpecializationArgs();
+ const auto *SecondTemplateArgs =
+ SecondMethod->getTemplateSpecializationArgs();
+
+ if ((FirstTemplateArgs && !SecondTemplateArgs) ||
+ (!FirstTemplateArgs && SecondTemplateArgs)) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(), MethodNoTemplateArguments)
+ << FirstMethodType << FirstName << (FirstTemplateArgs != nullptr);
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(), MethodNoTemplateArguments)
+ << SecondMethodType << SecondName
+ << (SecondTemplateArgs != nullptr);
+
+ Diagnosed = true;
+ break;
+ }
+
+ if (FirstTemplateArgs && SecondTemplateArgs) {
+ // Remove pack expansions from argument list.
+ auto ExpandTemplateArgumentList =
+ [](const TemplateArgumentList *TAL) {
+ llvm::SmallVector<const TemplateArgument *, 8> ExpandedList;
+ for (const TemplateArgument &TA : TAL->asArray()) {
+ if (TA.getKind() != TemplateArgument::Pack) {
+ ExpandedList.push_back(&TA);
+ continue;
+ }
+ for (const TemplateArgument &PackTA : TA.getPackAsArray()) {
+ ExpandedList.push_back(&PackTA);
+ }
+ }
+ return ExpandedList;
+ };
+ llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList =
+ ExpandTemplateArgumentList(FirstTemplateArgs);
+ llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList =
+ ExpandTemplateArgumentList(SecondTemplateArgs);
+
+ if (FirstExpandedList.size() != SecondExpandedList.size()) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(),
+ MethodDifferentNumberTemplateArguments)
+ << FirstMethodType << FirstName
+ << (unsigned)FirstExpandedList.size();
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(),
+ MethodDifferentNumberTemplateArguments)
+ << SecondMethodType << SecondName
+ << (unsigned)SecondExpandedList.size();
+
+ Diagnosed = true;
+ break;
+ }
+
+ bool TemplateArgumentMismatch = false;
+ for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {
+ const TemplateArgument &FirstTA = *FirstExpandedList[i],
+ &SecondTA = *SecondExpandedList[i];
+ if (ComputeTemplateArgumentODRHash(FirstTA) ==
+ ComputeTemplateArgumentODRHash(SecondTA)) {
+ continue;
+ }
+
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(),
+ MethodDifferentTemplateArgument)
+ << FirstMethodType << FirstName << FirstTA << i + 1;
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(),
+ MethodDifferentTemplateArgument)
+ << SecondMethodType << SecondName << SecondTA << i + 1;
+
+ TemplateArgumentMismatch = true;
+ break;
+ }
+
+ if (TemplateArgumentMismatch) {
+ Diagnosed = true;
+ break;
+ }
+ }
+
+ // Compute the hash of the method as if it has no body.
+ auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) {
+ Hash.clear();
+ Hash.AddFunctionDecl(D, true /*SkipBody*/);
+ return Hash.CalculateHash();
+ };
+
+ // Compare the hash generated to the hash stored. A difference means
+ // that a body was present in the original source. Due to merging,
+ // the stardard way of detecting a body will not work.
+ const bool HasFirstBody =
+ ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash();
+ const bool HasSecondBody =
+ ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash();
+
+ if (HasFirstBody != HasSecondBody) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(), MethodSingleBody)
+ << FirstMethodType << FirstName << HasFirstBody;
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(), MethodSingleBody)
+ << SecondMethodType << SecondName << HasSecondBody;
+ Diagnosed = true;
+ break;
+ }
+
+ if (HasFirstBody && HasSecondBody) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(), MethodDifferentBody)
+ << FirstMethodType << FirstName;
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(), MethodDifferentBody)
+ << SecondMethodType << SecondName;
+ Diagnosed = true;
+ break;
+ }
+
break;
}
case TypeAlias:
@@ -10481,6 +10844,305 @@ void ASTReader::diagnoseOdrViolations() {
Diagnosed = true;
break;
}
+ case FunctionTemplate: {
+ FunctionTemplateDecl *FirstTemplate =
+ cast<FunctionTemplateDecl>(FirstDecl);
+ FunctionTemplateDecl *SecondTemplate =
+ cast<FunctionTemplateDecl>(SecondDecl);
+
+ TemplateParameterList *FirstTPL =
+ FirstTemplate->getTemplateParameters();
+ TemplateParameterList *SecondTPL =
+ SecondTemplate->getTemplateParameters();
+
+ if (FirstTPL->size() != SecondTPL->size()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateDifferentNumberParameters)
+ << FirstTemplate << FirstTPL->size();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateDifferentNumberParameters)
+ << SecondTemplate << SecondTPL->size();
+
+ Diagnosed = true;
+ break;
+ }
+
+ bool ParameterMismatch = false;
+ for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {
+ NamedDecl *FirstParam = FirstTPL->getParam(i);
+ NamedDecl *SecondParam = SecondTPL->getParam(i);
+
+ if (FirstParam->getKind() != SecondParam->getKind()) {
+ enum {
+ TemplateTypeParameter,
+ NonTypeTemplateParameter,
+ TemplateTemplateParameter,
+ };
+ auto GetParamType = [](NamedDecl *D) {
+ switch (D->getKind()) {
+ default:
+ llvm_unreachable("Unexpected template parameter type");
+ case Decl::TemplateTypeParm:
+ return TemplateTypeParameter;
+ case Decl::NonTypeTemplateParm:
+ return NonTypeTemplateParameter;
+ case Decl::TemplateTemplateParm:
+ return TemplateTemplateParameter;
+ }
+ };
+
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentKind)
+ << FirstTemplate << (i + 1) << GetParamType(FirstParam);
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentKind)
+ << SecondTemplate << (i + 1) << GetParamType(SecondParam);
+
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (FirstParam->getName() != SecondParam->getName()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterName)
+ << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier()
+ << FirstParam;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterName)
+ << SecondTemplate << (i + 1)
+ << (bool)SecondParam->getIdentifier() << SecondParam;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (isa<TemplateTypeParmDecl>(FirstParam) &&
+ isa<TemplateTypeParmDecl>(SecondParam)) {
+ TemplateTypeParmDecl *FirstTTPD =
+ cast<TemplateTypeParmDecl>(FirstParam);
+ TemplateTypeParmDecl *SecondTTPD =
+ cast<TemplateTypeParmDecl>(SecondParam);
+ bool HasFirstDefaultArgument =
+ FirstTTPD->hasDefaultArgument() &&
+ !FirstTTPD->defaultArgumentWasInherited();
+ bool HasSecondDefaultArgument =
+ SecondTTPD->hasDefaultArgument() &&
+ !SecondTTPD->defaultArgumentWasInherited();
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+ QualType FirstType = FirstTTPD->getDefaultArgument();
+ QualType SecondType = SecondTTPD->getDefaultArgument();
+ if (ComputeQualTypeODRHash(FirstType) !=
+ ComputeQualTypeODRHash(SecondType)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << FirstTemplate << (i + 1) << FirstType;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << SecondTemplate << (i + 1) << SecondType;
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (FirstTTPD->isParameterPack() !=
+ SecondTTPD->isParameterPack()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (isa<TemplateTemplateParmDecl>(FirstParam) &&
+ isa<TemplateTemplateParmDecl>(SecondParam)) {
+ TemplateTemplateParmDecl *FirstTTPD =
+ cast<TemplateTemplateParmDecl>(FirstParam);
+ TemplateTemplateParmDecl *SecondTTPD =
+ cast<TemplateTemplateParmDecl>(SecondParam);
+
+ TemplateParameterList *FirstTPL =
+ FirstTTPD->getTemplateParameters();
+ TemplateParameterList *SecondTPL =
+ SecondTTPD->getTemplateParameters();
+
+ if (ComputeTemplateParameterListODRHash(FirstTPL) !=
+ ComputeTemplateParameterListODRHash(SecondTPL)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << FirstTemplate << (i + 1);
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << SecondTemplate << (i + 1);
+ ParameterMismatch = true;
+ break;
+ }
+
+ bool HasFirstDefaultArgument =
+ FirstTTPD->hasDefaultArgument() &&
+ !FirstTTPD->defaultArgumentWasInherited();
+ bool HasSecondDefaultArgument =
+ SecondTTPD->hasDefaultArgument() &&
+ !SecondTTPD->defaultArgumentWasInherited();
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+ TemplateArgument FirstTA =
+ FirstTTPD->getDefaultArgument().getArgument();
+ TemplateArgument SecondTA =
+ SecondTTPD->getDefaultArgument().getArgument();
+ if (ComputeTemplateArgumentODRHash(FirstTA) !=
+ ComputeTemplateArgumentODRHash(SecondTA)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << FirstTemplate << (i + 1) << FirstTA;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << SecondTemplate << (i + 1) << SecondTA;
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (FirstTTPD->isParameterPack() !=
+ SecondTTPD->isParameterPack()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (isa<NonTypeTemplateParmDecl>(FirstParam) &&
+ isa<NonTypeTemplateParmDecl>(SecondParam)) {
+ NonTypeTemplateParmDecl *FirstNTTPD =
+ cast<NonTypeTemplateParmDecl>(FirstParam);
+ NonTypeTemplateParmDecl *SecondNTTPD =
+ cast<NonTypeTemplateParmDecl>(SecondParam);
+
+ QualType FirstType = FirstNTTPD->getType();
+ QualType SecondType = SecondNTTPD->getType();
+ if (ComputeQualTypeODRHash(FirstType) !=
+ ComputeQualTypeODRHash(SecondType)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << FirstTemplate << (i + 1);
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << SecondTemplate << (i + 1);
+ ParameterMismatch = true;
+ break;
+ }
+
+ bool HasFirstDefaultArgument =
+ FirstNTTPD->hasDefaultArgument() &&
+ !FirstNTTPD->defaultArgumentWasInherited();
+ bool HasSecondDefaultArgument =
+ SecondNTTPD->hasDefaultArgument() &&
+ !SecondNTTPD->defaultArgumentWasInherited();
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+ Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
+ Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
+ if (ComputeODRHash(FirstDefaultArgument) !=
+ ComputeODRHash(SecondDefaultArgument)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << FirstTemplate << (i + 1) << FirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << SecondTemplate << (i + 1) << SecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (FirstNTTPD->isParameterPack() !=
+ SecondNTTPD->isParameterPack()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << SecondTemplate << (i + 1)
+ << SecondNTTPD->isParameterPack();
+ ParameterMismatch = true;
+ break;
+ }
+ }
+ }
+
+ if (ParameterMismatch) {
+ Diagnosed = true;
+ break;
+ }
+
+ break;
+ }
}
if (Diagnosed)
@@ -10660,6 +11322,195 @@ void ASTReader::diagnoseOdrViolations() {
Diagnosed = true;
break;
}
+ (void)Diagnosed;
+ assert(Diagnosed && "Unable to emit ODR diagnostic.");
+ }
+
+ // Issue ODR failures diagnostics for enums.
+ for (auto &Merge : EnumOdrMergeFailures) {
+ enum ODREnumDifference {
+ SingleScopedEnum,
+ EnumTagKeywordMismatch,
+ SingleSpecifiedType,
+ DifferentSpecifiedTypes,
+ DifferentNumberEnumConstants,
+ EnumConstantName,
+ EnumConstantSingleInitilizer,
+ EnumConstantDifferentInitilizer,
+ };
+
+ // If we've already pointed out a specific problem with this enum, don't
+ // bother issuing a general "something's different" diagnostic.
+ if (!DiagnosedOdrMergeFailures.insert(Merge.first).second)
+ continue;
+
+ EnumDecl *FirstEnum = Merge.first;
+ std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum);
+
+ using DeclHashes =
+ llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>;
+ auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum](
+ DeclHashes &Hashes, EnumDecl *Enum) {
+ for (auto *D : Enum->decls()) {
+ // Due to decl merging, the first EnumDecl is the parent of
+ // Decls in both records.
+ if (!ODRHash::isWhitelistedDecl(D, FirstEnum))
+ continue;
+ assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
+ Hashes.emplace_back(cast<EnumConstantDecl>(D),
+ ComputeSubDeclODRHash(D));
+ }
+ };
+ DeclHashes FirstHashes;
+ PopulateHashes(FirstHashes, FirstEnum);
+ bool Diagnosed = false;
+ for (auto &SecondEnum : Merge.second) {
+
+ if (FirstEnum == SecondEnum)
+ continue;
+
+ std::string SecondModule =
+ getOwningModuleNameForDiagnostic(SecondEnum);
+
+ auto ODRDiagError = [FirstEnum, &FirstModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODREnumDifference DiffType) {
+ return Diag(Loc, diag::err_module_odr_violation_enum)
+ << FirstEnum << FirstModule.empty() << FirstModule << Range
+ << DiffType;
+ };
+ auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc,
+ SourceRange Range,
+ ODREnumDifference DiffType) {
+ return Diag(Loc, diag::note_module_odr_violation_enum)
+ << SecondModule << Range << DiffType;
+ };
+
+ if (FirstEnum->isScoped() != SecondEnum->isScoped()) {
+ ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
+ SingleScopedEnum)
+ << FirstEnum->isScoped();
+ ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
+ SingleScopedEnum)
+ << SecondEnum->isScoped();
+ Diagnosed = true;
+ continue;
+ }
+
+ if (FirstEnum->isScoped() && SecondEnum->isScoped()) {
+ if (FirstEnum->isScopedUsingClassTag() !=
+ SecondEnum->isScopedUsingClassTag()) {
+ ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
+ EnumTagKeywordMismatch)
+ << FirstEnum->isScopedUsingClassTag();
+ ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
+ EnumTagKeywordMismatch)
+ << SecondEnum->isScopedUsingClassTag();
+ Diagnosed = true;
+ continue;
+ }
+ }
+
+ QualType FirstUnderlyingType =
+ FirstEnum->getIntegerTypeSourceInfo()
+ ? FirstEnum->getIntegerTypeSourceInfo()->getType()
+ : QualType();
+ QualType SecondUnderlyingType =
+ SecondEnum->getIntegerTypeSourceInfo()
+ ? SecondEnum->getIntegerTypeSourceInfo()->getType()
+ : QualType();
+ if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) {
+ ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
+ SingleSpecifiedType)
+ << !FirstUnderlyingType.isNull();
+ ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
+ SingleSpecifiedType)
+ << !SecondUnderlyingType.isNull();
+ Diagnosed = true;
+ continue;
+ }
+
+ if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
+ if (ComputeQualTypeODRHash(FirstUnderlyingType) !=
+ ComputeQualTypeODRHash(SecondUnderlyingType)) {
+ ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
+ DifferentSpecifiedTypes)
+ << FirstUnderlyingType;
+ ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
+ DifferentSpecifiedTypes)
+ << SecondUnderlyingType;
+ Diagnosed = true;
+ continue;
+ }
+ }
+
+ DeclHashes SecondHashes;
+ PopulateHashes(SecondHashes, SecondEnum);
+
+ if (FirstHashes.size() != SecondHashes.size()) {
+ ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
+ DifferentNumberEnumConstants)
+ << (int)FirstHashes.size();
+ ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
+ DifferentNumberEnumConstants)
+ << (int)SecondHashes.size();
+ Diagnosed = true;
+ continue;
+ }
+
+ for (unsigned I = 0; I < FirstHashes.size(); ++I) {
+ if (FirstHashes[I].second == SecondHashes[I].second)
+ continue;
+ const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first;
+ const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first;
+
+ if (FirstEnumConstant->getDeclName() !=
+ SecondEnumConstant->getDeclName()) {
+
+ ODRDiagError(FirstEnumConstant->getLocation(),
+ FirstEnumConstant->getSourceRange(), EnumConstantName)
+ << I + 1 << FirstEnumConstant;
+ ODRDiagNote(SecondEnumConstant->getLocation(),
+ SecondEnumConstant->getSourceRange(), EnumConstantName)
+ << I + 1 << SecondEnumConstant;
+ Diagnosed = true;
+ break;
+ }
+
+ const Expr *FirstInit = FirstEnumConstant->getInitExpr();
+ const Expr *SecondInit = SecondEnumConstant->getInitExpr();
+ if (!FirstInit && !SecondInit)
+ continue;
+
+ if (!FirstInit || !SecondInit) {
+ ODRDiagError(FirstEnumConstant->getLocation(),
+ FirstEnumConstant->getSourceRange(),
+ EnumConstantSingleInitilizer)
+ << I + 1 << FirstEnumConstant << (FirstInit != nullptr);
+ ODRDiagNote(SecondEnumConstant->getLocation(),
+ SecondEnumConstant->getSourceRange(),
+ EnumConstantSingleInitilizer)
+ << I + 1 << SecondEnumConstant << (SecondInit != nullptr);
+ Diagnosed = true;
+ break;
+ }
+
+ if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ ODRDiagError(FirstEnumConstant->getLocation(),
+ FirstEnumConstant->getSourceRange(),
+ EnumConstantDifferentInitilizer)
+ << I + 1 << FirstEnumConstant;
+ ODRDiagNote(SecondEnumConstant->getLocation(),
+ SecondEnumConstant->getSourceRange(),
+ EnumConstantDifferentInitilizer)
+ << I + 1 << SecondEnumConstant;
+ Diagnosed = true;
+ break;
+ }
+ }
+ }
+
+ (void)Diagnosed;
assert(Diagnosed && "Unable to emit ODR diagnostic.");
}
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index efbaf92a849a..ad37a2978df1 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1,4 +1,4 @@
-//===--- ASTReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
+//===- ASTReaderDecl.cpp - Decl Deserialization ---------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,42 +15,89 @@
#include "ASTCommon.h"
#include "ASTReaderInternals.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/AttrIterator.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.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/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/PragmaKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/Module.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <utility>
using namespace clang;
-using namespace clang::serialization;
+using namespace serialization;
//===----------------------------------------------------------------------===//
// Declaration deserialization
//===----------------------------------------------------------------------===//
namespace clang {
+
class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
ASTReader &Reader;
ASTRecordReader &Record;
ASTReader::RecordLocation Loc;
const DeclID ThisDeclID;
const SourceLocation ThisDeclLoc;
- typedef ASTReader::RecordData RecordData;
- TypeID TypeIDForTypeDecl;
+
+ using RecordData = ASTReader::RecordData;
+
+ TypeID DeferredTypeID = 0;
unsigned AnonymousDeclNumber;
- GlobalDeclID NamedDeclForTagDecl;
- IdentifierInfo *TypedefNameForLinkage;
+ GlobalDeclID NamedDeclForTagDecl = 0;
+ IdentifierInfo *TypedefNameForLinkage = nullptr;
- bool HasPendingBody;
+ bool HasPendingBody = false;
- ///\brief A flag to carry the information for a decl from the entity is
+ ///A flag to carry the information for a decl from the entity is
/// used. We use it to delay the marking of the canonical decl as used until
/// the entire declaration is deserialized and merged.
- bool IsDeclMarkedUsed;
+ bool IsDeclMarkedUsed = false;
uint64_t GetCurrentCursorOffset();
@@ -130,6 +177,8 @@ namespace clang {
void MergeDefinitionData(ObjCProtocolDecl *D,
struct ObjCProtocolDecl::DefinitionData &&NewDD);
+ static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC);
+
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
unsigned Index);
@@ -144,39 +193,34 @@ namespace clang {
public:
RedeclarableResult(Decl *MergeWith, GlobalDeclID FirstID, bool IsKeyDecl)
- : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {}
+ : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {}
- /// \brief Retrieve the first ID.
+ /// Retrieve the first ID.
GlobalDeclID getFirstID() const { return FirstID; }
- /// \brief Is this declaration a key declaration?
+ /// Is this declaration a key declaration?
bool isKeyDecl() const { return IsKeyDecl; }
- /// \brief Get a known declaration that this should be merged with, if
+ /// Get a known declaration that this should be merged with, if
/// any.
Decl *getKnownMergeTarget() const { return MergeWith; }
};
- /// \brief Class used to capture the result of searching for an existing
+ /// Class used to capture the result of searching for an existing
/// declaration of a specific kind and name, along with the ability
/// to update the place where this result was found (the declaration
/// chain hanging off an identifier or the DeclContext we searched in)
/// if requested.
class FindExistingResult {
ASTReader &Reader;
- NamedDecl *New;
- NamedDecl *Existing;
- bool AddResult;
-
- unsigned AnonymousDeclNumber;
- IdentifierInfo *TypedefNameForLinkage;
-
- void operator=(FindExistingResult &&) = delete;
+ NamedDecl *New = nullptr;
+ NamedDecl *Existing = nullptr;
+ bool AddResult = false;
+ unsigned AnonymousDeclNumber = 0;
+ IdentifierInfo *TypedefNameForLinkage = nullptr;
public:
- FindExistingResult(ASTReader &Reader)
- : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false),
- AnonymousDeclNumber(0), TypedefNameForLinkage(nullptr) {}
+ FindExistingResult(ASTReader &Reader) : Reader(Reader) {}
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing,
unsigned AnonymousDeclNumber,
@@ -193,9 +237,10 @@ namespace clang {
Other.AddResult = false;
}
+ FindExistingResult &operator=(FindExistingResult &&) = delete;
~FindExistingResult();
- /// \brief Suppress the addition of this result into the known set of
+ /// Suppress the addition of this result into the known set of
/// names.
void suppress() { AddResult = false; }
@@ -213,11 +258,8 @@ namespace clang {
ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record,
ASTReader::RecordLocation Loc,
DeclID thisDeclID, SourceLocation ThisDeclLoc)
- : Reader(Reader), Record(Record), Loc(Loc),
- ThisDeclID(thisDeclID), ThisDeclLoc(ThisDeclLoc),
- TypeIDForTypeDecl(0), NamedDeclForTagDecl(0),
- TypedefNameForLinkage(nullptr), HasPendingBody(false),
- IsDeclMarkedUsed(false) {}
+ : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID),
+ ThisDeclLoc(ThisDeclLoc) {}
template <typename T> static
void AddLazySpecializations(T *D,
@@ -232,7 +274,7 @@ namespace clang {
if (auto &Old = LazySpecializations) {
IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
- std::sort(IDs.begin(), IDs.end());
+ llvm::sort(IDs.begin(), IDs.end());
IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
}
@@ -265,13 +307,13 @@ namespace clang {
static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D);
static void markIncompleteDeclChainImpl(...);
- /// \brief Determine whether this declaration has a pending body.
+ /// Determine whether this declaration has a pending body.
bool hasPendingBody() const { return HasPendingBody; }
void ReadFunctionDefinition(FunctionDecl *FD);
void Visit(Decl *D);
- void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&);
+ void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &);
static void setNextObjCCategory(ObjCCategoryDecl *Cat,
ObjCCategoryDecl *Next) {
@@ -300,19 +342,23 @@ namespace clang {
void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
ClassTemplateSpecializationDecl *D);
+
void VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
VisitClassTemplateSpecializationDeclImpl(D);
}
+
void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
void VisitClassScopeFunctionSpecializationDecl(
ClassScopeFunctionSpecializationDecl *D);
RedeclarableResult
VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);
+
void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
VisitVarTemplateSpecializationDeclImpl(D);
}
+
void VisitVarTemplatePartialSpecializationDecl(
VarTemplatePartialSpecializationDecl *D);
void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
@@ -402,18 +448,22 @@ namespace clang {
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
};
-} // end namespace clang
+
+} // namespace clang
namespace {
+
/// Iterator over the redeclarations of a declaration that have already
/// been merged into the same redeclaration chain.
template<typename DeclT>
class MergedRedeclIterator {
- DeclT *Start, *Canonical, *Current;
+ DeclT *Start;
+ DeclT *Canonical = nullptr;
+ DeclT *Current = nullptr;
+
public:
- MergedRedeclIterator() : Current(nullptr) {}
- MergedRedeclIterator(DeclT *Start)
- : Start(Start), Canonical(nullptr), Current(Start) {}
+ MergedRedeclIterator() = default;
+ MergedRedeclIterator(DeclT *Start) : Start(Start), Current(Start) {}
DeclT *operator*() { return Current; }
@@ -438,7 +488,8 @@ public:
return A.Current != B.Current;
}
};
-} // end anonymous namespace
+
+} // namespace
template <typename DeclT>
static llvm::iterator_range<MergedRedeclIterator<DeclT>>
@@ -472,30 +523,27 @@ void ASTDeclReader::Visit(Decl *D) {
D->getCanonicalDecl()->Used |= IsDeclMarkedUsed;
IsDeclMarkedUsed = false;
- if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- if (DD->DeclInfo) {
- DeclaratorDecl::ExtInfo *Info =
- DD->DeclInfo.get<DeclaratorDecl::ExtInfo *>();
- Info->TInfo = GetTypeSourceInfo();
- }
- else {
- DD->DeclInfo = GetTypeSourceInfo();
- }
+ if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {
+ if (auto *TInfo = DD->getTypeSourceInfo())
+ Record.readTypeLoc(TInfo->getTypeLoc());
}
- if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+ if (auto *TD = dyn_cast<TypeDecl>(D)) {
// We have a fully initialized TypeDecl. Read its type now.
- TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
+ TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull());
// If this is a tag declaration with a typedef name for linkage, it's safe
// to load that typedef now.
if (NamedDeclForTagDecl)
cast<TagDecl>(D)->TypedefNameDeclOrQualifier =
cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl));
- } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+ } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
- ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull();
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull();
+ } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (DeferredTypeID)
+ FD->setType(Reader.GetType(DeferredTypeID));
+
// FunctionDecl's body was written last after all other Stmts/Exprs.
// We only read it if FD doesn't already have a body (e.g., from another
// module).
@@ -521,10 +569,10 @@ void ASTDeclReader::VisitDecl(Decl *D) {
Reader.addPendingDeclContextInfo(D,
SemaDCIDForTemplateParmDecl,
LexicalDCIDForTemplateParmDecl);
- D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
+ D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
} else {
- DeclContext *SemaDC = ReadDeclAs<DeclContext>();
- DeclContext *LexicalDC = ReadDeclAs<DeclContext>();
+ auto *SemaDC = ReadDeclAs<DeclContext>();
+ auto *LexicalDC = ReadDeclAs<DeclContext>();
if (!LexicalDC)
LexicalDC = SemaDC;
DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
@@ -615,7 +663,7 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
VisitNamedDecl(TD);
TD->setLocStart(ReadSourceLocation());
// Delay type reading until after we have fully initialized the decl.
- TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt());
+ DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
}
ASTDeclReader::RedeclarableResult
@@ -653,7 +701,7 @@ void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD);
-
+
TD->IdentifierNamespace = Record.readInt();
TD->setTagKind((TagDecl::TagKind)Record.readInt());
if (!isa<CXXRecordDecl>(TD))
@@ -662,12 +710,12 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
TD->setFreeStanding(Record.readInt());
TD->setCompleteDefinitionRequired(Record.readInt());
TD->setBraceRange(ReadSourceRange());
-
+
switch (Record.readInt()) {
case 0:
break;
case 1: { // ExtInfo
- TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
+ auto *Info = new (Reader.getContext()) TagDecl::ExtInfo();
ReadQualifierInfo(*Info);
TD->TypedefNameDeclOrQualifier = Info;
break;
@@ -698,6 +746,9 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
ED->IsScopedUsingClassTag = Record.readInt();
ED->IsFixed = Record.readInt();
+ ED->HasODRHash = true;
+ ED->ODRHash = Record.readInt();
+
// If this is a definition subject to the ODR, and we already have a
// definition, merge this one into it.
if (ED->IsCompleteDefinition &&
@@ -718,14 +769,15 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
ED->IsCompleteDefinition = false;
Reader.mergeDefinitionVisibility(OldDef, ED);
+ if (OldDef->getODRHash() != ED->getODRHash())
+ Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
} else {
OldDef = ED;
}
}
- if (EnumDecl *InstED = ReadDeclAs<EnumDecl>()) {
- TemplateSpecializationKind TSK =
- (TemplateSpecializationKind)Record.readInt();
+ if (auto *InstED = ReadDeclAs<EnumDecl>()) {
+ auto TSK = (TemplateSpecializationKind)Record.readInt();
SourceLocation POI = ReadSourceLocation();
ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK);
ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
@@ -739,12 +791,23 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
RD->setAnonymousStructOrUnion(Record.readInt());
RD->setHasObjectMember(Record.readInt());
RD->setHasVolatileMember(Record.readInt());
+ RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
+ RD->setNonTrivialToPrimitiveCopy(Record.readInt());
+ RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
+ RD->setParamDestroyedInCallee(Record.readInt());
+ RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt());
return Redecl;
}
void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
VisitNamedDecl(VD);
- VD->setType(Record.readType());
+ // For function declarations, defer reading the type in case the function has
+ // a deduced return type that references an entity declared within the
+ // function.
+ if (isa<FunctionDecl>(VD))
+ DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
+ else
+ VD->setType(Record.readType());
}
void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
@@ -759,17 +822,33 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
VisitValueDecl(DD);
DD->setInnerLocStart(ReadSourceLocation());
if (Record.readInt()) { // hasExtInfo
- DeclaratorDecl::ExtInfo *Info
- = new (Reader.getContext()) DeclaratorDecl::ExtInfo();
+ auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo();
ReadQualifierInfo(*Info);
DD->DeclInfo = Info;
}
+ QualType TSIType = Record.readType();
+ DD->setTypeSourceInfo(
+ TSIType.isNull() ? nullptr
+ : Reader.getContext().CreateTypeSourceInfo(TSIType));
}
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
RedeclarableResult Redecl = VisitRedeclarable(FD);
VisitDeclaratorDecl(FD);
+ // Attach a type to this function. Use the real type if possible, but fall
+ // back to the type as written if it involves a deduced return type.
+ if (FD->getTypeSourceInfo() &&
+ FD->getTypeSourceInfo()->getType()->castAs<FunctionType>()
+ ->getReturnType()->getContainedAutoType()) {
+ // We'll set up the real type in Visit, once we've finished loading the
+ // function.
+ FD->setType(FD->getTypeSourceInfo()->getType());
+ } else {
+ FD->setType(Reader.GetType(DeferredTypeID));
+ DeferredTypeID = 0;
+ }
+
ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName());
FD->IdentifierNamespace = Record.readInt();
@@ -786,12 +865,14 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->HasWrittenPrototype = Record.readInt();
FD->IsDeleted = Record.readInt();
FD->IsTrivial = Record.readInt();
+ FD->IsTrivialForCall = Record.readInt();
FD->IsDefaulted = Record.readInt();
FD->IsExplicitlyDefaulted = Record.readInt();
FD->HasImplicitReturnZero = Record.readInt();
FD->IsConstexpr = Record.readInt();
FD->UsesSEHTry = Record.readInt();
FD->HasSkippedBody = Record.readInt();
+ FD->IsMultiVersion = Record.readInt();
FD->IsLateTemplateParsed = Record.readInt();
FD->setCachedLinkage(Linkage(Record.readInt()));
FD->EndRangeLoc = ReadSourceLocation();
@@ -808,9 +889,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>());
break;
case FunctionDecl::TK_MemberSpecialization: {
- FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>();
- TemplateSpecializationKind TSK =
- (TemplateSpecializationKind)Record.readInt();
+ auto *InstFD = ReadDeclAs<FunctionDecl>();
+ auto TSK = (TemplateSpecializationKind)Record.readInt();
SourceLocation POI = ReadSourceLocation();
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
@@ -818,9 +898,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
break;
}
case FunctionDecl::TK_FunctionTemplateSpecialization: {
- FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>();
- TemplateSpecializationKind TSK =
- (TemplateSpecializationKind)Record.readInt();
+ auto *Template = ReadDeclAs<FunctionTemplateDecl>();
+ auto TSK = (TemplateSpecializationKind)Record.readInt();
// Template arguments.
SmallVector<TemplateArgument, 8> TemplArgs;
@@ -833,7 +912,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
if (HasTemplateArgumentsAsWritten) {
unsigned NumTemplateArgLocs = Record.readInt();
TemplArgLocs.reserve(NumTemplateArgLocs);
- for (unsigned i=0; i != NumTemplateArgLocs; ++i)
+ for (unsigned i = 0; i != NumTemplateArgLocs; ++i)
TemplArgLocs.push_back(Record.readTemplateArgumentLoc());
LAngleLoc = ReadSourceLocation();
@@ -846,7 +925,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
TemplateArgumentList *TemplArgList
= TemplateArgumentList::CreateCopy(C, TemplArgs);
TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
- for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i)
+ for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i)
TemplArgsInfo.addArgument(TemplArgLocs[i]);
FunctionTemplateSpecializationInfo *FTInfo
= FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK,
@@ -859,7 +938,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
if (FD->isCanonicalDecl()) { // if canonical add to template's set.
// The template that contains the specializations set. It's not safe to
// use getCanonicalDecl on Template since it may still be initializing.
- FunctionTemplateDecl *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>();
+ auto *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>();
// Get the InsertPos by FindNodeOrInsertPos() instead of calling
// InsertNode(FTInfo) directly to avoid the getASTContext() call in
// FunctionTemplateSpecializationInfo's Profile().
@@ -981,7 +1060,7 @@ ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() {
SmallVector<ObjCTypeParamDecl *, 4> typeParams;
typeParams.reserve(numParams);
for (unsigned i = 0; i != numParams; ++i) {
- auto typeParam = ReadDeclAs<ObjCTypeParamDecl>();
+ auto *typeParam = ReadDeclAs<ObjCTypeParamDecl>();
if (!typeParam)
return nullptr;
@@ -1034,7 +1113,7 @@ void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D,
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
RedeclarableResult Redecl = VisitRedeclarable(ID);
VisitObjCContainerDecl(ID);
- TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt());
+ DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
mergeRedeclarable(ID, Redecl);
ID->TypeParamList = ReadObjCTypeParamList();
@@ -1079,7 +1158,6 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
void ASTDeclReader::ReadObjCDefinitionData(
struct ObjCProtocolDecl::DefinitionData &Data) {
-
unsigned NumProtoRefs = Record.readInt();
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
ProtoRefs.reserve(NumProtoRefs);
@@ -1155,6 +1233,12 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
ProtoLocs.push_back(ReadSourceLocation());
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
Reader.getContext());
+
+ // Protocols in the class extension belong to the class.
+ if (NumProtoRefs > 0 && CD->ClassInterface && CD->IsClassExtension())
+ CD->ClassInterface->mergeClassExtensionProtocolList(
+ (ObjCProtocolDecl *const *)ProtoRefs.data(), NumProtoRefs,
+ Reader.getContext());
}
void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
@@ -1234,7 +1318,7 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
FD->setBitWidth(BW);
if (!FD->getDeclName()) {
- if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>())
+ if (auto *Tmpl = ReadDeclAs<FieldDecl>())
Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
}
mergeMergeable(FD);
@@ -1272,6 +1356,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->NonParmVarDeclBits.ExceptionVar = Record.readInt();
VD->NonParmVarDeclBits.NRVOVariable = Record.readInt();
VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt();
+ VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt();
VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt();
VD->NonParmVarDeclBits.IsInline = Record.readInt();
VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
@@ -1280,7 +1365,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt();
VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt();
}
- Linkage VarLinkage = Linkage(Record.readInt());
+ auto VarLinkage = Linkage(Record.readInt());
VD->setCachedLinkage(VarLinkage);
// Reconstruct the one piece of the IdentifierNamespace that we need.
@@ -1316,9 +1401,8 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>());
break;
case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
- VarDecl *Tmpl = ReadDeclAs<VarDecl>();
- TemplateSpecializationKind TSK =
- (TemplateSpecializationKind)Record.readInt();
+ auto *Tmpl = ReadDeclAs<VarDecl>();
+ auto TSK = (TemplateSpecializationKind)Record.readInt();
SourceLocation POI = ReadSourceLocation();
Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
mergeRedeclarable(VD, Redecl);
@@ -1357,7 +1441,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
void ASTDeclReader::VisitDecompositionDecl(DecompositionDecl *DD) {
VisitVarDecl(DD);
- BindingDecl **BDs = DD->getTrailingObjects<BindingDecl*>();
+ auto **BDs = DD->getTrailingObjects<BindingDecl *>();
for (unsigned I = 0; I != DD->NumBindings; ++I)
BDs[I] = ReadDeclAs<BindingDecl>();
}
@@ -1393,7 +1477,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
SmallVector<BlockDecl::Capture, 16> captures;
captures.reserve(numCaptures);
for (unsigned i = 0; i != numCaptures; ++i) {
- VarDecl *decl = ReadDeclAs<VarDecl>();
+ auto *decl = ReadDeclAs<VarDecl>();
unsigned flags = Record.readInt();
bool byRef = (flags & 1);
bool nested = (flags & 2);
@@ -1460,7 +1544,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
// Each module has its own anonymous namespace, which is disjoint from
// any other module's anonymous namespaces, so don't attach the anonymous
// namespace at all.
- NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
+ auto *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
if (!Record.isModule())
D->setAnonymousNamespace(Anon);
}
@@ -1483,7 +1567,7 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>());
D->setTypename(Record.readInt());
- if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>())
+ if (auto *Pattern = ReadDeclAs<NamedDecl>())
Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
mergeMergeable(D);
}
@@ -1491,7 +1575,7 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
VisitNamedDecl(D);
D->InstantiatedFrom = ReadDeclAs<NamedDecl>();
- NamedDecl **Expansions = D->getTrailingObjects<NamedDecl*>();
+ auto **Expansions = D->getTrailingObjects<NamedDecl *>();
for (unsigned I = 0; I != D->NumExpansions; ++I)
Expansions[I] = ReadDeclAs<NamedDecl>();
mergeMergeable(D);
@@ -1500,9 +1584,10 @@ void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
- D->setTargetDecl(ReadDeclAs<NamedDecl>());
+ D->Underlying = ReadDeclAs<NamedDecl>();
+ D->IdentifierNamespace = Record.readInt();
D->UsingOrNextShadow = ReadDeclAs<NamedDecl>();
- UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>();
+ auto *Pattern = ReadDeclAs<UsingShadowDecl>();
if (Pattern)
Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern);
mergeRedeclarable(D, Redecl);
@@ -1554,7 +1639,9 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.Polymorphic = Record.readInt();
Data.Abstract = Record.readInt();
Data.IsStandardLayout = Record.readInt();
- Data.HasNoNonEmptyBases = Record.readInt();
+ Data.IsCXX11StandardLayout = Record.readInt();
+ Data.HasBasesWithFields = Record.readInt();
+ Data.HasBasesWithNonStaticDataMembers = Record.readInt();
Data.HasPrivateFields = Record.readInt();
Data.HasProtectedFields = Record.readInt();
Data.HasPublicFields = Record.readInt();
@@ -1575,11 +1662,12 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.DefaultedMoveAssignmentIsDeleted = Record.readInt();
Data.DefaultedDestructorIsDeleted = Record.readInt();
Data.HasTrivialSpecialMembers = Record.readInt();
+ Data.HasTrivialSpecialMembersForCall = Record.readInt();
Data.DeclaredNonTrivialSpecialMembers = Record.readInt();
+ Data.DeclaredNonTrivialSpecialMembersForCall = Record.readInt();
Data.HasIrrelevantDestructor = Record.readInt();
Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
Data.HasDefaultedDefaultConstructor = Record.readInt();
- Data.CanPassInRegisters = Record.readInt();
Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
Data.HasConstexprDefaultConstructor = Record.readInt();
Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
@@ -1610,9 +1698,9 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.FirstFriend = ReadDeclID();
if (Data.IsLambda) {
- typedef LambdaCapture Capture;
- CXXRecordDecl::LambdaDefinitionData &Lambda
- = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
+ using Capture = LambdaCapture;
+
+ auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
Lambda.Dependent = Record.readInt();
Lambda.IsGenericLambda = Record.readInt();
Lambda.CaptureDefault = Record.readInt();
@@ -1627,16 +1715,16 @@ void ASTDeclReader::ReadCXXDefinitionData(
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
SourceLocation Loc = ReadSourceLocation();
bool IsImplicit = Record.readInt();
- LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record.readInt());
+ auto Kind = static_cast<LambdaCaptureKind>(Record.readInt());
switch (Kind) {
- case LCK_StarThis:
+ case LCK_StarThis:
case LCK_This:
case LCK_VLAType:
*ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
break;
case LCK_ByCopy:
case LCK_ByRef:
- VarDecl *Var = ReadDeclAs<VarDecl>();
+ auto *Var = ReadDeclAs<VarDecl>();
SourceLocation EllipsisLoc = ReadSourceLocation();
*ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
break;
@@ -1692,7 +1780,9 @@ void ASTDeclReader::MergeDefinitionData(
MATCH_FIELD(Polymorphic)
MATCH_FIELD(Abstract)
MATCH_FIELD(IsStandardLayout)
- MATCH_FIELD(HasNoNonEmptyBases)
+ MATCH_FIELD(IsCXX11StandardLayout)
+ MATCH_FIELD(HasBasesWithFields)
+ MATCH_FIELD(HasBasesWithNonStaticDataMembers)
MATCH_FIELD(HasPrivateFields)
MATCH_FIELD(HasProtectedFields)
MATCH_FIELD(HasPublicFields)
@@ -1713,11 +1803,12 @@ void ASTDeclReader::MergeDefinitionData(
MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
MATCH_FIELD(DefaultedDestructorIsDeleted)
OR_FIELD(HasTrivialSpecialMembers)
+ OR_FIELD(HasTrivialSpecialMembersForCall)
OR_FIELD(DeclaredNonTrivialSpecialMembers)
+ OR_FIELD(DeclaredNonTrivialSpecialMembersForCall)
MATCH_FIELD(HasIrrelevantDestructor)
OR_FIELD(HasConstexprNonCopyMoveConstructor)
OR_FIELD(HasDefaultedDefaultConstructor)
- MATCH_FIELD(CanPassInRegisters)
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
OR_FIELD(HasConstexprDefaultConstructor)
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
@@ -1775,29 +1866,31 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
else
DD = new (C) struct CXXRecordDecl::DefinitionData(D);
+ CXXRecordDecl *Canon = D->getCanonicalDecl();
+ // Set decl definition data before reading it, so that during deserialization
+ // when we read CXXRecordDecl, it already has definition data and we don't
+ // set fake one.
+ if (!Canon->DefinitionData)
+ Canon->DefinitionData = DD;
+ D->DefinitionData = Canon->DefinitionData;
ReadCXXDefinitionData(*DD, D);
- // We might already have a definition for this record. This can happen either
- // because we're reading an update record, or because we've already done some
- // merging. Either way, just merge into it.
- CXXRecordDecl *Canon = D->getCanonicalDecl();
- if (Canon->DefinitionData) {
+ // We might already have a different definition for this record. This can
+ // happen either because we're reading an update record, or because we've
+ // already done some merging. Either way, just merge into it.
+ if (Canon->DefinitionData != DD) {
MergeDefinitionData(Canon, std::move(*DD));
- D->DefinitionData = Canon->DefinitionData;
return;
}
// Mark this declaration as being a definition.
D->IsCompleteDefinition = true;
- D->DefinitionData = DD;
// If this is not the first declaration or is an update record, we can have
// other redeclarations already. Make a note that we need to propagate the
// DefinitionData pointer onto them.
- if (Update || Canon != D) {
- Canon->DefinitionData = D->DefinitionData;
+ if (Update || Canon != D)
Reader.PendingDefinitions.insert(D);
- }
}
ASTDeclReader::RedeclarableResult
@@ -1817,7 +1910,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
break;
case CXXRecTemplate: {
// Merged when we merge the template.
- ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>();
+ auto *Template = ReadDeclAs<ClassTemplateDecl>();
D->TemplateOrInstantiation = Template;
if (!Template->getTemplatedDecl()) {
// We've not actually loaded the ClassTemplateDecl yet, because we're
@@ -1826,14 +1919,13 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
//
// Beware: we do not yet know our canonical declaration, and may still
// get merged once the surrounding class template has got off the ground.
- TypeIDForTypeDecl = 0;
+ DeferredTypeID = 0;
}
break;
}
case CXXRecMemberSpecialization: {
- CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>();
- TemplateSpecializationKind TSK =
- (TemplateSpecializationKind)Record.readInt();
+ auto *RD = ReadDeclAs<CXXRecordDecl>();
+ auto TSK = (TemplateSpecializationKind)Record.readInt();
SourceLocation POI = ReadSourceLocation();
MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
MSI->setPointOfInstantiation(POI);
@@ -1877,7 +1969,7 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
while (NumOverridenMethods--) {
// Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
// MD may be initializing.
- if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>())
+ if (auto *MD = ReadDeclAs<CXXMethodDecl>())
Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl());
}
} else {
@@ -1904,7 +1996,7 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>()) {
- auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ CXXDestructorDecl *Canon = D->getCanonicalDecl();
auto *ThisArg = Record.readExpr();
// FIXME: Check consistency if we have an old and new operator delete.
if (!Canon->OperatorDelete) {
@@ -1922,7 +2014,7 @@ void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
VisitDecl(D);
D->ImportedAndComplete.setPointer(readModule());
D->ImportedAndComplete.setInt(Record.readInt());
- SourceLocation *StoredLocs = D->getTrailingObjects<SourceLocation>();
+ auto *StoredLocs = D->getTrailingObjects<SourceLocation>();
for (unsigned I = 0, N = Record.back(); I != N; ++I)
StoredLocs[I] = ReadSourceLocation();
Record.skipInts(1); // The number of stored source locations.
@@ -1965,7 +2057,7 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
DeclID PatternID = ReadDeclID();
- NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
+ auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
// FIXME handle associated constraints
D->init(TemplatedDecl, TemplateParams);
@@ -1989,8 +2081,7 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// If this is the first declaration of the template, fill in the information
// for the 'common' pointer.
if (ThisDeclID == Redecl.getFirstID()) {
- if (RedeclarableTemplateDecl *RTD
- = ReadDeclAs<RedeclarableTemplateDecl>()) {
+ if (auto *RTD = ReadDeclAs<RedeclarableTemplateDecl>()) {
assert(RTD->getKind() == D->getKind() &&
"InstantiatedFromMemberTemplate kind mismatch");
D->setInstantiatedFromMemberTemplate(RTD);
@@ -2058,15 +2149,15 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
ASTContext &C = Reader.getContext();
if (Decl *InstD = ReadDecl()) {
- if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
+ if (auto *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
D->SpecializedTemplate = CTD;
} else {
SmallVector<TemplateArgument, 8> TemplArgs;
Record.readTemplateArgumentList(TemplArgs);
TemplateArgumentList *ArgList
= TemplateArgumentList::CreateCopy(C, TemplArgs);
- ClassTemplateSpecializationDecl::SpecializedPartialSpecialization *PS
- = new (C) ClassTemplateSpecializationDecl::
+ auto *PS =
+ new (C) ClassTemplateSpecializationDecl::
SpecializedPartialSpecialization();
PS->PartialSpecialization
= cast<ClassTemplatePartialSpecializationDecl>(InstD);
@@ -2083,12 +2174,11 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {
- ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>();
+ auto *CanonPattern = ReadDeclAs<ClassTemplateDecl>();
if (D->isCanonicalDecl()) { // It's kept in the folding set.
// Set this as, or find, the canonical declaration for this specialization
ClassTemplateSpecializationDecl *CanonSpec;
- if (ClassTemplatePartialSpecializationDecl *Partial =
- dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
+ if (auto *Partial = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations
.GetOrInsertNode(Partial);
} else {
@@ -2114,8 +2204,8 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
// Explicit info.
if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) {
- ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo
- = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
+ auto *ExplicitInfo =
+ new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = TyInfo;
ExplicitInfo->ExternLoc = ReadSourceLocation();
ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation();
@@ -2169,14 +2259,14 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
ASTContext &C = Reader.getContext();
if (Decl *InstD = ReadDecl()) {
- if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
+ if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
D->SpecializedTemplate = VTD;
} else {
SmallVector<TemplateArgument, 8> TemplArgs;
Record.readTemplateArgumentList(TemplArgs);
TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(
C, TemplArgs);
- VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS =
+ auto *PS =
new (C)
VarTemplateSpecializationDecl::SpecializedPartialSpecialization();
PS->PartialSpecialization =
@@ -2188,7 +2278,7 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
// Explicit info.
if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) {
- VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo =
+ auto *ExplicitInfo =
new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = TyInfo;
ExplicitInfo->ExternLoc = ReadSourceLocation();
@@ -2205,11 +2295,10 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {
- VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>();
+ auto *CanonPattern = ReadDeclAs<VarTemplateDecl>();
if (D->isCanonicalDecl()) { // It's kept in the folding set.
// FIXME: If it's already present, merge it.
- if (VarTemplatePartialSpecializationDecl *Partial =
- dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
+ if (auto *Partial = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
CanonPattern->getCommonPtr()->PartialSpecializations
.GetOrInsertNode(Partial);
} else {
@@ -2276,8 +2365,7 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
D->setDepth(Record.readInt());
D->setPosition(Record.readInt());
if (D->isExpandedParameterPack()) {
- TemplateParameterList **Data =
- D->getTrailingObjects<TemplateParameterList *>();
+ auto **Data = D->getTrailingObjects<TemplateParameterList *>();
for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
I != N; ++I)
Data[I] = Record.readTemplateParameterList();
@@ -2351,7 +2439,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
(void)ReadDecl();
}
- T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
+ auto *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
if (FirstDecl != D) {
// We delay loading of the redeclaration chain to avoid deeply nested calls.
// We temporarily set the first (canonical) declaration as the previous one
@@ -2361,7 +2449,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
D->First = FirstDecl->getCanonicalDecl();
}
- T *DAsT = static_cast<T*>(D);
+ auto *DAsT = static_cast<T *>(D);
// Note that we need to load local redeclarations of this decl and build a
// decl chain for them. This must happen *after* we perform the preloading
@@ -2373,7 +2461,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
return RedeclarableResult(MergeWith, FirstDeclID, IsKeyDecl);
}
-/// \brief Attempts to merge the given declaration (D) with another declaration
+/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
@@ -2387,7 +2475,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
if (!DBase->isFirstDecl())
return;
- T *D = static_cast<T*>(DBase);
+ auto *D = static_cast<T *>(DBase);
if (auto *Existing = Redecl.getKnownMergeTarget())
// We already know of an existing declaration we should merge with.
@@ -2397,7 +2485,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
}
-/// \brief "Cast" to type T, asserting if we don't have an implicit conversion.
+/// "Cast" to type T, asserting if we don't have an implicit conversion.
/// We use this to put code in a template that will only be valid for certain
/// instantiations.
template<typename T> static T assert_cast(T t) { return t; }
@@ -2405,7 +2493,7 @@ template<typename T> static T assert_cast(...) {
llvm_unreachable("bad assert_cast");
}
-/// \brief Merge together the pattern declarations from two template
+/// Merge together the pattern declarations from two template
/// declarations.
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
@@ -2447,13 +2535,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
llvm_unreachable("merged an unknown kind of redeclarable template");
}
-/// \brief Attempts to merge the given declaration (D) with another declaration
+/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
RedeclarableResult &Redecl,
DeclID TemplatePatternID) {
- T *D = static_cast<T*>(DBase);
+ auto *D = static_cast<T *>(DBase);
T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
@@ -2487,7 +2575,21 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
}
}
-/// \brief Attempts to merge the given declaration (D) with another declaration
+/// ODR-like semantics for C/ObjC allow us to merge tag types and a structural
+/// check in Sema guarantees the types can be merged (see C11 6.2.7/1 or C89
+/// 6.1.2.6/1). Although most merging is done in Sema, we need to guarantee
+/// that some types are mergeable during deserialization, otherwise name
+/// lookup fails. This is the case for EnumConstantDecl.
+static bool allowODRLikeMergeInC(NamedDecl *ND) {
+ if (!ND)
+ return false;
+ // TODO: implement merge for other necessary decls.
+ if (isa<EnumConstantDecl>(ND))
+ return true;
+ return false;
+}
+
+/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity, for the case where the entity is not actually
/// redeclarable. This happens, for instance, when merging the fields of
/// identical class definitions from two different modules.
@@ -2497,10 +2599,12 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) {
if (!Reader.getContext().getLangOpts().Modules)
return;
- // ODR-based merging is only performed in C++. In C, identically-named things
- // in different translation units are not redeclarations (but may still have
- // compatible types).
- if (!Reader.getContext().getLangOpts().CPlusPlus)
+ // ODR-based merging is performed in C++ and in some cases (tag types) in C.
+ // Note that C identically-named things in different translation units are
+ // not redeclarations, but may still have compatible types, where ODR-like
+ // semantics may apply.
+ if (!Reader.getContext().getLangOpts().CPlusPlus &&
+ !allowODRLikeMergeInC(dyn_cast<NamedDecl>(static_cast<T*>(D))))
return;
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
@@ -2538,11 +2642,11 @@ void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
// Attribute Reading
//===----------------------------------------------------------------------===//
-/// \brief Reads attributes from the current stream position.
+/// Reads attributes from the current stream position.
void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
for (unsigned i = 0, e = Record.readInt(); i != e; ++i) {
Attr *New = nullptr;
- attr::Kind Kind = (attr::Kind)Record.readInt();
+ auto Kind = (attr::Kind)Record.readInt();
SourceRange Range = Record.readSourceRange();
ASTContext &Context = getContext();
@@ -2557,7 +2661,7 @@ void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
// ASTReader Implementation
//===----------------------------------------------------------------------===//
-/// \brief Note that we have loaded the declaration with the given
+/// Note that we have loaded the declaration with the given
/// Index.
///
/// This routine notes that this declaration has already been loaded,
@@ -2568,8 +2672,7 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
DeclsLoaded[Index] = D;
}
-
-/// \brief Determine whether the consumer will be interested in seeing
+/// Determine whether the consumer will be interested in seeing
/// this declaration (via HandleTopLevelDecl).
///
/// This routine should return true for anything that might affect
@@ -2588,8 +2691,8 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
return false;
}
- if (isa<FileScopeAsmDecl>(D) ||
- isa<ObjCProtocolDecl>(D) ||
+ if (isa<FileScopeAsmDecl>(D) ||
+ isa<ObjCProtocolDecl>(D) ||
isa<ObjCImplDecl>(D) ||
isa<ImportDecl>(D) ||
isa<PragmaCommentDecl>(D) ||
@@ -2597,10 +2700,10 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
return true;
if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D))
return !D->getDeclContext()->isFunctionOrMethod();
- if (VarDecl *Var = dyn_cast<VarDecl>(D))
+ if (const auto *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
Var->isThisDeclarationADefinition() == VarDecl::Definition;
- if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
+ if (const auto *Func = dyn_cast<FunctionDecl>(D))
return Func->doesThisDeclarationHaveABody() || HasBody;
if (auto *ES = D->getASTContext().getExternalSource())
@@ -2610,7 +2713,7 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
return false;
}
-/// \brief Get the correct cursor and offset for loading a declaration.
+/// Get the correct cursor and offset for loading a declaration.
ASTReader::RecordLocation
ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) {
GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID);
@@ -2623,8 +2726,7 @@ ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) {
}
ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) {
- ContinuousRangeMap<uint64_t, ModuleFile*, 4>::iterator I
- = GlobalBitOffsetsMap.find(GlobalOffset);
+ auto I = GlobalBitOffsetsMap.find(GlobalOffset);
assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map");
return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset);
@@ -2637,26 +2739,26 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) {
static bool isSameTemplateParameterList(const TemplateParameterList *X,
const TemplateParameterList *Y);
-/// \brief Determine whether two template parameters are similar enough
+/// Determine whether two template parameters are similar enough
/// that they may be used in declarations of the same template.
static bool isSameTemplateParameter(const NamedDecl *X,
const NamedDecl *Y) {
if (X->getKind() != Y->getKind())
return false;
- if (const TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
- const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y);
+ if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
+ const auto *TY = cast<TemplateTypeParmDecl>(Y);
return TX->isParameterPack() == TY->isParameterPack();
}
- if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
- const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y);
+ if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
+ const auto *TY = cast<NonTypeTemplateParmDecl>(Y);
return TX->isParameterPack() == TY->isParameterPack() &&
TX->getASTContext().hasSameType(TX->getType(), TY->getType());
}
- const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X);
- const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y);
+ const auto *TX = cast<TemplateTemplateParmDecl>(X);
+ const auto *TY = cast<TemplateTemplateParmDecl>(Y);
return TX->isParameterPack() == TY->isParameterPack() &&
isSameTemplateParameterList(TX->getTemplateParameters(),
TY->getTemplateParameters());
@@ -2709,7 +2811,7 @@ static bool isSameQualifier(const NestedNameSpecifier *X,
return !PX && !PY;
}
-/// \brief Determine whether two template parameter lists are similar enough
+/// Determine whether two template parameter lists are similar enough
/// that they may be used in declarations of the same template.
static bool isSameTemplateParameterList(const TemplateParameterList *X,
const TemplateParameterList *Y) {
@@ -2762,7 +2864,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
return true;
}
-/// \brief Determine whether the two declarations refer to the same entity.
+/// Determine whether the two declarations refer to the same entity.
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
@@ -2770,14 +2872,18 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return true;
// Must be in the same context.
- if (!X->getDeclContext()->getRedeclContext()->Equals(
- Y->getDeclContext()->getRedeclContext()))
+ //
+ // Note that we can't use DeclContext::Equals here, because the DeclContexts
+ // could be two different declarations of the same function. (We will fix the
+ // semantic DC to refer to the primary definition after merging.)
+ if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()),
+ cast<Decl>(Y->getDeclContext()->getRedeclContext())))
return false;
// Two typedefs refer to the same entity if they have the same underlying
// type.
- if (TypedefNameDecl *TypedefX = dyn_cast<TypedefNameDecl>(X))
- if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y))
+ if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X))
+ if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y))
return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(),
TypedefY->getUnderlyingType());
@@ -2796,8 +2902,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
}
// Compatible tags match.
- if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
- TagDecl *TagY = cast<TagDecl>(Y);
+ if (const auto *TagX = dyn_cast<TagDecl>(X)) {
+ const auto *TagY = cast<TagDecl>(Y);
return (TagX->getTagKind() == TagY->getTagKind()) ||
((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class ||
TagX->getTagKind() == TTK_Interface) &&
@@ -2808,28 +2914,51 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// Functions with the same type and linkage match.
// FIXME: This needs to cope with merging of prototyped/non-prototyped
// functions, etc.
- if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
- FunctionDecl *FuncY = cast<FunctionDecl>(Y);
- if (CXXConstructorDecl *CtorX = dyn_cast<CXXConstructorDecl>(X)) {
- CXXConstructorDecl *CtorY = cast<CXXConstructorDecl>(Y);
+ if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) {
+ const auto *FuncY = cast<FunctionDecl>(Y);
+ if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) {
+ const auto *CtorY = cast<CXXConstructorDecl>(Y);
if (CtorX->getInheritedConstructor() &&
!isSameEntity(CtorX->getInheritedConstructor().getConstructor(),
CtorY->getInheritedConstructor().getConstructor()))
return false;
}
+
+ if (FuncX->isMultiVersion() != FuncY->isMultiVersion())
+ return false;
+
+ // Multiversioned functions with different feature strings are represented
+ // as separate declarations.
+ if (FuncX->isMultiVersion()) {
+ const auto *TAX = FuncX->getAttr<TargetAttr>();
+ const auto *TAY = FuncY->getAttr<TargetAttr>();
+ assert(TAX && TAY && "Multiversion Function without target attribute");
+
+ if (TAX->getFeaturesStr() != TAY->getFeaturesStr())
+ return false;
+ }
+
ASTContext &C = FuncX->getASTContext();
- if (!C.hasSameType(FuncX->getType(), FuncY->getType())) {
+ auto GetTypeAsWritten = [](const FunctionDecl *FD) {
+ // Map to the first declaration that we've already merged into this one.
+ // The TSI of redeclarations might not match (due to calling conventions
+ // being inherited onto the type but not the TSI), but the TSI type of
+ // the first declaration of the function should match across modules.
+ FD = FD->getCanonicalDecl();
+ return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType()
+ : FD->getType();
+ };
+ QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY);
+ if (!C.hasSameType(XT, YT)) {
// We can get functions with different types on the redecl chain in C++17
// if they have differing exception specifications and at least one of
// the excpetion specs is unresolved.
- // 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>();
+ auto *XFPT = XT->getAs<FunctionProtoType>();
+ auto *YFPT = YT->getAs<FunctionProtoType>();
if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT &&
(isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) ||
isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) &&
- C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(),
- FuncY->getType()))
+ C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT))
return true;
return false;
}
@@ -2838,8 +2967,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
}
// Variables with the same type and linkage match.
- if (VarDecl *VarX = dyn_cast<VarDecl>(X)) {
- VarDecl *VarY = cast<VarDecl>(Y);
+ if (const auto *VarX = dyn_cast<VarDecl>(X)) {
+ const auto *VarY = cast<VarDecl>(Y);
if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) {
ASTContext &C = VarX->getASTContext();
if (C.hasSameType(VarX->getType(), VarY->getType()))
@@ -2861,15 +2990,15 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
}
// Namespaces with the same name and inlinedness match.
- if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
- NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y);
+ if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
+ const auto *NamespaceY = cast<NamespaceDecl>(Y);
return NamespaceX->isInline() == NamespaceY->isInline();
}
// Identical template names and kinds match if their template parameter lists
// and patterns match.
- if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) {
- TemplateDecl *TemplateY = cast<TemplateDecl>(Y);
+ if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
+ const auto *TemplateY = cast<TemplateDecl>(Y);
return isSameEntity(TemplateX->getTemplatedDecl(),
TemplateY->getTemplatedDecl()) &&
isSameTemplateParameterList(TemplateX->getTemplateParameters(),
@@ -2877,15 +3006,15 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
}
// Fields with the same name and the same type match.
- if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) {
- FieldDecl *FDY = cast<FieldDecl>(Y);
+ if (const auto *FDX = dyn_cast<FieldDecl>(X)) {
+ const auto *FDY = cast<FieldDecl>(Y);
// FIXME: Also check the bitwidth is odr-equivalent, if any.
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
}
// Indirect fields with the same target field match.
- if (auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
- auto *IFDY = cast<IndirectFieldDecl>(Y);
+ if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
+ const auto *IFDY = cast<IndirectFieldDecl>(Y);
return IFDX->getAnonField()->getCanonicalDecl() ==
IFDY->getAnonField()->getCanonicalDecl();
}
@@ -2896,32 +3025,32 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return true;
// Using shadow declarations with the same target match.
- if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) {
- UsingShadowDecl *USY = cast<UsingShadowDecl>(Y);
+ if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) {
+ const auto *USY = cast<UsingShadowDecl>(Y);
return USX->getTargetDecl() == USY->getTargetDecl();
}
// Using declarations with the same qualifier match. (We already know that
// the name matches.)
- if (auto *UX = dyn_cast<UsingDecl>(X)) {
- auto *UY = cast<UsingDecl>(Y);
+ if (const auto *UX = dyn_cast<UsingDecl>(X)) {
+ const auto *UY = cast<UsingDecl>(Y);
return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
UX->hasTypename() == UY->hasTypename() &&
UX->isAccessDeclaration() == UY->isAccessDeclaration();
}
- if (auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
- auto *UY = cast<UnresolvedUsingValueDecl>(Y);
+ if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
+ const auto *UY = cast<UnresolvedUsingValueDecl>(Y);
return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
UX->isAccessDeclaration() == UY->isAccessDeclaration();
}
- if (auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
+ if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
return isSameQualifier(
UX->getQualifier(),
cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
// Namespace alias definitions with the same target match.
- if (auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
- auto *NAY = cast<NamespaceAliasDecl>(Y);
+ if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
+ const auto *NAY = cast<NamespaceAliasDecl>(Y);
return NAX->getNamespace()->Equals(NAY->getNamespace());
}
@@ -2932,10 +3061,10 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
/// looking for declarations to merge.
DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
DeclContext *DC) {
- if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
+ if (auto *ND = dyn_cast<NamespaceDecl>(DC))
return ND->getOriginalNamespace();
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
// Try to dig out the definition.
auto *DD = RD->DefinitionData;
if (!DD)
@@ -2959,7 +3088,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
return DD->Definition;
}
- if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
+ if (auto *ED = dyn_cast<EnumDecl>(DC))
return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
: nullptr;
@@ -3021,23 +3150,50 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found,
return nullptr;
}
+/// Find the declaration to use to populate the anonymous declaration table
+/// for the given lexical DeclContext. We only care about finding local
+/// definitions of the context; we'll merge imported ones as we go.
+DeclContext *
+ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) {
+ // For classes, we track the definition as we merge.
+ if (auto *RD = dyn_cast<CXXRecordDecl>(LexicalDC)) {
+ auto *DD = RD->getCanonicalDecl()->DefinitionData;
+ return DD ? DD->Definition : nullptr;
+ }
+
+ // For anything else, walk its merged redeclarations looking for a definition.
+ // Note that we can't just call getDefinition here because the redeclaration
+ // chain isn't wired up.
+ for (auto *D : merged_redecls(cast<Decl>(LexicalDC))) {
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isThisDeclarationADefinition())
+ return FD;
+ if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (MD->isThisDeclarationADefinition())
+ return MD;
+ }
+
+ // No merged definition yet.
+ return nullptr;
+}
+
NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
unsigned Index) {
// If the lexical context has been merged, look into the now-canonical
// definition.
- if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
- DC = Merged;
+ auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl();
// If we've seen this before, return the canonical declaration.
- auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
+ auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC];
if (Index < Previous.size() && Previous[Index])
return Previous[Index];
// If this is the first time, but we have parsed a declaration of the context,
// build the anonymous declaration list from the parsed declaration.
- if (!cast<Decl>(DC)->isFromASTFile()) {
- numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) {
+ auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC);
+ if (PrimaryDC && !cast<Decl>(PrimaryDC)->isFromASTFile()) {
+ numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) {
if (Previous.size() == Number)
Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
else
@@ -3051,10 +3207,9 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC, unsigned Index,
NamedDecl *D) {
- if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
- DC = Merged;
+ auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl();
- auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
+ auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC];
if (Index >= Previous.size())
Previous.resize(Index + 1);
if (!Previous[Index])
@@ -3102,12 +3257,10 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// cause additional lookups here.
class UpToDateIdentifierRAII {
IdentifierInfo *II;
- bool WasOutToDate;
+ bool WasOutToDate = false;
public:
- explicit UpToDateIdentifierRAII(IdentifierInfo *II)
- : II(II), WasOutToDate(false)
- {
+ explicit UpToDateIdentifierRAII(IdentifierInfo *II) : II(II) {
if (II) {
WasOutToDate = II->isOutOfDate();
if (WasOutToDate)
@@ -3121,7 +3274,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
}
} UpToDate(Name.getAsIdentifierInfo());
- for (IdentifierResolver::iterator I = IdResolver.begin(Name),
+ for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I) {
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
@@ -3160,6 +3313,7 @@ template<typename DeclT>
Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) {
return D->RedeclLink.getLatestNotUpdated();
}
+
Decl *ASTDeclReader::getMostRecentDeclImpl(...) {
llvm_unreachable("getMostRecentDecl on non-redeclarable declaration");
}
@@ -3190,12 +3344,13 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
}
namespace clang {
+
template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<VarDecl> *D,
Decl *Previous, Decl *Canon) {
- VarDecl *VD = static_cast<VarDecl*>(D);
- VarDecl *PrevVD = cast<VarDecl>(Previous);
+ auto *VD = static_cast<VarDecl *>(D);
+ auto *PrevVD = cast<VarDecl>(Previous);
D->RedeclLink.setPrevious(PrevVD);
D->First = PrevVD->First;
@@ -3217,8 +3372,8 @@ template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<FunctionDecl> *D,
Decl *Previous, Decl *Canon) {
- FunctionDecl *FD = static_cast<FunctionDecl*>(D);
- FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
+ auto *FD = static_cast<FunctionDecl *>(D);
+ auto *PrevFD = cast<FunctionDecl>(Previous);
FD->RedeclLink.setPrevious(PrevFD);
FD->First = PrevFD->First;
@@ -3257,7 +3412,8 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
}
}
-} // end namespace clang
+
+} // namespace clang
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
@@ -3283,22 +3439,16 @@ static void inheritDefaultTemplateArguments(ASTContext &Context,
assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");
for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
- NamedDecl *FromParam = FromTP->getParam(N - I - 1);
- if (FromParam->isParameterPack())
- continue;
- NamedDecl *ToParam = ToTP->getParam(N - I - 1);
+ NamedDecl *FromParam = FromTP->getParam(I);
+ NamedDecl *ToParam = ToTP->getParam(I);
- if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) {
- if (!inheritDefaultTemplateArgument(Context, FTTP, ToParam))
- break;
- } else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
- if (!inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
- break;
- } else {
- if (!inheritDefaultTemplateArgument(
- Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam))
- break;
- }
+ if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam))
+ inheritDefaultTemplateArgument(Context, FTTP, ToParam);
+ else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam))
+ inheritDefaultTemplateArgument(Context, FNTTP, ToParam);
+ else
+ inheritDefaultTemplateArgument(
+ Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam);
}
}
@@ -3326,7 +3476,7 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
// If the declaration declares a template, it may inherit default arguments
// from the previous declaration.
- if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ if (auto *TD = dyn_cast<TemplateDecl>(D))
inheritDefaultTemplateArguments(Reader.getContext(),
cast<TemplateDecl>(Previous), TD);
}
@@ -3335,6 +3485,7 @@ template<typename DeclT>
void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) {
D->RedeclLink.setLatest(cast<DeclT>(Latest));
}
+
void ASTDeclReader::attachLatestDeclImpl(...) {
llvm_unreachable("attachLatestDecl on non-redeclarable declaration");
}
@@ -3356,6 +3507,7 @@ template<typename DeclT>
void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) {
D->RedeclLink.markIncomplete();
}
+
void ASTDeclReader::markIncompleteDeclChainImpl(...) {
llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration");
}
@@ -3371,7 +3523,7 @@ void ASTReader::markIncompleteDeclChain(Decl *D) {
}
}
-/// \brief Read the declaration at the given offset from the AST file.
+/// Read the declaration at the given offset from the AST file.
Decl *ASTReader::ReadDeclRecord(DeclID ID) {
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
SourceLocation DeclLoc;
@@ -3601,7 +3753,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
Error("attempt to read a C++ ctor initializer record as a declaration");
return nullptr;
case DECL_IMPORT:
- // Note: last entry of the ImportDecl record is the number of stored source
+ // Note: last entry of the ImportDecl record is the number of stored source
// locations.
D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
break;
@@ -3639,7 +3791,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// If this declaration is also a declaration context, get the
// offsets for its tables of lexical and visible declarations.
- if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
+ if (auto *DC = dyn_cast<DeclContext>(D)) {
std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
if (Offsets.first &&
ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC))
@@ -3655,13 +3807,13 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
PendingUpdateRecord(ID, D, /*JustLoaded=*/true));
// Load the categories after recursive loading is finished.
- if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
+ if (auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
// If we already have a definition when deserializing the ObjCInterfaceDecl,
// we put the Decl in PendingDefinitions so we can pull the categories here.
if (Class->isThisDeclarationADefinition() ||
PendingDefinitions.count(Class))
loadObjCCategories(ID, Class);
-
+
// If we have deserialized a declaration that has a definition the
// AST consumer might need to know about, queue it.
// We don't pass it to the consumer immediately because we may be in recursive
@@ -3706,7 +3858,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
- llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;
+ SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;
if (UpdI != DeclUpdateOffsets.end()) {
auto UpdateOffsets = std::move(UpdI->second);
@@ -3763,7 +3915,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
PendingVisibleUpdates.erase(I);
auto *DC = cast<DeclContext>(D)->getPrimaryContext();
- for (const PendingVisibleUpdate &Update : VisibleUpdates)
+ for (const auto &Update : VisibleUpdates)
Lookups[DC].Table.add(
Update.Mod, Update.Data,
reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod));
@@ -3812,27 +3964,28 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
}
namespace {
- /// \brief Given an ObjC interface, goes through the modules and links to the
+
+ /// Given an ObjC interface, goes through the modules and links to the
/// interface all the categories for it.
class ObjCCategoriesVisitor {
ASTReader &Reader;
ObjCInterfaceDecl *Interface;
llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized;
- ObjCCategoryDecl *Tail;
+ ObjCCategoryDecl *Tail = nullptr;
llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap;
serialization::GlobalDeclID InterfaceID;
unsigned PreviousGeneration;
-
+
void add(ObjCCategoryDecl *Cat) {
// Only process each category once.
if (!Deserialized.erase(Cat))
return;
-
+
// Check for duplicate categories.
if (Cat->getDeclName()) {
ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()];
- if (Existing &&
- Reader.getOwningModuleFile(Existing)
+ if (Existing &&
+ Reader.getOwningModuleFile(Existing)
!= Reader.getOwningModuleFile(Cat)) {
// FIXME: We should not warn for duplicates in diamond:
//
@@ -3842,8 +3995,8 @@ namespace {
// \ / //
// MB //
//
- // If there are duplicates in ML/MR, there will be warning when
- // creating MB *and* when importing MB. We should not warn when
+ // If there are duplicates in ML/MR, there will be warning when
+ // creating MB *and* when importing MB. We should not warn when
// importing.
Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
<< Interface->getDeclName() << Cat->getDeclName();
@@ -3853,7 +4006,7 @@ namespace {
Existing = Cat;
}
}
-
+
// Add this category to the end of the chain.
if (Tail)
ASTDeclReader::setNextObjCCategory(Tail, Cat);
@@ -3861,22 +4014,20 @@ namespace {
Interface->setCategoryListRaw(Cat);
Tail = Cat;
}
-
+
public:
ObjCCategoriesVisitor(ASTReader &Reader,
ObjCInterfaceDecl *Interface,
llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
serialization::GlobalDeclID InterfaceID,
unsigned PreviousGeneration)
- : Reader(Reader), Interface(Interface), Deserialized(Deserialized),
- Tail(nullptr), InterfaceID(InterfaceID),
- PreviousGeneration(PreviousGeneration)
- {
+ : Reader(Reader), Interface(Interface), Deserialized(Deserialized),
+ InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) {
// Populate the name -> category map with the set of known categories.
for (auto *Cat : Interface->known_categories()) {
if (Cat->getDeclName())
NameCategoryMap[Cat->getDeclName()] = Cat;
-
+
// Keep track of the tail of the category list.
Tail = Cat;
}
@@ -3887,8 +4038,8 @@ namespace {
// this module file, we're done.
if (M.Generation <= PreviousGeneration)
return true;
-
- // Map global ID of the definition down to the local ID used in this
+
+ // Map global ID of the definition down to the local ID used in this
// module file. If there is no such mapping, we'll find nothing here
// (or in any module it imports).
DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID);
@@ -3900,7 +4051,7 @@ namespace {
const ObjCCategoriesInfo Compare = { LocalID, 0 };
const ObjCCategoriesInfo *Result
= std::lower_bound(M.ObjCCategoriesMap,
- M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
+ M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
Compare);
if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap ||
Result->DefinitionID != LocalID) {
@@ -3909,7 +4060,7 @@ namespace {
// so suppress further lookup.
return Reader.isDeclIDFromModule(InterfaceID, M);
}
-
+
// We found something. Dig out all of the categories.
unsigned Offset = Result->Offset;
unsigned N = M.ObjCCategories[Offset];
@@ -3920,7 +4071,8 @@ namespace {
return true;
}
};
-} // end anonymous namespace
+
+} // namespace
void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
ObjCInterfaceDecl *D,
@@ -3973,13 +4125,13 @@ void ASTDeclReader::UpdateDecl(Decl *D,
break;
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
- NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>();
+ auto *Anon = ReadDeclAs<NamespaceDecl>();
// Each module has its own anonymous namespace, which is disjoint from
// any other module's anonymous namespaces, so don't attach the anonymous
// namespace at all.
if (!Record.isModule()) {
- if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D))
+ if (auto *TU = dyn_cast<TranslationUnitDecl>(D))
TU->setAnonymousNamespace(Anon);
else
cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon);
@@ -3988,7 +4140,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
case UPD_CXX_ADDED_VAR_DEFINITION: {
- VarDecl *VD = cast<VarDecl>(D);
+ auto *VD = cast<VarDecl>(D);
VD->NonParmVarDeclBits.IsInline = Record.readInt();
VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
uint64_t Val = Record.readInt();
@@ -4005,8 +4157,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
case UPD_CXX_POINT_OF_INSTANTIATION: {
SourceLocation POI = Record.readSourceLocation();
- if (VarTemplateSpecializationDecl *VTSD =
- dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {
VTSD->setPointOfInstantiation(POI);
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
@@ -4023,12 +4174,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: {
- auto Param = cast<ParmVarDecl>(D);
+ auto *Param = cast<ParmVarDecl>(D);
// We have to read the default argument regardless of whether we use it
// so that hypothetical further update records aren't messed up.
// TODO: Add a function to skip over the next expr record.
- auto DefaultArg = Record.readExpr();
+ auto *DefaultArg = Record.readExpr();
// Only apply the update if the parameter still has an uninstantiated
// default argument.
@@ -4038,8 +4189,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: {
- auto FD = cast<FieldDecl>(D);
- auto DefaultInit = Record.readExpr();
+ auto *FD = cast<FieldDecl>(D);
+ auto *DefaultInit = Record.readExpr();
// Only apply the update if the field still has an uninstantiated
// default member initializer.
@@ -4055,7 +4206,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
- FunctionDecl *FD = cast<FunctionDecl>(D);
+ auto *FD = cast<FunctionDecl>(D);
if (Reader.PendingBodies[FD]) {
// FIXME: Maybe check for ODR violations.
// It's safe to stop now because this update record is always last.
@@ -4082,6 +4233,9 @@ void ASTDeclReader::UpdateDecl(Decl *D,
bool HadRealDefinition =
OldDD && (OldDD->Definition != RD ||
!Reader.PendingFakeDefinitionData.count(OldDD));
+ RD->setParamDestroyedInCallee(Record.readInt());
+ RD->setArgPassingRestrictions(
+ (RecordDecl::ArgPassingKind)Record.readInt());
ReadCXXRecordDefinition(RD, /*Update*/true);
// Visible update is handled separately.
@@ -4098,13 +4252,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(POI);
} else {
- ClassTemplateSpecializationDecl *Spec =
- cast<ClassTemplateSpecializationDecl>(RD);
+ auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(POI);
if (Record.readInt()) {
- auto PartialSpec =
+ auto *PartialSpec =
ReadDeclAs<ClassTemplatePartialSpecializationDecl>();
SmallVector<TemplateArgument, 8> TemplArgs;
Record.readTemplateArgumentList(TemplArgs);
@@ -4177,18 +4330,17 @@ void ASTDeclReader::UpdateDecl(Decl *D,
QualType DeducedResultType = Record.readType();
for (auto *Redecl : merged_redecls(D)) {
// FIXME: If the return type is already deduced, check that it matches.
- FunctionDecl *FD = cast<FunctionDecl>(Redecl);
+ auto *FD = cast<FunctionDecl>(Redecl);
Reader.getContext().adjustDeducedFunctionResultType(FD,
DeducedResultType);
}
break;
}
- case UPD_DECL_MARKED_USED: {
+ case UPD_DECL_MARKED_USED:
// Maintain AST consistency: any later redeclarations are used too.
D->markUsed(Reader.getContext());
break;
- }
case UPD_MANGLING_NUMBER:
Reader.getContext().setManglingNumber(cast<NamedDecl>(D),
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
index 2b92ae65ea84..37a929907dca 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
@@ -33,19 +33,19 @@ struct HeaderFileInfo;
class HeaderSearch;
class IdentifierTable;
class ObjCMethodDecl;
-
+
namespace serialization {
class ModuleFile;
namespace reader {
-/// \brief Class that performs name lookup into a DeclContext stored
+/// Class that performs name lookup into a DeclContext stored
/// in an AST file.
class ASTDeclContextNameLookupTrait {
ASTReader &Reader;
ModuleFile &F;
-
+
public:
// Maximum number of lookup tables we allow before condensing the tables.
static const int MaxTables = 4;
@@ -121,7 +121,7 @@ struct DeclContextLookupTable {
MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table;
};
-/// \brief Base class for the trait describing the on-disk hash table for the
+/// Base class for the trait describing the on-disk hash table for the
/// identifiers in an AST file.
///
/// This class is not useful by itself; rather, it provides common
@@ -141,31 +141,31 @@ public:
}
static hash_value_type ComputeHash(const internal_key_type& a);
-
+
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
// This hopefully will just get inlined and removed by the optimizer.
static const internal_key_type&
GetInternalKey(const external_key_type& x) { return x; }
-
+
// This hopefully will just get inlined and removed by the optimizer.
static const external_key_type&
GetExternalKey(const internal_key_type& x) { return x; }
- static internal_key_type ReadKey(const unsigned char* d, unsigned n);
+ static internal_key_type ReadKey(const unsigned char* d, unsigned n);
};
-/// \brief Class that performs lookup for an identifier stored in an AST file.
+/// Class that performs lookup for an identifier stored in an AST file.
class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase {
ASTReader &Reader;
ModuleFile &F;
-
+
// If we know the IdentifierInfo in advance, it is here and we will
// not build a new one. Used when deserializing information about an
// identifier that was constructed before the AST file was read.
IdentifierInfo *KnownII;
-
+
public:
using data_type = IdentifierInfo *;
@@ -176,23 +176,23 @@ public:
data_type ReadData(const internal_key_type& k,
const unsigned char* d,
unsigned DataLen);
-
+
IdentID ReadIdentifierID(const unsigned char *d);
ASTReader &getReader() const { return Reader; }
};
-
-/// \brief The on-disk hash table used to contain information about
+
+/// The on-disk hash table used to contain information about
/// all of the identifiers in the program.
using ASTIdentifierLookupTable =
llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>;
-/// \brief Class that performs lookup for a selector's entries in the global
+/// Class that performs lookup for a selector's entries in the global
/// method pool stored in an AST file.
class ASTSelectorLookupTrait {
ASTReader &Reader;
ModuleFile &F;
-
+
public:
struct data_type {
SelectorID ID;
@@ -203,40 +203,40 @@ public:
SmallVector<ObjCMethodDecl *, 2> Instance;
SmallVector<ObjCMethodDecl *, 2> Factory;
};
-
+
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) {}
-
+
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
return a == b;
}
-
+
static hash_value_type ComputeHash(Selector Sel);
-
+
static const internal_key_type&
GetInternalKey(const external_key_type& x) { return x; }
-
+
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
-
+
internal_key_type ReadKey(const unsigned char* d, unsigned);
data_type ReadData(Selector, const unsigned char* d, unsigned DataLen);
};
-
-/// \brief The on-disk hash table used for the global method pool.
+
+/// The on-disk hash table used for the global method pool.
using ASTSelectorLookupTable =
llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>;
-
-/// \brief Trait class used to search the on-disk hash table containing all of
+
+/// Trait class used to search the on-disk hash table containing all of
/// the header search information.
///
-/// The on-disk hash table contains a mapping from each header path to
+/// The on-disk hash table contains a mapping from each header path to
/// information about that header (how many times it has been included, its
/// controlling macro, etc.). Note that we actually hash based on the size
/// and mtime, and support "deep" comparisons of file names based on current
@@ -259,31 +259,31 @@ public:
};
using internal_key_ref = const internal_key_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) {}
-
+
static hash_value_type ComputeHash(internal_key_ref ikey);
internal_key_type GetInternalKey(const FileEntry *FE);
bool EqualKey(internal_key_ref a, internal_key_ref b);
-
+
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
-
+
static internal_key_type ReadKey(const unsigned char *d, unsigned);
-
+
data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen);
};
-/// \brief The on-disk hash table used for known header files.
+/// The on-disk hash table used for known header files.
using HeaderFileInfoLookupTable =
llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>;
-
+
} // namespace reader
} // namespace serialization
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
index 6163b811c769..570b554986f8 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1,4 +1,4 @@
-//===--- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===//
+//===- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,13 +14,55 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/AttrIterator.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclCXX.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/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TypeTraits.h"
#include "clang/Lex/Token.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <string>
+
using namespace clang;
-using namespace clang::serialization;
+using namespace serialization;
namespace clang {
@@ -68,19 +110,20 @@ namespace clang {
ASTStmtReader(ASTRecordReader &Record, llvm::BitstreamCursor &Cursor)
: Record(Record), DeclsCursor(Cursor) {}
- /// \brief The number of record fields required for the Stmt class
+ /// The number of record fields required for the Stmt class
/// itself.
static const unsigned NumStmtFields = 0;
- /// \brief The number of record fields required for the Expr class
+ /// The number of record fields required for the Expr class
/// itself.
static const unsigned NumExprFields = NumStmtFields + 7;
- /// \brief Read and initialize a ExplicitTemplateArgumentList structure.
+ /// Read and initialize a ExplicitTemplateArgumentList structure.
void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
TemplateArgumentLoc *ArgsLocArray,
unsigned NumTemplateArgs);
- /// \brief Read and initialize a ExplicitTemplateArgumentList structure.
+
+ /// Read and initialize a ExplicitTemplateArgumentList structure.
void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList,
unsigned NumTemplateArgs);
@@ -89,7 +132,8 @@ namespace clang {
void Visit##Type(Type *);
#include "clang/AST/StmtNodes.inc"
};
-}
+
+} // namespace clang
void ASTStmtReader::ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
TemplateArgumentLoc *ArgsLocArray,
@@ -146,7 +190,7 @@ void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
VisitStmt(S);
- LabelDecl *LD = ReadDeclAs<LabelDecl>();
+ auto *LD = ReadDeclAs<LabelDecl>();
LD->setStmt(S);
S->setDecl(LD);
S->setSubStmt(Record.readSubStmt());
@@ -489,6 +533,12 @@ void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
E->setValue(Record.getContext(), Record.readAPInt());
}
+void ASTStmtReader::VisitFixedPointLiteral(FixedPointLiteral *E) {
+ VisitExpr(E);
+ E->setLocation(ReadSourceLocation());
+ E->setValue(Record.getContext(), Record.readAPInt());
+}
+
void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record.readInt()));
@@ -508,8 +558,7 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) {
assert(Record.peekInt() == E->getNumConcatenated() &&
"Wrong number of concatenated tokens!");
Record.skipInts(1);
- StringLiteral::StringKind kind =
- static_cast<StringLiteral::StringKind>(Record.readInt());
+ auto kind = static_cast<StringLiteral::StringKind>(Record.readInt());
bool isPascal = Record.readInt();
// Read string data
@@ -553,6 +602,7 @@ void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
E->setSubExpr(Record.readSubExpr());
E->setOpcode((UnaryOperator::Opcode)Record.readInt());
E->setOperatorLoc(ReadSourceLocation());
+ E->setCanOverflow(Record.readInt());
}
void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
@@ -565,7 +615,7 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
E->setRParenLoc(ReadSourceLocation());
E->setTypeSourceInfo(GetTypeSourceInfo());
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
- OffsetOfNode::Kind Kind = static_cast<OffsetOfNode::Kind>(Record.readInt());
+ auto Kind = static_cast<OffsetOfNode::Kind>(Record.readInt());
SourceLocation Start = ReadSourceLocation();
SourceLocation End = ReadSourceLocation();
switch (Kind) {
@@ -585,7 +635,7 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
break;
case OffsetOfNode::Base: {
- CXXBaseSpecifier *Base = new (Record.getContext()) CXXBaseSpecifier();
+ auto *Base = new (Record.getContext()) CXXBaseSpecifier();
*Base = Record.readCXXBaseSpecifier();
E->setComponent(I, OffsetOfNode(Base));
break;
@@ -675,7 +725,7 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) {
E->setCastKind((CastKind)Record.readInt());
CastExpr::path_iterator BaseI = E->path_begin();
while (NumBaseSpecs--) {
- CXXBaseSpecifier *BaseSpec = new (Record.getContext()) CXXBaseSpecifier;
+ auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier;
*BaseSpec = Record.readCXXBaseSpecifier();
*BaseI++ = BaseSpec;
}
@@ -719,6 +769,7 @@ ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
VisitCastExpr(E);
+ E->setIsPartOfExplicitCast(Record.readInt());
}
void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
@@ -749,7 +800,7 @@ void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
void ASTStmtReader::VisitInitListExpr(InitListExpr *E) {
VisitExpr(E);
- if (InitListExpr *SyntForm = cast_or_null<InitListExpr>(Record.readSubStmt()))
+ if (auto *SyntForm = cast_or_null<InitListExpr>(Record.readSubStmt()))
E->setSyntacticForm(SyntForm);
E->setLBraceLoc(ReadSourceLocation());
E->setRBraceLoc(ReadSourceLocation());
@@ -775,7 +826,7 @@ void ASTStmtReader::VisitInitListExpr(InitListExpr *E) {
}
void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
- typedef DesignatedInitExpr::Designator Designator;
+ using Designator = DesignatedInitExpr::Designator;
VisitExpr(E);
unsigned NumSubExprs = Record.readInt();
@@ -789,7 +840,7 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
while (Record.getIdx() < Record.size()) {
switch ((DesignatorTypes)Record.readInt()) {
case DESIG_FIELD_DECL: {
- FieldDecl *Field = ReadDeclAs<FieldDecl>();
+ auto *Field = ReadDeclAs<FieldDecl>();
SourceLocation DotLoc = ReadSourceLocation();
SourceLocation FieldLoc = ReadSourceLocation();
Designators.push_back(Designator(Field->getIdentifier(), DotLoc,
@@ -994,9 +1045,9 @@ void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
assert(NumElements == E->getNumElements() && "Wrong number of elements");
bool HasPackExpansions = Record.readInt();
assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch");
- ObjCDictionaryLiteral::KeyValuePair *KeyValues =
+ auto *KeyValues =
E->getTrailingObjects<ObjCDictionaryLiteral::KeyValuePair>();
- ObjCDictionaryLiteral::ExpansionData *Expansions =
+ auto *Expansions =
E->getTrailingObjects<ObjCDictionaryLiteral::ExpansionData>();
for (unsigned I = 0; I != NumElements; ++I) {
KeyValues[I].Key = Record.readSubExpr();
@@ -1047,8 +1098,8 @@ void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
unsigned MethodRefFlags = Record.readInt();
bool Implicit = Record.readInt() != 0;
if (Implicit) {
- ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>();
- ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>();
+ auto *Getter = ReadDeclAs<ObjCMethodDecl>();
+ auto *Setter = ReadDeclAs<ObjCMethodDecl>();
E->setImplicitProperty(Getter, Setter, MethodRefFlags);
} else {
E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(), MethodRefFlags);
@@ -1085,8 +1136,7 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
E->SelLocsKind = Record.readInt();
E->setDelegateInitCall(Record.readInt());
E->IsImplicit = Record.readInt();
- ObjCMessageExpr::ReceiverKind Kind
- = static_cast<ObjCMessageExpr::ReceiverKind>(Record.readInt());
+ auto Kind = static_cast<ObjCMessageExpr::ReceiverKind>(Record.readInt());
switch (Kind) {
case ObjCMessageExpr::Instance:
E->setInstanceReceiver(Record.readSubExpr());
@@ -1520,8 +1570,8 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
unsigned NumDecls = Record.readInt();
UnresolvedSet<8> Decls;
for (unsigned i = 0; i != NumDecls; ++i) {
- NamedDecl *D = ReadDeclAs<NamedDecl>();
- AccessSpecifier AS = (AccessSpecifier)Record.readInt();
+ auto *D = ReadDeclAs<NamedDecl>();
+ auto AS = (AccessSpecifier)Record.readInt();
Decls.addDecl(D, AS);
}
E->initializeResults(Record.getContext(), Decls.begin(), Decls.end());
@@ -1555,7 +1605,7 @@ void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) {
E->Loc = Range.getBegin();
E->RParenLoc = Range.getEnd();
- TypeSourceInfo **Args = E->getTrailingObjects<TypeSourceInfo *>();
+ auto **Args = E->getTrailingObjects<TypeSourceInfo *>();
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
Args[I] = GetTypeSourceInfo();
}
@@ -1639,7 +1689,7 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
E->NumParameters = Record.readInt();
E->ParamPack = ReadDeclAs<ParmVarDecl>();
E->NameLoc = ReadSourceLocation();
- ParmVarDecl **Parms = E->getTrailingObjects<ParmVarDecl *>();
+ auto **Parms = E->getTrailingObjects<ParmVarDecl *>();
for (unsigned i = 0, n = E->NumParameters; i != n; ++i)
Parms[i] = ReadDeclAs<ParmVarDecl>();
}
@@ -1647,7 +1697,7 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
VisitExpr(E);
E->State = Record.readSubExpr();
- auto VD = ReadDeclAs<ValueDecl>();
+ auto *VD = ReadDeclAs<ValueDecl>();
unsigned ManglingNumber = Record.readInt();
E->setExtendingDecl(VD, ManglingNumber);
}
@@ -1666,6 +1716,7 @@ void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
E->SourceExpr = Record.readSubExpr();
E->Loc = ReadSourceLocation();
+ E->setIsUnique(Record.readInt());
}
void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
@@ -1756,19 +1807,23 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) {
//===----------------------------------------------------------------------===//
namespace clang {
+
class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> {
ASTStmtReader *Reader;
ASTContext &Context;
+
public:
OMPClauseReader(ASTStmtReader *R, ASTRecordReader &Record)
: Reader(R), Context(Record.getContext()) {}
+
#define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *C);
#include "clang/Basic/OpenMPKinds.def"
OMPClause *readClause();
void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);
};
-}
+
+} // namespace clang
OMPClause *OMPClauseReader::readClause() {
OMPClause *C;
@@ -1801,7 +1856,7 @@ OMPClause *OMPClauseReader::readClause() {
C = new (Context) OMPScheduleClause();
break;
case OMPC_ordered:
- C = new (Context) OMPOrderedClause();
+ C = OMPOrderedClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_nowait:
C = new (Context) OMPNowaitClause();
@@ -1872,9 +1927,12 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_flush:
C = OMPFlushClause::CreateEmpty(Context, Reader->Record.readInt());
break;
- case OMPC_depend:
- C = OMPDependClause::CreateEmpty(Context, Reader->Record.readInt());
+ case OMPC_depend: {
+ unsigned NumVars = Reader->Record.readInt();
+ unsigned NumLoops = Reader->Record.readInt();
+ C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops);
break;
+ }
case OMPC_device:
C = new (Context) OMPDeviceClause();
break;
@@ -2032,6 +2090,10 @@ void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
C->setNumForLoops(Reader->Record.readSubExpr());
+ for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I)
+ C->setLoopNumIterations(I, Reader->Record.readSubExpr());
+ for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I)
+ C->setLoopCounter(I, Reader->Record.readSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation());
}
@@ -2340,10 +2402,11 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
+ for (unsigned I = 0; I != NumVars; ++I)
Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
- C->setCounterValue(Reader->Record.readSubExpr());
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
+ C->setLoopData(I, Reader->Record.readSubExpr());
}
void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
@@ -2393,7 +2456,7 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
Expr *AssociatedExpr = Reader->Record.readSubExpr();
- ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2487,7 +2550,7 @@ void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
Expr *AssociatedExpr = Reader->Record.readSubExpr();
- ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2529,7 +2592,7 @@ void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
Expr *AssociatedExpr = Reader->Record.readSubExpr();
- ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2579,7 +2642,7 @@ void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
Expr *AssociatedExpr = Reader->Record.readSubExpr();
- ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2622,7 +2685,7 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
Expr *AssociatedExpr = Reader->Record.readSubExpr();
- ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2632,6 +2695,7 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
+
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
E->setLocStart(ReadSourceLocation());
E->setLocEnd(ReadSourceLocation());
@@ -2917,6 +2981,7 @@ void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
+
void ASTStmtReader::VisitOMPDistributeParallelForDirective(
OMPDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
@@ -3025,7 +3090,6 @@ Expr *ASTReader::ReadSubExpr() {
// stack. Evaluation terminates when we see a STMT_STOP record, and
// the single remaining expression on the stack is our result.
Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
-
ReadingKindTracker ReadingKind(Read_Stmt, *this);
llvm::BitstreamCursor &Cursor = F.DeclsCursor;
@@ -3254,15 +3318,15 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
bool HadMultipleCandidates = Record.readInt();
- NamedDecl *FoundD = Record.readDeclAs<NamedDecl>();
- AccessSpecifier AS = (AccessSpecifier)Record.readInt();
+ auto *FoundD = Record.readDeclAs<NamedDecl>();
+ auto AS = (AccessSpecifier)Record.readInt();
DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS);
QualType T = Record.readType();
- ExprValueKind VK = static_cast<ExprValueKind>(Record.readInt());
- ExprObjectKind OK = static_cast<ExprObjectKind>(Record.readInt());
+ auto VK = static_cast<ExprValueKind>(Record.readInt());
+ auto OK = static_cast<ExprObjectKind>(Record.readInt());
Expr *Base = ReadSubExpr();
- ValueDecl *MemberD = Record.readDeclAs<ValueDecl>();
+ auto *MemberD = Record.readDeclAs<ValueDecl>();
SourceLocation MemberLoc = Record.readSourceLocation();
DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
bool IsArrow = Record.readInt();
@@ -3382,93 +3446,121 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_OBJC_STRING_LITERAL:
S = new (Context) ObjCStringLiteral(Empty);
break;
+
case EXPR_OBJC_BOXED_EXPRESSION:
S = new (Context) ObjCBoxedExpr(Empty);
break;
+
case EXPR_OBJC_ARRAY_LITERAL:
S = ObjCArrayLiteral::CreateEmpty(Context,
Record[ASTStmtReader::NumExprFields]);
break;
+
case EXPR_OBJC_DICTIONARY_LITERAL:
S = ObjCDictionaryLiteral::CreateEmpty(Context,
Record[ASTStmtReader::NumExprFields],
Record[ASTStmtReader::NumExprFields + 1]);
break;
+
case EXPR_OBJC_ENCODE:
S = new (Context) ObjCEncodeExpr(Empty);
break;
+
case EXPR_OBJC_SELECTOR_EXPR:
S = new (Context) ObjCSelectorExpr(Empty);
break;
+
case EXPR_OBJC_PROTOCOL_EXPR:
S = new (Context) ObjCProtocolExpr(Empty);
break;
+
case EXPR_OBJC_IVAR_REF_EXPR:
S = new (Context) ObjCIvarRefExpr(Empty);
break;
+
case EXPR_OBJC_PROPERTY_REF_EXPR:
S = new (Context) ObjCPropertyRefExpr(Empty);
break;
+
case EXPR_OBJC_SUBSCRIPT_REF_EXPR:
S = new (Context) ObjCSubscriptRefExpr(Empty);
break;
+
case EXPR_OBJC_KVC_REF_EXPR:
llvm_unreachable("mismatching AST file");
+
case EXPR_OBJC_MESSAGE_EXPR:
S = ObjCMessageExpr::CreateEmpty(Context,
Record[ASTStmtReader::NumExprFields],
Record[ASTStmtReader::NumExprFields + 1]);
break;
+
case EXPR_OBJC_ISA:
S = new (Context) ObjCIsaExpr(Empty);
break;
+
case EXPR_OBJC_INDIRECT_COPY_RESTORE:
S = new (Context) ObjCIndirectCopyRestoreExpr(Empty);
break;
+
case EXPR_OBJC_BRIDGED_CAST:
S = new (Context) ObjCBridgedCastExpr(Empty);
break;
+
case STMT_OBJC_FOR_COLLECTION:
S = new (Context) ObjCForCollectionStmt(Empty);
break;
+
case STMT_OBJC_CATCH:
S = new (Context) ObjCAtCatchStmt(Empty);
break;
+
case STMT_OBJC_FINALLY:
S = new (Context) ObjCAtFinallyStmt(Empty);
break;
+
case STMT_OBJC_AT_TRY:
S = ObjCAtTryStmt::CreateEmpty(Context,
Record[ASTStmtReader::NumStmtFields],
Record[ASTStmtReader::NumStmtFields + 1]);
break;
+
case STMT_OBJC_AT_SYNCHRONIZED:
S = new (Context) ObjCAtSynchronizedStmt(Empty);
break;
+
case STMT_OBJC_AT_THROW:
S = new (Context) ObjCAtThrowStmt(Empty);
break;
+
case STMT_OBJC_AUTORELEASE_POOL:
S = new (Context) ObjCAutoreleasePoolStmt(Empty);
break;
+
case EXPR_OBJC_BOOL_LITERAL:
S = new (Context) ObjCBoolLiteralExpr(Empty);
break;
+
case EXPR_OBJC_AVAILABILITY_CHECK:
S = new (Context) ObjCAvailabilityCheckExpr(Empty);
break;
+
case STMT_SEH_LEAVE:
S = new (Context) SEHLeaveStmt(Empty);
break;
+
case STMT_SEH_EXCEPT:
S = new (Context) SEHExceptStmt(Empty);
break;
+
case STMT_SEH_FINALLY:
S = new (Context) SEHFinallyStmt(Empty);
break;
+
case STMT_SEH_TRY:
S = new (Context) SEHTryStmt(Empty);
break;
+
case STMT_CXX_CATCH:
S = new (Context) CXXCatchStmt(Empty);
break;
@@ -3750,11 +3842,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
}
- case STMT_OMP_TARGET_TEAMS_DIRECTIVE: {
+ case STMT_OMP_TARGET_TEAMS_DIRECTIVE:
S = OMPTargetTeamsDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
- }
case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE: {
auto NumClauses = Record[ASTStmtReader::NumStmtFields];
@@ -3847,36 +3938,47 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_NULL_PTR_LITERAL:
S = new (Context) CXXNullPtrLiteralExpr(Empty);
break;
+
case EXPR_CXX_TYPEID_EXPR:
S = new (Context) CXXTypeidExpr(Empty, true);
break;
+
case EXPR_CXX_TYPEID_TYPE:
S = new (Context) CXXTypeidExpr(Empty, false);
break;
+
case EXPR_CXX_UUIDOF_EXPR:
S = new (Context) CXXUuidofExpr(Empty, true);
break;
+
case EXPR_CXX_PROPERTY_REF_EXPR:
S = new (Context) MSPropertyRefExpr(Empty);
break;
+
case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR:
S = new (Context) MSPropertySubscriptExpr(Empty);
break;
+
case EXPR_CXX_UUIDOF_TYPE:
S = new (Context) CXXUuidofExpr(Empty, false);
break;
+
case EXPR_CXX_THIS:
S = new (Context) CXXThisExpr(Empty);
break;
+
case EXPR_CXX_THROW:
S = new (Context) CXXThrowExpr(Empty);
break;
+
case EXPR_CXX_DEFAULT_ARG:
S = new (Context) CXXDefaultArgExpr(Empty);
break;
+
case EXPR_CXX_DEFAULT_INIT:
S = new (Context) CXXDefaultInitExpr(Empty);
break;
+
case EXPR_CXX_BIND_TEMPORARY:
S = new (Context) CXXBindTemporaryExpr(Empty);
break;
@@ -3884,12 +3986,15 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_SCALAR_VALUE_INIT:
S = new (Context) CXXScalarValueInitExpr(Empty);
break;
+
case EXPR_CXX_NEW:
S = new (Context) CXXNewExpr(Empty);
break;
+
case EXPR_CXX_DELETE:
S = new (Context) CXXDeleteExpr(Empty);
break;
+
case EXPR_CXX_PSEUDO_DESTRUCTOR:
S = new (Context) CXXPseudoDestructorExpr(Empty);
break;
@@ -4033,7 +4138,6 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_DEPENDENT_COAWAIT:
S = new (Context) DependentCoawaitExpr(Empty);
break;
-
}
// We hit a STMT_STOP, so we're done with this expression.
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 1e72ced2ee36..1a8d806e9d24 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -53,7 +53,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VersionTuple.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
@@ -79,16 +78,17 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.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/DJB.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
@@ -97,6 +97,7 @@
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -138,10 +139,10 @@ namespace clang {
ASTWriter &Writer;
ASTRecordWriter Record;
- /// \brief Type code that corresponds to the record generated.
+ /// Type code that corresponds to the record generated.
TypeCode Code = static_cast<TypeCode>(0);
- /// \brief Abbreviation to use for the record, if any.
+ /// Abbreviation to use for the record, if any.
unsigned AbbrevToUse = 0;
public:
@@ -276,6 +277,7 @@ void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
Record.push_back(C.getCC());
Record.push_back(C.getProducesResult());
Record.push_back(C.getNoCallerSavedRegs());
+ Record.push_back(C.getNoCfCheck());
if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult())
AbbrevToUse = 0;
@@ -293,7 +295,7 @@ static void addExceptionSpec(const FunctionProtoType *T,
Record.push_back(T->getNumExceptions());
for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
Record.AddTypeRef(T->getExceptionType(I));
- } else if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
+ } else if (isComputedNoexcept(T->getExceptionSpecType())) {
Record.AddStmt(T->getNoexceptExpr());
} else if (T->getExceptionSpecType() == EST_Uninstantiated) {
Record.AddDeclRef(T->getExceptionSpecDecl());
@@ -453,7 +455,15 @@ ASTTypeWriter::VisitDependentSizedExtVectorType(
Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
}
-void
+void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) {
+ Record.AddTypeRef(T->getElementType());
+ Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
+ Record.AddSourceLocation(T->getAttributeLoc());
+ Record.push_back(T->getVectorKind());
+ Code = TYPE_DEPENDENT_SIZED_VECTOR;
+}
+
+void
ASTTypeWriter::VisitDependentAddressSpaceType(
const DependentAddressSpaceType *T) {
Record.AddTypeRef(T->getPointeeType());
@@ -511,6 +521,7 @@ void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
Record.push_back(T->getKeyword());
Record.AddNestedNameSpecifier(T->getQualifier());
Record.AddTypeRef(T->getNamedType());
+ Record.AddDeclRef(T->getOwnedTagDecl());
Code = TYPE_ELABORATED;
}
@@ -661,7 +672,7 @@ void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(
SourceRange range = TL.getAttrOperandParensRange();
Record.AddSourceLocation(range.getBegin());
Record.AddSourceLocation(range.getEnd());
- Record.AddStmt(TL.getAttrExprOperand());
+ Record.AddStmt(TL.getAttrExprOperand());
}
void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
@@ -673,6 +684,11 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+void TypeLocWriter::VisitDependentVectorTypeLoc(
+ DependentVectorTypeLoc TL) {
+ Record.AddSourceLocation(TL.getNameLoc());
+}
+
void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
@@ -884,6 +900,7 @@ void ASTWriter::WriteTypeAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC
Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult
Abv->Add(BitCodeAbbrevOp(0)); // NoCallerSavedRegs
+ Abv->Add(BitCodeAbbrevOp(0)); // NoCfCheck
// FunctionProtoType
Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic
Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn
@@ -1104,6 +1121,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(UNUSED_FILESCOPED_DECLS);
RECORD(PPD_ENTITIES_OFFSETS);
RECORD(VTABLE_USES);
+ RECORD(PPD_SKIPPED_RANGES);
RECORD(REFERENCED_SELECTOR_POOL);
RECORD(TU_UPDATE_LEXICAL);
RECORD(SEMA_DECL_REFS);
@@ -1293,7 +1311,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_PRAGMA_COMMENT);
RECORD(DECL_PRAGMA_DETECT_MISMATCH);
RECORD(DECL_OMP_DECLARE_REDUCTION);
-
+
// Statements and Exprs can occur in the Decls and Types block.
AddStmtsExprs(Stream, Record);
@@ -1316,7 +1334,7 @@ void ASTWriter::WriteBlockInfoBlock() {
Stream.ExitBlock();
}
-/// \brief Prepares a path for being written to an AST file by converting it
+/// Prepares a path for being written to an AST file by converting it
/// to an absolute path and removing nested './'s.
///
/// \return \c true if the path was changed.
@@ -1326,7 +1344,7 @@ static bool cleanPathForOutput(FileManager &FileMgr,
return Changed | llvm::sys::path::remove_dots(Path);
}
-/// \brief Adjusts the given filename to only write out the portion of the
+/// Adjusts the given filename to only write out the portion of the
/// filename that is not part of the system root directory.
///
/// \param Filename the file name to adjust.
@@ -1436,7 +1454,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,
return Signature;
}
-/// \brief Write the control block.
+/// Write the control block.
void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
StringRef isysroot,
const std::string &OutputFile) {
@@ -1444,7 +1462,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);
RecordData Record;
-
+
// Metadata
auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>();
MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA));
@@ -1454,16 +1472,23 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps
+ MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PCHHasObjectFile
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev));
assert((!WritingModule || isysroot.empty()) &&
"writing module as a relocatable PCH?");
{
- RecordData::value_type Record[] = {METADATA, VERSION_MAJOR, VERSION_MINOR,
- CLANG_VERSION_MAJOR, CLANG_VERSION_MINOR,
- !isysroot.empty(), IncludeTimestamps,
- ASTHasCompilerErrors};
+ RecordData::value_type Record[] = {
+ METADATA,
+ VERSION_MAJOR,
+ VERSION_MINOR,
+ CLANG_VERSION_MAJOR,
+ CLANG_VERSION_MINOR,
+ !isysroot.empty(),
+ IncludeTimestamps,
+ Context.getLangOpts().BuildingPCHWithObjectFile,
+ ASTHasCompilerErrors};
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
}
@@ -1732,7 +1757,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
namespace {
-/// \brief An input file.
+/// An input file.
struct InputFileEntry {
const FileEntry *File;
bool IsSystemFile;
@@ -1842,7 +1867,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
// Source Manager Serialization
//===----------------------------------------------------------------------===//
-/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// Create an abbreviation for the SLocEntry that refers to a
/// file.
static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
@@ -1861,7 +1886,7 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
return Stream.EmitAbbrev(std::move(Abbrev));
}
-/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// Create an abbreviation for the SLocEntry that refers to a
/// buffer.
static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
@@ -1876,7 +1901,7 @@ static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
return Stream.EmitAbbrev(std::move(Abbrev));
}
-/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// Create an abbreviation for the SLocEntry that refers to a
/// buffer's blob.
static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream,
bool Compressed) {
@@ -1891,7 +1916,7 @@ static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream,
return Stream.EmitAbbrev(std::move(Abbrev));
}
-/// \brief Create an abbreviation for the SLocEntry that refers to a macro
+/// Create an abbreviation for the SLocEntry that refers to a macro
/// expansion.
static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
@@ -1902,6 +1927,7 @@ static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
return Stream.EmitAbbrev(std::move(Abbrev));
}
@@ -1911,11 +1937,11 @@ namespace {
// Trait used for the on-disk hash table of header search information.
class HeaderFileInfoTrait {
ASTWriter &Writer;
-
+
// Keep track of the framework names we've used during serialization.
SmallVector<char, 128> FrameworkStringData;
llvm::StringMap<unsigned> FrameworkNameOffset;
-
+
public:
HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {}
@@ -1928,7 +1954,7 @@ namespace {
using UnresolvedModule =
llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;
-
+
struct data_type {
const HeaderFileInfo &HFI;
ArrayRef<ModuleMap::KnownHeader> KnownHeaders;
@@ -1938,19 +1964,19 @@ namespace {
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
// match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key.
return llvm::hash_combine(key.Size, key.ModTime);
}
-
+
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);
+ endian::Writer LE(Out, little);
unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
LE.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
@@ -1966,7 +1992,7 @@ namespace {
void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
LE.write<uint64_t>(key.Size);
KeyLen -= 8;
LE.write<uint64_t>(key.ModTime);
@@ -1978,16 +2004,16 @@ namespace {
data_type_ref Data, unsigned DataLen) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
uint64_t Start = Out.tell(); (void)Start;
-
+
unsigned char Flags = (Data.HFI.isImport << 5)
| (Data.HFI.isPragmaOnce << 4)
| (Data.HFI.DirInfo << 1)
| Data.HFI.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);
LE.write<uint16_t>(Data.HFI.NumIncludes);
-
+
if (!Data.HFI.ControllingMacro)
LE.write<uint32_t>(Data.HFI.ControllingMacroID);
else
@@ -2000,10 +2026,10 @@ namespace {
= FrameworkNameOffset.find(Data.HFI.Framework);
if (Pos == FrameworkNameOffset.end()) {
Offset = FrameworkStringData.size() + 1;
- FrameworkStringData.append(Data.HFI.Framework.begin(),
+ FrameworkStringData.append(Data.HFI.Framework.begin(),
Data.HFI.Framework.end());
FrameworkStringData.push_back(0);
-
+
FrameworkNameOffset[Data.HFI.Framework] = Offset;
} else
Offset = Pos->second;
@@ -2027,14 +2053,14 @@ namespace {
assert(Out.tell() - Start == DataLen && "Wrong data length");
}
-
+
const char *strings_begin() const { return FrameworkStringData.begin(); }
const char *strings_end() const { return FrameworkStringData.end(); }
};
} // namespace
-/// \brief Write the header search block for the list of files that
+/// Write the header search block for the list of files that
///
/// \param HS The header search structure to save.
void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
@@ -2100,7 +2126,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
SmallVector<const FileEntry *, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
-
+
if (FilesByUID.size() > HS.header_file_size())
FilesByUID.resize(HS.header_file_size());
@@ -2148,7 +2174,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
llvm::raw_svector_ostream Out(TableData);
// Make sure that no bucket is at offset 0
- endian::Writer<little>(Out).write<uint32_t>(0);
+ endian::write<uint32_t>(Out, 0, little);
BucketOffset = Generator.Emit(Out, GeneratorTrait);
}
@@ -2162,13 +2188,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
-
+
// Write the header search table
RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,
NumHeaderSearchEntries, TableData.size()};
TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end());
Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);
-
+
// Free all of the strings we had to duplicate.
for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)
free(const_cast<char *>(SavedStrings[I]));
@@ -2198,7 +2224,7 @@ static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob,
Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob);
}
-/// \brief Writes the block containing the serialized form of the
+/// Writes the block containing the serialized form of the
/// source manager.
///
/// TODO: We should probably use an on-disk hash table (stored in a
@@ -2268,7 +2294,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Record.push_back(InputFileIDs[Content->OrigEntry]);
Record.push_back(File.NumCreatedFIDs);
-
+
FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID);
if (FDI != FileDeclIDs.end()) {
Record.push_back(FDI->second->FirstDeclIndex);
@@ -2277,9 +2303,9 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Record.push_back(0);
Record.push_back(0);
}
-
+
Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);
-
+
if (Content->BufferOverridden || Content->IsTransient)
EmitBlob = true;
} else {
@@ -2318,6 +2344,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
? SourceLocation()
: Expansion.getExpansionLocEnd(),
Record);
+ Record.push_back(Expansion.isExpansionTokenRange());
// Compute the token length for this macro expansion.
unsigned NextOffset = SourceMgr.getNextLocalOffset();
@@ -2420,7 +2447,7 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
return false;
}
-/// \brief Writes the block containing the serialized form of the
+/// Writes the block containing the serialized form of the
/// preprocessor.
void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
@@ -2480,8 +2507,8 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
MacroIdentifiers.push_back(Id.second);
// Sort the set of macro definitions that need to be serialized by the
// name of the macro, to provide a stable ordering.
- std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
- llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
+ llvm::less_ptr<IdentifierInfo>());
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
@@ -2540,7 +2567,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Record.clear();
}
- /// \brief Offsets of each of the macros into the bitstream, indexed by
+ /// Offsets of each of the macros into the bitstream, indexed by
/// the local macro ID
///
/// For each identifier that is associated with a macro, this map
@@ -2640,8 +2667,8 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
// If the preprocessor has a preprocessing record, emit it.
unsigned NumPreprocessingRecords = 0;
using namespace llvm;
-
- // Set up the abbreviation for
+
+ // Set up the abbreviation for
unsigned InclusionAbbrev = 0;
{
auto Abbrev = std::make_shared<BitCodeAbbrev>();
@@ -2653,15 +2680,15 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
}
-
- unsigned FirstPreprocessorEntityID
- = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0)
+
+ unsigned FirstPreprocessorEntityID
+ = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0)
+ NUM_PREDEF_PP_ENTITY_IDS;
unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID;
RecordData Record;
for (PreprocessingRecord::iterator E = PPRec.local_begin(),
EEnd = PPRec.local_end();
- E != EEnd;
+ E != EEnd;
(void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) {
Record.clear();
@@ -2702,7 +2729,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
continue;
}
-
+
llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
}
Stream.ExitBlock();
@@ -2726,6 +2753,26 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
bytes(PreprocessedEntityOffsets));
}
+
+ // Write the skipped region table for the preprocessing record.
+ ArrayRef<SourceRange> SkippedRanges = PPRec.getSkippedRanges();
+ if (SkippedRanges.size() > 0) {
+ std::vector<PPSkippedRange> SerializedSkippedRanges;
+ SerializedSkippedRanges.reserve(SkippedRanges.size());
+ for (auto const& Range : SkippedRanges)
+ SerializedSkippedRanges.emplace_back(Range);
+
+ using namespace llvm;
+ auto Abbrev = std::make_shared<BitCodeAbbrev>();
+ Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
+
+ Record.clear();
+ Record.push_back(PPD_SKIPPED_RANGES);
+ Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,
+ bytes(SerializedSkippedRanges));
+ }
}
unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
@@ -2755,21 +2802,21 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) {
return ID;
}
-/// \brief Compute the number of modules within the given tree (including the
+/// Compute the number of modules within the given tree (including the
/// given module).
static unsigned getNumberOfModules(Module *Mod) {
unsigned ChildModules = 0;
for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub)
ChildModules += getNumberOfModules(*Sub);
-
+
return ChildModules + 1;
}
void ASTWriter::WriteSubmodules(Module *WritingModule) {
// Enter the submodule description block.
Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);
-
+
// Write the abbreviations needed for the submodules block.
using namespace llvm;
@@ -2786,6 +2833,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh...
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
@@ -2862,7 +2910,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
getNumberOfModules(WritingModule),
FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS};
Stream.EmitRecord(SUBMODULE_METADATA, Record);
-
+
// Write all of the submodules.
std::queue<Module *> Q;
Q.push(WritingModule);
@@ -2890,7 +2938,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Mod->InferSubmodules,
Mod->InferExplicitSubmodules,
Mod->InferExportWildcard,
- Mod->ConfigMacrosExhaustive};
+ Mod->ConfigMacrosExhaustive,
+ Mod->ModuleMapIsPrivate};
Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
}
@@ -2938,7 +2987,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName());
}
- // Emit the imports.
+ // Emit the imports.
if (!Mod->Imports.empty()) {
RecordData Record;
for (auto *I : Mod->Imports)
@@ -2946,7 +2995,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
}
- // Emit the exports.
+ // Emit the exports.
if (!Mod->Exports.empty()) {
RecordData Record;
for (const auto &E : Mod->Exports) {
@@ -2996,12 +3045,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
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);
}
-
+
Stream.ExitBlock();
assert((NextSubmoduleID - FirstSubmoduleID ==
@@ -3040,7 +3089,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
unsigned &DiagStateID = DiagStateIDMap[State];
Record.push_back(DiagStateID);
-
+
if (DiagStateID == 0) {
DiagStateID = ++CurrID;
@@ -3071,8 +3120,11 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
!FileIDAndFile.second.HasLocalTransitions)
continue;
++NumLocations;
- AddSourceLocation(Diag.SourceMgr->getLocForStartOfFile(FileIDAndFile.first),
- Record);
+
+ SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0);
+ assert(!Loc.isInvalid() && "start loc for valid FileID is invalid");
+ AddSourceLocation(Loc, Record);
+
Record.push_back(FileIDAndFile.second.StateTransitions.size());
for (auto &StatePoint : FileIDAndFile.second.StateTransitions) {
Record.push_back(StatePoint.Offset);
@@ -3099,7 +3151,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
// Type Serialization
//===----------------------------------------------------------------------===//
-/// \brief Write the representation of a type to the AST stream.
+/// Write the representation of a type to the AST stream.
void ASTWriter::WriteType(QualType T) {
TypeIdx &IdxRef = TypeIdxs[T];
if (IdxRef.getIndex() == 0) // we haven't seen this type before.
@@ -3131,11 +3183,11 @@ void ASTWriter::WriteType(QualType T) {
// Declaration Serialization
//===----------------------------------------------------------------------===//
-/// \brief Write the block containing all of the declaration IDs
+/// Write the block containing all of the declaration IDs
/// lexically declared within the given DeclContext.
///
/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
-/// bistream, or 0 if no block was written.
+/// bitstream, or 0 if no block was written.
uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
DeclContext *DC) {
if (DC->decls_empty())
@@ -3190,8 +3242,8 @@ void ASTWriter::WriteFileDeclIDsMap() {
SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs(
FileDeclIDs.begin(), FileDeclIDs.end());
- std::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(),
- llvm::less_first());
+ llvm::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(),
+ llvm::less_first());
// Join the vectors of DeclIDs from all files.
SmallVector<DeclID, 256> FileGroupedDeclIDs;
@@ -3214,6 +3266,9 @@ void ASTWriter::WriteFileDeclIDsMap() {
void ASTWriter::WriteComments() {
Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3);
+ auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); });
+ if (!PP->getPreprocessorOpts().WriteCommentListToPCH)
+ return;
ArrayRef<RawComment *> RawComments = Context->Comments.getComments();
RecordData Record;
for (const auto *I : RawComments) {
@@ -3224,7 +3279,6 @@ void ASTWriter::WriteComments() {
Record.push_back(I->isAlmostTrailingComment());
Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record);
}
- Stream.ExitBlock();
}
//===----------------------------------------------------------------------===//
@@ -3261,7 +3315,7 @@ public:
data_type_ref Methods) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
LE.write<uint16_t>(KeyLen);
unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
@@ -3280,7 +3334,7 @@ public:
void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
uint64_t Start = Out.tell();
assert((Start >> 32) == 0 && "Selector key offset too large");
Writer.SetSelectorOffset(Sel, Start);
@@ -3297,7 +3351,7 @@ public:
data_type_ref Methods, unsigned DataLen) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
uint64_t Start = Out.tell(); (void)Start;
LE.write<uint32_t>(Methods.ID);
unsigned NumInstanceMethods = 0;
@@ -3343,7 +3397,7 @@ public:
} // namespace
-/// \brief Write ObjC data: selectors and the method pool.
+/// Write ObjC data: selectors and the method pool.
///
/// The method pool contains both instance and factory methods, stored
/// in an on-disk hash table indexed by the selector. The hash table also
@@ -3409,7 +3463,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
ASTMethodPoolTrait Trait(*this);
llvm::raw_svector_ostream Out(MethodPool);
// Make sure that no bucket is at offset 0
- endian::Writer<little>(Out).write<uint32_t>(0);
+ endian::write<uint32_t>(Out, 0, little);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -3447,7 +3501,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
}
}
-/// \brief Write the selectors referenced in @selector expression into AST file.
+/// Write the selectors referenced in @selector expression into AST file.
void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
using namespace llvm;
@@ -3522,8 +3576,8 @@ class ASTIdentifierTableTrait {
bool IsModule;
bool NeedDecls;
ASTWriter::RecordData *InterestingIdentifierOffsets;
-
- /// \brief Determines whether this is an "interesting" identifier that needs a
+
+ /// Determines whether this is an "interesting" identifier that needs a
/// full IdentifierInfo structure written into the hash table. Notably, this
/// doesn't check whether the name has macros defined; use PublicMacroIterator
/// to check that.
@@ -3558,7 +3612,7 @@ public:
bool needDecls() const { return NeedDecls; }
static hash_value_type ComputeHash(const IdentifierInfo* II) {
- return llvm::HashString(II->getName());
+ return llvm::djbHash(II->getName());
}
bool isInterestingIdentifier(const IdentifierInfo *II) {
@@ -3591,7 +3645,7 @@ public:
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen);
LE.write<uint16_t>(DataLen);
@@ -3620,7 +3674,7 @@ public:
IdentID ID, unsigned) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
auto MacroOffset = Writer.getMacroDirectivesOffset(II);
if (!isInterestingIdentifier(II, MacroOffset)) {
@@ -3665,12 +3719,12 @@ public:
} // namespace
-/// \brief Write the identifier table into the AST file.
+/// Write the identifier table into the AST file.
///
/// The identifier table consists of a blob containing string data
/// (the actual identifiers themselves) and a separate "offsets" index
/// that maps identifier IDs to locations within the blob.
-void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
+void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
IdentifierResolver &IdResolver,
bool IsModule) {
using namespace llvm;
@@ -3695,7 +3749,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
IIs.push_back(ID.second);
// Sort the identifiers lexicographically before getting them references so
// that their order is stable.
- std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs)
if (Trait.isInterestingNonMacroIdentifier(II))
getIdentifierRef(II);
@@ -3724,7 +3778,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
- endian::Writer<little>(Out).write<uint32_t>(0);
+ endian::write<uint32_t>(Out, 0, little);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -3820,8 +3874,7 @@ public:
using namespace llvm::support;
- endian::Writer<little>(Out)
- .write<uint32_t>(Writer.getChain()->getModuleFileID(F));
+ endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F), little);
}
std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,
@@ -3829,7 +3882,7 @@ public:
data_type_ref Lookup) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
unsigned KeyLen = 1;
switch (Name.getKind()) {
case DeclarationName::Identifier:
@@ -3863,7 +3916,7 @@ public:
void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
LE.write<uint8_t>(Name.getKind());
switch (Name.getKind()) {
case DeclarationName::Identifier:
@@ -3895,7 +3948,7 @@ public:
unsigned DataLen) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
uint64_t Start = Out.tell(); (void)Start;
for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)
LE.write<uint32_t>(DeclIDs[I]);
@@ -3993,7 +4046,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
}
// Sort the names into a stable order.
- std::sort(Names.begin(), Names.end());
+ llvm::sort(Names.begin(), Names.end());
if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
// We need to establish an ordering of constructor and conversion function
@@ -4096,7 +4149,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr);
}
-/// \brief Write the block containing all of the declaration IDs
+/// Write the block containing all of the declaration IDs
/// visible from the given DeclContext.
///
/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
@@ -4130,7 +4183,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
std::make_pair(Entry.first, Entry.second.getLookupResult()));
}
- std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
+ llvm::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
for (auto &NameAndResult : LookupResults) {
DeclarationName Name = NameAndResult.first;
DeclContext::lookup_result Result = NameAndResult.second;
@@ -4186,7 +4239,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
return Offset;
}
-/// \brief Write an UPDATE_VISIBLE block for the given context.
+/// Write an UPDATE_VISIBLE block for the given context.
///
/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing
/// DeclContext in a dependent AST file. As such, they only exist for the TU
@@ -4211,13 +4264,13 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);
}
-/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
+/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
RecordData::value_type Record[] = {Opts.getInt()};
Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
}
-/// \brief Write an OPENCL_EXTENSIONS block for the given OpenCLOptions.
+/// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions.
void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
if (!SemaRef.Context.getLangOpts().OpenCL)
return;
@@ -4274,16 +4327,16 @@ void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
void ASTWriter::WriteObjCCategories() {
SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
RecordData Categories;
-
+
for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {
unsigned Size = 0;
unsigned StartIndex = Categories.size();
-
+
ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];
-
+
// Allocate space for the size.
Categories.push_back(0);
-
+
// Add the categories.
for (ObjCInterfaceDecl::known_categories_iterator
Cat = Class->known_categories_begin(),
@@ -4292,10 +4345,10 @@ void ASTWriter::WriteObjCCategories() {
assert(getDeclID(*Cat) != 0 && "Bogus category");
AddDeclRef(*Cat, Categories);
}
-
+
// Update the size.
Categories[StartIndex] = Size;
-
+
// Record this interface -> category map.
ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };
CategoriesMap.push_back(CatInfo);
@@ -4344,7 +4397,7 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
}
-/// \brief Write the state of 'pragma clang optimize' at the end of the module.
+/// Write the state of 'pragma clang optimize' at the end of the module.
void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
RecordData Record;
SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation();
@@ -4352,14 +4405,14 @@ void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);
}
-/// \brief Write the state of 'pragma ms_struct' at the end of the module.
+/// Write the state of 'pragma ms_struct' at the end of the module.
void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) {
RecordData Record;
Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF);
Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record);
}
-/// \brief Write the state of 'pragma pointers_to_members' at the end of the
+/// Write the state of 'pragma pointers_to_members' at the end of the
//module.
void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) {
RecordData Record;
@@ -4368,7 +4421,7 @@ void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) {
Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record);
}
-/// \brief Write the state of 'pragma pack' at the end of the module.
+/// Write the state of 'pragma pack' at the end of the module.
void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {
// Don't serialize pragma pack state for modules, since it should only take
// effect on a per-submodule basis.
@@ -4427,7 +4480,7 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
// General Serialization Routines
//===----------------------------------------------------------------------===//
-/// \brief Emit the list of attributes to the specified record.
+/// Emit the list of attributes to the specified record.
void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
auto &Record = *this;
Record.push_back(Attrs.size());
@@ -4501,7 +4554,7 @@ void ASTWriter::AddVersionTuple(const VersionTuple &Version,
Record.push_back(0);
}
-/// \brief Note that the identifier II occurs at the given offset
+/// Note that the identifier II occurs at the given offset
/// within the identifier table.
void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
IdentID ID = IdentifierIDs[II];
@@ -4511,7 +4564,7 @@ void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
IdentifierOffsets[ID - FirstIdentID] = Offset;
}
-/// \brief Note that the selector Sel occurs at the given offset
+/// Note that the selector Sel occurs at the given offset
/// within the method pool/selector table.
void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
unsigned ID = SelectorIDs[Sel];
@@ -4555,7 +4608,7 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef,
WritingAST = true;
ASTHasCompilerErrors = hasErrors;
-
+
// Emit the file header.
Stream.Emit((unsigned)'C', 8);
Stream.Emit((unsigned)'P', 8);
@@ -4603,7 +4656,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// Make sure that the AST reader knows to finalize itself.
if (Chain)
Chain->finalizeForWriting();
-
+
ASTContext &Context = SemaRef.Context;
Preprocessor &PP = SemaRef.PP;
@@ -4644,7 +4697,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// headers.
RecordData TentativeDefinitions;
AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions);
-
+
// Build a record containing all of the file scoped decls in this file.
RecordData UnusedFileScopedDecls;
if (!isModule)
@@ -4732,13 +4785,15 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// analyze later in AST.
RecordData DeleteExprsToAnalyze;
- for (const auto &DeleteExprsInfo :
- SemaRef.getMismatchingDeleteExpressions()) {
- AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);
- DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());
- for (const auto &DeleteLoc : DeleteExprsInfo.second) {
- AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);
- DeleteExprsToAnalyze.push_back(DeleteLoc.second);
+ if (!isModule) {
+ for (const auto &DeleteExprsInfo :
+ SemaRef.getMismatchingDeleteExpressions()) {
+ AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);
+ DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());
+ for (const auto &DeleteLoc : DeleteExprsInfo.second) {
+ AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);
+ DeleteExprsToAnalyze.push_back(DeleteLoc.second);
+ }
}
}
@@ -4765,7 +4820,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
}
}
-
+
auto Abv = std::make_shared<BitCodeAbbrev>();
Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
@@ -4787,7 +4842,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// If we have any extern "C" names, write out a visible update for them.
if (Context.ExternCContext)
WriteDeclContextVisibleUpdate(Context.ExternCContext);
-
+
// If the translation unit has an anonymous namespace, and we don't already
// have an update block for it, write it as an update block.
// FIXME: Why do we not do this if there's already an update block?
@@ -4826,7 +4881,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
IIs.push_back(II);
}
// Sort the identifiers to visit based on their name.
- std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs) {
for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
DEnd = SemaRef.IdResolver.end();
@@ -4876,7 +4931,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// declaration-id:i32
// 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.
@@ -4890,7 +4945,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
for (ModuleFile &M : Chain->ModuleMgr) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
LE.write<uint8_t>(static_cast<uint8_t>(M.Kind));
StringRef Name =
M.Kind == MK_PrebuiltModule || M.Kind == MK_ExplicitModule
@@ -4970,7 +5025,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteOpenCLExtensionDecls(SemaRef);
WriteCUDAPragmas(SemaRef);
- // If we're emitting a module, write out the submodule information.
+ // If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
@@ -5020,7 +5075,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// Write the record containing CUDA-specific declaration references.
if (!CUDASpecialDeclRefs.empty())
Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);
-
+
// Write the delegating constructors.
if (!DelegatingCtorDecls.empty())
Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);
@@ -5063,7 +5118,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
};
// Sort and deduplicate module IDs.
- std::sort(Imports.begin(), Imports.end(), Cmp);
+ llvm::sort(Imports.begin(), Imports.end(), Cmp);
Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq),
Imports.end());
@@ -5167,6 +5222,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
UpdatedDeclContexts.insert(RD->getPrimaryContext());
+ Record.push_back(RD->isParamDestroyedInCallee());
+ Record.push_back(RD->getArgPassingRestrictions());
Record.AddCXXDefinitionData(RD);
Record.AddOffset(WriteDeclContextLexicalBlock(
*Context, const_cast<CXXRecordDecl *>(RD)));
@@ -5323,7 +5380,7 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) {
MacroID ASTWriter::getMacroID(MacroInfo *MI) {
if (!MI || MI->isBuiltinMacro())
return 0;
-
+
assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!");
return MacroIDs[MI];
}
@@ -5406,12 +5463,11 @@ void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) {
return;
}
+ AddTypeRef(TInfo->getType());
AddTypeLoc(TInfo->getTypeLoc());
}
void ASTRecordWriter::AddTypeLoc(TypeLoc TL) {
- AddTypeRef(TL.getType());
-
TypeLocWriter TLW(*this);
for (; !TL.isNull(); TL = TL.getNextTypeLoc())
TLW.Visit(TL);
@@ -5467,12 +5523,12 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) {
if (!D) {
return 0;
}
-
+
// If D comes from an AST file, its declaration ID is already known and
// fixed.
if (D->isFromASTFile())
return D->getGlobalID();
-
+
assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");
DeclID &ID = DeclIDs[D];
if (ID == 0) {
@@ -5516,7 +5572,9 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) {
return;
// FIXME: ParmVarDecls that are part of a function type of a parameter of
// a function/objc method, should not have TU as lexical context.
- if (isa<ParmVarDecl>(D))
+ // TemplateTemplateParmDecls that are part of an alias template, should not
+ // have TU as lexical context.
+ if (isa<ParmVarDecl>(D) || isa<TemplateTemplateParmDecl>(D))
return;
SourceManager &SM = Context->getSourceManager();
@@ -5734,6 +5792,7 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
+ AddTypeRef(NNS.getTypeLoc().getType());
AddTypeLoc(NNS.getTypeLoc());
AddSourceLocation(NNS.getLocalSourceRange().getEnd());
break;
@@ -5792,7 +5851,7 @@ void ASTRecordWriter::AddTemplateName(TemplateName Name) {
AddTemplateName(subst->getReplacement());
break;
}
-
+
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack();
@@ -5855,7 +5914,7 @@ void ASTRecordWriter::AddTemplateParameterList(
AddDeclRef(P);
}
-/// \brief Emit a template argument list.
+/// Emit a template argument list.
void ASTRecordWriter::AddTemplateArgumentList(
const TemplateArgumentList *TemplateArgs) {
assert(TemplateArgs && "No TemplateArgs!");
@@ -5892,7 +5951,7 @@ void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
Record->push_back(Base.getInheritConstructors());
AddTypeSourceInfo(Base.getTypeSourceInfo());
AddSourceRange(Base.getSourceRange());
- AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
+ AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
: SourceLocation());
}
@@ -5965,7 +6024,9 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Data.Polymorphic);
Record->push_back(Data.Abstract);
Record->push_back(Data.IsStandardLayout);
- Record->push_back(Data.HasNoNonEmptyBases);
+ Record->push_back(Data.IsCXX11StandardLayout);
+ Record->push_back(Data.HasBasesWithFields);
+ Record->push_back(Data.HasBasesWithNonStaticDataMembers);
Record->push_back(Data.HasPrivateFields);
Record->push_back(Data.HasProtectedFields);
Record->push_back(Data.HasPublicFields);
@@ -5986,11 +6047,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Data.DefaultedMoveAssignmentIsDeleted);
Record->push_back(Data.DefaultedDestructorIsDeleted);
Record->push_back(Data.HasTrivialSpecialMembers);
+ Record->push_back(Data.HasTrivialSpecialMembersForCall);
Record->push_back(Data.DeclaredNonTrivialSpecialMembers);
+ Record->push_back(Data.DeclaredNonTrivialSpecialMembersForCall);
Record->push_back(Data.HasIrrelevantDestructor);
Record->push_back(Data.HasConstexprNonCopyMoveConstructor);
Record->push_back(Data.HasDefaultedDefaultConstructor);
- Record->push_back(Data.CanPassInRegisters);
Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr);
Record->push_back(Data.HasConstexprDefaultConstructor);
Record->push_back(Data.HasNonLiteralTypeFieldsOrBases);
@@ -6024,9 +6086,9 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
AddUnresolvedSet(Data.Conversions.get(*Writer->Context));
AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context));
- // Data.Definition is the owning decl, no need to write it.
+ // Data.Definition is the owning decl, no need to write it.
AddDeclRef(D->getFirstFriend());
-
+
// Add lambda-specific data.
if (Data.IsLambda) {
auto &Lambda = D->getLambdaData();
@@ -6319,7 +6381,7 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
assert(!WritingAST && "Already writing the AST!");
if (!IFD->isFromASTFile())
return; // Declaration not imported from PCH.
-
+
assert(IFD->getDefinition() && "Category on a class without a definition?");
ObjCClassesWithCategories.insert(
const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index bb72a3b383ea..7286f2cac178 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
@@ -264,12 +265,13 @@ void ASTDeclWriter::Visit(Decl *D) {
// abbreviation infrastructure requires that arrays are encoded last, so
// we handle it here in the case of those classes derived from DeclaratorDecl
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- Record.AddTypeSourceInfo(DD->getTypeSourceInfo());
+ if (auto *TInfo = DD->getTypeSourceInfo())
+ Record.AddTypeLoc(TInfo->getTypeLoc());
}
// Handle FunctionDecl's body here and write it after all other Stmts/Exprs
// have been written. We want it last because we will not read it back when
- // retrieving it from the AST, we'll just lazily set the offset.
+ // retrieving it from the AST, we'll just lazily set the offset.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Record.push_back(FD->doesThisDeclarationHaveABody());
if (FD->doesThisDeclarationHaveABody())
@@ -429,6 +431,8 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
Record.push_back(D->isScoped());
Record.push_back(D->isScopedUsingClassTag());
Record.push_back(D->isFixed());
+ Record.push_back(D->getODRHash());
+
if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) {
Record.AddDeclRef(MemberInfo->getInstantiatedFrom());
Record.push_back(MemberInfo->getTemplateSpecializationKind());
@@ -465,6 +469,11 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
Record.push_back(D->isAnonymousStructOrUnion());
Record.push_back(D->hasObjectMember());
Record.push_back(D->hasVolatileMember());
+ Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize());
+ Record.push_back(D->isNonTrivialToPrimitiveCopy());
+ Record.push_back(D->isNonTrivialToPrimitiveDestroy());
+ Record.push_back(D->isParamDestroyedInCallee());
+ Record.push_back(D->getArgPassingRestrictions());
if (D->getDeclContext() == D->getLexicalDeclContext() &&
!D->hasAttrs() &&
@@ -507,6 +516,9 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
Record.push_back(D->hasExtInfo());
if (D->hasExtInfo())
Record.AddQualifierInfo(*D->getExtInfo());
+ // The location information is deferred until the end of the record.
+ Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType()
+ : QualType());
}
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
@@ -514,10 +526,10 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
VisitDeclaratorDecl(D);
Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
Record.push_back(D->getIdentifierNamespace());
-
+
// FunctionDecl's body is handled last at ASTWriterDecl::Visit,
// after everything else is written.
-
+
Record.push_back((int)D->SClass); // FIXME: stable encoding
Record.push_back(D->IsInline);
Record.push_back(D->IsInlineSpecified);
@@ -528,12 +540,14 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->HasWrittenPrototype);
Record.push_back(D->IsDeleted);
Record.push_back(D->IsTrivial);
+ Record.push_back(D->IsTrivialForCall);
Record.push_back(D->IsDefaulted);
Record.push_back(D->IsExplicitlyDefaulted);
Record.push_back(D->HasImplicitReturnZero);
Record.push_back(D->IsConstexpr);
Record.push_back(D->UsesSEHTry);
Record.push_back(D->HasSkippedBody);
+ Record.push_back(D->IsMultiVersion);
Record.push_back(D->IsLateTemplateParsed);
Record.push_back(D->getLinkageInternal());
Record.AddSourceLocation(D->getLocEnd());
@@ -562,10 +576,10 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.AddDeclRef(FTSInfo->getTemplate());
Record.push_back(FTSInfo->getTemplateSpecializationKind());
-
+
// Template arguments.
Record.AddTemplateArgumentList(FTSInfo->TemplateArguments);
-
+
// Template args as written.
Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr);
if (FTSInfo->TemplateArgumentsAsWritten) {
@@ -577,7 +591,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc);
Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc);
}
-
+
Record.AddSourceLocation(FTSInfo->getPointOfInstantiation());
if (D->isCanonicalDecl()) {
@@ -590,12 +604,12 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
DependentFunctionTemplateSpecializationInfo *
DFTSInfo = D->getDependentSpecializationInfo();
-
+
// Templates.
Record.push_back(DFTSInfo->getNumTemplates());
for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i)
Record.AddDeclRef(DFTSInfo->getTemplate(i));
-
+
// Templates args.
Record.push_back(DFTSInfo->getNumTemplateArgs());
for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i)
@@ -693,7 +707,7 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (D->isThisDeclarationADefinition()) {
// Write the DefinitionData
ObjCInterfaceDecl::DefinitionData &Data = D->data();
-
+
Record.AddTypeSourceInfo(D->getSuperClassTInfo());
Record.AddSourceLocation(D->getEndOfDefinitionLoc());
Record.push_back(Data.HasDesignatedInitializers);
@@ -704,7 +718,7 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
Record.AddDeclRef(P);
for (const auto &PL : D->protocol_locs())
Record.AddSourceLocation(PL);
-
+
// Write out the protocols that are transitively referenced.
Record.push_back(Data.AllReferencedProtocols.size());
for (ObjCList<ObjCProtocolDecl>::iterator
@@ -713,17 +727,17 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
P != PEnd; ++P)
Record.AddDeclRef(*P);
-
+
if (ObjCCategoryDecl *Cat = D->getCategoryListRaw()) {
// Ensure that we write out the set of categories for this class.
Writer.ObjCClassesWithCategories.insert(D);
-
+
// Make sure that the categories get serialized.
for (; Cat; Cat = Cat->getNextClassCategoryRaw())
(void)Writer.GetDeclRef(Cat);
}
- }
-
+ }
+
Code = serialization::DECL_OBJC_INTERFACE;
}
@@ -751,7 +765,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
VisitRedeclarable(D);
VisitObjCContainerDecl(D);
-
+
Record.push_back(D->isThisDeclarationADefinition());
if (D->isThisDeclarationADefinition()) {
Record.push_back(D->protocol_size());
@@ -760,7 +774,7 @@ void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
for (const auto &PL : D->protocol_locs())
Record.AddSourceLocation(PL);
}
-
+
Code = serialization::DECL_OBJC_PROTOCOL;
}
@@ -912,6 +926,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
Record.push_back(D->isCXXForRangeDecl());
+ Record.push_back(D->isObjCForDecl());
Record.push_back(D->isARCPseudoStrong());
Record.push_back(D->isInline());
Record.push_back(D->isInlineSpecified());
@@ -949,7 +964,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
if (ModulesCodegen)
Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));
}
-
+
enum {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
};
@@ -1143,7 +1158,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
Record.AddDeclRef(D->getAnonymousNamespace());
Code = serialization::DECL_NAMESPACE;
- if (Writer.hasChain() && D->isAnonymousNamespace() &&
+ if (Writer.hasChain() && D->isAnonymousNamespace() &&
D == D->getMostRecentDecl()) {
// This is a most recent reopening of the anonymous namespace. If its parent
// is in a previous PCH (or is the TU), mark that parent for update, because
@@ -1192,6 +1207,7 @@ void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
VisitRedeclarable(D);
VisitNamedDecl(D);
Record.AddDeclRef(D->getTargetDecl());
+ Record.push_back(D->getIdentifierNamespace());
Record.AddDeclRef(D->UsingOrNextShadow);
Record.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D));
Code = serialization::DECL_USING_SHADOW;
@@ -1396,7 +1412,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization());
}
-
+
VisitTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace());
}
@@ -1431,7 +1447,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
Record.push_back(D->isCanonicalDecl());
if (D->isCanonicalDecl()) {
- // When reading, we'll add it to the folding set of the following template.
+ // When reading, we'll add it to the folding set of the following template.
Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl());
}
@@ -1557,18 +1573,18 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
// memory.
if (D->isExpandedParameterPack())
Record.push_back(D->getNumExpansionTypes());
-
+
VisitDeclaratorDecl(D);
// TemplateParmPosition.
Record.push_back(D->getDepth());
Record.push_back(D->getPosition());
-
+
if (D->isExpandedParameterPack()) {
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
Record.AddTypeRef(D->getExpansionType(I));
Record.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I));
}
-
+
Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
} else {
// Rest of NonTypeTemplateParmDecl.
@@ -1625,7 +1641,7 @@ void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
Code = serialization::DECL_STATIC_ASSERT;
}
-/// \brief Emit the DeclContext part of a declaration context decl.
+/// Emit the DeclContext part of a declaration context decl.
void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC));
Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC));
@@ -1693,7 +1709,7 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
Record.AddDeclRef(FirstLocal);
}
- // Make sure that we serialize both the previous and the most-recent
+ // Make sure that we serialize both the previous and the most-recent
// declarations, which (transitively) ensures that all declarations in the
// chain get serialized.
//
@@ -1763,11 +1779,11 @@ void ASTWriter::WriteDeclAbbrevs() {
// DeclaratorDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
// FieldDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
// Type Source Info
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
DeclFieldAbbrev = Stream.EmitAbbrev(std::move(Abv));
@@ -1796,6 +1812,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// DeclaratorDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
// FieldDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
@@ -1803,7 +1820,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize
// Type Source Info
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
DeclObjCIvarAbbrev = Stream.EmitAbbrev(std::move(Abv));
@@ -1851,6 +1867,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScoped
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScopedUsingClassTag
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isFixed
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));// ODRHash
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedMembEnum
// DC
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset
@@ -1896,6 +1913,18 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasVolatileMember
+
+ // isNonTrivialToPrimitiveDefaultInitialize
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ // isNonTrivialToPrimitiveCopy
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ // isNonTrivialToPrimitiveDestroy
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ // isParamDestroyedInCallee
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ // getArgPassingRestrictions
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));
+
// DC
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset
@@ -1927,6 +1956,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// DeclaratorDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
// VarDecl
Abv->Add(BitCodeAbbrevOp(0)); // SClass
Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec
@@ -1943,7 +1973,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg
Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg
// Type Source Info
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
DeclParmVarAbbrev = Stream.EmitAbbrev(std::move(Abv));
@@ -2003,6 +2032,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// DeclaratorDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
// VarDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec
@@ -2011,6 +2041,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
Abv->Add(BitCodeAbbrevOp(0)); // isInline
Abv->Add(BitCodeAbbrevOp(0)); // isInlineSpecified
@@ -2022,7 +2053,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local)
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum)
// Type Source Info
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv));
@@ -2053,6 +2083,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// DeclaratorDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart
Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
// FunctionDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass
@@ -2065,12 +2096,14 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd
@@ -2162,6 +2195,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// CastExpr
Abv->Add(BitCodeAbbrevOp(0)); // PathSize
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast
// ImplicitCastExpr
ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv));
@@ -2209,17 +2243,20 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context,
}
void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
+ PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(),
+ "serializing");
+
// Determine the ID for this declaration.
serialization::DeclID ID;
assert(!D->isFromASTFile() && "should not be emitting imported decl");
serialization::DeclID &IDR = DeclIDs[D];
if (IDR == 0)
IDR = NextDeclID++;
-
+
ID = IDR;
assert(ID >= FirstDeclID && "invalid decl ID");
-
+
RecordData Record;
ASTDeclWriter W(*this, Context, Record);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
index c5f4495d2f01..09cb0ddc4d49 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements serialization for Statements and Expressions.
+/// Implements serialization for Statements and Expressions.
///
//===----------------------------------------------------------------------===//
@@ -247,7 +247,7 @@ void ASTStmtWriter::VisitGCCAsmStmt(GCCAsmStmt *S) {
Record.AddStmt(S->getAsmString());
// Outputs
- for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
+ for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
Record.AddIdentifierRef(S->getOutputIdentifier(I));
Record.AddStmt(S->getOutputConstraintLiteral(I));
Record.AddStmt(S->getOutputExpr(I));
@@ -444,6 +444,13 @@ void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
Code = serialization::EXPR_INTEGER_LITERAL;
}
+void ASTStmtWriter::VisitFixedPointLiteral(FixedPointLiteral *E) {
+ VisitExpr(E);
+ Record.AddSourceLocation(E->getLocation());
+ Record.AddAPInt(E->getValue());
+ Code = serialization::EXPR_INTEGER_LITERAL;
+}
+
void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
Record.push_back(E->getRawSemantics());
@@ -509,6 +516,7 @@ void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
Record.AddStmt(E->getSubExpr());
Record.push_back(E->getOpcode()); // FIXME: stable encoding
Record.AddSourceLocation(E->getOperatorLoc());
+ Record.push_back(E->canOverflow());
Code = serialization::EXPR_UNARY_OPERATOR;
}
@@ -705,6 +713,7 @@ ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
VisitCastExpr(E);
+ Record.push_back(E->isPartOfExplicitCast());
if (E->path_size() == 0)
AbbrevToUse = Writer.getExprImplicitCastAbbrev();
@@ -991,7 +1000,7 @@ void ASTStmtWriter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
Record.push_back(NumExpansions);
}
}
-
+
Record.AddDeclRef(E->getDictWithObjectsMethod());
Record.AddSourceRange(E->getSourceRange());
Code = serialization::EXPR_OBJC_DICTIONARY_LITERAL;
@@ -1055,7 +1064,7 @@ void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
Record.push_back(2);
Record.AddDeclRef(E->getClassReceiver());
}
-
+
Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR;
}
@@ -1066,7 +1075,7 @@ void ASTStmtWriter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
Record.AddStmt(E->getKeyExpr());
Record.AddDeclRef(E->getAtIndexMethodDecl());
Record.AddDeclRef(E->setAtIndexMethodDecl());
-
+
Code = serialization::EXPR_OBJC_SUBSCRIPT_REF_EXPR;
}
@@ -1099,9 +1108,9 @@ void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
Record.AddDeclRef(E->getMethodDecl());
} else {
Record.push_back(0);
- Record.AddSelectorRef(E->getSelector());
+ Record.AddSelectorRef(E->getSelector());
}
-
+
Record.AddSourceLocation(E->getLeftLoc());
Record.AddSourceLocation(E->getRightLoc());
@@ -1287,14 +1296,14 @@ void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) {
Record.push_back(E->ExplicitParams);
Record.push_back(E->ExplicitResultType);
Record.AddSourceLocation(E->ClosingBrace);
-
+
// Add capture initializers.
for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(),
CEnd = E->capture_init_end();
C != CEnd; ++C) {
Record.AddStmt(*C);
}
-
+
Code = serialization::EXPR_LAMBDA;
}
@@ -1441,7 +1450,7 @@ void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
Record.AddDeclRef(E->getOperatorDelete());
Record.AddStmt(E->getArgument());
Record.AddSourceLocation(E->getSourceRange().getBegin());
-
+
Code = serialization::EXPR_CXX_DELETE;
}
@@ -1698,6 +1707,7 @@ void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
Record.AddStmt(E->getSourceExpr());
Record.AddSourceLocation(E->getLocation());
+ Record.push_back(E->isUnique());
Code = serialization::EXPR_OPAQUE_VALUE;
}
@@ -1888,7 +1898,12 @@ void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
}
void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ Record.push_back(C->getLoopNumIterations().size());
Record.AddStmt(C->getNumForLoops());
+ for (Expr *NumIter : C->getLoopNumIterations())
+ Record.AddStmt(NumIter);
+ for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I)
+ Record.AddStmt(C->getLoopCunter(I));
Record.AddSourceLocation(C->getLParenLoc());
}
@@ -2092,13 +2107,15 @@ void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
Record.push_back(C->varlist_size());
+ Record.push_back(C->getNumLoops());
Record.AddSourceLocation(C->getLParenLoc());
Record.push_back(C->getDependencyKind());
Record.AddSourceLocation(C->getDependencyLoc());
Record.AddSourceLocation(C->getColonLoc());
for (auto *VE : C->varlists())
Record.AddStmt(VE);
- Record.AddStmt(C->getCounterValue());
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
+ Record.AddStmt(C->getLoopData(I));
}
void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
@@ -2675,13 +2692,13 @@ void ASTWriter::ClearSwitchCaseIDs() {
SwitchCaseIDs.clear();
}
-/// \brief Write the given substatement or subexpression to the
+/// Write the given substatement or subexpression to the
/// bitstream.
void ASTWriter::WriteSubStmt(Stmt *S) {
RecordData Record;
ASTStmtWriter Writer(*this, Record);
++NumStatements;
-
+
if (!S) {
Stream.EmitRecord(serialization::STMT_NULL_PTR, Record);
return;
@@ -2714,12 +2731,12 @@ void ASTWriter::WriteSubStmt(Stmt *S) {
#endif
Writer.Visit(S);
-
+
uint64_t Offset = Writer.Emit();
SubStmtEntries[S] = Offset;
}
-/// \brief Flush all of the statements that have been added to the
+/// Flush all of the statements that have been added to the
/// queue via AddStmt().
void ASTRecordWriter::FlushStmts() {
// We expect to be the only consumer of the two temporary statement maps,
@@ -2729,7 +2746,7 @@ void ASTRecordWriter::FlushStmts() {
for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
Writer->WriteSubStmt(StmtsToEmit[I]);
-
+
assert(N == StmtsToEmit.size() && "record modified while being written!");
// Note that we are at the end of a full expression. Any
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
index 20c114297b99..3733638d2977 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -21,9 +21,9 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/DJB.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -38,26 +38,26 @@ using namespace serialization;
//----------------------------------------------------------------------------//
namespace {
enum {
- /// \brief The block containing the index.
+ /// The block containing the index.
GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID
};
- /// \brief Describes the record types in the index.
+ /// Describes the record types in the index.
enum IndexRecordTypes {
- /// \brief Contains version information and potentially other metadata,
+ /// Contains version information and potentially other metadata,
/// used to determine if we can read this global index file.
INDEX_METADATA,
- /// \brief Describes a module, including its file name and dependencies.
+ /// Describes a module, including its file name and dependencies.
MODULE,
- /// \brief The index for identifiers.
+ /// The index for identifiers.
IDENTIFIER_INDEX
};
}
-/// \brief The name of the global index file.
+/// The name of the global index file.
static const char * const IndexFileName = "modules.idx";
-/// \brief The global index file version.
+/// The global index file version.
static const unsigned CurrentVersion = 1;
//----------------------------------------------------------------------------//
@@ -66,7 +66,7 @@ static const unsigned CurrentVersion = 1;
namespace {
-/// \brief Trait used to read the identifier index from the on-disk hash
+/// Trait used to read the identifier index from the on-disk hash
/// table.
class IdentifierIndexReaderTrait {
public:
@@ -81,7 +81,7 @@ public:
}
static hash_value_type ComputeHash(const internal_key_type& a) {
- return llvm::HashString(a);
+ return llvm::djbHash(a);
}
static std::pair<unsigned, unsigned>
@@ -245,7 +245,7 @@ GlobalModuleIndex::readIndex(StringRef Path) {
return std::make_pair(nullptr, EC_NotFound);
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
- /// \brief The main bitstream cursor for the main block.
+ /// The main bitstream cursor for the main block.
llvm::BitstreamCursor Cursor(*Buffer);
// Sniff for the signature.
@@ -289,7 +289,7 @@ void GlobalModuleIndex::getModuleDependencies(
bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) {
Hits.clear();
-
+
// If there's no identifier index, there is nothing we can do.
if (!IdentifierIndex)
return false;
@@ -368,12 +368,12 @@ LLVM_DUMP_METHOD void GlobalModuleIndex::dump() {
//----------------------------------------------------------------------------//
namespace {
- /// \brief Provides information about a specific module file.
+ /// Provides information about a specific module file.
struct ModuleFileInfo {
- /// \brief The numberic ID for this module file.
+ /// The numberic ID for this module file.
unsigned ID;
- /// \brief The set of modules on which this module depends. Each entry is
+ /// The set of modules on which this module depends. Each entry is
/// a module ID.
SmallVector<unsigned, 4> Dependencies;
ASTFileSignature Signature;
@@ -387,7 +387,7 @@ namespace {
: StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {}
};
- /// \brief Builder that generates the global module index file.
+ /// Builder that generates the global module index file.
class GlobalModuleIndexBuilder {
FileManager &FileMgr;
const PCHContainerReader &PCHContainerRdr;
@@ -398,26 +398,26 @@ namespace {
/// Information about each of the known module files.
ModuleFilesMap ModuleFiles;
- /// \brief Mapping from the imported module file to the imported
+ /// Mapping from the imported module file to the imported
/// information.
typedef std::multimap<const FileEntry *, ImportedModuleFileInfo>
ImportedModuleFilesMap;
- /// \brief Information about each importing of a module file.
+ /// Information about each importing of a module file.
ImportedModuleFilesMap ImportedModuleFiles;
- /// \brief Mapping from identifiers to the list of module file IDs that
+ /// Mapping from identifiers to the list of module file IDs that
/// consider this identifier to be interesting.
typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap;
- /// \brief A mapping from all interesting identifiers to the set of module
+ /// A mapping from all interesting identifiers to the set of module
/// files in which those identifiers are considered interesting.
InterestingIdentifierMap InterestingIdentifiers;
-
- /// \brief Write the block-info block for the global module index file.
+
+ /// Write the block-info block for the global module index file.
void emitBlockInfoBlock(llvm::BitstreamWriter &Stream);
- /// \brief Retrieve the module file information for the given file.
+ /// Retrieve the module file information for the given file.
ModuleFileInfo &getModuleFileInfo(const FileEntry *File) {
llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known
= ModuleFiles.find(File);
@@ -435,12 +435,12 @@ namespace {
FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr)
: FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
- /// \brief Load the contents of the given module file into the builder.
+ /// Load the contents of the given module file into the builder.
///
/// \returns true if an error occurred, false otherwise.
bool loadModuleFile(const FileEntry *File);
- /// \brief Write the index to the given bitstream.
+ /// Write the index to the given bitstream.
/// \returns true if an error occurred, false otherwise.
bool writeIndex(llvm::BitstreamWriter &Stream);
};
@@ -493,7 +493,7 @@ namespace {
: public serialization::reader::ASTIdentifierLookupTraitBase {
public:
- /// \brief The identifier and whether it is "interesting".
+ /// The identifier and whether it is "interesting".
typedef std::pair<StringRef, bool> data_type;
data_type ReadData(const internal_key_type& k,
@@ -608,7 +608,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Skip the import location
++Idx;
- // Load stored size/modification time.
+ // Load stored size/modification time.
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];
@@ -685,7 +685,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
namespace {
-/// \brief Trait used to generate the identifier index as an on-disk hash
+/// Trait used to generate the identifier index as an on-disk hash
/// table.
class IdentifierIndexWriterTrait {
public:
@@ -697,20 +697,20 @@ public:
typedef unsigned offset_type;
static hash_value_type ComputeHash(key_type_ref Key) {
- return llvm::HashString(Key);
+ return llvm::djbHash(Key);
}
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);
+ endian::Writer LE(Out, little);
unsigned KeyLen = Key.size();
unsigned DataLen = Data.size() * 4;
LE.write<uint16_t>(KeyLen);
LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
-
+
void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
Out.write(Key.data(), KeyLen);
}
@@ -719,7 +719,7 @@ public:
unsigned DataLen) {
using namespace llvm::support;
for (unsigned I = 0, N = Data.size(); I != N; ++I)
- endian::Writer<little>(Out).write<uint32_t>(Data[I]);
+ endian::write<uint32_t>(Out, Data[I], little);
}
};
@@ -740,7 +740,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
}
using namespace llvm;
-
+
// Emit the file header.
Stream.Emit((unsigned)'B', 8);
Stream.Emit((unsigned)'C', 8);
@@ -789,7 +789,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
I != IEnd; ++I) {
Generator.insert(I->first(), I->second, Trait);
}
-
+
// Create the on-disk hash table in a buffer.
SmallString<4096> IdentifierTable;
uint32_t BucketOffset;
@@ -797,7 +797,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
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);
+ endian::write<uint32_t>(Out, 0, little);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -902,7 +902,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
// Rename the newly-written index file to the proper name.
if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
- // Rename failed; just remove the
+ // Rename failed; just remove the
llvm::sys::fs::remove(IndexTmpPath);
return EC_IOError;
}
@@ -913,10 +913,10 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
namespace {
class GlobalIndexIdentifierIterator : public IdentifierIterator {
- /// \brief The current position within the identifier lookup table.
+ /// The current position within the identifier lookup table.
IdentifierIndexTable::key_iterator Current;
- /// \brief The end position within the identifier lookup table.
+ /// The end position within the identifier lookup table.
IdentifierIndexTable::key_iterator End;
public:
diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
index 5a44d26fe399..580e46e4f240 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
@@ -1,4 +1,4 @@
-//===--- Module.cpp - Module description ------------------------*- C++ -*-===//
+//===- Module.cpp - Module description ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,8 +11,12 @@
// been loaded from an AST file.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Serialization/Module.h"
#include "ASTReaderInternals.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -26,15 +30,16 @@ ModuleFile::~ModuleFile() {
}
template<typename Key, typename Offset, unsigned InitialCapacity>
-static void
+static void
dumpLocalRemap(StringRef Name,
const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) {
if (Map.begin() == Map.end())
return;
-
- typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType;
+
+ using MapType = ContinuousRangeMap<Key, Offset, InitialCapacity>;
+
llvm::errs() << " " << Name << ":\n";
- for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
+ for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
I != IEnd; ++I) {
llvm::errs() << " " << I->first << " -> " << I->second << "\n";
}
@@ -51,12 +56,12 @@ LLVM_DUMP_METHOD void ModuleFile::dump() {
}
llvm::errs() << "\n";
}
-
+
// Remapping tables.
- llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset
+ llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset
<< '\n';
dumpLocalRemap("Source location offset local -> global map", SLocRemap);
-
+
llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n'
<< " Number of identifiers: " << LocalNumIdentifiers << '\n';
dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap);
@@ -72,18 +77,18 @@ LLVM_DUMP_METHOD void ModuleFile::dump() {
llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n'
<< " Number of selectors: " << LocalNumSelectors << '\n';
dumpLocalRemap("Selector ID local -> global map", SelectorRemap);
-
+
llvm::errs() << " Base preprocessed entity ID: " << BasePreprocessedEntityID
- << '\n'
- << " Number of preprocessed entities: "
+ << '\n'
+ << " Number of preprocessed entities: "
<< NumPreprocessedEntities << '\n';
- dumpLocalRemap("Preprocessed entity ID local -> global map",
+ dumpLocalRemap("Preprocessed entity ID local -> global map",
PreprocessedEntityRemap);
-
+
llvm::errs() << " Base type index: " << BaseTypeIndex << '\n'
<< " Number of types: " << LocalNumTypes << '\n';
dumpLocalRemap("Type index local -> global map", TypeRemap);
-
+
llvm::errs() << " Base decl ID: " << BaseDeclID << '\n'
<< " Number of decls: " << LocalNumDecls << '\n';
dumpLocalRemap("Decl ID local -> global map", DeclRemap);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
index b512fa452cc1..57ebaca10c99 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
@@ -340,7 +340,7 @@ void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
unsigned N = size();
VisitOrder.clear();
VisitOrder.reserve(N);
-
+
// Record the number of incoming edges for each module. When we
// encounter a module with no incoming edges, push it into the queue
// to seed the queue.
@@ -477,21 +477,21 @@ namespace llvm {
static ChildIteratorType child_end(NodeRef Node) {
return Node->Imports.end();
}
-
+
static nodes_iterator nodes_begin(const ModuleManager &Manager) {
return nodes_iterator(Manager.begin());
}
-
+
static nodes_iterator nodes_end(const ModuleManager &Manager) {
return nodes_iterator(Manager.end());
}
};
-
+
template<>
struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
explicit DOTGraphTraits(bool IsSimple = false)
: DefaultDOTGraphTraits(IsSimple) {}
-
+
static bool renderGraphFromBottomUp() { return true; }
std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
diff --git a/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h b/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
index 44d1616a0110..ded7cd146449 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
@@ -37,7 +37,7 @@
namespace clang {
namespace serialization {
-/// \brief A collection of on-disk hash tables, merged when relevant for performance.
+/// 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.
@@ -57,7 +57,7 @@ private:
template<typename ReaderInfo, typename WriterInfo>
friend class MultiOnDiskHashTableGenerator;
- /// \brief A hash table stored on disk.
+ /// A hash table stored on disk.
struct OnDiskTable {
using HashTable = llvm::OnDiskIterableChainedHashTable<Info>;
@@ -79,14 +79,14 @@ private:
using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>;
using TableVector = llvm::TinyPtrVector<void *>;
- /// \brief The current set of on-disk and merged tables.
+ /// The current set of on-disk and merged tables.
/// We manually store the opaque value of the Table because TinyPtrVector
/// can't cope with holding a PointerUnion directly.
/// There can be at most one MergedTable in this vector, and if present,
/// it is the first table.
TableVector Tables;
- /// \brief Files corresponding to overridden tables that we've not yet
+ /// Files corresponding to overridden tables that we've not yet
/// discarded.
llvm::TinyPtrVector<file_type> PendingOverrides;
@@ -102,7 +102,7 @@ private:
llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>;
using table_range = llvm::iterator_range<table_iterator>;
- /// \brief The current set of on-disk tables.
+ /// The current set of on-disk tables.
table_range tables() {
auto Begin = Tables.begin(), End = Tables.end();
if (getMergedTable())
@@ -117,7 +117,7 @@ private:
.template dyn_cast<MergedTable*>();
}
- /// \brief Delete all our current on-disk tables.
+ /// Delete all our current on-disk tables.
void clear() {
for (auto *T : tables())
delete T;
@@ -194,7 +194,7 @@ public:
~MultiOnDiskHashTable() { clear(); }
- /// \brief Add the table \p Data loaded from file \p File.
+ /// 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;
@@ -225,7 +225,7 @@ public:
Tables.push_back(NewTable.getOpaqueValue());
}
- /// \brief Find and read the lookup results for \p EKey.
+ /// Find and read the lookup results for \p EKey.
data_type find(const external_key_type &EKey) {
data_type Result;
@@ -257,7 +257,7 @@ public:
return Result;
}
- /// \brief Read all the lookup results into a single value. This only makes
+ /// Read all the lookup results into a single value. This only makes
/// sense if merging values across keys is meaningful.
data_type findAll() {
data_type Result;
@@ -288,7 +288,7 @@ public:
}
};
-/// \brief Writer for the on-disk hash table.
+/// Writer for the on-disk hash table.
template<typename ReaderInfo, typename WriterInfo>
class MultiOnDiskHashTableGenerator {
using BaseTable = MultiOnDiskHashTable<ReaderInfo>;
@@ -312,7 +312,7 @@ public:
// Write our header information.
{
- endian::Writer<little> Writer(OutStream);
+ endian::Writer Writer(OutStream, little);
// Reserve four bytes for the bucket offset.
Writer.write<uint32_t>(0);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
index 048418ef62db..62b7fab0739a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
@@ -18,7 +18,7 @@
namespace clang { namespace ento {
-/// \brief Returns true if leak diagnostics should directly reference
+/// Returns true if leak diagnostics should directly reference
/// the allocatin site (where possible).
///
/// The default is false.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationState.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationState.h
new file mode 100644
index 000000000000..a6908bd7a651
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AllocationState.h
@@ -0,0 +1,34 @@
+//===--- AllocationState.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_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H
+
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+
+namespace clang {
+namespace ento {
+
+namespace allocation_state {
+
+ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym,
+ const Expr *Origin);
+
+/// This function provides an additional visitor that augments the bug report
+/// with information relevant to memory errors caused by the misuse of
+/// AF_InnerBuffer symbols.
+std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym);
+
+} // end namespace allocation_state
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
index 90d5c0e36a47..e4cdc500de6a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -15,8 +15,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/AST/ExprCXX.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"
using namespace clang;
@@ -29,8 +31,17 @@ class AnalysisOrderChecker
check::PostStmt<CastExpr>,
check::PreStmt<ArraySubscriptExpr>,
check::PostStmt<ArraySubscriptExpr>,
+ check::PreStmt<CXXNewExpr>,
+ check::PostStmt<CXXNewExpr>,
+ check::PreStmt<OffsetOfExpr>,
+ check::PostStmt<OffsetOfExpr>,
+ check::PreCall,
+ check::PostCall,
+ check::NewAllocator,
check::Bind,
- check::RegionChanges> {
+ check::RegionChanges,
+ check::LiveSymbols> {
+
bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const {
return Opts.getBooleanOption("*", false, this) ||
Opts.getBooleanOption(CallbackName, false, this);
@@ -72,11 +83,60 @@ public:
llvm::errs() << "PostStmt<ArraySubscriptExpr>\n";
}
+ void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PreStmtCXXNewExpr"))
+ llvm::errs() << "PreStmt<CXXNewExpr>\n";
+ }
+
+ void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PostStmtCXXNewExpr"))
+ llvm::errs() << "PostStmt<CXXNewExpr>\n";
+ }
+
+ void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
+ llvm::errs() << "PreStmt<OffsetOfExpr>\n";
+ }
+
+ void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
+ llvm::errs() << "PostStmt<OffsetOfExpr>\n";
+ }
+
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PreCall")) {
+ llvm::errs() << "PreCall";
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
+ llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
+ llvm::errs() << '\n';
+ }
+ }
+
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PostCall")) {
+ llvm::errs() << "PostCall";
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
+ llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
+ llvm::errs() << '\n';
+ }
+ }
+
+ void checkNewAllocator(const CXXNewExpr *CNE, SVal Target,
+ CheckerContext &C) const {
+ if (isCallbackEnabled(C, "NewAllocator"))
+ llvm::errs() << "NewAllocator\n";
+ }
+
void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const {
if (isCallbackEnabled(C, "Bind"))
llvm::errs() << "Bind\n";
}
+ void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const {
+ if (isCallbackEnabled(State, "LiveSymbols"))
+ llvm::errs() << "LiveSymbols\n";
+ }
+
ProgramStateRef
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
index 64c30e7a82c1..aadc6bac8d00 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
@@ -122,6 +122,8 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
E = CE.blocks_exhausted_end(); I != E; ++I) {
const BlockEdge &BE = I->first;
const CFGBlock *Exit = BE.getDst();
+ if (Exit->empty())
+ continue;
const CFGElement &CE = Exit->front();
if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {
SmallString<128> bufI;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index b944f90539d4..933380d494a4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -33,8 +33,8 @@ class ArrayBoundCheckerV2 :
enum OOB_Kind { OOB_Precedes, OOB_Excedes, OOB_Tainted };
- void reportOOB(CheckerContext &C, ProgramStateRef errorState,
- OOB_Kind kind) const;
+ void reportOOB(CheckerContext &C, ProgramStateRef errorState, OOB_Kind kind,
+ std::unique_ptr<BugReporterVisitor> Visitor = nullptr) const;
public:
void checkLocation(SVal l, bool isLoad, const Stmt*S,
@@ -125,7 +125,6 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
// have some flexibility in defining the base region, we can achieve
// various levels of conservatism in our buffer overflow checking.
ProgramStateRef state = checkerContext.getState();
- ProgramStateRef originalState = state;
SValBuilder &svalBuilder = checkerContext.getSValBuilder();
const RegionRawOffsetV2 &rawOffset =
@@ -205,8 +204,10 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
// If we are under constrained and the index variables are tainted, report.
if (state_exceedsUpperBound && state_withinUpperBound) {
- if (state->isTainted(rawOffset.getByteOffset())) {
- reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted);
+ SVal ByteOffset = rawOffset.getByteOffset();
+ if (state->isTainted(ByteOffset)) {
+ reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted,
+ llvm::make_unique<TaintBugVisitor>(ByteOffset));
return;
}
} else if (state_exceedsUpperBound) {
@@ -222,13 +223,12 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
}
while (false);
- if (state != originalState)
- checkerContext.addTransition(state);
+ checkerContext.addTransition(state);
}
-void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
- ProgramStateRef errorState,
- OOB_Kind kind) const {
+void ArrayBoundCheckerV2::reportOOB(
+ CheckerContext &checkerContext, ProgramStateRef errorState, OOB_Kind kind,
+ std::unique_ptr<BugReporterVisitor> Visitor) const {
ExplodedNode *errorNode = checkerContext.generateErrorNode(errorState);
if (!errorNode)
@@ -255,8 +255,9 @@ void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
break;
}
- checkerContext.emitReport(
- llvm::make_unique<BugReport>(*BT, os.str(), errorNode));
+ auto BR = llvm::make_unique<BugReport>(*BT, os.str(), errorNode);
+ BR->addVisitor(std::move(Visitor));
+ checkerContext.emitReport(std::move(BR));
}
#ifndef NDEBUG
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 371187747f03..7d6358acbbac 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -436,8 +436,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE,
return;
// Get the value of the "theType" argument.
- const LocationContext *LCtx = C.getLocationContext();
- SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
+ SVal TheTypeVal = C.getSVal(CE->getArg(1));
// FIXME: We really should allow ranges of valid theType values, and
// bifurcate the state appropriately.
@@ -457,7 +456,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE,
// Look at the value of the integer being passed by reference. Essentially
// we want to catch cases where the value passed in is not equal to the
// size of the type being created.
- SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
+ SVal TheValueExpr = C.getSVal(CE->getArg(2));
// FIXME: Eventually we should handle arbitrary locations. We can do this
// by having an enhanced memory model that does low-level typing.
@@ -571,7 +570,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
// Get the argument's value.
const Expr *Arg = CE->getArg(0);
- SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
+ SVal ArgVal = C.getSVal(Arg);
Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
if (!DefArgVal)
return;
@@ -977,8 +976,7 @@ assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
if (!State)
return nullptr;
- SymbolRef CollectionS =
- State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
+ SymbolRef CollectionS = C.getSVal(FCS->getCollection()).getAsSymbol();
return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
}
@@ -1166,7 +1164,7 @@ void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
namespace {
/// \class ObjCNonNilReturnValueChecker
-/// \brief The checker restricts the return values of APIs known to
+/// The checker restricts the return values of APIs known to
/// never (or almost never) return 'nil'.
class ObjCNonNilReturnValueChecker
: public Checker<check::PostObjCMessage,
@@ -1206,7 +1204,7 @@ ProgramStateRef
ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
ProgramStateRef State,
CheckerContext &C) const {
- SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
+ SVal Val = C.getSVal(NonNullExpr);
if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
return State->assume(*DV, true);
return State;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 097d4198800d..0e781d08e24c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -43,7 +43,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
case Builtin::BI__builtin_assume: {
assert (CE->arg_begin() != CE->arg_end());
- SVal ArgSVal = state->getSVal(CE->getArg(0), LCtx);
+ SVal ArgSVal = C.getSVal(CE->getArg(0));
if (ArgSVal.isUndef())
return true; // Return true to model purity.
@@ -68,7 +68,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
// __builtin_addressof is going from a reference to a pointer, but those
// are represented the same way in the analyzer.
assert (CE->arg_begin() != CE->arg_end());
- SVal X = state->getSVal(*(CE->arg_begin()), LCtx);
+ SVal X = C.getSVal(*(CE->arg_begin()));
C.addTransition(state->BindExpr(CE, LCtx, X));
return true;
}
@@ -83,8 +83,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
// Set the extent of the region in bytes. This enables us to use the
// SVal of the argument directly. If we save the extent in bits, we
// cannot represent values like symbol*8.
- DefinedOrUnknownSVal Size =
- state->getSVal(*(CE->arg_begin()), LCtx).castAs<DefinedOrUnknownSVal>();
+ auto Size = C.getSVal(*(CE->arg_begin())).castAs<DefinedOrUnknownSVal>();
SValBuilder& svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
@@ -97,7 +96,8 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
return true;
}
- case Builtin::BI__builtin_object_size: {
+ case Builtin::BI__builtin_object_size:
+ case Builtin::BI__builtin_constant_p: {
// This must be resolvable at compile time, so we defer to the constant
// evaluator for a value.
SVal V = UnknownVal();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 28ad7e9e5071..12a576e5d80d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -97,14 +97,17 @@ public:
void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStrlcpy(CheckerContext &C, const CallExpr *CE) const;
void evalStrcpyCommon(CheckerContext &C,
const CallExpr *CE,
bool returnEnd,
bool isBounded,
- bool isAppending) const;
+ bool isAppending,
+ bool returnPtr = true) const;
void evalStrcat(CheckerContext &C, const CallExpr *CE) const;
void evalStrncat(CheckerContext &C, const CallExpr *CE) const;
+ void evalStrlcat(CheckerContext &C, const CallExpr *CE) const;
void evalStrcmp(CheckerContext &C, const CallExpr *CE) const;
void evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
@@ -155,6 +158,10 @@ public:
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR);
+ static bool memsetAux(const Expr *DstBuffer, const Expr *CharE,
+ const Expr *Size, CheckerContext &C,
+ ProgramStateRef &State);
+
// Re-usable checks
ProgramStateRef checkNonNull(CheckerContext &C,
ProgramStateRef state,
@@ -194,6 +201,14 @@ public:
const Stmt *First,
const Stmt *Second) const;
+ void emitNullArgBug(CheckerContext &C, ProgramStateRef State, const Stmt *S,
+ StringRef WarningMsg) const;
+ void emitOutOfBoundsBug(CheckerContext &C, ProgramStateRef State,
+ const Stmt *S, StringRef WarningMsg) const;
+ void emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
+ const Stmt *S, StringRef WarningMsg) const;
+ void emitAdditionOverflowBug(CheckerContext &C, ProgramStateRef State) const;
+
ProgramStateRef checkAdditionOverflow(CheckerContext &C,
ProgramStateRef state,
NonLoc left,
@@ -239,30 +254,14 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
if (stateNull && !stateNonNull) {
- if (!Filter.CheckCStringNullArg)
- return nullptr;
-
- ExplodedNode *N = C.generateErrorNode(stateNull);
- if (!N)
- return nullptr;
-
- if (!BT_Null)
- BT_Null.reset(new BuiltinBug(
- Filter.CheckNameCStringNullArg, categories::UnixAPI,
- "Null pointer argument in call to byte string function"));
-
- SmallString<80> buf;
- llvm::raw_svector_ostream os(buf);
- assert(CurrentFunctionDescription);
- os << "Null pointer argument in call to " << CurrentFunctionDescription;
-
- // Generate a report for this bug.
- BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get());
- auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
+ if (Filter.CheckCStringNullArg) {
+ SmallString<80> buf;
+ llvm::raw_svector_ostream os(buf);
+ assert(CurrentFunctionDescription);
+ os << "Null pointer argument in call to " << CurrentFunctionDescription;
- report->addRange(S->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, S, *report);
- C.emitReport(std::move(report));
+ emitNullArgBug(C, stateNull, S, os.str());
+ }
return nullptr;
}
@@ -305,21 +304,14 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.generateErrorNode(StOutBound);
- if (!N)
+ // These checks are either enabled by the CString out-of-bounds checker
+ // explicitly or implicitly by the Malloc checker.
+ // In the latter case we only do modeling but do not emit warning.
+ if (!Filter.CheckCStringOutOfBounds)
return nullptr;
-
- if (!BT_Bounds) {
- BT_Bounds.reset(new BuiltinBug(
- Filter.CheckNameCStringOutOfBounds, "Out-of-bound array access",
- "Byte string function accesses out-of-bound array element"));
- }
- BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get());
-
- // Generate a report for this bug.
- std::unique_ptr<BugReport> report;
+ // Emit a bug report.
if (warningMsg) {
- report = llvm::make_unique<BugReport>(*BT, warningMsg, N);
+ emitOutOfBoundsBug(C, StOutBound, S, warningMsg);
} else {
assert(CurrentFunctionDescription);
assert(CurrentFunctionDescription[0] != '\0');
@@ -329,15 +321,8 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
os << toUppercase(CurrentFunctionDescription[0])
<< &CurrentFunctionDescription[1]
<< " accesses out-of-bound array element";
- report = llvm::make_unique<BugReport>(*BT, os.str(), N);
+ emitOutOfBoundsBug(C, StOutBound, S, os.str());
}
-
- // FIXME: It would be nice to eventually make this diagnostic more clear,
- // e.g., by referencing the original declaration or by saying *why* this
- // reference is outside the range.
-
- report->addRange(S->getSourceRange());
- C.emitReport(std::move(report));
return nullptr;
}
@@ -366,7 +351,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,
QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
// Check that the first buffer is non-null.
- SVal BufVal = state->getSVal(FirstBuf, LCtx);
+ SVal BufVal = C.getSVal(FirstBuf);
state = checkNonNull(C, state, FirstBuf, BufVal);
if (!state)
return nullptr;
@@ -378,15 +363,17 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,
// Get the access length and make sure it is known.
// FIXME: This assumes the caller has already checked that the access length
// is positive. And that it's unsigned.
- SVal LengthVal = state->getSVal(Size, LCtx);
+ SVal LengthVal = C.getSVal(Size);
Optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
if (!Length)
return state;
// Compute the offset of the last element to be accessed: size-1.
NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
- NonLoc LastOffset = svalBuilder
- .evalBinOpNN(state, BO_Sub, *Length, One, sizeTy).castAs<NonLoc>();
+ SVal Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy);
+ if (Offset.isUnknown())
+ return nullptr;
+ NonLoc LastOffset = Offset.castAs<NonLoc>();
// Check that the first buffer is sufficiently long.
SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
@@ -555,6 +542,80 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
C.emitReport(std::move(report));
}
+void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State,
+ const Stmt *S, StringRef WarningMsg) const {
+ if (ExplodedNode *N = C.generateErrorNode(State)) {
+ if (!BT_Null)
+ BT_Null.reset(new BuiltinBug(
+ Filter.CheckNameCStringNullArg, categories::UnixAPI,
+ "Null pointer argument in call to byte string function"));
+
+ BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Null.get());
+ auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
+ Report->addRange(S->getSourceRange());
+ bugreporter::trackNullOrUndefValue(N, S, *Report);
+ C.emitReport(std::move(Report));
+ }
+}
+
+void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
+ ProgramStateRef State, const Stmt *S,
+ StringRef WarningMsg) const {
+ if (ExplodedNode *N = C.generateErrorNode(State)) {
+ if (!BT_Bounds)
+ BT_Bounds.reset(new BuiltinBug(
+ Filter.CheckCStringOutOfBounds ? Filter.CheckNameCStringOutOfBounds
+ : Filter.CheckNameCStringNullArg,
+ "Out-of-bound array access",
+ "Byte string function accesses out-of-bound array element"));
+
+ BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Bounds.get());
+
+ // FIXME: It would be nice to eventually make this diagnostic more clear,
+ // e.g., by referencing the original declaration or by saying *why* this
+ // reference is outside the range.
+ auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
+ Report->addRange(S->getSourceRange());
+ C.emitReport(std::move(Report));
+ }
+}
+
+void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
+ const Stmt *S,
+ StringRef WarningMsg) const {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) {
+ if (!BT_NotCString)
+ BT_NotCString.reset(new BuiltinBug(
+ Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
+ "Argument is not a null-terminated string."));
+
+ auto Report = llvm::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
+
+ Report->addRange(S->getSourceRange());
+ C.emitReport(std::move(Report));
+ }
+}
+
+void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
+ ProgramStateRef State) const {
+ if (ExplodedNode *N = C.generateErrorNode(State)) {
+ if (!BT_NotCString)
+ BT_NotCString.reset(
+ new BuiltinBug(Filter.CheckNameCStringOutOfBounds, "API",
+ "Sum of expressions causes overflow."));
+
+ // This isn't a great error message, but this should never occur in real
+ // code anyway -- you'd have to create a buffer longer than a size_t can
+ // represent, which is sort of a contradiction.
+ const char *WarningMsg =
+ "This expression will create a string whose length is too big to "
+ "be represented as a size_t";
+
+ auto Report = llvm::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
+ C.emitReport(std::move(Report));
+ }
+}
+
ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
ProgramStateRef state,
NonLoc left,
@@ -598,26 +659,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
if (stateOverflow && !stateOkay) {
// We have an overflow. Emit a bug report.
- ExplodedNode *N = C.generateErrorNode(stateOverflow);
- if (!N)
- return nullptr;
-
- if (!BT_AdditionOverflow)
- BT_AdditionOverflow.reset(
- new BuiltinBug(Filter.CheckNameCStringOutOfBounds, "API",
- "Sum of expressions causes overflow"));
-
- // This isn't a great error message, but this should never occur in real
- // code anyway -- you'd have to create a buffer longer than a size_t can
- // represent, which is sort of a contradiction.
- const char *warning =
- "This expression will create a string whose length is too big to "
- "be represented as a size_t";
-
- // Generate a report for this bug.
- C.emitReport(
- llvm::make_unique<BugReport>(*BT_AdditionOverflow, warning, N));
-
+ emitAdditionOverflowBug(C, stateOverflow);
return nullptr;
}
@@ -717,15 +759,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
// C string. In the context of locations, the only time we can issue such
// a warning is for labels.
if (Optional<loc::GotoLabel> Label = Buf.getAs<loc::GotoLabel>()) {
- if (!Filter.CheckCStringNotNullTerm)
- return UndefinedVal();
-
- if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
- if (!BT_NotCString)
- BT_NotCString.reset(new BuiltinBug(
- Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
- "Argument is not a null-terminated string."));
-
+ if (Filter.CheckCStringNotNullTerm) {
SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
assert(CurrentFunctionDescription);
@@ -733,14 +767,9 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
<< " is the address of the label '" << Label->getLabel()->getName()
<< "', which is not a null-terminated string";
- // Generate a report for this bug.
- auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
-
- report->addRange(Ex->getSourceRange());
- C.emitReport(std::move(report));
+ emitNotCStringBug(C, state, Ex, os.str());
}
return UndefinedVal();
-
}
// If it's not a region and not a label, give up.
@@ -777,15 +806,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
// Other regions (mostly non-data) can't have a reliable C string length.
// In this case, an error is emitted and UndefinedVal is returned.
// The caller should always be prepared to handle this case.
- if (!Filter.CheckCStringNotNullTerm)
- return UndefinedVal();
-
- if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
- if (!BT_NotCString)
- BT_NotCString.reset(new BuiltinBug(
- Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
- "Argument is not a null-terminated string."));
-
+ if (Filter.CheckCStringNotNullTerm) {
SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
@@ -797,13 +818,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
else
os << "not a null-terminated string";
- // Generate a report for this bug.
- auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
-
- report->addRange(Ex->getSourceRange());
- C.emitReport(std::move(report));
+ emitNotCStringBug(C, state, Ex, os.str());
}
-
return UndefinedVal();
}
}
@@ -852,9 +868,10 @@ bool CStringChecker::IsFirstBufInBound(CheckerContext &C,
// Compute the offset of the last element to be accessed: size-1.
NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
- NonLoc LastOffset =
- svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy)
- .castAs<NonLoc>();
+ SVal Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy);
+ if (Offset.isUnknown())
+ return true; // cf top comment
+ NonLoc LastOffset = Offset.castAs<NonLoc>();
// Check that the first buffer is sufficiently long.
SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
@@ -987,6 +1004,95 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
}
}
+bool CStringChecker::memsetAux(const Expr *DstBuffer, const Expr *CharE,
+ const Expr *Size, CheckerContext &C,
+ ProgramStateRef &State) {
+ SVal MemVal = C.getSVal(DstBuffer);
+ SVal CharVal = C.getSVal(CharE);
+ SVal SizeVal = C.getSVal(Size);
+ const MemRegion *MR = MemVal.getAsRegion();
+ if (!MR)
+ return false;
+
+ // We're about to model memset by producing a "default binding" in the Store.
+ // Our current implementation - RegionStore - doesn't support default bindings
+ // that don't cover the whole base region. So we should first get the offset
+ // and the base region to figure out whether the offset of buffer is 0.
+ RegionOffset Offset = MR->getAsOffset();
+ const MemRegion *BR = Offset.getRegion();
+
+ Optional<NonLoc> SizeNL = SizeVal.getAs<NonLoc>();
+ if (!SizeNL)
+ return false;
+
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ ASTContext &Ctx = C.getASTContext();
+
+ // void *memset(void *dest, int ch, size_t count);
+ // For now we can only handle the case of offset is 0 and concrete char value.
+ if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
+ Offset.getOffset() == 0) {
+ // Get the base region's extent.
+ auto *SubReg = cast<SubRegion>(BR);
+ DefinedOrUnknownSVal Extent = SubReg->getExtent(svalBuilder);
+
+ ProgramStateRef StateWholeReg, StateNotWholeReg;
+ std::tie(StateWholeReg, StateNotWholeReg) =
+ State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL));
+
+ // With the semantic of 'memset()', we should convert the CharVal to
+ // unsigned char.
+ CharVal = svalBuilder.evalCast(CharVal, Ctx.UnsignedCharTy, Ctx.IntTy);
+
+ ProgramStateRef StateNullChar, StateNonNullChar;
+ std::tie(StateNullChar, StateNonNullChar) =
+ assumeZero(C, State, CharVal, Ctx.UnsignedCharTy);
+
+ if (StateWholeReg && !StateNotWholeReg && StateNullChar &&
+ !StateNonNullChar) {
+ // If the 'memset()' acts on the whole region of destination buffer and
+ // the value of the second argument of 'memset()' is zero, bind the second
+ // argument's value to the destination buffer with 'default binding'.
+ // FIXME: Since there is no perfect way to bind the non-zero character, we
+ // can only deal with zero value here. In the future, we need to deal with
+ // the binding of non-zero value in the case of whole region.
+ State = State->bindDefaultZero(svalBuilder.makeLoc(BR),
+ C.getLocationContext());
+ } else {
+ // If the destination buffer's extent is not equal to the value of
+ // third argument, just invalidate buffer.
+ State = InvalidateBuffer(C, State, DstBuffer, MemVal,
+ /*IsSourceBuffer*/ false, Size);
+ }
+
+ if (StateNullChar && !StateNonNullChar) {
+ // If the value of the second argument of 'memset()' is zero, set the
+ // string length of destination buffer to 0 directly.
+ State = setCStringLength(State, MR,
+ svalBuilder.makeZeroVal(Ctx.getSizeType()));
+ } else if (!StateNullChar && StateNonNullChar) {
+ SVal NewStrLen = svalBuilder.getMetadataSymbolVal(
+ CStringChecker::getTag(), MR, DstBuffer, Ctx.getSizeType(),
+ C.getLocationContext(), C.blockCount());
+
+ // If the value of second argument is not zero, then the string length
+ // is at least the size argument.
+ SVal NewStrLenGESize = svalBuilder.evalBinOp(
+ State, BO_GE, NewStrLen, SizeVal, svalBuilder.getConditionType());
+
+ State = setCStringLength(
+ State->assume(NewStrLenGESize.castAs<DefinedOrUnknownSVal>(), true),
+ MR, NewStrLen);
+ }
+ } else {
+ // If the offset is not zero and char value is not concrete, we can do
+ // nothing but invalidate the buffer.
+ State = InvalidateBuffer(C, State, DstBuffer, MemVal,
+ /*IsSourceBuffer*/ false, Size);
+ }
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// evaluation of individual function calls.
//===----------------------------------------------------------------------===//
@@ -1384,6 +1490,18 @@ void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const {
/* isAppending = */ false);
}
+void CStringChecker::evalStrlcpy(CheckerContext &C, const CallExpr *CE) const {
+ if (CE->getNumArgs() < 3)
+ return;
+
+ // char *strlcpy(char *dst, const char *src, size_t n);
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ true,
+ /* isBounded = */ true,
+ /* isAppending = */ false,
+ /* returnPtr = */ false);
+}
+
void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const {
if (CE->getNumArgs() < 2)
return;
@@ -1406,9 +1524,21 @@ void CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const {
/* isAppending = */ true);
}
+void CStringChecker::evalStrlcat(CheckerContext &C, const CallExpr *CE) const {
+ if (CE->getNumArgs() < 3)
+ return;
+
+ //char *strlcat(char *s1, const char *s2, size_t n);
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ false,
+ /* isBounded = */ true,
+ /* isAppending = */ true,
+ /* returnPtr = */ false);
+}
+
void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
bool returnEnd, bool isBounded,
- bool isAppending) const {
+ bool isAppending, bool returnPtr) const {
CurrentFunctionDescription = "string copy function";
ProgramStateRef state = C.getState();
const LocationContext *LCtx = C.getLocationContext();
@@ -1446,6 +1576,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
SVal maxLastElementIndex = UnknownVal();
const char *boundWarning = nullptr;
+ state = CheckOverlap(C, state, isBounded ? CE->getArg(2) : CE->getArg(1), Dst, srcExpr);
+
+ if (!state)
+ return;
+
// If the function is strncpy, strncat, etc... it is bounded.
if (isBounded) {
// Get the max number of characters to copy.
@@ -1518,7 +1653,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// If the size is known to be zero, we're done.
if (StateZeroSize && !StateNonZeroSize) {
- StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
+ if (returnPtr) {
+ StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
+ } else {
+ StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, *lenValNL);
+ }
C.addTransition(StateZeroSize);
return;
}
@@ -1649,16 +1788,22 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
finalStrLength = amountCopied;
}
- // The final result of the function will either be a pointer past the last
- // copied element, or a pointer to the start of the destination buffer.
- SVal Result = (returnEnd ? UnknownVal() : DstVal);
+ SVal Result;
+
+ if (returnPtr) {
+ // The final result of the function will either be a pointer past the last
+ // copied element, or a pointer to the start of the destination buffer.
+ Result = (returnEnd ? UnknownVal() : DstVal);
+ } else {
+ Result = finalStrLength;
+ }
assert(state);
// If the destination is a MemRegion, try to check for a buffer overflow and
// record the new string length.
if (Optional<loc::MemRegionVal> dstRegVal =
- DstVal.getAs<loc::MemRegionVal>()) {
+ DstVal.getAs<loc::MemRegionVal>()) {
QualType ptrTy = Dst->getType();
// If we have an exact value on a bounded copy, use that to check for
@@ -1666,9 +1811,9 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
if (boundWarning) {
if (Optional<NonLoc> maxLastNL = maxLastElementIndex.getAs<NonLoc>()) {
SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
- *maxLastNL, ptrTy);
+ *maxLastNL, ptrTy);
state = CheckLocation(C, state, CE->getArg(2), maxLastElement,
- boundWarning);
+ boundWarning);
if (!state)
return;
}
@@ -1677,7 +1822,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// Then, if the final length is known...
if (Optional<NonLoc> knownStrLength = finalStrLength.getAs<NonLoc>()) {
SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
- *knownStrLength, ptrTy);
+ *knownStrLength, ptrTy);
// ...and we haven't checked the bound, we'll check the actual copy.
if (!boundWarning) {
@@ -1689,7 +1834,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
}
// If this is a stpcpy-style copy, the last element is the return value.
- if (returnEnd)
+ if (returnPtr && returnEnd)
Result = lastElement;
}
@@ -1701,12 +1846,12 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// This would probably remove any existing bindings past the end of the
// string, but that's still an improvement over blank invalidation.
state = InvalidateBuffer(C, state, Dst, *dstRegVal,
- /*IsSourceBuffer*/false, nullptr);
+ /*IsSourceBuffer*/false, nullptr);
// Invalidate the source (const-invalidation without const-pointer-escaping
// the address of the top-level region).
state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true,
- nullptr);
+ nullptr);
// Set the C string length of the destination, if we know it.
if (isBounded && !isAppending) {
@@ -1722,12 +1867,13 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
assert(state);
- // If this is a stpcpy-style copy, but we were unable to check for a buffer
- // overflow, we still need a result. Conjure a return value.
- if (returnEnd && Result.isUnknown()) {
- Result = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
+ if (returnPtr) {
+ // If this is a stpcpy-style copy, but we were unable to check for a buffer
+ // overflow, we still need a result. Conjure a return value.
+ if (returnEnd && Result.isUnknown()) {
+ Result = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
+ }
}
-
// Set the return value.
state = state->BindExpr(CE, LCtx, Result);
C.addTransition(state);
@@ -1750,7 +1896,7 @@ void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const {
}
void CStringChecker::evalStrcasecmp(CheckerContext &C,
- const CallExpr *CE) const {
+ const CallExpr *CE) const {
if (CE->getNumArgs() < 2)
return;
@@ -1759,7 +1905,7 @@ void CStringChecker::evalStrcasecmp(CheckerContext &C,
}
void CStringChecker::evalStrncasecmp(CheckerContext &C,
- const CallExpr *CE) const {
+ const CallExpr *CE) const {
if (CE->getNumArgs() < 3)
return;
@@ -1768,7 +1914,7 @@ void CStringChecker::evalStrncasecmp(CheckerContext &C,
}
void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
- bool isBounded, bool ignoreCase) const {
+ bool isBounded, bool ignoreCase) const {
CurrentFunctionDescription = "string comparison function";
ProgramStateRef state = C.getState();
const LocationContext *LCtx = C.getLocationContext();
@@ -1813,7 +1959,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
// and we only need to check one size.
if (StSameBuf) {
StSameBuf = StSameBuf->BindExpr(CE, LCtx,
- svalBuilder.makeZeroVal(CE->getType()));
+ svalBuilder.makeZeroVal(CE->getType()));
C.addTransition(StSameBuf);
// If the two arguments are GUARANTEED to be the same, we're done!
@@ -1832,7 +1978,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
bool canComputeResult = false;
SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx,
- C.blockCount());
+ C.blockCount());
if (s1StrLiteral && s2StrLiteral) {
StringRef s1StrRef = s1StrLiteral->getString();
@@ -1867,7 +2013,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
// Use StringRef's comparison methods to compute the actual result.
int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
- : s1StrRef.compare(s2StrRef);
+ : s1StrRef.compare(s2StrRef);
// The strcmp function returns an integer greater than, equal to, or less
// than zero, [c11, p7.24.4.2].
@@ -1881,7 +2027,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
BinaryOperatorKind op = (compareRes == 1) ? BO_GT : BO_LT;
SVal compareWithZero =
svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
- svalBuilder.getConditionType());
+ svalBuilder.getConditionType());
DefinedSVal compareWithZeroVal = compareWithZero.castAs<DefinedSVal>();
state = state->assume(compareWithZeroVal, true);
}
@@ -1933,17 +2079,17 @@ void CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const {
// Invalidate the search string, representing the change of one delimiter
// character to NUL.
State = InvalidateBuffer(C, State, SearchStrPtr, Result,
- /*IsSourceBuffer*/false, nullptr);
+ /*IsSourceBuffer*/false, nullptr);
// Overwrite the search string pointer. The new value is either an address
// further along in the same string, or NULL if there are no more tokens.
State = State->bindLoc(*SearchStrLoc,
- SVB.conjureSymbolVal(getTag(),
- CE,
- LCtx,
- CharPtrTy,
- C.blockCount()),
- LCtx);
+ SVB.conjureSymbolVal(getTag(),
+ CE,
+ LCtx,
+ CharPtrTy,
+ C.blockCount()),
+ LCtx);
} else {
assert(SearchStrVal.isUnknown());
// Conjure a symbolic value. It's the best we can do.
@@ -1961,12 +2107,12 @@ void CStringChecker::evalStdCopy(CheckerContext &C, const CallExpr *CE) const {
}
void CStringChecker::evalStdCopyBackward(CheckerContext &C,
- const CallExpr *CE) const {
+ const CallExpr *CE) const {
evalStdCopyCommon(C, CE);
}
void CStringChecker::evalStdCopyCommon(CheckerContext &C,
- const CallExpr *CE) const {
+ const CallExpr *CE) const {
if (CE->getNumArgs() < 3)
return;
@@ -1983,7 +2129,7 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
const Expr *Dst = CE->getArg(2);
SVal DstVal = State->getSVal(Dst, LCtx);
State = InvalidateBuffer(C, State, Dst, DstVal, /*IsSource=*/false,
- /*Size=*/nullptr);
+ /*Size=*/nullptr);
SValBuilder &SVB = C.getSValBuilder();
@@ -2000,6 +2146,7 @@ void CStringChecker::evalMemset(CheckerContext &C, const CallExpr *CE) const {
CurrentFunctionDescription = "memory set function";
const Expr *Mem = CE->getArg(0);
+ const Expr *CharE = CE->getArg(1);
const Expr *Size = CE->getArg(2);
ProgramStateRef State = C.getState();
@@ -2032,9 +2179,11 @@ void CStringChecker::evalMemset(CheckerContext &C, const CallExpr *CE) const {
State = CheckBufferAccess(C, State, Size, Mem);
if (!State)
return;
- State = InvalidateBuffer(C, State, Mem, C.getSVal(Mem),
- /*IsSourceBuffer*/false, Size);
- if (!State)
+
+ // According to the values of the arguments, bind the value of the second
+ // argument to the destination buffer and set string length, or just
+ // invalidate the destination buffer.
+ if (!memsetAux(Mem, CharE, Size, C, State))
return;
State = State->BindExpr(CE, LCtx, MemVal);
@@ -2082,10 +2231,14 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
evalFunction = &CStringChecker::evalStrncpy;
else if (C.isCLibraryFunction(FDecl, "stpcpy"))
evalFunction = &CStringChecker::evalStpcpy;
+ else if (C.isCLibraryFunction(FDecl, "strlcpy"))
+ evalFunction = &CStringChecker::evalStrlcpy;
else if (C.isCLibraryFunction(FDecl, "strcat"))
evalFunction = &CStringChecker::evalStrcat;
else if (C.isCLibraryFunction(FDecl, "strncat"))
evalFunction = &CStringChecker::evalStrncat;
+ else if (C.isCLibraryFunction(FDecl, "strlcat"))
+ evalFunction = &CStringChecker::evalStrlcat;
else if (C.isCLibraryFunction(FDecl, "strlen"))
evalFunction = &CStringChecker::evalstrLength;
else if (C.isCLibraryFunction(FDecl, "strnlen"))
@@ -2149,10 +2302,10 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
if (!MR)
continue;
- SVal StrVal = state->getSVal(Init, C.getLocationContext());
+ SVal StrVal = C.getSVal(Init);
assert(StrVal.isValid() && "Initializer string is unknown or undefined");
DefinedOrUnknownSVal strLength =
- getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>();
+ getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>();
state = state->set<CStringLength>(MR, strLength);
}
@@ -2162,11 +2315,11 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
ProgramStateRef
CStringChecker::checkRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx,
- const CallEvent *Call) const {
+ const InvalidatedSymbols *,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
+ const CallEvent *Call) const {
CStringLengthTy Entries = state->get<CStringLength>();
if (Entries.isEmpty())
return state;
@@ -2176,7 +2329,7 @@ CStringChecker::checkRegionChanges(ProgramStateRef state,
// First build sets for the changed regions and their super-regions.
for (ArrayRef<const MemRegion *>::iterator
- I = Regions.begin(), E = Regions.end(); I != E; ++I) {
+ I = Regions.begin(), E = Regions.end(); I != E; ++I) {
const MemRegion *MR = *I;
Invalidated.insert(MR);
@@ -2191,7 +2344,7 @@ CStringChecker::checkRegionChanges(ProgramStateRef state,
// Then loop over the entries in the current state.
for (CStringLengthTy::iterator I = Entries.begin(),
- E = Entries.end(); I != E; ++I) {
+ E = Entries.end(); I != E; ++I) {
const MemRegion *MR = I.getKey();
// Is this entry for a super-region of a changed region?
@@ -2215,22 +2368,22 @@ CStringChecker::checkRegionChanges(ProgramStateRef state,
}
void CStringChecker::checkLiveSymbols(ProgramStateRef state,
- SymbolReaper &SR) const {
+ SymbolReaper &SR) const {
// Mark all symbols in our string length map as valid.
CStringLengthTy Entries = state->get<CStringLength>();
for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
- I != E; ++I) {
+ I != E; ++I) {
SVal Len = I.getData();
for (SymExpr::symbol_iterator si = Len.symbol_begin(),
- se = Len.symbol_end(); si != se; ++si)
+ se = Len.symbol_end(); si != se; ++si)
SR.markInUse(*si);
}
}
void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
- CheckerContext &C) const {
+ CheckerContext &C) const {
if (!SR.hasDeadSymbols())
return;
@@ -2241,7 +2394,7 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
CStringLengthTy::Factory &F = state->get_context<CStringLength>();
for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
- I != E; ++I) {
+ I != E; ++I) {
SVal Len = I.getData();
if (SymbolRef Sym = Len.getAsSymbol()) {
if (SR.isDead(Sym))
@@ -2260,11 +2413,11 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
}
-REGISTER_CHECKER(CStringNullArg)
-REGISTER_CHECKER(CStringOutOfBounds)
-REGISTER_CHECKER(CStringBufferOverlap)
+ REGISTER_CHECKER(CStringNullArg)
+ REGISTER_CHECKER(CStringOutOfBounds)
+ REGISTER_CHECKER(CStringBufferOverlap)
REGISTER_CHECKER(CStringNotNullTerm)
-void ento::registerCStringCheckerBasic(CheckerManager &Mgr) {
- registerCStringNullArg(Mgr);
-}
+ void ento::registerCStringCheckerBasic(CheckerManager &Mgr) {
+ Mgr.registerChecker<CStringChecker>();
+ }
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
index 4b5e97b69295..8b4aa857e775 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -80,6 +80,18 @@ class WalkAST: public StmtVisitor<WalkAST> {
/// of bytes to copy.
bool containsBadStrncatPattern(const CallExpr *CE);
+ /// Identify erroneous patterns in the last argument to strlcpy - the number
+ /// of bytes to copy.
+ /// The bad pattern checked is when the size is known
+ /// to be larger than the destination can handle.
+ /// char dst[2];
+ /// size_t cpy = 4;
+ /// strlcpy(dst, "abcd", sizeof("abcd") - 1);
+ /// strlcpy(dst, "abcd", 4);
+ /// strlcpy(dst + 3, "abcd", 2);
+ /// strlcpy(dst, "abcd", cpy);
+ bool containsBadStrlcpyPattern(const CallExpr *CE);
+
public:
WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
: Checker(Checker), BR(BR), AC(AC) {}
@@ -130,6 +142,54 @@ bool WalkAST::containsBadStrncatPattern(const CallExpr *CE) {
return false;
}
+bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+ if (CE->getNumArgs() != 3)
+ return false;
+ const Expr *DstArg = CE->getArg(0);
+ const Expr *LenArg = CE->getArg(2);
+
+ const auto *DstArgDecl = dyn_cast<DeclRefExpr>(DstArg->IgnoreParenImpCasts());
+ const auto *LenArgDecl = dyn_cast<DeclRefExpr>(LenArg->IgnoreParenLValueCasts());
+ uint64_t DstOff = 0;
+ // - size_t dstlen = sizeof(dst)
+ if (LenArgDecl) {
+ const auto *LenArgVal = dyn_cast<VarDecl>(LenArgDecl->getDecl());
+ if (LenArgVal->getInit())
+ LenArg = LenArgVal->getInit();
+ }
+
+ // - integral value
+ // We try to figure out if the last argument is possibly longer
+ // than the destination can possibly handle if its size can be defined.
+ if (const auto *IL = dyn_cast<IntegerLiteral>(LenArg->IgnoreParenImpCasts())) {
+ uint64_t ILRawVal = IL->getValue().getZExtValue();
+
+ // Case when there is pointer arithmetic on the destination buffer
+ // especially when we offset from the base decreasing the
+ // buffer length accordingly.
+ if (!DstArgDecl) {
+ if (const auto *BE = dyn_cast<BinaryOperator>(DstArg->IgnoreParenImpCasts())) {
+ DstArgDecl = dyn_cast<DeclRefExpr>(BE->getLHS()->IgnoreParenImpCasts());
+ if (BE->getOpcode() == BO_Add) {
+ if ((IL = dyn_cast<IntegerLiteral>(BE->getRHS()->IgnoreParenImpCasts()))) {
+ DstOff = IL->getValue().getZExtValue();
+ }
+ }
+ }
+ }
+ if (DstArgDecl) {
+ if (const auto *Buffer = dyn_cast<ConstantArrayType>(DstArgDecl->getType())) {
+ ASTContext &C = BR.getContext();
+ uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
+ if ((BufferLen - DstOff) < ILRawVal)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
void WalkAST::VisitCallExpr(CallExpr *CE) {
const FunctionDecl *FD = CE->getDirectCallee();
if (!FD)
@@ -159,6 +219,25 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
"C String API", os.str(), Loc,
LenArg->getSourceRange());
}
+ } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
+ if (containsBadStrlcpyPattern(CE)) {
+ const Expr *DstArg = CE->getArg(0);
+ const Expr *LenArg = CE->getArg(2);
+ PathDiagnosticLocation Loc =
+ PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC);
+
+ StringRef DstName = getPrintableName(DstArg);
+
+ SmallString<256> S;
+ llvm::raw_svector_ostream os(S);
+ os << "The third argument is larger than the size of the input buffer. ";
+ if (!DstName.empty())
+ os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
+
+ BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+ }
}
// Recurse and check children.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
index 668e772fe1b3..d1d37c75dfcc 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
@@ -48,7 +48,7 @@ void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {
auto &State = C.getState();
auto &SVB = C.getSValBuilder();
auto ThisVal =
- State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));
auto ParamVal = State->getSVal(Param);
ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 3e178152d925..059553b21995 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -101,7 +101,7 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
return;
ProgramStateRef state = C.getState();
- const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion();
+ const MemRegion *R = C.getSVal(E).getAsRegion();
if (!R)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index 65e81315f095..00e903355720 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -78,7 +78,7 @@ bool CastToStructVisitor::VisitCastExpr(const CastExpr *CE) {
// Don't warn for references
const ValueDecl *VD = nullptr;
if (const auto *SE = dyn_cast<DeclRefExpr>(U->getSubExpr()))
- VD = dyn_cast<ValueDecl>(SE->getDecl());
+ VD = SE->getDecl();
else if (const auto *SE = dyn_cast<MemberExpr>(U->getSubExpr()))
VD = SE->getMemberDecl();
if (!VD || VD->getType()->isReferenceType())
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 2818c9d9fd4a..f4d2e32cef11 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -126,7 +126,7 @@ public:
const CallEvent *Call,
PointerEscapeKind Kind) const;
void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
- void checkEndFunction(CheckerContext &Ctx) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
private:
void diagnoseMissingReleases(CheckerContext &C) const;
@@ -398,7 +398,7 @@ void ObjCDeallocChecker::checkPostObjCMessage(
/// Check for missing releases even when -dealloc does not call
/// '[super dealloc]'.
void ObjCDeallocChecker::checkEndFunction(
- CheckerContext &C) const {
+ const ReturnStmt *RS, CheckerContext &C) const {
diagnoseMissingReleases(C);
}
@@ -535,7 +535,7 @@ void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
continue;
// Prevents diagnosing multiple times for the same instance variable
- // at, for example, both a return and at the end of of the function.
+ // at, for example, both a return and at the end of the function.
NewUnreleased = F.remove(NewUnreleased, IvarSymbol);
if (State->getStateManager()
@@ -645,7 +645,7 @@ ObjCDeallocChecker::findPropertyOnDeallocatingInstance(
bool ObjCDeallocChecker::diagnoseExtraRelease(SymbolRef ReleasedValue,
const ObjCMethodCall &M,
CheckerContext &C) const {
- // Try to get the region from which the the released value was loaded.
+ // Try to get the region from which the released value was loaded.
// Note that, unlike diagnosing for missing releases, here we don't track
// values that must not be released in the state. This is because even if
// these values escape, it is still an error under the rules of MRR to
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 6dbacad7f2ea..202233acffab 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -37,6 +37,9 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) {
namespace {
struct ChecksFilter {
+ DefaultBool check_bcmp;
+ DefaultBool check_bcopy;
+ DefaultBool check_bzero;
DefaultBool check_gets;
DefaultBool check_getpw;
DefaultBool check_mktemp;
@@ -47,6 +50,9 @@ struct ChecksFilter {
DefaultBool check_FloatLoopCounter;
DefaultBool check_UncheckedReturn;
+ CheckName checkName_bcmp;
+ CheckName checkName_bcopy;
+ CheckName checkName_bzero;
CheckName checkName_gets;
CheckName checkName_getpw;
CheckName checkName_mktemp;
@@ -89,6 +95,9 @@ public:
// Checker-specific methods.
void checkLoopConditionForFloat(const ForStmt *FS);
+ void checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD);
+ void checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD);
+ void checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD);
void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
@@ -129,6 +138,9 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
// Set the evaluation function by switching on the callee name.
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
+ .Case("bcmp", &WalkAST::checkCall_bcmp)
+ .Case("bcopy", &WalkAST::checkCall_bcopy)
+ .Case("bzero", &WalkAST::checkCall_bzero)
.Case("gets", &WalkAST::checkCall_gets)
.Case("getpw", &WalkAST::checkCall_getpw)
.Case("mktemp", &WalkAST::checkCall_mktemp)
@@ -296,6 +308,132 @@ void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
}
//===----------------------------------------------------------------------===//
+// Check: Any use of bcmp.
+// CWE-477: Use of Obsolete Functions
+// bcmp was deprecated in POSIX.1-2008
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD) {
+ if (!filter.check_bcmp)
+ return;
+
+ const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
+ if (!FPT)
+ return;
+
+ // Verify that the function takes three arguments.
+ if (FPT->getNumParams() != 3)
+ return;
+
+ for (int i = 0; i < 2; i++) {
+ // Verify the first and second argument type is void*.
+ const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
+ if (!PT)
+ return;
+
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
+ return;
+ }
+
+ // Verify the third argument type is integer.
+ if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType())
+ return;
+
+ // Issue a warning.
+ PathDiagnosticLocation CELoc =
+ PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+ BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcmp,
+ "Use of deprecated function in call to 'bcmp()'",
+ "Security",
+ "The bcmp() function is obsoleted by memcmp().",
+ CELoc, CE->getCallee()->getSourceRange());
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of bcopy.
+// CWE-477: Use of Obsolete Functions
+// bcopy was deprecated in POSIX.1-2008
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD) {
+ if (!filter.check_bcopy)
+ return;
+
+ const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
+ if (!FPT)
+ return;
+
+ // Verify that the function takes three arguments.
+ if (FPT->getNumParams() != 3)
+ return;
+
+ for (int i = 0; i < 2; i++) {
+ // Verify the first and second argument type is void*.
+ const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
+ if (!PT)
+ return;
+
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
+ return;
+ }
+
+ // Verify the third argument type is integer.
+ if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType())
+ return;
+
+ // Issue a warning.
+ PathDiagnosticLocation CELoc =
+ PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+ BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcopy,
+ "Use of deprecated function in call to 'bcopy()'",
+ "Security",
+ "The bcopy() function is obsoleted by memcpy() "
+ "or memmove().",
+ CELoc, CE->getCallee()->getSourceRange());
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of bzero.
+// CWE-477: Use of Obsolete Functions
+// bzero was deprecated in POSIX.1-2008
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD) {
+ if (!filter.check_bzero)
+ return;
+
+ const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
+ if (!FPT)
+ return;
+
+ // Verify that the function takes two arguments.
+ if (FPT->getNumParams() != 2)
+ return;
+
+ // Verify the first argument type is void*.
+ const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
+ if (!PT)
+ return;
+
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
+ return;
+
+ // Verify the second argument type is integer.
+ if (!FPT->getParamType(1)->isIntegralOrUnscopedEnumerationType())
+ return;
+
+ // Issue a warning.
+ PathDiagnosticLocation CELoc =
+ PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+ BR.EmitBasicReport(AC->getDecl(), filter.checkName_bzero,
+ "Use of deprecated function in call to 'bzero()'",
+ "Security",
+ "The bzero() function is obsoleted by memset().",
+ CELoc, CE->getCallee()->getSourceRange());
+}
+
+
+//===----------------------------------------------------------------------===//
// Check: Any use of 'gets' is insecure.
// Originally: <rdar://problem/6335715>
// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
@@ -510,6 +648,17 @@ void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
if (!checkCall_strCommon(CE, FD))
return;
+ const auto *Target = CE->getArg(0)->IgnoreImpCasts(),
+ *Source = CE->getArg(1)->IgnoreImpCasts();
+ if (const auto *DeclRef = dyn_cast<DeclRefExpr>(Target))
+ if (const auto *Array = dyn_cast<ConstantArrayType>(DeclRef->getType())) {
+ uint64_t ArraySize = BR.getContext().getTypeSize(Array) / 8;
+ if (const auto *String = dyn_cast<StringLiteral>(Source)) {
+ if (ArraySize >= String->getLength() + 1)
+ return;
+ }
+ }
+
// Issue a warning.
PathDiagnosticLocation CELoc =
PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
@@ -764,6 +913,9 @@ public:
checker->filter.checkName_##name = mgr.getCurrentCheckName(); \
}
+REGISTER_CHECKER(bcmp)
+REGISTER_CHECKER(bcopy)
+REGISTER_CHECKER(bzero)
REGISTER_CHECKER(gets)
REGISTER_CHECKER(getpw)
REGISTER_CHECKER(mkstemp)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 95b6c4d3775d..7862a4c25681 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -42,6 +42,7 @@ class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
check::PreCall,
check::PostCall,
check::BranchCondition,
+ check::NewAllocator,
check::Location,
check::Bind,
check::DeadSymbols,
@@ -58,7 +59,7 @@ class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
check::Event<ImplicitNullDerefEvent>,
check::ASTDecl<FunctionDecl> > {
public:
- /// \brief Pre-visit the Statement.
+ /// Pre-visit the Statement.
///
/// The method will be called before the analyzer core processes the
/// statement. The notification is performed for every explored CFGElement,
@@ -71,7 +72,7 @@ public:
/// check::PreStmt<ReturnStmt>
void checkPreStmt(const ReturnStmt *DS, CheckerContext &C) const {}
- /// \brief Post-visit the Statement.
+ /// Post-visit the Statement.
///
/// The method will be called after the analyzer core processes the
/// statement. The notification is performed for every explored CFGElement,
@@ -81,7 +82,7 @@ public:
/// check::PostStmt<DeclStmt>
void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
- /// \brief Pre-visit the Objective C message.
+ /// Pre-visit the Objective C message.
///
/// This will be called before the analyzer core processes the method call.
/// This is called for any action which produces an Objective-C message send,
@@ -90,13 +91,13 @@ public:
/// check::PreObjCMessage
void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}
- /// \brief Post-visit the Objective C message.
+ /// Post-visit the Objective C message.
/// \sa checkPreObjCMessage()
///
/// check::PostObjCMessage
void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}
- /// \brief Visit an Objective-C message whose receiver is nil.
+ /// Visit an Objective-C message whose receiver is nil.
///
/// This will be called when the analyzer core processes a method call whose
/// receiver is definitely nil. In this case, check{Pre/Post}ObjCMessage and
@@ -105,7 +106,7 @@ public:
/// check::ObjCMessageNil
void checkObjCMessageNil(const ObjCMethodCall &M, CheckerContext &C) const {}
- /// \brief Pre-visit an abstract "call" event.
+ /// Pre-visit an abstract "call" event.
///
/// This is used for checkers that want to check arguments or attributed
/// behavior for functions and methods no matter how they are being invoked.
@@ -117,16 +118,32 @@ public:
/// check::PreCall
void checkPreCall(const CallEvent &Call, CheckerContext &C) const {}
- /// \brief Post-visit an abstract "call" event.
+ /// Post-visit an abstract "call" event.
/// \sa checkPreObjCMessage()
///
/// check::PostCall
void checkPostCall(const CallEvent &Call, CheckerContext &C) const {}
- /// \brief Pre-visit of the condition statement of a branch (such as IfStmt).
+ /// Pre-visit of the condition statement of a branch (such as IfStmt).
void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const {}
- /// \brief Called on a load from and a store to a location.
+ /// Post-visit the C++ operator new's allocation call.
+ ///
+ /// Execution of C++ operator new consists of the following phases: (1) call
+ /// default or overridden operator new() to allocate memory (2) cast the
+ /// return value of operator new() from void pointer type to class pointer
+ /// type, (3) assuming that the value is non-null, call the object's
+ /// constructor over this pointer, (4) declare that the value of the
+ /// new-expression is this pointer. This callback is called between steps
+ /// (2) and (3). Post-call for the allocator is called after step (1).
+ /// Pre-statement for the new-expression is called on step (4) when the value
+ /// of the expression is evaluated.
+ /// \param NE The C++ new-expression that triggered the allocation.
+ /// \param Target The allocated region, casted to the class type.
+ void checkNewAllocator(const CXXNewExpr *NE, SVal Target,
+ CheckerContext &) const {}
+
+ /// Called on a load from and a store to a location.
///
/// The method will be called each time a location (pointer) value is
/// accessed.
@@ -138,7 +155,7 @@ public:
void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
CheckerContext &) const {}
- /// \brief Called on binding of a value to a location.
+ /// Called on binding of a value to a location.
///
/// \param Loc The value of the location (pointer).
/// \param Val The value which will be stored at the location Loc.
@@ -147,7 +164,7 @@ public:
/// check::Bind
void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &) const {}
- /// \brief Called whenever a symbol becomes dead.
+ /// Called whenever a symbol becomes dead.
///
/// This callback should be used by the checkers to aggressively clean
/// up/reduce the checker state, which is important for reducing the overall
@@ -164,20 +181,20 @@ public:
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const {}
- /// \brief Called when the analyzer core starts analyzing a function,
+ /// Called when the analyzer core starts analyzing a function,
/// regardless of whether it is analyzed at the top level or is inlined.
///
/// check::BeginFunction
void checkBeginFunction(CheckerContext &Ctx) const {}
- /// \brief Called when the analyzer core reaches the end of a
+ /// Called when the analyzer core reaches the end of a
/// function being analyzed regardless of whether it is analyzed at the top
/// level or is inlined.
///
/// check::EndFunction
- void checkEndFunction(CheckerContext &Ctx) const {}
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const {}
- /// \brief Called after all the paths in the ExplodedGraph reach end of path
+ /// Called after all the paths in the ExplodedGraph reach end of path
/// - the symbolic execution graph is fully explored.
///
/// This callback should be used in cases when a checker needs to have a
@@ -190,14 +207,14 @@ public:
BugReporter &BR,
ExprEngine &Eng) const {}
- /// \brief Called after analysis of a TranslationUnit is complete.
+ /// Called after analysis of a TranslationUnit is complete.
///
/// check::EndOfTranslationUnit
void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
AnalysisManager &Mgr,
BugReporter &BR) const {}
- /// \brief Evaluates function call.
+ /// Evaluates function call.
///
/// The analysis core threats all function calls in the same way. However, some
/// functions have special meaning, which should be reflected in the program
@@ -212,7 +229,7 @@ public:
/// eval::Call
bool evalCall(const CallExpr *CE, CheckerContext &C) const { return true; }
- /// \brief Handles assumptions on symbolic values.
+ /// Handles assumptions on symbolic values.
///
/// This method is called when a symbolic expression is assumed to be true or
/// false. For example, the assumptions are performed when evaluating a
@@ -231,7 +248,7 @@ public:
/// check::LiveSymbols
void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const {}
- /// \brief Called when the contents of one or more regions change.
+ /// Called when the contents of one or more regions change.
///
/// This can occur in many different ways: an explicit bind, a blanket
/// invalidation of the region contents, or by passing a region to a function
@@ -263,7 +280,7 @@ public:
return State;
}
- /// \brief Called when pointers escape.
+ /// Called when pointers escape.
///
/// This notifies the checkers about pointer escape, which occurs whenever
/// the analyzer cannot track the symbol any more. For example, as a
@@ -283,7 +300,7 @@ public:
return State;
}
- /// \brief Called when const pointers escape.
+ /// Called when const pointers escape.
///
/// Note: in most cases checkPointerEscape callback is sufficient.
/// \sa checkPointerEscape
@@ -297,7 +314,7 @@ public:
/// check::Event<ImplicitNullDerefEvent>
void checkEvent(ImplicitNullDerefEvent Event) const {}
- /// \brief Check every declaration in the AST.
+ /// Check every declaration in the AST.
///
/// An AST traversal callback, which should only be used when the checker is
/// not path sensitive. It will be called for every Declaration in the AST and
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 9e9939ae25c0..b38992b0e030 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -105,7 +105,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
// After chdir("/"), enter the jail, set the enum value JAIL_ENTERED.
const Expr *ArgExpr = CE->getArg(0);
- SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
+ SVal ArgVal = C.getSVal(ArgExpr);
if (const MemRegion *R = ArgVal.getAsRegion()) {
R = R->StripCasts();
@@ -132,7 +132,7 @@ void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
if (!II_chdir)
II_chdir = &Ctx.Idents.get("chdir");
- // Ingnore chroot and chdir.
+ // Ignore chroot and chdir.
if (FD->getIdentifier() == II_chroot || FD->getIdentifier() == II_chdir)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
index e04e2ab2c320..d3489282ab62 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
@@ -39,7 +39,7 @@ class DeleteWithNonVirtualDtorChecker
: public Checker<check::PreStmt<CXXDeleteExpr>> {
mutable std::unique_ptr<BugType> BT;
- class DeleteBugVisitor : public BugReporterVisitorImpl<DeleteBugVisitor> {
+ class DeleteBugVisitor : public BugReporterVisitor {
public:
DeleteBugVisitor() : Satisfied(false) {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
@@ -110,8 +110,6 @@ DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
if (Satisfied)
return nullptr;
- ProgramStateRef State = N->getState();
- const LocationContext *LC = N->getLocationContext();
const Stmt *S = PathDiagnosticLocation::getStmt(N);
if (!S)
return nullptr;
@@ -128,7 +126,7 @@ DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
}
// Region associated with the current cast expression.
- const MemRegion *M = State->getSVal(CastE, LC).getAsRegion();
+ const MemRegion *M = N->getSVal(CastE).getAsRegion();
if (!M)
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index 598502305633..bc39c92ea970 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -24,22 +24,23 @@ using namespace ento;
namespace {
class DivZeroChecker : public Checker< check::PreStmt<BinaryOperator> > {
mutable std::unique_ptr<BuiltinBug> BT;
- void reportBug(const char *Msg,
- ProgramStateRef StateZero,
- CheckerContext &C) const ;
+ void reportBug(const char *Msg, ProgramStateRef StateZero, CheckerContext &C,
+ std::unique_ptr<BugReporterVisitor> Visitor = nullptr) const;
+
public:
void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
} // end anonymous namespace
-void DivZeroChecker::reportBug(const char *Msg,
- ProgramStateRef StateZero,
- CheckerContext &C) const {
+void DivZeroChecker::reportBug(
+ const char *Msg, ProgramStateRef StateZero, CheckerContext &C,
+ std::unique_ptr<BugReporterVisitor> Visitor) const {
if (ExplodedNode *N = C.generateErrorNode(StateZero)) {
if (!BT)
BT.reset(new BuiltinBug(this, "Division by zero"));
auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
+ R->addVisitor(std::move(Visitor));
bugreporter::trackNullOrUndefValue(N, bugreporter::GetDenomExpr(N), *R);
C.emitReport(std::move(R));
}
@@ -57,7 +58,7 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
if (!B->getRHS()->getType()->isScalarType())
return;
- SVal Denom = C.getState()->getSVal(B->getRHS(), C.getLocationContext());
+ SVal Denom = C.getSVal(B->getRHS());
Optional<DefinedSVal> DV = Denom.getAs<DefinedSVal>();
// Divide-by-undefined handled in the generic checking for uses of
@@ -78,7 +79,8 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
bool TaintedD = C.getState()->isTainted(*DV);
if ((stateNotZero && stateZero && TaintedD)) {
- reportBug("Division by a tainted value, possibly zero", stateZero, C);
+ reportBug("Division by a tainted value, possibly zero", stateZero, C,
+ llvm::make_unique<TaintBugVisitor>(*DV));
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
index 109897be2931..4e4d81cd6714 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
@@ -38,8 +38,7 @@ class DynamicTypeChecker : public Checker<check::PostStmt<ImplicitCastExpr>> {
new BugType(this, "Dynamic and static type mismatch", "Type Error"));
}
- class DynamicTypeBugVisitor
- : public BugReporterVisitorImpl<DynamicTypeBugVisitor> {
+ class DynamicTypeBugVisitor : public BugReporterVisitor {
public:
DynamicTypeBugVisitor(const MemRegion *Reg) : Reg(Reg) {}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index db9179e018a1..126e57645a43 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -59,7 +59,7 @@ class DynamicTypePropagation:
const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
CheckerContext &C) const;
- /// \brief Return a better dynamic type if one can be derived from the cast.
+ /// Return a better dynamic type if one can be derived from the cast.
const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
CheckerContext &C) const;
@@ -74,7 +74,7 @@ class DynamicTypePropagation:
new BugType(this, "Generics", categories::CoreFoundationObjectiveC));
}
- class GenericsBugVisitor : public BugReporterVisitorImpl<GenericsBugVisitor> {
+ class GenericsBugVisitor : public BugReporterVisitor {
public:
GenericsBugVisitor(SymbolRef S) : Sym(S) {}
@@ -562,7 +562,7 @@ void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
DestObjectPtrType->isUnspecialized())
return;
- SymbolRef Sym = State->getSVal(CE, C.getLocationContext()).getAsSymbol();
+ SymbolRef Sym = C.getSVal(CE).getAsSymbol();
if (!Sym)
return;
@@ -631,7 +631,7 @@ static const Expr *stripCastsAndSugar(const Expr *E) {
}
static bool isObjCTypeParamDependent(QualType Type) {
- // It is illegal to typedef parameterized types inside an interface. Therfore
+ // It is illegal to typedef parameterized types inside an interface. Therefore
// an Objective-C type can only be dependent on a type parameter when the type
// parameter structurally present in the type itself.
class IsObjCTypeParamDependentTypeVisitor
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 0005ec470d20..8de653c10f7e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -149,7 +149,7 @@ void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
// A specific instantiation of an inlined function may have more constrained
// values than can generally be assumed. Skip the check.
- if (LC->getCurrentStackFrame()->getParent() != nullptr)
+ if (LC->getStackFrame()->getParent() != nullptr)
return;
reportBug(getArgumentValueString(CE, C), C);
@@ -178,7 +178,7 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
// when we are analyzing it as an inlined function. This means that
// clang_analyzer_checkInlined(true) should always print TRUE, but
// clang_analyzer_checkInlined(false) should never actually print anything.
- if (LC->getCurrentStackFrame()->getParent() == nullptr)
+ if (LC->getStackFrame()->getParent() == nullptr)
return;
reportBug(getArgumentValueString(CE, C), C);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index 3fe89f96a43b..059203fca730 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -44,8 +44,7 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
if (!T->isPointerType())
return;
- ProgramStateRef state = C.getState();
- SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());
+ SVal RV = C.getSVal(B->getRHS());
if (!RV.isConstant() || RV.isZeroConstant())
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
new file mode 100644
index 000000000000..5cb51b01f044
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
@@ -0,0 +1,229 @@
+//===- GCDAntipatternChecker.cpp ---------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines GCDAntipatternChecker which checks against a common
+// antipattern when synchronous API is emulated from asynchronous callbacks
+// using a semaphore:
+//
+// dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+//
+// AnyCFunctionCall(^{
+// // code…
+// dispatch_semaphore_signal(sema);
+// })
+// dispatch_semaphore_wait(sema, *)
+//
+// Such code is a common performance problem, due to inability of GCD to
+// properly handle QoS when a combination of queues and semaphores is used.
+// Good code would either use asynchronous API (when available), or perform
+// the necessary action in asynchronous callback.
+//
+// Currently, the check is performed using a simple heuristical AST pattern
+// matching.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.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/Support/Debug.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+// ID of a node at which the diagnostic would be emitted.
+const char *WarnAtNode = "waitcall";
+
+class GCDAntipatternChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+};
+
+auto callsName(const char *FunctionName)
+ -> decltype(callee(functionDecl())) {
+ return callee(functionDecl(hasName(FunctionName)));
+}
+
+auto equalsBoundArgDecl(int ArgIdx, const char *DeclName)
+ -> decltype(hasArgument(0, expr())) {
+ return hasArgument(ArgIdx, ignoringParenCasts(declRefExpr(
+ to(varDecl(equalsBoundNode(DeclName))))));
+}
+
+auto bindAssignmentToDecl(const char *DeclName) -> decltype(hasLHS(expr())) {
+ return hasLHS(ignoringParenImpCasts(
+ declRefExpr(to(varDecl().bind(DeclName)))));
+}
+
+/// The pattern is very common in tests, and it is OK to use it there.
+/// We have to heuristics for detecting tests: method name starts with "test"
+/// (used in XCTest), and a class name contains "mock" or "test" (used in
+/// helpers which are not tests themselves, but used exclusively in tests).
+static bool isTest(const Decl *D) {
+ if (const auto* ND = dyn_cast<NamedDecl>(D)) {
+ std::string DeclName = ND->getNameAsString();
+ if (StringRef(DeclName).startswith("test"))
+ return true;
+ }
+ if (const auto *OD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (const auto *CD = dyn_cast<ObjCContainerDecl>(OD->getParent())) {
+ std::string ContainerName = CD->getNameAsString();
+ StringRef CN(ContainerName);
+ if (CN.contains_lower("test") || CN.contains_lower("mock"))
+ return true;
+ }
+ }
+ return false;
+}
+
+static auto findGCDAntiPatternWithSemaphore() -> decltype(compoundStmt()) {
+
+ const char *SemaphoreBinding = "semaphore_name";
+ auto SemaphoreCreateM = callExpr(allOf(
+ callsName("dispatch_semaphore_create"),
+ hasArgument(0, ignoringParenCasts(integerLiteral(equals(0))))));
+
+ auto SemaphoreBindingM = anyOf(
+ forEachDescendant(
+ varDecl(hasDescendant(SemaphoreCreateM)).bind(SemaphoreBinding)),
+ forEachDescendant(binaryOperator(bindAssignmentToDecl(SemaphoreBinding),
+ hasRHS(SemaphoreCreateM))));
+
+ auto HasBlockArgumentM = hasAnyArgument(hasType(
+ hasCanonicalType(blockPointerType())
+ ));
+
+ auto ArgCallsSignalM = hasAnyArgument(stmt(hasDescendant(callExpr(
+ allOf(
+ callsName("dispatch_semaphore_signal"),
+ equalsBoundArgDecl(0, SemaphoreBinding)
+ )))));
+
+ auto HasBlockAndCallsSignalM = allOf(HasBlockArgumentM, ArgCallsSignalM);
+
+ auto HasBlockCallingSignalM =
+ forEachDescendant(
+ stmt(anyOf(
+ callExpr(HasBlockAndCallsSignalM),
+ objcMessageExpr(HasBlockAndCallsSignalM)
+ )));
+
+ auto SemaphoreWaitM = forEachDescendant(
+ callExpr(
+ allOf(
+ callsName("dispatch_semaphore_wait"),
+ equalsBoundArgDecl(0, SemaphoreBinding)
+ )
+ ).bind(WarnAtNode));
+
+ return compoundStmt(
+ SemaphoreBindingM, HasBlockCallingSignalM, SemaphoreWaitM);
+}
+
+static auto findGCDAntiPatternWithGroup() -> decltype(compoundStmt()) {
+
+ const char *GroupBinding = "group_name";
+ auto DispatchGroupCreateM = callExpr(callsName("dispatch_group_create"));
+
+ auto GroupBindingM = anyOf(
+ forEachDescendant(
+ varDecl(hasDescendant(DispatchGroupCreateM)).bind(GroupBinding)),
+ forEachDescendant(binaryOperator(bindAssignmentToDecl(GroupBinding),
+ hasRHS(DispatchGroupCreateM))));
+
+ auto GroupEnterM = forEachDescendant(
+ stmt(callExpr(allOf(callsName("dispatch_group_enter"),
+ equalsBoundArgDecl(0, GroupBinding)))));
+
+ auto HasBlockArgumentM = hasAnyArgument(hasType(
+ hasCanonicalType(blockPointerType())
+ ));
+
+ auto ArgCallsSignalM = hasAnyArgument(stmt(hasDescendant(callExpr(
+ allOf(
+ callsName("dispatch_group_leave"),
+ equalsBoundArgDecl(0, GroupBinding)
+ )))));
+
+ auto HasBlockAndCallsLeaveM = allOf(HasBlockArgumentM, ArgCallsSignalM);
+
+ auto AcceptsBlockM =
+ forEachDescendant(
+ stmt(anyOf(
+ callExpr(HasBlockAndCallsLeaveM),
+ objcMessageExpr(HasBlockAndCallsLeaveM)
+ )));
+
+ auto GroupWaitM = forEachDescendant(
+ callExpr(
+ allOf(
+ callsName("dispatch_group_wait"),
+ equalsBoundArgDecl(0, GroupBinding)
+ )
+ ).bind(WarnAtNode));
+
+ return compoundStmt(GroupBindingM, GroupEnterM, AcceptsBlockM, GroupWaitM);
+}
+
+static void emitDiagnostics(const BoundNodes &Nodes,
+ const char* Type,
+ BugReporter &BR,
+ AnalysisDeclContext *ADC,
+ const GCDAntipatternChecker *Checker) {
+ const auto *SW = Nodes.getNodeAs<CallExpr>(WarnAtNode);
+ assert(SW);
+
+ std::string Diagnostics;
+ llvm::raw_string_ostream OS(Diagnostics);
+ OS << "Waiting on a callback using a " << Type << " creates useless threads "
+ << "and is subject to priority inversion; consider "
+ << "using a synchronous API or changing the caller to be asynchronous";
+
+ BR.EmitBasicReport(
+ ADC->getDecl(),
+ Checker,
+ /*Name=*/"GCD performance anti-pattern",
+ /*Category=*/"Performance",
+ OS.str(),
+ PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC),
+ SW->getSourceRange());
+}
+
+void GCDAntipatternChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+ if (isTest(D))
+ return;
+
+ AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
+
+ auto SemaphoreMatcherM = findGCDAntiPatternWithSemaphore();
+ auto Matches = match(SemaphoreMatcherM, *D->getBody(), AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, "semaphore", BR, ADC, this);
+
+ auto GroupMatcherM = findGCDAntiPatternWithGroup();
+ Matches = match(GroupMatcherM, *D->getBody(), AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, "group", BR, ADC, this);
+}
+
+}
+
+void ento::registerGCDAntipattern(CheckerManager &Mgr) {
+ Mgr.registerChecker<GCDAntipatternChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
index f0be41b293e4..3ef95e673b87 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
@@ -161,7 +161,7 @@ void GTestChecker::modelAssertionResultCopyConstructor(
const CXXConstructorCall *Call, CheckerContext &C) const {
assert(Call->getNumArgs() == 1);
- // The first parameter of the the copy constructor must be the other
+ // The first parameter of the copy constructor must be the other
// instance to initialize this instances fields from.
SVal OtherVal = Call->getArgSVal(0);
SVal ThisVal = Call->getCXXThisVal();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 43966656cd8d..899586745a0b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -48,24 +48,24 @@ private:
BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
}
- /// \brief Catch taint related bugs. Check if tainted data is passed to a
+ /// Catch taint related bugs. Check if tainted data is passed to a
/// system call etc.
bool checkPre(const CallExpr *CE, CheckerContext &C) const;
- /// \brief Add taint sources on a pre-visit.
+ /// Add taint sources on a pre-visit.
void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
- /// \brief Propagate taint generated at pre-visit.
+ /// Propagate taint generated at pre-visit.
bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
- /// \brief Add taint sources on a post visit.
+ /// Add taint sources on a post visit.
void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
/// Check if the region the expression evaluates to is the standard input,
/// and thus, is tainted.
static bool isStdin(const Expr *E, CheckerContext &C);
- /// \brief Given a pointer argument, return the value it points to.
+ /// Given a pointer argument, return the value it points to.
static Optional<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
/// Functions defining the attack surface.
@@ -100,26 +100,9 @@ private:
bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
- /// The bug visitor prints a diagnostic message at the location where a given
- /// variable was tainted.
- class TaintBugVisitor
- : public BugReporterVisitorImpl<TaintBugVisitor> {
- private:
- const SVal V;
-
- public:
- TaintBugVisitor(const SVal V) : V(V) {}
- void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); }
-
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
- };
-
typedef SmallVector<unsigned, 2> ArgVector;
- /// \brief A struct used to specify taint propagation rules for a function.
+ /// A struct used to specify taint propagation rules for a function.
///
/// If any of the possible taint source arguments is tainted, all of the
/// destination arguments should also be tainted. Use InvalidArgIndex in the
@@ -183,7 +166,7 @@ private:
return (V && State->isTainted(*V));
}
- /// \brief Pre-process a function which propagates taint according to the
+ /// Pre-process a function which propagates taint according to the
/// taint rule.
ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
@@ -214,28 +197,6 @@ const char GenericTaintChecker::MsgTaintedBufferSize[] =
/// points to data, which should be tainted on return.
REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
-std::shared_ptr<PathDiagnosticPiece>
-GenericTaintChecker::TaintBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) {
-
- // Find the ExplodedNode where the taint was first introduced
- if (!N->getState()->isTainted(V) || PrevN->getState()->isTainted(V))
- return nullptr;
-
- const Stmt *S = PathDiagnosticLocation::getStmt(N);
- if (!S)
- return nullptr;
-
- const LocationContext *NCtx = N->getLocationContext();
- PathDiagnosticLocation L =
- PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx);
- if (!L.isValid() || !L.asLocation().isValid())
- return nullptr;
-
- return std::make_shared<PathDiagnosticEventPiece>(
- L, "Taint originated here");
-}
-
GenericTaintChecker::TaintPropagationRule
GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
const FunctionDecl *FDecl,
@@ -468,7 +429,7 @@ bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
const Expr *Arg) {
ProgramStateRef State = C.getState();
- SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
+ SVal AddrVal = C.getSVal(Arg->IgnoreParens());
if (AddrVal.isUnknownOrUndef())
return None;
@@ -621,7 +582,7 @@ ProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE,
bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
ProgramStateRef State = C.getState();
- SVal Val = State->getSVal(E, C.getLocationContext());
+ SVal Val = C.getSVal(E);
// stdin is a pointer, so it would be a region.
const MemRegion *MemReg = Val.getAsRegion();
@@ -646,7 +607,8 @@ bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
if (const PointerType * PtrTy =
dyn_cast<PointerType>(D->getType().getTypePtr()))
- if (PtrTy->getPointeeType() == C.getASTContext().getFILEType())
+ if (PtrTy->getPointeeType().getCanonicalType() ==
+ C.getASTContext().getFILEType().getCanonicalType())
return true;
}
return false;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index cf57b8dca063..f102ca96a5c1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This defines IdenticalExprChecker, a check that warns about
+/// This defines IdenticalExprChecker, a check that warns about
/// unintended use of identical expressions.
///
/// It checks for use of identical expressions with comparison operators and
@@ -296,7 +296,7 @@ bool FindIdenticalExprVisitor::VisitConditionalOperator(
return true;
}
-/// \brief Determines whether two statement trees are identical regarding
+/// Determines whether two statement trees are identical regarding
/// operators and symbols.
///
/// Exceptions: expressions containing macros or functions with possible side
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
new file mode 100644
index 000000000000..29677f737f5c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
@@ -0,0 +1,318 @@
+//=== InnerPointerChecker.cpp -------------------------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a check that marks a raw pointer to a C++ container's
+// inner buffer released when the object is destroyed. This information can
+// be used by MallocChecker to detect use-after-free problems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AllocationState.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+using PtrSet = llvm::ImmutableSet<SymbolRef>;
+
+// Associate container objects with a set of raw pointer symbols.
+REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, PtrSet)
+
+// This is a trick to gain access to PtrSet's Factory.
+namespace clang {
+namespace ento {
+template <>
+struct ProgramStateTrait<PtrSet> : public ProgramStatePartialTrait<PtrSet> {
+ static void *GDMIndex() {
+ static int Index = 0;
+ return &Index;
+ }
+};
+} // end namespace ento
+} // end namespace clang
+
+namespace {
+
+class InnerPointerChecker
+ : public Checker<check::DeadSymbols, check::PostCall> {
+
+ CallDescription AppendFn, AssignFn, ClearFn, CStrFn, DataFn, EraseFn,
+ InsertFn, PopBackFn, PushBackFn, ReplaceFn, ReserveFn, ResizeFn,
+ ShrinkToFitFn, SwapFn;
+
+public:
+ class InnerPointerBRVisitor : public BugReporterVisitor {
+ SymbolRef PtrToBuf;
+
+ public:
+ InnerPointerBRVisitor(SymbolRef Sym) : PtrToBuf(Sym) {}
+
+ static void *getTag() {
+ static int Tag = 0;
+ return &Tag;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ ID.AddPointer(getTag());
+ }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ // FIXME: Scan the map once in the visitor's constructor and do a direct
+ // lookup by region.
+ bool isSymbolTracked(ProgramStateRef State, SymbolRef Sym) {
+ RawPtrMapTy Map = State->get<RawPtrMap>();
+ for (const auto Entry : Map) {
+ if (Entry.second.contains(Sym))
+ return true;
+ }
+ return false;
+ }
+ };
+
+ InnerPointerChecker()
+ : AppendFn("append"), AssignFn("assign"), ClearFn("clear"),
+ CStrFn("c_str"), DataFn("data"), EraseFn("erase"), InsertFn("insert"),
+ PopBackFn("pop_back"), PushBackFn("push_back"), ReplaceFn("replace"),
+ ReserveFn("reserve"), ResizeFn("resize"),
+ ShrinkToFitFn("shrink_to_fit"), SwapFn("swap") {}
+
+ /// Check if the object of this member function call is a `basic_string`.
+ bool isCalledOnStringObject(const CXXInstanceCall *ICall) const;
+
+ /// Check whether the called member function potentially invalidates
+ /// pointers referring to the container object's inner buffer.
+ bool isInvalidatingMemberFunction(const CallEvent &Call) const;
+
+ /// Mark pointer symbols associated with the given memory region released
+ /// in the program state.
+ void markPtrSymbolsReleased(const CallEvent &Call, ProgramStateRef State,
+ const MemRegion *ObjRegion,
+ CheckerContext &C) const;
+
+ /// Standard library functions that take a non-const `basic_string` argument by
+ /// reference may invalidate its inner pointers. Check for these cases and
+ /// mark the pointers released.
+ void checkFunctionArguments(const CallEvent &Call, ProgramStateRef State,
+ CheckerContext &C) const;
+
+ /// Record the connection between raw pointers referring to a container
+ /// object's inner buffer and the object's memory region in the program state.
+ /// Mark potentially invalidated pointers released.
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+
+ /// Clean up the program state map.
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+bool InnerPointerChecker::isCalledOnStringObject(
+ const CXXInstanceCall *ICall) const {
+ const auto *ObjRegion =
+ dyn_cast_or_null<TypedValueRegion>(ICall->getCXXThisVal().getAsRegion());
+ if (!ObjRegion)
+ return false;
+
+ QualType ObjTy = ObjRegion->getValueType();
+ if (ObjTy.isNull() ||
+ ObjTy->getAsCXXRecordDecl()->getName() != "basic_string")
+ return false;
+
+ return true;
+}
+
+bool InnerPointerChecker::isInvalidatingMemberFunction(
+ const CallEvent &Call) const {
+ if (const auto *MemOpCall = dyn_cast<CXXMemberOperatorCall>(&Call)) {
+ OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator();
+ if (Opc == OO_Equal || Opc == OO_PlusEqual)
+ return true;
+ return false;
+ }
+ return (isa<CXXDestructorCall>(Call) || Call.isCalled(AppendFn) ||
+ Call.isCalled(AssignFn) || Call.isCalled(ClearFn) ||
+ Call.isCalled(EraseFn) || Call.isCalled(InsertFn) ||
+ Call.isCalled(PopBackFn) || Call.isCalled(PushBackFn) ||
+ Call.isCalled(ReplaceFn) || Call.isCalled(ReserveFn) ||
+ Call.isCalled(ResizeFn) || Call.isCalled(ShrinkToFitFn) ||
+ Call.isCalled(SwapFn));
+}
+
+void InnerPointerChecker::markPtrSymbolsReleased(const CallEvent &Call,
+ ProgramStateRef State,
+ const MemRegion *MR,
+ CheckerContext &C) const {
+ if (const PtrSet *PS = State->get<RawPtrMap>(MR)) {
+ const Expr *Origin = Call.getOriginExpr();
+ for (const auto Symbol : *PS) {
+ // NOTE: `Origin` may be null, and will be stored so in the symbol's
+ // `RefState` in MallocChecker's `RegionState` program state map.
+ State = allocation_state::markReleased(State, Symbol, Origin);
+ }
+ State = State->remove<RawPtrMap>(MR);
+ C.addTransition(State);
+ return;
+ }
+}
+
+void InnerPointerChecker::checkFunctionArguments(const CallEvent &Call,
+ ProgramStateRef State,
+ CheckerContext &C) const {
+ if (const auto *FC = dyn_cast<AnyFunctionCall>(&Call)) {
+ const FunctionDecl *FD = FC->getDecl();
+ if (!FD || !FD->isInStdNamespace())
+ return;
+
+ for (unsigned I = 0, E = FD->getNumParams(); I != E; ++I) {
+ QualType ParamTy = FD->getParamDecl(I)->getType();
+ if (!ParamTy->isReferenceType() ||
+ ParamTy->getPointeeType().isConstQualified())
+ continue;
+
+ // In case of member operator calls, `this` is counted as an
+ // argument but not as a parameter.
+ bool isaMemberOpCall = isa<CXXMemberOperatorCall>(FC);
+ unsigned ArgI = isaMemberOpCall ? I+1 : I;
+
+ SVal Arg = FC->getArgSVal(ArgI);
+ const auto *ArgRegion =
+ dyn_cast_or_null<TypedValueRegion>(Arg.getAsRegion());
+ if (!ArgRegion)
+ continue;
+
+ markPtrSymbolsReleased(Call, State, ArgRegion, C);
+ }
+ }
+}
+
+// [string.require]
+//
+// "References, pointers, and iterators referring to the elements of a
+// basic_string sequence may be invalidated by the following uses of that
+// basic_string object:
+//
+// -- As an argument to any standard library function taking a reference
+// to non-const basic_string as an argument. For example, as an argument to
+// non-member functions swap(), operator>>(), and getline(), or as an argument
+// to basic_string::swap().
+//
+// -- Calling non-const member functions, except operator[], at, front, back,
+// begin, rbegin, end, and rend."
+
+void InnerPointerChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ if (const auto *ICall = dyn_cast<CXXInstanceCall>(&Call)) {
+ if (isCalledOnStringObject(ICall)) {
+ const auto *ObjRegion = dyn_cast_or_null<TypedValueRegion>(
+ ICall->getCXXThisVal().getAsRegion());
+
+ if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
+ SVal RawPtr = Call.getReturnValue();
+ if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
+ // Start tracking this raw pointer by adding it to the set of symbols
+ // associated with this container object in the program state map.
+
+ PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
+ const PtrSet *SetPtr = State->get<RawPtrMap>(ObjRegion);
+ PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
+ assert(C.wasInlined || !Set.contains(Sym));
+ Set = F.add(Set, Sym);
+
+ State = State->set<RawPtrMap>(ObjRegion, Set);
+ C.addTransition(State);
+ }
+ return;
+ }
+
+ // Check [string.require] / second point.
+ if (isInvalidatingMemberFunction(Call)) {
+ markPtrSymbolsReleased(Call, State, ObjRegion, C);
+ return;
+ }
+ }
+ }
+
+ // Check [string.require] / first point.
+ checkFunctionArguments(Call, State, C);
+}
+
+void InnerPointerChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
+ RawPtrMapTy RPM = State->get<RawPtrMap>();
+ for (const auto Entry : RPM) {
+ if (!SymReaper.isLiveRegion(Entry.first)) {
+ // Due to incomplete destructor support, some dead regions might
+ // remain in the program state map. Clean them up.
+ State = State->remove<RawPtrMap>(Entry.first);
+ }
+ if (const PtrSet *OldSet = State->get<RawPtrMap>(Entry.first)) {
+ PtrSet CleanedUpSet = *OldSet;
+ for (const auto Symbol : Entry.second) {
+ if (!SymReaper.isLive(Symbol))
+ CleanedUpSet = F.remove(CleanedUpSet, Symbol);
+ }
+ State = CleanedUpSet.isEmpty()
+ ? State->remove<RawPtrMap>(Entry.first)
+ : State->set<RawPtrMap>(Entry.first, CleanedUpSet);
+ }
+ }
+ C.addTransition(State);
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
+ if (!isSymbolTracked(N->getState(), PtrToBuf) ||
+ isSymbolTracked(PrevN->getState(), PtrToBuf))
+ return nullptr;
+
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S)
+ return nullptr;
+
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Dangling inner pointer obtained here";
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
+ nullptr);
+}
+
+namespace clang {
+namespace ento {
+namespace allocation_state {
+
+std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym) {
+ return llvm::make_unique<InnerPointerChecker::InnerPointerBRVisitor>(Sym);
+}
+
+} // end namespace allocation_state
+} // end namespace ento
+} // end namespace clang
+
+void ento::registerInnerPointerChecker(CheckerManager &Mgr) {
+ registerNewDeleteChecker(Mgr);
+ Mgr.registerChecker<InnerPointerChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 0f9b749506fa..520c32e1c770 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -46,19 +46,25 @@
// use setter and getters functions which separate the three cases. To store
// them we use a pointer union of symbol and memory region.
//
-// The checker works the following way: We record the past-end iterator for
-// all containers whenever their `.end()` is called. Since the Constraint
-// Manager cannot handle SVals we need to take over its role. We post-check
-// equality and non-equality comparisons and propagate the position of the
-// iterator to the other side of the comparison if it is past-end and we are in
-// the 'equal' branch (true-branch for `==` and false-branch for `!=`).
+// The checker works the following way: We record the begin and the
+// past-end iterator for all containers whenever their `.begin()` and `.end()`
+// are called. Since the Constraint Manager cannot handle such SVals we need
+// to take over its role. We post-check equality and non-equality comparisons
+// and record that the two sides are equal if we are in the 'equal' branch
+// (true-branch for `==` and false-branch for `!=`).
//
// In case of type-I or type-II iterators we get a concrete integer as a result
// of the comparison (1 or 0) but in case of type-III we only get a Symbol. In
// this latter case we record the symbol and reload it in evalAssume() and do
// the propagation there. We also handle (maybe double) negated comparisons
-// which are represented in the form of (x == 0 or x !=0 ) where x is the
+// which are represented in the form of (x == 0 or x != 0) where x is the
// comparison itself.
+//
+// Since `SimpleConstraintManager` cannot handle complex symbolic expressions
+// we only use expressions of the format S, S+n or S-n for iterator positions
+// where S is a conjured symbol and n is an unsigned concrete integer. When
+// making an assumption e.g. `S1 + n == S2 + m` we store `S1 - S2 == m - n` as
+// a constraint which we later retrieve when doing an actual comparison.
#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -80,7 +86,7 @@ private:
const MemRegion *Cont;
// Abstract offset
- SymbolRef Offset;
+ const SymbolRef Offset;
IteratorPosition(const MemRegion *C, SymbolRef Of)
: Cont(C), Offset(Of) {}
@@ -113,31 +119,39 @@ public:
typedef llvm::PointerUnion<const MemRegion *, SymbolRef> RegionOrSymbol;
-// Structure to record the symbolic end position of a container
+// Structure to record the symbolic begin and end position of a container
struct ContainerData {
private:
- SymbolRef End;
+ const SymbolRef Begin, End;
- ContainerData(SymbolRef E) : End(E) {}
+ ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {}
public:
+ static ContainerData fromBegin(SymbolRef B) {
+ return ContainerData(B, nullptr);
+ }
+
static ContainerData fromEnd(SymbolRef E) {
- return ContainerData(E);
+ return ContainerData(nullptr, E);
}
+ SymbolRef getBegin() const { return Begin; }
SymbolRef getEnd() const { return End; }
- ContainerData newEnd(SymbolRef E) const { return ContainerData(E); }
+ ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); }
+
+ ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); }
bool operator==(const ContainerData &X) const {
- return End == X.End;
+ return Begin == X.Begin && End == X.End;
}
bool operator!=(const ContainerData &X) const {
- return End != X.End;
+ return Begin != X.Begin || End != X.End;
}
void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.Add(Begin);
ID.Add(End);
}
};
@@ -167,8 +181,9 @@ public:
class IteratorChecker
: public Checker<check::PreCall, check::PostCall,
+ check::PreStmt<CXXOperatorCallExpr>,
check::PostStmt<MaterializeTemporaryExpr>,
- check::DeadSymbols,
+ check::LiveSymbols, check::DeadSymbols,
eval::Assume> {
std::unique_ptr<BugType> OutOfRangeBugType;
@@ -176,10 +191,22 @@ class IteratorChecker
void handleComparison(CheckerContext &C, const SVal &RetVal, const SVal &LVal,
const SVal &RVal, OverloadedOperatorKind Op) const;
void verifyDereference(CheckerContext &C, const SVal &Val) const;
+ void handleIncrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
+ bool Postfix) const;
+ void handleDecrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
+ bool Postfix) const;
+ void handleRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op,
+ const SVal &RetVal, const SVal &LHS,
+ const SVal &RHS) const;
+ void handleBegin(CheckerContext &C, const Expr *CE, const SVal &RetVal,
+ const SVal &Cont) const;
void handleEnd(CheckerContext &C, const Expr *CE, const SVal &RetVal,
const SVal &Cont) const;
void assignToContainer(CheckerContext &C, const Expr *CE, const SVal &RetVal,
const MemRegion *Cont) const;
+ void verifyRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op,
+ const SVal &RetVal, const SVal &LHS,
+ const SVal &RHS) const;
void reportOutOfRangeBug(const StringRef &Message, const SVal &Val,
CheckerContext &C, ExplodedNode *ErrNode) const;
@@ -196,8 +223,10 @@ public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+ void checkPreStmt(const CXXOperatorCallExpr *COCE, CheckerContext &C) const;
void checkPostStmt(const MaterializeTemporaryExpr *MTE,
CheckerContext &C) const;
+ void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond,
bool Assumption) const;
@@ -217,9 +246,13 @@ namespace {
bool isIteratorType(const QualType &Type);
bool isIterator(const CXXRecordDecl *CRD);
+bool isBeginCall(const FunctionDecl *Func);
bool isEndCall(const FunctionDecl *Func);
bool isSimpleComparisonOperator(OverloadedOperatorKind OK);
bool isDereferenceOperator(OverloadedOperatorKind OK);
+bool isIncrementOperator(OverloadedOperatorKind OK);
+bool isDecrementOperator(OverloadedOperatorKind OK);
+bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
BinaryOperator::Opcode getOpcode(const SymExpr *SE);
const RegionOrSymbol getRegionOrSymbol(const SVal &Val);
const ProgramStateRef processComparison(ProgramStateRef State,
@@ -230,7 +263,11 @@ const ProgramStateRef saveComparison(ProgramStateRef State,
const SVal &RVal, bool Eq);
const IteratorComparison *loadComparison(ProgramStateRef State,
const SymExpr *Condition);
+SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
+ProgramStateRef createContainerBegin(ProgramStateRef State,
+ const MemRegion *Cont,
+ const SymbolRef Sym);
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
const SymbolRef Sym);
const IteratorPosition *getIteratorPosition(ProgramStateRef State,
@@ -254,7 +291,9 @@ const ContainerData *getContainerData(ProgramStateRef State,
const MemRegion *Cont);
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
const ContainerData &CData);
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos);
+bool isZero(ProgramStateRef State, const NonLoc &Val);
} // namespace
IteratorChecker::IteratorChecker() {
@@ -272,6 +311,22 @@ void IteratorChecker::checkPreCall(const CallEvent &Call,
if (Func->isOverloadedOperator()) {
if (ChecksEnabled[CK_IteratorRangeChecker] &&
+ isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ // Check for out-of-range incrementions and decrementions
+ if (Call.getNumArgs() >= 1) {
+ verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
+ Call.getReturnValue(),
+ InstCall->getCXXThisVal(), Call.getArgSVal(0));
+ }
+ } else {
+ if (Call.getNumArgs() >= 2) {
+ verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
+ Call.getReturnValue(), Call.getArgSVal(0),
+ Call.getArgSVal(1));
+ }
+ }
+ } else if (ChecksEnabled[CK_IteratorRangeChecker] &&
isDereferenceOperator(Func->getOverloadedOperator())) {
// Check for dereference of out-of-range iterators
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
@@ -300,6 +355,36 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
handleComparison(C, Call.getReturnValue(), Call.getArgSVal(0),
Call.getArgSVal(1), Op);
}
+ } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ if (Call.getNumArgs() >= 1) {
+ handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
+ Call.getReturnValue(),
+ InstCall->getCXXThisVal(), Call.getArgSVal(0));
+ }
+ } else {
+ if (Call.getNumArgs() >= 2) {
+ handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
+ Call.getReturnValue(), Call.getArgSVal(0),
+ Call.getArgSVal(1));
+ }
+ }
+ } else if (isIncrementOperator(Func->getOverloadedOperator())) {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
+ Call.getNumArgs());
+ } else {
+ handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
+ Call.getNumArgs());
+ }
+ } else if (isDecrementOperator(Func->getOverloadedOperator())) {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
+ Call.getNumArgs());
+ } else {
+ handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
+ Call.getNumArgs());
+ }
}
} else {
const auto *OrigExpr = Call.getOriginExpr();
@@ -315,6 +400,11 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
return;
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ if (isBeginCall(Func)) {
+ handleBegin(C, OrigExpr, Call.getReturnValue(),
+ InstCall->getCXXThisVal());
+ return;
+ }
if (isEndCall(Func)) {
handleEnd(C, OrigExpr, Call.getReturnValue(),
InstCall->getCXXThisVal());
@@ -351,19 +441,80 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
}
}
+void IteratorChecker::checkPreStmt(const CXXOperatorCallExpr *COCE,
+ CheckerContext &C) const {
+ const auto *ThisExpr = COCE->getArg(0);
+
+ auto State = C.getState();
+ const auto *LCtx = C.getLocationContext();
+
+ const auto CurrentThis = State->getSVal(ThisExpr, LCtx);
+ if (const auto *Reg = CurrentThis.getAsRegion()) {
+ if (!Reg->getAs<CXXTempObjectRegion>())
+ return;
+ const auto OldState = C.getPredecessor()->getFirstPred()->getState();
+ const auto OldThis = OldState->getSVal(ThisExpr, LCtx);
+ // FIXME: This solution is unreliable. It may happen that another checker
+ // subscribes to the pre-statement check of `CXXOperatorCallExpr`
+ // and adds a transition before us. The proper fix is to make the
+ // CFG provide a `ConstructionContext` for the `CXXOperatorCallExpr`,
+ // which would turn the corresponding `CFGStmt` element into a
+ // `CFGCXXRecordTypedCall` element, which will allow `ExprEngine` to
+ // foresee that the `begin()`/`end()` call constructs the object
+ // directly in the temporary region that `CXXOperatorCallExpr` takes
+ // as its implicit object argument.
+ const auto *Pos = getIteratorPosition(OldState, OldThis);
+ if (!Pos)
+ return;
+ State = setIteratorPosition(State, CurrentThis, *Pos);
+ C.addTransition(State);
+ }
+}
+
void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE,
CheckerContext &C) const {
/* Transfer iterator state to temporary objects */
auto State = C.getState();
- const auto *LCtx = C.getLocationContext();
const auto *Pos =
- getIteratorPosition(State, State->getSVal(MTE->GetTemporaryExpr(), LCtx));
+ getIteratorPosition(State, C.getSVal(MTE->GetTemporaryExpr()));
if (!Pos)
return;
- State = setIteratorPosition(State, State->getSVal(MTE, LCtx), *Pos);
+ State = setIteratorPosition(State, C.getSVal(MTE), *Pos);
C.addTransition(State);
}
+void IteratorChecker::checkLiveSymbols(ProgramStateRef State,
+ SymbolReaper &SR) const {
+ // Keep symbolic expressions of iterator positions, container begins and ends
+ // alive
+ auto RegionMap = State->get<IteratorRegionMap>();
+ for (const auto Reg : RegionMap) {
+ const auto Offset = Reg.second.getOffset();
+ for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
+ if (isa<SymbolData>(*i))
+ SR.markLive(*i);
+ }
+
+ auto SymbolMap = State->get<IteratorSymbolMap>();
+ for (const auto Sym : SymbolMap) {
+ const auto Offset = Sym.second.getOffset();
+ for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
+ if (isa<SymbolData>(*i))
+ SR.markLive(*i);
+ }
+
+ auto ContMap = State->get<ContainerMap>();
+ for (const auto Cont : ContMap) {
+ const auto CData = Cont.second;
+ if (CData.getBegin()) {
+ SR.markLive(CData.getBegin());
+ }
+ if (CData.getEnd()) {
+ SR.markLive(CData.getEnd());
+ }
+ }
+}
+
void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const {
// Cleanup
@@ -386,7 +537,11 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
auto ContMap = State->get<ContainerMap>();
for (const auto Cont : ContMap) {
if (!SR.isLiveRegion(Cont.first)) {
- State = State->remove<ContainerMap>(Cont.first);
+ // We must keep the container data while it has live iterators to be able
+ // to compare them to the begin and the end of the container.
+ if (!hasLiveIterators(State, Cont.first)) {
+ State = State->remove<ContainerMap>(Cont.first);
+ }
}
}
@@ -396,6 +551,8 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
State = State->remove<IteratorComparisonMap>(Comp.first);
}
}
+
+ C.addTransition(State);
}
ProgramStateRef IteratorChecker::evalAssume(ProgramStateRef State, SVal Cond,
@@ -471,13 +628,209 @@ void IteratorChecker::verifyDereference(CheckerContext &C,
static CheckerProgramPointTag Tag("IteratorRangeChecker",
"IteratorOutOfRange");
auto *N = C.generateNonFatalErrorNode(State, &Tag);
- if (!N) {
+ if (!N)
return;
- }
reportOutOfRangeBug("Iterator accessed outside of its range.", Val, C, N);
}
}
+void IteratorChecker::handleIncrement(CheckerContext &C, const SVal &RetVal,
+ const SVal &Iter, bool Postfix) const {
+ // Increment the symbolic expressions which represents the position of the
+ // iterator
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Iter);
+ if (Pos) {
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto OldOffset = Pos->getOffset();
+ auto NewOffset =
+ SVB.evalBinOp(State, BO_Add,
+ nonloc::SymbolVal(OldOffset),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(OldOffset)).getAsSymbol();
+ auto NewPos = Pos->setTo(NewOffset);
+ State = setIteratorPosition(State, Iter, NewPos);
+ State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos);
+ C.addTransition(State);
+ }
+}
+
+void IteratorChecker::handleDecrement(CheckerContext &C, const SVal &RetVal,
+ const SVal &Iter, bool Postfix) const {
+ // Decrement the symbolic expressions which represents the position of the
+ // iterator
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Iter);
+ if (Pos) {
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto OldOffset = Pos->getOffset();
+ auto NewOffset =
+ SVB.evalBinOp(State, BO_Sub,
+ nonloc::SymbolVal(OldOffset),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(OldOffset)).getAsSymbol();
+ auto NewPos = Pos->setTo(NewOffset);
+ State = setIteratorPosition(State, Iter, NewPos);
+ State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos);
+ C.addTransition(State);
+ }
+}
+
+// This function tells the analyzer's engine that symbols produced by our
+// checker, most notably iterator positions, are relatively small.
+// A distance between items in the container should not be very large.
+// By assuming that it is within around 1/8 of the address space,
+// we can help the analyzer perform operations on these symbols
+// without being afraid of integer overflows.
+// FIXME: Should we provide it as an API, so that all checkers could use it?
+static ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym,
+ long Scale) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ BasicValueFactory &BV = SVB.getBasicValueFactory();
+
+ QualType T = Sym->getType();
+ assert(T->isSignedIntegerOrEnumerationType());
+ APSIntType AT = BV.getAPSIntType(T);
+
+ ProgramStateRef NewState = State;
+
+ llvm::APSInt Max = AT.getMaxValue() / AT.getValue(Scale);
+ SVal IsCappedFromAbove =
+ SVB.evalBinOpNN(State, BO_LE, nonloc::SymbolVal(Sym),
+ nonloc::ConcreteInt(Max), SVB.getConditionType());
+ if (auto DV = IsCappedFromAbove.getAs<DefinedSVal>()) {
+ NewState = NewState->assume(*DV, true);
+ if (!NewState)
+ return State;
+ }
+
+ llvm::APSInt Min = -Max;
+ SVal IsCappedFromBelow =
+ SVB.evalBinOpNN(State, BO_GE, nonloc::SymbolVal(Sym),
+ nonloc::ConcreteInt(Min), SVB.getConditionType());
+ if (auto DV = IsCappedFromBelow.getAs<DefinedSVal>()) {
+ NewState = NewState->assume(*DV, true);
+ if (!NewState)
+ return State;
+ }
+
+ return NewState;
+}
+
+void IteratorChecker::handleRandomIncrOrDecr(CheckerContext &C,
+ OverloadedOperatorKind Op,
+ const SVal &RetVal,
+ const SVal &LHS,
+ const SVal &RHS) const {
+ // Increment or decrement the symbolic expressions which represents the
+ // position of the iterator
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, LHS);
+ if (!Pos)
+ return;
+
+ const auto *value = &RHS;
+ if (auto loc = RHS.getAs<Loc>()) {
+ const auto val = State->getRawSVal(*loc);
+ value = &val;
+ }
+
+ auto &SymMgr = C.getSymbolManager();
+ auto &SVB = C.getSValBuilder();
+ auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
+ const auto OldOffset = Pos->getOffset();
+ SymbolRef NewOffset;
+ if (const auto intValue = value->getAs<nonloc::ConcreteInt>()) {
+ // For concrete integers we can calculate the new position
+ NewOffset = SVB.evalBinOp(State, BinOp, nonloc::SymbolVal(OldOffset),
+ *intValue,
+ SymMgr.getType(OldOffset)).getAsSymbol();
+ } else {
+ // For other symbols create a new symbol to keep expressions simple
+ const auto &LCtx = C.getLocationContext();
+ NewOffset = SymMgr.conjureSymbol(nullptr, LCtx, SymMgr.getType(OldOffset),
+ C.blockCount());
+ State = assumeNoOverflow(State, NewOffset, 4);
+ }
+ auto NewPos = Pos->setTo(NewOffset);
+ auto &TgtVal = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal;
+ State = setIteratorPosition(State, TgtVal, NewPos);
+ C.addTransition(State);
+}
+
+void IteratorChecker::verifyRandomIncrOrDecr(CheckerContext &C,
+ OverloadedOperatorKind Op,
+ const SVal &RetVal,
+ const SVal &LHS,
+ const SVal &RHS) const {
+ auto State = C.getState();
+
+ // If the iterator is initially inside its range, then the operation is valid
+ const auto *Pos = getIteratorPosition(State, LHS);
+ if (!Pos || !isOutOfRange(State, *Pos))
+ return;
+
+ auto value = RHS;
+ if (auto loc = RHS.getAs<Loc>()) {
+ value = State->getRawSVal(*loc);
+ }
+
+ // Incremention or decremention by 0 is never bug
+ if (isZero(State, value.castAs<NonLoc>()))
+ return;
+
+ auto &SymMgr = C.getSymbolManager();
+ auto &SVB = C.getSValBuilder();
+ auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
+ const auto OldOffset = Pos->getOffset();
+ const auto intValue = value.getAs<nonloc::ConcreteInt>();
+ if (!intValue)
+ return;
+
+ auto NewOffset = SVB.evalBinOp(State, BinOp, nonloc::SymbolVal(OldOffset),
+ *intValue,
+ SymMgr.getType(OldOffset)).getAsSymbol();
+ auto NewPos = Pos->setTo(NewOffset);
+
+ // If out of range, the only valid operation is to step into the range
+ if (isOutOfRange(State, NewPos)) {
+ auto *N = C.generateNonFatalErrorNode(State);
+ if (!N)
+ return;
+ reportOutOfRangeBug("Iterator accessed past its end.", LHS, C, N);
+ }
+}
+
+void IteratorChecker::handleBegin(CheckerContext &C, const Expr *CE,
+ const SVal &RetVal, const SVal &Cont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ while (const auto *CBOR = ContReg->getAs<CXXBaseObjectRegion>()) {
+ ContReg = CBOR->getSuperRegion();
+ }
+
+ // If the container already has a begin symbol then use it. Otherwise first
+ // create a new one.
+ auto State = C.getState();
+ auto BeginSym = getContainerBegin(State, ContReg);
+ if (!BeginSym) {
+ auto &SymMgr = C.getSymbolManager();
+ BeginSym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
+ C.getASTContext().LongTy, C.blockCount());
+ State = assumeNoOverflow(State, BeginSym, 4);
+ State = createContainerBegin(State, ContReg, BeginSym);
+ }
+ State = setIteratorPosition(State, RetVal,
+ IteratorPosition::getPosition(ContReg, BeginSym));
+ C.addTransition(State);
+}
+
void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE,
const SVal &RetVal, const SVal &Cont) const {
const auto *ContReg = Cont.getAsRegion();
@@ -496,6 +849,7 @@ void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE,
auto &SymMgr = C.getSymbolManager();
EndSym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
C.getASTContext().LongTy, C.blockCount());
+ State = assumeNoOverflow(State, EndSym, 4);
State = createContainerEnd(State, ContReg, EndSym);
}
State = setIteratorPosition(State, RetVal,
@@ -514,6 +868,7 @@ void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE,
auto &SymMgr = C.getSymbolManager();
auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
C.getASTContext().LongTy, C.blockCount());
+ State = assumeNoOverflow(State, Sym, 4);
State = setIteratorPosition(State, RetVal,
IteratorPosition::getPosition(Cont, Sym));
C.addTransition(State);
@@ -529,9 +884,12 @@ void IteratorChecker::reportOutOfRangeBug(const StringRef &Message,
namespace {
+bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
BinaryOperator::Opcode Opc);
+bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
+ BinaryOperator::Opcode Opc);
bool isIteratorType(const QualType &Type) {
if (Type->isPointerType())
@@ -585,6 +943,13 @@ bool isIterator(const CXXRecordDecl *CRD) {
HasPostIncrOp && HasDerefOp;
}
+bool isBeginCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ return IdInfo->getName().endswith_lower("begin");
+}
+
bool isEndCall(const FunctionDecl *Func) {
const auto *IdInfo = Func->getIdentifier();
if (!IdInfo)
@@ -601,11 +966,24 @@ bool isDereferenceOperator(OverloadedOperatorKind OK) {
OK == OO_Subscript;
}
+bool isIncrementOperator(OverloadedOperatorKind OK) {
+ return OK == OO_PlusPlus;
+}
+
+bool isDecrementOperator(OverloadedOperatorKind OK) {
+ return OK == OO_MinusMinus;
+}
+
+bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK) {
+ return OK == OO_Plus || OK == OO_PlusEqual || OK == OO_Minus ||
+ OK == OO_MinusEqual;
+}
+
BinaryOperator::Opcode getOpcode(const SymExpr *SE) {
if (const auto *BSE = dyn_cast<BinarySymExpr>(SE)) {
return BSE->getOpcode();
} else if (const auto *SC = dyn_cast<SymbolConjured>(SE)) {
- const auto *COE = dyn_cast<CXXOperatorCallExpr>(SC->getStmt());
+ const auto *COE = dyn_cast_or_null<CXXOperatorCallExpr>(SC->getStmt());
if (!COE)
return BO_Comma; // Extremal value, neither EQ nor NE
if (COE->getOperator() == OO_EqualEqual) {
@@ -660,6 +1038,14 @@ const IteratorComparison *loadComparison(ProgramStateRef State,
return State->get<IteratorComparisonMap>(Condition);
}
+SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont) {
+ const auto *CDataPtr = getContainerData(State, Cont);
+ if (!CDataPtr)
+ return nullptr;
+
+ return CDataPtr->getBegin();
+}
+
SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
const auto *CDataPtr = getContainerData(State, Cont);
if (!CDataPtr)
@@ -668,6 +1054,22 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
return CDataPtr->getEnd();
}
+ProgramStateRef createContainerBegin(ProgramStateRef State,
+ const MemRegion *Cont,
+ const SymbolRef Sym) {
+ // Only create if it does not exist
+ const auto *CDataPtr = getContainerData(State, Cont);
+ if (CDataPtr) {
+ if (CDataPtr->getBegin()) {
+ return State;
+ }
+ const auto CData = CDataPtr->newBegin(Sym);
+ return setContainerData(State, Cont, CData);
+ }
+ const auto CData = ContainerData::fromBegin(Sym);
+ return setContainerData(State, Cont, CData);
+}
+
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
const SymbolRef Sym) {
// Only create if it does not exist
@@ -675,14 +1077,12 @@ ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
if (CDataPtr) {
if (CDataPtr->getEnd()) {
return State;
- } else {
- const auto CData = CDataPtr->newEnd(Sym);
- return setContainerData(State, Cont, CData);
}
- } else {
- const auto CData = ContainerData::fromEnd(Sym);
+ const auto CData = CDataPtr->newEnd(Sym);
return setContainerData(State, Cont, CData);
}
+ const auto CData = ContainerData::fromEnd(Sym);
+ return setContainerData(State, Cont, CData);
}
const ContainerData *getContainerData(ProgramStateRef State,
@@ -767,17 +1167,55 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State,
const IteratorPosition &Pos1,
const IteratorPosition &Pos2,
bool Equal) {
- // Try to compare them and get a defined value
auto &SVB = State->getStateManager().getSValBuilder();
+
+ // FIXME: This code should be reworked as follows:
+ // 1. Subtract the operands using evalBinOp().
+ // 2. Assume that the result doesn't overflow.
+ // 3. Compare the result to 0.
+ // 4. Assume the result of the comparison.
const auto comparison =
SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Pos1.getOffset()),
- nonloc::SymbolVal(Pos2.getOffset()), SVB.getConditionType())
- .getAs<DefinedSVal>();
- if (comparison) {
- return State->assume(*comparison, Equal);
+ nonloc::SymbolVal(Pos2.getOffset()),
+ SVB.getConditionType());
+
+ assert(comparison.getAs<DefinedSVal>() &&
+ "Symbol comparison must be a `DefinedSVal`");
+
+ auto NewState = State->assume(comparison.castAs<DefinedSVal>(), Equal);
+ if (const auto CompSym = comparison.getAsSymbol()) {
+ assert(isa<SymIntExpr>(CompSym) &&
+ "Symbol comparison must be a `SymIntExpr`");
+ assert(BinaryOperator::isComparisonOp(
+ cast<SymIntExpr>(CompSym)->getOpcode()) &&
+ "Symbol comparison must be a comparison");
+ return assumeNoOverflow(NewState, cast<SymIntExpr>(CompSym)->getLHS(), 2);
}
- return State;
+ return NewState;
+}
+
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {
+ auto RegionMap = State->get<IteratorRegionMap>();
+ for (const auto Reg : RegionMap) {
+ if (Reg.second.getContainer() == Cont)
+ return true;
+ }
+
+ auto SymbolMap = State->get<IteratorSymbolMap>();
+ for (const auto Sym : SymbolMap) {
+ if (Sym.second.getContainer() == Cont)
+ return true;
+ }
+
+ return false;
+}
+
+bool isZero(ProgramStateRef State, const NonLoc &Val) {
+ auto &BVF = State->getBasicVals();
+ return compare(State, Val,
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))),
+ BO_EQ);
}
bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
@@ -789,6 +1227,13 @@ bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
// Out of range means less than the begin symbol or greater or equal to the
// end symbol.
+ const auto Beg = CData->getBegin();
+ if (Beg) {
+ if (isLess(State, Pos.getOffset(), Beg)) {
+ return true;
+ }
+ }
+
const auto End = CData->getEnd();
if (End) {
if (isGreaterOrEqual(State, Pos.getOffset(), End)) {
@@ -799,25 +1244,30 @@ bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
return false;
}
+bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
+ return compare(State, Sym1, Sym2, BO_LT);
+}
+
bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
return compare(State, Sym1, Sym2, BO_GE);
}
bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
BinaryOperator::Opcode Opc) {
- auto &SMgr = State->getStateManager();
- auto &SVB = SMgr.getSValBuilder();
+ return compare(State, nonloc::SymbolVal(Sym1), nonloc::SymbolVal(Sym2), Opc);
+}
+
+bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
+ BinaryOperator::Opcode Opc) {
+ auto &SVB = State->getStateManager().getSValBuilder();
const auto comparison =
- SVB.evalBinOp(State, Opc, nonloc::SymbolVal(Sym1),
- nonloc::SymbolVal(Sym2), SVB.getConditionType())
- .getAs<DefinedSVal>();
+ SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
- if(comparison) {
- return !!State->assume(*comparison, true);
- }
+ assert(comparison.getAs<DefinedSVal>() &&
+ "Symbol comparison must be a `DefinedSVal`");
- return false;
+ return !State->assume(comparison.castAs<DefinedSVal>(), false);
}
} // namespace
@@ -831,3 +1281,4 @@ bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
}
REGISTER_CHECKER(IteratorRangeChecker)
+
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
index 8076ca09591f..2fb627184eb9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
@@ -20,7 +20,7 @@
// been called on them. An invalidation method should either invalidate all
// the ivars or call another invalidation method (on self).
//
-// Partial invalidor annotation allows to addess cases when ivars are
+// Partial invalidor annotation allows to address cases when ivars are
// invalidated by other methods, which might or might not be called from
// the invalidation method. The checker checks that each invalidation
// method and all the partial methods cumulatively invalidate all ivars.
@@ -402,13 +402,13 @@ visit(const ObjCImplementationDecl *ImplD) const {
// Find the setter and the getter.
const ObjCMethodDecl *SetterD = PD->getSetterMethodDecl();
if (SetterD) {
- SetterD = cast<ObjCMethodDecl>(SetterD->getCanonicalDecl());
+ SetterD = SetterD->getCanonicalDecl();
PropSetterToIvarMap[SetterD] = ID;
}
const ObjCMethodDecl *GetterD = PD->getGetterMethodDecl();
if (GetterD) {
- GetterD = cast<ObjCMethodDecl>(GetterD->getCanonicalDecl());
+ GetterD = GetterD->getCanonicalDecl();
PropGetterToIvarMap[GetterD] = ID;
}
}
@@ -606,7 +606,7 @@ void IvarInvalidationCheckerImpl::MethodCrawler::checkObjCMessageExpr(
const ObjCMessageExpr *ME) {
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD) {
- MD = cast<ObjCMethodDecl>(MD->getCanonicalDecl());
+ MD = MD->getCanonicalDecl();
MethToIvarMapTy::const_iterator IvI = PropertyGetterToIvarMap.find(MD);
if (IvI != PropertyGetterToIvarMap.end())
markInvalidated(IvI->second);
@@ -630,7 +630,7 @@ void IvarInvalidationCheckerImpl::MethodCrawler::checkObjCPropertyRefExpr(
if (PA->isImplicitProperty()) {
const ObjCMethodDecl *MD = PA->getImplicitPropertySetter();
if (MD) {
- MD = cast<ObjCMethodDecl>(MD->getCanonicalDecl());
+ MD = MD->getCanonicalDecl();
MethToIvarMapTy::const_iterator IvI =PropertyGetterToIvarMap.find(MD);
if (IvI != PropertyGetterToIvarMap.end())
markInvalidated(IvI->second);
@@ -702,7 +702,7 @@ void IvarInvalidationCheckerImpl::MethodCrawler::VisitObjCMessageExpr(
// Check if we call a setter and set the property to 'nil'.
if (MD && (ME->getNumArgs() == 1) && isZero(ME->getArg(0))) {
- MD = cast<ObjCMethodDecl>(MD->getCanonicalDecl());
+ MD = MD->getCanonicalDecl();
MethToIvarMapTy::const_iterator IvI = PropertySetterToIvarMap.find(MD);
if (IvI != PropertySetterToIvarMap.end()) {
markInvalidated(IvI->second);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index 655ce33390c9..849b1193c042 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -113,8 +113,7 @@ NonLocalizedStringChecker::NonLocalizedStringChecker() {
}
namespace {
-class NonLocalizedStringBRVisitor final
- : public BugReporterVisitorImpl<NonLocalizedStringBRVisitor> {
+class NonLocalizedStringBRVisitor final : public BugReporterVisitor {
const MemRegion *NonLocalizedString;
bool Satisfied;
@@ -1017,8 +1016,7 @@ NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ,
if (!LiteralExpr)
return nullptr;
- ProgramStateRef State = Succ->getState();
- SVal LiteralSVal = State->getSVal(LiteralExpr, Succ->getLocationContext());
+ SVal LiteralSVal = Succ->getSVal(LiteralExpr);
if (LiteralSVal.getAsRegion() != NonLocalizedString)
return nullptr;
@@ -1108,7 +1106,7 @@ void EmptyLocalizationContextChecker::checkASTDecl(
void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
const ObjCMessageExpr *ME) {
- // FIXME: We may be able to use PPCallbacks to check for empy context
+ // FIXME: We may be able to use PPCallbacks to check for empty context
// comments as part of preprocessing and avoid this re-lexing hack.
const ObjCInterfaceDecl *OD = ME->getReceiverInterface();
if (!OD)
@@ -1389,7 +1387,7 @@ void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError(
// Generate the bug report.
BR.EmitBasicReport(AC->getDecl(), Checker, "Plural Misuse",
"Localizability Issue (Apple)",
- "Plural cases are not supported accross all languages. "
+ "Plural cases are not supported across all languages. "
"Use a .stringsdict file instead",
PathDiagnosticLocation(S, BR.getSourceManager(), AC));
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
index 0ee91cca4793..40eb0631d7c5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
@@ -78,7 +78,7 @@ private:
/// Bug visitor class to find the node where the request region was previously
/// used in order to include it into the BugReport path.
- class RequestNodeVisitor : public BugReporterVisitorImpl<RequestNodeVisitor> {
+ class RequestNodeVisitor : public BugReporterVisitor {
public:
RequestNodeVisitor(const MemRegion *const MemoryRegion,
const std::string &ErrText)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index f8473dbd7647..b8ef6701c0df 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -120,8 +120,7 @@ private:
/// The bug visitor which allows us to print extra diagnostics along the
/// BugReport path. For example, showing the allocation site of the leaked
/// region.
- class SecKeychainBugVisitor
- : public BugReporterVisitorImpl<SecKeychainBugVisitor> {
+ class SecKeychainBugVisitor : public BugReporterVisitor {
protected:
// The allocated region symbol tracked by the main analysis.
SymbolRef Sym;
@@ -202,7 +201,7 @@ static bool isBadDeallocationArgument(const MemRegion *Arg) {
static SymbolRef getAsPointeeSymbol(const Expr *Expr,
CheckerContext &C) {
ProgramStateRef State = C.getState();
- SVal ArgV = State->getSVal(Expr, C.getLocationContext());
+ SVal ArgV = C.getSVal(Expr);
if (Optional<loc::MemRegionVal> X = ArgV.getAs<loc::MemRegionVal>()) {
StoreManager& SM = C.getStoreManager();
@@ -297,7 +296,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
// Check the argument to the deallocator.
const Expr *ArgExpr = CE->getArg(paramIdx);
- SVal ArgSVal = State->getSVal(ArgExpr, C.getLocationContext());
+ SVal ArgSVal = C.getSVal(ArgExpr);
// Undef is reported by another checker.
if (ArgSVal.isUndef())
@@ -426,8 +425,7 @@ void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
// allocated value symbol, since our diagnostics depend on the value
// returned by the call. Ex: Data should only be freed if noErr was
// returned during allocation.)
- SymbolRef RetStatusSymbol =
- State->getSVal(CE, C.getLocationContext()).getAsSymbol();
+ SymbolRef RetStatusSymbol = C.getSVal(CE).getAsSymbol();
C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);
// Track the allocated value in the checker state.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 904c9ffa37df..ebaf79a780c0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -30,6 +30,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "AllocationState.h"
#include <climits>
#include <utility>
@@ -45,7 +46,8 @@ enum AllocationFamily {
AF_CXXNew,
AF_CXXNewArray,
AF_IfNameIndex,
- AF_Alloca
+ AF_Alloca,
+ AF_InnerBuffer
};
class RefState {
@@ -134,10 +136,10 @@ enum ReallocPairKind {
};
/// \class ReallocPair
-/// \brief Stores information about the symbol being reallocated by a call to
+/// Stores information about the symbol being reallocated by a call to
/// 'realloc' to allow modeling failed reallocation later in the path.
struct ReallocPair {
- // \brief The symbol which realloc reallocated.
+ // The symbol which realloc reallocated.
SymbolRef ReallocatedSym;
ReallocPairKind Kind;
@@ -162,6 +164,7 @@ class MallocChecker : public Checker<check::DeadSymbols,
check::PreCall,
check::PostStmt<CallExpr>,
check::PostStmt<CXXNewExpr>,
+ check::NewAllocator,
check::PreStmt<CXXDeleteExpr>,
check::PostStmt<BlockExpr>,
check::PostObjCMessage,
@@ -176,11 +179,11 @@ public:
II_strdup(nullptr), II_win_strdup(nullptr), II_kmalloc(nullptr),
II_if_nameindex(nullptr), II_if_freenameindex(nullptr),
II_wcsdup(nullptr), II_win_wcsdup(nullptr), II_g_malloc(nullptr),
- II_g_malloc0(nullptr), II_g_realloc(nullptr), II_g_try_malloc(nullptr),
- II_g_try_malloc0(nullptr), II_g_try_realloc(nullptr),
- II_g_free(nullptr), II_g_memdup(nullptr), II_g_malloc_n(nullptr),
- II_g_malloc0_n(nullptr), II_g_realloc_n(nullptr),
- II_g_try_malloc_n(nullptr), II_g_try_malloc0_n(nullptr),
+ II_g_malloc0(nullptr), II_g_realloc(nullptr), II_g_try_malloc(nullptr),
+ II_g_try_malloc0(nullptr), II_g_try_realloc(nullptr),
+ II_g_free(nullptr), II_g_memdup(nullptr), II_g_malloc_n(nullptr),
+ II_g_malloc0_n(nullptr), II_g_realloc_n(nullptr),
+ II_g_try_malloc_n(nullptr), II_g_try_malloc0_n(nullptr),
II_g_try_realloc_n(nullptr) {}
/// In pessimistic mode, the checker assumes that it does not know which
@@ -207,6 +210,8 @@ public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const;
+ void checkNewAllocator(const CXXNewExpr *NE, SVal Target,
+ CheckerContext &C) const;
void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const;
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
@@ -243,30 +248,30 @@ private:
*II_realloc, *II_calloc, *II_valloc, *II_reallocf,
*II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
*II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
- *II_win_wcsdup, *II_g_malloc, *II_g_malloc0,
- *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0,
- *II_g_try_realloc, *II_g_free, *II_g_memdup,
- *II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n,
- *II_g_try_malloc_n, *II_g_try_malloc0_n,
+ *II_win_wcsdup, *II_g_malloc, *II_g_malloc0,
+ *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0,
+ *II_g_try_realloc, *II_g_free, *II_g_memdup,
+ *II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n,
+ *II_g_try_malloc_n, *II_g_try_malloc0_n,
*II_g_try_realloc_n;
mutable Optional<uint64_t> KernelZeroFlagVal;
void initIdentifierInfo(ASTContext &C) const;
- /// \brief Determine family of a deallocation expression.
+ /// Determine family of a deallocation expression.
AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const;
- /// \brief Print names of allocators and deallocators.
+ /// Print names of allocators and deallocators.
///
/// \returns true on success.
bool printAllocDeallocName(raw_ostream &os, CheckerContext &C,
const Expr *E) const;
- /// \brief Print expected name of an allocator based on the deallocator's
+ /// Print expected name of an allocator based on the deallocator's
/// family derived from the DeallocExpr.
void printExpectedAllocName(raw_ostream &os, CheckerContext &C,
const Expr *DeallocExpr) const;
- /// \brief Print expected name of a deallocator based on the allocator's
+ /// Print expected name of a deallocator based on the allocator's
/// family.
void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) const;
@@ -281,10 +286,18 @@ private:
bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const;
///@}
- /// \brief Perform a zero-allocation check.
+ /// Process C++ operator new()'s allocation, which is the part of C++
+ /// new-expression that goes before the constructor.
+ void processNewAllocation(const CXXNewExpr *NE, CheckerContext &C,
+ SVal Target) const;
+
+ /// Perform a zero-allocation check.
+ /// The optional \p RetVal parameter specifies the newly allocated pointer
+ /// value; if unspecified, the value of expression \p E is used.
ProgramStateRef ProcessZeroAllocation(CheckerContext &C, const Expr *E,
const unsigned AllocationSizeArg,
- ProgramStateRef State) const;
+ ProgramStateRef State,
+ Optional<SVal> RetVal = None) const;
ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
const CallExpr *CE,
@@ -300,7 +313,7 @@ private:
AllocationFamily Family = AF_Malloc);
static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE,
- ProgramStateRef State);
+ ProgramStateRef State, SVal Target);
// Check if this malloc() for special flags. At present that means M_ZERO or
// __GFP_ZERO (in which case, treat it like calloc).
@@ -309,9 +322,12 @@ private:
const ProgramStateRef &State) const;
/// Update the RefState to reflect the new memory allocation.
+ /// The optional \p RetVal parameter specifies the newly allocated pointer
+ /// value; if unspecified, the value of expression \p E is used.
static ProgramStateRef
MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State,
- AllocationFamily Family = AF_Malloc);
+ AllocationFamily Family = AF_Malloc,
+ Optional<SVal> RetVal = None);
ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att,
@@ -330,14 +346,14 @@ private:
ProgramStateRef ReallocMemAux(CheckerContext &C, const CallExpr *CE,
bool FreesMemOnFailure,
- ProgramStateRef State,
+ ProgramStateRef State,
bool SuffixWithN = false) const;
static SVal evalMulForBufferSize(CheckerContext &C, const Expr *Blocks,
const Expr *BlockBytes);
static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
ProgramStateRef State);
- ///\brief Check if the memory associated with this symbol was released.
+ ///Check if the memory associated with this symbol was released.
bool isReleased(SymbolRef Sym, CheckerContext &C) const;
bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
@@ -415,8 +431,7 @@ private:
/// The bug visitor which allows us to print extra diagnostics along the
/// BugReport path. For example, showing the allocation site of the leaked
/// region.
- class MallocBugVisitor final
- : public BugReporterVisitorImpl<MallocBugVisitor> {
+ class MallocBugVisitor final : public BugReporterVisitor {
protected:
enum NotificationMode {
Normal,
@@ -432,15 +447,24 @@ private:
// A symbol from when the primary region should have been reallocated.
SymbolRef FailedReallocSymbol;
+ // A C++ destructor stack frame in which memory was released. Used for
+ // miscellaneous false positive suppression.
+ const StackFrameContext *ReleaseDestructorLC;
+
bool IsLeak;
public:
MallocBugVisitor(SymbolRef S, bool isLeak = false)
- : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
+ : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr),
+ ReleaseDestructorLC(nullptr), IsLeak(isLeak) {}
+
+ static void *getTag() {
+ static int Tag = 0;
+ return &Tag;
+ }
void Profile(llvm::FoldingSetNodeID &ID) const override {
- static int X = 0;
- ID.AddPointer(&X);
+ ID.AddPointer(getTag());
ID.AddPointer(Sym);
}
@@ -456,8 +480,13 @@ private:
inline bool isReleased(const RefState *S, const RefState *SPrev,
const Stmt *Stmt) {
// Did not track -> released. Other state (allocated) -> released.
- return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt)) &&
- (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
+ // The statement associated with the release might be missing.
+ bool IsReleased = (S && S->isReleased()) &&
+ (!SPrev || !SPrev->isReleased());
+ assert(!IsReleased ||
+ (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt))) ||
+ (!Stmt && S->getAllocationFamily() == AF_InnerBuffer));
+ return IsReleased;
}
inline bool isRelinquished(const RefState *S, const RefState *SPrev,
@@ -486,7 +515,7 @@ private:
BugReporterContext &BRC,
BugReport &BR) override;
- std::unique_ptr<PathDiagnosticPiece>
+ std::shared_ptr<PathDiagnosticPiece>
getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
BugReport &BR) override {
if (!IsLeak)
@@ -496,7 +525,7 @@ private:
PathDiagnosticLocation::createEndOfPath(EndPathNode,
BRC.getSourceManager());
// Do not add the statement itself as a range in case of leak.
- return llvm::make_unique<PathDiagnosticEventPiece>(L, BR.getDescription(),
+ return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(),
false);
}
@@ -623,7 +652,7 @@ bool MallocChecker::isCMemFunction(const FunctionDecl *FD,
initIdentifierInfo(C);
if (Family == AF_Malloc && CheckFree) {
- if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf ||
+ if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf ||
FunI == II_g_free)
return true;
}
@@ -633,12 +662,12 @@ bool MallocChecker::isCMemFunction(const FunctionDecl *FD,
FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
FunI == II_win_wcsdup || FunI == II_kmalloc ||
- FunI == II_g_malloc || FunI == II_g_malloc0 ||
- FunI == II_g_realloc || FunI == II_g_try_malloc ||
+ FunI == II_g_malloc || FunI == II_g_malloc0 ||
+ FunI == II_g_realloc || FunI == II_g_try_malloc ||
FunI == II_g_try_malloc0 || FunI == II_g_try_realloc ||
- FunI == II_g_memdup || FunI == II_g_malloc_n ||
- FunI == II_g_malloc0_n || FunI == II_g_realloc_n ||
- FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n ||
+ FunI == II_g_memdup || FunI == II_g_malloc_n ||
+ FunI == II_g_malloc0_n || FunI == II_g_realloc_n ||
+ FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n ||
FunI == II_g_try_realloc_n)
return true;
}
@@ -758,7 +787,7 @@ llvm::Optional<ProgramStateRef> MallocChecker::performKernelMalloc(
return None;
const Expr *FlagsEx = CE->getArg(CE->getNumArgs() - 1);
- const SVal V = State->getSVal(FlagsEx, C.getLocationContext());
+ const SVal V = C.getSVal(FlagsEx);
if (!V.getAs<NonLoc>()) {
// The case where 'V' can be a location can only be due to a bad header,
// so in this case bail out.
@@ -844,7 +873,7 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
return;
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
State = ProcessZeroAllocation(C, CE, 0, State);
- } else if (FunI == II_realloc || FunI == II_g_realloc ||
+ } else if (FunI == II_realloc || FunI == II_g_realloc ||
FunI == II_g_try_realloc) {
State = ReallocMemAux(C, CE, false, State);
State = ProcessZeroAllocation(C, CE, 1, State);
@@ -907,7 +936,7 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
return;
State = MallocMemAux(C, CE, CE->getArg(1), UndefinedVal(), State);
State = ProcessZeroAllocation(C, CE, 1, State);
- } else if (FunI == II_g_malloc_n || FunI == II_g_try_malloc_n ||
+ } else if (FunI == II_g_malloc_n || FunI == II_g_try_malloc_n ||
FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
if (CE->getNumArgs() < 2)
return;
@@ -949,13 +978,15 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
}
// Performs a 0-sized allocations check.
-ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
- const Expr *E,
- const unsigned AllocationSizeArg,
- ProgramStateRef State) const {
+ProgramStateRef MallocChecker::ProcessZeroAllocation(
+ CheckerContext &C, const Expr *E, const unsigned AllocationSizeArg,
+ ProgramStateRef State, Optional<SVal> RetVal) const {
if (!State)
return nullptr;
+ if (!RetVal)
+ RetVal = C.getSVal(E);
+
const Expr *Arg = nullptr;
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
@@ -972,8 +1003,7 @@ ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
assert(Arg);
- Optional<DefinedSVal> DefArgVal =
- State->getSVal(Arg, C.getLocationContext()).getAs<DefinedSVal>();
+ Optional<DefinedSVal> DefArgVal = C.getSVal(Arg).getAs<DefinedSVal>();
if (!DefArgVal)
return State;
@@ -988,8 +1018,7 @@ ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
if (TrueState && !FalseState) {
- SVal retVal = State->getSVal(E, C.getLocationContext());
- SymbolRef Sym = retVal.getAsLocSymbol();
+ SymbolRef Sym = RetVal->getAsLocSymbol();
if (!Sym)
return State;
@@ -1050,9 +1079,9 @@ static bool treatUnusedNewEscaped(const CXXNewExpr *NE) {
return false;
}
-void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
- CheckerContext &C) const {
-
+void MallocChecker::processNewAllocation(const CXXNewExpr *NE,
+ CheckerContext &C,
+ SVal Target) const {
if (NE->getNumPlacementArgs())
for (CXXNewExpr::const_arg_iterator I = NE->placement_arg_begin(),
E = NE->placement_arg_end(); I != E; ++I)
@@ -1072,37 +1101,48 @@ void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
// MallocUpdateRefState() instead of MallocMemAux() which breakes the
// existing binding.
State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
- : AF_CXXNew);
- State = addExtentSize(C, NE, State);
- State = ProcessZeroAllocation(C, NE, 0, State);
+ : AF_CXXNew, Target);
+ State = addExtentSize(C, NE, State, Target);
+ State = ProcessZeroAllocation(C, NE, 0, State, Target);
C.addTransition(State);
}
+void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
+ CheckerContext &C) const {
+ if (!C.getAnalysisManager().getAnalyzerOptions().mayInlineCXXAllocator())
+ processNewAllocation(NE, C, C.getSVal(NE));
+}
+
+void MallocChecker::checkNewAllocator(const CXXNewExpr *NE, SVal Target,
+ CheckerContext &C) const {
+ if (!C.wasInlined)
+ processNewAllocation(NE, C, Target);
+}
+
// Sets the extent value of the MemRegion allocated by
// new expression NE to its size in Bytes.
//
ProgramStateRef MallocChecker::addExtentSize(CheckerContext &C,
const CXXNewExpr *NE,
- ProgramStateRef State) {
+ ProgramStateRef State,
+ SVal Target) {
if (!State)
return nullptr;
SValBuilder &svalBuilder = C.getSValBuilder();
SVal ElementCount;
- const LocationContext *LCtx = C.getLocationContext();
const SubRegion *Region;
if (NE->isArray()) {
const Expr *SizeExpr = NE->getArraySize();
- ElementCount = State->getSVal(SizeExpr, C.getLocationContext());
+ ElementCount = C.getSVal(SizeExpr);
// Store the extent size for the (symbolic)region
// containing the elements.
- Region = (State->getSVal(NE, LCtx))
- .getAsRegion()
+ Region = Target.getAsRegion()
->getAs<SubRegion>()
- ->getSuperRegion()
+ ->StripCasts()
->getAs<SubRegion>();
} else {
ElementCount = svalBuilder.makeIntVal(1, true);
- Region = (State->getSVal(NE, LCtx)).getAsRegion()->getAs<SubRegion>();
+ Region = Target.getAsRegion()->getAs<SubRegion>();
}
assert(Region);
@@ -1199,7 +1239,8 @@ MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
if (I != E) {
- return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), State);
+ return MallocMemAux(C, CE, CE->getArg(I->getASTIndex()), UndefinedVal(),
+ State);
}
return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
}
@@ -1212,8 +1253,7 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
if (!State)
return nullptr;
- return MallocMemAux(C, CE, State->getSVal(SizeEx, C.getLocationContext()),
- Init, State, Family);
+ return MallocMemAux(C, CE, C.getSVal(SizeEx), Init, State, Family);
}
ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
@@ -1239,7 +1279,7 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
// Fill the region with the initialization value.
- State = State->bindDefault(RetVal, Init, LCtx);
+ State = State->bindDefaultInitial(RetVal, Init, LCtx);
// Set the region's extent equal to the Size parameter.
const SymbolicRegion *R =
@@ -1263,18 +1303,22 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
const Expr *E,
ProgramStateRef State,
- AllocationFamily Family) {
+ AllocationFamily Family,
+ Optional<SVal> RetVal) {
if (!State)
return nullptr;
// Get the return value.
- SVal retVal = State->getSVal(E, C.getLocationContext());
+ if (!RetVal)
+ RetVal = C.getSVal(E);
// We expect the malloc functions to return a pointer.
- if (!retVal.getAs<Loc>())
+ if (!RetVal->getAs<Loc>())
return nullptr;
- SymbolRef Sym = retVal.getAsLocSymbol();
+ SymbolRef Sym = RetVal->getAsLocSymbol();
+ // This is a return value of a function that was not inlined, such as malloc()
+ // or new(). We've checked that in the caller. Therefore, it must be a symbol.
assert(Sym);
// Set the symbol's state to Allocated.
@@ -1294,9 +1338,9 @@ ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
bool ReleasedAllocated = false;
for (const auto &Arg : Att->args()) {
- ProgramStateRef StateI = FreeMemAux(C, CE, State, Arg,
- Att->getOwnKind() == OwnershipAttr::Holds,
- ReleasedAllocated);
+ ProgramStateRef StateI = FreeMemAux(
+ C, CE, State, Arg.getASTIndex(),
+ Att->getOwnKind() == OwnershipAttr::Holds, ReleasedAllocated);
if (StateI)
State = StateI;
}
@@ -1429,6 +1473,7 @@ void MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C,
case AF_CXXNew: os << "'new'"; return;
case AF_CXXNewArray: os << "'new[]'"; return;
case AF_IfNameIndex: os << "'if_nameindex()'"; return;
+ case AF_InnerBuffer: os << "container-specific allocator"; return;
case AF_Alloca:
case AF_None: llvm_unreachable("not a deallocation expression");
}
@@ -1441,6 +1486,7 @@ void MallocChecker::printExpectedDeallocName(raw_ostream &os,
case AF_CXXNew: os << "'delete'"; return;
case AF_CXXNewArray: os << "'delete[]'"; return;
case AF_IfNameIndex: os << "'if_freenameindex()'"; return;
+ case AF_InnerBuffer: os << "container-specific deallocator"; return;
case AF_Alloca:
case AF_None: llvm_unreachable("suspicious argument");
}
@@ -1457,7 +1503,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
if (!State)
return nullptr;
- SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
+ SVal ArgVal = C.getSVal(ArgExpr);
if (!ArgVal.getAs<DefinedOrUnknownSVal>())
return nullptr;
DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
@@ -1615,7 +1661,9 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
return Optional<MallocChecker::CheckKind>();
}
case AF_CXXNew:
- case AF_CXXNewArray: {
+ case AF_CXXNewArray:
+ // FIXME: Add new CheckKind for AF_InnerBuffer.
+ case AF_InnerBuffer: {
if (IsALeakCheck) {
if (ChecksEnabled[CK_NewDeleteLeaksChecker])
return CK_NewDeleteLeaksChecker;
@@ -1945,6 +1993,11 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
R->markInteresting(Sym);
R->addRange(Range);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
+
+ const RefState *RS = C.getState()->get<RegionState>(Sym);
+ if (RS->getAllocationFamily() == AF_InnerBuffer)
+ R->addVisitor(allocation_state::getInnerPointerBRVisitor(Sym));
+
C.emitReport(std::move(R));
}
}
@@ -2047,8 +2100,8 @@ void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal,
if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_BadFree[*CheckKind])
- BT_BadFree[*CheckKind].reset(
- new BugType(CheckNames[*CheckKind], "Bad free", "Memory Error"));
+ BT_BadFree[*CheckKind].reset(new BugType(
+ CheckNames[*CheckKind], "Bad free", categories::MemoryError));
SmallString<100> Buf;
llvm::raw_svector_ostream Os(Buf);
@@ -2084,8 +2137,7 @@ ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C,
return nullptr;
const Expr *arg0Expr = CE->getArg(0);
- const LocationContext *LCtx = C.getLocationContext();
- SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
+ SVal Arg0Val = C.getSVal(arg0Expr);
if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
return nullptr;
DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
@@ -2099,7 +2151,7 @@ ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C,
const Expr *Arg1 = CE->getArg(1);
// Get the value of the size argument.
- SVal TotalSize = State->getSVal(Arg1, LCtx);
+ SVal TotalSize = C.getSVal(Arg1);
if (SuffixWithN)
TotalSize = evalMulForBufferSize(C, Arg1, CE->getArg(2));
if (!TotalSize.getAs<DefinedOrUnknownSVal>())
@@ -2133,7 +2185,7 @@ ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C,
// Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
assert(!PrtIsNull);
SymbolRef FromPtr = arg0Val.getAsSymbol();
- SVal RetVal = State->getSVal(CE, LCtx);
+ SVal RetVal = C.getSVal(CE);
SymbolRef ToPtr = RetVal.getAsSymbol();
if (!FromPtr || !ToPtr)
return nullptr;
@@ -2216,7 +2268,7 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
// Do not show local variables belonging to a function other than
// where the error is reported.
if (!VR ||
- (VR->getStackFrame() == LeakContext->getCurrentStackFrame()))
+ (VR->getStackFrame() == LeakContext->getStackFrame()))
ReferenceRegion = MR;
}
}
@@ -2406,7 +2458,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
// Check if we are returning a symbol.
ProgramStateRef State = C.getState();
- SVal RetVal = State->getSVal(E, C.getLocationContext());
+ SVal RetVal = C.getSVal(E);
SymbolRef Sym = RetVal.getAsSymbol();
if (!Sym)
// If we are returning a field of the allocated struct or an array element,
@@ -2436,8 +2488,7 @@ void MallocChecker::checkPostStmt(const BlockExpr *BE,
ProgramStateRef state = C.getState();
const BlockDataRegion *R =
- cast<BlockDataRegion>(state->getSVal(BE,
- C.getLocationContext()).getAsRegion());
+ cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
E = R->referenced_vars_end();
@@ -2793,36 +2844,138 @@ static SymbolRef findFailedReallocSymbol(ProgramStateRef currState,
return nullptr;
}
+static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) {
+ if (const IdentifierInfo *II = DD->getParent()->getIdentifier()) {
+ StringRef N = II->getName();
+ if (N.contains_lower("ptr") || N.contains_lower("pointer")) {
+ if (N.contains_lower("ref") || N.contains_lower("cnt") ||
+ N.contains_lower("intrusive") || N.contains_lower("shared")) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
BugReport &BR) {
+
ProgramStateRef state = N->getState();
ProgramStateRef statePrev = PrevN->getState();
const RefState *RS = state->get<RegionState>(Sym);
const RefState *RSPrev = statePrev->get<RegionState>(Sym);
- if (!RS)
- return nullptr;
const Stmt *S = PathDiagnosticLocation::getStmt(N);
- if (!S)
+ // When dealing with containers, we sometimes want to give a note
+ // even if the statement is missing.
+ if (!S && (!RS || RS->getAllocationFamily() != AF_InnerBuffer))
return nullptr;
+ const LocationContext *CurrentLC = N->getLocationContext();
+
+ // If we find an atomic fetch_add or fetch_sub within the destructor in which
+ // the pointer was released (before the release), this is likely a destructor
+ // of a shared pointer.
+ // Because we don't model atomics, and also because we don't know that the
+ // original reference count is positive, we should not report use-after-frees
+ // on objects deleted in such destructors. This can probably be improved
+ // through better shared pointer modeling.
+ if (ReleaseDestructorLC) {
+ if (const auto *AE = dyn_cast<AtomicExpr>(S)) {
+ AtomicExpr::AtomicOp Op = AE->getOp();
+ if (Op == AtomicExpr::AO__c11_atomic_fetch_add ||
+ Op == AtomicExpr::AO__c11_atomic_fetch_sub) {
+ if (ReleaseDestructorLC == CurrentLC ||
+ ReleaseDestructorLC->isParentOf(CurrentLC)) {
+ BR.markInvalid(getTag(), S);
+ }
+ }
+ }
+ }
+
// FIXME: We will eventually need to handle non-statement-based events
// (__attribute__((cleanup))).
// Find out if this is an interesting point and what is the kind.
- const char *Msg = nullptr;
+ StringRef Msg;
StackHintGeneratorForSymbol *StackHint = nullptr;
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+
if (Mode == Normal) {
if (isAllocated(RS, RSPrev, S)) {
Msg = "Memory is allocated";
StackHint = new StackHintGeneratorForSymbol(Sym,
"Returned allocated memory");
} else if (isReleased(RS, RSPrev, S)) {
- Msg = "Memory is released";
+ const auto Family = RS->getAllocationFamily();
+ switch (Family) {
+ case AF_Alloca:
+ case AF_Malloc:
+ case AF_CXXNew:
+ case AF_CXXNewArray:
+ case AF_IfNameIndex:
+ Msg = "Memory is released";
+ break;
+ case AF_InnerBuffer: {
+ OS << "Inner pointer invalidated by call to ";
+ if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) {
+ OS << "destructor";
+ } else {
+ OS << "'";
+ const Stmt *S = RS->getStmt();
+ if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
+ OS << MemCallE->getMethodDecl()->getNameAsString();
+ } else if (const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
+ OS << OpCallE->getDirectCallee()->getNameAsString();
+ } else if (const auto *CallE = dyn_cast<CallExpr>(S)) {
+ auto &CEMgr = BRC.getStateManager().getCallEventManager();
+ CallEventRef<> Call = CEMgr.getSimpleCall(CallE, state, CurrentLC);
+ const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl());
+ OS << (D ? D->getNameAsString() : "unknown");
+ }
+ OS << "'";
+ }
+ Msg = OS.str();
+ break;
+ }
+ case AF_None:
+ llvm_unreachable("Unhandled allocation family!");
+ }
StackHint = new StackHintGeneratorForSymbol(Sym,
"Returning; memory was released");
+
+ // See if we're releasing memory while inlining a destructor
+ // (or one of its callees). This turns on various common
+ // false positive suppressions.
+ bool FoundAnyDestructor = false;
+ for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
+ if (isReferenceCountingPointerDestructor(DD)) {
+ // This immediately looks like a reference-counting destructor.
+ // We're bad at guessing the original reference count of the object,
+ // so suppress the report for now.
+ BR.markInvalid(getTag(), DD);
+ } else if (!FoundAnyDestructor) {
+ assert(!ReleaseDestructorLC &&
+ "There can be only one release point!");
+ // Suspect that it's a reference counting pointer destructor.
+ // On one of the next nodes might find out that it has atomic
+ // reference counting operations within it (see the code above),
+ // and if so, we'd conclude that it likely is a reference counting
+ // pointer destructor.
+ ReleaseDestructorLC = LC->getStackFrame();
+ // It is unlikely that releasing memory is delegated to a destructor
+ // inside a destructor of a shared pointer, because it's fairly hard
+ // to pass the information that the pointer indeed needs to be
+ // released into it. So we're only interested in the innermost
+ // destructor.
+ FoundAnyDestructor = true;
+ }
+ }
+ }
} else if (isRelinquished(RS, RSPrev, S)) {
Msg = "Memory ownership is transferred";
StackHint = new StackHintGeneratorForSymbol(Sym, "");
@@ -2856,13 +3009,24 @@ std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
}
}
- if (!Msg)
+ if (Msg.empty())
return nullptr;
assert(StackHint);
// Generate the extra diagnostic.
- PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
- N->getLocationContext());
+ PathDiagnosticLocation Pos;
+ if (!S) {
+ assert(RS->getAllocationFamily() == AF_InnerBuffer);
+ auto PostImplCall = N->getLocation().getAs<PostImplicitCall>();
+ if (!PostImplCall)
+ return nullptr;
+ Pos = PathDiagnosticLocation(PostImplCall->getLocation(),
+ BRC.getSourceManager());
+ } else {
+ Pos = PathDiagnosticLocation(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ }
+
return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true, StackHint);
}
@@ -2890,6 +3054,20 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
}
}
+namespace clang {
+namespace ento {
+namespace allocation_state {
+
+ProgramStateRef
+markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) {
+ AllocationFamily Family = AF_InnerBuffer;
+ return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin));
+}
+
+} // end namespace allocation_state
+} // end namespace ento
+} // end namespace clang
+
void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
registerCStringCheckerBasic(mgr);
MallocChecker *checker = mgr.registerChecker<MallocChecker>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
index 497978f07815..19c1d077afa1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
@@ -46,7 +46,7 @@ class MisusedMovedObjectChecker
: public Checker<check::PreCall, check::PostCall, check::EndFunction,
check::DeadSymbols, check::RegionChanges> {
public:
- void checkEndFunction(CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
void checkPreCall(const CallEvent &MC, CheckerContext &C) const;
void checkPostCall(const CallEvent &MC, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
@@ -61,7 +61,7 @@ public:
private:
enum MisuseKind {MK_FunCall, MK_Copy, MK_Move};
- class MovedBugVisitor : public BugReporterVisitorImpl<MovedBugVisitor> {
+ class MovedBugVisitor : public BugReporterVisitor {
public:
MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {}
@@ -101,8 +101,6 @@ static ProgramStateRef removeFromState(ProgramStateRef State,
const MemRegion *Region) {
if (!Region)
return State;
- // Note: The isSubRegionOf function is not reflexive.
- State = State->remove<TrackedRegionMap>(Region);
for (auto &E : State->get<TrackedRegionMap>()) {
if (E.first->isSubRegionOf(Region))
State = State->remove<TrackedRegionMap>(E.first);
@@ -224,7 +222,8 @@ ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
// Removing the function parameters' MemRegion from the state. This is needed
// for PODs where the trivial destructor does not even created nor executed.
-void MisusedMovedObjectChecker::checkEndFunction(CheckerContext &C) const {
+void MisusedMovedObjectChecker::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &C) const {
auto State = C.getState();
TrackedRegionMapTy Objects = State->get<TrackedRegionMap>();
if (Objects.isEmpty())
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
new file mode 100644
index 000000000000..5060b0e0a6e0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -0,0 +1,88 @@
+// MmapWriteExecChecker.cpp - Check for the prot argument -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker tests the 3rd argument of mmap's calls to check if
+// it is writable and executable in the same time. It's somehow
+// an optional checker since for example in JIT libraries it is pretty common.
+//
+//===----------------------------------------------------------------------===//
+
+#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/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using llvm::APSInt;
+
+namespace {
+class MmapWriteExecChecker : public Checker<check::PreCall> {
+ CallDescription MmapFn;
+ CallDescription MprotectFn;
+ static int ProtWrite;
+ static int ProtExec;
+ static int ProtRead;
+ mutable std::unique_ptr<BugType> BT;
+public:
+ MmapWriteExecChecker() : MmapFn("mmap", 6), MprotectFn("mprotect", 3) {}
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+ int ProtExecOv;
+ int ProtReadOv;
+};
+}
+
+int MmapWriteExecChecker::ProtWrite = 0x02;
+int MmapWriteExecChecker::ProtExec = 0x04;
+int MmapWriteExecChecker::ProtRead = 0x01;
+
+void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (Call.isCalled(MmapFn) || Call.isCalled(MprotectFn)) {
+ SVal ProtVal = Call.getArgSVal(2);
+ Optional<nonloc::ConcreteInt> ProtLoc = ProtVal.getAs<nonloc::ConcreteInt>();
+ int64_t Prot = ProtLoc->getValue().getSExtValue();
+ if (ProtExecOv != ProtExec)
+ ProtExec = ProtExecOv;
+ if (ProtReadOv != ProtRead)
+ ProtRead = ProtReadOv;
+
+ // Wrong settings
+ if (ProtRead == ProtExec)
+ return;
+
+ if ((Prot & (ProtWrite | ProtExec)) == (ProtWrite | ProtExec)) {
+ if (!BT)
+ BT.reset(new BugType(this, "W^X check fails, Write Exec prot flags set", "Security"));
+
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
+
+ auto Report = llvm::make_unique<BugReport>(
+ *BT, "Both PROT_WRITE and PROT_EXEC flags are set. This can "
+ "lead to exploitable memory regions, which could be overwritten "
+ "with malicious code", N);
+ Report->addRange(Call.getArgSourceRange(2));
+ C.emitReport(std::move(Report));
+ }
+ }
+}
+
+void ento::registerMmapWriteExecChecker(CheckerManager &mgr) {
+ MmapWriteExecChecker *Mwec =
+ mgr.registerChecker<MmapWriteExecChecker>();
+ Mwec->ProtExecOv =
+ mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtExec", 0x04, Mwec);
+ Mwec->ProtReadOv =
+ mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtRead", 0x01, Mwec);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index 559c75d7a5b0..2bd68b625c1f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -186,8 +186,7 @@ static void setFlag(ProgramStateRef state, SVal val, CheckerContext &C) {
}
static QualType parameterTypeFromSVal(SVal val, CheckerContext &C) {
- const StackFrameContext *
- SFC = C.getLocationContext()->getCurrentStackFrame();
+ const StackFrameContext * SFC = C.getStackFrame();
if (Optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>()) {
const MemRegion* R = X->getRegion();
if (const VarRegion *VR = R->getAs<VarRegion>())
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 6d05159e51b0..01d2c0491b85 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -44,13 +44,9 @@ public:
};
} // end anonymous namespace
-void NonNullParamChecker::checkPreCall(const CallEvent &Call,
- CheckerContext &C) const {
+/// \return Bitvector marking non-null attributes.
+static llvm::SmallBitVector getNonNullAttrs(const CallEvent &Call) {
const Decl *FD = Call.getDecl();
- if (!FD)
- return;
-
- // Merge all non-null attributes
unsigned NumArgs = Call.getNumArgs();
llvm::SmallBitVector AttrNonNull(NumArgs);
for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
@@ -58,49 +54,54 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
AttrNonNull.set(0, NumArgs);
break;
}
- for (unsigned Val : NonNull->args()) {
- if (Val >= NumArgs)
+ for (const ParamIdx &Idx : NonNull->args()) {
+ unsigned IdxAST = Idx.getASTIndex();
+ if (IdxAST >= NumArgs)
continue;
- AttrNonNull.set(Val);
+ AttrNonNull.set(IdxAST);
}
}
+ return AttrNonNull;
+}
- ProgramStateRef state = C.getState();
+void NonNullParamChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (!Call.getDecl())
+ return;
+
+ llvm::SmallBitVector AttrNonNull = getNonNullAttrs(Call);
+ unsigned NumArgs = Call.getNumArgs();
- CallEvent::param_type_iterator TyI = Call.param_type_begin(),
- TyE = Call.param_type_end();
+ ProgramStateRef state = C.getState();
+ ArrayRef<ParmVarDecl*> parms = Call.parameters();
for (unsigned idx = 0; idx < NumArgs; ++idx) {
+ // For vararg functions, a corresponding parameter decl may not exist.
+ bool HasParam = idx < parms.size();
// Check if the parameter is a reference. We want to report when reference
// to a null pointer is passed as a parameter.
- bool haveRefTypeParam = false;
- if (TyI != TyE) {
- haveRefTypeParam = (*TyI)->isReferenceType();
- TyI++;
- }
-
+ bool haveRefTypeParam =
+ HasParam ? parms[idx]->getType()->isReferenceType() : false;
bool haveAttrNonNull = AttrNonNull[idx];
- if (!haveAttrNonNull) {
- // Check if the parameter is also marked 'nonnull'.
- ArrayRef<ParmVarDecl*> parms = Call.parameters();
- if (idx < parms.size())
- haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
- }
- if (!haveRefTypeParam && !haveAttrNonNull)
+ // Check if the parameter is also marked 'nonnull'.
+ if (!haveAttrNonNull && HasParam)
+ haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
+
+ if (!haveAttrNonNull && !haveRefTypeParam)
continue;
// If the value is unknown or undefined, we can't perform this check.
const Expr *ArgE = Call.getArgExpr(idx);
SVal V = Call.getArgSVal(idx);
- Optional<DefinedSVal> DV = V.getAs<DefinedSVal>();
+ auto DV = V.getAs<DefinedSVal>();
if (!DV)
continue;
- // Process the case when the argument is not a location.
assert(!haveRefTypeParam || DV->getAs<Loc>());
+ // Process the case when the argument is not a location.
if (haveAttrNonNull && !DV->getAs<Loc>()) {
// If the argument is a union type, we want to handle a potential
// transparent_union GCC extension.
@@ -112,66 +113,63 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
continue;
- if (Optional<nonloc::CompoundVal> CSV =
- DV->getAs<nonloc::CompoundVal>()) {
- nonloc::CompoundVal::iterator CSV_I = CSV->begin();
- assert(CSV_I != CSV->end());
- V = *CSV_I;
- DV = V.getAs<DefinedSVal>();
- assert(++CSV_I == CSV->end());
- // FIXME: Handle (some_union){ some_other_union_val }, which turns into
- // a LazyCompoundVal inside a CompoundVal.
- if (!V.getAs<Loc>())
- continue;
- // Retrieve the corresponding expression.
- if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
- if (const InitListExpr *IE =
- dyn_cast<InitListExpr>(CE->getInitializer()))
- ArgE = dyn_cast<Expr>(*(IE->begin()));
-
- } else {
- // FIXME: Handle LazyCompoundVals?
+ auto CSV = DV->getAs<nonloc::CompoundVal>();
+
+ // FIXME: Handle LazyCompoundVals?
+ if (!CSV)
continue;
- }
+
+ V = *(CSV->begin());
+ DV = V.getAs<DefinedSVal>();
+ assert(++CSV->begin() == CSV->end());
+ // FIXME: Handle (some_union){ some_other_union_val }, which turns into
+ // a LazyCompoundVal inside a CompoundVal.
+ if (!V.getAs<Loc>())
+ continue;
+
+ // Retrieve the corresponding expression.
+ if (const auto *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
+ if (const auto *IE = dyn_cast<InitListExpr>(CE->getInitializer()))
+ ArgE = dyn_cast<Expr>(*(IE->begin()));
}
ConstraintManager &CM = C.getConstraintManager();
ProgramStateRef stateNotNull, stateNull;
std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
- if (stateNull) {
- if (!stateNotNull) {
- // Generate an error node. Check for a null node in case
- // we cache out.
- if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
-
- std::unique_ptr<BugReport> R;
- if (haveAttrNonNull)
- R = genReportNullAttrNonNull(errorNode, ArgE);
- else if (haveRefTypeParam)
- R = genReportReferenceToNullPointer(errorNode, ArgE);
-
- // Highlight the range of the argument that was null.
- R->addRange(Call.getArgSourceRange(idx));
-
- // Emit the bug report.
- C.emitReport(std::move(R));
- }
-
- // Always return. Either we cached out or we just emitted an error.
- return;
+ // Generate an error node. Check for a null node in case
+ // we cache out.
+ if (stateNull && !stateNotNull) {
+ if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
+
+ std::unique_ptr<BugReport> R;
+ if (haveAttrNonNull)
+ R = genReportNullAttrNonNull(errorNode, ArgE);
+ else if (haveRefTypeParam)
+ R = genReportReferenceToNullPointer(errorNode, ArgE);
+
+ // Highlight the range of the argument that was null.
+ R->addRange(Call.getArgSourceRange(idx));
+
+ // Emit the bug report.
+ C.emitReport(std::move(R));
}
+
+ // Always return. Either we cached out or we just emitted an error.
+ return;
+ }
+
+ if (stateNull) {
if (ExplodedNode *N = C.generateSink(stateNull, C.getPredecessor())) {
ImplicitNullDerefEvent event = {
- V, false, N, &C.getBugReporter(),
- /*IsDirectDereference=*/haveRefTypeParam};
+ V, false, N, &C.getBugReporter(),
+ /*IsDirectDereference=*/haveRefTypeParam};
dispatchEvent(event);
}
}
// If a pointer value passed the check we should assume that it is
// indeed not null from this point forward.
- assert(stateNotNull);
state = stateNotNull;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
index 0b4ecb41d20f..6f3180eb839a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
@@ -54,7 +54,7 @@ private:
} // namespace
-/// Lazily initialize cache for required identifier informations.
+/// Lazily initialize cache for required identifier information.
void NonnullGlobalConstantsChecker::initIdentifierInfo(ASTContext &Ctx) const {
if (NSStringII)
return;
@@ -73,9 +73,9 @@ void NonnullGlobalConstantsChecker::checkLocation(SVal location, bool isLoad,
return;
ProgramStateRef State = C.getState();
- SVal V = State->getSVal(location.castAs<Loc>());
if (isGlobalConstString(location)) {
+ SVal V = State->getSVal(location.castAs<Loc>());
Optional<DefinedOrUnknownSVal> Constr = V.getAs<DefinedOrUnknownSVal>();
if (Constr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index fa9a317683ba..7d1ca61c97a9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -30,6 +30,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/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -40,21 +41,6 @@ using namespace clang;
using namespace ento;
namespace {
-// Do not reorder! The getMostNullable method relies on the order.
-// Optimization: Most pointers expected to be unspecified. When a symbol has an
-// unspecified or nonnull type non of the rules would indicate any problem for
-// that symbol. For this reason only nullable and contradicted nullability are
-// stored for a symbol. When a symbol is already contradicted, it can not be
-// casted back to nullable.
-enum class Nullability : char {
- Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
- // not report any nullability related issue for this symbol.
- // This nullability is propagated aggressively to avoid false
- // positive results. See the comment on getMostNullable method.
- Nullable,
- Unspecified,
- Nonnull
-};
/// Returns the most nullable nullability. This is used for message expressions
/// like [receiver method], where the nullability of this expression is either
@@ -142,8 +128,7 @@ public:
DefaultBool NeedTracking;
private:
- class NullabilityBugVisitor
- : public BugReporterVisitorImpl<NullabilityBugVisitor> {
+ class NullabilityBugVisitor : public BugReporterVisitor {
public:
NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
@@ -265,7 +250,7 @@ REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *,
// initial direct violation has been discovered, and (3) warning after a direct
// violation that has been implicitly or explicitly suppressed (for
// example, with a cast of NULL to _Nonnull). In essence, once an invariant
-// violation is detected on a path, this checker will be esentially turned off
+// violation is detected on a path, this checker will be essentially turned off
// for the rest of the analysis
//
// The analyzer takes this approach (rather than generating a sink node) to
@@ -345,17 +330,6 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
nullptr);
}
-static Nullability getNullabilityAnnotation(QualType Type) {
- const auto *AttrType = Type->getAs<AttributedType>();
- if (!AttrType)
- return Nullability::Unspecified;
- if (AttrType->getAttrKind() == AttributedType::attr_nullable)
- return Nullability::Nullable;
- else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
- return Nullability::Nonnull;
- return Nullability::Unspecified;
-}
-
/// Returns true when the value stored at the given location is null
/// and the passed in type is nonnnull.
static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
@@ -560,8 +534,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
if (State->get<InvariantViolated>())
return;
- auto RetSVal =
- State->getSVal(S, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
+ auto RetSVal = C.getSVal(S).getAs<DefinedOrUnknownSVal>();
if (!RetSVal)
return;
@@ -873,7 +846,7 @@ void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
// are either item retrieval related or not interesting nullability wise.
// Using this fact, to keep the code easier to read just ignore the return
// value of every instance method of dictionaries.
- if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {
+ if (M.isInstanceMessage() && Name.contains("Dictionary")) {
State =
State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
C.addTransition(State);
@@ -881,7 +854,7 @@ void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
}
// For similar reasons ignore some methods of Cocoa arrays.
StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
- if (Name.find("Array") != StringRef::npos &&
+ if (Name.contains("Array") &&
(FirstSelectorSlot == "firstObject" ||
FirstSelectorSlot == "lastObject")) {
State =
@@ -894,7 +867,7 @@ void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
// encodings are used. Using lossless encodings is so frequent that ignoring
// this class of methods reduced the emitted diagnostics by about 30% on
// some projects (and all of that was false positives).
- if (Name.find("String") != StringRef::npos) {
+ if (Name.contains("String")) {
for (auto Param : M.parameters()) {
if (Param->getName() == "encoding") {
State = State->set<NullabilityMap>(ReturnRegion,
@@ -977,8 +950,7 @@ void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
if (DestNullability == Nullability::Unspecified)
return;
- auto RegionSVal =
- State->getSVal(CE, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
+ auto RegionSVal = C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
const MemRegion *Region = getTrackRegion(*RegionSVal);
if (!Region)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
index 40e379cb2efc..d1749cfdbe27 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
@@ -270,8 +270,10 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
hasRHS(SuspiciousNumberObjectExprM)));
auto ConversionThroughBranchingM =
- ifStmt(hasCondition(SuspiciousNumberObjectExprM))
- .bind("pedantic");
+ ifStmt(allOf(
+ hasCondition(SuspiciousNumberObjectExprM),
+ unless(hasConditionVariableStatement(declStmt())
+ ))).bind("pedantic");
auto ConversionThroughCallM =
callExpr(hasAnyArgument(allOf(hasType(SuspiciousScalarTypeM),
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index cbaa5c23592d..b7339fe79f69 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -39,7 +39,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
const Expr *Ex = S->getSynchExpr();
ProgramStateRef state = C.getState();
- SVal V = state->getSVal(Ex, C.getLocationContext());
+ SVal V = C.getSVal(Ex);
// Uninitialized value used for the mutex?
if (V.getAs<UndefinedVal>()) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
new file mode 100644
index 000000000000..81bcda51b8f8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
@@ -0,0 +1,209 @@
+//===- ObjCAutoreleaseWriteChecker.cpp ----------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCAutoreleaseWriteChecker which warns against writes
+// into autoreleased out parameters which cause crashes.
+// An example of a problematic write is a write to {@code error} in the example
+// below:
+//
+// - (BOOL) mymethod:(NSError *__autoreleasing *)error list:(NSArray*) list {
+// [list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+// NSString *myString = obj;
+// if ([myString isEqualToString:@"error"] && error)
+// *error = [NSError errorWithDomain:@"MyDomain" code:-1];
+// }];
+// return false;
+// }
+//
+// Such code will crash on read from `*error` due to the autorelease pool
+// in `enumerateObjectsUsingBlock` implementation freeing the error object
+// on exit from the function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.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/Twine.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+const char *ProblematicWriteBind = "problematicwrite";
+const char *CapturedBind = "capturedbind";
+const char *ParamBind = "parambind";
+const char *IsMethodBind = "ismethodbind";
+
+class ObjCAutoreleaseWriteChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+private:
+ std::vector<std::string> SelectorsWithAutoreleasingPool = {
+ // Common to NSArray, NSSet, NSOrderedSet
+ "enumerateObjectsUsingBlock:",
+ "enumerateObjectsWithOptions:usingBlock:",
+
+ // Common to NSArray and NSOrderedSet
+ "enumerateObjectsAtIndexes:options:usingBlock:",
+ "indexOfObjectAtIndexes:options:passingTest:",
+ "indexesOfObjectsAtIndexes:options:passingTest:",
+ "indexOfObjectPassingTest:",
+ "indexOfObjectWithOptions:passingTest:",
+ "indexesOfObjectsPassingTest:",
+ "indexesOfObjectsWithOptions:passingTest:",
+
+ // NSDictionary
+ "enumerateKeysAndObjectsUsingBlock:",
+ "enumerateKeysAndObjectsWithOptions:usingBlock:",
+ "keysOfEntriesPassingTest:",
+ "keysOfEntriesWithOptions:passingTest:",
+
+ // NSSet
+ "objectsPassingTest:",
+ "objectsWithOptions:passingTest:",
+ "enumerateIndexPathsWithOptions:usingBlock:",
+
+ // NSIndexSet
+ "enumerateIndexesWithOptions:usingBlock:",
+ "enumerateIndexesUsingBlock:",
+ "enumerateIndexesInRange:options:usingBlock:",
+ "enumerateRangesUsingBlock:",
+ "enumerateRangesWithOptions:usingBlock:",
+ "enumerateRangesInRange:options:usingBlock:",
+ "indexPassingTest:",
+ "indexesPassingTest:",
+ "indexWithOptions:passingTest:",
+ "indexesWithOptions:passingTest:",
+ "indexInRange:options:passingTest:",
+ "indexesInRange:options:passingTest:"
+ };
+
+ std::vector<std::string> FunctionsWithAutoreleasingPool = {
+ "dispatch_async", "dispatch_group_async", "dispatch_barrier_async"};
+};
+}
+
+static inline std::vector<llvm::StringRef> toRefs(std::vector<std::string> V) {
+ return std::vector<llvm::StringRef>(V.begin(), V.end());
+}
+
+static auto callsNames(std::vector<std::string> FunctionNames)
+ -> decltype(callee(functionDecl())) {
+ return callee(functionDecl(hasAnyName(toRefs(FunctionNames))));
+}
+
+static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR,
+ AnalysisManager &AM,
+ const ObjCAutoreleaseWriteChecker *Checker) {
+ AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
+
+ const auto *PVD = Match.getNodeAs<ParmVarDecl>(ParamBind);
+ QualType Ty = PVD->getType();
+ if (Ty->getPointeeType().getObjCLifetime() != Qualifiers::OCL_Autoreleasing)
+ return;
+ const char *ActionMsg = "Write to";
+ const auto *MarkedStmt = Match.getNodeAs<Expr>(ProblematicWriteBind);
+ bool IsCapture = false;
+
+ // Prefer to warn on write, but if not available, warn on capture.
+ if (!MarkedStmt) {
+ MarkedStmt = Match.getNodeAs<Expr>(CapturedBind);
+ assert(MarkedStmt);
+ ActionMsg = "Capture of";
+ IsCapture = true;
+ }
+
+ SourceRange Range = MarkedStmt->getSourceRange();
+ PathDiagnosticLocation Location = PathDiagnosticLocation::createBegin(
+ MarkedStmt, BR.getSourceManager(), ADC);
+ bool IsMethod = Match.getNodeAs<ObjCMethodDecl>(IsMethodBind) != nullptr;
+ const char *Name = IsMethod ? "method" : "function";
+
+ BR.EmitBasicReport(
+ ADC->getDecl(), Checker,
+ /*Name=*/(llvm::Twine(ActionMsg)
+ + " autoreleasing out parameter inside autorelease pool").str(),
+ /*Category=*/"Memory",
+ (llvm::Twine(ActionMsg) + " autoreleasing out parameter " +
+ (IsCapture ? "'" + PVD->getName() + "'" + " " : "") + "inside " +
+ "autorelease pool that may exit before " + Name + " returns; consider "
+ "writing first to a strong local variable declared outside of the block")
+ .str(),
+ Location,
+ Range);
+}
+
+void ObjCAutoreleaseWriteChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+
+ auto DoublePointerParamM =
+ parmVarDecl(hasType(hasCanonicalType(pointerType(
+ pointee(hasCanonicalType(objcObjectPointerType()))))))
+ .bind(ParamBind);
+
+ auto ReferencedParamM =
+ declRefExpr(to(parmVarDecl(DoublePointerParamM))).bind(CapturedBind);
+
+ // Write into a binded object, e.g. *ParamBind = X.
+ auto WritesIntoM = binaryOperator(
+ hasLHS(unaryOperator(
+ hasOperatorName("*"),
+ hasUnaryOperand(
+ ignoringParenImpCasts(ReferencedParamM))
+ )),
+ hasOperatorName("=")
+ ).bind(ProblematicWriteBind);
+
+ auto ArgumentCaptureM = hasAnyArgument(
+ ignoringParenImpCasts(ReferencedParamM));
+ auto CapturedInParamM = stmt(anyOf(
+ callExpr(ArgumentCaptureM),
+ objcMessageExpr(ArgumentCaptureM)));
+
+ // WritesIntoM happens inside a block passed as an argument.
+ auto WritesOrCapturesInBlockM = hasAnyArgument(allOf(
+ hasType(hasCanonicalType(blockPointerType())),
+ forEachDescendant(
+ stmt(anyOf(WritesIntoM, CapturedInParamM))
+ )));
+
+ auto BlockPassedToMarkedFuncM = stmt(anyOf(
+ callExpr(allOf(
+ callsNames(FunctionsWithAutoreleasingPool), WritesOrCapturesInBlockM)),
+ objcMessageExpr(allOf(
+ hasAnySelector(toRefs(SelectorsWithAutoreleasingPool)),
+ WritesOrCapturesInBlockM))
+ ));
+
+ auto HasParamAndWritesInMarkedFuncM = allOf(
+ hasAnyParameter(DoublePointerParamM),
+ forEachDescendant(BlockPassedToMarkedFuncM));
+
+ auto MatcherM = decl(anyOf(
+ objcMethodDecl(HasParamAndWritesInMarkedFuncM).bind(IsMethodBind),
+ functionDecl(HasParamAndWritesInMarkedFuncM),
+ blockDecl(HasParamAndWritesInMarkedFuncM)));
+
+ auto Matches = match(MatcherM, *D, AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, D, BR, AM, this);
+}
+
+void ento::registerAutoreleaseWriteChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<ObjCAutoreleaseWriteChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index 58ebf72660b6..fb05ca630b45 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -39,7 +39,7 @@ class ObjCContainersChecker : public Checker< check::PreStmt<CallExpr>,
}
inline SymbolRef getArraySym(const Expr *E, CheckerContext &C) const {
- SVal ArrayRef = C.getState()->getSVal(E, C.getLocationContext());
+ SVal ArrayRef = C.getSVal(E);
SymbolRef ArraySym = ArrayRef.getAsSymbol();
return ArraySym;
}
@@ -66,13 +66,13 @@ REGISTER_MAP_WITH_PROGRAMSTATE(ArraySizeMap, SymbolRef, DefinedSVal)
void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
- SVal SizeV = State->getSVal(Size, C.getLocationContext());
+ SVal SizeV = C.getSVal(Size);
// Undefined is reported by another checker.
if (SizeV.isUnknownOrUndef())
return;
// Get the ArrayRef symbol.
- SVal ArrayRef = State->getSVal(Array, C.getLocationContext());
+ SVal ArrayRef = C.getSVal(Array);
SymbolRef ArraySym = ArrayRef.getAsSymbol();
if (!ArraySym)
return;
@@ -128,7 +128,7 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
// Get the index.
const Expr *IdxExpr = CE->getArg(1);
- SVal IdxVal = State->getSVal(IdxExpr, C.getLocationContext());
+ SVal IdxVal = C.getSVal(IdxExpr);
if (IdxVal.isUnknownOrUndef())
return;
DefinedSVal Idx = IdxVal.castAs<DefinedSVal>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index 32a1adb587bf..d01c6ae6e093 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
@@ -81,7 +81,7 @@ private:
}
-/// \brief Determine whether the given class has a superclass that we want
+/// Determine whether the given class has a superclass that we want
/// to check. The name of the found superclass is stored in SuperclassName.
///
/// \param D The declaration to check for superclasses.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index ffa3a2700616..629520437369 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -86,11 +86,11 @@ public:
namespace {
enum SelfFlagEnum {
- /// \brief No flag set.
+ /// No flag set.
SelfFlag_None = 0x0,
- /// \brief Value came from 'self'.
+ /// Value came from 'self'.
SelfFlag_Self = 0x1,
- /// \brief Value came from the result of an initializer (e.g. [super init]).
+ /// Value came from the result of an initializer (e.g. [super init]).
SelfFlag_InitRes = 0x2
};
}
@@ -98,7 +98,7 @@ enum SelfFlagEnum {
REGISTER_MAP_WITH_PROGRAMSTATE(SelfFlag, SymbolRef, unsigned)
REGISTER_TRAIT_WITH_PROGRAMSTATE(CalledInit, bool)
-/// \brief A call receiving a reference to 'self' invalidates the object that
+/// A call receiving a reference to 'self' invalidates the object that
/// 'self' contains. This keeps the "self flags" assigned to the 'self'
/// object before the call so we can assign them to the new object that 'self'
/// points to after the call.
@@ -128,11 +128,11 @@ static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) {
return getSelfFlags(val, C) & flag;
}
-/// \brief Returns true of the value of the expression is the object that 'self'
+/// Returns true of the value of the expression is the object that 'self'
/// points to and is an object that did not come from the result of calling
/// an initializer.
static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
- SVal exprVal = C.getState()->getSVal(E, C.getLocationContext());
+ SVal exprVal = C.getSVal(E);
if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
return false; // value did not come from 'self'.
if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
@@ -183,7 +183,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
// value out when we return from this method.
state = state->set<CalledInit>(true);
- SVal V = state->getSVal(Msg.getOriginExpr(), C.getLocationContext());
+ SVal V = C.getSVal(Msg.getOriginExpr());
addSelfFlag(state, V, SelfFlag_InitRes, C);
return;
}
@@ -407,7 +407,7 @@ static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND) {
return ID != nullptr;
}
-/// \brief Returns true if the location is 'self'.
+/// Returns true if the location is 'self'.
static bool isSelfVar(SVal location, CheckerContext &C) {
AnalysisDeclContext *analCtx = C.getCurrentAnalysisDeclContext();
if (!analCtx->getSelfDecl())
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
index 69b19a785938..fcba3b33f3e0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
@@ -62,9 +62,7 @@ private:
REGISTER_SET_WITH_PROGRAMSTATE(CalledSuperDealloc, SymbolRef)
namespace {
-class SuperDeallocBRVisitor final
- : public BugReporterVisitorImpl<SuperDeallocBRVisitor> {
-
+class SuperDeallocBRVisitor final : public BugReporterVisitor {
SymbolRef ReceiverSymbol;
bool Satisfied;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index 6c0c53dd64cb..f69f3492edb1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -67,7 +67,7 @@ public:
visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
}
- /// \brief Look for records of overly padded types. If padding *
+ /// Look for records of overly padded types. If padding *
/// PadMultiplier exceeds AllowedPad, then generate a report.
/// PadMultiplier is used to share code with the array padding
/// checker.
@@ -97,7 +97,7 @@ public:
reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder);
}
- /// \brief Look for arrays of overly padded types. If the padding of the
+ /// Look for arrays of overly padded types. If the padding of the
/// array type exceeds AllowedPad, then generate a report.
void visitVariable(const VarDecl *VD) const {
const ArrayType *ArrTy = VD->getType()->getAsArrayTypeUnsafe();
@@ -237,7 +237,7 @@ public:
};
std::transform(RD->field_begin(), RD->field_end(),
std::back_inserter(Fields), GatherSizesAndAlignments);
- std::sort(Fields.begin(), Fields.end());
+ llvm::sort(Fields.begin(), Fields.end());
// This lets us skip over vptrs and non-virtual bases,
// so that we can just worry about the fields in our object.
// Note that this does cause us to miss some cases where we
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 8caf6df4d970..63f82b275ba2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -154,8 +154,7 @@ void PointerArithChecker::reportPointerArithMisuse(const Expr *E,
return;
ProgramStateRef State = C.getState();
- const MemRegion *Region =
- State->getSVal(E, C.getLocationContext()).getAsRegion();
+ const MemRegion *Region = C.getSVal(E).getAsRegion();
if (!Region)
return;
if (PointedNeeded)
@@ -227,7 +226,7 @@ void PointerArithChecker::checkPostStmt(const CallExpr *CE,
if (AllocFunctions.count(FunI) == 0)
return;
- SVal SV = State->getSVal(CE, C.getLocationContext());
+ SVal SV = C.getSVal(CE);
const MemRegion *Region = SV.getAsRegion();
if (!Region)
return;
@@ -248,7 +247,7 @@ void PointerArithChecker::checkPostStmt(const CXXNewExpr *NE,
AllocKind Kind = getKindOfNewOp(NE, FD);
ProgramStateRef State = C.getState();
- SVal AllocedVal = State->getSVal(NE, C.getLocationContext());
+ SVal AllocedVal = C.getSVal(NE);
const MemRegion *Region = AllocedVal.getAsRegion();
if (!Region)
return;
@@ -263,7 +262,7 @@ void PointerArithChecker::checkPostStmt(const CastExpr *CE,
const Expr *CastedExpr = CE->getSubExpr();
ProgramStateRef State = C.getState();
- SVal CastedVal = State->getSVal(CastedExpr, C.getLocationContext());
+ SVal CastedVal = C.getSVal(CastedExpr);
const MemRegion *Region = CastedVal.getAsRegion();
if (!Region)
@@ -281,7 +280,7 @@ void PointerArithChecker::checkPreStmt(const CastExpr *CE,
const Expr *CastedExpr = CE->getSubExpr();
ProgramStateRef State = C.getState();
- SVal CastedVal = State->getSVal(CastedExpr, C.getLocationContext());
+ SVal CastedVal = C.getSVal(CastedExpr);
const MemRegion *Region = CastedVal.getAsRegion();
if (!Region)
@@ -304,12 +303,15 @@ void PointerArithChecker::checkPreStmt(const UnaryOperator *UOp,
void PointerArithChecker::checkPreStmt(const ArraySubscriptExpr *SubsExpr,
CheckerContext &C) const {
- ProgramStateRef State = C.getState();
- SVal Idx = State->getSVal(SubsExpr->getIdx(), C.getLocationContext());
+ SVal Idx = C.getSVal(SubsExpr->getIdx());
// Indexing with 0 is OK.
if (Idx.isZeroConstant())
return;
+
+ // Indexing vector-type expressions is also OK.
+ if (SubsExpr->getBase()->getType()->isVectorType())
+ return;
reportPointerArithMisuse(SubsExpr->getBase(), C);
}
@@ -324,14 +326,14 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *BOp,
ProgramStateRef State = C.getState();
if (Rhs->getType()->isIntegerType() && Lhs->getType()->isPointerType()) {
- SVal RHSVal = State->getSVal(Rhs, C.getLocationContext());
+ SVal RHSVal = C.getSVal(Rhs);
if (State->isNull(RHSVal).isConstrainedTrue())
return;
reportPointerArithMisuse(Lhs, C, !BOp->isAdditiveOp());
}
// The int += ptr; case is not valid C++.
if (Lhs->getType()->isIntegerType() && Rhs->getType()->isPointerType()) {
- SVal LHSVal = State->getSVal(Lhs, C.getLocationContext());
+ SVal LHSVal = C.getSVal(Lhs);
if (State->isNull(LHSVal).isConstrainedTrue())
return;
reportPointerArithMisuse(Rhs, C);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index 2d33ebc2610d..9aa5348e4c34 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -39,10 +39,8 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
if (B->getOpcode() != BO_Sub)
return;
- ProgramStateRef state = C.getState();
- const LocationContext *LCtx = C.getLocationContext();
- SVal LV = state->getSVal(B->getLHS(), LCtx);
- SVal RV = state->getSVal(B->getRHS(), LCtx);
+ SVal LV = C.getSVal(B->getLHS());
+ SVal RV = C.getSVal(B->getRHS());
const MemRegion *LR = LV.getAsRegion();
const MemRegion *RR = RV.getAsRegion();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index dab29be1c8fb..10ab952e069b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -109,8 +109,6 @@ REGISTER_MAP_WITH_PROGRAMSTATE(DestroyRetVal, const MemRegion *, SymbolRef)
void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const {
- ProgramStateRef state = C.getState();
- const LocationContext *LCtx = C.getLocationContext();
StringRef FName = C.getCalleeName(CE);
if (FName.empty())
return;
@@ -121,34 +119,31 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
if (FName == "pthread_mutex_lock" ||
FName == "pthread_rwlock_rdlock" ||
FName == "pthread_rwlock_wrlock")
- AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
- false, PthreadSemantics);
+ AcquireLock(C, CE, C.getSVal(CE->getArg(0)), false, PthreadSemantics);
else if (FName == "lck_mtx_lock" ||
FName == "lck_rw_lock_exclusive" ||
FName == "lck_rw_lock_shared")
- AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
- false, XNUSemantics);
+ AcquireLock(C, CE, C.getSVal(CE->getArg(0)), false, XNUSemantics);
else if (FName == "pthread_mutex_trylock" ||
FName == "pthread_rwlock_tryrdlock" ||
FName == "pthread_rwlock_trywrlock")
- AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+ AcquireLock(C, CE, C.getSVal(CE->getArg(0)),
true, PthreadSemantics);
else if (FName == "lck_mtx_try_lock" ||
FName == "lck_rw_try_lock_exclusive" ||
FName == "lck_rw_try_lock_shared")
- AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
- true, XNUSemantics);
+ AcquireLock(C, CE, C.getSVal(CE->getArg(0)), true, XNUSemantics);
else if (FName == "pthread_mutex_unlock" ||
FName == "pthread_rwlock_unlock" ||
FName == "lck_mtx_unlock" ||
FName == "lck_rw_done")
- ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
+ ReleaseLock(C, CE, C.getSVal(CE->getArg(0)));
else if (FName == "pthread_mutex_destroy")
- DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx), PthreadSemantics);
+ DestroyLock(C, CE, C.getSVal(CE->getArg(0)), PthreadSemantics);
else if (FName == "lck_mtx_destroy")
- DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx), XNUSemantics);
+ DestroyLock(C, CE, C.getSVal(CE->getArg(0)), XNUSemantics);
else if (FName == "pthread_mutex_init")
- InitLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
+ InitLock(C, CE, C.getSVal(CE->getArg(0)));
}
// When a lock is destroyed, in some semantics(like PthreadSemantics) we are not
@@ -232,7 +227,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
if (sym)
state = resolvePossiblyDestroyedMutex(state, lockR, sym);
- SVal X = state->getSVal(CE, C.getLocationContext());
+ SVal X = C.getSVal(CE);
if (X.isUnknownOrUndef())
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index e47494a3e90b..9c85c0983723 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -555,7 +555,7 @@ public:
}
const RetainSummary *find(IdentifierInfo* II, Selector S) {
- // FIXME: Class method lookup. Right now we dont' have a good way
+ // FIXME: Class method lookup. Right now we don't have a good way
// of going between IdentifierInfo* and the class hierarchy.
MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
@@ -883,21 +883,22 @@ RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
//===----------------------------------------------------------------------===//
static bool isRetain(const FunctionDecl *FD, StringRef FName) {
- return FName.endswith("Retain");
+ return FName.startswith_lower("retain") || FName.endswith_lower("retain");
}
static bool isRelease(const FunctionDecl *FD, StringRef FName) {
- return FName.endswith("Release");
+ return FName.startswith_lower("release") || FName.endswith_lower("release");
}
static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
- return FName.endswith("Autorelease");
+ return FName.startswith_lower("autorelease") ||
+ FName.endswith_lower("autorelease");
}
static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) {
// FIXME: Remove FunctionDecl parameter.
// FIXME: Is it really okay if MakeCollectable isn't a suffix?
- return FName.find("MakeCollectable") != StringRef::npos;
+ return FName.find_lower("MakeCollectable") != StringRef::npos;
}
static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
@@ -1787,8 +1788,7 @@ namespace {
//===---------===//
// Bug Reports. //
//===---------===//
-
- class CFRefReportVisitor : public BugReporterVisitorImpl<CFRefReportVisitor> {
+ class CFRefReportVisitor : public BugReporterVisitor {
protected:
SymbolRef Sym;
const SummaryLogTy &SummaryLog;
@@ -1809,7 +1809,7 @@ namespace {
BugReporterContext &BRC,
BugReport &BR) override;
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
+ std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
BugReport &BR) override;
};
@@ -1820,18 +1820,9 @@ namespace {
const SummaryLogTy &log)
: CFRefReportVisitor(sym, GCEnabled, log) {}
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
+ std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
BugReport &BR) override;
-
- std::unique_ptr<BugReporterVisitor> clone() const override {
- // The curiously-recurring template pattern only works for one level of
- // subclassing. Rather than make a new template base for
- // CFRefReportVisitor, we simply override clone() to do the right thing.
- // This could be trouble someday if BugReporterVisitorImpl is ever
- // used for something else besides a convenient implementation of clone().
- return llvm::make_unique<CFRefLeakReportVisitor>(*this);
- }
};
class CFRefReport : public BugReport {
@@ -1929,6 +1920,14 @@ static bool isNumericLiteralExpression(const Expr *E) {
isa<CXXBoolLiteralExpr>(E);
}
+static Optional<std::string> describeRegion(const MemRegion *MR) {
+ if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
+ return std::string(VR->getDecl()->getName());
+ // Once we support more storage locations for bindings,
+ // this would need to be improved.
+ return None;
+}
+
/// Returns true if this stack frame is for an Objective-C method that is a
/// property getter or setter whose body has been synthesized by the analyzer.
static bool isSynthesizedAccessor(const StackFrameContext *SFC) {
@@ -1969,8 +1968,8 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,
const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
if (isa<ObjCIvarRefExpr>(S) &&
- isSynthesizedAccessor(LCtx->getCurrentStackFrame())) {
- S = LCtx->getCurrentStackFrame()->getCallSite();
+ isSynthesizedAccessor(LCtx->getStackFrame())) {
+ S = LCtx->getStackFrame()->getCallSite();
}
if (isa<ObjCArrayLiteral>(S)) {
@@ -2298,7 +2297,7 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
const VarRegion *VR = R->getBaseRegion()->getAs<VarRegion>();
// Do not show local variables belonging to a function other than
// where the error is reported.
- if (!VR || VR->getStackFrame() == LeakContext->getCurrentStackFrame())
+ if (!VR || VR->getStackFrame() == LeakContext->getStackFrame())
FirstBinding = R;
}
@@ -2356,14 +2355,14 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
InterestingMethodContext);
}
-std::unique_ptr<PathDiagnosticPiece>
+std::shared_ptr<PathDiagnosticPiece>
CFRefReportVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *EndN, BugReport &BR) {
BR.markInteresting(Sym);
return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
}
-std::unique_ptr<PathDiagnosticPiece>
+std::shared_ptr<PathDiagnosticPiece>
CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *EndN, BugReport &BR) {
@@ -2393,9 +2392,9 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
os << "Object leaked: ";
- if (FirstBinding) {
- os << "object allocated and stored into '"
- << FirstBinding->getString() << '\'';
+ Optional<std::string> RegionDescription = describeRegion(FirstBinding);
+ if (RegionDescription) {
+ os << "object allocated and stored into '" << *RegionDescription << '\'';
}
else
os << "allocated object";
@@ -2450,7 +2449,7 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
os << " is not referenced later in this execution path and has a retain "
"count of +" << RV->getCount();
- return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
+ return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
}
void CFRefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
@@ -2513,7 +2512,8 @@ void CFRefLeakReport::deriveAllocLocation(CheckerContext &Ctx,SymbolRef sym) {
UniqueingDecl = AllocNode->getLocationContext()->getDecl();
}
-void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled, bool IncludeAllocationLine) {
+void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled,
+ bool IncludeAllocationLine) {
assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
Description.clear();
llvm::raw_string_ostream os(Description);
@@ -2522,8 +2522,9 @@ void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled, boo
os << "(when using garbage collection) ";
os << "of an object";
- if (AllocBinding) {
- os << " stored into '" << AllocBinding->getString() << '\'';
+ Optional<std::string> RegionDescription = describeRegion(AllocBinding);
+ if (RegionDescription) {
+ os << " stored into '" << *RegionDescription << '\'';
if (IncludeAllocationLine) {
FullSourceLoc SL(AllocStmt->getLocStart(), Ctx.getSourceManager());
os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
@@ -2742,7 +2743,7 @@ public:
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkBeginFunction(CheckerContext &C) const;
- void checkEndFunction(CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
RefVal V, ArgEffect E, RefVal::Kind &hasErr,
@@ -2799,9 +2800,7 @@ void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
return;
ProgramStateRef state = C.getState();
- const BlockDataRegion *R =
- cast<BlockDataRegion>(state->getSVal(BE,
- C.getLocationContext()).getAsRegion());
+ auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
E = R->referenced_vars_end();
@@ -2851,7 +2850,7 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
}
ProgramStateRef state = C.getState();
- SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
+ SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
if (!Sym)
return;
const RefVal* T = getRefBinding(state, Sym);
@@ -2874,7 +2873,7 @@ void RetainCountChecker::processObjCLiterals(CheckerContext &C,
ProgramStateRef state = C.getState();
const ExplodedNode *pred = C.getPredecessor();
for (const Stmt *Child : Ex->children()) {
- SVal V = state->getSVal(Child, pred->getLocationContext());
+ SVal V = pred->getSVal(Child);
if (SymbolRef sym = V.getAsSymbol())
if (const RefVal* T = getRefBinding(state, sym)) {
RefVal::Kind hasErr = (RefVal::Kind) 0;
@@ -2913,10 +2912,9 @@ void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
CheckerContext &C) const {
const ExplodedNode *Pred = C.getPredecessor();
- const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
- if (SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
+ if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) {
QualType ResultTy = Ex->getType();
State = setRefBinding(State, Sym,
RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
@@ -3993,7 +3991,8 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
Ctx.addTransition(state);
}
-void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
+void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &Ctx) const {
ProgramStateRef state = Ctx.getState();
RefBindingsTy B = state->get<RefBindings>();
ExplodedNode *Pred = Ctx.getPredecessor();
@@ -4001,7 +4000,7 @@ void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
// Don't process anything within synthesized bodies.
const LocationContext *LCtx = Pred->getLocationContext();
if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
- assert(!LCtx->inTopFrame());
+ assert(!LCtx->inTopFrame());
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index 19fa0fb193cc..1952715a9b7c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -40,7 +40,7 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
if (!RetE)
return;
- SVal V = state->getSVal(RetE, C.getLocationContext());
+ SVal V = C.getSVal(RetE);
const MemRegion *R = V.getAsRegion();
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
new file mode 100644
index 000000000000..55516a34d1a7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
@@ -0,0 +1,223 @@
+//=- RunLoopAutoreleaseLeakChecker.cpp --------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//
+//===----------------------------------------------------------------------===//
+//
+// A checker for detecting leaks resulting from allocating temporary
+// autoreleased objects before starting the main run loop.
+//
+// Checks for two antipatterns:
+// 1. ObjCMessageExpr followed by [[NSRunLoop mainRunLoop] run] in the same
+// autorelease pool.
+// 2. ObjCMessageExpr followed by [[NSRunLoop mainRunLoop] run] in no
+// autorelease pool.
+//
+// Any temporary objects autoreleased in code called in those expressions
+// will not be deallocated until the program exits, and are effectively leaks.
+//
+//===----------------------------------------------------------------------===//
+//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/ASTMatchers/ASTMatchFinder.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/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+const char * RunLoopBind = "NSRunLoopM";
+const char * RunLoopRunBind = "RunLoopRunM";
+const char * OtherMsgBind = "OtherMessageSentM";
+const char * AutoreleasePoolBind = "AutoreleasePoolM";
+const char * OtherStmtAutoreleasePoolBind = "OtherAutoreleasePoolM";
+
+class RunLoopAutoreleaseLeakChecker : public Checker<check::ASTCodeBody> {
+
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+
+};
+
+} // end anonymous namespace
+
+
+using TriBoolTy = Optional<bool>;
+using MemoizationMapTy = llvm::DenseMap<const Stmt *, Optional<TriBoolTy>>;
+
+static TriBoolTy
+seenBeforeRec(const Stmt *Parent, const Stmt *A, const Stmt *B,
+ MemoizationMapTy &Memoization) {
+ for (const Stmt *C : Parent->children()) {
+ if (!C) continue;
+
+ if (C == A)
+ return true;
+
+ if (C == B)
+ return false;
+
+ Optional<TriBoolTy> &Cached = Memoization[C];
+ if (!Cached)
+ Cached = seenBeforeRec(C, A, B, Memoization);
+
+ if (Cached->hasValue())
+ return Cached->getValue();
+ }
+
+ return None;
+}
+
+/// \return Whether {@code A} occurs before {@code B} in traversal of
+/// {@code Parent}.
+/// Conceptually a very incomplete/unsound approximation of happens-before
+/// relationship (A is likely to be evaluated before B),
+/// but useful enough in this case.
+static bool seenBefore(const Stmt *Parent, const Stmt *A, const Stmt *B) {
+ MemoizationMapTy Memoization;
+ TriBoolTy Val = seenBeforeRec(Parent, A, B, Memoization);
+ return Val.getValue();
+}
+
+static void emitDiagnostics(BoundNodes &Match,
+ const Decl *D,
+ BugReporter &BR,
+ AnalysisManager &AM,
+ const RunLoopAutoreleaseLeakChecker *Checker) {
+
+ assert(D->hasBody());
+ const Stmt *DeclBody = D->getBody();
+
+ AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
+
+ const auto *ME = Match.getNodeAs<ObjCMessageExpr>(OtherMsgBind);
+ assert(ME);
+
+ const auto *AP =
+ Match.getNodeAs<ObjCAutoreleasePoolStmt>(AutoreleasePoolBind);
+ const auto *OAP =
+ Match.getNodeAs<ObjCAutoreleasePoolStmt>(OtherStmtAutoreleasePoolBind);
+ bool HasAutoreleasePool = (AP != nullptr);
+
+ const auto *RL = Match.getNodeAs<ObjCMessageExpr>(RunLoopBind);
+ const auto *RLR = Match.getNodeAs<Stmt>(RunLoopRunBind);
+ assert(RLR && "Run loop launch not found");
+ assert(ME != RLR);
+
+ // Launch of run loop occurs before the message-sent expression is seen.
+ if (seenBefore(DeclBody, RLR, ME))
+ return;
+
+ if (HasAutoreleasePool && (OAP != AP))
+ return;
+
+ PathDiagnosticLocation Location = PathDiagnosticLocation::createBegin(
+ ME, BR.getSourceManager(), ADC);
+ SourceRange Range = ME->getSourceRange();
+
+ BR.EmitBasicReport(ADC->getDecl(), Checker,
+ /*Name=*/"Memory leak inside autorelease pool",
+ /*Category=*/"Memory",
+ /*Name=*/
+ (Twine("Temporary objects allocated in the") +
+ " autorelease pool " +
+ (HasAutoreleasePool ? "" : "of last resort ") +
+ "followed by the launch of " +
+ (RL ? "main run loop " : "xpc_main ") +
+ "may never get released; consider moving them to a "
+ "separate autorelease pool")
+ .str(),
+ Location, Range);
+}
+
+static StatementMatcher getRunLoopRunM(StatementMatcher Extra = anything()) {
+ StatementMatcher MainRunLoopM =
+ objcMessageExpr(hasSelector("mainRunLoop"),
+ hasReceiverType(asString("NSRunLoop")),
+ Extra)
+ .bind(RunLoopBind);
+
+ StatementMatcher MainRunLoopRunM = objcMessageExpr(hasSelector("run"),
+ hasReceiver(MainRunLoopM),
+ Extra).bind(RunLoopRunBind);
+
+ StatementMatcher XPCRunM =
+ callExpr(callee(functionDecl(hasName("xpc_main")))).bind(RunLoopRunBind);
+ return anyOf(MainRunLoopRunM, XPCRunM);
+}
+
+static StatementMatcher getOtherMessageSentM(StatementMatcher Extra = anything()) {
+ return objcMessageExpr(unless(anyOf(equalsBoundNode(RunLoopBind),
+ equalsBoundNode(RunLoopRunBind))),
+ Extra)
+ .bind(OtherMsgBind);
+}
+
+static void
+checkTempObjectsInSamePool(const Decl *D, AnalysisManager &AM, BugReporter &BR,
+ const RunLoopAutoreleaseLeakChecker *Chkr) {
+ StatementMatcher RunLoopRunM = getRunLoopRunM();
+ StatementMatcher OtherMessageSentM = getOtherMessageSentM(
+ hasAncestor(autoreleasePoolStmt().bind(OtherStmtAutoreleasePoolBind)));
+
+ StatementMatcher RunLoopInAutorelease =
+ autoreleasePoolStmt(
+ hasDescendant(RunLoopRunM),
+ hasDescendant(OtherMessageSentM)).bind(AutoreleasePoolBind);
+
+ DeclarationMatcher GroupM = decl(hasDescendant(RunLoopInAutorelease));
+
+ auto Matches = match(GroupM, *D, AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, D, BR, AM, Chkr);
+}
+
+static void
+checkTempObjectsInNoPool(const Decl *D, AnalysisManager &AM, BugReporter &BR,
+ const RunLoopAutoreleaseLeakChecker *Chkr) {
+
+ auto NoPoolM = unless(hasAncestor(autoreleasePoolStmt()));
+
+ StatementMatcher RunLoopRunM = getRunLoopRunM(NoPoolM);
+ StatementMatcher OtherMessageSentM = getOtherMessageSentM(NoPoolM);
+
+ DeclarationMatcher GroupM = functionDecl(
+ isMain(),
+ hasDescendant(RunLoopRunM),
+ hasDescendant(OtherMessageSentM)
+ );
+
+ auto Matches = match(GroupM, *D, AM.getASTContext());
+
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, D, BR, AM, Chkr);
+
+}
+
+void RunLoopAutoreleaseLeakChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+ checkTempObjectsInSamePool(D, AM, BR, this);
+ checkTempObjectsInNoPool(D, AM, BR, this);
+}
+
+void ento::registerRunLoopAutoreleaseLeakChecker(CheckerManager &mgr) {
+ mgr.registerChecker<RunLoopAutoreleaseLeakChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 25975628c553..e7a20fa03a4a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -47,7 +47,7 @@ public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
- void checkEndFunction(CheckerContext &Ctx) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
private:
void checkReturnedBlockCaptures(const BlockDataRegion &B,
@@ -120,7 +120,7 @@ bool StackAddrEscapeChecker::isArcManagedBlock(const MemRegion *R,
bool StackAddrEscapeChecker::isNotInCurrentFrame(const MemRegion *R,
CheckerContext &C) {
const StackSpaceRegion *S = cast<StackSpaceRegion>(R->getMemorySpace());
- return S->getStackFrame() != C.getLocationContext()->getCurrentStackFrame();
+ return S->getStackFrame() != C.getStackFrame();
}
bool StackAddrEscapeChecker::isSemaphoreCaptured(const BlockDecl &B) const {
@@ -129,7 +129,7 @@ bool StackAddrEscapeChecker::isSemaphoreCaptured(const BlockDecl &B) const {
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 true;
}
return false;
}
@@ -175,9 +175,9 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
// 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
+ // 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;
@@ -255,8 +255,7 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
return;
RetE = RetE->IgnoreParens();
- const LocationContext *LCtx = C.getLocationContext();
- SVal V = C.getState()->getSVal(RetE, LCtx);
+ SVal V = C.getSVal(RetE);
const MemRegion *R = V.getAsRegion();
if (!R)
return;
@@ -264,7 +263,7 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
if (const BlockDataRegion *B = dyn_cast<BlockDataRegion>(R))
checkReturnedBlockCaptures(*B, C);
- if (!isa<StackSpaceRegion>(R->getMemorySpace()) ||
+ if (!isa<StackSpaceRegion>(R->getMemorySpace()) ||
isNotInCurrentFrame(R, C) || isArcManagedBlock(R, C))
return;
@@ -288,7 +287,8 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
EmitStackError(C, R, RetE);
}
-void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
+void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &Ctx) const {
if (!ChecksEnabled[CK_StackAddrEscapeChecker])
return;
@@ -304,8 +304,7 @@ void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
public:
SmallVector<std::pair<const MemRegion *, const MemRegion *>, 10> V;
- CallBack(CheckerContext &CC)
- : Ctx(CC), CurSFC(CC.getLocationContext()->getCurrentStackFrame()) {}
+ CallBack(CheckerContext &CC) : Ctx(CC), CurSFC(CC.getStackFrame()) {}
bool HandleBinding(StoreManager &SMgr, Store S, const MemRegion *Region,
SVal Val) override {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 915514b42133..d77975559e3f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -242,22 +242,19 @@ void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const {
void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(3)), state, C))
return;
}
void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(3)), state, C))
return;
}
void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!(state = CheckNullStream(state->getSVal(CE->getArg(0),
- C.getLocationContext()), state, C)))
+ if (!(state = CheckNullStream(C.getSVal(CE->getArg(0)), state, C)))
return;
// Check the legality of the 'whence' argument of 'fseek'.
SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext());
@@ -283,57 +280,49 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
- if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
- state, C))
+ if (!CheckNullStream(C.getSVal(CE->getArg(0)), state, C))
return;
}
@@ -363,8 +352,7 @@ ProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state,
ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
ProgramStateRef state,
CheckerContext &C) const {
- SymbolRef Sym =
- state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol();
+ SymbolRef Sym = C.getSVal(CE->getArg(0)).getAsSymbol();
if (!Sym)
return state;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index 5268bbf5562e..f4c0edbab3f0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
@@ -55,7 +55,7 @@ public:
}
};
-class DivisionBRVisitor : public BugReporterVisitorImpl<DivisionBRVisitor> {
+class DivisionBRVisitor : public BugReporterVisitor {
private:
SymbolRef ZeroSymbol;
const StackFrameContext *SFC;
@@ -85,7 +85,7 @@ class TestAfterDivZeroChecker
public:
void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
- void checkEndFunction(CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
void setDivZeroMap(SVal Var, CheckerContext &C) const;
bool hasDivZeroMap(SVal Var, const CheckerContext &C) const;
bool isZero(SVal S, CheckerContext &C) const;
@@ -114,8 +114,7 @@ DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred,
if (!E)
return nullptr;
- ProgramStateRef State = Succ->getState();
- SVal S = State->getSVal(E, Succ->getLocationContext());
+ SVal S = Succ->getSVal(E);
if (ZeroSymbol == S.getAsSymbol() && SFC == Succ->getStackFrame()) {
Satisfied = true;
@@ -181,7 +180,8 @@ void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
}
}
-void TestAfterDivZeroChecker::checkEndFunction(CheckerContext &C) const {
+void TestAfterDivZeroChecker::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &C) const {
ProgramStateRef State = C.getState();
DivZeroMapTy DivZeroes = State->get<DivZeroMap>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
index 8ad962875b06..ee185b813611 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
@@ -30,7 +30,7 @@ class TraversalDumper : public Checker< check::BranchCondition,
public:
void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
void checkBeginFunction(CheckerContext &C) const;
- void checkEndFunction(CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
};
}
@@ -56,7 +56,8 @@ void TraversalDumper::checkBeginFunction(CheckerContext &C) const {
llvm::outs() << "--BEGIN FUNCTION--\n";
}
-void TraversalDumper::checkEndFunction(CheckerContext &C) const {
+void TraversalDumper::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &C) const {
llvm::outs() << "--END FUNCTION--\n";
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
new file mode 100644
index 000000000000..f3d68014224d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
@@ -0,0 +1,90 @@
+//== TrustNonnullChecker.cpp - Checker for trusting annotations -*- 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 methods annotated with _Nonnull
+// which come from system headers actually return a non-null pointer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.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/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class TrustNonnullChecker : public Checker<check::PostCall> {
+private:
+ /// \returns Whether we trust the result of the method call to be
+ /// a non-null pointer.
+ bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const {
+ QualType ExprRetType = Call.getResultType();
+ if (!ExprRetType->isAnyPointerType())
+ return false;
+
+ if (getNullabilityAnnotation(ExprRetType) == Nullability::Nonnull)
+ return true;
+
+ // The logic for ObjC instance method calls is more complicated,
+ // as the return value is nil when the receiver is nil.
+ if (!isa<ObjCMethodCall>(&Call))
+ return false;
+
+ const auto *MCall = cast<ObjCMethodCall>(&Call);
+ const ObjCMethodDecl *MD = MCall->getDecl();
+
+ // Distrust protocols.
+ if (isa<ObjCProtocolDecl>(MD->getDeclContext()))
+ return false;
+
+ QualType DeclRetType = MD->getReturnType();
+ if (getNullabilityAnnotation(DeclRetType) != Nullability::Nonnull)
+ return false;
+
+ // For class messages it is sufficient for the declaration to be
+ // annotated _Nonnull.
+ if (!MCall->isInstanceMessage())
+ return true;
+
+ // Alternatively, the analyzer could know that the receiver is not null.
+ SVal Receiver = MCall->getReceiverSVal();
+ ConditionTruthVal TV = C.getState()->isNonNull(Receiver);
+ if (TV.isConstrainedTrue())
+ return true;
+
+ return false;
+ }
+
+public:
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
+ // Only trust annotations for system headers for non-protocols.
+ if (!Call.isInSystemHeader())
+ return;
+
+ ProgramStateRef State = C.getState();
+
+ if (isNonNullPtr(Call, C))
+ if (auto L = Call.getReturnValue().getAs<Loc>())
+ State = State->assume(*L, /*Assumption=*/true);
+
+ C.addTransition(State);
+ }
+};
+
+} // end empty namespace
+
+
+void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<TrustNonnullChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index 0a274292aa39..934ee63318fa 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -59,7 +59,7 @@ public:
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
CheckerContext &Ctx) const {
- SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
+ SVal X = Ctx.getSVal(Condition);
if (X.isUndef()) {
// Generate a sink node, which implicitly marks both outgoing branches as
// infeasible.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 17fe8610da06..6a93c10c7644 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -55,9 +55,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
return;
ProgramStateRef state = C.getState();
- const BlockDataRegion *R =
- cast<BlockDataRegion>(state->getSVal(BE,
- C.getLocationContext()).getAsRegion());
+ auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
E = R->referenced_vars_end();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 172ce346f1ba..b9a93bedca2e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -37,12 +37,11 @@ public:
static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex) {
ProgramStateRef state = C.getState();
- const LocationContext *LCtx = C.getLocationContext();
if (!isa<ArraySubscriptExpr>(Ex))
return false;
- SVal Loc = state->getSVal(Ex, LCtx);
+ SVal Loc = C.getSVal(Ex);
if (!Loc.isValid())
return false;
@@ -64,11 +63,18 @@ static bool isShiftOverflow(const BinaryOperator *B, CheckerContext &C) {
B->getRHS(), C.getASTContext().getIntWidth(B->getLHS()->getType()));
}
+static bool isLeftShiftResultUnrepresentable(const BinaryOperator *B,
+ CheckerContext &C) {
+ SValBuilder &SB = C.getSValBuilder();
+ ProgramStateRef State = C.getState();
+ const llvm::APSInt *LHS = SB.getKnownValue(State, C.getSVal(B->getLHS()));
+ const llvm::APSInt *RHS = SB.getKnownValue(State, C.getSVal(B->getRHS()));
+ return (unsigned)RHS->getZExtValue() > LHS->countLeadingZeros();
+}
+
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
CheckerContext &C) const {
- ProgramStateRef state = C.getState();
- const LocationContext *LCtx = C.getLocationContext();
- if (state->getSVal(B, LCtx).isUndef()) {
+ if (C.getSVal(B).isUndef()) {
// Do not report assignments of uninitialized values inside swap functions.
// This should allow to swap partially uninitialized structs
@@ -92,11 +98,11 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
const Expr *Ex = nullptr;
bool isLeft = true;
- if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
+ if (C.getSVal(B->getLHS()).isUndef()) {
Ex = B->getLHS()->IgnoreParenCasts();
isLeft = true;
}
- else if (state->getSVal(B->getRHS(), LCtx).isUndef()) {
+ else if (C.getSVal(B->getRHS()).isUndef()) {
Ex = B->getRHS()->IgnoreParenCasts();
isLeft = false;
}
@@ -141,6 +147,19 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
C.isNegative(B->getLHS())) {
OS << "The result of the left shift is undefined because the left "
"operand is negative";
+ } else if (B->getOpcode() == BinaryOperatorKind::BO_Shl &&
+ isLeftShiftResultUnrepresentable(B, C)) {
+ ProgramStateRef State = C.getState();
+ SValBuilder &SB = C.getSValBuilder();
+ const llvm::APSInt *LHS =
+ SB.getKnownValue(State, C.getSVal(B->getLHS()));
+ const llvm::APSInt *RHS =
+ SB.getKnownValue(State, C.getSVal(B->getRHS()));
+ OS << "The result of the left shift is undefined due to shifting \'"
+ << LHS->getSExtValue() << "\' by \'" << RHS->getZExtValue()
+ << "\', which is unrepresentable in the unsigned version of "
+ << "the return type \'" << B->getLHS()->getType().getAsString()
+ << "\'";
} else {
OS << "The result of the '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index c3dcf1fac197..2ef6855ba6b7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -51,17 +51,20 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
if (!N)
return;
- const char *str = "Assigned value is garbage or undefined";
-
+ static const char *const DefaultMsg =
+ "Assigned value is garbage or undefined";
if (!BT)
- BT.reset(new BuiltinBug(this, str));
+ BT.reset(new BuiltinBug(this, DefaultMsg));
// Generate a report for this bug.
+ llvm::SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+
const Expr *ex = nullptr;
while (StoreE) {
if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) {
- str = "The expression is an uninitialized value. "
+ OS << "The expression is an uninitialized value. "
"The computed value will also be garbage";
ex = U->getSubExpr();
@@ -70,9 +73,8 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
if (B->isCompoundAssignmentOp()) {
- ProgramStateRef state = C.getState();
- if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
- str = "The left expression of the compound assignment is an "
+ if (C.getSVal(B->getLHS()).isUndef()) {
+ OS << "The left expression of the compound assignment is an "
"uninitialized value. The computed value will also be garbage";
ex = B->getLHS();
break;
@@ -88,10 +90,26 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
ex = VD->getInit();
}
+ if (const auto *CD =
+ dyn_cast<CXXConstructorDecl>(C.getStackFrame()->getDecl())) {
+ if (CD->isImplicit()) {
+ for (auto I : CD->inits()) {
+ if (I->getInit()->IgnoreImpCasts() == StoreE) {
+ OS << "Value assigned to field '" << I->getMember()->getName()
+ << "' in implicit constructor is garbage or undefined";
+ break;
+ }
+ }
+ }
+ }
+
break;
}
- auto R = llvm::make_unique<BugReport>(*BT, str, N);
+ if (OS.str().empty())
+ OS << DefaultMsg;
+
+ auto R = llvm::make_unique<BugReport>(*BT, OS.str(), N);
if (ex) {
R->addRange(ex->getSourceRange());
bugreporter::trackNullOrUndefValue(N, ex, *R);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
new file mode 100644
index 000000000000..398228a9d887
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
@@ -0,0 +1,688 @@
+//===----- UninitializedObjectChecker.cpp ------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a checker that reports uninitialized fields in objects
+// created after a constructor call.
+//
+// This checker has two options:
+// - "Pedantic" (boolean). If its not set or is set to false, the checker
+// won't emit warnings for objects that don't have at least one initialized
+// field. This may be set with
+//
+// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`.
+//
+// - "NotesAsWarnings" (boolean). If set to true, the checker will emit a
+// warning for each uninitalized field, as opposed to emitting one warning
+// per constructor call, and listing the uninitialized fields that belongs
+// to it in notes. Defaults to false.
+//
+// `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include <algorithm>
+
+using namespace clang;
+using namespace clang::ento;
+
+namespace {
+
+class UninitializedObjectChecker : public Checker<check::EndFunction> {
+ std::unique_ptr<BuiltinBug> BT_uninitField;
+
+public:
+ // These fields will be initialized when registering the checker.
+ bool IsPedantic;
+ bool ShouldConvertNotesToWarnings;
+
+ UninitializedObjectChecker()
+ : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
+};
+
+/// Represents a field chain. A field chain is a vector of fields where the
+/// first element of the chain is the object under checking (not stored), and
+/// every other element is a field, and the element that precedes it is the
+/// object that contains it.
+///
+/// Note that this class is immutable, and new fields may only be added through
+/// constructor calls.
+class FieldChainInfo {
+ using FieldChain = llvm::ImmutableList<const FieldRegion *>;
+
+ FieldChain Chain;
+
+ const bool IsDereferenced = false;
+
+public:
+ FieldChainInfo() = default;
+
+ FieldChainInfo(const FieldChainInfo &Other, const bool IsDereferenced)
+ : Chain(Other.Chain), IsDereferenced(IsDereferenced) {}
+
+ FieldChainInfo(const FieldChainInfo &Other, const FieldRegion *FR,
+ const bool IsDereferenced = false);
+
+ bool contains(const FieldRegion *FR) const { return Chain.contains(FR); }
+ bool isPointer() const;
+
+ /// If this is a fieldchain whose last element is an uninitialized region of a
+ /// pointer type, `IsDereferenced` will store whether the pointer itself or
+ /// the pointee is uninitialized.
+ bool isDereferenced() const;
+ const FieldDecl *getEndOfChain() const;
+ void print(llvm::raw_ostream &Out) const;
+
+private:
+ /// Prints every element except the last to `Out`. Since ImmutableLists store
+ /// elements in reverse order, and have no reverse iterators, we use a
+ /// recursive function to print the fieldchain correctly. The last element in
+ /// the chain is to be printed by `print`.
+ static void printTail(llvm::raw_ostream &Out,
+ const llvm::ImmutableListImpl<const FieldRegion *> *L);
+ friend struct FieldChainInfoComparator;
+};
+
+struct FieldChainInfoComparator {
+ bool operator()(const FieldChainInfo &lhs, const FieldChainInfo &rhs) const {
+ assert(!lhs.Chain.isEmpty() && !rhs.Chain.isEmpty() &&
+ "Attempted to store an empty fieldchain!");
+ return *lhs.Chain.begin() < *rhs.Chain.begin();
+ }
+};
+
+using UninitFieldSet = std::set<FieldChainInfo, FieldChainInfoComparator>;
+
+/// Searches for and stores uninitialized fields in a non-union object.
+class FindUninitializedFields {
+ ProgramStateRef State;
+ const TypedValueRegion *const ObjectR;
+
+ const bool IsPedantic;
+ bool IsAnyFieldInitialized = false;
+
+ UninitFieldSet UninitFields;
+
+public:
+ FindUninitializedFields(ProgramStateRef State,
+ const TypedValueRegion *const R, bool IsPedantic);
+ const UninitFieldSet &getUninitFields();
+
+private:
+ /// Adds a FieldChainInfo object to UninitFields. Return true if an insertion
+ /// took place.
+ bool addFieldToUninits(FieldChainInfo LocalChain);
+
+ // For the purposes of this checker, we'll regard the object under checking as
+ // a directed tree, where
+ // * the root is the object under checking
+ // * every node is an object that is
+ // - a union
+ // - a non-union record
+ // - a pointer/reference
+ // - an array
+ // - of a primitive type, which we'll define later in a helper function.
+ // * the parent of each node is the object that contains it
+ // * every leaf is an array, a primitive object, a nullptr or an undefined
+ // pointer.
+ //
+ // Example:
+ //
+ // struct A {
+ // struct B {
+ // int x, y = 0;
+ // };
+ // B b;
+ // int *iptr = new int;
+ // B* bptr;
+ //
+ // A() {}
+ // };
+ //
+ // The directed tree:
+ //
+ // ->x
+ // /
+ // ->b--->y
+ // /
+ // A-->iptr->(int value)
+ // \
+ // ->bptr
+ //
+ // From this we'll construct a vector of fieldchains, where each fieldchain
+ // represents an uninitialized field. An uninitialized field may be a
+ // primitive object, a pointer, a pointee or a union without a single
+ // initialized field.
+ // In the above example, for the default constructor call we'll end up with
+ // these fieldchains:
+ //
+ // this->b.x
+ // this->iptr (pointee uninit)
+ // this->bptr (pointer uninit)
+ //
+ // We'll traverse each node of the above graph with the appropiate one of
+ // these methods:
+
+ /// This method checks a region of a union object, and returns true if no
+ /// field is initialized within the region.
+ bool isUnionUninit(const TypedValueRegion *R);
+
+ /// This method checks a region of a non-union object, and returns true if
+ /// an uninitialized field is found within the region.
+ bool isNonUnionUninit(const TypedValueRegion *R, FieldChainInfo LocalChain);
+
+ /// This method checks a region of a pointer or reference object, and returns
+ /// true if the ptr/ref object itself or any field within the pointee's region
+ /// is uninitialized.
+ bool isPointerOrReferenceUninit(const FieldRegion *FR,
+ FieldChainInfo LocalChain);
+
+ /// This method returns true if the value of a primitive object is
+ /// uninitialized.
+ bool isPrimitiveUninit(const SVal &V);
+
+ // Note that we don't have a method for arrays -- the elements of an array are
+ // often left uninitialized intentionally even when it is of a C++ record
+ // type, so we'll assume that an array is always initialized.
+ // TODO: Add a support for nonloc::LocAsInteger.
+};
+
+} // end of anonymous namespace
+
+// Static variable instantionations.
+
+static llvm::ImmutableListFactory<const FieldRegion *> Factory;
+
+// Utility function declarations.
+
+/// Returns the object that was constructed by CtorDecl, or None if that isn't
+/// possible.
+static Optional<nonloc::LazyCompoundVal>
+getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context);
+
+/// Checks whether the constructor under checking is called by another
+/// constructor.
+static bool isCalledByConstructor(const CheckerContext &Context);
+
+/// Returns whether FD can be (transitively) dereferenced to a void pointer type
+/// (void*, void**, ...). The type of the region behind a void pointer isn't
+/// known, and thus FD can not be analyzed.
+static bool isVoidPointer(const FieldDecl *FD);
+
+/// Returns true if T is a primitive type. We defined this type so that for
+/// objects that we'd only like analyze as much as checking whether their
+/// value is undefined or not, such as ints and doubles, can be analyzed with
+/// ease. This also helps ensuring that every special field type is handled
+/// correctly.
+static bool isPrimitiveType(const QualType &T) {
+ return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType();
+}
+
+/// Constructs a note message for a given FieldChainInfo object.
+static void printNoteMessage(llvm::raw_ostream &Out,
+ const FieldChainInfo &Chain);
+
+/// Returns with Field's name. This is a helper function to get the correct name
+/// even if Field is a captured lambda variable.
+static StringRef getVariableName(const FieldDecl *Field);
+
+//===----------------------------------------------------------------------===//
+// Methods for UninitializedObjectChecker.
+//===----------------------------------------------------------------------===//
+
+void UninitializedObjectChecker::checkEndFunction(
+ const ReturnStmt *RS, CheckerContext &Context) const {
+
+ const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
+ Context.getLocationContext()->getDecl());
+ if (!CtorDecl)
+ return;
+
+ if (!CtorDecl->isUserProvided())
+ return;
+
+ if (CtorDecl->getParent()->isUnion())
+ return;
+
+ // This avoids essentially the same error being reported multiple times.
+ if (isCalledByConstructor(Context))
+ return;
+
+ Optional<nonloc::LazyCompoundVal> Object = getObjectVal(CtorDecl, Context);
+ if (!Object)
+ return;
+
+ FindUninitializedFields F(Context.getState(), Object->getRegion(),
+ IsPedantic);
+
+ const UninitFieldSet &UninitFields = F.getUninitFields();
+
+ if (UninitFields.empty())
+ return;
+
+ // There are uninitialized fields in the record.
+
+ ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState());
+ if (!Node)
+ return;
+
+ PathDiagnosticLocation LocUsedForUniqueing;
+ const Stmt *CallSite = Context.getStackFrame()->getCallSite();
+ if (CallSite)
+ LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
+ CallSite, Context.getSourceManager(), Node->getLocationContext());
+
+ // For Plist consumers that don't support notes just yet, we'll convert notes
+ // to warnings.
+ if (ShouldConvertNotesToWarnings) {
+ for (const auto &Chain : UninitFields) {
+ SmallString<100> WarningBuf;
+ llvm::raw_svector_ostream WarningOS(WarningBuf);
+
+ printNoteMessage(WarningOS, Chain);
+
+ auto Report = llvm::make_unique<BugReport>(
+ *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
+ Node->getLocationContext()->getDecl());
+ Context.emitReport(std::move(Report));
+ }
+ return;
+ }
+
+ SmallString<100> WarningBuf;
+ llvm::raw_svector_ostream WarningOS(WarningBuf);
+ WarningOS << UninitFields.size() << " uninitialized field"
+ << (UninitFields.size() == 1 ? "" : "s")
+ << " at the end of the constructor call";
+
+ auto Report = llvm::make_unique<BugReport>(
+ *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
+ Node->getLocationContext()->getDecl());
+
+ for (const auto &Chain : UninitFields) {
+ SmallString<200> NoteBuf;
+ llvm::raw_svector_ostream NoteOS(NoteBuf);
+
+ printNoteMessage(NoteOS, Chain);
+
+ Report->addNote(NoteOS.str(),
+ PathDiagnosticLocation::create(Chain.getEndOfChain(),
+ Context.getSourceManager()));
+ }
+ Context.emitReport(std::move(Report));
+}
+
+//===----------------------------------------------------------------------===//
+// Methods for FindUninitializedFields.
+//===----------------------------------------------------------------------===//
+
+FindUninitializedFields::FindUninitializedFields(
+ ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic)
+ : State(State), ObjectR(R), IsPedantic(IsPedantic) {}
+
+const UninitFieldSet &FindUninitializedFields::getUninitFields() {
+ isNonUnionUninit(ObjectR, FieldChainInfo());
+
+ if (!IsPedantic && !IsAnyFieldInitialized)
+ UninitFields.clear();
+
+ return UninitFields;
+}
+
+bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) {
+ if (State->getStateManager().getContext().getSourceManager().isInSystemHeader(
+ Chain.getEndOfChain()->getLocation()))
+ return false;
+
+ return UninitFields.insert(Chain).second;
+}
+
+bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
+ FieldChainInfo LocalChain) {
+ assert(R->getValueType()->isRecordType() &&
+ !R->getValueType()->isUnionType() &&
+ "This method only checks non-union record objects!");
+
+ const RecordDecl *RD =
+ R->getValueType()->getAs<RecordType>()->getDecl()->getDefinition();
+ assert(RD && "Referred record has no definition");
+
+ bool ContainsUninitField = false;
+
+ // Are all of this non-union's fields initialized?
+ for (const FieldDecl *I : RD->fields()) {
+
+ const auto FieldVal =
+ State->getLValue(I, loc::MemRegionVal(R)).castAs<loc::MemRegionVal>();
+ const auto *FR = FieldVal.getRegionAs<FieldRegion>();
+ QualType T = I->getType();
+
+ // If LocalChain already contains FR, then we encountered a cyclic
+ // reference. In this case, region FR is already under checking at an
+ // earlier node in the directed tree.
+ if (LocalChain.contains(FR))
+ return false;
+
+ if (T->isStructureOrClassType()) {
+ if (isNonUnionUninit(FR, {LocalChain, FR}))
+ ContainsUninitField = true;
+ continue;
+ }
+
+ if (T->isUnionType()) {
+ if (isUnionUninit(FR)) {
+ if (addFieldToUninits({LocalChain, FR}))
+ ContainsUninitField = true;
+ } else
+ IsAnyFieldInitialized = true;
+ continue;
+ }
+
+ if (T->isArrayType()) {
+ IsAnyFieldInitialized = true;
+ continue;
+ }
+
+ if (T->isPointerType() || T->isReferenceType()) {
+ if (isPointerOrReferenceUninit(FR, LocalChain))
+ ContainsUninitField = true;
+ continue;
+ }
+
+ if (isPrimitiveType(T)) {
+ SVal V = State->getSVal(FieldVal);
+
+ if (isPrimitiveUninit(V)) {
+ if (addFieldToUninits({LocalChain, FR}))
+ ContainsUninitField = true;
+ }
+ continue;
+ }
+
+ llvm_unreachable("All cases are handled!");
+ }
+
+ // Checking bases.
+ // FIXME: As of now, because of `isCalledByConstructor`, objects whose type
+ // is a descendant of another type will emit warnings for uninitalized
+ // inherited members.
+ // This is not the only way to analyze bases of an object -- if we didn't
+ // filter them out, and didn't analyze the bases, this checker would run for
+ // each base of the object in order of base initailization and in theory would
+ // find every uninitalized field. This approach could also make handling
+ // diamond inheritances more easily.
+ //
+ // This rule (that a descendant type's cunstructor is responsible for
+ // initializing inherited data members) is not obvious, and should it should
+ // be.
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ if (!CXXRD)
+ return ContainsUninitField;
+
+ for (const CXXBaseSpecifier &BaseSpec : CXXRD->bases()) {
+ const auto *BaseRegion = State->getLValue(BaseSpec, R)
+ .castAs<loc::MemRegionVal>()
+ .getRegionAs<TypedValueRegion>();
+
+ if (isNonUnionUninit(BaseRegion, LocalChain))
+ ContainsUninitField = true;
+ }
+
+ return ContainsUninitField;
+}
+
+bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) {
+ assert(R->getValueType()->isUnionType() &&
+ "This method only checks union objects!");
+ // TODO: Implement support for union fields.
+ return false;
+}
+
+// Note that pointers/references don't contain fields themselves, so in this
+// function we won't add anything to LocalChain.
+bool FindUninitializedFields::isPointerOrReferenceUninit(
+ const FieldRegion *FR, FieldChainInfo LocalChain) {
+
+ assert((FR->getDecl()->getType()->isPointerType() ||
+ FR->getDecl()->getType()->isReferenceType()) &&
+ "This method only checks pointer/reference objects!");
+
+ SVal V = State->getSVal(FR);
+
+ if (V.isUnknown() || V.isZeroConstant()) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ if (V.isUndef()) {
+ return addFieldToUninits({LocalChain, FR});
+ }
+
+ const FieldDecl *FD = FR->getDecl();
+
+ // TODO: The dynamic type of a void pointer may be retrieved with
+ // `getDynamicTypeInfo`.
+ if (isVoidPointer(FD)) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ assert(V.getAs<Loc>() && "V should be Loc at this point!");
+
+ // At this point the pointer itself is initialized and points to a valid
+ // location, we'll now check the pointee.
+ SVal DerefdV = State->getSVal(V.castAs<Loc>());
+
+ // TODO: Dereferencing should be done according to the dynamic type.
+ while (Optional<Loc> L = DerefdV.getAs<Loc>()) {
+ DerefdV = State->getSVal(*L);
+ }
+
+ // If V is a pointer pointing to a record type.
+ if (Optional<nonloc::LazyCompoundVal> RecordV =
+ DerefdV.getAs<nonloc::LazyCompoundVal>()) {
+
+ const TypedValueRegion *R = RecordV->getRegion();
+
+ // We can't reason about symbolic regions, assume its initialized.
+ // Note that this also avoids a potential infinite recursion, because
+ // constructors for list-like classes are checked without being called, and
+ // the Static Analyzer will construct a symbolic region for Node *next; or
+ // similar code snippets.
+ if (R->getSymbolicBase()) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ const QualType T = R->getValueType();
+
+ if (T->isStructureOrClassType())
+ return isNonUnionUninit(R, {LocalChain, FR});
+
+ if (T->isUnionType()) {
+ if (isUnionUninit(R)) {
+ return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true});
+ } else {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+ }
+
+ if (T->isArrayType()) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ llvm_unreachable("All cases are handled!");
+ }
+
+ // TODO: If possible, it should be asserted that the DerefdV at this point is
+ // primitive.
+
+ if (isPrimitiveUninit(DerefdV))
+ return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true});
+
+ IsAnyFieldInitialized = true;
+ return false;
+}
+
+bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) {
+ if (V.isUndef())
+ return true;
+
+ IsAnyFieldInitialized = true;
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods for FieldChainInfo.
+//===----------------------------------------------------------------------===//
+
+FieldChainInfo::FieldChainInfo(const FieldChainInfo &Other,
+ const FieldRegion *FR, const bool IsDereferenced)
+ : FieldChainInfo(Other, IsDereferenced) {
+ assert(!contains(FR) && "Can't add a field that is already a part of the "
+ "fieldchain! Is this a cyclic reference?");
+ Chain = Factory.add(FR, Other.Chain);
+}
+
+bool FieldChainInfo::isPointer() const {
+ assert(!Chain.isEmpty() && "Empty fieldchain!");
+ return (*Chain.begin())->getDecl()->getType()->isPointerType();
+}
+
+bool FieldChainInfo::isDereferenced() const {
+ assert(isPointer() && "Only pointers may or may not be dereferenced!");
+ return IsDereferenced;
+}
+
+const FieldDecl *FieldChainInfo::getEndOfChain() const {
+ assert(!Chain.isEmpty() && "Empty fieldchain!");
+ return (*Chain.begin())->getDecl();
+}
+
+// TODO: This function constructs an incorrect fieldchain string in the
+// following case:
+//
+// struct Base { int x; };
+// struct D1 : Base {}; struct D2 : Base {};
+//
+// struct MostDerived : D1, D2 {
+// MostDerived() {}
+// }
+//
+// A call to MostDerived::MostDerived() will cause two notes that say
+// "uninitialized field 'this->x'", but we can't refer to 'x' directly,
+// we need an explicit namespace resolution whether the uninit field was
+// 'D1::x' or 'D2::x'.
+void FieldChainInfo::print(llvm::raw_ostream &Out) const {
+ if (Chain.isEmpty())
+ return;
+
+ const llvm::ImmutableListImpl<const FieldRegion *> *L =
+ Chain.getInternalPointer();
+ printTail(Out, L->getTail());
+ Out << getVariableName(L->getHead()->getDecl());
+}
+
+void FieldChainInfo::printTail(
+ llvm::raw_ostream &Out,
+ const llvm::ImmutableListImpl<const FieldRegion *> *L) {
+ if (!L)
+ return;
+
+ printTail(Out, L->getTail());
+ const FieldDecl *Field = L->getHead()->getDecl();
+ Out << getVariableName(Field);
+ Out << (Field->getType()->isPointerType() ? "->" : ".");
+}
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static bool isVoidPointer(const FieldDecl *FD) {
+ QualType T = FD->getType();
+
+ while (!T.isNull()) {
+ if (T->isVoidPointerType())
+ return true;
+ T = T->getPointeeType();
+ }
+ return false;
+}
+
+static Optional<nonloc::LazyCompoundVal>
+getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) {
+
+ Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl->getParent(),
+ Context.getStackFrame());
+ // Getting the value for 'this'.
+ SVal This = Context.getState()->getSVal(ThisLoc);
+
+ // Getting the value for '*this'.
+ SVal Object = Context.getState()->getSVal(This.castAs<Loc>());
+
+ return Object.getAs<nonloc::LazyCompoundVal>();
+}
+
+// TODO: We should also check that if the constructor was called by another
+// constructor, whether those two are in any relation to one another. In it's
+// current state, this introduces some false negatives.
+static bool isCalledByConstructor(const CheckerContext &Context) {
+ const LocationContext *LC = Context.getLocationContext()->getParent();
+
+ while (LC) {
+ if (isa<CXXConstructorDecl>(LC->getDecl()))
+ return true;
+
+ LC = LC->getParent();
+ }
+ return false;
+}
+
+static void printNoteMessage(llvm::raw_ostream &Out,
+ const FieldChainInfo &Chain) {
+ if (Chain.isPointer()) {
+ if (Chain.isDereferenced())
+ Out << "uninitialized pointee 'this->";
+ else
+ Out << "uninitialized pointer 'this->";
+ } else
+ Out << "uninitialized field 'this->";
+ Chain.print(Out);
+ Out << "'";
+}
+
+static StringRef getVariableName(const FieldDecl *Field) {
+ // If Field is a captured lambda variable, Field->getName() will return with
+ // an empty string. We can however acquire it's name from the lambda's
+ // captures.
+ const auto *CXXParent = dyn_cast<CXXRecordDecl>(Field->getParent());
+
+ if (CXXParent && CXXParent->isLambda()) {
+ assert(CXXParent->captures_begin());
+ auto It = CXXParent->captures_begin() + Field->getFieldIndex();
+ return It->getCapturedVar()->getName();
+ }
+
+ return Field->getName();
+}
+
+void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) {
+ auto Chk = Mgr.registerChecker<UninitializedObjectChecker>();
+ Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption(
+ "Pedantic", /*DefaultVal*/ false, Chk);
+ Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption(
+ "NotesAsWarnings", /*DefaultVal*/ false, Chk);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 7f9a00ff876d..a6b50dc37740 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -194,7 +194,7 @@ void UnixAPIChecker::CheckOpenVariant(CheckerContext &C,
// Now check if oflags has O_CREAT set.
const Expr *oflagsEx = CE->getArg(FlagsArgIndex);
- const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
+ const SVal V = C.getSVal(oflagsEx);
if (!V.getAs<NonLoc>()) {
// The case where 'V' can be a location can only be due to a bad header,
// so in this case bail out.
@@ -248,8 +248,7 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
// Check if the first argument is stack allocated. If so, issue a warning
// because that's likely to be bad news.
ProgramStateRef state = C.getState();
- const MemRegion *R =
- state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
+ const MemRegion *R = C.getSVal(CE->getArg(0)).getAsRegion();
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
return;
@@ -336,7 +335,7 @@ void UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
ProgramStateRef state = C.getState();
ProgramStateRef trueState = nullptr, falseState = nullptr;
const Expr *arg = CE->getArg(sizeArg);
- SVal argVal = state->getSVal(arg, C.getLocationContext());
+ SVal argVal = C.getSVal(arg);
if (argVal.isUnknownOrUndef())
return;
@@ -364,7 +363,7 @@ void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
unsigned int i;
for (i = 0; i < nArgs; i++) {
const Expr *arg = CE->getArg(i);
- SVal argVal = state->getSVal(arg, C.getLocationContext());
+ SVal argVal = C.getSVal(arg);
if (argVal.isUnknownOrUndef()) {
if (i == 0)
continue;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 6f21e868b174..dbd12cc9b65a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -132,7 +132,8 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
ci != ce; ++ci) {
if (Optional<CFGStmt> S = (*ci).getAs<CFGStmt>())
if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
- if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable) {
+ if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable ||
+ CE->isBuiltinAssumeFalse(Eng.getContext())) {
foundUnreachable = true;
break;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index 40217bdee892..2584f2011819 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -32,19 +32,18 @@ class VLASizeChecker : public Checker< check::PreStmt<DeclStmt> > {
mutable std::unique_ptr<BugType> BT;
enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Tainted, VLA_Negative };
- void reportBug(VLASize_Kind Kind,
- const Expr *SizeE,
- ProgramStateRef State,
- CheckerContext &C) const;
+ void reportBug(VLASize_Kind Kind, const Expr *SizeE, ProgramStateRef State,
+ CheckerContext &C,
+ std::unique_ptr<BugReporterVisitor> Visitor = nullptr) const;
+
public:
void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
};
} // end anonymous namespace
-void VLASizeChecker::reportBug(VLASize_Kind Kind,
- const Expr *SizeE,
- ProgramStateRef State,
- CheckerContext &C) const {
+void VLASizeChecker::reportBug(
+ VLASize_Kind Kind, const Expr *SizeE, ProgramStateRef State,
+ CheckerContext &C, std::unique_ptr<BugReporterVisitor> Visitor) const {
// Generate an error node.
ExplodedNode *N = C.generateErrorNode(State);
if (!N)
@@ -73,6 +72,7 @@ void VLASizeChecker::reportBug(VLASize_Kind Kind,
}
auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
+ report->addVisitor(std::move(Visitor));
report->addRange(SizeE->getSourceRange());
bugreporter::trackNullOrUndefValue(N, SizeE, *report);
C.emitReport(std::move(report));
@@ -94,7 +94,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// FIXME: Handle multi-dimensional VLAs.
const Expr *SE = VLA->getSizeExpr();
ProgramStateRef state = C.getState();
- SVal sizeV = state->getSVal(SE, C.getLocationContext());
+ SVal sizeV = C.getSVal(SE);
if (sizeV.isUndef()) {
reportBug(VLA_Garbage, SE, state, C);
@@ -108,7 +108,8 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// Check if the size is tainted.
if (state->isTainted(sizeV)) {
- reportBug(VLA_Tainted, SE, nullptr, C);
+ reportBug(VLA_Tainted, SE, nullptr, C,
+ llvm::make_unique<TaintBugVisitor>(sizeV));
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
index 1ebac2118a42..bd657340fcfb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -56,7 +56,6 @@ public:
private:
const MemRegion *getVAListAsRegion(SVal SV, const Expr *VAExpr,
bool &IsSymbolic, CheckerContext &C) const;
- StringRef getVariableNameFromRegion(const MemRegion *Reg) const;
const ExplodedNode *getStartCallSite(const ExplodedNode *N,
const MemRegion *Reg) const;
@@ -70,7 +69,7 @@ private:
bool IsCopy) const;
void checkVAListEndCall(const CallEvent &Call, CheckerContext &C) const;
- class ValistBugVisitor : public BugReporterVisitorImpl<ValistBugVisitor> {
+ class ValistBugVisitor : public BugReporterVisitor {
public:
ValistBugVisitor(const MemRegion *Reg, bool IsLeak = false)
: Reg(Reg), IsLeak(IsLeak) {}
@@ -79,7 +78,7 @@ private:
ID.AddPointer(&X);
ID.AddPointer(Reg);
}
- std::unique_ptr<PathDiagnosticPiece>
+ std::shared_ptr<PathDiagnosticPiece>
getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
BugReport &BR) override {
if (!IsLeak)
@@ -88,8 +87,7 @@ private:
PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(
EndPathNode, BRC.getSourceManager());
// Do not add the statement itself as a range in case of leak.
- return llvm::make_unique<PathDiagnosticEventPiece>(L, BR.getDescription(),
- false);
+ return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(), false);
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
@@ -189,7 +187,7 @@ void ValistChecker::checkPreStmt(const VAArgExpr *VAA,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
const Expr *VASubExpr = VAA->getSubExpr();
- SVal VAListSVal = State->getSVal(VASubExpr, C.getLocationContext());
+ SVal VAListSVal = C.getSVal(VASubExpr);
bool Symbolic;
const MemRegion *VAList =
getVAListAsRegion(VAListSVal, VASubExpr, Symbolic, C);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index c5010f53785a..5b602468cdd4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -48,7 +48,7 @@ public:
DefaultBool IsPureOnly;
void checkBeginFunction(CheckerContext &C) const;
- void checkEndFunction(CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
private:
@@ -57,7 +57,7 @@ private:
void reportBug(StringRef Msg, bool PureError, const MemRegion *Reg,
CheckerContext &C) const;
- class VirtualBugVisitor : public BugReporterVisitorImpl<VirtualBugVisitor> {
+ class VirtualBugVisitor : public BugReporterVisitor {
private:
const MemRegion *ObjectRegion;
bool Found;
@@ -108,7 +108,7 @@ VirtualCallChecker::VirtualBugVisitor::VisitNode(const ExplodedNode *N,
if (!MD)
return nullptr;
auto ThiSVal =
- State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
const MemRegion *Reg = ThiSVal.castAs<loc::MemRegionVal>().getRegion();
if (!Reg)
return nullptr;
@@ -167,7 +167,8 @@ void VirtualCallChecker::checkBeginFunction(CheckerContext &C) const {
}
// The EndFunction callback when leave a constructor or a destructor.
-void VirtualCallChecker::checkEndFunction(CheckerContext &C) const {
+void VirtualCallChecker::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &C) const {
registerCtorDtorCallInState(false, C);
}
@@ -230,7 +231,7 @@ void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction,
// Enter a constructor, set the corresponding memregion be true.
if (isa<CXXConstructorDecl>(MD)) {
auto ThiSVal =
- State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
const MemRegion *Reg = ThiSVal.getAsRegion();
if (IsBeginFunction)
State = State->set<CtorDtorMap>(Reg, ObjectState::CtorCalled);
@@ -244,7 +245,7 @@ void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction,
// Enter a Destructor, set the corresponding memregion be true.
if (isa<CXXDestructorDecl>(MD)) {
auto ThiSVal =
- State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
const MemRegion *Reg = ThiSVal.getAsRegion();
if (IsBeginFunction)
State = State->set<CtorDtorMap>(Reg, ObjectState::DtorCalled);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 1cc08f0d9fe7..dc0d3ec8493a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -26,9 +26,12 @@ AnalysisManager::AnalysisManager(
// Adding LoopExit elements to the CFG is a requirement for loop
// unrolling.
Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
+ Options.includeScopesInCFG(),
Options.shouldSynthesizeBodies(),
Options.shouldConditionalizeStaticInitializers(),
/*addCXXNewAllocator=*/true,
+ Options.includeRichConstructorsInCFG(),
+ Options.shouldElideConstructors(),
injector),
Ctx(ASTCtx), Diags(diags), LangOpts(lang), PathConsumers(PDC),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 48e3e22af04a..9b2dc32e0600 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -1,4 +1,4 @@
-//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===//
+//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,8 +16,15 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
@@ -55,9 +62,32 @@ AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
return UserMode;
}
+AnalyzerOptions::ExplorationStrategyKind
+AnalyzerOptions::getExplorationStrategy() {
+ if (ExplorationStrategy == ExplorationStrategyKind::NotSet) {
+ StringRef StratStr =
+ Config
+ .insert(std::make_pair("exploration_strategy", "unexplored_first_queue"))
+ .first->second;
+ ExplorationStrategy =
+ llvm::StringSwitch<ExplorationStrategyKind>(StratStr)
+ .Case("dfs", ExplorationStrategyKind::DFS)
+ .Case("bfs", ExplorationStrategyKind::BFS)
+ .Case("unexplored_first",
+ ExplorationStrategyKind::UnexploredFirst)
+ .Case("unexplored_first_queue",
+ ExplorationStrategyKind::UnexploredFirstQueue)
+ .Case("bfs_block_dfs_contents",
+ ExplorationStrategyKind::BFSBlockDFSContents)
+ .Default(ExplorationStrategyKind::NotSet);
+ assert(ExplorationStrategy != ExplorationStrategyKind::NotSet &&
+ "User mode is invalid.");
+ }
+ return ExplorationStrategy;
+}
+
IPAKind AnalyzerOptions::getIPAMode() {
if (IPAMode == IPAK_NotSet) {
-
// Use the User Mode to set the default IPA value.
// Note, we have to add the string to the Config map for the ConfigDumper
// checker to function properly.
@@ -169,7 +199,7 @@ bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
bool AnalyzerOptions::includeTemporaryDtorsInCFG() {
return getBooleanOption(IncludeTemporaryDtorsInCFG,
"cfg-temporary-dtors",
- /* Default = */ false);
+ /* Default = */ true);
}
bool AnalyzerOptions::includeImplicitDtorsInCFG() {
@@ -185,7 +215,19 @@ bool AnalyzerOptions::includeLifetimeInCFG() {
bool AnalyzerOptions::includeLoopExitInCFG() {
return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
- /* Default = */ false);
+ /* Default = */ false);
+}
+
+bool AnalyzerOptions::includeRichConstructorsInCFG() {
+ return getBooleanOption(IncludeRichConstructorsInCFG,
+ "cfg-rich-constructors",
+ /* Default = */ true);
+}
+
+bool AnalyzerOptions::includeScopesInCFG() {
+ return getBooleanOption(IncludeScopesInCFG,
+ "cfg-scopes",
+ /* Default = */ false);
}
bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
@@ -203,7 +245,7 @@ bool AnalyzerOptions::mayInlineTemplateFunctions() {
bool AnalyzerOptions::mayInlineCXXAllocator() {
return getBooleanOption(InlineCXXAllocator,
"c++-allocator-inlining",
- /*Default=*/false);
+ /*Default=*/true);
}
bool AnalyzerOptions::mayInlineCXXContainerMethods() {
@@ -218,6 +260,11 @@ bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() {
/*Default=*/false);
}
+bool AnalyzerOptions::mayInlineCXXTemporaryDtors() {
+ return getBooleanOption(InlineCXXTemporaryDtors,
+ "c++-temp-dtor-inlining",
+ /*Default=*/true);
+}
bool AnalyzerOptions::mayInlineObjCMethod() {
return getBooleanOption(ObjCInliningMode,
@@ -249,6 +296,12 @@ bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() {
/* Default = */ true);
}
+bool AnalyzerOptions::shouldCrosscheckWithZ3() {
+ return getBooleanOption(CrosscheckWithZ3,
+ "crosscheck-with-z3",
+ /* Default = */ false);
+}
+
bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() {
return getBooleanOption(ReportIssuesInMainSourceFile,
"report-in-main-source-file",
@@ -262,6 +315,18 @@ bool AnalyzerOptions::shouldWriteStableReportFilename() {
/* Default = */ false);
}
+bool AnalyzerOptions::shouldSerializeStats() {
+ return getBooleanOption(SerializeStats,
+ "serialize-stats",
+ /* Default = */ false);
+}
+
+bool AnalyzerOptions::shouldElideConstructors() {
+ return getBooleanOption(ElideConstructors,
+ "elide-constructors",
+ /* Default = */ true);
+}
+
int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
const CheckerBase *C,
bool SearchInParents) {
@@ -299,7 +364,6 @@ unsigned AnalyzerOptions::getAlwaysInlineSize() {
unsigned AnalyzerOptions::getMaxInlinableSize() {
if (!MaxInlinableSize.hasValue()) {
-
int DefaultValue = 0;
UserModeKind HighLevelMode = getUserMode();
switch (HighLevelMode) {
@@ -324,6 +388,12 @@ unsigned AnalyzerOptions::getGraphTrimInterval() {
return GraphTrimInterval.getValue();
}
+unsigned AnalyzerOptions::getMaxSymbolComplexity() {
+ if (!MaxSymbolComplexity.hasValue())
+ MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 35);
+ return MaxSymbolComplexity.getValue();
+}
+
unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
if (!MaxTimesInlineLarge.hasValue())
MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
@@ -392,3 +462,34 @@ bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
getBooleanOption("notes-as-events", /*Default=*/false);
return DisplayNotesAsEvents.getValue();
}
+
+bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() {
+ if (!AggressiveBinaryOperationSimplification.hasValue())
+ AggressiveBinaryOperationSimplification =
+ getBooleanOption("aggressive-binary-operation-simplification",
+ /*Default=*/false);
+ return AggressiveBinaryOperationSimplification.getValue();
+}
+
+StringRef AnalyzerOptions::getCTUDir() {
+ if (!CTUDir.hasValue()) {
+ CTUDir = getOptionAsString("ctu-dir", "");
+ if (!llvm::sys::fs::is_directory(*CTUDir))
+ CTUDir = "";
+ }
+ return CTUDir.getValue();
+}
+
+bool AnalyzerOptions::naiveCTUEnabled() {
+ if (!NaiveCTU.hasValue()) {
+ NaiveCTU = getBooleanOption("experimental-enable-naive-ctu-analysis",
+ /*Default=*/false);
+ }
+ return NaiveCTU.getValue();
+}
+
+StringRef AnalyzerOptions::getCTUIndexName() {
+ if (!CTUIndexName.hasValue())
+ CTUIndexName = getOptionAsString("ctu-index-name", "externalFnMap.txt");
+ return CTUIndexName.getValue();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index ec7a7e9e4b1c..db4c1432ccc3 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -1,4 +1,4 @@
-//=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- C++ -*-//
+//===- BasicValueFactory.cpp - Basic values for Path Sens analysis --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,9 +13,18 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/STLExtras.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
using namespace clang;
using namespace ento;
@@ -40,10 +49,11 @@ void PointerToMemberData::Profile(
ID.AddPointer(L.getInternalPointer());
}
-typedef std::pair<SVal, uintptr_t> SValData;
-typedef std::pair<SVal, SVal> SValPair;
+using SValData = std::pair<SVal, uintptr_t>;
+using SValPair = std::pair<SVal, SVal>;
namespace llvm {
+
template<> struct FoldingSetTrait<SValData> {
static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
X.first.Profile(ID);
@@ -57,20 +67,21 @@ template<> struct FoldingSetTrait<SValPair> {
X.second.Profile(ID);
}
};
-}
-typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
- PersistentSValsTy;
+} // namespace llvm
-typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
- PersistentSValPairsTy;
+using PersistentSValsTy =
+ llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData>>;
+
+using PersistentSValPairsTy =
+ llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair>>;
BasicValueFactory::~BasicValueFactory() {
// Note that the dstor for the contents of APSIntSet will never be called,
// so we iterate over the set and invoke the dstor for each APSInt. This
// frees an aux. memory allocated to represent very large constants.
- for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
- I->getValue().~APSInt();
+ for (const auto &I : APSIntSet)
+ I.getValue().~APSInt();
delete (PersistentSValsTy*) PersistentSVals;
delete (PersistentSValPairsTy*) PersistentSValPairs;
@@ -79,7 +90,8 @@ BasicValueFactory::~BasicValueFactory() {
const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
llvm::FoldingSetNodeID ID;
void *InsertPos;
- typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
+
+ using FoldNodeTy = llvm::FoldingSetNodeWrapper<llvm::APSInt>;
X.Profile(ID);
FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
@@ -107,14 +119,12 @@ const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
}
const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
-
return getValue(getAPSIntType(T).getValue(X));
}
const CompoundValData*
BasicValueFactory::getCompoundValData(QualType T,
llvm::ImmutableList<SVal> Vals) {
-
llvm::FoldingSetNodeID ID;
CompoundValData::Profile(ID, T, Vals);
void *InsertPos;
@@ -150,7 +160,7 @@ BasicValueFactory::getLazyCompoundValData(const StoreRef &store,
}
const PointerToMemberData *BasicValueFactory::getPointerToMemberData(
- const DeclaratorDecl *DD, llvm::ImmutableList<const CXXBaseSpecifier*> L) {
+ const DeclaratorDecl *DD, llvm::ImmutableList<const CXXBaseSpecifier *> L) {
llvm::FoldingSetNodeID ID;
PointerToMemberData::Profile(ID, DD, L);
void *InsertPos;
@@ -167,7 +177,7 @@ const PointerToMemberData *BasicValueFactory::getPointerToMemberData(
return D;
}
-const clang::ento::PointerToMemberData *BasicValueFactory::accumCXXBase(
+const PointerToMemberData *BasicValueFactory::accumCXXBase(
llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
const nonloc::PointerToMember &PTM) {
nonloc::PointerToMember::PTMDataType PTMDT = PTM.getPTMData();
@@ -195,10 +205,9 @@ const clang::ento::PointerToMemberData *BasicValueFactory::accumCXXBase(
const llvm::APSInt*
BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1, const llvm::APSInt& V2) {
-
switch (Op) {
default:
- assert (false && "Invalid Opcode.");
+ assert(false && "Invalid Opcode.");
case BO_Mul:
return &getValue( V1 * V2 );
@@ -220,11 +229,9 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
return &getValue( V1 - V2 );
case BO_Shl: {
-
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
- // FIXME: Expand these checks to include all undefined behavior.
if (V1.isSigned() && V1.isNegative())
return nullptr;
@@ -236,16 +243,16 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
if (Amt >= V1.getBitWidth())
return nullptr;
+ if (V1.isSigned() && Amt > V1.countLeadingZeros())
+ return nullptr;
+
return &getValue( V1.operator<<( (unsigned) Amt ));
}
case BO_Shr: {
-
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
- // FIXME: Expand these checks to include all undefined behavior.
-
if (V2.isSigned() && V2.isNegative())
return nullptr;
@@ -288,10 +295,8 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
}
}
-
const std::pair<SVal, uintptr_t>&
BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
-
// Lazily create the folding set.
if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
@@ -302,7 +307,8 @@ BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
- typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
+ using FoldNodeTy = llvm::FoldingSetNodeWrapper<SValData>;
+
FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
if (!P) {
@@ -316,7 +322,6 @@ BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
const std::pair<SVal, SVal>&
BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
-
// Lazily create the folding set.
if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
@@ -327,7 +332,8 @@ BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
- typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
+ using FoldNodeTy = llvm::FoldingSetNodeWrapper<SValPair>;
+
FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
if (!P) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index de0e87bb8249..f990eb6a058d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1,4 +1,4 @@
-// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--//
+//===- BugReporter.cpp - Generate PathDiagnostics for bugs ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,28 +13,62 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.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/ExprCXX.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.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/Statistic.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/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
#include <memory>
#include <queue>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
@@ -47,7 +81,7 @@ STATISTIC(MaxValidBugClassSize,
"The maximum number of bug reports in the same equivalence class "
"where at least one report is valid (not suppressed)");
-BugReporterVisitor::~BugReporterVisitor() {}
+BugReporterVisitor::~BugReporterVisitor() = default;
void BugReporterContext::anchor() {}
@@ -127,10 +161,9 @@ static void removeRedundantMsgs(PathPieces &path) {
if (i == N-1)
break;
- if (PathDiagnosticEventPiece *nextEvent =
+ if (auto *nextEvent =
dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
- PathDiagnosticEventPiece *event =
- cast<PathDiagnosticEventPiece>(piece.get());
+ auto *event = cast<PathDiagnosticEventPiece>(piece.get());
// Check to see if we should keep one of the two pieces. If we
// come up with a preference, record which piece to keep, and consume
// another piece from the path.
@@ -152,15 +185,16 @@ static void removeRedundantMsgs(PathPieces &path) {
/// A map from PathDiagnosticPiece to the LocationContext of the inlined
/// function call it represents.
-typedef llvm::DenseMap<const PathPieces *, const LocationContext *>
- LocationContextMap;
+using LocationContextMap =
+ llvm::DenseMap<const PathPieces *, const LocationContext *>;
/// Recursively scan through a path and prune out calls and macros pieces
/// that aren't needed. Return true if afterwards the path contains
/// "interesting stuff" which means it shouldn't be pruned from the parent path.
static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
- LocationContextMap &LCM) {
- bool containsSomethingInteresting = false;
+ LocationContextMap &LCM,
+ bool IsInteresting = false) {
+ bool containsSomethingInteresting = IsInteresting;
const unsigned N = pieces.size();
for (unsigned i = 0 ; i < N ; ++i) {
@@ -174,12 +208,8 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
auto &call = cast<PathDiagnosticCallPiece>(*piece);
// Check if the location context is interesting.
assert(LCM.count(&call.path));
- if (R->isInteresting(LCM[&call.path])) {
- containsSomethingInteresting = true;
- break;
- }
-
- if (!removeUnneededCalls(call.path, R, LCM))
+ if (!removeUnneededCalls(call.path, R, LCM,
+ R->isInteresting(LCM[&call.path])))
continue;
containsSomethingInteresting = true;
@@ -187,7 +217,7 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
}
case PathDiagnosticPiece::Macro: {
auto &macro = cast<PathDiagnosticMacroPiece>(*piece);
- if (!removeUnneededCalls(macro.subPieces, R, LCM))
+ if (!removeUnneededCalls(macro.subPieces, R, LCM, IsInteresting))
continue;
containsSomethingInteresting = true;
break;
@@ -225,12 +255,11 @@ static bool hasImplicitBody(const Decl *D) {
static void
adjustCallLocations(PathPieces &Pieces,
PathDiagnosticLocation *LastCallLocation = nullptr) {
- for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
- PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(I->get());
+ for (const auto &I : Pieces) {
+ auto *Call = dyn_cast<PathDiagnosticCallPiece>(I.get());
- if (!Call) {
+ if (!Call)
continue;
- }
if (LastCallLocation) {
bool CallerIsImplicit = hasImplicitBody(Call->getCaller());
@@ -313,29 +342,19 @@ static void removePiecesWithInvalidLocations(PathPieces &Pieces) {
//===----------------------------------------------------------------------===//
namespace {
-class NodeMapClosure : public BugReport::NodeResolver {
- InterExplodedGraphMap &M;
-public:
- NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
-
- const ExplodedNode *getOriginalNode(const ExplodedNode *N) override {
- return M.lookup(N);
- }
-};
class PathDiagnosticBuilder : public BugReporterContext {
BugReport *R;
PathDiagnosticConsumer *PDC;
- NodeMapClosure NMC;
+
public:
const LocationContext *LC;
PathDiagnosticBuilder(GRBugReporter &br,
BugReport *r, InterExplodedGraphMap &Backmap,
PathDiagnosticConsumer *pdc)
- : BugReporterContext(br),
- R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext())
- {}
+ : BugReporterContext(br, Backmap), R(r), PDC(pdc),
+ LC(r->getErrorNode()->getLocationContext()) {}
PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
@@ -352,19 +371,18 @@ public:
return getParentMap().getParent(S);
}
- NodeMapClosure& getNodeResolver() override { return NMC; }
-
PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
- return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive;
+ return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Minimal;
}
bool supportsLogicalOpControlFlow() const {
return PDC ? PDC->supportsLogicalOpControlFlow() : true;
}
};
-} // end anonymous namespace
+
+} // namespace
PathDiagnosticLocation
PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
@@ -378,7 +396,6 @@ PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
PathDiagnosticLocation
PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
const ExplodedNode *N) {
-
// Slow, but probably doesn't matter.
if (os.str().empty())
os << ' ';
@@ -432,12 +449,12 @@ static PathDiagnosticLocation
getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P,
const LocationContext *LC, bool allowNestedContexts) {
if (!S)
- return PathDiagnosticLocation();
+ return {};
while (const Stmt *Parent = getEnclosingParent(S, P)) {
switch (Parent->getStmtClass()) {
case Stmt::BinaryOperatorClass: {
- const BinaryOperator *B = cast<BinaryOperator>(Parent);
+ const auto *B = cast<BinaryOperator>(Parent);
if (B->isLogicalOp())
return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
break;
@@ -503,46 +520,21 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
}
//===----------------------------------------------------------------------===//
-// "Visitors only" path diagnostic generation algorithm.
-//===----------------------------------------------------------------------===//
-static bool GenerateVisitorsOnlyPathDiagnostic(
- PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
- ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
- // All path generation skips the very first node (the error node).
- // This is because there is special handling for the end-of-path note.
- N = N->getFirstPred();
- if (!N)
- return true;
-
- BugReport *R = PDB.getBugReport();
- while (const ExplodedNode *Pred = N->getFirstPred()) {
- for (auto &V : visitors)
- // Visit all the node pairs, but throw the path pieces away.
- V->VisitNode(N, Pred, PDB, *R);
-
- N = Pred;
- }
-
- return R->isValid();
-}
-
-//===----------------------------------------------------------------------===//
// "Minimal" path diagnostic generation algorithm.
//===----------------------------------------------------------------------===//
-typedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair;
-typedef SmallVector<StackDiagPair, 6> StackDiagVector;
+using StackDiagPair =
+ std::pair<PathDiagnosticCallPiece *, const ExplodedNode *>;
+using StackDiagVector = SmallVector<StackDiagPair, 6>;
static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
StackDiagVector &CallStack) {
// If the piece contains a special message, add it to all the call
// pieces on the active stack.
- if (PathDiagnosticEventPiece *ep = dyn_cast<PathDiagnosticEventPiece>(&P)) {
-
+ if (auto *ep = dyn_cast<PathDiagnosticEventPiece>(&P)) {
if (ep->hasCallStackHint())
- for (StackDiagVector::iterator I = CallStack.begin(),
- E = CallStack.end(); I != E; ++I) {
- PathDiagnosticCallPiece *CP = I->first;
- const ExplodedNode *N = I->second;
+ for (const auto &I : CallStack) {
+ PathDiagnosticCallPiece *CP = I.first;
+ const ExplodedNode *N = I.second;
std::string stackMsg = ep->getCallStackMessage(N);
// The last message on the path to final bug is the most important
@@ -556,693 +548,271 @@ static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
-static bool GenerateMinimalPathDiagnostic(
- PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
- LocationContextMap &LCM,
- ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
-
- SourceManager& SMgr = PDB.getSourceManager();
- const LocationContext *LC = PDB.LC;
- const ExplodedNode *NextNode = N->pred_empty()
- ? nullptr : *(N->pred_begin());
-
- StackDiagVector CallStack;
-
- while (NextNode) {
- N = NextNode;
- PDB.LC = N->getLocationContext();
- NextNode = N->getFirstPred();
-
- ProgramPoint P = N->getLocation();
-
- do {
- if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
- auto C = PathDiagnosticCallPiece::construct(N, *CE, SMgr);
- // Record the mapping from call piece to LocationContext.
- LCM[&C->path] = CE->getCalleeContext();
- auto *P = C.get();
- PD.getActivePath().push_front(std::move(C));
- PD.pushActivePath(&P->path);
- CallStack.push_back(StackDiagPair(P, N));
- break;
- }
-
- if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
- // Flush all locations, and pop the active path.
- bool VisitedEntireCall = PD.isWithinCall();
- PD.popActivePath();
-
- // Either we just added a bunch of stuff to the top-level path, or
- // we have a previous CallExitEnd. If the former, it means that the
- // path terminated within a function call. We must then take the
- // current contents of the active path and place it within
- // a new PathDiagnosticCallPiece.
- PathDiagnosticCallPiece *C;
- if (VisitedEntireCall) {
- C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front().get());
- } else {
- const Decl *Caller = CE->getLocationContext()->getDecl();
- C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
- // Record the mapping from call piece to LocationContext.
- LCM[&C->path] = CE->getCalleeContext();
- }
-
- C->setCallee(*CE, SMgr);
- if (!CallStack.empty()) {
- assert(CallStack.back().first == C);
- CallStack.pop_back();
- }
- break;
- }
-
- if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
- const CFGBlock *Src = BE->getSrc();
- const CFGBlock *Dst = BE->getDst();
- const Stmt *T = Src->getTerminator();
-
- if (!T)
- break;
-
- PathDiagnosticLocation Start =
- PathDiagnosticLocation::createBegin(T, SMgr,
- N->getLocationContext());
-
- switch (T->getStmtClass()) {
- default:
- break;
-
- case Stmt::GotoStmtClass:
- case Stmt::IndirectGotoStmtClass: {
- const Stmt *S = PathDiagnosticLocation::getNextStmt(N);
-
- if (!S)
- break;
-
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
- const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
-
- os << "Control jumps to line "
- << End.asLocation().getExpansionLineNumber();
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- break;
- }
-
- case Stmt::SwitchStmtClass: {
- // Figure out what case arm we took.
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
-
- if (const Stmt *S = Dst->getLabel()) {
- PathDiagnosticLocation End(S, SMgr, LC);
-
- switch (S->getStmtClass()) {
- default:
- os << "No cases match in the switch statement. "
- "Control jumps to line "
- << End.asLocation().getExpansionLineNumber();
- break;
- case Stmt::DefaultStmtClass:
- os << "Control jumps to the 'default' case at line "
- << End.asLocation().getExpansionLineNumber();
- break;
-
- case Stmt::CaseStmtClass: {
- os << "Control jumps to 'case ";
- const CaseStmt *Case = cast<CaseStmt>(S);
- const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
-
- // Determine if it is an enum.
- bool GetRawInt = true;
-
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
- // FIXME: Maybe this should be an assertion. Are there cases
- // were it is not an EnumConstantDecl?
- const EnumConstantDecl *D =
- dyn_cast<EnumConstantDecl>(DR->getDecl());
-
- if (D) {
- GetRawInt = false;
- os << *D;
- }
- }
-
- if (GetRawInt)
- os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
-
- os << ":' at line "
- << End.asLocation().getExpansionLineNumber();
- break;
- }
- }
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- else {
- os << "'Default' branch taken. ";
- const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
-
- break;
- }
-
- case Stmt::BreakStmtClass:
- case Stmt::ContinueStmtClass: {
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
- PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- break;
- }
-
- // Determine control-flow for ternary '?'.
- case Stmt::BinaryConditionalOperatorClass:
- case Stmt::ConditionalOperatorClass: {
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
- os << "'?' condition is ";
-
- if (*(Src->succ_begin()+1) == Dst)
- os << "false";
- else
- os << "true";
-
- PathDiagnosticLocation End = PDB.ExecutionContinues(N);
-
- if (const Stmt *S = End.asStmt())
- End = PDB.getEnclosingStmtLocation(S);
-
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- break;
- }
-
- // Determine control-flow for short-circuited '&&' and '||'.
- case Stmt::BinaryOperatorClass: {
- if (!PDB.supportsLogicalOpControlFlow())
- break;
- const BinaryOperator *B = cast<BinaryOperator>(T);
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
- os << "Left side of '";
-
- if (B->getOpcode() == BO_LAnd) {
- os << "&&" << "' is ";
-
- if (*(Src->succ_begin()+1) == Dst) {
- os << "false";
- PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
- PathDiagnosticLocation Start =
- PathDiagnosticLocation::createOperatorLoc(B, SMgr);
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- else {
- os << "true";
- PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
- PathDiagnosticLocation End = PDB.ExecutionContinues(N);
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- }
- else {
- assert(B->getOpcode() == BO_LOr);
- os << "||" << "' is ";
-
- if (*(Src->succ_begin()+1) == Dst) {
- os << "false";
- PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
- PathDiagnosticLocation End = PDB.ExecutionContinues(N);
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- else {
- os << "true";
- PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
- PathDiagnosticLocation Start =
- PathDiagnosticLocation::createOperatorLoc(B, SMgr);
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- }
-
- break;
- }
+std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForSwitchOP(
+ const ExplodedNode *N,
+ const CFGBlock *Dst,
+ const SourceManager &SM,
+ const LocationContext *LC,
+ PathDiagnosticBuilder &PDB,
+ PathDiagnosticLocation &Start
+ ) {
+ // Figure out what case arm we took.
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ PathDiagnosticLocation End;
- case Stmt::DoStmtClass: {
- if (*(Src->succ_begin()) == Dst) {
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
-
- os << "Loop condition is true. ";
- PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
-
- if (const Stmt *S = End.asStmt())
- End = PDB.getEnclosingStmtLocation(S);
-
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- else {
- PathDiagnosticLocation End = PDB.ExecutionContinues(N);
-
- if (const Stmt *S = End.asStmt())
- End = PDB.getEnclosingStmtLocation(S);
-
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(
- Start, End, "Loop condition is false. Exiting loop"));
- }
-
- break;
- }
-
- case Stmt::WhileStmtClass:
- case Stmt::ForStmtClass: {
- if (*(Src->succ_begin()+1) == Dst) {
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
-
- os << "Loop condition is false. ";
- PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
- if (const Stmt *S = End.asStmt())
- End = PDB.getEnclosingStmtLocation(S);
-
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
- os.str()));
- }
- else {
- PathDiagnosticLocation End = PDB.ExecutionContinues(N);
- if (const Stmt *S = End.asStmt())
- End = PDB.getEnclosingStmtLocation(S);
-
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(
- Start, End, "Loop condition is true. Entering loop body"));
- }
-
- break;
- }
+ if (const Stmt *S = Dst->getLabel()) {
+ End = PathDiagnosticLocation(S, SM, LC);
- case Stmt::IfStmtClass: {
- PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+ switch (S->getStmtClass()) {
+ default:
+ os << "No cases match in the switch statement. "
+ "Control jumps to line "
+ << End.asLocation().getExpansionLineNumber();
+ break;
+ case Stmt::DefaultStmtClass:
+ os << "Control jumps to the 'default' case at line "
+ << End.asLocation().getExpansionLineNumber();
+ break;
- if (const Stmt *S = End.asStmt())
- End = PDB.getEnclosingStmtLocation(S);
+ case Stmt::CaseStmtClass: {
+ os << "Control jumps to 'case ";
+ const auto *Case = cast<CaseStmt>(S);
+ const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
- if (*(Src->succ_begin()+1) == Dst)
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(
- Start, End, "Taking false branch"));
- else
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(
- Start, End, "Taking true branch"));
+ // Determine if it is an enum.
+ bool GetRawInt = true;
- break;
- }
- }
- }
- } while(0);
-
- if (NextNode) {
- // Add diagnostic pieces from custom visitors.
- BugReport *R = PDB.getBugReport();
- llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
- for (auto &V : visitors) {
- if (auto p = V->VisitNode(N, NextNode, PDB, *R)) {
- if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get())
- continue;
+ if (const auto *DR = dyn_cast<DeclRefExpr>(LHS)) {
+ // FIXME: Maybe this should be an assertion. Are there cases
+ // were it is not an EnumConstantDecl?
+ const auto *D = dyn_cast<EnumConstantDecl>(DR->getDecl());
- updateStackPiecesWithMessage(*p, CallStack);
- PD.getActivePath().push_front(std::move(p));
+ if (D) {
+ GetRawInt = false;
+ os << *D;
}
}
- }
- }
-
- if (!PDB.getBugReport()->isValid())
- return false;
-
- // After constructing the full PathDiagnostic, do a pass over it to compact
- // PathDiagnosticPieces that occur within a macro.
- CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager());
- return true;
-}
-
-//===----------------------------------------------------------------------===//
-// "Extensive" PathDiagnostic generation.
-//===----------------------------------------------------------------------===//
-
-static bool IsControlFlowExpr(const Stmt *S) {
- const Expr *E = dyn_cast<Expr>(S);
-
- if (!E)
- return false;
-
- E = E->IgnoreParenCasts();
-
- if (isa<AbstractConditionalOperator>(E))
- return true;
-
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
- if (B->isLogicalOp())
- return true;
- return false;
-}
-
-namespace {
-class ContextLocation : public PathDiagnosticLocation {
- bool IsDead;
-public:
- ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
- : PathDiagnosticLocation(L), IsDead(isdead) {}
-
- void markDead() { IsDead = true; }
- bool isDead() const { return IsDead; }
-};
-
-static PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
- const LocationContext *LC,
- bool firstCharOnly = false) {
- if (const Stmt *S = L.asStmt()) {
- const Stmt *Original = S;
- while (1) {
- // Adjust the location for some expressions that are best referenced
- // by one of their subexpressions.
- switch (S->getStmtClass()) {
- default:
- break;
- case Stmt::ParenExprClass:
- case Stmt::GenericSelectionExprClass:
- S = cast<Expr>(S)->IgnoreParens();
- firstCharOnly = true;
- continue;
- case Stmt::BinaryConditionalOperatorClass:
- case Stmt::ConditionalOperatorClass:
- S = cast<AbstractConditionalOperator>(S)->getCond();
- firstCharOnly = true;
- continue;
- case Stmt::ChooseExprClass:
- S = cast<ChooseExpr>(S)->getCond();
- firstCharOnly = true;
- continue;
- case Stmt::BinaryOperatorClass:
- S = cast<BinaryOperator>(S)->getLHS();
- firstCharOnly = true;
- continue;
- }
+ if (GetRawInt)
+ os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
+ os << ":' at line " << End.asLocation().getExpansionLineNumber();
break;
}
-
- if (S != Original)
- L = PathDiagnosticLocation(S, L.getManager(), LC);
- }
-
- if (firstCharOnly)
- L = PathDiagnosticLocation::createSingleLocation(L);
-
- return L;
-}
-
-class EdgeBuilder {
- std::vector<ContextLocation> CLocs;
- typedef std::vector<ContextLocation>::iterator iterator;
- PathDiagnostic &PD;
- PathDiagnosticBuilder &PDB;
- PathDiagnosticLocation PrevLoc;
-
- bool IsConsumedExpr(const PathDiagnosticLocation &L);
-
- bool containsLocation(const PathDiagnosticLocation &Container,
- const PathDiagnosticLocation &Containee);
-
- PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
-
-
-
- void popLocation() {
- if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
- // For contexts, we only one the first character as the range.
- rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true));
}
- CLocs.pop_back();
+ } else {
+ os << "'Default' branch taken. ";
+ End = PDB.ExecutionContinues(os, N);
+ }
+ return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
+ os.str());
+}
+
+
+std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForGotoOP(
+ const Stmt *S,
+ PathDiagnosticBuilder &PDB,
+ PathDiagnosticLocation &Start) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
+ os << "Control jumps to line " << End.asLocation().getExpansionLineNumber();
+ return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, os.str());
+
+}
+
+std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForBinaryOP(
+ const ExplodedNode *N,
+ const Stmt *T,
+ const CFGBlock *Src,
+ const CFGBlock *Dst,
+ const SourceManager &SM,
+ PathDiagnosticBuilder &PDB,
+ const LocationContext *LC) {
+ const auto *B = cast<BinaryOperator>(T);
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "Left side of '";
+ PathDiagnosticLocation Start, End;
+
+ if (B->getOpcode() == BO_LAnd) {
+ os << "&&"
+ << "' is ";
+
+ if (*(Src->succ_begin() + 1) == Dst) {
+ os << "false";
+ End = PathDiagnosticLocation(B->getLHS(), SM, LC);
+ Start =
+ PathDiagnosticLocation::createOperatorLoc(B, SM);
+ } else {
+ os << "true";
+ Start = PathDiagnosticLocation(B->getLHS(), SM, LC);
+ End = PDB.ExecutionContinues(N);
+ }
+ } else {
+ assert(B->getOpcode() == BO_LOr);
+ os << "||"
+ << "' is ";
+
+ if (*(Src->succ_begin() + 1) == Dst) {
+ os << "false";
+ Start = PathDiagnosticLocation(B->getLHS(), SM, LC);
+ End = PDB.ExecutionContinues(N);
+ } else {
+ os << "true";
+ End = PathDiagnosticLocation(B->getLHS(), SM, LC);
+ Start =
+ PathDiagnosticLocation::createOperatorLoc(B, SM);
+ }
}
+ return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
+ os.str());
+}
-public:
- EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
- : PD(pd), PDB(pdb) {
-
- // If the PathDiagnostic already has pieces, add the enclosing statement
- // of the first piece as a context as well.
- if (!PD.path.empty()) {
- PrevLoc = (*PD.path.begin())->getLocation();
-
- if (const Stmt *S = PrevLoc.asStmt())
- addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
- }
- }
+void generateMinimalDiagForBlockEdge(const ExplodedNode *N, BlockEdge BE,
+ const SourceManager &SM,
+ PathDiagnosticBuilder &PDB,
+ PathDiagnostic &PD) {
+ const LocationContext *LC = N->getLocationContext();
+ const CFGBlock *Src = BE.getSrc();
+ const CFGBlock *Dst = BE.getDst();
+ const Stmt *T = Src->getTerminator();
+ if (!T)
+ return;
- ~EdgeBuilder() {
- while (!CLocs.empty()) popLocation();
+ auto Start = PathDiagnosticLocation::createBegin(T, SM, LC);
+ switch (T->getStmtClass()) {
+ default:
+ break;
- // Finally, add an initial edge from the start location of the first
- // statement (if it doesn't already exist).
- PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin(
- PDB.LC,
- PDB.getSourceManager());
- if (L.isValid())
- rawAddEdge(L);
+ case Stmt::GotoStmtClass:
+ case Stmt::IndirectGotoStmtClass: {
+ if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N))
+ PD.getActivePath().push_front(generateDiagForGotoOP(S, PDB, Start));
+ break;
}
- void flushLocations() {
- while (!CLocs.empty())
- popLocation();
- PrevLoc = PathDiagnosticLocation();
+ case Stmt::SwitchStmtClass: {
+ PD.getActivePath().push_front(
+ generateDiagForSwitchOP(N, Dst, SM, LC, PDB, Start));
+ break;
}
- void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false,
- bool IsPostJump = false);
-
- void rawAddEdge(PathDiagnosticLocation NewLoc);
-
- void addContext(const Stmt *S);
- void addContext(const PathDiagnosticLocation &L);
- void addExtendedContext(const Stmt *S);
-};
-} // end anonymous namespace
-
-
-PathDiagnosticLocation
-EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
- if (const Stmt *S = L.asStmt()) {
- if (IsControlFlowExpr(S))
- return L;
-
- return PDB.getEnclosingStmtLocation(S);
+ case Stmt::BreakStmtClass:
+ case Stmt::ContinueStmtClass: {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, os.str()));
+ break;
}
- return L;
-}
-
-bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
- const PathDiagnosticLocation &Containee) {
-
- if (Container == Containee)
- return true;
+ // Determine control-flow for ternary '?'.
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "'?' condition is ";
- if (Container.asDecl())
- return true;
+ if (*(Src->succ_begin() + 1) == Dst)
+ os << "false";
+ else
+ os << "true";
- if (const Stmt *S = Containee.asStmt())
- if (const Stmt *ContainerS = Container.asStmt()) {
- while (S) {
- if (S == ContainerS)
- return true;
- S = PDB.getParent(S);
- }
- return false;
- }
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
- // Less accurate: compare using source ranges.
- SourceRange ContainerR = Container.asRange();
- SourceRange ContaineeR = Containee.asRange();
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
- SourceManager &SM = PDB.getSourceManager();
- SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
- SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
- SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
- SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
-
- unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
- unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
- unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
- unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
-
- assert(ContainerBegLine <= ContainerEndLine);
- assert(ContaineeBegLine <= ContaineeEndLine);
-
- return (ContainerBegLine <= ContaineeBegLine &&
- ContainerEndLine >= ContaineeEndLine &&
- (ContainerBegLine != ContaineeBegLine ||
- SM.getExpansionColumnNumber(ContainerRBeg) <=
- SM.getExpansionColumnNumber(ContaineeRBeg)) &&
- (ContainerEndLine != ContaineeEndLine ||
- SM.getExpansionColumnNumber(ContainerREnd) >=
- SM.getExpansionColumnNumber(ContaineeREnd)));
-}
-
-void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
- if (!PrevLoc.isValid()) {
- PrevLoc = NewLoc;
- return;
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, os.str()));
+ break;
}
- const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC);
- const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC);
+ // Determine control-flow for short-circuited '&&' and '||'.
+ case Stmt::BinaryOperatorClass: {
+ if (!PDB.supportsLogicalOpControlFlow())
+ break;
- if (PrevLocClean.asLocation().isInvalid()) {
- PrevLoc = NewLoc;
- return;
+ std::shared_ptr<PathDiagnosticControlFlowPiece> Diag =
+ generateDiagForBinaryOP(N, T, Src, Dst, SM, PDB, LC);
+ PD.getActivePath().push_front(Diag);
+ break;
}
- if (NewLocClean.asLocation() == PrevLocClean.asLocation())
- return;
-
- // FIXME: Ignore intra-macro edges for now.
- if (NewLocClean.asLocation().getExpansionLoc() ==
- PrevLocClean.asLocation().getExpansionLoc())
- return;
-
- PD.getActivePath().push_front(
- std::make_shared<PathDiagnosticControlFlowPiece>(NewLocClean,
- PrevLocClean));
- PrevLoc = NewLoc;
-}
-
-void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd,
- bool IsPostJump) {
-
- if (!alwaysAdd && NewLoc.asLocation().isMacroID())
- return;
+ case Stmt::DoStmtClass:
+ if (*(Src->succ_begin()) == Dst) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
- const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
+ os << "Loop condition is true. ";
+ PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
- while (!CLocs.empty()) {
- ContextLocation &TopContextLoc = CLocs.back();
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
- // Is the top location context the same as the one for the new location?
- if (TopContextLoc == CLoc) {
- if (alwaysAdd) {
- if (IsConsumedExpr(TopContextLoc))
- TopContextLoc.markDead();
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
+ os.str()));
+ } else {
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
- rawAddEdge(NewLoc);
- }
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
- if (IsPostJump)
- TopContextLoc.markDead();
- return;
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(
+ Start, End, "Loop condition is false. Exiting loop"));
}
+ break;
- if (containsLocation(TopContextLoc, CLoc)) {
- if (alwaysAdd) {
- rawAddEdge(NewLoc);
-
- if (IsConsumedExpr(CLoc)) {
- CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true));
- return;
- }
- }
+ case Stmt::WhileStmtClass:
+ case Stmt::ForStmtClass:
+ if (*(Src->succ_begin() + 1) == Dst) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "Loop condition is false. ";
+ PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
+ os.str()));
+ } else {
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
- CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump));
- return;
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(
+ Start, End, "Loop condition is true. Entering loop body"));
}
- // Context does not contain the location. Flush it.
- popLocation();
- }
-
- // If we reach here, there is no enclosing context. Just add the edge.
- rawAddEdge(NewLoc);
-}
+ break;
-bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
- if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
- return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
+ case Stmt::IfStmtClass: {
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
- return false;
-}
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
-void EdgeBuilder::addExtendedContext(const Stmt *S) {
- if (!S)
- return;
-
- const Stmt *Parent = PDB.getParent(S);
- while (Parent) {
- if (isa<CompoundStmt>(Parent))
- Parent = PDB.getParent(Parent);
+ if (*(Src->succ_begin() + 1) == Dst)
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(
+ Start, End, "Taking false branch"));
else
- break;
- }
+ PD.getActivePath().push_front(
+ std::make_shared<PathDiagnosticControlFlowPiece>(
+ Start, End, "Taking true branch"));
- if (Parent) {
- switch (Parent->getStmtClass()) {
- case Stmt::DoStmtClass:
- case Stmt::ObjCAtSynchronizedStmtClass:
- addContext(Parent);
- default:
- break;
- }
+ break;
}
-
- addContext(S);
-}
-
-void EdgeBuilder::addContext(const Stmt *S) {
- if (!S)
- return;
-
- PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC);
- addContext(L);
-}
-
-void EdgeBuilder::addContext(const PathDiagnosticLocation &L) {
- while (!CLocs.empty()) {
- const PathDiagnosticLocation &TopContextLoc = CLocs.back();
-
- // Is the top location context the same as the one for the new location?
- if (TopContextLoc == L)
- return;
-
- if (containsLocation(TopContextLoc, L)) {
- CLocs.push_back(L);
- return;
- }
-
- // Context does not contain the location. Flush it.
- popLocation();
}
-
- CLocs.push_back(L);
}
// Cone-of-influence: support the reverse propagation of "interesting" symbols
@@ -1256,7 +826,7 @@ void EdgeBuilder::addContext(const PathDiagnosticLocation &L) {
// because the constraint solver sometimes simplifies certain symbolic values
// into constants when appropriate, and this complicates reasoning about
// interesting values.
-typedef llvm::DenseSet<const Expr *> InterestingExprs;
+using InterestingExprs = llvm::DenseSet<const Expr *>;
static void reversePropagateIntererstingSymbols(BugReport &R,
InterestingExprs &IE,
@@ -1275,7 +845,7 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
case Stmt::BinaryOperatorClass:
case Stmt::UnaryOperatorClass: {
for (const Stmt *SubStmt : Ex->children()) {
- if (const Expr *child = dyn_cast_or_null<Expr>(SubStmt)) {
+ if (const auto *child = dyn_cast_or_null<Expr>(SubStmt)) {
IE.insert(child);
SVal ChildV = State->getSVal(child, LCtx);
R.markInteresting(ChildV);
@@ -1295,10 +865,10 @@ static void reversePropagateInterestingSymbols(BugReport &R,
const LocationContext *CallerCtx)
{
// FIXME: Handle non-CallExpr-based CallEvents.
- const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame();
+ const StackFrameContext *Callee = CalleeCtx->getStackFrame();
const Stmt *CallSite = Callee->getCallSite();
- if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
+ if (const auto *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
FunctionDecl::param_const_iterator PI = FD->param_begin(),
PE = FD->param_end();
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
@@ -1338,16 +908,6 @@ static bool isJumpToFalseBranch(const BlockEdge *BE) {
return (*(Src->succ_begin()+1) == BE->getDst());
}
-/// Return true if the terminator is a loop and the destination is the
-/// false branch.
-static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) {
- if (!isLoop(Term))
- return false;
-
- // Did we take the false branch?
- return isJumpToFalseBranch(BE);
-}
-
static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) {
while (SubS) {
if (SubS == S)
@@ -1375,7 +935,7 @@ static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
const Stmt *LoopBody = nullptr;
switch (Term->getStmtClass()) {
case Stmt::CXXForRangeStmtClass: {
- const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
+ const auto *FR = cast<CXXForRangeStmt>(Term);
if (isContainedByStmt(PM, FR->getInc(), S))
return true;
if (isContainedByStmt(PM, FR->getLoopVarStmt(), S))
@@ -1384,14 +944,14 @@ static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
break;
}
case Stmt::ForStmtClass: {
- const ForStmt *FS = cast<ForStmt>(Term);
+ const auto *FS = cast<ForStmt>(Term);
if (isContainedByStmt(PM, FS->getInc(), S))
return true;
LoopBody = FS->getBody();
break;
}
case Stmt::ObjCForCollectionStmtClass: {
- const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term);
+ const auto *FC = cast<ObjCForCollectionStmt>(Term);
LoopBody = FC->getBody();
break;
}
@@ -1404,210 +964,7 @@ static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
return isContainedByStmt(PM, LoopBody, S);
}
-//===----------------------------------------------------------------------===//
-// Top-level logic for generating extensive path diagnostics.
-//===----------------------------------------------------------------------===//
-
-static bool GenerateExtensivePathDiagnostic(
- PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
- LocationContextMap &LCM,
- ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
- EdgeBuilder EB(PD, PDB);
- const SourceManager& SM = PDB.getSourceManager();
- StackDiagVector CallStack;
- InterestingExprs IE;
-
- const ExplodedNode *NextNode = N->pred_empty() ? nullptr : *(N->pred_begin());
- while (NextNode) {
- N = NextNode;
- NextNode = N->getFirstPred();
- ProgramPoint P = N->getLocation();
-
- do {
- if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
- if (const Expr *Ex = PS->getStmtAs<Expr>())
- reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(), Ex,
- N->getLocationContext());
- }
-
- if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
- const Stmt *S = CE->getCalleeContext()->getCallSite();
- if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
- reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(), Ex,
- N->getLocationContext());
- }
-
- auto C = PathDiagnosticCallPiece::construct(N, *CE, SM);
- LCM[&C->path] = CE->getCalleeContext();
-
- EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true);
- EB.flushLocations();
-
- auto *P = C.get();
- PD.getActivePath().push_front(std::move(C));
- PD.pushActivePath(&P->path);
- CallStack.push_back(StackDiagPair(P, N));
- break;
- }
-
- // Pop the call hierarchy if we are done walking the contents
- // of a function call.
- if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
- // Add an edge to the start of the function.
- const Decl *D = CE->getCalleeContext()->getDecl();
- PathDiagnosticLocation pos =
- PathDiagnosticLocation::createBegin(D, SM);
- EB.addEdge(pos);
-
- // Flush all locations, and pop the active path.
- bool VisitedEntireCall = PD.isWithinCall();
- EB.flushLocations();
- PD.popActivePath();
- PDB.LC = N->getLocationContext();
-
- // Either we just added a bunch of stuff to the top-level path, or
- // we have a previous CallExitEnd. If the former, it means that the
- // path terminated within a function call. We must then take the
- // current contents of the active path and place it within
- // a new PathDiagnosticCallPiece.
- PathDiagnosticCallPiece *C;
- if (VisitedEntireCall) {
- C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front().get());
- } else {
- const Decl *Caller = CE->getLocationContext()->getDecl();
- C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
- LCM[&C->path] = CE->getCalleeContext();
- }
-
- C->setCallee(*CE, SM);
- EB.addContext(C->getLocation());
-
- if (!CallStack.empty()) {
- assert(CallStack.back().first == C);
- CallStack.pop_back();
- }
- break;
- }
-
- // Note that is important that we update the LocationContext
- // after looking at CallExits. CallExit basically adds an
- // edge in the *caller*, so we don't want to update the LocationContext
- // too soon.
- PDB.LC = N->getLocationContext();
-
- // Block edges.
- if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
- // Does this represent entering a call? If so, look at propagating
- // interesting symbols across call boundaries.
- if (NextNode) {
- const LocationContext *CallerCtx = NextNode->getLocationContext();
- const LocationContext *CalleeCtx = PDB.LC;
- if (CallerCtx != CalleeCtx) {
- reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(),
- CalleeCtx, CallerCtx);
- }
- }
-
- // Are we jumping to the head of a loop? Add a special diagnostic.
- if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
- PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const CompoundStmt *CS = nullptr;
-
- if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
- CS = dyn_cast<CompoundStmt>(FS->getBody());
- else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
- CS = dyn_cast<CompoundStmt>(WS->getBody());
-
- auto p = std::make_shared<PathDiagnosticEventPiece>(
- L, "Looping back to the head of the loop");
- p->setPrunable(true);
-
- EB.addEdge(p->getLocation(), true);
- PD.getActivePath().push_front(std::move(p));
-
- if (CS) {
- PathDiagnosticLocation BL =
- PathDiagnosticLocation::createEndBrace(CS, SM);
- EB.addEdge(BL);
- }
- }
-
- const CFGBlock *BSrc = BE->getSrc();
- ParentMap &PM = PDB.getParentMap();
-
- if (const Stmt *Term = BSrc->getTerminator()) {
- // Are we jumping past the loop body without ever executing the
- // loop (because the condition was false)?
- if (isLoopJumpPastBody(Term, &*BE) &&
- !isInLoopBody(PM,
- getStmtBeforeCond(PM,
- BSrc->getTerminatorCondition(),
- N),
- Term)) {
- PathDiagnosticLocation L(Term, SM, PDB.LC);
- auto PE = std::make_shared<PathDiagnosticEventPiece>(
- L, "Loop body executed 0 times");
- PE->setPrunable(true);
-
- EB.addEdge(PE->getLocation(), true);
- PD.getActivePath().push_front(std::move(PE));
- }
-
- // In any case, add the terminator as the current statement
- // context for control edges.
- EB.addContext(Term);
- }
-
- break;
- }
-
- if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
- Optional<CFGElement> First = BE->getFirstElement();
- if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) {
- const Stmt *stmt = S->getStmt();
- if (IsControlFlowExpr(stmt)) {
- // Add the proper context for '&&', '||', and '?'.
- EB.addContext(stmt);
- }
- else
- EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
- }
-
- break;
- }
-
-
- } while (0);
-
- if (!NextNode)
- continue;
-
- // Add pieces from custom visitors.
- BugReport *R = PDB.getBugReport();
- llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
- for (auto &V : visitors) {
- if (auto p = V->VisitNode(N, NextNode, PDB, *R)) {
- if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get())
- continue;
-
- const PathDiagnosticLocation &Loc = p->getLocation();
- EB.addEdge(Loc, true);
- updateStackPiecesWithMessage(*p, CallStack);
- PD.getActivePath().push_front(std::move(p));
-
- if (const Stmt *S = Loc.asStmt())
- EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
- }
- }
- }
-
- return PDB.getBugReport()->isValid();
-}
-
-/// \brief Adds a sanitized control-flow diagnostic edge to a path.
+/// Adds a sanitized control-flow diagnostic edge to a path.
static void addEdgeToPath(PathPieces &path,
PathDiagnosticLocation &PrevLoc,
PathDiagnosticLocation NewLoc,
@@ -1638,8 +995,7 @@ static void addEdgeToPath(PathPieces &path,
/// which returns the element for ObjCForCollectionStmts.
static const Stmt *getTerminatorCondition(const CFGBlock *B) {
const Stmt *S = B->getTerminatorCondition();
- if (const ObjCForCollectionStmt *FS =
- dyn_cast_or_null<ObjCForCollectionStmt>(S))
+ if (const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(S))
return FS->getElement();
return S;
}
@@ -1651,269 +1007,256 @@ static const char StrLoopRangeEmpty[] =
static const char StrLoopCollectionEmpty[] =
"Loop body skipped when collection is empty";
-static bool GenerateAlternateExtensivePathDiagnostic(
- PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
- LocationContextMap &LCM,
- ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
-
- BugReport *report = PDB.getBugReport();
+static std::unique_ptr<FilesToLineNumsMap>
+findExecutedLines(SourceManager &SM, const ExplodedNode *N);
+
+/// Generate diagnostics for the node \p N,
+/// and write it into \p PD.
+/// \p AddPathEdges Whether diagnostic consumer can generate path arrows
+/// showing both row and column.
+static void generatePathDiagnosticsForNode(const ExplodedNode *N,
+ PathDiagnostic &PD,
+ PathDiagnosticLocation &PrevLoc,
+ PathDiagnosticBuilder &PDB,
+ LocationContextMap &LCM,
+ StackDiagVector &CallStack,
+ InterestingExprs &IE,
+ bool AddPathEdges) {
+ ProgramPoint P = N->getLocation();
const SourceManager& SM = PDB.getSourceManager();
- StackDiagVector CallStack;
- InterestingExprs IE;
- PathDiagnosticLocation PrevLoc = PD.getLocation();
+ // Have we encountered an entrance to a call? It may be
+ // the case that we have not encountered a matching
+ // call exit before this point. This means that the path
+ // terminated within the call itself.
+ if (auto CE = P.getAs<CallEnter>()) {
+
+ if (AddPathEdges) {
+ // Add an edge to the start of the function.
+ const StackFrameContext *CalleeLC = CE->getCalleeContext();
+ const Decl *D = CalleeLC->getDecl();
+ // Add the edge only when the callee has body. We jump to the beginning
+ // of the *declaration*, however we expect it to be followed by the
+ // body. This isn't the case for autosynthesized property accessors in
+ // Objective-C. No need for a similar extra check for CallExit points
+ // because the exit edge comes from a statement (i.e. return),
+ // not from declaration.
+ if (D->hasBody())
+ addEdgeToPath(PD.getActivePath(), PrevLoc,
+ PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
+ }
- const ExplodedNode *NextNode = N->getFirstPred();
- while (NextNode) {
- N = NextNode;
- NextNode = N->getFirstPred();
- ProgramPoint P = N->getLocation();
-
- do {
- // Have we encountered an entrance to a call? It may be
- // the case that we have not encountered a matching
- // call exit before this point. This means that the path
- // terminated within the call itself.
- if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
- // Add an edge to the start of the function.
- const StackFrameContext *CalleeLC = CE->getCalleeContext();
- const Decl *D = CalleeLC->getDecl();
- // Add the edge only when the callee has body. We jump to the beginning
- // of the *declaration*, however we expect it to be followed by the
- // body. This isn't the case for autosynthesized property accessors in
- // Objective-C. No need for a similar extra check for CallExit points
- // because the exit edge comes from a statement (i.e. return),
- // not from declaration.
- if (D->hasBody())
- addEdgeToPath(PD.getActivePath(), PrevLoc,
- PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
+ // Did we visit an entire call?
+ bool VisitedEntireCall = PD.isWithinCall();
+ PD.popActivePath();
- // Did we visit an entire call?
- bool VisitedEntireCall = PD.isWithinCall();
- PD.popActivePath();
+ PathDiagnosticCallPiece *C;
+ if (VisitedEntireCall) {
+ C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front().get());
+ } else {
+ const Decl *Caller = CE->getLocationContext()->getDecl();
+ C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
+
+ if (AddPathEdges) {
+ // Since we just transferred the path over to the call piece,
+ // reset the mapping from active to location context.
+ assert(PD.getActivePath().size() == 1 &&
+ PD.getActivePath().front().get() == C);
+ LCM[&PD.getActivePath()] = nullptr;
+ }
- PathDiagnosticCallPiece *C;
- if (VisitedEntireCall) {
- PathDiagnosticPiece *P = PD.getActivePath().front().get();
- C = cast<PathDiagnosticCallPiece>(P);
- } else {
- const Decl *Caller = CE->getLocationContext()->getDecl();
- C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
-
- // Since we just transferred the path over to the call piece,
- // reset the mapping from active to location context.
- assert(PD.getActivePath().size() == 1 &&
- PD.getActivePath().front().get() == C);
- LCM[&PD.getActivePath()] = nullptr;
-
- // Record the location context mapping for the path within
- // the call.
- assert(LCM[&C->path] == nullptr ||
- LCM[&C->path] == CE->getCalleeContext());
- LCM[&C->path] = CE->getCalleeContext();
-
- // If this is the first item in the active path, record
- // the new mapping from active path to location context.
- const LocationContext *&NewLC = LCM[&PD.getActivePath()];
- if (!NewLC)
- NewLC = N->getLocationContext();
-
- PDB.LC = NewLC;
- }
- C->setCallee(*CE, SM);
+ // Record the location context mapping for the path within
+ // the call.
+ assert(LCM[&C->path] == nullptr ||
+ LCM[&C->path] == CE->getCalleeContext());
+ LCM[&C->path] = CE->getCalleeContext();
- // Update the previous location in the active path.
- PrevLoc = C->getLocation();
+ // If this is the first item in the active path, record
+ // the new mapping from active path to location context.
+ const LocationContext *&NewLC = LCM[&PD.getActivePath()];
+ if (!NewLC)
+ NewLC = N->getLocationContext();
- if (!CallStack.empty()) {
- assert(CallStack.back().first == C);
- CallStack.pop_back();
- }
- break;
- }
+ PDB.LC = NewLC;
+ }
+ C->setCallee(*CE, SM);
- // Query the location context here and the previous location
- // as processing CallEnter may change the active path.
- PDB.LC = N->getLocationContext();
+ // Update the previous location in the active path.
+ PrevLoc = C->getLocation();
- // Record the mapping from the active path to the location
- // context.
- assert(!LCM[&PD.getActivePath()] ||
- LCM[&PD.getActivePath()] == PDB.LC);
- LCM[&PD.getActivePath()] = PDB.LC;
-
- // Have we encountered an exit from a function call?
- if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
- const Stmt *S = CE->getCalleeContext()->getCallSite();
- // Propagate the interesting symbols accordingly.
- if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
- reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(), Ex,
- N->getLocationContext());
- }
+ if (!CallStack.empty()) {
+ assert(CallStack.back().first == C);
+ CallStack.pop_back();
+ }
+ return;
+ }
- // We are descending into a call (backwards). Construct
- // a new call piece to contain the path pieces for that call.
- auto C = PathDiagnosticCallPiece::construct(N, *CE, SM);
- // Record the location context for this call piece.
- LCM[&C->path] = CE->getCalleeContext();
+ if (AddPathEdges) {
+ // Query the location context here and the previous location
+ // as processing CallEnter may change the active path.
+ PDB.LC = N->getLocationContext();
- // Add the edge to the return site.
- addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC);
- auto *P = C.get();
- PD.getActivePath().push_front(std::move(C));
- PrevLoc.invalidate();
+ // Record the mapping from the active path to the location
+ // context.
+ assert(!LCM[&PD.getActivePath()] || LCM[&PD.getActivePath()] == PDB.LC);
+ LCM[&PD.getActivePath()] = PDB.LC;
+ }
- // Make the contents of the call the active path for now.
- PD.pushActivePath(&P->path);
- CallStack.push_back(StackDiagPair(P, N));
- break;
- }
+ // Have we encountered an exit from a function call?
+ if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
- if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
- // For expressions, make sure we propagate the
- // interesting symbols correctly.
- if (const Expr *Ex = PS->getStmtAs<Expr>())
- reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(), Ex,
- N->getLocationContext());
-
- // Add an edge. If this is an ObjCForCollectionStmt do
- // not add an edge here as it appears in the CFG both
- // as a terminator and as a terminator condition.
- if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
- PathDiagnosticLocation L =
- PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC);
- addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
- }
- break;
+ // We are descending into a call (backwards). Construct
+ // a new call piece to contain the path pieces for that call.
+ auto C = PathDiagnosticCallPiece::construct(N, *CE, SM);
+ // Record the mapping from call piece to LocationContext.
+ LCM[&C->path] = CE->getCalleeContext();
+
+ if (AddPathEdges) {
+ const Stmt *S = CE->getCalleeContext()->getCallSite();
+ // Propagate the interesting symbols accordingly.
+ if (const auto *Ex = dyn_cast_or_null<Expr>(S)) {
+ reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
+ N->getState().get(), Ex,
+ N->getLocationContext());
}
+ // Add the edge to the return site.
+ addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC);
+ PrevLoc.invalidate();
+ }
- // Block edges.
- if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
- // Does this represent entering a call? If so, look at propagating
- // interesting symbols across call boundaries.
- if (NextNode) {
- const LocationContext *CallerCtx = NextNode->getLocationContext();
- const LocationContext *CalleeCtx = PDB.LC;
- if (CallerCtx != CalleeCtx) {
- reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(),
- CalleeCtx, CallerCtx);
- }
- }
+ auto *P = C.get();
+ PD.getActivePath().push_front(std::move(C));
- // Are we jumping to the head of a loop? Add a special diagnostic.
- if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
- PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const Stmt *Body = nullptr;
-
- if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
- Body = FS->getBody();
- else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
- Body = WS->getBody();
- else if (const ObjCForCollectionStmt *OFS =
- dyn_cast<ObjCForCollectionStmt>(Loop)) {
- Body = OFS->getBody();
- } else if (const CXXForRangeStmt *FRS =
- dyn_cast<CXXForRangeStmt>(Loop)) {
- Body = FRS->getBody();
- }
- // do-while statements are explicitly excluded here
+ // Make the contents of the call the active path for now.
+ PD.pushActivePath(&P->path);
+ CallStack.push_back(StackDiagPair(P, N));
+ return;
+ }
- auto p = std::make_shared<PathDiagnosticEventPiece>(
- L, "Looping back to the head "
- "of the loop");
- p->setPrunable(true);
+ if (auto PS = P.getAs<PostStmt>()) {
+ if (!AddPathEdges)
+ return;
- addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
- PD.getActivePath().push_front(std::move(p));
+ // For expressions, make sure we propagate the
+ // interesting symbols correctly.
+ if (const Expr *Ex = PS->getStmtAs<Expr>())
+ reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
+ N->getState().get(), Ex,
+ N->getLocationContext());
+
+ // Add an edge. If this is an ObjCForCollectionStmt do
+ // not add an edge here as it appears in the CFG both
+ // as a terminator and as a terminator condition.
+ if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
+ PathDiagnosticLocation L =
+ PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC);
+ addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
+ }
- if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
- addEdgeToPath(PD.getActivePath(), PrevLoc,
- PathDiagnosticLocation::createEndBrace(CS, SM),
- PDB.LC);
- }
- }
+ } else if (auto BE = P.getAs<BlockEdge>()) {
- const CFGBlock *BSrc = BE->getSrc();
- ParentMap &PM = PDB.getParentMap();
-
- if (const Stmt *Term = BSrc->getTerminator()) {
- // Are we jumping past the loop body without ever executing the
- // loop (because the condition was false)?
- if (isLoop(Term)) {
- const Stmt *TermCond = getTerminatorCondition(BSrc);
- bool IsInLoopBody =
- isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
-
- const char *str = nullptr;
-
- if (isJumpToFalseBranch(&*BE)) {
- if (!IsInLoopBody) {
- if (isa<ObjCForCollectionStmt>(Term)) {
- str = StrLoopCollectionEmpty;
- } else if (isa<CXXForRangeStmt>(Term)) {
- str = StrLoopRangeEmpty;
- } else {
- str = StrLoopBodyZero;
- }
- }
- } else {
- str = StrEnteringLoop;
- }
+ if (!AddPathEdges) {
+ generateMinimalDiagForBlockEdge(N, *BE, SM, PDB, PD);
+ return;
+ }
- if (str) {
- PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC);
- auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
- PE->setPrunable(true);
- addEdgeToPath(PD.getActivePath(), PrevLoc,
- PE->getLocation(), PDB.LC);
- PD.getActivePath().push_front(std::move(PE));
- }
- } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
- isa<GotoStmt>(Term)) {
- PathDiagnosticLocation L(Term, SM, PDB.LC);
- addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
- }
- }
- break;
+ // Does this represent entering a call? If so, look at propagating
+ // interesting symbols across call boundaries.
+ if (const ExplodedNode *NextNode = N->getFirstPred()) {
+ const LocationContext *CallerCtx = NextNode->getLocationContext();
+ const LocationContext *CalleeCtx = PDB.LC;
+ if (CallerCtx != CalleeCtx && AddPathEdges) {
+ reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
+ N->getState().get(),
+ CalleeCtx, CallerCtx);
}
- } while (0);
+ }
- if (!NextNode)
- continue;
+ // Are we jumping to the head of a loop? Add a special diagnostic.
+ if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
+ PathDiagnosticLocation L(Loop, SM, PDB.LC);
+ const Stmt *Body = nullptr;
+
+ if (const auto *FS = dyn_cast<ForStmt>(Loop))
+ Body = FS->getBody();
+ else if (const auto *WS = dyn_cast<WhileStmt>(Loop))
+ Body = WS->getBody();
+ else if (const auto *OFS = dyn_cast<ObjCForCollectionStmt>(Loop)) {
+ Body = OFS->getBody();
+ } else if (const auto *FRS = dyn_cast<CXXForRangeStmt>(Loop)) {
+ Body = FRS->getBody();
+ }
+ // do-while statements are explicitly excluded here
- // Add pieces from custom visitors.
- llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
- for (auto &V : visitors) {
- if (auto p = V->VisitNode(N, NextNode, PDB, *report)) {
- if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get())
- continue;
+ auto p = std::make_shared<PathDiagnosticEventPiece>(
+ L, "Looping back to the head "
+ "of the loop");
+ p->setPrunable(true);
- addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
- updateStackPiecesWithMessage(*p, CallStack);
- PD.getActivePath().push_front(std::move(p));
+ addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
+ PD.getActivePath().push_front(std::move(p));
+
+ if (const auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
+ addEdgeToPath(PD.getActivePath(), PrevLoc,
+ PathDiagnosticLocation::createEndBrace(CS, SM),
+ PDB.LC);
}
}
- }
- // Add an edge to the start of the function.
- // We'll prune it out later, but it helps make diagnostics more uniform.
- const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame();
- const Decl *D = CalleeLC->getDecl();
- addEdgeToPath(PD.getActivePath(), PrevLoc,
- PathDiagnosticLocation::createBegin(D, SM),
- CalleeLC);
+ const CFGBlock *BSrc = BE->getSrc();
+ ParentMap &PM = PDB.getParentMap();
+
+ if (const Stmt *Term = BSrc->getTerminator()) {
+ // Are we jumping past the loop body without ever executing the
+ // loop (because the condition was false)?
+ if (isLoop(Term)) {
+ const Stmt *TermCond = getTerminatorCondition(BSrc);
+ bool IsInLoopBody =
+ isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
+
+ const char *str = nullptr;
+
+ if (isJumpToFalseBranch(&*BE)) {
+ if (!IsInLoopBody) {
+ if (isa<ObjCForCollectionStmt>(Term)) {
+ str = StrLoopCollectionEmpty;
+ } else if (isa<CXXForRangeStmt>(Term)) {
+ str = StrLoopRangeEmpty;
+ } else {
+ str = StrLoopBodyZero;
+ }
+ }
+ } else {
+ str = StrEnteringLoop;
+ }
- return report->isValid();
+ if (str) {
+ PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC);
+ auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
+ PE->setPrunable(true);
+ addEdgeToPath(PD.getActivePath(), PrevLoc,
+ PE->getLocation(), PDB.LC);
+ PD.getActivePath().push_front(std::move(PE));
+ }
+ } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
+ isa<GotoStmt>(Term)) {
+ PathDiagnosticLocation L(Term, SM, PDB.LC);
+ addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
+ }
+ }
+ }
}
-static const Stmt *getLocStmt(PathDiagnosticLocation L) {
- if (!L.isValid())
- return nullptr;
- return L.asStmt();
+static std::unique_ptr<PathDiagnostic>
+generateEmptyDiagnosticForReport(BugReport *R, SourceManager &SM) {
+ BugType &BT = R->getBugType();
+ return llvm::make_unique<PathDiagnostic>(
+ R->getBugType().getCheckName(), R->getDeclWithIssue(),
+ R->getBugType().getName(), R->getDescription(),
+ R->getShortDescription(/*Fallback=*/false), BT.getCategory(),
+ R->getUniqueingLocation(), R->getUniqueingDecl(),
+ findExecutedLines(SM, R->getErrorNode()));
}
static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
@@ -1940,7 +1283,7 @@ static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
switch (S->getStmtClass()) {
case Stmt::BinaryOperatorClass: {
- const BinaryOperator *BO = cast<BinaryOperator>(S);
+ const auto *BO = cast<BinaryOperator>(S);
if (!BO->isLogicalOp())
return false;
return BO->getLHS() == Cond || BO->getRHS() == Cond;
@@ -1962,7 +1305,7 @@ static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
case Stmt::BinaryConditionalOperatorClass:
return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
case Stmt::ConditionalOperatorClass: {
- const ConditionalOperator *CO = cast<ConditionalOperator>(S);
+ const auto *CO = cast<ConditionalOperator>(S);
return CO->getCond() == Cond ||
CO->getLHS() == Cond ||
CO->getRHS() == Cond;
@@ -1970,7 +1313,7 @@ static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
case Stmt::ObjCForCollectionStmtClass:
return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
case Stmt::CXXForRangeStmtClass: {
- const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S);
+ const auto *FRS = cast<CXXForRangeStmt>(S);
return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
}
default:
@@ -1979,16 +1322,15 @@ static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
}
static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
- if (const ForStmt *FS = dyn_cast<ForStmt>(FL))
+ if (const auto *FS = dyn_cast<ForStmt>(FL))
return FS->getInc() == S || FS->getInit() == S;
- if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL))
+ if (const auto *FRS = dyn_cast<CXXForRangeStmt>(FL))
return FRS->getInc() == S || FRS->getRangeStmt() == S ||
FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
return false;
}
-typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
- OptimizedCallsSet;
+using OptimizedCallsSet = llvm::DenseSet<const PathDiagnosticCallPiece *>;
/// Adds synthetic edges from top-level statements to their subexpressions.
///
@@ -2000,8 +1342,7 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
PathPieces::iterator Prev = pieces.end();
for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
Prev = I, ++I) {
- PathDiagnosticControlFlowPiece *Piece =
- dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ auto *Piece = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!Piece)
continue;
@@ -2022,7 +1363,7 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
// This is important for nested logical expressions (||, &&, ?:) where we
// want to show all the levels of context.
while (true) {
- const Stmt *Dst = getLocStmt(Piece->getEndLocation());
+ const Stmt *Dst = Piece->getEndLocation().getStmtOrNull();
// We are looking at an edge. Is the destination within a larger
// expression?
@@ -2045,9 +1386,11 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
auto *PrevPiece = dyn_cast<PathDiagnosticControlFlowPiece>(Prev->get());
if (PrevPiece) {
- if (const Stmt *PrevSrc = getLocStmt(PrevPiece->getStartLocation())) {
+ if (const Stmt *PrevSrc =
+ PrevPiece->getStartLocation().getStmtOrNull()) {
const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM);
- if (PrevSrcParent == getStmtParent(getLocStmt(DstContext), PM)) {
+ if (PrevSrcParent ==
+ getStmtParent(DstContext.getStmtOrNull(), PM)) {
PrevPiece->setEndLocation(DstContext);
break;
}
@@ -2066,7 +1409,7 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
}
}
-/// \brief Move edges from a branch condition to a branch target
+/// Move edges from a branch condition to a branch target
/// when the condition is simple.
///
/// This restructures some of the work of addContextEdges. That function
@@ -2076,17 +1419,15 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
/// the branch to the branch condition, and (3) an edge from the branch
/// condition to the branch target. We keep (1), but may wish to remove (2)
/// and move the source of (3) to the branch if the branch condition is simple.
-///
static void simplifySimpleBranches(PathPieces &pieces) {
for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
-
- auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!PieceI)
continue;
- const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
- const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
+ const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
+ const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull();
if (!s1Start || !s1End)
continue;
@@ -2101,7 +1442,7 @@ static void simplifySimpleBranches(PathPieces &pieces) {
if (NextI == E)
break;
- auto *EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
+ const auto *EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
if (EV) {
StringRef S = EV->getString();
if (S == StrEnteringLoop || S == StrLoopBodyZero ||
@@ -2119,8 +1460,8 @@ static void simplifySimpleBranches(PathPieces &pieces) {
if (!PieceNextI)
continue;
- const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
- const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
+ const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
+ const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull();
if (!s2Start || !s2End || s1End != s2Start)
continue;
@@ -2151,7 +1492,7 @@ static void simplifySimpleBranches(PathPieces &pieces) {
static Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
SourceRange Range) {
SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
- SM.getExpansionRange(Range.getEnd()).second);
+ SM.getExpansionRange(Range.getEnd()).getEnd());
FileID FID = SM.getFileID(ExpansionRange.getBegin());
if (FID != SM.getFileID(ExpansionRange.getEnd()))
@@ -2203,22 +1544,21 @@ static void removeContextCycles(PathPieces &Path, SourceManager &SM,
ParentMap &PM) {
for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
// Pattern match the current piece and its successor.
- PathDiagnosticControlFlowPiece *PieceI =
- dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!PieceI) {
++I;
continue;
}
- const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
- const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
+ const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
+ const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull();
PathPieces::iterator NextI = I; ++NextI;
if (NextI == E)
break;
- PathDiagnosticControlFlowPiece *PieceNextI =
+ const auto *PieceNextI =
dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
if (!PieceNextI) {
@@ -2235,8 +1575,8 @@ static void removeContextCycles(PathPieces &Path, SourceManager &SM,
}
}
- const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
- const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
+ const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
+ const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull();
if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
const size_t MAX_SHORT_LINE_LENGTH = 80;
@@ -2255,10 +1595,8 @@ static void removeContextCycles(PathPieces &Path, SourceManager &SM,
}
}
-/// \brief Return true if X is contained by Y.
-static bool lexicalContains(ParentMap &PM,
- const Stmt *X,
- const Stmt *Y) {
+/// Return true if X is contained by Y.
+static bool lexicalContains(ParentMap &PM, const Stmt *X, const Stmt *Y) {
while (X) {
if (X == Y)
return true;
@@ -2268,24 +1606,21 @@ static bool lexicalContains(ParentMap &PM,
}
// Remove short edges on the same line less than 3 columns in difference.
-static void removePunyEdges(PathPieces &path,
- SourceManager &SM,
+static void removePunyEdges(PathPieces &path, SourceManager &SM,
ParentMap &PM) {
-
bool erased = false;
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
erased ? I : ++I) {
-
erased = false;
- auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!PieceI)
continue;
- const Stmt *start = getLocStmt(PieceI->getStartLocation());
- const Stmt *end = getLocStmt(PieceI->getEndLocation());
+ const Stmt *start = PieceI->getStartLocation().getStmtOrNull();
+ const Stmt *end = PieceI->getEndLocation().getStmtOrNull();
if (!start || !end)
continue;
@@ -2326,7 +1661,7 @@ static void removePunyEdges(PathPieces &path,
static void removeIdenticalEvents(PathPieces &path) {
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
- auto *PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());
if (!PieceI)
continue;
@@ -2335,7 +1670,7 @@ static void removeIdenticalEvents(PathPieces &path) {
if (NextI == E)
return;
- auto *PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
+ const auto *PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
if (!PieceNextI)
continue;
@@ -2376,8 +1711,8 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
continue;
}
- const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
- const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
+ const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
+ const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull();
const Stmt *level1 = getStmtParent(s1Start, PM);
const Stmt *level2 = getStmtParent(s1End, PM);
@@ -2385,15 +1720,15 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
if (NextI == E)
break;
- auto *PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
+ const auto *PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
if (!PieceNextI) {
++I;
continue;
}
- const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
- const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
+ const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
+ const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull();
const Stmt *level3 = getStmtParent(s2Start, PM);
const Stmt *level4 = getStmtParent(s2End, PM);
@@ -2411,7 +1746,6 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
//
// NOTE: this will be limited later in cases where we add barriers
// to prevent this optimization.
- //
if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
path.erase(NextI);
@@ -2426,7 +1760,6 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
//
// NOTE: this will be limited later in cases where we add barriers
// to prevent this optimization.
- //
if (s1End && s1End == s2Start && level2) {
bool removeEdge = false;
// Remove edges into the increment or initialization of a
@@ -2492,8 +1825,7 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
//
// (X -> element)
if (s1End == s2Start) {
- const ObjCForCollectionStmt *FS =
- dyn_cast_or_null<ObjCForCollectionStmt>(level3);
+ const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(level3);
if (FS && FS->getCollection()->IgnoreParens() == s2Start &&
s2End == FS->getElement()) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
@@ -2531,8 +1863,7 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
/// statement had an invalid source location), this function does nothing.
// FIXME: We should just generate invalid edges anyway and have the optimizer
// deal with them.
-static void dropFunctionEntryEdge(PathPieces &Path,
- LocationContextMap &LCM,
+static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM,
SourceManager &SM) {
const auto *FirstEdge =
dyn_cast<PathDiagnosticControlFlowPiece>(Path.front().get());
@@ -2547,11 +1878,134 @@ static void dropFunctionEntryEdge(PathPieces &Path,
Path.pop_front();
}
+using VisitorsDiagnosticsTy = llvm::DenseMap<const ExplodedNode *,
+ std::vector<std::shared_ptr<PathDiagnosticPiece>>>;
+
+/// This function is responsible for generating diagnostic pieces that are
+/// *not* provided by bug report visitors.
+/// These diagnostics may differ depending on the consumer's settings,
+/// and are therefore constructed separately for each consumer.
+///
+/// There are two path diagnostics generation modes: with adding edges (used
+/// for plists) and without (used for HTML and text).
+/// When edges are added (\p ActiveScheme is Extensive),
+/// the path is modified to insert artificially generated
+/// edges.
+/// Otherwise, more detailed diagnostics is emitted for block edges, explaining
+/// the transitions in words.
+static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
+ PathDiagnosticConsumer::PathGenerationScheme ActiveScheme,
+ PathDiagnosticBuilder &PDB,
+ const ExplodedNode *ErrorNode,
+ const VisitorsDiagnosticsTy &VisitorsDiagnostics) {
+
+ bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None);
+ bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive);
+ SourceManager &SM = PDB.getSourceManager();
+ BugReport *R = PDB.getBugReport();
+ AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions();
+ StackDiagVector CallStack;
+ InterestingExprs IE;
+ LocationContextMap LCM;
+ std::unique_ptr<PathDiagnostic> PD = generateEmptyDiagnosticForReport(R, SM);
+
+ if (GenerateDiagnostics) {
+ auto EndNotes = VisitorsDiagnostics.find(ErrorNode);
+ std::shared_ptr<PathDiagnosticPiece> LastPiece;
+ if (EndNotes != VisitorsDiagnostics.end()) {
+ assert(!EndNotes->second.empty());
+ LastPiece = EndNotes->second[0];
+ } else {
+ LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, ErrorNode, *R);
+ }
+ PD->setEndOfPath(LastPiece);
+ }
+
+ PathDiagnosticLocation PrevLoc = PD->getLocation();
+ const ExplodedNode *NextNode = ErrorNode->getFirstPred();
+ while (NextNode) {
+ if (GenerateDiagnostics)
+ generatePathDiagnosticsForNode(
+ NextNode, *PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges);
+
+ auto VisitorNotes = VisitorsDiagnostics.find(NextNode);
+ NextNode = NextNode->getFirstPred();
+ if (!GenerateDiagnostics || VisitorNotes == VisitorsDiagnostics.end())
+ continue;
+
+ // This is a workaround due to inability to put shared PathDiagnosticPiece
+ // into a FoldingSet.
+ std::set<llvm::FoldingSetNodeID> DeduplicationSet;
+
+ // Add pieces from custom visitors.
+ for (const auto &Note : VisitorNotes->second) {
+ llvm::FoldingSetNodeID ID;
+ Note->Profile(ID);
+ auto P = DeduplicationSet.insert(ID);
+ if (!P.second)
+ continue;
+
+ if (AddPathEdges)
+ addEdgeToPath(PD->getActivePath(), PrevLoc, Note->getLocation(),
+ PDB.LC);
+ updateStackPiecesWithMessage(*Note, CallStack);
+ PD->getActivePath().push_front(Note);
+ }
+ }
+
+ if (AddPathEdges) {
+ // Add an edge to the start of the function.
+ // We'll prune it out later, but it helps make diagnostics more uniform.
+ const StackFrameContext *CalleeLC = PDB.LC->getStackFrame();
+ const Decl *D = CalleeLC->getDecl();
+ addEdgeToPath(PD->getActivePath(), PrevLoc,
+ PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
+ }
+
+ if (!AddPathEdges && GenerateDiagnostics)
+ CompactPathDiagnostic(PD->getMutablePieces(), SM);
+
+ // Finally, prune the diagnostic path of uninteresting stuff.
+ if (!PD->path.empty()) {
+ if (R->shouldPrunePath() && Opts.shouldPrunePaths()) {
+ bool stillHasNotes =
+ removeUnneededCalls(PD->getMutablePieces(), R, LCM);
+ assert(stillHasNotes);
+ (void)stillHasNotes;
+ }
+
+ // Redirect all call pieces to have valid locations.
+ adjustCallLocations(PD->getMutablePieces());
+ removePiecesWithInvalidLocations(PD->getMutablePieces());
+
+ if (AddPathEdges) {
+
+ // Reduce the number of edges from a very conservative set
+ // to an aesthetically pleasing subset that conveys the
+ // necessary information.
+ OptimizedCallsSet OCS;
+ while (optimizeEdges(PD->getMutablePieces(), SM, OCS, LCM)) {}
+
+ // Drop the very first function-entry edge. It's not really necessary
+ // for top-level functions.
+ dropFunctionEntryEdge(PD->getMutablePieces(), LCM, SM);
+ }
+
+ // Remove messages that are basically the same, and edges that may not
+ // make sense.
+ // We have to do this after edge optimization in the Extensive mode.
+ removeRedundantMsgs(PD->getMutablePieces());
+ removeEdgesToDefaultInitializers(PD->getMutablePieces());
+ }
+ return PD;
+}
+
//===----------------------------------------------------------------------===//
// Methods for BugType and subclasses.
//===----------------------------------------------------------------------===//
-void BugType::anchor() { }
+
+void BugType::anchor() {}
void BugType::FlushReports(BugReporter &BR) {}
@@ -2569,14 +2023,17 @@ void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) {
llvm::FoldingSetNodeID ID;
visitor->Profile(ID);
- void *InsertPos;
- if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos))
+ void *InsertPos = nullptr;
+ if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
return;
+ }
- CallbacksSet.InsertNode(visitor.get(), InsertPos);
Callbacks.push_back(std::move(visitor));
- ++ConfigurationChangeToken;
+}
+
+void BugReport::clearVisitors() {
+ Callbacks.clear();
}
BugReport::~BugReport() {
@@ -2594,7 +2051,7 @@ const Decl *BugReport::getDeclWithIssue() const {
return nullptr;
const LocationContext *LC = N->getLocationContext();
- return LC->getCurrentStackFrame()->getDecl();
+ return LC->getStackFrame()->getDecl();
}
void BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
@@ -2622,11 +2079,9 @@ void BugReport::markInteresting(SymbolRef sym) {
if (!sym)
return;
- // If the symbol wasn't already in our set, note a configuration change.
- if (getInterestingSymbols().insert(sym).second)
- ++ConfigurationChangeToken;
+ getInterestingSymbols().insert(sym);
- if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym))
+ if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
getInterestingRegions().insert(meta->getRegion());
}
@@ -2634,12 +2089,10 @@ void BugReport::markInteresting(const MemRegion *R) {
if (!R)
return;
- // If the base region wasn't already in our set, note a configuration change.
R = R->getBaseRegion();
- if (getInterestingRegions().insert(R).second)
- ++ConfigurationChangeToken;
+ getInterestingRegions().insert(R);
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R))
getInterestingSymbols().insert(SR->getSymbol());
}
@@ -2673,7 +2126,7 @@ bool BugReport::isInteresting(const MemRegion *R) {
bool b = getInterestingRegions().count(R);
if (b)
return true;
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R))
return getInterestingSymbols().count(SR->getSymbol());
return false;
}
@@ -2733,7 +2186,7 @@ llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() {
// If no custom ranges, add the range of the statement corresponding to
// the error node.
if (Ranges.empty()) {
- if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
+ if (const auto *E = dyn_cast_or_null<Expr>(getStmt()))
addRange(E->getSourceRange());
else
return llvm::make_range(ranges_iterator(), ranges_iterator());
@@ -2761,9 +2214,11 @@ PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
// Methods for BugReporter and subclasses.
//===----------------------------------------------------------------------===//
-BugReportEquivClass::~BugReportEquivClass() { }
-GRBugReporter::~GRBugReporter() { }
-BugReporterData::~BugReporterData() {}
+BugReportEquivClass::~BugReportEquivClass() = default;
+
+GRBugReporter::~GRBugReporter() = default;
+
+BugReporterData::~BugReporterData() = default;
ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
@@ -2774,11 +2229,8 @@ BugReporter::~BugReporter() {
FlushReports();
// Free the bug reports we are tracking.
- typedef std::vector<BugReportEquivClass *> ContTy;
- for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
- I != E; ++I) {
- delete *I;
- }
+ for (const auto I : EQClassesVector)
+ delete I;
}
void BugReporter::FlushReports() {
@@ -2790,18 +2242,13 @@ void BugReporter::FlushReports() {
// FIXME: Only NSErrorChecker needs BugType's FlushReports.
// Turn NSErrorChecker into a proper checker and remove this.
SmallVector<const BugType *, 16> bugTypes(BugTypes.begin(), BugTypes.end());
- for (SmallVectorImpl<const BugType *>::iterator
- I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
- const_cast<BugType*>(*I)->FlushReports(*this);
+ for (const auto I : bugTypes)
+ const_cast<BugType*>(I)->FlushReports(*this);
// We need to flush reports in deterministic order to ensure the order
// of the reports is consistent between runs.
- typedef std::vector<BugReportEquivClass *> ContVecTy;
- for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end();
- EI != EE; ++EI){
- BugReportEquivClass& EQ = **EI;
- FlushReport(EQ);
- }
+ for (const auto EQ : EQClassesVector)
+ FlushReport(*EQ);
// BugReporter owns and deletes only BugTypes created implicitly through
// EmitBasicReport.
@@ -2818,6 +2265,7 @@ void BugReporter::FlushReports() {
//===----------------------------------------------------------------------===//
namespace {
+
/// A wrapper around a report graph, which contains only a single path, and its
/// node maps.
class ReportGraph {
@@ -2832,10 +2280,12 @@ public:
class TrimmedGraph {
InterExplodedGraphMap InverseMap;
- typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy;
+ using PriorityMapTy = llvm::DenseMap<const ExplodedNode *, unsigned>;
+
PriorityMapTy PriorityMap;
- typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair;
+ using NodeIndexPair = std::pair<const ExplodedNode *, size_t>;
+
SmallVector<NodeIndexPair, 32> ReportNodes;
std::unique_ptr<ExplodedGraph> G;
@@ -2873,7 +2323,8 @@ public:
bool popNextReportGraph(ReportGraph &GraphWrapper);
};
-}
+
+} // namespace
TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
ArrayRef<const ExplodedNode *> Nodes) {
@@ -2929,8 +2380,8 @@ TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
}
// Sort the error paths from longest to shortest.
- std::sort(ReportNodes.begin(), ReportNodes.end(),
- PriorityCompare<true>(PriorityMap));
+ llvm::sort(ReportNodes.begin(), ReportNodes.end(),
+ PriorityCompare<true>(PriorityMap));
}
bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
@@ -2986,23 +2437,21 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
return true;
}
-
/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
/// and collapses PathDiagosticPieces that are expanded by macros.
static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
- typedef std::vector<
- std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>
- MacroStackTy;
+ using MacroStackTy =
+ std::vector<
+ std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>;
- typedef std::vector<std::shared_ptr<PathDiagnosticPiece>> PiecesTy;
+ using PiecesTy = std::vector<std::shared_ptr<PathDiagnosticPiece>>;
MacroStackTy MacroStack;
PiecesTy Pieces;
for (PathPieces::const_iterator I = path.begin(), E = path.end();
- I!=E; ++I) {
-
- auto &piece = *I;
+ I != E; ++I) {
+ const auto &piece = *I;
// Recursively compact calls.
if (auto *call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {
@@ -3081,43 +2530,69 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
path.insert(path.end(), Pieces.begin(), Pieces.end());
}
-bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
- PathDiagnosticConsumer &PC,
- ArrayRef<BugReport *> &bugReports) {
- assert(!bugReports.empty());
+/// Generate notes from all visitors.
+/// Notes associated with {@code ErrorNode} are generated using
+/// {@code getEndPath}, and the rest are generated with {@code VisitNode}.
+static std::unique_ptr<VisitorsDiagnosticsTy>
+generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode,
+ BugReporterContext &BRC) {
+ auto Notes = llvm::make_unique<VisitorsDiagnosticsTy>();
+ BugReport::VisitorList visitors;
- bool HasValid = false;
- bool HasInvalid = false;
- SmallVector<const ExplodedNode *, 32> errorNodes;
- for (ArrayRef<BugReport*>::iterator I = bugReports.begin(),
- E = bugReports.end(); I != E; ++I) {
- if ((*I)->isValid()) {
- HasValid = true;
- errorNodes.push_back((*I)->getErrorNode());
- } else {
- // Keep the errorNodes list in sync with the bugReports list.
- HasInvalid = true;
- errorNodes.push_back(nullptr);
+ // Run visitors on all nodes starting from the node *before* the last one.
+ // The last node is reserved for notes generated with {@code getEndPath}.
+ const ExplodedNode *NextNode = ErrorNode->getFirstPred();
+ while (NextNode) {
+
+ // At each iteration, move all visitors from report to visitor list.
+ for (BugReport::visitor_iterator I = R->visitor_begin(),
+ E = R->visitor_end();
+ I != E; ++I) {
+ visitors.push_back(std::move(*I));
}
- }
+ R->clearVisitors();
- // If all the reports have been marked invalid by a previous path generation,
- // we're done.
- if (!HasValid)
- return false;
+ const ExplodedNode *Pred = NextNode->getFirstPred();
+ if (!Pred) {
+ std::shared_ptr<PathDiagnosticPiece> LastPiece;
+ for (auto &V : visitors) {
+ V->finalizeVisitor(BRC, ErrorNode, *R);
- typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme;
- PathGenerationScheme ActiveScheme = PC.getGenerationScheme();
+ if (auto Piece = V->getEndPath(BRC, ErrorNode, *R)) {
+ assert(!LastPiece &&
+ "There can only be one final piece in a diagnostic.");
+ LastPiece = std::move(Piece);
+ (*Notes)[ErrorNode].push_back(LastPiece);
+ }
+ }
+ break;
+ }
- if (ActiveScheme == PathDiagnosticConsumer::Extensive) {
- AnalyzerOptions &options = getAnalyzerOptions();
- if (options.getBooleanOption("path-diagnostics-alternate", true)) {
- ActiveScheme = PathDiagnosticConsumer::AlternateExtensive;
+ for (auto &V : visitors) {
+ auto P = V->VisitNode(NextNode, Pred, BRC, *R);
+ if (P)
+ (*Notes)[NextNode].push_back(std::move(P));
}
+
+ if (!R->isValid())
+ break;
+
+ NextNode = Pred;
}
- TrimmedGraph TrimG(&getGraph(), errorNodes);
- ReportGraph ErrorGraph;
+ return Notes;
+}
+
+/// Find a non-invalidated report for a given equivalence class,
+/// and return together with a cache of visitors notes.
+/// If none found, return a nullptr paired with an empty cache.
+static
+std::pair<BugReport*, std::unique_ptr<VisitorsDiagnosticsTy>> findValidReport(
+ TrimmedGraph &TrimG,
+ ReportGraph &ErrorGraph,
+ ArrayRef<BugReport *> &bugReports,
+ AnalyzerOptions &Opts,
+ GRBugReporter &Reporter) {
while (TrimG.popNextReportGraph(ErrorGraph)) {
// Find the BugReport with the original location.
@@ -3125,125 +2600,85 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
BugReport *R = bugReports[ErrorGraph.Index];
assert(R && "No original report found for sliced graph.");
assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
+ const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode;
- // Start building the path diagnostic...
- PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC);
- const ExplodedNode *N = ErrorGraph.ErrorNode;
+ // Register refutation visitors first, if they mark the bug invalid no
+ // further analysis is required
+ R->addVisitor(llvm::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());
// Register additional node visitors.
R->addVisitor(llvm::make_unique<NilReceiverBRVisitor>());
R->addVisitor(llvm::make_unique<ConditionBRVisitor>());
- R->addVisitor(llvm::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());
R->addVisitor(llvm::make_unique<CXXSelfAssignmentBRVisitor>());
- BugReport::VisitorList visitors;
- unsigned origReportConfigToken, finalReportConfigToken;
- LocationContextMap LCM;
-
- // While generating diagnostics, it's possible the visitors will decide
- // new symbols and regions are interesting, or add other visitors based on
- // the information they find. If they do, we need to regenerate the path
- // based on our new report configuration.
- do {
- // Get a clean copy of all the visitors.
- for (BugReport::visitor_iterator I = R->visitor_begin(),
- E = R->visitor_end(); I != E; ++I)
- visitors.push_back((*I)->clone());
-
- // Clear out the active path from any previous work.
- PD.resetPath();
- origReportConfigToken = R->getConfigurationChangeToken();
-
- // Generate the very last diagnostic piece - the piece is visible before
- // the trace is expanded.
- std::unique_ptr<PathDiagnosticPiece> LastPiece;
- for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
- I != E; ++I) {
- if (std::unique_ptr<PathDiagnosticPiece> Piece =
- (*I)->getEndPath(PDB, N, *R)) {
- assert (!LastPiece &&
- "There can only be one final piece in a diagnostic.");
- LastPiece = std::move(Piece);
- }
- }
+ BugReporterContext BRC(Reporter, ErrorGraph.BackMap);
- if (ActiveScheme != PathDiagnosticConsumer::None) {
- if (!LastPiece)
- LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
- assert(LastPiece);
- PD.setEndOfPath(std::move(LastPiece));
- }
+ // Run all visitors on a given graph, once.
+ std::unique_ptr<VisitorsDiagnosticsTy> visitorNotes =
+ generateVisitorsDiagnostics(R, ErrorNode, BRC);
- // Make sure we get a clean location context map so we don't
- // hold onto old mappings.
- LCM.clear();
+ if (R->isValid()) {
+ if (Opts.shouldCrosscheckWithZ3()) {
+ // If crosscheck is enabled, remove all visitors, add the refutation
+ // visitor and check again
+ R->clearVisitors();
+ R->addVisitor(llvm::make_unique<FalsePositiveRefutationBRVisitor>());
- switch (ActiveScheme) {
- case PathDiagnosticConsumer::AlternateExtensive:
- GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);
- break;
- case PathDiagnosticConsumer::Extensive:
- GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);
- break;
- case PathDiagnosticConsumer::Minimal:
- GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors);
- break;
- case PathDiagnosticConsumer::None:
- GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors);
- break;
+ // We don't overrite the notes inserted by other visitors because the
+ // refutation manager does not add any new note to the path
+ generateVisitorsDiagnostics(R, ErrorGraph.ErrorNode, BRC);
}
- // Clean up the visitors we used.
- visitors.clear();
-
- // Did anything change while generating this path?
- finalReportConfigToken = R->getConfigurationChangeToken();
- } while (finalReportConfigToken != origReportConfigToken);
-
- if (!R->isValid())
- continue;
-
- // Finally, prune the diagnostic path of uninteresting stuff.
- if (!PD.path.empty()) {
- if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) {
- bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM);
- assert(stillHasNotes);
- (void)stillHasNotes;
- }
+ // Check if the bug is still valid
+ if (R->isValid())
+ return std::make_pair(R, std::move(visitorNotes));
+ }
+ }
- // Redirect all call pieces to have valid locations.
- adjustCallLocations(PD.getMutablePieces());
- removePiecesWithInvalidLocations(PD.getMutablePieces());
+ return std::make_pair(nullptr, llvm::make_unique<VisitorsDiagnosticsTy>());
+}
- if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) {
- SourceManager &SM = getSourceManager();
+std::unique_ptr<DiagnosticForConsumerMapTy>
+GRBugReporter::generatePathDiagnostics(
+ ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> &bugReports) {
+ assert(!bugReports.empty());
- // Reduce the number of edges from a very conservative set
- // to an aesthetically pleasing subset that conveys the
- // necessary information.
- OptimizedCallsSet OCS;
- while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {}
+ auto Out = llvm::make_unique<DiagnosticForConsumerMapTy>();
+ bool HasValid = false;
+ SmallVector<const ExplodedNode *, 32> errorNodes;
+ for (const auto I : bugReports) {
+ if (I->isValid()) {
+ HasValid = true;
+ errorNodes.push_back(I->getErrorNode());
+ } else {
+ // Keep the errorNodes list in sync with the bugReports list.
+ errorNodes.push_back(nullptr);
+ }
+ }
- // Drop the very first function-entry edge. It's not really necessary
- // for top-level functions.
- dropFunctionEntryEdge(PD.getMutablePieces(), LCM, SM);
- }
+ // If all the reports have been marked invalid by a previous path generation,
+ // we're done.
+ if (!HasValid)
+ return Out;
- // Remove messages that are basically the same, and edges that may not
- // make sense.
- // We have to do this after edge optimization in the Extensive mode.
- removeRedundantMsgs(PD.getMutablePieces());
- removeEdgesToDefaultInitializers(PD.getMutablePieces());
+ TrimmedGraph TrimG(&getGraph(), errorNodes);
+ ReportGraph ErrorGraph;
+ auto ReportInfo = findValidReport(TrimG, ErrorGraph, bugReports,
+ getAnalyzerOptions(), *this);
+ BugReport *R = ReportInfo.first;
+
+ if (R && R->isValid()) {
+ const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode;
+ for (PathDiagnosticConsumer *PC : consumers) {
+ PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, PC);
+ std::unique_ptr<PathDiagnostic> PD = generatePathDiagnosticForConsumer(
+ PC->getGenerationScheme(), PDB, ErrorNode, *ReportInfo.second);
+ (*Out)[PC] = std::move(PD);
}
-
- // We found a report and didn't suppress it.
- return true;
}
- // We suppressed all the reports in this equivalence class.
- assert(!HasInvalid && "Inconsistent suppression");
- (void)HasInvalid;
- return false;
+ return Out;
}
void BugReporter::Register(BugType *BT) {
@@ -3293,20 +2728,21 @@ void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
EQ->AddReport(std::move(R));
}
-
//===----------------------------------------------------------------------===//
// Emitting reports in equivalence classes.
//===----------------------------------------------------------------------===//
namespace {
+
struct FRIEC_WLItem {
const ExplodedNode *N;
ExplodedNode::const_succ_iterator I, E;
FRIEC_WLItem(const ExplodedNode *n)
- : N(n), I(N->succ_begin()), E(N->succ_end()) {}
+ : N(n), I(N->succ_begin()), E(N->succ_end()) {}
};
-}
+
+} // namespace
static const CFGBlock *findBlockForNode(const ExplodedNode *N) {
ProgramPoint P = N->getLocation();
@@ -3396,7 +2832,6 @@ static bool isInevitablySinking(const ExplodedNode *N) {
static BugReport *
FindReportInEquivalenceClass(BugReportEquivClass& EQ,
SmallVectorImpl<BugReport*> &bugReports) {
-
BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
assert(I != E);
BugType& BT = I->getBugType();
@@ -3406,10 +2841,10 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// to 'Nodes'. Any of the reports will serve as a "representative" report.
if (!BT.isSuppressOnSink()) {
BugReport *R = &*I;
- for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
- const ExplodedNode *N = I->getErrorNode();
+ for (auto &I : EQ) {
+ const ExplodedNode *N = I.getErrorNode();
if (N) {
- R = &*I;
+ R = &I;
bugReports.push_back(R);
}
}
@@ -3450,8 +2885,9 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// At this point we know that 'N' is not a sink and it has at least one
// successor. Use a DFS worklist to find a non-sink end-of-path node.
- typedef FRIEC_WLItem WLItem;
- typedef SmallVector<WLItem, 10> DFSWorkList;
+ using WLItem = FRIEC_WLItem;
+ using DFSWorkList = SmallVector<WLItem, 10>;
+
llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
DFSWorkList WL;
@@ -3501,90 +2937,166 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
void BugReporter::FlushReport(BugReportEquivClass& EQ) {
SmallVector<BugReport*, 10> bugReports;
- BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
- if (exampleReport) {
- for (PathDiagnosticConsumer *PDC : getPathDiagnosticConsumers()) {
- FlushReport(exampleReport, *PDC, bugReports);
+ BugReport *report = FindReportInEquivalenceClass(EQ, bugReports);
+ if (!report)
+ return;
+
+ ArrayRef<PathDiagnosticConsumer*> Consumers = getPathDiagnosticConsumers();
+ std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics =
+ generateDiagnosticForConsumerMap(report, Consumers, bugReports);
+
+ for (auto &P : *Diagnostics) {
+ PathDiagnosticConsumer *Consumer = P.first;
+ std::unique_ptr<PathDiagnostic> &PD = P.second;
+
+ // If the path is empty, generate a single step path with the location
+ // of the issue.
+ if (PD->path.empty()) {
+ PathDiagnosticLocation L = report->getLocation(getSourceManager());
+ auto piece = llvm::make_unique<PathDiagnosticEventPiece>(
+ L, report->getDescription());
+ for (SourceRange Range : report->getRanges())
+ piece->addRange(Range);
+ PD->setEndOfPath(std::move(piece));
}
- }
-}
-void BugReporter::FlushReport(BugReport *exampleReport,
- PathDiagnosticConsumer &PD,
- ArrayRef<BugReport*> bugReports) {
+ PathPieces &Pieces = PD->getMutablePieces();
+ if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) {
+ // For path diagnostic consumers that don't support extra notes,
+ // we may optionally convert those to path notes.
+ for (auto I = report->getNotes().rbegin(),
+ E = report->getNotes().rend(); I != E; ++I) {
+ PathDiagnosticNotePiece *Piece = I->get();
+ auto ConvertedPiece = std::make_shared<PathDiagnosticEventPiece>(
+ Piece->getLocation(), Piece->getString());
+ for (const auto &R: Piece->getRanges())
+ ConvertedPiece->addRange(R);
+
+ Pieces.push_front(std::move(ConvertedPiece));
+ }
+ } else {
+ for (auto I = report->getNotes().rbegin(),
+ E = report->getNotes().rend(); I != E; ++I)
+ Pieces.push_front(*I);
+ }
- // FIXME: Make sure we use the 'R' for the path that was actually used.
- // Probably doesn't make a difference in practice.
- BugType& BT = exampleReport->getBugType();
+ // Get the meta data.
+ const BugReport::ExtraTextList &Meta = report->getExtraText();
+ for (const auto &i : Meta)
+ PD->addMeta(i);
- std::unique_ptr<PathDiagnostic> D(new PathDiagnostic(
- exampleReport->getBugType().getCheckName(),
- exampleReport->getDeclWithIssue(), exampleReport->getBugType().getName(),
- exampleReport->getDescription(),
- exampleReport->getShortDescription(/*Fallback=*/false), BT.getCategory(),
- exampleReport->getUniqueingLocation(),
- exampleReport->getUniqueingDecl()));
+ Consumer->HandlePathDiagnostic(std::move(PD));
+ }
+}
- if (exampleReport->isPathSensitive()) {
- // Generate the full path diagnostic, using the generation scheme
- // specified by the PathDiagnosticConsumer. Note that we have to generate
- // path diagnostics even for consumers which do not support paths, because
- // the BugReporterVisitors may mark this bug as a false positive.
- assert(!bugReports.empty());
+/// Insert all lines participating in the function signature \p Signature
+/// into \p ExecutedLines.
+static void populateExecutedLinesWithFunctionSignature(
+ const Decl *Signature, SourceManager &SM,
+ std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) {
+ SourceRange SignatureSourceRange;
+ const Stmt* Body = Signature->getBody();
+ if (const auto FD = dyn_cast<FunctionDecl>(Signature)) {
+ SignatureSourceRange = FD->getSourceRange();
+ } else if (const auto OD = dyn_cast<ObjCMethodDecl>(Signature)) {
+ SignatureSourceRange = OD->getSourceRange();
+ } else {
+ return;
+ }
+ SourceLocation Start = SignatureSourceRange.getBegin();
+ SourceLocation End = Body ? Body->getSourceRange().getBegin()
+ : SignatureSourceRange.getEnd();
+ unsigned StartLine = SM.getExpansionLineNumber(Start);
+ unsigned EndLine = SM.getExpansionLineNumber(End);
- MaxBugClassSize.updateMax(bugReports.size());
+ FileID FID = SM.getFileID(SM.getExpansionLoc(Start));
+ for (unsigned Line = StartLine; Line <= EndLine; Line++)
+ ExecutedLines->operator[](FID.getHashValue()).insert(Line);
+}
- if (!generatePathDiagnostic(*D.get(), PD, bugReports))
- return;
+static void populateExecutedLinesWithStmt(
+ const Stmt *S, SourceManager &SM,
+ std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) {
+ SourceLocation Loc = S->getSourceRange().getBegin();
+ SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
+ FileID FID = SM.getFileID(ExpansionLoc);
+ unsigned LineNo = SM.getExpansionLineNumber(ExpansionLoc);
+ ExecutedLines->operator[](FID.getHashValue()).insert(LineNo);
+}
- MaxValidBugClassSize.updateMax(bugReports.size());
+/// \return all executed lines including function signatures on the path
+/// starting from \p N.
+static std::unique_ptr<FilesToLineNumsMap>
+findExecutedLines(SourceManager &SM, const ExplodedNode *N) {
+ auto ExecutedLines = llvm::make_unique<FilesToLineNumsMap>();
- // Examine the report and see if the last piece is in a header. Reset the
- // report location to the last piece in the main source file.
- AnalyzerOptions &Opts = getAnalyzerOptions();
- if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
- D->resetDiagnosticLocationToMainFile();
- }
-
- // If the path is empty, generate a single step path with the location
- // of the issue.
- if (D->path.empty()) {
- PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
- auto piece = llvm::make_unique<PathDiagnosticEventPiece>(
- L, exampleReport->getDescription());
- for (SourceRange Range : exampleReport->getRanges())
- piece->addRange(Range);
- D->setEndOfPath(std::move(piece));
- }
-
- PathPieces &Pieces = D->getMutablePieces();
- if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) {
- // For path diagnostic consumers that don't support extra notes,
- // we may optionally convert those to path notes.
- for (auto I = exampleReport->getNotes().rbegin(),
- E = exampleReport->getNotes().rend(); I != E; ++I) {
- PathDiagnosticNotePiece *Piece = I->get();
- auto ConvertedPiece = std::make_shared<PathDiagnosticEventPiece>(
- Piece->getLocation(), Piece->getString());
- for (const auto &R: Piece->getRanges())
- ConvertedPiece->addRange(R);
+ while (N) {
+ if (N->getFirstPred() == nullptr) {
+ // First node: show signature of the entrance point.
+ const Decl *D = N->getLocationContext()->getDecl();
+ populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines);
+ } else if (auto CE = N->getLocationAs<CallEnter>()) {
+ // Inlined function: show signature.
+ const Decl* D = CE->getCalleeContext()->getDecl();
+ populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines);
+ } else if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) {
+ populateExecutedLinesWithStmt(S, SM, ExecutedLines);
+
+ // Show extra context for some parent kinds.
+ const Stmt *P = N->getParentMap().getParent(S);
+
+ // The path exploration can die before the node with the associated
+ // return statement is generated, but we do want to show the whole
+ // return.
+ if (const auto *RS = dyn_cast_or_null<ReturnStmt>(P)) {
+ populateExecutedLinesWithStmt(RS, SM, ExecutedLines);
+ P = N->getParentMap().getParent(RS);
+ }
- Pieces.push_front(std::move(ConvertedPiece));
+ if (P && (isa<SwitchCase>(P) || isa<LabelStmt>(P)))
+ populateExecutedLinesWithStmt(P, SM, ExecutedLines);
}
- } else {
- for (auto I = exampleReport->getNotes().rbegin(),
- E = exampleReport->getNotes().rend(); I != E; ++I)
- Pieces.push_front(*I);
+
+ N = N->getFirstPred();
}
+ return ExecutedLines;
+}
+
+std::unique_ptr<DiagnosticForConsumerMapTy>
+BugReporter::generateDiagnosticForConsumerMap(
+ BugReport *report, ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> bugReports) {
- // Get the meta data.
- const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
- for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
- e = Meta.end(); i != e; ++i) {
- D->addMeta(*i);
+ if (!report->isPathSensitive()) {
+ auto Out = llvm::make_unique<DiagnosticForConsumerMapTy>();
+ for (auto *Consumer : consumers)
+ (*Out)[Consumer] = generateEmptyDiagnosticForReport(report,
+ getSourceManager());
+ return Out;
}
- PD.HandlePathDiagnostic(std::move(D));
+ // Generate the full path sensitive diagnostic, using the generation scheme
+ // specified by the PathDiagnosticConsumer. Note that we have to generate
+ // path diagnostics even for consumers which do not support paths, because
+ // the BugReporterVisitors may mark this bug as a false positive.
+ assert(!bugReports.empty());
+ MaxBugClassSize.updateMax(bugReports.size());
+ std::unique_ptr<DiagnosticForConsumerMapTy> Out =
+ generatePathDiagnostics(consumers, bugReports);
+
+ if (Out->empty())
+ return Out;
+
+ MaxValidBugClassSize.updateMax(bugReports.size());
+
+ // Examine the report and see if the last piece is in a header. Reset the
+ // report location to the last piece in the main source file.
+ AnalyzerOptions &Opts = getAnalyzerOptions();
+ for (auto const &P : *Out)
+ if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
+ P.second->resetDiagnosticLocationToMainFile();
+
+ return Out;
}
void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
@@ -3595,12 +3107,12 @@ void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
EmitBasicReport(DeclWithIssue, Checker->getCheckName(), Name, Category, Str,
Loc, Ranges);
}
+
void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
CheckName CheckName,
StringRef name, StringRef category,
StringRef str, PathDiagnosticLocation Loc,
ArrayRef<SourceRange> Ranges) {
-
// 'BT' is owned by BugReporter.
BugType *BT = getBugTypeForName(CheckName, name, category);
auto R = llvm::make_unique<BugReport>(*BT, str, Loc);
@@ -3621,84 +3133,3 @@ BugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name,
BT = new BugType(CheckName, name, category);
return BT;
}
-
-LLVM_DUMP_METHOD void PathPieces::dump() const {
- unsigned index = 0;
- for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
- llvm::errs() << "[" << index++ << "] ";
- (*I)->dump();
- llvm::errs() << "\n";
- }
-}
-
-LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
- llvm::errs() << "CALL\n--------------\n";
-
- if (const Stmt *SLoc = getLocStmt(getLocation()))
- SLoc->dump();
- else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
- llvm::errs() << *ND << "\n";
- else
- getLocation().dump();
-}
-
-LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
- llvm::errs() << "EVENT\n--------------\n";
- llvm::errs() << getString() << "\n";
- llvm::errs() << " ---- at ----\n";
- getLocation().dump();
-}
-
-LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
- llvm::errs() << "CONTROL\n--------------\n";
- getStartLocation().dump();
- llvm::errs() << " ---- to ----\n";
- getEndLocation().dump();
-}
-
-LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
- llvm::errs() << "MACRO\n--------------\n";
- // FIXME: Print which macro is being invoked.
-}
-
-LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
- llvm::errs() << "NOTE\n--------------\n";
- llvm::errs() << getString() << "\n";
- llvm::errs() << " ---- at ----\n";
- getLocation().dump();
-}
-
-LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
- if (!isValid()) {
- llvm::errs() << "<INVALID>\n";
- return;
- }
-
- switch (K) {
- case RangeK:
- // FIXME: actually print the range.
- llvm::errs() << "<range>\n";
- break;
- case SingleLocK:
- asLocation().dump();
- llvm::errs() << "\n";
- break;
- case StmtK:
- if (S)
- S->dump();
- else
- llvm::errs() << "<NULL STMT>\n";
- break;
- case DeclK:
- if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
- llvm::errs() << *ND << "\n";
- else if (isa<BlockDecl>(D))
- // FIXME: Make this nicer.
- llvm::errs() << "<block>\n";
- else if (D)
- llvm::errs() << "<unknown decl>\n";
- else
- llvm::errs() << "<NULL DECL>\n";
- break;
- }
-}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 972f4c5f3da2..d4d33c1746ce 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1,4 +1,4 @@
-// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
+//===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,37 +11,83 @@
// enhance the diagnostics reported for a bug.
//
//===----------------------------------------------------------------------===//
+
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
+#include "llvm/ADT/ArrayRef.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/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <deque>
+#include <memory>
+#include <string>
+#include <utility>
using namespace clang;
using namespace ento;
-using llvm::FoldingSetNodeID;
-
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
bool bugreporter::isDeclRefExprToReference(const Expr *E) {
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl()->getType()->isReferenceType();
- }
return false;
}
+static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
+ if (B->isAdditiveOp() && B->getType()->isPointerType()) {
+ if (B->getLHS()->getType()->isPointerType()) {
+ return B->getLHS();
+ } else if (B->getRHS()->getType()->isPointerType()) {
+ return B->getRHS();
+ }
+ }
+ return nullptr;
+}
+
/// 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:
@@ -55,33 +101,27 @@ bool bugreporter::isDeclRefExprToReference(const Expr *E) {
/// x->y.z ==> x (lvalue)
/// foo()->y.z ==> foo() (rvalue)
const Expr *bugreporter::getDerefExpr(const Stmt *S) {
- const Expr *E = dyn_cast<Expr>(S);
+ const auto *E = dyn_cast<Expr>(S);
if (!E)
return nullptr;
while (true) {
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (const auto *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)) {
+ } else if (const auto *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;
- }
+ if (const Expr *Inner = peelOffPointerArithmetic(B)) {
+ E = Inner;
} else {
// Probably more arithmetic can be pattern-matched here,
// but for now give up.
break;
}
- } else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
+ } else if (const auto *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.
@@ -94,14 +134,16 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
}
}
// Pattern match for a few useful cases: a[0], p->f, *p etc.
- else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
E = ME->getBase();
- } else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
+ } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
E = IvarRef->getBase();
- } else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
+ } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
E = AE->getBase();
- } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
E = PE->getSubExpr();
+ } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
+ E = EWC->getSubExpr();
} else {
// Other arbitrary stuff.
break;
@@ -111,7 +153,7 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
// 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 (const auto *CE = dyn_cast<ImplicitCastExpr>(E))
if (CE->getCastKind() == CK_LValueToRValue)
E = CE->getSubExpr();
@@ -120,14 +162,14 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
- if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
+ if (const auto *BE = dyn_cast<BinaryOperator>(S))
return BE->getRHS();
return nullptr;
}
const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
- if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
+ if (const auto *RS = dyn_cast<ReturnStmt>(S))
return RS->getRetValue();
return nullptr;
}
@@ -136,13 +178,18 @@ const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
// Definitions for bug reporter visitors.
//===----------------------------------------------------------------------===//
-std::unique_ptr<PathDiagnosticPiece>
+std::shared_ptr<PathDiagnosticPiece>
BugReporterVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
return nullptr;
}
-std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
+void
+BugReporterVisitor::finalizeVisitor(BugReporterContext &BRC,
+ const ExplodedNode *EndPathNode,
+ BugReport &BR) {}
+
+std::shared_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
PathDiagnosticLocation L =
PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
@@ -151,16 +198,461 @@ std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
// Only add the statement itself as a range if we didn't specify any
// special ranges for this report.
- auto P = llvm::make_unique<PathDiagnosticEventPiece>(
+ auto P = std::make_shared<PathDiagnosticEventPiece>(
L, BR.getDescription(), Ranges.begin() == Ranges.end());
for (SourceRange Range : Ranges)
P->addRange(Range);
- return std::move(P);
+ return P;
+}
+
+/// \return name of the macro inside the location \p Loc.
+static StringRef getMacroName(SourceLocation Loc,
+ BugReporterContext &BRC) {
+ return Lexer::getImmediateMacroName(
+ Loc,
+ BRC.getSourceManager(),
+ BRC.getASTContext().getLangOpts());
+}
+
+/// \return Whether given spelling location corresponds to an expansion
+/// of a function-like macro.
+static bool isFunctionMacroExpansion(SourceLocation Loc,
+ const SourceManager &SM) {
+ if (!Loc.isMacroID())
+ return false;
+ while (SM.isMacroArgExpansion(Loc))
+ Loc = SM.getImmediateExpansionRange(Loc).getBegin();
+ std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc);
+ SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first);
+ const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
+ return EInfo.isFunctionMacroExpansion();
+}
+
+/// \return Whether \c RegionOfInterest was modified at \p N,
+/// where \p ReturnState is a state associated with the return
+/// from the current frame.
+static bool wasRegionOfInterestModifiedAt(
+ const SubRegion *RegionOfInterest,
+ const ExplodedNode *N,
+ SVal ValueAfter) {
+ ProgramStateRef State = N->getState();
+ ProgramStateManager &Mgr = N->getState()->getStateManager();
+
+ if (!N->getLocationAs<PostStore>()
+ && !N->getLocationAs<PostInitializer>()
+ && !N->getLocationAs<PostStmt>())
+ return false;
+
+ // Writing into region of interest.
+ if (auto PS = N->getLocationAs<PostStmt>())
+ if (auto *BO = PS->getStmtAs<BinaryOperator>())
+ if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
+ N->getSVal(BO->getLHS()).getAsRegion()))
+ return true;
+
+ // SVal after the state is possibly different.
+ SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
+ if (!Mgr.getSValBuilder().areEqual(State, ValueAtN, ValueAfter).isConstrainedTrue() &&
+ (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
+ return true;
+
+ return false;
}
namespace {
+
+/// Put a diagnostic on return statement of all inlined functions
+/// for which the region of interest \p RegionOfInterest was passed into,
+/// but not written inside, and it has caused an undefined read or a null
+/// pointer dereference outside.
+class NoStoreFuncVisitor final : public BugReporterVisitor {
+ const SubRegion *RegionOfInterest;
+ const SourceManager &SM;
+ const PrintingPolicy &PP;
+ static constexpr const char *DiagnosticsMsg =
+ "Returning without writing to '";
+
+ /// Frames writing into \c RegionOfInterest.
+ /// This visitor generates a note only if a function does not write into
+ /// a region of interest. This information is not immediately available
+ /// by looking at the node associated with the exit from the function
+ /// (usually the return statement). To avoid recomputing the same information
+ /// many times (going up the path for each node and checking whether the
+ /// region was written into) we instead lazily compute the
+ /// stack frames along the path which write into the region of interest.
+ llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
+ llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
+
+public:
+ NoStoreFuncVisitor(const SubRegion *R)
+ : RegionOfInterest(R),
+ SM(R->getMemRegionManager()->getContext().getSourceManager()),
+ PP(R->getMemRegionManager()->getContext().getPrintingPolicy()) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int Tag = 0;
+ ID.AddPointer(&Tag);
+ }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override {
+
+ const LocationContext *Ctx = N->getLocationContext();
+ const StackFrameContext *SCtx = Ctx->getStackFrame();
+ ProgramStateRef State = N->getState();
+ auto CallExitLoc = N->getLocationAs<CallExitBegin>();
+
+ // No diagnostic if region was modified inside the frame.
+ if (!CallExitLoc)
+ return nullptr;
+
+ CallEventRef<> Call =
+ BRC.getStateManager().getCallEventManager().getCaller(SCtx, State);
+
+ // Region of interest corresponds to an IVar, exiting a method
+ // which could have written into that IVar, but did not.
+ if (const auto *MC = dyn_cast<ObjCMethodCall>(Call))
+ if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest))
+ if (potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
+ IvarR->getDecl()) &&
+ !isRegionOfInterestModifiedInFrame(N))
+ return notModifiedMemberDiagnostics(
+ Ctx, *CallExitLoc, Call, MC->getReceiverSVal().getAsRegion());
+
+ if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
+ const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
+ if (RegionOfInterest->isSubRegionOf(ThisR)
+ && !CCall->getDecl()->isImplicit()
+ && !isRegionOfInterestModifiedInFrame(N))
+ return notModifiedMemberDiagnostics(Ctx, *CallExitLoc, Call, ThisR);
+ }
+
+ ArrayRef<ParmVarDecl *> parameters = getCallParameters(Call);
+ for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
+ const ParmVarDecl *PVD = parameters[I];
+ SVal S = Call->getArgSVal(I);
+ unsigned IndirectionLevel = 1;
+ QualType T = PVD->getType();
+ while (const MemRegion *R = S.getAsRegion()) {
+ if (RegionOfInterest->isSubRegionOf(R)
+ && !isPointerToConst(PVD->getType())) {
+
+ if (isRegionOfInterestModifiedInFrame(N))
+ return nullptr;
+
+ return notModifiedParameterDiagnostics(
+ Ctx, *CallExitLoc, Call, PVD, R, IndirectionLevel);
+ }
+ QualType PT = T->getPointeeType();
+ if (PT.isNull() || PT->isVoidType()) break;
+ S = State->getSVal(R, PT);
+ T = PT;
+ IndirectionLevel++;
+ }
+ }
+
+ return nullptr;
+ }
+
+private:
+
+ /// \return Whether the method declaration \p Parent
+ /// syntactically has a binary operation writing into the ivar \p Ivar.
+ bool potentiallyWritesIntoIvar(const Decl *Parent,
+ const ObjCIvarDecl *Ivar) {
+ using namespace ast_matchers;
+ if (!Parent || !Parent->getBody())
+ return false;
+ StatementMatcher WriteIntoIvarM = binaryOperator(
+ hasOperatorName("="), hasLHS(ignoringParenImpCasts(objcIvarRefExpr(
+ hasDeclaration(equalsNode(Ivar))))));
+ StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM));
+ auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext());
+ return !Matches.empty();
+ }
+
+ /// Check and lazily calculate whether the region of interest is
+ /// modified in the stack frame to which \p N belongs.
+ /// The calculation is cached in FramesModifyingRegion.
+ bool isRegionOfInterestModifiedInFrame(const ExplodedNode *N) {
+ const LocationContext *Ctx = N->getLocationContext();
+ const StackFrameContext *SCtx = Ctx->getStackFrame();
+ if (!FramesModifyingCalculated.count(SCtx))
+ findModifyingFrames(N);
+ return FramesModifyingRegion.count(SCtx);
+ }
+
+
+ /// Write to \c FramesModifyingRegion all stack frames along
+ /// the path in the current stack frame which modify \c RegionOfInterest.
+ void findModifyingFrames(const ExplodedNode *N) {
+ assert(N->getLocationAs<CallExitBegin>());
+ ProgramStateRef LastReturnState = N->getState();
+ SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
+ const LocationContext *Ctx = N->getLocationContext();
+ const StackFrameContext *OriginalSCtx = Ctx->getStackFrame();
+
+ do {
+ ProgramStateRef State = N->getState();
+ auto CallExitLoc = N->getLocationAs<CallExitBegin>();
+ if (CallExitLoc) {
+ LastReturnState = State;
+ ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
+ }
+
+ FramesModifyingCalculated.insert(
+ N->getLocationContext()->getStackFrame());
+
+ if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtReturn)) {
+ const StackFrameContext *SCtx = N->getStackFrame();
+ while (!SCtx->inTopFrame()) {
+ auto p = FramesModifyingRegion.insert(SCtx);
+ if (!p.second)
+ break; // Frame and all its parents already inserted.
+ SCtx = SCtx->getParent()->getStackFrame();
+ }
+ }
+
+ // Stop calculation at the call to the current function.
+ if (auto CE = N->getLocationAs<CallEnter>())
+ if (CE->getCalleeContext() == OriginalSCtx)
+ break;
+
+ N = N->getFirstPred();
+ } while (N);
+ }
+
+ /// Get parameters associated with runtime definition in order
+ /// to get the correct parameter name.
+ ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) {
+ // Use runtime definition, if available.
+ RuntimeDefinition RD = Call->getRuntimeDefinition();
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
+ return FD->parameters();
+
+ return Call->parameters();
+ }
+
+ /// \return whether \p Ty points to a const type, or is a const reference.
+ bool isPointerToConst(QualType Ty) {
+ return !Ty->getPointeeType().isNull() &&
+ Ty->getPointeeType().getCanonicalType().isConstQualified();
+ }
+
+ /// \return Diagnostics piece for the member field not modified
+ /// in a given function.
+ std::shared_ptr<PathDiagnosticPiece> notModifiedMemberDiagnostics(
+ const LocationContext *Ctx,
+ CallExitBegin &CallExitLoc,
+ CallEventRef<> Call,
+ const MemRegion *ArgRegion) {
+ const char *TopRegionName = isa<ObjCMethodCall>(Call) ? "self" : "this";
+ SmallString<256> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+ os << DiagnosticsMsg;
+ bool out = prettyPrintRegionName(TopRegionName, "->", /*IsReference=*/true,
+ /*IndirectionLevel=*/1, ArgRegion, os, PP);
+
+ // Return nothing if we have failed to pretty-print.
+ if (!out)
+ return nullptr;
+
+ os << "'";
+ PathDiagnosticLocation L =
+ getPathDiagnosticLocation(CallExitLoc.getReturnStmt(), SM, Ctx, Call);
+ return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
+ }
+
+ /// \return Diagnostics piece for the parameter \p PVD not modified
+ /// in a given function.
+ /// \p IndirectionLevel How many times \c ArgRegion has to be dereferenced
+ /// before we get to the super region of \c RegionOfInterest
+ std::shared_ptr<PathDiagnosticPiece>
+ notModifiedParameterDiagnostics(const LocationContext *Ctx,
+ CallExitBegin &CallExitLoc,
+ CallEventRef<> Call,
+ const ParmVarDecl *PVD,
+ const MemRegion *ArgRegion,
+ unsigned IndirectionLevel) {
+ PathDiagnosticLocation L = getPathDiagnosticLocation(
+ CallExitLoc.getReturnStmt(), SM, Ctx, Call);
+ SmallString<256> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+ os << DiagnosticsMsg;
+ bool IsReference = PVD->getType()->isReferenceType();
+ const char *Sep = IsReference && IndirectionLevel == 1 ? "." : "->";
+ bool Success = prettyPrintRegionName(
+ PVD->getQualifiedNameAsString().c_str(),
+ Sep, IsReference, IndirectionLevel, ArgRegion, os, PP);
+
+ // Print the parameter name if the pretty-printing has failed.
+ if (!Success)
+ PVD->printQualifiedName(os);
+ os << "'";
+ return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
+ }
+
+ /// \return a path diagnostic location for the optionally
+ /// present return statement \p RS.
+ PathDiagnosticLocation getPathDiagnosticLocation(const ReturnStmt *RS,
+ const SourceManager &SM,
+ const LocationContext *Ctx,
+ CallEventRef<> Call) {
+ if (RS)
+ return PathDiagnosticLocation::createBegin(RS, SM, Ctx);
+ return PathDiagnosticLocation(
+ Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(), SM);
+ }
+
+ /// Pretty-print region \p ArgRegion starting from parent to \p os.
+ /// \return whether printing has succeeded
+ bool prettyPrintRegionName(StringRef TopRegionName,
+ StringRef Sep,
+ bool IsReference,
+ int IndirectionLevel,
+ const MemRegion *ArgRegion,
+ llvm::raw_svector_ostream &os,
+ const PrintingPolicy &PP) {
+ SmallVector<const MemRegion *, 5> Subregions;
+ const MemRegion *R = RegionOfInterest;
+ while (R != ArgRegion) {
+ if (!(isa<FieldRegion>(R) || isa<CXXBaseObjectRegion>(R) ||
+ isa<ObjCIvarRegion>(R)))
+ return false; // Pattern-matching failed.
+ Subregions.push_back(R);
+ R = cast<SubRegion>(R)->getSuperRegion();
+ }
+ bool IndirectReference = !Subregions.empty();
+
+ if (IndirectReference)
+ IndirectionLevel--; // Due to "->" symbol.
+
+ if (IsReference)
+ IndirectionLevel--; // Due to reference semantics.
+
+ bool ShouldSurround = IndirectReference && IndirectionLevel > 0;
+
+ if (ShouldSurround)
+ os << "(";
+ for (int i = 0; i < IndirectionLevel; i++)
+ os << "*";
+ os << TopRegionName;
+ if (ShouldSurround)
+ os << ")";
+
+ for (auto I = Subregions.rbegin(), E = Subregions.rend(); I != E; ++I) {
+ if (const auto *FR = dyn_cast<FieldRegion>(*I)) {
+ os << Sep;
+ FR->getDecl()->getDeclName().print(os, PP);
+ Sep = ".";
+ } else if (const auto *IR = dyn_cast<ObjCIvarRegion>(*I)) {
+ os << "->";
+ IR->getDecl()->getDeclName().print(os, PP);
+ Sep = ".";
+ } else if (isa<CXXBaseObjectRegion>(*I)) {
+ continue; // Just keep going up to the base region.
+ } else {
+ llvm_unreachable("Previous check has missed an unexpected region");
+ }
+ }
+ return true;
+ }
+};
+
+/// Suppress null-pointer-dereference bugs where dereferenced null was returned
+/// the macro.
+class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor {
+ const SubRegion *RegionOfInterest;
+ const SVal ValueAtDereference;
+
+ // Do not invalidate the reports where the value was modified
+ // after it got assigned to from the macro.
+ bool WasModified = false;
+
+public:
+ MacroNullReturnSuppressionVisitor(const SubRegion *R,
+ const SVal V) : RegionOfInterest(R),
+ ValueAtDereference(V) {}
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override {
+ if (WasModified)
+ return nullptr;
+
+ auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
+ if (!BugPoint)
+ return nullptr;
+
+ const SourceManager &SMgr = BRC.getSourceManager();
+ if (auto Loc = matchAssignment(N, BRC)) {
+ if (isFunctionMacroExpansion(*Loc, SMgr)) {
+ std::string MacroName = getMacroName(*Loc, BRC);
+ SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
+ if (!BugLoc.isMacroID() || getMacroName(BugLoc, BRC) != MacroName)
+ BR.markInvalid(getTag(), MacroName.c_str());
+ }
+ }
+
+ if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference))
+ WasModified = true;
+
+ return nullptr;
+ }
+
+ static void addMacroVisitorIfNecessary(
+ const ExplodedNode *N, const MemRegion *R,
+ bool EnableNullFPSuppression, BugReport &BR,
+ const SVal V) {
+ AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
+ if (EnableNullFPSuppression && Options.shouldSuppressNullReturnPaths()
+ && V.getAs<Loc>())
+ BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
+ R->getAs<SubRegion>(), V));
+ }
+
+ void* getTag() const {
+ static int Tag = 0;
+ return static_cast<void *>(&Tag);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ ID.AddPointer(getTag());
+ }
+
+private:
+ /// \return Source location of right hand side of an assignment
+ /// into \c RegionOfInterest, empty optional if none found.
+ Optional<SourceLocation> matchAssignment(const ExplodedNode *N,
+ BugReporterContext &BRC) {
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ ProgramStateRef State = N->getState();
+ auto *LCtx = N->getLocationContext();
+ if (!S)
+ return None;
+
+ if (const auto *DS = dyn_cast<DeclStmt>(S)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
+ if (const Expr *RHS = VD->getInit())
+ if (RegionOfInterest->isSubRegionOf(
+ State->getLValue(VD, LCtx).getAsRegion()))
+ return RHS->getLocStart();
+ } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
+ const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
+ const Expr *RHS = BO->getRHS();
+ if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
+ return RHS->getLocStart();
+ }
+ }
+ return None;
+ }
+};
+
/// Emits an extra note at the return statement of an interesting stack frame.
///
/// The returned value is marked as an interesting value, and if it's null,
@@ -168,19 +660,20 @@ namespace {
///
/// This visitor is intended to be used when another visitor discovers that an
/// interesting value comes from an inlined function call.
-class ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> {
+class ReturnVisitor : public BugReporterVisitor {
const StackFrameContext *StackFrame;
enum {
Initial,
MaybeUnsuppress,
Satisfied
- } Mode;
+ } Mode = Initial;
bool EnableNullFPSuppression;
+ bool ShouldInvalidate = true;
public:
ReturnVisitor(const StackFrameContext *Frame, bool Suppressed)
- : StackFrame(Frame), Mode(Initial), EnableNullFPSuppression(Suppressed) {}
+ : StackFrame(Frame), EnableNullFPSuppression(Suppressed) {}
static void *getTag() {
static int Tag = 0;
@@ -235,7 +728,7 @@ public:
// Check the return value.
ProgramStateRef State = Node->getState();
- SVal RetVal = State->getSVal(S, Node->getLocationContext());
+ SVal RetVal = Node->getSVal(S);
// Handle cases where a reference is returned and then immediately used.
if (cast<Expr>(S)->isGLValue())
@@ -243,9 +736,7 @@ public:
RetVal = State->getSVal(*LValue);
// See if the return value is NULL. If so, suppress the report.
- SubEngine *Eng = State->getStateManager().getOwningEngine();
- assert(Eng && "Cannot file a bug report without an owning engine");
- AnalyzerOptions &Options = Eng->getAnalysisManager().options;
+ AnalyzerOptions &Options = State->getAnalysisManager().options;
bool EnableNullFPSuppression = false;
if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
@@ -274,7 +765,7 @@ public:
if (!SP)
return nullptr;
- const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
+ const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
if (!Ret)
return nullptr;
@@ -329,8 +820,7 @@ public:
// If we have counter-suppression enabled, make sure we keep visiting
// future nodes. We want to emit a path note as well, in case
// the report is resurrected as valid later on.
- ExprEngine &Eng = BRC.getBugReporter().getEngine();
- AnalyzerOptions &Options = Eng.getAnalysisManager().options;
+ AnalyzerOptions &Options = BRC.getAnalyzerOptions();
if (EnableNullFPSuppression && hasCounterSuppression(Options))
Mode = MaybeUnsuppress;
@@ -352,8 +842,8 @@ public:
}
} else {
// FIXME: We should have a more generalized location printing mechanism.
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE))
- if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
+ if (const auto *DR = dyn_cast<DeclRefExpr>(RetE))
+ if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
Out << " (loaded from '" << *DD << "')";
}
@@ -368,8 +858,7 @@ public:
visitNodeMaybeUnsuppress(const ExplodedNode *N, const ExplodedNode *PrevN,
BugReporterContext &BRC, BugReport &BR) {
#ifndef NDEBUG
- ExprEngine &Eng = BRC.getBugReporter().getEngine();
- AnalyzerOptions &Options = Eng.getAnalysisManager().options;
+ AnalyzerOptions &Options = BRC.getAnalyzerOptions();
assert(hasCounterSuppression(Options));
#endif
@@ -406,7 +895,7 @@ public:
if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true,
EnableNullFPSuppression))
- BR.removeInvalidation(ReturnVisitor::getTag(), StackFrame);
+ ShouldInvalidate = false;
// If we /can't/ track the null pointer, we should err on the side of
// false negatives, and continue towards marking this report invalid.
@@ -432,18 +921,16 @@ public:
llvm_unreachable("Invalid visit mode!");
}
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override {
- if (EnableNullFPSuppression)
+ void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
+ BugReport &BR) override {
+ if (EnableNullFPSuppression && ShouldInvalidate)
BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
- return nullptr;
}
};
-} // end anonymous namespace
+} // namespace
-void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
+void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
static int tag = 0;
ID.AddPointer(&tag);
ID.AddPointer(R);
@@ -466,7 +953,7 @@ static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
return false;
const MemSpaceRegion *VarSpace = VR->getMemorySpace();
- const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
+ const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
if (!FrameSpace) {
// If we ever directly evaluate global DeclStmts, this assertion will be
// invalid, but this still seems preferable to silently accepting an
@@ -477,14 +964,131 @@ static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
assert(VR->getDecl()->hasLocalStorage());
const LocationContext *LCtx = N->getLocationContext();
- return FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame();
+ return FrameSpace->getStackFrame() == LCtx->getStackFrame();
+}
+
+/// Show diagnostics for initializing or declaring a region \p R with a bad value.
+static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os,
+ const MemRegion *R, SVal V, const DeclStmt *DS) {
+ if (R->canPrintPretty()) {
+ R->printPretty(os);
+ os << " ";
+ }
+
+ if (V.getAs<loc::ConcreteInt>()) {
+ bool b = false;
+ if (R->isBoundable()) {
+ if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
+ os << action << "nil";
+ b = true;
+ }
+ }
+ }
+ if (!b)
+ os << action << "a null pointer value";
+
+ } else if (auto CVal = V.getAs<nonloc::ConcreteInt>()) {
+ os << action << CVal->getValue();
+ } else if (DS) {
+ if (V.isUndef()) {
+ if (isa<VarRegion>(R)) {
+ const auto *VD = cast<VarDecl>(DS->getSingleDecl());
+ if (VD->getInit()) {
+ os << (R->canPrintPretty() ? "initialized" : "Initializing")
+ << " to a garbage value";
+ } else {
+ os << (R->canPrintPretty() ? "declared" : "Declaring")
+ << " without an initial value";
+ }
+ }
+ } else {
+ os << (R->canPrintPretty() ? "initialized" : "Initialized")
+ << " here";
+ }
+ }
+}
+
+/// Display diagnostics for passing bad region as a parameter.
+static void showBRParamDiagnostics(llvm::raw_svector_ostream& os,
+ const VarRegion *VR,
+ SVal V) {
+ const auto *Param = cast<ParmVarDecl>(VR->getDecl());
+
+ os << "Passing ";
+
+ if (V.getAs<loc::ConcreteInt>()) {
+ if (Param->getType()->isObjCObjectPointerType())
+ os << "nil object reference";
+ else
+ os << "null pointer value";
+ } else if (V.isUndef()) {
+ os << "uninitialized value";
+ } else if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
+ os << "the value " << CI->getValue();
+ } else {
+ os << "value";
+ }
+
+ // Printed parameter indexes are 1-based, not 0-based.
+ unsigned Idx = Param->getFunctionScopeIndex() + 1;
+ os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
+ if (VR->canPrintPretty()) {
+ os << " ";
+ VR->printPretty(os);
+ }
+}
+
+/// Show default diagnostics for storing bad region.
+static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os,
+ const MemRegion *R,
+ SVal V) {
+ if (V.getAs<loc::ConcreteInt>()) {
+ bool b = false;
+ if (R->isBoundable()) {
+ if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
+ os << "nil object reference stored";
+ b = true;
+ }
+ }
+ }
+ if (!b) {
+ if (R->canPrintPretty())
+ os << "Null pointer value stored";
+ else
+ os << "Storing null pointer value";
+ }
+
+ } else if (V.isUndef()) {
+ if (R->canPrintPretty())
+ os << "Uninitialized value stored";
+ else
+ os << "Storing uninitialized value";
+
+ } else if (auto CV = V.getAs<nonloc::ConcreteInt>()) {
+ if (R->canPrintPretty())
+ os << "The value " << CV->getValue() << " is assigned";
+ else
+ os << "Assigning " << CV->getValue();
+
+ } else {
+ if (R->canPrintPretty())
+ os << "Value assigned";
+ else
+ os << "Assigning value";
+ }
+
+ if (R->canPrintPretty()) {
+ os << " to ";
+ R->printPretty(os);
+ }
}
std::shared_ptr<PathDiagnosticPiece>
FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
const ExplodedNode *Pred,
BugReporterContext &BRC, BugReport &BR) {
-
if (Satisfied)
return nullptr;
@@ -493,7 +1097,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
bool IsParam = false;
// First see if we reached the declaration of the region.
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ if (const auto *VR = dyn_cast<VarRegion>(R)) {
if (isInitializationOfVar(Pred, VR)) {
StoreSite = Pred;
InitE = VR->getDecl()->getInit();
@@ -539,8 +1143,8 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
// 'this' should never be NULL, but this visitor isn't just for NULL and
// UndefinedVal.)
if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
+ if (const auto *VR = dyn_cast<VarRegion>(R)) {
+ const auto *Param = cast<ParmVarDecl>(VR->getDecl());
ProgramStateManager &StateMgr = BRC.getStateManager();
CallEventManager &CallMgr = StateMgr.getCallEventManager();
@@ -554,7 +1158,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
// If this is a CXXTempObjectRegion, the Expr responsible for its creation
// is wrapped inside of it.
- if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R))
+ if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
InitE = TmpR->getExpr();
}
@@ -584,8 +1188,8 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
const Stmt *S = PS->getStmt();
const char *action = nullptr;
- const DeclStmt *DS = dyn_cast<DeclStmt>(S);
- const VarRegion *VR = dyn_cast<VarRegion>(R);
+ const auto *DS = dyn_cast<DeclStmt>(S);
+ const auto *VR = dyn_cast<VarRegion>(R);
if (DS) {
action = R->canPrintPretty() ? "initialized to " :
@@ -596,8 +1200,8 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (VR) {
// See if we can get the BlockVarRegion.
ProgramStateRef State = StoreSite->getState();
- SVal V = State->getSVal(S, PS->getLocationContext());
- if (const BlockDataRegion *BDR =
+ SVal V = StoreSite->getSVal(S);
+ if (const auto *BDR =
dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
if (Optional<KnownSVal> KV =
@@ -608,122 +1212,16 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
}
}
}
+ if (action)
+ showBRDiagnostics(action, os, R, V, DS);
- if (action) {
- if (R->canPrintPretty()) {
- R->printPretty(os);
- os << " ";
- }
-
- if (V.getAs<loc::ConcreteInt>()) {
- bool b = false;
- if (R->isBoundable()) {
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
- if (TR->getValueType()->isObjCObjectPointerType()) {
- os << action << "nil";
- b = true;
- }
- }
- }
-
- if (!b)
- os << action << "a null pointer value";
- } else if (Optional<nonloc::ConcreteInt> CVal =
- V.getAs<nonloc::ConcreteInt>()) {
- os << action << CVal->getValue();
- }
- else if (DS) {
- if (V.isUndef()) {
- if (isa<VarRegion>(R)) {
- const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
- if (VD->getInit()) {
- os << (R->canPrintPretty() ? "initialized" : "Initializing")
- << " to a garbage value";
- } else {
- os << (R->canPrintPretty() ? "declared" : "Declaring")
- << " without an initial value";
- }
- }
- }
- else {
- os << (R->canPrintPretty() ? "initialized" : "Initialized")
- << " here";
- }
- }
- }
} else if (StoreSite->getLocation().getAs<CallEnter>()) {
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
-
- os << "Passing ";
-
- if (V.getAs<loc::ConcreteInt>()) {
- if (Param->getType()->isObjCObjectPointerType())
- os << "nil object reference";
- else
- os << "null pointer value";
- } else if (V.isUndef()) {
- os << "uninitialized value";
- } else if (Optional<nonloc::ConcreteInt> CI =
- V.getAs<nonloc::ConcreteInt>()) {
- os << "the value " << CI->getValue();
- } else {
- os << "value";
- }
-
- // Printed parameter indexes are 1-based, not 0-based.
- unsigned Idx = Param->getFunctionScopeIndex() + 1;
- os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
- if (R->canPrintPretty()) {
- os << " ";
- R->printPretty(os);
- }
- }
+ if (const auto *VR = dyn_cast<VarRegion>(R))
+ showBRParamDiagnostics(os, VR, V);
}
- if (os.str().empty()) {
- if (V.getAs<loc::ConcreteInt>()) {
- bool b = false;
- if (R->isBoundable()) {
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
- if (TR->getValueType()->isObjCObjectPointerType()) {
- os << "nil object reference stored";
- b = true;
- }
- }
- }
- if (!b) {
- if (R->canPrintPretty())
- os << "Null pointer value stored";
- else
- os << "Storing null pointer value";
- }
-
- } else if (V.isUndef()) {
- if (R->canPrintPretty())
- os << "Uninitialized value stored";
- else
- os << "Storing uninitialized value";
-
- } else if (Optional<nonloc::ConcreteInt> CV =
- V.getAs<nonloc::ConcreteInt>()) {
- if (R->canPrintPretty())
- os << "The value " << CV->getValue() << " is assigned";
- else
- os << "Assigning " << CV->getValue();
-
- } else {
- if (R->canPrintPretty())
- os << "Value assigned";
- else
- os << "Assigning value";
- }
-
- if (R->canPrintPretty()) {
- os << " to ";
- R->printPretty(os);
- }
- }
+ if (os.str().empty())
+ showBRDefaultDiagnostics(os, R, V);
// Construct a new PathDiagnosticPiece.
ProgramPoint P = StoreSite->getLocation();
@@ -778,7 +1276,6 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
if (isUnderconstrained(PrevN)) {
-
IsSatisfied = true;
// As a sanity check, make sure that the negation of the constraint
@@ -816,20 +1313,18 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
SuppressInlineDefensiveChecksVisitor::
SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
- : V(Value), IsSatisfied(false), IsTrackingTurnedOn(false) {
-
- // Check if the visitor is disabled.
- SubEngine *Eng = N->getState()->getStateManager().getOwningEngine();
- assert(Eng && "Cannot file a bug report without an owning engine");
- AnalyzerOptions &Options = Eng->getAnalysisManager().options;
- if (!Options.shouldSuppressInlinedDefensiveChecks())
- IsSatisfied = true;
+ : V(Value) {
+ // Check if the visitor is disabled.
+ AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
+ if (!Options.shouldSuppressInlinedDefensiveChecks())
+ IsSatisfied = true;
- assert(N->getState()->isNull(V).isConstrainedTrue() &&
- "The visitor only tracks the cases where V is constrained to 0");
+ assert(N->getState()->isNull(V).isConstrainedTrue() &&
+ "The visitor only tracks the cases where V is constrained to 0");
}
-void SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const {
+void SuppressInlineDefensiveChecksVisitor::Profile(
+ llvm::FoldingSetNodeID &ID) const {
static int id = 0;
ID.AddPointer(&id);
ID.Add(V);
@@ -878,10 +1373,6 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
if (!BugPoint)
return nullptr;
- SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
- if (BugLoc.isMacroID())
- return nullptr;
-
ProgramPoint CurPoint = Succ->getLocation();
const Stmt *CurTerminatorStmt = nullptr;
if (auto BE = CurPoint.getAs<BlockEdge>()) {
@@ -902,14 +1393,14 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
SourceLocation TerminatorLoc = CurTerminatorStmt->getLocStart();
if (TerminatorLoc.isMacroID()) {
- const SourceManager &SMgr = BRC.getSourceManager();
- std::pair<FileID, unsigned> TLInfo = SMgr.getDecomposedLoc(TerminatorLoc);
- SrcMgr::SLocEntry SE = SMgr.getSLocEntry(TLInfo.first);
- const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
- if (EInfo.isFunctionMacroExpansion()) {
+ SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
+
+ // Suppress reports unless we are in that same macro.
+ if (!BugLoc.isMacroID() ||
+ getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)) {
BR.markInvalid("Suppress Macro IDC", CurLC);
- return nullptr;
}
+ return nullptr;
}
}
return nullptr;
@@ -917,8 +1408,8 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
static const MemRegion *getLocationRegionIfReference(const Expr *E,
const ExplodedNode *N) {
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
if (!VD->getType()->isReferenceType())
return nullptr;
ProgramStateManager &StateMgr = N->getState()->getStateManager();
@@ -939,12 +1430,12 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) {
Ex = Ex->IgnoreParenCasts();
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(Ex))
return peelOffOuterExpr(EWC->getSubExpr(), N);
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return peelOffOuterExpr(OVE->getSourceExpr(), N);
- if (auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
- auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
+ if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
+ const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
if (PropRef && PropRef->isMessagingGetter()) {
const Expr *GetterMessageSend =
POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
@@ -954,7 +1445,7 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
}
// Peel off the ternary operator.
- if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
+ if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
// Find a node where the branching occurred and find out which branch
// we took (true/false) by looking at the ExplodedGraph.
const ExplodedNode *NI = N;
@@ -975,6 +1466,68 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
NI = NI->getFirstPred();
} while (NI);
}
+
+ if (auto *BO = dyn_cast<BinaryOperator>(Ex))
+ if (const Expr *SubEx = peelOffPointerArithmetic(BO))
+ return peelOffOuterExpr(SubEx, N);
+
+ return Ex;
+}
+
+/// Walk through nodes until we get one that matches the statement exactly.
+/// Alternately, if we hit a known lvalue for the statement, we know we've
+/// gone too far (though we can likely track the lvalue better anyway).
+static const ExplodedNode* findNodeForStatement(const ExplodedNode *N,
+ const Stmt *S,
+ const Expr *Inner) {
+ do {
+ const ProgramPoint &pp = N->getLocation();
+ if (auto ps = pp.getAs<StmtPoint>()) {
+ if (ps->getStmt() == S || ps->getStmt() == Inner)
+ break;
+ } else if (auto CEE = pp.getAs<CallExitEnd>()) {
+ if (CEE->getCalleeContext()->getCallSite() == S ||
+ CEE->getCalleeContext()->getCallSite() == Inner)
+ break;
+ }
+ N = N->getFirstPred();
+ } while (N);
+ return N;
+}
+
+/// Find the ExplodedNode where the lvalue (the value of 'Ex')
+/// was computed.
+static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
+ const Expr *Inner) {
+ while (N) {
+ if (auto P = N->getLocation().getAs<PostStmt>()) {
+ if (P->getStmt() == Inner)
+ break;
+ }
+ N = N->getFirstPred();
+ }
+ assert(N && "Unable to find the lvalue node.");
+ return N;
+}
+
+/// Performing operator `&' on an lvalue expression is essentially a no-op.
+/// Then, if we are taking addresses of fields or elements, these are also
+/// unlikely to matter.
+static const Expr* peelOfOuterAddrOf(const Expr* Ex) {
+ Ex = Ex->IgnoreParenCasts();
+
+ // FIXME: There's a hack in our Store implementation that always computes
+ // field offsets around null pointers as if they are always equal to 0.
+ // The idea here is to report accesses to fields as null dereferences
+ // even though the pointer value that's being dereferenced is actually
+ // the offset of the field rather than exactly 0.
+ // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
+ // This code interacts heavily with this hack; otherwise the value
+ // would not be null at all for most fields, so we'd be unable to track it.
+ if (const auto *Op = dyn_cast<UnaryOperator>(Ex))
+ if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue())
+ if (const Expr *DerefEx = bugreporter::getDerefExpr(Op->getSubExpr()))
+ return DerefEx;
return Ex;
}
@@ -985,52 +1538,23 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
if (!S || !N)
return false;
- if (const Expr *Ex = dyn_cast<Expr>(S))
+ if (const auto *Ex = dyn_cast<Expr>(S))
S = peelOffOuterExpr(Ex, N);
const Expr *Inner = nullptr;
- if (const Expr *Ex = dyn_cast<Expr>(S)) {
+ if (const auto *Ex = dyn_cast<Expr>(S)) {
+ Ex = peelOfOuterAddrOf(Ex);
Ex = Ex->IgnoreParenCasts();
- // Performing operator `&' on an lvalue expression is essentially a no-op.
- // Then, if we are taking addresses of fields or elements, these are also
- // unlikely to matter.
- // FIXME: There's a hack in our Store implementation that always computes
- // field offsets around null pointers as if they are always equal to 0.
- // The idea here is to report accesses to fields as null dereferences
- // even though the pointer value that's being dereferenced is actually
- // the offset of the field rather than exactly 0.
- // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
- // This code interacts heavily with this hack; otherwise the value
- // would not be null at all for most fields, so we'd be unable to track it.
- if (const auto *Op = dyn_cast<UnaryOperator>(Ex))
- if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue())
- if (const Expr *DerefEx = getDerefExpr(Op->getSubExpr()))
- Ex = DerefEx;
-
- if (Ex && (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex)))
+ if (Ex && (ExplodedGraph::isInterestingLValueExpr(Ex)
+ || CallEvent::isCallStmt(Ex)))
Inner = Ex;
}
if (IsArg && !Inner) {
assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call");
} else {
- // Walk through nodes until we get one that matches the statement exactly.
- // Alternately, if we hit a known lvalue for the statement, we know we've
- // gone too far (though we can likely track the lvalue better anyway).
- do {
- const ProgramPoint &pp = N->getLocation();
- if (Optional<StmtPoint> ps = pp.getAs<StmtPoint>()) {
- if (ps->getStmt() == S || ps->getStmt() == Inner)
- break;
- } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) {
- if (CEE->getCalleeContext()->getCallSite() == S ||
- CEE->getCalleeContext()->getCallSite() == Inner)
- break;
- }
- N = N->getFirstPred();
- } while (N);
-
+ N = findNodeForStatement(N, S, Inner);
if (!N)
return false;
}
@@ -1041,51 +1565,44 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// At this point in the path, the receiver should be live since we are at the
// message send expr. If it is nil, start tracking it.
if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(S, N))
- trackNullOrUndefValue(N, Receiver, report, false, EnableNullFPSuppression);
-
+ trackNullOrUndefValue(N, Receiver, report, /* IsArg=*/ false,
+ EnableNullFPSuppression);
// See if the expression we're interested refers to a variable.
// If so, we can track both its contents and constraints on its value.
if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
- const MemRegion *R = nullptr;
-
- // Find the ExplodedNode where the lvalue (the value of 'Ex')
- // was computed. We need this for getting the location value.
- const ExplodedNode *LVNode = N;
- while (LVNode) {
- if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
- if (P->getStmt() == Inner)
- break;
- }
- LVNode = LVNode->getFirstPred();
- }
- assert(LVNode && "Unable to find the lvalue node.");
+ const ExplodedNode *LVNode = findNodeForExpression(N, Inner);
ProgramStateRef LVState = LVNode->getState();
- SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext());
-
- if (LVState->isNull(LVal).isConstrainedTrue()) {
- // In case of C++ references, we want to differentiate between a null
- // reference and reference to null pointer.
- // If the LVal is null, check if we are dealing with null reference.
- // For those, we want to track the location of the reference.
- if (const MemRegion *RR = getLocationRegionIfReference(Inner, N))
- R = RR;
- } else {
- R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion();
-
- // If this is a C++ reference to a null pointer, we are tracking the
- // pointer. In addition, we should find the store at which the reference
- // got initialized.
- if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) {
- if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>())
- report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
+ SVal LVal = LVNode->getSVal(Inner);
+
+ const MemRegion *RR = getLocationRegionIfReference(Inner, N);
+ bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
+
+ // If this is a C++ reference to a null pointer, we are tracking the
+ // pointer. In addition, we should find the store at which the reference
+ // got initialized.
+ if (RR && !LVIsNull) {
+ if (auto KV = LVal.getAs<KnownSVal>())
+ report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
*KV, RR, EnableNullFPSuppression));
- }
}
+ // In case of C++ references, we want to differentiate between a null
+ // reference and reference to null pointer.
+ // If the LVal is null, check if we are dealing with null reference.
+ // For those, we want to track the location of the reference.
+ const MemRegion *R = (RR && LVIsNull) ? RR :
+ LVNode->getSVal(Inner).getAsRegion();
+
if (R) {
+
// Mark both the variable region and its contents as interesting.
SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
+ report.addVisitor(
+ llvm::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R)));
+
+ MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
+ N, R, EnableNullFPSuppression, report, V);
report.markInteresting(R);
report.markInteresting(V);
@@ -1094,21 +1611,21 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// If the contents are symbolic, find out when they became null.
if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true))
report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
- V.castAs<DefinedSVal>(), false));
+ V.castAs<DefinedSVal>(), false));
// Add visitor, which will suppress inline defensive checks.
- if (Optional<DefinedSVal> DV = V.getAs<DefinedSVal>()) {
+ if (auto DV = V.getAs<DefinedSVal>()) {
if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
EnableNullFPSuppression) {
report.addVisitor(
llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
- LVNode));
+ LVNode));
}
}
- if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
+ if (auto KV = V.getAs<KnownSVal>())
report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
- *KV, R, EnableNullFPSuppression));
+ *KV, R, EnableNullFPSuppression));
return true;
}
}
@@ -1119,7 +1636,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// If the value came from an inlined function call, we should at least make
// sure that function isn't pruned in our output.
- if (const Expr *E = dyn_cast<Expr>(S))
+ if (const auto *E = dyn_cast<Expr>(S))
S = E->IgnoreParenCasts();
ReturnVisitor::addVisitorIfNecessary(N, S, report, EnableNullFPSuppression);
@@ -1128,40 +1645,40 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// base value that was dereferenced.
// assert(!V.isUnknownOrUndef());
// Is it a symbolic value?
- if (Optional<loc::MemRegionVal> L = V.getAs<loc::MemRegionVal>()) {
+ if (auto L = V.getAs<loc::MemRegionVal>()) {
+ report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
+
// At this point we are dealing with the region's LValue.
// However, if the rvalue is a symbolic region, we should track it as well.
// Try to use the correct type when looking up the value.
SVal RVal;
- if (const Expr *E = dyn_cast<Expr>(S))
+ if (const auto *E = dyn_cast<Expr>(S))
RVal = state->getRawSVal(L.getValue(), E->getType());
else
RVal = state->getSVal(L->getRegion());
- report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
- if (Optional<KnownSVal> KV = RVal.getAs<KnownSVal>())
+ if (auto KV = RVal.getAs<KnownSVal>())
report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
- *KV, L->getRegion(), EnableNullFPSuppression));
+ *KV, L->getRegion(), EnableNullFPSuppression));
const MemRegion *RegionRVal = RVal.getAsRegion();
if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
report.markInteresting(RegionRVal);
report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
- loc::MemRegionVal(RegionRVal), false));
+ loc::MemRegionVal(RegionRVal), false));
}
}
-
return true;
}
const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
const ExplodedNode *N) {
- const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
+ const auto *ME = dyn_cast<ObjCMessageExpr>(S);
if (!ME)
return nullptr;
if (const Expr *Receiver = ME->getInstanceReceiver()) {
ProgramStateRef state = N->getState();
- SVal V = state->getSVal(Receiver, N->getLocationContext());
+ SVal V = N->getSVal(Receiver);
if (state->isNull(V).isConstrainedTrue())
return Receiver;
}
@@ -1184,7 +1701,7 @@ NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
llvm::SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
- if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
+ if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
OS << "'";
ME->getSelector().print(OS);
OS << "' not called";
@@ -1217,16 +1734,15 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
const Stmt *Head = WorkList.front();
WorkList.pop_front();
- ProgramStateRef state = N->getState();
- ProgramStateManager &StateMgr = state->getStateManager();
+ ProgramStateManager &StateMgr = N->getState()->getStateManager();
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(Head)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
const VarRegion *R =
StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
// What did we load?
- SVal V = state->getSVal(S, N->getLocationContext());
+ SVal V = N->getSVal(S);
if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
// Register a new visitor with the BugReport.
@@ -1267,7 +1783,6 @@ std::shared_ptr<PathDiagnosticPiece>
ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
const ExplodedNode *Prev,
BugReporterContext &BRC, BugReport &BR) {
-
ProgramPoint progPoint = N->getLocation();
ProgramStateRef CurrentState = N->getState();
ProgramStateRef PrevState = Prev->getState();
@@ -1289,11 +1804,8 @@ ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
}
if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
- // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
- // violation.
const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
- cast<GRBugReporter>(BRC.getBugReporter()).
- getEngine().geteagerlyAssumeBinOpBifurcationTags();
+ ExprEngine::geteagerlyAssumeBinOpBifurcationTags();
const ProgramPointTag *tag = PS->getTag();
if (tag == tags.first)
@@ -1389,7 +1901,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, bool tookTrue,
return P;
break;
case Stmt::UnaryOperatorClass: {
- const UnaryOperator *UO = cast<UnaryOperator>(CondTmp);
+ const auto *UO = cast<UnaryOperator>(CondTmp);
if (UO->getOpcode() == UO_LNot) {
tookTrueTmp = !tookTrueTmp;
CondTmp = UO->getSubExpr();
@@ -1432,7 +1944,6 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
isa<CXXBoolLiteralExpr>(Ex) ||
isa<IntegerLiteral>(Ex) ||
isa<FloatingLiteral>(Ex))) {
-
StringRef StartName = Lexer::getImmediateMacroNameForDiagnostics(LocStart,
BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
StringRef EndName = Lexer::getImmediateMacroNameForDiagnostics(LocEnd,
@@ -1463,7 +1974,7 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
}
}
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
const bool quotes = isa<VarDecl>(DR->getDecl());
if (quotes) {
Out << '\'';
@@ -1487,7 +1998,7 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
return quotes;
}
- if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
+ if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
QualType OriginalTy = OriginalExpr->getType();
if (OriginalTy->isPointerType()) {
if (IL->getValue() == 0) {
@@ -1513,7 +2024,6 @@ std::shared_ptr<PathDiagnosticPiece>
ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
const bool tookTrue, BugReporterContext &BRC,
BugReport &R, const ExplodedNode *N) {
-
bool shouldInvert = false;
Optional<bool> shouldPrune;
@@ -1618,8 +2128,8 @@ std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable(
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
if (report.isInteresting(R))
@@ -1635,8 +2145,7 @@ std::shared_ptr<PathDiagnosticPiece>
ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
const bool tookTrue, BugReporterContext &BRC,
BugReport &report, const ExplodedNode *N) {
-
- const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ const auto *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
return nullptr;
@@ -1684,14 +2193,11 @@ bool ConditionBRVisitor::isPieceMessageGeneric(
Piece->getString() == GenericFalseMessage;
}
-std::unique_ptr<PathDiagnosticPiece>
-LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) {
+void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
+ BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) {
// Here we suppress false positives coming from system headers. This list is
// based on known issues.
- ExprEngine &Eng = BRC.getBugReporter().getEngine();
- AnalyzerOptions &Options = Eng.getAnalysisManager().options;
+ AnalyzerOptions &Options = BRC.getAnalyzerOptions();
const Decl *D = N->getLocationContext()->getDecl();
if (AnalysisDeclContext::isInStdNamespace(D)) {
@@ -1701,8 +2207,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// TR1, Boost, or llvm/ADT.
if (Options.shouldSuppressFromCXXStandardLibrary()) {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
-
+ return;
} else {
// If the complete 'std' suppression is not enabled, suppress reports
// from the 'std' namespace that are known to produce false positives.
@@ -1710,27 +2215,27 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// The analyzer issues a false use-after-free when std::list::pop_front
// or std::list::pop_back are called multiple times because we cannot
// reason about the internal invariants of the data structure.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "list") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
// The analyzer issues a false positive when the constructor of
// std::__independent_bits_engine from algorithms is used.
- if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "__independent_bits_engine") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
LCtx = LCtx->getParent()) {
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
+ const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
if (!MD)
continue;
@@ -1743,7 +2248,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// data structure.
if (CD->getName() == "basic_string") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
// The analyzer issues a false positive on
@@ -1751,7 +2256,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// because it does not reason properly about temporary destructors.
if (CD->getName() == "shared_ptr") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
}
@@ -1765,18 +2270,15 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
Loc = Loc.getSpellingLoc();
if (SM.getFilename(Loc).endswith("sys/queue.h")) {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
-
- return nullptr;
}
std::shared_ptr<PathDiagnosticPiece>
UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC, BugReport &BR) {
-
ProgramStateRef State = N->getState();
ProgramPoint ProgLoc = N->getLocation();
@@ -1789,18 +2291,17 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
unsigned Idx = 0;
- ArrayRef<ParmVarDecl*> parms = Call->parameters();
+ ArrayRef<ParmVarDecl *> parms = Call->parameters();
- for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
- I != E; ++I, ++Idx) {
+ for (const auto ParamDecl : parms) {
const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
+ ++Idx;
// Are we tracking the argument or its subregion?
- if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts())))
+ if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
continue;
// Check the function parameter type.
- const ParmVarDecl *ParamDecl = *I;
assert(ParamDecl && "Formal parameter has no decl?");
QualType T = ParamDecl->getType();
@@ -1832,7 +2333,7 @@ CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,
if (Satisfied)
return nullptr;
- auto Edge = Succ->getLocation().getAs<BlockEdge>();
+ const auto Edge = Succ->getLocation().getAs<BlockEdge>();
if (!Edge.hasValue())
return nullptr;
@@ -1859,7 +2360,7 @@ CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,
const auto Param =
State->getSVal(State->getRegion(Met->getParamDecl(0), LCtx));
const auto This =
- State->getSVal(SVB.getCXXThis(Met, LCtx->getCurrentStackFrame()));
+ State->getSVal(SVB.getCXXThis(Met, LCtx->getStackFrame()));
auto L = PathDiagnosticLocation::create(Met, BRC.getSourceManager());
@@ -1877,3 +2378,82 @@ CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,
return std::move(Piece);
}
+
+std::shared_ptr<PathDiagnosticPiece>
+TaintBugVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,
+ BugReporterContext &BRC, BugReport &BR) {
+
+ // Find the ExplodedNode where the taint was first introduced
+ if (!N->getState()->isTainted(V) || PrevN->getState()->isTainted(V))
+ return nullptr;
+
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S)
+ return nullptr;
+
+ const LocationContext *NCtx = N->getLocationContext();
+ PathDiagnosticLocation L =
+ PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx);
+ if (!L.isValid() || !L.asLocation().isValid())
+ return nullptr;
+
+ return std::make_shared<PathDiagnosticEventPiece>(L, "Taint originated here");
+}
+
+FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
+ : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
+
+void FalsePositiveRefutationBRVisitor::finalizeVisitor(
+ BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
+ // Collect new constraints
+ VisitNode(EndPathNode, nullptr, BRC, BR);
+
+ // Create a refutation manager
+ std::unique_ptr<SMTSolver> RefutationSolver = CreateZ3Solver();
+ ASTContext &Ctx = BRC.getASTContext();
+
+ // Add constraints to the solver
+ for (const auto &I : Constraints) {
+ SymbolRef Sym = I.first;
+
+ SMTExprRef Constraints = RefutationSolver->fromBoolean(false);
+ for (const auto &Range : I.second) {
+ Constraints = RefutationSolver->mkOr(
+ Constraints,
+ RefutationSolver->getRangeExpr(Ctx, Sym, Range.From(), Range.To(),
+ /*InRange=*/true));
+ }
+ RefutationSolver->addConstraint(Constraints);
+ }
+
+ // And check for satisfiability
+ if (RefutationSolver->check().isConstrainedFalse())
+ BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
+ // Collect new constraints
+ const ConstraintRangeTy &NewCs = N->getState()->get<ConstraintRange>();
+ ConstraintRangeTy::Factory &CF =
+ N->getState()->get_context<ConstraintRange>();
+
+ // Add constraints if we don't have them yet
+ for (auto const &C : NewCs) {
+ const SymbolRef &Sym = C.first;
+ if (!Constraints.contains(Sym)) {
+ Constraints = CF.add(Constraints, Sym, C.second);
+ }
+ }
+
+ return nullptr;
+}
+
+void FalsePositiveRefutationBRVisitor::Profile(
+ llvm::FoldingSetNodeID &ID) const {
+ static int Tag = 0;
+ ID.AddPointer(&Tag);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 776369be9dba..fe9260e32dd8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -1,4 +1,4 @@
-//===- Calls.cpp - Wrapper for all function and method calls ------*- C++ -*--//
+//===- CallEvent.cpp - Wrapper for all function and method calls ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,14 +14,53 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/CrossTU/CrossTranslationUnit.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <utility>
#define DEBUG_TYPE "static-analyzer-call-event"
@@ -29,11 +68,13 @@ using namespace clang;
using namespace ento;
QualType CallEvent::getResultType() const {
+ ASTContext &Ctx = getState()->getStateManager().getContext();
const Expr *E = getOriginExpr();
- assert(E && "Calls without origin expressions do not have results");
- QualType ResultTy = E->getType();
+ if (!E)
+ return Ctx.VoidTy;
+ assert(E);
- ASTContext &Ctx = getState()->getStateManager().getContext();
+ QualType ResultTy = E->getType();
// A function that returns a reference to 'int' will have a result type
// of simply 'int'. Check the origin expr's value kind to recover the
@@ -78,7 +119,7 @@ static bool isCallback(QualType T) {
}
static bool isVoidPointerToNonConst(QualType T) {
- if (const PointerType *PT = T->getAs<PointerType>()) {
+ if (const auto *PT = T->getAs<PointerType>()) {
QualType PointeeTy = PT->getPointeeType();
if (PointeeTy.isConstQualified())
return false;
@@ -119,14 +160,76 @@ bool CallEvent::hasVoidPointerToNonConstArg() const {
}
bool CallEvent::isGlobalCFunction(StringRef FunctionName) const {
- const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(getDecl());
+ const auto *FD = dyn_cast_or_null<FunctionDecl>(getDecl());
if (!FD)
return false;
return CheckerContext::isCLibraryFunction(FD, FunctionName);
}
-/// \brief Returns true if a type is a pointer-to-const or reference-to-const
+AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const {
+ const Decl *D = getDecl();
+
+ // If the callee is completely unknown, we cannot construct the stack frame.
+ if (!D)
+ return nullptr;
+
+ // FIXME: Skip virtual functions for now. There's no easy procedure to foresee
+ // the exact decl that should be used, especially when it's not a definition.
+ if (const Decl *RD = getRuntimeDefinition().getDecl())
+ if (RD != D)
+ return nullptr;
+
+ return LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
+}
+
+const StackFrameContext *CallEvent::getCalleeStackFrame() const {
+ AnalysisDeclContext *ADC = getCalleeAnalysisDeclContext();
+ if (!ADC)
+ return nullptr;
+
+ const Expr *E = getOriginExpr();
+ if (!E)
+ return nullptr;
+
+ // Recover CFG block via reverse lookup.
+ // TODO: If we were to keep CFG element information as part of the CallEvent
+ // instead of doing this reverse lookup, we would be able to build the stack
+ // frame for non-expression-based calls, and also we wouldn't need the reverse
+ // lookup.
+ CFGStmtMap *Map = LCtx->getAnalysisDeclContext()->getCFGStmtMap();
+ const CFGBlock *B = Map->getBlock(E);
+ assert(B);
+
+ // Also recover CFG index by scanning the CFG block.
+ unsigned Idx = 0, Sz = B->size();
+ for (; Idx < Sz; ++Idx)
+ if (auto StmtElem = (*B)[Idx].getAs<CFGStmt>())
+ if (StmtElem->getStmt() == E)
+ break;
+ assert(Idx < Sz);
+
+ return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, Idx);
+}
+
+const VarRegion *CallEvent::getParameterLocation(unsigned Index) const {
+ const StackFrameContext *SFC = getCalleeStackFrame();
+ // We cannot construct a VarRegion without a stack frame.
+ if (!SFC)
+ return nullptr;
+
+ const ParmVarDecl *PVD = parameters()[Index];
+ const VarRegion *VR =
+ State->getStateManager().getRegionManager().getVarRegion(PVD, SFC);
+
+ // This sanity check would fail if our parameter declaration doesn't
+ // correspond to the stack frame's function declaration.
+ assert(VR->getStackFrame() == SFC);
+
+ return VR;
+}
+
+/// Returns true if a type is a pointer-to-const or reference-to-const
/// with no further indirection.
static bool isPointerToConst(QualType Ty) {
QualType PointeeTy = Ty->getPointeeType();
@@ -235,7 +338,7 @@ SVal CallEvent::getArgSVal(unsigned Index) const {
SourceRange CallEvent::getArgSourceRange(unsigned Index) const {
const Expr *ArgE = getArgExpr(Index);
if (!ArgE)
- return SourceRange();
+ return {};
return ArgE->getSourceRange();
}
@@ -266,7 +369,6 @@ void CallEvent::dump(raw_ostream &Out) const {
Out << "Unknown call (type " << getKind() << ")";
}
-
bool CallEvent::isCallStmt(const Stmt *S) {
return isa<CallExpr>(S) || isa<ObjCMessageExpr>(S)
|| isa<CXXConstructExpr>(S)
@@ -275,11 +377,11 @@ bool CallEvent::isCallStmt(const Stmt *S) {
QualType CallEvent::getDeclaredResultType(const Decl *D) {
assert(D);
- if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->getReturnType();
- if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getReturnType();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ if (const auto *BD = dyn_cast<BlockDecl>(D)) {
// Blocks are difficult because the return type may not be stored in the
// BlockDecl itself. The AST should probably be enhanced, but for now we
// just do what we can.
@@ -296,7 +398,7 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) {
return Ty;
}
- return QualType();
+ return {};
}
llvm_unreachable("unknown callable kind");
@@ -305,11 +407,11 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) {
bool CallEvent::isVariadic(const Decl *D) {
assert(D);
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->isVariadic();
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->isVariadic();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->isVariadic();
llvm_unreachable("unknown callable kind");
@@ -350,32 +452,53 @@ ArrayRef<ParmVarDecl*> AnyFunctionCall::parameters() const {
RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const {
const FunctionDecl *FD = getDecl();
+ if (!FD)
+ return {};
+
// 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);
- }
+ AnalysisDeclContext *AD =
+ getLocationContext()->getAnalysisDeclContext()->
+ getManager()->getContext(FD);
+ bool IsAutosynthesized;
+ Stmt* Body = AD->getBody(IsAutosynthesized);
+ LLVM_DEBUG({
+ if (IsAutosynthesized)
+ llvm::dbgs() << "Using autosynthesized body for " << FD->getName()
+ << "\n";
+ });
+ if (Body) {
+ const Decl* Decl = AD->getDecl();
+ return RuntimeDefinition(Decl);
}
- return RuntimeDefinition();
+ SubEngine *Engine = getState()->getStateManager().getOwningEngine();
+ AnalyzerOptions &Opts = Engine->getAnalysisManager().options;
+
+ // Try to get CTU definition only if CTUDir is provided.
+ if (!Opts.naiveCTUEnabled())
+ return {};
+
+ cross_tu::CrossTranslationUnitContext &CTUCtx =
+ *Engine->getCrossTranslationUnitContext();
+ llvm::Expected<const FunctionDecl *> CTUDeclOrError =
+ CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+
+ if (!CTUDeclOrError) {
+ handleAllErrors(CTUDeclOrError.takeError(),
+ [&](const cross_tu::IndexError &IE) {
+ CTUCtx.emitCrossTUDiagnostics(IE);
+ });
+ return {};
+ }
+
+ return RuntimeDefinition(*CTUDeclOrError);
}
void AnyFunctionCall::getInitialStackFrameContents(
const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const {
- const FunctionDecl *D = cast<FunctionDecl>(CalleeCtx->getDecl());
+ const auto *D = cast<FunctionDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
D->parameters());
@@ -442,7 +565,6 @@ bool AnyFunctionCall::argumentsMayEscape() const {
return false;
}
-
const FunctionDecl *SimpleFunctionCall::getDecl() const {
const FunctionDecl *D = getOriginExpr()->getDirectCallee();
if (D)
@@ -451,9 +573,8 @@ const FunctionDecl *SimpleFunctionCall::getDecl() const {
return getSVal(getOriginExpr()->getCallee()).getAsFunctionDecl();
}
-
const FunctionDecl *CXXInstanceCall::getDecl() const {
- const CallExpr *CE = cast_or_null<CallExpr>(getOriginExpr());
+ const auto *CE = cast_or_null<CallExpr>(getOriginExpr());
if (!CE)
return AnyFunctionCall::getDecl();
@@ -470,15 +591,20 @@ void CXXInstanceCall::getExtraInvalidatedValues(
Values.push_back(ThisVal);
// Don't invalidate if the method is const and there are no mutable fields.
- if (const CXXMethodDecl *D = cast_or_null<CXXMethodDecl>(getDecl())) {
+ if (const auto *D = cast_or_null<CXXMethodDecl>(getDecl())) {
if (!D->isConst())
return;
// Get the record decl for the class of 'This'. D->getParent() may return a
// base class decl, rather than the class of the instance which needs to be
// checked for mutable fields.
+ // TODO: We might as well look at the dynamic type of the object.
const Expr *Ex = getCXXThisExpr()->ignoreParenBaseCasts();
- const CXXRecordDecl *ParentRecord = Ex->getType()->getAsCXXRecordDecl();
- if (!ParentRecord || ParentRecord->hasMutableFields())
+ QualType T = Ex->getType();
+ if (T->isPointerType()) // Arrow or implicit-this syntax?
+ T = T->getPointeeType();
+ const CXXRecordDecl *ParentRecord = T->getAsCXXRecordDecl();
+ assert(ParentRecord);
+ if (ParentRecord->hasMutableFields())
return;
// Preserve CXXThis.
const MemRegion *ThisRegion = ThisVal.getAsRegion();
@@ -501,27 +627,26 @@ SVal CXXInstanceCall::getCXXThisVal() const {
return ThisVal;
}
-
RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
// Do we have a decl at all?
const Decl *D = getDecl();
if (!D)
- return RuntimeDefinition();
+ return {};
// If the method is non-virtual, we know we can inline it.
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
+ const auto *MD = cast<CXXMethodDecl>(D);
if (!MD->isVirtual())
return AnyFunctionCall::getRuntimeDefinition();
// Do we know the implicit 'this' object being called?
const MemRegion *R = getCXXThisVal().getAsRegion();
if (!R)
- return RuntimeDefinition();
+ return {};
// Do we know anything about the type of 'this'?
DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R);
if (!DynType.isValid())
- return RuntimeDefinition();
+ return {};
// Is the type a C++ class? (This is mostly a defensive check.)
QualType RegionType = DynType.getType()->getPointeeType();
@@ -529,7 +654,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl();
if (!RD || !RD->hasDefinition())
- return RuntimeDefinition();
+ return {};
// Find the decl for this method in that class.
const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true);
@@ -547,13 +672,13 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
// this is fixed. <rdar://problem/12287087>
//assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo");
- return RuntimeDefinition();
+ return {};
}
// Does the decl that we found have an implementation?
const FunctionDecl *Definition;
if (!Result->hasBody(Definition))
- return RuntimeDefinition();
+ return {};
// We found a definition. If we're not sure that this devirtualization is
// actually what will happen at runtime, make sure to provide the region so
@@ -574,7 +699,7 @@ void CXXInstanceCall::getInitialStackFrameContents(
ProgramStateManager &StateMgr = getState()->getStateManager();
SValBuilder &SVB = StateMgr.getSValBuilder();
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
+ const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
// If we devirtualized to a different member function, we need to make sure
@@ -587,7 +712,15 @@ void CXXInstanceCall::getInitialStackFrameContents(
// FIXME: CallEvent maybe shouldn't be directly accessing StoreManager.
bool Failed;
ThisVal = StateMgr.getStoreManager().attemptDownCast(ThisVal, Ty, Failed);
- assert(!Failed && "Calling an incorrectly devirtualized method");
+ if (Failed) {
+ // We might have suffered some sort of placement new earlier, so
+ // we're constructing in a completely unexpected storage.
+ // Fall back to a generic pointer cast for this-value.
+ const CXXMethodDecl *StaticMD = cast<CXXMethodDecl>(getDecl());
+ const CXXRecordDecl *StaticClass = StaticMD->getParent();
+ QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass));
+ ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy);
+ }
}
if (!ThisVal.isUnknown())
@@ -595,8 +728,6 @@ void CXXInstanceCall::getInitialStackFrameContents(
}
}
-
-
const Expr *CXXMemberCall::getCXXThisExpr() const {
return getOriginExpr()->getImplicitObjectArgument();
}
@@ -606,19 +737,17 @@ RuntimeDefinition CXXMemberCall::getRuntimeDefinition() const {
// id-expression in the class member access expression is a qualified-id,
// that function is called. Otherwise, its final overrider in the dynamic type
// of the object expression is called.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee()))
+ if (const auto *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee()))
if (ME->hasQualifier())
return AnyFunctionCall::getRuntimeDefinition();
return CXXInstanceCall::getRuntimeDefinition();
}
-
const Expr *CXXMemberOperatorCall::getCXXThisExpr() const {
return getOriginExpr()->getArg(0);
}
-
const BlockDataRegion *BlockCall::getBlockRegion() const {
const Expr *Callee = getOriginExpr()->getCallee();
const MemRegion *DataReg = getSVal(Callee).getAsRegion();
@@ -663,7 +792,6 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
Params);
}
-
SVal CXXConstructorCall::getCXXThisVal() const {
if (Data)
return loc::MemRegionVal(static_cast<const MemRegion *>(Data));
@@ -672,8 +800,13 @@ SVal CXXConstructorCall::getCXXThisVal() const {
void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values,
RegionAndSymbolInvalidationTraits *ETraits) const {
- if (Data)
- Values.push_back(loc::MemRegionVal(static_cast<const MemRegion *>(Data)));
+ if (Data) {
+ loc::MemRegionVal MV(static_cast<const MemRegion *>(Data));
+ if (SymbolRef Sym = MV.getAsSymbol(true))
+ ETraits->setTrait(Sym,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape);
+ Values.push_back(MV);
+ }
}
void CXXConstructorCall::getInitialStackFrameContents(
@@ -684,7 +817,7 @@ void CXXConstructorCall::getInitialStackFrameContents(
SVal ThisVal = getCXXThisVal();
if (!ThisVal.isUnknown()) {
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
+ const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
}
@@ -785,7 +918,7 @@ SourceRange ObjCMethodCall::getSourceRange() const {
llvm_unreachable("unknown message kind");
}
-typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy;
+using ObjCMessageDataTy = llvm::PointerIntPair<const PseudoObjectExpr *, 2>;
const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
assert(Data && "Lazy lookup not yet performed.");
@@ -799,7 +932,7 @@ getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) {
// This handles the funny case of assigning to the result of a getter.
// This can happen if the getter returns a non-const reference.
- if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(Syntactic))
+ if (const auto *BO = dyn_cast<BinaryOperator>(Syntactic))
Syntactic = BO->getLHS();
return Syntactic;
@@ -807,13 +940,12 @@ getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) {
ObjCMessageKind ObjCMethodCall::getMessageKind() const {
if (!Data) {
-
// Find the parent, ignoring implicit casts.
ParentMap &PM = getLocationContext()->getParentMap();
const Stmt *S = PM.getParentIgnoreParenCasts(getOriginExpr());
// Check if parent is a PseudoObjectExpr.
- if (const PseudoObjectExpr *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) {
+ if (const auto *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) {
const Expr *Syntactic = getSyntacticFromForPseudoObjectExpr(POE);
ObjCMessageKind K;
@@ -875,15 +1007,14 @@ const ObjCPropertyDecl *ObjCMethodCall::getAccessedProperty() const {
bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
Selector Sel) const {
assert(IDecl);
- const SourceManager &SM =
- getState()->getStateManager().getContext().getSourceManager();
-
+ AnalysisManager &AMgr =
+ getState()->getStateManager().getOwningEngine()->getAnalysisManager();
// If the class interface is declared inside the main file, assume it is not
// subcassed.
// TODO: It could actually be subclassed if the subclass is private as well.
// This is probably very rare.
SourceLocation InterfLoc = IDecl->getEndOfDefinitionLoc();
- if (InterfLoc.isValid() && SM.isInMainFile(InterfLoc))
+ if (InterfLoc.isValid() && AMgr.isInCodeFile(InterfLoc))
return false;
// Assume that property accessors are not overridden.
@@ -905,7 +1036,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
return false;
// If outside the main file,
- if (D->getLocation().isValid() && !SM.isInMainFile(D->getLocation()))
+ if (D->getLocation().isValid() && !AMgr.isInCodeFile(D->getLocation()))
return true;
if (D->isOverriding()) {
@@ -965,7 +1096,6 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
Selector Sel = E->getSelector();
if (E->isInstanceMessage()) {
-
// Find the receiver type.
const ObjCObjectPointerType *ReceiverT = nullptr;
bool CanBeSubClassed = false;
@@ -980,13 +1110,13 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
} else {
Receiver = getReceiverSVal().getAsRegion();
if (!Receiver)
- return RuntimeDefinition();
+ return {};
DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver);
if (!DTI.isValid()) {
assert(isa<AllocaRegion>(Receiver) &&
"Unhandled untyped region class!");
- return RuntimeDefinition();
+ return {};
}
QualType DynType = DTI.getType();
@@ -1041,11 +1171,9 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
// need to revisit this someday. In terms of memory, this table
// stays around until clang quits, which also may be bad if we
// need to release memory.
- typedef std::pair<const ObjCInterfaceDecl*, Selector>
- PrivateMethodKey;
- typedef llvm::DenseMap<PrivateMethodKey,
- Optional<const ObjCMethodDecl *> >
- PrivateMethodCache;
+ using PrivateMethodKey = std::pair<const ObjCInterfaceDecl *, Selector>;
+ using PrivateMethodCache =
+ llvm::DenseMap<PrivateMethodKey, Optional<const ObjCMethodDecl *>>;
static PrivateMethodCache PMC;
Optional<const ObjCMethodDecl *> &Val = PMC[std::make_pair(IDecl, Sel)];
@@ -1090,7 +1218,6 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
else
return RuntimeDefinition(MD, nullptr);
}
-
} else {
// This is a class method.
// If we have type info for the receiver class, we are calling via
@@ -1101,7 +1228,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
}
}
- return RuntimeDefinition();
+ return {};
}
bool ObjCMethodCall::argumentsMayEscape() const {
@@ -1118,7 +1245,7 @@ bool ObjCMethodCall::argumentsMayEscape() const {
void ObjCMethodCall::getInitialStackFrameContents(
const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const {
- const ObjCMethodDecl *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl());
+ const auto *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
D->parameters());
@@ -1135,12 +1262,12 @@ void ObjCMethodCall::getInitialStackFrameContents(
CallEventRef<>
CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
const LocationContext *LCtx) {
- if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE))
+ if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(CE))
return create<CXXMemberCall>(MCE, State, LCtx);
- if (const CXXOperatorCallExpr *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
+ if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
const FunctionDecl *DirectCallee = OpCE->getDirectCallee();
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DirectCallee))
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee))
if (MD->isInstance())
return create<CXXMemberOperatorCall>(OpCE, State, LCtx);
@@ -1153,12 +1280,11 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
return create<SimpleFunctionCall>(CE, State, LCtx);
}
-
CallEventRef<>
CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
ProgramStateRef State) {
const LocationContext *ParentCtx = CalleeCtx->getParent();
- const LocationContext *CallerCtx = ParentCtx->getCurrentStackFrame();
+ const LocationContext *CallerCtx = ParentCtx->getStackFrame();
assert(CallerCtx && "This should not be used for top-level stack frames");
const Stmt *CallSite = CalleeCtx->getCallSite();
@@ -1171,7 +1297,7 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
case Stmt::CXXConstructExprClass:
case Stmt::CXXTemporaryObjectExprClass: {
SValBuilder &SVB = State->getStateManager().getSValBuilder();
- const CXXMethodDecl *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl());
+ const auto *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl());
Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx);
SVal ThisVal = State->getSVal(ThisPtr);
@@ -1192,12 +1318,11 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
// destructors, though this could change in the future.
const CFGBlock *B = CalleeCtx->getCallSiteBlock();
CFGElement E = (*B)[CalleeCtx->getIndex()];
- assert(E.getAs<CFGImplicitDtor>() &&
+ assert((E.getAs<CFGImplicitDtor>() || E.getAs<CFGTemporaryDtor>()) &&
"All other CFG elements should have exprs");
- assert(!E.getAs<CFGTemporaryDtor>() && "We don't handle temporaries yet");
SValBuilder &SVB = State->getStateManager().getSValBuilder();
- const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl());
+ const auto *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl());
Loc ThisPtr = SVB.getCXXThis(Dtor, CalleeCtx);
SVal ThisVal = State->getSVal(ThisPtr);
@@ -1205,7 +1330,7 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
if (Optional<CFGAutomaticObjDtor> AutoDtor = E.getAs<CFGAutomaticObjDtor>())
Trigger = AutoDtor->getTriggerStmt();
else if (Optional<CFGDeleteDtor> DeleteDtor = E.getAs<CFGDeleteDtor>())
- Trigger = cast<Stmt>(DeleteDtor->getDeleteExpr());
+ Trigger = DeleteDtor->getDeleteExpr();
else
Trigger = Dtor->getBody();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 61cbf3854bb2..6cf931abbddd 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -20,9 +20,8 @@ using namespace clang;
using namespace ento;
const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const {
- ProgramStateRef State = getState();
const Expr *Callee = CE->getCallee();
- SVal L = State->getSVal(Callee, Pred->getLocationContext());
+ SVal L = Pred->getSVal(Callee);
return L.getAsFunctionDecl();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index ed41914ebd05..b9facffcc8b5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -15,8 +15,12 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+namespace clang {
+
+namespace ento {
+
// Recursively find any substatements containing macros
-bool clang::ento::containsMacro(const Stmt *S) {
+bool containsMacro(const Stmt *S) {
if (S->getLocStart().isMacroID())
return true;
@@ -31,7 +35,7 @@ bool clang::ento::containsMacro(const Stmt *S) {
}
// Recursively find any substatements containing enum constants
-bool clang::ento::containsEnum(const Stmt *S) {
+bool containsEnum(const Stmt *S) {
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
if (DR && isa<EnumConstantDecl>(DR->getDecl()))
@@ -45,7 +49,7 @@ bool clang::ento::containsEnum(const Stmt *S) {
}
// Recursively find any substatements containing static vars
-bool clang::ento::containsStaticLocal(const Stmt *S) {
+bool containsStaticLocal(const Stmt *S) {
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
if (DR)
@@ -61,7 +65,7 @@ bool clang::ento::containsStaticLocal(const Stmt *S) {
}
// Recursively find any substatements containing __builtin_offsetof
-bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {
+bool containsBuiltinOffsetOf(const Stmt *S) {
if (isa<OffsetOfExpr>(S))
return true;
@@ -74,7 +78,7 @@ bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {
// Extract lhs and rhs from assignment statement
std::pair<const clang::VarDecl *, const clang::Expr *>
-clang::ento::parseAssignment(const Stmt *S) {
+parseAssignment(const Stmt *S) {
const VarDecl *VD = nullptr;
const Expr *RHS = nullptr;
@@ -94,3 +98,18 @@ clang::ento::parseAssignment(const Stmt *S) {
return std::make_pair(VD, RHS);
}
+
+Nullability getNullabilityAnnotation(QualType Type) {
+ const auto *AttrType = Type->getAs<AttributedType>();
+ if (!AttrType)
+ return Nullability::Unspecified;
+ if (AttrType->getAttrKind() == AttributedType::attr_nullable)
+ return Nullability::Nullable;
+ else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
+ return Nullability::Nonnull;
+ return Nullability::Unspecified;
+}
+
+
+} // end namespace ento
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 49f3edef2a2d..712872a15d8a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -1,4 +1,4 @@
-//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
+//===- CheckerManager.cpp - Static Analyzer Checker Manager ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,10 +13,20 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/AST/DeclBase.h"
+#include "clang/AST/Stmt.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <vector>
using namespace clang;
using namespace ento;
@@ -43,9 +53,9 @@ void CheckerManager::finishedCheckerRegistration() {
#ifndef NDEBUG
// Make sure that for every event that has listeners, there is at least
// one dispatcher registered for it.
- for (llvm::DenseMap<EventTag, EventInfo>::iterator
- I = Events.begin(), E = Events.end(); I != E; ++I)
- assert(I->second.HasDispatcher && "No dispatcher registered for an event");
+ for (const auto &Event : Events)
+ assert(Event.second.HasDispatcher &&
+ "No dispatcher registered for an event");
#endif
}
@@ -65,25 +75,22 @@ void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
} else {
// Find the checkers that should run for this Decl and cache them.
checkers = &CachedDeclCheckersMap[DeclKind];
- for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
- DeclCheckerInfo &info = DeclCheckers[i];
+ for (const auto &info : DeclCheckers)
if (info.IsForDeclFn(D))
checkers->push_back(info.CheckFn);
- }
}
assert(checkers);
- for (CachedDeclCheckers::iterator
- I = checkers->begin(), E = checkers->end(); I != E; ++I)
- (*I)(D, mgr, BR);
+ for (const auto checker : *checkers)
+ checker(D, mgr, BR);
}
void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
BugReporter &BR) {
assert(D && D->hasBody());
- for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
- BodyCheckers[i](D, mgr, BR);
+ for (const auto BodyChecker : BodyCheckers)
+ BodyChecker(D, mgr, BR);
}
//===----------------------------------------------------------------------===//
@@ -118,10 +125,8 @@ static void expandGraphWithCheckers(CHECK_CTX checkCtx,
}
NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI) {
- checkCtx.runChecker(*I, B, *NI);
- }
+ for (const auto &NI : *PrevSet)
+ checkCtx.runChecker(*I, B, NI);
// If all the produced transitions are sinks, stop.
if (CurrSet->empty())
@@ -133,21 +138,23 @@ static void expandGraphWithCheckers(CHECK_CTX checkCtx,
}
namespace {
+
struct CheckStmtContext {
- typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
+ using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
+
bool IsPreVisit;
const CheckersTy &Checkers;
const Stmt *S;
ExprEngine &Eng;
bool WasInlined;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
const Stmt *s, ExprEngine &eng, bool wasInlined = false)
- : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
- WasInlined(wasInlined) {}
+ : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
+ WasInlined(wasInlined) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckStmtFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -160,9 +167,10 @@ namespace {
checkFn(S, C);
}
};
-}
-/// \brief Run checkers for visiting Stmts.
+} // namespace
+
+/// Run checkers for visiting Stmts.
void CheckerManager::runCheckersForStmt(bool isPreVisit,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
@@ -175,8 +183,9 @@ void CheckerManager::runCheckersForStmt(bool isPreVisit,
}
namespace {
+
struct CheckObjCMessageContext {
- typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
ObjCMessageVisitKind Kind;
bool WasInlined;
@@ -184,19 +193,18 @@ namespace {
const ObjCMethodCall &Msg;
ExprEngine &Eng;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
const CheckersTy &checkers,
const ObjCMethodCall &msg, ExprEngine &eng,
bool wasInlined)
- : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers),
- Msg(msg), Eng(eng) { }
+ : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
+ Eng(eng) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
-
bool IsPreVisit;
switch (Kind) {
@@ -215,9 +223,10 @@ namespace {
checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
}
};
-}
-/// \brief Run checkers for visiting obj-c messages.
+} // namespace
+
+/// Run checkers for visiting obj-c messages.
void CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
@@ -242,24 +251,27 @@ CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
}
llvm_unreachable("Unknown Kind");
}
+
namespace {
+
// FIXME: This has all the same signatures as CheckObjCMessageContext.
// Is there a way we can merge the two?
struct CheckCallContext {
- typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
+
bool IsPreVisit, WasInlined;
const CheckersTy &Checkers;
const CallEvent &Call;
ExprEngine &Eng;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
const CallEvent &call, ExprEngine &eng,
bool wasInlined)
- : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
- Call(call), Eng(eng) { }
+ : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
+ Call(call), Eng(eng) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckCallFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -269,9 +281,10 @@ namespace {
checkFn(*Call.cloneWithState(Pred->getState()), C);
}
};
-}
-/// \brief Run checkers for visiting an abstract call event.
+} // namespace
+
+/// Run checkers for visiting an abstract call event.
void CheckerManager::runCheckersForCallEvent(bool isPreVisit,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
@@ -286,8 +299,10 @@ void CheckerManager::runCheckersForCallEvent(bool isPreVisit,
}
namespace {
+
struct CheckLocationContext {
- typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
+
const CheckersTy &Checkers;
SVal Loc;
bool IsLoad;
@@ -295,15 +310,15 @@ namespace {
const Stmt *BoundEx;
ExprEngine &Eng;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckLocationContext(const CheckersTy &checkers,
SVal loc, bool isLoad, const Stmt *NodeEx,
const Stmt *BoundEx,
ExprEngine &eng)
- : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
- BoundEx(BoundEx), Eng(eng) {}
+ : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
+ BoundEx(BoundEx), Eng(eng) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckLocationFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -317,9 +332,10 @@ namespace {
checkFn(Loc, IsLoad, BoundEx, C);
}
};
-}
-/// \brief Run checkers for load/store of a location.
+} // namespace
+
+/// Run checkers for load/store of a location.
void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
@@ -333,8 +349,10 @@ void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
}
namespace {
+
struct CheckBindContext {
- typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
+
const CheckersTy &Checkers;
SVal Loc;
SVal Val;
@@ -342,13 +360,13 @@ namespace {
ExprEngine &Eng;
const ProgramPoint &PP;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckBindContext(const CheckersTy &checkers,
SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
const ProgramPoint &pp)
- : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
+ : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckBindFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -358,9 +376,10 @@ namespace {
checkFn(Loc, Val, S, C);
}
};
-}
-/// \brief Run checkers for binding of a value to a location.
+} // namespace
+
+/// Run checkers for binding of a value to a location.
void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
SVal location, SVal val,
@@ -373,24 +392,26 @@ void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
BugReporter &BR,
ExprEngine &Eng) {
- for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
- EndAnalysisCheckers[i](G, BR, Eng);
+ for (const auto EndAnalysisChecker : EndAnalysisCheckers)
+ EndAnalysisChecker(G, BR, Eng);
}
namespace {
+
struct CheckBeginFunctionContext {
- typedef std::vector<CheckerManager::CheckBeginFunctionFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
+
const CheckersTy &Checkers;
ExprEngine &Eng;
const ProgramPoint &PP;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
const ProgramPoint &PP)
: Checkers(Checkers), Eng(Eng), PP(PP) {}
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
const ProgramPoint &L = PP.withTag(checkFn.Checker);
@@ -399,7 +420,8 @@ struct CheckBeginFunctionContext {
checkFn(C);
}
};
-}
+
+} // namespace
void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
const BlockEdge &L,
@@ -411,42 +433,42 @@ void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
expandGraphWithCheckers(C, Dst, Src);
}
-/// \brief Run checkers for end of path.
+/// Run checkers for end of path.
// Note, We do not chain the checker output (like in expandGraphWithCheckers)
// for this callback since end of path nodes are expected to be final.
void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
ExplodedNodeSet &Dst,
ExplodedNode *Pred,
- ExprEngine &Eng) {
-
+ ExprEngine &Eng,
+ const ReturnStmt *RS) {
// We define the builder outside of the loop bacause if at least one checkers
// creates a sucsessor for Pred, we do not need to generate an
// autotransition for it.
NodeBuilder Bldr(Pred, Dst, BC);
- for (unsigned i = 0, e = EndFunctionCheckers.size(); i != e; ++i) {
- CheckEndFunctionFunc checkFn = EndFunctionCheckers[i];
-
+ for (const auto checkFn : EndFunctionCheckers) {
const ProgramPoint &L = BlockEntrance(BC.Block,
Pred->getLocationContext(),
checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
- checkFn(C);
+ checkFn(RS, C);
}
}
namespace {
+
struct CheckBranchConditionContext {
- typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
+
const CheckersTy &Checkers;
const Stmt *Condition;
ExprEngine &Eng;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckBranchConditionContext(const CheckersTy &checkers,
const Stmt *Cond, ExprEngine &eng)
- : Checkers(checkers), Condition(Cond), Eng(eng) {}
+ : Checkers(checkers), Condition(Cond), Eng(eng) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -456,9 +478,10 @@ namespace {
checkFn(Condition, C);
}
};
-}
-/// \brief Run checkers for branch condition.
+} // namespace
+
+/// Run checkers for branch condition.
void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
ExplodedNodeSet &Dst,
ExplodedNode *Pred,
@@ -469,29 +492,69 @@ void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
expandGraphWithCheckers(C, Dst, Src);
}
-/// \brief Run checkers for live symbols.
+namespace {
+
+ struct CheckNewAllocatorContext {
+ using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
+
+ const CheckersTy &Checkers;
+ const CXXNewExpr *NE;
+ SVal Target;
+ bool WasInlined;
+ ExprEngine &Eng;
+
+ CheckNewAllocatorContext(const CheckersTy &Checkers, const CXXNewExpr *NE,
+ SVal Target, bool WasInlined, ExprEngine &Eng)
+ : Checkers(Checkers), NE(NE), Target(Target), WasInlined(WasInlined),
+ Eng(Eng) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
+ NodeBuilder &Bldr, ExplodedNode *Pred) {
+ ProgramPoint L = PostAllocatorCall(NE, Pred->getLocationContext());
+ CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
+ checkFn(NE, Target, C);
+ }
+ };
+
+} // namespace
+
+void CheckerManager::runCheckersForNewAllocator(
+ const CXXNewExpr *NE, SVal Target, ExplodedNodeSet &Dst, ExplodedNode *Pred,
+ ExprEngine &Eng, bool WasInlined) {
+ ExplodedNodeSet Src;
+ Src.insert(Pred);
+ CheckNewAllocatorContext C(NewAllocatorCheckers, NE, Target, WasInlined, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+/// Run checkers for live symbols.
void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
SymbolReaper &SymReaper) {
- for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
- LiveSymbolsCheckers[i](state, SymReaper);
+ for (const auto LiveSymbolsChecker : LiveSymbolsCheckers)
+ LiveSymbolsChecker(state, SymReaper);
}
namespace {
+
struct CheckDeadSymbolsContext {
- typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
+ using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
+
const CheckersTy &Checkers;
SymbolReaper &SR;
const Stmt *S;
ExprEngine &Eng;
ProgramPoint::Kind ProgarmPointKind;
- CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
- CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
-
CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
const Stmt *s, ExprEngine &eng,
ProgramPoint::Kind K)
- : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
+ : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -505,9 +568,10 @@ namespace {
checkFn(SR, C);
}
};
-}
-/// \brief Run checkers for dead symbols.
+} // namespace
+
+/// Run checkers for dead symbols.
void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
SymbolReaper &SymReaper,
@@ -518,7 +582,7 @@ void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
expandGraphWithCheckers(C, Dst, Src);
}
-/// \brief Run checkers for region changes.
+/// Run checkers for region changes.
ProgramStateRef
CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
@@ -526,19 +590,18 @@ CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) {
- for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
+ for (const auto RegionChangesChecker : RegionChangesCheckers) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
return nullptr;
- state = RegionChangesCheckers[i](state, invalidated,
- ExplicitRegions, Regions,
- LCtx, Call);
+ state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
+ LCtx, Call);
}
return state;
}
-/// \brief Run checkers to process symbol escape event.
+/// Run checkers to process symbol escape event.
ProgramStateRef
CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
@@ -549,58 +612,55 @@ CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
(Kind != PSK_DirectEscapeOnCall &&
Kind != PSK_IndirectEscapeOnCall)) &&
"Call must not be NULL when escaping on call");
- for (unsigned i = 0, e = PointerEscapeCheckers.size(); i != e; ++i) {
- // If any checker declares the state infeasible (or if it starts that
- // way), bail out.
- if (!State)
- return nullptr;
- State = PointerEscapeCheckers[i](State, Escaped, Call, Kind, ETraits);
- }
+ for (const auto PointerEscapeChecker : PointerEscapeCheckers) {
+ // If any checker declares the state infeasible (or if it starts that
+ // way), bail out.
+ if (!State)
+ return nullptr;
+ State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
+ }
return State;
}
-/// \brief Run checkers for handling assumptions on symbolic values.
+/// Run checkers for handling assumptions on symbolic values.
ProgramStateRef
CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
SVal Cond, bool Assumption) {
- for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
+ for (const auto EvalAssumeChecker : EvalAssumeCheckers) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
return nullptr;
- state = EvalAssumeCheckers[i](state, Cond, Assumption);
+ state = EvalAssumeChecker(state, Cond, Assumption);
}
return state;
}
-/// \brief Run checkers for evaluating a call.
+/// Run checkers for evaluating a call.
/// Only one checker will evaluate the call.
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const CallEvent &Call,
ExprEngine &Eng) {
const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
- for (ExplodedNodeSet::iterator
- NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
- ExplodedNode *Pred = *NI;
+ for (const auto Pred : Src) {
bool anyEvaluated = false;
ExplodedNodeSet checkDst;
NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
// Check if any of the EvalCall callbacks can evaluate the call.
- for (std::vector<EvalCallFunc>::iterator
- EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
- EI != EE; ++EI) {
+ for (const auto EvalCallChecker : EvalCallCheckers) {
ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
- const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K,
- Pred->getLocationContext(), EI->Checker);
+ const ProgramPoint &L =
+ ProgramPoint::getProgramPoint(CE, K, Pred->getLocationContext(),
+ EvalCallChecker.Checker);
bool evaluated = false;
{ // CheckerContext generates transitions(populates checkDest) on
// destruction, so introduce the scope to make sure it gets properly
// populated.
CheckerContext C(B, Eng, Pred, L);
- evaluated = (*EI)(CE, C);
+ evaluated = EvalCallChecker(CE, C);
}
assert(!(evaluated && anyEvaluated)
&& "There are more than one checkers evaluating the call");
@@ -621,21 +681,20 @@ void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
}
}
-/// \brief Run checkers for the entire Translation Unit.
+/// Run checkers for the entire Translation Unit.
void CheckerManager::runCheckersOnEndOfTranslationUnit(
const TranslationUnitDecl *TU,
AnalysisManager &mgr,
BugReporter &BR) {
- for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
- EndOfTranslationUnitCheckers[i](TU, mgr, BR);
+ for (const auto EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
+ EndOfTranslationUnitChecker(TU, mgr, BR);
}
void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
ProgramStateRef State,
const char *NL, const char *Sep) {
- for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
- I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
- I->second->printState(Out, State, NL, Sep);
+ for (const auto &CheckerTag : CheckerTags)
+ CheckerTag.second->printState(Out, State, NL, Sep);
}
//===----------------------------------------------------------------------===//
@@ -661,6 +720,7 @@ void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
StmtCheckers.push_back(info);
}
+
void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
HandlesStmtFunc isForStmtFn) {
StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
@@ -711,6 +771,10 @@ void CheckerManager::_registerForBranchCondition(
BranchConditionCheckers.push_back(checkfn);
}
+void CheckerManager::_registerForNewAllocator(CheckNewAllocatorFunc checkfn) {
+ NewAllocatorCheckers.push_back(checkfn);
+}
+
void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
LiveSymbolsCheckers.push_back(checkfn);
}
@@ -760,15 +824,13 @@ CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
// Find the checkers that should run for this Stmt and cache them.
CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
- for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
- StmtCheckerInfo &Info = StmtCheckers[i];
+ for (const auto &Info : StmtCheckers)
if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
Checkers.push_back(Info.CheckFn);
- }
return Checkers;
}
CheckerManager::~CheckerManager() {
- for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
- CheckerDtors[i]();
+ for (const auto CheckerDtor : CheckerDtors)
+ CheckerDtor();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index c9cb189a5b72..645845ec2181 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -1,4 +1,4 @@
-//===--- CheckerRegistry.cpp - Maintains all available checkers -*- C++ -*-===//
+//===- CheckerRegistry.cpp - Maintains all available checkers -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,18 +9,26 @@
#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstddef>
+#include <tuple>
using namespace clang;
using namespace ento;
static const char PackageSeparator = '.';
-typedef llvm::SetVector<const CheckerRegistry::CheckerInfo *> CheckerInfoSet;
+using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>;
static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
const CheckerRegistry::CheckerInfo &b) {
@@ -50,8 +58,7 @@ static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
// Use a binary search to find the possible start of the package.
CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), "");
auto end = checkers.cend();
- CheckerRegistry::CheckerInfoList::const_iterator i =
- std::lower_bound(checkers.cbegin(), end, packageInfo, checkerNameLT);
+ auto i = std::lower_bound(checkers.cbegin(), end, packageInfo, checkerNameLT);
// If we didn't even find a possible package, give up.
if (i == end)
@@ -73,12 +80,11 @@ static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
size = packageSize->getValue();
// Step through all the checkers in the package.
- for (auto checkEnd = i+size; i != checkEnd; ++i) {
+ for (auto checkEnd = i+size; i != checkEnd; ++i)
if (opt.isEnabled())
collected.insert(&*i);
else
collected.remove(&*i);
- }
}
void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
@@ -97,42 +103,38 @@ void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
SmallVectorImpl<CheckerOptInfo> &opts) const {
// Sort checkers for efficient collection.
- std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+ llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
// Collect checkers enabled by the options.
CheckerInfoSet enabledCheckers;
- for (SmallVectorImpl<CheckerOptInfo>::iterator
- i = opts.begin(), e = opts.end(); i != e; ++i) {
- collectCheckers(Checkers, Packages, *i, enabledCheckers);
- }
+ for (auto &i : opts)
+ collectCheckers(Checkers, Packages, i, enabledCheckers);
// Initialize the CheckerManager with all enabled checkers.
- for (CheckerInfoSet::iterator
- i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) {
- checkerMgr.setCurrentCheckName(CheckName((*i)->FullName));
- (*i)->Initialize(checkerMgr);
+ for (const auto *i :enabledCheckers) {
+ checkerMgr.setCurrentCheckName(CheckName(i->FullName));
+ i->Initialize(checkerMgr);
}
}
void CheckerRegistry::validateCheckerOptions(const AnalyzerOptions &opts,
DiagnosticsEngine &diags) const {
- for (auto &config : opts.Config) {
+ for (const auto &config : opts.Config) {
size_t pos = config.getKey().find(':');
if (pos == StringRef::npos)
continue;
bool hasChecker = false;
StringRef checkerName = config.getKey().substr(0, pos);
- for (auto &checker : Checkers) {
+ for (const auto &checker : Checkers) {
if (checker.FullName.startswith(checkerName) &&
(checker.FullName.size() == pos || checker.FullName[pos] == '.')) {
hasChecker = true;
break;
}
}
- if (!hasChecker) {
+ if (!hasChecker)
diags.Report(diag::err_unknown_analyzer_checker) << checkerName;
- }
}
}
@@ -141,7 +143,7 @@ void CheckerRegistry::printHelp(raw_ostream &out,
// FIXME: Alphabetical sort puts 'experimental' in the middle.
// Would it be better to name it '~experimental' or something else
// that's ASCIIbetically last?
- std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+ llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
// FIXME: Print available packages.
@@ -149,28 +151,26 @@ void CheckerRegistry::printHelp(raw_ostream &out,
// Find the maximum option length.
size_t optionFieldWidth = 0;
- for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
- i != e; ++i) {
+ for (const auto &i : Checkers) {
// Limit the amount of padding we are willing to give up for alignment.
// Package.Name Description [Hidden]
- size_t nameLength = i->FullName.size();
+ size_t nameLength = i.FullName.size();
if (nameLength <= maxNameChars)
optionFieldWidth = std::max(optionFieldWidth, nameLength);
}
const size_t initialPad = 2;
- for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
- i != e; ++i) {
- out.indent(initialPad) << i->FullName;
+ for (const auto &i : Checkers) {
+ out.indent(initialPad) << i.FullName;
- int pad = optionFieldWidth - i->FullName.size();
+ int pad = optionFieldWidth - i.FullName.size();
// Break on long option names.
if (pad < 0) {
out << '\n';
pad = optionFieldWidth + initialPad;
}
- out.indent(pad + 2) << i->Desc;
+ out.indent(pad + 2) << i.Desc;
out << '\n';
}
@@ -178,19 +178,13 @@ void CheckerRegistry::printHelp(raw_ostream &out,
void CheckerRegistry::printList(
raw_ostream &out, SmallVectorImpl<CheckerOptInfo> &opts) const {
- std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+ llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
// Collect checkers enabled by the options.
CheckerInfoSet enabledCheckers;
- for (SmallVectorImpl<CheckerOptInfo>::iterator i = opts.begin(),
- e = opts.end();
- i != e; ++i) {
- collectCheckers(Checkers, Packages, *i, enabledCheckers);
- }
+ for (auto &i : opts)
+ collectCheckers(Checkers, Packages, i, enabledCheckers);
- for (CheckerInfoSet::const_iterator i = enabledCheckers.begin(),
- e = enabledCheckers.end();
- i != e; ++i) {
- out << (*i)->FullName << '\n';
- }
+ for (const auto *i : enabledCheckers)
+ out << i->FullName << '\n';
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
index 8de2b0e8d271..ef9c44c51be4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
@@ -1,4 +1,4 @@
-//== ConstraintManager.cpp - Constraints on symbolic values -----*- C++ -*--==//
+//===- ConstraintManager.cpp - Constraints on symbolic values. ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,12 +11,17 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/AST/Type.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
using namespace clang;
using namespace ento;
-ConstraintManager::~ConstraintManager() {}
+ConstraintManager::~ConstraintManager() = default;
static DefinedSVal getLocFromSymbol(const ProgramStateRef &State,
SymbolRef Sym) {
@@ -35,5 +40,5 @@ ConditionTruthVal ConstraintManager::checkNull(ProgramStateRef State,
return ConditionTruthVal(false);
if (!P.first && P.second)
return ConditionTruthVal(true);
- return ConditionTruthVal();
+ return {};
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index e2e9ddf5048e..c17b6aae37e2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -1,4 +1,4 @@
-//==- CoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
+//===- CoreEngine.cpp - Path-Sensitive Dataflow Engine --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,27 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <utility>
using namespace clang;
using namespace ento;
@@ -34,146 +50,42 @@ STATISTIC(NumPathsExplored,
"The # of paths explored by the analyzer.");
//===----------------------------------------------------------------------===//
-// Worklist classes for exploration of reachable states.
+// Core analysis engine.
//===----------------------------------------------------------------------===//
-WorkList::Visitor::~Visitor() {}
-
-namespace {
-class DFS : public WorkList {
- SmallVector<WorkListUnit,20> Stack;
-public:
- bool hasWork() const override {
- return !Stack.empty();
- }
-
- void enqueue(const WorkListUnit& U) override {
- Stack.push_back(U);
- }
-
- WorkListUnit dequeue() override {
- assert (!Stack.empty());
- const WorkListUnit& U = Stack.back();
- Stack.pop_back(); // This technically "invalidates" U, but we are fine.
- return U;
- }
-
- bool visitItemsInWorkList(Visitor &V) override {
- for (SmallVectorImpl<WorkListUnit>::iterator
- I = Stack.begin(), E = Stack.end(); I != E; ++I) {
- if (V.visit(*I))
- return true;
- }
- return false;
- }
-};
-
-class BFS : public WorkList {
- std::deque<WorkListUnit> Queue;
-public:
- bool hasWork() const override {
- return !Queue.empty();
- }
-
- void enqueue(const WorkListUnit& U) override {
- Queue.push_back(U);
- }
-
- WorkListUnit dequeue() override {
- WorkListUnit U = Queue.front();
- Queue.pop_front();
- return U;
- }
-
- bool visitItemsInWorkList(Visitor &V) override {
- for (std::deque<WorkListUnit>::iterator
- I = Queue.begin(), E = Queue.end(); I != E; ++I) {
- if (V.visit(*I))
- return true;
- }
- return false;
+static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts) {
+ switch (Opts.getExplorationStrategy()) {
+ case AnalyzerOptions::ExplorationStrategyKind::DFS:
+ return WorkList::makeDFS();
+ case AnalyzerOptions::ExplorationStrategyKind::BFS:
+ return WorkList::makeBFS();
+ case AnalyzerOptions::ExplorationStrategyKind::BFSBlockDFSContents:
+ return WorkList::makeBFSBlockDFSContents();
+ case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirst:
+ return WorkList::makeUnexploredFirst();
+ case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirstQueue:
+ return WorkList::makeUnexploredFirstPriorityQueue();
+ default:
+ llvm_unreachable("Unexpected case");
}
-};
-
-} // end anonymous namespace
-
-// Place the dstor for WorkList here because it contains virtual member
-// functions, and we the code for the dstor generated in one compilation unit.
-WorkList::~WorkList() {}
-
-WorkList *WorkList::makeDFS() { return new DFS(); }
-WorkList *WorkList::makeBFS() { return new BFS(); }
-
-namespace {
- class BFSBlockDFSContents : public WorkList {
- std::deque<WorkListUnit> Queue;
- SmallVector<WorkListUnit,20> Stack;
- public:
- bool hasWork() const override {
- return !Queue.empty() || !Stack.empty();
- }
-
- void enqueue(const WorkListUnit& U) override {
- if (U.getNode()->getLocation().getAs<BlockEntrance>())
- Queue.push_front(U);
- else
- Stack.push_back(U);
- }
-
- WorkListUnit dequeue() override {
- // Process all basic blocks to completion.
- if (!Stack.empty()) {
- const WorkListUnit& U = Stack.back();
- Stack.pop_back(); // This technically "invalidates" U, but we are fine.
- return U;
- }
-
- assert(!Queue.empty());
- // Don't use const reference. The subsequent pop_back() might make it
- // unsafe.
- WorkListUnit U = Queue.front();
- Queue.pop_front();
- return U;
- }
- bool visitItemsInWorkList(Visitor &V) override {
- for (SmallVectorImpl<WorkListUnit>::iterator
- I = Stack.begin(), E = Stack.end(); I != E; ++I) {
- if (V.visit(*I))
- return true;
- }
- for (std::deque<WorkListUnit>::iterator
- I = Queue.begin(), E = Queue.end(); I != E; ++I) {
- if (V.visit(*I))
- return true;
- }
- return false;
- }
-
- };
-} // end anonymous namespace
-
-WorkList* WorkList::makeBFSBlockDFSContents() {
- return new BFSBlockDFSContents();
}
-//===----------------------------------------------------------------------===//
-// Core analysis engine.
-//===----------------------------------------------------------------------===//
+CoreEngine::CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS,
+ AnalyzerOptions &Opts)
+ : SubEng(subengine), WList(generateWorkList(Opts)),
+ BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
ProgramStateRef InitState) {
-
if (G.num_roots() == 0) { // Initialize the analysis by constructing
// the root if none exists.
const CFGBlock *Entry = &(L->getCFG()->getEntry());
- assert (Entry->empty() &&
- "Entry block must be empty.");
+ assert(Entry->empty() && "Entry block must be empty.");
- assert (Entry->succ_size() == 1 &&
- "Entry block must have 1 successor.");
+ assert(Entry->succ_size() == 1 && "Entry block must have 1 successor.");
// Mark the entry block as visited.
FunctionSummaries->markVisitedBasicBlock(Entry->getBlockID(),
@@ -195,7 +107,7 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
bool IsNew;
ExplodedNode *Node = G.getNode(StartLoc, InitState, false, &IsNew);
- assert (IsNew);
+ assert(IsNew);
G.addRoot(Node);
NodeBuilderContext BuilderCtx(*this, StartLoc.getDst(), Node);
@@ -251,13 +163,12 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
break;
case ProgramPoint::BlockExitKind:
- assert (false && "BlockExit location never occur in forward analysis.");
+ assert(false && "BlockExit location never occur in forward analysis.");
break;
- case ProgramPoint::CallEnterKind: {
+ case ProgramPoint::CallEnterKind:
HandleCallEnter(Loc.castAs<CallEnter>(), Pred);
break;
- }
case ProgramPoint::CallExitBeginKind:
SubEng.processCallExit(Pred);
@@ -275,7 +186,8 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
Loc.getAs<PostInitializer>() ||
Loc.getAs<PostImplicitCall>() ||
Loc.getAs<CallExitEnd>() ||
- Loc.getAs<LoopExit>());
+ Loc.getAs<LoopExit>() ||
+ Loc.getAs<PostAllocatorCall>());
HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
break;
}
@@ -294,7 +206,6 @@ bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
}
void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
-
const CFGBlock *Blk = L.getDst();
NodeBuilderContext BuilderCtx(*this, Blk, Pred);
@@ -306,18 +217,14 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
// Check if we are entering the EXIT block.
if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
-
- assert (L.getLocationContext()->getCFG()->getExit().size() == 0
- && "EXIT block cannot contain Stmts.");
+ assert(L.getLocationContext()->getCFG()->getExit().empty() &&
+ "EXIT block cannot contain Stmts.");
// Get return statement..
const ReturnStmt *RS = nullptr;
if (!L.getSrc()->empty()) {
if (Optional<CFGStmt> LastStmt = L.getSrc()->back().getAs<CFGStmt>()) {
- if ((RS = dyn_cast<ReturnStmt>(LastStmt->getStmt()))) {
- if (!RS->getRetValue())
- RS = nullptr;
- }
+ RS = dyn_cast<ReturnStmt>(LastStmt->getStmt());
}
}
@@ -345,12 +252,11 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
ExplodedNode *Pred) {
-
// Increment the block counter.
const LocationContext *LC = Pred->getLocationContext();
unsigned BlockId = L.getBlock()->getBlockID();
BlockCounter Counter = WList->getBlockCounter();
- Counter = BCounterFactory.IncrementCount(Counter, LC->getCurrentStackFrame(),
+ Counter = BCounterFactory.IncrementCount(Counter, LC->getStackFrame(),
BlockId);
WList->setBlockCounter(Counter);
@@ -364,7 +270,6 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
}
void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
-
if (const Stmt *Term = B->getTerminator()) {
switch (Term->getStmtClass()) {
default:
@@ -397,7 +302,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
return;
- case Stmt::CXXTryStmtClass: {
+ case Stmt::CXXTryStmtClass:
// Generate a node for each of the successors.
// Our logic for EH analysis can certainly be improved.
for (CFGBlock::const_succ_iterator it = B->succ_begin(),
@@ -408,7 +313,6 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
}
}
return;
- }
case Stmt::DoStmtClass:
HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
@@ -433,7 +337,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
case Stmt::IndirectGotoStmtClass: {
// Only 1 successor: the indirect goto dispatch block.
- assert (B->succ_size() == 1);
+ assert(B->succ_size() == 1);
IndirectGotoNodeBuilder
builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
@@ -443,7 +347,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
return;
}
- case Stmt::ObjCForCollectionStmtClass: {
+ case Stmt::ObjCForCollectionStmtClass:
// In the case of ObjCForCollectionStmt, it appears twice in a CFG:
//
// (1) inside a basic block, which represents the binding of the
@@ -456,7 +360,6 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
// contain nil elements.
HandleBranch(Term, Term, B, Pred);
return;
- }
case Stmt::SwitchStmtClass: {
SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
@@ -472,8 +375,8 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
}
}
- assert (B->succ_size() == 1 &&
- "Blocks with no terminator should have at most 1 successor.");
+ assert(B->succ_size() == 1 &&
+ "Blocks with no terminator should have at most 1 successor.");
generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
Pred->State, Pred);
@@ -518,9 +421,8 @@ void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
enqueue(Dst);
}
-
void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
- ExplodedNode *Pred) {
+ ExplodedNode *Pred) {
assert(B);
assert(!B->empty());
@@ -537,14 +439,13 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
void CoreEngine::generateNode(const ProgramPoint &Loc,
ProgramStateRef State,
ExplodedNode *Pred) {
-
bool IsNew;
ExplodedNode *Node = G.getNode(Loc, State, false, &IsNew);
if (Pred)
Node->addPredecessor(Pred, G); // Link 'Node' with its predecessor.
else {
- assert (IsNew);
+ assert(IsNew);
G.addRoot(Node); // 'Node' has no predecessor. Make it a root.
}
@@ -555,7 +456,7 @@ void CoreEngine::generateNode(const ProgramPoint &Loc,
void CoreEngine::enqueueStmtNode(ExplodedNode *N,
const CFGBlock *Block, unsigned Idx) {
assert(Block);
- assert (!N->isSink());
+ assert(!N->isSink());
// Check if this node entered a callee.
if (N->getLocation().getAs<CallEnter>()) {
@@ -605,8 +506,7 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N,
const ReturnStmt *RS) {
// Create a CallExitBegin node and enqueue it.
- const StackFrameContext *LocCtx
- = cast<StackFrameContext>(N->getLocationContext());
+ const auto *LocCtx = cast<StackFrameContext>(N->getLocationContext());
// Use the callee location context.
CallExitBegin Loc(LocCtx, RS);
@@ -617,40 +517,33 @@ ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N,
return isNew ? Node : nullptr;
}
-
void CoreEngine::enqueue(ExplodedNodeSet &Set) {
- for (ExplodedNodeSet::iterator I = Set.begin(),
- E = Set.end(); I != E; ++I) {
- WList->enqueue(*I);
- }
+ for (const auto I : Set)
+ WList->enqueue(I);
}
void CoreEngine::enqueue(ExplodedNodeSet &Set,
const CFGBlock *Block, unsigned Idx) {
- for (ExplodedNodeSet::iterator I = Set.begin(),
- E = Set.end(); I != E; ++I) {
- enqueueStmtNode(*I, Block, Idx);
- }
+ for (const auto I : Set)
+ enqueueStmtNode(I, Block, Idx);
}
void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS) {
- for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
- ExplodedNode *N = *I;
+ for (auto I : Set) {
// If we are in an inlined call, generate CallExitBegin node.
- if (N->getLocationContext()->getParent()) {
- N = generateCallExitBeginNode(N, RS);
- if (N)
- WList->enqueue(N);
+ if (I->getLocationContext()->getParent()) {
+ I = generateCallExitBeginNode(I, RS);
+ if (I)
+ WList->enqueue(I);
} else {
// TODO: We should run remove dead bindings here.
- G.addEndOfPath(N);
+ G.addEndOfPath(I);
NumPathsExplored++;
}
}
}
-
-void NodeBuilder::anchor() { }
+void NodeBuilder::anchor() {}
ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
ProgramStateRef State,
@@ -671,16 +564,15 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
return N;
}
-void NodeBuilderWithSinks::anchor() { }
+void NodeBuilderWithSinks::anchor() {}
StmtNodeBuilder::~StmtNodeBuilder() {
if (EnclosingBldr)
- for (ExplodedNodeSet::iterator I = Frontier.begin(),
- E = Frontier.end(); I != E; ++I )
- EnclosingBldr->addNodes(*I);
+ for (const auto I : Frontier)
+ EnclosingBldr->addNodes(I);
}
-void BranchNodeBuilder::anchor() { }
+void BranchNodeBuilder::anchor() {}
ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
bool branch,
@@ -714,11 +606,9 @@ IndirectGotoNodeBuilder::generateNode(const iterator &I,
return Succ;
}
-
ExplodedNode*
SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
ProgramStateRef St) {
-
bool IsNew;
ExplodedNode *Succ =
Eng.G.getNode(BlockEdge(Src, I.getBlock(), Pred->getLocationContext()),
@@ -731,7 +621,6 @@ SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
return Succ;
}
-
ExplodedNode*
SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
bool IsSink) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
index a01ff36a8aae..530933916889 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
@@ -1,4 +1,4 @@
-//==- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------*- C++ -*-//
+//===- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,6 +14,13 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
namespace clang {
namespace ento {
@@ -28,15 +35,15 @@ DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
return *GDMType;
// Otherwise, fall back to what we know about the region.
- if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
+ if (const auto *TR = dyn_cast<TypedRegion>(Reg))
return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false);
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
+ if (const auto *SR = dyn_cast<SymbolicRegion>(Reg)) {
SymbolRef Sym = SR->getSymbol();
return DynamicTypeInfo(Sym->getType());
}
- return DynamicTypeInfo();
+ return {};
}
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
@@ -47,5 +54,28 @@ ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
return NewState;
}
+void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out,
+ const char *NL, const char *Sep) {
+ bool First = true;
+ for (const auto &I : State->get<DynamicTypeMap>()) {
+ if (First) {
+ Out << NL << "Dynamic types of regions:" << NL;
+ First = false;
+ }
+ const MemRegion *MR = I.first;
+ const DynamicTypeInfo &DTI = I.second;
+ Out << MR << " : ";
+ if (DTI.isValid()) {
+ Out << DTI.getType()->getPointeeType().getAsString();
+ if (DTI.canBeASubClass()) {
+ Out << " (or its subclass)";
+ }
+ } else {
+ Out << "Invalid type info";
+ }
+ Out << NL;
+ }
+}
+
} // namespace ento
} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
index c6acb9d1851c..eccaee292c40 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -1,4 +1,4 @@
-//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
+//===- Environment.cpp - Map from Stmt* to Locations/Values ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,12 +11,25 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Stmt.h"
#include "clang/Analysis/AnalysisDeclContext.h"
-#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
using namespace clang;
using namespace ento;
@@ -46,16 +59,16 @@ static const Expr *ignoreTransparentExprs(const Expr *E) {
}
static const Stmt *ignoreTransparentExprs(const Stmt *S) {
- if (const Expr *E = dyn_cast<Expr>(S))
+ if (const auto *E = dyn_cast<Expr>(S))
return ignoreTransparentExprs(E);
return S;
}
EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
- : std::pair<const Stmt *,
- const StackFrameContext *>(ignoreTransparentExprs(S),
- L ? L->getCurrentStackFrame()
- : nullptr) {}
+ : std::pair<const Stmt *,
+ const StackFrameContext *>(ignoreTransparentExprs(S),
+ L ? L->getStackFrame()
+ : nullptr) {}
SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
const SVal* X = ExprBindings.lookup(E);
@@ -95,7 +108,7 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();
case Stmt::ReturnStmtClass: {
- const ReturnStmt *RS = cast<ReturnStmt>(S);
+ const auto *RS = cast<ReturnStmt>(S);
if (const Expr *RE = RS->getRetValue())
return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
return UndefinedVal();
@@ -121,20 +134,25 @@ Environment EnvironmentManager::bindExpr(Environment Env,
}
namespace {
+
class MarkLiveCallback final : public SymbolVisitor {
SymbolReaper &SymReaper;
+
public:
MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
+
bool VisitSymbol(SymbolRef sym) override {
SymReaper.markLive(sym);
return true;
}
+
bool VisitMemRegion(const MemRegion *R) override {
SymReaper.markLive(R);
return true;
}
};
-} // end anonymous namespace
+
+} // namespace
// removeDeadBindings:
// - Remove subexpression bindings.
@@ -147,7 +165,6 @@ Environment
EnvironmentManager::removeDeadBindings(Environment Env,
SymbolReaper &SymReaper,
ProgramStateRef ST) {
-
// We construct a new Environment object entirely, as this is cheaper than
// individually removing all the subexpression bindings (which will greatly
// outnumber block-level expression bindings).
@@ -156,14 +173,13 @@ EnvironmentManager::removeDeadBindings(Environment Env,
MarkLiveCallback CB(SymReaper);
ScanReachableSymbols RSScaner(ST, CB);
- llvm::ImmutableMapRef<EnvironmentEntry,SVal>
+ llvm::ImmutableMapRef<EnvironmentEntry, SVal>
EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
F.getTreeFactory());
// Iterate over the block-expr bindings.
for (Environment::iterator I = Env.begin(), E = Env.end();
I != E; ++I) {
-
const EnvironmentEntry &BlkExpr = I.getKey();
const SVal &X = I.getData();
@@ -186,28 +202,41 @@ EnvironmentManager::removeDeadBindings(Environment Env,
}
void Environment::print(raw_ostream &Out, const char *NL,
- const char *Sep) const {
- bool isFirst = true;
+ const char *Sep, const LocationContext *WithLC) const {
+ if (ExprBindings.isEmpty())
+ return;
+
+ if (!WithLC) {
+ // Find the freshest location context.
+ llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts;
+ for (auto I : *this) {
+ const LocationContext *LC = I.first.getLocationContext();
+ if (FoundContexts.count(LC) == 0) {
+ // This context is fresher than all other contexts so far.
+ WithLC = LC;
+ for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent())
+ FoundContexts.insert(LCI);
+ }
+ }
+ }
- for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
- const EnvironmentEntry &En = I.getKey();
+ assert(WithLC);
- if (isFirst) {
- Out << NL << NL
- << "Expressions:"
- << NL;
- isFirst = false;
- } else {
- Out << NL;
- }
+ LangOptions LO; // FIXME.
+ PrintingPolicy PP(LO);
- const Stmt *S = En.getStmt();
- assert(S != nullptr && "Expected non-null Stmt");
+ Out << NL << NL << "Expressions by stack frame:" << NL;
+ WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
+ for (auto I : ExprBindings) {
+ if (I.first.getLocationContext() != LC)
+ continue;
- Out << " (" << (const void*) En.getLocationContext() << ','
- << (const void*) S << ") ";
- LangOptions LO; // FIXME.
- S->printPretty(Out, nullptr, PrintingPolicy(LO));
- Out << " : " << I.getData();
- }
+ const Stmt *S = I.first.getStmt();
+ assert(S != nullptr && "Expected non-null Stmt");
+
+ Out << "(" << (const void *)LC << ',' << (const void *)S << ") ";
+ S->printPretty(Out, nullptr, PP);
+ Out << " : " << I.second << NL;
+ }
+ });
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 3bc8e09333b9..ece103d9d09a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -1,4 +1,4 @@
-//=-- ExplodedGraph.cpp - Local, Path-Sens. "Exploded Graph" -*- C++ -*------=//
+//===- ExplodedGraph.cpp - Local, Path-Sens. "Exploded Graph" -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,13 +13,24 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/Stmt.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <memory>
using namespace clang;
using namespace ento;
@@ -29,7 +40,7 @@ using namespace ento;
//===----------------------------------------------------------------------===//
// An out of line virtual method to provide a home for the class vtable.
-ExplodedNode::Auditor::~Auditor() {}
+ExplodedNode::Auditor::~Auditor() = default;
#ifndef NDEBUG
static ExplodedNode::Auditor* NodeAuditor = nullptr;
@@ -45,10 +56,9 @@ void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
// Cleanup.
//===----------------------------------------------------------------------===//
-ExplodedGraph::ExplodedGraph()
- : NumNodes(0), ReclaimNodeInterval(0) {}
+ExplodedGraph::ExplodedGraph() = default;
-ExplodedGraph::~ExplodedGraph() {}
+ExplodedGraph::~ExplodedGraph() = default;
//===----------------------------------------------------------------------===//
// Node reclamation.
@@ -187,12 +197,9 @@ void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
return;
ReclaimCounter = ReclaimNodeInterval;
- for (NodeVector::iterator it = ChangedNodes.begin(), et = ChangedNodes.end();
- it != et; ++it) {
- ExplodedNode *node = *it;
+ for (const auto node : ChangedNodes)
if (shouldCollect(node))
collectNode(node);
- }
ChangedNodes.clear();
}
@@ -210,11 +217,11 @@ void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
// 2. The group is empty, in which case the storage value is null.
// 3. The group contains a single node.
// 4. The group contains more than one node.
-typedef BumpVector<ExplodedNode *> ExplodedNodeVector;
-typedef llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *> GroupStorage;
+using ExplodedNodeVector = BumpVector<ExplodedNode *>;
+using GroupStorage = llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *>;
void ExplodedNode::addPredecessor(ExplodedNode *V, ExplodedGraph &G) {
- assert (!V->isSink());
+ assert(!V->isSink());
Preds.addNode(V, G);
V->Succs.addNode(this, G);
#ifndef NDEBUG
@@ -346,25 +353,22 @@ std::unique_ptr<ExplodedGraph>
ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
InterExplodedGraphMap *ForwardMap,
InterExplodedGraphMap *InverseMap) const {
-
if (Nodes.empty())
return nullptr;
- typedef llvm::DenseSet<const ExplodedNode*> Pass1Ty;
+ using Pass1Ty = llvm::DenseSet<const ExplodedNode *>;
Pass1Ty Pass1;
- typedef InterExplodedGraphMap Pass2Ty;
+ using Pass2Ty = InterExplodedGraphMap;
InterExplodedGraphMap Pass2Scratch;
Pass2Ty &Pass2 = ForwardMap ? *ForwardMap : Pass2Scratch;
SmallVector<const ExplodedNode*, 10> WL1, WL2;
// ===- Pass 1 (reverse DFS) -===
- for (ArrayRef<const NodeTy *>::iterator I = Sinks.begin(), E = Sinks.end();
- I != E; ++I) {
- if (*I)
- WL1.push_back(*I);
- }
+ for (const auto Sink : Sinks)
+ if (Sink)
+ WL1.push_back(Sink);
// Process the first worklist until it is empty.
while (!WL1.empty()) {
@@ -445,4 +449,3 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
return G;
}
-
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 3be37e7ae301..2b4bdd754fdb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1,4 +1,4 @@
-//=-- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=
+//===- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,31 +15,75 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
-#include "clang/AST/CharUnits.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
-#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
-#include "clang/Basic/Builtins.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ConstructionContext.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#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/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DOTGraphTraits.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
-
-#ifndef NDEBUG
-#include "llvm/Support/GraphWriter.h"
-#endif
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
-using llvm::APSInt;
#define DEBUG_TYPE "ExprEngine"
@@ -54,14 +98,77 @@ STATISTIC(NumMaxBlockCountReachedInInlined,
STATISTIC(NumTimesRetriedWithoutInlining,
"The # of times we re-evaluated a call without inlining");
-typedef std::pair<const CXXBindTemporaryExpr *, const StackFrameContext *>
- CXXBindTemporaryContext;
-// Keeps track of whether CXXBindTemporaryExpr nodes have been evaluated.
-// The StackFrameContext assures that nested calls due to inlined recursive
-// functions do not interfere.
-REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedTemporariesSet,
- llvm::ImmutableSet<CXXBindTemporaryContext>)
+//===----------------------------------------------------------------------===//
+// Internal program state traits.
+//===----------------------------------------------------------------------===//
+
+// When modeling a C++ constructor, for a variety of reasons we need to track
+// the location of the object for the duration of its ConstructionContext.
+// ObjectsUnderConstruction maps statements within the construction context
+// to the object's location, so that on every such statement the location
+// could have been retrieved.
+
+/// ConstructedObjectKey is used for being able to find the path-sensitive
+/// memory region of a freshly constructed object while modeling the AST node
+/// that syntactically represents the object that is being constructed.
+/// Semantics of such nodes may sometimes require access to the region that's
+/// not otherwise present in the program state, or to the very fact that
+/// the construction context was present and contained references to these
+/// AST nodes.
+class ConstructedObjectKey {
+ typedef std::pair<ConstructionContextItem, const LocationContext *>
+ ConstructedObjectKeyImpl;
+
+ const ConstructedObjectKeyImpl Impl;
+
+ const void *getAnyASTNodePtr() const {
+ if (const Stmt *S = getItem().getStmtOrNull())
+ return S;
+ else
+ return getItem().getCXXCtorInitializer();
+ }
+
+public:
+ explicit ConstructedObjectKey(const ConstructionContextItem &Item,
+ const LocationContext *LC)
+ : Impl(Item, LC) {}
+
+ const ConstructionContextItem &getItem() const { return Impl.first; }
+ const LocationContext *getLocationContext() const { return Impl.second; }
+
+ void print(llvm::raw_ostream &OS, PrinterHelper *Helper, PrintingPolicy &PP) {
+ OS << '(' << getLocationContext() << ',' << getAnyASTNodePtr() << ','
+ << getItem().getKindAsString();
+ if (getItem().getKind() == ConstructionContextItem::ArgumentKind)
+ OS << " #" << getItem().getIndex();
+ OS << ") ";
+ if (const Stmt *S = getItem().getStmtOrNull()) {
+ S->printPretty(OS, Helper, PP);
+ } else {
+ const CXXCtorInitializer *I = getItem().getCXXCtorInitializer();
+ OS << I->getAnyMember()->getNameAsString();
+ }
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.Add(Impl.first);
+ ID.AddPointer(Impl.second);
+ }
+
+ bool operator==(const ConstructedObjectKey &RHS) const {
+ return Impl == RHS.Impl;
+ }
+
+ bool operator<(const ConstructedObjectKey &RHS) const {
+ return Impl < RHS.Impl;
+ }
+};
+
+typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
+ ObjectsUnderConstructionMap;
+REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
+ ObjectsUnderConstructionMap)
//===----------------------------------------------------------------------===//
// Engine construction and deletion.
@@ -69,25 +176,21 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedTemporariesSet,
static const char* TagProviderName = "ExprEngine";
-ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
+ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
+ AnalysisManager &mgr, bool gcEnabled,
SetOfConstDecls *VisitedCalleesIn,
FunctionSummariesTy *FS,
InliningModes HowToInlineIn)
- : AMgr(mgr),
- AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
- Engine(*this, FS),
- G(Engine.getGraph()),
- StateMgr(getContext(), mgr.getStoreManagerCreator(),
- mgr.getConstraintManagerCreator(), G.getAllocator(),
- this),
- SymMgr(StateMgr.getSymbolManager()),
- svalBuilder(StateMgr.getSValBuilder()),
- currStmtIdx(0), currBldrCtx(nullptr),
- ObjCNoRet(mgr.getASTContext()),
- ObjCGCEnabled(gcEnabled), BR(mgr, *this),
- VisitedCallees(VisitedCalleesIn),
- HowToInline(HowToInlineIn)
-{
+ : CTU(CTU), AMgr(mgr),
+ AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
+ Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
+ StateMgr(getContext(), mgr.getStoreManagerCreator(),
+ mgr.getConstraintManagerCreator(), G.getAllocator(),
+ this),
+ SymMgr(StateMgr.getSymbolManager()),
+ svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
+ ObjCGCEnabled(gcEnabled), BR(mgr, *this),
+ VisitedCallees(VisitedCalleesIn), HowToInline(HowToInlineIn) {
unsigned TrimInterval = mgr.options.getGraphTrimInterval();
if (TrimInterval != 0) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
@@ -111,8 +214,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
// FIXME: It would be nice if we had a more general mechanism to add
// such preconditions. Some day.
do {
-
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Precondition: the first argument of 'main' is an integer guaranteed
// to be > 0.
const IdentifierInfo *II = FD->getIdentifier();
@@ -121,7 +223,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
const ParmVarDecl *PD = FD->getParamDecl(0);
QualType T = PD->getType();
- const BuiltinType *BT = dyn_cast<BuiltinType>(T);
+ const auto *BT = dyn_cast<BuiltinType>(T);
if (!BT || !BT->isInteger())
break;
@@ -145,9 +247,9 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
}
break;
}
- while (0);
+ while (false);
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
// Precondition: 'self' is always non-null upon entry to an Objective-C
// method.
const ImplicitParamDecl *SelfD = MD->getSelfDecl();
@@ -161,12 +263,12 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
}
}
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
if (!MD->isStatic()) {
// Precondition: 'this' is always non-null upon entry to the
// top-level function. This is our starting assumption for
// analyzing an "open" program.
- const StackFrameContext *SFC = InitLoc->getCurrentStackFrame();
+ const StackFrameContext *SFC = InitLoc->getStackFrame();
if (SFC->getParent() == nullptr) {
loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
SVal V = state->getSVal(L);
@@ -237,17 +339,30 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
const Expr *Init = InitWithAdjustments->skipRValueSubobjectAdjustments(
CommaLHSs, Adjustments);
+ // Take the region for Init, i.e. for the whole object. If we do not remember
+ // the region in which the object originally was constructed, come up with
+ // a new temporary region out of thin air and copy the contents of the object
+ // (which are currently present in the Environment, because Init is an rvalue)
+ // into that region. This is not correct, but it is better than nothing.
const TypedValueRegion *TR = nullptr;
- if (const MaterializeTemporaryExpr *MT =
- dyn_cast<MaterializeTemporaryExpr>(Result)) {
- StorageDuration SD = MT->getStorageDuration();
- // If this object is bound to a reference with static storage duration, we
- // put it in a different region to prevent "address leakage" warnings.
- if (SD == SD_Static || SD == SD_Thread)
- TR = MRMgr.getCXXStaticTempObjectRegion(Init);
- }
- if (!TR)
+ if (const auto *MT = dyn_cast<MaterializeTemporaryExpr>(Result)) {
+ if (Optional<SVal> V = getObjectUnderConstruction(State, MT, LC)) {
+ State = finishObjectConstruction(State, MT, LC);
+ State = State->BindExpr(Result, LC, *V);
+ return State;
+ } else {
+ StorageDuration SD = MT->getStorageDuration();
+ // If this object is bound to a reference with static storage duration, we
+ // put it in a different region to prevent "address leakage" warnings.
+ if (SD == SD_Static || SD == SD_Thread) {
+ TR = MRMgr.getCXXStaticTempObjectRegion(Init);
+ } else {
+ TR = MRMgr.getCXXTempObjectRegion(Init, LC);
+ }
+ }
+ } else {
TR = MRMgr.getCXXTempObjectRegion(Init, LC);
+ }
SVal Reg = loc::MemRegionVal(TR);
SVal BaseReg = Reg;
@@ -264,7 +379,9 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
break;
case SubobjectAdjustment::MemberPointerAdjustment:
// FIXME: Unimplemented.
- State = State->bindDefault(Reg, UnknownVal(), LC);
+ State = State->invalidateRegions(Reg, InitWithAdjustments,
+ currBldrCtx->blockCount(), LC, true,
+ nullptr, nullptr, nullptr);
return State;
}
}
@@ -283,7 +400,8 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
currBldrCtx->blockCount());
State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
- // Then we'd need to take the value that certainly exists and bind it over.
+ // Then we'd need to take the value that certainly exists and bind it
+ // over.
if (InitValWithAdjustments.isUnknown()) {
// Try to recover some path sensitivity in case we couldn't
// compute the value.
@@ -308,6 +426,77 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
return State;
}
+ProgramStateRef
+ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC, SVal V) {
+ ConstructedObjectKey Key(Item, LC->getStackFrame());
+ // FIXME: Currently the state might already contain the marker due to
+ // incorrect handling of temporaries bound to default parameters.
+ assert(!State->get<ObjectsUnderConstruction>(Key) ||
+ Key.getItem().getKind() ==
+ ConstructionContextItem::TemporaryDestructorKind);
+ return State->set<ObjectsUnderConstruction>(Key, V);
+}
+
+Optional<SVal>
+ExprEngine::getObjectUnderConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key(Item, LC->getStackFrame());
+ return Optional<SVal>::create(State->get<ObjectsUnderConstruction>(Key));
+}
+
+ProgramStateRef
+ExprEngine::finishObjectConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key(Item, LC->getStackFrame());
+ assert(State->contains<ObjectsUnderConstruction>(Key));
+ return State->remove<ObjectsUnderConstruction>(Key);
+}
+
+ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
+ // FIXME: Currently the state might already contain the marker due to
+ // incorrect handling of temporaries bound to default parameters.
+ return State->set<ObjectsUnderConstruction>(Key, UnknownVal());
+}
+
+ProgramStateRef
+ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
+ assert(State->contains<ObjectsUnderConstruction>(Key));
+ return State->remove<ObjectsUnderConstruction>(Key);
+}
+
+bool ExprEngine::isDestructorElided(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
+ return State->contains<ObjectsUnderConstruction>(Key);
+}
+
+bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
+ const LocationContext *FromLC,
+ const LocationContext *ToLC) {
+ const LocationContext *LC = FromLC;
+ while (LC != ToLC) {
+ assert(LC && "ToLC must be a parent of FromLC!");
+ for (auto I : State->get<ObjectsUnderConstruction>())
+ if (I.first.getLocationContext() == LC)
+ return false;
+
+ LC = LC->getParent();
+ }
+ return true;
+}
+
+
//===----------------------------------------------------------------------===//
// Top-level transfer function logic (Dispatcher).
//===----------------------------------------------------------------------===//
@@ -331,8 +520,36 @@ ExprEngine::processRegionChanges(ProgramStateRef state,
LCtx, Call);
}
+static void printObjectsUnderConstructionForContext(raw_ostream &Out,
+ ProgramStateRef State,
+ const char *NL,
+ const char *Sep,
+ const LocationContext *LC) {
+ PrintingPolicy PP =
+ LC->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();
+ for (auto I : State->get<ObjectsUnderConstruction>()) {
+ ConstructedObjectKey Key = I.first;
+ SVal Value = I.second;
+ if (Key.getLocationContext() != LC)
+ continue;
+ Key.print(Out, nullptr, PP);
+ Out << " : " << Value << NL;
+ }
+}
+
void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) {
+ const char *NL, const char *Sep,
+ const LocationContext *LCtx) {
+ if (LCtx) {
+ if (!State->get<ObjectsUnderConstruction>().isEmpty()) {
+ Out << Sep << "Objects under construction:" << NL;
+
+ LCtx->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
+ printObjectsUnderConstructionForContext(Out, State, NL, Sep, LC);
+ });
+ }
+ }
+
getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
}
@@ -348,10 +565,12 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
switch (E.getKind()) {
case CFGElement::Statement:
- ProcessStmt(const_cast<Stmt*>(E.castAs<CFGStmt>().getStmt()), Pred);
+ case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
+ ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
return;
case CFGElement::Initializer:
- ProcessInitializer(E.castAs<CFGInitializer>().getInitializer(), Pred);
+ ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
return;
case CFGElement::NewAllocator:
ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),
@@ -368,15 +587,16 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
return;
case CFGElement::LifetimeEnds:
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
return;
}
}
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
- const CFGStmt S,
+ const Stmt *S,
const ExplodedNode *Pred,
const LocationContext *LC) {
-
// Are we never purging state values?
if (AMgr.options.AnalysisPurgeOpt == PurgeNone)
return false;
@@ -386,17 +606,17 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
return true;
// Is this on a non-expression?
- if (!isa<Expr>(S.getStmt()))
+ if (!isa<Expr>(S))
return true;
// Run before processing a call.
- if (CallEvent::isCallStmt(S.getStmt()))
+ if (CallEvent::isCallStmt(S))
return true;
// Is this an expression that is consumed by another expression? If so,
// postpone cleaning out the state.
ParentMap &PM = LC->getAnalysisDeclContext()->getParentMap();
- return !PM.isConsumedExpr(cast<Expr>(S.getStmt()));
+ return !PM.isConsumedExpr(cast<Expr>(S));
}
void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
@@ -426,9 +646,16 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
LC = LC->getParent();
}
- const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : nullptr;
+ const StackFrameContext *SFC = LC ? LC->getStackFrame() : nullptr;
SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
+ for (auto I : CleanedState->get<ObjectsUnderConstruction>()) {
+ if (SymbolRef Sym = I.second.getAsSymbol())
+ SymReaper.markLive(Sym);
+ if (const MemRegion *MR = I.second.getAsRegion())
+ SymReaper.markLive(MR);
+ }
+
getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
// Create a state in which dead bindings are removed from the environment
@@ -457,9 +684,8 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
// environment, the store, and the constraints cleaned up but have the
// user-supplied states as the predecessors.
StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
- for (ExplodedNodeSet::const_iterator
- I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) {
- ProgramStateRef CheckerState = (*I)->getState();
+ for (const auto I : CheckedSet) {
+ ProgramStateRef CheckerState = I->getState();
// The constraint manager has not been cleaned up yet, so clean up now.
CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
@@ -476,35 +702,34 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
// generate a transition to that state.
ProgramStateRef CleanedCheckerSt =
StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
- Bldr.generateNode(DiagnosticStmt, *I, CleanedCheckerSt, &cleanupTag, K);
+ Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, &cleanupTag, K);
}
}
}
-void ExprEngine::ProcessStmt(const CFGStmt S,
- ExplodedNode *Pred) {
+void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
// Reclaim any unnecessary nodes in the ExplodedGraph.
G.reclaimRecentlyAllocatedNodes();
- const Stmt *currStmt = S.getStmt();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
currStmt->getLocStart(),
"Error evaluating statement");
// Remove dead bindings and symbols.
ExplodedNodeSet CleanedStates;
- if (shouldRemoveDeadBindings(AMgr, S, Pred, Pred->getLocationContext())){
- removeDead(Pred, CleanedStates, currStmt, Pred->getLocationContext());
+ if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,
+ Pred->getLocationContext())) {
+ removeDead(Pred, CleanedStates, currStmt,
+ Pred->getLocationContext());
} else
CleanedStates.Add(Pred);
// Visit the statement.
ExplodedNodeSet Dst;
- for (ExplodedNodeSet::iterator I = CleanedStates.begin(),
- E = CleanedStates.end(); I != E; ++I) {
+ for (const auto I : CleanedStates) {
ExplodedNodeSet DstI;
// Visit the statement.
- Visit(currStmt, *I, DstI);
+ Visit(currStmt, I, DstI);
Dst.insert(DstI);
}
@@ -530,36 +755,38 @@ void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
-void ExprEngine::ProcessInitializer(const CFGInitializer Init,
+void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
ExplodedNode *Pred) {
- const CXXCtorInitializer *BMI = Init.getInitializer();
+ const CXXCtorInitializer *BMI = CFGInit.getInitializer();
+ const Expr *Init = BMI->getInit()->IgnoreImplicit();
+ const LocationContext *LC = Pred->getLocationContext();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
BMI->getSourceLocation(),
"Error evaluating initializer");
// We don't clean up dead bindings here.
- const StackFrameContext *stackFrame =
- cast<StackFrameContext>(Pred->getLocationContext());
- const CXXConstructorDecl *decl =
- cast<CXXConstructorDecl>(stackFrame->getDecl());
+ const auto *stackFrame = cast<StackFrameContext>(Pred->getLocationContext());
+ const auto *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
ProgramStateRef State = Pred->getState();
SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
- ExplodedNodeSet Tmp(Pred);
+ ExplodedNodeSet Tmp;
SVal FieldLoc;
// Evaluate the initializer, if necessary
if (BMI->isAnyMemberInitializer()) {
// Constructors build the object directly in the field,
// but non-objects must be copied in from the initializer.
- if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) {
- assert(BMI->getInit()->IgnoreImplicit() == CtorExpr);
- (void)CtorExpr;
+ if (getObjectUnderConstruction(State, BMI, LC)) {
// The field was directly constructed, so there is no need to bind.
+ // But we still need to stop tracking the object under construction.
+ State = finishObjectConstruction(State, BMI, LC);
+ NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
+ PostStore PS(Init, LC, /*Loc*/ nullptr, /*tag*/ nullptr);
+ Bldr.generateNode(PS, State, Pred);
} else {
- const Expr *Init = BMI->getInit()->IgnoreImplicit();
const ValueDecl *Field;
if (BMI->isIndirectMemberInitializer()) {
Field = BMI->getIndirectMember();
@@ -593,15 +820,12 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
InitVal = State->getSVal(BMI->getInit(), stackFrame);
}
- assert(Tmp.size() == 1 && "have not generated any new nodes yet");
- assert(*Tmp.begin() == Pred && "have not generated any new nodes yet");
- Tmp.clear();
-
PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
}
} else {
assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());
+ Tmp.insert(Pred);
// We already did all the work when visiting the CXXConstructExpr.
}
@@ -610,9 +834,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
ExplodedNodeSet Dst;
NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
- ExplodedNode *N = *I;
- Bldr.generateNode(PP, N->getState(), N);
+ for (const auto I : Tmp) {
+ ProgramStateRef State = I->getState();
+ Bldr.generateNode(PP, State, I);
}
// Enqueue the new nodes onto the work list.
@@ -688,8 +912,15 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
varType = cast<TypedValueRegion>(Region)->getValueType();
}
+ // FIXME: We need to run the same destructor on every element of the array.
+ // This workaround will just run the first destructor (which will still
+ // invalidate the entire array).
+ EvalCallOptions CallOpts;
+ Region = makeZeroElementRegion(state, loc::MemRegionVal(Region), varType,
+ CallOpts.IsArrayCtorOrDtor).getAsRegion();
+
VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(), /*IsBase=*/ false,
- Pred, Dst);
+ Pred, Dst, CallOpts);
}
void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
@@ -699,12 +930,12 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
const LocationContext *LCtx = Pred->getLocationContext();
const CXXDeleteExpr *DE = Dtor.getDeleteExpr();
const Stmt *Arg = DE->getArgument();
+ QualType DTy = DE->getDestroyedType();
SVal ArgVal = State->getSVal(Arg, LCtx);
// If the argument to delete is known to be a null value,
// don't run destructor.
if (State->isNull(ArgVal).isConstrainedTrue()) {
- QualType DTy = DE->getDestroyedType();
QualType BTy = getContext().getBaseElementType(DTy);
const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
const CXXDestructorDecl *Dtor = RD->getDestructor();
@@ -715,19 +946,30 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
return;
}
- VisitCXXDestructor(DE->getDestroyedType(),
- ArgVal.getAsRegion(),
- DE, /*IsBase=*/ false,
- Pred, Dst);
+ EvalCallOptions CallOpts;
+ const MemRegion *ArgR = ArgVal.getAsRegion();
+ if (DE->isArrayForm()) {
+ // FIXME: We need to run the same destructor on every element of the array.
+ // This workaround will just run the first destructor (which will still
+ // invalidate the entire array).
+ CallOpts.IsArrayCtorOrDtor = true;
+ // Yes, it may even be a multi-dimensional array.
+ while (const auto *AT = getContext().getAsArrayType(DTy))
+ DTy = AT->getElementType();
+ if (ArgR)
+ ArgR = getStoreManager().GetElementZeroRegion(cast<SubRegion>(ArgR), DTy);
+ }
+
+ VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
}
void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
const LocationContext *LCtx = Pred->getLocationContext();
- const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
+ const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
- LCtx->getCurrentStackFrame());
+ LCtx->getStackFrame());
SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
// Create the base object region.
@@ -737,51 +979,94 @@ void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
Base->isVirtual());
VisitCXXDestructor(BaseTy, BaseVal.castAs<loc::MemRegionVal>().getRegion(),
- CurDtor->getBody(), /*IsBase=*/ true, Pred, Dst);
+ CurDtor->getBody(), /*IsBase=*/ true, Pred, Dst, {});
}
void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
const FieldDecl *Member = D.getFieldDecl();
+ QualType T = Member->getType();
ProgramStateRef State = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
- const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
+ const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
Loc ThisVal = getSValBuilder().getCXXThis(CurDtor,
- LCtx->getCurrentStackFrame());
+ LCtx->getStackFrame());
SVal FieldVal =
State->getLValue(Member, State->getSVal(ThisVal).castAs<Loc>());
- VisitCXXDestructor(Member->getType(),
- FieldVal.castAs<loc::MemRegionVal>().getRegion(),
- CurDtor->getBody(), /*IsBase=*/false, Pred, Dst);
+ // FIXME: We need to run the same destructor on every element of the array.
+ // This workaround will just run the first destructor (which will still
+ // invalidate the entire array).
+ EvalCallOptions CallOpts;
+ FieldVal = makeZeroElementRegion(State, FieldVal, T,
+ CallOpts.IsArrayCtorOrDtor);
+
+ VisitCXXDestructor(T, FieldVal.castAs<loc::MemRegionVal>().getRegion(),
+ CurDtor->getBody(), /*IsBase=*/false, Pred, Dst, CallOpts);
}
void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
- ExplodedNodeSet CleanDtorState;
- StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
+ const CXXBindTemporaryExpr *BTE = D.getBindTemporaryExpr();
ProgramStateRef State = Pred->getState();
- if (State->contains<InitializedTemporariesSet>(
- std::make_pair(D.getBindTemporaryExpr(), Pred->getStackFrame()))) {
+ const LocationContext *LC = Pred->getLocationContext();
+ const MemRegion *MR = nullptr;
+
+ if (Optional<SVal> V =
+ getObjectUnderConstruction(State, D.getBindTemporaryExpr(),
+ Pred->getLocationContext())) {
// FIXME: Currently we insert temporary destructors for default parameters,
- // but we don't insert the constructors.
- State = State->remove<InitializedTemporariesSet>(
- std::make_pair(D.getBindTemporaryExpr(), Pred->getStackFrame()));
+ // but we don't insert the constructors, so the entry in
+ // ObjectsUnderConstruction may be missing.
+ State = finishObjectConstruction(State, D.getBindTemporaryExpr(),
+ Pred->getLocationContext());
+ MR = V->getAsRegion();
+ }
+
+ // If copy elision has occured, and the constructor corresponding to the
+ // destructor was elided, we need to skip the destructor as well.
+ if (isDestructorElided(State, BTE, LC)) {
+ State = cleanupElidedDestructor(State, BTE, LC);
+ NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ PostImplicitCall PP(D.getDestructorDecl(getContext()),
+ D.getBindTemporaryExpr()->getLocStart(),
+ Pred->getLocationContext());
+ Bldr.generateNode(PP, State, Pred);
+ return;
}
+
+ ExplodedNodeSet CleanDtorState;
+ StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
- QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
+ QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
// FIXME: Currently CleanDtorState can be empty here due to temporaries being
// bound to default parameters.
assert(CleanDtorState.size() <= 1);
ExplodedNode *CleanPred =
CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
- // FIXME: Inlining of temporary destructors is not supported yet anyway, so
- // we just put a NULL region for now. This will need to be changed later.
- VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
- /*IsBase=*/false, CleanPred, Dst);
+
+ EvalCallOptions CallOpts;
+ CallOpts.IsTemporaryCtorOrDtor = true;
+ if (!MR) {
+ CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
+
+ // If we have no MR, we still need to unwrap the array to avoid destroying
+ // the whole array at once. Regardless, we'd eventually need to model array
+ // destructors properly, element-by-element.
+ while (const ArrayType *AT = getContext().getAsArrayType(T)) {
+ T = AT->getElementType();
+ CallOpts.IsArrayCtorOrDtor = true;
+ }
+ } else {
+ // We'd eventually need to makeZeroElementRegion() trick here,
+ // but for now we don't have the respective construction contexts,
+ // so MR would always be null in this case. Do nothing for now.
+ }
+ VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),
+ /*IsBase=*/false, CleanPred, Dst, CallOpts);
}
void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
@@ -791,19 +1076,23 @@ void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
const CFGBlock *DstT,
const CFGBlock *DstF) {
BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
- if (Pred->getState()->contains<InitializedTemporariesSet>(
- std::make_pair(BTE, Pred->getStackFrame()))) {
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LC = Pred->getLocationContext();
+ if (getObjectUnderConstruction(State, BTE, LC)) {
TempDtorBuilder.markInfeasible(false);
- TempDtorBuilder.generateNode(Pred->getState(), true, Pred);
+ TempDtorBuilder.generateNode(State, true, Pred);
} else {
TempDtorBuilder.markInfeasible(true);
- TempDtorBuilder.generateNode(Pred->getState(), false, Pred);
+ TempDtorBuilder.generateNode(State, false, Pred);
}
}
void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
ExplodedNodeSet &PreVisit,
ExplodedNodeSet &Dst) {
+ // This is a fallback solution in case we didn't have a construction
+ // context when we were constructing the temporary. Otherwise the map should
+ // have been populated there.
if (!getAnalysisManager().options.includeTemporaryDtorsInCFG()) {
// In case we don't have temporary destructors in the CFG, do not mark
// the initialization - we would otherwise never clean it up.
@@ -813,34 +1102,39 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
for (ExplodedNode *Node : PreVisit) {
ProgramStateRef State = Node->getState();
-
- if (!State->contains<InitializedTemporariesSet>(
- std::make_pair(BTE, Node->getStackFrame()))) {
- // FIXME: Currently the state might already contain the marker due to
+ const LocationContext *LC = Node->getLocationContext();
+ if (!getObjectUnderConstruction(State, BTE, LC)) {
+ // FIXME: Currently the state might also already contain the marker due to
// incorrect handling of temporaries bound to default parameters; for
// those, we currently skip the CXXBindTemporaryExpr but rely on adding
// temporary destructor nodes.
- State = State->add<InitializedTemporariesSet>(
- std::make_pair(BTE, Node->getStackFrame()));
+ State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());
}
StmtBldr.generateNode(BTE, Node, State);
}
}
-namespace {
-class CollectReachableSymbolsCallback final : public SymbolVisitor {
- InvalidatedSymbols Symbols;
+ProgramStateRef ExprEngine::escapeValue(ProgramStateRef State, SVal V,
+ PointerEscapeKind K) const {
+ class CollectReachableSymbolsCallback final : public SymbolVisitor {
+ InvalidatedSymbols Symbols;
-public:
- explicit CollectReachableSymbolsCallback(ProgramStateRef State) {}
- const InvalidatedSymbols &getSymbols() const { return Symbols; }
+ public:
+ explicit CollectReachableSymbolsCallback(ProgramStateRef State) {}
- bool VisitSymbol(SymbolRef Sym) override {
- Symbols.insert(Sym);
- return true;
- }
-};
-} // end anonymous namespace
+ const InvalidatedSymbols &getSymbols() const { return Symbols; }
+
+ bool VisitSymbol(SymbolRef Sym) override {
+ Symbols.insert(Sym);
+ return true;
+ }
+ };
+
+ const CollectReachableSymbolsCallback &Scanner =
+ State->scanReachableSymbols<CollectReachableSymbolsCallback>(V);
+ return getCheckerManager().runCheckersForPointerEscape(
+ State, Scanner.getSymbols(), /*CallEvent*/ nullptr, K, nullptr);
+}
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) {
@@ -930,8 +1224,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
- case Stmt::CapturedStmtClass:
- {
+ case Stmt::CapturedStmtClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
break;
@@ -1026,6 +1319,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::AddrLabelExprClass:
case Stmt::AttributedStmtClass:
case Stmt::IntegerLiteralClass:
+ case Stmt::FixedPointLiteralClass:
case Stmt::CharacterLiteralClass:
case Stmt::ImplicitValueInitExprClass:
case Stmt::CXXScalarValueInitExprClass:
@@ -1060,16 +1354,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
const Expr *ArgE;
- if (const CXXDefaultArgExpr *DefE = dyn_cast<CXXDefaultArgExpr>(S))
+ if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
ArgE = DefE->getExpr();
- else if (const CXXDefaultInitExpr *DefE = dyn_cast<CXXDefaultInitExpr>(S))
+ else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
ArgE = DefE->getExpr();
else
llvm_unreachable("unknown constant wrapper kind");
bool IsTemporary = false;
- if (const MaterializeTemporaryExpr *MTE =
- dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
ArgE = MTE->GetTemporaryExpr();
IsTemporary = true;
}
@@ -1079,15 +1372,14 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ConstantVal = UnknownVal();
const LocationContext *LCtx = Pred->getLocationContext();
- for (ExplodedNodeSet::iterator I = PreVisit.begin(), E = PreVisit.end();
- I != E; ++I) {
- ProgramStateRef State = (*I)->getState();
+ for (const auto I : PreVisit) {
+ ProgramStateRef State = I->getState();
State = State->BindExpr(S, LCtx, *ConstantVal);
if (IsTemporary)
State = createTemporaryRegionIfNeeded(State, LCtx,
cast<Expr>(S),
cast<Expr>(S));
- Bldr2.generateNode(S, *I, State);
+ Bldr2.generateNode(S, I, State);
}
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
@@ -1108,12 +1400,10 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
- const Expr *Ex = cast<Expr>(S);
+ const auto *Ex = cast<Expr>(S);
QualType resultType = Ex->getType();
- for (ExplodedNodeSet::iterator it = preVisit.begin(), et = preVisit.end();
- it != et; ++it) {
- ExplodedNode *N = *it;
+ for (const auto N : preVisit) {
const LocationContext *LCtx = N->getLocationContext();
SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
resultType,
@@ -1127,17 +1417,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
->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);
+ State = escapeValue(State, Val, PSK_EscapeOther);
}
Bldr2.generateNode(S, N, State);
@@ -1184,7 +1465,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break;
case Stmt::BinaryOperatorClass: {
- const BinaryOperator* B = cast<BinaryOperator>(S);
+ const auto *B = cast<BinaryOperator>(S);
if (B->isLogicalOp()) {
Bldr.takeNodes(Pred);
VisitLogicalExpr(B, Pred, Dst);
@@ -1216,12 +1497,12 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
}
case Stmt::CXXOperatorCallExprClass: {
- const CXXOperatorCallExpr *OCE = cast<CXXOperatorCallExpr>(S);
+ const auto *OCE = cast<CXXOperatorCallExpr>(S);
// For instance method operators, make sure the 'this' argument has a
// valid region.
const Decl *Callee = OCE->getCalleeDecl();
- if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
if (MD->isInstance()) {
ProgramStateRef State = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
@@ -1239,34 +1520,38 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
// FALLTHROUGH
LLVM_FALLTHROUGH;
}
+
case Stmt::CallExprClass:
case Stmt::CXXMemberCallExprClass:
- case Stmt::UserDefinedLiteralClass: {
+ case Stmt::UserDefinedLiteralClass:
Bldr.takeNodes(Pred);
VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
- }
- case Stmt::CXXCatchStmtClass: {
+ case Stmt::CXXCatchStmtClass:
Bldr.takeNodes(Pred);
VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
- }
case Stmt::CXXTemporaryObjectExprClass:
- case Stmt::CXXConstructExprClass: {
+ case Stmt::CXXConstructExprClass:
Bldr.takeNodes(Pred);
VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
- }
case Stmt::CXXNewExprClass: {
Bldr.takeNodes(Pred);
+
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
ExplodedNodeSet PostVisit;
- VisitCXXNewExpr(cast<CXXNewExpr>(S), Pred, PostVisit);
+ for (const auto i : PreVisit)
+ VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
+
getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
Bldr.addNodes(Dst);
break;
@@ -1275,12 +1560,11 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXDeleteExprClass: {
Bldr.takeNodes(Pred);
ExplodedNodeSet PreVisit;
- const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
+ const auto *CDE = cast<CXXDeleteExpr>(S);
getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- for (ExplodedNodeSet::iterator i = PreVisit.begin(),
- e = PreVisit.end(); i != e ; ++i)
- VisitCXXDeleteExpr(CDE, *i, Dst);
+ for (const auto i : PreVisit)
+ VisitCXXDeleteExpr(CDE, i, Dst);
Bldr.addNodes(Dst);
break;
@@ -1290,7 +1574,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ChooseExprClass: { // __builtin_choose_expr
Bldr.takeNodes(Pred);
- const ChooseExpr *C = cast<ChooseExpr>(S);
+ const auto *C = cast<ChooseExpr>(S);
VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
Bldr.addNodes(Dst);
break;
@@ -1311,8 +1595,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: { // '?' operator
Bldr.takeNodes(Pred);
- const AbstractConditionalOperator *C
- = cast<AbstractConditionalOperator>(S);
+ const auto *C = cast<AbstractConditionalOperator>(S);
VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
Bldr.addNodes(Dst);
break;
@@ -1326,7 +1609,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::DeclRefExprClass: {
Bldr.takeNodes(Pred);
- const DeclRefExpr *DE = cast<DeclRefExpr>(S);
+ const auto *DE = cast<DeclRefExpr>(S);
VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
Bldr.addNodes(Dst);
break;
@@ -1347,7 +1630,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXFunctionalCastExprClass:
case Stmt::ObjCBridgedCastExprClass: {
Bldr.takeNodes(Pred);
- const CastExpr *C = cast<CastExpr>(S);
+ const auto *C = cast<CastExpr>(S);
ExplodedNodeSet dstExpr;
VisitCast(C, C->getSubExpr(), Pred, dstExpr);
@@ -1359,14 +1642,12 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Expr::MaterializeTemporaryExprClass: {
Bldr.takeNodes(Pred);
- const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(S);
+ const auto *MTE = cast<MaterializeTemporaryExpr>(S);
ExplodedNodeSet dstPrevisit;
getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
ExplodedNodeSet dstExpr;
- for (ExplodedNodeSet::iterator i = dstPrevisit.begin(),
- e = dstPrevisit.end(); i != e ; ++i) {
- CreateCXXTemporaryObject(MTE, *i, dstExpr);
- }
+ for (const auto i : dstPrevisit)
+ CreateCXXTemporaryObject(MTE, i, dstExpr);
getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
Bldr.addNodes(Dst);
break;
@@ -1421,11 +1702,19 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.addNodes(Dst);
break;
- case Stmt::OffsetOfExprClass:
+ case Stmt::OffsetOfExprClass: {
Bldr.takeNodes(Pred);
- VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+ ExplodedNodeSet PostVisit;
+ for (const auto Node : PreVisit)
+ VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
+
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
Bldr.addNodes(Dst);
break;
+ }
case Stmt::UnaryExprOrTypeTraitExprClass:
Bldr.takeNodes(Pred);
@@ -1435,7 +1724,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break;
case Stmt::StmtExprClass: {
- const StmtExpr *SE = cast<StmtExpr>(S);
+ const auto *SE = cast<StmtExpr>(S);
if (SE->getSubStmt()->body_empty()) {
// Empty statement expression.
@@ -1444,7 +1733,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break;
}
- if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
+ if (const auto *LastExpr =
+ dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
ProgramStateRef state = Pred->getState();
Bldr.generateNode(SE, Pred,
state->BindExpr(SE, Pred->getLocationContext(),
@@ -1456,7 +1746,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::UnaryOperatorClass: {
Bldr.takeNodes(Pred);
- const UnaryOperator *U = cast<UnaryOperator>(S);
+ const auto *U = cast<UnaryOperator>(S);
if (AMgr.options.eagerlyAssumeBinOpBifurcation && (U->getOpcode() == UO_LNot)) {
ExplodedNodeSet Tmp;
VisitUnaryOperator(U, Pred, Tmp);
@@ -1471,7 +1761,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::PseudoObjectExprClass: {
Bldr.takeNodes(Pred);
ProgramStateRef state = Pred->getState();
- const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
+ const auto *PE = cast<PseudoObjectExpr>(S);
if (const Expr *Result = PE->getResultExpr()) {
SVal V = state->getSVal(Result, Pred->getLocationContext());
Bldr.generateNode(S, Pred,
@@ -1490,8 +1780,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
const LocationContext *CalleeLC) {
- const StackFrameContext *CalleeSF = CalleeLC->getCurrentStackFrame();
- const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame();
+ const StackFrameContext *CalleeSF = CalleeLC->getStackFrame();
+ const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame();
assert(CalleeSF && CallerSF);
ExplodedNode *BeforeProcessingCall = nullptr;
const Stmt *CE = CalleeSF->getCallSite();
@@ -1503,7 +1793,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
N = N->pred_empty() ? nullptr : *(N->pred_begin());
// Skip the nodes corresponding to the inlined code.
- if (L.getLocationContext()->getCurrentStackFrame() != CallerSF)
+ if (L.getStackFrame() != CallerSF)
continue;
// We reached the caller. Find the node right before we started
// processing the call.
@@ -1602,10 +1892,10 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
// Check if we stopped at the top level function or not.
// Root node should have the location context of the top most function.
const LocationContext *CalleeLC = Pred->getLocation().getLocationContext();
- const LocationContext *CalleeSF = CalleeLC->getCurrentStackFrame();
+ const LocationContext *CalleeSF = CalleeLC->getStackFrame();
const LocationContext *RootLC =
(*G.roots_begin())->getLocation().getLocationContext();
- if (RootLC->getCurrentStackFrame() != CalleeSF) {
+ if (RootLC->getStackFrame() != CalleeSF) {
Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
// Re-run the call evaluation without inlining it, by storing the
@@ -1639,14 +1929,14 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
const LocationContext *LCtx,
ASTContext &Ctx) {
- const Expr *Ex = dyn_cast<Expr>(Condition);
+ const auto *Ex = dyn_cast<Expr>(Condition);
if (!Ex)
return UnknownVal();
uint64_t bits = 0;
bool bitsInit = false;
- while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+ while (const auto *CE = dyn_cast<CastExpr>(Ex)) {
QualType T = CE->getType();
if (!T->isIntegralOrEnumerationType())
@@ -1674,7 +1964,7 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
#ifndef NDEBUG
static const Stmt *getRightmostLeaf(const Stmt *Condition) {
while (Condition) {
- const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
+ const auto *BO = dyn_cast<BinaryOperator>(Condition);
if (!BO || !BO->isLogicalOp()) {
return Condition;
}
@@ -1700,10 +1990,10 @@ static const Stmt *getRightmostLeaf(const Stmt *Condition) {
// space.
static const Stmt *ResolveCondition(const Stmt *Condition,
const CFGBlock *B) {
- if (const Expr *Ex = dyn_cast<Expr>(Condition))
+ if (const auto *Ex = dyn_cast<Expr>(Condition))
Condition = Ex->IgnoreParens();
- const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
+ const auto *BO = dyn_cast<BinaryOperator>(Condition);
if (!BO || !BO->isLogicalOp())
return Condition;
@@ -1751,7 +2041,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
return;
}
- if (const Expr *Ex = dyn_cast<Expr>(Condition))
+ if (const auto *Ex = dyn_cast<Expr>(Condition))
Condition = Ex->IgnoreParens();
Condition = ResolveCondition(Condition, BldCtx.getBlock());
@@ -1767,10 +2057,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
return;
BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
- for (NodeBuilder::iterator I = CheckersOutSet.begin(),
- E = CheckersOutSet.end(); E != I; ++I) {
- ExplodedNode *PredI = *I;
-
+ for (const auto PredI : CheckersOutSet) {
if (PredI->isSink())
continue;
@@ -1779,7 +2066,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
if (X.isUnknownOrUndef()) {
// Give it a chance to recover from unknown.
- if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
+ if (const auto *Ex = dyn_cast<Expr>(Condition)) {
if (Ex->getType()->isIntegralOrEnumerationType()) {
// Try to recover some path-sensitivity. Right now casts of symbolic
// integers that promote their values are currently not tracked well.
@@ -1836,13 +2123,13 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
void ExprEngine::processStaticInitializer(const DeclStmt *DS,
NodeBuilderContext &BuilderCtx,
ExplodedNode *Pred,
- clang::ento::ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Dst,
const CFGBlock *DstT,
const CFGBlock *DstF) {
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
currBldrCtx = &BuilderCtx;
- const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ const auto *VD = cast<VarDecl>(DS->getSingleDecl());
ProgramStateRef state = Pred->getState();
bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
BranchNodeBuilder builder(Pred, Dst, BuilderCtx, DstT, DstF);
@@ -1860,7 +2147,6 @@ void ExprEngine::processStaticInitializer(const DeclStmt *DS,
/// processIndirectGoto - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
-
ProgramStateRef state = builder.getState();
SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
@@ -1871,7 +2157,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
// (3) We have no clue about the label. Dispatch to all targets.
//
- typedef IndirectGotoNodeBuilder::iterator iterator;
+ using iterator = IndirectGotoNodeBuilder::iterator;
if (Optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
const LabelDecl *L = LV->getLabel();
@@ -1897,26 +2183,10 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
// This is really a catch-all. We don't support symbolics yet.
// FIXME: Implement dispatch for symbolic pointers.
- for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
+ for (iterator I = builder.begin(), E = builder.end(); I != E; ++I)
builder.generateNode(I, state);
}
-#if 0
-static bool stackFrameDoesNotContainInitializedTemporaries(ExplodedNode &Pred) {
- const StackFrameContext* Frame = Pred.getStackFrame();
- const llvm::ImmutableSet<CXXBindTemporaryContext> &Set =
- Pred.getState()->get<InitializedTemporariesSet>();
- return std::find_if(Set.begin(), Set.end(),
- [&](const CXXBindTemporaryContext &Ctx) {
- if (Ctx.second == Frame) {
- Ctx.first->dump();
- llvm::errs() << "\n";
- }
- return Ctx.second == Frame;
- }) == Set.end();
-}
-#endif
-
void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
@@ -1930,9 +2200,48 @@ void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred,
const ReturnStmt *RS) {
- // FIXME: Assert that stackFrameDoesNotContainInitializedTemporaries(*Pred)).
- // We currently cannot enable this assert, as lifetime extended temporaries
- // are not modelled correctly.
+ // FIXME: We currently cannot assert that temporaries are clear, because
+ // lifetime extended temporaries are not always modelled correctly. In some
+ // cases when we materialize the temporary, we do
+ // createTemporaryRegionIfNeeded(), and the region changes, and also the
+ // respective destructor becomes automatic from temporary. So for now clean up
+ // the state manually before asserting. Ideally, the code above the assertion
+ // should go away, but the assertion should remain.
+ {
+ ExplodedNodeSet CleanUpObjects;
+ NodeBuilder Bldr(Pred, CleanUpObjects, BC);
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *FromLC = Pred->getLocationContext();
+ const LocationContext *ToLC = FromLC->getStackFrame()->getParent();
+ const LocationContext *LC = FromLC;
+ while (LC != ToLC) {
+ assert(LC && "ToLC must be a parent of FromLC!");
+ for (auto I : State->get<ObjectsUnderConstruction>())
+ if (I.first.getLocationContext() == LC) {
+ // The comment above only pardons us for not cleaning up a
+ // temporary destructor. If any other statements are found here,
+ // it must be a separate problem.
+ assert(I.first.getItem().getKind() ==
+ ConstructionContextItem::TemporaryDestructorKind ||
+ I.first.getItem().getKind() ==
+ ConstructionContextItem::ElidedDestructorKind);
+ State = State->remove<ObjectsUnderConstruction>(I.first);
+ }
+ LC = LC->getParent();
+ }
+ if (State != Pred->getState()) {
+ Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);
+ if (!Pred) {
+ // The node with clean temporaries already exists. We might have reached
+ // it on a path on which we initialize different temporaries.
+ return;
+ }
+ }
+ }
+ assert(areAllObjectsFullyConstructed(Pred->getState(),
+ Pred->getLocationContext(),
+ Pred->getStackFrame()->getParent()));
+
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
StateMgr.EndPath(Pred->getState());
@@ -1943,12 +2252,10 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);
// Notify checkers.
- for (ExplodedNodeSet::iterator I = AfterRemovedDead.begin(),
- E = AfterRemovedDead.end(); I != E; ++I) {
- getCheckerManager().runCheckersForEndFunction(BC, Dst, *I, *this);
- }
+ for (const auto I : AfterRemovedDead)
+ getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS);
} else {
- getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this);
+ getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS);
}
Engine.enqueueEndOfFunction(Dst, RS);
@@ -1957,7 +2264,8 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
/// ProcessSwitch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
- typedef SwitchNodeBuilder::iterator iterator;
+ using iterator = SwitchNodeBuilder::iterator;
+
ProgramStateRef state = builder.getState();
const Expr *CondE = builder.getCondition();
SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
@@ -1986,7 +2294,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
// Evaluate the LHS of the case value.
llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());
assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
-
+
// Get the RHS of the case, if it exists.
llvm::APSInt V2;
if (const Expr *E = Case->getRHS())
@@ -2046,16 +2354,16 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
// C permits "extern void v", and if you cast the address to a valid type,
// you can even do things with it. We simply pretend
assert(Ex->isGLValue() || VD->getType()->isVoidType());
const LocationContext *LocCtxt = Pred->getLocationContext();
const Decl *D = LocCtxt->getDecl();
- const auto *MD = D ? dyn_cast<CXXMethodDecl>(D) : nullptr;
+ const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
- SVal V;
- bool IsReference;
+ Optional<std::pair<SVal, QualType>> VInfo;
+
if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
MD->getParent()->isLambda()) {
@@ -2064,25 +2372,23 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField;
CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
- const FieldDecl *FD = LambdaCaptureFields[VD];
- if (!FD) {
- // When a constant is captured, sometimes no corresponding field is
- // created in the lambda object.
- assert(VD->getType().isConstQualified());
- V = state->getLValue(VD, LocCtxt);
- IsReference = false;
- } else {
+
+ // Sema follows a sequence of complex rules to determine whether the
+ // variable should be captured.
+ if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
Loc CXXThis =
- svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame());
+ svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
SVal CXXThisVal = state->getSVal(CXXThis);
- V = state->getLValue(FD, CXXThisVal);
- IsReference = FD->getType()->isReferenceType();
+ VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
}
- } else {
- V = state->getLValue(VD, LocCtxt);
- IsReference = VD->getType()->isReferenceType();
}
+ if (!VInfo)
+ VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
+
+ SVal V = VInfo->first;
+ bool IsReference = VInfo->second->isReferenceType();
+
// For references, the 'lvalue' is the pointer address stored in the
// reference region.
if (IsReference) {
@@ -2096,13 +2402,13 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
ProgramPoint::PostLValueKind);
return;
}
- if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
+ if (const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
assert(!Ex->isGLValue());
SVal V = svalBuilder.makeIntVal(ED->getInitVal());
Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
return;
}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
SVal V = svalBuilder.getFunctionPointer(FD);
Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
@@ -2118,7 +2424,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
currBldrCtx->blockCount());
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
- ProgramPoint::PostLValueKind);
+ ProgramPoint::PostLValueKind);
+ return;
+ }
+ if (isa<BindingDecl>(D)) {
+ // FIXME: proper support for bound declarations.
+ // For now, let's just prevent crashing.
return;
}
@@ -2151,9 +2462,17 @@ void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
ProgramStateRef state = Node->getState();
if (IsGLValueLike) {
- SVal V = state->getLValue(A->getType(),
- state->getSVal(Idx, LCtx),
- state->getSVal(Base, LCtx));
+ QualType T = A->getType();
+
+ // One of the forbidden LValue types! We still need to have sensible
+ // symbolic locations to represent this stuff. Note that arithmetic on
+ // void pointers is a GCC extension.
+ if (T->isVoidType())
+ T = getContext().CharTy;
+
+ SVal V = state->getLValue(T,
+ state->getSVal(Idx, LCtx),
+ state->getSVal(Base, LCtx));
Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
} else if (IsVectorType) {
@@ -2171,7 +2490,6 @@ a vector and not a forbidden lvalue type");
/// VisitMemberExpr - Transfer function for member expressions.
void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
-
// FIXME: Prechecks eventually go in ::Visit().
ExplodedNodeSet CheckedSet;
getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
@@ -2182,30 +2500,26 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
// Handle static member variables and enum constants accessed via
// member syntax.
if (isa<VarDecl>(Member) || isa<EnumConstantDecl>(Member)) {
- ExplodedNodeSet Dst;
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
- I != E; ++I) {
- VisitCommonDeclRefExpr(M, Member, Pred, EvalSet);
- }
+ for (const auto I : CheckedSet)
+ VisitCommonDeclRefExpr(M, Member, I, EvalSet);
} else {
StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
ExplodedNodeSet Tmp;
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
- I != E; ++I) {
- ProgramStateRef state = (*I)->getState();
- const LocationContext *LCtx = (*I)->getLocationContext();
+ for (const auto I : CheckedSet) {
+ ProgramStateRef state = I->getState();
+ const LocationContext *LCtx = I->getLocationContext();
Expr *BaseExpr = M->getBase();
// Handle C++ method calls.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(Member)) {
if (MD->isInstance())
state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
SVal MDVal = svalBuilder.getFunctionPointer(MD);
state = state->BindExpr(M, LCtx, MDVal);
- Bldr.generateNode(M, *I, state);
+ Bldr.generateNode(M, I, state);
continue;
}
@@ -2213,7 +2527,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
SVal baseExprVal = state->getSVal(BaseExpr, LCtx);
- FieldDecl *field = cast<FieldDecl>(Member);
+ const auto *field = cast<FieldDecl>(Member);
SVal L = state->getLValue(field, baseExprVal);
if (M->isGLValue() || M->getType()->isArrayType()) {
@@ -2223,8 +2537,8 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
// pointers as soon as they are used.
if (!M->isGLValue()) {
assert(M->getType()->isArrayType());
- const ImplicitCastExpr *PE =
- dyn_cast<ImplicitCastExpr>((*I)->getParentMap().getParentIgnoreParens(M));
+ const auto *PE =
+ dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
}
@@ -2237,11 +2551,11 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
L = UnknownVal();
}
- Bldr.generateNode(M, *I, state->BindExpr(M, LCtx, L), nullptr,
+ Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,
ProgramPoint::PostLValueKind);
} else {
- Bldr.takeNodes(*I);
- evalLoad(Tmp, M, M, *I, state, L);
+ Bldr.takeNodes(I);
+ evalLoad(Tmp, M, M, I, state, L);
Bldr.addNodes(Tmp);
}
}
@@ -2261,10 +2575,9 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
ExplodedNodeSet AfterInvalidateSet;
StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
- for (ExplodedNodeSet::iterator I = AfterPreSet.begin(), E = AfterPreSet.end();
- I != E; ++I) {
- ProgramStateRef State = (*I)->getState();
- const LocationContext *LCtx = (*I)->getLocationContext();
+ for (const auto I : AfterPreSet) {
+ ProgramStateRef State = I->getState();
+ const LocationContext *LCtx = I->getLocationContext();
SmallVector<SVal, 8> ValuesToInvalidate;
for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {
@@ -2281,7 +2594,7 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
SVal ResultVal = UnknownVal();
State = State->BindExpr(AE, LCtx, ResultVal);
- Bldr.generateNode(AE, *I, State, nullptr,
+ Bldr.generateNode(AE, I, State, nullptr,
ProgramPoint::PostStmtKind);
}
@@ -2324,15 +2637,7 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
// Otherwise, find all symbols referenced by 'val' that we are tracking
// and stop tracking them.
- CollectReachableSymbolsCallback Scanner =
- State->scanReachableSymbols<CollectReachableSymbolsCallback>(Val);
- const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
- State = getCheckerManager().runCheckersForPointerEscape(State,
- EscapedSymbols,
- /*CallEvent*/ nullptr,
- PSK_EscapeOnBind,
- nullptr);
-
+ State = escapeValue(State, Val, PSK_EscapeOnBind);
return State;
}
@@ -2343,7 +2648,6 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) {
-
if (!Invalidated || Invalidated->empty())
return State;
@@ -2357,16 +2661,13 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
// If the symbols were invalidated by a call, we want to find out which ones
// were invalidated directly due to being arguments to the call.
InvalidatedSymbols SymbolsDirectlyInvalidated;
- for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
- E = ExplicitRegions.end(); I != E; ++I) {
- if (const SymbolicRegion *R = (*I)->StripCasts()->getAs<SymbolicRegion>())
+ for (const auto I : ExplicitRegions) {
+ if (const SymbolicRegion *R = I->StripCasts()->getAs<SymbolicRegion>())
SymbolsDirectlyInvalidated.insert(R->getSymbol());
}
InvalidatedSymbols SymbolsIndirectlyInvalidated;
- for (InvalidatedSymbols::const_iterator I=Invalidated->begin(),
- E = Invalidated->end(); I!=E; ++I) {
- SymbolRef sym = *I;
+ for (const auto &sym : *Invalidated) {
if (SymbolsDirectlyInvalidated.count(sym))
continue;
SymbolsIndirectlyInvalidated.insert(sym);
@@ -2390,7 +2691,6 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
ExplodedNode *Pred,
SVal location, SVal Val,
bool atDeclInit, const ProgramPoint *PP) {
-
const LocationContext *LC = Pred->getLocationContext();
PostStmt PS(StoreE, LC);
if (!PP)
@@ -2414,9 +2714,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
return;
}
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
- I!=E; ++I) {
- ExplodedNode *PredI = *I;
+ for (const auto PredI : CheckedSet) {
ProgramStateRef state = PredI->getState();
state = processPointerEscapedOnBind(state, location, Val, LC);
@@ -2465,8 +2763,8 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
if (location.isUndef())
return;
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- evalBind(Dst, StoreE, *NI, location, Val, false);
+ for (const auto I : Tmp)
+ evalBind(Dst, StoreE, I, location, Val, false);
}
void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
@@ -2476,46 +2774,8 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
ProgramStateRef state,
SVal location,
const ProgramPointTag *tag,
- QualType LoadTy)
-{
+ QualType LoadTy) {
assert(!location.getAs<NonLoc>() && "location cannot be a NonLoc.");
-
- // Are we loading from a region? This actually results in two loads; one
- // to fetch the address of the referenced value and one to fetch the
- // referenced value.
- if (const TypedValueRegion *TR =
- dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
-
- QualType ValTy = TR->getValueType();
- if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
- static SimpleProgramPointTag
- loadReferenceTag(TagProviderName, "Load Reference");
- ExplodedNodeSet Tmp;
- evalLoadCommon(Tmp, NodeEx, BoundEx, Pred, state,
- location, &loadReferenceTag,
- getContext().getPointerType(RT->getPointeeType()));
-
- // Perform the load from the referenced value.
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
- state = (*I)->getState();
- location = state->getSVal(BoundEx, (*I)->getLocationContext());
- evalLoadCommon(Dst, NodeEx, BoundEx, *I, state, location, tag, LoadTy);
- }
- return;
- }
- }
-
- evalLoadCommon(Dst, NodeEx, BoundEx, Pred, state, location, tag, LoadTy);
-}
-
-void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst,
- const Expr *NodeEx,
- const Expr *BoundEx,
- ExplodedNode *Pred,
- ProgramStateRef state,
- SVal location,
- const ProgramPointTag *tag,
- QualType LoadTy) {
assert(NodeEx);
assert(BoundEx);
// Evaluate the location (checks for bad dereferences).
@@ -2529,9 +2789,9 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst,
return;
// Proceed with the load.
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
- state = (*NI)->getState();
- const LocationContext *LCtx = (*NI)->getLocationContext();
+ for (const auto I : Tmp) {
+ state = I->getState();
+ const LocationContext *LCtx = I->getLocationContext();
SVal V = UnknownVal();
if (location.isValid()) {
@@ -2540,7 +2800,7 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst,
V = state->getSVal(location.castAs<Loc>(), LoadTy);
}
- Bldr.generateNode(NodeEx, *NI, state->BindExpr(BoundEx, LCtx, V), tag,
+ Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,
ProgramPoint::PostLoadKind);
}
}
@@ -2597,8 +2857,7 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
const Expr *Ex) {
StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);
- for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
- ExplodedNode *Pred = *I;
+ for (const auto Pred : Src) {
// Test if the previous node was as the same expression. This can happen
// when the expression fails to evaluate to anything meaningful and
// (as an optimization) we don't generate a node.
@@ -2648,7 +2907,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
for (const Expr *O : A->outputs()) {
SVal X = state->getSVal(O, Pred->getLocationContext());
- assert (!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.
+ assert(!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.
if (Optional<Loc> LV = X.getAs<Loc>())
state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext());
@@ -2672,16 +2931,15 @@ static ExprEngine* GraphPrintCheckerState;
static SourceManager* GraphPrintSourceManager;
namespace llvm {
-template<>
-struct DOTGraphTraits<ExplodedNode*> :
- public DefaultDOTGraphTraits {
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+template<>
+struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
+ DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
// FIXME: Since we do not cache error nodes in ExprEngine now, this does not
// work.
static std::string getNodeAttributes(const ExplodedNode *N, void*) {
- return "";
+ return {};
}
// De-duplicate some source location pretty-printing.
@@ -2694,15 +2952,8 @@ struct DOTGraphTraits<ExplodedNode*> :
<< "\\l";
}
}
- static void printLocation2(raw_ostream &Out, SourceLocation SLoc) {
- if (SLoc.isFileID() && GraphPrintSourceManager->isInMainFile(SLoc))
- Out << "line " << GraphPrintSourceManager->getExpansionLineNumber(SLoc);
- else
- SLoc.print(Out, *GraphPrintSourceManager);
- }
static std::string getNodeLabel(const ExplodedNode *N, void*){
-
std::string sbuf;
llvm::raw_string_ostream Out(sbuf);
@@ -2710,14 +2961,13 @@ struct DOTGraphTraits<ExplodedNode*> :
ProgramPoint Loc = N->getLocation();
switch (Loc.getKind()) {
- case ProgramPoint::BlockEntranceKind: {
+ case ProgramPoint::BlockEntranceKind:
Out << "Block Entrance: B"
<< Loc.castAs<BlockEntrance>().getBlock()->getBlockID();
break;
- }
case ProgramPoint::BlockExitKind:
- assert (false);
+ assert(false);
break;
case ProgramPoint::CallEnterKind:
@@ -2808,7 +3058,7 @@ struct DOTGraphTraits<ExplodedNode*> :
const Stmt *Label = E.getDst()->getLabel();
if (Label) {
- if (const CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
+ if (const auto *C = dyn_cast<CaseStmt>(Label)) {
Out << "\\lcase ";
LangOptions LO; // FIXME.
if (C->getLHS())
@@ -2822,7 +3072,7 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << ":";
}
else {
- assert (isa<DefaultStmt>(Label));
+ assert(isa<DefaultStmt>(Label));
Out << "\\ldefault:";
}
}
@@ -2863,6 +3113,8 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << "\\lPostStore\\l";
else if (Loc.getAs<PostLValue>())
Out << "\\lPostLValue\\l";
+ else if (Loc.getAs<PostAllocatorCall>())
+ Out << "\\lPostAllocatorCall\\l";
break;
}
@@ -2872,40 +3124,7 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << "\\|StateID: " << (const void*) state.get()
<< " NodeID: " << (const void*) N << "\\|";
- // Analysis stack backtrace.
- Out << "Location context stack (from current to outer):\\l";
- const LocationContext *LC = Loc.getLocationContext();
- unsigned Idx = 0;
- for (; LC; LC = LC->getParent(), ++Idx) {
- Out << Idx << ". (" << (const void *)LC << ") ";
- switch (LC->getKind()) {
- case LocationContext::StackFrame:
- if (const NamedDecl *D = dyn_cast<NamedDecl>(LC->getDecl()))
- Out << "Calling " << D->getQualifiedNameAsString();
- else
- Out << "Calling anonymous code";
- if (const Stmt *S = cast<StackFrameContext>(LC)->getCallSite()) {
- Out << " at ";
- printLocation2(Out, S->getLocStart());
- }
- break;
- case LocationContext::Block:
- Out << "Invoking block";
- if (const Decl *D = cast<BlockInvocationContext>(LC)->getBlockDecl()) {
- Out << " defined at ";
- printLocation2(Out, D->getLocStart());
- }
- break;
- case LocationContext::Scope:
- Out << "Entering scope";
- // FIXME: Add more info once ScopeContext is activated.
- break;
- }
- Out << "\\l";
- }
- Out << "\\l";
-
- state->printDOT(Out);
+ state->printDOT(Out, N->getLocationContext());
Out << "\\l";
@@ -2916,23 +3135,24 @@ struct DOTGraphTraits<ExplodedNode*> :
return Out.str();
}
};
-} // end llvm namespace
+
+} // namespace llvm
#endif
void ExprEngine::ViewGraph(bool trim) {
#ifndef NDEBUG
if (trim) {
- std::vector<const ExplodedNode*> Src;
+ std::vector<const ExplodedNode *> Src;
// Flush any outstanding reports to make sure we cover all the nodes.
// This does not cause them to get displayed.
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I)
- const_cast<BugType*>(*I)->FlushReports(BR);
+ for (const auto I : BR)
+ const_cast<BugType *>(I)->FlushReports(BR);
// Iterate through the reports and get their nodes.
for (BugReporter::EQClasses_iterator
EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
- ExplodedNode *N = const_cast<ExplodedNode*>(EI->begin()->getErrorNode());
+ const auto *N = const_cast<ExplodedNode *>(EI->begin()->getErrorNode());
if (N) Src.push_back(N);
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 3e7a50365f50..61b7a290e42a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -20,7 +20,7 @@ using namespace clang;
using namespace ento;
using llvm::APSInt;
-/// \brief Optionally conjure and return a symbol for offset when processing
+/// 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
@@ -257,13 +257,23 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx,
QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr,
ExplodedNode* Pred) {
+ if (T->isLValueReferenceType()) {
+ assert(!CastE->getType()->isLValueReferenceType());
+ ExTy = getContext().getLValueReferenceType(ExTy);
+ } else if (T->isRValueReferenceType()) {
+ assert(!CastE->getType()->isRValueReferenceType());
+ ExTy = getContext().getRValueReferenceType(ExTy);
+ }
// Delegate to SValBuilder to process.
- SVal V = state->getSVal(Ex, LCtx);
- V = svalBuilder.evalCast(V, T, ExTy);
+ SVal OrigV = state->getSVal(Ex, LCtx);
+ SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
// Negate the result if we're treating the boolean as a signed i1
if (CastE->getCastKind() == CK_BooleanToSignedIntegral)
V = evalMinus(V);
state = state->BindExpr(CastE, LCtx, V);
+ if (V.isUnknown() && !OrigV.isUnknown()) {
+ state = escapeValue(state, OrigV, PSK_EscapeOther);
+ }
Bldr.generateNode(CastE, Pred, state);
return state;
@@ -580,24 +590,12 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
SVal InitVal = state->getSVal(InitEx, LC);
assert(DS->isSingleDecl());
- if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) {
- assert(InitEx->IgnoreImplicit() == CtorExpr);
- (void)CtorExpr;
+ if (getObjectUnderConstruction(state, DS, LC)) {
+ state = finishObjectConstruction(state, DS, LC);
// We constructed the object directly in the variable.
// No need to bind anything.
B.generateNode(DS, UpdatedN, state);
} else {
- // We bound the temp obj region to the CXXConstructExpr. Now recover
- // the lazy compound value when the variable is not a reference.
- if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() &&
- !VD->getType()->isReferenceType()) {
- if (Optional<loc::MemRegionVal> M =
- InitVal.getAs<loc::MemRegionVal>()) {
- InitVal = state->getSVal(M->getRegion());
- assert(InitVal.getAs<nonloc::LazyCompoundVal>());
- }
- }
-
// Recover some path-sensitivity if a scalar value evaluated to
// UnknownVal.
if (InitVal.isUnknown()) {
@@ -686,7 +684,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
// known to be false, 1 if the value is known to be true and a new symbol
// when the assumption is unknown.
nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType()));
- X = evalBinOp(N->getState(), BO_NE,
+ X = evalBinOp(N->getState(), BO_NE,
svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()),
Zero, B->getType());
}
@@ -760,7 +758,11 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) {
ProgramPoint PP = N->getLocation();
if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) {
- assert(N->pred_size() == 1);
+ // If the state N has multiple predecessors P, it means that successors
+ // of P are all equivalent.
+ // In turn, that means that all nodes at P are equivalent in terms
+ // of observable behavior at N, and we can follow any of them.
+ // FIXME: a more robust solution which does not walk up the tree.
continue;
}
SrcBlock = PP.castAs<BlockEdge>().getSrc();
@@ -1062,6 +1064,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// constant value. If the UnaryOperator has location type, create the
// constant with int type and pointer width.
SVal RHS;
+ SVal Result;
if (U->getType()->isAnyPointerType())
RHS = svalBuilder.makeArrayIndex(1);
@@ -1070,7 +1073,14 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
else
RHS = UnknownVal();
- SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());
+ // The use of an operand of type bool with the ++ operators is deprecated
+ // but valid until C++17. And if the operand of the ++ operator is of type
+ // bool, it is set to true until C++17. Note that for '_Bool', it is also
+ // set to true when it encounters ++ operator.
+ if (U->getType()->isBooleanType() && U->isIncrementOp())
+ Result = svalBuilder.makeTruthVal(true, U->getType());
+ else
+ Result = evalBinOp(state, Op, V2, RHS, U->getType());
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown()){
@@ -1092,7 +1102,6 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
Constraint = svalBuilder.evalEQ(state, SymVal,
svalBuilder.makeZeroVal(U->getType()));
-
state = state->assume(Constraint, false);
assert(state);
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index dad93111966f..4f1766a813c6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/ParentMap.h"
@@ -41,19 +42,30 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
const CallEvent &Call) {
SVal ThisVal;
bool AlwaysReturnsLValue;
+ const CXXRecordDecl *ThisRD = nullptr;
if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
assert(Ctor->getDecl()->isTrivial());
assert(Ctor->getDecl()->isCopyOrMoveConstructor());
ThisVal = Ctor->getCXXThisVal();
+ ThisRD = Ctor->getDecl()->getParent();
AlwaysReturnsLValue = false;
} else {
assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial());
assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() ==
OO_Equal);
ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal();
+ ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent();
AlwaysReturnsLValue = true;
}
+ assert(ThisRD);
+ if (ThisRD->isEmpty()) {
+ // Do nothing for empty classes. Otherwise it'd retrieve an UnknownVal
+ // and bind it and RegionStore would think that the actual value
+ // in this region at this offset is unknown.
+ return;
+ }
+
const LocationContext *LCtx = Pred->getLocationContext();
ExplodedNodeSet Dst;
@@ -84,52 +96,50 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
}
-/// Returns a region representing the first element of a (possibly
-/// multi-dimensional) array.
-///
-/// On return, \p Ty will be set to the base type of the array.
-///
-/// If the type is not an array type at all, the original value is returned.
-static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
- QualType &Ty) {
+SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
+ QualType &Ty, bool &IsArray) {
SValBuilder &SVB = State->getStateManager().getSValBuilder();
ASTContext &Ctx = SVB.getContext();
while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
Ty = AT->getElementType();
LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
+ IsArray = true;
}
return LValue;
}
+std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
+ const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
+ const ConstructionContext *CC, EvalCallOptions &CallOpts) {
+ MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
-const MemRegion *
-ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
- ExplodedNode *Pred) {
- const LocationContext *LCtx = Pred->getLocationContext();
- ProgramStateRef State = Pred->getState();
-
- // See if we're constructing an existing region by looking at the next
- // element in the CFG.
-
- if (auto Elem = findElementDirectlyInitializedByCurrentConstructor()) {
- if (Optional<CFGStmt> StmtElem = Elem->getAs<CFGStmt>()) {
- auto *DS = cast<DeclStmt>(StmtElem->getStmt());
- if (const auto *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
- if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) {
- SVal LValue = State->getLValue(Var, LCtx);
- QualType Ty = Var->getType();
- LValue = makeZeroElementRegion(State, LValue, Ty);
- return LValue.getAsRegion();
- }
- }
- } else if (Optional<CFGInitializer> InitElem = Elem->getAs<CFGInitializer>()) {
- const CXXCtorInitializer *Init = InitElem->getInitializer();
+ // See if we're constructing an existing region by looking at the
+ // current construction context.
+ if (CC) {
+ switch (CC->getKind()) {
+ case ConstructionContext::CXX17ElidedCopyVariableKind:
+ case ConstructionContext::SimpleVariableKind: {
+ const auto *DSCC = cast<VariableConstructionContext>(CC);
+ const auto *DS = DSCC->getDeclStmt();
+ const auto *Var = cast<VarDecl>(DS->getSingleDecl());
+ SVal LValue = State->getLValue(Var, LCtx);
+ QualType Ty = Var->getType();
+ LValue =
+ makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor);
+ State =
+ addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue);
+ return std::make_pair(State, LValue);
+ }
+ case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
+ case ConstructionContext::SimpleConstructorInitializerKind: {
+ const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
+ const auto *Init = ICC->getCXXCtorInitializer();
assert(Init->isAnyMemberInitializer());
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr =
- getSValBuilder().getCXXThis(CurCtor, LCtx->getCurrentStackFrame());
+ getSValBuilder().getCXXThis(CurCtor, LCtx->getStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
const ValueDecl *Field;
@@ -143,92 +153,155 @@ ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
}
QualType Ty = Field->getType();
- FieldVal = makeZeroElementRegion(State, FieldVal, Ty);
- return FieldVal.getAsRegion();
+ FieldVal = makeZeroElementRegion(State, FieldVal, Ty,
+ CallOpts.IsArrayCtorOrDtor);
+ State = addObjectUnderConstruction(State, Init, LCtx, FieldVal);
+ return std::make_pair(State, FieldVal);
}
-
- // FIXME: This will eventually need to handle new-expressions as well.
- // Don't forget to update the pre-constructor initialization code in
- // ExprEngine::VisitCXXConstructExpr.
- }
- // If we couldn't find an existing region to construct into, assume we're
- // constructing a temporary.
- MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
- return MRMgr.getCXXTempObjectRegion(CE, LCtx);
-}
-
-/// Returns true if the initializer for \Elem can be a direct
-/// constructor.
-static bool canHaveDirectConstructor(CFGElement Elem){
- // DeclStmts and CXXCtorInitializers for fields can be directly constructed.
-
- if (Optional<CFGStmt> StmtElem = Elem.getAs<CFGStmt>()) {
- if (isa<DeclStmt>(StmtElem->getStmt())) {
- return true;
+ case ConstructionContext::NewAllocatedObjectKind: {
+ if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
+ const auto *NE = NECC->getCXXNewExpr();
+ SVal V = *getObjectUnderConstruction(State, NE, LCtx);
+ if (const SubRegion *MR =
+ dyn_cast_or_null<SubRegion>(V.getAsRegion())) {
+ if (NE->isArray()) {
+ // TODO: In fact, we need to call the constructor for every
+ // allocated element, not just the first one!
+ CallOpts.IsArrayCtorOrDtor = true;
+ return std::make_pair(
+ State, loc::MemRegionVal(getStoreManager().GetElementZeroRegion(
+ MR, NE->getType()->getPointeeType())));
+ }
+ return std::make_pair(State, V);
+ }
+ // TODO: Detect when the allocator returns a null pointer.
+ // Constructor shall not be called in this case.
+ }
+ break;
}
- }
-
- if (Elem.getKind() == CFGElement::Initializer) {
- return true;
- }
-
- return false;
-}
+ case ConstructionContext::SimpleReturnedValueKind:
+ case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
+ // The temporary is to be managed by the parent stack frame.
+ // So build it in the parent stack frame if we're not in the
+ // top frame of the analysis.
+ const StackFrameContext *SFC = LCtx->getStackFrame();
+ if (const LocationContext *CallerLCtx = SFC->getParent()) {
+ auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
+ .getAs<CFGCXXRecordTypedCall>();
+ if (!RTC) {
+ // We were unable to find the correct construction context for the
+ // call in the parent stack frame. This is equivalent to not being
+ // able to find construction context at all.
+ break;
+ }
+ return prepareForObjectConstruction(
+ cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
+ RTC->getConstructionContext(), CallOpts);
+ } else {
+ // We are on the top frame of the analysis.
+ // TODO: What exactly happens when we are? Does the temporary object
+ // live long enough in the region store in this case? Would checkers
+ // think that this object immediately goes out of scope?
+ CallOpts.IsTemporaryCtorOrDtor = true;
+ SVal V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
+ return std::make_pair(State, V);
+ }
+ llvm_unreachable("Unhandled return value construction context!");
+ }
+ case ConstructionContext::ElidedTemporaryObjectKind: {
+ assert(AMgr.getAnalyzerOptions().shouldElideConstructors());
+ const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
+ const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
+ const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
+ const CXXConstructExpr *CE = TCC->getConstructorAfterElision();
+
+ // Support pre-C++17 copy elision. We'll have the elidable copy
+ // constructor in the AST and in the CFG, but we'll skip it
+ // and construct directly into the final object. This call
+ // also sets the CallOpts flags for us.
+ SVal V;
+ // If the elided copy/move constructor is not supported, there's still
+ // benefit in trying to model the non-elided constructor.
+ // Stash our state before trying to elide, as it'll get overwritten.
+ ProgramStateRef PreElideState = State;
+ EvalCallOptions PreElideCallOpts = CallOpts;
+
+ std::tie(State, V) = prepareForObjectConstruction(
+ CE, State, LCtx, TCC->getConstructionContextAfterElision(), CallOpts);
+
+ // FIXME: This definition of "copy elision has not failed" is unreliable.
+ // It doesn't indicate that the constructor will actually be inlined
+ // later; it is still up to evalCall() to decide.
+ if (!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) {
+ // Remember that we've elided the constructor.
+ State = addObjectUnderConstruction(State, CE, LCtx, V);
+
+ // Remember that we've elided the destructor.
+ if (BTE)
+ State = elideDestructor(State, BTE, LCtx);
+
+ // Instead of materialization, shamelessly return
+ // the final object destination.
+ if (MTE)
+ State = addObjectUnderConstruction(State, MTE, LCtx, V);
+
+ return std::make_pair(State, V);
+ } else {
+ // Copy elision failed. Revert the changes and proceed as if we have
+ // a simple temporary.
+ State = PreElideState;
+ CallOpts = PreElideCallOpts;
+ }
+ LLVM_FALLTHROUGH;
+ }
+ case ConstructionContext::SimpleTemporaryObjectKind: {
+ const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
+ const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
+ const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
+ SVal V = UnknownVal();
+
+ if (MTE) {
+ if (const ValueDecl *VD = MTE->getExtendingDecl()) {
+ assert(MTE->getStorageDuration() != SD_FullExpression);
+ if (!VD->getType()->isReferenceType()) {
+ // We're lifetime-extended by a surrounding aggregate.
+ // Automatic destructors aren't quite working in this case
+ // on the CFG side. We should warn the caller about that.
+ // FIXME: Is there a better way to retrieve this information from
+ // the MaterializeTemporaryExpr?
+ CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true;
+ }
+ }
-Optional<CFGElement>
-ExprEngine::findElementDirectlyInitializedByCurrentConstructor() {
- const NodeBuilderContext &CurrBldrCtx = getBuilderContext();
- // See if we're constructing an existing region by looking at the next
- // element in the CFG.
- const CFGBlock *B = CurrBldrCtx.getBlock();
- assert(isa<CXXConstructExpr>(((*B)[currStmtIdx]).castAs<CFGStmt>().getStmt()));
- unsigned int NextStmtIdx = currStmtIdx + 1;
- if (NextStmtIdx >= B->size())
- return None;
-
- CFGElement Next = (*B)[NextStmtIdx];
-
- // Is this a destructor? If so, we might be in the middle of an assignment
- // to a local or member: look ahead one more element to see what we find.
- while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
- ++NextStmtIdx;
- Next = (*B)[NextStmtIdx];
- }
+ if (MTE->getStorageDuration() == SD_Static ||
+ MTE->getStorageDuration() == SD_Thread)
+ V = loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E));
+ }
- if (canHaveDirectConstructor(Next))
- return Next;
+ if (V.isUnknown())
+ V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
- return None;
-}
+ if (BTE)
+ State = addObjectUnderConstruction(State, BTE, LCtx, V);
-const CXXConstructExpr *
-ExprEngine::findDirectConstructorForCurrentCFGElement() {
- // Go backward in the CFG to see if the previous element (ignoring
- // destructors) was a CXXConstructExpr. If so, that constructor
- // was constructed directly into an existing region.
- // This process is essentially the inverse of that performed in
- // findElementDirectlyInitializedByCurrentConstructor().
- if (currStmtIdx == 0)
- return nullptr;
-
- const CFGBlock *B = getBuilderContext().getBlock();
- assert(canHaveDirectConstructor((*B)[currStmtIdx]));
-
- unsigned int PreviousStmtIdx = currStmtIdx - 1;
- CFGElement Previous = (*B)[PreviousStmtIdx];
-
- while (Previous.getAs<CFGImplicitDtor>() && PreviousStmtIdx > 0) {
- --PreviousStmtIdx;
- Previous = (*B)[PreviousStmtIdx];
- }
+ if (MTE)
+ State = addObjectUnderConstruction(State, MTE, LCtx, V);
- if (Optional<CFGStmt> PrevStmtElem = Previous.getAs<CFGStmt>()) {
- if (auto *CtorExpr = dyn_cast<CXXConstructExpr>(PrevStmtElem->getStmt())) {
- return CtorExpr;
+ CallOpts.IsTemporaryCtorOrDtor = true;
+ return std::make_pair(State, V);
+ }
+ case ConstructionContext::ArgumentKind: {
+ // Function argument constructors. Not implemented yet.
+ break;
+ }
}
}
-
- return nullptr;
+ // If we couldn't find an existing region to construct into, assume we're
+ // constructing a temporary. Notify the caller of our failure.
+ CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
+ return std::make_pair(
+ State, loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)));
}
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
@@ -237,21 +310,41 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
- const MemRegion *Target = nullptr;
+ SVal Target = UnknownVal();
+
+ if (Optional<SVal> ElidedTarget =
+ getObjectUnderConstruction(State, CE, LCtx)) {
+ // We've previously modeled an elidable constructor by pretending that it in
+ // fact constructs into the correct target. This constructor can therefore
+ // be skipped.
+ Target = *ElidedTarget;
+ StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
+ State = finishObjectConstruction(State, CE, LCtx);
+ if (auto L = Target.getAs<Loc>())
+ State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));
+ Bldr.generateNode(CE, Pred, State);
+ return;
+ }
// FIXME: Handle arrays, which run the same constructor for every element.
// For now, we just run the first constructor (which should still invalidate
// the entire array).
+ EvalCallOptions CallOpts;
+ auto C = getCurrentCFGElement().getAs<CFGConstructor>();
+ assert(C || getCurrentCFGElement().getAs<CFGStmt>());
+ const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
+
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
- Target = getRegionForConstructedObject(CE, Pred);
+ std::tie(State, Target) =
+ prepareForObjectConstruction(CE, State, LCtx, CC, CallOpts);
break;
}
case CXXConstructExpr::CK_VirtualBase:
// Make sure we are not calling virtual base class initializers twice.
// Only the most-derived object should initialize virtual base classes.
- if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) {
+ if (const Stmt *Outer = LCtx->getStackFrame()->getCallSite()) {
const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer);
if (OuterCtor) {
switch (OuterCtor->getConstructionKind()) {
@@ -281,48 +374,59 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// otherwise always available during construction.
if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) {
MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
- Target = MRMgr.getCXXTempObjectRegion(CE, LCtx);
+ Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(CE, LCtx));
+ CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
break;
}
// FALLTHROUGH
case CXXConstructExpr::CK_Delegating: {
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
- LCtx->getCurrentStackFrame());
+ LCtx->getStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
- Target = ThisVal.getAsRegion();
+ Target = ThisVal;
} else {
// Cast to the base type.
bool IsVirtual =
(CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase);
SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(),
IsVirtual);
- Target = BaseVal.getAsRegion();
+ Target = BaseVal;
}
break;
}
}
+ if (State != Pred->getState()) {
+ static SimpleProgramPointTag T("ExprEngine",
+ "Prepare for object construction");
+ ExplodedNodeSet DstPrepare;
+ StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx);
+ BldrPrepare.generateNode(CE, Pred, State, &T, ProgramPoint::PreStmtKind);
+ assert(DstPrepare.size() <= 1);
+ if (DstPrepare.size() == 0)
+ return;
+ Pred = *BldrPrepare.begin();
+ }
+
CallEventManager &CEMgr = getStateManager().getCallEventManager();
CallEventRef<CXXConstructorCall> Call =
- CEMgr.getCXXConstructorCall(CE, Target, State, LCtx);
+ CEMgr.getCXXConstructorCall(CE, Target.getAsRegion(), State, LCtx);
ExplodedNodeSet DstPreVisit;
getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
+ // FIXME: Is it possible and/or useful to do this before PreStmt?
ExplodedNodeSet PreInitialized;
{
StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);
- if (CE->requiresZeroInitialization()) {
- // Type of the zero doesn't matter.
- SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy);
-
- for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
- E = DstPreVisit.end();
- I != E; ++I) {
- ProgramStateRef State = (*I)->getState();
+ for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
+ E = DstPreVisit.end();
+ I != E; ++I) {
+ ProgramStateRef State = (*I)->getState();
+ if (CE->requiresZeroInitialization()) {
// FIXME: Once we properly handle constructors in new-expressions, we'll
// need to invalidate the region before setting a default value, to make
// sure there aren't any lingering bindings around. This probably needs
@@ -335,10 +439,11 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// actually make things worse. Placement new makes this tricky as well,
// since it's then possible to be initializing one part of a multi-
// dimensional array.
- State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx);
- Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
- ProgramPoint::PreStmtKind);
+ State = State->bindDefaultZero(Target, LCtx);
}
+
+ Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
+ ProgramPoint::PreStmtKind);
}
}
@@ -349,10 +454,9 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNodeSet DstEvaluated;
StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
- bool IsArray = isa<ElementRegion>(Target);
if (CE->getConstructor()->isTrivial() &&
CE->getConstructor()->isCopyOrMoveConstructor() &&
- !IsArray) {
+ !CallOpts.IsArrayCtorOrDtor) {
// FIXME: Handle other kinds of trivial constructors as well.
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
@@ -361,10 +465,10 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
} else {
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
- defaultEvalCall(Bldr, *I, *Call);
+ defaultEvalCall(Bldr, *I, *Call, CallOpts);
}
- // If the CFG was contructed without elements for temporary destructors
+ // If the CFG was constructed without elements for temporary destructors
// and the just-called constructor created a temporary object then
// stop exploration if the temporary object has a noreturn constructor.
// This can lose coverage because the destructor, if it were present
@@ -373,20 +477,30 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// paths when no-return temporary destructors are used for assertions.
const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext();
if (!ADC->getCFGBuildOptions().AddTemporaryDtors) {
- const MemRegion *Target = Call->getCXXThisVal().getAsRegion();
- if (Target && isa<CXXTempObjectRegion>(Target) &&
- Call->getDecl()->getParent()->isAnyDestructorNoReturn()) {
+ const MemRegion *Target = Call->getCXXThisVal().getAsRegion();
+ if (Target && isa<CXXTempObjectRegion>(Target) &&
+ Call->getDecl()->getParent()->isAnyDestructorNoReturn()) {
+
+ // If we've inlined the constructor, then DstEvaluated would be empty.
+ // In this case we still want a sink, which could be implemented
+ // in processCallExit. But we don't have that implemented at the moment,
+ // so if you hit this assertion, see if you can avoid inlining
+ // the respective constructor when analyzer-config cfg-temporary-dtors
+ // is set to false.
+ // Otherwise there's nothing wrong with inlining such constructor.
+ assert(!DstEvaluated.empty() &&
+ "We should not have inlined this constructor!");
for (ExplodedNode *N : DstEvaluated) {
Bldr.generateSink(CE, N, N->getState());
}
- // There is no need to run the PostCall and PostStmtchecker
+ // There is no need to run the PostCall and PostStmt checker
// callbacks because we just generated sinks on all nodes in th
// frontier.
return;
}
- }
+ }
ExplodedNodeSet DstPostCall;
getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated,
@@ -399,19 +513,11 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
const Stmt *S,
bool IsBaseDtor,
ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+ ExplodedNodeSet &Dst,
+ const EvalCallOptions &CallOpts) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
- // FIXME: We need to run the same destructor on every element of the array.
- // This workaround will just run the first destructor (which will still
- // invalidate the entire array).
- SVal DestVal = UnknownVal();
- if (Dest)
- DestVal = loc::MemRegionVal(Dest);
- DestVal = makeZeroElementRegion(State, DestVal, ObjectType);
- Dest = DestVal.getAsRegion();
-
const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
assert(RecordDecl && "Only CXXRecordDecls should have destructors");
const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
@@ -432,7 +538,7 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
- defaultEvalCall(Bldr, *I, *Call);
+ defaultEvalCall(Bldr, *I, *Call, CallOpts);
ExplodedNodeSet DstPostCall;
getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
@@ -455,15 +561,58 @@ void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
*Call, *this);
- ExplodedNodeSet DstInvalidated;
- StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
- for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
- I != E; ++I)
- defaultEvalCall(Bldr, *I, *Call);
- getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
- *Call, *this);
-}
+ ExplodedNodeSet DstPostCall;
+ StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx);
+ for (auto I : DstPreCall) {
+ // FIXME: Provide evalCall for checkers?
+ defaultEvalCall(CallBldr, I, *Call);
+ }
+ // If the call is inlined, DstPostCall will be empty and we bail out now.
+
+ // Store return value of operator new() for future use, until the actual
+ // CXXNewExpr gets processed.
+ ExplodedNodeSet DstPostValue;
+ StmtNodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx);
+ for (auto I : DstPostCall) {
+ // FIXME: Because CNE serves as the "call site" for the allocator (due to
+ // lack of a better expression in the AST), the conjured return value symbol
+ // is going to be of the same type (C++ object pointer type). Technically
+ // this is not correct because the operator new's prototype always says that
+ // it returns a 'void *'. So we should change the type of the symbol,
+ // and then evaluate the cast over the symbolic pointer from 'void *' to
+ // the object pointer type. But without changing the symbol's type it
+ // is breaking too much to evaluate the no-op symbolic cast over it, so we
+ // skip it for now.
+ ProgramStateRef State = I->getState();
+ SVal RetVal = State->getSVal(CNE, LCtx);
+
+ // If this allocation function is not declared as non-throwing, failures
+ // /must/ be signalled by exceptions, and thus the return value will never
+ // be NULL. -fno-exceptions does not influence this semantics.
+ // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
+ // where new can return NULL. If we end up supporting that option, we can
+ // consider adding a check for it here.
+ // C++11 [basic.stc.dynamic.allocation]p3.
+ if (const FunctionDecl *FD = CNE->getOperatorNew()) {
+ QualType Ty = FD->getType();
+ if (const auto *ProtoType = Ty->getAs<FunctionProtoType>())
+ if (!ProtoType->isNothrow())
+ State = State->assume(RetVal.castAs<DefinedOrUnknownSVal>(), true);
+ }
+ ValueBldr.generateNode(
+ CNE, I, addObjectUnderConstruction(State, CNE, LCtx, RetVal));
+ }
+
+ ExplodedNodeSet DstPostPostCallCallback;
+ getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback,
+ DstPostValue, *Call, *this);
+ for (auto I : DstPostPostCallCallback) {
+ getCheckerManager().runCheckersForNewAllocator(
+ CNE, *getObjectUnderConstruction(I->getState(), CNE, LCtx), Dst, I,
+ *this);
+ }
+}
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -474,69 +623,74 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
unsigned blockCount = currBldrCtx->blockCount();
const LocationContext *LCtx = Pred->getLocationContext();
- DefinedOrUnknownSVal symVal = UnknownVal();
+ SVal symVal = UnknownVal();
FunctionDecl *FD = CNE->getOperatorNew();
- bool IsStandardGlobalOpNewFunction = false;
- if (FD && !isa<CXXMethodDecl>(FD) && !FD->isVariadic()) {
- if (FD->getNumParams() == 2) {
- QualType T = FD->getParamDecl(1)->getType();
- if (const IdentifierInfo *II = T.getBaseTypeIdentifier())
- // NoThrow placement new behaves as a standard new.
- IsStandardGlobalOpNewFunction = II->getName().equals("nothrow_t");
- }
- else
- // Placement forms are considered non-standard.
- IsStandardGlobalOpNewFunction = (FD->getNumParams() == 1);
+ bool IsStandardGlobalOpNewFunction =
+ FD->isReplaceableGlobalAllocationFunction();
+
+ ProgramStateRef State = Pred->getState();
+
+ // Retrieve the stored operator new() return value.
+ if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ symVal = *getObjectUnderConstruction(State, CNE, LCtx);
+ State = finishObjectConstruction(State, CNE, LCtx);
}
// We assume all standard global 'operator new' functions allocate memory in
// heap. We realize this is an approximation that might not correctly model
// a custom global allocator.
- if (IsStandardGlobalOpNewFunction)
- symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
- else
- symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
- blockCount);
+ if (symVal.isUnknown()) {
+ if (IsStandardGlobalOpNewFunction)
+ symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
+ else
+ symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
+ blockCount);
+ }
- ProgramStateRef State = Pred->getState();
CallEventManager &CEMgr = getStateManager().getCallEventManager();
CallEventRef<CXXAllocatorCall> Call =
CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
- // Invalidate placement args.
- // FIXME: Once we figure out how we want allocators to work,
- // we should be using the usual pre-/(default-)eval-/post-call checks here.
- State = Call->invalidateRegions(blockCount);
- if (!State)
- return;
+ if (!AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ // Invalidate placement args.
+ // FIXME: Once we figure out how we want allocators to work,
+ // we should be using the usual pre-/(default-)eval-/post-call checks here.
+ State = Call->invalidateRegions(blockCount);
+ if (!State)
+ return;
- // If this allocation function is not declared as non-throwing, failures
- // /must/ be signalled by exceptions, and thus the return value will never be
- // NULL. -fno-exceptions does not influence this semantics.
- // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
- // where new can return NULL. If we end up supporting that option, we can
- // consider adding a check for it here.
- // C++11 [basic.stc.dynamic.allocation]p3.
- if (FD) {
- QualType Ty = FD->getType();
- if (const FunctionProtoType *ProtoType = Ty->getAs<FunctionProtoType>())
- if (!ProtoType->isNothrow(getContext()))
- State = State->assume(symVal, true);
+ // If this allocation function is not declared as non-throwing, failures
+ // /must/ be signalled by exceptions, and thus the return value will never
+ // be NULL. -fno-exceptions does not influence this semantics.
+ // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
+ // where new can return NULL. If we end up supporting that option, we can
+ // consider adding a check for it here.
+ // C++11 [basic.stc.dynamic.allocation]p3.
+ if (FD) {
+ QualType Ty = FD->getType();
+ if (const auto *ProtoType = Ty->getAs<FunctionProtoType>())
+ if (!ProtoType->isNothrow())
+ if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>())
+ State = State->assume(*dSymVal, true);
+ }
}
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ SVal Result = symVal;
+
if (CNE->isArray()) {
// FIXME: allocating an array requires simulating the constructors.
// For now, just return a symbolicated region.
- const SubRegion *NewReg =
- symVal.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>();
- QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
- const ElementRegion *EleReg =
- getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
- State = State->BindExpr(CNE, Pred->getLocationContext(),
- loc::MemRegionVal(EleReg));
+ if (const SubRegion *NewReg =
+ dyn_cast_or_null<SubRegion>(symVal.getAsRegion())) {
+ QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
+ const ElementRegion *EleReg =
+ getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
+ Result = loc::MemRegionVal(EleReg);
+ }
+ State = State->BindExpr(CNE, Pred->getLocationContext(), Result);
Bldr.generateNode(CNE, Pred, State);
return;
}
@@ -545,7 +699,6 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
// CXXNewExpr, we need to make sure that the constructed object is not
// immediately invalidated here. (The placement call should happen before
// the constructor call anyway.)
- SVal Result = symVal;
if (FD && FD->isReservedGlobalPlacementOperator()) {
// Non-array placement new should always return the placement location.
SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index caf86b26b66d..3ee67f3d6882 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -15,8 +15,8 @@
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ParentMap.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "llvm/ADT/SmallSet.h"
@@ -74,15 +74,14 @@ static std::pair<const Stmt*,
const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
const Stmt *S = nullptr;
const CFGBlock *Blk = nullptr;
- const StackFrameContext *SF =
- Node->getLocation().getLocationContext()->getCurrentStackFrame();
+ const StackFrameContext *SF = Node->getStackFrame();
// Back up through the ExplodedGraph until we reach a statement node in this
// stack frame.
while (Node) {
const ProgramPoint &PP = Node->getLocation();
- if (PP.getLocationContext()->getCurrentStackFrame() == SF) {
+ if (PP.getStackFrame() == SF) {
if (Optional<StmtPoint> SP = PP.getAs<StmtPoint>()) {
S = SP->getStmt();
break;
@@ -121,7 +120,7 @@ static std::pair<const Stmt*,
/// Adjusts a return value when the called function's return type does not
/// match the caller's expression type. This can happen when a dynamic call
-/// is devirtualized, and the overridding method has a covariant (more specific)
+/// is devirtualized, and the overriding method has a covariant (more specific)
/// return type than the parent's method. For C++ objects, this means we need
/// to add base casts.
static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy,
@@ -193,23 +192,6 @@ static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call,
return RuntimeCallee->getCanonicalDecl() != StaticDecl->getCanonicalDecl();
}
-/// Returns true if the CXXConstructExpr \p E was intended to construct a
-/// prvalue for the region in \p V.
-///
-/// Note that we can't just test for rvalue vs. glvalue because
-/// CXXConstructExprs embedded in DeclStmts and initializers are considered
-/// rvalues by the AST, and the analyzer would like to treat them as lvalues.
-static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V) {
- if (E->isGLValue())
- return false;
-
- const MemRegion *MR = V.getAsRegion();
- if (!MR)
- return false;
-
- return isa<CXXTempObjectRegion>(MR);
-}
-
/// The call exit is simulated with a sequence of nodes, which occur between
/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
@@ -221,13 +203,12 @@ static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V) {
void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// Step 1 CEBNode was generated before the call.
PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
- const StackFrameContext *calleeCtx =
- CEBNode->getLocationContext()->getCurrentStackFrame();
+ const StackFrameContext *calleeCtx = CEBNode->getStackFrame();
// The parent context might not be a stack frame, so make sure we
// look up the first enclosing stack frame.
const StackFrameContext *callerCtx =
- calleeCtx->getParent()->getCurrentStackFrame();
+ calleeCtx->getParent()->getStackFrame();
const Stmt *CE = calleeCtx->getCallSite();
ProgramStateRef state = CEBNode->getState();
@@ -269,13 +250,24 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
loc::MemRegionVal This =
svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
SVal ThisV = state->getSVal(This);
-
- // If the constructed object is a temporary prvalue, get its bindings.
- if (isTemporaryPRValue(CCE, ThisV))
- ThisV = state->getSVal(ThisV.castAs<Loc>());
-
+ ThisV = state->getSVal(ThisV.castAs<Loc>());
state = state->BindExpr(CCE, callerCtx, ThisV);
}
+
+ if (const auto *CNE = dyn_cast<CXXNewExpr>(CE)) {
+ // We are currently evaluating a CXXNewAllocator CFGElement. It takes a
+ // while to reach the actual CXXNewExpr element from here, so keep the
+ // region for later use.
+ // Additionally cast the return value of the inlined operator new
+ // (which is of type 'void *') to the correct object type.
+ SVal AllocV = state->getSVal(CNE, callerCtx);
+ AllocV = svalBuilder.evalCast(
+ AllocV, CNE->getType(),
+ getContext().getPointerType(getContext().VoidTy));
+
+ state = addObjectUnderConstruction(state, CNE, calleeCtx->getParent(),
+ AllocV);
+ }
}
// Step 3: BindedRetNode -> CleanedNodes
@@ -315,6 +307,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
CallExitEnd Loc(calleeCtx, callerCtx);
bool isNew;
ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState();
+
ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);
CEENode->addPredecessor(*I, G);
if (!isNew)
@@ -331,16 +324,32 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
CallEventRef<> UpdatedCall = Call.cloneWithState(CEEState);
ExplodedNodeSet DstPostCall;
- getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode,
- *UpdatedCall, *this,
- /*WasInlined=*/true);
-
+ if (const CXXNewExpr *CNE = dyn_cast_or_null<CXXNewExpr>(CE)) {
+ ExplodedNodeSet DstPostPostCallCallback;
+ getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback,
+ CEENode, *UpdatedCall, *this,
+ /*WasInlined=*/true);
+ for (auto I : DstPostPostCallCallback) {
+ getCheckerManager().runCheckersForNewAllocator(
+ CNE,
+ *getObjectUnderConstruction(I->getState(), CNE,
+ calleeCtx->getParent()),
+ DstPostCall, I, *this,
+ /*WasInlined=*/true);
+ }
+ } else {
+ getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode,
+ *UpdatedCall, *this,
+ /*WasInlined=*/true);
+ }
ExplodedNodeSet Dst;
if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, *Msg,
*this,
/*WasInlined=*/true);
- } else if (CE) {
+ } else if (CE &&
+ !(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
+ AMgr.getAnalyzerOptions().mayInlineCXXAllocator())) {
getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
*this, /*WasInlined=*/true);
} else {
@@ -407,7 +416,7 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
assert(D);
const LocationContext *CurLC = Pred->getLocationContext();
- const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame();
+ const StackFrameContext *CallerSFC = CurLC->getStackFrame();
const LocationContext *ParentOfCallee = CallerSFC;
if (Call.getKind() == CE_Block &&
!cast<BlockCall>(Call).isConversionFromLambda()) {
@@ -542,19 +551,45 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
}
} else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){
SVal ThisV = C->getCXXThisVal();
-
- // If the constructed object is a temporary prvalue, get its bindings.
- if (isTemporaryPRValue(cast<CXXConstructExpr>(E), ThisV))
- ThisV = State->getSVal(ThisV.castAs<Loc>());
-
+ ThisV = State->getSVal(ThisV.castAs<Loc>());
return State->BindExpr(E, LCtx, ThisV);
}
- // Conjure a symbol if the return value is unknown.
+ SVal R;
QualType ResultTy = Call.getResultType();
- SValBuilder &SVB = getSValBuilder();
unsigned Count = currBldrCtx->blockCount();
- SVal R = SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+ if (auto RTC = getCurrentCFGElement().getAs<CFGCXXRecordTypedCall>()) {
+ // Conjure a temporary if the function returns an object by value.
+ SVal Target;
+ assert(RTC->getStmt() == Call.getOriginExpr());
+ EvalCallOptions CallOpts; // FIXME: We won't really need those.
+ std::tie(State, Target) =
+ prepareForObjectConstruction(Call.getOriginExpr(), State, LCtx,
+ RTC->getConstructionContext(), CallOpts);
+ assert(Target.getAsRegion());
+ // Invalidate the region so that it didn't look uninitialized. Don't notify
+ // the checkers.
+ State = State->invalidateRegions(Target.getAsRegion(), E, Count, LCtx,
+ /* CausedByPointerEscape=*/false, nullptr,
+ &Call, nullptr);
+
+ R = State->getSVal(Target.castAs<Loc>(), E->getType());
+ } else {
+ // Conjure a symbol if the return value is unknown.
+
+ // See if we need to conjure a heap pointer instead of
+ // a regular unknown pointer.
+ bool IsHeapPointer = false;
+ if (const auto *CNE = dyn_cast<CXXNewExpr>(E))
+ if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+ // FIXME: Delegate this to evalCall in MallocChecker?
+ IsHeapPointer = true;
+ }
+
+ R = IsHeapPointer ? svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count)
+ : svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy,
+ Count);
+ }
return State->BindExpr(E, LCtx, R);
}
@@ -570,17 +605,12 @@ void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
Bldr.generateNode(Call.getProgramPoint(), State, Pred);
}
-enum CallInlinePolicy {
- CIP_Allowed,
- CIP_DisallowedOnce,
- CIP_DisallowedAlways
-};
-
-static CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
- const ExplodedNode *Pred,
- AnalyzerOptions &Opts) {
+ExprEngine::CallInlinePolicy
+ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
+ AnalyzerOptions &Opts,
+ const ExprEngine::EvalCallOptions &CallOpts) {
const LocationContext *CurLC = Pred->getLocationContext();
- const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame();
+ const StackFrameContext *CallerSFC = CurLC->getStackFrame();
switch (Call.getKind()) {
case CE_Function:
case CE_Block:
@@ -596,22 +626,24 @@ static CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call);
+ const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr();
+
+ auto CCE = getCurrentCFGElement().getAs<CFGConstructor>();
+ const ConstructionContext *CC = CCE ? CCE->getConstructionContext()
+ : nullptr;
+
+ if (CC && isa<NewAllocatedObjectConstructionContext>(CC) &&
+ !Opts.mayInlineCXXAllocator())
+ return CIP_DisallowedOnce;
+
// FIXME: We don't handle constructors or destructors for arrays properly.
// Even once we do, we still need to be careful about implicitly-generated
// initializers for array fields in default move/copy constructors.
- const MemRegion *Target = Ctor.getCXXThisVal().getAsRegion();
- if (Target && isa<ElementRegion>(Target))
+ // We still allow construction into ElementRegion targets when they don't
+ // represent array elements.
+ if (CallOpts.IsArrayCtorOrDtor)
return CIP_DisallowedOnce;
- // FIXME: This is a hack. We don't use the correct region for a new
- // expression, so if we inline the constructor its result will just be
- // thrown away. This short-term hack is tracked in <rdar://problem/12180598>
- // and the longer-term possible fix is discussed in PR12014.
- const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr();
- if (const Stmt *Parent = CurLC->getParentMap().getParent(CtorExpr))
- if (isa<CXXNewExpr>(Parent))
- return CIP_DisallowedOnce;
-
// Inlining constructors requires including initializers in the CFG.
const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers");
@@ -626,12 +658,25 @@ static CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
return CIP_DisallowedAlways;
- // FIXME: This is a hack. We don't handle temporary destructors
- // right now, so we shouldn't inline their constructors.
- if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete)
- if (!Target || !isa<DeclRegion>(Target))
+ if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) {
+ // If we don't handle temporary destructors, we shouldn't inline
+ // their constructors.
+ if (CallOpts.IsTemporaryCtorOrDtor &&
+ !Opts.includeTemporaryDtorsInCFG())
+ return CIP_DisallowedOnce;
+
+ // If we did not find the correct this-region, it would be pointless
+ // to inline the constructor. Instead we will simply invalidate
+ // the fake temporary target.
+ if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion)
return CIP_DisallowedOnce;
+ // If the temporary is lifetime-extended by binding it to a reference-type
+ // field within an aggregate, automatic destructors don't work properly.
+ if (CallOpts.IsTemporaryLifetimeExtendedViaAggregate)
+ return CIP_DisallowedOnce;
+ }
+
break;
}
case CE_CXXDestructor: {
@@ -643,13 +688,19 @@ static CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors");
(void)ADC;
- const CXXDestructorCall &Dtor = cast<CXXDestructorCall>(Call);
-
// FIXME: We don't handle constructors or destructors for arrays properly.
- const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion();
- if (Target && isa<ElementRegion>(Target))
+ if (CallOpts.IsArrayCtorOrDtor)
+ return CIP_DisallowedOnce;
+
+ // Allow disabling temporary destructor inlining with a separate option.
+ if (CallOpts.IsTemporaryCtorOrDtor && !Opts.mayInlineCXXTemporaryDtors())
return CIP_DisallowedOnce;
+ // If we did not find the correct this-region, it would be pointless
+ // to inline the destructor. Instead we will simply invalidate
+ // the fake temporary target.
+ if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion)
+ return CIP_DisallowedOnce;
break;
}
case CE_CXXAllocator:
@@ -731,8 +782,9 @@ static bool isCXXSharedPtrDtor(const FunctionDecl *FD) {
/// This checks static properties of the function, such as its signature and
/// CFG, to determine whether the analyzer should ever consider inlining it,
/// in any context.
-static bool mayInlineDecl(AnalysisDeclContext *CalleeADC,
- AnalyzerOptions &Opts) {
+static bool mayInlineDecl(AnalysisManager &AMgr,
+ AnalysisDeclContext *CalleeADC) {
+ AnalyzerOptions &Opts = AMgr.getAnalyzerOptions();
// FIXME: Do not inline variadic calls.
if (CallEvent::isVariadic(CalleeADC->getDecl()))
return false;
@@ -755,7 +807,7 @@ static bool mayInlineDecl(AnalysisDeclContext *CalleeADC,
// Conditionally control the inlining of methods on objects that look
// like C++ containers.
if (!Opts.mayInlineCXXContainerMethods())
- if (!Ctx.getSourceManager().isInMainFile(FD->getLocation()))
+ if (!AMgr.isInCodeFile(FD->getLocation()))
if (isContainerMethod(Ctx, FD))
return false;
@@ -788,7 +840,8 @@ static bool mayInlineDecl(AnalysisDeclContext *CalleeADC,
}
bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
- const ExplodedNode *Pred) {
+ const ExplodedNode *Pred,
+ const EvalCallOptions &CallOpts) {
if (!D)
return false;
@@ -797,14 +850,6 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
- // Temporary object destructor processing is currently broken, so we never
- // inline them.
- // FIXME: Remove this once temp destructors are working.
- if (isa<CXXDestructorCall>(Call)) {
- if ((*currBldrCtx->getBlock())[currStmtIdx].getAs<CFGTemporaryDtor>())
- return false;
- }
-
// The auto-synthesized bodies are essential to inline as they are
// usually small and commonly used. Note: we should do this check early on to
// ensure we always inline these calls.
@@ -823,7 +868,7 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
} else {
// We haven't actually checked the static properties of this function yet.
// Do that now, and record our decision in the function summaries.
- if (mayInlineDecl(CalleeADC, Opts)) {
+ if (mayInlineDecl(getAnalysisManager(), CalleeADC)) {
Engine.FunctionSummaries->markMayInline(D);
} else {
Engine.FunctionSummaries->markShouldNotInline(D);
@@ -835,7 +880,7 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
// FIXME: this checks both static and dynamic properties of the call, which
// means we're redoing a bit of work that could be cached in the function
// summary.
- CallInlinePolicy CIP = mayInlineCallKind(Call, Pred, Opts);
+ CallInlinePolicy CIP = mayInlineCallKind(Call, Pred, Opts, CallOpts);
if (CIP != CIP_Allowed) {
if (CIP == CIP_DisallowedAlways) {
assert(!MayInline.hasValue() || MayInline.getValue());
@@ -887,7 +932,8 @@ static bool isTrivialObjectAssignment(const CallEvent &Call) {
}
void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
- const CallEvent &CallTemplate) {
+ const CallEvent &CallTemplate,
+ const EvalCallOptions &CallOpts) {
// Make sure we have the most recent state attached to the call.
ProgramStateRef State = Pred->getState();
CallEventRef<> Call = CallTemplate.cloneWithState(State);
@@ -910,7 +956,7 @@ void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
} else {
RuntimeDefinition RD = Call->getRuntimeDefinition();
const Decl *D = RD.getDecl();
- if (shouldInlineCall(*Call, D, Pred)) {
+ if (shouldInlineCall(*Call, D, Pred, CallOpts)) {
if (RD.mayHaveOtherDefinitions()) {
AnalyzerOptions &Options = getAnalysisManager().options;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index f5e64f4a5a8c..d76b9cbcfaca 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -42,6 +42,47 @@ void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
}
+/// Generate a node in \p Bldr for an iteration statement using ObjC
+/// for-loop iterator.
+static void populateObjCForDestinationSet(
+ ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder,
+ const ObjCForCollectionStmt *S, const Stmt *elem, SVal elementV,
+ SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx,
+ StmtNodeBuilder &Bldr, bool hasElements) {
+
+ for (ExplodedNode *Pred : dstLocation) {
+ ProgramStateRef state = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+
+ SVal hasElementsV = svalBuilder.makeTruthVal(hasElements);
+
+ // FIXME: S is not an expression. We should not be binding values to it.
+ ProgramStateRef nextState = state->BindExpr(S, LCtx, hasElementsV);
+
+ if (auto MV = elementV.getAs<loc::MemRegionVal>())
+ if (const auto *R = dyn_cast<TypedValueRegion>(MV->getRegion())) {
+ // FIXME: The proper thing to do is to really iterate over the
+ // container. We will do this with dispatch logic to the store.
+ // For now, just 'conjure' up a symbolic value.
+ QualType T = R->getValueType();
+ assert(Loc::isLocType(T));
+
+ SVal V;
+ if (hasElements) {
+ SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
+ currBldrCtx->blockCount());
+ V = svalBuilder.makeLoc(Sym);
+ } else {
+ V = svalBuilder.makeIntVal(0, T);
+ }
+
+ nextState = nextState->bindLoc(elementV, V, LCtx);
+ }
+
+ Bldr.generateNode(S, Pred, nextState);
+ }
+}
+
void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -72,60 +113,35 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
// result in state splitting.
const Stmt *elem = S->getElement();
+ const Stmt *collection = S->getCollection();
ProgramStateRef state = Pred->getState();
- SVal elementV;
+ SVal collectionV = state->getSVal(collection, Pred->getLocationContext());
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
+ SVal elementV;
+ if (const auto *DS = dyn_cast<DeclStmt>(elem)) {
const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
assert(elemD->getInit() == nullptr);
elementV = state->getLValue(elemD, Pred->getLocationContext());
- }
- else {
+ } else {
elementV = state->getSVal(elem, Pred->getLocationContext());
}
+ bool isContainerNull = state->isNull(collectionV).isConstrainedTrue();
+
ExplodedNodeSet dstLocation;
evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, false);
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
- for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
- NE = dstLocation.end(); NI!=NE; ++NI) {
- Pred = *NI;
- ProgramStateRef state = Pred->getState();
- const LocationContext *LCtx = Pred->getLocationContext();
-
- // Handle the case where the container still has elements.
- SVal TrueV = svalBuilder.makeTruthVal(1);
- ProgramStateRef hasElems = state->BindExpr(S, LCtx, TrueV);
-
- // Handle the case where the container has no elements.
- SVal FalseV = svalBuilder.makeTruthVal(0);
- ProgramStateRef noElems = state->BindExpr(S, LCtx, FalseV);
+ if (!isContainerNull)
+ populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV,
+ SymMgr, currBldrCtx, Bldr,
+ /*hasElements=*/true);
- if (Optional<loc::MemRegionVal> MV = elementV.getAs<loc::MemRegionVal>())
- if (const TypedValueRegion *R =
- dyn_cast<TypedValueRegion>(MV->getRegion())) {
- // FIXME: The proper thing to do is to really iterate over the
- // container. We will do this with dispatch logic to the store.
- // For now, just 'conjure' up a symbolic value.
- QualType T = R->getValueType();
- assert(Loc::isLocType(T));
- SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
- currBldrCtx->blockCount());
- SVal V = svalBuilder.makeLoc(Sym);
- hasElems = hasElems->bindLoc(elementV, V, LCtx);
-
- // Bind the location to 'nil' on the false branch.
- SVal nilV = svalBuilder.makeIntVal(0, T);
- noElems = noElems->bindLoc(elementV, nilV, LCtx);
- }
-
- // Create the new nodes.
- Bldr.generateNode(S, Pred, hasElems);
- Bldr.generateNode(S, Pred, noElems);
- }
+ populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV,
+ SymMgr, currBldrCtx, Bldr,
+ /*hasElements=*/false);
// Finally, run any custom checkers.
// FIXME: Eventually all pre- and post-checks should live in VisitStmt.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FunctionSummary.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FunctionSummary.cpp
index c21735b8b882..94edd84d15d2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FunctionSummary.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FunctionSummary.cpp
@@ -1,4 +1,4 @@
-//== FunctionSummary.cpp - Stores summaries of functions. ----------*- C++ -*-//
+//===- FunctionSummary.cpp - Stores summaries of functions. ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,21 +12,20 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
+
using namespace clang;
using namespace ento;
unsigned FunctionSummariesTy::getTotalNumBasicBlocks() {
unsigned Total = 0;
- for (MapTy::iterator I = Map.begin(), E = Map.end(); I != E; ++I) {
- Total += I->second.TotalBasicBlocks;
- }
+ for (const auto &I : Map)
+ Total += I.second.TotalBasicBlocks;
return Total;
}
unsigned FunctionSummariesTy::getTotalNumVisitedBasicBlocks() {
unsigned Total = 0;
- for (MapTy::iterator I = Map.begin(), E = Map.end(); I != E; ++I) {
- Total += I->second.VisitedBasicBlocks.count();
- }
+ for (const auto &I : Map)
+ Total += I.second.VisitedBasicBlocks.count();
return Total;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index ebf1487d4bfc..d5e5f96dee0f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -1,4 +1,4 @@
-//===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- C++ -*-===//
+//===- HTMLDiagnostics.cpp - HTML Diagnostics for Paths -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,24 +11,43 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Stmt.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
#include "clang/Rewrite/Core/HTMLRewrite.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <map>
+#include <memory>
+#include <set>
#include <sstream>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
@@ -41,15 +60,19 @@ namespace {
class HTMLDiagnostics : public PathDiagnosticConsumer {
std::string Directory;
- bool createdDir, noDir;
+ bool createdDir = false;
+ bool noDir = false;
const Preprocessor &PP;
AnalyzerOptions &AnalyzerOpts;
const bool SupportsCrossFileDiagnostics;
+
public:
HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
const std::string& prefix,
const Preprocessor &pp,
- bool supportsMultipleFiles);
+ bool supportsMultipleFiles)
+ : Directory(prefix), PP(pp), AnalyzerOpts(AnalyzerOpts),
+ SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
@@ -94,20 +117,13 @@ public:
/// \return Javascript for navigating the HTML report using j/k keys.
std::string generateKeyboardNavigationJavascript();
-};
-} // end anonymous namespace
+private:
+ /// \return Javascript for displaying shortcuts help;
+ std::string showHelpJavascript();
+};
-HTMLDiagnostics::HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
- const std::string& prefix,
- const Preprocessor &pp,
- bool supportsMultipleFiles)
- : Directory(prefix),
- createdDir(false),
- noDir(false),
- PP(pp),
- AnalyzerOpts(AnalyzerOpts),
- SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
+} // namespace
void ento::createHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
PathDiagnosticConsumers &C,
@@ -130,24 +146,19 @@ void ento::createHTMLSingleFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
void HTMLDiagnostics::FlushDiagnosticsImpl(
std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) {
- for (std::vector<const PathDiagnostic *>::iterator it = Diags.begin(),
- et = Diags.end(); it != et; ++it) {
- ReportDiag(**it, filesMade);
- }
+ for (const auto Diag : Diags)
+ ReportDiag(*Diag, filesMade);
}
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
FilesMade *filesMade) {
-
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
if (std::error_code ec = llvm::sys::fs::create_directories(Directory)) {
llvm::errs() << "warning: could not create directory '"
<< Directory << "': " << ec.message() << '\n';
-
noDir = true;
-
return;
}
}
@@ -174,7 +185,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
SmallString<128> declName("unknown");
int offsetDecl = 0;
if (const Decl *DeclWithIssue = D.getDeclWithIssue()) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue))
+ if (const auto *ND = dyn_cast<NamedDecl>(DeclWithIssue))
declName = ND->getDeclName().getAsString();
if (const Stmt *Body = DeclWithIssue->getBody()) {
@@ -212,7 +223,6 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
<< "': " << EC.message() << '\n';
return;
}
-
} else {
int i = 1;
std::error_code EC;
@@ -228,10 +238,8 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
<< "-" << 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);
+ EC = llvm::sys::fs::openFileForReadWrite(
+ Model, FD, llvm::sys::fs::CD_CreateNew, llvm::sys::fs::OF_None);
if (EC && EC != llvm::errc::file_exists) {
llvm::errs() << "warning: could not create file '" << Model
<< "': " << EC.message() << '\n';
@@ -253,7 +261,6 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
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) {
@@ -309,10 +316,12 @@ std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
const RewriteBuffer *Buf = R.getRewriteBufferFor(FileIDs[0]);
if (!Buf)
- return "";
+ return {};
// Add CSS, header, and footer.
- const FileEntry* Entry = SMgr.getFileEntryForID(FileIDs[0]);
+ FileID FID =
+ path.back()->getLocation().asLocation().getExpansionLoc().getFileID();
+ const FileEntry* Entry = SMgr.getFileEntryForID(FID);
FinalizeHTML(D, R, SMgr, path, FileIDs[0], Entry, declName);
std::string file;
@@ -323,6 +332,114 @@ std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
return os.str();
}
+/// Write executed lines from \p D in JSON format into \p os.
+static void serializeExecutedLines(
+ const PathDiagnostic &D,
+ const PathPieces &path,
+ llvm::raw_string_ostream &os) {
+ // Copy executed lines from path diagnostics.
+ std::map<unsigned, std::set<unsigned>> ExecutedLines;
+ for (auto I = D.executedLines_begin(),
+ E = D.executedLines_end(); I != E; ++I) {
+ std::set<unsigned> &LinesInFile = ExecutedLines[I->first];
+ for (unsigned LineNo : I->second) {
+ LinesInFile.insert(LineNo);
+ }
+ }
+
+ // We need to include all lines for which any kind of diagnostics appears.
+ for (const auto &P : path) {
+ FullSourceLoc Loc = P->getLocation().asLocation().getExpansionLoc();
+ FileID FID = Loc.getFileID();
+ unsigned LineNo = Loc.getLineNumber();
+ ExecutedLines[FID.getHashValue()].insert(LineNo);
+ }
+
+ os << "var relevant_lines = {";
+ for (auto I = ExecutedLines.begin(),
+ E = ExecutedLines.end(); I != E; ++I) {
+ if (I != ExecutedLines.begin())
+ os << ", ";
+
+ os << "\"" << I->first << "\": {";
+ for (unsigned LineNo : I->second) {
+ if (LineNo != *(I->second.begin()))
+ os << ", ";
+
+ os << "\"" << LineNo << "\": 1";
+ }
+ os << "}";
+ }
+
+ os << "};";
+}
+
+/// \return JavaScript for an option to only show relevant lines.
+static std::string showRelevantLinesJavascript(
+ const PathDiagnostic &D, const PathPieces &path) {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+ os << "<script type='text/javascript'>\n";
+ serializeExecutedLines(D, path, os);
+ os << R"<<<(
+
+var filterCounterexample = function (hide) {
+ var tables = document.getElementsByClassName("code");
+ for (var t=0; t<tables.length; t++) {
+ var table = tables[t];
+ var file_id = table.getAttribute("data-fileid");
+ var lines_in_fid = relevant_lines[file_id];
+ if (!lines_in_fid) {
+ lines_in_fid = {};
+ }
+ var lines = table.getElementsByClassName("codeline");
+ for (var i=0; i<lines.length; i++) {
+ var el = lines[i];
+ var lineNo = el.getAttribute("data-linenumber");
+ if (!lines_in_fid[lineNo]) {
+ if (hide) {
+ el.setAttribute("hidden", "");
+ } else {
+ el.removeAttribute("hidden");
+ }
+ }
+ }
+ }
+}
+
+window.addEventListener("keydown", function (event) {
+ if (event.defaultPrevented) {
+ return;
+ }
+ if (event.key == "S") {
+ var checked = document.getElementsByName("showCounterexample")[0].checked;
+ filterCounterexample(!checked);
+ document.getElementsByName("showCounterexample")[0].checked = !checked;
+ } else {
+ return;
+ }
+ event.preventDefault();
+}, true);
+
+document.addEventListener("DOMContentLoaded", function() {
+ document.querySelector('input[name="showCounterexample"]').onchange=
+ function (event) {
+ filterCounterexample(this.checked);
+ };
+});
+</script>
+
+<form>
+ <input type="checkbox" name="showCounterexample" id="showCounterexample" />
+ <label for="showCounterexample">
+ Show only relevant lines
+ </label>
+</form>
+)<<<";
+
+ 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) {
@@ -340,9 +457,15 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber();
int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber();
+ R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), showHelpJavascript());
+
R.InsertTextBefore(SMgr.getLocForStartOfFile(FID),
generateKeyboardNavigationJavascript());
+ // Checkbox and javascript for filtering the output to the counterexample.
+ R.InsertTextBefore(SMgr.getLocForStartOfFile(FID),
+ showRelevantLinesJavascript(D, path));
+
// Add the name of the file as an <h1> tag.
{
std::string s;
@@ -379,8 +502,8 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
// Output any other meta data.
- for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
- I!=E; ++I) {
+ for (PathDiagnostic::meta_iterator I = D.meta_begin(), E = D.meta_end();
+ I != E; ++I) {
os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
}
@@ -388,11 +511,24 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
</table>
<!-- REPORTSUMMARYEXTRA -->
<h3>Annotated Source Code</h3>
-<p><span class='macro'>[?]
- <span class='expansion'>Use j/k keys for keyboard navigation</span>
-</span></p>
+<p>Press <a href="#" onclick="toggleHelp(); return false;">'?'</a>
+ to see keyboard shortcuts</p>
+<input type="checkbox" class="spoilerhider" id="showinvocation" />
+<label for="showinvocation" >Show analyzer invocation</label>
+<div class="spoiler">clang -cc1 )<<<";
+ os << html::EscapeText(AnalyzerOpts.FullCompilerInvocation);
+ os << R"<<<(
+</div>
+<div id='tooltiphint' hidden="true">
+ <p>Keyboard shortcuts: </p>
+ <ul>
+ <li>Use 'j/k' keys for keyboard navigation</li>
+ <li>Use 'Shift+S' to show/hide relevant lines</li>
+ <li>Use '?' to toggle this window</li>
+ </ul>
+ <a href="#" onclick="toggleHelp(); return false;">Close</a>
+</div>
)<<<";
-
R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
@@ -450,6 +586,34 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
}
+std::string HTMLDiagnostics::showHelpJavascript() {
+ return R"<<<(
+<script type='text/javascript'>
+
+var toggleHelp = function() {
+ var hint = document.querySelector("#tooltiphint");
+ var attributeName = "hidden";
+ if (hint.hasAttribute(attributeName)) {
+ hint.removeAttribute(attributeName);
+ } else {
+ hint.setAttribute("hidden", "true");
+ }
+};
+window.addEventListener("keydown", function (event) {
+ if (event.defaultPrevented) {
+ return;
+ }
+ if (event.key == "?") {
+ toggleHelp();
+ } else {
+ return;
+ }
+ event.preventDefault();
+});
+</script>
+)<<<";
+}
+
void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr,
const PathPieces& path, FileID FID) {
// Process the path.
@@ -494,7 +658,6 @@ void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr,
void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
const PathDiagnosticPiece& P,
unsigned num, unsigned max) {
-
// For now, just draw a box above the line in question, and emit the
// warning.
FullSourceLoc Pos = P.getLocation().asLocation();
@@ -634,9 +797,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
os << "</td><td>";
}
- if (const PathDiagnosticMacroPiece *MP =
- dyn_cast<PathDiagnosticMacroPiece>(&P)) {
-
+ if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(&P)) {
os << "Within the expansion of the macro '";
// Get the name of the macro by relexing it.
@@ -707,10 +868,8 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
// Now highlight the ranges.
ArrayRef<SourceRange> Ranges = P.getRanges();
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- HighlightRange(R, LPosInfo.first, *I);
- }
+ for (const auto &Range : Ranges)
+ HighlightRange(R, LPosInfo.first, Range);
}
static void EmitAlphaCounter(raw_ostream &os, unsigned n) {
@@ -726,18 +885,13 @@ static void EmitAlphaCounter(raw_ostream &os, unsigned n) {
unsigned HTMLDiagnostics::ProcessMacroPiece(raw_ostream &os,
const PathDiagnosticMacroPiece& P,
unsigned num) {
-
- for (PathPieces::const_iterator I = P.subPieces.begin(), E=P.subPieces.end();
- I!=E; ++I) {
-
- if (const PathDiagnosticMacroPiece *MP =
- dyn_cast<PathDiagnosticMacroPiece>(I->get())) {
+ for (const auto &subPiece : P.subPieces) {
+ if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(subPiece.get())) {
num = ProcessMacroPiece(os, *MP, num);
continue;
}
- if (PathDiagnosticEventPiece *EP =
- dyn_cast<PathDiagnosticEventPiece>(I->get())) {
+ if (const auto *EP = dyn_cast<PathDiagnosticEventPiece>(subPiece.get())) {
os << "<div class=\"msg msgEvent\" style=\"width:94%; "
"margin-left:5px\">"
"<table class=\"msgT\"><tr>"
@@ -862,7 +1016,7 @@ window.addEventListener("keydown", function (event) {
navigateTo(/*up=*/true);
} else {
return;
- }
+ }
event.preventDefault();
}, true);
</script>
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
index 274ebe7a941b..6c55c61dd399 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
@@ -26,7 +26,7 @@
using namespace clang;
-// Get a string representation of the parts of the signature that can be
+// Get a string representation of the parts of the signature that can be
// overloaded on.
static std::string GetSignature(const FunctionDecl *Target) {
if (!Target)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
index a8c4b05cea13..da4574c61515 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
@@ -97,9 +97,7 @@ changeIntBoundNode(internal::Matcher<Decl> VarNodeMatcher) {
unaryOperator(anyOf(hasOperatorName("--"), hasOperatorName("++")),
hasUnaryOperand(ignoringParenImpCasts(
declRefExpr(to(varDecl(VarNodeMatcher)))))),
- binaryOperator(anyOf(hasOperatorName("="), hasOperatorName("+="),
- hasOperatorName("/="), hasOperatorName("*="),
- hasOperatorName("-=")),
+ binaryOperator(isAssignmentOperator(),
hasLHS(ignoringParenImpCasts(
declRefExpr(to(varDecl(VarNodeMatcher)))))));
}
@@ -143,13 +141,15 @@ 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"))))),
+ hasLoopInit(
+ anyOf(declStmt(hasSingleDecl(
+ varDecl(allOf(hasInitializer(ignoringParenImpCasts(
+ integerLiteral().bind("initNum"))),
+ equalsBoundNode("initVarName"))))),
+ binaryOperator(hasLHS(declRefExpr(to(varDecl(
+ equalsBoundNode("initVarName"))))),
+ hasRHS(ignoringParenImpCasts(
+ integerLiteral().bind("initNum")))))),
// Incrementation should be a simple increment or decrement
// operator call.
hasIncrement(unaryOperator(
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
index 05865c294cb7..9192f49eac6d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
@@ -14,10 +14,16 @@
///
//===----------------------------------------------------------------------===//
+#include "clang/AST/AST.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
using namespace clang;
using namespace ento;
+using namespace clang::ast_matchers;
+
+const auto MatchRef = "matchref";
/// Return the loops condition Stmt or NULL if LoopStmt is not a loop
static const Expr *getLoopCondition(const Stmt *LoopStmt) {
@@ -49,7 +55,8 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
// TODO Nested loops are currently widened as a result of the invalidation
// being so inprecise. When the invalidation is improved, the handling
// of nested loops will also need to be improved.
- const StackFrameContext *STC = LCtx->getCurrentStackFrame();
+ ASTContext &ASTCtx = LCtx->getAnalysisDeclContext()->getASTContext();
+ const StackFrameContext *STC = LCtx->getStackFrame();
MemRegionManager &MRMgr = PrevState->getStateManager().getRegionManager();
const MemRegion *Regions[] = {MRMgr.getStackLocalsRegion(STC),
MRMgr.getStackArgumentsRegion(STC),
@@ -59,6 +66,30 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
ITraits.setTrait(Region,
RegionAndSymbolInvalidationTraits::TK_EntireMemSpace);
}
+
+ // References should not be invalidated.
+ auto Matches = match(findAll(stmt(hasDescendant(varDecl(hasType(referenceType())).bind(MatchRef)))),
+ *LCtx->getDecl()->getBody(), ASTCtx);
+ for (BoundNodes Match : Matches) {
+ const VarDecl *VD = Match.getNodeAs<VarDecl>(MatchRef);
+ assert(VD);
+ const VarRegion *VarMem = MRMgr.getVarRegion(VD, LCtx);
+ ITraits.setTrait(VarMem,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents);
+ }
+
+
+ // 'this' pointer is not an lvalue, we should not invalidate it. If the loop
+ // is located in a method, constructor or destructor, the value of 'this'
+ // pointer shoule remain unchanged.
+ if (const CXXMethodDecl *CXXMD = dyn_cast<CXXMethodDecl>(STC->getDecl())) {
+ const CXXThisRegion *ThisR = MRMgr.getCXXThisRegion(
+ CXXMD->getThisType(STC->getAnalysisDeclContext()->getASTContext()),
+ STC);
+ ITraits.setTrait(ThisR,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents);
+ }
+
return PrevState->invalidateRegions(Regions, getLoopCondition(LoopStmt),
BlockCount, LCtx, true, nullptr, nullptr,
&ITraits);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index cb8ba6de3626..cb2122c7749e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1,4 +1,4 @@
-//== MemRegion.cpp - Abstract memory regions for static analysis --*- C++ -*--//
+//===- MemRegion.cpp - Abstract memory regions for static analysis --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,19 +14,51 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CheckedArithmetic.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
+#include <functional>
+#include <iterator>
+#include <string>
+#include <tuple>
+#include <utility>
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "MemRegion"
+
//===----------------------------------------------------------------------===//
// MemRegion Construction.
//===----------------------------------------------------------------------===//
@@ -37,8 +69,7 @@ RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1,
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, arg1, superRegion);
void *InsertPos;
- RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
- InsertPos));
+ auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
if (!R) {
R = A.Allocate<RegionTy>();
@@ -55,8 +86,7 @@ RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, arg1, arg2, superRegion);
void *InsertPos;
- RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
- InsertPos));
+ auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
if (!R) {
R = A.Allocate<RegionTy>();
@@ -75,8 +105,7 @@ RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
void *InsertPos;
- RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
- InsertPos));
+ auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
if (!R) {
R = A.Allocate<RegionTy>();
@@ -91,27 +120,26 @@ RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
// Object destruction.
//===----------------------------------------------------------------------===//
-MemRegion::~MemRegion() {}
+MemRegion::~MemRegion() = default;
-MemRegionManager::~MemRegionManager() {
- // All regions and their data are BumpPtrAllocated. No need to call
- // their destructors.
-}
+// All regions and their data are BumpPtrAllocated. No need to call their
+// destructors.
+MemRegionManager::~MemRegionManager() = default;
//===----------------------------------------------------------------------===//
// Basic methods.
//===----------------------------------------------------------------------===//
bool SubRegion::isSubRegionOf(const MemRegion* R) const {
- const MemRegion* r = getSuperRegion();
- while (r != nullptr) {
+ const MemRegion* r = this;
+ do {
if (r == R)
return true;
- if (const SubRegion* sr = dyn_cast<SubRegion>(r))
+ if (const auto *sr = dyn_cast<SubRegion>(r))
r = sr->getSuperRegion();
else
break;
- }
+ } while (r != nullptr);
return false;
}
@@ -119,16 +147,16 @@ MemRegionManager* SubRegion::getMemRegionManager() const {
const SubRegion* r = this;
do {
const MemRegion *superRegion = r->getSuperRegion();
- if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) {
+ if (const auto *sr = dyn_cast<SubRegion>(superRegion)) {
r = sr;
continue;
}
return superRegion->getMemRegionManager();
- } while (1);
+ } while (true);
}
const StackFrameContext *VarRegion::getStackFrame() const {
- const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
+ const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
return SSR ? SSR->getStackFrame() : nullptr;
}
@@ -215,17 +243,17 @@ void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getCodeRegion());
}
-void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const StringLiteral* Str,
- const MemRegion* superRegion) {
+void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const StringLiteral *Str,
+ const MemRegion *superRegion) {
ID.AddInteger(static_cast<unsigned>(StringRegionKind));
ID.AddPointer(Str);
ID.AddPointer(superRegion);
}
-void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const ObjCStringLiteral* Str,
- const MemRegion* superRegion) {
+void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const ObjCStringLiteral *Str,
+ const MemRegion *superRegion) {
ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind));
ID.AddPointer(Str);
ID.AddPointer(superRegion);
@@ -380,13 +408,19 @@ void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
// Region anchors.
//===----------------------------------------------------------------------===//
-void GlobalsSpaceRegion::anchor() { }
-void NonStaticGlobalSpaceRegion::anchor() { }
-void StackSpaceRegion::anchor() { }
-void TypedRegion::anchor() { }
-void TypedValueRegion::anchor() { }
-void CodeTextRegion::anchor() { }
-void SubRegion::anchor() { }
+void GlobalsSpaceRegion::anchor() {}
+
+void NonStaticGlobalSpaceRegion::anchor() {}
+
+void StackSpaceRegion::anchor() {}
+
+void TypedRegion::anchor() {}
+
+void TypedValueRegion::anchor() {}
+
+void CodeTextRegion::anchor() {}
+
+void SubRegion::anchor() {}
//===----------------------------------------------------------------------===//
// Region pretty-printing.
@@ -408,7 +442,7 @@ void MemRegion::dumpToStream(raw_ostream &os) const {
}
void AllocaRegion::dumpToStream(raw_ostream &os) const {
- os << "alloca{" << static_cast<const void*>(Ex) << ',' << Cnt << '}';
+ os << "alloca{" << static_cast<const void *>(Ex) << ',' << Cnt << '}';
}
void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
@@ -416,7 +450,7 @@ void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
}
void BlockCodeRegion::dumpToStream(raw_ostream &os) const {
- os << "block_code{" << static_cast<const void*>(this) << '}';
+ os << "block_code{" << static_cast<const void *>(this) << '}';
}
void BlockDataRegion::dumpToStream(raw_ostream &os) const {
@@ -425,19 +459,19 @@ void BlockDataRegion::dumpToStream(raw_ostream &os) const {
for (BlockDataRegion::referenced_vars_iterator
I = referenced_vars_begin(),
E = referenced_vars_end(); I != E; ++I)
- os << "(" << I.getCapturedRegion() << "," <<
+ os << "(" << I.getCapturedRegion() << "<-" <<
I.getOriginalRegion() << ") ";
os << '}';
}
void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
// FIXME: More elaborate pretty-printing.
- os << "{ " << static_cast<const void*>(CL) << " }";
+ os << "{ " << static_cast<const void *>(CL) << " }";
}
void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
os << "temp_object{" << getValueType().getAsString() << ','
- << static_cast<const void*>(Ex) << '}';
+ << static_cast<const void *>(Ex) << '}';
}
void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
@@ -478,7 +512,11 @@ void SymbolicRegion::dumpToStream(raw_ostream &os) const {
}
void VarRegion::dumpToStream(raw_ostream &os) const {
- os << *cast<VarDecl>(D);
+ const auto *VD = cast<VarDecl>(D);
+ if (const IdentifierInfo *ID = VD->getIdentifier())
+ os << ID->getName();
+ else
+ os << "VarRegion{" << static_cast<const void *>(this) << '}';
}
LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
@@ -622,19 +660,18 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
// Get variable name.
if (R && R->canPrintPrettyAsExpr()) {
R->printPrettyAsExpr(os);
- if (UseQuotes) {
+ if (UseQuotes)
return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str();
- } else {
+ else
return (llvm::Twine(os.str()) + ArrayIndices).str();
- }
}
return VariableName;
}
SourceRange MemRegion::sourceRange() const {
- const VarRegion *const VR = dyn_cast<VarRegion>(this->getBaseRegion());
- const FieldRegion *const FR = dyn_cast<FieldRegion>(this);
+ const auto *const VR = dyn_cast<VarRegion>(this->getBaseRegion());
+ const auto *const FR = dyn_cast<FieldRegion>(this);
// Check for more specific regions first.
// FieldRegion
@@ -646,9 +683,8 @@ SourceRange MemRegion::sourceRange() const {
return VR->getDecl()->getSourceRange();
}
// Return invalid source range (can be checked by client).
- else {
- return SourceRange{};
- }
+ else
+ return {};
}
//===----------------------------------------------------------------------===//
@@ -738,13 +774,14 @@ const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//
-const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){
+
+const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){
return getSubRegion<StringRegion>(
Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
}
const ObjCStringRegion *
-MemRegionManager::getObjCStringRegion(const ObjCStringLiteral* Str){
+MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){
return getSubRegion<ObjCStringRegion>(
Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
}
@@ -757,21 +794,20 @@ getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
const DeclContext *DC,
const VarDecl *VD) {
while (LC) {
- if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
+ if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) {
if (cast<DeclContext>(SFC->getDecl()) == DC)
return SFC;
}
- if (const BlockInvocationContext *BC =
- dyn_cast<BlockInvocationContext>(LC)) {
- const BlockDataRegion *BR =
- static_cast<const BlockDataRegion*>(BC->getContextData());
+ if (const auto *BC = dyn_cast<BlockInvocationContext>(LC)) {
+ const auto *BR =
+ static_cast<const BlockDataRegion *>(BC->getContextData());
// FIXME: This can be made more efficient.
for (BlockDataRegion::referenced_vars_iterator
I = BR->referenced_vars_begin(),
E = BR->referenced_vars_end(); I != E; ++I) {
- if (const VarRegion *VR = dyn_cast<VarRegion>(I.getOriginalRegion()))
- if (VR->getDecl() == VD)
- return cast<VarRegion>(I.getCapturedRegion());
+ const VarRegion *VR = I.getOriginalRegion();
+ if (VR->getDecl() == VD)
+ return cast<VarRegion>(I.getCapturedRegion());
}
}
@@ -818,7 +854,7 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
if (V.is<const VarRegion*>())
return V.get<const VarRegion*>();
- const StackFrameContext *STC = V.get<const StackFrameContext*>();
+ const auto *STC = V.get<const StackFrameContext *>();
if (!STC) {
// FIXME: Assign a more sensible memory space to static locals
@@ -836,7 +872,7 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD))
sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
getFunctionCodeRegion(cast<NamedDecl>(STCD)));
- else if (const BlockDecl *BD = dyn_cast<BlockDecl>(STCD)) {
+ else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) {
// FIXME: The fallback type here is totally bogus -- though it should
// never be queried, it will prevent uniquing with the real
// BlockCodeRegion. Ideally we'd fix the AST so that we always had a
@@ -885,7 +921,7 @@ MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
if (LC) {
// FIXME: Once we implement scope handling, we want the parent region
// to be the scope.
- const StackFrameContext *STC = LC->getCurrentStackFrame();
+ const StackFrameContext *STC = LC->getStackFrame();
assert(STC);
sReg = getStackLocalsRegion(STC);
}
@@ -913,7 +949,7 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
if (CL->isFileScope())
sReg = getGlobalsRegion();
else {
- const StackFrameContext *STC = LC->getCurrentStackFrame();
+ const StackFrameContext *STC = LC->getStackFrame();
assert(STC);
sReg = getStackLocalsRegion(STC);
}
@@ -932,7 +968,7 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
void *InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- ElementRegion* R = cast_or_null<ElementRegion>(data);
+ auto *R = cast_or_null<ElementRegion>(data);
if (!R) {
R = A.Allocate<ElementRegion>();
@@ -954,7 +990,6 @@ MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy,
return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion());
}
-
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) {
return getSubRegion<SymbolicRegion>(sym, getUnknownRegion());
@@ -979,7 +1014,7 @@ MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
const CXXTempObjectRegion*
MemRegionManager::getCXXTempObjectRegion(Expr const *E,
LocationContext const *LC) {
- const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ const StackFrameContext *SFC = LC->getStackFrame();
assert(SFC);
return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC));
}
@@ -1017,10 +1052,8 @@ MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
if (IsVirtual) {
// Virtual base regions should not be layered, since the layout rules
// are different.
- while (const CXXBaseObjectRegion *Base =
- dyn_cast<CXXBaseObjectRegion>(Super)) {
+ while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super))
Super = cast<SubRegion>(Base->getSuperRegion());
- }
assert(Super && !isa<MemSpaceRegion>(Super));
}
}
@@ -1031,7 +1064,7 @@ MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
const CXXThisRegion*
MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC) {
- const PointerType *PT = thisPointerTy->getAs<PointerType>();
+ const auto *PT = thisPointerTy->getAs<PointerType>();
assert(PT);
// Inside the body of the operator() of a lambda a this expr might refer to an
// object in one of the parent location contexts.
@@ -1045,7 +1078,7 @@ MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
LC = LC->getParent();
D = dyn_cast<CXXMethodDecl>(LC->getDecl());
}
- const StackFrameContext *STC = LC->getCurrentStackFrame();
+ const StackFrameContext *STC = LC->getStackFrame();
assert(STC);
return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
}
@@ -1053,14 +1086,14 @@ MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
const AllocaRegion*
MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
const LocationContext *LC) {
- const StackFrameContext *STC = LC->getCurrentStackFrame();
+ const StackFrameContext *STC = LC->getStackFrame();
assert(STC);
return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
}
const MemSpaceRegion *MemRegion::getMemorySpace() const {
const MemRegion *R = this;
- const SubRegion* SR = dyn_cast<SubRegion>(this);
+ const auto *SR = dyn_cast<SubRegion>(this);
while (SR) {
R = SR->getSuperRegion();
@@ -1121,7 +1154,7 @@ const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const {
while (true) {
switch (R->getKind()) {
case ElementRegionKind: {
- const ElementRegion *ER = cast<ElementRegion>(R);
+ const auto *ER = cast<ElementRegion>(R);
if (!ER->getIndex().isZeroConstant())
return R;
R = ER->getSuperRegion();
@@ -1139,10 +1172,10 @@ const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const {
}
const SymbolicRegion *MemRegion::getSymbolicBase() const {
- const SubRegion *SubR = dyn_cast<SubRegion>(this);
+ const auto *SubR = dyn_cast<SubRegion>(this);
while (SubR) {
- if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR))
+ if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR))
return SymR;
SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
}
@@ -1150,7 +1183,7 @@ const SymbolicRegion *MemRegion::getSymbolicBase() const {
}
RegionRawOffset ElementRegion::getAsArrayOffset() const {
- CharUnits offset = CharUnits::Zero();
+ int64_t offset = 0;
const ElementRegion *ER = this;
const MemRegion *superR = nullptr;
ASTContext &C = getContext();
@@ -1162,7 +1195,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
// FIXME: generalize to symbolic offsets.
SVal index = ER->getIndex();
- if (Optional<nonloc::ConcreteInt> CI = index.getAs<nonloc::ConcreteInt>()) {
+ if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
// Update the offset.
int64_t i = CI->getValue().getSExtValue();
@@ -1175,8 +1208,15 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
break;
}
- CharUnits size = C.getTypeSizeInChars(elemType);
- offset += (i * size);
+ int64_t size = C.getTypeSizeInChars(elemType).getQuantity();
+ if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
+ offset = *NewOffset;
+ } else {
+ LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
+ << "offset overflowing, returning unknown\n");
+
+ return nullptr;
+ }
}
// Go to the next ElementRegion (if any).
@@ -1188,10 +1228,9 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
}
assert(superR && "super region cannot be NULL");
- return RegionRawOffset(superR, offset);
+ return RegionRawOffset(superR, CharUnits::fromQuantity(offset));
}
-
/// Returns true if \p Base is an immediate base class of \p Child
static bool isImmediateBase(const CXXRecordDecl *Child,
const CXXRecordDecl *Base) {
@@ -1207,47 +1246,46 @@ static bool isImmediateBase(const CXXRecordDecl *Child,
return false;
}
-RegionOffset MemRegion::getAsOffset() const {
- const MemRegion *R = this;
+static RegionOffset calculateOffset(const MemRegion *R) {
const MemRegion *SymbolicOffsetBase = nullptr;
int64_t Offset = 0;
- while (1) {
+ while (true) {
switch (R->getKind()) {
- case CodeSpaceRegionKind:
- case StackLocalsSpaceRegionKind:
- case StackArgumentsSpaceRegionKind:
- case HeapSpaceRegionKind:
- case UnknownSpaceRegionKind:
- case StaticGlobalSpaceRegionKind:
- case GlobalInternalSpaceRegionKind:
- case GlobalSystemSpaceRegionKind:
- case GlobalImmutableSpaceRegionKind:
+ case MemRegion::CodeSpaceRegionKind:
+ case MemRegion::StackLocalsSpaceRegionKind:
+ case MemRegion::StackArgumentsSpaceRegionKind:
+ case MemRegion::HeapSpaceRegionKind:
+ case MemRegion::UnknownSpaceRegionKind:
+ case MemRegion::StaticGlobalSpaceRegionKind:
+ case MemRegion::GlobalInternalSpaceRegionKind:
+ case MemRegion::GlobalSystemSpaceRegionKind:
+ case MemRegion::GlobalImmutableSpaceRegionKind:
// Stores can bind directly to a region space to set a default value.
assert(Offset == 0 && !SymbolicOffsetBase);
goto Finish;
- case FunctionCodeRegionKind:
- case BlockCodeRegionKind:
- case BlockDataRegionKind:
+ case MemRegion::FunctionCodeRegionKind:
+ case MemRegion::BlockCodeRegionKind:
+ case MemRegion::BlockDataRegionKind:
// These will never have bindings, but may end up having values requested
// if the user does some strange casting.
if (Offset != 0)
SymbolicOffsetBase = R;
goto Finish;
- case SymbolicRegionKind:
- case AllocaRegionKind:
- case CompoundLiteralRegionKind:
- case CXXThisRegionKind:
- case StringRegionKind:
- case ObjCStringRegionKind:
- case VarRegionKind:
- case CXXTempObjectRegionKind:
+ case MemRegion::SymbolicRegionKind:
+ case MemRegion::AllocaRegionKind:
+ case MemRegion::CompoundLiteralRegionKind:
+ case MemRegion::CXXThisRegionKind:
+ case MemRegion::StringRegionKind:
+ case MemRegion::ObjCStringRegionKind:
+ case MemRegion::VarRegionKind:
+ case MemRegion::CXXTempObjectRegionKind:
// Usual base regions.
goto Finish;
- case ObjCIvarRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
// This is a little strange, but it's a compromise between
// ObjCIvarRegions having unknown compile-time offsets (when using the
// non-fragile runtime) and yet still being distinct, non-overlapping
@@ -1255,15 +1293,15 @@ RegionOffset MemRegion::getAsOffset() const {
// of computing offsets.
goto Finish;
- case CXXBaseObjectRegionKind: {
- const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R);
+ case MemRegion::CXXBaseObjectRegionKind: {
+ const auto *BOR = cast<CXXBaseObjectRegion>(R);
R = BOR->getSuperRegion();
QualType Ty;
bool RootIsSymbolic = false;
- if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R)) {
- Ty = TVR->getDesugaredValueType(getContext());
- } else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+ if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) {
+ Ty = TVR->getDesugaredValueType(R->getContext());
+ } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
// If our base region is symbolic, we don't know what type it really is.
// Pretend the type of the symbol is the true dynamic type.
// (This will at least be self-consistent for the life of the symbol.)
@@ -1296,18 +1334,18 @@ RegionOffset MemRegion::getAsOffset() const {
continue;
CharUnits BaseOffset;
- const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);
+ const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child);
if (BOR->isVirtual())
BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl());
else
BaseOffset = Layout.getBaseClassOffset(BOR->getDecl());
// The base offset is in chars, not in bits.
- Offset += BaseOffset.getQuantity() * getContext().getCharWidth();
+ Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
break;
}
- case ElementRegionKind: {
- const ElementRegion *ER = cast<ElementRegion>(R);
+ case MemRegion::ElementRegionKind: {
+ const auto *ER = cast<ElementRegion>(R);
R = ER->getSuperRegion();
QualType EleTy = ER->getValueType();
@@ -1327,15 +1365,15 @@ RegionOffset MemRegion::getAsOffset() const {
int64_t i = CI->getValue().getSExtValue();
// This type size is in bits.
- Offset += i * getContext().getTypeSize(EleTy);
+ Offset += i * R->getContext().getTypeSize(EleTy);
} else {
// We cannot compute offset for non-concrete index.
SymbolicOffsetBase = R;
}
break;
}
- case FieldRegionKind: {
- const FieldRegion *FR = cast<FieldRegion>(R);
+ case MemRegion::FieldRegionKind: {
+ const auto *FR = cast<FieldRegion>(R);
R = FR->getSuperRegion();
const RecordDecl *RD = FR->getDecl()->getParent();
@@ -1360,7 +1398,7 @@ RegionOffset MemRegion::getAsOffset() const {
if (FR->getDecl() == *FI)
break;
}
- const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+ const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD);
// This is offset in bits.
Offset += Layout.getFieldOffset(idx);
break;
@@ -1374,6 +1412,12 @@ RegionOffset MemRegion::getAsOffset() const {
return RegionOffset(R, Offset);
}
+RegionOffset MemRegion::getAsOffset() const {
+ if (!cachedOffset)
+ cachedOffset = calculateOffset(this);
+ return *cachedOffset;
+}
+
//===----------------------------------------------------------------------===//
// BlockDataRegion
//===----------------------------------------------------------------------===//
@@ -1419,13 +1463,14 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
BumpVectorContext BC(A);
- typedef BumpVector<const MemRegion*> VarVec;
- VarVec *BV = A.Allocate<VarVec>();
+ using VarVec = BumpVector<const MemRegion *>;
+
+ auto *BV = A.Allocate<VarVec>();
new (BV) VarVec(BC, NumBlockVars);
- VarVec *BVOriginal = A.Allocate<VarVec>();
+ auto *BVOriginal = A.Allocate<VarVec>();
new (BVOriginal) VarVec(BC, NumBlockVars);
- for (const VarDecl *VD : ReferencedBlockVars) {
+ for (const auto *VD : ReferencedBlockVars) {
const VarRegion *VR = nullptr;
const VarRegion *OriginalVR = nullptr;
std::tie(VR, OriginalVR) = getCaptureRegions(VD);
@@ -1443,14 +1488,13 @@ BlockDataRegion::referenced_vars_iterator
BlockDataRegion::referenced_vars_begin() const {
const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
- BumpVector<const MemRegion*> *Vec =
- static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
+ auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
if (Vec == (void*) 0x1)
return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
- BumpVector<const MemRegion*> *VecOriginal =
- static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
+ auto *VecOriginal =
+ static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
VecOriginal->begin());
@@ -1460,14 +1504,13 @@ BlockDataRegion::referenced_vars_iterator
BlockDataRegion::referenced_vars_end() const {
const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
- BumpVector<const MemRegion*> *Vec =
- static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
+ auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
if (Vec == (void*) 0x1)
return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
- BumpVector<const MemRegion*> *VecOriginal =
- static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
+ auto *VecOriginal =
+ static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
return BlockDataRegion::referenced_vars_iterator(Vec->end(),
VecOriginal->end());
@@ -1495,7 +1538,7 @@ void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
InvalidationKinds IK) {
assert(MR);
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
setTrait(SR->getSymbol(), IK);
else
MRTraitsMap[MR] |= IK;
@@ -1515,7 +1558,7 @@ bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR,
if (!MR)
return false;
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
return hasTrait(SR->getSymbol(), IK);
const_region_iterator I = MRTraitsMap.find(MR);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 669748c0127a..1b698ec5c086 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -1,4 +1,4 @@
-//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===//
+//===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,26 +13,52 @@
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.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/ExprCXX.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/ParentMap.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
bool PathDiagnosticMacroPiece::containsEvent() const {
- for (auto &P : subPieces) {
+ for (const auto &P : subPieces) {
if (isa<PathDiagnosticEventPiece>(*P))
return true;
- if (auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
+ if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
if (MP->containsEvent())
return true;
}
@@ -43,23 +69,27 @@ static StringRef StripTrailingDots(StringRef s) {
for (StringRef::size_type i = s.size(); i != 0; --i)
if (s[i - 1] != '.')
return s.substr(0, i);
- return "";
+ return {};
}
PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
Kind k, DisplayHint hint)
- : str(StripTrailingDots(s)), kind(k), Hint(hint),
- LastInMainSourceFile(false) {}
+ : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
- : kind(k), Hint(hint), LastInMainSourceFile(false) {}
+ : kind(k), Hint(hint) {}
-PathDiagnosticPiece::~PathDiagnosticPiece() {}
-PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
-PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
-PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
-PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
-PathDiagnosticNotePiece::~PathDiagnosticNotePiece() {}
+PathDiagnosticPiece::~PathDiagnosticPiece() = default;
+
+PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
+
+PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
+
+PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
+
+PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
+
+PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const {
@@ -96,22 +126,20 @@ void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
}
}
-PathDiagnostic::~PathDiagnostic() {}
-
-PathDiagnostic::PathDiagnostic(StringRef CheckName, const Decl *declWithIssue,
- StringRef bugtype, StringRef verboseDesc,
- StringRef shortDesc, StringRef category,
- PathDiagnosticLocation LocationToUnique,
- const Decl *DeclToUnique)
- : CheckName(CheckName),
- DeclWithIssue(declWithIssue),
- BugType(StripTrailingDots(bugtype)),
- VerboseDesc(StripTrailingDots(verboseDesc)),
- ShortDesc(StripTrailingDots(shortDesc)),
- Category(StripTrailingDots(category)),
- UniqueingLoc(LocationToUnique),
- UniqueingDecl(DeclToUnique),
- path(pathImpl) {}
+PathDiagnostic::~PathDiagnostic() = default;
+
+PathDiagnostic::PathDiagnostic(
+ StringRef CheckName, const Decl *declWithIssue, StringRef bugtype,
+ StringRef verboseDesc, StringRef shortDesc, StringRef category,
+ PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
+ std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
+ : CheckName(CheckName), DeclWithIssue(declWithIssue),
+ BugType(StripTrailingDots(bugtype)),
+ VerboseDesc(StripTrailingDots(verboseDesc)),
+ ShortDesc(StripTrailingDots(shortDesc)),
+ Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
+ UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
+ path(pathImpl) {}
static PathDiagnosticCallPiece *
getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
@@ -122,11 +150,11 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
if (CallLoc.isMacroID())
return nullptr;
- assert(SMgr.isInMainFile(CallLoc) &&
- "The call piece should be in the main file.");
+ assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) &&
+ "The call piece should not be in a header file.");
// Check if CP represents a path through a function outside of the main file.
- if (!SMgr.isInMainFile(CP->callEnterWithin.asLocation()))
+ if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr))
return CP;
const PathPieces &Path = CP->path;
@@ -135,10 +163,8 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
// Check if the last piece in the callee path is a call to a function outside
// of the main file.
- if (PathDiagnosticCallPiece *CPInner =
- dyn_cast<PathDiagnosticCallPiece>(Path.back().get())) {
+ if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
return getFirstStackedCallToHeaderFile(CPInner, SMgr);
- }
// Otherwise, the last piece is in the main file.
return nullptr;
@@ -154,14 +180,14 @@ void PathDiagnostic::resetDiagnosticLocationToMainFile() {
// We only need to check if the report ends inside headers, if the last piece
// is a call piece.
- if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
+ if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
CP = getFirstStackedCallToHeaderFile(CP, SMgr);
if (CP) {
// Mark the piece.
CP->setAsLastInMainSourceFile();
// Update the path diagnostic message.
- const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee());
+ const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
if (ND) {
SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
@@ -178,14 +204,12 @@ void PathDiagnostic::resetDiagnosticLocationToMainFile() {
}
}
-void PathDiagnosticConsumer::anchor() { }
+void PathDiagnosticConsumer::anchor() {}
PathDiagnosticConsumer::~PathDiagnosticConsumer() {
// Delete the contents of the FoldingSet if it isn't empty already.
- for (llvm::FoldingSet<PathDiagnostic>::iterator it =
- Diags.begin(), et = Diags.end() ; it != et ; ++it) {
- delete &*it;
- }
+ for (auto &Diag : Diags)
+ delete &Diag;
}
void PathDiagnosticConsumer::HandlePathDiagnostic(
@@ -216,9 +240,8 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
while (!WorkList.empty()) {
const PathPieces &path = *WorkList.pop_back_val();
- for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
- ++I) {
- const PathDiagnosticPiece *piece = I->get();
+ for (const auto &I : path) {
+ const PathDiagnosticPiece *piece = I.get();
FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
@@ -230,28 +253,23 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
// Check the source ranges.
ArrayRef<SourceRange> Ranges = piece->getRanges();
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
+ for (const auto &I : Ranges) {
+ SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
if (!L.isFileID() || SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
- L = SMgr.getExpansionLoc(I->getEnd());
+ L = SMgr.getExpansionLoc(I.getEnd());
if (!L.isFileID() || SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
}
- if (const PathDiagnosticCallPiece *call =
- dyn_cast<PathDiagnosticCallPiece>(piece)) {
+ if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
WorkList.push_back(&call->path);
- }
- else if (const PathDiagnosticMacroPiece *macro =
- dyn_cast<PathDiagnosticMacroPiece>(piece)) {
+ else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
WorkList.push_back(&macro->subPieces);
- }
}
}
@@ -381,11 +399,29 @@ static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
return None;
}
+static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
+ std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
+ std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
+ const SourceManager &SM = XL.getManager();
+ std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
+ if (InSameTU.first)
+ return XL.isBeforeInTranslationUnitThan(YL);
+ const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
+ const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
+ if (!XFE || !YFE)
+ return XFE && !YFE;
+ int NameCmp = XFE->getName().compare(YFE->getName());
+ if (NameCmp != 0)
+ return NameCmp == -1;
+ // Last resort: Compare raw file IDs that are possibly expansions.
+ return XL.getFileID() < YL.getFileID();
+}
+
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
FullSourceLoc XL = X.getLocation().asLocation();
FullSourceLoc YL = Y.getLocation().asLocation();
if (XL != YL)
- return XL.isBeforeInTranslationUnitThan(YL);
+ return compareCrossTUSourceLocs(XL, YL);
if (X.getBugType() != Y.getBugType())
return X.getBugType() < Y.getBugType();
if (X.getCategory() != Y.getCategory())
@@ -405,7 +441,8 @@ static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
SourceLocation YDL = YD->getLocation();
if (XDL != YDL) {
const SourceManager &SM = XL.getManager();
- return SM.isBeforeInTranslationUnit(XDL, YDL);
+ return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
+ FullSourceLoc(YDL, SM));
}
}
PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
@@ -429,11 +466,8 @@ void PathDiagnosticConsumer::FlushDiagnostics(
flushed = true;
std::vector<const PathDiagnostic *> BatchDiags;
- for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
- et = Diags.end(); it != et; ++it) {
- const PathDiagnostic *D = &*it;
- BatchDiags.push_back(D);
- }
+ for (const auto &D : Diags)
+ BatchDiags.push_back(&D);
// Sort the diagnostics so that they are always emitted in a deterministic
// order.
@@ -450,11 +484,8 @@ void PathDiagnosticConsumer::FlushDiagnostics(
FlushDiagnosticsImpl(BatchDiags, Files);
// Delete the flushed diagnostics.
- for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
- et = BatchDiags.end(); it != et; ++it) {
- const PathDiagnostic *D = *it;
+ for (const auto D : BatchDiags)
delete D;
- }
// Clear out the FoldingSet.
Diags.clear();
@@ -553,6 +584,8 @@ getLocationForCaller(const StackFrameContext *SFC,
switch (Source.getKind()) {
case CFGElement::Statement:
+ case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
SM, CallerCtx);
case CFGElement::Initializer: {
@@ -576,8 +609,20 @@ getLocationForCaller(const StackFrameContext *SFC,
return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
}
- case CFGElement::TemporaryDtor:
- case CFGElement::NewAllocator:
+ case CFGElement::NewAllocator: {
+ const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
+ return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
+ }
+ case CFGElement::TemporaryDtor: {
+ // Temporary destructors are for temporaries. They die immediately at around
+ // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
+ // they'd be dealt with via an AutomaticObjectDtor instead.
+ const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
+ return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
+ CallerCtx);
+ }
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
llvm_unreachable("not yet implemented!");
case CFGElement::LifetimeEnds:
case CFGElement::LoopExit:
@@ -605,7 +650,7 @@ PathDiagnosticLocation
PathDiagnosticLocation::createEnd(const Stmt *S,
const SourceManager &SM,
LocationOrAnalysisDeclContext LAC) {
- if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
+ if (const auto *CS = dyn_cast<CompoundStmt>(S))
return createEndBrace(CS, SM);
return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
SM, SingleLocK);
@@ -624,7 +669,6 @@ PathDiagnosticLocation::createConditionalColonLoc(
return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
}
-
PathDiagnosticLocation
PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
const SourceManager &SM) {
@@ -649,8 +693,7 @@ PathDiagnosticLocation
PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
const SourceManager &SM) {
// FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
- if (const CompoundStmt *CS =
- dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
+ if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
if (!CS->body_empty()) {
SourceLocation Loc = (*CS->body_begin())->getLocStart();
return PathDiagnosticLocation(Loc, SM, SingleLocK);
@@ -741,6 +784,8 @@ const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
return CEE->getCalleeContext()->getCallSite();
if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
return PIPP->getInitializer()->getInit();
+ if (Optional<CallExitBegin> CEB = P.getAs<CallExitBegin>())
+ return CEB->getReturnStmt();
return nullptr;
}
@@ -790,11 +835,11 @@ PathDiagnosticLocation
const LocationContext *LC = N->getLocationContext();
// For member expressions, return the location of the '.' or '->'.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
+ if (const auto *ME = dyn_cast<MemberExpr>(S))
return PathDiagnosticLocation::createMemberLoc(ME, SM);
// For binary operators, return the location of the operator.
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+ if (const auto *B = dyn_cast<BinaryOperator>(S))
return PathDiagnosticLocation::createOperatorLoc(B, SM);
if (P.getAs<PostStmtPurgeDeadSymbols>())
@@ -856,7 +901,7 @@ PathDiagnosticRange
default:
break;
case Stmt::DeclStmtClass: {
- const DeclStmt *DS = cast<DeclStmt>(S);
+ const auto *DS = cast<DeclStmt>(S);
if (DS->isSingleDecl()) {
// Should always be the case, but we'll be defensive.
return SourceRange(DS->getLocStart(),
@@ -886,9 +931,9 @@ PathDiagnosticRange
break;
}
case DeclK:
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getSourceRange();
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (Stmt *Body = FD->getBody())
return Body->getSourceRange();
}
@@ -898,7 +943,7 @@ PathDiagnosticRange
}
}
- return SourceRange(Loc,Loc);
+ return SourceRange(Loc, Loc);
}
void PathDiagnosticLocation::flatten() {
@@ -954,17 +999,55 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
// non-autosynthesized callbacks.
// Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
// defaults to false.
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
IsCalleeAnAutosynthesizedPropertyAccessor = (
MD->isPropertyAccessor() &&
CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
}
-static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
- StringRef Prefix = StringRef()) {
+static void describeTemplateParameters(raw_ostream &Out,
+ const ArrayRef<TemplateArgument> TAList,
+ const LangOptions &LO,
+ StringRef Prefix = StringRef(),
+ StringRef Postfix = StringRef());
+
+static void describeTemplateParameter(raw_ostream &Out,
+ const TemplateArgument &TArg,
+ const LangOptions &LO) {
+
+ if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
+ describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
+ } else {
+ TArg.print(PrintingPolicy(LO), Out);
+ }
+}
+
+static void describeTemplateParameters(raw_ostream &Out,
+ const ArrayRef<TemplateArgument> TAList,
+ const LangOptions &LO,
+ StringRef Prefix, StringRef Postfix) {
+ if (TAList.empty())
+ return;
+
+ Out << Prefix;
+ for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
+ describeTemplateParameter(Out, TAList[I], LO);
+ Out << ", ";
+ }
+ describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
+ Out << Postfix;
+}
+
+static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
+ StringRef Prefix = StringRef()) {
if (!D->getIdentifier())
return;
- Out << Prefix << '\'' << *D << '\'';
+ Out << Prefix << '\'' << *D;
+ if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
+ D->getASTContext().getLangOpts(), "<", ">");
+
+ Out << '\'';
}
static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
@@ -979,7 +1062,7 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
return ExtendedDescription;
}
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
Out << Prefix;
if (ExtendedDescription && !MD->isUserProvided()) {
if (MD->isExplicitlyDefaulted())
@@ -988,7 +1071,7 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
Out << "implicit ";
}
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
if (CD->isDefaultConstructor())
Out << "default ";
else if (CD->isCopyConstructor())
@@ -998,7 +1081,6 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
Out << "constructor";
describeClass(Out, MD->getParent(), " for ");
-
} else if (isa<CXXDestructorDecl>(MD)) {
if (!MD->isUserProvided()) {
Out << "destructor";
@@ -1007,15 +1089,12 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
// Use ~Foo for explicitly-written destructors.
Out << "'" << *MD << "'";
}
-
} else if (MD->isCopyAssignmentOperator()) {
Out << "copy assignment operator";
describeClass(Out, MD->getParent(), " for ");
-
} else if (MD->isMoveAssignmentOperator()) {
Out << "move assignment operator";
describeClass(Out, MD->getParent(), " for ");
-
} else {
if (MD->getParent()->getIdentifier())
Out << "'" << *MD->getParent() << "::" << *MD << "'";
@@ -1026,7 +1105,16 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
return true;
}
- Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
+ Out << Prefix << '\'' << cast<NamedDecl>(*D);
+
+ // Adding template parameters.
+ if (const auto FD = dyn_cast<FunctionDecl>(D))
+ if (const TemplateArgumentList *TAList =
+ FD->getTemplateSpecializationArgs())
+ describeTemplateParameters(Out, TAList->asArray(),
+ FD->getASTContext().getLangOpts(), "<", ">");
+
+ Out << '\'';
return true;
}
@@ -1055,7 +1143,7 @@ PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
return nullptr;
if (Callee->isImplicit() || !Callee->hasBody())
return nullptr;
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
if (MD->isDefaulted())
return nullptr;
@@ -1095,13 +1183,10 @@ PathDiagnosticCallPiece::getCallExitEvent() const {
}
static void compute_path_size(const PathPieces &pieces, unsigned &size) {
- for (PathPieces::const_iterator it = pieces.begin(),
- et = pieces.end(); it != et; ++it) {
- const PathDiagnosticPiece *piece = it->get();
- if (const PathDiagnosticCallPiece *cp =
- dyn_cast<PathDiagnosticCallPiece>(piece)) {
+ for (const auto &I : pieces) {
+ const PathDiagnosticPiece *piece = I.get();
+ if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
compute_path_size(cp->path, size);
- }
else
++size;
}
@@ -1129,19 +1214,16 @@ void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
// FIXME: Add profiling support for code hints.
ID.AddInteger((unsigned) getDisplayHint());
ArrayRef<SourceRange> Ranges = getRanges();
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
- I != E; ++I) {
- ID.AddInteger(I->getBegin().getRawEncoding());
- ID.AddInteger(I->getEnd().getRawEncoding());
+ for (const auto &I : Ranges) {
+ ID.AddInteger(I.getBegin().getRawEncoding());
+ ID.AddInteger(I.getEnd().getRawEncoding());
}
}
void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticPiece::Profile(ID);
- for (PathPieces::const_iterator it = path.begin(),
- et = path.end(); it != et; ++it) {
- ID.Add(**it);
- }
+ for (const auto &I : path)
+ ID.Add(*I);
}
void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
@@ -1151,15 +1233,14 @@ void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticPiece::Profile(ID);
- for (const_iterator I = begin(), E = end(); I != E; ++I)
- ID.Add(*I);
+ for (const auto &I : *this)
+ ID.Add(I);
}
void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticSpotPiece::Profile(ID);
- for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
- I != E; ++I)
- ID.Add(**I);
+ for (const auto &I : subPieces)
+ ID.Add(*I);
}
void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
@@ -1175,34 +1256,32 @@ void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
Profile(ID);
- for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
- ID.Add(**I);
+ for (const auto &I : path)
+ ID.Add(*I);
for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
ID.AddString(*I);
}
-StackHintGenerator::~StackHintGenerator() {}
+StackHintGenerator::~StackHintGenerator() = default;
std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
+ if (!N)
+ return getMessageForSymbolNotFound();
+
ProgramPoint P = N->getLocation();
CallExitEnd CExit = P.castAs<CallExitEnd>();
// FIXME: Use CallEvent to abstract this over all calls.
const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
- const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
+ const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
if (!CE)
- return "";
-
- if (!N)
- return getMessageForSymbolNotFound();
+ return {};
// Check if one of the parameters are set to the interesting symbol.
- ProgramStateRef State = N->getState();
- const LocationContext *LCtx = N->getLocationContext();
unsigned ArgIndex = 0;
for (CallExpr::const_arg_iterator I = CE->arg_begin(),
E = CE->arg_end(); I != E; ++I, ++ArgIndex){
- SVal SV = State->getSVal(*I, LCtx);
+ SVal SV = N->getSVal(*I);
// Check if the variable corresponding to the symbol is passed by value.
SymbolRef AS = SV.getAsLocSymbol();
@@ -1212,7 +1291,10 @@ std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
// Check if the parameter is a pointer to the symbol.
if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
- SVal PSV = State->getSVal(Reg->getRegion());
+ // Do not attempt to dereference void*.
+ if ((*I)->getType()->isVoidPointerType())
+ continue;
+ SVal PSV = N->getState()->getSVal(Reg->getRegion());
SymbolRef AS = PSV.getAsLocSymbol();
if (AS == Sym) {
return getMessageForArg(*I, ArgIndex);
@@ -1221,7 +1303,7 @@ std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
}
// Check if we are returning the interesting symbol.
- SVal SV = State->getSVal(CE, LCtx);
+ SVal SV = N->getSVal(CE);
SymbolRef RetSym = SV.getAsLocSymbol();
if (RetSym == Sym) {
return getMessageForReturn(CE);
@@ -1243,3 +1325,84 @@ std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
return os.str();
}
+
+LLVM_DUMP_METHOD void PathPieces::dump() const {
+ unsigned index = 0;
+ for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
+ llvm::errs() << "[" << index++ << "] ";
+ (*I)->dump();
+ llvm::errs() << "\n";
+ }
+}
+
+LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
+ llvm::errs() << "CALL\n--------------\n";
+
+ if (const Stmt *SLoc = getLocation().getStmtOrNull())
+ SLoc->dump();
+ else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
+ llvm::errs() << *ND << "\n";
+ else
+ getLocation().dump();
+}
+
+LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
+ llvm::errs() << "EVENT\n--------------\n";
+ llvm::errs() << getString() << "\n";
+ llvm::errs() << " ---- at ----\n";
+ getLocation().dump();
+}
+
+LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
+ llvm::errs() << "CONTROL\n--------------\n";
+ getStartLocation().dump();
+ llvm::errs() << " ---- to ----\n";
+ getEndLocation().dump();
+}
+
+LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
+ llvm::errs() << "MACRO\n--------------\n";
+ // FIXME: Print which macro is being invoked.
+}
+
+LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
+ llvm::errs() << "NOTE\n--------------\n";
+ llvm::errs() << getString() << "\n";
+ llvm::errs() << " ---- at ----\n";
+ getLocation().dump();
+}
+
+LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
+ if (!isValid()) {
+ llvm::errs() << "<INVALID>\n";
+ return;
+ }
+
+ switch (K) {
+ case RangeK:
+ // FIXME: actually print the range.
+ llvm::errs() << "<range>\n";
+ break;
+ case SingleLocK:
+ asLocation().dump();
+ llvm::errs() << "\n";
+ break;
+ case StmtK:
+ if (S)
+ S->dump();
+ else
+ llvm::errs() << "<NULL STMT>\n";
+ break;
+ case DeclK:
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
+ llvm::errs() << *ND << "\n";
+ else if (isa<BlockDecl>(D))
+ // FIXME: Make this nicer.
+ llvm::errs() << "<block>\n";
+ else if (D)
+ llvm::errs() << "<unknown decl>\n";
+ else
+ llvm::errs() << "<NULL DECL>\n";
+ break;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 66812ed8ff5b..cfe780db9ec9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -16,9 +16,12 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/Core/HTMLRewrite.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
using namespace clang;
@@ -30,6 +33,7 @@ namespace {
const std::string OutputFile;
const LangOptions &LangOpts;
const bool SupportsCrossFileDiagnostics;
+ const bool SerializeStatistics;
public:
PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
const std::string& prefix,
@@ -61,7 +65,8 @@ PlistDiagnostics::PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
bool supportsMultipleFiles)
: OutputFile(output),
LangOpts(LO),
- SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
+ SupportsCrossFileDiagnostics(supportsMultipleFiles),
+ SerializeStatistics(AnalyzerOpts.shouldSerializeStats()) {}
void ento::createPlistDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
PathDiagnosticConsumers &C,
@@ -79,6 +84,41 @@ void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
PP.getLangOpts(), true));
}
+static void EmitRanges(raw_ostream &o,
+ const ArrayRef<SourceRange> Ranges,
+ const FIDMap& FM,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ unsigned indent) {
+
+ if (Ranges.empty())
+ return;
+
+ Indent(o, indent) << "<key>ranges</key>\n";
+ Indent(o, indent) << "<array>\n";
+ ++indent;
+ for (auto &R : Ranges)
+ EmitRange(o, SM,
+ Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts),
+ FM, indent + 1);
+ --indent;
+ Indent(o, indent) << "</array>\n";
+}
+
+static void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent) {
+ // Output the text.
+ assert(!Message.empty());
+ Indent(o, indent) << "<key>extended_message</key>\n";
+ Indent(o, indent);
+ EmitString(o, Message) << '\n';
+
+ // Output the short text.
+ // FIXME: Really use a short string.
+ Indent(o, indent) << "<key>message</key>\n";
+ Indent(o, indent);
+ EmitString(o, Message) << '\n';
+}
+
static void ReportControlFlow(raw_ostream &o,
const PathDiagnosticControlFlowPiece& P,
const FIDMap& FM,
@@ -133,7 +173,7 @@ static void ReportControlFlow(raw_ostream &o,
Indent(o, indent) << "</dict>\n";
}
-static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
+static void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
const FIDMap& FM,
const SourceManager &SM,
const LangOptions &LangOpts,
@@ -158,34 +198,14 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
// Output the ranges (if any).
ArrayRef<SourceRange> Ranges = P.getRanges();
-
- if (!Ranges.empty()) {
- Indent(o, indent) << "<key>ranges</key>\n";
- Indent(o, indent) << "<array>\n";
- ++indent;
- for (auto &R : Ranges)
- EmitRange(o, SM,
- Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts),
- FM, indent + 1);
- --indent;
- Indent(o, indent) << "</array>\n";
- }
+ EmitRanges(o, Ranges, FM, SM, LangOpts, indent);
// Output the call depth.
Indent(o, indent) << "<key>depth</key>";
EmitInteger(o, depth) << '\n';
// Output the text.
- assert(!P.getString().empty());
- Indent(o, indent) << "<key>extended_message</key>\n";
- Indent(o, indent);
- EmitString(o, P.getString()) << '\n';
-
- // Output the short text.
- // FIXME: Really use a short string.
- Indent(o, indent) << "<key>message</key>\n";
- Indent(o, indent);
- EmitString(o, P.getString()) << '\n';
+ EmitMessage(o, P.getString(), indent);
// Finish up.
--indent;
@@ -241,6 +261,34 @@ static void ReportMacro(raw_ostream &o,
}
}
+static void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
+ const FIDMap& FM,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ unsigned indent,
+ unsigned depth) {
+
+ Indent(o, indent) << "<dict>\n";
+ ++indent;
+
+ // Output the location.
+ FullSourceLoc L = P.getLocation().asLocation();
+
+ Indent(o, indent) << "<key>location</key>\n";
+ EmitLocation(o, SM, L, FM, indent);
+
+ // Output the ranges (if any).
+ ArrayRef<SourceRange> Ranges = P.getRanges();
+ EmitRanges(o, Ranges, FM, SM, LangOpts, indent);
+
+ // Output the text.
+ EmitMessage(o, P.getString(), indent);
+
+ // Finish up.
+ --indent;
+ Indent(o, indent); o << "</dict>\n";
+}
+
static void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P,
const FIDMap& FM, const SourceManager &SM,
const LangOptions &LangOpts) {
@@ -266,7 +314,7 @@ static void ReportPiece(raw_ostream &o,
indent, depth);
break;
case PathDiagnosticPiece::Event:
- ReportEvent(o, cast<PathDiagnosticSpotPiece>(P), FM, SM, LangOpts,
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
indent, depth, isKeyEvent);
break;
case PathDiagnosticPiece::Macro:
@@ -274,7 +322,8 @@ static void ReportPiece(raw_ostream &o,
indent, depth);
break;
case PathDiagnosticPiece::Note:
- // FIXME: Extend the plist format to support those.
+ ReportNote(o, cast<PathDiagnosticNotePiece>(P), FM, SM, LangOpts,
+ indent, depth);
break;
}
}
@@ -359,15 +408,39 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
DE = Diags.end(); DI!=DE; ++DI) {
- o << " <dict>\n"
- " <key>path</key>\n";
+ o << " <dict>\n";
const PathDiagnostic *D = *DI;
+ const PathPieces &PP = D->path;
+
+ assert(std::is_partitioned(
+ PP.begin(), PP.end(),
+ [](const std::shared_ptr<PathDiagnosticPiece> &E)
+ { return E->getKind() == PathDiagnosticPiece::Note; }) &&
+ "PathDiagnostic is not partitioned so that notes precede the rest");
+
+ PathPieces::const_iterator FirstNonNote = std::partition_point(
+ PP.begin(), PP.end(),
+ [](const std::shared_ptr<PathDiagnosticPiece> &E)
+ { return E->getKind() == PathDiagnosticPiece::Note; });
+
+ PathPieces::const_iterator I = PP.begin();
+
+ if (FirstNonNote != PP.begin()) {
+ o << " <key>notes</key>\n"
+ " <array>\n";
+
+ for (; I != FirstNonNote; ++I)
+ ReportDiag(o, **I, FM, *SM, LangOpts);
+
+ o << " </array>\n";
+ }
+
+ o << " <key>path</key>\n";
o << " <array>\n";
- for (PathPieces::const_iterator I = D->path.begin(), E = D->path.end();
- I != E; ++I)
+ for (PathPieces::const_iterator E = PP.end(); I != E; ++I)
ReportDiag(o, **I, FM, *SM, LangOpts);
o << " </array>\n";
@@ -484,6 +557,15 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " </array>\n";
+ if (llvm::AreStatisticsEnabled() && SerializeStatistics) {
+ o << " <key>statistics</key>\n";
+ std::string stats;
+ llvm::raw_string_ostream os(stats);
+ llvm::PrintStatisticsJSON(os);
+ os.flush();
+ EmitString(o, html::EscapeText(stats)) << '\n';
+ }
+
// Finish.
o << "</dict>\n</plist>";
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 5b6b7339697f..94e2e00d8bbc 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -11,12 +11,14 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/Analysis/CFG.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -125,16 +127,27 @@ ProgramStateRef ProgramState::bindLoc(Loc LV,
return newState;
}
-ProgramStateRef ProgramState::bindDefault(SVal loc,
- SVal V,
- const LocationContext *LCtx) const {
+ProgramStateRef
+ProgramState::bindDefaultInitial(SVal loc, SVal V,
+ const LocationContext *LCtx) const {
+ ProgramStateManager &Mgr = getStateManager();
+ const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
+ const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
+ ProgramStateRef new_state = makeWithStore(newStore);
+ return Mgr.getOwningEngine()
+ ? Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx)
+ : new_state;
+}
+
+ProgramStateRef
+ProgramState::bindDefaultZero(SVal loc, const LocationContext *LCtx) const {
ProgramStateManager &Mgr = getStateManager();
const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
- const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V);
+ const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
ProgramStateRef new_state = makeWithStore(newStore);
- return Mgr.getOwningEngine() ?
- Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx) :
- new_state;
+ return Mgr.getOwningEngine()
+ ? Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx)
+ : new_state;
}
typedef ArrayRef<const MemRegion *> RegionList;
@@ -254,7 +267,7 @@ SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {
}
SVal ProgramState::getSVal(Loc location, QualType T) const {
- SVal V = getRawSVal(cast<Loc>(location), T);
+ SVal V = getRawSVal(location, T);
// If 'V' is a symbolic value that is *perfectly* constrained to
// be a constant value, use that value instead to lessen the burden
@@ -324,9 +337,8 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
// Get the offset: the minimum value of the array index type.
BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
- // FIXME: This should be using ValueManager::ArrayindexTy...somehow.
if (indexTy.isNull())
- indexTy = Ctx.IntTy;
+ indexTy = svalBuilder.getArrayIndexType();
nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
// Adjust the index.
@@ -354,6 +366,17 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
}
+ConditionTruthVal ProgramState::isNonNull(SVal V) const {
+ ConditionTruthVal IsNull = isNull(V);
+ if (IsNull.isUnderconstrained())
+ return IsNull;
+ return ConditionTruthVal(!IsNull.getValue());
+}
+
+ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
+ return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
+}
+
ConditionTruthVal ProgramState::isNull(SVal V) const {
if (V.isZeroConstant())
return true;
@@ -426,24 +449,30 @@ void ProgramState::setStore(const StoreRef &newStore) {
// State pretty-printing.
//===----------------------------------------------------------------------===//
-void ProgramState::print(raw_ostream &Out,
- const char *NL, const char *Sep) const {
+void ProgramState::print(raw_ostream &Out, const char *NL, const char *Sep,
+ const LocationContext *LC) const {
// Print the store.
ProgramStateManager &Mgr = getStateManager();
Mgr.getStoreManager().print(getStore(), Out, NL, Sep);
// Print out the environment.
- Env.print(Out, NL, Sep);
+ Env.print(Out, NL, Sep, LC);
// Print out the constraints.
Mgr.getConstraintManager().print(this, Out, NL, Sep);
+ // Print out the tracked dynamic types.
+ printDynamicTypeInfo(this, Out, NL, Sep);
+
+ // Print out tainted symbols.
+ printTaint(Out, NL, Sep);
+
// Print checker-specific data.
- Mgr.getOwningEngine()->printState(Out, this, NL, Sep);
+ Mgr.getOwningEngine()->printState(Out, this, NL, Sep, LC);
}
-void ProgramState::printDOT(raw_ostream &Out) const {
- print(Out, "\\l", "\\|");
+void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LC) const {
+ print(Out, "\\l", "\\|", LC);
}
LLVM_DUMP_METHOD void ProgramState::dump() const {
@@ -455,7 +484,7 @@ void ProgramState::printTaint(raw_ostream &Out,
TaintMapImpl TM = get<TaintMap>();
if (!TM.isEmpty())
- Out <<"Tainted Symbols:" << NL;
+ Out <<"Tainted symbols:" << NL;
for (TaintMapImpl::iterator I = TM.begin(), E = TM.end(); I != E; ++I) {
Out << I->first << " : " << I->second << NL;
@@ -466,6 +495,10 @@ void ProgramState::dumpTaint() const {
printTaint(llvm::errs());
}
+AnalysisManager& ProgramState::getAnalysisManager() const {
+ return stateMgr->getOwningEngine()->getAnalysisManager();
+}
+
//===----------------------------------------------------------------------===//
// Generic Data Map.
//===----------------------------------------------------------------------===//
@@ -781,8 +814,7 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
// complete. For example, this would not currently identify
// overlapping fields in a union as tainted. To identify this we can
// check for overlapping/nested byte offsets.
- if (Kind == I.second &&
- (R == I.first || R->isSubRegionOf(I.first)))
+ if (Kind == I.second && R->isSubRegionOf(I.first))
return true;
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5a4031c0b4a5..e8c7bdbde385 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -12,10 +12,10 @@
//
//===----------------------------------------------------------------------===//
-#include "RangedConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/Support/raw_ostream.h"
@@ -23,263 +23,203 @@
using namespace clang;
using namespace ento;
-/// A Range represents the closed range [from, to]. The caller must
-/// guarantee that from <= to. Note that Range is immutable, so as not
-/// to subvert RangeSet's immutability.
-namespace {
-class Range : public std::pair<const llvm::APSInt *, const llvm::APSInt *> {
-public:
- Range(const llvm::APSInt &from, const llvm::APSInt &to)
- : std::pair<const llvm::APSInt *, const llvm::APSInt *>(&from, &to) {
- assert(from <= to);
- }
- bool Includes(const llvm::APSInt &v) const {
- return *first <= v && v <= *second;
- }
- const llvm::APSInt &From() const { return *first; }
- const llvm::APSInt &To() const { return *second; }
- const llvm::APSInt *getConcreteValue() const {
- return &From() == &To() ? &From() : nullptr;
- }
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddPointer(&From());
- ID.AddPointer(&To());
- }
-};
-
-class RangeTrait : public llvm::ImutContainerInfo<Range> {
-public:
- // When comparing if one Range is less than another, we should compare
- // the actual APSInt values instead of their pointers. This keeps the order
- // consistent (instead of comparing by pointer values) and can potentially
- // be used to speed up some of the operations in RangeSet.
- static inline bool isLess(key_type_ref lhs, key_type_ref rhs) {
- return *lhs.first < *rhs.first ||
- (!(*rhs.first < *lhs.first) && *lhs.second < *rhs.second);
- }
-};
-
-/// RangeSet contains a set of ranges. If the set is empty, then
-/// there the value of a symbol is overly constrained and there are no
-/// possible values for that symbol.
-class RangeSet {
- typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet;
- PrimRangeSet ranges; // no need to make const, since it is an
- // ImmutableSet - this allows default operator=
- // to work.
-public:
- typedef PrimRangeSet::Factory Factory;
- typedef PrimRangeSet::iterator iterator;
-
- RangeSet(PrimRangeSet RS) : ranges(RS) {}
-
- /// Create a new set with all ranges of this set and RS.
- /// Possible intersections are not checked here.
- RangeSet addRange(Factory &F, const RangeSet &RS) {
- PrimRangeSet Ranges(RS.ranges);
- for (const auto &range : ranges)
- Ranges = F.add(Ranges, range);
- return RangeSet(Ranges);
- }
-
- iterator begin() const { return ranges.begin(); }
- iterator end() const { return ranges.end(); }
-
- bool isEmpty() const { return ranges.isEmpty(); }
-
- /// Construct a new RangeSet representing '{ [from, to] }'.
- RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to)
- : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
-
- /// Profile - Generates a hash profile of this RangeSet for use
- /// by FoldingSet.
- void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); }
-
- /// getConcreteValue - If a symbol is contrained to equal a specific integer
- /// constant then this method returns that value. Otherwise, it returns
- /// NULL.
- const llvm::APSInt *getConcreteValue() const {
- return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr;
- }
+void RangeSet::IntersectInRange(BasicValueFactory &BV, Factory &F,
+ const llvm::APSInt &Lower, const llvm::APSInt &Upper,
+ PrimRangeSet &newRanges, PrimRangeSet::iterator &i,
+ PrimRangeSet::iterator &e) const {
+ // There are six cases for each range R in the set:
+ // 1. R is entirely before the intersection range.
+ // 2. R is entirely after the intersection range.
+ // 3. R contains the entire intersection range.
+ // 4. R starts before the intersection range and ends in the middle.
+ // 5. R starts in the middle of the intersection range and ends after it.
+ // 6. R is entirely contained in the intersection range.
+ // These correspond to each of the conditions below.
+ for (/* i = begin(), e = end() */; i != e; ++i) {
+ if (i->To() < Lower) {
+ continue;
+ }
+ if (i->From() > Upper) {
+ break;
+ }
-private:
- void IntersectInRange(BasicValueFactory &BV, Factory &F,
- const llvm::APSInt &Lower, const llvm::APSInt &Upper,
- PrimRangeSet &newRanges, PrimRangeSet::iterator &i,
- PrimRangeSet::iterator &e) const {
- // There are six cases for each range R in the set:
- // 1. R is entirely before the intersection range.
- // 2. R is entirely after the intersection range.
- // 3. R contains the entire intersection range.
- // 4. R starts before the intersection range and ends in the middle.
- // 5. R starts in the middle of the intersection range and ends after it.
- // 6. R is entirely contained in the intersection range.
- // These correspond to each of the conditions below.
- for (/* i = begin(), e = end() */; i != e; ++i) {
- if (i->To() < Lower) {
- continue;
- }
- if (i->From() > Upper) {
+ if (i->Includes(Lower)) {
+ if (i->Includes(Upper)) {
+ newRanges =
+ F.add(newRanges, Range(BV.getValue(Lower), BV.getValue(Upper)));
break;
- }
-
- if (i->Includes(Lower)) {
- if (i->Includes(Upper)) {
- newRanges =
- F.add(newRanges, Range(BV.getValue(Lower), BV.getValue(Upper)));
- break;
- } else
- newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
- } else {
- if (i->Includes(Upper)) {
- newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
- break;
- } else
- newRanges = F.add(newRanges, *i);
- }
+ } else
+ newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
+ } else {
+ if (i->Includes(Upper)) {
+ newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
+ break;
+ } else
+ newRanges = F.add(newRanges, *i);
}
}
+}
- const llvm::APSInt &getMinValue() const {
- assert(!isEmpty());
- return ranges.begin()->From();
- }
+const llvm::APSInt &RangeSet::getMinValue() const {
+ assert(!isEmpty());
+ return ranges.begin()->From();
+}
- bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const {
- // This function has nine cases, the cartesian product of range-testing
- // both the upper and lower bounds against the symbol's type.
- // Each case requires a different pinning operation.
- // The function returns false if the described range is entirely outside
- // the range of values for the associated symbol.
- APSIntType Type(getMinValue());
- APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true);
- APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true);
-
- switch (LowerTest) {
+bool RangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const {
+ // This function has nine cases, the cartesian product of range-testing
+ // both the upper and lower bounds against the symbol's type.
+ // Each case requires a different pinning operation.
+ // The function returns false if the described range is entirely outside
+ // the range of values for the associated symbol.
+ APSIntType Type(getMinValue());
+ APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true);
+ APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true);
+
+ switch (LowerTest) {
+ case APSIntType::RTR_Below:
+ switch (UpperTest) {
case APSIntType::RTR_Below:
- switch (UpperTest) {
- case APSIntType::RTR_Below:
- // The entire range is outside the symbol's set of possible values.
- // If this is a conventionally-ordered range, the state is infeasible.
- if (Lower <= Upper)
- return false;
-
- // However, if the range wraps around, it spans all possible values.
- Lower = Type.getMinValue();
- Upper = Type.getMaxValue();
- break;
- case APSIntType::RTR_Within:
- // The range starts below what's possible but ends within it. Pin.
- Lower = Type.getMinValue();
- Type.apply(Upper);
- break;
- case APSIntType::RTR_Above:
- // The range spans all possible values for the symbol. Pin.
- Lower = Type.getMinValue();
- Upper = Type.getMaxValue();
- break;
- }
+ // The entire range is outside the symbol's set of possible values.
+ // If this is a conventionally-ordered range, the state is infeasible.
+ if (Lower <= Upper)
+ return false;
+
+ // However, if the range wraps around, it spans all possible values.
+ Lower = Type.getMinValue();
+ Upper = Type.getMaxValue();
break;
case APSIntType::RTR_Within:
- switch (UpperTest) {
- case APSIntType::RTR_Below:
- // The range wraps around, but all lower values are not possible.
- Type.apply(Lower);
- Upper = Type.getMaxValue();
- break;
- case APSIntType::RTR_Within:
- // The range may or may not wrap around, but both limits are valid.
- Type.apply(Lower);
- Type.apply(Upper);
- break;
- case APSIntType::RTR_Above:
- // The range starts within what's possible but ends above it. Pin.
- Type.apply(Lower);
- Upper = Type.getMaxValue();
- break;
- }
+ // The range starts below what's possible but ends within it. Pin.
+ Lower = Type.getMinValue();
+ Type.apply(Upper);
break;
case APSIntType::RTR_Above:
- switch (UpperTest) {
- case APSIntType::RTR_Below:
- // The range wraps but is outside the symbol's set of possible values.
- return false;
- case APSIntType::RTR_Within:
- // The range starts above what's possible but ends within it (wrap).
- Lower = Type.getMinValue();
- Type.apply(Upper);
- break;
- case APSIntType::RTR_Above:
- // The entire range is outside the symbol's set of possible values.
- // If this is a conventionally-ordered range, the state is infeasible.
- if (Lower <= Upper)
- return false;
-
- // However, if the range wraps around, it spans all possible values.
- Lower = Type.getMinValue();
- Upper = Type.getMaxValue();
- break;
- }
+ // The range spans all possible values for the symbol. Pin.
+ Lower = Type.getMinValue();
+ Upper = Type.getMaxValue();
+ break;
+ }
+ break;
+ case APSIntType::RTR_Within:
+ switch (UpperTest) {
+ case APSIntType::RTR_Below:
+ // The range wraps around, but all lower values are not possible.
+ Type.apply(Lower);
+ Upper = Type.getMaxValue();
+ break;
+ case APSIntType::RTR_Within:
+ // The range may or may not wrap around, but both limits are valid.
+ Type.apply(Lower);
+ Type.apply(Upper);
+ break;
+ case APSIntType::RTR_Above:
+ // The range starts within what's possible but ends above it. Pin.
+ Type.apply(Lower);
+ Upper = Type.getMaxValue();
break;
}
+ break;
+ case APSIntType::RTR_Above:
+ switch (UpperTest) {
+ case APSIntType::RTR_Below:
+ // The range wraps but is outside the symbol's set of possible values.
+ return false;
+ case APSIntType::RTR_Within:
+ // The range starts above what's possible but ends within it (wrap).
+ Lower = Type.getMinValue();
+ Type.apply(Upper);
+ break;
+ case APSIntType::RTR_Above:
+ // The entire range is outside the symbol's set of possible values.
+ // If this is a conventionally-ordered range, the state is infeasible.
+ if (Lower <= Upper)
+ return false;
- return true;
+ // However, if the range wraps around, it spans all possible values.
+ Lower = Type.getMinValue();
+ Upper = Type.getMaxValue();
+ break;
+ }
+ break;
}
-public:
- // Returns a set containing the values in the receiving set, intersected with
- // the closed range [Lower, Upper]. Unlike the Range type, this range uses
- // modular arithmetic, corresponding to the common treatment of C integer
- // overflow. Thus, if the Lower bound is greater than the Upper bound, the
- // range is taken to wrap around. This is equivalent to taking the
- // intersection with the two ranges [Min, Upper] and [Lower, Max],
- // or, alternatively, /removing/ all integers between Upper and Lower.
- RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower,
- llvm::APSInt Upper) const {
- if (!pin(Lower, Upper))
- return F.getEmptySet();
-
- PrimRangeSet newRanges = F.getEmptySet();
-
- PrimRangeSet::iterator i = begin(), e = end();
- if (Lower <= Upper)
- IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
- else {
- // The order of the next two statements is important!
- // IntersectInRange() does not reset the iteration state for i and e.
- // Therefore, the lower range most be handled first.
- IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e);
- IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e);
- }
+ return true;
+}
+
+// Returns a set containing the values in the receiving set, intersected with
+// the closed range [Lower, Upper]. Unlike the Range type, this range uses
+// modular arithmetic, corresponding to the common treatment of C integer
+// overflow. Thus, if the Lower bound is greater than the Upper bound, the
+// range is taken to wrap around. This is equivalent to taking the
+// intersection with the two ranges [Min, Upper] and [Lower, Max],
+// or, alternatively, /removing/ all integers between Upper and Lower.
+RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F,
+ llvm::APSInt Lower, llvm::APSInt Upper) const {
+ if (!pin(Lower, Upper))
+ return F.getEmptySet();
- return newRanges;
+ PrimRangeSet newRanges = F.getEmptySet();
+
+ PrimRangeSet::iterator i = begin(), e = end();
+ if (Lower <= Upper)
+ IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
+ else {
+ // The order of the next two statements is important!
+ // IntersectInRange() does not reset the iteration state for i and e.
+ // Therefore, the lower range most be handled first.
+ IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e);
+ IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e);
}
- void print(raw_ostream &os) const {
- bool isFirst = true;
- os << "{ ";
- for (iterator i = begin(), e = end(); i != e; ++i) {
- if (isFirst)
- isFirst = false;
- else
- os << ", ";
-
- os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
- << ']';
+ return newRanges;
+}
+
+// Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set
+// [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal
+// signed values of the type.
+RangeSet RangeSet::Negate(BasicValueFactory &BV, Factory &F) const {
+ PrimRangeSet newRanges = F.getEmptySet();
+
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ const llvm::APSInt &from = i->From(), &to = i->To();
+ const llvm::APSInt &newTo = (from.isMinSignedValue() ?
+ BV.getMaxValue(from) :
+ BV.getValue(- from));
+ if (to.isMaxSignedValue() && !newRanges.isEmpty() &&
+ newRanges.begin()->From().isMinSignedValue()) {
+ assert(newRanges.begin()->To().isMinSignedValue() &&
+ "Ranges should not overlap");
+ assert(!from.isMinSignedValue() && "Ranges should not overlap");
+ const llvm::APSInt &newFrom = newRanges.begin()->From();
+ newRanges =
+ F.add(F.remove(newRanges, *newRanges.begin()), Range(newFrom, newTo));
+ } else if (!to.isMinSignedValue()) {
+ const llvm::APSInt &newFrom = BV.getValue(- to);
+ newRanges = F.add(newRanges, Range(newFrom, newTo));
+ }
+ if (from.isMinSignedValue()) {
+ newRanges = F.add(newRanges, Range(BV.getMinValue(from),
+ BV.getMinValue(from)));
}
- os << " }";
}
- bool operator==(const RangeSet &other) const {
- return ranges == other.ranges;
- }
-};
-} // end anonymous namespace
+ return newRanges;
+}
-REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange,
- CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef,
- RangeSet))
+void RangeSet::print(raw_ostream &os) const {
+ bool isFirst = true;
+ os << "{ ";
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ if (isFirst)
+ isFirst = false;
+ else
+ os << ", ";
+
+ os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
+ << ']';
+ }
+ os << " }";
+}
namespace {
class RangeConstraintManager : public RangedConstraintManager {
@@ -344,6 +284,8 @@ private:
RangeSet::Factory F;
RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
+ const RangeSet* getRangeForMinusSymbol(ProgramStateRef State,
+ SymbolRef Sym);
RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
@@ -360,6 +302,7 @@ private:
RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment);
+
};
} // end anonymous namespace
@@ -400,9 +343,11 @@ bool RangeConstraintManager::canReasonAbout(SVal X) const {
if (BinaryOperator::isEqualityOp(SSE->getOpcode()) ||
BinaryOperator::isRelationalOp(SSE->getOpcode())) {
// We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
+ // We've recently started producing Loc <> NonLoc comparisons (that
+ // result from casts of one of the operands between eg. intptr_t and
+ // void *), but we can't reason about them yet.
if (Loc::isLocType(SSE->getLHS()->getType())) {
- assert(Loc::isLocType(SSE->getRHS()->getType()));
- return true;
+ return Loc::isLocType(SSE->getRHS()->getType());
}
}
}
@@ -474,7 +419,7 @@ static RangeSet assumeNonZero(
--IntType.getZeroValue());
}
-/// \brief Apply implicit constraints for bitwise OR- and AND-.
+/// 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.
@@ -515,9 +460,15 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
return *V;
+ BasicValueFactory &BV = getBasicVals();
+
+ // If Sym is a difference of symbols A - B, then maybe we have range set
+ // stored for B - A.
+ if (const RangeSet *R = getRangeForMinusSymbol(State, Sym))
+ return R->Negate(BV, F);
+
// Lazily generate a new RangeSet representing all possible values for the
// given symbol type.
- BasicValueFactory &BV = getBasicVals();
QualType T = Sym->getType();
RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
@@ -533,6 +484,32 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
return Result;
}
+// FIXME: Once SValBuilder supports unary minus, we should use SValBuilder to
+// obtain the negated symbolic expression instead of constructing the
+// symbol manually. This will allow us to support finding ranges of not
+// only negated SymSymExpr-type expressions, but also of other, simpler
+// expressions which we currently do not know how to negate.
+const RangeSet*
+RangeConstraintManager::getRangeForMinusSymbol(ProgramStateRef State,
+ SymbolRef Sym) {
+ if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
+ if (SSE->getOpcode() == BO_Sub) {
+ QualType T = Sym->getType();
+ SymbolManager &SymMgr = State->getSymbolManager();
+ SymbolRef negSym = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
+ SSE->getLHS(), T);
+ if (const RangeSet *negV = State->get<ConstraintRange>(negSym)) {
+ // Unsigned range set cannot be negated, unless it is [0, 0].
+ if ((negV->getConcreteValue() &&
+ (*negV->getConcreteValue() == 0)) ||
+ T->isSignedIntegerOrEnumerationType())
+ return negV;
+ }
+ }
+ }
+ return nullptr;
+}
+
//===------------------------------------------------------------------------===
// assumeSymX methods: protected interface for RangeConstraintManager.
//===------------------------------------------------------------------------===/
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
index 55ff15806efe..f99853f07073 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#include "RangedConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
namespace clang {
@@ -52,17 +52,18 @@ ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State,
assert(BinaryOperator::isComparisonOp(Op));
// For now, we only support comparing pointers.
- assert(Loc::isLocType(SSE->getLHS()->getType()));
- assert(Loc::isLocType(SSE->getRHS()->getType()));
- QualType DiffTy = SymMgr.getContext().getPointerDiffType();
- SymbolRef Subtraction =
- SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy);
-
- const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
- Op = BinaryOperator::reverseComparisonOp(Op);
- if (!Assumption)
- Op = BinaryOperator::negateComparisonOp(Op);
- return assumeSymRel(State, Subtraction, Op, Zero);
+ if (Loc::isLocType(SSE->getLHS()->getType()) &&
+ Loc::isLocType(SSE->getRHS()->getType())) {
+ QualType DiffTy = SymMgr.getContext().getPointerDiffType();
+ SymbolRef Subtraction =
+ SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy);
+
+ const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
+ Op = BinaryOperator::reverseComparisonOp(Op);
+ if (!Assumption)
+ Op = BinaryOperator::negateComparisonOp(Op);
+ return assumeSymRel(State, Subtraction, Op, Zero);
+ }
}
// If we get here, there's nothing else we can do but treat the symbol as
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index e2e69bb28ec2..db6449e6d5f3 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -230,11 +230,6 @@ Optional<SVal> RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
}
Optional<SVal> RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
- if (R->isBoundable())
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R))
- if (TR->getValueType()->isUnionType())
- return UnknownVal();
-
return Optional<SVal>::create(lookup(R, BindingKey::Default));
}
@@ -338,7 +333,7 @@ private:
/// To disable all small-struct-dependent behavior, set the option to "0".
unsigned SmallStructLimit;
- /// \brief A helper used to populate the work list with the given set of
+ /// A helper used to populate the work list with the given set of
/// regions.
void populateWorkList(invalidateRegionsWorker &W,
ArrayRef<SVal> Values,
@@ -409,8 +404,22 @@ public: // Part of public interface to class.
RegionBindingsRef bind(RegionBindingsConstRef B, Loc LV, SVal V);
- // BindDefault is only used to initialize a region with a default value.
- StoreRef BindDefault(Store store, const MemRegion *R, SVal V) override {
+ // BindDefaultInitial is only used to initialize a region with
+ // a default value.
+ StoreRef BindDefaultInitial(Store store, const MemRegion *R,
+ SVal V) override {
+ RegionBindingsRef B = getRegionBindings(store);
+ // Use other APIs when you have to wipe the region that was initialized
+ // earlier.
+ assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
+ "Double initialization!");
+ B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
+ return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
+ }
+
+ // BindDefaultZero is used for zeroing constructors that may accidentally
+ // overwrite existing bindings.
+ StoreRef BindDefaultZero(Store store, const MemRegion *R) override {
// FIXME: The offsets of empty bases can be tricky because of
// of the so called "empty base class optimization".
// If a base class has been optimized out
@@ -420,24 +429,14 @@ public: // Part of public interface to class.
// and trying to infer them from offsets/alignments
// seems to be error-prone and non-trivial because of the trailing padding.
// As a temporary mitigation we don't create bindings for empty bases.
- if (R->getKind() == MemRegion::CXXBaseObjectRegionKind &&
- cast<CXXBaseObjectRegion>(R)->getDecl()->isEmpty())
- return StoreRef(store, *this);
+ if (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
+ if (BR->getDecl()->isEmpty())
+ return StoreRef(store, *this);
RegionBindingsRef B = getRegionBindings(store);
- assert(!B.lookup(R, BindingKey::Direct));
-
- BindingKey Key = BindingKey::Make(R, BindingKey::Default);
- if (B.lookup(Key)) {
- const SubRegion *SR = cast<SubRegion>(R);
- assert(SR->getAsOffset().getOffset() ==
- SR->getSuperRegion()->getAsOffset().getOffset() &&
- "A default value must come from a super-region");
- B = removeSubRegionBindings(B, SR);
- } else {
- B = B.addBinding(Key, V);
- }
-
+ SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
+ B = removeSubRegionBindings(B, cast<SubRegion>(R));
+ B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
}
@@ -474,7 +473,7 @@ public: // Part of public interface to class.
const TypedRegion *R,
SVal DefaultVal);
- /// \brief Create a new store with the specified binding removed.
+ /// Create a new store with the specified binding removed.
/// \param ST the original store, that is the basis for the new store.
/// \param L the location whose binding should be removed.
StoreRef killBinding(Store ST, Loc L) override;
@@ -492,7 +491,7 @@ public: // Part of public interface to class.
bool includedInBindings(Store store, const MemRegion *region) const override;
- /// \brief Return the value bound to specified location in a given state.
+ /// Return the value bound to specified location in a given state.
///
/// The high level logic for this method is this:
/// getBinding (L)
@@ -825,7 +824,7 @@ collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
FieldVector FieldsInSymbolicSubregions;
if (TopKey.hasSymbolicOffset()) {
getSymbolicOffsetFields(TopKey, FieldsInSymbolicSubregions);
- Top = cast<SubRegion>(TopKey.getConcreteOffsetRegion());
+ Top = TopKey.getConcreteOffsetRegion();
TopKey = BindingKey::Make(Top, BindingKey::Default);
}
@@ -871,7 +870,7 @@ collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
} else if (NextKey.hasSymbolicOffset()) {
const MemRegion *Base = NextKey.getConcreteOffsetRegion();
- if (Top->isSubRegionOf(Base)) {
+ if (Top->isSubRegionOf(Base) && Top != Base) {
// Case 3: The next key is symbolic and we just changed something within
// its concrete region. We don't know if the binding is still valid, so
// we'll be conservative and include it.
@@ -881,7 +880,7 @@ collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
} else if (const SubRegion *BaseSR = dyn_cast<SubRegion>(Base)) {
// Case 4: The next key is symbolic, but we changed a known
// super-region. In this case the binding is certainly included.
- if (Top == Base || BaseSR->isSubRegionOf(Top))
+ if (BaseSR->isSubRegionOf(Top))
if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
Bindings.push_back(*I);
}
@@ -1095,7 +1094,7 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
return;
}
- if (T->isStructureOrClassType()) {
+ if (T->isRecordType()) {
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelevant.
DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
@@ -1342,7 +1341,8 @@ RegionStoreManager::getSizeInElements(ProgramStateRef state,
// If a variable is reinterpreted as a type that doesn't fit into a larger
// type evenly, round it down.
// This is a signed value, since it's used in arithmetic with signed indices.
- return svalBuilder.makeIntVal(RegionSize / EleSize, false);
+ return svalBuilder.makeIntVal(RegionSize / EleSize,
+ svalBuilder.getArrayIndexType());
}
//===----------------------------------------------------------------------===//
@@ -1401,12 +1401,12 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
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);
+ } else {
+ T = cast<TypedValueRegion>(MR)->getValueType();
}
// FIXME: Perhaps this method should just take a 'const MemRegion*' argument
@@ -1446,7 +1446,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
return UnknownVal();
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
- return CastRetrievedVal(getBindingForField(B, FR), FR, T, false);
+ return CastRetrievedVal(getBindingForField(B, FR), FR, T);
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
// FIXME: Here we actually perform an implicit conversion from the loaded
@@ -1454,7 +1454,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
// more intelligently. For example, an 'element' can encompass multiple
// bound regions (e.g., several bound bytes), or could be a subset of
// a larger value.
- return CastRetrievedVal(getBindingForElement(B, ER), ER, T, false);
+ return CastRetrievedVal(getBindingForElement(B, ER), ER, T);
}
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
@@ -1464,7 +1464,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
// reinterpretted, it is possible we stored a different value that could
// fit within the ivar. Either we need to cast these when storing them
// or reinterpret them lazily (as we do here).
- return CastRetrievedVal(getBindingForObjCIvar(B, IVR), IVR, T, false);
+ return CastRetrievedVal(getBindingForObjCIvar(B, IVR), IVR, T);
}
if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
@@ -1474,7 +1474,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
// variable is reinterpretted, it is possible we stored a different value
// that could fit within the variable. Either we need to cast these when
// storing them or reinterpret them lazily (as we do here).
- return CastRetrievedVal(getBindingForVar(B, VR), VR, T, false);
+ return CastRetrievedVal(getBindingForVar(B, VR), VR, T);
}
const SVal *V = B.lookup(R, BindingKey::Direct);
@@ -1606,7 +1606,7 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
const MemRegion* superR = R->getSuperRegion();
// Check if the region is an element region of a string literal.
- if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
+ if (const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
// FIXME: Handle loads from strings where the literal is treated as
// an integer, e.g., *((unsigned int*)"hello")
QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
@@ -1629,6 +1629,36 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
char c = (i >= length) ? '\0' : Str->getCodeUnit(i);
return svalBuilder.makeIntVal(c, T);
}
+ } else if (const VarRegion *VR = dyn_cast<VarRegion>(superR)) {
+ // Check if the containing array is const and has an initialized value.
+ const VarDecl *VD = VR->getDecl();
+ // Either the array or the array element has to be const.
+ if (VD->getType().isConstQualified() || R->getElementType().isConstQualified()) {
+ if (const Expr *Init = VD->getInit()) {
+ if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
+ // The array index has to be known.
+ if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
+ int64_t i = CI->getValue().getSExtValue();
+ // If it is known that the index is out of bounds, we can return
+ // an undefined value.
+ if (i < 0)
+ return UndefinedVal();
+
+ if (auto CAT = Ctx.getAsConstantArrayType(VD->getType()))
+ if (CAT->getSize().sle(i))
+ return UndefinedVal();
+
+ // If there is a list, but no init, it must be zero.
+ if (i >= InitList->getNumInits())
+ return svalBuilder.makeZeroVal(R->getElementType());
+
+ if (const Expr *ElemInit = InitList->getInit(i))
+ if (Optional<SVal> V = svalBuilder.getConstantVal(ElemInit))
+ return *V;
+ }
+ }
+ }
+ }
}
// Check for loads from a code text region. For such loads, just give up.
@@ -1678,7 +1708,34 @@ SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
if (const Optional<SVal> &V = B.getDirectBinding(R))
return *V;
- QualType Ty = R->getValueType();
+ // Is the field declared constant and has an in-class initializer?
+ const FieldDecl *FD = R->getDecl();
+ QualType Ty = FD->getType();
+ if (Ty.isConstQualified())
+ if (const Expr *Init = FD->getInClassInitializer())
+ if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
+ return *V;
+
+ // If the containing record was initialized, try to get its constant value.
+ const MemRegion* superR = R->getSuperRegion();
+ if (const auto *VR = dyn_cast<VarRegion>(superR)) {
+ const VarDecl *VD = VR->getDecl();
+ QualType RecordVarTy = VD->getType();
+ unsigned Index = FD->getFieldIndex();
+ // Either the record variable or the field has to be const qualified.
+ if (RecordVarTy.isConstQualified() || Ty.isConstQualified())
+ if (const Expr *Init = VD->getInit())
+ if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
+ if (Index < InitList->getNumInits()) {
+ if (const Expr *FieldInit = InitList->getInit(Index))
+ if (Optional<SVal> V = svalBuilder.getConstantVal(FieldInit))
+ return *V;
+ } else {
+ return svalBuilder.makeZeroVal(Ty);
+ }
+ }
+ }
+
return getBindingForFieldOrElementCommon(B, R, Ty);
}
@@ -1776,7 +1833,7 @@ RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
// quickly result in a warning.
bool hasPartialLazyBinding = false;
- const SubRegion *SR = dyn_cast<SubRegion>(R);
+ const SubRegion *SR = R;
while (SR) {
const MemRegion *Base = SR->getSuperRegion();
if (Optional<SVal> D = getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
@@ -2050,6 +2107,9 @@ RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
R = GetElementZeroRegion(SR, T);
}
+ assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
+ "'this' pointer is not an l-value and is not assignable");
+
// Clear out bindings that may overlap with this binding.
RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
return NewB.addBinding(BindingKey::Make(R, BindingKey::Direct), V);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp
new file mode 100644
index 000000000000..d379562bf325
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp
@@ -0,0 +1,181 @@
+//== SMTConstraintManager.cpp -----------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+
+using namespace clang;
+using namespace ento;
+
+ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State,
+ SymbolRef Sym,
+ bool Assumption) {
+ ASTContext &Ctx = getBasicVals().getContext();
+
+ QualType RetTy;
+ bool hasComparison;
+
+ SMTExprRef Exp = Solver->getExpr(Ctx, Sym, &RetTy, &hasComparison);
+
+ // Create zero comparison for implicit boolean cast, with reversed assumption
+ if (!hasComparison && !RetTy->isBooleanType())
+ return assumeExpr(State, Sym,
+ Solver->getZeroExpr(Ctx, Exp, RetTy, !Assumption));
+
+ return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp));
+}
+
+ProgramStateRef SMTConstraintManager::assumeSymInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, bool InRange) {
+ ASTContext &Ctx = getBasicVals().getContext();
+ return assumeExpr(State, Sym,
+ Solver->getRangeExpr(Ctx, Sym, From, To, InRange));
+}
+
+ProgramStateRef
+SMTConstraintManager::assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym,
+ bool Assumption) {
+ // Skip anything that is unsupported
+ return State;
+}
+
+ConditionTruthVal SMTConstraintManager::checkNull(ProgramStateRef State,
+ SymbolRef Sym) {
+ ASTContext &Ctx = getBasicVals().getContext();
+
+ QualType RetTy;
+ // The expression may be casted, so we cannot call getZ3DataExpr() directly
+ SMTExprRef VarExp = Solver->getExpr(Ctx, Sym, &RetTy);
+ SMTExprRef Exp = Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/true);
+
+ // Negate the constraint
+ SMTExprRef NotExp =
+ Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/false);
+
+ Solver->reset();
+ addStateConstraints(State);
+
+ Solver->push();
+ Solver->addConstraint(Exp);
+ ConditionTruthVal isSat = Solver->check();
+
+ Solver->pop();
+ Solver->addConstraint(NotExp);
+ ConditionTruthVal isNotSat = Solver->check();
+
+ // Zero is the only possible solution
+ if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse())
+ return true;
+
+ // Zero is not a solution
+ if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue())
+ return false;
+
+ // Zero may be a solution
+ return ConditionTruthVal();
+}
+
+const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State,
+ SymbolRef Sym) const {
+ BasicValueFactory &BVF = getBasicVals();
+ ASTContext &Ctx = BVF.getContext();
+
+ if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
+ QualType Ty = Sym->getType();
+ assert(!Ty->isRealFloatingType());
+ llvm::APSInt Value(Ctx.getTypeSize(Ty),
+ !Ty->isSignedIntegerOrEnumerationType());
+
+ SMTExprRef Exp =
+ Solver->fromData(SD->getSymbolID(), Ty, Ctx.getTypeSize(Ty));
+
+ Solver->reset();
+ addStateConstraints(State);
+
+ // Constraints are unsatisfiable
+ ConditionTruthVal isSat = Solver->check();
+ if (!isSat.isConstrainedTrue())
+ return nullptr;
+
+ // Model does not assign interpretation
+ if (!Solver->getInterpretation(Exp, Value))
+ return nullptr;
+
+ // A value has been obtained, check if it is the only value
+ SMTExprRef NotExp = Solver->fromBinOp(
+ Exp, BO_NE,
+ Ty->isBooleanType() ? Solver->fromBoolean(Value.getBoolValue())
+ : Solver->fromAPSInt(Value),
+ false);
+
+ Solver->addConstraint(NotExp);
+
+ ConditionTruthVal isNotSat = Solver->check();
+ if (isNotSat.isConstrainedTrue())
+ return nullptr;
+
+ // This is the only solution, store it
+ return &BVF.getValue(Value);
+ }
+
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
+ SymbolRef CastSym = SC->getOperand();
+ QualType CastTy = SC->getType();
+ // Skip the void type
+ if (CastTy->isVoidType())
+ return nullptr;
+
+ const llvm::APSInt *Value;
+ if (!(Value = getSymVal(State, CastSym)))
+ return nullptr;
+ return &BVF.Convert(SC->getType(), *Value);
+ }
+
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ const llvm::APSInt *LHS, *RHS;
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
+ LHS = getSymVal(State, SIE->getLHS());
+ RHS = &SIE->getRHS();
+ } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
+ LHS = &ISE->getLHS();
+ RHS = getSymVal(State, ISE->getRHS());
+ } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
+ // Early termination to avoid expensive call
+ LHS = getSymVal(State, SSM->getLHS());
+ RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr;
+ } else {
+ llvm_unreachable("Unsupported binary expression to get symbol value!");
+ }
+
+ if (!LHS || !RHS)
+ return nullptr;
+
+ llvm::APSInt ConvertedLHS, ConvertedRHS;
+ QualType LTy, RTy;
+ std::tie(ConvertedLHS, LTy) = Solver->fixAPSInt(Ctx, *LHS);
+ std::tie(ConvertedRHS, RTy) = Solver->fixAPSInt(Ctx, *RHS);
+ Solver->doIntTypeConversion<llvm::APSInt, &SMTSolver::castAPSInt>(
+ Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
+ return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
+ }
+
+ llvm_unreachable("Unsupported expression to get symbol value!");
+}
+
+ConditionTruthVal
+SMTConstraintManager::checkModel(ProgramStateRef State,
+ const SMTExprRef &Exp) const {
+ Solver->reset();
+ Solver->addConstraint(Exp);
+ addStateConstraints(State);
+ return Solver->check();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 04452e3e7cc2..f292dca8e99f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -1,4 +1,4 @@
-// SValBuilder.cpp - Basic class for all SValBuilder implementations -*- C++ -*-
+//===- SValBuilder.cpp - Basic class for all SValBuilder implementations --===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,12 +13,33 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <tuple>
using namespace clang;
using namespace ento;
@@ -27,7 +48,7 @@ using namespace ento;
// Basic SVal creation.
//===----------------------------------------------------------------------===//
-void SValBuilder::anchor() { }
+void SValBuilder::anchor() {}
DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) {
if (Loc::isLocType(type))
@@ -95,12 +116,12 @@ nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
}
DefinedOrUnknownSVal
-SValBuilder::getRegionValueSymbolVal(const TypedValueRegion* region) {
+SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
QualType T = region->getValueType();
if (T->isNullPtrType())
return makeZeroVal(T);
-
+
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
@@ -149,7 +170,6 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
return nonloc::SymbolVal(sym);
}
-
DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
const LocationContext *LCtx,
QualType type,
@@ -217,10 +237,10 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
return nonloc::SymbolVal(sym);
}
-DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl *DD) {
assert(!DD || isa<CXXMethodDecl>(DD) || isa<FieldDecl>(DD));
- if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(DD)) {
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(DD)) {
// Sema treats pointers to static member functions as have function pointer
// type, so return a function pointer for the method.
// We don't need to play a similar trick for static member fields
@@ -277,19 +297,19 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
return makeZeroVal(E->getType());
case Stmt::ObjCStringLiteralClass: {
- const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(E);
+ const auto *SL = cast<ObjCStringLiteral>(E);
return makeLoc(getRegionManager().getObjCStringRegion(SL));
}
case Stmt::StringLiteralClass: {
- const StringLiteral *SL = cast<StringLiteral>(E);
+ const auto *SL = cast<StringLiteral>(E);
return makeLoc(getRegionManager().getStringRegion(SL));
}
// Fast-path some expressions to avoid the overhead of going through the AST's
// constant evaluator
case Stmt::CharacterLiteralClass: {
- const CharacterLiteral *C = cast<CharacterLiteral>(E);
+ const auto *C = cast<CharacterLiteral>(E);
return makeIntVal(C->getValue(), C->getType());
}
@@ -297,7 +317,7 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
return makeBoolVal(cast<CXXBoolLiteralExpr>(E));
case Stmt::TypeTraitExprClass: {
- const TypeTraitExpr *TE = cast<TypeTraitExpr>(E);
+ const auto *TE = cast<TypeTraitExpr>(E);
return makeTruthVal(TE->getValue(), TE->getType());
}
@@ -310,12 +330,19 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
case Stmt::CXXNullPtrLiteralExprClass:
return makeNull();
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass:
+ case Stmt::CXXStaticCastExprClass:
case Stmt::ImplicitCastExprClass: {
- const CastExpr *CE = cast<CastExpr>(E);
+ const auto *CE = cast<CastExpr>(E);
switch (CE->getCastKind()) {
default:
break;
case CK_ArrayToPointerDecay:
+ case CK_IntegralToPointer:
+ case CK_NoOp:
case CK_BitCast: {
const Expr *SE = CE->getSubExpr();
Optional<SVal> Val = getConstantVal(SE);
@@ -348,20 +375,18 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
}
}
-//===----------------------------------------------------------------------===//
-
SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
BinaryOperator::Opcode Op,
NonLoc LHS, NonLoc RHS,
QualType ResultTy) {
- if (!State->isTainted(RHS) && !State->isTainted(LHS))
- return UnknownVal();
-
const SymExpr *symLHS = LHS.getAsSymExpr();
const SymExpr *symRHS = RHS.getAsSymExpr();
+
// TODO: When the Max Complexity is reached, we should conjure a symbol
// instead of generating an Unknown value and propagate the taint info to it.
- const unsigned MaxComp = 10000; // 100000 28X
+ const unsigned MaxComp = StateMgr.getOwningEngine()
+ ->getAnalysisManager()
+ .options.getMaxSymbolComplexity();
if (symLHS && symRHS &&
(symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp)
@@ -378,10 +403,8 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
return UnknownVal();
}
-
SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
SVal lhs, SVal rhs, QualType type) {
-
if (lhs.isUndef() || rhs.isUndef())
return UndefinedVal();
@@ -413,10 +436,19 @@ SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
type);
}
+ConditionTruthVal SValBuilder::areEqual(ProgramStateRef state, SVal lhs,
+ SVal rhs) {
+ return state->isNonNull(evalEQ(state, lhs, rhs));
+}
+
+SVal SValBuilder::evalEQ(ProgramStateRef state, SVal lhs, SVal rhs) {
+ return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType());
+}
+
DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
DefinedOrUnknownSVal lhs,
DefinedOrUnknownSVal rhs) {
- return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType())
+ return evalEQ(state, static_cast<SVal>(lhs), static_cast<SVal>(rhs))
.castAs<DefinedOrUnknownSVal>();
}
@@ -425,7 +457,7 @@ DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
/// Assumes the input types are canonical.
static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
QualType FromTy) {
- while (Context.UnwrapSimilarPointerTypes(ToTy, FromTy)) {
+ while (Context.UnwrapSimilarTypes(ToTy, FromTy)) {
Qualifiers Quals1, Quals2;
ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);
@@ -440,6 +472,10 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
// If we are casting to void, the 'From' value can be used to represent the
// 'To' value.
+ //
+ // FIXME: Doing this after unwrapping the types doesn't make any sense. A
+ // cast from 'int**' to 'void**' is not special in the way that a cast from
+ // 'int*' to 'void*' is.
if (ToTy->isVoidType())
return true;
@@ -454,7 +490,6 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
// of the original value is known to be greater than the max of the target type.
SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
QualType castTy, QualType originalTy) {
-
// No truncations if target type is big enough.
if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
return evalCast(val, castTy, originalTy);
@@ -548,8 +583,8 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
}
// Check for casts from array type to another type.
- if (const ArrayType *arrayT =
- dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
+ if (const auto *arrayT =
+ dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
// We will always decay to a pointer.
QualType elemTy = arrayT->getElementType();
val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
index a83421426a13..559ca2c9840d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -1,4 +1,4 @@
-//= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- C++ -*-==//
+//===- RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,20 +12,31 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "llvm/Support/raw_ostream.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+
using namespace clang;
using namespace ento;
-using llvm::APSInt;
//===----------------------------------------------------------------------===//
// Symbol iteration within an SVal.
//===----------------------------------------------------------------------===//
-
//===----------------------------------------------------------------------===//
// Utility methods.
//===----------------------------------------------------------------------===//
@@ -39,7 +50,7 @@ bool SVal::hasConjuredSymbol() const {
if (Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
const MemRegion *R = RV->getRegion();
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
SymbolRef sym = SR->getSymbol();
if (isa<SymbolConjured>(sym))
return true;
@@ -53,18 +64,18 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
const MemRegion* R = X->getRegion();
if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
+ if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
return FD;
}
if (auto X = getAs<nonloc::PointerToMember>()) {
- if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
return MD;
}
return nullptr;
}
-/// \brief If this SVal is a location (subclasses Loc) and wraps a symbol,
+/// If this SVal is a location (subclasses Loc) and wraps a symbol,
/// return that SymbolRef. Otherwise return 0.
///
/// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
@@ -95,8 +106,8 @@ SymbolRef SVal::getLocSymbolInBase() const {
const MemRegion *R = X->getRegion();
- while (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
- if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR))
+ while (const auto *SR = dyn_cast<SubRegion>(R)) {
+ if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
return SymR->getSymbol();
else
R = SR->getSuperRegion();
@@ -107,7 +118,7 @@ SymbolRef SVal::getLocSymbolInBase() const {
// TODO: The next 3 functions have to be simplified.
-/// \brief If this SVal wraps a symbol return that SymbolRef.
+/// If this SVal wraps a symbol return that SymbolRef.
/// Otherwise, return 0.
///
/// Casts are ignored during lookup.
@@ -189,14 +200,14 @@ nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const {
const PTMDataType PTMD = getPTMData();
if (PTMD.is<const DeclaratorDecl *>())
- return nonloc::PointerToMember::iterator();
+ return {};
return PTMD.get<const PointerToMemberData *>()->begin();
}
nonloc::PointerToMember::iterator nonloc::PointerToMember::end() const {
const PTMDataType PTMD = getPTMData();
if (PTMD.is<const DeclaratorDecl *>())
- return nonloc::PointerToMember::iterator();
+ return {};
return PTMD.get<const PointerToMemberData *>()->end();
}
@@ -220,7 +231,6 @@ bool SVal::isZeroConstant() const {
return isConstant(0);
}
-
//===----------------------------------------------------------------------===//
// Transfer function dispatch for Non-Locs.
//===----------------------------------------------------------------------===//
@@ -254,7 +264,6 @@ nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
BinaryOperator::Opcode Op,
const loc::ConcreteInt& R) const {
-
assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
@@ -291,19 +300,15 @@ void SVal::dumpToStream(raw_ostream &os) const {
void NonLoc::dumpToStream(raw_ostream &os) const {
switch (getSubKind()) {
case nonloc::ConcreteIntKind: {
- const nonloc::ConcreteInt& C = castAs<nonloc::ConcreteInt>();
- if (C.getValue().isUnsigned())
- os << C.getValue().getZExtValue();
- else
- os << C.getValue().getSExtValue();
- os << ' ' << (C.getValue().isUnsigned() ? 'U' : 'S')
- << C.getValue().getBitWidth() << 'b';
+ const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
+ os << Value << ' ' << (Value.isSigned() ? 'S' : 'U')
+ << Value.getBitWidth() << 'b';
break;
}
- case nonloc::SymbolValKind: {
+ case nonloc::SymbolValKind:
os << castAs<nonloc::SymbolVal>().getSymbol();
break;
- }
+
case nonloc::LocAsIntegerKind: {
const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
@@ -313,14 +318,14 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
os << "compoundVal{";
bool first = true;
- for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
+ for (const auto &I : C) {
if (first) {
os << ' '; first = false;
}
else
os << ", ";
- (*I).dumpToStream(os);
+ I.dumpToStream(os);
}
os << "}";
break;
@@ -353,7 +358,7 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
break;
}
default:
- assert (false && "Pretty-printed not implemented for this NonLoc.");
+ assert(false && "Pretty-printed not implemented for this NonLoc.");
break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 94d29d5a6ba3..62c54fc956a9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
using namespace clang;
@@ -157,7 +159,8 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR));
if (const SymbolicRegion *SymR = R->getSymbolicBase())
- return nonloc::SymbolVal(SymR->getSymbol());
+ return makeNonLoc(SymR->getSymbol(), BO_NE,
+ BasicVals.getZeroWithPtrWidth(), castTy);
// FALL-THROUGH
LLVM_FALLTHROUGH;
@@ -307,6 +310,197 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
return makeNonLoc(LHS, op, *ConvertedRHS, resultTy);
}
+// See if Sym is known to be a relation Rel with Bound.
+static bool isInRelation(BinaryOperator::Opcode Rel, SymbolRef Sym,
+ llvm::APSInt Bound, ProgramStateRef State) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ SVal Result =
+ SVB.evalBinOpNN(State, Rel, nonloc::SymbolVal(Sym),
+ nonloc::ConcreteInt(Bound), SVB.getConditionType());
+ if (auto DV = Result.getAs<DefinedSVal>()) {
+ return !State->assume(*DV, false);
+ }
+ return false;
+}
+
+// See if Sym is known to be within [min/4, max/4], where min and max
+// are the bounds of the symbol's integral type. With such symbols,
+// some manipulations can be performed without the risk of overflow.
+// assume() doesn't cause infinite recursion because we should be dealing
+// with simpler symbols on every recursive call.
+static bool isWithinConstantOverflowBounds(SymbolRef Sym,
+ ProgramStateRef State) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ BasicValueFactory &BV = SVB.getBasicValueFactory();
+
+ QualType T = Sym->getType();
+ assert(T->isSignedIntegerOrEnumerationType() &&
+ "This only works with signed integers!");
+ APSIntType AT = BV.getAPSIntType(T);
+
+ llvm::APSInt Max = AT.getMaxValue() / AT.getValue(4), Min = -Max;
+ return isInRelation(BO_LE, Sym, Max, State) &&
+ isInRelation(BO_GE, Sym, Min, State);
+}
+
+// Same for the concrete integers: see if I is within [min/4, max/4].
+static bool isWithinConstantOverflowBounds(llvm::APSInt I) {
+ APSIntType AT(I);
+ assert(!AT.isUnsigned() &&
+ "This only works with signed integers!");
+
+ llvm::APSInt Max = AT.getMaxValue() / AT.getValue(4), Min = -Max;
+ return (I <= Max) && (I >= -Max);
+}
+
+static std::pair<SymbolRef, llvm::APSInt>
+decomposeSymbol(SymbolRef Sym, BasicValueFactory &BV) {
+ if (const auto *SymInt = dyn_cast<SymIntExpr>(Sym))
+ if (BinaryOperator::isAdditiveOp(SymInt->getOpcode()))
+ return std::make_pair(SymInt->getLHS(),
+ (SymInt->getOpcode() == BO_Add) ?
+ (SymInt->getRHS()) :
+ (-SymInt->getRHS()));
+
+ // Fail to decompose: "reduce" the problem to the "$x + 0" case.
+ return std::make_pair(Sym, BV.getValue(0, Sym->getType()));
+}
+
+// Simplify "(LSym + LInt) Op (RSym + RInt)" assuming all values are of the
+// same signed integral type and no overflows occur (which should be checked
+// by the caller).
+static NonLoc doRearrangeUnchecked(ProgramStateRef State,
+ BinaryOperator::Opcode Op,
+ SymbolRef LSym, llvm::APSInt LInt,
+ SymbolRef RSym, llvm::APSInt RInt) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ BasicValueFactory &BV = SVB.getBasicValueFactory();
+ SymbolManager &SymMgr = SVB.getSymbolManager();
+
+ QualType SymTy = LSym->getType();
+ assert(SymTy == RSym->getType() &&
+ "Symbols are not of the same type!");
+ assert(APSIntType(LInt) == BV.getAPSIntType(SymTy) &&
+ "Integers are not of the same type as symbols!");
+ assert(APSIntType(RInt) == BV.getAPSIntType(SymTy) &&
+ "Integers are not of the same type as symbols!");
+
+ QualType ResultTy;
+ if (BinaryOperator::isComparisonOp(Op))
+ ResultTy = SVB.getConditionType();
+ else if (BinaryOperator::isAdditiveOp(Op))
+ ResultTy = SymTy;
+ else
+ llvm_unreachable("Operation not suitable for unchecked rearrangement!");
+
+ // FIXME: Can we use assume() without getting into an infinite recursion?
+ if (LSym == RSym)
+ return SVB.evalBinOpNN(State, Op, nonloc::ConcreteInt(LInt),
+ nonloc::ConcreteInt(RInt), ResultTy)
+ .castAs<NonLoc>();
+
+ SymbolRef ResultSym = nullptr;
+ BinaryOperator::Opcode ResultOp;
+ llvm::APSInt ResultInt;
+ if (BinaryOperator::isComparisonOp(Op)) {
+ // Prefer comparing to a non-negative number.
+ // FIXME: Maybe it'd be better to have consistency in
+ // "$x - $y" vs. "$y - $x" because those are solver's keys.
+ if (LInt > RInt) {
+ ResultSym = SymMgr.getSymSymExpr(RSym, BO_Sub, LSym, SymTy);
+ ResultOp = BinaryOperator::reverseComparisonOp(Op);
+ ResultInt = LInt - RInt; // Opposite order!
+ } else {
+ ResultSym = SymMgr.getSymSymExpr(LSym, BO_Sub, RSym, SymTy);
+ ResultOp = Op;
+ ResultInt = RInt - LInt; // Opposite order!
+ }
+ } else {
+ ResultSym = SymMgr.getSymSymExpr(LSym, Op, RSym, SymTy);
+ ResultInt = (Op == BO_Add) ? (LInt + RInt) : (LInt - RInt);
+ ResultOp = BO_Add;
+ // Bring back the cosmetic difference.
+ if (ResultInt < 0) {
+ ResultInt = -ResultInt;
+ ResultOp = BO_Sub;
+ } else if (ResultInt == 0) {
+ // Shortcut: Simplify "$x + 0" to "$x".
+ return nonloc::SymbolVal(ResultSym);
+ }
+ }
+ const llvm::APSInt &PersistentResultInt = BV.getValue(ResultInt);
+ return nonloc::SymbolVal(
+ SymMgr.getSymIntExpr(ResultSym, ResultOp, PersistentResultInt, ResultTy));
+}
+
+// Rearrange if symbol type matches the result type and if the operator is a
+// comparison operator, both symbol and constant must be within constant
+// overflow bounds.
+static bool shouldRearrange(ProgramStateRef State, BinaryOperator::Opcode Op,
+ SymbolRef Sym, llvm::APSInt Int, QualType Ty) {
+ return Sym->getType() == Ty &&
+ (!BinaryOperator::isComparisonOp(Op) ||
+ (isWithinConstantOverflowBounds(Sym, State) &&
+ isWithinConstantOverflowBounds(Int)));
+}
+
+static Optional<NonLoc> tryRearrange(ProgramStateRef State,
+ BinaryOperator::Opcode Op, NonLoc Lhs,
+ NonLoc Rhs, QualType ResultTy) {
+ ProgramStateManager &StateMgr = State->getStateManager();
+ SValBuilder &SVB = StateMgr.getSValBuilder();
+
+ // We expect everything to be of the same type - this type.
+ QualType SingleTy;
+
+ auto &Opts =
+ StateMgr.getOwningEngine()->getAnalysisManager().getAnalyzerOptions();
+
+ // FIXME: After putting complexity threshold to the symbols we can always
+ // rearrange additive operations but rearrange comparisons only if
+ // option is set.
+ if(!Opts.shouldAggressivelySimplifyBinaryOperation())
+ return None;
+
+ SymbolRef LSym = Lhs.getAsSymbol();
+ if (!LSym)
+ return None;
+
+ if (BinaryOperator::isComparisonOp(Op)) {
+ SingleTy = LSym->getType();
+ if (ResultTy != SVB.getConditionType())
+ return None;
+ // Initialize SingleTy later with a symbol's type.
+ } else if (BinaryOperator::isAdditiveOp(Op)) {
+ SingleTy = ResultTy;
+ if (LSym->getType() != SingleTy)
+ return None;
+ // Substracting unsigned integers is a nightmare.
+ if (!SingleTy->isSignedIntegerOrEnumerationType())
+ return None;
+ } else {
+ // Don't rearrange other operations.
+ return None;
+ }
+
+ assert(!SingleTy.isNull() && "We should have figured out the type by now!");
+
+ SymbolRef RSym = Rhs.getAsSymbol();
+ if (!RSym || RSym->getType() != SingleTy)
+ return None;
+
+ BasicValueFactory &BV = State->getBasicVals();
+ llvm::APSInt LInt, RInt;
+ std::tie(LSym, LInt) = decomposeSymbol(LSym, BV);
+ std::tie(RSym, RInt) = decomposeSymbol(RSym, BV);
+ if (!shouldRearrange(State, Op, LSym, LInt, SingleTy) ||
+ !shouldRearrange(State, Op, RSym, RInt, SingleTy))
+ return None;
+
+ // We know that no overflows can occur anymore.
+ return doRearrangeUnchecked(State, Op, LSym, LInt, RSym, RInt);
+}
+
SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs,
@@ -559,6 +753,9 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
+ if (Optional<NonLoc> V = tryRearrange(state, op, lhs, rhs, resultTy))
+ return *V;
+
// Give up -- this is not a symbolic expression we can handle.
return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
}
@@ -988,6 +1185,12 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
elementType = resultTy->getPointeeType();
}
+ // Represent arithmetic on void pointers as arithmetic on char pointers.
+ // It is fine when a TypedValueRegion of char value type represents
+ // a void pointer. Note that arithmetic on void pointers is a GCC extension.
+ if (elementType->isVoidType())
+ elementType = getContext().CharTy;
+
if (Optional<NonLoc> indexV = index.getAs<NonLoc>()) {
return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV,
superR, getContext()));
@@ -1023,24 +1226,50 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
ProgramStateRef State;
SValBuilder &SVB;
+ // Cache results for the lifetime of the Simplifier. Results change every
+ // time new constraints are added to the program state, which is the whole
+ // point of simplifying, and for that very reason it's pointless to maintain
+ // the same cache for the duration of the whole analysis.
+ llvm::DenseMap<SymbolRef, SVal> Cached;
+
+ static bool isUnchanged(SymbolRef Sym, SVal Val) {
+ return Sym == Val.getAsSymbol();
+ }
+
+ SVal cache(SymbolRef Sym, SVal V) {
+ Cached[Sym] = V;
+ return V;
+ }
+
+ SVal skip(SymbolRef Sym) {
+ return cache(Sym, SVB.makeSymbolVal(Sym));
+ }
+
public:
Simplifier(ProgramStateRef State)
: State(State), SVB(State->getStateManager().getSValBuilder()) {}
SVal VisitSymbolData(const SymbolData *S) {
+ // No cache here.
if (const llvm::APSInt *I =
- SVB.getKnownValue(State, nonloc::SymbolVal(S)))
+ SVB.getKnownValue(State, SVB.makeSymbolVal(S)))
return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I)
: (SVal)SVB.makeIntVal(*I);
- return Loc::isLocType(S->getType()) ? (SVal)SVB.makeLoc(S)
- : nonloc::SymbolVal(S);
+ return SVB.makeSymbolVal(S);
}
// TODO: Support SymbolCast. Support IntSymExpr when/if we actually
// start producing them.
SVal VisitSymIntExpr(const SymIntExpr *S) {
+ auto I = Cached.find(S);
+ if (I != Cached.end())
+ return I->second;
+
SVal LHS = Visit(S->getLHS());
+ if (isUnchanged(S->getLHS(), LHS))
+ return skip(S);
+
SVal RHS;
// By looking at the APSInt in the right-hand side of S, we cannot
// figure out if it should be treated as a Loc or as a NonLoc.
@@ -1059,13 +1288,31 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
} else {
RHS = SVB.makeIntVal(S->getRHS());
}
- return SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType());
+
+ return cache(
+ S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
}
SVal VisitSymSymExpr(const SymSymExpr *S) {
+ auto I = Cached.find(S);
+ if (I != Cached.end())
+ return I->second;
+
+ // For now don't try to simplify mixed Loc/NonLoc expressions
+ // because they often appear from LocAsInteger operations
+ // and we don't know how to combine a LocAsInteger
+ // with a concrete value.
+ if (Loc::isLocType(S->getLHS()->getType()) !=
+ Loc::isLocType(S->getRHS()->getType()))
+ return skip(S);
+
SVal LHS = Visit(S->getLHS());
SVal RHS = Visit(S->getRHS());
- return SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType());
+ if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS))
+ return skip(S);
+
+ return cache(
+ S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
}
SVal VisitSymExpr(SymbolRef S) { return nonloc::SymbolVal(S); }
@@ -1075,13 +1322,20 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
SVal VisitNonLocSymbolVal(nonloc::SymbolVal V) {
// Simplification is much more costly than computing complexity.
// For high complexity, it may be not worth it.
- if (V.getSymbol()->computeComplexity() > 100)
- return V;
return Visit(V.getSymbol());
}
SVal VisitSVal(SVal V) { return V; }
};
- return Simplifier(State).Visit(V);
+ // A crude way of preventing this function from calling itself from evalBinOp.
+ static bool isReentering = false;
+ if (isReentering)
+ return V;
+
+ isReentering = true;
+ SVal SimplifiedV = Simplifier(State).Visit(V);
+ isReentering = false;
+
+ return SimplifiedV;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
index 173fdd8d0056..94188a9ef698 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -1,4 +1,4 @@
-//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==//
+//===- Store.cpp - Interface for maps from Locations to Values ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,18 +12,37 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstdint>
using namespace clang;
using namespace ento;
StoreManager::StoreManager(ProgramStateManager &stateMgr)
- : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
- MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
+ : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
+ MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
StoreRef StoreManager::enterStackFrame(Store OldStore,
const CallEvent &Call,
@@ -33,11 +52,8 @@ StoreRef StoreManager::enterStackFrame(Store OldStore,
SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings;
Call.getInitialStackFrameContents(LCtx, InitialBindings);
- for (CallEvent::BindingsTy::iterator I = InitialBindings.begin(),
- E = InitialBindings.end();
- I != E; ++I) {
- Store = Bind(Store.getStore(), I->first, I->second);
- }
+ for (const auto &I : InitialBindings)
+ Store = Bind(Store.getStore(), I.first, I.second);
return Store;
}
@@ -49,10 +65,6 @@ const ElementRegion *StoreManager::MakeElementRegion(const SubRegion *Base,
return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext());
}
-StoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) {
- return StoreRef(store, *this);
-}
-
const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R,
QualType T) {
NonLoc idx = svalBuilder.makeZeroArrayIndex();
@@ -61,7 +73,6 @@ const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R,
}
const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) {
-
ASTContext &Ctx = StateMgr.getContext();
// Handle casts to Objective-C objects.
@@ -92,7 +103,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
// Handle casts from compatible types.
if (R->isBoundable())
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
+ if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
if (CanonPointeeTy == ObjTy)
return R;
@@ -164,7 +175,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
// Edge case: we are at 0 bytes off the beginning of baseR. We
// check to see if type we are casting to is the same as the base
// region. If so, just return the base region.
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(baseR)) {
+ if (const auto *TR = dyn_cast<TypedValueRegion>(baseR)) {
QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
if (CanonPointeeTy == ObjTy)
@@ -219,7 +230,7 @@ static bool regionMatchesCXXRecordType(SVal V, QualType Ty) {
if (!MR)
return true;
- const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
+ const auto *TVR = dyn_cast<TypedValueRegion>(MR);
if (!TVR)
return true;
@@ -253,11 +264,9 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) {
SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) {
// Walk through the path to create nested CXXBaseRegions.
SVal Result = Derived;
- for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end();
- I != E; ++I) {
- Result = evalDerivedToBase(Result, I->Base->getType(),
- I->Base->isVirtual());
- }
+ for (const auto &I : Path)
+ Result = evalDerivedToBase(Result, I.Base->getType(),
+ I.Base->isVirtual());
return Result;
}
@@ -286,9 +295,9 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
/// symbolic regions, where the dynamic type is merely bounded (and even then,
/// only ostensibly!), but does not take advantage of any dynamic type info.
static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) {
- if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR))
+ if (const auto *TVR = dyn_cast<TypedValueRegion>(MR))
return TVR->getValueType()->getAsCXXRecordDecl();
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
return SR->getSymbol()->getType()->getPointeeCXXRecordDecl();
return nullptr;
}
@@ -327,7 +336,7 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front());
}
- if (const CXXBaseObjectRegion *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) {
+ if (const auto *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) {
// Drill down the chain to get the derived classes.
MR = BaseR->getSuperRegion();
continue;
@@ -348,7 +357,7 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
const MemRegion *Uncasted = MR->StripCasts(/*IncludeBaseCasts=*/false);
if (Uncasted == MR) {
// We reached the bottom of the hierarchy and did not find the derived
- // class. We we must be casting the base to derived, so the cast should
+ // class. We must be casting the base to derived, so the cast should
// fail.
break;
}
@@ -361,27 +370,27 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
return UnknownVal();
}
-
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
- QualType castTy, bool performTestOnly) {
-
+ QualType castTy) {
if (castTy.isNull() || V.isUnknownOrUndef())
return V;
- ASTContext &Ctx = svalBuilder.getContext();
-
- if (performTestOnly) {
- // Automatically translate references to pointers.
- QualType T = R->getValueType();
- if (const ReferenceType *RT = T->getAs<ReferenceType>())
- T = Ctx.getPointerType(RT->getPointeeType());
-
- assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T));
- return V;
- }
+ // When retrieving symbolic pointer and expecting a non-void pointer,
+ // wrap them into element regions of the expected type if necessary.
+ // SValBuilder::dispatchCast() doesn't do that, but it is necessary to
+ // make sure that the retrieved value makes sense, because there's no other
+ // cast in the AST that would tell us to cast it to the correct pointer type.
+ // We might need to do that for non-void pointers as well.
+ // FIXME: We really need a single good function to perform casts for us
+ // correctly every time we need it.
+ if (castTy->isPointerType() && !castTy->isVoidPointerType())
+ if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion()))
+ if (SR->getSymbol()->getType().getCanonicalType() !=
+ castTy.getCanonicalType())
+ return loc::MemRegionVal(castRegion(SR, castTy));
return svalBuilder.dispatchCast(V, castTy);
}
@@ -421,7 +430,7 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
// NOTE: We must have this check first because ObjCIvarDecl is a subclass
// of FieldDecl.
- if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D))
+ if (const auto *ID = dyn_cast<ObjCIvarDecl>(D))
return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR));
return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
@@ -433,28 +442,26 @@ SVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) {
SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
SVal Base) {
-
// If the base is an unknown or undefined value, just return it back.
// FIXME: For absolute pointer addresses, we just return that value back as
// well, although in reality we should return the offset added to that
// value. 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>();
// Pointer of any type can be cast and used as array base.
- const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
+ const auto *ElemR = dyn_cast<ElementRegion>(BaseRegion);
// Convert the offset to the appropriate size and signedness.
Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>();
if (!ElemR) {
- //
// If the base region is not an ElementRegion, create one.
// This can happen in the following example:
//
@@ -462,7 +469,6 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
// p[1] = 8;
//
// Observe that 'p' binds to an AllocaRegion.
- //
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
BaseRegion, Ctx));
}
@@ -499,7 +505,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
Ctx));
}
-StoreManager::BindingsHandler::~BindingsHandler() {}
+StoreManager::BindingsHandler::~BindingsHandler() = default;
bool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr,
Store store,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index f2d5ee83f3cc..ed197010ebb7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -1,4 +1,4 @@
-//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
+//===- SymbolManager.h - Management of Symbolic Values --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,15 +13,27 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
using namespace clang;
using namespace ento;
-void SymExpr::anchor() { }
+void SymExpr::anchor() {}
LLVM_DUMP_METHOD void SymExpr::dump() const {
dumpToStream(llvm::errs());
@@ -88,7 +100,7 @@ void SymbolMetadata::dumpToStream(raw_ostream &os) const {
<< getRegion() << ',' << T.getAsString() << '}';
}
-void SymbolData::anchor() { }
+void SymbolData::anchor() {}
void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
os << "reg_$" << getSymbolID()
@@ -138,7 +150,7 @@ void SymExpr::symbol_iterator::expand() {
itr.push_back(cast<IntSymExpr>(SE)->getRHS());
return;
case SymExpr::SymSymExprKind: {
- const SymSymExpr *x = cast<SymSymExpr>(SE);
+ const auto *x = cast<SymSymExpr>(SE);
itr.push_back(x->getLHS());
itr.push_back(x->getRHS());
return;
@@ -147,13 +159,6 @@ void SymExpr::symbol_iterator::expand() {
llvm_unreachable("unhandled expansion case");
}
-unsigned SymExpr::computeComplexity() const {
- unsigned R = 0;
- for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
- R++;
- return R;
-}
-
const SymbolRegionValue*
SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
llvm::FoldingSetNodeID profile;
@@ -192,7 +197,6 @@ const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
const SymbolDerived*
SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
const TypedValueRegion *R) {
-
llvm::FoldingSetNodeID profile;
SymbolDerived::Profile(profile, parentSymbol, R);
void *InsertPos;
@@ -227,7 +231,6 @@ const SymbolMetadata *
SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
const LocationContext *LCtx,
unsigned Count, const void *SymbolTag) {
-
llvm::FoldingSetNodeID profile;
SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag);
void *InsertPos;
@@ -382,11 +385,10 @@ void SymbolReaper::markDependentsLive(SymbolRef sym) {
LI->second = HaveMarkedDependents;
if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
- for (SymbolRefSmallVectorTy::const_iterator I = Deps->begin(),
- E = Deps->end(); I != E; ++I) {
- if (TheLiving.find(*I) != TheLiving.end())
+ for (const auto I : *Deps) {
+ if (TheLiving.find(I) != TheLiving.end())
continue;
- markLive(*I);
+ markLive(I);
}
}
}
@@ -405,7 +407,7 @@ void SymbolReaper::markLive(const MemRegion *region) {
void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
for (auto SR = dyn_cast<SubRegion>(region); SR;
SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
- if (auto ER = dyn_cast<ElementRegion>(SR)) {
+ if (const auto ER = dyn_cast<ElementRegion>(SR)) {
SVal Idx = ER->getIndex();
for (auto SI = Idx.symbol_begin(), SE = Idx.symbol_end(); SI != SE; ++SI)
markLive(*SI);
@@ -432,10 +434,10 @@ bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
MR = MR->getBaseRegion();
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
return isLive(SR->getSymbol());
- if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
+ if (const auto *VR = dyn_cast<VarRegion>(MR))
return isLive(VR, true);
// FIXME: This is a gross over-approximation. What we really need is a way to
@@ -533,7 +535,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
if (!LCtx)
return false;
- const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
+ const StackFrameContext *CurrentContext = LCtx->getStackFrame();
if (VarContext == CurrentContext) {
// If no statement is provided, everything is live.
@@ -547,7 +549,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
return false;
unsigned &cachedQuery =
- const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
+ const_cast<SymbolReaper *>(this)->includedRegionCache[VR];
if (cachedQuery) {
return cachedQuery == 1;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/WorkList.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/WorkList.cpp
new file mode 100644
index 000000000000..4b227375da9b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/WorkList.cpp
@@ -0,0 +1,254 @@
+//===- WorkList.cpp - Analyzer work-list implementation--------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines different worklist implementations for the static analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "llvm/ADT/PriorityQueue.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include <deque>
+#include <vector>
+
+using namespace clang;
+using namespace ento;
+
+#define DEBUG_TYPE "WorkList"
+
+STATISTIC(MaxQueueSize, "Maximum size of the worklist");
+STATISTIC(MaxReachableSize, "Maximum size of auxiliary worklist set");
+
+//===----------------------------------------------------------------------===//
+// Worklist classes for exploration of reachable states.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class DFS : public WorkList {
+ SmallVector<WorkListUnit, 20> Stack;
+
+public:
+ bool hasWork() const override {
+ return !Stack.empty();
+ }
+
+ void enqueue(const WorkListUnit& U) override {
+ Stack.push_back(U);
+ }
+
+ WorkListUnit dequeue() override {
+ assert(!Stack.empty());
+ const WorkListUnit& U = Stack.back();
+ Stack.pop_back(); // This technically "invalidates" U, but we are fine.
+ return U;
+ }
+};
+
+class BFS : public WorkList {
+ std::deque<WorkListUnit> Queue;
+
+public:
+ bool hasWork() const override {
+ return !Queue.empty();
+ }
+
+ void enqueue(const WorkListUnit& U) override {
+ Queue.push_back(U);
+ }
+
+ WorkListUnit dequeue() override {
+ WorkListUnit U = Queue.front();
+ Queue.pop_front();
+ return U;
+ }
+};
+
+} // namespace
+
+// Place the dstor for WorkList here because it contains virtual member
+// functions, and we the code for the dstor generated in one compilation unit.
+WorkList::~WorkList() = default;
+
+std::unique_ptr<WorkList> WorkList::makeDFS() {
+ return llvm::make_unique<DFS>();
+}
+
+std::unique_ptr<WorkList> WorkList::makeBFS() {
+ return llvm::make_unique<BFS>();
+}
+
+namespace {
+
+ class BFSBlockDFSContents : public WorkList {
+ std::deque<WorkListUnit> Queue;
+ SmallVector<WorkListUnit, 20> Stack;
+
+ public:
+ bool hasWork() const override {
+ return !Queue.empty() || !Stack.empty();
+ }
+
+ void enqueue(const WorkListUnit& U) override {
+ if (U.getNode()->getLocation().getAs<BlockEntrance>())
+ Queue.push_front(U);
+ else
+ Stack.push_back(U);
+ }
+
+ WorkListUnit dequeue() override {
+ // Process all basic blocks to completion.
+ if (!Stack.empty()) {
+ const WorkListUnit& U = Stack.back();
+ Stack.pop_back(); // This technically "invalidates" U, but we are fine.
+ return U;
+ }
+
+ assert(!Queue.empty());
+ // Don't use const reference. The subsequent pop_back() might make it
+ // unsafe.
+ WorkListUnit U = Queue.front();
+ Queue.pop_front();
+ return U;
+ }
+ };
+
+} // namespace
+
+std::unique_ptr<WorkList> WorkList::makeBFSBlockDFSContents() {
+ return llvm::make_unique<BFSBlockDFSContents>();
+}
+
+namespace {
+
+class UnexploredFirstStack : public WorkList {
+ /// Stack of nodes known to have statements we have not traversed yet.
+ SmallVector<WorkListUnit, 20> StackUnexplored;
+
+ /// Stack of all other nodes.
+ SmallVector<WorkListUnit, 20> StackOthers;
+
+ using BlockID = unsigned;
+ using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
+
+ llvm::DenseSet<LocIdentifier> Reachable;
+
+public:
+ bool hasWork() const override {
+ return !(StackUnexplored.empty() && StackOthers.empty());
+ }
+
+ void enqueue(const WorkListUnit &U) override {
+ const ExplodedNode *N = U.getNode();
+ auto BE = N->getLocation().getAs<BlockEntrance>();
+
+ if (!BE) {
+ // Assume the choice of the order of the preceeding block entrance was
+ // correct.
+ StackUnexplored.push_back(U);
+ } else {
+ LocIdentifier LocId = std::make_pair(
+ BE->getBlock()->getBlockID(),
+ N->getLocationContext()->getStackFrame());
+ auto InsertInfo = Reachable.insert(LocId);
+
+ if (InsertInfo.second) {
+ StackUnexplored.push_back(U);
+ } else {
+ StackOthers.push_back(U);
+ }
+ }
+ MaxReachableSize.updateMax(Reachable.size());
+ MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size());
+ }
+
+ WorkListUnit dequeue() override {
+ if (!StackUnexplored.empty()) {
+ WorkListUnit &U = StackUnexplored.back();
+ StackUnexplored.pop_back();
+ return U;
+ } else {
+ WorkListUnit &U = StackOthers.back();
+ StackOthers.pop_back();
+ return U;
+ }
+ }
+};
+
+} // namespace
+
+std::unique_ptr<WorkList> WorkList::makeUnexploredFirst() {
+ return llvm::make_unique<UnexploredFirstStack>();
+}
+
+namespace {
+class UnexploredFirstPriorityQueue : public WorkList {
+ using BlockID = unsigned;
+ using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
+
+ // How many times each location was visited.
+ // Is signed because we negate it later in order to have a reversed
+ // comparison.
+ using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
+
+ // Compare by number of times the location was visited first (negated
+ // to prefer less often visited locations), then by insertion time (prefer
+ // expanding nodes inserted sooner first).
+ using QueuePriority = std::pair<int, unsigned long>;
+ using QueueItem = std::pair<WorkListUnit, QueuePriority>;
+
+ struct ExplorationComparator {
+ bool operator() (const QueueItem &LHS, const QueueItem &RHS) {
+ return LHS.second < RHS.second;
+ }
+ };
+
+ // Number of inserted nodes, used to emulate DFS ordering in the priority
+ // queue when insertions are equal.
+ unsigned long Counter = 0;
+
+ // Number of times a current location was reached.
+ VisitedTimesMap NumReached;
+
+ // The top item is the largest one.
+ llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
+ queue;
+
+public:
+ bool hasWork() const override {
+ return !queue.empty();
+ }
+
+ void enqueue(const WorkListUnit &U) override {
+ const ExplodedNode *N = U.getNode();
+ unsigned NumVisited = 0;
+ if (auto BE = N->getLocation().getAs<BlockEntrance>()) {
+ LocIdentifier LocId = std::make_pair(
+ BE->getBlock()->getBlockID(),
+ N->getLocationContext()->getStackFrame());
+ NumVisited = NumReached[LocId]++;
+ }
+
+ queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
+ }
+
+ WorkListUnit dequeue() override {
+ QueueItem U = queue.top();
+ queue.pop();
+ return U.first;
+ }
+};
+} // namespace
+
+std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityQueue() {
+ return llvm::make_unique<UnexploredFirstPriorityQueue>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
index f9f9057a89cd..7379ded49c80 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -10,7 +10,11 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h"
#include "clang/Config/config.h"
@@ -21,30 +25,9 @@ using namespace ento;
#include <z3.h>
-// Forward declarations
-namespace {
-class Z3Expr;
-class ConstraintZ3 {};
-} // end anonymous namespace
-
-typedef llvm::ImmutableSet<std::pair<SymbolRef, Z3Expr>> ConstraintZ3Ty;
-
-// Expansion of REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintZ3, Z3SetPair)
-namespace clang {
-namespace ento {
-template <>
-struct ProgramStateTrait<ConstraintZ3>
- : public ProgramStatePartialTrait<ConstraintZ3Ty> {
- static void *GDMIndex() {
- static int Index;
- return &Index;
- }
-};
-} // end namespace ento
-} // end namespace clang
-
namespace {
+/// Configuration class for Z3
class Z3Config {
friend class Z3Context;
@@ -63,45 +46,60 @@ public:
~Z3Config() { Z3_del_config(Config); }
}; // end class Z3Config
-class Z3Context {
- Z3_context ZC_P;
+// Function used to report errors
+void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) {
+ llvm::report_fatal_error("Z3 error: " +
+ llvm::Twine(Z3_get_error_msg_ex(Context, Error)));
+}
+/// Wrapper for Z3 context
+class Z3Context : public SMTContext {
public:
- static Z3_context ZC;
+ Z3_context Context;
- Z3Context() : ZC_P(Z3_mk_context_rc(Z3Config().Config)) { ZC = ZC_P; }
+ Z3Context() : SMTContext() {
+ Context = Z3_mk_context_rc(Z3Config().Config);
+ // The error function is set here because the context is the first object
+ // created by the backend
+ Z3_set_error_handler(Context, Z3ErrorHandler);
+ }
- ~Z3Context() {
- Z3_del_context(ZC);
- Z3_finalize_memory();
- ZC_P = nullptr;
+ virtual ~Z3Context() {
+ Z3_del_context(Context);
+ Context = nullptr;
}
}; // end class Z3Context
-class Z3Sort {
- friend class Z3Expr;
+/// Wrapper for Z3 Sort
+class Z3Sort : public SMTSort {
+ friend class Z3Solver;
+
+ Z3Context &Context;
Z3_sort Sort;
- Z3Sort() : Sort(nullptr) {}
- Z3Sort(Z3_sort ZS) : Sort(ZS) {
- Z3_inc_ref(Z3Context::ZC, reinterpret_cast<Z3_ast>(Sort));
+public:
+ /// Default constructor, mainly used by make_shared
+ Z3Sort(Z3Context &C, Z3_sort ZS) : SMTSort(), Context(C), Sort(ZS) {
+ Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
}
-public:
/// Override implicit copy constructor for correct reference counting.
- Z3Sort(const Z3Sort &Copy) : Sort(Copy.Sort) {
- Z3_inc_ref(Z3Context::ZC, reinterpret_cast<Z3_ast>(Sort));
+ Z3Sort(const Z3Sort &Copy)
+ : SMTSort(), Context(Copy.Context), Sort(Copy.Sort) {
+ Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
}
/// Provide move constructor
- Z3Sort(Z3Sort &&Move) : Sort(nullptr) { *this = std::move(Move); }
+ Z3Sort(Z3Sort &&Move) : SMTSort(), Context(Move.Context), Sort(nullptr) {
+ *this = std::move(Move);
+ }
/// Provide move assignment constructor
Z3Sort &operator=(Z3Sort &&Move) {
if (this != &Move) {
if (Sort)
- Z3_dec_ref(Z3Context::ZC, reinterpret_cast<Z3_ast>(Sort));
+ Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
Sort = Move.Sort;
Move.Sort = nullptr;
}
@@ -110,119 +108,78 @@ public:
~Z3Sort() {
if (Sort)
- Z3_dec_ref(Z3Context::ZC, reinterpret_cast<Z3_ast>(Sort));
- }
-
- // Return a boolean sort.
- static Z3Sort getBoolSort() { return Z3Sort(Z3_mk_bool_sort(Z3Context::ZC)); }
-
- // Return an appropriate bitvector sort for the given bitwidth.
- static Z3Sort getBitvectorSort(unsigned BitWidth) {
- return Z3Sort(Z3_mk_bv_sort(Z3Context::ZC, BitWidth));
- }
-
- // Return an appropriate floating-point sort for the given bitwidth.
- static Z3Sort getFloatSort(unsigned BitWidth) {
- Z3_sort Sort;
-
- switch (BitWidth) {
- default:
- llvm_unreachable("Unsupported floating-point bitwidth!");
- break;
- case 16:
- Sort = Z3_mk_fpa_sort_16(Z3Context::ZC);
- break;
- case 32:
- Sort = Z3_mk_fpa_sort_32(Z3Context::ZC);
- break;
- case 64:
- Sort = Z3_mk_fpa_sort_64(Z3Context::ZC);
- break;
- case 128:
- Sort = Z3_mk_fpa_sort_128(Z3Context::ZC);
- break;
- }
- return Z3Sort(Sort);
+ Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
}
- // Return an appropriate sort for the given AST.
- static Z3Sort getSort(Z3_ast AST) {
- return Z3Sort(Z3_get_sort(Z3Context::ZC, AST));
+ bool isBitvectorSortImpl() const override {
+ return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BV_SORT);
}
- Z3_sort_kind getSortKind() const {
- return Z3_get_sort_kind(Z3Context::ZC, Sort);
+ bool isFloatSortImpl() const override {
+ return (Z3_get_sort_kind(Context.Context, Sort) == Z3_FLOATING_POINT_SORT);
}
- unsigned getBitvectorSortSize() const {
- assert(getSortKind() == Z3_BV_SORT && "Not a bitvector sort!");
- return Z3_get_bv_sort_size(Z3Context::ZC, Sort);
+ bool isBooleanSortImpl() const override {
+ return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BOOL_SORT);
}
- unsigned getFloatSortSize() const {
- assert(getSortKind() == Z3_FLOATING_POINT_SORT &&
- "Not a floating-point sort!");
- return Z3_fpa_get_ebits(Z3Context::ZC, Sort) +
- Z3_fpa_get_sbits(Z3Context::ZC, Sort);
+ unsigned getBitvectorSortSizeImpl() const override {
+ return Z3_get_bv_sort_size(Context.Context, Sort);
}
- bool operator==(const Z3Sort &Other) const {
- return Z3_is_eq_sort(Z3Context::ZC, Sort, Other.Sort);
+ unsigned getFloatSortSizeImpl() const override {
+ return Z3_fpa_get_ebits(Context.Context, Sort) +
+ Z3_fpa_get_sbits(Context.Context, Sort);
+ }
+
+ bool equal_to(SMTSort const &Other) const override {
+ return Z3_is_eq_sort(Context.Context, Sort,
+ static_cast<const Z3Sort &>(Other).Sort);
}
Z3Sort &operator=(const Z3Sort &Move) {
- Z3_inc_ref(Z3Context::ZC, reinterpret_cast<Z3_ast>(Move.Sort));
- Z3_dec_ref(Z3Context::ZC, reinterpret_cast<Z3_ast>(Sort));
+ Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Move.Sort));
+ Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
Sort = Move.Sort;
return *this;
}
- void print(raw_ostream &OS) const {
- OS << Z3_sort_to_string(Z3Context::ZC, Sort);
+ void print(raw_ostream &OS) const override {
+ OS << Z3_sort_to_string(Context.Context, Sort);
}
-
- LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
}; // end class Z3Sort
-class Z3Expr {
- friend class Z3Model;
- friend class Z3Solver;
+static const Z3Sort &toZ3Sort(const SMTSort &S) {
+ return static_cast<const Z3Sort &>(S);
+}
- Z3_ast AST;
+class Z3Expr : public SMTExpr {
+ friend class Z3Solver;
- Z3Expr(Z3_ast ZA) : AST(ZA) { Z3_inc_ref(Z3Context::ZC, AST); }
+ Z3Context &Context;
- // Return an appropriate floating-point rounding mode.
- static Z3Expr getFloatRoundingMode() {
- // TODO: Don't assume nearest ties to even rounding mode
- return Z3Expr(Z3_mk_fpa_rne(Z3Context::ZC));
- }
+ Z3_ast AST;
- // Determine whether two float semantics are equivalent
- static bool areEquivalent(const llvm::fltSemantics &LHS,
- const llvm::fltSemantics &RHS) {
- return (llvm::APFloat::semanticsPrecision(LHS) ==
- llvm::APFloat::semanticsPrecision(RHS)) &&
- (llvm::APFloat::semanticsMinExponent(LHS) ==
- llvm::APFloat::semanticsMinExponent(RHS)) &&
- (llvm::APFloat::semanticsMaxExponent(LHS) ==
- llvm::APFloat::semanticsMaxExponent(RHS)) &&
- (llvm::APFloat::semanticsSizeInBits(LHS) ==
- llvm::APFloat::semanticsSizeInBits(RHS));
+public:
+ Z3Expr(Z3Context &C, Z3_ast ZA) : SMTExpr(), Context(C), AST(ZA) {
+ Z3_inc_ref(Context.Context, AST);
}
-public:
/// Override implicit copy constructor for correct reference counting.
- Z3Expr(const Z3Expr &Copy) : AST(Copy.AST) { Z3_inc_ref(Z3Context::ZC, AST); }
+ Z3Expr(const Z3Expr &Copy) : SMTExpr(), Context(Copy.Context), AST(Copy.AST) {
+ Z3_inc_ref(Context.Context, AST);
+ }
/// Provide move constructor
- Z3Expr(Z3Expr &&Move) : AST(nullptr) { *this = std::move(Move); }
+ Z3Expr(Z3Expr &&Move) : SMTExpr(), Context(Move.Context), AST(nullptr) {
+ *this = std::move(Move);
+ }
/// Provide move assignment constructor
Z3Expr &operator=(Z3Expr &&Move) {
if (this != &Move) {
if (AST)
- Z3_dec_ref(Z3Context::ZC, AST);
+ Z3_dec_ref(Context.Context, AST);
AST = Move.AST;
Move.AST = nullptr;
}
@@ -231,1388 +188,854 @@ public:
~Z3Expr() {
if (AST)
- Z3_dec_ref(Z3Context::ZC, AST);
- }
-
- /// Get the corresponding IEEE floating-point type for a given bitwidth.
- static const llvm::fltSemantics &getFloatSemantics(unsigned BitWidth) {
- switch (BitWidth) {
- default:
- llvm_unreachable("Unsupported floating-point semantics!");
- break;
- case 16:
- return llvm::APFloat::IEEEhalf();
- case 32:
- return llvm::APFloat::IEEEsingle();
- case 64:
- return llvm::APFloat::IEEEdouble();
- case 128:
- return llvm::APFloat::IEEEquad();
- }
+ Z3_dec_ref(Context.Context, AST);
}
- /// Construct a Z3Expr from a unary operator, given a Z3_context.
- static Z3Expr fromUnOp(const UnaryOperator::Opcode Op, const Z3Expr &Exp) {
- Z3_ast AST;
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ ID.AddInteger(Z3_get_ast_hash(Context.Context, AST));
+ }
- switch (Op) {
- default:
- llvm_unreachable("Unimplemented opcode");
- break;
+ /// Comparison of AST equality, not model equivalence.
+ bool equal_to(SMTExpr const &Other) const override {
+ assert(Z3_is_eq_sort(Context.Context, Z3_get_sort(Context.Context, AST),
+ Z3_get_sort(Context.Context,
+ static_cast<const Z3Expr &>(Other).AST)) &&
+ "AST's must have the same sort");
+ return Z3_is_eq_ast(Context.Context, AST,
+ static_cast<const Z3Expr &>(Other).AST);
+ }
- case UO_Minus:
- AST = Z3_mk_bvneg(Z3Context::ZC, Exp.AST);
- break;
+ /// Override implicit move constructor for correct reference counting.
+ Z3Expr &operator=(const Z3Expr &Move) {
+ Z3_inc_ref(Context.Context, Move.AST);
+ Z3_dec_ref(Context.Context, AST);
+ AST = Move.AST;
+ return *this;
+ }
- case UO_Not:
- AST = Z3_mk_bvnot(Z3Context::ZC, Exp.AST);
- break;
+ void print(raw_ostream &OS) const override {
+ OS << Z3_ast_to_string(Context.Context, AST);
+ }
+}; // end class Z3Expr
- case UO_LNot:
- AST = Z3_mk_not(Z3Context::ZC, Exp.AST);
- break;
- }
+static const Z3Expr &toZ3Expr(const SMTExpr &E) {
+ return static_cast<const Z3Expr &>(E);
+}
- return Z3Expr(AST);
- }
+class Z3Model {
+ friend class Z3Solver;
+
+ Z3Context &Context;
+
+ Z3_model Model;
- /// Construct a Z3Expr from a floating-point unary operator, given a
- /// Z3_context.
- static Z3Expr fromFloatUnOp(const UnaryOperator::Opcode Op,
- const Z3Expr &Exp) {
- Z3_ast AST;
+public:
+ Z3Model(Z3Context &C, Z3_model ZM) : Context(C), Model(ZM) {
+ assert(C.Context != nullptr);
+ Z3_model_inc_ref(Context.Context, Model);
+ }
- switch (Op) {
- default:
- llvm_unreachable("Unimplemented opcode");
- break;
+ /// Override implicit copy constructor for correct reference counting.
+ Z3Model(const Z3Model &Copy) : Context(Copy.Context), Model(Copy.Model) {
+ Z3_model_inc_ref(Context.Context, Model);
+ }
- case UO_Minus:
- AST = Z3_mk_fpa_neg(Z3Context::ZC, Exp.AST);
- break;
+ /// Provide move constructor
+ Z3Model(Z3Model &&Move) : Context(Move.Context), Model(nullptr) {
+ *this = std::move(Move);
+ }
- case UO_LNot:
- return Z3Expr::fromUnOp(Op, Exp);
+ /// Provide move assignment constructor
+ Z3Model &operator=(Z3Model &&Move) {
+ if (this != &Move) {
+ if (Model)
+ Z3_model_dec_ref(Context.Context, Model);
+ Model = Move.Model;
+ Move.Model = nullptr;
}
+ return *this;
+ }
- return Z3Expr(AST);
+ ~Z3Model() {
+ if (Model)
+ Z3_model_dec_ref(Context.Context, Model);
}
- /// Construct a Z3Expr from a n-ary binary operator.
- static Z3Expr fromNBinOp(const BinaryOperator::Opcode Op,
- const std::vector<Z3_ast> &ASTs) {
- Z3_ast AST;
+ void print(raw_ostream &OS) const {
+ OS << Z3_model_to_string(Context.Context, Model);
+ }
- switch (Op) {
- default:
- llvm_unreachable("Unimplemented opcode");
- break;
+ LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
+}; // end class Z3Model
- case BO_LAnd:
- AST = Z3_mk_and(Z3Context::ZC, ASTs.size(), ASTs.data());
- break;
+/// Get the corresponding IEEE floating-point type for a given bitwidth.
+static const llvm::fltSemantics &getFloatSemantics(unsigned BitWidth) {
+ switch (BitWidth) {
+ default:
+ llvm_unreachable("Unsupported floating-point semantics!");
+ break;
+ case 16:
+ return llvm::APFloat::IEEEhalf();
+ case 32:
+ return llvm::APFloat::IEEEsingle();
+ case 64:
+ return llvm::APFloat::IEEEdouble();
+ case 128:
+ return llvm::APFloat::IEEEquad();
+ }
+}
- case BO_LOr:
- AST = Z3_mk_or(Z3Context::ZC, ASTs.size(), ASTs.data());
- break;
- }
+// Determine whether two float semantics are equivalent
+static bool areEquivalent(const llvm::fltSemantics &LHS,
+ const llvm::fltSemantics &RHS) {
+ return (llvm::APFloat::semanticsPrecision(LHS) ==
+ llvm::APFloat::semanticsPrecision(RHS)) &&
+ (llvm::APFloat::semanticsMinExponent(LHS) ==
+ llvm::APFloat::semanticsMinExponent(RHS)) &&
+ (llvm::APFloat::semanticsMaxExponent(LHS) ==
+ llvm::APFloat::semanticsMaxExponent(RHS)) &&
+ (llvm::APFloat::semanticsSizeInBits(LHS) ==
+ llvm::APFloat::semanticsSizeInBits(RHS));
+}
- return Z3Expr(AST);
- }
-
- /// Construct a Z3Expr from a binary operator, given a Z3_context.
- static Z3Expr fromBinOp(const Z3Expr &LHS, const BinaryOperator::Opcode Op,
- const Z3Expr &RHS, bool isSigned) {
- Z3_ast AST;
-
- assert(Z3Sort::getSort(LHS.AST) == Z3Sort::getSort(RHS.AST) &&
- "AST's must have the same sort!");
-
- switch (Op) {
- default:
- llvm_unreachable("Unimplemented opcode");
- break;
-
- // Multiplicative operators
- case BO_Mul:
- AST = Z3_mk_bvmul(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_Div:
- AST = isSigned ? Z3_mk_bvsdiv(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvudiv(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_Rem:
- AST = isSigned ? Z3_mk_bvsrem(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvurem(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Additive operators
- case BO_Add:
- AST = Z3_mk_bvadd(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_Sub:
- AST = Z3_mk_bvsub(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Bitwise shift operators
- case BO_Shl:
- AST = Z3_mk_bvshl(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_Shr:
- AST = isSigned ? Z3_mk_bvashr(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvlshr(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Relational operators
- case BO_LT:
- AST = isSigned ? Z3_mk_bvslt(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvult(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_GT:
- AST = isSigned ? Z3_mk_bvsgt(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvugt(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_LE:
- AST = isSigned ? Z3_mk_bvsle(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvule(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_GE:
- AST = isSigned ? Z3_mk_bvsge(Z3Context::ZC, LHS.AST, RHS.AST)
- : Z3_mk_bvuge(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Equality operators
- case BO_EQ:
- AST = Z3_mk_eq(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_NE:
- return Z3Expr::fromUnOp(UO_LNot,
- Z3Expr::fromBinOp(LHS, BO_EQ, RHS, isSigned));
- break;
-
- // Bitwise operators
- case BO_And:
- AST = Z3_mk_bvand(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_Xor:
- AST = Z3_mk_bvxor(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_Or:
- AST = Z3_mk_bvor(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Logical operators
- case BO_LAnd:
- case BO_LOr: {
- std::vector<Z3_ast> Args = {LHS.AST, RHS.AST};
- return Z3Expr::fromNBinOp(Op, Args);
- }
- }
+} // end anonymous namespace
- return Z3Expr(AST);
- }
-
- /// Construct a Z3Expr from a special floating-point binary operator, given
- /// a Z3_context.
- static Z3Expr fromFloatSpecialBinOp(const Z3Expr &LHS,
- const BinaryOperator::Opcode Op,
- const llvm::APFloat::fltCategory &RHS) {
- Z3_ast AST;
-
- switch (Op) {
- default:
- llvm_unreachable("Unimplemented opcode");
- break;
-
- // Equality operators
- case BO_EQ:
- switch (RHS) {
- case llvm::APFloat::fcInfinity:
- AST = Z3_mk_fpa_is_infinite(Z3Context::ZC, LHS.AST);
- break;
- case llvm::APFloat::fcNaN:
- AST = Z3_mk_fpa_is_nan(Z3Context::ZC, LHS.AST);
- break;
- case llvm::APFloat::fcNormal:
- AST = Z3_mk_fpa_is_normal(Z3Context::ZC, LHS.AST);
- break;
- case llvm::APFloat::fcZero:
- AST = Z3_mk_fpa_is_zero(Z3Context::ZC, LHS.AST);
- break;
- }
- break;
- case BO_NE:
- return Z3Expr::fromFloatUnOp(
- UO_LNot, Z3Expr::fromFloatSpecialBinOp(LHS, BO_EQ, RHS));
- break;
- }
+typedef llvm::ImmutableSet<std::pair<SymbolRef, Z3Expr>> ConstraintZ3Ty;
+REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintZ3, ConstraintZ3Ty)
- return Z3Expr(AST);
- }
+namespace {
- /// Construct a Z3Expr from a floating-point binary operator, given a
- /// Z3_context.
- static Z3Expr fromFloatBinOp(const Z3Expr &LHS,
- const BinaryOperator::Opcode Op,
- const Z3Expr &RHS) {
- Z3_ast AST;
+class Z3Solver : public SMTSolver {
+ friend class Z3ConstraintManager;
- assert(Z3Sort::getSort(LHS.AST) == Z3Sort::getSort(RHS.AST) &&
- "AST's must have the same sort!");
+ Z3Context Context;
- switch (Op) {
- default:
- llvm_unreachable("Unimplemented opcode");
- break;
+ Z3_solver Solver;
- // Multiplicative operators
- case BO_Mul: {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- AST = Z3_mk_fpa_mul(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST);
- break;
- }
- case BO_Div: {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- AST = Z3_mk_fpa_div(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST);
- break;
- }
- case BO_Rem:
- AST = Z3_mk_fpa_rem(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Additive operators
- case BO_Add: {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- AST = Z3_mk_fpa_add(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST);
- break;
- }
- case BO_Sub: {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- AST = Z3_mk_fpa_sub(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST);
- break;
- }
+public:
+ Z3Solver() : SMTSolver(), Solver(Z3_mk_simple_solver(Context.Context)) {
+ Z3_solver_inc_ref(Context.Context, Solver);
+ }
+
+ /// Override implicit copy constructor for correct reference counting.
+ Z3Solver(const Z3Solver &Copy)
+ : SMTSolver(), Context(Copy.Context), Solver(Copy.Solver) {
+ Z3_solver_inc_ref(Context.Context, Solver);
+ }
+
+ /// Provide move constructor
+ Z3Solver(Z3Solver &&Move)
+ : SMTSolver(), Context(Move.Context), Solver(nullptr) {
+ *this = std::move(Move);
+ }
- // Relational operators
- case BO_LT:
- AST = Z3_mk_fpa_lt(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_GT:
- AST = Z3_mk_fpa_gt(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_LE:
- AST = Z3_mk_fpa_leq(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_GE:
- AST = Z3_mk_fpa_geq(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
-
- // Equality operators
- case BO_EQ:
- AST = Z3_mk_fpa_eq(Z3Context::ZC, LHS.AST, RHS.AST);
- break;
- case BO_NE:
- return Z3Expr::fromFloatUnOp(UO_LNot,
- Z3Expr::fromFloatBinOp(LHS, BO_EQ, RHS));
- break;
-
- // Logical operators
- case BO_LAnd:
- case BO_LOr:
- return Z3Expr::fromBinOp(LHS, Op, RHS, false);
+ /// Provide move assignment constructor
+ Z3Solver &operator=(Z3Solver &&Move) {
+ if (this != &Move) {
+ if (Solver)
+ Z3_solver_dec_ref(Context.Context, Solver);
+ Solver = Move.Solver;
+ Move.Solver = nullptr;
}
+ return *this;
+ }
- return Z3Expr(AST);
+ ~Z3Solver() {
+ if (Solver)
+ Z3_solver_dec_ref(Context.Context, Solver);
}
- /// Construct a Z3Expr from a SymbolData, given a Z3_context.
- static Z3Expr fromData(const SymbolID ID, bool isBool, bool isFloat,
- uint64_t BitWidth) {
- llvm::Twine Name = "$" + llvm::Twine(ID);
+ void addConstraint(const SMTExprRef &Exp) const override {
+ Z3_solver_assert(Context.Context, Solver, toZ3Expr(*Exp).AST);
+ }
- Z3Sort Sort;
- if (isBool)
- Sort = Z3Sort::getBoolSort();
- else if (isFloat)
- Sort = Z3Sort::getFloatSort(BitWidth);
- else
- Sort = Z3Sort::getBitvectorSort(BitWidth);
-
- Z3_symbol Symbol = Z3_mk_string_symbol(Z3Context::ZC, Name.str().c_str());
- Z3_ast AST = Z3_mk_const(Z3Context::ZC, Symbol, Sort.Sort);
- return Z3Expr(AST);
- }
-
- /// Construct a Z3Expr from a SymbolCast, given a Z3_context.
- static Z3Expr fromCast(const Z3Expr &Exp, QualType ToTy, uint64_t ToBitWidth,
- QualType FromTy, uint64_t FromBitWidth) {
- Z3_ast AST;
-
- if ((FromTy->isIntegralOrEnumerationType() &&
- ToTy->isIntegralOrEnumerationType()) ||
- (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) ||
- (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) ||
- (FromTy->isReferenceType() ^ ToTy->isReferenceType())) {
- // Special case: Z3 boolean type is distinct from bitvector type, so
- // must use if-then-else expression instead of direct cast
- if (FromTy->isBooleanType()) {
- assert(ToBitWidth > 0 && "BitWidth must be positive!");
- Z3Expr Zero = Z3Expr::fromInt("0", ToBitWidth);
- Z3Expr One = Z3Expr::fromInt("1", ToBitWidth);
- AST = Z3_mk_ite(Z3Context::ZC, Exp.AST, One.AST, Zero.AST);
- } else if (ToBitWidth > FromBitWidth) {
- AST = FromTy->isSignedIntegerOrEnumerationType()
- ? Z3_mk_sign_ext(Z3Context::ZC, ToBitWidth - FromBitWidth,
- Exp.AST)
- : Z3_mk_zero_ext(Z3Context::ZC, ToBitWidth - FromBitWidth,
- Exp.AST);
- } else if (ToBitWidth < FromBitWidth) {
- AST = Z3_mk_extract(Z3Context::ZC, ToBitWidth - 1, 0, Exp.AST);
- } else {
- // Both are bitvectors with the same width, ignore the type cast
- return Exp;
- }
- } else if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) {
- if (ToBitWidth != FromBitWidth) {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- Z3Sort Sort = Z3Sort::getFloatSort(ToBitWidth);
- AST = Z3_mk_fpa_to_fp_float(Z3Context::ZC, RoundingMode.AST, Exp.AST,
- Sort.Sort);
- } else {
- return Exp;
- }
- } else if (FromTy->isIntegralOrEnumerationType() &&
- ToTy->isRealFloatingType()) {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- Z3Sort Sort = Z3Sort::getFloatSort(ToBitWidth);
- AST = FromTy->isSignedIntegerOrEnumerationType()
- ? Z3_mk_fpa_to_fp_signed(Z3Context::ZC, RoundingMode.AST,
- Exp.AST, Sort.Sort)
- : Z3_mk_fpa_to_fp_unsigned(Z3Context::ZC, RoundingMode.AST,
- Exp.AST, Sort.Sort);
- } else if (FromTy->isRealFloatingType() &&
- ToTy->isIntegralOrEnumerationType()) {
- Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode();
- AST = ToTy->isSignedIntegerOrEnumerationType()
- ? Z3_mk_fpa_to_sbv(Z3Context::ZC, RoundingMode.AST, Exp.AST,
- ToBitWidth)
- : Z3_mk_fpa_to_ubv(Z3Context::ZC, RoundingMode.AST, Exp.AST,
- ToBitWidth);
- } else {
- llvm_unreachable("Unsupported explicit type cast!");
- }
+ SMTSortRef getBoolSort() override {
+ return std::make_shared<Z3Sort>(Context, Z3_mk_bool_sort(Context.Context));
+ }
- return Z3Expr(AST);
+ SMTSortRef getBitvectorSort(unsigned BitWidth) override {
+ return std::make_shared<Z3Sort>(Context,
+ Z3_mk_bv_sort(Context.Context, BitWidth));
}
- /// Construct a Z3Expr from a boolean, given a Z3_context.
- static Z3Expr fromBoolean(const bool Bool) {
- Z3_ast AST = Bool ? Z3_mk_true(Z3Context::ZC) : Z3_mk_false(Z3Context::ZC);
- return Z3Expr(AST);
+ SMTSortRef getSort(const SMTExprRef &Exp) override {
+ return std::make_shared<Z3Sort>(
+ Context, Z3_get_sort(Context.Context, toZ3Expr(*Exp).AST));
}
- /// Construct a Z3Expr from a finite APFloat, given a Z3_context.
- static Z3Expr fromAPFloat(const llvm::APFloat &Float) {
- Z3_ast AST;
- Z3Sort Sort = Z3Sort::getFloatSort(
- llvm::APFloat::semanticsSizeInBits(Float.getSemantics()));
+ SMTSortRef getFloat16Sort() override {
+ return std::make_shared<Z3Sort>(Context,
+ Z3_mk_fpa_sort_16(Context.Context));
+ }
- llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), true);
- Z3Expr Z3Int = Z3Expr::fromAPSInt(Int);
- AST = Z3_mk_fpa_to_fp_bv(Z3Context::ZC, Z3Int.AST, Sort.Sort);
+ SMTSortRef getFloat32Sort() override {
+ return std::make_shared<Z3Sort>(Context,
+ Z3_mk_fpa_sort_32(Context.Context));
+ }
- return Z3Expr(AST);
+ SMTSortRef getFloat64Sort() override {
+ return std::make_shared<Z3Sort>(Context,
+ Z3_mk_fpa_sort_64(Context.Context));
}
- /// Construct a Z3Expr from an APSInt, given a Z3_context.
- static Z3Expr fromAPSInt(const llvm::APSInt &Int) {
- Z3Sort Sort = Z3Sort::getBitvectorSort(Int.getBitWidth());
- Z3_ast AST =
- Z3_mk_numeral(Z3Context::ZC, Int.toString(10).c_str(), Sort.Sort);
- return Z3Expr(AST);
+ SMTSortRef getFloat128Sort() override {
+ return std::make_shared<Z3Sort>(Context,
+ Z3_mk_fpa_sort_128(Context.Context));
}
- /// Construct a Z3Expr from an integer, given a Z3_context.
- static Z3Expr fromInt(const char *Int, uint64_t BitWidth) {
- Z3Sort Sort = Z3Sort::getBitvectorSort(BitWidth);
- Z3_ast AST = Z3_mk_numeral(Z3Context::ZC, Int, Sort.Sort);
- return Z3Expr(AST);
+ SMTExprRef newExprRef(const SMTExpr &E) const override {
+ return std::make_shared<Z3Expr>(toZ3Expr(E));
}
- /// Construct an APFloat from a Z3Expr, given the AST representation
- static bool toAPFloat(const Z3Sort &Sort, const Z3_ast &AST,
- llvm::APFloat &Float, bool useSemantics = true) {
- assert(Sort.getSortKind() == Z3_FLOATING_POINT_SORT &&
- "Unsupported sort to floating-point!");
+ SMTExprRef mkBVNeg(const SMTExprRef &Exp) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvneg(Context.Context, toZ3Expr(*Exp).AST)));
+ }
- llvm::APSInt Int(Sort.getFloatSortSize(), true);
- const llvm::fltSemantics &Semantics =
- Z3Expr::getFloatSemantics(Sort.getFloatSortSize());
- Z3Sort BVSort = Z3Sort::getBitvectorSort(Sort.getFloatSortSize());
- if (!Z3Expr::toAPSInt(BVSort, AST, Int, true)) {
- return false;
- }
+ SMTExprRef mkBVNot(const SMTExprRef &Exp) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvnot(Context.Context, toZ3Expr(*Exp).AST)));
+ }
- if (useSemantics &&
- !Z3Expr::areEquivalent(Float.getSemantics(), Semantics)) {
- assert(false && "Floating-point types don't match!");
- return false;
- }
+ SMTExprRef mkNot(const SMTExprRef &Exp) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_not(Context.Context, toZ3Expr(*Exp).AST)));
+ }
- Float = llvm::APFloat(Semantics, Int);
- return true;
+ SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvadd(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Construct an APSInt from a Z3Expr, given the AST representation
- static bool toAPSInt(const Z3Sort &Sort, const Z3_ast &AST, llvm::APSInt &Int,
- bool useSemantics = true) {
- switch (Sort.getSortKind()) {
- default:
- llvm_unreachable("Unsupported sort to integer!");
- case Z3_BV_SORT: {
- if (useSemantics && Int.getBitWidth() != Sort.getBitvectorSortSize()) {
- assert(false && "Bitvector types don't match!");
- return false;
- }
+ SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvsub(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- uint64_t Value[2];
- // Force cast because Z3 defines __uint64 to be a unsigned long long
- // type, which isn't compatible with a unsigned long type, even if they
- // are the same size.
- Z3_get_numeral_uint64(Z3Context::ZC, AST,
- reinterpret_cast<__uint64 *>(&Value[0]));
- if (Sort.getBitvectorSortSize() <= 64) {
- Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), true);
- } else if (Sort.getBitvectorSortSize() == 128) {
- Z3Expr ASTHigh = Z3Expr(Z3_mk_extract(Z3Context::ZC, 127, 64, AST));
- Z3_get_numeral_uint64(Z3Context::ZC, AST,
- reinterpret_cast<__uint64 *>(&Value[1]));
- Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), true);
- } else {
- assert(false && "Bitwidth not supported!");
- return false;
- }
- return true;
- }
- case Z3_BOOL_SORT:
- if (useSemantics && Int.getBitWidth() < 1) {
- assert(false && "Boolean type doesn't match!");
- return false;
- }
- Int = llvm::APSInt(
- llvm::APInt(Int.getBitWidth(),
- Z3_get_bool_value(Z3Context::ZC, AST) == Z3_L_TRUE ? 1
- : 0),
- true);
- return true;
- }
+ SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvmul(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddInteger(Z3_get_ast_hash(Z3Context::ZC, AST));
+ SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvsrem(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- bool operator<(const Z3Expr &Other) const {
- llvm::FoldingSetNodeID ID1, ID2;
- Profile(ID1);
- Other.Profile(ID2);
- return ID1 < ID2;
+ SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvurem(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Comparison of AST equality, not model equivalence.
- bool operator==(const Z3Expr &Other) const {
- assert(Z3_is_eq_sort(Z3Context::ZC, Z3_get_sort(Z3Context::ZC, AST),
- Z3_get_sort(Z3Context::ZC, Other.AST)) &&
- "AST's must have the same sort");
- return Z3_is_eq_ast(Z3Context::ZC, AST, Other.AST);
+ SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvsdiv(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Override implicit move constructor for correct reference counting.
- Z3Expr &operator=(const Z3Expr &Move) {
- Z3_inc_ref(Z3Context::ZC, Move.AST);
- Z3_dec_ref(Z3Context::ZC, AST);
- AST = Move.AST;
- return *this;
+ SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvudiv(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- void print(raw_ostream &OS) const {
- OS << Z3_ast_to_string(Z3Context::ZC, AST);
+ SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvshl(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
-}; // end class Z3Expr
+ SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvashr(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
-class Z3Model {
- Z3_model Model;
+ SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvlshr(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
-public:
- Z3Model(Z3_model ZM) : Model(ZM) { Z3_model_inc_ref(Z3Context::ZC, Model); }
+ SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvxor(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- /// Override implicit copy constructor for correct reference counting.
- Z3Model(const Z3Model &Copy) : Model(Copy.Model) {
- Z3_model_inc_ref(Z3Context::ZC, Model);
+ SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvor(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Provide move constructor
- Z3Model(Z3Model &&Move) : Model(nullptr) { *this = std::move(Move); }
+ SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvand(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- /// Provide move assignment constructor
- Z3Model &operator=(Z3Model &&Move) {
- if (this != &Move) {
- if (Model)
- Z3_model_dec_ref(Z3Context::ZC, Model);
- Model = Move.Model;
- Move.Model = nullptr;
- }
- return *this;
+ SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvult(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- ~Z3Model() {
- if (Model)
- Z3_model_dec_ref(Z3Context::ZC, Model);
+ SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvslt(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Given an expression, extract the value of this operand in the model.
- bool getInterpretation(const Z3Expr &Exp, llvm::APSInt &Int) const {
- Z3_func_decl Func =
- Z3_get_app_decl(Z3Context::ZC, Z3_to_app(Z3Context::ZC, Exp.AST));
- if (Z3_model_has_interp(Z3Context::ZC, Model, Func) != Z3_L_TRUE)
- return false;
+ SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvugt(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- Z3_ast Assign = Z3_model_get_const_interp(Z3Context::ZC, Model, Func);
- Z3Sort Sort = Z3Sort::getSort(Assign);
- return Z3Expr::toAPSInt(Sort, Assign, Int, true);
+ SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvsgt(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Given an expression, extract the value of this operand in the model.
- bool getInterpretation(const Z3Expr &Exp, llvm::APFloat &Float) const {
- Z3_func_decl Func =
- Z3_get_app_decl(Z3Context::ZC, Z3_to_app(Z3Context::ZC, Exp.AST));
- if (Z3_model_has_interp(Z3Context::ZC, Model, Func) != Z3_L_TRUE)
- return false;
+ SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvule(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- Z3_ast Assign = Z3_model_get_const_interp(Z3Context::ZC, Model, Func);
- Z3Sort Sort = Z3Sort::getSort(Assign);
- return Z3Expr::toAPFloat(Sort, Assign, Float, true);
+ SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvsle(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- void print(raw_ostream &OS) const {
- OS << Z3_model_to_string(Z3Context::ZC, Model);
+ SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvuge(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
-}; // end class Z3Model
+ SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_bvsge(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
-class Z3Solver {
- friend class Z3ConstraintManager;
+ SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
+ return newExprRef(Z3Expr(Context, Z3_mk_and(Context.Context, 2, Args)));
+ }
- Z3_solver Solver;
+ SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
+ return newExprRef(Z3Expr(Context, Z3_mk_or(Context.Context, 2, Args)));
+ }
- Z3Solver(Z3_solver ZS) : Solver(ZS) {
- Z3_solver_inc_ref(Z3Context::ZC, Solver);
+ SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_eq(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
-public:
- /// Override implicit copy constructor for correct reference counting.
- Z3Solver(const Z3Solver &Copy) : Solver(Copy.Solver) {
- Z3_solver_inc_ref(Z3Context::ZC, Solver);
+ SMTExprRef mkFPNeg(const SMTExprRef &Exp) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_neg(Context.Context, toZ3Expr(*Exp).AST)));
}
- /// Provide move constructor
- Z3Solver(Z3Solver &&Move) : Solver(nullptr) { *this = std::move(Move); }
+ SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) override {
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_is_infinite(Context.Context, toZ3Expr(*Exp).AST)));
+ }
- /// Provide move assignment constructor
- Z3Solver &operator=(Z3Solver &&Move) {
- if (this != &Move) {
- if (Solver)
- Z3_solver_dec_ref(Z3Context::ZC, Solver);
- Solver = Move.Solver;
- Move.Solver = nullptr;
- }
- return *this;
+ SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_is_nan(Context.Context, toZ3Expr(*Exp).AST)));
}
- ~Z3Solver() {
- if (Solver)
- Z3_solver_dec_ref(Z3Context::ZC, Solver);
+ SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) override {
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_is_normal(Context.Context, toZ3Expr(*Exp).AST)));
}
- /// Given a constraint, add it to the solver
- void addConstraint(const Z3Expr &Exp) {
- Z3_solver_assert(Z3Context::ZC, Solver, Exp.AST);
+ SMTExprRef mkFPIsZero(const SMTExprRef &Exp) override {
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_is_zero(Context.Context, toZ3Expr(*Exp).AST)));
}
- /// Given a program state, construct the logical conjunction and add it to
- /// the solver
- void addStateConstraints(ProgramStateRef State) {
- // TODO: Don't add all the constraints, only the relevant ones
- ConstraintZ3Ty CZ = State->get<ConstraintZ3>();
- ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end();
+ SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(
+ Z3Expr(Context,
+ Z3_mk_fpa_mul(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST)));
+ }
- // Construct the logical AND of all the constraints
- if (I != IE) {
- std::vector<Z3_ast> ASTs;
+ SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(
+ Z3Expr(Context,
+ Z3_mk_fpa_div(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST)));
+ }
- while (I != IE)
- ASTs.push_back(I++->second.AST);
+ SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_rem(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- Z3Expr Conj = Z3Expr::fromNBinOp(BO_LAnd, ASTs);
- addConstraint(Conj);
- }
+ SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(
+ Z3Expr(Context,
+ Z3_mk_fpa_add(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST)));
}
- /// Check if the constraints are satisfiable
- Z3_lbool check() { return Z3_solver_check(Z3Context::ZC, Solver); }
+ SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(
+ Z3Expr(Context,
+ Z3_mk_fpa_sub(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST)));
+ }
- /// Push the current solver state
- void push() { return Z3_solver_push(Z3Context::ZC, Solver); }
+ SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_lt(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
- /// Pop the previous solver state
- void pop(unsigned NumStates = 1) {
- assert(Z3_solver_get_num_scopes(Z3Context::ZC, Solver) >= NumStates);
- return Z3_solver_pop(Z3Context::ZC, Solver, NumStates);
+ SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_gt(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Get a model from the solver. Caller should check the model is
- /// satisfiable.
- Z3Model getModel() {
- return Z3Model(Z3_solver_get_model(Z3Context::ZC, Solver));
+ SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_leq(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
}
- /// Reset the solver and remove all constraints.
- void reset() { Z3_solver_reset(Z3Context::ZC, Solver); }
-}; // end class Z3Solver
+ SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_geq(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
-void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) {
- llvm::report_fatal_error("Z3 error: " +
- llvm::Twine(Z3_get_error_msg_ex(Context, Error)));
-}
+ SMTExprRef mkFPEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_fpa_eq(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
-class Z3ConstraintManager : public SimpleConstraintManager {
- Z3Context Context;
- mutable Z3Solver Solver;
+ SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
+ const SMTExprRef &F) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_ite(Context.Context, toZ3Expr(*Cond).AST,
+ toZ3Expr(*T).AST, toZ3Expr(*F).AST)));
+ }
-public:
- Z3ConstraintManager(SubEngine *SE, SValBuilder &SB)
- : SimpleConstraintManager(SE, SB),
- Solver(Z3_mk_simple_solver(Z3Context::ZC)) {
- Z3_set_error_handler(Z3Context::ZC, Z3ErrorHandler);
+ SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) override {
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_sign_ext(Context.Context, i, toZ3Expr(*Exp).AST)));
}
- //===------------------------------------------------------------------===//
- // Implementation for interface from ConstraintManager.
- //===------------------------------------------------------------------===//
+ SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) override {
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_zero_ext(Context.Context, i, toZ3Expr(*Exp).AST)));
+ }
- bool canReasonAbout(SVal X) const override;
+ SMTExprRef mkBVExtract(unsigned High, unsigned Low,
+ const SMTExprRef &Exp) override {
+ return newExprRef(Z3Expr(Context, Z3_mk_extract(Context.Context, High, Low,
+ toZ3Expr(*Exp).AST)));
+ }
- ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
-
- const llvm::APSInt *getSymVal(ProgramStateRef State,
- SymbolRef Sym) const override;
-
- ProgramStateRef removeDeadBindings(ProgramStateRef St,
- SymbolReaper &SymReaper) override;
-
- void print(ProgramStateRef St, raw_ostream &Out, const char *nl,
- const char *sep) override;
-
- //===------------------------------------------------------------------===//
- // Implementation for interface from SimpleConstraintManager.
- //===------------------------------------------------------------------===//
-
- ProgramStateRef assumeSym(ProgramStateRef state, SymbolRef Sym,
- bool Assumption) override;
-
- ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool InRange) override;
-
- ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym,
- bool Assumption) override;
-
-private:
- //===------------------------------------------------------------------===//
- // Internal implementation.
- //===------------------------------------------------------------------===//
-
- // Check whether a new model is satisfiable, and update the program state.
- ProgramStateRef assumeZ3Expr(ProgramStateRef State, SymbolRef Sym,
- const Z3Expr &Exp);
-
- // Generate and check a Z3 model, using the given constraint.
- Z3_lbool checkZ3Model(ProgramStateRef State, const Z3Expr &Exp) const;
-
- // Generate a Z3Expr that represents the given symbolic expression.
- // Sets the hasComparison parameter if the expression has a comparison
- // operator.
- // Sets the RetTy parameter to the final return type after promotions and
- // casts.
- Z3Expr getZ3Expr(SymbolRef Sym, QualType *RetTy = nullptr,
- bool *hasComparison = nullptr) const;
-
- // Generate a Z3Expr that takes the logical not of an expression.
- Z3Expr getZ3NotExpr(const Z3Expr &Exp) const;
-
- // Generate a Z3Expr that compares the expression to zero.
- Z3Expr getZ3ZeroExpr(const Z3Expr &Exp, QualType RetTy,
- bool Assumption) const;
-
- // Recursive implementation to unpack and generate symbolic expression.
- // Sets the hasComparison and RetTy parameters. See getZ3Expr().
- Z3Expr getZ3SymExpr(SymbolRef Sym, QualType *RetTy,
- bool *hasComparison) const;
-
- // Wrapper to generate Z3Expr from SymbolData.
- Z3Expr getZ3DataExpr(const SymbolID ID, QualType Ty) const;
-
- // Wrapper to generate Z3Expr from SymbolCast.
- Z3Expr getZ3CastExpr(const Z3Expr &Exp, QualType FromTy, QualType Ty) const;
-
- // Wrapper to generate Z3Expr from BinarySymExpr.
- // Sets the hasComparison and RetTy parameters. See getZ3Expr().
- Z3Expr getZ3SymBinExpr(const BinarySymExpr *BSE, bool *hasComparison,
- QualType *RetTy) const;
-
- // Wrapper to generate Z3Expr from unpacked binary symbolic expression.
- // Sets the RetTy parameter. See getZ3Expr().
- Z3Expr getZ3BinExpr(const Z3Expr &LHS, QualType LTy,
- BinaryOperator::Opcode Op, const Z3Expr &RHS,
- QualType RTy, QualType *RetTy) const;
-
- //===------------------------------------------------------------------===//
- // Helper functions.
- //===------------------------------------------------------------------===//
-
- // Recover the QualType of an APSInt.
- // TODO: Refactor to put elsewhere
- QualType getAPSIntType(const llvm::APSInt &Int) const;
-
- // Perform implicit type conversion on binary symbolic expressions.
- // May modify all input parameters.
- // TODO: Refactor to use built-in conversion functions
- void doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, QualType &LTy,
- QualType &RTy) const;
-
- // Perform implicit integer type conversion.
- // May modify all input parameters.
- // TODO: Refactor to use Sema::handleIntegerConversion()
- template <typename T,
- T(doCast)(const T &, QualType, uint64_t, QualType, uint64_t)>
- void doIntTypeConversion(T &LHS, QualType &LTy, T &RHS, QualType &RTy) const;
-
- // Perform implicit floating-point type conversion.
- // May modify all input parameters.
- // TODO: Refactor to use Sema::handleFloatConversion()
- template <typename T,
- T(doCast)(const T &, QualType, uint64_t, QualType, uint64_t)>
- void doFloatTypeConversion(T &LHS, QualType &LTy, T &RHS,
- QualType &RTy) const;
-
- // Callback function for doCast parameter on APSInt type.
- static llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy,
- uint64_t ToWidth, QualType FromTy,
- uint64_t FromWidth);
-}; // end class Z3ConstraintManager
+ SMTExprRef mkBVConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_concat(Context.Context, toZ3Expr(*LHS).AST,
+ toZ3Expr(*RHS).AST)));
+ }
-Z3_context Z3Context::ZC;
+ SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(Z3Expr(
+ Context,
+ Z3_mk_fpa_to_fp_float(Context.Context, toZ3Expr(*RoundingMode).AST,
+ toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
+ }
-} // end anonymous namespace
+ SMTExprRef mkFPtoSBV(const SMTExprRef &From, const SMTSortRef &To) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(Z3Expr(
+ Context,
+ Z3_mk_fpa_to_fp_signed(Context.Context, toZ3Expr(*RoundingMode).AST,
+ toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
+ }
-ProgramStateRef Z3ConstraintManager::assumeSym(ProgramStateRef State,
- SymbolRef Sym, bool Assumption) {
- QualType RetTy;
- bool hasComparison;
+ SMTExprRef mkFPtoUBV(const SMTExprRef &From, const SMTSortRef &To) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(Z3Expr(
+ Context,
+ Z3_mk_fpa_to_fp_unsigned(Context.Context, toZ3Expr(*RoundingMode).AST,
+ toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
+ }
- Z3Expr Exp = getZ3Expr(Sym, &RetTy, &hasComparison);
- // Create zero comparison for implicit boolean cast, with reversed assumption
- if (!hasComparison && !RetTy->isBooleanType())
- return assumeZ3Expr(State, Sym, getZ3ZeroExpr(Exp, RetTy, !Assumption));
+ SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_to_sbv(Context.Context, toZ3Expr(*RoundingMode).AST,
+ toZ3Expr(*From).AST, ToWidth)));
+ }
- return assumeZ3Expr(State, Sym, Assumption ? Exp : getZ3NotExpr(Exp));
-}
+ SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) override {
+ SMTExprRef RoundingMode = getFloatRoundingMode();
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_to_ubv(Context.Context, toZ3Expr(*RoundingMode).AST,
+ toZ3Expr(*From).AST, ToWidth)));
+ }
-ProgramStateRef Z3ConstraintManager::assumeSymInclusiveRange(
- ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
- const llvm::APSInt &To, bool InRange) {
- QualType RetTy;
- // The expression may be casted, so we cannot call getZ3DataExpr() directly
- Z3Expr Exp = getZ3Expr(Sym, &RetTy);
-
- assert((getAPSIntType(From) == getAPSIntType(To)) &&
- "Range values have different types!");
- QualType RTy = getAPSIntType(From);
- bool isSignedTy = RetTy->isSignedIntegerOrEnumerationType();
- Z3Expr FromExp = Z3Expr::fromAPSInt(From);
- Z3Expr ToExp = Z3Expr::fromAPSInt(To);
-
- // Construct single (in)equality
- if (From == To)
- return assumeZ3Expr(State, Sym,
- getZ3BinExpr(Exp, RetTy, InRange ? BO_EQ : BO_NE,
- FromExp, RTy, nullptr));
-
- // Construct two (in)equalities, and a logical and/or
- Z3Expr LHS =
- getZ3BinExpr(Exp, RetTy, InRange ? BO_GE : BO_LT, FromExp, RTy, nullptr);
- Z3Expr RHS =
- getZ3BinExpr(Exp, RetTy, InRange ? BO_LE : BO_GT, ToExp, RTy, nullptr);
- return assumeZ3Expr(
- State, Sym,
- Z3Expr::fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, isSignedTy));
-}
+ SMTExprRef mkBoolean(const bool b) override {
+ return newExprRef(Z3Expr(Context, b ? Z3_mk_true(Context.Context)
+ : Z3_mk_false(Context.Context)));
+ }
-ProgramStateRef Z3ConstraintManager::assumeSymUnsupported(ProgramStateRef State,
- SymbolRef Sym,
- bool Assumption) {
- // Skip anything that is unsupported
- return State;
-}
+ SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) override {
+ const SMTSortRef Sort = getBitvectorSort(BitWidth);
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_numeral(Context.Context, Int.toString(10).c_str(),
+ toZ3Sort(*Sort).Sort)));
+ }
-bool Z3ConstraintManager::canReasonAbout(SVal X) const {
- const TargetInfo &TI = getBasicVals().getContext().getTargetInfo();
+ SMTExprRef mkFloat(const llvm::APFloat Float) override {
+ SMTSortRef Sort =
+ getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics()));
- Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
- if (!SymVal)
- return true;
+ llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false);
+ SMTExprRef Z3Int = mkBitvector(Int, Int.getBitWidth());
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST,
+ toZ3Sort(*Sort).Sort)));
+ }
- const SymExpr *Sym = SymVal->getSymbol();
- do {
- QualType Ty = Sym->getType();
+ SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) override {
+ return newExprRef(
+ Z3Expr(Context, Z3_mk_const(Context.Context,
+ Z3_mk_string_symbol(Context.Context, Name),
+ toZ3Sort(*Sort).Sort)));
+ }
- // Complex types are not modeled
- if (Ty->isComplexType() || Ty->isComplexIntegerType())
- return false;
+ llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
+ bool isUnsigned) override {
+ return llvm::APSInt(llvm::APInt(
+ BitWidth, Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST),
+ 10));
+ }
- // Non-IEEE 754 floating-point types are not modeled
- if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
- (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
- &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
- return false;
+ bool getBoolean(const SMTExprRef &Exp) override {
+ return Z3_get_bool_value(Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE;
+ }
- if (isa<SymbolData>(Sym)) {
- break;
- } else if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
- Sym = SC->getOperand();
- } else if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
- if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
- Sym = SIE->getLHS();
- } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
- Sym = ISE->getRHS();
- } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
- return canReasonAbout(nonloc::SymbolVal(SSM->getLHS())) &&
- canReasonAbout(nonloc::SymbolVal(SSM->getRHS()));
- } else {
- llvm_unreachable("Unsupported binary expression to reason about!");
- }
- } else {
- llvm_unreachable("Unsupported expression to reason about!");
- }
- } while (Sym);
+ SMTExprRef getFloatRoundingMode() override {
+ // TODO: Don't assume nearest ties to even rounding mode
+ return newExprRef(Z3Expr(Context, Z3_mk_fpa_rne(Context.Context)));
+ }
- return true;
-}
+ SMTExprRef fromData(const SymbolID ID, const QualType &Ty,
+ uint64_t BitWidth) override {
+ llvm::Twine Name = "$" + llvm::Twine(ID);
+ return mkSymbol(Name.str().c_str(), mkSort(Ty, BitWidth));
+ }
+
+ SMTExprRef fromBoolean(const bool Bool) override {
+ Z3_ast AST =
+ Bool ? Z3_mk_true(Context.Context) : Z3_mk_false(Context.Context);
+ return newExprRef(Z3Expr(Context, AST));
+ }
+
+ SMTExprRef fromAPFloat(const llvm::APFloat &Float) override {
+ SMTSortRef Sort =
+ getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics()));
-ConditionTruthVal Z3ConstraintManager::checkNull(ProgramStateRef State,
- SymbolRef Sym) {
- QualType RetTy;
- // The expression may be casted, so we cannot call getZ3DataExpr() directly
- Z3Expr VarExp = getZ3Expr(Sym, &RetTy);
- Z3Expr Exp = getZ3ZeroExpr(VarExp, RetTy, true);
- // Negate the constraint
- Z3Expr NotExp = getZ3ZeroExpr(VarExp, RetTy, false);
+ llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false);
+ SMTExprRef Z3Int = fromAPSInt(Int);
+ return newExprRef(Z3Expr(
+ Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST,
+ toZ3Sort(*Sort).Sort)));
+ }
- Solver.reset();
- Solver.addStateConstraints(State);
+ SMTExprRef fromAPSInt(const llvm::APSInt &Int) override {
+ SMTSortRef Sort = getBitvectorSort(Int.getBitWidth());
+ Z3_ast AST = Z3_mk_numeral(Context.Context, Int.toString(10).c_str(),
+ toZ3Sort(*Sort).Sort);
+ return newExprRef(Z3Expr(Context, AST));
+ }
- Solver.push();
- Solver.addConstraint(Exp);
- Z3_lbool isSat = Solver.check();
+ SMTExprRef fromInt(const char *Int, uint64_t BitWidth) override {
+ SMTSortRef Sort = getBitvectorSort(BitWidth);
+ Z3_ast AST = Z3_mk_numeral(Context.Context, Int, toZ3Sort(*Sort).Sort);
+ return newExprRef(Z3Expr(Context, AST));
+ }
- Solver.pop();
- Solver.addConstraint(NotExp);
- Z3_lbool isNotSat = Solver.check();
+ bool toAPFloat(const SMTSortRef &Sort, const SMTExprRef &AST,
+ llvm::APFloat &Float, bool useSemantics) {
+ assert(Sort->isFloatSort() && "Unsupported sort to floating-point!");
- // Zero is the only possible solution
- if (isSat == Z3_L_TRUE && isNotSat == Z3_L_FALSE)
+ llvm::APSInt Int(Sort->getFloatSortSize(), true);
+ const llvm::fltSemantics &Semantics =
+ getFloatSemantics(Sort->getFloatSortSize());
+ SMTSortRef BVSort = getBitvectorSort(Sort->getFloatSortSize());
+ if (!toAPSInt(BVSort, AST, Int, true)) {
+ return false;
+ }
+
+ if (useSemantics && !areEquivalent(Float.getSemantics(), Semantics)) {
+ assert(false && "Floating-point types don't match!");
+ return false;
+ }
+
+ Float = llvm::APFloat(Semantics, Int);
return true;
- // Zero is not a solution
- else if (isSat == Z3_L_FALSE && isNotSat == Z3_L_TRUE)
- return false;
+ }
- // Zero may be a solution
- return ConditionTruthVal();
-}
+ bool toAPSInt(const SMTSortRef &Sort, const SMTExprRef &AST,
+ llvm::APSInt &Int, bool useSemantics) {
+ if (Sort->isBitvectorSort()) {
+ if (useSemantics && Int.getBitWidth() != Sort->getBitvectorSortSize()) {
+ assert(false && "Bitvector types don't match!");
+ return false;
+ }
-const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State,
- SymbolRef Sym) const {
- BasicValueFactory &BV = getBasicVals();
- ASTContext &Ctx = BV.getContext();
+ // FIXME: This function is also used to retrieve floating-point values,
+ // which can be 16, 32, 64 or 128 bits long. Bitvectors can be anything
+ // between 1 and 64 bits long, which is the reason we have this weird
+ // guard. In the future, we need proper calls in the backend to retrieve
+ // floating-points and its special values (NaN, +/-infinity, +/-zero),
+ // then we can drop this weird condition.
+ if (Sort->getBitvectorSortSize() <= 64 ||
+ Sort->getBitvectorSortSize() == 128) {
+ Int = getBitvector(AST, Int.getBitWidth(), Int.isUnsigned());
+ return true;
+ }
- if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
- QualType Ty = Sym->getType();
- assert(!Ty->isRealFloatingType());
- llvm::APSInt Value(Ctx.getTypeSize(Ty),
- !Ty->isSignedIntegerOrEnumerationType());
-
- Z3Expr Exp = getZ3DataExpr(SD->getSymbolID(), Ty);
-
- Solver.reset();
- Solver.addStateConstraints(State);
-
- // Constraints are unsatisfiable
- if (Solver.check() != Z3_L_TRUE)
- return nullptr;
-
- Z3Model Model = Solver.getModel();
- // Model does not assign interpretation
- if (!Model.getInterpretation(Exp, Value))
- return nullptr;
-
- // A value has been obtained, check if it is the only value
- Z3Expr NotExp = Z3Expr::fromBinOp(
- Exp, BO_NE,
- Ty->isBooleanType() ? Z3Expr::fromBoolean(Value.getBoolValue())
- : Z3Expr::fromAPSInt(Value),
- false);
-
- Solver.addConstraint(NotExp);
- if (Solver.check() == Z3_L_TRUE)
- return nullptr;
-
- // This is the only solution, store it
- return &BV.getValue(Value);
- } else if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
- SymbolRef CastSym = SC->getOperand();
- QualType CastTy = SC->getType();
- // Skip the void type
- if (CastTy->isVoidType())
- return nullptr;
-
- const llvm::APSInt *Value;
- if (!(Value = getSymVal(State, CastSym)))
- return nullptr;
- return &BV.Convert(SC->getType(), *Value);
- } else if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
- const llvm::APSInt *LHS, *RHS;
- if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
- LHS = getSymVal(State, SIE->getLHS());
- RHS = &SIE->getRHS();
- } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
- LHS = &ISE->getLHS();
- RHS = getSymVal(State, ISE->getRHS());
- } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
- // Early termination to avoid expensive call
- LHS = getSymVal(State, SSM->getLHS());
- RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr;
- } else {
- llvm_unreachable("Unsupported binary expression to get symbol value!");
+ assert(false && "Bitwidth not supported!");
+ return false;
}
- if (!LHS || !RHS)
- return nullptr;
+ if (Sort->isBooleanSort()) {
+ if (useSemantics && Int.getBitWidth() < 1) {
+ assert(false && "Boolean type doesn't match!");
+ return false;
+ }
- llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
- QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
- doIntTypeConversion<llvm::APSInt, Z3ConstraintManager::castAPSInt>(
- ConvertedLHS, LTy, ConvertedRHS, RTy);
- return BV.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
- }
+ Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), getBoolean(AST)),
+ Int.isUnsigned());
+ return true;
+ }
- llvm_unreachable("Unsupported expression to get symbol value!");
-}
+ llvm_unreachable("Unsupported sort to integer!");
+ }
-ProgramStateRef
-Z3ConstraintManager::removeDeadBindings(ProgramStateRef State,
- SymbolReaper &SymReaper) {
- ConstraintZ3Ty CZ = State->get<ConstraintZ3>();
- ConstraintZ3Ty::Factory &CZFactory = State->get_context<ConstraintZ3>();
+ bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) override {
+ Z3Model Model = getModel();
+ Z3_func_decl Func = Z3_get_app_decl(
+ Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
+ if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
+ return false;
- for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) {
- if (SymReaper.maybeDead(I->first))
- CZ = CZFactory.remove(CZ, *I);
+ SMTExprRef Assign = newExprRef(
+ Z3Expr(Context,
+ Z3_model_get_const_interp(Context.Context, Model.Model, Func)));
+ SMTSortRef Sort = getSort(Assign);
+ return toAPSInt(Sort, Assign, Int, true);
}
- return State->set<ConstraintZ3>(CZ);
-}
+ bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) override {
+ Z3Model Model = getModel();
+ Z3_func_decl Func = Z3_get_app_decl(
+ Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
+ if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
+ return false;
-//===------------------------------------------------------------------===//
-// Internal implementation.
-//===------------------------------------------------------------------===//
+ SMTExprRef Assign = newExprRef(
+ Z3Expr(Context,
+ Z3_model_get_const_interp(Context.Context, Model.Model, Func)));
+ SMTSortRef Sort = getSort(Assign);
+ return toAPFloat(Sort, Assign, Float, true);
+ }
-ProgramStateRef Z3ConstraintManager::assumeZ3Expr(ProgramStateRef State,
- SymbolRef Sym,
- const Z3Expr &Exp) {
- // Check the model, avoid simplifying AST to save time
- if (checkZ3Model(State, Exp) == Z3_L_TRUE)
- return State->add<ConstraintZ3>(std::make_pair(Sym, Exp));
+ ConditionTruthVal check() const override {
+ Z3_lbool res = Z3_solver_check(Context.Context, Solver);
+ if (res == Z3_L_TRUE)
+ return true;
- return nullptr;
-}
+ if (res == Z3_L_FALSE)
+ return false;
-Z3_lbool Z3ConstraintManager::checkZ3Model(ProgramStateRef State,
- const Z3Expr &Exp) const {
- Solver.reset();
- Solver.addConstraint(Exp);
- Solver.addStateConstraints(State);
- return Solver.check();
-}
+ return ConditionTruthVal();
+ }
-Z3Expr Z3ConstraintManager::getZ3Expr(SymbolRef Sym, QualType *RetTy,
- bool *hasComparison) const {
- if (hasComparison) {
- *hasComparison = false;
+ void push() override { return Z3_solver_push(Context.Context, Solver); }
+
+ void pop(unsigned NumStates = 1) override {
+ assert(Z3_solver_get_num_scopes(Context.Context, Solver) >= NumStates);
+ return Z3_solver_pop(Context.Context, Solver, NumStates);
}
- return getZ3SymExpr(Sym, RetTy, hasComparison);
-}
+ /// Get a model from the solver. Caller should check the model is
+ /// satisfiable.
+ Z3Model getModel() {
+ return Z3Model(Context, Z3_solver_get_model(Context.Context, Solver));
+ }
-Z3Expr Z3ConstraintManager::getZ3NotExpr(const Z3Expr &Exp) const {
- return Z3Expr::fromUnOp(UO_LNot, Exp);
-}
+ /// Reset the solver and remove all constraints.
+ void reset() const override { Z3_solver_reset(Context.Context, Solver); }
-Z3Expr Z3ConstraintManager::getZ3ZeroExpr(const Z3Expr &Exp, QualType Ty,
- bool Assumption) const {
- ASTContext &Ctx = getBasicVals().getContext();
- if (Ty->isRealFloatingType()) {
- llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty));
- return Z3Expr::fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE,
- Z3Expr::fromAPFloat(Zero));
- } else if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() ||
- Ty->isBlockPointerType() || Ty->isReferenceType()) {
- bool isSigned = Ty->isSignedIntegerOrEnumerationType();
- // Skip explicit comparison for boolean types
- if (Ty->isBooleanType())
- return Assumption ? getZ3NotExpr(Exp) : Exp;
- return Z3Expr::fromBinOp(Exp, Assumption ? BO_EQ : BO_NE,
- Z3Expr::fromInt("0", Ctx.getTypeSize(Ty)),
- isSigned);
- }
-
- llvm_unreachable("Unsupported type for zero value!");
-}
+ void print(raw_ostream &OS) const override {
+ OS << Z3_solver_to_string(Context.Context, Solver);
+ }
+}; // end class Z3Solver
-Z3Expr Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy,
- bool *hasComparison) const {
- if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
- if (RetTy)
- *RetTy = Sym->getType();
-
- return getZ3DataExpr(SD->getSymbolID(), Sym->getType());
- } else if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
- if (RetTy)
- *RetTy = Sym->getType();
-
- QualType FromTy;
- Z3Expr Exp = getZ3SymExpr(SC->getOperand(), &FromTy, hasComparison);
- // Casting an expression with a comparison invalidates it. Note that this
- // must occur after the recursive call above.
- // e.g. (signed char) (x > 0)
- if (hasComparison)
- *hasComparison = false;
- return getZ3CastExpr(Exp, FromTy, Sym->getType());
- } else if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
- Z3Expr Exp = getZ3SymBinExpr(BSE, hasComparison, RetTy);
- // Set the hasComparison parameter, in post-order traversal order.
- if (hasComparison)
- *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode());
- return Exp;
- }
-
- llvm_unreachable("Unsupported SymbolRef type!");
-}
+class Z3ConstraintManager : public SMTConstraintManager {
+ SMTSolverRef Solver = CreateZ3Solver();
-Z3Expr Z3ConstraintManager::getZ3DataExpr(const SymbolID ID,
- QualType Ty) const {
- ASTContext &Ctx = getBasicVals().getContext();
- return Z3Expr::fromData(ID, Ty->isBooleanType(), Ty->isRealFloatingType(),
- Ctx.getTypeSize(Ty));
-}
+public:
+ Z3ConstraintManager(SubEngine *SE, SValBuilder &SB)
+ : SMTConstraintManager(SE, SB, Solver) {}
-Z3Expr Z3ConstraintManager::getZ3CastExpr(const Z3Expr &Exp, QualType FromTy,
- QualType ToTy) const {
- ASTContext &Ctx = getBasicVals().getContext();
- return Z3Expr::fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy,
- Ctx.getTypeSize(FromTy));
-}
+ void addStateConstraints(ProgramStateRef State) const override {
+ // TODO: Don't add all the constraints, only the relevant ones
+ ConstraintZ3Ty CZ = State->get<ConstraintZ3>();
+ ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end();
-Z3Expr Z3ConstraintManager::getZ3SymBinExpr(const BinarySymExpr *BSE,
- bool *hasComparison,
- QualType *RetTy) const {
- QualType LTy, RTy;
- BinaryOperator::Opcode Op = BSE->getOpcode();
-
- if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
- RTy = getAPSIntType(SIE->getRHS());
- Z3Expr LHS = getZ3SymExpr(SIE->getLHS(), &LTy, hasComparison);
- Z3Expr RHS = Z3Expr::fromAPSInt(SIE->getRHS());
- return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy);
- } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
- LTy = getAPSIntType(ISE->getLHS());
- Z3Expr LHS = Z3Expr::fromAPSInt(ISE->getLHS());
- Z3Expr RHS = getZ3SymExpr(ISE->getRHS(), &RTy, hasComparison);
- return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy);
- } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
- Z3Expr LHS = getZ3SymExpr(SSM->getLHS(), &LTy, hasComparison);
- Z3Expr RHS = getZ3SymExpr(SSM->getRHS(), &RTy, hasComparison);
- return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy);
- } else {
- llvm_unreachable("Unsupported BinarySymExpr type!");
- }
-}
+ // Construct the logical AND of all the constraints
+ if (I != IE) {
+ std::vector<SMTExprRef> ASTs;
-Z3Expr Z3ConstraintManager::getZ3BinExpr(const Z3Expr &LHS, QualType LTy,
- BinaryOperator::Opcode Op,
- const Z3Expr &RHS, QualType RTy,
- QualType *RetTy) const {
- Z3Expr NewLHS = LHS;
- Z3Expr NewRHS = RHS;
- doTypeConversion(NewLHS, NewRHS, LTy, RTy);
- // Update the return type parameter if the output type has changed.
- if (RetTy) {
- // A boolean result can be represented as an integer type in C/C++, but at
- // this point we only care about the Z3 type. Set it as a boolean type to
- // avoid subsequent Z3 errors.
- if (BinaryOperator::isComparisonOp(Op) || BinaryOperator::isLogicalOp(Op)) {
- ASTContext &Ctx = getBasicVals().getContext();
- *RetTy = Ctx.BoolTy;
- } else {
- *RetTy = LTy;
- }
+ SMTExprRef Constraint = Solver->newExprRef(I++->second);
+ while (I != IE) {
+ Constraint = Solver->mkAnd(Constraint, Solver->newExprRef(I++->second));
+ }
- // If the two operands are pointers and the operation is a subtraction, the
- // result is of type ptrdiff_t, which is signed
- if (LTy->isAnyPointerType() && LTy == RTy && Op == BO_Sub) {
- ASTContext &Ctx = getBasicVals().getContext();
- *RetTy = Ctx.getIntTypeForBitwidth(Ctx.getTypeSize(LTy), true);
+ Solver->addConstraint(Constraint);
}
}
- return LTy->isRealFloatingType()
- ? Z3Expr::fromFloatBinOp(NewLHS, Op, NewRHS)
- : Z3Expr::fromBinOp(NewLHS, Op, NewRHS,
- LTy->isSignedIntegerOrEnumerationType());
-}
+ bool canReasonAbout(SVal X) const override {
+ const TargetInfo &TI = getBasicVals().getContext().getTargetInfo();
-//===------------------------------------------------------------------===//
-// Helper functions.
-//===------------------------------------------------------------------===//
+ Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
+ if (!SymVal)
+ return true;
-QualType Z3ConstraintManager::getAPSIntType(const llvm::APSInt &Int) const {
- ASTContext &Ctx = getBasicVals().getContext();
- return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned());
-}
+ const SymExpr *Sym = SymVal->getSymbol();
+ QualType Ty = Sym->getType();
-void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS,
- QualType &LTy, QualType &RTy) const {
- ASTContext &Ctx = getBasicVals().getContext();
-
- // Perform type conversion
- if (LTy->isIntegralOrEnumerationType() &&
- RTy->isIntegralOrEnumerationType()) {
- if (LTy->isArithmeticType() && RTy->isArithmeticType())
- return doIntTypeConversion<Z3Expr, Z3Expr::fromCast>(LHS, LTy, RHS, RTy);
- } else if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) {
- return doFloatTypeConversion<Z3Expr, Z3Expr::fromCast>(LHS, LTy, RHS, RTy);
- } else if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) ||
- (LTy->isBlockPointerType() || RTy->isBlockPointerType()) ||
- (LTy->isReferenceType() || RTy->isReferenceType())) {
- // TODO: Refactor to Sema::FindCompositePointerType(), and
- // Sema::CheckCompareOperands().
-
- uint64_t LBitWidth = Ctx.getTypeSize(LTy);
- uint64_t RBitWidth = Ctx.getTypeSize(RTy);
-
- // Cast the non-pointer type to the pointer type.
- // TODO: Be more strict about this.
- if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) ||
- (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) ||
- (LTy->isReferenceType() ^ RTy->isReferenceType())) {
- if (LTy->isNullPtrType() || LTy->isBlockPointerType() ||
- LTy->isReferenceType()) {
- LHS = Z3Expr::fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- } else {
- RHS = Z3Expr::fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- }
- }
+ // Complex types are not modeled
+ if (Ty->isComplexType() || Ty->isComplexIntegerType())
+ return false;
- // Cast the void pointer type to the non-void pointer type.
- // For void types, this assumes that the casted value is equal to the value
- // of the original pointer, and does not account for alignment requirements.
- if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) {
- assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) &&
- "Pointer types have different bitwidths!");
- if (RTy->isVoidPointerType())
- RTy = LTy;
- else
- LTy = RTy;
- }
+ // Non-IEEE 754 floating-point types are not modeled
+ if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+ (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
+ &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
+ return false;
- if (LTy == RTy)
- return;
- }
+ if (isa<SymbolData>(Sym))
+ return true;
- // Fallback: for the solver, assume that these types don't really matter
- if ((LTy.getCanonicalType() == RTy.getCanonicalType()) ||
- (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) {
- LTy = RTy;
- return;
- }
+ SValBuilder &SVB = getSValBuilder();
- // TODO: Refine behavior for invalid type casts
-}
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
+ return canReasonAbout(SVB.makeSymbolVal(SC->getOperand()));
-template <typename T,
- T(doCast)(const T &, QualType, uint64_t, QualType, uint64_t)>
-void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType &LTy, T &RHS,
- QualType &RTy) const {
- ASTContext &Ctx = getBasicVals().getContext();
-
- uint64_t LBitWidth = Ctx.getTypeSize(LTy);
- uint64_t RBitWidth = Ctx.getTypeSize(RTy);
-
- // Always perform integer promotion before checking type equality.
- // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion
- if (LTy->isPromotableIntegerType()) {
- QualType NewTy = Ctx.getPromotedIntegerType(LTy);
- uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
- LHS = (*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth);
- LTy = NewTy;
- LBitWidth = NewBitWidth;
- }
- if (RTy->isPromotableIntegerType()) {
- QualType NewTy = Ctx.getPromotedIntegerType(RTy);
- uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
- RHS = (*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth);
- RTy = NewTy;
- RBitWidth = NewBitWidth;
- }
-
- if (LTy == RTy)
- return;
-
- // Perform integer type conversion
- // Note: Safe to skip updating bitwidth because this must terminate
- bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType();
- bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType();
-
- int order = Ctx.getIntegerTypeOrder(LTy, RTy);
- if (isLSignedTy == isRSignedTy) {
- // Same signedness; use the higher-ranked type
- if (order == 1) {
- RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else {
- LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- }
- } else if (order != (isLSignedTy ? 1 : -1)) {
- // The unsigned type has greater than or equal rank to the
- // signed type, so use the unsigned type
- if (isRSignedTy) {
- RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else {
- LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- }
- } else if (LBitWidth != RBitWidth) {
- // The two types are different widths; if we are here, that
- // means the signed type is larger than the unsigned type, so
- // use the signed type.
- if (isLSignedTy) {
- RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else {
- LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS()));
+
+ if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS()));
+
+ if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) &&
+ canReasonAbout(SVB.makeSymbolVal(SSE->getRHS()));
}
- } else {
- // The signed type is higher-ranked than the unsigned type,
- // but isn't actually any bigger (like unsigned int and long
- // on most 32-bit systems). Use the unsigned type corresponding
- // to the signed type.
- QualType NewTy = Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy);
- RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = NewTy;
- LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = NewTy;
+
+ llvm_unreachable("Unsupported expression to reason about!");
}
-}
-template <typename T,
- T(doCast)(const T &, QualType, uint64_t, QualType, uint64_t)>
-void Z3ConstraintManager::doFloatTypeConversion(T &LHS, QualType &LTy, T &RHS,
- QualType &RTy) const {
- ASTContext &Ctx = getBasicVals().getContext();
-
- uint64_t LBitWidth = Ctx.getTypeSize(LTy);
- uint64_t RBitWidth = Ctx.getTypeSize(RTy);
-
- // Perform float-point type promotion
- if (!LTy->isRealFloatingType()) {
- LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- LBitWidth = RBitWidth;
- }
- if (!RTy->isRealFloatingType()) {
- RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- RBitWidth = LBitWidth;
- }
-
- if (LTy == RTy)
- return;
-
- // If we have two real floating types, convert the smaller operand to the
- // bigger result
- // Note: Safe to skip updating bitwidth because this must terminate
- int order = Ctx.getFloatingTypeOrder(LTy, RTy);
- if (order > 0) {
- RHS = Z3Expr::fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else if (order == 0) {
- LHS = Z3Expr::fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- } else {
- llvm_unreachable("Unsupported floating-point type cast!");
+ ProgramStateRef removeDeadBindings(ProgramStateRef State,
+ SymbolReaper &SymReaper) override {
+ ConstraintZ3Ty CZ = State->get<ConstraintZ3>();
+ ConstraintZ3Ty::Factory &CZFactory = State->get_context<ConstraintZ3>();
+
+ for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) {
+ if (SymReaper.maybeDead(I->first))
+ CZ = CZFactory.remove(CZ, *I);
+ }
+
+ return State->set<ConstraintZ3>(CZ);
}
-}
-llvm::APSInt Z3ConstraintManager::castAPSInt(const llvm::APSInt &V,
- QualType ToTy, uint64_t ToWidth,
- QualType FromTy,
- uint64_t FromWidth) {
- APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType());
- return TargetType.convert(V);
-}
+ ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym,
+ const SMTExprRef &Exp) override {
+ // Check the model, avoid simplifying AST to save time
+ if (checkModel(State, Exp).isConstrainedTrue())
+ return State->add<ConstraintZ3>(std::make_pair(Sym, toZ3Expr(*Exp)));
+
+ return nullptr;
+ }
-//==------------------------------------------------------------------------==/
-// Pretty-printing.
-//==------------------------------------------------------------------------==/
+ //==------------------------------------------------------------------------==/
+ // Pretty-printing.
+ //==------------------------------------------------------------------------==/
-void Z3ConstraintManager::print(ProgramStateRef St, raw_ostream &OS,
- const char *nl, const char *sep) {
+ void print(ProgramStateRef St, raw_ostream &OS, const char *nl,
+ const char *sep) override {
- ConstraintZ3Ty CZ = St->get<ConstraintZ3>();
+ ConstraintZ3Ty CZ = St->get<ConstraintZ3>();
- OS << nl << sep << "Constraints:";
- for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) {
- OS << nl << ' ' << I->first << " : ";
- I->second.print(OS);
+ OS << nl << sep << "Constraints:";
+ for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) {
+ OS << nl << ' ' << I->first << " : ";
+ I->second.print(OS);
+ }
+ OS << nl;
}
- OS << nl;
-}
+}; // end class Z3ConstraintManager
+
+} // end anonymous namespace
#endif
+std::unique_ptr<SMTSolver> clang::ento::CreateZ3Solver() {
+#if CLANG_ANALYZER_WITH_Z3
+ return llvm::make_unique<Z3Solver>();
+#else
+ llvm::report_fatal_error("Clang was not compiled with Z3 support, rebuild "
+ "with -DCLANG_ANALYZER_BUILD_Z3=ON",
+ false);
+ return nullptr;
+#endif
+}
+
std::unique_ptr<ConstraintManager>
ento::CreateZ3ConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) {
#if CLANG_ANALYZER_WITH_Z3
return llvm::make_unique<Z3ConstraintManager>(Eng, StMgr.getSValBuilder());
#else
- llvm::report_fatal_error("Clang was not compiled with Z3 support!", false);
+ llvm::report_fatal_error("Clang was not compiled with Z3 support, rebuild "
+ "with -DCLANG_ANALYZER_BUILD_Z3=ON",
+ false);
return nullptr;
#endif
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index fccea9ee53bf..44abde5da6d1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -22,6 +22,7 @@
#include "clang/Analysis/CallGraph.h"
#include "clang/Analysis/CodeInjector.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/CrossTU/CrossTranslationUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
@@ -57,6 +58,8 @@ STATISTIC(NumFunctionsAnalyzed,
"with inlining turned on).");
STATISTIC(NumBlocksInAnalyzedFunctions,
"The # of basic blocks in the analyzed functions.");
+STATISTIC(NumVisitedBlocksInAnalyzedFunctions,
+ "The # of visited basic blocks in the analyzed functions.");
STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
@@ -70,7 +73,7 @@ void ento::createPlistHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
const Preprocessor &PP) {
createHTMLDiagnosticConsumer(AnalyzerOpts, C,
llvm::sys::path::parent_path(prefix), PP);
- createPlistDiagnosticConsumer(AnalyzerOpts, C, prefix, PP);
+ createPlistMultiFileDiagnosticConsumer(AnalyzerOpts, C, prefix, PP);
}
void ento::createTextPathDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
@@ -161,6 +164,8 @@ class AnalysisConsumer : public AnalysisASTConsumer,
/// Bug Reporter to use while recursively visiting Decls.
BugReporter *RecVisitorBR;
+ std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns;
+
public:
ASTContext *Ctx;
const Preprocessor &PP;
@@ -168,8 +173,9 @@ public:
AnalyzerOptionsRef Opts;
ArrayRef<std::string> Plugins;
CodeInjector *Injector;
+ cross_tu::CrossTranslationUnitContext CTU;
- /// \brief Stores the declarations from the local translation unit.
+ /// Stores the declarations from the local translation unit.
/// Note, we pre-compute the local declarations at parse time as an
/// optimization to make sure we do not deserialize everything from disk.
/// The local declaration to all declarations ratio might be very small when
@@ -186,28 +192,31 @@ public:
std::unique_ptr<AnalysisManager> Mgr;
/// Time the analyzes time of each translation unit.
- static llvm::Timer* TUTotalTimer;
+ std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
+ std::unique_ptr<llvm::Timer> TUTotalTimer;
/// The information about analyzed functions shared throughout the
/// translation unit.
FunctionSummariesTy FunctionSummaries;
- AnalysisConsumer(const Preprocessor &pp, const std::string &outdir,
+ AnalysisConsumer(CompilerInstance &CI, const std::string &outdir,
AnalyzerOptionsRef opts, ArrayRef<std::string> plugins,
CodeInjector *injector)
- : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr), PP(pp),
- OutDir(outdir), Opts(std::move(opts)), Plugins(plugins),
- Injector(injector) {
+ : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
+ PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
+ Plugins(plugins), Injector(injector), CTU(CI) {
DigestAnalyzerOptions();
- if (Opts->PrintStats) {
- llvm::EnableStatistics(false);
- TUTotalTimer = new llvm::Timer("time", "Analyzer Total Time");
+ if (Opts->PrintStats || Opts->shouldSerializeStats()) {
+ AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
+ "analyzer", "Analyzer timers");
+ TUTotalTimer = llvm::make_unique<llvm::Timer>(
+ "time", "Analyzer total time", *AnalyzerTimers);
+ llvm::EnableStatistics(/* PrintOnExit= */ false);
}
}
~AnalysisConsumer() override {
if (Opts->PrintStats) {
- delete TUTotalTimer;
llvm::PrintStatistics();
}
}
@@ -286,32 +295,33 @@ public:
void Initialize(ASTContext &Context) override {
Ctx = &Context;
- checkerMgr = createCheckerManager(*Opts, PP.getLangOpts(), Plugins,
- PP.getDiagnostics());
+ checkerMgr =
+ createCheckerManager(*Opts, PP.getLangOpts(), Plugins,
+ CheckerRegistrationFns, PP.getDiagnostics());
Mgr = llvm::make_unique<AnalysisManager>(
*Ctx, PP.getDiagnostics(), PP.getLangOpts(), PathConsumers,
CreateStoreMgr, CreateConstraintMgr, checkerMgr.get(), *Opts, Injector);
}
- /// \brief Store the top level decls in the set to be processed later on.
+ /// Store the top level decls in the set to be processed later on.
/// (Doing this pre-processing avoids deserialization of data from PCH.)
bool HandleTopLevelDecl(DeclGroupRef D) override;
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
void HandleTranslationUnit(ASTContext &C) override;
- /// \brief Determine which inlining mode should be used when this function is
+ /// Determine which inlining mode should be used when this function is
/// analyzed. This allows to redefine the default inlining policies when
/// analyzing a given function.
ExprEngine::InliningModes
getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
- /// \brief Build the call graph for all the top level decls of this TU and
+ /// Build the call graph for all the top level decls of this TU and
/// use it to define the order in which the functions should be visited.
void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);
- /// \brief Run analyzes(syntax or path sensitive) on the given function.
+ /// Run analyzes(syntax or path sensitive) on the given function.
/// \param Mode - determines if we are requesting syntax only or path
/// sensitive only analysis.
/// \param VisitedCallees - The output parameter, which is populated with the
@@ -378,13 +388,20 @@ public:
PathConsumers.push_back(Consumer);
}
+ void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
+ CheckerRegistrationFns.push_back(std::move(Fn));
+ }
+
private:
void storeTopLevelDecls(DeclGroupRef DG);
std::string getFunctionName(const Decl *D);
- /// \brief Check if we should skip (not analyze) the given function.
+ /// Check if we should skip (not analyze) the given function.
AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
+ void runAnalysisOnTranslationUnit(ASTContext &C);
+ /// Print \p S to stderr if \c Opts->AnalyzerDisplayProgress is set.
+ void reportAnalyzerProgress(StringRef S);
};
} // end anonymous namespace
@@ -392,8 +409,6 @@ private:
//===----------------------------------------------------------------------===//
// AnalysisConsumer implementation.
//===----------------------------------------------------------------------===//
-llvm::Timer* AnalysisConsumer::TUTotalTimer = nullptr;
-
bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
storeTopLevelDecls(DG);
return true;
@@ -508,68 +523,90 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
}
}
+static bool isBisonFile(ASTContext &C) {
+ const SourceManager &SM = C.getSourceManager();
+ FileID FID = SM.getMainFileID();
+ StringRef Buffer = SM.getBuffer(FID)->getBuffer();
+ if (Buffer.startswith("/* A Bison parser, made by"))
+ return true;
+ return false;
+}
+
+void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) {
+ BugReporter BR(*Mgr);
+ TranslationUnitDecl *TU = C.getTranslationUnitDecl();
+ checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
+
+ // Run the AST-only checks using the order in which functions are defined.
+ // If inlining is not turned on, use the simplest function order for path
+ // sensitive analyzes as well.
+ RecVisitorMode = AM_Syntax;
+ if (!Mgr->shouldInlineCall())
+ RecVisitorMode |= AM_Path;
+ RecVisitorBR = &BR;
+
+ // Process all the top level declarations.
+ //
+ // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
+ // entries. Thus we don't use an iterator, but rely on LocalTUDecls
+ // random access. By doing so, we automatically compensate for iterators
+ // possibly being invalidated, although this is a bit slower.
+ const unsigned LocalTUDeclsSize = LocalTUDecls.size();
+ for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
+ TraverseDecl(LocalTUDecls[i]);
+ }
+
+ if (Mgr->shouldInlineCall())
+ HandleDeclsCallGraph(LocalTUDeclsSize);
+
+ // After all decls handled, run checkers on the entire TranslationUnit.
+ checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
+
+ RecVisitorBR = nullptr;
+}
+
+void AnalysisConsumer::reportAnalyzerProgress(StringRef S) {
+ if (Opts->AnalyzerDisplayProgress)
+ llvm::errs() << S;
+}
+
void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
+
// Don't run the actions if an error has occurred with parsing the file.
DiagnosticsEngine &Diags = PP.getDiagnostics();
if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
return;
- // Don't analyze if the user explicitly asked for no checks to be performed
- // on this file.
- if (Opts->DisableAllChecks)
- return;
-
- {
- if (TUTotalTimer) TUTotalTimer->startTimer();
-
- // Introduce a scope to destroy BR before Mgr.
- BugReporter BR(*Mgr);
- TranslationUnitDecl *TU = C.getTranslationUnitDecl();
- checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
-
- // Run the AST-only checks using the order in which functions are defined.
- // If inlining is not turned on, use the simplest function order for path
- // sensitive analyzes as well.
- RecVisitorMode = AM_Syntax;
- if (!Mgr->shouldInlineCall())
- RecVisitorMode |= AM_Path;
- RecVisitorBR = &BR;
-
- // Process all the top level declarations.
- //
- // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
- // entries. Thus we don't use an iterator, but rely on LocalTUDecls
- // random access. By doing so, we automatically compensate for iterators
- // possibly being invalidated, although this is a bit slower.
- const unsigned LocalTUDeclsSize = LocalTUDecls.size();
- for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
- TraverseDecl(LocalTUDecls[i]);
- }
+ if (TUTotalTimer) TUTotalTimer->startTimer();
- if (Mgr->shouldInlineCall())
- HandleDeclsCallGraph(LocalTUDeclsSize);
+ if (isBisonFile(C)) {
+ reportAnalyzerProgress("Skipping bison-generated file\n");
+ } else if (Opts->DisableAllChecks) {
- // After all decls handled, run checkers on the entire TranslationUnit.
- checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
-
- RecVisitorBR = nullptr;
+ // Don't analyze if the user explicitly asked for no checks to be performed
+ // on this file.
+ reportAnalyzerProgress("All checks are disabled using a supplied option\n");
+ } else {
+ // Otherwise, just run the analysis.
+ runAnalysisOnTranslationUnit(C);
}
- // Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
- // FIXME: This should be replaced with something that doesn't rely on
- // side-effects in PathDiagnosticConsumer's destructor. This is required when
- // used with option -disable-free.
- Mgr.reset();
-
if (TUTotalTimer) TUTotalTimer->stopTimer();
// Count how many basic blocks we have not covered.
NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
+ NumVisitedBlocksInAnalyzedFunctions =
+ FunctionSummaries.getTotalNumVisitedBasicBlocks();
if (NumBlocksInAnalyzedFunctions > 0)
PercentReachableBlocks =
(FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
NumBlocksInAnalyzedFunctions;
+ // Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
+ // FIXME: This should be replaced with something that doesn't rely on
+ // side-effects in PathDiagnosticConsumer's destructor. This is required when
+ // used with option -disable-free.
+ Mgr.reset();
}
std::string AnalysisConsumer::getFunctionName(const Decl *D) {
@@ -648,7 +685,7 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
SourceLocation SL = Body ? Body->getLocStart() : D->getLocation();
SL = SM.getExpansionLoc(SL);
- if (!Opts->AnalyzeAll && !SM.isWrittenInMainFile(SL)) {
+ if (!Opts->AnalyzeAll && !Mgr->isInCodeFile(SL)) {
if (SL.isInvalid() || SM.isInSystemHeader(SL))
return AM_None;
return Mode & ~AM_Path;
@@ -704,7 +741,8 @@ void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
return;
- ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries,IMode);
+ ExprEngine Eng(CTU, *Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries,
+ IMode);
// Set the graph auditor.
std::unique_ptr<ExplodedNode::Auditor> Auditor;
@@ -762,7 +800,7 @@ ento::CreateAnalysisConsumer(CompilerInstance &CI) {
bool hasModelPath = analyzerOpts->Config.count("model-path") > 0;
return llvm::make_unique<AnalysisConsumer>(
- CI.getPreprocessor(), CI.getFrontendOpts().OutputFile, analyzerOpts,
+ CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
CI.getFrontendOpts().Plugins,
hasModelPath ? new ModelInjector(CI) : nullptr);
}
@@ -852,9 +890,9 @@ UbigraphViz::~UbigraphViz() {
std::string Ubiviz;
if (auto Path = llvm::sys::findProgramByName("ubiviz"))
Ubiviz = *Path;
- const char *args[] = {Ubiviz.c_str(), Filename.c_str(), nullptr};
+ std::array<StringRef, 2> Args{{Ubiviz, Filename}};
- if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, {}, 0, 0, &ErrMsg)) {
+ if (llvm::sys::ExecuteAndWait(Ubiviz, Args, llvm::None, {}, 0, 0, &ErrMsg)) {
llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 6792f89876cd..a260c2d85b11 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -111,16 +111,21 @@ getCheckerOptList(const AnalyzerOptions &opts) {
return checkerOpts;
}
-std::unique_ptr<CheckerManager>
-ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
- ArrayRef<std::string> plugins,
- DiagnosticsEngine &diags) {
+std::unique_ptr<CheckerManager> ento::createCheckerManager(
+ AnalyzerOptions &opts, const LangOptions &langOpts,
+ ArrayRef<std::string> plugins,
+ ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
+ DiagnosticsEngine &diags) {
std::unique_ptr<CheckerManager> checkerMgr(
new CheckerManager(langOpts, opts));
SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
ClangCheckerRegistry allCheckers(plugins, &diags);
+
+ for (const auto &Fn : checkerRegistrationFns)
+ Fn(allCheckers);
+
allCheckers.initializeManager(*checkerMgr, checkerOpts);
allCheckers.validateCheckerOptions(opts, diags);
checkerMgr->finishedCheckerRegistration();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp
index a65a5ee0a451..60825ef7411d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements an ASTConsumer for consuming model files.
+/// This file implements an ASTConsumer for consuming model files.
///
/// This ASTConsumer handles the AST of a parsed model file. All top level
/// function definitions will be collected from that model file for later
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index cdb1ed9b3815..c43d30440c8f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -10,6 +10,7 @@
#include "ModelInjector.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Stack.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
@@ -95,11 +96,10 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
ParseModelFileAction parseModelFile(Bodies);
- const unsigned ThreadStackSize = 8 << 20;
llvm::CrashRecoveryContext CRC;
CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); },
- ThreadStackSize);
+ DesiredStackSize);
Instance.getPreprocessor().FinalizeForModelFile();
@@ -109,7 +109,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
// The preprocessor enters to the main file id when parsing is started, so
// the main file id is changed to the model file during parsing and it needs
- // to be reseted to the former main file id after parsing of the model file
+ // to be reset to the former main file id after parsing of the model file
// is done.
SM.setMainFileID(mainFileID);
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h
index 98a5f69d68e8..b1b6de9ef9d9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines the clang::ento::ModelInjector class which implements the
+/// This file defines the clang::ento::ModelInjector class which implements the
/// clang::CodeInjector interface. This class is responsible for injecting
/// function definitions that were synthesized from model files.
///
@@ -43,7 +43,7 @@ public:
Stmt *getBody(const ObjCMethodDecl *D) override;
private:
- /// \brief Synthesize a body for a declaration
+ /// Synthesize a body for a declaration
///
/// This method first looks up the appropriate model file based on the
/// model-path configuration option and the name of the declaration that is
diff --git a/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index 6da0de7edf9a..a5d2d1d24729 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -369,7 +369,7 @@ SyntaxTree::Impl::getRelativeName(const NamedDecl *ND,
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.
+ // Strip the qualifier, if Val refers to something 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))
@@ -741,7 +741,7 @@ public:
List.pop();
}
// TODO this is here to get a stable output, not a good heuristic
- std::sort(Result.begin(), Result.end());
+ llvm::sort(Result.begin(), Result.end());
return Result;
}
int peekMax() const {
diff --git a/contrib/llvm/tools/clang/lib/Tooling/AllTUsExecution.cpp b/contrib/llvm/tools/clang/lib/Tooling/AllTUsExecution.cpp
new file mode 100644
index 000000000000..b761556ee76b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/AllTUsExecution.cpp
@@ -0,0 +1,161 @@
+//===- lib/Tooling/AllTUsExecution.cpp - Execute actions on all TUs. ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/AllTUsExecution.h"
+#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+#include "llvm/Support/ThreadPool.h"
+
+namespace clang {
+namespace tooling {
+
+const char *AllTUsToolExecutor::ExecutorName = "AllTUsToolExecutor";
+
+namespace {
+llvm::Error make_string_error(const llvm::Twine &Message) {
+ return llvm::make_error<llvm::StringError>(Message,
+ llvm::inconvertibleErrorCode());
+}
+
+ArgumentsAdjuster getDefaultArgumentsAdjusters() {
+ return combineAdjusters(
+ getClangStripOutputAdjuster(),
+ combineAdjusters(getClangSyntaxOnlyAdjuster(),
+ getClangStripDependencyFileAdjuster()));
+}
+
+class ThreadSafeToolResults : public ToolResults {
+public:
+ void addResult(StringRef Key, StringRef Value) override {
+ std::unique_lock<std::mutex> LockGuard(Mutex);
+ Results.addResult(Key, Value);
+ }
+
+ std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
+ AllKVResults() override {
+ return Results.AllKVResults();
+ }
+
+ void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)>
+ Callback) override {
+ Results.forEachResult(Callback);
+ }
+
+private:
+ InMemoryToolResults Results;
+ std::mutex Mutex;
+};
+
+} // namespace
+
+AllTUsToolExecutor::AllTUsToolExecutor(
+ const CompilationDatabase &Compilations, unsigned ThreadCount,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : Compilations(Compilations), Results(new ThreadSafeToolResults),
+ Context(Results.get()), ThreadCount(ThreadCount) {}
+
+AllTUsToolExecutor::AllTUsToolExecutor(
+ CommonOptionsParser Options, unsigned ThreadCount,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : OptionsParser(std::move(Options)),
+ Compilations(OptionsParser->getCompilations()),
+ Results(new ThreadSafeToolResults), Context(Results.get()),
+ ThreadCount(ThreadCount) {}
+
+llvm::Error AllTUsToolExecutor::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.");
+
+ std::string ErrorMsg;
+ std::mutex TUMutex;
+ auto AppendError = [&](llvm::Twine Err) {
+ std::unique_lock<std::mutex> LockGuard(TUMutex);
+ ErrorMsg += Err.str();
+ };
+
+ auto Log = [&](llvm::Twine Msg) {
+ std::unique_lock<std::mutex> LockGuard(TUMutex);
+ llvm::errs() << Msg.str() << "\n";
+ };
+
+ auto Files = Compilations.getAllFiles();
+ // Add a counter to track the progress.
+ const std::string TotalNumStr = std::to_string(Files.size());
+ unsigned Counter = 0;
+ auto Count = [&]() {
+ std::unique_lock<std::mutex> LockGuard(TUMutex);
+ return ++Counter;
+ };
+
+ auto &Action = Actions.front();
+
+ {
+ llvm::ThreadPool Pool(ThreadCount == 0 ? llvm::hardware_concurrency()
+ : ThreadCount);
+
+ for (std::string File : Files) {
+ Pool.async(
+ [&](std::string Path) {
+ Log("[" + std::to_string(Count()) + "/" + TotalNumStr +
+ "] Processing file " + Path);
+ ClangTool Tool(Compilations, {Path});
+ Tool.appendArgumentsAdjuster(Action.second);
+ Tool.appendArgumentsAdjuster(getDefaultArgumentsAdjusters());
+ for (const auto &FileAndContent : OverlayFiles)
+ Tool.mapVirtualFile(FileAndContent.first(),
+ FileAndContent.second);
+ if (Tool.run(Action.first.get()))
+ AppendError(llvm::Twine("Failed to run action on ") + Path +
+ "\n");
+ },
+ File);
+ }
+ }
+
+ if (!ErrorMsg.empty())
+ return make_string_error(ErrorMsg);
+
+ return llvm::Error::success();
+}
+
+static llvm::cl::opt<unsigned> ExecutorConcurrency(
+ "execute-concurrency",
+ llvm::cl::desc("The number of threads used to process all files in "
+ "parallel. Set to 0 for hardware concurrency."),
+ llvm::cl::init(0));
+
+class AllTUsToolExecutorPlugin : public ToolExecutorPlugin {
+public:
+ llvm::Expected<std::unique_ptr<ToolExecutor>>
+ create(CommonOptionsParser &OptionsParser) override {
+ if (OptionsParser.getSourcePathList().empty())
+ return make_string_error(
+ "[AllTUsToolExecutorPlugin] Please provide a directory/file path in "
+ "the compilation database.");
+ return llvm::make_unique<AllTUsToolExecutor>(std::move(OptionsParser),
+ ExecutorConcurrency);
+ }
+};
+
+static ToolExecutorPluginRegistry::Add<AllTUsToolExecutorPlugin>
+ X("all-TUs", "Runs FrontendActions on all TUs in the compilation database. "
+ "Tool results are stored in memory.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the plugin.
+volatile int AllTUsToolExecutorAnchorSource = 0;
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp b/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
index 7068ec2c4010..c8e9c167422e 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
@@ -1,4 +1,4 @@
-//===--- ArgumentsAdjusters.cpp - Command line arguments adjuster ---------===//
+//===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,6 +13,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstddef>
namespace clang {
namespace tooling {
@@ -21,7 +24,7 @@ namespace tooling {
ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
- for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ for (size_t i = 0, e = Args.size(); i < e; ++i) {
StringRef Arg = Args[i];
// FIXME: Remove options that generate output.
if (!Arg.startswith("-fcolor-diagnostics") &&
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
index 92b76b157dcb..31a769fa21e5 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
@@ -1,4 +1,4 @@
-//===--- CompilationDatabase.cpp - ----------------------------------------===//
+//===- CompilationDatabase.cpp --------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,9 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -26,20 +28,38 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Arg.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <iterator>
+#include <memory>
#include <sstream>
+#include <string>
#include <system_error>
+#include <utility>
+#include <vector>
+
using namespace clang;
using namespace tooling;
LLVM_INSTANTIATE_REGISTRY(CompilationDatabasePluginRegistry)
-CompilationDatabase::~CompilationDatabase() {}
+CompilationDatabase::~CompilationDatabase() = default;
std::unique_ptr<CompilationDatabase>
CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
@@ -121,20 +141,20 @@ std::vector<CompileCommand> CompilationDatabase::getAllCompileCommands() const {
return Result;
}
-CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
+CompilationDatabasePlugin::~CompilationDatabasePlugin() = default;
namespace {
+
// Helper for recursively searching through a chain of actions and collecting
// all inputs, direct and indirect, of compile jobs.
struct CompileJobAnalyzer {
+ SmallVector<std::string, 2> Inputs;
+
void run(const driver::Action *A) {
runImpl(A, false);
}
- SmallVector<std::string, 2> Inputs;
-
private:
-
void runImpl(const driver::Action *A, bool Collect) {
bool CollectChildren = Collect;
switch (A->getKind()) {
@@ -142,16 +162,16 @@ private:
CollectChildren = true;
break;
- case driver::Action::InputClass: {
+ case driver::Action::InputClass:
if (Collect) {
- const driver::InputAction *IA = cast<driver::InputAction>(A);
+ const auto *IA = cast<driver::InputAction>(A);
Inputs.push_back(IA->getInputArg().getSpelling());
}
- } break;
+ break;
default:
// Don't care about others
- ;
+ break;
}
for (const driver::Action *AI : A->inputs())
@@ -168,7 +188,7 @@ public:
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override {
- if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
+ if (Info.getID() == diag::warn_drv_input_file_unused) {
// Arg 1 for this diagnostic is the option that didn't get used.
UnusedInputs.push_back(Info.getArgStdStr(0));
} else if (DiagLevel >= DiagnosticsEngine::Error) {
@@ -186,18 +206,21 @@ public:
// S2 in Arr where S1 == S2?"
struct MatchesAny {
MatchesAny(ArrayRef<std::string> Arr) : Arr(Arr) {}
+
bool operator() (StringRef S) {
for (const std::string *I = Arr.begin(), *E = Arr.end(); I != E; ++I)
if (*I == S)
return true;
return false;
}
+
private:
ArrayRef<std::string> Arr;
};
+
} // namespace
-/// \brief Strips any positional args and possible argv[0] from a command-line
+/// Strips any positional args and possible argv[0] from a command-line
/// provided by the user to construct a FixedCompilationDatabase.
///
/// FixedCompilationDatabase requires a command line to be in this format as it
@@ -224,7 +247,7 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts);
UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
&*DiagOpts, &DiagClient, false);
// The clang executable path isn't required since the jobs the driver builds
@@ -362,11 +385,11 @@ class FixedCompilationDatabasePlugin : public CompilationDatabasePlugin {
}
};
+} // namespace
+
static CompilationDatabasePluginRegistry::Add<FixedCompilationDatabasePlugin>
X("fixed-compilation-database", "Reads plain-text flags file");
-} // namespace
-
namespace clang {
namespace tooling {
@@ -375,5 +398,5 @@ namespace tooling {
extern volatile int JSONAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED JSONAnchorDest = JSONAnchorSource;
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
index 6d4f3a340142..67e2dcfd73c1 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
@@ -1,4 +1,4 @@
-//===--- Replacement.cpp - Framework for clang refactoring tools ----------===//
+//===- Replacement.cpp - Framework for clang refactoring tools ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,21 +12,34 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Core/Replacement.h"
-
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_os_ostream.h"
-
-namespace clang {
-namespace tooling {
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <limits>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace tooling;
static const char * const InvalidLocation = "";
@@ -80,6 +93,9 @@ std::string Replacement::toString() const {
return Stream.str();
}
+namespace clang {
+namespace tooling {
+
bool operator<(const Replacement &LHS, const Replacement &RHS) {
if (LHS.getOffset() != RHS.getOffset())
return LHS.getOffset() < RHS.getOffset();
@@ -99,6 +115,9 @@ bool operator==(const Replacement &LHS, const Replacement &RHS) {
LHS.getReplacementText() == RHS.getReplacementText();
}
+} // namespace tooling
+} // namespace clang
+
void Replacement::setFromSourceLocation(const SourceManager &Sources,
SourceLocation Start, unsigned Length,
StringRef ReplacementText) {
@@ -201,7 +220,7 @@ Replacements Replacements::getCanonicalReplacements() const {
llvm::Expected<Replacements>
Replacements::mergeIfOrderIndependent(const Replacement &R) const {
Replacements Rs(R);
- // A Replacements set containg a single replacement that is `R` referring to
+ // A Replacements set containing a single replacement that is `R` referring to
// the code after the existing replacements `Replaces` are applied.
Replacements RsShiftedByReplaces(getReplacementInChangedCode(R));
// A Replacements set that is `Replaces` referring to the code after `R` is
@@ -231,7 +250,7 @@ llvm::Error Replacements::add(const Replacement &R) {
replacement_error::wrong_file_path, R, *Replaces.begin());
// Special-case header insertions.
- if (R.getOffset() == UINT_MAX) {
+ if (R.getOffset() == std::numeric_limits<unsigned>::max()) {
Replaces.insert(R);
return llvm::Error::success();
}
@@ -396,6 +415,7 @@ public:
// Returns 'true' if an element from the second set should be merged next.
bool mergeSecond() const { return MergeSecond; }
+
int deltaFirst() const { return DeltaFirst; }
Replacement asReplacement() const { return {FilePath, Offset, Length, Text}; }
@@ -463,11 +483,11 @@ Replacements Replacements::merge(const Replacements &ReplacesToMerge) const {
// Returns a set of non-overlapping and sorted ranges that is equivalent to
// \p Ranges.
static std::vector<Range> combineAndSortRanges(std::vector<Range> Ranges) {
- std::sort(Ranges.begin(), Ranges.end(),
- [](const Range &LHS, const Range &RHS) {
- if (LHS.getOffset() != RHS.getOffset())
- return LHS.getOffset() < RHS.getOffset();
- return LHS.getLength() < RHS.getLength();
+ llvm::sort(Ranges.begin(), Ranges.end(),
+ [](const Range &LHS, const Range &RHS) {
+ if (LHS.getOffset() != RHS.getOffset())
+ return LHS.getOffset() < RHS.getOffset();
+ return LHS.getLength() < RHS.getLength();
});
std::vector<Range> Result;
for (const auto &R : Ranges) {
@@ -485,6 +505,9 @@ static std::vector<Range> combineAndSortRanges(std::vector<Range> Ranges) {
return Result;
}
+namespace clang {
+namespace tooling {
+
std::vector<Range>
calculateRangesAfterReplacements(const Replacements &Replaces,
const std::vector<Range> &Ranges) {
@@ -508,10 +531,13 @@ calculateRangesAfterReplacements(const Replacements &Replaces,
return FakeReplaces.merge(Replaces).getAffectedRanges();
}
+} // namespace tooling
+} // namespace clang
+
std::vector<Range> Replacements::getAffectedRanges() const {
std::vector<Range> ChangedRanges;
int Shift = 0;
- for (const Replacement &R : Replaces) {
+ for (const auto &R : Replaces) {
unsigned Offset = R.getOffset() + Shift;
unsigned Length = R.getReplacementText().size();
Shift += Length - R.getLength();
@@ -522,7 +548,7 @@ std::vector<Range> Replacements::getAffectedRanges() const {
unsigned Replacements::getShiftedCodePosition(unsigned Position) const {
unsigned Offset = 0;
- for (const auto& R : Replaces) {
+ for (const auto &R : Replaces) {
if (R.getOffset() + R.getLength() <= Position) {
Offset += R.getReplacementText().size() - R.getLength();
continue;
@@ -530,7 +556,7 @@ unsigned Replacements::getShiftedCodePosition(unsigned Position) const {
if (R.getOffset() < Position &&
R.getOffset() + R.getReplacementText().size() <= Position) {
Position = R.getOffset() + R.getReplacementText().size();
- if (R.getReplacementText().size() > 0)
+ if (!R.getReplacementText().empty())
Position--;
}
break;
@@ -538,6 +564,9 @@ unsigned Replacements::getShiftedCodePosition(unsigned Position) const {
return Position + Offset;
}
+namespace clang {
+namespace tooling {
+
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) {
bool Result = true;
for (auto I = Replaces.rbegin(), E = Replaces.rend(); I != E; ++I) {
@@ -596,5 +625,5 @@ std::map<std::string, Replacements> groupReplacementsByFile(
return Result;
}
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp b/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp
index 498d683f8924..7ae67747acb2 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp
@@ -21,10 +21,10 @@ static llvm::cl::opt<std::string>
llvm::cl::init("standalone"));
void InMemoryToolResults::addResult(StringRef Key, StringRef Value) {
- KVResults.push_back({Key.str(), Value.str()});
+ KVResults.push_back({Strings.save(Key), Strings.save(Value)});
}
-std::vector<std::pair<std::string, std::string>>
+std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
InMemoryToolResults::AllKVResults() {
return KVResults;
}
@@ -96,10 +96,13 @@ createExecutorFromCommandLineArgs(int &argc, const char **argv,
}
// This anchor is used to force the linker to link in the generated object file
-// and thus register the StandaloneToolExecutorPlugin.
+// and thus register the StandaloneToolExecutorPlugin etc.
extern volatile int StandaloneToolExecutorAnchorSource;
+extern volatile int AllTUsToolExecutorAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED StandaloneToolExecutorAnchorDest =
StandaloneToolExecutorAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED AllTUsToolExecutorAnchorDest =
+ AllTUsToolExecutorAnchorSource;
} // end namespace tooling
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp b/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp
index 86ed036e2dbe..202b3f00f3fb 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp
@@ -1,4 +1,4 @@
-//===--- FileMatchTrie.cpp - ----------------------------------------------===//
+//===- FileMatchTrie.cpp --------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,31 +13,37 @@
#include "clang/Tooling/FileMatchTrie.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <sstream>
+#include <string>
+#include <vector>
+
using namespace clang;
using namespace tooling;
namespace {
-/// \brief Default \c PathComparator using \c llvm::sys::fs::equivalent().
+
+/// Default \c PathComparator using \c llvm::sys::fs::equivalent().
struct DefaultPathComparator : public PathComparator {
bool equivalent(StringRef FileA, StringRef FileB) const override {
return FileA == FileB || llvm::sys::fs::equivalent(FileA, FileB);
}
};
-}
+
+} // namespace
namespace clang {
namespace tooling {
-/// \brief A node of the \c FileMatchTrie.
+
+/// A node of the \c FileMatchTrie.
///
/// Each node has storage for up to one path and a map mapping a path segment to
/// child nodes. The trie starts with an empty root node.
class FileMatchTrieNode {
public:
- /// \brief Inserts 'NewPath' into this trie. \c ConsumedLength denotes
+ /// Inserts 'NewPath' into this trie. \c ConsumedLength denotes
/// the number of \c NewPath's trailing characters already consumed during
/// recursion.
///
@@ -75,7 +81,7 @@ public:
Children[Element].insert(NewPath, ConsumedLength + Element.size() + 1);
}
- /// \brief Tries to find the node under this \c FileMatchTrieNode that best
+ /// Tries to find the node under this \c FileMatchTrieNode that best
/// matches 'FileName'.
///
/// If multiple paths fit 'FileName' equally well, \c IsAmbiguous is set to
@@ -85,7 +91,7 @@ public:
///
/// To find the best matching node for a given path 'p', the
/// \c findEquivalent() function is called recursively for each path segment
- /// (back to fron) of 'p' until a node 'n' is reached that does not ..
+ /// (back to front) of 'p' until a node 'n' is reached that does not ..
/// - .. have children. In this case it is checked
/// whether the stored path is equivalent to 'p'. If yes, the best match is
/// found. Otherwise continue with the parent node as if this node did not
@@ -103,7 +109,7 @@ public:
if (Children.empty()) {
if (Comparator.equivalent(StringRef(Path), FileName))
return StringRef(Path);
- return StringRef();
+ return {};
}
StringRef Element(llvm::sys::path::filename(FileName.drop_back(
ConsumedLength)));
@@ -119,13 +125,13 @@ public:
std::vector<StringRef> AllChildren;
getAll(AllChildren, MatchingChild);
StringRef Result;
- for (unsigned i = 0; i < AllChildren.size(); i++) {
- if (Comparator.equivalent(AllChildren[i], FileName)) {
+ for (const auto &Child : AllChildren) {
+ if (Comparator.equivalent(Child, FileName)) {
if (Result.empty()) {
- Result = AllChildren[i];
+ Result = Child;
} else {
IsAmbiguous = true;
- return StringRef();
+ return {};
}
}
}
@@ -133,7 +139,7 @@ public:
}
private:
- /// \brief Gets all paths under this FileMatchTrieNode.
+ /// Gets all paths under this FileMatchTrieNode.
void getAll(std::vector<StringRef> &Results,
llvm::StringMap<FileMatchTrieNode>::const_iterator Except) const {
if (Path.empty())
@@ -158,14 +164,15 @@ private:
// The children of this node stored in a map based on the next path segment.
llvm::StringMap<FileMatchTrieNode> Children;
};
-} // end namespace tooling
-} // end namespace clang
+
+} // namespace tooling
+} // namespace clang
FileMatchTrie::FileMatchTrie()
- : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {}
+ : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {}
FileMatchTrie::FileMatchTrie(PathComparator *Comparator)
- : Root(new FileMatchTrieNode), Comparator(Comparator) {}
+ : Root(new FileMatchTrieNode), Comparator(Comparator) {}
FileMatchTrie::~FileMatchTrie() {
delete Root;
@@ -179,7 +186,7 @@ StringRef FileMatchTrie::findEquivalent(StringRef FileName,
raw_ostream &Error) const {
if (llvm::sys::path::is_relative(FileName)) {
Error << "Cannot resolve relative paths";
- return StringRef();
+ return {};
}
bool IsAmbiguous = false;
StringRef Result = Root->findEquivalent(*Comparator, FileName, IsAmbiguous);
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Inclusions/CMakeLists.txt b/contrib/llvm/tools/clang/lib/Tooling/Inclusions/CMakeLists.txt
new file mode 100644
index 000000000000..00afb50f3a69
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Inclusions/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangToolingInclusions
+ HeaderIncludes.cpp
+ IncludeStyle.cpp
+
+ LINK_LIBS
+ clangBasic
+ clangLex
+ clangRewrite
+ clangToolingCore
+ )
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/contrib/llvm/tools/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
new file mode 100644
index 000000000000..99c0866a6855
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -0,0 +1,330 @@
+//===--- HeaderIncludes.cpp - Insert/Delete #includes --*- C++ -*----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Inclusions/HeaderIncludes.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace tooling {
+namespace {
+
+LangOptions createLangOpts() {
+ LangOptions LangOpts;
+ LangOpts.CPlusPlus = 1;
+ LangOpts.CPlusPlus11 = 1;
+ LangOpts.CPlusPlus14 = 1;
+ LangOpts.LineComment = 1;
+ LangOpts.CXXOperatorNames = 1;
+ LangOpts.Bool = 1;
+ LangOpts.ObjC1 = 1;
+ LangOpts.ObjC2 = 1;
+ LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
+ LangOpts.DeclSpecKeyword = 1; // To get __declspec.
+ LangOpts.WChar = 1; // To get wchar_t
+ return LangOpts;
+}
+
+// Returns the offset after skipping a sequence of tokens, matched by \p
+// GetOffsetAfterSequence, from the start of the code.
+// \p GetOffsetAfterSequence should be a function that matches a sequence of
+// tokens and returns an offset after the sequence.
+unsigned getOffsetAfterTokenSequence(
+ StringRef FileName, StringRef Code, const IncludeStyle &Style,
+ llvm::function_ref<unsigned(const SourceManager &, Lexer &, Token &)>
+ GetOffsetAfterSequence) {
+ SourceManagerForFile VirtualSM(FileName, Code);
+ SourceManager &SM = VirtualSM.get();
+ Lexer Lex(SM.getMainFileID(), SM.getBuffer(SM.getMainFileID()), SM,
+ createLangOpts());
+ Token Tok;
+ // Get the first token.
+ Lex.LexFromRawLexer(Tok);
+ return GetOffsetAfterSequence(SM, Lex, Tok);
+}
+
+// Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is,
+// \p Tok will be the token after this directive; otherwise, it can be any token
+// after the given \p Tok (including \p Tok).
+bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &Tok) {
+ bool Matched = Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
+ Tok.is(tok::raw_identifier) &&
+ Tok.getRawIdentifier() == Name && !Lex.LexFromRawLexer(Tok) &&
+ Tok.is(tok::raw_identifier);
+ if (Matched)
+ Lex.LexFromRawLexer(Tok);
+ return Matched;
+}
+
+void skipComments(Lexer &Lex, Token &Tok) {
+ while (Tok.is(tok::comment))
+ if (Lex.LexFromRawLexer(Tok))
+ return;
+}
+
+// Returns the offset after header guard directives and any comments
+// before/after header guards. If no header guard presents in the code, this
+// will returns the offset after skipping all comments from the start of the
+// code.
+unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName,
+ StringRef Code,
+ const IncludeStyle &Style) {
+ return getOffsetAfterTokenSequence(
+ FileName, Code, Style,
+ [](const SourceManager &SM, Lexer &Lex, Token Tok) {
+ skipComments(Lex, Tok);
+ unsigned InitialOffset = SM.getFileOffset(Tok.getLocation());
+ if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) {
+ skipComments(Lex, Tok);
+ if (checkAndConsumeDirectiveWithName(Lex, "define", Tok))
+ return SM.getFileOffset(Tok.getLocation());
+ }
+ return InitialOffset;
+ });
+}
+
+// Check if a sequence of tokens is like
+// "#include ("header.h" | <header.h>)".
+// If it is, \p Tok will be the token after this directive; otherwise, it can be
+// any token after the given \p Tok (including \p Tok).
+bool checkAndConsumeInclusiveDirective(Lexer &Lex, Token &Tok) {
+ auto Matched = [&]() {
+ Lex.LexFromRawLexer(Tok);
+ return true;
+ };
+ if (Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
+ Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "include") {
+ if (Lex.LexFromRawLexer(Tok))
+ return false;
+ if (Tok.is(tok::string_literal))
+ return Matched();
+ if (Tok.is(tok::less)) {
+ while (!Lex.LexFromRawLexer(Tok) && Tok.isNot(tok::greater)) {
+ }
+ if (Tok.is(tok::greater))
+ return Matched();
+ }
+ }
+ return false;
+}
+
+// Returns the offset of the last #include directive after which a new
+// #include can be inserted. This ignores #include's after the #include block(s)
+// in the beginning of a file to avoid inserting headers into code sections
+// where new #include's should not be added by default.
+// These code sections include:
+// - raw string literals (containing #include).
+// - #if blocks.
+// - Special #include's among declarations (e.g. functions).
+//
+// If no #include after which a new #include can be inserted, this returns the
+// offset after skipping all comments from the start of the code.
+// Inserting after an #include is not allowed if it comes after code that is not
+// #include (e.g. pre-processing directive that is not #include, declarations).
+unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code,
+ const IncludeStyle &Style) {
+ return getOffsetAfterTokenSequence(
+ FileName, Code, Style,
+ [](const SourceManager &SM, Lexer &Lex, Token Tok) {
+ skipComments(Lex, Tok);
+ unsigned MaxOffset = SM.getFileOffset(Tok.getLocation());
+ while (checkAndConsumeInclusiveDirective(Lex, Tok))
+ MaxOffset = SM.getFileOffset(Tok.getLocation());
+ return MaxOffset;
+ });
+}
+
+inline StringRef trimInclude(StringRef IncludeName) {
+ return IncludeName.trim("\"<>");
+}
+
+const char IncludeRegexPattern[] =
+ R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
+
+} // anonymous namespace
+
+IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle &Style,
+ StringRef FileName)
+ : Style(Style), FileName(FileName) {
+ FileStem = llvm::sys::path::stem(FileName);
+ for (const auto &Category : Style.IncludeCategories)
+ CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
+ IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
+ FileName.endswith(".cpp") || FileName.endswith(".c++") ||
+ FileName.endswith(".cxx") || FileName.endswith(".m") ||
+ FileName.endswith(".mm");
+}
+
+int IncludeCategoryManager::getIncludePriority(StringRef IncludeName,
+ bool CheckMainHeader) const {
+ int Ret = INT_MAX;
+ for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
+ if (CategoryRegexs[i].match(IncludeName)) {
+ Ret = Style.IncludeCategories[i].Priority;
+ break;
+ }
+ if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
+ Ret = 0;
+ return Ret;
+}
+
+bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
+ if (!IncludeName.startswith("\""))
+ return false;
+ StringRef HeaderStem =
+ llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
+ if (FileStem.startswith(HeaderStem) ||
+ FileStem.startswith_lower(HeaderStem)) {
+ llvm::Regex MainIncludeRegex((HeaderStem + Style.IncludeIsMainRegex).str(),
+ llvm::Regex::IgnoreCase);
+ if (MainIncludeRegex.match(FileStem))
+ return true;
+ }
+ return false;
+}
+
+HeaderIncludes::HeaderIncludes(StringRef FileName, StringRef Code,
+ const IncludeStyle &Style)
+ : FileName(FileName), Code(Code), FirstIncludeOffset(-1),
+ MinInsertOffset(
+ getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style)),
+ MaxInsertOffset(MinInsertOffset +
+ getMaxHeaderInsertionOffset(
+ FileName, Code.drop_front(MinInsertOffset), Style)),
+ Categories(Style, FileName),
+ IncludeRegex(llvm::Regex(IncludeRegexPattern)) {
+ // Add 0 for main header and INT_MAX for headers that are not in any
+ // category.
+ Priorities = {0, INT_MAX};
+ for (const auto &Category : Style.IncludeCategories)
+ Priorities.insert(Category.Priority);
+ SmallVector<StringRef, 32> Lines;
+ Code.drop_front(MinInsertOffset).split(Lines, "\n");
+
+ unsigned Offset = MinInsertOffset;
+ unsigned NextLineOffset;
+ SmallVector<StringRef, 4> Matches;
+ for (auto Line : Lines) {
+ NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1);
+ if (IncludeRegex.match(Line, &Matches)) {
+ // If this is the last line without trailing newline, we need to make
+ // sure we don't delete across the file boundary.
+ addExistingInclude(
+ Include(Matches[2],
+ tooling::Range(
+ Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+ NextLineOffset);
+ }
+ Offset = NextLineOffset;
+ }
+
+ // Populate CategoryEndOfssets:
+ // - Ensure that CategoryEndOffset[Highest] is always populated.
+ // - If CategoryEndOffset[Priority] isn't set, use the next higher value
+ // that is set, up to CategoryEndOffset[Highest].
+ auto Highest = Priorities.begin();
+ if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) {
+ if (FirstIncludeOffset >= 0)
+ CategoryEndOffsets[*Highest] = FirstIncludeOffset;
+ else
+ CategoryEndOffsets[*Highest] = MinInsertOffset;
+ }
+ // By this point, CategoryEndOffset[Highest] is always set appropriately:
+ // - to an appropriate location before/after existing #includes, or
+ // - to right after the header guard, or
+ // - to the beginning of the file.
+ for (auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I)
+ if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
+ CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];
+}
+
+// \p Offset: the start of the line following this include directive.
+void HeaderIncludes::addExistingInclude(Include IncludeToAdd,
+ unsigned NextLineOffset) {
+ auto Iter =
+ ExistingIncludes.try_emplace(trimInclude(IncludeToAdd.Name)).first;
+ Iter->second.push_back(std::move(IncludeToAdd));
+ auto &CurInclude = Iter->second.back();
+ // The header name with quotes or angle brackets.
+ // Only record the offset of current #include if we can insert after it.
+ if (CurInclude.R.getOffset() <= MaxInsertOffset) {
+ int Priority = Categories.getIncludePriority(
+ CurInclude.Name, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+ CategoryEndOffsets[Priority] = NextLineOffset;
+ IncludesByPriority[Priority].push_back(&CurInclude);
+ if (FirstIncludeOffset < 0)
+ FirstIncludeOffset = CurInclude.R.getOffset();
+ }
+}
+
+llvm::Optional<tooling::Replacement>
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+ assert(IncludeName == trimInclude(IncludeName));
+ // If a <header> ("header") already exists in code, "header" (<header>) with
+ // different quotation will still be inserted.
+ // FIXME: figure out if this is the best behavior.
+ auto It = ExistingIncludes.find(IncludeName);
+ if (It != ExistingIncludes.end())
+ for (const auto &Inc : It->second)
+ if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+ (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+ return llvm::None;
+ std::string Quoted = IsAngled ? ("<" + IncludeName + ">").str()
+ : ("\"" + IncludeName + "\"").str();
+ StringRef QuotedName = Quoted;
+ int Priority = Categories.getIncludePriority(
+ QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+ auto CatOffset = CategoryEndOffsets.find(Priority);
+ assert(CatOffset != CategoryEndOffsets.end());
+ unsigned InsertOffset = CatOffset->second; // Fall back offset
+ auto Iter = IncludesByPriority.find(Priority);
+ if (Iter != IncludesByPriority.end()) {
+ for (const auto *Inc : Iter->second) {
+ if (QuotedName < Inc->Name) {
+ InsertOffset = Inc->R.getOffset();
+ break;
+ }
+ }
+ }
+ assert(InsertOffset <= Code.size());
+ std::string NewInclude = ("#include " + QuotedName + "\n").str();
+ // When inserting headers at end of the code, also append '\n' to the code
+ // if it does not end with '\n'.
+ // FIXME: when inserting multiple #includes at the end of code, only one
+ // newline should be added.
+ if (InsertOffset == Code.size() && (!Code.empty() && Code.back() != '\n'))
+ NewInclude = "\n" + NewInclude;
+ return tooling::Replacement(FileName, InsertOffset, 0, NewInclude);
+}
+
+tooling::Replacements HeaderIncludes::remove(llvm::StringRef IncludeName,
+ bool IsAngled) const {
+ assert(IncludeName == trimInclude(IncludeName));
+ tooling::Replacements Result;
+ auto Iter = ExistingIncludes.find(IncludeName);
+ if (Iter == ExistingIncludes.end())
+ return Result;
+ for (const auto &Inc : Iter->second) {
+ if ((IsAngled && StringRef(Inc.Name).startswith("\"")) ||
+ (!IsAngled && StringRef(Inc.Name).startswith("<")))
+ continue;
+ llvm::Error Err = Result.add(tooling::Replacement(
+ FileName, Inc.R.getOffset(), Inc.R.getLength(), ""));
+ if (Err) {
+ auto ErrMsg = "Unexpected conflicts in #include deletions: " +
+ llvm::toString(std::move(Err));
+ llvm_unreachable(ErrMsg.c_str());
+ }
+ }
+ return Result;
+}
+
+
+} // namespace tooling
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Inclusions/IncludeStyle.cpp b/contrib/llvm/tools/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
new file mode 100644
index 000000000000..3597710f1f6e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
@@ -0,0 +1,31 @@
+//===--- IncludeStyle.cpp - Style of C++ #include directives -----*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Inclusions/IncludeStyle.h"
+
+using clang::tooling::IncludeStyle;
+
+namespace llvm {
+namespace yaml {
+
+void MappingTraits<IncludeStyle::IncludeCategory>::mapping(
+ IO &IO, IncludeStyle::IncludeCategory &Category) {
+ IO.mapOptional("Regex", Category.Regex);
+ IO.mapOptional("Priority", Category.Priority);
+}
+
+void ScalarEnumerationTraits<IncludeStyle::IncludeBlocksStyle>::enumeration(
+ IO &IO, IncludeStyle::IncludeBlocksStyle &Value) {
+ IO.enumCase(Value, "Preserve", IncludeStyle::IBS_Preserve);
+ IO.enumCase(Value, "Merge", IncludeStyle::IBS_Merge);
+ IO.enumCase(Value, "Regroup", IncludeStyle::IBS_Regroup);
+}
+
+} // namespace yaml
+} // namespace llvm
diff --git a/contrib/llvm/tools/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
new file mode 100644
index 000000000000..bc564584bd01
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -0,0 +1,458 @@
+//===- InterpolatingCompilationDatabase.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// InterpolatingCompilationDatabase wraps another CompilationDatabase and
+// attempts to heuristically determine appropriate compile commands for files
+// that are not included, such as headers or newly created files.
+//
+// Motivating cases include:
+// Header files that live next to their implementation files. These typically
+// share a base filename. (libclang/CXString.h, libclang/CXString.cpp).
+// Some projects separate headers from includes. Filenames still typically
+// match, maybe other path segments too. (include/llvm/IR/Use.h, lib/IR/Use.cc).
+// Matches are sometimes only approximate (Sema.h, SemaDecl.cpp). This goes
+// for directories too (Support/Unix/Process.inc, lib/Support/Process.cpp).
+// Even if we can't find a "right" compile command, even a random one from
+// the project will tend to get important flags like -I and -x right.
+//
+// We "borrow" the compile command for the closest available file:
+// - points are awarded if the filename matches (ignoring extension)
+// - points are awarded if the directory structure matches
+// - ties are broken by length of path prefix match
+//
+// The compile command is adjusted, replacing the filename and removing output
+// file arguments. The -x and -std flags may be affected too.
+//
+// Source language is a tricky issue: is it OK to use a .c file's command
+// for building a .cc file? What language is a .h file in?
+// - We only consider compile commands for c-family languages as candidates.
+// - For files whose language is implied by the filename (e.g. .m, .hpp)
+// we prefer candidates from the same language.
+// If we must cross languages, we drop any -x and -std flags.
+// - For .h files, candidates from any c-family language are acceptable.
+// We use the candidate's language, inserting e.g. -x c++-header.
+//
+// This class is only useful when wrapping databases that can enumerate all
+// their compile commands. If getAllFilenames() is empty, no inference occurs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Types.h"
+#include "clang/Frontend/LangStandard.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+namespace clang {
+namespace tooling {
+namespace {
+using namespace llvm;
+namespace types = clang::driver::types;
+namespace path = llvm::sys::path;
+
+// The length of the prefix these two strings have in common.
+size_t matchingPrefix(StringRef L, StringRef R) {
+ size_t Limit = std::min(L.size(), R.size());
+ for (size_t I = 0; I < Limit; ++I)
+ if (L[I] != R[I])
+ return I;
+ return Limit;
+}
+
+// A comparator for searching SubstringWithIndexes with std::equal_range etc.
+// Optionaly prefix semantics: compares equal if the key is a prefix.
+template <bool Prefix> struct Less {
+ bool operator()(StringRef Key, std::pair<StringRef, size_t> Value) const {
+ StringRef V = Prefix ? Value.first.substr(0, Key.size()) : Value.first;
+ return Key < V;
+ }
+ bool operator()(std::pair<StringRef, size_t> Value, StringRef Key) const {
+ StringRef V = Prefix ? Value.first.substr(0, Key.size()) : Value.first;
+ return V < Key;
+ }
+};
+
+// Infer type from filename. If we might have gotten it wrong, set *Certain.
+// *.h will be inferred as a C header, but not certain.
+types::ID guessType(StringRef Filename, bool *Certain = nullptr) {
+ // path::extension is ".cpp", lookupTypeForExtension wants "cpp".
+ auto Lang =
+ types::lookupTypeForExtension(path::extension(Filename).substr(1));
+ if (Certain)
+ *Certain = Lang != types::TY_CHeader && Lang != types::TY_INVALID;
+ return Lang;
+}
+
+// Return Lang as one of the canonical supported types.
+// e.g. c-header --> c; fortran --> TY_INVALID
+static types::ID foldType(types::ID Lang) {
+ switch (Lang) {
+ case types::TY_C:
+ case types::TY_CHeader:
+ return types::TY_C;
+ case types::TY_ObjC:
+ case types::TY_ObjCHeader:
+ return types::TY_ObjC;
+ case types::TY_CXX:
+ case types::TY_CXXHeader:
+ return types::TY_CXX;
+ case types::TY_ObjCXX:
+ case types::TY_ObjCXXHeader:
+ return types::TY_ObjCXX;
+ default:
+ return types::TY_INVALID;
+ }
+}
+
+// A CompileCommand that can be applied to another file.
+struct TransferableCommand {
+ // Flags that should not apply to all files are stripped from CommandLine.
+ CompileCommand Cmd;
+ // Language detected from -x or the filename.
+ types::ID Type = types::TY_INVALID;
+ // Standard specified by -std.
+ LangStandard::Kind Std = LangStandard::lang_unspecified;
+
+ TransferableCommand(CompileCommand C)
+ : Cmd(std::move(C)), Type(guessType(Cmd.Filename)) {
+ std::vector<std::string> NewArgs = {Cmd.CommandLine.front()};
+ // Parse the old args in order to strip out and record unwanted flags.
+ auto OptTable = clang::driver::createDriverOptTable();
+ std::vector<const char *> Argv;
+ for (unsigned I = 1; I < Cmd.CommandLine.size(); ++I)
+ Argv.push_back(Cmd.CommandLine[I].c_str());
+ unsigned MissingI, MissingC;
+ auto ArgList = OptTable->ParseArgs(Argv, MissingI, MissingC);
+ for (const auto *Arg : ArgList) {
+ const auto &option = Arg->getOption();
+ // Strip input and output files.
+ if (option.matches(clang::driver::options::OPT_INPUT) ||
+ option.matches(clang::driver::options::OPT_o)) {
+ continue;
+ }
+ // Strip -x, but record the overridden language.
+ if (option.matches(clang::driver::options::OPT_x)) {
+ for (const char *Value : Arg->getValues())
+ Type = types::lookupTypeForTypeSpecifier(Value);
+ continue;
+ }
+ // Strip --std, but record the value.
+ if (option.matches(clang::driver::options::OPT_std_EQ)) {
+ for (const char *Value : Arg->getValues()) {
+ Std = llvm::StringSwitch<LangStandard::Kind>(Value)
+#define LANGSTANDARD(id, name, lang, desc, features) \
+ .Case(name, LangStandard::lang_##id)
+#define LANGSTANDARD_ALIAS(id, alias) .Case(alias, LangStandard::lang_##id)
+#include "clang/Frontend/LangStandards.def"
+ .Default(Std);
+ }
+ continue;
+ }
+ llvm::opt::ArgStringList ArgStrs;
+ Arg->render(ArgList, ArgStrs);
+ NewArgs.insert(NewArgs.end(), ArgStrs.begin(), ArgStrs.end());
+ }
+ Cmd.CommandLine = std::move(NewArgs);
+
+ if (Std != LangStandard::lang_unspecified) // -std take precedence over -x
+ Type = toType(LangStandard::getLangStandardForKind(Std).getLanguage());
+ Type = foldType(Type);
+ }
+
+ // Produce a CompileCommand for \p filename, based on this one.
+ CompileCommand transferTo(StringRef Filename) const {
+ CompileCommand Result = Cmd;
+ Result.Filename = Filename;
+ bool TypeCertain;
+ auto TargetType = guessType(Filename, &TypeCertain);
+ // If the filename doesn't determine the language (.h), transfer with -x.
+ if (!TypeCertain) {
+ TargetType = types::onlyPrecompileType(TargetType) // header?
+ ? types::lookupHeaderTypeForSourceType(Type)
+ : Type;
+ Result.CommandLine.push_back("-x");
+ Result.CommandLine.push_back(types::getTypeName(TargetType));
+ }
+ // --std flag may only be transferred if the language is the same.
+ // We may consider "translating" these, e.g. c++11 -> c11.
+ if (Std != LangStandard::lang_unspecified && foldType(TargetType) == Type) {
+ Result.CommandLine.push_back(
+ "-std=" +
+ std::string(LangStandard::getLangStandardForKind(Std).getName()));
+ }
+ Result.CommandLine.push_back(Filename);
+ return Result;
+ }
+
+private:
+ // Map the language from the --std flag to that of the -x flag.
+ static types::ID toType(InputKind::Language Lang) {
+ switch (Lang) {
+ case InputKind::C:
+ return types::TY_C;
+ case InputKind::CXX:
+ return types::TY_CXX;
+ case InputKind::ObjC:
+ return types::TY_ObjC;
+ case InputKind::ObjCXX:
+ return types::TY_ObjCXX;
+ default:
+ return types::TY_INVALID;
+ }
+ }
+};
+
+// CommandIndex does the real work: given a filename, it produces the best
+// matching TransferableCommand by matching filenames. Basic strategy:
+// - Build indexes of each of the substrings we want to look up by.
+// These indexes are just sorted lists of the substrings.
+// - Forward requests to the inner CDB. If it fails, we must pick a proxy.
+// - Each criterion corresponds to a range lookup into the index, so we only
+// need O(log N) string comparisons to determine scores.
+// - We then break ties among the candidates with the highest score.
+class CommandIndex {
+public:
+ CommandIndex(std::vector<TransferableCommand> AllCommands)
+ : Commands(std::move(AllCommands)), Strings(Arena) {
+ // Sort commands by filename for determinism (index is a tiebreaker later).
+ llvm::sort(
+ Commands.begin(), Commands.end(),
+ [](const TransferableCommand &Left, const TransferableCommand &Right) {
+ return Left.Cmd.Filename < Right.Cmd.Filename;
+ });
+ for (size_t I = 0; I < Commands.size(); ++I) {
+ StringRef Path =
+ Strings.save(StringRef(Commands[I].Cmd.Filename).lower());
+ Paths.push_back({Path, I});
+ Stems.emplace_back(sys::path::stem(Path), I);
+ auto Dir = ++sys::path::rbegin(Path), DirEnd = sys::path::rend(Path);
+ for (int J = 0; J < DirectorySegmentsIndexed && Dir != DirEnd; ++J, ++Dir)
+ if (Dir->size() > ShortDirectorySegment) // not trivial ones
+ Components.emplace_back(*Dir, I);
+ }
+ llvm::sort(Paths.begin(), Paths.end());
+ llvm::sort(Stems.begin(), Stems.end());
+ llvm::sort(Components.begin(), Components.end());
+ }
+
+ bool empty() const { return Commands.empty(); }
+
+ // Returns the command that best fits OriginalFilename.
+ // Candidates with PreferLanguage will be chosen over others (unless it's
+ // TY_INVALID, or all candidates are bad).
+ const TransferableCommand &chooseProxy(StringRef OriginalFilename,
+ types::ID PreferLanguage) const {
+ assert(!empty() && "need at least one candidate!");
+ std::string Filename = OriginalFilename.lower();
+ auto Candidates = scoreCandidates(Filename);
+ std::pair<size_t, int> Best =
+ pickWinner(Candidates, Filename, PreferLanguage);
+
+ DEBUG_WITH_TYPE("interpolate",
+ llvm::dbgs()
+ << "interpolate: chose "
+ << Commands[Best.first].Cmd.Filename << " as proxy for "
+ << OriginalFilename << " preferring "
+ << (PreferLanguage == types::TY_INVALID
+ ? "none"
+ : types::getTypeName(PreferLanguage))
+ << " score=" << Best.second << "\n");
+ return Commands[Best.first];
+ }
+
+private:
+ using SubstringAndIndex = std::pair<StringRef, size_t>;
+ // Directory matching parameters: we look at the last two segments of the
+ // parent directory (usually the semantically significant ones in practice).
+ // We search only the last four of each candidate (for efficiency).
+ constexpr static int DirectorySegmentsIndexed = 4;
+ constexpr static int DirectorySegmentsQueried = 2;
+ constexpr static int ShortDirectorySegment = 1; // Only look at longer names.
+
+ // Award points to candidate entries that should be considered for the file.
+ // Returned keys are indexes into paths, and the values are (nonzero) scores.
+ DenseMap<size_t, int> scoreCandidates(StringRef Filename) const {
+ // Decompose Filename into the parts we care about.
+ // /some/path/complicated/project/Interesting.h
+ // [-prefix--][---dir---] [-dir-] [--stem---]
+ StringRef Stem = sys::path::stem(Filename);
+ llvm::SmallVector<StringRef, DirectorySegmentsQueried> Dirs;
+ llvm::StringRef Prefix;
+ auto Dir = ++sys::path::rbegin(Filename),
+ DirEnd = sys::path::rend(Filename);
+ for (int I = 0; I < DirectorySegmentsQueried && Dir != DirEnd; ++I, ++Dir) {
+ if (Dir->size() > ShortDirectorySegment)
+ Dirs.push_back(*Dir);
+ Prefix = Filename.substr(0, Dir - DirEnd);
+ }
+
+ // Now award points based on lookups into our various indexes.
+ DenseMap<size_t, int> Candidates; // Index -> score.
+ auto Award = [&](int Points, ArrayRef<SubstringAndIndex> Range) {
+ for (const auto &Entry : Range)
+ Candidates[Entry.second] += Points;
+ };
+ // Award one point if the file's basename is a prefix of the candidate,
+ // and another if it's an exact match (so exact matches get two points).
+ Award(1, indexLookup</*Prefix=*/true>(Stem, Stems));
+ Award(1, indexLookup</*Prefix=*/false>(Stem, Stems));
+ // For each of the last few directories in the Filename, award a point
+ // if it's present in the candidate.
+ for (StringRef Dir : Dirs)
+ Award(1, indexLookup</*Prefix=*/false>(Dir, Components));
+ // Award one more point if the whole rest of the path matches.
+ if (sys::path::root_directory(Prefix) != Prefix)
+ Award(1, indexLookup</*Prefix=*/true>(Prefix, Paths));
+ return Candidates;
+ }
+
+ // Pick a single winner from the set of scored candidates.
+ // Returns (index, score).
+ std::pair<size_t, int> pickWinner(const DenseMap<size_t, int> &Candidates,
+ StringRef Filename,
+ types::ID PreferredLanguage) const {
+ struct ScoredCandidate {
+ size_t Index;
+ bool Preferred;
+ int Points;
+ size_t PrefixLength;
+ };
+ // Choose the best candidate by (preferred, points, prefix length, alpha).
+ ScoredCandidate Best = {size_t(-1), false, 0, 0};
+ for (const auto &Candidate : Candidates) {
+ ScoredCandidate S;
+ S.Index = Candidate.first;
+ S.Preferred = PreferredLanguage == types::TY_INVALID ||
+ PreferredLanguage == Commands[S.Index].Type;
+ S.Points = Candidate.second;
+ if (!S.Preferred && Best.Preferred)
+ continue;
+ if (S.Preferred == Best.Preferred) {
+ if (S.Points < Best.Points)
+ continue;
+ if (S.Points == Best.Points) {
+ S.PrefixLength = matchingPrefix(Filename, Paths[S.Index].first);
+ if (S.PrefixLength < Best.PrefixLength)
+ continue;
+ // hidden heuristics should at least be deterministic!
+ if (S.PrefixLength == Best.PrefixLength)
+ if (S.Index > Best.Index)
+ continue;
+ }
+ }
+ // PrefixLength was only set above if actually needed for a tiebreak.
+ // But it definitely needs to be set to break ties in the future.
+ S.PrefixLength = matchingPrefix(Filename, Paths[S.Index].first);
+ Best = S;
+ }
+ // Edge case: no candidate got any points.
+ // We ignore PreferredLanguage at this point (not ideal).
+ if (Best.Index == size_t(-1))
+ return {longestMatch(Filename, Paths).second, 0};
+ return {Best.Index, Best.Points};
+ }
+
+ // Returns the range within a sorted index that compares equal to Key.
+ // If Prefix is true, it's instead the range starting with Key.
+ template <bool Prefix>
+ ArrayRef<SubstringAndIndex>
+ indexLookup(StringRef Key, const std::vector<SubstringAndIndex> &Idx) const {
+ // Use pointers as iteratiors to ease conversion of result to ArrayRef.
+ auto Range = std::equal_range(Idx.data(), Idx.data() + Idx.size(), Key,
+ Less<Prefix>());
+ return {Range.first, Range.second};
+ }
+
+ // Performs a point lookup into a nonempty index, returning a longest match.
+ SubstringAndIndex
+ longestMatch(StringRef Key, const std::vector<SubstringAndIndex> &Idx) const {
+ assert(!Idx.empty());
+ // Longest substring match will be adjacent to a direct lookup.
+ auto It =
+ std::lower_bound(Idx.begin(), Idx.end(), SubstringAndIndex{Key, 0});
+ if (It == Idx.begin())
+ return *It;
+ if (It == Idx.end())
+ return *--It;
+ // Have to choose between It and It-1
+ size_t Prefix = matchingPrefix(Key, It->first);
+ size_t PrevPrefix = matchingPrefix(Key, (It - 1)->first);
+ return Prefix > PrevPrefix ? *It : *--It;
+ }
+
+ std::vector<TransferableCommand> Commands; // Indexes point into this.
+ BumpPtrAllocator Arena;
+ StringSaver Strings;
+ // Indexes of candidates by certain substrings.
+ // String is lowercase and sorted, index points into OriginalPaths.
+ std::vector<SubstringAndIndex> Paths; // Full path.
+ std::vector<SubstringAndIndex> Stems; // Basename, without extension.
+ std::vector<SubstringAndIndex> Components; // Last path components.
+};
+
+// The actual CompilationDatabase wrapper delegates to its inner database.
+// If no match, looks up a command in CommandIndex and transfers it to the file.
+class InterpolatingCompilationDatabase : public CompilationDatabase {
+public:
+ InterpolatingCompilationDatabase(std::unique_ptr<CompilationDatabase> Inner)
+ : Inner(std::move(Inner)), Index(allCommands()) {}
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef Filename) const override {
+ auto Known = Inner->getCompileCommands(Filename);
+ if (Index.empty() || !Known.empty())
+ return Known;
+ bool TypeCertain;
+ auto Lang = guessType(Filename, &TypeCertain);
+ if (!TypeCertain)
+ Lang = types::TY_INVALID;
+ return {Index.chooseProxy(Filename, foldType(Lang)).transferTo(Filename)};
+ }
+
+ std::vector<std::string> getAllFiles() const override {
+ return Inner->getAllFiles();
+ }
+
+ std::vector<CompileCommand> getAllCompileCommands() const override {
+ return Inner->getAllCompileCommands();
+ }
+
+private:
+ std::vector<TransferableCommand> allCommands() {
+ std::vector<TransferableCommand> Result;
+ for (auto Command : Inner->getAllCompileCommands()) {
+ Result.emplace_back(std::move(Command));
+ if (Result.back().Type == types::TY_INVALID)
+ Result.pop_back();
+ }
+ return Result;
+ }
+
+ std::unique_ptr<CompilationDatabase> Inner;
+ CommandIndex Index;
+};
+
+} // namespace
+
+std::unique_ptr<CompilationDatabase>
+inferMissingCompileCommands(std::unique_ptr<CompilationDatabase> Inner) {
+ return llvm::make_unique<InterpolatingCompilationDatabase>(std::move(Inner));
+}
+
+} // namespace tooling
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
index f9a230eb63a0..2fa5fce279d6 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
@@ -1,4 +1,4 @@
-//===--- JSONCompilationDatabase.cpp - ------------------------------------===//
+//===- JSONCompilationDatabase.cpp ----------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,22 +12,38 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/JSONCompilationDatabase.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
-#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
+#include <string>
#include <system_error>
+#include <tuple>
+#include <utility>
+#include <vector>
-namespace clang {
-namespace tooling {
+using namespace clang;
+using namespace tooling;
namespace {
-/// \brief A parser for escaped strings of command line arguments.
+/// A parser for escaped strings of command line arguments.
///
/// Assumes \-escaping for quoted arguments (see the documentation of
/// unescapeCommandLine(...)).
@@ -151,17 +167,23 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin {
}
};
-} // end namespace
+} // namespace
// Register the JSONCompilationDatabasePlugin with the
// CompilationDatabasePluginRegistry using this statically initialized variable.
static CompilationDatabasePluginRegistry::Add<JSONCompilationDatabasePlugin>
X("json-compilation-database", "Reads JSON formatted compilation databases");
+namespace clang {
+namespace tooling {
+
// This anchor is used to force the linker to link in the generated object file
// and thus register the JSONCompilationDatabasePlugin.
volatile int JSONAnchorSource = 0;
+} // namespace tooling
+} // namespace clang
+
std::unique_ptr<JSONCompilationDatabase>
JSONCompilationDatabase::loadFromFile(StringRef FilePath,
std::string &ErrorMessage,
@@ -201,11 +223,10 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
llvm::raw_string_ostream ES(Error);
StringRef Match = MatchTrie.findEquivalent(NativeFilePath, ES);
if (Match.empty())
- return std::vector<CompileCommand>();
- llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefI = IndexByFile.find(Match);
+ return {};
+ const auto CommandsRefI = IndexByFile.find(Match);
if (CommandsRefI == IndexByFile.end())
- return std::vector<CompileCommand>();
+ return {};
std::vector<CompileCommand> Commands;
getCommands(CommandsRefI->getValue(), Commands);
return Commands;
@@ -214,15 +235,8 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
std::vector<std::string>
JSONCompilationDatabase::getAllFiles() const {
std::vector<std::string> Result;
-
- llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefI = IndexByFile.begin();
- const llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefEnd = IndexByFile.end();
- for (; CommandsRefI != CommandsRefEnd; ++CommandsRefI) {
- Result.push_back(CommandsRefI->first().str());
- }
-
+ for (const auto &CommandRef : IndexByFile)
+ Result.push_back(CommandRef.first().str());
return Result;
}
@@ -237,28 +251,26 @@ static std::vector<std::string>
nodeToCommandLine(JSONCommandLineSyntax Syntax,
const std::vector<llvm::yaml::ScalarNode *> &Nodes) {
SmallString<1024> Storage;
- if (Nodes.size() == 1) {
+ if (Nodes.size() == 1)
return unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage));
- }
std::vector<std::string> Arguments;
- for (auto *Node : Nodes) {
+ for (const auto *Node : Nodes)
Arguments.push_back(Node->getValue(Storage));
- }
return Arguments;
}
void JSONCompilationDatabase::getCommands(
ArrayRef<CompileCommandRef> CommandsRef,
std::vector<CompileCommand> &Commands) const {
- for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
+ for (const auto &CommandRef : CommandsRef) {
SmallString<8> DirectoryStorage;
SmallString<32> FilenameStorage;
SmallString<32> OutputStorage;
- auto Output = std::get<3>(CommandsRef[I]);
+ auto Output = std::get<3>(CommandRef);
Commands.emplace_back(
- std::get<0>(CommandsRef[I])->getValue(DirectoryStorage),
- std::get<1>(CommandsRef[I])->getValue(FilenameStorage),
- nodeToCommandLine(Syntax, std::get<2>(CommandsRef[I])),
+ std::get<0>(CommandRef)->getValue(DirectoryStorage),
+ std::get<1>(CommandRef)->getValue(FilenameStorage),
+ nodeToCommandLine(Syntax, std::get<2>(CommandRef)),
Output ? Output->getValue(OutputStorage) : "");
}
}
@@ -274,13 +286,13 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
ErrorMessage = "Error while parsing YAML.";
return false;
}
- llvm::yaml::SequenceNode *Array = dyn_cast<llvm::yaml::SequenceNode>(Root);
+ auto *Array = dyn_cast<llvm::yaml::SequenceNode>(Root);
if (!Array) {
ErrorMessage = "Expected array.";
return false;
}
- for (auto& NextObject : *Array) {
- llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject);
+ for (auto &NextObject : *Array) {
+ auto *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject);
if (!Object) {
ErrorMessage = "Expected object.";
return false;
@@ -290,8 +302,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
llvm::yaml::ScalarNode *File = nullptr;
llvm::yaml::ScalarNode *Output = nullptr;
for (auto& NextKeyValue : *Object) {
- llvm::yaml::ScalarNode *KeyString =
- dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
if (!KeyString) {
ErrorMessage = "Expected strings as key.";
return false;
@@ -303,10 +314,8 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
ErrorMessage = "Expected value.";
return false;
}
- llvm::yaml::ScalarNode *ValueString =
- dyn_cast<llvm::yaml::ScalarNode>(Value);
- llvm::yaml::SequenceNode *SequenceString =
- dyn_cast<llvm::yaml::SequenceNode>(Value);
+ auto *ValueString = dyn_cast<llvm::yaml::ScalarNode>(Value);
+ auto *SequenceString = dyn_cast<llvm::yaml::SequenceNode>(Value);
if (KeyValue == "arguments" && !SequenceString) {
ErrorMessage = "Expected sequence as value.";
return false;
@@ -319,7 +328,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
} else if (KeyValue == "arguments") {
Command = std::vector<llvm::yaml::ScalarNode *>();
for (auto &Argument : *SequenceString) {
- auto Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument);
+ auto *Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument);
if (!Scalar) {
ErrorMessage = "Only strings are allowed in 'arguments'.";
return false;
@@ -370,6 +379,3 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
}
return true;
}
-
-} // end namespace tooling
-} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp
index e4cc6a5617b6..e8b0fdbeb662 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp
@@ -15,7 +15,7 @@
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::AtomicChange)
namespace {
-/// \brief Helper to (de)serialize an AtomicChange since we don't have direct
+/// Helper to (de)serialize an AtomicChange since we don't have direct
/// access to its data members.
/// Data members of a normalized AtomicChange can be directly mapped from/to
/// YAML string.
@@ -50,7 +50,7 @@ struct NormalizedAtomicChange {
namespace llvm {
namespace yaml {
-/// \brief Specialized MappingTraits to describe how an AtomicChange is
+/// Specialized MappingTraits to describe how an AtomicChange is
/// (de)serialized.
template <> struct MappingTraits<NormalizedAtomicChange> {
static void mapping(IO &Io, NormalizedAtomicChange &Doc) {
@@ -63,7 +63,7 @@ template <> struct MappingTraits<NormalizedAtomicChange> {
}
};
-/// \brief Specialized MappingTraits to describe how an AtomicChange is
+/// Specialized MappingTraits to describe how an AtomicChange is
/// (de)serialized.
template <> struct MappingTraits<clang::tooling::AtomicChange> {
static void mapping(IO &Io, clang::tooling::AtomicChange &Doc) {
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp
index b0847a740048..a12454cd29ef 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements the "extract" refactoring that can pull code into
+/// Implements the "extract" refactoring that can pull code into
/// new functions, methods or declare new variables.
///
//===----------------------------------------------------------------------===//
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 c8ed9dd19a8e..44ffae90efa7 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides an action to rename every symbol at a point.
+/// Provides an action to rename every symbol at a point.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
index 3bfb5bbe35e4..63f536c72a6f 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -32,7 +32,7 @@ namespace {
class NamedDeclOccurrenceFindingVisitor
: public RecursiveSymbolVisitor<NamedDeclOccurrenceFindingVisitor> {
public:
- // \brief Finds the NamedDecl at a point in the source.
+ // Finds the NamedDecl at a point in the source.
// \param Point the location in the source to search for the NamedDecl.
explicit NamedDeclOccurrenceFindingVisitor(const SourceLocation Point,
const ASTContext &Context)
@@ -58,7 +58,7 @@ public:
const NamedDecl *getNamedDecl() const { return Result; }
private:
- // \brief Determines if the Point is within Start and End.
+ // Determines if the Point is within Start and End.
bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
// FIXME: Add tests for Point == End.
return Point == Start || Point == End ||
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 40b70d8a0590..2e7c9b0cc31b 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides an action to find USR for the symbol at <offset>, as well as
+/// Provides an action to find USR for the symbol at <offset>, as well as
/// all additional USRs.
///
//===----------------------------------------------------------------------===//
@@ -55,7 +55,7 @@ const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl) {
}
namespace {
-// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
+// NamedDeclFindingConsumer should delegate finding USRs of given Decl to
// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
// Decl refers to class and adds USRs of all overridden methods if Decl refers
// to virtual method.
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 c77304a17332..fb06b91118b0 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Methods for finding all instances of a USR. Our strategy is very
+/// Methods for finding all instances of a USR. Our strategy is very
/// simple; we just compare the USR at every relevant AST node with the one
/// provided.
///
@@ -50,7 +50,7 @@ bool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) {
return SM.getFileEntryForID(FileIdAndOffset.first) != nullptr;
}
-// \brief This visitor recursively searches for all instances of a USR in a
+// This visitor recursively searches for all instances of a USR in a
// translation unit and stores them for later usage.
class USRLocFindingASTVisitor
: public RecursiveSymbolVisitor<USRLocFindingASTVisitor> {
@@ -80,7 +80,7 @@ public:
// Non-visitors:
- /// \brief Returns a set of unique symbol occurrences. Duplicate or
+ /// Returns a set of unique symbol occurrences. Duplicate or
/// overlapping occurrences are erroneous and should be reported!
SymbolOccurrences takeOccurrences() { return std::move(Occurrences); }
@@ -524,7 +524,7 @@ createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
llvm::Error Err = ReplaceChange.replace(
SM, CharSourceRange::getTokenRange(Start, End), Text);
if (Err) {
- llvm::errs() << "Faile to add replacement to AtomicChange: "
+ llvm::errs() << "Failed to add replacement to AtomicChange: "
<< llvm::toString(std::move(Err)) << "\n";
return;
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp b/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp
index eea8e39d134c..7312baf9dc77 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp
@@ -30,9 +30,11 @@ static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
StandaloneToolExecutor::StandaloneToolExecutor(
const CompilationDatabase &Compilations,
llvm::ArrayRef<std::string> SourcePaths,
+ IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
- : Tool(Compilations, SourcePaths), Context(&Results),
- ArgsAdjuster(getDefaultArgumentsAdjusters()) {
+ : Tool(Compilations, SourcePaths, std::move(PCHContainerOps),
+ std::move(BaseFS)),
+ Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
// Use self-defined default argument adjusters instead of the default
// adjusters that come with the old `ClangTool`.
Tool.clearArgumentsAdjusters();
@@ -43,7 +45,7 @@ StandaloneToolExecutor::StandaloneToolExecutor(
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: OptionsParser(std::move(Options)),
Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList(),
- PCHContainerOps),
+ std::move(PCHContainerOps)),
Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
Tool.clearArgumentsAdjusters();
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
index 4fbfa4f00473..a106154f4b28 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
@@ -1,4 +1,4 @@
-//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
+//===- Tooling.cpp - Running clang standalone tools -----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,90 +13,113 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Tooling.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/llvm-config.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
#define DEBUG_TYPE "clang-tooling"
-namespace clang {
-namespace tooling {
+using namespace clang;
+using namespace tooling;
-ToolAction::~ToolAction() {}
+ToolAction::~ToolAction() = default;
-FrontendActionFactory::~FrontendActionFactory() {}
+FrontendActionFactory::~FrontendActionFactory() = default;
// FIXME: This file contains structural duplication with other parts of the
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.
-/// \brief Builds a clang driver initialized for running clang tools.
-static clang::driver::Driver *newDriver(
- clang::DiagnosticsEngine *Diagnostics, const char *BinaryName,
+/// Builds a clang driver initialized for running clang tools.
+static driver::Driver *newDriver(
+ DiagnosticsEngine *Diagnostics, const char *BinaryName,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
- clang::driver::Driver *CompilerDriver =
- new clang::driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
- *Diagnostics, std::move(VFS));
+ driver::Driver *CompilerDriver =
+ new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
+ *Diagnostics, std::move(VFS));
CompilerDriver->setTitle("clang_based_tool");
return CompilerDriver;
}
-/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
+/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
///
-/// Returns NULL on error.
+/// Returns nullptr on error.
static const llvm::opt::ArgStringList *getCC1Arguments(
- clang::DiagnosticsEngine *Diagnostics,
- clang::driver::Compilation *Compilation) {
+ DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation) {
// We expect to get back exactly one Command job, if we didn't something
// failed. Extract that job from the Compilation.
- const clang::driver::JobList &Jobs = Compilation->getJobs();
- if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
+ const driver::JobList &Jobs = Compilation->getJobs();
+ if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
SmallString<256> error_msg;
llvm::raw_svector_ostream error_stream(error_msg);
Jobs.Print(error_stream, "; ", true);
- Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
+ Diagnostics->Report(diag::err_fe_expected_compiler_job)
<< error_stream.str();
return nullptr;
}
// The one job we find should be to invoke clang again.
- const clang::driver::Command &Cmd =
- cast<clang::driver::Command>(*Jobs.begin());
+ const auto &Cmd = cast<driver::Command>(*Jobs.begin());
if (StringRef(Cmd.getCreator().getName()) != "clang") {
- Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
+ Diagnostics->Report(diag::err_fe_expected_clang_command);
return nullptr;
}
return &Cmd.getArguments();
}
-/// \brief Returns a clang build invocation initialized from the CC1 flags.
-clang::CompilerInvocation *newInvocation(
- clang::DiagnosticsEngine *Diagnostics,
- const llvm::opt::ArgStringList &CC1Args) {
+namespace clang {
+namespace tooling {
+
+/// Returns a clang build invocation initialized from the CC1 flags.
+CompilerInvocation *newInvocation(
+ DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args) {
assert(!CC1Args.empty() && "Must at least contain the program name!");
- clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
- clang::CompilerInvocation::CreateFromArgs(
+ CompilerInvocation *Invocation = new CompilerInvocation;
+ CompilerInvocation::CreateFromArgs(
*Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
*Diagnostics);
Invocation->getFrontendOpts().DisableFree = false;
@@ -104,7 +127,7 @@ clang::CompilerInvocation *newInvocation(
return Invocation;
}
-bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code,
const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
return runToolOnCodeWithArgs(ToolAction, Code, std::vector<std::string>(),
@@ -112,6 +135,9 @@ bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
std::move(PCHContainerOps));
}
+} // namespace tooling
+} // namespace clang
+
static std::vector<std::string>
getSyntaxOnlyToolArgs(const Twine &ToolName,
const std::vector<std::string> &ExtraArgs,
@@ -124,30 +150,42 @@ getSyntaxOnlyToolArgs(const Twine &ToolName,
return Args;
}
+namespace clang {
+namespace tooling {
+
bool runToolOnCodeWithArgs(
- clang::FrontendAction *ToolAction, const Twine &Code,
+ FrontendAction *ToolAction, const Twine &Code,
+ llvm::IntrusiveRefCntPtr<vfs::FileSystem> VFS,
const std::vector<std::string> &Args, const Twine &FileName,
const Twine &ToolName,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- const FileContentMappings &VirtualMappedFiles) {
-
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
- OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+
llvm::IntrusiveRefCntPtr<FileManager> Files(
- new FileManager(FileSystemOptions(), OverlayFileSystem));
+ new FileManager(FileSystemOptions(), VFS));
ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster();
ToolInvocation Invocation(
getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
ToolAction, Files.get(),
std::move(PCHContainerOps));
+ return Invocation.run();
+}
+
+bool runToolOnCodeWithArgs(
+ FrontendAction *ToolAction, const Twine &Code,
+ const std::vector<std::string> &Args, const Twine &FileName,
+ const Twine &ToolName,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ const FileContentMappings &VirtualMappedFiles) {
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
SmallString<1024> CodeStorage;
- InMemoryFileSystem->addFile(FileNameRef, 0,
+ InMemoryFileSystem->addFile(FileName, 0,
llvm::MemoryBuffer::getMemBuffer(
Code.toNullTerminatedStringRef(CodeStorage)));
@@ -157,7 +195,8 @@ bool runToolOnCodeWithArgs(
llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second));
}
- return Invocation.run();
+ return runToolOnCodeWithArgs(ToolAction, Code, OverlayFileSystem, Args,
+ FileName, ToolName);
}
std::string getAbsolutePath(StringRef File) {
@@ -190,7 +229,7 @@ void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
TokenRef.startswith("--driver-mode="));
}
auto TargetMode =
- clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
+ driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
if (!AlreadyHasMode && TargetMode.DriverMode) {
CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
}
@@ -201,6 +240,9 @@ void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
}
}
+} // namespace tooling
+} // namespace clang
+
namespace {
class SingleFrontendActionFactory : public FrontendActionFactory {
@@ -212,22 +254,20 @@ public:
FrontendAction *create() override { return Action; }
};
-}
+} // namespace
ToolInvocation::ToolInvocation(
std::vector<std::string> CommandLine, ToolAction *Action,
FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false),
- Files(Files), PCHContainerOps(std::move(PCHContainerOps)),
- DiagConsumer(nullptr) {}
+ Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {}
ToolInvocation::ToolInvocation(
std::vector<std::string> CommandLine, FrontendAction *FAction,
FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: CommandLine(std::move(CommandLine)),
Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true),
- Files(Files), PCHContainerOps(std::move(PCHContainerOps)),
- DiagConsumer(nullptr) {}
+ Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {}
ToolInvocation::~ToolInvocation() {
if (OwnsAction)
@@ -254,23 +294,22 @@ bool ToolInvocation::run() {
TextDiagnosticPrinter DiagnosticPrinter(
llvm::errs(), &*DiagOpts);
DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
- const std::unique_ptr<clang::driver::Driver> Driver(
+ const std::unique_ptr<driver::Driver> Driver(
newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem()));
// Since the input might only be virtual, don't check whether it exists.
Driver->setCheckInputsExist(false);
- const std::unique_ptr<clang::driver::Compilation> Compilation(
+ const std::unique_ptr<driver::Compilation> Compilation(
Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
if (!Compilation)
return false;
const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
&Diagnostics, Compilation.get());
- if (!CC1Args) {
+ if (!CC1Args)
return false;
- }
- std::unique_ptr<clang::CompilerInvocation> Invocation(
+ std::unique_ptr<CompilerInvocation> Invocation(
newInvocation(&Diagnostics, *CC1Args));
// FIXME: remove this when all users have migrated!
for (const auto &It : MappedFileContents) {
@@ -285,8 +324,8 @@ bool ToolInvocation::run() {
}
bool ToolInvocation::runInvocation(
- const char *BinaryName, clang::driver::Compilation *Compilation,
- std::shared_ptr<clang::CompilerInvocation> Invocation,
+ const char *BinaryName, driver::Compilation *Compilation,
+ std::shared_ptr<CompilerInvocation> Invocation,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
// Show the invocation, with -v.
if (Invocation->getHeaderSearchOpts().Verbose) {
@@ -304,7 +343,7 @@ bool FrontendActionFactory::runInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) {
// Create a compiler instance to handle the actual work.
- clang::CompilerInstance Compiler(std::move(PCHContainerOps));
+ CompilerInstance Compiler(std::move(PCHContainerOps));
Compiler.setInvocation(std::move(Invocation));
Compiler.setFileManager(Files);
@@ -328,20 +367,20 @@ bool FrontendActionFactory::runInvocation(
ClangTool::ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<vfs::FileSystem> BaseFS)
: Compilations(Compilations), SourcePaths(SourcePaths),
PCHContainerOps(std::move(PCHContainerOps)),
- OverlayFileSystem(new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
+ OverlayFileSystem(new vfs::OverlayFileSystem(std::move(BaseFS))),
InMemoryFileSystem(new vfs::InMemoryFileSystem),
- Files(new FileManager(FileSystemOptions(), OverlayFileSystem)),
- DiagConsumer(nullptr) {
+ Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) {
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
appendArgumentsAdjuster(getClangStripOutputAdjuster());
appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
appendArgumentsAdjuster(getClangStripDependencyFileAdjuster());
}
-ClangTool::~ClangTool() {}
+ClangTool::~ClangTool() = default;
void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
MappedFileContents.push_back(std::make_pair(FilePath, Content));
@@ -372,10 +411,14 @@ int ClangTool::run(ToolAction *Action) {
// This just needs to be some symbol in the binary.
static int StaticSymbol;
- llvm::SmallString<128> InitialDirectory;
- if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory))
+ std::string InitialDirectory;
+ if (llvm::ErrorOr<std::string> CWD =
+ OverlayFileSystem->getCurrentWorkingDirectory()) {
+ InitialDirectory = std::move(*CWD);
+ } else {
llvm::report_fatal_error("Cannot detect current path: " +
- Twine(EC.message()));
+ Twine(CWD.getError().message()));
+ }
// First insert all absolute paths into the in-memory VFS. These are global
// for all compile commands.
@@ -387,6 +430,7 @@ int ClangTool::run(ToolAction *Action) {
llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
bool ProcessingFailed = false;
+ bool FileSkipped = false;
for (const auto &SourcePath : SourcePaths) {
std::string File(getAbsolutePath(SourcePath));
@@ -400,12 +444,8 @@ int ClangTool::run(ToolAction *Action) {
std::vector<CompileCommand> CompileCommandsForFile =
Compilations.getCompileCommands(File);
if (CompileCommandsForFile.empty()) {
- // FIXME: There are two use cases here: doing a fuzzy
- // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
- // about the .cc files that were not found, and the use case where I
- // specify all files I want to run over explicitly, where this should
- // be an error. We'll want to add an option for this.
llvm::errs() << "Skipping " << File << ". Compile command not found.\n";
+ FileSkipped = true;
continue;
}
for (CompileCommand &CompileCommand : CompileCommandsForFile) {
@@ -448,7 +488,7 @@ int ClangTool::run(ToolAction *Action) {
// FIXME: We need a callback mechanism for the tool writer to output a
// customized message for each file.
- DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; });
+ LLVM_DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; });
ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
PCHContainerOps);
Invocation.setDiagnosticConsumer(DiagConsumer);
@@ -465,7 +505,7 @@ int ClangTool::run(ToolAction *Action) {
Twine(InitialDirectory) + "\n!");
}
}
- return ProcessingFailed ? 1 : 0;
+ return ProcessingFailed ? 1 : (FileSkipped ? 2 : 0);
}
namespace {
@@ -493,13 +533,17 @@ public:
return true;
}
};
-}
+
+} // namespace
int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
ASTBuilderAction Action(ASTs);
return run(&Action);
}
+namespace clang {
+namespace tooling {
+
std::unique_ptr<ASTUnit>
buildASTFromCode(const Twine &Code, const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
@@ -540,5 +584,5 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
return std::move(ASTs[0]);
}
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp b/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp
index b7179ffd6416..de2f9d7fe76e 100644
--- a/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp
+++ b/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a clang-format tool that automatically formats
+/// This file implements a clang-format tool that automatically formats
/// (fragments of) C++ code.
///
//===----------------------------------------------------------------------===//
@@ -22,7 +22,8 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/Process.h"
using namespace llvm;
using clang::tooling::Replacements;
@@ -59,17 +60,18 @@ LineRanges("lines", cl::desc("<start line>:<end line> - format a range of\n"
"Can only be used with one input file."),
cl::cat(ClangFormatCategory));
static cl::opt<std::string>
- Style("style",
- cl::desc(clang::format::StyleOptionHelpDescription),
- cl::init("file"), cl::cat(ClangFormatCategory));
+ Style("style", cl::desc(clang::format::StyleOptionHelpDescription),
+ cl::init(clang::format::DefaultFormatStyle),
+ cl::cat(ClangFormatCategory));
static cl::opt<std::string>
-FallbackStyle("fallback-style",
- cl::desc("The name of the predefined style used as a\n"
- "fallback in case clang-format is invoked with\n"
- "-style=file, but can not find the .clang-format\n"
- "file to use.\n"
- "Use -fallback-style=none to skip formatting."),
- cl::init("LLVM"), cl::cat(ClangFormatCategory));
+ FallbackStyle("fallback-style",
+ cl::desc("The name of the predefined style used as a\n"
+ "fallback in case clang-format is invoked with\n"
+ "-style=file, but can not find the .clang-format\n"
+ "file to use.\n"
+ "Use -fallback-style=none to skip formatting."),
+ cl::init(clang::format::DefaultFallbackStyle),
+ cl::cat(ClangFormatCategory));
static cl::opt<std::string>
AssumeFileName("assume-filename",
@@ -337,7 +339,7 @@ static void PrintVersion(raw_ostream &OS) {
}
int main(int argc, const char **argv) {
- llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+ llvm::InitLLVM X(argc, argv);
cl::HideUnrelatedOptions(ClangFormatCategory);
@@ -357,10 +359,27 @@ int main(int argc, const char **argv) {
}
if (DumpConfig) {
+ StringRef FileName;
+ std::unique_ptr<llvm::MemoryBuffer> Code;
+ if (FileNames.empty()) {
+ // We can't read the code to detect the language if there's no
+ // file name, so leave Code empty here.
+ FileName = AssumeFileName;
+ } else {
+ // Read in the code in case the filename alone isn't enough to
+ // detect the language.
+ ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
+ MemoryBuffer::getFileOrSTDIN(FileNames[0]);
+ if (std::error_code EC = CodeOrErr.getError()) {
+ llvm::errs() << EC.message() << "\n";
+ return 1;
+ }
+ FileName = (FileNames[0] == "-") ? AssumeFileName : FileNames[0];
+ Code = std::move(CodeOrErr.get());
+ }
llvm::Expected<clang::format::FormatStyle> FormatStyle =
- clang::format::getStyle(
- Style, FileNames.empty() ? AssumeFileName : FileNames[0],
- FallbackStyle);
+ clang::format::getStyle(Style, FileName, FallbackStyle,
+ Code ? Code->getBuffer() : "");
if (!FormatStyle) {
llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
return 1;
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp
index 1a16746d589d..ef5a191bda0a 100644
--- a/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp
@@ -16,6 +16,7 @@
#include "llvm/Option/Arg.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Config/config.h"
+#include "clang/Basic/Stack.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -26,6 +27,7 @@
#include "clang/Frontend/Utils.h"
#include "clang/FrontendTool/Utils.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
@@ -72,13 +74,6 @@ void initializePollyPasses(llvm::PassRegistry &Registry);
#endif
#ifdef CLANG_HAVE_RLIMITS
-// The amount of stack we think is "sufficient". If less than this much is
-// available, we may be unable to reach our template instantiation depth
-// limit and other similar limits.
-// FIXME: Unify this with the stack we request when spawning a thread to build
-// a module.
-static const int kSufficientStack = 8 << 20;
-
#if defined(__linux__) && defined(__PIE__)
static size_t getCurrentStackAllocation() {
// If we can't compute the current stack usage, allow for 512K of command
@@ -116,7 +111,7 @@ static size_t getCurrentStackAllocation() {
#include <alloca.h>
LLVM_ATTRIBUTE_NOINLINE
-static void ensureStackAddressSpace(int ExtraChunks = 0) {
+static void ensureStackAddressSpace() {
// Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
// relatively close to the stack (they are only guaranteed to be 128MiB
// apart). This results in crashes if we happen to heap-allocate more than
@@ -125,7 +120,7 @@ static void ensureStackAddressSpace(int ExtraChunks = 0) {
// To avoid these crashes, ensure that we have sufficient virtual memory
// pages allocated before we start running.
size_t Curr = getCurrentStackAllocation();
- const int kTargetStack = kSufficientStack - 256 * 1024;
+ const int kTargetStack = DesiredStackSize - 256 * 1024;
if (Curr < kTargetStack) {
volatile char *volatile Alloc =
static_cast<volatile char *>(alloca(kTargetStack - Curr));
@@ -145,21 +140,23 @@ static void ensureSufficientStack() {
// Increase the soft stack limit to our desired level, if necessary and
// possible.
- if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kSufficientStack) {
+ if (rlim.rlim_cur != RLIM_INFINITY &&
+ rlim.rlim_cur < rlim_t(DesiredStackSize)) {
// Try to allocate sufficient stack.
- if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= kSufficientStack)
- rlim.rlim_cur = kSufficientStack;
+ if (rlim.rlim_max == RLIM_INFINITY ||
+ rlim.rlim_max >= rlim_t(DesiredStackSize))
+ rlim.rlim_cur = DesiredStackSize;
else if (rlim.rlim_cur == rlim.rlim_max)
return;
else
rlim.rlim_cur = rlim.rlim_max;
if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||
- rlim.rlim_cur != kSufficientStack)
+ rlim.rlim_cur != DesiredStackSize)
return;
}
- // We should now have a stack of size at least kSufficientStack. Ensure
+ // We should now have a stack of size at least DesiredStackSize. Ensure
// that we can actually use that much, if necessary.
ensureStackAddressSpace();
}
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
index 191c7df7ab1e..09db014019bf 100644
--- a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -61,7 +62,7 @@ using namespace llvm::opt;
namespace {
-/// \brief Helper class for representing a single invocation of the assembler.
+/// Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
/// @name Target Options
/// @{
@@ -93,9 +94,11 @@ struct AssemblerInvocation {
std::string DwarfDebugFlags;
std::string DwarfDebugProducer;
std::string DebugCompilationDir;
+ std::map<const std::string, const std::string> DebugPrefixMap;
llvm::DebugCompressionType CompressDebugSections =
llvm::DebugCompressionType::None;
std::string MainFileName;
+ std::string SplitDwarfFile;
/// @}
/// @name Frontend Options
@@ -181,7 +184,13 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Issue errors on unknown arguments.
for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
- Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
+ auto ArgString = A->getAsString(Args);
+ std::string Nearest;
+ if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
+ Diags.Report(diag::err_drv_unknown_argument) << ArgString;
+ else
+ Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
+ << ArgString << Nearest;
Success = false;
}
@@ -225,6 +234,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
+ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
+ Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
+
// Frontend Options
if (Args.hasArg(OPT_INPUT)) {
bool First = true;
@@ -240,6 +252,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
}
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
Opts.OutputPath = Args.getLastArgValue(OPT_o);
+ Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
if (Arg *A = Args.getLastArg(OPT_filetype)) {
StringRef Name = A->getValue();
unsigned OutputType = StringSwitch<unsigned>(Name)
@@ -275,22 +288,17 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
}
static std::unique_ptr<raw_fd_ostream>
-getOutputStream(AssemblerInvocation &Opts, DiagnosticsEngine &Diags,
- bool Binary) {
- if (Opts.OutputPath.empty())
- Opts.OutputPath = "-";
-
+getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
// Make sure that the Out file gets unlinked from the disk if we get a
// SIGINT.
- if (Opts.OutputPath != "-")
- sys::RemoveFileOnSignal(Opts.OutputPath);
+ if (Path != "-")
+ sys::RemoveFileOnSignal(Path);
std::error_code EC;
auto Out = llvm::make_unique<raw_fd_ostream>(
- Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
+ Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
if (EC) {
- Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath
- << EC.message();
+ Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
return nullptr;
}
@@ -335,9 +343,15 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
- std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts, Diags, IsBinary);
+ if (Opts.OutputPath.empty())
+ Opts.OutputPath = "-";
+ std::unique_ptr<raw_fd_ostream> FDOS =
+ getOutputStream(Opts.OutputPath, Diags, IsBinary);
if (!FDOS)
return true;
+ std::unique_ptr<raw_fd_ostream> DwoOS;
+ if (!Opts.SplitDwarfFile.empty())
+ DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
@@ -367,6 +381,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
if (!Opts.DebugCompilationDir.empty())
Ctx.setCompilationDir(Opts.DebugCompilationDir);
+ if (!Opts.DebugPrefixMap.empty())
+ for (const auto &KV : Opts.DebugPrefixMap)
+ Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
if (!Opts.MainFileName.empty())
Ctx.setMainFileName(StringRef(Opts.MainFileName));
Ctx.setDwarfVersion(Opts.DwarfVersion);
@@ -392,17 +409,19 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
MCInstPrinter *IP = TheTarget->createMCInstPrinter(
llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
- MCCodeEmitter *CE = nullptr;
- MCAsmBackend *MAB = nullptr;
- if (Opts.ShowEncoding) {
- CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MCTargetOptions Options;
- MAB = TheTarget->createMCAsmBackend(*STI, *MRI, Options);
- }
+
+ std::unique_ptr<MCCodeEmitter> CE;
+ if (Opts.ShowEncoding)
+ CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
+ MCTargetOptions MCOptions;
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+
auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out);
Str.reset(TheTarget->createAsmStreamer(
Ctx, std::move(FOut), /*asmverbose*/ true,
- /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst));
+ /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
+ Opts.ShowInst));
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
Str.reset(createNullStreamer(Ctx));
} else {
@@ -413,17 +432,26 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Out = BOS.get();
}
- MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MCTargetOptions Options;
- MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, Options);
+ std::unique_ptr<MCCodeEmitter> CE(
+ TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
+ MCTargetOptions MCOptions;
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+ std::unique_ptr<MCObjectWriter> OW =
+ DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
+ : MAB->createObjectWriter(*Out);
+
Triple T(Opts.Triple);
Str.reset(TheTarget->createMCObjectStreamer(
- T, Ctx, std::unique_ptr<MCAsmBackend>(MAB), *Out, std::unique_ptr<MCCodeEmitter>(CE), *STI,
+ T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
}
+ // Assembly to object compilation should leverage assembly info.
+ Str->setUseAssemblerInfoForParsing(true);
+
bool Failed = false;
std::unique_ptr<MCAsmParser> Parser(
@@ -460,8 +488,12 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
FDOS.reset();
// Delete output file if there were errors.
- if (Failed && Opts.OutputPath != "-")
- sys::fs::remove(Opts.OutputPath);
+ if (Failed) {
+ if (Opts.OutputPath != "-")
+ sys::fs::remove(Opts.OutputPath);
+ if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
+ sys::fs::remove(Opts.SplitDwarfFile);
+ }
return Failed;
}
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1gen_reproducer_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1gen_reproducer_main.cpp
new file mode 100644
index 000000000000..a4c034d8d357
--- /dev/null
+++ b/contrib/llvm/tools/clang/tools/driver/cc1gen_reproducer_main.cpp
@@ -0,0 +1,196 @@
+//===-- cc1gen_reproducer_main.cpp - Clang reproducer generator ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1gen-reproducer functionality, which
+// generates reproducers for invocations for clang-based tools.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+namespace {
+
+struct UnsavedFileHash {
+ std::string Name;
+ std::string MD5;
+};
+
+struct ClangInvocationInfo {
+ std::string Toolchain;
+ std::string LibclangOperation;
+ std::string LibclangOptions;
+ std::vector<std::string> Arguments;
+ std::vector<std::string> InvocationArguments;
+ std::vector<UnsavedFileHash> UnsavedFileHashes;
+ bool Dump = false;
+};
+
+} // end anonymous namespace
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(UnsavedFileHash)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<UnsavedFileHash> {
+ static void mapping(IO &IO, UnsavedFileHash &Info) {
+ IO.mapRequired("name", Info.Name);
+ IO.mapRequired("md5", Info.MD5);
+ }
+};
+
+template <> struct MappingTraits<ClangInvocationInfo> {
+ static void mapping(IO &IO, ClangInvocationInfo &Info) {
+ IO.mapRequired("toolchain", Info.Toolchain);
+ IO.mapOptional("libclang.operation", Info.LibclangOperation);
+ IO.mapOptional("libclang.opts", Info.LibclangOptions);
+ IO.mapRequired("args", Info.Arguments);
+ IO.mapOptional("invocation-args", Info.InvocationArguments);
+ IO.mapOptional("unsaved_file_hashes", Info.UnsavedFileHashes);
+ }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+static std::string generateReproducerMetaInfo(const ClangInvocationInfo &Info) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ OS << '{';
+ bool NeedComma = false;
+ auto EmitKey = [&](StringRef Key) {
+ if (NeedComma)
+ OS << ", ";
+ NeedComma = true;
+ OS << '"' << Key << "\": ";
+ };
+ auto EmitStringKey = [&](StringRef Key, StringRef Value) {
+ if (Value.empty())
+ return;
+ EmitKey(Key);
+ OS << '"' << Value << '"';
+ };
+ EmitStringKey("libclang.operation", Info.LibclangOperation);
+ EmitStringKey("libclang.opts", Info.LibclangOptions);
+ if (!Info.InvocationArguments.empty()) {
+ EmitKey("invocation-args");
+ OS << '[';
+ for (const auto &Arg : llvm::enumerate(Info.InvocationArguments)) {
+ if (Arg.index())
+ OS << ',';
+ OS << '"' << Arg.value() << '"';
+ }
+ OS << ']';
+ }
+ OS << '}';
+ // FIXME: Compare unsaved file hashes and report mismatch in the reproducer.
+ if (Info.Dump)
+ llvm::outs() << "REPRODUCER METAINFO: " << OS.str() << "\n";
+ return std::move(OS.str());
+}
+
+/// Generates a reproducer for a set of arguments from a specific invocation.
+static llvm::Optional<driver::Driver::CompilationDiagnosticReport>
+generateReproducerForInvocationArguments(ArrayRef<const char *> Argv,
+ const ClangInvocationInfo &Info) {
+ using namespace driver;
+ auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Argv[0]);
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions;
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new IgnoringDiagConsumer());
+ ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
+ Driver TheDriver(Argv[0], llvm::sys::getDefaultTargetTriple(), Diags);
+ TheDriver.setTargetAndMode(TargetAndMode);
+
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Argv));
+ if (C && !C->containsError()) {
+ for (const auto &J : C->getJobs()) {
+ if (const Command *Cmd = dyn_cast<Command>(&J)) {
+ Driver::CompilationDiagnosticReport Report;
+ TheDriver.generateCompilationDiagnostics(
+ *C, *Cmd, generateReproducerMetaInfo(Info), &Report);
+ return Report;
+ }
+ }
+ }
+
+ return None;
+}
+
+std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes);
+
+static void printReproducerInformation(
+ llvm::raw_ostream &OS, const ClangInvocationInfo &Info,
+ const driver::Driver::CompilationDiagnosticReport &Report) {
+ OS << "REPRODUCER:\n";
+ OS << "{\n";
+ OS << R"("files":[)";
+ for (const auto &File : llvm::enumerate(Report.TemporaryFiles)) {
+ if (File.index())
+ OS << ',';
+ OS << '"' << File.value() << '"';
+ }
+ OS << "]\n}\n";
+}
+
+int cc1gen_reproducer_main(ArrayRef<const char *> Argv, const char *Argv0,
+ void *MainAddr) {
+ if (Argv.size() < 1) {
+ llvm::errs() << "error: missing invocation file\n";
+ return 1;
+ }
+ // Parse the invocation descriptor.
+ StringRef Input = Argv[0];
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+ llvm::MemoryBuffer::getFile(Input);
+ if (!Buffer) {
+ llvm::errs() << "error: failed to read " << Input << ": "
+ << Buffer.getError().message() << "\n";
+ return 1;
+ }
+ llvm::yaml::Input YAML(Buffer.get()->getBuffer());
+ ClangInvocationInfo InvocationInfo;
+ YAML >> InvocationInfo;
+ if (Argv.size() > 1 && Argv[1] == StringRef("-v"))
+ InvocationInfo.Dump = true;
+
+ // Create an invocation that will produce the reproducer.
+ std::vector<const char *> DriverArgs;
+ for (const auto &Arg : InvocationInfo.Arguments)
+ DriverArgs.push_back(Arg.c_str());
+ std::string Path = GetExecutablePath(Argv0, /*CanonicalPrefixes=*/true);
+ DriverArgs[0] = Path.c_str();
+ llvm::Optional<driver::Driver::CompilationDiagnosticReport> Report =
+ generateReproducerForInvocationArguments(DriverArgs, InvocationInfo);
+
+ // Emit the information about the reproduce files to stdout.
+ int Result = 1;
+ if (Report) {
+ printReproducerInformation(llvm::outs(), InvocationInfo, *Report);
+ Result = 0;
+ }
+
+ // Remove the input file.
+ llvm::sys::fs::remove(Input);
+ return Result;
+}
diff --git a/contrib/llvm/tools/clang/tools/driver/driver.cpp b/contrib/llvm/tools/clang/tools/driver/driver.cpp
index 1b614accb2ce..0455ba029c65 100644
--- a/contrib/llvm/tools/clang/tools/driver/driver.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/driver.cpp
@@ -12,9 +12,9 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Driver/Driver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
@@ -26,7 +26,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
@@ -34,9 +33,8 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
@@ -205,6 +203,8 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
+extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv,
+ const char *Argv0, void *MainAddr);
static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
SmallVectorImpl<const char *> &ArgVector,
@@ -310,29 +310,22 @@ static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) {
return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
if (Tool == "as")
return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP);
+ if (Tool == "gen-reproducer")
+ return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP);
// Reject unknown tools.
- llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n";
+ llvm::errs() << "error: unknown integrated tool '" << Tool << "'. "
+ << "Valid tools include '-cc1' and '-cc1as'.\n";
return 1;
}
int main(int argc_, const char **argv_) {
- llvm::sys::PrintStackTraceOnErrorSignal(argv_[0]);
- llvm::PrettyStackTraceProgram X(argc_, argv_);
- llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ llvm::InitLLVM X(argc_, argv_);
+ SmallVector<const char *, 256> argv(argv_, argv_ + argc_);
if (llvm::sys::Process::FixupStandardFileDescriptors())
return 1;
- SmallVector<const char *, 256> argv;
- llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
- std::error_code EC = llvm::sys::Process::GetArgumentVector(
- argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);
- if (EC) {
- llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
- return 1;
- }
-
llvm::InitializeAllTargets();
auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);
@@ -491,7 +484,7 @@ int main(int argc_, const char **argv_) {
// On Windows, abort will return an exit code of 3. In these cases,
// generate additional diagnostic information if possible.
bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70;
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
DiagnoseCrash |= CommandRes == 3;
#endif
if (DiagnoseCrash) {
@@ -507,7 +500,7 @@ int main(int argc_, const char **argv_) {
// results now. This happens in -disable-free mode.
llvm::TimerGroup::printAll(llvm::errs());
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
// Exit status should not be negative on Win32, unless abnormal termination.
// Once abnormal termiation was caught, negative status should not be
// propagated.
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
index b0e2ddd91362..6b3df825808f 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -87,6 +87,8 @@ GetFlattenedSpellings(const Record &Attr) {
} else if (Variety == "Clang") {
Ret.emplace_back("GNU", Name, "", false);
Ret.emplace_back("CXX11", Name, "clang", false);
+ if (Spelling->getValueAsBit("AllowInC"))
+ Ret.emplace_back("C2x", Name, "clang", false);
} else
Ret.push_back(FlattenedSpelling(*Spelling));
}
@@ -102,6 +104,7 @@ static std::string ReadPCHRecord(StringRef type) {
.Case("Expr *", "Record.readExpr()")
.Case("IdentifierInfo *", "Record.getIdentifierInfo()")
.Case("StringRef", "Record.readString()")
+ .Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())")
.Default("Record.readInt()");
}
@@ -120,6 +123,7 @@ static std::string WritePCHRecord(StringRef type, StringRef name) {
.Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
.Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ");\n")
.Case("StringRef", "AddString(" + std::string(name) + ");\n")
+ .Case("ParamIdx", "push_back(" + std::string(name) + ".serialize());\n")
.Default("push_back(" + std::string(name) + ");\n");
}
@@ -229,6 +233,7 @@ namespace {
virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
virtual void writePCHWrite(raw_ostream &OS) const = 0;
+ virtual std::string getIsOmitted() const { return "false"; }
virtual void writeValue(raw_ostream &OS) const = 0;
virtual void writeDump(raw_ostream &OS) const = 0;
virtual void writeDumpChildren(raw_ostream &OS) const {}
@@ -296,23 +301,29 @@ namespace {
std::string(getUpperName()) + "()");
}
+ std::string getIsOmitted() const override {
+ if (type == "IdentifierInfo *")
+ return "!get" + getUpperName().str() + "()";
+ if (type == "ParamIdx")
+ return "!get" + getUpperName().str() + "().isValid()";
+ return "false";
+ }
+
void writeValue(raw_ostream &OS) const override {
- if (type == "FunctionDecl *") {
+ if (type == "FunctionDecl *")
OS << "\" << get" << getUpperName()
<< "()->getNameInfo().getAsString() << \"";
- } else if (type == "IdentifierInfo *") {
- OS << "\";\n";
- if (isOptional())
- OS << " if (get" << getUpperName() << "()) ";
- else
- OS << " ";
- OS << "OS << get" << getUpperName() << "()->getName();\n";
- OS << " OS << \"";
- } else if (type == "TypeSourceInfo *") {
+ else if (type == "IdentifierInfo *")
+ // Some non-optional (comma required) identifier arguments can be the
+ // empty string but are then recorded as a nullptr.
+ OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName()
+ << "()->getName() : \"\") << \"";
+ else if (type == "TypeSourceInfo *")
OS << "\" << get" << getUpperName() << "().getAsString() << \"";
- } else {
+ else if (type == "ParamIdx")
+ OS << "\" << get" << getUpperName() << "().getSourceIndex() << \"";
+ else
OS << "\" << get" << getUpperName() << "() << \"";
- }
}
void writeDump(raw_ostream &OS) const override {
@@ -320,9 +331,10 @@ namespace {
OS << " OS << \" \";\n";
OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
} else if (type == "IdentifierInfo *") {
- if (isOptional())
- OS << " if (SA->get" << getUpperName() << "())\n ";
- OS << " OS << \" \" << SA->get" << getUpperName()
+ // Some non-optional (comma required) identifier arguments can be the
+ // empty string but are then recorded as a nullptr.
+ OS << " if (SA->get" << getUpperName() << "())\n"
+ << " OS << \" \" << SA->get" << getUpperName()
<< "()->getName();\n";
} else if (type == "TypeSourceInfo *") {
OS << " OS << \" \" << SA->get" << getUpperName()
@@ -332,6 +344,11 @@ namespace {
<< getUpperName() << "\";\n";
} else if (type == "int" || type == "unsigned") {
OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
+ } else if (type == "ParamIdx") {
+ if (isOptional())
+ OS << " if (SA->get" << getUpperName() << "().isValid())\n ";
+ OS << " OS << \" \" << SA->get" << getUpperName()
+ << "().getSourceIndex();\n";
} else {
llvm_unreachable("Unknown SimpleArgument type!");
}
@@ -574,12 +591,15 @@ namespace {
<< "Type());\n";
}
+ std::string getIsOmitted() const override {
+ return "!is" + getLowerName().str() + "Expr || !" + getLowerName().str()
+ + "Expr";
+ }
+
void writeValue(raw_ostream &OS) const override {
OS << "\";\n";
- // The aligned attribute argument expression is optional.
- OS << " if (is" << getLowerName() << "Expr && "
- << getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Expr->printPretty(OS, nullptr, Policy);\n";
+ OS << " " << getLowerName()
+ << "Expr->printPretty(OS, nullptr, Policy);\n";
OS << " OS << \"";
}
@@ -606,6 +626,10 @@ namespace {
virtual void writeValueImpl(raw_ostream &OS) const {
OS << " OS << Val;\n";
}
+ // Assumed to receive a parameter: raw_ostream OS.
+ virtual void writeDumpImpl(raw_ostream &OS) const {
+ OS << " OS << \" \" << Val;\n";
+ }
public:
VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
@@ -732,7 +756,22 @@ namespace {
void writeDump(raw_ostream &OS) const override {
OS << " for (const auto &Val : SA->" << RangeName << "())\n";
- OS << " OS << \" \" << Val;\n";
+ writeDumpImpl(OS);
+ }
+ };
+
+ class VariadicParamIdxArgument : public VariadicArgument {
+ public:
+ VariadicParamIdxArgument(const Record &Arg, StringRef Attr)
+ : VariadicArgument(Arg, Attr, "ParamIdx") {}
+
+ public:
+ void writeValueImpl(raw_ostream &OS) const override {
+ OS << " OS << Val.getSourceIndex();\n";
+ }
+
+ void writeDumpImpl(raw_ostream &OS) const override {
+ OS << " OS << \" \" << Val.getSourceIndex();\n";
}
};
@@ -1134,6 +1173,13 @@ namespace {
}
};
+ class VariadicIdentifierArgument : public VariadicArgument {
+ public:
+ VariadicIdentifierArgument(const Record &Arg, StringRef Attr)
+ : VariadicArgument(Arg, Attr, "IdentifierInfo *")
+ {}
+ };
+
class VariadicStringArgument : public VariadicArgument {
public:
VariadicStringArgument(const Record &Arg, StringRef Attr)
@@ -1235,6 +1281,12 @@ createArgument(const Record &Arg, StringRef Attr,
Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr);
else if (ArgName == "VariadicExprArgument")
Ptr = llvm::make_unique<VariadicExprArgument>(Arg, Attr);
+ else if (ArgName == "VariadicParamIdxArgument")
+ Ptr = llvm::make_unique<VariadicParamIdxArgument>(Arg, Attr);
+ else if (ArgName == "ParamIdxArgument")
+ Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");
+ else if (ArgName == "VariadicIdentifierArgument")
+ Ptr = llvm::make_unique<VariadicIdentifierArgument>(Arg, Attr);
else if (ArgName == "VersionArgument")
Ptr = llvm::make_unique<VersionArgument>(Arg, Attr);
@@ -1366,7 +1418,7 @@ writePrettyPrintFunction(Record &R,
" OS << \"" << Prefix << Spelling;
if (Variety == "Pragma") {
- OS << " \";\n";
+ OS << "\";\n";
OS << " printPrettyPragma(OS, Policy);\n";
OS << " OS << \"\\n\";";
OS << " break;\n";
@@ -1374,33 +1426,83 @@ writePrettyPrintFunction(Record &R,
continue;
}
- // Fake arguments aren't part of the parsed form and should not be
- // pretty-printed.
- bool hasNonFakeArgs = llvm::any_of(
- Args, [](const std::unique_ptr<Argument> &A) { return !A->isFake(); });
-
- // FIXME: always printing the parenthesis isn't the correct behavior for
- // attributes which have optional arguments that were not provided. For
- // instance: __attribute__((aligned)) will be pretty printed as
- // __attribute__((aligned())). The logic should check whether there is only
- // a single argument, and if it is optional, whether it has been provided.
- if (hasNonFakeArgs)
- OS << "(";
if (Spelling == "availability") {
+ OS << "(";
writeAvailabilityValue(OS);
+ OS << ")";
} else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") {
- writeDeprecatedAttrValue(OS, Variety);
+ OS << "(";
+ writeDeprecatedAttrValue(OS, Variety);
+ OS << ")";
} else {
- unsigned index = 0;
+ // To avoid printing parentheses around an empty argument list or
+ // printing spurious commas at the end of an argument list, we need to
+ // determine where the last provided non-fake argument is.
+ unsigned NonFakeArgs = 0;
+ unsigned TrailingOptArgs = 0;
+ bool FoundNonOptArg = false;
+ for (const auto &arg : llvm::reverse(Args)) {
+ if (arg->isFake())
+ continue;
+ ++NonFakeArgs;
+ if (FoundNonOptArg)
+ continue;
+ // FIXME: arg->getIsOmitted() == "false" means we haven't implemented
+ // any way to detect whether the argument was omitted.
+ if (!arg->isOptional() || arg->getIsOmitted() == "false") {
+ FoundNonOptArg = true;
+ continue;
+ }
+ if (!TrailingOptArgs++)
+ OS << "\";\n"
+ << " unsigned TrailingOmittedArgs = 0;\n";
+ OS << " if (" << arg->getIsOmitted() << ")\n"
+ << " ++TrailingOmittedArgs;\n";
+ }
+ if (TrailingOptArgs)
+ OS << " OS << \"";
+ if (TrailingOptArgs < NonFakeArgs)
+ OS << "(";
+ else if (TrailingOptArgs)
+ OS << "\";\n"
+ << " if (TrailingOmittedArgs < " << NonFakeArgs << ")\n"
+ << " OS << \"(\";\n"
+ << " OS << \"";
+ unsigned ArgIndex = 0;
for (const auto &arg : Args) {
- if (arg->isFake()) continue;
- if (index++) OS << ", ";
+ if (arg->isFake())
+ continue;
+ if (ArgIndex) {
+ if (ArgIndex >= NonFakeArgs - TrailingOptArgs)
+ OS << "\";\n"
+ << " if (" << ArgIndex << " < " << NonFakeArgs
+ << " - TrailingOmittedArgs)\n"
+ << " OS << \", \";\n"
+ << " OS << \"";
+ else
+ OS << ", ";
+ }
+ std::string IsOmitted = arg->getIsOmitted();
+ if (arg->isOptional() && IsOmitted != "false")
+ OS << "\";\n"
+ << " if (!(" << IsOmitted << ")) {\n"
+ << " OS << \"";
arg->writeValue(OS);
+ if (arg->isOptional() && IsOmitted != "false")
+ OS << "\";\n"
+ << " }\n"
+ << " OS << \"";
+ ++ArgIndex;
}
+ if (TrailingOptArgs < NonFakeArgs)
+ OS << ")";
+ else if (TrailingOptArgs)
+ OS << "\";\n"
+ << " if (TrailingOmittedArgs < " << NonFakeArgs << ")\n"
+ << " OS << \")\";\n"
+ << " OS << \"";
}
- if (hasNonFakeArgs)
- OS << ")";
OS << Suffix + "\";\n";
OS <<
@@ -1414,7 +1516,7 @@ writePrettyPrintFunction(Record &R,
OS << "}\n\n";
}
-/// \brief Return the index of a spelling in a spelling list.
+/// Return the index of a spelling in a spelling list.
static unsigned
getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
const FlattenedSpelling &Spelling) {
@@ -1963,7 +2065,7 @@ static void forEachUniqueSpelling(const Record &Attr, Fn &&F) {
}
}
-/// \brief Emits the first-argument-is-type property for attributes.
+/// Emits the first-argument-is-type property for attributes.
static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -1985,7 +2087,7 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
}
-/// \brief Emits the parse-arguments-in-unevaluated-context property for
+/// Emits the parse-arguments-in-unevaluated-context property for
/// attributes.
static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
@@ -2013,6 +2115,34 @@ static bool isIdentifierArgument(Record *Arg) {
.Default(false);
}
+static bool isVariadicIdentifierArgument(Record *Arg) {
+ return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch<bool>(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicIdentifierArgument", true)
+ .Default(false);
+}
+
+static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records,
+ raw_ostream &OS) {
+ OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n";
+ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
+ for (const auto *A : Attrs) {
+ // Determine whether the first argument is a variadic identifier.
+ std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
+ if (Args.empty() || !isVariadicIdentifierArgument(Args[0]))
+ continue;
+
+ // All these spellings take an identifier argument.
+ forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) {
+ OS << ".Case(\"" << S.name() << "\", "
+ << "true"
+ << ")\n";
+ });
+ }
+ OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n";
+}
+
// Emits the first-argument-is-identifier property for attributes.
static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
@@ -2063,10 +2193,14 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses();
assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
std::string SuperName;
+ bool Inheritable = false;
for (const auto &Super : llvm::reverse(Supers)) {
const Record *R = Super.first;
- if (R->getName() != "TargetSpecificAttr" && SuperName.empty())
+ if (R->getName() != "TargetSpecificAttr" &&
+ R->getName() != "DeclOrTypeAttr" && SuperName.empty())
SuperName = R->getName();
+ if (R->getName() == "InheritableAttr")
+ Inheritable = true;
}
OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
@@ -2160,8 +2294,13 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << " )\n";
OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
- << ( R.getValueAsBit("LateParsed") ? "true" : "false" ) << ", "
- << ( R.getValueAsBit("DuplicatesAllowedWhileMerging") ? "true" : "false" ) << ")\n";
+ << ( R.getValueAsBit("LateParsed") ? "true" : "false" );
+ if (Inheritable) {
+ OS << ", "
+ << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"
+ : "false");
+ }
+ OS << ")\n";
for (auto const &ai : Args) {
OS << " , ";
@@ -3030,7 +3169,7 @@ static void emitArgInfo(const Record &R, raw_ostream &OS) {
}
static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
- OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
+ OS << "static bool defaultAppertainsTo(Sema &, const ParsedAttr &,";
OS << "const Decl *) {\n";
OS << " return true;\n";
OS << "}\n\n";
@@ -3166,11 +3305,16 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
// Otherwise, generate an appertainsTo check specific to this attribute which
// checks all of the given subjects against the Decl passed in. Return the
// name of that check to the caller.
+ //
+ // If D is null, that means the attribute was not applied to a declaration
+ // at all (for instance because it was applied to a type), or that the caller
+ // has determined that the check should fail (perhaps prior to the creation
+ // of the declaration).
std::string FnName = "check" + Attr.getName().str() + "AppertainsTo";
std::stringstream SS;
- SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
+ SS << "static bool " << FnName << "(Sema &S, const ParsedAttr &Attr, ";
SS << "const Decl *D) {\n";
- SS << " if (";
+ SS << " if (!D || (";
for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
// If the subject has custom code associated with it, generate a function
// for it. The function cannot be inlined into this check (yet) because it
@@ -3186,7 +3330,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
if (I + 1 != E)
SS << " && ";
}
- SS << ") {\n";
+ SS << ")) {\n";
SS << " S.Diag(Attr.getLoc(), diag::";
SS << (Warn ? "warn_attribute_wrong_decl_type_str" :
"err_attribute_wrong_decl_type_str");
@@ -3240,7 +3384,7 @@ emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport,
static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
- OS << "const AttributeList &) {\n";
+ OS << "const ParsedAttr &) {\n";
OS << " return true;\n";
OS << "}\n\n";
}
@@ -3279,7 +3423,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
if (I != CustomLangOptsSet.end())
return *I;
- OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
+ OS << "static bool " << FnName << "(Sema &S, const ParsedAttr &Attr) {\n";
OS << " if (" << Test << ")\n";
OS << " return true;\n\n";
OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
@@ -3312,7 +3456,7 @@ static std::string GenerateTargetRequirements(const Record &Attr,
// If there are other attributes which share the same parsed attribute kind,
// such as target-specific attributes with a shared spelling, collapse the
// duplicate architectures. This is required because a shared target-specific
- // attribute has only one AttributeList::Kind enumeration value, but it
+ // attribute has only one ParsedAttr::Kind enumeration value, but it
// 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")) {
@@ -3349,7 +3493,7 @@ static std::string GenerateTargetRequirements(const Record &Attr,
static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
- << "const AttributeList &Attr) {\n";
+ << "const ParsedAttr &Attr) {\n";
OS << " return UINT_MAX;\n";
OS << "}\n\n";
}
@@ -3372,7 +3516,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
std::string Name = Attr.getName().str() + "AttrSpellingMap";
- OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
+ OS << "static unsigned " << Name << "(const ParsedAttr &Attr) {\n";
OS << Enum;
OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
@@ -3422,12 +3566,14 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
// the spellings are identical, and custom parsing rules match, etc.
// We need to generate struct instances based off ParsedAttrInfo from
- // AttributeList.cpp.
+ // ParsedAttr.cpp.
SS << " { ";
emitArgInfo(*I->second, SS);
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
- SS << ", " << I->second->isSubClassOf("TypeAttr");
+ SS << ", "
+ << (I->second->isSubClassOf("TypeAttr") ||
+ I->second->isSubClassOf("DeclOrTypeAttr"));
SS << ", " << I->second->isSubClassOf("StmtAttr");
SS << ", " << IsKnownToGCC(*I->second);
SS << ", " << PragmaAttributeSupport.isAttributedSupported(*I->second);
@@ -3445,7 +3591,8 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
SS << " // AT_" << I->first << "\n";
}
- OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
+ OS << "static const ParsedAttrInfo AttrInfoMap[ParsedAttr::UnknownAttribute "
+ "+ 1] = {\n";
OS << SS.str();
OS << "};\n\n";
@@ -3473,7 +3620,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
// specific attribute, or MSP430-specific attribute. Additionally, an
// attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
// for the same semantic attribute. Ultimately, we need to map each of
- // these to a single AttributeList::Kind value, but the StringMatcher
+ // these to a single ParsedAttr::Kind value, but the StringMatcher
// class cannot handle duplicate match strings. So we generate a list of
// string to match based on the syntax, and emit multiple string matchers
// depending on the syntax used.
@@ -3520,34 +3667,34 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Spelling += RawSpelling;
if (SemaHandler)
- Matches->push_back(StringMatcher::StringPair(Spelling,
- "return AttributeList::AT_" + AttrName + ";"));
+ Matches->push_back(StringMatcher::StringPair(
+ Spelling, "return ParsedAttr::AT_" + AttrName + ";"));
else
- Matches->push_back(StringMatcher::StringPair(Spelling,
- "return AttributeList::IgnoredAttribute;"));
+ Matches->push_back(StringMatcher::StringPair(
+ Spelling, "return ParsedAttr::IgnoredAttribute;"));
}
}
}
-
- OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
- OS << "AttributeList::Syntax Syntax) {\n";
- OS << " if (AttributeList::AS_GNU == Syntax) {\n";
+
+ OS << "static ParsedAttr::Kind getAttrKind(StringRef Name, ";
+ OS << "ParsedAttr::Syntax Syntax) {\n";
+ OS << " if (ParsedAttr::AS_GNU == Syntax) {\n";
StringMatcher("Name", GNU, OS).Emit();
- OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
+ OS << " } else if (ParsedAttr::AS_Declspec == Syntax) {\n";
StringMatcher("Name", Declspec, OS).Emit();
- OS << " } else if (AttributeList::AS_Microsoft == Syntax) {\n";
+ OS << " } else if (ParsedAttr::AS_Microsoft == Syntax) {\n";
StringMatcher("Name", Microsoft, OS).Emit();
- OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
+ OS << " } else if (ParsedAttr::AS_CXX11 == Syntax) {\n";
StringMatcher("Name", CXX11, OS).Emit();
- OS << " } else if (AttributeList::AS_C2x == Syntax) {\n";
+ OS << " } else if (ParsedAttr::AS_C2x == Syntax) {\n";
StringMatcher("Name", C2x, OS).Emit();
- OS << " } else if (AttributeList::AS_Keyword == Syntax || ";
- OS << "AttributeList::AS_ContextSensitiveKeyword == Syntax) {\n";
+ OS << " } else if (ParsedAttr::AS_Keyword == Syntax || ";
+ OS << "ParsedAttr::AS_ContextSensitiveKeyword == Syntax) {\n";
StringMatcher("Name", Keywords, OS).Emit();
- OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n";
+ OS << " } else if (ParsedAttr::AS_Pragma == Syntax) {\n";
StringMatcher("Name", Pragma, OS).Emit();
OS << " }\n";
- OS << " return AttributeList::UnknownAttribute;\n"
+ OS << " return ParsedAttr::UnknownAttribute;\n"
<< "}\n";
}
@@ -3592,6 +3739,7 @@ void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
emitClangAttrArgContextList(Records, OS);
emitClangAttrIdentifierArgList(Records, OS);
+ emitClangAttrVariadicIdentifierArgList(Records, OS);
emitClangAttrTypeArgList(Records, OS);
emitClangAttrLateParsedList(Records, OS);
}
@@ -3753,8 +3901,8 @@ static void WriteDocumentation(RecordKeeper &Records,
const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
const StringRef Replacement = Deprecated.getValueAsString("Replacement");
if (!Replacement.empty())
- OS << " This attribute has been superseded by ``"
- << Replacement << "``.";
+ OS << " This attribute has been superseded by ``" << Replacement
+ << "``.";
OS << "\n\n";
}
@@ -3807,9 +3955,9 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
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;
+ llvm::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
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
index bfdb268b63ba..bea97ae13289 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
@@ -22,7 +22,7 @@
using namespace llvm;
-/// \brief Convert a code point to the corresponding UTF-8 sequence represented
+/// Convert a code point to the corresponding UTF-8 sequence represented
/// as a C string literal.
///
/// \returns true on success.
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
index d9d99e0bb002..6bfb3f9f61f5 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -14,12 +14,13 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.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/STLExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringToOffsetTable.h"
@@ -154,16 +155,7 @@ static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
RHS->DiagsInGroup.front());
}
-static SMRange findSuperClassRange(const Record *R, StringRef SuperName) {
- ArrayRef<std::pair<Record *, SMRange>> Supers = R->getSuperClasses();
- auto I = std::find_if(Supers.begin(), Supers.end(),
- [&](const std::pair<Record *, SMRange> &SuperPair) {
- return SuperPair.first->getName() == SuperName;
- });
- return (I != Supers.end()) ? I->second : SMRange();
-}
-
-/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
+/// Invert the 1-[0/1] mapping of diags to group into a one to many
/// mapping of groups to diags in the group.
static void groupDiagnostics(const std::vector<Record*> &Diags,
const std::vector<Record*> &DiagGroups,
@@ -216,9 +208,9 @@ static void groupDiagnostics(const std::vector<Record*> &Diags,
E = SortedGroups.end();
I != E; ++I) {
MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
- std::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
+ llvm::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
}
- std::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
+ llvm::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
// Warn about the same group being used anonymously in multiple places.
for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
@@ -236,22 +228,10 @@ static void groupDiagnostics(const std::vector<Record*> &Diags,
if (NextDiagGroup == (*I)->ExplicitDef)
continue;
- SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
- SmallString<64> Replacement;
- if (InGroupRange.isValid()) {
- Replacement += "InGroup<";
- Replacement += (*I)->ExplicitDef->getName();
- Replacement += ">";
- }
- SMFixIt FixIt(InGroupRange, Replacement);
-
- SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
+ SrcMgr.PrintMessage((*DI)->getLoc().front(),
SourceMgr::DK_Error,
Twine("group '") + Name +
- "' is referred to anonymously",
- None,
- InGroupRange.isValid() ? FixIt
- : ArrayRef<SMFixIt>());
+ "' is referred to anonymously");
SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(),
SourceMgr::DK_Note, "group defined here");
}
@@ -266,19 +246,14 @@ static void groupDiagnostics(const std::vector<Record*> &Diags,
const Record *NextDiagGroup = GroupInit->getDef();
std::string Name = NextDiagGroup->getValueAsString("GroupName");
- SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
- SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
+ SrcMgr.PrintMessage((*DI)->getLoc().front(),
SourceMgr::DK_Error,
Twine("group '") + Name +
- "' is referred to anonymously",
- InGroupRange);
+ "' is referred to anonymously");
for (++DI; DI != DE; ++DI) {
- GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
- InGroupRange = findSuperClassRange(*DI, "InGroup");
- SrcMgr.PrintMessage(GroupInit->getDef()->getLoc().front(),
- SourceMgr::DK_Note, "also referenced here",
- InGroupRange);
+ SrcMgr.PrintMessage((*DI)->getLoc().front(),
+ SourceMgr::DK_Note, "also referenced here");
}
}
}
@@ -467,6 +442,735 @@ void InferPedantic::compute(VecOrSet DiagsInPedantic,
}
}
+namespace {
+enum PieceKind {
+ MultiPieceClass,
+ TextPieceClass,
+ PlaceholderPieceClass,
+ SelectPieceClass,
+ PluralPieceClass,
+ DiffPieceClass,
+ SubstitutionPieceClass,
+};
+
+enum ModifierType {
+ MT_Unknown,
+ MT_Placeholder,
+ MT_Select,
+ MT_Sub,
+ MT_Plural,
+ MT_Diff,
+ MT_Ordinal,
+ MT_S,
+ MT_Q,
+ MT_ObjCClass,
+ MT_ObjCInstance,
+};
+
+static StringRef getModifierName(ModifierType MT) {
+ switch (MT) {
+ case MT_Select:
+ return "select";
+ case MT_Sub:
+ return "sub";
+ case MT_Diff:
+ return "diff";
+ case MT_Plural:
+ return "plural";
+ case MT_Ordinal:
+ return "ordinal";
+ case MT_S:
+ return "s";
+ case MT_Q:
+ return "q";
+ case MT_Placeholder:
+ return "";
+ case MT_ObjCClass:
+ return "objcclass";
+ case MT_ObjCInstance:
+ return "objcinstance";
+ case MT_Unknown:
+ llvm_unreachable("invalid modifier type");
+ }
+ // Unhandled case
+ llvm_unreachable("invalid modifier type");
+}
+
+struct Piece {
+ // This type and its derived classes are move-only.
+ Piece(PieceKind Kind) : ClassKind(Kind) {}
+ Piece(Piece const &O) = delete;
+ Piece &operator=(Piece const &) = delete;
+ virtual ~Piece() {}
+
+ PieceKind getPieceClass() const { return ClassKind; }
+ static bool classof(const Piece *) { return true; }
+
+private:
+ PieceKind ClassKind;
+};
+
+struct MultiPiece : Piece {
+ MultiPiece() : Piece(MultiPieceClass) {}
+ MultiPiece(std::vector<Piece *> Pieces)
+ : Piece(MultiPieceClass), Pieces(std::move(Pieces)) {}
+
+ std::vector<Piece *> Pieces;
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == MultiPieceClass;
+ }
+};
+
+struct TextPiece : Piece {
+ StringRef Role;
+ std::string Text;
+ TextPiece(StringRef Text, StringRef Role = "")
+ : Piece(TextPieceClass), Role(Role), Text(Text.str()) {}
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == TextPieceClass;
+ }
+};
+
+struct PlaceholderPiece : Piece {
+ ModifierType Kind;
+ int Index;
+ PlaceholderPiece(ModifierType Kind, int Index)
+ : Piece(PlaceholderPieceClass), Kind(Kind), Index(Index) {}
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == PlaceholderPieceClass;
+ }
+};
+
+struct SelectPiece : Piece {
+protected:
+ SelectPiece(PieceKind Kind, ModifierType ModKind)
+ : Piece(Kind), ModKind(ModKind) {}
+
+public:
+ SelectPiece(ModifierType ModKind) : SelectPiece(SelectPieceClass, ModKind) {}
+
+ ModifierType ModKind;
+ std::vector<Piece *> Options;
+ int Index;
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == SelectPieceClass ||
+ P->getPieceClass() == PluralPieceClass;
+ }
+};
+
+struct PluralPiece : SelectPiece {
+ PluralPiece() : SelectPiece(PluralPieceClass, MT_Plural) {}
+
+ std::vector<Piece *> OptionPrefixes;
+ int Index;
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == PluralPieceClass;
+ }
+};
+
+struct DiffPiece : Piece {
+ DiffPiece() : Piece(DiffPieceClass) {}
+
+ Piece *Options[2] = {};
+ int Indexes[2] = {};
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == DiffPieceClass;
+ }
+};
+
+struct SubstitutionPiece : Piece {
+ SubstitutionPiece() : Piece(SubstitutionPieceClass) {}
+
+ std::string Name;
+ std::vector<int> Modifiers;
+
+ static bool classof(const Piece *P) {
+ return P->getPieceClass() == SubstitutionPieceClass;
+ }
+};
+
+/// Diagnostic text, parsed into pieces.
+
+
+struct DiagnosticTextBuilder {
+ DiagnosticTextBuilder(DiagnosticTextBuilder const &) = delete;
+ DiagnosticTextBuilder &operator=(DiagnosticTextBuilder const &) = delete;
+
+ DiagnosticTextBuilder(RecordKeeper &Records) {
+ // Build up the list of substitution records.
+ for (auto *S : Records.getAllDerivedDefinitions("TextSubstitution")) {
+ EvaluatingRecordGuard Guard(&EvaluatingRecord, S);
+ Substitutions.try_emplace(
+ S->getName(), DiagText(*this, S->getValueAsString("Substitution")));
+ }
+
+ // Check that no diagnostic definitions have the same name as a
+ // substitution.
+ for (Record *Diag : Records.getAllDerivedDefinitions("Diagnostic")) {
+ StringRef Name = Diag->getName();
+ if (Substitutions.count(Name))
+ llvm::PrintFatalError(
+ Diag->getLoc(),
+ "Diagnostic '" + Name +
+ "' has same name as TextSubstitution definition");
+ }
+ }
+
+ std::vector<std::string> buildForDocumentation(StringRef Role,
+ const Record *R);
+ std::string buildForDefinition(const Record *R);
+
+ Piece *getSubstitution(SubstitutionPiece *S) const {
+ auto It = Substitutions.find(S->Name);
+ if (It == Substitutions.end())
+ PrintFatalError("Failed to find substitution with name: " + S->Name);
+ return It->second.Root;
+ }
+
+ LLVM_ATTRIBUTE_NORETURN void PrintFatalError(llvm::Twine const &Msg) const {
+ assert(EvaluatingRecord && "not evaluating a record?");
+ llvm::PrintFatalError(EvaluatingRecord->getLoc(), Msg);
+ }
+
+private:
+ struct DiagText {
+ DiagnosticTextBuilder &Builder;
+ std::vector<Piece *> AllocatedPieces;
+ Piece *Root = nullptr;
+
+ template <class T, class... Args> T *New(Args &&... args) {
+ static_assert(std::is_base_of<Piece, T>::value, "must be piece");
+ T *Mem = new T(std::forward<Args>(args)...);
+ AllocatedPieces.push_back(Mem);
+ return Mem;
+ }
+
+ DiagText(DiagnosticTextBuilder &Builder, StringRef Text)
+ : Builder(Builder), Root(parseDiagText(Text)) {}
+
+ Piece *parseDiagText(StringRef &Text, bool Nested = false);
+ int parseModifier(StringRef &) const;
+
+ public:
+ DiagText(DiagText &&O) noexcept
+ : Builder(O.Builder), AllocatedPieces(std::move(O.AllocatedPieces)),
+ Root(O.Root) {
+ O.Root = nullptr;
+ }
+
+ ~DiagText() {
+ for (Piece *P : AllocatedPieces)
+ delete P;
+ }
+ };
+
+private:
+ const Record *EvaluatingRecord = nullptr;
+ struct EvaluatingRecordGuard {
+ EvaluatingRecordGuard(const Record **Dest, const Record *New)
+ : Dest(Dest), Old(*Dest) {
+ *Dest = New;
+ }
+ ~EvaluatingRecordGuard() { *Dest = Old; }
+ const Record **Dest;
+ const Record *Old;
+ };
+
+ StringMap<DiagText> Substitutions;
+};
+
+template <class Derived> struct DiagTextVisitor {
+ using ModifierMappingsType = Optional<std::vector<int>>;
+
+private:
+ Derived &getDerived() { return static_cast<Derived &>(*this); }
+
+public:
+ std::vector<int>
+ getSubstitutionMappings(SubstitutionPiece *P,
+ const ModifierMappingsType &Mappings) const {
+ std::vector<int> NewMappings;
+ for (int Idx : P->Modifiers)
+ NewMappings.push_back(mapIndex(Idx, Mappings));
+ return NewMappings;
+ }
+
+ struct SubstitutionContext {
+ SubstitutionContext(DiagTextVisitor &Visitor, SubstitutionPiece *P)
+ : Visitor(Visitor) {
+ Substitution = Visitor.Builder.getSubstitution(P);
+ OldMappings = std::move(Visitor.ModifierMappings);
+ std::vector<int> NewMappings =
+ Visitor.getSubstitutionMappings(P, OldMappings);
+ Visitor.ModifierMappings = std::move(NewMappings);
+ }
+
+ ~SubstitutionContext() {
+ Visitor.ModifierMappings = std::move(OldMappings);
+ }
+
+ private:
+ DiagTextVisitor &Visitor;
+ Optional<std::vector<int>> OldMappings;
+
+ public:
+ Piece *Substitution;
+ };
+
+public:
+ DiagTextVisitor(DiagnosticTextBuilder &Builder) : Builder(Builder) {}
+
+ void Visit(Piece *P) {
+ switch (P->getPieceClass()) {
+#define CASE(T) \
+ case T##PieceClass: \
+ return getDerived().Visit##T(static_cast<T##Piece *>(P))
+ CASE(Multi);
+ CASE(Text);
+ CASE(Placeholder);
+ CASE(Select);
+ CASE(Plural);
+ CASE(Diff);
+ CASE(Substitution);
+#undef CASE
+ }
+ }
+
+ void VisitSubstitution(SubstitutionPiece *P) {
+ SubstitutionContext Guard(*this, P);
+ Visit(Guard.Substitution);
+ }
+
+ int mapIndex(int Idx,
+ ModifierMappingsType const &ModifierMappings) const {
+ if (!ModifierMappings)
+ return Idx;
+ if (ModifierMappings->size() <= static_cast<unsigned>(Idx))
+ Builder.PrintFatalError("Modifier value '" + std::to_string(Idx) +
+ "' is not valid for this mapping (has " +
+ std::to_string(ModifierMappings->size()) +
+ " mappings)");
+ return (*ModifierMappings)[Idx];
+ }
+
+ int mapIndex(int Idx) const {
+ return mapIndex(Idx, ModifierMappings);
+ }
+
+protected:
+ DiagnosticTextBuilder &Builder;
+ ModifierMappingsType ModifierMappings;
+};
+
+void escapeRST(StringRef Str, std::string &Out) {
+ for (auto K : Str) {
+ if (StringRef("`*|_[]\\").count(K))
+ Out.push_back('\\');
+ Out.push_back(K);
+ }
+}
+
+template <typename It> void padToSameLength(It Begin, It End) {
+ size_t Width = 0;
+ for (It I = Begin; I != End; ++I)
+ Width = std::max(Width, I->size());
+ for (It I = Begin; I != End; ++I)
+ (*I) += std::string(Width - I->size(), ' ');
+}
+
+template <typename It> void makeTableRows(It Begin, It End) {
+ if (Begin == End)
+ return;
+ padToSameLength(Begin, End);
+ for (It I = Begin; I != End; ++I)
+ *I = "|" + *I + "|";
+}
+
+void makeRowSeparator(std::string &Str) {
+ for (char &K : Str)
+ K = (K == '|' ? '+' : '-');
+}
+
+struct DiagTextDocPrinter : DiagTextVisitor<DiagTextDocPrinter> {
+ using BaseTy = DiagTextVisitor<DiagTextDocPrinter>;
+ DiagTextDocPrinter(DiagnosticTextBuilder &Builder,
+ std::vector<std::string> &RST)
+ : BaseTy(Builder), RST(RST) {}
+
+ void gatherNodes(
+ Piece *OrigP, const ModifierMappingsType &CurrentMappings,
+ std::vector<std::pair<Piece *, ModifierMappingsType>> &Pieces) const {
+ if (auto *Sub = dyn_cast<SubstitutionPiece>(OrigP)) {
+ ModifierMappingsType NewMappings =
+ getSubstitutionMappings(Sub, CurrentMappings);
+ return gatherNodes(Builder.getSubstitution(Sub), NewMappings, Pieces);
+ }
+ if (auto *MD = dyn_cast<MultiPiece>(OrigP)) {
+ for (Piece *Node : MD->Pieces)
+ gatherNodes(Node, CurrentMappings, Pieces);
+ return;
+ }
+ Pieces.push_back(std::make_pair(OrigP, CurrentMappings));
+ }
+
+ void VisitMulti(MultiPiece *P) {
+ if (P->Pieces.empty()) {
+ RST.push_back("");
+ return;
+ }
+
+ if (P->Pieces.size() == 1)
+ return Visit(P->Pieces[0]);
+
+ // Flatten the list of nodes, replacing any substitution pieces with the
+ // recursively flattened substituted node.
+ std::vector<std::pair<Piece *, ModifierMappingsType>> Pieces;
+ gatherNodes(P, ModifierMappings, Pieces);
+
+ std::string EmptyLinePrefix;
+ size_t Start = RST.size();
+ bool HasMultipleLines = true;
+ for (const std::pair<Piece *, ModifierMappingsType> &NodePair : Pieces) {
+ std::vector<std::string> Lines;
+ DiagTextDocPrinter Visitor{Builder, Lines};
+ Visitor.ModifierMappings = NodePair.second;
+ Visitor.Visit(NodePair.first);
+
+ if (Lines.empty())
+ continue;
+
+ // We need a vertical separator if either this or the previous piece is a
+ // multi-line piece, or this is the last piece.
+ const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : "";
+ HasMultipleLines = Lines.size() > 1;
+
+ if (Start + Lines.size() > RST.size())
+ RST.resize(Start + Lines.size(), EmptyLinePrefix);
+
+ padToSameLength(Lines.begin(), Lines.end());
+ for (size_t I = 0; I != Lines.size(); ++I)
+ RST[Start + I] += Separator + Lines[I];
+ std::string Empty(Lines[0].size(), ' ');
+ for (size_t I = Start + Lines.size(); I != RST.size(); ++I)
+ RST[I] += Separator + Empty;
+ EmptyLinePrefix += Separator + Empty;
+ }
+ for (size_t I = Start; I != RST.size(); ++I)
+ RST[I] += "|";
+ EmptyLinePrefix += "|";
+
+ makeRowSeparator(EmptyLinePrefix);
+ RST.insert(RST.begin() + Start, EmptyLinePrefix);
+ RST.insert(RST.end(), EmptyLinePrefix);
+ }
+
+ void VisitText(TextPiece *P) {
+ RST.push_back("");
+ auto &S = RST.back();
+
+ StringRef T = P->Text;
+ while (!T.empty() && T.front() == ' ') {
+ RST.back() += " |nbsp| ";
+ T = T.drop_front();
+ }
+
+ std::string Suffix;
+ while (!T.empty() && T.back() == ' ') {
+ Suffix += " |nbsp| ";
+ T = T.drop_back();
+ }
+
+ if (!T.empty()) {
+ S += ':';
+ S += P->Role;
+ S += ":`";
+ escapeRST(T, S);
+ S += '`';
+ }
+
+ S += Suffix;
+ }
+
+ void VisitPlaceholder(PlaceholderPiece *P) {
+ RST.push_back(std::string(":placeholder:`") +
+ char('A' + mapIndex(P->Index)) + "`");
+ }
+
+ void VisitSelect(SelectPiece *P) {
+ std::vector<size_t> SeparatorIndexes;
+ SeparatorIndexes.push_back(RST.size());
+ RST.emplace_back();
+ for (auto *O : P->Options) {
+ Visit(O);
+ SeparatorIndexes.push_back(RST.size());
+ RST.emplace_back();
+ }
+
+ makeTableRows(RST.begin() + SeparatorIndexes.front(),
+ RST.begin() + SeparatorIndexes.back() + 1);
+ for (size_t I : SeparatorIndexes)
+ makeRowSeparator(RST[I]);
+ }
+
+ void VisitPlural(PluralPiece *P) { VisitSelect(P); }
+
+ void VisitDiff(DiffPiece *P) { Visit(P->Options[1]); }
+
+ std::vector<std::string> &RST;
+};
+
+struct DiagTextPrinter : DiagTextVisitor<DiagTextPrinter> {
+public:
+ using BaseTy = DiagTextVisitor<DiagTextPrinter>;
+ DiagTextPrinter(DiagnosticTextBuilder &Builder, std::string &Result)
+ : BaseTy(Builder), Result(Result) {}
+
+ void VisitMulti(MultiPiece *P) {
+ for (auto *Child : P->Pieces)
+ Visit(Child);
+ }
+ void VisitText(TextPiece *P) { Result += P->Text; }
+ void VisitPlaceholder(PlaceholderPiece *P) {
+ Result += "%";
+ Result += getModifierName(P->Kind);
+ addInt(mapIndex(P->Index));
+ }
+ void VisitSelect(SelectPiece *P) {
+ Result += "%";
+ Result += getModifierName(P->ModKind);
+ if (P->ModKind == MT_Select) {
+ Result += "{";
+ for (auto *D : P->Options) {
+ Visit(D);
+ Result += '|';
+ }
+ if (!P->Options.empty())
+ Result.erase(--Result.end());
+ Result += '}';
+ }
+ addInt(mapIndex(P->Index));
+ }
+
+ void VisitPlural(PluralPiece *P) {
+ Result += "%plural{";
+ assert(P->Options.size() == P->OptionPrefixes.size());
+ for (unsigned I = 0, End = P->Options.size(); I < End; ++I) {
+ if (P->OptionPrefixes[I])
+ Visit(P->OptionPrefixes[I]);
+ Visit(P->Options[I]);
+ Result += "|";
+ }
+ if (!P->Options.empty())
+ Result.erase(--Result.end());
+ Result += '}';
+ addInt(mapIndex(P->Index));
+ }
+
+ void VisitDiff(DiffPiece *P) {
+ Result += "%diff{";
+ Visit(P->Options[0]);
+ Result += "|";
+ Visit(P->Options[1]);
+ Result += "}";
+ addInt(mapIndex(P->Indexes[0]));
+ Result += ",";
+ addInt(mapIndex(P->Indexes[1]));
+ }
+
+ void addInt(int Val) { Result += std::to_string(Val); }
+
+ std::string &Result;
+};
+
+int DiagnosticTextBuilder::DiagText::parseModifier(StringRef &Text) const {
+ if (Text.empty() || !isdigit(Text[0]))
+ Builder.PrintFatalError("expected modifier in diagnostic");
+ int Val = 0;
+ do {
+ Val *= 10;
+ Val += Text[0] - '0';
+ Text = Text.drop_front();
+ } while (!Text.empty() && isdigit(Text[0]));
+ return Val;
+}
+
+Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
+ bool Nested) {
+ std::vector<Piece *> Parsed;
+
+ while (!Text.empty()) {
+ size_t End = (size_t)-2;
+ do
+ End = Nested ? Text.find_first_of("%|}", End + 2)
+ : Text.find_first_of('%', End + 2);
+ while (End < Text.size() - 1 && Text[End] == '%' &&
+ (Text[End + 1] == '%' || Text[End + 1] == '|'));
+
+ if (End) {
+ Parsed.push_back(New<TextPiece>(Text.slice(0, End), "diagtext"));
+ Text = Text.slice(End, StringRef::npos);
+ if (Text.empty())
+ break;
+ }
+
+ if (Text[0] == '|' || Text[0] == '}')
+ break;
+
+ // Drop the '%'.
+ Text = Text.drop_front();
+
+ // Extract the (optional) modifier.
+ size_t ModLength = Text.find_first_of("0123456789{");
+ StringRef Modifier = Text.slice(0, ModLength);
+ Text = Text.slice(ModLength, StringRef::npos);
+ ModifierType ModType = llvm::StringSwitch<ModifierType>{Modifier}
+ .Case("select", MT_Select)
+ .Case("sub", MT_Sub)
+ .Case("diff", MT_Diff)
+ .Case("plural", MT_Plural)
+ .Case("s", MT_S)
+ .Case("ordinal", MT_Ordinal)
+ .Case("q", MT_Q)
+ .Case("objcclass", MT_ObjCClass)
+ .Case("objcinstance", MT_ObjCInstance)
+ .Case("", MT_Placeholder)
+ .Default(MT_Unknown);
+
+ switch (ModType) {
+ case MT_Unknown:
+ Builder.PrintFatalError("Unknown modifier type: " + Modifier);
+ case MT_Select: {
+ SelectPiece *Select = New<SelectPiece>(MT_Select);
+ do {
+ Text = Text.drop_front(); // '{' or '|'
+ Select->Options.push_back(parseDiagText(Text, true));
+ assert(!Text.empty() && "malformed %select");
+ } while (Text.front() == '|');
+ // Drop the trailing '}'.
+ Text = Text.drop_front(1);
+ Select->Index = parseModifier(Text);
+ Parsed.push_back(Select);
+ continue;
+ }
+ case MT_Plural: {
+ PluralPiece *Plural = New<PluralPiece>();
+ do {
+ Text = Text.drop_front(); // '{' or '|'
+ size_t End = Text.find_first_of(":");
+ if (End == StringRef::npos)
+ Builder.PrintFatalError("expected ':' while parsing %plural");
+ ++End;
+ assert(!Text.empty());
+ Plural->OptionPrefixes.push_back(
+ New<TextPiece>(Text.slice(0, End), "diagtext"));
+ Text = Text.slice(End, StringRef::npos);
+ Plural->Options.push_back(parseDiagText(Text, true));
+ assert(!Text.empty() && "malformed %select");
+ } while (Text.front() == '|');
+ // Drop the trailing '}'.
+ Text = Text.drop_front(1);
+ Plural->Index = parseModifier(Text);
+ Parsed.push_back(Plural);
+ continue;
+ }
+ case MT_Sub: {
+ SubstitutionPiece *Sub = New<SubstitutionPiece>();
+ Text = Text.drop_front(); // '{'
+ size_t NameSize = Text.find_first_of('}');
+ assert(NameSize != size_t(-1) && "failed to find the end of the name");
+ assert(NameSize != 0 && "empty name?");
+ Sub->Name = Text.substr(0, NameSize).str();
+ Text = Text.drop_front(NameSize);
+ Text = Text.drop_front(); // '}'
+ if (!Text.empty()) {
+ while (true) {
+ if (!isdigit(Text[0]))
+ break;
+ Sub->Modifiers.push_back(parseModifier(Text));
+ if (Text.empty() || Text[0] != ',')
+ break;
+ Text = Text.drop_front(); // ','
+ assert(!Text.empty() && isdigit(Text[0]) &&
+ "expected another modifier");
+ }
+ }
+ Parsed.push_back(Sub);
+ continue;
+ }
+ case MT_Diff: {
+ DiffPiece *Diff = New<DiffPiece>();
+ Text = Text.drop_front(); // '{'
+ Diff->Options[0] = parseDiagText(Text, true);
+ Text = Text.drop_front(); // '|'
+ Diff->Options[1] = parseDiagText(Text, true);
+
+ Text = Text.drop_front(); // '}'
+ Diff->Indexes[0] = parseModifier(Text);
+ Text = Text.drop_front(); // ','
+ Diff->Indexes[1] = parseModifier(Text);
+ Parsed.push_back(Diff);
+ continue;
+ }
+ case MT_S: {
+ SelectPiece *Select = New<SelectPiece>(ModType);
+ Select->Options.push_back(New<TextPiece>(""));
+ Select->Options.push_back(New<TextPiece>("s", "diagtext"));
+ Select->Index = parseModifier(Text);
+ Parsed.push_back(Select);
+ continue;
+ }
+ case MT_Q:
+ case MT_Placeholder:
+ case MT_ObjCClass:
+ case MT_ObjCInstance:
+ case MT_Ordinal: {
+ Parsed.push_back(New<PlaceholderPiece>(ModType, parseModifier(Text)));
+ continue;
+ }
+ }
+ }
+
+ return New<MultiPiece>(Parsed);
+}
+
+std::vector<std::string>
+DiagnosticTextBuilder::buildForDocumentation(StringRef Severity,
+ const Record *R) {
+ EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
+ StringRef Text = R->getValueAsString("Text");
+
+ DiagText D(*this, Text);
+ TextPiece *Prefix = D.New<TextPiece>(Severity, Severity);
+ Prefix->Text += ": ";
+ auto *MP = dyn_cast<MultiPiece>(D.Root);
+ if (!MP) {
+ MP = D.New<MultiPiece>();
+ MP->Pieces.push_back(D.Root);
+ D.Root = MP;
+ }
+ MP->Pieces.insert(MP->Pieces.begin(), Prefix);
+ std::vector<std::string> Result;
+ DiagTextDocPrinter{*this, Result}.Visit(D.Root);
+ return Result;
+}
+
+std::string DiagnosticTextBuilder::buildForDefinition(const Record *R) {
+ EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
+ StringRef Text = R->getValueAsString("Text");
+ DiagText D(*this, Text);
+ std::string Result;
+ DiagTextPrinter{*this, Result}.Visit(D.Root);
+ return Result;
+}
+
+} // namespace
+
//===----------------------------------------------------------------------===//
// Warning Tables (.inc file) generation.
//===----------------------------------------------------------------------===//
@@ -481,6 +1185,7 @@ static bool isRemark(const Record &Diag) {
return ClsName == "CLASS_REMARK";
}
+
/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
/// declarations of Clang diagnostics.
namespace clang {
@@ -496,8 +1201,9 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
OS << "#endif\n\n";
}
- const std::vector<Record*> &Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
+ DiagnosticTextBuilder DiagTextBuilder(Records);
+
+ std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
std::vector<Record*> DiagGroups
= Records.getAllDerivedDefinitions("DiagGroup");
@@ -546,7 +1252,7 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
// Description string.
OS << ", \"";
- OS.write_escaped(R.getValueAsString("Text")) << '"';
+ OS.write_escaped(DiagTextBuilder.buildForDefinition(&R)) << '"';
// Warning associated with the diagnostic. This is stored as an index into
// the alphabetically sorted warning table.
@@ -598,7 +1304,7 @@ static std::string getDiagCategoryEnum(llvm::StringRef name) {
return enumName.str();
}
-/// \brief Emit the array of diagnostic subgroups.
+/// Emit the array of diagnostic subgroups.
///
/// The array of diagnostic subgroups contains for each group a list of its
/// subgroups. The individual lists are separated by '-1'. Groups with no
@@ -645,7 +1351,7 @@ static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
OS << "};\n\n";
}
-/// \brief Emit the list of diagnostic arrays.
+/// Emit the list of diagnostic arrays.
///
/// This data structure is a large array that contains itself arrays of varying
/// size. Each array represents a list of diagnostics. The different arrays are
@@ -686,7 +1392,7 @@ static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
OS << "};\n\n";
}
-/// \brief Emit a list of group names.
+/// Emit a list of group names.
///
/// This creates a long string which by itself contains a list of pascal style
/// strings, which consist of a length byte directly followed by the string.
@@ -703,7 +1409,7 @@ static void emitDiagGroupNames(StringToOffsetTable &GroupNames,
OS << "};\n\n";
}
-/// \brief Emit diagnostic arrays and related data structures.
+/// Emit diagnostic arrays and related data structures.
///
/// This creates the actual diagnostic array, an array of diagnostic subgroups
/// and an array of subgroup names.
@@ -727,7 +1433,7 @@ static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
OS << "#endif // GET_DIAG_ARRAYS\n\n";
}
-/// \brief Emit diagnostic table.
+/// Emit diagnostic table.
///
/// The table is sorted by the name of the diagnostic group. Each element
/// consists of the name of the diagnostic group (given as offset in the
@@ -802,7 +1508,7 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
OS << "#endif // GET_DIAG_TABLE\n\n";
}
-/// \brief Emit the table of diagnostic categories.
+/// Emit the table of diagnostic categories.
///
/// The table has the form of macro calls that have two parameters. The
/// category's name as well as an enum that represents the category. The
@@ -889,9 +1595,10 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
Index.push_back(RecordIndexElement(R));
}
- std::sort(Index.begin(), Index.end(),
- [](const RecordIndexElement &Lhs,
- const RecordIndexElement &Rhs) { return Lhs.Name < Rhs.Name; });
+ llvm::sort(Index.begin(), Index.end(),
+ [](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) {
+ return Lhs.Name < Rhs.Name;
+ });
for (unsigned i = 0, e = Index.size(); i != e; ++i) {
const RecordIndexElement &R = Index[i];
@@ -907,261 +1614,6 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
namespace docs {
namespace {
-/// Diagnostic text, parsed into pieces.
-struct DiagText {
- struct Piece {
- // This type and its derived classes are move-only.
- Piece() {}
- Piece(Piece &&O) {}
- Piece &operator=(Piece &&O) { return *this; }
-
- virtual void print(std::vector<std::string> &RST) = 0;
- virtual ~Piece() {}
- };
- struct TextPiece : Piece {
- StringRef Role;
- std::string Text;
- void print(std::vector<std::string> &RST) override;
- };
- struct PlaceholderPiece : Piece {
- int Index;
- void print(std::vector<std::string> &RST) override;
- };
- struct SelectPiece : Piece {
- SelectPiece() {}
- SelectPiece(SelectPiece &&O) noexcept : Options(std::move(O.Options)) {}
- std::vector<DiagText> Options;
- void print(std::vector<std::string> &RST) override;
- };
-
- std::vector<std::unique_ptr<Piece>> Pieces;
-
- DiagText();
- DiagText(DiagText &&O) noexcept : Pieces(std::move(O.Pieces)) {}
-
- DiagText(StringRef Text);
- DiagText(StringRef Kind, StringRef Text);
-
- template<typename P> void add(P Piece) {
- Pieces.push_back(llvm::make_unique<P>(std::move(Piece)));
- }
- void print(std::vector<std::string> &RST);
-};
-
-DiagText parseDiagText(StringRef &Text, bool Nested = false) {
- DiagText Parsed;
-
- while (!Text.empty()) {
- size_t End = (size_t)-2;
- do
- End = Nested ? Text.find_first_of("%|}", End + 2)
- : Text.find_first_of('%', End + 2);
- while (End < Text.size() - 1 && Text[End] == '%' && Text[End + 1] == '%');
-
- if (End) {
- DiagText::TextPiece Piece;
- Piece.Role = "diagtext";
- Piece.Text = Text.slice(0, End);
- Parsed.add(std::move(Piece));
- Text = Text.slice(End, StringRef::npos);
- if (Text.empty()) break;
- }
-
- if (Text[0] == '|' || Text[0] == '}')
- break;
-
- // Drop the '%'.
- Text = Text.drop_front();
-
- // Extract the (optional) modifier.
- size_t ModLength = Text.find_first_of("0123456789{");
- StringRef Modifier = Text.slice(0, ModLength);
- Text = Text.slice(ModLength, StringRef::npos);
-
- // FIXME: Handle %ordinal here.
- if (Modifier == "select" || Modifier == "plural") {
- DiagText::SelectPiece Select;
- do {
- Text = Text.drop_front();
- if (Modifier == "plural")
- while (Text[0] != ':')
- Text = Text.drop_front();
- Select.Options.push_back(parseDiagText(Text, true));
- assert(!Text.empty() && "malformed %select");
- } while (Text.front() == '|');
- Parsed.add(std::move(Select));
-
- // Drop the trailing '}n'.
- Text = Text.drop_front(2);
- continue;
- }
-
- // For %diff, just take the second alternative (tree diagnostic). It would
- // be preferable to take the first one, and replace the $ with the suitable
- // placeholders.
- if (Modifier == "diff") {
- Text = Text.drop_front(); // '{'
- parseDiagText(Text, true);
- Text = Text.drop_front(); // '|'
-
- DiagText D = parseDiagText(Text, true);
- for (auto &P : D.Pieces)
- Parsed.Pieces.push_back(std::move(P));
-
- Text = Text.drop_front(4); // '}n,m'
- continue;
- }
-
- if (Modifier == "s") {
- Text = Text.drop_front();
- DiagText::SelectPiece Select;
- Select.Options.push_back(DiagText(""));
- Select.Options.push_back(DiagText("s"));
- Parsed.add(std::move(Select));
- continue;
- }
-
- assert(!Text.empty() && isdigit(Text[0]) && "malformed placeholder");
- DiagText::PlaceholderPiece Placeholder;
- Placeholder.Index = Text[0] - '0';
- Parsed.add(std::move(Placeholder));
- Text = Text.drop_front();
- continue;
- }
- return Parsed;
-}
-
-DiagText::DiagText() {}
-
-DiagText::DiagText(StringRef Text) : DiagText(parseDiagText(Text, false)) {}
-
-DiagText::DiagText(StringRef Kind, StringRef Text) : DiagText(parseDiagText(Text, false)) {
- TextPiece Prefix;
- Prefix.Role = Kind;
- Prefix.Text = Kind;
- Prefix.Text += ": ";
- Pieces.insert(Pieces.begin(),
- llvm::make_unique<TextPiece>(std::move(Prefix)));
-}
-
-void escapeRST(StringRef Str, std::string &Out) {
- for (auto K : Str) {
- if (StringRef("`*|_[]\\").count(K))
- Out.push_back('\\');
- Out.push_back(K);
- }
-}
-
-template<typename It> void padToSameLength(It Begin, It End) {
- size_t Width = 0;
- for (It I = Begin; I != End; ++I)
- Width = std::max(Width, I->size());
- for (It I = Begin; I != End; ++I)
- (*I) += std::string(Width - I->size(), ' ');
-}
-
-template<typename It> void makeTableRows(It Begin, It End) {
- if (Begin == End) return;
- padToSameLength(Begin, End);
- for (It I = Begin; I != End; ++I)
- *I = "|" + *I + "|";
-}
-
-void makeRowSeparator(std::string &Str) {
- for (char &K : Str)
- K = (K == '|' ? '+' : '-');
-}
-
-void DiagText::print(std::vector<std::string> &RST) {
- if (Pieces.empty()) {
- RST.push_back("");
- return;
- }
-
- if (Pieces.size() == 1)
- return Pieces[0]->print(RST);
-
- std::string EmptyLinePrefix;
- size_t Start = RST.size();
- bool HasMultipleLines = true;
- for (auto &P : Pieces) {
- std::vector<std::string> Lines;
- P->print(Lines);
- if (Lines.empty())
- continue;
-
- // We need a vertical separator if either this or the previous piece is a
- // multi-line piece, or this is the last piece.
- const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : "";
- HasMultipleLines = Lines.size() > 1;
-
- if (Start + Lines.size() > RST.size())
- RST.resize(Start + Lines.size(), EmptyLinePrefix);
-
- padToSameLength(Lines.begin(), Lines.end());
- for (size_t I = 0; I != Lines.size(); ++I)
- RST[Start + I] += Separator + Lines[I];
- std::string Empty(Lines[0].size(), ' ');
- for (size_t I = Start + Lines.size(); I != RST.size(); ++I)
- RST[I] += Separator + Empty;
- EmptyLinePrefix += Separator + Empty;
- }
- for (size_t I = Start; I != RST.size(); ++I)
- RST[I] += "|";
- EmptyLinePrefix += "|";
-
- makeRowSeparator(EmptyLinePrefix);
- RST.insert(RST.begin() + Start, EmptyLinePrefix);
- RST.insert(RST.end(), EmptyLinePrefix);
-}
-
-void DiagText::TextPiece::print(std::vector<std::string> &RST) {
- RST.push_back("");
- auto &S = RST.back();
-
- StringRef T = Text;
- while (!T.empty() && T.front() == ' ') {
- RST.back() += " |nbsp| ";
- T = T.drop_front();
- }
-
- std::string Suffix;
- while (!T.empty() && T.back() == ' ') {
- Suffix += " |nbsp| ";
- T = T.drop_back();
- }
-
- if (!T.empty()) {
- S += ':';
- S += Role;
- S += ":`";
- escapeRST(T, S);
- S += '`';
- }
-
- S += Suffix;
-}
-
-void DiagText::PlaceholderPiece::print(std::vector<std::string> &RST) {
- RST.push_back(std::string(":placeholder:`") + char('A' + Index) + "`");
-}
-
-void DiagText::SelectPiece::print(std::vector<std::string> &RST) {
- std::vector<size_t> SeparatorIndexes;
- SeparatorIndexes.push_back(RST.size());
- RST.emplace_back();
- for (auto &O : Options) {
- O.print(RST);
- SeparatorIndexes.push_back(RST.size());
- RST.emplace_back();
- }
-
- makeTableRows(RST.begin() + SeparatorIndexes.front(),
- RST.begin() + SeparatorIndexes.back() + 1);
- for (size_t I : SeparatorIndexes)
- makeRowSeparator(RST[I]);
-}
-
bool isRemarkGroup(const Record *DiagGroup,
const std::map<std::string, GroupInfo> &DiagsInGroup) {
bool AnyRemarks = false, AnyNonRemarks = false;
@@ -1206,12 +1658,13 @@ void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
}
-void writeDiagnosticText(StringRef Role, StringRef Text, raw_ostream &OS) {
+void writeDiagnosticText(DiagnosticTextBuilder &Builder, const Record *R,
+ StringRef Role, raw_ostream &OS) {
+ StringRef Text = R->getValueAsString("Text");
if (Text == "%0")
OS << "The text of this diagnostic is not controlled by Clang.\n\n";
else {
- std::vector<std::string> Out;
- DiagText(Role, Text).print(Out);
+ std::vector<std::string> Out = Builder.buildForDocumentation(Role, R);
for (auto &Line : Out)
OS << Line << "\n";
OS << "\n";
@@ -1234,11 +1687,14 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
OS << Documentation->getValueAsString("Intro") << "\n";
+ DiagnosticTextBuilder Builder(Records);
+
std::vector<Record*> Diags =
Records.getAllDerivedDefinitions("Diagnostic");
+
std::vector<Record*> DiagGroups =
Records.getAllDerivedDefinitions("DiagGroup");
- std::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
+ llvm::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
DiagGroupParentMap DGParentMap(Records);
@@ -1257,10 +1713,10 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
DiagsInPedanticSet.end());
RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
GroupsInPedanticSet.end());
- std::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
- beforeThanCompare);
- std::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
- beforeThanCompare);
+ llvm::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
+ beforeThanCompare);
+ llvm::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
+ beforeThanCompare);
PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
DiagsInPedantic.begin(),
DiagsInPedantic.end());
@@ -1309,7 +1765,7 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
OS << "Also controls ";
bool First = true;
- std::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
+ llvm::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
for (const auto &Name : GroupInfo.SubGroups) {
if (!First) OS << ", ";
OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
@@ -1325,7 +1781,8 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
Severity[0] = tolower(Severity[0]);
if (Severity == "ignored")
Severity = IsRemarkGroup ? "remark" : "warning";
- writeDiagnosticText(Severity, D->getValueAsString("Text"), OS);
+
+ writeDiagnosticText(Builder, D, Severity, OS);
}
}
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index 59314510e0ad..7fe487e54698 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -111,7 +111,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
auto DocumentationForOption = [&](Record *R) -> DocumentedOption {
auto &A = Aliases[R];
- std::sort(A.begin(), A.end(), CompareByName);
+ llvm::sort(A.begin(), A.end(), CompareByName);
return {R, std::move(A)};
};
@@ -120,7 +120,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
Documentation D;
auto &Groups = GroupsInGroup[R];
- std::sort(Groups.begin(), Groups.end(), CompareByLocation);
+ llvm::sort(Groups.begin(), Groups.end(), CompareByLocation);
for (Record *G : Groups) {
D.Groups.emplace_back();
D.Groups.back().Group = G;
@@ -129,7 +129,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
}
auto &Options = OptionsInGroup[R];
- std::sort(Options.begin(), Options.end(), CompareByName);
+ llvm::sort(Options.begin(), Options.end(), CompareByName);
for (Record *O : Options)
D.Options.push_back(DocumentationForOption(O));
@@ -245,19 +245,27 @@ void emitOptionWithArgs(StringRef Prefix, const Record *Option,
void emitOptionName(StringRef Prefix, const Record *Option, raw_ostream &OS) {
// Find the arguments to list after the option.
unsigned NumArgs = getNumArgsForKind(Option->getValueAsDef("Kind"), Option);
+ bool HasMetaVarName = !Option->isValueUnset("MetaVarName");
std::vector<std::string> Args;
- if (!Option->isValueUnset("MetaVarName"))
+ if (HasMetaVarName)
Args.push_back(Option->getValueAsString("MetaVarName"));
else if (NumArgs == 1)
Args.push_back("<arg>");
- while (Args.size() < NumArgs) {
- Args.push_back(("<arg" + Twine(Args.size() + 1) + ">").str());
- // Use '--args <arg1> <arg2>...' if any number of args are allowed.
- if (Args.size() == 2 && NumArgs == UnlimitedArgs) {
- Args.back() += "...";
- break;
+ // Fill up arguments if this option didn't provide a meta var name or it
+ // supports an unlimited number of arguments. We can't see how many arguments
+ // already are in a meta var name, so assume it has right number. This is
+ // needed for JoinedAndSeparate options so that there arent't too many
+ // arguments.
+ if (!HasMetaVarName || NumArgs == UnlimitedArgs) {
+ while (Args.size() < NumArgs) {
+ Args.push_back(("<arg" + Twine(Args.size() + 1) + ">").str());
+ // Use '--args <arg1> <arg2>...' if any number of args are allowed.
+ if (Args.size() == 2 && NumArgs == UnlimitedArgs) {
+ Args.back() += "...";
+ break;
+ }
}
}
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp
index 8f3de0b67d77..4fda8e47e4a8 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp
@@ -23,7 +23,7 @@ using namespace llvm;
// Static Analyzer Checkers Tables generation
//===----------------------------------------------------------------------===//
-/// \brief True if it is specified hidden or a parent package is specified
+/// True if it is specified hidden or a parent package is specified
/// as hidden, otherwise false.
static bool isHidden(const Record &R) {
if (R.getValueAsBit("Hidden"))
diff --git a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
index 8117d2f4a232..eca03a5892e2 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
@@ -304,7 +304,7 @@ class Intrinsic {
ListInit *Body;
/// The architectural #ifdef guard.
std::string Guard;
- /// Set if the Unvailable bit is 1. This means we don't generate a body,
+ /// Set if the Unavailable bit is 1. This means we don't generate a body,
/// just an "unavailable" attribute on a declaration.
bool IsUnavailable;
/// Is this intrinsic safe for big-endian? or does it need its arguments
@@ -552,7 +552,11 @@ public:
// run - Emit arm_neon.h.inc
void run(raw_ostream &o);
+ // runFP16 - Emit arm_fp16.h.inc
+ void runFP16(raw_ostream &o);
+
// runHeader - Emit all the __builtin prototypes used in arm_neon.h
+ // and arm_fp16.h
void runHeader(raw_ostream &o);
// runTests - Emit tests for all the Neon intrinsics.
@@ -852,6 +856,35 @@ void Type::applyModifier(char Mod) {
NumVectors = 0;
Float = true;
break;
+ case 'Y':
+ Bitwidth = ElementBitwidth = 16;
+ NumVectors = 0;
+ Float = true;
+ break;
+ case 'I':
+ Bitwidth = ElementBitwidth = 32;
+ NumVectors = 0;
+ Float = false;
+ Signed = true;
+ break;
+ case 'L':
+ Bitwidth = ElementBitwidth = 64;
+ NumVectors = 0;
+ Float = false;
+ Signed = true;
+ break;
+ case 'U':
+ Bitwidth = ElementBitwidth = 32;
+ NumVectors = 0;
+ Float = false;
+ Signed = false;
+ break;
+ case 'O':
+ Bitwidth = ElementBitwidth = 64;
+ NumVectors = 0;
+ Float = false;
+ Signed = false;
+ break;
case 'f':
Float = true;
ElementBitwidth = 32;
@@ -915,7 +948,7 @@ void Type::applyModifier(char Mod) {
break;
case 'c':
Constant = true;
- // Fall through
+ LLVM_FALLTHROUGH;
case 'p':
Pointer = true;
Bitwidth = ElementBitwidth;
@@ -962,6 +995,19 @@ void Type::applyModifier(char Mod) {
if (!AppliedQuad)
Bitwidth *= 2;
break;
+ case '7':
+ if (AppliedQuad)
+ Bitwidth /= 2;
+ ElementBitwidth = 8;
+ break;
+ case '8':
+ ElementBitwidth = 8;
+ break;
+ case '9':
+ if (!AppliedQuad)
+ Bitwidth *= 2;
+ ElementBitwidth = 8;
+ break;
default:
llvm_unreachable("Unhandled character!");
}
@@ -1010,7 +1056,7 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
}
static bool isFloatingPointProtoModifier(char Mod) {
- return Mod == 'F' || Mod == 'f' || Mod == 'H';
+ return Mod == 'F' || Mod == 'f' || Mod == 'H' || Mod == 'Y' || Mod == 'I';
}
std::string Intrinsic::getBuiltinTypeStr() {
@@ -1974,7 +2020,7 @@ void NeonEmitter::createIntrinsic(Record *R,
}
}
- std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
+ llvm::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()),
NewTypeSpecs.end());
auto &Entry = IntrinsicMap[Name];
@@ -2116,8 +2162,7 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
OS << "#endif\n\n";
}
-void
-NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
+void NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
SmallVectorImpl<Intrinsic *> &Defs) {
OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
@@ -2142,11 +2187,15 @@ NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
Record *R = Def->getRecord();
if (R->getValueAsBit("isVCVT_N")) {
// VCVT between floating- and fixed-point values takes an immediate
- // in the range [1, 32) for f32 or [1, 64) for f64.
+ // in the range [1, 32) for f32 or [1, 64) for f64 or [1, 16) for f16.
LowerBound = "1";
- if (Def->getBaseType().getElementSizeInBits() == 32)
+ if (Def->getBaseType().getElementSizeInBits() == 16 ||
+ Def->getName().find('h') != std::string::npos)
+ // VCVTh operating on FP16 intrinsics in range [1, 16)
+ UpperBound = "15";
+ else if (Def->getBaseType().getElementSizeInBits() == 32)
UpperBound = "31";
- else
+ else
UpperBound = "63";
} else if (R->getValueAsBit("isScalarShift")) {
// Right shifts have an 'r' in the name, left shifts do not. Convert
@@ -2420,12 +2469,125 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#endif /* __ARM_NEON_H */\n";
}
+/// run - Read the records in arm_fp16.td and output arm_fp16.h. arm_fp16.h
+/// is comprised of type definitions and function declarations.
+void NeonEmitter::runFP16(raw_ostream &OS) {
+ OS << "/*===---- arm_fp16.h - ARM FP16 intrinsics "
+ "------------------------------"
+ "---===\n"
+ " *\n"
+ " * Permission is hereby granted, free of charge, to any person "
+ "obtaining a copy\n"
+ " * of this software and associated documentation files (the "
+ "\"Software\"), to deal\n"
+ " * in the Software without restriction, including without limitation "
+ "the rights\n"
+ " * to use, copy, modify, merge, publish, distribute, sublicense, "
+ "and/or sell\n"
+ " * copies of the Software, and to permit persons to whom the Software "
+ "is\n"
+ " * furnished to do so, subject to the following conditions:\n"
+ " *\n"
+ " * The above copyright notice and this permission notice shall be "
+ "included in\n"
+ " * all copies or substantial portions of the Software.\n"
+ " *\n"
+ " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
+ "EXPRESS OR\n"
+ " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
+ "MERCHANTABILITY,\n"
+ " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
+ "SHALL THE\n"
+ " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
+ "OTHER\n"
+ " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
+ "ARISING FROM,\n"
+ " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
+ "DEALINGS IN\n"
+ " * THE SOFTWARE.\n"
+ " *\n"
+ " *===-----------------------------------------------------------------"
+ "---"
+ "---===\n"
+ " */\n\n";
+
+ OS << "#ifndef __ARM_FP16_H\n";
+ OS << "#define __ARM_FP16_H\n\n";
+
+ OS << "#include <stdint.h>\n\n";
+
+ OS << "typedef __fp16 float16_t;\n";
+
+ OS << "#define __ai static inline __attribute__((__always_inline__, "
+ "__nodebug__))\n\n";
+
+ SmallVector<Intrinsic *, 128> Defs;
+ std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
+ for (auto *R : RV)
+ createIntrinsic(R, Defs);
+
+ for (auto *I : Defs)
+ I->indexBody();
+
+ std::stable_sort(
+ Defs.begin(), Defs.end(),
+ [](const Intrinsic *A, const Intrinsic *B) { return *A < *B; });
+
+ // Only emit a def when its requirements have been met.
+ // FIXME: This loop could be made faster, but it's fast enough for now.
+ bool MadeProgress = true;
+ std::string InGuard;
+ while (!Defs.empty() && MadeProgress) {
+ MadeProgress = false;
+
+ for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin();
+ I != Defs.end(); /*No step*/) {
+ bool DependenciesSatisfied = true;
+ for (auto *II : (*I)->getDependencies()) {
+ if (std::find(Defs.begin(), Defs.end(), II) != Defs.end())
+ DependenciesSatisfied = false;
+ }
+ if (!DependenciesSatisfied) {
+ // Try the next one.
+ ++I;
+ continue;
+ }
+
+ // Emit #endif/#if pair if needed.
+ if ((*I)->getGuard() != InGuard) {
+ if (!InGuard.empty())
+ OS << "#endif\n";
+ InGuard = (*I)->getGuard();
+ if (!InGuard.empty())
+ OS << "#if " << InGuard << "\n";
+ }
+
+ // Actually generate the intrinsic code.
+ OS << (*I)->generate();
+
+ MadeProgress = true;
+ I = Defs.erase(I);
+ }
+ }
+ assert(Defs.empty() && "Some requirements were not satisfied!");
+ if (!InGuard.empty())
+ OS << "#endif\n";
+
+ OS << "\n";
+ OS << "#undef __ai\n\n";
+ OS << "#endif /* __ARM_FP16_H */\n";
+}
+
namespace clang {
void EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).run(OS);
}
+void EmitFP16(RecordKeeper &Records, raw_ostream &OS) {
+ NeonEmitter(Records).runFP16(OS);
+}
+
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runHeader(OS);
}
diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
index 840b330a732c..a2ba131628f1 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
@@ -52,6 +52,7 @@ enum ActionType {
GenClangCommentCommandInfo,
GenClangCommentCommandList,
GenArmNeon,
+ GenArmFP16,
GenArmNeonSema,
GenArmNeonTest,
GenAttrDocs,
@@ -139,6 +140,7 @@ cl::opt<ActionType> Action(
"Generate list of commands that are used in "
"documentation comments"),
clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"),
+ clEnumValN(GenArmFP16, "gen-arm-fp16", "Generate arm_fp16.h for clang"),
clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
"Generate ARM NEON sema support for clang"),
clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
@@ -250,6 +252,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenArmNeon:
EmitNeon(Records, OS);
break;
+ case GenArmFP16:
+ EmitFP16(Records, OS);
+ break;
case GenArmNeonSema:
EmitNeonSema(Records, OS);
break;
diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h b/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h
index 342c889ca47a..706e812ae874 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h
+++ b/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h
@@ -65,6 +65,7 @@ void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS);
void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
+void EmitFP16(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);
void EmitNeon2(RecordKeeper &Records, raw_ostream &OS);
diff --git a/contrib/llvm/tools/llc/llc.cpp b/contrib/llvm/tools/llc/llc.cpp
index a4810890f9b4..2329fb3e87c9 100644
--- a/contrib/llvm/tools/llc/llc.cpp
+++ b/contrib/llvm/tools/llc/llc.cpp
@@ -16,7 +16,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
@@ -40,14 +41,14 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <memory>
@@ -66,6 +67,11 @@ InputLanguage("x", cl::desc("Input language ('ir' or 'mir')"));
static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
+static cl::opt<std::string>
+ SplitDwarfOutputFile("split-dwarf-output",
+ cl::desc(".dwo output filename"),
+ cl::value_desc("filename"));
+
static cl::opt<unsigned>
TimeCompilations("time-compilations", cl::Hidden, cl::init(1u),
cl::value_desc("N"),
@@ -226,7 +232,7 @@ static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName,
OpenFlags |= sys::fs::F_Text;
auto FDOut = llvm::make_unique<ToolOutputFile>(OutputFilename, EC, OpenFlags);
if (EC) {
- errs() << EC.message() << '\n';
+ WithColor::error() << EC.message() << '\n';
return nullptr;
}
@@ -262,20 +268,18 @@ static void InlineAsmDiagHandler(const SMDiagnostic &SMD, void *Context,
// For testing purposes, we print the LocCookie here.
if (LocCookie)
- errs() << "note: !srcloc = " << LocCookie << "\n";
+ WithColor::note() << "!srcloc = " << LocCookie << "\n";
}
// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
// Enable debug stream buffering.
EnableDebugBuffering = true;
LLVMContext Context;
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
@@ -327,7 +331,7 @@ int main(int argc, char **argv) {
YamlFile =
llvm::make_unique<ToolOutputFile>(RemarksFilename, EC, sys::fs::F_None);
if (EC) {
- errs() << EC.message() << '\n';
+ WithColor::error(errs(), argv[0]) << EC.message() << '\n';
return 1;
}
Context.setDiagnosticsOutputFile(
@@ -336,7 +340,8 @@ int main(int argc, char **argv) {
if (InputLanguage != "" && InputLanguage != "ir" &&
InputLanguage != "mir") {
- errs() << argv[0] << "Input language must be '', 'IR' or 'MIR'\n";
+ WithColor::error(errs(), argv[0])
+ << "input language must be '', 'IR' or 'MIR'\n";
return 1;
}
@@ -359,7 +364,8 @@ static bool addPass(PassManagerBase &PM, const char *argv0,
const PassRegistry *PR = PassRegistry::getPassRegistry();
const PassInfo *PI = PR->getPassInfo(PassName);
if (!PI) {
- errs() << argv0 << ": run-pass " << PassName << " is not registered.\n";
+ WithColor::error(errs(), argv0)
+ << "run-pass " << PassName << " is not registered.\n";
return true;
}
@@ -367,7 +373,8 @@ static bool addPass(PassManagerBase &PM, const char *argv0,
if (PI->getNormalCtor())
P = PI->getNormalCtor()();
else {
- errs() << argv0 << ": cannot create pass: " << PI->getPassName() << "\n";
+ WithColor::error(errs(), argv0)
+ << "cannot create pass: " << PI->getPassName() << "\n";
return true;
}
std::string Banner = std::string("After ") + std::string(P->getPassName());
@@ -395,17 +402,9 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (MIR)
M = MIR->parseIRModule();
} else
- M = parseIRFile(InputFilename, Err, Context);
+ M = parseIRFile(InputFilename, Err, Context, false);
if (!M) {
- Err.print(argv[0], errs());
- return 1;
- }
-
- // Verify module immediately to catch problems before doInitialization() is
- // called on any passes.
- if (!NoVerify && verifyModule(*M, &errs())) {
- errs() << argv[0] << ": " << InputFilename
- << ": error: input module is broken!\n";
+ Err.print(argv[0], WithColor::error(errs(), argv[0]));
return 1;
}
@@ -425,7 +424,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
Error);
if (!TheTarget) {
- errs() << argv[0] << ": " << Error;
+ WithColor::error(errs(), argv[0]) << Error;
return 1;
}
@@ -434,7 +433,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
default:
- errs() << argv[0] << ": invalid optimization level.\n";
+ WithColor::error(errs(), argv[0]) << "invalid optimization level.\n";
return 1;
case ' ': break;
case '0': OLvl = CodeGenOpt::None; break;
@@ -473,6 +472,17 @@ static int compileModule(char **argv, LLVMContext &Context) {
GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);
if (!Out) return 1;
+ std::unique_ptr<ToolOutputFile> DwoOut;
+ if (!SplitDwarfOutputFile.empty()) {
+ std::error_code EC;
+ DwoOut = llvm::make_unique<ToolOutputFile>(SplitDwarfOutputFile, EC,
+ sys::fs::F_None);
+ if (EC) {
+ WithColor::error(errs(), argv[0]) << EC.message() << '\n';
+ return 1;
+ }
+ }
+
// Build up all of the passes that we want to do to the module.
legacy::PassManager PM;
@@ -487,14 +497,27 @@ static int compileModule(char **argv, LLVMContext &Context) {
// Add the target data from the target machine, if it exists, or the module.
M->setDataLayout(Target->createDataLayout());
+ // This needs to be done after setting datalayout since it calls verifier
+ // to check debug info whereas verifier relies on correct datalayout.
+ UpgradeDebugInfo(*M);
+
+ // Verify module immediately to catch problems before doInitialization() is
+ // called on any passes.
+ if (!NoVerify && verifyModule(*M, &errs())) {
+ std::string Prefix =
+ (Twine(argv[0]) + Twine(": ") + Twine(InputFilename)).str();
+ WithColor::error(errs(), Prefix) << "input module is broken!\n";
+ return 1;
+ }
+
// Override function attributes based on CPUStr, FeaturesStr, and command line
// flags.
setFunctionAttributes(CPUStr, FeaturesStr, *M);
if (RelaxAll.getNumOccurrences() > 0 &&
FileType != TargetMachine::CGFT_ObjectFile)
- errs() << argv[0]
- << ": warning: ignoring -mc-relax-all because filetype != obj";
+ WithColor::warning(errs(), argv[0])
+ << ": warning: ignoring -mc-relax-all because filetype != obj";
{
raw_pwrite_stream *OS = &Out->os();
@@ -518,13 +541,15 @@ static int compileModule(char **argv, LLVMContext &Context) {
// selection.
if (!RunPassNames->empty()) {
if (!MIR) {
- errs() << argv0 << ": run-pass is for .mir file only.\n";
+ WithColor::warning(errs(), argv[0])
+ << "run-pass is for .mir file only.\n";
return 1;
}
TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM);
if (TPC.hasLimitedCodeGenPipeline()) {
- errs() << argv0 << ": run-pass cannot be used with "
- << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
+ WithColor::warning(errs(), argv[0])
+ << "run-pass cannot be used with "
+ << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
return 1;
}
@@ -539,9 +564,12 @@ static int compileModule(char **argv, LLVMContext &Context) {
TPC.setInitialized();
PM.add(createPrintMIRPass(*OS));
PM.add(createFreeMachineFunctionPass());
- } else if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, MMI)) {
- errs() << argv0 << ": target does not support generation of this"
- << " file type!\n";
+ } else if (Target->addPassesToEmitFile(PM, *OS,
+ DwoOut ? &DwoOut->os() : nullptr,
+ FileType, NoVerify, MMI)) {
+ WithColor::warning(errs(), argv[0])
+ << "target does not support generation of this"
+ << " file type!\n";
return 1;
}
@@ -560,7 +588,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
// in the future.
SmallVector<char, 0> CompileTwiceBuffer;
if (CompileTwice) {
- std::unique_ptr<Module> M2(llvm::CloneModule(M.get()));
+ std::unique_ptr<Module> M2(llvm::CloneModule(*M));
PM.run(*M2);
CompileTwiceBuffer = Buffer;
Buffer.clear();
@@ -596,6 +624,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
// Declare success.
Out->keep();
+ if (DwoOut)
+ DwoOut->keep();
return 0;
}
diff --git a/contrib/llvm/tools/lld/COFF/CMakeLists.txt b/contrib/llvm/tools/lld/COFF/CMakeLists.txt
index 4610ccc880fd..bb241e788c19 100644
--- a/contrib/llvm/tools/lld/COFF/CMakeLists.txt
+++ b/contrib/llvm/tools/lld/COFF/CMakeLists.txt
@@ -18,7 +18,6 @@ add_lld_library(lldCOFF
MarkLive.cpp
MinGW.cpp
PDB.cpp
- Strings.cpp
SymbolTable.cpp
Symbols.cpp
Writer.cpp
diff --git a/contrib/llvm/tools/lld/COFF/Chunks.cpp b/contrib/llvm/tools/lld/COFF/Chunks.cpp
index 557b02654426..412ff783222b 100644
--- a/contrib/llvm/tools/lld/COFF/Chunks.cpp
+++ b/contrib/llvm/tools/lld/COFF/Chunks.cpp
@@ -31,8 +31,7 @@ namespace coff {
SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
: Chunk(SectionKind), Repl(this), Header(H), File(F),
- Relocs(File->getCOFFObj()->getRelocations(Header)),
- NumRelocs(std::distance(Relocs.begin(), Relocs.end())) {
+ Relocs(File->getCOFFObj()->getRelocations(Header)) {
// Initialize SectionName.
File->getCOFFObj()->getSectionName(Header, SectionName);
@@ -51,13 +50,21 @@ static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
static void or32(uint8_t *P, uint32_t V) { write32le(P, read32le(P) | V); }
+// Verify that given sections are appropriate targets for SECREL
+// relocations. This check is relaxed because unfortunately debug
+// sections have section-relative relocations against absolute symbols.
+static bool checkSecRel(const SectionChunk *Sec, OutputSection *OS) {
+ if (OS)
+ return true;
+ if (Sec->isCodeView())
+ return false;
+ fatal("SECREL relocation cannot be applied to absolute symbols");
+}
+
static void applySecRel(const SectionChunk *Sec, uint8_t *Off,
OutputSection *OS, uint64_t S) {
- if (!OS) {
- if (Sec->isCodeView())
- return;
- fatal("SECREL relocation cannot be applied to absolute symbols");
- }
+ if (!checkSecRel(Sec, OS))
+ return;
uint64_t SecRel = S - OS->getRVA();
if (SecRel > UINT32_MAX) {
error("overflow in SECREL relocation in section: " + Sec->getSectionName());
@@ -67,10 +74,13 @@ static void applySecRel(const SectionChunk *Sec, uint8_t *Off,
}
static void applySecIdx(uint8_t *Off, OutputSection *OS) {
- // If we have no output section, this must be an absolute symbol. Use the
- // sentinel absolute symbol section index.
- uint16_t SecIdx = OS ? OS->SectionIndex : DefinedAbsolute::OutputSectionIndex;
- add16(Off, SecIdx);
+ // Absolute symbol doesn't have section index, but section index relocation
+ // against absolute symbol should be resolved to one plus the last output
+ // section index. This is required for compatibility with MSVC.
+ if (OS)
+ add16(Off, OS->SectionIndex);
+ else
+ add16(Off, DefinedAbsolute::NumOutputSections + 1);
}
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS,
@@ -88,7 +98,8 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS,
case IMAGE_REL_AMD64_SECTION: applySecIdx(Off, OS); break;
case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, OS, S); break;
default:
- fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
+ fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +
+ toString(File));
}
}
@@ -102,7 +113,8 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS,
case IMAGE_REL_I386_SECTION: applySecIdx(Off, OS); break;
case IMAGE_REL_I386_SECREL: applySecRel(this, Off, OS, S); break;
default:
- fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
+ fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +
+ toString(File));
}
}
@@ -112,11 +124,10 @@ static void applyMOV(uint8_t *Off, uint16_t V) {
}
static uint16_t readMOV(uint8_t *Off) {
- uint16_t Opcode1 = read16le(Off);
- uint16_t Opcode2 = read16le(Off + 2);
- uint16_t Imm = (Opcode2 & 0x00ff) | ((Opcode2 >> 4) & 0x0700);
- Imm |= ((Opcode1 << 1) & 0x0800) | ((Opcode1 & 0x000f) << 12);
- return Imm;
+ uint16_t Op1 = read16le(Off);
+ uint16_t Op2 = read16le(Off + 2);
+ return (Op2 & 0x00ff) | ((Op2 >> 4) & 0x0700) | ((Op1 << 1) & 0x0800) |
+ ((Op1 & 0x000f) << 12);
}
void applyMOV32T(uint8_t *Off, uint32_t V) {
@@ -153,7 +164,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS,
uint64_t S, uint64_t P) const {
// Pointer to thumb code must have the LSB set.
uint64_t SX = S;
- if (OS && (OS->getPermissions() & IMAGE_SCN_MEM_EXECUTE))
+ if (OS && (OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE))
SX |= 1;
switch (Type) {
case IMAGE_REL_ARM_ADDR32: add32(Off, SX + Config->ImageBase); break;
@@ -165,18 +176,19 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS,
case IMAGE_REL_ARM_SECTION: applySecIdx(Off, OS); break;
case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, OS, S); break;
default:
- fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
+ fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +
+ toString(File));
}
}
// Interpret the existing immediate value as a byte offset to the
// target symbol, then update the instruction with the immediate as
// the page offset from the current instruction to the target.
-static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P) {
+static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) {
uint32_t Orig = read32le(Off);
uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC);
S += Imm;
- Imm = (S >> 12) - (P >> 12);
+ Imm = (S >> Shift) - (P >> Shift);
uint32_t ImmLo = (Imm & 0x3) << 29;
uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;
uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);
@@ -213,19 +225,70 @@ static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) {
applyArm64Imm(Off, Imm >> Size, Size);
}
+static void applySecRelLow12A(const SectionChunk *Sec, uint8_t *Off,
+ OutputSection *OS, uint64_t S) {
+ if (checkSecRel(Sec, OS))
+ applyArm64Imm(Off, (S - OS->getRVA()) & 0xfff, 0);
+}
+
+static void applySecRelHigh12A(const SectionChunk *Sec, uint8_t *Off,
+ OutputSection *OS, uint64_t S) {
+ if (!checkSecRel(Sec, OS))
+ return;
+ uint64_t SecRel = (S - OS->getRVA()) >> 12;
+ if (0xfff < SecRel) {
+ error("overflow in SECREL_HIGH12A relocation in section: " +
+ Sec->getSectionName());
+ return;
+ }
+ applyArm64Imm(Off, SecRel & 0xfff, 0);
+}
+
+static void applySecRelLdr(const SectionChunk *Sec, uint8_t *Off,
+ OutputSection *OS, uint64_t S) {
+ if (checkSecRel(Sec, OS))
+ applyArm64Ldr(Off, (S - OS->getRVA()) & 0xfff);
+}
+
+static void applyArm64Branch26(uint8_t *Off, int64_t V) {
+ if (!isInt<28>(V))
+ fatal("relocation out of range");
+ or32(Off, (V & 0x0FFFFFFC) >> 2);
+}
+
+static void applyArm64Branch19(uint8_t *Off, int64_t V) {
+ if (!isInt<21>(V))
+ fatal("relocation out of range");
+ or32(Off, (V & 0x001FFFFC) << 3);
+}
+
+static void applyArm64Branch14(uint8_t *Off, int64_t V) {
+ if (!isInt<16>(V))
+ fatal("relocation out of range");
+ or32(Off, (V & 0x0000FFFC) << 3);
+}
+
void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS,
uint64_t S, uint64_t P) const {
switch (Type) {
- case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P); break;
+ case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P, 12); break;
+ case IMAGE_REL_ARM64_REL21: applyArm64Addr(Off, S, P, 0); break;
case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break;
case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break;
- case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break;
+ case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(Off, S - P); break;
+ case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(Off, S - P); break;
+ case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(Off, S - P); break;
case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_ARM64_ADDR32NB: add32(Off, S); break;
case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break;
case IMAGE_REL_ARM64_SECREL: applySecRel(this, Off, OS, S); break;
+ case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, Off, OS, S); break;
+ case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, Off, OS, S); break;
+ case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, Off, OS, S); break;
+ case IMAGE_REL_ARM64_SECTION: applySecIdx(Off, OS); break;
default:
- fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
+ fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +
+ toString(File));
}
}
@@ -234,7 +297,8 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
return;
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> A = getContents();
- memcpy(Buf + OutputSectionOff, A.data(), A.size());
+ if (!A.empty())
+ memcpy(Buf + OutputSectionOff, A.data(), A.size());
// Apply relocations.
size_t InputSize = getSize();
@@ -350,8 +414,8 @@ bool SectionChunk::hasData() const {
return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
}
-uint32_t SectionChunk::getPermissions() const {
- return Header->Characteristics & PermMask;
+uint32_t SectionChunk::getOutputCharacteristics() const {
+ return Header->Characteristics & (PermMask | TypeMask);
}
bool SectionChunk::isCOMDAT() const {
@@ -378,6 +442,7 @@ ArrayRef<uint8_t> SectionChunk::getContents() const {
}
void SectionChunk::replace(SectionChunk *Other) {
+ Alignment = std::max(Alignment, Other->Alignment);
Other->Repl = Repl;
Other->Live = false;
}
@@ -388,7 +453,7 @@ CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
Alignment = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue()));
}
-uint32_t CommonChunk::getPermissions() const {
+uint32_t CommonChunk::getOutputCharacteristics() const {
return IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE;
}
@@ -433,7 +498,7 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const {
void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const {
int64_t Off = ImpSymbol->getRVA() & 0xfff;
memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64));
- applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA);
+ applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA, 12);
applyArm64Ldr(Buf + OutputSectionOff + 4, Off);
}
@@ -453,12 +518,14 @@ void LocalImportChunk::writeTo(uint8_t *Buf) const {
}
}
-void SEHTableChunk::writeTo(uint8_t *Buf) const {
+void RVATableChunk::writeTo(uint8_t *Buf) const {
ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff);
size_t Cnt = 0;
- for (Defined *D : Syms)
- Begin[Cnt++] = D->getRVA();
+ for (const ChunkAndOffset &CO : Syms)
+ Begin[Cnt++] = CO.InputChunk->getRVA() + CO.Offset;
std::sort(Begin, Begin + Cnt);
+ assert(std::unique(Begin, Begin + Cnt) == Begin + Cnt &&
+ "RVA tables should be de-duplicated");
}
// Windows-specific. This class represents a block in .reloc section.
@@ -531,5 +598,47 @@ uint8_t Baserel::getDefaultType() {
}
}
+std::map<uint32_t, MergeChunk *> MergeChunk::Instances;
+
+MergeChunk::MergeChunk(uint32_t Alignment)
+ : Builder(StringTableBuilder::RAW, Alignment) {
+ this->Alignment = Alignment;
+}
+
+void MergeChunk::addSection(SectionChunk *C) {
+ auto *&MC = Instances[C->Alignment];
+ if (!MC)
+ MC = make<MergeChunk>(C->Alignment);
+ MC->Sections.push_back(C);
+}
+
+void MergeChunk::finalizeContents() {
+ for (SectionChunk *C : Sections)
+ if (C->isLive())
+ Builder.add(toStringRef(C->getContents()));
+ Builder.finalize();
+
+ for (SectionChunk *C : Sections) {
+ if (!C->isLive())
+ continue;
+ size_t Off = Builder.getOffset(toStringRef(C->getContents()));
+ C->setOutputSection(Out);
+ C->setRVA(RVA + Off);
+ C->OutputSectionOff = OutputSectionOff + Off;
+ }
+}
+
+uint32_t MergeChunk::getOutputCharacteristics() const {
+ return IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA;
+}
+
+size_t MergeChunk::getSize() const {
+ return Builder.getSize();
+}
+
+void MergeChunk::writeTo(uint8_t *Buf) const {
+ Builder.write(Buf + OutputSectionOff);
+}
+
} // namespace coff
} // namespace lld
diff --git a/contrib/llvm/tools/lld/COFF/Chunks.h b/contrib/llvm/tools/lld/COFF/Chunks.h
index 381527ee6ef2..9e896531bd9a 100644
--- a/contrib/llvm/tools/lld/COFF/Chunks.h
+++ b/contrib/llvm/tools/lld/COFF/Chunks.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/COFF.h"
#include <utility>
#include <vector>
@@ -37,9 +38,11 @@ class ObjFile;
class OutputSection;
class Symbol;
-// Mask for section types (code, data, bss, disacardable, etc.)
-// and permissions (writable, readable or executable).
-const uint32_t PermMask = 0xFF0000F0;
+// Mask for permissions (discardable, writable, readable, executable, etc).
+const uint32_t PermMask = 0xFE000000;
+
+// Mask for section types (code, data, bss).
+const uint32_t TypeMask = 0x000000E0;
// A Chunk represents a chunk of data that will occupy space in the
// output (if the resolver chose that). It may or may not be backed by
@@ -60,6 +63,10 @@ public:
// before calling this function.
virtual void writeTo(uint8_t *Buf) const {}
+ // Called by the writer after an RVA is assigned, but before calling
+ // getSize().
+ virtual void finalizeContents() {}
+
// The writer sets and uses the addresses.
uint64_t getRVA() const { return RVA; }
void setRVA(uint64_t V) { RVA = V; }
@@ -70,7 +77,7 @@ public:
virtual bool hasData() const { return true; }
// Returns readable/writable/executable bits.
- virtual uint32_t getPermissions() const { return 0; }
+ virtual uint32_t getOutputCharacteristics() const { return 0; }
// Returns the section name if this is a section chunk.
// It is illegal to call this function on non-section chunks.
@@ -137,7 +144,7 @@ public:
ArrayRef<uint8_t> getContents() const;
void writeTo(uint8_t *Buf) const override;
bool hasData() const override;
- uint32_t getPermissions() const override;
+ uint32_t getOutputCharacteristics() const override;
StringRef getSectionName() const override { return SectionName; }
void getBaserels(std::vector<Baserel> *Res) override;
bool isCOMDAT() const;
@@ -208,11 +215,11 @@ public:
// The COMDAT leader symbol if this is a COMDAT chunk.
DefinedRegular *Sym = nullptr;
+ ArrayRef<coff_relocation> Relocs;
+
private:
StringRef SectionName;
std::vector<SectionChunk *> AssocChildren;
- llvm::iterator_range<const coff_relocation *> Relocs;
- size_t NumRelocs;
// Used by the garbage collector.
bool Live;
@@ -222,13 +229,40 @@ private:
uint32_t Class[2] = {0, 0};
};
+// This class is used to implement an lld-specific feature (not implemented in
+// MSVC) that minimizes the output size by finding string literals sharing tail
+// parts and merging them.
+//
+// If string tail merging is enabled and a section is identified as containing a
+// string literal, it is added to a MergeChunk with an appropriate alignment.
+// The MergeChunk then tail merges the strings using the StringTableBuilder
+// class and assigns RVAs and section offsets to each of the member chunks based
+// on the offsets assigned by the StringTableBuilder.
+class MergeChunk : public Chunk {
+public:
+ MergeChunk(uint32_t Alignment);
+ static void addSection(SectionChunk *C);
+ void finalizeContents() override;
+
+ uint32_t getOutputCharacteristics() const override;
+ StringRef getSectionName() const override { return ".rdata"; }
+ size_t getSize() const override;
+ void writeTo(uint8_t *Buf) const override;
+
+ static std::map<uint32_t, MergeChunk *> Instances;
+ std::vector<SectionChunk *> Sections;
+
+private:
+ llvm::StringTableBuilder Builder;
+};
+
// A chunk for common symbols. Common chunks don't have actual data.
class CommonChunk : public Chunk {
public:
CommonChunk(const COFFSymbolRef Sym);
size_t getSize() const override { return Sym.getValue(); }
bool hasData() const override { return false; }
- uint32_t getPermissions() const override;
+ uint32_t getOutputCharacteristics() const override;
StringRef getSectionName() const override { return ".bss"; }
private:
@@ -320,17 +354,41 @@ private:
Defined *Sym;
};
-// Windows-specific.
-// A chunk for SEH table which contains RVAs of safe exception handler
-// functions. x86-only.
-class SEHTableChunk : public Chunk {
+// Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and
+// offset into the chunk. Order does not matter as the RVA table will be sorted
+// later.
+struct ChunkAndOffset {
+ Chunk *InputChunk;
+ uint32_t Offset;
+
+ struct DenseMapInfo {
+ static ChunkAndOffset getEmptyKey() {
+ return {llvm::DenseMapInfo<Chunk *>::getEmptyKey(), 0};
+ }
+ static ChunkAndOffset getTombstoneKey() {
+ return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0};
+ }
+ static unsigned getHashValue(const ChunkAndOffset &CO) {
+ return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue(
+ {CO.InputChunk, CO.Offset});
+ }
+ static bool isEqual(const ChunkAndOffset &LHS, const ChunkAndOffset &RHS) {
+ return LHS.InputChunk == RHS.InputChunk && LHS.Offset == RHS.Offset;
+ }
+ };
+};
+
+using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;
+
+// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.
+class RVATableChunk : public Chunk {
public:
- explicit SEHTableChunk(std::set<Defined *> S) : Syms(std::move(S)) {}
+ explicit RVATableChunk(SymbolRVASet S) : Syms(std::move(S)) {}
size_t getSize() const override { return Syms.size() * 4; }
void writeTo(uint8_t *Buf) const override;
private:
- std::set<Defined *> Syms;
+ SymbolRVASet Syms;
};
// Windows-specific.
@@ -362,4 +420,10 @@ void applyBranch24T(uint8_t *Off, int32_t V);
} // namespace coff
} // namespace lld
+namespace llvm {
+template <>
+struct DenseMapInfo<lld::coff::ChunkAndOffset>
+ : lld::coff::ChunkAndOffset::DenseMapInfo {};
+}
+
#endif
diff --git a/contrib/llvm/tools/lld/COFF/Config.h b/contrib/llvm/tools/lld/COFF/Config.h
index b01689930fac..3ae50b868333 100644
--- a/contrib/llvm/tools/lld/COFF/Config.h
+++ b/contrib/llvm/tools/lld/COFF/Config.h
@@ -10,6 +10,7 @@
#ifndef LLD_COFF_CONFIG_H
#define LLD_COFF_CONFIG_H
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/CachePruning.h"
@@ -71,6 +72,12 @@ enum class DebugType {
Fixup = 0x4, /// Relocation Table
};
+enum class GuardCFLevel {
+ Off,
+ NoLongJmp, // Emit gfids but no longjmp tables
+ Full, // Enable all protections.
+};
+
// Global configuration.
struct Configuration {
enum ManifestKind { SideBySide, Embed, No };
@@ -85,13 +92,19 @@ struct Configuration {
std::string ImportName;
bool DoGC = true;
bool DoICF = true;
+ bool TailMerge;
bool Relocatable = true;
bool Force = false;
bool Debug = false;
bool DebugDwarf = false;
bool DebugGHashes = false;
+ bool DebugSymtab = false;
+ bool ShowTiming = false;
unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
+ std::vector<std::string> NatvisFiles;
+ llvm::SmallString<128> PDBAltPath;
llvm::SmallString<128> PDBPath;
+ llvm::SmallString<128> PDBSourcePath;
std::vector<llvm::StringRef> Argv;
// Symbols in this set are considered as live by the garbage collector.
@@ -110,15 +123,18 @@ struct Configuration {
bool SaveTemps = false;
+ // /guard:cf
+ GuardCFLevel GuardCF = GuardCFLevel::Off;
+
// Used for SafeSEH.
Symbol *SEHTable = nullptr;
Symbol *SEHCount = nullptr;
// Used for /opt:lldlto=N
- unsigned LTOOptLevel = 2;
+ unsigned LTOO = 2;
// Used for /opt:lldltojobs=N
- unsigned LTOJobs = 0;
+ unsigned ThinLTOJobs = 0;
// Used for /opt:lldltopartitions=N
unsigned LTOPartitions = 1;
@@ -152,6 +168,9 @@ struct Configuration {
// Used for /alternatename.
std::map<StringRef, StringRef> AlternateNames;
+ // Used for /order.
+ llvm::StringMap<int> Order;
+
// Used for /lldmap.
std::string MapFile;
@@ -164,7 +183,7 @@ struct Configuration {
uint32_t MinorImageVersion = 0;
uint32_t MajorOSVersion = 6;
uint32_t MinorOSVersion = 0;
- bool CanExitEarly = false;
+ uint32_t Timestamp = 0;
bool DynamicBase = true;
bool AllowBind = true;
bool NxCompat = true;
@@ -174,8 +193,12 @@ struct Configuration {
bool HighEntropyVA = false;
bool AppContainer = false;
bool MinGW = false;
+ bool WarnMissingOrderSymbol = true;
bool WarnLocallyDefinedImported = true;
+ bool Incremental = true;
+ bool IntegrityCheck = false;
bool KillAt = false;
+ bool Repro = false;
};
extern Configuration *Config;
diff --git a/contrib/llvm/tools/lld/COFF/DLL.cpp b/contrib/llvm/tools/lld/COFF/DLL.cpp
index 195839139670..464abe8e0894 100644
--- a/contrib/llvm/tools/lld/COFF/DLL.cpp
+++ b/contrib/llvm/tools/lld/COFF/DLL.cpp
@@ -18,8 +18,8 @@
//
//===----------------------------------------------------------------------===//
-#include "Chunks.h"
#include "DLL.h"
+#include "Chunks.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Path.h"
diff --git a/contrib/llvm/tools/lld/COFF/DLL.h b/contrib/llvm/tools/lld/COFF/DLL.h
index ad312789edf1..c5d6e7c93abf 100644
--- a/contrib/llvm/tools/lld/COFF/DLL.h
+++ b/contrib/llvm/tools/lld/COFF/DLL.h
@@ -76,6 +76,11 @@ class EdataContents {
public:
EdataContents();
std::vector<Chunk *> Chunks;
+
+ uint64_t getRVA() { return Chunks[0]->getRVA(); }
+ uint64_t getSize() {
+ return Chunks.back()->getRVA() + Chunks.back()->getSize() - getRVA();
+ }
};
} // namespace coff
diff --git a/contrib/llvm/tools/lld/COFF/Driver.cpp b/contrib/llvm/tools/lld/COFF/Driver.cpp
index d4030588e211..da7527607ffb 100644
--- a/contrib/llvm/tools/lld/COFF/Driver.cpp
+++ b/contrib/llvm/tools/lld/COFF/Driver.cpp
@@ -9,14 +9,18 @@
#include "Driver.h"
#include "Config.h"
+#include "ICF.h"
#include "InputFiles.h"
+#include "MarkLive.h"
#include "MinGW.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
+#include "lld/Common/Args.h"
#include "lld/Common/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Timer.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
@@ -35,9 +39,8 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#include <algorithm>
-#include <memory>
-
#include <future>
+#include <memory>
using namespace llvm;
using namespace llvm::object;
@@ -47,20 +50,20 @@ using llvm::sys::Process;
namespace lld {
namespace coff {
+static Timer InputFileTimer("Input File Reading", Timer::root());
+
Configuration *Config;
LinkerDriver *Driver;
bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
- errorHandler().LogName = Args[0];
+ errorHandler().LogName = sys::path::filename(Args[0]);
errorHandler().ErrorOS = &Diag;
errorHandler().ColorDiagnostics = Diag.has_colors();
errorHandler().ErrorLimitExceededMsg =
"too many errors emitted, stopping now"
- " (use /ERRORLIMIT:0 to see all errors)";
+ " (use /errorlimit:0 to see all errors)";
errorHandler().ExitEarly = CanExitEarly;
Config = make<Configuration>();
- Config->Argv = {Args.begin(), Args.end()};
- Config->CanExitEarly = CanExitEarly;
Symtab = make<SymbolTable>();
@@ -72,6 +75,9 @@ bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
exitLld(errorCount() ? 1 : 0);
freeArena();
+ ObjFile::Instances.clear();
+ ImportFile::Instances.clear();
+ BitcodeFile::Instances.clear();
return !errorCount();
}
@@ -93,7 +99,7 @@ typedef std::pair<std::unique_ptr<MemoryBuffer>, std::error_code> MBErrPair;
// Create a std::future that opens and maps a file using the best strategy for
// the host platform.
static std::future<MBErrPair> createFutureForFile(std::string Path) {
-#if LLVM_ON_WIN32
+#if _WIN32
// On Windows, file I/O is relatively slow so it is best to do this
// asynchronously.
auto Strategy = std::launch::async;
@@ -101,7 +107,9 @@ static std::future<MBErrPair> createFutureForFile(std::string Path) {
auto Strategy = std::launch::deferred;
#endif
return std::async(Strategy, [=]() {
- auto MBOrErr = MemoryBuffer::getFile(Path);
+ auto MBOrErr = MemoryBuffer::getFile(Path,
+ /*FileSize*/ -1,
+ /*RequiresNullTerminator*/ false);
if (!MBOrErr)
return MBErrPair{nullptr, MBOrErr.getError()};
return MBErrPair{std::move(*MBOrErr), std::error_code()};
@@ -120,39 +128,46 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> MB) {
void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB,
bool WholeArchive) {
+ StringRef Filename = MB->getBufferIdentifier();
+
MemoryBufferRef MBRef = takeBuffer(std::move(MB));
- FilePaths.push_back(MBRef.getBufferIdentifier());
+ FilePaths.push_back(Filename);
// File type is detected by contents, not by file extension.
switch (identify_magic(MBRef.getBuffer())) {
case file_magic::windows_resource:
Resources.push_back(MBRef);
break;
-
case file_magic::archive:
if (WholeArchive) {
std::unique_ptr<Archive> File =
- CHECK(Archive::create(MBRef),
- MBRef.getBufferIdentifier() + ": failed to parse archive");
+ CHECK(Archive::create(MBRef), Filename + ": failed to parse archive");
for (MemoryBufferRef M : getArchiveMembers(File.get()))
- addArchiveBuffer(M, "<whole-archive>", MBRef.getBufferIdentifier());
+ addArchiveBuffer(M, "<whole-archive>", Filename);
return;
}
Symtab->addFile(make<ArchiveFile>(MBRef));
break;
-
case file_magic::bitcode:
Symtab->addFile(make<BitcodeFile>(MBRef));
break;
-
+ case file_magic::coff_object:
+ case file_magic::coff_import_library:
+ Symtab->addFile(make<ObjFile>(MBRef));
+ break;
case file_magic::coff_cl_gl_object:
- error(MBRef.getBufferIdentifier() + ": is not a native COFF file. "
- "Recompile without /GL");
+ error(Filename + ": is not a native COFF file. Recompile without /GL");
break;
-
+ case file_magic::pecoff_executable:
+ if (Filename.endswith_lower(".dll")) {
+ error(Filename + ": bad file type. Did you specify a DLL instead of an "
+ "import library?");
+ break;
+ }
+ LLVM_FALLTHROUGH;
default:
- Symtab->addFile(make<ObjFile>(MBRef));
+ error(MBRef.getBufferIdentifier() + ": unknown file type");
break;
}
}
@@ -228,7 +243,29 @@ static bool isDecorated(StringRef Sym) {
void LinkerDriver::parseDirectives(StringRef S) {
ArgParser Parser;
// .drectve is always tokenized using Windows shell rules.
- opt::InputArgList Args = Parser.parseDirectives(S);
+ // /EXPORT: option can appear too many times, processing in fastpath.
+ opt::InputArgList Args;
+ std::vector<StringRef> Exports;
+ std::tie(Args, Exports) = Parser.parseDirectives(S);
+
+ for (StringRef E : Exports) {
+ // If a common header file contains dllexported function
+ // declarations, many object files may end up with having the
+ // same /EXPORT options. In order to save cost of parsing them,
+ // we dedup them first.
+ if (!DirectivesExports.insert(E).second)
+ continue;
+
+ Export Exp = parseExport(E);
+ if (Config->Machine == I386 && Config->MinGW) {
+ if (!isDecorated(Exp.Name))
+ Exp.Name = Saver.save("_" + Exp.Name);
+ if (!Exp.ExtName.empty() && !isDecorated(Exp.ExtName))
+ Exp.ExtName = Saver.save("_" + Exp.ExtName);
+ }
+ Exp.Directives = true;
+ Config->Exports.push_back(Exp);
+ }
for (auto *Arg : Args) {
switch (Arg->getOption().getUnaliasedOption().getID()) {
@@ -245,25 +282,6 @@ void LinkerDriver::parseDirectives(StringRef S) {
case OPT_entry:
Config->Entry = addUndefined(mangle(Arg->getValue()));
break;
- case OPT_export: {
- // If a common header file contains dllexported function
- // declarations, many object files may end up with having the
- // same /EXPORT options. In order to save cost of parsing them,
- // we dedup them first.
- if (!DirectivesExports.insert(Arg->getValue()).second)
- break;
-
- Export E = parseExport(Arg->getValue());
- if (Config->Machine == I386 && Config->MinGW) {
- if (!isDecorated(E.Name))
- E.Name = Saver.save("_" + E.Name);
- if (!E.ExtName.empty() && !isDecorated(E.ExtName))
- E.ExtName = Saver.save("_" + E.ExtName);
- }
- E.Directives = true;
- Config->Exports.push_back(E);
- break;
- }
case OPT_failifmismatch:
checkFailIfMismatch(Arg->getValue());
break;
@@ -316,13 +334,24 @@ StringRef LinkerDriver::doFindFile(StringRef Filename) {
return Filename;
}
+static Optional<sys::fs::UniqueID> getUniqueID(StringRef Path) {
+ sys::fs::UniqueID Ret;
+ if (sys::fs::getUniqueID(Path, Ret))
+ return None;
+ return Ret;
+}
+
// Resolves a file path. This never returns the same path
// (in that case, it returns None).
Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
StringRef Path = doFindFile(Filename);
- bool Seen = !VisitedFiles.insert(Path.lower()).second;
- if (Seen)
- return None;
+
+ if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path)) {
+ bool Seen = !VisitedFiles.insert(*ID).second;
+ if (Seen)
+ return None;
+ }
+
if (Path.endswith_lower(".lib"))
VisitedLibs.insert(sys::path::filename(Path));
return Path;
@@ -345,11 +374,14 @@ Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {
return None;
if (!VisitedLibs.insert(Filename.lower()).second)
return None;
+
StringRef Path = doFindLib(Filename);
if (Config->NoDefaultLibs.count(Path))
return None;
- if (!VisitedFiles.insert(Path.lower()).second)
- return None;
+
+ if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))
+ if (!VisitedFiles.insert(*ID).second)
+ return None;
return Path;
}
@@ -384,7 +416,24 @@ StringRef LinkerDriver::mangle(StringRef Sym) {
}
// Windows specific -- find default entry point name.
+//
+// There are four different entry point functions for Windows executables,
+// each of which corresponds to a user-defined "main" function. This function
+// infers an entry point from a user-defined "main" function.
StringRef LinkerDriver::findDefaultEntry() {
+ // As a special case, if /nodefaultlib is given, we directly look for an
+ // entry point. This is because, if no default library is linked, users
+ // need to define an entry point instead of a "main".
+ if (Config->NoDefaultLibAll) {
+ for (StringRef S : {"mainCRTStartup", "wmainCRTStartup",
+ "WinMainCRTStartup", "wWinMainCRTStartup"}) {
+ StringRef Entry = Symtab->findMangle(S);
+ if (!Entry.empty() && !isa<Undefined>(Symtab->find(Entry)))
+ return mangle(S);
+ }
+ return "";
+ }
+
// User-defined main functions and their corresponding entry points.
static const char *Entries[][2] = {
{"main", "mainCRTStartup"},
@@ -534,10 +583,49 @@ static void createImportLibrary(bool AsLib) {
Exports.push_back(E2);
}
- auto E = writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports,
- Config->Machine, false);
- handleAllErrors(std::move(E),
- [&](ErrorInfoBase &EIB) { error(EIB.message()); });
+ auto HandleError = [](Error &&E) {
+ handleAllErrors(std::move(E),
+ [](ErrorInfoBase &EIB) { error(EIB.message()); });
+ };
+ std::string LibName = getImportName(AsLib);
+ std::string Path = getImplibPath();
+
+ if (!Config->Incremental) {
+ HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine,
+ Config->MinGW));
+ return;
+ }
+
+ // If the import library already exists, replace it only if the contents
+ // have changed.
+ ErrorOr<std::unique_ptr<MemoryBuffer>> OldBuf = MemoryBuffer::getFile(
+ Path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false);
+ if (!OldBuf) {
+ HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine,
+ Config->MinGW));
+ return;
+ }
+
+ SmallString<128> TmpName;
+ if (std::error_code EC =
+ sys::fs::createUniqueFile(Path + ".tmp-%%%%%%%%.lib", TmpName))
+ fatal("cannot create temporary file for import library " + Path + ": " +
+ EC.message());
+
+ if (Error E = writeImportLibrary(LibName, TmpName, Exports, Config->Machine,
+ Config->MinGW)) {
+ HandleError(std::move(E));
+ return;
+ }
+
+ std::unique_ptr<MemoryBuffer> NewBuf = check(MemoryBuffer::getFile(
+ TmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false));
+ if ((*OldBuf)->getBuffer() != NewBuf->getBuffer()) {
+ OldBuf->reset();
+ HandleError(errorCodeToError(sys::fs::rename(TmpName, Path)));
+ } else {
+ sys::fs::remove(TmpName);
+ }
}
static void parseModuleDefs(StringRef Path) {
@@ -570,9 +658,18 @@ static void parseModuleDefs(StringRef Path) {
for (COFFShortExport E1 : M.Exports) {
Export E2;
+ // In simple cases, only Name is set. Renamed exports are parsed
+ // and set as "ExtName = Name". If Name has the form "OtherDll.Func",
+ // it shouldn't be a normal exported function but a forward to another
+ // DLL instead. This is supported by both MS and GNU linkers.
+ if (E1.ExtName != E1.Name && StringRef(E1.Name).contains('.')) {
+ E2.Name = Saver.save(E1.ExtName);
+ E2.ForwardTo = Saver.save(E1.Name);
+ Config->Exports.push_back(E2);
+ continue;
+ }
E2.Name = Saver.save(E1.Name);
- if (E1.isWeak())
- E2.ExtName = Saver.save(E1.ExtName);
+ E2.ExtName = Saver.save(E1.ExtName);
E2.Ordinal = E1.Ordinal;
E2.Noname = E1.Noname;
E2.Data = E1.Data;
@@ -635,8 +732,8 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) {
log("Creating a temporary archive for " + Path + " to remove bitcode files");
SmallString<128> S;
- if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path),
- ".lib", S))
+ if (std::error_code EC = sys::fs::createTemporaryFile(
+ "lld-" + sys::path::stem(Path), ".lib", S))
fatal("cannot create a temporary file: " + EC.message());
std::string Temp = S.str();
TemporaryFiles.push_back(Temp);
@@ -712,6 +809,8 @@ void LinkerDriver::enqueueTask(std::function<void()> Task) {
}
bool LinkerDriver::run() {
+ ScopedTimer T(InputFileTimer);
+
bool DidWork = !TaskQueue.empty();
while (!TaskQueue.empty()) {
TaskQueue.front()();
@@ -720,6 +819,46 @@ bool LinkerDriver::run() {
return DidWork;
}
+// Parse an /order file. If an option is given, the linker places
+// COMDAT sections in the same order as their names appear in the
+// given file.
+static void parseOrderFile(StringRef Arg) {
+ // For some reason, the MSVC linker requires a filename to be
+ // preceded by "@".
+ if (!Arg.startswith("@")) {
+ error("malformed /order option: '@' missing");
+ return;
+ }
+
+ // Get a list of all comdat sections for error checking.
+ DenseSet<StringRef> Set;
+ for (Chunk *C : Symtab->getChunks())
+ if (auto *Sec = dyn_cast<SectionChunk>(C))
+ if (Sec->Sym)
+ Set.insert(Sec->Sym->getName());
+
+ // Open a file.
+ StringRef Path = Arg.substr(1);
+ std::unique_ptr<MemoryBuffer> MB = CHECK(
+ MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);
+
+ // Parse a file. An order file contains one symbol per line.
+ // All symbols that were not present in a given order file are
+ // considered to have the lowest priority 0 and are placed at
+ // end of an output section.
+ for (std::string S : args::getLines(MB->getMemBufferRef())) {
+ if (Config->Machine == I386 && !isDecorated(S))
+ S = "_" + S;
+
+ if (Set.count(S) == 0) {
+ if (Config->WarnMissingOrderSymbol)
+ warn("/order:" + Arg + ": missing symbol: " + S + " [LNK4037]");
+ }
+ else
+ Config->Order[S] = INT_MIN + Config->Order.size();
+ }
+}
+
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// If the first command line argument is "/lib", link.exe acts like lib.exe.
// We call our own implementation of lib.exe that understands bitcode files.
@@ -735,11 +874,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
InitializeAllTargetMCs();
InitializeAllAsmParsers();
InitializeAllAsmPrinters();
- InitializeAllDisassemblers();
// Parse command line options.
ArgParser Parser;
- opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1));
+ opt::InputArgList Args = Parser.parseLINK(ArgsArr);
// Parse and evaluate -mllvm options.
std::vector<const char *> V;
@@ -763,6 +901,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
return;
}
+ if (Args.hasArg(OPT_show_timing))
+ Config->ShowTiming = true;
+
+ ScopedTimer T(Timer::root());
// Handle --version, which is an lld extension. This option is a bit odd
// because it doesn't start with "/", but we deliberately chose "--" to
// avoid conflict with /version and for compatibility with clang-cl.
@@ -805,7 +947,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Handle /ignore
for (auto *Arg : Args.filtered(OPT_ignore)) {
- if (StringRef(Arg->getValue()) == "4217")
+ if (StringRef(Arg->getValue()) == "4037")
+ Config->WarnMissingOrderSymbol = false;
+ else if (StringRef(Arg->getValue()) == "4217")
Config->WarnLocallyDefinedImported = false;
// Other warning numbers are ignored.
}
@@ -826,6 +970,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Handle /debug
if (Args.hasArg(OPT_debug, OPT_debug_dwarf, OPT_debug_ghash)) {
Config->Debug = true;
+ Config->Incremental = true;
if (auto *Arg = Args.getLastArg(OPT_debugtype))
Config->DebugTypes = parseDebugType(Arg->getValue());
else
@@ -834,9 +979,17 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Handle /pdb
bool ShouldCreatePDB = Args.hasArg(OPT_debug, OPT_debug_ghash);
- if (ShouldCreatePDB)
+ if (ShouldCreatePDB) {
if (auto *Arg = Args.getLastArg(OPT_pdb))
Config->PDBPath = Arg->getValue();
+ if (auto *Arg = Args.getLastArg(OPT_pdbaltpath))
+ Config->PDBAltPath = Arg->getValue();
+ if (Args.hasArg(OPT_natvis))
+ Config->NatvisFiles = Args.getAllArgValues(OPT_natvis);
+
+ if (auto *Arg = Args.getLastArg(OPT_pdb_source_path))
+ Config->PDBSourcePath = Arg->getValue();
+ }
// Handle /noentry
if (Args.hasArg(OPT_noentry)) {
@@ -860,6 +1013,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
DynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)
Config->DynamicBase = false;
+ // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the
+ // default setting for any other project type.", but link.exe defaults to
+ // /FIXED:NO for exe outputs as well. Match behavior, not docs.
bool Fixed = Args.hasFlag(OPT_fixed, OPT_fixed_no, false);
if (Fixed) {
if (DynamicBaseArg &&
@@ -895,6 +1051,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_stack))
parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit);
+ // Handle /guard:cf
+ if (auto *Arg = Args.getLastArg(OPT_guard))
+ parseGuard(Arg->getValue());
+
// Handle /heap
if (auto *Arg = Args.getLastArg(OPT_heap))
parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit);
@@ -909,6 +1069,23 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion,
&Config->MinorOSVersion);
+ // Handle /timestamp
+ if (llvm::opt::Arg *Arg = Args.getLastArg(OPT_timestamp, OPT_repro)) {
+ if (Arg->getOption().getID() == OPT_repro) {
+ Config->Timestamp = 0;
+ Config->Repro = true;
+ } else {
+ Config->Repro = false;
+ StringRef Value(Arg->getValue());
+ if (Value.getAsInteger(0, Config->Timestamp))
+ fatal(Twine("invalid timestamp: ") + Value +
+ ". Expected 32-bit integer");
+ }
+ } else {
+ Config->Repro = false;
+ Config->Timestamp = time(nullptr);
+ }
+
// Handle /alternatename
for (auto *Arg : Args.filtered(OPT_alternatename))
parseAlternateName(Arg->getValue());
@@ -922,8 +1099,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Config->Implib = Arg->getValue();
// Handle /opt.
- bool DoGC = !Args.hasArg(OPT_debug);
- unsigned ICFLevel = 1; // 0: off, 1: limited, 2: on
+ bool DoGC = !Args.hasArg(OPT_debug) || Args.hasArg(OPT_profile);
+ unsigned ICFLevel =
+ Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on
+ unsigned TailMerge = 1;
for (auto *Arg : Args.filtered(OPT_opt)) {
std::string Str = StringRef(Arg->getValue()).lower();
SmallVector<StringRef, 1> Vec;
@@ -937,14 +1116,18 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
ICFLevel = 2;
} else if (S == "noicf") {
ICFLevel = 0;
+ } else if (S == "lldtailmerge") {
+ TailMerge = 2;
+ } else if (S == "nolldtailmerge") {
+ TailMerge = 0;
} else if (S.startswith("lldlto=")) {
StringRef OptLevel = S.substr(7);
- if (OptLevel.getAsInteger(10, Config->LTOOptLevel) ||
- Config->LTOOptLevel > 3)
+ if (OptLevel.getAsInteger(10, Config->LTOO) || Config->LTOO > 3)
error("/opt:lldlto: invalid optimization level: " + OptLevel);
} else if (S.startswith("lldltojobs=")) {
StringRef Jobs = S.substr(11);
- if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0)
+ if (Jobs.getAsInteger(10, Config->ThinLTOJobs) ||
+ Config->ThinLTOJobs == 0)
error("/opt:lldltojobs: invalid job count: " + Jobs);
} else if (S.startswith("lldltopartitions=")) {
StringRef N = S.substr(17);
@@ -965,6 +1148,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
ICFLevel = 0;
Config->DoGC = DoGC;
Config->DoICF = ICFLevel > 0;
+ Config->TailMerge = (TailMerge == 1 && Config->DoICF) || TailMerge == 2;
// Handle /lldsavetemps
if (Args.hasArg(OPT_lldsavetemps))
@@ -992,6 +1176,14 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_merge))
parseMerge(Arg->getValue());
+ // Add default section merging rules after user rules. User rules take
+ // precedence, but we will emit a warning if there is a conflict.
+ parseMerge(".idata=.rdata");
+ parseMerge(".didat=.rdata");
+ parseMerge(".edata=.rdata");
+ parseMerge(".xdata=.rdata");
+ parseMerge(".bss=.data");
+
// Handle /section
for (auto *Arg : Args.filtered(OPT_section))
parseSection(Arg->getValue());
@@ -1029,39 +1221,77 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (!Config->ManifestInput.empty() &&
Config->Manifest != Configuration::Embed) {
- fatal("/MANIFESTINPUT: requires /MANIFEST:EMBED");
+ fatal("/manifestinput: requires /manifest:embed");
}
// Handle miscellaneous boolean flags.
Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);
Config->AllowIsolation =
Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
+ Config->Incremental =
+ Args.hasFlag(OPT_incremental, OPT_incremental_no,
+ !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order) &&
+ !Args.hasArg(OPT_profile));
+ Config->IntegrityCheck =
+ Args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
- Config->TerminalServerAware = Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
+ Config->TerminalServerAware =
+ !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf);
Config->DebugGHashes = Args.hasArg(OPT_debug_ghash);
+ Config->DebugSymtab = Args.hasArg(OPT_debug_symtab);
Config->MapFile = getMapFile(Args);
+ if (Config->Incremental && Args.hasArg(OPT_profile)) {
+ warn("ignoring '/incremental' due to '/profile' specification");
+ Config->Incremental = false;
+ }
+
+ if (Config->Incremental && Args.hasArg(OPT_order)) {
+ warn("ignoring '/incremental' due to '/order' specification");
+ Config->Incremental = false;
+ }
+
+ if (Config->Incremental && Config->DoGC) {
+ warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to "
+ "disable");
+ Config->Incremental = false;
+ }
+
+ if (Config->Incremental && Config->DoICF) {
+ warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to "
+ "disable");
+ Config->Incremental = false;
+ }
+
if (errorCount())
return;
- bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag);
+ std::set<sys::fs::UniqueID> WholeArchives;
+ for (auto *Arg : Args.filtered(OPT_wholearchive_file))
+ if (Optional<StringRef> Path = doFindFile(Arg->getValue()))
+ if (Optional<sys::fs::UniqueID> ID = getUniqueID(*Path))
+ WholeArchives.insert(*ID);
+
+ // A predicate returning true if a given path is an argument for
+ // /wholearchive:, or /wholearchive is enabled globally.
+ // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"
+ // needs to be handled as "/wholearchive:foo.obj foo.obj".
+ auto IsWholeArchive = [&](StringRef Path) -> bool {
+ if (Args.hasArg(OPT_wholearchive_flag))
+ return true;
+ if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))
+ return WholeArchives.count(*ID);
+ return false;
+ };
+
// Create a list of input files. Files can be given as arguments
// for /defaultlib option.
- std::vector<MemoryBufferRef> MBs;
- for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) {
- switch (Arg->getOption().getID()) {
- case OPT_INPUT:
- if (Optional<StringRef> Path = findFile(Arg->getValue()))
- enqueuePath(*Path, WholeArchiveFlag);
- break;
- case OPT_wholearchive_file:
- if (Optional<StringRef> Path = findFile(Arg->getValue()))
- enqueuePath(*Path, true);
- break;
- }
- }
+ for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file))
+ if (Optional<StringRef> Path = findFile(Arg->getValue()))
+ enqueuePath(*Path, IsWholeArchive(*Path));
+
for (auto *Arg : Args.filtered(OPT_defaultlib))
if (Optional<StringRef> Path = findLib(Arg->getValue()))
enqueuePath(*Path, false);
@@ -1165,10 +1395,24 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue());
}
- // Put the PDB next to the image if no /pdb flag was passed.
- if (ShouldCreatePDB && Config->PDBPath.empty()) {
- Config->PDBPath = Config->OutputFile;
- sys::path::replace_extension(Config->PDBPath, ".pdb");
+ if (ShouldCreatePDB) {
+ // Put the PDB next to the image if no /pdb flag was passed.
+ if (Config->PDBPath.empty()) {
+ Config->PDBPath = Config->OutputFile;
+ sys::path::replace_extension(Config->PDBPath, ".pdb");
+ }
+
+ // The embedded PDB path should be the absolute path to the PDB if no
+ // /pdbaltpath flag was passed.
+ if (Config->PDBAltPath.empty()) {
+ Config->PDBAltPath = Config->PDBPath;
+
+ // It's important to make the path absolute and remove dots. This path
+ // will eventually be written into the PE header, and certain Microsoft
+ // tools won't work correctly if these assumptions are not held.
+ sys::fs::make_absolute(Config->PDBAltPath);
+ sys::path::remove_dots(Config->PDBAltPath);
+ }
}
// Set default image base if /base is not given.
@@ -1181,11 +1425,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Symtab->addAbsolute("___safe_se_handler_count", 0);
}
- // We do not support /guard:cf (control flow protection) yet.
- // Define CFG symbols anyway so that we can link MSVC 2015 CRT.
Symtab->addAbsolute(mangle("__guard_fids_count"), 0);
Symtab->addAbsolute(mangle("__guard_fids_table"), 0);
- Symtab->addAbsolute(mangle("__guard_flags"), 0x100);
+ Symtab->addAbsolute(mangle("__guard_flags"), 0);
Symtab->addAbsolute(mangle("__guard_iat_count"), 0);
Symtab->addAbsolute(mangle("__guard_iat_table"), 0);
Symtab->addAbsolute(mangle("__guard_longjmp_count"), 0);
@@ -1260,7 +1502,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Handle /safeseh.
if (Args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) {
for (ObjFile *File : ObjFile::Instances)
- if (!File->SEHCompat)
+ if (!File->hasSafeSEH())
error("/safeseh: " + File->getName() + " is not compatible with SEH");
if (errorCount())
return;
@@ -1280,7 +1522,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
E.Name = Def->getName();
E.Sym = Def;
if (Def->getChunk() &&
- !(Def->getChunk()->getPermissions() & IMAGE_SCN_MEM_EXECUTE))
+ !(Def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
E.Data = true;
Config->Exports.push_back(E);
});
@@ -1309,11 +1551,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
continue;
}
+ // If the symbol isn't common, it must have been replaced with a regular
+ // symbol, which will carry its own alignment.
auto *DC = dyn_cast<DefinedCommon>(Sym);
- if (!DC) {
- warn("/aligncomm symbol " + Name + " of wrong kind");
+ if (!DC)
continue;
- }
CommonChunk *C = DC->getChunk();
C->Alignment = std::max(C->Alignment, Alignment);
@@ -1323,6 +1565,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (Config->Manifest == Configuration::SideBySide)
createSideBySideManifest();
+ // Handle /order. We want to do this at this moment because we
+ // need a complete list of comdat sections to warn on nonexistent
+ // functions.
+ if (auto *Arg = Args.getLastArg(OPT_order))
+ parseOrderFile(Arg->getValue());
+
// Identify unreferenced COMDAT sections.
if (Config->DoGC)
markLive(Symtab->getChunks());
@@ -1333,6 +1581,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Write the result.
writeResult();
+
+ // Stop early so we can print the results.
+ Timer::root().stop();
+ if (Config->ShowTiming)
+ Timer::root().print();
}
} // namespace coff
diff --git a/contrib/llvm/tools/lld/COFF/Driver.h b/contrib/llvm/tools/lld/COFF/Driver.h
index 3f7fad1038f3..627e991a9028 100644
--- a/contrib/llvm/tools/lld/COFF/Driver.h
+++ b/contrib/llvm/tools/lld/COFF/Driver.h
@@ -21,6 +21,7 @@
#include "llvm/Object/COFF.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TarWriter.h"
#include <memory>
#include <set>
@@ -36,12 +37,6 @@ using llvm::COFF::MachineTypes;
using llvm::COFF::WindowsSubsystem;
using llvm::Optional;
-// Implemented in MarkLive.cpp.
-void markLive(ArrayRef<Chunk *> Chunks);
-
-// Implemented in ICF.cpp.
-void doICF(ArrayRef<Chunk *> Chunks);
-
class COFFOptTable : public llvm::opt::OptTable {
public:
COFFOptTable();
@@ -56,8 +51,10 @@ public:
llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
// Tokenizes a given string and then parses as command line options in
- // .drectve section.
- llvm::opt::InputArgList parseDirectives(StringRef S);
+ // .drectve section. /EXPORT options are returned in second element
+ // to be processed in fastpath.
+ std::pair<llvm::opt::InputArgList, std::vector<StringRef>>
+ parseDirectives(StringRef S);
private:
// Parses command line options.
@@ -98,7 +95,11 @@ private:
// Library search path. The first element is always "" (current directory).
std::vector<StringRef> SearchPaths;
- std::set<std::string> VisitedFiles;
+
+ // We don't want to add the same file more than once.
+ // Files are uniquified by their filesystem and file number.
+ std::set<llvm::sys::fs::UniqueID> VisitedFiles;
+
std::set<std::string> VisitedLibs;
Symbol *addUndefined(StringRef Sym);
@@ -143,6 +144,8 @@ StringRef machineToStr(MachineTypes MT);
// Parses a string in the form of "<integer>[,<integer>]".
void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr);
+void parseGuard(StringRef Arg);
+
// Parses a string in the form of "<integer>[.<integer>]".
// Minor's default value is 0.
void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);
diff --git a/contrib/llvm/tools/lld/COFF/DriverUtils.cpp b/contrib/llvm/tools/lld/COFF/DriverUtils.cpp
index 4b3b6d5e09d6..c12e791f9507 100644
--- a/contrib/llvm/tools/lld/COFF/DriverUtils.cpp
+++ b/contrib/llvm/tools/lld/COFF/DriverUtils.cpp
@@ -61,12 +61,7 @@ public:
StringRef Exe = Saver.save(*ExeOrErr);
Args.insert(Args.begin(), Exe);
- std::vector<const char *> Vec;
- for (StringRef S : Args)
- Vec.push_back(S.data());
- Vec.push_back(nullptr);
-
- if (sys::ExecuteAndWait(Args[0], Vec.data()) != 0)
+ if (sys::ExecuteAndWait(Args[0], Args) != 0)
fatal("ExecuteAndWait failed: " +
llvm::join(Args.begin(), Args.end(), " "));
}
@@ -128,6 +123,21 @@ void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
fatal("invalid number: " + S2);
}
+void parseGuard(StringRef FullArg) {
+ SmallVector<StringRef, 1> SplitArgs;
+ FullArg.split(SplitArgs, ",");
+ for (StringRef Arg : SplitArgs) {
+ if (Arg.equals_lower("no"))
+ Config->GuardCF = GuardCFLevel::Off;
+ else if (Arg.equals_lower("nolongjmp"))
+ Config->GuardCF = GuardCFLevel::NoLongJmp;
+ else if (Arg.equals_lower("cf") || Arg.equals_lower("longjmp"))
+ Config->GuardCF = GuardCFLevel::Full;
+ else
+ fatal("invalid argument to /guard: " + Arg);
+ }
+}
+
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
uint32_t *Minor) {
@@ -170,6 +180,10 @@ void parseMerge(StringRef S) {
std::tie(From, To) = S.split('=');
if (From.empty() || To.empty())
fatal("/merge: invalid argument: " + S);
+ if (From == ".rsrc" || To == ".rsrc")
+ fatal("/merge: cannot merge '.rsrc' with any section");
+ if (From == ".reloc" || To == ".reloc")
+ fatal("/merge: cannot merge '.reloc' with any section");
auto Pair = Config->Merge.insert(std::make_pair(From, To));
bool Inserted = Pair.second;
if (!Inserted) {
@@ -418,15 +432,15 @@ static std::string createManifestXml() {
return createManifestXmlWithExternalMt(DefaultXml);
}
-static std::unique_ptr<MemoryBuffer>
+static std::unique_ptr<WritableMemoryBuffer>
createMemoryBufferForManifestRes(size_t ManifestSize) {
size_t ResSize = alignTo(
object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE +
sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) +
sizeof(object::WinResHeaderSuffix) + ManifestSize,
object::WIN_RES_DATA_ALIGNMENT);
- return MemoryBuffer::getNewMemBuffer(ResSize,
- Config->OutputFile + ".manifest.res");
+ return WritableMemoryBuffer::getNewMemBuffer(ResSize, Config->OutputFile +
+ ".manifest.res");
}
static void writeResFileHeader(char *&Buf) {
@@ -465,16 +479,16 @@ static void writeResEntryHeader(char *&Buf, size_t ManifestSize) {
std::unique_ptr<MemoryBuffer> createManifestRes() {
std::string Manifest = createManifestXml();
- std::unique_ptr<MemoryBuffer> Res =
+ std::unique_ptr<WritableMemoryBuffer> Res =
createMemoryBufferForManifestRes(Manifest.size());
- char *Buf = const_cast<char *>(Res->getBufferStart());
+ char *Buf = Res->getBufferStart();
writeResFileHeader(Buf);
writeResEntryHeader(Buf, Manifest.size());
// Copy the manifest data into the .res file.
std::copy(Manifest.begin(), Manifest.end(), Buf);
- return Res;
+ return std::move(Res);
}
void createSideBySideManifest() {
@@ -558,6 +572,12 @@ err:
static StringRef undecorate(StringRef Sym) {
if (Config->Machine != I386)
return Sym;
+ // In MSVC mode, a fully decorated stdcall function is exported
+ // as-is with the leading underscore (with type IMPORT_NAME).
+ // In MinGW mode, a decorated stdcall function gets the underscore
+ // removed, just like normal cdecl functions.
+ if (Sym.startswith("_") && Sym.contains('@') && !Config->MinGW)
+ return Sym;
return Sym.startswith("_") ? Sym.substr(1) : Sym;
}
@@ -731,6 +751,28 @@ static const llvm::opt::OptTable::Info InfoTable[] = {
COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {}
+// Set color diagnostics according to --color-diagnostics={auto,always,never}
+// or --no-color-diagnostics flags.
+static void handleColorDiagnostics(opt::InputArgList &Args) {
+ auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
+ OPT_no_color_diagnostics);
+ if (!Arg)
+ return;
+ if (Arg->getOption().getID() == OPT_color_diagnostics) {
+ errorHandler().ColorDiagnostics = true;
+ } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) {
+ errorHandler().ColorDiagnostics = false;
+ } else {
+ StringRef S = Arg->getValue();
+ if (S == "always")
+ errorHandler().ColorDiagnostics = true;
+ else if (S == "never")
+ errorHandler().ColorDiagnostics = false;
+ else if (S != "auto")
+ error("unknown option: --color-diagnostics=" + S);
+ }
+}
+
static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {
StringRef S = Arg->getValue();
@@ -749,50 +791,73 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
// Make InputArgList from string vectors.
unsigned MissingIndex;
unsigned MissingCount;
- SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
// We need to get the quoting style for response files before parsing all
// options so we parse here before and ignore all the options but
// --rsp-quoting.
- opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
+ opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount);
// Expand response files (arguments in the form of @<filename>)
// and then parse the argument again.
- cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
- Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
+ SmallVector<const char *, 256> ExpandedArgv(Argv.data(), Argv.data() + Argv.size());
+ cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), ExpandedArgv);
+ Args = Table.ParseArgs(makeArrayRef(ExpandedArgv).drop_front(), MissingIndex,
+ MissingCount);
// Print the real command line if response files are expanded.
- if (Args.hasArg(OPT_verbose) && Argv.size() != Vec.size()) {
+ if (Args.hasArg(OPT_verbose) && Argv.size() != ExpandedArgv.size()) {
std::string Msg = "Command line:";
- for (const char *S : Vec)
+ for (const char *S : ExpandedArgv)
Msg += " " + std::string(S);
message(Msg);
}
+ // Save the command line after response file expansion so we can write it to
+ // the PDB if necessary.
+ Config->Argv = {ExpandedArgv.begin(), ExpandedArgv.end()};
+
// Handle /WX early since it converts missing argument warnings to errors.
errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);
if (MissingCount)
fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");
+
+ handleColorDiagnostics(Args);
+
for (auto *Arg : Args.filtered(OPT_UNKNOWN))
warn("ignoring unknown argument: " + Arg->getSpelling());
+
+ if (Args.hasArg(OPT_lib))
+ warn("ignoring /lib since it's not the first argument");
+
return Args;
}
// Tokenizes and parses a given string as command line in .drective section.
-opt::InputArgList ArgParser::parseDirectives(StringRef S) {
- // Make InputArgList from string vectors.
+// /EXPORT options are processed in fastpath.
+std::pair<opt::InputArgList, std::vector<StringRef>>
+ArgParser::parseDirectives(StringRef S) {
+ std::vector<StringRef> Exports;
+ SmallVector<const char *, 16> Rest;
+
+ for (StringRef Tok : tokenize(S)) {
+ if (Tok.startswith_lower("/export:") || Tok.startswith_lower("-export:"))
+ Exports.push_back(Tok.substr(strlen("/export:")));
+ else
+ Rest.push_back(Tok.data());
+ }
+
+ // Make InputArgList from unparsed string vectors.
unsigned MissingIndex;
unsigned MissingCount;
- opt::InputArgList Args =
- Table.ParseArgs(tokenize(S), MissingIndex, MissingCount);
+ opt::InputArgList Args = Table.ParseArgs(Rest, MissingIndex, MissingCount);
if (MissingCount)
fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");
for (auto *Arg : Args.filtered(OPT_UNKNOWN))
warn("ignoring unknown argument: " + Arg->getSpelling());
- return Args;
+ return {std::move(Args), std::move(Exports)};
}
// link.exe has an interesting feature. If LINK or _LINK_ environment
@@ -802,11 +867,11 @@ opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Argv) {
// Concatenate LINK env and command line arguments, and then parse them.
if (Optional<std::string> S = Process::GetEnv("LINK")) {
std::vector<const char *> V = tokenize(*S);
- Argv.insert(Argv.begin(), V.begin(), V.end());
+ Argv.insert(std::next(Argv.begin()), V.begin(), V.end());
}
if (Optional<std::string> S = Process::GetEnv("_LINK_")) {
std::vector<const char *> V = tokenize(*S);
- Argv.insert(Argv.begin(), V.begin(), V.end());
+ Argv.insert(std::next(Argv.begin()), V.begin(), V.end());
}
return parse(Argv);
}
diff --git a/contrib/llvm/tools/lld/COFF/ICF.cpp b/contrib/llvm/tools/lld/COFF/ICF.cpp
index 48895c34886c..7feb3c4e0b0c 100644
--- a/contrib/llvm/tools/lld/COFF/ICF.cpp
+++ b/contrib/llvm/tools/lld/COFF/ICF.cpp
@@ -18,13 +18,16 @@
//
//===----------------------------------------------------------------------===//
+#include "ICF.h"
#include "Chunks.h"
#include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Timer.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <atomic>
#include <vector>
@@ -34,6 +37,8 @@ using namespace llvm;
namespace lld {
namespace coff {
+static Timer ICFTimer("ICF", Timer::root());
+
class ICF {
public:
void run(ArrayRef<Chunk *> V);
@@ -41,6 +46,8 @@ public:
private:
void segregate(size_t Begin, size_t End, bool Constant);
+ bool assocEquals(const SectionChunk *A, const SectionChunk *B);
+
bool equalsConstant(const SectionChunk *A, const SectionChunk *B);
bool equalsVariable(const SectionChunk *A, const SectionChunk *B);
@@ -59,13 +66,6 @@ private:
std::atomic<bool> Repeat = {false};
};
-// Returns a hash value for S.
-uint32_t ICF::getHash(SectionChunk *C) {
- return hash_combine(C->getPermissions(), C->SectionName, C->NumRelocs,
- C->Alignment, uint32_t(C->Header->SizeOfRawData),
- C->Checksum, C->getContents());
-}
-
// Returns true if section S is subject of ICF.
//
// Microsoft's documentation
@@ -73,21 +73,27 @@ uint32_t ICF::getHash(SectionChunk *C) {
// 2017) says that /opt:icf folds both functions and read-only data.
// Despite that, the MSVC linker folds only functions. We found
// a few instances of programs that are not safe for data merging.
-// Therefore, we merge only functions just like the MSVC tool. However, we merge
-// identical .xdata sections, because the address of unwind information is
-// insignificant to the user program and the Visual C++ linker does this.
+// Therefore, we merge only functions just like the MSVC tool. However, we also
+// merge read-only sections in a couple of cases where the address of the
+// section is insignificant to the user program and the behaviour matches that
+// of the Visual C++ linker.
bool ICF::isEligible(SectionChunk *C) {
// Non-comdat chunks, dead chunks, and writable chunks are not elegible.
- bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
+ bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
if (!C->isCOMDAT() || !C->isLive() || Writable)
return false;
// Code sections are eligible.
- if (C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
+ if (C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
return true;
- // .xdata unwind info sections are eligble.
- return C->getSectionName().split('$').first == ".xdata";
+ // .pdata and .xdata unwind info sections are eligible.
+ StringRef OutSecName = C->getSectionName().split('$').first;
+ if (OutSecName == ".pdata" || OutSecName == ".xdata")
+ return true;
+
+ // So are vtables.
+ return C->Sym && C->Sym->getName().startswith("??_7");
}
// Split an equivalence class into smaller classes.
@@ -116,10 +122,23 @@ void ICF::segregate(size_t Begin, size_t End, bool Constant) {
}
}
+// Returns true if two sections' associative children are equal.
+bool ICF::assocEquals(const SectionChunk *A, const SectionChunk *B) {
+ auto ChildClasses = [&](const SectionChunk *SC) {
+ std::vector<uint32_t> Classes;
+ for (const SectionChunk *C : SC->children())
+ if (!C->SectionName.startswith(".debug") &&
+ C->SectionName != ".gfids$y" && C->SectionName != ".gljmp$y")
+ Classes.push_back(C->Class[Cnt % 2]);
+ return Classes;
+ };
+ return ChildClasses(A) == ChildClasses(B);
+}
+
// Compare "non-moving" part of two sections, namely everything
// except relocation targets.
bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) {
- if (A->NumRelocs != B->NumRelocs)
+ if (A->Relocs.size() != B->Relocs.size())
return false;
// Compare relocations.
@@ -142,10 +161,11 @@ bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) {
return false;
// Compare section attributes and contents.
- return A->getPermissions() == B->getPermissions() &&
- A->SectionName == B->SectionName && A->Alignment == B->Alignment &&
+ return A->getOutputCharacteristics() == B->getOutputCharacteristics() &&
+ A->SectionName == B->SectionName &&
A->Header->SizeOfRawData == B->Header->SizeOfRawData &&
- A->Checksum == B->Checksum && A->getContents() == B->getContents();
+ A->Checksum == B->Checksum && A->getContents() == B->getContents() &&
+ assocEquals(A, B);
}
// Compare "moving" part of two sections, namely relocation targets.
@@ -161,9 +181,12 @@ bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
return D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2];
return false;
};
- return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
+ return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(),
+ Eq) &&
+ assocEquals(A, B);
}
+// Find the first Chunk after Begin that has a different class from Begin.
size_t ICF::findBoundary(size_t Begin, size_t End) {
for (size_t I = Begin + 1; I < End; ++I)
if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2])
@@ -173,11 +196,8 @@ size_t ICF::findBoundary(size_t Begin, size_t End) {
void ICF::forEachClassRange(size_t Begin, size_t End,
std::function<void(size_t, size_t)> Fn) {
- if (Begin > 0)
- Begin = findBoundary(Begin - 1, End);
-
while (Begin < End) {
- size_t Mid = findBoundary(Begin, Chunks.size());
+ size_t Mid = findBoundary(Begin, End);
Fn(Begin, Mid);
Begin = Mid;
}
@@ -193,12 +213,22 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
return;
}
- // Split sections into 256 shards and call Fn in parallel.
- size_t NumShards = 256;
+ // Shard into non-overlapping intervals, and call Fn in parallel.
+ // The sharding must be completed before any calls to Fn are made
+ // so that Fn can modify the Chunks in its shard without causing data
+ // races.
+ const size_t NumShards = 256;
size_t Step = Chunks.size() / NumShards;
- for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
- size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
- forEachClassRange(I * Step, End, Fn);
+ size_t Boundaries[NumShards + 1];
+ Boundaries[0] = 0;
+ Boundaries[NumShards] = Chunks.size();
+ for_each_n(parallel::par, size_t(1), NumShards, [&](size_t I) {
+ Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size());
+ });
+ for_each_n(parallel::par, size_t(1), NumShards + 1, [&](size_t I) {
+ if (Boundaries[I - 1] < Boundaries[I]) {
+ forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);
+ }
});
++Cnt;
}
@@ -207,6 +237,8 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
// Two sections are considered the same if their section headers,
// contents and relocations are all the same.
void ICF::run(ArrayRef<Chunk *> Vec) {
+ ScopedTimer T(ICFTimer);
+
// Collect only mergeable sections and group by hash value.
uint32_t NextId = 1;
for (Chunk *C : Vec) {
@@ -218,10 +250,16 @@ void ICF::run(ArrayRef<Chunk *> Vec) {
}
}
+ // Make sure that ICF doesn't merge sections that are being handled by string
+ // tail merging.
+ for (auto &P : MergeChunk::Instances)
+ for (SectionChunk *SC : P.second->Sections)
+ SC->Class[0] = NextId++;
+
// Initially, we use hash values to partition sections.
for_each(parallel::par, Chunks.begin(), Chunks.end(), [&](SectionChunk *SC) {
// Set MSB to 1 to avoid collisions with non-hash classs.
- SC->Class[0] = getHash(SC) | (1 << 31);
+ SC->Class[0] = xxHash64(SC->getContents()) | (1 << 31);
});
// From now on, sections in Chunks are ordered so that sections in
diff --git a/contrib/llvm/tools/lld/COFF/Strings.h b/contrib/llvm/tools/lld/COFF/ICF.h
index 67fc1c773c66..9c54e0c9ec2d 100644
--- a/contrib/llvm/tools/lld/COFF/Strings.h
+++ b/contrib/llvm/tools/lld/COFF/ICF.h
@@ -1,4 +1,4 @@
-//===- Strings.h ------------------------------------------------*- C++ -*-===//
+//===- ICF.h --------------------------------------------------------------===//
//
// The LLVM Linker
//
@@ -7,17 +7,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_COFF_STRINGS_H
-#define LLD_COFF_STRINGS_H
+#ifndef LLD_COFF_ICF_H
+#define LLD_COFF_ICF_H
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include <string>
+#include "lld/Common/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
namespace lld {
namespace coff {
-llvm::Optional<std::string> demangleMSVC(llvm::StringRef S);
-}
-}
+
+class Chunk;
+
+void doICF(ArrayRef<Chunk *> Chunks);
+
+} // namespace coff
+} // namespace lld
#endif
diff --git a/contrib/llvm/tools/lld/COFF/InputFiles.cpp b/contrib/llvm/tools/lld/COFF/InputFiles.cpp
index a8f52e0391f7..289cdb1f6cd0 100644
--- a/contrib/llvm/tools/lld/COFF/InputFiles.cpp
+++ b/contrib/llvm/tools/lld/COFF/InputFiles.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Target/TargetOptions.h"
#include <cstring>
#include <system_error>
@@ -138,12 +139,13 @@ void ObjFile::initializeChunks() {
if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT)
SparseChunks[I] = PendingComdat;
else
- SparseChunks[I] = readSection(I, nullptr);
+ SparseChunks[I] = readSection(I, nullptr, "");
}
}
SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
- const coff_aux_section_definition *Def) {
+ const coff_aux_section_definition *Def,
+ StringRef LeaderName) {
const coff_section *Sec;
StringRef Name;
if (auto EC = COFFObj->getSection(SectionNumber, Sec))
@@ -151,15 +153,7 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
if (auto EC = COFFObj->getSectionName(Sec, Name))
fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " +
EC.message());
- if (Name == ".sxdata") {
- ArrayRef<uint8_t> Data;
- COFFObj->getSectionContents(Sec, Data);
- if (Data.size() % 4 != 0)
- fatal(".sxdata must be an array of symbol table indices");
- SXData = {reinterpret_cast<const ulittle32_t *>(Data.data()),
- Data.size() / 4};
- return nullptr;
- }
+
if (Name == ".drectve") {
ArrayRef<uint8_t> Data;
COFFObj->getSectionContents(Sec, Data);
@@ -177,8 +171,8 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
// CodeView needs a linker support. We need to interpret and debug
// info, and then write it to a separate .pdb file.
- // Ignore debug info unless /debug is given.
- if (!Config->Debug && Name.startswith(".debug"))
+ // Ignore DWARF debug info unless /debug is given.
+ if (!Config->Debug && Name.startswith(".debug_"))
return nullptr;
if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
@@ -191,6 +185,18 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
// linked in the regular manner.
if (C->isCodeView())
DebugChunks.push_back(C);
+ else if (Config->GuardCF != GuardCFLevel::Off && Name == ".gfids$y")
+ GuardFidChunks.push_back(C);
+ else if (Config->GuardCF != GuardCFLevel::Off && Name == ".gljmp$y")
+ GuardLJmpChunks.push_back(C);
+ else if (Name == ".sxdata")
+ SXDataChunks.push_back(C);
+ else if (Config->TailMerge && Sec->NumberOfRelocations == 0 &&
+ Name == ".rdata" && LeaderName.startswith("??_C@"))
+ // COFF sections that look like string literal sections (i.e. no
+ // relocations, in .rdata, leader symbol name matches the MSVC name mangling
+ // for string literals) are subject to string tail merging.
+ MergeChunk::addSection(C);
else
Chunks.push_back(C);
@@ -199,7 +205,13 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
void ObjFile::readAssociativeDefinition(
COFFSymbolRef Sym, const coff_aux_section_definition *Def) {
- SectionChunk *Parent = SparseChunks[Def->getNumber(Sym.isBigObj())];
+ readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj()));
+}
+
+void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym,
+ const coff_aux_section_definition *Def,
+ uint32_t ParentSection) {
+ SectionChunk *Parent = SparseChunks[ParentSection];
// If the parent is pending, it probably means that its section definition
// appears after us in the symbol table. Leave the associated section as
@@ -211,7 +223,7 @@ void ObjFile::readAssociativeDefinition(
// the section; otherwise mark it as discarded.
int32_t SectionNumber = Sym.getSectionNumber();
if (Parent) {
- SparseChunks[SectionNumber] = readSection(SectionNumber, Def);
+ SparseChunks[SectionNumber] = readSection(SectionNumber, Def, "");
if (SparseChunks[SectionNumber])
Parent->addAssociative(SparseChunks[SectionNumber]);
} else {
@@ -219,6 +231,35 @@ void ObjFile::readAssociativeDefinition(
}
}
+void ObjFile::recordPrevailingSymbolForMingw(
+ COFFSymbolRef Sym, DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {
+ // For comdat symbols in executable sections, where this is the copy
+ // of the section chunk we actually include instead of discarding it,
+ // add the symbol to a map to allow using it for implicitly
+ // associating .[px]data$<func> sections to it.
+ int32_t SectionNumber = Sym.getSectionNumber();
+ SectionChunk *SC = SparseChunks[SectionNumber];
+ if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) {
+ StringRef Name;
+ COFFObj->getSymbolName(Sym, Name);
+ PrevailingSectionMap[Name] = SectionNumber;
+ }
+}
+
+void ObjFile::maybeAssociateSEHForMingw(
+ COFFSymbolRef Sym, const coff_aux_section_definition *Def,
+ const DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {
+ StringRef Name;
+ COFFObj->getSymbolName(Sym, Name);
+ if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$")) {
+ // For MinGW, treat .[px]data$<func> as implicitly associative to
+ // the symbol <func>.
+ auto ParentSym = PrevailingSectionMap.find(Name);
+ if (ParentSym != PrevailingSectionMap.end())
+ readAssociativeDefinition(Sym, Def, ParentSym->second);
+ }
+}
+
Symbol *ObjFile::createRegular(COFFSymbolRef Sym) {
SectionChunk *SC = SparseChunks[Sym.getSectionNumber()];
if (Sym.isExternal()) {
@@ -242,19 +283,24 @@ void ObjFile::initializeSymbols() {
std::vector<uint32_t> PendingIndexes;
PendingIndexes.reserve(NumSymbols);
+ DenseMap<StringRef, uint32_t> PrevailingSectionMap;
std::vector<const coff_aux_section_definition *> ComdatDefs(
COFFObj->getNumberOfSections() + 1);
for (uint32_t I = 0; I < NumSymbols; ++I) {
COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I));
+ bool PrevailingComdat;
if (COFFSym.isUndefined()) {
Symbols[I] = createUndefined(COFFSym);
} else if (COFFSym.isWeakExternal()) {
Symbols[I] = createUndefined(COFFSym);
uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex;
WeakAliases.emplace_back(Symbols[I], TagIndex);
- } else if (Optional<Symbol *> OptSym = createDefined(COFFSym, ComdatDefs)) {
+ } else if (Optional<Symbol *> OptSym =
+ createDefined(COFFSym, ComdatDefs, PrevailingComdat)) {
Symbols[I] = *OptSym;
+ if (Config->MinGW && PrevailingComdat)
+ recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap);
} else {
// createDefined() returns None if a symbol belongs to a section that
// was pending at the point when the symbol was read. This can happen in
@@ -272,9 +318,19 @@ void ObjFile::initializeSymbols() {
for (uint32_t I : PendingIndexes) {
COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
- if (auto *Def = Sym.getSectionDefinition())
+ if (auto *Def = Sym.getSectionDefinition()) {
if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
readAssociativeDefinition(Sym, Def);
+ else if (Config->MinGW)
+ maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap);
+ }
+ if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) {
+ StringRef Name;
+ COFFObj->getSymbolName(Sym, Name);
+ log("comdat section " + Name +
+ " without leader and unassociated, discarding");
+ continue;
+ }
Symbols[I] = createRegular(Sym);
}
@@ -293,61 +349,65 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) {
Optional<Symbol *> ObjFile::createDefined(
COFFSymbolRef Sym,
- std::vector<const coff_aux_section_definition *> &ComdatDefs) {
- StringRef Name;
+ std::vector<const coff_aux_section_definition *> &ComdatDefs,
+ bool &Prevailing) {
+ Prevailing = false;
+ auto GetName = [&]() {
+ StringRef S;
+ COFFObj->getSymbolName(Sym, S);
+ return S;
+ };
+
if (Sym.isCommon()) {
auto *C = make<CommonChunk>(Sym);
Chunks.push_back(C);
- COFFObj->getSymbolName(Sym, Name);
- Symbol *S =
- Symtab->addCommon(this, Name, Sym.getValue(), Sym.getGeneric(), C);
- return S;
+ return Symtab->addCommon(this, GetName(), Sym.getValue(), Sym.getGeneric(),
+ C);
}
+
if (Sym.isAbsolute()) {
- COFFObj->getSymbolName(Sym, Name);
+ StringRef Name = GetName();
+
// Skip special symbols.
if (Name == "@comp.id")
return nullptr;
- // COFF spec 5.10.1. The .sxdata section.
if (Name == "@feat.00") {
- if (Sym.getValue() & 1)
- SEHCompat = true;
+ Feat00Flags = Sym.getValue();
return nullptr;
}
+
if (Sym.isExternal())
return Symtab->addAbsolute(Name, Sym);
- else
- return make<DefinedAbsolute>(Name, Sym);
+ return make<DefinedAbsolute>(Name, Sym);
}
+
int32_t SectionNumber = Sym.getSectionNumber();
if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
return nullptr;
- // Reserved sections numbers don't have contents.
if (llvm::COFF::isReservedSectionNumber(SectionNumber))
- fatal("broken object file: " + toString(this));
+ fatal(toString(this) + ": " + GetName() +
+ " should not refer to special section " + Twine(SectionNumber));
- // This symbol references a section which is not present in the section
- // header.
if ((uint32_t)SectionNumber >= SparseChunks.size())
- fatal("broken object file: " + toString(this));
+ fatal(toString(this) + ": " + GetName() +
+ " should not refer to non-existent section " + Twine(SectionNumber));
// Handle comdat leader symbols.
if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) {
ComdatDefs[SectionNumber] = nullptr;
Symbol *Leader;
- bool Prevailing;
if (Sym.isExternal()) {
- COFFObj->getSymbolName(Sym, Name);
std::tie(Leader, Prevailing) =
- Symtab->addComdat(this, Name, Sym.getGeneric());
+ Symtab->addComdat(this, GetName(), Sym.getGeneric());
} else {
Leader = make<DefinedRegular>(this, /*Name*/ "", false,
/*IsExternal*/ false, Sym.getGeneric());
Prevailing = true;
}
+
if (Prevailing) {
- SectionChunk *C = readSection(SectionNumber, Def);
+ SectionChunk *C = readSection(SectionNumber, Def, GetName());
SparseChunks[SectionNumber] = C;
C->Sym = cast<DefinedRegular>(Leader);
cast<DefinedRegular>(Leader)->Data = &C->Repl;
@@ -429,7 +489,8 @@ void ImportFile::parse() {
// address pointed by the __imp_ symbol. (This allows you to call
// DLL functions just like regular non-DLL functions.)
if (Hdr->getType() == llvm::COFF::IMPORT_CODE)
- ThunkSym = Symtab->addImportThunk(Name, ImpSym, Hdr->Machine);
+ ThunkSym = Symtab->addImportThunk(
+ Name, cast_or_null<DefinedImportData>(ImpSym), Hdr->Machine);
}
void BitcodeFile::parse() {
@@ -462,7 +523,7 @@ void BitcodeFile::parse() {
} else {
Sym = Symtab->addRegular(this, SymName);
}
- SymbolBodies.push_back(Sym);
+ Symbols.push_back(Sym);
}
Directives = Obj->getCOFFLinkerOpts();
}
@@ -486,10 +547,7 @@ MachineTypes BitcodeFile::getMachineType() {
// Returns the last element of a path, which is supposed to be a filename.
static StringRef getBasename(StringRef Path) {
- size_t Pos = Path.find_last_of("\\/");
- if (Pos == StringRef::npos)
- return Path;
- return Path.substr(Pos + 1);
+ return sys::path::filename(Path, sys::path::Style::windows);
}
// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
diff --git a/contrib/llvm/tools/lld/COFF/InputFiles.h b/contrib/llvm/tools/lld/COFF/InputFiles.h
index adedbc2ad7a8..2bfb9e4b002a 100644
--- a/contrib/llvm/tools/lld/COFF/InputFiles.h
+++ b/contrib/llvm/tools/lld/COFF/InputFiles.h
@@ -13,6 +13,7 @@
#include "Config.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
@@ -110,6 +111,9 @@ public:
MachineTypes getMachineType() override;
ArrayRef<Chunk *> getChunks() { return Chunks; }
ArrayRef<SectionChunk *> getDebugChunks() { return DebugChunks; }
+ ArrayRef<SectionChunk *> getSXDataChunks() { return SXDataChunks; }
+ ArrayRef<SectionChunk *> getGuardFidChunks() { return GuardFidChunks; }
+ ArrayRef<SectionChunk *> getGuardLJmpChunks() { return GuardLJmpChunks; }
ArrayRef<Symbol *> getSymbols() { return Symbols; }
// Returns a Symbol object for the SymbolIndex'th symbol in the
@@ -123,13 +127,17 @@ public:
static std::vector<ObjFile *> Instances;
- // True if this object file is compatible with SEH.
- // COFF-specific and x86-only.
- bool SEHCompat = false;
+ // Flags in the absolute @feat.00 symbol if it is present. These usually
+ // indicate if an object was compiled with certain security features enabled
+ // like stack guard, safeseh, /guard:cf, or other things.
+ uint32_t Feat00Flags = 0;
- // The symbol table indexes of the safe exception handlers.
- // COFF-specific and x86-only.
- ArrayRef<llvm::support::ulittle32_t> SXData;
+ // True if this object file is compatible with SEH. COFF-specific and
+ // x86-only. COFF spec 5.10.1. The .sxdata section.
+ bool hasSafeSEH() { return Feat00Flags & 0x1; }
+
+ // True if this file was compiled with /guard:cf.
+ bool hasGuardCF() { return Feat00Flags & 0x800; }
// Pointer to the PDB module descriptor builder. Various debug info records
// will reference object files by "module index", which is here. Things like
@@ -143,16 +151,31 @@ private:
SectionChunk *
readSection(uint32_t SectionNumber,
- const llvm::object::coff_aux_section_definition *Def);
+ const llvm::object::coff_aux_section_definition *Def,
+ StringRef LeaderName);
void readAssociativeDefinition(
COFFSymbolRef COFFSym,
const llvm::object::coff_aux_section_definition *Def);
+ void readAssociativeDefinition(
+ COFFSymbolRef COFFSym,
+ const llvm::object::coff_aux_section_definition *Def,
+ uint32_t ParentSection);
+
+ void recordPrevailingSymbolForMingw(
+ COFFSymbolRef COFFSym,
+ llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);
+
+ void maybeAssociateSEHForMingw(
+ COFFSymbolRef Sym, const llvm::object::coff_aux_section_definition *Def,
+ const llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);
+
llvm::Optional<Symbol *>
createDefined(COFFSymbolRef Sym,
std::vector<const llvm::object::coff_aux_section_definition *>
- &ComdatDefs);
+ &ComdatDefs,
+ bool &PrevailingComdat);
Symbol *createRegular(COFFSymbolRef Sym);
Symbol *createUndefined(COFFSymbolRef Sym);
@@ -165,6 +188,15 @@ private:
// CodeView debug info sections.
std::vector<SectionChunk *> DebugChunks;
+ // Chunks containing symbol table indices of exception handlers. Only used for
+ // 32-bit x86.
+ std::vector<SectionChunk *> SXDataChunks;
+
+ // Chunks containing symbol table indices of address taken symbols and longjmp
+ // targets. These are not linked into the final binary when /guard:cf is set.
+ std::vector<SectionChunk *> GuardFidChunks;
+ std::vector<SectionChunk *> GuardLJmpChunks;
+
// This vector contains the same chunks as Chunks, but they are
// indexed such that you can get a SectionChunk by section index.
// Nonexistent section indices are filled with null pointers.
@@ -184,15 +216,14 @@ private:
// for details about the format.
class ImportFile : public InputFile {
public:
- explicit ImportFile(MemoryBufferRef M)
- : InputFile(ImportKind, M), Live(!Config->DoGC) {}
+ explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M) {}
static bool classof(const InputFile *F) { return F->kind() == ImportKind; }
static std::vector<ImportFile *> Instances;
- DefinedImportData *ImpSym = nullptr;
- DefinedImportThunk *ThunkSym = nullptr;
+ Symbol *ImpSym = nullptr;
+ Symbol *ThunkSym = nullptr;
std::string DLLName;
private:
@@ -204,12 +235,15 @@ public:
Chunk *Location = nullptr;
// We want to eliminate dllimported symbols if no one actually refers them.
- // This "Live" bit is used to keep track of which import library members
+ // These "Live" bits are used to keep track of which import library members
// are actually in use.
//
// If the Live bit is turned off by MarkLive, Writer will ignore dllimported
- // symbols provided by this import library member.
- bool Live;
+ // symbols provided by this import library member. We also track whether the
+ // imported symbol is used separately from whether the thunk is used in order
+ // to avoid creating unnecessary thunks.
+ bool Live = !Config->DoGC;
+ bool ThunkLive = !Config->DoGC;
};
// Used for LTO.
@@ -217,7 +251,7 @@ class BitcodeFile : public InputFile {
public:
explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
- ArrayRef<Symbol *> getSymbols() { return SymbolBodies; }
+ ArrayRef<Symbol *> getSymbols() { return Symbols; }
MachineTypes getMachineType() override;
static std::vector<BitcodeFile *> Instances;
std::unique_ptr<llvm::lto::InputFile> Obj;
@@ -225,7 +259,7 @@ public:
private:
void parse() override;
- std::vector<Symbol *> SymbolBodies;
+ std::vector<Symbol *> Symbols;
};
} // namespace coff
diff --git a/contrib/llvm/tools/lld/COFF/LTO.cpp b/contrib/llvm/tools/lld/COFF/LTO.cpp
index fa2a54b61841..93f7ba3f9e4c 100644
--- a/contrib/llvm/tools/lld/COFF/LTO.cpp
+++ b/contrib/llvm/tools/lld/COFF/LTO.cpp
@@ -12,6 +12,7 @@
#include "InputFiles.h"
#include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -40,47 +41,32 @@ using namespace llvm::object;
using namespace lld;
using namespace lld::coff;
-static void diagnosticHandler(const DiagnosticInfo &DI) {
- SmallString<128> ErrStorage;
- raw_svector_ostream OS(ErrStorage);
- DiagnosticPrinterRawOStream DP(OS);
- DI.print(DP);
- warn(ErrStorage);
-}
-
-static void checkError(Error E) {
- handleAllErrors(std::move(E),
- [&](ErrorInfoBase &EIB) { error(EIB.message()); });
-}
+static std::unique_ptr<lto::LTO> createLTO() {
+ lto::Config C;
+ C.Options = InitTargetOptionsFromCodeGenFlags();
-static void saveBuffer(StringRef Buffer, const Twine &Path) {
- std::error_code EC;
- raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
- if (EC)
- error("cannot create " + Path + ": " + EC.message());
- OS << Buffer;
-}
+ // Always emit a section per function/datum with LTO. LLVM LTO should get most
+ // of the benefit of linker GC, but there are still opportunities for ICF.
+ C.Options.FunctionSections = true;
+ C.Options.DataSections = true;
-static std::unique_ptr<lto::LTO> createLTO() {
- lto::Config Conf;
- Conf.Options = InitTargetOptionsFromCodeGenFlags();
// Use static reloc model on 32-bit x86 because it usually results in more
// compact code, and because there are also known code generation bugs when
// using the PIC model (see PR34306).
if (Config->Machine == COFF::IMAGE_FILE_MACHINE_I386)
- Conf.RelocModel = Reloc::Static;
+ C.RelocModel = Reloc::Static;
else
- Conf.RelocModel = Reloc::PIC_;
- Conf.DisableVerify = true;
- Conf.DiagHandler = diagnosticHandler;
- Conf.OptLevel = Config->LTOOptLevel;
+ C.RelocModel = Reloc::PIC_;
+ C.DisableVerify = true;
+ C.DiagHandler = diagnosticHandler;
+ C.OptLevel = Config->LTOO;
if (Config->SaveTemps)
- checkError(Conf.addSaveTemps(std::string(Config->OutputFile) + ".",
- /*UseInputModulePath*/ true));
+ checkError(C.addSaveTemps(std::string(Config->OutputFile) + ".",
+ /*UseInputModulePath*/ true));
lto::ThinBackend Backend;
- if (Config->LTOJobs != 0)
- Backend = lto::createInProcessThinBackend(Config->LTOJobs);
- return llvm::make_unique<lto::LTO>(std::move(Conf), Backend,
+ if (Config->ThinLTOJobs != 0)
+ Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);
+ return llvm::make_unique<lto::LTO>(std::move(C), Backend,
Config->LTOPartitions);
}
@@ -119,7 +105,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
// and return the resulting objects.
std::vector<StringRef> BitcodeCompiler::compile() {
unsigned MaxTasks = LTOObj->getMaxTasks();
- Buff.resize(MaxTasks);
+ Buf.resize(MaxTasks);
Files.resize(MaxTasks);
// The /lldltocache option specifies the path to a directory in which to cache
@@ -127,15 +113,15 @@ std::vector<StringRef> BitcodeCompiler::compile() {
// specified, configure LTO to use it as the cache directory.
lto::NativeObjectCache Cache;
if (!Config->LTOCache.empty())
- Cache = check(
- lto::localCache(Config->LTOCache,
- [&](size_t Task, std::unique_ptr<MemoryBuffer> MB,
- StringRef Path) { Files[Task] = std::move(MB); }));
+ Cache = check(lto::localCache(
+ Config->LTOCache, [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
+ Files[Task] = std::move(MB);
+ }));
checkError(LTOObj->run(
[&](size_t Task) {
return llvm::make_unique<lto::NativeObjectStream>(
- llvm::make_unique<raw_svector_ostream>(Buff[Task]));
+ llvm::make_unique<raw_svector_ostream>(Buf[Task]));
},
Cache));
@@ -144,15 +130,15 @@ std::vector<StringRef> BitcodeCompiler::compile() {
std::vector<StringRef> Ret;
for (unsigned I = 0; I != MaxTasks; ++I) {
- if (Buff[I].empty())
+ if (Buf[I].empty())
continue;
if (Config->SaveTemps) {
if (I == 0)
- saveBuffer(Buff[I], Config->OutputFile + ".lto.obj");
+ saveBuffer(Buf[I], Config->OutputFile + ".lto.obj");
else
- saveBuffer(Buff[I], Config->OutputFile + Twine(I) + ".lto.obj");
+ saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.obj");
}
- Ret.emplace_back(Buff[I].data(), Buff[I].size());
+ Ret.emplace_back(Buf[I].data(), Buf[I].size());
}
for (std::unique_ptr<MemoryBuffer> &File : Files)
diff --git a/contrib/llvm/tools/lld/COFF/LTO.h b/contrib/llvm/tools/lld/COFF/LTO.h
index a444aa7ac4fe..f00924654780 100644
--- a/contrib/llvm/tools/lld/COFF/LTO.h
+++ b/contrib/llvm/tools/lld/COFF/LTO.h
@@ -48,7 +48,7 @@ public:
private:
std::unique_ptr<llvm::lto::LTO> LTOObj;
- std::vector<SmallString<0>> Buff;
+ std::vector<SmallString<0>> Buf;
std::vector<std::unique_ptr<MemoryBuffer>> Files;
};
}
diff --git a/contrib/llvm/tools/lld/COFF/MapFile.cpp b/contrib/llvm/tools/lld/COFF/MapFile.cpp
index 717ed3419ea5..6ca1b6647bd7 100644
--- a/contrib/llvm/tools/lld/COFF/MapFile.cpp
+++ b/contrib/llvm/tools/lld/COFF/MapFile.cpp
@@ -23,7 +23,6 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
-
#include "lld/Common/ErrorHandler.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/raw_ostream.h"
@@ -37,14 +36,15 @@ using namespace lld::coff;
typedef DenseMap<const SectionChunk *, SmallVector<DefinedRegular *, 4>>
SymbolMapTy;
+static const std::string Indent8 = " "; // 8 spaces
+static const std::string Indent16 = " "; // 16 spaces
+
// Print out the first three columns of a line.
static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,
uint64_t Align) {
OS << format("%08llx %08llx %5lld ", Addr, Size, Align);
}
-static std::string indent(int Depth) { return std::string(Depth * 8, ' '); }
-
// Returns a list of all symbols that we want to print out.
static std::vector<DefinedRegular *> getSymbols() {
std::vector<DefinedRegular *> V;
@@ -79,7 +79,7 @@ getSymbolStrings(ArrayRef<DefinedRegular *> Syms) {
for_each_n(parallel::par, (size_t)0, Syms.size(), [&](size_t I) {
raw_string_ostream OS(Str[I]);
writeHeader(OS, Syms[I]->getRVA(), 0, 0);
- OS << indent(2) << toString(*Syms[I]);
+ OS << Indent16 << toString(*Syms[I]);
});
DenseMap<DefinedRegular *, std::string> Ret;
@@ -108,7 +108,7 @@ void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) {
// Print out file contents.
for (OutputSection *Sec : OutputSections) {
writeHeader(OS, Sec->getRVA(), Sec->getVirtualSize(), /*Align=*/PageSize);
- OS << Sec->getName() << '\n';
+ OS << Sec->Name << '\n';
for (Chunk *C : Sec->getChunks()) {
auto *SC = dyn_cast<SectionChunk>(C);
@@ -116,7 +116,7 @@ void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) {
continue;
writeHeader(OS, SC->getRVA(), SC->getSize(), SC->Alignment);
- OS << indent(1) << SC->File->getName() << ":(" << SC->getSectionName()
+ OS << Indent8 << SC->File->getName() << ":(" << SC->getSectionName()
<< ")\n";
for (DefinedRegular *Sym : SectionSyms[SC])
OS << SymStr[Sym] << '\n';
diff --git a/contrib/llvm/tools/lld/COFF/MarkLive.cpp b/contrib/llvm/tools/lld/COFF/MarkLive.cpp
index 01be60d12d82..57ae450a9138 100644
--- a/contrib/llvm/tools/lld/COFF/MarkLive.cpp
+++ b/contrib/llvm/tools/lld/COFF/MarkLive.cpp
@@ -9,16 +9,21 @@
#include "Chunks.h"
#include "Symbols.h"
+#include "lld/Common/Timer.h"
#include "llvm/ADT/STLExtras.h"
#include <vector>
namespace lld {
namespace coff {
+static Timer GCTimer("GC", Timer::root());
+
// Set live bit on for each reachable chunk. Unmarked (unreachable)
// COMDAT chunks will be ignored by Writer, so they will be excluded
// from the final output.
void markLive(ArrayRef<Chunk *> Chunks) {
+ ScopedTimer T(GCTimer);
+
// We build up a worklist of sections which have been marked as live. We only
// push into the worklist when we discover an unmarked section, and we mark
// as we push, so sections never appear twice in the list.
@@ -43,7 +48,7 @@ void markLive(ArrayRef<Chunk *> Chunks) {
else if (auto *Sym = dyn_cast<DefinedImportData>(B))
Sym->File->Live = true;
else if (auto *Sym = dyn_cast<DefinedImportThunk>(B))
- Sym->WrappedSym->File->Live = true;
+ Sym->WrappedSym->File->Live = Sym->WrappedSym->File->ThunkLive = true;
};
// Add GC root chunks.
diff --git a/contrib/llvm/tools/lld/COFF/MarkLive.h b/contrib/llvm/tools/lld/COFF/MarkLive.h
new file mode 100644
index 000000000000..5b652dd48196
--- /dev/null
+++ b/contrib/llvm/tools/lld/COFF/MarkLive.h
@@ -0,0 +1,24 @@
+//===- MarkLive.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COFF_MARKLIVE_H
+#define LLD_COFF_MARKLIVE_H
+
+#include "lld/Common/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace lld {
+namespace coff {
+
+void markLive(ArrayRef<Chunk *> Chunks);
+
+} // namespace coff
+} // namespace lld
+
+#endif // LLD_COFF_MARKLIVE_H
diff --git a/contrib/llvm/tools/lld/COFF/MinGW.cpp b/contrib/llvm/tools/lld/COFF/MinGW.cpp
index b7a47165640d..2ca00587331f 100644
--- a/contrib/llvm/tools/lld/COFF/MinGW.cpp
+++ b/contrib/llvm/tools/lld/COFF/MinGW.cpp
@@ -138,7 +138,7 @@ void coff::writeDefFile(StringRef Name) {
<< "@" << E.Ordinal;
if (auto *Def = dyn_cast_or_null<Defined>(E.Sym)) {
if (Def && Def->getChunk() &&
- !(Def->getChunk()->getPermissions() & IMAGE_SCN_MEM_EXECUTE))
+ !(Def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
OS << " DATA";
}
OS << "\n";
diff --git a/contrib/llvm/tools/lld/COFF/Options.td b/contrib/llvm/tools/lld/COFF/Options.td
index 2a1de14657c1..871bad8bd655 100644
--- a/contrib/llvm/tools/lld/COFF/Options.td
+++ b/contrib/llvm/tools/lld/COFF/Options.td
@@ -20,6 +20,10 @@ def align : P<"align", "Section alignment">;
def aligncomm : P<"aligncomm", "Set common symbol alignment">;
def alternatename : P<"alternatename", "Define weak alias">;
def base : P<"base", "Base address of the program">;
+def color_diagnostics: Flag<["--"], "color-diagnostics">,
+ HelpText<"Use colors in diagnostics">;
+def color_diagnostics_eq: Joined<["--"], "color-diagnostics=">,
+ HelpText<"Use colors in diagnostics; one of 'always', 'never', 'auto'">;
def defaultlib : P<"defaultlib", "Add the library to the list of input files">;
def delayload : P<"delayload", "Delay loaded DLL name">;
def entry : P<"entry", "Name of entry point symbol">;
@@ -28,9 +32,12 @@ def errorlimit : P<"errorlimit",
def export : P<"export", "Export a function">;
// No help text because /failifmismatch is not intended to be used by the user.
def failifmismatch : P<"failifmismatch", "">;
+def guard : P<"guard", "Control flow guard">;
def heap : P<"heap", "Size of the heap">;
def ignore : P<"ignore", "Specify warning codes to ignore">;
def implib : P<"implib", "Import library name">;
+def lib : F<"lib">,
+ HelpText<"Act like lib.exe; must be first argument if present">;
def libpath : P<"libpath", "Additional library search path">;
def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">;
def lldltocache : P<"lldltocache", "Path to ThinLTO cached object file directory">;
@@ -42,12 +49,18 @@ def merge : P<"merge", "Combine sections">;
def mllvm : P<"mllvm", "Options to pass to LLVM">;
def nodefaultlib : P<"nodefaultlib", "Remove a default library">;
def opt : P<"opt", "Control optimizations">;
+def order : P<"order", "Put functions in order">;
def out : P<"out", "Path to file to write output">;
+def natvis : P<"natvis", "Path to natvis file to embed in the PDB">;
+def no_color_diagnostics: F<"no-color-diagnostics">,
+ HelpText<"Do not use colors in diagnostics">;
def pdb : P<"pdb", "PDB file path">;
+def pdbaltpath : P<"pdbaltpath", "PDB file path to embed in the image">;
def section : P<"section", "Specify section attributes">;
def stack : P<"stack", "Size of the stack">;
def stub : P<"stub", "Specify DOS stub file">;
def subsystem : P<"subsystem", "Specify subsystem">;
+def timestamp : P<"timestamp", "Specify the PE header timestamp">;
def version : P<"version", "Specify a version number in the PE header">;
def wholearchive_file : P<"wholearchive", "Include all object files from this archive">;
@@ -72,12 +85,14 @@ def deffile : Joined<["/", "-"], "def:">,
HelpText<"Use module-definition file">;
def debug : F<"debug">, HelpText<"Embed a symbol table in the image">;
+def debug_full : F<"debug:full">, Alias<debug>;
def debugtype : P<"debugtype", "Debug Info Options">;
def dll : F<"dll">, HelpText<"Create a DLL">;
def driver : P<"driver", "Generate a Windows NT Kernel Mode Driver">;
def nodefaultlib_all : F<"nodefaultlib">;
def noentry : F<"noentry">;
def profile : F<"profile">;
+def repro : F<"Brepro">, HelpText<"Use a hash of the executable as the PE header timestamp">;
def swaprun_cd : F<"swaprun:cd">;
def swaprun_net : F<"swaprun:net">;
def verbose : F<"verbose">;
@@ -102,6 +117,12 @@ defm fixed : B<"fixed", "Disable base relocations",
defm highentropyva : B<"highentropyva",
"Enable 64-bit ASLR (default on 64-bit)",
"Disable 64-bit ASLR">;
+defm incremental : B<"incremental",
+ "Keep original import library if contents are unchanged",
+ "Overwrite import library even if contents are unchanged">;
+defm integritycheck : B<"integritycheck",
+ "Set FORCE_INTEGRITY bit in PE header",
+ "No effect (default)">;
defm largeaddressaware : B<"largeaddressaware",
"Enable large addresses (default on 64-bit)",
"Disable large addresses (default on 32-bit)">;
@@ -120,11 +141,14 @@ def help_q : Flag<["/?", "-?"], "">, Alias<help>;
// LLD extensions
def debug_ghash : F<"debug:ghash">;
def debug_dwarf : F<"debug:dwarf">;
+def debug_symtab : F<"debug:symtab">;
def export_all_symbols : F<"export-all-symbols">;
def kill_at : F<"kill-at">;
def lldmingw : F<"lldmingw">;
def msvclto : F<"msvclto">;
def output_def : Joined<["/", "-"], "output-def:">;
+def pdb_source_path : P<"pdbsourcepath",
+ "Base path used to make relative source file path absolute in PDB">;
def rsp_quoting : Joined<["--"], "rsp-quoting=">,
HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;
def dash_dash_version : Flag<["--"], "version">,
@@ -133,6 +157,7 @@ def dash_dash_version : Flag<["--"], "version">,
// Flags for debugging
def lldmap : F<"lldmap">;
def lldmap_file : Joined<["/", "-"], "lldmap:">;
+def show_timing : F<"time">;
//==============================================================================
// The flags below do nothing. They are defined only for link.exe compatibility.
@@ -147,8 +172,6 @@ multiclass QB<string name> {
def functionpadmin : F<"functionpadmin">;
def ignoreidl : F<"ignoreidl">;
-def incremental : F<"incremental">;
-def no_incremental : F<"incremental:no">;
def nologo : F<"nologo">;
def throwingnew : F<"throwingnew">;
def editandcontinue : F<"editandcontinue">;
@@ -158,8 +181,6 @@ def delay : QF<"delay">;
def errorreport : QF<"errorreport">;
def idlout : QF<"idlout">;
def maxilksize : QF<"maxilksize">;
-def natvis : QF<"natvis">;
-def pdbaltpath : QF<"pdbaltpath">;
def tlbid : QF<"tlbid">;
def tlbout : QF<"tlbout">;
def verbose_all : QF<"verbose">;
diff --git a/contrib/llvm/tools/lld/COFF/PDB.cpp b/contrib/llvm/tools/lld/COFF/PDB.cpp
index 8ca52556ae58..766bf3f6b456 100644
--- a/contrib/llvm/tools/lld/COFF/PDB.cpp
+++ b/contrib/llvm/tools/lld/COFF/PDB.cpp
@@ -15,7 +15,7 @@
#include "Symbols.h"
#include "Writer.h"
#include "lld/Common/ErrorHandler.h"
-#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
+#include "lld/Common/Timer.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@@ -45,8 +45,10 @@
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/CVDebugRecord.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JamCRC.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -61,6 +63,15 @@ using llvm::object::coff_section;
static ExitOnError ExitOnErr;
+static Timer TotalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root());
+
+static Timer AddObjectsTimer("Add Objects", TotalPdbLinkTimer);
+static Timer TypeMergingTimer("Type Merging", AddObjectsTimer);
+static Timer SymbolMergingTimer("Symbol Merging", AddObjectsTimer);
+static Timer GlobalsLayoutTimer("Globals Stream Layout", TotalPdbLinkTimer);
+static Timer TpiStreamLayoutTimer("TPI Stream Layout", TotalPdbLinkTimer);
+static Timer DiskCommitTimer("Commit to Disk", TotalPdbLinkTimer);
+
namespace {
/// Map from type index and item index in a type server PDB to the
/// corresponding index in the destination PDB.
@@ -74,11 +85,19 @@ class PDBLinker {
public:
PDBLinker(SymbolTable *Symtab)
: Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc),
- IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {}
+ IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {
+ // This isn't strictly necessary, but link.exe usually puts an empty string
+ // as the first "valid" string in the string table, so we do the same in
+ // order to maintain as much byte-for-byte compatibility as possible.
+ PDBStrTab.insert("");
+ }
/// Emit the basic PDB structure: initial streams, headers, etc.
void initialize(const llvm::codeview::DebugInfo &BuildId);
+ /// Add natvis files specified on the command line.
+ void addNatvisFiles();
+
/// Link CodeView from each object file in the symbol table into the PDB.
void addObjectsToPDB();
@@ -106,9 +125,6 @@ public:
void addSections(ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable);
- void addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
- OutputSection *OS, Chunk *C);
-
/// Write the PDB to disk.
void commit();
@@ -137,6 +153,11 @@ private:
llvm::SmallString<128> NativePath;
+ /// A list of other PDBs which are loaded during the linking process and which
+ /// we need to keep around since the linking operation may reference pointers
+ /// inside of these PDBs.
+ llvm::SmallVector<std::unique_ptr<pdb::NativeSession>, 2> LoadedPDBs;
+
std::vector<pdb::SecMapEntry> SectionMap;
/// Type index mappings of type server PDBs that we've loaded so far.
@@ -184,8 +205,8 @@ static bool canUseDebugH(ArrayRef<uint8_t> DebugH) {
DebugH = DebugH.drop_front(sizeof(object::debug_h_header));
return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC &&
Header->Version == 0 &&
- Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1) &&
- (DebugH.size() % 20 == 0);
+ Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) &&
+ (DebugH.size() % 8 == 0);
}
static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *File) {
@@ -237,6 +258,8 @@ maybeReadTypeServerRecord(CVTypeArray &Types) {
Expected<const CVIndexMap&> PDBLinker::mergeDebugT(ObjFile *File,
CVIndexMap &ObjectIndexMap) {
+ ScopedTimer T(TypeMergingTimer);
+
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
if (Data.empty())
return ObjectIndexMap;
@@ -348,10 +371,16 @@ Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
return std::move(E);
}
- auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
+ pdb::NativeSession *Session = ExpectedSession->get();
+
+ // Keep a strong reference to this PDB, so that it's safe to hold pointers
+ // into the file.
+ LoadedPDBs.push_back(std::move(*ExpectedSession));
+
+ auto ExpectedTpi = Session->getPDBFile().getPDBTpiStream();
if (auto E = ExpectedTpi.takeError())
fatal("Type server does not have TPI stream: " + toString(std::move(E)));
- auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
+ auto ExpectedIpi = Session->getPDBFile().getPDBIpiStream();
if (auto E = ExpectedIpi.takeError())
fatal("Type server does not have TPI stream: " + toString(std::move(E)));
@@ -428,6 +457,38 @@ static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind,
}
}
+static void
+recordStringTableReferenceAtOffset(MutableArrayRef<uint8_t> Contents,
+ uint32_t Offset,
+ std::vector<ulittle32_t *> &StrTableRefs) {
+ Contents =
+ Contents.drop_front(Offset).take_front(sizeof(support::ulittle32_t));
+ ulittle32_t *Index = reinterpret_cast<ulittle32_t *>(Contents.data());
+ StrTableRefs.push_back(Index);
+}
+
+static void
+recordStringTableReferences(SymbolKind Kind, MutableArrayRef<uint8_t> Contents,
+ std::vector<ulittle32_t *> &StrTableRefs) {
+ // For now we only handle S_FILESTATIC, but we may need the same logic for
+ // S_DEFRANGE and S_DEFRANGE_SUBFIELD. However, I cannot seem to generate any
+ // PDBs that contain these types of records, so because of the uncertainty
+ // they are omitted here until we can prove that it's necessary.
+ switch (Kind) {
+ case SymbolKind::S_FILESTATIC:
+ // FileStaticSym::ModFileOffset
+ recordStringTableReferenceAtOffset(Contents, 4, StrTableRefs);
+ break;
+ case SymbolKind::S_DEFRANGE:
+ case SymbolKind::S_DEFRANGE_SUBFIELD:
+ log("Not fixing up string table reference in S_DEFRANGE / "
+ "S_DEFRANGE_SUBFIELD record");
+ break;
+ default:
+ break;
+ }
+}
+
static SymbolKind symbolKind(ArrayRef<uint8_t> RecordData) {
const RecordPrefix *Prefix =
reinterpret_cast<const RecordPrefix *>(RecordData.data());
@@ -644,53 +705,65 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjFile *File,
pdb::GSIStreamBuilder &GsiBuilder,
const CVIndexMap &IndexMap,
TypeCollection &IDTable,
+ std::vector<ulittle32_t *> &StringTableRefs,
BinaryStreamRef SymData) {
// FIXME: Improve error recovery by warning and skipping records when
// possible.
- CVSymbolArray Syms;
- BinaryStreamReader Reader(SymData);
- ExitOnErr(Reader.readArray(Syms, Reader.getLength()));
+ ArrayRef<uint8_t> SymsBuffer;
+ cantFail(SymData.readBytes(0, SymData.getLength(), SymsBuffer));
SmallVector<SymbolScope, 4> Scopes;
- for (CVSymbol Sym : Syms) {
- // Discover type index references in the record. Skip it if we don't know
- // where they are.
- SmallVector<TiReference, 32> TypeRefs;
- if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) {
- log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind()));
- continue;
- }
-
- // Copy the symbol record so we can mutate it.
- MutableArrayRef<uint8_t> NewData = copySymbolForPdb(Sym, Alloc);
-
- // Re-map all the type index references.
- MutableArrayRef<uint8_t> Contents =
- NewData.drop_front(sizeof(RecordPrefix));
- remapTypesInSymbolRecord(File, Sym.kind(), Contents, IndexMap, TypeRefs);
- // An object file may have S_xxx_ID symbols, but these get converted to
- // "real" symbols in a PDB.
- translateIdSymbols(NewData, IDTable);
-
- SymbolKind NewKind = symbolKind(NewData);
-
- // Fill in "Parent" and "End" fields by maintaining a stack of scopes.
- CVSymbol NewSym(NewKind, NewData);
- if (symbolOpensScope(NewKind))
- scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), NewSym);
- else if (symbolEndsScope(NewKind))
- scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File);
-
- // Add the symbol to the globals stream if necessary. Do this before adding
- // the symbol to the module since we may need to get the next symbol offset,
- // and writing to the module's symbol stream will update that offset.
- if (symbolGoesInGlobalsStream(NewSym))
- addGlobalSymbol(GsiBuilder, *File, NewSym);
+ auto EC = forEachCodeViewRecord<CVSymbol>(
+ SymsBuffer, [&](const CVSymbol &Sym) -> llvm::Error {
+ // Discover type index references in the record. Skip it if we don't
+ // know where they are.
+ SmallVector<TiReference, 32> TypeRefs;
+ if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) {
+ log("ignoring unknown symbol record with kind 0x" +
+ utohexstr(Sym.kind()));
+ return Error::success();
+ }
- // Add the symbol to the module.
- if (symbolGoesInModuleStream(NewSym))
- File->ModuleDBI->addSymbol(NewSym);
- }
+ // Copy the symbol record so we can mutate it.
+ MutableArrayRef<uint8_t> NewData = copySymbolForPdb(Sym, Alloc);
+
+ // Re-map all the type index references.
+ MutableArrayRef<uint8_t> Contents =
+ NewData.drop_front(sizeof(RecordPrefix));
+ remapTypesInSymbolRecord(File, Sym.kind(), Contents, IndexMap,
+ TypeRefs);
+
+ // An object file may have S_xxx_ID symbols, but these get converted to
+ // "real" symbols in a PDB.
+ translateIdSymbols(NewData, IDTable);
+
+ // If this record refers to an offset in the object file's string table,
+ // add that item to the global PDB string table and re-write the index.
+ recordStringTableReferences(Sym.kind(), Contents, StringTableRefs);
+
+ SymbolKind NewKind = symbolKind(NewData);
+
+ // Fill in "Parent" and "End" fields by maintaining a stack of scopes.
+ CVSymbol NewSym(NewKind, NewData);
+ if (symbolOpensScope(NewKind))
+ scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(),
+ NewSym);
+ else if (symbolEndsScope(NewKind))
+ scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File);
+
+ // Add the symbol to the globals stream if necessary. Do this before
+ // adding the symbol to the module since we may need to get the next
+ // symbol offset, and writing to the module's symbol stream will update
+ // that offset.
+ if (symbolGoesInGlobalsStream(NewSym))
+ addGlobalSymbol(GsiBuilder, *File, NewSym);
+
+ // Add the symbol to the module.
+ if (symbolGoesInModuleStream(NewSym))
+ File->ModuleDBI->addSymbol(NewSym);
+ return Error::success();
+ });
+ cantFail(std::move(EC));
}
// Allocate memory for a .debug$S section and relocate it.
@@ -704,6 +777,32 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
".debug$S");
}
+static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) {
+ OutputSection *OS = C->getOutputSection();
+ pdb::SectionContrib SC;
+ memset(&SC, 0, sizeof(SC));
+ SC.ISect = OS->SectionIndex;
+ SC.Off = C->getRVA() - OS->getRVA();
+ SC.Size = C->getSize();
+ if (auto *SecChunk = dyn_cast<SectionChunk>(C)) {
+ SC.Characteristics = SecChunk->Header->Characteristics;
+ SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();
+ ArrayRef<uint8_t> Contents = SecChunk->getContents();
+ JamCRC CRC(0);
+ ArrayRef<char> CharContents = makeArrayRef(
+ reinterpret_cast<const char *>(Contents.data()), Contents.size());
+ CRC.update(CharContents);
+ SC.DataCrc = CRC.getCRC();
+ } else {
+ SC.Characteristics = OS->Header.Characteristics;
+ // FIXME: When we start creating DBI for import libraries, use those here.
+ SC.Imod = Modi;
+ }
+ SC.RelocCrc = 0; // FIXME
+
+ return SC;
+}
+
void PDBLinker::addObjFile(ObjFile *File) {
// Add a module descriptor for every object file. We need to put an absolute
// path to the object into the PDB. If this is a plain object, we make its
@@ -718,6 +817,17 @@ void PDBLinker::addObjFile(ObjFile *File) {
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
File->ModuleDBI->setObjFileName(Path);
+ auto Chunks = File->getChunks();
+ uint32_t Modi = File->ModuleDBI->getModuleIndex();
+ for (Chunk *C : Chunks) {
+ auto *SecChunk = dyn_cast<SectionChunk>(C);
+ if (!SecChunk || !SecChunk->isLive())
+ continue;
+ pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi);
+ File->ModuleDBI->setFirstSectionContrib(SC);
+ break;
+ }
+
// Before we can process symbol substreams from .debug$S, we need to process
// type information, file checksums, and the string table. Add type info to
// the PDB first, so that we can get the map from object file type and item
@@ -734,7 +844,12 @@ void PDBLinker::addObjFile(ObjFile *File) {
const CVIndexMap &IndexMap = *IndexMapResult;
+ ScopedTimer T(SymbolMergingTimer);
+
// Now do all live .debug$S sections.
+ DebugStringTableSubsectionRef CVStrTab;
+ DebugChecksumsSubsectionRef Checksums;
+ std::vector<ulittle32_t *> StringTableReferences;
for (SectionChunk *DebugChunk : File->getDebugChunks()) {
if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
continue;
@@ -748,14 +863,17 @@ void PDBLinker::addObjFile(ObjFile *File) {
BinaryStreamReader Reader(RelocatedDebugContents, support::little);
ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));
- DebugStringTableSubsectionRef CVStrTab;
- DebugChecksumsSubsectionRef Checksums;
for (const DebugSubsectionRecord &SS : Subsections) {
switch (SS.kind()) {
- case DebugSubsectionKind::StringTable:
+ case DebugSubsectionKind::StringTable: {
+ assert(!CVStrTab.valid() &&
+ "Encountered multiple string table subsections!");
ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
break;
+ }
case DebugSubsectionKind::FileChecksums:
+ assert(!Checksums.valid() &&
+ "Encountered multiple checksum subsections!");
ExitOnErr(Checksums.initialize(SS.getRecordData()));
break;
case DebugSubsectionKind::Lines:
@@ -766,10 +884,12 @@ void PDBLinker::addObjFile(ObjFile *File) {
case DebugSubsectionKind::Symbols:
if (Config->DebugGHashes) {
mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap,
- GlobalIDTable, SS.getRecordData());
+ GlobalIDTable, StringTableReferences,
+ SS.getRecordData());
} else {
mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap,
- IDTable, SS.getRecordData());
+ IDTable, StringTableReferences,
+ SS.getRecordData());
}
break;
default:
@@ -777,25 +897,55 @@ void PDBLinker::addObjFile(ObjFile *File) {
break;
}
}
+ }
- if (Checksums.valid()) {
- // Make a new file checksum table that refers to offsets in the PDB-wide
- // string table. Generally the string table subsection appears after the
- // checksum table, so we have to do this after looping over all the
- // subsections.
- if (!CVStrTab.valid())
- fatal(".debug$S sections must have both a string table subsection "
- "and a checksum subsection table or neither");
- auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab);
- for (FileChecksumEntry &FC : Checksums) {
- StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
- ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI,
- FileName));
- NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
- }
- File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
+ // We should have seen all debug subsections across the entire object file now
+ // which means that if a StringTable subsection and Checksums subsection were
+ // present, now is the time to handle them.
+ if (!CVStrTab.valid()) {
+ if (Checksums.valid())
+ fatal(".debug$S sections with a checksums subsection must also contain a "
+ "string table subsection");
+
+ if (!StringTableReferences.empty())
+ warn("No StringTable subsection was encountered, but there are string "
+ "table references");
+ return;
+ }
+
+ // Rewrite each string table reference based on the value that the string
+ // assumes in the final PDB.
+ for (ulittle32_t *Ref : StringTableReferences) {
+ auto ExpectedString = CVStrTab.getString(*Ref);
+ if (!ExpectedString) {
+ warn("Invalid string table reference");
+ consumeError(ExpectedString.takeError());
+ continue;
}
+
+ *Ref = PDBStrTab.insert(*ExpectedString);
}
+
+ // Make a new file checksum table that refers to offsets in the PDB-wide
+ // string table. Generally the string table subsection appears after the
+ // checksum table, so we have to do this after looping over all the
+ // subsections.
+ auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab);
+ for (FileChecksumEntry &FC : Checksums) {
+ SmallString<128> FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
+ if (!sys::path::is_absolute(FileName) &&
+ !Config->PDBSourcePath.empty()) {
+ SmallString<128> AbsoluteFileName = Config->PDBSourcePath;
+ sys::path::append(AbsoluteFileName, FileName);
+ sys::path::native(AbsoluteFileName);
+ sys::path::remove_dots(AbsoluteFileName, /*remove_dot_dots=*/true);
+ FileName = std::move(AbsoluteFileName);
+ }
+ ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI,
+ FileName));
+ NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
+ }
+ File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
}
static PublicSym32 createPublic(Defined *Def) {
@@ -818,12 +968,15 @@ static PublicSym32 createPublic(Defined *Def) {
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
// TpiData.
void PDBLinker::addObjectsToPDB() {
+ ScopedTimer T1(AddObjectsTimer);
for (ObjFile *File : ObjFile::Instances)
addObjFile(File);
Builder.getStringTableBuilder().setStrings(PDBStrTab);
+ T1.stop();
// Construct TPI and IPI stream contents.
+ ScopedTimer T2(TpiStreamLayoutTimer);
if (Config->DebugGHashes) {
addTypeInfo(Builder.getTpiBuilder(), GlobalTypeTable);
addTypeInfo(Builder.getIpiBuilder(), GlobalIDTable);
@@ -831,7 +984,9 @@ void PDBLinker::addObjectsToPDB() {
addTypeInfo(Builder.getTpiBuilder(), TypeTable);
addTypeInfo(Builder.getIpiBuilder(), IDTable);
}
+ T2.stop();
+ ScopedTimer T3(GlobalsLayoutTimer);
// Compute the public and global symbols.
auto &GsiBuilder = Builder.getGsiBuilder();
std::vector<PublicSym32> Publics;
@@ -853,6 +1008,35 @@ void PDBLinker::addObjectsToPDB() {
}
}
+void PDBLinker::addNatvisFiles() {
+ for (StringRef File : Config->NatvisFiles) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> DataOrErr =
+ MemoryBuffer::getFile(File);
+ if (!DataOrErr) {
+ warn("Cannot open input file: " + File);
+ continue;
+ }
+ Builder.addInjectedSource(File, std::move(*DataOrErr));
+ }
+}
+
+static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) {
+ switch (Machine) {
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ return codeview::CPUType::X64;
+ case COFF::IMAGE_FILE_MACHINE_ARM:
+ return codeview::CPUType::ARM7;
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ return codeview::CPUType::ARM64;
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ return codeview::CPUType::ARMNT;
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ return codeview::CPUType::Intel80386;
+ default:
+ llvm_unreachable("Unsupported CPU Type");
+ }
+}
+
static void addCommonLinkerModuleSymbols(StringRef Path,
pdb::DbiModuleDescriptorBuilder &Mod,
BumpPtrAllocator &Allocator) {
@@ -863,7 +1047,7 @@ static void addCommonLinkerModuleSymbols(StringRef Path,
ONS.Name = "* Linker *";
ONS.Signature = 0;
- CS.Machine = Config->is64() ? CPUType::X64 : CPUType::Intel80386;
+ CS.Machine = toCodeViewMachine(Config->Machine);
// Interestingly, if we set the string to 0.0.0.0, then when trying to view
// local variables WinDbg emits an error that private symbols are not present.
// By setting this to a valid MSVC linker version string, local variables are
@@ -914,9 +1098,9 @@ static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod,
BumpPtrAllocator &Allocator) {
SectionSym Sym(SymbolRecordKind::SectionSym);
Sym.Alignment = 12; // 2^12 = 4KB
- Sym.Characteristics = OS.getCharacteristics();
+ Sym.Characteristics = OS.Header.Characteristics;
Sym.Length = OS.getVirtualSize();
- Sym.Name = OS.getName();
+ Sym.Name = OS.Name;
Sym.Rva = OS.getRVA();
Sym.SectionNumber = OS.SectionIndex;
Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
@@ -928,10 +1112,15 @@ void coff::createPDB(SymbolTable *Symtab,
ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo &BuildId) {
+ ScopedTimer T1(TotalPdbLinkTimer);
PDBLinker PDB(Symtab);
+
PDB.initialize(BuildId);
PDB.addObjectsToPDB();
PDB.addSections(OutputSections, SectionTable);
+ PDB.addNatvisFiles();
+
+ ScopedTimer T2(DiskCommitTimer);
PDB.commit();
}
@@ -945,44 +1134,22 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo &BuildId) {
// Add an Info stream.
auto &InfoBuilder = Builder.getInfoBuilder();
- InfoBuilder.setAge(BuildId.PDB70.Age);
-
GUID uuid;
memcpy(&uuid, &BuildId.PDB70.Signature, sizeof(uuid));
+ InfoBuilder.setAge(BuildId.PDB70.Age);
InfoBuilder.setGuid(uuid);
- InfoBuilder.setSignature(time(nullptr));
InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
// Add an empty DBI stream.
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setAge(BuildId.PDB70.Age);
DbiBuilder.setVersionHeader(pdb::PdbDbiV70);
- ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
-}
-
-void PDBLinker::addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
- OutputSection *OS, Chunk *C) {
- pdb::SectionContrib SC;
- memset(&SC, 0, sizeof(SC));
- SC.ISect = OS->SectionIndex;
- SC.Off = C->getRVA() - OS->getRVA();
- SC.Size = C->getSize();
- if (auto *SecChunk = dyn_cast<SectionChunk>(C)) {
- SC.Characteristics = SecChunk->Header->Characteristics;
- SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();
- ArrayRef<uint8_t> Contents = SecChunk->getContents();
- JamCRC CRC(0);
- ArrayRef<char> CharContents = makeArrayRef(
- reinterpret_cast<const char *>(Contents.data()), Contents.size());
- CRC.update(CharContents);
- SC.DataCrc = CRC.getCRC();
- } else {
- SC.Characteristics = OS->getCharacteristics();
- // FIXME: When we start creating DBI for import libraries, use those here.
- SC.Imod = LinkerModule.getModuleIndex();
- }
- SC.RelocCrc = 0; // FIXME
- Builder.getDbiBuilder().addSectionContrib(SC);
+ DbiBuilder.setMachineType(Config->Machine);
+ // Technically we are not link.exe 14.11, but there are known cases where
+ // debugging tools on Windows expect Microsoft-specific version numbers or
+ // they fail to work at all. Since we know we produce PDBs that are
+ // compatible with LINK 14.11, we set that version number here.
+ DbiBuilder.setBuildNumber(14, 11);
}
void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,
@@ -1000,8 +1167,11 @@ void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,
// Add section contributions. They must be ordered by ascending RVA.
for (OutputSection *OS : OutputSections) {
addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc);
- for (Chunk *C : OS->getChunks())
- addSectionContrib(LinkerModule, OS, C);
+ for (Chunk *C : OS->getChunks()) {
+ pdb::SectionContrib SC =
+ createSectionContrib(C, LinkerModule.getModuleIndex());
+ Builder.getDbiBuilder().addSectionContrib(SC);
+ }
}
// Add Section Map stream.
@@ -1020,3 +1190,145 @@ void PDBLinker::commit() {
// Write to a file.
ExitOnErr(Builder.commit(Config->PDBPath));
}
+
+static Expected<StringRef>
+getFileName(const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
+ auto Iter = Checksums.getArray().at(FileID);
+ if (Iter == Checksums.getArray().end())
+ return make_error<CodeViewError>(cv_error_code::no_records);
+ uint32_t Offset = Iter->FileNameOffset;
+ return Strings.getString(Offset);
+}
+
+static uint32_t getSecrelReloc() {
+ switch (Config->Machine) {
+ case AMD64:
+ return COFF::IMAGE_REL_AMD64_SECREL;
+ case I386:
+ return COFF::IMAGE_REL_I386_SECREL;
+ case ARMNT:
+ return COFF::IMAGE_REL_ARM_SECREL;
+ case ARM64:
+ return COFF::IMAGE_REL_ARM64_SECREL;
+ default:
+ llvm_unreachable("unknown machine type");
+ }
+}
+
+// Try to find a line table for the given offset Addr into the given chunk C.
+// If a line table was found, the line table, the string and checksum tables
+// that are used to interpret the line table, and the offset of Addr in the line
+// table are stored in the output arguments. Returns whether a line table was
+// found.
+static bool findLineTable(const SectionChunk *C, uint32_t Addr,
+ DebugStringTableSubsectionRef &CVStrTab,
+ DebugChecksumsSubsectionRef &Checksums,
+ DebugLinesSubsectionRef &Lines,
+ uint32_t &OffsetInLinetable) {
+ ExitOnError ExitOnErr;
+ uint32_t SecrelReloc = getSecrelReloc();
+
+ for (SectionChunk *DbgC : C->File->getDebugChunks()) {
+ if (DbgC->getSectionName() != ".debug$S")
+ continue;
+
+ // Build a mapping of SECREL relocations in DbgC that refer to C.
+ DenseMap<uint32_t, uint32_t> Secrels;
+ for (const coff_relocation &R : DbgC->Relocs) {
+ if (R.Type != SecrelReloc)
+ continue;
+
+ if (auto *S = dyn_cast_or_null<DefinedRegular>(
+ C->File->getSymbols()[R.SymbolTableIndex]))
+ if (S->getChunk() == C)
+ Secrels[R.VirtualAddress] = S->getValue();
+ }
+
+ ArrayRef<uint8_t> Contents =
+ consumeDebugMagic(DbgC->getContents(), ".debug$S");
+ DebugSubsectionArray Subsections;
+ BinaryStreamReader Reader(Contents, support::little);
+ ExitOnErr(Reader.readArray(Subsections, Contents.size()));
+
+ for (const DebugSubsectionRecord &SS : Subsections) {
+ switch (SS.kind()) {
+ case DebugSubsectionKind::StringTable: {
+ assert(!CVStrTab.valid() &&
+ "Encountered multiple string table subsections!");
+ ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
+ break;
+ }
+ case DebugSubsectionKind::FileChecksums:
+ assert(!Checksums.valid() &&
+ "Encountered multiple checksum subsections!");
+ ExitOnErr(Checksums.initialize(SS.getRecordData()));
+ break;
+ case DebugSubsectionKind::Lines: {
+ ArrayRef<uint8_t> Bytes;
+ auto Ref = SS.getRecordData();
+ ExitOnErr(Ref.readLongestContiguousChunk(0, Bytes));
+ size_t OffsetInDbgC = Bytes.data() - DbgC->getContents().data();
+
+ // Check whether this line table refers to C.
+ auto I = Secrels.find(OffsetInDbgC);
+ if (I == Secrels.end())
+ break;
+
+ // Check whether this line table covers Addr in C.
+ DebugLinesSubsectionRef LinesTmp;
+ ExitOnErr(LinesTmp.initialize(BinaryStreamReader(Ref)));
+ uint32_t OffsetInC = I->second + LinesTmp.header()->RelocOffset;
+ if (Addr < OffsetInC || Addr >= OffsetInC + LinesTmp.header()->CodeSize)
+ break;
+
+ assert(!Lines.header() &&
+ "Encountered multiple line tables for function!");
+ ExitOnErr(Lines.initialize(BinaryStreamReader(Ref)));
+ OffsetInLinetable = Addr - OffsetInC;
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (CVStrTab.valid() && Checksums.valid() && Lines.header())
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Use CodeView line tables to resolve a file and line number for the given
+// offset into the given chunk and return them, or {"", 0} if a line table was
+// not found.
+std::pair<StringRef, uint32_t> coff::getFileLine(const SectionChunk *C,
+ uint32_t Addr) {
+ ExitOnError ExitOnErr;
+
+ DebugStringTableSubsectionRef CVStrTab;
+ DebugChecksumsSubsectionRef Checksums;
+ DebugLinesSubsectionRef Lines;
+ uint32_t OffsetInLinetable;
+
+ if (!findLineTable(C, Addr, CVStrTab, Checksums, Lines, OffsetInLinetable))
+ return {"", 0};
+
+ uint32_t NameIndex;
+ uint32_t LineNumber;
+ for (LineColumnEntry &Entry : Lines) {
+ for (const LineNumberEntry &LN : Entry.LineNumbers) {
+ if (LN.Offset > OffsetInLinetable) {
+ StringRef Filename =
+ ExitOnErr(getFileName(CVStrTab, Checksums, NameIndex));
+ return {Filename, LineNumber};
+ }
+ LineInfo LI(LN.Flags);
+ NameIndex = Entry.NameIndex;
+ LineNumber = LI.getStartLine();
+ }
+ }
+ StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, NameIndex));
+ return {Filename, LineNumber};
+}
diff --git a/contrib/llvm/tools/lld/COFF/PDB.h b/contrib/llvm/tools/lld/COFF/PDB.h
index defd7d236790..a98d129a633b 100644
--- a/contrib/llvm/tools/lld/COFF/PDB.h
+++ b/contrib/llvm/tools/lld/COFF/PDB.h
@@ -22,12 +22,16 @@ union DebugInfo;
namespace lld {
namespace coff {
class OutputSection;
+class SectionChunk;
class SymbolTable;
void createPDB(SymbolTable *Symtab,
llvm::ArrayRef<OutputSection *> OutputSections,
llvm::ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo &BuildId);
+
+std::pair<llvm::StringRef, uint32_t> getFileLine(const SectionChunk *C,
+ uint32_t Addr);
}
}
diff --git a/contrib/llvm/tools/lld/COFF/Strings.cpp b/contrib/llvm/tools/lld/COFF/Strings.cpp
deleted file mode 100644
index 89b9c5186fd1..000000000000
--- a/contrib/llvm/tools/lld/COFF/Strings.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- Strings.cpp -------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Strings.h"
-#include <mutex>
-
-#if defined(_MSC_VER)
-#include <Windows.h>
-#include <DbgHelp.h>
-#pragma comment(lib, "dbghelp.lib")
-#endif
-
-using namespace lld;
-using namespace lld::coff;
-using namespace llvm;
-
-Optional<std::string> coff::demangleMSVC(StringRef S) {
-#if defined(_MSC_VER)
- // UnDecorateSymbolName is not thread-safe, so we need a mutex.
- static std::mutex Mu;
- std::lock_guard<std::mutex> Lock(Mu);
-
- char Buf[4096];
- if (S.startswith("?"))
- if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0))
- return std::string(Buf, Len);
-#endif
- return None;
-}
diff --git a/contrib/llvm/tools/lld/COFF/SymbolTable.cpp b/contrib/llvm/tools/lld/COFF/SymbolTable.cpp
index df76679535cb..b286d865caaf 100644
--- a/contrib/llvm/tools/lld/COFF/SymbolTable.cpp
+++ b/contrib/llvm/tools/lld/COFF/SymbolTable.cpp
@@ -11,9 +11,11 @@
#include "Config.h"
#include "Driver.h"
#include "LTO.h"
+#include "PDB.h"
#include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Timer.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -24,6 +26,8 @@ using namespace llvm;
namespace lld {
namespace coff {
+static Timer LTOTimer("LTO", Timer::root());
+
SymbolTable *Symtab;
void SymbolTable::addFile(InputFile *File) {
@@ -34,8 +38,9 @@ void SymbolTable::addFile(InputFile *File) {
if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
Config->Machine = MT;
} else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) {
- fatal(toString(File) + ": machine type " + machineToStr(MT) +
+ error(toString(File) + ": machine type " + machineToStr(MT) +
" conflicts with " + machineToStr(Config->Machine));
+ return;
}
if (auto *F = dyn_cast<ObjFile>(File)) {
@@ -61,6 +66,66 @@ static void errorOrWarn(const Twine &S) {
error(S);
}
+// Returns the name of the symbol in SC whose value is <= Addr that is closest
+// to Addr. This is generally the name of the global variable or function whose
+// definition contains Addr.
+static StringRef getSymbolName(SectionChunk *SC, uint32_t Addr) {
+ DefinedRegular *Candidate = nullptr;
+
+ for (Symbol *S : SC->File->getSymbols()) {
+ auto *D = dyn_cast_or_null<DefinedRegular>(S);
+ if (!D || D->getChunk() != SC || D->getValue() > Addr ||
+ (Candidate && D->getValue() < Candidate->getValue()))
+ continue;
+
+ Candidate = D;
+ }
+
+ if (!Candidate)
+ return "";
+ return Candidate->getName();
+}
+
+static std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) {
+ struct Location {
+ StringRef SymName;
+ std::pair<StringRef, uint32_t> FileLine;
+ };
+ std::vector<Location> Locations;
+
+ for (Chunk *C : File->getChunks()) {
+ auto *SC = dyn_cast<SectionChunk>(C);
+ if (!SC)
+ continue;
+ for (const coff_relocation &R : SC->Relocs) {
+ if (R.SymbolTableIndex != SymIndex)
+ continue;
+ std::pair<StringRef, uint32_t> FileLine =
+ getFileLine(SC, R.VirtualAddress);
+ StringRef SymName = getSymbolName(SC, R.VirtualAddress);
+ if (!FileLine.first.empty() || !SymName.empty())
+ Locations.push_back({SymName, FileLine});
+ }
+ }
+
+ if (Locations.empty())
+ return "\n>>> referenced by " + toString(File) + "\n";
+
+ std::string Out;
+ llvm::raw_string_ostream OS(Out);
+ for (Location Loc : Locations) {
+ OS << "\n>>> referenced by ";
+ if (!Loc.FileLine.first.empty())
+ OS << Loc.FileLine.first << ":" << Loc.FileLine.second
+ << "\n>>> ";
+ OS << toString(File);
+ if (!Loc.SymName.empty())
+ OS << ":(" << Loc.SymName << ')';
+ }
+ OS << '\n';
+ return OS.str();
+}
+
void SymbolTable::reportRemainingUndefines() {
SmallPtrSet<Symbol *, 8> Undefs;
DenseMap<Symbol *, Symbol *> LocalImports;
@@ -120,20 +185,23 @@ void SymbolTable::reportRemainingUndefines() {
if (Config->WarnLocallyDefinedImported)
if (Symbol *Imp = LocalImports.lookup(B))
warn("<root>: locally defined symbol imported: " + Imp->getName() +
- " (defined in " + toString(Imp->getFile()) + ")");
+ " (defined in " + toString(Imp->getFile()) + ") [LNK4217]");
}
for (ObjFile *File : ObjFile::Instances) {
+ size_t SymIndex = (size_t)-1;
for (Symbol *Sym : File->getSymbols()) {
+ ++SymIndex;
if (!Sym)
continue;
if (Undefs.count(Sym))
- errorOrWarn(toString(File) + ": undefined symbol: " + Sym->getName());
+ errorOrWarn("undefined symbol: " + Sym->getName() +
+ getSymbolLocations(File, SymIndex));
if (Config->WarnLocallyDefinedImported)
if (Symbol *Imp = LocalImports.lookup(Sym))
warn(toString(File) + ": locally defined symbol imported: " +
Imp->getName() + " (defined in " + toString(Imp->getFile()) +
- ")");
+ ") [LNK4217]");
}
}
}
@@ -142,7 +210,7 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
if (Sym)
return {Sym, false};
- Sym = (Symbol *)make<SymbolUnion>();
+ Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
Sym->IsUsedInRegularObj = false;
Sym->PendingArchiveLoad = false;
return {Sym, true};
@@ -274,30 +342,29 @@ Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,
return S;
}
-DefinedImportData *SymbolTable::addImportData(StringRef N, ImportFile *F) {
+Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(N);
S->IsUsedInRegularObj = true;
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
replaceSymbol<DefinedImportData>(S, N, F);
- return cast<DefinedImportData>(S);
+ return S;
}
reportDuplicate(S, F);
return nullptr;
}
-DefinedImportThunk *SymbolTable::addImportThunk(StringRef Name,
- DefinedImportData *ID,
- uint16_t Machine) {
+Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID,
+ uint16_t Machine) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
S->IsUsedInRegularObj = true;
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine);
- return cast<DefinedImportThunk>(S);
+ return S;
}
reportDuplicate(S, ID->File);
@@ -314,10 +381,7 @@ std::vector<Chunk *> SymbolTable::getChunks() {
}
Symbol *SymbolTable::find(StringRef Name) {
- auto It = SymMap.find(CachedHashStringRef(Name));
- if (It == SymMap.end())
- return nullptr;
- return It->second;
+ return SymMap.lookup(CachedHashStringRef(Name));
}
Symbol *SymbolTable::findUnderscore(StringRef Name) {
@@ -384,6 +448,8 @@ std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
void SymbolTable::addCombinedLTOObjects() {
if (BitcodeFile::Instances.empty())
return;
+
+ ScopedTimer T(LTOTimer);
for (StringRef Object : compileBitcodeFiles()) {
auto *Obj = make<ObjFile>(MemoryBufferRef(Object, "lto.tmp"));
Obj->parse();
diff --git a/contrib/llvm/tools/lld/COFF/SymbolTable.h b/contrib/llvm/tools/lld/COFF/SymbolTable.h
index 55481e6475bb..30cb1a5410c3 100644
--- a/contrib/llvm/tools/lld/COFF/SymbolTable.h
+++ b/contrib/llvm/tools/lld/COFF/SymbolTable.h
@@ -92,9 +92,9 @@ public:
Symbol *addCommon(InputFile *F, StringRef N, uint64_t Size,
const llvm::object::coff_symbol_generic *S = nullptr,
CommonChunk *C = nullptr);
- DefinedImportData *addImportData(StringRef N, ImportFile *F);
- DefinedImportThunk *addImportThunk(StringRef Name, DefinedImportData *S,
- uint16_t Machine);
+ Symbol *addImportData(StringRef N, ImportFile *F);
+ Symbol *addImportThunk(StringRef Name, DefinedImportData *S,
+ uint16_t Machine);
void reportDuplicate(Symbol *Existing, InputFile *NewFile);
diff --git a/contrib/llvm/tools/lld/COFF/Symbols.cpp b/contrib/llvm/tools/lld/COFF/Symbols.cpp
index 4c5ab48c7565..7c8b7d5e8fc5 100644
--- a/contrib/llvm/tools/lld/COFF/Symbols.cpp
+++ b/contrib/llvm/tools/lld/COFF/Symbols.cpp
@@ -9,9 +9,9 @@
#include "Symbols.h"
#include "InputFiles.h"
-#include "Strings.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -21,7 +21,7 @@ using namespace llvm::object;
// Returns a symbol name for an error message.
std::string lld::toString(coff::Symbol &B) {
- if (Optional<std::string> S = coff::demangleMSVC(B.getName()))
+ if (Optional<std::string> S = lld::demangleMSVC(B.getName()))
return ("\"" + *S + "\" (" + B.getName() + ")").str();
return B.getName();
}
@@ -58,7 +58,7 @@ bool Symbol::isLive() const {
if (auto *Imp = dyn_cast<DefinedImportData>(this))
return Imp->File->Live;
if (auto *Imp = dyn_cast<DefinedImportThunk>(this))
- return Imp->WrappedSym->File->Live;
+ return Imp->WrappedSym->File->ThunkLive;
// Assume any other kind of symbol is live.
return true;
}
@@ -71,7 +71,7 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
}
-uint16_t DefinedAbsolute::OutputSectionIndex = 0;
+uint16_t DefinedAbsolute::NumOutputSections;
static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
if (Machine == AMD64)
diff --git a/contrib/llvm/tools/lld/COFF/Symbols.h b/contrib/llvm/tools/lld/COFF/Symbols.h
index d8a030705e27..783965adbd9a 100644
--- a/contrib/llvm/tools/lld/COFF/Symbols.h
+++ b/contrib/llvm/tools/lld/COFF/Symbols.h
@@ -213,11 +213,10 @@ public:
uint64_t getRVA() { return VA - Config->ImageBase; }
void setVA(uint64_t V) { VA = V; }
- // The sentinel absolute symbol section index. Section index relocations
- // against absolute symbols resolve to this 16 bit number, and it is the
- // largest valid section index plus one. This is written by the Writer.
- static uint16_t OutputSectionIndex;
- uint16_t getSecIdx() { return OutputSectionIndex; }
+ // Section index relocations against absolute symbols resolve to
+ // this 16 bit number, and it is the largest valid section index
+ // plus one. This variable keeps it.
+ static uint16_t NumOutputSections;
private:
uint64_t VA;
@@ -416,6 +415,8 @@ union SymbolUnion {
template <typename T, typename... ArgT>
void replaceSymbol(Symbol *S, ArgT &&... Arg) {
+ static_assert(std::is_trivially_destructible<T>(),
+ "Symbol types must be trivially destructible");
static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
static_assert(alignof(T) <= alignof(SymbolUnion),
"SymbolUnion not aligned enough");
diff --git a/contrib/llvm/tools/lld/COFF/Writer.cpp b/contrib/llvm/tools/lld/COFF/Writer.cpp
index 584f0621bea3..d17405ec26ab 100644
--- a/contrib/llvm/tools/lld/COFF/Writer.cpp
+++ b/contrib/llvm/tools/lld/COFF/Writer.cpp
@@ -17,6 +17,7 @@
#include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Timer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -25,7 +26,9 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Parallel.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <cstdio>
#include <map>
@@ -40,8 +43,40 @@ using namespace llvm::support::endian;
using namespace lld;
using namespace lld::coff;
+/* To re-generate DOSProgram:
+$ cat > /tmp/DOSProgram.asm
+org 0
+ ; Copy cs to ds.
+ push cs
+ pop ds
+ ; Point ds:dx at the $-terminated string.
+ mov dx, str
+ ; Int 21/AH=09h: Write string to standard output.
+ mov ah, 0x9
+ int 0x21
+ ; Int 21/AH=4Ch: Exit with return code (in AL).
+ mov ax, 0x4C01
+ int 0x21
+str:
+ db 'This program cannot be run in DOS mode.$'
+align 8, db 0
+$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
+$ xxd -i /tmp/DOSProgram.bin
+*/
+static unsigned char DOSProgram[] = {
+ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,
+ 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
+ 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
+ 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
+ 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00
+};
+static_assert(sizeof(DOSProgram) % 8 == 0,
+ "DOSProgram size must be multiple of 8");
+
static const int SectorSize = 512;
-static const int DOSStubSize = 64;
+static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram);
+static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8");
+
static const int NumberfOfDataDirectory = 16;
namespace {
@@ -69,24 +104,25 @@ public:
uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA());
D->PointerToRawData = Offs;
+ TimeDateStamps.push_back(&D->TimeDateStamp);
++D;
}
}
+ void setTimeDateStamp(uint32_t TimeDateStamp) {
+ for (support::ulittle32_t *TDS : TimeDateStamps)
+ *TDS = TimeDateStamp;
+ }
+
private:
+ mutable std::vector<support::ulittle32_t *> TimeDateStamps;
const std::vector<Chunk *> &Records;
};
class CVDebugRecordChunk : public Chunk {
public:
- CVDebugRecordChunk() {
- PDBAbsPath = Config->PDBPath;
- if (!PDBAbsPath.empty())
- llvm::sys::fs::make_absolute(PDBAbsPath);
- }
-
size_t getSize() const override {
- return sizeof(codeview::DebugInfo) + PDBAbsPath.size() + 1;
+ return sizeof(codeview::DebugInfo) + Config->PDBAltPath.size() + 1;
}
void writeTo(uint8_t *B) const override {
@@ -96,12 +132,11 @@ public:
// variable sized field (PDB Path)
char *P = reinterpret_cast<char *>(B + OutputSectionOff + sizeof(*BuildId));
- if (!PDBAbsPath.empty())
- memcpy(P, PDBAbsPath.data(), PDBAbsPath.size());
- P[PDBAbsPath.size()] = '\0';
+ if (!Config->PDBAltPath.empty())
+ memcpy(P, Config->PDBAltPath.data(), Config->PDBAltPath.size());
+ P[Config->PDBAltPath.size()] = '\0';
}
- SmallString<128> PDBAbsPath;
mutable codeview::DebugInfo *BuildId = nullptr;
};
@@ -116,12 +151,19 @@ private:
void createMiscChunks();
void createImportTables();
void createExportTable();
+ void mergeSections();
void assignAddresses();
void removeEmptySections();
void createSymbolAndStringTable();
void openFile(StringRef OutputPath);
template <typename PEHeaderTy> void writeHeader();
- void createSEHTable(OutputSection *RData);
+ void createSEHTable();
+ void createGuardCFTables();
+ void markSymbolsForRVATable(ObjFile *File,
+ ArrayRef<SectionChunk *> SymIdxChunks,
+ SymbolRVASet &TableSymbols);
+ void maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,
+ StringRef CountSym);
void setSectionPermissions();
void writeSections();
void writeBuildId();
@@ -131,9 +173,8 @@ private:
size_t addEntryToStringTable(StringRef Str);
OutputSection *findSection(StringRef Name);
- OutputSection *createSection(StringRef Name);
- void addBaserels(OutputSection *Dest);
- void addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V);
+ void addBaserels();
+ void addBaserelBlocks(std::vector<Baserel> &V);
uint32_t getSizeOfInitializedData();
std::map<StringRef, std::vector<DefinedImportData *>> binImports();
@@ -145,9 +186,9 @@ private:
IdataContents Idata;
DelayLoadContents DelayIdata;
EdataContents Edata;
- SEHTableChunk *SEHTable = nullptr;
+ bool SetNoSEHCharacteristic = false;
- Chunk *DebugDirectory = nullptr;
+ DebugDirectoryChunk *DebugDirectory = nullptr;
std::vector<Chunk *> DebugRecords;
CVDebugRecordChunk *BuildId = nullptr;
Optional<codeview::DebugInfo> PreviousBuildId;
@@ -157,50 +198,55 @@ private:
uint32_t PointerToSymbolTable = 0;
uint64_t SizeOfImage;
uint64_t SizeOfHeaders;
+
+ OutputSection *TextSec;
+ OutputSection *RdataSec;
+ OutputSection *BuildidSec;
+ OutputSection *DataSec;
+ OutputSection *PdataSec;
+ OutputSection *IdataSec;
+ OutputSection *EdataSec;
+ OutputSection *DidatSec;
+ OutputSection *RsrcSec;
+ OutputSection *RelocSec;
+
+ // The first and last .pdata sections in the output file.
+ //
+ // We need to keep track of the location of .pdata in whichever section it
+ // gets merged into so that we can sort its contents and emit a correct data
+ // directory entry for the exception table. This is also the case for some
+ // other sections (such as .edata) but because the contents of those sections
+ // are entirely linker-generated we can keep track of their locations using
+ // the chunks that the linker creates. All .pdata chunks come from input
+ // files, so we need to keep track of them separately.
+ Chunk *FirstPdata = nullptr;
+ Chunk *LastPdata;
};
} // anonymous namespace
namespace lld {
namespace coff {
-void writeResult() { Writer().run(); }
-
-void OutputSection::setRVA(uint64_t RVA) {
- Header.VirtualAddress = RVA;
- for (Chunk *C : Chunks)
- C->setRVA(C->getRVA() + RVA);
-}
+static Timer CodeLayoutTimer("Code Layout", Timer::root());
+static Timer DiskCommitTimer("Commit Output File", Timer::root());
-void OutputSection::setFileOffset(uint64_t Off) {
- // If a section has no actual data (i.e. BSS section), we want to
- // set 0 to its PointerToRawData. Otherwise the output is rejected
- // by the loader.
- if (Header.SizeOfRawData == 0)
- return;
- Header.PointerToRawData = Off;
-}
+void writeResult() { Writer().run(); }
void OutputSection::addChunk(Chunk *C) {
Chunks.push_back(C);
C->setOutputSection(this);
- uint64_t Off = Header.VirtualSize;
- Off = alignTo(Off, C->Alignment);
- C->setRVA(Off);
- C->OutputSectionOff = Off;
- Off += C->getSize();
- if (Off > UINT32_MAX)
- error("section larger than 4 GiB: " + Name);
- Header.VirtualSize = Off;
- if (C->hasData())
- Header.SizeOfRawData = alignTo(Off, SectorSize);
}
-void OutputSection::addPermissions(uint32_t C) {
- Header.Characteristics |= C & PermMask;
+void OutputSection::setPermissions(uint32_t C) {
+ Header.Characteristics &= ~PermMask;
+ Header.Characteristics |= C;
}
-void OutputSection::setPermissions(uint32_t C) {
- Header.Characteristics = C & PermMask;
+void OutputSection::merge(OutputSection *Other) {
+ for (Chunk *C : Other->Chunks)
+ C->setOutputSection(this);
+ Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end());
+ Other->Chunks.clear();
}
// Write the section header to a given buffer.
@@ -284,17 +330,22 @@ static Optional<codeview::DebugInfo> loadExistingBuildId(StringRef Path) {
// The main function of the writer.
void Writer::run() {
+ ScopedTimer T1(CodeLayoutTimer);
+
createSections();
createMiscChunks();
createImportTables();
createExportTable();
- if (Config->Relocatable)
- createSection(".reloc");
+ mergeSections();
assignAddresses();
removeEmptySections();
setSectionPermissions();
createSymbolAndStringTable();
+ if (FileSize > UINT32_MAX)
+ fatal("image size (" + Twine(FileSize) + ") " +
+ "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")");
+
// We must do this before opening the output file, as it depends on being able
// to read the contents of the existing output file.
PreviousBuildId = loadExistingBuildId(Config->OutputFile);
@@ -308,35 +359,79 @@ void Writer::run() {
sortExceptionTable();
writeBuildId();
- if (!Config->PDBPath.empty() && Config->Debug) {
+ T1.stop();
+ if (!Config->PDBPath.empty() && Config->Debug) {
assert(BuildId);
createPDB(Symtab, OutputSections, SectionTable, *BuildId->BuildId);
}
writeMapFile(OutputSections);
+ ScopedTimer T2(DiskCommitTimer);
if (auto E = Buffer->commit())
fatal("failed to write the output file: " + toString(std::move(E)));
}
-static StringRef getOutputSection(StringRef Name) {
+static StringRef getOutputSectionName(StringRef Name) {
StringRef S = Name.split('$').first;
// Treat a later period as a separator for MinGW, for sections like
// ".ctors.01234".
- S = S.substr(0, S.find('.', 1));
+ return S.substr(0, S.find('.', 1));
+}
- auto It = Config->Merge.find(S);
- if (It == Config->Merge.end())
- return S;
- return It->second;
+// For /order.
+static void sortBySectionOrder(std::vector<Chunk *> &Chunks) {
+ auto GetPriority = [](const Chunk *C) {
+ if (auto *Sec = dyn_cast<SectionChunk>(C))
+ if (Sec->Sym)
+ return Config->Order.lookup(Sec->Sym->getName());
+ return 0;
+ };
+
+ std::stable_sort(Chunks.begin(), Chunks.end(),
+ [=](const Chunk *A, const Chunk *B) {
+ return GetPriority(A) < GetPriority(B);
+ });
}
// Create output section objects and add them to OutputSections.
void Writer::createSections() {
- // First, bin chunks by name.
- std::map<StringRef, std::vector<Chunk *>> Map;
+ // First, create the builtin sections.
+ const uint32_t DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
+ const uint32_t BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ const uint32_t CODE = IMAGE_SCN_CNT_CODE;
+ const uint32_t DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
+ const uint32_t R = IMAGE_SCN_MEM_READ;
+ const uint32_t W = IMAGE_SCN_MEM_WRITE;
+ const uint32_t X = IMAGE_SCN_MEM_EXECUTE;
+
+ SmallDenseMap<std::pair<StringRef, uint32_t>, OutputSection *> Sections;
+ auto CreateSection = [&](StringRef Name, uint32_t OutChars) {
+ OutputSection *&Sec = Sections[{Name, OutChars}];
+ if (!Sec) {
+ Sec = make<OutputSection>(Name, OutChars);
+ OutputSections.push_back(Sec);
+ }
+ return Sec;
+ };
+
+ // Try to match the section order used by link.exe.
+ TextSec = CreateSection(".text", CODE | R | X);
+ CreateSection(".bss", BSS | R | W);
+ RdataSec = CreateSection(".rdata", DATA | R);
+ BuildidSec = CreateSection(".buildid", DATA | R);
+ DataSec = CreateSection(".data", DATA | R | W);
+ PdataSec = CreateSection(".pdata", DATA | R);
+ IdataSec = CreateSection(".idata", DATA | R);
+ EdataSec = CreateSection(".edata", DATA | R);
+ DidatSec = CreateSection(".didat", DATA | R);
+ RsrcSec = CreateSection(".rsrc", DATA | R);
+ RelocSec = CreateSection(".reloc", DATA | DISCARDABLE | R);
+
+ // Then bin chunks by name and output characteristics.
+ std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> Map;
for (Chunk *C : Symtab->getChunks()) {
auto *SC = dyn_cast<SectionChunk>(C);
if (SC && !SC->isLive()) {
@@ -344,42 +439,71 @@ void Writer::createSections() {
SC->printDiscardedMessage();
continue;
}
- Map[C->getSectionName()].push_back(C);
+ Map[{C->getSectionName(), C->getOutputCharacteristics()}].push_back(C);
}
+ // Process an /order option.
+ if (!Config->Order.empty())
+ for (auto &Pair : Map)
+ sortBySectionOrder(Pair.second);
+
// Then create an OutputSection for each section.
// '$' and all following characters in input section names are
// discarded when determining output section. So, .text$foo
// contributes to .text, for example. See PE/COFF spec 3.2.
- SmallDenseMap<StringRef, OutputSection *> Sections;
for (auto Pair : Map) {
- StringRef Name = getOutputSection(Pair.first);
- OutputSection *&Sec = Sections[Name];
- if (!Sec) {
- Sec = make<OutputSection>(Name);
- OutputSections.push_back(Sec);
- }
+ StringRef Name = getOutputSectionName(Pair.first.first);
+ uint32_t OutChars = Pair.first.second;
+
+ // In link.exe, there is a special case for the I386 target where .CRT
+ // sections are treated as if they have output characteristics DATA | R if
+ // their characteristics are DATA | R | W. This implements the same special
+ // case for all architectures.
+ if (Name == ".CRT")
+ OutChars = DATA | R;
+
+ OutputSection *Sec = CreateSection(Name, OutChars);
std::vector<Chunk *> &Chunks = Pair.second;
- for (Chunk *C : Chunks) {
+ for (Chunk *C : Chunks)
Sec->addChunk(C);
- Sec->addPermissions(C->getPermissions());
- }
}
+
+ // Finally, move some output sections to the end.
+ auto SectionOrder = [&](OutputSection *S) {
+ // Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
+ // the loader cannot handle holes. Stripping can remove other discardable ones
+ // than .reloc, which is first of them (created early).
+ if (S->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
+ return 2;
+ // .rsrc should come at the end of the non-discardable sections because its
+ // size may change by the Win32 UpdateResources() function, causing
+ // subsequent sections to move (see https://crbug.com/827082).
+ if (S == RsrcSec)
+ return 1;
+ return 0;
+ };
+ std::stable_sort(OutputSections.begin(), OutputSections.end(),
+ [&](OutputSection *S, OutputSection *T) {
+ return SectionOrder(S) < SectionOrder(T);
+ });
}
void Writer::createMiscChunks() {
- OutputSection *RData = createSection(".rdata");
+ for (auto &P : MergeChunk::Instances)
+ RdataSec->addChunk(P.second);
// Create thunks for locally-dllimported symbols.
if (!Symtab->LocalImportChunks.empty()) {
for (Chunk *C : Symtab->LocalImportChunks)
- RData->addChunk(C);
+ RdataSec->addChunk(C);
}
// Create Debug Information Chunks
if (Config->Debug) {
DebugDirectory = make<DebugDirectoryChunk>(DebugRecords);
+ OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;
+
// Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We
// output a PDB no matter what, and this chunk provides the only means of
// allowing a debugger to match a PDB and an executable. So we need it even
@@ -388,12 +512,18 @@ void Writer::createMiscChunks() {
BuildId = CVChunk;
DebugRecords.push_back(CVChunk);
- RData->addChunk(DebugDirectory);
+ DebugInfoSec->addChunk(DebugDirectory);
for (Chunk *C : DebugRecords)
- RData->addChunk(C);
+ DebugInfoSec->addChunk(C);
}
- createSEHTable(RData);
+ // Create SEH table. x86-only.
+ if (Config->Machine == I386)
+ createSEHTable();
+
+ // Create /guard:cf tables if requested.
+ if (Config->GuardCF != GuardCFLevel::Off)
+ createGuardCFTables();
}
// Create .idata section for the DLL-imported symbol table.
@@ -414,53 +544,49 @@ void Writer::createImportTables() {
std::string DLL = StringRef(File->DLLName).lower();
if (Config->DLLOrder.count(DLL) == 0)
Config->DLLOrder[DLL] = Config->DLLOrder.size();
- }
- OutputSection *Text = createSection(".text");
- for (ImportFile *File : ImportFile::Instances) {
- if (!File->Live)
- continue;
-
- if (DefinedImportThunk *Thunk = File->ThunkSym)
- Text->addChunk(Thunk->getChunk());
+ if (File->ThunkSym) {
+ if (!isa<DefinedImportThunk>(File->ThunkSym))
+ fatal(toString(*File->ThunkSym) + " was replaced");
+ DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym);
+ if (File->ThunkLive)
+ TextSec->addChunk(Thunk->getChunk());
+ }
+ if (File->ImpSym && !isa<DefinedImportData>(File->ImpSym))
+ fatal(toString(*File->ImpSym) + " was replaced");
+ DefinedImportData *ImpSym = cast_or_null<DefinedImportData>(File->ImpSym);
if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) {
if (!File->ThunkSym)
fatal("cannot delay-load " + toString(File) +
- " due to import of data: " + toString(*File->ImpSym));
- DelayIdata.add(File->ImpSym);
+ " due to import of data: " + toString(*ImpSym));
+ DelayIdata.add(ImpSym);
} else {
- Idata.add(File->ImpSym);
+ Idata.add(ImpSym);
}
}
- if (!Idata.empty()) {
- OutputSection *Sec = createSection(".idata");
+ if (!Idata.empty())
for (Chunk *C : Idata.getChunks())
- Sec->addChunk(C);
- }
+ IdataSec->addChunk(C);
if (!DelayIdata.empty()) {
Defined *Helper = cast<Defined>(Config->DelayLoadHelper);
DelayIdata.create(Helper);
- OutputSection *Sec = createSection(".didat");
for (Chunk *C : DelayIdata.getChunks())
- Sec->addChunk(C);
- Sec = createSection(".data");
+ DidatSec->addChunk(C);
for (Chunk *C : DelayIdata.getDataChunks())
- Sec->addChunk(C);
- Sec = createSection(".text");
+ DataSec->addChunk(C);
for (Chunk *C : DelayIdata.getCodeChunks())
- Sec->addChunk(C);
+ TextSec->addChunk(C);
}
}
void Writer::createExportTable() {
if (Config->Exports.empty())
return;
- OutputSection *Sec = createSection(".edata");
for (Chunk *C : Edata.Chunks)
- Sec->addChunk(C);
+ EdataSec->addChunk(C);
}
// The Windows loader doesn't seem to like empty sections,
@@ -484,19 +610,31 @@ size_t Writer::addEntryToStringTable(StringRef Str) {
}
Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
- // Relative symbols are unrepresentable in a COFF symbol table.
- if (isa<DefinedSynthetic>(Def))
- return None;
-
- // Don't write dead symbols or symbols in codeview sections to the symbol
- // table.
- if (!Def->isLive())
+ coff_symbol16 Sym;
+ switch (Def->kind()) {
+ case Symbol::DefinedAbsoluteKind:
+ Sym.Value = Def->getRVA();
+ Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
+ break;
+ case Symbol::DefinedSyntheticKind:
+ // Relative symbols are unrepresentable in a COFF symbol table.
return None;
- if (auto *D = dyn_cast<DefinedRegular>(Def))
- if (D->getChunk()->isCodeView())
+ default: {
+ // Don't write symbols that won't be written to the output to the symbol
+ // table.
+ Chunk *C = Def->getChunk();
+ if (!C)
+ return None;
+ OutputSection *OS = C->getOutputSection();
+ if (!OS)
return None;
- coff_symbol16 Sym;
+ Sym.Value = Def->getRVA() - OS->getRVA();
+ Sym.SectionNumber = OS->SectionIndex;
+ break;
+ }
+ }
+
StringRef Name = Def->getName();
if (Name.size() > COFF::NameSize) {
Sym.Name.Offset.Zeroes = 0;
@@ -515,46 +653,27 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
}
Sym.NumberOfAuxSymbols = 0;
-
- switch (Def->kind()) {
- case Symbol::DefinedAbsoluteKind:
- Sym.Value = Def->getRVA();
- Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
- break;
- default: {
- uint64_t RVA = Def->getRVA();
- OutputSection *Sec = nullptr;
- for (OutputSection *S : OutputSections) {
- if (S->getRVA() > RVA)
- break;
- Sec = S;
- }
- Sym.Value = RVA - Sec->getRVA();
- Sym.SectionNumber = Sec->SectionIndex;
- break;
- }
- }
return Sym;
}
void Writer::createSymbolAndStringTable() {
- // Name field in the section table is 8 byte long. Longer names need
- // to be written to the string table. First, construct string table.
+ // PE/COFF images are limited to 8 byte section names. Longer names can be
+ // supported by writing a non-standard string table, but this string table is
+ // not mapped at runtime and the long names will therefore be inaccessible.
+ // link.exe always truncates section names to 8 bytes, whereas binutils always
+ // preserves long section names via the string table. LLD adopts a hybrid
+ // solution where discardable sections have long names preserved and
+ // non-discardable sections have their names truncated, to ensure that any
+ // section which is mapped at runtime also has its name mapped at runtime.
for (OutputSection *Sec : OutputSections) {
- StringRef Name = Sec->getName();
- if (Name.size() <= COFF::NameSize)
+ if (Sec->Name.size() <= COFF::NameSize)
continue;
- // If a section isn't discardable (i.e. will be mapped at runtime),
- // prefer a truncated section name over a long section name in
- // the string table that is unavailable at runtime. This is different from
- // what link.exe does, but finding ".eh_fram" instead of "/4" is useful
- // to libunwind.
- if ((Sec->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0)
+ if ((Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)
continue;
- Sec->setStringTableOff(addEntryToStringTable(Name));
+ Sec->setStringTableOff(addEntryToStringTable(Sec->Name));
}
- if (Config->DebugDwarf) {
+ if (Config->DebugDwarf || Config->DebugSymtab) {
for (ObjFile *File : ObjFile::Instances) {
for (Symbol *B : File->getSymbols()) {
auto *D = dyn_cast_or_null<Defined>(B);
@@ -571,16 +690,45 @@ void Writer::createSymbolAndStringTable() {
if (OutputSymtab.empty() && Strtab.empty())
return;
- OutputSection *LastSection = OutputSections.back();
// We position the symbol table to be adjacent to the end of the last section.
- uint64_t FileOff = LastSection->getFileOff() +
- alignTo(LastSection->getRawSize(), SectorSize);
+ uint64_t FileOff = FileSize;
PointerToSymbolTable = FileOff;
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
FileOff += 4 + Strtab.size();
FileSize = alignTo(FileOff, SectorSize);
}
+void Writer::mergeSections() {
+ if (!PdataSec->getChunks().empty()) {
+ FirstPdata = PdataSec->getChunks().front();
+ LastPdata = PdataSec->getChunks().back();
+ }
+
+ for (auto &P : Config->Merge) {
+ StringRef ToName = P.second;
+ if (P.first == ToName)
+ continue;
+ StringSet<> Names;
+ while (1) {
+ if (!Names.insert(ToName).second)
+ fatal("/merge: cycle found for section '" + P.first + "'");
+ auto I = Config->Merge.find(ToName);
+ if (I == Config->Merge.end())
+ break;
+ ToName = I->second;
+ }
+ OutputSection *From = findSection(P.first);
+ OutputSection *To = findSection(ToName);
+ if (!From)
+ continue;
+ if (!To) {
+ From->Name = ToName;
+ continue;
+ }
+ To->merge(From);
+ }
+}
+
// Visits all sections to assign incremental, non-overlapping RVAs and
// file offsets.
void Writer::assignAddresses() {
@@ -590,35 +738,57 @@ void Writer::assignAddresses() {
SizeOfHeaders +=
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
SizeOfHeaders = alignTo(SizeOfHeaders, SectorSize);
- uint64_t RVA = 0x1000; // The first page is kept unmapped.
+ uint64_t RVA = PageSize; // The first page is kept unmapped.
FileSize = SizeOfHeaders;
- // Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
- // the loader cannot handle holes.
- std::stable_partition(
- OutputSections.begin(), OutputSections.end(), [](OutputSection *S) {
- return (S->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0;
- });
+
for (OutputSection *Sec : OutputSections) {
- if (Sec->getName() == ".reloc")
- addBaserels(Sec);
- Sec->setRVA(RVA);
- Sec->setFileOffset(FileSize);
- RVA += alignTo(Sec->getVirtualSize(), PageSize);
- FileSize += alignTo(Sec->getRawSize(), SectorSize);
+ if (Sec == RelocSec)
+ addBaserels();
+ uint64_t RawSize = 0, VirtualSize = 0;
+ Sec->Header.VirtualAddress = RVA;
+ for (Chunk *C : Sec->getChunks()) {
+ VirtualSize = alignTo(VirtualSize, C->Alignment);
+ C->setRVA(RVA + VirtualSize);
+ C->OutputSectionOff = VirtualSize;
+ C->finalizeContents();
+ VirtualSize += C->getSize();
+ if (C->hasData())
+ RawSize = alignTo(VirtualSize, SectorSize);
+ }
+ if (VirtualSize > UINT32_MAX)
+ error("section larger than 4 GiB: " + Sec->Name);
+ Sec->Header.VirtualSize = VirtualSize;
+ Sec->Header.SizeOfRawData = RawSize;
+ if (RawSize != 0)
+ Sec->Header.PointerToRawData = FileSize;
+ RVA += alignTo(VirtualSize, PageSize);
+ FileSize += alignTo(RawSize, SectorSize);
}
SizeOfImage = alignTo(RVA, PageSize);
}
template <typename PEHeaderTy> void Writer::writeHeader() {
- // Write DOS stub
+ // Write DOS header. For backwards compatibility, the first part of a PE/COFF
+ // executable consists of an MS-DOS MZ executable. If the executable is run
+ // under DOS, that program gets run (usually to just print an error message).
+ // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
+ // the PE header instead.
uint8_t *Buf = Buffer->getBufferStart();
auto *DOS = reinterpret_cast<dos_header *>(Buf);
- Buf += DOSStubSize;
+ Buf += sizeof(dos_header);
DOS->Magic[0] = 'M';
DOS->Magic[1] = 'Z';
+ DOS->UsedBytesInTheLastPage = DOSStubSize % 512;
+ DOS->FileSizeInPages = divideCeil(DOSStubSize, 512);
+ DOS->HeaderSizeInParagraphs = sizeof(dos_header) / 16;
+
DOS->AddressOfRelocationTable = sizeof(dos_header);
DOS->AddressOfNewExeHeader = DOSStubSize;
+ // Write DOS program.
+ memcpy(Buf, DOSProgram, sizeof(DOSProgram));
+ Buf += sizeof(DOSProgram);
+
// Write PE magic
memcpy(Buf, PEMagic, sizeof(PEMagic));
Buf += sizeof(PEMagic);
@@ -688,24 +858,27 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
if (!Config->AllowIsolation)
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
- if (Config->Machine == I386 && !SEHTable &&
- !Symtab->findUnderscore("_load_config_used"))
+ if (Config->GuardCF != GuardCFLevel::Off)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
+ if (Config->IntegrityCheck)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
+ if (SetNoSEHCharacteristic)
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
if (Config->TerminalServerAware)
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
PE->NumberOfRvaAndSize = NumberfOfDataDirectory;
- if (OutputSection *Text = findSection(".text")) {
- PE->BaseOfCode = Text->getRVA();
- PE->SizeOfCode = Text->getRawSize();
+ if (TextSec->getVirtualSize()) {
+ PE->BaseOfCode = TextSec->getRVA();
+ PE->SizeOfCode = TextSec->getRawSize();
}
PE->SizeOfInitializedData = getSizeOfInitializedData();
// Write data directory
auto *Dir = reinterpret_cast<data_directory *>(Buf);
Buf += sizeof(*Dir) * NumberfOfDataDirectory;
- if (OutputSection *Sec = findSection(".edata")) {
- Dir[EXPORT_TABLE].RelativeVirtualAddress = Sec->getRVA();
- Dir[EXPORT_TABLE].Size = Sec->getVirtualSize();
+ if (!Config->Exports.empty()) {
+ Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata.getRVA();
+ Dir[EXPORT_TABLE].Size = Edata.getSize();
}
if (!Idata.empty()) {
Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA();
@@ -713,17 +886,18 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
Dir[IAT].RelativeVirtualAddress = Idata.getIATRVA();
Dir[IAT].Size = Idata.getIATSize();
}
- if (OutputSection *Sec = findSection(".rsrc")) {
- Dir[RESOURCE_TABLE].RelativeVirtualAddress = Sec->getRVA();
- Dir[RESOURCE_TABLE].Size = Sec->getVirtualSize();
+ if (RsrcSec->getVirtualSize()) {
+ Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA();
+ Dir[RESOURCE_TABLE].Size = RsrcSec->getVirtualSize();
}
- if (OutputSection *Sec = findSection(".pdata")) {
- Dir[EXCEPTION_TABLE].RelativeVirtualAddress = Sec->getRVA();
- Dir[EXCEPTION_TABLE].Size = Sec->getVirtualSize();
+ if (FirstPdata) {
+ Dir[EXCEPTION_TABLE].RelativeVirtualAddress = FirstPdata->getRVA();
+ Dir[EXCEPTION_TABLE].Size =
+ LastPdata->getRVA() + LastPdata->getSize() - FirstPdata->getRVA();
}
- if (OutputSection *Sec = findSection(".reloc")) {
- Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = Sec->getRVA();
- Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
+ if (RelocSec->getVirtualSize()) {
+ Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = RelocSec->getRVA();
+ Dir[BASE_RELOCATION_TABLE].Size = RelocSec->getVirtualSize();
}
if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {
if (Defined *B = dyn_cast<Defined>(Sym)) {
@@ -792,35 +966,172 @@ void Writer::openFile(StringRef Path) {
"failed to open " + Path);
}
-void Writer::createSEHTable(OutputSection *RData) {
- // Create SEH table. x86-only.
- if (Config->Machine != I386)
- return;
-
- std::set<Defined *> Handlers;
+void Writer::createSEHTable() {
+ // Set the no SEH characteristic on x86 binaries unless we find exception
+ // handlers.
+ SetNoSEHCharacteristic = true;
+ SymbolRVASet Handlers;
for (ObjFile *File : ObjFile::Instances) {
- if (!File->SEHCompat)
+ // FIXME: We should error here instead of earlier unless /safeseh:no was
+ // passed.
+ if (!File->hasSafeSEH())
return;
- for (uint32_t I : File->SXData)
- if (Symbol *B = File->getSymbol(I))
- if (B->isLive())
- Handlers.insert(cast<Defined>(B));
+
+ markSymbolsForRVATable(File, File->getSXDataChunks(), Handlers);
+ }
+
+ // Remove the "no SEH" characteristic if all object files were built with
+ // safeseh, we found some exception handlers, and there is a load config in
+ // the object.
+ SetNoSEHCharacteristic =
+ Handlers.empty() || !Symtab->findUnderscore("_load_config_used");
+
+ maybeAddRVATable(std::move(Handlers), "__safe_se_handler_table",
+ "__safe_se_handler_count");
+}
+
+// Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set
+// cannot contain duplicates. Therefore, the set is uniqued by Chunk and the
+// symbol's offset into that Chunk.
+static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) {
+ Chunk *C = S->getChunk();
+ if (auto *SC = dyn_cast<SectionChunk>(C))
+ C = SC->Repl; // Look through ICF replacement.
+ uint32_t Off = S->getRVA() - (C ? C->getRVA() : 0);
+ RVASet.insert({C, Off});
+}
+
+// Visit all relocations from all section contributions of this object file and
+// mark the relocation target as address-taken.
+static void markSymbolsWithRelocations(ObjFile *File,
+ SymbolRVASet &UsedSymbols) {
+ for (Chunk *C : File->getChunks()) {
+ // We only care about live section chunks. Common chunks and other chunks
+ // don't generally contain relocations.
+ SectionChunk *SC = dyn_cast<SectionChunk>(C);
+ if (!SC || !SC->isLive())
+ continue;
+
+ // Look for relocations in this section against symbols in executable output
+ // sections.
+ for (Symbol *Ref : SC->symbols()) {
+ // FIXME: Do further testing to see if the relocation type matters,
+ // especially for 32-bit where taking the address of something usually
+ // uses an absolute relocation instead of a relative one.
+ if (auto *D = dyn_cast_or_null<Defined>(Ref)) {
+ Chunk *RefChunk = D->getChunk();
+ OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr;
+ if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ addSymbolToRVASet(UsedSymbols, D);
+ }
+ }
+ }
+}
+
+// Create the guard function id table. This is a table of RVAs of all
+// address-taken functions. It is sorted and uniqued, just like the safe SEH
+// table.
+void Writer::createGuardCFTables() {
+ SymbolRVASet AddressTakenSyms;
+ SymbolRVASet LongJmpTargets;
+ for (ObjFile *File : ObjFile::Instances) {
+ // If the object was compiled with /guard:cf, the address taken symbols
+ // are in .gfids$y sections, and the longjmp targets are in .gljmp$y
+ // sections. If the object was not compiled with /guard:cf, we assume there
+ // were no setjmp targets, and that all code symbols with relocations are
+ // possibly address-taken.
+ if (File->hasGuardCF()) {
+ markSymbolsForRVATable(File, File->getGuardFidChunks(), AddressTakenSyms);
+ markSymbolsForRVATable(File, File->getGuardLJmpChunks(), LongJmpTargets);
+ } else {
+ markSymbolsWithRelocations(File, AddressTakenSyms);
+ }
+ }
+
+ // Mark the image entry as address-taken.
+ if (Config->Entry)
+ addSymbolToRVASet(AddressTakenSyms, cast<Defined>(Config->Entry));
+
+ // Ensure sections referenced in the gfid table are 16-byte aligned.
+ for (const ChunkAndOffset &C : AddressTakenSyms)
+ if (C.InputChunk->Alignment < 16)
+ C.InputChunk->Alignment = 16;
+
+ maybeAddRVATable(std::move(AddressTakenSyms), "__guard_fids_table",
+ "__guard_fids_count");
+
+ // Add the longjmp target table unless the user told us not to.
+ if (Config->GuardCF == GuardCFLevel::Full)
+ maybeAddRVATable(std::move(LongJmpTargets), "__guard_longjmp_table",
+ "__guard_longjmp_count");
+
+ // Set __guard_flags, which will be used in the load config to indicate that
+ // /guard:cf was enabled.
+ uint32_t GuardFlags = uint32_t(coff_guard_flags::CFInstrumented) |
+ uint32_t(coff_guard_flags::HasFidTable);
+ if (Config->GuardCF == GuardCFLevel::Full)
+ GuardFlags |= uint32_t(coff_guard_flags::HasLongJmpTable);
+ Symbol *FlagSym = Symtab->findUnderscore("__guard_flags");
+ cast<DefinedAbsolute>(FlagSym)->setVA(GuardFlags);
+}
+
+// Take a list of input sections containing symbol table indices and add those
+// symbols to an RVA table. The challenge is that symbol RVAs are not known and
+// depend on the table size, so we can't directly build a set of integers.
+void Writer::markSymbolsForRVATable(ObjFile *File,
+ ArrayRef<SectionChunk *> SymIdxChunks,
+ SymbolRVASet &TableSymbols) {
+ for (SectionChunk *C : SymIdxChunks) {
+ // Skip sections discarded by linker GC. This comes up when a .gfids section
+ // is associated with something like a vtable and the vtable is discarded.
+ // In this case, the associated gfids section is discarded, and we don't
+ // mark the virtual member functions as address-taken by the vtable.
+ if (!C->isLive())
+ continue;
+
+ // Validate that the contents look like symbol table indices.
+ ArrayRef<uint8_t> Data = C->getContents();
+ if (Data.size() % 4 != 0) {
+ warn("ignoring " + C->getSectionName() +
+ " symbol table index section in object " + toString(File));
+ continue;
+ }
+
+ // Read each symbol table index and check if that symbol was included in the
+ // final link. If so, add it to the table symbol set.
+ ArrayRef<ulittle32_t> SymIndices(
+ reinterpret_cast<const ulittle32_t *>(Data.data()), Data.size() / 4);
+ ArrayRef<Symbol *> ObjSymbols = File->getSymbols();
+ for (uint32_t SymIndex : SymIndices) {
+ if (SymIndex >= ObjSymbols.size()) {
+ warn("ignoring invalid symbol table index in section " +
+ C->getSectionName() + " in object " + toString(File));
+ continue;
+ }
+ if (Symbol *S = ObjSymbols[SymIndex]) {
+ if (S->isLive())
+ addSymbolToRVASet(TableSymbols, cast<Defined>(S));
+ }
+ }
}
+}
- if (Handlers.empty())
+// Replace the absolute table symbol with a synthetic symbol pointing to
+// TableChunk so that we can emit base relocations for it and resolve section
+// relative relocations.
+void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,
+ StringRef CountSym) {
+ if (TableSymbols.empty())
return;
- SEHTable = make<SEHTableChunk>(Handlers);
- RData->addChunk(SEHTable);
+ RVATableChunk *TableChunk = make<RVATableChunk>(std::move(TableSymbols));
+ RdataSec->addChunk(TableChunk);
- // Replace the absolute table symbol with a synthetic symbol pointing to the
- // SEHTable chunk so that we can emit base relocations for it and resolve
- // section relative relocations.
- Symbol *T = Symtab->find("___safe_se_handler_table");
- Symbol *C = Symtab->find("___safe_se_handler_count");
- replaceSymbol<DefinedSynthetic>(T, T->getName(), SEHTable);
- cast<DefinedAbsolute>(C)->setVA(SEHTable->getSize() / 4);
+ Symbol *T = Symtab->findUnderscore(TableSym);
+ Symbol *C = Symtab->findUnderscore(CountSym);
+ replaceSymbol<DefinedSynthetic>(T, T->getName(), TableChunk);
+ cast<DefinedAbsolute>(C)->setVA(TableChunk->getSize() / 4);
}
// Handles /section options to allow users to overwrite
@@ -829,16 +1140,17 @@ void Writer::setSectionPermissions() {
for (auto &P : Config->Section) {
StringRef Name = P.first;
uint32_t Perm = P.second;
- if (auto *Sec = findSection(Name))
- Sec->setPermissions(Perm);
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->Name == Name)
+ Sec->setPermissions(Perm);
}
}
// Write section contents to a mmap'ed file.
void Writer::writeSections() {
- // Record the section index that should be used when resolving a section
- // relocation against an absolute symbol.
- DefinedAbsolute::OutputSectionIndex = OutputSections.size() + 1;
+ // Record the number of sections to apply section index relocations
+ // against absolute symbols. See applySecIdx in Chunks.cpp..
+ DefinedAbsolute::NumOutputSections = OutputSections.size();
uint8_t *Buf = Buffer->getBufferStart();
for (OutputSection *Sec : OutputSections) {
@@ -846,7 +1158,7 @@ void Writer::writeSections() {
// Fill gaps between functions in .text with INT3 instructions
// instead of leaving as NUL bytes (which can be interpreted as
// ADD instructions).
- if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE)
+ if (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE)
memset(SecBuf, 0xCC, Sec->getRawSize());
for_each(parallel::par, Sec->getChunks().begin(), Sec->getChunks().end(),
[&](Chunk *C) { C->writeTo(SecBuf); });
@@ -854,32 +1166,65 @@ void Writer::writeSections() {
}
void Writer::writeBuildId() {
- // If we're not writing a build id (e.g. because /debug is not specified),
- // then just return;
- if (!Config->Debug)
- return;
+ // There are two important parts to the build ID.
+ // 1) If building with debug info, the COFF debug directory contains a
+ // timestamp as well as a Guid and Age of the PDB.
+ // 2) In all cases, the PE COFF file header also contains a timestamp.
+ // For reproducibility, instead of a timestamp we want to use a hash of the
+ // binary, however when building with debug info the hash needs to take into
+ // account the debug info, since it's possible to add blank lines to a file
+ // which causes the debug info to change but not the generated code.
+ //
+ // To handle this, we first set the Guid and Age in the debug directory (but
+ // only if we're doing a debug build). Then, we hash the binary (thus causing
+ // the hash to change if only the debug info changes, since the Age will be
+ // different). Finally, we write that hash into the debug directory (if
+ // present) as well as the COFF file header (always).
+ if (Config->Debug) {
+ assert(BuildId && "BuildId is not set!");
+ if (PreviousBuildId.hasValue()) {
+ *BuildId->BuildId = *PreviousBuildId;
+ BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
+ } else {
+ BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
+ BuildId->BuildId->PDB70.Age = 1;
+ llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
+ }
+ }
- assert(BuildId && "BuildId is not set!");
+ // At this point the only fields in the COFF file which remain unset are the
+ // "timestamp" in the COFF file header, and the ones in the coff debug
+ // directory. Now we can hash the file and write that hash to the various
+ // timestamp fields in the file.
+ StringRef OutputFileData(
+ reinterpret_cast<const char *>(Buffer->getBufferStart()),
+ Buffer->getBufferSize());
- if (PreviousBuildId.hasValue()) {
- *BuildId->BuildId = *PreviousBuildId;
- BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
- return;
- }
+ uint32_t Timestamp = Config->Timestamp;
+ if (Config->Repro)
+ Timestamp = static_cast<uint32_t>(xxHash64(OutputFileData));
+
+ if (DebugDirectory)
+ DebugDirectory->setTimeDateStamp(Timestamp);
- BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
- BuildId->BuildId->PDB70.Age = 1;
- llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
+ uint8_t *Buf = Buffer->getBufferStart();
+ Buf += DOSStubSize + sizeof(PEMagic);
+ object::coff_file_header *CoffHeader =
+ reinterpret_cast<coff_file_header *>(Buf);
+ CoffHeader->TimeDateStamp = Timestamp;
}
// Sort .pdata section contents according to PE/COFF spec 5.5.
void Writer::sortExceptionTable() {
- OutputSection *Sec = findSection(".pdata");
- if (!Sec)
+ if (!FirstPdata)
return;
// We assume .pdata contains function table entries only.
- uint8_t *Begin = Buffer->getBufferStart() + Sec->getFileOff();
- uint8_t *End = Begin + Sec->getVirtualSize();
+ auto BufAddr = [&](Chunk *C) {
+ return Buffer->getBufferStart() + C->getOutputSection()->getFileOff() +
+ C->getRVA() - C->getOutputSection()->getRVA();
+ };
+ uint8_t *Begin = BufAddr(FirstPdata);
+ uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize();
if (Config->Machine == AMD64) {
struct Entry { ulittle32_t Begin, End, Unwind; };
sort(parallel::par, (Entry *)Begin, (Entry *)End,
@@ -897,7 +1242,7 @@ void Writer::sortExceptionTable() {
OutputSection *Writer::findSection(StringRef Name) {
for (OutputSection *Sec : OutputSections)
- if (Sec->getName() == Name)
+ if (Sec->Name == Name)
return Sec;
return nullptr;
}
@@ -905,55 +1250,31 @@ OutputSection *Writer::findSection(StringRef Name) {
uint32_t Writer::getSizeOfInitializedData() {
uint32_t Res = 0;
for (OutputSection *S : OutputSections)
- if (S->getPermissions() & IMAGE_SCN_CNT_INITIALIZED_DATA)
+ if (S->Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
Res += S->getRawSize();
return Res;
}
-// Returns an existing section or create a new one if not found.
-OutputSection *Writer::createSection(StringRef Name) {
- if (auto *Sec = findSection(Name))
- return Sec;
- const auto DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
- const auto BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
- const auto CODE = IMAGE_SCN_CNT_CODE;
- const auto DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
- const auto R = IMAGE_SCN_MEM_READ;
- const auto W = IMAGE_SCN_MEM_WRITE;
- const auto X = IMAGE_SCN_MEM_EXECUTE;
- uint32_t Perms = StringSwitch<uint32_t>(Name)
- .Case(".bss", BSS | R | W)
- .Case(".data", DATA | R | W)
- .Cases(".didat", ".edata", ".idata", ".rdata", DATA | R)
- .Case(".reloc", DATA | DISCARDABLE | R)
- .Case(".text", CODE | R | X)
- .Default(0);
- if (!Perms)
- llvm_unreachable("unknown section name");
- auto Sec = make<OutputSection>(Name);
- Sec->addPermissions(Perms);
- OutputSections.push_back(Sec);
- return Sec;
-}
-
-// Dest is .reloc section. Add contents to that section.
-void Writer::addBaserels(OutputSection *Dest) {
+// Add base relocations to .reloc section.
+void Writer::addBaserels() {
+ if (!Config->Relocatable)
+ return;
std::vector<Baserel> V;
for (OutputSection *Sec : OutputSections) {
- if (Sec == Dest)
+ if (Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
continue;
// Collect all locations for base relocations.
for (Chunk *C : Sec->getChunks())
C->getBaserels(&V);
// Add the addresses to .reloc section.
if (!V.empty())
- addBaserelBlocks(Dest, V);
+ addBaserelBlocks(V);
V.clear();
}
}
// Add addresses to .reloc section. Note that addresses are grouped by page.
-void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V) {
+void Writer::addBaserelBlocks(std::vector<Baserel> &V) {
const uint32_t Mask = ~uint32_t(PageSize - 1);
uint32_t Page = V[0].RVA & Mask;
size_t I = 0, J = 1;
@@ -961,11 +1282,11 @@ void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V) {
uint32_t P = V[J].RVA & Mask;
if (P == Page)
continue;
- Dest->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
+ RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
I = J;
Page = P;
}
if (I == J)
return;
- Dest->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
+ RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
}
diff --git a/contrib/llvm/tools/lld/COFF/Writer.h b/contrib/llvm/tools/lld/COFF/Writer.h
index 21be1be6e92a..d37276cb6d91 100644
--- a/contrib/llvm/tools/lld/COFF/Writer.h
+++ b/contrib/llvm/tools/lld/COFF/Writer.h
@@ -13,6 +13,7 @@
#include "Chunks.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/COFF.h"
+#include <chrono>
#include <cstdint>
#include <vector>
@@ -29,16 +30,14 @@ void writeResult();
// non-overlapping file offsets and RVAs.
class OutputSection {
public:
- OutputSection(llvm::StringRef N) : Name(N), Header({}) {}
- void setRVA(uint64_t);
- void setFileOffset(uint64_t);
+ OutputSection(llvm::StringRef N, uint32_t Chars) : Name(N) {
+ Header.Characteristics = Chars;
+ }
void addChunk(Chunk *C);
- llvm::StringRef getName() { return Name; }
+ void merge(OutputSection *Other);
ArrayRef<Chunk *> getChunks() { return Chunks; }
void addPermissions(uint32_t C);
void setPermissions(uint32_t C);
- uint32_t getPermissions() { return Header.Characteristics & PermMask; }
- uint32_t getCharacteristics() { return Header.Characteristics; }
uint64_t getRVA() { return Header.VirtualAddress; }
uint64_t getFileOff() { return Header.PointerToRawData; }
void writeHeaderTo(uint8_t *Buf);
@@ -60,9 +59,10 @@ public:
// N.B. The section index is one based.
uint32_t SectionIndex = 0;
-private:
llvm::StringRef Name;
- llvm::object::coff_section Header;
+ llvm::object::coff_section Header = {};
+
+private:
uint32_t StringTableOff = 0;
std::vector<Chunk *> Chunks;
};
diff --git a/contrib/llvm/tools/lld/Common/Args.cpp b/contrib/llvm/tools/lld/Common/Args.cpp
index 680cf5bd0a6e..ff77bfcc3b76 100644
--- a/contrib/llvm/tools/lld/Common/Args.cpp
+++ b/contrib/llvm/tools/lld/Common/Args.cpp
@@ -18,13 +18,17 @@ using namespace llvm;
using namespace lld;
int lld::args::getInteger(opt::InputArgList &Args, unsigned Key, int Default) {
- int V = Default;
- if (auto *Arg = Args.getLastArg(Key)) {
- StringRef S = Arg->getValue();
- if (!to_integer(S, V, 10))
- error(Arg->getSpelling() + ": number expected, but got '" + S + "'");
- }
- return V;
+ auto *A = Args.getLastArg(Key);
+ if (!A)
+ return Default;
+
+ int V;
+ if (to_integer(A->getValue(), V, 10))
+ return V;
+
+ StringRef Spelling = Args.getArgString(A->getIndex());
+ error(Spelling + ": number expected, but got '" + A->getValue() + "'");
+ return 0;
}
std::vector<StringRef> lld::args::getStrings(opt::InputArgList &Args, int Id) {
diff --git a/contrib/llvm/tools/lld/Common/CMakeLists.txt b/contrib/llvm/tools/lld/Common/CMakeLists.txt
index b376893f35a4..a45fe209f06f 100644
--- a/contrib/llvm/tools/lld/Common/CMakeLists.txt
+++ b/contrib/llvm/tools/lld/Common/CMakeLists.txt
@@ -10,6 +10,7 @@ add_lld_library(lldCommon
Strings.cpp
TargetOptionsCommandFlags.cpp
Threads.cpp
+ Timer.cpp
Version.cpp
ADDITIONAL_HEADER_DIRS
diff --git a/contrib/llvm/tools/lld/Common/ErrorHandler.cpp b/contrib/llvm/tools/lld/Common/ErrorHandler.cpp
index 18affce4d5a6..d1cb3dbbe03c 100644
--- a/contrib/llvm/tools/lld/Common/ErrorHandler.cpp
+++ b/contrib/llvm/tools/lld/Common/ErrorHandler.cpp
@@ -12,7 +12,8 @@
#include "lld/Common/Threads.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Error.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include <mutex>
@@ -59,6 +60,30 @@ void lld::exitLld(int Val) {
_exit(Val);
}
+void lld::diagnosticHandler(const DiagnosticInfo &DI) {
+ SmallString<128> S;
+ raw_svector_ostream OS(S);
+ DiagnosticPrinterRawOStream DP(OS);
+ DI.print(DP);
+ switch (DI.getSeverity()) {
+ case DS_Error:
+ error(S);
+ break;
+ case DS_Warning:
+ warn(S);
+ break;
+ case DS_Remark:
+ case DS_Note:
+ message(S);
+ break;
+ }
+}
+
+void lld::checkError(Error E) {
+ handleAllErrors(std::move(E),
+ [&](ErrorInfoBase &EIB) { error(EIB.message()); });
+}
+
void ErrorHandler::print(StringRef S, raw_ostream::Colors C) {
*ErrorOS << LogName << ": ";
if (ColorDiagnostics) {
diff --git a/contrib/llvm/tools/lld/Common/Strings.cpp b/contrib/llvm/tools/lld/Common/Strings.cpp
index 6cd4ad8d600a..36f4f77d8476 100644
--- a/contrib/llvm/tools/lld/Common/Strings.cpp
+++ b/contrib/llvm/tools/lld/Common/Strings.cpp
@@ -8,7 +8,21 @@
//===----------------------------------------------------------------------===//
#include "lld/Common/Strings.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/LLVM.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/Support/GlobPattern.h"
+#include <algorithm>
+#include <mutex>
+#include <vector>
+
+#if defined(_MSC_VER)
+#include <Windows.h>
+
+// DbgHelp.h must be included after Windows.h.
+#include <DbgHelp.h>
+#pragma comment(lib, "dbghelp.lib")
+#endif
using namespace llvm;
using namespace lld;
@@ -30,3 +44,66 @@ Optional<std::string> lld::demangleItanium(StringRef Name) {
free(Buf);
return S;
}
+
+Optional<std::string> lld::demangleMSVC(StringRef S) {
+#if defined(_MSC_VER)
+ // UnDecorateSymbolName is not thread-safe, so we need a mutex.
+ static std::mutex Mu;
+ std::lock_guard<std::mutex> Lock(Mu);
+
+ char Buf[4096];
+ if (S.startswith("?"))
+ if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0))
+ return std::string(Buf, Len);
+#endif
+ return None;
+}
+
+StringMatcher::StringMatcher(ArrayRef<StringRef> Pat) {
+ for (StringRef S : Pat) {
+ Expected<GlobPattern> Pat = GlobPattern::create(S);
+ if (!Pat)
+ error(toString(Pat.takeError()));
+ else
+ Patterns.push_back(*Pat);
+ }
+}
+
+bool StringMatcher::match(StringRef S) const {
+ for (const GlobPattern &Pat : Patterns)
+ if (Pat.match(S))
+ return true;
+ return false;
+}
+
+// Converts a hex string (e.g. "deadbeef") to a vector.
+std::vector<uint8_t> lld::parseHex(StringRef S) {
+ std::vector<uint8_t> Hex;
+ while (!S.empty()) {
+ StringRef B = S.substr(0, 2);
+ S = S.substr(2);
+ uint8_t H;
+ if (!to_integer(B, H, 16)) {
+ error("not a hexadecimal value: " + B);
+ return {};
+ }
+ Hex.push_back(H);
+ }
+ return Hex;
+}
+
+// Returns true if S is valid as a C language identifier.
+bool lld::isValidCIdentifier(StringRef S) {
+ return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&
+ std::all_of(S.begin() + 1, S.end(),
+ [](char C) { return C == '_' || isAlnum(C); });
+}
+
+// Write the contents of the a buffer to a file
+void lld::saveBuffer(StringRef Buffer, const Twine &Path) {
+ std::error_code EC;
+ raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
+ if (EC)
+ error("cannot create " + Path + ": " + EC.message());
+ OS << Buffer;
+}
diff --git a/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp b/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp
index e8e582f4c256..b46df363c361 100644
--- a/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp
+++ b/contrib/llvm/tools/lld/Common/TargetOptionsCommandFlags.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This file exists as a place for global variables defined in LLVM's
-// CodeGen/CommandFlags.def. By putting the resulting object file in
+// CodeGen/CommandFlags.inc. By putting the resulting object file in
// an archive and linking with it, the definitions will automatically be
// included when needed and skipped when already present.
//
@@ -16,12 +16,12 @@
#include "lld/Common/TargetOptionsCommandFlags.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/Target/TargetOptions.h"
// Define an externally visible version of
// InitTargetOptionsFromCodeGenFlags, so that its functionality can be
-// used without having to include llvm/CodeGen/CommandFlags.def, which
+// used without having to include llvm/CodeGen/CommandFlags.inc, which
// would lead to multiple definitions of the command line flags.
llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() {
return ::InitTargetOptionsFromCodeGenFlags();
@@ -30,3 +30,5 @@ llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() {
llvm::Optional<llvm::CodeModel::Model> lld::GetCodeModelFromCMModel() {
return getCodeModel();
}
+
+std::string lld::GetCPUStr() { return ::getCPUStr(); }
diff --git a/contrib/llvm/tools/lld/Common/Timer.cpp b/contrib/llvm/tools/lld/Common/Timer.cpp
new file mode 100644
index 000000000000..89f9829b47cf
--- /dev/null
+++ b/contrib/llvm/tools/lld/Common/Timer.cpp
@@ -0,0 +1,80 @@
+//===- Timer.cpp ----------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Common/Timer.h"
+#include "lld/Common/ErrorHandler.h"
+#include "llvm/Support/Format.h"
+
+using namespace lld;
+using namespace llvm;
+
+ScopedTimer::ScopedTimer(Timer &T) : T(&T) { T.start(); }
+
+void ScopedTimer::stop() {
+ if (!T)
+ return;
+ T->stop();
+ T = nullptr;
+}
+
+ScopedTimer::~ScopedTimer() { stop(); }
+
+Timer::Timer(llvm::StringRef Name) : Name(Name), Parent(nullptr) {}
+Timer::Timer(llvm::StringRef Name, Timer &Parent)
+ : Name(Name), Parent(&Parent) {}
+
+void Timer::start() {
+ if (Parent && Total.count() == 0)
+ Parent->Children.push_back(this);
+ StartTime = std::chrono::high_resolution_clock::now();
+}
+
+void Timer::stop() {
+ Total += (std::chrono::high_resolution_clock::now() - StartTime);
+}
+
+Timer &Timer::root() {
+ static Timer RootTimer("Total Link Time");
+ return RootTimer;
+}
+
+void Timer::print() {
+ double TotalDuration = static_cast<double>(root().millis());
+
+ // We want to print the grand total under all the intermediate phases, so we
+ // print all children first, then print the total under that.
+ for (const auto &Child : Children)
+ Child->print(1, TotalDuration);
+
+ message(std::string(49, '-'));
+
+ root().print(0, root().millis(), false);
+}
+
+double Timer::millis() const {
+ return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
+ Total)
+ .count();
+}
+
+void Timer::print(int Depth, double TotalDuration, bool Recurse) const {
+ double P = 100.0 * millis() / TotalDuration;
+
+ SmallString<32> Str;
+ llvm::raw_svector_ostream Stream(Str);
+ std::string S = std::string(Depth * 2, ' ') + Name + std::string(":");
+ Stream << format("%-30s%5d ms (%5.1f%%)", S.c_str(), (int)millis(), P);
+
+ message(Str);
+
+ if (Recurse) {
+ for (const auto &Child : Children)
+ Child->print(Depth + 1, TotalDuration);
+ }
+}
diff --git a/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.cpp b/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.cpp
index 48273d0eb398..7551919cf86f 100644
--- a/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.cpp
+++ b/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.cpp
@@ -34,12 +34,11 @@
#include "LinkerScript.h"
#include "OutputSections.h"
#include "Relocations.h"
-#include "Strings.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Memory.h"
-
+#include "lld/Common/Strings.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -342,7 +341,7 @@ static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2,
// patch or 0 if no patch required.
static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off,
uint64_t Limit) {
- uint64_t ISAddr = IS->getParent()->Addr + IS->OutSecOff;
+ uint64_t ISAddr = IS->getVA(0);
// Advance Off so that (ISAddr + Off) modulo 0x1000 is at least 0xff8.
uint64_t InitialPageOff = (ISAddr + Off) & 0xfff;
@@ -406,7 +405,7 @@ lld::elf::Patch843419Section::Patch843419Section(InputSection *P, uint64_t Off)
}
uint64_t lld::elf::Patch843419Section::getLDSTAddr() const {
- return Patchee->getParent()->Addr + Patchee->OutSecOff + PatcheeOffset;
+ return Patchee->getVA(PatcheeOffset);
}
void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) {
@@ -555,9 +554,8 @@ static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset,
if (RelIt != IS->Relocations.end() && RelIt->Type == R_AARCH64_JUMP26)
return;
- if (Config->Verbose)
- message("detected cortex-a53-843419 erratum sequence starting at " +
- utohexstr(AdrpAddr) + " in unpatched output.");
+ log("detected cortex-a53-843419 erratum sequence starting at " +
+ utohexstr(AdrpAddr) + " in unpatched output.");
auto *PS = make<Patch843419Section>(IS, PatcheeOffset);
Patches.push_back(PS);
@@ -603,7 +601,7 @@ AArch64Err843419Patcher::patchInputSectionDescription(
(DataSym == MapSyms.end()) ? IS->Data.size() : (*DataSym)->Value;
while (Off < Limit) {
- uint64_t StartAddr = IS->getParent()->Addr + IS->OutSecOff + Off;
+ uint64_t StartAddr = IS->getVA(Off);
if (uint64_t PatcheeOffset = scanCortexA53Errata843419(IS, Off, Limit))
implementPatch(StartAddr, PatcheeOffset, IS, Patches);
}
diff --git a/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.h b/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.h
index 6c100f25d8af..edd154d4cab3 100644
--- a/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.h
+++ b/contrib/llvm/tools/lld/ELF/AArch64ErrataFix.h
@@ -11,7 +11,6 @@
#define LLD_ELF_AARCH64ERRATAFIX_H
#include "lld/Common/LLVM.h"
-
#include <map>
#include <vector>
diff --git a/contrib/llvm/tools/lld/ELF/Arch/AArch64.cpp b/contrib/llvm/tools/lld/ELF/Arch/AArch64.cpp
index a741cd1cb6da..ae072d4adaac 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/AArch64.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/AArch64.cpp
@@ -34,7 +34,7 @@ public:
AArch64();
RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const override;
- bool isPicRel(RelType Type) const override;
+ RelType getDynRel(RelType Type) const override;
void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
void writePltHeader(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
@@ -93,6 +93,11 @@ RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S,
return R_TLSDESC_CALL;
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
+ case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC:
return R_TLS;
case R_AARCH64_CALL26:
case R_AARCH64_CONDBR19:
@@ -148,8 +153,10 @@ bool AArch64::usesOnlyLowPageBits(RelType Type) const {
}
}
-bool AArch64::isPicRel(RelType Type) const {
- return Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64;
+RelType AArch64::getDynRel(RelType Type) const {
+ if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64)
+ return Type;
+ return R_AARCH64_NONE;
}
void AArch64::writeGotPlt(uint8_t *Buf, const Symbol &) const {
@@ -244,12 +251,12 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
switch (Type) {
case R_AARCH64_ABS16:
case R_AARCH64_PREL16:
- checkIntUInt<16>(Loc, Val, Type);
+ checkIntUInt(Loc, Val, 16, Type);
write16le(Loc, Val);
break;
case R_AARCH64_ABS32:
case R_AARCH64_PREL32:
- checkIntUInt<32>(Loc, Val, Type);
+ checkIntUInt(Loc, Val, 32, Type);
write32le(Loc, Val);
break;
case R_AARCH64_ABS64:
@@ -264,11 +271,11 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case R_AARCH64_TLSDESC_ADR_PAGE21:
- checkInt<33>(Loc, Val, Type);
+ checkInt(Loc, Val, 33, Type);
write32AArch64Addr(Loc, Val >> 12);
break;
case R_AARCH64_ADR_PREL_LO21:
- checkInt<21>(Loc, Val, Type);
+ checkInt(Loc, Val, 21, Type);
write32AArch64Addr(Loc, Val);
break;
case R_AARCH64_JUMP26:
@@ -282,38 +289,40 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
write32le(Loc, 0x14000000);
LLVM_FALLTHROUGH;
case R_AARCH64_CALL26:
- checkInt<28>(Loc, Val, Type);
+ checkInt(Loc, Val, 28, Type);
or32le(Loc, (Val & 0x0FFFFFFC) >> 2);
break;
case R_AARCH64_CONDBR19:
case R_AARCH64_LD_PREL_LO19:
- checkAlignment<4>(Loc, Val, Type);
- checkInt<21>(Loc, Val, Type);
+ checkAlignment(Loc, Val, 4, Type);
+ checkInt(Loc, Val, 21, Type);
or32le(Loc, (Val & 0x1FFFFC) << 3);
break;
- case R_AARCH64_LD64_GOT_LO12_NC:
- case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
- case R_AARCH64_TLSDESC_LD64_LO12:
- checkAlignment<8>(Loc, Val, Type);
- or32le(Loc, (Val & 0xFF8) << 7);
- break;
case R_AARCH64_LDST8_ABS_LO12_NC:
+ case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
or32AArch64Imm(Loc, getBits(Val, 0, 11));
break;
case R_AARCH64_LDST16_ABS_LO12_NC:
- checkAlignment<2>(Loc, Val, Type);
+ case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ checkAlignment(Loc, Val, 2, Type);
or32AArch64Imm(Loc, getBits(Val, 1, 11));
break;
case R_AARCH64_LDST32_ABS_LO12_NC:
- checkAlignment<4>(Loc, Val, Type);
+ case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ checkAlignment(Loc, Val, 4, Type);
or32AArch64Imm(Loc, getBits(Val, 2, 11));
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
- checkAlignment<8>(Loc, Val, Type);
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case R_AARCH64_TLSDESC_LD64_LO12:
+ checkAlignment(Loc, Val, 8, Type);
or32AArch64Imm(Loc, getBits(Val, 3, 11));
break;
case R_AARCH64_LDST128_ABS_LO12_NC:
- checkAlignment<16>(Loc, Val, Type);
+ case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC:
+ checkAlignment(Loc, Val, 16, Type);
or32AArch64Imm(Loc, getBits(Val, 4, 11));
break;
case R_AARCH64_MOVW_UABS_G0_NC:
@@ -329,11 +338,11 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
or32le(Loc, (Val & 0xFFFF000000000000) >> 43);
break;
case R_AARCH64_TSTBR14:
- checkInt<16>(Loc, Val, Type);
+ checkInt(Loc, Val, 16, Type);
or32le(Loc, (Val & 0xFFFC) << 3);
break;
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
- checkInt<24>(Loc, Val, Type);
+ checkInt(Loc, Val, 24, Type);
or32AArch64Imm(Loc, Val >> 12);
break;
case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
@@ -357,7 +366,7 @@ void AArch64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
// movk x0, #0x10
// nop
// nop
- checkUInt<32>(Loc, Val, Type);
+ checkUInt(Loc, Val, 32, Type);
switch (Type) {
case R_AARCH64_TLSDESC_ADD_LO12:
@@ -407,7 +416,7 @@ void AArch64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {
}
void AArch64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
- checkUInt<32>(Loc, Val, Type);
+ checkUInt(Loc, Val, 32, Type);
if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
// Generate MOVZ.
diff --git a/contrib/llvm/tools/lld/ELF/Arch/AMDGPU.cpp b/contrib/llvm/tools/lld/ELF/Arch/AMDGPU.cpp
index 505e0e6ad480..48b27f23510c 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/AMDGPU.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/AMDGPU.cpp
@@ -66,6 +66,7 @@ void AMDGPU::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
write32le(Loc, Val);
break;
case R_AMDGPU_ABS64:
+ case R_AMDGPU_REL64:
write64le(Loc, Val);
break;
case R_AMDGPU_GOTPCREL32_HI:
@@ -86,6 +87,7 @@ RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S,
case R_AMDGPU_REL32:
case R_AMDGPU_REL32_LO:
case R_AMDGPU_REL32_HI:
+ case R_AMDGPU_REL64:
return R_PC;
case R_AMDGPU_GOTPCREL:
case R_AMDGPU_GOTPCREL32_LO:
diff --git a/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp b/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp
index fc2ac9beef9c..acf9a615f20b 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp
@@ -29,7 +29,6 @@ public:
uint32_t calcEFlags() const override;
RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const override;
- bool isPicRel(RelType Type) const override;
RelType getDynRel(RelType Type) const override;
int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override;
void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
@@ -55,6 +54,7 @@ ARM::ARM() {
TlsGotRel = R_ARM_TLS_TPOFF32;
TlsModuleIndexRel = R_ARM_TLS_DTPMOD32;
TlsOffsetRel = R_ARM_TLS_DTPOFF32;
+ GotBaseSymInGotPlt = false;
GotEntrySize = 4;
GotPltEntrySize = 4;
PltEntrySize = 16;
@@ -170,18 +170,10 @@ RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,
}
}
-bool ARM::isPicRel(RelType Type) const {
- return (Type == R_ARM_TARGET1 && !Config->Target1Rel) ||
- (Type == R_ARM_ABS32);
-}
-
RelType ARM::getDynRel(RelType Type) const {
- if (Type == R_ARM_TARGET1 && !Config->Target1Rel)
+ if ((Type == R_ARM_ABS32) || (Type == R_ARM_TARGET1 && !Config->Target1Rel))
return R_ARM_ABS32;
- if (Type == R_ARM_ABS32)
- return Type;
- // Keep it going with a dummy value so that we can find more reloc errors.
- return R_ARM_ABS32;
+ return R_ARM_NONE;
}
void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const {
@@ -401,7 +393,7 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
write32le(Loc, 1);
break;
case R_ARM_PREL31:
- checkInt<31>(Loc, Val, Type);
+ checkInt(Loc, Val, 31, Type);
write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));
break;
case R_ARM_CALL:
@@ -410,7 +402,7 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
if (Val & 1) {
// If bit 0 of Val is 1 the target is Thumb, we must select a BLX.
// The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
- checkInt<26>(Loc, Val, Type);
+ checkInt(Loc, Val, 26, Type);
write32le(Loc, 0xfa000000 | // opcode
((Val & 2) << 23) | // H
((Val >> 2) & 0x00ffffff)); // imm24
@@ -425,16 +417,16 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_ARM_JUMP24:
case R_ARM_PC24:
case R_ARM_PLT32:
- checkInt<26>(Loc, Val, Type);
+ checkInt(Loc, Val, 26, Type);
write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff));
break;
case R_ARM_THM_JUMP11:
- checkInt<12>(Loc, Val, Type);
+ checkInt(Loc, Val, 12, Type);
write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff));
break;
case R_ARM_THM_JUMP19:
// Encoding T3: Val = S:J2:J1:imm6:imm11:0
- checkInt<21>(Loc, Val, Type);
+ checkInt(Loc, Val, 21, Type);
write16le(Loc,
(read16le(Loc) & 0xfbc0) | // opcode cond
((Val >> 10) & 0x0400) | // S
@@ -460,7 +452,7 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_ARM_THM_JUMP24:
// Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
// FIXME: Use of I1 and I2 require v6T2ops
- checkInt<25>(Loc, Val, Type);
+ checkInt(Loc, Val, 25, Type);
write16le(Loc,
0xf000 | // opcode
((Val >> 14) & 0x0400) | // S
@@ -478,14 +470,14 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
break;
case R_ARM_MOVT_ABS:
case R_ARM_MOVT_PREL:
- checkInt<32>(Loc, Val, Type);
+ checkInt(Loc, Val, 32, Type);
write32le(Loc, (read32le(Loc) & ~0x000f0fff) |
(((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff));
break;
case R_ARM_THM_MOVT_ABS:
case R_ARM_THM_MOVT_PREL:
// Encoding T1: A = imm4:i:imm3:imm8
- checkInt<32>(Loc, Val, Type);
+ checkInt(Loc, Val, 32, Type);
write16le(Loc,
0xf2c0 | // opcode
((Val >> 17) & 0x0400) | // i
diff --git a/contrib/llvm/tools/lld/ELF/Arch/Hexagon.cpp b/contrib/llvm/tools/lld/ELF/Arch/Hexagon.cpp
new file mode 100644
index 000000000000..ff5e862bafa2
--- /dev/null
+++ b/contrib/llvm/tools/lld/ELF/Arch/Hexagon.cpp
@@ -0,0 +1,103 @@
+//===-- Hexagon.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InputFiles.h"
+#include "Symbols.h"
+#include "Target.h"
+#include "lld/Common/ErrorHandler.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::ELF;
+using namespace lld;
+using namespace lld::elf;
+
+namespace {
+class Hexagon final : public TargetInfo {
+public:
+ uint32_t calcEFlags() const override;
+ RelExpr getRelExpr(RelType Type, const Symbol &S,
+ const uint8_t *Loc) const override;
+ void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+};
+} // namespace
+
+// Support V60 only at the moment.
+uint32_t Hexagon::calcEFlags() const { return 0x60; }
+
+static uint32_t applyMask(uint32_t Mask, uint32_t Data) {
+ uint32_t Result = 0;
+ size_t Off = 0;
+
+ for (size_t Bit = 0; Bit != 32; ++Bit) {
+ uint32_t ValBit = (Data >> Off) & 1;
+ uint32_t MaskBit = (Mask >> Bit) & 1;
+ if (MaskBit) {
+ Result |= (ValBit << Bit);
+ ++Off;
+ }
+ }
+ return Result;
+}
+
+RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S,
+ const uint8_t *Loc) const {
+ switch (Type) {
+ case R_HEX_B15_PCREL:
+ case R_HEX_B15_PCREL_X:
+ case R_HEX_B22_PCREL:
+ case R_HEX_B22_PCREL_X:
+ case R_HEX_B32_PCREL_X:
+ return R_PC;
+ default:
+ return R_ABS;
+ }
+}
+
+static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
+
+void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
+ switch (Type) {
+ case R_HEX_NONE:
+ break;
+ case R_HEX_12_X:
+ or32le(Loc, applyMask(0x000007e0, Val));
+ break;
+ case R_HEX_32_6_X:
+ or32le(Loc, applyMask(0x0fff3fff, Val >> 6));
+ break;
+ case R_HEX_B15_PCREL:
+ or32le(Loc, applyMask(0x00df20fe, Val >> 2));
+ break;
+ case R_HEX_B15_PCREL_X:
+ or32le(Loc, applyMask(0x00df20fe, Val & 0x3f));
+ break;
+ case R_HEX_B22_PCREL:
+ or32le(Loc, applyMask(0x1ff3ffe, Val >> 2));
+ break;
+ case R_HEX_B22_PCREL_X:
+ or32le(Loc, applyMask(0x1ff3ffe, Val & 0x3f));
+ break;
+ case R_HEX_B32_PCREL_X:
+ or32le(Loc, applyMask(0x0fff3fff, Val >> 6));
+ break;
+ default:
+ error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type));
+ break;
+ }
+}
+
+TargetInfo *elf::getHexagonTargetInfo() {
+ static Hexagon Target;
+ return &Target;
+}
diff --git a/contrib/llvm/tools/lld/ELF/Arch/Mips.cpp b/contrib/llvm/tools/lld/ELF/Arch/Mips.cpp
index e8af36e6d11e..dc70401c0b0e 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/Mips.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/Mips.cpp
@@ -32,7 +32,6 @@ public:
RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const override;
int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override;
- bool isPicRel(RelType Type) const override;
RelType getDynRel(RelType Type) const override;
void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
void writePltHeader(uint8_t *Buf) const override;
@@ -50,6 +49,7 @@ template <class ELFT> MIPS<ELFT>::MIPS() {
DefaultMaxPageSize = 65536;
GotEntrySize = sizeof(typename ELFT::uint);
GotPltEntrySize = sizeof(typename ELFT::uint);
+ GotBaseSymInGotPlt = false;
PltEntrySize = 16;
PltHeaderSize = 32;
CopyRel = R_MIPS_COPY;
@@ -101,8 +101,6 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
case R_MIPS_HIGHEST:
case R_MICROMIPS_HI16:
case R_MICROMIPS_LO16:
- case R_MICROMIPS_HIGHER:
- case R_MICROMIPS_HIGHEST:
// R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate
// offset between start of function and 'gp' value which by default
// equal to the start of .got section. In that case we consider these
@@ -124,8 +122,6 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
case R_MIPS_TLS_TPREL_LO16:
case R_MIPS_TLS_TPREL32:
case R_MIPS_TLS_TPREL64:
- case R_MICROMIPS_GOT_OFST:
- case R_MICROMIPS_SUB:
case R_MICROMIPS_TLS_DTPREL_HI16:
case R_MICROMIPS_TLS_DTPREL_LO16:
case R_MICROMIPS_TLS_TPREL_HI16:
@@ -155,7 +151,6 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
case R_MIPS_GOT_DISP:
case R_MIPS_TLS_GOTTPREL:
case R_MICROMIPS_CALL16:
- case R_MICROMIPS_GOT_DISP:
case R_MICROMIPS_TLS_GOTTPREL:
return R_MIPS_GOT_OFF;
case R_MIPS_CALL_HI16:
@@ -168,7 +163,6 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
case R_MICROMIPS_GOT_LO16:
return R_MIPS_GOT_OFF32;
case R_MIPS_GOT_PAGE:
- case R_MICROMIPS_GOT_PAGE:
return R_MIPS_GOT_LOCAL_PAGE;
case R_MIPS_TLS_GD:
case R_MICROMIPS_TLS_GD:
@@ -183,12 +177,10 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
}
}
-template <class ELFT> bool MIPS<ELFT>::isPicRel(RelType Type) const {
- return Type == R_MIPS_32 || Type == R_MIPS_64;
-}
-
template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType Type) const {
- return RelativeRel;
+ if (Type == R_MIPS_32 || Type == R_MIPS_64)
+ return RelativeRel;
+ return R_MIPS_NONE;
}
template <class ELFT>
@@ -213,8 +205,8 @@ template <endianness E> static uint32_t readShuffle(const uint8_t *Loc) {
}
template <endianness E>
-static void writeRelocation(uint8_t *Loc, uint64_t V, uint8_t BitsSize,
- uint8_t Shift) {
+static void writeValue(uint8_t *Loc, uint64_t V, uint8_t BitsSize,
+ uint8_t Shift) {
uint32_t Instr = read32<E>(Loc);
uint32_t Mask = 0xffffffff >> (32 - BitsSize);
uint32_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask);
@@ -222,14 +214,14 @@ static void writeRelocation(uint8_t *Loc, uint64_t V, uint8_t BitsSize,
}
template <endianness E>
-static void writeMicroRelocation32(uint8_t *Loc, uint64_t V, uint8_t BitsSize,
- uint8_t Shift) {
+static void writeShuffleValue(uint8_t *Loc, uint64_t V, uint8_t BitsSize,
+ uint8_t Shift) {
// See comments in readShuffle for purpose of this code.
uint16_t *Words = (uint16_t *)Loc;
if (E == support::little)
std::swap(Words[0], Words[1]);
- writeRelocation<E>(Loc, V, BitsSize, Shift);
+ writeValue<E>(Loc, V, BitsSize, Shift);
if (E == support::little)
std::swap(Words[0], Words[1]);
@@ -301,9 +293,9 @@ template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const {
write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2
uint64_t GotPlt = InX::GotPlt->getVA();
- writeRelocation<E>(Buf, GotPlt + 0x8000, 16, 16);
- writeRelocation<E>(Buf + 4, GotPlt, 16, 0);
- writeRelocation<E>(Buf + 8, GotPlt, 16, 0);
+ writeValue<E>(Buf, GotPlt + 0x8000, 16, 16);
+ writeValue<E>(Buf + 4, GotPlt, 16, 0);
+ writeValue<E>(Buf + 8, GotPlt, 16, 0);
}
template <class ELFT>
@@ -338,9 +330,9 @@ void MIPS<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
write32<E>(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15)
write32<E>(Buf + 8, JrInst); // jr $25 / jr.hb $25
write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry)
- writeRelocation<E>(Buf, GotPltEntryAddr + 0x8000, 16, 16);
- writeRelocation<E>(Buf + 4, GotPltEntryAddr, 16, 0);
- writeRelocation<E>(Buf + 12, GotPltEntryAddr, 16, 0);
+ writeValue<E>(Buf, GotPltEntryAddr + 0x8000, 16, 16);
+ writeValue<E>(Buf + 4, GotPltEntryAddr, 16, 0);
+ writeValue<E>(Buf + 12, GotPltEntryAddr, 16, 0);
}
template <class ELFT>
@@ -459,9 +451,6 @@ calculateMipsRelChain(uint8_t *Loc, RelType Type, uint64_t Val) {
return std::make_pair(Type2, Val);
if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16))
return std::make_pair(Type3, -Val);
- if (Type2 == R_MICROMIPS_SUB &&
- (Type3 == R_MICROMIPS_HI16 || Type3 == R_MICROMIPS_LO16))
- return std::make_pair(Type3, -Val);
error(getErrorLocation(Loc) + "unsupported relocations combination " +
Twine(Type));
return std::make_pair(Type & 0xff, Val);
@@ -471,6 +460,9 @@ template <class ELFT>
void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
const endianness E = ELFT::TargetEndianness;
+ if (ELFT::Is64Bits || Config->MipsN32Abi)
+ std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val);
+
// Thread pointer and DRP offsets from the start of TLS data area.
// https://www.linux-mips.org/wiki/NPTL
if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 ||
@@ -485,9 +477,6 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
Val -= 0x7000;
}
- if (ELFT::Is64Bits || Config->MipsN32Abi)
- std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val);
-
switch (Type) {
case R_MIPS_32:
case R_MIPS_GPREL32:
@@ -501,25 +490,25 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
write64<E>(Loc, Val);
break;
case R_MIPS_26:
- writeRelocation<E>(Loc, Val, 26, 2);
+ writeValue<E>(Loc, Val, 26, 2);
break;
case R_MIPS_GOT16:
// The R_MIPS_GOT16 relocation's value in "relocatable" linking mode
// is updated addend (not a GOT index). In that case write high 16 bits
// to store a correct addend value.
if (Config->Relocatable) {
- writeRelocation<E>(Loc, Val + 0x8000, 16, 16);
+ writeValue<E>(Loc, Val + 0x8000, 16, 16);
} else {
- checkInt<16>(Loc, Val, Type);
- writeRelocation<E>(Loc, Val, 16, 0);
+ checkInt(Loc, Val, 16, Type);
+ writeValue<E>(Loc, Val, 16, 0);
}
break;
case R_MICROMIPS_GOT16:
if (Config->Relocatable) {
- writeMicroRelocation32<E>(Loc, Val + 0x8000, 16, 16);
+ writeShuffleValue<E>(Loc, Val + 0x8000, 16, 16);
} else {
- checkInt<16>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 16, 0);
+ checkInt(Loc, Val, 16, Type);
+ writeShuffleValue<E>(Loc, Val, 16, 0);
}
break;
case R_MIPS_CALL16:
@@ -529,7 +518,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_MIPS_TLS_GD:
case R_MIPS_TLS_GOTTPREL:
case R_MIPS_TLS_LDM:
- checkInt<16>(Loc, Val, Type);
+ checkInt(Loc, Val, 16, Type);
LLVM_FALLTHROUGH;
case R_MIPS_CALL_LO16:
case R_MIPS_GOT_LO16:
@@ -538,28 +527,25 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_MIPS_PCLO16:
case R_MIPS_TLS_DTPREL_LO16:
case R_MIPS_TLS_TPREL_LO16:
- writeRelocation<E>(Loc, Val, 16, 0);
+ writeValue<E>(Loc, Val, 16, 0);
break;
- case R_MICROMIPS_GOT_DISP:
- case R_MICROMIPS_GOT_PAGE:
case R_MICROMIPS_GPREL16:
case R_MICROMIPS_TLS_GD:
case R_MICROMIPS_TLS_LDM:
- checkInt<16>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 16, 0);
+ checkInt(Loc, Val, 16, Type);
+ writeShuffleValue<E>(Loc, Val, 16, 0);
break;
case R_MICROMIPS_CALL16:
case R_MICROMIPS_CALL_LO16:
- case R_MICROMIPS_GOT_OFST:
case R_MICROMIPS_LO16:
case R_MICROMIPS_TLS_DTPREL_LO16:
case R_MICROMIPS_TLS_GOTTPREL:
case R_MICROMIPS_TLS_TPREL_LO16:
- writeMicroRelocation32<E>(Loc, Val, 16, 0);
+ writeShuffleValue<E>(Loc, Val, 16, 0);
break;
case R_MICROMIPS_GPREL7_S2:
- checkInt<7>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 7, 2);
+ checkInt(Loc, Val, 7, Type);
+ writeShuffleValue<E>(Loc, Val, 7, 2);
break;
case R_MIPS_CALL_HI16:
case R_MIPS_GOT_HI16:
@@ -567,86 +553,80 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_MIPS_PCHI16:
case R_MIPS_TLS_DTPREL_HI16:
case R_MIPS_TLS_TPREL_HI16:
- writeRelocation<E>(Loc, Val + 0x8000, 16, 16);
+ writeValue<E>(Loc, Val + 0x8000, 16, 16);
break;
case R_MICROMIPS_CALL_HI16:
case R_MICROMIPS_GOT_HI16:
case R_MICROMIPS_HI16:
case R_MICROMIPS_TLS_DTPREL_HI16:
case R_MICROMIPS_TLS_TPREL_HI16:
- writeMicroRelocation32<E>(Loc, Val + 0x8000, 16, 16);
+ writeShuffleValue<E>(Loc, Val + 0x8000, 16, 16);
break;
case R_MIPS_HIGHER:
- writeRelocation<E>(Loc, Val + 0x80008000, 16, 32);
+ writeValue<E>(Loc, Val + 0x80008000, 16, 32);
break;
case R_MIPS_HIGHEST:
- writeRelocation<E>(Loc, Val + 0x800080008000, 16, 48);
- break;
- case R_MICROMIPS_HIGHER:
- writeMicroRelocation32<E>(Loc, Val + 0x80008000, 16, 32);
- break;
- case R_MICROMIPS_HIGHEST:
- writeMicroRelocation32<E>(Loc, Val + 0x800080008000, 16, 48);
+ writeValue<E>(Loc, Val + 0x800080008000, 16, 48);
break;
case R_MIPS_JALR:
case R_MICROMIPS_JALR:
// Ignore this optimization relocation for now
break;
case R_MIPS_PC16:
- checkAlignment<4>(Loc, Val, Type);
- checkInt<18>(Loc, Val, Type);
- writeRelocation<E>(Loc, Val, 16, 2);
+ checkAlignment(Loc, Val, 4, Type);
+ checkInt(Loc, Val, 18, Type);
+ writeValue<E>(Loc, Val, 16, 2);
break;
case R_MIPS_PC19_S2:
- checkAlignment<4>(Loc, Val, Type);
- checkInt<21>(Loc, Val, Type);
- writeRelocation<E>(Loc, Val, 19, 2);
+ checkAlignment(Loc, Val, 4, Type);
+ checkInt(Loc, Val, 21, Type);
+ writeValue<E>(Loc, Val, 19, 2);
break;
case R_MIPS_PC21_S2:
- checkAlignment<4>(Loc, Val, Type);
- checkInt<23>(Loc, Val, Type);
- writeRelocation<E>(Loc, Val, 21, 2);
+ checkAlignment(Loc, Val, 4, Type);
+ checkInt(Loc, Val, 23, Type);
+ writeValue<E>(Loc, Val, 21, 2);
break;
case R_MIPS_PC26_S2:
- checkAlignment<4>(Loc, Val, Type);
- checkInt<28>(Loc, Val, Type);
- writeRelocation<E>(Loc, Val, 26, 2);
+ checkAlignment(Loc, Val, 4, Type);
+ checkInt(Loc, Val, 28, Type);
+ writeValue<E>(Loc, Val, 26, 2);
break;
case R_MIPS_PC32:
- writeRelocation<E>(Loc, Val, 32, 0);
+ writeValue<E>(Loc, Val, 32, 0);
break;
case R_MICROMIPS_26_S1:
case R_MICROMIPS_PC26_S1:
- checkInt<27>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 26, 1);
+ checkInt(Loc, Val, 27, Type);
+ writeShuffleValue<E>(Loc, Val, 26, 1);
break;
case R_MICROMIPS_PC7_S1:
- checkInt<8>(Loc, Val, Type);
+ checkInt(Loc, Val, 8, Type);
writeMicroRelocation16<E>(Loc, Val, 7, 1);
break;
case R_MICROMIPS_PC10_S1:
- checkInt<11>(Loc, Val, Type);
+ checkInt(Loc, Val, 11, Type);
writeMicroRelocation16<E>(Loc, Val, 10, 1);
break;
case R_MICROMIPS_PC16_S1:
- checkInt<17>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 16, 1);
+ checkInt(Loc, Val, 17, Type);
+ writeShuffleValue<E>(Loc, Val, 16, 1);
break;
case R_MICROMIPS_PC18_S3:
- checkInt<21>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 18, 3);
+ checkInt(Loc, Val, 21, Type);
+ writeShuffleValue<E>(Loc, Val, 18, 3);
break;
case R_MICROMIPS_PC19_S2:
- checkInt<21>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 19, 2);
+ checkInt(Loc, Val, 21, Type);
+ writeShuffleValue<E>(Loc, Val, 19, 2);
break;
case R_MICROMIPS_PC21_S1:
- checkInt<22>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 21, 1);
+ checkInt(Loc, Val, 22, Type);
+ writeShuffleValue<E>(Loc, Val, 21, 1);
break;
case R_MICROMIPS_PC23_S2:
- checkInt<25>(Loc, Val, Type);
- writeMicroRelocation32<E>(Loc, Val, 23, 2);
+ checkInt(Loc, Val, 25, Type);
+ writeShuffleValue<E>(Loc, Val, 23, 2);
break;
default:
error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
@@ -655,19 +635,26 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType Type) const {
return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST ||
- Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_GOT_OFST;
+ Type == R_MICROMIPS_LO16;
}
// Return true if the symbol is a PIC function.
template <class ELFT> bool elf::isMipsPIC(const Defined *Sym) {
- typedef typename ELFT::Ehdr Elf_Ehdr;
- if (!Sym->Section || !Sym->isFunc())
+ if (!Sym->isFunc())
+ return false;
+
+ if (Sym->StOther & STO_MIPS_PIC)
+ return true;
+
+ if (!Sym->Section)
+ return false;
+
+ ObjFile<ELFT> *File =
+ cast<InputSectionBase>(Sym->Section)->template getFile<ELFT>();
+ if (!File)
return false;
- auto *Sec = cast<InputSectionBase>(Sym->Section);
- const Elf_Ehdr *Hdr = Sec->template getFile<ELFT>()->getObj().getHeader();
- return (Sym->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC ||
- (Hdr->e_flags & EF_MIPS_PIC);
+ return File->getObj().getHeader()->e_flags & EF_MIPS_PIC;
}
template <class ELFT> TargetInfo *elf::getMipsTargetInfo() {
diff --git a/contrib/llvm/tools/lld/ELF/Arch/MipsArchTree.cpp b/contrib/llvm/tools/lld/ELF/Arch/MipsArchTree.cpp
index 754a47001579..98ceac3075e0 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/MipsArchTree.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/MipsArchTree.cpp
@@ -65,25 +65,30 @@ static StringRef getNanName(bool IsNan2008) {
static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; }
static void checkFlags(ArrayRef<FileFlags> Files) {
+ assert(!Files.empty() && "expected non-empty file list");
+
uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
bool Nan = Files[0].Flags & EF_MIPS_NAN2008;
bool Fp = Files[0].Flags & EF_MIPS_FP64;
- for (const FileFlags &F : Files.slice(1)) {
+ for (const FileFlags &F : Files) {
+ if (Config->Is64 && F.Flags & EF_MIPS_MICROMIPS)
+ error(toString(F.File) + ": microMIPS 64-bit is not supported");
+
uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
if (ABI != ABI2)
- error("target ABI '" + getAbiName(ABI) + "' is incompatible with '" +
- getAbiName(ABI2) + "': " + toString(F.File));
+ error(toString(F.File) + ": ABI '" + getAbiName(ABI2) +
+ "' is incompatible with target ABI '" + getAbiName(ABI) + "'");
bool Nan2 = F.Flags & EF_MIPS_NAN2008;
if (Nan != Nan2)
- error("target -mnan=" + getNanName(Nan) + " is incompatible with -mnan=" +
- getNanName(Nan2) + ": " + toString(F.File));
+ error(toString(F.File) + ": -mnan=" + getNanName(Nan2) +
+ " is incompatible with target -mnan=" + getNanName(Nan));
bool Fp2 = F.Flags & EF_MIPS_FP64;
if (Fp != Fp2)
- error("target -mfp" + getFpName(Fp) + " is incompatible with -mfp" +
- getFpName(Fp2) + ": " + toString(F.File));
+ error(toString(F.File) + ": -mfp" + getFpName(Fp2) +
+ " is incompatible with target -mfp" + getFpName(Fp));
}
}
@@ -102,11 +107,13 @@ static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {
for (const FileFlags &F : Files.slice(1)) {
bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
if (IsPic && !IsPic2)
- warn("linking abicalls code " + toString(Files[0].File) +
- " with non-abicalls file: " + toString(F.File));
+ warn(toString(F.File) +
+ ": linking non-abicalls code with abicalls code " +
+ toString(Files[0].File));
if (!IsPic && IsPic2)
- warn("linking non-abicalls code " + toString(Files[0].File) +
- " with abicalls file: " + toString(F.File));
+ warn(toString(F.File) +
+ ": linking abicalls code with non-abicalls code " +
+ toString(Files[0].File));
}
// Compute the result PIC/non-PIC flag.
@@ -326,7 +333,7 @@ static StringRef getMipsFpAbiName(uint8_t FpAbi) {
case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
return "-msoft-float";
case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
- return "-mips32r2 -mfp64 (old)";
+ return "-mgp32 -mfp64 (old)";
case Mips::Val_GNU_MIPS_ABI_FP_XX:
return "-mfpxx";
case Mips::Val_GNU_MIPS_ABI_FP_64:
@@ -343,9 +350,9 @@ uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
return NewFlag;
if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
- error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
- "' is incompatible with '" + getMipsFpAbiName(NewFlag) +
- "': " + FileName);
+ error(FileName + ": floating point ABI '" + getMipsFpAbiName(NewFlag) +
+ "' is incompatible with target floating point ABI '" +
+ getMipsFpAbiName(OldFlag) + "'");
return OldFlag;
}
diff --git a/contrib/llvm/tools/lld/ELF/Arch/PPC.cpp b/contrib/llvm/tools/lld/ELF/Arch/PPC.cpp
index 6af0df331df6..20cae0e59cf4 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/PPC.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/PPC.cpp
@@ -21,13 +21,18 @@ using namespace lld::elf;
namespace {
class PPC final : public TargetInfo {
public:
- PPC() { GotBaseSymOff = 0x8000; }
+ PPC();
void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const override;
};
} // namespace
+PPC::PPC() {
+ GotBaseSymOff = 0x8000;
+ GotBaseSymInGotPlt = false;
+}
+
RelExpr PPC::getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const {
switch (Type) {
diff --git a/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp b/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp
index ac4021b5918d..fa3bf6c62a0d 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp
@@ -14,12 +14,14 @@
#include "llvm/Support/Endian.h"
using namespace llvm;
+using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
static uint64_t PPC64TocOffset = 0x8000;
+static uint64_t DynamicThreadPointerOffset = 0x8000;
uint64_t elf::getPPC64TocBase() {
// The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
@@ -39,11 +41,21 @@ namespace {
class PPC64 final : public TargetInfo {
public:
PPC64();
+ uint32_t calcEFlags() const override;
RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const override;
+ void writePltHeader(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
int32_t Index, unsigned RelOff) const override;
void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+ void writeGotHeader(uint8_t *Buf) const override;
+ bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
+ uint64_t BranchAddr, const Symbol &S) const override;
+ RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,
+ RelExpr Expr) const override;
+ void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+ void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+ void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
};
} // namespace
@@ -51,21 +63,35 @@ public:
// #higher(value), #highera(value), #highest(value), and #highesta(value)
// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
// document.
-static uint16_t applyPPCLo(uint64_t V) { return V; }
-static uint16_t applyPPCHi(uint64_t V) { return V >> 16; }
-static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; }
-static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; }
-static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; }
-static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
-static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
+static uint16_t lo(uint64_t V) { return V; }
+static uint16_t hi(uint64_t V) { return V >> 16; }
+static uint16_t ha(uint64_t V) { return (V + 0x8000) >> 16; }
+static uint16_t higher(uint64_t V) { return V >> 32; }
+static uint16_t highera(uint64_t V) { return (V + 0x8000) >> 32; }
+static uint16_t highest(uint64_t V) { return V >> 48; }
+static uint16_t highesta(uint64_t V) { return (V + 0x8000) >> 48; }
PPC64::PPC64() {
- PltRel = GotRel = R_PPC64_GLOB_DAT;
+ GotRel = R_PPC64_GLOB_DAT;
+ PltRel = R_PPC64_JMP_SLOT;
RelativeRel = R_PPC64_RELATIVE;
+ IRelativeRel = R_PPC64_IRELATIVE;
GotEntrySize = 8;
+ PltEntrySize = 4;
GotPltEntrySize = 8;
- PltEntrySize = 32;
- PltHeaderSize = 0;
+ GotBaseSymInGotPlt = false;
+ GotBaseSymOff = 0x8000;
+ GotHeaderEntriesNum = 1;
+ GotPltHeaderEntriesNum = 2;
+ PltHeaderSize = 60;
+ NeedsThunks = true;
+ TcbSize = 8;
+ TlsTpOffset = 0x7000;
+
+ TlsModuleIndexRel = R_PPC64_DTPMOD64;
+ TlsOffsetRel = R_PPC64_DTPREL64;
+
+ TlsGotRel = R_PPC64_TPREL64;
// We need 64K pages (at least under glibc/Linux, the loader won't
// set different permissions on a finer granularity than that).
@@ -80,6 +106,110 @@ PPC64::PPC64() {
// And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
// use 0x10000000 as the starting address.
DefaultImageBase = 0x10000000;
+
+ TrapInstr =
+ (Config->IsLE == sys::IsLittleEndianHost) ? 0x7fe00008 : 0x0800e07f;
+}
+
+static uint32_t getEFlags(InputFile *File) {
+ if (Config->EKind == ELF64BEKind)
+ return cast<ObjFile<ELF64BE>>(File)->getObj().getHeader()->e_flags;
+ return cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags;
+}
+
+// This file implements v2 ABI. This function makes sure that all
+// object files have v2 or an unspecified version as an ABI version.
+uint32_t PPC64::calcEFlags() const {
+ for (InputFile *F : ObjectFiles) {
+ uint32_t Flag = getEFlags(F);
+ if (Flag == 1)
+ error(toString(F) + ": ABI version 1 is not supported");
+ else if (Flag > 2)
+ error(toString(F) + ": unrecognized e_flags: " + Twine(Flag));
+ }
+ return 2;
+}
+
+void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
+ // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement.
+ // The general dynamic code sequence for a global `x` will look like:
+ // Instruction Relocation Symbol
+ // addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x
+ // addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x
+ // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x
+ // R_PPC64_REL24 __tls_get_addr
+ // nop None None
+
+ // Relaxing to local exec entails converting:
+ // addis r3, r2, x@got@tlsgd@ha into nop
+ // addi r3, r3, x@got@tlsgd@l into addis r3, r13, x@tprel@ha
+ // bl __tls_get_addr(x@tlsgd) into nop
+ // nop into addi r3, r3, x@tprel@l
+
+ uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+
+ switch (Type) {
+ case R_PPC64_GOT_TLSGD16_HA:
+ write32(Loc - EndianOffset, 0x60000000); // nop
+ break;
+ case R_PPC64_GOT_TLSGD16_LO:
+ write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13
+ relocateOne(Loc, R_PPC64_TPREL16_HA, Val);
+ break;
+ case R_PPC64_TLSGD:
+ write32(Loc, 0x60000000); // nop
+ write32(Loc + 4, 0x38630000); // addi r3, r3
+ relocateOne(Loc + 4 + EndianOffset, R_PPC64_TPREL16_LO, Val);
+ break;
+ default:
+ llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
+ }
+}
+
+
+void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
+ // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.
+ // The local dynamic code sequence for a global `x` will look like:
+ // Instruction Relocation Symbol
+ // addis r3, r2, x@got@tlsld@ha R_PPC64_GOT_TLSLD16_HA x
+ // addi r3, r3, x@got@tlsld@l R_PPC64_GOT_TLSLD16_LO x
+ // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSLD x
+ // R_PPC64_REL24 __tls_get_addr
+ // nop None None
+
+ // Relaxing to local exec entails converting:
+ // addis r3, r2, x@got@tlsld@ha into nop
+ // addi r3, r3, x@got@tlsld@l into addis r3, r13, 0
+ // bl __tls_get_addr(x@tlsgd) into nop
+ // nop into addi r3, r3, 4096
+
+ uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+ switch (Type) {
+ case R_PPC64_GOT_TLSLD16_HA:
+ write32(Loc - EndianOffset, 0x60000000); // nop
+ break;
+ case R_PPC64_GOT_TLSLD16_LO:
+ write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13, 0
+ break;
+ case R_PPC64_TLSLD:
+ write32(Loc, 0x60000000); // nop
+ write32(Loc + 4, 0x38631000); // addi r3, r3, 4096
+ break;
+ case R_PPC64_DTPREL16:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_DTPREL16_HI:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_LO:
+ case R_PPC64_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ relocateOne(Loc, Type, Val);
+ break;
+ default:
+ llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
+ }
}
RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
@@ -95,48 +225,162 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
case R_PPC64_TOC:
return R_PPC_TOC;
case R_PPC64_REL24:
- return R_PPC_PLT_OPD;
+ return R_PPC_CALL_PLT;
+ case R_PPC64_REL16_LO:
+ case R_PPC64_REL16_HA:
+ case R_PPC64_REL32:
+ case R_PPC64_REL64:
+ return R_PC;
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSGD16_HA:
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSGD16_LO:
+ return R_TLSGD_GOT;
+ case R_PPC64_GOT_TLSLD16:
+ case R_PPC64_GOT_TLSLD16_HA:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TLSLD16_LO:
+ return R_TLSLD_GOT;
+ case R_PPC64_GOT_TPREL16_HA:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_HI:
+ return R_GOT_OFF;
+ case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ return R_TLSLD_GOT_OFF;
+ case R_PPC64_TPREL16:
+ case R_PPC64_TPREL16_HA:
+ case R_PPC64_TPREL16_LO:
+ case R_PPC64_TPREL16_HI:
+ case R_PPC64_TPREL16_DS:
+ case R_PPC64_TPREL16_LO_DS:
+ case R_PPC64_TPREL16_HIGHER:
+ case R_PPC64_TPREL16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHESTA:
+ return R_TLS;
+ case R_PPC64_DTPREL16:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_DTPREL16_HI:
+ case R_PPC64_DTPREL16_HIGHER:
+ case R_PPC64_DTPREL16_HIGHERA:
+ case R_PPC64_DTPREL16_HIGHEST:
+ case R_PPC64_DTPREL16_HIGHESTA:
+ case R_PPC64_DTPREL16_LO:
+ case R_PPC64_DTPREL16_LO_DS:
+ case R_PPC64_DTPREL64:
+ return R_ABS;
+ case R_PPC64_TLSGD:
+ return R_TLSDESC_CALL;
+ case R_PPC64_TLSLD:
+ return R_TLSLD_HINT;
+ case R_PPC64_TLS:
+ return R_HINT;
default:
return R_ABS;
}
}
+void PPC64::writeGotHeader(uint8_t *Buf) const {
+ write64(Buf, getPPC64TocBase());
+}
+
+void PPC64::writePltHeader(uint8_t *Buf) const {
+ // The generic resolver stub goes first.
+ write32(Buf + 0, 0x7c0802a6); // mflr r0
+ write32(Buf + 4, 0x429f0005); // bcl 20,4*cr7+so,8 <_glink+0x8>
+ write32(Buf + 8, 0x7d6802a6); // mflr r11
+ write32(Buf + 12, 0x7c0803a6); // mtlr r0
+ write32(Buf + 16, 0x7d8b6050); // subf r12, r11, r12
+ write32(Buf + 20, 0x380cffcc); // subi r0,r12,52
+ write32(Buf + 24, 0x7800f082); // srdi r0,r0,62,2
+ write32(Buf + 28, 0xe98b002c); // ld r12,44(r11)
+ write32(Buf + 32, 0x7d6c5a14); // add r11,r12,r11
+ write32(Buf + 36, 0xe98b0000); // ld r12,0(r11)
+ write32(Buf + 40, 0xe96b0008); // ld r11,8(r11)
+ write32(Buf + 44, 0x7d8903a6); // mtctr r12
+ write32(Buf + 48, 0x4e800420); // bctr
+
+ // The 'bcl' instruction will set the link register to the address of the
+ // following instruction ('mflr r11'). Here we store the offset from that
+ // instruction to the first entry in the GotPlt section.
+ int64_t GotPltOffset = InX::GotPlt->getVA() - (InX::Plt->getVA() + 8);
+ write64(Buf + 52, GotPltOffset);
+}
+
void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
- uint64_t Off = GotPltEntryAddr - getPPC64TocBase();
-
- // FIXME: What we should do, in theory, is get the offset of the function
- // descriptor in the .opd section, and use that as the offset from %r2 (the
- // TOC-base pointer). Instead, we have the GOT-entry offset, and that will
- // be a pointer to the function descriptor in the .opd section. Using
- // this scheme is simpler, but requires an extra indirection per PLT dispatch.
-
- write32be(Buf, 0xf8410028); // std %r2, 40(%r1)
- write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
- write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
- write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
- write32be(Buf + 16, 0x7d6903a6); // mtctr %r11
- write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
- write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
- write32be(Buf + 28, 0x4e800420); // bctr
+ int32_t Offset = PltHeaderSize + Index * PltEntrySize;
+ // bl __glink_PLTresolve
+ write32(Buf, 0x48000000 | ((-Offset) & 0x03FFFFFc));
}
static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {
- uint64_t V = Val - PPC64TocOffset;
+ // Relocations relative to the toc-base need to be adjusted by the Toc offset.
+ uint64_t TocBiasedVal = Val - PPC64TocOffset;
+ // Relocations relative to dtv[dtpmod] need to be adjusted by the DTP offset.
+ uint64_t DTPBiasedVal = Val - DynamicThreadPointerOffset;
+
switch (Type) {
+ // TOC biased relocation.
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSLD16:
case R_PPC64_TOC16:
- return {R_PPC64_ADDR16, V};
+ return {R_PPC64_ADDR16, TocBiasedVal};
case R_PPC64_TOC16_DS:
- return {R_PPC64_ADDR16_DS, V};
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
+ return {R_PPC64_ADDR16_DS, TocBiasedVal};
+ case R_PPC64_GOT_TLSGD16_HA:
+ case R_PPC64_GOT_TLSLD16_HA:
+ case R_PPC64_GOT_TPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_HA:
case R_PPC64_TOC16_HA:
- return {R_PPC64_ADDR16_HA, V};
+ return {R_PPC64_ADDR16_HA, TocBiasedVal};
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TPREL16_HI:
+ case R_PPC64_GOT_DTPREL16_HI:
case R_PPC64_TOC16_HI:
- return {R_PPC64_ADDR16_HI, V};
+ return {R_PPC64_ADDR16_HI, TocBiasedVal};
+ case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_TOC16_LO:
- return {R_PPC64_ADDR16_LO, V};
+ return {R_PPC64_ADDR16_LO, TocBiasedVal};
case R_PPC64_TOC16_LO_DS:
- return {R_PPC64_ADDR16_LO_DS, V};
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ return {R_PPC64_ADDR16_LO_DS, TocBiasedVal};
+
+ // Dynamic Thread pointer biased relocation types.
+ case R_PPC64_DTPREL16:
+ return {R_PPC64_ADDR16, DTPBiasedVal};
+ case R_PPC64_DTPREL16_DS:
+ return {R_PPC64_ADDR16_DS, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HA:
+ return {R_PPC64_ADDR16_HA, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HI:
+ return {R_PPC64_ADDR16_HI, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHER:
+ return {R_PPC64_ADDR16_HIGHER, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHERA:
+ return {R_PPC64_ADDR16_HIGHERA, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHEST:
+ return {R_PPC64_ADDR16_HIGHEST, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHESTA:
+ return {R_PPC64_ADDR16_HIGHESTA, DTPBiasedVal};
+ case R_PPC64_DTPREL16_LO:
+ return {R_PPC64_ADDR16_LO, DTPBiasedVal};
+ case R_PPC64_DTPREL16_LO_DS:
+ return {R_PPC64_ADDR16_LO_DS, DTPBiasedVal};
+ case R_PPC64_DTPREL64:
+ return {R_PPC64_ADDR64, DTPBiasedVal};
+
default:
return {Type, Val};
}
@@ -149,68 +393,139 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
switch (Type) {
case R_PPC64_ADDR14: {
- checkAlignment<4>(Loc, Val, Type);
+ checkAlignment(Loc, Val, 4, Type);
// Preserve the AA/LK bits in the branch instruction
uint8_t AALK = Loc[3];
- write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc));
+ write16(Loc + 2, (AALK & 3) | (Val & 0xfffc));
break;
}
case R_PPC64_ADDR16:
- checkInt<16>(Loc, Val, Type);
- write16be(Loc, Val);
+ case R_PPC64_TPREL16:
+ checkInt(Loc, Val, 16, Type);
+ write16(Loc, Val);
break;
case R_PPC64_ADDR16_DS:
- checkInt<16>(Loc, Val, Type);
- write16be(Loc, (read16be(Loc) & 3) | (Val & ~3));
+ case R_PPC64_TPREL16_DS:
+ checkInt(Loc, Val, 16, Type);
+ write16(Loc, (read16(Loc) & 3) | (Val & ~3));
break;
case R_PPC64_ADDR16_HA:
case R_PPC64_REL16_HA:
- write16be(Loc, applyPPCHa(Val));
+ case R_PPC64_TPREL16_HA:
+ write16(Loc, ha(Val));
break;
case R_PPC64_ADDR16_HI:
case R_PPC64_REL16_HI:
- write16be(Loc, applyPPCHi(Val));
+ case R_PPC64_TPREL16_HI:
+ write16(Loc, hi(Val));
break;
case R_PPC64_ADDR16_HIGHER:
- write16be(Loc, applyPPCHigher(Val));
+ case R_PPC64_TPREL16_HIGHER:
+ write16(Loc, higher(Val));
break;
case R_PPC64_ADDR16_HIGHERA:
- write16be(Loc, applyPPCHighera(Val));
+ case R_PPC64_TPREL16_HIGHERA:
+ write16(Loc, highera(Val));
break;
case R_PPC64_ADDR16_HIGHEST:
- write16be(Loc, applyPPCHighest(Val));
+ case R_PPC64_TPREL16_HIGHEST:
+ write16(Loc, highest(Val));
break;
case R_PPC64_ADDR16_HIGHESTA:
- write16be(Loc, applyPPCHighesta(Val));
+ case R_PPC64_TPREL16_HIGHESTA:
+ write16(Loc, highesta(Val));
break;
case R_PPC64_ADDR16_LO:
- write16be(Loc, applyPPCLo(Val));
+ case R_PPC64_REL16_LO:
+ case R_PPC64_TPREL16_LO:
+ write16(Loc, lo(Val));
break;
case R_PPC64_ADDR16_LO_DS:
- case R_PPC64_REL16_LO:
- write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(Val) & ~3));
+ case R_PPC64_TPREL16_LO_DS:
+ write16(Loc, (read16(Loc) & 3) | (lo(Val) & ~3));
break;
case R_PPC64_ADDR32:
case R_PPC64_REL32:
- checkInt<32>(Loc, Val, Type);
- write32be(Loc, Val);
+ checkInt(Loc, Val, 32, Type);
+ write32(Loc, Val);
break;
case R_PPC64_ADDR64:
case R_PPC64_REL64:
case R_PPC64_TOC:
- write64be(Loc, Val);
+ write64(Loc, Val);
break;
case R_PPC64_REL24: {
uint32_t Mask = 0x03FFFFFC;
- checkInt<24>(Loc, Val, Type);
- write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask));
+ checkInt(Loc, Val, 24, Type);
+ write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
break;
}
+ case R_PPC64_DTPREL64:
+ write64(Loc, Val - DynamicThreadPointerOffset);
+ break;
default:
error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
}
}
+bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
+ uint64_t BranchAddr, const Symbol &S) const {
+ // If a function is in the plt it needs to be called through
+ // a call stub.
+ return Type == R_PPC64_REL24 && S.isInPlt();
+}
+
+RelExpr PPC64::adjustRelaxExpr(RelType Type, const uint8_t *Data,
+ RelExpr Expr) const {
+ if (Expr == R_RELAX_TLS_GD_TO_IE)
+ return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
+ if (Expr == R_RELAX_TLS_LD_TO_LE)
+ return R_RELAX_TLS_LD_TO_LE_ABS;
+ return Expr;
+}
+
+// Reference: 3.7.4.1 of the 64-bit ELF V2 abi supplement.
+// The general dynamic code sequence for a global `x` uses 4 instructions.
+// Instruction Relocation Symbol
+// addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x
+// addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x
+// bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x
+// R_PPC64_REL24 __tls_get_addr
+// nop None None
+//
+// Relaxing to initial-exec entails:
+// 1) Convert the addis/addi pair that builds the address of the tls_index
+// struct for 'x' to an addis/ld pair that loads an offset from a got-entry.
+// 2) Convert the call to __tls_get_addr to a nop.
+// 3) Convert the nop following the call to an add of the loaded offset to the
+// thread pointer.
+// Since the nop must directly follow the call, the R_PPC64_TLSGD relocation is
+// used as the relaxation hint for both steps 2 and 3.
+void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {
+ switch (Type) {
+ case R_PPC64_GOT_TLSGD16_HA:
+ // This is relaxed from addis rT, r2, sym@got@tlsgd@ha to
+ // addis rT, r2, sym@got@tprel@ha.
+ relocateOne(Loc, R_PPC64_GOT_TPREL16_HA, Val);
+ return;
+ case R_PPC64_GOT_TLSGD16_LO: {
+ // Relax from addi r3, rA, sym@got@tlsgd@l to
+ // ld r3, sym@got@tprel@l(rA)
+ uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+ uint32_t InputRegister = (read32(Loc - EndianOffset) & (0x1f << 16));
+ write32(Loc - EndianOffset, 0xE8600000 | InputRegister);
+ relocateOne(Loc, R_PPC64_GOT_TPREL16_LO_DS, Val);
+ return;
+ }
+ case R_PPC64_TLSGD:
+ write32(Loc, 0x60000000); // bl __tls_get_addr(sym@tlsgd) --> nop
+ write32(Loc + 4, 0x7c636A14); // nop --> add r3, r3, r13
+ return;
+ default:
+ llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
+ }
+}
+
TargetInfo *elf::getPPC64TargetInfo() {
static PPC64 Target;
return &Target;
diff --git a/contrib/llvm/tools/lld/ELF/Arch/SPARCV9.cpp b/contrib/llvm/tools/lld/ELF/Arch/SPARCV9.cpp
index d9d6e1390407..36f5c836930e 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/SPARCV9.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/SPARCV9.cpp
@@ -77,23 +77,23 @@ void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_SPARC_32:
case R_SPARC_UA32:
// V-word32
- checkUInt<32>(Loc, Val, Type);
+ checkUInt(Loc, Val, 32, Type);
write32be(Loc, Val);
break;
case R_SPARC_DISP32:
// V-disp32
- checkInt<32>(Loc, Val, Type);
+ checkInt(Loc, Val, 32, Type);
write32be(Loc, Val);
break;
case R_SPARC_WDISP30:
case R_SPARC_WPLT30:
// V-disp30
- checkInt<32>(Loc, Val, Type);
+ checkInt(Loc, Val, 32, Type);
write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff));
break;
case R_SPARC_22:
// V-imm22
- checkUInt<22>(Loc, Val, Type);
+ checkUInt(Loc, Val, 22, Type);
write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff));
break;
case R_SPARC_GOT22:
@@ -103,7 +103,7 @@ void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
break;
case R_SPARC_WDISP19:
// V-disp19
- checkInt<21>(Loc, Val, Type);
+ checkInt(Loc, Val, 21, Type);
write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff));
break;
case R_SPARC_GOT10:
@@ -137,7 +137,7 @@ void SPARCV9::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t Off = PltHeaderSize + Index * PltEntrySize;
+ uint64_t Off = getPltEntryOffset(Index);
relocateOne(Buf, R_SPARC_22, Off);
relocateOne(Buf + 4, R_SPARC_WDISP19, -(Off + 4 - PltEntrySize));
}
diff --git a/contrib/llvm/tools/lld/ELF/Arch/X86.cpp b/contrib/llvm/tools/lld/ELF/Arch/X86.cpp
index 94b46acdd896..0624fe78750c 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/X86.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/X86.cpp
@@ -46,7 +46,6 @@ public:
} // namespace
X86::X86() {
- GotBaseSymOff = -1;
CopyRel = R_386_COPY;
GotRel = R_386_GLOB_DAT;
PltRel = R_386_JUMP_SLOT;
@@ -78,9 +77,9 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
case R_386_TLS_LDO_32:
return R_ABS;
case R_386_TLS_GD:
- return R_TLSGD;
+ return R_TLSGD_GOT_FROM_END;
case R_386_TLS_LDM:
- return R_TLSLD;
+ return R_TLSLD_GOT_FROM_END;
case R_386_PLT32:
return R_PLT_PC;
case R_386_PC8:
@@ -228,7 +227,7 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
}
write32le(Buf + 7, RelOff);
- write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
+ write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
}
int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
@@ -260,15 +259,15 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
// R_386_{PC,}{8,16} are not part of the i386 psABI, but they are
// being used for some 16-bit programs such as boot loaders, so
// we want to support them.
- checkUInt<8>(Loc, Val, Type);
+ checkIntUInt(Loc, Val, 8, Type);
*Loc = Val;
break;
case R_386_PC8:
- checkInt<8>(Loc, Val, Type);
+ checkInt(Loc, Val, 8, Type);
*Loc = Val;
break;
case R_386_16:
- checkUInt<16>(Loc, Val, Type);
+ checkIntUInt(Loc, Val, 16, Type);
write16le(Loc, Val);
break;
case R_386_PC16:
@@ -282,7 +281,7 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
// current location subtracted from it.
// We just check that Val fits in 17 bits. This misses some cases, but
// should have no false positives.
- checkInt<17>(Loc, Val, Type);
+ checkInt(Loc, Val, 17, Type);
write16le(Loc, Val);
break;
case R_386_32:
@@ -305,7 +304,7 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_386_TLS_LE_32:
case R_386_TLS_TPOFF:
case R_386_TLS_TPOFF32:
- checkInt<32>(Loc, Val, Type);
+ checkInt(Loc, Val, 32, Type);
write32le(Loc, Val);
break;
default:
@@ -448,6 +447,7 @@ void RetpolinePic::writePltHeader(uint8_t *Buf) const {
0x89, 0xc8, // 2b: mov %ecx, %eax
0x59, // 2d: pop %ecx
0xc3, // 2e: ret
+ 0xcc, // 2f: int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
@@ -461,21 +461,23 @@ void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Insn[] = {
- 0x50, // pushl %eax
- 0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax
- 0xe8, 0, 0, 0, 0, // call plt+0x20
- 0xe9, 0, 0, 0, 0, // jmp plt+0x12
- 0x68, 0, 0, 0, 0, // pushl $reloc_offset
- 0xe9, 0, 0, 0, 0, // jmp plt+0
+ 0x50, // pushl %eax
+ 0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax
+ 0xe8, 0, 0, 0, 0, // call plt+0x20
+ 0xe9, 0, 0, 0, 0, // jmp plt+0x12
+ 0x68, 0, 0, 0, 0, // pushl $reloc_offset
+ 0xe9, 0, 0, 0, 0, // jmp plt+0
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize();
+ unsigned Off = getPltEntryOffset(Index);
write32le(Buf + 3, GotPltEntryAddr - Ebx);
- write32le(Buf + 8, -Index * PltEntrySize - PltHeaderSize - 12 + 32);
- write32le(Buf + 13, -Index * PltEntrySize - PltHeaderSize - 17 + 18);
+ write32le(Buf + 8, -Off - 12 + 32);
+ write32le(Buf + 13, -Off - 17 + 18);
write32le(Buf + 18, RelOff);
- write32le(Buf + 23, -Index * PltEntrySize - PltHeaderSize - 27);
+ write32le(Buf + 23, -Off - 27);
}
RetpolineNoPic::RetpolineNoPic() {
@@ -488,7 +490,7 @@ void RetpolineNoPic::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
}
void RetpolineNoPic::writePltHeader(uint8_t *Buf) const {
- const uint8_t PltData[] = {
+ const uint8_t Insn[] = {
0xff, 0x35, 0, 0, 0, 0, // 0: pushl GOTPLT+4
0x50, // 6: pushl %eax
0xa1, 0, 0, 0, 0, // 7: mov GOTPLT+8, %eax
@@ -504,8 +506,9 @@ void RetpolineNoPic::writePltHeader(uint8_t *Buf) const {
0x89, 0xc8, // 2b: mov %ecx, %eax
0x59, // 2d: pop %ecx
0xc3, // 2e: ret
+ 0xcc, // 2f: int3; padding
};
- memcpy(Buf, PltData, sizeof(PltData));
+ memcpy(Buf, Insn, sizeof(Insn));
uint32_t GotPlt = InX::GotPlt->getVA();
write32le(Buf + 2, GotPlt + 4);
@@ -516,20 +519,23 @@ void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Insn[] = {
- 0x50, // 0: pushl %eax
- 0xa1, 0, 0, 0, 0, // 1: mov foo_in_GOT, %eax
- 0xe8, 0, 0, 0, 0, // 6: call plt+0x20
- 0xe9, 0, 0, 0, 0, // b: jmp plt+0x11
- 0x68, 0, 0, 0, 0, // 10: pushl $reloc_offset
- 0xe9, 0, 0, 0, 0, // 15: jmp plt+0
+ 0x50, // 0: pushl %eax
+ 0xa1, 0, 0, 0, 0, // 1: mov foo_in_GOT, %eax
+ 0xe8, 0, 0, 0, 0, // 6: call plt+0x20
+ 0xe9, 0, 0, 0, 0, // b: jmp plt+0x11
+ 0x68, 0, 0, 0, 0, // 10: pushl $reloc_offset
+ 0xe9, 0, 0, 0, 0, // 15: jmp plt+0
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding
+ 0xcc, // 1f: int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
+ unsigned Off = getPltEntryOffset(Index);
write32le(Buf + 2, GotPltEntryAddr);
- write32le(Buf + 7, -Index * PltEntrySize - PltHeaderSize - 11 + 32);
- write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16 + 17);
+ write32le(Buf + 7, -Off - 11 + 32);
+ write32le(Buf + 12, -Off - 16 + 17);
write32le(Buf + 17, RelOff);
- write32le(Buf + 22, -Index * PltEntrySize - PltHeaderSize - 26);
+ write32le(Buf + 22, -Off - 26);
}
TargetInfo *elf::getX86TargetInfo() {
diff --git a/contrib/llvm/tools/lld/ELF/Arch/X86_64.cpp b/contrib/llvm/tools/lld/ELF/Arch/X86_64.cpp
index 3db391e9f01c..d4bdb3730c58 100644
--- a/contrib/llvm/tools/lld/ELF/Arch/X86_64.cpp
+++ b/contrib/llvm/tools/lld/ELF/Arch/X86_64.cpp
@@ -28,7 +28,7 @@ public:
X86_64();
RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const override;
- bool isPicRel(RelType Type) const override;
+ RelType getDynRel(RelType Type) const override;
void writeGotPltHeader(uint8_t *Buf) const override;
void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
void writePltHeader(uint8_t *Buf) const override;
@@ -43,6 +43,8 @@ public:
void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+ bool adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const override;
private:
void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
@@ -51,7 +53,6 @@ private:
} // namespace
template <class ELFT> X86_64<ELFT>::X86_64() {
- GotBaseSymOff = -1;
CopyRel = R_X86_64_COPY;
GotRel = R_X86_64_GLOB_DAT;
PltRel = R_X86_64_JUMP_SLOT;
@@ -106,6 +107,11 @@ RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S,
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTTPOFF:
return R_GOT_PC;
+ case R_X86_64_GOTOFF64:
+ return R_GOTREL_FROM_END;
+ case R_X86_64_GOTPC32:
+ case R_X86_64_GOTPC64:
+ return R_GOTONLY_PC_FROM_END;
case R_X86_64_NONE:
return R_NONE;
default:
@@ -124,7 +130,7 @@ template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
template <class ELFT>
void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
// See comments in X86::writeGotPlt.
- write32le(Buf, S.getPltVA() + 6);
+ write64le(Buf, S.getPltVA() + 6);
}
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
@@ -153,12 +159,14 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
write32le(Buf + 7, Index);
- write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
+ write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
}
-template <class ELFT> bool X86_64<ELFT>::isPicRel(RelType Type) const {
- return Type != R_X86_64_PC32 && Type != R_X86_64_32 &&
- Type != R_X86_64_TPOFF32;
+template <class ELFT> RelType X86_64<ELFT>::getDynRel(RelType Type) const {
+ if (Type == R_X86_64_64 || Type == R_X86_64_PC64 || Type == R_X86_64_SIZE32 ||
+ Type == R_X86_64_SIZE64)
+ return Type;
+ return R_X86_64_NONE;
}
template <class ELFT>
@@ -285,20 +293,21 @@ template <class ELFT>
void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
switch (Type) {
case R_X86_64_8:
- checkUInt<8>(Loc, Val, Type);
+ checkUInt(Loc, Val, 8, Type);
*Loc = Val;
break;
case R_X86_64_16:
- checkUInt<16>(Loc, Val, Type);
+ checkUInt(Loc, Val, 16, Type);
write16le(Loc, Val);
break;
case R_X86_64_32:
- checkUInt<32>(Loc, Val, Type);
+ checkUInt(Loc, Val, 32, Type);
write32le(Loc, Val);
break;
case R_X86_64_32S:
case R_X86_64_TPOFF32:
case R_X86_64_GOT32:
+ case R_X86_64_GOTPC32:
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
@@ -309,7 +318,7 @@ void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_X86_64_TLSLD:
case R_X86_64_DTPOFF32:
case R_X86_64_SIZE32:
- checkInt<32>(Loc, Val, Type);
+ checkInt(Loc, Val, 32, Type);
write32le(Loc, Val);
break;
case R_X86_64_64:
@@ -318,6 +327,8 @@ void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
case R_X86_64_PC64:
case R_X86_64_SIZE64:
case R_X86_64_GOT64:
+ case R_X86_64_GOTOFF64:
+ case R_X86_64_GOTPC64:
write64le(Loc, Val);
break;
default:
@@ -460,6 +471,55 @@ void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {
write32le(Loc - 1, Val + 1);
}
+// This anonymous namespace works around a warning bug in
+// old versions of gcc. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
+namespace {
+
+// A split-stack prologue starts by checking the amount of stack remaining
+// in one of two ways:
+// A) Comparing of the stack pointer to a field in the tcb.
+// B) Or a load of a stack pointer offset with an lea to r10 or r11.
+template <>
+bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const {
+ // Replace "cmp %fs:0x70,%rsp" and subsequent branch
+ // with "stc, nopl 0x0(%rax,%rax,1)"
+ if (Loc + 8 < End && memcmp(Loc, "\x64\x48\x3b\x24\x25", 4) == 0) {
+ memcpy(Loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8);
+ return true;
+ }
+
+ // Adjust "lea -0x200(%rsp),%r10" to lea "-0x4200(%rsp),%r10"
+ if (Loc + 7 < End && memcmp(Loc, "\x4c\x8d\x94\x24\x00\xfe\xff", 7) == 0) {
+ memcpy(Loc, "\x4c\x8d\x94\x24\x00\xbe\xff", 7);
+ return true;
+ }
+
+ // Adjust "lea -0x200(%rsp),%r11" to lea "-0x4200(%rsp),%r11"
+ if (Loc + 7 < End && memcmp(Loc, "\x4c\x8d\x9c\x24\x00\xfe\xff", 7) == 0) {
+ memcpy(Loc, "\x4c\x8d\x9c\x24\x00\xbe\xff", 7);
+ return true;
+ }
+ return false;
+}
+
+template <>
+bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const {
+ llvm_unreachable("Target doesn't support split stacks.");
+}
+
+} // namespace
+
+// These nonstandard PLT entries are to migtigate Spectre v2 security
+// vulnerability. In order to mitigate Spectre v2, we want to avoid indirect
+// branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT
+// entries, we use a CALL followed by MOV and RET to do the same thing as an
+// indirect jump. That instruction sequence is so-called "retpoline".
+//
+// We have two types of retpoline PLTs as a size optimization. If `-z now`
+// is specified, all dynamic symbols are resolved at load-time. Thus, when
+// that option is given, we can omit code for symbol lazy resolution.
namespace {
template <class ELFT> class Retpoline : public X86_64<ELFT> {
public:
@@ -487,7 +547,7 @@ template <class ELFT> Retpoline<ELFT>::Retpoline() {
template <class ELFT>
void Retpoline<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
- write32le(Buf, S.getPltVA() + 17);
+ write64le(Buf, S.getPltVA() + 17);
}
template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {
@@ -501,6 +561,8 @@ template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 19: int3; .align 16
0x4c, 0x89, 0x1c, 0x24, // 20: next: mov %r11, (%rsp)
0xc3, // 24: ret
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25: int3; padding
+ 0xcc, 0xcc, 0xcc, 0xcc, // 2c: int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
@@ -516,14 +578,15 @@ void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
unsigned RelOff) const {
const uint8_t Insn[] = {
0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0: mov foo@GOTPLT(%rip), %r11
- 0xe8, 0, 0, 0, 0, // 7: callq plt+0x20
- 0xe9, 0, 0, 0, 0, // c: jmp plt+0x12
- 0x68, 0, 0, 0, 0, // 11: pushq <relocation index>
- 0xe9, 0, 0, 0, 0, // 16: jmp plt+0
+ 0xe8, 0, 0, 0, 0, // 7: callq plt+0x20
+ 0xe9, 0, 0, 0, 0, // c: jmp plt+0x12
+ 0x68, 0, 0, 0, 0, // 11: pushq <relocation index>
+ 0xe9, 0, 0, 0, 0, // 16: jmp plt+0
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
- uint64_t Off = TargetInfo::PltHeaderSize + TargetInfo::PltEntrySize * Index;
+ uint64_t Off = TargetInfo::getPltEntryOffset(Index);
write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
write32le(Buf + 8, -Off - 12 + 32);
@@ -547,6 +610,9 @@ void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const {
0xcc, 0xcc, 0xcc, 0xcc, // c: int3; .align 16
0x4c, 0x89, 0x1c, 0x24, // 10: next: mov %r11, (%rsp)
0xc3, // 14: ret
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 15: int3; padding
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding
+ 0xcc, // 1f: int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
}
@@ -556,17 +622,17 @@ void RetpolineZNow<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Insn[] = {
- 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11
- 0xe9, 0, 0, 0, 0, // jmp plt+0
+ 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11
+ 0xe9, 0, 0, 0, 0, // jmp plt+0
+ 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding
};
memcpy(Buf, Insn, sizeof(Insn));
write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
- write32le(Buf + 8,
- -Index * TargetInfo::PltEntrySize - TargetInfo::PltHeaderSize - 12);
+ write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12);
}
-template <class ELFT> TargetInfo *getTargetInfo() {
+template <class ELFT> static TargetInfo *getTargetInfo() {
if (Config->ZRetpolineplt) {
if (Config->ZNow) {
static RetpolineZNow<ELFT> T;
diff --git a/contrib/llvm/tools/lld/ELF/CMakeLists.txt b/contrib/llvm/tools/lld/ELF/CMakeLists.txt
index 7ec837841315..fb2f53a72025 100644
--- a/contrib/llvm/tools/lld/ELF/CMakeLists.txt
+++ b/contrib/llvm/tools/lld/ELF/CMakeLists.txt
@@ -12,6 +12,7 @@ add_lld_library(lldELF
Arch/AMDGPU.cpp
Arch/ARM.cpp
Arch/AVR.cpp
+ Arch/Hexagon.cpp
Arch/Mips.cpp
Arch/MipsArchTree.cpp
Arch/PPC.cpp
@@ -19,6 +20,7 @@ add_lld_library(lldELF
Arch/SPARCV9.cpp
Arch/X86.cpp
Arch/X86_64.cpp
+ CallGraphSort.cpp
Driver.cpp
DriverUtils.cpp
EhFrame.cpp
@@ -35,7 +37,6 @@ add_lld_library(lldELF
Relocations.cpp
ScriptLexer.cpp
ScriptParser.cpp
- Strings.cpp
SymbolTable.cpp
Symbols.cpp
SyntheticSections.cpp
@@ -46,6 +47,7 @@ add_lld_library(lldELF
LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
BinaryFormat
+ BitWriter
Core
DebugInfoDWARF
LTO
diff --git a/contrib/llvm/tools/lld/ELF/CallGraphSort.cpp b/contrib/llvm/tools/lld/ELF/CallGraphSort.cpp
new file mode 100644
index 000000000000..33ac159a6e26
--- /dev/null
+++ b/contrib/llvm/tools/lld/ELF/CallGraphSort.cpp
@@ -0,0 +1,249 @@
+//===- CallGraphSort.cpp --------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Implementation of Call-Chain Clustering from: Optimizing Function Placement
+/// for Large-Scale Data-Center Applications
+/// https://research.fb.com/wp-content/uploads/2017/01/cgo2017-hfsort-final1.pdf
+///
+/// The goal of this algorithm is to improve runtime performance of the final
+/// executable by arranging code sections such that page table and i-cache
+/// misses are minimized.
+///
+/// Definitions:
+/// * Cluster
+/// * An ordered list of input sections which are layed out as a unit. At the
+/// beginning of the algorithm each input section has its own cluster and
+/// the weight of the cluster is the sum of the weight of all incomming
+/// edges.
+/// * Call-Chain Clustering (C³) Heuristic
+/// * Defines when and how clusters are combined. Pick the highest weighted
+/// input section then add it to its most likely predecessor if it wouldn't
+/// penalize it too much.
+/// * Density
+/// * The weight of the cluster divided by the size of the cluster. This is a
+/// proxy for the ammount of execution time spent per byte of the cluster.
+///
+/// It does so given a call graph profile by the following:
+/// * Build a weighted call graph from the call graph profile
+/// * Sort input sections by weight
+/// * For each input section starting with the highest weight
+/// * Find its most likely predecessor cluster
+/// * Check if the combined cluster would be too large, or would have too low
+/// a density.
+/// * If not, then combine the clusters.
+/// * Sort non-empty clusters by density
+///
+//===----------------------------------------------------------------------===//
+
+#include "CallGraphSort.h"
+#include "OutputSections.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
+
+using namespace llvm;
+using namespace lld;
+using namespace lld::elf;
+
+namespace {
+struct Edge {
+ int From;
+ uint64_t Weight;
+};
+
+struct Cluster {
+ Cluster(int Sec, size_t S) {
+ Sections.push_back(Sec);
+ Size = S;
+ }
+
+ double getDensity() const {
+ if (Size == 0)
+ return 0;
+ return double(Weight) / double(Size);
+ }
+
+ std::vector<int> Sections;
+ size_t Size = 0;
+ uint64_t Weight = 0;
+ uint64_t InitialWeight = 0;
+ std::vector<Edge> Preds;
+};
+
+class CallGraphSort {
+public:
+ CallGraphSort();
+
+ DenseMap<const InputSectionBase *, int> run();
+
+private:
+ std::vector<Cluster> Clusters;
+ std::vector<const InputSectionBase *> Sections;
+
+ void groupClusters();
+};
+
+// Maximum ammount the combined cluster density can be worse than the original
+// cluster to consider merging.
+constexpr int MAX_DENSITY_DEGRADATION = 8;
+
+// Maximum cluster size in bytes.
+constexpr uint64_t MAX_CLUSTER_SIZE = 1024 * 1024;
+} // end anonymous namespace
+
+// Take the edge list in Config->CallGraphProfile, resolve symbol names to
+// Symbols, and generate a graph between InputSections with the provided
+// weights.
+CallGraphSort::CallGraphSort() {
+ llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
+ uint64_t> &Profile = Config->CallGraphProfile;
+ DenseMap<const InputSectionBase *, int> SecToCluster;
+
+ auto GetOrCreateNode = [&](const InputSectionBase *IS) -> int {
+ auto Res = SecToCluster.insert(std::make_pair(IS, Clusters.size()));
+ if (Res.second) {
+ Sections.push_back(IS);
+ Clusters.emplace_back(Clusters.size(), IS->getSize());
+ }
+ return Res.first->second;
+ };
+
+ // Create the graph.
+ for (const auto &C : Profile) {
+ const auto *FromSB = cast<InputSectionBase>(C.first.first->Repl);
+ const auto *ToSB = cast<InputSectionBase>(C.first.second->Repl);
+ uint64_t Weight = C.second;
+
+ // Ignore edges between input sections belonging to different output
+ // sections. This is done because otherwise we would end up with clusters
+ // containing input sections that can't actually be placed adjacently in the
+ // output. This messes with the cluster size and density calculations. We
+ // would also end up moving input sections in other output sections without
+ // moving them closer to what calls them.
+ if (FromSB->getOutputSection() != ToSB->getOutputSection())
+ continue;
+
+ int From = GetOrCreateNode(FromSB);
+ int To = GetOrCreateNode(ToSB);
+
+ Clusters[To].Weight += Weight;
+
+ if (From == To)
+ continue;
+
+ // Add an edge
+ Clusters[To].Preds.push_back({From, Weight});
+ }
+ for (Cluster &C : Clusters)
+ C.InitialWeight = C.Weight;
+}
+
+// It's bad to merge clusters which would degrade the density too much.
+static bool isNewDensityBad(Cluster &A, Cluster &B) {
+ double NewDensity = double(A.Weight + B.Weight) / double(A.Size + B.Size);
+ if (NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION)
+ return true;
+ return false;
+}
+
+static void mergeClusters(Cluster &Into, Cluster &From) {
+ Into.Sections.insert(Into.Sections.end(), From.Sections.begin(),
+ From.Sections.end());
+ Into.Size += From.Size;
+ Into.Weight += From.Weight;
+ From.Sections.clear();
+ From.Size = 0;
+ From.Weight = 0;
+}
+
+// Group InputSections into clusters using the Call-Chain Clustering heuristic
+// then sort the clusters by density.
+void CallGraphSort::groupClusters() {
+ std::vector<int> SortedSecs(Clusters.size());
+ std::vector<Cluster *> SecToCluster(Clusters.size());
+
+ for (int SI = 0, SE = Clusters.size(); SI != SE; ++SI) {
+ SortedSecs[SI] = SI;
+ SecToCluster[SI] = &Clusters[SI];
+ }
+
+ std::stable_sort(SortedSecs.begin(), SortedSecs.end(), [&](int A, int B) {
+ return Clusters[B].getDensity() < Clusters[A].getDensity();
+ });
+
+ for (int SI : SortedSecs) {
+ // Clusters[SI] is the same as SecToClusters[SI] here because it has not
+ // been merged into another cluster yet.
+ Cluster &C = Clusters[SI];
+
+ int BestPred = -1;
+ uint64_t BestWeight = 0;
+
+ for (Edge &E : C.Preds) {
+ if (BestPred == -1 || E.Weight > BestWeight) {
+ BestPred = E.From;
+ BestWeight = E.Weight;
+ }
+ }
+
+ // don't consider merging if the edge is unlikely.
+ if (BestWeight * 10 <= C.InitialWeight)
+ continue;
+
+ Cluster *PredC = SecToCluster[BestPred];
+ if (PredC == &C)
+ continue;
+
+ if (C.Size + PredC->Size > MAX_CLUSTER_SIZE)
+ continue;
+
+ if (isNewDensityBad(*PredC, C))
+ continue;
+
+ // NOTE: Consider using a disjoint-set to track section -> cluster mapping
+ // if this is ever slow.
+ for (int SI : C.Sections)
+ SecToCluster[SI] = PredC;
+
+ mergeClusters(*PredC, C);
+ }
+
+ // Remove empty or dead nodes. Invalidates all cluster indices.
+ llvm::erase_if(Clusters, [](const Cluster &C) {
+ return C.Size == 0 || C.Sections.empty();
+ });
+
+ // Sort by density.
+ std::stable_sort(Clusters.begin(), Clusters.end(),
+ [](const Cluster &A, const Cluster &B) {
+ return A.getDensity() > B.getDensity();
+ });
+}
+
+DenseMap<const InputSectionBase *, int> CallGraphSort::run() {
+ groupClusters();
+
+ // Generate order.
+ llvm::DenseMap<const InputSectionBase *, int> OrderMap;
+ ssize_t CurOrder = 1;
+
+ for (const Cluster &C : Clusters)
+ for (int SecIndex : C.Sections)
+ OrderMap[Sections[SecIndex]] = CurOrder++;
+
+ return OrderMap;
+}
+
+// Sort sections by the profile data provided by -callgraph-profile-file
+//
+// This first builds a call graph based on the profile data then merges sections
+// according to the C³ huristic. All clusters are then sorted by a density
+// metric to further improve locality.
+DenseMap<const InputSectionBase *, int> elf::computeCallGraphProfileOrder() {
+ return CallGraphSort().run();
+}
diff --git a/contrib/llvm/tools/lld/ELF/CallGraphSort.h b/contrib/llvm/tools/lld/ELF/CallGraphSort.h
new file mode 100644
index 000000000000..3f96dc88f435
--- /dev/null
+++ b/contrib/llvm/tools/lld/ELF/CallGraphSort.h
@@ -0,0 +1,23 @@
+//===- CallGraphSort.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_CALL_GRAPH_SORT_H
+#define LLD_ELF_CALL_GRAPH_SORT_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace lld {
+namespace elf {
+class InputSectionBase;
+
+llvm::DenseMap<const InputSectionBase *, int> computeCallGraphProfileOrder();
+} // namespace elf
+} // namespace lld
+
+#endif
diff --git a/contrib/llvm/tools/lld/ELF/Config.h b/contrib/llvm/tools/lld/ELF/Config.h
index a9f3e7d3d2de..53f0852fa98f 100644
--- a/contrib/llvm/tools/lld/ELF/Config.h
+++ b/contrib/llvm/tools/lld/ELF/Config.h
@@ -10,6 +10,7 @@
#ifndef LLD_ELF_CONFIG_H
#define LLD_ELF_CONFIG_H
+#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
@@ -17,13 +18,13 @@
#include "llvm/Support/CachePruning.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Endian.h"
-
#include <vector>
namespace lld {
namespace elf {
class InputFile;
+class InputSectionBase;
enum ELFKind {
ELFNoneKind,
@@ -39,6 +40,9 @@ enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid };
// For --discard-{all,locals,none}.
enum class DiscardPolicy { Default, All, Locals, None };
+// For --icf={none,safe,all}.
+enum class ICFLevel { None, Safe, All };
+
// For --strip-{all,debug}.
enum class StripPolicy { None, All, Debug };
@@ -82,21 +86,27 @@ struct Configuration {
llvm::StringMap<uint64_t> SectionStartMap;
llvm::StringRef Chroot;
llvm::StringRef DynamicLinker;
+ llvm::StringRef DwoDir;
llvm::StringRef Entry;
llvm::StringRef Emulation;
llvm::StringRef Fini;
llvm::StringRef Init;
llvm::StringRef LTOAAPipeline;
llvm::StringRef LTONewPmPasses;
+ llvm::StringRef LTOObjPath;
+ llvm::StringRef LTOSampleProfile;
llvm::StringRef MapFile;
llvm::StringRef OutputFile;
llvm::StringRef OptRemarksFilename;
+ llvm::StringRef ProgName;
llvm::StringRef SoName;
llvm::StringRef Sysroot;
llvm::StringRef ThinLTOCacheDir;
+ llvm::StringRef ThinLTOIndexOnlyArg;
+ std::pair<llvm::StringRef, llvm::StringRef> ThinLTOObjectSuffixReplace;
+ std::pair<llvm::StringRef, llvm::StringRef> ThinLTOPrefixReplace;
std::string Rpath;
std::vector<VersionDefinition> VersionDefinitions;
- std::vector<llvm::StringRef> Argv;
std::vector<llvm::StringRef> AuxiliaryList;
std::vector<llvm::StringRef> FilterList;
std::vector<llvm::StringRef> SearchPaths;
@@ -106,34 +116,41 @@ struct Configuration {
std::vector<SymbolVersion> VersionScriptGlobals;
std::vector<SymbolVersion> VersionScriptLocals;
std::vector<uint8_t> BuildIdVector;
+ llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
+ uint64_t>
+ CallGraphProfile;
bool AllowMultipleDefinition;
- bool AndroidPackDynRelocs = false;
+ bool AndroidPackDynRelocs;
bool ARMHasBlx = false;
bool ARMHasMovtMovw = false;
bool ARMJ1J2BranchEncoding = false;
bool AsNeeded = false;
bool Bsymbolic;
bool BsymbolicFunctions;
+ bool CheckSections;
bool CompressDebugSections;
+ bool Cref;
bool DefineCommon;
bool Demangle = true;
bool DisableVerify;
bool EhFrameHdr;
bool EmitRelocs;
bool EnableNewDtags;
+ bool ExecuteOnly;
bool ExportDynamic;
bool FixCortexA53Errata843419;
bool GcSections;
bool GdbIndex;
bool GnuHash = false;
+ bool GnuUnique;
bool HasDynamicList = false;
bool HasDynSymTab;
- bool ICF;
- bool ICFData;
+ bool IgnoreDataAddressEquality;
+ bool IgnoreFunctionAddressEquality;
+ bool LTODebugPassManager;
+ bool LTONewPassManager;
bool MergeArmExidx;
bool MipsN32Abi = false;
- bool NoGnuUnique;
- bool NoUndefinedVersion;
bool NoinhibitExec;
bool Nostdlib;
bool OFormatBinary;
@@ -141,7 +158,9 @@ struct Configuration {
bool OptRemarksWithHotness;
bool Pie;
bool PrintGcSections;
+ bool PrintIcfSections;
bool Relocatable;
+ bool RelrPackDynRelocs;
bool SaveTemps;
bool SingleRoRx;
bool Shared;
@@ -149,14 +168,22 @@ struct Configuration {
bool SysvHash = false;
bool Target1Rel;
bool Trace;
- bool Verbose;
+ bool ThinLTOEmitImportsFiles;
+ bool ThinLTOIndexOnly;
+ bool UndefinedVersion;
+ bool UseAndroidRelrTags = false;
+ bool WarnBackrefs;
bool WarnCommon;
bool WarnMissingEntry;
+ bool WarnSymbolOrdering;
+ bool WriteAddends;
bool ZCombreloc;
+ bool ZCopyreloc;
bool ZExecstack;
bool ZHazardplt;
bool ZIfuncnoplt;
- bool ZNocopyreloc;
+ bool ZInitfirst;
+ bool ZKeepTextSectionPrefix;
bool ZNodelete;
bool ZNodlopen;
bool ZNow;
@@ -165,9 +192,9 @@ struct Configuration {
bool ZRodynamic;
bool ZText;
bool ZRetpolineplt;
- bool ExitEarly;
bool ZWxneeded;
DiscardPolicy Discard;
+ ICFLevel ICF;
OrphanHandlingPolicy OrphanHandling;
SortSectionPolicy SortSection;
StripPolicy Strip;
@@ -180,6 +207,7 @@ struct Configuration {
uint16_t EMachine = llvm::ELF::EM_NONE;
llvm::Optional<uint64_t> ImageBase;
uint64_t MaxPageSize;
+ uint64_t MipsGotSize;
uint64_t ZStackSize;
unsigned LTOPartitions;
unsigned LTOO;
@@ -245,6 +273,12 @@ struct Configuration {
// The only instance of Configuration struct.
extern Configuration *Config;
+static inline void errorOrWarn(const Twine &Msg) {
+ if (!Config->NoinhibitExec)
+ error(Msg);
+ else
+ warn(Msg);
+}
} // namespace elf
} // namespace lld
diff --git a/contrib/llvm/tools/lld/ELF/Driver.cpp b/contrib/llvm/tools/lld/ELF/Driver.cpp
index e6f4eea18b13..b8be526d9424 100644
--- a/contrib/llvm/tools/lld/ELF/Driver.cpp
+++ b/contrib/llvm/tools/lld/ELF/Driver.cpp
@@ -30,9 +30,9 @@
#include "InputFiles.h"
#include "InputSection.h"
#include "LinkerScript.h"
+#include "MarkLive.h"
#include "OutputSections.h"
#include "ScriptParser.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
@@ -42,12 +42,16 @@
#include "lld/Common/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
+#include "lld/Common/TargetOptionsCommandFlags.h"
#include "lld/Common/Threads.h"
#include "lld/Common/Version.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/TargetSelect.h"
@@ -66,16 +70,18 @@ using namespace lld::elf;
Configuration *elf::Config;
LinkerDriver *elf::Driver;
-static void setConfigs();
+static void setConfigs(opt::InputArgList &Args);
bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
raw_ostream &Error) {
- errorHandler().LogName = Args[0];
+ errorHandler().LogName = sys::path::filename(Args[0]);
errorHandler().ErrorLimitExceededMsg =
"too many errors emitted, stopping now (use "
"-error-limit=0 to see all errors)";
errorHandler().ErrorOS = &Error;
+ errorHandler().ExitEarly = CanExitEarly;
errorHandler().ColorDiagnostics = Error.has_colors();
+
InputSections.clear();
OutputSections.clear();
Tar = nullptr;
@@ -88,14 +94,14 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
Driver = make<LinkerDriver>();
Script = make<LinkerScript>();
Symtab = make<SymbolTable>();
- Config->Argv = {Args.begin(), Args.end()};
+ Config->ProgName = Args[0];
- Driver->main(Args, CanExitEarly);
+ Driver->main(Args);
// Exit immediately if we don't need to return to the caller.
// This saves time because the overhead of calling destructors
// for all globally-allocated objects is not negligible.
- if (Config->ExitEarly)
+ if (CanExitEarly)
exitLld(errorCount() ? 1 : 0);
freeArena();
@@ -113,7 +119,8 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
std::pair<ELFKind, uint16_t> Ret =
StringSwitch<std::pair<ELFKind, uint16_t>>(S)
- .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64})
+ .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec",
+ {ELF64LEKind, EM_AARCH64})
.Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM})
.Case("elf32_x86_64", {ELF32LEKind, EM_X86_64})
.Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS})
@@ -122,6 +129,7 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
.Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
.Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
.Case("elf64ppc", {ELF64BEKind, EM_PPC64})
+ .Case("elf64lppc", {ELF64LEKind, EM_PPC64})
.Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64})
.Case("elf_i386", {ELF32LEKind, EM_386})
.Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
@@ -228,11 +236,15 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
Files.push_back(
createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path));
return;
- default:
+ case file_magic::bitcode:
+ case file_magic::elf_relocatable:
if (InLib)
Files.push_back(make<LazyObjFile>(MBRef, "", 0));
else
Files.push_back(createObjectFile(MBRef));
+ break;
+ default:
+ error(Path + ": unknown file type");
}
}
@@ -248,18 +260,11 @@ void LinkerDriver::addLibrary(StringRef Name) {
// LTO calls LLVM functions to compile bitcode files to native code.
// Technically this can be delayed until we read bitcode files, but
// we don't bother to do lazily because the initialization is fast.
-static void initLLVM(opt::InputArgList &Args) {
+static void initLLVM() {
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
-
- // Parse and evaluate -mllvm options.
- std::vector<const char *> V;
- V.push_back("lld (LLVM option parsing)");
- for (auto *Arg : Args.filtered(OPT_mllvm))
- V.push_back(Arg->getValue());
- cl::ParseCommandLineOptions(V.size(), V.data());
}
// Some command line options or some combinations of them are not allowed.
@@ -290,11 +295,21 @@ static void checkOptions(opt::InputArgList &Args) {
error("-r and -shared may not be used together");
if (Config->GcSections)
error("-r and --gc-sections may not be used together");
- if (Config->ICF)
+ if (Config->GdbIndex)
+ error("-r and --gdb-index may not be used together");
+ if (Config->ICF != ICFLevel::None)
error("-r and --icf may not be used together");
if (Config->Pie)
error("-r and -pie may not be used together");
}
+
+ if (Config->ExecuteOnly) {
+ if (Config->EMachine != EM_AARCH64)
+ error("-execute-only is only supported on AArch64 targets");
+
+ if (Config->SingleRoRx && !Script->HasSectionsCommand)
+ error("-execute-only and -no-rosegment cannot be used together");
+ }
}
static const char *getReproduceOption(opt::InputArgList &Args) {
@@ -310,7 +325,38 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
return false;
}
-void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
+static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2,
+ bool Default) {
+ for (auto *Arg : Args.filtered_reverse(OPT_z)) {
+ if (K1 == Arg->getValue())
+ return true;
+ if (K2 == Arg->getValue())
+ return false;
+ }
+ return Default;
+}
+
+static bool isKnown(StringRef S) {
+ return S == "combreloc" || S == "copyreloc" || S == "defs" ||
+ S == "execstack" || S == "hazardplt" || S == "ifunc-noplt" ||
+ S == "initfirst" ||
+ S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" ||
+ S == "nocombreloc" || S == "nocopyreloc" || S == "nodelete" ||
+ S == "nodlopen" || S == "noexecstack" ||
+ S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" ||
+ S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" ||
+ S == "rodynamic" || S == "text" || S == "wxneeded" ||
+ S.startswith("max-page-size=") || S.startswith("stack-size=");
+}
+
+// Report an error for an unknown -z option.
+static void checkZOptions(opt::InputArgList &Args) {
+ for (auto *Arg : Args.filtered(OPT_z))
+ if (!isKnown(Arg->getValue()))
+ error("unknown -z value: " + StringRef(Arg->getValue()));
+}
+
+void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
ELFOptTable Parser;
opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
@@ -319,7 +365,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
// Handle -help
if (Args.hasArg(OPT_help)) {
- printHelp(ArgsArr[0]);
+ printHelp();
return;
}
@@ -348,9 +394,6 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
if (Args.hasArg(OPT_version))
return;
- Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown);
- errorHandler().ExitEarly = Config->ExitEarly;
-
if (const char *Path = getReproduceOption(Args)) {
// Note that --reproduce is a debug option so you can ignore it
// if you are trying to understand the whole picture of the code.
@@ -368,10 +411,14 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
}
readConfigs(Args);
- initLLVM(Args);
+ checkZOptions(Args);
+ initLLVM();
createFiles(Args);
+ if (errorCount())
+ return;
+
inferMachineType();
- setConfigs();
+ setConfigs(Args);
checkOptions(Args);
if (errorCount())
return;
@@ -455,6 +502,8 @@ static bool isOutputFormatBinary(opt::InputArgList &Args) {
StringRef S = Arg->getValue();
if (S == "binary")
return true;
+ if (S.startswith("elf"))
+ return false;
error("unknown --oformat value: " + S);
}
return false;
@@ -482,6 +531,15 @@ static StringRef getDynamicLinker(opt::InputArgList &Args) {
return Arg->getValue();
}
+static ICFLevel getICF(opt::InputArgList &Args) {
+ auto *Arg = Args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all);
+ if (!Arg || Arg->getOption().getID() == OPT_icf_none)
+ return ICFLevel::None;
+ if (Arg->getOption().getID() == OPT_icf_safe)
+ return ICFLevel::Safe;
+ return ICFLevel::All;
+}
+
static StripPolicy getStrip(opt::InputArgList &Args) {
if (Args.hasArg(OPT_relocatable))
return StripPolicy::None;
@@ -556,6 +614,8 @@ getBuildId(opt::InputArgList &Args) {
return {BuildIdKind::Fast, {}};
StringRef S = Arg->getValue();
+ if (S == "fast")
+ return {BuildIdKind::Fast, {}};
if (S == "md5")
return {BuildIdKind::Md5, {}};
if (S == "sha1" || S == "tree")
@@ -570,6 +630,57 @@ getBuildId(opt::InputArgList &Args) {
return {BuildIdKind::None, {}};
}
+static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &Args) {
+ StringRef S = Args.getLastArgValue(OPT_pack_dyn_relocs, "none");
+ if (S == "android")
+ return {true, false};
+ if (S == "relr")
+ return {false, true};
+ if (S == "android+relr")
+ return {true, true};
+
+ if (S != "none")
+ error("unknown -pack-dyn-relocs format: " + S);
+ return {false, false};
+}
+
+static void readCallGraph(MemoryBufferRef MB) {
+ // Build a map from symbol name to section
+ DenseMap<StringRef, const Symbol *> SymbolNameToSymbol;
+ for (InputFile *File : ObjectFiles)
+ for (Symbol *Sym : File->getSymbols())
+ SymbolNameToSymbol[Sym->getName()] = Sym;
+
+ for (StringRef L : args::getLines(MB)) {
+ SmallVector<StringRef, 3> Fields;
+ L.split(Fields, ' ');
+ uint64_t Count;
+ if (Fields.size() != 3 || !to_integer(Fields[2], Count))
+ fatal(MB.getBufferIdentifier() + ": parse error");
+ const Symbol *FromSym = SymbolNameToSymbol.lookup(Fields[0]);
+ const Symbol *ToSym = SymbolNameToSymbol.lookup(Fields[1]);
+ if (Config->WarnSymbolOrdering) {
+ if (!FromSym)
+ warn(MB.getBufferIdentifier() + ": no such symbol: " + Fields[0]);
+ if (!ToSym)
+ warn(MB.getBufferIdentifier() + ": no such symbol: " + Fields[1]);
+ }
+ if (!FromSym || !ToSym || Count == 0)
+ continue;
+ warnUnorderableSymbol(FromSym);
+ warnUnorderableSymbol(ToSym);
+ const Defined *FromSymD = dyn_cast<Defined>(FromSym);
+ const Defined *ToSymD = dyn_cast<Defined>(ToSym);
+ if (!FromSymD || !ToSymD)
+ continue;
+ const auto *FromSB = dyn_cast_or_null<InputSectionBase>(FromSymD->Section);
+ const auto *ToSB = dyn_cast_or_null<InputSectionBase>(ToSymD->Section);
+ if (!FromSB || !ToSB)
+ continue;
+ Config->CallGraphProfile[std::make_pair(FromSB, ToSB)] += Count;
+ }
+}
+
static bool getCompressDebugSections(opt::InputArgList &Args) {
StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none");
if (S == "none")
@@ -581,54 +692,100 @@ static bool getCompressDebugSections(opt::InputArgList &Args) {
return true;
}
-static int parseInt(StringRef S, opt::Arg *Arg) {
- int V = 0;
- if (!to_integer(S, V, 10))
- error(Arg->getSpelling() + ": number expected, but got '" + S + "'");
- return V;
+static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &Args,
+ unsigned Id) {
+ auto *Arg = Args.getLastArg(Id);
+ if (!Arg)
+ return {"", ""};
+
+ StringRef S = Arg->getValue();
+ std::pair<StringRef, StringRef> Ret = S.split(';');
+ if (Ret.second.empty())
+ error(Arg->getSpelling() + " expects 'old;new' format, but got " + S);
+ return Ret;
+}
+
+// Parse the symbol ordering file and warn for any duplicate entries.
+static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef MB) {
+ SetVector<StringRef> Names;
+ for (StringRef S : args::getLines(MB))
+ if (!Names.insert(S) && Config->WarnSymbolOrdering)
+ warn(MB.getBufferIdentifier() + ": duplicate ordered symbol: " + S);
+
+ return Names.takeVector();
+}
+
+static void parseClangOption(StringRef Opt, const Twine &Msg) {
+ std::string Err;
+ raw_string_ostream OS(Err);
+
+ const char *Argv[] = {Config->ProgName.data(), Opt.data()};
+ if (cl::ParseCommandLineOptions(2, Argv, "", &OS))
+ return;
+ OS.flush();
+ error(Msg + ": " + StringRef(Err).trim());
}
// Initializes Config members by the command line options.
void LinkerDriver::readConfigs(opt::InputArgList &Args) {
+ errorHandler().Verbose = Args.hasArg(OPT_verbose);
+ errorHandler().FatalWarnings =
+ Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
+ ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);
+
Config->AllowMultipleDefinition =
- Args.hasArg(OPT_allow_multiple_definition) || hasZOption(Args, "muldefs");
+ Args.hasFlag(OPT_allow_multiple_definition,
+ OPT_no_allow_multiple_definition, false) ||
+ hasZOption(Args, "muldefs");
Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
+ Config->CheckSections =
+ Args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
Config->Chroot = Args.getLastArgValue(OPT_chroot);
Config->CompressDebugSections = getCompressDebugSections(Args);
+ Config->Cref = Args.hasFlag(OPT_cref, OPT_no_cref, false);
Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common,
!Args.hasArg(OPT_relocatable));
Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
Config->DisableVerify = Args.hasArg(OPT_disable_verify);
Config->Discard = getDiscard(Args);
+ Config->DwoDir = Args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);
Config->DynamicLinker = getDynamicLinker(Args);
Config->EhFrameHdr =
Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false);
Config->EmitRelocs = Args.hasArg(OPT_emit_relocs);
- Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
+ Config->EnableNewDtags =
+ Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true);
Config->Entry = Args.getLastArgValue(OPT_entry);
+ Config->ExecuteOnly =
+ Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false);
Config->ExportDynamic =
Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
- errorHandler().FatalWarnings =
- Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
Config->FilterList = args::getStrings(Args, OPT_filter);
Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419);
Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
+ Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);
Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
- Config->ICF = Args.hasFlag(OPT_icf_all, OPT_icf_none, false);
- Config->ICFData = Args.hasArg(OPT_icf_data);
+ Config->ICF = getICF(Args);
+ Config->IgnoreDataAddressEquality =
+ Args.hasArg(OPT_ignore_data_address_equality);
+ Config->IgnoreFunctionAddressEquality =
+ Args.hasArg(OPT_ignore_function_address_equality);
Config->Init = Args.getLastArgValue(OPT_init, "_init");
Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline);
+ Config->LTODebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager);
+ Config->LTONewPassManager = Args.hasArg(OPT_lto_new_pass_manager);
Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes);
Config->LTOO = args::getInteger(Args, OPT_lto_O, 2);
+ Config->LTOObjPath = Args.getLastArgValue(OPT_plugin_opt_obj_path_eq);
Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1);
+ Config->LTOSampleProfile = Args.getLastArgValue(OPT_lto_sample_profile);
Config->MapFile = Args.getLastArgValue(OPT_Map);
- Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique);
+ Config->MipsGotSize = args::getInteger(Args, OPT_mips_got_size, 0xfff0);
Config->MergeArmExidx =
Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);
- Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version);
Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec);
Config->Nostdlib = Args.hasArg(OPT_nostdlib);
Config->OFormatBinary = isOutputFormatBinary(Args);
@@ -638,7 +795,9 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->Optimize = args::getInteger(Args, OPT_O, 1);
Config->OrphanHandling = getOrphanHandling(Args);
Config->OutputFile = Args.getLastArgValue(OPT_o);
- Config->Pie = Args.hasFlag(OPT_pie, OPT_nopie, false);
+ Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false);
+ Config->PrintIcfSections =
+ Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
Config->PrintGcSections =
Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
Config->Rpath = getRpath(Args);
@@ -658,49 +817,59 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->ThinLTOCachePolicy = CHECK(
parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)),
"--thinlto-cache-policy: invalid cache policy");
+ Config->ThinLTOEmitImportsFiles =
+ Args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files);
+ Config->ThinLTOIndexOnly = Args.hasArg(OPT_plugin_opt_thinlto_index_only) ||
+ Args.hasArg(OPT_plugin_opt_thinlto_index_only_eq);
+ Config->ThinLTOIndexOnlyArg =
+ Args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq);
Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u);
- ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);
+ Config->ThinLTOObjectSuffixReplace =
+ getOldNewOptions(Args, OPT_plugin_opt_thinlto_object_suffix_replace_eq);
+ Config->ThinLTOPrefixReplace =
+ getOldNewOptions(Args, OPT_plugin_opt_thinlto_prefix_replace_eq);
Config->Trace = Args.hasArg(OPT_trace);
Config->Undefined = args::getStrings(Args, OPT_undefined);
+ Config->UndefinedVersion =
+ Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true);
+ Config->UseAndroidRelrTags = Args.hasFlag(
+ OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);
- Config->Verbose = Args.hasArg(OPT_verbose);
- errorHandler().Verbose = Config->Verbose;
- Config->WarnCommon = Args.hasArg(OPT_warn_common);
- Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
- Config->ZExecstack = hasZOption(Args, "execstack");
+ Config->WarnBackrefs =
+ Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
+ Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
+ Config->WarnSymbolOrdering =
+ Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
+ Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true);
+ Config->ZCopyreloc = getZFlag(Args, "copyreloc", "nocopyreloc", true);
+ Config->ZExecstack = getZFlag(Args, "execstack", "noexecstack", false);
Config->ZHazardplt = hasZOption(Args, "hazardplt");
Config->ZIfuncnoplt = hasZOption(Args, "ifunc-noplt");
- Config->ZNocopyreloc = hasZOption(Args, "nocopyreloc");
+ Config->ZInitfirst = hasZOption(Args, "initfirst");
+ Config->ZKeepTextSectionPrefix = getZFlag(
+ Args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
Config->ZNodelete = hasZOption(Args, "nodelete");
Config->ZNodlopen = hasZOption(Args, "nodlopen");
- Config->ZNow = hasZOption(Args, "now");
+ Config->ZNow = getZFlag(Args, "now", "lazy", false);
Config->ZOrigin = hasZOption(Args, "origin");
- Config->ZRelro = !hasZOption(Args, "norelro");
+ Config->ZRelro = getZFlag(Args, "relro", "norelro", true);
Config->ZRetpolineplt = hasZOption(Args, "retpolineplt");
Config->ZRodynamic = hasZOption(Args, "rodynamic");
Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0);
- Config->ZText = !hasZOption(Args, "notext");
+ Config->ZText = getZFlag(Args, "text", "notext", true);
Config->ZWxneeded = hasZOption(Args, "wxneeded");
- // Parse LTO plugin-related options for compatibility with gold.
- for (auto *Arg : Args.filtered(OPT_plugin_opt, OPT_plugin_opt_eq)) {
- StringRef S = Arg->getValue();
- if (S == "disable-verify")
- Config->DisableVerify = true;
- else if (S == "save-temps")
- Config->SaveTemps = true;
- else if (S.startswith("O"))
- Config->LTOO = parseInt(S.substr(1), Arg);
- else if (S.startswith("lto-partitions="))
- Config->LTOPartitions = parseInt(S.substr(15), Arg);
- else if (S.startswith("jobs="))
- Config->ThinLTOJobs = parseInt(S.substr(5), Arg);
- else if (!S.startswith("/") && !S.startswith("-fresolution=") &&
- !S.startswith("-pass-through=") && !S.startswith("mcpu=") &&
- !S.startswith("thinlto") && S != "-function-sections" &&
- S != "-data-sections")
- error(Arg->getSpelling() + ": unknown option: " + S);
- }
+ // Parse LTO options.
+ if (auto *Arg = Args.getLastArg(OPT_plugin_opt_mcpu_eq))
+ parseClangOption(Saver.save("-mcpu=" + StringRef(Arg->getValue())),
+ Arg->getSpelling());
+
+ for (auto *Arg : Args.filtered(OPT_plugin_opt))
+ parseClangOption(Arg->getValue(), Arg->getSpelling());
+
+ // Parse -mllvm options.
+ for (auto *Arg : Args.filtered(OPT_mllvm))
+ parseClangOption(Arg->getValue(), Arg->getSpelling());
if (Config->LTOO > 3)
error("invalid optimization level for LTO: " + Twine(Config->LTOO));
@@ -743,17 +912,12 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args);
- if (auto *Arg = Args.getLastArg(OPT_pack_dyn_relocs_eq)) {
- StringRef S = Arg->getValue();
- if (S == "android")
- Config->AndroidPackDynRelocs = true;
- else if (S != "none")
- error("unknown -pack-dyn-relocs format: " + S);
- }
+ std::tie(Config->AndroidPackDynRelocs, Config->RelrPackDynRelocs) =
+ getPackDynRelocs(Args);
if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file))
if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
- Config->SymbolOrderingFile = args::getLines(*Buffer);
+ Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer);
// If --retain-symbol-file is used, we'll keep only the symbols listed in
// the file and discard all others.
@@ -781,32 +945,67 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
{Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false});
}
+ // If --export-dynamic-symbol=foo is given and symbol foo is defined in
+ // an object file in an archive file, that object file should be pulled
+ // out and linked. (It doesn't have to behave like that from technical
+ // point of view, but this is needed for compatibility with GNU.)
+ for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
+ Config->Undefined.push_back(Arg->getValue());
+
for (auto *Arg : Args.filtered(OPT_version_script))
- if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
- readVersionScript(*Buffer);
+ if (Optional<std::string> Path = searchScript(Arg->getValue())) {
+ if (Optional<MemoryBufferRef> Buffer = readFile(*Path))
+ readVersionScript(*Buffer);
+ } else {
+ error(Twine("cannot find version script ") + Arg->getValue());
+ }
}
// Some Config members do not directly correspond to any particular
// command line options, but computed based on other Config values.
// This function initialize such members. See Config.h for the details
// of these values.
-static void setConfigs() {
+static void setConfigs(opt::InputArgList &Args) {
ELFKind Kind = Config->EKind;
uint16_t Machine = Config->EMachine;
- // There is an ILP32 ABI for x86-64, although it's not very popular.
- // It is called the x32 ABI.
- bool IsX32 = (Kind == ELF32LEKind && Machine == EM_X86_64);
-
Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs);
Config->Is64 = (Kind == ELF64LEKind || Kind == ELF64BEKind);
Config->IsLE = (Kind == ELF32LEKind || Kind == ELF64LEKind);
Config->Endianness =
Config->IsLE ? support::endianness::little : support::endianness::big;
Config->IsMips64EL = (Kind == ELF64LEKind && Machine == EM_MIPS);
- Config->IsRela = Config->Is64 || IsX32 || Config->MipsN32Abi;
Config->Pic = Config->Pie || Config->Shared;
Config->Wordsize = Config->Is64 ? 8 : 4;
+
+ // There is an ILP32 ABI for x86-64, although it's not very popular.
+ // It is called the x32 ABI.
+ bool IsX32 = (Kind == ELF32LEKind && Machine == EM_X86_64);
+
+ // ELF defines two different ways to store relocation addends as shown below:
+ //
+ // Rel: Addends are stored to the location where relocations are applied.
+ // Rela: Addends are stored as part of relocation entry.
+ //
+ // In other words, Rela makes it easy to read addends at the price of extra
+ // 4 or 8 byte for each relocation entry. We don't know why ELF defined two
+ // different mechanisms in the first place, but this is how the spec is
+ // defined.
+ //
+ // You cannot choose which one, Rel or Rela, you want to use. Instead each
+ // ABI defines which one you need to use. The following expression expresses
+ // that.
+ Config->IsRela =
+ (Config->Is64 || IsX32 || Machine == EM_PPC) && Machine != EM_MIPS;
+
+ // If the output uses REL relocations we must store the dynamic relocation
+ // addends to the output sections. We also store addends for RELA relocations
+ // if --apply-dynamic-relocs is used.
+ // We default to not writing the addends when using RELA relocations since
+ // any standard conforming tool can find it in r_addend.
+ Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs,
+ OPT_no_apply_dynamic_relocs, false) ||
+ !Config->IsRela;
}
// Returns a value of "-format" option.
@@ -821,6 +1020,10 @@ static bool getBinaryOption(StringRef S) {
}
void LinkerDriver::createFiles(opt::InputArgList &Args) {
+ // For --{push,pop}-state.
+ std::vector<std::tuple<bool, bool, bool>> Stack;
+
+ // Iterate over argv to process input files and positional arguments.
for (auto *Arg : Args) {
switch (Arg->getOption().getUnaliasedOption().getID()) {
case OPT_library:
@@ -829,8 +1032,15 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
case OPT_INPUT:
addFile(Arg->getValue(), /*WithLOption=*/false);
break;
+ case OPT_defsym: {
+ StringRef From;
+ StringRef To;
+ std::tie(From, To) = StringRef(Arg->getValue()).split('=');
+ readDefsym(From, MemoryBufferRef(To, "-defsym"));
+ break;
+ }
case OPT_script:
- if (Optional<std::string> Path = searchLinkerScript(Arg->getValue())) {
+ if (Optional<std::string> Path = searchScript(Arg->getValue())) {
if (Optional<MemoryBufferRef> MB = readFile(*Path))
readLinkerScript(*MB);
break;
@@ -858,11 +1068,48 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
case OPT_no_whole_archive:
InWholeArchive = false;
break;
+ case OPT_just_symbols:
+ if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) {
+ Files.push_back(createObjectFile(*MB));
+ Files.back()->JustSymbols = true;
+ }
+ break;
+ case OPT_start_group:
+ if (InputFile::IsInGroup)
+ error("nested --start-group");
+ InputFile::IsInGroup = true;
+ break;
+ case OPT_end_group:
+ if (!InputFile::IsInGroup)
+ error("stray --end-group");
+ InputFile::IsInGroup = false;
+ ++InputFile::NextGroupId;
+ break;
case OPT_start_lib:
+ if (InLib)
+ error("nested --start-lib");
+ if (InputFile::IsInGroup)
+ error("may not nest --start-lib in --start-group");
InLib = true;
+ InputFile::IsInGroup = true;
break;
case OPT_end_lib:
+ if (!InLib)
+ error("stray --end-lib");
InLib = false;
+ InputFile::IsInGroup = false;
+ ++InputFile::NextGroupId;
+ break;
+ case OPT_push_state:
+ Stack.emplace_back(Config->AsNeeded, Config->Static, InWholeArchive);
+ break;
+ case OPT_pop_state:
+ if (Stack.empty()) {
+ error("unbalanced --push-state/--pop-state");
+ break;
+ }
+ std::tie(Config->AsNeeded, Config->Static, InWholeArchive) = Stack.back();
+ Stack.pop_back();
break;
}
}
@@ -935,14 +1182,6 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {
return Ret;
}
-static Optional<StringRef> getArchiveName(InputFile *File) {
- if (isa<ArchiveFile>(File))
- return File->getName();
- if (!File->ArchiveName.empty())
- return File->ArchiveName;
- return None;
-}
-
// Handles the -exclude-libs option. If a static library file is specified
// by the -exclude-libs option, all public symbols from the archive become
// private unless otherwise specified by version scripts or something.
@@ -950,18 +1189,140 @@ static Optional<StringRef> getArchiveName(InputFile *File) {
//
// This is not a popular option, but some programs such as bionic libc use it.
template <class ELFT>
-static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) {
+static void excludeLibs(opt::InputArgList &Args) {
DenseSet<StringRef> Libs = getExcludeLibs(Args);
bool All = Libs.count("ALL");
- for (InputFile *File : Files)
- if (Optional<StringRef> Archive = getArchiveName(File))
- if (All || Libs.count(path::filename(*Archive)))
+ auto Visit = [&](InputFile *File) {
+ if (!File->ArchiveName.empty())
+ if (All || Libs.count(path::filename(File->ArchiveName)))
for (Symbol *Sym : File->getSymbols())
- if (!Sym->isLocal())
+ if (!Sym->isLocal() && Sym->File == File)
Sym->VersionId = VER_NDX_LOCAL;
+ };
+
+ for (InputFile *File : ObjectFiles)
+ Visit(File);
+
+ for (BitcodeFile *File : BitcodeFiles)
+ Visit(File);
+}
+
+// Force Sym to be entered in the output. Used for -u or equivalent.
+template <class ELFT> static void handleUndefined(StringRef Name) {
+ Symbol *Sym = Symtab->find(Name);
+ if (!Sym)
+ return;
+
+ // Since symbol S may not be used inside the program, LTO may
+ // eliminate it. Mark the symbol as "used" to prevent it.
+ Sym->IsUsedInRegularObj = true;
+
+ if (Sym->isLazy())
+ Symtab->fetchLazy<ELFT>(Sym);
+}
+
+template <class ELFT> static bool shouldDemote(Symbol &Sym) {
+ // If all references to a DSO happen to be weak, the DSO is not added to
+ // DT_NEEDED. If that happens, we need to eliminate shared symbols created
+ // from the DSO. Otherwise, they become dangling references that point to a
+ // non-existent DSO.
+ if (auto *S = dyn_cast<SharedSymbol>(&Sym))
+ return !S->getFile<ELFT>().IsNeeded;
+
+ // We are done processing archives, so lazy symbols that were used but not
+ // found can be converted to undefined. We could also just delete the other
+ // lazy symbols, but that seems to be more work than it is worth.
+ return Sym.isLazy() && Sym.IsUsedInRegularObj;
}
+// Some files, such as .so or files between -{start,end}-lib may be removed
+// after their symbols are added to the symbol table. If that happens, we
+// need to remove symbols that refer files that no longer exist, so that
+// they won't appear in the symbol table of the output file.
+//
+// We remove symbols by demoting them to undefined symbol.
+template <class ELFT> static void demoteSymbols() {
+ for (Symbol *Sym : Symtab->getSymbols()) {
+ if (shouldDemote<ELFT>(*Sym)) {
+ bool Used = Sym->Used;
+ replaceSymbol<Undefined>(Sym, nullptr, Sym->getName(), Sym->Binding,
+ Sym->StOther, Sym->Type);
+ Sym->Used = Used;
+ }
+ }
+}
+
+// The section referred to by S is considered address-significant. Set the
+// KeepUnique flag on the section if appropriate.
+static void markAddrsig(Symbol *S) {
+ if (auto *D = dyn_cast_or_null<Defined>(S))
+ if (D->Section)
+ // We don't need to keep text sections unique under --icf=all even if they
+ // are address-significant.
+ if (Config->ICF == ICFLevel::Safe || !(D->Section->Flags & SHF_EXECINSTR))
+ D->Section->KeepUnique = true;
+}
+
+// Record sections that define symbols mentioned in --keep-unique <symbol>
+// and symbols referred to by address-significance tables. These sections are
+// ineligible for ICF.
+template <class ELFT>
+static void findKeepUniqueSections(opt::InputArgList &Args) {
+ for (auto *Arg : Args.filtered(OPT_keep_unique)) {
+ StringRef Name = Arg->getValue();
+ auto *D = dyn_cast_or_null<Defined>(Symtab->find(Name));
+ if (!D || !D->Section) {
+ warn("could not find symbol " + Name + " to keep unique");
+ continue;
+ }
+ D->Section->KeepUnique = true;
+ }
+
+ // --icf=all --ignore-data-address-equality means that we can ignore
+ // the dynsym and address-significance tables entirely.
+ if (Config->ICF == ICFLevel::All && Config->IgnoreDataAddressEquality)
+ return;
+
+ // Symbols in the dynsym could be address-significant in other executables
+ // or DSOs, so we conservatively mark them as address-significant.
+ for (Symbol *S : Symtab->getSymbols())
+ if (S->includeInDynsym())
+ markAddrsig(S);
+
+ // Visit the address-significance table in each object file and mark each
+ // referenced symbol as address-significant.
+ for (InputFile *F : ObjectFiles) {
+ auto *Obj = cast<ObjFile<ELFT>>(F);
+ ArrayRef<Symbol *> Syms = Obj->getSymbols();
+ if (Obj->AddrsigSec) {
+ ArrayRef<uint8_t> Contents =
+ check(Obj->getObj().getSectionContents(Obj->AddrsigSec));
+ const uint8_t *Cur = Contents.begin();
+ while (Cur != Contents.end()) {
+ unsigned Size;
+ const char *Err;
+ uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);
+ if (Err)
+ fatal(toString(F) + ": could not decode addrsig section: " + Err);
+ markAddrsig(Syms[SymIndex]);
+ Cur += Size;
+ }
+ } else {
+ // If an object file does not have an address-significance table,
+ // conservatively mark all of its symbols as address-significant.
+ for (Symbol *S : Syms)
+ markAddrsig(S);
+ }
+ }
+}
+
+static const char *LibcallRoutineNames[] = {
+#define HANDLE_LIBCALL(code, name) name,
+#include "llvm/IR/RuntimeLibcalls.def"
+#undef HANDLE_LIBCALL
+};
+
// Do actual linking. Note that when this function is called,
// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
@@ -1010,14 +1371,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (InputFile *F : Files)
Symtab->addFile<ELFT>(F);
- // Process -defsym option.
- for (auto *Arg : Args.filtered(OPT_defsym)) {
- StringRef From;
- StringRef To;
- std::tie(From, To) = StringRef(Arg->getValue()).split('=');
- readDefsym(From, MemoryBufferRef(To, "-defsym"));
- }
-
// Now that we have every file, we can decide if we will need a
// dynamic symbol table.
// We need one if we were asked to export dynamic symbols or if we are
@@ -1034,24 +1387,39 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// Handle the `--undefined <sym>` options.
for (StringRef S : Config->Undefined)
- Symtab->fetchIfLazy<ELFT>(S);
+ handleUndefined<ELFT>(S);
- // If an entry symbol is in a static archive, pull out that file now
- // to complete the symbol table. After this, no new names except a
- // few linker-synthesized ones will be added to the symbol table.
- Symtab->fetchIfLazy<ELFT>(Config->Entry);
+ // If an entry symbol is in a static archive, pull out that file now.
+ handleUndefined<ELFT>(Config->Entry);
+
+ // If any of our inputs are bitcode files, the LTO code generator may create
+ // references to certain library functions that might not be explicit in the
+ // bitcode file's symbol table. If any of those library functions are defined
+ // in a bitcode file in an archive member, we need to arrange to use LTO to
+ // compile those archive members by adding them to the link beforehand.
+ //
+ // With this the symbol table should be complete. After this, no new names
+ // except a few linker-synthesized ones will be added to the symbol table.
+ if (!BitcodeFiles.empty())
+ for (const char *S : LibcallRoutineNames)
+ handleUndefined<ELFT>(S);
// Return if there were name resolution errors.
if (errorCount())
return;
- // Handle undefined symbols in DSOs.
- if (!Config->Shared)
- Symtab->scanShlibUndefined<ELFT>();
+ // Now when we read all script files, we want to finalize order of linker
+ // script commands, which can be not yet final because of INSERT commands.
+ Script->processInsertCommands();
+
+ // We want to declare linker script's symbols early,
+ // so that we can version them.
+ // They also might be exported if referenced by DSOs.
+ Script->declareSymbols();
// Handle the -exclude-libs option.
if (Args.hasArg(OPT_exclude_libs))
- excludeLibs<ELFT>(Args, Files);
+ excludeLibs<ELFT>(Args);
// Create ElfHeader early. We need a dummy section in
// addReservedSymbols to mark the created symbols as not absolute.
@@ -1074,10 +1442,18 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_wrap))
Symtab->addSymbolWrap<ELFT>(Arg->getValue());
+ // Do link-time optimization if given files are LLVM bitcode files.
+ // This compiles bitcode files into real object files.
Symtab->addCombinedLTOObject<ELFT>();
if (errorCount())
return;
+ // If -thinlto-index-only is given, we should create only "index
+ // files" and not object files. Index file creation is already done
+ // in addCombinedLTOObject, so we are done if that's the case.
+ if (Config->ThinLTOIndexOnly)
+ return;
+
// Apply symbol renames for -wrap.
Symtab->applySymbolWrap();
@@ -1124,11 +1500,20 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// Do size optimizations: garbage collection, merging of SHF_MERGE sections
// and identical code folding.
- markLive<ELFT>();
decompressSections();
+ splitSections<ELFT>();
+ markLive<ELFT>();
+ demoteSymbols<ELFT>();
mergeSections();
- if (Config->ICF)
+ if (Config->ICF != ICFLevel::None) {
+ findKeepUniqueSections<ELFT>(Args);
doIcf<ELFT>();
+ }
+
+ // Read the callgraph now that we know what was gced or icfed
+ if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file))
+ if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
+ readCallGraph(*Buffer);
// Write the result to the file.
writeResult<ELFT>();
diff --git a/contrib/llvm/tools/lld/ELF/Driver.h b/contrib/llvm/tools/lld/ELF/Driver.h
index 7d2ad7b9cfde..3804fa20f2d3 100644
--- a/contrib/llvm/tools/lld/ELF/Driver.h
+++ b/contrib/llvm/tools/lld/ELF/Driver.h
@@ -26,7 +26,7 @@ extern class LinkerDriver *Driver;
class LinkerDriver {
public:
- void main(ArrayRef<const char *> Args, bool CanExitEarly);
+ void main(ArrayRef<const char *> Args);
void addFile(StringRef Path, bool WithLOption);
void addLibrary(StringRef Name);
@@ -63,11 +63,11 @@ enum {
#undef OPTION
};
-void printHelp(const char *Argv0);
+void printHelp();
std::string createResponseFile(const llvm::opt::InputArgList &Args);
llvm::Optional<std::string> findFromSearchPaths(StringRef Path);
-llvm::Optional<std::string> searchLinkerScript(StringRef Path);
+llvm::Optional<std::string> searchScript(StringRef Path);
llvm::Optional<std::string> searchLibrary(StringRef Path);
} // namespace elf
diff --git a/contrib/llvm/tools/lld/ELF/DriverUtils.cpp b/contrib/llvm/tools/lld/ELF/DriverUtils.cpp
index 774de9f1d03c..c8ca622b0628 100644
--- a/contrib/llvm/tools/lld/ELF/DriverUtils.cpp
+++ b/contrib/llvm/tools/lld/ELF/DriverUtils.cpp
@@ -29,6 +29,7 @@
using namespace llvm;
using namespace llvm::sys;
+using namespace llvm::opt;
using namespace lld;
using namespace lld::elf;
@@ -58,18 +59,18 @@ static void handleColorDiagnostics(opt::InputArgList &Args) {
OPT_no_color_diagnostics);
if (!Arg)
return;
- else if (Arg->getOption().getID() == OPT_color_diagnostics)
+ if (Arg->getOption().getID() == OPT_color_diagnostics) {
errorHandler().ColorDiagnostics = true;
- else if (Arg->getOption().getID() == OPT_no_color_diagnostics)
+ } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) {
errorHandler().ColorDiagnostics = false;
- else {
+ } else {
StringRef S = Arg->getValue();
if (S == "always")
errorHandler().ColorDiagnostics = true;
else if (S == "never")
errorHandler().ColorDiagnostics = false;
else if (S != "auto")
- error("unknown option: -color-diagnostics=" + S);
+ error("unknown option: --color-diagnostics=" + S);
}
}
@@ -87,6 +88,29 @@ static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
return cl::TokenizeGNUCommandLine;
}
+// Gold LTO plugin takes a `--plugin-opt foo=bar` option as an alias for
+// `--plugin-opt=foo=bar`. We want to handle `--plugin-opt=foo=` as an
+// option name and `bar` as a value. Unfortunately, OptParser cannot
+// handle an option with a space in it.
+//
+// In this function, we concatenate command line arguments so that
+// `--plugin-opt <foo>` is converted to `--plugin-opt=<foo>`. This is a
+// bit hacky, but looks like it is still better than handling --plugin-opt
+// options by hand.
+static void concatLTOPluginOptions(SmallVectorImpl<const char *> &Args) {
+ SmallVector<const char *, 256> V;
+ for (size_t I = 0, E = Args.size(); I != E; ++I) {
+ StringRef S = Args[I];
+ if ((S == "-plugin-opt" || S == "--plugin-opt") && I + 1 != E) {
+ V.push_back(Saver.save(S + "=" + Args[I + 1]).data());
+ ++I;
+ } else {
+ V.push_back(Args[I]);
+ }
+ }
+ Args = std::move(V);
+}
+
// Parses a given list of options.
opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
// Make InputArgList from string vectors.
@@ -102,6 +126,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
// Expand response files (arguments in the form of @<filename>)
// and then parse the argument again.
cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
+ concatLTOPluginOptions(Vec);
Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
handleColorDiagnostics(Args);
@@ -113,9 +138,9 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
return Args;
}
-void elf::printHelp(const char *Argv0) {
- ELFOptTable().PrintHelp(outs(), Argv0, "lld", false /*ShowHidden*/,
- true /*ShowAllAliases*/);
+void elf::printHelp() {
+ ELFOptTable().PrintHelp(outs(), Config->ProgName.data(), "lld",
+ false /*ShowHidden*/, true /*ShowAllAliases*/);
outs() << "\n";
// Scripts generated by Libtool versions up to at least 2.4.6 (the most
@@ -123,13 +148,7 @@ void elf::printHelp(const char *Argv0) {
// in a message for the -help option. If it doesn't match, the scripts
// assume that the linker doesn't support very basic features such as
// shared libraries. Therefore, we need to print out at least "elf".
- // Here, we print out all the targets that we support.
- outs() << Argv0 << ": supported targets: "
- << "elf32-i386 elf32-iamcu elf32-littlearm elf32-ntradbigmips "
- << "elf32-ntradlittlemips elf32-powerpc elf32-tradbigmips "
- << "elf32-tradlittlemips elf32-x86-64 "
- << "elf64-amdgpu elf64-littleaarch64 elf64-powerpc elf64-tradbigmips "
- << "elf64-tradlittlemips elf64-x86-64\n";
+ outs() << Config->ProgName << ": supported targets: elf\n";
}
// Reconstructs command line arguments so that so that you can re-run
@@ -208,10 +227,10 @@ Optional<std::string> elf::searchLibrary(StringRef Name) {
return None;
}
-// If a linker script doesn't exist in the current directory, we also look for
-// the script in the '-L' search paths. This matches the behaviour of both '-T'
-// and linker script INPUT() directives in ld.bfd.
-Optional<std::string> elf::searchLinkerScript(StringRef Name) {
+// If a linker/version script doesn't exist in the current directory, we also
+// look for the script in the '-L' search paths. This matches the behaviour of
+// '-T', --version-script=, and linker script INPUT() command in ld.bfd.
+Optional<std::string> elf::searchScript(StringRef Name) {
if (fs::exists(Name))
return Name.str();
return findFromSearchPaths(Name);
diff --git a/contrib/llvm/tools/lld/ELF/EhFrame.cpp b/contrib/llvm/tools/lld/ELF/EhFrame.cpp
index 62abc3973e7e..20b32c0a96e6 100644
--- a/contrib/llvm/tools/lld/ELF/EhFrame.cpp
+++ b/contrib/llvm/tools/lld/ELF/EhFrame.cpp
@@ -20,18 +20,16 @@
#include "Config.h"
#include "InputSection.h"
#include "Relocations.h"
-#include "Strings.h"
-
+#include "Target.h"
#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Strings.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Object/ELF.h"
-#include "llvm/Support/Endian.h"
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::dwarf;
using namespace llvm::object;
-using namespace llvm::support::endian;
using namespace lld;
using namespace lld::elf;
@@ -73,7 +71,7 @@ size_t EhReader::readEhRecordSize() {
// First 4 bytes of CIE/FDE is the size of the record.
// If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
// but we do not support that format yet.
- uint64_t V = read32(D.data(), Config->Endianness);
+ uint64_t V = read32(D.data());
if (V == UINT32_MAX)
failOn(D.data(), "CIE/FDE too large");
uint64_t Size = V + 4;
diff --git a/contrib/llvm/tools/lld/ELF/Filesystem.cpp b/contrib/llvm/tools/lld/ELF/Filesystem.cpp
index 8d0b5d8a2f1c..5cf240eeca56 100644
--- a/contrib/llvm/tools/lld/ELF/Filesystem.cpp
+++ b/contrib/llvm/tools/lld/ELF/Filesystem.cpp
@@ -44,7 +44,7 @@ using namespace lld::elf;
// The calling thread returns almost immediately.
void elf::unlinkAsync(StringRef Path) {
// Removing a file is async on windows.
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
sys::fs::remove(Path);
#else
if (!ThreadsEnabled || !sys::fs::exists(Path) ||
diff --git a/contrib/llvm/tools/lld/ELF/GdbIndex.cpp b/contrib/llvm/tools/lld/ELF/GdbIndex.cpp
index d27b57f95938..85449a200647 100644
--- a/contrib/llvm/tools/lld/ELF/GdbIndex.cpp
+++ b/contrib/llvm/tools/lld/ELF/GdbIndex.cpp
@@ -34,7 +34,7 @@ template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *Obj) {
.Case(".debug_ranges", &RangeSection)
.Case(".debug_line", &LineSection)
.Default(nullptr)) {
- Sec->maybeUncompress();
+ Sec->maybeDecompress();
M->Data = toStringRef(Sec->Data);
M->Sec = Sec;
continue;
diff --git a/contrib/llvm/tools/lld/ELF/GdbIndex.h b/contrib/llvm/tools/lld/ELF/GdbIndex.h
index 41ae9d793c11..eba1ba22f879 100644
--- a/contrib/llvm/tools/lld/ELF/GdbIndex.h
+++ b/contrib/llvm/tools/lld/ELF/GdbIndex.h
@@ -49,7 +49,6 @@ public:
return LineSection;
}
StringRef getFileName() const override { return ""; }
- StringRef getCUIndexSection() const override { return ""; }
StringRef getAbbrevSection() const override { return AbbrevSection; }
StringRef getStringSection() const override { return StrSection; }
StringRef getGnuPubNamesSection() const override {
diff --git a/contrib/llvm/tools/lld/ELF/ICF.cpp b/contrib/llvm/tools/lld/ELF/ICF.cpp
index b1e12e0590d5..075938bd16b9 100644
--- a/contrib/llvm/tools/lld/ELF/ICF.cpp
+++ b/contrib/llvm/tools/lld/ELF/ICF.cpp
@@ -77,10 +77,13 @@
#include "Config.h"
#include "SymbolTable.h"
#include "Symbols.h"
+#include "SyntheticSections.h"
+#include "Writer.h"
#include "lld/Common/Threads.h"
-#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <atomic>
@@ -112,9 +115,9 @@ private:
size_t findBoundary(size_t Begin, size_t End);
void forEachClassRange(size_t Begin, size_t End,
- std::function<void(size_t, size_t)> Fn);
+ llvm::function_ref<void(size_t, size_t)> Fn);
- void forEachClass(std::function<void(size_t, size_t)> Fn);
+ void forEachClass(llvm::function_ref<void(size_t, size_t)> Fn);
std::vector<InputSection *> Sections;
@@ -153,23 +156,40 @@ private:
};
}
-// Returns a hash value for S. Note that the information about
-// relocation targets is not included in the hash value.
-template <class ELFT> static uint32_t getHash(InputSection *S) {
- return hash_combine(S->Flags, S->getSize(), S->NumRelocations, S->Data);
-}
-
// Returns true if section S is subject of ICF.
static bool isEligible(InputSection *S) {
- // Don't merge read only data sections unless --icf-data was passed.
- if (!(S->Flags & SHF_EXECINSTR) && !Config->ICFData)
+ if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC))
+ return false;
+
+ // Don't merge writable sections. .data.rel.ro sections are marked as writable
+ // but are semantically read-only.
+ if ((S->Flags & SHF_WRITE) && S->Name != ".data.rel.ro" &&
+ !S->Name.startswith(".data.rel.ro."))
return false;
- // .init and .fini contains instructions that must be executed to
- // initialize and finalize the process. They cannot and should not
- // be merged.
- return S->Live && (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE) &&
- S->Name != ".init" && S->Name != ".fini";
+ // SHF_LINK_ORDER sections are ICF'd as a unit with their dependent sections,
+ // so we don't consider them for ICF individually.
+ if (S->Flags & SHF_LINK_ORDER)
+ return false;
+
+ // Don't merge synthetic sections as their Data member is not valid and empty.
+ // The Data member needs to be valid for ICF as it is used by ICF to determine
+ // the equality of section contents.
+ if (isa<SyntheticSection>(S))
+ return false;
+
+ // .init and .fini contains instructions that must be executed to initialize
+ // and finalize the process. They cannot and should not be merged.
+ if (S->Name == ".init" || S->Name == ".fini")
+ return false;
+
+ // A user program may enumerate sections named with a C identifier using
+ // __start_* and __stop_* symbols. We cannot ICF any such sections because
+ // that could change program semantics.
+ if (isValidCIdentifier(S->Name))
+ return false;
+
+ return true;
}
// Split an equivalence class into smaller classes.
@@ -214,9 +234,6 @@ template <class ELFT>
template <class RelTy>
bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA,
const InputSection *SecB, ArrayRef<RelTy> RB) {
- if (RA.size() != RB.size())
- return false;
-
for (size_t I = 0; I < RA.size(); ++I) {
if (RA[I].r_offset != RB[I].r_offset ||
RA[I].getType(Config->IsMips64EL) != RB[I].getType(Config->IsMips64EL))
@@ -284,6 +301,13 @@ bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) {
A->getSize() != B->getSize() || A->Data != B->Data)
return false;
+ // If two sections have different output sections, we cannot merge them.
+ // FIXME: This doesn't do the right thing in the case where there is a linker
+ // script. We probably need to move output section assignment before ICF to
+ // get the correct behaviour here.
+ if (getOutputSectionName(A) != getOutputSectionName(B))
+ return false;
+
if (A->AreRelocsRela)
return constantEq(A, A->template relas<ELFT>(), B,
B->template relas<ELFT>());
@@ -350,17 +374,12 @@ template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t Begin, size_t End) {
// vector. Therefore, Sections vector can be considered as contiguous
// groups of sections, grouped by the class.
//
-// This function calls Fn on every group that starts within [Begin, End).
-// Note that a group must start in that range but doesn't necessarily
-// have to end before End.
+// This function calls Fn on every group within [Begin, End).
template <class ELFT>
void ICF<ELFT>::forEachClassRange(size_t Begin, size_t End,
- std::function<void(size_t, size_t)> Fn) {
- if (Begin > 0)
- Begin = findBoundary(Begin - 1, End);
-
+ llvm::function_ref<void(size_t, size_t)> Fn) {
while (Begin < End) {
- size_t Mid = findBoundary(Begin, Sections.size());
+ size_t Mid = findBoundary(Begin, End);
Fn(Begin, Mid);
Begin = Mid;
}
@@ -368,7 +387,7 @@ void ICF<ELFT>::forEachClassRange(size_t Begin, size_t End,
// Call Fn on each equivalence class.
template <class ELFT>
-void ICF<ELFT>::forEachClass(std::function<void(size_t, size_t)> Fn) {
+void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> Fn) {
// If threading is disabled or the number of sections are
// too small to use threading, call Fn sequentially.
if (!ThreadsEnabled || Sections.size() < 1024) {
@@ -380,16 +399,32 @@ void ICF<ELFT>::forEachClass(std::function<void(size_t, size_t)> Fn) {
Current = Cnt % 2;
Next = (Cnt + 1) % 2;
- // Split sections into 256 shards and call Fn in parallel.
- size_t NumShards = 256;
+ // Shard into non-overlapping intervals, and call Fn in parallel.
+ // The sharding must be completed before any calls to Fn are made
+ // so that Fn can modify the Chunks in its shard without causing data
+ // races.
+ const size_t NumShards = 256;
size_t Step = Sections.size() / NumShards;
- parallelForEachN(0, NumShards, [&](size_t I) {
- size_t End = (I == NumShards - 1) ? Sections.size() : (I + 1) * Step;
- forEachClassRange(I * Step, End, Fn);
+ size_t Boundaries[NumShards + 1];
+ Boundaries[0] = 0;
+ Boundaries[NumShards] = Sections.size();
+
+ parallelForEachN(1, NumShards, [&](size_t I) {
+ Boundaries[I] = findBoundary((I - 1) * Step, Sections.size());
+ });
+
+ parallelForEachN(1, NumShards + 1, [&](size_t I) {
+ if (Boundaries[I - 1] < Boundaries[I])
+ forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);
});
++Cnt;
}
+static void print(const Twine &S) {
+ if (Config->PrintIcfSections)
+ message(S);
+}
+
// The main function of ICF.
template <class ELFT> void ICF<ELFT>::run() {
// Collect sections to merge.
@@ -401,7 +436,7 @@ template <class ELFT> void ICF<ELFT>::run() {
// Initially, we use hash values to partition sections.
parallelForEach(Sections, [&](InputSection *S) {
// Set MSB to 1 to avoid collisions with non-hash IDs.
- S->Class[0] = getHash<ELFT>(S) | (1 << 31);
+ S->Class[0] = xxHash64(S->Data) | (1U << 31);
});
// From now on, sections in Sections vector are ordered so that sections
@@ -424,25 +459,21 @@ template <class ELFT> void ICF<ELFT>::run() {
log("ICF needed " + Twine(Cnt) + " iterations");
// Merge sections by the equivalence class.
- forEachClass([&](size_t Begin, size_t End) {
+ forEachClassRange(0, Sections.size(), [&](size_t Begin, size_t End) {
if (End - Begin == 1)
return;
-
- log("selected " + Sections[Begin]->Name);
+ print("selected section " + toString(Sections[Begin]));
for (size_t I = Begin + 1; I < End; ++I) {
- log(" removed " + Sections[I]->Name);
+ print(" removing identical section " + toString(Sections[I]));
Sections[Begin]->replace(Sections[I]);
+
+ // At this point we know sections merged are fully identical and hence
+ // we want to remove duplicate implicit dependencies such as link order
+ // and relocation sections.
+ for (InputSection *IS : Sections[I]->DependentSections)
+ IS->Live = false;
}
});
-
- // Mark ARM Exception Index table sections that refer to folded code
- // sections as not live. These sections have an implict dependency
- // via the link order dependency.
- if (Config->EMachine == EM_ARM)
- for (InputSectionBase *Sec : InputSections)
- if (auto *S = dyn_cast<InputSection>(Sec))
- if (S->Flags & SHF_LINK_ORDER)
- S->Live = S->getLinkOrderDep()->Live;
}
// ICF entry point function.
diff --git a/contrib/llvm/tools/lld/ELF/ICF.h b/contrib/llvm/tools/lld/ELF/ICF.h
index 24219855fc17..a6c8636ead6d 100644
--- a/contrib/llvm/tools/lld/ELF/ICF.h
+++ b/contrib/llvm/tools/lld/ELF/ICF.h
@@ -12,8 +12,10 @@
namespace lld {
namespace elf {
+
template <class ELFT> void doIcf();
-}
+
+} // namespace elf
} // namespace lld
#endif
diff --git a/contrib/llvm/tools/lld/ELF/InputFiles.cpp b/contrib/llvm/tools/lld/ELF/InputFiles.cpp
index dfd5bbf1e0fc..0eb605a556ae 100644
--- a/contrib/llvm/tools/lld/ELF/InputFiles.cpp
+++ b/contrib/llvm/tools/lld/ELF/InputFiles.cpp
@@ -38,14 +38,23 @@ using namespace llvm::sys::fs;
using namespace lld;
using namespace lld::elf;
+bool InputFile::IsInGroup;
+uint32_t InputFile::NextGroupId;
std::vector<BinaryFile *> elf::BinaryFiles;
std::vector<BitcodeFile *> elf::BitcodeFiles;
+std::vector<LazyObjFile *> elf::LazyObjFiles;
std::vector<InputFile *> elf::ObjectFiles;
std::vector<InputFile *> elf::SharedFiles;
TarWriter *elf::Tar;
-InputFile::InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
+InputFile::InputFile(Kind K, MemoryBufferRef M)
+ : MB(M), GroupId(NextGroupId), FileKind(K) {
+ // All files within the same --{start,end}-group get the same group ID.
+ // Otherwise, a new file will get a new group ID.
+ if (!IsInGroup)
+ ++NextGroupId;
+}
Optional<MemoryBufferRef> elf::readFile(StringRef Path) {
// The --chroot option changes our virtual root directory.
@@ -55,7 +64,7 @@ Optional<MemoryBufferRef> elf::readFile(StringRef Path) {
log(Path);
- auto MBOrErr = MemoryBuffer::getFile(Path);
+ auto MBOrErr = MemoryBuffer::getFile(Path, -1, false);
if (auto EC = MBOrErr.getError()) {
error("cannot open " + Path + ": " + EC.message());
return None;
@@ -115,51 +124,60 @@ std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
}
template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
- DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(this));
- const DWARFObject &Obj = Dwarf.getDWARFObj();
- DwarfLine.reset(new DWARFDebugLine);
+ Dwarf = llvm::make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this));
+ const DWARFObject &Obj = Dwarf->getDWARFObj();
DWARFDataExtractor LineData(Obj, Obj.getLineSection(), Config->IsLE,
Config->Wordsize);
- // The second parameter is offset in .debug_line section
- // for compilation unit (CU) of interest. We have only one
- // CU (object file), so offset is always 0.
- // FIXME: Provide the associated DWARFUnit if there is one. DWARF v5
- // needs it in order to find indirect strings.
- const DWARFDebugLine::LineTable *LT =
- DwarfLine->getOrParseLineTable(LineData, 0, nullptr);
-
- // Return if there is no debug information about CU available.
- if (!Dwarf.getNumCompileUnits())
- return;
-
- // Loop over variable records and insert them to VariableLoc.
- DWARFCompileUnit *CU = Dwarf.getCompileUnitAtIndex(0);
- for (const auto &Entry : CU->dies()) {
- DWARFDie Die(CU, &Entry);
- // Skip all tags that are not variables.
- if (Die.getTag() != dwarf::DW_TAG_variable)
+ for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf->compile_units()) {
+ auto Report = [](Error Err) {
+ handleAllErrors(std::move(Err),
+ [](ErrorInfoBase &Info) { warn(Info.message()); });
+ };
+ Expected<const DWARFDebugLine::LineTable *> ExpectedLT =
+ Dwarf->getLineTableForUnit(CU.get(), Report);
+ const DWARFDebugLine::LineTable *LT = nullptr;
+ if (ExpectedLT)
+ LT = *ExpectedLT;
+ else
+ Report(ExpectedLT.takeError());
+ if (!LT)
continue;
+ LineTables.push_back(LT);
- // Skip if a local variable because we don't need them for generating error
- // messages. In general, only non-local symbols can fail to be linked.
- if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
- continue;
+ // Loop over variable records and insert them to VariableLoc.
+ for (const auto &Entry : CU->dies()) {
+ DWARFDie Die(CU.get(), &Entry);
+ // Skip all tags that are not variables.
+ if (Die.getTag() != dwarf::DW_TAG_variable)
+ continue;
- // Get the source filename index for the variable.
- unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
- if (!LT->hasFileAtIndex(File))
- continue;
+ // Skip if a local variable because we don't need them for generating
+ // error messages. In general, only non-local symbols can fail to be
+ // linked.
+ if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
+ continue;
- // Get the line number on which the variable is declared.
- unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
+ // Get the source filename index for the variable.
+ unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
+ if (!LT->hasFileAtIndex(File))
+ continue;
- // Get the name of the variable and add the collected information to
- // VariableLoc. Usually Name is non-empty, but it can be empty if the input
- // object file lacks some debug info.
- StringRef Name = dwarf::toString(Die.find(dwarf::DW_AT_name), "");
- if (!Name.empty())
- VariableLoc.insert({Name, {File, Line}});
+ // Get the line number on which the variable is declared.
+ unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
+
+ // Here we want to take the variable name to add it into VariableLoc.
+ // Variable can have regular and linkage name associated. At first, we try
+ // to get linkage name as it can be different, for example when we have
+ // two variables in different namespaces of the same object. Use common
+ // name otherwise, but handle the case when it also absent in case if the
+ // input object file lacks some debug info.
+ StringRef Name =
+ dwarf::toString(Die.find(dwarf::DW_AT_linkage_name),
+ dwarf::toString(Die.find(dwarf::DW_AT_name), ""));
+ if (!Name.empty())
+ VariableLoc.insert({Name, {LT, File, Line}});
+ }
}
}
@@ -170,11 +188,6 @@ Optional<std::pair<std::string, unsigned>>
ObjFile<ELFT>::getVariableLoc(StringRef Name) {
llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
- // There is always only one CU so it's offset is 0.
- const DWARFDebugLine::LineTable *LT = DwarfLine->getLineTable(0);
- if (!LT)
- return None;
-
// Return if we have no debug information about data object.
auto It = VariableLoc.find(Name);
if (It == VariableLoc.end())
@@ -182,12 +195,12 @@ ObjFile<ELFT>::getVariableLoc(StringRef Name) {
// Take file name string from line table.
std::string FileName;
- if (!LT->getFileNameByIndex(
- It->second.first /* File */, nullptr,
+ if (!It->second.LT->getFileNameByIndex(
+ It->second.File, nullptr,
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))
return None;
- return std::make_pair(FileName, It->second.second /*Line*/);
+ return std::make_pair(FileName, It->second.Line);
}
// Returns source line information for a given offset
@@ -197,29 +210,15 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *S,
uint64_t Offset) {
llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
- // The offset to CU is 0.
- const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0);
- if (!Tbl)
- return None;
-
// Use fake address calcuated by adding section file offset and offset in
// section. See comments for ObjectInfo class.
DILineInfo Info;
- Tbl->getFileLineInfoForAddress(
- S->getOffsetInFile() + Offset, nullptr,
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info);
- if (Info.Line == 0)
- return None;
- return Info;
-}
-
-// Returns source line information for a given offset
-// using DWARF debug info.
-template <class ELFT>
-std::string ObjFile<ELFT>::getLineInfo(InputSectionBase *S, uint64_t Offset) {
- if (Optional<DILineInfo> Info = getDILineInfo(S, Offset))
- return Info->FileName + ":" + std::to_string(Info->Line);
- return "";
+ for (const llvm::DWARFDebugLine::LineTable *LT : LineTables)
+ if (LT->getFileLineInfoForAddress(
+ S->getOffsetInFile() + Offset, nullptr,
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info))
+ return Info;
+ return None;
}
// Returns "<internal>", "foo.a(bar.o)" or "baz.o".
@@ -249,7 +248,7 @@ ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {
template <class ELFT>
typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalELFSyms() {
- return makeArrayRef(ELFSyms.begin() + FirstNonLocal, ELFSyms.end());
+ return makeArrayRef(ELFSyms.begin() + FirstGlobal, ELFSyms.end());
}
template <class ELFT>
@@ -260,9 +259,9 @@ uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
template <class ELFT>
void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections,
const Elf_Shdr *Symtab) {
- FirstNonLocal = Symtab->sh_info;
+ FirstGlobal = Symtab->sh_info;
ELFSyms = CHECK(getObj().symbols(Symtab), this);
- if (FirstNonLocal == 0 || FirstNonLocal > ELFSyms.size())
+ if (FirstGlobal == 0 || FirstGlobal > ELFSyms.size())
fatal(toString(this) + ": invalid sh_info in symbol table");
StringTable =
@@ -278,17 +277,22 @@ ObjFile<ELFT>::ObjFile(MemoryBufferRef M, StringRef ArchiveName)
template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() {
if (this->Symbols.empty())
return {};
- return makeArrayRef(this->Symbols).slice(1, this->FirstNonLocal - 1);
+ return makeArrayRef(this->Symbols).slice(1, this->FirstGlobal - 1);
}
template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getGlobalSymbols() {
- return makeArrayRef(this->Symbols).slice(this->FirstNonLocal);
+ return makeArrayRef(this->Symbols).slice(this->FirstGlobal);
}
template <class ELFT>
void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
- // Read section and symbol tables.
- initializeSections(ComdatGroups);
+ // Read a section table. JustSymbols is usually false.
+ if (this->JustSymbols)
+ initializeJustSymbols();
+ else
+ initializeSections(ComdatGroups);
+
+ // Read a symbol table.
initializeSymbols();
}
@@ -312,7 +316,7 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
// we use a section name as a signature.
//
// Such SHT_GROUP sections are invalid from the perspective of the ELF
- // standard, but GNU gold 1.14 (the neweset version as of July 2017) or
+ // standard, but GNU gold 1.14 (the newest version as of July 2017) or
// older produce such sections as outputs for the -r option, so we need
// a bug-compatibility.
if (Signature.empty() && Sym->getType() == STT_SECTION)
@@ -332,9 +336,19 @@ ObjFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
}
template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
- // We don't merge sections if -O0 (default is -O1). This makes sometimes
- // the linker significantly faster, although the output will be bigger.
- if (Config->Optimize == 0)
+ // On a regular link we don't merge sections if -O0 (default is -O1). This
+ // sometimes makes the linker significantly faster, although the output will
+ // be bigger.
+ //
+ // Doing the same for -r would create a problem as it would combine sections
+ // with different sh_entsize. One option would be to just copy every SHF_MERGE
+ // section as is to the output. While this would produce a valid ELF file with
+ // usable SHF_MERGE sections, tools like (llvm-)?dwarfdump get confused when
+ // they see two .debug_str. We could have separate logic for combining
+ // SHF_MERGE sections based both on their name and sh_entsize, but that seems
+ // to be more trouble than it is worth. Instead, we just use the regular (-O1)
+ // logic for -r.
+ if (Config->Optimize == 0 && !Config->Relocatable)
return false;
// A mergeable section with size 0 is useless because they don't have
@@ -365,12 +379,33 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
return true;
}
+// This is for --just-symbols.
+//
+// --just-symbols is a very minor feature that allows you to link your
+// output against other existing program, so that if you load both your
+// program and the other program into memory, your output can refer the
+// other program's symbols.
+//
+// When the option is given, we link "just symbols". The section table is
+// initialized with null pointers.
+template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
+ ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this);
+ this->Sections.resize(ObjSections.size());
+
+ for (const Elf_Shdr &Sec : ObjSections) {
+ if (Sec.sh_type != SHT_SYMTAB)
+ continue;
+ this->initSymtab(ObjSections, &Sec);
+ return;
+ }
+}
+
template <class ELFT>
void ObjFile<ELFT>::initializeSections(
DenseSet<CachedHashStringRef> &ComdatGroups) {
const ELFFile<ELFT> &Obj = this->getObj();
- ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this);
+ ArrayRef<Elf_Shdr> ObjSections = CHECK(Obj.sections(), this);
uint64_t Size = ObjSections.size();
this->Sections.resize(Size);
this->SectionStringTable =
@@ -385,6 +420,17 @@ void ObjFile<ELFT>::initializeSections(
// if -r is given, we'll let the final link discard such sections.
// This is compatible with GNU.
if ((Sec.sh_flags & SHF_EXCLUDE) && !Config->Relocatable) {
+ if (Sec.sh_type == SHT_LLVM_ADDRSIG) {
+ // We ignore the address-significance table if we know that the object
+ // file was created by objcopy or ld -r. This is because these tools
+ // will reorder the symbols in the symbol table, invalidating the data
+ // in the address-significance table, which refers to symbols by index.
+ if (Sec.sh_link != 0)
+ this->AddrsigSec = &Sec;
+ else if (Config->ICF == ICFLevel::Safe)
+ warn(toString(this) + ": --icf=safe is incompatible with object "
+ "files created using objcopy or ld -r");
+ }
this->Sections[I] = &InputSection::Discarded;
continue;
}
@@ -435,8 +481,15 @@ void ObjFile<ELFT>::initializeSections(
if (Sec.sh_link >= this->Sections.size())
fatal(toString(this) +
": invalid sh_link index: " + Twine(Sec.sh_link));
- this->Sections[Sec.sh_link]->DependentSections.push_back(
- cast<InputSection>(this->Sections[I]));
+
+ InputSectionBase *LinkSec = this->Sections[Sec.sh_link];
+ InputSection *IS = cast<InputSection>(this->Sections[I]);
+ LinkSec->DependentSections.push_back(IS);
+ if (!isa<InputSection>(LinkSec))
+ error("a section " + IS->Name +
+ " with SHF_LINK_ORDER should not refer a non-regular "
+ "section: " +
+ toString(LinkSec));
}
}
}
@@ -573,10 +626,11 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
}
case SHT_RELA:
case SHT_REL: {
- // Find the relocation target section and associate this
- // section with it. Target can be discarded, for example
- // if it is a duplicated member of SHT_GROUP section, we
- // do not create or proccess relocatable sections then.
+ // Find a relocation target section and associate this section with that.
+ // Target may have been discarded if it is in a different section group
+ // and the group is discarded, even though it's a violation of the
+ // spec. We handle that situation gracefully by discarding dangling
+ // relocation sections.
InputSectionBase *Target = getRelocTarget(Sec);
if (!Target)
return nullptr;
@@ -591,32 +645,28 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
fatal(toString(this) +
": multiple relocation sections to one section are not supported");
- // Mergeable sections with relocations are tricky because relocations
- // need to be taken into account when comparing section contents for
- // merging. It's not worth supporting such mergeable sections because
- // they are rare and it'd complicates the internal design (we usually
- // have to determine if two sections are mergeable early in the link
- // process much before applying relocations). We simply handle mergeable
- // sections with relocations as non-mergeable.
+ // ELF spec allows mergeable sections with relocations, but they are
+ // rare, and it is in practice hard to merge such sections by contents,
+ // because applying relocations at end of linking changes section
+ // contents. So, we simply handle such sections as non-mergeable ones.
+ // Degrading like this is acceptable because section merging is optional.
if (auto *MS = dyn_cast<MergeInputSection>(Target)) {
Target = toRegularSection(MS);
this->Sections[Sec.sh_info] = Target;
}
- size_t NumRelocations;
if (Sec.sh_type == SHT_RELA) {
ArrayRef<Elf_Rela> Rels = CHECK(this->getObj().relas(&Sec), this);
Target->FirstRelocation = Rels.begin();
- NumRelocations = Rels.size();
+ Target->NumRelocations = Rels.size();
Target->AreRelocsRela = true;
} else {
ArrayRef<Elf_Rel> Rels = CHECK(this->getObj().rels(&Sec), this);
Target->FirstRelocation = Rels.begin();
- NumRelocations = Rels.size();
+ Target->NumRelocations = Rels.size();
Target->AreRelocsRela = false;
}
- assert(isUInt<31>(NumRelocations));
- Target->NumRelocations = NumRelocations;
+ assert(isUInt<31>(Target->NumRelocations));
// Relocation sections processed by the linker are usually removed
// from the output, so returning `nullptr` for the normal case.
@@ -648,13 +698,24 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
if (Name == ".note.GNU-stack")
return &InputSection::Discarded;
- // Split stacks is a feature to support a discontiguous stack. At least
- // as of 2017, it seems that the feature is not being used widely.
- // Only GNU gold supports that. We don't. For the details about that,
- // see https://gcc.gnu.org/wiki/SplitStacks
+ // Split stacks is a feature to support a discontiguous stack,
+ // commonly used in the programming language Go. For the details,
+ // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
+ // for split stack will include a .note.GNU-split-stack section.
if (Name == ".note.GNU-split-stack") {
- error(toString(this) +
- ": object file compiled with -fsplit-stack is not supported");
+ if (Config->Relocatable) {
+ error("Cannot mix split-stack and non-split-stack in a relocatable link");
+ return &InputSection::Discarded;
+ }
+ this->SplitStack = true;
+ return &InputSection::Discarded;
+ }
+
+ // An object file cmpiled for split stack, but where some of the
+ // functions were compiled with the no_split_stack_attribute will
+ // include a .note.GNU-no-split-stack section.
+ if (Name == ".note.GNU-no-split-stack") {
+ this->SomeNoSplitStack = true;
return &InputSection::Discarded;
}
@@ -666,6 +727,14 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
if (Name.startswith(".gnu.linkonce."))
return &InputSection::Discarded;
+ // If we are creating a new .build-id section, strip existing .build-id
+ // sections so that the output won't have more than one .build-id.
+ // This is not usually a problem because input object files normally don't
+ // have .build-id sections, but you can create such files by
+ // "ld.{bfd,gold,lld} -r --build-id", and we want to guard against it.
+ if (Name == ".note.gnu.build-id" && Config->BuildId != BuildIdKind::None)
+ return &InputSection::Discarded;
+
// The linker merges EH (exception handling) frames and creates a
// .eh_frame_hdr section for runtime. So we handle them with a special
// class. For relocatable outputs, they are just passed through.
@@ -747,33 +816,33 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)
File(std::move(File)) {}
template <class ELFT> void ArchiveFile::parse() {
- Symbols.reserve(File->getNumberOfSymbols());
for (const Archive::Symbol &Sym : File->symbols())
- Symbols.push_back(Symtab->addLazyArchive<ELFT>(Sym.getName(), *this, Sym));
+ Symtab->addLazyArchive<ELFT>(Sym.getName(), *this, Sym);
}
// Returns a buffer pointing to a member file containing a given symbol.
-std::pair<MemoryBufferRef, uint64_t>
-ArchiveFile::getMember(const Archive::Symbol *Sym) {
+InputFile *ArchiveFile::fetch(const Archive::Symbol &Sym) {
Archive::Child C =
- CHECK(Sym->getMember(), toString(this) +
- ": could not get the member for symbol " +
- Sym->getName());
+ CHECK(Sym.getMember(), toString(this) +
+ ": could not get the member for symbol " +
+ Sym.getName());
if (!Seen.insert(C.getChildOffset()).second)
- return {MemoryBufferRef(), 0};
+ return nullptr;
- MemoryBufferRef Ret =
+ MemoryBufferRef MB =
CHECK(C.getMemoryBufferRef(),
toString(this) +
": could not get the buffer for the member defining symbol " +
- Sym->getName());
+ Sym.getName());
+
+ if (Tar && C.getParent()->isThin())
+ Tar->append(relativeToRoot(CHECK(C.getFullName(), this)), MB.getBuffer());
- if (C.getParent()->isThin() && Tar)
- Tar->append(relativeToRoot(CHECK(C.getFullName(), this)), Ret.getBuffer());
- if (C.getParent()->isThin())
- return {Ret, 0};
- return {Ret, C.getChildOffset()};
+ InputFile *File = createObjectFile(
+ MB, getName(), C.getParent()->isThin() ? 0 : C.getChildOffset());
+ File->GroupId = GroupId;
+ return File;
}
template <class ELFT>
@@ -830,34 +899,42 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
}
}
+// Parses ".gnu.version" section which is a parallel array for the symbol table.
+// If a given file doesn't have ".gnu.version" section, returns VER_NDX_GLOBAL.
+template <class ELFT> std::vector<uint32_t> SharedFile<ELFT>::parseVersyms() {
+ size_t Size = this->ELFSyms.size() - this->FirstGlobal;
+ if (!VersymSec)
+ return std::vector<uint32_t>(Size, VER_NDX_GLOBAL);
+
+ const char *Base = this->MB.getBuffer().data();
+ const Elf_Versym *Versym =
+ reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) +
+ this->FirstGlobal;
+
+ std::vector<uint32_t> Ret(Size);
+ for (size_t I = 0; I < Size; ++I)
+ Ret[I] = Versym[I].vs_index;
+ return Ret;
+}
+
// Parse the version definitions in the object file if present. Returns a vector
// whose nth element contains a pointer to the Elf_Verdef for version identifier
-// n. Version identifiers that are not definitions map to nullptr. The array
-// always has at least length 1.
+// n. Version identifiers that are not definitions map to nullptr.
template <class ELFT>
-std::vector<const typename ELFT::Verdef *>
-SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) {
- std::vector<const Elf_Verdef *> Verdefs(1);
- // We only need to process symbol versions for this DSO if it has both a
- // versym and a verdef section, which indicates that the DSO contains symbol
- // version definitions.
- if (!VersymSec || !VerdefSec)
- return Verdefs;
-
- // The location of the first global versym entry.
- const char *Base = this->MB.getBuffer().data();
- Versym = reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) +
- this->FirstNonLocal;
+std::vector<const typename ELFT::Verdef *> SharedFile<ELFT>::parseVerdefs() {
+ if (!VerdefSec)
+ return {};
// We cannot determine the largest verdef identifier without inspecting
// every Elf_Verdef, but both bfd and gold assign verdef identifiers
// sequentially starting from 1, so we predict that the largest identifier
// will be VerdefCount.
unsigned VerdefCount = VerdefSec->sh_info;
- Verdefs.resize(VerdefCount + 1);
+ std::vector<const Elf_Verdef *> Verdefs(VerdefCount + 1);
// Build the Verdefs array by following the chain of Elf_Verdef objects
// from the start of the .gnu.version_d section.
+ const char *Base = this->MB.getBuffer().data();
const char *Verdef = Base + VerdefSec->sh_offset;
for (unsigned I = 0; I != VerdefCount; ++I) {
auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef);
@@ -871,82 +948,99 @@ SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) {
return Verdefs;
}
+// We do not usually care about alignments of data in shared object
+// files because the loader takes care of it. However, if we promote a
+// DSO symbol to point to .bss due to copy relocation, we need to keep
+// the original alignment requirements. We infer it in this function.
+template <class ELFT>
+uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections,
+ const Elf_Sym &Sym) {
+ uint64_t Ret = UINT64_MAX;
+ if (Sym.st_value)
+ Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value);
+ if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size())
+ Ret = std::min<uint64_t>(Ret, Sections[Sym.st_shndx].sh_addralign);
+ return (Ret > UINT32_MAX) ? 0 : Ret;
+}
+
// Fully parse the shared object file. This must be called after parseSoName().
+//
+// This function parses symbol versions. If a DSO has version information,
+// the file has a ".gnu.version_d" section which contains symbol version
+// definitions. Each symbol is associated to one version through a table in
+// ".gnu.version" section. That table is a parallel array for the symbol
+// table, and each table entry contains an index in ".gnu.version_d".
+//
+// The special index 0 is reserved for VERF_NDX_LOCAL and 1 is for
+// VER_NDX_GLOBAL. There's no table entry for these special versions in
+// ".gnu.version_d".
+//
+// The file format for symbol versioning is perhaps a bit more complicated
+// than necessary, but you can easily understand the code if you wrap your
+// head around the data structure described above.
template <class ELFT> void SharedFile<ELFT>::parseRest() {
- // Create mapping from version identifiers to Elf_Verdef entries.
- const Elf_Versym *Versym = nullptr;
- Verdefs = parseVerdefs(Versym);
-
+ Verdefs = parseVerdefs(); // parse .gnu.version_d
+ std::vector<uint32_t> Versyms = parseVersyms(); // parse .gnu.version
ArrayRef<Elf_Shdr> Sections = CHECK(this->getObj().sections(), this);
+ // System libraries can have a lot of symbols with versions. Using a
+ // fixed buffer for computing the versions name (foo@ver) can save a
+ // lot of allocations.
+ SmallString<0> VersionedNameBuffer;
+
// Add symbols to the symbol table.
- Elf_Sym_Range Syms = this->getGlobalELFSyms();
- for (const Elf_Sym &Sym : Syms) {
- unsigned VersymIndex = VER_NDX_GLOBAL;
- if (Versym) {
- VersymIndex = Versym->vs_index;
- ++Versym;
- }
- bool Hidden = VersymIndex & VERSYM_HIDDEN;
- VersymIndex = VersymIndex & ~VERSYM_HIDDEN;
+ ArrayRef<Elf_Sym> Syms = this->getGlobalELFSyms();
+ for (size_t I = 0; I < Syms.size(); ++I) {
+ const Elf_Sym &Sym = Syms[I];
StringRef Name = CHECK(Sym.getName(this->StringTable), this);
if (Sym.isUndefined()) {
- Undefs.push_back(Name);
+ Symbol *S = Symtab->addUndefined<ELFT>(Name, Sym.getBinding(),
+ Sym.st_other, Sym.getType(),
+ /*CanOmitFromDynSym=*/false, this);
+ S->ExportDynamic = true;
continue;
}
+ // ELF spec requires that all local symbols precede weak or global
+ // symbols in each symbol table, and the index of first non-local symbol
+ // is stored to sh_info. If a local symbol appears after some non-local
+ // symbol, that's a violation of the spec.
if (Sym.getBinding() == STB_LOCAL) {
warn("found local symbol '" + Name +
"' in global part of symbol table in file " + toString(this));
continue;
}
- if (Config->EMachine == EM_MIPS) {
- // FIXME: MIPS BFD linker puts _gp_disp symbol into DSO files
- // and incorrectly assigns VER_NDX_LOCAL to this section global
- // symbol. Here is a workaround for this bug.
- if (Versym && VersymIndex == VER_NDX_LOCAL && Name == "_gp_disp")
- continue;
- }
-
- const Elf_Verdef *Ver = nullptr;
- if (VersymIndex != VER_NDX_GLOBAL) {
- if (VersymIndex >= Verdefs.size() || VersymIndex == VER_NDX_LOCAL) {
- error("corrupt input file: version definition index " +
- Twine(VersymIndex) + " for symbol " + Name +
- " is out of bounds\n>>> defined in " + toString(this));
- continue;
- }
- Ver = Verdefs[VersymIndex];
- } else {
- VersymIndex = 0;
- }
-
- // We do not usually care about alignments of data in shared object
- // files because the loader takes care of it. However, if we promote a
- // DSO symbol to point to .bss due to copy relocation, we need to keep
- // the original alignment requirements. We infer it here.
- uint64_t Alignment = 1;
- if (Sym.st_value)
- Alignment = 1ULL << countTrailingZeros((uint64_t)Sym.st_value);
- if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) {
- uint64_t SecAlign = Sections[Sym.st_shndx].sh_addralign;
- Alignment = std::min(Alignment, SecAlign);
- }
- if (Alignment > UINT32_MAX)
- error(toString(this) + ": alignment too large: " + Name);
+ // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly
+ // assigns VER_NDX_LOCAL to this section global symbol. Here is a
+ // workaround for this bug.
+ uint32_t Idx = Versyms[I] & ~VERSYM_HIDDEN;
+ if (Config->EMachine == EM_MIPS && Idx == VER_NDX_LOCAL &&
+ Name == "_gp_disp")
+ continue;
- if (!Hidden)
- Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex);
+ uint64_t Alignment = getAlignment(Sections, Sym);
+ if (!(Versyms[I] & VERSYM_HIDDEN))
+ Symtab->addShared(Name, *this, Sym, Alignment, Idx);
// Also add the symbol with the versioned name to handle undefined symbols
// with explicit versions.
- if (Ver) {
- StringRef VerName = this->StringTable.data() + Ver->getAux()->vda_name;
- Name = Saver.save(Name + "@" + VerName);
- Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex);
+ if (Idx == VER_NDX_GLOBAL)
+ continue;
+
+ if (Idx >= Verdefs.size() || Idx == VER_NDX_LOCAL) {
+ error("corrupt input file: version definition index " + Twine(Idx) +
+ " for symbol " + Name + " is out of bounds\n>>> defined in " +
+ toString(this));
+ continue;
}
+
+ StringRef VerName =
+ this->StringTable.data() + Verdefs[Idx]->getAux()->vda_name;
+ VersionedNameBuffer.clear();
+ Name = (Name + "@" + VerName).toStringRef(VersionedNameBuffer);
+ Symtab->addShared(Saver.save(Name), *this, Sym, Alignment, Idx);
}
}
@@ -979,8 +1073,9 @@ static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) {
case Triple::x86_64:
return EM_X86_64;
default:
- fatal(Path + ": could not infer e_machine from bitcode target triple " +
+ error(Path + ": could not infer e_machine from bitcode target triple " +
T.str());
+ return EM_NONE;
}
}
@@ -989,17 +1084,21 @@ BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,
: InputFile(BitcodeKind, MB) {
this->ArchiveName = ArchiveName;
- // Here we pass a new MemoryBufferRef which is identified by ArchiveName
- // (the fully resolved path of the archive) + member name + offset of the
- // member in the archive.
- // ThinLTO uses the MemoryBufferRef identifier to access its internal
- // data structures and if two archives define two members with the same name,
- // this causes a collision which result in only one of the objects being
- // taken into consideration at LTO time (which very likely causes undefined
- // symbols later in the link stage).
- MemoryBufferRef MBRef(MB.getBuffer(),
- Saver.save(ArchiveName + MB.getBufferIdentifier() +
- utostr(OffsetInArchive)));
+ std::string Path = MB.getBufferIdentifier().str();
+ if (Config->ThinLTOIndexOnly)
+ Path = replaceThinLTOSuffix(MB.getBufferIdentifier());
+
+ // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
+ // name. If two archives define two members with the same name, this
+ // causes a collision which result in only one of the objects being taken
+ // into consideration at LTO time (which very likely causes undefined
+ // symbols later in the link stage). So we append file offset to make
+ // filename unique.
+ MemoryBufferRef MBRef(
+ MB.getBuffer(),
+ Saver.save(ArchiveName + Path +
+ (ArchiveName.empty() ? "" : utostr(OffsetInArchive))));
+
Obj = CHECK(lto::InputFile::create(MBRef), this);
Triple T(Obj->getTargetTriple());
@@ -1023,7 +1122,7 @@ template <class ELFT>
static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
const lto::InputFile::Symbol &ObjSym,
BitcodeFile &F) {
- StringRef NameRef = Saver.save(ObjSym.getName());
+ StringRef Name = Saver.save(ObjSym.getName());
uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL;
uint8_t Type = ObjSym.isTLS() ? STT_TLS : STT_NOTYPE;
@@ -1032,20 +1131,20 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
int C = ObjSym.getComdatIndex();
if (C != -1 && !KeptComdats[C])
- return Symtab->addUndefined<ELFT>(NameRef, Binding, Visibility, Type,
+ return Symtab->addUndefined<ELFT>(Name, Binding, Visibility, Type,
CanOmitFromDynSym, &F);
if (ObjSym.isUndefined())
- return Symtab->addUndefined<ELFT>(NameRef, Binding, Visibility, Type,
+ return Symtab->addUndefined<ELFT>(Name, Binding, Visibility, Type,
CanOmitFromDynSym, &F);
if (ObjSym.isCommon())
- return Symtab->addCommon(NameRef, ObjSym.getCommonSize(),
+ return Symtab->addCommon(Name, ObjSym.getCommonSize(),
ObjSym.getCommonAlignment(), Binding, Visibility,
STT_OBJECT, F);
- return Symtab->addBitcode(NameRef, Binding, Visibility, Type,
- CanOmitFromDynSym, F);
+ return Symtab->addBitcode(Name, Binding, Visibility, Type, CanOmitFromDynSym,
+ F);
}
template <class ELFT>
@@ -1080,8 +1179,8 @@ static ELFKind getELFKind(MemoryBufferRef MB) {
void BinaryFile::parse() {
ArrayRef<uint8_t> Data = toArrayRef(MB.getBuffer());
- auto *Section = make<InputSection>(nullptr, SHF_ALLOC | SHF_WRITE,
- SHT_PROGBITS, 8, Data, ".data");
+ auto *Section = make<InputSection>(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
+ 8, Data, ".data");
Sections.push_back(Section);
// For each input file foo that is embedded to a result as a binary
@@ -1101,11 +1200,6 @@ void BinaryFile::parse() {
Data.size(), 0, STB_GLOBAL, nullptr, nullptr);
}
-static bool isBitcode(MemoryBufferRef MB) {
- using namespace sys::fs;
- return identify_magic(MB.getBuffer()) == file_magic::bitcode;
-}
-
InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName,
uint64_t OffsetInArchive) {
if (isBitcode(MB))
@@ -1141,9 +1235,9 @@ InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) {
}
MemoryBufferRef LazyObjFile::getBuffer() {
- if (Seen)
+ if (AddedToLink)
return MemoryBufferRef();
- Seen = true;
+ AddedToLink = true;
return MB;
}
@@ -1151,66 +1245,72 @@ InputFile *LazyObjFile::fetch() {
MemoryBufferRef MBRef = getBuffer();
if (MBRef.getBuffer().empty())
return nullptr;
- return createObjectFile(MBRef, ArchiveName, OffsetInArchive);
+
+ InputFile *File = createObjectFile(MBRef, ArchiveName, OffsetInArchive);
+ File->GroupId = GroupId;
+ return File;
}
template <class ELFT> void LazyObjFile::parse() {
- for (StringRef Sym : getSymbolNames())
- Symtab->addLazyObject<ELFT>(Sym, *this);
+ // A lazy object file wraps either a bitcode file or an ELF file.
+ if (isBitcode(this->MB)) {
+ std::unique_ptr<lto::InputFile> Obj =
+ CHECK(lto::InputFile::create(this->MB), this);
+ for (const lto::InputFile::Symbol &Sym : Obj->symbols())
+ if (!Sym.isUndefined())
+ Symtab->addLazyObject<ELFT>(Saver.save(Sym.getName()), *this);
+ return;
+ }
+
+ switch (getELFKind(this->MB)) {
+ case ELF32LEKind:
+ addElfSymbols<ELF32LE>();
+ return;
+ case ELF32BEKind:
+ addElfSymbols<ELF32BE>();
+ return;
+ case ELF64LEKind:
+ addElfSymbols<ELF64LE>();
+ return;
+ case ELF64BEKind:
+ addElfSymbols<ELF64BE>();
+ return;
+ default:
+ llvm_unreachable("getELFKind");
+ }
}
-template <class ELFT> std::vector<StringRef> LazyObjFile::getElfSymbols() {
- typedef typename ELFT::Shdr Elf_Shdr;
- typedef typename ELFT::Sym Elf_Sym;
- typedef typename ELFT::SymRange Elf_Sym_Range;
+template <class ELFT> void LazyObjFile::addElfSymbols() {
+ ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(MB.getBuffer()));
+ ArrayRef<typename ELFT::Shdr> Sections = CHECK(Obj.sections(), this);
- ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(this->MB.getBuffer()));
- ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this);
- for (const Elf_Shdr &Sec : Sections) {
+ for (const typename ELFT::Shdr &Sec : Sections) {
if (Sec.sh_type != SHT_SYMTAB)
continue;
- Elf_Sym_Range Syms = CHECK(Obj.symbols(&Sec), this);
- uint32_t FirstNonLocal = Sec.sh_info;
+ typename ELFT::SymRange Syms = CHECK(Obj.symbols(&Sec), this);
+ uint32_t FirstGlobal = Sec.sh_info;
StringRef StringTable =
CHECK(Obj.getStringTableForSymtab(Sec, Sections), this);
- std::vector<StringRef> V;
- for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal))
+ for (const typename ELFT::Sym &Sym : Syms.slice(FirstGlobal))
if (Sym.st_shndx != SHN_UNDEF)
- V.push_back(CHECK(Sym.getName(StringTable), this));
- return V;
+ Symtab->addLazyObject<ELFT>(CHECK(Sym.getName(StringTable), this),
+ *this);
+ return;
}
- return {};
}
-std::vector<StringRef> LazyObjFile::getBitcodeSymbols() {
- std::unique_ptr<lto::InputFile> Obj =
- CHECK(lto::InputFile::create(this->MB), this);
- std::vector<StringRef> V;
- for (const lto::InputFile::Symbol &Sym : Obj->symbols())
- if (!Sym.isUndefined())
- V.push_back(Saver.save(Sym.getName()));
- return V;
-}
+std::string elf::replaceThinLTOSuffix(StringRef Path) {
+ StringRef Suffix = Config->ThinLTOObjectSuffixReplace.first;
+ StringRef Repl = Config->ThinLTOObjectSuffixReplace.second;
-// Returns a vector of globally-visible defined symbol names.
-std::vector<StringRef> LazyObjFile::getSymbolNames() {
- if (isBitcode(this->MB))
- return getBitcodeSymbols();
-
- switch (getELFKind(this->MB)) {
- case ELF32LEKind:
- return getElfSymbols<ELF32LE>();
- case ELF32BEKind:
- return getElfSymbols<ELF32BE>();
- case ELF64LEKind:
- return getElfSymbols<ELF64LE>();
- case ELF64BEKind:
- return getElfSymbols<ELF64BE>();
- default:
- llvm_unreachable("getELFKind");
+ if (!Path.endswith(Suffix)) {
+ error("-thinlto-object-suffix-replace=" + Suffix + ";" + Repl +
+ " was given, but " + Path + " does not end with the suffix");
+ return "";
}
+ return (Path.drop_back(Suffix.size()) + Repl).str();
}
template void ArchiveFile::parse<ELF32LE>();
diff --git a/contrib/llvm/tools/lld/ELF/InputFiles.h b/contrib/llvm/tools/lld/ELF/InputFiles.h
index 70109f002e98..0db3203b0ba2 100644
--- a/contrib/llvm/tools/lld/ELF/InputFiles.h
+++ b/contrib/llvm/tools/lld/ELF/InputFiles.h
@@ -12,22 +12,20 @@
#include "Config.h"
#include "lld/Common/ErrorHandler.h"
-
#include "lld/Common/LLVM.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/IR/Comdat.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Support/Threading.h"
-
#include <map>
namespace llvm {
-class DWARFDebugLine;
class TarWriter;
struct DILineInfo;
namespace lto {
@@ -48,7 +46,6 @@ namespace elf {
using llvm::object::Archive;
-class Lazy;
class Symbol;
// If -reproduce option is given, all input files are written
@@ -90,15 +87,15 @@ public:
// Returns object file symbols. It is a runtime error to call this
// function on files of other types.
ArrayRef<Symbol *> getSymbols() {
- assert(FileKind == ObjKind || FileKind == BitcodeKind ||
- FileKind == ArchiveKind);
+ assert(FileKind == BinaryKind || FileKind == ObjKind ||
+ FileKind == BitcodeKind);
return Symbols;
}
// Filename of .a which contained this file. If this file was
// not in an archive file, it is the empty string. We use this
// string for creating error messages.
- StringRef ArchiveName;
+ std::string ArchiveName;
// If this is an architecture-specific file, the following members
// have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
@@ -112,6 +109,20 @@ public:
std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
uint64_t Offset);
+ // True if this is an argument for --just-symbols. Usually false.
+ bool JustSymbols = false;
+
+ // GroupId is used for --warn-backrefs which is an optional error
+ // checking feature. All files within the same --{start,end}-group or
+ // --{start,end}-lib get the same group ID. Otherwise, each file gets a new
+ // group ID. For more info, see checkDependency() in SymbolTable.cpp.
+ uint32_t GroupId;
+ static bool IsInGroup;
+ static uint32_t NextGroupId;
+
+ // Index of MIPS GOT built for this file.
+ llvm::Optional<size_t> MipsGotIndex;
+
protected:
InputFile(Kind K, MemoryBufferRef M);
std::vector<InputSectionBase *> Sections;
@@ -144,7 +155,7 @@ public:
protected:
ArrayRef<Elf_Sym> ELFSyms;
- uint32_t FirstNonLocal = 0;
+ uint32_t FirstGlobal = 0;
ArrayRef<Elf_Word> SymtabSHNDX;
StringRef StringTable;
void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab);
@@ -183,9 +194,6 @@ public:
return getSymbol(SymIndex);
}
- // Returns source line information for a given offset.
- // If no information is available, returns "".
- std::string getLineInfo(InputSectionBase *S, uint64_t Offset);
llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);
llvm::Optional<std::pair<std::string, unsigned>> getVariableLoc(StringRef Name);
@@ -199,10 +207,22 @@ public:
// symbol table.
StringRef SourceFile;
+ // True if the file defines functions compiled with
+ // -fsplit-stack. Usually false.
+ bool SplitStack = false;
+
+ // True if the file defines functions compiled with -fsplit-stack,
+ // but had one or more functions with the no_split_stack attribute.
+ bool SomeNoSplitStack = false;
+
+ // Pointer to this input file's .llvm_addrsig section, if it has one.
+ const Elf_Shdr *AddrsigSec = nullptr;
+
private:
void
initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
void initializeSymbols();
+ void initializeJustSymbols();
void initializeDwarf();
InputSectionBase *getRelocTarget(const Elf_Shdr &Sec);
InputSectionBase *createInputSection(const Elf_Shdr &Sec);
@@ -218,8 +238,14 @@ private:
// reporting. Linker may find reasonable number of errors in a
// single object file, so we cache debugging information in order to
// parse it only once for each object file we link.
- std::unique_ptr<llvm::DWARFDebugLine> DwarfLine;
- llvm::DenseMap<StringRef, std::pair<unsigned, unsigned>> VariableLoc;
+ std::unique_ptr<llvm::DWARFContext> Dwarf;
+ std::vector<const llvm::DWARFDebugLine::LineTable *> LineTables;
+ struct VarLoc {
+ const llvm::DWARFDebugLine::LineTable *LT;
+ unsigned File;
+ unsigned Line;
+ };
+ llvm::DenseMap<StringRef, VarLoc> VariableLoc;
llvm::once_flag InitDwarfLine;
};
@@ -243,13 +269,11 @@ public:
template <class ELFT> void parse();
MemoryBufferRef getBuffer();
InputFile *fetch();
+ bool AddedToLink = false;
private:
- std::vector<StringRef> getSymbolNames();
- template <class ELFT> std::vector<StringRef> getElfSymbols();
- std::vector<StringRef> getBitcodeSymbols();
+ template <class ELFT> void addElfSymbols();
- bool Seen = false;
uint64_t OffsetInArchive;
};
@@ -260,11 +284,11 @@ public:
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
template <class ELFT> void parse();
- // Returns a memory buffer for a given symbol and the offset in the archive
- // for the member. An empty memory buffer and an offset of zero
- // is returned if we have already returned the same memory buffer.
- // (So that we don't instantiate same members more than once.)
- std::pair<MemoryBufferRef, uint64_t> getMember(const Archive::Symbol *Sym);
+ // Pulls out an object file that contains a definition for Sym and
+ // returns it. If the same file was instantiated before, this
+ // function returns a nullptr (so we don't instantiate the same file
+ // more than once.)
+ InputFile *fetch(const Archive::Symbol &Sym);
private:
std::unique_ptr<Archive> File;
@@ -291,7 +315,6 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
typedef typename ELFT::Verdef Elf_Verdef;
typedef typename ELFT::Versym Elf_Versym;
- std::vector<StringRef> Undefs;
const Elf_Shdr *VersymSec = nullptr;
const Elf_Shdr *VerdefSec = nullptr;
@@ -299,8 +322,6 @@ public:
std::vector<const Elf_Verdef *> Verdefs;
std::string SoName;
- llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
-
static bool classof(const InputFile *F) {
return F->kind() == Base::SharedKind;
}
@@ -309,7 +330,9 @@ public:
void parseSoName();
void parseRest();
- std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym);
+ uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym);
+ std::vector<const Elf_Verdef *> parseVerdefs();
+ std::vector<uint32_t> parseVersyms();
struct NeededVer {
// The string table offset of the version name in the output file.
@@ -338,8 +361,15 @@ InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",
uint64_t OffsetInArchive = 0);
InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName);
+inline bool isBitcode(MemoryBufferRef MB) {
+ return identify_magic(MB.getBuffer()) == llvm::file_magic::bitcode;
+}
+
+std::string replaceThinLTOSuffix(StringRef Path);
+
extern std::vector<BinaryFile *> BinaryFiles;
extern std::vector<BitcodeFile *> BitcodeFiles;
+extern std::vector<LazyObjFile *> LazyObjFiles;
extern std::vector<InputFile *> ObjectFiles;
extern std::vector<InputFile *> SharedFiles;
diff --git a/contrib/llvm/tools/lld/ELF/InputSection.cpp b/contrib/llvm/tools/lld/ELF/InputSection.cpp
index 0b8fe7ba6b59..54fb57cf9888 100644
--- a/contrib/llvm/tools/lld/ELF/InputSection.cpp
+++ b/contrib/llvm/tools/lld/ELF/InputSection.cpp
@@ -14,6 +14,7 @@
#include "LinkerScript.h"
#include "OutputSections.h"
#include "Relocations.h"
+#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
@@ -26,7 +27,10 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/xxhash.h"
+#include <algorithm>
#include <mutex>
+#include <set>
+#include <vector>
using namespace llvm;
using namespace llvm::ELF;
@@ -45,32 +49,6 @@ std::string lld::toString(const InputSectionBase *Sec) {
return (toString(Sec->File) + ":(" + Sec->Name + ")").str();
}
-DenseMap<SectionBase *, int> elf::buildSectionOrder() {
- DenseMap<SectionBase *, int> SectionOrder;
- if (Config->SymbolOrderingFile.empty())
- return SectionOrder;
-
- // Build a map from symbols to their priorities. Symbols that didn't
- // appear in the symbol ordering file have the lowest priority 0.
- // All explicitly mentioned symbols have negative (higher) priorities.
- DenseMap<StringRef, int> SymbolOrder;
- int Priority = -Config->SymbolOrderingFile.size();
- for (StringRef S : Config->SymbolOrderingFile)
- SymbolOrder.insert({S, Priority++});
-
- // Build a map from sections to their priorities.
- for (InputFile *File : ObjectFiles) {
- for (Symbol *Sym : File->getSymbols()) {
- auto *D = dyn_cast<Defined>(Sym);
- if (!D || !D->Section)
- continue;
- int &Priority = SectionOrder[D->Section];
- Priority = std::min(Priority, SymbolOrder.lookup(D->getName()));
- }
- }
- return SectionOrder;
-}
-
template <class ELFT>
static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &File,
const typename ELFT::Shdr &Hdr) {
@@ -168,12 +146,8 @@ uint64_t SectionBase::getOffset(uint64_t Offset) const {
return Offset == uint64_t(-1) ? OS->Size : Offset;
}
case Regular:
- return cast<InputSection>(this)->OutSecOff + Offset;
- case Synthetic: {
- auto *IS = cast<InputSection>(this);
- // For synthetic sections we treat offset -1 as the end of the section.
- return IS->OutSecOff + (Offset == uint64_t(-1) ? IS->getSize() : Offset);
- }
+ case Synthetic:
+ return cast<InputSection>(this)->getOffset(Offset);
case EHFrame:
// The file crtbeginT.o has relocations pointing to the start of an empty
// .eh_frame that is known to be the first in the link. It does that to
@@ -182,16 +156,21 @@ uint64_t SectionBase::getOffset(uint64_t Offset) const {
case Merge:
const MergeInputSection *MS = cast<MergeInputSection>(this);
if (InputSection *IS = MS->getParent())
- return IS->OutSecOff + MS->getOffset(Offset);
- return MS->getOffset(Offset);
+ return IS->getOffset(MS->getParentOffset(Offset));
+ return MS->getParentOffset(Offset);
}
llvm_unreachable("invalid section kind");
}
+uint64_t SectionBase::getVA(uint64_t Offset) const {
+ const OutputSection *Out = getOutputSection();
+ return (Out ? Out->Addr : 0) + getOffset(Offset);
+}
+
OutputSection *SectionBase::getOutputSection() {
InputSection *Sec;
if (auto *IS = dyn_cast<InputSection>(this))
- return IS->getParent();
+ Sec = IS;
else if (auto *MS = dyn_cast<MergeInputSection>(this))
Sec = MS->getParent();
else if (auto *EH = dyn_cast<EhInputSection>(this))
@@ -201,34 +180,50 @@ OutputSection *SectionBase::getOutputSection() {
return Sec ? Sec->getParent() : nullptr;
}
-// Uncompress section contents if required. Note that this function
+// Decompress section contents if required. Note that this function
// is called from parallelForEach, so it must be thread-safe.
-void InputSectionBase::maybeUncompress() {
- if (UncompressBuf || !Decompressor::isCompressedELFSection(Flags, Name))
+void InputSectionBase::maybeDecompress() {
+ if (DecompressBuf)
+ return;
+ if (!(Flags & SHF_COMPRESSED) && !Name.startswith(".zdebug"))
return;
+ // Decompress a section.
Decompressor Dec = check(Decompressor::create(Name, toStringRef(Data),
Config->IsLE, Config->Is64));
size_t Size = Dec.getDecompressedSize();
- UncompressBuf.reset(new char[Size]());
- if (Error E = Dec.decompress({UncompressBuf.get(), Size}))
+ DecompressBuf.reset(new char[Size + Name.size()]());
+ if (Error E = Dec.decompress({DecompressBuf.get(), Size}))
fatal(toString(this) +
": decompress failed: " + llvm::toString(std::move(E)));
- Data = makeArrayRef((uint8_t *)UncompressBuf.get(), Size);
+ Data = makeArrayRef((uint8_t *)DecompressBuf.get(), Size);
Flags &= ~(uint64_t)SHF_COMPRESSED;
+
+ // A section name may have been altered if compressed. If that's
+ // the case, restore the original name. (i.e. ".zdebug_" -> ".debug_")
+ if (Name.startswith(".zdebug")) {
+ DecompressBuf[Size] = '.';
+ memcpy(&DecompressBuf[Size + 1], Name.data() + 2, Name.size() - 2);
+ Name = StringRef(&DecompressBuf[Size], Name.size() - 1);
+ }
}
InputSection *InputSectionBase::getLinkOrderDep() const {
- if ((Flags & SHF_LINK_ORDER) && Link != 0) {
- InputSectionBase *L = File->getSections()[Link];
- if (auto *IS = dyn_cast<InputSection>(L))
- return IS;
- error("a section with SHF_LINK_ORDER should not refer a non-regular "
- "section: " +
- toString(L));
- }
+ assert(Link);
+ assert(Flags & SHF_LINK_ORDER);
+ return cast<InputSection>(File->getSections()[Link]);
+}
+
+// Find a function symbol that encloses a given location.
+template <class ELFT>
+Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) {
+ for (Symbol *B : File->getSymbols())
+ if (Defined *D = dyn_cast<Defined>(B))
+ if (D->Section == this && D->Type == STT_FUNC && D->Value <= Offset &&
+ Offset < D->Value + D->Size)
+ return D;
return nullptr;
}
@@ -241,9 +236,8 @@ std::string InputSectionBase::getLocation(uint64_t Offset) {
.str();
// First check if we can get desired values from debugging information.
- std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset);
- if (!LineInfo.empty())
- return LineInfo;
+ if (Optional<DILineInfo> Info = getFile<ELFT>()->getDILineInfo(this, Offset))
+ return Info->FileName + ":" + std::to_string(Info->Line);
// File->SourceFile contains STT_FILE symbol that contains a
// source file name. If it's missing, we use an object file name.
@@ -251,12 +245,8 @@ std::string InputSectionBase::getLocation(uint64_t Offset) {
if (SrcFile.empty())
SrcFile = toString(File);
- // Find a function symbol that encloses a given location.
- for (Symbol *B : File->getSymbols())
- if (auto *D = dyn_cast<Defined>(B))
- if (D->Section == this && D->Type == STT_FUNC)
- if (D->Value <= Offset && Offset < D->Value + D->Size)
- return SrcFile + ":(function " + toString(*D) + ")";
+ if (Defined *D = getEnclosingFunction<ELFT>(Offset))
+ return SrcFile + ":(function " + toString(*D) + ")";
// If there's no symbol, print out the offset in the section.
return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str();
@@ -292,7 +282,7 @@ std::string InputSectionBase::getObjMsg(uint64_t Off) {
std::string Archive;
if (!File->ArchiveName.empty())
- Archive = (" in archive " + File->ArchiveName).str();
+ Archive = " in archive " + File->ArchiveName;
// Find a symbol that encloses a given location.
for (Symbol *B : File->getSymbols())
@@ -345,8 +335,9 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) {
*To++ = Sections[Idx]->getOutputSection()->SectionIndex;
}
-InputSectionBase *InputSection::getRelocatedSection() {
- assert(Type == SHT_RELA || Type == SHT_REL);
+InputSectionBase *InputSection::getRelocatedSection() const {
+ if (!File || (Type != SHT_RELA && Type != SHT_REL))
+ return nullptr;
ArrayRef<InputSectionBase *> Sections = File->getSections();
return Sections[Info];
}
@@ -365,12 +356,12 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf);
Buf += sizeof(RelTy);
- if (Config->IsRela)
+ if (RelTy::IsRela)
P->r_addend = getAddend<ELFT>(Rel);
// Output section VA is zero for -r, so r_offset is an offset within the
// section, but for --emit-relocs it is an virtual address.
- P->r_offset = Sec->getOutputSection()->Addr + Sec->getOffset(Rel.r_offset);
+ P->r_offset = Sec->getVA(Rel.r_offset);
P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Sym), Type,
Config->IsMips64EL);
@@ -395,17 +386,32 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
continue;
}
- if (Config->IsRela) {
- P->r_addend =
- Sym.getVA(getAddend<ELFT>(Rel)) - Section->getOutputSection()->Addr;
- } else if (Config->Relocatable) {
- const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset;
- Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset,
- Target->getImplicitAddend(BufLoc, Type),
- &Sym});
+ int64_t Addend = getAddend<ELFT>(Rel);
+ const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset;
+ if (!RelTy::IsRela)
+ Addend = Target->getImplicitAddend(BufLoc, Type);
+
+ if (Config->EMachine == EM_MIPS && Config->Relocatable &&
+ Target->getRelExpr(Type, Sym, BufLoc) == R_MIPS_GOTREL) {
+ // Some MIPS relocations depend on "gp" value. By default,
+ // this value has 0x7ff0 offset from a .got section. But
+ // relocatable files produced by a complier or a linker
+ // might redefine this default value and we must use it
+ // for a calculation of the relocation result. When we
+ // generate EXE or DSO it's trivial. Generating a relocatable
+ // output is more difficult case because the linker does
+ // not calculate relocations in this mode and loses
+ // individual "gp" values used by each input object file.
+ // As a workaround we add the "gp" value to the relocation
+ // addend and save it back to the file.
+ Addend += Sec->getFile<ELFT>()->MipsGp0;
}
- }
+ if (RelTy::IsRela)
+ P->r_addend = Sym.getVA(Addend) - Section->getOutputSection()->Addr;
+ else if (Config->Relocatable)
+ Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, Addend, &Sym});
+ }
}
}
@@ -481,14 +487,17 @@ static uint64_t getARMStaticBase(const Symbol &Sym) {
return OS->PtLoad->FirstSec->Addr;
}
-static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
- const Symbol &Sym, RelExpr Expr) {
+static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
+ uint64_t P, const Symbol &Sym, RelExpr Expr) {
switch (Expr) {
case R_INVALID:
return 0;
case R_ABS:
+ case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
return Sym.getVA(A);
+ case R_ADDEND:
+ return A;
case R_ARM_SBREL:
return Sym.getVA(A) - getARMStaticBase(Sym);
case R_GOT:
@@ -505,7 +514,9 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
case R_GOT_FROM_END:
case R_RELAX_TLS_GD_TO_IE_END:
return Sym.getGotOffset() + A - InX::Got->getSize();
+ case R_TLSLD_GOT_OFF:
case R_GOT_OFF:
+ case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
return Sym.getGotOffset() + A;
case R_GOT_PAGE_PC:
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
@@ -516,11 +527,12 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
case R_HINT:
case R_NONE:
case R_TLSDESC_CALL:
+ case R_TLSLD_HINT:
llvm_unreachable("cannot relocate hint relocs");
case R_MIPS_GOTREL:
- return Sym.getVA(A) - InX::MipsGot->getGp();
+ return Sym.getVA(A) - InX::MipsGot->getGp(File);
case R_MIPS_GOT_GP:
- return InX::MipsGot->getGp() + A;
+ return InX::MipsGot->getGp(File) + A;
case R_MIPS_GOT_GP_PC: {
// R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target
// is _gp_disp symbol. In that case we should use the following
@@ -529,7 +541,7 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
// microMIPS variants of these relocations use slightly different
// expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi()
// to correctly handle less-sugnificant bit of the microMIPS symbol.
- uint64_t V = InX::MipsGot->getGp() + A - P;
+ uint64_t V = InX::MipsGot->getGp(File) + A - P;
if (Type == R_MIPS_LO16 || Type == R_MICROMIPS_LO16)
V += 4;
if (Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_HI16)
@@ -540,21 +552,23 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
// If relocation against MIPS local symbol requires GOT entry, this entry
// should be initialized by 'page address'. This address is high 16-bits
// of sum the symbol's value and the addend.
- return InX::MipsGot->getVA() + InX::MipsGot->getPageEntryOffset(Sym, A) -
- InX::MipsGot->getGp();
+ return InX::MipsGot->getVA() +
+ InX::MipsGot->getPageEntryOffset(File, Sym, A) -
+ InX::MipsGot->getGp(File);
case R_MIPS_GOT_OFF:
case R_MIPS_GOT_OFF32:
// In case of MIPS if a GOT relocation has non-zero addend this addend
// should be applied to the GOT entry content not to the GOT entry offset.
// That is why we use separate expression type.
- return InX::MipsGot->getVA() + InX::MipsGot->getSymEntryOffset(Sym, A) -
- InX::MipsGot->getGp();
+ return InX::MipsGot->getVA() +
+ InX::MipsGot->getSymEntryOffset(File, Sym, A) -
+ InX::MipsGot->getGp(File);
case R_MIPS_TLSGD:
- return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() +
- InX::MipsGot->getGlobalDynOffset(Sym) - InX::MipsGot->getGp();
+ return InX::MipsGot->getVA() + InX::MipsGot->getGlobalDynOffset(File, Sym) -
+ InX::MipsGot->getGp(File);
case R_MIPS_TLSLD:
- return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() +
- InX::MipsGot->getTlsIndexOff() - InX::MipsGot->getGp();
+ return InX::MipsGot->getVA() + InX::MipsGot->getTlsIndexOffset(File) -
+ InX::MipsGot->getGp(File);
case R_PAGE_PC:
case R_PLT_PAGE_PC: {
uint64_t Dest;
@@ -583,25 +597,27 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
case R_PLT:
return Sym.getPltVA() + A;
case R_PLT_PC:
- case R_PPC_PLT_OPD:
+ case R_PPC_CALL_PLT:
return Sym.getPltVA() + A - P;
- case R_PPC_OPD: {
+ case R_PPC_CALL: {
uint64_t SymVA = Sym.getVA(A);
// If we have an undefined weak symbol, we might get here with a symbol
// address of zero. That could overflow, but the code must be unreachable,
// so don't bother doing anything at all.
if (!SymVA)
return 0;
- if (Out::Opd) {
- // If this is a local call, and we currently have the address of a
- // function-descriptor, get the underlying code address instead.
- uint64_t OpdStart = Out::Opd->Addr;
- uint64_t OpdEnd = OpdStart + Out::Opd->Size;
- bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd;
- if (InOpd)
- SymVA = read64be(&Out::OpdBuf[SymVA - OpdStart]);
- }
- return SymVA - P;
+
+ // PPC64 V2 ABI describes two entry points to a function. The global entry
+ // point sets up the TOC base pointer. When calling a local function, the
+ // call should branch to the local entry point rather than the global entry
+ // point. Section 3.4.1 describes using the 3 most significant bits of the
+ // st_other field to find out how many instructions there are between the
+ // local and global entry point.
+ uint8_t StOther = (Sym.StOther >> 5) & 7;
+ if (StOther == 0 || StOther == 1)
+ return SymVA - P;
+
+ return SymVA - P + (1LL << StOther);
}
case R_PPC_TOC:
return getPPC64TocBase() + A;
@@ -618,25 +634,44 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P,
// statically to zero.
if (Sym.isTls() && Sym.isUndefWeak())
return 0;
- if (Target->TcbSize)
+
+ // For TLS variant 1 the TCB is a fixed size, whereas for TLS variant 2 the
+ // TCB is on unspecified size and content. Targets that implement variant 1
+ // should set TcbSize.
+ if (Target->TcbSize) {
+ // PPC64 V2 ABI has the thread pointer offset into the middle of the TLS
+ // storage area by TlsTpOffset for efficient addressing TCB and up to
+ // 4KB – 8 B of other thread library information (placed before the TCB).
+ // Subtracting this offset will get the address of the first TLS block.
+ if (Target->TlsTpOffset)
+ return Sym.getVA(A) - Target->TlsTpOffset;
+
+ // If thread pointer is not offset into the middle, the first thing in the
+ // TLS storage area is the TCB. Add the TcbSize to get the address of the
+ // first TLS block.
return Sym.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align);
+ }
return Sym.getVA(A) - Out::TlsPhdr->p_memsz;
case R_RELAX_TLS_GD_TO_LE_NEG:
case R_NEG_TLS:
return Out::TlsPhdr->p_memsz - Sym.getVA(A);
case R_SIZE:
- return A; // Sym.getSize was already folded into the addend.
+ return Sym.getSize() + A;
case R_TLSDESC:
return InX::Got->getGlobalDynAddr(Sym) + A;
case R_TLSDESC_PAGE:
return getAArch64Page(InX::Got->getGlobalDynAddr(Sym) + A) -
getAArch64Page(P);
- case R_TLSGD:
+ case R_TLSGD_GOT:
+ return InX::Got->getGlobalDynOffset(Sym) + A;
+ case R_TLSGD_GOT_FROM_END:
return InX::Got->getGlobalDynOffset(Sym) + A - InX::Got->getSize();
case R_TLSGD_PC:
return InX::Got->getGlobalDynAddr(Sym) + A - P;
- case R_TLSLD:
+ case R_TLSLD_GOT_FROM_END:
return InX::Got->getTlsIndexOff() + A - InX::Got->getSize();
+ case R_TLSLD_GOT:
+ return InX::Got->getTlsIndexOff() + A;
case R_TLSLD_PC:
return InX::Got->getTlsIndexVA() + A - P;
}
@@ -656,6 +691,14 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
for (const RelTy &Rel : Rels) {
RelType Type = Rel.getType(Config->IsMips64EL);
+
+ // GCC 8.0 or earlier have a bug that they emit R_386_GOTPC relocations
+ // against _GLOBAL_OFFSET_TABLE_ for .debug_info. The bug has been fixed
+ // in 2017 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630), but we
+ // need to keep this bug-compatible code for a while.
+ if (Config->EMachine == EM_386 && Type == R_386_GOTPC)
+ continue;
+
uint64_t Offset = getOffset(Rel.r_offset);
uint8_t *BufLoc = Buf + Offset;
int64_t Addend = getAddend<ELFT>(Rel);
@@ -666,17 +709,27 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc);
if (Expr == R_NONE)
continue;
+
if (Expr != R_ABS) {
- // GCC 8.0 or earlier have a bug that it emits R_386_GOTPC relocations
- // against _GLOBAL_OFFSET_TABLE for .debug_info. The bug seems to have
- // been fixed in 2017: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630,
- // but we need to keep this bug-compatible code for a while.
- if (Config->EMachine == EM_386 && Type == R_386_GOTPC)
- continue;
+ std::string Msg = getLocation<ELFT>(Offset) +
+ ": has non-ABS relocation " + toString(Type) +
+ " against symbol '" + toString(Sym) + "'";
+ if (Expr != R_PC) {
+ error(Msg);
+ return;
+ }
- error(getLocation<ELFT>(Offset) + ": has non-ABS relocation " +
- toString(Type) + " against symbol '" + toString(Sym) + "'");
- return;
+ // If the control reaches here, we found a PC-relative relocation in a
+ // non-ALLOC section. Since non-ALLOC section is not loaded into memory
+ // at runtime, the notion of PC-relative doesn't make sense here. So,
+ // this is a usage error. However, GNU linkers historically accept such
+ // relocations without any errors and relocate them as if they were at
+ // address 0. For bug-compatibilty, we accept them with warnings. We
+ // know Steel Bank Common Lisp as of 2018 have this bug.
+ warn(Msg);
+ Target->relocateOne(BufLoc, Type,
+ SignExtend64<Bits>(Sym.getVA(Addend - Offset)));
+ continue;
}
if (Sym.isTls() && !Out::TlsPhdr)
@@ -705,6 +758,9 @@ static void relocateNonAllocForRelocatable(InputSection *Sec, uint8_t *Buf) {
template <class ELFT>
void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
+ if (Flags & SHF_EXECINSTR)
+ adjustSplitStackFunctionPrologues<ELFT>(Buf, BufEnd);
+
if (Flags & SHF_ALLOC) {
relocateAlloc(Buf, BufEnd);
return;
@@ -724,14 +780,17 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
const unsigned Bits = Config->Wordsize * 8;
for (const Relocation &Rel : Relocations) {
- uint64_t Offset = getOffset(Rel.Offset);
+ uint64_t Offset = Rel.Offset;
+ if (auto *Sec = dyn_cast<InputSection>(this))
+ Offset += Sec->OutSecOff;
uint8_t *BufLoc = Buf + Offset;
RelType Type = Rel.Type;
uint64_t AddrLoc = getOutputSection()->Addr + Offset;
RelExpr Expr = Rel.Expr;
uint64_t TargetVA = SignExtend64(
- getRelocTargetVA(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr), Bits);
+ getRelocTargetVA(File, Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr),
+ Bits);
switch (Expr) {
case R_RELAX_GOT_PC:
@@ -742,6 +801,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
Target->relaxTlsIeToLe(BufLoc, Type, TargetVA);
break;
case R_RELAX_TLS_LD_TO_LE:
+ case R_RELAX_TLS_LD_TO_LE_ABS:
Target->relaxTlsLdToLe(BufLoc, Type, TargetVA);
break;
case R_RELAX_TLS_GD_TO_LE:
@@ -750,15 +810,28 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
break;
case R_RELAX_TLS_GD_TO_IE:
case R_RELAX_TLS_GD_TO_IE_ABS:
+ case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
case R_RELAX_TLS_GD_TO_IE_END:
Target->relaxTlsGdToIe(BufLoc, Type, TargetVA);
break;
- case R_PPC_PLT_OPD:
+ case R_PPC_CALL:
+ // If this is a call to __tls_get_addr, it may be part of a TLS
+ // sequence that has been relaxed and turned into a nop. In this
+ // case, we don't want to handle it as a call.
+ if (read32(BufLoc) == 0x60000000) // nop
+ break;
+
// Patch a nop (0x60000000) to a ld.
- if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000)
- write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1)
- LLVM_FALLTHROUGH;
+ if (Rel.Sym->NeedsTocRestore) {
+ if (BufLoc + 8 > BufEnd || read32(BufLoc + 4) != 0x60000000) {
+ error(getErrorLocation(BufLoc) + "call lacks nop, can't restore toc");
+ break;
+ }
+ write32(BufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)
+ }
+ Target->relocateOne(BufLoc, Type, TargetVA);
+ break;
default:
Target->relocateOne(BufLoc, Type, TargetVA);
break;
@@ -766,6 +839,101 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
}
}
+// For each function-defining prologue, find any calls to __morestack,
+// and replace them with calls to __morestack_non_split.
+static void switchMorestackCallsToMorestackNonSplit(
+ DenseSet<Defined *> &Prologues, std::vector<Relocation *> &MorestackCalls) {
+
+ // If the target adjusted a function's prologue, all calls to
+ // __morestack inside that function should be switched to
+ // __morestack_non_split.
+ Symbol *MoreStackNonSplit = Symtab->find("__morestack_non_split");
+
+ // Sort both collections to compare addresses efficiently.
+ llvm::sort(MorestackCalls.begin(), MorestackCalls.end(),
+ [](const Relocation *L, const Relocation *R) {
+ return L->Offset < R->Offset;
+ });
+ std::vector<Defined *> Functions(Prologues.begin(), Prologues.end());
+ llvm::sort(
+ Functions.begin(), Functions.end(),
+ [](const Defined *L, const Defined *R) { return L->Value < R->Value; });
+
+ auto It = MorestackCalls.begin();
+ for (Defined *F : Functions) {
+ // Find the first call to __morestack within the function.
+ while (It != MorestackCalls.end() && (*It)->Offset < F->Value)
+ ++It;
+ // Adjust all calls inside the function.
+ while (It != MorestackCalls.end() && (*It)->Offset < F->Value + F->Size) {
+ (*It)->Sym = MoreStackNonSplit;
+ ++It;
+ }
+ }
+}
+
+static bool enclosingPrologueAdjusted(uint64_t Offset,
+ const DenseSet<Defined *> &Prologues) {
+ for (Defined *F : Prologues)
+ if (F->Value <= Offset && Offset < F->Value + F->Size)
+ return true;
+ return false;
+}
+
+// If a function compiled for split stack calls a function not
+// compiled for split stack, then the caller needs its prologue
+// adjusted to ensure that the called function will have enough stack
+// available. Find those functions, and adjust their prologues.
+template <class ELFT>
+void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf,
+ uint8_t *End) {
+ if (!getFile<ELFT>()->SplitStack)
+ return;
+ DenseSet<Defined *> AdjustedPrologues;
+ std::vector<Relocation *> MorestackCalls;
+
+ for (Relocation &Rel : Relocations) {
+ // Local symbols can't possibly be cross-calls, and should have been
+ // resolved long before this line.
+ if (Rel.Sym->isLocal())
+ continue;
+
+ Defined *D = dyn_cast<Defined>(Rel.Sym);
+ // A reference to an undefined symbol was an error, and should not
+ // have gotten to this point.
+ if (!D)
+ continue;
+
+ // Ignore calls into the split-stack api.
+ if (D->getName().startswith("__morestack")) {
+ if (D->getName().equals("__morestack"))
+ MorestackCalls.push_back(&Rel);
+ continue;
+ }
+
+ // A relocation to non-function isn't relevant. Sometimes
+ // __morestack is not marked as a function, so this check comes
+ // after the name check.
+ if (D->Type != STT_FUNC)
+ continue;
+
+ if (enclosingPrologueAdjusted(Rel.Offset, AdjustedPrologues))
+ continue;
+
+ if (Defined *F = getEnclosingFunction<ELFT>(Rel.Offset)) {
+ if (Target->adjustPrologueForCrossSplitStack(Buf + F->Value, End)) {
+ AdjustedPrologues.insert(F);
+ continue;
+ }
+ }
+ if (!getFile<ELFT>()->SomeNoSplitStack)
+ error("function call at " + getErrorLocation(Buf + Rel.Offset) +
+ "crosses a split-stack boundary, but unable " +
+ "to adjust the enclosing function's prologue");
+ }
+ switchMorestackCallsToMorestackNonSplit(AdjustedPrologues, MorestackCalls);
+}
+
template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
if (Type == SHT_NOBITS)
return;
@@ -837,10 +1005,6 @@ static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels,
// .eh_frame is a sequence of CIE or FDE records.
// This function splits an input section into records and returns them.
template <class ELFT> void EhInputSection::split() {
- // Early exit if already split.
- if (!Pieces.empty())
- return;
-
if (AreRelocsRela)
split<ELFT>(relas<ELFT>());
else
@@ -905,8 +1069,7 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data,
bool IsAlloc = Flags & SHF_ALLOC;
for (size_t I = 0; I != Size; I += EntSize)
- Pieces.emplace_back(I, xxHash64(toStringRef(Data.slice(I, EntSize))),
- !IsAlloc);
+ Pieces.emplace_back(I, xxHash64(Data.slice(I, EntSize)), !IsAlloc);
}
template <class ELFT>
@@ -935,15 +1098,9 @@ void MergeInputSection::splitIntoPieces() {
else
splitNonStrings(Data, Entsize);
- if (Config->GcSections && (Flags & SHF_ALLOC))
- for (uint64_t Off : LiveOffsets)
- getSectionPiece(Off)->Live = true;
-}
-
-// Do binary search to get a section piece at a given input offset.
-SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) {
- auto *This = static_cast<const MergeInputSection *>(this);
- return const_cast<SectionPiece *>(This->getSectionPiece(Offset));
+ OffsetMap.reserve(Pieces.size());
+ for (size_t I = 0, E = Pieces.size(); I != E; ++I)
+ OffsetMap[Pieces[I].InputOff] = I;
}
template <class It, class T, class Compare>
@@ -959,32 +1116,34 @@ static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) {
return Comp(Value, *First) ? First : First + 1;
}
-const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const {
- if (Data.size() <= Offset)
- fatal(toString(this) + ": entry is past the end of the section");
+// Do binary search to get a section piece at a given input offset.
+static SectionPiece *findSectionPiece(MergeInputSection *Sec, uint64_t Offset) {
+ if (Sec->Data.size() <= Offset)
+ fatal(toString(Sec) + ": entry is past the end of the section");
// Find the element this offset points to.
auto I = fastUpperBound(
- Pieces.begin(), Pieces.end(), Offset,
+ Sec->Pieces.begin(), Sec->Pieces.end(), Offset,
[](const uint64_t &A, const SectionPiece &B) { return A < B.InputOff; });
--I;
return &*I;
}
+SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) {
+ // Find a piece starting at a given offset.
+ auto It = OffsetMap.find(Offset);
+ if (It != OffsetMap.end())
+ return &Pieces[It->second];
+
+ // If Offset is not at beginning of a section piece, it is not in the map.
+ // In that case we need to search from the original section piece vector.
+ return findSectionPiece(this, Offset);
+}
+
// Returns the offset in an output section for a given input offset.
// Because contents of a mergeable section is not contiguous in output,
// it is not just an addition to a base output offset.
-uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
- if (!Live)
- return 0;
-
- // Initialize OffsetMap lazily.
- llvm::call_once(InitOffsetMap, [&] {
- OffsetMap.reserve(Pieces.size());
- for (size_t I = 0; I < Pieces.size(); ++I)
- OffsetMap[Pieces[I].InputOff] = I;
- });
-
+uint64_t MergeInputSection::getParentOffset(uint64_t Offset) const {
// Find a string starting at a given offset.
auto It = OffsetMap.find(Offset);
if (It != OffsetMap.end())
@@ -992,10 +1151,8 @@ uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
// If Offset is not at beginning of a section piece, it is not in the map.
// In that case we need to search from the original section piece vector.
- const SectionPiece &Piece = *getSectionPiece(Offset);
- if (!Piece.Live)
- return 0;
-
+ const SectionPiece &Piece =
+ *findSectionPiece(const_cast<MergeInputSection *>(this), Offset);
uint64_t Addend = Offset - Piece.InputOff;
return Piece.OutputOff + Addend;
}
diff --git a/contrib/llvm/tools/lld/ELF/InputSection.h b/contrib/llvm/tools/lld/ELF/InputSection.h
index 8c114ae71948..4db01e035e32 100644
--- a/contrib/llvm/tools/lld/ELF/InputSection.h
+++ b/contrib/llvm/tools/lld/ELF/InputSection.h
@@ -18,8 +18,6 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Object/ELF.h"
-#include "llvm/Support/Threading.h"
-#include <mutex>
namespace lld {
namespace elf {
@@ -63,6 +61,9 @@ public:
unsigned Bss : 1;
+ // Set for sections that should not be folded by ICF.
+ unsigned KeepUnique : 1;
+
// These corresponds to the fields in Elf_Shdr.
uint32_t Alignment;
uint64_t Flags;
@@ -80,13 +81,15 @@ public:
// section.
uint64_t getOffset(uint64_t Offset) const;
+ uint64_t getVA(uint64_t Offset = 0) const;
+
protected:
SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,
uint64_t Entsize, uint64_t Alignment, uint32_t Type,
uint32_t Info, uint32_t Link)
: Name(Name), Repl(this), SectionKind(SectionKind), Live(false),
- Bss(false), Alignment(Alignment), Flags(Flags), Entsize(Entsize),
- Type(Type), Link(Link), Info(Info) {}
+ Bss(false), KeepUnique(false), Alignment(Alignment), Flags(Flags),
+ Entsize(Entsize), Type(Type), Link(Link), Info(Info) {}
};
// This corresponds to a section of an input file.
@@ -103,7 +106,7 @@ public:
static bool classof(const SectionBase *S) { return S->kind() != Output; }
- // The file which contains this section. It's dynamic type is always
+ // The file which contains this section. Its dynamic type is always
// ObjFile<ELFT>, but in order to avoid ELFT, we use InputFile as
// its static type.
InputFile *File;
@@ -161,10 +164,15 @@ public:
InputSection *getLinkOrderDep() const;
+ // Get the function symbol that encloses this offset from within the
+ // section.
+ template <class ELFT>
+ Defined *getEnclosingFunction(uint64_t Offset);
+
// Compilers emit zlib-compressed debug sections if the -gz option
// is given. This function checks if this section is compressed, and
// if so, decompress in memory.
- void maybeUncompress();
+ void maybeDecompress();
// Returns a source location string. Used to construct an error message.
template <class ELFT> std::string getLocation(uint64_t Offset);
@@ -182,6 +190,15 @@ public:
// This vector contains such "cooked" relocations.
std::vector<Relocation> Relocations;
+ // A function compiled with -fsplit-stack calling a function
+ // compiled without -fsplit-stack needs its prologue adjusted. Find
+ // such functions and adjust their prologues. This is very similar
+ // to relocation. See https://gcc.gnu.org/wiki/SplitStacks for more
+ // information.
+ template <typename ELFT>
+ void adjustSplitStackFunctionPrologues(uint8_t *Buf, uint8_t *End);
+
+
template <typename T> llvm::ArrayRef<T> getDataAs() const {
size_t S = Data.size();
assert(S % sizeof(T) == 0);
@@ -189,9 +206,9 @@ public:
}
private:
- // A pointer that owns uncompressed data if a section is compressed by zlib.
+ // A pointer that owns decompressed data if a section is compressed by zlib.
// Since the feature is not used often, this is usually a nullptr.
- std::unique_ptr<char[]> UncompressBuf;
+ std::unique_ptr<char[]> DecompressBuf;
};
// SectionPiece represents a piece of splittable section contents.
@@ -200,7 +217,7 @@ private:
// be found by looking at the next one).
struct SectionPiece {
SectionPiece(size_t Off, uint32_t Hash, bool Live)
- : InputOff(Off), Hash(Hash), OutputOff(-1),
+ : InputOff(Off), Hash(Hash), OutputOff(0),
Live(Live || !Config->GcSections) {}
uint32_t InputOff;
@@ -223,19 +240,14 @@ public:
static bool classof(const SectionBase *S) { return S->kind() == Merge; }
void splitIntoPieces();
- // Mark the piece at a given offset live. Used by GC.
- void markLiveAt(uint64_t Offset) {
- if (this->Flags & llvm::ELF::SHF_ALLOC)
- LiveOffsets.insert(Offset);
- }
-
- // Translate an offset in the input section to an offset
- // in the output section.
- uint64_t getOffset(uint64_t Offset) const;
+ // Translate an offset in the input section to an offset in the parent
+ // MergeSyntheticSection.
+ uint64_t getParentOffset(uint64_t Offset) const;
// Splittable sections are handled as a sequence of data
// rather than a single large blob of data.
std::vector<SectionPiece> Pieces;
+ llvm::DenseMap<uint32_t, uint32_t> OffsetMap;
// Returns I'th piece's data. This function is very hot when
// string merging is enabled, so we want to inline.
@@ -249,18 +261,15 @@ public:
// Returns the SectionPiece at a given input section offset.
SectionPiece *getSectionPiece(uint64_t Offset);
- const SectionPiece *getSectionPiece(uint64_t Offset) const;
+ const SectionPiece *getSectionPiece(uint64_t Offset) const {
+ return const_cast<MergeInputSection *>(this)->getSectionPiece(Offset);
+ }
SyntheticSection *getParent() const;
private:
void splitStrings(ArrayRef<uint8_t> A, size_t Size);
void splitNonStrings(ArrayRef<uint8_t> A, size_t Size);
-
- mutable llvm::DenseMap<uint32_t, uint32_t> OffsetMap;
- mutable llvm::once_flag InitOffsetMap;
-
- llvm::DenseSet<uint64_t> LiveOffsets;
};
struct EhSectionPiece {
@@ -310,6 +319,8 @@ public:
// beginning of the output section.
template <class ELFT> void writeTo(uint8_t *Buf);
+ uint64_t getOffset(uint64_t Offset) const { return OutSecOff + Offset; }
+
OutputSection *getParent() const;
// This variable has two usages. Initially, it represents an index in the
@@ -320,7 +331,7 @@ public:
static bool classof(const SectionBase *S);
- InputSectionBase *getRelocatedSection();
+ InputSectionBase *getRelocatedSection() const;
template <class ELFT, class RelTy>
void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
@@ -342,10 +353,6 @@ private:
// The list of all input sections.
extern std::vector<InputSectionBase *> InputSections;
-
-// Builds section order for handling --symbol-ordering-file.
-llvm::DenseMap<SectionBase *, int> buildSectionOrder();
-
} // namespace elf
std::string toString(const elf::InputSectionBase *);
diff --git a/contrib/llvm/tools/lld/ELF/LTO.cpp b/contrib/llvm/tools/lld/ELF/LTO.cpp
index bfd85288d186..ef58932e86cc 100644
--- a/contrib/llvm/tools/lld/ELF/LTO.cpp
+++ b/contrib/llvm/tools/lld/ELF/LTO.cpp
@@ -20,6 +20,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/LTO/Caching.h"
#include "llvm/LTO/Config.h"
@@ -29,7 +31,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstddef>
#include <memory>
@@ -44,70 +45,92 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
-// This is for use when debugging LTO.
-static void saveBuffer(StringRef Buffer, const Twine &Path) {
+// Creates an empty file to store a list of object files for final
+// linking of distributed ThinLTO.
+static std::unique_ptr<raw_fd_ostream> openFile(StringRef File) {
std::error_code EC;
- raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
- if (EC)
- error("cannot create " + Path + ": " + EC.message());
- OS << Buffer;
-}
-
-static void diagnosticHandler(const DiagnosticInfo &DI) {
- SmallString<128> ErrStorage;
- raw_svector_ostream OS(ErrStorage);
- DiagnosticPrinterRawOStream DP(OS);
- DI.print(DP);
- warn(ErrStorage);
+ auto Ret =
+ llvm::make_unique<raw_fd_ostream>(File, EC, sys::fs::OpenFlags::F_None);
+ if (EC) {
+ error("cannot open " + File + ": " + EC.message());
+ return nullptr;
+ }
+ return Ret;
}
-static void checkError(Error E) {
- handleAllErrors(std::move(E),
- [&](ErrorInfoBase &EIB) { error(EIB.message()); });
+static std::string getThinLTOOutputFile(StringRef ModulePath) {
+ return lto::getThinLTOOutputFile(ModulePath,
+ Config->ThinLTOPrefixReplace.first,
+ Config->ThinLTOPrefixReplace.second);
}
-static std::unique_ptr<lto::LTO> createLTO() {
- lto::Config Conf;
+static lto::Config createConfig() {
+ lto::Config C;
// LLD supports the new relocations.
- Conf.Options = InitTargetOptionsFromCodeGenFlags();
- Conf.Options.RelaxELFRelocations = true;
+ C.Options = InitTargetOptionsFromCodeGenFlags();
+ C.Options.RelaxELFRelocations = true;
// Always emit a section per function/datum with LTO.
- Conf.Options.FunctionSections = true;
- Conf.Options.DataSections = true;
+ C.Options.FunctionSections = true;
+ C.Options.DataSections = true;
if (Config->Relocatable)
- Conf.RelocModel = None;
+ C.RelocModel = None;
else if (Config->Pic)
- Conf.RelocModel = Reloc::PIC_;
+ C.RelocModel = Reloc::PIC_;
else
- Conf.RelocModel = Reloc::Static;
- Conf.CodeModel = GetCodeModelFromCMModel();
- Conf.DisableVerify = Config->DisableVerify;
- Conf.DiagHandler = diagnosticHandler;
- Conf.OptLevel = Config->LTOO;
+ C.RelocModel = Reloc::Static;
+
+ C.CodeModel = GetCodeModelFromCMModel();
+ C.DisableVerify = Config->DisableVerify;
+ C.DiagHandler = diagnosticHandler;
+ C.OptLevel = Config->LTOO;
+ C.CPU = GetCPUStr();
// Set up a custom pipeline if we've been asked to.
- Conf.OptPipeline = Config->LTONewPmPasses;
- Conf.AAPipeline = Config->LTOAAPipeline;
+ C.OptPipeline = Config->LTONewPmPasses;
+ C.AAPipeline = Config->LTOAAPipeline;
// Set up optimization remarks if we've been asked to.
- Conf.RemarksFilename = Config->OptRemarksFilename;
- Conf.RemarksWithHotness = Config->OptRemarksWithHotness;
+ C.RemarksFilename = Config->OptRemarksFilename;
+ C.RemarksWithHotness = Config->OptRemarksWithHotness;
+
+ C.SampleProfile = Config->LTOSampleProfile;
+ C.UseNewPM = Config->LTONewPassManager;
+ C.DebugPassManager = Config->LTODebugPassManager;
+ C.DwoDir = Config->DwoDir;
if (Config->SaveTemps)
- checkError(Conf.addSaveTemps(std::string(Config->OutputFile) + ".",
- /*UseInputModulePath*/ true));
+ checkError(C.addSaveTemps(Config->OutputFile.str() + ".",
+ /*UseInputModulePath*/ true));
+ return C;
+}
+BitcodeCompiler::BitcodeCompiler() {
+ // Initialize LTOObj.
lto::ThinBackend Backend;
- if (Config->ThinLTOJobs != -1u)
+
+ if (Config->ThinLTOIndexOnly) {
+ StringRef Path = Config->ThinLTOIndexOnlyArg;
+ if (!Path.empty())
+ IndexFile = openFile(Path);
+
+ auto OnIndexWrite = [&](const std::string &Identifier) {
+ ObjectToIndexFileState[Identifier] = true;
+ };
+
+ Backend = lto::createWriteIndexesThinBackend(
+ Config->ThinLTOPrefixReplace.first, Config->ThinLTOPrefixReplace.second,
+ Config->ThinLTOEmitImportsFiles, IndexFile.get(), OnIndexWrite);
+ } else if (Config->ThinLTOJobs != -1U) {
Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);
- return llvm::make_unique<lto::LTO>(std::move(Conf), Backend,
- Config->LTOPartitions);
-}
+ }
-BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {
+ LTOObj = llvm::make_unique<lto::LTO>(createConfig(), Backend,
+ Config->LTOPartitions);
+
+ // Initialize UsedStartStop.
for (Symbol *Sym : Symtab->getSymbols()) {
StringRef Name = Sym->getName();
for (StringRef Prefix : {"__start_", "__stop_"})
@@ -125,20 +148,20 @@ static void undefine(Symbol *S) {
void BitcodeCompiler::add(BitcodeFile &F) {
lto::InputFile &Obj = *F.Obj;
- unsigned SymNum = 0;
- std::vector<Symbol *> Syms = F.getSymbols();
- std::vector<lto::SymbolResolution> Resols(Syms.size());
+ bool IsExec = !Config->Shared && !Config->Relocatable;
- DenseSet<StringRef> ScriptSymbols;
- for (BaseCommand *Base : Script->SectionCommands)
- if (auto *Cmd = dyn_cast<SymbolAssignment>(Base))
- ScriptSymbols.insert(Cmd->Name);
+ if (Config->ThinLTOIndexOnly)
+ ObjectToIndexFileState.insert({Obj.getName(), false});
+
+ ArrayRef<Symbol *> Syms = F.getSymbols();
+ ArrayRef<lto::InputFile::Symbol> ObjSyms = Obj.symbols();
+ std::vector<lto::SymbolResolution> Resols(Syms.size());
// Provide a resolution to the LTO API for each symbol.
- for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) {
- Symbol *Sym = Syms[SymNum];
- lto::SymbolResolution &R = Resols[SymNum];
- ++SymNum;
+ for (size_t I = 0, E = Syms.size(); I != E; ++I) {
+ Symbol *Sym = Syms[I];
+ const lto::InputFile::Symbol &ObjSym = ObjSyms[I];
+ lto::SymbolResolution &R = Resols[I];
// Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
// reports two symbols for module ASM defined. Without this check, lld
@@ -156,25 +179,46 @@ void BitcodeCompiler::add(BitcodeFile &F) {
R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj ||
(R.Prevailing && Sym->includeInDynsym()) ||
UsedStartStop.count(ObjSym.getSectionName());
+ const auto *DR = dyn_cast<Defined>(Sym);
+ R.FinalDefinitionInLinkageUnit =
+ (IsExec || Sym->Visibility != STV_DEFAULT) && DR &&
+ // Skip absolute symbols from ELF objects, otherwise PC-rel relocations
+ // will be generated by for them, triggering linker errors.
+ // Symbol section is always null for bitcode symbols, hence the check
+ // for isElf(). Skip linker script defined symbols as well: they have
+ // no File defined.
+ !(DR->Section == nullptr && (!Sym->File || Sym->File->isElf()));
+
if (R.Prevailing)
undefine(Sym);
- // We tell LTO to not apply interprocedural optimization for following
- // symbols because otherwise LTO would inline them while their values are
- // still not final:
- // 1) Aliased (with --defsym) or wrapped (with --wrap) symbols.
- // 2) Symbols redefined in linker script.
- R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(Sym->getName());
+ // We tell LTO to not apply interprocedural optimization for wrapped
+ // (with --wrap) symbols because otherwise LTO would inline them while
+ // their values are still not final.
+ R.LinkerRedefined = !Sym->CanInline;
}
checkError(LTOObj->add(std::move(F.Obj), Resols));
}
+static void createEmptyIndex(StringRef ModulePath) {
+ std::string Path = replaceThinLTOSuffix(getThinLTOOutputFile(ModulePath));
+ std::unique_ptr<raw_fd_ostream> OS = openFile(Path + ".thinlto.bc");
+ if (!OS)
+ return;
+
+ ModuleSummaryIndex M(/*HaveGVs*/ false);
+ M.setSkipModuleByDistributedBackend();
+ WriteIndexToFile(M, *OS);
+
+ if (Config->ThinLTOEmitImportsFiles)
+ openFile(Path + ".imports");
+}
+
// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile(s).
std::vector<InputFile *> BitcodeCompiler::compile() {
- std::vector<InputFile *> Ret;
unsigned MaxTasks = LTOObj->getMaxTasks();
- Buff.resize(MaxTasks);
+ Buf.resize(MaxTasks);
Files.resize(MaxTasks);
// The --thinlto-cache-dir option specifies the path to a directory in which
@@ -184,35 +228,67 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
if (!Config->ThinLTOCacheDir.empty())
Cache = check(
lto::localCache(Config->ThinLTOCacheDir,
- [&](size_t Task, std::unique_ptr<MemoryBuffer> MB,
- StringRef Path) { Files[Task] = std::move(MB); }));
+ [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
+ Files[Task] = std::move(MB);
+ }));
checkError(LTOObj->run(
[&](size_t Task) {
return llvm::make_unique<lto::NativeObjectStream>(
- llvm::make_unique<raw_svector_ostream>(Buff[Task]));
+ llvm::make_unique<raw_svector_ostream>(Buf[Task]));
},
Cache));
+ // Emit empty index files for non-indexed files
+ if (Config->ThinLTOIndexOnly) {
+ for (auto &Identifier : ObjectToIndexFileState)
+ if (!Identifier.getValue()) {
+ std::string Path = getThinLTOOutputFile(Identifier.getKey());
+ openFile(Path + ".thinlto.bc");
+
+ if (Config->ThinLTOEmitImportsFiles)
+ openFile(Path + ".imports");
+ }
+ }
+
+ // If LazyObjFile has not been added to link, emit empty index files.
+ // This is needed because this is what GNU gold plugin does and we have a
+ // distributed build system that depends on that behavior.
+ if (Config->ThinLTOIndexOnly) {
+ for (LazyObjFile *F : LazyObjFiles)
+ if (!F->AddedToLink && isBitcode(F->MB))
+ createEmptyIndex(F->getName());
+
+ if (!Config->LTOObjPath.empty())
+ saveBuffer(Buf[0], Config->LTOObjPath);
+
+ // ThinLTO with index only option is required to generate only the index
+ // files. After that, we exit from linker and ThinLTO backend runs in a
+ // distributed environment.
+ if (IndexFile)
+ IndexFile->close();
+ return {};
+ }
+
if (!Config->ThinLTOCacheDir.empty())
pruneCache(Config->ThinLTOCacheDir, Config->ThinLTOCachePolicy);
+ std::vector<InputFile *> Ret;
for (unsigned I = 0; I != MaxTasks; ++I) {
- if (Buff[I].empty())
+ if (Buf[I].empty())
continue;
if (Config->SaveTemps) {
if (I == 0)
- saveBuffer(Buff[I], Config->OutputFile + ".lto.o");
+ saveBuffer(Buf[I], Config->OutputFile + ".lto.o");
else
- saveBuffer(Buff[I], Config->OutputFile + Twine(I) + ".lto.o");
+ saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.o");
}
- InputFile *Obj = createObjectFile(MemoryBufferRef(Buff[I], "lto.tmp"));
+ InputFile *Obj = createObjectFile(MemoryBufferRef(Buf[I], "lto.tmp"));
Ret.push_back(Obj);
}
for (std::unique_ptr<MemoryBuffer> &File : Files)
if (File)
Ret.push_back(createObjectFile(*File));
-
return Ret;
}
diff --git a/contrib/llvm/tools/lld/ELF/LTO.h b/contrib/llvm/tools/lld/ELF/LTO.h
index 223af507a97d..8803078eb1df 100644
--- a/contrib/llvm/tools/lld/ELF/LTO.h
+++ b/contrib/llvm/tools/lld/ELF/LTO.h
@@ -24,6 +24,7 @@
#include "lld/Common/LLVM.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <vector>
@@ -38,6 +39,7 @@ namespace elf {
class BitcodeFile;
class InputFile;
+class LazyObjFile;
class BitcodeCompiler {
public:
@@ -49,9 +51,11 @@ public:
private:
std::unique_ptr<llvm::lto::LTO> LTOObj;
- std::vector<SmallString<0>> Buff;
+ std::vector<SmallString<0>> Buf;
std::vector<std::unique_ptr<MemoryBuffer>> Files;
llvm::DenseSet<StringRef> UsedStartStop;
+ std::unique_ptr<llvm::raw_fd_ostream> IndexFile;
+ llvm::StringMap<bool> ObjectToIndexFileState;
};
} // namespace elf
} // namespace lld
diff --git a/contrib/llvm/tools/lld/ELF/LinkerScript.cpp b/contrib/llvm/tools/lld/ELF/LinkerScript.cpp
index 23c3a11a9d1d..d94970e4847e 100644
--- a/contrib/llvm/tools/lld/ELF/LinkerScript.cpp
+++ b/contrib/llvm/tools/lld/ELF/LinkerScript.cpp
@@ -15,13 +15,13 @@
#include "Config.h"
#include "InputSection.h"
#include "OutputSections.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -74,7 +74,7 @@ uint64_t ExprValue::getSectionOffset() const {
// If the alignment is trivial, we don't have to compute the full
// value to know the offset. This allows this function to succeed in
// cases where the output section is not yet known.
- if (Alignment == 1)
+ if (Alignment == 1 && (!Sec || !Sec->getOutputSection()))
return Val;
return getValue() - getSecAddr();
}
@@ -102,28 +102,68 @@ OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) {
return CmdRef;
}
+// Expands the memory region by the specified size.
+static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size,
+ StringRef RegionName, StringRef SecName) {
+ MemRegion->CurPos += Size;
+ uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin;
+ if (NewSize > MemRegion->Length)
+ error("section '" + SecName + "' will not fit in region '" + RegionName +
+ "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes");
+}
+
+void LinkerScript::expandMemoryRegions(uint64_t Size) {
+ if (Ctx->MemRegion)
+ expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name,
+ Ctx->OutSec->Name);
+ // Only expand the LMARegion if it is different from MemRegion.
+ if (Ctx->LMARegion && Ctx->MemRegion != Ctx->LMARegion)
+ expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name,
+ Ctx->OutSec->Name);
+}
+
+void LinkerScript::expandOutputSection(uint64_t Size) {
+ Ctx->OutSec->Size += Size;
+ expandMemoryRegions(Size);
+}
+
void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
uint64_t Val = E().getValue();
if (Val < Dot && InSec)
error(Loc + ": unable to move location counter backward for: " +
Ctx->OutSec->Name);
- Dot = Val;
// Update to location counter means update to section size.
if (InSec)
- Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
+ expandOutputSection(Val - Dot);
+ else
+ expandMemoryRegions(Val - Dot);
+
+ Dot = Val;
}
-// This function is called from processSectionCommands,
-// while we are fixing the output section layout.
-void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
+// Used for handling linker symbol assignments, for both finalizing
+// their values and doing early declarations. Returns true if symbol
+// should be defined from linker script.
+static bool shouldDefineSym(SymbolAssignment *Cmd) {
if (Cmd->Name == ".")
- return;
+ return false;
- // If a symbol was in PROVIDE(), we need to define it only when
- // it is a referenced undefined symbol.
+ if (!Cmd->Provide)
+ return true;
+
+ // If a symbol was in PROVIDE(), we need to define it only
+ // when it is a referenced undefined symbol.
Symbol *B = Symtab->find(Cmd->Name);
- if (Cmd->Provide && (!B || B->isDefined()))
+ if (B && !B->isDefined())
+ return true;
+ return false;
+}
+
+// This function is called from processSectionCommands,
+// while we are fixing the output section layout.
+void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
+ if (!shouldDefineSym(Cmd))
return;
// Define a symbol.
@@ -153,6 +193,76 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
Cmd->Sym = cast<Defined>(Sym);
}
+// This function is called from LinkerScript::declareSymbols.
+// It creates a placeholder symbol if needed.
+static void declareSymbol(SymbolAssignment *Cmd) {
+ if (!shouldDefineSym(Cmd))
+ return;
+
+ // We can't calculate final value right now.
+ Symbol *Sym;
+ uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
+ std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility,
+ /*CanOmitFromDynSym*/ false,
+ /*File*/ nullptr);
+ replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility,
+ STT_NOTYPE, 0, 0, nullptr);
+ Cmd->Sym = cast<Defined>(Sym);
+ Cmd->Provide = false;
+}
+
+// This method is used to handle INSERT AFTER statement. Here we rebuild
+// the list of script commands to mix sections inserted into.
+void LinkerScript::processInsertCommands() {
+ std::vector<BaseCommand *> V;
+ auto Insert = [&](std::vector<BaseCommand *> &From) {
+ V.insert(V.end(), From.begin(), From.end());
+ From.clear();
+ };
+
+ for (BaseCommand *Base : SectionCommands) {
+ if (auto *OS = dyn_cast<OutputSection>(Base)) {
+ Insert(InsertBeforeCommands[OS->Name]);
+ V.push_back(Base);
+ Insert(InsertAfterCommands[OS->Name]);
+ continue;
+ }
+ V.push_back(Base);
+ }
+
+ for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands})
+ for (const std::pair<StringRef, std::vector<BaseCommand *>> &P : Cmds)
+ if (!P.second.empty())
+ error("unable to INSERT AFTER/BEFORE " + P.first +
+ ": section not defined");
+
+ SectionCommands = std::move(V);
+}
+
+// Symbols defined in script should not be inlined by LTO. At the same time
+// we don't know their final values until late stages of link. Here we scan
+// over symbol assignment commands and create placeholder symbols if needed.
+void LinkerScript::declareSymbols() {
+ assert(!Ctx);
+ for (BaseCommand *Base : SectionCommands) {
+ if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+ declareSymbol(Cmd);
+ continue;
+ }
+
+ // If the output section directive has constraints,
+ // we can't say for sure if it is going to be included or not.
+ // Skip such sections for now. Improve the checks if we ever
+ // need symbols from that sections to be declared early.
+ auto *Sec = cast<OutputSection>(Base);
+ if (Sec->Constraint != ConstraintKind::NoConstraint)
+ continue;
+ for (BaseCommand *Base2 : Sec->SectionCommands)
+ if (auto *Cmd = dyn_cast<SymbolAssignment>(Base2))
+ declareSymbol(Cmd);
+ }
+}
+
// This function is called from assignAddresses, while we are
// fixing the output section addresses. This function is supposed
// to set the final value for a given symbol assignment.
@@ -249,23 +359,11 @@ static void sortSections(MutableArrayRef<InputSection *> Vec,
// --sort-section is handled as an inner SORT command.
// 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
// 4. If no SORT command is given, sort according to --sort-section.
-// 5. If no SORT commands are given and --sort-section is not specified,
-// apply sorting provided by --symbol-ordering-file if any exist.
-static void sortInputSections(
- MutableArrayRef<InputSection *> Vec, const SectionPattern &Pat,
- const DenseMap<SectionBase *, int> &Order) {
+static void sortInputSections(MutableArrayRef<InputSection *> Vec,
+ const SectionPattern &Pat) {
if (Pat.SortOuter == SortSectionPolicy::None)
return;
- if (Pat.SortOuter == SortSectionPolicy::Default &&
- Config->SortSection == SortSectionPolicy::Default) {
- // If -symbol-ordering-file was given, sort accordingly.
- // Usually, Order is empty.
- if (!Order.empty())
- sortByOrder(Vec, [&](InputSectionBase *S) { return Order.lookup(S); });
- return;
- }
-
if (Pat.SortInner == SortSectionPolicy::Default)
sortSections(Vec, Config->SortSection);
else
@@ -275,8 +373,7 @@ static void sortInputSections(
// Compute and remember which sections the InputSectionDescription matches.
std::vector<InputSection *>
-LinkerScript::computeInputSections(const InputSectionDescription *Cmd,
- const DenseMap<SectionBase *, int> &Order) {
+LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
std::vector<InputSection *> Ret;
// Collects all sections that satisfy constraints of Cmd.
@@ -290,8 +387,11 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd,
// For -emit-relocs we have to ignore entries like
// .rela.dyn : { *(.rela.data) }
// which are common because they are in the default bfd script.
- if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
- continue;
+ // We do not ignore SHT_REL[A] linker-synthesized sections here because
+ // want to support scripts that do custom layout for them.
+ if (auto *IS = dyn_cast<InputSection>(Sec))
+ if (IS->getRelocatedSection())
+ continue;
std::string Filename = getFilename(Sec->File);
if (!Cmd->FilePat.match(Filename) ||
@@ -307,7 +407,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd,
}
sortInputSections(MutableArrayRef<InputSection *>(Ret).slice(SizeBefore),
- Pat, Order);
+ Pat);
}
return Ret;
}
@@ -315,22 +415,31 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd,
void LinkerScript::discard(ArrayRef<InputSection *> V) {
for (InputSection *S : V) {
if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab ||
- S == InX::DynStrTab)
+ S == InX::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn ||
+ S == InX::RelrDyn)
error("discarding " + S->Name + " section is not allowed");
+ // You can discard .hash and .gnu.hash sections by linker scripts. Since
+ // they are synthesized sections, we need to handle them differently than
+ // other regular sections.
+ if (S == InX::GnuHashTab)
+ InX::GnuHashTab = nullptr;
+ if (S == InX::HashTab)
+ InX::HashTab = nullptr;
+
S->Assigned = false;
S->Live = false;
discard(S->DependentSections);
}
}
-std::vector<InputSection *> LinkerScript::createInputSectionList(
- OutputSection &OutCmd, const DenseMap<SectionBase *, int> &Order) {
+std::vector<InputSection *>
+LinkerScript::createInputSectionList(OutputSection &OutCmd) {
std::vector<InputSection *> Ret;
for (BaseCommand *Base : OutCmd.SectionCommands) {
if (auto *Cmd = dyn_cast<InputSectionDescription>(Base)) {
- Cmd->Sections = computeInputSections(Cmd, Order);
+ Cmd->Sections = computeInputSections(Cmd);
Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end());
}
}
@@ -359,7 +468,6 @@ void LinkerScript::processSectionCommands() {
Ctx->OutSec = Aether;
size_t I = 0;
- DenseMap<SectionBase *, int> Order = buildSectionOrder();
// Add input sections to output sections.
for (BaseCommand *Base : SectionCommands) {
// Handle symbol assignments outside of any output section.
@@ -369,12 +477,13 @@ void LinkerScript::processSectionCommands() {
}
if (auto *Sec = dyn_cast<OutputSection>(Base)) {
- std::vector<InputSection *> V = createInputSectionList(*Sec, Order);
+ std::vector<InputSection *> V = createInputSectionList(*Sec);
// The output section name `/DISCARD/' is special.
// Any input section assigned to it is discarded.
if (Sec->Name == "/DISCARD/") {
discard(V);
+ Sec->SectionCommands.clear();
continue;
}
@@ -414,6 +523,8 @@ void LinkerScript::processSectionCommands() {
Sec->SectionIndex = I++;
if (Sec->Noload)
Sec->Type = SHT_NOBITS;
+ if (Sec->NonAlloc)
+ Sec->Flags &= ~(uint64_t)SHF_ALLOC;
}
}
Ctx = nullptr;
@@ -484,7 +595,7 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,
// ignored. We should not have two output .text sections just because one was
// in a group and another was not for example.
//
- // It also seems that that wording was a late addition and didn't get the
+ // It also seems that wording was a late addition and didn't get the
// necessary scrutiny.
//
// Merging sections with different flags is expected by some users. One
@@ -529,11 +640,11 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,
void LinkerScript::addOrphanSections() {
unsigned End = SectionCommands.size();
StringMap<OutputSection *> Map;
-
std::vector<OutputSection *> V;
- for (InputSectionBase *S : InputSections) {
+
+ auto Add = [&](InputSectionBase *S) {
if (!S->Live || S->Parent)
- continue;
+ return;
StringRef Name = getOutputSectionName(S);
@@ -545,12 +656,24 @@ void LinkerScript::addOrphanSections() {
if (OutputSection *Sec =
findByName(makeArrayRef(SectionCommands).slice(0, End), Name)) {
Sec->addSection(cast<InputSection>(S));
- continue;
+ return;
}
if (OutputSection *OS = addInputSec(Map, S, Name))
V.push_back(OS);
- assert(S->getOutputSection()->SectionIndex == INT_MAX);
+ assert(S->getOutputSection()->SectionIndex == UINT32_MAX);
+ };
+
+ // For futher --emit-reloc handling code we need target output section
+ // to be created before we create relocation output section, so we want
+ // to create target sections first. We do not want priority handling
+ // for synthetic sections because them are special.
+ for (InputSectionBase *IS : InputSections) {
+ if (auto *Sec = dyn_cast<InputSection>(IS))
+ if (InputSectionBase *Rel = Sec->getRelocatedSection())
+ if (auto *RelIS = dyn_cast_or_null<InputSectionBase>(Rel->Parent))
+ Add(RelIS);
+ Add(IS);
}
// If no SECTIONS command was given, we should insert sections commands
@@ -585,33 +708,15 @@ void LinkerScript::output(InputSection *S) {
// Update output section size after adding each section. This is so that
// SIZEOF works correctly in the case below:
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
- Ctx->OutSec->Size = Pos - Ctx->OutSec->Addr;
-
- // If there is a memory region associated with this input section, then
- // place the section in that region and update the region index.
- if (Ctx->LMARegion)
- Ctx->LMARegion->CurPos += Pos - Before;
- // FIXME: should we also produce overflow errors for LMARegion?
-
- if (Ctx->MemRegion) {
- uint64_t &CurOffset = Ctx->MemRegion->CurPos;
- CurOffset += Pos - Before;
- uint64_t CurSize = CurOffset - Ctx->MemRegion->Origin;
- if (CurSize > Ctx->MemRegion->Length) {
- uint64_t OverflowAmt = CurSize - Ctx->MemRegion->Length;
- error("section '" + Ctx->OutSec->Name + "' will not fit in region '" +
- Ctx->MemRegion->Name + "': overflowed by " + Twine(OverflowAmt) +
- " bytes");
- }
- }
+ expandOutputSection(Pos - Before);
}
void LinkerScript::switchTo(OutputSection *Sec) {
- if (Ctx->OutSec == Sec)
- return;
-
Ctx->OutSec = Sec;
+
+ uint64_t Before = advance(0, 1);
Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment);
+ expandMemoryRegions(Ctx->OutSec->Addr - Before);
}
// This function searches for a memory region to place the given output
@@ -646,6 +751,13 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {
return nullptr;
}
+static OutputSection *findFirstSection(PhdrEntry *Load) {
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->PtLoad == Load)
+ return Sec;
+ return nullptr;
+}
+
// This function assigns offsets to input sections and an output section
// for a single sections command (e.g. ".text { *(.text); }").
void LinkerScript::assignOffsets(OutputSection *Sec) {
@@ -671,12 +783,14 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
// will set the LMA such that the difference between VMA and LMA for the
// section is the same as the preceding output section in the same region
// https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
+ // This, however, should only be done by the first "non-header" section
+ // in the segment.
if (PhdrEntry *L = Ctx->OutSec->PtLoad)
- L->LMAOffset = Ctx->LMAOffset;
+ if (Sec == findFirstSection(L))
+ L->LMAOffset = Ctx->LMAOffset;
- // The Size previously denoted how many InputSections had been added to this
- // section, and was used for sorting SHF_LINK_ORDER sections. Reset it to
- // compute the actual size value.
+ // We can call this method multiple times during the creation of
+ // thunks and want to start over calculation each time.
Sec->Size = 0;
// We visited SectionsCommands from processSectionCommands to
@@ -685,7 +799,9 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
for (BaseCommand *Base : Sec->SectionCommands) {
// This handles the assignments to symbol or to the dot.
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+ Cmd->Addr = Dot;
assignSymbol(Cmd, true);
+ Cmd->Size = Dot - Cmd->Addr;
continue;
}
@@ -693,17 +809,7 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {
Cmd->Offset = Dot - Ctx->OutSec->Addr;
Dot += Cmd->Size;
- if (Ctx->MemRegion)
- Ctx->MemRegion->CurPos += Cmd->Size;
- if (Ctx->LMARegion)
- Ctx->LMARegion->CurPos += Cmd->Size;
- Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
- continue;
- }
-
- // Handle ASSERT().
- if (auto *Cmd = dyn_cast<AssertCommand>(Base)) {
- Cmd->Expression();
+ expandOutputSection(Cmd->Size);
continue;
}
@@ -728,24 +834,28 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
}
}
-void LinkerScript::removeEmptyCommands() {
- // It is common practice to use very generic linker scripts. So for any
- // given run some of the output sections in the script will be empty.
- // We could create corresponding empty output sections, but that would
- // clutter the output.
- // We instead remove trivially empty sections. The bfd linker seems even
- // more aggressive at removing them.
- llvm::erase_if(SectionCommands, [&](BaseCommand *Base) {
- if (auto *Sec = dyn_cast<OutputSection>(Base))
- return !Sec->Live;
+static bool isDiscardable(OutputSection &Sec) {
+ // We do not remove empty sections that are explicitly
+ // assigned to any segment.
+ if (!Sec.Phdrs.empty())
return false;
- });
-}
-static bool isAllSectionDescription(const OutputSection &Cmd) {
- for (BaseCommand *Base : Cmd.SectionCommands)
+ // We do not want to remove sections that reference symbols in address and
+ // other expressions. We add script symbols as undefined, and want to ensure
+ // all of them are defined in the output, hence have to keep them.
+ if (Sec.ExpressionsUseSymbols)
+ return false;
+
+ for (BaseCommand *Base : Sec.SectionCommands) {
+ if (auto Cmd = dyn_cast<SymbolAssignment>(Base))
+ // Don't create empty output sections just for unreferenced PROVIDE
+ // symbols.
+ if (Cmd->Name != "." && !Cmd->Sym)
+ continue;
+
if (!isa<InputSectionDescription>(*Base))
return false;
+ }
return true;
}
@@ -761,7 +871,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
// Given that we want to create the section, we have to worry what impact
// it will have on the link. For example, if we just create a section with
// 0 for flags, it would change which PT_LOADs are created.
- // We could remember that that particular section is dummy and ignore it in
+ // We could remember that particular section is dummy and ignore it in
// other parts of the linker, but unfortunately there are quite a few places
// that would need to change:
// * The program header creation.
@@ -772,29 +882,47 @@ void LinkerScript::adjustSectionsBeforeSorting() {
// the previous sections. Only a few flags are needed to keep the impact low.
uint64_t Flags = SHF_ALLOC;
- for (BaseCommand *Cmd : SectionCommands) {
+ for (BaseCommand *&Cmd : SectionCommands) {
auto *Sec = dyn_cast<OutputSection>(Cmd);
if (!Sec)
continue;
- if (Sec->Live) {
- Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
- continue;
- }
-
- if (isAllSectionDescription(*Sec))
- continue;
- Sec->Live = true;
- Sec->Flags = Flags;
+ // Handle align (e.g. ".foo : ALIGN(16) { ... }").
+ if (Sec->AlignExpr)
+ Sec->Alignment =
+ std::max<uint32_t>(Sec->Alignment, Sec->AlignExpr().getValue());
+
+ // A live output section means that some input section was added to it. It
+ // might have been removed (if it was empty synthetic section), but we at
+ // least know the flags.
+ if (Sec->Live)
+ Flags = Sec->Flags;
+
+ // We do not want to keep any special flags for output section
+ // in case it is empty.
+ bool IsEmpty = getInputSections(Sec).empty();
+ if (IsEmpty)
+ Sec->Flags = Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
+
+ if (IsEmpty && isDiscardable(*Sec)) {
+ Sec->Live = false;
+ Cmd = nullptr;
+ }
}
+
+ // It is common practice to use very generic linker scripts. So for any
+ // given run some of the output sections in the script will be empty.
+ // We could create corresponding empty output sections, but that would
+ // clutter the output.
+ // We instead remove trivially empty sections. The bfd linker seems even
+ // more aggressive at removing them.
+ llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; });
}
void LinkerScript::adjustSectionsAfterSorting() {
// Try and find an appropriate memory region to assign offsets in.
for (BaseCommand *Base : SectionCommands) {
if (auto *Sec = dyn_cast<OutputSection>(Base)) {
- if (!Sec->Live)
- continue;
if (!Sec->LMARegionName.empty()) {
if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName))
Sec->LMARegion = M;
@@ -802,10 +930,6 @@ void LinkerScript::adjustSectionsAfterSorting() {
error("memory region '" + Sec->LMARegionName + "' not declared");
}
Sec->MemRegion = findMemoryRegion(Sec);
- // Handle align (e.g. ".foo : ALIGN(16) { ... }").
- if (Sec->AlignExpr)
- Sec->Alignment =
- std::max<uint32_t>(Sec->Alignment, Sec->AlignExpr().getValue());
}
}
@@ -816,9 +940,9 @@ void LinkerScript::adjustSectionsAfterSorting() {
// PHDRS { seg PT_LOAD; }
// SECTIONS { .aaa : { *(.aaa) } }
std::vector<StringRef> DefPhdrs;
- auto FirstPtLoad =
- std::find_if(PhdrsCommands.begin(), PhdrsCommands.end(),
- [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; });
+ auto FirstPtLoad = llvm::find_if(PhdrsCommands, [](const PhdrsCommand &Cmd) {
+ return Cmd.Type == PT_LOAD;
+ });
if (FirstPtLoad != PhdrsCommands.end())
DefPhdrs.push_back(FirstPtLoad->Name);
@@ -840,11 +964,13 @@ void LinkerScript::adjustSectionsAfterSorting() {
}
}
-static OutputSection *findFirstSection(PhdrEntry *Load) {
- for (OutputSection *Sec : OutputSections)
- if (Sec->PtLoad == Load)
- return Sec;
- return nullptr;
+static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) {
+ // If there is no SECTIONS or if the linkerscript is explicit about program
+ // headers, do our best to allocate them.
+ if (!Script->HasSectionsCommand || AllocateHeaders)
+ return 0;
+ // Otherwise only allocate program headers if that would not add a page.
+ return alignDown(Min, Config->MaxPageSize);
}
// Try to find an address for the file and program headers output sections,
@@ -870,17 +996,22 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
return;
PhdrEntry *FirstPTLoad = *It;
+ bool HasExplicitHeaders =
+ llvm::any_of(PhdrsCommands, [](const PhdrsCommand &Cmd) {
+ return Cmd.HasPhdrs || Cmd.HasFilehdr;
+ });
uint64_t HeaderSize = getHeaderSize();
- // When linker script with SECTIONS is being used, don't output headers
- // unless there's a space for them.
- uint64_t Base = HasSectionsCommand ? alignDown(Min, Config->MaxPageSize) : 0;
- if (HeaderSize <= Min - Base || Script->hasPhdrsCommands()) {
+ if (HeaderSize <= Min - computeBase(Min, HasExplicitHeaders)) {
Min = alignDown(Min - HeaderSize, Config->MaxPageSize);
Out::ElfHeader->Addr = Min;
Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;
return;
}
+ // Error if we were explicitly asked to allocate headers.
+ if (HasExplicitHeaders)
+ error("could not allocate headers");
+
Out::ElfHeader->PtLoad = nullptr;
Out::ProgramHeaders->PtLoad = nullptr;
FirstPTLoad->FirstSec = findFirstSection(FirstPTLoad);
@@ -924,15 +1055,11 @@ void LinkerScript::assignAddresses() {
for (BaseCommand *Base : SectionCommands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+ Cmd->Addr = Dot;
assignSymbol(Cmd, false);
+ Cmd->Size = Dot - Cmd->Addr;
continue;
}
-
- if (auto *Cmd = dyn_cast<AssertCommand>(Base)) {
- Cmd->Expression();
- continue;
- }
-
assignOffsets(cast<OutputSection>(Base));
}
Ctx = nullptr;
@@ -996,9 +1123,9 @@ ExprValue LinkerScript::getSymbolValue(StringRef Name, const Twine &Loc) {
if (Symbol *Sym = Symtab->find(Name)) {
if (auto *DS = dyn_cast<Defined>(Sym))
return {DS->Section, false, DS->Value, Loc};
- if (auto *SS = dyn_cast<SharedSymbol>(Sym))
- if (!ErrorOnMissingSection || SS->CopyRelSec)
- return {SS->CopyRelSec, false, 0, Loc};
+ if (isa<SharedSymbol>(Sym))
+ if (!ErrorOnMissingSection)
+ return {nullptr, false, 0, Loc};
}
error(Loc + ": symbol not found: " + Name);
diff --git a/contrib/llvm/tools/lld/ELF/LinkerScript.h b/contrib/llvm/tools/lld/ELF/LinkerScript.h
index 0d7578cd2f1d..3b790dd4669f 100644
--- a/contrib/llvm/tools/lld/ELF/LinkerScript.h
+++ b/contrib/llvm/tools/lld/ELF/LinkerScript.h
@@ -11,9 +11,9 @@
#define LLD_ELF_LINKER_SCRIPT_H
#include "Config.h"
-#include "Strings.h"
#include "Writer.h"
#include "lld/Common/LLVM.h"
+#include "lld/Common/Strings.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@@ -75,7 +75,6 @@ enum SectionsCommandKind {
AssignmentKind, // . = expr or <sym> = expr
OutputSectionKind,
InputSectionKind,
- AssertKind, // ASSERT(expr)
ByteKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr)
};
@@ -106,6 +105,16 @@ struct SymbolAssignment : BaseCommand {
// Holds file name and line number for error reporting.
std::string Location;
+
+ // A string representation of this command. We use this for -Map.
+ std::string CommandString;
+
+ // Address of this assignment command.
+ unsigned Addr;
+
+ // Size of this assignment command. This is usually 0, but if
+ // you move '.' this may be greater than 0.
+ unsigned Size;
};
// Linker scripts allow additional constraints to be put on ouput sections.
@@ -167,24 +176,23 @@ struct InputSectionDescription : BaseCommand {
std::vector<std::pair<ThunkSection *, uint32_t>> ThunkSections;
};
-// Represents an ASSERT().
-struct AssertCommand : BaseCommand {
- AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {}
-
- static bool classof(const BaseCommand *C) { return C->Kind == AssertKind; }
-
- Expr Expression;
-};
-
// Represents BYTE(), SHORT(), LONG(), or QUAD().
struct ByteCommand : BaseCommand {
- ByteCommand(Expr E, unsigned Size)
- : BaseCommand(ByteKind), Expression(E), Size(Size) {}
+ ByteCommand(Expr E, unsigned Size, std::string CommandString)
+ : BaseCommand(ByteKind), CommandString(CommandString), Expression(E),
+ Size(Size) {}
static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; }
+ // Keeps string representing the command. Used for -Map" is perhaps better.
+ std::string CommandString;
+
Expr Expression;
+
+ // This is just an offset of this assignment command in the output section.
unsigned Offset;
+
+ // Size of this data command.
unsigned Size;
};
@@ -215,14 +223,13 @@ class LinkerScript final {
void addSymbol(SymbolAssignment *Cmd);
void assignSymbol(SymbolAssignment *Cmd, bool InSec);
void setDot(Expr E, const Twine &Loc, bool InSec);
+ void expandOutputSection(uint64_t Size);
+ void expandMemoryRegions(uint64_t Size);
std::vector<InputSection *>
- computeInputSections(const InputSectionDescription *,
- const llvm::DenseMap<SectionBase *, int> &Order);
+ computeInputSections(const InputSectionDescription *);
- std::vector<InputSection *>
- createInputSectionList(OutputSection &Cmd,
- const llvm::DenseMap<SectionBase *, int> &Order);
+ std::vector<InputSection *> createInputSectionList(OutputSection &Cmd);
std::vector<size_t> getPhdrIndices(OutputSection *Sec);
@@ -257,7 +264,6 @@ public:
ExprValue getSymbolValue(StringRef Name, const Twine &Loc);
void addOrphanSections();
- void removeEmptyCommands();
void adjustSectionsBeforeSorting();
void adjustSectionsAfterSorting();
@@ -268,6 +274,10 @@ public:
void assignAddresses();
void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);
void processSectionCommands();
+ void declareSymbols();
+
+ // Used to handle INSERT AFTER statements.
+ void processInsertCommands();
// SECTIONS command list.
std::vector<BaseCommand *> SectionCommands;
@@ -287,6 +297,11 @@ public:
// A list of symbols referenced by the script.
std::vector<llvm::StringRef> ReferencedSymbols;
+
+ // Used to implement INSERT [AFTER|BEFORE]. Contains commands that need
+ // to be inserted into SECTIONS commands list.
+ llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
+ llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertBeforeCommands;
};
extern LinkerScript *Script;
diff --git a/contrib/llvm/tools/lld/ELF/MapFile.cpp b/contrib/llvm/tools/lld/ELF/MapFile.cpp
index dcc829315e64..54fddfb7b299 100644
--- a/contrib/llvm/tools/lld/ELF/MapFile.cpp
+++ b/contrib/llvm/tools/lld/ELF/MapFile.cpp
@@ -23,11 +23,13 @@
#include "InputFiles.h"
#include "LinkerScript.h"
#include "OutputSections.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
+#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -36,57 +38,46 @@ using namespace llvm::object;
using namespace lld;
using namespace lld::elf;
-typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy;
+typedef DenseMap<const SectionBase *, SmallVector<Defined *, 4>> SymbolMapTy;
+
+static const std::string Indent8 = " "; // 8 spaces
+static const std::string Indent16 = " "; // 16 spaces
// Print out the first three columns of a line.
-static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,
- uint64_t Align) {
- int W = Config->Is64 ? 16 : 8;
- OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align);
+static void writeHeader(raw_ostream &OS, uint64_t VMA, uint64_t LMA,
+ uint64_t Size, uint64_t Align) {
+ if (Config->Is64)
+ OS << format("%16llx %16llx %8llx %5lld ", VMA, LMA, Size, Align);
+ else
+ OS << format("%8llx %8llx %8llx %5lld ", VMA, LMA, Size, Align);
}
-static std::string indent(int Depth) { return std::string(Depth * 8, ' '); }
-
// Returns a list of all symbols that we want to print out.
-static std::vector<Symbol *> getSymbols() {
- std::vector<Symbol *> V;
- for (InputFile *File : ObjectFiles) {
- for (Symbol *B : File->getSymbols()) {
- if (auto *SS = dyn_cast<SharedSymbol>(B))
- if (SS->CopyRelSec || SS->NeedsPltAddr)
- V.push_back(SS);
+static std::vector<Defined *> getSymbols() {
+ std::vector<Defined *> V;
+ for (InputFile *File : ObjectFiles)
+ for (Symbol *B : File->getSymbols())
if (auto *DR = dyn_cast<Defined>(B))
- if (DR->File == File && !DR->isSection() && DR->Section &&
- DR->Section->Live)
+ if (!DR->isSection() && DR->Section && DR->Section->Live &&
+ (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss))
V.push_back(DR);
- }
- }
return V;
}
// Returns a map from sections to their symbols.
-static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) {
+static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {
SymbolMapTy Ret;
- for (Symbol *S : Syms) {
- if (auto *DR = dyn_cast<Defined>(S)) {
- Ret[DR->Section].push_back(S);
- continue;
- }
-
- SharedSymbol *SS = cast<SharedSymbol>(S);
- if (SS->CopyRelSec)
- Ret[SS->CopyRelSec].push_back(S);
- else
- Ret[InX::Plt].push_back(S);
- }
+ for (Defined *DR : Syms)
+ Ret[DR->Section].push_back(DR);
// Sort symbols by address. We want to print out symbols in the
// order in the output file rather than the order they appeared
// in the input files.
for (auto &It : Ret) {
- SmallVectorImpl<Symbol *> &V = It.second;
- std::sort(V.begin(), V.end(),
- [](Symbol *A, Symbol *B) { return A->getVA() < B->getVA(); });
+ SmallVectorImpl<Defined *> &V = It.second;
+ std::stable_sort(V.begin(), V.end(), [](Defined *A, Defined *B) {
+ return A->getVA() < B->getVA();
+ });
}
return Ret;
}
@@ -95,12 +86,15 @@ static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) {
// Demangling symbols (which is what toString() does) is slow, so
// we do that in batch using parallel-for.
static DenseMap<Symbol *, std::string>
-getSymbolStrings(ArrayRef<Symbol *> Syms) {
+getSymbolStrings(ArrayRef<Defined *> Syms) {
std::vector<std::string> Str(Syms.size());
parallelForEachN(0, Syms.size(), [&](size_t I) {
raw_string_ostream OS(Str[I]);
- writeHeader(OS, Syms[I]->getVA(), Syms[I]->getSize(), 0);
- OS << indent(2) << toString(*Syms[I]);
+ OutputSection *OSec = Syms[I]->getOutputSection();
+ uint64_t VMA = Syms[I]->getVA();
+ uint64_t LMA = OSec ? OSec->getLMA() + VMA - OSec->getVA(0) : 0;
+ writeHeader(OS, VMA, LMA, Syms[I]->getSize(), 1);
+ OS << Indent16 << toString(*Syms[I]);
});
DenseMap<Symbol *, std::string> Ret;
@@ -109,6 +103,44 @@ getSymbolStrings(ArrayRef<Symbol *> Syms) {
return Ret;
}
+// Print .eh_frame contents. Since the section consists of EhSectionPieces,
+// we need a specialized printer for that section.
+//
+// .eh_frame tend to contain a lot of section pieces that are contiguous
+// both in input file and output file. Such pieces are squashed before
+// being displayed to make output compact.
+static void printEhFrame(raw_ostream &OS, OutputSection *OSec) {
+ std::vector<EhSectionPiece> Pieces;
+
+ auto Add = [&](const EhSectionPiece &P) {
+ // If P is adjacent to Last, squash the two.
+ if (!Pieces.empty()) {
+ EhSectionPiece &Last = Pieces.back();
+ if (Last.Sec == P.Sec && Last.InputOff + Last.Size == P.InputOff &&
+ Last.OutputOff + Last.Size == P.OutputOff) {
+ Last.Size += P.Size;
+ return;
+ }
+ }
+ Pieces.push_back(P);
+ };
+
+ // Gather section pieces.
+ for (const CieRecord *Rec : InX::EhFrame->getCieRecords()) {
+ Add(*Rec->Cie);
+ for (const EhSectionPiece *Fde : Rec->Fdes)
+ Add(*Fde);
+ }
+
+ // Print out section pieces.
+ for (EhSectionPiece &P : Pieces) {
+ writeHeader(OS, OSec->Addr + P.OutputOff, OSec->getLMA() + P.OutputOff,
+ P.Size, 1);
+ OS << Indent8 << toString(P.Sec->File) << ":(" << P.Sec->Name << "+0x"
+ << Twine::utohexstr(P.InputOff) + ")\n";
+ }
+}
+
void elf::writeMapFile() {
if (Config->MapFile.empty())
return;
@@ -122,32 +154,109 @@ void elf::writeMapFile() {
}
// Collect symbol info that we want to print out.
- std::vector<Symbol *> Syms = getSymbols();
+ std::vector<Defined *> Syms = getSymbols();
SymbolMapTy SectionSyms = getSectionSyms(Syms);
DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
// Print out the header line.
int W = Config->Is64 ? 16 : 8;
- OS << left_justify("Address", W) << ' ' << left_justify("Size", W)
- << " Align Out In Symbol\n";
+ OS << right_justify("VMA", W) << ' ' << right_justify("LMA", W)
+ << " Size Align Out In Symbol\n";
+
+ for (BaseCommand *Base : Script->SectionCommands) {
+ if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+ if (Cmd->Provide && !Cmd->Sym)
+ continue;
+ //FIXME: calculate and print LMA.
+ writeHeader(OS, Cmd->Addr, 0, Cmd->Size, 1);
+ OS << Cmd->CommandString << '\n';
+ continue;
+ }
- // Print out file contents.
- for (OutputSection *OSec : OutputSections) {
- writeHeader(OS, OSec->Addr, OSec->Size, OSec->Alignment);
+ auto *OSec = cast<OutputSection>(Base);
+ writeHeader(OS, OSec->Addr, OSec->getLMA(), OSec->Size, OSec->Alignment);
OS << OSec->Name << '\n';
// Dump symbols for each input section.
for (BaseCommand *Base : OSec->SectionCommands) {
- auto *ISD = dyn_cast<InputSectionDescription>(Base);
- if (!ISD)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {
+ for (InputSection *IS : ISD->Sections) {
+ if (IS == InX::EhFrame) {
+ printEhFrame(OS, OSec);
+ continue;
+ }
+
+ writeHeader(OS, IS->getVA(0), OSec->getLMA() + IS->getOffset(0),
+ IS->getSize(), IS->Alignment);
+ OS << Indent8 << toString(IS) << '\n';
+ for (Symbol *Sym : SectionSyms[IS])
+ OS << SymStr[Sym] << '\n';
+ }
+ continue;
+ }
+
+ if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {
+ writeHeader(OS, OSec->Addr + Cmd->Offset, OSec->getLMA() + Cmd->Offset,
+ Cmd->Size, 1);
+ OS << Indent8 << Cmd->CommandString << '\n';
+ continue;
+ }
+
+ if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+ if (Cmd->Provide && !Cmd->Sym)
+ continue;
+ writeHeader(OS, Cmd->Addr, OSec->getLMA() + Cmd->Addr - OSec->getVA(0),
+ Cmd->Size, 1);
+ OS << Indent8 << Cmd->CommandString << '\n';
continue;
- for (InputSection *IS : ISD->Sections) {
- writeHeader(OS, OSec->Addr + IS->OutSecOff, IS->getSize(),
- IS->Alignment);
- OS << indent(1) << toString(IS) << '\n';
- for (Symbol *Sym : SectionSyms[IS])
- OS << SymStr[Sym] << '\n';
}
}
}
}
+
+static void print(StringRef A, StringRef B) {
+ outs() << left_justify(A, 49) << " " << B << "\n";
+}
+
+// Output a cross reference table to stdout. This is for --cref.
+//
+// For each global symbol, we print out a file that defines the symbol
+// followed by files that uses that symbol. Here is an example.
+//
+// strlen /lib/x86_64-linux-gnu/libc.so.6
+// tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o
+// lib/libLLVMSupport.a(PrettyStackTrace.cpp.o)
+//
+// In this case, strlen is defined by libc.so.6 and used by other two
+// files.
+void elf::writeCrossReferenceTable() {
+ if (!Config->Cref)
+ return;
+
+ // Collect symbols and files.
+ MapVector<Symbol *, SetVector<InputFile *>> Map;
+ for (InputFile *File : ObjectFiles) {
+ for (Symbol *Sym : File->getSymbols()) {
+ if (isa<SharedSymbol>(Sym))
+ Map[Sym].insert(File);
+ if (auto *D = dyn_cast<Defined>(Sym))
+ if (!D->isLocal() && (!D->Section || D->Section->Live))
+ Map[D].insert(File);
+ }
+ }
+
+ // Print out a header.
+ outs() << "Cross Reference Table\n\n";
+ print("Symbol", "File");
+
+ // Print out a table.
+ for (auto KV : Map) {
+ Symbol *Sym = KV.first;
+ SetVector<InputFile *> &Files = KV.second;
+
+ print(toString(*Sym), toString(Sym->File));
+ for (InputFile *File : Files)
+ if (File != Sym->File)
+ print("", toString(File));
+ }
+}
diff --git a/contrib/llvm/tools/lld/ELF/MapFile.h b/contrib/llvm/tools/lld/ELF/MapFile.h
index 2d93e26d4cf8..0282425888b7 100644
--- a/contrib/llvm/tools/lld/ELF/MapFile.h
+++ b/contrib/llvm/tools/lld/ELF/MapFile.h
@@ -13,6 +13,7 @@
namespace lld {
namespace elf {
void writeMapFile();
+void writeCrossReferenceTable();
} // namespace elf
} // namespace lld
diff --git a/contrib/llvm/tools/lld/ELF/MarkLive.cpp b/contrib/llvm/tools/lld/ELF/MarkLive.cpp
index 88f558c7a3c6..a8371e212c3e 100644
--- a/contrib/llvm/tools/lld/ELF/MarkLive.cpp
+++ b/contrib/llvm/tools/lld/ELF/MarkLive.cpp
@@ -20,15 +20,15 @@
//
//===----------------------------------------------------------------------===//
+#include "MarkLive.h"
#include "InputSection.h"
#include "LinkerScript.h"
#include "OutputSections.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "Target.h"
-#include "Writer.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
#include <functional>
@@ -60,8 +60,9 @@ static typename ELFT::uint getAddend(InputSectionBase &Sec,
static DenseMap<StringRef, std::vector<InputSectionBase *>> CNamedSections;
template <class ELFT, class RelT>
-static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
- std::function<void(InputSectionBase *, uint64_t)> Fn) {
+static void
+resolveReloc(InputSectionBase &Sec, RelT &Rel,
+ llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
Symbol &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
// If a symbol is referenced in a live section, it is used.
@@ -90,7 +91,7 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
template <class ELFT>
static void
forEachSuccessor(InputSection &Sec,
- std::function<void(InputSectionBase *, uint64_t)> Fn) {
+ llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
if (Sec.AreRelocsRela) {
for (const typename ELFT::Rela &Rel : Sec.template relas<ELFT>())
resolveReloc<ELFT>(Sec, Rel, Fn);
@@ -120,7 +121,7 @@ forEachSuccessor(InputSection &Sec,
template <class ELFT, class RelTy>
static void
scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels,
- std::function<void(InputSectionBase *, uint64_t)> Fn) {
+ llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
const endianness E = ELFT::TargetEndianness;
for (unsigned I = 0, N = EH.Pieces.size(); I < N; ++I) {
@@ -155,14 +156,10 @@ scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels,
template <class ELFT>
static void
scanEhFrameSection(EhInputSection &EH,
- std::function<void(InputSectionBase *, uint64_t)> Fn) {
+ llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
if (!EH.NumRelocations)
return;
- // Unfortunately we need to split .eh_frame early since some relocations in
- // .eh_frame keep other section alive and some don't.
- EH.split<ELFT>();
-
if (EH.AreRelocsRela)
scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Fn);
else
@@ -207,7 +204,7 @@ template <class ELFT> static void doGcSections() {
// (splittable) sections, each piece of data has independent liveness bit.
// So we explicitly tell it which offset is in use.
if (auto *MS = dyn_cast<MergeInputSection>(Sec))
- MS->markLiveAt(Offset);
+ MS->getSectionPiece(Offset)->Live = true;
if (Sec->Live)
return;
@@ -279,13 +276,18 @@ template <class ELFT> void elf::markLive() {
// The -gc-sections option works only for SHF_ALLOC sections
// (sections that are memory-mapped at runtime). So we can
- // unconditionally make non-SHF_ALLOC sections alive.
+ // unconditionally make non-SHF_ALLOC sections alive except
+ // SHF_LINK_ORDER and SHT_REL/SHT_RELA sections.
//
- // Non SHF_ALLOC sections are not removed even if they are
+ // Usually, SHF_ALLOC sections are not removed even if they are
// unreachable through relocations because reachability is not
// a good signal whether they are garbage or not (e.g. there is
// usually no section referring to a .comment section, but we
- // want to keep it.)
+ // want to keep it.).
+ //
+ // Note on SHF_LINK_ORDER: Such sections contain metadata and they
+ // have a reverse dependency on the InputSection they are linked with.
+ // We are able to garbage collect them.
//
// Note on SHF_REL{,A}: Such sections reach here only when -r
// or -emit-reloc were given. And they are subject of garbage
@@ -293,8 +295,9 @@ template <class ELFT> void elf::markLive() {
// remove its relocation section.
for (InputSectionBase *Sec : InputSections) {
bool IsAlloc = (Sec->Flags & SHF_ALLOC);
+ bool IsLinkOrder = (Sec->Flags & SHF_LINK_ORDER);
bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA);
- if (!IsAlloc && !IsRel)
+ if (!IsAlloc && !IsLinkOrder && !IsRel)
Sec->Live = true;
}
@@ -305,8 +308,7 @@ template <class ELFT> void elf::markLive() {
if (Config->PrintGcSections)
for (InputSectionBase *Sec : InputSections)
if (!Sec->Live)
- message("removing unused section from '" + Sec->Name + "' in file '" +
- Sec->File->getName() + "'");
+ message("removing unused section " + toString(Sec));
}
template void elf::markLive<ELF32LE>();
diff --git a/contrib/llvm/tools/lld/ELF/MarkLive.h b/contrib/llvm/tools/lld/ELF/MarkLive.h
new file mode 100644
index 000000000000..c9b99add34de
--- /dev/null
+++ b/contrib/llvm/tools/lld/ELF/MarkLive.h
@@ -0,0 +1,21 @@
+//===- MarkLive.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_MARKLIVE_H
+#define LLD_ELF_MARKLIVE_H
+
+namespace lld {
+namespace elf {
+
+template <class ELFT> void markLive();
+
+} // namespace elf
+} // namespace lld
+
+#endif // LLD_ELF_MARKLIVE_H
diff --git a/contrib/llvm/tools/lld/ELF/Options.td b/contrib/llvm/tools/lld/ELF/Options.td
index 20027e90aefd..04a4f8ffbe28 100644
--- a/contrib/llvm/tools/lld/ELF/Options.td
+++ b/contrib/llvm/tools/lld/ELF/Options.td
@@ -4,66 +4,91 @@ include "llvm/Option/OptParser.td"
// two can precede the option name except those that start with 'o'.
class F<string name>: Flag<["--", "-"], name>;
class J<string name>: Joined<["--", "-"], name>;
-class S<string name>: Separate<["--", "-"], name>;
-multiclass Eq<string name> {
- def "": Separate<["--", "-"], name>;
- def _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
+multiclass Eq<string name, string help> {
+ def NAME: Separate<["--", "-"], name>;
+ def NAME # _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>,
+ HelpText<help>;
}
-def auxiliary: S<"auxiliary">, HelpText<"Set DT_AUXILIARY field to the specified name">;
+multiclass B<string name, string help1, string help2> {
+ def NAME: Flag<["--", "-"], name>, HelpText<help1>;
+ def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>;
+}
+
+defm auxiliary: Eq<"auxiliary", "Set DT_AUXILIARY field to the specified name">;
def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind defined symbols locally">;
def Bsymbolic_functions: F<"Bsymbolic-functions">,
HelpText<"Bind defined function symbols locally">;
-def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
+def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries (default)">;
def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
-def build_id: F<"build-id">, HelpText<"Generate build ID note">;
+def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">;
+
+def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">,
+ MetaVarName<"[fast,md5,sha,uuid,0x<hexstring>]">;
-def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">;
+defm check_sections: B<"check-sections",
+ "Check section addresses for overlaps (default)",
+ "Do not check section addresses for overlaps">;
-defm compress_debug_sections : Eq<"compress-debug-sections">,
- HelpText<"Compress DWARF debug sections">;
+defm compress_debug_sections:
+ Eq<"compress-debug-sections", "Compress DWARF debug sections">,
+ MetaVarName<"[none,zlib]">;
-defm defsym: Eq<"defsym">, HelpText<"Define a symbol alias">;
+defm defsym: Eq<"defsym", "Define a symbol alias">, MetaVarName<"<symbol>=<value>">;
-defm library_path: Eq<"library-path">,
- HelpText<"Add a directory to the library search path">, MetaVarName<"<dir>">;
+defm library_path:
+ Eq<"library-path", "Add a directory to the library search path">, MetaVarName<"<dir>">;
def O: JoinedOrSeparate<["-"], "O">, HelpText<"Optimize output file size">;
-defm Tbss: Eq<"Tbss">,
- HelpText<"Same as --section-start with .bss as the sectionname">;
+defm Tbss: Eq<"Tbss", "Same as --section-start with .bss as the sectionname">;
-defm Tdata: Eq<"Tdata">,
- HelpText<"Same as --section-start with .data as the sectionname">;
+defm Tdata: Eq<"Tdata", "Same as --section-start with .data as the sectionname">;
-defm Ttext: Eq<"Ttext">,
- HelpText<"Same as --section-start with .text as the sectionname">;
+defm Ttext: Eq<"Ttext", "Same as --section-start with .text as the sectionname">;
-def allow_multiple_definition: F<"allow-multiple-definition">,
- HelpText<"Allow multiple definitions">;
+defm allow_multiple_definition: B<"allow-multiple-definition",
+ "Allow multiple definitions",
+ "Do not allow multiple definitions (default)">;
-def as_needed: F<"as-needed">,
- HelpText<"Only set DT_NEEDED for shared libraries if used">;
+defm apply_dynamic_relocs: B<"apply-dynamic-relocs",
+ "Apply link-time values for dynamic relocations",
+ "Do not apply link-time values for dynamic relocations (default)">;
+
+defm as_needed: B<"as-needed",
+ "Only set DT_NEEDED for shared libraries if used",
+ "Always set DT_NEEDED for shared libraries (default)">;
+
+defm call_graph_ordering_file:
+ Eq<"call-graph-ordering-file", "Layout sections to optimize the given callgraph">;
// -chroot doesn't have a help text because it is an internal option.
-def chroot: S<"chroot">;
+def chroot: Separate<["--", "-"], "chroot">;
def color_diagnostics: F<"color-diagnostics">,
- HelpText<"Use colors in diagnostics">;
+ HelpText<"Alias for --color-diagnostics=always">;
def color_diagnostics_eq: J<"color-diagnostics=">,
- HelpText<"Use colors in diagnostics">;
+ HelpText<"Use colors in diagnostics">,
+ MetaVarName<"[auto,always,never]">;
+
+defm cref: B<"cref",
+ "Output cross reference table",
+ "Do not output cross reference table">;
-def define_common: F<"define-common">,
- HelpText<"Assign space to common symbols">;
+defm define_common: B<"define-common",
+ "Assign space to common symbols",
+ "Do not assign space to common symbols">;
-def demangle: F<"demangle">, HelpText<"Demangle symbol names">;
+defm demangle: B<"demangle",
+ "Demangle symbol names (default)",
+ "Do not demangle symbol names">;
def disable_new_dtags: F<"disable-new-dtags">,
HelpText<"Disable new dynamic tags">;
@@ -76,158 +101,130 @@ def discard_locals: F<"discard-locals">,
def discard_none: F<"discard-none">,
HelpText<"Keep all symbols in the symbol table">;
-def dynamic_linker: S<"dynamic-linker">,
- HelpText<"Which dynamic linker to use">;
+defm dynamic_linker: Eq<"dynamic-linker", "Which dynamic linker to use">;
-defm dynamic_list: Eq<"dynamic-list">,
- HelpText<"Read a list of dynamic symbols">;
+defm dynamic_list: Eq<"dynamic-list", "Read a list of dynamic symbols">;
-def eh_frame_hdr: F<"eh-frame-hdr">,
- HelpText<"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header">;
+defm eh_frame_hdr: B<"eh-frame-hdr",
+ "Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header",
+ "Do not create .eh_frame_hdr section">;
def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">;
def enable_new_dtags: F<"enable-new-dtags">,
- HelpText<"Enable new dynamic tags">;
+ HelpText<"Enable new dynamic tags (default)">;
+
+def end_group: F<"end-group">,
+ HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">;
def end_lib: F<"end-lib">,
HelpText<"End a grouping of objects that should be treated as if they were together in an archive">;
-defm entry: Eq<"entry">, HelpText<"Name of entry point symbol">,
+defm entry: Eq<"entry", "Name of entry point symbol">,
MetaVarName<"<entry>">;
-defm error_limit: Eq<"error-limit">,
- HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">;
+defm error_limit:
+ Eq<"error-limit", "Maximum number of errors to emit before stopping (0 = no limit)">;
def error_unresolved_symbols: F<"error-unresolved-symbols">,
HelpText<"Report unresolved symbols as errors">;
-defm exclude_libs: Eq<"exclude-libs">,
- HelpText<"Exclude static libraries from automatic export">;
+defm exclude_libs: Eq<"exclude-libs", "Exclude static libraries from automatic export">;
+
+defm execute_only: B<"execute-only",
+ "Do not mark executable sections readable",
+ "Mark executable sections readable (default)">;
-def export_dynamic: F<"export-dynamic">,
- HelpText<"Put symbols in the dynamic symbol table">;
+defm export_dynamic: B<"export-dynamic",
+ "Put symbols in the dynamic symbol table",
+ "Do not put symbols in the dynamic symbol table (default)">;
-defm export_dynamic_symbol: Eq<"export-dynamic-symbol">,
- HelpText<"Put a symbol in the dynamic symbol table">;
+defm export_dynamic_symbol:
+ Eq<"export-dynamic-symbol", "Put a symbol in the dynamic symbol table">;
-def fatal_warnings: F<"fatal-warnings">,
- HelpText<"Treat warnings as errors">;
+defm fatal_warnings: B<"fatal-warnings",
+ "Treat warnings as errors",
+ "Do not treat warnings as errors (default)">;
-defm filter: Eq<"filter">,
- HelpText<"Set DT_FILTER field to the specified name">;
+defm filter: Eq<"filter", "Set DT_FILTER field to the specified name">;
-defm fini: Eq<"fini">,
- HelpText<"Specify a finalizer function">, MetaVarName<"<symbol>">;
+defm fini: Eq<"fini", "Specify a finalizer function">, MetaVarName<"<symbol>">;
def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">,
HelpText<"Apply fixes for AArch64 Cortex-A53 erratum 843419">;
-def full_shutdown : F<"full-shutdown">,
- HelpText<"Perform a full shutdown instead of calling _exit">;
+defm format: Eq<"format", "Change the input format of the inputs following this option">,
+ MetaVarName<"[default,elf,binary]">;
-defm format: Eq<"format">,
- HelpText<"Change the input format of the inputs following this option">,
- MetaVarName<"<input-format>">;
+defm gc_sections: B<"gc-sections",
+ "Enable garbage collection of unused sections",
+ "Disable garbage collection of unused sections (default)">;
-def gc_sections: F<"gc-sections">,
- HelpText<"Enable garbage collection of unused sections">;
+defm gdb_index: B<"gdb-index",
+ "Generate .gdb_index section",
+ "Do not generate .gdb_index section (default)">;
-def gdb_index: F<"gdb-index">,
- HelpText<"Generate .gdb_index section">;
+defm gnu_unique: B<"gnu-unique",
+ "Enable STB_GNU_UNIQUE symbol binding (default)",
+ "Disable STB_GNU_UNIQUE symbol binding">;
-defm hash_style: Eq<"hash-style">,
- HelpText<"Specify hash style (sysv, gnu or both)">;
+defm hash_style: Eq<"hash-style", "Specify hash style (sysv, gnu or both)">;
def help: F<"help">, HelpText<"Print option help">;
def icf_all: F<"icf=all">, HelpText<"Enable identical code folding">;
-def icf_data: F<"icf-data">,
- HelpText<"Enable ICF to also fold identical read only data">;
+def icf_safe: F<"icf=safe">, HelpText<"Enable safe identical code folding">;
+
+def icf_none: F<"icf=none">, HelpText<"Disable identical code folding (default)">;
-def icf_none: F<"icf=none">, HelpText<"Disable identical code folding">;
+def ignore_function_address_equality: F<"ignore-function-address-equality">,
+ HelpText<"lld can break the address equality of functions">;
-defm image_base : Eq<"image-base">, HelpText<"Set the base address">;
+def ignore_data_address_equality: F<"ignore-data-address-equality">,
+ HelpText<"lld can break the address equality of data">;
-defm init: Eq<"init">, HelpText<"Specify an initializer function">,
+defm image_base: Eq<"image-base", "Set the base address">;
+
+defm init: Eq<"init", "Specify an initializer function">,
MetaVarName<"<symbol>">;
-defm library: Eq<"library">, HelpText<"Root name of library to use">,
- MetaVarName<"<libName>">;
+defm just_symbols: Eq<"just-symbols", "Just link symbols">;
-def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,
- HelpText<"Optimization level for LTO">;
+defm keep_unique: Eq<"keep-unique", "Do not fold this symbol during ICF">;
+
+defm library: Eq<"library", "Root name of library to use">,
+ MetaVarName<"<libName>">;
def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
-defm Map: Eq<"Map">, HelpText<"Print a link map to the specified file">;
+defm Map: Eq<"Map", "Print a link map to the specified file">;
-def merge_exidx_entries: F<"merge-exidx-entries">,
- HelpText<"Enable merging .ARM.exidx entries">;
+defm merge_exidx_entries: B<"merge-exidx-entries",
+ "Enable merging .ARM.exidx entries (default)",
+ "Disable merging .ARM.exidx entries">;
def nostdlib: F<"nostdlib">,
HelpText<"Only search directories specified on the command line">;
-def no_as_needed: F<"no-as-needed">,
- HelpText<"Always DT_NEEDED for shared libraries">;
-
def no_color_diagnostics: F<"no-color-diagnostics">,
HelpText<"Do not use colors in diagnostics">;
-def no_define_common: F<"no-define-common">,
- HelpText<"Do not assign space to common symbols">;
-
-def no_demangle: F<"no-demangle">,
- HelpText<"Do not demangle symbol names">;
-
def no_dynamic_linker: F<"no-dynamic-linker">,
HelpText<"Inhibit output of .interp section">;
-def no_eh_frame_hdr: F<"no-eh-frame-hdr">,
- HelpText<"Do not create .eh_frame_hdr section">;
-
-def no_export_dynamic: F<"no-export-dynamic">;
-def no_fatal_warnings: F<"no-fatal-warnings">;
-
-def no_gc_sections: F<"no-gc-sections">,
- HelpText<"Disable garbage collection of unused sections">;
-
-def no_gdb_index: F<"no-gdb-index">,
- HelpText<"Do not generate .gdb_index section">;
-
-def no_gnu_unique: F<"no-gnu-unique">,
- HelpText<"Disable STB_GNU_UNIQUE symbol binding">;
-
-def no_merge_exidx_entries: F<"no-merge-exidx-entries">,
- HelpText<"Disable merging .ARM.exidx entries">;
-
-def no_threads: F<"no-threads">,
- HelpText<"Do not run the linker multi-threaded">;
-
-def no_whole_archive: F<"no-whole-archive">,
- HelpText<"Restores the default behavior of loading archive members">;
-
def noinhibit_exec: F<"noinhibit-exec">,
HelpText<"Retain the executable output file whenever it is still usable">;
-def nopie: F<"nopie">, HelpText<"Do not create a position independent executable">;
-
-def no_omagic: Flag<["--"], "no-omagic">, MetaVarName<"<magic>">,
+def no_omagic: F<"no-omagic">, MetaVarName<"<magic>">,
HelpText<"Do not set the text data sections to be writable">;
-def no_print_gc_sections: F<"no-print-gc-sections">,
- HelpText<"Do not list removed unused sections">;
-
def no_rosegment: F<"no-rosegment">,
HelpText<"Do not put read-only non-executable sections in their own segment">;
def no_undefined: F<"no-undefined">,
HelpText<"Report unresolved symbols even if the linker is creating a shared library">;
-def no_undefined_version: F<"no-undefined-version">,
- HelpText<"Report version scripts that refer undefined symbols">;
-
def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
HelpText<"Path to file to write output">;
@@ -237,42 +234,62 @@ def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">,
HelpText<"Set the text and data sections to be readable and writable">;
-defm orphan_handling: Eq<"orphan-handling">,
- HelpText<"Control how orphan sections are handled when linker script used">;
+defm orphan_handling:
+ Eq<"orphan-handling", "Control how orphan sections are handled when linker script used">;
+
+defm pack_dyn_relocs:
+ Eq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,
+ MetaVarName<"[none,android,relr,android+relr]">;
+
+defm use_android_relr_tags: B<"use-android-relr-tags",
+ "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
+ "Use SHT_RELR / DT_RELR* tags (default)">;
+
+defm pie: B<"pie",
+ "Create a position independent executable",
+ "Do not create a position independent executable (default)">;
+
+defm print_gc_sections: B<"print-gc-sections",
+ "List removed unused sections",
+ "Do not list removed unused sections (default)">;
-def pack_dyn_relocs_eq: J<"pack-dyn-relocs=">, MetaVarName<"<format>">,
- HelpText<"Pack dynamic relocations in the given format (none or android)">;
+defm print_icf_sections: B<"print-icf-sections",
+ "List identical folded sections",
+ "Do not list identical folded sections (default)">;
-def pie: F<"pie">, HelpText<"Create a position independent executable">;
+def pop_state: F<"pop-state">,
+ HelpText<"Undo the effect of -push-state">;
-def print_gc_sections: F<"print-gc-sections">,
- HelpText<"List removed unused sections">;
+def push_state: F<"push-state">,
+ HelpText<"Save the current state of -as-needed, -static and -whole-archive">;
def print_map: F<"print-map">,
HelpText<"Print a link map to the standard output">;
-defm reproduce: Eq<"reproduce">,
- HelpText<"Dump linker invocation and input files for debugging">;
+defm reproduce: Eq<"reproduce", "Dump linker invocation and input files for debugging">;
-defm rpath: Eq<"rpath">, HelpText<"Add a DT_RUNPATH to the output">;
+defm rpath: Eq<"rpath", "Add a DT_RUNPATH to the output">;
def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;
-defm retain_symbols_file: Eq<"retain-symbols-file">,
- HelpText<"Retain only the symbols listed in the file">,
+defm retain_symbols_file:
+ Eq<"retain-symbols-file", "Retain only the symbols listed in the file">,
MetaVarName<"<file>">;
-defm script: Eq<"script">, HelpText<"Read linker script">;
+defm script: Eq<"script", "Read linker script">;
-def section_start: S<"section-start">, MetaVarName<"<address>">,
- HelpText<"Set address of section">;
+defm section_start: Eq<"section-start", "Set address of section">,
+ MetaVarName<"<address>">;
def shared: F<"shared">, HelpText<"Build a shared object">;
-defm soname: Eq<"soname">, HelpText<"Set DT_SONAME">;
+defm soname: Eq<"soname", "Set DT_SONAME">;
-defm sort_section: Eq<"sort-section">,
- HelpText<"Specifies sections sorting rule when linkerscript is used">;
+defm sort_section:
+ Eq<"sort-section", "Specifies sections sorting rule when linkerscript is used">;
+
+def start_group: F<"start-group">,
+ HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">;
def start_lib: F<"start-lib">,
HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">;
@@ -281,33 +298,39 @@ def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;
def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
-def symbol_ordering_file: S<"symbol-ordering-file">,
- HelpText<"Layout sections in the order specified by symbol file">;
+defm symbol_ordering_file:
+ Eq<"symbol-ordering-file", "Layout sections to place symbols in the order specified by symbol ordering file">;
-defm sysroot: Eq<"sysroot">, HelpText<"Set the system root">;
+defm sysroot: Eq<"sysroot", "Set the system root">;
def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">;
-def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">;
+def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32 (default)">;
-defm target2: Eq<"target2">,
- HelpText<"Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel">,
+defm target2:
+ Eq<"target2", "Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel">,
MetaVarName<"<type>">;
-def threads: F<"threads">, HelpText<"Run the linker multi-threaded">;
+defm threads: B<"threads",
+ "Run the linker multi-threaded (default)",
+ "Do not run the linker multi-threaded">;
def trace: F<"trace">, HelpText<"Print the names of the input files">;
-defm trace_symbol : Eq<"trace-symbol">, HelpText<"Trace references to symbols">;
+defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">;
+
+defm undefined: Eq<"undefined", "Force undefined symbol during linking">,
+ MetaVarName<"<symbol>">;
-defm undefined: Eq<"undefined">,
- HelpText<"Force undefined symbol during linking">;
+defm unresolved_symbols:
+ Eq<"unresolved-symbols", "Determine how to handle unresolved symbols">;
-defm unresolved_symbols: Eq<"unresolved-symbols">,
- HelpText<"Determine how to handle unresolved symbols">;
+defm undefined_version: B<"undefined-version",
+ "Allow unused version in version script (default)",
+ "Report version scripts that refer undefined symbols">;
-defm rsp_quoting: Eq<"rsp-quoting">,
- HelpText<"Quoting style for response files. Values supported: windows|posix">;
+defm rsp_quoting: Eq<"rsp-quoting", "Quoting style for response files">,
+ MetaVarName<"[posix,windows]">;
def v: Flag<["-"], "v">, HelpText<"Display the version number">;
@@ -315,91 +338,123 @@ def verbose: F<"verbose">, HelpText<"Verbose mode">;
def version: F<"version">, HelpText<"Display the version number and exit">;
-defm version_script: Eq<"version-script">, HelpText<"Read a version script">;
+defm version_script: Eq<"version-script", "Read a version script">;
+
+defm warn_backrefs: B<"warn-backrefs",
+ "Warn about backward symbol references to fetch archive members",
+ "Do not warn about backward symbol references to fetch archive members (default)">;
+
+defm warn_common: B<"warn-common",
+ "Warn about duplicate common symbols",
+ "Do not warn about duplicate common symbols (default)">;
-def warn_common: F<"warn-common">,
- HelpText<"Warn about duplicate common symbols">;
+defm warn_symbol_ordering: B<"warn-symbol-ordering",
+ "Warn about problems with the symbol ordering file (default)",
+ "Do not warn about problems with the symbol ordering file">;
def warn_unresolved_symbols: F<"warn-unresolved-symbols">,
HelpText<"Report unresolved symbols as warnings">;
-def whole_archive: F<"whole-archive">,
- HelpText<"Force load of all members in a static library">;
+defm whole_archive: B<"whole-archive",
+ "Force load of all members in a static library",
+ "Do not force load of all members in a static library (default)">;
-defm wrap: Eq<"wrap">, HelpText<"Use wrapper functions for symbol">,
- MetaVarName<"<symbol>">;
+defm wrap: Eq<"wrap", "Use wrapper functions for symbol">,
+ MetaVarName<"<symbol>=<symbol>">;
def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
HelpText<"Linker option extensions">;
// Aliases
-def alias_auxiliary: Separate<["-"], "f">, Alias<auxiliary>;
-def alias_Bdynamic_call_shared: F<"call_shared">, Alias<Bdynamic>;
-def alias_Bdynamic_dy: F<"dy">, Alias<Bdynamic>;
-def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>;
-def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>;
-def alias_Bstatic_static: F<"static">, Alias<Bstatic>;
-def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>;
-def alias_define_common_dc: F<"dc">, Alias<define_common>;
-def alias_define_common_dp: F<"dp">, Alias<define_common>;
-def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
-def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
-def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>;
-def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
-def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
-def alias_filter: Separate<["-"], "F">, Alias<filter>;
-def alias_format_b: S<"b">, Alias<format>;
-def alias_library: JoinedOrSeparate<["-"], "l">, Alias<library>;
-def alias_library_path: JoinedOrSeparate<["-"], "L">, Alias<library_path>;
-def alias_omagic: Flag<["-"], "N">, Alias<omagic>;
-def alias_o_output: Joined<["--"], "output=">, Alias<o>;
-def alias_o_output2 : Separate<["--"], "output">, Alias<o>;
-def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>;
-def alias_print_map_M: Flag<["-"], "M">, Alias<print_map>;
-def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>;
-def alias_rpath_R: JoinedOrSeparate<["-"], "R">, Alias<rpath>;
-def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias<script>;
-def alias_shared_Bshareable: F<"Bshareable">, Alias<shared>;
-def alias_soname_h: JoinedOrSeparate<["-"], "h">, Alias<soname>;
-def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>;
-def alias_strip_debug_S: Flag<["-"], "S">, Alias<strip_debug>;
-def alias_trace: Flag<["-"], "t">, Alias<trace>;
-def alias_trace_symbol_y : JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>;
-def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>;
-def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>;
-def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
-def alias_version_V: Flag<["-"], "V">, Alias<version>;
-
-// Our symbol resolution algorithm handles symbols in archive files differently
-// than traditional linkers, so we don't need --start-group and --end-group.
-// These options are recongized for compatibility but ignored.
-def end_group: F<"end-group">;
-def end_group_paren: Flag<["-"], ")">;
-def start_group: F<"start-group">;
-def start_group_paren: Flag<["-"], "(">;
+def: Separate<["-"], "f">, Alias<auxiliary>, HelpText<"Alias for --auxiliary">;
+def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
+def: F<"dy">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
+def: F<"dn">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
+def: F<"non_shared">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
+def: F<"static">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
+def: Flag<["-"], "d">, Alias<define_common>, HelpText<"Alias for --define-common">;
+def: F<"dc">, Alias<define_common>, HelpText<"Alias for --define-common">;
+def: F<"dp">, Alias<define_common>, HelpText<"Alias for --define-common">;
+def: Flag<["-"], "x">, Alias<discard_all>, HelpText<"Alias for --discard-all">;
+def: Flag<["-"], "X">, Alias<discard_locals>, HelpText<"Alias for --discard-locals">;
+def: Flag<["-"], "q">, Alias<emit_relocs>, HelpText<"Alias for --emit-relocs">;
+def: Flag<["-"], ")">, Alias<end_group>, HelpText<"Alias for --end-group">;
+def: JoinedOrSeparate<["-"], "e">, Alias<entry>, HelpText<"Alias for --entry">;
+def: Flag<["-"], "E">, Alias<export_dynamic>, HelpText<"Alias for --export-dynamic">;
+def: Separate<["-"], "F">, Alias<filter>, HelpText<"Alias for --filter">;
+def: Separate<["-"], "b">, Alias<format>, HelpText<"Alias for --format">;
+def: JoinedOrSeparate<["-"], "l">, Alias<library>, HelpText<"Alias for --library">;
+def: JoinedOrSeparate<["-"], "L">, Alias<library_path>, HelpText<"Alias for --library-path">;
+def: F<"no-pic-executable">, Alias<no_pie>, HelpText<"Alias for --no-pie">;
+def: Flag<["-"], "N">, Alias<omagic>, HelpText<"Alias for --omagic">;
+def: Joined<["--"], "output=">, Alias<o>, HelpText<"Alias for -o">;
+def: Separate<["--"], "output">, Alias<o>, HelpText<"Alias for -o">;
+def: F<"pic-executable">, Alias<pie>, HelpText<"Alias for --pie">;
+def: Flag<["-"], "M">, Alias<print_map>, HelpText<"Alias for --print-map">;
+def: Flag<["-"], "r">, Alias<relocatable>, HelpText<"Alias for --relocatable">;
+def: JoinedOrSeparate<["-"], "R">, Alias<rpath>, HelpText<"Alias for --rpath">;
+def: JoinedOrSeparate<["-"], "T">, Alias<script>, HelpText<"Alias for --script">;
+def: F<"Bshareable">, Alias<shared>, HelpText<"Alias for --shared">;
+def: JoinedOrSeparate<["-"], "h">, Alias<soname>, HelpText<"Alias for --soname">;
+def: Flag<["-"], "(">, Alias<start_group>, HelpText<"Alias for --start-group">;
+def: Flag<["-"], "s">, Alias<strip_all>, HelpText<"Alias for --strip-all">;
+def: Flag<["-"], "S">, Alias<strip_debug>, HelpText<"Alias for --strip-debug">;
+def: Flag<["-"], "t">, Alias<trace>, HelpText<"Alias for --trace">;
+def: JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>, HelpText<"Alias for --trace-symbol">;
+def: Separate<["-", "--"], "Ttext-segment">, Alias<Ttext>, HelpText<"Alias for --Ttext">;
+def: Joined<["-", "--"], "Ttext-segment=">, Alias<Ttext>, HelpText<"Alias for --Ttext">;
+def: JoinedOrSeparate<["-"], "u">, Alias<undefined>, HelpText<"Alias for --undefined">;
+def: Flag<["-"], "V">, Alias<version>, HelpText<"Alias for --version">;
// LTO-related options.
def lto_aa_pipeline: J<"lto-aa-pipeline=">,
HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
+def lto_debug_pass_manager: F<"lto-debug-pass-manager">,
+ HelpText<"Debug new pass manager">;
+def lto_new_pass_manager: F<"lto-new-pass-manager">,
+ HelpText<"Use new pass manager">;
def lto_newpm_passes: J<"lto-newpm-passes=">,
HelpText<"Passes to run during LTO">;
+def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,
+ HelpText<"Optimization level for LTO">;
def lto_partitions: J<"lto-partitions=">,
HelpText<"Number of LTO codegen partitions">;
+def lto_sample_profile: J<"lto-sample-profile=">,
+ HelpText<"Sample profile file path">;
def disable_verify: F<"disable-verify">;
-def mllvm: S<"mllvm">;
+defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">;
def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">,
HelpText<"YAML output file for optimization remarks">;
def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">,
- HelpText<"Include hotness informations in the optimization remarks file">;
-defm plugin_opt: Eq<"plugin-opt">,
- HelpText<"specifies LTO options for compatibility with GNU linkers">;
+ HelpText<"Include hotness information in the optimization remarks file">;
+defm plugin_opt: Eq<"plugin-opt", "specifies LTO options for compatibility with GNU linkers">;
def save_temps: F<"save-temps">;
def thinlto_cache_dir: J<"thinlto-cache-dir=">,
HelpText<"Path to ThinLTO cached object file directory">;
-def thinlto_cache_policy: S<"thinlto-cache-policy">,
- HelpText<"Pruning policy for the ThinLTO cache">;
+defm thinlto_cache_policy: Eq<"thinlto-cache-policy", "Pruning policy for the ThinLTO cache">;
def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">;
+def: J<"plugin-opt=O">, Alias<lto_O>, HelpText<"Alias for -lto-O">;
+def: F<"plugin-opt=debug-pass-manager">,
+ Alias<lto_debug_pass_manager>, HelpText<"Alias for -lto-debug-pass-manager">;
+def: F<"plugin-opt=disable-verify">, Alias<disable_verify>, HelpText<"Alias for -disable-verify">;
+def plugin_opt_dwo_dir_eq: J<"plugin-opt=dwo_dir=">,
+ HelpText<"Directory to store .dwo files when LTO and debug fission are used">;
+def: J<"plugin-opt=jobs=">, Alias<thinlto_jobs>, HelpText<"Alias for -thinlto-jobs">;
+def: J<"plugin-opt=lto-partitions=">, Alias<lto_partitions>, HelpText<"Alias for -lto-partitions">;
+def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">;
+def: F<"plugin-opt=new-pass-manager">,
+ Alias<lto_new_pass_manager>, HelpText<"Alias for -lto-new-pass-manager">;
+def plugin_opt_obj_path_eq: J<"plugin-opt=obj-path=">;
+def: J<"plugin-opt=sample-profile=">,
+ Alias<lto_sample_profile>, HelpText<"Alias for -lto-sample-profile">;
+def: F<"plugin-opt=save-temps">, Alias<save_temps>, HelpText<"Alias for -save-temps">;
+def plugin_opt_thinlto_emit_imports_files: F<"plugin-opt=thinlto-emit-imports-files">;
+def plugin_opt_thinlto_index_only: F<"plugin-opt=thinlto-index-only">;
+def plugin_opt_thinlto_index_only_eq: J<"plugin-opt=thinlto-index-only=">;
+def plugin_opt_thinlto_object_suffix_replace_eq: J<"plugin-opt=thinlto-object-suffix-replace=">;
+def plugin_opt_thinlto_prefix_replace_eq: J<"plugin-opt=thinlto-prefix-replace=">;
+
// Ignore LTO plugin-related options.
// clang -flto passes -plugin and -plugin-opt to the linker. This is required
// for ld.gold and ld.bfd to get LTO working. But it's not for lld which doesn't
@@ -407,31 +462,38 @@ def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">;
// just ignore the option on lld side as it's easier. In fact, the linker could
// be called 'ld' and understanding which linker is used would require parsing of
// --version output.
-def plugin: S<"plugin">;
-def plugin_eq: J<"plugin=">;
+defm plugin: Eq<"plugin", "Ignored for compatibility with GNU linkers">;
+
+def plugin_opt_fresolution_eq: J<"plugin-opt=-fresolution=">;
+def plugin_opt_pass_through_eq: J<"plugin-opt=-pass-through=">;
+def plugin_opt_thinlto: J<"plugin-opt=thinlto">;
+def plugin_opt_slash: J<"plugin-opt=/">;
// Options listed below are silently ignored for now for compatibility.
-def allow_shlib_undefined: F<"allow-shlib-undefined">;
-def cref: F<"cref">;
-def detect_odr_violations: F<"detect-odr-violations">;
-def g: Flag<["-"], "g">;
-def long_plt: F<"long-plt">;
-def no_add_needed: F<"no-add-needed">;
-def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">;
-def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">;
-def no_ctors_in_init_array: F<"no-ctors-in-init-array">;
-def no_keep_memory: F<"no-keep-memory">;
-def no_mmap_output_file: F<"no-mmap-output-file">;
-def no_warn_common: F<"no-warn-common">;
-def no_warn_mismatch: F<"no-warn-mismatch">;
-def rpath_link: S<"rpath-link">;
-def rpath_link_eq: J<"rpath-link=">;
-def sort_common: F<"sort-common">;
-def stats: F<"stats">;
-def warn_execstack: F<"warn-execstack">;
-def warn_once: F<"warn-once">;
-def warn_shared_textrel: F<"warn-shared-textrel">;
-def EB : F<"EB">;
-def EL : F<"EL">;
-def G: JoinedOrSeparate<["-"], "G">;
-def Qy : F<"Qy">;
+def: F<"allow-shlib-undefined">;
+def: F<"detect-odr-violations">;
+def: Flag<["-"], "g">;
+def: F<"long-plt">;
+def: F<"no-add-needed">;
+def: F<"no-allow-shlib-undefined">;
+def: F<"no-copy-dt-needed-entries">;
+def: F<"no-ctors-in-init-array">;
+def: F<"no-keep-memory">;
+def: F<"no-mmap-output-file">;
+def: F<"no-warn-mismatch">;
+def: Separate<["--", "-"], "rpath-link">;
+def: J<"rpath-link=">;
+def: F<"sort-common">;
+def: F<"stats">;
+def: F<"warn-execstack">;
+def: F<"warn-once">;
+def: F<"warn-shared-textrel">;
+def: F<"EB">;
+def: F<"EL">;
+def: JoinedOrSeparate<["-"], "G">;
+def: F<"Qy">;
+
+// Hidden option used for testing MIPS multi-GOT implementation.
+defm mips_got_size:
+ Eq<"mips-got-size", "Max size of a single MIPS GOT. 0x10000 by default.">,
+ Flags<[HelpHidden]>;
diff --git a/contrib/llvm/tools/lld/ELF/OutputSections.cpp b/contrib/llvm/tools/lld/ELF/OutputSections.cpp
index 94c98284196f..8253b18b486c 100644
--- a/contrib/llvm/tools/lld/ELF/OutputSections.cpp
+++ b/contrib/llvm/tools/lld/ELF/OutputSections.cpp
@@ -10,11 +10,11 @@
#include "OutputSections.h"
#include "Config.h"
#include "LinkerScript.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/Compression.h"
@@ -25,15 +25,12 @@
using namespace llvm;
using namespace llvm::dwarf;
using namespace llvm::object;
-using namespace llvm::support::endian;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
uint8_t Out::First;
-OutputSection *Out::Opd;
-uint8_t *Out::OpdBuf;
PhdrEntry *Out::TlsPhdr;
OutputSection *Out::DebugInfo;
OutputSection *Out::ElfHeader;
@@ -45,7 +42,9 @@ OutputSection *Out::FiniArray;
std::vector<OutputSection *> elf::OutputSections;
uint32_t OutputSection::getPhdrFlags() const {
- uint32_t Ret = PF_R;
+ uint32_t Ret = 0;
+ if (Config->EMachine != EM_ARM || !(Flags & SHF_ARM_PURECODE))
+ Ret |= PF_R;
if (Flags & SHF_WRITE)
Ret |= PF_W;
if (Flags & SHF_EXECINSTR)
@@ -70,9 +69,7 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) {
OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
: BaseCommand(OutputSectionKind),
SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
- /*Info*/ 0,
- /*Link*/ 0),
- SectionIndex(INT_MAX) {
+ /*Info*/ 0, /*Link*/ 0) {
Live = false;
}
@@ -91,13 +88,15 @@ static bool canMergeToProgbits(unsigned Type) {
void OutputSection::addSection(InputSection *IS) {
if (!Live) {
// If IS is the first section to be added to this section,
- // initialize Type and Entsize from IS.
+ // initialize Type, Entsize and flags from IS.
Live = true;
Type = IS->Type;
Entsize = IS->Entsize;
+ Flags = IS->Flags;
} else {
// Otherwise, check if new type or flags are compatible with existing ones.
- if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS)))
+ unsigned Mask = SHF_ALLOC | SHF_TLS | SHF_LINK_ORDER;
+ if ((Flags & Mask) != (IS->Flags & Mask))
error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
": 0x" + utohexstr(Flags));
@@ -114,9 +113,14 @@ void OutputSection::addSection(InputSection *IS) {
}
IS->Parent = this;
- Flags |= IS->Flags;
+ uint64_t AndMask =
+ Config->EMachine == EM_ARM ? (uint64_t)SHF_ARM_PURECODE : 0;
+ uint64_t OrMask = ~AndMask;
+ uint64_t AndFlags = (Flags & IS->Flags) & AndMask;
+ uint64_t OrFlags = (Flags | IS->Flags) & OrMask;
+ Flags = AndFlags | OrFlags;
+
Alignment = std::max(Alignment, IS->Alignment);
- IS->OutSecOff = Size++;
// If this section contains a table of fixed-size entries, sh_entsize
// holds the element size. If it contains elements of different size we
@@ -134,8 +138,8 @@ void OutputSection::addSection(InputSection *IS) {
}
}
-void elf::sortByOrder(MutableArrayRef<InputSection *> In,
- std::function<int(InputSectionBase *S)> Order) {
+static void sortByOrder(MutableArrayRef<InputSection *> In,
+ llvm::function_ref<int(InputSectionBase *S)> Order) {
typedef std::pair<int, InputSection *> Pair;
auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
@@ -158,11 +162,11 @@ bool OutputSection::classof(const BaseCommand *C) {
return C->Kind == OutputSectionKind;
}
-void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) {
+void OutputSection::sort(llvm::function_ref<int(InputSectionBase *S)> Order) {
assert(Live);
- assert(SectionCommands.size() == 1);
- sortByOrder(cast<InputSectionDescription>(SectionCommands[0])->Sections,
- Order);
+ for (BaseCommand *B : SectionCommands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(B))
+ sortByOrder(ISD->Sections, Order);
}
// Fill [Buf, Buf + Size) with Filler.
@@ -205,11 +209,11 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
if (Size == 1)
*Buf = Data;
else if (Size == 2)
- write16(Buf, Data, Config->Endianness);
+ write16(Buf, Data);
else if (Size == 4)
- write32(Buf, Data, Config->Endianness);
+ write32(Buf, Data);
else if (Size == 8)
- write64(Buf, Data, Config->Endianness);
+ write64(Buf, Data);
else
llvm_unreachable("unsupported Size argument");
}
@@ -231,12 +235,7 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
}
// Write leading padding.
- std::vector<InputSection *> Sections;
- for (BaseCommand *Cmd : SectionCommands)
- if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
- for (InputSection *IS : ISD->Sections)
- if (IS->Live)
- Sections.push_back(IS);
+ std::vector<InputSection *> Sections = getInputSections(this);
uint32_t Filler = getFiller();
if (Filler)
fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);
@@ -281,17 +280,13 @@ static void finalizeShtGroup(OutputSection *OS,
}
template <class ELFT> void OutputSection::finalize() {
- InputSection *First = nullptr;
- for (BaseCommand *Base : SectionCommands) {
- if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {
- if (ISD->Sections.empty())
- continue;
- if (First == nullptr)
- First = ISD->Sections.front();
- }
- if (isa<ByteCommand>(Base) && Type == SHT_NOBITS)
- Type = SHT_PROGBITS;
- }
+ if (Type == SHT_NOBITS)
+ for (BaseCommand *Base : SectionCommands)
+ if (isa<ByteCommand>(Base))
+ Type = SHT_PROGBITS;
+
+ std::vector<InputSection *> V = getInputSections(this);
+ InputSection *First = V.empty() ? nullptr : V[0];
if (Flags & SHF_LINK_ORDER) {
// We must preserve the link order dependency of sections with the
@@ -367,8 +362,6 @@ static bool compCtors(const InputSection *A, const InputSection *B) {
assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
X = X.substr(6);
Y = Y.substr(6);
- if (X.empty() && Y.empty())
- return false;
return X < Y;
}
@@ -394,6 +387,14 @@ int elf::getPriority(StringRef S) {
return V;
}
+std::vector<InputSection *> elf::getInputSections(OutputSection *OS) {
+ std::vector<InputSection *> Ret;
+ for (BaseCommand *Base : OS->SectionCommands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
+ Ret.insert(Ret.end(), ISD->Sections.begin(), ISD->Sections.end());
+ return Ret;
+}
+
// Sorts input sections by section name suffixes, so that .foo.N comes
// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
// We want to keep the original order if the priorities are the same
diff --git a/contrib/llvm/tools/lld/ELF/OutputSections.h b/contrib/llvm/tools/lld/ELF/OutputSections.h
index c006eae0c04b..efb6aabe9743 100644
--- a/contrib/llvm/tools/lld/ELF/OutputSections.h
+++ b/contrib/llvm/tools/lld/ELF/OutputSections.h
@@ -14,7 +14,6 @@
#include "InputSection.h"
#include "LinkerScript.h"
#include "Relocations.h"
-
#include "lld/Common/LLVM.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELF.h"
@@ -52,7 +51,7 @@ public:
uint64_t getLMA() const { return PtLoad ? Addr + PtLoad->LMAOffset : Addr; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
- unsigned SectionIndex;
+ uint32_t SectionIndex = UINT32_MAX;
unsigned SortRank;
uint32_t getPhdrFlags() const;
@@ -100,13 +99,16 @@ public:
std::string Location;
std::string MemoryRegionName;
std::string LMARegionName;
+ bool NonAlloc = false;
bool Noload = false;
+ bool ExpressionsUseSymbols = false;
+ bool InOverlay = false;
template <class ELFT> void finalize();
template <class ELFT> void writeTo(uint8_t *Buf);
template <class ELFT> void maybeCompress();
- void sort(std::function<int(InputSectionBase *S)> Order);
+ void sort(llvm::function_ref<int(InputSectionBase *S)> Order);
void sortInitFini();
void sortCtorsDtors();
@@ -120,13 +122,13 @@ private:
int getPriority(StringRef S);
+std::vector<InputSection *> getInputSections(OutputSection* OS);
+
// All output sections that are handled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
struct Out {
static uint8_t First;
- static OutputSection *Opd;
- static uint8_t *OpdBuf;
static PhdrEntry *TlsPhdr;
static OutputSection *DebugInfo;
static OutputSection *ElfHeader;
@@ -143,8 +145,6 @@ namespace lld {
namespace elf {
uint64_t getHeaderSize();
-void sortByOrder(llvm::MutableArrayRef<InputSection *> In,
- std::function<int(InputSectionBase *S)> Order);
extern std::vector<OutputSection *> OutputSections;
} // namespace elf
diff --git a/contrib/llvm/tools/lld/ELF/Relocations.cpp b/contrib/llvm/tools/lld/ELF/Relocations.cpp
index d8dd895ecec8..5d7896a1b632 100644
--- a/contrib/llvm/tools/lld/ELF/Relocations.cpp
+++ b/contrib/llvm/tools/lld/ELF/Relocations.cpp
@@ -45,14 +45,14 @@
#include "Config.h"
#include "LinkerScript.h"
#include "OutputSections.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
#include "lld/Common/Memory.h"
-
+#include "lld/Common/Strings.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -80,55 +80,22 @@ static std::string getLocation(InputSectionBase &S, const Symbol &Sym,
return Msg + S.getObjMsg(Off);
}
-// This is a MIPS-specific rule.
-//
-// In case of MIPS GP-relative relocations always resolve to a definition
-// in a regular input file, ignoring the one-definition rule. So we,
-// for example, should not attempt to create a dynamic relocation even
-// if the target symbol is preemptible. There are two two MIPS GP-relative
-// relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16
-// can be against a preemptible symbol.
-//
-// To get MIPS relocation type we apply 0xff mask. In case of O32 ABI all
-// relocation types occupy eight bit. In case of N64 ABI we extract first
-// relocation from 3-in-1 packet because only the first relocation can
-// be against a real symbol.
-static bool isMipsGprel(RelType Type) {
- if (Config->EMachine != EM_MIPS)
- return false;
- Type &= 0xff;
- return Type == R_MIPS_GPREL16 || Type == R_MICROMIPS_GPREL16 ||
- Type == R_MICROMIPS_GPREL7_S2;
-}
-
// This function is similar to the `handleTlsRelocation`. MIPS does not
// support any relaxations for TLS relocations so by factoring out MIPS
// handling in to the separate function we can simplify the code and do not
// pollute other `handleTlsRelocation` by MIPS `ifs` statements.
// Mips has a custom MipsGotSection that handles the writing of GOT entries
// without dynamic relocations.
-template <class ELFT>
static unsigned handleMipsTlsRelocation(RelType Type, Symbol &Sym,
InputSectionBase &C, uint64_t Offset,
int64_t Addend, RelExpr Expr) {
if (Expr == R_MIPS_TLSLD) {
- if (InX::MipsGot->addTlsIndex() && Config->Pic)
- InX::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::MipsGot,
- InX::MipsGot->getTlsIndexOff(), false, nullptr,
- 0});
+ InX::MipsGot->addTlsIndex(*C.File);
C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
return 1;
}
-
if (Expr == R_MIPS_TLSGD) {
- if (InX::MipsGot->addDynTlsEntry(Sym) && Sym.IsPreemptible) {
- uint64_t Off = InX::MipsGot->getGlobalDynOffset(Sym);
- InX::RelaDyn->addReloc(
- {Target->TlsModuleIndexRel, InX::MipsGot, Off, false, &Sym, 0});
- if (Sym.IsPreemptible)
- InX::RelaDyn->addReloc({Target->TlsOffsetRel, InX::MipsGot,
- Off + Config->Wordsize, false, &Sym, 0});
- }
+ InX::MipsGot->addDynTlsEntry(*C.File, Sym);
C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
return 1;
}
@@ -161,7 +128,7 @@ static unsigned handleARMTlsRelocation(RelType Type, Symbol &Sym,
auto AddTlsReloc = [&](uint64_t Off, RelType Type, Symbol *Dest, bool Dyn) {
if (Dyn)
- InX::RelaDyn->addReloc({Type, InX::Got, Off, false, Dest, 0});
+ InX::RelaDyn->addReloc(Type, InX::Got, Off, Dest);
else
InX::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
};
@@ -207,7 +174,7 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C,
if (Config->EMachine == EM_ARM)
return handleARMTlsRelocation<ELFT>(Type, Sym, C, Offset, Addend, Expr);
if (Config->EMachine == EM_MIPS)
- return handleMipsTlsRelocation<ELFT>(Type, Sym, C, Offset, Addend, Expr);
+ return handleMipsTlsRelocation(Type, Sym, C, Offset, Addend, Expr);
if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) &&
Config->Shared) {
@@ -221,40 +188,62 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C,
return 1;
}
- if (isRelExprOneOf<R_TLSLD_PC, R_TLSLD>(Expr)) {
+ if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC,
+ R_TLSLD_HINT>(Expr)) {
// Local-Dynamic relocs can be relaxed to Local-Exec.
if (!Config->Shared) {
C.Relocations.push_back(
- {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
- return 2;
+ {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
+ Offset, Addend, &Sym});
+ return Target->TlsGdRelaxSkip;
}
+ if (Expr == R_TLSLD_HINT)
+ return 1;
if (InX::Got->addTlsIndex())
- InX::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::Got,
- InX::Got->getTlsIndexOff(), false, nullptr, 0});
+ InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got,
+ InX::Got->getTlsIndexOff(), nullptr);
C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
return 1;
}
// Local-Dynamic relocs can be relaxed to Local-Exec.
- if (isRelExprOneOf<R_ABS, R_TLSLD, R_TLSLD_PC>(Expr) && !Config->Shared) {
- C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
+ if (Expr == R_ABS && !Config->Shared) {
+ C.Relocations.push_back(
+ {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
+ Offset, Addend, &Sym});
+ return 1;
+ }
+
+ // Local-Dynamic sequence where offset of tls variable relative to dynamic
+ // thread pointer is stored in the got.
+ if (Expr == R_TLSLD_GOT_OFF) {
+ // Local-Dynamic relocs can be relaxed to local-exec
+ if (!Config->Shared) {
+ C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
+ return 1;
+ }
+ if (!Sym.isInGot()) {
+ InX::Got->addEntry(Sym);
+ uint64_t Off = Sym.getGotOffset();
+ InX::Got->Relocations.push_back({R_ABS, Target->TlsOffsetRel, Off, 0, &Sym});
+ }
+ C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
return 1;
}
- if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD,
- R_TLSGD_PC>(Expr)) {
+ if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD_GOT,
+ R_TLSGD_GOT_FROM_END, R_TLSGD_PC>(Expr)) {
if (Config->Shared) {
if (InX::Got->addDynTlsEntry(Sym)) {
uint64_t Off = InX::Got->getGlobalDynOffset(Sym);
- InX::RelaDyn->addReloc(
- {Target->TlsModuleIndexRel, InX::Got, Off, false, &Sym, 0});
+ InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got, Off, &Sym);
// If the symbol is preemptible we need the dynamic linker to write
// the offset too.
uint64_t OffsetOff = Off + Config->Wordsize;
if (Sym.IsPreemptible)
- InX::RelaDyn->addReloc(
- {Target->TlsOffsetRel, InX::Got, OffsetOff, false, &Sym, 0});
+ InX::RelaDyn->addReloc(Target->TlsOffsetRel, InX::Got, OffsetOff,
+ &Sym);
else
InX::Got->Relocations.push_back(
{R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Sym});
@@ -271,8 +260,8 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C,
Offset, Addend, &Sym});
if (!Sym.isInGot()) {
InX::Got->addEntry(Sym);
- InX::RelaDyn->addReloc(
- {Target->TlsGotRel, InX::Got, Sym.getGotOffset(), false, &Sym, 0});
+ InX::RelaDyn->addReloc(Target->TlsGotRel, InX::Got, Sym.getGotOffset(),
+ &Sym);
}
} else {
C.Relocations.push_back(
@@ -336,7 +325,7 @@ static bool isAbsoluteValue(const Symbol &Sym) {
// Returns true if Expr refers a PLT entry.
static bool needsPlt(RelExpr Expr) {
- return isRelExprOneOf<R_PLT_PC, R_PPC_PLT_OPD, R_PLT, R_PLT_PAGE_PC>(Expr);
+ return isRelExprOneOf<R_PLT_PC, R_PPC_CALL_PLT, R_PLT, R_PLT_PAGE_PC>(Expr);
}
// Returns true if Expr refers a GOT entry. Note that this function
@@ -352,7 +341,8 @@ static bool needsGot(RelExpr Expr) {
// file (PC, or GOT for example).
static bool isRelExpr(RelExpr Expr) {
return isRelExprOneOf<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL,
- R_PAGE_PC, R_RELAX_GOT_PC>(Expr);
+ R_PPC_CALL, R_PPC_CALL_PLT, R_PAGE_PC,
+ R_RELAX_GOT_PC>(Expr);
}
// Returns true if a given relocation can be computed at link-time.
@@ -367,13 +357,16 @@ static bool isRelExpr(RelExpr Expr) {
static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
InputSectionBase &S, uint64_t RelOff) {
// These expressions always compute a constant
- if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
- R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
- R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
- R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD,
- R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
+ if (isRelExprOneOf<
+ R_GOT_FROM_END, R_GOT_OFF, R_TLSLD_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
+ R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
+ R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
+ R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END,
+ R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT,
+ R_TLSLD_HINT>(E))
return true;
+ // The computation involves output from the ifunc resolver.
if (Sym.isGnuIFunc() && Config->ZIfuncnoplt)
return false;
@@ -420,39 +413,45 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
}
static RelExpr toPlt(RelExpr Expr) {
- if (Expr == R_PPC_OPD)
- return R_PPC_PLT_OPD;
- if (Expr == R_PC)
+ switch (Expr) {
+ case R_PPC_CALL:
+ return R_PPC_CALL_PLT;
+ case R_PC:
return R_PLT_PC;
- if (Expr == R_PAGE_PC)
+ case R_PAGE_PC:
return R_PLT_PAGE_PC;
- if (Expr == R_ABS)
+ case R_ABS:
return R_PLT;
- return Expr;
+ default:
+ return Expr;
+ }
}
static RelExpr fromPlt(RelExpr Expr) {
// We decided not to use a plt. Optimize a reference to the plt to a
// reference to the symbol itself.
- if (Expr == R_PLT_PC)
+ switch (Expr) {
+ case R_PLT_PC:
return R_PC;
- if (Expr == R_PPC_PLT_OPD)
- return R_PPC_OPD;
- if (Expr == R_PLT)
+ case R_PPC_CALL_PLT:
+ return R_PPC_CALL;
+ case R_PLT:
return R_ABS;
- return Expr;
+ default:
+ return Expr;
+ }
}
// Returns true if a given shared symbol is in a read-only segment in a DSO.
-template <class ELFT> static bool isReadOnly(SharedSymbol *SS) {
+template <class ELFT> static bool isReadOnly(SharedSymbol &SS) {
typedef typename ELFT::Phdr Elf_Phdr;
// Determine if the symbol is read-only by scanning the DSO's program headers.
- const SharedFile<ELFT> &File = SS->getFile<ELFT>();
+ const SharedFile<ELFT> &File = SS.getFile<ELFT>();
for (const Elf_Phdr &Phdr : check(File.getObj().program_headers()))
if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) &&
- !(Phdr.p_flags & ELF::PF_W) && SS->Value >= Phdr.p_vaddr &&
- SS->Value < Phdr.p_vaddr + Phdr.p_memsz)
+ !(Phdr.p_flags & ELF::PF_W) && SS.Value >= Phdr.p_vaddr &&
+ SS.Value < Phdr.p_vaddr + Phdr.p_memsz)
return true;
return false;
}
@@ -461,26 +460,45 @@ template <class ELFT> static bool isReadOnly(SharedSymbol *SS) {
//
// If two or more symbols are at the same offset, and at least one of
// them are copied by a copy relocation, all of them need to be copied.
-// Otherwise, they would refer different places at runtime.
+// Otherwise, they would refer to different places at runtime.
template <class ELFT>
-static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) {
+static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) {
typedef typename ELFT::Sym Elf_Sym;
- SharedFile<ELFT> &File = SS->getFile<ELFT>();
+ SharedFile<ELFT> &File = SS.getFile<ELFT>();
- std::vector<SharedSymbol *> Ret;
+ SmallSet<SharedSymbol *, 4> Ret;
for (const Elf_Sym &S : File.getGlobalELFSyms()) {
if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS ||
- S.st_value != SS->Value)
+ S.st_value != SS.Value)
continue;
StringRef Name = check(S.getName(File.getStringTable()));
Symbol *Sym = Symtab->find(Name);
if (auto *Alias = dyn_cast_or_null<SharedSymbol>(Sym))
- Ret.push_back(Alias);
+ Ret.insert(Alias);
}
return Ret;
}
+// When a symbol is copy relocated or we create a canonical plt entry, it is
+// effectively a defined symbol. In the case of copy relocation the symbol is
+// in .bss and in the case of a canonical plt entry it is in .plt. This function
+// replaces the existing symbol with a Defined pointing to the appropriate
+// location.
+static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value,
+ uint64_t Size) {
+ Symbol Old = Sym;
+ replaceSymbol<Defined>(&Sym, Sym.File, Sym.getName(), Sym.Binding,
+ Sym.StOther, Sym.Type, Value, Size, Sec);
+ Sym.PltIndex = Old.PltIndex;
+ Sym.GotIndex = Old.GotIndex;
+ Sym.VerdefIndex = Old.VerdefIndex;
+ Sym.IsPreemptible = true;
+ Sym.ExportDynamic = true;
+ Sym.IsUsedInRegularObj = true;
+ Sym.Used = true;
+}
+
// Reserve space in .bss or .bss.rel.ro for copy relocation.
//
// The copy relocation is pretty much a hack. If you use a copy relocation
@@ -523,17 +541,17 @@ static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) {
// to the variable in .bss. This kind of issue is sometimes very hard to
// debug. What's a solution? Instead of exporting a varaible V from a DSO,
// define an accessor getV().
-template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
+template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) {
// Copy relocation against zero-sized symbol doesn't make sense.
- uint64_t SymSize = SS->getSize();
- if (SymSize == 0)
- fatal("cannot create a copy relocation for symbol " + toString(*SS));
+ uint64_t SymSize = SS.getSize();
+ if (SymSize == 0 || SS.Alignment == 0)
+ fatal("cannot create a copy relocation for symbol " + toString(SS));
// See if this symbol is in a read-only segment. If so, preserve the symbol's
// memory protection by reserving space in the .bss.rel.ro section.
bool IsReadOnly = isReadOnly<ELFT>(SS);
BssSection *Sec = make<BssSection>(IsReadOnly ? ".bss.rel.ro" : ".bss",
- SymSize, SS->Alignment);
+ SymSize, SS.Alignment);
if (IsReadOnly)
InX::BssRelRo->getParent()->addSection(Sec);
else
@@ -542,125 +560,10 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
// Look through the DSO's dynamic symbol table for aliases and create a
// dynamic symbol for each one. This causes the copy relocation to correctly
// interpose any aliases.
- for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) {
- Sym->CopyRelSec = Sec;
- Sym->IsPreemptible = false;
- Sym->IsUsedInRegularObj = true;
- Sym->Used = true;
- }
+ for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS))
+ replaceWithDefined(*Sym, Sec, 0, Sym->Size);
- InX::RelaDyn->addReloc({Target->CopyRel, Sec, 0, false, SS, 0});
-}
-
-static void errorOrWarn(const Twine &Msg) {
- if (!Config->NoinhibitExec)
- error(Msg);
- else
- warn(Msg);
-}
-
-// Returns PLT relocation expression.
-//
-// This handles a non PIC program call to function in a shared library. In
-// an ideal world, we could just report an error saying the relocation can
-// overflow at runtime. In the real world with glibc, crt1.o has a
-// R_X86_64_PC32 pointing to libc.so.
-//
-// The general idea on how to handle such cases is to create a PLT entry and
-// use that as the function value.
-//
-// For the static linking part, we just return a plt expr and everything
-// else will use the the PLT entry as the address.
-//
-// The remaining problem is making sure pointer equality still works. We
-// need the help of the dynamic linker for that. We let it know that we have
-// a direct reference to a so symbol by creating an undefined symbol with a
-// non zero st_value. Seeing that, the dynamic linker resolves the symbol to
-// the value of the symbol we created. This is true even for got entries, so
-// pointer equality is maintained. To avoid an infinite loop, the only entry
-// that points to the real function is a dedicated got entry used by the
-// plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
-// R_386_JMP_SLOT, etc).
-static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) {
- Sym.NeedsPltAddr = true;
- Sym.IsPreemptible = false;
- IsConstant = true;
- return toPlt(Expr);
-}
-
-// This modifies the expression if we can use a copy relocation or point the
-// symbol to the PLT.
-template <class ELFT>
-static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
- InputSectionBase &S, uint64_t RelOff,
- bool &IsConstant) {
- // If a relocation can be applied at link-time, we don't need to
- // create a dynamic relocation in the first place.
- if (IsConstant)
- return Expr;
-
- // We can create any dynamic relocation supported by the dynamic linker if a
- // section is writable or we are passed -z notext.
- bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText;
- if (CanWrite && Target->isPicRel(Type))
- return Expr;
-
- // If the relocation is to a weak undef, and we are producing
- // executable, give up on it and produce a non preemptible 0.
- if (!Config->Shared && Sym.isUndefWeak()) {
- Sym.IsPreemptible = false;
- IsConstant = true;
- return Expr;
- }
-
- // If we got here we know that this relocation would require the dynamic
- // linker to write a value to read only memory or use an unsupported
- // relocation.
-
- // We can hack around it if we are producing an executable and
- // the refered symbol can be preemepted to refer to the executable.
- if (!CanWrite && (Config->Shared || (Config->Pic && !isRelExpr(Expr)))) {
- error(
- "can't create dynamic relocation " + toString(Type) + " against " +
- (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +
- " in readonly segment; recompile object files with -fPIC" +
- getLocation(S, Sym, RelOff));
- return Expr;
- }
-
- // Copy relocations are only possible if we are creating an executable and the
- // symbol is shared.
- if (!Sym.isShared() || Config->Shared)
- return Expr;
-
- if (Sym.getVisibility() != STV_DEFAULT) {
- error("cannot preempt symbol: " + toString(Sym) +
- getLocation(S, Sym, RelOff));
- return Expr;
- }
-
- if (Sym.isObject()) {
- // Produce a copy relocation.
- auto *B = dyn_cast<SharedSymbol>(&Sym);
- if (B && !B->CopyRelSec) {
- if (Config->ZNocopyreloc)
- error("unresolvable relocation " + toString(Type) +
- " against symbol '" + toString(*B) +
- "'; recompile with -fPIC or remove '-z nocopyreloc'" +
- getLocation(S, Sym, RelOff));
-
- addCopyRelSymbol<ELFT>(B);
- }
- IsConstant = true;
- return Expr;
- }
-
- if (Sym.isFunc())
- return getPltExpr(Sym, Expr, IsConstant);
-
- errorOrWarn("symbol '" + toString(Sym) + "' defined in " +
- toString(Sym.File) + " has no type");
- return Expr;
+ InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS);
}
// MIPS has an odd notion of "paired" relocations to calculate addends.
@@ -735,7 +638,7 @@ static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,
return false;
bool CanBeExternal =
- Sym.computeBinding() != STB_LOCAL && Sym.getVisibility() == STV_DEFAULT;
+ Sym.computeBinding() != STB_LOCAL && Sym.Visibility == STV_DEFAULT;
if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal)
return false;
@@ -763,12 +666,12 @@ static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,
// this for the N32 ABI. Iterate over relocation with the same offset and put
// theirs types into the single bit-set.
template <class RelTy> static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End) {
- RelType Type = Rel->getType(Config->IsMips64EL);
+ RelType Type = 0;
uint64_t Offset = Rel->r_offset;
int N = 0;
- while (Rel + 1 != End && (Rel + 1)->r_offset == Offset)
- Type |= (++Rel)->getType(Config->IsMips64EL) << (8 * ++N);
+ while (Rel != End && Rel->r_offset == Offset)
+ Type |= (Rel++)->getType(Config->IsMips64EL) << (8 * N++);
return Type;
}
@@ -818,16 +721,34 @@ private:
};
} // namespace
+static void addRelativeReloc(InputSectionBase *IS, uint64_t OffsetInSec,
+ Symbol *Sym, int64_t Addend, RelExpr Expr,
+ RelType Type) {
+ // Add a relative relocation. If RelrDyn section is enabled, and the
+ // relocation offset is guaranteed to be even, add the relocation to
+ // the RelrDyn section, otherwise add it to the RelaDyn section.
+ // RelrDyn sections don't support odd offsets. Also, RelrDyn sections
+ // don't store the addend values, so we must write it to the relocated
+ // address.
+ if (InX::RelrDyn && IS->Alignment >= 2 && OffsetInSec % 2 == 0) {
+ IS->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym});
+ InX::RelrDyn->Relocs.push_back({IS, OffsetInSec});
+ return;
+ }
+ InX::RelaDyn->addReloc(Target->RelativeRel, IS, OffsetInSec, Sym, Addend,
+ Expr, Type);
+}
+
template <class ELFT, class GotPltSection>
static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt,
- RelocationBaseSection *Rel, RelType Type, Symbol &Sym,
- bool UseSymVA) {
+ RelocationBaseSection *Rel, RelType Type, Symbol &Sym) {
Plt->addEntry<ELFT>(Sym);
GotPlt->addEntry(Sym);
- Rel->addReloc({Type, GotPlt, Sym.getGotPltOffset(), UseSymVA, &Sym, 0});
+ Rel->addReloc(
+ {Type, GotPlt, Sym.getGotPltOffset(), !Sym.IsPreemptible, &Sym, 0});
}
-template <class ELFT> static void addGotEntry(Symbol &Sym, bool Preemptible) {
+template <class ELFT> static void addGotEntry(Symbol &Sym) {
InX::Got->addEntry(Sym);
RelExpr Expr = Sym.isTls() ? R_TLS : R_ABS;
@@ -840,7 +761,8 @@ template <class ELFT> static void addGotEntry(Symbol &Sym, bool Preemptible) {
// add a static relocation to a Relocations vector so that
// InputSection::relocate will do the work for us. We may be able
// to just write a value now, but it is a TODO.)
- bool IsLinkTimeConstant = !Preemptible && (!Config->Pic || isAbsolute(Sym));
+ bool IsLinkTimeConstant =
+ !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym));
if (IsLinkTimeConstant) {
InX::Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym});
return;
@@ -848,23 +770,33 @@ template <class ELFT> static void addGotEntry(Symbol &Sym, bool Preemptible) {
// Otherwise, we emit a dynamic relocation to .rel[a].dyn so that
// the GOT slot will be fixed at load-time.
- RelType Type;
- if (Sym.isTls())
- Type = Target->TlsGotRel;
- else if (!Preemptible && Config->Pic && !isAbsolute(Sym))
- Type = Target->RelativeRel;
- else
- Type = Target->GotRel;
- InX::RelaDyn->addReloc({Type, InX::Got, Off, !Preemptible, &Sym, 0});
+ if (!Sym.isTls() && !Sym.IsPreemptible && Config->Pic && !isAbsolute(Sym)) {
+ addRelativeReloc(InX::Got, Off, &Sym, 0, R_ABS, Target->GotRel);
+ return;
+ }
+ InX::RelaDyn->addReloc(Sym.isTls() ? Target->TlsGotRel : Target->GotRel,
+ InX::Got, Off, &Sym, 0,
+ Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->GotRel);
+}
- // REL type relocations don't have addend fields unlike RELAs, and
- // their addends are stored to the section to which they are applied.
- // So, store addends if we need to.
- //
- // This is ugly -- the difference between REL and RELA should be
- // handled in a better way. It's a TODO.
- if (!Config->IsRela && !Preemptible)
- InX::Got->Relocations.push_back({R_ABS, Target->GotRel, Off, 0, &Sym});
+// Return true if we can define a symbol in the executable that
+// contains the value/function of a symbol defined in a shared
+// library.
+static bool canDefineSymbolInExecutable(Symbol &Sym) {
+ // If the symbol has default visibility the symbol defined in the
+ // executable will preempt it.
+ // Note that we want the visibility of the shared symbol itself, not
+ // the visibility of the symbol in the output file we are producing. That is
+ // why we use Sym.StOther.
+ if ((Sym.StOther & 0x3) == STV_DEFAULT)
+ return true;
+
+ // If we are allowed to break address equality of functions, defining
+ // a plt entry will allow the program to call the function in the
+ // .so, but the .so and the executable will no agree on the address
+ // of the function. Similar logic for objects.
+ return ((Sym.isFunc() && Config->IgnoreFunctionAddressEquality) ||
+ (Sym.isObject() && Config->IgnoreDataAddressEquality));
}
// The reason we have to do this early scan is as follows
@@ -881,131 +813,27 @@ template <class ELFT> static void addGotEntry(Symbol &Sym, bool Preemptible) {
// complicates things for the dynamic linker and means we would have to reserve
// space for the extra PT_LOAD even if we end up not using it.
template <class ELFT, class RelTy>
-static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
- OffsetGetter GetOffset(Sec);
-
- // Not all relocations end up in Sec.Relocations, but a lot do.
- Sec.Relocations.reserve(Rels.size());
-
- for (auto I = Rels.begin(), End = Rels.end(); I != End; ++I) {
- const RelTy &Rel = *I;
- Symbol &Sym = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
- RelType Type = Rel.getType(Config->IsMips64EL);
-
- // Deal with MIPS oddity.
- if (Config->MipsN32Abi)
- Type = getMipsN32RelType(I, End);
-
- // Get an offset in an output section this relocation is applied to.
- uint64_t Offset = GetOffset.get(Rel.r_offset);
- if (Offset == uint64_t(-1))
- continue;
-
- // Skip if the target symbol is an erroneous undefined symbol.
- if (maybeReportUndefined(Sym, Sec, Rel.r_offset))
- continue;
-
- RelExpr Expr =
- Target->getRelExpr(Type, Sym, Sec.Data.begin() + Rel.r_offset);
-
- // Ignore "hint" relocations because they are only markers for relaxation.
- if (isRelExprOneOf<R_HINT, R_NONE>(Expr))
- continue;
-
- // Handle yet another MIPS-ness.
- if (isMipsGprel(Type)) {
- int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal());
- Sec.Relocations.push_back({R_MIPS_GOTREL, Type, Offset, Addend, &Sym});
- continue;
- }
-
- bool Preemptible = Sym.IsPreemptible;
-
- // Strenghten or relax a PLT access.
- //
- // GNU ifunc symbols must be accessed via PLT because their addresses
- // are determined by runtime. If the -z ifunc-noplt option is specified,
- // we permit the optimization of ifunc calls by omitting the PLT entry
- // and preserving relocations at ifunc call sites.
- //
- // On the other hand, if we know that a PLT entry will be resolved within
- // the same ELF module, we can skip PLT access and directly jump to the
- // destination function. For example, if we are linking a main exectuable,
- // all dynamic symbols that can be resolved within the executable will
- // actually be resolved that way at runtime, because the main exectuable
- // is always at the beginning of a search list. We can leverage that fact.
- if (Sym.isGnuIFunc() && !Config->ZIfuncnoplt)
- Expr = toPlt(Expr);
- else if (!Preemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym))
- Expr =
- Target->adjustRelaxExpr(Type, Sec.Data.data() + Rel.r_offset, Expr);
- else if (!Preemptible)
- Expr = fromPlt(Expr);
-
- bool IsConstant =
- isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Rel.r_offset);
-
- Expr = adjustExpr<ELFT>(Sym, Expr, Type, Sec, Rel.r_offset, IsConstant);
- if (errorCount())
- continue;
-
- // This relocation does not require got entry, but it is relative to got and
- // needs it to be created. Here we request for that.
- if (isRelExprOneOf<R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL,
- R_GOTREL_FROM_END, R_PPC_TOC>(Expr))
- InX::Got->HasGotOffRel = true;
-
- // Read an addend.
- int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal());
-
- // Process some TLS relocations, including relaxing TLS relocations.
- // Note that this function does not handle all TLS relocations.
- if (unsigned Processed =
- handleTlsRelocation<ELFT>(Type, Sym, Sec, Offset, Addend, Expr)) {
- I += (Processed - 1);
- continue;
- }
-
- // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
- if (needsPlt(Expr) && !Sym.isInPlt()) {
- if (Sym.isGnuIFunc() && !Preemptible)
- addPltEntry<ELFT>(InX::Iplt, InX::IgotPlt, InX::RelaIplt,
- Target->IRelativeRel, Sym, true);
- else
- addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel,
- Sym, !Preemptible);
- }
-
- // Create a GOT slot if a relocation needs GOT.
- if (needsGot(Expr)) {
- if (Config->EMachine == EM_MIPS) {
- // MIPS ABI has special rules to process GOT entries and doesn't
- // require relocation entries for them. A special case is TLS
- // relocations. In that case dynamic loader applies dynamic
- // relocations to initialize TLS GOT entries.
- // See "Global Offset Table" in Chapter 5 in the following document
- // for detailed description:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- InX::MipsGot->addEntry(Sym, Addend, Expr);
- if (Sym.isTls() && Sym.IsPreemptible)
- InX::RelaDyn->addReloc({Target->TlsGotRel, InX::MipsGot,
- Sym.getGotOffset(), false, &Sym, 0});
- } else if (!Sym.isInGot()) {
- addGotEntry<ELFT>(Sym, Preemptible);
- }
- }
-
- if (!needsPlt(Expr) && !needsGot(Expr) && Sym.IsPreemptible) {
- // We don't know anything about the finaly symbol. Just ask the dynamic
- // linker to handle the relocation for us.
- if (!Target->isPicRel(Type))
- errorOrWarn(
- "relocation " + toString(Type) +
- " cannot be used against shared object; recompile with -fPIC" +
- getLocation(Sec, Sym, Offset));
+static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,
+ uint64_t Offset, Symbol &Sym, const RelTy &Rel,
+ int64_t Addend) {
+ if (isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Offset)) {
+ Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+ return;
+ }
+ if (Sym.isGnuIFunc() && Config->ZIfuncnoplt) {
+ InX::RelaDyn->addReloc(Type, &Sec, Offset, &Sym, Addend, R_ADDEND, Type);
+ return;
+ }
+ bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText;
+ if (CanWrite) {
+ // R_GOT refers to a position in the got, even if the symbol is preemptible.
+ bool IsPreemptibleValue = Sym.IsPreemptible && Expr != R_GOT;
- InX::RelaDyn->addReloc(
- {Target->getDynRel(Type), &Sec, Offset, false, &Sym, Addend});
+ if (!IsPreemptibleValue) {
+ addRelativeReloc(&Sec, Offset, &Sym, Addend, Expr, Type);
+ return;
+ } else if (RelType Rel = Target->getDynRel(Type)) {
+ InX::RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, R_ADDEND, Type);
// MIPS ABI turns using of GOT and dynamic relocations inside out.
// While regular ABI uses dynamic relocations to fill up GOT entries
@@ -1023,47 +851,210 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
// a dynamic relocation.
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19
if (Config->EMachine == EM_MIPS)
- InX::MipsGot->addEntry(Sym, Addend, Expr);
- continue;
+ InX::MipsGot->addEntry(*Sec.File, Sym, Addend, Expr);
+ return;
}
+ }
- // The size is not going to change, so we fold it in here.
- if (Expr == R_SIZE)
- Addend += Sym.getSize();
+ // If the relocation is to a weak undef, and we are producing
+ // executable, give up on it and produce a non preemptible 0.
+ if (!Config->Shared && Sym.isUndefWeak()) {
+ Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+ return;
+ }
- // If the produced value is a constant, we just remember to write it
- // when outputting this section. We also have to do it if the format
- // uses Elf_Rel, since in that case the written value is the addend.
- if (IsConstant) {
- Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
- continue;
- }
+ if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) {
+ error(
+ "can't create dynamic relocation " + toString(Type) + " against " +
+ (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +
+ " in readonly segment; recompile object files with -fPIC "
+ "or pass '-Wl,-z,notext' to allow text relocations in the output" +
+ getLocation(Sec, Sym, Offset));
+ return;
+ }
- // Preserve relocations against ifuncs if we were asked to do so.
- if (Sym.isGnuIFunc() && Config->ZIfuncnoplt) {
- if (Config->IsRela)
- InX::RelaDyn->addReloc({Type, &Sec, Offset, false, &Sym, Addend});
- else
- // Preserve the existing addend.
- InX::RelaDyn->addReloc({Type, &Sec, Offset, false, &Sym, 0});
- continue;
+ // Copy relocations are only possible if we are creating an executable.
+ if (Config->Shared) {
+ errorOrWarn("relocation " + toString(Type) +
+ " cannot be used against symbol " + toString(Sym) +
+ "; recompile with -fPIC" + getLocation(Sec, Sym, Offset));
+ return;
+ }
+
+ // If the symbol is undefined we already reported any relevant errors.
+ if (Sym.isUndefined())
+ return;
+
+ if (!canDefineSymbolInExecutable(Sym)) {
+ error("cannot preempt symbol: " + toString(Sym) +
+ getLocation(Sec, Sym, Offset));
+ return;
+ }
+
+ if (Sym.isObject()) {
+ // Produce a copy relocation.
+ if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) {
+ if (!Config->ZCopyreloc)
+ error("unresolvable relocation " + toString(Type) +
+ " against symbol '" + toString(*SS) +
+ "'; recompile with -fPIC or remove '-z nocopyreloc'" +
+ getLocation(Sec, Sym, Offset));
+ addCopyRelSymbol<ELFT>(*SS);
}
+ Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+ return;
+ }
- // If the output being produced is position independent, the final value
- // is still not known. In that case we still need some help from the
- // dynamic linker. We can however do better than just copying the incoming
- // relocation. We can process some of it and and just ask the dynamic
- // linker to add the load address.
- if (Config->IsRela) {
- InX::RelaDyn->addReloc(
- {Target->RelativeRel, &Sec, Offset, true, &Sym, Addend});
- } else {
- // In REL, addends are stored to the target section.
- InX::RelaDyn->addReloc(
- {Target->RelativeRel, &Sec, Offset, true, &Sym, 0});
- Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+ if (Sym.isFunc()) {
+ // This handles a non PIC program call to function in a shared library. In
+ // an ideal world, we could just report an error saying the relocation can
+ // overflow at runtime. In the real world with glibc, crt1.o has a
+ // R_X86_64_PC32 pointing to libc.so.
+ //
+ // The general idea on how to handle such cases is to create a PLT entry and
+ // use that as the function value.
+ //
+ // For the static linking part, we just return a plt expr and everything
+ // else will use the PLT entry as the address.
+ //
+ // The remaining problem is making sure pointer equality still works. We
+ // need the help of the dynamic linker for that. We let it know that we have
+ // a direct reference to a so symbol by creating an undefined symbol with a
+ // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
+ // the value of the symbol we created. This is true even for got entries, so
+ // pointer equality is maintained. To avoid an infinite loop, the only entry
+ // that points to the real function is a dedicated got entry used by the
+ // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
+ // R_386_JMP_SLOT, etc).
+
+ // For position independent executable on i386, the plt entry requires ebx
+ // to be set. This causes two problems:
+ // * If some code has a direct reference to a function, it was probably
+ // compiled without -fPIE/-fPIC and doesn't maintain ebx.
+ // * If a library definition gets preempted to the executable, it will have
+ // the wrong ebx value.
+ if (Config->Pie && Config->EMachine == EM_386)
+ errorOrWarn("symbol '" + toString(Sym) +
+ "' cannot be preempted; recompile with -fPIE" +
+ getLocation(Sec, Sym, Offset));
+ if (!Sym.isInPlt())
+ addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel,
+ Sym);
+ if (!Sym.isDefined())
+ replaceWithDefined(Sym, InX::Plt, Sym.getPltOffset(), 0);
+ Sym.NeedsPltAddr = true;
+ Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+ return;
+ }
+
+ errorOrWarn("symbol '" + toString(Sym) + "' has no type" +
+ getLocation(Sec, Sym, Offset));
+}
+
+template <class ELFT, class RelTy>
+static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I,
+ RelTy *End) {
+ const RelTy &Rel = *I;
+ Symbol &Sym = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
+ RelType Type;
+
+ // Deal with MIPS oddity.
+ if (Config->MipsN32Abi) {
+ Type = getMipsN32RelType(I, End);
+ } else {
+ Type = Rel.getType(Config->IsMips64EL);
+ ++I;
+ }
+
+ // Get an offset in an output section this relocation is applied to.
+ uint64_t Offset = GetOffset.get(Rel.r_offset);
+ if (Offset == uint64_t(-1))
+ return;
+
+ // Skip if the target symbol is an erroneous undefined symbol.
+ if (maybeReportUndefined(Sym, Sec, Rel.r_offset))
+ return;
+
+ const uint8_t *RelocatedAddr = Sec.Data.begin() + Rel.r_offset;
+ RelExpr Expr = Target->getRelExpr(Type, Sym, RelocatedAddr);
+
+ // Ignore "hint" relocations because they are only markers for relaxation.
+ if (isRelExprOneOf<R_HINT, R_NONE>(Expr))
+ return;
+
+ // Strenghten or relax relocations.
+ //
+ // GNU ifunc symbols must be accessed via PLT because their addresses
+ // are determined by runtime.
+ //
+ // On the other hand, if we know that a PLT entry will be resolved within
+ // the same ELF module, we can skip PLT access and directly jump to the
+ // destination function. For example, if we are linking a main exectuable,
+ // all dynamic symbols that can be resolved within the executable will
+ // actually be resolved that way at runtime, because the main exectuable
+ // is always at the beginning of a search list. We can leverage that fact.
+ if (Sym.isGnuIFunc() && !Config->ZIfuncnoplt)
+ Expr = toPlt(Expr);
+ else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym))
+ Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr);
+ else if (!Sym.IsPreemptible)
+ Expr = fromPlt(Expr);
+
+ // This relocation does not require got entry, but it is relative to got and
+ // needs it to be created. Here we request for that.
+ if (isRelExprOneOf<R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL,
+ R_GOTREL_FROM_END, R_PPC_TOC>(Expr))
+ InX::Got->HasGotOffRel = true;
+
+ // Read an addend.
+ int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal());
+
+ // Process some TLS relocations, including relaxing TLS relocations.
+ // Note that this function does not handle all TLS relocations.
+ if (unsigned Processed =
+ handleTlsRelocation<ELFT>(Type, Sym, Sec, Offset, Addend, Expr)) {
+ I += (Processed - 1);
+ return;
+ }
+
+ // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
+ if (needsPlt(Expr) && !Sym.isInPlt()) {
+ if (Sym.isGnuIFunc() && !Sym.IsPreemptible)
+ addPltEntry<ELFT>(InX::Iplt, InX::IgotPlt, InX::RelaIplt,
+ Target->IRelativeRel, Sym);
+ else
+ addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel,
+ Sym);
+ }
+
+ // Create a GOT slot if a relocation needs GOT.
+ if (needsGot(Expr)) {
+ if (Config->EMachine == EM_MIPS) {
+ // MIPS ABI has special rules to process GOT entries and doesn't
+ // require relocation entries for them. A special case is TLS
+ // relocations. In that case dynamic loader applies dynamic
+ // relocations to initialize TLS GOT entries.
+ // See "Global Offset Table" in Chapter 5 in the following document
+ // for detailed description:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ InX::MipsGot->addEntry(*Sec.File, Sym, Addend, Expr);
+ } else if (!Sym.isInGot()) {
+ addGotEntry<ELFT>(Sym);
}
}
+
+ processRelocAux<ELFT>(Sec, Expr, Type, Offset, Sym, Rel, Addend);
+}
+
+template <class ELFT, class RelTy>
+static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
+ OffsetGetter GetOffset(Sec);
+
+ // Not all relocations end up in Sec.Relocations, but a lot do.
+ Sec.Relocations.reserve(Rels.size());
+
+ for (auto I = Rels.begin(), End = Rels.end(); I != End;)
+ scanReloc<ELFT>(Sec, GetOffset, I, End);
}
template <class ELFT> void elf::scanRelocations(InputSectionBase &S) {
@@ -1278,17 +1269,30 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) {
//
// We follow a simple but conservative heuristic to place ThunkSections at
// offsets that are multiples of a Target specific branch range.
-// For an InputSectionRange that is smaller than the range, a single
+// For an InputSectionDescription that is smaller than the range, a single
// ThunkSection at the end of the range will do.
+//
+// For an InputSectionDescription that is more than twice the size of the range,
+// we place the last ThunkSection at range bytes from the end of the
+// InputSectionDescription in order to increase the likelihood that the
+// distance from a thunk to its target will be sufficiently small to
+// allow for the creation of a short thunk.
void ThunkCreator::createInitialThunkSections(
ArrayRef<OutputSection *> OutputSections) {
forEachInputSectionDescription(
OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {
if (ISD->Sections.empty())
return;
+ uint32_t ISDBegin = ISD->Sections.front()->OutSecOff;
+ uint32_t ISDEnd =
+ ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize();
+ uint32_t LastThunkLowerBound = -1;
+ if (ISDEnd - ISDBegin > Target->ThunkSectionSpacing * 2)
+ LastThunkLowerBound = ISDEnd - Target->ThunkSectionSpacing;
+
uint32_t ISLimit;
- uint32_t PrevISLimit = ISD->Sections.front()->OutSecOff;
- uint32_t ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing;
+ uint32_t PrevISLimit = ISDBegin;
+ uint32_t ThunkUpperBound = ISDBegin + Target->ThunkSectionSpacing;
for (const InputSection *IS : ISD->Sections) {
ISLimit = IS->OutSecOff + IS->getSize();
@@ -1296,6 +1300,8 @@ void ThunkCreator::createInitialThunkSections(
addThunkSection(OS, ISD, PrevISLimit);
ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing;
}
+ if (ISLimit > LastThunkLowerBound)
+ break;
PrevISLimit = ISLimit;
}
addThunkSection(OS, ISD, ISLimit);
@@ -1312,17 +1318,22 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type,
uint64_t Src) {
- auto Res = ThunkedSymbols.insert({&Sym, std::vector<Thunk *>()});
- if (!Res.second) {
- // Check existing Thunks for Sym to see if they can be reused
- for (Thunk *ET : Res.first->second)
- if (ET->isCompatibleWith(Type) &&
- Target->inBranchRange(Type, Src, ET->ThunkSym->getVA()))
- return std::make_pair(ET, false);
- }
+ std::vector<Thunk *> *ThunkVec = nullptr;
+ // We use (section, offset) pair to find the thunk position if possible so
+ // that we create only one thunk for aliased symbols or ICFed sections.
+ if (auto *D = dyn_cast<Defined>(&Sym))
+ if (!D->isInPlt() && D->Section)
+ ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}];
+ if (!ThunkVec)
+ ThunkVec = &ThunkedSymbols[&Sym];
+ // Check existing Thunks for Sym to see if they can be reused
+ for (Thunk *ET : *ThunkVec)
+ if (ET->isCompatibleWith(Type) &&
+ Target->inBranchRange(Type, Src, ET->getThunkTargetSym()->getVA()))
+ return std::make_pair(ET, false);
// No existing compatible Thunk in range, create a new one
Thunk *T = addThunk(Type, Sym);
- Res.first->second.push_back(T);
+ ThunkVec->push_back(T);
return std::make_pair(T, true);
}
@@ -1330,7 +1341,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type,
// InputSectionDescription::Sections.
void ThunkCreator::forEachInputSectionDescription(
ArrayRef<OutputSection *> OutputSections,
- std::function<void(OutputSection *, InputSectionDescription *)> Fn) {
+ llvm::function_ref<void(OutputSection *, InputSectionDescription *)> Fn) {
for (OutputSection *OS : OutputSections) {
if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
continue;
@@ -1398,7 +1409,7 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {
for (InputSection *IS : ISD->Sections)
for (Relocation &Rel : IS->Relocations) {
- uint64_t Src = OS->Addr + IS->OutSecOff + Rel.Offset;
+ uint64_t Src = IS->getVA(Rel.Offset);
// If we are a relocation to an existing Thunk, check if it is
// still in range. If not then Rel will be altered to point to its
@@ -1413,7 +1424,6 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
bool IsNew;
std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src);
if (IsNew) {
- AddressesChanged = true;
// Find or create a ThunkSection for the new Thunk
ThunkSection *TS;
if (auto *TIS = T->getTargetInputSection())
@@ -1421,13 +1431,18 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
else
TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src);
TS->addThunk(T);
- Thunks[T->ThunkSym] = T;
+ Thunks[T->getThunkTargetSym()] = T;
}
// Redirect relocation to Thunk, we never go via the PLT to a Thunk
- Rel.Sym = T->ThunkSym;
+ Rel.Sym = T->getThunkTargetSym();
Rel.Expr = fromPlt(Rel.Expr);
}
+ for (auto &P : ISD->ThunkSections)
+ AddressesChanged |= P.first->assignOffsets();
});
+ for (auto &P : ThunkedSections)
+ AddressesChanged |= P.second->assignOffsets();
+
// Merge all created synthetic ThunkSections back into OutputSection
mergeThunks(OutputSections);
++Pass;
diff --git a/contrib/llvm/tools/lld/ELF/Relocations.h b/contrib/llvm/tools/lld/ELF/Relocations.h
index 2cc8adfa5985..a4125111c4fe 100644
--- a/contrib/llvm/tools/lld/ELF/Relocations.h
+++ b/contrib/llvm/tools/lld/ELF/Relocations.h
@@ -21,7 +21,7 @@ class Symbol;
class InputSection;
class InputSectionBase;
class OutputSection;
-class OutputSection;
+class SectionBase;
// Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL.
typedef uint32_t RelType;
@@ -32,6 +32,7 @@ typedef uint32_t RelType;
enum RelExpr {
R_INVALID,
R_ABS,
+ R_ADDEND,
R_ARM_SBREL,
R_GOT,
R_GOTONLY_PC,
@@ -58,27 +59,33 @@ enum RelExpr {
R_PLT,
R_PLT_PAGE_PC,
R_PLT_PC,
- R_PPC_OPD,
- R_PPC_PLT_OPD,
+ R_PPC_CALL,
+ R_PPC_CALL_PLT,
R_PPC_TOC,
R_RELAX_GOT_PC,
R_RELAX_GOT_PC_NOPIC,
R_RELAX_TLS_GD_TO_IE,
R_RELAX_TLS_GD_TO_IE_ABS,
R_RELAX_TLS_GD_TO_IE_END,
+ R_RELAX_TLS_GD_TO_IE_GOT_OFF,
R_RELAX_TLS_GD_TO_IE_PAGE_PC,
R_RELAX_TLS_GD_TO_LE,
R_RELAX_TLS_GD_TO_LE_NEG,
R_RELAX_TLS_IE_TO_LE,
R_RELAX_TLS_LD_TO_LE,
+ R_RELAX_TLS_LD_TO_LE_ABS,
R_SIZE,
R_TLS,
R_TLSDESC,
R_TLSDESC_CALL,
R_TLSDESC_PAGE,
- R_TLSGD,
+ R_TLSGD_GOT,
+ R_TLSGD_GOT_FROM_END,
R_TLSGD_PC,
- R_TLSLD,
+ R_TLSLD_GOT,
+ R_TLSLD_GOT_FROM_END,
+ R_TLSLD_GOT_OFF,
+ R_TLSLD_HINT,
R_TLSLD_PC,
};
@@ -150,7 +157,7 @@ private:
void forEachInputSectionDescription(
ArrayRef<OutputSection *> OutputSections,
- std::function<void(OutputSection *, InputSectionDescription *)> Fn);
+ llvm::function_ref<void(OutputSection *, InputSectionDescription *)> Fn);
std::pair<Thunk *, bool> getThunk(Symbol &Sym, RelType Type, uint64_t Src);
@@ -160,6 +167,8 @@ private:
bool normalizeExistingThunk(Relocation &Rel, uint64_t Src);
// Record all the available Thunks for a Symbol
+ llvm::DenseMap<std::pair<SectionBase *, uint64_t>, std::vector<Thunk *>>
+ ThunkedSymbolsBySection;
llvm::DenseMap<Symbol *, std::vector<Thunk *>> ThunkedSymbols;
// Find a Thunk from the Thunks symbol definition, we can use this to find
diff --git a/contrib/llvm/tools/lld/ELF/ScriptLexer.cpp b/contrib/llvm/tools/lld/ELF/ScriptLexer.cpp
index ef5a1cff7590..d4b1f6d99cc1 100644
--- a/contrib/llvm/tools/lld/ELF/ScriptLexer.cpp
+++ b/contrib/llvm/tools/lld/ELF/ScriptLexer.cpp
@@ -66,8 +66,6 @@ size_t ScriptLexer::getColumnNumber() {
std::string ScriptLexer::getCurrentLocation() {
std::string Filename = getCurrentMB().getBufferIdentifier();
- if (!Pos)
- return Filename;
return (Filename + ":" + Twine(getLineNumber())).str();
}
@@ -116,8 +114,9 @@ void ScriptLexer::tokenize(MemoryBufferRef MB) {
}
// ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
+ // "|", "||", "&" and "&&" are different operators.
if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||
- S.startswith(">=")) {
+ S.startswith(">=") || S.startswith("||") || S.startswith("&&")) {
Vec.push_back(S.substr(0, 2));
S = S.substr(2);
continue;
@@ -282,10 +281,7 @@ static bool encloses(StringRef S, StringRef T) {
MemoryBufferRef ScriptLexer::getCurrentMB() {
// Find input buffer containing the current token.
- assert(!MBs.empty());
- if (!Pos)
- return MBs[0];
-
+ assert(!MBs.empty() && Pos > 0);
for (MemoryBufferRef MB : MBs)
if (encloses(MB.getBuffer(), Tokens[Pos - 1]))
return MB;
diff --git a/contrib/llvm/tools/lld/ELF/ScriptParser.cpp b/contrib/llvm/tools/lld/ELF/ScriptParser.cpp
index 3d2606db8d06..ddb4a49a3e5e 100644
--- a/contrib/llvm/tools/lld/ELF/ScriptParser.cpp
+++ b/contrib/llvm/tools/lld/ELF/ScriptParser.cpp
@@ -63,6 +63,7 @@ private:
void readExtern();
void readGroup();
void readInclude();
+ void readInput();
void readMemory();
void readOutput();
void readOutputArch();
@@ -74,12 +75,14 @@ private:
void readVersion();
void readVersionScriptCommand();
- SymbolAssignment *readAssignment(StringRef Name);
+ SymbolAssignment *readSymbolAssignment(StringRef Name);
ByteCommand *readByteCommand(StringRef Tok);
uint32_t readFill();
uint32_t parseFill(StringRef Tok);
void readSectionAddressType(OutputSection *Cmd);
+ OutputSection *readOverlaySectionDescription();
OutputSection *readOutputSectionDescription(StringRef OutSec);
+ std::vector<BaseCommand *> readOverlay();
std::vector<StringRef> readOutputSectionPhdrs();
InputSectionDescription *readInputSectionDescription(StringRef Tok);
StringMatcher readFilePatterns();
@@ -88,16 +91,16 @@ private:
unsigned readPhdrType();
SortSectionPolicy readSortKind();
SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
- SymbolAssignment *readProvideOrAssignment(StringRef Tok);
+ SymbolAssignment *readAssignment(StringRef Tok);
void readSort();
- AssertCommand *readAssert();
- Expr readAssertExpr();
+ Expr readAssert();
Expr readConstant();
Expr getPageSize();
uint64_t readMemoryAssignment(StringRef, StringRef, StringRef);
std::pair<uint32_t, uint32_t> readMemoryAttributes();
+ Expr combine(StringRef Op, Expr L, Expr R);
Expr readExpr();
Expr readExpr1(Expr Lhs, int MinPrec);
StringRef readParenLiteral();
@@ -157,17 +160,6 @@ static ExprValue sub(ExprValue A, ExprValue B) {
return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};
}
-static ExprValue mul(ExprValue A, ExprValue B) {
- return A.getValue() * B.getValue();
-}
-
-static ExprValue div(ExprValue A, ExprValue B) {
- if (uint64_t BV = B.getValue())
- return A.getValue() / BV;
- error("division by zero");
- return 0;
-}
-
static ExprValue bitAnd(ExprValue A, ExprValue B) {
moveAbsRight(A, B);
return {A.Sec, A.ForceAbsolute,
@@ -237,16 +229,16 @@ void ScriptParser::readLinkerScript() {
if (Tok == ";")
continue;
- if (Tok == "ASSERT") {
- Script->SectionCommands.push_back(readAssert());
- } else if (Tok == "ENTRY") {
+ if (Tok == "ENTRY") {
readEntry();
} else if (Tok == "EXTERN") {
readExtern();
- } else if (Tok == "GROUP" || Tok == "INPUT") {
+ } else if (Tok == "GROUP") {
readGroup();
} else if (Tok == "INCLUDE") {
readInclude();
+ } else if (Tok == "INPUT") {
+ readInput();
} else if (Tok == "MEMORY") {
readMemory();
} else if (Tok == "OUTPUT") {
@@ -265,7 +257,7 @@ void ScriptParser::readLinkerScript() {
readSections();
} else if (Tok == "VERSION") {
readVersion();
- } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) {
+ } else if (SymbolAssignment *Cmd = readAssignment(Tok)) {
Script->SectionCommands.push_back(Cmd);
} else {
setError("unknown directive: " + Tok);
@@ -336,13 +328,12 @@ void ScriptParser::readExtern() {
}
void ScriptParser::readGroup() {
- expect("(");
- while (!errorCount() && !consume(")")) {
- if (consume("AS_NEEDED"))
- readAsNeeded();
- else
- addFile(unquote(next()));
- }
+ bool Orig = InputFile::IsInGroup;
+ InputFile::IsInGroup = true;
+ readInput();
+ InputFile::IsInGroup = Orig;
+ if (!Orig)
+ ++InputFile::NextGroupId;
}
void ScriptParser::readInclude() {
@@ -353,7 +344,7 @@ void ScriptParser::readInclude() {
return;
}
- if (Optional<std::string> Path = searchLinkerScript(Tok)) {
+ if (Optional<std::string> Path = searchScript(Tok)) {
if (Optional<MemoryBufferRef> MB = readFile(*Path))
tokenize(*MB);
return;
@@ -361,6 +352,16 @@ void ScriptParser::readInclude() {
setError("cannot find linker script " + Tok);
}
+void ScriptParser::readInput() {
+ expect("(");
+ while (!errorCount() && !consume(")")) {
+ if (consume("AS_NEEDED"))
+ readAsNeeded();
+ else
+ addFile(unquote(next()));
+ }
+}
+
void ScriptParser::readOutput() {
// -o <file> takes predecence over OUTPUT(<file>).
expect("(");
@@ -437,6 +438,49 @@ void ScriptParser::readSearchDir() {
expect(")");
}
+// This reads an overlay description. Overlays are used to describe output
+// sections that use the same virtual memory range and normally would trigger
+// linker's sections sanity check failures.
+// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
+std::vector<BaseCommand *> ScriptParser::readOverlay() {
+ // VA and LMA expressions are optional, though for simplicity of
+ // implementation we assume they are not. That is what OVERLAY was designed
+ // for first of all: to allow sections with overlapping VAs at different LMAs.
+ Expr AddrExpr = readExpr();
+ expect(":");
+ expect("AT");
+ Expr LMAExpr = readParenExpr();
+ expect("{");
+
+ std::vector<BaseCommand *> V;
+ OutputSection *Prev = nullptr;
+ while (!errorCount() && !consume("}")) {
+ // VA is the same for all sections. The LMAs are consecutive in memory
+ // starting from the base load address specified.
+ OutputSection *OS = readOverlaySectionDescription();
+ OS->AddrExpr = AddrExpr;
+ if (Prev)
+ OS->LMAExpr = [=] { return Prev->getLMA() + Prev->Size; };
+ else
+ OS->LMAExpr = LMAExpr;
+ V.push_back(OS);
+ Prev = OS;
+ }
+
+ // According to the specification, at the end of the overlay, the location
+ // counter should be equal to the overlay base address plus size of the
+ // largest section seen in the overlay.
+ // Here we want to create the Dot assignment command to achieve that.
+ Expr MoveDot = [=] {
+ uint64_t Max = 0;
+ for (BaseCommand *Cmd : V)
+ Max = std::max(Max, cast<OutputSection>(Cmd)->Size);
+ return AddrExpr().getValue() + Max;
+ };
+ V.push_back(make<SymbolAssignment>(".", MoveDot, getCurrentLocation()));
+ return V;
+}
+
void ScriptParser::readSections() {
Script->HasSectionsCommand = true;
@@ -446,26 +490,48 @@ void ScriptParser::readSections() {
Config->SingleRoRx = true;
expect("{");
+ std::vector<BaseCommand *> V;
while (!errorCount() && !consume("}")) {
StringRef Tok = next();
- BaseCommand *Cmd = readProvideOrAssignment(Tok);
- if (!Cmd) {
- if (Tok == "ASSERT")
- Cmd = readAssert();
- else
- Cmd = readOutputSectionDescription(Tok);
+ if (Tok == "OVERLAY") {
+ for (BaseCommand *Cmd : readOverlay())
+ V.push_back(Cmd);
+ continue;
}
- Script->SectionCommands.push_back(Cmd);
+
+ if (BaseCommand *Cmd = readAssignment(Tok))
+ V.push_back(Cmd);
+ else
+ V.push_back(readOutputSectionDescription(Tok));
+ }
+
+ if (!atEOF() && consume("INSERT")) {
+ std::vector<BaseCommand *> *Dest = nullptr;
+ if (consume("AFTER"))
+ Dest = &Script->InsertAfterCommands[next()];
+ else if (consume("BEFORE"))
+ Dest = &Script->InsertBeforeCommands[next()];
+ else
+ setError("expected AFTER/BEFORE, but got '" + next() + "'");
+ if (Dest)
+ Dest->insert(Dest->end(), V.begin(), V.end());
+ return;
}
+
+ Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),
+ V.end());
}
static int precedence(StringRef Op) {
return StringSwitch<int>(Op)
- .Cases("*", "/", 5)
- .Cases("+", "-", 4)
- .Cases("<<", ">>", 3)
- .Cases("<", "<=", ">", ">=", "==", "!=", 2)
- .Cases("&", "|", 1)
+ .Cases("*", "/", "%", 8)
+ .Cases("+", "-", 7)
+ .Cases("<<", ">>", 6)
+ .Cases("<", "<=", ">", ">=", "==", "!=", 5)
+ .Case("&", 4)
+ .Case("|", 3)
+ .Case("&&", 2)
+ .Case("||", 1)
.Default(-1);
}
@@ -588,11 +654,7 @@ void ScriptParser::readSort() {
expect(")");
}
-AssertCommand *ScriptParser::readAssert() {
- return make<AssertCommand>(readAssertExpr());
-}
-
-Expr ScriptParser::readAssertExpr() {
+Expr ScriptParser::readAssert() {
expect("(");
Expr E = readExpr();
expect(",");
@@ -617,12 +679,14 @@ uint32_t ScriptParser::readFill() {
return V;
}
-// Reads an expression and/or the special directive "(NOLOAD)" for an
-// output section definition.
+// Reads an expression and/or the special directive for an output
+// section definition. Directive is one of following: "(NOLOAD)",
+// "(COPY)", "(INFO)" or "(OVERLAY)".
//
// An output section name can be followed by an address expression
-// and/or by "(NOLOAD)". This grammar is not LL(1) because "(" can be
-// interpreted as either the beginning of some expression or "(NOLOAD)".
+// and/or directive. This grammar is not LL(1) because "(" can be
+// interpreted as either the beginning of some expression or beginning
+// of directive.
//
// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
// https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
@@ -633,6 +697,11 @@ void ScriptParser::readSectionAddressType(OutputSection *Cmd) {
Cmd->Noload = true;
return;
}
+ if (consume("COPY") || consume("INFO") || consume("OVERLAY")) {
+ expect(")");
+ Cmd->NonAlloc = true;
+ return;
+ }
Cmd->AddrExpr = readExpr();
expect(")");
} else {
@@ -657,10 +726,23 @@ static Expr checkAlignment(Expr E, std::string &Loc) {
};
}
+OutputSection *ScriptParser::readOverlaySectionDescription() {
+ OutputSection *Cmd =
+ Script->createOutputSection(next(), getCurrentLocation());
+ Cmd->InOverlay = true;
+ expect("{");
+ while (!errorCount() && !consume("}"))
+ Cmd->SectionCommands.push_back(readInputSectionRules(next()));
+ Cmd->Phdrs = readOutputSectionPhdrs();
+ return Cmd;
+}
+
OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
OutputSection *Cmd =
Script->createOutputSection(OutSec, getCurrentLocation());
+ size_t SymbolsReferenced = Script->ReferencedSymbols.size();
+
if (peek() != ":")
readSectionAddressType(Cmd);
expect(":");
@@ -684,13 +766,10 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
StringRef Tok = next();
if (Tok == ";") {
// Empty commands are allowed. Do nothing here.
- } else if (SymbolAssignment *Assign = readProvideOrAssignment(Tok)) {
+ } else if (SymbolAssignment *Assign = readAssignment(Tok)) {
Cmd->SectionCommands.push_back(Assign);
} else if (ByteCommand *Data = readByteCommand(Tok)) {
Cmd->SectionCommands.push_back(Data);
- } else if (Tok == "ASSERT") {
- Cmd->SectionCommands.push_back(readAssert());
- expect(";");
} else if (Tok == "CONSTRUCTORS") {
// CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
// by name. This is for very old file formats such as ECOFF/XCOFF.
@@ -727,6 +806,8 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
// Consume optional comma following output section command.
consume(",");
+ if (Script->ReferencedSymbols.size() > SymbolsReferenced)
+ Cmd->ExpressionsUseSymbols = true;
return Cmd;
}
@@ -749,30 +830,39 @@ uint32_t ScriptParser::parseFill(StringRef Tok) {
SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) {
expect("(");
- SymbolAssignment *Cmd = readAssignment(next());
+ SymbolAssignment *Cmd = readSymbolAssignment(next());
Cmd->Provide = Provide;
Cmd->Hidden = Hidden;
expect(")");
- expect(";");
return Cmd;
}
-SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
+SymbolAssignment *ScriptParser::readAssignment(StringRef Tok) {
+ // Assert expression returns Dot, so this is equal to ".=."
+ if (Tok == "ASSERT")
+ return make<SymbolAssignment>(".", readAssert(), getCurrentLocation());
+
+ size_t OldPos = Pos;
SymbolAssignment *Cmd = nullptr;
- if (peek() == "=" || peek() == "+=") {
- Cmd = readAssignment(Tok);
- expect(";");
- } else if (Tok == "PROVIDE") {
+ if (peek() == "=" || peek() == "+=")
+ Cmd = readSymbolAssignment(Tok);
+ else if (Tok == "PROVIDE")
Cmd = readProvideHidden(true, false);
- } else if (Tok == "HIDDEN") {
+ else if (Tok == "HIDDEN")
Cmd = readProvideHidden(false, true);
- } else if (Tok == "PROVIDE_HIDDEN") {
+ else if (Tok == "PROVIDE_HIDDEN")
Cmd = readProvideHidden(true, true);
+
+ if (Cmd) {
+ Cmd->CommandString =
+ Tok.str() + " " +
+ llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");
+ expect(";");
}
return Cmd;
}
-SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
+SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {
StringRef Op = next();
assert(Op == "=" || Op == "+=");
Expr E = readExpr();
@@ -795,15 +885,31 @@ Expr ScriptParser::readExpr() {
return E;
}
-static Expr combine(StringRef Op, Expr L, Expr R) {
+Expr ScriptParser::combine(StringRef Op, Expr L, Expr R) {
if (Op == "+")
return [=] { return add(L(), R()); };
if (Op == "-")
return [=] { return sub(L(), R()); };
if (Op == "*")
- return [=] { return mul(L(), R()); };
- if (Op == "/")
- return [=] { return div(L(), R()); };
+ return [=] { return L().getValue() * R().getValue(); };
+ if (Op == "/") {
+ std::string Loc = getCurrentLocation();
+ return [=]() -> uint64_t {
+ if (uint64_t RV = R().getValue())
+ return L().getValue() / RV;
+ error(Loc + ": division by zero");
+ return 0;
+ };
+ }
+ if (Op == "%") {
+ std::string Loc = getCurrentLocation();
+ return [=]() -> uint64_t {
+ if (uint64_t RV = R().getValue())
+ return L().getValue() % RV;
+ error(Loc + ": modulo by zero");
+ return 0;
+ };
+ }
if (Op == "<<")
return [=] { return L().getValue() << R().getValue(); };
if (Op == ">>")
@@ -820,6 +926,10 @@ static Expr combine(StringRef Op, Expr L, Expr R) {
return [=] { return L().getValue() == R().getValue(); };
if (Op == "!=")
return [=] { return L().getValue() != R().getValue(); };
+ if (Op == "||")
+ return [=] { return L().getValue() || R().getValue(); };
+ if (Op == "&&")
+ return [=] { return L().getValue() && R().getValue(); };
if (Op == "&")
return [=] { return bitAnd(L(), R()); };
if (Op == "|")
@@ -873,20 +983,13 @@ Expr ScriptParser::readConstant() {
if (S == "MAXPAGESIZE")
return [] { return Config->MaxPageSize; };
setError("unknown constant: " + S);
- return {};
+ return [] { return 0; };
}
// Parses Tok as an integer. It recognizes hexadecimal (prefixed with
// "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
// have "K" (Ki) or "M" (Mi) suffixes.
static Optional<uint64_t> parseInt(StringRef Tok) {
- // Negative number
- if (Tok.startswith("-")) {
- if (Optional<uint64_t> Val = parseInt(Tok.substr(1)))
- return -*Val;
- return None;
- }
-
// Hexadecimal
uint64_t Val;
if (Tok.startswith_lower("0x")) {
@@ -925,7 +1028,13 @@ ByteCommand *ScriptParser::readByteCommand(StringRef Tok) {
.Default(-1);
if (Size == -1)
return nullptr;
- return make<ByteCommand>(readParenExpr(), Size);
+
+ size_t OldPos = Pos;
+ Expr E = readParenExpr();
+ std::string CommandString =
+ Tok.str() + " " +
+ llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");
+ return make<ByteCommand>(E, Size, CommandString);
}
StringRef ScriptParser::readParenLiteral() {
@@ -1006,7 +1115,7 @@ Expr ScriptParser::readPrimary() {
};
}
if (Tok == "ASSERT")
- return readAssertExpr();
+ return readAssert();
if (Tok == "CONSTANT")
return readConstant();
if (Tok == "DATA_SEGMENT_ALIGN") {
@@ -1043,8 +1152,10 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "LENGTH") {
StringRef Name = readParenLiteral();
- if (Script->MemoryRegions.count(Name) == 0)
+ if (Script->MemoryRegions.count(Name) == 0) {
setError("memory region not defined: " + Name);
+ return [] { return 0; };
+ }
return [=] { return Script->MemoryRegions[Name]->Length; };
}
if (Tok == "LOADADDR") {
@@ -1055,10 +1166,22 @@ Expr ScriptParser::readPrimary() {
return Cmd->getLMA();
};
}
+ if (Tok == "MAX" || Tok == "MIN") {
+ expect("(");
+ Expr A = readExpr();
+ expect(",");
+ Expr B = readExpr();
+ expect(")");
+ if (Tok == "MIN")
+ return [=] { return std::min(A().getValue(), B().getValue()); };
+ return [=] { return std::max(A().getValue(), B().getValue()); };
+ }
if (Tok == "ORIGIN") {
StringRef Name = readParenLiteral();
- if (Script->MemoryRegions.count(Name) == 0)
+ if (Script->MemoryRegions.count(Name) == 0) {
setError("memory region not defined: " + Name);
+ return [] { return 0; };
+ }
return [=] { return Script->MemoryRegions[Name]->Origin; };
}
if (Tok == "SEGMENT_START") {
@@ -1240,6 +1363,9 @@ ScriptParser::readSymbols() {
// Reads an "extern C++" directive, e.g.,
// "extern "C++" { ns::*; "f(int, double)"; };"
+//
+// The last semicolon is optional. E.g. this is OK:
+// "extern "C++" { ns::*; "f(int, double)" };"
std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
StringRef Tok = next();
bool IsCXX = Tok == "\"C++\"";
@@ -1252,6 +1378,8 @@ std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
StringRef Tok = next();
bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok);
Ret.push_back({unquote(Tok), IsCXX, HasWildcard});
+ if (consume("}"))
+ return Ret;
expect(";");
}
@@ -1291,11 +1419,10 @@ void ScriptParser::readMemory() {
uint64_t Length = readMemoryAssignment("LENGTH", "len", "l");
// Add the memory region to the region map.
- if (Script->MemoryRegions.count(Name))
- setError("region '" + Name + "' already defined");
MemoryRegion *MR =
make<MemoryRegion>(Name, Origin, Length, Flags, NegFlags);
- Script->MemoryRegions[Name] = MR;
+ if (!Script->MemoryRegions.insert({Name, MR}).second)
+ setError("region '" + Name + "' already defined");
}
}
diff --git a/contrib/llvm/tools/lld/ELF/Strings.cpp b/contrib/llvm/tools/lld/ELF/Strings.cpp
deleted file mode 100644
index 0ef33a14bc3d..000000000000
--- a/contrib/llvm/tools/lld/ELF/Strings.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- Strings.cpp -------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Strings.h"
-#include "Config.h"
-#include "lld/Common/ErrorHandler.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Demangle/Demangle.h"
-#include <algorithm>
-#include <cstring>
-
-using namespace llvm;
-using namespace lld;
-using namespace lld::elf;
-
-StringMatcher::StringMatcher(ArrayRef<StringRef> Pat) {
- for (StringRef S : Pat) {
- Expected<GlobPattern> Pat = GlobPattern::create(S);
- if (!Pat)
- error(toString(Pat.takeError()));
- else
- Patterns.push_back(*Pat);
- }
-}
-
-bool StringMatcher::match(StringRef S) const {
- for (const GlobPattern &Pat : Patterns)
- if (Pat.match(S))
- return true;
- return false;
-}
-
-// Converts a hex string (e.g. "deadbeef") to a vector.
-std::vector<uint8_t> elf::parseHex(StringRef S) {
- std::vector<uint8_t> Hex;
- while (!S.empty()) {
- StringRef B = S.substr(0, 2);
- S = S.substr(2);
- uint8_t H;
- if (!to_integer(B, H, 16)) {
- error("not a hexadecimal value: " + B);
- return {};
- }
- Hex.push_back(H);
- }
- return Hex;
-}
-
-// Returns true if S is valid as a C language identifier.
-bool elf::isValidCIdentifier(StringRef S) {
- return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&
- std::all_of(S.begin() + 1, S.end(),
- [](char C) { return C == '_' || isAlnum(C); });
-}
diff --git a/contrib/llvm/tools/lld/ELF/Strings.h b/contrib/llvm/tools/lld/ELF/Strings.h
deleted file mode 100644
index 5009df65f4c1..000000000000
--- a/contrib/llvm/tools/lld/ELF/Strings.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//===- Strings.h ------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_STRINGS_H
-#define LLD_ELF_STRINGS_H
-
-#include "lld/Common/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/GlobPattern.h"
-#include <vector>
-
-namespace lld {
-namespace elf {
-
-std::vector<uint8_t> parseHex(StringRef S);
-bool isValidCIdentifier(StringRef S);
-
-// This is a lazy version of StringRef. String size is computed lazily
-// when it is needed. It is more efficient than StringRef to instantiate
-// if you have a string whose size is unknown.
-//
-// ELF string tables contain a lot of null-terminated strings.
-// Most of them are not necessary for the linker because they are names
-// of local symbols and the linker doesn't use local symbol names for
-// name resolution. So, we use this class to represents strings read
-// from string tables.
-class StringRefZ {
-public:
- StringRefZ() : Start(nullptr), Size(0) {}
- StringRefZ(const char *S, size_t Size) : Start(S), Size(Size) {}
-
- /*implicit*/ StringRefZ(const char *S) : Start(S), Size(-1) {}
-
- /*implicit*/ StringRefZ(llvm::StringRef S)
- : Start(S.data()), Size(S.size()) {}
-
- operator llvm::StringRef() const {
- if (Size == (size_t)-1)
- Size = strlen(Start);
- return {Start, Size};
- }
-
-private:
- const char *Start;
- mutable size_t Size;
-};
-
-// This class represents multiple glob patterns.
-class StringMatcher {
-public:
- StringMatcher() = default;
- explicit StringMatcher(ArrayRef<StringRef> Pat);
-
- bool match(StringRef S) const;
-
-private:
- std::vector<llvm::GlobPattern> Patterns;
-};
-
-inline ArrayRef<uint8_t> toArrayRef(StringRef S) {
- return {(const uint8_t *)S.data(), S.size()};
-}
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/contrib/llvm/tools/lld/ELF/SymbolTable.cpp b/contrib/llvm/tools/lld/ELF/SymbolTable.cpp
index c41e2b2de748..1f5a84ec2c7d 100644
--- a/contrib/llvm/tools/lld/ELF/SymbolTable.cpp
+++ b/contrib/llvm/tools/lld/ELF/SymbolTable.cpp
@@ -38,7 +38,7 @@ static InputFile *getFirstElf() {
return ObjectFiles[0];
if (!SharedFiles.empty())
return SharedFiles[0];
- return nullptr;
+ return BitcodeFiles[0];
}
// All input object files must be for the same architecture
@@ -82,6 +82,7 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) {
// Lazy object file
if (auto *F = dyn_cast<LazyObjFile>(File)) {
+ LazyObjFiles.push_back(F);
F->parse<ELFT>();
return;
}
@@ -117,7 +118,7 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) {
// not in native object file format but in the LLVM bitcode format.
// This function compiles bitcode files into a few big native files
// using LLVM functions and replaces bitcode symbols with the results.
-// Because all bitcode files that consist of a program are passed
+// Because all bitcode files that the program consists of are passed
// to the compiler at once, it can do whole-program optimization.
template <class ELFT> void SymbolTable::addCombinedLTOObject() {
if (BitcodeFiles.empty())
@@ -157,6 +158,12 @@ template <class ELFT> void SymbolTable::addSymbolWrap(StringRef Name) {
Symbol *Sym = find(Name);
if (!Sym)
return;
+
+ // Do not wrap the same symbol twice.
+ for (const WrappedSymbol &S : WrappedSymbols)
+ if (S.Sym == Sym)
+ return;
+
Symbol *Real = addUndefined<ELFT>(Saver.save("__real_" + Name));
Symbol *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name));
WrappedSymbols.push_back({Sym, Real, Wrap});
@@ -189,7 +196,7 @@ void SymbolTable::applySymbolWrap() {
// First, make a copy of __real_sym.
Symbol *Real = nullptr;
if (W.Real->isDefined()) {
- Real = (Symbol *)make<SymbolUnion>();
+ Real = reinterpret_cast<Symbol *>(make<SymbolUnion>());
memcpy(Real, W.Real, sizeof(SymbolUnion));
}
@@ -237,8 +244,7 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Symbol *Sym;
if (IsNew) {
- Sym = (Symbol *)make<SymbolUnion>();
- Sym->InVersionScript = false;
+ Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
@@ -297,26 +303,88 @@ Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding,
uint8_t Visibility = getVisibility(StOther);
std::tie(S, WasInserted) =
insert(Name, Type, Visibility, CanOmitFromDynSym, File);
+
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
if (WasInserted || (isa<SharedSymbol>(S) && Visibility != STV_DEFAULT)) {
replaceSymbol<Undefined>(S, File, Name, Binding, StOther, Type);
return S;
}
+
if (S->isShared() || S->isLazy() || (S->isUndefined() && Binding != STB_WEAK))
S->Binding = Binding;
- if (Binding != STB_WEAK) {
+
+ if (!Config->GcSections && Binding != STB_WEAK)
if (auto *SS = dyn_cast<SharedSymbol>(S))
- if (!Config->GcSections)
- SS->getFile<ELFT>().IsNeeded = true;
- }
- if (auto *L = dyn_cast<Lazy>(S)) {
+ SS->getFile<ELFT>().IsNeeded = true;
+
+ if (S->isLazy()) {
// An undefined weak will not fetch archive members. See comment on Lazy in
// Symbols.h for the details.
- if (Binding == STB_WEAK)
- L->Type = Type;
- else if (InputFile *F = L->fetch())
- addFile<ELFT>(F);
+ if (Binding == STB_WEAK) {
+ S->Type = Type;
+ return S;
+ }
+
+ // Do extra check for --warn-backrefs.
+ //
+ // --warn-backrefs is an option to prevent an undefined reference from
+ // fetching an archive member written earlier in the command line. It can be
+ // used to keep compatibility with GNU linkers to some degree.
+ // I'll explain the feature and why you may find it useful in this comment.
+ //
+ // lld's symbol resolution semantics is more relaxed than traditional Unix
+ // linkers. For example,
+ //
+ // ld.lld foo.a bar.o
+ //
+ // succeeds even if bar.o contains an undefined symbol that has to be
+ // resolved by some object file in foo.a. Traditional Unix linkers don't
+ // allow this kind of backward reference, as they visit each file only once
+ // from left to right in the command line while resolving all undefined
+ // symbols at the moment of visiting.
+ //
+ // In the above case, since there's no undefined symbol when a linker visits
+ // foo.a, no files are pulled out from foo.a, and because the linker forgets
+ // about foo.a after visiting, it can't resolve undefined symbols in bar.o
+ // that could have been resolved otherwise.
+ //
+ // That lld accepts more relaxed form means that (besides it'd make more
+ // sense) you can accidentally write a command line or a build file that
+ // works only with lld, even if you have a plan to distribute it to wider
+ // users who may be using GNU linkers. With --warn-backrefs, you can detect
+ // a library order that doesn't work with other Unix linkers.
+ //
+ // The option is also useful to detect cyclic dependencies between static
+ // archives. Again, lld accepts
+ //
+ // ld.lld foo.a bar.a
+ //
+ // even if foo.a and bar.a depend on each other. With --warn-backrefs, it is
+ // handled as an error.
+ //
+ // Here is how the option works. We assign a group ID to each file. A file
+ // with a smaller group ID can pull out object files from an archive file
+ // with an equal or greater group ID. Otherwise, it is a reverse dependency
+ // and an error.
+ //
+ // A file outside --{start,end}-group gets a fresh ID when instantiated. All
+ // files within the same --{start,end}-group get the same group ID. E.g.
+ //
+ // ld.lld A B --start-group C D --end-group E
+ //
+ // A forms group 0. B form group 1. C and D (including their member object
+ // files) form group 2. E forms group 3. I think that you can see how this
+ // group assignment rule simulates the traditional linker's semantics.
+ bool Backref =
+ Config->WarnBackrefs && File && S->File->GroupId < File->GroupId;
+ fetchLazy<ELFT>(S);
+
+ // We don't report backward references to weak symbols as they can be
+ // overridden later.
+ if (Backref && S->Binding != STB_WEAK)
+ warn("backward reference detected: " + Name + " in " + toString(File) +
+ " refers to " + toString(S->File));
}
return S;
}
@@ -384,7 +452,11 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
bool WasInserted;
std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther),
/*CanOmitFromDynSym*/ false, &File);
+
int Cmp = compareDefined(S, WasInserted, Binding, N);
+ if (Cmp < 0)
+ return S;
+
if (Cmp > 0) {
auto *Bss = make<BssSection>("COMMON", Size, Alignment);
Bss->File = &File;
@@ -392,45 +464,43 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
InputSections.push_back(Bss);
replaceSymbol<Defined>(S, &File, N, Binding, StOther, Type, 0, Size, Bss);
- } else if (Cmp == 0) {
- auto *D = cast<Defined>(S);
- auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
- if (!Bss) {
- // Non-common symbols take precedence over common symbols.
- if (Config->WarnCommon)
- warn("common " + S->getName() + " is overridden");
- return S;
- }
+ return S;
+ }
+ auto *D = cast<Defined>(S);
+ auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
+ if (!Bss) {
+ // Non-common symbols take precedence over common symbols.
if (Config->WarnCommon)
- warn("multiple common of " + D->getName());
+ warn("common " + S->getName() + " is overridden");
+ return S;
+ }
- Bss->Alignment = std::max(Bss->Alignment, Alignment);
- if (Size > Bss->Size) {
- D->File = Bss->File = &File;
- D->Size = Bss->Size = Size;
- }
+ if (Config->WarnCommon)
+ warn("multiple common of " + D->getName());
+
+ Bss->Alignment = std::max(Bss->Alignment, Alignment);
+ if (Size > Bss->Size) {
+ D->File = Bss->File = &File;
+ D->Size = Bss->Size = Size;
}
return S;
}
-static void warnOrError(const Twine &Msg) {
- if (Config->AllowMultipleDefinition)
- warn(Msg);
- else
- error(Msg);
-}
-
static void reportDuplicate(Symbol *Sym, InputFile *NewFile) {
- warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
- toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
+ if (!Config->AllowMultipleDefinition)
+ error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
+ toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
}
-static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec,
- uint64_t ErrOffset) {
+static void reportDuplicate(Symbol *Sym, InputFile *NewFile,
+ InputSectionBase *ErrSec, uint64_t ErrOffset) {
+ if (Config->AllowMultipleDefinition)
+ return;
+
Defined *D = cast<Defined>(Sym);
if (!D->Section || !ErrSec) {
- reportDuplicate(Sym, ErrSec ? ErrSec->File : nullptr);
+ reportDuplicate(Sym, NewFile);
return;
}
@@ -454,7 +524,7 @@ static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec,
if (!Src2.empty())
Msg += Src2 + "\n>>> ";
Msg += Obj2;
- warnOrError(Msg);
+ error(Msg);
}
Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
@@ -470,7 +540,8 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
replaceSymbol<Defined>(S, File, Name, Binding, StOther, Type, Value, Size,
Section);
else if (Cmp == 0)
- reportDuplicate(S, dyn_cast_or_null<InputSectionBase>(Section), Value);
+ reportDuplicate(S, File, dyn_cast_or_null<InputSectionBase>(Section),
+ Value);
return S;
}
@@ -491,8 +562,8 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File,
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
- if (WasInserted || ((S->isUndefined() || S->isLazy()) &&
- S->getVisibility() == STV_DEFAULT)) {
+ if (WasInserted ||
+ ((S->isUndefined() || S->isLazy()) && S->Visibility == STV_DEFAULT)) {
uint8_t Binding = S->Binding;
bool WasUndefined = S->isUndefined();
replaceSymbol<SharedSymbol>(S, File, Name, Sym.getBinding(), Sym.st_other,
@@ -531,85 +602,58 @@ Symbol *SymbolTable::find(StringRef Name) {
return SymVector[It->second];
}
-template <class ELFT>
-Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &F,
- const object::Archive::Symbol Sym) {
+// This is used to handle lazy symbols. May replace existent
+// symbol with lazy version or request to Fetch it.
+template <class ELFT, typename LazyT, typename... ArgT>
+static void replaceOrFetchLazy(StringRef Name, InputFile &File,
+ llvm::function_ref<InputFile *()> Fetch,
+ ArgT &&... Arg) {
Symbol *S;
bool WasInserted;
- std::tie(S, WasInserted) = insert(Name);
+ std::tie(S, WasInserted) = Symtab->insert(Name);
if (WasInserted) {
- replaceSymbol<LazyArchive>(S, F, Sym, Symbol::UnknownType);
- return S;
+ replaceSymbol<LazyT>(S, File, Symbol::UnknownType,
+ std::forward<ArgT>(Arg)...);
+ return;
}
if (!S->isUndefined())
- return S;
+ return;
// An undefined weak will not fetch archive members. See comment on Lazy in
// Symbols.h for the details.
if (S->isWeak()) {
- replaceSymbol<LazyArchive>(S, F, Sym, S->Type);
+ replaceSymbol<LazyT>(S, File, S->Type, std::forward<ArgT>(Arg)...);
S->Binding = STB_WEAK;
- return S;
+ return;
}
- std::pair<MemoryBufferRef, uint64_t> MBInfo = F.getMember(&Sym);
- if (!MBInfo.first.getBuffer().empty())
- addFile<ELFT>(createObjectFile(MBInfo.first, F.getName(), MBInfo.second));
- return S;
+
+ if (InputFile *F = Fetch())
+ Symtab->addFile<ELFT>(F);
}
template <class ELFT>
-void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) {
- Symbol *S;
- bool WasInserted;
- std::tie(S, WasInserted) = insert(Name);
- if (WasInserted) {
- replaceSymbol<LazyObject>(S, Obj, Name, Symbol::UnknownType);
- return;
- }
- if (!S->isUndefined())
- return;
-
- // See comment for addLazyArchive above.
- if (S->isWeak())
- replaceSymbol<LazyObject>(S, Obj, Name, S->Type);
- else if (InputFile *F = Obj.fetch())
- addFile<ELFT>(F);
-}
-
-// If we already saw this symbol, force loading its file.
-template <class ELFT> void SymbolTable::fetchIfLazy(StringRef Name) {
- if (Symbol *B = find(Name)) {
- // Mark the symbol not to be eliminated by LTO
- // even if it is a bitcode symbol.
- B->IsUsedInRegularObj = true;
- if (auto *L = dyn_cast<Lazy>(B))
- if (InputFile *File = L->fetch())
- addFile<ELFT>(File);
- }
+void SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &F,
+ const object::Archive::Symbol Sym) {
+ replaceOrFetchLazy<ELFT, LazyArchive>(Name, F, [&]() { return F.fetch(Sym); },
+ Sym);
}
-// This function takes care of the case in which shared libraries depend on
-// the user program (not the other way, which is usual). Shared libraries
-// may have undefined symbols, expecting that the user program provides
-// the definitions for them. An example is BSD's __progname symbol.
-// We need to put such symbols to the main program's .dynsym so that
-// shared libraries can find them.
-// Except this, we ignore undefined symbols in DSOs.
-template <class ELFT> void SymbolTable::scanShlibUndefined() {
- for (InputFile *F : SharedFiles) {
- for (StringRef U : cast<SharedFile<ELFT>>(F)->getUndefinedSymbols()) {
- Symbol *Sym = find(U);
- if (!Sym || !Sym->isDefined())
- continue;
- Sym->ExportDynamic = true;
+template <class ELFT>
+void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) {
+ replaceOrFetchLazy<ELFT, LazyObject>(Name, Obj, [&]() { return Obj.fetch(); },
+ Name);
+}
- // If -dynamic-list is given, the default version is set to
- // VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym.
- // Set to VER_NDX_GLOBAL so the symbol will be handled as if it were
- // specified by -dynamic-list.
- Sym->VersionId = VER_NDX_GLOBAL;
- }
+template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) {
+ if (auto *S = dyn_cast<LazyArchive>(Sym)) {
+ if (InputFile *File = S->fetch())
+ addFile<ELFT>(File);
+ return;
}
+
+ auto *S = cast<LazyObject>(Sym);
+ if (InputFile *File = cast<LazyObjFile>(S->File)->fetch())
+ addFile<ELFT>(File);
}
// Initialize DemangledSyms with a map from demangled symbols to symbol
@@ -708,7 +752,7 @@ void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
// Get a list of symbols which we need to assign the version to.
std::vector<Symbol *> Syms = findByVersion(Ver);
if (Syms.empty()) {
- if (Config->NoUndefinedVersion)
+ if (!Config->UndefinedVersion)
error("version script assignment of '" + VersionName + "' to symbol '" +
Ver.Name + "' failed: symbol not defined");
return;
@@ -722,10 +766,10 @@ void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
if (Sym->getName().contains('@'))
continue;
- if (Sym->InVersionScript)
- warn("duplicate symbol '" + Ver.Name + "' in version script");
+ if (Sym->VersionId != Config->DefaultSymbolVersion &&
+ Sym->VersionId != VersionId)
+ error("duplicate symbol '" + Ver.Name + "' in version script");
Sym->VersionId = VersionId;
- Sym->InVersionScript = true;
}
}
@@ -773,6 +817,11 @@ void SymbolTable::scanVersionScript() {
Sym->parseSymbolVersion();
}
+template void SymbolTable::addFile<ELF32LE>(InputFile *);
+template void SymbolTable::addFile<ELF32BE>(InputFile *);
+template void SymbolTable::addFile<ELF64LE>(InputFile *);
+template void SymbolTable::addFile<ELF64BE>(InputFile *);
+
template void SymbolTable::addSymbolWrap<ELF32LE>(StringRef);
template void SymbolTable::addSymbolWrap<ELF32BE>(StringRef);
template void SymbolTable::addSymbolWrap<ELF64LE>(StringRef);
@@ -797,16 +846,16 @@ template void SymbolTable::addCombinedLTOObject<ELF32BE>();
template void SymbolTable::addCombinedLTOObject<ELF64LE>();
template void SymbolTable::addCombinedLTOObject<ELF64BE>();
-template Symbol *
+template void
SymbolTable::addLazyArchive<ELF32LE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
-template Symbol *
+template void
SymbolTable::addLazyArchive<ELF32BE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
-template Symbol *
+template void
SymbolTable::addLazyArchive<ELF64LE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
-template Symbol *
+template void
SymbolTable::addLazyArchive<ELF64BE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
@@ -815,6 +864,11 @@ template void SymbolTable::addLazyObject<ELF32BE>(StringRef, LazyObjFile &);
template void SymbolTable::addLazyObject<ELF64LE>(StringRef, LazyObjFile &);
template void SymbolTable::addLazyObject<ELF64BE>(StringRef, LazyObjFile &);
+template void SymbolTable::fetchLazy<ELF32LE>(Symbol *);
+template void SymbolTable::fetchLazy<ELF32BE>(Symbol *);
+template void SymbolTable::fetchLazy<ELF64LE>(Symbol *);
+template void SymbolTable::fetchLazy<ELF64BE>(Symbol *);
+
template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> &,
const typename ELF32LE::Sym &,
uint32_t Alignment, uint32_t);
@@ -827,13 +881,3 @@ template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> &,
template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> &,
const typename ELF64BE::Sym &,
uint32_t Alignment, uint32_t);
-
-template void SymbolTable::fetchIfLazy<ELF32LE>(StringRef);
-template void SymbolTable::fetchIfLazy<ELF32BE>(StringRef);
-template void SymbolTable::fetchIfLazy<ELF64LE>(StringRef);
-template void SymbolTable::fetchIfLazy<ELF64BE>(StringRef);
-
-template void SymbolTable::scanShlibUndefined<ELF32LE>();
-template void SymbolTable::scanShlibUndefined<ELF32BE>();
-template void SymbolTable::scanShlibUndefined<ELF64LE>();
-template void SymbolTable::scanShlibUndefined<ELF64BE>();
diff --git a/contrib/llvm/tools/lld/ELF/SymbolTable.h b/contrib/llvm/tools/lld/ELF/SymbolTable.h
index e7341b05baf5..5e6d44dfe4f9 100644
--- a/contrib/llvm/tools/lld/ELF/SymbolTable.h
+++ b/contrib/llvm/tools/lld/ELF/SymbolTable.h
@@ -12,7 +12,7 @@
#include "InputFiles.h"
#include "LTO.h"
-#include "Strings.h"
+#include "lld/Common/Strings.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseMap.h"
@@ -60,8 +60,8 @@ public:
uint32_t VerdefIndex);
template <class ELFT>
- Symbol *addLazyArchive(StringRef Name, ArchiveFile &F,
- const llvm::object::Archive::Symbol S);
+ void addLazyArchive(StringRef Name, ArchiveFile &F,
+ const llvm::object::Archive::Symbol S);
template <class ELFT> void addLazyObject(StringRef Name, LazyObjFile &Obj);
@@ -77,8 +77,8 @@ public:
uint8_t Visibility, bool CanOmitFromDynSym,
InputFile *File);
- template <class ELFT> void fetchIfLazy(StringRef Name);
- template <class ELFT> void scanShlibUndefined();
+ template <class ELFT> void fetchLazy(Symbol *Sym);
+
void scanVersionScript();
Symbol *find(StringRef Name);
@@ -90,7 +90,6 @@ public:
private:
std::vector<Symbol *> findByVersion(SymbolVersion Ver);
std::vector<Symbol *> findAllByVersion(SymbolVersion Ver);
- void defsym(Symbol *Dst, Symbol *Src);
llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms();
void handleAnonymousVersion();
diff --git a/contrib/llvm/tools/lld/ELF/Symbols.cpp b/contrib/llvm/tools/lld/ELF/Symbols.cpp
index 13a91aab80bb..4243cb1e80ef 100644
--- a/contrib/llvm/tools/lld/ELF/Symbols.cpp
+++ b/contrib/llvm/tools/lld/ELF/Symbols.cpp
@@ -14,7 +14,6 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"
-
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
@@ -39,6 +38,7 @@ Defined *ElfSym::GlobalOffsetTable;
Defined *ElfSym::MipsGp;
Defined *ElfSym::MipsGpDisp;
Defined *ElfSym::MipsLocalGp;
+Defined *ElfSym::RelaIpltEnd;
static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
switch (Sym.kind()) {
@@ -58,6 +58,7 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
return D.Value;
IS = IS->Repl;
+
uint64_t Offset = D.Value;
// An object in an SHF_MERGE section might be referenced via a
@@ -76,8 +77,6 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
Addend = 0;
}
- const OutputSection *OutSec = IS->getOutputSection();
-
// In the typical case, this is actually very simple and boils
// down to adding together 3 numbers:
// 1. The address of the output section.
@@ -88,7 +87,7 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
// If you understand the data structures involved with this next
// line (and how they get built), then you have a pretty good
// understanding of the linker.
- uint64_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset);
+ uint64_t VA = IS->getVA(Offset);
if (D.isTls() && !Config->Relocatable) {
if (!Out::TlsPhdr)
@@ -98,20 +97,12 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
}
return VA;
}
- case Symbol::SharedKind: {
- auto &SS = cast<SharedSymbol>(Sym);
- if (SS.CopyRelSec)
- return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff;
- if (SS.NeedsPltAddr)
- return Sym.getPltVA();
- return 0;
- }
+ case Symbol::SharedKind:
case Symbol::UndefinedKind:
return 0;
case Symbol::LazyArchiveKind:
case Symbol::LazyObjectKind:
- assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer");
- return 0;
+ llvm_unreachable("lazy symbol reached writer");
}
llvm_unreachable("invalid symbol kind");
}
@@ -134,22 +125,26 @@ uint64_t Symbol::getGotPltVA() const {
}
uint64_t Symbol::getGotPltOffset() const {
- return GotPltIndex * Target->GotPltEntrySize;
+ if (IsInIgot)
+ return PltIndex * Target->GotPltEntrySize;
+ return (PltIndex + Target->GotPltHeaderEntriesNum) * Target->GotPltEntrySize;
}
uint64_t Symbol::getPltVA() const {
if (this->IsInIplt)
return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize;
- return InX::Plt->getVA() + Target->PltHeaderSize +
- PltIndex * Target->PltEntrySize;
+ return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex);
+}
+
+uint64_t Symbol::getPltOffset() const {
+ assert(!this->IsInIplt);
+ return Target->getPltEntryOffset(PltIndex);
}
uint64_t Symbol::getSize() const {
if (const auto *DR = dyn_cast<Defined>(this))
return DR->Size;
- if (const auto *S = dyn_cast<SharedSymbol>(this))
- return S->Size;
- return 0;
+ return cast<SharedSymbol>(this)->Size;
}
OutputSection *Symbol::getOutputSection() const {
@@ -158,13 +153,6 @@ OutputSection *Symbol::getOutputSection() const {
return Sec->Repl->getOutputSection();
return nullptr;
}
-
- if (auto *S = dyn_cast<SharedSymbol>(this)) {
- if (S->CopyRelSec)
- return S->CopyRelSec->getParent();
- return nullptr;
- }
-
return nullptr;
}
@@ -180,7 +168,7 @@ void Symbol::parseSymbolVersion() {
return;
// Truncate the symbol name so that it doesn't include the version string.
- Name = {S.data(), Pos};
+ NameSize = Pos;
// If this is not in this DSO, it is not a definition.
if (!isDefined())
@@ -206,33 +194,15 @@ void Symbol::parseSymbolVersion() {
// It is an error if the specified version is not defined.
// Usually version script is not provided when linking executable,
// but we may still want to override a versioned symbol from DSO,
- // so we do not report error in this case.
- if (Config->Shared)
+ // so we do not report error in this case. We also do not error
+ // if the symbol has a local version as it won't be in the dynamic
+ // symbol table.
+ if (Config->Shared && VersionId != VER_NDX_LOCAL)
error(toString(File) + ": symbol " + S + " has undefined version " +
Verstr);
}
-InputFile *Lazy::fetch() {
- if (auto *S = dyn_cast<LazyArchive>(this))
- return S->fetch();
- return cast<LazyObject>(this)->fetch();
-}
-
-ArchiveFile &LazyArchive::getFile() { return *cast<ArchiveFile>(File); }
-
-InputFile *LazyArchive::fetch() {
- std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile().getMember(&Sym);
-
- // getMember returns an empty buffer if the member was already
- // read from the library.
- if (MBInfo.first.getBuffer().empty())
- return nullptr;
- return createObjectFile(MBInfo.first, getFile().getName(), MBInfo.second);
-}
-
-LazyObjFile &LazyObject::getFile() { return *cast<LazyObjFile>(File); }
-
-InputFile *LazyObject::fetch() { return getFile().fetch(); }
+InputFile *LazyArchive::fetch() { return cast<ArchiveFile>(File)->fetch(Sym); }
uint8_t Symbol::computeBinding() const {
if (Config->Relocatable)
@@ -241,7 +211,7 @@ uint8_t Symbol::computeBinding() const {
return STB_LOCAL;
if (VersionId == VER_NDX_LOCAL && isDefined())
return STB_LOCAL;
- if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
+ if (!Config->GnuUnique && Binding == STB_GNU_UNIQUE)
return STB_GLOBAL;
return Binding;
}
@@ -273,6 +243,27 @@ void elf::printTraceSymbol(Symbol *Sym) {
message(toString(Sym->File) + S + Sym->getName());
}
+void elf::warnUnorderableSymbol(const Symbol *Sym) {
+ if (!Config->WarnSymbolOrdering)
+ return;
+
+ const InputFile *File = Sym->File;
+ auto *D = dyn_cast<Defined>(Sym);
+
+ auto Warn = [&](StringRef S) { warn(toString(File) + S + Sym->getName()); };
+
+ if (Sym->isUndefined())
+ Warn(": unable to order undefined symbol: ");
+ else if (Sym->isShared())
+ Warn(": unable to order shared symbol: ");
+ else if (D && !D->Section)
+ Warn(": unable to order absolute symbol: ");
+ else if (D && isa<OutputSection>(D->Section))
+ Warn(": unable to order synthetic symbol: ");
+ else if (D && !D->Section->Repl->Live)
+ Warn(": unable to order discarded symbol: ");
+}
+
// Returns a symbol for an error message.
std::string lld::toString(const Symbol &B) {
if (Config->Demangle)
diff --git a/contrib/llvm/tools/lld/ELF/Symbols.h b/contrib/llvm/tools/lld/ELF/Symbols.h
index 9b7207383345..8c9513b9368b 100644
--- a/contrib/llvm/tools/lld/ELF/Symbols.h
+++ b/contrib/llvm/tools/lld/ELF/Symbols.h
@@ -7,8 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// All symbols are handled as SymbolBodies regardless of their types.
-// This file defines various types of SymbolBodies.
+// This file defines various types of Symbols.
//
//===----------------------------------------------------------------------===//
@@ -16,9 +15,8 @@
#define LLD_ELF_SYMBOLS_H
#include "InputSection.h"
-#include "Strings.h"
-
#include "lld/Common/LLVM.h"
+#include "lld/Common/Strings.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
@@ -34,6 +32,20 @@ template <class ELFT> class ObjFile;
class OutputSection;
template <class ELFT> class SharedFile;
+// This is a StringRef-like container that doesn't run strlen().
+//
+// ELF string tables contain a lot of null-terminated strings. Most of them
+// are not necessary for the linker because they are names of local symbols,
+// and the linker doesn't use local symbol names for name resolution. So, we
+// use this class to represents strings read from string tables.
+struct StringRefZ {
+ StringRefZ(const char *S) : Data(S), Size(-1) {}
+ StringRefZ(StringRef S) : Data(S.data()), Size(S.size()) {}
+
+ const char *Data;
+ const uint32_t Size;
+};
+
// The base class for real symbol classes.
class Symbol {
public:
@@ -47,6 +59,25 @@ public:
Kind kind() const { return static_cast<Kind>(SymbolKind); }
+ // The file from which this symbol was created.
+ InputFile *File;
+
+protected:
+ const char *NameData;
+ mutable uint32_t NameSize;
+
+public:
+ uint32_t DynsymIndex = 0;
+ uint32_t GotIndex = -1;
+ uint32_t PltIndex = -1;
+ uint32_t GlobalDynIndex = -1;
+
+ // This field is a index to the symbol's version definition.
+ uint32_t VerdefIndex = -1;
+
+ // Version definition index.
+ uint16_t VersionId;
+
// Symbol binding. This is not overwritten by replaceSymbol to track
// changes during resolution. In particular:
// - An undefined weak is still weak when it resolves to a shared library.
@@ -54,8 +85,11 @@ public:
// remember it is weak.
uint8_t Binding;
- // Version definition index.
- uint16_t VersionId;
+ // The following fields have the same meaning as the ELF symbol attributes.
+ uint8_t Type; // symbol type
+ uint8_t StOther; // st_other field value
+
+ const uint8_t SymbolKind;
// Symbol visibility. This is the computed minimum visibility of all
// observed non-DSO symbols.
@@ -81,12 +115,6 @@ public:
// True if this symbol is specified by --trace-symbol option.
unsigned Traced : 1;
- // This symbol version was found in a version script.
- unsigned InVersionScript : 1;
-
- // The file from which this symbol was created.
- InputFile *File;
-
bool includeInDynsym() const;
uint8_t computeBinding() const;
bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
@@ -100,15 +128,15 @@ public:
return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;
}
- // True is this is an undefined weak symbol. This only works once
- // all input files have been added.
- bool isUndefWeak() const {
- // See comment on Lazy the details.
- return isWeak() && (isUndefined() || isLazy());
+ // True if this is an undefined weak symbol.
+ bool isUndefWeak() const { return isWeak() && isUndefined(); }
+
+ StringRef getName() const {
+ if (NameSize == (uint32_t)-1)
+ NameSize = strlen(NameData);
+ return {NameData, NameSize};
}
- StringRef getName() const { return Name; }
- uint8_t getVisibility() const { return StOther & 0x3; }
void parseSymbolVersion();
bool isInGot() const { return GotIndex != -1U; }
@@ -121,34 +149,22 @@ public:
uint64_t getGotPltOffset() const;
uint64_t getGotPltVA() const;
uint64_t getPltVA() const;
+ uint64_t getPltOffset() const;
uint64_t getSize() const;
OutputSection *getOutputSection() const;
- uint32_t DynsymIndex = 0;
- uint32_t GotIndex = -1;
- uint32_t GotPltIndex = -1;
- uint32_t PltIndex = -1;
- uint32_t GlobalDynIndex = -1;
-
protected:
Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding,
uint8_t StOther, uint8_t Type)
- : Binding(Binding), File(File), SymbolKind(K), NeedsPltAddr(false),
- IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false),
- IsInIgot(false), IsPreemptible(false), Used(!Config->GcSections),
- Type(Type), StOther(StOther), Name(Name) {}
-
- const unsigned SymbolKind : 8;
+ : File(File), NameData(Name.Data), NameSize(Name.Size), Binding(Binding),
+ Type(Type), StOther(StOther), SymbolKind(K), NeedsPltAddr(false),
+ IsInIplt(false), IsInIgot(false), IsPreemptible(false),
+ Used(!Config->GcSections), NeedsTocRestore(false) {}
public:
// True the symbol should point to its PLT entry.
// For SharedSymbol only.
unsigned NeedsPltAddr : 1;
- // True if this symbol has an entry in the global part of MIPS GOT.
- unsigned IsInGlobalMipsGot : 1;
-
- // True if this symbol is referenced by 32-bit GOT relocations.
- unsigned Is32BitMipsGot : 1;
// True if this symbol is in the Iplt sub-section of the Plt.
unsigned IsInIplt : 1;
@@ -156,14 +172,15 @@ public:
// True if this symbol is in the Igot sub-section of the .got.plt or .got.
unsigned IsInIgot : 1;
+ // True if this symbol is preemptible at load time.
unsigned IsPreemptible : 1;
// True if an undefined or shared symbol is used from a live section.
unsigned Used : 1;
- // The following fields have the same meaning as the ELF symbol attributes.
- uint8_t Type; // symbol type
- uint8_t StOther; // st_other field value
+ // True if a call to this symbol needs to be followed by a restore of the
+ // PPC64 toc pointer.
+ unsigned NeedsTocRestore : 1;
// The Type field may also have this value. It means that we have not yet seen
// a non-Lazy symbol with this name, so we don't know what its type is. The
@@ -178,9 +195,6 @@ public:
bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; }
bool isObject() const { return Type == llvm::ELF::STT_OBJECT; }
bool isFile() const { return Type == llvm::ELF::STT_FILE; }
-
-protected:
- StringRefZ Name;
};
// Represents a symbol that is defined in the current output file.
@@ -214,8 +228,9 @@ public:
SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,
uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,
uint32_t Alignment, uint32_t VerdefIndex)
- : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value),
- Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) {
+ : Symbol(SharedKind, &File, Name, Binding, StOther, Type),
+ Alignment(Alignment), Value(Value), Size(Size) {
+ this->VerdefIndex = VerdefIndex;
// GNU ifunc is a mechanism to allow user-supplied functions to
// resolve PLT slot values at load-time. This is contrary to the
// regular symbol resolution scheme in which symbols are resolved just
@@ -240,54 +255,36 @@ public:
return *cast<SharedFile<ELFT>>(File);
}
- // If not null, there is a copy relocation to this section.
- InputSection *CopyRelSec = nullptr;
+ uint32_t Alignment;
uint64_t Value; // st_value
uint64_t Size; // st_size
-
- // This field is a index to the symbol's version definition.
- uint32_t VerdefIndex;
-
- uint32_t Alignment;
};
-// This represents a symbol that is not yet in the link, but we know where to
-// find it if needed. If the resolver finds both Undefined and Lazy for the same
-// name, it will ask the Lazy to load a file.
+// LazyArchive and LazyObject represent a symbols that is not yet in the link,
+// but we know where to find it if needed. If the resolver finds both Undefined
+// and Lazy for the same name, it will ask the Lazy to load a file.
//
// A special complication is the handling of weak undefined symbols. They should
// not load a file, but we have to remember we have seen both the weak undefined
// and the lazy. We represent that with a lazy symbol with a weak binding. This
// means that code looking for undefined symbols normally also has to take lazy
// symbols into consideration.
-class Lazy : public Symbol {
-public:
- static bool classof(const Symbol *S) { return S->isLazy(); }
-
- // Returns an object file for this symbol, or a nullptr if the file
- // was already returned.
- InputFile *fetch();
-
-protected:
- Lazy(Kind K, InputFile &File, StringRef Name, uint8_t Type)
- : Symbol(K, &File, Name, llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT,
- Type) {}
-};
// This class represents a symbol defined in an archive file. It is
// created from an archive file header, and it knows how to load an
// object file from an archive to replace itself with a defined
// symbol.
-class LazyArchive : public Lazy {
+class LazyArchive : public Symbol {
public:
- LazyArchive(InputFile &File, const llvm::object::Archive::Symbol S,
- uint8_t Type)
- : Lazy(LazyArchiveKind, File, S.getName(), Type), Sym(S) {}
+ LazyArchive(InputFile &File, uint8_t Type,
+ const llvm::object::Archive::Symbol S)
+ : Symbol(LazyArchiveKind, &File, S.getName(), llvm::ELF::STB_GLOBAL,
+ llvm::ELF::STV_DEFAULT, Type),
+ Sym(S) {}
static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; }
- ArchiveFile &getFile();
InputFile *fetch();
private:
@@ -296,15 +293,13 @@ private:
// LazyObject symbols represents symbols in object files between
// --start-lib and --end-lib options.
-class LazyObject : public Lazy {
+class LazyObject : public Symbol {
public:
- LazyObject(InputFile &File, StringRef Name, uint8_t Type)
- : Lazy(LazyObjectKind, File, Name, Type) {}
+ LazyObject(InputFile &File, uint8_t Type, StringRef Name)
+ : Symbol(LazyObjectKind, &File, Name, llvm::ELF::STB_GLOBAL,
+ llvm::ELF::STV_DEFAULT, Type) {}
static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; }
-
- LazyObjFile &getFile();
- InputFile *fetch();
};
// Some linker-generated symbols need to be created as
@@ -334,6 +329,9 @@ struct ElfSym {
static Defined *MipsGp;
static Defined *MipsGpDisp;
static Defined *MipsLocalGp;
+
+ // __rela_iplt_end or __rel_iplt_end
+ static Defined *RelaIpltEnd;
};
// A buffer class that is large enough to hold any Symbol-derived
@@ -351,6 +349,8 @@ void printTraceSymbol(Symbol *Sym);
template <typename T, typename... ArgT>
void replaceSymbol(Symbol *S, ArgT &&... Arg) {
+ static_assert(std::is_trivially_destructible<T>(),
+ "Symbol types must be trivially destructible");
static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
static_assert(alignof(T) <= alignof(SymbolUnion),
"SymbolUnion not aligned enough");
@@ -367,13 +367,14 @@ void replaceSymbol(Symbol *S, ArgT &&... Arg) {
S->ExportDynamic = Sym.ExportDynamic;
S->CanInline = Sym.CanInline;
S->Traced = Sym.Traced;
- S->InVersionScript = Sym.InVersionScript;
// Print out a log message if --trace-symbol was specified.
// This is for debugging.
if (S->Traced)
printTraceSymbol(S);
}
+
+void warnUnorderableSymbol(const Symbol *Sym);
} // namespace elf
std::string toString(const elf::Symbol &B);
diff --git a/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp b/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp
index a5a851f95400..8b02a14c93c2 100644
--- a/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp
+++ b/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp
@@ -20,15 +20,16 @@
#include "InputFiles.h"
#include "LinkerScript.h"
#include "OutputSections.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "Target.h"
#include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
#include "lld/Common/Version.h"
+#include "llvm/ADT/SetOperations.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/Object/Decompressor.h"
@@ -47,27 +48,20 @@ using namespace llvm::dwarf;
using namespace llvm::ELF;
using namespace llvm::object;
using namespace llvm::support;
-using namespace llvm::support::endian;
using namespace lld;
using namespace lld::elf;
-constexpr size_t MergeNoTailSection::NumShards;
-
-static void write32(void *Buf, uint32_t Val) {
- endian::write32(Buf, Val, Config->Endianness);
-}
+using llvm::support::endian::read32le;
+using llvm::support::endian::write32le;
+using llvm::support::endian::write64le;
-uint64_t SyntheticSection::getVA() const {
- if (OutputSection *Sec = getParent())
- return Sec->Addr + OutSecOff;
- return 0;
-}
+constexpr size_t MergeNoTailSection::NumShards;
// Returns an LLD version string.
static ArrayRef<uint8_t> getVersion() {
// Check LLD_VERSION first for ease of testing.
- // You can get consitent output by using the environment variable.
+ // You can get consistent output by using the environment variable.
// This is only for testing.
StringRef S = getenv("LLD_VERSION");
if (S.empty())
@@ -192,8 +186,6 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
auto *Opt = reinterpret_cast<const Elf_Mips_Options *>(D.data());
if (Opt->kind == ODK_REGINFO) {
- if (Config->Relocatable && Opt->getRegInfo().ri_gp_value)
- error(Filename + ": unsupported non-zero ri_gp_value");
Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask;
Sec->getFile<ELFT>()->MipsGp0 = Opt->getRegInfo().ri_gp_value;
break;
@@ -244,10 +236,8 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
error(toString(Sec->File) + ": invalid size of .reginfo section");
return nullptr;
}
- auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data());
- if (Config->Relocatable && R->ri_gp_value)
- error(toString(Sec->File) + ": unsupported non-zero ri_gp_value");
+ auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data());
Reginfo.ri_gprmask |= R->ri_gprmask;
Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value;
};
@@ -266,8 +256,8 @@ InputSection *elf::createInterpSection() {
return Sec;
}
-Symbol *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
- uint64_t Size, InputSectionBase &Section) {
+Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
+ uint64_t Size, InputSectionBase &Section) {
auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,
Value, Size, &Section);
if (InX::SymTab)
@@ -338,8 +328,6 @@ void BuildIdSection::computeHash(
BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment)
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Name) {
this->Bss = true;
- if (OutputSection *Sec = getParent())
- Sec->Alignment = std::max(Sec->Alignment, Alignment);
this->Size = Size;
}
@@ -347,7 +335,7 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) {
switch (Config->BuildId) {
case BuildIdKind::Fast:
computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) {
- write64le(Dest, xxHash64(toStringRef(Arr)));
+ write64le(Dest, xxHash64(Arr));
});
break;
case BuildIdKind::Md5:
@@ -380,15 +368,11 @@ EhFrameSection::EhFrameSection()
// and where their relocations point to.
template <class ELFT, class RelTy>
CieRecord *EhFrameSection::addCie(EhSectionPiece &Cie, ArrayRef<RelTy> Rels) {
- auto *Sec = cast<EhInputSection>(Cie.Sec);
- if (read32(Cie.data().data() + 4, Config->Endianness) != 0)
- fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame");
-
Symbol *Personality = nullptr;
unsigned FirstRelI = Cie.FirstRelocation;
if (FirstRelI != (unsigned)-1)
Personality =
- &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
+ &Cie.Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
// Search for an existing CIE by CIE contents/relocation target pair.
CieRecord *&Rec = CieMap[{Cie.data(), Personality}];
@@ -433,14 +417,14 @@ bool EhFrameSection::isFdeLive(EhSectionPiece &Fde, ArrayRef<RelTy> Rels) {
// one and associates FDEs to the CIE.
template <class ELFT, class RelTy>
void EhFrameSection::addSectionAux(EhInputSection *Sec, ArrayRef<RelTy> Rels) {
- DenseMap<size_t, CieRecord *> OffsetToCie;
+ OffsetToCie.clear();
for (EhSectionPiece &Piece : Sec->Pieces) {
// The empty record is the end marker.
if (Piece.Size == 4)
return;
size_t Offset = Piece.InputOff;
- uint32_t ID = read32(Piece.data().data() + 4, Config->Endianness);
+ uint32_t ID = read32(Piece.data().data() + 4);
if (ID == 0) {
OffsetToCie[Offset] = addCie<ELFT>(Piece, Rels);
continue;
@@ -468,10 +452,6 @@ template <class ELFT> void EhFrameSection::addSection(InputSectionBase *C) {
for (auto *DS : Sec->DependentSections)
DependentSections.push_back(DS);
- // .eh_frame is a sequence of CIE or FDE records. This function
- // splits it into pieces so that we can call
- // SplitInputSection::getSectionPiece on the section.
- Sec->split<ELFT>();
if (Sec->Pieces.empty())
return;
@@ -494,9 +474,7 @@ static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
}
void EhFrameSection::finalizeContents() {
- if (this->Size)
- return; // Already finalized.
-
+ assert(!this->Size); // Not finalized.
size_t Off = 0;
for (CieRecord *Rec : CieRecords) {
Rec->Cie->OutputOff = Off;
@@ -509,10 +487,10 @@ void EhFrameSection::finalizeContents() {
}
// The LSB standard does not allow a .eh_frame section with zero
- // Call Frame Information records. Therefore add a CIE record length
- // 0 as a terminator if this .eh_frame section is empty.
- if (Off == 0)
- Off = 4;
+ // Call Frame Information records. glibc unwind-dw2-fde.c
+ // classify_object_over_fdes expects there is a CIE record length 0 as a
+ // terminator. Thus we add one unconditionally.
+ Off += 4;
this->Size = Off;
}
@@ -524,25 +502,47 @@ std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {
uint8_t *Buf = getParent()->Loc + OutSecOff;
std::vector<FdeData> Ret;
+ uint64_t VA = InX::EhFrameHdr->getVA();
for (CieRecord *Rec : CieRecords) {
uint8_t Enc = getFdeEncoding(Rec->Cie);
for (EhSectionPiece *Fde : Rec->Fdes) {
- uint32_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
- uint32_t FdeVA = getParent()->Addr + Fde->OutputOff;
- Ret.push_back({Pc, FdeVA});
+ uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
+ uint64_t FdeVA = getParent()->Addr + Fde->OutputOff;
+ if (!isInt<32>(Pc - VA))
+ fatal(toString(Fde->Sec) + ": PC offset is too large: 0x" +
+ Twine::utohexstr(Pc - VA));
+ Ret.push_back({uint32_t(Pc - VA), uint32_t(FdeVA - VA)});
}
}
+
+ // Sort the FDE list by their PC and uniqueify. Usually there is only
+ // one FDE for a PC (i.e. function), but if ICF merges two functions
+ // into one, there can be more than one FDEs pointing to the address.
+ auto Less = [](const FdeData &A, const FdeData &B) {
+ return A.PcRel < B.PcRel;
+ };
+ std::stable_sort(Ret.begin(), Ret.end(), Less);
+ auto Eq = [](const FdeData &A, const FdeData &B) {
+ return A.PcRel == B.PcRel;
+ };
+ Ret.erase(std::unique(Ret.begin(), Ret.end(), Eq), Ret.end());
+
return Ret;
}
static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
switch (Size) {
case DW_EH_PE_udata2:
- return read16(Buf, Config->Endianness);
+ return read16(Buf);
+ case DW_EH_PE_sdata2:
+ return (int16_t)read16(Buf);
case DW_EH_PE_udata4:
- return read32(Buf, Config->Endianness);
+ return read32(Buf);
+ case DW_EH_PE_sdata4:
+ return (int32_t)read32(Buf);
case DW_EH_PE_udata8:
- return read64(Buf, Config->Endianness);
+ case DW_EH_PE_sdata8:
+ return read64(Buf);
case DW_EH_PE_absptr:
return readUint(Buf);
}
@@ -556,7 +556,7 @@ uint64_t EhFrameSection::getFdePc(uint8_t *Buf, size_t FdeOff,
// The starting address to which this FDE applies is
// stored at FDE + 8 byte.
size_t Off = FdeOff + 8;
- uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0x7);
+ uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0xf);
if ((Enc & 0x70) == DW_EH_PE_absptr)
return Addr;
if ((Enc & 0x70) == DW_EH_PE_pcrel)
@@ -589,7 +589,15 @@ void EhFrameSection::writeTo(uint8_t *Buf) {
GotSection::GotSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
- Target->GotEntrySize, ".got") {}
+ Target->GotEntrySize, ".got") {
+ // PPC64 saves the ElfSym::GlobalOffsetTable .TOC. as the first entry in the
+ // .got. If there are no references to .TOC. in the symbol table,
+ // ElfSym::GlobalOffsetTable will not be defined and we won't need to save
+ // .TOC. in the .got. When it is defined, we increase NumEntries by the number
+ // of entries used to emit ElfSym::GlobalOffsetTable.
+ if (ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt)
+ NumEntries += Target->GotHeaderEntriesNum;
+}
void GotSection::addEntry(Symbol &Sym) {
Sym.GotIndex = NumEntries;
@@ -623,196 +631,383 @@ uint64_t GotSection::getGlobalDynOffset(const Symbol &B) const {
return B.GlobalDynIndex * Config->Wordsize;
}
-void GotSection::finalizeContents() { Size = NumEntries * Config->Wordsize; }
+void GotSection::finalizeContents() {
+ Size = NumEntries * Config->Wordsize;
+}
bool GotSection::empty() const {
// We need to emit a GOT even if it's empty if there's a relocation that is
// relative to GOT(such as GOTOFFREL) or there's a symbol that points to a GOT
- // (i.e. _GLOBAL_OFFSET_TABLE_).
- return NumEntries == 0 && !HasGotOffRel && !ElfSym::GlobalOffsetTable;
+ // (i.e. _GLOBAL_OFFSET_TABLE_) that the target defines relative to the .got.
+ return NumEntries == 0 && !HasGotOffRel &&
+ !(ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt);
}
void GotSection::writeTo(uint8_t *Buf) {
// Buf points to the start of this section's buffer,
// whereas InputSectionBase::relocateAlloc() expects its argument
// to point to the start of the output section.
+ Target->writeGotHeader(Buf);
relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);
}
+static uint64_t getMipsPageAddr(uint64_t Addr) {
+ return (Addr + 0x8000) & ~0xffff;
+}
+
+static uint64_t getMipsPageCount(uint64_t Size) {
+ return (Size + 0xfffe) / 0xffff + 1;
+}
+
MipsGotSection::MipsGotSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16,
".got") {}
-void MipsGotSection::addEntry(Symbol &Sym, int64_t Addend, RelExpr Expr) {
- // For "true" local symbols which can be referenced from the same module
- // only compiler creates two instructions for address loading:
- //
- // lw $8, 0($gp) # R_MIPS_GOT16
- // addi $8, $8, 0 # R_MIPS_LO16
- //
- // The first instruction loads high 16 bits of the symbol address while
- // the second adds an offset. That allows to reduce number of required
- // GOT entries because only one global offset table entry is necessary
- // for every 64 KBytes of local data. So for local symbols we need to
- // allocate number of GOT entries to hold all required "page" addresses.
- //
- // All global symbols (hidden and regular) considered by compiler uniformly.
- // It always generates a single `lw` instruction and R_MIPS_GOT16 relocation
- // to load address of the symbol. So for each such symbol we need to
- // allocate dedicated GOT entry to store its address.
- //
- // If a symbol is preemptible we need help of dynamic linker to get its
- // final address. The corresponding GOT entries are allocated in the
- // "global" part of GOT. Entries for non preemptible global symbol allocated
- // in the "local" part of GOT.
- //
- // See "Global Offset Table" in Chapter 5:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+void MipsGotSection::addEntry(InputFile &File, Symbol &Sym, int64_t Addend,
+ RelExpr Expr) {
+ FileGot &G = getGot(File);
if (Expr == R_MIPS_GOT_LOCAL_PAGE) {
- // At this point we do not know final symbol value so to reduce number
- // of allocated GOT entries do the following trick. Save all output
- // sections referenced by GOT relocations. Then later in the `finalize`
- // method calculate number of "pages" required to cover all saved output
- // section and allocate appropriate number of GOT entries.
- PageIndexMap.insert({Sym.getOutputSection(), 0});
- return;
- }
- if (Sym.isTls()) {
- // GOT entries created for MIPS TLS relocations behave like
- // almost GOT entries from other ABIs. They go to the end
- // of the global offset table.
- Sym.GotIndex = TlsEntries.size();
- TlsEntries.push_back(&Sym);
- return;
- }
- auto AddEntry = [&](Symbol &S, uint64_t A, GotEntries &Items) {
- if (S.isInGot() && !A)
- return;
- size_t NewIndex = Items.size();
- if (!EntryIndexMap.insert({{&S, A}, NewIndex}).second)
- return;
- Items.emplace_back(&S, A);
- if (!A)
- S.GotIndex = NewIndex;
- };
- if (Sym.IsPreemptible) {
- // Ignore addends for preemptible symbols. They got single GOT entry anyway.
- AddEntry(Sym, 0, GlobalEntries);
- Sym.IsInGlobalMipsGot = true;
- } else if (Expr == R_MIPS_GOT_OFF32) {
- AddEntry(Sym, Addend, LocalEntries32);
- Sym.Is32BitMipsGot = true;
- } else {
- // Hold local GOT entries accessed via a 16-bit index separately.
- // That allows to write them in the beginning of the GOT and keep
- // their indexes as less as possible to escape relocation's overflow.
- AddEntry(Sym, Addend, LocalEntries);
- }
+ if (const OutputSection *OS = Sym.getOutputSection())
+ G.PagesMap.insert({OS, {}});
+ else
+ G.Local16.insert({{nullptr, getMipsPageAddr(Sym.getVA(Addend))}, 0});
+ } else if (Sym.isTls())
+ G.Tls.insert({&Sym, 0});
+ else if (Sym.IsPreemptible && Expr == R_ABS)
+ G.Relocs.insert({&Sym, 0});
+ else if (Sym.IsPreemptible)
+ G.Global.insert({&Sym, 0});
+ else if (Expr == R_MIPS_GOT_OFF32)
+ G.Local32.insert({{&Sym, Addend}, 0});
+ else
+ G.Local16.insert({{&Sym, Addend}, 0});
}
-bool MipsGotSection::addDynTlsEntry(Symbol &Sym) {
- if (Sym.GlobalDynIndex != -1U)
- return false;
- Sym.GlobalDynIndex = TlsEntries.size();
- // Global Dynamic TLS entries take two GOT slots.
- TlsEntries.push_back(nullptr);
- TlsEntries.push_back(&Sym);
- return true;
+void MipsGotSection::addDynTlsEntry(InputFile &File, Symbol &Sym) {
+ getGot(File).DynTlsSymbols.insert({&Sym, 0});
}
-// Reserves TLS entries for a TLS module ID and a TLS block offset.
-// In total it takes two GOT slots.
-bool MipsGotSection::addTlsIndex() {
- if (TlsIndexOff != uint32_t(-1))
- return false;
- TlsIndexOff = TlsEntries.size() * Config->Wordsize;
- TlsEntries.push_back(nullptr);
- TlsEntries.push_back(nullptr);
- return true;
+void MipsGotSection::addTlsIndex(InputFile &File) {
+ getGot(File).DynTlsSymbols.insert({nullptr, 0});
}
-static uint64_t getMipsPageAddr(uint64_t Addr) {
- return (Addr + 0x8000) & ~0xffff;
+size_t MipsGotSection::FileGot::getEntriesNum() const {
+ return getPageEntriesNum() + Local16.size() + Global.size() + Relocs.size() +
+ Tls.size() + DynTlsSymbols.size() * 2;
}
-static uint64_t getMipsPageCount(uint64_t Size) {
- return (Size + 0xfffe) / 0xffff + 1;
+size_t MipsGotSection::FileGot::getPageEntriesNum() const {
+ size_t Num = 0;
+ for (const std::pair<const OutputSection *, FileGot::PageBlock> &P : PagesMap)
+ Num += P.second.Count;
+ return Num;
}
-uint64_t MipsGotSection::getPageEntryOffset(const Symbol &B,
- int64_t Addend) const {
- const OutputSection *OutSec = B.getOutputSection();
- uint64_t SecAddr = getMipsPageAddr(OutSec->Addr);
- uint64_t SymAddr = getMipsPageAddr(B.getVA(Addend));
- uint64_t Index = PageIndexMap.lookup(OutSec) + (SymAddr - SecAddr) / 0xffff;
- assert(Index < PageEntriesNum);
- return (HeaderEntriesNum + Index) * Config->Wordsize;
+size_t MipsGotSection::FileGot::getIndexedEntriesNum() const {
+ size_t Count = getPageEntriesNum() + Local16.size() + Global.size();
+ // If there are relocation-only entries in the GOT, TLS entries
+ // are allocated after them. TLS entries should be addressable
+ // by 16-bit index so count both reloc-only and TLS entries.
+ if (!Tls.empty() || !DynTlsSymbols.empty())
+ Count += Relocs.size() + Tls.size() + DynTlsSymbols.size() * 2;
+ return Count;
}
-uint64_t MipsGotSection::getSymEntryOffset(const Symbol &B,
- int64_t Addend) const {
- // Calculate offset of the GOT entries block: TLS, global, local.
- uint64_t Index = HeaderEntriesNum + PageEntriesNum;
- if (B.isTls())
- Index += LocalEntries.size() + LocalEntries32.size() + GlobalEntries.size();
- else if (B.IsInGlobalMipsGot)
- Index += LocalEntries.size() + LocalEntries32.size();
- else if (B.Is32BitMipsGot)
- Index += LocalEntries.size();
- // Calculate offset of the GOT entry in the block.
- if (B.isInGot())
- Index += B.GotIndex;
- else {
- auto It = EntryIndexMap.find({&B, Addend});
- assert(It != EntryIndexMap.end());
- Index += It->second;
+MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &F) {
+ if (!F.MipsGotIndex.hasValue()) {
+ Gots.emplace_back();
+ Gots.back().File = &F;
+ F.MipsGotIndex = Gots.size() - 1;
+ }
+ return Gots[*F.MipsGotIndex];
+}
+
+uint64_t MipsGotSection::getPageEntryOffset(const InputFile *F,
+ const Symbol &Sym,
+ int64_t Addend) const {
+ const FileGot &G = Gots[*F->MipsGotIndex];
+ uint64_t Index = 0;
+ if (const OutputSection *OutSec = Sym.getOutputSection()) {
+ uint64_t SecAddr = getMipsPageAddr(OutSec->Addr);
+ uint64_t SymAddr = getMipsPageAddr(Sym.getVA(Addend));
+ Index = G.PagesMap.lookup(OutSec).FirstIndex + (SymAddr - SecAddr) / 0xffff;
+ } else {
+ Index = G.Local16.lookup({nullptr, getMipsPageAddr(Sym.getVA(Addend))});
}
return Index * Config->Wordsize;
}
-uint64_t MipsGotSection::getTlsOffset() const {
- return (getLocalEntriesNum() + GlobalEntries.size()) * Config->Wordsize;
+uint64_t MipsGotSection::getSymEntryOffset(const InputFile *F, const Symbol &S,
+ int64_t Addend) const {
+ const FileGot &G = Gots[*F->MipsGotIndex];
+ Symbol *Sym = const_cast<Symbol *>(&S);
+ if (Sym->isTls())
+ return G.Tls.lookup(Sym) * Config->Wordsize;
+ if (Sym->IsPreemptible)
+ return G.Global.lookup(Sym) * Config->Wordsize;
+ return G.Local16.lookup({Sym, Addend}) * Config->Wordsize;
}
-uint64_t MipsGotSection::getGlobalDynOffset(const Symbol &B) const {
- return B.GlobalDynIndex * Config->Wordsize;
+uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *F) const {
+ const FileGot &G = Gots[*F->MipsGotIndex];
+ return G.DynTlsSymbols.lookup(nullptr) * Config->Wordsize;
+}
+
+uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *F,
+ const Symbol &S) const {
+ const FileGot &G = Gots[*F->MipsGotIndex];
+ Symbol *Sym = const_cast<Symbol *>(&S);
+ return G.DynTlsSymbols.lookup(Sym) * Config->Wordsize;
}
const Symbol *MipsGotSection::getFirstGlobalEntry() const {
- return GlobalEntries.empty() ? nullptr : GlobalEntries.front().first;
+ if (Gots.empty())
+ return nullptr;
+ const FileGot &PrimGot = Gots.front();
+ if (!PrimGot.Global.empty())
+ return PrimGot.Global.front().first;
+ if (!PrimGot.Relocs.empty())
+ return PrimGot.Relocs.front().first;
+ return nullptr;
}
unsigned MipsGotSection::getLocalEntriesNum() const {
- return HeaderEntriesNum + PageEntriesNum + LocalEntries.size() +
- LocalEntries32.size();
+ if (Gots.empty())
+ return HeaderEntriesNum;
+ return HeaderEntriesNum + Gots.front().getPageEntriesNum() +
+ Gots.front().Local16.size();
+}
+
+bool MipsGotSection::tryMergeGots(FileGot &Dst, FileGot &Src, bool IsPrimary) {
+ FileGot Tmp = Dst;
+ set_union(Tmp.PagesMap, Src.PagesMap);
+ set_union(Tmp.Local16, Src.Local16);
+ set_union(Tmp.Global, Src.Global);
+ set_union(Tmp.Relocs, Src.Relocs);
+ set_union(Tmp.Tls, Src.Tls);
+ set_union(Tmp.DynTlsSymbols, Src.DynTlsSymbols);
+
+ size_t Count = IsPrimary ? HeaderEntriesNum : 0;
+ Count += Tmp.getIndexedEntriesNum();
+
+ if (Count * Config->Wordsize > Config->MipsGotSize)
+ return false;
+
+ std::swap(Tmp, Dst);
+ return true;
}
void MipsGotSection::finalizeContents() { updateAllocSize(); }
bool MipsGotSection::updateAllocSize() {
- PageEntriesNum = 0;
- for (std::pair<const OutputSection *, size_t> &P : PageIndexMap) {
- // For each output section referenced by GOT page relocations calculate
- // and save into PageIndexMap an upper bound of MIPS GOT entries required
- // to store page addresses of local symbols. We assume the worst case -
- // each 64kb page of the output section has at least one GOT relocation
- // against it. And take in account the case when the section intersects
- // page boundaries.
- P.second = PageEntriesNum;
- PageEntriesNum += getMipsPageCount(P.first->Size);
- }
- Size = (getLocalEntriesNum() + GlobalEntries.size() + TlsEntries.size()) *
- Config->Wordsize;
+ Size = HeaderEntriesNum * Config->Wordsize;
+ for (const FileGot &G : Gots)
+ Size += G.getEntriesNum() * Config->Wordsize;
return false;
}
+template <class ELFT> void MipsGotSection::build() {
+ if (Gots.empty())
+ return;
+
+ std::vector<FileGot> MergedGots(1);
+
+ // For each GOT move non-preemptible symbols from the `Global`
+ // to `Local16` list. Preemptible symbol might become non-preemptible
+ // one if, for example, it gets a related copy relocation.
+ for (FileGot &Got : Gots) {
+ for (auto &P: Got.Global)
+ if (!P.first->IsPreemptible)
+ Got.Local16.insert({{P.first, 0}, 0});
+ Got.Global.remove_if([&](const std::pair<Symbol *, size_t> &P) {
+ return !P.first->IsPreemptible;
+ });
+ }
+
+ // For each GOT remove "reloc-only" entry if there is "global"
+ // entry for the same symbol. And add local entries which indexed
+ // using 32-bit value at the end of 16-bit entries.
+ for (FileGot &Got : Gots) {
+ Got.Relocs.remove_if([&](const std::pair<Symbol *, size_t> &P) {
+ return Got.Global.count(P.first);
+ });
+ set_union(Got.Local16, Got.Local32);
+ Got.Local32.clear();
+ }
+
+ // Evaluate number of "reloc-only" entries in the resulting GOT.
+ // To do that put all unique "reloc-only" and "global" entries
+ // from all GOTs to the future primary GOT.
+ FileGot *PrimGot = &MergedGots.front();
+ for (FileGot &Got : Gots) {
+ set_union(PrimGot->Relocs, Got.Global);
+ set_union(PrimGot->Relocs, Got.Relocs);
+ Got.Relocs.clear();
+ }
+
+ // Evaluate number of "page" entries in each GOT.
+ for (FileGot &Got : Gots) {
+ for (std::pair<const OutputSection *, FileGot::PageBlock> &P :
+ Got.PagesMap) {
+ const OutputSection *OS = P.first;
+ uint64_t SecSize = 0;
+ for (BaseCommand *Cmd : OS->SectionCommands) {
+ if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
+ for (InputSection *IS : ISD->Sections) {
+ uint64_t Off = alignTo(SecSize, IS->Alignment);
+ SecSize = Off + IS->getSize();
+ }
+ }
+ P.second.Count = getMipsPageCount(SecSize);
+ }
+ }
+
+ // Merge GOTs. Try to join as much as possible GOTs but do not exceed
+ // maximum GOT size. At first, try to fill the primary GOT because
+ // the primary GOT can be accessed in the most effective way. If it
+ // is not possible, try to fill the last GOT in the list, and finally
+ // create a new GOT if both attempts failed.
+ for (FileGot &SrcGot : Gots) {
+ InputFile *File = SrcGot.File;
+ if (tryMergeGots(MergedGots.front(), SrcGot, true)) {
+ File->MipsGotIndex = 0;
+ } else {
+ // If this is the first time we failed to merge with the primary GOT,
+ // MergedGots.back() will also be the primary GOT. We must make sure not
+ // to try to merge again with IsPrimary=false, as otherwise, if the
+ // inputs are just right, we could allow the primary GOT to become 1 or 2
+ // words too big due to ignoring the header size.
+ if (MergedGots.size() == 1 ||
+ !tryMergeGots(MergedGots.back(), SrcGot, false)) {
+ MergedGots.emplace_back();
+ std::swap(MergedGots.back(), SrcGot);
+ }
+ File->MipsGotIndex = MergedGots.size() - 1;
+ }
+ }
+ std::swap(Gots, MergedGots);
+
+ // Reduce number of "reloc-only" entries in the primary GOT
+ // by substracting "global" entries exist in the primary GOT.
+ PrimGot = &Gots.front();
+ PrimGot->Relocs.remove_if([&](const std::pair<Symbol *, size_t> &P) {
+ return PrimGot->Global.count(P.first);
+ });
+
+ // Calculate indexes for each GOT entry.
+ size_t Index = HeaderEntriesNum;
+ for (FileGot &Got : Gots) {
+ Got.StartIndex = &Got == PrimGot ? 0 : Index;
+ for (std::pair<const OutputSection *, FileGot::PageBlock> &P :
+ Got.PagesMap) {
+ // For each output section referenced by GOT page relocations calculate
+ // and save into PagesMap an upper bound of MIPS GOT entries required
+ // to store page addresses of local symbols. We assume the worst case -
+ // each 64kb page of the output section has at least one GOT relocation
+ // against it. And take in account the case when the section intersects
+ // page boundaries.
+ P.second.FirstIndex = Index;
+ Index += P.second.Count;
+ }
+ for (auto &P: Got.Local16)
+ P.second = Index++;
+ for (auto &P: Got.Global)
+ P.second = Index++;
+ for (auto &P: Got.Relocs)
+ P.second = Index++;
+ for (auto &P: Got.Tls)
+ P.second = Index++;
+ for (auto &P: Got.DynTlsSymbols) {
+ P.second = Index;
+ Index += 2;
+ }
+ }
+
+ // Update Symbol::GotIndex field to use this
+ // value later in the `sortMipsSymbols` function.
+ for (auto &P : PrimGot->Global)
+ P.first->GotIndex = P.second;
+ for (auto &P : PrimGot->Relocs)
+ P.first->GotIndex = P.second;
+
+ // Create dynamic relocations.
+ for (FileGot &Got : Gots) {
+ // Create dynamic relocations for TLS entries.
+ for (std::pair<Symbol *, size_t> &P : Got.Tls) {
+ Symbol *S = P.first;
+ uint64_t Offset = P.second * Config->Wordsize;
+ if (S->IsPreemptible)
+ InX::RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S);
+ }
+ for (std::pair<Symbol *, size_t> &P : Got.DynTlsSymbols) {
+ Symbol *S = P.first;
+ uint64_t Offset = P.second * Config->Wordsize;
+ if (S == nullptr) {
+ if (!Config->Pic)
+ continue;
+ InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
+ } else {
+ // When building a shared library we still need a dynamic relocation
+ // for the module index. Therefore only checking for
+ // S->IsPreemptible is not sufficient (this happens e.g. for
+ // thread-locals that have been marked as local through a linker script)
+ if (!S->IsPreemptible && !Config->Pic)
+ continue;
+ InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
+ // However, we can skip writing the TLS offset reloc for non-preemptible
+ // symbols since it is known even in shared libraries
+ if (!S->IsPreemptible)
+ continue;
+ Offset += Config->Wordsize;
+ InX::RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S);
+ }
+ }
+
+ // Do not create dynamic relocations for non-TLS
+ // entries in the primary GOT.
+ if (&Got == PrimGot)
+ continue;
+
+ // Dynamic relocations for "global" entries.
+ for (const std::pair<Symbol *, size_t> &P : Got.Global) {
+ uint64_t Offset = P.second * Config->Wordsize;
+ InX::RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first);
+ }
+ if (!Config->Pic)
+ continue;
+ // Dynamic relocations for "local" entries in case of PIC.
+ for (const std::pair<const OutputSection *, FileGot::PageBlock> &L :
+ Got.PagesMap) {
+ size_t PageCount = L.second.Count;
+ for (size_t PI = 0; PI < PageCount; ++PI) {
+ uint64_t Offset = (L.second.FirstIndex + PI) * Config->Wordsize;
+ InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first,
+ int64_t(PI * 0x10000)});
+ }
+ }
+ for (const std::pair<GotEntry, size_t> &P : Got.Local16) {
+ uint64_t Offset = P.second * Config->Wordsize;
+ InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, true,
+ P.first.first, P.first.second});
+ }
+ }
+}
+
bool MipsGotSection::empty() const {
// We add the .got section to the result for dynamic MIPS target because
// its address and properties are mentioned in the .dynamic section.
return Config->Relocatable;
}
-uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); }
+uint64_t MipsGotSection::getGp(const InputFile *F) const {
+ // For files without related GOT or files refer a primary GOT
+ // returns "common" _gp value. For secondary GOTs calculate
+ // individual _gp values.
+ if (!F || !F->MipsGotIndex.hasValue() || *F->MipsGotIndex == 0)
+ return ElfSym::MipsGp->getVA(0);
+ return getVA() + Gots[*F->MipsGotIndex].StartIndex * Config->Wordsize +
+ 0x7ff0;
+}
void MipsGotSection::writeTo(uint8_t *Buf) {
// Set the MSB of the second GOT slot. This is not required by any
@@ -830,59 +1025,67 @@ void MipsGotSection::writeTo(uint8_t *Buf) {
// keep doing this for now. We really need to revisit this to see
// if we had to do this.
writeUint(Buf + Config->Wordsize, (uint64_t)1 << (Config->Wordsize * 8 - 1));
- Buf += HeaderEntriesNum * Config->Wordsize;
- // Write 'page address' entries to the local part of the GOT.
- for (std::pair<const OutputSection *, size_t> &L : PageIndexMap) {
- size_t PageCount = getMipsPageCount(L.first->Size);
- uint64_t FirstPageAddr = getMipsPageAddr(L.first->Addr);
- for (size_t PI = 0; PI < PageCount; ++PI) {
- uint8_t *Entry = Buf + (L.second + PI) * Config->Wordsize;
- writeUint(Entry, FirstPageAddr + PI * 0x10000);
- }
- }
- Buf += PageEntriesNum * Config->Wordsize;
- auto AddEntry = [&](const GotEntry &SA) {
- uint8_t *Entry = Buf;
- Buf += Config->Wordsize;
- const Symbol *Sym = SA.first;
- uint64_t VA = Sym->getVA(SA.second);
- if (Sym->StOther & STO_MIPS_MICROMIPS)
- VA |= 1;
- writeUint(Entry, VA);
- };
- std::for_each(std::begin(LocalEntries), std::end(LocalEntries), AddEntry);
- std::for_each(std::begin(LocalEntries32), std::end(LocalEntries32), AddEntry);
- std::for_each(std::begin(GlobalEntries), std::end(GlobalEntries), AddEntry);
- // Initialize TLS-related GOT entries. If the entry has a corresponding
- // dynamic relocations, leave it initialized by zero. Write down adjusted
- // TLS symbol's values otherwise. To calculate the adjustments use offsets
- // for thread-local storage.
- // https://www.linux-mips.org/wiki/NPTL
- if (TlsIndexOff != -1U && !Config->Pic)
- writeUint(Buf + TlsIndexOff, 1);
- for (const Symbol *B : TlsEntries) {
- if (!B || B->IsPreemptible)
- continue;
- uint64_t VA = B->getVA();
- if (B->GotIndex != -1U) {
- uint8_t *Entry = Buf + B->GotIndex * Config->Wordsize;
- writeUint(Entry, VA - 0x7000);
+ for (const FileGot &G : Gots) {
+ auto Write = [&](size_t I, const Symbol *S, int64_t A) {
+ uint64_t VA = A;
+ if (S) {
+ VA = S->getVA(A);
+ if (S->StOther & STO_MIPS_MICROMIPS)
+ VA |= 1;
+ }
+ writeUint(Buf + I * Config->Wordsize, VA);
+ };
+ // Write 'page address' entries to the local part of the GOT.
+ for (const std::pair<const OutputSection *, FileGot::PageBlock> &L :
+ G.PagesMap) {
+ size_t PageCount = L.second.Count;
+ uint64_t FirstPageAddr = getMipsPageAddr(L.first->Addr);
+ for (size_t PI = 0; PI < PageCount; ++PI)
+ Write(L.second.FirstIndex + PI, nullptr, FirstPageAddr + PI * 0x10000);
}
- if (B->GlobalDynIndex != -1U) {
- uint8_t *Entry = Buf + B->GlobalDynIndex * Config->Wordsize;
- writeUint(Entry, 1);
- Entry += Config->Wordsize;
- writeUint(Entry, VA - 0x8000);
+ // Local, global, TLS, reloc-only entries.
+ // If TLS entry has a corresponding dynamic relocations, leave it
+ // initialized by zero. Write down adjusted TLS symbol's values otherwise.
+ // To calculate the adjustments use offsets for thread-local storage.
+ // https://www.linux-mips.org/wiki/NPTL
+ for (const std::pair<GotEntry, size_t> &P : G.Local16)
+ Write(P.second, P.first.first, P.first.second);
+ // Write VA to the primary GOT only. For secondary GOTs that
+ // will be done by REL32 dynamic relocations.
+ if (&G == &Gots.front())
+ for (const std::pair<const Symbol *, size_t> &P : G.Global)
+ Write(P.second, P.first, 0);
+ for (const std::pair<Symbol *, size_t> &P : G.Relocs)
+ Write(P.second, P.first, 0);
+ for (const std::pair<Symbol *, size_t> &P : G.Tls)
+ Write(P.second, P.first, P.first->IsPreemptible ? 0 : -0x7000);
+ for (const std::pair<Symbol *, size_t> &P : G.DynTlsSymbols) {
+ if (P.first == nullptr && !Config->Pic)
+ Write(P.second, nullptr, 1);
+ else if (P.first && !P.first->IsPreemptible) {
+ // If we are emitting PIC code with relocations we mustn't write
+ // anything to the GOT here. When using Elf_Rel relocations the value
+ // one will be treated as an addend and will cause crashes at runtime
+ if (!Config->Pic)
+ Write(P.second, nullptr, 1);
+ Write(P.second + 1, P.first, -0x8000);
+ }
}
}
}
+// On PowerPC the .plt section is used to hold the table of function addresses
+// instead of the .got.plt, and the type is SHT_NOBITS similar to a .bss
+// section. I don't know why we have a BSS style type for the section but it is
+// consitent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.
GotPltSection::GotPltSection()
- : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
- Target->GotPltEntrySize, ".got.plt") {}
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE,
+ Config->EMachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
+ Target->GotPltEntrySize,
+ Config->EMachine == EM_PPC64 ? ".plt" : ".got.plt") {}
void GotPltSection::addEntry(Symbol &Sym) {
- Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size();
+ assert(Sym.PltIndex == Entries.size());
Entries.push_back(&Sym);
}
@@ -900,16 +1103,37 @@ void GotPltSection::writeTo(uint8_t *Buf) {
}
}
-// On ARM the IgotPltSection is part of the GotSection, on other Targets it is
-// part of the .got.plt
+bool GotPltSection::empty() const {
+ // We need to emit a GOT.PLT even if it's empty if there's a symbol that
+ // references the _GLOBAL_OFFSET_TABLE_ and the Target defines the symbol
+ // relative to the .got.plt section.
+ return Entries.empty() &&
+ !(ElfSym::GlobalOffsetTable && Target->GotBaseSymInGotPlt);
+}
+
+static StringRef getIgotPltName() {
+ // On ARM the IgotPltSection is part of the GotSection.
+ if (Config->EMachine == EM_ARM)
+ return ".got";
+
+ // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection
+ // needs to be named the same.
+ if (Config->EMachine == EM_PPC64)
+ return ".plt";
+
+ return ".got.plt";
+}
+
+// On PowerPC64 the GotPltSection type is SHT_NOBITS so we have to follow suit
+// with the IgotPltSection.
IgotPltSection::IgotPltSection()
- : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
- Target->GotPltEntrySize,
- Config->EMachine == EM_ARM ? ".got" : ".got.plt") {}
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE,
+ Config->EMachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
+ Target->GotPltEntrySize, getIgotPltName()) {}
void IgotPltSection::addEntry(Symbol &Sym) {
Sym.IsInIgot = true;
- Sym.GotPltIndex = Entries.size();
+ assert(Sym.PltIndex == Entries.size());
Entries.push_back(&Sym);
}
@@ -1005,8 +1229,14 @@ void DynamicSection<ELFT>::addInt(int32_t Tag, uint64_t Val) {
template <class ELFT>
void DynamicSection<ELFT>::addInSec(int32_t Tag, InputSection *Sec) {
+ Entries.push_back({Tag, [=] { return Sec->getVA(0); }});
+}
+
+template <class ELFT>
+void DynamicSection<ELFT>::addInSecRelative(int32_t Tag, InputSection *Sec) {
+ size_t TagOffset = Entries.size() * Entsize;
Entries.push_back(
- {Tag, [=] { return Sec->getParent()->Addr + Sec->OutSecOff; }});
+ {Tag, [=] { return Sec->getVA(0) - (getVA() + TagOffset); }});
}
template <class ELFT>
@@ -1034,6 +1264,8 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
uint32_t DtFlags1 = 0;
if (Config->Bsymbolic)
DtFlags |= DF_SYMBOLIC;
+ if (Config->ZInitfirst)
+ DtFlags1 |= DF_1_INITFIRST;
if (Config->ZNodelete)
DtFlags1 |= DF_1_NODELETE;
if (Config->ZNodlopen)
@@ -1046,6 +1278,8 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
DtFlags |= DF_ORIGIN;
DtFlags1 |= DF_1_ORIGIN;
}
+ if (!Config->ZText)
+ DtFlags |= DF_TEXTREL;
if (DtFlags)
addInt(DT_FLAGS, DtFlags);
@@ -1081,6 +1315,14 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels);
}
}
+ if (InX::RelrDyn && !InX::RelrDyn->Relocs.empty()) {
+ addInSec(Config->UseAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
+ InX::RelrDyn);
+ addSize(Config->UseAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
+ InX::RelrDyn->getParent());
+ addInt(Config->UseAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
+ sizeof(Elf_Relr));
+ }
// .rel[a].plt section usually consists of two parts, containing plt and
// iplt relocations. It is possible to have only iplt relocations in the
// output. In that case RelaPlt is empty and have zero offset, the same offset
@@ -1160,8 +1402,23 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
else
addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols());
addInSec(DT_PLTGOT, InX::MipsGot);
- if (InX::MipsRldMap)
- addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap);
+ if (InX::MipsRldMap) {
+ if (!Config->Pie)
+ addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap);
+ // Store the offset to the .rld_map section
+ // relative to the address of the tag.
+ addInSecRelative(DT_MIPS_RLD_MAP_REL, InX::MipsRldMap);
+ }
+ }
+
+ // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
+ if (Config->EMachine == EM_PPC64 && !InX::Plt->empty()) {
+ // The Glink tag points to 32 bytes before the first lazy symbol resolution
+ // stub, which starts directly after the header.
+ Entries.push_back({DT_PPC64_GLINK, [=] {
+ unsigned Offset = Target->PltHeaderSize - 32;
+ return InX::Plt->getVA(0) + Offset;
+ }});
}
addInt(DT_NULL, 0);
@@ -1181,13 +1438,16 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
}
uint64_t DynamicReloc::getOffset() const {
- return InputSec->getOutputSection()->Addr + InputSec->getOffset(OffsetInSec);
+ return InputSec->getVA(OffsetInSec);
}
-int64_t DynamicReloc::getAddend() const {
+int64_t DynamicReloc::computeAddend() const {
if (UseSymVA)
return Sym->getVA(Addend);
- return Addend;
+ if (!OutputSec)
+ return Addend;
+ // See the comment in the DynamicReloc ctor.
+ return getMipsPageAddr(OutputSec->Addr) + Addend;
}
uint32_t DynamicReloc::getSymIndex() const {
@@ -1202,6 +1462,23 @@ RelocationBaseSection::RelocationBaseSection(StringRef Name, uint32_t Type,
: SyntheticSection(SHF_ALLOC, Type, Config->Wordsize, Name),
DynamicTag(DynamicTag), SizeDynamicTag(SizeDynamicTag) {}
+void RelocationBaseSection::addReloc(RelType DynType, InputSectionBase *IS,
+ uint64_t OffsetInSec, Symbol *Sym) {
+ addReloc({DynType, IS, OffsetInSec, false, Sym, 0});
+}
+
+void RelocationBaseSection::addReloc(RelType DynType,
+ InputSectionBase *InputSec,
+ uint64_t OffsetInSec, Symbol *Sym,
+ int64_t Addend, RelExpr Expr,
+ RelType Type) {
+ // Write the addends to the relocated address if required. We skip
+ // it if the written value would be zero.
+ if (Config->WriteAddends && (Expr != R_ADDEND || Addend != 0))
+ InputSec->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym});
+ addReloc({DynType, InputSec, OffsetInSec, Expr != R_ADDEND, Sym, Addend});
+}
+
void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) {
if (Reloc.Type == Target->RelativeRel)
++NumRelativeRelocs;
@@ -1218,23 +1495,17 @@ void RelocationBaseSection::finalizeContents() {
getParent()->Link = Link;
}
+RelrBaseSection::RelrBaseSection()
+ : SyntheticSection(SHF_ALLOC,
+ Config->UseAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
+ Config->Wordsize, ".relr.dyn") {}
+
template <class ELFT>
static void encodeDynamicReloc(typename ELFT::Rela *P,
const DynamicReloc &Rel) {
if (Config->IsRela)
- P->r_addend = Rel.getAddend();
+ P->r_addend = Rel.computeAddend();
P->r_offset = Rel.getOffset();
- if (Config->EMachine == EM_MIPS && Rel.getInputSec() == InX::MipsGot)
- // The MIPS GOT section contains dynamic relocations that correspond to TLS
- // entries. These entries are placed after the global and local sections of
- // the GOT. At the point when we create these relocations, the size of the
- // global and local sections is unknown, so the offset that we store in the
- // TLS entry's DynamicReloc is relative to the start of the TLS section of
- // the GOT, rather than being relative to the start of the GOT. This line of
- // code adds the size of the global and local sections to the virtual
- // address computed by getOffset() in order to adjust it into the TLS
- // section.
- P->r_offset += InX::MipsGot->getTlsOffset();
P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->IsMips64EL);
}
@@ -1247,32 +1518,22 @@ RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort)
this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
}
-template <class ELFT, class RelTy>
-static bool compRelocations(const RelTy &A, const RelTy &B) {
- bool AIsRel = A.getType(Config->IsMips64EL) == Target->RelativeRel;
- bool BIsRel = B.getType(Config->IsMips64EL) == Target->RelativeRel;
+static bool compRelocations(const DynamicReloc &A, const DynamicReloc &B) {
+ bool AIsRel = A.Type == Target->RelativeRel;
+ bool BIsRel = B.Type == Target->RelativeRel;
if (AIsRel != BIsRel)
return AIsRel;
-
- return A.getSymbol(Config->IsMips64EL) < B.getSymbol(Config->IsMips64EL);
+ return A.getSymIndex() < B.getSymIndex();
}
template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
- uint8_t *BufBegin = Buf;
+ if (Sort)
+ std::stable_sort(Relocs.begin(), Relocs.end(), compRelocations);
+
for (const DynamicReloc &Rel : Relocs) {
encodeDynamicReloc<ELFT>(reinterpret_cast<Elf_Rela *>(Buf), Rel);
Buf += Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
}
-
- if (Sort) {
- if (Config->IsRela)
- std::stable_sort((Elf_Rela *)BufBegin,
- (Elf_Rela *)BufBegin + Relocs.size(),
- compRelocations<ELFT, Elf_Rela>);
- else
- std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(),
- compRelocations<ELFT, Elf_Rel>);
- }
}
template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
@@ -1360,10 +1621,10 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
NonRelatives.push_back(R);
}
- std::sort(Relatives.begin(), Relatives.end(),
- [](const Elf_Rel &A, const Elf_Rel &B) {
- return A.r_offset < B.r_offset;
- });
+ llvm::sort(Relatives.begin(), Relatives.end(),
+ [](const Elf_Rel &A, const Elf_Rel &B) {
+ return A.r_offset < B.r_offset;
+ });
// Try to find groups of relative relocations which are spaced one word
// apart from one another. These generally correspond to vtable entries. The
@@ -1441,10 +1702,10 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
}
// Finally the non-relative relocations.
- std::sort(NonRelatives.begin(), NonRelatives.end(),
- [](const Elf_Rela &A, const Elf_Rela &B) {
- return A.r_offset < B.r_offset;
- });
+ llvm::sort(NonRelatives.begin(), NonRelatives.end(),
+ [](const Elf_Rela &A, const Elf_Rela &B) {
+ return A.r_offset < B.r_offset;
+ });
if (!NonRelatives.empty()) {
Add(NonRelatives.size());
Add(HasAddendIfRela);
@@ -1467,6 +1728,97 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
return RelocData.size() != OldSize;
}
+template <class ELFT> RelrSection<ELFT>::RelrSection() {
+ this->Entsize = Config->Wordsize;
+}
+
+template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
+ // This function computes the contents of an SHT_RELR packed relocation
+ // section.
+ //
+ // Proposal for adding SHT_RELR sections to generic-abi is here:
+ // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+ //
+ // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks
+ // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ]
+ //
+ // i.e. start with an address, followed by any number of bitmaps. The address
+ // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63
+ // relocations each, at subsequent offsets following the last address entry.
+ //
+ // The bitmap entries must have 1 in the least significant bit. The assumption
+ // here is that an address cannot have 1 in lsb. Odd addresses are not
+ // supported.
+ //
+ // Excluding the least significant bit in the bitmap, each non-zero bit in
+ // the bitmap represents a relocation to be applied to a corresponding machine
+ // word that follows the base address word. The second least significant bit
+ // represents the machine word immediately following the initial address, and
+ // each bit that follows represents the next word, in linear order. As such,
+ // a single bitmap can encode up to 31 relocations in a 32-bit object, and
+ // 63 relocations in a 64-bit object.
+ //
+ // This encoding has a couple of interesting properties:
+ // 1. Looking at any entry, it is clear whether it's an address or a bitmap:
+ // even means address, odd means bitmap.
+ // 2. Just a simple list of addresses is a valid encoding.
+
+ size_t OldSize = RelrRelocs.size();
+ RelrRelocs.clear();
+
+ // Same as Config->Wordsize but faster because this is a compile-time
+ // constant.
+ const size_t Wordsize = sizeof(typename ELFT::uint);
+
+ // Number of bits to use for the relocation offsets bitmap.
+ // Must be either 63 or 31.
+ const size_t NBits = Wordsize * 8 - 1;
+
+ // Get offsets for all relative relocations and sort them.
+ std::vector<uint64_t> Offsets;
+ for (const RelativeReloc &Rel : Relocs)
+ Offsets.push_back(Rel.getOffset());
+ llvm::sort(Offsets.begin(), Offsets.end());
+
+ // For each leading relocation, find following ones that can be folded
+ // as a bitmap and fold them.
+ for (size_t I = 0, E = Offsets.size(); I < E;) {
+ // Add a leading relocation.
+ RelrRelocs.push_back(Elf_Relr(Offsets[I]));
+ uint64_t Base = Offsets[I] + Wordsize;
+ ++I;
+
+ // Find foldable relocations to construct bitmaps.
+ while (I < E) {
+ uint64_t Bitmap = 0;
+
+ while (I < E) {
+ uint64_t Delta = Offsets[I] - Base;
+
+ // If it is too far, it cannot be folded.
+ if (Delta >= NBits * Wordsize)
+ break;
+
+ // If it is not a multiple of wordsize away, it cannot be folded.
+ if (Delta % Wordsize)
+ break;
+
+ // Fold it.
+ Bitmap |= 1ULL << (Delta / Wordsize);
+ ++I;
+ }
+
+ if (!Bitmap)
+ break;
+
+ RelrRelocs.push_back(Elf_Relr((Bitmap << 1) | 1));
+ Base += NBits * Wordsize;
+ }
+ }
+
+ return RelrRelocs.size() != OldSize;
+}
+
SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec)
: SyntheticSection(StrTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0,
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
@@ -1482,50 +1834,70 @@ SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec)
static bool sortMipsSymbols(const SymbolTableEntry &L,
const SymbolTableEntry &R) {
// Sort entries related to non-local preemptible symbols by GOT indexes.
- // All other entries go to the first part of GOT in arbitrary order.
- bool LIsInLocalGot = !L.Sym->IsInGlobalMipsGot;
- bool RIsInLocalGot = !R.Sym->IsInGlobalMipsGot;
- if (LIsInLocalGot || RIsInLocalGot)
- return !RIsInLocalGot;
- return L.Sym->GotIndex < R.Sym->GotIndex;
+ // All other entries go to the beginning of a dynsym in arbitrary order.
+ if (L.Sym->isInGot() && R.Sym->isInGot())
+ return L.Sym->GotIndex < R.Sym->GotIndex;
+ if (!L.Sym->isInGot() && !R.Sym->isInGot())
+ return false;
+ return !L.Sym->isInGot();
}
void SymbolTableBaseSection::finalizeContents() {
getParent()->Link = StrTabSec.getParent()->SectionIndex;
+ if (this->Type != SHT_DYNSYM)
+ return;
+
// If it is a .dynsym, there should be no local symbols, but we need
// to do a few things for the dynamic linker.
- if (this->Type == SHT_DYNSYM) {
- // Section's Info field has the index of the first non-local symbol.
- // Because the first symbol entry is a null entry, 1 is the first.
- getParent()->Info = 1;
-
- if (InX::GnuHashTab) {
- // NB: It also sorts Symbols to meet the GNU hash table requirements.
- InX::GnuHashTab->addSymbols(Symbols);
- } else if (Config->EMachine == EM_MIPS) {
- std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
- }
- size_t I = 0;
- for (const SymbolTableEntry &S : Symbols) S.Sym->DynsymIndex = ++I;
- return;
+ // Section's Info field has the index of the first non-local symbol.
+ // Because the first symbol entry is a null entry, 1 is the first.
+ getParent()->Info = 1;
+
+ if (InX::GnuHashTab) {
+ // NB: It also sorts Symbols to meet the GNU hash table requirements.
+ InX::GnuHashTab->addSymbols(Symbols);
+ } else if (Config->EMachine == EM_MIPS) {
+ std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
}
+
+ size_t I = 0;
+ for (const SymbolTableEntry &S : Symbols)
+ S.Sym->DynsymIndex = ++I;
}
// The ELF spec requires that all local symbols precede global symbols, so we
// sort symbol entries in this function. (For .dynsym, we don't do that because
// symbols for dynamic linking are inherently all globals.)
+//
+// Aside from above, we put local symbols in groups starting with the STT_FILE
+// symbol. That is convenient for purpose of identifying where are local symbols
+// coming from.
void SymbolTableBaseSection::postThunkContents() {
- if (this->Type == SHT_DYNSYM)
- return;
- // move all local symbols before global symbols.
- auto It = std::stable_partition(
+ assert(this->Type == SHT_SYMTAB);
+
+ // Move all local symbols before global symbols.
+ auto E = std::stable_partition(
Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {
return S.Sym->isLocal() || S.Sym->computeBinding() == STB_LOCAL;
});
- size_t NumLocals = It - Symbols.begin();
+ size_t NumLocals = E - Symbols.begin();
getParent()->Info = NumLocals + 1;
+
+ // We want to group the local symbols by file. For that we rebuild the local
+ // part of the symbols vector. We do not need to care about the STT_FILE
+ // symbols, they are already naturally placed first in each group. That
+ // happens because STT_FILE is always the first symbol in the object and hence
+ // precede all other local symbols we add for a file.
+ MapVector<InputFile *, std::vector<SymbolTableEntry>> Arr;
+ for (const SymbolTableEntry &S : llvm::make_range(Symbols.begin(), E))
+ Arr[S.Sym->File].push_back(S);
+
+ auto I = Symbols.begin();
+ for (std::pair<InputFile *, std::vector<SymbolTableEntry>> &P : Arr)
+ for (SymbolTableEntry &Entry : P.second)
+ *I++ = Entry;
}
void SymbolTableBaseSection::addSymbol(Symbol *B) {
@@ -1563,6 +1935,23 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec)
this->Entsize = sizeof(Elf_Sym);
}
+static BssSection *getCommonSec(Symbol *Sym) {
+ if (!Config->DefineCommon)
+ if (auto *D = dyn_cast<Defined>(Sym))
+ return dyn_cast_or_null<BssSection>(D->Section);
+ return nullptr;
+}
+
+static uint32_t getSymSectionIndex(Symbol *Sym) {
+ if (getCommonSec(Sym))
+ return SHN_COMMON;
+ if (!isa<Defined>(Sym) || Sym->NeedsPltAddr)
+ return SHN_UNDEF;
+ if (const OutputSection *OS = Sym->getOutputSection())
+ return OS->SectionIndex >= SHN_LORESERVE ? SHN_XINDEX : OS->SectionIndex;
+ return SHN_ABS;
+}
+
// Write the internal symbol table contents to the output symbol table.
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
// The first entry is a null entry as per the ELF spec.
@@ -1584,20 +1973,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
}
ESym->st_name = Ent.StrTabOffset;
-
- // Set a section index.
- BssSection *CommonSec = nullptr;
- if (!Config->DefineCommon)
- if (auto *D = dyn_cast<Defined>(Sym))
- CommonSec = dyn_cast_or_null<BssSection>(D->Section);
- if (CommonSec)
- ESym->st_shndx = SHN_COMMON;
- else if (const OutputSection *OutSec = Sym->getOutputSection())
- ESym->st_shndx = OutSec->SectionIndex;
- else if (isa<Defined>(Sym))
- ESym->st_shndx = SHN_ABS;
- else
- ESym->st_shndx = SHN_UNDEF;
+ ESym->st_shndx = getSymSectionIndex(Ent.Sym);
// Copy symbol size if it is a defined symbol. st_size is not significant
// for undefined symbols, so whether copying it or not is up to us if that's
@@ -1612,7 +1988,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
// st_value is usually an address of a symbol, but that has a
// special meaining for uninstantiated common symbols (this can
// occur if -r is given).
- if (CommonSec)
+ if (BssSection *CommonSec = getCommonSec(Ent.Sym))
ESym->st_value = CommonSec->Alignment;
else
ESym->st_value = Sym->getVA();
@@ -1633,9 +2009,11 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
ESym->st_other |= STO_MIPS_PLT;
if (isMicroMips()) {
// Set STO_MIPS_MICROMIPS flag and less-significant bit for
- // defined microMIPS symbols and shared symbols with PLT record.
- if ((Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) ||
- (Sym->isShared() && Sym->NeedsPltAddr)) {
+ // a defined microMIPS symbol and symbol should point to its
+ // PLT entry (in case of microMIPS, PLT entries always contain
+ // microMIPS code).
+ if (Sym->isDefined() &&
+ ((Sym->StOther & STO_MIPS_MICROMIPS) || Sym->NeedsPltAddr)) {
if (StrTabSec.isDynamic())
ESym->st_value |= 1;
ESym->st_other |= STO_MIPS_MICROMIPS;
@@ -1650,6 +2028,44 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
}
}
+SymtabShndxSection::SymtabShndxSection()
+ : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndxr") {
+ this->Entsize = 4;
+}
+
+void SymtabShndxSection::writeTo(uint8_t *Buf) {
+ // We write an array of 32 bit values, where each value has 1:1 association
+ // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX,
+ // we need to write actual index, otherwise, we must write SHN_UNDEF(0).
+ Buf += 4; // Ignore .symtab[0] entry.
+ for (const SymbolTableEntry &Entry : InX::SymTab->getSymbols()) {
+ if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX)
+ write32(Buf, Entry.Sym->getOutputSection()->SectionIndex);
+ Buf += 4;
+ }
+}
+
+bool SymtabShndxSection::empty() const {
+ // SHT_SYMTAB can hold symbols with section indices values up to
+ // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX
+ // section. Problem is that we reveal the final section indices a bit too
+ // late, and we do not know them here. For simplicity, we just always create
+ // a .symtab_shndxr section when the amount of output sections is huge.
+ size_t Size = 0;
+ for (BaseCommand *Base : Script->SectionCommands)
+ if (isa<OutputSection>(Base))
+ ++Size;
+ return Size < SHN_LORESERVE;
+}
+
+void SymtabShndxSection::finalizeContents() {
+ getParent()->Link = InX::SymTab->getParent()->SectionIndex;
+}
+
+size_t SymtabShndxSection::getSize() const {
+ return InX::SymTab->getNumSymbols() * 4;
+}
+
// .hash and .gnu.hash sections contain on-disk hash tables that map
// symbol names to their dynamic symbol table indices. Their purpose
// is to help the dynamic linker resolve symbols quickly. If ELF files
@@ -1688,12 +2104,14 @@ GnuHashTableSection::GnuHashTableSection()
void GnuHashTableSection::finalizeContents() {
getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
- // Computes bloom filter size in word size. We want to allocate 8
+ // Computes bloom filter size in word size. We want to allocate 12
// bits for each symbol. It must be a power of two.
- if (Symbols.empty())
+ if (Symbols.empty()) {
MaskWords = 1;
- else
- MaskWords = NextPowerOf2((Symbols.size() - 1) / Config->Wordsize);
+ } else {
+ uint64_t NumBits = Symbols.size() * 12;
+ MaskWords = NextPowerOf2(NumBits / (Config->Wordsize * 8));
+ }
Size = 16; // Header
Size += Config->Wordsize * MaskWords; // Bloom filter
@@ -1711,7 +2129,7 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {
write32(Buf, NBuckets);
write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size());
write32(Buf + 8, MaskWords);
- write32(Buf + 12, getShift2());
+ write32(Buf + 12, Shift2);
Buf += 16;
// Write a bloom filter and a hash table.
@@ -1728,12 +2146,12 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {
// [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2),
// p.9, https://www.akkadia.org/drepper/dsohowto.pdf
void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) {
- const unsigned C = Config->Wordsize * 8;
+ unsigned C = Config->Is64 ? 64 : 32;
for (const Entry &Sym : Symbols) {
size_t I = (Sym.Hash / C) & (MaskWords - 1);
uint64_t Val = readUint(Buf + I * Config->Wordsize);
Val |= uint64_t(1) << (Sym.Hash % C);
- Val |= uint64_t(1) << ((Sym.Hash >> getShift2()) % C);
+ Val |= uint64_t(1) << ((Sym.Hash >> Shift2) % C);
writeUint(Buf + I * Config->Wordsize, Val);
}
}
@@ -1775,21 +2193,23 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) {
// its type correctly.
std::vector<SymbolTableEntry>::iterator Mid =
std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) {
- // Shared symbols that this executable preempts are special. The dynamic
- // linker has to look them up, so they have to be in the hash table.
- if (auto *SS = dyn_cast<SharedSymbol>(S.Sym))
- return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr;
return !S.Sym->isDefined();
});
- if (Mid == V.end())
- return;
// We chose load factor 4 for the on-disk hash table. For each hash
// collision, the dynamic linker will compare a uint32_t hash value.
- // Since the integer comparison is quite fast, we believe we can make
- // the load factor even larger. 4 is just a conservative choice.
+ // Since the integer comparison is quite fast, we believe we can
+ // make the load factor even larger. 4 is just a conservative choice.
+ //
+ // Note that we don't want to create a zero-sized hash table because
+ // Android loader as of 2018 doesn't like a .gnu.hash containing such
+ // table. If that's the case, we create a hash table with one unused
+ // dummy slot.
NBuckets = std::max<size_t>((V.end() - Mid) / 4, 1);
+ if (Mid == V.end())
+ return;
+
for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) {
Symbol *B = Ent.Sym;
uint32_t Hash = hashGnu(B->getName());
@@ -1845,9 +2265,12 @@ void HashTableSection::writeTo(uint8_t *Buf) {
}
}
-PltSection::PltSection(size_t S)
- : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"),
- HeaderSize(S) {
+// On PowerPC64 the lazy symbol resolvers go into the `global linkage table`
+// in the .glink section, rather then the typical .plt section.
+PltSection::PltSection(bool IsIplt)
+ : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
+ Config->EMachine == EM_PPC64 ? ".glink" : ".plt"),
+ HeaderSize(IsIplt ? 0 : Target->PltHeaderSize), IsIplt(IsIplt) {
// The PLT needs to be writable on SPARC as the dynamic linker will
// modify the instructions in the PLT entries.
if (Config->EMachine == EM_SPARCV9)
@@ -1857,7 +2280,7 @@ PltSection::PltSection(size_t S)
void PltSection::writeTo(uint8_t *Buf) {
// At beginning of PLT but not the IPLT, we have code to call the dynamic
// linker to resolve dynsyms at runtime. Write such code.
- if (HeaderSize != 0)
+ if (!IsIplt)
Target->writePltHeader(Buf);
size_t Off = HeaderSize;
// The IPlt is immediately after the Plt, account for this in RelOff
@@ -1876,7 +2299,7 @@ void PltSection::writeTo(uint8_t *Buf) {
template <class ELFT> void PltSection::addEntry(Symbol &Sym) {
Sym.PltIndex = Entries.size();
RelocationBaseSection *PltRelocSection = InX::RelaPlt;
- if (HeaderSize == 0) {
+ if (IsIplt) {
PltRelocSection = InX::RelaIplt;
Sym.IsInIplt = true;
}
@@ -1893,7 +2316,7 @@ size_t PltSection::getSize() const {
// example ARM uses mapping symbols to aid disassembly
void PltSection::addSymbols() {
// The PLT may have symbols defined for the Header, the IPLT has no header
- if (HeaderSize != 0)
+ if (!IsIplt)
Target->addPltHeaderSymbols(*this);
size_t Off = HeaderSize;
for (size_t I = 0; I < Entries.size(); ++I) {
@@ -1903,7 +2326,7 @@ void PltSection::addSymbols() {
}
unsigned PltSection::getPltRelocOff() const {
- return (HeaderSize == 0) ? InX::Plt->getSize() : 0;
+ return IsIplt ? InX::Plt->getSize() : 0;
}
// The string hash function for .gdb_index.
@@ -1914,16 +2337,48 @@ static uint32_t computeGdbHash(StringRef S) {
return H;
}
-static std::vector<GdbIndexChunk::CuEntry> readCuList(DWARFContext &Dwarf) {
- std::vector<GdbIndexChunk::CuEntry> Ret;
+GdbIndexSection::GdbIndexSection()
+ : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index") {}
+
+// Returns the desired size of an on-disk hash table for a .gdb_index section.
+// There's a tradeoff between size and collision rate. We aim 75% utilization.
+size_t GdbIndexSection::computeSymtabSize() const {
+ return std::max<size_t>(NextPowerOf2(Symbols.size() * 4 / 3), 1024);
+}
+
+// Compute the output section size.
+void GdbIndexSection::initOutputSize() {
+ Size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8;
+
+ for (GdbChunk &Chunk : Chunks)
+ Size += Chunk.CompilationUnits.size() * 16 + Chunk.AddressAreas.size() * 20;
+
+ // Add the constant pool size if exists.
+ if (!Symbols.empty()) {
+ GdbSymbol &Sym = Symbols.back();
+ Size += Sym.NameOff + Sym.Name.size() + 1;
+ }
+}
+
+static std::vector<InputSection *> getDebugInfoSections() {
+ std::vector<InputSection *> Ret;
+ for (InputSectionBase *S : InputSections)
+ if (InputSection *IS = dyn_cast<InputSection>(S))
+ if (IS->Name == ".debug_info")
+ Ret.push_back(IS);
+ return Ret;
+}
+
+static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &Dwarf) {
+ std::vector<GdbIndexSection::CuEntry> Ret;
for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units())
Ret.push_back({Cu->getOffset(), Cu->getLength() + 4});
return Ret;
}
-static std::vector<GdbIndexChunk::AddressEntry>
+static std::vector<GdbIndexSection::AddressEntry>
readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {
- std::vector<GdbIndexChunk::AddressEntry> Ret;
+ std::vector<GdbIndexSection::AddressEntry> Ret;
uint32_t CuIdx = 0;
for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) {
@@ -1947,218 +2402,192 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {
return Ret;
}
-static std::vector<GdbIndexChunk::NameTypeEntry>
-readPubNamesAndTypes(DWARFContext &Dwarf) {
+static std::vector<GdbIndexSection::NameTypeEntry>
+readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) {
StringRef Sec1 = Dwarf.getDWARFObj().getGnuPubNamesSection();
StringRef Sec2 = Dwarf.getDWARFObj().getGnuPubTypesSection();
- std::vector<GdbIndexChunk::NameTypeEntry> Ret;
+ std::vector<GdbIndexSection::NameTypeEntry> Ret;
for (StringRef Sec : {Sec1, Sec2}) {
DWARFDebugPubTable Table(Sec, Config->IsLE, true);
- for (const DWARFDebugPubTable::Set &Set : Table.getData()) {
- for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) {
- CachedHashStringRef S(Ent.Name, computeGdbHash(Ent.Name));
- Ret.push_back({S, Ent.Descriptor.toBits()});
- }
- }
+ for (const DWARFDebugPubTable::Set &Set : Table.getData())
+ for (const DWARFDebugPubTable::Entry &Ent : Set.Entries)
+ Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)},
+ (Ent.Descriptor.toBits() << 24) | Idx});
}
return Ret;
}
-static std::vector<InputSection *> getDebugInfoSections() {
- std::vector<InputSection *> Ret;
- for (InputSectionBase *S : InputSections)
- if (InputSection *IS = dyn_cast<InputSection>(S))
- if (IS->Name == ".debug_info")
- Ret.push_back(IS);
- return Ret;
-}
+// Create a list of symbols from a given list of symbol names and types
+// by uniquifying them by name.
+static std::vector<GdbIndexSection::GdbSymbol>
+createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) {
+ typedef GdbIndexSection::GdbSymbol GdbSymbol;
+ typedef GdbIndexSection::NameTypeEntry NameTypeEntry;
-void GdbIndexSection::fixCuIndex() {
- uint32_t Idx = 0;
- for (GdbIndexChunk &Chunk : Chunks) {
- for (GdbIndexChunk::AddressEntry &Ent : Chunk.AddressAreas)
- Ent.CuIndex += Idx;
- Idx += Chunk.CompilationUnits.size();
- }
-}
+ // The number of symbols we will handle in this function is of the order
+ // of millions for very large executables, so we use multi-threading to
+ // speed it up.
+ size_t NumShards = 32;
+ size_t Concurrency = 1;
+ if (ThreadsEnabled)
+ Concurrency =
+ std::min<size_t>(PowerOf2Floor(hardware_concurrency()), NumShards);
-std::vector<std::vector<uint32_t>> GdbIndexSection::createCuVectors() {
- std::vector<std::vector<uint32_t>> Ret;
- uint32_t Idx = 0;
- uint32_t Off = 0;
+ // A sharded map to uniquify symbols by name.
+ std::vector<DenseMap<CachedHashStringRef, size_t>> Map(NumShards);
+ size_t Shift = 32 - countTrailingZeros(NumShards);
- for (GdbIndexChunk &Chunk : Chunks) {
- for (GdbIndexChunk::NameTypeEntry &Ent : Chunk.NamesAndTypes) {
- GdbSymbol *&Sym = Symbols[Ent.Name];
- if (!Sym) {
- Sym = make<GdbSymbol>(GdbSymbol{Ent.Name.hash(), Off, Ret.size()});
- Off += Ent.Name.size() + 1;
- Ret.push_back({});
- }
+ // Instantiate GdbSymbols while uniqufying them by name.
+ std::vector<std::vector<GdbSymbol>> Symbols(NumShards);
+ parallelForEachN(0, Concurrency, [&](size_t ThreadId) {
+ for (ArrayRef<NameTypeEntry> Entries : NameTypes) {
+ for (const NameTypeEntry &Ent : Entries) {
+ size_t ShardId = Ent.Name.hash() >> Shift;
+ if ((ShardId & (Concurrency - 1)) != ThreadId)
+ continue;
+
+ size_t &Idx = Map[ShardId][Ent.Name];
+ if (Idx) {
+ Symbols[ShardId][Idx - 1].CuVector.push_back(Ent.Type);
+ continue;
+ }
- // gcc 5.4.1 produces a buggy .debug_gnu_pubnames that contains
- // duplicate entries, so we want to dedup them.
- std::vector<uint32_t> &Vec = Ret[Sym->CuVectorIndex];
- uint32_t Val = (Ent.Type << 24) | Idx;
- if (Vec.empty() || Vec.back() != Val)
- Vec.push_back(Val);
+ Idx = Symbols[ShardId].size() + 1;
+ Symbols[ShardId].push_back({Ent.Name, {Ent.Type}, 0, 0});
+ }
}
- Idx += Chunk.CompilationUnits.size();
+ });
+
+ size_t NumSymbols = 0;
+ for (ArrayRef<GdbSymbol> V : Symbols)
+ NumSymbols += V.size();
+
+ // The return type is a flattened vector, so we'll copy each vector
+ // contents to Ret.
+ std::vector<GdbSymbol> Ret;
+ Ret.reserve(NumSymbols);
+ for (std::vector<GdbSymbol> &Vec : Symbols)
+ for (GdbSymbol &Sym : Vec)
+ Ret.push_back(std::move(Sym));
+
+ // CU vectors and symbol names are adjacent in the output file.
+ // We can compute their offsets in the output file now.
+ size_t Off = 0;
+ for (GdbSymbol &Sym : Ret) {
+ Sym.CuVectorOff = Off;
+ Off += (Sym.CuVector.size() + 1) * 4;
+ }
+ for (GdbSymbol &Sym : Ret) {
+ Sym.NameOff = Off;
+ Off += Sym.Name.size() + 1;
}
- StringPoolSize = Off;
return Ret;
}
-template <class ELFT> GdbIndexSection *elf::createGdbIndex() {
- // Gather debug info to create a .gdb_index section.
+// Returns a newly-created .gdb_index section.
+template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
std::vector<InputSection *> Sections = getDebugInfoSections();
- std::vector<GdbIndexChunk> Chunks(Sections.size());
-
- parallelForEachN(0, Chunks.size(), [&](size_t I) {
- ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>();
- DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(File));
-
- Chunks[I].DebugInfoSec = Sections[I];
- Chunks[I].CompilationUnits = readCuList(Dwarf);
- Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]);
- Chunks[I].NamesAndTypes = readPubNamesAndTypes(Dwarf);
- });
// .debug_gnu_pub{names,types} are useless in executables.
// They are present in input object files solely for creating
- // a .gdb_index. So we can remove it from the output.
+ // a .gdb_index. So we can remove them from the output.
for (InputSectionBase *S : InputSections)
if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes")
S->Live = false;
- // Create a .gdb_index and returns it.
- return make<GdbIndexSection>(std::move(Chunks));
-}
-
-static size_t getCuSize(ArrayRef<GdbIndexChunk> Arr) {
- size_t Ret = 0;
- for (const GdbIndexChunk &D : Arr)
- Ret += D.CompilationUnits.size();
- return Ret;
-}
-
-static size_t getAddressAreaSize(ArrayRef<GdbIndexChunk> Arr) {
- size_t Ret = 0;
- for (const GdbIndexChunk &D : Arr)
- Ret += D.AddressAreas.size();
- return Ret;
-}
-
-std::vector<GdbSymbol *> GdbIndexSection::createGdbSymtab() {
- uint32_t Size = NextPowerOf2(Symbols.size() * 4 / 3);
- if (Size < 1024)
- Size = 1024;
+ std::vector<GdbChunk> Chunks(Sections.size());
+ std::vector<std::vector<NameTypeEntry>> NameTypes(Sections.size());
- uint32_t Mask = Size - 1;
- std::vector<GdbSymbol *> Ret(Size);
+ parallelForEachN(0, Sections.size(), [&](size_t I) {
+ ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>();
+ DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(File));
- for (auto &KV : Symbols) {
- GdbSymbol *Sym = KV.second;
- uint32_t I = Sym->NameHash & Mask;
- uint32_t Step = ((Sym->NameHash * 17) & Mask) | 1;
+ Chunks[I].Sec = Sections[I];
+ Chunks[I].CompilationUnits = readCuList(Dwarf);
+ Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]);
+ NameTypes[I] = readPubNamesAndTypes(Dwarf, I);
+ });
- while (Ret[I])
- I = (I + Step) & Mask;
- Ret[I] = Sym;
- }
+ auto *Ret = make<GdbIndexSection>();
+ Ret->Chunks = std::move(Chunks);
+ Ret->Symbols = createSymbols(NameTypes);
+ Ret->initOutputSize();
return Ret;
}
-GdbIndexSection::GdbIndexSection(std::vector<GdbIndexChunk> &&C)
- : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"), Chunks(std::move(C)) {
- fixCuIndex();
- CuVectors = createCuVectors();
- GdbSymtab = createGdbSymtab();
-
- // Compute offsets early to know the section size.
- // Each chunk size needs to be in sync with what we write in writeTo.
- CuTypesOffset = CuListOffset + getCuSize(Chunks) * 16;
- SymtabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * 20;
- ConstantPoolOffset = SymtabOffset + GdbSymtab.size() * 8;
-
- size_t Off = 0;
- for (ArrayRef<uint32_t> Vec : CuVectors) {
- CuVectorOffsets.push_back(Off);
- Off += (Vec.size() + 1) * 4;
- }
- StringPoolOffset = ConstantPoolOffset + Off;
-}
-
-size_t GdbIndexSection::getSize() const {
- return StringPoolOffset + StringPoolSize;
-}
-
void GdbIndexSection::writeTo(uint8_t *Buf) {
- // Write the section header.
- write32le(Buf, 7);
- write32le(Buf + 4, CuListOffset);
- write32le(Buf + 8, CuTypesOffset);
- write32le(Buf + 12, CuTypesOffset);
- write32le(Buf + 16, SymtabOffset);
- write32le(Buf + 20, ConstantPoolOffset);
- Buf += 24;
+ // Write the header.
+ auto *Hdr = reinterpret_cast<GdbIndexHeader *>(Buf);
+ uint8_t *Start = Buf;
+ Hdr->Version = 7;
+ Buf += sizeof(*Hdr);
// Write the CU list.
- for (GdbIndexChunk &D : Chunks) {
- for (GdbIndexChunk::CuEntry &Cu : D.CompilationUnits) {
- write64le(Buf, D.DebugInfoSec->OutSecOff + Cu.CuOffset);
+ Hdr->CuListOff = Buf - Start;
+ for (GdbChunk &Chunk : Chunks) {
+ for (CuEntry &Cu : Chunk.CompilationUnits) {
+ write64le(Buf, Chunk.Sec->OutSecOff + Cu.CuOffset);
write64le(Buf + 8, Cu.CuLength);
Buf += 16;
}
}
// Write the address area.
- for (GdbIndexChunk &D : Chunks) {
- for (GdbIndexChunk::AddressEntry &E : D.AddressAreas) {
- uint64_t BaseAddr =
- E.Section->getParent()->Addr + E.Section->getOffset(0);
+ Hdr->CuTypesOff = Buf - Start;
+ Hdr->AddressAreaOff = Buf - Start;
+ uint32_t CuOff = 0;
+ for (GdbChunk &Chunk : Chunks) {
+ for (AddressEntry &E : Chunk.AddressAreas) {
+ uint64_t BaseAddr = E.Section->getVA(0);
write64le(Buf, BaseAddr + E.LowAddress);
write64le(Buf + 8, BaseAddr + E.HighAddress);
- write32le(Buf + 16, E.CuIndex);
+ write32le(Buf + 16, E.CuIndex + CuOff);
Buf += 20;
}
+ CuOff += Chunk.CompilationUnits.size();
}
- // Write the symbol table.
- for (GdbSymbol *Sym : GdbSymtab) {
- if (Sym) {
- write32le(Buf, Sym->NameOffset + StringPoolOffset - ConstantPoolOffset);
- write32le(Buf + 4, CuVectorOffsets[Sym->CuVectorIndex]);
- }
- Buf += 8;
+ // Write the on-disk open-addressing hash table containing symbols.
+ Hdr->SymtabOff = Buf - Start;
+ size_t SymtabSize = computeSymtabSize();
+ uint32_t Mask = SymtabSize - 1;
+
+ for (GdbSymbol &Sym : Symbols) {
+ uint32_t H = Sym.Name.hash();
+ uint32_t I = H & Mask;
+ uint32_t Step = ((H * 17) & Mask) | 1;
+
+ while (read32le(Buf + I * 8))
+ I = (I + Step) & Mask;
+
+ write32le(Buf + I * 8, Sym.NameOff);
+ write32le(Buf + I * 8 + 4, Sym.CuVectorOff);
}
+ Buf += SymtabSize * 8;
+
+ // Write the string pool.
+ Hdr->ConstantPoolOff = Buf - Start;
+ for (GdbSymbol &Sym : Symbols)
+ memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size());
+
// Write the CU vectors.
- for (ArrayRef<uint32_t> Vec : CuVectors) {
- write32le(Buf, Vec.size());
+ for (GdbSymbol &Sym : Symbols) {
+ write32le(Buf, Sym.CuVector.size());
Buf += 4;
- for (uint32_t Val : Vec) {
+ for (uint32_t Val : Sym.CuVector) {
write32le(Buf, Val);
Buf += 4;
}
}
-
- // Write the string pool.
- for (auto &KV : Symbols) {
- CachedHashStringRef S = KV.first;
- GdbSymbol *Sym = KV.second;
- size_t Off = Sym->NameOffset;
- memcpy(Buf + Off, S.val().data(), S.size());
- Buf[Off + S.size()] = '\0';
- }
}
bool GdbIndexSection::empty() const { return !Out::DebugInfo; }
EhFrameHeader::EhFrameHeader()
- : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame_hdr") {}
+ : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {}
// .eh_frame_hdr contains a binary search table of pointers to FDEs.
// Each entry of the search table consists of two values,
@@ -2169,14 +2598,6 @@ void EhFrameHeader::writeTo(uint8_t *Buf) {
std::vector<FdeData> Fdes = InX::EhFrame->getFdeData();
- // Sort the FDE list by their PC and uniqueify. Usually there is only
- // one FDE for a PC (i.e. function), but if ICF merges two functions
- // into one, there can be more than one FDEs pointing to the address.
- auto Less = [](const FdeData &A, const FdeData &B) { return A.Pc < B.Pc; };
- std::stable_sort(Fdes.begin(), Fdes.end(), Less);
- auto Eq = [](const FdeData &A, const FdeData &B) { return A.Pc == B.Pc; };
- Fdes.erase(std::unique(Fdes.begin(), Fdes.end(), Eq), Fdes.end());
-
Buf[0] = 1;
Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
Buf[2] = DW_EH_PE_udata4;
@@ -2185,10 +2606,9 @@ void EhFrameHeader::writeTo(uint8_t *Buf) {
write32(Buf + 8, Fdes.size());
Buf += 12;
- uint64_t VA = this->getVA();
for (FdeData &Fde : Fdes) {
- write32(Buf, Fde.Pc - VA);
- write32(Buf + 4, Fde.FdeVA - VA);
+ write32(Buf, Fde.PcRel);
+ write32(Buf + 4, Fde.FdeVARel);
Buf += 8;
}
}
@@ -2298,11 +2718,9 @@ VersionNeedSection<ELFT>::VersionNeedSection()
NextIndex = getVerDefNum() + 1;
}
-template <class ELFT>
-void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
- SharedFile<ELFT> &File = SS->getFile<ELFT>();
- const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
- if (!Ver) {
+template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {
+ auto &File = cast<SharedFile<ELFT>>(*SS->File);
+ if (SS->VerdefIndex == VER_NDX_GLOBAL) {
SS->VersionId = VER_NDX_GLOBAL;
return;
}
@@ -2312,7 +2730,9 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
// for the soname.
if (File.VerdefMap.empty())
Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)});
+ const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver];
+
// If we don't already know that we need an Elf_Vernaux for this Elf_Verdef,
// prepare to create one by allocating a version identifier and creating a
// dynstr entry for the version name.
@@ -2476,11 +2896,20 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef Name,
return make<MergeNoTailSection>(Name, Type, Flags, Alignment);
}
-// Debug sections may be compressed by zlib. Uncompress if exists.
+// Debug sections may be compressed by zlib. Decompress if exists.
void elf::decompressSections() {
+ parallelForEach(InputSections,
+ [](InputSectionBase *Sec) { Sec->maybeDecompress(); });
+}
+
+template <class ELFT> void elf::splitSections() {
+ // splitIntoPieces needs to be called on each MergeInputSection
+ // before calling finalizeContents().
parallelForEach(InputSections, [](InputSectionBase *Sec) {
- if (Sec->Live)
- Sec->maybeUncompress();
+ if (auto *S = dyn_cast<MergeInputSection>(Sec))
+ S->splitIntoPieces();
+ else if (auto *Eh = dyn_cast<EhInputSection>(Sec))
+ Eh->split<ELFT>();
});
}
@@ -2492,14 +2921,6 @@ void elf::decompressSections() {
// that it replaces. It then finalizes each synthetic section in order
// to compute an output offset for each piece of each input section.
void elf::mergeSections() {
- // splitIntoPieces needs to be called on each MergeInputSection
- // before calling finalizeContents(). Do that first.
- parallelForEach(InputSections, [](InputSectionBase *Sec) {
- if (Sec->Live)
- if (auto *S = dyn_cast<MergeInputSection>(Sec))
- S->splitIntoPieces();
- });
-
std::vector<MergeSyntheticSection *> MergeSections;
for (InputSectionBase *&S : InputSections) {
MergeInputSection *MS = dyn_cast<MergeInputSection>(S);
@@ -2508,8 +2929,10 @@ void elf::mergeSections() {
// We do not want to handle sections that are not alive, so just remove
// them instead of trying to merge.
- if (!MS->Live)
+ if (!MS->Live) {
+ S = nullptr;
continue;
+ }
StringRef OutsecName = getOutputSectionName(MS);
uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
@@ -2561,8 +2984,7 @@ ARMExidxSentinelSection::ARMExidxSentinelSection()
// address described by any other table entry.
void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
assert(Highest);
- uint64_t S =
- Highest->getParent()->Addr + Highest->getOffset(Highest->getSize());
+ uint64_t S = Highest->getVA(Highest->getSize());
uint64_t P = getVA();
Target->relocateOne(Buf, R_ARM_PREL31, S - P);
write32le(Buf + 4, 1);
@@ -2570,15 +2992,16 @@ void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
// The sentinel has to be removed if there are no other .ARM.exidx entries.
bool ARMExidxSentinelSection::empty() const {
- OutputSection *OS = getParent();
- for (auto *B : OS->SectionCommands)
- if (auto *ISD = dyn_cast<InputSectionDescription>(B))
- for (auto *S : ISD->Sections)
- if (!isa<ARMExidxSentinelSection>(S))
- return false;
+ for (InputSection *IS : getInputSections(getParent()))
+ if (!isa<ARMExidxSentinelSection>(IS))
+ return false;
return true;
}
+bool ARMExidxSentinelSection::classof(const SectionBase *D) {
+ return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX;
+}
+
ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
Config->Wordsize, ".text.thunk") {
@@ -2587,16 +3010,13 @@ ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
}
void ThunkSection::addThunk(Thunk *T) {
- uint64_t Off = alignTo(Size, T->Alignment);
- T->Offset = Off;
Thunks.push_back(T);
T->addSymbols(*this);
- Size = Off + T->size();
}
void ThunkSection::writeTo(uint8_t *Buf) {
- for (const Thunk *T : Thunks)
- T->writeTo(Buf + T->Offset, *this);
+ for (Thunk *T : Thunks)
+ T->writeTo(Buf + T->Offset);
}
InputSection *ThunkSection::getTargetInputSection() const {
@@ -2606,6 +3026,20 @@ InputSection *ThunkSection::getTargetInputSection() const {
return T->getTargetInputSection();
}
+bool ThunkSection::assignOffsets() {
+ uint64_t Off = 0;
+ for (Thunk *T : Thunks) {
+ Off = alignTo(Off, T->Alignment);
+ T->setOffset(Off);
+ uint32_t Size = T->size();
+ T->getThunkTargetSym()->Size = Size;
+ Off += Size;
+ }
+ bool Changed = Off != Size;
+ Size = Off;
+ return Changed;
+}
+
InputSection *InX::ARMAttributes;
BssSection *InX::Bss;
BssSection *InX::BssRelRo;
@@ -2627,16 +3061,23 @@ MipsRldMapSection *InX::MipsRldMap;
PltSection *InX::Plt;
PltSection *InX::Iplt;
RelocationBaseSection *InX::RelaDyn;
+RelrBaseSection *InX::RelrDyn;
RelocationBaseSection *InX::RelaPlt;
RelocationBaseSection *InX::RelaIplt;
StringTableSection *InX::ShStrTab;
StringTableSection *InX::StrTab;
SymbolTableBaseSection *InX::SymTab;
+SymtabShndxSection *InX::SymTabShndx;
+
+template GdbIndexSection *GdbIndexSection::create<ELF32LE>();
+template GdbIndexSection *GdbIndexSection::create<ELF32BE>();
+template GdbIndexSection *GdbIndexSection::create<ELF64LE>();
+template GdbIndexSection *GdbIndexSection::create<ELF64BE>();
-template GdbIndexSection *elf::createGdbIndex<ELF32LE>();
-template GdbIndexSection *elf::createGdbIndex<ELF32BE>();
-template GdbIndexSection *elf::createGdbIndex<ELF64LE>();
-template GdbIndexSection *elf::createGdbIndex<ELF64BE>();
+template void elf::splitSections<ELF32LE>();
+template void elf::splitSections<ELF32BE>();
+template void elf::splitSections<ELF64LE>();
+template void elf::splitSections<ELF64BE>();
template void EhFrameSection::addSection<ELF32LE>(InputSectionBase *);
template void EhFrameSection::addSection<ELF32BE>(InputSectionBase *);
@@ -2648,6 +3089,11 @@ template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
template void PltSection::addEntry<ELF64BE>(Symbol &Sym);
+template void MipsGotSection::build<ELF32LE>();
+template void MipsGotSection::build<ELF32BE>();
+template void MipsGotSection::build<ELF64LE>();
+template void MipsGotSection::build<ELF64BE>();
+
template class elf::MipsAbiFlagsSection<ELF32LE>;
template class elf::MipsAbiFlagsSection<ELF32BE>;
template class elf::MipsAbiFlagsSection<ELF64LE>;
@@ -2678,6 +3124,11 @@ template class elf::AndroidPackedRelocationSection<ELF32BE>;
template class elf::AndroidPackedRelocationSection<ELF64LE>;
template class elf::AndroidPackedRelocationSection<ELF64BE>;
+template class elf::RelrSection<ELF32LE>;
+template class elf::RelrSection<ELF32BE>;
+template class elf::RelrSection<ELF64LE>;
+template class elf::RelrSection<ELF64BE>;
+
template class elf::SymbolTableSection<ELF32LE>;
template class elf::SymbolTableSection<ELF32BE>;
template class elf::SymbolTableSection<ELF64LE>;
diff --git a/contrib/llvm/tools/lld/ELF/SyntheticSections.h b/contrib/llvm/tools/lld/ELF/SyntheticSections.h
index a990590513bb..a780c6631374 100644
--- a/contrib/llvm/tools/lld/ELF/SyntheticSections.h
+++ b/contrib/llvm/tools/lld/ELF/SyntheticSections.h
@@ -26,10 +26,12 @@
#include "InputSection.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Endian.h"
#include <functional>
namespace lld {
namespace elf {
+class Defined;
class SharedSymbol;
class SyntheticSection : public InputSection {
@@ -51,7 +53,6 @@ public:
// If any additional finalization of contents are needed post thunk creation.
virtual void postThunkContents() {}
virtual bool empty() const { return false; }
- uint64_t getVA() const;
static bool classof(const SectionBase *D) {
return D->kind() == InputSectionBase::Synthetic;
@@ -78,13 +79,18 @@ public:
size_t NumFdes = 0;
struct FdeData {
- uint32_t Pc;
- uint32_t FdeVA;
+ uint32_t PcRel;
+ uint32_t FdeVARel;
};
std::vector<FdeData> getFdeData() const;
+ ArrayRef<CieRecord *> getCieRecords() const { return CieRecords; }
private:
+ // This is used only when parsing EhInputSection. We keep it here to avoid
+ // allocating one for each EhInputSection.
+ llvm::DenseMap<size_t, CieRecord *> OffsetToCie;
+
uint64_t Size = 0;
template <class ELFT, class RelTy>
@@ -173,12 +179,21 @@ public:
bool updateAllocSize() override;
void finalizeContents() override;
bool empty() const override;
- void addEntry(Symbol &Sym, int64_t Addend, RelExpr Expr);
- bool addDynTlsEntry(Symbol &Sym);
- bool addTlsIndex();
- uint64_t getPageEntryOffset(const Symbol &B, int64_t Addend) const;
- uint64_t getSymEntryOffset(const Symbol &B, int64_t Addend) const;
- uint64_t getGlobalDynOffset(const Symbol &B) const;
+
+ // Join separate GOTs built for each input file to generate
+ // primary and optional multiple secondary GOTs.
+ template <class ELFT> void build();
+
+ void addEntry(InputFile &File, Symbol &Sym, int64_t Addend, RelExpr Expr);
+ void addDynTlsEntry(InputFile &File, Symbol &Sym);
+ void addTlsIndex(InputFile &File);
+
+ uint64_t getPageEntryOffset(const InputFile *F, const Symbol &S,
+ int64_t Addend) const;
+ uint64_t getSymEntryOffset(const InputFile *F, const Symbol &S,
+ int64_t Addend) const;
+ uint64_t getGlobalDynOffset(const InputFile *F, const Symbol &S) const;
+ uint64_t getTlsIndexOffset(const InputFile *F) const;
// Returns the symbol which corresponds to the first entry of the global part
// of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
@@ -190,13 +205,8 @@ public:
// the number of reserved entries.
unsigned getLocalEntriesNum() const;
- // Returns offset of TLS part of the MIPS GOT table. This part goes
- // after 'local' and 'global' entries.
- uint64_t getTlsOffset() const;
-
- uint32_t getTlsIndexOff() const { return TlsIndexOff; }
-
- uint64_t getGp() const;
+ // Return _gp value for primary GOT (nullptr) or particular input file.
+ uint64_t getGp(const InputFile *F = nullptr) const;
private:
// MIPS GOT consists of three parts: local, global and tls. Each part
@@ -235,32 +245,110 @@ private:
// addressing, but MIPS ABI requires that these entries be present in GOT.
// TLS entries:
// Entries created by TLS relocations.
+ //
+ // If the sum of local, global and tls entries is less than 64K only single
+ // got is enough. Otherwise, multi-got is created. Series of primary and
+ // multiple secondary GOTs have the following layout:
+ // - Primary GOT
+ // Header
+ // Local entries
+ // Global entries
+ // Relocation only entries
+ // TLS entries
+ //
+ // - Secondary GOT
+ // Local entries
+ // Global entries
+ // TLS entries
+ // ...
+ //
+ // All GOT entries required by relocations from a single input file entirely
+ // belong to either primary or one of secondary GOTs. To reference GOT entries
+ // each GOT has its own _gp value points to the "middle" of the GOT.
+ // In the code this value loaded to the register which is used for GOT access.
+ //
+ // MIPS 32 function's prologue:
+ // lui v0,0x0
+ // 0: R_MIPS_HI16 _gp_disp
+ // addiu v0,v0,0
+ // 4: R_MIPS_LO16 _gp_disp
+ //
+ // MIPS 64:
+ // lui at,0x0
+ // 14: R_MIPS_GPREL16 main
+ //
+ // Dynamic linker does not know anything about secondary GOTs and cannot
+ // use a regular MIPS mechanism for GOT entries initialization. So we have
+ // to use an approach accepted by other architectures and create dynamic
+ // relocations R_MIPS_REL32 to initialize global entries (and local in case
+ // of PIC code) in secondary GOTs. But ironically MIPS dynamic linker
+ // requires GOT entries and correspondingly ordered dynamic symbol table
+ // entries to deal with dynamic relocations. To handle this problem
+ // relocation-only section in the primary GOT contains entries for all
+ // symbols referenced in global parts of secondary GOTs. Although the sum
+ // of local and normal global entries of the primary got should be less
+ // than 64K, the size of the primary got (including relocation-only entries
+ // can be greater than 64K, because parts of the primary got that overflow
+ // the 64K limit are used only by the dynamic linker at dynamic link-time
+ // and not by 16-bit gp-relative addressing at run-time.
+ //
+ // For complete multi-GOT description see the following link
+ // https://dmz-portal.mips.com/wiki/MIPS_Multi_GOT
// Number of "Header" entries.
static const unsigned HeaderEntriesNum = 2;
- // Number of allocated "Page" entries.
- uint32_t PageEntriesNum = 0;
- // Map output sections referenced by MIPS GOT relocations
- // to the first index of "Page" entries allocated for this section.
- llvm::SmallMapVector<const OutputSection *, size_t, 16> PageIndexMap;
-
- typedef std::pair<const Symbol *, uint64_t> GotEntry;
- typedef std::vector<GotEntry> GotEntries;
- // Map from Symbol-Addend pair to the GOT index.
- llvm::DenseMap<GotEntry, size_t> EntryIndexMap;
- // Local entries (16-bit access).
- GotEntries LocalEntries;
- // Local entries (32-bit access).
- GotEntries LocalEntries32;
-
- // Normal and reloc-only global entries.
- GotEntries GlobalEntries;
-
- // TLS entries.
- std::vector<const Symbol *> TlsEntries;
- uint32_t TlsIndexOff = -1;
uint64_t Size = 0;
+
+ size_t LocalEntriesNum = 0;
+
+ // Symbol and addend.
+ typedef std::pair<Symbol *, int64_t> GotEntry;
+
+ struct FileGot {
+ InputFile *File = nullptr;
+ size_t StartIndex = 0;
+
+ struct PageBlock {
+ size_t FirstIndex = 0;
+ size_t Count = 0;
+ };
+
+ // Map output sections referenced by MIPS GOT relocations
+ // to the description (index/count) "page" entries allocated
+ // for this section.
+ llvm::SmallMapVector<const OutputSection *, PageBlock, 16> PagesMap;
+ // Maps from Symbol+Addend pair or just Symbol to the GOT entry index.
+ llvm::MapVector<GotEntry, size_t> Local16;
+ llvm::MapVector<GotEntry, size_t> Local32;
+ llvm::MapVector<Symbol *, size_t> Global;
+ llvm::MapVector<Symbol *, size_t> Relocs;
+ llvm::MapVector<Symbol *, size_t> Tls;
+ // Set of symbols referenced by dynamic TLS relocations.
+ llvm::MapVector<Symbol *, size_t> DynTlsSymbols;
+
+ // Total number of all entries.
+ size_t getEntriesNum() const;
+ // Number of "page" entries.
+ size_t getPageEntriesNum() const;
+ // Number of entries require 16-bit index to access.
+ size_t getIndexedEntriesNum() const;
+
+ bool isOverflow() const;
+ };
+
+ // Container of GOT created for each input file.
+ // After building a final series of GOTs this container
+ // holds primary and secondary GOT's.
+ std::vector<FileGot> Gots;
+
+ // Return (and create if necessary) `FileGot`.
+ FileGot &getGot(InputFile &F);
+
+ // Try to merge two GOTs. In case of success the `Dst` contains
+ // result of merging and the function returns true. In case of
+ // ovwerflow the `Dst` is unchanged and the function returns false.
+ bool tryMergeGots(FileGot & Dst, FileGot & Src, bool IsPrimary);
};
class GotPltSection final : public SyntheticSection {
@@ -269,7 +357,7 @@ public:
void addEntry(Symbol &Sym);
size_t getSize() const override;
void writeTo(uint8_t *Buf) override;
- bool empty() const override { return Entries.empty(); }
+ bool empty() const override;
private:
std::vector<const Symbol *> Entries;
@@ -310,30 +398,48 @@ private:
class DynamicReloc {
public:
- DynamicReloc(uint32_t Type, const InputSectionBase *InputSec,
+ DynamicReloc(RelType Type, const InputSectionBase *InputSec,
uint64_t OffsetInSec, bool UseSymVA, Symbol *Sym, int64_t Addend)
: Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec),
- UseSymVA(UseSymVA), Addend(Addend) {}
+ UseSymVA(UseSymVA), Addend(Addend), OutputSec(nullptr) {}
+ // This constructor records dynamic relocation settings used by MIPS
+ // multi-GOT implementation. It's to relocate addresses of 64kb pages
+ // lie inside the output section.
+ DynamicReloc(RelType Type, const InputSectionBase *InputSec,
+ uint64_t OffsetInSec, const OutputSection *OutputSec,
+ int64_t Addend)
+ : Type(Type), Sym(nullptr), InputSec(InputSec), OffsetInSec(OffsetInSec),
+ UseSymVA(false), Addend(Addend), OutputSec(OutputSec) {}
uint64_t getOffset() const;
- int64_t getAddend() const;
uint32_t getSymIndex() const;
const InputSectionBase *getInputSec() const { return InputSec; }
- uint32_t Type;
+ // Computes the addend of the dynamic relocation. Note that this is not the
+ // same as the Addend member variable as it also includes the symbol address
+ // if UseSymVA is true.
+ int64_t computeAddend() const;
+
+ RelType Type;
private:
Symbol *Sym;
const InputSectionBase *InputSec = nullptr;
uint64_t OffsetInSec;
+ // If this member is true, the dynamic relocation will not be against the
+ // symbol but will instead be a relative relocation that simply adds the
+ // load address. This means we need to write the symbol virtual address
+ // plus the original addend as the final relocation addend.
bool UseSymVA;
int64_t Addend;
+ const OutputSection *OutputSec;
};
template <class ELFT> class DynamicSection final : public SyntheticSection {
typedef typename ELFT::Dyn Elf_Dyn;
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::Relr Elf_Relr;
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::Sym Elf_Sym;
@@ -350,6 +456,7 @@ private:
void add(int32_t Tag, std::function<uint64_t()> Fn);
void addInt(int32_t Tag, uint64_t Val);
void addInSec(int32_t Tag, InputSection *Sec);
+ void addInSecRelative(int32_t Tag, InputSection *Sec);
void addOutSec(int32_t Tag, OutputSection *Sec);
void addSize(int32_t Tag, OutputSection *Sec);
void addSym(int32_t Tag, Symbol *Sym);
@@ -361,6 +468,13 @@ class RelocationBaseSection : public SyntheticSection {
public:
RelocationBaseSection(StringRef Name, uint32_t Type, int32_t DynamicTag,
int32_t SizeDynamicTag);
+ void addReloc(RelType DynType, InputSectionBase *IS, uint64_t OffsetInSec,
+ Symbol *Sym);
+ // Add a dynamic relocation that might need an addend. This takes care of
+ // writing the addend to the output section if needed.
+ void addReloc(RelType DynType, InputSectionBase *InputSec,
+ uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr,
+ RelType Type);
void addReloc(const DynamicReloc &Reloc);
bool empty() const override { return Relocs.empty(); }
size_t getSize() const override { return Relocs.size() * this->Entsize; }
@@ -405,6 +519,39 @@ private:
SmallVector<char, 0> RelocData;
};
+struct RelativeReloc {
+ uint64_t getOffset() const { return InputSec->getVA(OffsetInSec); }
+
+ const InputSectionBase *InputSec;
+ uint64_t OffsetInSec;
+};
+
+class RelrBaseSection : public SyntheticSection {
+public:
+ RelrBaseSection();
+ std::vector<RelativeReloc> Relocs;
+};
+
+// RelrSection is used to encode offsets for relative relocations.
+// Proposal for adding SHT_RELR sections to generic-abi is here:
+// https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+// For more details, see the comment in RelrSection::updateAllocSize().
+template <class ELFT> class RelrSection final : public RelrBaseSection {
+ typedef typename ELFT::Relr Elf_Relr;
+
+public:
+ RelrSection();
+
+ bool updateAllocSize() override;
+ size_t getSize() const override { return RelrRelocs.size() * this->Entsize; }
+ void writeTo(uint8_t *Buf) override {
+ memcpy(Buf, RelrRelocs.data(), getSize());
+ }
+
+private:
+ std::vector<Elf_Relr> RelrRelocs;
+};
+
struct SymbolTableEntry {
Symbol *Sym;
size_t StrTabOffset;
@@ -441,6 +588,16 @@ public:
void writeTo(uint8_t *Buf) override;
};
+class SymtabShndxSection final : public SyntheticSection {
+public:
+ SymtabShndxSection();
+
+ void writeTo(uint8_t *Buf) override;
+ size_t getSize() const override;
+ bool empty() const override;
+ void finalizeContents() override;
+};
+
// Outputs GNU Hash section. For detailed explanation see:
// https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
class GnuHashTableSection final : public SyntheticSection {
@@ -455,7 +612,7 @@ public:
void addSymbols(std::vector<SymbolTableEntry> &Symbols);
private:
- size_t getShift2() const { return Config->Is64 ? 6 : 5; }
+ enum { Shift2 = 6 };
void writeBloomFilter(uint8_t *Buf);
void writeHashTable(uint8_t *Buf);
@@ -484,13 +641,13 @@ private:
size_t Size = 0;
};
-// The PltSection is used for both the Plt and Iplt. The former always has a
+// The PltSection is used for both the Plt and Iplt. The former usually has a
// header as its first entry that is used at run-time to resolve lazy binding.
// The latter is used for GNU Ifunc symbols, that will be subject to a
// Target->IRelativeRel.
class PltSection : public SyntheticSection {
public:
- PltSection(size_t HeaderSize);
+ PltSection(bool IsIplt);
void writeTo(uint8_t *Buf) override;
size_t getSize() const override;
bool empty() const override { return Entries.empty(); }
@@ -501,13 +658,12 @@ public:
private:
unsigned getPltRelocOff() const;
std::vector<std::pair<const Symbol *, unsigned>> Entries;
- // Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero
size_t HeaderSize;
+ bool IsIplt;
};
-// GdbIndexChunk is created for each .debug_info section and contains
-// information to create a part of .gdb_index for a given input section.
-struct GdbIndexChunk {
+class GdbIndexSection final : public SyntheticSection {
+public:
struct AddressEntry {
InputSection *Section;
uint64_t LowAddress;
@@ -522,59 +678,51 @@ struct GdbIndexChunk {
struct NameTypeEntry {
llvm::CachedHashStringRef Name;
- uint8_t Type;
+ uint32_t Type;
};
- InputSection *DebugInfoSec;
- std::vector<AddressEntry> AddressAreas;
- std::vector<CuEntry> CompilationUnits;
- std::vector<NameTypeEntry> NamesAndTypes;
-};
+ struct GdbChunk {
+ InputSection *Sec;
+ std::vector<AddressEntry> AddressAreas;
+ std::vector<CuEntry> CompilationUnits;
+ };
-// The symbol type for the .gdb_index section.
-struct GdbSymbol {
- uint32_t NameHash;
- size_t NameOffset;
- size_t CuVectorIndex;
-};
+ struct GdbSymbol {
+ llvm::CachedHashStringRef Name;
+ std::vector<uint32_t> CuVector;
+ uint32_t NameOff;
+ uint32_t CuVectorOff;
+ };
-class GdbIndexSection final : public SyntheticSection {
-public:
- GdbIndexSection(std::vector<GdbIndexChunk> &&Chunks);
+ GdbIndexSection();
+ template <typename ELFT> static GdbIndexSection *create();
void writeTo(uint8_t *Buf) override;
- size_t getSize() const override;
+ size_t getSize() const override { return Size; }
bool empty() const override;
private:
- void fixCuIndex();
- std::vector<std::vector<uint32_t>> createCuVectors();
- std::vector<GdbSymbol *> createGdbSymtab();
-
- // A symbol table for this .gdb_index section.
- std::vector<GdbSymbol *> GdbSymtab;
-
- // CU vector is a part of constant pool area of section.
- std::vector<std::vector<uint32_t>> CuVectors;
+ struct GdbIndexHeader {
+ llvm::support::ulittle32_t Version;
+ llvm::support::ulittle32_t CuListOff;
+ llvm::support::ulittle32_t CuTypesOff;
+ llvm::support::ulittle32_t AddressAreaOff;
+ llvm::support::ulittle32_t SymtabOff;
+ llvm::support::ulittle32_t ConstantPoolOff;
+ };
- // Symbol table contents.
- llvm::DenseMap<llvm::CachedHashStringRef, GdbSymbol *> Symbols;
+ void initOutputSize();
+ size_t computeSymtabSize() const;
- // Each chunk contains information gathered from a debug sections of single
- // object and used to build different areas of gdb index.
- std::vector<GdbIndexChunk> Chunks;
+ // Each chunk contains information gathered from debug sections of a
+ // single object file.
+ std::vector<GdbChunk> Chunks;
- static constexpr uint32_t CuListOffset = 24;
- uint32_t CuTypesOffset;
- uint32_t SymtabOffset;
- uint32_t ConstantPoolOffset;
- uint32_t StringPoolOffset;
- uint32_t StringPoolSize;
+ // A symbol table for this .gdb_index section.
+ std::vector<GdbSymbol> Symbols;
- std::vector<size_t> CuVectorOffsets;
+ size_t Size;
};
-template <class ELFT> GdbIndexSection *createGdbIndex();
-
// --eh-frame-hdr option tells linker to construct a header for all the
// .eh_frame sections. This header is placed to a section named .eh_frame_hdr
// and also to a PT_GNU_EH_FRAME segment.
@@ -653,7 +801,7 @@ template <class ELFT> class VersionNeedSection final : public SyntheticSection {
public:
VersionNeedSection();
- void addSymbol(SharedSymbol *SS);
+ void addSymbol(Symbol *Sym);
void finalizeContents() override;
void writeTo(uint8_t *Buf) override;
size_t getSize() const override;
@@ -668,13 +816,12 @@ public:
class MergeSyntheticSection : public SyntheticSection {
public:
void addSection(MergeInputSection *MS);
+ std::vector<MergeInputSection *> Sections;
protected:
MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags,
uint32_t Alignment)
: SyntheticSection(Flags, Type, Alignment, Name) {}
-
- std::vector<MergeInputSection *> Sections;
};
class MergeTailSection final : public MergeSyntheticSection {
@@ -787,7 +934,12 @@ public:
void writeTo(uint8_t *Buf) override;
bool empty() const override;
- InputSection *Highest = 0;
+ static bool classof(const SectionBase *D);
+
+ // The last section referenced by a regular .ARM.exidx section.
+ // It is found and filled in Writer<ELFT>::resolveShfLinkOrder().
+ // The sentinel points at the end of that section.
+ InputSection *Highest = nullptr;
};
// A container for one or more linker generated thunks. Instances of these
@@ -805,19 +957,21 @@ public:
size_t getSize() const override { return Size; }
void writeTo(uint8_t *Buf) override;
InputSection *getTargetInputSection() const;
+ bool assignOffsets();
private:
- std::vector<const Thunk *> Thunks;
+ std::vector<Thunk *> Thunks;
size_t Size = 0;
};
InputSection *createInterpSection();
MergeInputSection *createCommentSection();
void decompressSections();
+template <class ELFT> void splitSections();
void mergeSections();
-Symbol *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
- uint64_t Size, InputSectionBase &Section);
+Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
+ uint64_t Size, InputSectionBase &Section);
// Linker generated sections which can be used as inputs.
struct InX {
@@ -842,11 +996,13 @@ struct InX {
static PltSection *Plt;
static PltSection *Iplt;
static RelocationBaseSection *RelaDyn;
+ static RelrBaseSection *RelrDyn;
static RelocationBaseSection *RelaPlt;
static RelocationBaseSection *RelaIplt;
static StringTableSection *ShStrTab;
static StringTableSection *StrTab;
static SymbolTableBaseSection *SymTab;
+ static SymtabShndxSection* SymTabShndx;
};
template <class ELFT> struct In {
diff --git a/contrib/llvm/tools/lld/ELF/Target.cpp b/contrib/llvm/tools/lld/ELF/Target.cpp
index b528fd583c1a..815f3a045551 100644
--- a/contrib/llvm/tools/lld/ELF/Target.cpp
+++ b/contrib/llvm/tools/lld/ELF/Target.cpp
@@ -60,6 +60,8 @@ TargetInfo *elf::getTarget() {
return getARMTargetInfo();
case EM_AVR:
return getAVRTargetInfo();
+ case EM_HEXAGON:
+ return getHexagonTargetInfo();
case EM_MIPS:
switch (Config->EKind) {
case ELF32LEKind:
@@ -87,29 +89,29 @@ TargetInfo *elf::getTarget() {
fatal("unknown target machine");
}
-template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) {
+template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *Loc) {
for (InputSectionBase *D : InputSections) {
- auto *IS = dyn_cast<InputSection>(D);
- if (!IS || !IS->getParent())
+ auto *IS = cast<InputSection>(D);
+ if (!IS->getParent())
continue;
uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff;
if (ISLoc <= Loc && Loc < ISLoc + IS->getSize())
- return IS->template getLocation<ELFT>(Loc - ISLoc) + ": ";
+ return {IS, IS->template getLocation<ELFT>(Loc - ISLoc) + ": "};
}
- return "";
+ return {};
}
-std::string elf::getErrorLocation(const uint8_t *Loc) {
+ErrorPlace elf::getErrorPlace(const uint8_t *Loc) {
switch (Config->EKind) {
case ELF32LEKind:
- return getErrorLoc<ELF32LE>(Loc);
+ return getErrPlace<ELF32LE>(Loc);
case ELF32BEKind:
- return getErrorLoc<ELF32BE>(Loc);
+ return getErrPlace<ELF32BE>(Loc);
case ELF64LEKind:
- return getErrorLoc<ELF64LE>(Loc);
+ return getErrPlace<ELF64LE>(Loc);
case ELF64BEKind:
- return getErrorLoc<ELF64BE>(Loc);
+ return getErrPlace<ELF64BE>(Loc);
default:
llvm_unreachable("unknown ELF type");
}
@@ -128,6 +130,12 @@ bool TargetInfo::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
return false;
}
+bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const {
+ llvm_unreachable("Target doesn't support split stacks.");
+}
+
+
bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {
return true;
}
diff --git a/contrib/llvm/tools/lld/ELF/Target.h b/contrib/llvm/tools/lld/ELF/Target.h
index 1f58adba1817..82c7b8f7b6c5 100644
--- a/contrib/llvm/tools/lld/ELF/Target.h
+++ b/contrib/llvm/tools/lld/ELF/Target.h
@@ -25,9 +25,9 @@ class Symbol;
class TargetInfo {
public:
virtual uint32_t calcEFlags() const { return 0; }
- virtual bool isPicRel(RelType Type) const { return true; }
virtual RelType getDynRel(RelType Type) const { return Type; }
virtual void writeGotPltHeader(uint8_t *Buf) const {}
+ virtual void writeGotHeader(uint8_t *Buf) const {}
virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {};
virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const;
virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const;
@@ -43,8 +43,12 @@ public:
virtual void addPltHeaderSymbols(InputSection &IS) const {}
virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {}
+ unsigned getPltEntryOffset(unsigned Index) const {
+ return Index * PltEntrySize + PltHeaderSize;
+ }
+
// Returns true if a relocation only uses the low bits of a value such that
- // all those bits are in in the same page. For example, if the relocation
+ // all those bits are in the same page. For example, if the relocation
// only uses the low 12 bits in a system with 4k pages. If this is true, the
// bits will always have the same value at runtime and we don't have to emit
// a dynamic relocation.
@@ -55,6 +59,13 @@ public:
virtual bool needsThunk(RelExpr Expr, RelType RelocType,
const InputFile *File, uint64_t BranchAddr,
const Symbol &S) const;
+
+ // The function with a prologue starting at Loc was compiled with
+ // -fsplit-stack and it calls a function compiled without. Adjust the prologue
+ // to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks.
+ virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const;
+
// Return true if we can reach Dst from Src with Relocation RelocType
virtual bool inBranchRange(RelType Type, uint64_t Src,
uint64_t Dst) const;
@@ -71,9 +82,10 @@ public:
uint64_t getImageBase();
- // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for
- // end of .got
+ // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got or .got.plt section.
uint64_t GotBaseSymOff = 0;
+ // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.
+ bool GotBaseSymInGotPlt = true;
// On systems with range extensions we place collections of Thunks at
// regular spacings that enable the majority of branches reach the Thunks.
@@ -97,9 +109,18 @@ public:
// to support lazy loading.
unsigned GotPltHeaderEntriesNum = 3;
- // Set to 0 for variant 2
+ // On PPC ELF V2 abi, the first entry in the .got is the .TOC.
+ unsigned GotHeaderEntriesNum = 0;
+
+ // For TLS variant 1, the TCB is a fixed size specified by the Target.
+ // For variant 2, the TCB is an unspecified size.
+ // Set to 0 for variant 2.
unsigned TcbSize = 0;
+ // Set to the offset (in bytes) that the thread pointer is initialized to
+ // point to, relative to the start of the thread local storage.
+ unsigned TlsTpOffset = 0;
+
bool NeedsThunks = false;
// A 4-byte field corresponding to one or more trap instructions, used to pad
@@ -126,6 +147,7 @@ TargetInfo *getAArch64TargetInfo();
TargetInfo *getAMDGPUTargetInfo();
TargetInfo *getARMTargetInfo();
TargetInfo *getAVRTargetInfo();
+TargetInfo *getHexagonTargetInfo();
TargetInfo *getPPC64TargetInfo();
TargetInfo *getPPCTargetInfo();
TargetInfo *getSPARCV9TargetInfo();
@@ -134,7 +156,17 @@ TargetInfo *getX86TargetInfo();
TargetInfo *getX86_64TargetInfo();
template <class ELFT> TargetInfo *getMipsTargetInfo();
-std::string getErrorLocation(const uint8_t *Loc);
+struct ErrorPlace {
+ InputSectionBase *IS;
+ std::string Loc;
+};
+
+// Returns input section and corresponding source string for the given location.
+ErrorPlace getErrorPlace(const uint8_t *Loc);
+
+static inline std::string getErrorLocation(const uint8_t *Loc) {
+ return getErrorPlace(Loc).Loc;
+}
uint64_t getPPC64TocBase();
uint64_t getAArch64Page(uint64_t Expr);
@@ -146,39 +178,74 @@ template <class ELFT> bool isMipsPIC(const Defined *Sym);
static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V,
int64_t Min, uint64_t Max) {
- error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) +
- " out of range: " + V + " is not in [" + Twine(Min) + ", " +
- Twine(Max) + "]");
+ ErrorPlace ErrPlace = getErrorPlace(Loc);
+ StringRef Hint;
+ if (ErrPlace.IS && ErrPlace.IS->Name.startswith(".debug"))
+ Hint = "; consider recompiling with -fdebug-types-section to reduce size "
+ "of debug sections";
+
+ error(ErrPlace.Loc + "relocation " + lld::toString(Type) +
+ " out of range: " + V.str() + " is not in [" + Twine(Min).str() + ", " +
+ Twine(Max).str() + "]" + Hint);
}
-template <unsigned N>
-static void checkInt(uint8_t *Loc, int64_t V, RelType Type) {
- if (!llvm::isInt<N>(V))
+// Sign-extend Nth bit all the way to MSB.
+inline int64_t signExtend(uint64_t V, int N) {
+ return int64_t(V << (64 - N)) >> (64 - N);
+}
+
+// Make sure that V can be represented as an N bit signed integer.
+inline void checkInt(uint8_t *Loc, int64_t V, int N, RelType Type) {
+ if (V != signExtend(V, N))
reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N));
}
-template <unsigned N>
-static void checkUInt(uint8_t *Loc, uint64_t V, RelType Type) {
- if (!llvm::isUInt<N>(V))
+// Make sure that V can be represented as an N bit unsigned integer.
+inline void checkUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {
+ if ((V >> N) != 0)
reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N));
}
-template <unsigned N>
-static void checkIntUInt(uint8_t *Loc, uint64_t V, RelType Type) {
- if (!llvm::isInt<N>(V) && !llvm::isUInt<N>(V))
- // For the error message we should cast V to a signed integer so that error
- // messages show a small negative value rather than an extremely large one
+// Make sure that V can be represented as an N bit signed or unsigned integer.
+inline void checkIntUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {
+ // For the error message we should cast V to a signed integer so that error
+ // messages show a small negative value rather than an extremely large one
+ if (V != (uint64_t)signExtend(V, N) && (V >> N) != 0)
reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N),
- llvm::maxUIntN(N));
+ llvm::maxIntN(N));
}
-template <unsigned N>
-static void checkAlignment(uint8_t *Loc, uint64_t V, RelType Type) {
+inline void checkAlignment(uint8_t *Loc, uint64_t V, int N, RelType Type) {
if ((V & (N - 1)) != 0)
error(getErrorLocation(Loc) + "improper alignment for relocation " +
lld::toString(Type) + ": 0x" + llvm::utohexstr(V) +
" is not aligned to " + Twine(N) + " bytes");
}
+
+// Endianness-aware read/write.
+inline uint16_t read16(const void *P) {
+ return llvm::support::endian::read16(P, Config->Endianness);
+}
+
+inline uint32_t read32(const void *P) {
+ return llvm::support::endian::read32(P, Config->Endianness);
+}
+
+inline uint64_t read64(const void *P) {
+ return llvm::support::endian::read64(P, Config->Endianness);
+}
+
+inline void write16(void *P, uint16_t V) {
+ llvm::support::endian::write16(P, V, Config->Endianness);
+}
+
+inline void write32(void *P, uint32_t V) {
+ llvm::support::endian::write32(P, V, Config->Endianness);
+}
+
+inline void write64(void *P, uint64_t V) {
+ llvm::support::endian::write64(P, V, Config->Endianness);
+}
} // namespace elf
} // namespace lld
diff --git a/contrib/llvm/tools/lld/ELF/Thunks.cpp b/contrib/llvm/tools/lld/ELF/Thunks.cpp
index b0bbf6da705a..2cd7e51ae357 100644
--- a/contrib/llvm/tools/lld/ELF/Thunks.cpp
+++ b/contrib/llvm/tools/lld/ELF/Thunks.cpp
@@ -40,7 +40,6 @@
using namespace llvm;
using namespace llvm::object;
-using namespace llvm::support::endian;
using namespace llvm::ELF;
namespace lld {
@@ -52,59 +51,112 @@ namespace {
class AArch64ABSLongThunk final : public Thunk {
public:
AArch64ABSLongThunk(Symbol &Dest) : Thunk(Dest) {}
- uint32_t size() const override { return 16; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t size() override { return 16; }
+ void writeTo(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
};
class AArch64ADRPThunk final : public Thunk {
public:
AArch64ADRPThunk(Symbol &Dest) : Thunk(Dest) {}
- uint32_t size() const override { return 12; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t size() override { return 12; }
+ void writeTo(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
};
+// Base class for ARM thunks.
+//
+// An ARM thunk may be either short or long. A short thunk is simply a branch
+// (B) instruction, and it may be used to call ARM functions when the distance
+// from the thunk to the target is less than 32MB. Long thunks can branch to any
+// virtual address and can switch between ARM and Thumb, and they are
+// implemented in the derived classes. This class tries to create a short thunk
+// if the target is in range, otherwise it creates a long thunk.
+class ARMThunk : public Thunk {
+public:
+ ARMThunk(Symbol &Dest) : Thunk(Dest) {}
+
+ bool mayUseShortThunk();
+ uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
+ void writeTo(uint8_t *Buf) override;
+ bool isCompatibleWith(RelType Type) const override;
+
+ // Returns the size of a long thunk.
+ virtual uint32_t sizeLong() = 0;
+
+ // Writes a long thunk to Buf.
+ virtual void writeLong(uint8_t *Buf) = 0;
+
+private:
+ // This field tracks whether all previously considered layouts would allow
+ // this thunk to be short. If we have ever needed a long thunk, we always
+ // create a long thunk, even if the thunk may be short given the current
+ // distance to the target. We do this because transitioning from long to short
+ // can create layout oscillations in certain corner cases which would prevent
+ // the layout from converging.
+ bool MayUseShortThunk = true;
+};
+
+// Base class for Thumb-2 thunks.
+//
+// This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
+// which has a range of 16MB.
+class ThumbThunk : public Thunk {
+public:
+ ThumbThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+
+ bool mayUseShortThunk();
+ uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
+ void writeTo(uint8_t *Buf) override;
+ bool isCompatibleWith(RelType Type) const override;
+
+ // Returns the size of a long thunk.
+ virtual uint32_t sizeLong() = 0;
+
+ // Writes a long thunk to Buf.
+ virtual void writeLong(uint8_t *Buf) = 0;
+
+private:
+ // See comment in ARMThunk above.
+ bool MayUseShortThunk = true;
+};
+
// Specific ARM Thunk implementations. The naming convention is:
// Source State, TargetState, Target Requirement, ABS or PI, Range
-class ARMV7ABSLongThunk final : public Thunk {
+class ARMV7ABSLongThunk final : public ARMThunk {
public:
- ARMV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) {}
+ ARMV7ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {}
- uint32_t size() const override { return 12; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t sizeLong() override { return 12; }
+ void writeLong(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
- bool isCompatibleWith(RelType Type) const override;
};
-class ARMV7PILongThunk final : public Thunk {
+class ARMV7PILongThunk final : public ARMThunk {
public:
- ARMV7PILongThunk(Symbol &Dest) : Thunk(Dest) {}
+ ARMV7PILongThunk(Symbol &Dest) : ARMThunk(Dest) {}
- uint32_t size() const override { return 16; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t sizeLong() override { return 16; }
+ void writeLong(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
- bool isCompatibleWith(RelType Type) const override;
};
-class ThumbV7ABSLongThunk final : public Thunk {
+class ThumbV7ABSLongThunk final : public ThumbThunk {
public:
- ThumbV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+ ThumbV7ABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {}
- uint32_t size() const override { return 10; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t sizeLong() override { return 10; }
+ void writeLong(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
- bool isCompatibleWith(RelType Type) const override;
};
-class ThumbV7PILongThunk final : public Thunk {
+class ThumbV7PILongThunk final : public ThumbThunk {
public:
- ThumbV7PILongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+ ThumbV7PILongThunk(Symbol &Dest) : ThumbThunk(Dest) {}
- uint32_t size() const override { return 12; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t sizeLong() override { return 12; }
+ void writeLong(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
- bool isCompatibleWith(RelType Type) const override;
};
// MIPS LA25 thunk
@@ -112,8 +164,8 @@ class MipsThunk final : public Thunk {
public:
MipsThunk(Symbol &Dest) : Thunk(Dest) {}
- uint32_t size() const override { return 16; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t size() override { return 16; }
+ void writeTo(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
InputSection *getTargetInputSection() const override;
};
@@ -123,8 +175,8 @@ class MicroMipsThunk final : public Thunk {
public:
MicroMipsThunk(Symbol &Dest) : Thunk(Dest) {}
- uint32_t size() const override { return 14; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t size() override { return 14; }
+ void writeTo(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
InputSection *getTargetInputSection() const override;
};
@@ -134,14 +186,44 @@ class MicroMipsR6Thunk final : public Thunk {
public:
MicroMipsR6Thunk(Symbol &Dest) : Thunk(Dest) {}
- uint32_t size() const override { return 12; }
- void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+ uint32_t size() override { return 12; }
+ void writeTo(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
InputSection *getTargetInputSection() const override;
};
+
+// PPC64 Plt call stubs.
+// Any call site that needs to call through a plt entry needs a call stub in
+// the .text section. The call stub is responsible for:
+// 1) Saving the toc-pointer to the stack.
+// 2) Loading the target functions address from the procedure linkage table into
+// r12 for use by the target functions global entry point, and into the count
+// register.
+// 3) Transfering control to the target function through an indirect branch.
+class PPC64PltCallStub final : public Thunk {
+public:
+ PPC64PltCallStub(Symbol &Dest) : Thunk(Dest) {}
+ uint32_t size() override { return 20; }
+ void writeTo(uint8_t *Buf) override;
+ void addSymbols(ThunkSection &IS) override;
+};
+
} // end anonymous namespace
+Defined *Thunk::addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
+ InputSectionBase &Section) {
+ Defined *D = addSyntheticLocal(Name, Type, Value, /*Size=*/0, Section);
+ Syms.push_back(D);
+ return D;
+}
+
+void Thunk::setOffset(uint64_t NewOffset) {
+ for (Defined *D : Syms)
+ D->Value = D->Value - Offset + NewOffset;
+ Offset = NewOffset;
+}
+
// AArch64 long range Thunks
static uint64_t getAArch64ThunkDestVA(const Symbol &S) {
@@ -149,7 +231,7 @@ static uint64_t getAArch64ThunkDestVA(const Symbol &S) {
return V;
}
-void AArch64ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void AArch64ABSLongThunk::writeTo(uint8_t *Buf) {
const uint8_t Data[] = {
0x50, 0x00, 0x00, 0x58, // ldr x16, L0
0x00, 0x02, 0x1f, 0xd6, // br x16
@@ -162,11 +244,10 @@ void AArch64ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
}
void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {
- ThunkSym = addSyntheticLocal(
- Saver.save("__AArch64AbsLongThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), IS);
- addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
- addSyntheticLocal("$d", STT_NOTYPE, Offset + 8, 0, IS);
+ addSymbol(Saver.save("__AArch64AbsLongThunk_" + Destination.getName()),
+ STT_FUNC, 0, IS);
+ addSymbol("$x", STT_NOTYPE, 0, IS);
+ addSymbol("$d", STT_NOTYPE, 8, IS);
}
// This Thunk has a maximum range of 4Gb, this is sufficient for all programs
@@ -174,26 +255,24 @@ void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {
// clang and gcc do not support the large code model for position independent
// code so it is safe to use this for position independent thunks without
// worrying about the destination being more than 4Gb away.
-void AArch64ADRPThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void AArch64ADRPThunk::writeTo(uint8_t *Buf) {
const uint8_t Data[] = {
0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
0x00, 0x02, 0x1f, 0xd6, // br x16
};
uint64_t S = getAArch64ThunkDestVA(Destination);
- uint64_t P = ThunkSym->getVA();
+ uint64_t P = getThunkTargetSym()->getVA();
memcpy(Buf, Data, sizeof(Data));
Target->relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,
getAArch64Page(S) - getAArch64Page(P));
Target->relocateOne(Buf + 4, R_AARCH64_ADD_ABS_LO12_NC, S);
}
-void AArch64ADRPThunk::addSymbols(ThunkSection &IS)
-{
- ThunkSym = addSyntheticLocal(
- Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), IS);
- addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
+void AArch64ADRPThunk::addSymbols(ThunkSection &IS) {
+ addSymbol(Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
+ 0, IS);
+ addSymbol("$x", STT_NOTYPE, 0, IS);
}
// ARM Target Thunks
@@ -202,7 +281,81 @@ static uint64_t getARMThunkDestVA(const Symbol &S) {
return SignExtend64<32>(V);
}
-void ARMV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+// This function returns true if the target is not Thumb and is within 2^26, and
+// it has not previously returned false (see comment for MayUseShortThunk).
+bool ARMThunk::mayUseShortThunk() {
+ if (!MayUseShortThunk)
+ return false;
+ uint64_t S = getARMThunkDestVA(Destination);
+ if (S & 1) {
+ MayUseShortThunk = false;
+ return false;
+ }
+ uint64_t P = getThunkTargetSym()->getVA();
+ int64_t Offset = S - P - 8;
+ MayUseShortThunk = llvm::isInt<26>(Offset);
+ return MayUseShortThunk;
+}
+
+void ARMThunk::writeTo(uint8_t *Buf) {
+ if (!mayUseShortThunk()) {
+ writeLong(Buf);
+ return;
+ }
+
+ uint64_t S = getARMThunkDestVA(Destination);
+ uint64_t P = getThunkTargetSym()->getVA();
+ int64_t Offset = S - P - 8;
+ const uint8_t Data[] = {
+ 0x00, 0x00, 0x00, 0xea, // b S
+ };
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_JUMP24, Offset);
+}
+
+bool ARMThunk::isCompatibleWith(RelType Type) const {
+ // Thumb branch relocations can't use BLX
+ return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
+}
+
+// This function returns true if the target is Thumb and is within 2^25, and
+// it has not previously returned false (see comment for MayUseShortThunk).
+bool ThumbThunk::mayUseShortThunk() {
+ if (!MayUseShortThunk)
+ return false;
+ uint64_t S = getARMThunkDestVA(Destination);
+ if ((S & 1) == 0) {
+ MayUseShortThunk = false;
+ return false;
+ }
+ uint64_t P = getThunkTargetSym()->getVA() & ~1;
+ int64_t Offset = S - P - 4;
+ MayUseShortThunk = llvm::isInt<25>(Offset);
+ return MayUseShortThunk;
+}
+
+void ThumbThunk::writeTo(uint8_t *Buf) {
+ if (!mayUseShortThunk()) {
+ writeLong(Buf);
+ return;
+ }
+
+ uint64_t S = getARMThunkDestVA(Destination);
+ uint64_t P = getThunkTargetSym()->getVA();
+ int64_t Offset = S - P - 4;
+ const uint8_t Data[] = {
+ 0x00, 0xf0, 0x00, 0xb0, // b.w S
+ };
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_THM_JUMP24, Offset);
+}
+
+bool ThumbThunk::isCompatibleWith(RelType Type) const {
+ // ARM branch relocations can't use BLX
+ return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
+}
+
+void ARMV7ABSLongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
@@ -215,18 +368,12 @@ void ARMV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
}
void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {
- ThunkSym = addSyntheticLocal(
- Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), IS);
- addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
-}
-
-bool ARMV7ABSLongThunk::isCompatibleWith(RelType Type) const {
- // Thumb branch relocations can't use BLX
- return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
+ addSymbol(Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()),
+ STT_FUNC, 0, IS);
+ addSymbol("$a", STT_NOTYPE, 0, IS);
}
-void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void ThumbV7ABSLongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
@@ -239,18 +386,12 @@ void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
}
void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
- ThunkSym = addSyntheticLocal(
- Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
- Offset | 0x1, size(), IS);
- addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
+ addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()),
+ STT_FUNC, 1, IS);
+ addSymbol("$t", STT_NOTYPE, 0, IS);
}
-bool ThumbV7ABSLongThunk::isCompatibleWith(RelType Type) const {
- // ARM branch relocations can't use BLX
- return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
-}
-
-void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void ARMV7PILongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8)
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8)
@@ -258,7 +399,7 @@ void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
0x1c, 0xff, 0x2f, 0xe1, // bx r12
};
uint64_t S = getARMThunkDestVA(Destination);
- uint64_t P = ThunkSym->getVA();
+ uint64_t P = getThunkTargetSym()->getVA();
uint64_t Offset = S - P - 16;
memcpy(Buf, Data, sizeof(Data));
Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset);
@@ -266,18 +407,12 @@ void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
}
void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {
- ThunkSym = addSyntheticLocal(
- Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), IS);
- addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
+ addSymbol(Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
+ 0, IS);
+ addSymbol("$a", STT_NOTYPE, 0, IS);
}
-bool ARMV7PILongThunk::isCompatibleWith(RelType Type) const {
- // Thumb branch relocations can't use BLX
- return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
-}
-
-void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void ThumbV7PILongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)
@@ -285,7 +420,7 @@ void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
0x60, 0x47, // bx r12
};
uint64_t S = getARMThunkDestVA(Destination);
- uint64_t P = ThunkSym->getVA() & ~0x1;
+ uint64_t P = getThunkTargetSym()->getVA() & ~0x1;
uint64_t Offset = S - P - 12;
memcpy(Buf, Data, sizeof(Data));
Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset);
@@ -293,32 +428,25 @@ void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
}
void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
- ThunkSym = addSyntheticLocal(
- Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC,
- Offset | 0x1, size(), IS);
- addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
-}
-
-bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const {
- // ARM branch relocations can't use BLX
- return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
+ addSymbol(Saver.save("__ThumbV7PILongThunk_" + Destination.getName()),
+ STT_FUNC, 1, IS);
+ addSymbol("$t", STT_NOTYPE, 0, IS);
}
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
-void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+void MipsThunk::writeTo(uint8_t *Buf) {
uint64_t S = Destination.getVA();
- write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func)
- write32(Buf + 4, 0x08000000 | (S >> 2), Config->Endianness); // j func
- write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
- write32(Buf + 12, 0x00000000, Config->Endianness); // nop
+ write32(Buf, 0x3c190000); // lui $25, %hi(func)
+ write32(Buf + 4, 0x08000000 | (S >> 2)); // j func
+ write32(Buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
+ write32(Buf + 12, 0x00000000); // nop
Target->relocateOne(Buf, R_MIPS_HI16, S);
Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
}
void MipsThunk::addSymbols(ThunkSection &IS) {
- ThunkSym =
- addSyntheticLocal(Saver.save("__LA25Thunk_" + Destination.getName()),
- STT_FUNC, Offset, size(), IS);
+ addSymbol(Saver.save("__LA25Thunk_" + Destination.getName()), STT_FUNC, 0,
+ IS);
}
InputSection *MipsThunk::getTargetInputSection() const {
@@ -328,22 +456,21 @@ InputSection *MipsThunk::getTargetInputSection() const {
// Write microMIPS R2-R5 LA25 thunk code
// to call PIC function from the non-PIC one.
-void MicroMipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+void MicroMipsThunk::writeTo(uint8_t *Buf) {
uint64_t S = Destination.getVA() | 1;
- write16(Buf, 0x41b9, Config->Endianness); // lui $25, %hi(func)
- write16(Buf + 4, 0xd400, Config->Endianness); // j func
- write16(Buf + 8, 0x3339, Config->Endianness); // addiu $25, $25, %lo(func)
- write16(Buf + 12, 0x0c00, Config->Endianness); // nop
+ write16(Buf, 0x41b9); // lui $25, %hi(func)
+ write16(Buf + 4, 0xd400); // j func
+ write16(Buf + 8, 0x3339); // addiu $25, $25, %lo(func)
+ write16(Buf + 12, 0x0c00); // nop
Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S);
Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S);
}
void MicroMipsThunk::addSymbols(ThunkSection &IS) {
- ThunkSym =
- addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
- STT_FUNC, Offset, size(), IS);
- ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+ Defined *D = addSymbol(
+ Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);
+ D->StOther |= STO_MIPS_MICROMIPS;
}
InputSection *MicroMipsThunk::getTargetInputSection() const {
@@ -353,22 +480,21 @@ InputSection *MicroMipsThunk::getTargetInputSection() const {
// Write microMIPS R6 LA25 thunk code
// to call PIC function from the non-PIC one.
-void MicroMipsR6Thunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+void MicroMipsR6Thunk::writeTo(uint8_t *Buf) {
uint64_t S = Destination.getVA() | 1;
- uint64_t P = ThunkSym->getVA();
- write16(Buf, 0x1320, Config->Endianness); // lui $25, %hi(func)
- write16(Buf + 4, 0x3339, Config->Endianness); // addiu $25, $25, %lo(func)
- write16(Buf + 8, 0x9400, Config->Endianness); // bc func
+ uint64_t P = getThunkTargetSym()->getVA();
+ write16(Buf, 0x1320); // lui $25, %hi(func)
+ write16(Buf + 4, 0x3339); // addiu $25, $25, %lo(func)
+ write16(Buf + 8, 0x9400); // bc func
Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S);
Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12);
}
void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) {
- ThunkSym =
- addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
- STT_FUNC, Offset, size(), IS);
- ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+ Defined *D = addSymbol(
+ Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);
+ D->StOther |= STO_MIPS_MICROMIPS;
}
InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
@@ -376,6 +502,25 @@ InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
return dyn_cast<InputSection>(DR.Section);
}
+void PPC64PltCallStub::writeTo(uint8_t *Buf) {
+ int64_t Off = Destination.getGotPltVA() - getPPC64TocBase();
+ // Need to add 0x8000 to offset to account for the low bits being signed.
+ uint16_t OffHa = (Off + 0x8000) >> 16;
+ uint16_t OffLo = Off;
+
+ write32(Buf + 0, 0xf8410018); // std r2,24(r1)
+ write32(Buf + 4, 0x3d820000 | OffHa); // addis r12,r2, X@plt@to@ha
+ write32(Buf + 8, 0xe98c0000 | OffLo); // ld r12,X@plt@toc@l(r12)
+ write32(Buf + 12, 0x7d8903a6); // mtctr r12
+ write32(Buf + 16, 0x4e800420); // bctr
+}
+
+void PPC64PltCallStub::addSymbols(ThunkSection &IS) {
+ Defined *S = addSymbol(Saver.save("__plt_" + Destination.getName()), STT_FUNC,
+ 0, IS);
+ S->NeedsTocRestore = true;
+}
+
Thunk::Thunk(Symbol &D) : Destination(D), Offset(0) {}
Thunk::~Thunk() = default;
@@ -419,15 +564,26 @@ static Thunk *addThunkMips(RelType Type, Symbol &S) {
return make<MipsThunk>(S);
}
+static Thunk *addThunkPPC64(RelType Type, Symbol &S) {
+ if (Type == R_PPC64_REL24)
+ return make<PPC64PltCallStub>(S);
+ fatal("unexpected relocation type");
+}
+
Thunk *addThunk(RelType Type, Symbol &S) {
if (Config->EMachine == EM_AARCH64)
return addThunkAArch64(Type, S);
- else if (Config->EMachine == EM_ARM)
+
+ if (Config->EMachine == EM_ARM)
return addThunkArm(Type, S);
- else if (Config->EMachine == EM_MIPS)
+
+ if (Config->EMachine == EM_MIPS)
return addThunkMips(Type, S);
- llvm_unreachable("add Thunk only supported for ARM and Mips");
- return nullptr;
+
+ if (Config->EMachine == EM_PPC64)
+ return addThunkPPC64(Type, S);
+
+ llvm_unreachable("add Thunk only supported for ARM, Mips and PowerPC");
}
} // end namespace elf
diff --git a/contrib/llvm/tools/lld/ELF/Thunks.h b/contrib/llvm/tools/lld/ELF/Thunks.h
index 828fac0bf53b..ed82b4d946ac 100644
--- a/contrib/llvm/tools/lld/ELF/Thunks.h
+++ b/contrib/llvm/tools/lld/ELF/Thunks.h
@@ -14,6 +14,7 @@
namespace lld {
namespace elf {
+class Defined;
class Symbol;
class ThunkSection;
// Class to describe an instance of a Thunk.
@@ -30,12 +31,17 @@ public:
Thunk(Symbol &Destination);
virtual ~Thunk();
- virtual uint32_t size() const { return 0; }
- virtual void writeTo(uint8_t *Buf, ThunkSection &IS) const {}
+ virtual uint32_t size() = 0;
+ virtual void writeTo(uint8_t *Buf) = 0;
- // All Thunks must define at least one symbol ThunkSym so that we can
- // redirect relocations to it.
- virtual void addSymbols(ThunkSection &IS) {}
+ // All Thunks must define at least one symbol, known as the thunk target
+ // symbol, so that we can redirect relocations to it. The thunk may define
+ // additional symbols, but these are never targets for relocations.
+ virtual void addSymbols(ThunkSection &IS) = 0;
+
+ void setOffset(uint64_t Offset);
+ Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
+ InputSectionBase &Section);
// Some Thunks must be placed immediately before their Target as they elide
// a branch and fall through to the first Symbol in the Target.
@@ -45,10 +51,12 @@ public:
// compatible with it.
virtual bool isCompatibleWith(RelType Type) const { return true; }
+ Defined *getThunkTargetSym() const { return Syms[0]; }
+
// The alignment requirement for this Thunk, defaults to the size of the
// typical code section alignment.
Symbol &Destination;
- Symbol *ThunkSym;
+ llvm::SmallVector<Defined *, 3> Syms;
uint64_t Offset = 0;
uint32_t Alignment = 4;
};
diff --git a/contrib/llvm/tools/lld/ELF/Writer.cpp b/contrib/llvm/tools/lld/ELF/Writer.cpp
index 40834a3e9522..d9f445c29235 100644
--- a/contrib/llvm/tools/lld/ELF/Writer.cpp
+++ b/contrib/llvm/tools/lld/ELF/Writer.cpp
@@ -9,18 +9,19 @@
#include "Writer.h"
#include "AArch64ErrataFix.h"
+#include "CallGraphSort.h"
#include "Config.h"
#include "Filesystem.h"
#include "LinkerScript.h"
#include "MapFile.h"
#include "OutputSections.h"
#include "Relocations.h"
-#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
@@ -49,7 +50,7 @@ public:
private:
void copyLocalSymbols();
void addSectionSymbols();
- void forEachRelSec(std::function<void(InputSectionBase &)> Fn);
+ void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> Fn);
void sortSections();
void resolveShfLinkOrder();
void sortInputSections();
@@ -62,6 +63,7 @@ private:
void assignFileOffsets();
void assignFileOffsetsBinary();
void setPhdrs();
+ void checkSections();
void fixSectionAlignments();
void openFile();
void writeTrapInstr();
@@ -81,39 +83,48 @@ private:
uint64_t FileSize;
uint64_t SectionHeaderOff;
-
- bool HasGotBaseSym = false;
};
} // anonymous namespace
-StringRef elf::getOutputSectionName(InputSectionBase *S) {
- // ".zdebug_" is a prefix for ZLIB-compressed sections.
- // Because we decompressed input sections, we want to remove 'z'.
- if (S->Name.startswith(".zdebug_"))
- return Saver.save("." + S->Name.substr(2));
+static bool isSectionPrefix(StringRef Prefix, StringRef Name) {
+ return Name.startswith(Prefix) || Name == Prefix.drop_back();
+}
+StringRef elf::getOutputSectionName(const InputSectionBase *S) {
if (Config->Relocatable)
return S->Name;
// This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want
// to emit .rela.text.foo as .rela.text.bar for consistency (this is not
// technically required, but not doing it is odd). This code guarantees that.
- if ((S->Type == SHT_REL || S->Type == SHT_RELA) &&
- !isa<SyntheticSection>(S)) {
- OutputSection *Out =
- cast<InputSection>(S)->getRelocatedSection()->getOutputSection();
- if (S->Type == SHT_RELA)
- return Saver.save(".rela" + Out->Name);
- return Saver.save(".rel" + Out->Name);
+ if (auto *IS = dyn_cast<InputSection>(S)) {
+ if (InputSectionBase *Rel = IS->getRelocatedSection()) {
+ OutputSection *Out = Rel->getOutputSection();
+ if (S->Type == SHT_RELA)
+ return Saver.save(".rela" + Out->Name);
+ return Saver.save(".rel" + Out->Name);
+ }
}
+ // This check is for -z keep-text-section-prefix. This option separates text
+ // sections with prefix ".text.hot", ".text.unlikely", ".text.startup" or
+ // ".text.exit".
+ // When enabled, this allows identifying the hot code region (.text.hot) in
+ // the final binary which can be selectively mapped to huge pages or mlocked,
+ // for instance.
+ if (Config->ZKeepTextSectionPrefix)
+ for (StringRef V :
+ {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) {
+ if (isSectionPrefix(V, S->Name))
+ return V.drop_back();
+ }
+
for (StringRef V :
{".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) {
- StringRef Prefix = V.drop_back();
- if (S->Name.startswith(V) || S->Name == Prefix)
- return Prefix;
+ if (isSectionPrefix(V, S->Name))
+ return V.drop_back();
}
// CommonSection is identified as "COMMON" in linker scripts.
@@ -194,21 +205,30 @@ void elf::addReservedSymbols() {
Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
}
+ // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which
+ // combines the typical ELF GOT with the small data sections. It commonly
+ // includes .got .toc .sdata .sbss. The .TOC. symbol replaces both
+ // _GLOBAL_OFFSET_TABLE_ and _SDA_BASE_ from the 32-bit ABI. It is used to
+ // represent the TOC base which is offset by 0x8000 bytes from the start of
+ // the .got section.
ElfSym::GlobalOffsetTable = addOptionalRegular(
- "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff);
+ (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_",
+ Out::ElfHeader, Target->GotBaseSymOff);
// __ehdr_start is the location of ELF file headers. Note that we define
// this symbol unconditionally even when using a linker script, which
// differs from the behavior implemented by GNU linker which only define
// this symbol if ELF headers are in the memory mapped segment.
+ addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
+
// __executable_start is not documented, but the expectation of at
- // least the android libc is that it points to the elf header too.
+ // least the Android libc is that it points to the ELF header.
+ addOptionalRegular("__executable_start", Out::ElfHeader, 0, STV_HIDDEN);
+
// __dso_handle symbol is passed to cxa_finalize as a marker to identify
// each DSO. The address of the symbol doesn't matter as long as they are
// different in different DSOs, so we chose the start address of the DSO.
- for (const char *Name :
- {"__ehdr_start", "__executable_start", "__dso_handle"})
- addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN);
+ addOptionalRegular("__dso_handle", Out::ElfHeader, 0, STV_HIDDEN);
// If linker script do layout we do not need to create any standart symbols.
if (Script->HasSectionsCommand)
@@ -267,6 +287,7 @@ template <class ELFT> static void createSyntheticSections() {
if (Config->Strip != StripPolicy::All) {
InX::StrTab = make<StringTableSection>(".strtab", false);
InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab);
+ InX::SymTabShndx = make<SymtabShndxSection>();
}
if (Config->BuildId != BuildIdKind::None) {
@@ -280,10 +301,9 @@ template <class ELFT> static void createSyntheticSections() {
// If there is a SECTIONS command and a .data.rel.ro section name use name
// .data.rel.ro.bss so that we match in the .data.rel.ro output section.
// This makes sure our relro is contiguous.
- bool HasDataRelRo =
- Script->HasSectionsCommand && findSection(".data.rel.ro");
- InX::BssRelRo = make<BssSection>(
- HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
+ bool HasDataRelRo = Script->HasSectionsCommand && findSection(".data.rel.ro");
+ InX::BssRelRo =
+ make<BssSection>(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
Add(InX::BssRelRo);
// Add MIPS-specific sections.
@@ -330,6 +350,11 @@ template <class ELFT> static void createSyntheticSections() {
Add(InX::RelaDyn);
}
+ if (Config->RelrPackDynRelocs) {
+ InX::RelrDyn = make<RelrSection<ELFT>>();
+ Add(InX::RelrDyn);
+ }
+
// Add .got. MIPS' .got is so different from the other archs,
// it has its own class.
if (Config->EMachine == EM_MIPS) {
@@ -346,7 +371,7 @@ template <class ELFT> static void createSyntheticSections() {
Add(InX::IgotPlt);
if (Config->GdbIndex) {
- InX::GdbIndex = createGdbIndex<ELFT>();
+ InX::GdbIndex = GdbIndexSection::create<ELFT>();
Add(InX::GdbIndex);
}
@@ -369,9 +394,9 @@ template <class ELFT> static void createSyntheticSections() {
false /*Sort*/);
Add(InX::RelaIplt);
- InX::Plt = make<PltSection>(Target->PltHeaderSize);
+ InX::Plt = make<PltSection>(false);
Add(InX::Plt);
- InX::Iplt = make<PltSection>(0);
+ InX::Iplt = make<PltSection>(true);
Add(InX::Iplt);
if (!Config->Relocatable) {
@@ -385,6 +410,8 @@ template <class ELFT> static void createSyntheticSections() {
if (InX::SymTab)
Add(InX::SymTab);
+ if (InX::SymTabShndx)
+ Add(InX::SymTabShndx);
Add(InX::ShStrTab);
if (InX::StrTab)
Add(InX::StrTab);
@@ -454,6 +481,9 @@ template <class ELFT> void Writer<ELFT>::run() {
Sec->Addr = 0;
}
+ if (Config->CheckSections)
+ checkSections();
+
// It does not make sense try to open the file if we have error already.
if (errorCount())
return;
@@ -476,8 +506,9 @@ template <class ELFT> void Writer<ELFT>::run() {
if (errorCount())
return;
- // Handle -Map option.
+ // Handle -Map and -cref options.
writeMapFile();
+ writeCrossReferenceTable();
if (errorCount())
return;
@@ -487,11 +518,7 @@ template <class ELFT> void Writer<ELFT>::run() {
static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,
const Symbol &B) {
- if (B.isFile() || B.isSection())
- return false;
-
- // If sym references a section in a discarded group, don't keep it.
- if (Sec == &InputSection::Discarded)
+ if (B.isSection())
return false;
if (Config->Discard == DiscardPolicy::None)
@@ -638,6 +665,9 @@ static bool isRelroSection(const OutputSection *Sec) {
if (InX::Got && Sec == InX::Got->getParent())
return true;
+ if (Sec->Name.equals(".toc"))
+ return true;
+
// .got.plt contains pointers to external function symbols. They are
// by default resolved lazily, so we usually cannot put it into RELRO.
// However, if "-z now" is given, the lazy symbol resolution is
@@ -669,20 +699,22 @@ static bool isRelroSection(const OutputSection *Sec) {
// * It is easy to check if a give branch was taken.
// * It is easy two see how similar two ranks are (see getRankProximity).
enum RankFlags {
- RF_NOT_ADDR_SET = 1 << 16,
- RF_NOT_INTERP = 1 << 15,
- RF_NOT_ALLOC = 1 << 14,
- RF_WRITE = 1 << 13,
- RF_EXEC_WRITE = 1 << 12,
- RF_EXEC = 1 << 11,
- RF_NON_TLS_BSS = 1 << 10,
- RF_NON_TLS_BSS_RO = 1 << 9,
- RF_NOT_TLS = 1 << 8,
- RF_BSS = 1 << 7,
+ RF_NOT_ADDR_SET = 1 << 18,
+ RF_NOT_INTERP = 1 << 17,
+ RF_NOT_ALLOC = 1 << 16,
+ RF_WRITE = 1 << 15,
+ RF_EXEC_WRITE = 1 << 14,
+ RF_EXEC = 1 << 13,
+ RF_RODATA = 1 << 12,
+ RF_NON_TLS_BSS = 1 << 11,
+ RF_NON_TLS_BSS_RO = 1 << 10,
+ RF_NOT_TLS = 1 << 9,
+ RF_BSS = 1 << 8,
+ RF_NOTE = 1 << 7,
RF_PPC_NOT_TOCBSS = 1 << 6,
- RF_PPC_OPD = 1 << 5,
- RF_PPC_TOCL = 1 << 4,
- RF_PPC_TOC = 1 << 3,
+ RF_PPC_TOCL = 1 << 5,
+ RF_PPC_TOC = 1 << 4,
+ RF_PPC_GOT = 1 << 3,
RF_PPC_BRANCH_LT = 1 << 2,
RF_MIPS_GPREL = 1 << 1,
RF_MIPS_NOT_GOT = 1 << 0
@@ -713,8 +745,7 @@ static unsigned getSectionRank(const OutputSection *Sec) {
// considerations:
// * Read-only sections come first such that they go in the
// PT_LOAD covering the program headers at the start of the file.
- // * Read-only, executable sections come next, unless the
- // -no-rosegment option is used.
+ // * Read-only, executable sections come next.
// * Writable, executable sections follow such that .plt on
// architectures where it needs to be writable will be placed
// between .text and .data.
@@ -726,11 +757,16 @@ static unsigned getSectionRank(const OutputSection *Sec) {
if (IsExec) {
if (IsWrite)
Rank |= RF_EXEC_WRITE;
- else if (!Config->SingleRoRx)
+ else
Rank |= RF_EXEC;
- } else {
- if (IsWrite)
- Rank |= RF_WRITE;
+ } else if (IsWrite) {
+ Rank |= RF_WRITE;
+ } else if (Sec->Type == SHT_PROGBITS) {
+ // Make non-executable and non-writable PROGBITS sections (e.g .rodata
+ // .eh_frame) closer to .text. They likely contain PC or GOT relative
+ // relocations and there could be relocation overflow if other huge sections
+ // (.dynstr .dynsym) were placed in between.
+ Rank |= RF_RODATA;
}
// If we got here we know that both A and B are in the same PT_LOAD.
@@ -766,6 +802,12 @@ static unsigned getSectionRank(const OutputSection *Sec) {
if (IsNoBits)
Rank |= RF_BSS;
+ // We create a NOTE segment for contiguous .note sections, so make
+ // them contigous if there are more than one .note section with the
+ // same attributes.
+ if (Sec->Type == SHT_NOTE)
+ Rank |= RF_NOTE;
+
// Some architectures have additional ordering restrictions for sections
// within the same PT_LOAD.
if (Config->EMachine == EM_PPC64) {
@@ -779,18 +821,19 @@ static unsigned getSectionRank(const OutputSection *Sec) {
if (Name != ".tocbss")
Rank |= RF_PPC_NOT_TOCBSS;
- if (Name == ".opd")
- Rank |= RF_PPC_OPD;
-
if (Name == ".toc1")
Rank |= RF_PPC_TOCL;
if (Name == ".toc")
Rank |= RF_PPC_TOC;
+ if (Name == ".got")
+ Rank |= RF_PPC_GOT;
+
if (Name == ".branch_lt")
Rank |= RF_PPC_BRANCH_LT;
}
+
if (Config->EMachine == EM_MIPS) {
// All sections with SHF_MIPS_GPREL flag should be grouped together
// because data in these sections is addressable with a gp relative address.
@@ -822,8 +865,6 @@ void PhdrEntry::add(OutputSection *Sec) {
p_align = std::max(p_align, Sec->Alignment);
if (p_type == PT_LOAD)
Sec->PtLoad = this;
- if (Sec->LMAExpr)
- ASectionHasLMA = true;
}
// The beginning and the ending of .rel[a].plt section are marked
@@ -833,17 +874,19 @@ void PhdrEntry::add(OutputSection *Sec) {
// need these symbols, since IRELATIVE relocs are resolved through GOT
// and PLT. For details, see http://www.airs.com/blog/archives/403.
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
- if (!Config->Static)
+ if (needsInterpSection())
return;
StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
- addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
+ ElfSym::RelaIpltEnd =
+ addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
}
template <class ELFT>
-void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) {
+void Writer<ELFT>::forEachRelSec(
+ llvm::function_ref<void(InputSectionBase &)> Fn) {
// Scan all relocations. Each relocation goes through a series
// of tests to determine if it needs special treatment, such as
// creating GOT, PLT, copy relocations, etc.
@@ -863,14 +906,18 @@ void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) {
// defining these symbols explicitly in the linker script.
template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
if (ElfSym::GlobalOffsetTable) {
- // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
- // be at some offset from the base of the .got section, usually 0 or the end
- // of the .got
- InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
- : cast<InputSection>(InX::Got);
+ // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually
+ // to the start of the .got or .got.plt section.
+ InputSection *GotSection = InX::GotPlt;
+ if (!Target->GotBaseSymInGotPlt)
+ GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
+ : cast<InputSection>(InX::Got);
ElfSym::GlobalOffsetTable->Section = GotSection;
}
+ if (ElfSym::RelaIpltEnd)
+ ElfSym::RelaIpltEnd->Value = InX::RelaIplt->getSize();
+
PhdrEntry *Last = nullptr;
PhdrEntry *LastRO = nullptr;
@@ -940,8 +987,7 @@ static int getRankProximityAux(OutputSection *A, OutputSection *B) {
static int getRankProximity(OutputSection *A, BaseCommand *B) {
if (auto *Sec = dyn_cast<OutputSection>(B))
- if (Sec->Live)
- return getRankProximityAux(A, Sec);
+ return getRankProximityAux(A, Sec);
return -1;
}
@@ -960,11 +1006,9 @@ static int getRankProximity(OutputSection *A, BaseCommand *B) {
// rw_sec : { *(rw_sec) }
// would mean that the RW PT_LOAD would become unaligned.
static bool shouldSkip(BaseCommand *Cmd) {
- if (isa<OutputSection>(Cmd))
- return false;
if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd))
return Assign->Name != ".";
- return true;
+ return false;
}
// We want to place orphan sections so that they share as much
@@ -987,20 +1031,16 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B,
int Proximity = getRankProximity(Sec, *I);
for (; I != E; ++I) {
auto *CurSec = dyn_cast<OutputSection>(*I);
- if (!CurSec || !CurSec->Live)
+ if (!CurSec)
continue;
if (getRankProximity(Sec, CurSec) != Proximity ||
Sec->SortRank < CurSec->SortRank)
break;
}
- auto IsLiveSection = [](BaseCommand *Cmd) {
- auto *OS = dyn_cast<OutputSection>(Cmd);
- return OS && OS->Live;
- };
-
+ auto IsOutputSec = [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); };
auto J = std::find_if(llvm::make_reverse_iterator(I),
- llvm::make_reverse_iterator(B), IsLiveSection);
+ llvm::make_reverse_iterator(B), IsOutputSec);
I = J.base();
// As a special case, if the orphan section is the last section, put
@@ -1008,7 +1048,7 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B,
// This matches bfd's behavior and is convenient when the linker script fully
// specifies the start of the file, but doesn't care about the end (the non
// alloc sections for example).
- auto NextSec = std::find_if(I, E, IsLiveSection);
+ auto NextSec = std::find_if(I, E, IsOutputSec);
if (NextSec == E)
return E;
@@ -1017,32 +1057,172 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B,
return I;
}
-// If no layout was provided by linker script, we want to apply default
-// sorting for special input sections and handle --symbol-ordering-file.
-template <class ELFT> void Writer<ELFT>::sortInputSections() {
- assert(!Script->HasSectionsCommand);
+// Builds section order for handling --symbol-ordering-file.
+static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
+ DenseMap<const InputSectionBase *, int> SectionOrder;
+ // Use the rarely used option -call-graph-ordering-file to sort sections.
+ if (!Config->CallGraphProfile.empty())
+ return computeCallGraphProfileOrder();
- // Sort input sections by priority using the list provided
- // by --symbol-ordering-file.
- DenseMap<SectionBase *, int> Order = buildSectionOrder();
- if (!Order.empty())
- for (BaseCommand *Base : Script->SectionCommands)
- if (auto *Sec = dyn_cast<OutputSection>(Base))
- if (Sec->Live)
- Sec->sort([&](InputSectionBase *S) { return Order.lookup(S); });
+ if (Config->SymbolOrderingFile.empty())
+ return SectionOrder;
+
+ struct SymbolOrderEntry {
+ int Priority;
+ bool Present;
+ };
+
+ // Build a map from symbols to their priorities. Symbols that didn't
+ // appear in the symbol ordering file have the lowest priority 0.
+ // All explicitly mentioned symbols have negative (higher) priorities.
+ DenseMap<StringRef, SymbolOrderEntry> SymbolOrder;
+ int Priority = -Config->SymbolOrderingFile.size();
+ for (StringRef S : Config->SymbolOrderingFile)
+ SymbolOrder.insert({S, {Priority++, false}});
+
+ // Build a map from sections to their priorities.
+ auto AddSym = [&](Symbol &Sym) {
+ auto It = SymbolOrder.find(Sym.getName());
+ if (It == SymbolOrder.end())
+ return;
+ SymbolOrderEntry &Ent = It->second;
+ Ent.Present = true;
+
+ warnUnorderableSymbol(&Sym);
+
+ if (auto *D = dyn_cast<Defined>(&Sym)) {
+ if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) {
+ int &Priority = SectionOrder[cast<InputSectionBase>(Sec->Repl)];
+ Priority = std::min(Priority, Ent.Priority);
+ }
+ }
+ };
+ // We want both global and local symbols. We get the global ones from the
+ // symbol table and iterate the object files for the local ones.
+ for (Symbol *Sym : Symtab->getSymbols())
+ if (!Sym->isLazy())
+ AddSym(*Sym);
+ for (InputFile *File : ObjectFiles)
+ for (Symbol *Sym : File->getSymbols())
+ if (Sym->isLocal())
+ AddSym(*Sym);
+
+ if (Config->WarnSymbolOrdering)
+ for (auto OrderEntry : SymbolOrder)
+ if (!OrderEntry.second.Present)
+ warn("symbol ordering file: no such symbol: " + OrderEntry.first);
+
+ return SectionOrder;
+}
+
+// Sorts the sections in ISD according to the provided section order.
+static void
+sortISDBySectionOrder(InputSectionDescription *ISD,
+ const DenseMap<const InputSectionBase *, int> &Order) {
+ std::vector<InputSection *> UnorderedSections;
+ std::vector<std::pair<InputSection *, int>> OrderedSections;
+ uint64_t UnorderedSize = 0;
+
+ for (InputSection *IS : ISD->Sections) {
+ auto I = Order.find(IS);
+ if (I == Order.end()) {
+ UnorderedSections.push_back(IS);
+ UnorderedSize += IS->getSize();
+ continue;
+ }
+ OrderedSections.push_back({IS, I->second});
+ }
+ llvm::sort(
+ OrderedSections.begin(), OrderedSections.end(),
+ [&](std::pair<InputSection *, int> A, std::pair<InputSection *, int> B) {
+ return A.second < B.second;
+ });
+
+ // Find an insertion point for the ordered section list in the unordered
+ // section list. On targets with limited-range branches, this is the mid-point
+ // of the unordered section list. This decreases the likelihood that a range
+ // extension thunk will be needed to enter or exit the ordered region. If the
+ // ordered section list is a list of hot functions, we can generally expect
+ // the ordered functions to be called more often than the unordered functions,
+ // making it more likely that any particular call will be within range, and
+ // therefore reducing the number of thunks required.
+ //
+ // For example, imagine that you have 8MB of hot code and 32MB of cold code.
+ // If the layout is:
+ //
+ // 8MB hot
+ // 32MB cold
+ //
+ // only the first 8-16MB of the cold code (depending on which hot function it
+ // is actually calling) can call the hot code without a range extension thunk.
+ // However, if we use this layout:
+ //
+ // 16MB cold
+ // 8MB hot
+ // 16MB cold
+ //
+ // both the last 8-16MB of the first block of cold code and the first 8-16MB
+ // of the second block of cold code can call the hot code without a thunk. So
+ // we effectively double the amount of code that could potentially call into
+ // the hot code without a thunk.
+ size_t InsPt = 0;
+ if (Target->ThunkSectionSpacing && !OrderedSections.empty()) {
+ uint64_t UnorderedPos = 0;
+ for (; InsPt != UnorderedSections.size(); ++InsPt) {
+ UnorderedPos += UnorderedSections[InsPt]->getSize();
+ if (UnorderedPos > UnorderedSize / 2)
+ break;
+ }
+ }
+
+ ISD->Sections.clear();
+ for (InputSection *IS : makeArrayRef(UnorderedSections).slice(0, InsPt))
+ ISD->Sections.push_back(IS);
+ for (std::pair<InputSection *, int> P : OrderedSections)
+ ISD->Sections.push_back(P.first);
+ for (InputSection *IS : makeArrayRef(UnorderedSections).slice(InsPt))
+ ISD->Sections.push_back(IS);
+}
+
+static void sortSection(OutputSection *Sec,
+ const DenseMap<const InputSectionBase *, int> &Order) {
+ StringRef Name = Sec->Name;
// Sort input sections by section name suffixes for
// __attribute__((init_priority(N))).
- if (OutputSection *Sec = findSection(".init_array"))
- Sec->sortInitFini();
- if (OutputSection *Sec = findSection(".fini_array"))
- Sec->sortInitFini();
+ if (Name == ".init_array" || Name == ".fini_array") {
+ if (!Script->HasSectionsCommand)
+ Sec->sortInitFini();
+ return;
+ }
// Sort input sections by the special rule for .ctors and .dtors.
- if (OutputSection *Sec = findSection(".ctors"))
- Sec->sortCtorsDtors();
- if (OutputSection *Sec = findSection(".dtors"))
- Sec->sortCtorsDtors();
+ if (Name == ".ctors" || Name == ".dtors") {
+ if (!Script->HasSectionsCommand)
+ Sec->sortCtorsDtors();
+ return;
+ }
+
+ // Never sort these.
+ if (Name == ".init" || Name == ".fini")
+ return;
+
+ // Sort input sections by priority using the list provided
+ // by --symbol-ordering-file.
+ if (!Order.empty())
+ for (BaseCommand *B : Sec->SectionCommands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(B))
+ sortISDBySectionOrder(ISD, Order);
+}
+
+// If no layout was provided by linker script, we want to apply default
+// sorting for special input sections. This also handles --symbol-ordering-file.
+template <class ELFT> void Writer<ELFT>::sortInputSections() {
+ // Build the order once since it is expensive.
+ DenseMap<const InputSectionBase *, int> Order = buildSectionOrder();
+ for (BaseCommand *Base : Script->SectionCommands)
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ sortSection(Sec, Order);
}
template <class ELFT> void Writer<ELFT>::sortSections() {
@@ -1053,22 +1233,29 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
if (Config->Relocatable)
return;
- for (BaseCommand *Base : Script->SectionCommands)
- if (auto *Sec = dyn_cast<OutputSection>(Base))
- Sec->SortRank = getSectionRank(Sec);
+ sortInputSections();
- if (!Script->HasSectionsCommand) {
- sortInputSections();
+ for (BaseCommand *Base : Script->SectionCommands) {
+ auto *OS = dyn_cast<OutputSection>(Base);
+ if (!OS)
+ continue;
+ OS->SortRank = getSectionRank(OS);
+
+ // We want to assign rude approximation values to OutSecOff fields
+ // to know the relative order of the input sections. We use it for
+ // sorting SHF_LINK_ORDER sections. See resolveShfLinkOrder().
+ uint64_t I = 0;
+ for (InputSection *Sec : getInputSections(OS))
+ Sec->OutSecOff = I++;
+ }
+ if (!Script->HasSectionsCommand) {
// We know that all the OutputSections are contiguous in this case.
- auto E = Script->SectionCommands.end();
- auto I = Script->SectionCommands.begin();
auto IsSection = [](BaseCommand *Base) { return isa<OutputSection>(Base); };
- I = std::find_if(I, E, IsSection);
- E = std::find_if(llvm::make_reverse_iterator(E),
- llvm::make_reverse_iterator(I), IsSection)
- .base();
- std::stable_sort(I, E, compareSections);
+ std::stable_sort(
+ llvm::find_if(Script->SectionCommands, IsSection),
+ llvm::find_if(llvm::reverse(Script->SectionCommands), IsSection).base(),
+ compareSections);
return;
}
@@ -1099,7 +1286,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// The way we define an order then is:
// * Sort only the orphan sections. They are in the end right now.
// * Move each orphan section to its preferred position. We try
- // to put each section in the last position where it it can share
+ // to put each section in the last position where it can share
// a PT_LOAD.
//
// There is some ambiguity as to where exactly a new entry should be
@@ -1115,7 +1302,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
auto E = Script->SectionCommands.end();
auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {
if (auto *Sec = dyn_cast<OutputSection>(Base))
- return Sec->Live && Sec->SectionIndex == INT_MAX;
+ return Sec->SectionIndex == UINT32_MAX;
return false;
});
@@ -1190,8 +1377,7 @@ static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
};
// Get the last table Entry from the previous .ARM.exidx section.
- const ExidxEntry &PrevEntry = *reinterpret_cast<const ExidxEntry *>(
- Prev->Data.data() + Prev->getSize() - sizeof(ExidxEntry));
+ const ExidxEntry &PrevEntry = Prev->getDataAs<ExidxEntry>().back();
if (IsExtabRef(PrevEntry.Unwind))
return false;
@@ -1203,14 +1389,7 @@ static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
// consecutive identical entries are rare and the effort to check that they
// are identical is high.
- if (isa<SyntheticSection>(Cur))
- // Exidx sentinel section has implicit EXIDX_CANTUNWIND;
- return PrevEntry.Unwind == 0x1;
-
- ArrayRef<const ExidxEntry> Entries(
- reinterpret_cast<const ExidxEntry *>(Cur->Data.data()),
- Cur->getSize() / sizeof(ExidxEntry));
- for (const ExidxEntry &Entry : Entries)
+ for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())
if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)
return false;
// All table entries in this .ARM.exidx Section can be merged into the
@@ -1240,13 +1419,12 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
if (!Config->Relocatable && Config->EMachine == EM_ARM &&
Sec->Type == SHT_ARM_EXIDX) {
- if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) {
+ if (auto *Sentinel = dyn_cast<ARMExidxSentinelSection>(Sections.back())) {
assert(Sections.size() >= 2 &&
"We should create a sentinel section only if there are "
"alive regular exidx sections.");
// The last executable section is required to fill the sentinel.
// Remember it here so that we don't have to find it again.
- auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back());
Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
}
@@ -1257,16 +1435,13 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
// previous one. This does not require any rewriting of InputSection
// contents but misses opportunities for fine grained deduplication
// where only a subset of the InputSection contents can be merged.
- int Cur = 1;
- int Prev = 0;
+ size_t Prev = 0;
// The last one is a sentinel entry which should not be removed.
- int N = Sections.size() - 1;
- while (Cur < N) {
- if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
- Sections[Cur] = nullptr;
+ for (size_t I = 1; I < Sections.size() - 1; ++I) {
+ if (isDuplicateArmExidxSec(Sections[Prev], Sections[I]))
+ Sections[I] = nullptr;
else
- Prev = Cur;
- ++Cur;
+ Prev = I;
}
}
}
@@ -1277,14 +1452,12 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
// Remove the Sections we marked as duplicate earlier.
for (BaseCommand *Base : Sec->SectionCommands)
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
- ISD->Sections.erase(
- std::remove(ISD->Sections.begin(), ISD->Sections.end(), nullptr),
- ISD->Sections.end());
+ llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; });
}
}
static void applySynthetic(const std::vector<SyntheticSection *> &Sections,
- std::function<void(SyntheticSection *)> Fn) {
+ llvm::function_ref<void(SyntheticSection *)> Fn) {
for (SyntheticSection *SS : Sections)
if (SS && SS->getParent() && !SS->empty())
Fn(SS);
@@ -1311,27 +1484,15 @@ static void removeUnusedSyntheticSections() {
if (!SS)
return;
OutputSection *OS = SS->getParent();
- if (!SS->empty() || !OS)
+ if (!OS || !SS->empty())
continue;
- std::vector<BaseCommand *>::iterator Empty = OS->SectionCommands.end();
- for (auto I = OS->SectionCommands.begin(), E = OS->SectionCommands.end();
- I != E; ++I) {
- BaseCommand *B = *I;
- if (auto *ISD = dyn_cast<InputSectionDescription>(B)) {
+ // If we reach here, then SS is an unused synthetic section and we want to
+ // remove it from corresponding input section description of output section.
+ for (BaseCommand *B : OS->SectionCommands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(B))
llvm::erase_if(ISD->Sections,
[=](InputSection *IS) { return IS == SS; });
- if (ISD->Sections.empty())
- Empty = I;
- }
- }
- if (Empty != OS->SectionCommands.end())
- OS->SectionCommands.erase(Empty);
-
- // If there are no other sections in the output section, remove it from the
- // output.
- if (OS->SectionCommands.empty())
- OS->Live = false;
}
}
@@ -1426,9 +1587,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (InX::DynSymTab && Sym->includeInDynsym()) {
InX::DynSymTab->addSymbol(Sym);
- if (auto *SS = dyn_cast<SharedSymbol>(Sym))
- if (cast<SharedFile<ELFT>>(Sym->File)->IsNeeded)
- In<ELFT>::VerNeed->addSymbol(SS);
+ if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File))
+ if (File->IsNeeded && !Sym->isUndefined())
+ In<ELFT>::VerNeed->addSymbol(Sym);
}
}
@@ -1436,10 +1597,12 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (errorCount())
return;
+ if (InX::MipsGot)
+ InX::MipsGot->build<ELFT>();
+
removeUnusedSyntheticSections();
sortSections();
- Script->removeEmptyCommands();
// Now that we have the final list, create a list of all the
// OutputSections for convenience.
@@ -1447,6 +1610,15 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (auto *Sec = dyn_cast<OutputSection>(Base))
OutputSections.push_back(Sec);
+ // Ensure data sections are not mixed with executable sections when
+ // -execute-only is used.
+ if (Config->ExecuteOnly)
+ for (OutputSection *OS : OutputSections)
+ if (OS->Flags & SHF_EXECINSTR)
+ for (InputSection *IS : getInputSections(OS))
+ if (!(IS->Flags & SHF_EXECINSTR))
+ error("-execute-only does not support intermingling data and code");
+
// Prefer command line supplied address over other constraints.
for (OutputSection *Sec : OutputSections) {
auto I = Config->SectionStartMap.find(Sec->Name);
@@ -1455,7 +1627,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
}
// This is a bit of a hack. A value of 0 means undef, so we set it
- // to 1 t make __ehdr_start defined. The section number is not
+ // to 1 to make __ehdr_start defined. The section number is not
// particularly relevant.
Out::ElfHeader->SectionIndex = 1;
@@ -1481,12 +1653,13 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one.
applySynthetic(
- {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab,
- InX::HashTab, InX::SymTab, InX::ShStrTab, InX::StrTab,
- In<ELFT>::VerDef, InX::DynStrTab, InX::Got, InX::MipsGot,
- InX::IgotPlt, InX::GotPlt, InX::RelaDyn, InX::RelaIplt,
- InX::RelaPlt, InX::Plt, InX::Iplt, InX::EhFrameHdr,
- In<ELFT>::VerSym, In<ELFT>::VerNeed, InX::Dynamic},
+ {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab,
+ InX::HashTab, InX::SymTab, InX::SymTabShndx, InX::ShStrTab,
+ InX::StrTab, In<ELFT>::VerDef, InX::DynStrTab, InX::Got,
+ InX::MipsGot, InX::IgotPlt, InX::GotPlt, InX::RelaDyn,
+ InX::RelrDyn, InX::RelaIplt, InX::RelaPlt, InX::Plt,
+ InX::Iplt, InX::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed,
+ InX::Dynamic},
[](SyntheticSection *SS) { SS->finalizeContents(); });
if (!Script->HasSectionsCommand && !Config->Relocatable)
@@ -1498,10 +1671,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Some architectures need to generate content that depends on the address
// of InputSections. For example some architectures use small displacements
- // for jump instructions that is is the linker's responsibility for creating
+ // for jump instructions that is the linker's responsibility for creating
// range extension thunks for. As the generation of the content may also
// alter InputSection addresses we must converge to a fixed point.
- if (Target->NeedsThunks || Config->AndroidPackDynRelocs) {
+ if (Target->NeedsThunks || Config->AndroidPackDynRelocs ||
+ Config->RelrPackDynRelocs) {
ThunkCreator TC;
AArch64Err843419Patcher A64P;
bool Changed;
@@ -1518,34 +1692,48 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (InX::MipsGot)
InX::MipsGot->updateAllocSize();
Changed |= InX::RelaDyn->updateAllocSize();
+ if (InX::RelrDyn)
+ Changed |= InX::RelrDyn->updateAllocSize();
} while (Changed);
}
+ // createThunks may have added local symbols to the static symbol table
+ applySynthetic({InX::SymTab},
+ [](SyntheticSection *SS) { SS->postThunkContents(); });
+
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
for (OutputSection *Sec : OutputSections)
Sec->finalize<ELFT>();
-
- // createThunks may have added local symbols to the static symbol table
- applySynthetic({InX::SymTab},
- [](SyntheticSection *SS) { SS->postThunkContents(); });
}
// The linker is expected to define SECNAME_start and SECNAME_end
// symbols for a few sections. This function defines them.
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
- auto Define = [&](StringRef Start, StringRef End, OutputSection *OS) {
- // These symbols resolve to the image base if the section does not exist.
- // A special value -1 indicates end of the section.
+ // If a section does not exist, there's ambiguity as to how we
+ // define _start and _end symbols for an init/fini section. Since
+ // the loader assume that the symbols are always defined, we need to
+ // always define them. But what value? The loader iterates over all
+ // pointers between _start and _end to run global ctors/dtors, so if
+ // the section is empty, their symbol values don't actually matter
+ // as long as _start and _end point to the same location.
+ //
+ // That said, we don't want to set the symbols to 0 (which is
+ // probably the simplest value) because that could cause some
+ // program to fail to link due to relocation overflow, if their
+ // program text is above 2 GiB. We use the address of the .text
+ // section instead to prevent that failure.
+ OutputSection *Default = findSection(".text");
+ if (!Default)
+ Default = Out::ElfHeader;
+ auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) {
if (OS) {
addOptionalRegular(Start, OS, 0);
addOptionalRegular(End, OS, -1);
} else {
- if (Config->Pic)
- OS = Out::ElfHeader;
- addOptionalRegular(Start, OS, 0);
- addOptionalRegular(End, OS, 0);
+ addOptionalRegular(Start, Default, 0);
+ addOptionalRegular(End, Default, 0);
}
};
@@ -1567,12 +1755,12 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
StringRef S = Sec->Name;
if (!isValidCIdentifier(S))
return;
- addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
- addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
+ addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_PROTECTED);
+ addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_PROTECTED);
}
static bool needsPtLoad(OutputSection *Sec) {
- if (!(Sec->Flags & SHF_ALLOC))
+ if (!(Sec->Flags & SHF_ALLOC) || Sec->Noload)
return false;
// Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
@@ -1590,6 +1778,8 @@ static bool needsPtLoad(OutputSection *Sec) {
static uint64_t computeFlags(uint64_t Flags) {
if (Config->Omagic)
return PF_R | PF_W | PF_X;
+ if (Config->ExecuteOnly && (Flags & PF_X))
+ return Flags & ~PF_R;
if (Config->SingleRoRx && !(Flags & PF_W))
return Flags | PF_X;
return Flags;
@@ -1628,10 +1818,14 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
// Segments are contiguous memory regions that has the same attributes
// (e.g. executable or writable). There is one phdr for each segment.
// Therefore, we need to create a new phdr when the next section has
- // different flags or is loaded at a discontiguous address using AT linker
- // script command.
+ // different flags or is loaded at a discontiguous address or memory
+ // region using AT or AT> linker script command, respectively. At the same
+ // time, we don't want to create a separate load segment for the headers,
+ // even if the first output section has an AT or AT> attribute.
uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
- if ((Sec->LMAExpr && Load->ASectionHasLMA) ||
+ if (((Sec->LMAExpr ||
+ (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) &&
+ Load->LastSec != Out::ProgramHeaders) ||
Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) {
Load = AddHdr(PT_LOAD, NewFlags);
@@ -1694,11 +1888,9 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
// pages for the stack non-executable. If you really want an executable
// stack, you can pass -z execstack, but that's not recommended for
// security reasons.
- unsigned Perm;
+ unsigned Perm = PF_R | PF_W;
if (Config->ZExecstack)
- Perm = PF_R | PF_W | PF_X;
- else
- Perm = PF_R | PF_W;
+ Perm |= PF_X;
AddHdr(PT_GNU_STACK, Perm)->p_memsz = Config->ZStackSize;
// PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable
@@ -1816,6 +2008,12 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
FileSize = alignTo(Off, Config->Wordsize);
}
+static std::string rangeToString(uint64_t Addr, uint64_t Len) {
+ if (Len == 0)
+ return "<empty range at 0x" + utohexstr(Addr) + ">";
+ return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]";
+}
+
// Assign file offsets to output sections.
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
uint64_t Off = 0;
@@ -1840,6 +2038,24 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
SectionHeaderOff = alignTo(Off, Config->Wordsize);
FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
+
+ // Our logic assumes that sections have rising VA within the same segment.
+ // With use of linker scripts it is possible to violate this rule and get file
+ // offset overlaps or overflows. That should never happen with a valid script
+ // which does not move the location counter backwards and usually scripts do
+ // not do that. Unfortunately, there are apps in the wild, for example, Linux
+ // kernel, which control segment distribution explicitly and move the counter
+ // backwards, so we have to allow doing that to support linking them. We
+ // perform non-critical checks for overlaps in checkSectionOverlap(), but here
+ // we want to prevent file size overflows because it would crash the linker.
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec->Type == SHT_NOBITS)
+ continue;
+ if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize))
+ error("unable to place section " + Sec->Name + " at file offset " +
+ rangeToString(Sec->Offset, Sec->Offset + Sec->Size) +
+ "; check your linker script for overflows");
+ }
}
// Finalize the program headers. We call this function after we assign
@@ -1878,6 +2094,97 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
}
}
+// A helper struct for checkSectionOverlap.
+namespace {
+struct SectionOffset {
+ OutputSection *Sec;
+ uint64_t Offset;
+};
+} // namespace
+
+// Check whether sections overlap for a specific address range (file offsets,
+// load and virtual adresses).
+static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections,
+ bool IsVirtualAddr) {
+ llvm::sort(Sections.begin(), Sections.end(),
+ [=](const SectionOffset &A, const SectionOffset &B) {
+ return A.Offset < B.Offset;
+ });
+
+ // Finding overlap is easy given a vector is sorted by start position.
+ // If an element starts before the end of the previous element, they overlap.
+ for (size_t I = 1, End = Sections.size(); I < End; ++I) {
+ SectionOffset A = Sections[I - 1];
+ SectionOffset B = Sections[I];
+ if (B.Offset >= A.Offset + A.Sec->Size)
+ continue;
+
+ // If both sections are in OVERLAY we allow the overlapping of virtual
+ // addresses, because it is what OVERLAY was designed for.
+ if (IsVirtualAddr && A.Sec->InOverlay && B.Sec->InOverlay)
+ continue;
+
+ errorOrWarn("section " + A.Sec->Name + " " + Name +
+ " range overlaps with " + B.Sec->Name + "\n>>> " + A.Sec->Name +
+ " range is " + rangeToString(A.Offset, A.Sec->Size) + "\n>>> " +
+ B.Sec->Name + " range is " +
+ rangeToString(B.Offset, B.Sec->Size));
+ }
+}
+
+// Check for overlapping sections and address overflows.
+//
+// In this function we check that none of the output sections have overlapping
+// file offsets. For SHF_ALLOC sections we also check that the load address
+// ranges and the virtual address ranges don't overlap
+template <class ELFT> void Writer<ELFT>::checkSections() {
+ // First, check that section's VAs fit in available address space for target.
+ for (OutputSection *OS : OutputSections)
+ if ((OS->Addr + OS->Size < OS->Addr) ||
+ (!ELFT::Is64Bits && OS->Addr + OS->Size > UINT32_MAX))
+ errorOrWarn("section " + OS->Name + " at 0x" + utohexstr(OS->Addr) +
+ " of size 0x" + utohexstr(OS->Size) +
+ " exceeds available address space");
+
+ // Check for overlapping file offsets. In this case we need to skip any
+ // section marked as SHT_NOBITS. These sections don't actually occupy space in
+ // the file so Sec->Offset + Sec->Size can overlap with others. If --oformat
+ // binary is specified only add SHF_ALLOC sections are added to the output
+ // file so we skip any non-allocated sections in that case.
+ std::vector<SectionOffset> FileOffs;
+ for (OutputSection *Sec : OutputSections)
+ if (0 < Sec->Size && Sec->Type != SHT_NOBITS &&
+ (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC)))
+ FileOffs.push_back({Sec, Sec->Offset});
+ checkOverlap("file", FileOffs, false);
+
+ // When linking with -r there is no need to check for overlapping virtual/load
+ // addresses since those addresses will only be assigned when the final
+ // executable/shared object is created.
+ if (Config->Relocatable)
+ return;
+
+ // Checking for overlapping virtual and load addresses only needs to take
+ // into account SHF_ALLOC sections since others will not be loaded.
+ // Furthermore, we also need to skip SHF_TLS sections since these will be
+ // mapped to other addresses at runtime and can therefore have overlapping
+ // ranges in the file.
+ std::vector<SectionOffset> VMAs;
+ for (OutputSection *Sec : OutputSections)
+ if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+ VMAs.push_back({Sec, Sec->Addr});
+ checkOverlap("virtual address", VMAs, true);
+
+ // Finally, check that the load addresses don't overlap. This will usually be
+ // the same as the virtual addresses but can be different when using a linker
+ // script with AT().
+ std::vector<SectionOffset> LMAs;
+ for (OutputSection *Sec : OutputSections)
+ if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+ LMAs.push_back({Sec, Sec->getLMA()});
+ checkOverlap("load address", LMAs, false);
+}
+
// The entry point address is chosen in the following ways.
//
// 1. the '-e' entry command-line option;
@@ -1919,8 +2226,20 @@ static uint16_t getELFType() {
return ET_EXEC;
}
+static uint8_t getAbiVersion() {
+ // MIPS non-PIC executable gets ABI version 1.
+ if (Config->EMachine == EM_MIPS && getELFType() == ET_EXEC &&
+ (Config->EFlags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
+ return 1;
+ return 0;
+}
+
template <class ELFT> void Writer<ELFT>::writeHeader() {
uint8_t *Buf = Buffer->getBufferStart();
+ // For executable segments, the trap instructions are written before writing
+ // the header. Setting Elf header bytes to zero ensures that any unused bytes
+ // in header are zero-cleared, instead of having trap instructions.
+ memset(Buf, 0, sizeof(Elf_Ehdr));
memcpy(Buf, "\177ELF", 4);
// Write the ELF header.
@@ -1929,6 +2248,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
EHdr->e_ident[EI_DATA] = Config->IsLE ? ELFDATA2LSB : ELFDATA2MSB;
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
EHdr->e_ident[EI_OSABI] = Config->OSABI;
+ EHdr->e_ident[EI_ABIVERSION] = getAbiVersion();
EHdr->e_type = getELFType();
EHdr->e_machine = Config->EMachine;
EHdr->e_version = EV_CURRENT;
@@ -1938,8 +2258,6 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
EHdr->e_ehsize = sizeof(Elf_Ehdr);
EHdr->e_phnum = Phdrs.size();
EHdr->e_shentsize = sizeof(Elf_Shdr);
- EHdr->e_shnum = OutputSections.size() + 1;
- EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex;
if (!Config->Relocatable) {
EHdr->e_phoff = sizeof(Elf_Ehdr);
@@ -1960,8 +2278,30 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
++HBuf;
}
- // Write the section header table. Note that the first table entry is null.
+ // Write the section header table.
+ //
+ // The ELF header can only store numbers up to SHN_LORESERVE in the e_shnum
+ // and e_shstrndx fields. When the value of one of these fields exceeds
+ // SHN_LORESERVE ELF requires us to put sentinel values in the ELF header and
+ // use fields in the section header at index 0 to store
+ // the value. The sentinel values and fields are:
+ // e_shnum = 0, SHdrs[0].sh_size = number of sections.
+ // e_shstrndx = SHN_XINDEX, SHdrs[0].sh_link = .shstrtab section index.
auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
+ size_t Num = OutputSections.size() + 1;
+ if (Num >= SHN_LORESERVE)
+ SHdrs->sh_size = Num;
+ else
+ EHdr->e_shnum = Num;
+
+ uint32_t StrTabIndex = InX::ShStrTab->getParent()->SectionIndex;
+ if (StrTabIndex >= SHN_LORESERVE) {
+ SHdrs->sh_link = StrTabIndex;
+ EHdr->e_shstrndx = SHN_XINDEX;
+ } else {
+ EHdr->e_shstrndx = StrTabIndex;
+ }
+
for (OutputSection *Sec : OutputSections)
Sec->writeHeaderTo<ELFT>(++SHdrs);
}
@@ -2032,14 +2372,6 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
template <class ELFT> void Writer<ELFT>::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
- // PPC64 needs to process relocations in the .opd section
- // before processing relocations in code-containing sections.
- if (auto *OpdCmd = findSection(".opd")) {
- Out::Opd = OpdCmd;
- Out::OpdBuf = Buf + Out::Opd->Offset;
- OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset);
- }
-
OutputSection *EhFrameHdr = nullptr;
if (InX::EhFrameHdr && !InX::EhFrameHdr->empty())
EhFrameHdr = InX::EhFrameHdr->getParent();
@@ -2052,8 +2384,7 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
Sec->writeTo<ELFT>(Buf + Sec->Offset);
for (OutputSection *Sec : OutputSections)
- if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
- Sec->Type != SHT_RELA)
+ if (Sec != EhFrameHdr && Sec->Type != SHT_REL && Sec->Type != SHT_RELA)
Sec->writeTo<ELFT>(Buf + Sec->Offset);
// The .eh_frame_hdr depends on .eh_frame section contents, therefore
diff --git a/contrib/llvm/tools/lld/ELF/Writer.h b/contrib/llvm/tools/lld/ELF/Writer.h
index f48f9d1e01b2..7806f824c58f 100644
--- a/contrib/llvm/tools/lld/ELF/Writer.h
+++ b/contrib/llvm/tools/lld/ELF/Writer.h
@@ -23,7 +23,6 @@ class InputSectionBase;
template <class ELFT> class ObjFile;
class SymbolTable;
template <class ELFT> void writeResult();
-template <class ELFT> void markLive();
// This describes a program header entry.
// Each contains type, access flags and range of output sections that will be
@@ -45,16 +44,11 @@ struct PhdrEntry {
OutputSection *LastSec = nullptr;
bool HasLMA = false;
- // True if one of the sections in this program header has a LMA specified via
- // linker script: AT(addr). We never allow 2 or more sections with LMA in the
- // same program header.
- bool ASectionHasLMA = false;
-
uint64_t LMAOffset = 0;
};
void addReservedSymbols();
-llvm::StringRef getOutputSectionName(InputSectionBase *S);
+llvm::StringRef getOutputSectionName(const InputSectionBase *S);
template <class ELFT> uint32_t calcMipsEFlags();
diff --git a/contrib/llvm/tools/lld/LICENSE.TXT b/contrib/llvm/tools/lld/LICENSE.TXT
index ec97986c86ba..e05e1845766e 100644
--- a/contrib/llvm/tools/lld/LICENSE.TXT
+++ b/contrib/llvm/tools/lld/LICENSE.TXT
@@ -4,7 +4,7 @@ lld License
University of Illinois/NCSA
Open Source License
-Copyright (c) 2011-2016 by the contributors listed in CREDITS.TXT
+Copyright (c) 2011-2018 by the contributors listed in CREDITS.TXT
All rights reserved.
Developed by:
diff --git a/contrib/llvm/tools/lld/docs/AtomLLD.rst b/contrib/llvm/tools/lld/docs/AtomLLD.rst
new file mode 100644
index 000000000000..614e568d1997
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/AtomLLD.rst
@@ -0,0 +1,62 @@
+ATOM-based lld
+==============
+
+Note: this document discuss Mach-O port of LLD. For ELF and COFF,
+see :doc:`index`.
+
+ATOM-based lld is a new set of modular code for creating linker tools.
+Currently it supports Mach-O.
+
+* End-User Features:
+
+ * Compatible with existing linker options
+ * Reads standard Object Files
+ * Writes standard Executable Files
+ * Remove clang's reliance on "the system linker"
+ * Uses the LLVM `"UIUC" BSD-Style license`__.
+
+* Applications:
+
+ * Modular design
+ * Support cross linking
+ * Easy to add new CPU support
+ * Can be built as static tool or library
+
+* Design and Implementation:
+
+ * Extensive unit tests
+ * Internal linker model can be dumped/read to textual format
+ * Additional linking features can be plugged in as "passes"
+ * OS specific and CPU specific code factored out
+
+Why a new linker?
+-----------------
+
+The fact that clang relies on whatever linker tool you happen to have installed
+means that clang has been very conservative adopting features which require a
+recent linker.
+
+In the same way that the MC layer of LLVM has removed clang's reliance on the
+system assembler tool, the lld project will remove clang's reliance on the
+system linker tool.
+
+
+Contents
+--------
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ getting_started
+ development
+ open_projects
+ sphinx_intro
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`search`
+
+__ http://llvm.org/docs/DeveloperPolicy.html#license
diff --git a/contrib/llvm/tools/lld/docs/CMakeLists.txt b/contrib/llvm/tools/lld/docs/CMakeLists.txt
new file mode 100644
index 000000000000..112ce35e8cf4
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/CMakeLists.txt
@@ -0,0 +1,8 @@
+if (LLVM_ENABLE_SPHINX)
+ include(AddSphinxTarget)
+ if (SPHINX_FOUND)
+ if (${SPHINX_OUTPUT_HTML})
+ add_sphinx_target(html lld)
+ endif()
+ endif()
+endif()
diff --git a/contrib/llvm/tools/lld/docs/Driver.rst b/contrib/llvm/tools/lld/docs/Driver.rst
new file mode 100644
index 000000000000..4ee6ce0c985f
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/Driver.rst
@@ -0,0 +1,82 @@
+======
+Driver
+======
+
+Note: this document discuss Mach-O port of LLD. For ELF and COFF,
+see :doc:`index`.
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+This document describes the lld driver. The purpose of this document is to
+describe both the motivation and design goals for the driver, as well as details
+of the internal implementation.
+
+Overview
+========
+
+The lld driver is designed to support a number of different command line
+interfaces. The main interfaces we plan to support are binutils' ld, Apple's
+ld, and Microsoft's link.exe.
+
+Flavors
+-------
+
+Each of these different interfaces is referred to as a flavor. There is also an
+extra flavor "core" which is used to exercise the core functionality of the
+linker it the test suite.
+
+* gnu
+* darwin
+* link
+* core
+
+Selecting a Flavor
+^^^^^^^^^^^^^^^^^^
+
+There are two different ways to tell lld which flavor to be. They are checked in
+order, so the second overrides the first. The first is to symlink :program:`lld`
+as :program:`lld-{flavor}` or just :program:`{flavor}`. You can also specify
+it as the first command line argument using ``-flavor``::
+
+ $ lld -flavor gnu
+
+There is a shortcut for ``-flavor core`` as ``-core``.
+
+
+Adding an Option to an existing Flavor
+======================================
+
+#. Add the option to the desired :file:`lib/Driver/{flavor}Options.td`.
+
+#. Add to :cpp:class:`lld::FlavorLinkingContext` a getter and setter method
+ for the option.
+
+#. Modify :cpp:func:`lld::FlavorDriver::parse` in :file:
+ `lib/Driver/{Flavor}Driver.cpp` to call the targetInfo setter
+ for corresponding to the option.
+
+#. Modify {Flavor}Reader and {Flavor}Writer to use the new targtInfo option.
+
+
+Adding a Flavor
+===============
+
+#. Add an entry for the flavor in :file:`include/lld/Common/Driver.h` to
+ :cpp:class:`lld::UniversalDriver::Flavor`.
+
+#. Add an entry in :file:`lib/Driver/UniversalDriver.cpp` to
+ :cpp:func:`lld::Driver::strToFlavor` and
+ :cpp:func:`lld::UniversalDriver::link`.
+ This allows the flavor to be selected via symlink and `-flavor`.
+
+#. Add a tablegen file called :file:`lib/Driver/{flavor}Options.td` that
+ describes the options. If the options are a superset of another driver, that
+ driver's td file can simply be included. The :file:`{flavor}Options.td` file
+ must also be added to :file:`lib/Driver/CMakeLists.txt`.
+
+#. Add a ``{flavor}Driver`` as a subclass of :cpp:class:`lld::Driver`
+ in :file:`lib/Driver/{flavor}Driver.cpp`.
diff --git a/contrib/llvm/tools/lld/docs/NewLLD.rst b/contrib/llvm/tools/lld/docs/NewLLD.rst
new file mode 100644
index 000000000000..afdb41e0a145
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/NewLLD.rst
@@ -0,0 +1,309 @@
+The ELF, COFF and Wasm Linkers
+==============================
+
+The ELF Linker as a Library
+---------------------------
+
+You can embed LLD to your program by linking against it and calling the linker's
+entry point function lld::elf::link.
+
+The current policy is that it is your reponsibility to give trustworthy object
+files. The function is guaranteed to return as long as you do not pass corrupted
+or malicious object files. A corrupted file could cause a fatal error or SEGV.
+That being said, you don't need to worry too much about it if you create object
+files in the usual way and give them to the linker. It is naturally expected to
+work, or otherwise it's a linker's bug.
+
+Design
+======
+
+We will describe the design of the linkers in the rest of the document.
+
+Key Concepts
+------------
+
+Linkers are fairly large pieces of software.
+There are many design choices you have to make to create a complete linker.
+
+This is a list of design choices we've made for ELF and COFF LLD.
+We believe that these high-level design choices achieved a right balance
+between speed, simplicity and extensibility.
+
+* Implement as native linkers
+
+ We implemented the linkers as native linkers for each file format.
+
+ The linkers share the same design but share very little code.
+ Sharing code makes sense if the benefit is worth its cost.
+ In our case, the object formats are different enough that we thought the layer
+ to abstract the differences wouldn't be worth its complexity and run-time
+ cost. Elimination of the abstract layer has greatly simplified the
+ implementation.
+
+* Speed by design
+
+ One of the most important things in archiving high performance is to
+ do less rather than do it efficiently.
+ Therefore, the high-level design matters more than local optimizations.
+ Since we are trying to create a high-performance linker,
+ it is very important to keep the design as efficient as possible.
+
+ Broadly speaking, we do not do anything until we have to do it.
+ For example, we do not read section contents or relocations
+ until we need them to continue linking.
+ When we need to do some costly operation (such as looking up
+ a hash table for each symbol), we do it only once.
+ We obtain a handler (which is typically just a pointer to actual data)
+ on the first operation and use it throughout the process.
+
+* Efficient archive file handling
+
+ LLD's handling of archive files (the files with ".a" file extension) is
+ different from the traditional Unix linkers and similar to Windows linkers.
+ We'll describe how the traditional Unix linker handles archive files, what the
+ problem is, and how LLD approached the problem.
+
+ The traditional Unix linker maintains a set of undefined symbols during
+ linking. The linker visits each file in the order as they appeared in the
+ command line until the set becomes empty. What the linker would do depends on
+ file type.
+
+ - If the linker visits an object file, the linker links object files to the
+ result, and undefined symbols in the object file are added to the set.
+
+ - If the linker visits an archive file, it checks for the archive file's
+ symbol table and extracts all object files that have definitions for any
+ symbols in the set.
+
+ This algorithm sometimes leads to a counter-intuitive behavior. If you give
+ archive files before object files, nothing will happen because when the linker
+ visits archives, there is no undefined symbols in the set. As a result, no
+ files are extracted from the first archive file, and the link is done at that
+ point because the set is empty after it visits one file.
+
+ You can fix the problem by reordering the files,
+ but that cannot fix the issue of mutually-dependent archive files.
+
+ Linking mutually-dependent archive files is tricky. You may specify the same
+ archive file multiple times to let the linker visit it more than once. Or,
+ you may use the special command line options, `--start-group` and
+ `--end-group`, to let the linker loop over the files between the options until
+ no new symbols are added to the set.
+
+ Visiting the same archive files multiple makes the linker slower.
+
+ Here is how LLD approaches the problem. Instead of memorizing only undefined
+ symbols, we program LLD so that it memorizes all symbols. When it sees an
+ undefined symbol that can be resolved by extracting an object file from an
+ archive file it previously visited, it immediately extracts the file and link
+ it. It is doable because LLD does not forget symbols it have seen in archive
+ files.
+
+ We believe that the LLD's way is efficient and easy to justify.
+
+ The semantics of LLD's archive handling is different from the traditional
+ Unix's. You can observe it if you carefully craft archive files to exploit
+ it. However, in reality, we don't know any program that cannot link with our
+ algorithm so far, so it's not going to cause trouble.
+
+Numbers You Want to Know
+------------------------
+
+To give you intuition about what kinds of data the linker is mainly working on,
+I'll give you the list of objects and their numbers LLD has to read and process
+in order to link a very large executable. In order to link Chrome with debug
+info, which is roughly 2 GB in output size, LLD reads
+
+- 17,000 files,
+- 1,800,000 sections,
+- 6,300,000 symbols, and
+- 13,000,000 relocations.
+
+LLD produces the 2 GB executable in 15 seconds.
+
+These numbers vary depending on your program, but in general,
+you have a lot of relocations and symbols for each file.
+If your program is written in C++, symbol names are likely to be
+pretty long because of name mangling.
+
+It is important to not waste time on relocations and symbols.
+
+In the above case, the total amount of symbol strings is 450 MB,
+and inserting all of them to a hash table takes 1.5 seconds.
+Therefore, if you causally add a hash table lookup for each symbol,
+it would slow down the linker by 10%. So, don't do that.
+
+On the other hand, you don't have to pursue efficiency
+when handling files.
+
+Important Data Structures
+-------------------------
+
+We will describe the key data structures in LLD in this section. The linker can
+be understood as the interactions between them. Once you understand their
+functions, the code of the linker should look obvious to you.
+
+* Symbol
+
+ This class represents a symbol.
+ They are created for symbols in object files or archive files.
+ The linker creates linker-defined symbols as well.
+
+ There are basically three types of Symbols: Defined, Undefined, or Lazy.
+
+ - Defined symbols are for all symbols that are considered as "resolved",
+ including real defined symbols, COMDAT symbols, common symbols,
+ absolute symbols, linker-created symbols, etc.
+ - Undefined symbols represent undefined symbols, which need to be replaced by
+ Defined symbols by the resolver until the link is complete.
+ - Lazy symbols represent symbols we found in archive file headers
+ which can turn into Defined if we read archieve members.
+
+ There's only one Symbol instance for each unique symbol name. This uniqueness
+ is guaranteed by the symbol table. As the resolver reads symbols from input
+ files, it replaces an existing Symbol with the "best" Symbol for its symbol
+ name using the placement new.
+
+ The above mechanism allows you to use pointers to Symbols as a very cheap way
+ to access name resolution results. Assume for example that you have a pointer
+ to an undefined symbol before name resolution. If the symbol is resolved to a
+ defined symbol by the resolver, the pointer will "automatically" point to the
+ defined symbol, because the undefined symbol the pointer pointed to will have
+ been replaced by the defined symbol in-place.
+
+* SymbolTable
+
+ SymbolTable is basically a hash table from strings to Symbols
+ with logic to resolve symbol conflicts. It resolves conflicts by symbol type.
+
+ - If we add Defined and Undefined symbols, the symbol table will keep the
+ former.
+ - If we add Defined and Lazy symbols, it will keep the former.
+ - If we add Lazy and Undefined, it will keep the former,
+ but it will also trigger the Lazy symbol to load the archive member
+ to actually resolve the symbol.
+
+* Chunk (COFF specific)
+
+ Chunk represents a chunk of data that will occupy space in an output.
+ Each regular section becomes a chunk.
+ Chunks created for common or BSS symbols are not backed by sections.
+ The linker may create chunks to append additional data to an output as well.
+
+ Chunks know about their size, how to copy their data to mmap'ed outputs,
+ and how to apply relocations to them.
+ Specifically, section-based chunks know how to read relocation tables
+ and how to apply them.
+
+* InputSection (ELF specific)
+
+ Since we have less synthesized data for ELF, we don't abstract slices of
+ input files as Chunks for ELF. Instead, we directly use the input section
+ as an internal data type.
+
+ InputSection knows about their size and how to copy themselves to
+ mmap'ed outputs, just like COFF Chunks.
+
+* OutputSection
+
+ OutputSection is a container of InputSections (ELF) or Chunks (COFF).
+ An InputSection or Chunk belongs to at most one OutputSection.
+
+There are mainly three actors in this linker.
+
+* InputFile
+
+ InputFile is a superclass of file readers.
+ We have a different subclass for each input file type,
+ such as regular object file, archive file, etc.
+ They are responsible for creating and owning Symbols and InputSections/Chunks.
+
+* Writer
+
+ The writer is responsible for writing file headers and InputSections/Chunks to
+ a file. It creates OutputSections, put all InputSections/Chunks into them,
+ assign unique, non-overlapping addresses and file offsets to them, and then
+ write them down to a file.
+
+* Driver
+
+ The linking process is driven by the driver. The driver:
+
+ - processes command line options,
+ - creates a symbol table,
+ - creates an InputFile for each input file and puts all symbols within into
+ the symbol table,
+ - checks if there's no remaining undefined symbols,
+ - creates a writer,
+ - and passes the symbol table to the writer to write the result to a file.
+
+Link-Time Optimization
+----------------------
+
+LTO is implemented by handling LLVM bitcode files as object files.
+The linker resolves symbols in bitcode files normally. If all symbols
+are successfully resolved, it then runs LLVM passes
+with all bitcode files to convert them to one big regular ELF/COFF file.
+Finally, the linker replaces bitcode symbols with ELF/COFF symbols,
+so that they are linked as if they were in the native format from the beginning.
+
+The details are described in this document.
+http://llvm.org/docs/LinkTimeOptimization.html
+
+Glossary
+--------
+
+* RVA (COFF)
+
+ Short for Relative Virtual Address.
+
+ Windows executables or DLLs are not position-independent; they are
+ linked against a fixed address called an image base. RVAs are
+ offsets from an image base.
+
+ Default image bases are 0x140000000 for executables and 0x18000000
+ for DLLs. For example, when we are creating an executable, we assume
+ that the executable will be loaded at address 0x140000000 by the
+ loader, so we apply relocations accordingly. Result texts and data
+ will contain raw absolute addresses.
+
+* VA
+
+ Short for Virtual Address. For COFF, it is equivalent to RVA + image base.
+
+* Base relocations (COFF)
+
+ Relocation information for the loader. If the loader decides to map
+ an executable or a DLL to a different address than their image
+ bases, it fixes up binaries using information contained in the base
+ relocation table. A base relocation table consists of a list of
+ locations containing addresses. The loader adds a difference between
+ RVA and actual load address to all locations listed there.
+
+ Note that this run-time relocation mechanism is much simpler than ELF.
+ There's no PLT or GOT. Images are relocated as a whole just
+ by shifting entire images in memory by some offsets. Although doing
+ this breaks text sharing, I think this mechanism is not actually bad
+ on today's computers.
+
+* ICF
+
+ Short for Identical COMDAT Folding (COFF) or Identical Code Folding (ELF).
+
+ ICF is an optimization to reduce output size by merging read-only sections
+ by not only their names but by their contents. If two read-only sections
+ happen to have the same metadata, actual contents and relocations,
+ they are merged by ICF. It is known as an effective technique,
+ and it usually reduces C++ program's size by a few percent or more.
+
+ Note that this is not an entirely sound optimization. C/C++ require
+ different functions have different addresses. If a program depends on
+ that property, it would fail at runtime.
+
+ On Windows, that's not really an issue because MSVC link.exe enabled
+ the optimization by default. As long as your program works
+ with the linker's default settings, your program should be safe with ICF.
+
+ On Unix, your program is generally not guaranteed to be safe with ICF,
+ although large programs happen to work correctly.
+ LLD works fine with ICF for example.
diff --git a/contrib/llvm/tools/lld/docs/README.txt b/contrib/llvm/tools/lld/docs/README.txt
new file mode 100644
index 000000000000..eb09a2d2b7ea
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/README.txt
@@ -0,0 +1,12 @@
+lld Documentation
+=================
+
+The lld documentation is written using the Sphinx documentation generator. It is
+currently tested with Sphinx 1.1.3.
+
+We currently use the 'nature' theme and a Beaker inspired structure.
+
+To rebuild documents into html:
+
+ [/lld/docs]> make html
+
diff --git a/contrib/llvm/tools/lld/docs/Readers.rst b/contrib/llvm/tools/lld/docs/Readers.rst
new file mode 100644
index 000000000000..b69a0b34fabe
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/Readers.rst
@@ -0,0 +1,174 @@
+.. _Readers:
+
+Developing lld Readers
+======================
+
+Note: this document discuss Mach-O port of LLD. For ELF and COFF,
+see :doc:`index`.
+
+Introduction
+------------
+
+The purpose of a "Reader" is to take an object file in a particular format
+and create an `lld::File`:cpp:class: (which is a graph of Atoms)
+representing the object file. A Reader inherits from
+`lld::Reader`:cpp:class: which lives in
+:file:`include/lld/Core/Reader.h` and
+:file:`lib/Core/Reader.cpp`.
+
+The Reader infrastructure for an object format ``Foo`` requires the
+following pieces in order to fit into lld:
+
+:file:`include/lld/ReaderWriter/ReaderFoo.h`
+
+ .. cpp:class:: ReaderOptionsFoo : public ReaderOptions
+
+ This Options class is the only way to configure how the Reader will
+ parse any file into an `lld::Reader`:cpp:class: object. This class
+ should be declared in the `lld`:cpp:class: namespace.
+
+ .. cpp:function:: Reader *createReaderFoo(ReaderOptionsFoo &reader)
+
+ This factory function configures and create the Reader. This function
+ should be declared in the `lld`:cpp:class: namespace.
+
+:file:`lib/ReaderWriter/Foo/ReaderFoo.cpp`
+
+ .. cpp:class:: ReaderFoo : public Reader
+
+ This is the concrete Reader class which can be called to parse
+ object files. It should be declared in an anonymous namespace or
+ if there is shared code with the `lld::WriterFoo`:cpp:class: you
+ can make a nested namespace (e.g. `lld::foo`:cpp:class:).
+
+You may have noticed that :cpp:class:`ReaderFoo` is not declared in the
+``.h`` file. An important design aspect of lld is that all Readers are
+created *only* through an object-format-specific
+:cpp:func:`createReaderFoo` factory function. The creation of the Reader is
+parametrized through a :cpp:class:`ReaderOptionsFoo` class. This options
+class is the one-and-only way to control how the Reader operates when
+parsing an input file into an Atom graph. For instance, you may want the
+Reader to only accept certain architectures. The options class can be
+instantiated from command line options or be programmatically configured.
+
+Where to start
+--------------
+
+The lld project already has a skeleton of source code for Readers for
+``ELF``, ``PECOFF``, ``MachO``, and lld's native ``YAML`` graph format.
+If your file format is a variant of one of those, you should modify the
+existing Reader to support your variant. This is done by customizing the Options
+class for the Reader and making appropriate changes to the ``.cpp`` file to
+interpret those options and act accordingly.
+
+If your object file format is not a variant of any existing Reader, you'll need
+to create a new Reader subclass with the organization described above.
+
+Readers are factories
+---------------------
+
+The linker will usually only instantiate your Reader once. That one Reader will
+have its loadFile() method called many times with different input files.
+To support multithreaded linking, the Reader may be parsing multiple input
+files in parallel. Therefore, there should be no parsing state in you Reader
+object. Any parsing state should be in ivars of your File subclass or in
+some temporary object.
+
+The key method to implement in a reader is::
+
+ virtual error_code loadFile(LinkerInput &input,
+ std::vector<std::unique_ptr<File>> &result);
+
+It takes a memory buffer (which contains the contents of the object file
+being read) and returns an instantiated lld::File object which is
+a collection of Atoms. The result is a vector of File pointers (instead of
+simple a File pointer) because some file formats allow multiple object
+"files" to be encoded in one file system file.
+
+
+Memory Ownership
+----------------
+
+Atoms are always owned by their File object. During core linking when Atoms
+are coalesced or stripped away, core linking does not delete them.
+Core linking just removes those unused Atoms from its internal list.
+The destructor of a File object is responsible for deleting all Atoms it
+owns, and if ownership of the MemoryBuffer was passed to it, the File
+destructor needs to delete that too.
+
+Making Atoms
+------------
+
+The internal model of lld is purely Atom based. But most object files do not
+have an explicit concept of Atoms, instead most have "sections". The way
+to think of this is that a section is just a list of Atoms with common
+attributes.
+
+The first step in parsing section-based object files is to cleave each
+section into a list of Atoms. The technique may vary by section type. For
+code sections (e.g. .text), there are usually symbols at the start of each
+function. Those symbol addresses are the points at which the section is
+cleaved into discrete Atoms. Some file formats (like ELF) also include the
+length of each symbol in the symbol table. Otherwise, the length of each
+Atom is calculated to run to the start of the next symbol or the end of the
+section.
+
+Other sections types can be implicitly cleaved. For instance c-string literals
+or unwind info (e.g. .eh_frame) can be cleaved by having the Reader look at
+the content of the section. It is important to cleave sections into Atoms
+to remove false dependencies. For instance the .eh_frame section often
+has no symbols, but contains "pointers" to the functions for which it
+has unwind info. If the .eh_frame section was not cleaved (but left as one
+big Atom), there would always be a reference (from the eh_frame Atom) to
+each function. So the linker would be unable to coalesce or dead stripped
+away the function atoms.
+
+The lld Atom model also requires that a reference to an undefined symbol be
+modeled as a Reference to an UndefinedAtom. So the Reader also needs to
+create an UndefinedAtom for each undefined symbol in the object file.
+
+Once all Atoms have been created, the second step is to create References
+(recall that Atoms are "nodes" and References are "edges"). Most References
+are created by looking at the "relocation records" in the object file. If
+a function contains a call to "malloc", there is usually a relocation record
+specifying the address in the section and the symbol table index. Your
+Reader will need to convert the address to an Atom and offset and the symbol
+table index into a target Atom. If "malloc" is not defined in the object file,
+the target Atom of the Reference will be an UndefinedAtom.
+
+
+Performance
+-----------
+Once you have the above working to parse an object file into Atoms and
+References, you'll want to look at performance. Some techniques that can
+help performance are:
+
+* Use llvm::BumpPtrAllocator or pre-allocate one big vector<Reference> and then
+ just have each atom point to its subrange of References in that vector.
+ This can be faster that allocating each Reference as separate object.
+* Pre-scan the symbol table and determine how many atoms are in each section
+ then allocate space for all the Atom objects at once.
+* Don't copy symbol names or section content to each Atom, instead use
+ StringRef and ArrayRef in each Atom to point to its name and content in the
+ MemoryBuffer.
+
+
+Testing
+-------
+
+We are still working on infrastructure to test Readers. The issue is that
+you don't want to check in binary files to the test suite. And the tools
+for creating your object file from assembly source may not be available on
+every OS.
+
+We are investigating a way to use YAML to describe the section, symbols,
+and content of a file. Then have some code which will write out an object
+file from that YAML description.
+
+Once that is in place, you can write test cases that contain section/symbols
+YAML and is run through the linker to produce Atom/References based YAML which
+is then run through FileCheck to verify the Atoms and References are as
+expected.
+
+
+
diff --git a/contrib/llvm/tools/lld/docs/ReleaseNotes.rst b/contrib/llvm/tools/lld/docs/ReleaseNotes.rst
new file mode 100644
index 000000000000..58f47980893a
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/ReleaseNotes.rst
@@ -0,0 +1,43 @@
+=======================
+LLD 7.0.0 Release Notes
+=======================
+
+.. contents::
+ :local:
+
+.. warning::
+ These are in-progress notes for the upcoming LLVM 7.0.0 release.
+ Release notes for previous releases can be found on
+ `the Download Page <http://releases.llvm.org/download.html>`_.
+
+Introduction
+============
+
+This document contains the release notes for the lld linker, release 7.0.0.
+Here we describe the status of lld, including major improvements
+from the previous release. All lld releases may be downloaded
+from the `LLVM releases web site <http://llvm.org/releases/>`_.
+
+Non-comprehensive list of changes in this release
+=================================================
+
+ELF Improvements
+----------------
+
+* Item 1.
+
+COFF Improvements
+-----------------
+
+* Improved correctness of exporting mangled stdcall symbols.
+
+* Completed support for ARM64 relocations.
+
+* Added support for outputting PDB debug info for MinGW targets.
+
+* Improved compatibility of output binaries with GNU binutils objcopy/strip.
+
+MachO Improvements
+------------------
+
+* Item 1.
diff --git a/contrib/llvm/tools/lld/docs/WebAssembly.rst b/contrib/llvm/tools/lld/docs/WebAssembly.rst
new file mode 100644
index 000000000000..264d221970b1
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/WebAssembly.rst
@@ -0,0 +1,36 @@
+WebAssembly lld port
+====================
+
+Note: The WebAssembly port is still a work in progress and is be lacking
+certain features.
+
+The WebAssembly version of lld takes WebAssembly binaries as inputs and produces
+a WebAssembly binary as its output. For the most part this port tried to mimic
+the behaviour of traditional ELF linkers and specifically the ELF lld port.
+Where possible that command line flags and the semantics should be the same.
+
+
+Object file format
+------------------
+
+The format the input object files that lld expects is specified as part of the
+the WebAssembly tool conventions
+https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md.
+
+This is object format that the llvm will produce when run with the
+``wasm32-unknown-unknown`` target. To build llvm with WebAssembly support
+currently requires enabling the experimental backed using
+``-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly``.
+
+
+Missing features
+----------------
+
+There are several key features that are not yet implement in the WebAssembly
+ports:
+
+- COMDAT support. This means that support for C++ is still very limited.
+- Function stripping. Currently there is no support for ``--gc-sections`` so
+ functions and data from a given object will linked as a unit.
+- Section start/end symbols. The synthetic symbols that mark the start and
+ of data regions are not yet created in the output file.
diff --git a/contrib/llvm/tools/lld/docs/_static/favicon.ico b/contrib/llvm/tools/lld/docs/_static/favicon.ico
new file mode 100644
index 000000000000..724ad6e12dd4
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/_static/favicon.ico
Binary files differ
diff --git a/contrib/llvm/tools/lld/docs/_templates/indexsidebar.html b/contrib/llvm/tools/lld/docs/_templates/indexsidebar.html
new file mode 100644
index 000000000000..588be9309bde
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/_templates/indexsidebar.html
@@ -0,0 +1,4 @@
+<h3>Bugs</h3>
+
+<p>lld bugs should be reported at the
+ LLVM <a href="https://bugs.llvm.org/">Bugzilla</a>.</p>
diff --git a/contrib/llvm/tools/lld/docs/_templates/layout.html b/contrib/llvm/tools/lld/docs/_templates/layout.html
new file mode 100644
index 000000000000..519a24bce63a
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/_templates/layout.html
@@ -0,0 +1,12 @@
+{% extends "!layout.html" %}
+
+{% block extrahead %}
+<style type="text/css">
+ table.right { float: right; margin-left: 20px; }
+ table.right td { border: 1px solid #ccc; }
+</style>
+{% endblock %}
+
+{% block rootrellink %}
+ <li><a href="{{ pathto('index') }}">lld Home</a>&nbsp;|&nbsp;</li>
+{% endblock %}
diff --git a/contrib/llvm/tools/lld/docs/conf.py b/contrib/llvm/tools/lld/docs/conf.py
new file mode 100644
index 000000000000..3598fbf50f0d
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/conf.py
@@ -0,0 +1,255 @@
+# -*- coding: utf-8 -*-
+#
+# lld documentation build configuration file.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+from datetime import date
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'lld'
+copyright = u'2011-%d, LLVM Project' % date.today().year
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short version.
+version = '7'
+# The full version, including alpha/beta/rc tags.
+release = '7'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%Y-%m-%d'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+show_authors = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'friendly'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'llvm-theme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ["."]
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# If given, this must be the name of an image file (path relative to the
+# configuration directory) that is the favicon of the docs. Modern browsers use
+# this as icon for tabs, windows and bookmarks. It should be a Windows-style
+# icon file (.ico), which is 16x16 or 32x32 pixels large. Default: None. The
+# image file will be copied to the _static directory of the output HTML, but
+# only if the file does not already exist there.
+html_favicon = '_static/favicon.ico'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%Y-%m-%d'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {'index': 'indexsidebar.html'}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+# html_additional_pages = {'index': 'index.html'}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'llddoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('contents', 'lld.tex', u'lld Documentation',
+ u'LLVM project', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('contents', 'lld', u'lld Documentation',
+ [u'LLVM project'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('contents', 'lld', u'lld Documentation',
+ u'LLVM project', 'lld', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# FIXME: Define intersphinx configration.
+intersphinx_mapping = {}
+
+
+# -- Options for extensions ----------------------------------------------------
+
+# Enable this if you want TODOs to show up in the generated documentation.
+todo_include_todos = True
diff --git a/contrib/llvm/tools/lld/docs/design.rst b/contrib/llvm/tools/lld/docs/design.rst
new file mode 100644
index 000000000000..1e111f979bb5
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/design.rst
@@ -0,0 +1,421 @@
+.. _design:
+
+Linker Design
+=============
+
+Note: this document discuss Mach-O port of LLD. For ELF and COFF,
+see :doc:`index`.
+
+Introduction
+------------
+
+lld is a new generation of linker. It is not "section" based like traditional
+linkers which mostly just interlace sections from multiple object files into the
+output file. Instead, lld is based on "Atoms". Traditional section based
+linking work well for simple linking, but their model makes advanced linking
+features difficult to implement. Features like dead code stripping, reordering
+functions for locality, and C++ coalescing require the linker to work at a finer
+grain.
+
+An atom is an indivisible chunk of code or data. An atom has a set of
+attributes, such as: name, scope, content-type, alignment, etc. An atom also
+has a list of References. A Reference contains: a kind, an optional offset, an
+optional addend, and an optional target atom.
+
+The Atom model allows the linker to use standard graph theory models for linking
+data structures. Each atom is a node, and each Reference is an edge. The
+feature of dead code stripping is implemented by following edges to mark all
+live atoms, and then delete the non-live atoms.
+
+
+Atom Model
+----------
+
+An atom is an indivisible chunk of code or data. Typically each user written
+function or global variable is an atom. In addition, the compiler may emit
+other atoms, such as for literal c-strings or floating point constants, or for
+runtime data structures like dwarf unwind info or pointers to initializers.
+
+A simple "hello world" object file would be modeled like this:
+
+.. image:: hello.png
+
+There are three atoms: main, a proxy for printf, and an anonymous atom
+containing the c-string literal "hello world". The Atom "main" has two
+references. One is the call site for the call to printf, and the other is a
+reference for the instruction that loads the address of the c-string literal.
+
+There are only four different types of atoms:
+
+ * DefinedAtom
+ 95% of all atoms. This is a chunk of code or data
+
+ * UndefinedAtom
+ This is a place holder in object files for a reference to some atom
+ outside the translation unit.During core linking it is usually replaced
+ by (coalesced into) another Atom.
+
+ * SharedLibraryAtom
+ If a required symbol name turns out to be defined in a dynamic shared
+ library (and not some object file). A SharedLibraryAtom is the
+ placeholder Atom used to represent that fact.
+
+ It is similar to an UndefinedAtom, but it also tracks information
+ about the associated shared library.
+
+ * AbsoluteAtom
+ This is for embedded support where some stuff is implemented in ROM at
+ some fixed address. This atom has no content. It is just an address
+ that the Writer needs to fix up any references to point to.
+
+
+File Model
+----------
+
+The linker views the input files as basically containers of Atoms and
+References, and just a few attributes of their own. The linker works with three
+kinds of files: object files, static libraries, and dynamic shared libraries.
+Each kind of file has reader object which presents the file in the model
+expected by the linker.
+
+Object File
+~~~~~~~~~~~
+
+An object file is just a container of atoms. When linking an object file, a
+reader is instantiated which parses the object file and instantiates a set of
+atoms representing all content in the .o file. The linker adds all those atoms
+to a master graph.
+
+Static Library (Archive)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the traditional unix static archive which is just a collection of object
+files with a "table of contents". When linking with a static library, by default
+nothing is added to the master graph of atoms. Instead, if after merging all
+atoms from object files into a master graph, if any "undefined" atoms are left
+remaining in the master graph, the linker reads the table of contents for each
+static library to see if any have the needed definitions. If so, the set of
+atoms from the specified object file in the static library is added to the
+master graph of atoms.
+
+Dynamic Library (Shared Object)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Dynamic libraries are different than object files and static libraries in that
+they don't directly add any content. Their purpose is to check at build time
+that the remaining undefined references can be resolved at runtime, and provide
+a list of dynamic libraries (SO_NEEDED) that will be needed at runtime. The way
+this is modeled in the linker is that a dynamic library contributes no atoms to
+the initial graph of atoms. Instead, (like static libraries) if there are
+"undefined" atoms in the master graph of all atoms, then each dynamic library is
+checked to see if exports the required symbol. If so, a "shared library" atom is
+instantiated by the by the reader which the linker uses to replace the
+"undefined" atom.
+
+Linking Steps
+-------------
+
+Through the use of abstract Atoms, the core of linking is architecture
+independent and file format independent. All command line parsing is factored
+out into a separate "options" abstraction which enables the linker to be driven
+with different command line sets.
+
+The overall steps in linking are:
+
+ #. Command line processing
+
+ #. Parsing input files
+
+ #. Resolving
+
+ #. Passes/Optimizations
+
+ #. Generate output file
+
+The Resolving and Passes steps are done purely on the master graph of atoms, so
+they have no notion of file formats such as mach-o or ELF.
+
+
+Input Files
+~~~~~~~~~~~
+
+Existing developer tools using different file formats for object files.
+A goal of lld is to be file format independent. This is done
+through a plug-in model for reading object files. The lld::Reader is the base
+class for all object file readers. A Reader follows the factory method pattern.
+A Reader instantiates an lld::File object (which is a graph of Atoms) from a
+given object file (on disk or in-memory).
+
+Every Reader subclass defines its own "options" class (for instance the mach-o
+Reader defines the class ReaderOptionsMachO). This options class is the
+one-and-only way to control how the Reader operates when parsing an input file
+into an Atom graph. For instance, you may want the Reader to only accept
+certain architectures. The options class can be instantiated from command
+line options, or it can be subclassed and the ivars programmatically set.
+
+Resolving
+~~~~~~~~~
+
+The resolving step takes all the atoms' graphs from each object file and
+combines them into one master object graph. Unfortunately, it is not as simple
+as appending the atom list from each file into one big list. There are many
+cases where atoms need to be coalesced. That is, two or more atoms need to be
+coalesced into one atom. This is necessary to support: C language "tentative
+definitions", C++ weak symbols for templates and inlines defined in headers,
+replacing undefined atoms with actual definition atoms, and for merging copies
+of constants like c-strings and floating point constants.
+
+The linker support coalescing by-name and by-content. By-name is used for
+tentative definitions and weak symbols. By-content is used for constant data
+that can be merged.
+
+The resolving process maintains some global linking "state", including a "symbol
+table" which is a map from llvm::StringRef to lld::Atom*. With these data
+structures, the linker iterates all atoms in all input files. For each atom, it
+checks if the atom is named and has a global or hidden scope. If so, the atom
+is added to the symbol table map. If there already is a matching atom in that
+table, that means the current atom needs to be coalesced with the found atom, or
+it is a multiple definition error.
+
+When all initial input file atoms have been processed by the resolver, a scan is
+made to see if there are any undefined atoms in the graph. If there are, the
+linker scans all libraries (both static and dynamic) looking for definitions to
+replace the undefined atoms. It is an error if any undefined atoms are left
+remaining.
+
+Dead code stripping (if requested) is done at the end of resolving. The linker
+does a simple mark-and-sweep. It starts with "root" atoms (like "main" in a main
+executable) and follows each references and marks each Atom that it visits as
+"live". When done, all atoms not marked "live" are removed.
+
+The result of the Resolving phase is the creation of an lld::File object. The
+goal is that the lld::File model is **the** internal representation
+throughout the linker. The file readers parse (mach-o, ELF, COFF) into an
+lld::File. The file writers (mach-o, ELF, COFF) taken an lld::File and produce
+their file kind, and every Pass only operates on an lld::File. This is not only
+a simpler, consistent model, but it enables the state of the linker to be dumped
+at any point in the link for testing purposes.
+
+
+Passes
+~~~~~~
+
+The Passes step is an open ended set of routines that each get a change to
+modify or enhance the current lld::File object. Some example Passes are:
+
+ * stub (PLT) generation
+
+ * GOT instantiation
+
+ * order_file optimization
+
+ * branch island generation
+
+ * branch shim generation
+
+ * Objective-C optimizations (Darwin specific)
+
+ * TLV instantiation (Darwin specific)
+
+ * DTrace probe processing (Darwin specific)
+
+ * compact unwind encoding (Darwin specific)
+
+
+Some of these passes are specific to Darwin's runtime environments. But many of
+the passes are applicable to any OS (such as generating branch island for out of
+range branch instructions).
+
+The general structure of a pass is to iterate through the atoms in the current
+lld::File object, inspecting each atom and doing something. For instance, the
+stub pass, looks for call sites to shared library atoms (e.g. call to printf).
+It then instantiates a "stub" atom (PLT entry) and a "lazy pointer" atom for
+each proxy atom needed, and these new atoms are added to the current lld::File
+object. Next, all the noted call sites to shared library atoms have their
+References altered to point to the stub atom instead of the shared library atom.
+
+
+Generate Output File
+~~~~~~~~~~~~~~~~~~~~
+
+Once the passes are done, the output file writer is given current lld::File
+object. The writer's job is to create the executable content file wrapper and
+place the content of the atoms into it.
+
+lld uses a plug-in model for writing output files. All concrete writers (e.g.
+ELF, mach-o, etc) are subclasses of the lld::Writer class.
+
+Unlike the Reader class which has just one method to instantiate an lld::File,
+the Writer class has multiple methods. The crucial method is to generate the
+output file, but there are also methods which allow the Writer to contribute
+Atoms to the resolver and specify passes to run.
+
+An example of contributing
+atoms is that if the Writer knows a main executable is being linked and such
+an executable requires a specially named entry point (e.g. "_main"), the Writer
+can add an UndefinedAtom with that special name to the resolver. This will
+cause the resolver to issue an error if that symbol is not defined.
+
+Sometimes a Writer supports lazily created symbols, such as names for the start
+of sections. To support this, the Writer can create a File object which vends
+no initial atoms, but does lazily supply atoms by name as needed.
+
+Every Writer subclass defines its own "options" class (for instance the mach-o
+Writer defines the class WriterOptionsMachO). This options class is the
+one-and-only way to control how the Writer operates when producing an output
+file from an Atom graph. For instance, you may want the Writer to optimize
+the output for certain OS versions, or strip local symbols, etc. The options
+class can be instantiated from command line options, or it can be subclassed
+and the ivars programmatically set.
+
+
+lld::File representations
+-------------------------
+
+Just as LLVM has three representations of its IR model, lld has two
+representations of its File/Atom/Reference model:
+
+ * In memory, abstract C++ classes (lld::Atom, lld::Reference, and lld::File).
+
+ * textual (in YAML)
+
+
+Textual representations in YAML
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In designing a textual format we want something easy for humans to read and easy
+for the linker to parse. Since an atom has lots of attributes most of which are
+usually just the default, we should define default values for every attribute so
+that those can be omitted from the text representation. Here is the atoms for a
+simple hello world program expressed in YAML::
+
+ target-triple: x86_64-apple-darwin11
+
+ atoms:
+ - name: _main
+ scope: global
+ type: code
+ content: [ 55, 48, 89, e5, 48, 8d, 3d, 00, 00, 00, 00, 30, c0, e8, 00, 00,
+ 00, 00, 31, c0, 5d, c3 ]
+ fixups:
+ - offset: 07
+ kind: pcrel32
+ target: 2
+ - offset: 0E
+ kind: call32
+ target: _fprintf
+
+ - type: c-string
+ content: [ 73, 5A, 00 ]
+
+ ...
+
+The biggest use for the textual format will be writing test cases. Writing test
+cases in C is problematic because the compiler may vary its output over time for
+its own optimization reasons which my inadvertently disable or break the linker
+feature trying to be tested. By writing test cases in the linkers own textual
+format, we can exactly specify every attribute of every atom and thus target
+specific linker logic.
+
+The textual/YAML format follows the ReaderWriter patterns used in lld. The lld
+library comes with the classes: ReaderYAML and WriterYAML.
+
+
+Testing
+-------
+
+The lld project contains a test suite which is being built up as new code is
+added to lld. All new lld functionality should have a tests added to the test
+suite. The test suite is `lit <http://llvm.org/cmds/lit.html/>`_ driven. Each
+test is a text file with comments telling lit how to run the test and check the
+result To facilitate testing, the lld project builds a tool called lld-core.
+This tool reads a YAML file (default from stdin), parses it into one or more
+lld::File objects in memory and then feeds those lld::File objects to the
+resolver phase.
+
+
+Resolver testing
+~~~~~~~~~~~~~~~~
+
+Basic testing is the "core linking" or resolving phase. That is where the
+linker merges object files. All test cases are written in YAML. One feature of
+YAML is that it allows multiple "documents" to be encoding in one YAML stream.
+That means one text file can appear to the linker as multiple .o files - the
+normal case for the linker.
+
+Here is a simple example of a core linking test case. It checks that an
+undefined atom from one file will be replaced by a definition from another
+file::
+
+ # RUN: lld-core %s | FileCheck %s
+
+ #
+ # Test that undefined atoms are replaced with defined atoms.
+ #
+
+ ---
+ atoms:
+ - name: foo
+ definition: undefined
+ ---
+ atoms:
+ - name: foo
+ scope: global
+ type: code
+ ...
+
+ # CHECK: name: foo
+ # CHECK: scope: global
+ # CHECK: type: code
+ # CHECK-NOT: name: foo
+ # CHECK: ...
+
+
+Passes testing
+~~~~~~~~~~~~~~
+
+Since Passes just operate on an lld::File object, the lld-core tool has the
+option to run a particular pass (after resolving). Thus, you can write a YAML
+test case with carefully crafted input to exercise areas of a Pass and the check
+the resulting lld::File object as represented in YAML.
+
+
+Design Issues
+-------------
+
+There are a number of open issues in the design of lld. The plan is to wait and
+make these design decisions when we need to.
+
+
+Debug Info
+~~~~~~~~~~
+
+Currently, the lld model says nothing about debug info. But the most popular
+debug format is DWARF and there is some impedance mismatch with the lld model
+and DWARF. In lld there are just Atoms and only Atoms that need to be in a
+special section at runtime have an associated section. Also, Atoms do not have
+addresses. The way DWARF is spec'ed different parts of DWARF are supposed to go
+into specially named sections and the DWARF references function code by address.
+
+CPU and OS specific functionality
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Currently, lld has an abstract "Platform" that deals with any CPU or OS specific
+differences in linking. We just keep adding virtual methods to the base
+Platform class as we find linking areas that might need customization. At some
+point we'll need to structure this better.
+
+
+File Attributes
+~~~~~~~~~~~~~~~
+
+Currently, lld::File just has a path and a way to iterate its atoms. We will
+need to add more attributes on a File. For example, some equivalent to the
+target triple. There is also a number of cached or computed attributes that
+could make various Passes more efficient. For instance, on Darwin there are a
+number of Objective-C optimizations that can be done by a Pass. But it would
+improve the plain C case if the Objective-C optimization Pass did not have to
+scan all atoms looking for any Objective-C data structures. This could be done
+if the lld::File object had an attribute that said if the file had any
+Objective-C data in it. The Resolving phase would then be required to "merge"
+that attribute as object files are added.
diff --git a/contrib/llvm/tools/lld/docs/development.rst b/contrib/llvm/tools/lld/docs/development.rst
new file mode 100644
index 000000000000..ce91341d665f
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/development.rst
@@ -0,0 +1,45 @@
+.. _development:
+
+Development
+===========
+
+Note: this document discuss Mach-O port of LLD. For ELF and COFF,
+see :doc:`index`.
+
+lld is developed as part of the `LLVM <http://llvm.org>`_ project.
+
+Creating a Reader
+-----------------
+
+See the :ref:`Creating a Reader <Readers>` guide.
+
+
+Modifying the Driver
+--------------------
+
+See :doc:`Driver`.
+
+
+Debugging
+---------
+
+You can run lld with ``-mllvm -debug`` command line options to enable debugging
+printouts. If you want to enable debug information for some specific pass, you
+can run it with ``-mllvm '-debug-only=<pass>'``, where pass is a name used in
+the ``DEBUG_WITH_TYPE()`` macro.
+
+
+
+Documentation
+-------------
+
+The project documentation is written in reStructuredText and generated using the
+`Sphinx <http://sphinx.pocoo.org/>`_ documentation generator. For more
+information on writing documentation for the project, see the
+:ref:`sphinx_intro`.
+
+.. toctree::
+ :hidden:
+
+ Readers
+ Driver
diff --git a/contrib/llvm/tools/lld/docs/getting_started.rst b/contrib/llvm/tools/lld/docs/getting_started.rst
new file mode 100644
index 000000000000..97c3d1bccbda
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/getting_started.rst
@@ -0,0 +1,106 @@
+.. _getting_started:
+
+Getting Started: Building and Running lld
+=========================================
+
+This page gives you the shortest path to checking out and building lld. If you
+run into problems, please file bugs in the `LLVM Bugzilla`__
+
+__ http://llvm.org/bugs/
+
+Building lld
+------------
+
+On Unix-like Systems
+~~~~~~~~~~~~~~~~~~~~
+
+1. Get the required tools.
+
+ * `CMake 2.8`_\+.
+ * make (or any build system CMake supports).
+ * `Clang 3.1`_\+ or GCC 4.7+ (C++11 support is required).
+
+ * If using Clang, you will also need `libc++`_.
+ * `Python 2.4`_\+ (not 3.x) for running tests.
+
+.. _CMake 2.8: http://www.cmake.org/cmake/resources/software.html
+.. _Clang 3.1: http://clang.llvm.org/
+.. _libc++: http://libcxx.llvm.org/
+.. _Python 2.4: http://python.org/download/
+
+2. Check out LLVM::
+
+ $ cd path/to/llvm-project
+ $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
+
+3. Check out lld::
+
+ $ cd llvm/tools
+ $ svn co http://llvm.org/svn/llvm-project/lld/trunk lld
+
+ * lld can also be checked out to ``path/to/llvm-project`` and built as an external
+ project.
+
+4. Build LLVM and lld::
+
+ $ cd path/to/llvm-build/llvm (out of source build required)
+ $ cmake -G "Unix Makefiles" path/to/llvm-project/llvm
+ $ make
+
+ * If you want to build with clang and it is not the default compiler or
+ it is installed in an alternate location, you'll need to tell the cmake tool
+ the location of the C and C++ compiler via CMAKE_C_COMPILER and
+ CMAKE_CXX_COMPILER. For example::
+
+ $ cmake -DCMAKE_CXX_COMPILER=/path/to/clang++ -DCMAKE_C_COMPILER=/path/to/clang ...
+
+5. Test::
+
+ $ make check-lld
+
+Using Visual Studio
+~~~~~~~~~~~~~~~~~~~
+
+#. Get the required tools.
+
+ * `CMake 2.8`_\+.
+ * `Visual Studio 12 (2013) or later`_ (required for C++11 support)
+ * `Python 2.4`_\+ (not 3.x) for running tests.
+
+.. _CMake 2.8: http://www.cmake.org/cmake/resources/software.html
+.. _Visual Studio 12 (2013) or later: http://www.microsoft.com/visualstudio/11/en-us
+.. _Python 2.4: http://python.org/download/
+
+#. Check out LLVM::
+
+ $ cd path/to/llvm-project
+ $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
+
+#. Check out lld::
+
+ $ cd llvm/tools
+ $ svn co http://llvm.org/svn/llvm-project/lld/trunk lld
+
+ * lld can also be checked out to ``path/to/llvm-project`` and built as an external
+ project.
+
+#. Generate Visual Studio project files::
+
+ $ cd path/to/llvm-build/llvm (out of source build required)
+ $ cmake -G "Visual Studio 11" path/to/llvm-project/llvm
+
+#. Build
+
+ * Open LLVM.sln in Visual Studio.
+ * Build the ``ALL_BUILD`` target.
+
+#. Test
+
+ * Build the ``lld-test`` target.
+
+More Information
+~~~~~~~~~~~~~~~~
+
+For more information on using CMake see the `LLVM CMake guide`_.
+
+.. _LLVM CMake guide: http://llvm.org/docs/CMake.html
diff --git a/contrib/llvm/tools/lld/docs/hello.png b/contrib/llvm/tools/lld/docs/hello.png
new file mode 100644
index 000000000000..70df111f1abd
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/hello.png
Binary files differ
diff --git a/contrib/llvm/tools/lld/docs/index.rst b/contrib/llvm/tools/lld/docs/index.rst
new file mode 100644
index 000000000000..2821ce4d214e
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/index.rst
@@ -0,0 +1,178 @@
+LLD - The LLVM Linker
+=====================
+
+LLD is a linker from the LLVM project. That is a drop-in replacement
+for system linkers and runs much faster than them. It also provides
+features that are useful for toolchain developers.
+
+The linker supports ELF (Unix), PE/COFF (Windows), Mach-O (macOS) and
+WebAssembly in descending order of completeness. Internally, LLD consists of
+several different linkers. The ELF port is the one that will be described in
+this document. The PE/COFF port is complete, including
+Windows debug info (PDB) support. The WebAssembly port is still a work in
+progress (See :doc:`WebAssembly`). The Mach-O port is built based on a
+different architecture than the others. For the details about Mach-O, please
+read :doc:`AtomLLD`.
+
+Features
+--------
+
+- LLD is a drop-in replacement for the GNU linkers. That accepts the
+ same command line arguments and linker scripts as GNU.
+
+ We are currently working closely with the FreeBSD project to make
+ LLD default system linker in future versions of the operating
+ system, so we are serious about addressing compatibility issues. As
+ of February 2017, LLD is able to link the entire FreeBSD/amd64 base
+ system including the kernel. With a few work-in-progress patches it
+ can link approximately 95% of the ports collection on AMD64. For the
+ details, see `FreeBSD quarterly status report
+ <https://www.freebsd.org/news/status/report-2016-10-2016-12.html#Using-LLVM%27s-LLD-Linker-as-FreeBSD%27s-System-Linker>`_.
+
+- LLD is very fast. When you link a large program on a multicore
+ machine, you can expect that LLD runs more than twice as fast as GNU
+ gold linker. Your milage may vary, though.
+
+- It supports various CPUs/ABIs including x86-64, x86, x32, AArch64,
+ ARM, MIPS 32/64 big/little-endian, PowerPC, PowerPC 64 and AMDGPU.
+ Among these, x86-64 is the most well-supported target and have
+ reached production quality. AArch64 and MIPS seem decent too. x86
+ should be OK but not well tested yet. ARM support is being developed
+ actively.
+
+- It is always a cross-linker, meaning that it always supports all the
+ above targets however it was built. In fact, we don't provide a
+ build-time option to enable/disable each target. This should make it
+ easy to use our linker as part of a cross-compile toolchain.
+
+- You can embed LLD to your program to eliminate dependency to
+ external linkers. All you have to do is to construct object files
+ and command line arguments just like you would do to invoke an
+ external linker and then call the linker's main function,
+ ``lld::elf::link``, from your code.
+
+- It is small. We are using LLVM libObject library to read from object
+ files, so it is not completely a fair comparison, but as of February
+ 2017, LLD/ELF consists only of 21k lines of C++ code while GNU gold
+ consists of 198k lines of C++ code.
+
+- Link-time optimization (LTO) is supported by default. Essentially,
+ all you have to do to do LTO is to pass the ``-flto`` option to clang.
+ Then clang creates object files not in the native object file format
+ but in LLVM bitcode format. LLD reads bitcode object files, compile
+ them using LLVM and emit an output file. Because in this way LLD can
+ see the entire program, it can do the whole program optimization.
+
+- Some very old features for ancient Unix systems (pre-90s or even
+ before that) have been removed. Some default settings have been
+ tuned for the 21st century. For example, the stack is marked as
+ non-executable by default to tighten security.
+
+Performance
+-----------
+
+This is a link time comparison on a 2-socket 20-core 40-thread Xeon
+E5-2680 2.80 GHz machine with an SSD drive. We ran gold and lld with
+or without multi-threading support. To disable multi-threading, we
+added ``-no-threads`` to the command lines.
+
+============ =========== ============ ==================== ================== =============== =============
+Program Output size GNU ld GNU gold w/o threads GNU gold w/threads lld w/o threads lld w/threads
+ffmpeg dbg 92 MiB 1.72s 1.16s 1.01s 0.60s 0.35s
+mysqld dbg 154 MiB 8.50s 2.96s 2.68s 1.06s 0.68s
+clang dbg 1.67 GiB 104.03s 34.18s 23.49s 14.82s 5.28s
+chromium dbg 1.14 GiB 209.05s [1]_ 64.70s 60.82s 27.60s 16.70s
+============ =========== ============ ==================== ================== =============== =============
+
+As you can see, lld is significantly faster than GNU linkers.
+Note that this is just a benchmark result of our environment.
+Depending on number of available cores, available amount of memory or
+disk latency/throughput, your results may vary.
+
+.. [1] Since GNU ld doesn't support the ``-icf=all`` and
+ ``-gdb-index`` options, we removed them from the command line
+ for GNU ld. GNU ld would have been slower than this if it had
+ these options.
+
+Build
+-----
+
+If you have already checked out LLVM using SVN, you can check out LLD
+under ``tools`` directory just like you probably did for clang. For the
+details, see `Getting Started with the LLVM System
+<http://llvm.org/docs/GettingStarted.html>`_.
+
+If you haven't checkout out LLVM, the easiest way to build LLD is to
+checkout the entire LLVM projects/sub-projects from a git mirror and
+build that tree. You need `cmake` and of course a C++ compiler.
+
+.. code-block:: console
+
+ $ git clone https://github.com/llvm-project/llvm-project-20170507 llvm-project
+ $ mkdir build
+ $ cd build
+ $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-project/llvm
+ $ make install
+
+Using LLD
+---------
+
+LLD is installed as ``ld.lld``. On Unix, linkers are invoked by
+compiler drivers, so you are not expected to use that command
+directly. There are a few ways to tell compiler drivers to use ld.lld
+instead of the default linker.
+
+The easiest way to do that is to overwrite the default linker. After
+installing LLD to somewhere on your disk, you can create a symbolic
+link by doing ``ln -s /path/to/ld.lld /usr/bin/ld`` so that
+``/usr/bin/ld`` is resolved to LLD.
+
+If you don't want to change the system setting, you can use clang's
+``-fuse-ld`` option. In this way, you want to set ``-fuse-ld=lld`` to
+LDFLAGS when building your programs.
+
+LLD leaves its name and version number to a ``.comment`` section in an
+output. If you are in doubt whether you are successfully using LLD or
+not, run ``readelf --string-dump .comment <output-file>`` and examine the
+output. If the string "Linker: LLD" is included in the output, you are
+using LLD.
+
+History
+-------
+
+Here is a brief project history of the ELF and COFF ports.
+
+- May 2015: We decided to rewrite the COFF linker and did that.
+ Noticed that the new linker is much faster than the MSVC linker.
+
+- July 2015: The new ELF port was developed based on the COFF linker
+ architecture.
+
+- September 2015: The first patches to support MIPS and AArch64 landed.
+
+- October 2015: Succeeded to self-host the ELF port. We have noticed
+ that the linker was faster than the GNU linkers, but we weren't sure
+ at the time if we would be able to keep the gap as we would add more
+ features to the linker.
+
+- July 2016: Started working on improving the linker script support.
+
+- December 2016: Succeeded to build the entire FreeBSD base system
+ including the kernel. We had widen the performance gap against the
+ GNU linkers.
+
+Internals
+---------
+
+For the internals of the linker, please read :doc:`NewLLD`. It is a bit
+outdated but the fundamental concepts remain valid. We'll update the
+document soon.
+
+.. toctree::
+ :maxdepth: 1
+
+ NewLLD
+ AtomLLD
+ WebAssembly
+ windows_support
+ ReleaseNotes
diff --git a/contrib/llvm/tools/lld/docs/ld.lld.1 b/contrib/llvm/tools/lld/docs/ld.lld.1
new file mode 100644
index 000000000000..67591f2bbcac
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/ld.lld.1
@@ -0,0 +1,577 @@
+.\" This file is distributed under the University of Illinois Open Source
+.\" License. See LICENSE.TXT for details.
+.\"
+.\" This man page documents only lld's ELF linking support, obtained originally
+.\" from FreeBSD.
+.Dd August 22, 2018
+.Dt LD.LLD 1
+.Os
+.Sh NAME
+.Nm ld.lld
+.Nd ELF linker from the LLVM project
+.Sh SYNOPSIS
+.Nm ld.lld
+.Op Ar options
+.Ar objfile ...
+.Sh DESCRIPTION
+A linker takes one or more object, archive, and library files, and combines
+them into an output file (an executable, a shared library, or another object
+file).
+It relocates code and data from the input files and resolves symbol
+references between them.
+.Pp
+.Nm
+is a drop-in replacement for the GNU BFD and gold linkers.
+It accepts most of the same command line arguments and linker scripts
+as GNU linkers.
+.Pp
+Many options have both a single-letter and long form.
+When using the long form options other than those beginning with the
+letter
+.Cm o
+may be specified using either one or two dashes preceding the option name.
+Long options beginning with
+.Cm o
+require two dashes to avoid confusion with the
+.Fl o Ar path
+option.
+.Pp
+These options are available:
+.Bl -tag -width indent
+.It Fl -allow-multiple-definition
+Do not error if a symbol is defined multiple times.
+The first definition will be used.
+.It Fl -apply-dynamic-relocs
+Apply link-time values for dynamic relocations.
+.It Fl -as-needed
+Only set
+.Dv DT_NEEDED
+for shared libraries if used.
+.It Fl -auxiliary Ns = Ns Ar value
+Set the
+.Dv DT_AUXILIARY
+field to the specified name.
+.It Fl -Bdynamic , Fl -dy
+Link against shared libraries.
+.It Fl -Bstatic , Fl -static , Fl -dn
+Do not link against shared libraries.
+.It Fl -Bsymbolic
+Bind defined symbols locally.
+.It Fl -Bsymbolic-functions
+Bind defined function symbols locally.
+.It Fl -build-id Ns = Ns Ar value
+Generate a build ID note.
+.Ar value
+may be one of
+.Cm fast ,
+.Cm md5 ,
+.Cm sha1 ,
+.Cm tree ,
+.Cm uuid ,
+.Cm 0x Ns Ar hex-string ,
+and
+.Cm none .
+.Cm tree
+is an alias for
+.Cm sha1 .
+Build-IDs of type
+.Cm fast ,
+.Cm md5 ,
+.Cm sha1 ,
+and
+.Cm tree
+are calculated from the object contents.
+.Cm fast
+is not intended to be cryptographically secure.
+.It Fl -build-id
+Synonym for
+.Fl -build-id Ns = Ns Cm fast .
+.It Fl -color-diagnostics Ns = Ns Ar value
+Use colors in diagnostics.
+.Ar value
+may be one of
+.Cm always ,
+.Cm auto ,
+and
+.Cm never .
+.Cm auto
+enables color if and only if output is to a terminal.
+.It Fl -color-diagnostics
+Alias for
+.Fl -color-diagnostics Ns = Ns Cm auto .
+.It Fl -compress-debug-sections Ns = Ns Ar value
+Compress DWARF debug sections.
+.Ar value
+may be
+.Cm none
+or
+.Cm zlib .
+.It Fl -cref
+Output cross reference table.
+.It Fl -define-common , Fl d
+Assign space to common symbols.
+.It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression
+Define a symbol alias.
+.Ar expression
+may be another symbol or a linker script expression.
+For example,
+.Ql --defsym=foo=bar
+or
+.Ql --defsym=foo=bar+0x100 .
+.It Fl -demangle
+Demangle symbol names.
+.It Fl -disable-new-dtags
+Disable new dynamic tags.
+.It Fl -discard-all , Fl x
+Delete all local symbols.
+.It Fl -discard-locals , Fl X
+Delete temporary local symbols.
+.It Fl -discard-none
+Keep all symbols in the symbol table.
+.It Fl -dynamic-linker Ns = Ns Ar value
+Specify the dynamic linker to be used for a dynamically linked executable.
+This is recorded in an ELF segment of type
+.Dv PT_INTERP .
+.It Fl -dynamic-list Ns = Ns Ar file
+Read a list of dynamic symbols from
+.Ar file .
+.It Fl -eh-frame-hdr
+Request creation of
+.Li .eh_frame_hdr
+section and
+.Dv PT_GNU_EH_FRAME
+segment header.
+.It Fl -emit-relocs , Fl q
+Generate relocations in the output.
+.It Fl -enable-new-dtags
+Enable new dynamic tags.
+.It Fl -end-lib
+End a grouping of objects that should be treated as if they were together
+in an archive.
+.It Fl -entry Ns = Ns Ar entry
+Name of entry point symbol.
+.It Fl -error-limit Ns = Ns Ar value
+Maximum number of errors to emit before stopping.
+A value of zero indicates that there is no limit.
+.It Fl -error-unresolved-symbols
+Report unresolved symbols as errors.
+.It Fl -exclude-libs Ns = Ns Ar value
+Exclude static libraries from automatic export.
+.It Fl -export-dynamic , Fl E
+Put symbols in the dynamic symbol table.
+.It Fl -export-dynamic-symbol Ns = Ns Ar symbol
+Include
+.Ar symbol
+in the dynamic symbol table.
+.It Fl -fatal-warnings
+Treat warnings as errors.
+.It Fl -filter Ns = Ns Ar value , Fl F Ar value
+Set the
+.Dv DT_FILTER
+field to the specified value.
+.It Fl -fini Ns = Ns Ar symbol
+Specify a finalizer function.
+.It Fl -format Ns = Ns Ar input-format , Fl b Ar input-format
+Specify the format of the inputs following this option.
+.Ar input-format
+may be one of
+.Cm binary ,
+.Cm elf ,
+and
+.Cm default .
+.Cm default
+is a synonym for
+.Cm elf .
+.It Fl -gc-sections
+Enable garbage collection of unused sections.
+.It Fl -gdb-index
+Generate
+.Li .gdb_index
+section.
+.It Fl -hash-style Ns = Ns Ar value
+Specify hash style.
+.Ar value
+may be
+.Cm sysv ,
+.Cm gnu ,
+or
+.Cm both .
+.Cm both
+is the default.
+.It Fl -help
+Print a help message.
+.It Fl -icf Ns = Ns Cm all
+Enable identical code folding.
+.It Fl -icf Ns = Ns Cm safe
+Enable safe identical code folding.
+.It Fl -icf Ns = Ns Cm none
+Disable identical code folding.
+.It Fl -image-base Ns = Ns Ar value
+Set the base address to
+.Ar value .
+.It Fl -init Ns = Ns Ar symbol
+Specify an initializer function.
+.It Fl -keep-unique Ns = Ns Ar symbol
+Do not fold
+.Ar symbol
+during ICF.
+.It Fl l Ar libName, Fl -library Ns = Ns Ar libName
+Root name of library to use.
+.It Fl L Ar dir , Fl -library-path Ns = Ns Ar dir
+Add a directory to the library search path.
+.It Fl -lto-aa-pipeline Ns = Ns Ar value
+AA pipeline to run during LTO.
+Used in conjunction with
+.Fl -lto-newpm-passes .
+.It Fl -lto-newpm-passes Ns = Ns Ar value
+Passes to run during LTO.
+.It Fl -lto-O Ns Ar opt-level
+Optimization level for LTO.
+.It Fl -lto-partitions Ns = Ns Ar value
+Number of LTO codegen partitions.
+.It Fl m Ar value
+Set target emulation.
+.It Fl -Map Ns = Ns Ar file , Fl M Ar file
+Print a link map to
+.Ar file .
+.It Fl -no-as-needed
+Always set
+.Dv DT_NEEDED
+for shared libraries.
+.It Fl -no-color-diagnostics
+Do not use colors in diagnostics.
+.It Fl -no-define-common
+Do not assign space to common symbols.
+.It Fl -no-demangle
+Do not demangle symbol names.
+.It Fl -no-dynamic-linker
+Inhibit output of an
+.Li .interp
+section.
+.It Fl -no-gc-sections
+Disable garbage collection of unused sections.
+.It Fl -no-gnu-unique
+Disable STB_GNU_UNIQUE symbol binding.
+.It Fl -no-rosegment
+Do not put read-only non-executable sections in their own segment.
+.It Fl -no-threads
+Do not run the linker multi-threaded.
+.It Fl -no-undefined-version
+Report version scripts that refer undefined symbols.
+.It Fl -no-undefined
+Report unresolved symbols even if the linker is creating a shared library.
+.It Fl -no-whole-archive
+Restores the default behavior of loading archive members.
+.It Fl -no-pie
+Do not create a position independent executable.
+.It Fl -noinhibit-exec
+Retain the executable output file whenever it is still usable.
+.It Fl -nostdlib
+Only search directories specified on the command line.
+.It Fl o Ar path
+Write the output executable, library, or object to
+.Ar path .
+If not specified,
+.Dv a.out
+is used as a default.
+.It Fl O Ns Ar value
+Optimize output file size.
+.Ar value
+may be:
+.Pp
+.Bl -tag -width 2n -compact
+.It Cm 0
+Disable string merging.
+.It Cm 1
+Enable string merging.
+.It Cm 2
+Enable string tail merging.
+.El
+.Pp
+.Fl O Ns Cm 1
+is the default.
+.It Fl -oformat Ns = Ns Ar format
+Specify the format for the output object file.
+The only supported
+.Ar format
+is
+.Cm binary ,
+which produces output with no ELF header.
+.It Fl -omagic , Fl N
+Set the text and data sections to be readable and writable.
+.It Fl -opt-remarks-filename Ar file
+Write optimization remarks in YAML format to
+.Ar file .
+.It Fl -opt-remarks-with-hotness
+Include hotness information in the optimization remarks file.
+.It Fl -pie
+Create a position independent executable.
+.It Fl -print-gc-sections
+List removed unused sections.
+.It Fl -print-map
+Print a link map to the standard output.
+.It Fl -push-state
+Save the current state of
+.Fl -as-needed ,
+.Fl -static ,
+and
+.Fl -while-archive.
+.It Fl -pop-state
+Undo the effect of
+.Fl -push-state.
+.It Fl -relocatable , Fl r
+Create relocatable object file.
+.It Fl -reproduce Ns = Ns Ar value
+Dump linker invocation and input files for debugging.
+.It Fl -retain-symbols-file Ns = Ns Ar file
+Retain only the symbols listed in the file.
+.It Fl -rpath Ns = Ns Ar value , Fl R Ar value
+Add a
+.Dv DT_RUNPATH
+to the output.
+.It Fl -rsp-quoting Ns = Ns Ar value
+Quoting style for response files.
+The supported values are
+.Cm windows
+and
+.Cm posix .
+.It Fl -script Ns = Ns Ar file , Fl T Ar file
+Read linker script from
+.Ar file .
+.It Fl -section-start Ns = Ns Ar section Ns = Ns Ar address
+Set address of section.
+.It Fl -shared , Fl -Bsharable
+Build a shared object.
+.It Fl -soname Ns = Ns Ar value , Fl h Ar value
+Set
+.Dv DT_SONAME
+to
+.Ar value .
+.It Fl -sort-section Ns = Ns Ar value
+Specifies sections sorting rule when linkerscript is used.
+.It Fl -start-lib
+Start a grouping of objects that should be treated as if they were together
+in an archive.
+.It Fl -strip-all , Fl s
+Strip all symbols.
+.It Fl -strip-debug , Fl S
+Strip debugging information.
+.It Fl -symbol-ordering-file Ns = Ns Ar file
+Lay out sections in the order specified by
+.Ar file .
+.It Fl -sysroot Ns = Ns Ar value
+Set the system root.
+.It Fl -target1-abs
+Interpret
+.Dv R_ARM_TARGET1
+as
+.Dv R_ARM_ABS32 .
+.It Fl -target1-rel
+Interpret
+.Dv R_ARM_TARGET1
+as
+.Dv R_ARM_REL32 .
+.It Fl -target2 Ns = Ns Ar type
+Interpret
+.Dv R_ARM_TARGET2
+as
+.Ar type ,
+where
+.Ar type
+is one of
+.Cm rel ,
+.Cm abs ,
+or
+.Cm got-rel .
+.It Fl -Tbss Ns = Ns Ar value
+Same as
+.Fl -section-start
+with
+.Li .bss
+as the sectionname.
+.It Fl -Tdata Ns = Ns Ar value
+Same as
+.Fl -section-start
+with
+.Li .data
+as the sectionname.
+.It Fl -Ttext Ns = Ns Ar value
+Same as
+.Fl -section-start
+with
+.Li .text
+as the sectionname.
+.It Fl -thinlto-cache-dir Ns = Ns Ar value
+Path to ThinLTO cached object file directory.
+.It Fl -thinlto-cache-policy Ns = Ns Ar value
+Pruning policy for the ThinLTO cache.
+.It Fl -thinlto-jobs Ns = Ns Ar value
+Number of ThinLTO jobs.
+.It Fl -threads
+Run the linker multi-threaded.
+This option is enabled by default.
+.It Fl -trace
+Print the names of the input files.
+.It Fl -trace-symbol Ns = Ns Ar symbol , Fl y Ar symbol
+Trace references to
+.Ar symbol .
+.It Fl -undefined Ns = Ns Ar symbol , Fl u Ar symbol
+Force
+.Ar symbol
+to be an undefined symbol during linking.
+.It Fl -unresolved-symbols Ns = Ns Ar value
+Determine how to handle unresolved symbols.
+.It Fl v
+Display the version number and proceed with linking if object files are
+specified.
+.It Fl V , Fl -version
+Display the version number and exit.
+.It Fl -verbose
+Verbose mode.
+.It Fl -version-script Ns = Ns Ar file
+Read version script from
+.Ar file .
+.It Fl -warn-backrefs
+Warn about reverse or cyclic dependencies to or between static archives.
+This can be used to ensure linker invocation remains compatible with
+traditional Unix-like linkers.
+.It Fl -warn-common
+Warn about duplicate common symbols.
+.It Fl -warn-unresolved-symbols
+Report unresolved symbols as warnings.
+.It Fl -whole-archive
+Force load of all members in a static library.
+.It Fl -wrap Ns = Ns Ar symbol
+Use wrapper functions for symbol.
+.It Fl z Ar option
+Linker option extensions.
+.Bl -tag -width indent
+.It Cm execstack
+Make the main stack executable.
+Stack permissions are recorded in the
+.Dv PT_GNU_STACK
+segment.
+.It Cm ifunc-noplt
+Do not emit PLT entries for GNU ifuncs.
+Instead, preserve relocations for ifunc call sites so that they may
+be applied by a run-time loader.
+Note that this feature requires special loader support and will
+generally result in application crashes when used outside of freestanding
+environments.
+.It Cm initfirst
+Sets the
+.Dv DF_1_INITFIRST
+flag to indicate the module should be initialized first.
+.It Cm muldefs
+Do not error if a symbol is defined multiple times.
+The first definition will be used.
+This is a synonym for
+.Fl -allow-multiple-definition.
+.It Cm nocombreloc
+Disable combining and sorting multiple relocation sections.
+.It Cm nocopyreloc
+Disable the creation of copy relocations.
+.It Cm nodelete
+Set the
+.Dv DF_1_NODELETE
+flag to indicate that the object cannot be unloaded from a process.
+.It Cm nodlopen
+Set the
+.Dv DF_1_NOOPEN
+flag to indcate that the object may not be opened by
+.Xr dlopen 3 .
+.It Cm norelro
+Do not indicate that portions of the object shold be mapped read-only
+after initial relocation processing.
+The object will omit the
+.Dv PT_GNU_RELRO
+segment.
+.It Cm notext
+Allow relocations against read-only segments.
+Sets the
+.Dv DT_TEXTREL flag in the
+.Dv DYNAMIC
+section.
+.It Cm now
+Set the
+.Dv DF_BIND_NOW
+flag to indicate that the run-time loader should perform all relocation
+processing as part of object initialization.
+By default relocations may be performed on demand.
+.It Cm origin
+Set the
+.Dv DF_ORIGIN
+flag to indicate that the object requires
+$ORIGIN
+processing.
+.It Cm retpolineplt
+Emit retpoline format PLT entries as a mitigation for CVE-2017-5715.
+.It Cm rodynamic
+Make the
+.Li .dynamic
+section read-only.
+The
+.Dv DT_DEBUG
+tag will not be emitted.
+.It Cm stack-size Ns = Ns Ar size
+Set the main thread's stack size to
+.Ar size .
+The stack size is recorded as the size of the
+.Ar size .
+.Dv PT_GNU_STACK
+program segment.
+.It Cm text
+Do not allow relocations against read-only segments.
+This is the default.
+.It Cm wxneeded
+Create a
+.Dv PT_OPENBSD_WXNEEDED
+segment.
+.El
+.El
+.Sh IMPLEMENTATION NOTES
+.Nm Ap s
+handing of archive files (those with a
+.Pa .a
+file extension) is different from traditional linkers used on Unix-like
+systems.
+.Pp
+Traditional linkers maintain a set of undefined symbols during linking.
+The linker processes each file in the order in which it appears on the
+command line, until the set of undefined symbols becomes empty.
+An object file is linked into the output object when it is encountered,
+with its undefined symbols added to the set.
+Upon encountering an archive file a traditional linker searches the objects
+contained therein, and processes those that satisfy symbols in the unresolved
+set.
+.Pp
+Handling mutually dependent archives may be awkward when using a traditional
+linker.
+Archive files may have to be specified multiple times, or the special command
+line options
+.Fl -start-group
+and
+.Fl -end-group
+may be used to have the linker loop over the files in the group until no new
+symbols are added to the set.
+.Pp
+.Nm
+records all symbols found in objects and archives as it iterates over
+command line arguments.
+When
+.Nm
+encounters an undefined symbol that can be resolved by an object file
+contained in a previously processed archive file, it immediately extracts
+and links it into the output object.
+.Pp
+With certain archive inputs
+.Nm
+may produce different results compared to traditional linkers.
+In practice, large bodies of third party software have been linked with
+.Nm
+without material issues.
+.Pp
+The
+.Fl -warn-backrefs
+option may be used to identify a linker invocation that may be incompatible
+with traditional Unix-like linker behavior.
diff --git a/contrib/llvm/tools/lld/docs/llvm-theme/layout.html b/contrib/llvm/tools/lld/docs/llvm-theme/layout.html
new file mode 100644
index 000000000000..0cd0918eac2a
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/llvm-theme/layout.html
@@ -0,0 +1,22 @@
+{#
+ sphinxdoc/layout.html
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the sphinxdoc theme.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{% extends "basic/layout.html" %}
+
+{% block relbar1 %}
+<div class="logo">
+<a href="{{ pathto('index') }}"><img src="{{
+pathto("_static/logo.png", 1) }}" alt="LLVM Documentation"/></a>
+</div>
+{{ super() }}
+{% endblock %}
+
+{# put the sidebar before the body #}
+{% block sidebar1 %}{{ sidebar() }}{% endblock %}
+{% block sidebar2 %}{% endblock %}
diff --git a/contrib/llvm/tools/lld/docs/llvm-theme/static/contents.png b/contrib/llvm/tools/lld/docs/llvm-theme/static/contents.png
new file mode 100644
index 000000000000..7fb82154a174
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/llvm-theme/static/contents.png
Binary files differ
diff --git a/contrib/llvm/tools/lld/docs/llvm-theme/static/llvm.css b/contrib/llvm/tools/lld/docs/llvm-theme/static/llvm.css
new file mode 100644
index 000000000000..32802bb6a2d0
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/llvm-theme/static/llvm.css
@@ -0,0 +1,345 @@
+/*
+ * sphinxdoc.css_t
+ * ~~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- sphinxdoc theme. Originally created by
+ * Armin Ronacher for Werkzeug.
+ *
+ * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+ font-size: 14px;
+ letter-spacing: -0.01em;
+ line-height: 150%;
+ text-align: center;
+ background-color: #BFD1D4;
+ color: black;
+ padding: 0;
+ border: 1px solid #aaa;
+
+ margin: 0px 80px 0px 80px;
+ min-width: 740px;
+}
+
+div.logo {
+ background-color: white;
+ text-align: left;
+ padding: 10px 10px 15px 15px;
+}
+
+div.document {
+ background-color: white;
+ text-align: left;
+ background-image: url(contents.png);
+ background-repeat: repeat-x;
+}
+
+div.bodywrapper {
+ margin: 0 240px 0 0;
+ border-right: 1px solid #ccc;
+}
+
+div.body {
+ margin: 0;
+ padding: 0.5em 20px 20px 20px;
+}
+
+div.related {
+ font-size: 1em;
+}
+
+div.related ul {
+ background-image: url(navigation.png);
+ height: 2em;
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+}
+
+div.related ul li {
+ margin: 0;
+ padding: 0;
+ height: 2em;
+ float: left;
+}
+
+div.related ul li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+div.related ul li a {
+ margin: 0;
+ padding: 0 5px 0 5px;
+ line-height: 1.75em;
+ color: #EE9816;
+}
+
+div.related ul li a:hover {
+ color: #3CA8E7;
+}
+
+div.sphinxsidebarwrapper {
+ padding: 0;
+}
+
+div.sphinxsidebar {
+ margin: 0;
+ padding: 0.5em 15px 15px 0;
+ width: 210px;
+ float: right;
+ font-size: 1em;
+ text-align: left;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+ margin: 1em 0 0.5em 0;
+ font-size: 1em;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: white;
+ border: 1px solid #86989B;
+ background-color: #AFC1C4;
+}
+
+div.sphinxsidebar h3 a {
+ color: white;
+}
+
+div.sphinxsidebar ul {
+ padding-left: 1.5em;
+ margin-top: 7px;
+ padding: 0;
+ line-height: 130%;
+}
+
+div.sphinxsidebar ul ul {
+ margin-left: 20px;
+}
+
+div.footer {
+ background-color: #E3EFF1;
+ color: #86989B;
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-size: 0.8em;
+ text-align: right;
+}
+
+div.footer a {
+ color: #86989B;
+ text-decoration: underline;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+p {
+ margin: 0.8em 0 0.5em 0;
+}
+
+a {
+ color: #CA7900;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #2491CF;
+}
+
+div.body a {
+ text-decoration: underline;
+}
+
+h1 {
+ margin: 0;
+ padding: 0.7em 0 0.3em 0;
+ font-size: 1.5em;
+ color: #11557C;
+}
+
+h2 {
+ margin: 1.3em 0 0.2em 0;
+ font-size: 1.35em;
+ padding: 0;
+}
+
+h3 {
+ margin: 1em 0 -0.3em 0;
+ font-size: 1.2em;
+}
+
+div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
+ color: black!important;
+}
+
+h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
+ display: none;
+ margin: 0 0 0 0.3em;
+ padding: 0 0.2em 0 0.2em;
+ color: #aaa!important;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+ display: inline;
+}
+
+h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
+h5 a.anchor:hover, h6 a.anchor:hover {
+ color: #777;
+ background-color: #eee;
+}
+
+a.headerlink {
+ color: #c60f0f!important;
+ font-size: 1em;
+ margin-left: 6px;
+ padding: 0 4px 0 4px;
+ text-decoration: none!important;
+}
+
+a.headerlink:hover {
+ background-color: #ccc;
+ color: white!important;
+}
+
+cite, code, tt {
+ font-family: 'Consolas', 'Deja Vu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.95em;
+ letter-spacing: 0.01em;
+}
+
+tt {
+ background-color: #f2f2f2;
+ border-bottom: 1px solid #ddd;
+ color: #333;
+}
+
+tt.descname, tt.descclassname, tt.xref {
+ border: 0;
+}
+
+hr {
+ border: 1px solid #abc;
+ margin: 2em;
+}
+
+a tt {
+ border: 0;
+ color: #CA7900;
+}
+
+a tt:hover {
+ color: #2491CF;
+}
+
+pre {
+ font-family: 'Consolas', 'Deja Vu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.95em;
+ letter-spacing: 0.015em;
+ line-height: 120%;
+ padding: 0.5em;
+ border: 1px solid #ccc;
+ background-color: #f8f8f8;
+}
+
+pre a {
+ color: inherit;
+ text-decoration: underline;
+}
+
+td.linenos pre {
+ padding: 0.5em 0;
+}
+
+div.quotebar {
+ background-color: #f8f8f8;
+ max-width: 250px;
+ float: right;
+ padding: 2px 7px;
+ border: 1px solid #ccc;
+}
+
+div.topic {
+ background-color: #f8f8f8;
+}
+
+table {
+ border-collapse: collapse;
+ margin: 0 -0.5em 0 -0.5em;
+}
+
+table td, table th {
+ padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+div.admonition, div.warning {
+ font-size: 0.9em;
+ margin: 1em 0 1em 0;
+ border: 1px solid #86989B;
+ background-color: #f7f7f7;
+ padding: 0;
+}
+
+div.admonition p, div.warning p {
+ margin: 0.5em 1em 0.5em 1em;
+ padding: 0;
+}
+
+div.admonition pre, div.warning pre {
+ margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+ margin: 0;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: white;
+ border-bottom: 1px solid #86989B;
+ font-weight: bold;
+ background-color: #AFC1C4;
+}
+
+div.warning {
+ border: 1px solid #940000;
+}
+
+div.warning p.admonition-title {
+ background-color: #CF0000;
+ border-bottom-color: #940000;
+}
+
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+ margin: 0.1em 0.5em 0.5em 3em;
+ padding: 0;
+}
+
+div.versioninfo {
+ margin: 1em 0 0 0;
+ border: 1px solid #ccc;
+ background-color: #DDEAF0;
+ padding: 8px;
+ line-height: 1.3em;
+ font-size: 0.9em;
+}
+
+.viewcode-back {
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/contrib/llvm/tools/lld/docs/llvm-theme/static/logo.png b/contrib/llvm/tools/lld/docs/llvm-theme/static/logo.png
new file mode 100644
index 000000000000..4fc899028dc6
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/llvm-theme/static/logo.png
Binary files differ
diff --git a/contrib/llvm/tools/lld/docs/llvm-theme/static/navigation.png b/contrib/llvm/tools/lld/docs/llvm-theme/static/navigation.png
new file mode 100644
index 000000000000..1081dc1439fb
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/llvm-theme/static/navigation.png
Binary files differ
diff --git a/contrib/llvm/tools/lld/docs/llvm-theme/theme.conf b/contrib/llvm/tools/lld/docs/llvm-theme/theme.conf
new file mode 100644
index 000000000000..330fc92ffa18
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/llvm-theme/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = llvm.css
+pygments_style = friendly
diff --git a/contrib/llvm/tools/lld/docs/make.bat b/contrib/llvm/tools/lld/docs/make.bat
new file mode 100644
index 000000000000..8471252d709f
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/make.bat
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\lld.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\lld.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
diff --git a/contrib/llvm/tools/lld/docs/open_projects.rst b/contrib/llvm/tools/lld/docs/open_projects.rst
new file mode 100644
index 000000000000..eeb9f9f48f34
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/open_projects.rst
@@ -0,0 +1,11 @@
+.. _open_projects:
+
+Open Projects
+=============
+
+.. include:: ../include/lld/Core/TODO.txt
+
+Documentation TODOs
+~~~~~~~~~~~~~~~~~~~
+
+.. todolist::
diff --git a/contrib/llvm/tools/lld/docs/sphinx_intro.rst b/contrib/llvm/tools/lld/docs/sphinx_intro.rst
new file mode 100644
index 000000000000..6bb9816b5ab4
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/sphinx_intro.rst
@@ -0,0 +1,127 @@
+.. _sphinx_intro:
+
+Sphinx Introduction for LLVM Developers
+=======================================
+
+This document is intended as a short and simple introduction to the Sphinx
+documentation generation system for LLVM developers.
+
+Quickstart
+----------
+
+To get started writing documentation, you will need to:
+
+ 1. Have the Sphinx tools :ref:`installed <installing_sphinx>`.
+
+ 2. Understand how to :ref:`build the documentation
+ <building_the_documentation>`.
+
+ 3. Start :ref:`writing documentation <writing_documentation>`!
+
+.. _installing_sphinx:
+
+Installing Sphinx
+~~~~~~~~~~~~~~~~~
+
+You should be able to install Sphinx using the standard Python package
+installation tool ``easy_install``, as follows::
+
+ $ sudo easy_install sphinx
+ Searching for sphinx
+ Reading http://pypi.python.org/simple/sphinx/
+ Reading http://sphinx.pocoo.org/
+ Best match: Sphinx 1.1.3
+ ... more lines here ..
+
+If you do not have root access (or otherwise want to avoid installing Sphinx in
+system directories) see the section on :ref:`installing_sphinx_in_a_venv` .
+
+If you do not have the ``easy_install`` tool on your system, you should be able
+to install it using:
+
+ Linux
+ Use your distribution's standard package management tool to install it,
+ i.e., ``apt-get install easy_install`` or ``yum install easy_install``.
+
+ Mac OS X
+ All modern Mac OS X systems come with ``easy_install`` as part of the base
+ system.
+
+ Windows
+ See the `setuptools <http://pypi.python.org/pypi/setuptools>`_ package web
+ page for instructions.
+
+
+.. _building_the_documentation:
+
+Building the documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to build the documentation need to add ``-DLLVM_ENABLE_SPHINX=ON`` to
+your ``cmake`` command. Once you do this you can build the docs using
+``docs-lld-html`` build (``ninja`` or ``make``) target.
+
+That build target will invoke ``sphinx-build`` with the appropriate options for
+the project, and generate the HTML documentation in a ``tools/lld/docs/html``
+subdirectory.
+
+.. _writing_documentation:
+
+Writing documentation
+~~~~~~~~~~~~~~~~~~~~~
+
+The documentation itself is written in the reStructuredText (ReST) format, and
+Sphinx defines additional tags to support features like cross-referencing.
+
+The ReST format itself is organized around documents mostly being readable
+plaintext documents. You should generally be able to write new documentation
+easily just by following the style of the existing documentation.
+
+If you want to understand the formatting of the documents more, the best place
+to start is Sphinx's own `ReST Primer <http://sphinx.pocoo.org/rest.html>`_.
+
+
+Learning More
+-------------
+
+If you want to learn more about the Sphinx system, the best place to start is
+the Sphinx documentation itself, available `here
+<http://sphinx.pocoo.org/contents.html>`_.
+
+
+.. _installing_sphinx_in_a_venv:
+
+Installing Sphinx in a Virtual Environment
+------------------------------------------
+
+Most Python developers prefer to work with tools inside a *virtualenv* (virtual
+environment) instance, which functions as an application sandbox. This avoids
+polluting your system installation with different packages used by various
+projects (and ensures that dependencies for different packages don't conflict
+with one another). Of course, you need to first have the virtualenv software
+itself which generally would be installed at the system level::
+
+ $ sudo easy_install virtualenv
+
+but after that you no longer need to install additional packages in the system
+directories.
+
+Once you have the *virtualenv* tool itself installed, you can create a
+virtualenv for Sphinx using::
+
+ $ virtualenv ~/my-sphinx-install
+ New python executable in /Users/dummy/my-sphinx-install/bin/python
+ Installing setuptools............done.
+ Installing pip...............done.
+
+ $ ~/my-sphinx-install/bin/easy_install sphinx
+ ... install messages here ...
+
+and from now on you can "activate" the *virtualenv* using::
+
+ $ source ~/my-sphinx-install/bin/activate
+
+which will change your PATH to ensure the sphinx-build tool from inside the
+virtual environment will be used. See the `virtualenv website
+<http://www.virtualenv.org/en/latest/index.html>`_ for more information on using
+virtual environments.
diff --git a/contrib/llvm/tools/lld/docs/windows_support.rst b/contrib/llvm/tools/lld/docs/windows_support.rst
new file mode 100644
index 000000000000..a0a2c4d9f1bc
--- /dev/null
+++ b/contrib/llvm/tools/lld/docs/windows_support.rst
@@ -0,0 +1,97 @@
+.. raw:: html
+
+ <style type="text/css">
+ .none { background-color: #FFCCCC }
+ .partial { background-color: #FFFF99 }
+ .good { background-color: #CCFF99 }
+ </style>
+
+.. role:: none
+.. role:: partial
+.. role:: good
+
+===============
+Windows support
+===============
+
+LLD supports Windows operating system. When invoked as ``lld-link.exe`` or with
+``-flavor link``, the driver for Windows operating system is used to parse
+command line options, and it drives further linking processes. LLD accepts
+almost all command line options that the linker shipped with Microsoft Visual
+C++ (link.exe) supports.
+
+The current status is that LLD can link itself on Windows x86/x64
+using Visual C++ 2013 as the compiler.
+
+Development status
+==================
+
+Driver
+ :good:`Mostly done`. Some exotic command line options that are not usually
+ used for application develompent, such as ``/DRIVER``, are not supported.
+
+Linking against DLL
+ :good:`Done`. LLD can read import libraries needed to link against DLL. Both
+ export-by-name and export-by-ordinal are supported.
+
+Linking against static library
+ :good:`Done`. The format of static library (.lib) on Windows is actually the
+ same as on Unix (.a). LLD can read it.
+
+Creating DLL
+ :good:`Done`. LLD creates a DLL if ``/DLL`` option is given. Exported
+ functions can be specified either via command line (``/EXPORT``) or via
+ module-definition file (.def). Both export-by-name and export-by-ordinal are
+ supported.
+
+Windows resource files support
+ :good:`Done`. If an ``.res`` file is given, LLD converts the file to a COFF
+ file using LLVM's Object library.
+
+Safe Structured Exception Handler (SEH)
+ :good:`Done` for both x86 and x64.
+
+Module-definition file
+ :partial:`Partially done`. LLD currently recognizes these directives:
+ ``EXPORTS``, ``HEAPSIZE``, ``STACKSIZE``, ``NAME``, and ``VERSION``.
+
+Debug info
+ :good:`Done`. LLD can emit PDBs that are at parity with those generated by
+ link.exe. However, LLD does not support /DEBUG:FASTLINK.
+
+
+Downloading LLD
+===============
+
+The Windows version of LLD is included in the `pre-built binaries of LLVM's
+releases <https://releases.llvm.org/download.html>`_ and in the `LLVM Snapshot
+Builds <https://llvm.org/builds/>`_.
+
+Building LLD
+============
+
+Using Visual Studio IDE/MSBuild
+-------------------------------
+
+1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror),
+#. run ``cmake -G "Visual Studio 12" <llvm-source-dir>`` from VS command prompt,
+#. open LLVM.sln with Visual Studio, and
+#. build ``lld`` target in ``lld executables`` folder
+
+Alternatively, you can use msbuild if you don't like to work in an IDE::
+
+ msbuild LLVM.sln /m /target:"lld executables\lld"
+
+MSBuild.exe had been shipped as a component of the .NET framework, but since
+2013 it's part of Visual Studio. You can find it at "C:\\Program Files
+(x86)\\msbuild".
+
+You can build LLD as a 64 bit application. To do that, open VS2013 x64 command
+prompt and run cmake for "Visual Studio 12 Win64" target.
+
+Using Ninja
+-----------
+
+1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror),
+#. run ``cmake -G ninja <llvm-source-dir>`` from VS command prompt,
+#. run ``ninja lld``
diff --git a/contrib/llvm/tools/lld/include/lld/Common/Driver.h b/contrib/llvm/tools/lld/include/lld/Common/Driver.h
index 15ec3cd44cb5..f6d92933af62 100644
--- a/contrib/llvm/tools/lld/include/lld/Common/Driver.h
+++ b/contrib/llvm/tools/lld/include/lld/Common/Driver.h
@@ -30,7 +30,7 @@ bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
}
namespace mach_o {
-bool link(llvm::ArrayRef<const char *> Args,
+bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
llvm::raw_ostream &Diag = llvm::errs());
}
diff --git a/contrib/llvm/tools/lld/include/lld/Common/ErrorHandler.h b/contrib/llvm/tools/lld/include/lld/Common/ErrorHandler.h
index 8ae6f46ac59e..f17f7cc99035 100644
--- a/contrib/llvm/tools/lld/include/lld/Common/ErrorHandler.h
+++ b/contrib/llvm/tools/lld/include/lld/Common/ErrorHandler.h
@@ -7,21 +7,62 @@
//
//===----------------------------------------------------------------------===//
//
-// In LLD, we have three levels of errors: fatal, error or warn.
+// We designed lld's error handlers with the following goals in mind:
//
-// Fatal makes the program exit immediately with an error message.
-// You shouldn't use it except for reporting a corrupted input file.
+// - Errors can occur at any place where we handle user input, but we don't
+// want them to affect the normal execution path too much. Ideally,
+// handling errors should be as simple as reporting them and exit (but
+// without actually doing exit).
//
-// Error prints out an error message and increment a global variable
-// ErrorCount to record the fact that we met an error condition. It does
-// not exit, so it is safe for a lld-as-a-library use case. It is generally
-// useful because it can report more than one error in a single run.
+// In particular, the design to wrap all functions that could fail with
+// ErrorOr<T> is rejected because otherwise we would have to wrap a large
+// number of functions in lld with ErrorOr. With that approach, if some
+// function F can fail, not only F but all functions that transitively call
+// F have to be wrapped with ErrorOr. That seemed too much.
//
-// Warn doesn't do anything but printing out a given message.
+// - Finding only one error at a time is not sufficient. We want to find as
+// many errors as possible with one execution of the linker. That means the
+// linker needs to keep running after a first error and give up at some
+// checkpoint (beyond which it would find cascading, false errors caused by
+// the previous errors).
//
-// It is not recommended to use llvm::outs() or llvm::errs() directly
-// in LLD because they are not thread-safe. The functions declared in
-// this file are mutually excluded, so you want to use them instead.
+// - We want a simple interface to report errors. Unlike Clang, the data we
+// handle is compiled binary, so we don't need an error reporting mechanism
+// that's as sophisticated as the one that Clang has.
+//
+// The current lld's error handling mechanism is simple:
+//
+// - When you find an error, report it using error() and continue as far as
+// you can. An internal error counter is incremented by one every time you
+// call error().
+//
+// A common idiom to handle an error is calling error() and then returning
+// a reasonable default value. For example, if your function handles a
+// user-supplied alignment value, and if you find an invalid alignment
+// (e.g. 17 which is not 2^n), you may report it using error() and continue
+// as if it were alignment 1 (which is the simplest reasonable value).
+//
+// Note that you should not continue with an invalid value; that breaks the
+// internal consistency. You need to maintain all variables have some sane
+// value even after an error occurred. So, when you have to continue with
+// some value, always use a dummy value.
+//
+// - Find a reasonable checkpoint at where you want to stop the linker, and
+// add code to return from the function if errorCount() > 0. In most cases,
+// a checkpoint already exists, so you don't need to do anything for this.
+//
+// This interface satisfies all the goals that we mentioned above.
+//
+// You should never call fatal() except for reporting a corrupted input file.
+// fatal() immediately terminates the linker, so the function is not desirable
+// if you are using lld as a subroutine in other program, and with that you
+// can find only one error at a time.
+//
+// warn() doesn't do anything but printing out a given message.
+//
+// It is not recommended to use llvm::outs() or llvm::errs() directly in lld
+// because they are not thread-safe. The functions declared in this file are
+// thread-safe.
//
//===----------------------------------------------------------------------===//
@@ -34,6 +75,10 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
+namespace llvm {
+class DiagnosticInfo;
+}
+
namespace lld {
class ErrorHandler {
@@ -74,6 +119,9 @@ inline uint64_t errorCount() { return errorHandler().ErrorCount; }
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
+void diagnosticHandler(const llvm::DiagnosticInfo &DI);
+void checkError(Error E);
+
// check functions are convenient functions to strip errors
// from error-or-value objects.
template <class T> T check(ErrorOr<T> E) {
diff --git a/contrib/llvm/tools/lld/include/lld/Common/Strings.h b/contrib/llvm/tools/lld/include/lld/Common/Strings.h
index 1a63f75f9ecf..e17b25763781 100644
--- a/contrib/llvm/tools/lld/include/lld/Common/Strings.h
+++ b/contrib/llvm/tools/lld/include/lld/Common/Strings.h
@@ -10,14 +10,40 @@
#ifndef LLD_STRINGS_H
#define LLD_STRINGS_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/GlobPattern.h"
#include <string>
+#include <vector>
namespace lld {
// Returns a demangled C++ symbol name. If Name is not a mangled
// name, it returns Optional::None.
llvm::Optional<std::string> demangleItanium(llvm::StringRef Name);
+llvm::Optional<std::string> demangleMSVC(llvm::StringRef S);
+
+std::vector<uint8_t> parseHex(llvm::StringRef S);
+bool isValidCIdentifier(llvm::StringRef S);
+
+// Write the contents of the a buffer to a file
+void saveBuffer(llvm::StringRef Buffer, const llvm::Twine &Path);
+
+// This class represents multiple glob patterns.
+class StringMatcher {
+public:
+ StringMatcher() = default;
+ explicit StringMatcher(llvm::ArrayRef<llvm::StringRef> Pat);
+
+ bool match(llvm::StringRef S) const;
+
+private:
+ std::vector<llvm::GlobPattern> Patterns;
+};
+
+inline llvm::ArrayRef<uint8_t> toArrayRef(llvm::StringRef S) {
+ return {reinterpret_cast<const uint8_t *>(S.data()), S.size()};
}
+} // namespace lld
#endif
diff --git a/contrib/llvm/tools/lld/include/lld/Common/TargetOptionsCommandFlags.h b/contrib/llvm/tools/lld/include/lld/Common/TargetOptionsCommandFlags.h
index 9c4ff7cea3fb..8443b184aa70 100644
--- a/contrib/llvm/tools/lld/include/lld/Common/TargetOptionsCommandFlags.h
+++ b/contrib/llvm/tools/lld/include/lld/Common/TargetOptionsCommandFlags.h
@@ -18,4 +18,5 @@
namespace lld {
llvm::TargetOptions InitTargetOptionsFromCodeGenFlags();
llvm::Optional<llvm::CodeModel::Model> GetCodeModelFromCMModel();
+std::string GetCPUStr();
}
diff --git a/contrib/llvm/tools/lld/include/lld/Common/Timer.h b/contrib/llvm/tools/lld/include/lld/Common/Timer.h
new file mode 100644
index 000000000000..6654af626919
--- /dev/null
+++ b/contrib/llvm/tools/lld/include/lld/Common/Timer.h
@@ -0,0 +1,59 @@
+//===- Timer.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COMMON_TIMER_H
+#define LLD_COMMON_TIMER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <assert.h>
+#include <chrono>
+#include <map>
+#include <memory>
+
+namespace lld {
+
+class Timer;
+
+struct ScopedTimer {
+ explicit ScopedTimer(Timer &T);
+
+ ~ScopedTimer();
+
+ void stop();
+
+ Timer *T = nullptr;
+};
+
+class Timer {
+public:
+ Timer(llvm::StringRef Name, Timer &Parent);
+
+ static Timer &root();
+
+ void start();
+ void stop();
+ void print();
+
+ double millis() const;
+
+private:
+ explicit Timer(llvm::StringRef Name);
+ void print(int Depth, double TotalDuration, bool Recurse = true) const;
+
+ std::chrono::time_point<std::chrono::high_resolution_clock> StartTime;
+ std::chrono::nanoseconds Total;
+ std::vector<Timer *> Children;
+ std::string Name;
+ Timer *Parent;
+};
+
+} // namespace lld
+
+#endif
diff --git a/contrib/llvm/tools/lld/include/lld/Common/Version.h b/contrib/llvm/tools/lld/include/lld/Common/Version.h
index 93de77df5804..23a10ed6dbf3 100644
--- a/contrib/llvm/tools/lld/include/lld/Common/Version.h
+++ b/contrib/llvm/tools/lld/include/lld/Common/Version.h
@@ -18,7 +18,7 @@
#include "llvm/ADT/StringRef.h"
namespace lld {
-/// \brief Retrieves a string representing the complete lld version.
+/// Retrieves a string representing the complete lld version.
std::string getLLDVersion();
}
diff --git a/contrib/llvm/tools/lld/include/lld/Core/DefinedAtom.h b/contrib/llvm/tools/lld/include/lld/Core/DefinedAtom.h
index 6229d67e25a5..ba10b45411f1 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/DefinedAtom.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/DefinedAtom.h
@@ -18,7 +18,7 @@
namespace lld {
class File;
-/// \brief The fundamental unit of linking.
+/// The fundamental unit of linking.
///
/// A C function or global variable is an atom. An atom has content and
/// attributes. The content of a function atom is the instructions that
@@ -179,10 +179,10 @@ public:
};
enum DynamicExport {
- /// \brief The linker may or may not export this atom dynamically depending
+ /// The linker may or may not export this atom dynamically depending
/// on the output type and other context of the link.
dynamicExportNormal,
- /// \brief The linker will always export this atom dynamically.
+ /// The linker will always export this atom dynamically.
dynamicExportAlways,
};
@@ -212,26 +212,26 @@ public:
}
};
- /// \brief returns a value for the order of this Atom within its file.
+ /// returns a value for the order of this Atom within its file.
///
/// This is used by the linker to order the layout of Atoms so that the
/// resulting image is stable and reproducible.
virtual uint64_t ordinal() const = 0;
- /// \brief the number of bytes of space this atom's content will occupy in the
+ /// the number of bytes of space this atom's content will occupy in the
/// final linked image.
///
/// For a function atom, it is the number of bytes of code in the function.
virtual uint64_t size() const = 0;
- /// \brief The size of the section from which the atom is instantiated.
+ /// The size of the section from which the atom is instantiated.
///
/// Merge::mergeByLargestSection is defined in terms of section size
/// and not in terms of atom size, so we need this function separate
/// from size().
virtual uint64_t sectionSize() const { return 0; }
- /// \brief The visibility of this atom to other atoms.
+ /// The visibility of this atom to other atoms.
///
/// C static functions have scope scopeTranslationUnit. Regular C functions
/// have scope scopeGlobal. Functions compiled with visibility=hidden have
@@ -239,48 +239,48 @@ public:
/// not by the OS loader.
virtual Scope scope() const = 0;
- /// \brief Whether the linker should use direct or indirect access to this
+ /// Whether the linker should use direct or indirect access to this
/// atom.
virtual Interposable interposable() const = 0;
- /// \brief how the linker should handle if multiple atoms have the same name.
+ /// how the linker should handle if multiple atoms have the same name.
virtual Merge merge() const = 0;
- /// \brief The type of this atom, such as code or data.
+ /// The type of this atom, such as code or data.
virtual ContentType contentType() const = 0;
- /// \brief The alignment constraints on how this atom must be laid out in the
+ /// The alignment constraints on how this atom must be laid out in the
/// final linked image (e.g. 16-byte aligned).
virtual Alignment alignment() const = 0;
- /// \brief Whether this atom must be in a specially named section in the final
+ /// Whether this atom must be in a specially named section in the final
/// linked image, or if the linker can infer the section based on the
/// contentType().
virtual SectionChoice sectionChoice() const = 0;
- /// \brief If sectionChoice() != sectionBasedOnContent, then this return the
+ /// If sectionChoice() != sectionBasedOnContent, then this return the
/// name of the section the atom should be placed into.
virtual StringRef customSectionName() const = 0;
- /// \brief constraints on whether the linker may dead strip away this atom.
+ /// constraints on whether the linker may dead strip away this atom.
virtual DeadStripKind deadStrip() const = 0;
- /// \brief Under which conditions should this atom be dynamically exported.
+ /// Under which conditions should this atom be dynamically exported.
virtual DynamicExport dynamicExport() const {
return dynamicExportNormal;
}
- /// \brief Code model used by the atom.
+ /// Code model used by the atom.
virtual CodeModel codeModel() const { return codeNA; }
- /// \brief Returns the OS memory protections required for this atom's content
+ /// Returns the OS memory protections required for this atom's content
/// at runtime.
///
/// A function atom is R_X, a global variable is RW_, and a read-only constant
/// is R__.
virtual ContentPermissions permissions() const;
- /// \brief returns a reference to the raw (unrelocated) bytes of this Atom's
+ /// returns a reference to the raw (unrelocated) bytes of this Atom's
/// content.
virtual ArrayRef<uint8_t> rawContent() const = 0;
@@ -317,10 +317,10 @@ public:
const void *_it;
};
- /// \brief Returns an iterator to the beginning of this Atom's References.
+ /// Returns an iterator to the beginning of this Atom's References.
virtual reference_iterator begin() const = 0;
- /// \brief Returns an iterator to the end of this Atom's References.
+ /// Returns an iterator to the end of this Atom's References.
virtual reference_iterator end() const = 0;
/// Adds a reference to this atom.
@@ -361,11 +361,11 @@ protected:
~DefinedAtom() override = default;
- /// \brief Returns a pointer to the Reference object that the abstract
+ /// Returns a pointer to the Reference object that the abstract
/// iterator "points" to.
virtual const Reference *derefIterator(const void *iter) const = 0;
- /// \brief Adjusts the abstract iterator to "point" to the next Reference
+ /// Adjusts the abstract iterator to "point" to the next Reference
/// object for this Atom.
virtual void incrementIterator(const void *&iter) const = 0;
};
diff --git a/contrib/llvm/tools/lld/include/lld/Core/File.h b/contrib/llvm/tools/lld/include/lld/Core/File.h
index 20418688dfa0..54f533576a4b 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/File.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/File.h
@@ -43,7 +43,7 @@ class File {
public:
virtual ~File();
- /// \brief Kinds of files that are supported.
+ /// Kinds of files that are supported.
enum Kind {
kindErrorObject, ///< a error object file (.o)
kindNormalizedObject, ///< a normalized file (.o)
@@ -59,7 +59,7 @@ public:
kindArchiveLibrary ///< archive (.a)
};
- /// \brief Returns file kind. Need for dyn_cast<> on File objects.
+ /// Returns file kind. Need for dyn_cast<> on File objects.
Kind kind() const {
return _kind;
}
@@ -114,10 +114,8 @@ public:
AtomRange(AtomVector<T> &v) : _v(v) {}
AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
- typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
- const T*> ConstDerefFn;
-
- typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
+ using ConstDerefFn = const T* (*)(const OwningAtomPtr<T>&);
+ using DerefFn = T* (*)(OwningAtomPtr<T>&);
typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
ConstDerefFn> ConstItTy;
@@ -174,19 +172,19 @@ public:
AtomVector<T> &_v;
};
- /// \brief Must be implemented to return the AtomVector object for
+ /// Must be implemented to return the AtomVector object for
/// all DefinedAtoms in this File.
virtual const AtomRange<DefinedAtom> defined() const = 0;
- /// \brief Must be implemented to return the AtomVector object for
+ /// Must be implemented to return the AtomVector object for
/// all UndefinedAtomw in this File.
virtual const AtomRange<UndefinedAtom> undefined() const = 0;
- /// \brief Must be implemented to return the AtomVector object for
+ /// Must be implemented to return the AtomVector object for
/// all SharedLibraryAtoms in this File.
virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
- /// \brief Must be implemented to return the AtomVector object for
+ /// Must be implemented to return the AtomVector object for
/// all AbsoluteAtoms in this File.
virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
@@ -196,7 +194,7 @@ public:
/// of a different file. We need to destruct all atoms before any files.
virtual void clearAtoms() = 0;
- /// \brief If a file is parsed using a different method than doParse(),
+ /// If a file is parsed using a different method than doParse(),
/// one must use this method to set the last error status, so that
/// doParse will not be called twice. Only YAML reader uses this
/// (because YAML reader does not read blobs but structured data).
@@ -214,12 +212,12 @@ public:
}
protected:
- /// \brief only subclasses of File can be instantiated
+ /// only subclasses of File can be instantiated
File(StringRef p, Kind kind)
: _path(p), _kind(kind), _ordinal(UINT64_MAX),
_nextAtomOrdinal(0) {}
- /// \brief Subclasses should override this method to parse the
+ /// Subclasses should override this method to parse the
/// memory buffer passed to this file's constructor.
virtual std::error_code doParse() { return std::error_code(); }
diff --git a/contrib/llvm/tools/lld/include/lld/Core/Instrumentation.h b/contrib/llvm/tools/lld/include/lld/Core/Instrumentation.h
index 162375905e17..939d64557587 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/Instrumentation.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/Instrumentation.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provide an Instrumentation API that optionally uses VTune interfaces.
+/// Provide an Instrumentation API that optionally uses VTune interfaces.
///
//===----------------------------------------------------------------------===//
@@ -24,7 +24,7 @@
namespace lld {
#ifdef LLD_HAS_VTUNE
-/// \brief A unique global scope for instrumentation data.
+/// A unique global scope for instrumentation data.
///
/// Domains last for the lifetime of the application and cannot be destroyed.
/// Multiple Domains created with the same name represent the same domain.
@@ -38,7 +38,7 @@ public:
__itt_domain *operator->() const { return _domain; }
};
-/// \brief A global reference to a string constant.
+/// A global reference to a string constant.
///
/// These are uniqued by the ITT runtime and cannot be deleted. They are not
/// specific to a domain.
@@ -54,7 +54,7 @@ public:
operator __itt_string_handle *() const { return _handle; }
};
-/// \brief A task on a single thread. Nests within other tasks.
+/// A task on a single thread. Nests within other tasks.
///
/// Each thread has its own task stack and tasks nest recursively on that stack.
/// A task cannot transfer threads.
@@ -68,7 +68,7 @@ class ScopedTask {
ScopedTask &operator=(const ScopedTask &) = delete;
public:
- /// \brief Create a task in Domain \p d named \p s.
+ /// Create a task in Domain \p d named \p s.
ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) {
__itt_task_begin(d, __itt_null, __itt_null, s);
}
@@ -83,7 +83,7 @@ public:
return *this;
}
- /// \brief Prematurely end this task.
+ /// Prematurely end this task.
void end() {
if (_domain)
__itt_task_end(_domain);
@@ -93,7 +93,7 @@ public:
~ScopedTask() { end(); }
};
-/// \brief A specific point in time. Allows metadata to be associated.
+/// A specific point in time. Allows metadata to be associated.
class Marker {
public:
Marker(const Domain &d, const StringHandle &s) {
diff --git a/contrib/llvm/tools/lld/include/lld/Core/LinkingContext.h b/contrib/llvm/tools/lld/include/lld/Core/LinkingContext.h
index eb9510cbd215..52ab1a2480e8 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/LinkingContext.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/LinkingContext.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <memory>
@@ -31,7 +30,7 @@ class Writer;
class Node;
class SharedLibraryFile;
-/// \brief The LinkingContext class encapsulates "what and how" to link.
+/// The LinkingContext class encapsulates "what and how" to link.
///
/// The base class LinkingContext contains the options needed by core linking.
/// Subclasses of LinkingContext have additional options needed by specific
@@ -167,10 +166,10 @@ public:
/// After all set* methods are called, the Driver calls this method
/// to validate that there are no missing options or invalid combinations
/// of options. If there is a problem, a description of the problem
- /// is written to the supplied stream.
+ /// is written to the global error handler.
///
/// \returns true if there is an error with the current settings.
- bool validate(raw_ostream &diagnostics);
+ bool validate();
/// Formats symbol name for use in error messages.
virtual std::string demangle(StringRef symbolName) const = 0;
@@ -250,7 +249,7 @@ protected:
private:
/// Validate the subclass bits. Only called by validate.
- virtual bool validateImpl(raw_ostream &diagnostics) = 0;
+ virtual bool validateImpl() = 0;
};
} // end namespace lld
diff --git a/contrib/llvm/tools/lld/include/lld/Core/PassManager.h b/contrib/llvm/tools/lld/include/lld/Core/PassManager.h
index 2ea65ae13ace..f2ef10f406f2 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/PassManager.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/PassManager.h
@@ -20,7 +20,7 @@ namespace lld {
class SimpleFile;
class Pass;
-/// \brief Owns and runs a collection of passes.
+/// Owns and runs a collection of passes.
///
/// This class is currently just a container for passes and a way to run them.
///
@@ -40,7 +40,7 @@ public:
}
private:
- /// \brief Passes in the order they should run.
+ /// Passes in the order they should run.
std::vector<std::unique_ptr<Pass>> _passes;
};
} // end namespace lld
diff --git a/contrib/llvm/tools/lld/include/lld/Core/Reader.h b/contrib/llvm/tools/lld/include/lld/Core/Reader.h
index c7baf86af61f..6cf6282ff39c 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/Reader.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/Reader.h
@@ -32,7 +32,7 @@ class File;
class LinkingContext;
class MachOLinkingContext;
-/// \brief An abstract class for reading object files, library files, and
+/// An abstract class for reading object files, library files, and
/// executable files.
///
/// Each file format (e.g. mach-o, etc) has a concrete subclass of Reader.
@@ -46,14 +46,14 @@ public:
/// 2) the whole file content buffer if the above is not enough.
virtual bool canParse(llvm::file_magic magic, MemoryBufferRef mb) const = 0;
- /// \brief Parse a supplied buffer (already filled with the contents of a
+ /// Parse a supplied buffer (already filled with the contents of a
/// file) and create a File object.
/// The resulting File object takes ownership of the MemoryBuffer.
virtual ErrorOr<std::unique_ptr<File>>
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &) const = 0;
};
-/// \brief An abstract class for handling alternate yaml representations
+/// An abstract class for handling alternate yaml representations
/// of object files.
///
/// The YAML syntax allows "tags" which are used to specify the type of
diff --git a/contrib/llvm/tools/lld/include/lld/Core/Resolver.h b/contrib/llvm/tools/lld/include/lld/Core/Resolver.h
index fb62a779c0a5..5157c9fddc1a 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/Resolver.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/Resolver.h
@@ -28,7 +28,7 @@ namespace lld {
class Atom;
class LinkingContext;
-/// \brief The Resolver is responsible for merging all input object files
+/// The Resolver is responsible for merging all input object files
/// and producing a merged graph.
class Resolver {
public:
@@ -50,7 +50,7 @@ public:
// Handle a shared library file.
llvm::Error handleSharedLibrary(File &);
- /// @brief do work of merging and resolving and return list
+ /// do work of merging and resolving and return list
bool resolve();
std::unique_ptr<SimpleFile> resultFile() { return std::move(_result); }
@@ -61,7 +61,7 @@ private:
bool undefinesAdded(int begin, int end);
File *getFile(int &index);
- /// \brief The main function that iterates over the files to resolve
+ /// The main function that iterates over the files to resolve
bool resolveUndefines();
void updateReferences();
void deadStripOptimize();
diff --git a/contrib/llvm/tools/lld/include/lld/Core/Simple.h b/contrib/llvm/tools/lld/include/lld/Core/Simple.h
index 3aa7abf5d12b..feeed6ae473b 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/Simple.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/Simple.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provide simple implementations for Atoms and File.
+/// Provide simple implementations for Atoms and File.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/lld/include/lld/Core/SymbolTable.h b/contrib/llvm/tools/lld/include/lld/Core/SymbolTable.h
index 9c39a6ed507c..156c56eafbf7 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/SymbolTable.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/SymbolTable.h
@@ -12,7 +12,7 @@
#include "lld/Common/LLVM.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/DJB.h"
#include <cstring>
#include <map>
#include <vector>
@@ -27,35 +27,35 @@ class ResolverOptions;
class SharedLibraryAtom;
class UndefinedAtom;
-/// \brief The SymbolTable class is responsible for coalescing atoms.
+/// The SymbolTable class is responsible for coalescing atoms.
///
/// All atoms coalescable by-name or by-content should be added.
/// The method replacement() can be used to find the replacement atom
/// if an atom has been coalesced away.
class SymbolTable {
public:
- /// @brief add atom to symbol table
+ /// add atom to symbol table
bool add(const DefinedAtom &);
- /// @brief add atom to symbol table
+ /// add atom to symbol table
bool add(const UndefinedAtom &);
- /// @brief add atom to symbol table
+ /// add atom to symbol table
bool add(const SharedLibraryAtom &);
- /// @brief add atom to symbol table
+ /// add atom to symbol table
bool add(const AbsoluteAtom &);
- /// @brief returns atom in symbol table for specified name (or nullptr)
+ /// returns atom in symbol table for specified name (or nullptr)
const Atom *findByName(StringRef sym);
- /// @brief returns vector of remaining UndefinedAtoms
+ /// returns vector of remaining UndefinedAtoms
std::vector<const UndefinedAtom *> undefines();
- /// @brief if atom has been coalesced away, return replacement, else return atom
+ /// if atom has been coalesced away, return replacement, else return atom
const Atom *replacement(const Atom *);
- /// @brief if atom has been coalesced away, return true
+ /// if atom has been coalesced away, return true
bool isCoalescedAway(const Atom *);
private:
@@ -65,7 +65,7 @@ private:
static StringRef getEmptyKey() { return StringRef(); }
static StringRef getTombstoneKey() { return StringRef(" ", 1); }
static unsigned getHashValue(StringRef const val) {
- return llvm::HashString(val);
+ return llvm::djbHash(val, 0);
}
static bool isEqual(StringRef const lhs, StringRef const rhs) {
return lhs.equals(rhs);
diff --git a/contrib/llvm/tools/lld/include/lld/Core/TODO.txt b/contrib/llvm/tools/lld/include/lld/Core/TODO.txt
index 8b523045de75..2aa61ff8612d 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/TODO.txt
+++ b/contrib/llvm/tools/lld/include/lld/Core/TODO.txt
@@ -6,9 +6,6 @@ include/lld/Core
abstraction only works for returning low level OS errors. It does not
work for describing formatting issues.
-* We need to design a diagnostics interface. It would be nice to share code
- with Clang_ where possible.
-
* We need to add more attributes to File. In particular, we need cpu
and OS information (like target triples). We should also provide explicit
support for `LLVM IR module flags metadata`__.
diff --git a/contrib/llvm/tools/lld/include/lld/Core/Writer.h b/contrib/llvm/tools/lld/include/lld/Core/Writer.h
index 1f0ca4cda41f..1cdfabefebd7 100644
--- a/contrib/llvm/tools/lld/include/lld/Core/Writer.h
+++ b/contrib/llvm/tools/lld/include/lld/Core/Writer.h
@@ -20,17 +20,17 @@ class File;
class LinkingContext;
class MachOLinkingContext;
-/// \brief The Writer is an abstract class for writing object files, shared
+/// The Writer is an abstract class for writing object files, shared
/// library files, and executable files. Each file format (e.g. mach-o, etc)
/// has a concrete subclass of Writer.
class Writer {
public:
virtual ~Writer();
- /// \brief Write a file from the supplied File object
+ /// Write a file from the supplied File object
virtual llvm::Error writeFile(const File &linkedFile, StringRef path) = 0;
- /// \brief This method is called by Core Linking to give the Writer a chance
+ /// This method is called by Core Linking to give the Writer a chance
/// to add file format specific "files" to set of files to be linked. This is
/// how file format specific atoms can be added to the link.
virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) {}
diff --git a/contrib/llvm/tools/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/contrib/llvm/tools/lld/include/lld/ReaderWriter/MachOLinkingContext.h
index 9eefa8c4d944..fde65880c3e3 100644
--- a/contrib/llvm/tools/lld/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/contrib/llvm/tools/lld/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -89,7 +89,7 @@ public:
bool exportDynamicSymbols);
void addPasses(PassManager &pm) override;
- bool validateImpl(raw_ostream &diagnostics) override;
+ bool validateImpl() override;
std::string demangle(StringRef symbolName) const override;
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
@@ -201,7 +201,7 @@ public:
uint32_t swiftVersion() const { return _swiftVersion; }
- /// \brief Checks whether a given path on the filesystem exists.
+ /// Checks whether a given path on the filesystem exists.
///
/// When running in -test_file_usage mode, this method consults an
/// internally maintained list of files that exist (provided by -path_exists)
@@ -211,7 +211,7 @@ public:
/// Like pathExists() but only used on files - not directories.
bool fileExists(StringRef path) const;
- /// \brief Adds any library search paths derived from the given base, possibly
+ /// Adds any library search paths derived from the given base, possibly
/// modified by -syslibroots.
///
/// The set of paths added consists of approximately all syslibroot-prepended
@@ -219,7 +219,7 @@ public:
/// for whatever reason. With various edge-cases for compatibility.
void addModifiedSearchDir(StringRef libPath, bool isSystemPath = false);
- /// \brief Determine whether -lFoo can be resolve within the given path, and
+ /// Determine whether -lFoo can be resolve within the given path, and
/// return the filename if so.
///
/// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
@@ -228,7 +228,7 @@ public:
llvm::Optional<StringRef> searchDirForLibrary(StringRef path,
StringRef libName) const;
- /// \brief Iterates through all search path entries looking for libName (as
+ /// Iterates through all search path entries looking for libName (as
/// specified by -lFoo).
llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
@@ -236,11 +236,11 @@ public:
/// the path with syslibroot.
void addFrameworkSearchDir(StringRef fwPath, bool isSystemPath = false);
- /// \brief Iterates through all framework directories looking for
+ /// Iterates through all framework directories looking for
/// Foo.framework/Foo (when fwName = "Foo").
llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
- /// \brief The dylib's binary compatibility version, in the raw uint32 format.
+ /// The dylib's binary compatibility version, in the raw uint32 format.
///
/// When building a dynamic library, this is the compatibility version that
/// gets embedded into the result. Other Mach-O binaries that link against
@@ -249,28 +249,28 @@ public:
/// installed dynamic library.
uint32_t compatibilityVersion() const { return _compatibilityVersion; }
- /// \brief The dylib's current version, in the the raw uint32 format.
+ /// The dylib's current version, in the the raw uint32 format.
///
/// When building a dynamic library, this is the current version that gets
/// embedded into the result. Other Mach-O binaries that link against
/// this library will store the compatibility version in its load command.
uint32_t currentVersion() const { return _currentVersion; }
- /// \brief The dylib's install name.
+ /// The dylib's install name.
///
/// Binaries that link against the dylib will embed this path into the dylib
/// load command. When loading the binaries at runtime, this is the location
/// on disk that the loader will look for the dylib.
StringRef installName() const { return _installName; }
- /// \brief Whether or not the dylib has side effects during initialization.
+ /// Whether or not the dylib has side effects during initialization.
///
/// Dylibs marked as being dead strippable provide the guarantee that loading
/// the dylib has no side effects, allowing the linker to strip out the dylib
/// when linking a binary that does not use any of its symbols.
bool deadStrippableDylib() const { return _deadStrippableDylib; }
- /// \brief Whether or not to use flat namespace.
+ /// Whether or not to use flat namespace.
///
/// MachO usually uses a two-level namespace, where each external symbol
/// referenced by the target is associated with the dylib that will provide
@@ -282,7 +282,7 @@ public:
/// loaded flat_namespace dylibs must be resolvable at build time.
bool useFlatNamespace() const { return _flatNamespace; }
- /// \brief How to handle undefined symbols.
+ /// How to handle undefined symbols.
///
/// Options are:
/// * error: Report an error and terminate linking.
@@ -294,7 +294,7 @@ public:
/// runtime.
UndefinedMode undefinedMode() const { return _undefinedMode; }
- /// \brief The path to the executable that will load the bundle at runtime.
+ /// The path to the executable that will load the bundle at runtime.
///
/// When building a Mach-O bundle, this executable will be examined if there
/// are undefined symbols after the main link phase. It is expected that this
@@ -331,7 +331,7 @@ public:
/// Add section alignment constraint on final layout.
void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
- /// \brief Add a section based on a command-line sectcreate option.
+ /// Add a section based on a command-line sectcreate option.
void addSectCreateSection(StringRef seg, StringRef sect,
std::unique_ptr<MemoryBuffer> content);
diff --git a/contrib/llvm/tools/lld/lib/Core/LinkingContext.cpp b/contrib/llvm/tools/lld/lib/Core/LinkingContext.cpp
index 5de863aa7f37..0f225c322122 100644
--- a/contrib/llvm/tools/lld/lib/Core/LinkingContext.cpp
+++ b/contrib/llvm/tools/lld/lib/Core/LinkingContext.cpp
@@ -20,8 +20,8 @@ LinkingContext::LinkingContext() = default;
LinkingContext::~LinkingContext() = default;
-bool LinkingContext::validate(raw_ostream &diagnostics) {
- return validateImpl(diagnostics);
+bool LinkingContext::validate() {
+ return validateImpl();
}
llvm::Error LinkingContext::writeFile(const File &linkedFile) const {
diff --git a/contrib/llvm/tools/lld/lib/Driver/CMakeLists.txt b/contrib/llvm/tools/lld/lib/Driver/CMakeLists.txt
index 097a8177ea1f..ff67c282f47e 100644
--- a/contrib/llvm/tools/lld/lib/Driver/CMakeLists.txt
+++ b/contrib/llvm/tools/lld/lib/Driver/CMakeLists.txt
@@ -13,6 +13,7 @@ add_lld_library(lldDriver
Support
LINK_LIBS
+ lldCommon
lldCore
lldMachO
lldReaderWriter
diff --git a/contrib/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp b/contrib/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp
index a019e9c32800..ad22845207e1 100644
--- a/contrib/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/contrib/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp
@@ -13,6 +13,8 @@
///
//===----------------------------------------------------------------------===//
+#include "lld/Common/Args.h"
+#include "lld/Common/ErrorHandler.h"
#include "lld/Common/LLVM.h"
#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/Error.h"
@@ -110,11 +112,11 @@ parseMemberFiles(std::unique_ptr<File> file) {
return members;
}
-std::vector<std::unique_ptr<File>>
-loadFile(MachOLinkingContext &ctx, StringRef path,
- raw_ostream &diag, bool wholeArchive, bool upwardDylib) {
+std::vector<std::unique_ptr<File>> loadFile(MachOLinkingContext &ctx,
+ StringRef path, bool wholeArchive,
+ bool upwardDylib) {
if (ctx.logInputFiles())
- diag << path << "\n";
+ message(path);
ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = ctx.getMemoryBuffer(path);
if (std::error_code ec = mbOrErr.getError())
@@ -155,10 +157,9 @@ static std::string canonicalizePath(StringRef path) {
}
static void addFile(StringRef path, MachOLinkingContext &ctx,
- bool loadWholeArchive,
- bool upwardDylib, raw_ostream &diag) {
+ bool loadWholeArchive, bool upwardDylib) {
std::vector<std::unique_ptr<File>> files =
- loadFile(ctx, path, diag, loadWholeArchive, upwardDylib);
+ loadFile(ctx, path, loadWholeArchive, upwardDylib);
for (std::unique_ptr<File> &file : files)
ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
}
@@ -166,8 +167,7 @@ static void addFile(StringRef path, MachOLinkingContext &ctx,
// Export lists are one symbol per line. Blank lines are ignored.
// Trailing comments start with #.
static std::error_code parseExportsList(StringRef exportFilePath,
- MachOLinkingContext &ctx,
- raw_ostream &diagnostics) {
+ MachOLinkingContext &ctx) {
// Map in export list file.
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
MemoryBuffer::getFileOrSTDIN(exportFilePath);
@@ -197,8 +197,7 @@ static std::error_code parseExportsList(StringRef exportFilePath,
/// libfrob.a(bar.o):_bar
/// x86_64:_foo64
static std::error_code parseOrderFile(StringRef orderFilePath,
- MachOLinkingContext &ctx,
- raw_ostream &diagnostics) {
+ MachOLinkingContext &ctx) {
// Map in order file.
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
MemoryBuffer::getFileOrSTDIN(orderFilePath);
@@ -252,8 +251,7 @@ static std::error_code parseOrderFile(StringRef orderFilePath,
// per line. The <dir> prefix is prepended to each partial path.
//
static llvm::Error loadFileList(StringRef fileListPath,
- MachOLinkingContext &ctx, bool forceLoad,
- raw_ostream &diagnostics) {
+ MachOLinkingContext &ctx, bool forceLoad) {
// If there is a comma, split off <dir>.
std::pair<StringRef, StringRef> opt = fileListPath.split(',');
StringRef filePath = opt.first;
@@ -286,9 +284,9 @@ static llvm::Error loadFileList(StringRef fileListPath,
+ "'");
}
if (ctx.testingFileUsage()) {
- diagnostics << "Found filelist entry " << canonicalizePath(path) << '\n';
+ message("Found filelist entry " + canonicalizePath(path));
}
- addFile(path, ctx, forceLoad, false, diagnostics);
+ addFile(path, ctx, forceLoad, false);
buffer = lineAndRest.second;
}
return llvm::Error::success();
@@ -317,8 +315,7 @@ static void parseLLVMOptions(const LinkingContext &ctx) {
namespace lld {
namespace mach_o {
-bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
- raw_ostream &diagnostics) {
+bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {
// Parse command line options using DarwinLdOptions.td
DarwinLdOptTable table;
unsigned missingIndex;
@@ -326,17 +323,20 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
llvm::opt::InputArgList parsedArgs =
table.ParseArgs(args.slice(1), missingIndex, missingCount);
if (missingCount) {
- diagnostics << "error: missing arg value for '"
- << parsedArgs.getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
+ error("missing arg value for '" +
+ Twine(parsedArgs.getArgString(missingIndex)) + "' expected " +
+ Twine(missingCount) + " argument(s).");
return false;
}
for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) {
- diagnostics << "warning: ignoring unknown argument: "
- << unknownArg->getAsString(parsedArgs) << "\n";
+ warn("ignoring unknown argument: " +
+ Twine(unknownArg->getAsString(parsedArgs)));
}
+ errorHandler().Verbose = parsedArgs.hasArg(OPT_v);
+ errorHandler().ErrorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20);
+
// Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;
bool isStaticExecutable = false;
@@ -367,8 +367,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
if (llvm::opt::Arg *archStr = parsedArgs.getLastArg(OPT_arch)) {
arch = MachOLinkingContext::archFromName(archStr->getValue());
if (arch == MachOLinkingContext::arch_unknown) {
- diagnostics << "error: unknown arch named '" << archStr->getValue()
- << "'\n";
+ error("unknown arch named '" + Twine(archStr->getValue()) + "'");
return false;
}
}
@@ -386,7 +385,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
if (parsedArgs.size() == 0)
table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false);
else
- diagnostics << "error: -arch not specified and could not be inferred\n";
+ error("-arch not specified and could not be inferred");
return false;
}
}
@@ -402,7 +401,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
os = MachOLinkingContext::OS::macOSX;
if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
minOSVersion)) {
- diagnostics << "error: malformed macosx_version_min value\n";
+ error("malformed macosx_version_min value");
return false;
}
break;
@@ -410,7 +409,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
os = MachOLinkingContext::OS::iOS;
if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
minOSVersion)) {
- diagnostics << "error: malformed ios_version_min value\n";
+ error("malformed ios_version_min value");
return false;
}
break;
@@ -418,7 +417,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
os = MachOLinkingContext::OS::iOS_simulator;
if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
minOSVersion)) {
- diagnostics << "error: malformed ios_simulator_version_min value\n";
+ error("malformed ios_simulator_version_min value");
return false;
}
break;
@@ -452,14 +451,14 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
if (llvm::opt::Arg *imageBase = parsedArgs.getLastArg(OPT_image_base)) {
uint64_t baseAddress;
if (parseNumberBase16(imageBase->getValue(), baseAddress)) {
- diagnostics << "error: image_base expects a hex number\n";
+ error("image_base expects a hex number");
return false;
} else if (baseAddress < ctx.pageZeroSize()) {
- diagnostics << "error: image_base overlaps with __PAGEZERO\n";
+ error("image_base overlaps with __PAGEZERO");
return false;
} else if (baseAddress % ctx.pageSize()) {
- diagnostics << "error: image_base must be a multiple of page size ("
- << "0x" << llvm::utohexstr(ctx.pageSize()) << ")\n";
+ error("image_base must be a multiple of page size (0x" +
+ llvm::utohexstr(ctx.pageSize()) + ")");
return false;
}
@@ -488,13 +487,12 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Handle -compatibility_version and -current_version
if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_compatibility_version)) {
if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
- diagnostics
- << "error: -compatibility_version can only be used with -dylib\n";
+ error("-compatibility_version can only be used with -dylib");
return false;
}
uint32_t parsedVers;
if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
- diagnostics << "error: -compatibility_version value is malformed\n";
+ error("-compatibility_version value is malformed");
return false;
}
ctx.setCompatibilityVersion(parsedVers);
@@ -502,12 +500,12 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_current_version)) {
if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
- diagnostics << "-current_version can only be used with -dylib\n";
+ error("-current_version can only be used with -dylib");
return false;
}
uint32_t parsedVers;
if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
- diagnostics << "error: -current_version value is malformed\n";
+ error("-current_version value is malformed");
return false;
}
ctx.setCurrentVersion(parsedVers);
@@ -526,17 +524,19 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
alignStr += 2;
unsigned long long alignValue;
if (llvm::getAsUnsignedInteger(alignStr, 16, alignValue)) {
- diagnostics << "error: -sectalign alignment value '"
- << alignStr << "' not a valid number\n";
+ error("-sectalign alignment value '" + Twine(alignStr) +
+ "' not a valid number");
return false;
}
uint16_t align = 1 << llvm::countTrailingZeros(alignValue);
if (!llvm::isPowerOf2_64(alignValue)) {
- diagnostics << "warning: alignment for '-sectalign "
- << segName << " " << sectName
- << llvm::format(" 0x%llX", alignValue)
- << "' is not a power of two, using "
- << llvm::format("0x%08X", align) << "\n";
+ std::string Msg;
+ llvm::raw_string_ostream OS(Msg);
+ OS << "alignment for '-sectalign " << segName << " " << sectName
+ << llvm::format(" 0x%llX", alignValue)
+ << "' is not a power of two, using " << llvm::format("0x%08X", align);
+ OS.flush();
+ warn(Msg);
}
ctx.addSectionAlignment(segName, sectName, align);
}
@@ -562,18 +562,14 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
if (parsedArgs.getLastArg(OPT_keep_private_externs)) {
ctx.setKeepPrivateExterns(true);
if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
- diagnostics << "warning: -keep_private_externs only used in -r mode\n";
+ warn("-keep_private_externs only used in -r mode");
}
// Handle -dependency_info <path> used by Xcode.
- if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info)) {
- if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue())) {
- diagnostics << "warning: " << ec.message()
- << ", processing '-dependency_info "
- << depInfo->getValue()
- << "'\n";
- }
- }
+ if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info))
+ if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue()))
+ warn(ec.message() + ", processing '-dependency_info " +
+ depInfo->getValue());
// In -test_file_usage mode, we'll be given an explicit list of paths that
// exist. We'll also be expected to print out information about how we located
@@ -639,31 +635,28 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Now that we've constructed the final set of search paths, print out those
// search paths in verbose mode.
- if (parsedArgs.getLastArg(OPT_v)) {
- diagnostics << "Library search paths:\n";
+ if (errorHandler().Verbose) {
+ message("Library search paths:");
for (auto path : ctx.searchDirs()) {
- diagnostics << " " << path << '\n';
+ message(" " + path);
}
- diagnostics << "Framework search paths:\n";
+ message("Framework search paths:");
for (auto path : ctx.frameworkDirs()) {
- diagnostics << " " << path << '\n';
+ message(" " + path);
}
}
// Handle -exported_symbols_list <file>
for (auto expFile : parsedArgs.filtered(OPT_exported_symbols_list)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) {
- diagnostics << "error: -exported_symbols_list cannot be combined "
- << "with -unexported_symbol[s_list]\n";
- return false;
+ error("-exported_symbols_list cannot be combined with "
+ "-unexported_symbol[s_list]");
+ return false;
}
ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList);
- if (std::error_code ec = parseExportsList(expFile->getValue(), ctx,
- diagnostics)) {
- diagnostics << "error: " << ec.message()
- << ", processing '-exported_symbols_list "
- << expFile->getValue()
- << "'\n";
+ if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) {
+ error(ec.message() + ", processing '-exported_symbols_list " +
+ expFile->getValue());
return false;
}
}
@@ -671,9 +664,9 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Handle -exported_symbol <symbol>
for (auto symbol : parsedArgs.filtered(OPT_exported_symbol)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) {
- diagnostics << "error: -exported_symbol cannot be combined "
- << "with -unexported_symbol[s_list]\n";
- return false;
+ error("-exported_symbol cannot be combined with "
+ "-unexported_symbol[s_list]");
+ return false;
}
ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList);
ctx.addExportSymbol(symbol->getValue());
@@ -682,17 +675,14 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Handle -unexported_symbols_list <file>
for (auto expFile : parsedArgs.filtered(OPT_unexported_symbols_list)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) {
- diagnostics << "error: -unexported_symbols_list cannot be combined "
- << "with -exported_symbol[s_list]\n";
- return false;
+ error("-unexported_symbols_list cannot be combined with "
+ "-exported_symbol[s_list]");
+ return false;
}
ctx.setExportMode(MachOLinkingContext::ExportMode::blackList);
- if (std::error_code ec = parseExportsList(expFile->getValue(), ctx,
- diagnostics)) {
- diagnostics << "error: " << ec.message()
- << ", processing '-unexported_symbols_list "
- << expFile->getValue()
- << "'\n";
+ if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) {
+ error(ec.message() + ", processing '-unexported_symbols_list " +
+ expFile->getValue());
return false;
}
}
@@ -700,9 +690,9 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Handle -unexported_symbol <symbol>
for (auto symbol : parsedArgs.filtered(OPT_unexported_symbol)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) {
- diagnostics << "error: -unexported_symbol cannot be combined "
- << "with -exported_symbol[s_list]\n";
- return false;
+ error("-unexported_symbol cannot be combined with "
+ "-exported_symbol[s_list]");
+ return false;
}
ctx.setExportMode(MachOLinkingContext::ExportMode::blackList);
ctx.addExportSymbol(symbol->getValue());
@@ -711,30 +701,26 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Handle obosolete -multi_module and -single_module
if (llvm::opt::Arg *mod =
parsedArgs.getLastArg(OPT_multi_module, OPT_single_module)) {
- if (mod->getOption().getID() == OPT_multi_module) {
- diagnostics << "warning: -multi_module is obsolete and being ignored\n";
- }
- else {
- if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
- diagnostics << "warning: -single_module being ignored. "
- "It is only for use when producing a dylib\n";
- }
- }
+ if (mod->getOption().getID() == OPT_multi_module)
+ warn("-multi_module is obsolete and being ignored");
+ else if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB)
+ warn("-single_module being ignored. It is only for use when producing a "
+ "dylib");
}
// Handle obsolete ObjC options: -objc_gc_compaction, -objc_gc, -objc_gc_only
if (parsedArgs.getLastArg(OPT_objc_gc_compaction)) {
- diagnostics << "error: -objc_gc_compaction is not supported\n";
+ error("-objc_gc_compaction is not supported");
return false;
}
if (parsedArgs.getLastArg(OPT_objc_gc)) {
- diagnostics << "error: -objc_gc is not supported\n";
+ error("-objc_gc is not supported");
return false;
}
if (parsedArgs.getLastArg(OPT_objc_gc_only)) {
- diagnostics << "error: -objc_gc_only is not supported\n";
+ error("-objc_gc_only is not supported");
return false;
}
@@ -746,22 +732,20 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
case MachOLinkingContext::OS::macOSX:
if ((minOSVersion < 0x000A0500) &&
(pie->getOption().getID() == OPT_pie)) {
- diagnostics << "-pie can only be used when targeting "
- "Mac OS X 10.5 or later\n";
+ error("-pie can only be used when targeting Mac OS X 10.5 or later");
return false;
}
break;
case MachOLinkingContext::OS::iOS:
if ((minOSVersion < 0x00040200) &&
(pie->getOption().getID() == OPT_pie)) {
- diagnostics << "-pie can only be used when targeting "
- "iOS 4.2 or later\n";
+ error("-pie can only be used when targeting iOS 4.2 or later");
return false;
}
break;
case MachOLinkingContext::OS::iOS_simulator:
if (pie->getOption().getID() == OPT_no_pie) {
- diagnostics << "iOS simulator programs must be built PIE\n";
+ error("iOS simulator programs must be built PIE");
return false;
}
break;
@@ -774,12 +758,12 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
break;
case llvm::MachO::MH_DYLIB:
case llvm::MachO::MH_BUNDLE:
- diagnostics << "warning: " << pie->getSpelling() << " being ignored. "
- << "It is only used when linking main executables\n";
+ warn(pie->getSpelling() +
+ " being ignored. It is only used when linking main executables");
break;
default:
- diagnostics << pie->getSpelling()
- << " can only used when linking main executables\n";
+ error(pie->getSpelling() +
+ " can only used when linking main executables");
return false;
}
}
@@ -934,7 +918,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
uint32_t sdkVersion = 0;
if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
sdkVersion)) {
- diagnostics << "error: malformed sdkVersion value\n";
+ error("malformed sdkVersion value");
return false;
}
ctx.setSdkVersion(sdkVersion);
@@ -943,9 +927,8 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// with min_version, then we need to give an warning as we have no sdk
// version to put in that command.
// FIXME: We need to decide whether to make this an error.
- diagnostics << "warning: -sdk_version is required when emitting "
- "min version load command. "
- "Setting sdk version to match provided min version\n";
+ warn("-sdk_version is required when emitting min version load command. "
+ "Setting sdk version to match provided min version");
ctx.setSdkVersion(ctx.osMinVersion());
}
@@ -954,7 +937,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
uint64_t version = 0;
if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
version)) {
- diagnostics << "error: malformed source_version value\n";
+ error("malformed source_version value");
return false;
}
ctx.setSourceVersion(version);
@@ -964,12 +947,12 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) {
uint64_t stackSizeVal;
if (parseNumberBase16(stackSize->getValue(), stackSizeVal)) {
- diagnostics << "error: stack_size expects a hex number\n";
+ error("stack_size expects a hex number");
return false;
}
if ((stackSizeVal % ctx.pageSize()) != 0) {
- diagnostics << "error: stack_size must be a multiple of page size ("
- << "0x" << llvm::utohexstr(ctx.pageSize()) << ")\n";
+ error("stack_size must be a multiple of page size (0x" +
+ llvm::utohexstr(ctx.pageSize()) + ")");
return false;
}
@@ -982,12 +965,9 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// Handle -order_file <file>
for (auto orderFile : parsedArgs.filtered(OPT_order_file)) {
- if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx,
- diagnostics)) {
- diagnostics << "error: " << ec.message()
- << ", processing '-order_file "
- << orderFile->getValue()
- << "'\n";
+ if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx)) {
+ error(ec.message() + ", processing '-order_file " + orderFile->getValue()
+ + "'");
return false;
}
}
@@ -1011,8 +991,8 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
else if (StringRef(undef->getValue()).equals("dynamic_lookup"))
UndefMode = MachOLinkingContext::UndefinedMode::dynamicLookup;
else {
- diagnostics << "error: invalid option to -undefined "
- "[ warning | error | suppress | dynamic_lookup ]\n";
+ error("invalid option to -undefined [ warning | error | suppress | "
+ "dynamic_lookup ]");
return false;
}
@@ -1026,8 +1006,8 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
// illegal. Emit a diagnostic if they've been (mis)used.
if (UndefMode == MachOLinkingContext::UndefinedMode::warning ||
UndefMode == MachOLinkingContext::UndefinedMode::suppress) {
- diagnostics << "error: can't use -undefined warning or suppress with "
- "-twolevel_namespace\n";
+ error("can't use -undefined warning or suppress with "
+ "-twolevel_namespace");
return false;
}
}
@@ -1046,19 +1026,16 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
case llvm::MachO::MH_DYLIB:
case llvm::MachO::MH_BUNDLE:
if (!ctx.minOS("10.5", "2.0")) {
- if (ctx.os() == MachOLinkingContext::OS::macOSX) {
- diagnostics << "error: -rpath can only be used when targeting "
- "OS X 10.5 or later\n";
- } else {
- diagnostics << "error: -rpath can only be used when targeting "
- "iOS 2.0 or later\n";
- }
+ if (ctx.os() == MachOLinkingContext::OS::macOSX)
+ error("-rpath can only be used when targeting OS X 10.5 or later");
+ else
+ error("-rpath can only be used when targeting iOS 2.0 or later");
return false;
}
break;
default:
- diagnostics << "error: -rpath can only be used when creating "
- "a dynamic final linked image\n";
+ error("-rpath can only be used when creating a dynamic final linked "
+ "image");
return false;
}
@@ -1068,7 +1045,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
}
// Parse the LLVM options before we process files in case the file handling
- // makes use of things like DEBUG().
+ // makes use of things like LLVM_DEBUG().
parseLLVMOptions(ctx);
// Handle input files and sectcreate.
@@ -1079,52 +1056,46 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
default:
continue;
case OPT_INPUT:
- addFile(arg->getValue(), ctx, globalWholeArchive, false, diagnostics);
+ addFile(arg->getValue(), ctx, globalWholeArchive, false);
break;
case OPT_upward_library:
- addFile(arg->getValue(), ctx, false, true, diagnostics);
+ addFile(arg->getValue(), ctx, false, true);
break;
case OPT_force_load:
- addFile(arg->getValue(), ctx, true, false, diagnostics);
+ addFile(arg->getValue(), ctx, true, false);
break;
case OPT_l:
case OPT_upward_l:
upward = (arg->getOption().getID() == OPT_upward_l);
resolvedPath = ctx.searchLibrary(arg->getValue());
if (!resolvedPath) {
- diagnostics << "Unable to find library for " << arg->getSpelling()
- << arg->getValue() << "\n";
+ error("Unable to find library for " + arg->getSpelling() +
+ arg->getValue());
return false;
} else if (ctx.testingFileUsage()) {
- diagnostics << "Found " << (upward ? "upward " : " ") << "library "
- << canonicalizePath(resolvedPath.getValue()) << '\n';
+ message(Twine("Found ") + (upward ? "upward " : " ") + "library " +
+ canonicalizePath(resolvedPath.getValue()));
}
- addFile(resolvedPath.getValue(), ctx, globalWholeArchive,
- upward, diagnostics);
+ addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward);
break;
case OPT_framework:
case OPT_upward_framework:
upward = (arg->getOption().getID() == OPT_upward_framework);
resolvedPath = ctx.findPathForFramework(arg->getValue());
if (!resolvedPath) {
- diagnostics << "Unable to find framework for "
- << arg->getSpelling() << " " << arg->getValue() << "\n";
+ error("Unable to find framework for " + arg->getSpelling() + " " +
+ arg->getValue());
return false;
} else if (ctx.testingFileUsage()) {
- diagnostics << "Found " << (upward ? "upward " : " ") << "framework "
- << canonicalizePath(resolvedPath.getValue()) << '\n';
+ message(Twine("Found ") + (upward ? "upward " : " ") + "framework " +
+ canonicalizePath(resolvedPath.getValue()));
}
- addFile(resolvedPath.getValue(), ctx, globalWholeArchive,
- upward, diagnostics);
+ addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward);
break;
case OPT_filelist:
- if (auto ec = loadFileList(arg->getValue(),
- ctx, globalWholeArchive,
- diagnostics)) {
+ if (auto ec = loadFileList(arg->getValue(), ctx, globalWholeArchive)) {
handleAllErrors(std::move(ec), [&](const llvm::ErrorInfoBase &EI) {
- diagnostics << "error: ";
- EI.log(diagnostics);
- diagnostics << ", processing '-filelist " << arg->getValue() << "'\n";
+ error(EI.message() + ", processing '-filelist " + arg->getValue());
});
return false;
}
@@ -1138,7 +1109,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
MemoryBuffer::getFile(fileName);
if (!contentOrErr) {
- diagnostics << "error: can't open -sectcreate file " << fileName << "\n";
+ error("can't open -sectcreate file " + Twine(fileName));
return false;
}
@@ -1149,12 +1120,12 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
}
if (ctx.getNodes().empty()) {
- diagnostics << "No input files\n";
+ error("No input files");
return false;
}
// Validate the combination of options used.
- return ctx.validate(diagnostics);
+ return ctx.validate();
}
static void createFiles(MachOLinkingContext &ctx, bool Implicit) {
@@ -1170,9 +1141,18 @@ static void createFiles(MachOLinkingContext &ctx, bool Implicit) {
}
/// This is where the link is actually performed.
-bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) {
+bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
+ raw_ostream &Error) {
+ errorHandler().LogName = llvm::sys::path::filename(args[0]);
+ errorHandler().ErrorLimitExceededMsg =
+ "too many errors emitted, stopping now (use "
+ "'-error-limit 0' to see all errors)";
+ errorHandler().ErrorOS = &Error;
+ errorHandler().ExitEarly = CanExitEarly;
+ errorHandler().ColorDiagnostics = Error.has_colors();
+
MachOLinkingContext ctx;
- if (!parse(args, ctx, diagnostics))
+ if (!parse(args, ctx))
return false;
if (ctx.doNothing())
return true;
@@ -1214,9 +1194,10 @@ bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) {
if (auto ec = pm.runOnFile(*merged)) {
// FIXME: This should be passed to logAllUnhandledErrors but it needs
// to be passed a Twine instead of a string.
- diagnostics << "Failed to run passes on file '" << ctx.outputPath()
- << "': ";
- logAllUnhandledErrors(std::move(ec), diagnostics, std::string());
+ *errorHandler().ErrorOS << "Failed to run passes on file '"
+ << ctx.outputPath() << "': ";
+ logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS,
+ std::string());
return false;
}
@@ -1227,11 +1208,18 @@ bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) {
if (auto ec = ctx.writeFile(*merged)) {
// FIXME: This should be passed to logAllUnhandledErrors but it needs
// to be passed a Twine instead of a string.
- diagnostics << "Failed to write file '" << ctx.outputPath() << "': ";
- logAllUnhandledErrors(std::move(ec), diagnostics, std::string());
+ *errorHandler().ErrorOS << "Failed to write file '" << ctx.outputPath()
+ << "': ";
+ logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS,
+ std::string());
return false;
}
+ // Call exit() if we can to avoid calling destructors.
+ if (CanExitEarly)
+ exitLld(errorCount() ? 1 : 0);
+
+
return true;
}
diff --git a/contrib/llvm/tools/lld/lib/Driver/DarwinLdOptions.td b/contrib/llvm/tools/lld/lib/Driver/DarwinLdOptions.td
index fa07f33646e7..3bbde8bf1c1c 100644
--- a/contrib/llvm/tools/lld/lib/Driver/DarwinLdOptions.td
+++ b/contrib/llvm/tools/lld/lib/Driver/DarwinLdOptions.td
@@ -227,6 +227,14 @@ def t : Flag<["-"], "t">,
HelpText<"Print the names of the input files as ld processes them">;
def v : Flag<["-"], "v">,
HelpText<"Print linker information">;
+def error_limit : Separate<["-", "--"], "error-limit">,
+ MetaVarName<"<number>">,
+ HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">;
+
+// Ignored options
+def lto_library : Separate<["-"], "lto_library">,
+ MetaVarName<"<path>">,
+ HelpText<"Ignored for compatibility with other linkers">;
// Obsolete options
def grp_obsolete : OptionGroup<"obsolete">, HelpText<"OBSOLETE OPTIONS">;
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/FileArchive.cpp b/contrib/llvm/tools/lld/lib/ReaderWriter/FileArchive.cpp
index 04c0bee76989..2f52d9d34312 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/FileArchive.cpp
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/FileArchive.cpp
@@ -38,7 +38,7 @@ namespace lld {
namespace {
-/// \brief The FileArchive class represents an Archive Library file
+/// The FileArchive class represents an Archive Library file
class FileArchive : public lld::ArchiveLibraryFile {
public:
FileArchive(std::unique_ptr<MemoryBuffer> mb, const Registry &reg,
@@ -46,7 +46,7 @@ public:
: ArchiveLibraryFile(path), _mb(std::shared_ptr<MemoryBuffer>(mb.release())),
_registry(reg), _logLoading(logLoading) {}
- /// \brief Check if any member of the archive contains an Atom with the
+ /// Check if any member of the archive contains an Atom with the
/// specified name and return the File object for that member, or nullptr.
File *find(StringRef name) override {
auto member = _symbolMemberMap.find(name);
@@ -77,7 +77,7 @@ public:
return file;
}
- /// \brief parse each member
+ /// parse each member
std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
if (std::error_code ec = parse())
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index aee9959ca6b8..8cb6710857e3 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -674,7 +674,7 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
*loc32 = ref.addend() + inAtomAddress - fixupAddress;
return;
case delta32Anon:
- // The value we write here should be the the delta to the target
+ // The value we write here should be the delta to the target
// after taking in to account the difference from the fixup back to the
// last defined label
// ie, if we have:
@@ -690,7 +690,7 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
*loc64 = ref.addend() + inAtomAddress - fixupAddress;
return;
case delta64Anon:
- // The value we write here should be the the delta to the target
+ // The value we write here should be the delta to the target
// after taking in to account the difference from the fixup back to the
// last defined label
// ie, if we have:
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CMakeLists.txt
index f2fc34772496..37d1de432c0f 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CMakeLists.txt
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -26,6 +26,7 @@ add_lld_library(lldMachO
Support
LINK_LIBS
+ lldCommon
lldCore
lldYAML
${LLVM_PTHREAD_LIB}
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
index 1e210409237f..fa0aaa103eeb 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
@@ -282,7 +282,7 @@ public:
private:
llvm::Error perform(SimpleFile &mergedFile) override {
- DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
+ LLVM_DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
std::map<const Atom *, CompactUnwindEntry> unwindLocs;
std::map<const Atom *, const Atom *> dwarfFrames;
@@ -319,7 +319,7 @@ private:
// Finally, we can start creating pages based on these entries.
- DEBUG(llvm::dbgs() << " Splitting entries into pages\n");
+ LLVM_DEBUG(llvm::dbgs() << " Splitting entries into pages\n");
// FIXME: we split the entries into pages naively: lots of 4k pages followed
// by a small one. ld64 tried to minimize space and align them to real 4k
// boundaries. That might be worth doing, or perhaps we could perform some
@@ -336,11 +336,13 @@ private:
pages.back().entries = remainingInfos.slice(0, entriesInPage);
remainingInfos = remainingInfos.slice(entriesInPage);
- DEBUG(llvm::dbgs()
- << " Page from " << pages.back().entries[0].rangeStart->name()
- << " to " << pages.back().entries.back().rangeStart->name() << " + "
- << llvm::format("0x%x", pages.back().entries.back().rangeLength)
- << " has " << entriesInPage << " entries\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << " Page from "
+ << pages.back().entries[0].rangeStart->name() << " to "
+ << pages.back().entries.back().rangeStart->name() << " + "
+ << llvm::format("0x%x",
+ pages.back().entries.back().rangeLength)
+ << " has " << entriesInPage << " entries\n");
} while (!remainingInfos.empty());
auto *unwind = new (_file.allocator())
@@ -360,7 +362,7 @@ private:
const SimpleFile &mergedFile,
std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
std::vector<const Atom *> &personalities, uint32_t &numLSDAs) {
- DEBUG(llvm::dbgs() << " Collecting __compact_unwind entries\n");
+ LLVM_DEBUG(llvm::dbgs() << " Collecting __compact_unwind entries\n");
for (const DefinedAtom *atom : mergedFile.defined()) {
if (atom->contentType() != DefinedAtom::typeCompactUnwindInfo)
@@ -369,14 +371,15 @@ private:
auto unwindEntry = extractCompactUnwindEntry(atom);
unwindLocs.insert(std::make_pair(unwindEntry.rangeStart, unwindEntry));
- DEBUG(llvm::dbgs() << " Entry for " << unwindEntry.rangeStart->name()
- << ", encoding="
- << llvm::format("0x%08x", unwindEntry.encoding));
+ LLVM_DEBUG(llvm::dbgs() << " Entry for "
+ << unwindEntry.rangeStart->name() << ", encoding="
+ << llvm::format("0x%08x", unwindEntry.encoding));
if (unwindEntry.personalityFunction)
- DEBUG(llvm::dbgs() << ", personality="
- << unwindEntry.personalityFunction->name()
- << ", lsdaLoc=" << unwindEntry.lsdaLocation->name());
- DEBUG(llvm::dbgs() << '\n');
+ LLVM_DEBUG(llvm::dbgs()
+ << ", personality="
+ << unwindEntry.personalityFunction->name()
+ << ", lsdaLoc=" << unwindEntry.lsdaLocation->name());
+ LLVM_DEBUG(llvm::dbgs() << '\n');
// Count number of LSDAs we see, since we need to know how big the index
// will be while laying out the section.
@@ -454,7 +457,7 @@ private:
const std::map<const Atom *, const Atom *> &dwarfFrames) {
std::vector<CompactUnwindEntry> unwindInfos;
- DEBUG(llvm::dbgs() << " Creating __unwind_info entries\n");
+ LLVM_DEBUG(llvm::dbgs() << " Creating __unwind_info entries\n");
// The final order in the __unwind_info section must be derived from the
// order of typeCode atoms, since that's how they'll be put into the object
// file eventually (yuck!).
@@ -465,10 +468,10 @@ private:
unwindInfos.push_back(finalizeUnwindInfoEntryForAtom(
atom, unwindLocs, personalities, dwarfFrames));
- DEBUG(llvm::dbgs() << " Entry for " << atom->name()
- << ", final encoding="
- << llvm::format("0x%08x", unwindInfos.back().encoding)
- << '\n');
+ LLVM_DEBUG(llvm::dbgs()
+ << " Entry for " << atom->name() << ", final encoding="
+ << llvm::format("0x%08x", unwindInfos.back().encoding)
+ << '\n');
}
return unwindInfos;
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/LayoutPass.cpp b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
index 7bca07eb16d6..9058e4f562e2 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
@@ -191,7 +191,7 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
// Sort atoms by their ordinal overrides only if they fall in the same
// chain.
if (leftRoot == rightRoot) {
- DEBUG(reason = formatReason("override", lc._override, rc._override));
+ LLVM_DEBUG(reason = formatReason("override", lc._override, rc._override));
return lc._override < rc._override;
}
@@ -200,8 +200,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
DefinedAtom::ContentPermissions rightPerms = rightRoot->permissions();
if (leftPerms != rightPerms) {
- DEBUG(reason =
- formatReason("contentPerms", (int)leftPerms, (int)rightPerms));
+ LLVM_DEBUG(
+ reason = formatReason("contentPerms", (int)leftPerms, (int)rightPerms));
return leftPerms < rightPerms;
}
@@ -210,7 +210,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
DefinedAtom::ContentType rightType = rightRoot->contentType();
if (leftType != rightType) {
- DEBUG(reason = formatReason("contentType", (int)leftType, (int)rightType));
+ LLVM_DEBUG(reason =
+ formatReason("contentType", (int)leftType, (int)rightType));
return leftType < rightType;
}
@@ -226,8 +227,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
const File *rightFile = &rightRoot->file();
if (leftFile != rightFile) {
- DEBUG(reason = formatReason(".o order", (int)leftFile->ordinal(),
- (int)rightFile->ordinal()));
+ LLVM_DEBUG(reason = formatReason(".o order", (int)leftFile->ordinal(),
+ (int)rightFile->ordinal()));
return leftFile->ordinal() < rightFile->ordinal();
}
@@ -236,8 +237,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
uint64_t rightOrdinal = rightRoot->ordinal();
if (leftOrdinal != rightOrdinal) {
- DEBUG(reason = formatReason("ordinal", (int)leftRoot->ordinal(),
- (int)rightRoot->ordinal()));
+ LLVM_DEBUG(reason = formatReason("ordinal", (int)leftRoot->ordinal(),
+ (int)rightRoot->ordinal()));
return leftOrdinal < rightOrdinal;
}
@@ -251,7 +252,7 @@ static bool compareAtoms(const LayoutPass::SortKey &lc,
LayoutPass::SortOverride customSorter) {
std::string reason;
bool result = compareAtomsSub(lc, rc, customSorter, reason);
- DEBUG({
+ LLVM_DEBUG({
StringRef comp = result ? "<" : ">=";
llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
<< "' " << comp << " '"
@@ -441,7 +442,7 @@ void LayoutPass::undecorate(File::AtomRange<DefinedAtom> &atomRange,
/// Perform the actual pass
llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
- DEBUG(llvm::dbgs() << "******** Laying out atoms:\n");
+ LLVM_DEBUG(llvm::dbgs() << "******** Laying out atoms:\n");
// sort the atoms
ScopedTask task(getDefaultDomain(), "LayoutPass");
File::AtomRange<DefinedAtom> atomRange = mergedFile.defined();
@@ -450,12 +451,12 @@ llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
buildFollowOnTable(atomRange);
// Check the structure of followon graph if running in debug mode.
- DEBUG(checkFollowonChain(atomRange));
+ LLVM_DEBUG(checkFollowonChain(atomRange));
// Build override maps
buildOrdinalOverrideMap(atomRange);
- DEBUG({
+ LLVM_DEBUG({
llvm::dbgs() << "unsorted atoms:\n";
printDefinedAtoms(atomRange);
});
@@ -465,15 +466,15 @@ llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
[&](const LayoutPass::SortKey &l, const LayoutPass::SortKey &r) -> bool {
return compareAtoms(l, r, _customSorter);
});
- DEBUG(checkTransitivity(vec, _customSorter));
+ LLVM_DEBUG(checkTransitivity(vec, _customSorter));
undecorate(atomRange, vec);
- DEBUG({
+ LLVM_DEBUG({
llvm::dbgs() << "sorted atoms:\n";
printDefinedAtoms(atomRange);
});
- DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
+ LLVM_DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
return llvm::Error::success();
}
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 4ef7a62a8297..ce423d03aae3 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "lld/Common/ErrorHandler.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "ArchHandler.h"
#include "File.h"
@@ -579,29 +580,26 @@ MachOLinkingContext::findPathForFramework(StringRef fwName) const{
return llvm::None;
}
-bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
+bool MachOLinkingContext::validateImpl() {
// TODO: if -arch not specified, look at arch of first .o file.
if (_currentVersion && _outputMachOType != MH_DYLIB) {
- diagnostics << "error: -current_version can only be used with dylibs\n";
+ error("-current_version can only be used with dylibs");
return false;
}
if (_compatibilityVersion && _outputMachOType != MH_DYLIB) {
- diagnostics
- << "error: -compatibility_version can only be used with dylibs\n";
+ error("-compatibility_version can only be used with dylibs");
return false;
}
if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) {
- diagnostics
- << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
+ error("-mark_dead_strippable_dylib can only be used with dylibs");
return false;
}
if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) {
- diagnostics
- << "error: -bundle_loader can only be used with Mach-O bundles\n";
+ error("-bundle_loader can only be used with Mach-O bundles");
return false;
}
diff --git a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 3b07a40f9bf2..473de894894e 100644
--- a/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -906,7 +906,7 @@ readCompUnit(const NormalizedFile &normalizedFile,
abbrevData.getU8(&abbrevOffset);
uint32_t name;
llvm::dwarf::Form form;
- llvm::DWARFFormParams formParams = {version, addrSize, Format};
+ llvm::dwarf::FormParams formParams = {version, addrSize, Format};
TranslationUnitSource tu;
while ((name = abbrevData.getULEB128(&abbrevOffset)) |
(form = static_cast<llvm::dwarf::Form>(
@@ -1431,8 +1431,8 @@ llvm::Error
normalizedObjectToAtoms(MachOFile *file,
const NormalizedFile &normalizedFile,
bool copyRefs) {
- DEBUG(llvm::dbgs() << "******** Normalizing file to atoms: "
- << file->path() << "\n");
+ LLVM_DEBUG(llvm::dbgs() << "******** Normalizing file to atoms: "
+ << file->path() << "\n");
bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
// Create atoms from each section.
diff --git a/contrib/llvm/tools/lld/tools/lld/lld.cpp b/contrib/llvm/tools/lld/tools/lld/lld.cpp
index fa4bf6f64328..65a9a800ec7a 100644
--- a/contrib/llvm/tools/lld/tools/lld/lld.cpp
+++ b/contrib/llvm/tools/lld/tools/lld/lld.cpp
@@ -7,12 +7,22 @@
//
//===----------------------------------------------------------------------===//
//
-// This is the entry point to the lld driver. This is a thin wrapper which
-// dispatches to the given platform specific driver.
+// This file contains the main function of the lld executable. The main
+// function is a thin wrapper which dispatches to the platform specific
+// driver.
//
-// If there is -flavor option, it is dispatched according to the arguments.
-// If the flavor parameter is not present, then it is dispatched according
-// to argv[0].
+// lld is a single executable that contains four different linkers for ELF,
+// COFF, WebAssembly and Mach-O. The main function dispatches according to
+// argv[0] (i.e. command name). The most common name for each target is shown
+// below:
+//
+// - ld.lld: ELF (Unix)
+// - ld64: Mach-O (macOS)
+// - lld-link: COFF (Windows)
+// - ld-wasm: WebAssembly
+//
+// lld can be invoked as "lld" along with "-flavor" option. This is for
+// backward compatibility and not recommended.
//
//===----------------------------------------------------------------------===//
@@ -20,10 +30,9 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include <cstdlib>
using namespace lld;
using namespace llvm;
@@ -102,13 +111,18 @@ static Flavor parseFlavor(std::vector<const char *> &V) {
return parseProgname(Arg0);
}
+// If this function returns true, lld calls _exit() so that it quickly
+// exits without invoking destructors of globally allocated objects.
+//
+// We don't want to do that if we are running tests though, because
+// doing that breaks leak sanitizer. So, lit sets this environment variable,
+// and we use it to detect whether we are running tests or not.
+static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; }
+
/// Universal linker main(). This linker emulates the gnu, darwin, or
/// windows linker based on the argv[0] or -flavor option.
int main(int Argc, const char **Argv) {
- // Standard set up, so program fails gracefully.
- sys::PrintStackTraceOnErrorSignal(Argv[0]);
- PrettyStackTraceProgram StackPrinter(Argc, Argv);
- llvm_shutdown_obj Shutdown;
+ InitLLVM X(Argc, Argv);
std::vector<const char *> Args(Argv, Argv + Argc);
#ifdef __FreeBSD__
@@ -118,16 +132,17 @@ int main(int Argc, const char **Argv) {
case Gnu:
if (isPETarget(Args))
return !mingw::link(Args);
- return !elf::link(Args, true);
+ return !elf::link(Args, canExitEarly());
case WinLink:
- return !coff::link(Args, true);
+ return !coff::link(Args, canExitEarly());
case Darwin:
- return !mach_o::link(Args);
+ return !mach_o::link(Args, canExitEarly());
case Wasm:
- return !wasm::link(Args, true);
+ return !wasm::link(Args, canExitEarly());
default:
die("lld is a generic driver.\n"
- "Invoke ld.lld (Unix), ld (macOS) or lld-link (Windows) instead.");
+ "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-lld"
+ " (WebAssembly) instead");
}
#endif
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBAddress.h b/contrib/llvm/tools/lldb/include/lldb/API/SBAddress.h
index 9e697beffdd1..02e847b97aa1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBAddress.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBAddress.h
@@ -54,9 +54,9 @@ public:
lldb::SBSymbolContext GetSymbolContext(uint32_t resolve_scope);
// The following functions grab individual objects for a given address and
- // are less efficient if you want more than one symbol related objects.
- // Use one of the following when you want multiple debug symbol related
- // objects for an address:
+ // are less efficient if you want more than one symbol related objects. Use
+ // one of the following when you want multiple debug symbol related objects
+ // for an address:
// lldb::SBSymbolContext SBAddress::GetSymbolContext (uint32_t
// resolve_scope);
// lldb::SBSymbolContext SBTarget::ResolveSymbolContextForAddress (const
@@ -80,8 +80,6 @@ public:
lldb::SBLineEntry GetLineEntry();
- lldb::AddressClass GetAddressClass();
-
protected:
friend class SBBlock;
friend class SBBreakpointLocation;
@@ -103,7 +101,7 @@ protected:
const lldb_private::Address *operator->() const;
- friend bool operator==(const SBAddress &lhs, const SBAddress &rhs);
+ friend bool LLDB_API operator==(const SBAddress &lhs, const SBAddress &rhs);
lldb_private::Address *get();
@@ -119,7 +117,7 @@ private:
std::unique_ptr<lldb_private::Address> m_opaque_ap;
};
-bool operator==(const SBAddress &lhs, const SBAddress &rhs);
+bool LLDB_API operator==(const SBAddress &lhs, const SBAddress &rhs);
} // namespace lldb
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBBroadcaster.h b/contrib/llvm/tools/lldb/include/lldb/API/SBBroadcaster.h
index 3fc47af65513..dc6c50ec0a8a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBBroadcaster.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBBroadcaster.h
@@ -46,17 +46,17 @@ public:
bool RemoveListener(const lldb::SBListener &listener,
uint32_t event_mask = UINT32_MAX);
- // This comparison is checking if the internal opaque pointer value
- // is equal to that in "rhs".
+ // This comparison is checking if the internal opaque pointer value is equal
+ // to that in "rhs".
bool operator==(const lldb::SBBroadcaster &rhs) const;
- // This comparison is checking if the internal opaque pointer value
- // is not equal to that in "rhs".
+ // This comparison is checking if the internal opaque pointer value is not
+ // equal to that in "rhs".
bool operator!=(const lldb::SBBroadcaster &rhs) const;
- // This comparison is checking if the internal opaque pointer value
- // is less than that in "rhs" so SBBroadcaster objects can be contained
- // in ordered containers.
+ // This comparison is checking if the internal opaque pointer value is less
+ // than that in "rhs" so SBBroadcaster objects can be contained in ordered
+ // containers.
bool operator<(const lldb::SBBroadcaster &rhs) const;
protected:
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h
index 80f24ceca7b4..8b9f06599366 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h
@@ -138,23 +138,20 @@ public:
lldb::SBCommandReturnObject result);
// The pointer based interface is not useful in SWIG, since the cursor &
- // last_char arguments are string pointers INTO current_line
- // and you can't do that in a scripting language interface in general...
+ // last_char arguments are string pointers INTO current_line and you can't do
+ // that in a scripting language interface in general...
// In either case, the way this works is that the you give it a line and
- // cursor position in the line. The function
- // will return the number of completions. The matches list will contain
- // number_of_completions + 1 elements. The first
- // element is the common substring after the cursor position for all the
- // matches. The rest of the elements are the
- // matches. The first element is useful if you are emulating the common shell
- // behavior where the tab completes
- // to the string that is common among all the matches, then you should first
- // check if the first element is non-empty,
+ // cursor position in the line. The function will return the number of
+ // completions. The matches list will contain number_of_completions + 1
+ // elements. The first element is the common substring after the cursor
+ // position for all the matches. The rest of the elements are the matches.
+ // The first element is useful if you are emulating the common shell behavior
+ // where the tab completes to the string that is common among all the
+ // matches, then you should first check if the first element is non-empty,
// and if so just insert it and move the cursor to the end of the insertion.
- // The next tab will return an empty
- // common substring, and a list of choices (if any), at which point you should
- // display the choices and let the user
+ // The next tab will return an empty common substring, and a list of choices
+ // (if any), at which point you should display the choices and let the user
// type further to disambiguate.
int HandleCompletion(const char *current_line, const char *cursor,
@@ -167,9 +164,9 @@ public:
bool WasInterrupted() const;
- // Catch commands before they execute by registering a callback that will
- // get called when the command gets executed. This allows GUI or command
- // line interfaces to intercept a command and stop it from happening
+ // Catch commands before they execute by registering a callback that will get
+ // called when the command gets executed. This allows GUI or command line
+ // interfaces to intercept a command and stop it from happening
bool SetCommandOverrideCallback(const char *command_name,
lldb::CommandOverrideCallback callback,
void *baton);
@@ -211,6 +208,25 @@ public:
void SetPromptOnQuit(bool b);
//----------------------------------------------------------------------
+ /// Sets whether the command interpreter should allow custom exit codes
+ /// for the 'quit' command.
+ //----------------------------------------------------------------------
+ void AllowExitCodeOnQuit(bool allow);
+
+ //----------------------------------------------------------------------
+ /// Returns true if the user has called the 'quit' command with a custom exit
+ /// code.
+ //----------------------------------------------------------------------
+ bool HasCustomQuitExitCode();
+
+ //----------------------------------------------------------------------
+ /// Returns the exit code that the user has specified when running the
+ /// 'quit' command. Returns 0 if the user hasn't called 'quit' at all or
+ /// without a custom exit code.
+ //----------------------------------------------------------------------
+ int GetQuitStatus();
+
+ //----------------------------------------------------------------------
/// Resolve the command just as HandleCommand would, expanding abbreviations
/// and aliases. If successful, result->GetOutput has the full expansion.
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h
index c73e3f7cf1f2..a372ea2ad9ee 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h
@@ -67,8 +67,7 @@ public:
bool GetDescription(lldb::SBStream &description);
- // deprecated, these two functions do not take
- // ownership of file handle
+ // deprecated, these two functions do not take ownership of file handle
void SetImmediateOutputFile(FILE *fh);
void SetImmediateErrorFile(FILE *fh);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBData.h b/contrib/llvm/tools/lldb/include/lldb/API/SBData.h
index 7aa4ea0ff8d0..7ff619e68667 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBData.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBData.h
@@ -71,11 +71,10 @@ public:
lldb::addr_t base_addr = LLDB_INVALID_ADDRESS);
// it would be nice to have SetData(SBError, const void*, size_t) when
- // endianness and address size can be
- // inferred from the existing DataExtractor, but having two SetData()
- // signatures triggers a SWIG bug where
- // the typemap isn't applied before resolving the overload, and thus the right
- // function never gets called
+ // endianness and address size can be inferred from the existing
+ // DataExtractor, but having two SetData() signatures triggers a SWIG bug
+ // where the typemap isn't applied before resolving the overload, and thus
+ // the right function never gets called
void SetData(lldb::SBError &error, const void *buf, size_t size,
lldb::ByteOrder endian, uint8_t addr_size);
@@ -87,9 +86,8 @@ public:
const char *data);
// in the following CreateData*() and SetData*() prototypes, the two
- // parameters array and array_len
- // should not be renamed or rearranged, because doing so will break the SWIG
- // typemap
+ // parameters array and array_len should not be renamed or rearranged,
+ // because doing so will break the SWIG typemap
static lldb::SBData CreateDataFromUInt64Array(lldb::ByteOrder endian,
uint32_t addr_byte_size,
uint64_t *array,
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h b/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h
index 8379a6911afc..a416b460f318 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h
@@ -181,6 +181,8 @@ public:
static const char *StateAsCString(lldb::StateType state);
+ static SBStructuredData GetBuildConfiguration();
+
static bool StateIsRunningState(lldb::StateType state);
static bool StateIsStoppedState(lldb::StateType state);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBExpressionOptions.h b/contrib/llvm/tools/lldb/include/lldb/API/SBExpressionOptions.h
index 370811d0c355..1459ba6fee2a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBExpressionOptions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBExpressionOptions.h
@@ -51,10 +51,8 @@ public:
uint32_t GetOneThreadTimeoutInMicroSeconds() const;
// Set the timeout for running on one thread, 0 means use the default
- // behavior.
- // If you set this higher than the overall timeout, you'll get an error when
- // you
- // try to run the expression.
+ // behavior. If you set this higher than the overall timeout, you'll get an
+ // error when you try to run the expression.
void SetOneThreadTimeoutInMicroSeconds(uint32_t timeout = 0);
bool GetTryAllThreads() const;
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBFrame.h b/contrib/llvm/tools/lldb/include/lldb/API/SBFrame.h
index 58339750def6..b8953dd13236 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBFrame.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBFrame.h
@@ -153,10 +153,10 @@ public:
lldb::DynamicValueType use_dynamic);
// Find a value for a variable expression path like "rect.origin.x" or
- // "pt_ptr->x", "*self", "*this->obj_ptr". The returned value is _not_
- // and expression result and is not a constant object like
- // SBFrame::EvaluateExpression(...) returns, but a child object of
- // the variable value.
+ // "pt_ptr->x", "*self", "*this->obj_ptr". The returned value is _not_ and
+ // expression result and is not a constant object like
+ // SBFrame::EvaluateExpression(...) returns, but a child object of the
+ // variable value.
lldb::SBValue GetValueForVariablePath(const char *var_expr_cstr,
DynamicValueType use_dynamic);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h b/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h
index 23daf1c56637..5ef02b8f696a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h
@@ -16,8 +16,7 @@
#include <stdio.h>
// There's a lot to be fixed here, but need to wait for underlying insn
-// implementation
-// to be revised & settle down first.
+// implementation to be revised & settle down first.
class InstructionImpl;
@@ -37,8 +36,6 @@ public:
SBAddress GetAddress();
- lldb::AddressClass GetAddressClass();
-
const char *GetMnemonic(lldb::SBTarget target);
const char *GetOperands(lldb::SBTarget target);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBInstructionList.h b/contrib/llvm/tools/lldb/include/lldb/API/SBInstructionList.h
index 0323a3c80c05..c8fed5c83192 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBInstructionList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBInstructionList.h
@@ -33,8 +33,8 @@ public:
lldb::SBInstruction GetInstructionAtIndex(uint32_t idx);
// ----------------------------------------------------------------------
- // Returns the number of instructions between the start and end address.
- // If canSetBreakpoint is true then the count will be the number of
+ // Returns the number of instructions between the start and end address. If
+ // canSetBreakpoint is true then the count will be the number of
// instructions on which a breakpoint can be set.
// ----------------------------------------------------------------------
size_t GetInstructionsCount(const SBAddress &start,
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBLaunchInfo.h b/contrib/llvm/tools/lldb/include/lldb/API/SBLaunchInfo.h
index 1cece235127f..80eea7e42921 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBLaunchInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBLaunchInfo.h
@@ -12,6 +12,10 @@
#include "lldb/API/SBDefines.h"
+namespace lldb_private {
+class SBLaunchInfoImpl;
+}
+
namespace lldb {
class SBPlatform;
@@ -141,11 +145,10 @@ protected:
friend class SBPlatform;
friend class SBTarget;
- lldb_private::ProcessLaunchInfo &ref();
-
const lldb_private::ProcessLaunchInfo &ref() const;
+ void set_ref(const lldb_private::ProcessLaunchInfo &info);
- ProcessLaunchInfoSP m_opaque_sp;
+ std::shared_ptr<lldb_private::SBLaunchInfoImpl> m_opaque_sp;
};
} // namespace lldb
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBModule.h b/contrib/llvm/tools/lldb/include/lldb/API/SBModule.h
index bcc3997a275b..d73267f8af50 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBModule.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBModule.h
@@ -129,6 +129,21 @@ public:
lldb::SBCompileUnit GetCompileUnitAtIndex(uint32_t);
+ //------------------------------------------------------------------
+ /// Find compile units related to *this module and passed source
+ /// file.
+ ///
+ /// @param[in] sb_file_spec
+ /// A lldb::SBFileSpec object that contains source file
+ /// specification.
+ ///
+ /// @return
+ /// A lldb::SBSymbolContextList that gets filled in with all of
+ /// the symbol contexts for all the matches.
+ //------------------------------------------------------------------
+ lldb::SBSymbolContextList
+ FindCompileUnits(const lldb::SBFileSpec &sb_file_spec);
+
size_t GetNumSymbols();
lldb::SBSymbol GetSymbolAtIndex(size_t idx);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h b/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h
index 2e8925941fb7..4ad24f63f076 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h
@@ -98,10 +98,10 @@ public:
lldb::SBThread GetSelectedThread() const;
//------------------------------------------------------------------
- // Function for lazily creating a thread using the current OS
- // plug-in. This function will be removed in the future when there
- // are APIs to create SBThread objects through the interface and add
- // them to the process through the SBProcess API.
+ // Function for lazily creating a thread using the current OS plug-in. This
+ // function will be removed in the future when there are APIs to create
+ // SBThread objects through the interface and add them to the process through
+ // the SBProcess API.
//------------------------------------------------------------------
lldb::SBThread CreateOSPluginThread(lldb::tid_t tid, lldb::addr_t context);
@@ -313,6 +313,40 @@ public:
const lldb::SBFileSpec &remote_image_spec,
lldb::SBError &error);
+ //------------------------------------------------------------------
+ /// Load a shared library into this process, starting with a
+ /// library name and a list of paths, searching along the list of
+ /// paths till you find a matching library.
+ ///
+ /// @param[in] local_spec
+ /// The name of the shared library that you want to load.
+ /// If local_spec is a relative path, the relative path will be
+ /// appended to the search paths.
+ /// If the local_spec is an absolute path, just the basename is used.
+ ///
+ /// @param[in] paths
+ /// A list of paths to search for the library whose basename is
+ /// local_spec.
+ ///
+ /// @param[out] loaded_path
+ /// If the library was found along the paths, this will store the
+ /// full path to the found library.
+ ///
+ /// @param[out] error
+ /// An error object that gets filled in with any errors that
+ /// might occur when trying to search for the shared library.
+ ///
+ /// @return
+ /// A token that represents the shared library that can be
+ /// later passed to UnloadImage. A value of
+ /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
+ /// library can't be opened.
+ //------------------------------------------------------------------
+ uint32_t LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
+ SBStringList &paths,
+ lldb::SBFileSpec &loaded_path,
+ lldb::SBError &error);
+
lldb::SBError UnloadImage(uint32_t image_token);
lldb::SBError SendEventData(const char *data);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h b/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h
index a75afc7ee375..7364ca7797f8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h
@@ -26,13 +26,12 @@ public:
bool IsValid() const;
- // If this stream is not redirected to a file, it will maintain a local
- // cache for the stream data which can be accessed using this accessor.
+ // If this stream is not redirected to a file, it will maintain a local cache
+ // for the stream data which can be accessed using this accessor.
const char *GetData();
- // If this stream is not redirected to a file, it will maintain a local
- // cache for the stream output whose length can be accessed using this
- // accessor.
+ // If this stream is not redirected to a file, it will maintain a local cache
+ // for the stream output whose length can be accessed using this accessor.
size_t GetSize();
void Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
@@ -44,8 +43,8 @@ public:
void RedirectToFileDescriptor(int fd, bool transfer_fh_ownership);
// If the stream is redirected to a file, forget about the file and if
- // ownership of the file was transferred to this object, close the file.
- // If the stream is backed by a local cache, clear this cache.
+ // ownership of the file was transferred to this object, close the file. If
+ // the stream is backed by a local cache, clear this cache.
void Clear();
protected:
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBStructuredData.h b/contrib/llvm/tools/lldb/include/lldb/API/SBStructuredData.h
index f3baaf7c4801..ca8229a574df 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBStructuredData.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBStructuredData.h
@@ -99,6 +99,7 @@ public:
protected:
friend class SBTraceOptions;
friend class SBDebugger;
+ friend class SBTarget;
StructuredDataImplUP m_impl_up;
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBSymbol.h b/contrib/llvm/tools/lldb/include/lldb/API/SBSymbol.h
index d17a4ccffe02..a29ac61d2912 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBSymbol.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBSymbol.h
@@ -55,8 +55,8 @@ public:
bool GetDescription(lldb::SBStream &description);
//----------------------------------------------------------------------
- // Returns true if the symbol is externally visible in the module that
- // it is defined in
+ // Returns true if the symbol is externally visible in the module that it is
+ // defined in
//----------------------------------------------------------------------
bool IsExternal();
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h b/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h
index 4085a16b43fb..8d99545902fe 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h
@@ -75,6 +75,8 @@ public:
lldb::SBProcess GetProcess();
+ lldb::SBStructuredData GetStatistics();
+
//------------------------------------------------------------------
/// Return the platform object associated with the target.
///
@@ -163,6 +165,7 @@ public:
bool stop_at_entry, lldb::SBError &error);
SBProcess LoadCore(const char *core_file);
+ SBProcess LoadCore(const char *core_file, lldb::SBError &error);
//------------------------------------------------------------------
/// Launch a new process with sensible defaults.
@@ -289,6 +292,21 @@ public:
lldb::SBModule FindModule(const lldb::SBFileSpec &file_spec);
+ //------------------------------------------------------------------
+ /// Find compile units related to *this target and passed source
+ /// file.
+ ///
+ /// @param[in] sb_file_spec
+ /// A lldb::SBFileSpec object that contains source file
+ /// specification.
+ ///
+ /// @return
+ /// A lldb::SBSymbolContextList that gets filled in with all of
+ /// the symbol contexts for all the matches.
+ //------------------------------------------------------------------
+ lldb::SBSymbolContextList
+ FindCompileUnits(const lldb::SBFileSpec &sb_file_spec);
+
lldb::ByteOrder GetByteOrder();
uint32_t GetAddressByteSize();
@@ -716,9 +734,9 @@ public:
// Finds all breakpoints by name, returning the list in bkpt_list. Returns
// false if the name is not a valid breakpoint name, true otherwise.
bool FindBreakpointsByName(const char *name, SBBreakpointList &bkpt_list);
-
+
void GetBreakpointNames(SBStringList &names);
-
+
void DeleteBreakpointName(const char *name);
bool EnableAllBreakpoints();
@@ -773,8 +791,7 @@ public:
const void *buf, size_t size);
// The "WithFlavor" is necessary to keep SWIG from getting confused about
- // overloaded arguments when
- // using the buf + size -> Python Object magic.
+ // overloaded arguments when using the buf + size -> Python Object magic.
lldb::SBInstructionList GetInstructionsWithFlavor(lldb::SBAddress base_addr,
const char *flavor_string,
@@ -827,8 +844,8 @@ protected:
friend class SBValue;
//------------------------------------------------------------------
- // Constructors are private, use static Target::Create function to
- // create an instance of this class.
+ // Constructors are private, use static Target::Create function to create an
+ // instance of this class.
//------------------------------------------------------------------
lldb::TargetSP GetSP() const;
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBThread.h b/contrib/llvm/tools/lldb/include/lldb/API/SBThread.h
index 7f1cf10cc456..afc05d2c61ad 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBThread.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBThread.h
@@ -93,6 +93,8 @@ public:
void StepOver(lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
+ void StepOver(lldb::RunMode stop_other_threads, SBError &error);
+
void StepInto(lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
void StepInto(const char *target_name,
@@ -103,10 +105,16 @@ public:
void StepOut();
- void StepOutOfFrame(lldb::SBFrame &frame);
+ void StepOut(SBError &error);
+
+ void StepOutOfFrame(SBFrame &frame);
+
+ void StepOutOfFrame(SBFrame &frame, SBError &error);
void StepInstruction(bool step_over);
+ void StepInstruction(bool step_over, SBError &error);
+
SBError StepOverUntil(lldb::SBFrame &frame, lldb::SBFileSpec &file_spec,
uint32_t line);
@@ -119,6 +127,8 @@ public:
void RunToAddress(lldb::addr_t addr);
+ void RunToAddress(lldb::addr_t addr, SBError &error);
+
SBError ReturnFromFrame(SBFrame &frame, SBValue &return_value);
SBError UnwindInnermostExpression();
@@ -146,8 +156,12 @@ public:
//--------------------------------------------------------------------------
bool Suspend();
+ bool Suspend(SBError &error);
+
bool Resume();
+ bool Resume(SBError &error);
+
bool IsSuspended();
bool IsStopped();
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h b/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h
index 5ef8915b58f9..ab5bdfea993d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h
@@ -134,8 +134,7 @@ public:
lldb::SBType type);
// this has no address! GetAddress() and GetLoadAddress() as well as
- // AddressOf()
- // on the return of this call all return invalid
+ // AddressOf() on the return of this call all return invalid
lldb::SBValue CreateValueFromData(const char *name, lldb::SBData data,
lldb::SBType type);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBValueList.h b/contrib/llvm/tools/lldb/include/lldb/API/SBValueList.h
index 495b0140cad0..0242dd7f71a2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBValueList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBValueList.h
@@ -43,8 +43,8 @@ public:
const lldb::SBValueList &operator=(const lldb::SBValueList &rhs);
protected:
- // only useful for visualizing the pointer or comparing two SBValueLists
- // to see if they are backed by the same underlying Impl.
+ // only useful for visualizing the pointer or comparing two SBValueLists to
+ // see if they are backed by the same underlying Impl.
void *opaque_ptr();
private:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h
index 9a798090a59f..ec4bc946280f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -33,8 +33,8 @@
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class Breakpoint Breakpoint.h "lldb/Breakpoint/Breakpoint.h"
-/// @brief Class that manages logical breakpoint setting.
+/// @class Breakpoint Breakpoint.h "lldb/Breakpoint/Breakpoint.h" Class that
+/// manages logical breakpoint setting.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -42,33 +42,28 @@ namespace lldb_private {
/// A breakpoint has four main parts, a filter, a resolver, the list of
/// breakpoint
/// locations that have been determined for the filter/resolver pair, and
-/// finally
-/// a set of options for the breakpoint.
+/// finally a set of options for the breakpoint.
///
/// \b Filter:
-/// This is an object derived from SearchFilter. It manages the search
-/// for breakpoint location matches through the symbols in the module list of
-/// the target
-/// that owns it. It also filters out locations based on whatever logic it
-/// wants.
+/// This is an object derived from SearchFilter. It manages the search for
+/// breakpoint location matches through the symbols in the module list of the
+/// target that owns it. It also filters out locations based on whatever
+/// logic it wants.
///
/// \b Resolver:
-/// This is an object derived from BreakpointResolver. It provides a
-/// callback to the filter that will find breakpoint locations. How it does
-/// this is
+/// This is an object derived from BreakpointResolver. It provides a callback
+/// to the filter that will find breakpoint locations. How it does this is
/// determined by what kind of resolver it is.
///
/// The Breakpoint class also provides constructors for the common breakpoint
-/// cases
-/// which make the appropriate filter and resolver for you.
+/// cases which make the appropriate filter and resolver for you.
///
/// \b Location List:
-/// This stores the breakpoint locations that have been determined
-/// to date. For a given breakpoint, there will be only one location with a
-/// given
-/// address. Adding a location at an already taken address will just return the
-/// location
-/// already at that address. Locations can be looked up by ID, or by address.
+/// This stores the breakpoint locations that have been determined to date.
+/// For a given breakpoint, there will be only one location with a given
+/// address. Adding a location at an already taken address will just return
+/// the location already at that address. Locations can be looked up by ID,
+/// or by address.
///
/// \b Options:
/// This includes:
@@ -77,25 +72,17 @@ namespace lldb_private {
/// \b Callback
/// \b Condition
/// Note, these options can be set on the breakpoint, and they can also be set
-/// on the
-/// individual locations. The options set on the breakpoint take precedence
-/// over the
-/// options set on the individual location.
-/// So for instance disabling the breakpoint will cause NONE of the locations to
-/// get hit.
-/// But if the breakpoint is enabled, then the location's enabled state will be
-/// checked
-/// to determine whether to insert that breakpoint location.
+/// on the individual locations. The options set on the breakpoint take
+/// precedence over the options set on the individual location. So for
+/// instance disabling the breakpoint will cause NONE of the locations to get
+/// hit. But if the breakpoint is enabled, then the location's enabled state
+/// will be checked to determine whether to insert that breakpoint location.
/// Similarly, if the breakpoint condition says "stop", we won't check the
-/// location's condition.
-/// But if the breakpoint condition says "continue", then we will check the
-/// location for whether
-/// to actually stop or not.
-/// One subtle point worth observing here is that you don't actually stop at a
-/// Breakpoint, you
-/// always stop at one of its locations. So the "should stop" tests are done by
-/// the location,
-/// not by the breakpoint.
+/// location's condition. But if the breakpoint condition says "continue",
+/// then we will check the location for whether to actually stop or not. One
+/// subtle point worth observing here is that you don't actually stop at a
+/// Breakpoint, you always stop at one of its locations. So the "should stop"
+/// tests are done by the location, not by the breakpoint.
//----------------------------------------------------------------------
class Breakpoint : public std::enable_shared_from_this<Breakpoint>,
public Stoppoint {
@@ -103,8 +90,8 @@ public:
static const ConstString &GetEventIdentifier();
//------------------------------------------------------------------
- /// An enum specifying the match style for breakpoint settings. At
- /// present only used for function name style breakpoints.
+ /// An enum specifying the match style for breakpoint settings. At present
+ /// only used for function name style breakpoints.
//------------------------------------------------------------------
typedef enum { Exact, Regexp, Glob } MatchType;
@@ -191,9 +178,9 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is not virtual since there should be no reason to subclass
- /// breakpoints. The varieties of breakpoints are specified instead by
- /// providing different resolvers & filters.
+ /// The destructor is not virtual since there should be no reason to
+ /// subclass breakpoints. The varieties of breakpoints are specified
+ /// instead by providing different resolvers & filters.
//------------------------------------------------------------------
~Breakpoint() override;
@@ -202,8 +189,7 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Tell whether this breakpoint is an "internal" breakpoint.
- /// @return
+ /// Tell whether this breakpoint is an "internal" breakpoint. @return
/// Returns \b true if this is an internal breakpoint, \b false otherwise.
//------------------------------------------------------------------
bool IsInternal() const;
@@ -214,13 +200,13 @@ public:
void Dump(Stream *s) override;
//------------------------------------------------------------------
- // The next set of methods provide ways to tell the breakpoint to update
- // it's location list - usually done when modules appear or disappear.
+ // The next set of methods provide ways to tell the breakpoint to update it's
+ // location list - usually done when modules appear or disappear.
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Tell this breakpoint to clear all its breakpoint sites. Done
- /// when the process holding the breakpoint sites is destroyed.
+ /// Tell this breakpoint to clear all its breakpoint sites. Done when the
+ /// process holding the breakpoint sites is destroyed.
//------------------------------------------------------------------
void ClearAllBreakpointSites();
@@ -231,8 +217,8 @@ public:
void ResolveBreakpoint();
//------------------------------------------------------------------
- /// Tell this breakpoint to scan a given module list and resolve any
- /// new locations that match the breakpoint's specifications.
+ /// Tell this breakpoint to scan a given module list and resolve any new
+ /// locations that match the breakpoint's specifications.
///
/// @param[in] module_list
/// The list of modules to look in for new locations.
@@ -245,8 +231,8 @@ public:
bool send_event = true);
//------------------------------------------------------------------
- /// Tell this breakpoint to scan a given module list and resolve any
- /// new locations that match the breakpoint's specifications.
+ /// Tell this breakpoint to scan a given module list and resolve any new
+ /// locations that match the breakpoint's specifications.
///
/// @param[in] changed_modules
/// The list of modules to look in for new locations.
@@ -274,9 +260,9 @@ public:
bool delete_locations = false);
//------------------------------------------------------------------
- /// Tells the breakpoint the old module \a old_module_sp has been
- /// replaced by new_module_sp (usually because the underlying file has been
- /// rebuilt, and the old version is gone.)
+ /// Tells the breakpoint the old module \a old_module_sp has been replaced
+ /// by new_module_sp (usually because the underlying file has been rebuilt,
+ /// and the old version is gone.)
///
/// @param[in] old_module_sp
/// The old module that is going away.
@@ -287,13 +273,13 @@ public:
lldb::ModuleSP new_module_sp);
//------------------------------------------------------------------
- // The next set of methods provide access to the breakpoint locations
- // for this breakpoint.
+ // The next set of methods provide access to the breakpoint locations for
+ // this breakpoint.
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Add a location to the breakpoint's location list. This is only meant
- /// to be called by the breakpoint's resolver. FIXME: how do I ensure that?
+ /// Add a location to the breakpoint's location list. This is only meant to
+ /// be called by the breakpoint's resolver. FIXME: how do I ensure that?
///
/// @param[in] addr
/// The Address specifying the new location.
@@ -359,12 +345,12 @@ public:
/// Removes all invalid breakpoint locations.
///
/// Removes all breakpoint locations with architectures that aren't
- /// compatible with \a arch. Also remove any breakpoint locations
- /// with whose locations have address where the section has been
- /// deleted (module and object files no longer exist).
+ /// compatible with \a arch. Also remove any breakpoint locations with whose
+ /// locations have address where the section has been deleted (module and
+ /// object files no longer exist).
///
- /// This is typically used after the process calls exec, or anytime
- /// the architecture of the target changes.
+ /// This is typically used after the process calls exec, or anytime the
+ /// architecture of the target changes.
///
/// @param[in] arch
/// If valid, check the module in each breakpoint to make sure
@@ -403,8 +389,7 @@ public:
uint32_t GetIgnoreCount() const;
//------------------------------------------------------------------
- /// Return the current hit count for all locations.
- /// @return
+ /// Return the current hit count for all locations. @return
/// The current hit count for all locations.
//------------------------------------------------------------------
uint32_t GetHitCount() const;
@@ -422,7 +407,8 @@ public:
bool IsOneShot() const;
//------------------------------------------------------------------
- /// If \a auto_continue is \b true, breakpoint will auto-continue when on hit.
+ /// If \a auto_continue is \b true, breakpoint will auto-continue when on
+ /// hit.
//------------------------------------------------------------------
void SetAutoContinue(bool auto_continue);
@@ -508,8 +494,8 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Return the number of breakpoint locations that have resolved to
- /// actual breakpoint sites.
+ /// Return the number of breakpoint locations that have resolved to actual
+ /// breakpoint sites.
///
/// @return
/// The number locations resolved breakpoint sites.
@@ -541,10 +527,9 @@ public:
//------------------------------------------------------------------
/// Set the "kind" description for a breakpoint. If the breakpoint is hit
- /// the stop info will show this "kind" description instead of the breakpoint
- /// number. Mostly useful for internal breakpoints, where the breakpoint
- /// number
- /// doesn't have meaning to the user.
+ /// the stop info will show this "kind" description instead of the
+ /// breakpoint number. Mostly useful for internal breakpoints, where the
+ /// breakpoint number doesn't have meaning to the user.
///
/// @param[in] kind
/// New "kind" description.
@@ -574,10 +559,9 @@ public:
//------------------------------------------------------------------
/// Find breakpoint locations which match the (filename, line_number)
- /// description.
- /// The breakpoint location collection is to be filled with the matching
- /// locations.
- /// It should be initialized with 0 size by the API client.
+ /// description. The breakpoint location collection is to be filled with the
+ /// matching locations. It should be initialized with 0 size by the API
+ /// client.
///
/// @return
/// True if there is a match
@@ -661,13 +645,12 @@ public:
/// Set a pre-condition filter that overrides all user provided
/// filters/callbacks etc.
///
- /// Used to define fancy breakpoints that can do dynamic hit detection without
- /// taking up the condition slot -
- /// which really belongs to the user anyway...
+ /// Used to define fancy breakpoints that can do dynamic hit detection
+ /// without taking up the condition slot - which really belongs to the user
+ /// anyway...
///
- /// The Precondition should not continue the target, it should return true if
- /// the condition says to stop and
- /// false otherwise.
+ /// The Precondition should not continue the target, it should return true
+ /// if the condition says to stop and false otherwise.
///
//------------------------------------------------------------------
void SetPrecondition(BreakpointPreconditionSP precondition_sp) {
@@ -706,10 +689,9 @@ protected:
//------------------------------------------------------------------
/// Constructors and Destructors
/// Only the Target can make a breakpoint, and it owns the breakpoint
- /// lifespans.
- /// The constructor takes a filter and a resolver. Up in Target there are
- /// convenience
- /// variants that make breakpoints for some common cases.
+ /// lifespans. The constructor takes a filter and a resolver. Up in Target
+ /// there are convenience variants that make breakpoints for some common
+ /// cases.
///
/// @param[in] target
/// The target in which the breakpoint will be set.
@@ -744,10 +726,10 @@ protected:
void DecrementIgnoreCount();
// BreakpointLocation::IgnoreCountShouldStop &
- // Breakpoint::IgnoreCountShouldStop can only be called once per stop,
- // and BreakpointLocation::IgnoreCountShouldStop should be tested first, and
- // if it returns false we should
- // continue, otherwise we should test Breakpoint::IgnoreCountShouldStop.
+ // Breakpoint::IgnoreCountShouldStop can only be called once per stop, and
+ // BreakpointLocation::IgnoreCountShouldStop should be tested first, and if
+ // it returns false we should continue, otherwise we should test
+ // Breakpoint::IgnoreCountShouldStop.
bool IgnoreCountShouldStop();
@@ -760,8 +742,7 @@ protected:
private:
// This one should only be used by Target to copy breakpoints from target to
- // target - primarily from the dummy
- // target to prime new targets.
+ // target - primarily from the dummy target to prime new targets.
Breakpoint(Target &new_target, Breakpoint &bp_to_copy_from);
//------------------------------------------------------------------
@@ -782,9 +763,9 @@ private:
BreakpointPreconditionSP m_precondition_sp; // The precondition is a
// breakpoint-level hit filter
// that can be used
- // to skip certain breakpoint hits. For instance, exception breakpoints
- // use this to limit the stop to certain exception classes, while leaving
- // the condition & callback free for user specification.
+ // to skip certain breakpoint hits. For instance, exception breakpoints use
+ // this to limit the stop to certain exception classes, while leaving the
+ // condition & callback free for user specification.
std::unique_ptr<BreakpointOptions>
m_options_up; // Settable breakpoint options
BreakpointLocationList
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointID.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointID.h
index 57411b316317..bbad45ca2d8b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointID.h
@@ -57,7 +57,7 @@ public:
//------------------------------------------------------------------
/// Takes an input string containing the description of a breakpoint or
- /// breakpoint and location and returns the a BreakpointID filled out with
+ /// breakpoint and location and returns a BreakpointID filled out with
/// the proper id and location.
///
/// @param[in] input
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointIDList.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointIDList.h
index 5877b6c551ad..ec305583e8d9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointIDList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointIDList.h
@@ -55,7 +55,7 @@ public:
bool FindBreakpointID(const char *bp_id, size_t *position) const;
- void InsertStringArray(const char **string_array, size_t array_size,
+ void InsertStringArray(llvm::ArrayRef<const char *> string_array,
CommandReturnObject &result);
// Returns a pair consisting of the beginning and end of a breakpoint
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointList.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointList.h
index 9f38f8aa120d..f4c013d41cc2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointList.h
@@ -23,7 +23,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointList BreakpointList.h "lldb/Breakpoint/BreakpointList.h"
-/// @brief This class manages a list of breakpoints.
+/// This class manages a list of breakpoints.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -91,7 +91,8 @@ public:
lldb::BreakpointSP GetBreakpointAtIndex(size_t i);
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint with index \a i, const version
+ /// Returns a shared pointer to the breakpoint with index \a i, const
+ /// version
///
/// @param[in] i
/// The breakpoint index to seek for.
@@ -138,13 +139,13 @@ public:
//------------------------------------------------------------------
/// Removes all invalid breakpoint locations.
///
- /// Removes all breakpoint locations in the list with architectures
- /// that aren't compatible with \a arch. Also remove any breakpoint
- /// locations with whose locations have address where the section
- /// has been deleted (module and object files no longer exist).
+ /// Removes all breakpoint locations in the list with architectures that
+ /// aren't compatible with \a arch. Also remove any breakpoint locations
+ /// with whose locations have address where the section has been deleted
+ /// (module and object files no longer exist).
///
- /// This is typically used after the process calls exec, or anytime
- /// the architecture of the target changes.
+ /// This is typically used after the process calls exec, or anytime the
+ /// architecture of the target changes.
///
/// @param[in] arch
/// If valid, check the module in each breakpoint to make sure
@@ -163,8 +164,8 @@ public:
//------------------------------------------------------------------
/// Removes all the breakpoints from this list - first checking the
- /// ePermDelete on the breakpoints. This call should be used unless you
- /// are shutting down and need to actually clear them all.
+ /// ePermDelete on the breakpoints. This call should be used unless you are
+ /// shutting down and need to actually clear them all.
//------------------------------------------------------------------
void RemoveAllowed(bool notify);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index b68a9ffad04c..c5911085e61b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -27,22 +27,20 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointLocation BreakpointLocation.h
-/// "lldb/Breakpoint/BreakpointLocation.h"
-/// @brief Class that manages one unique (by address) instance of a logical
-/// breakpoint.
+/// "lldb/Breakpoint/BreakpointLocation.h" Class that manages one unique (by
+/// address) instance of a logical breakpoint.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// General Outline:
/// A breakpoint location is defined by the breakpoint that produces it,
-/// and the address that resulted in this particular instantiation.
-/// Each breakpoint location also may have a breakpoint site if its
-/// address has been loaded into the program.
-/// Finally it has a settable options object.
+/// and the address that resulted in this particular instantiation. Each
+/// breakpoint location also may have a breakpoint site if its address has
+/// been loaded into the program. Finally it has a settable options object.
///
/// FIXME: Should we also store some fingerprint for the location, so
-/// we can map one location to the "equivalent location" on rerun? This
-/// would be useful if you've set options on the locations.
+/// we can map one location to the "equivalent location" on rerun? This would
+/// be useful if you've set options on the locations.
//----------------------------------------------------------------------
class BreakpointLocation
@@ -52,22 +50,19 @@ public:
~BreakpointLocation() override;
//------------------------------------------------------------------
- /// Gets the load address for this breakpoint location
- /// @return
+ /// Gets the load address for this breakpoint location @return
/// Returns breakpoint location load address, \b
/// LLDB_INVALID_ADDRESS if not yet set.
//------------------------------------------------------------------
lldb::addr_t GetLoadAddress() const override;
//------------------------------------------------------------------
- /// Gets the Address for this breakpoint location
- /// @return
+ /// Gets the Address for this breakpoint location @return
/// Returns breakpoint location Address.
//------------------------------------------------------------------
Address &GetAddress();
//------------------------------------------------------------------
- /// Gets the Breakpoint that created this breakpoint location
- /// @return
+ /// Gets the Breakpoint that created this breakpoint location @return
/// Returns the owning breakpoint.
//------------------------------------------------------------------
Breakpoint &GetBreakpoint();
@@ -75,12 +70,11 @@ public:
Target &GetTarget();
//------------------------------------------------------------------
- /// Determines whether we should stop due to a hit at this
- /// breakpoint location.
+ /// Determines whether we should stop due to a hit at this breakpoint
+ /// location.
///
- /// Side Effects: This may evaluate the breakpoint condition, and
- /// run the callback. So this command may do a considerable amount
- /// of work.
+ /// Side Effects: This may evaluate the breakpoint condition, and run the
+ /// callback. So this command may do a considerable amount of work.
///
/// @return
/// \b true if this breakpoint location thinks we should stop,
@@ -93,8 +87,7 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// If \a enable is \b true, enable the breakpoint, if \b false
- /// disable it.
+ /// If \a enable is \b true, enable the breakpoint, if \b false disable it.
//------------------------------------------------------------------
void SetEnabled(bool enabled);
@@ -138,8 +131,8 @@ public:
//------------------------------------------------------------------
/// Set the callback action invoked when the breakpoint is hit.
///
- /// The callback will return a bool indicating whether the target
- /// should stop at this breakpoint or not.
+ /// The callback will return a bool indicating whether the target should
+ /// stop at this breakpoint or not.
///
/// @param[in] callback
/// The method that will get called when the breakpoint is hit.
@@ -213,8 +206,8 @@ public:
bool ResolveBreakpointSite();
//------------------------------------------------------------------
- /// Clear this breakpoint location's breakpoint site - for instance
- /// when disabling the breakpoint.
+ /// Clear this breakpoint location's breakpoint site - for instance when
+ /// disabling the breakpoint.
///
/// @return
/// \b true if there was a breakpoint site to be cleared, \b false
@@ -223,8 +216,7 @@ public:
bool ClearBreakpointSite();
//------------------------------------------------------------------
- /// Return whether this breakpoint location has a breakpoint site.
- /// @return
+ /// Return whether this breakpoint location has a breakpoint site. @return
/// \b true if there was a breakpoint site for this breakpoint
/// location, \b false otherwise.
//------------------------------------------------------------------
@@ -237,8 +229,7 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Print a description of this breakpoint location to the stream
- /// \a s.
+ /// Print a description of this breakpoint location to the stream \a s.
///
/// @param[in] s
/// The stream to which to print the description.
@@ -259,8 +250,8 @@ public:
//------------------------------------------------------------------
/// Use this to set location specific breakpoint options.
///
- /// It will create a copy of the containing breakpoint's options if
- /// that hasn't been done already
+ /// It will create a copy of the containing breakpoint's options if that
+ /// hasn't been done already
///
/// @return
/// A pointer to the breakpoint options.
@@ -302,8 +293,7 @@ public:
//------------------------------------------------------------------
/// Returns whether we should resolve Indirect functions in setting the
- /// breakpoint site
- /// for this location.
+ /// breakpoint site for this location.
///
/// @return
/// \b true if the breakpoint SITE for this location should be set on the
@@ -315,8 +305,7 @@ public:
//------------------------------------------------------------------
/// Returns whether the address set in the breakpoint site for this location
- /// was found by resolving
- /// an indirect symbol.
+ /// was found by resolving an indirect symbol.
///
/// @return
/// \b true or \b false as given in the description above.
@@ -327,8 +316,7 @@ public:
//------------------------------------------------------------------
/// Returns whether the address set in the breakpoint location was re-routed
- /// to the target of a
- /// re-exported symbol.
+ /// to the target of a re-exported symbol.
///
/// @return
/// \b true or \b false as given in the description above.
@@ -339,10 +327,8 @@ public:
//------------------------------------------------------------------
/// Returns whether the two breakpoint locations might represent "equivalent
- /// locations".
- /// This is used when modules changed to determine if a Location in the old
- /// module might
- /// be the "same as" the input location.
+ /// locations". This is used when modules changed to determine if a Location
+ /// in the old module might be the "same as" the input location.
///
/// @param[in] location
/// The location to compare against.
@@ -384,8 +370,7 @@ private:
//------------------------------------------------------------------
// Constructors and Destructors
//
- // Only the Breakpoint can make breakpoint locations, and it owns
- // them.
+ // Only the Breakpoint can make breakpoint locations, and it owns them.
//------------------------------------------------------------------
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
index 4b2d9d4b344d..579d468647f3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
@@ -178,8 +178,8 @@ public:
protected:
//------------------------------------------------------------------
- // Classes that inherit from BreakpointLocationCollection can see
- // and modify these
+ // Classes that inherit from BreakpointLocationCollection can see and modify
+ // these
//------------------------------------------------------------------
private:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
index 46eb2612bbe8..4e61abb2838e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -26,21 +26,16 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointLocationList BreakpointLocationList.h
-/// "lldb/Breakpoint/BreakpointLocationList.h"
-/// @brief This class is used by Breakpoint to manage a list of breakpoint
-/// locations,
-// each breakpoint location in the list
-/// has a unique ID, and is unique by Address as well.
+/// "lldb/Breakpoint/BreakpointLocationList.h" This class is used by
+/// Breakpoint to manage a list of breakpoint locations, each breakpoint
+/// location in the list has a unique ID, and is unique by Address as well.
//----------------------------------------------------------------------
-
class BreakpointLocationList {
- // Only Breakpoints can make the location list, or add elements to it.
- // This is not just some random collection of locations. Rather, the act of
- // adding the location
- // to this list sets its ID, and implicitly all the locations have the same
- // breakpoint ID as
- // well. If you need a generic container for breakpoint locations, use
- // BreakpointLocationCollection.
+ // Only Breakpoints can make the location list, or add elements to it. This
+ // is not just some random collection of locations. Rather, the act of
+ // adding the location to this list sets its ID, and implicitly all the
+ // locations have the same breakpoint ID as well. If you need a generic
+ // container for breakpoint locations, use BreakpointLocationCollection.
friend class Breakpoint;
public:
@@ -52,8 +47,8 @@ public:
void Dump(Stream *s) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint location at address
- /// \a addr - const version.
+ /// Returns a shared pointer to the breakpoint location at address \a addr -
+ /// const version.
///
/// @param[in] addr
/// The address to look for.
@@ -65,8 +60,8 @@ public:
const lldb::BreakpointLocationSP FindByAddress(const Address &addr) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint location with id
- /// \a breakID, const version.
+ /// Returns a shared pointer to the breakpoint location with id \a breakID,
+ /// const version.
///
/// @param[in] breakID
/// The breakpoint location ID to seek for.
@@ -78,8 +73,8 @@ public:
lldb::BreakpointLocationSP FindByID(lldb::break_id_t breakID) const;
//------------------------------------------------------------------
- /// Returns the breakpoint location id to the breakpoint location
- /// at address \a addr.
+ /// Returns the breakpoint location id to the breakpoint location at address
+ /// \a addr.
///
/// @param[in] addr
/// The address to match.
@@ -90,9 +85,8 @@ public:
lldb::break_id_t FindIDByAddress(const Address &addr);
//------------------------------------------------------------------
- /// Returns a breakpoint location list of the breakpoint locations
- /// in the module \a module. This list is allocated, and owned by
- /// the caller.
+ /// Returns a breakpoint location list of the breakpoint locations in the
+ /// module \a module. This list is allocated, and owned by the caller.
///
/// @param[in] module
/// The module to seek in.
@@ -108,8 +102,7 @@ public:
BreakpointLocationCollection &bp_loc_list);
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint location with
- /// index \a i.
+ /// Returns a shared pointer to the breakpoint location with index \a i.
///
/// @param[in] i
/// The breakpoint location index to seek for.
@@ -121,8 +114,8 @@ public:
lldb::BreakpointLocationSP GetByIndex(size_t i);
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint location with index
- /// \a i, const version.
+ /// Returns a shared pointer to the breakpoint location with index \a i,
+ /// const version.
///
/// @param[in] i
/// The breakpoint location index to seek for.
@@ -134,20 +127,20 @@ public:
const lldb::BreakpointLocationSP GetByIndex(size_t i) const;
//------------------------------------------------------------------
- /// Removes all the locations in this list from their breakpoint site
- /// owners list.
+ /// Removes all the locations in this list from their breakpoint site owners
+ /// list.
//------------------------------------------------------------------
void ClearAllBreakpointSites();
//------------------------------------------------------------------
- /// Tells all the breakpoint locations in this list to attempt to
- /// resolve any possible breakpoint sites.
+ /// Tells all the breakpoint locations in this list to attempt to resolve
+ /// any possible breakpoint sites.
//------------------------------------------------------------------
void ResolveAllBreakpointSites();
//------------------------------------------------------------------
- /// Returns the number of breakpoint locations in this list with
- /// resolved breakpoints.
+ /// Returns the number of breakpoint locations in this list with resolved
+ /// breakpoints.
///
/// @result
/// Number of qualifying breakpoint locations.
@@ -163,8 +156,8 @@ public:
uint32_t GetHitCount() const;
//------------------------------------------------------------------
- /// Enquires of the breakpoint location in this list with ID \a
- /// breakID whether we should stop.
+ /// Enquires of the breakpoint location in this list with ID \a breakID
+ /// whether we should stop.
///
/// @param[in] context
/// This contains the information about this stop.
@@ -186,8 +179,8 @@ public:
size_t GetSize() const { return m_locations.size(); }
//------------------------------------------------------------------
- /// Print a description of the breakpoint locations in this list to
- /// the stream \a s.
+ /// Print a description of the breakpoint locations in this list to the
+ /// stream \a s.
///
/// @param[in] s
/// The stream to which to print the description.
@@ -204,9 +197,9 @@ protected:
//------------------------------------------------------------------
/// This is the standard constructor.
///
- /// It creates an empty breakpoint location list. It is protected
- /// here because only Breakpoints are allowed to create the
- /// breakpoint location list.
+ /// It creates an empty breakpoint location list. It is protected here
+ /// because only Breakpoints are allowed to create the breakpoint location
+ /// list.
//------------------------------------------------------------------
BreakpointLocationList(Breakpoint &owner);
@@ -235,6 +228,8 @@ protected:
lldb::BreakpointLocationSP from_location_sp);
bool RemoveLocation(const lldb::BreakpointLocationSP &bp_loc_sp);
+
+ void RemoveLocationByIndex(size_t idx);
void RemoveInvalidLocations(const ArchSpec &arch);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointName.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointName.h
index 1cfa141011a0..292a0de4f48b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointName.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointName.h
@@ -80,8 +80,8 @@ public:
*this = Permissions();
}
- // Merge the permissions from incoming into this set of permissions.
- // Only merge set permissions, and most restrictive permission wins.
+ // Merge the permissions from incoming into this set of permissions. Only
+ // merge set permissions, and most restrictive permission wins.
void MergeInto(const Permissions &incoming)
{
MergePermission(incoming, listPerm);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index 0229d52df471..84821817f980 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -27,9 +27,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointOptions BreakpointOptions.h
-/// "lldb/Breakpoint/BreakpointOptions.h"
-/// @brief Class that manages the options on a breakpoint or breakpoint
-/// location.
+/// "lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a
+/// breakpoint or breakpoint location.
//----------------------------------------------------------------------
class BreakpointOptions {
@@ -106,9 +105,8 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// This constructor allows you to specify all the breakpoint options
- /// except the callback. That one is more complicated, and better
- /// to do by hand.
+ /// This constructor allows you to specify all the breakpoint options except
+ /// the callback. That one is more complicated, and better to do by hand.
///
/// @param[in] condition
/// The expression which if it evaluates to \b true if we are to stop
@@ -125,8 +123,8 @@ public:
bool auto_continue = false);
//------------------------------------------------------------------
- /// Breakpoints make options with all flags set. Locations and Names make options
- /// with no flags set.
+ /// Breakpoints make options with all flags set. Locations and Names make
+ /// options with no flags set.
//------------------------------------------------------------------
BreakpointOptions(bool all_flags_set);
BreakpointOptions(const BreakpointOptions &rhs);
@@ -156,18 +154,16 @@ public:
// Callbacks
//
// Breakpoint callbacks come in two forms, synchronous and asynchronous.
- // Synchronous callbacks will get
- // run before any of the thread plans are consulted, and if they return false
- // the target will continue
- // "under the radar" of the thread plans. There are a couple of restrictions
- // to synchronous callbacks:
- // 1) They should NOT resume the target themselves. Just return false if you
- // want the target to restart.
- // 2) Breakpoints with synchronous callbacks can't have conditions (or rather,
- // they can have them, but they
- // won't do anything. Ditto with ignore counts, etc... You are supposed
- // to control that all through the
- // callback.
+ // Synchronous callbacks will get run before any of the thread plans are
+ // consulted, and if they return false the target will continue "under the
+ // radar" of the thread plans. There are a couple of restrictions to
+ // synchronous callbacks:
+ // 1) They should NOT resume the target themselves.
+ // Just return false if you want the target to restart.
+ // 2) Breakpoints with synchronous callbacks can't have conditions
+ // (or rather, they can have them, but they won't do anything.
+ // Ditto with ignore counts, etc... You are supposed to control that all
+ // through the callback.
// Asynchronous callbacks get run as part of the "ShouldStop" logic in the
// thread plan. The logic there is:
// a) If the breakpoint is thread specific and not for this thread, continue
@@ -181,12 +177,10 @@ public:
// b) If the ignore count says we shouldn't stop, then ditto.
// c) If the condition says we shouldn't stop, then ditto.
// d) Otherwise, the callback will get run, and if it returns true we will
- // stop, and if false we won't.
+ // stop, and if false we won't.
// The asynchronous callback can run the target itself, but at present that
- // should be the last action the
- // callback does. We will relax this condition at some point, but it will
- // take a bit of plumbing to get
- // that to work.
+ // should be the last action the callback does. We will relax this condition
+ // at some point, but it will take a bit of plumbing to get that to work.
//
//------------------------------------------------------------------
@@ -227,8 +221,8 @@ public:
//------------------------------------------------------------------
void ClearCallback();
- // The rest of these functions are meant to be used only within the breakpoint
- // handling mechanism.
+ // The rest of these functions are meant to be used only within the
+ // breakpoint handling mechanism.
//------------------------------------------------------------------
/// Use this function to invoke the callback for a specific stop.
@@ -367,8 +361,7 @@ public:
//------------------------------------------------------------------
/// Return the current thread spec for this option. This will return nullptr
- /// if the no thread
- /// specifications have been set for this Option yet.
+ /// if the no thread specifications have been set for this Option yet.
/// @return
/// The thread specification pointer for this option, or nullptr if none
/// has
@@ -377,8 +370,8 @@ public:
const ThreadSpec *GetThreadSpecNoCreate() const;
//------------------------------------------------------------------
- /// Returns a pointer to the ThreadSpec for this option, creating it.
- /// if it hasn't been created already. This API is used for setting the
+ /// Returns a pointer to the ThreadSpec for this option, creating it. if it
+ /// hasn't been created already. This API is used for setting the
/// ThreadSpec items for this option.
//------------------------------------------------------------------
ThreadSpec *GetThreadSpec();
@@ -400,8 +393,8 @@ public:
lldb::user_id_t break_loc_id);
//------------------------------------------------------------------
- /// Set a callback based on BreakpointOptions::CommandData.
- /// @param[in] cmd_data
+ /// Set a callback based on BreakpointOptions::CommandData. @param[in]
+ /// cmd_data
/// A UP holding the new'ed CommandData object.
/// The breakpoint will take ownership of pointer held by this object.
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h
index 7bcd889ce78b..944741308da6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h
@@ -26,24 +26,19 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointResolver BreakpointResolver.h
-/// "lldb/Breakpoint/BreakpointResolver.h"
-/// @brief This class works with SearchFilter to resolve logical breakpoints to
-/// their
-/// of concrete breakpoint locations.
+/// "lldb/Breakpoint/BreakpointResolver.h" This class works with SearchFilter
+/// to resolve logical breakpoints to their of concrete breakpoint locations.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// General Outline:
-/// The BreakpointResolver is a Searcher. In that protocol,
-/// the SearchFilter asks the question "At what depth of the symbol context
-/// descent do you want your callback to get called?" of the filter. The
-/// resolver
-/// answers this question (in the GetDepth method) and provides the resolution
-/// callback.
+/// The BreakpointResolver is a Searcher. In that protocol, the SearchFilter
+/// asks the question "At what depth of the symbol context descent do you want
+/// your callback to get called?" of the filter. The resolver answers this
+/// question (in the GetDepth method) and provides the resolution callback.
/// Each Breakpoint has a BreakpointResolver, and it calls either
-/// ResolveBreakpoint
-/// or ResolveBreakpointInModules to tell it to look for new breakpoint
-/// locations.
+/// ResolveBreakpoint or ResolveBreakpointInModules to tell it to look for new
+/// breakpoint locations.
//----------------------------------------------------------------------
class BreakpointResolver : public Searcher {
@@ -53,8 +48,7 @@ public:
//------------------------------------------------------------------
/// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint
/// to make sense. It can be constructed without a breakpoint, but you have
- /// to
- /// call SetBreakpoint before ResolveBreakpoint.
+ /// to call SetBreakpoint before ResolveBreakpoint.
///
/// @param[in] bkpt
/// The breakpoint that owns this resolver.
@@ -82,9 +76,9 @@ public:
void SetBreakpoint(Breakpoint *bkpt);
//------------------------------------------------------------------
- /// This updates the offset for this breakpoint. All the locations currently
- /// set for this breakpoint will have their offset adjusted when this is
- /// called.
+ /// This updates the offset for this breakpoint. All the locations
+ /// currently set for this breakpoint will have their offset adjusted when
+ /// this is called.
///
/// @param[in] offset
/// The offset to add to all locations.
@@ -92,9 +86,9 @@ public:
void SetOffset(lldb::addr_t offset);
//------------------------------------------------------------------
- /// This updates the offset for this breakpoint. All the locations currently
- /// set for this breakpoint will have their offset adjusted when this is
- /// called.
+ /// This updates the offset for this breakpoint. All the locations
+ /// currently set for this breakpoint will have their offset adjusted when
+ /// this is called.
///
/// @param[in] offset
/// The offset to add to all locations.
@@ -103,8 +97,7 @@ public:
//------------------------------------------------------------------
/// In response to this method the resolver scans all the modules in the
- /// breakpoint's
- /// target, and adds any new locations it finds.
+ /// breakpoint's target, and adds any new locations it finds.
///
/// @param[in] filter
/// The filter that will manage the search for this resolver.
@@ -113,8 +106,7 @@ public:
//------------------------------------------------------------------
/// In response to this method the resolver scans the modules in the module
- /// list
- /// \a modules, and adds any new locations it finds.
+ /// list \a modules, and adds any new locations it finds.
///
/// @param[in] filter
/// The filter that will manage the search for this resolver.
@@ -157,8 +149,8 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// An enumeration for keeping track of the concrete subclass that
- /// is actually instantiated. Values of this enumeration are kept in the
+ /// An enumeration for keeping track of the concrete subclass that is
+ /// actually instantiated. Values of this enumeration are kept in the
/// BreakpointResolver's SubclassID field. They are used for concrete type
/// identification.
enum ResolverTy {
@@ -171,8 +163,8 @@ public:
UnknownResolver
};
- // Translate the Ty to name for serialization,
- // the "+2" is one for size vrs. index, and one for UnknownResolver.
+ // Translate the Ty to name for serialization, the "+2" is one for size vrs.
+ // index, and one for UnknownResolver.
static const char *g_ty_to_name[LastKnownResolverType + 2];
//------------------------------------------------------------------
@@ -199,8 +191,8 @@ public:
protected:
// Used for serializing resolver options:
- // The options in this enum and the strings in the
- // g_option_names must be kept in sync.
+ // The options in this enum and the strings in the g_option_names must be
+ // kept in sync.
enum class OptionNames : uint32_t {
AddressOffset = 0,
ExactMatch,
@@ -227,12 +219,10 @@ public:
protected:
//------------------------------------------------------------------
- /// SetSCMatchesByLine - Takes a symbol context list of matches which
- /// supposedly represent the same file and
- /// line number in a CU, and find the nearest actual line number that matches,
- /// and then filter down the
- /// matching addresses to unique entries, and skip the prologue if asked to do
- /// so, and then set
+ /// Takes a symbol context list of matches which supposedly represent the
+ /// same file and line number in a CU, and find the nearest actual line
+ /// number that matches, and then filter down the matching addresses to
+ /// unique entries, and skip the prologue if asked to do so, and then set
/// breakpoint locations in this breakpoint for all the resultant addresses.
void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list,
bool skip_prologue, llvm::StringRef log_ident);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h
index 9d757c8853b9..5845fe7cabed 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h
@@ -21,10 +21,9 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointResolverAddress BreakpointResolverAddress.h
-/// "lldb/Breakpoint/BreakpointResolverAddress.h"
-/// @brief This class sets breakpoints on a given Address. This breakpoint only
-/// takes
-/// once, and then it won't attempt to reset itself.
+/// "lldb/Breakpoint/BreakpointResolverAddress.h" This class sets breakpoints
+/// on a given Address. This breakpoint only takes once, and then it won't
+/// attempt to reset itself.
//----------------------------------------------------------------------
class BreakpointResolverAddress : public BreakpointResolver {
@@ -74,8 +73,7 @@ protected:
FileSpec m_module_filespec; // If this filespec is Valid, and m_addr is an
// offset, then it will be converted
// to a Section+Offset address in this module, whenever that module gets
- // around to
- // being loaded.
+ // around to being loaded.
private:
DISALLOW_COPY_AND_ASSIGN(BreakpointResolverAddress);
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h
index f7bba3d4ccb4..3464f8ea80d8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h
@@ -20,10 +20,9 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointResolverFileLine BreakpointResolverFileLine.h
-/// "lldb/Breakpoint/BreakpointResolverFileLine.h"
-/// @brief This class sets breakpoints by file and line. Optionally, it will
-/// look for inlined
-/// instances of the file and line specification.
+/// "lldb/Breakpoint/BreakpointResolverFileLine.h" This class sets breakpoints
+/// by file and line. Optionally, it will look for inlined instances of the
+/// file and line specification.
//----------------------------------------------------------------------
class BreakpointResolverFileLine : public BreakpointResolver {
@@ -63,7 +62,7 @@ public:
lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override;
protected:
- void FilterContexts(SymbolContextList &sc_list);
+ void FilterContexts(SymbolContextList &sc_list, bool is_relative);
friend class Breakpoint;
FileSpec m_file_spec; // This is the file spec we are looking for.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
index d620e99ffc60..c1a7a15566a5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
@@ -23,9 +23,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointResolverFileRegex BreakpointResolverFileRegex.h
-/// "lldb/Breakpoint/BreakpointResolverFileRegex.h"
-/// @brief This class sets breakpoints by file and line. Optionally, it will
-/// look for inlined
+/// "lldb/Breakpoint/BreakpointResolverFileRegex.h" This class sets
+/// breakpoints by file and line. Optionally, it will look for inlined
/// instances of the file and line specification.
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
index c7716d5146ef..794ea67bb721 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
@@ -24,10 +24,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointResolverName BreakpointResolverName.h
-/// "lldb/Breakpoint/BreakpointResolverName.h"
-/// @brief This class sets breakpoints on a given function name, either by exact
-/// match
-/// or by regular expression.
+/// "lldb/Breakpoint/BreakpointResolverName.h" This class sets breakpoints on
+/// a given function name, either by exact match or by regular expression.
//----------------------------------------------------------------------
class BreakpointResolverName : public BreakpointResolver {
@@ -48,8 +46,8 @@ public:
uint32_t name_type_mask, lldb::LanguageType language,
lldb::addr_t offset, bool skip_prologue);
- // Creates a function breakpoint by regular expression. Takes over control of
- // the lifespan of func_regex.
+ // Creates a function breakpoint by regular expression. Takes over control
+ // of the lifespan of func_regex.
BreakpointResolverName(Breakpoint *bkpt, RegularExpression &func_regex,
lldb::LanguageType language, lldb::addr_t offset,
bool skip_prologue);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h
index 6e9875615fd9..c9bd883ca738 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h
@@ -28,15 +28,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointSite BreakpointSite.h "lldb/Breakpoint/BreakpointSite.h"
-/// @brief Class that manages the actual breakpoint that will be inserted
-/// into the running program.
+/// Class that manages the actual breakpoint that will be inserted into the
+/// running program.
///
-/// The BreakpointSite class handles the physical breakpoint that is
-/// actually inserted in the target program. As such, it is also the
-/// one that gets hit, when the program stops. It keeps a list of all
-/// BreakpointLocations that share this physical site. When the
-/// breakpoint is hit, all the locations are informed by the breakpoint
-/// site. Breakpoint sites are owned by the process.
+/// The BreakpointSite class handles the physical breakpoint that is actually
+/// inserted in the target program. As such, it is also the one that gets
+/// hit, when the program stops. It keeps a list of all BreakpointLocations
+/// that share this physical site. When the breakpoint is hit, all the
+/// locations are informed by the breakpoint site. Breakpoint sites are owned
+/// by the process.
//----------------------------------------------------------------------
class BreakpointSite : public std::enable_shared_from_this<BreakpointSite>,
@@ -101,10 +101,9 @@ public:
/// Tells whether the current breakpoint site is enabled or not
///
/// This is a low-level enable bit for the breakpoint sites. If a
- /// breakpoint site has no enabled owners, it should just get
- /// removed. This enable/disable is for the low-level target code
- /// to enable and disable breakpoint sites when single stepping,
- /// etc.
+ /// breakpoint site has no enabled owners, it should just get removed. This
+ /// enable/disable is for the low-level target code to enable and disable
+ /// breakpoint sites when single stepping, etc.
//------------------------------------------------------------------
bool IsEnabled() const;
@@ -118,8 +117,7 @@ public:
//------------------------------------------------------------------
/// Enquires of the breakpoint locations that produced this breakpoint site
- /// whether
- /// we should stop at this location.
+ /// whether we should stop at this location.
///
/// @param[in] context
/// This contains the information about this stop.
@@ -138,9 +136,8 @@ public:
void Dump(Stream *s) const override;
//------------------------------------------------------------------
- /// The "Owners" are the breakpoint locations that share this
- /// breakpoint site. The method adds the \a owner to this breakpoint
- /// site's owner list.
+ /// The "Owners" are the breakpoint locations that share this breakpoint
+ /// site. The method adds the \a owner to this breakpoint site's owner list.
///
/// @param[in] context
/// \a owner is the Breakpoint Location to add.
@@ -148,8 +145,8 @@ public:
void AddOwner(const lldb::BreakpointLocationSP &owner);
//------------------------------------------------------------------
- /// This method returns the number of breakpoint locations currently
- /// located at this breakpoint site.
+ /// This method returns the number of breakpoint locations currently located
+ /// at this breakpoint site.
///
/// @return
/// The number of owners.
@@ -157,10 +154,10 @@ public:
size_t GetNumberOfOwners();
//------------------------------------------------------------------
- /// This method returns the breakpoint location at index \a index
- /// located at this breakpoint site. The owners are listed ordinally
- /// from 0 to GetNumberOfOwners() - 1 so you can use this method to iterate
- /// over the owners
+ /// This method returns the breakpoint location at index \a index located at
+ /// this breakpoint site. The owners are listed ordinally from 0 to
+ /// GetNumberOfOwners() - 1 so you can use this method to iterate over the
+ /// owners
///
/// @param[in] index
/// The index in the list of owners for which you wish the owner location.
@@ -183,9 +180,9 @@ public:
size_t CopyOwnersList(BreakpointLocationCollection &out_collection);
//------------------------------------------------------------------
- /// Check whether the owners of this breakpoint site have any
- /// thread specifiers, and if yes, is \a thread contained in any
- /// of these specifiers.
+ /// Check whether the owners of this breakpoint site have any thread
+ /// specifiers, and if yes, is \a thread contained in any of these
+ /// specifiers.
///
/// @param[in] thread
/// The thread against which to test.
@@ -198,9 +195,9 @@ public:
//------------------------------------------------------------------
/// Print a description of this breakpoint site to the stream \a s.
- /// GetDescription tells you about the breakpoint site's owners.
- /// Use BreakpointSite::Dump(Stream *) to get information about the
- /// breakpoint site itself.
+ /// GetDescription tells you about the breakpoint site's owners. Use
+ /// BreakpointSite::Dump(Stream *) to get information about the breakpoint
+ /// site itself.
///
/// @param[in] s
/// The stream to which to print the description.
@@ -226,7 +223,8 @@ public:
bool IsBreakpointAtThisSite(lldb::break_id_t bp_id);
//------------------------------------------------------------------
- /// Tell whether ALL the breakpoints in the location collection are internal.
+ /// Tell whether ALL the breakpoints in the location collection are
+ /// internal.
///
/// @result
/// \b true if all breakpoint locations are owned by internal breakpoints,
@@ -241,15 +239,16 @@ public:
private:
friend class Process;
friend class BreakpointLocation;
- // The StopInfoBreakpoint knows when it is processing a hit for a thread for a
- // site, so let it be the
- // one to manage setting the location hit count once and only once.
+ // The StopInfoBreakpoint knows when it is processing a hit for a thread for
+ // a site, so let it be the one to manage setting the location hit count once
+ // and only once.
friend class StopInfoBreakpoint;
void BumpHitCounts();
//------------------------------------------------------------------
- /// The method removes the owner at \a break_loc_id from this breakpoint list.
+ /// The method removes the owner at \a break_loc_id from this breakpoint
+ /// list.
///
/// @param[in] context
/// \a break_loc_id is the Breakpoint Location to remove.
@@ -264,8 +263,8 @@ private:
bool
m_enabled; ///< Boolean indicating if this breakpoint site enabled or not.
- // Consider adding an optimization where if there is only one
- // owner, we don't store a list. The usual case will be only one owner...
+ // Consider adding an optimization where if there is only one owner, we don't
+ // store a list. The usual case will be only one owner...
BreakpointLocationCollection m_owners; ///< This has the BreakpointLocations
///that share this breakpoint site.
std::recursive_mutex
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSiteList.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSiteList.h
index 1431fe799675..d6530c170430 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSiteList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSiteList.h
@@ -24,8 +24,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class BreakpointSiteList BreakpointSiteList.h
-/// "lldb/Breakpoint/BreakpointSiteList.h"
-/// @brief Class that manages lists of BreakpointSite shared pointers.
+/// "lldb/Breakpoint/BreakpointSiteList.h" Class that manages lists of
+/// BreakpointSite shared pointers.
//----------------------------------------------------------------------
class BreakpointSiteList {
// At present Process directly accesses the map of BreakpointSites so it can
@@ -56,15 +56,13 @@ public:
lldb::break_id_t Add(const lldb::BreakpointSiteSP &bp_site_sp);
//------------------------------------------------------------------
- /// Standard Dump routine, doesn't do anything at present.
- /// @param[in] s
+ /// Standard Dump routine, doesn't do anything at present. @param[in] s
/// Stream into which to dump the description.
//------------------------------------------------------------------
void Dump(Stream *s) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint site at address
- /// \a addr.
+ /// Returns a shared pointer to the breakpoint site at address \a addr.
///
/// @param[in] addr
/// The address to look for.
@@ -89,8 +87,8 @@ public:
lldb::BreakpointSiteSP FindByID(lldb::break_id_t breakID);
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint site with id \a breakID - const
- /// version.
+ /// Returns a shared pointer to the breakpoint site with id \a breakID -
+ /// const version.
///
/// @param[in] breakID
/// The breakpoint site ID to seek for.
@@ -103,7 +101,8 @@ public:
const lldb::BreakpointSiteSP FindByID(lldb::break_id_t breakID) const;
//------------------------------------------------------------------
- /// Returns the breakpoint site id to the breakpoint site at address \a addr.
+ /// Returns the breakpoint site id to the breakpoint site at address \a
+ /// addr.
///
/// @param[in] addr
/// The address to match.
@@ -161,8 +160,8 @@ public:
void *baton);
//------------------------------------------------------------------
- /// Enquires of the breakpoint site on in this list with ID \a breakID whether
- /// we should stop for the breakpoint or not.
+ /// Enquires of the breakpoint site on in this list with ID \a breakID
+ /// whether we should stop for the breakpoint or not.
///
/// @param[in] context
/// This contains the information about this stop.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointCallbackContext.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointCallbackContext.h
index 2680584845d7..1dac342d3325 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointCallbackContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointCallbackContext.h
@@ -17,18 +17,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class StoppointCallbackContext StoppointCallbackContext.h
-/// "lldb/Breakpoint/StoppointCallbackContext.h"
-/// @brief Class holds the information that a breakpoint callback needs to
-/// evaluate this stop.
+/// "lldb/Breakpoint/StoppointCallbackContext.h" Class holds the information
+/// that a breakpoint callback needs to evaluate this stop.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// General Outline:
/// When we hit a breakpoint we need to package up whatever information is
-/// needed
-/// to evaluate breakpoint commands and conditions. This class is the container
-/// of
-/// that information.
+/// needed to evaluate breakpoint commands and conditions. This class is the
+/// container of that information.
//----------------------------------------------------------------------
class StoppointCallbackContext {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointLocation.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointLocation.h
index f64035bbb941..5c717bbc3b0f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointLocation.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/StoppointLocation.h
@@ -77,8 +77,8 @@ protected:
// breakpoint/watchpoint
uint32_t m_byte_size; // The size in bytes of stop location. e.g. the length
// of the trap opcode for
- // software breakpoints, or the optional length in bytes for
- // hardware breakpoints, or the length of the watchpoint.
+ // software breakpoints, or the optional length in bytes for hardware
+ // breakpoints, or the length of the watchpoint.
uint32_t
m_hit_count; // Number of times this breakpoint/watchpoint has been hit
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h
index 69067a567621..10df18a5c266 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h
@@ -71,9 +71,9 @@ public:
bool IsEnabled() const;
- // This doesn't really enable/disable the watchpoint.
- // It is currently just for use in the Process plugin's
- // {Enable,Disable}Watchpoint, which should be used instead.
+ // This doesn't really enable/disable the watchpoint. It is currently just
+ // for use in the Process plugin's {Enable,Disable}Watchpoint, which should
+ // be used instead.
void SetEnabled(bool enabled, bool notify = true);
@@ -197,10 +197,8 @@ private:
uint32_t m_disabled_count; // Keep track of the count that the watchpoint is
// disabled while in ephemeral mode.
// At the end of the ephemeral mode when the watchpoint is to be enabled
- // again,
- // we check the count, if it is more than 1, it means the user-supplied
- // actions
- // actually want the watchpoint to be disabled!
+ // again, we check the count, if it is more than 1, it means the user-
+ // supplied actions actually want the watchpoint to be disabled!
uint32_t m_watch_read : 1, // 1 if we stop when the watched data is read from
m_watch_write : 1, // 1 if we stop when the watched data is written to
m_watch_was_read : 1, // Set to 1 when watchpoint is hit for a read access
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointList.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointList.h
index 9abac9167b0b..d5e0da444afb 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointList.h
@@ -25,15 +25,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class WatchpointList WatchpointList.h "lldb/Breakpoint/WatchpointList.h"
-/// @brief This class is used by Watchpoint to manage a list of watchpoints,
+/// This class is used by Watchpoint to manage a list of watchpoints,
// each watchpoint in the list has a unique ID, and is unique by Address as
// well.
//----------------------------------------------------------------------
class WatchpointList {
- // Only Target can make the watchpoint list, or add elements to it.
- // This is not just some random collection of watchpoints. Rather, the act of
- // adding the watchpoint to this list sets its ID.
+ // Only Target can make the watchpoint list, or add elements to it. This is
+ // not just some random collection of watchpoints. Rather, the act of adding
+ // the watchpoint to this list sets its ID.
friend class Watchpoint;
friend class Target;
@@ -70,9 +70,8 @@ public:
void DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the watchpoint at address
- /// \a addr -
- /// const version.
+ /// Returns a shared pointer to the watchpoint at address \a addr - const
+ /// version.
///
/// @param[in] addr
/// The address to look for.
@@ -84,9 +83,8 @@ public:
const lldb::WatchpointSP FindByAddress(lldb::addr_t addr) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the watchpoint with watchpoint spec
- /// \a spec -
- /// const version.
+ /// Returns a shared pointer to the watchpoint with watchpoint spec \a spec
+ /// - const version.
///
/// @param[in] spec
/// The watchpoint spec to look for.
@@ -98,8 +96,7 @@ public:
const lldb::WatchpointSP FindBySpec(std::string spec) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the watchpoint with id
- /// \a watchID, const
+ /// Returns a shared pointer to the watchpoint with id \a watchID, const
/// version.
///
/// @param[in] watchID
@@ -112,8 +109,7 @@ public:
lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const;
//------------------------------------------------------------------
- /// Returns the watchpoint id to the watchpoint
- /// at address \a addr.
+ /// Returns the watchpoint id to the watchpoint at address \a addr.
///
/// @param[in] addr
/// The address to match.
@@ -124,8 +120,8 @@ public:
lldb::watch_id_t FindIDByAddress(lldb::addr_t addr);
//------------------------------------------------------------------
- /// Returns the watchpoint id to the watchpoint
- /// with watchpoint spec \a spec.
+ /// Returns the watchpoint id to the watchpoint with watchpoint spec \a
+ /// spec.
///
/// @param[in] spec
/// The watchpoint spec to match.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h
index 6ab1264a1c7f..8cb3b97f3a62 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h
@@ -25,8 +25,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class WatchpointOptions WatchpointOptions.h
-/// "lldb/Breakpoint/WatchpointOptions.h"
-/// @brief Class that manages the options on a watchpoint.
+/// "lldb/Breakpoint/WatchpointOptions.h" Class that manages the options on a
+/// watchpoint.
//----------------------------------------------------------------------
class WatchpointOptions {
@@ -69,15 +69,13 @@ public:
// Callbacks
//
// Watchpoint callbacks come in two forms, synchronous and asynchronous.
- // Synchronous callbacks will get
- // run before any of the thread plans are consulted, and if they return false
- // the target will continue
- // "under the radar" of the thread plans. There are a couple of restrictions
- // to synchronous callbacks:
- // 1) They should NOT resume the target themselves. Just return false if you
- // want the target to restart.
- // 2) Watchpoints with synchronous callbacks can't have conditions (or rather,
- // they can have them, but they
+ // Synchronous callbacks will get run before any of the thread plans are
+ // consulted, and if they return false the target will continue "under the
+ // radar" of the thread plans. There are a couple of restrictions to
+ // synchronous callbacks: 1) They should NOT resume the target themselves.
+ // Just return false if you want the target to restart. 2) Watchpoints with
+ // synchronous callbacks can't have conditions (or rather, they can have
+ // them, but they
// won't do anything. Ditto with ignore counts, etc... You are supposed
// to control that all through the
// callback.
@@ -118,8 +116,8 @@ public:
//------------------------------------------------------------------
void ClearCallback();
- // The rest of these functions are meant to be used only within the watchpoint
- // handling mechanism.
+ // The rest of these functions are meant to be used only within the
+ // watchpoint handling mechanism.
//------------------------------------------------------------------
/// Use this function to invoke the callback for a specific stop.
@@ -168,8 +166,7 @@ public:
//------------------------------------------------------------------
/// Return the current thread spec for this option. This will return nullptr
- /// if the no thread
- /// specifications have been set for this Option yet.
+ /// if the no thread specifications have been set for this Option yet.
/// @return
/// The thread specification pointer for this option, or nullptr if none
/// has
@@ -178,8 +175,8 @@ public:
const ThreadSpec *GetThreadSpecNoCreate() const;
//------------------------------------------------------------------
- /// Returns a pointer to the ThreadSpec for this option, creating it.
- /// if it hasn't been created already. This API is used for setting the
+ /// Returns a pointer to the ThreadSpec for this option, creating it. if it
+ /// hasn't been created already. This API is used for setting the
/// ThreadSpec items for this option.
//------------------------------------------------------------------
ThreadSpec *GetThreadSpec();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Address.h b/contrib/llvm/tools/lldb/include/lldb/Core/Address.h
index 4c77458061d0..617aaefe91c9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Address.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Address.h
@@ -11,8 +11,8 @@
#define liblldb_Address_h_
#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-enumerations.h" // for AddressClass::eAddressClassInvalid
#include "lldb/lldb-forward.h" // for SectionWP, SectionSP, ModuleSP
+#include "lldb/lldb-private-enumerations.h" // for AddressClass
#include "lldb/lldb-types.h" // for addr_t
#include <stddef.h> // for size_t
@@ -53,54 +53,50 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Address Address.h "lldb/Core/Address.h"
-/// @brief A section + offset based address class.
+/// A section + offset based address class.
///
-/// The Address class allows addresses to be relative to a section
-/// that can move during runtime due to images (executables, shared
-/// libraries, bundles, frameworks) being loaded at different
-/// addresses than the addresses found in the object file that
-/// represents them on disk. There are currently two types of addresses
-/// for a section:
+/// The Address class allows addresses to be relative to a section that can
+/// move during runtime due to images (executables, shared libraries, bundles,
+/// frameworks) being loaded at different addresses than the addresses found
+/// in the object file that represents them on disk. There are currently two
+/// types of addresses for a section:
/// @li file addresses
/// @li load addresses
///
-/// File addresses represent the virtual addresses that are in the "on
-/// disk" object files. These virtual addresses are converted to be
-/// relative to unique sections scoped to the object file so that
-/// when/if the addresses slide when the images are loaded/unloaded
-/// in memory, we can easily track these changes without having to
-/// update every object (compile unit ranges, line tables, function
-/// address ranges, lexical block and inlined subroutine address
-/// ranges, global and static variables) each time an image is loaded or
-/// unloaded.
+/// File addresses represent the virtual addresses that are in the "on disk"
+/// object files. These virtual addresses are converted to be relative to
+/// unique sections scoped to the object file so that when/if the addresses
+/// slide when the images are loaded/unloaded in memory, we can easily track
+/// these changes without having to update every object (compile unit ranges,
+/// line tables, function address ranges, lexical block and inlined subroutine
+/// address ranges, global and static variables) each time an image is loaded
+/// or unloaded.
///
-/// Load addresses represent the virtual addresses where each section
-/// ends up getting loaded at runtime. Before executing a program, it
-/// is common for all of the load addresses to be unresolved. When a
-/// DynamicLoader plug-in receives notification that shared libraries
-/// have been loaded/unloaded, the load addresses of the main executable
-/// and any images (shared libraries) will be resolved/unresolved. When
-/// this happens, breakpoints that are in one of these sections can be
-/// set/cleared.
+/// Load addresses represent the virtual addresses where each section ends up
+/// getting loaded at runtime. Before executing a program, it is common for
+/// all of the load addresses to be unresolved. When a DynamicLoader plug-in
+/// receives notification that shared libraries have been loaded/unloaded, the
+/// load addresses of the main executable and any images (shared libraries)
+/// will be resolved/unresolved. When this happens, breakpoints that are in
+/// one of these sections can be set/cleared.
//----------------------------------------------------------------------
class Address {
public:
//------------------------------------------------------------------
- /// Dump styles allow the Address::Dump(Stream *,DumpStyle) const
- /// function to display Address contents in a variety of ways.
+ /// Dump styles allow the Address::Dump(Stream *,DumpStyle) const function
+ /// to display Address contents in a variety of ways.
//------------------------------------------------------------------
typedef enum {
DumpStyleInvalid, ///< Invalid dump style
DumpStyleSectionNameOffset, ///< Display as the section name + offset.
///< \code
/// // address for printf in libSystem.B.dylib as a section name + offset
- /// libSystem.B.dylib.__TEXT.__text + 0x0005cfdf
- /// \endcode
+ /// libSystem.B.dylib.__TEXT.__text + 0x0005cfdf \endcode
DumpStyleSectionPointerOffset, ///< Display as the section pointer + offset
///(debug output).
///< \code
- /// // address for printf in libSystem.B.dylib as a section pointer + offset
- /// (lldb::Section *)0x35cc50 + 0x000000000005cfdf \endcode
+ /// // address for printf in libSystem.B.dylib as a section pointer +
+ /// offset (lldb::Section *)0x35cc50 + 0x000000000005cfdf \endcode
DumpStyleFileAddress, ///< Display as the file address (if any).
///< \code
/// // address for printf in libSystem.B.dylib as a file address
@@ -135,8 +131,8 @@ public:
//------------------------------------------------------------------
/// Default constructor.
///
- /// Initialize with a invalid section (NULL) and an invalid
- /// offset (LLDB_INVALID_ADDRESS).
+ /// Initialize with a invalid section (NULL) and an invalid offset
+ /// (LLDB_INVALID_ADDRESS).
//------------------------------------------------------------------
Address() : m_section_wp(), m_offset(LLDB_INVALID_ADDRESS) {}
@@ -154,8 +150,7 @@ public:
//------------------------------------------------------------------
/// Construct with a section pointer and offset.
///
- /// Initialize the address with the supplied \a section and \a
- /// offset.
+ /// Initialize the address with the supplied \a section and \a offset.
///
/// @param[in] section
/// A section pointer to a valid lldb::Section, or NULL if the
@@ -175,8 +170,8 @@ public:
//------------------------------------------------------------------
/// Construct with a virtual address and section list.
///
- /// Initialize and resolve the address with the supplied virtual
- /// address \a file_addr.
+ /// Initialize and resolve the address with the supplied virtual address \a
+ /// file_addr.
///
/// @param[in] file_addr
/// A virtual file address.
@@ -191,8 +186,8 @@ public:
//------------------------------------------------------------------
/// Assignment operator.
///
-/// Copies the address value from another Address object \a rhs
-/// into \a this object.
+/// Copies the address value from another Address object \a rhs into \a this
+/// object.
///
/// @param[in] rhs
/// A const Address object reference to copy.
@@ -207,8 +202,8 @@ public:
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Sets the section to an invalid value (NULL) and an invalid
- /// offset (LLDB_INVALID_ADDRESS).
+ /// Sets the section to an invalid value (NULL) and an invalid offset
+ /// (LLDB_INVALID_ADDRESS).
//------------------------------------------------------------------
void Clear() {
m_section_wp.reset();
@@ -250,9 +245,9 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s. There are many ways to display a section
- /// offset based address, and \a style lets the user choose.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s. There are many ways to display a section offset based address, and
+ /// \a style lets the user choose.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -275,14 +270,14 @@ public:
DumpStyle fallback_style = DumpStyleInvalid,
uint32_t addr_byte_size = UINT32_MAX) const;
- lldb::AddressClass GetAddressClass() const;
+ AddressClass GetAddressClass() const;
//------------------------------------------------------------------
/// Get the file address.
///
- /// If an address comes from a file on disk that has section
- /// relative addresses, then it has a virtual address that is
- /// relative to unique section in the object file.
+ /// If an address comes from a file on disk that has section relative
+ /// addresses, then it has a virtual address that is relative to unique
+ /// section in the object file.
///
/// @return
/// The valid file virtual address, or LLDB_INVALID_ADDRESS if
@@ -294,12 +289,12 @@ public:
//------------------------------------------------------------------
/// Get the load address.
///
- /// If an address comes from a file on disk that has section
- /// relative addresses, then it has a virtual address that is
- /// relative to unique section in the object file. Sections get
- /// resolved at runtime by DynamicLoader plug-ins as images
- /// (executables and shared libraries) get loaded/unloaded. If a
- /// section is loaded, then the load address can be resolved.
+ /// If an address comes from a file on disk that has section relative
+ /// addresses, then it has a virtual address that is relative to unique
+ /// section in the object file. Sections get resolved at runtime by
+ /// DynamicLoader plug-ins as images (executables and shared libraries) get
+ /// loaded/unloaded. If a section is loaded, then the load address can be
+ /// resolved.
///
/// @return
/// The valid load virtual address, or LLDB_INVALID_ADDRESS if
@@ -310,12 +305,12 @@ public:
//------------------------------------------------------------------
/// Get the load address as a callable code load address.
///
- /// This function will first resolve its address to a load address.
- /// Then, if the address turns out to be in code address, return the
- /// load address that would be required to call or return to. The
- /// address might have extra bits set (bit zero will be set to Thumb
- /// functions for an ARM target) that are required when changing the
- /// program counter to setting a return address.
+ /// This function will first resolve its address to a load address. Then, if
+ /// the address turns out to be in code address, return the load address
+ /// that would be required to call or return to. The address might have
+ /// extra bits set (bit zero will be set to Thumb functions for an ARM
+ /// target) that are required when changing the program counter to setting a
+ /// return address.
///
/// @return
/// The valid load virtual address, or LLDB_INVALID_ADDRESS if
@@ -327,14 +322,14 @@ public:
//------------------------------------------------------------------
/// Get the load address as an opcode load address.
///
- /// This function will first resolve its address to a load address.
- /// Then, if the address turns out to be in code address, return the
- /// load address for an opcode. This address object might have
- /// extra bits set (bit zero will be set to Thumb functions for an
+ /// This function will first resolve its address to a load address. Then, if
+ /// the address turns out to be in code address, return the load address for
+ /// an opcode. This address object might have extra bits set (bit zero will
+ /// be set to Thumb functions for an
/// ARM target) that are required for changing the program counter
- /// and this function will remove any bits that are intended for
- /// these special purposes. The result of this function can be used
- /// to safely write a software breakpoint trap to memory.
+ /// and this function will remove any bits that are intended for these
+ /// special purposes. The result of this function can be used to safely
+ /// write a software breakpoint trap to memory.
///
/// @return
/// The valid load virtual address with extra callable bits
@@ -343,7 +338,7 @@ public:
//------------------------------------------------------------------
lldb::addr_t GetOpcodeLoadAddress(
Target *target,
- lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
+ AddressClass addr_class = AddressClass::eInvalid) const;
//------------------------------------------------------------------
/// Get the section relative offset value.
@@ -357,11 +352,11 @@ public:
//------------------------------------------------------------------
/// Check if an address is section offset.
///
- /// When converting a virtual file or load address into a section
- /// offset based address, we often need to know if, given a section
- /// list, if the address was able to be converted to section offset.
- /// This function returns true if the current value contained in
- /// this object is section offset based.
+ /// When converting a virtual file or load address into a section offset
+ /// based address, we often need to know if, given a section list, if the
+ /// address was able to be converted to section offset. This function
+ /// returns true if the current value contained in this object is section
+ /// offset based.
///
/// @return
/// Returns \b true if the address has a valid section and
@@ -375,8 +370,8 @@ public:
/// Check if the object state is valid.
///
/// A valid Address object contains either a section pointer and
- /// and offset (for section offset based addresses), or just a valid
- /// offset (for absolute addresses that have no section).
+ /// offset (for section offset based addresses), or just a valid offset
+ /// (for absolute addresses that have no section).
///
/// @return
/// Returns \b true if the offset is valid, \b false
@@ -395,8 +390,8 @@ public:
//------------------------------------------------------------------
/// Resolve a file virtual address using a section list.
///
- /// Given a list of sections, attempt to resolve \a addr as a
- /// an offset into one of the file sections.
+ /// Given a list of sections, attempt to resolve \a addr as an offset into
+ /// one of the file sections.
///
/// @return
/// Returns \b true if \a addr was able to be resolved, \b false
@@ -408,11 +403,10 @@ public:
//------------------------------------------------------------------
/// Set the address to represent \a load_addr.
///
- /// The address will attempt to find a loaded section within
- /// \a target that contains \a load_addr. If successful, this
- /// address object will have a valid section and offset. Else this
- /// address object will have no section (NULL) and the offset will
- /// be \a load_addr.
+ /// The address will attempt to find a loaded section within \a target that
+ /// contains \a load_addr. If successful, this address object will have a
+ /// valid section and offset. Else this address object will have no section
+ /// (NULL) and the offset will be \a load_addr.
///
/// @param[in] load_addr
/// A load address from a current process.
@@ -438,7 +432,7 @@ public:
bool SetOpcodeLoadAddress(
lldb::addr_t load_addr, Target *target,
- lldb::AddressClass addr_class = lldb::eAddressClassInvalid,
+ AddressClass addr_class = AddressClass::eInvalid,
bool allow_section_end = false);
bool SetCallableLoadAddress(lldb::addr_t load_addr, Target *target);
@@ -507,10 +501,10 @@ public:
//------------------------------------------------------------------
/// Reconstruct a symbol context from an address.
///
- /// This class doesn't inherit from SymbolContextScope because many
- /// address objects have short lifespans. Address objects that are
- /// section offset can reconstruct their symbol context by looking
- /// up the address in the module found in the section.
+ /// This class doesn't inherit from SymbolContextScope because many address
+ /// objects have short lifespans. Address objects that are section offset
+ /// can reconstruct their symbol context by looking up the address in the
+ /// module found in the section.
///
/// @see SymbolContextScope::CalculateSymbolContext(SymbolContext*)
//------------------------------------------------------------------
@@ -531,11 +525,11 @@ public:
bool CalculateSymbolContextLineEntry(LineEntry &line_entry) const;
//------------------------------------------------------------------
- // Returns true if the section should be valid, but isn't because
- // the shared pointer to the section can't be reconstructed from
- // a weak pointer that contains a valid weak reference to a section.
- // Returns false if the section weak pointer has no reference to
- // a section, or if the section is still valid
+ // Returns true if the section should be valid, but isn't because the shared
+ // pointer to the section can't be reconstructed from a weak pointer that
+ // contains a valid weak reference to a section. Returns false if the section
+ // weak pointer has no reference to a section, or if the section is still
+ // valid
//------------------------------------------------------------------
bool SectionWasDeleted() const;
@@ -547,29 +541,27 @@ protected:
lldb::addr_t m_offset; ///< Offset into section if \a m_section_wp is valid...
//------------------------------------------------------------------
- // Returns true if the m_section_wp once had a reference to a valid
- // section shared pointer, but no longer does. This can happen if
- // we have an address from a module that gets unloaded and deleted.
- // This function should only be called if GetSection() returns an
- // empty shared pointer and you want to know if this address used to
- // have a valid section.
+ // Returns true if the m_section_wp once had a reference to a valid section
+ // shared pointer, but no longer does. This can happen if we have an address
+ // from a module that gets unloaded and deleted. This function should only be
+ // called if GetSection() returns an empty shared pointer and you want to
+ // know if this address used to have a valid section.
//------------------------------------------------------------------
bool SectionWasDeletedPrivate() const;
};
//----------------------------------------------------------------------
// NOTE: Be careful using this operator. It can correctly compare two
-// addresses from the same Module correctly. It can't compare two
-// addresses from different modules in any meaningful way, but it will
-// compare the module pointers.
+// addresses from the same Module correctly. It can't compare two addresses
+// from different modules in any meaningful way, but it will compare the module
+// pointers.
//
// To sum things up:
-// - works great for addresses within the same module
-// - it works for addresses across multiple modules, but don't expect the
+// - works great for addresses within the same module - it works for addresses
+// across multiple modules, but don't expect the
// address results to make much sense
//
-// This basically lets Address objects be used in ordered collection
-// classes.
+// This basically lets Address objects be used in ordered collection classes.
//----------------------------------------------------------------------
bool operator<(const Address &lhs, const Address &rhs);
bool operator>(const Address &lhs, const Address &rhs);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h
index e787d1d5740d..9f69c87ee354 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h
@@ -30,23 +30,23 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class AddressRange AddressRange.h "lldb/Core/AddressRange.h"
-/// @brief A section + offset based address range class.
+/// A section + offset based address range class.
//----------------------------------------------------------------------
class AddressRange {
public:
//------------------------------------------------------------------
/// Default constructor.
///
- /// Initialize with a invalid section (NULL), an invalid
- /// offset (LLDB_INVALID_ADDRESS), and zero byte size.
+ /// Initialize with a invalid section (NULL), an invalid offset
+ /// (LLDB_INVALID_ADDRESS), and zero byte size.
//------------------------------------------------------------------
AddressRange();
//------------------------------------------------------------------
/// Construct with a section pointer, offset, and byte_size.
///
- /// Initialize the address with the supplied \a section, \a
- /// offset and \a byte_size.
+ /// Initialize the address with the supplied \a section, \a offset and \a
+ /// byte_size.
///
/// @param[in] section
/// A section pointer to a valid lldb::Section, or NULL if the
@@ -64,8 +64,8 @@ public:
//------------------------------------------------------------------
/// Construct with a virtual address, section list and byte size.
///
- /// Initialize and resolve the address with the supplied virtual
- /// address \a file_addr, and byte size \a byte_size.
+ /// Initialize and resolve the address with the supplied virtual address \a
+ /// file_addr, and byte size \a byte_size.
///
/// @param[in] file_addr
/// A virtual address.
@@ -82,8 +82,8 @@ public:
//------------------------------------------------------------------
/// Construct with a Address object address and byte size.
///
- /// Initialize by copying the section offset address in \a so_addr,
- /// and setting the byte size to \a byte_size.
+ /// Initialize by copying the section offset address in \a so_addr, and
+ /// setting the byte size to \a byte_size.
///
/// @param[in] so_addr
/// A section offset address object.
@@ -135,8 +135,8 @@ public:
// Contains (const Address *so_addr_ptr) const;
//------------------------------------------------------------------
- /// Check if a section offset \a so_addr when represented as a file
- /// address is contained within this object's file address range.
+ /// Check if a section offset \a so_addr when represented as a file address
+ /// is contained within this object's file address range.
///
/// @param[in] so_addr
/// A section offset address object reference.
@@ -149,8 +149,8 @@ public:
bool ContainsFileAddress(const Address &so_addr) const;
//------------------------------------------------------------------
- /// Check if the resolved file address \a file_addr is contained
- /// within this object's file address range.
+ /// Check if the resolved file address \a file_addr is contained within this
+ /// object's file address range.
///
/// @param[in] so_addr
/// A section offset address object reference.
@@ -163,8 +163,8 @@ public:
bool ContainsFileAddress(lldb::addr_t file_addr) const;
//------------------------------------------------------------------
- /// Check if a section offset \a so_addr when represented as a load
- /// address is contained within this object's load address range.
+ /// Check if a section offset \a so_addr when represented as a load address
+ /// is contained within this object's load address range.
///
/// @param[in] so_addr
/// A section offset address object reference.
@@ -177,8 +177,8 @@ public:
bool ContainsLoadAddress(const Address &so_addr, Target *target) const;
//------------------------------------------------------------------
- /// Check if the resolved load address \a load_addr is contained
- /// within this object's load address range.
+ /// Check if the resolved load address \a load_addr is contained within this
+ /// object's load address range.
///
/// @param[in] so_addr
/// A section offset address object reference.
@@ -193,10 +193,10 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s. There are many ways to display a section
- /// offset based address range, and \a style lets the user choose
- /// how the base address gets displayed.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s. There are many ways to display a section offset based address
+ /// range, and \a style lets the user choose how the base address gets
+ /// displayed.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -219,11 +219,11 @@ public:
//------------------------------------------------------------------
/// Dump a debug description of this object to a Stream.
///
- /// Dump a debug description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a debug description of the contents of this object to the supplied
+ /// stream \a s.
///
- /// The debug description contains verbose internal state such
- /// and pointer values, reference counts, etc.
+ /// The debug description contains verbose internal state such and pointer
+ /// values, reference counts, etc.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -261,8 +261,8 @@ public:
/// The number of bytes that this object occupies in memory.
//------------------------------------------------------------------
size_t MemorySize() const {
- // Noting special for the memory size of a single AddressRange object,
- // it is just the size of itself.
+ // Noting special for the memory size of a single AddressRange object, it
+ // is just the size of itself.
return sizeof(AddressRange);
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h
index 432268e497b4..cfd103e0be01 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h
@@ -27,18 +27,16 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class AddressResolver AddressResolver.h "lldb/Core/AddressResolver.h"
-/// @brief This class works with SearchFilter to resolve function names and
-/// source file locations to their concrete addresses.
+/// This class works with SearchFilter to resolve function names and source
+/// file locations to their concrete addresses.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// General Outline:
-/// The AddressResolver is a Searcher. In that protocol,
-/// the SearchFilter asks the question "At what depth of the symbol context
-/// descent do you want your callback to get called?" of the filter. The
-/// resolver
-/// answers this question (in the GetDepth method) and provides the resolution
-/// callback.
+/// The AddressResolver is a Searcher. In that protocol, the SearchFilter
+/// asks the question "At what depth of the symbol context descent do you want
+/// your callback to get called?" of the filter. The resolver answers this
+/// question (in the GetDepth method) and provides the resolution callback.
//----------------------------------------------------------------------
class AddressResolver : public Searcher {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h
index ec15cc76d887..e434a62e0319 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h
@@ -31,10 +31,9 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class AddressResolverFileLine AddressResolverFileLine.h
-/// "lldb/Core/AddressResolverFileLine.h"
-/// @brief This class finds address for source file and line. Optionally, it
-/// will look for inlined
-/// instances of the file and line specification.
+/// "lldb/Core/AddressResolverFileLine.h" This class finds address for source
+/// file and line. Optionally, it will look for inlined instances of the file
+/// and line specification.
//----------------------------------------------------------------------
class AddressResolverFileLine : public AddressResolver {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h
index aadc05495999..49a805f2115a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h
@@ -30,10 +30,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class AddressResolverName AddressResolverName.h
-/// "lldb/Core/AddressResolverName.h"
-/// @brief This class finds addresses for a given function name, either by exact
-/// match
-/// or by regular expression.
+/// "lldb/Core/AddressResolverName.h" This class finds addresses for a given
+/// function name, either by exact match or by regular expression.
//----------------------------------------------------------------------
class AddressResolverName : public AddressResolver {
@@ -41,8 +39,8 @@ public:
AddressResolverName(const char *func_name,
AddressResolver::MatchType type = Exact);
- // Creates a function breakpoint by regular expression. Takes over control of
- // the lifespan of func_regex.
+ // Creates a function breakpoint by regular expression. Takes over control
+ // of the lifespan of func_regex.
AddressResolverName(RegularExpression &func_regex);
AddressResolverName(const char *class_name, const char *method,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Architecture.h b/contrib/llvm/tools/lldb/include/lldb/Core/Architecture.h
index af774ecdaf9c..3a5a9789223d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Architecture.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Architecture.h
@@ -31,7 +31,41 @@ public:
/// stopped at the current PC. The code is generic and applies to all
/// ARM CPUs.
//------------------------------------------------------------------
- virtual void OverrideStopInfo(Thread &thread) = 0;
+ virtual void OverrideStopInfo(Thread &thread) const = 0;
+
+ //------------------------------------------------------------------
+ /// This method is used to get the number of bytes that should be
+ /// skipped, from function start address, to reach the first
+ /// instruction after the prologue. If overrode, it must return
+ /// non-zero only if the current address matches one of the known
+ /// function entry points.
+ ///
+ /// This method is called only if the standard platform-independent
+ /// code fails to get the number of bytes to skip, giving the plugin
+ /// a chance to try to find the missing info.
+ ///
+ /// This is specifically used for PPC64, where functions may have
+ /// more than one entry point, global and local, so both should
+ /// be compared with current address, in order to find out the
+ /// number of bytes that should be skipped, in case we are stopped
+ /// at either function entry point.
+ //------------------------------------------------------------------
+ virtual size_t GetBytesToSkip(Symbol &func, const Address &curr_addr) const {
+ return 0;
+ }
+
+ //------------------------------------------------------------------
+ /// Adjust function breakpoint address, if needed. In some cases,
+ /// the function start address is not the right place to set the
+ /// breakpoint, specially in functions with multiple entry points.
+ ///
+ /// This is specifically used for PPC64, for functions that have
+ /// both a global and a local entry point. In this case, the
+ /// breakpoint is adjusted to the first function address reached
+ /// by both entry points.
+ //------------------------------------------------------------------
+ virtual void AdjustBreakpointAddress(const Symbol &func,
+ Address &addr) const {}
private:
Architecture(const Architecture &) = delete;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h b/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h
index 825287db5984..4851007c9a2a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h
@@ -59,10 +59,9 @@ public:
uint32_t GetEventBits() const { return m_event_bits; }
- // Tell whether this BroadcastEventSpec is contained in in_spec.
- // That is:
- // (a) the two spec's share the same broadcaster class
- // (b) the event bits of this spec are wholly contained in those of in_spec.
+ // Tell whether this BroadcastEventSpec is contained in in_spec. That is: (a)
+ // the two spec's share the same broadcaster class (b) the event bits of this
+ // spec are wholly contained in those of in_spec.
bool IsContainedIn(BroadcastEventSpec in_spec) const {
if (m_broadcaster_class != in_spec.GetBroadcasterClass())
return false;
@@ -224,21 +223,21 @@ private:
};
//----------------------------------------------------------------------
-/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h"
-/// @brief An event broadcasting class.
+/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h" An event
+/// broadcasting class.
///
-/// The Broadcaster class is designed to be subclassed by objects that
-/// wish to vend events in a multi-threaded environment. Broadcaster
-/// objects can each vend 32 events. Each event is represented by a bit
-/// in a 32 bit value and these bits can be set:
+/// The Broadcaster class is designed to be subclassed by objects that wish to
+/// vend events in a multi-threaded environment. Broadcaster objects can each
+/// vend 32 events. Each event is represented by a bit in a 32 bit value and
+/// these bits can be set:
/// @see Broadcaster::SetEventBits(uint32_t)
/// or cleared:
/// @see Broadcaster::ResetEventBits(uint32_t)
-/// When an event gets set the Broadcaster object will notify the
-/// Listener object that is listening for the event (if there is one).
+/// When an event gets set the Broadcaster object will notify the Listener
+/// object that is listening for the event (if there is one).
///
-/// Subclasses should provide broadcast bit definitions for any events
-/// they vend, typically using an enumeration:
+/// Subclasses should provide broadcast bit definitions for any events they
+/// vend, typically using an enumeration:
/// \code
/// class Foo : public Broadcaster
/// {
@@ -324,12 +323,11 @@ public:
//------------------------------------------------------------------
/// Listen for any events specified by \a event_mask.
///
- /// Only one listener can listen to each event bit in a given
- /// Broadcaster. Once a listener has acquired an event bit, no
- /// other broadcaster will have access to it until it is
- /// relinquished by the first listener that gets it. The actual
- /// event bits that get acquired by \a listener may be different
- /// from what is requested in \a event_mask, and to track this the
+ /// Only one listener can listen to each event bit in a given Broadcaster.
+ /// Once a listener has acquired an event bit, no other broadcaster will
+ /// have access to it until it is relinquished by the first listener that
+ /// gets it. The actual event bits that get acquired by \a listener may be
+ /// different from what is requested in \a event_mask, and to track this the
/// actual event bits that are acquired get returned.
///
/// @param[in] listener
@@ -349,8 +347,7 @@ public:
}
//------------------------------------------------------------------
- /// Get the NULL terminated C string name of this Broadcaster
- /// object.
+ /// Get the NULL terminated C string name of this Broadcaster object.
///
/// @return
/// The NULL terminated C string name of this Broadcaster.
@@ -395,10 +392,10 @@ public:
}
//------------------------------------------------------------------
- /// Removes a Listener from this broadcasters list and frees the
- /// event bits specified by \a event_mask that were previously
- /// acquired by \a listener (assuming \a listener was listening to
- /// this object) for other listener objects to use.
+ /// Removes a Listener from this broadcasters list and frees the event bits
+ /// specified by \a event_mask that were previously acquired by \a listener
+ /// (assuming \a listener was listening to this object) for other listener
+ /// objects to use.
///
/// @param[in] listener
/// A Listener object that previously called AddListener.
@@ -420,10 +417,9 @@ public:
//------------------------------------------------------------------
/// Provides a simple mechanism to temporarily redirect events from
/// broadcaster. When you call this function passing in a listener and
- /// event type mask, all events from the broadcaster matching the mask
- /// will now go to the hijacking listener.
- /// Only one hijack can occur at a time. If we need more than this we
- /// will have to implement a Listener stack.
+ /// event type mask, all events from the broadcaster matching the mask will
+ /// now go to the hijacking listener. Only one hijack can occur at a time.
+ /// If we need more than this we will have to implement a Listener stack.
///
/// @param[in] listener
/// A Listener object. You do not need to call StartListeningForEvents
@@ -454,8 +450,7 @@ public:
void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); }
// This needs to be filled in if you are going to register the broadcaster
- // with the broadcaster
- // manager and do broadcaster class matching.
+ // with the broadcaster manager and do broadcaster class matching.
// FIXME: Probably should make a ManagedBroadcaster subclass with all the bits
// needed to work
// with the BroadcasterManager, so that it is clearer how to add one.
@@ -465,21 +460,17 @@ public:
protected:
// BroadcasterImpl contains the actual Broadcaster implementation. The
- // Broadcaster makes a BroadcasterImpl
- // which lives as long as it does. The Listeners & the Events hold a weak
- // pointer to the BroadcasterImpl,
- // so that they can survive if a Broadcaster they were listening to is
- // destroyed w/o their being able to
- // unregister from it (which can happen if the Broadcasters & Listeners are
- // being destroyed on separate threads
- // simultaneously.
- // The Broadcaster itself can't be shared out as a weak pointer, because some
- // things that are broadcasters
- // (e.g. the Target and the Process) are shared in their own right.
+ // Broadcaster makes a BroadcasterImpl which lives as long as it does. The
+ // Listeners & the Events hold a weak pointer to the BroadcasterImpl, so that
+ // they can survive if a Broadcaster they were listening to is destroyed w/o
+ // their being able to unregister from it (which can happen if the
+ // Broadcasters & Listeners are being destroyed on separate threads
+ // simultaneously. The Broadcaster itself can't be shared out as a weak
+ // pointer, because some things that are broadcasters (e.g. the Target and
+ // the Process) are shared in their own right.
//
// For the most part, the Broadcaster functions dispatch to the
- // BroadcasterImpl, and are documented in the
- // public Broadcaster API above.
+ // BroadcasterImpl, and are documented in the public Broadcaster API above.
class BroadcasterImpl {
friend class Listener;
@@ -557,7 +548,7 @@ protected:
llvm::SmallVector<std::pair<lldb::ListenerSP, uint32_t &>, 4>
GetListeners();
- Broadcaster &m_broadcaster; ///< The broadcsater that this implements
+ Broadcaster &m_broadcaster; ///< The broadcaster that this implements
event_names_map m_event_names; ///< Optionally define event names for
///readability and logging for each event bit
collection m_listeners; ///< A list of Listener / event_mask pairs that are
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h b/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h
index 57fa483bd3a3..3e29307039e4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h
@@ -39,60 +39,57 @@ class Status;
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class Communication Communication.h "lldb/Core/Communication.h"
-/// @brief An abstract communications class.
+/// @class Communication Communication.h "lldb/Core/Communication.h" An
+/// abstract communications class.
///
-/// Communication is an class that handles data communication
-/// between two data sources. It uses a Connection class to do the
-/// real communication. This approach has a couple of advantages: it
-/// allows a single instance of this class to be used even though its
-/// connection can change. Connections could negotiate for different
-/// connections based on abilities like starting with Bluetooth and
-/// negotiating up to WiFi if available. It also allows this class to be
-/// subclassed by any interfaces that don't want to give bytes but want
-/// to validate and give out packets. This can be done by overriding:
+/// Communication is an class that handles data communication between two data
+/// sources. It uses a Connection class to do the real communication. This
+/// approach has a couple of advantages: it allows a single instance of this
+/// class to be used even though its connection can change. Connections could
+/// negotiate for different connections based on abilities like starting with
+/// Bluetooth and negotiating up to WiFi if available. It also allows this
+/// class to be subclassed by any interfaces that don't want to give bytes but
+/// want to validate and give out packets. This can be done by overriding:
///
/// AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast);
///
-/// Communication inherits from Broadcaster which means it can be
-/// used in conjunction with Listener to wait for multiple broadcaster
-/// objects and multiple events from each of those objects.
-/// Communication defines a set of pre-defined event bits (see
-/// enumerations definitions that start with "eBroadcastBit" below).
+/// Communication inherits from Broadcaster which means it can be used in
+/// conjunction with Listener to wait for multiple broadcaster objects and
+/// multiple events from each of those objects. Communication defines a set of
+/// pre-defined event bits (see enumerations definitions that start with
+/// "eBroadcastBit" below).
///
/// There are two modes in which communications can occur:
/// @li single-threaded
/// @li multi-threaded
///
-/// In single-threaded mode, all reads and writes happen synchronously
-/// on the calling thread.
+/// In single-threaded mode, all reads and writes happen synchronously on the
+/// calling thread.
///
-/// In multi-threaded mode, a read thread is spawned that continually
-/// reads data and caches any received bytes. To start the read thread
-/// clients call:
+/// In multi-threaded mode, a read thread is spawned that continually reads
+/// data and caches any received bytes. To start the read thread clients call:
///
/// bool Communication::StartReadThread (Status *);
///
-/// If true is returned a read thread has been spawned that will
-/// continually execute a call to the pure virtual DoRead function:
+/// If true is returned a read thread has been spawned that will continually
+/// execute a call to the pure virtual DoRead function:
///
/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t);
///
-/// When bytes are received the data gets cached in \a m_bytes and this
-/// class will broadcast a \b eBroadcastBitReadThreadGotBytes event.
-/// Clients that want packet based communication should override
-/// AppendBytesToCache. The subclasses can choose to call the
-/// built in AppendBytesToCache with the \a broadcast parameter set to
-/// false. This will cause the \b eBroadcastBitReadThreadGotBytes event
-/// not get broadcast, and then the subclass can post a \b
-/// eBroadcastBitPacketAvailable event when a full packet of data has
-/// been received.
+/// When bytes are received the data gets cached in \a m_bytes and this class
+/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that
+/// want packet based communication should override AppendBytesToCache. The
+/// subclasses can choose to call the built in AppendBytesToCache with the \a
+/// broadcast parameter set to false. This will cause the \b
+/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the
+/// subclass can post a \b eBroadcastBitPacketAvailable event when a full
+/// packet of data has been received.
///
-/// If the connection is disconnected a \b eBroadcastBitDisconnected
-/// event gets broadcast. If the read thread exits a \b
-/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients
-/// can also post a \b eBroadcastBitReadThreadShouldExit event to this
-/// object which will cause the read thread to exit.
+/// If the connection is disconnected a \b eBroadcastBitDisconnected event
+/// gets broadcast. If the read thread exits a \b
+/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also
+/// post a \b eBroadcastBitReadThreadShouldExit event to this object which
+/// will cause the read thread to exit.
//----------------------------------------------------------------------
class Communication : public Broadcaster {
public:
@@ -120,8 +117,8 @@ public:
size_t src_len);
//------------------------------------------------------------------
- /// Construct the Communication object with the specified name for
- /// the Broadcaster that this object inherits from.
+ /// Construct the Communication object with the specified name for the
+ /// Broadcaster that this object inherits from.
///
/// @param[in] broadcaster_name
/// The name of the broadcaster object. This name should be as
@@ -141,9 +138,8 @@ public:
void Clear();
//------------------------------------------------------------------
- /// Connect using the current connection by passing \a url to its
- /// connect function.
- /// string.
+ /// Connect using the current connection by passing \a url to its connect
+ /// function. string.
///
/// @param[in] url
/// A string that contains all information needed by the
@@ -160,8 +156,7 @@ public:
lldb::ConnectionStatus Connect(const char *url, Status *error_ptr);
//------------------------------------------------------------------
- /// Disconnect the communications connection if one is currently
- /// connected.
+ /// Disconnect the communications connection if one is currently connected.
///
/// @return
/// \b True if the disconnect succeeded, \b false otherwise. The
@@ -189,16 +184,15 @@ public:
//------------------------------------------------------------------
/// Read bytes from the current connection.
///
- /// If no read thread is running, this function call the
- /// connection's Connection::Read(...) function to get any available.
+ /// If no read thread is running, this function call the connection's
+ /// Connection::Read(...) function to get any available.
///
- /// If a read thread has been started, this function will check for
- /// any cached bytes that have already been read and return any
- /// currently available bytes. If no bytes are cached, it will wait
- /// for the bytes to become available by listening for the \a
- /// eBroadcastBitReadThreadGotBytes event. If this function consumes
- /// all of the bytes in the cache, it will reset the
- /// \a eBroadcastBitReadThreadGotBytes event bit.
+ /// If a read thread has been started, this function will check for any
+ /// cached bytes that have already been read and return any currently
+ /// available bytes. If no bytes are cached, it will wait for the bytes to
+ /// become available by listening for the \a eBroadcastBitReadThreadGotBytes
+ /// event. If this function consumes all of the bytes in the cache, it will
+ /// reset the \a eBroadcastBitReadThreadGotBytes event bit.
///
/// @param[in] dst
/// A destination buffer that must be at least \a dst_len bytes
@@ -220,8 +214,8 @@ public:
lldb::ConnectionStatus &status, Status *error_ptr);
//------------------------------------------------------------------
- /// The actual write function that attempts to write to the
- /// communications protocol.
+ /// The actual write function that attempts to write to the communications
+ /// protocol.
///
/// Subclasses must override this function.
///
@@ -242,11 +236,10 @@ public:
//------------------------------------------------------------------
/// Sets the connection that it to be used by this class.
///
- /// By making a communication class that uses different connections
- /// it allows a single communication interface to negotiate and
- /// change its connection without any interruption to the client.
- /// It also allows the Communication class to be subclassed for
- /// packet based communication.
+ /// By making a communication class that uses different connections it
+ /// allows a single communication interface to negotiate and change its
+ /// connection without any interruption to the client. It also allows the
+ /// Communication class to be subclassed for packet based communication.
///
/// @param[in] connection
/// A connection that this class will own and destroy.
@@ -257,19 +250,19 @@ public:
void SetConnection(Connection *connection);
//------------------------------------------------------------------
- /// Starts a read thread whose sole purpose it to read bytes from
- /// the current connection. This function will call connection's
- /// read function:
+ /// Starts a read thread whose sole purpose it to read bytes from the
+ /// current connection. This function will call connection's read function:
///
/// size_t Connection::Read (void *, size_t);
///
/// When bytes are read and cached, this function will call:
///
- /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool
+ /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len,
+ /// bool
/// broadcast);
///
- /// Subclasses should override this function if they wish to override
- /// the default action of caching the bytes and broadcasting a \b
+ /// Subclasses should override this function if they wish to override the
+ /// default action of caching the bytes and broadcasting a \b
/// eBroadcastBitReadThreadGotBytes event.
///
/// @return
@@ -277,8 +270,8 @@ public:
/// false otherwise.
///
/// @see size_t Connection::Read (void *, size_t);
- /// @see void Communication::AppendBytesToCache (const uint8_t * bytes, size_t
- /// len, bool broadcast);
+ /// @see void Communication::AppendBytesToCache (const uint8_t * bytes,
+ /// size_t len, bool broadcast);
//------------------------------------------------------------------
virtual bool StartReadThread(Status *error_ptr = nullptr);
@@ -301,11 +294,10 @@ public:
bool ReadThreadIsRunning();
//------------------------------------------------------------------
- /// The static read thread function. This function will call
- /// the "DoRead" function continuously and wait for data to become
- /// available. When data is received it will append the available
- /// data to the internal cache and broadcast a
- /// \b eBroadcastBitReadThreadGotBytes event.
+ /// The static read thread function. This function will call the "DoRead"
+ /// function continuously and wait for data to become available. When data
+ /// is received it will append the available data to the internal cache and
+ /// broadcast a \b eBroadcastBitReadThreadGotBytes event.
///
/// @param[in] comm_ptr
/// A pointer to an instance of this class.
@@ -364,18 +356,17 @@ protected:
lldb::ConnectionStatus &status, Status *error_ptr);
//------------------------------------------------------------------
- /// Append new bytes that get read from the read thread into the
- /// internal object byte cache. This will cause a \b
- /// eBroadcastBitReadThreadGotBytes event to be broadcast if \a
- /// broadcast is true.
+ /// Append new bytes that get read from the read thread into the internal
+ /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes
+ /// event to be broadcast if \a broadcast is true.
///
- /// Subclasses can override this function in order to inspect the
- /// received data and check if a packet is available.
+ /// Subclasses can override this function in order to inspect the received
+ /// data and check if a packet is available.
///
- /// Subclasses can also still call this function from the
- /// overridden method to allow the caching to correctly happen and
- /// suppress the broadcasting of the \a eBroadcastBitReadThreadGotBytes
- /// event by setting \a broadcast to false.
+ /// Subclasses can also still call this function from the overridden method
+ /// to allow the caching to correctly happen and suppress the broadcasting
+ /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast
+ /// to false.
///
/// @param[in] src
/// A source buffer that must be at least \a src_len bytes
@@ -389,9 +380,9 @@ protected:
lldb::ConnectionStatus status);
//------------------------------------------------------------------
- /// Get any available bytes from our data cache. If this call
- /// empties the data cache, the \b eBroadcastBitReadThreadGotBytes event
- /// will be reset to signify no more bytes are available.
+ /// Get any available bytes from our data cache. If this call empties the
+ /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset
+ /// to signify no more bytes are available.
///
/// @param[in] dst
/// A destination buffer that must be at least \a dst_len bytes
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h b/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h
index 34d35ffe7c80..cc7176e5c95d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h
@@ -76,7 +76,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Debugger Debugger.h "lldb/Core/Debugger.h"
-/// @brief A class to manage flag bits.
+/// A class to manage flag bits.
///
/// Provides a global root objects for the debugger core.
//----------------------------------------------------------------------
@@ -156,11 +156,9 @@ public:
lldb::ListenerSP GetListener() { return m_listener_sp; }
// This returns the Debugger's scratch source manager. It won't be able to
- // look up files in debug
- // information, but it can look up files by absolute path and display them to
- // you.
- // To get the target's source manager, call GetSourceManager on the target
- // instead.
+ // look up files in debug information, but it can look up files by absolute
+ // path and display them to you. To get the target's source manager, call
+ // GetSourceManager on the target instead.
SourceManager &GetSourceManager();
lldb::TargetSP GetSelectedTarget() {
@@ -171,10 +169,9 @@ public:
//------------------------------------------------------------------
/// Get accessor for the target list.
///
- /// The target list is part of the global debugger object. This
- /// the single debugger shared instance to control where targets
- /// get created and to allow for tracking and searching for targets
- /// based on certain criteria.
+ /// The target list is part of the global debugger object. This the single
+ /// debugger shared instance to control where targets get created and to
+ /// allow for tracking and searching for targets based on certain criteria.
///
/// @return
/// A global shared target list.
@@ -188,9 +185,8 @@ public:
void DispatchInputEndOfFile();
//------------------------------------------------------------------
- // If any of the streams are not set, set them to the in/out/err
- // stream of the top most input reader to ensure they at least have
- // something
+ // If any of the streams are not set, set them to the in/out/err stream of
+ // the top most input reader to ensure they at least have something
//------------------------------------------------------------------
void AdoptTopIOHandlerFilesIfInvalid(lldb::StreamFileSP &in,
lldb::StreamFileSP &out,
@@ -323,9 +319,8 @@ public:
Status RunREPL(lldb::LanguageType language, const char *repl_options);
// This is for use in the command interpreter, when you either want the
- // selected target, or if no target
- // is present you want to prime the dummy target with entities that will be
- // copied over to new targets.
+ // selected target, or if no target is present you want to prime the dummy
+ // target with entities that will be copied over to new targets.
Target *GetSelectedOrDummyTarget(bool prefer_dummy = false);
Target *GetDummyTarget();
@@ -378,8 +373,8 @@ protected:
lldb::BroadcasterManagerSP m_broadcaster_manager_sp; // The debugger acts as a
// broadcaster manager of
// last resort.
- // It needs to get constructed before the target_list or any other
- // member that might want to broadcast through the debugger.
+ // It needs to get constructed before the target_list or any other member
+ // that might want to broadcast through the debugger.
TerminalState m_terminal_state;
TargetList m_target_list;
@@ -418,8 +413,8 @@ protected:
};
private:
- // Use Debugger::CreateInstance() to get a shared pointer to a new
- // debugger object
+ // Use Debugger::CreateInstance() to get a shared pointer to a new debugger
+ // object
Debugger(lldb::LogOutputCallback m_log_callback, void *baton);
DISALLOW_COPY_AND_ASSIGN(Debugger);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h b/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h
index fa5e6a636aaf..ef1f2ee54dd1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h
@@ -22,8 +22,8 @@
#include "lldb/Utility/ConstString.h" // for ConstString
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for AddressClass, AddressClass...
#include "lldb/lldb-forward.h" // for InstructionSP, DisassemblerSP
+#include "lldb/lldb-private-enumerations.h" // for AddressClass
#include "lldb/lldb-types.h" // for addr_t, offset_t
#include "llvm/ADT/StringRef.h" // for StringRef
@@ -78,7 +78,7 @@ namespace lldb_private {
class Instruction {
public:
Instruction(const Address &address,
- lldb::AddressClass addr_class = lldb::eAddressClassInvalid);
+ AddressClass addr_class = AddressClass::eInvalid);
virtual ~Instruction();
@@ -102,12 +102,11 @@ public:
virtual void
CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0;
- lldb::AddressClass GetAddressClass();
+ AddressClass GetAddressClass();
void SetAddress(const Address &addr) {
- // Invalidate the address class to lazily discover
- // it if we need to.
- m_address_class = lldb::eAddressClassInvalid;
+ // Invalidate the address class to lazily discover it if we need to.
+ m_address_class = AddressClass::eInvalid;
m_address = addr;
}
@@ -235,14 +234,15 @@ public:
protected:
Address m_address; // The section offset address of this instruction
// We include an address class in the Instruction class to
- // allow the instruction specify the eAddressClassCodeAlternateISA
- // (currently used for thumb), and also to specify data (eAddressClassData).
- // The usual value will be eAddressClassCode, but often when
- // disassembling memory, you might run into data. This can
- // help us to disassemble appropriately.
+ // allow the instruction specify the
+ // AddressClass::eCodeAlternateISA (currently used for
+ // thumb), and also to specify data (AddressClass::eData).
+ // The usual value will be AddressClass::eCode, but often
+ // when disassembling memory, you might run into data.
+ // This can help us to disassemble appropriately.
private:
- lldb::AddressClass
- m_address_class; // Use GetAddressClass () accessor function!
+ AddressClass m_address_class; // Use GetAddressClass () accessor function!
+
protected:
Opcode m_opcode; // The opcode for this instruction
std::string m_opcode_name;
@@ -365,12 +365,10 @@ public:
};
// FindPlugin should be lax about the flavor string (it is too annoying to
- // have various internal uses of the
- // disassembler fail because the global flavor string gets set wrong.
- // Instead, if you get a flavor string you
+ // have various internal uses of the disassembler fail because the global
+ // flavor string gets set wrong. Instead, if you get a flavor string you
// don't understand, use the default. Folks who care to check can use the
- // FlavorValidForArchSpec method on the
- // disassembler they got back.
+ // FlavorValidForArchSpec method on the disassembler they got back.
static lldb::DisassemblerSP
FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name);
@@ -470,8 +468,8 @@ public:
const char *flavor) = 0;
protected:
- // SourceLine and SourceLinesToDisplay structures are only used in
- // the mixed source and assembly display methods internal to this class.
+ // SourceLine and SourceLinesToDisplay structures are only used in the mixed
+ // source and assembly display methods internal to this class.
struct SourceLine {
FileSpec file;
@@ -494,9 +492,9 @@ protected:
struct SourceLinesToDisplay {
std::vector<SourceLine> lines;
- // index of the "current" source line, if we want to highlight that
- // when displaying the source lines. (as opposed to the surrounding
- // source lines provided to give context)
+ // index of the "current" source line, if we want to highlight that when
+ // displaying the source lines. (as opposed to the surrounding source
+ // lines provided to give context)
size_t current_source_line;
// Whether to print a blank line at the end of the source lines.
@@ -507,8 +505,8 @@ protected:
}
};
- // Get the function's declaration line number, hopefully a line number earlier
- // than the opening curly brace at the start of the function body.
+ // Get the function's declaration line number, hopefully a line number
+ // earlier than the opening curly brace at the start of the function body.
static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc);
// Add the provided SourceLine to the map of filenames-to-source-lines-seen.
@@ -517,14 +515,13 @@ protected:
std::map<FileSpec, std::set<uint32_t>> &source_lines_seen);
// Given a source line, determine if we should print it when we're doing
- // mixed source & assembly output.
- // We're currently using the target.process.thread.step-avoid-regexp setting
- // (which is used for stepping over inlined STL functions by default) to
- // determine what source lines to avoid showing.
+ // mixed source & assembly output. We're currently using the
+ // target.process.thread.step-avoid-regexp setting (which is used for
+ // stepping over inlined STL functions by default) to determine what source
+ // lines to avoid showing.
//
// Returns true if this source line should be elided (if the source line
- // should
- // not be displayed).
+ // should not be displayed).
static bool
ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
const SymbolContext &sc, SourceLine &line);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/DumpRegisterValue.h b/contrib/llvm/tools/lldb/include/lldb/Core/DumpRegisterValue.h
new file mode 100644
index 000000000000..bc4860fbc0e5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/DumpRegisterValue.h
@@ -0,0 +1,31 @@
+//===-- DumpRegisterValue.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_CORE_DUMPREGISTERVALUE_H
+#define LLDB_CORE_DUMPREGISTERVALUE_H
+
+#include "lldb/lldb-enumerations.h"
+#include <cstdint>
+
+namespace lldb_private {
+
+class RegisterValue;
+struct RegisterInfo;
+class Stream;
+
+// The default value of 0 for reg_name_right_align_at means no alignment at
+// all.
+bool DumpRegisterValue(const RegisterValue &reg_val, Stream *s,
+ const RegisterInfo *reg_info, bool prefix_with_name,
+ bool prefix_with_alt_name, lldb::Format format,
+ uint32_t reg_name_right_align_at = 0);
+
+} // namespace lldb_private
+
+#endif // LLDB_CORE_DUMPREGISTERVALUE_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h b/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h
index b0a4267a00a2..5d23bcd7b96e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h
@@ -48,62 +48,61 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class EmulateInstruction EmulateInstruction.h
/// "lldb/Core/EmulateInstruction.h"
-/// @brief A class that allows emulation of CPU opcodes.
+/// A class that allows emulation of CPU opcodes.
///
-/// This class is a plug-in interface that is accessed through the
-/// standard static FindPlugin function call in the EmulateInstruction
-/// class. The FindPlugin takes a target triple and returns a new object
-/// if there is a plug-in that supports the architecture and OS. Four
-/// callbacks and a baton are provided. The four callbacks are read
-/// register, write register, read memory and write memory.
+/// This class is a plug-in interface that is accessed through the standard
+/// static FindPlugin function call in the EmulateInstruction class. The
+/// FindPlugin takes a target triple and returns a new object if there is a
+/// plug-in that supports the architecture and OS. Four callbacks and a baton
+/// are provided. The four callbacks are read register, write register, read
+/// memory and write memory.
///
-/// This class is currently designed for these main use cases:
-/// - Auto generation of Call Frame Information (CFI) from assembly code
-/// - Predicting single step breakpoint locations
-/// - Emulating instructions for breakpoint traps
+/// This class is currently designed for these main use cases: - Auto
+/// generation of Call Frame Information (CFI) from assembly code - Predicting
+/// single step breakpoint locations - Emulating instructions for breakpoint
+/// traps
///
-/// Objects can be asked to read an instruction which will cause a call
-/// to the read register callback to get the PC, followed by a read
-/// memory call to read the opcode. If ReadInstruction () returns true,
-/// then a call to EmulateInstruction::EvaluateInstruction () can be
-/// made. At this point the EmulateInstruction subclass will use all of
-/// the callbacks to emulate an instruction.
+/// Objects can be asked to read an instruction which will cause a call to the
+/// read register callback to get the PC, followed by a read memory call to
+/// read the opcode. If ReadInstruction () returns true, then a call to
+/// EmulateInstruction::EvaluateInstruction () can be made. At this point the
+/// EmulateInstruction subclass will use all of the callbacks to emulate an
+/// instruction.
///
/// Clients that provide the callbacks can either do the read/write
-/// registers/memory to actually emulate the instruction on a real or
-/// virtual CPU, or watch for the EmulateInstruction::Context which
-/// is context for the read/write register/memory which explains why
-/// the callback is being called. Examples of a context are:
-/// "pushing register 3 onto the stack at offset -12", or "adjusting
-/// stack pointer by -16". This extra context allows the generation of
+/// registers/memory to actually emulate the instruction on a real or virtual
+/// CPU, or watch for the EmulateInstruction::Context which is context for the
+/// read/write register/memory which explains why the callback is being
+/// called. Examples of a context are: "pushing register 3 onto the stack at
+/// offset -12", or "adjusting stack pointer by -16". This extra context
+/// allows the generation of
/// CFI information from assembly code without having to actually do
/// the read/write register/memory.
///
-/// Clients must be prepared that not all instructions for an
-/// Instruction Set Architecture (ISA) will be emulated.
+/// Clients must be prepared that not all instructions for an Instruction Set
+/// Architecture (ISA) will be emulated.
///
-/// Subclasses at the very least should implement the instructions that
-/// save and restore registers onto the stack and adjustment to the stack
-/// pointer. By just implementing a few instructions for an ISA that are
-/// the typical prologue opcodes, you can then generate CFI using a
-/// class that will soon be available.
+/// Subclasses at the very least should implement the instructions that save
+/// and restore registers onto the stack and adjustment to the stack pointer.
+/// By just implementing a few instructions for an ISA that are the typical
+/// prologue opcodes, you can then generate CFI using a class that will soon
+/// be available.
///
-/// Implementing all of the instructions that affect the PC can then
-/// allow single step prediction support.
+/// Implementing all of the instructions that affect the PC can then allow
+/// single step prediction support.
///
-/// Implementing all of the instructions allows for emulation of opcodes
-/// for breakpoint traps and will pave the way for "thread centric"
-/// debugging. The current debugging model is "process centric" where
-/// all threads must be stopped when any thread is stopped; when
-/// hitting software breakpoints we must disable the breakpoint by
-/// restoring the original breakpoint opcode, single stepping and
-/// restoring the breakpoint trap. If all threads were allowed to run
-/// then other threads could miss the breakpoint.
+/// Implementing all of the instructions allows for emulation of opcodes for
+/// breakpoint traps and will pave the way for "thread centric" debugging. The
+/// current debugging model is "process centric" where all threads must be
+/// stopped when any thread is stopped; when hitting software breakpoints we
+/// must disable the breakpoint by restoring the original breakpoint opcode,
+/// single stepping and restoring the breakpoint trap. If all threads were
+/// allowed to run then other threads could miss the breakpoint.
///
-/// This class centralizes the code that usually is done in separate
-/// code paths in a debugger (single step prediction, finding save
-/// restore locations of registers for unwinding stack frame variables)
-/// and emulating the instruction is just a bonus.
+/// This class centralizes the code that usually is done in separate code
+/// paths in a debugger (single step prediction, finding save restore
+/// locations of registers for unwinding stack frame variables) and emulating
+/// the instruction is just a bonus.
//----------------------------------------------------------------------
class EmulateInstruction : public PluginInterface {
@@ -125,8 +124,8 @@ public:
// prologue
eContextPushRegisterOnStack,
- // Exclusively used when restoring a register off the stack as part of
- // the epilogue
+ // Exclusively used when restoring a register off the stack as part of the
+ // epilogue
eContextPopRegisterOffStack,
// Add or subtract a value from the stack
@@ -135,8 +134,8 @@ public:
// Adjust the frame pointer for the current frame
eContextSetFramePointer,
- // Typically in an epilogue sequence. Copy the frame pointer back
- // into the stack pointer, use SP for CFA calculations again.
+ // Typically in an epilogue sequence. Copy the frame pointer back into the
+ // stack pointer, use SP for CFA calculations again.
eContextRestoreStackPointer,
// Add or subtract a value from a base address register (other than SP)
@@ -159,8 +158,8 @@ public:
// Used when performing an absolute branch where the
eContextAbsoluteBranchRegister,
- // Used when performing a supervisor call to an operating system to
- // provide a service:
+ // Used when performing a supervisor call to an operating system to provide
+ // a service:
eContextSupervisorCall,
// Used when performing a MemU operation to read the PC-relative offset
@@ -360,9 +359,8 @@ public:
const RegisterValue &reg_value);
// Type to represent the condition of an instruction. The UINT32 value is
- // reserved for the
- // unconditional case and all other value can be used in an architecture
- // dependent way.
+ // reserved for the unconditional case and all other value can be used in an
+ // architecture dependent way.
typedef uint32_t InstructionCondition;
static const InstructionCondition UnconditionalCondition = UINT32_MAX;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Event.h b/contrib/llvm/tools/lldb/include/lldb/Core/Event.h
index f4c7f4769a37..fa3017057675 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Event.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Event.h
@@ -121,10 +121,8 @@ public:
const ConstString &GetFlavor() const override { return GetFlavorString(); }
- bool WaitForEventReceived(
- const std::chrono::microseconds &abstime = std::chrono::microseconds(0),
- bool *timed_out = nullptr) {
- return m_predicate.WaitForValueEqualTo(true, abstime, timed_out);
+ bool WaitForEventReceived(const Timeout<std::micro> &timeout = llvm::None) {
+ return m_predicate.WaitForValueEqualTo(true, timeout);
}
private:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h b/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h
index 54bce4fd2f41..855d749ed5d4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h
@@ -28,9 +28,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class FileLineResolver FileLineResolver.h "lldb/Core/FileLineResolver.h"
-/// @brief This class finds address for source file and line. Optionally, it
-/// will look for inlined
-/// instances of the file and line specification.
+/// This class finds address for source file and line. Optionally, it will
+/// look for inlined instances of the file and line specification.
//----------------------------------------------------------------------
class FileLineResolver : public Searcher {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/FileSpecList.h b/contrib/llvm/tools/lldb/include/lldb/Core/FileSpecList.h
index 3cbffca44f69..713ed2aaffc6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/FileSpecList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/FileSpecList.h
@@ -25,7 +25,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class FileSpecList FileSpecList.h "lldb/Core/FileSpecList.h"
-/// @brief A file collection class.
+/// A file collection class.
///
/// A class that contains a mutable list of FileSpec objects.
//----------------------------------------------------------------------
@@ -56,8 +56,7 @@ public:
//------------------------------------------------------------------
/// Assignment operator.
///
- /// Replace the file list in this object with the file list from
- /// \a rhs.
+ /// Replace the file list in this object with the file list from \a rhs.
///
/// @param[in] rhs
/// A file list object to copy.
@@ -80,8 +79,8 @@ public:
//------------------------------------------------------------------
/// Append a FileSpec object if unique.
///
- /// Appends \a file to the end of the file list if it doesn't
- /// already exist in the file list.
+ /// Appends \a file to the end of the file list if it doesn't already exist
+ /// in the file list.
///
/// @param[in] file
/// A new file to append to this file list.
@@ -107,8 +106,8 @@ public:
//------------------------------------------------------------------
/// Find a file index.
///
- /// Find the index of the file in the file spec list that matches
- /// \a file starting \a idx entries into the file spec list.
+ /// Find the index of the file in the file spec list that matches \a file
+ /// starting \a idx entries into the file spec list.
///
/// @param[in] idx
/// An index into the file list.
@@ -119,24 +118,18 @@ public:
/// @param[in] full
/// Should FileSpec::Equal be called with "full" true or false.
///
- /// @param[in] remove_backup_dots
- /// Should FileSpec::Equal be called with "remove_backup_dots" true or
- /// false.
- ///
/// @return
/// The index of the file that matches \a file if it is found,
/// else UINT32_MAX is returned.
//------------------------------------------------------------------
- size_t FindFileIndex(size_t idx, const FileSpec &file, bool full,
- bool remove_backup_dots = false) const;
+ size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const;
//------------------------------------------------------------------
/// Get file at index.
///
- /// Gets a file from the file list. If \a idx is not a valid index,
- /// an empty FileSpec object will be returned. The file objects
- /// that are returned can be tested using
- /// FileSpec::operator void*().
+ /// Gets a file from the file list. If \a idx is not a valid index, an empty
+ /// FileSpec object will be returned. The file objects that are returned can
+ /// be tested using FileSpec::operator void*().
///
/// @param[in] idx
/// An index into the file list.
@@ -151,8 +144,8 @@ public:
//------------------------------------------------------------------
/// Get file specification pointer at index.
///
- /// Gets a file from the file list. The file objects that are
- /// returned can be tested using FileSpec::operator void*().
+ /// Gets a file from the file list. The file objects that are returned can
+ /// be tested using FileSpec::operator void*().
///
/// @param[in] idx
/// An index into the file list.
@@ -166,9 +159,9 @@ public:
//------------------------------------------------------------------
/// Get the memory cost of this object.
///
- /// Return the size in bytes that this object takes in memory. This
- /// returns the size in bytes of this object, not any shared string
- /// values it may refer to.
+ /// Return the size in bytes that this object takes in memory. This returns
+ /// the size in bytes of this object, not any shared string values it may
+ /// refer to.
///
/// @return
/// The number of bytes that this object occupies in memory.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h b/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h
index aa5ccb48e56a..93c7b3a94e4e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h
@@ -10,6 +10,7 @@
#ifndef liblldb_FormatEntity_h_
#define liblldb_FormatEntity_h_
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/FileSpec.h" // for FileSpec
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h" // for Format::eFormatDefault, Format
@@ -211,17 +212,15 @@ public:
llvm::StringRef &variable_name,
llvm::StringRef &variable_format);
- static size_t AutoComplete(llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches);
+ static size_t AutoComplete(lldb_private::CompletionRequest &request);
//----------------------------------------------------------------------
// Format the current elements into the stream \a s.
//
- // The root element will be stripped off and the format str passed in
- // will be either an empty string (print a description of this object),
- // or contain a . separated series like a domain name that identifies
- // further sub elements to display.
+ // The root element will be stripped off and the format str passed in will be
+ // either an empty string (print a description of this object), or contain a
+ // `.`-separated series like a domain name that identifies further
+ // sub-elements to display.
//----------------------------------------------------------------------
static bool FormatFileSpec(const FileSpec &file, Stream &s,
llvm::StringRef elements,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h b/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h
index e8cfbade5c61..2170ad10674e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h
@@ -63,14 +63,13 @@ public:
virtual ~IOHandler();
- // Each IOHandler gets to run until it is done. It should read data
- // from the "in" and place output into "out" and "err and return
- // when done.
+ // Each IOHandler gets to run until it is done. It should read data from the
+ // "in" and place output into "out" and "err and return when done.
virtual void Run() = 0;
- // Called when an input reader should relinquish its control so another
- // can be pushed onto the IO handler stack, or so the current IO
- // handler can pop itself off the stack
+ // Called when an input reader should relinquish its control so another can
+ // be pushed onto the IO handler stack, or so the current IO handler can pop
+ // itself off the stack
virtual void Cancel() = 0;
@@ -273,8 +272,8 @@ public:
//------------------------------------------------------------------
virtual bool IOHandlerIsInputComplete(IOHandler &io_handler,
StringList &lines) {
- // Impose no requirements for input to be considered
- // complete. subclasses should do something more intelligent.
+ // Impose no requirements for input to be considered complete. subclasses
+ // should do something more intelligent.
return true;
}
@@ -289,8 +288,8 @@ public:
//------------------------------------------------------------------
// Intercept the IOHandler::Interrupt() calls and do something.
//
- // Return true if the interrupt was handled, false if the IOHandler
- // should continue to try handle the interrupt itself.
+ // Return true if the interrupt was handled, false if the IOHandler should
+ // continue to try handle the interrupt itself.
//------------------------------------------------------------------
virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
@@ -302,8 +301,7 @@ protected:
// IOHandlerDelegateMultiline
//
// A IOHandlerDelegate that handles terminating multi-line input when
-// the last line is equal to "end_line" which is specified in the
-// constructor.
+// the last line is equal to "end_line" which is specified in the constructor.
//----------------------------------------------------------------------
class IOHandlerDelegateMultiline : public IOHandlerDelegate {
public:
@@ -325,9 +323,8 @@ public:
// Determine whether the end of input signal has been entered
const size_t num_lines = lines.GetSize();
if (num_lines > 0 && lines[num_lines - 1] == m_end_line) {
- // Remove the terminal line from "lines" so it doesn't appear in
- // the resulting input and return true to indicate we are done
- // getting lines
+ // Remove the terminal line from "lines" so it doesn't appear in the
+ // resulting input and return true to indicate we are done getting lines
lines.PopBack();
return true;
}
@@ -454,8 +451,7 @@ protected:
};
// The order of base classes is important. Look at the constructor of
-// IOHandlerConfirm
-// to see how.
+// IOHandlerConfirm to see how.
class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline {
public:
IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h b/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h
index ecbe3548d687..6554c64fa870 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h
@@ -13,10 +13,14 @@
// C Includes
// C++ Includes
+#include <cassert>
+#include <string>
#include <vector>
// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
#include "lldb/lldb-private-forward.h"
+#include "lldb/lldb-types.h"
namespace lldb_private {
class LoadedModuleInfoList {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Mangled.h b/contrib/llvm/tools/lldb/include/lldb/Core/Mangled.h
index 22778fabe63d..d263297ecfc6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Mangled.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Mangled.h
@@ -28,15 +28,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Mangled Mangled.h "lldb/Core/Mangled.h"
-/// @brief A class that handles mangled names.
+/// A class that handles mangled names.
///
-/// Designed to handle mangled names. The demangled version of any names
-/// will be computed when the demangled name is accessed through the
-/// Demangled() acccessor. This class can also tokenize the demangled
-/// version of the name for powerful searches. Functions and symbols
-/// could make instances of this class for their mangled names. Uniqued
-/// string pools are used for the mangled, demangled, and token string
-/// values to allow for faster comparisons and for efficient memory use.
+/// Designed to handle mangled names. The demangled version of any names will
+/// be computed when the demangled name is accessed through the Demangled()
+/// acccessor. This class can also tokenize the demangled version of the name
+/// for powerful searches. Functions and symbols could make instances of this
+/// class for their mangled names. Uniqued string pools are used for the
+/// mangled, demangled, and token string values to allow for faster
+/// comparisons and for efficient memory use.
//----------------------------------------------------------------------
class Mangled {
public:
@@ -91,16 +91,16 @@ public:
//----------------------------------------------------------------------
/// Destructor
///
- /// Releases its ref counts on the mangled and demangled strings that
- /// live in the global string pool.
+ /// Releases its ref counts on the mangled and demangled strings that live
+ /// in the global string pool.
//----------------------------------------------------------------------
~Mangled();
//----------------------------------------------------------------------
/// Convert to pointer operator.
///
- /// This allows code to check a Mangled object to see if it contains
- /// a valid mangled name using code such as:
+ /// This allows code to check a Mangled object to see if it contains a valid
+ /// mangled name using code such as:
///
/// @code
/// Mangled mangled(...);
@@ -117,8 +117,8 @@ public:
//----------------------------------------------------------------------
/// Logical NOT operator.
///
- /// This allows code to check a Mangled object to see if it contains
- /// an empty mangled name using code such as:
+ /// This allows code to check a Mangled object to see if it contains an
+ /// empty mangled name using code such as:
///
/// @code
/// Mangled mangled(...);
@@ -158,8 +158,8 @@ public:
//----------------------------------------------------------------------
/// Dump a description of this object to a Stream \a s.
///
- /// Dump a Mangled object to stream \a s. We don't force our
- /// demangled name to be computed currently (we don't use the accessor).
+ /// Dump a Mangled object to stream \a s. We don't force our demangled name
+ /// to be computed currently (we don't use the accessor).
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -245,9 +245,9 @@ public:
//----------------------------------------------------------------------
/// Get the memory cost of this object.
///
- /// Return the size in bytes that this object takes in memory. This
- /// returns the size in bytes of this object, not any shared string
- /// values it may refer to.
+ /// Return the size in bytes that this object takes in memory. This returns
+ /// the size in bytes of this object, not any shared string values it may
+ /// refer to.
///
/// @return
/// The number of bytes that this object occupies in memory.
@@ -259,8 +259,8 @@ public:
//----------------------------------------------------------------------
/// Set the string value in this object.
///
- /// If \a is_mangled is \b true, then the mangled named is set to \a
- /// name, else the demangled name is set to \a name.
+ /// If \a is_mangled is \b true, then the mangled named is set to \a name,
+ /// else the demangled name is set to \a name.
///
/// @param[in] name
/// The already const version of the name for this object.
@@ -285,14 +285,14 @@ public:
//----------------------------------------------------------------------
/// Try to guess the language from the mangling.
///
- /// For a mangled name to have a language it must have both a mangled
- /// and a demangled name and it can be guessed from the mangling what
- /// the language is. Note: this will return C++ for any language that
- /// uses Itanium ABI mangling.
+ /// For a mangled name to have a language it must have both a mangled and a
+ /// demangled name and it can be guessed from the mangling what the language
+ /// is. Note: this will return C++ for any language that uses Itanium ABI
+ /// mangling.
///
- /// Standard C function names will return eLanguageTypeUnknown because
- /// they aren't mangled and it isn't clear what language the name
- /// represents (there will be no mangled name).
+ /// Standard C function names will return eLanguageTypeUnknown because they
+ /// aren't mangled and it isn't clear what language the name represents
+ /// (there will be no mangled name).
///
/// @return
/// The language for the mangled/demangled name, eLanguageTypeUnknown
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h b/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h
index d56a6d537868..1bdf59c73649 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h
@@ -24,6 +24,7 @@
// Project includes
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Stream.h"
+#include "llvm/Support/DJB.h"
class MappedHash {
public:
@@ -32,22 +33,10 @@ public:
// by the ELF GNU_HASH sections
};
- static uint32_t HashStringUsingDJB(const char *s) {
- uint32_t h = 5381;
-
- for (unsigned char c = *s; c; c = *++s)
- h = ((h << 5) + h) + c;
-
- return h;
- }
-
- static uint32_t HashString(uint32_t hash_function, const char *s) {
- if (!s)
- return 0;
-
+ static uint32_t HashString(uint32_t hash_function, llvm::StringRef s) {
switch (hash_function) {
case MappedHash::eHashFunctionDJB:
- return HashStringUsingDJB(s);
+ return llvm::djbHash(s);
default:
break;
@@ -152,164 +141,6 @@ public:
// Write (int fd);
};
- template <typename __KeyType, class __HeaderDataType, class __ValueType>
- class ExportTable {
- public:
- typedef __HeaderDataType HeaderDataType;
- typedef Header<HeaderDataType> HeaderType;
- typedef __KeyType KeyType;
- typedef __ValueType ValueType;
-
- struct Entry {
- uint32_t hash;
- KeyType key;
- ValueType value;
- };
-
- typedef std::vector<ValueType> ValueArrayType;
-
- typedef std::map<KeyType, ValueArrayType> HashData;
- // Map a name hash to one or more name infos
- typedef std::map<uint32_t, HashData> HashToHashData;
-
- virtual KeyType GetKeyForStringType(const char *cstr) const = 0;
-
- virtual size_t GetByteSize(const HashData &key_to_key_values) = 0;
-
- virtual bool WriteHashData(const HashData &hash_data,
- lldb_private::Stream &ostrm) = 0;
- //
- void AddEntry(const char *cstr, const ValueType &value) {
- Entry entry;
- entry.hash = MappedHash::HashString(eHashFunctionDJB, cstr);
- entry.key = GetKeyForStringType(cstr);
- entry.value = value;
- m_entries.push_back(entry);
- }
-
- void Save(const HeaderDataType &header_data, lldb_private::Stream &ostrm) {
- if (m_entries.empty())
- return;
-
- const uint32_t num_entries = m_entries.size();
- uint32_t i = 0;
-
- HeaderType header;
-
- header.magic = HASH_MAGIC;
- header.version = 1;
- header.hash_function = eHashFunctionDJB;
- header.bucket_count = 0;
- header.hashes_count = 0;
- header.prologue_length = header_data.GetByteSize();
-
- // We need to figure out the number of unique hashes first before we can
- // calculate the number of buckets we want to use.
- typedef std::vector<uint32_t> hash_coll;
- hash_coll unique_hashes;
- unique_hashes.resize(num_entries);
- for (i = 0; i < num_entries; ++i)
- unique_hashes[i] = m_entries[i].hash;
- std::sort(unique_hashes.begin(), unique_hashes.end());
- hash_coll::iterator pos =
- std::unique(unique_hashes.begin(), unique_hashes.end());
- const size_t num_unique_hashes =
- std::distance(unique_hashes.begin(), pos);
-
- if (num_unique_hashes > 1024)
- header.bucket_count = num_unique_hashes / 4;
- else if (num_unique_hashes > 16)
- header.bucket_count = num_unique_hashes / 2;
- else
- header.bucket_count = num_unique_hashes;
- if (header.bucket_count == 0)
- header.bucket_count = 1;
-
- std::vector<HashToHashData> hash_buckets;
- std::vector<uint32_t> hash_indexes(header.bucket_count, 0);
- std::vector<uint32_t> hash_values;
- std::vector<uint32_t> hash_offsets;
- hash_buckets.resize(header.bucket_count);
- uint32_t bucket_entry_empties = 0;
- // StreamString hash_file_data(Stream::eBinary,
- // dwarf->GetObjectFile()->GetAddressByteSize(),
- // dwarf->GetObjectFile()->GetByteSize());
-
- // Push all of the hashes into their buckets and create all bucket
- // entries all populated with data.
- for (i = 0; i < num_entries; ++i) {
- const uint32_t hash = m_entries[i].hash;
- const uint32_t bucket_idx = hash % header.bucket_count;
- const uint32_t strp_offset = m_entries[i].str_offset;
- const uint32_t die_offset = m_entries[i].die_offset;
- hash_buckets[bucket_idx][hash][strp_offset].push_back(die_offset);
- }
-
- // Now for each bucket we write the bucket value which is the
- // number of hashes and the hash index encoded into a single
- // 32 bit unsigned integer.
- for (i = 0; i < header.bucket_count; ++i) {
- HashToHashData &bucket_entry = hash_buckets[i];
-
- if (bucket_entry.empty()) {
- // Empty bucket
- ++bucket_entry_empties;
- hash_indexes[i] = UINT32_MAX;
- } else {
- const uint32_t hash_value_index = hash_values.size();
- uint32_t hash_count = 0;
- typename HashToHashData::const_iterator pos, end = bucket_entry.end();
- for (pos = bucket_entry.begin(); pos != end; ++pos) {
- hash_values.push_back(pos->first);
- hash_offsets.push_back(GetByteSize(pos->second));
- ++hash_count;
- }
-
- hash_indexes[i] = hash_value_index;
- }
- }
- header.hashes_count = hash_values.size();
-
- // Write the header out now that we have the hash_count
- header.Write(ostrm);
-
- // Now for each bucket we write the start index of the hashes
- // for the current bucket, or UINT32_MAX if the bucket is empty
- for (i = 0; i < header.bucket_count; ++i) {
- ostrm.PutHex32(hash_indexes[i]);
- }
-
- // Now we need to write out all of the hash values
- for (i = 0; i < header.hashes_count; ++i) {
- ostrm.PutHex32(hash_values[i]);
- }
-
- // Now we need to write out all of the hash data offsets,
- // there is an offset for each hash in the hashes array
- // that was written out above
- for (i = 0; i < header.hashes_count; ++i) {
- ostrm.PutHex32(hash_offsets[i]);
- }
-
- // Now we write the data for each hash and verify we got the offset
- // correct above...
- for (i = 0; i < header.bucket_count; ++i) {
- HashToHashData &bucket_entry = hash_buckets[i];
-
- typename HashToHashData::const_iterator pos, end = bucket_entry.end();
- for (pos = bucket_entry.begin(); pos != end; ++pos) {
- if (!bucket_entry.empty()) {
- WriteHashData(pos->second);
- }
- }
- }
- }
-
- protected:
- typedef std::vector<Entry> collection;
- collection m_entries;
- };
-
// A class for reading and using a saved hash table from a block of data
// in memory
template <typename __KeyType, class __HeaderType, class __HashData>
@@ -377,8 +208,8 @@ public:
return result;
}
- bool Find(const char *name, Pair &pair) const {
- if (!name || !name[0])
+ bool Find(llvm::StringRef name, Pair &pair) const {
+ if (name.empty())
return false;
if (IsValid()) {
@@ -425,13 +256,12 @@ public:
return false;
}
- // This method must be implemented in any subclasses.
- // The KeyType is user specified and must somehow result in a string
- // value. For example, the KeyType might be a string offset in a string
- // table and subclasses can store their string table as a member of the
- // subclass and return a valie "const char *" given a "key". The value
- // could also be a C string pointer, in which case just returning "key"
- // will suffice.
+ // This method must be implemented in any subclasses. The KeyType is user
+ // specified and must somehow result in a string value. For example, the
+ // KeyType might be a string offset in a string table and subclasses can
+ // store their string table as a member of the subclass and return a valie
+ // "const char *" given a "key". The value could also be a C string
+ // pointer, in which case just returning "key" will suffice.
virtual const char *GetStringForKeyType(KeyType key) const = 0;
virtual bool ReadHashData(uint32_t hash_data_offset,
@@ -439,20 +269,19 @@ public:
// This method must be implemented in any subclasses and it must try to
// read one "Pair" at the offset pointed to by the "hash_data_offset_ptr"
- // parameter. This offset should be updated as bytes are consumed and
- // a value "Result" enum should be returned. If the "name" matches the
- // full name for the "pair.key" (which must be filled in by this call),
- // then the HashData in the pair ("pair.value") should be extracted and
- // filled in and "eResultKeyMatch" should be returned. If "name" doesn't
- // match this string for the key, then "eResultKeyMismatch" should be
- // returned and all data for the current HashData must be consumed or
- // skipped and the "hash_data_offset_ptr" offset needs to be updated to
- // point to the next HashData. If the end of the HashData objects for
- // a given hash value have been reached, then "eResultEndOfHashData"
- // should be returned. If anything else goes wrong during parsing,
- // return "eResultError" and the corresponding "Find()" function will
- // be canceled and return false.
- virtual Result GetHashDataForName(const char *name,
+ // parameter. This offset should be updated as bytes are consumed and a
+ // value "Result" enum should be returned. If the "name" matches the full
+ // name for the "pair.key" (which must be filled in by this call), then the
+ // HashData in the pair ("pair.value") should be extracted and filled in
+ // and "eResultKeyMatch" should be returned. If "name" doesn't match this
+ // string for the key, then "eResultKeyMismatch" should be returned and all
+ // data for the current HashData must be consumed or skipped and the
+ // "hash_data_offset_ptr" offset needs to be updated to point to the next
+ // HashData. If the end of the HashData objects for a given hash value have
+ // been reached, then "eResultEndOfHashData" should be returned. If
+ // anything else goes wrong during parsing, return "eResultError" and the
+ // corresponding "Find()" function will be canceled and return false.
+ virtual Result GetHashDataForName(llvm::StringRef name,
lldb::offset_t *hash_data_offset_ptr,
Pair &pair) const = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Module.h b/contrib/llvm/tools/lldb/include/lldb/Core/Module.h
index da981ade78ba..83d5f519f086 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Module.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Module.h
@@ -12,6 +12,7 @@
#include "lldb/Core/Address.h" // for Address
#include "lldb/Core/ModuleSpec.h" // for ModuleSpec
+#include "lldb/Symbol/ObjectFile.h" // for ObjectFile
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/PathMappingList.h"
@@ -93,33 +94,30 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Module Module.h "lldb/Core/Module.h"
-/// @brief A class that describes an executable image and its associated
+/// A class that describes an executable image and its associated
/// object and symbol files.
///
/// The module is designed to be able to select a single slice of an
-/// executable image as it would appear on disk and during program
-/// execution.
+/// executable image as it would appear on disk and during program execution.
///
/// Modules control when and if information is parsed according to which
/// accessors are called. For example the object file (ObjectFile)
-/// representation will only be parsed if the object file is requested
-/// using the Module::GetObjectFile() is called. The debug symbols
-/// will only be parsed if the symbol vendor (SymbolVendor) is
-/// requested using the Module::GetSymbolVendor() is called.
+/// representation will only be parsed if the object file is requested using
+/// the Module::GetObjectFile() is called. The debug symbols will only be
+/// parsed if the symbol vendor (SymbolVendor) is requested using the
+/// Module::GetSymbolVendor() is called.
///
-/// The module will parse more detailed information as more queries are
-/// made.
+/// The module will parse more detailed information as more queries are made.
//----------------------------------------------------------------------
class Module : public std::enable_shared_from_this<Module>,
public SymbolContextScope {
public:
- // Static functions that can track the lifetime of module objects.
- // This is handy because we might have Module objects that are in
- // shared pointers that aren't in the global module list (from
- // ModuleList). If this is the case we need to know about it.
- // The modules in the global list maintained by these functions
- // can be viewed using the "target modules list" command using the
- // "--global" (-g for short).
+ // Static functions that can track the lifetime of module objects. This is
+ // handy because we might have Module objects that are in shared pointers
+ // that aren't in the global module list (from ModuleList). If this is the
+ // case we need to know about it. The modules in the global list maintained
+ // by these functions can be viewed using the "target modules list" command
+ // using the "--global" (-g for short).
static size_t GetNumberAllocatedModules();
static Module *GetAllocatedModuleAtIndex(size_t idx);
@@ -129,8 +127,8 @@ public:
//------------------------------------------------------------------
/// Construct with file specification and architecture.
///
- /// Clients that wish to share modules with other targets should
- /// use ModuleList::GetSharedModule().
+ /// Clients that wish to share modules with other targets should use
+ /// ModuleList::GetSharedModule().
///
/// @param[in] file_spec
/// The file specification for the on disk representation of
@@ -158,8 +156,23 @@ public:
Module(const ModuleSpec &module_spec);
- static lldb::ModuleSP
- CreateJITModule(const lldb::ObjectFileJITDelegateSP &delegate_sp);
+ template <typename ObjFilePlugin, typename... Args>
+ static lldb::ModuleSP CreateModuleFromObjectFile(Args &&... args) {
+ // Must create a module and place it into a shared pointer before we can
+ // create an object file since it has a std::weak_ptr back to the module,
+ // so we need to control the creation carefully in this static function
+ lldb::ModuleSP module_sp(new Module());
+ module_sp->m_objfile_sp =
+ std::make_shared<ObjFilePlugin>(module_sp, std::forward<Args>(args)...);
+
+ // Once we get the object file, update our module with the object file's
+ // architecture since it might differ in vendor/os if some parts were
+ // unknown.
+ if (!module_sp->m_objfile_sp->GetArchitecture(module_sp->m_arch))
+ return nullptr;
+
+ return module_sp;
+ }
//------------------------------------------------------------------
/// Destructor.
@@ -169,13 +182,13 @@ public:
bool MatchesModuleSpec(const ModuleSpec &module_ref);
//------------------------------------------------------------------
- /// Set the load address for all sections in a module to be the
- /// file address plus \a slide.
+ /// Set the load address for all sections in a module to be the file address
+ /// plus \a slide.
///
- /// Many times a module will be loaded in a target with a constant
- /// offset applied to all top level sections. This function can
- /// set the load address for all top level sections to be the
- /// section file address + offset.
+ /// Many times a module will be loaded in a target with a constant offset
+ /// applied to all top level sections. This function can set the load
+ /// address for all top level sections to be the section file address +
+ /// offset.
///
/// @param[in] target
/// The target in which to apply the section load addresses.
@@ -225,19 +238,18 @@ public:
//------------------------------------------------------------------
/// Get the module path and object name.
///
- /// Modules can refer to object files. In this case the specification
- /// is simple and would return the path to the file:
+ /// Modules can refer to object files. In this case the specification is
+ /// simple and would return the path to the file:
///
/// "/usr/lib/foo.dylib"
///
- /// Modules can be .o files inside of a BSD archive (.a file). In
- /// this case, the object specification will look like:
+ /// Modules can be .o files inside of a BSD archive (.a file). In this case,
+ /// the object specification will look like:
///
/// "/usr/lib/foo.a(bar.o)"
///
- /// There are many places where logging wants to log this fully
- /// qualified specification, so we centralize this functionality
- /// here.
+ /// There are many places where logging wants to log this fully qualified
+ /// specification, so we centralize this functionality here.
///
/// @return
/// The object path + object name if there is one.
@@ -247,11 +259,10 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s. The dumped content will be only what has
- /// been loaded or parsed up to this point at which this function
- /// is called, so this is a good way to see what has been parsed
- /// in a module.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s. The dumped content will be only what has been loaded or parsed up
+ /// to this point at which this function is called, so this is a good way to
+ /// see what has been parsed in a module.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -316,8 +327,8 @@ public:
//------------------------------------------------------------------
/// Find compile units by partial or full path.
///
- /// Finds all compile units that match \a path in all of the modules
- /// and returns the results in \a sc_list.
+ /// Finds all compile units that match \a path in all of the modules and
+ /// returns the results in \a sc_list.
///
/// @param[in] path
/// The name of the function we are looking for.
@@ -342,8 +353,7 @@ public:
///
/// If the function is an inlined function, it will have a block,
/// representing the inlined function, and the function will be the
- /// containing function. If it is not inlined, then the block will
- /// be NULL.
+ /// containing function. If it is not inlined, then the block will be NULL.
///
/// @param[in] name
/// The name of the compile unit we are looking for.
@@ -379,8 +389,7 @@ public:
///
/// If the function is an inlined function, it will have a block,
/// representing the inlined function, and the function will be the
- /// containing function. If it is not inlined, then the block will
- /// be NULL.
+ /// containing function. If it is not inlined, then the block will be NULL.
///
/// @param[in] regex
/// A regular expression to use when matching the name.
@@ -438,26 +447,19 @@ public:
/// @param[in] parent_decl_ctx
/// If valid, a decl context that results must exist within
///
- /// @param[in] append
- /// If \b true, any matches will be appended to \a
- /// variable_list, else matches replace the contents of
- /// \a variable_list.
- ///
/// @param[in] max_matches
/// Allow the number of matches to be limited to \a
/// max_matches. Specify UINT32_MAX to get all possible matches.
///
/// @param[in] variable_list
- /// A list of variables that gets the matches appended to (if
- /// \a append it \b true), or replace (if \a append is \b false).
+ /// A list of variables that gets the matches appended to.
///
/// @return
/// The number of matches added to \a variable_list.
//------------------------------------------------------------------
size_t FindGlobalVariables(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- bool append, size_t max_matches,
- VariableList &variable_list);
+ size_t max_matches, VariableList &variable_list);
//------------------------------------------------------------------
/// Find global and static variables by regular expression.
@@ -465,44 +467,36 @@ public:
/// @param[in] regex
/// A regular expression to use when matching the name.
///
- /// @param[in] append
- /// If \b true, any matches will be appended to \a
- /// variable_list, else matches replace the contents of
- /// \a variable_list.
- ///
/// @param[in] max_matches
/// Allow the number of matches to be limited to \a
/// max_matches. Specify UINT32_MAX to get all possible matches.
///
/// @param[in] variable_list
- /// A list of variables that gets the matches appended to (if
- /// \a append it \b true), or replace (if \a append is \b false).
+ /// A list of variables that gets the matches appended to.
///
/// @return
/// The number of matches added to \a variable_list.
//------------------------------------------------------------------
- size_t FindGlobalVariables(const RegularExpression &regex, bool append,
- size_t max_matches, VariableList &variable_list);
+ size_t FindGlobalVariables(const RegularExpression &regex, size_t max_matches,
+ VariableList &variable_list);
//------------------------------------------------------------------
/// Find types by name.
///
- /// Type lookups in modules go through the SymbolVendor (which will
- /// use one or more SymbolFile subclasses). The SymbolFile needs to
- /// be able to lookup types by basename and not the fully qualified
- /// typename. This allows the type accelerator tables to stay small,
- /// even with heavily templatized C++. The type search will then
- /// narrow down the search results. If "exact_match" is true, then
- /// the type search will only match exact type name matches. If
- /// "exact_match" is false, the type will match as long as the base
- /// typename matches and as long as any immediate containing
- /// namespaces/class scopes that are specified match. So to search
- /// for a type "d" in "b::c", the name "b::c::d" can be specified
- /// and it will match any class/namespace "b" which contains a
- /// class/namespace "c" which contains type "d". We do this to
- /// allow users to not always have to specify complete scoping on
- /// all expressions, but it also allows for exact matching when
- /// required.
+ /// Type lookups in modules go through the SymbolVendor (which will use one
+ /// or more SymbolFile subclasses). The SymbolFile needs to be able to
+ /// lookup types by basename and not the fully qualified typename. This
+ /// allows the type accelerator tables to stay small, even with heavily
+ /// templatized C++. The type search will then narrow down the search
+ /// results. If "exact_match" is true, then the type search will only match
+ /// exact type name matches. If "exact_match" is false, the type will match
+ /// as long as the base typename matches and as long as any immediate
+ /// containing namespaces/class scopes that are specified match. So to
+ /// search for a type "d" in "b::c", the name "b::c::d" can be specified and
+ /// it will match any class/namespace "b" which contains a class/namespace
+ /// "c" which contains type "d". We do this to allow users to not always
+ /// have to specify complete scoping on all expressions, but it also allows
+ /// for exact matching when required.
///
/// @param[in] sc
/// A symbol context that scopes where to extract a type list
@@ -535,9 +529,9 @@ public:
const ConstString &type_name, bool exact_match);
//------------------------------------------------------------------
- /// Find types by name that are in a namespace. This function is
- /// used by the expression parser when searches need to happen in
- /// an exact namespace scope.
+ /// Find types by name that are in a namespace. This function is used by the
+ /// expression parser when searches need to happen in an exact namespace
+ /// scope.
///
/// @param[in] sc
/// A symbol context that scopes where to extract a type list
@@ -572,9 +566,9 @@ public:
//------------------------------------------------------------------
/// Get const accessor for the module file specification.
///
- /// This function returns the file for the module on the host system
- /// that is running LLDB. This can differ from the path on the
- /// platform since we might be doing remote debugging.
+ /// This function returns the file for the module on the host system that is
+ /// running LLDB. This can differ from the path on the platform since we
+ /// might be doing remote debugging.
///
/// @return
/// A const reference to the file specification object.
@@ -584,14 +578,13 @@ public:
//------------------------------------------------------------------
/// Get accessor for the module platform file specification.
///
- /// Platform file refers to the path of the module as it is known on
- /// the remote system on which it is being debugged. For local
- /// debugging this is always the same as Module::GetFileSpec(). But
- /// remote debugging might mention a file "/usr/lib/liba.dylib"
- /// which might be locally downloaded and cached. In this case the
- /// platform file could be something like:
- /// "/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib"
- /// The file could also be cached in a local developer kit directory.
+ /// Platform file refers to the path of the module as it is known on the
+ /// remote system on which it is being debugged. For local debugging this is
+ /// always the same as Module::GetFileSpec(). But remote debugging might
+ /// mention a file "/usr/lib/liba.dylib" which might be locally downloaded
+ /// and cached. In this case the platform file could be something like:
+ /// "/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib" The
+ /// file could also be cached in a local developer kit directory.
///
/// @return
/// A const reference to the file specification object.
@@ -631,8 +624,8 @@ public:
}
//------------------------------------------------------------------
- /// Tells whether this module is capable of being the main executable
- /// for a process.
+ /// Tells whether this module is capable of being the main executable for a
+ /// process.
///
/// @return
/// \b true if it is, \b false otherwise.
@@ -640,9 +633,9 @@ public:
bool IsExecutable();
//------------------------------------------------------------------
- /// Tells whether this module has been loaded in the target passed in.
- /// This call doesn't distinguish between whether the module is loaded
- /// by the dynamic loader, or by a "target module add" type call.
+ /// Tells whether this module has been loaded in the target passed in. This
+ /// call doesn't distinguish between whether the module is loaded by the
+ /// dynamic loader, or by a "target module add" type call.
///
/// @param[in] target
/// The target to check whether this is loaded in.
@@ -673,9 +666,8 @@ public:
//------------------------------------------------------------------
/// Get the object file representation for the current architecture.
///
- /// If the object file has not been located or parsed yet, this
- /// function will find the best ObjectFile plug-in that can parse
- /// Module::m_file.
+ /// If the object file has not been located or parsed yet, this function
+ /// will find the best ObjectFile plug-in that can parse Module::m_file.
///
/// @return
/// If Module::m_file does not exist, or no plug-in was found
@@ -688,12 +680,12 @@ public:
virtual ObjectFile *GetObjectFile();
//------------------------------------------------------------------
- /// Get the unified section list for the module. This is the section
- /// list created by the module's object file and any debug info and
- /// symbol files created by the symbol vendor.
+ /// Get the unified section list for the module. This is the section list
+ /// created by the module's object file and any debug info and symbol files
+ /// created by the symbol vendor.
///
- /// If the symbol vendor has not been loaded yet, this function
- /// will return the section list for the object file.
+ /// If the symbol vendor has not been loaded yet, this function will return
+ /// the section list for the object file.
///
/// @return
/// Unified module section list.
@@ -701,27 +693,26 @@ public:
virtual SectionList *GetSectionList();
//------------------------------------------------------------------
- /// Notify the module that the file addresses for the Sections have
- /// been updated.
+ /// Notify the module that the file addresses for the Sections have been
+ /// updated.
///
- /// If the Section file addresses for a module are updated, this
- /// method should be called. Any parts of the module, object file,
- /// or symbol file that has cached those file addresses must invalidate
- /// or update its cache.
+ /// If the Section file addresses for a module are updated, this method
+ /// should be called. Any parts of the module, object file, or symbol file
+ /// that has cached those file addresses must invalidate or update its
+ /// cache.
//------------------------------------------------------------------
virtual void SectionFileAddressesChanged();
- uint32_t GetVersion(uint32_t *versions, uint32_t num_versions);
+ llvm::VersionTuple GetVersion();
//------------------------------------------------------------------
/// Load an object file from memory.
///
- /// If available, the size of the object file in memory may be
- /// passed to avoid additional round trips to process memory.
- /// If the size is not provided, a default value is used. This
- /// value should be large enough to enable the ObjectFile plugins
- /// to read the header of the object file without going back to the
- /// process.
+ /// If available, the size of the object file in memory may be passed to
+ /// avoid additional round trips to process memory. If the size is not
+ /// provided, a default value is used. This value should be large enough to
+ /// enable the ObjectFile plugins to read the header of the object file
+ /// without going back to the process.
///
/// @return
/// The object file loaded from memory or nullptr, if the operation
@@ -733,9 +724,8 @@ public:
//------------------------------------------------------------------
/// Get the symbol vendor interface for the current architecture.
///
- /// If the symbol vendor file has not been located yet, this
- /// function will find the best SymbolVendor plug-in that can
- /// use the current object file.
+ /// If the symbol vendor file has not been located yet, this function will
+ /// find the best SymbolVendor plug-in that can use the current object file.
///
/// @return
/// If this module does not have a valid object file, or no
@@ -758,11 +748,11 @@ public:
TypeList *GetTypeList();
//------------------------------------------------------------------
- /// Get a pointer to the UUID value contained in this object.
+ /// Get a reference to the UUID value contained in this object.
///
- /// If the executable image file doesn't not have a UUID value built
- /// into the file format, an MD5 checksum of the entire file, or
- /// slice of the file for the current architecture should be used.
+ /// If the executable image file doesn't not have a UUID value built into
+ /// the file format, an MD5 checksum of the entire file, or slice of the
+ /// file for the current architecture should be used.
///
/// @return
/// A const pointer to the internal copy of the UUID value in
@@ -775,14 +765,13 @@ public:
/// A debugging function that will cause everything in a module to
/// be parsed.
///
- /// All compile units will be parsed, along with all globals and
- /// static variables and all functions for those compile units.
- /// All types, scopes, local variables, static variables, global
- /// variables, and line tables will be parsed. This can be used
- /// prior to dumping a module to see a complete list of the
- /// resulting debug information that gets parsed, or as a debug
- /// function to ensure that the module can consume all of the
- /// debug data the symbol vendor provides.
+ /// All compile units will be parsed, along with all globals and static
+ /// variables and all functions for those compile units. All types, scopes,
+ /// local variables, static variables, global variables, and line tables
+ /// will be parsed. This can be used prior to dumping a module to see a
+ /// complete list of the resulting debug information that gets parsed, or as
+ /// a debug function to ensure that the module can consume all of the debug
+ /// data the symbol vendor provides.
//------------------------------------------------------------------
void ParseAllDebugSymbols();
@@ -791,17 +780,16 @@ public:
//------------------------------------------------------------------
/// Resolve the symbol context for the given address.
///
- /// Tries to resolve the matching symbol context based on a lookup
- /// from the current symbol vendor. If the lazy lookup fails,
- /// an attempt is made to parse the eh_frame section to handle
- /// stripped symbols. If this fails, an attempt is made to resolve
- /// the symbol to the previous address to handle the case of a
- /// function with a tail call.
+ /// Tries to resolve the matching symbol context based on a lookup from the
+ /// current symbol vendor. If the lazy lookup fails, an attempt is made to
+ /// parse the eh_frame section to handle stripped symbols. If this fails,
+ /// an attempt is made to resolve the symbol to the previous address to
+ /// handle the case of a function with a tail call.
///
- /// Use properties of the modified SymbolContext to inspect any
- /// resolved target, module, compilation unit, symbol, function,
- /// function block or line entry. Use the return value to determine
- /// which of these properties have been modified.
+ /// Use properties of the modified SymbolContext to inspect any resolved
+ /// target, module, compilation unit, symbol, function, function block or
+ /// line entry. Use the return value to determine which of these properties
+ /// have been modified.
///
/// @param[in] so_addr
/// A load address to resolve.
@@ -836,15 +824,14 @@ public:
//------------------------------------------------------------------
/// Resolve items in the symbol context for a given file and line.
///
- /// Tries to resolve \a file_path and \a line to a list of matching
- /// symbol contexts.
+ /// Tries to resolve \a file_path and \a line to a list of matching symbol
+ /// contexts.
///
- /// The line table entries contains addresses that can be used to
- /// further resolve the values in each match: the function, block,
- /// symbol. Care should be taken to minimize the amount of
- /// information that is requested to only what is needed --
- /// typically the module, compile unit, line table and line table
- /// entry are sufficient.
+ /// The line table entries contains addresses that can be used to further
+ /// resolve the values in each match: the function, block, symbol. Care
+ /// should be taken to minimize the amount of information that is requested
+ /// to only what is needed -- typically the module, compile unit, line table
+ /// and line table entry are sufficient.
///
/// @param[in] file_path
/// A path to a source file to match. If \a file_path does not
@@ -883,15 +870,14 @@ public:
//------------------------------------------------------------------
/// Resolve items in the symbol context for a given file and line.
///
- /// Tries to resolve \a file_spec and \a line to a list of matching
- /// symbol contexts.
+ /// Tries to resolve \a file_spec and \a line to a list of matching symbol
+ /// contexts.
///
- /// The line table entries contains addresses that can be used to
- /// further resolve the values in each match: the function, block,
- /// symbol. Care should be taken to minimize the amount of
- /// information that is requested to only what is needed --
- /// typically the module, compile unit, line table and line table
- /// entry are sufficient.
+ /// The line table entries contains addresses that can be used to further
+ /// resolve the values in each match: the function, block, symbol. Care
+ /// should be taken to minimize the amount of information that is requested
+ /// to only what is needed -- typically the module, compile unit, line table
+ /// and line table entry are sufficient.
///
/// @param[in] file_spec
/// A file spec to a source file to match. If \a file_path does
@@ -936,12 +922,10 @@ public:
TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language);
// Special error functions that can do printf style formatting that will
- // prepend the message with
- // something appropriate for this module (like the architecture, path and
- // object name (if any)).
- // This centralizes code so that everyone doesn't need to format their error
- // and log messages on
- // their own and keeps the output a bit more consistent.
+ // prepend the message with something appropriate for this module (like the
+ // architecture, path and object name (if any)). This centralizes code so
+ // that everyone doesn't need to format their error and log messages on their
+ // own and keeps the output a bit more consistent.
void LogMessage(Log *log, const char *format, ...)
__attribute__((format(printf, 3, 4)));
@@ -960,15 +944,15 @@ public:
__attribute__((format(printf, 2, 3)));
//------------------------------------------------------------------
- // Return true if the file backing this module has changed since the
- // module was originally created since we saved the initial file
- // modification time when the module first gets created.
+ // Return true if the file backing this module has changed since the module
+ // was originally created since we saved the initial file modification time
+ // when the module first gets created.
//------------------------------------------------------------------
bool FileHasChanged() const;
//------------------------------------------------------------------
- // SymbolVendor, SymbolFile and ObjectFile member objects should
- // lock the module mutex to avoid deadlocks.
+ // SymbolVendor, SymbolFile and ObjectFile member objects should lock the
+ // module mutex to avoid deadlocks.
//------------------------------------------------------------------
std::recursive_mutex &GetMutex() const { return m_mutex; }
@@ -979,14 +963,13 @@ public:
}
//------------------------------------------------------------------
- /// Finds a source file given a file spec using the module source
- /// path remappings (if any).
+ /// Finds a source file given a file spec using the module source path
+ /// remappings (if any).
///
/// Tries to resolve \a orig_spec by checking the module source path
- /// remappings. It makes sure the file exists, so this call can be
- /// expensive if the remappings are on a network file system, so
- /// use this function sparingly (not in a tight debug info parsing
- /// loop).
+ /// remappings. It makes sure the file exists, so this call can be expensive
+ /// if the remappings are on a network file system, so use this function
+ /// sparingly (not in a tight debug info parsing loop).
///
/// @param[in] orig_spec
/// The original source file path to try and remap.
@@ -1004,9 +987,9 @@ public:
//------------------------------------------------------------------
/// Remaps a source file given \a path into \a new_path.
///
- /// Remaps \a path if any source remappings match. This function
- /// does NOT stat the file system so it can be used in tight loops
- /// where debug info is being parsed.
+ /// Remaps \a path if any source remappings match. This function does NOT
+ /// stat the file system so it can be used in tight loops where debug info
+ /// is being parsed.
///
/// @param[in] path
/// The original source file path to try and remap.
@@ -1021,43 +1004,28 @@ public:
bool RemapSourceFile(llvm::StringRef path, std::string &new_path) const;
bool RemapSourceFile(const char *, std::string &) const = delete;
- //------------------------------------------------------------------
- /// Loads this module to memory.
- ///
- /// Loads the bits needed to create an executable image to the memory.
- /// It is useful with bare-metal targets where target does not have the
- /// ability to start a process itself.
- ///
- /// @param[in] target
- /// Target where to load the module.
- ///
- /// @return
- //------------------------------------------------------------------
- Status LoadInMemory(Target &target, bool set_pc);
-
//----------------------------------------------------------------------
/// @class LookupInfo Module.h "lldb/Core/Module.h"
- /// @brief A class that encapsulates name lookup information.
- ///
- /// Users can type a wide variety of partial names when setting
- /// breakpoints by name or when looking for functions by name.
- /// SymbolVendor and SymbolFile objects are only required to implement
- /// name lookup for function basenames and for fully mangled names.
- /// This means if the user types in a partial name, we must reduce this
- /// to a name lookup that will work with all SymbolFile objects. So we
- /// might reduce a name lookup to look for a basename, and then prune
- /// out any results that don't match.
- ///
- /// The "m_name" member variable represents the name as it was typed
- /// by the user. "m_lookup_name" will be the name we actually search
- /// for through the symbol or objects files. Lanaguage is included in
- /// case we need to filter results by language at a later date. The
- /// "m_name_type_mask" member variable tells us what kinds of names we
- /// are looking for and can help us prune out unwanted results.
+ /// A class that encapsulates name lookup information.
+ ///
+ /// Users can type a wide variety of partial names when setting breakpoints
+ /// by name or when looking for functions by name. SymbolVendor and
+ /// SymbolFile objects are only required to implement name lookup for
+ /// function basenames and for fully mangled names. This means if the user
+ /// types in a partial name, we must reduce this to a name lookup that will
+ /// work with all SymbolFile objects. So we might reduce a name lookup to
+ /// look for a basename, and then prune out any results that don't match.
+ ///
+ /// The "m_name" member variable represents the name as it was typed by the
+ /// user. "m_lookup_name" will be the name we actually search for through
+ /// the symbol or objects files. Lanaguage is included in case we need to
+ /// filter results by language at a later date. The "m_name_type_mask"
+ /// member variable tells us what kinds of names we are looking for and can
+ /// help us prune out unwanted results.
///
/// Function lookups are done in Module.cpp, ModuleList.cpp and in
- /// BreakpointResolverName.cpp and they all now use this class to do
- /// lookups correctly.
+ /// BreakpointResolverName.cpp and they all now use this class to do lookups
+ /// correctly.
//----------------------------------------------------------------------
class LookupInfo {
public:
@@ -1146,7 +1114,7 @@ protected:
std::atomic<bool> m_did_load_objfile{false};
std::atomic<bool> m_did_load_symbol_vendor{false};
- std::atomic<bool> m_did_parse_uuid{false};
+ std::atomic<bool> m_did_set_uuid{false};
mutable bool m_file_has_changed : 1,
m_first_file_changed_log : 1; /// See if the module was modified after it
/// was initially opened.
@@ -1156,9 +1124,9 @@ protected:
///
/// Tries to resolve \a vm_addr as a file address (if \a
/// vm_addr_is_file_addr is true) or as a load address if \a
- /// vm_addr_is_file_addr is false) in the symbol vendor.
- /// \a resolve_scope indicates what clients wish to resolve
- /// and can be used to limit the scope of what is parsed.
+ /// vm_addr_is_file_addr is false) in the symbol vendor. \a resolve_scope
+ /// indicates what clients wish to resolve and can be used to limit the
+ /// scope of what is parsed.
///
/// @param[in] vm_addr
/// The load virtual address to resolve.
@@ -1196,6 +1164,8 @@ protected:
bool SetArchitecture(const ArchSpec &new_arch);
+ void SetUUID(const lldb_private::UUID &uuid);
+
SectionList *GetUnifiedSectionList();
friend class ModuleList;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleChild.h b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleChild.h
index 8f2985c8185b..73438040c359 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleChild.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleChild.h
@@ -16,7 +16,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ModuleChild ModuleChild.h "lldb/Core/ModuleChild.h"
-/// @brief A mix in class that contains a pointer back to the module
+/// A mix in class that contains a pointer back to the module
/// that owns the object which inherits from it.
//----------------------------------------------------------------------
class ModuleChild {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h
index 4b637c9b0427..e1d8a9a7fb85 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h
@@ -12,6 +12,7 @@
#include "lldb/Core/Address.h" // for Address
#include "lldb/Core/ModuleSpec.h" // for ModuleSpec
+#include "lldb/Core/UserSettingsController.h"
#include "lldb/Utility/FileSpec.h" // for FileSpec
#include "lldb/Utility/Iterable.h"
#include "lldb/Utility/Status.h" // for Status
@@ -74,12 +75,21 @@ class VariableList;
namespace lldb_private {
+class ModuleListProperties : public Properties {
+public:
+ ModuleListProperties();
+
+ FileSpec GetClangModulesCachePath() const;
+ bool SetClangModulesCachePath(llvm::StringRef path);
+ bool GetEnableExternalLookup() const;
+};
+
//----------------------------------------------------------------------
/// @class ModuleList ModuleList.h "lldb/Core/ModuleList.h"
-/// @brief A collection class for Module objects.
+/// A collection class for Module objects.
///
-/// Modules in the module collection class are stored as reference
-/// counted shared pointers to Module objects.
+/// Modules in the module collection class are stored as reference counted
+/// shared pointers to Module objects.
//----------------------------------------------------------------------
class ModuleList {
public:
@@ -107,8 +117,7 @@ public:
//------------------------------------------------------------------
/// Copy Constructor.
///
- /// Creates a new module list object with a copy of the modules from
- /// \a rhs.
+ /// Creates a new module list object with a copy of the modules from \a rhs.
///
/// @param[in] rhs
/// Another module list object.
@@ -146,9 +155,9 @@ public:
void Append(const lldb::ModuleSP &module_sp);
//------------------------------------------------------------------
- /// Append a module to the module list and remove any equivalent
- /// modules. Equivalent modules are ones whose file, platform file
- /// and architecture matches.
+ /// Append a module to the module list and remove any equivalent modules.
+ /// Equivalent modules are ones whose file, platform file and architecture
+ /// matches.
///
/// Replaces the module to the collection.
///
@@ -169,27 +178,27 @@ public:
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Clears the list of modules and releases a reference to each
- /// module object and if the reference count goes to zero, the
- /// module will be deleted.
+ /// Clears the list of modules and releases a reference to each module
+ /// object and if the reference count goes to zero, the module will be
+ /// deleted.
//------------------------------------------------------------------
void Clear();
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Clears the list of modules and releases a reference to each
- /// module object and if the reference count goes to zero, the
- /// module will be deleted. Also release all memory that might be
- /// held by any collection classes (like std::vector)
+ /// Clears the list of modules and releases a reference to each module
+ /// object and if the reference count goes to zero, the module will be
+ /// deleted. Also release all memory that might be held by any collection
+ /// classes (like std::vector)
//------------------------------------------------------------------
void Destroy();
//------------------------------------------------------------------
/// Dump the description of each module contained in this list.
///
- /// Dump the description of each module contained in this list to
- /// the supplied stream \a s.
+ /// Dump the description of each module contained in this list to the
+ /// supplied stream \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -220,8 +229,8 @@ public:
//------------------------------------------------------------------
/// Get the module shared pointer for the module at index \a idx without
- /// acquiring the ModuleList mutex. This MUST already have been
- /// acquired with ModuleList::GetMutex and locked for this call to be safe.
+ /// acquiring the ModuleList mutex. This MUST already have been acquired
+ /// with ModuleList::GetMutex and locked for this call to be safe.
///
/// @param[in] idx
/// An index into this module collection.
@@ -249,9 +258,9 @@ public:
Module *GetModulePointerAtIndex(size_t idx) const;
//------------------------------------------------------------------
- /// Get the module pointer for the module at index \a idx without
- /// acquiring the ModuleList mutex. This MUST already have been
- /// acquired with ModuleList::GetMutex and locked for this call to be safe.
+ /// Get the module pointer for the module at index \a idx without acquiring
+ /// the ModuleList mutex. This MUST already have been acquired with
+ /// ModuleList::GetMutex and locked for this call to be safe.
///
/// @param[in] idx
/// An index into this module collection.
@@ -267,8 +276,8 @@ public:
//------------------------------------------------------------------
/// Find compile units by partial or full path.
///
- /// Finds all compile units that match \a path in all of the modules
- /// and returns the results in \a sc_list.
+ /// Finds all compile units that match \a path in all of the modules and
+ /// returns the results in \a sc_list.
///
/// @param[in] path
/// The name of the compile unit we are looking for.
@@ -315,24 +324,17 @@ public:
/// The name of the global or static variable we are looking
/// for.
///
- /// @param[in] append
- /// If \b true, any matches will be appended to \a
- /// variable_list, else matches replace the contents of
- /// \a variable_list.
- ///
/// @param[in] max_matches
/// Allow the number of matches to be limited to \a
/// max_matches. Specify UINT32_MAX to get all possible matches.
///
/// @param[in] variable_list
- /// A list of variables that gets the matches appended to (if
- /// \a append it \b true), or replace (if \a append is \b false).
+ /// A list of variables that gets the matches appended to.
///
/// @return
/// The number of matches added to \a variable_list.
//------------------------------------------------------------------
- size_t FindGlobalVariables(const ConstString &name, bool append,
- size_t max_matches,
+ size_t FindGlobalVariables(const ConstString &name, size_t max_matches,
VariableList &variable_list) const;
//------------------------------------------------------------------
@@ -341,29 +343,21 @@ public:
/// @param[in] regex
/// A regular expression to use when matching the name.
///
- /// @param[in] append
- /// If \b true, any matches will be appended to \a
- /// variable_list, else matches replace the contents of
- /// \a variable_list.
- ///
/// @param[in] max_matches
/// Allow the number of matches to be limited to \a
/// max_matches. Specify UINT32_MAX to get all possible matches.
///
/// @param[in] variable_list
- /// A list of variables that gets the matches appended to (if
- /// \a append it \b true), or replace (if \a append is \b false).
+ /// A list of variables that gets the matches appended to.
///
/// @return
/// The number of matches added to \a variable_list.
//------------------------------------------------------------------
- size_t FindGlobalVariables(const RegularExpression &regex, bool append,
- size_t max_matches,
+ size_t FindGlobalVariables(const RegularExpression &regex, size_t max_matches,
VariableList &variable_list) const;
//------------------------------------------------------------------
- /// Finds the first module whose file specification matches \a
- /// file_spec.
+ /// Finds the first module whose file specification matches \a file_spec.
///
/// @param[in] file_spec_ptr
/// A file specification object to match against the Module's
@@ -400,9 +394,9 @@ public:
//------------------------------------------------------------------
// Find a module by UUID
//
- // The UUID value for a module is extracted from the ObjectFile and
- // is the MD5 checksum, or a smarter object file equivalent, so
- // finding modules by UUID values is very efficient and accurate.
+ // The UUID value for a module is extracted from the ObjectFile and is the
+ // MD5 checksum, or a smarter object file equivalent, so finding modules by
+ // UUID values is very efficient and accurate.
//------------------------------------------------------------------
lldb::ModuleSP FindModule(const UUID &uuid) const;
@@ -534,6 +528,8 @@ public:
Stream *feedback_stream = nullptr,
bool continue_on_error = true);
+ static ModuleListProperties &GetGlobalModuleListProperties();
+
static bool ModuleIsInCache(const Module *module_ptr);
static Status GetSharedModule(const ModuleSpec &module_spec,
@@ -551,7 +547,7 @@ public:
static size_t RemoveOrphanSharedModules(bool mandatory);
static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr);
-
+
void ForEach(std::function<bool(const lldb::ModuleSP &module_sp)> const
&callback) const;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
index cc95bd0a0638..16a35a187780 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
@@ -34,9 +34,9 @@ public:
m_object_name(), m_object_offset(0), m_object_size(0),
m_source_mappings() {}
- ModuleSpec(const FileSpec &file_spec)
+ ModuleSpec(const FileSpec &file_spec, const UUID& uuid = UUID())
: m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(),
- m_uuid(), m_object_name(), m_object_offset(0),
+ m_uuid(uuid), m_object_name(), m_object_offset(0),
m_object_size(file_spec.GetByteSize()), m_source_mappings() {}
ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
@@ -341,8 +341,8 @@ public:
m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
}
- // The index "i" must be valid and this can't be used in
- // multi-threaded code as no mutex lock is taken.
+ // The index "i" must be valid and this can't be used in multi-threaded code
+ // as no mutex lock is taken.
ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; }
bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h b/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h
index 68e6ca20b266..b782294f1f60 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h
@@ -477,11 +477,11 @@ public:
const ConstString &name);
//------------------------------------------------------------------
- // Some plug-ins might register a DebuggerInitializeCallback
- // callback when registering the plug-in. After a new Debugger
- // instance is created, this DebuggerInitialize function will get
- // called. This allows plug-ins to install Properties and do any
- // other initialization that requires a debugger instance.
+ // Some plug-ins might register a DebuggerInitializeCallback callback when
+ // registering the plug-in. After a new Debugger instance is created, this
+ // DebuggerInitialize function will get called. This allows plug-ins to
+ // install Properties and do any other initialization that requires a
+ // debugger instance.
//------------------------------------------------------------------
static void DebuggerInitialize(Debugger &debugger);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
index 91fd409fb4ed..45bda26e2659 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
@@ -27,9 +27,8 @@
namespace lldb_private {
//----------------------------------------------------------------------
-// Templatized classes for dealing with generic ranges and also
-// collections of ranges, or collections of ranges that have associated
-// data.
+// Templatized classes for dealing with generic ranges and also collections of
+// ranges, or collections of ranges that have associated data.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -214,8 +213,8 @@ public:
else
minimal_ranges.push_back(*pos);
}
- // Use the swap technique in case our new vector is much smaller.
- // We must swap when using the STL because std::vector objects never
+ // Use the swap technique in case our new vector is much smaller. We
+ // must swap when using the STL because std::vector objects never
// release or reduce the memory once it has been allocated/reserved.
m_entries.swap(minimal_ranges);
}
@@ -228,8 +227,8 @@ public:
#endif
if (m_entries.empty())
return fail_value;
- // m_entries must be sorted, so if we aren't empty, we grab the
- // first range's base
+ // m_entries must be sorted, so if we aren't empty, we grab the first
+ // range's base
return m_entries.front().GetRangeBase();
}
@@ -239,8 +238,8 @@ public:
#endif
if (m_entries.empty())
return fail_value;
- // m_entries must be sorted, so if we aren't empty, we grab the
- // last range's end
+ // m_entries must be sorted, so if we aren't empty, we grab the last
+ // range's end
return m_entries.back().GetRangeEnd();
}
@@ -446,8 +445,8 @@ public:
else
minimal_ranges.push_back(*pos);
}
- // Use the swap technique in case our new vector is much smaller.
- // We must swap when using the STL because std::vector objects never
+ // Use the swap technique in case our new vector is much smaller. We
+ // must swap when using the STL because std::vector objects never
// release or reduce the memory once it has been allocated/reserved.
m_entries.swap(minimal_ranges);
}
@@ -460,8 +459,8 @@ public:
#endif
if (m_entries.empty())
return fail_value;
- // m_entries must be sorted, so if we aren't empty, we grab the
- // first range's base
+ // m_entries must be sorted, so if we aren't empty, we grab the first
+ // range's base
return m_entries.front().GetRangeBase();
}
@@ -471,8 +470,8 @@ public:
#endif
if (m_entries.empty())
return fail_value;
- // m_entries must be sorted, so if we aren't empty, we grab the
- // last range's end
+ // m_entries must be sorted, so if we aren't empty, we grab the last
+ // range's end
return m_entries.back().GetRangeEnd();
}
@@ -604,8 +603,8 @@ protected:
//----------------------------------------------------------------------
// A simple range with data class where you get to define the type of
-// the range base "B", the type used for the range byte size "S", and
-// the type for the associated data "T".
+// the range base "B", the type used for the range byte size "S", and the type
+// for the associated data "T".
//----------------------------------------------------------------------
template <typename B, typename S, typename T>
struct RangeData : public Range<B, S> {
@@ -688,8 +687,8 @@ public:
}
}
- // We we can combine at least one entry, then we make a new collection
- // and populate it accordingly, and then swap it into place.
+ // We we can combine at least one entry, then we make a new collection and
+ // populate it accordingly, and then swap it into place.
if (can_combine) {
Collection minimal_ranges;
for (pos = m_entries.begin(), end = m_entries.end(), prev = end;
@@ -699,9 +698,9 @@ public:
else
minimal_ranges.push_back(*pos);
}
- // Use the swap technique in case our new vector is much smaller.
- // We must swap when using the STL because std::vector objects never
- // release or reduce the memory once it has been allocated/reserved.
+ // Use the swap technique in case our new vector is much smaller. We must
+ // swap when using the STL because std::vector objects never release or
+ // reduce the memory once it has been allocated/reserved.
m_entries.swap(minimal_ranges);
}
}
@@ -828,8 +827,8 @@ protected:
Collection m_entries;
};
-// Same as RangeDataArray, but uses std::vector as to not
-// require static storage of N items in the class itself
+// Same as RangeDataArray, but uses std::vector as to not require static
+// storage of N items in the class itself
template <typename B, typename S, typename T> class RangeDataVector {
public:
typedef RangeData<B, S, T> Entry;
@@ -878,8 +877,8 @@ public:
}
}
- // We we can combine at least one entry, then we make a new collection
- // and populate it accordingly, and then swap it into place.
+ // We we can combine at least one entry, then we make a new collection and
+ // populate it accordingly, and then swap it into place.
if (can_combine) {
Collection minimal_ranges;
for (pos = m_entries.begin(), end = m_entries.end(), prev = end;
@@ -889,15 +888,15 @@ public:
else
minimal_ranges.push_back(*pos);
}
- // Use the swap technique in case our new vector is much smaller.
- // We must swap when using the STL because std::vector objects never
- // release or reduce the memory once it has been allocated/reserved.
+ // Use the swap technique in case our new vector is much smaller. We must
+ // swap when using the STL because std::vector objects never release or
+ // reduce the memory once it has been allocated/reserved.
m_entries.swap(minimal_ranges);
}
}
- // Calculate the byte size of ranges with zero byte sizes by finding
- // the next entry with a base address > the current base address
+ // Calculate the byte size of ranges with zero byte sizes by finding the next
+ // entry with a base address > the current base address
void CalculateSizesOfZeroByteSizeRanges(S full_size = 0) {
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert(IsSorted());
@@ -907,9 +906,9 @@ public:
typename Collection::iterator next;
for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos) {
if (pos->GetByteSize() == 0) {
- // Watch out for multiple entries with same address and make sure
- // we find an entry that is greater than the current base address
- // before we use that for the size
+ // Watch out for multiple entries with same address and make sure we
+ // find an entry that is greater than the current base address before
+ // we use that for the size
auto curr_base = pos->GetRangeBase();
for (next = pos + 1; next != end; ++next) {
auto next_base = next->GetRangeBase();
@@ -1060,8 +1059,8 @@ public:
}
// This method will return the entry that contains the given address, or the
- // entry following that address. If you give it an address of 0 and the first
- // entry starts at address 0x100, you will get the entry at 0x100.
+ // entry following that address. If you give it an address of 0 and the
+ // first entry starts at address 0x100, you will get the entry at 0x100.
//
// For most uses, FindEntryThatContains is the correct one to use, this is a
// less commonly needed behavior. It was added for core file memory regions,
@@ -1102,8 +1101,8 @@ protected:
//----------------------------------------------------------------------
// A simple range with data class where you get to define the type of
-// the range base "B", the type used for the range byte size "S", and
-// the type for the associated data "T".
+// the range base "B", the type used for the range byte size "S", and the type
+// for the associated data "T".
//----------------------------------------------------------------------
template <typename B, typename T> struct AddressData {
typedef B BaseType;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h b/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h
index a45db00fb76e..b369c3dff9a9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h
@@ -35,7 +35,7 @@ namespace lldb_private {
class RegisterValue {
public:
- enum { kMaxRegisterByteSize = 32u };
+ enum { kMaxRegisterByteSize = 64u };
enum Type {
eTypeInvalid,
@@ -95,14 +95,13 @@ public:
bool GetData(DataExtractor &data) const;
- // Copy the register value from this object into a buffer in "dst"
- // and obey the "dst_byte_order" when copying the data. Also watch out
- // in case "dst_len" is longer or shorter than the register value
- // described by "reg_info" and only copy the least significant bytes
- // of the register value, or pad the destination with zeroes if the
- // register byte size is shorter that "dst_len" (all while correctly
- // abiding the "dst_byte_order"). Returns the number of bytes copied
- // into "dst".
+ // Copy the register value from this object into a buffer in "dst" and obey
+ // the "dst_byte_order" when copying the data. Also watch out in case
+ // "dst_len" is longer or shorter than the register value described by
+ // "reg_info" and only copy the least significant bytes of the register
+ // value, or pad the destination with zeroes if the register byte size is
+ // shorter that "dst_len" (all while correctly abiding the "dst_byte_order").
+ // Returns the number of bytes copied into "dst".
uint32_t GetAsMemoryData(const RegisterInfo *reg_info, void *dst,
uint32_t dst_len, lldb::ByteOrder dst_byte_order,
Status &error) const;
@@ -249,12 +248,6 @@ public:
Status SetValueFromData(const RegisterInfo *reg_info, DataExtractor &data,
lldb::offset_t offset, bool partial_data_ok);
- // The default value of 0 for reg_name_right_align_at means no alignment at
- // all.
- bool Dump(Stream *s, const RegisterInfo *reg_info, bool prefix_with_name,
- bool prefix_with_alt_name, lldb::Format format,
- uint32_t reg_name_right_align_at = 0) const;
-
const void *GetBytes() const;
lldb::ByteOrder GetByteOrder() const {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h b/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h
index d851ed5464c9..55f1ac05c975 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h
@@ -40,8 +40,8 @@ struct CStringEqualBinaryPredicate {
};
//----------------------------------------------------------------------
-// Templated type for finding an entry in a std::map<F,S> whose value
-// is equal to something
+// Templated type for finding an entry in a std::map<F,S> whose value is equal
+// to something
//----------------------------------------------------------------------
template <class F, class S> class ValueEquals {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h b/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h
index 943398b88020..40671a242ec3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h
@@ -36,9 +36,9 @@ namespace lldb_private {
//----------------------------------------------------------------------
// A class designed to hold onto values and their corresponding types.
-// Operators are defined and Scalar objects will correctly promote
-// their types and values before performing these operations. Type
-// promotion currently follows the ANSI C type promotion rules.
+// Operators are defined and Scalar objects will correctly promote their types
+// and values before performing these operations. Type promotion currently
+// follows the ANSI C type promotion rules.
//----------------------------------------------------------------------
class Scalar {
public:
@@ -50,13 +50,13 @@ public:
e_ulong,
e_slonglong,
e_ulonglong,
- e_float,
- e_double,
- e_long_double,
- e_uint128,
e_sint128,
+ e_uint128,
+ e_sint256,
e_uint256,
- e_sint256
+ e_float,
+ e_double,
+ e_long_double
};
//------------------------------------------------------------------
@@ -165,8 +165,6 @@ public:
bool Promote(Scalar::Type type);
- bool Cast(Scalar::Type type);
-
bool MakeSigned();
bool MakeUnsigned();
@@ -182,10 +180,10 @@ public:
static Scalar::Type GetValueTypeForFloatWithByteSize(size_t byte_size);
//----------------------------------------------------------------------
- // All operators can benefits from the implicit conversions that will
- // happen automagically by the compiler, so no temporary objects will
- // need to be created. As a result, we currently don't need a variety of
- // overloaded set value accessors.
+ // All operators can benefits from the implicit conversions that will happen
+ // automagically by the compiler, so no temporary objects will need to be
+ // created. As a result, we currently don't need a variety of overloaded set
+ // value accessors.
//----------------------------------------------------------------------
Scalar &operator=(const int i);
Scalar &operator=(unsigned int v);
@@ -204,27 +202,27 @@ public:
Scalar &operator&=(const Scalar &rhs);
//----------------------------------------------------------------------
- // Shifts the current value to the right without maintaining the current
- // sign of the value (if it is signed).
+ // Shifts the current value to the right without maintaining the current sign
+ // of the value (if it is signed).
//----------------------------------------------------------------------
bool ShiftRightLogical(const Scalar &rhs); // Returns true on success
//----------------------------------------------------------------------
- // Takes the absolute value of the current value if it is signed, else
- // the value remains unchanged.
- // Returns false if the contained value has a void type.
+ // Takes the absolute value of the current value if it is signed, else the
+ // value remains unchanged. Returns false if the contained value has a void
+ // type.
//----------------------------------------------------------------------
bool AbsoluteValue(); // Returns true on success
//----------------------------------------------------------------------
- // Negates the current value (even for unsigned values).
- // Returns false if the contained value has a void type.
+ // Negates the current value (even for unsigned values). Returns false if the
+ // contained value has a void type.
//----------------------------------------------------------------------
bool UnaryNegate(); // Returns true on success
//----------------------------------------------------------------------
- // Inverts all bits in the current value as long as it isn't void or
- // a float/double/long double type.
- // Returns false if the contained value has a void/float/double/long
- // double type, else the value is inverted and true is returned.
+ // Inverts all bits in the current value as long as it isn't void or a
+ // float/double/long double type. Returns false if the contained value has a
+ // void/float/double/long double type, else the value is inverted and true is
+ // returned.
//----------------------------------------------------------------------
bool OnesComplement(); // Returns true on success
@@ -234,9 +232,9 @@ public:
Scalar::Type GetType() const { return m_type; }
//----------------------------------------------------------------------
- // Returns a casted value of the current contained data without
- // modifying the current value. FAIL_VALUE will be returned if the type
- // of the value is void or invalid.
+ // Returns a casted value of the current contained data without modifying the
+ // current value. FAIL_VALUE will be returned if the type of the value is
+ // void or invalid.
//----------------------------------------------------------------------
int SInt(int fail_value = 0) const;
@@ -344,8 +342,8 @@ private:
};
//----------------------------------------------------------------------
-// Split out the operators into a format where the compiler will be able
-// to implicitly convert numbers into Scalar objects.
+// Split out the operators into a format where the compiler will be able to
+// implicitly convert numbers into Scalar objects.
//
// This allows code like:
// Scalar two(2);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h b/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h
index 5861afc801cb..2e641983dc73 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h
@@ -52,9 +52,9 @@ class Target;
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class Searcher SearchFilter.h "lldb/Core/SearchFilter.h"
-/// @brief Class that is driven by the SearchFilter to search the
-/// SymbolContext space of the target program.
+/// @class Searcher SearchFilter.h "lldb/Core/SearchFilter.h" Class that is
+/// driven by the SearchFilter to search the SymbolContext space of the target
+/// program.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -99,10 +99,10 @@ public:
};
//----------------------------------------------------------------------
-/// @class SearchFilter SearchFilter.h "lldb/Core/SearchFilter.h"
-/// @brief Class descends through the SymbolContext space of the target,
-/// applying a filter at each stage till it reaches the depth specified by
-/// the GetDepth method of the searcher, and calls its callback at that point.
+/// @class SearchFilter SearchFilter.h "lldb/Core/SearchFilter.h" Class
+/// descends through the SymbolContext space of the target, applying a filter
+/// at each stage till it reaches the depth specified by the GetDepth method
+/// of the searcher, and calls its callback at that point.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -110,15 +110,12 @@ public:
/// Provides the callback and search depth for the SearchFilter search.
///
/// The search is done by cooperation between the search filter and the
-/// searcher.
-/// The search filter does the heavy work of recursing through the SymbolContext
-/// space of the target program's symbol space. The Searcher specifies the
-/// depth
-/// at which it wants its callback to be invoked. Note that since the
-/// resolution
-/// of the Searcher may be greater than that of the SearchFilter, before the
-/// Searcher qualifies an address it should pass it to "AddressPasses."
-/// The default implementation is "Everything Passes."
+/// searcher. The search filter does the heavy work of recursing through the
+/// SymbolContext space of the target program's symbol space. The Searcher
+/// specifies the depth at which it wants its callback to be invoked. Note
+/// that since the resolution of the Searcher may be greater than that of the
+/// SearchFilter, before the Searcher qualifies an address it should pass it
+/// to "AddressPasses." The default implementation is "Everything Passes."
//----------------------------------------------------------------------
class SearchFilter {
@@ -172,8 +169,8 @@ public:
virtual bool AddressPasses(Address &addr);
//------------------------------------------------------------------
- /// Call this method with a FileSpec to see if \a file spec passes the filter
- /// as the name of a compilation unit.
+ /// Call this method with a FileSpec to see if \a file spec passes the
+ /// filter as the name of a compilation unit.
///
/// @param[in] fileSpec
/// The file spec to check against the filter.
@@ -218,11 +215,10 @@ public:
virtual void SearchInModuleList(Searcher &searcher, ModuleList &modules);
//------------------------------------------------------------------
- /// This determines which items are REQUIRED for the filter to pass.
- /// For instance, if you are filtering by Compilation Unit, obviously
- /// symbols that have no compilation unit can't pass So return
- /// eSymbolContextCU
- /// and search callbacks can then short cut the search to avoid looking at
+ /// This determines which items are REQUIRED for the filter to pass. For
+ /// instance, if you are filtering by Compilation Unit, obviously symbols
+ /// that have no compilation unit can't pass So return eSymbolContextCU and
+ /// search callbacks can then short cut the search to avoid looking at
/// things that obviously won't pass.
///
/// @return
@@ -303,8 +299,7 @@ protected:
OptionNames name, FileSpecList &file_list);
// These are utility functions to assist with the search iteration. They are
- // used by the
- // default Search method.
+ // used by the default Search method.
Searcher::CallbackReturn DoModuleIteration(const SymbolContext &context,
Searcher &searcher);
@@ -333,9 +328,9 @@ private:
//----------------------------------------------------------------------
/// @class SearchFilterForUnconstrainedSearches SearchFilter.h
-/// "lldb/Core/SearchFilter.h"
-/// @brief This is a SearchFilter that searches through all modules. It also
-/// consults the Target::ModuleIsExcludedForUnconstrainedSearches.
+/// "lldb/Core/SearchFilter.h" This is a SearchFilter that searches through
+/// all modules. It also consults the
+/// Target::ModuleIsExcludedForUnconstrainedSearches.
//----------------------------------------------------------------------
class SearchFilterForUnconstrainedSearches : public SearchFilter {
public:
@@ -360,8 +355,8 @@ protected:
};
//----------------------------------------------------------------------
-/// @class SearchFilterByModule SearchFilter.h "lldb/Core/SearchFilter.h"
-/// @brief This is a SearchFilter that restricts the search to a given module.
+/// @class SearchFilterByModule SearchFilter.h "lldb/Core/SearchFilter.h" This
+/// is a SearchFilter that restricts the search to a given module.
//----------------------------------------------------------------------
class SearchFilterByModule : public SearchFilter {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Section.h b/contrib/llvm/tools/lldb/include/lldb/Core/Section.h
index 2d5d6443ba7f..8e275ce3199e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Section.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Section.h
@@ -182,6 +182,8 @@ public:
lldb::SectionType GetType() const { return m_type; }
+ const char *GetTypeAsCString() const;
+
lldb::SectionSP GetParent() const { return m_parent_wp.lock(); }
bool IsThreadSpecific() const { return m_thread_specific; }
@@ -270,10 +272,9 @@ protected:
SectionList m_children; // Child sections
bool m_fake : 1, // If true, then this section only can contain the address if
// one of its
- // children contains an address. This allows for gaps between the children
- // that are contained in the address range for this section, but do not
- // produce
- // hits unless the children contain the address.
+ // children contains an address. This allows for gaps between the
+ // children that are contained in the address range for this section, but
+ // do not produce hits unless the children contain the address.
m_encrypted : 1, // Set to true if the contents are encrypted
m_thread_specific : 1, // This section is thread specific
m_readable : 1, // If this section has read permissions
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h b/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h
index 053badf64ddc..ef652531244d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h
@@ -106,9 +106,8 @@ public:
#ifndef SWIG
// The SourceFileCache class separates the source manager from the cache of
- // source files, so the
- // cache can be stored in the Debugger, but the source managers can be per
- // target.
+ // source files, so the cache can be stored in the Debugger, but the source
+ // managers can be per target.
class SourceFileCache {
public:
SourceFileCache() = default;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamBuffer.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamBuffer.h
index 3b18573021b3..307dc7e18a5e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamBuffer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamBuffer.h
@@ -39,9 +39,8 @@ public:
void Clear() { m_packet.clear(); }
// Beware, this might not be NULL terminated as you can expect from
- // StringString as there may be random bits in the llvm::SmallVector. If
- // you are using this class to create a C string, be sure the call PutChar
- // ('\0')
+ // StringString as there may be random bits in the llvm::SmallVector. If you
+ // are using this class to create a C string, be sure the call PutChar ('\0')
// after you have created your string, or use StreamString.
const char *GetData() const { return m_packet.data(); }
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h
index 49c55e96abe1..44ec2464385f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h
@@ -46,7 +46,7 @@ public:
}
void Clear() {
- stds::lock_guard<_MutexType> guard(m_mutex);
+ std::lock_guard<_MutexType> guard(m_mutex);
m_set.clear();
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeValue.h b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeValue.h
index 60eaf91c4f02..10ef8fa41d0c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeValue.h
@@ -17,6 +17,7 @@
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-defines.h"
namespace lldb_private {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h
index e8c6c7c1353e..fe3e831a6045 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h
@@ -25,11 +25,10 @@ namespace lldb_private {
//----------------------------------------------------------------------
// Templatized uniqued string map.
//
-// This map is useful for mapping unique C string names to values of
-// type T. Each "const char *" name added must be unique for a given
+// This map is useful for mapping unique C string names to values of type T.
+// Each "const char *" name added must be unique for a given
// C string value. ConstString::GetCString() can provide such strings.
-// Any other string table that has guaranteed unique values can also
-// be used.
+// Any other string table that has guaranteed unique values can also be used.
//----------------------------------------------------------------------
template <typename T> class UniqueCStringMap {
public:
@@ -51,9 +50,9 @@ public:
};
//------------------------------------------------------------------
- // Call this function multiple times to add a bunch of entries to
- // this map, then later call UniqueCStringMap<T>::Sort() before doing
- // any searches by name.
+ // Call this function multiple times to add a bunch of entries to this map,
+ // then later call UniqueCStringMap<T>::Sort() before doing any searches by
+ // name.
//------------------------------------------------------------------
void Append(ConstString unique_cstr, const T &value) {
m_map.push_back(typename UniqueCStringMap<T>::Entry(unique_cstr, value));
@@ -64,8 +63,8 @@ public:
void Clear() { m_map.clear(); }
//------------------------------------------------------------------
- // Call this function to always keep the map sorted when putting
- // entries into the map.
+ // Call this function to always keep the map sorted when putting entries into
+ // the map.
//------------------------------------------------------------------
void Insert(ConstString unique_cstr, const T &value) {
typename UniqueCStringMap<T>::Entry e(unique_cstr, value);
@@ -79,8 +78,8 @@ public:
//------------------------------------------------------------------
// Get an entries by index in a variety of forms.
//
- // The caller is responsible for ensuring that the collection does
- // not change during while using the returned values.
+ // The caller is responsible for ensuring that the collection does not change
+ // during while using the returned values.
//------------------------------------------------------------------
bool GetValueAtIndex(uint32_t idx, T &value) const {
if (idx < m_map.size()) {
@@ -94,12 +93,12 @@ public:
return m_map[idx].cstring;
}
- // Use this function if you have simple types in your map that you
- // can easily copy when accessing values by index.
+ // Use this function if you have simple types in your map that you can easily
+ // copy when accessing values by index.
T GetValueAtIndexUnchecked(uint32_t idx) const { return m_map[idx].value; }
- // Use this function if you have complex types in your map that you
- // don't want to copy when accessing values by index.
+ // Use this function if you have complex types in your map that you don't
+ // want to copy when accessing values by index.
const T &GetValueRefAtIndexUnchecked(uint32_t idx) const {
return m_map[idx].value;
}
@@ -111,8 +110,8 @@ public:
//------------------------------------------------------------------
// Find the value for the unique string in the map.
//
- // Return the value for \a unique_cstr if one is found, return
- // \a fail_value otherwise. This method works well for simple type
+ // Return the value for \a unique_cstr if one is found, return \a fail_value
+ // otherwise. This method works well for simple type
// T values and only if there is a sensible failure value that can
// be returned and that won't match any existing values.
//------------------------------------------------------------------
@@ -128,11 +127,11 @@ public:
}
//------------------------------------------------------------------
- // Get a pointer to the first entry that matches "name". nullptr will
- // be returned if there is no entry that matches "name".
+ // Get a pointer to the first entry that matches "name". nullptr will be
+ // returned if there is no entry that matches "name".
//
- // The caller is responsible for ensuring that the collection does
- // not change during while using the returned pointer.
+ // The caller is responsible for ensuring that the collection does not change
+ // during while using the returned pointer.
//------------------------------------------------------------------
const Entry *FindFirstValueForName(ConstString unique_cstr) const {
Entry search_entry(unique_cstr);
@@ -144,12 +143,12 @@ public:
}
//------------------------------------------------------------------
- // Get a pointer to the next entry that matches "name" from a
- // previously returned Entry pointer. nullptr will be returned if there
- // is no subsequent entry that matches "name".
+ // Get a pointer to the next entry that matches "name" from a previously
+ // returned Entry pointer. nullptr will be returned if there is no subsequent
+ // entry that matches "name".
//
- // The caller is responsible for ensuring that the collection does
- // not change during while using the returned pointer.
+ // The caller is responsible for ensuring that the collection does not change
+ // during while using the returned pointer.
//------------------------------------------------------------------
const Entry *FindNextValueForName(const Entry *entry_ptr) const {
if (!m_map.empty()) {
@@ -204,16 +203,15 @@ public:
bool IsEmpty() const { return m_map.empty(); }
//------------------------------------------------------------------
- // Reserve memory for at least "n" entries in the map. This is
- // useful to call when you know you will be adding a lot of entries
- // using UniqueCStringMap::Append() (which should be followed by a
- // call to UniqueCStringMap::Sort()) or to UniqueCStringMap::Insert().
+ // Reserve memory for at least "n" entries in the map. This is useful to call
+ // when you know you will be adding a lot of entries using
+ // UniqueCStringMap::Append() (which should be followed by a call to
+ // UniqueCStringMap::Sort()) or to UniqueCStringMap::Insert().
//------------------------------------------------------------------
void Reserve(size_t n) { m_map.reserve(n); }
//------------------------------------------------------------------
- // Sort the unsorted contents in this map. A typical code flow would
- // be:
+ // Sort the unsorted contents in this map. A typical code flow would be:
// size_t approximate_num_entries = ....
// UniqueCStringMap<uint32_t> my_map;
// my_map.Reserve (approximate_num_entries);
@@ -226,12 +224,11 @@ public:
void Sort() { std::sort(m_map.begin(), m_map.end()); }
//------------------------------------------------------------------
- // Since we are using a vector to contain our items it will always
- // double its memory consumption as things are added to the vector,
- // so if you intend to keep a UniqueCStringMap around and have
- // a lot of entries in the map, you will want to call this function
- // to create a new vector and copy _only_ the exact size needed as
- // part of the finalization of the string map.
+ // Since we are using a vector to contain our items it will always double its
+ // memory consumption as things are added to the vector, so if you intend to
+ // keep a UniqueCStringMap around and have a lot of entries in the map, you
+ // will want to call this function to create a new vector and copy _only_ the
+ // exact size needed as part of the finalization of the string map.
//------------------------------------------------------------------
void SizeToFit() {
if (m_map.size() < m_map.capacity()) {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/UserSettingsController.h b/contrib/llvm/tools/lldb/include/lldb/Core/UserSettingsController.h
index 67bc9b2c0713..aefd42e751ab 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/UserSettingsController.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/UserSettingsController.h
@@ -49,8 +49,8 @@ public:
virtual ~Properties() {}
virtual lldb::OptionValuePropertiesSP GetValueProperties() const {
- // This function is virtual in case subclasses want to lazily
- // implement creating the properties.
+ // This function is virtual in case subclasses want to lazily implement
+ // creating the properties.
return m_collection_sp;
}
@@ -82,16 +82,11 @@ public:
// We sometimes need to introduce a setting to enable experimental features,
// but then we don't want the setting for these to cause errors when the
- // setting
- // goes away. Add a sub-topic of the settings using this experimental name,
- // and
- // two things will happen. One is that settings that don't find the name will
- // not
- // be treated as errors. Also, if you decide to keep the settings just move
- // them into
- // the containing properties, and we will auto-forward the experimental
- // settings to the
- // real one.
+ // setting goes away. Add a sub-topic of the settings using this
+ // experimental name, and two things will happen. One is that settings that
+ // don't find the name will not be treated as errors. Also, if you decide to
+ // keep the settings just move them into the containing properties, and we
+ // will auto-forward the experimental settings to the real one.
static const char *GetExperimentalSettingsName();
static bool IsSettingExperimental(llvm::StringRef setting);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Value.h b/contrib/llvm/tools/lldb/include/lldb/Core/Value.h
index 678b56fc49f5..801e818c6f5c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Value.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Value.h
@@ -48,8 +48,8 @@ namespace lldb_private {
class Value {
public:
- // Values Less than zero are an error, greater than or equal to zero
- // returns what the Scalar result is.
+ // Values Less than zero are an error, greater than or equal to zero returns
+ // what the Scalar result is.
enum ValueType {
// m_value contains...
// ============================
@@ -107,8 +107,7 @@ public:
byte_order != lldb::eByteOrderInvalid);
}
// Casts a vector, if valid, to an unsigned int of matching or largest
- // supported size.
- // Truncates to the beginning of the vector if required.
+ // supported size. Truncates to the beginning of the vector if required.
// Returns a default constructed Scalar if the Vector data is internally
// inconsistent.
llvm::APInt rhs = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128,
@@ -229,6 +228,9 @@ public:
static const char *GetContextTypeAsCString(ContextType context_type);
+ /// Convert this value's file address to a load address, if possible.
+ void ConvertToLoadAddress(Module *module, Target *target);
+
bool GetData(DataExtractor &data);
void Clear();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h
index fa1d14870b05..fddc06413196 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h
@@ -11,7 +11,6 @@
#define liblldb_ValueObject_h_
#include "lldb/Core/Value.h"
-#include "lldb/DataFormatters/DumpValueObjectOptions.h" // for DumpValueObj...
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h" // for TypeImpl
#include "lldb/Target/ExecutionContext.h"
@@ -45,6 +44,9 @@ namespace lldb_private {
class Declaration;
}
namespace lldb_private {
+class DumpValueObjectOptions;
+}
+namespace lldb_private {
class EvaluateExpressionOptions;
}
namespace lldb_private {
@@ -286,10 +288,10 @@ public:
return m_exe_ctx_ref;
}
- // Set the EvaluationPoint to the values in exe_scope,
- // Return true if the Evaluation Point changed.
- // Since the ExecutionContextScope is always going to be valid currently,
- // the Updated Context will also always be valid.
+ // Set the EvaluationPoint to the values in exe_scope, Return true if the
+ // Evaluation Point changed. Since the ExecutionContextScope is always
+ // going to be valid currently, the Updated Context will also always be
+ // valid.
// bool
// SetContext (ExecutionContextScope *exe_scope);
@@ -327,8 +329,7 @@ public:
void SetInvalid() {
// Use the stop id to mark us as invalid, leave the thread id and the
- // stack id around for logging and
- // history purposes.
+ // stack id around for logging and history purposes.
m_mod_id.SetInvalid();
// Can't update an invalid state.
@@ -464,17 +465,16 @@ public:
virtual bool SetValueFromCString(const char *value_str, Status &error);
- // Return the module associated with this value object in case the
- // value is from an executable file and might have its data in
- // sections of the file. This can be used for variables.
+ // Return the module associated with this value object in case the value is
+ // from an executable file and might have its data in sections of the file.
+ // This can be used for variables.
virtual lldb::ModuleSP GetModule();
ValueObject *GetRoot();
// Given a ValueObject, loop over itself and its parent, and its parent's
- // parent, ..
- // until either the given callback returns false, or you end up at a null
- // pointer
+ // parent, .. until either the given callback returns false, or you end up at
+ // a null pointer
ValueObject *FollowParentChain(std::function<bool(ValueObject *)>);
virtual bool GetDeclaration(Declaration &decl);
@@ -517,9 +517,9 @@ public:
virtual bool ResolveValue(Scalar &scalar);
- // return 'false' whenever you set the error, otherwise
- // callers may assume true means everything is OK - this will
- // break breakpoint conditions among potentially a few others
+ // return 'false' whenever you set the error, otherwise callers may assume
+ // true means everything is OK - this will break breakpoint conditions among
+ // potentially a few others
virtual bool IsLogicalTrue(Status &error);
virtual const char *GetLocationAsCString();
@@ -646,8 +646,8 @@ public:
virtual lldb::ValueObjectSP CastPointerType(const char *name,
lldb::TypeSP &type_sp);
- // The backing bits of this value object were updated, clear any
- // descriptive string, so we know we have to refetch them
+ // The backing bits of this value object were updated, clear any descriptive
+ // string, so we know we have to refetch them
virtual void ValueUpdated() {
ClearUserVisibleData(eClearUserVisibleDataItemsValue |
eClearUserVisibleDataItemsSummary |
@@ -694,9 +694,8 @@ public:
lldb::ValueObjectSP Persist();
- // returns true if this is a char* or a char[]
- // if it is a char* and check_pointer is true,
- // it also checks that the pointer is valid
+ // returns true if this is a char* or a char[] if it is a char* and
+ // check_pointer is true, it also checks that the pointer is valid
bool IsCStringContainer(bool check_pointer = false);
std::pair<size_t, bool>
@@ -776,11 +775,9 @@ public:
}
// Use GetParent for display purposes, but if you want to tell the parent to
- // update itself
- // then use m_parent. The ValueObjectDynamicValue's parent is not the correct
- // parent for
- // displaying, they are really siblings, so for display it needs to route
- // through to its grandparent.
+ // update itself then use m_parent. The ValueObjectDynamicValue's parent is
+ // not the correct parent for displaying, they are really siblings, so for
+ // display it needs to route through to its grandparent.
virtual ValueObject *GetParent() { return m_parent; }
virtual const ValueObject *GetParent() const { return m_parent; }
@@ -904,9 +901,9 @@ protected:
ValueObjectManager *m_manager; // This object is managed by the root object
// (any ValueObject that gets created
// without a parent.) The manager gets passed through all the generations of
- // dependent objects, and will keep the whole cluster of objects alive as long
- // as a shared pointer to any of them has been handed out. Shared pointers to
- // value objects must always be made with the GetSP method.
+ // dependent objects, and will keep the whole cluster of objects alive as
+ // long as a shared pointer to any of them has been handed out. Shared
+ // pointers to value objects must always be made with the GetSP method.
ChildrenManager m_children;
std::map<ConstString, ValueObject *> m_synthetic_children;
@@ -954,21 +951,19 @@ protected:
// Constructors and Destructors
//------------------------------------------------------------------
- // Use the no-argument constructor to make a constant variable object (with no
- // ExecutionContextScope.)
+ // Use the no-argument constructor to make a constant variable object (with
+ // no ExecutionContextScope.)
ValueObject();
// Use this constructor to create a "root variable object". The ValueObject
- // will be locked to this context
- // through-out its lifespan.
+ // will be locked to this context through-out its lifespan.
ValueObject(ExecutionContextScope *exe_scope,
AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad);
// Use this constructor to create a ValueObject owned by another ValueObject.
- // It will inherit the ExecutionContext
- // of its parent.
+ // It will inherit the ExecutionContext of its parent.
ValueObject(ValueObject &parent);
@@ -990,8 +985,8 @@ protected:
virtual void CalculateSyntheticValue(bool use_synthetic = true);
- // Should only be called by ValueObject::GetChildAtIndex()
- // Returns a ValueObject managed by this ValueObject's manager.
+ // Should only be called by ValueObject::GetChildAtIndex() Returns a
+ // ValueObject managed by this ValueObject's manager.
virtual ValueObject *CreateChildAtIndex(size_t idx,
bool synthetic_array_member,
int32_t synthetic_index);
@@ -1043,8 +1038,9 @@ private:
//------------------------------------------------------------------------------
// A value object manager class that is seeded with the static variable value
// and it vends the user facing value object. If the type is dynamic it can
-// vend the dynamic type. If this user type also has a synthetic type associated
-// with it, it will vend the synthetic type. The class watches the process' stop
+// vend the dynamic type. If this user type also has a synthetic type
+// associated with it, it will vend the synthetic type. The class watches the
+// process' stop
// ID and will update the user type when needed.
//------------------------------------------------------------------------------
class ValueObjectManager {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
index e32e14030418..b3af6c0ae827 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
@@ -39,9 +39,9 @@ namespace lldb_private {
//----------------------------------------------------------------------
// A ValueObject that obtains its children from some source other than
// real information
-// This is currently used to implement Python-based children and filters
-// but you can bind it to any source of synthetic information and have
-// it behave accordingly
+// This is currently used to implement Python-based children and filters but
+// you can bind it to any source of synthetic information and have it behave
+// accordingly
//----------------------------------------------------------------------
class ValueObjectSynthetic : public ValueObject {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h
index 343099bf2a7b..369fa686a9ff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h
@@ -21,15 +21,14 @@
namespace lldb_private {
-// this class is the high-level front-end of LLDB Data Visualization
-// code in FormatManager.h/cpp is the low-level implementation of this feature
-// clients should refer to this class as the entry-point into the data
-// formatters
+// this class is the high-level front-end of LLDB Data Visualization code in
+// FormatManager.h/cpp is the low-level implementation of this feature clients
+// should refer to this class as the entry-point into the data formatters
// unless they have a good reason to bypass this and go to the backend
class DataVisualization {
public:
- // use this call to force the FM to consider itself updated even when there is
- // no apparent reason for that
+ // use this call to force the FM to consider itself updated even when there
+ // is no apparent reason for that
static void ForceUpdate();
static uint32_t GetCurrentRevision();
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h
index c559c212c2db..458477578d3f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h
@@ -160,8 +160,8 @@ public:
private:
bool m_is_regex;
- // this works better than TypeAndOrName because the latter only wraps a TypeSP
- // whereas TypePair can also be backed by a CompilerType
+ // this works better than TypeAndOrName because the latter only wraps a
+ // TypeSP whereas TypePair can also be backed by a CompilerType
struct TypeOrName {
std::string m_type_name;
TypePair m_type_pair;
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h
index 924ef0cdf6b4..e973c8b3e849 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h
@@ -33,12 +33,10 @@
namespace lldb_private {
// this file (and its. cpp) contain the low-level implementation of LLDB Data
-// Visualization
-// class DataVisualization is the high-level front-end of this feature
-// clients should refer to that class as the entry-point into the data
-// formatters
-// unless they have a good reason to bypass it and prefer to use this file's
-// objects directly
+// Visualization class DataVisualization is the high-level front-end of this
+// feature clients should refer to that class as the entry-point into the data
+// formatters unless they have a good reason to bypass it and prefer to use
+// this file's objects directly
class FormatManager : public IFormatChangeListener {
typedef FormatMap<ConstString, TypeSummaryImpl> NamedSummariesMap;
@@ -175,24 +173,22 @@ public:
static const char *GetFormatAsCString(lldb::Format format);
- // if the user tries to add formatters for, say, "struct Foo"
- // those will not match any type because of the way we strip qualifiers from
- // typenames
- // this method looks for the case where the user is adding a
- // "class","struct","enum" or "union" Foo
- // and strips the unnecessary qualifier
+ // if the user tries to add formatters for, say, "struct Foo" those will not
+ // match any type because of the way we strip qualifiers from typenames this
+ // method looks for the case where the user is adding a
+ // "class","struct","enum" or "union" Foo and strips the unnecessary
+ // qualifier
static ConstString GetValidTypeName(const ConstString &type);
// when DataExtractor dumps a vectorOfT, it uses a predefined format for each
- // item
- // this method returns it, or eFormatInvalid if vector_format is not a
+ // item this method returns it, or eFormatInvalid if vector_format is not a
// vectorOf
static lldb::Format GetSingleItemFormat(lldb::Format vector_format);
- // this returns true if the ValueObjectPrinter is *highly encouraged*
- // to actually represent this ValueObject in one-liner format
- // If this object has a summary formatter, however, we should not
- // try and do one-lining, just let the summary do the right thing
+ // this returns true if the ValueObjectPrinter is *highly encouraged* to
+ // actually represent this ValueObject in one-liner format If this object has
+ // a summary formatter, however, we should not try and do one-lining, just
+ // let the summary do the right thing
bool ShouldPrintAsOneLiner(ValueObject &valobj);
void Changed() override;
@@ -249,15 +245,12 @@ private:
TypeCategoryMap &GetCategories() { return m_categories_map; }
- // These functions are meant to initialize formatters that are very
- // low-level/global in nature
- // and do not naturally belong in any language. The intent is that most
- // formatters go in
- // language-specific categories. Eventually, the runtimes should also be
- // allowed to vend their
- // own formatters, and then one could put formatters that depend on specific
- // library load events
- // in the language runtimes, on an as-needed basis
+ // These functions are meant to initialize formatters that are very low-
+ // level/global in nature and do not naturally belong in any language. The
+ // intent is that most formatters go in language-specific categories.
+ // Eventually, the runtimes should also be allowed to vend their own
+ // formatters, and then one could put formatters that depend on specific
+ // library load events in the language runtimes, on an as-needed basis
void LoadSystemFormatters();
void LoadVectorFormatters();
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
index 2df5bf4efcfb..df88e88011fe 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
@@ -43,12 +43,10 @@ public:
virtual uint32_t GetCurrentRevision() = 0;
};
-// if the user tries to add formatters for, say, "struct Foo"
-// those will not match any type because of the way we strip qualifiers from
-// typenames
-// this method looks for the case where the user is adding a
-// "class","struct","enum" or "union" Foo
-// and strips the unnecessary qualifier
+// if the user tries to add formatters for, say, "struct Foo" those will not
+// match any type because of the way we strip qualifiers from typenames this
+// method looks for the case where the user is adding a "class","struct","enum"
+// or "union" Foo and strips the unnecessary qualifier
static inline ConstString GetValidTypeName_Impl(const ConstString &type) {
if (type.IsEmpty())
return type;
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h
index 8d4a099fbec9..18207921bb71 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h
@@ -266,8 +266,7 @@ public:
// I can't use a std::unique_ptr for this because the Deleter is a template
// argument there
// and I want the same type to represent both pointers I want to free and
- // pointers I don't need
- // to free - which is what this class essentially is
+ // pointers I don't need to free - which is what this class essentially is
// It's very specialized to the needs of this file, and not suggested for
// general use
template <typename T = uint8_t, typename U = char, typename S = size_t>
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h
index 8cfe021da3e0..77e3542f5522 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h
@@ -146,10 +146,9 @@ public:
virtual Type GetType() { return Type::eTypeUnknown; }
// we are using a ValueObject* instead of a ValueObjectSP because we do not
- // need to hold on to this for
- // extended periods of time and we trust the ValueObject to stay around for as
- // long as it is required
- // for us to generate its value
+ // need to hold on to this for extended periods of time and we trust the
+ // ValueObject to stay around for as long as it is required for us to
+ // generate its value
virtual bool FormatObject(ValueObject *valobj, std::string &dest) const = 0;
virtual std::string GetDescription() = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h
index 1bde565aa5c8..17cd61ae8c1e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h
@@ -258,10 +258,9 @@ public:
void SetOptions(uint32_t value) { m_flags.SetValue(value); }
// we are using a ValueObject* instead of a ValueObjectSP because we do not
- // need to hold on to this for
- // extended periods of time and we trust the ValueObject to stay around for as
- // long as it is required
- // for us to generate its summary
+ // need to hold on to this for extended periods of time and we trust the
+ // ValueObject to stay around for as long as it is required for us to
+ // generate its summary
virtual bool FormatObject(ValueObject *valobj, std::string &dest,
const TypeSummaryOptions &options) = 0;
@@ -311,8 +310,8 @@ private:
// summaries implemented via a C++ function
struct CXXFunctionSummaryFormat : public TypeSummaryImpl {
- // we should convert these to SBValue and SBStream if we ever cross
- // the boundary towards the external world
+ // we should convert these to SBValue and SBStream if we ever cross the
+ // boundary towards the external world
typedef std::function<bool(ValueObject &, Stream &,
const TypeSummaryOptions &)>
Callback;
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h
index 59fb6d3fcdbb..07dacd670a62 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h
@@ -55,34 +55,29 @@ public:
virtual size_t GetIndexOfChildWithName(const ConstString &name) = 0;
// this function is assumed to always succeed and it if fails, the front-end
- // should know to deal
- // with it in the correct way (most probably, by refusing to return any
- // children)
- // the return value of Update() should actually be interpreted as
- // "ValueObjectSyntheticFilter cache is good/bad"
- // if =true, ValueObjectSyntheticFilter is allowed to use the children it
- // fetched previously and cached
- // if =false, ValueObjectSyntheticFilter must throw away its cache, and query
- // again for children
+ // should know to deal with it in the correct way (most probably, by refusing
+ // to return any children) the return value of Update() should actually be
+ // interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
+ // ValueObjectSyntheticFilter is allowed to use the children it fetched
+ // previously and cached if =false, ValueObjectSyntheticFilter must throw
+ // away its cache, and query again for children
virtual bool Update() = 0;
// if this function returns false, then CalculateNumChildren() MUST return 0
- // since UI frontends
- // might validly decide not to inquire for children given a false return value
- // from this call
- // if it returns true, then CalculateNumChildren() can return any number >= 0
- // (0 being valid)
- // it should if at all possible be more efficient than CalculateNumChildren()
+ // since UI frontends might validly decide not to inquire for children given
+ // a false return value from this call if it returns true, then
+ // CalculateNumChildren() can return any number >= 0 (0 being valid) it
+ // should if at all possible be more efficient than CalculateNumChildren()
virtual bool MightHaveChildren() = 0;
// if this function returns a non-null ValueObject, then the returned
- // ValueObject will stand
- // for this ValueObject whenever a "value" request is made to this ValueObject
+ // ValueObject will stand for this ValueObject whenever a "value" request is
+ // made to this ValueObject
virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
- // if this function returns a non-empty ConstString, then clients are expected
- // to use the return
- // as the name of the type of this ValueObject for display purposes
+ // if this function returns a non-empty ConstString, then clients are
+ // expected to use the return as the name of the type of this ValueObject for
+ // display purposes
virtual ConstString GetSyntheticTypeName() { return ConstString(); }
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
@@ -212,6 +207,19 @@ public:
return *this;
}
+ bool GetFrontEndWantsDereference() const {
+ return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
+ lldb::eTypeOptionFrontEndWantsDereference;
+ }
+
+ Flags &SetFrontEndWantsDereference(bool value = true) {
+ if (value)
+ m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
+ else
+ m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
+ return *this;
+ }
+
uint32_t GetValue() { return m_flags; }
void SetValue(uint32_t value) { m_flags = value; }
@@ -231,6 +239,8 @@ public:
bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
bool NonCacheable() const { return m_flags.GetNonCacheable(); }
+
+ bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
void SetCascades(bool value) { m_flags.SetCascades(value); }
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h
index 3c414e39353f..fa2a89148118 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h
@@ -147,10 +147,9 @@ public:
virtual Type GetType() { return Type::eTypeUnknown; }
// we are using a ValueObject* instead of a ValueObjectSP because we do not
- // need to hold on to this for
- // extended periods of time and we trust the ValueObject to stay around for as
- // long as it is required
- // for us to generate its value
+ // need to hold on to this for extended periods of time and we trust the
+ // ValueObject to stay around for as long as it is required for us to
+ // generate its value
virtual ValidationResult FormatObject(ValueObject *valobj) const = 0;
virtual std::string GetDescription() = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
index 41851436873d..67048a4932cf 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -47,16 +47,16 @@ protected:
InstancePointersSetSP m_printed_instance_pointers;
- // only this class (and subclasses, if any) should ever be concerned with
- // the depth mechanism
+ // only this class (and subclasses, if any) should ever be concerned with the
+ // depth mechanism
ValueObjectPrinter(ValueObject *valobj, Stream *s,
const DumpValueObjectOptions &options,
const DumpValueObjectOptions::PointerDepth &ptr_depth,
uint32_t curr_depth,
InstancePointersSetSP printed_instance_pointers);
- // we should actually be using delegating constructors here
- // but some versions of GCC still have trouble with those
+ // we should actually be using delegating constructors here but some versions
+ // of GCC still have trouble with those
void Init(ValueObject *valobj, Stream *s,
const DumpValueObjectOptions &options,
const DumpValueObjectOptions::PointerDepth &ptr_depth,
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h
index fcf5aba6ecbe..f695d2290502 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h
@@ -13,6 +13,7 @@
#include "lldb/lldb-forward.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/ConstString.h"
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h
index c85aaa5c1f9a..b4bd9697da58 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h
@@ -18,22 +18,22 @@
#include "lldb/lldb-private.h"
#include <functional>
-class DWARFCompileUnit;
+class DWARFUnit;
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class DWARFExpression DWARFExpression.h "lldb/Expression/DWARFExpression.h"
-/// @brief Encapsulates a DWARF location expression and interprets it.
+/// @class DWARFExpression DWARFExpression.h
+/// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location
+/// expression and interprets it.
///
/// DWARF location expressions are used in two ways by LLDB. The first
-/// use is to find entities specified in the debug information, since
-/// their locations are specified in precisely this language. The second
-/// is to interpret expressions without having to run the target in cases
-/// where the overhead from copying JIT-compiled code into the target is
-/// too high or where the target cannot be run. This class encapsulates
-/// a single DWARF location expression or a location list and interprets
-/// it.
+/// use is to find entities specified in the debug information, since their
+/// locations are specified in precisely this language. The second is to
+/// interpret expressions without having to run the target in cases where the
+/// overhead from copying JIT-compiled code into the target is too high or
+/// where the target cannot be run. This class encapsulates a single DWARF
+/// location expression or a location list and interprets it.
//----------------------------------------------------------------------
class DWARFExpression {
public:
@@ -46,7 +46,7 @@ public:
//------------------------------------------------------------------
/// Constructor
//------------------------------------------------------------------
- explicit DWARFExpression(DWARFCompileUnit *dwarf_cu);
+ explicit DWARFExpression(DWARFUnit *dwarf_cu);
//------------------------------------------------------------------
/// Constructor
@@ -62,7 +62,7 @@ public:
/// The byte length of the location expression.
//------------------------------------------------------------------
DWARFExpression(lldb::ModuleSP module, const DataExtractor &data,
- DWARFCompileUnit *dwarf_cu, lldb::offset_t data_offset,
+ DWARFUnit *dwarf_cu, lldb::offset_t data_offset,
lldb::offset_t data_length);
//------------------------------------------------------------------
@@ -130,12 +130,12 @@ public:
//------------------------------------------------------------------
/// If a location is not a location list, return true if the location
- /// contains a DW_OP_addr () opcode in the stream that matches \a
- /// file_addr. If file_addr is LLDB_INVALID_ADDRESS, the this
- /// function will return true if the variable there is any DW_OP_addr
- /// in a location that (yet still is NOT a location list). This helps
- /// us detect if a variable is a global or static variable since
- /// there is no other indication from DWARF debug info.
+ /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr.
+ /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true
+ /// if the variable there is any DW_OP_addr in a location that (yet still is
+ /// NOT a location list). This helps us detect if a variable is a global or
+ /// static variable since there is no other indication from DWARF debug
+ /// info.
///
/// @param[in] op_addr_idx
/// The DW_OP_addr index to retrieve in case there is more than
@@ -161,8 +161,8 @@ public:
&link_address_callback);
//------------------------------------------------------------------
- /// Make the expression parser read its location information from a
- /// given data source. Does not change the offset and length
+ /// Make the expression parser read its location information from a given
+ /// data source. Does not change the offset and length
///
/// @param[in] data
/// A data extractor configured to read the DWARF location expression's
@@ -171,8 +171,8 @@ public:
void SetOpcodeData(const DataExtractor &data);
//------------------------------------------------------------------
- /// Make the expression parser read its location information from a
- /// given data source
+ /// Make the expression parser read its location information from a given
+ /// data source
///
/// @param[in] module_sp
/// The module that defines the DWARF expression.
@@ -193,16 +193,15 @@ public:
//------------------------------------------------------------------
/// Copy the DWARF location expression into a local buffer.
///
- /// It is a good idea to copy the data so we don't keep the entire
- /// object file worth of data around just for a few bytes of location
- /// expression. LLDB typically will mmap the entire contents of debug
- /// information files, and if we use SetOpcodeData, it will get a
- /// shared reference to all of this data for the and cause the object
- /// file to have to stay around. Even worse, a very very large ".a"
- /// that contains one or more .o files could end up being referenced.
- /// Location lists are typically small so even though we are copying
- /// the data, it shouldn't amount to that much for the variables we
- /// end up parsing.
+ /// It is a good idea to copy the data so we don't keep the entire object
+ /// file worth of data around just for a few bytes of location expression.
+ /// LLDB typically will mmap the entire contents of debug information files,
+ /// and if we use SetOpcodeData, it will get a shared reference to all of
+ /// this data for the and cause the object file to have to stay around. Even
+ /// worse, a very very large ".a" that contains one or more .o files could
+ /// end up being referenced. Location lists are typically small so even
+ /// though we are copying the data, it shouldn't amount to that much for the
+ /// variables we end up parsing.
///
/// @param[in] module_sp
/// The module that defines the DWARF expression.
@@ -254,8 +253,8 @@ public:
//------------------------------------------------------------------
/// Wrapper for the static evaluate function that accepts an
- /// ExecutionContextScope instead of an ExecutionContext and uses
- /// member variables to populate many operands
+ /// ExecutionContextScope instead of an ExecutionContext and uses member
+ /// variables to populate many operands
//------------------------------------------------------------------
bool Evaluate(ExecutionContextScope *exe_scope,
lldb::addr_t loclist_base_load_addr,
@@ -263,8 +262,8 @@ public:
Value &result, Status *error_ptr) const;
//------------------------------------------------------------------
- /// Wrapper for the static evaluate function that uses member
- /// variables to populate many operands
+ /// Wrapper for the static evaluate function that uses member variables to
+ /// populate many operands
//------------------------------------------------------------------
bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::addr_t loclist_base_load_addr,
@@ -332,7 +331,7 @@ public:
//------------------------------------------------------------------
static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes,
- DWARFCompileUnit *dwarf_cu, const lldb::offset_t offset,
+ DWARFUnit *dwarf_cu, const lldb::offset_t offset,
const lldb::offset_t length,
const lldb::RegisterKind reg_set,
const Value *initial_value_ptr,
@@ -348,7 +347,7 @@ public:
lldb::addr_t loclist_base_load_addr,
lldb::addr_t address, ABI *abi);
- static size_t LocationListSize(const DWARFCompileUnit *dwarf_cu,
+ static size_t LocationListSize(const DWARFUnit *dwarf_cu,
const DataExtractor &debug_loc_data,
lldb::offset_t offset);
@@ -356,7 +355,7 @@ public:
int address_size, int dwarf_ref_size,
bool location_expression);
- static void PrintDWARFLocationList(Stream &s, const DWARFCompileUnit *cu,
+ static void PrintDWARFLocationList(Stream &s, const DWARFUnit *cu,
const DataExtractor &debug_loc_data,
lldb::offset_t offset);
@@ -389,7 +388,7 @@ protected:
lldb::offset_t &offset, lldb::offset_t &len);
static bool AddressRangeForLocationListEntry(
- const DWARFCompileUnit *dwarf_cu, const DataExtractor &debug_loc_data,
+ const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data,
lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc);
bool GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset,
@@ -401,7 +400,7 @@ protected:
lldb::ModuleWP m_module_wp; ///< Module which defined this expression.
DataExtractor m_data; ///< A data extractor capable of reading opcode bytes
- DWARFCompileUnit *m_dwarf_cu; ///< The DWARF compile unit this expression
+ DWARFUnit *m_dwarf_cu; ///< The DWARF compile unit this expression
///belongs to. It is used
///< to evaluate values indexing into the .debug_addr section (e.g.
///< DW_OP_GNU_addr_index, DW_OP_GNU_const_index)
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h
index 860444e9c2c2..6b9363864722 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h
@@ -28,14 +28,14 @@ namespace lldb_private {
class RecordingMemoryManager;
//----------------------------------------------------------------------
-/// @class Expression Expression.h "lldb/Expression/Expression.h"
-/// @brief Encapsulates a single expression for use in lldb
+/// @class Expression Expression.h "lldb/Expression/Expression.h" Encapsulates
+/// a single expression for use in lldb
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. Expression encapsulates
-/// the objects needed to parse and interpret or JIT an expression. It
-/// uses the expression parser appropriate to the language of the expression
-/// to produce LLVM IR from the expression.
+/// and as a backend for the expr command. Expression encapsulates the
+/// objects needed to parse and interpret or JIT an expression. It uses the
+/// expression parser appropriate to the language of the expression to produce
+/// LLVM IR from the expression.
//----------------------------------------------------------------------
class Expression {
public:
@@ -58,20 +58,19 @@ public:
//------------------------------------------------------------------
/// Return the function name that should be used for executing the
- /// expression. Text() should contain the definition of this
- /// function.
+ /// expression. Text() should contain the definition of this function.
//------------------------------------------------------------------
virtual const char *FunctionName() = 0;
//------------------------------------------------------------------
- /// Return the language that should be used when parsing. To use
- /// the default, return eLanguageTypeUnknown.
+ /// Return the language that should be used when parsing. To use the
+ /// default, return eLanguageTypeUnknown.
//------------------------------------------------------------------
virtual lldb::LanguageType Language() { return lldb::eLanguageTypeUnknown; }
//------------------------------------------------------------------
- /// Return the desired result type of the function, or
- /// eResultTypeAny if indifferent.
+ /// Return the desired result type of the function, or eResultTypeAny if
+ /// indifferent.
//------------------------------------------------------------------
virtual ResultType DesiredResultType() { return eResultTypeAny; }
@@ -80,14 +79,12 @@ public:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Return true if validation code should be inserted into the
- /// expression.
+ /// Return true if validation code should be inserted into the expression.
//------------------------------------------------------------------
virtual bool NeedsValidation() = 0;
//------------------------------------------------------------------
- /// Return true if external variables in the expression should be
- /// resolved.
+ /// Return true if external variables in the expression should be resolved.
//------------------------------------------------------------------
virtual bool NeedsVariableResolution() = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h
index a550d576f437..66957926650a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h
@@ -20,8 +20,8 @@ class IRExecutionUnit;
//----------------------------------------------------------------------
/// @class ExpressionParser ExpressionParser.h
-/// "lldb/Expression/ExpressionParser.h"
-/// @brief Encapsulates an instance of a compiler that can parse expressions.
+/// "lldb/Expression/ExpressionParser.h" Encapsulates an instance of a
+/// compiler that can parse expressions.
///
/// ExpressionParser is the base class for llvm based Expression parsers.
//----------------------------------------------------------------------
@@ -50,8 +50,8 @@ public:
virtual ~ExpressionParser(){};
//------------------------------------------------------------------
- /// Parse a single expression and convert it to IR using Clang. Don't
- /// wrap the expression in anything at all.
+ /// Parse a single expression and convert it to IR using Clang. Don't wrap
+ /// the expression in anything at all.
///
/// @param[in] diagnostic_manager
/// The diagnostic manager in which to store the errors and warnings.
@@ -64,8 +64,8 @@ public:
//------------------------------------------------------------------
/// Try to use the FixIts in the diagnostic_manager to rewrite the
- /// expression. If successful, the rewritten expression is stored
- /// in the diagnostic_manager, get it out with GetFixedExpression.
+ /// expression. If successful, the rewritten expression is stored in the
+ /// diagnostic_manager, get it out with GetFixedExpression.
///
/// @param[in] diagnostic_manager
/// The diagnostic manager containing fixit's to apply.
@@ -78,8 +78,8 @@ public:
}
//------------------------------------------------------------------
- /// Ready an already-parsed expression for execution, possibly
- /// evaluating it statically.
+ /// Ready an already-parsed expression for execution, possibly evaluating it
+ /// statically.
///
/// @param[out] func_addr
/// The address to which the function has been written.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionSourceCode.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionSourceCode.h
index 02fc72aaf251..b5a6187bf3c5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionSourceCode.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionSourceCode.h
@@ -40,9 +40,8 @@ public:
bool static_method, ExecutionContext &exe_ctx) const;
// Given a string returned by GetText, find the beginning and end of the body
- // passed to CreateWrapped.
- // Return true if the bounds could be found. This will also work on text with
- // FixItHints applied.
+ // passed to CreateWrapped. Return true if the bounds could be found. This
+ // will also work on text with FixItHints applied.
static bool GetOriginalBodyBounds(std::string transformed_text,
lldb::LanguageType wrapping_language,
size_t &start_loc, size_t &end_loc);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
index 20a5e67cf9b7..ffcad54fb9f9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
@@ -18,11 +18,11 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ExpressionTypeSystemHelper ExpressionTypeSystemHelper.h
/// "lldb/Expression/ExpressionTypeSystemHelper.h"
-/// @brief A helper object that the Expression can pass to its ExpressionParser
+/// A helper object that the Expression can pass to its ExpressionParser
/// to provide generic information that
/// any type of expression will need to supply. It's only job is to support
-/// dyn_cast so that the expression parser
-/// can cast it back to the requisite specific type.
+/// dyn_cast so that the expression parser can cast it back to the requisite
+/// specific type.
///
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h
index c7570932c15a..89b0500faf9c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h
@@ -69,15 +69,12 @@ public:
void SetName(const ConstString &name) { m_frozen_sp->SetName(name); }
// this function is used to copy the address-of m_live_sp into m_frozen_sp
- // this is necessary because the results of certain cast and
- // pointer-arithmetic
- // operations (such as those described in bugzilla issues 11588 and 11618)
- // generate
- // frozen objects that do not have a valid address-of, which can be
- // troublesome when
- // using synthetic children providers. Transferring the address-of the live
- // object
- // solves these issues and provides the expected user-level behavior
+ // this is necessary because the results of certain cast and pointer-
+ // arithmetic operations (such as those described in bugzilla issues 11588
+ // and 11618) generate frozen objects that do not have a valid address-of,
+ // which can be troublesome when using synthetic children providers.
+ // Transferring the address-of the live object solves these issues and
+ // provides the expected user-level behavior
void TransferAddress(bool force = false) {
if (m_live_sp.get() == nullptr)
return;
@@ -129,7 +126,7 @@ public:
//----------------------------------------------------------------------
/// @class ExpressionVariableList ExpressionVariable.h
/// "lldb/Expression/ExpressionVariable.h"
-/// @brief A list of variable references.
+/// A list of variable references.
///
/// This class stores variables internally, acting as the permanent store.
//----------------------------------------------------------------------
@@ -242,7 +239,12 @@ public:
lldb::ByteOrder byte_order,
uint32_t addr_byte_size) = 0;
- virtual ConstString GetNextPersistentVariableName() = 0;
+ /// Return a new persistent variable name with the specified prefix.
+ ConstString GetNextPersistentVariableName(Target &target,
+ llvm::StringRef prefix);
+
+ virtual llvm::StringRef
+ GetPersistentVariablePrefix(bool is_error = false) const = 0;
virtual void
RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h b/contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h
index 56305d5181bd..c36263e34240 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h
@@ -29,7 +29,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class FunctionCaller FunctionCaller.h "lldb/Expression/FunctionCaller.h"
-/// @brief Encapsulates a function that can be called.
+/// Encapsulates a function that can be called.
///
/// A given FunctionCaller object can handle a single function signature.
/// Once constructed, it can set up any number of concurrent calls to
@@ -42,8 +42,8 @@ namespace lldb_private {
/// struct with the written arguments. This method lets Clang handle the
/// vagaries of function calling conventions.
///
-/// The simplest use of the FunctionCaller is to construct it with a
-/// function representative of the signature you want to use, then call
+/// The simplest use of the FunctionCaller is to construct it with a function
+/// representative of the signature you want to use, then call
/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
///
/// If you need to reuse the arguments for several calls, you can call
@@ -53,8 +53,8 @@ namespace lldb_private {
/// If you need to call the function on the thread plan stack, you can also
/// call InsertFunction() followed by GetThreadPlanToCallFunction().
///
-/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
-/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
+/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed a
+/// pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
/// and its address returned in that variable.
///
/// Any of the methods that take arg_addr_ptr can be passed nullptr, and the
@@ -170,8 +170,8 @@ public:
DiagnosticManager &diagnostic_manager);
//------------------------------------------------------------------
- /// Insert an argument struct with a non-default function address and
- /// non-default argument values
+ /// Insert an argument struct with a non-default function address and non-
+ /// default argument values
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
@@ -308,28 +308,25 @@ public:
//------------------------------------------------------------------
/// Return the function name that should be used for executing the
- /// expression. Text() should contain the definition of this
- /// function.
+ /// expression. Text() should contain the definition of this function.
//------------------------------------------------------------------
const char *FunctionName() override {
return m_wrapper_function_name.c_str();
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when registering
- /// local variables. May be nullptr if the Expression doesn't care.
+ /// Return the object that the parser should use when registering local
+ /// variables. May be nullptr if the Expression doesn't care.
//------------------------------------------------------------------
ExpressionVariableList *LocalVariables() { return nullptr; }
//------------------------------------------------------------------
- /// Return true if validation code should be inserted into the
- /// expression.
+ /// Return true if validation code should be inserted into the expression.
//------------------------------------------------------------------
bool NeedsValidation() override { return false; }
//------------------------------------------------------------------
- /// Return true if external variables in the expression should be
- /// resolved.
+ /// Return true if external variables in the expression should be resolved.
//------------------------------------------------------------------
bool NeedsVariableResolution() override { return false; }
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h
index b793a60585bb..f31c03cfb9ef 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h
@@ -33,17 +33,18 @@ class Stream;
//----------------------------------------------------------------------
/// @class DynamicCheckerFunctions IRDynamicChecks.h
-/// "lldb/Expression/IRDynamicChecks.h"
-/// @brief Encapsulates dynamic check functions used by expressions.
+/// "lldb/Expression/IRDynamicChecks.h" Encapsulates dynamic check functions
+/// used by expressions.
///
/// Each of the utility functions encapsulated in this class is responsible
-/// for validating some data that an expression is about to use. Examples are:
+/// for validating some data that an expression is about to use. Examples
+/// are:
///
-/// a = *b; // check that b is a valid pointer
-/// [b init]; // check that b is a valid object to send "init" to
+/// a = *b; // check that b is a valid pointer [b init]; // check that b
+/// is a valid object to send "init" to
///
-/// The class installs each checker function into the target process and
-/// makes it available to IRDynamicChecks to use.
+/// The class installs each checker function into the target process and makes
+/// it available to IRDynamicChecks to use.
//----------------------------------------------------------------------
class DynamicCheckerFunctions {
public:
@@ -58,8 +59,8 @@ public:
~DynamicCheckerFunctions();
//------------------------------------------------------------------
- /// Install the utility functions into a process. This binds the
- /// instance of DynamicCheckerFunctions to that process.
+ /// Install the utility functions into a process. This binds the instance
+ /// of DynamicCheckerFunctions to that process.
///
/// @param[in] diagnostic_manager
/// A diagnostic manager to report errors to.
@@ -81,16 +82,16 @@ public:
};
//----------------------------------------------------------------------
-/// @class IRDynamicChecks IRDynamicChecks.h "lldb/Expression/IRDynamicChecks.h"
-/// @brief Adds dynamic checks to a user-entered expression to reduce its
-/// likelihood of crashing
+/// @class IRDynamicChecks IRDynamicChecks.h
+/// "lldb/Expression/IRDynamicChecks.h" Adds dynamic checks to a user-entered
+/// expression to reduce its likelihood of crashing
///
/// When an IR function is executed in the target process, it may cause
-/// crashes or hangs by dereferencing NULL pointers, trying to call Objective-C
-/// methods on objects that do not respond to them, and so forth.
+/// crashes or hangs by dereferencing NULL pointers, trying to call
+/// Objective-C methods on objects that do not respond to them, and so forth.
///
-/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions
-/// to appropriate locations in an expression's IR.
+/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions to
+/// appropriate locations in an expression's IR.
//----------------------------------------------------------------------
class IRDynamicChecks : public llvm::ModulePass {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h
index 703fcd152af4..e73f8956d955 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h
@@ -42,23 +42,23 @@ namespace lldb_private {
class Status;
//----------------------------------------------------------------------
-/// @class IRExecutionUnit IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h"
-/// @brief Contains the IR and, optionally, JIT-compiled code for a module.
+/// @class IRExecutionUnit IRExecutionUnit.h
+/// "lldb/Expression/IRExecutionUnit.h" Contains the IR and, optionally, JIT-
+/// compiled code for a module.
///
-/// This class encapsulates the compiled version of an expression, in IR
-/// form (for interpretation purposes) and in raw machine code form (for
-/// execution in the target).
+/// This class encapsulates the compiled version of an expression, in IR form
+/// (for interpretation purposes) and in raw machine code form (for execution
+/// in the target).
///
-/// This object wraps an IR module that comes from the expression parser,
-/// and knows how to use the JIT to make it into executable code. It can
-/// then be used as input to the IR interpreter, or the address of the
-/// executable code can be passed to a thread plan to run in the target.
+/// This object wraps an IR module that comes from the expression parser, and
+/// knows how to use the JIT to make it into executable code. It can then be
+/// used as input to the IR interpreter, or the address of the executable code
+/// can be passed to a thread plan to run in the target.
///
/// This class creates a subclass of LLVM's SectionMemoryManager, because that
-/// is
-/// how the JIT emits code. Because LLDB needs to move JIT-compiled code
-/// into the target process, the IRExecutionUnit knows how to copy the
-/// emitted code into the target process.
+/// is how the JIT emits code. Because LLDB needs to move JIT-compiled code
+/// into the target process, the IRExecutionUnit knows how to copy the emitted
+/// code into the target process.
//----------------------------------------------------------------------
class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
public IRMemoryMap,
@@ -90,9 +90,9 @@ public:
lldb::addr_t &func_end);
//------------------------------------------------------------------
- /// Accessors for IRForTarget and other clients that may want binary
- /// data placed on their behalf. The binary data is owned by the
- /// IRExecutionUnit unless the client explicitly chooses to free it.
+ /// Accessors for IRForTarget and other clients that may want binary data
+ /// placed on their behalf. The binary data is owned by the IRExecutionUnit
+ /// unless the client explicitly chooses to free it.
//------------------------------------------------------------------
lldb::addr_t WriteNow(const uint8_t *bytes, size_t size, Status &error);
@@ -123,7 +123,7 @@ public:
//----------------------------------------------------------------------
/// @class JittedFunction IRExecutionUnit.h
/// "lldb/Expression/IRExecutionUnit.h"
- /// @brief Encapsulates a single function that has been generated by the JIT.
+ /// Encapsulates a single function that has been generated by the JIT.
///
/// Functions that have been generated by the JIT are first resident in the
/// local process, and then placed in the target process. JittedFunction
@@ -182,9 +182,9 @@ public:
private:
//------------------------------------------------------------------
- /// Look up the object in m_address_map that contains a given address,
- /// find where it was copied to, and return the remote address at the
- /// same offset into the copied entity
+ /// Look up the object in m_address_map that contains a given address, find
+ /// where it was copied to, and return the remote address at the same offset
+ /// into the copied entity
///
/// @param[in] local_address
/// The address in the debugger.
@@ -195,9 +195,9 @@ private:
lldb::addr_t GetRemoteAddressForLocal(lldb::addr_t local_address);
//------------------------------------------------------------------
- /// Look up the object in m_address_map that contains a given address,
- /// find where it was copied to, and return its address range in the
- /// target process
+ /// Look up the object in m_address_map that contains a given address, find
+ /// where it was copied to, and return its address range in the target
+ /// process
///
/// @param[in] local_address
/// The address in the debugger.
@@ -272,8 +272,8 @@ private:
~MemoryManager() override;
//------------------------------------------------------------------
- /// Allocate space for executable code, and add it to the
- /// m_spaceBlocks map
+ /// Allocate space for executable code, and add it to the m_spaceBlocks
+ /// map
///
/// @param[in] Size
/// The size of the area.
@@ -315,8 +315,8 @@ private:
bool IsReadOnly) override;
//------------------------------------------------------------------
- /// Called when object loading is complete and section page
- /// permissions can be applied. Currently unimplemented for LLDB.
+ /// Called when object loading is complete and section page permissions
+ /// can be applied. Currently unimplemented for LLDB.
///
/// @param[out] ErrMsg
/// The error that prevented the page protection from succeeding.
@@ -355,11 +355,11 @@ private:
//----------------------------------------------------------------------
/// @class AllocationRecord IRExecutionUnit.h
- /// "lldb/Expression/IRExecutionUnit.h"
- /// @brief Encapsulates a single allocation request made by the JIT.
+ /// "lldb/Expression/IRExecutionUnit.h" Encapsulates a single allocation
+ /// request made by the JIT.
///
- /// Allocations made by the JIT are first queued up and then applied in
- /// bulk to the underlying process.
+ /// Allocations made by the JIT are first queued up and then applied in bulk
+ /// to the underlying process.
//----------------------------------------------------------------------
enum class AllocationKind { Stub, Code, Data, Global, Bytes };
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h
index 36e03c6fc4f6..2d87346b7066 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h
@@ -29,12 +29,12 @@ class IRMemoryMap;
//----------------------------------------------------------------------
/// @class IRInterpreter IRInterpreter.h "lldb/Expression/IRInterpreter.h"
-/// @brief Attempt to interpret the function's code if it does not require
+/// Attempt to interpret the function's code if it does not require
/// running the target.
///
-/// In some cases, the IR for an expression can be evaluated entirely
-/// in the debugger, manipulating variables but not executing any code
-/// in the target. The IRInterpreter attempts to do this.
+/// In some cases, the IR for an expression can be evaluated entirely in the
+/// debugger, manipulating variables but not executing any code in the target.
+/// The IRInterpreter attempts to do this.
//----------------------------------------------------------------------
class IRInterpreter {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h
index abb5cd745053..df8a03f4763f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h
@@ -20,19 +20,19 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h"
-/// @brief Encapsulates memory that may exist in the process but must
+/// Encapsulates memory that may exist in the process but must
/// also be available in the host process.
///
-/// This class encapsulates a group of memory objects that must be readable
-/// or writable from the host process regardless of whether the process
-/// exists. This allows the IR interpreter as well as JITted code to access
-/// the same memory. All allocations made by this class are represented as
-/// disjoint intervals.
+/// This class encapsulates a group of memory objects that must be readable or
+/// writable from the host process regardless of whether the process exists.
+/// This allows the IR interpreter as well as JITted code to access the same
+/// memory. All allocations made by this class are represented as disjoint
+/// intervals.
///
/// Point queries against this group of memory objects can be made by the
-/// address in the tar at which they reside. If the inferior does not
-/// exist, allocations still get made-up addresses. If an inferior appears
-/// at some point, then those addresses need to be re-mapped.
+/// address in the tar at which they reside. If the inferior does not exist,
+/// allocations still get made-up addresses. If an inferior appears at some
+/// point, then those addresses need to be re-mapped.
//----------------------------------------------------------------------
class IRMemoryMap {
public:
@@ -83,8 +83,8 @@ public:
lldb::TargetSP GetTarget() { return m_target_wp.lock(); }
protected:
- // This function should only be used if you know you are using the JIT.
- // Any other cases should use GetBestExecutionContextScope().
+ // This function should only be used if you know you are using the JIT. Any
+ // other cases should use GetBestExecutionContextScope().
lldb::ProcessWP &GetProcessWP() { return m_process_wp; }
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h
index 745d413e077b..a2f87e8a6e25 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h
@@ -26,25 +26,24 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class LLVMUserExpression LLVMUserExpression.h
-/// "lldb/Expression/LLVMUserExpression.h"
-/// @brief Encapsulates a one-time expression for use in lldb.
+/// "lldb/Expression/LLVMUserExpression.h" Encapsulates a one-time expression
+/// for use in lldb.
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. LLVMUserExpression is a virtual base
-/// class that encapsulates the objects needed to parse and JIT an expression.
-/// The actual parsing part will be provided by the specific implementations
-/// of LLVMUserExpression - which will be vended through the appropriate
-/// TypeSystem.
+/// and as a backend for the expr command. LLVMUserExpression is a virtual
+/// base class that encapsulates the objects needed to parse and JIT an
+/// expression. The actual parsing part will be provided by the specific
+/// implementations of LLVMUserExpression - which will be vended through the
+/// appropriate TypeSystem.
//----------------------------------------------------------------------
class LLVMUserExpression : public UserExpression {
public:
// The IRPasses struct is filled in by a runtime after an expression is
- // compiled and can be used to to run
- // fixups/analysis passes as required. EarlyPasses are run on the generated
- // module before lldb runs its own IR
+ // compiled and can be used to to run fixups/analysis passes as required.
+ // EarlyPasses are run on the generated module before lldb runs its own IR
// fixups and inserts instrumentation code/pointer checks. LatePasses are run
- // after the module has been processed by
- // llvm, before the module is assembled and run in the ThreadPlan.
+ // after the module has been processed by llvm, before the module is
+ // assembled and run in the ThreadPlan.
struct IRPasses {
IRPasses() : EarlyPasses(nullptr), LatePasses(nullptr){};
std::shared_ptr<llvm::legacy::PassManager> EarlyPasses;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h
index ced5cb2bf2b7..96ca80c882e5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h
@@ -30,7 +30,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class UserExpression UserExpression.h "lldb/Expression/UserExpression.h"
-/// @brief Encapsulates a one-time expression for use in lldb.
+/// Encapsulates a one-time expression for use in lldb.
///
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command. UserExpression is a virtual base
@@ -103,8 +103,8 @@ public:
bool MatchesContext(ExecutionContext &exe_ctx);
//------------------------------------------------------------------
- /// Execute the parsed expression by callinng the derived class's
- /// DoExecute method.
+ /// Execute the parsed expression by callinng the derived class's DoExecute
+ /// method.
///
/// @param[in] diagnostic_manager
/// A diagnostic manager to report errors to.
@@ -177,32 +177,29 @@ public:
//------------------------------------------------------------------
/// Return the function name that should be used for executing the
- /// expression. Text() should contain the definition of this
- /// function.
+ /// expression. Text() should contain the definition of this function.
//------------------------------------------------------------------
const char *FunctionName() override { return "$__lldb_expr"; }
//------------------------------------------------------------------
- /// Return the language that should be used when parsing. To use
- /// the default, return eLanguageTypeUnknown.
+ /// Return the language that should be used when parsing. To use the
+ /// default, return eLanguageTypeUnknown.
//------------------------------------------------------------------
lldb::LanguageType Language() override { return m_language; }
//------------------------------------------------------------------
- /// Return the desired result type of the function, or
- /// eResultTypeAny if indifferent.
+ /// Return the desired result type of the function, or eResultTypeAny if
+ /// indifferent.
//------------------------------------------------------------------
ResultType DesiredResultType() override { return m_desired_type; }
//------------------------------------------------------------------
- /// Return true if validation code should be inserted into the
- /// expression.
+ /// Return true if validation code should be inserted into the expression.
//------------------------------------------------------------------
bool NeedsValidation() override { return true; }
//------------------------------------------------------------------
- /// Return true if external variables in the expression should be
- /// resolved.
+ /// Return true if external variables in the expression should be resolved.
//------------------------------------------------------------------
bool NeedsVariableResolution() override { return true; }
@@ -216,8 +213,8 @@ public:
virtual lldb::ModuleSP GetJITModule() { return lldb::ModuleSP(); }
//------------------------------------------------------------------
- /// Evaluate one expression in the scratch context of the
- /// target passed in the exe_ctx and return its result.
+ /// Evaluate one expression in the scratch context of the target passed in
+ /// the exe_ctx and return its result.
///
/// @param[in] exe_ctx
/// The execution context to use when evaluating the expression.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h b/contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h
index 9c54db35fa37..5d4bc8676b95 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h
@@ -25,13 +25,13 @@
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class UtilityFunction UtilityFunction.h "lldb/Expression/UtilityFunction.h"
-/// @brief Encapsulates a bit of source code that provides a function that is
-/// callable
+/// @class UtilityFunction UtilityFunction.h
+/// "lldb/Expression/UtilityFunction.h" Encapsulates a bit of source code that
+/// provides a function that is callable
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. UtilityFunction encapsulates
-/// a self-contained function meant to be used from other code. Utility
+/// and as a backend for the expr command. UtilityFunction encapsulates a
+/// self-contained function meant to be used from other code. Utility
/// functions can perform error-checking for ClangUserExpressions,
//----------------------------------------------------------------------
class UtilityFunction : public Expression {
@@ -69,8 +69,7 @@ public:
/// Check whether the given PC is inside the function
///
/// Especially useful if the function dereferences nullptr to indicate a
- /// failed
- /// assert.
+ /// failed assert.
///
/// @param[in] pc
/// The program counter to check.
@@ -80,8 +79,8 @@ public:
/// false if not (or the function is not JIT compiled)
//------------------------------------------------------------------
bool ContainsAddress(lldb::addr_t address) {
- // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS,
- // so this always returns false if the function is not JIT compiled yet
+ // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS, so
+ // this always returns false if the function is not JIT compiled yet
return (address >= m_jit_start_addr && address < m_jit_end_addr);
}
@@ -93,33 +92,29 @@ public:
//------------------------------------------------------------------
/// Return the function name that should be used for executing the
- /// expression. Text() should contain the definition of this
- /// function.
+ /// expression. Text() should contain the definition of this function.
//------------------------------------------------------------------
const char *FunctionName() override { return m_function_name.c_str(); }
//------------------------------------------------------------------
- /// Return the object that the parser should use when registering
- /// local variables. May be nullptr if the Expression doesn't care.
+ /// Return the object that the parser should use when registering local
+ /// variables. May be nullptr if the Expression doesn't care.
//------------------------------------------------------------------
ExpressionVariableList *LocalVariables() { return nullptr; }
//------------------------------------------------------------------
- /// Return true if validation code should be inserted into the
- /// expression.
+ /// Return true if validation code should be inserted into the expression.
//------------------------------------------------------------------
bool NeedsValidation() override { return false; }
//------------------------------------------------------------------
- /// Return true if external variables in the expression should be
- /// resolved.
+ /// Return true if external variables in the expression should be resolved.
//------------------------------------------------------------------
bool NeedsVariableResolution() override { return false; }
- // This makes the function caller function.
- // Pass in the ThreadSP if you have one available, compilation can end up
- // calling code (e.g. to look up indirect
- // functions) and we don't want this to wander onto another thread.
+ // This makes the function caller function. Pass in the ThreadSP if you have
+ // one available, compilation can end up calling code (e.g. to look up
+ // indirect functions) and we don't want this to wander onto another thread.
FunctionCaller *MakeFunctionCaller(const CompilerType &return_type,
const ValueList &arg_value_list,
lldb::ThreadSP compilation_thread,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake b/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake
index 73f4b8f6cc4a..02a57ad8ca92 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake
@@ -12,8 +12,14 @@
#cmakedefine LLDB_CONFIG_TERMIOS_SUPPORTED
+#cmakedefine01 LLDB_EDITLINE_USE_WCHAR
+
+#cmakedefine01 LLDB_HAVE_EL_RFUNC_T
+
#cmakedefine LLDB_DISABLE_POSIX
+#define LLDB_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}"
+
#cmakedefine01 HAVE_SYS_EVENT_H
#cmakedefine01 HAVE_PPOLL
@@ -24,6 +30,8 @@
#cmakedefine01 HAVE_NR_PROCESS_VM_READV
+#ifndef HAVE_LIBCOMPRESSION
#cmakedefine HAVE_LIBCOMPRESSION
+#endif
#endif // #ifndef LLDB_HOST_CONFIG_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h b/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h
index fc190a4eca8f..ed8e633c113f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h
@@ -25,7 +25,8 @@ namespace lldb_private {
//------------------------------------------------------------------
struct ResumeAction {
lldb::tid_t tid; // The thread ID that this action applies to,
- // LLDB_INVALID_THREAD_ID for the default thread action
+ // LLDB_INVALID_THREAD_ID for the default thread
+ // action
lldb::StateType state; // Valid values are eStateStopped/eStateSuspended,
// eStateRunning, and eStateStepping.
int signal; // When resuming this thread, resume it with this signal if this
@@ -34,10 +35,9 @@ struct ResumeAction {
//------------------------------------------------------------------
// A class that contains instructions for all threads for
-// NativeProcessProtocol::Resume(). Each thread can either run, stay
-// suspended, or step when the process is resumed. We optionally
-// have the ability to also send a signal to the thread when the
-// action is run or step.
+// NativeProcessProtocol::Resume(). Each thread can either run, stay suspended,
+// or step when the process is resumed. We optionally have the ability to also
+// send a signal to the thread when the action is run or step.
//------------------------------------------------------------------
class ResumeActionList {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Editline.h b/contrib/llvm/tools/lldb/include/lldb/Host/Editline.h
index 0b75e9c923ca..beb96e7c4924 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Editline.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Editline.h
@@ -23,8 +23,8 @@
// broken, which is why we're
// working around it here.
// c) When resizing the terminal window, if the cursor moves between rows
-// libedit will get confused.
-// d) The incremental search uses escape to cancel input, so it's confused by
+// libedit will get confused. d) The incremental search uses escape to cancel
+// input, so it's confused by
// ANSI sequences starting with escape.
// e) Emoji support is fairly terrible, presumably it doesn't understand
// composed characters?
@@ -33,24 +33,13 @@
#define liblldb_Editline_h_
#if defined(__cplusplus)
+#if LLDB_EDITLINE_USE_WCHAR
+#include <codecvt>
+#endif
#include <locale>
#include <sstream>
#include <vector>
-// components needed to handle wide characters ( <codecvt>, codecvt_utf8,
-// libedit built with '--enable-widec' )
-// are available on some platforms. The wchar_t versions of libedit functions
-// will only be
-// used in cases where this is true. This is a compile time dependecy, for now
-// selected per target Platform
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
- defined(__OpenBSD__)
-#define LLDB_EDITLINE_USE_WCHAR 1
-#include <codecvt>
-#else
-#define LLDB_EDITLINE_USE_WCHAR 0
-#endif
-
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/lldb-private.h"
@@ -82,7 +71,11 @@ using EditLineStringStreamType = std::stringstream;
using EditLineCharType = char;
#endif
-#ifdef EL_CLIENTDATA /* editline with wide support + wide char read function */
+// At one point the callback type of el_set getchar callback changed from char
+// to wchar_t. It is not possible to detect differentiate between the two
+// versions exactly, but this is a pretty good approximation and allows us to
+// build against almost any editline version out there.
+#if LLDB_EDITLINE_USE_WCHAR || defined(EL_CLIENTDATA) || LLDB_HAVE_EL_RFUNC_T
using EditLineGetCharType = wchar_t;
#else
using EditLineGetCharType = char;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/File.h b/contrib/llvm/tools/lldb/include/lldb/Host/File.h
index 1dfa12ea593d..d240f810bc8b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/File.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/File.h
@@ -23,7 +23,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class File File.h "lldb/Host/File.h"
-/// @brief A file class.
+/// A file class.
///
/// A file class that divides abstracts the LLDB core from host file
/// functionality.
@@ -65,9 +65,9 @@ public:
//------------------------------------------------------------------
/// Constructor with path.
///
- /// Takes a path to a file which can be just a filename, or a full
- /// path. If \a path is not nullptr or empty, this function will call
- /// File::Open (const char *path, uint32_t options, uint32_t permissions).
+ /// Takes a path to a file which can be just a filename, or a full path. If
+ /// \a path is not nullptr or empty, this function will call File::Open
+ /// (const char *path, uint32_t options, uint32_t permissions).
///
/// @param[in] path
/// The full or partial path to a file.
@@ -78,7 +78,8 @@ public:
/// @param[in] permissions
/// Options to use when opening (see File::Permissions)
///
- /// @see File::Open (const char *path, uint32_t options, uint32_t permissions)
+ /// @see File::Open (const char *path, uint32_t options, uint32_t
+ /// permissions)
//------------------------------------------------------------------
File(const char *path, uint32_t options,
uint32_t permissions = lldb::eFilePermissionsFileDefault);
@@ -87,8 +88,7 @@ public:
/// Constructor with FileSpec.
///
/// Takes a FileSpec pointing to a file which can be just a filename, or a
- /// full
- /// path. If \a path is not nullptr or empty, this function will call
+ /// full path. If \a path is not nullptr or empty, this function will call
/// File::Open (const char *path, uint32_t options, uint32_t permissions).
///
/// @param[in] filespec
@@ -100,7 +100,8 @@ public:
/// @param[in] permissions
/// Options to use when opening (see File::Permissions)
///
- /// @see File::Open (const char *path, uint32_t options, uint32_t permissions)
+ /// @see File::Open (const char *path, uint32_t options, uint32_t
+ /// permissions)
//------------------------------------------------------------------
File(const FileSpec &filespec, uint32_t options,
uint32_t permissions = lldb::eFilePermissionsFileDefault);
@@ -125,8 +126,8 @@ public:
//------------------------------------------------------------------
/// Convert to pointer operator.
///
- /// This allows code to check a File object to see if it
- /// contains anything valid using code such as:
+ /// This allows code to check a File object to see if it contains anything
+ /// valid using code such as:
///
/// @code
/// File file(...);
@@ -143,8 +144,8 @@ public:
//------------------------------------------------------------------
/// Logical NOT operator.
///
- /// This allows code to check a File object to see if it is
- /// invalid using code such as:
+ /// This allows code to check a File object to see if it is invalid using
+ /// code such as:
///
/// @code
/// File file(...);
@@ -169,8 +170,7 @@ public:
//------------------------------------------------------------------
/// Open a file for read/writing with the specified options.
///
- /// Takes a path to a file which can be just a filename, or a full
- /// path.
+ /// Takes a path to a file which can be just a filename, or a full path.
///
/// @param[in] path
/// The full or partial path to a file.
@@ -202,8 +202,8 @@ public:
/// Read bytes from a file from the current file position.
///
/// NOTE: This function is NOT thread safe. Use the read function
- /// that takes an "off_t &offset" to ensure correct operation in
- /// multi-threaded environments.
+ /// that takes an "off_t &offset" to ensure correct operation in multi-
+ /// threaded environments.
///
/// @param[in] buf
/// A buffer where to put the bytes that are read.
@@ -222,8 +222,8 @@ public:
/// Write bytes to a file at the current file position.
///
/// NOTE: This function is NOT thread safe. Use the write function
- /// that takes an "off_t &offset" to ensure correct operation in
- /// multi-threaded environments.
+ /// that takes an "off_t &offset" to ensure correct operation in multi-
+ /// threaded environments.
///
/// @param[in] buf
/// A buffer where to put the bytes that are read.
@@ -243,10 +243,10 @@ public:
/// Seek to an offset relative to the beginning of the file.
///
/// NOTE: This function is NOT thread safe, other threads that
- /// access this object might also change the current file position.
- /// For thread safe reads and writes see the following functions:
- /// @see File::Read (void *, size_t, off_t &)
- /// @see File::Write (const void *, size_t, off_t &)
+ /// access this object might also change the current file position. For
+ /// thread safe reads and writes see the following functions: @see
+ /// File::Read (void *, size_t, off_t &) @see File::Write (const void *,
+ /// size_t, off_t &)
///
/// @param[in] offset
/// The offset to seek to within the file relative to the
@@ -265,10 +265,10 @@ public:
/// Seek to an offset relative to the current file position.
///
/// NOTE: This function is NOT thread safe, other threads that
- /// access this object might also change the current file position.
- /// For thread safe reads and writes see the following functions:
- /// @see File::Read (void *, size_t, off_t &)
- /// @see File::Write (const void *, size_t, off_t &)
+ /// access this object might also change the current file position. For
+ /// thread safe reads and writes see the following functions: @see
+ /// File::Read (void *, size_t, off_t &) @see File::Write (const void *,
+ /// size_t, off_t &)
///
/// @param[in] offset
/// The offset to seek to within the file relative to the
@@ -287,10 +287,10 @@ public:
/// Seek to an offset relative to the end of the file.
///
/// NOTE: This function is NOT thread safe, other threads that
- /// access this object might also change the current file position.
- /// For thread safe reads and writes see the following functions:
- /// @see File::Read (void *, size_t, off_t &)
- /// @see File::Write (const void *, size_t, off_t &)
+ /// access this object might also change the current file position. For
+ /// thread safe reads and writes see the following functions: @see
+ /// File::Read (void *, size_t, off_t &) @see File::Write (const void *,
+ /// size_t, off_t &)
///
/// @param[in,out] offset
/// The offset to seek to within the file relative to the
@@ -310,8 +310,8 @@ public:
/// Read bytes from a file from the specified file offset.
///
/// NOTE: This function is thread safe in that clients manager their
- /// own file position markers and reads on other threads won't mess
- /// up the current read.
+ /// own file position markers and reads on other threads won't mess up the
+ /// current read.
///
/// @param[in] dst
/// A buffer where to put the bytes that are read.
@@ -335,8 +335,8 @@ public:
/// Read bytes from a file from the specified file offset.
///
/// NOTE: This function is thread safe in that clients manager their
- /// own file position markers and reads on other threads won't mess
- /// up the current read.
+ /// own file position markers and reads on other threads won't mess up the
+ /// current read.
///
/// @param[in,out] num_bytes
/// The number of bytes to read form the current file position
@@ -367,9 +367,9 @@ public:
/// Write bytes to a file at the specified file offset.
///
/// NOTE: This function is thread safe in that clients manager their
- /// own file position markers, though clients will need to implement
- /// their own locking externally to avoid multiple people writing
- /// to the file at the same time.
+ /// own file position markers, though clients will need to implement their
+ /// own locking externally to avoid multiple people writing to the file at
+ /// the same time.
///
/// @param[in] src
/// A buffer containing the bytes to write.
@@ -431,10 +431,9 @@ public:
//------------------------------------------------------------------
/// Return true if this file from a real terminal.
///
- /// Just knowing a file is a interactive isn't enough, we also need
- /// to know if the terminal has a width and height so we can do
- /// cursor movement and other terminal manipulations by sending
- /// escape sequences.
+ /// Just knowing a file is a interactive isn't enough, we also need to know
+ /// if the terminal has a width and height so we can do cursor movement and
+ /// other terminal manipulations by sending escape sequences.
///
/// @return
/// True if this file is a terminal (tty, not a pty) that has
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Host.h b/contrib/llvm/tools/lldb/include/lldb/Host/Host.h
index f099c72381be..459e9f563d1e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Host.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Host.h
@@ -12,8 +12,9 @@
#include "lldb/Host/File.h"
#include "lldb/Host/HostThread.h"
+#include "lldb/Utility/Environment.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/StringList.h"
+#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-private.h"
#include <cerrno>
@@ -56,10 +57,9 @@ inline bool operator!=(WaitStatus a, WaitStatus b) { return !(a == b); }
//----------------------------------------------------------------------
/// @class Host Host.h "lldb/Host/Host.h"
-/// @brief A class that provides host computer information.
+/// A class that provides host computer information.
///
-/// Host is a class that answers information about the host operating
-/// system.
+/// Host is a class that answers information about the host operating system.
//----------------------------------------------------------------------
class Host {
public:
@@ -72,18 +72,17 @@ public:
//------------------------------------------------------------------
/// Start monitoring a child process.
///
- /// Allows easy monitoring of child processes. \a callback will be
- /// called when the child process exits or if it gets a signal. The
- /// callback will only be called with signals if \a monitor_signals
- /// is \b true. \a callback will usually be called from another
- /// thread so the callback function must be thread safe.
+ /// Allows easy monitoring of child processes. \a callback will be called
+ /// when the child process exits or if it gets a signal. The callback will
+ /// only be called with signals if \a monitor_signals is \b true. \a
+ /// callback will usually be called from another thread so the callback
+ /// function must be thread safe.
///
- /// When the callback gets called, the return value indicates if
- /// monitoring should stop. If \b true is returned from \a callback
- /// the information will be removed. If \b false is returned then
- /// monitoring will continue. If the child process exits, the
- /// monitoring will automatically stop after the callback returned
- /// regardless of the callback return value.
+ /// When the callback gets called, the return value indicates if monitoring
+ /// should stop. If \b true is returned from \a callback the information
+ /// will be removed. If \b false is returned then monitoring will continue.
+ /// If the child process exits, the monitoring will automatically stop after
+ /// the callback returned regardless of the callback return value.
///
/// @param[in] callback
/// A function callback to call when a child receives a signal
@@ -126,9 +125,8 @@ public:
static void Kill(lldb::pid_t pid, int signo);
//------------------------------------------------------------------
- /// Get the thread token (the one returned by ThreadCreate when the thread was
- /// created) for the
- /// calling thread in the current process.
+ /// Get the thread token (the one returned by ThreadCreate when the thread
+ /// was created) for the calling thread in the current process.
///
/// @return
/// The thread token for the calling thread in the current process.
@@ -138,11 +136,11 @@ public:
static const char *GetSignalAsCString(int signo);
//------------------------------------------------------------------
- /// Given an address in the current process (the process that
- /// is running the LLDB code), return the name of the module that
- /// it comes from. This can be useful when you need to know the
- /// path to the shared library that your code is running in for
- /// loading resources that are relative to your binary.
+ /// Given an address in the current process (the process that is running the
+ /// LLDB code), return the name of the module that it comes from. This can
+ /// be useful when you need to know the path to the shared library that your
+ /// code is running in for loading resources that are relative to your
+ /// binary.
///
/// @param[in] host_addr
/// The pointer to some code in the current process.
@@ -155,10 +153,9 @@ public:
static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr);
//------------------------------------------------------------------
- /// If you have an executable that is in a bundle and want to get
- /// back to the bundle directory from the path itself, this
- /// function will change a path to a file within a bundle to the
- /// bundle directory itself.
+ /// If you have an executable that is in a bundle and want to get back to
+ /// the bundle directory from the path itself, this function will change a
+ /// path to a file within a bundle to the bundle directory itself.
///
/// @param[in] file
/// A file spec that might point to a file in a bundle.
@@ -176,10 +173,9 @@ public:
FileSpec &bundle_directory);
//------------------------------------------------------------------
- /// When executable files may live within a directory, where the
- /// directory represents an executable bundle (like the MacOSX
- /// app bundles), then locate the executable within the containing
- /// bundle.
+ /// When executable files may live within a directory, where the directory
+ /// represents an executable bundle (like the MacOSX app bundles), then
+ /// locate the executable within the containing bundle.
///
/// @param[in,out] file
/// A file spec that currently points to the bundle that will
@@ -203,11 +199,14 @@ public:
static const lldb::UnixSignalsSP &GetUnixSignals();
+ /// Launch the process specified in launch_info. The monitoring callback in
+ /// launch_info must be set, and it will be called when the process
+ /// terminates.
static Status LaunchProcess(ProcessLaunchInfo &launch_info);
//------------------------------------------------------------------
- /// Perform expansion of the command-line for this launch info
- /// This can potentially involve wildcard expansion
+ /// Perform expansion of the command-line for this launch info This can
+ /// potentially involve wildcard expansion
// environment variable replacement, and whatever other
// argument magic the platform defines as part of its typical
// user experience
@@ -224,8 +223,7 @@ public:
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t timeout_sec,
- bool run_in_default_shell = true);
+ const Timeout<std::micro> &timeout, bool run_in_default_shell = true);
static Status RunShellCommand(
const Args &args,
@@ -236,13 +234,12 @@ public:
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t timeout_sec,
- bool run_in_default_shell = true);
+ const Timeout<std::micro> &timeout, bool run_in_default_shell = true);
static bool OpenFileInExternalEditor(const FileSpec &file_spec,
uint32_t line_no);
- static size_t GetEnvironment(StringList &env);
+ static Environment GetEnvironment();
static std::unique_ptr<Connection>
CreateDefaultConnection(llvm::StringRef url);
@@ -252,8 +249,8 @@ public:
namespace llvm {
template <> struct format_provider<lldb_private::WaitStatus> {
- /// Options = "" gives a human readable description of the status
- /// Options = "g" gives a gdb-remote protocol status (e.g., X09)
+ /// Options = "" gives a human readable description of the status Options =
+ /// "g" gives a gdb-remote protocol status (e.g., X09)
static void format(const lldb_private::WaitStatus &WS, raw_ostream &OS,
llvm::StringRef Options);
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h
index b4a2f8baf37f..df762d7160e0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h
@@ -12,7 +12,7 @@
//----------------------------------------------------------------------
/// @class HostInfo HostInfo.h "lldb/Host/HostInfo.h"
-/// @brief A class that provides host computer information.
+/// A class that provides host computer information.
///
/// HostInfo is a class that answers information about the host operating
/// system. Note that HostInfo is NOT intended to be used to manipulate or
@@ -22,15 +22,16 @@
/// HostInfoWindows) in a separate file, and then typedefed to HostInfo here.
/// Users of the class reference it as HostInfo::method().
///
-/// Not all hosts provide the same functionality. It is important that methods
-/// only be implemented at the lowest level at which they make sense. It should
-/// be up to the clients of the class to ensure that they not attempt to call a
-/// method which doesn't make sense for a particular platform. For example,
-/// when implementing a method that only makes sense on a posix-compliant
-/// system, implement it on HostInfoPosix, and not on HostInfoBase with a
-/// default implementation. This way, users of HostInfo are required to think
-/// about the implications of calling a particular method and if used in a
-/// context where the method doesn't make sense, will generate a compiler error.
+/// Not all hosts provide the same functionality. It is important that
+/// methods only be implemented at the lowest level at which they make sense.
+/// It should be up to the clients of the class to ensure that they not
+/// attempt to call a method which doesn't make sense for a particular
+/// platform. For example, when implementing a method that only makes sense
+/// on a posix-compliant system, implement it on HostInfoPosix, and not on
+/// HostInfoBase with a default implementation. This way, users of HostInfo
+/// are required to think about the implications of calling a particular
+/// method and if used in a context where the method doesn't make sense, will
+/// generate a compiler error.
///
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostInfoBase.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostInfoBase.h
index 52648d2031fc..b2567b296277 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostInfoBase.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostInfoBase.h
@@ -63,25 +63,39 @@ public:
static llvm::Optional<ArchitectureKind> ParseArchitectureKind(llvm::StringRef kind);
- //------------------------------------------------------------------
- /// Find a resource files that are related to LLDB.
- ///
- /// Operating systems have different ways of storing shared
- /// libraries and related resources. This function abstracts the
- /// access to these paths.
- ///
- /// @param[in] path_type
- /// The type of LLDB resource path you are looking for. If the
- /// enumeration ends with "Dir", then only the \a file_spec's
- /// directory member gets filled in.
- ///
- /// @param[in] file_spec
- /// A file spec that gets filled in with the appropriate path.
- ///
- /// @return
- /// \b true if \a resource_path was resolved, \a false otherwise.
- //------------------------------------------------------------------
- static bool GetLLDBPath(lldb::PathType type, FileSpec &file_spec);
+ /// Returns the directory containing the lldb shared library. Only the
+ /// directory member of the FileSpec is filled in.
+ static FileSpec GetShlibDir();
+
+ /// Returns the directory containing the support executables (debugserver,
+ /// ...). Only the directory member of the FileSpec is filled in.
+ static FileSpec GetSupportExeDir();
+
+ /// Returns the directory containing the lldb headers. Only the directory
+ /// member of the FileSpec is filled in.
+ static FileSpec GetHeaderDir();
+
+ /// Returns the directory containing the python modules. Only the directory
+ /// member of the FileSpec is filled in.
+ static FileSpec GetPythonDir();
+
+ /// Returns the directory containing the system plugins. Only the directory
+ /// member of the FileSpec is filled in.
+ static FileSpec GetSystemPluginDir();
+
+ /// Returns the directory containing the user plugins. Only the directory
+ /// member of the FileSpec is filled in.
+ static FileSpec GetUserPluginDir();
+
+ /// Returns the proces temporary directory. This directory will be cleaned up
+ /// when this process exits. Only the directory member of the FileSpec is
+ /// filled in.
+ static FileSpec GetProcessTempDir();
+
+ /// Returns the global temporary directory. This directory will **not** be
+ /// cleaned up when this process exits. Only the directory member of the
+ /// FileSpec is filled in.
+ static FileSpec GetGlobalTempDir();
//---------------------------------------------------------------------------
/// If the triple does not specify the vendor, os, and environment parts, we
@@ -98,7 +112,6 @@ protected:
static bool ComputeTempFileBaseDirectory(FileSpec &file_spec);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec);
- static bool ComputeClangDirectory(FileSpec &file_spec);
static bool ComputeUserPluginsDirectory(FileSpec &file_spec);
static void ComputeHostArchitectureSupport(ArchSpec &arch_32,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostProcess.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostProcess.h
index dfc997bd81f7..626ebab7ce68 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostProcess.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostProcess.h
@@ -15,17 +15,17 @@
//----------------------------------------------------------------------
/// @class HostInfo HostInfo.h "lldb/Host/HostProcess.h"
-/// @brief A class that represents a running process on the host machine.
+/// A class that represents a running process on the host machine.
///
/// HostProcess allows querying and manipulation of processes running on the
-/// host machine. It is not intended to be represent a process which is
-/// being debugged, although the native debug engine of a platform may likely
-/// back inferior processes by a HostProcess.
+/// host machine. It is not intended to be represent a process which is being
+/// debugged, although the native debug engine of a platform may likely back
+/// inferior processes by a HostProcess.
///
/// HostProcess is implemented using static polymorphism so that on any given
-/// platform, an instance of HostProcess will always be able to bind statically
-/// to the concrete Process implementation for that platform. See HostInfo
-/// for more details.
+/// platform, an instance of HostProcess will always be able to bind
+/// statically to the concrete Process implementation for that platform. See
+/// HostInfo for more details.
///
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostThread.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostThread.h
index 0d2fbe6045af..120776283aa4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostThread.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostThread.h
@@ -22,7 +22,7 @@ class HostNativeThreadBase;
//----------------------------------------------------------------------
/// @class HostInfo HostInfo.h "lldb/Host/HostThread.h"
-/// @brief A class that represents a thread running inside of a process on the
+/// A class that represents a thread running inside of a process on the
/// local machine.
///
/// HostThread allows querying and manipulation of threads running on the host
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/MainLoop.h b/contrib/llvm/tools/lldb/include/lldb/Host/MainLoop.h
index c59a5aa5b0e8..13d1ff0212fa 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/MainLoop.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/MainLoop.h
@@ -21,12 +21,12 @@
namespace lldb_private {
-// Implementation of the MainLoopBase class. It can monitor file descriptors for
-// readability using ppoll, kqueue, poll or WSAPoll. On Windows it only supports
-// polling sockets, and will not work on generic file handles or pipes. On
-// systems without kqueue or ppoll handling singnals is not supported. In
-// addition to the common base, this class provides the ability to invoke a
-// given handler when a signal is received.
+// Implementation of the MainLoopBase class. It can monitor file descriptors
+// for readability using ppoll, kqueue, poll or WSAPoll. On Windows it only
+// supports polling sockets, and will not work on generic file handles or
+// pipes. On systems without kqueue or ppoll handling singnals is not
+// supported. In addition to the common base, this class provides the ability
+// to invoke a given handler when a signal is received.
//
// Since this class is primarily intended to be used for single-threaded
// processing, it does not attempt to perform any internal synchronisation and
@@ -49,13 +49,13 @@ public:
const Callback &callback,
Status &error) override;
- // Listening for signals from multiple MainLoop instances is perfectly safe as
- // long as they don't try to listen for the same signal. The callback function
- // is invoked when the control returns to the Run() function, not when the
- // hander is executed. This mean that you can treat the callback as a normal
- // function and perform things which would not be safe in a signal handler.
- // However, since the callback is not invoked synchronously, you cannot use
- // this mechanism to handle SIGSEGV and the like.
+ // Listening for signals from multiple MainLoop instances is perfectly safe
+ // as long as they don't try to listen for the same signal. The callback
+ // function is invoked when the control returns to the Run() function, not
+ // when the hander is executed. This mean that you can treat the callback as
+ // a normal function and perform things which would not be safe in a signal
+ // handler. However, since the callback is not invoked synchronously, you
+ // cannot use this mechanism to handle SIGSEGV and the like.
SignalHandleUP RegisterSignal(int signo, const Callback &callback,
Status &error);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h b/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h
index a87d262e9452..bf01ba16db0e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h
@@ -18,21 +18,17 @@
namespace lldb_private {
// The purpose of this class is to enable multiplexed processing of data from
-// different sources
-// without resorting to multi-threading. Clients can register IOObjects, which
-// will be monitored
-// for readability, and when they become ready, the specified callback will be
-// invoked.
-// Monitoring for writability is not supported, but can be easily added if
-// needed.
+// different sources without resorting to multi-threading. Clients can register
+// IOObjects, which will be monitored for readability, and when they become
+// ready, the specified callback will be invoked. Monitoring for writability is
+// not supported, but can be easily added if needed.
//
// The RegisterReadObject function return a handle, which controls the duration
-// of the monitoring. When
-// this handle is destroyed, the callback is deregistered.
+// of the monitoring. When this handle is destroyed, the callback is
+// deregistered.
//
// This class simply defines the interface common for all platforms, actual
-// implementations are
-// platform-specific.
+// implementations are platform-specific.
class MainLoopBase {
private:
class ReadHandle;
@@ -52,8 +48,7 @@ public:
}
// Waits for registered events and invoke the proper callbacks. Returns when
- // all callbacks
- // deregister themselves or when someone requests termination.
+ // all callbacks deregister themselves or when someone requests termination.
virtual Status Run() { llvm_unreachable("Not implemented"); }
// Requests the exit of the Run() function.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h b/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h
index 9ad36e90a779..341284800a4e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h
@@ -24,6 +24,9 @@ public:
explicit MonitoringProcessLauncher(
std::unique_ptr<ProcessLauncher> delegate_launcher);
+ /// Launch the process specified in launch_info. The monitoring callback in
+ /// launch_info must be set, and it will be called when the process
+ /// terminates.
HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info,
Status &error) override;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/PosixApi.h b/contrib/llvm/tools/lldb/include/lldb/Host/PosixApi.h
index d5c48dd6d170..dae2bb480091 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/PosixApi.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/PosixApi.h
@@ -11,13 +11,14 @@
#define liblldb_Host_PosixApi_h
// This file defines platform specific functions, macros, and types necessary
-// to provide a minimum level of compatibility across all platforms to rely
-// on various posix api functionality.
+// to provide a minimum level of compatibility across all platforms to rely on
+// various posix api functionality.
#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h"
#else
#include <unistd.h>
+#include <csignal>
#endif
#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h b/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h
index 3ee27e74b4ba..d8128e71c53e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h
@@ -20,6 +20,7 @@
// Other libraries and framework includes
// Project includes
+#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-defines.h"
//#define DB_PTHREAD_LOG_EVENTS
@@ -38,8 +39,8 @@ typedef enum {
//----------------------------------------------------------------------
/// @class Predicate Predicate.h "lldb/Host/Predicate.h"
-/// @brief A C++ wrapper class for providing threaded access to a value
-/// of type T.
+/// A C++ wrapper class for providing threaded access to a value of
+/// type T.
///
/// A templatized class that provides multi-threaded access to a value
/// of type T. Threads can efficiently wait for bits within T to be set
@@ -118,169 +119,39 @@ public:
}
//------------------------------------------------------------------
- /// Set some bits in \a m_value.
+ /// Wait for Cond(m_value) to be true.
///
- /// Logically set the bits \a bits in the contained \a m_value in a
- /// thread safe way and broadcast if needed.
+ /// Waits in a thread safe way for Cond(m_value) to be true. If Cond(m_value)
+ /// is already true, this function will return without waiting.
///
- /// @param[in] bits
- /// The bits to set in \a m_value.
+ /// It is possible for the value to be changed between the time the value is
+ /// set and the time the waiting thread wakes up. If the value no longer
+ /// satisfies the condition when the waiting thread wakes up, it will go back
+ /// into a wait state. It may be necessary for the calling code to use
+ /// additional thread synchronization methods to detect transitory states.
///
- /// @param[in] broadcast_type
- /// A value indicating when and if to broadcast. See the
- /// PredicateBroadcastType enumeration for details.
- ///
- /// @see Predicate::Broadcast()
- //------------------------------------------------------------------
- void SetValueBits(T bits, PredicateBroadcastType broadcast_type) {
- std::lock_guard<std::mutex> guard(m_mutex);
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (bits = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, bits,
- broadcast_type);
-#endif
- const T old_value = m_value;
- m_value |= bits;
-
- Broadcast(old_value, broadcast_type);
- }
-
- //------------------------------------------------------------------
- /// Reset some bits in \a m_value.
- ///
- /// Logically reset (clear) the bits \a bits in the contained
- /// \a m_value in a thread safe way and broadcast if needed.
- ///
- /// @param[in] bits
- /// The bits to clear in \a m_value.
- ///
- /// @param[in] broadcast_type
- /// A value indicating when and if to broadcast. See the
- /// PredicateBroadcastType enumeration for details.
- ///
- /// @see Predicate::Broadcast()
- //------------------------------------------------------------------
- void ResetValueBits(T bits, PredicateBroadcastType broadcast_type) {
- std::lock_guard<std::mutex> guard(m_mutex);
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (bits = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, bits,
- broadcast_type);
-#endif
- const T old_value = m_value;
- m_value &= ~bits;
-
- Broadcast(old_value, broadcast_type);
- }
-
- //------------------------------------------------------------------
- /// Wait for bits to be set in \a m_value.
- ///
- /// Waits in a thread safe way for any bits in \a bits to get
- /// logically set in \a m_value. If any bits are already set in
- /// \a m_value, this function will return without waiting.
- ///
- /// It is possible for the value to be changed between the time
- /// the bits are set and the time the waiting thread wakes up.
- /// If the bits are no longer set when the waiting thread wakes
- /// up, it will go back into a wait state. It may be necessary
- /// for the calling code to use additional thread synchronization
- /// methods to detect transitory states.
- ///
- /// @param[in] bits
- /// The bits we are waiting to be set in \a m_value.
- ///
- /// @param[in] abstime
- /// If non-nullptr, the absolute time at which we should stop
- /// waiting, else wait an infinite amount of time.
- ///
- /// @return
- /// Any bits of the requested bits that actually were set within
- /// the time specified. Zero if a timeout or unrecoverable error
- /// occurred.
- //------------------------------------------------------------------
- T WaitForSetValueBits(T bits, const std::chrono::microseconds &timeout =
- std::chrono::microseconds(0)) {
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (std::lock_guard) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
- std::unique_lock<std::mutex> lock(m_mutex);
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (bits = 0x%8.8x, timeout = %llu), m_value = 0x%8.8x\n",
- __FUNCTION__, bits, timeout.count(), m_value);
-#endif
- while ((m_value & bits) == 0) {
- if (timeout == std::chrono::microseconds(0)) {
- m_condition.wait(lock);
- } else {
- std::cv_status result = m_condition.wait_for(lock, timeout);
- if (result == std::cv_status::timeout)
- break;
- }
- }
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n",
- __FUNCTION__, bits, m_value, m_value & bits);
-#endif
-
- return m_value & bits;
- }
-
- //------------------------------------------------------------------
- /// Wait for bits to be reset in \a m_value.
- ///
- /// Waits in a thread safe way for any bits in \a bits to get
- /// logically reset in \a m_value. If all bits are already reset in
- /// \a m_value, this function will return without waiting.
- ///
- /// It is possible for the value to be changed between the time
- /// the bits are reset and the time the waiting thread wakes up.
- /// If the bits are no set when the waiting thread wakes up, it will
- /// go back into a wait state. It may be necessary for the calling
- /// code to use additional thread synchronization methods to detect
- /// transitory states.
- ///
- /// @param[in] bits
- /// The bits we are waiting to be reset in \a m_value.
+ /// @param[in] Cond
+ /// The condition we want \a m_value satisfy.
///
- /// @param[in] abstime
- /// If non-nullptr, the absolute time at which we should stop
- /// waiting, else wait an infinite amount of time.
+ /// @param[in] timeout
+ /// How long to wait for the condition to hold.
///
/// @return
- /// Zero on successful waits, or non-zero if a timeout or
- /// unrecoverable error occurs.
+ /// @li m_value if Cond(m_value) is true.
+ /// @li None otherwise (timeout occurred).
//------------------------------------------------------------------
- T WaitForResetValueBits(T bits, const std::chrono::microseconds &timeout =
- std::chrono::microseconds(0)) {
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (std::lock_guard) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
+ template <typename C>
+ llvm::Optional<T> WaitFor(C Cond, const Timeout<std::micro> &timeout) {
std::unique_lock<std::mutex> lock(m_mutex);
-
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (bits = 0x%8.8x, timeout = %llu), m_value = 0x%8.8x\n",
- __FUNCTION__, bits, timeout.count(), m_value);
-#endif
- while ((m_value & bits) != 0) {
- if (timeout == std::chrono::microseconds(0)) {
- m_condition.wait(lock);
- } else {
- std::cv_status result = m_condition.wait_for(lock, timeout);
- if (result == std::cv_status::timeout)
- break;
- }
+ auto RealCond = [&] { return Cond(m_value); };
+ if (!timeout) {
+ m_condition.wait(lock, RealCond);
+ return m_value;
}
-
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n",
- __FUNCTION__, bits, m_value, m_value & bits);
-#endif
- return m_value & bits;
+ if (m_condition.wait_for(lock, *timeout, RealCond))
+ return m_value;
+ return llvm::None;
}
-
//------------------------------------------------------------------
/// Wait for \a m_value to be equal to \a value.
///
@@ -298,124 +169,17 @@ public:
/// @param[in] value
/// The value we want \a m_value to be equal to.
///
- /// @param[in] abstime
- /// If non-nullptr, the absolute time at which we should stop
- /// waiting, else wait an infinite amount of time.
- ///
- /// @param[out] timed_out
- /// If not null, set to true if we return because of a time out,
- /// and false if the value was set.
+ /// @param[in] timeout
+ /// How long to wait for the condition to hold.
///
/// @return
/// @li \b true if the \a m_value is equal to \a value
- /// @li \b false otherwise
+ /// @li \b false otherwise (timeout occurred)
//------------------------------------------------------------------
- bool WaitForValueEqualTo(T value, const std::chrono::microseconds &timeout =
- std::chrono::microseconds(0),
- bool *timed_out = nullptr) {
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (std::lock_guard) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
- std::unique_lock<std::mutex> lock(m_mutex);
-
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (value = 0x%8.8x, timeout = %llu), m_value = 0x%8.8x\n",
- __FUNCTION__, value, timeout.count(), m_value);
-#endif
- if (timed_out)
- *timed_out = false;
-
- while (m_value != value) {
- if (timeout == std::chrono::microseconds(0)) {
- m_condition.wait(lock);
- } else {
- std::cv_status result = m_condition.wait_for(lock, timeout);
- if (result == std::cv_status::timeout) {
- if (timed_out)
- *timed_out = true;
- break;
- }
- }
- }
-
- return m_value == value;
- }
-
- //------------------------------------------------------------------
- /// Wait for \a m_value to be equal to \a value and then set it to
- /// a new value.
- ///
- /// Waits in a thread safe way for \a m_value to be equal to \a
- /// value and then sets \a m_value to \a new_value. If \a m_value
- /// is already equal to \a value, this function will immediately
- /// set \a m_value to \a new_value and return without waiting.
- ///
- /// It is possible for the value to be changed between the time
- /// the value is set and the time the waiting thread wakes up.
- /// If the value no longer matches the requested value when the
- /// waiting thread wakes up, it will go back into a wait state. It
- /// may be necessary for the calling code to use additional thread
- /// synchronization methods to detect transitory states.
- ///
- /// @param[in] value
- /// The value we want \a m_value to be equal to.
- ///
- /// @param[in] new_value
- /// The value to which \a m_value will be set if \b true is
- /// returned.
- ///
- /// @param[in] abstime
- /// If non-nullptr, the absolute time at which we should stop
- /// waiting, else wait an infinite amount of time.
- ///
- /// @param[out] timed_out
- /// If not null, set to true if we return because of a time out,
- /// and false if the value was set.
- ///
- /// @return
- /// @li \b true if the \a m_value became equal to \a value
- /// @li \b false otherwise
- //------------------------------------------------------------------
- bool WaitForValueEqualToAndSetValueTo(
- T wait_value, T new_value,
- const std::chrono::microseconds &timeout = std::chrono::microseconds(0),
- bool *timed_out = nullptr) {
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (std::lock_guard) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
- std::unique_lock<std::mutex> lock(m_mutex);
-
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (wait_value = 0x%8.8x, new_value = 0x%8.8x, timeout = %llu), "
- "m_value = 0x%8.8x\n",
- __FUNCTION__, wait_value, new_value, timeout.count(), m_value);
-#endif
- if (timed_out)
- *timed_out = false;
-
- while (m_value != wait_value) {
- if (timeout == std::chrono::microseconds(0)) {
- m_condition.wait(lock);
- } else {
- std::cv_status result = m_condition.wait_for(lock, timeout);
- if (result == std::cv_status::timeout) {
- if (timed_out)
- *timed_out = true;
- break;
- }
- }
- }
-
- if (m_value == wait_value) {
- m_value = new_value;
- return true;
- }
-
- return false;
+ bool WaitForValueEqualTo(T value,
+ const Timeout<std::micro> &timeout = llvm::None) {
+ return WaitFor([&value](T current) { return value == current; }, timeout) !=
+ llvm::None;
}
//------------------------------------------------------------------
@@ -435,51 +199,23 @@ public:
/// @param[in] value
/// The value we want \a m_value to not be equal to.
///
- /// @param[out] new_value
- /// The new value if \b true is returned.
- ///
- /// @param[in] abstime
- /// If non-nullptr, the absolute time at which we should stop
- /// waiting, else wait an infinite amount of time.
+ /// @param[in] timeout
+ /// How long to wait for the condition to hold.
///
/// @return
- /// @li \b true if the \a m_value is equal to \a value
- /// @li \b false otherwise
+ /// @li m_value if m_value != value
+ /// @li None otherwise (timeout occurred).
//------------------------------------------------------------------
- bool WaitForValueNotEqualTo(
- T value, T &new_value,
- const std::chrono::microseconds &timeout = std::chrono::microseconds(0)) {
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (std::lock_guard) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
- std::unique_lock<std::mutex> lock(m_mutex);
-#ifdef DB_PTHREAD_LOG_EVENTS
- printf("%s (value = 0x%8.8x, timeout = %llu), m_value = 0x%8.8x\n",
- __FUNCTION__, value, timeout.count(), m_value);
-#endif
- while (m_value == value) {
- if (timeout == std::chrono::microseconds(0)) {
- m_condition.wait(lock);
- } else {
- std::cv_status result = m_condition.wait_for(lock, timeout);
- if (result == std::cv_status::timeout)
- break;
- }
- }
-
- if (m_value != value) {
- new_value = m_value;
- return true;
- }
- return false;
+ llvm::Optional<T>
+ WaitForValueNotEqualTo(T value,
+ const Timeout<std::micro> &timeout = llvm::None) {
+ return WaitFor([&value](T current) { return value != current; }, timeout);
}
protected:
//----------------------------------------------------------------------
- // pthread condition and mutex variable to control access and allow
- // blocking between the main thread and the spotlight index thread.
+ // pthread condition and mutex variable to control access and allow blocking
+ // between the main thread and the spotlight index thread.
//----------------------------------------------------------------------
T m_value; ///< The templatized value T that we are protecting access to
mutable std::mutex m_mutex; ///< The mutex to use when accessing the data
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h b/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h
index 7044fdbd9ef9..6f39eea716e8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h
@@ -26,9 +26,9 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ProcessRunLock ProcessRunLock.h "lldb/Host/ProcessRunLock.h"
-/// @brief A class used to prevent the process from starting while other
-/// threads are accessing its data, and prevent access to its data while
-/// it is running.
+/// A class used to prevent the process from starting while other
+/// threads are accessing its data, and prevent access to its data while it is
+/// running.
//----------------------------------------------------------------------
class ProcessRunLock {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/PseudoTerminal.h b/contrib/llvm/tools/lldb/include/lldb/Host/PseudoTerminal.h
index 00c0da6f3315..858bd35f73a6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/PseudoTerminal.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/PseudoTerminal.h
@@ -19,10 +19,10 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class PseudoTerminal PseudoTerminal.h "lldb/Host/PseudoTerminal.h"
-/// @brief A pseudo terminal helper class.
+/// A pseudo terminal helper class.
///
-/// The pseudo terminal class abstracts the use of pseudo terminals on
-/// the host system.
+/// The pseudo terminal class abstracts the use of pseudo terminals on the
+/// host system.
//----------------------------------------------------------------------
class PseudoTerminal {
public:
@@ -33,19 +33,17 @@ public:
//------------------------------------------------------------------
/// Default constructor
///
- /// Constructs this object with invalid master and slave file
- /// descriptors.
+ /// Constructs this object with invalid master and slave file descriptors.
//------------------------------------------------------------------
PseudoTerminal();
//------------------------------------------------------------------
/// Destructor
///
- /// The destructor will close the master and slave file descriptors
- /// if they are valid and ownership has not been released using
- /// one of:
- /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
- /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+ /// The destructor will close the master and slave file descriptors if they
+ /// are valid and ownership has not been released using one of: @li
+ /// PseudoTerminal::ReleaseMasterFileDescriptor() @li
+ /// PseudoTerminal::ReleaseSaveFileDescriptor()
//------------------------------------------------------------------
~PseudoTerminal();
@@ -62,20 +60,18 @@ public:
//------------------------------------------------------------------
/// Fork a child process that uses pseudo terminals for its stdio.
///
- /// In the parent process, a call to this function results in a pid
- /// being returned. If the pid is valid, the master file descriptor
- /// can be used for read/write access to stdio of the child process.
+ /// In the parent process, a call to this function results in a pid being
+ /// returned. If the pid is valid, the master file descriptor can be used
+ /// for read/write access to stdio of the child process.
///
- /// In the child process the stdin/stdout/stderr will already be
- /// routed to the slave pseudo terminal and the master file
- /// descriptor will be closed as it is no longer needed by the child
- /// process.
+ /// In the child process the stdin/stdout/stderr will already be routed to
+ /// the slave pseudo terminal and the master file descriptor will be closed
+ /// as it is no longer needed by the child process.
///
- /// This class will close the file descriptors for the master/slave
- /// when the destructor is called. The file handles can be released
- /// using either:
- /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
- /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+ /// This class will close the file descriptors for the master/slave when the
+ /// destructor is called. The file handles can be released using either: @li
+ /// PseudoTerminal::ReleaseMasterFileDescriptor() @li
+ /// PseudoTerminal::ReleaseSaveFileDescriptor()
///
/// @param[out] error
/// An pointer to an error that can describe any errors that
@@ -91,10 +87,10 @@ public:
//------------------------------------------------------------------
/// The master file descriptor accessor.
///
- /// This object retains ownership of the master file descriptor when
- /// this accessor is used. Users can call the member function
- /// PseudoTerminal::ReleaseMasterFileDescriptor() if this
- /// object should release ownership of the slave file descriptor.
+ /// This object retains ownership of the master file descriptor when this
+ /// accessor is used. Users can call the member function
+ /// PseudoTerminal::ReleaseMasterFileDescriptor() if this object should
+ /// release ownership of the slave file descriptor.
///
/// @return
/// The master file descriptor, or PseudoTerminal::invalid_fd
@@ -107,10 +103,10 @@ public:
//------------------------------------------------------------------
/// The slave file descriptor accessor.
///
- /// This object retains ownership of the slave file descriptor when
- /// this accessor is used. Users can call the member function
- /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this
- /// object should release ownership of the slave file descriptor.
+ /// This object retains ownership of the slave file descriptor when this
+ /// accessor is used. Users can call the member function
+ /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this object should
+ /// release ownership of the slave file descriptor.
///
/// @return
/// The slave file descriptor, or PseudoTerminal::invalid_fd
@@ -146,12 +142,12 @@ public:
/// Open the first available pseudo terminal.
///
/// Opens the first available pseudo terminal with \a oflag as the
- /// permissions. The opened master file descriptor is stored in this
- /// object and can be accessed by calling the
- /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients
- /// can call the PseudoTerminal::ReleaseMasterFileDescriptor()
- /// accessor function if they wish to use the master file descriptor
- /// beyond the lifespan of this object.
+ /// permissions. The opened master file descriptor is stored in this object
+ /// and can be accessed by calling the
+ /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients can call the
+ /// PseudoTerminal::ReleaseMasterFileDescriptor() accessor function if they
+ /// wish to use the master file descriptor beyond the lifespan of this
+ /// object.
///
/// If this object still has a valid master file descriptor when its
/// destructor is called, it will close it.
@@ -169,8 +165,8 @@ public:
/// successfully opened.
/// @li \b false if anything goes wrong.
///
- /// @see PseudoTerminal::GetMasterFileDescriptor()
- /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+ /// @see PseudoTerminal::GetMasterFileDescriptor() @see
+ /// PseudoTerminal::ReleaseMasterFileDescriptor()
//------------------------------------------------------------------
bool OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len);
@@ -178,12 +174,12 @@ public:
/// Open the slave for the current master pseudo terminal.
///
/// A master pseudo terminal should already be valid prior to
- /// calling this function. The opened slave file descriptor is
- /// stored in this object and can be accessed by calling the
- /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients
- /// can call the PseudoTerminal::ReleaseSlaveFileDescriptor()
- /// accessor function if they wish to use the slave file descriptor
- /// beyond the lifespan of this object.
+ /// calling this function. The opened slave file descriptor is stored in
+ /// this object and can be accessed by calling the
+ /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients can call the
+ /// PseudoTerminal::ReleaseSlaveFileDescriptor() accessor function if they
+ /// wish to use the slave file descriptor beyond the lifespan of this
+ /// object.
///
/// If this object still has a valid slave file descriptor when its
/// destructor is called, it will close it.
@@ -200,19 +196,19 @@ public:
/// successfully opened.
/// @li \b false if anything goes wrong.
///
- /// @see PseudoTerminal::OpenFirstAvailableMaster()
- /// @see PseudoTerminal::GetSlaveFileDescriptor()
- /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+ /// @see PseudoTerminal::OpenFirstAvailableMaster() @see
+ /// PseudoTerminal::GetSlaveFileDescriptor() @see
+ /// PseudoTerminal::ReleaseSlaveFileDescriptor()
//------------------------------------------------------------------
bool OpenSlave(int oflag, char *error_str, size_t error_len);
//------------------------------------------------------------------
/// Release the master file descriptor.
///
- /// Releases ownership of the master pseudo terminal file descriptor
- /// without closing it. The destructor for this class will close the
- /// master file descriptor if the ownership isn't released using this
- /// call and the master file descriptor has been opened.
+ /// Releases ownership of the master pseudo terminal file descriptor without
+ /// closing it. The destructor for this class will close the master file
+ /// descriptor if the ownership isn't released using this call and the
+ /// master file descriptor has been opened.
///
/// @return
/// The master file descriptor, or PseudoTerminal::invalid_fd
@@ -223,10 +219,10 @@ public:
//------------------------------------------------------------------
/// Release the slave file descriptor.
///
- /// Release ownership of the slave pseudo terminal file descriptor
- /// without closing it. The destructor for this class will close the
- /// slave file descriptor if the ownership isn't released using this
- /// call and the slave file descriptor has been opened.
+ /// Release ownership of the slave pseudo terminal file descriptor without
+ /// closing it. The destructor for this class will close the slave file
+ /// descriptor if the ownership isn't released using this call and the slave
+ /// file descriptor has been opened.
///
/// @return
/// The slave file descriptor, or PseudoTerminal::invalid_fd
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h b/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h
index 37f468f23ce0..f6e51fd45679 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h
@@ -60,10 +60,8 @@ public:
virtual Status Accept(Socket *&socket) = 0;
// Initialize a Tcp Socket object in listening mode. listen and accept are
- // implemented
- // separately because the caller may wish to manipulate or query the socket
- // after it is
- // initialized, but before entering a blocking accept.
+ // implemented separately because the caller may wish to manipulate or query
+ // the socket after it is initialized, but before entering a blocking accept.
static Status TcpListen(llvm::StringRef host_and_port,
bool child_processes_inherit, Socket *&socket,
Predicate<uint16_t> *predicate, int backlog = 5);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/SocketAddress.h b/contrib/llvm/tools/lldb/include/lldb/Host/SocketAddress.h
index ebc6f4e57ee8..749a9c664c81 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/SocketAddress.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/SocketAddress.h
@@ -111,17 +111,16 @@ public:
uint16_t GetPort() const;
//------------------------------------------------------------------
- // Set the port if the socket address for the family has a port.
- // The family must be set correctly prior to calling this function.
+ // Set the port if the socket address for the family has a port. The family
+ // must be set correctly prior to calling this function.
//------------------------------------------------------------------
bool SetPort(uint16_t port);
//------------------------------------------------------------------
- // Set the socket address according to the first match from a call
- // to getaddrinfo() (or equivalent functions for systems that don't
- // have getaddrinfo(). If "addr_info_ptr" is not NULL, it will get
- // filled in with the match that was used to populate this socket
- // address.
+ // Set the socket address according to the first match from a call to
+ // getaddrinfo() (or equivalent functions for systems that don't have
+ // getaddrinfo(). If "addr_info_ptr" is not NULL, it will get filled in with
+ // the match that was used to populate this socket address.
//------------------------------------------------------------------
bool
getaddrinfo(const char *host, // Hostname ("foo.bar.com" or "foo" or IP
@@ -133,9 +132,9 @@ public:
int ai_protocol = 0, int ai_flags = 0);
//------------------------------------------------------------------
- // Quick way to set the SocketAddress to localhost given the family.
- // Returns true if successful, false if "family" doesn't support
- // localhost or if "family" is not supported by this class.
+ // Quick way to set the SocketAddress to localhost given the family. Returns
+ // true if successful, false if "family" doesn't support localhost or if
+ // "family" is not supported by this class.
//------------------------------------------------------------------
bool SetToLocalhost(sa_family_t family, uint16_t port);
@@ -190,11 +189,10 @@ public:
}
//------------------------------------------------------------------
- // Conversion operators to allow getting the contents of this class
- // as a pointer to the appropriate structure. This allows an instance
- // of this class to be used in calls that take one of the sockaddr
- // structure variants without having to manually use the correct
- // accessor function.
+ // Conversion operators to allow getting the contents of this class as a
+ // pointer to the appropriate structure. This allows an instance of this
+ // class to be used in calls that take one of the sockaddr structure variants
+ // without having to manually use the correct accessor function.
//------------------------------------------------------------------
operator struct sockaddr *() { return &m_socket_addr.sa; }
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/StringConvert.h b/contrib/llvm/tools/lldb/include/lldb/Host/StringConvert.h
index 05bd7808ecd4..d197df10d79e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/StringConvert.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/StringConvert.h
@@ -24,7 +24,7 @@ namespace StringConvert {
//----------------------------------------------------------------------
/// @namespace StringConvert StringConvert.h "lldb/Host/StringConvert.h"
-/// @brief Utility classes for converting strings into Integers
+/// Utility classes for converting strings into Integers
//----------------------------------------------------------------------
int32_t ToSInt32(const char *s, int32_t fail_value = 0, int base = 0,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h b/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h
index 5f8632d221f7..ce95d91497f8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h
@@ -29,16 +29,16 @@ public:
//----------------------------------------------------------------------
// Locate the executable file given a module specification.
//
- // Locating the file should happen only on the local computer or using
- // the current computers global settings.
+ // Locating the file should happen only on the local computer or using the
+ // current computers global settings.
//----------------------------------------------------------------------
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec);
//----------------------------------------------------------------------
// Locate the symbol file given a module specification.
//
- // Locating the file should happen only on the local computer or using
- // the current computers global settings.
+ // Locating the file should happen only on the local computer or using the
+ // current computers global settings.
//----------------------------------------------------------------------
static FileSpec LocateExecutableSymbolFile(const ModuleSpec &module_spec);
@@ -51,10 +51,10 @@ public:
//
// Locating the file can try to download the file from a corporate build
// repository, or using any other means necessary to locate both the
- // unstripped object file and the debug symbols.
- // The force_lookup argument controls whether the external program is called
- // unconditionally to find the symbol file, or if the user's settings are
- // checked to see if they've enabled the external program before calling.
+ // unstripped object file and the debug symbols. The force_lookup argument
+ // controls whether the external program is called unconditionally to find
+ // the symbol file, or if the user's settings are checked to see if they've
+ // enabled the external program before calling.
//
//----------------------------------------------------------------------
static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/TaskPool.h b/contrib/llvm/tools/lldb/include/lldb/Host/TaskPool.h
index 13076e7eb70b..fe1714151076 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/TaskPool.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/TaskPool.h
@@ -20,32 +20,27 @@
namespace lldb_private {
-// Global TaskPool class for running tasks in parallel on a set of worker thread
-// created the first
-// time the task pool is used. The TaskPool provide no guarantee about the order
-// the task will be run
-// and about what tasks will run in parallel. None of the task added to the task
-// pool should block
-// on something (mutex, future, condition variable) what will be set only by the
-// completion of an
-// other task on the task pool as they may run on the same thread sequentally.
+// Global TaskPool class for running tasks in parallel on a set of worker
+// thread created the first time the task pool is used. The TaskPool provide no
+// guarantee about the order the task will be run and about what tasks will run
+// in parallel. None of the task added to the task pool should block on
+// something (mutex, future, condition variable) what will be set only by the
+// completion of an other task on the task pool as they may run on the same
+// thread sequentally.
class TaskPool {
public:
// Add a new task to the task pool and return a std::future belonging to the
- // newly created task.
- // The caller of this function has to wait on the future for this task to
- // complete.
+ // newly created task. The caller of this function has to wait on the future
+ // for this task to complete.
template <typename F, typename... Args>
static std::future<typename std::result_of<F(Args...)>::type>
AddTask(F &&f, Args &&... args);
// Run all of the specified tasks on the task pool and wait until all of them
- // are finished
- // before returning. This method is intended to be used for small number tasks
- // where listing
- // them as function arguments is acceptable. For running large number of tasks
- // you should use
- // AddTask for each task and then call wait() on each returned future.
+ // are finished before returning. This method is intended to be used for
+ // small number tasks where listing them as function arguments is acceptable.
+ // For running large number of tasks you should use AddTask for each task and
+ // then call wait() on each returned future.
template <typename... T> static void RunTasks(T &&... tasks);
private:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Terminal.h b/contrib/llvm/tools/lldb/include/lldb/Host/Terminal.h
index f0d93ad24ed6..193b6d21d51e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Terminal.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Terminal.h
@@ -44,7 +44,7 @@ protected:
//----------------------------------------------------------------------
/// @class State Terminal.h "lldb/Host/Terminal.h"
-/// @brief A terminal state saving/restoring class.
+/// A terminal state saving/restoring class.
///
/// This class can be used to remember the terminal state for a file
/// descriptor and later restore that state as it originally was.
@@ -64,9 +64,9 @@ public:
//------------------------------------------------------------------
/// Save the TTY state for \a fd.
///
- /// Save the current state of the TTY for the file descriptor "fd"
- /// and if "save_process_group" is true, attempt to save the process
- /// group info for the TTY.
+ /// Save the current state of the TTY for the file descriptor "fd" and if
+ /// "save_process_group" is true, attempt to save the process group info for
+ /// the TTY.
///
/// @param[in] fd
/// The file descriptor to save the state of.
@@ -84,8 +84,8 @@ public:
//------------------------------------------------------------------
/// Restore the TTY state to the cached state.
///
- /// Restore the state of the TTY using the cached values from a
- /// previous call to TerminalState::Save(int,bool).
+ /// Restore the state of the TTY using the cached values from a previous
+ /// call to TerminalState::Save(int,bool).
///
/// @return
/// Returns \b true if the TTY state was successfully restored,
@@ -147,7 +147,7 @@ protected:
//----------------------------------------------------------------------
/// @class TerminalStateSwitcher Terminal.h "lldb/Host/Terminal.h"
-/// @brief A TTY state switching class.
+/// A TTY state switching class.
///
/// This class can be used to remember 2 TTY states for a given file
/// descriptor and switch between the two states.
@@ -182,10 +182,9 @@ public:
bool Restore(uint32_t idx) const;
//------------------------------------------------------------------
- /// Save the TTY state information for the state at index \a idx.
- /// The TTY state is saved for the file descriptor \a fd and
- /// the process group information will also be saved if requested
- /// by \a save_process_group.
+ /// Save the TTY state information for the state at index \a idx. The TTY
+ /// state is saved for the file descriptor \a fd and the process group
+ /// information will also be saved if requested by \a save_process_group.
///
/// @param[in] idx
/// The index into the state array where the state should be
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/XML.h b/contrib/llvm/tools/lldb/include/lldb/Host/XML.h
index 96b5227305e1..5088f1f25b0d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/XML.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/XML.h
@@ -82,6 +82,9 @@ public:
llvm::StringRef GetAttributeValue(const char *name,
const char *fail_value = nullptr) const;
+ bool GetAttributeValueAsUnsigned(const char *name, uint64_t &value,
+ uint64_t fail_value = 0, int base = 0) const;
+
XMLNode FindFirstChildElementWithName(const char *name) const;
XMLNode GetElementForPath(const NamePath &path);
@@ -97,8 +100,8 @@ public:
void ForEachSiblingElement(NodeCallback const &callback) const;
//----------------------------------------------------------------------
- // Iterate through only the sibling nodes that are elements and whose
- // name matches \a name.
+ // Iterate through only the sibling nodes that are elements and whose name
+ // matches \a name.
//----------------------------------------------------------------------
void ForEachSiblingElementWithName(const char *name,
NodeCallback const &callback) const;
@@ -134,8 +137,8 @@ public:
const char *url = "untitled.xml");
//----------------------------------------------------------------------
- // If \a name is nullptr, just get the root element node, else only return
- // a value XMLNode if the name of the root element matches \a name.
+ // If \a name is nullptr, just get the root element node, else only return a
+ // value XMLNode if the name of the root element matches \a name.
//----------------------------------------------------------------------
XMLNode GetRootElement(const char *required_name = nullptr);
@@ -173,12 +176,11 @@ public:
StructuredData::ObjectSP GetStructuredData();
protected:
- // Using a node returned from GetValueNode() extract its value as a
- // string (if possible). Array and dictionary nodes will return false
- // as they have no string value. Boolean nodes will return true and
- // \a value will be "true" or "false" as the string value comes from
- // the element name itself. All other nodes will return the text
- // content of the XMLNode.
+ // Using a node returned from GetValueNode() extract its value as a string
+ // (if possible). Array and dictionary nodes will return false as they have
+ // no string value. Boolean nodes will return true and \a value will be
+ // "true" or "false" as the string value comes from the element name itself.
+ // All other nodes will return the text content of the XMLNode.
static bool ExtractStringFromValueNode(const XMLNode &node,
std::string &value);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h
index 4d5cab5cbec2..c69f7227a5cf 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h
@@ -19,8 +19,8 @@
// option structure
struct option {
const char *name;
- // has_arg can't be an enum because some compilers complain about
- // type mismatches in all the code that assumes it is an int.
+ // has_arg can't be an enum because some compilers complain about type
+ // mismatches in all the code that assumes it is an int.
int has_arg;
int *flag;
int val;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeBreakpoint.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeBreakpoint.h
index 73639d64c9e8..681570aadef0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeBreakpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeBreakpoint.h
@@ -45,8 +45,8 @@ protected:
private:
bool m_enabled;
- // -----------------------------------------------------------
- // interface for NativeBreakpointList
+ // ----------------------------------------------------------- interface for
+ // NativeBreakpointList
// -----------------------------------------------------------
void AddRef();
int32_t DecRef();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index bd8b8744b115..d96835d75839 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -69,8 +69,8 @@ public:
virtual Status Kill() = 0;
//------------------------------------------------------------------
- // Tells a process not to stop the inferior on given signals
- // and just reinject them back.
+ // Tells a process not to stop the inferior on given signals and just
+ // reinject them back.
//------------------------------------------------------------------
virtual Status IgnoreSignals(llvm::ArrayRef<int> signals);
@@ -421,33 +421,30 @@ protected:
int m_terminal_fd;
uint32_t m_stop_id = 0;
- // Set of signal numbers that LLDB directly injects back to inferior
- // without stopping it.
+ // Set of signal numbers that LLDB directly injects back to inferior without
+ // stopping it.
llvm::DenseSet<int> m_signals_to_ignore;
// lldb_private::Host calls should be used to launch a process for debugging,
- // and
- // then the process should be attached to. When attaching to a process
- // lldb_private::Host calls should be used to locate the process to attach to,
- // and then this function should be called.
+ // and then the process should be attached to. When attaching to a process
+ // lldb_private::Host calls should be used to locate the process to attach
+ // to, and then this function should be called.
NativeProcessProtocol(lldb::pid_t pid, int terminal_fd,
NativeDelegate &delegate);
- // -----------------------------------------------------------
- // Internal interface for state handling
+ // ----------------------------------------------------------- Internal
+ // interface for state handling
// -----------------------------------------------------------
void SetState(lldb::StateType state, bool notify_delegates = true);
- // Derived classes need not implement this. It can be used as a
- // hook to clear internal caches that should be invalidated when
- // stop ids change.
+ // Derived classes need not implement this. It can be used as a hook to
+ // clear internal caches that should be invalidated when stop ids change.
//
- // Note this function is called with the state mutex obtained
- // by the caller.
+ // Note this function is called with the state mutex obtained by the caller.
virtual void DoStopIDBumped(uint32_t newBumpId);
- // -----------------------------------------------------------
- // Internal interface for software breakpoints
+ // ----------------------------------------------------------- Internal
+ // interface for software breakpoints
// -----------------------------------------------------------
Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
@@ -466,11 +463,6 @@ protected:
NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid);
- // -----------------------------------------------------------
- // Static helper methods for derived classes.
- // -----------------------------------------------------------
- static Status ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch);
-
private:
void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeRegisterContext.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeRegisterContext.h
index a8c5fa17e264..26458db153c1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeRegisterContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeRegisterContext.h
@@ -98,17 +98,14 @@ public:
virtual lldb::addr_t GetWatchpointAddress(uint32_t wp_index);
// MIPS Linux kernel returns a masked address (last 3bits are masked)
- // when a HW watchpoint is hit. However user may not have set a watchpoint
- // on this address. This function emulates the instruction at PC and
- // finds the base address used in the load/store instruction. This gives the
- // exact address used to read/write the variable being watched.
- // For example:
- // 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at
- // 'm',
+ // when a HW watchpoint is hit. However user may not have set a watchpoint on
+ // this address. This function emulates the instruction at PC and finds the
+ // base address used in the load/store instruction. This gives the exact
+ // address used to read/write the variable being watched. For example: 'n' is
+ // at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm',
// then watch exception is generated even when 'n' is read/written. This
- // function
- // returns address of 'n' so that client can check whether a watchpoint is set
- // on this address or not.
+ // function returns address of 'n' so that client can check whether a
+ // watchpoint is set on this address or not.
virtual lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index);
virtual bool HardwareSingleStep(bool enable);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeThreadProtocol.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeThreadProtocol.h
index 5609cdda4eea..6f4452c688e7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeThreadProtocol.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeThreadProtocol.h
@@ -32,14 +32,6 @@ public:
virtual NativeRegisterContext &GetRegisterContext() = 0;
- virtual Status ReadRegister(uint32_t reg, RegisterValue &reg_value);
-
- virtual Status WriteRegister(uint32_t reg, const RegisterValue &reg_value);
-
- virtual Status SaveAllRegisters(lldb::DataBufferSP &data_sp);
-
- virtual Status RestoreAllRegisters(lldb::DataBufferSP &data_sp);
-
virtual bool GetStopReason(ThreadStopInfo &stop_info,
std::string &description) = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h b/contrib/llvm/tools/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h
index 945ec835f778..5b3a18d21079 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h
@@ -12,12 +12,13 @@
#include "lldb/Host/posix/HostInfoPosix.h"
#include "lldb/Utility/FileSpec.h"
+#include "llvm/Support/VersionTuple.h"
namespace lldb_private {
class HostInfoFreeBSD : public HostInfoPosix {
public:
- static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+ static llvm::VersionTuple GetOSVersion();
static bool GetOSBuildString(std::string &s);
static bool GetOSKernelDescription(std::string &s);
static FileSpec GetProgramFileSpec();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h
index 9ebff6ba6b0e..0d4de79d03b1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h
@@ -12,12 +12,13 @@
#include "lldb/Host/posix/HostInfoPosix.h"
#include "lldb/Utility/FileSpec.h"
+#include "llvm/Support/VersionTuple.h"
namespace lldb_private {
class HostInfoNetBSD : public HostInfoPosix {
public:
- static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+ static llvm::VersionTuple GetOSVersion();
static bool GetOSBuildString(std::string &s);
static bool GetOSKernelDescription(std::string &s);
static FileSpec GetProgramFileSpec();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
index b7e08eb33af7..0d125ca2c813 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
@@ -72,7 +72,7 @@ public:
lldb::IOObjectSP GetReadObject() override { return m_read_sp; }
- uint16_t GetListeningPort(uint32_t timeout_sec);
+ uint16_t GetListeningPort(const Timeout<std::micro> &timeout);
bool GetChildProcessesInherit() const;
void SetChildProcessesInherit(bool child_processes_inherit);
@@ -104,8 +104,8 @@ protected:
Predicate<uint16_t>
m_port_predicate; // Used when binding to port zero to wait for the thread
- // that creates the socket, binds and listens to resolve
- // the port number.
+ // that creates the socket, binds and listens to
+ // resolve the port number.
Pipe m_pipe;
std::recursive_mutex m_mutex;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostInfoPosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostInfoPosix.h
index 34994aea44fe..dda70f9f5a96 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostInfoPosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostInfoPosix.h
@@ -33,13 +33,12 @@ public:
static bool GetEnvironmentVar(const std::string &var_name, std::string &var);
+ static bool ComputePathRelativeToLibrary(FileSpec &file_spec,
+ llvm::StringRef dir);
+
protected:
static bool ComputeSupportExeDirectory(FileSpec &file_spec);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
- static bool ComputePythonDirectory(FileSpec &file_spec);
- static bool ComputeClangDirectory(FileSpec &file_spec);
- static bool ComputePathRelativeToLibrary(FileSpec &file_spec,
- llvm::StringRef dir);
};
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/PipePosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/PipePosix.h
index 8208b1b8bd6b..bb65a56abd00 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/PipePosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/PipePosix.h
@@ -17,7 +17,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class PipePosix PipePosix.h "lldb/Host/posix/PipePosix.h"
-/// @brief A posix-based implementation of Pipe, a class that abtracts
+/// A posix-based implementation of Pipe, a class that abtracts
/// unix style pipes.
///
/// A class that abstracts the LLDB core from host pipe functionality.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandAlias.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandAlias.h
index 4658a1e444f4..01522bd6ecea 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandAlias.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandAlias.h
@@ -16,8 +16,9 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
@@ -40,17 +41,11 @@ public:
bool WantsCompletion() override;
- int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) override;
+ int HandleCompletion(CompletionRequest &request) override;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override;
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override;
Options *GetOptions() override;
@@ -74,8 +69,8 @@ public:
OptionArgVectorSP GetOptionArguments() const { return m_option_args_sp; }
const char *GetOptionString() { return m_option_string.c_str(); }
- // this takes an alias - potentially nested (i.e. an alias to an alias)
- // and expands it all the way to a non-alias command
+ // this takes an alias - potentially nested (i.e. an alias to an alias) and
+ // expands it all the way to a non-alias command
std::pair<lldb::CommandObjectSP, OptionArgVectorSP> Desugar();
protected:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h
index 8bac3e8639d7..d17864e05f3e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h
@@ -18,6 +18,7 @@
// Project includes
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/lldb-private.h"
@@ -29,20 +30,13 @@ class CommandCompletions {
public:
//----------------------------------------------------------------------
// This is the command completion callback that is used to complete the
- // argument of the option
- // it is bound to (in the OptionDefinition table below). Return the total
- // number of matches.
+ // argument of the option it is bound to (in the OptionDefinition table
+ // below). Return the total number of matches.
//----------------------------------------------------------------------
- typedef int (*CompletionCallback)(
- CommandInterpreter &interpreter,
- llvm::StringRef completion_str, // This is the argument we are completing
- int match_start_point, // This is the point in the list of matches that
- // you should start returning elements
- int max_return_elements, // This is the number of matches requested.
- lldb_private::SearchFilter
- *searcher, // A search filter to limit the search...
- bool &word_complete,
- lldb_private::StringList &matches); // The array of matches we return.
+ typedef int (*CompletionCallback)(CommandInterpreter &interpreter,
+ CompletionRequest &request,
+ // A search filter to limit the search...
+ lldb_private::SearchFilter *searcher);
typedef enum {
eNoCompletion = 0u,
eSourceFileCompletion = (1u << 0),
@@ -54,9 +48,9 @@ public:
ePlatformPluginCompletion = (1u << 6),
eArchitectureCompletion = (1u << 7),
eVariablePathCompletion = (1u << 8),
- // This item serves two purposes. It is the last element in the enum,
- // so you can add custom enums starting from here in your Option class.
- // Also if you & in this bit the base code will not process the option.
+ // This item serves two purposes. It is the last element in the enum, so
+ // you can add custom enums starting from here in your Option class. Also
+ // if you & in this bit the base code will not process the option.
eCustomCompletion = (1u << 9)
} CommonCompletionTypes;
@@ -67,81 +61,55 @@ public:
static bool InvokeCommonCompletionCallbacks(
CommandInterpreter &interpreter, uint32_t completion_mask,
- llvm::StringRef completion_str, int match_start_point,
- int max_return_elements, SearchFilter *searcher, bool &word_complete,
- StringList &matches);
+ lldb_private::CompletionRequest &request, SearchFilter *searcher);
//----------------------------------------------------------------------
// These are the generic completer functions:
//----------------------------------------------------------------------
static int DiskFiles(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name, int match_start_point,
- int max_return_elements, SearchFilter *searcher,
- bool &word_complete, StringList &matches);
+ CompletionRequest &request, SearchFilter *searcher);
static int DiskFiles(const llvm::Twine &partial_file_name,
StringList &matches, TildeExpressionResolver &Resolver);
static int DiskDirectories(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- StringList &matches);
+ CompletionRequest &request,
+ SearchFilter *searcher);
static int DiskDirectories(const llvm::Twine &partial_file_name,
StringList &matches,
TildeExpressionResolver &Resolver);
static int SourceFiles(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- StringList &matches);
+ CompletionRequest &request, SearchFilter *searcher);
static int Modules(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name, int match_start_point,
- int max_return_elements, SearchFilter *searcher,
- bool &word_complete, lldb_private::StringList &matches);
+ CompletionRequest &request, SearchFilter *searcher);
static int Symbols(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name, int match_start_point,
- int max_return_elements, SearchFilter *searcher,
- bool &word_complete, lldb_private::StringList &matches);
+ CompletionRequest &request, SearchFilter *searcher);
static int SettingsNames(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- lldb_private::StringList &matches);
+ CompletionRequest &request, SearchFilter *searcher);
static int PlatformPluginNames(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- lldb_private::StringList &matches);
+ CompletionRequest &request,
+ SearchFilter *searcher);
static int ArchitectureNames(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- lldb_private::StringList &matches);
+ CompletionRequest &request,
+ SearchFilter *searcher);
static int VariablePath(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- lldb_private::StringList &matches);
+ CompletionRequest &request, SearchFilter *searcher);
//----------------------------------------------------------------------
- // The Completer class is a convenient base class for building searchers
- // that go along with the SearchFilter passed to the standard Completer
- // functions.
+ // The Completer class is a convenient base class for building searchers that
+ // go along with the SearchFilter passed to the standard Completer functions.
//----------------------------------------------------------------------
class Completer : public Searcher {
public:
- Completer(CommandInterpreter &interpreter, llvm::StringRef completion_str,
- int match_start_point, int max_return_elements,
- StringList &matches);
+ Completer(CommandInterpreter &interpreter, CompletionRequest &request);
~Completer() override;
@@ -154,10 +122,7 @@ public:
protected:
CommandInterpreter &m_interpreter;
- std::string m_completion_str;
- int m_match_start_point;
- int m_max_return_elements;
- StringList &m_matches;
+ CompletionRequest &m_request;
private:
DISALLOW_COPY_AND_ASSIGN(Completer);
@@ -169,9 +134,7 @@ public:
class SourceFileCompleter : public Completer {
public:
SourceFileCompleter(CommandInterpreter &interpreter,
- bool include_support_files,
- llvm::StringRef completion_str, int match_start_point,
- int max_return_elements, StringList &matches);
+ bool include_support_files, CompletionRequest &request);
Searcher::Depth GetDepth() override;
@@ -197,8 +160,7 @@ public:
class ModuleCompleter : public Completer {
public:
ModuleCompleter(CommandInterpreter &interpreter,
- llvm::StringRef completion_str, int match_start_point,
- int max_return_elements, StringList &matches);
+ CompletionRequest &request);
Searcher::Depth GetDepth() override;
@@ -222,8 +184,7 @@ public:
class SymbolCompleter : public Completer {
public:
SymbolCompleter(CommandInterpreter &interpreter,
- llvm::StringRef completion_str, int match_start_point,
- int max_return_elements, StringList &matches);
+ CompletionRequest &request);
Searcher::Depth GetDepth() override;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h
index 5e561f47946d..78f505c24754 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -19,11 +19,12 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/IOHandler.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandAlias.h"
#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-forward.h"
@@ -86,11 +87,10 @@ public:
m_add_to_history = value;
}
// These return the default behaviors if the behavior is not
- // eLazyBoolCalculate.
- // But I've also left the ivars public since for different ways of running the
- // interpreter you might want to force different defaults... In that case,
- // just grab
- // the LazyBool ivars directly and do what you want with eLazyBoolCalculate.
+ // eLazyBoolCalculate. But I've also left the ivars public since for
+ // different ways of running the interpreter you might want to force
+ // different defaults... In that case, just grab the LazyBool ivars directly
+ // and do what you want with eLazyBoolCalculate.
bool GetStopOnContinue() const { return DefaultToNo(m_stop_on_continue); }
void SetStopOnContinue(bool stop_on_continue) {
@@ -293,26 +293,19 @@ public:
CommandObject *GetCommandObjectForCommand(llvm::StringRef &command_line);
// This handles command line completion. You are given a pointer to the
- // command string buffer, to the current cursor,
- // and to the end of the string (in case it is not NULL terminated).
- // You also passed in an StringList object to fill with the returns.
- // The first element of the array will be filled with the string that you
- // would need to insert at
- // the cursor point to complete the cursor point to the longest common
- // matching prefix.
- // If you want to limit the number of elements returned, set
- // max_return_elements to the number of elements
- // you want returned. Otherwise set max_return_elements to -1.
- // If you want to start some way into the match list, then set
- // match_start_point to the desired start
- // point.
- // Returns:
- // -1 if the completion character should be inserted
- // -2 if the entire command line should be deleted and replaced with
- // matches.GetStringAtIndex(0)
+ // command string buffer, to the current cursor, and to the end of the string
+ // (in case it is not NULL terminated). You also passed in an StringList
+ // object to fill with the returns. The first element of the array will be
+ // filled with the string that you would need to insert at the cursor point
+ // to complete the cursor point to the longest common matching prefix. If you
+ // want to limit the number of elements returned, set max_return_elements to
+ // the number of elements you want returned. Otherwise set
+ // max_return_elements to -1. If you want to start some way into the match
+ // list, then set match_start_point to the desired start point. Returns: -1
+ // if the completion character should be inserted -2 if the entire command
+ // line should be deleted and replaced with matches.GetStringAtIndex(0)
// INT_MAX if the number of matches is > max_return_elements, but it is
- // expensive to compute.
- // Otherwise, returns the number of matches.
+ // expensive to compute. Otherwise, returns the number of matches.
//
// FIXME: Only max_return_elements == -1 is supported at present.
int HandleCompletion(const char *current_line, const char *cursor,
@@ -320,15 +313,9 @@ public:
int max_return_elements, StringList &matches);
// This version just returns matches, and doesn't compute the substring. It
- // is here so the
- // Help command can call it for the first argument.
- // word_complete tells whether the completions are considered a "complete"
- // response (so the
- // completer should complete the quote & put a space after the word.
- int HandleCompletionMatches(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches);
+ // is here so the Help command can call it for the first argument. It uses
+ // a CompletionRequest for simplicity reasons.
+ int HandleCompletionMatches(CompletionRequest &request);
int GetCommandNamesMatchingPartialString(const char *cmd_cstr,
bool include_aliases,
@@ -469,6 +456,30 @@ public:
void SetPromptOnQuit(bool b);
+ //------------------------------------------------------------------
+ /// Specify if the command interpreter should allow that the user can
+ /// specify a custom exit code when calling 'quit'.
+ //------------------------------------------------------------------
+ void AllowExitCodeOnQuit(bool allow);
+
+ //------------------------------------------------------------------
+ /// Sets the exit code for the quit command.
+ /// @param[in] exit_code
+ /// The exit code that the driver should return on exit.
+ /// @return True if the exit code was successfully set; false if the
+ /// interpreter doesn't allow custom exit codes.
+ /// @see AllowExitCodeOnQuit
+ //------------------------------------------------------------------
+ LLVM_NODISCARD bool SetQuitExitCode(int exit_code);
+
+ //------------------------------------------------------------------
+ /// Returns the exit code that the user has specified when running the
+ /// 'quit' command.
+ /// @param[out] exited
+ /// Set to true if the user has called quit with a custom exit code.
+ //------------------------------------------------------------------
+ int GetQuitExitCode(bool &exited) const;
+
void ResolveCommand(const char *command_line, CommandReturnObject &result);
bool GetStopCmdSourceOnError() const;
@@ -572,6 +583,12 @@ private:
uint32_t m_num_errors;
bool m_quit_requested;
bool m_stopped_for_crash;
+
+ // The exit code the user has requested when calling the 'quit' command.
+ // No value means the user hasn't set a custom exit code so far.
+ llvm::Optional<int> m_quit_exit_code;
+ // If the driver is accepts custom exit codes for the 'quit' command.
+ bool m_allow_exit_code = false;
};
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h
index ff4c829e5c70..7afb18b2f598 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h
@@ -20,9 +20,11 @@
// Project includes
#include "lldb/Utility/Flags.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-private.h"
@@ -31,9 +33,8 @@ namespace lldb_private {
// This function really deals with CommandObjectLists, but we didn't make a
// CommandObjectList class, so I'm sticking it here. But we really should have
// such a class. Anyway, it looks up the commands in the map that match the
-// partial
-// string cmd_str, inserts the matches into matches, and returns the number
-// added.
+// partial string cmd_str, inserts the matches into matches, and returns the
+// number added.
template <typename ValueType>
int AddNamesMatchingPartialString(const std::map<std::string, ValueType> &in_map,
@@ -137,8 +138,8 @@ public:
void SetSyntax(llvm::StringRef str);
- // override this to return true if you want to enable the user to delete
- // the Command object from the Command dictionary (aliases have their own
+ // override this to return true if you want to enable the user to delete the
+ // Command object from the Command dictionary (aliases have their own
// deletion scheme, so they do not need to care about this)
virtual bool IsRemovable() const { return false; }
@@ -148,9 +149,9 @@ public:
virtual bool IsAlias() { return false; }
- // override this to return true if your command is somehow a "dash-dash"
- // form of some other command (e.g. po is expr -O --); this is a powerful
- // hint to the help system that one cannot pass options to this command
+ // override this to return true if your command is somehow a "dash-dash" form
+ // of some other command (e.g. po is expr -O --); this is a powerful hint to
+ // the help system that one cannot pass options to this command
virtual bool IsDashDashCommand() { return false; }
virtual lldb::CommandObjectSP GetSubcommandSP(llvm::StringRef sub_cmd,
@@ -174,10 +175,9 @@ public:
virtual void GenerateHelpText(Stream &result);
- // this is needed in order to allow the SBCommand class to
- // transparently try and load subcommands - it will fail on
- // anything but a multiword command, but it avoids us doing
- // type checkings and casts
+ // this is needed in order to allow the SBCommand class to transparently try
+ // and load subcommands - it will fail on anything but a multiword command,
+ // but it avoids us doing type checkings and casts
virtual bool LoadSubCommand(llvm::StringRef cmd_name,
const lldb::CommandObjectSP &command_obj) {
return false;
@@ -185,9 +185,9 @@ public:
virtual bool WantsRawCommandString() = 0;
- // By default, WantsCompletion = !WantsRawCommandString.
- // Subclasses who want raw command string but desire, for example,
- // argument completion should override this method to return true.
+ // By default, WantsCompletion = !WantsRawCommandString. Subclasses who want
+ // raw command string but desire, for example, argument completion should
+ // override this method to return true.
virtual bool WantsCompletion() { return !WantsRawCommandString(); }
virtual Options *GetOptions();
@@ -209,10 +209,10 @@ public:
static const char *GetArgumentName(lldb::CommandArgumentType arg_type);
// Generates a nicely formatted command args string for help command output.
- // By default, all possible args are taken into account, for example,
- // '<expr | variable-name>'. This can be refined by passing a second arg
- // specifying which option set(s) we are interested, which could then, for
- // example, produce either '<expr>' or '<variable-name>'.
+ // By default, all possible args are taken into account, for example, '<expr
+ // | variable-name>'. This can be refined by passing a second arg specifying
+ // which option set(s) we are interested, which could then, for example,
+ // produce either '<expr>' or '<variable-name>'.
void GetFormattedCommandArguments(Stream &str,
uint32_t opt_set_mask = LLDB_OPT_SET_ALL);
@@ -223,44 +223,13 @@ public:
void SetCommandName(llvm::StringRef name);
//------------------------------------------------------------------
- /// The input array contains a parsed version of the line. The insertion
- /// point is given by cursor_index (the index in input of the word containing
- /// the cursor) and cursor_char_position (the position of the cursor in that
- /// word.)
/// This default version handles calling option argument completions and then
- /// calls
- /// HandleArgumentCompletion if the cursor is on an argument, not an option.
- /// Don't override this method, override HandleArgumentCompletion instead
- /// unless
- /// you have special reasons.
- ///
- /// @param[in] interpreter
- /// The command interpreter doing the completion.
- ///
- /// @param[in] input
- /// The command line parsed into words
- ///
- /// @param[in] cursor_index
- /// The index in \ainput of the word in which the cursor lies.
- ///
- /// @param[in] cursor_char_pos
- /// The character position of the cursor in its argument word.
- ///
- /// @param[in] match_start_point
- /// @param[in] match_return_elements
- /// FIXME: Not yet implemented... If there is a match that is expensive
- /// to compute, these are
- /// here to allow you to compute the completions in batches. Start the
- /// completion from \amatch_start_point,
- /// and return \amatch_return_elements elements.
+ /// calls HandleArgumentCompletion if the cursor is on an argument, not an
+ /// option. Don't override this method, override HandleArgumentCompletion
+ /// instead unless you have special reasons.
///
- /// @param[out] word_complete
- /// \btrue if this is a complete option value (a space will be inserted
- /// after the
- /// completion.) \bfalse otherwise.
- ///
- /// @param[out] matches
- /// The array of matches returned.
+ /// @param[in/out] request
+ /// The completion request that needs to be answered.
///
/// FIXME: This is the wrong return value, since we also need to make a
/// distinction between
@@ -269,10 +238,7 @@ public:
/// @return
/// \btrue if we were in an option, \bfalse otherwise.
//------------------------------------------------------------------
- virtual int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches);
+ virtual int HandleCompletion(CompletionRequest &request);
//------------------------------------------------------------------
/// The input array contains a parsed version of the line. The insertion
@@ -280,36 +246,10 @@ public:
/// the cursor) and cursor_char_position (the position of the cursor in that
/// word.)
/// We've constructed the map of options and their arguments as well if that
- /// is
- /// helpful for the completion.
- ///
- /// @param[in] interpreter
- /// The command interpreter doing the completion.
- ///
- /// @param[in] input
- /// The command line parsed into words
- ///
- /// @param[in] cursor_index
- /// The index in \ainput of the word in which the cursor lies.
- ///
- /// @param[in] cursor_char_pos
- /// The character position of the cursor in its argument word.
+ /// is helpful for the completion.
///
- /// @param[in] opt_element_vector
- /// The results of the options parse of \a input.
- ///
- /// @param[in] match_start_point
- /// @param[in] match_return_elements
- /// See CommandObject::HandleCompletions for a description of how these
- /// work.
- ///
- /// @param[out] word_complete
- /// \btrue if this is a complete option value (a space will be inserted
- /// after the
- /// completion.) \bfalse otherwise.
- ///
- /// @param[out] matches
- /// The array of matches returned.
+ /// @param[in/out] request
+ /// The completion request that needs to be answered.
///
/// FIXME: This is the wrong return value, since we also need to make a
/// distinction between
@@ -318,10 +258,9 @@ public:
/// @return
/// The number of completions.
//------------------------------------------------------------------
- virtual int HandleArgumentCompletion(
- Args &input, int &cursor_index, int &cursor_char_position,
- OptionElementVector &opt_element_vector, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
+ virtual int
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) {
return 0;
}
@@ -397,6 +336,10 @@ public:
CommandReturnObject &result) = 0;
protected:
+ bool ParseOptionsAndNotify(Args &args, CommandReturnObject &result,
+ OptionGroupOptions &group_options,
+ ExecutionContext &exe_ctx);
+
virtual const char *GetInvalidTargetDescription() {
return "invalid target, create a target using the 'target create' command";
}
@@ -414,18 +357,16 @@ protected:
}
// This is for use in the command interpreter, when you either want the
- // selected target, or if no target
- // is present you want to prime the dummy target with entities that will be
- // copied over to new targets.
+ // selected target, or if no target is present you want to prime the dummy
+ // target with entities that will be copied over to new targets.
Target *GetSelectedOrDummyTarget(bool prefer_dummy = false);
Target *GetDummyTarget();
- // If a command needs to use the "current" thread, use this call.
- // Command objects will have an ExecutionContext to use, and that may or may
- // not have a thread in it. If it
- // does, you should use that by default, if not, then use the
- // ExecutionContext's target's selected thread, etc...
- // This call insulates you from the details of this calculation.
+ // If a command needs to use the "current" thread, use this call. Command
+ // objects will have an ExecutionContext to use, and that may or may not have
+ // a thread in it. If it does, you should use that by default, if not, then
+ // use the ExecutionContext's target's selected thread, etc... This call
+ // insulates you from the details of this calculation.
Thread *GetDefaultThread();
//------------------------------------------------------------------
@@ -492,7 +433,8 @@ public:
bool Execute(const char *args_string, CommandReturnObject &result) override;
protected:
- virtual bool DoExecute(const char *command, CommandReturnObject &result) = 0;
+ virtual bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) = 0;
bool WantsRawCommandString() override { return true; }
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
index 947272f4212e..d9eff9a6e545 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
@@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Utility/CompletionRequest.h"
namespace lldb_private {
@@ -56,10 +57,7 @@ public:
bool WantsRawCommandString() override { return false; }
- int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) override;
+ int HandleCompletion(CompletionRequest &request) override;
const char *GetRepeatCommand(Args &current_command_args,
uint32_t index) override;
@@ -87,8 +85,8 @@ public:
~CommandObjectProxy() override;
- // Subclasses must provide a command object that will be transparently
- // used for this object.
+ // Subclasses must provide a command object that will be transparently used
+ // for this object.
virtual CommandObject *GetProxyCommandObject() = 0;
llvm::StringRef GetHelpLong() override;
@@ -121,17 +119,11 @@ public:
Options *GetOptions() override;
- int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) override;
-
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override;
+ int HandleCompletion(CompletionRequest &request) override;
+
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override;
const char *GetRepeatCommand(Args &current_command_args,
uint32_t index) override;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h
index 50dbebc21b1d..36c3f068bdf3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h
@@ -17,6 +17,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/RegularExpression.h"
namespace lldb_private {
@@ -40,13 +41,10 @@ public:
bool HasRegexEntries() const { return !m_entries.empty(); }
- int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) override;
+ int HandleCompletion(CompletionRequest &request) override;
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override;
+ bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override;
struct Entry {
RegularExpression regex;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionArgParser.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionArgParser.h
new file mode 100644
index 000000000000..5ace7e5d0250
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionArgParser.h
@@ -0,0 +1,43 @@
+//===-- OptionArgParser.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_INTERPRETER_OPTIONARGPARSER_H
+#define LLDB_INTERPRETER_OPTIONARGPARSER_H
+
+#include "lldb/lldb-private-types.h"
+
+namespace lldb_private {
+
+struct OptionArgParser {
+ static lldb::addr_t ToAddress(const ExecutionContext *exe_ctx,
+ llvm::StringRef s, lldb::addr_t fail_value,
+ Status *error);
+
+ static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr);
+
+ static char ToChar(llvm::StringRef s, char fail_value, bool *success_ptr);
+
+ static int64_t ToOptionEnum(llvm::StringRef s,
+ OptionEnumValueElement *enum_values,
+ int32_t fail_value, Status &error);
+
+ static lldb::ScriptLanguage ToScriptLanguage(llvm::StringRef s,
+ lldb::ScriptLanguage fail_value,
+ bool *success_ptr);
+
+ // TODO: Use StringRef
+ static Status ToFormat(const char *s, lldb::Format &format,
+ size_t *byte_size_ptr); // If non-NULL, then a
+ // byte size can precede
+ // the format character
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_OPTIONARGPARSER_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h
index 53d08d79d67a..2489a648dd7e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h
@@ -24,9 +24,9 @@ namespace lldb_private {
class OptionGroupBoolean : public OptionGroup {
public:
- // When 'no_argument_toggle_default' is true, then setting the option
- // value does NOT require an argument, it sets the boolean value to the
- // inverse of the default value
+ // When 'no_argument_toggle_default' is true, then setting the option value
+ // does NOT require an argument, it sets the boolean value to the inverse of
+ // the default value
OptionGroupBoolean(uint32_t usage_mask, bool required,
const char *long_option, int short_option,
const char *usage_text, bool default_value,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h
index e79662400279..cda4246f1b01 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h
@@ -16,6 +16,7 @@
// Project includes
#include "lldb/Interpreter/Options.h"
#include "lldb/Utility/ConstString.h"
+#include "llvm/Support/VersionTuple.h"
namespace lldb_private {
@@ -28,8 +29,6 @@ class OptionGroupPlatform : public OptionGroup {
public:
OptionGroupPlatform(bool include_platform_option)
: OptionGroup(), m_platform_name(), m_sdk_sysroot(),
- m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX),
- m_os_version_update(UINT32_MAX),
m_include_platform_option(include_platform_option) {}
~OptionGroupPlatform() override = default;
@@ -72,9 +71,7 @@ protected:
std::string m_platform_name;
ConstString m_sdk_sysroot;
ConstString m_sdk_build;
- uint32_t m_os_version_major;
- uint32_t m_os_version_minor;
- uint32_t m_os_version_update;
+ llvm::VersionTuple m_os_version;
bool m_include_platform_option;
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h
index 6008e1ea4411..4748e309c77e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h
@@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/FormatEntity.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-defines.h"
@@ -76,8 +77,8 @@ public:
//-----------------------------------------------------------------
virtual Type GetType() const = 0;
- // If this value is always hidden, the avoid showing any info on this
- // value, just show the info for the child values.
+ // If this value is always hidden, the avoid showing any info on this value,
+ // just show the info for the child values.
virtual bool ValueIsTransparent() const {
return GetType() == eTypeProperties;
}
@@ -100,9 +101,7 @@ public:
virtual lldb::OptionValueSP DeepCopy() const = 0;
virtual size_t AutoComplete(CommandInterpreter &interpreter,
- llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches);
+ CompletionRequest &request);
//-----------------------------------------------------------------
// Subclasses can override these functions
@@ -126,8 +125,8 @@ public:
virtual bool DumpQualifiedName(Stream &strm) const;
//-----------------------------------------------------------------
- // Subclasses should NOT override these functions as they use the
- // above functions to implement functionality
+ // Subclasses should NOT override these functions as they use the above
+ // functions to implement functionality
//-----------------------------------------------------------------
uint32_t GetTypeAsMask() { return 1u << GetType(); }
@@ -183,9 +182,8 @@ public:
CreateValueFromCStringForTypeMask(const char *value_cstr, uint32_t type_mask,
Status &error);
- // Get this value as a uint64_t value if it is encoded as a boolean,
- // uint64_t or int64_t. Other types will cause "fail_value" to be
- // returned
+ // Get this value as a uint64_t value if it is encoded as a boolean, uint64_t
+ // or int64_t. Other types will cause "fail_value" to be returned
uint64_t GetUInt64Value(uint64_t fail_value, bool *success_ptr);
OptionValueArch *GetAsArch();
@@ -339,10 +337,10 @@ protected:
void *m_baton;
bool m_value_was_set; // This can be used to see if a value has been set
// by a call to SetValueFromCString(). It is often
- // handy to know if an option value was set from
- // the command line or as a setting, versus if we
- // just have the default value that was already
- // populated in the option value.
+ // handy to know if an option value was set from the
+ // command line or as a setting, versus if we just have
+ // the default value that was already populated in the
+ // option value.
};
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h
index d66448aa2bed..15b74ad17893 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h
@@ -12,6 +12,7 @@
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/CompletionRequest.h"
namespace lldb_private {
@@ -57,9 +58,8 @@ public:
lldb::OptionValueSP DeepCopy() const override;
- size_t AutoComplete(CommandInterpreter &interpreter, llvm::StringRef s,
- int match_start_point, int max_return_elements,
- bool &word_complete, StringList &matches) override;
+ size_t AutoComplete(CommandInterpreter &interpreter,
+ lldb_private::CompletionRequest &request) override;
//---------------------------------------------------------------------
// Subclass specific functions
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h
index bbf4e371a893..44709d00763f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h
@@ -78,8 +78,8 @@ public:
}
bool AppendValue(const lldb::OptionValueSP &value_sp) {
- // Make sure the value_sp object is allowed to contain
- // values of the type passed in...
+ // Make sure the value_sp object is allowed to contain values of the type
+ // passed in...
if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
m_values.push_back(value_sp);
return true;
@@ -88,8 +88,8 @@ public:
}
bool InsertValue(size_t idx, const lldb::OptionValueSP &value_sp) {
- // Make sure the value_sp object is allowed to contain
- // values of the type passed in...
+ // Make sure the value_sp object is allowed to contain values of the type
+ // passed in...
if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
if (idx < m_values.size())
m_values.insert(m_values.begin() + idx, value_sp);
@@ -101,8 +101,8 @@ public:
}
bool ReplaceValue(size_t idx, const lldb::OptionValueSP &value_sp) {
- // Make sure the value_sp object is allowed to contain
- // values of the type passed in...
+ // Make sure the value_sp object is allowed to contain values of the type
+ // passed in...
if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
if (idx < m_values.size()) {
m_values[idx] = value_sp;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h
index 1ff84dd3367d..6d2a16e59597 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h
@@ -50,9 +50,8 @@ public:
return true;
}
- size_t AutoComplete(CommandInterpreter &interpreter, llvm::StringRef s,
- int match_start_point, int max_return_elements,
- bool &word_complete, StringList &matches) override;
+ size_t AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) override;
//---------------------------------------------------------------------
// Subclass specific functions
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
index 4aa8823e620f..08d6ac70de52 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
@@ -59,9 +59,8 @@ public:
lldb::OptionValueSP DeepCopy() const override;
- size_t AutoComplete(CommandInterpreter &interpreter, llvm::StringRef s,
- int match_start_point, int max_return_elements,
- bool &word_complete, StringList &matches) override;
+ size_t AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) override;
//---------------------------------------------------------------------
// Subclass specific functions
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
index 293ecd0d8054..41a479e2fc9e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
@@ -54,9 +54,8 @@ public:
lldb::OptionValueSP DeepCopy() const override;
- size_t AutoComplete(CommandInterpreter &interpreter, llvm::StringRef s,
- int match_start_point, int max_return_elements,
- bool &word_complete, StringList &matches) override;
+ size_t AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) override;
//---------------------------------------------------------------------
// Subclass specific functions
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
index e5a65b7e7eb6..880e434dc5c0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
@@ -45,9 +45,8 @@ public:
lldb::OptionValueSP DeepCopy() const override;
- size_t AutoComplete(CommandInterpreter &interpreter, llvm::StringRef s,
- int match_start_point, int max_return_elements,
- bool &word_complete, StringList &matches) override;
+ size_t AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) override;
//---------------------------------------------------------------------
// Subclass specific functions
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h
index 16d31aa4ea90..96bd93ab3d7b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h
@@ -75,15 +75,15 @@ public:
//---------------------------------------------------------------------
// Get the index of a property given its exact name in this property
- // collection, "name" can't be a path to a property path that refers
- // to a property within a property
+ // collection, "name" can't be a path to a property path that refers to a
+ // property within a property
//---------------------------------------------------------------------
virtual uint32_t GetPropertyIndex(const ConstString &name) const;
//---------------------------------------------------------------------
- // Get a property by exact name exists in this property collection, name
- // can not be a path to a property path that refers to a property within
- // a property
+ // Get a property by exact name exists in this property collection, name can
+ // not be a path to a property path that refers to a property within a
+ // property
//---------------------------------------------------------------------
virtual const Property *GetProperty(const ExecutionContext *exe_ctx,
bool will_modify,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h
index be13ff073721..96404bed8e67 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h
@@ -34,9 +34,9 @@ public:
//---------------------------------------------------------------------
// Decode a uint64_t from "value_cstr" return a OptionValueUInt64 object
- // inside of a lldb::OptionValueSP object if all goes well. If the
- // string isn't a uint64_t value or any other error occurs, return an
- // empty lldb::OptionValueSP and fill error in with the correct stuff.
+ // inside of a lldb::OptionValueSP object if all goes well. If the string
+ // isn't a uint64_t value or any other error occurs, return an empty
+ // lldb::OptionValueSP and fill error in with the correct stuff.
//---------------------------------------------------------------------
static lldb::OptionValueSP Create(const char *, Status &) = delete;
static lldb::OptionValueSP Create(llvm::StringRef value_str, Status &error);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h
index 6e0aeebb0e99..950efb518d5a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h
@@ -61,9 +61,8 @@ public:
void SetCurrentValue(const UUID &value) { m_uuid = value; }
- size_t AutoComplete(CommandInterpreter &interpreter, llvm::StringRef s,
- int match_start_point, int max_return_elements,
- bool &word_complete, StringList &matches) override;
+ size_t AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) override;
protected:
UUID m_uuid;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h
index 87121005575a..316bf568fd92 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h
@@ -17,7 +17,9 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/CompletionRequest.h"
+#include "lldb/Utility/Status.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-private.h"
@@ -25,6 +27,24 @@
namespace lldb_private {
+struct Option;
+
+typedef std::vector<std::tuple<std::string, int, std::string>> OptionArgVector;
+typedef std::shared_ptr<OptionArgVector> OptionArgVectorSP;
+
+struct OptionArgElement {
+ enum { eUnrecognizedArg = -1, eBareDash = -2, eBareDoubleDash = -3 };
+
+ OptionArgElement(int defs_index, int pos, int arg_pos)
+ : opt_defs_index(defs_index), opt_pos(pos), opt_arg_pos(arg_pos) {}
+
+ int opt_defs_index;
+ int opt_pos;
+ int opt_arg_pos;
+};
+
+typedef std::vector<OptionArgElement> OptionElementVector;
+
static inline bool isprint8(int ch) {
if (ch & 0xffffff00u)
return false;
@@ -33,90 +53,18 @@ static inline bool isprint8(int ch) {
//----------------------------------------------------------------------
/// @class Options Options.h "lldb/Interpreter/Options.h"
-/// @brief A command line option parsing protocol class.
+/// A command line option parsing protocol class.
///
-/// Options is designed to be subclassed to contain all needed
-/// options for a given command. The options can be parsed by calling:
-/// \code
-/// Status Args::ParseOptions (Options &);
-/// \endcode
+/// Options is designed to be subclassed to contain all needed options for a
+/// given command. The options can be parsed by calling the Parse function.
///
-/// The options are specified using the format defined for the libc
-/// options parsing function getopt_long_only:
-/// \code
+/// The options are specified using the format defined for the libc options
+/// parsing function getopt_long_only: \code
/// #include <getopt.h>
/// int getopt_long_only(int argc, char * const *argv, const char
/// *optstring, const struct option *longopts, int *longindex);
/// \endcode
///
-/// Example code:
-/// \code
-/// #include <getopt.h>
-/// #include <string>
-///
-/// class CommandOptions : public Options
-/// {
-/// public:
-/// virtual struct option *
-/// GetLongOptions() {
-/// return g_options;
-/// }
-///
-/// virtual Status
-/// SetOptionValue (uint32_t option_idx, int option_val, const char
-/// *option_arg)
-/// {
-/// Status error;
-/// switch (option_val)
-/// {
-/// case 'g': debug = true; break;
-/// case 'v': verbose = true; break;
-/// case 'l': log_file = option_arg; break;
-/// case 'f': log_flags = strtoull(option_arg, nullptr, 0); break;
-/// default:
-/// error.SetErrorStringWithFormat("unrecognized short option
-/// %c", option_val);
-/// break;
-/// }
-///
-/// return error;
-/// }
-///
-/// CommandOptions (CommandInterpreter &interpreter) : debug (true),
-/// verbose (false), log_file (), log_flags (0)
-/// {}
-///
-/// bool debug;
-/// bool verbose;
-/// std::string log_file;
-/// uint32_t log_flags;
-///
-/// static struct option g_options[];
-///
-/// };
-///
-/// struct option CommandOptions::g_options[] =
-/// {
-/// { "debug", no_argument, nullptr, 'g' },
-/// { "log-file", required_argument, nullptr, 'l' },
-/// { "log-flags", required_argument, nullptr, 'f' },
-/// { "verbose", no_argument, nullptr, 'v' },
-/// { nullptr, 0, nullptr, 0 }
-/// };
-///
-/// int main (int argc, const char **argv, const char **envp)
-/// {
-/// CommandOptions options;
-/// Args main_command;
-/// main_command.SetArguments(argc, argv, false);
-/// main_command.ParseOptions(options);
-///
-/// if (options.verbose)
-/// {
-/// std::cout << "verbose is on" << std::endl;
-/// }
-/// }
-/// \endcode
//----------------------------------------------------------------------
class Options {
public:
@@ -143,9 +91,9 @@ public:
bool VerifyOptions(CommandReturnObject &result);
- // Verify that the options given are in the options table and can
- // be used together, but there may be some required options that are
- // missing (used to verify options that get folded into command aliases).
+ // Verify that the options given are in the options table and can be used
+ // together, but there may be some required options that are missing (used to
+ // verify options that get folded into command aliases).
bool VerifyPartialOptions(CommandReturnObject &result);
void OutputFormattedUsageText(Stream &strm,
@@ -157,20 +105,50 @@ public:
bool SupportsLongOption(const char *long_option);
- // The following two pure virtual functions must be defined by every
- // class that inherits from this class.
+ // The following two pure virtual functions must be defined by every class
+ // that inherits from this class.
virtual llvm::ArrayRef<OptionDefinition> GetDefinitions() {
return llvm::ArrayRef<OptionDefinition>();
}
- // Call this prior to parsing any options. This call will call the
- // subclass OptionParsingStarting() and will avoid the need for all
+ // Call this prior to parsing any options. This call will call the subclass
+ // OptionParsingStarting() and will avoid the need for all
// OptionParsingStarting() function instances from having to call the
- // Option::OptionParsingStarting() like they did before. This was error
- // prone and subclasses shouldn't have to do it.
+ // Option::OptionParsingStarting() like they did before. This was error prone
+ // and subclasses shouldn't have to do it.
void NotifyOptionParsingStarting(ExecutionContext *execution_context);
+ //------------------------------------------------------------------
+ /// Parse the provided arguments.
+ ///
+ /// The parsed options are set via calls to SetOptionValue. In case of a
+ /// successful parse, the function returns a copy of the input arguments
+ /// with the parsed options removed. Otherwise, it returns an error.
+ ///
+ /// param[in] platform_sp
+ /// The platform used for option validation. This is necessary
+ /// because an empty execution_context is not enough to get us
+ /// to a reasonable platform. If the platform isn't given,
+ /// we'll try to get it from the execution context. If we can't
+ /// get it from the execution context, we'll skip validation.
+ ///
+ /// param[in] require_validation
+ /// When true, it will fail option parsing if validation could
+ /// not occur due to not having a platform.
+ //------------------------------------------------------------------
+ llvm::Expected<Args> Parse(const Args &args,
+ ExecutionContext *execution_context,
+ lldb::PlatformSP platform_sp,
+ bool require_validation);
+
+ llvm::Expected<Args> ParseAlias(const Args &args,
+ OptionArgVector *option_arg_vector,
+ std::string &input_line);
+
+ OptionElementVector ParseForCompletion(const Args &args,
+ uint32_t cursor_index);
+
Status NotifyOptionParsingFinished(ExecutionContext *execution_context);
//------------------------------------------------------------------
@@ -196,99 +174,48 @@ public:
ExecutionContext *execution_context) = 0;
//------------------------------------------------------------------
- /// Handles the generic bits of figuring out whether we are in an
- /// option, and if so completing it.
- ///
- /// @param[in] input
- /// The command line parsed into words
+ /// Handles the generic bits of figuring out whether we are in an option,
+ /// and if so completing it.
///
- /// @param[in] cursor_index
- /// The index in \ainput of the word in which the cursor lies.
- ///
- /// @param[in] char_pos
- /// The character position of the cursor in its argument word.
- ///
- /// @param[in] match_start_point
- /// @param[in] match_return_elements
- /// See CommandObject::HandleCompletions for a description of
- /// how these work.
+ /// @param[in/out] request
+ /// The completion request that we need to act upon.
///
/// @param[in] interpreter
/// The interpreter that's doing the completing.
///
- /// @param[out] word_complete
- /// \btrue if this is a complete option value (a space will be
- /// inserted after the completion.) \b false otherwise.
- ///
- /// @param[out] matches
- /// The array of matches returned.
- ///
/// FIXME: This is the wrong return value, since we also need to
- /// make a distinction between total number of matches, and the
- /// window the user wants returned.
+ /// make a distinction between total number of matches, and the window the
+ /// user wants returned.
///
/// @return
/// \btrue if we were in an option, \bfalse otherwise.
//------------------------------------------------------------------
- bool HandleOptionCompletion(Args &input, OptionElementVector &option_map,
- int cursor_index, int char_pos,
- int match_start_point, int max_return_elements,
- CommandInterpreter &interpreter,
- bool &word_complete,
- lldb_private::StringList &matches);
+ bool HandleOptionCompletion(lldb_private::CompletionRequest &request,
+ OptionElementVector &option_map,
+ CommandInterpreter &interpreter);
//------------------------------------------------------------------
- /// Handles the generic bits of figuring out whether we are in an
- /// option, and if so completing it.
- ///
- /// @param[in] interpreter
- /// The command interpreter doing the completion.
- ///
- /// @param[in] input
- /// The command line parsed into words
- ///
- /// @param[in] cursor_index
- /// The index in \ainput of the word in which the cursor lies.
- ///
- /// @param[in] char_pos
- /// The character position of the cursor in its argument word.
+ /// Handles the generic bits of figuring out whether we are in an option,
+ /// and if so completing it.
///
- /// @param[in] opt_element_vector
- /// The results of the options parse of \a input.
- ///
- /// @param[in] opt_element_index
- /// The position in \a opt_element_vector of the word in \a
- /// input containing the cursor.
- ///
- /// @param[in] match_start_point
- /// @param[in] match_return_elements
- /// See CommandObject::HandleCompletions for a description of
- /// how these work.
+ /// @param[in/out] request
+ /// The completion request that we need to act upon.
///
/// @param[in] interpreter
- /// The command interpreter in which we're doing completion.
- ///
- /// @param[out] word_complete
- /// \btrue if this is a complete option value (a space will
- /// be inserted after the completion.) \bfalse otherwise.
- ///
- /// @param[out] matches
- /// The array of matches returned.
+ /// The command interpreter doing the completion.
///
/// FIXME: This is the wrong return value, since we also need to
- /// make a distinction between total number of matches, and the
- /// window the user wants returned.
+ /// make a distinction between total number of matches, and the window the
+ /// user wants returned.
///
/// @return
/// \btrue if we were in an option, \bfalse otherwise.
//------------------------------------------------------------------
virtual bool
- HandleOptionArgumentCompletion(Args &input, int cursor_index, int char_pos,
+ HandleOptionArgumentCompletion(lldb_private::CompletionRequest &request,
OptionElementVector &opt_element_vector,
- int opt_element_index, int match_start_point,
- int max_return_elements,
- CommandInterpreter &interpreter,
- bool &word_complete, StringList &matches);
+ int opt_element_index,
+ CommandInterpreter &interpreter);
protected:
// This is a set of options expressed as indexes into the options table for
@@ -319,14 +246,14 @@ protected:
void OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b,
OptionSet &union_set);
- // Subclasses must reset their option values prior to starting a new
- // option parse. Each subclass must override this function and revert
- // all option settings to default values.
+ // Subclasses must reset their option values prior to starting a new option
+ // parse. Each subclass must override this function and revert all option
+ // settings to default values.
virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0;
virtual Status OptionParsingFinished(ExecutionContext *execution_context) {
- // If subclasses need to know when the options are done being parsed
- // they can implement this function to do extra checking
+ // If subclasses need to know when the options are done being parsed they
+ // can implement this function to do extra checking
Status error;
return error;
}
@@ -347,8 +274,8 @@ public:
virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0;
virtual Status OptionParsingFinished(ExecutionContext *execution_context) {
- // If subclasses need to know when the options are done being parsed
- // they can implement this function to do extra checking
+ // If subclasses need to know when the options are done being parsed they
+ // can implement this function to do extra checking
Status error;
return error;
}
@@ -364,8 +291,8 @@ public:
//----------------------------------------------------------------------
/// Append options from a OptionGroup class.
///
- /// Append all options from \a group using the exact same option groups
- /// that each option is defined with.
+ /// Append all options from \a group using the exact same option groups that
+ /// each option is defined with.
///
/// @param[in] group
/// A group of options to take option values from and copy their
@@ -376,9 +303,9 @@ public:
//----------------------------------------------------------------------
/// Append options from a OptionGroup class.
///
- /// Append options from \a group that have a usage mask that has any bits
- /// in "src_mask" set. After the option definition is copied into the
- /// options definitions in this class, set the usage_mask to "dst_mask".
+ /// Append options from \a group that have a usage mask that has any bits in
+ /// "src_mask" set. After the option definition is copied into the options
+ /// definitions in this class, set the usage_mask to "dst_mask".
///
/// @param[in] group
/// A group of options to take option values from and copy their
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 335231cb29ec..d2189edd04a6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -96,13 +96,13 @@ public:
virtual bool Interrupt() { return false; }
virtual bool ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0;
virtual void ExecuteInterpreterLoop() = 0;
virtual bool ExecuteOneLineWithReturn(
- const char *in_string, ScriptReturnType return_type, void *ret_value,
+ llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
return true;
}
@@ -343,7 +343,7 @@ public:
}
virtual bool
- RunScriptBasedCommand(const char *impl_function, const char *args,
+ RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj,
Status &error,
@@ -351,12 +351,11 @@ public:
return false;
}
- virtual bool
- RunScriptBasedCommand(StructuredData::GenericSP impl_obj_sp, const char *args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject &cmd_retobj,
- Status &error,
- const lldb_private::ExecutionContext &exe_ctx) {
+ virtual bool RunScriptBasedCommand(
+ StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj, Status &error,
+ const lldb_private::ExecutionContext &exe_ctx) {
return false;
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h
index a5387cca21c5..1664362431f9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h
@@ -30,21 +30,21 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Block Block.h "lldb/Symbol/Block.h"
-/// @brief A class that describes a single lexical block.
+/// A class that describes a single lexical block.
///
/// A Function object owns a BlockList object which owns one or more
-/// Block objects. The BlockList object contains a section offset
-/// address range, and Block objects contain one or more ranges
-/// which are offsets into that range. Blocks are can have discontiguous
-/// ranges within the BlockList address range, and each block can
-/// contain child blocks each with their own sets of ranges.
+/// Block objects. The BlockList object contains a section offset address
+/// range, and Block objects contain one or more ranges which are offsets into
+/// that range. Blocks are can have discontiguous ranges within the BlockList
+/// address range, and each block can contain child blocks each with their own
+/// sets of ranges.
///
-/// Each block has a variable list that represents local, argument, and
-/// static variables that are scoped to the block.
+/// Each block has a variable list that represents local, argument, and static
+/// variables that are scoped to the block.
///
-/// Inlined functions are represented by attaching a
-/// InlineFunctionInfo shared pointer object to a block. Inlined
-/// functions are represented as named blocks.
+/// Inlined functions are represented by attaching a InlineFunctionInfo shared
+/// pointer object to a block. Inlined functions are represented as named
+/// blocks.
//----------------------------------------------------------------------
class Block : public UserID, public SymbolContextScope {
public:
@@ -54,10 +54,9 @@ public:
//------------------------------------------------------------------
/// Construct with a User ID \a uid, \a depth.
///
- /// Initialize this block with the specified UID \a uid. The
- /// \a depth in the \a block_list is used to represent the parent,
- /// sibling, and child block information and also allows for partial
- /// parsing at the block level.
+ /// Initialize this block with the specified UID \a uid. The \a depth in the
+ /// \a block_list is used to represent the parent, sibling, and child block
+ /// information and also allows for partial parsing at the block level.
///
/// @param[in] uid
/// The UID for a given block. This value is given by the
@@ -146,8 +145,7 @@ public:
bool Contains(const Range &range) const;
//------------------------------------------------------------------
- /// Check if this object contains "block" as a child block at any
- /// depth.
+ /// Check if this object contains "block" as a child block at any depth.
///
/// @param[in] block
/// A potential child block.
@@ -256,8 +254,8 @@ public:
lldb::VariableListSP GetBlockVariableList(bool can_create);
//------------------------------------------------------------------
- /// Get the variable list for this block and optionally all child
- /// blocks if \a get_child_variables is \b true.
+ /// Get the variable list for this block and optionally all child blocks if
+ /// \a get_child_variables is \b true.
///
/// @param[in] get_child_variables
/// If \b true, all variables from all child blocks will be
@@ -286,8 +284,8 @@ public:
VariableList *variable_list);
//------------------------------------------------------------------
- /// Appends the variables from this block, and optionally from all
- /// parent blocks, to \a variable_list.
+ /// Appends the variables from this block, and optionally from all parent
+ /// blocks, to \a variable_list.
///
/// @param[in] can_create
/// If \b true, the variables can be parsed if they already
@@ -334,8 +332,8 @@ public:
//------------------------------------------------------------------
/// Get the memory cost of this object.
///
- /// Returns the cost of this object plus any owned objects from the
- /// ranges, variables, and inline function information.
+ /// Returns the cost of this object plus any owned objects from the ranges,
+ /// variables, and inline function information.
///
/// @return
/// The number of bytes that this object occupies in memory.
@@ -374,9 +372,8 @@ public:
//------------------------------------------------------------------
/// Set accessor for the variable list.
///
- /// Called by the SymbolFile plug-ins after they have parsed the
- /// variable lists and are ready to hand ownership of the list over
- /// to this object.
+ /// Called by the SymbolFile plug-ins after they have parsed the variable
+ /// lists and are ready to hand ownership of the list over to this object.
///
/// @param[in] variable_list_sp
/// A shared pointer to a VariableList.
@@ -403,8 +400,8 @@ public:
uint32_t GetRangeIndexContainingAddress(const Address &addr);
//------------------------------------------------------------------
- // Since blocks might have multiple discontiguous address ranges,
- // we need to be able to get at any of the address ranges in a block.
+ // Since blocks might have multiple discontiguous address ranges, we need to
+ // be able to get at any of the address ranges in a block.
//------------------------------------------------------------------
bool GetRangeAtIndex(uint32_t range_idx, AddressRange &range);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h
index a5b8dacd15da..38632c5bd5de 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -255,6 +255,9 @@ public:
&type_fields,
bool packed = false);
+ static bool IsOperator(const char *name,
+ clang::OverloadedOperatorKind &op_kind);
+
//------------------------------------------------------------------
// Structure, Unions, Classes
//------------------------------------------------------------------
@@ -304,6 +307,9 @@ public:
lldb::AccessType access_type, const char *class_name,
int kind, const TemplateParameterInfos &infos);
+ clang::TemplateTemplateParmDecl *
+ CreateTemplateTemplateParmDecl(const char *template_name);
+
clang::ClassTemplateSpecializationDecl *CreateClassTemplateSpecializationDecl(
clang::DeclContext *decl_ctx,
clang::ClassTemplateDecl *class_template_decl, int kind,
@@ -636,8 +642,7 @@ public:
//----------------------------------------------------------------------
// Using the current type, create a new typedef to that type using
- // "typedef_name"
- // as the name and "decl_ctx" as the decl context.
+ // "typedef_name" as the name and "decl_ctx" as the decl context.
static CompilerType
CreateTypedefType(const CompilerType &type, const char *typedef_name,
const CompilerDeclContext &compiler_decl_ctx);
@@ -654,8 +659,7 @@ public:
GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
// Returns -1 if this isn't a function of if the function doesn't have a
- // prototype
- // Returns a value >= 0 if there is a prototype.
+ // prototype Returns a value >= 0 if there is a prototype.
int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
@@ -767,8 +771,8 @@ public:
bool &child_is_base_class, bool &child_is_deref_of_parent,
ValueObject *valobj, uint64_t &language_flags) override;
- // Lookup a child given a name. This function will match base class names
- // and member member names in "clang_type" only, not descendants.
+ // Lookup a child given a name. This function will match base class names and
+ // member member names in "clang_type" only, not descendants.
uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
bool omit_empty_base_classes) override;
@@ -798,8 +802,8 @@ public:
CompilerType GetTypeForFormatters(void *type) override;
#define LLDB_INVALID_DECL_LEVEL UINT32_MAX
- // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if
- // child_decl_ctx could not be found in decl_ctx.
+ // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if child_decl_ctx
+ // could not be found in decl_ctx.
uint32_t CountDeclLevels(clang::DeclContext *frame_decl_ctx,
clang::DeclContext *child_decl_ctx,
ConstString *child_name = nullptr,
@@ -825,6 +829,7 @@ public:
clang::CXXMethodDecl *
AddMethodToCXXRecordType(lldb::opaque_compiler_type_t type, const char *name,
+ const char *mangled_name,
const CompilerType &method_type,
lldb::AccessType access, bool is_virtual,
bool is_static, bool is_inline, bool is_explicit,
@@ -889,13 +894,13 @@ public:
// Pointers & References
//------------------------------------------------------------------
- // Call this function using the class type when you want to make a
- // member pointer type to pointee_type.
+ // Call this function using the class type when you want to make a member
+ // pointer type to pointee_type.
static CompilerType CreateMemberPointerType(const CompilerType &type,
const CompilerType &pointee_type);
- // Converts "s" to a floating point value and place resulting floating
- // point bytes in the "dst" buffer.
+ // Converts "s" to a floating point value and place resulting floating point
+ // bytes in the "dst" buffer.
size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
const char *s, uint8_t *dst,
size_t dst_size) override;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h
index 6823ad748282..52a164a1d2dd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h
@@ -250,13 +250,12 @@ private:
// recorded and placed into the decls_to_deport set.
//
// A call to "ExecuteDeportWorkQueues" completes all the Decls that
- // are in decls_to_deport, adding any Decls it sees along the way that
- // it hasn't already deported. It proceeds until decls_to_deport is
- // empty.
+ // are in decls_to_deport, adding any Decls it sees along the way that it
+ // hasn't already deported. It proceeds until decls_to_deport is empty.
//
- // These calls must be paired. Leaving a minion in deport mode or
- // trying to start deport minion with a new pair of queues will result
- // in an assertion failure.
+ // These calls must be paired. Leaving a minion in deport mode or trying
+ // to start deport minion with a new pair of queues will result in an
+ // assertion failure.
void
InitDeportWorkQueues(std::set<clang::NamedDecl *> *decls_to_deport,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
index 61bbc122dd5f..ef0010314e1d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
@@ -60,21 +60,21 @@ public:
//------------------------------------------------------------------
clang::Decl *GetExternalDecl(uint32_t ID) override {
- // This method only needs to be implemented if the AST source ever
- // passes back decl sets as VisibleDeclaration objects.
+ // This method only needs to be implemented if the AST source ever passes
+ // back decl sets as VisibleDeclaration objects.
return nullptr;
}
clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
- // This operation is meant to be used via a LazyOffsetPtr. It only
- // needs to be implemented if the AST source uses methods like
+ // This operation is meant to be used via a LazyOffsetPtr. It only needs
+ // to be implemented if the AST source uses methods like
// FunctionDecl::setLazyBody when building decls.
return nullptr;
}
clang::Selector GetExternalSelector(uint32_t ID) override {
- // This operation only needs to be implemented if the AST source
- // returns non-zero for GetNumKnownSelectors().
+ // This operation only needs to be implemented if the AST source returns
+ // non-zero for GetNumKnownSelectors().
return clang::Selector();
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompactUnwindInfo.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompactUnwindInfo.h
index 630067241735..711420f66a46 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompactUnwindInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompactUnwindInfo.h
@@ -22,23 +22,18 @@
namespace lldb_private {
// Compact Unwind info is an unwind format used on Darwin. The unwind
-// instructions
-// for typical compiler-generated functions can be expressed in a 32-bit
-// encoding.
-// The format includes a two-level index so the unwind information for a
-// function
-// can be found by two binary searches in the section. It can represent both
-// stack frames that use a frame-pointer register and frameless functions, on
-// i386/x86_64 for instance. When a function is too complex to be represented
-// in
-// the compact unwind format, it calls out to eh_frame unwind instructions.
+// instructions for typical compiler-generated functions can be expressed in a
+// 32-bit encoding. The format includes a two-level index so the unwind
+// information for a function can be found by two binary searches in the
+// section. It can represent both stack frames that use a frame-pointer
+// register and frameless functions, on i386/x86_64 for instance. When a
+// function is too complex to be represented in the compact unwind format, it
+// calls out to eh_frame unwind instructions.
// On Mac OS X / iOS, a function will have either a compact unwind
-// representation
-// or an eh_frame representation. If lldb is going to benefit from the
-// compiler's
-// description about saved register locations, it must be able to read both
-// sources of information.
+// representation or an eh_frame representation. If lldb is going to benefit
+// from the compiler's description about saved register locations, it must be
+// able to read both sources of information.
class CompactUnwindInfo {
public:
@@ -54,9 +49,8 @@ private:
// The top level index entries of the compact unwind info
// (internal representation of struct
// unwind_info_section_header_index_entry)
- // There are relatively few of these (one per 500/1000 functions, depending on
- // format) so
- // creating them on first scan will not be too costly.
+ // There are relatively few of these (one per 500/1000 functions, depending
+ // on format) so creating them on first scan will not be too costly.
struct UnwindIndex {
uint32_t function_offset; // The offset of the first function covered by
// this index
@@ -84,8 +78,7 @@ private:
};
// An internal object used to store the information we retrieve about a
- // function --
- // the encoding bits and possibly the LSDA/personality function.
+ // function -- the encoding bits and possibly the LSDA/personality function.
struct FunctionInfo {
uint32_t encoding; // compact encoding 32-bit value for this function
Address lsda_address; // the address of the LSDA data for this function
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h
index e7a1ebc8c00f..b816439cee13 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h
@@ -21,16 +21,16 @@
namespace lldb_private {
//----------------------------------------------------------------------
/// @class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h"
-/// @brief A class that describes a compilation unit.
+/// A class that describes a compilation unit.
///
/// A representation of a compilation unit, or compiled source file.
-/// The UserID of the compile unit is specified by the SymbolFile
-/// plug-in and can have any value as long as the value is unique
-/// within the Module that owns this compile units.
+/// The UserID of the compile unit is specified by the SymbolFile plug-in and
+/// can have any value as long as the value is unique within the Module that
+/// owns this compile units.
///
-/// Each compile unit has a list of functions, global and static
-/// variables, support file list (include files and inlined source
-/// files), and a line table.
+/// Each compile unit has a list of functions, global and static variables,
+/// support file list (include files and inlined source files), and a line
+/// table.
//----------------------------------------------------------------------
class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
public ModuleChild,
@@ -41,9 +41,9 @@ public:
//------------------------------------------------------------------
/// Construct with a module, path, UID and language.
///
- /// Initialize the compile unit given the owning \a module, a path
- /// to convert into a FileSpec, the SymbolFile plug-in supplied
- /// \a uid, and the source language type.
+ /// Initialize the compile unit given the owning \a module, a path to
+ /// convert into a FileSpec, the SymbolFile plug-in supplied \a uid, and the
+ /// source language type.
///
/// @param[in] module
/// The parent module that owns this compile unit. This value
@@ -81,9 +81,9 @@ public:
//------------------------------------------------------------------
/// Construct with a module, file spec, UID and language.
///
- /// Initialize the compile unit given the owning \a module, a path
- /// to convert into a FileSpec, the SymbolFile plug-in supplied
- /// \a uid, and the source language type.
+ /// Initialize the compile unit given the owning \a module, a path to
+ /// convert into a FileSpec, the SymbolFile plug-in supplied \a uid, and the
+ /// source language type.
///
/// @param[in] module
/// The parent module that owns this compile unit. This value
@@ -127,8 +127,8 @@ public:
//------------------------------------------------------------------
/// Add a function to this compile unit.
///
- /// Typically called by the SymbolFile plug-ins as they partially
- /// parse the debug information.
+ /// Typically called by the SymbolFile plug-ins as they partially parse the
+ /// debug information.
///
/// @param[in] function_sp
/// A shared pointer to the Function object.
@@ -163,13 +163,12 @@ public:
void GetDescription(Stream *s, lldb::DescriptionLevel level) const;
//------------------------------------------------------------------
- /// Get a shared pointer to a function in this compile unit by
- /// index.
+ /// Get a shared pointer to a function in this compile unit by index.
///
- /// Typically called when iterating though all functions in a
- /// compile unit after all functions have been parsed. This provides
- /// raw access to the function shared pointer list and will not
- /// cause the SymbolFile plug-in to parse any unparsed functions.
+ /// Typically called when iterating though all functions in a compile unit
+ /// after all functions have been parsed. This provides raw access to the
+ /// function shared pointer list and will not cause the SymbolFile plug-in
+ /// to parse any unparsed functions.
///
/// @param[in] idx
/// An index into the function list.
@@ -195,16 +194,15 @@ public:
//------------------------------------------------------------------
/// Find the line entry by line and optional inlined file spec.
///
- /// Finds the first line entry that has an index greater than
- /// \a start_idx that matches \a line. If \a file_spec_ptr
- /// is NULL, then the search matches line entries whose file matches
- /// the file for the compile unit. If \a file_spec_ptr is
- /// not NULL, line entries must match the specified file spec (for
- /// inlined line table entries).
+ /// Finds the first line entry that has an index greater than \a start_idx
+ /// that matches \a line. If \a file_spec_ptr is NULL, then the search
+ /// matches line entries whose file matches the file for the compile unit.
+ /// If \a file_spec_ptr is not NULL, line entries must match the specified
+ /// file spec (for inlined line table entries).
///
- /// Multiple calls to this function can find all entries that match
- /// a given file and line by starting with \a start_idx equal to zero,
- /// and calling this function back with the return value + 1.
+ /// Multiple calls to this function can find all entries that match a given
+ /// file and line by starting with \a start_idx equal to zero, and calling
+ /// this function back with the return value + 1.
///
/// @param[in] start_idx
/// The zero based index at which to start looking for matches.
@@ -237,10 +235,9 @@ public:
//------------------------------------------------------------------
/// Get the line table for the compile unit.
///
- /// Called by clients and the SymbolFile plug-in. The SymbolFile
- /// plug-ins use this function to determine if the line table has
- /// be parsed yet. Clients use this function to get the line table
- /// from a compile unit.
+ /// Called by clients and the SymbolFile plug-in. The SymbolFile plug-ins
+ /// use this function to determine if the line table has be parsed yet.
+ /// Clients use this function to get the line table from a compile unit.
///
/// @return
/// The line table object pointer, or NULL if this line table
@@ -253,8 +250,8 @@ public:
//------------------------------------------------------------------
/// Get the compile unit's support file list.
///
- /// The support file list is used by the line table, and any objects
- /// that have valid Declaration objects.
+ /// The support file list is used by the line table, and any objects that
+ /// have valid Declaration objects.
///
/// @return
/// A support file list object.
@@ -264,8 +261,8 @@ public:
//------------------------------------------------------------------
/// Get the compile unit's imported module list.
///
- /// This reports all the imports that the compile unit made,
- /// including the current module.
+ /// This reports all the imports that the compile unit made, including the
+ /// current module.
///
/// @return
/// A list of imported module names.
@@ -275,9 +272,8 @@ public:
//------------------------------------------------------------------
/// Get the SymbolFile plug-in user data.
///
- /// SymbolFile plug-ins can store user data to internal state or
- /// objects to quickly allow them to parse more information for a
- /// given object.
+ /// SymbolFile plug-ins can store user data to internal state or objects to
+ /// quickly allow them to parse more information for a given object.
///
/// @return
/// The user data stored with the CompileUnit when it was
@@ -288,9 +284,9 @@ public:
//------------------------------------------------------------------
/// Get the variable list for a compile unit.
///
- /// Called by clients to get the variable list for a compile unit.
- /// The variable list will contain all global and static variables
- /// that were defined at the compile unit level.
+ /// Called by clients to get the variable list for a compile unit. The
+ /// variable list will contain all global and static variables that were
+ /// defined at the compile unit level.
///
/// @param[in] can_create
/// If \b true, the variable list will be parsed on demand. If
@@ -309,9 +305,8 @@ public:
//------------------------------------------------------------------
/// Finds a function by user ID.
///
- /// Typically used by SymbolFile plug-ins when partially parsing
- /// the debug information to see if the function has been parsed
- /// yet.
+ /// Typically used by SymbolFile plug-ins when partially parsing the debug
+ /// information to see if the function has been parsed yet.
///
/// @param[in] uid
/// The user ID of the function to find. This value is supplied
@@ -328,10 +323,9 @@ public:
//------------------------------------------------------------------
/// Set the line table for the compile unit.
///
- /// Called by the SymbolFile plug-in when if first parses the line
- /// table and hands ownership of the line table to this object. The
- /// compile unit owns the line table object and will delete the
- /// object when it is deleted.
+ /// Called by the SymbolFile plug-in when if first parses the line table and
+ /// hands ownership of the line table to this object. The compile unit owns
+ /// the line table object and will delete the object when it is deleted.
///
/// @param[in] line_table
/// A line table object pointer that this object now owns.
@@ -343,9 +337,8 @@ public:
//------------------------------------------------------------------
/// Set accessor for the variable list.
///
- /// Called by the SymbolFile plug-ins after they have parsed the
- /// variable lists and are ready to hand ownership of the list over
- /// to this object.
+ /// Called by the SymbolFile plug-ins after they have parsed the variable
+ /// lists and are ready to hand ownership of the list over to this object.
///
/// @param[in] variable_list_sp
/// A shared pointer to a VariableList.
@@ -355,9 +348,8 @@ public:
//------------------------------------------------------------------
/// Resolve symbol contexts by file and line.
///
- /// Given a file in \a file_spec, and a line number, find all
- /// instances and append them to the supplied symbol context list
- /// \a sc_list.
+ /// Given a file in \a file_spec, and a line number, find all instances and
+ /// append them to the supplied symbol context list \a sc_list.
///
/// @param[in] file_spec
/// A file specification. If \a file_spec contains no directory
@@ -405,10 +397,10 @@ public:
//------------------------------------------------------------------
/// Get whether compiler optimizations were enabled for this compile unit
///
- /// "optimized" means that the debug experience may be difficult
- /// for the user to understand. Variables may not be available when
- /// the developer would expect them, stepping through the source lines
- /// in the function may appear strange, etc.
+ /// "optimized" means that the debug experience may be difficult for the
+ /// user to understand. Variables may not be available when the developer
+ /// would expect them, stepping through the source lines in the function may
+ /// appear strange, etc.
///
/// @return
/// Returns 'true' if this compile unit was compiled with
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h
index 70d56db7fc21..1170832a7396 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h
@@ -28,13 +28,12 @@ class DataExtractor;
//----------------------------------------------------------------------
// A class that can carry around a clang ASTContext and a opaque clang
-// QualType. A clang::QualType can be easily reconstructed from an
-// opaque clang type and often the ASTContext is needed when doing
-// various type related tasks, so this class allows both items to travel
-// in a single very lightweight class that can be used. There are many
-// static equivalents of the member functions that allow the ASTContext
-// and the opaque clang QualType to be specified for ease of use and
-// to avoid code duplication.
+// QualType. A clang::QualType can be easily reconstructed from an opaque clang
+// type and often the ASTContext is needed when doing various type related
+// tasks, so this class allows both items to travel in a single very
+// lightweight class that can be used. There are many static equivalents of the
+// member functions that allow the ASTContext and the opaque clang QualType to
+// be specified for ease of use and to avoid code duplication.
//----------------------------------------------------------------------
class CompilerType {
public:
@@ -206,8 +205,7 @@ public:
CompilerType GetFullyUnqualifiedType() const;
// Returns -1 if this isn't a function of if the function doesn't have a
- // prototype
- // Returns a value >= 0 if there is a prototype.
+ // prototype Returns a value >= 0 if there is a prototype.
int GetFunctionArgumentCount() const;
CompilerType GetFunctionArgumentTypeAtIndex(size_t idx) const;
@@ -220,14 +218,14 @@ public:
//----------------------------------------------------------------------
// If this type is a reference to a type (L value or R value reference),
- // return a new type with the reference removed, else return the current
- // type itself.
+ // return a new type with the reference removed, else return the current type
+ // itself.
//----------------------------------------------------------------------
CompilerType GetNonReferenceType() const;
//----------------------------------------------------------------------
- // If this type is a pointer type, return the type that the pointer
- // points to, else return an invalid type.
+ // If this type is a pointer type, return the type that the pointer points
+ // to, else return an invalid type.
//----------------------------------------------------------------------
CompilerType GetPointeeType() const;
@@ -237,44 +235,44 @@ public:
CompilerType GetPointerType() const;
//----------------------------------------------------------------------
- // Return a new CompilerType that is a L value reference to this type if
- // this type is valid and the type system supports L value references,
- // else return an invalid type.
+ // Return a new CompilerType that is a L value reference to this type if this
+ // type is valid and the type system supports L value references, else return
+ // an invalid type.
//----------------------------------------------------------------------
CompilerType GetLValueReferenceType() const;
//----------------------------------------------------------------------
- // Return a new CompilerType that is a R value reference to this type if
- // this type is valid and the type system supports R value references,
- // else return an invalid type.
+ // Return a new CompilerType that is a R value reference to this type if this
+ // type is valid and the type system supports R value references, else return
+ // an invalid type.
//----------------------------------------------------------------------
CompilerType GetRValueReferenceType() const;
//----------------------------------------------------------------------
- // Return a new CompilerType adds a const modifier to this type if
- // this type is valid and the type system supports const modifiers,
- // else return an invalid type.
+ // Return a new CompilerType adds a const modifier to this type if this type
+ // is valid and the type system supports const modifiers, else return an
+ // invalid type.
//----------------------------------------------------------------------
CompilerType AddConstModifier() const;
//----------------------------------------------------------------------
- // Return a new CompilerType adds a volatile modifier to this type if
- // this type is valid and the type system supports volatile modifiers,
- // else return an invalid type.
+ // Return a new CompilerType adds a volatile modifier to this type if this
+ // type is valid and the type system supports volatile modifiers, else return
+ // an invalid type.
//----------------------------------------------------------------------
CompilerType AddVolatileModifier() const;
//----------------------------------------------------------------------
- // Return a new CompilerType adds a restrict modifier to this type if
- // this type is valid and the type system supports restrict modifiers,
- // else return an invalid type.
+ // Return a new CompilerType adds a restrict modifier to this type if this
+ // type is valid and the type system supports restrict modifiers, else return
+ // an invalid type.
//----------------------------------------------------------------------
CompilerType AddRestrictModifier() const;
//----------------------------------------------------------------------
- // Create a typedef to this type using "name" as the name of the typedef
- // this type is valid and the type system supports typedefs, else return
- // an invalid type.
+ // Create a typedef to this type using "name" as the name of the typedef this
+ // type is valid and the type system supports typedefs, else return an
+ // invalid type.
//----------------------------------------------------------------------
CompilerType CreateTypedef(const char *name,
const CompilerDeclContext &decl_ctx) const;
@@ -311,8 +309,8 @@ public:
//----------------------------------------------------------------------
// If this type is an enumeration, iterate through all of its enumerators
- // using a callback. If the callback returns true, keep iterating, else
- // abort the iteration.
+ // using a callback. If the callback returns true, keep iterating, else abort
+ // the iteration.
//----------------------------------------------------------------------
void ForEachEnumerator(
std::function<bool(const CompilerType &integer_type,
@@ -351,8 +349,8 @@ public:
bool &child_is_deref_of_parent, ValueObject *valobj,
uint64_t &language_flags) const;
- // Lookup a child given a name. This function will match base class names
- // and member member names in "clang_type" only, not descendants.
+ // Lookup a child given a name. This function will match base class names and
+ // member member names in "clang_type" only, not descendants.
uint32_t GetIndexOfChildWithName(const char *name,
bool omit_empty_base_classes) const;
@@ -385,8 +383,8 @@ public:
// Pointers & References
//------------------------------------------------------------------
- // Converts "s" to a floating point value and place resulting floating
- // point bytes in the "dst" buffer.
+ // Converts "s" to a floating point value and place resulting floating point
+ // bytes in the "dst" buffer.
size_t ConvertStringToFloatValue(const char *s, uint8_t *dst,
size_t dst_size) const;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
index a1bd1bc8b1c9..133c66d4ae4f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
@@ -25,12 +25,12 @@
namespace lldb_private {
-// DWARFCallFrameInfo is a class which can read eh_frame and DWARF
-// Call Frame Information FDEs. It stores little information internally.
-// Only two APIs are exported - one to find the high/low pc values
-// of a function given a text address via the information in the
-// eh_frame / debug_frame, and one to generate an UnwindPlan based
-// on the FDE in the eh_frame / debug_frame section.
+// DWARFCallFrameInfo is a class which can read eh_frame and DWARF Call Frame
+// Information FDEs. It stores little information internally. Only two APIs
+// are exported - one to find the high/low pc values of a function given a text
+// address via the information in the eh_frame / debug_frame, and one to
+// generate an UnwindPlan based on the FDE in the eh_frame / debug_frame
+// section.
class DWARFCallFrameInfo {
public:
@@ -40,13 +40,13 @@ public:
~DWARFCallFrameInfo() = default;
- // Locate an AddressRange that includes the provided Address in this
- // object's eh_frame/debug_info
- // Returns true if a range is found to cover that address.
+ // Locate an AddressRange that includes the provided Address in this object's
+ // eh_frame/debug_info Returns true if a range is found to cover that
+ // address.
bool GetAddressRange(Address addr, AddressRange &range);
- // Return an UnwindPlan based on the call frame information encoded
- // in the FDE of this DWARFCallFrameInfo section.
+ // Return an UnwindPlan based on the call frame information encoded in the
+ // FDE of this DWARFCallFrameInfo section.
bool GetUnwindPlan(Address addr, UnwindPlan &unwind_plan);
typedef RangeVector<lldb::addr_t, uint32_t> FunctionAddressAndSizeVector;
@@ -55,12 +55,11 @@ public:
// Build a vector of file address and size for all functions in this Module
// based on the eh_frame FDE entries.
//
- // The eh_frame information can be a useful source of file address and size of
- // the functions in a Module. Often a binary's non-exported symbols are
- // stripped
- // before shipping so lldb won't know the start addr / size of many functions
- // in the Module. But the eh_frame can help to give the addresses of these
- // stripped symbols, at least.
+ // The eh_frame information can be a useful source of file address and size
+ // of the functions in a Module. Often a binary's non-exported symbols are
+ // stripped before shipping so lldb won't know the start addr / size of many
+ // functions in the Module. But the eh_frame can help to give the addresses
+ // of these stripped symbols, at least.
//
// @param[out] function_info
// A vector provided by the caller is filled out. May be empty if no
@@ -112,10 +111,9 @@ private:
typedef std::map<dw_offset_t, CIESP> cie_map_t;
- // Start address (file address), size, offset of FDE location
- // used for finding an FDE for a given File address; the start address field
- // is
- // an offset into an individual Module.
+ // Start address (file address), size, offset of FDE location used for
+ // finding an FDE for a given File address; the start address field is an
+ // offset into an individual Module.
typedef RangeDataVector<lldb::addr_t, uint32_t, dw_offset_t> FDEEntryMap;
bool IsEHFrame() const;
@@ -133,8 +131,8 @@ private:
void GetCFIData();
// Applies the specified DWARF opcode to the given row. This function handle
- // the commands
- // operates only on a single row (these are the ones what can appear both in
+ // the commands operates only on a single row (these are the ones what can
+ // appear both in
// CIE and in FDE).
// Returns true if the opcode is handled and false otherwise.
bool HandleCommonDwarfOpcode(uint8_t primary_opcode, uint8_t extended_opcode,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/DeclVendor.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/DeclVendor.h
index f0ce9157cfa5..d1ccb4191cbc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/DeclVendor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/DeclVendor.h
@@ -20,9 +20,8 @@
namespace lldb_private {
//----------------------------------------------------------------------
-// The Decl vendor class is intended as a generic interface to search
-// for named declarations that are not necessarily backed by a specific
-// symbol file.
+// The Decl vendor class is intended as a generic interface to search for named
+// declarations that are not necessarily backed by a specific symbol file.
//----------------------------------------------------------------------
class DeclVendor {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Declaration.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Declaration.h
index 581176e23961..b654988bccd2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Declaration.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Declaration.h
@@ -17,13 +17,12 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Declaration Declaration.h "lldb/Symbol/Declaration.h"
-/// @brief A class that describes the declaration location of a
+/// A class that describes the declaration location of a
/// lldb object.
///
-/// The declarations include the file specification, line number, and
-/// the column info and can help track where functions, blocks, inlined
-/// functions, types, variables, any many other debug core objects were
-/// declared.
+/// The declarations include the file specification, line number, and the
+/// column info and can help track where functions, blocks, inlined functions,
+/// types, variables, any many other debug core objects were declared.
//----------------------------------------------------------------------
class Declaration {
public:
@@ -92,8 +91,8 @@ public:
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Sets the file specification to be empty, and the line and column
- /// to zero.
+ /// Sets the file specification to be empty, and the line and column to
+ /// zero.
//------------------------------------------------------------------
void Clear() {
m_file.Clear();
@@ -106,9 +105,9 @@ public:
//------------------------------------------------------------------
/// Compare two declaration objects.
///
- /// Compares the two file specifications from \a lhs and \a rhs. If
- /// the file specifications are equal, then continue to compare the
- /// line number and column numbers respectively.
+ /// Compares the two file specifications from \a lhs and \a rhs. If the file
+ /// specifications are equal, then continue to compare the line number and
+ /// column numbers respectively.
///
/// @param[in] lhs
/// The Left Hand Side const Declaration object reference.
@@ -126,8 +125,8 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h
index 27f42cf425b2..ae8bcc892ce4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h
@@ -12,8 +12,8 @@ class UnwindTable;
class FuncUnwinders {
public:
- // FuncUnwinders objects are used to track UnwindPlans for a function
- // (named or not - really just an address range)
+ // FuncUnwinders objects are used to track UnwindPlans for a function (named
+ // or not - really just an address range)
// We'll record four different UnwindPlans for each address range:
//
@@ -28,8 +28,8 @@ public:
// available for some reason.
// Additionally, FuncUnwinds object can be asked where the prologue
- // instructions are finished for migrating breakpoints past the
- // stack frame setup instructions when we don't have line table information.
+ // instructions are finished for migrating breakpoints past the stack frame
+ // setup instructions when we don't have line table information.
FuncUnwinders(lldb_private::UnwindTable &unwind_table, AddressRange range);
@@ -38,10 +38,8 @@ public:
// current_offset is the byte offset into the function.
// 0 means no instructions have executed yet. -1 means the offset is unknown.
// On architectures where the pc points to the next instruction that will
- // execute, this
- // offset value will have already been decremented by 1 to stay within the
- // bounds of the
- // correct function body.
+ // execute, this offset value will have already been decremented by 1 to stay
+ // within the bounds of the correct function body.
lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target,
int current_offset);
@@ -69,24 +67,19 @@ public:
// A function may have a Language Specific Data Area specified -- a block of
// data in
// the object file which is used in the processing of an exception throw /
- // catch.
- // If any of the UnwindPlans have the address of the LSDA region for this
- // function,
- // this will return it.
+ // catch. If any of the UnwindPlans have the address of the LSDA region for
+ // this function, this will return it.
Address GetLSDAAddress(Target &target);
// A function may have a Personality Routine associated with it -- used in the
// processing of throwing an exception. If any of the UnwindPlans have the
- // address of the personality routine, this will return it. Read the
- // target-pointer
- // at this address to get the personality function address.
+ // address of the personality routine, this will return it. Read the target-
+ // pointer at this address to get the personality function address.
Address GetPersonalityRoutinePtrAddress(Target &target);
// The following methods to retrieve specific unwind plans should rarely be
- // used.
- // Instead, clients should ask for the *behavior* they are looking for, using
- // one
- // of the above UnwindPlan retrieval methods.
+ // used. Instead, clients should ask for the *behavior* they are looking for,
+ // using one of the above UnwindPlan retrieval methods.
lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread,
int current_offset);
@@ -116,11 +109,11 @@ public:
private:
lldb::UnwindAssemblySP GetUnwindAssemblyProfiler(Target &target);
- // Do a simplistic comparison for the register restore rule for getting
- // the caller's pc value on two UnwindPlans -- returns LazyBoolYes if
- // they have the same unwind rule for the pc, LazyBoolNo if they do not
- // have the same unwind rule for the pc, and LazyBoolCalculate if it was
- // unable to determine this for some reason.
+ // Do a simplistic comparison for the register restore rule for getting the
+ // caller's pc value on two UnwindPlans -- returns LazyBoolYes if they have
+ // the same unwind rule for the pc, LazyBoolNo if they do not have the same
+ // unwind rule for the pc, and LazyBoolCalculate if it was unable to
+ // determine this for some reason.
lldb_private::LazyBool CompareUnwindPlansForIdenticalInitialPCLocation(
Thread &thread, const lldb::UnwindPlanSP &a, const lldb::UnwindPlanSP &b);
@@ -143,8 +136,8 @@ private:
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
- // Fetching the UnwindPlans can be expensive - if we've already attempted
- // to get one & failed, don't try again.
+ // Fetching the UnwindPlans can be expensive - if we've already attempted to
+ // get one & failed, don't try again.
bool m_tried_unwind_plan_assembly : 1, m_tried_unwind_plan_eh_frame : 1,
m_tried_unwind_plan_debug_frame : 1,
m_tried_unwind_plan_eh_frame_augmented : 1,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h
index 9d376007a411..28c6b4857b10 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h
@@ -21,10 +21,10 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class FunctionInfo Function.h "lldb/Symbol/Function.h"
-/// @brief A class that contains generic function information.
+/// A class that contains generic function information.
///
-/// This provides generic function information that gets reused between
-/// inline functions and function types.
+/// This provides generic function information that gets reused between inline
+/// functions and function types.
//----------------------------------------------------------------------
class FunctionInfo {
public:
@@ -67,8 +67,8 @@ public:
//------------------------------------------------------------------
/// Compare two function information objects.
///
- /// First compares the method names, and if equal, then compares
- /// the declaration information.
+ /// First compares the method names, and if equal, then compares the
+ /// declaration information.
///
/// @param[in] lhs
/// The Left Hand Side const FunctionInfo object reference.
@@ -86,8 +86,8 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -141,13 +141,13 @@ protected:
//----------------------------------------------------------------------
/// @class InlineFunctionInfo Function.h "lldb/Symbol/Function.h"
-/// @brief A class that describes information for an inlined function.
+/// A class that describes information for an inlined function.
//----------------------------------------------------------------------
class InlineFunctionInfo : public FunctionInfo {
public:
//------------------------------------------------------------------
- /// Construct with the function method name, mangled name, and
- /// optional declaration information.
+ /// Construct with the function method name, mangled name, and optional
+ /// declaration information.
///
/// @param[in] name
/// A C string name for the method name for this function. This
@@ -171,8 +171,8 @@ public:
const Declaration *call_decl_ptr);
//------------------------------------------------------------------
- /// Construct with the function method name, mangled name, and
- /// optional declaration information.
+ /// Construct with the function method name, mangled name, and optional
+ /// declaration information.
///
/// @param[in] name
/// A name for the method name for this function. This value
@@ -202,8 +202,8 @@ public:
//------------------------------------------------------------------
/// Compare two inlined function information objects.
///
- /// First compares the FunctionInfo objects, and if equal,
- /// compares the mangled names.
+ /// First compares the FunctionInfo objects, and if equal, compares the
+ /// mangled names.
///
/// @param[in] lhs
/// The Left Hand Side const InlineFunctionInfo object
@@ -223,8 +223,8 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -292,17 +292,15 @@ private:
//----------------------------------------------------------------------
/// @class Function Function.h "lldb/Symbol/Function.h"
-/// @brief A class that describes a function.
+/// A class that describes a function.
///
-/// Functions belong to CompileUnit objects (Function::m_comp_unit),
-/// have unique user IDs (Function::UserID), know how to reconstruct
-/// their symbol context (Function::SymbolContextScope), have a
-/// specific function type (Function::m_type_uid), have a simple
-/// method name (FunctionInfo::m_name), be declared at a specific
-/// location (FunctionInfo::m_declaration), possibly have mangled
-/// names (Function::m_mangled), an optional return type
-/// (Function::m_type), and contains lexical blocks
-/// (Function::m_blocks).
+/// Functions belong to CompileUnit objects (Function::m_comp_unit), have
+/// unique user IDs (Function::UserID), know how to reconstruct their symbol
+/// context (Function::SymbolContextScope), have a specific function type
+/// (Function::m_type_uid), have a simple method name (FunctionInfo::m_name),
+/// be declared at a specific location (FunctionInfo::m_declaration), possibly
+/// have mangled names (Function::m_mangled), an optional return type
+/// (Function::m_type), and contains lexical blocks (Function::m_blocks).
///
/// The function information is split into a few pieces:
/// @li The concrete instance information
@@ -311,15 +309,14 @@ private:
/// The abstract information is found in the function type (Type) that
/// describes a function information, return type and parameter types.
///
-/// The concrete information is the address range information and
-/// specific locations for an instance of this function.
+/// The concrete information is the address range information and specific
+/// locations for an instance of this function.
//----------------------------------------------------------------------
class Function : public UserID, public SymbolContextScope {
public:
//------------------------------------------------------------------
- /// Construct with a compile unit, function UID, function type UID,
- /// optional mangled name, function type, and a section offset
- /// based address range.
+ /// Construct with a compile unit, function UID, function type UID, optional
+ /// mangled name, function type, and a section offset based address range.
///
/// @param[in] comp_unit
/// The compile unit to which this function belongs.
@@ -352,9 +349,8 @@ public:
Type *func_type, const AddressRange &range);
//------------------------------------------------------------------
- /// Construct with a compile unit, function UID, function type UID,
- /// optional mangled name, function type, and a section offset
- /// based address range.
+ /// Construct with a compile unit, function UID, function type UID, optional
+ /// mangled name, function type, and a section offset based address range.
///
/// @param[in] comp_unit
/// The compile unit to which this function belongs.
@@ -408,10 +404,10 @@ public:
lldb::LanguageType GetLanguage() const;
//------------------------------------------------------------------
- /// Find the file and line number of the source location of the start
- /// of the function. This will use the declaration if present and fall
- /// back on the line table if that fails. So there may NOT be a line
- /// table entry for this source file/line combo.
+ /// Find the file and line number of the source location of the start of the
+ /// function. This will use the declaration if present and fall back on the
+ /// line table if that fails. So there may NOT be a line table entry for
+ /// this source file/line combo.
///
/// @param[out] source_file
/// The source file.
@@ -422,8 +418,8 @@ public:
void GetStartLineSourceInfo(FileSpec &source_file, uint32_t &line_no);
//------------------------------------------------------------------
- /// Find the file and line number of the source location of the end
- /// of the function.
+ /// Find the file and line number of the source location of the end of the
+ /// function.
///
///
/// @param[out] source_file
@@ -497,8 +493,8 @@ public:
CompilerDeclContext GetDeclContext();
//------------------------------------------------------------------
- /// Get accessor for the type that describes the function
- /// return value type, and parameter types.
+ /// Get accessor for the type that describes the function return value type,
+ /// and parameter types.
///
/// @return
/// A type object pointer.
@@ -506,8 +502,8 @@ public:
Type *GetType();
//------------------------------------------------------------------
- /// Get const accessor for the type that describes the function
- /// return value type, and parameter types.
+ /// Get const accessor for the type that describes the function return value
+ /// type, and parameter types.
///
/// @return
/// A const type object pointer.
@@ -518,10 +514,8 @@ public:
//------------------------------------------------------------------
/// Get the size of the prologue instructions for this function. The
- /// "prologue"
- /// instructions include any instructions given line number 0 immediately
- /// following
- /// the prologue end.
+ /// "prologue" instructions include any instructions given line number 0
+ /// immediately following the prologue end.
///
/// @return
/// The size of the prologue.
@@ -531,8 +525,8 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -567,10 +561,10 @@ public:
///
/// The debug information may provide information about whether this
/// function was compiled with optimization or not. In this case,
- /// "optimized" means that the debug experience may be difficult
- /// for the user to understand. Variables may not be available when
- /// the developer would expect them, stepping through the source lines
- /// in the function may appear strange, etc.
+ /// "optimized" means that the debug experience may be difficult for the
+ /// user to understand. Variables may not be available when the developer
+ /// would expect them, stepping through the source lines in the function may
+ /// appear strange, etc.
///
/// @return
/// Returns 'true' if this function was compiled with
@@ -582,10 +576,10 @@ public:
//------------------------------------------------------------------
/// Get whether this function represents a 'top-level' function
///
- /// The concept of a top-level function is language-specific, mostly
- /// meant to represent the notion of scripting-style code that has
- /// global visibility of the variables/symbols/functions/...
- /// defined within the containing file/module
+ /// The concept of a top-level function is language-specific, mostly meant
+ /// to represent the notion of scripting-style code that has global
+ /// visibility of the variables/symbols/functions/... defined within the
+ /// containing file/module
///
/// If stopped in a top-level function, LLDB will expose global variables
/// as-if locals in the 'frame variable' command
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h
index ee111942c205..29c8cdceacff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h
@@ -216,8 +216,7 @@ public:
CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
// Returns -1 if this isn't a function of if the function doesn't have a
- // prototype
- // Returns a value >= 0 if there is a prototype.
+ // prototype Returns a value >= 0 if there is a prototype.
int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
@@ -294,8 +293,8 @@ public:
bool &child_is_base_class, bool &child_is_deref_of_parent,
ValueObject *valobj, uint64_t &language_flags) override;
- // Lookup a child given a name. This function will match base class names
- // and member member names in "clang_type" only, not descendants.
+ // Lookup a child given a name. This function will match base class names and
+ // member member names in "clang_type" only, not descendants.
uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
bool omit_empty_base_classes) override;
@@ -347,8 +346,8 @@ public:
Stream *s, const DataExtractor &data,
lldb::offset_t data_offset, size_t data_byte_size) override;
- // Converts "s" to a floating point value and place resulting floating
- // point bytes in the "dst" buffer.
+ // Converts "s" to a floating point value and place resulting floating point
+ // bytes in the "dst" buffer.
size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
const char *s, uint8_t *dst,
size_t dst_size) override;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h
index b9a1a1442d47..c1ce614609c1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h
@@ -18,7 +18,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class LineEntry LineEntry.h "lldb/Symbol/LineEntry.h"
-/// @brief A line table entry class.
+/// A line table entry class.
//----------------------------------------------------------------------
struct LineEntry {
//------------------------------------------------------------------
@@ -44,8 +44,8 @@ struct LineEntry {
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -79,8 +79,8 @@ struct LineEntry {
Target *target, bool show_address_only) const;
//------------------------------------------------------------------
- /// Dumps information specific to a process that stops at this
- /// line entry to the supplied stream \a s.
+ /// Dumps information specific to a process that stops at this line entry to
+ /// the supplied stream \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -123,25 +123,25 @@ struct LineEntry {
static int Compare(const LineEntry &lhs, const LineEntry &rhs);
//------------------------------------------------------------------
- /// Give the range for this LineEntry + any additional LineEntries for
- /// this same source line that are contiguous.
+ /// Give the range for this LineEntry + any additional LineEntries for this
+ /// same source line that are contiguous.
///
/// A compiler may emit multiple line entries for a single source line,
- /// e.g. to indicate subexpressions at different columns. This method
- /// will get the AddressRange for all of the LineEntries for this source
- /// line that are contiguous.
+ /// e.g. to indicate subexpressions at different columns. This method will
+ /// get the AddressRange for all of the LineEntries for this source line
+ /// that are contiguous.
//
- /// Line entries with a line number of 0 are treated specially - these
- /// are compiler-generated line table entries that the user did not
- /// write in their source code, and we want to skip past in the debugger.
- /// If this LineEntry is for line 32, and the following LineEntry is for
- /// line 0, we will extend the range to include the AddressRange of the
- /// line 0 LineEntry (and it will include the range of the following
- /// LineEntries that match either 32 or 0.)
- ///
- /// If the initial LineEntry this method is called on is a line #0, only
- /// the range of contiuous LineEntries with line #0 will be included in
- /// the complete range.
+ /// Line entries with a line number of 0 are treated specially - these are
+ /// compiler-generated line table entries that the user did not write in
+ /// their source code, and we want to skip past in the debugger. If this
+ /// LineEntry is for line 32, and the following LineEntry is for line 0, we
+ /// will extend the range to include the AddressRange of the line 0
+ /// LineEntry (and it will include the range of the following LineEntries
+ /// that match either 32 or 0.)
+ ///
+ /// If the initial LineEntry this method is called on is a line #0, only the
+ /// range of contiuous LineEntries with line #0 will be included in the
+ /// complete range.
///
/// @return
/// The contiguous AddressRange for this source line.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h
index a55e797f7b16..fe8be0c55764 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h
@@ -25,8 +25,8 @@
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class LineSequence LineTable.h "lldb/Symbol/LineTable.h"
-/// @brief An abstract base class used during symbol table creation.
+/// @class LineSequence LineTable.h "lldb/Symbol/LineTable.h" An abstract base
+/// class used during symbol table creation.
//----------------------------------------------------------------------
class LineSequence {
public:
@@ -42,7 +42,7 @@ private:
//----------------------------------------------------------------------
/// @class LineTable LineTable.h "lldb/Symbol/LineTable.h"
-/// @brief A line table class.
+/// A line table class.
//----------------------------------------------------------------------
class LineTable {
public:
@@ -111,8 +111,7 @@ public:
void GetDescription(Stream *s, Target *target, lldb::DescriptionLevel level);
//------------------------------------------------------------------
- /// Find a line entry that contains the section offset address \a
- /// so_addr.
+ /// Find a line entry that contains the section offset address \a so_addr.
///
/// @param[in] so_addr
/// A section offset address object containing the address we
@@ -134,12 +133,12 @@ public:
uint32_t *index_ptr = nullptr);
//------------------------------------------------------------------
- /// Find a line entry index that has a matching file index and
- /// source line number.
+ /// Find a line entry index that has a matching file index and source line
+ /// number.
///
- /// Finds the next line entry that has a matching \a file_idx and
- /// source line number \a line starting at the \a start_idx entries
- /// into the line entry collection.
+ /// Finds the next line entry that has a matching \a file_idx and source
+ /// line number \a line starting at the \a start_idx entries into the line
+ /// entry collection.
///
/// @param[in] start_idx
/// The number of entries to skip when starting the search.
@@ -224,8 +223,8 @@ public:
bool append);
//------------------------------------------------------------------
- /// Given a file range link map, relink the current line table
- /// and return a fixed up line table.
+ /// Given a file range link map, relink the current line table and return a
+ /// fixed up line table.
///
/// @param[out] file_range_map
/// A collection of file ranges that maps to new file ranges
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h
index 110379234fb5..2138d22808c3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h
@@ -25,23 +25,23 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ObjectContainer ObjectContainer.h "lldb/Symbol/ObjectContainer.h"
-/// @brief A plug-in interface definition class for object containers.
+/// A plug-in interface definition class for object containers.
///
-/// Object containers contain object files from one or more
-/// architectures, and also can contain one or more named objects.
+/// Object containers contain object files from one or more architectures, and
+/// also can contain one or more named objects.
///
-/// Typical object containers are static libraries (.a files) that
-/// contain multiple named object files, and universal files that contain
-/// multiple architectures.
+/// Typical object containers are static libraries (.a files) that contain
+/// multiple named object files, and universal files that contain multiple
+/// architectures.
//----------------------------------------------------------------------
class ObjectContainer : public PluginInterface, public ModuleChild {
public:
//------------------------------------------------------------------
/// Construct with a parent module, offset, and header data.
///
- /// Object files belong to modules and a valid module must be
- /// supplied upon construction. The at an offset within a file for
- /// objects that contain more than one architecture or object.
+ /// Object files belong to modules and a valid module must be supplied upon
+ /// construction. The at an offset within a file for objects that contain
+ /// more than one architecture or object.
//------------------------------------------------------------------
ObjectContainer(const lldb::ModuleSP &module_sp, const FileSpec *file,
lldb::offset_t file_offset, lldb::offset_t length,
@@ -58,18 +58,17 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is virtual since this class is designed to be
- /// inherited from by the plug-in instance.
+ /// The destructor is virtual since this class is designed to be inherited
+ /// from by the plug-in instance.
//------------------------------------------------------------------
~ObjectContainer() override = default;
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the current contents of this object
- /// to the supplied stream \a s. The dumping should include the
- /// section list if it has been parsed, and the symbol table
- /// if it has been parsed.
+ /// Dump a description of the current contents of this object to the
+ /// supplied stream \a s. The dumping should include the section list if it
+ /// has been parsed, and the symbol table if it has been parsed.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -101,8 +100,8 @@ public:
//------------------------------------------------------------------
/// Returns the offset into a file at which this object resides.
///
- /// Some files contain many object files, and this function allows
- /// access to an object's offset within the file.
+ /// Some files contain many object files, and this function allows access to
+ /// an object's offset within the file.
///
/// @return
/// The offset in bytes into the file. Defaults to zero for
@@ -124,10 +123,10 @@ public:
//------------------------------------------------------------------
/// Get the number of architectures in this object file.
///
- /// The default implementation returns 1 as for object files that
- /// contain a single architecture. ObjectContainer instances that
- /// contain more than one architecture should override this function
- /// and return an appropriate value.
+ /// The default implementation returns 1 as for object files that contain a
+ /// single architecture. ObjectContainer instances that contain more than
+ /// one architecture should override this function and return an appropriate
+ /// value.
///
/// @return
/// The number of architectures contained in this object file.
@@ -137,11 +136,11 @@ public:
//------------------------------------------------------------------
/// Attempts to parse the object header.
///
- /// This function is used as a test to see if a given plug-in
- /// instance can parse the header data already contained in
- /// ObjectContainer::m_data. If an object file parser does not
- /// recognize that magic bytes in a header, false should be returned
- /// and the next plug-in can attempt to parse an object file.
+ /// This function is used as a test to see if a given plug-in instance can
+ /// parse the header data already contained in ObjectContainer::m_data. If
+ /// an object file parser does not recognize that magic bytes in a header,
+ /// false should be returned and the next plug-in can attempt to parse an
+ /// object file.
///
/// @return
/// Returns \b true if the header was parsed successfully, \b
@@ -152,14 +151,14 @@ public:
//------------------------------------------------------------------
/// Selects an architecture in an object file.
///
- /// Object files that contain a single architecture should verify
- /// that the specified \a arch matches the architecture in in
- /// object file and return \b true or \b false accordingly.
+ /// Object files that contain a single architecture should verify that the
+ /// specified \a arch matches the architecture in in object file and return
+ /// \b true or \b false accordingly.
///
- /// Object files that contain more than one architecture should
- /// attempt to select that architecture, and if successful, clear
- /// out any previous state from any previously selected architecture
- /// and prepare to return information for the new architecture.
+ /// Object files that contain more than one architecture should attempt to
+ /// select that architecture, and if successful, clear out any previous
+ /// state from any previously selected architecture and prepare to return
+ /// information for the new architecture.
///
/// @return
/// Returns a pointer to the object file of the requested \a
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h
index dff802522da8..1e9ae8b45417 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h
@@ -20,6 +20,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/UUID.h"
#include "lldb/lldb-private.h"
+#include "llvm/Support/VersionTuple.h"
namespace lldb_private {
@@ -44,16 +45,15 @@ public:
//----------------------------------------------------------------------
/// @class ObjectFile ObjectFile.h "lldb/Symbol/ObjectFile.h"
-/// @brief A plug-in interface definition class for object file parsers.
+/// A plug-in interface definition class for object file parsers.
///
-/// Object files belong to Module objects and know how to extract
-/// information from executable, shared library, and object (.o) files
-/// used by operating system runtime. The symbol table and section list
-/// for an object file.
+/// Object files belong to Module objects and know how to extract information
+/// from executable, shared library, and object (.o) files used by operating
+/// system runtime. The symbol table and section list for an object file.
///
-/// Object files can be represented by the entire file, or by part of a
-/// file. An example of a partial file ObjectFile is one that contains
-/// information for one of multiple architectures in the same file.
+/// Object files can be represented by the entire file, or by part of a file.
+/// An example of a partial file ObjectFile is one that contains information
+/// for one of multiple architectures in the same file.
///
/// Once an architecture is selected the object file information can be
/// extracted from this abstract class.
@@ -88,12 +88,17 @@ public:
eStrataJIT
} Strata;
+ struct LoadableData {
+ lldb::addr_t Dest;
+ llvm::ArrayRef<uint8_t> Contents;
+ };
+
//------------------------------------------------------------------
/// Construct with a parent module, offset, and header data.
///
- /// Object files belong to modules and a valid module must be
- /// supplied upon construction. The at an offset within a file for
- /// objects that contain more than one architecture or object.
+ /// Object files belong to modules and a valid module must be supplied upon
+ /// construction. The at an offset within a file for objects that contain
+ /// more than one architecture or object.
//------------------------------------------------------------------
ObjectFile(const lldb::ModuleSP &module_sp, const FileSpec *file_spec_ptr,
lldb::offset_t file_offset, lldb::offset_t length,
@@ -105,18 +110,17 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is virtual since this class is designed to be
- /// inherited from by the plug-in instance.
+ /// The destructor is virtual since this class is designed to be inherited
+ /// from by the plug-in instance.
//------------------------------------------------------------------
~ObjectFile() override;
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the current contents of this object
- /// to the supplied stream \a s. The dumping should include the
- /// section list if it has been parsed, and the symbol table
- /// if it has been parsed.
+ /// Dump a description of the current contents of this object to the
+ /// supplied stream \a s. The dumping should include the section list if it
+ /// has been parsed, and the symbol table if it has been parsed.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -126,9 +130,9 @@ public:
//------------------------------------------------------------------
/// Find a ObjectFile plug-in that can parse \a file_spec.
///
- /// Scans all loaded plug-in interfaces that implement versions of
- /// the ObjectFile plug-in interface and returns the first
- /// instance that can parse the file.
+ /// Scans all loaded plug-in interfaces that implement versions of the
+ /// ObjectFile plug-in interface and returns the first instance that can
+ /// parse the file.
///
/// @param[in] module
/// The parent module that owns this object file.
@@ -156,9 +160,9 @@ public:
//------------------------------------------------------------------
/// Find a ObjectFile plug-in that can parse a file in memory.
///
- /// Scans all loaded plug-in interfaces that implement versions of
- /// the ObjectFile plug-in interface and returns the first
- /// instance that can parse the file.
+ /// Scans all loaded plug-in interfaces that implement versions of the
+ /// ObjectFile plug-in interface and returns the first instance that can
+ /// parse the file.
///
/// @param[in] module
/// The parent module that owns this object file.
@@ -189,9 +193,9 @@ public:
//------------------------------------------------------------------
/// Split a path into a file path with object name.
///
- /// For paths like "/tmp/foo.a(bar.o)" we often need to split a path
- /// up into the actual path name and into the object name so we can
- /// make a valid object file from it.
+ /// For paths like "/tmp/foo.a(bar.o)" we often need to split a path up into
+ /// the actual path name and into the object name so we can make a valid
+ /// object file from it.
///
/// @param[in] path_with_object
/// A path that might contain an archive path with a .o file
@@ -228,29 +232,25 @@ public:
//------------------------------------------------------------------
/// Get the address type given a file address in an object file.
///
- /// Many binary file formats know what kinds
- /// This is primarily for ARM binaries, though it can be applied to
- /// any executable file format that supports different opcode types
- /// within the same binary. ARM binaries support having both ARM and
- /// Thumb within the same executable container. We need to be able
- /// to get
- /// @return
+ /// Many binary file formats know what kinds This is primarily for ARM
+ /// binaries, though it can be applied to any executable file format that
+ /// supports different opcode types within the same binary. ARM binaries
+ /// support having both ARM and Thumb within the same executable container.
+ /// We need to be able to get @return
/// The size of an address in bytes for the currently selected
/// architecture (and object for archives). Returns zero if no
/// architecture or object has been selected.
//------------------------------------------------------------------
- virtual lldb::AddressClass GetAddressClass(lldb::addr_t file_addr);
+ virtual AddressClass GetAddressClass(lldb::addr_t file_addr);
//------------------------------------------------------------------
/// Extract the dependent modules from an object file.
///
- /// If an object file has information about which other images it
- /// depends on (such as shared libraries), this function will
- /// provide the list. Since many executables or shared libraries
- /// may depend on the same files,
- /// FileSpecList::AppendIfUnique(const FileSpec &) should be
- /// used to make sure any files that are added are not already in
- /// the list.
+ /// If an object file has information about which other images it depends on
+ /// (such as shared libraries), this function will provide the list. Since
+ /// many executables or shared libraries may depend on the same files,
+ /// FileSpecList::AppendIfUnique(const FileSpec &) should be used to make
+ /// sure any files that are added are not already in the list.
///
/// @param[out] file_list
/// A list of file specification objects that gets dependent
@@ -275,8 +275,8 @@ public:
//------------------------------------------------------------------
/// Returns the offset into a file at which this object resides.
///
- /// Some files contain many object files, and this function allows
- /// access to an object's offset within the file.
+ /// Some files contain many object files, and this function allows access to
+ /// an object's offset within the file.
///
/// @return
/// The offset in bytes into the file. Defaults to zero for
@@ -307,8 +307,8 @@ public:
//------------------------------------------------------------------
/// Get the name of the cpu, vendor and OS for this object file.
///
- /// This value is a string that represents the target triple where
- /// the cpu type, the vendor and the OS are encoded into a string.
+ /// This value is a string that represents the target triple where the cpu
+ /// type, the vendor and the OS are encoded into a string.
///
/// @param[out] target_triple
/// The string value of the target triple.
@@ -320,11 +320,11 @@ public:
virtual bool GetArchitecture(ArchSpec &arch) = 0;
//------------------------------------------------------------------
- /// Gets the section list for the currently selected architecture
- /// (and object for archives).
+ /// Gets the section list for the currently selected architecture (and
+ /// object for archives).
///
- /// Section list parsing can be deferred by ObjectFile instances
- /// until this accessor is called the first time.
+ /// Section list parsing can be deferred by ObjectFile instances until this
+ /// accessor is called the first time.
///
/// @return
/// The list of sections contained in this object file.
@@ -334,17 +334,17 @@ public:
virtual void CreateSections(SectionList &unified_section_list) = 0;
//------------------------------------------------------------------
- /// Notify the ObjectFile that the file addresses in the Sections
- /// for this module have been changed.
+ /// Notify the ObjectFile that the file addresses in the Sections for this
+ /// module have been changed.
//------------------------------------------------------------------
virtual void SectionFileAddressesChanged() {}
//------------------------------------------------------------------
- /// Gets the symbol table for the currently selected architecture
- /// (and object for archives).
+ /// Gets the symbol table for the currently selected architecture (and
+ /// object for archives).
///
- /// Symbol table parsing can be deferred by ObjectFile instances
- /// until this accessor is called the first time.
+ /// Symbol table parsing can be deferred by ObjectFile instances until this
+ /// accessor is called the first time.
///
/// @return
/// The symbol table for this object file.
@@ -360,11 +360,11 @@ public:
//------------------------------------------------------------------
/// Appends a Symbol for the specified so_addr to the symbol table.
///
- /// If verify_unique is false, the symbol table is not searched
- /// to determine if a Symbol found at this address has already been
- /// added to the symbol table. When verify_unique is true, this
- /// method resolves the Symbol as the first match in the SymbolTable
- /// and appends a Symbol only if required/found.
+ /// If verify_unique is false, the symbol table is not searched to determine
+ /// if a Symbol found at this address has already been added to the symbol
+ /// table. When verify_unique is true, this method resolves the Symbol as
+ /// the first match in the SymbolTable and appends a Symbol only if
+ /// required/found.
///
/// @return
/// The resolved symbol or nullptr. Returns nullptr if a
@@ -372,13 +372,13 @@ public:
//------------------------------------------------------------------
virtual Symbol *ResolveSymbolForAddress(const Address &so_addr,
bool verify_unique) {
- // Typically overridden to lazily add stripped symbols recoverable from
- // the exception handling unwind information (i.e. without parsing
- // the entire eh_frame section.
+ // Typically overridden to lazily add stripped symbols recoverable from the
+ // exception handling unwind information (i.e. without parsing the entire
+ // eh_frame section.
//
- // The availability of LC_FUNCTION_STARTS allows ObjectFileMachO
- // to efficiently add stripped symbols when the symbol table is
- // first constructed. Poorer cousins are PECoff and ELF.
+ // The availability of LC_FUNCTION_STARTS allows ObjectFileMachO to
+ // efficiently add stripped symbols when the symbol table is first
+ // constructed. Poorer cousins are PECoff and ELF.
return nullptr;
}
@@ -410,10 +410,9 @@ public:
//------------------------------------------------------------------
/// Gets the UUID for this object file.
///
- /// If the object file format contains a UUID, the value should be
- /// returned. Else ObjectFile instances should return the MD5
- /// checksum of all of the bytes for the object file (or memory for
- /// memory based object files).
+ /// If the object file format contains a UUID, the value should be returned.
+ /// Else ObjectFile instances should return the MD5 checksum of all of the
+ /// bytes for the object file (or memory for memory based object files).
///
/// @return
/// Returns \b true if a UUID was successfully extracted into
@@ -424,8 +423,8 @@ public:
//------------------------------------------------------------------
/// Gets the symbol file spec list for this object file.
///
- /// If the object file format contains a debug symbol file link,
- /// the values will be returned in the FileSpecList.
+ /// If the object file format contains a debug symbol file link, the values
+ /// will be returned in the FileSpecList.
///
/// @return
/// Returns filespeclist.
@@ -438,8 +437,8 @@ public:
/// Gets the file spec list of libraries re-exported by this object file.
///
/// If the object file format has the notion of one library re-exporting the
- /// symbols from another,
- /// the re-exported libraries will be returned in the FileSpecList.
+ /// symbols from another, the re-exported libraries will be returned in the
+ /// FileSpecList.
///
/// @return
/// Returns filespeclist.
@@ -449,8 +448,8 @@ public:
}
//------------------------------------------------------------------
- /// Sets the load address for an entire module, assuming a rigid
- /// slide of sections, if possible in the implementation.
+ /// Sets the load address for an entire module, assuming a rigid slide of
+ /// sections, if possible in the implementation.
///
/// @return
/// Returns true iff any section's load address changed.
@@ -461,8 +460,8 @@ public:
}
//------------------------------------------------------------------
- /// Gets whether endian swapping should occur when extracting data
- /// from this object file.
+ /// Gets whether endian swapping should occur when extracting data from this
+ /// object file.
///
/// @return
/// Returns \b true if endian swapping is needed, \b false
@@ -473,11 +472,11 @@ public:
//------------------------------------------------------------------
/// Attempts to parse the object header.
///
- /// This function is used as a test to see if a given plug-in
- /// instance can parse the header data already contained in
- /// ObjectFile::m_data. If an object file parser does not
- /// recognize that magic bytes in a header, false should be returned
- /// and the next plug-in can attempt to parse an object file.
+ /// This function is used as a test to see if a given plug-in instance can
+ /// parse the header data already contained in ObjectFile::m_data. If an
+ /// object file parser does not recognize that magic bytes in a header,
+ /// false should be returned and the next plug-in can attempt to parse an
+ /// object file.
///
/// @return
/// Returns \b true if the header was parsed successfully, \b
@@ -488,11 +487,11 @@ public:
//------------------------------------------------------------------
/// Returns a reference to the UnwindTable for this ObjectFile
///
- /// The UnwindTable contains FuncUnwinders objects for any function in
- /// this ObjectFile. If a FuncUnwinders object hasn't been created yet
- /// (i.e. the function has yet to be unwound in a stack walk), it
- /// will be created when requested. Specifically, we do not create
- /// FuncUnwinders objects for functions until they are needed.
+ /// The UnwindTable contains FuncUnwinders objects for any function in this
+ /// ObjectFile. If a FuncUnwinders object hasn't been created yet (i.e. the
+ /// function has yet to be unwound in a stack walk), it will be created when
+ /// requested. Specifically, we do not create FuncUnwinders objects for
+ /// functions until they are needed.
///
/// @return
/// Returns the unwind table for this object file.
@@ -500,21 +499,21 @@ public:
virtual lldb_private::UnwindTable &GetUnwindTable() { return m_unwind_table; }
//------------------------------------------------------------------
- /// Returns if the function bounds for symbols in this symbol file
- /// are likely accurate.
+ /// Returns if the function bounds for symbols in this symbol file are
+ /// likely accurate.
///
/// The unwinder can emulate the instructions of functions to understand
- /// prologue/epilogue code sequences, where registers are spilled on
- /// the stack, etc. This feature relies on having the correct start
- /// addresses of all functions. If the ObjectFile has a way to tell
- /// that symbols have been stripped and there's no way to reconstruct
- /// start addresses (e.g. LC_FUNCTION_STARTS on Mach-O, or eh_frame
- /// unwind info), the ObjectFile should indicate that assembly emulation
- /// should not be used for this module.
+ /// prologue/epilogue code sequences, where registers are spilled on the
+ /// stack, etc. This feature relies on having the correct start addresses
+ /// of all functions. If the ObjectFile has a way to tell that symbols have
+ /// been stripped and there's no way to reconstruct start addresses (e.g.
+ /// LC_FUNCTION_STARTS on Mach-O, or eh_frame unwind info), the ObjectFile
+ /// should indicate that assembly emulation should not be used for this
+ /// module.
///
- /// It is uncommon for this to return false. An ObjectFile needs to
- /// be sure that symbol start addresses are unavailable before false
- /// is returned. If it is unclear, this should return true.
+ /// It is uncommon for this to return false. An ObjectFile needs to be sure
+ /// that symbol start addresses are unavailable before false is returned.
+ /// If it is unclear, this should return true.
///
/// @return
/// Returns true if assembly emulation should be used for this
@@ -542,9 +541,9 @@ public:
}
//------------------------------------------------------------------
- /// Returns the address of the Entry Point in this object file - if
- /// the object file doesn't have an entry point (because it is not an
- /// executable file) then an invalid address is returned.
+ /// Returns the address of the Entry Point in this object file - if the
+ /// object file doesn't have an entry point (because it is not an executable
+ /// file) then an invalid address is returned.
///
/// @return
/// Returns the entry address for this module.
@@ -552,14 +551,13 @@ public:
virtual lldb_private::Address GetEntryPointAddress() { return Address(); }
//------------------------------------------------------------------
- /// Returns the address that represents the header of this object
- /// file.
+ /// Returns the address that represents the header of this object file.
///
- /// The header address is defined as where the header for the object
- /// file is that describes the content of the file. If the header
- /// doesn't appear in a section that is defined in the object file,
- /// an address with no section is returned that has the file offset
- /// set in the m_file_offset member of the lldb_private::Address object.
+ /// The header address is defined as where the header for the object file is
+ /// that describes the content of the file. If the header doesn't appear in
+ /// a section that is defined in the object file, an address with no section
+ /// is returned that has the file offset set in the m_file_offset member of
+ /// the lldb_private::Address object.
///
/// @return
/// Returns the entry address for this module.
@@ -571,9 +569,9 @@ public:
virtual uint32_t GetNumThreadContexts() { return 0; }
//------------------------------------------------------------------
- /// Some object files may have an identifier string embedded in them,
- /// e.g. in a Mach-O core file using the LC_IDENT load command (which
- /// is obsolete, but can still be found in some old files)
+ /// Some object files may have an identifier string embedded in them, e.g.
+ /// in a Mach-O core file using the LC_IDENT load command (which is
+ /// obsolete, but can still be found in some old files)
///
/// @return
/// Returns the identifier string if one exists, else an empty
@@ -584,11 +582,11 @@ public:
}
//------------------------------------------------------------------
- /// When the ObjectFile is a core file, lldb needs to locate the
- /// "binary" in the core file. lldb can iterate over the pages looking
- /// for a valid binary, but some core files may have metadata
- /// describing where the main binary is exactly which removes ambiguity
- /// when there are multiple binaries present in the captured memory pages.
+ /// When the ObjectFile is a core file, lldb needs to locate the "binary" in
+ /// the core file. lldb can iterate over the pages looking for a valid
+ /// binary, but some core files may have metadata describing where the main
+ /// binary is exactly which removes ambiguity when there are multiple
+ /// binaries present in the captured memory pages.
///
/// @param[out] address
/// If the address of the binary is specified, this will be set.
@@ -615,13 +613,12 @@ public:
}
//------------------------------------------------------------------
- /// The object file should be able to calculate its type by looking
- /// at its file header and possibly the sections or other data in
- /// the object file. The file type is used in the debugger to help
- /// select the correct plug-ins for the job at hand, so this is
- /// important to get right. If any eTypeXXX definitions do not match
- /// up with the type of file you are loading, please feel free to
- /// add a new enumeration value.
+ /// The object file should be able to calculate its type by looking at its
+ /// file header and possibly the sections or other data in the object file.
+ /// The file type is used in the debugger to help select the correct plug-
+ /// ins for the job at hand, so this is important to get right. If any
+ /// eTypeXXX definitions do not match up with the type of file you are
+ /// loading, please feel free to add a new enumeration value.
///
/// @return
/// The calculated file type for the current object file.
@@ -629,20 +626,19 @@ public:
virtual Type CalculateType() = 0;
//------------------------------------------------------------------
- /// In cases where the type can't be calculated (elf files), this
- /// routine allows someone to explicitly set it. As an example,
- /// SymbolVendorELF uses this routine to set eTypeDebugInfo when
- /// loading debug link files.
+ /// In cases where the type can't be calculated (elf files), this routine
+ /// allows someone to explicitly set it. As an example, SymbolVendorELF uses
+ /// this routine to set eTypeDebugInfo when loading debug link files.
virtual void SetType(Type type) { m_type = type; }
//------------------------------------------------------------------
- /// The object file should be able to calculate the strata of the
- /// object file.
+ /// The object file should be able to calculate the strata of the object
+ /// file.
///
- /// Many object files for platforms might be for either user space
- /// debugging or for kernel debugging. If your object file subclass
- /// can figure this out, it will help with debugger plug-in selection
- /// when it comes time to debug.
+ /// Many object files for platforms might be for either user space debugging
+ /// or for kernel debugging. If your object file subclass can figure this
+ /// out, it will help with debugger plug-in selection when it comes time to
+ /// debug.
///
/// @return
/// The calculated object file strata for the current object
@@ -653,96 +649,31 @@ public:
//------------------------------------------------------------------
/// Get the object file version numbers.
///
- /// Many object files have a set of version numbers that describe
- /// the version of the executable or shared library. Typically there
- /// are major, minor and build, but there may be more. This function
- /// will extract the versions from object files if they are available.
- ///
- /// If \a versions is NULL, or if \a num_versions is 0, the return
- /// value will indicate how many version numbers are available in
- /// this object file. Then a subsequent call can be made to this
- /// function with a value of \a versions and \a num_versions that
- /// has enough storage to store some or all version numbers.
- ///
- /// @param[out] versions
- /// A pointer to an array of uint32_t types that is \a num_versions
- /// long. If this value is NULL, the return value will indicate
- /// how many version numbers are required for a subsequent call
- /// to this function so that all versions can be retrieved. If
- /// the value is non-NULL, then at most \a num_versions of the
- /// existing versions numbers will be filled into \a versions.
- /// If there is no version information available, \a versions
- /// will be filled with \a num_versions UINT32_MAX values
- /// and zero will be returned.
- ///
- /// @param[in] num_versions
- /// The maximum number of entries to fill into \a versions. If
- /// this value is zero, then the return value will indicate
- /// how many version numbers there are in total so another call
- /// to this function can be make with adequate storage in
- /// \a versions to get all of the version numbers. If \a
- /// num_versions is less than the actual number of version
- /// numbers in this object file, only \a num_versions will be
- /// filled into \a versions (if \a versions is non-NULL).
- ///
- /// @return
- /// This function always returns the number of version numbers
- /// that this object file has regardless of the number of
- /// version numbers that were copied into \a versions.
- //------------------------------------------------------------------
- virtual uint32_t GetVersion(uint32_t *versions, uint32_t num_versions) {
- if (versions && num_versions) {
- for (uint32_t i = 0; i < num_versions; ++i)
- versions[i] = UINT32_MAX;
- }
- return 0;
- }
+ /// Many object files have a set of version numbers that describe the
+ /// version of the executable or shared library. Typically there are major,
+ /// minor and build, but there may be more. This function will extract the
+ /// versions from object files if they are available.
+ ///
+ /// @return
+ /// This function returns extracted version numbers as a
+ /// llvm::VersionTuple. In case of error an empty VersionTuple is
+ /// returned.
+ //------------------------------------------------------------------
+ virtual llvm::VersionTuple GetVersion() { return llvm::VersionTuple(); }
//------------------------------------------------------------------
/// Get the minimum OS version this object file can run on.
///
- /// Some object files have information that specifies the minimum OS
- /// version that they can be used on.
- ///
- /// If \a versions is NULL, or if \a num_versions is 0, the return
- /// value will indicate how many version numbers are available in
- /// this object file. Then a subsequent call can be made to this
- /// function with a value of \a versions and \a num_versions that
- /// has enough storage to store some or all version numbers.
- ///
- /// @param[out] versions
- /// A pointer to an array of uint32_t types that is \a num_versions
- /// long. If this value is NULL, the return value will indicate
- /// how many version numbers are required for a subsequent call
- /// to this function so that all versions can be retrieved. If
- /// the value is non-NULL, then at most \a num_versions of the
- /// existing versions numbers will be filled into \a versions.
- /// If there is no version information available, \a versions
- /// will be filled with \a num_versions UINT32_MAX values
- /// and zero will be returned.
- ///
- /// @param[in] num_versions
- /// The maximum number of entries to fill into \a versions. If
- /// this value is zero, then the return value will indicate
- /// how many version numbers there are in total so another call
- /// to this function can be make with adequate storage in
- /// \a versions to get all of the version numbers. If \a
- /// num_versions is less than the actual number of version
- /// numbers in this object file, only \a num_versions will be
- /// filled into \a versions (if \a versions is non-NULL).
- ///
- /// @return
- /// This function always returns the number of version numbers
- /// that this object file has regardless of the number of
- /// version numbers that were copied into \a versions.
- //------------------------------------------------------------------
- virtual uint32_t GetMinimumOSVersion(uint32_t *versions,
- uint32_t num_versions) {
- if (versions && num_versions) {
- for (uint32_t i = 0; i < num_versions; ++i)
- versions[i] = UINT32_MAX;
- }
- return 0;
+ /// Some object files have information that specifies the minimum OS version
+ /// that they can be used on.
+ ///
+ /// @return
+ /// This function returns extracted version numbers as a
+ /// llvm::VersionTuple. In case of error an empty VersionTuple is
+ /// returned.
+ //------------------------------------------------------------------
+ virtual llvm::VersionTuple GetMinimumOSVersion() {
+ return llvm::VersionTuple();
}
//------------------------------------------------------------------
@@ -762,12 +693,11 @@ public:
//------------------------------------------------------------------
/// Return true if this file is a dynamic link editor (dyld)
///
- /// Often times dyld has symbols that mirror symbols in libc and
- /// other shared libraries (like "malloc" and "free") and the user
- /// does _not_ want to stop in these shared libraries by default.
- /// We can ask the ObjectFile if it is such a file and should be
- /// avoided for things like settings breakpoints and doing function
- /// lookups for expressions.
+ /// Often times dyld has symbols that mirror symbols in libc and other
+ /// shared libraries (like "malloc" and "free") and the user does _not_ want
+ /// to stop in these shared libraries by default. We can ask the ObjectFile
+ /// if it is such a file and should be avoided for things like settings
+ /// breakpoints and doing function lookups for expressions.
//------------------------------------------------------------------
virtual bool GetIsDynamicLinkEditor() { return false; }
@@ -786,10 +716,9 @@ public:
return m_strata;
}
- // When an object file is in memory, subclasses should try and lock
- // the process weak pointer. If the process weak pointer produces a
- // valid ProcessSP, then subclasses can call this function to read
- // memory.
+ // When an object file is in memory, subclasses should try and lock the
+ // process weak pointer. If the process weak pointer produces a valid
+ // ProcessSP, then subclasses can call this function to read memory.
static lldb::DataBufferSP ReadMemory(const lldb::ProcessSP &process_sp,
lldb::addr_t addr, size_t byte_size);
@@ -809,8 +738,8 @@ public:
size_t dst_len);
// This function will transparently decompress section data if the section if
- // compressed. Note that for compressed section the resulting data size may be
- // larger than what Section::GetFileSize reports.
+ // compressed. Note that for compressed section the resulting data size may
+ // be larger than what Section::GetFileSize reports.
virtual size_t ReadSectionData(Section *section,
DataExtractor &section_data);
@@ -829,16 +758,16 @@ public:
//------------------------------------------------------------------
/// Loads this objfile to memory.
///
- /// Loads the bits needed to create an executable image to the memory.
- /// It is useful with bare-metal targets where target does not have the
- /// ability to start a process itself.
+ /// Loads the bits needed to create an executable image to the memory. It is
+ /// useful with bare-metal targets where target does not have the ability to
+ /// start a process itself.
///
/// @param[in] target
/// Target where to load.
///
/// @return
//------------------------------------------------------------------
- virtual Status LoadInMemory(Target &target, bool set_pc);
+ virtual std::vector<LoadableData> GetLoadableData(Target &target);
protected:
//------------------------------------------------------------------
@@ -864,9 +793,9 @@ protected:
uint32_t m_synthetic_symbol_idx;
//------------------------------------------------------------------
- /// Sets the architecture for a module. At present the architecture
- /// can only be set if it is invalid. It is not allowed to switch from
- /// one concrete architecture to another.
+ /// Sets the architecture for a module. At present the architecture can
+ /// only be set if it is invalid. It is not allowed to switch from one
+ /// concrete architecture to another.
///
/// @param[in] new_arch
/// The architecture this module will be set to.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h
index 44c67f6f4716..9523158e0780 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h
@@ -20,11 +20,9 @@ namespace lldb_private {
class Symbol : public SymbolContextScope {
public:
- // ObjectFile readers can classify their symbol table entries and searches can
- // be made
- // on specific types where the symbol values will have drastically different
- // meanings
- // and sorting requirements.
+ // ObjectFile readers can classify their symbol table entries and searches
+ // can be made on specific types where the symbol values will have
+ // drastically different meanings and sorting requirements.
Symbol();
Symbol(uint32_t symID, const char *name, bool name_is_mangled,
@@ -52,56 +50,53 @@ public:
bool ValueIsAddress() const;
//------------------------------------------------------------------
- // The GetAddressRef() accessor functions should only be called if
- // you previously call ValueIsAddress() otherwise you might get an
- // reference to an Address object that contains an constant integer
- // value in m_addr_range.m_base_addr.m_offset which could be
- // incorrectly used to represent an absolute address since it has
- // no section.
+ // The GetAddressRef() accessor functions should only be called if you
+ // previously call ValueIsAddress() otherwise you might get an reference to
+ // an Address object that contains an constant integer value in
+ // m_addr_range.m_base_addr.m_offset which could be incorrectly used to
+ // represent an absolute address since it has no section.
//------------------------------------------------------------------
Address &GetAddressRef() { return m_addr_range.GetBaseAddress(); }
const Address &GetAddressRef() const { return m_addr_range.GetBaseAddress(); }
//------------------------------------------------------------------
- // Makes sure the symbol's value is an address and returns the file
- // address. Returns LLDB_INVALID_ADDRESS if the symbol's value isn't
- // an address.
+ // Makes sure the symbol's value is an address and returns the file address.
+ // Returns LLDB_INVALID_ADDRESS if the symbol's value isn't an address.
//------------------------------------------------------------------
lldb::addr_t GetFileAddress() const;
//------------------------------------------------------------------
- // Makes sure the symbol's value is an address and gets the load
- // address using \a target if it is. Returns LLDB_INVALID_ADDRESS
- // if the symbol's value isn't an address or if the section isn't
- // loaded in \a target.
+ // Makes sure the symbol's value is an address and gets the load address
+ // using \a target if it is. Returns LLDB_INVALID_ADDRESS if the symbol's
+ // value isn't an address or if the section isn't loaded in \a target.
//------------------------------------------------------------------
lldb::addr_t GetLoadAddress(Target *target) const;
//------------------------------------------------------------------
- // Access the address value. Do NOT hand out the AddressRange as an
- // object as the byte size of the address range may not be filled in
- // and it should be accessed via GetByteSize().
+ // Access the address value. Do NOT hand out the AddressRange as an object as
+ // the byte size of the address range may not be filled in and it should be
+ // accessed via GetByteSize().
//------------------------------------------------------------------
Address GetAddress() const {
- // Make sure the our value is an address before we hand a copy out.
- // We use the Address inside m_addr_range to contain the value for
- // symbols that are not address based symbols so we are using it
- // for more than just addresses. For example undefined symbols on
- // MacOSX have a nlist.n_value of 0 (zero) and this will get placed
- // into m_addr_range.m_base_addr.m_offset and it will have no section.
- // So in the GetAddress() accessor, we need to hand out an invalid
- // address if the symbol's value isn't an address.
+ // Make sure the our value is an address before we hand a copy out. We use
+ // the Address inside m_addr_range to contain the value for symbols that
+ // are not address based symbols so we are using it for more than just
+ // addresses. For example undefined symbols on MacOSX have a nlist.n_value
+ // of 0 (zero) and this will get placed into
+ // m_addr_range.m_base_addr.m_offset and it will have no section. So in the
+ // GetAddress() accessor, we need to hand out an invalid address if the
+ // symbol's value isn't an address.
if (ValueIsAddress())
return m_addr_range.GetBaseAddress();
else
return Address();
}
- // When a symbol's value isn't an address, we need to access the raw
- // value. This function will ensure this symbol's value isn't an address
- // and return the integer value if this checks out, otherwise it will
- // return "fail_value" if the symbol is an address value.
+ // When a symbol's value isn't an address, we need to access the raw value.
+ // This function will ensure this symbol's value isn't an address and return
+ // the integer value if this checks out, otherwise it will return
+ // "fail_value" if the symbol is an address value.
uint64_t GetIntegerValue(uint64_t fail_value = 0) const {
if (ValueIsAddress()) {
// This symbol's value is an address. Use Symbol::GetAddress() to get the
@@ -238,9 +233,8 @@ public:
protected:
// This is the internal guts of ResolveReExportedSymbol, it assumes
- // reexport_name is not null, and that module_spec
- // is valid. We track the modules we've already seen to make sure we don't
- // get caught in a cycle.
+ // reexport_name is not null, and that module_spec is valid. We track the
+ // modules we've already seen to make sure we don't get caught in a cycle.
Symbol *ResolveReExportedSymbolInModuleSpec(
Target &target, ConstString &reexport_name,
@@ -260,8 +254,8 @@ protected:
m_size_is_sibling : 1, // m_size contains the index of this symbol's
// sibling
m_size_is_synthesized : 1, // non-zero if this symbol's size was
- // calculated using a delta between this symbol
- // and the next
+ // calculated using a delta between this
+ // symbol and the next
m_size_is_valid : 1,
m_demangled_is_synthesized : 1, // The demangled name was created should
// not be used for expressions or other
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h
index f84b7cf916fe..0ec0006f193a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h
@@ -29,14 +29,12 @@ namespace lldb_private {
class SymbolContextScope;
//----------------------------------------------------------------------
-/// @class SymbolContext SymbolContext.h "lldb/Symbol/SymbolContext.h"
-/// @brief Defines a symbol context baton that can be handed other debug
-/// core functions.
+/// @class SymbolContext SymbolContext.h "lldb/Symbol/SymbolContext.h" Defines
+/// a symbol context baton that can be handed other debug core functions.
///
-/// Many debugger functions require a context when doing lookups. This
-/// class provides a common structure that can be used as the result
-/// of a query that can contain a single result. Examples of such
-/// queries include
+/// Many debugger functions require a context when doing lookups. This class
+/// provides a common structure that can be used as the result of a query that
+/// can contain a single result. Examples of such queries include
/// @li Looking up a load address.
//----------------------------------------------------------------------
class SymbolContext {
@@ -44,14 +42,14 @@ public:
//------------------------------------------------------------------
/// Default constructor.
///
- /// Initialize all pointer members to nullptr and all struct members
- /// to their default state.
+ /// Initialize all pointer members to nullptr and all struct members to
+ /// their default state.
//------------------------------------------------------------------
SymbolContext();
//------------------------------------------------------------------
- /// Construct with an object that knows how to reconstruct its
- /// symbol context.
+ /// Construct with an object that knows how to reconstruct its symbol
+ /// context.
///
/// @param[in] sc_scope
/// A symbol context scope object that knows how to reconstruct
@@ -60,8 +58,8 @@ public:
explicit SymbolContext(SymbolContextScope *sc_scope);
//------------------------------------------------------------------
- /// Construct with module, and optional compile unit, function,
- /// block, line table, line entry and symbol.
+ /// Construct with module, and optional compile unit, function, block, line
+ /// table, line entry and symbol.
///
/// Initialize all pointer to the specified values.
///
@@ -112,8 +110,8 @@ public:
//------------------------------------------------------------------
/// Assignment operator.
///
- /// Copies the address value from another SymbolContext object \a
- /// rhs into \a this object.
+ /// Copies the address value from another SymbolContext object \a rhs into
+ /// \a this object.
///
/// @param[in] rhs
/// A const SymbolContext object reference to copy.
@@ -126,16 +124,16 @@ public:
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Resets all pointer members to nullptr, and clears any class objects
- /// to their default state.
+ /// Resets all pointer members to nullptr, and clears any class objects to
+ /// their default state.
//------------------------------------------------------------------
void Clear(bool clear_target);
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of this object to the
- /// supplied stream \a s.
+ /// Dump a description of the contents of this object to the supplied stream
+ /// \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -145,13 +143,12 @@ public:
//------------------------------------------------------------------
/// Dump the stop context in this object to a Stream.
///
- /// Dump the best description of this object to the stream. The
- /// information displayed depends on the amount and quality of the
- /// information in this context. If a module, function, file and
- /// line number are available, they will be dumped. If only a
- /// module and function or symbol name with offset is available,
- /// that will be output. Else just the address at which the target
- /// was stopped will be displayed.
+ /// Dump the best description of this object to the stream. The information
+ /// displayed depends on the amount and quality of the information in this
+ /// context. If a module, function, file and line number are available, they
+ /// will be dumped. If only a module and function or symbol name with offset
+ /// is available, that will be output. Else just the address at which the
+ /// target was stopped will be displayed.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -267,21 +264,21 @@ public:
lldb::LanguageType GetLanguage() const;
//------------------------------------------------------------------
- /// Find a block that defines the function represented by this
- /// symbol context.
+ /// Find a block that defines the function represented by this symbol
+ /// context.
///
- /// If this symbol context points to a block that is an inlined
- /// function, or is contained within an inlined function, the block
- /// that defines the inlined function is returned.
+ /// If this symbol context points to a block that is an inlined function, or
+ /// is contained within an inlined function, the block that defines the
+ /// inlined function is returned.
///
- /// If this symbol context has no block in it, or the block is not
- /// itself an inlined function block or contained within one, we
- /// return the top level function block.
+ /// If this symbol context has no block in it, or the block is not itself an
+ /// inlined function block or contained within one, we return the top level
+ /// function block.
///
- /// This is a handy function to call when you want to get the block
- /// whose variable list will include the arguments for the function
- /// that is represented by this symbol context (whether the function
- /// is an inline function or not).
+ /// This is a handy function to call when you want to get the block whose
+ /// variable list will include the arguments for the function that is
+ /// represented by this symbol context (whether the function is an inline
+ /// function or not).
///
/// @return
/// The block object pointer that defines the function that is
@@ -290,8 +287,8 @@ public:
Block *GetFunctionBlock();
//------------------------------------------------------------------
- /// If this symbol context represents a function that is a method,
- /// return true and provide information about the method.
+ /// If this symbol context represents a function that is a method, return
+ /// true and provide information about the method.
///
/// @param[out] language
/// If \b true is returned, the language for the method.
@@ -313,8 +310,7 @@ public:
ConstString &language_object_name);
//------------------------------------------------------------------
- /// Sorts the types in TypeMap according to SymbolContext
- /// to TypeList
+ /// Sorts the types in TypeMap according to SymbolContext to TypeList
///
//------------------------------------------------------------------
void SortTypeList(TypeMap &type_map, TypeList &type_list) const;
@@ -322,8 +318,8 @@ public:
//------------------------------------------------------------------
/// Find a name of the innermost function for the symbol context.
///
- /// For instance, if the symbol context contains an inlined block,
- /// it will return the inlined function name.
+ /// For instance, if the symbol context contains an inlined block, it will
+ /// return the inlined function name.
///
/// @param[in] prefer_mangled
/// if \btrue, then the mangled name will be returned if there
@@ -339,14 +335,13 @@ public:
//------------------------------------------------------------------
/// Get the line entry that corresponds to the function.
///
- /// If the symbol context contains an inlined block, the line entry
- /// for the start address of the inlined function will be returned,
- /// otherwise the line entry for the start address of the function
- /// will be returned. This can be used after doing a
- /// Module::FindFunctions(...) or ModuleList::FindFunctions(...)
- /// call in order to get the correct line table information for
- /// the symbol context.
- /// it will return the inlined function name.
+ /// If the symbol context contains an inlined block, the line entry for the
+ /// start address of the inlined function will be returned, otherwise the
+ /// line entry for the start address of the function will be returned. This
+ /// can be used after doing a Module::FindFunctions(...) or
+ /// ModuleList::FindFunctions(...) call in order to get the correct line
+ /// table information for the symbol context. it will return the inlined
+ /// function name.
///
/// @param[in] prefer_mangled
/// if \btrue, then the mangled name will be returned if there
@@ -361,8 +356,8 @@ public:
//------------------------------------------------------------------
/// Find the block containing the inlined block that contains this block.
///
- /// For instance, if the symbol context contains an inlined block,
- /// it will return the inlined function name.
+ /// For instance, if the symbol context contains an inlined block, it will
+ /// return the inlined function name.
///
/// @param[in] curr_frame_pc
/// The address within the block of this object.
@@ -440,11 +435,11 @@ private:
//----------------------------------------------------------------------
/// @class SymbolContextList SymbolContext.h "lldb/Symbol/SymbolContext.h"
-/// @brief Defines a list of symbol context objects.
+/// Defines a list of symbol context objects.
///
-/// This class provides a common structure that can be used to contain
-/// the result of a query that can contain a multiple results. Examples
-/// of such queries include:
+/// This class provides a common structure that can be used to contain the
+/// result of a query that can contain a multiple results. Examples of such
+/// queries include:
/// @li Looking up a function by name.
/// @li Finding all addresses for a specified file and line number.
//----------------------------------------------------------------------
@@ -491,8 +486,8 @@ public:
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
- /// Dump a description of the contents of each symbol context in
- /// the list to the supplied stream \a s.
+ /// Dump a description of the contents of each symbol context in the list to
+ /// the supplied stream \a s.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -502,8 +497,8 @@ public:
//------------------------------------------------------------------
/// Get accessor for a symbol context at index \a idx.
///
- /// Dump a description of the contents of each symbol context in
- /// the list to the supplied stream \a s.
+ /// Dump a description of the contents of each symbol context in the list to
+ /// the supplied stream \a s.
///
/// @param[in] idx
/// The zero based index into the symbol context list.
@@ -521,8 +516,8 @@ public:
//------------------------------------------------------------------
/// Direct reference accessor for a symbol context at index \a idx.
///
- /// The index \a idx must be a valid index, no error checking will
- /// be done to ensure that it is valid.
+ /// The index \a idx must be a valid index, no error checking will be done
+ /// to ensure that it is valid.
///
/// @param[in] idx
/// The zero based index into the symbol context list.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h
index 926e34bc03a2..c2fbb5272fc0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h
@@ -20,16 +20,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class SymbolContextScope SymbolContextScope.h
-/// "lldb/Symbol/SymbolContextScope.h"
-/// @brief Inherit from this if your object is part of a symbol context
+/// "lldb/Symbol/SymbolContextScope.h" Inherit from this if your object is
+/// part of a symbol context
/// and can reconstruct its symbol context.
///
-/// Many objects that are part of a symbol context that have pointers
-/// back to parent objects that own them. Any members of a symbol
-/// context that, once they are built, will not go away, can inherit
-/// from this pure virtual class and can then reconstruct their symbol
-/// context without having to keep a complete SymbolContext object in
-/// the object.
+/// Many objects that are part of a symbol context that have pointers back to
+/// parent objects that own them. Any members of a symbol context that, once
+/// they are built, will not go away, can inherit from this pure virtual class
+/// and can then reconstruct their symbol context without having to keep a
+/// complete SymbolContext object in the object.
///
/// Examples of these objects include:
/// @li Module
@@ -38,14 +37,14 @@ namespace lldb_private {
/// @li Block
/// @li Symbol
///
-/// Other objects can store a "SymbolContextScope *" using any pointers
-/// to one of the above objects. This allows clients to hold onto a
-/// pointer that uniquely will identify a symbol context. Those clients
-/// can then always reconstruct the symbol context using the pointer, or
-/// use it to uniquely identify a symbol context for an object.
+/// Other objects can store a "SymbolContextScope *" using any pointers to one
+/// of the above objects. This allows clients to hold onto a pointer that
+/// uniquely will identify a symbol context. Those clients can then always
+/// reconstruct the symbol context using the pointer, or use it to uniquely
+/// identify a symbol context for an object.
///
-/// Example objects include that currently use "SymbolContextScope *"
-/// objects include:
+/// Example objects include that currently use "SymbolContextScope *" objects
+/// include:
/// @li Variable objects that can reconstruct where they are scoped
/// by making sure the SymbolContextScope * comes from the scope
/// in which the variable was declared. If a variable is a global,
@@ -63,11 +62,11 @@ namespace lldb_private {
/// location) match within the same thread, that the stack
/// frame is the same as the previous stack frame.
///
-/// Objects that adhere to this protocol can reconstruct enough of a
-/// symbol context to allow functions that take a symbol context to be
-/// called. Lists can also be created using a SymbolContextScope* and
-/// and object pairs that allow large collections of objects to be
-/// passed around with minimal overhead.
+/// Objects that adhere to this protocol can reconstruct enough of a symbol
+/// context to allow functions that take a symbol context to be called. Lists
+/// can also be created using a SymbolContextScope* and and object pairs that
+/// allow large collections of objects to be passed around with minimal
+/// overhead.
//----------------------------------------------------------------------
class SymbolContextScope {
public:
@@ -76,9 +75,9 @@ public:
//------------------------------------------------------------------
/// Reconstruct the object's symbol context into \a sc.
///
- /// The object should fill in as much of the SymbolContext as it
- /// can so function calls that require a symbol context can be made
- /// for the given object.
+ /// The object should fill in as much of the SymbolContext as it can so
+ /// function calls that require a symbol context can be made for the given
+ /// object.
///
/// @param[out] sc
/// A symbol context object pointer that gets filled in.
@@ -100,9 +99,9 @@ public:
//------------------------------------------------------------------
/// Dump the object's symbol context to the stream \a s.
///
- /// The object should dump its symbol context to the stream \a s.
- /// This function is widely used in the DumpDebug and verbose output
- /// for lldb objects.
+ /// The object should dump its symbol context to the stream \a s. This
+ /// function is widely used in the DumpDebug and verbose output for lldb
+ /// objects.
///
/// @param[in] s
/// The stream to which to dump the object's symbol context.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h
index 69110dc68cd7..7b77c60a3c3d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h
@@ -26,10 +26,10 @@ public:
//------------------------------------------------------------------
// Symbol file ability bits.
//
- // Each symbol file can claim to support one or more symbol file
- // abilities. These get returned from SymbolFile::GetAbilities().
- // These help us to determine which plug-in will be best to load
- // the debug information found in files.
+ // Each symbol file can claim to support one or more symbol file abilities.
+ // These get returned from SymbolFile::GetAbilities(). These help us to
+ // determine which plug-in will be best to load the debug information found
+ // in files.
//------------------------------------------------------------------
enum Abilities {
CompileUnits = (1u << 0),
@@ -148,10 +148,10 @@ public:
SymbolContextList &sc_list);
virtual uint32_t
FindGlobalVariables(const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
+ const CompilerDeclContext *parent_decl_ctx,
uint32_t max_matches, VariableList &variables);
virtual uint32_t FindGlobalVariables(const RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
VariableList &variables);
virtual uint32_t FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
@@ -200,6 +200,8 @@ public:
//------------------------------------------------------------------
virtual void SectionFileAddressesChanged() {}
+ virtual void Dump(Stream &s) {}
+
protected:
ObjectFile *m_obj_file; // The object file that symbols can be extracted from.
uint32_t m_abilities;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h
index 7db3de6e690c..312b146f2970 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h
@@ -22,14 +22,13 @@
namespace lldb_private {
//----------------------------------------------------------------------
-// The symbol vendor class is designed to abstract the process of
-// searching for debug information for a given module. Platforms can
-// subclass this class and provide extra ways to find debug information.
-// Examples would be a subclass that would allow for locating a stand
-// alone debug file, parsing debug maps, or runtime data in the object
-// files. A symbol vendor can use multiple sources (SymbolFile
-// objects) to provide the information and only parse as deep as needed
-// in order to provide the information that is requested.
+// The symbol vendor class is designed to abstract the process of searching for
+// debug information for a given module. Platforms can subclass this class and
+// provide extra ways to find debug information. Examples would be a subclass
+// that would allow for locating a stand alone debug file, parsing debug maps,
+// or runtime data in the object files. A symbol vendor can use multiple
+// sources (SymbolFile objects) to provide the information and only parse as
+// deep as needed in order to provide the information that is requested.
//----------------------------------------------------------------------
class SymbolVendor : public ModuleChild, public PluginInterface {
public:
@@ -82,11 +81,11 @@ public:
virtual size_t FindGlobalVariables(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- bool append, size_t max_matches,
+ size_t max_matches,
VariableList &variables);
virtual size_t FindGlobalVariables(const RegularExpression &regex,
- bool append, size_t max_matches,
+ size_t max_matches,
VariableList &variables);
virtual size_t FindFunctions(const ConstString &name,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h
index 9740dc25a587..fec2578c9fec 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h
@@ -24,8 +24,8 @@
namespace lldb_private {
//----------------------------------------------------------------------
-// CompilerContext allows an array of these items to be passed to
-// perform detailed lookups in SymbolVendor and SymbolFile functions.
+// CompilerContext allows an array of these items to be passed to perform
+// detailed lookups in SymbolVendor and SymbolFile functions.
//----------------------------------------------------------------------
struct CompilerContext {
CompilerContext(CompilerContextKind t, const ConstString &n)
@@ -82,16 +82,12 @@ public:
eEncodingIsSyntheticUID
} EncodingDataType;
- // We must force the underlying type of the enum to be unsigned here. Not all
- // compilers
- // behave the same with regards to the default underlying type of an enum, but
- // because
- // this enum is used in an enum bitfield and integer comparisons are done with
- // the value
- // we need to guarantee that it's always unsigned so that, for example,
- // eResolveStateFull
- // doesn't compare less than eResolveStateUnresolved when used in a 2-bit
- // bitfield.
+ // We must force the underlying type of the enum to be unsigned here. Not
+ // all compilers behave the same with regards to the default underlying type
+ // of an enum, but because this enum is used in an enum bitfield and integer
+ // comparisons are done with the value we need to guarantee that it's always
+ // unsigned so that, for example, eResolveStateFull doesn't compare less than
+ // eResolveStateUnresolved when used in a 2-bit bitfield.
typedef enum ResolveStateTag : unsigned {
eResolveStateUnresolved = 0,
eResolveStateForward = 1,
@@ -106,8 +102,7 @@ public:
ResolveState compiler_type_resolve_state);
// This makes an invalid type. Used for functions that return a Type when
- // they
- // get an error.
+ // they get an error.
Type();
Type(const Type &rhs);
@@ -119,7 +114,8 @@ public:
void DumpTypeName(Stream *s);
// Since Type instances only keep a "SymbolFile *" internally, other classes
- // like TypeImpl need make sure the module is still around before playing with
+ // like TypeImpl need make sure the module is still around before playing
+ // with
// Type instances. They can store a weak pointer to the Module;
lldb::ModuleSP GetModule();
@@ -188,8 +184,8 @@ public:
CompilerType GetFullCompilerType();
// Get the clang type, and resolve definitions enough so that the type could
- // have layout performed. This allows ptrs and refs to class/struct/union/enum
- // types remain forward declarations.
+ // have layout performed. This allows ptrs and refs to
+ // class/struct/union/enum types remain forward declarations.
CompilerType GetLayoutCompilerType();
// Get the clang type and leave class/struct/union/enum types as forward
@@ -198,8 +194,8 @@ public:
static int Compare(const Type &a, const Type &b);
- // From a fully qualified typename, split the type into the type basename
- // and the remaining type scope (namespaces/classes).
+ // From a fully qualified typename, split the type into the type basename and
+ // the remaining type scope (namespaces/classes).
static bool GetTypeScopeAndBasename(const llvm::StringRef& name,
llvm::StringRef &scope,
llvm::StringRef &basename,
@@ -366,8 +362,8 @@ protected:
lldb::TypeSP type_sp;
};
-// the two classes here are used by the public API as a backend to
-// the SBType and SBTypeList classes
+// the two classes here are used by the public API as a backend to the SBType
+// and SBTypeList classes
class TypeImpl {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h
index ff85d8428746..94d1b9cdf3fd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h
@@ -66,8 +66,8 @@ public:
// {
// }
//
- // Then you can use the llvm casting on any "TypeSystem *" to get an
- // instance of your subclass.
+ // Then you can use the llvm casting on any "TypeSystem *" to get an instance
+ // of your subclass.
//----------------------------------------------------------------------
enum LLVMCastKind {
eKindClang,
@@ -94,8 +94,7 @@ public:
Target *target);
// Free up any resources associated with this TypeSystem. Done before
- // removing
- // all the TypeSystems from the TypeSystemMap.
+ // removing all the TypeSystems from the TypeSystemMap.
virtual void Finalize() {}
virtual DWARFASTParser *GetDWARFParser() { return nullptr; }
@@ -239,8 +238,7 @@ public:
virtual CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) = 0;
// Returns -1 if this isn't a function of if the function doesn't have a
- // prototype
- // Returns a value >= 0 if there is a prototype.
+ // prototype Returns a value >= 0 if there is a prototype.
virtual int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType
@@ -332,8 +330,8 @@ public:
bool &child_is_base_class, bool &child_is_deref_of_parent,
ValueObject *valobj, uint64_t &language_flags) = 0;
- // Lookup a child given a name. This function will match base class names
- // and member member names in "clang_type" only, not descendants.
+ // Lookup a child given a name. This function will match base class names and
+ // member member names in "clang_type" only, not descendants.
virtual uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
bool omit_empty_base_classes) = 0;
@@ -395,8 +393,8 @@ public:
lldb::offset_t data_offset,
size_t data_byte_size) = 0;
- // Converts "s" to a floating point value and place resulting floating
- // point bytes in the "dst" buffer.
+ // Converts "s" to a floating point value and place resulting floating point
+ // bytes in the "dst" buffer.
virtual size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
const char *s, uint8_t *dst,
size_t dst_size) = 0;
@@ -481,23 +479,17 @@ public:
virtual LazyBool ShouldPrintAsOneLiner(void *type, ValueObject *valobj);
// Type systems can have types that are placeholder types, which are meant to
- // indicate
- // the presence of a type, but offer no actual information about said types,
- // and leave
- // the burden of actually figuring type information out to dynamic type
- // resolution. For instance
- // a language with a generics system, can use placeholder types to indicate
- // "type argument goes here",
- // without promising uniqueness of the placeholder, nor attaching any actually
- // idenfiable information
- // to said placeholder. This API allows type systems to tell LLDB when such a
- // type has been encountered
- // In response, the debugger can react by not using this type as a cache entry
- // in any type-specific way
- // For instance, LLDB will currently not cache any formatters that are
- // discovered on such a type as
- // attributable to the meaningless type itself, instead preferring to use the
- // dynamic type
+ // indicate the presence of a type, but offer no actual information about
+ // said types, and leave the burden of actually figuring type information out
+ // to dynamic type resolution. For instance a language with a generics
+ // system, can use placeholder types to indicate "type argument goes here",
+ // without promising uniqueness of the placeholder, nor attaching any
+ // actually idenfiable information to said placeholder. This API allows type
+ // systems to tell LLDB when such a type has been encountered In response,
+ // the debugger can react by not using this type as a cache entry in any
+ // type-specific way For instance, LLDB will currently not cache any
+ // formatters that are discovered on such a type as attributable to the
+ // meaningless type itself, instead preferring to use the dynamic type
virtual bool IsMeaninglessWithoutDynamicResolution(void *type);
protected:
@@ -514,8 +506,8 @@ public:
// empties the map.
void Clear();
- // Iterate through all of the type systems that are created. Return true
- // from callback to keep iterating, false to stop iterating.
+ // Iterate through all of the type systems that are created. Return true from
+ // callback to keep iterating, false to stop iterating.
void ForEach(std::function<bool(TypeSystem *)> const &callback);
TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
index abb57a2c499d..a76ea23b46bc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -25,28 +25,25 @@
namespace lldb_private {
-// The UnwindPlan object specifies how to unwind out of a function - where
-// this function saves the caller's register values before modifying them
-// (for non-volatile aka saved registers) and how to find this frame's
-// Canonical Frame Address (CFA).
-
-// Most commonly, registers are saved on the stack, offset some bytes from
-// the Canonical Frame Address, or CFA, which is the starting address of
-// this function's stack frame (the CFA is same as the eh_frame's CFA,
-// whatever that may be on a given architecture).
-// The CFA address for the stack frame does not change during
-// the lifetime of the function.
+// The UnwindPlan object specifies how to unwind out of a function - where this
+// function saves the caller's register values before modifying them (for non-
+// volatile aka saved registers) and how to find this frame's Canonical Frame
+// Address (CFA).
+
+// Most commonly, registers are saved on the stack, offset some bytes from the
+// Canonical Frame Address, or CFA, which is the starting address of this
+// function's stack frame (the CFA is same as the eh_frame's CFA, whatever that
+// may be on a given architecture). The CFA address for the stack frame does
+// not change during the lifetime of the function.
// Internally, the UnwindPlan is structured as a vector of register locations
// organized by code address in the function, showing which registers have been
-// saved at that point and where they are saved.
-// It can be thought of as the expanded table form of the DWARF CFI
-// encoded information.
+// saved at that point and where they are saved. It can be thought of as the
+// expanded table form of the DWARF CFI encoded information.
// Other unwind information sources will be converted into UnwindPlans before
-// being added to a FuncUnwinders object. The unwind source may be
-// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based
-// prologue analysis.
+// being added to a FuncUnwinders object. The unwind source may be an eh_frame
+// FDE, a DWARF debug_frame FDE, or assembly language based prologue analysis.
// The UnwindPlan is the canonical form of this information that the unwinder
// code will use when walking the stack.
@@ -371,12 +368,10 @@ public:
void InsertRow(const RowSP &row_sp, bool replace_existing = false);
// Returns a pointer to the best row for the given offset into the function's
- // instructions.
- // If offset is -1 it indicates that the function start is unknown - the final
- // row in the UnwindPlan is returned.
- // In practice, the UnwindPlan for a function with no known start address will
- // be the architectural default
- // UnwindPlan which will only have one row.
+ // instructions. If offset is -1 it indicates that the function start is
+ // unknown - the final row in the UnwindPlan is returned. In practice, the
+ // UnwindPlan for a function with no known start address will be the
+ // architectural default UnwindPlan which will only have one row.
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const;
lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
@@ -427,15 +422,13 @@ public:
}
// Is this UnwindPlan valid at all instructions? If not, then it is assumed
- // valid at call sites,
- // e.g. for exception handling.
+ // valid at call sites, e.g. for exception handling.
lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const {
return m_plan_is_valid_at_all_instruction_locations;
}
// Is this UnwindPlan valid at all instructions? If not, then it is assumed
- // valid at call sites,
- // e.g. for exception handling.
+ // valid at call sites, e.g. for exception handling.
void SetUnwindPlanValidAtAllInstructions(
lldb_private::LazyBool valid_at_all_insn) {
m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h
index 851d24bea03b..5c83e3003192 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h
@@ -18,8 +18,8 @@
namespace lldb_private {
// A class which holds all the FuncUnwinders objects for a given ObjectFile.
-// The UnwindTable is populated with FuncUnwinders objects lazily during
-// the debug session.
+// The UnwindTable is populated with FuncUnwinders objects lazily during the
+// debug session.
class UnwindTable {
public:
@@ -39,16 +39,13 @@ public:
bool GetAllowAssemblyEmulationUnwindPlans();
// Normally when we create a new FuncUnwinders object we track it in this
- // UnwindTable so it can
- // be reused later. But for the target modules show-unwind we want to create
- // brand new
- // UnwindPlans for the function of interest - so ignore any existing
- // FuncUnwinders for that
- // function and don't add this new one to our UnwindTable.
- // This FuncUnwinders object does have a reference to the UnwindTable but the
- // lifetime of this
- // uncached FuncUnwinders is expected to be short so in practice this will not
- // be a problem.
+ // UnwindTable so it can be reused later. But for the target modules show-
+ // unwind we want to create brand new UnwindPlans for the function of
+ // interest - so ignore any existing FuncUnwinders for that function and
+ // don't add this new one to our UnwindTable. This FuncUnwinders object does
+ // have a reference to the UnwindTable but the lifetime of this uncached
+ // FuncUnwinders is expected to be short so in practice this will not be a
+ // problem.
lldb::FuncUnwindersSP
GetUncachedFuncUnwindersContainingAddress(const Address &addr,
SymbolContext &sc);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h
index 507b41309042..531312e63591 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h
@@ -17,6 +17,7 @@
#include "lldb/Core/RangeMap.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/Declaration.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private.h"
@@ -53,11 +54,11 @@ public:
SymbolContextScope *GetSymbolContextScope() const { return m_owner_scope; }
- // Since a variable can have a basename "i" and also a mangled
- // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
- // "(anonymous namespace)::i", this function will allow a generic match
- // function that can be called by commands and expression parsers to make
- // sure we match anything we come across.
+ // Since a variable can have a basename "i" and also a mangled named
+ // "_ZN12_GLOBAL__N_11iE" and a demangled mangled name "(anonymous
+ // namespace)::i", this function will allow a generic match function that can
+ // be called by commands and expression parsers to make sure we match
+ // anything we come across.
bool NameMatches(const ConstString &name) const;
bool NameMatches(const RegularExpression &regex) const;
@@ -103,8 +104,7 @@ public:
ValueObjectList &valobj_list);
static size_t AutoComplete(const ExecutionContext &exe_ctx,
- llvm::StringRef name, StringList &matches,
- bool &word_complete);
+ CompletionRequest &request);
CompilerDeclContext GetDeclContext();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h
index c9e0be89a3bc..6729a9c108a9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h
@@ -50,11 +50,11 @@ public:
size_t AppendVariablesIfUnique(VariableList &var_list);
- // Returns the actual number of unique variables that were added to the
- // list. "total_matches" will get updated with the actually number of
- // matches that were found regardless of whether they were unique or not
- // to allow for error conditions when nothing is found, versus conditions
- // where any variables that match "regex" were already in "var_list".
+ // Returns the actual number of unique variables that were added to the list.
+ // "total_matches" will get updated with the actually number of matches that
+ // were found regardless of whether they were unique or not to allow for
+ // error conditions when nothing is found, versus conditions where any
+ // variables that match "regex" were already in "var_list".
size_t AppendVariablesIfUnique(const RegularExpression &regex,
VariableList &var_list, size_t &total_matches);
@@ -66,6 +66,7 @@ public:
size_t MemorySize() const;
size_t GetSize() const;
+ bool Empty() const { return m_variables.empty(); }
protected:
typedef std::vector<lldb::VariableSP> collection;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h b/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h
index 0418d683af63..343b3a749597 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h
@@ -82,8 +82,7 @@ public:
protected:
// This is the method the ABI will call to actually calculate the return
- // value.
- // Don't put it in a persistent value object, that will be done by the
+ // value. Don't put it in a persistent value object, that will be done by the
// ABI::GetReturnValueObject.
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl(Thread &thread, CompilerType &ast_type) const = 0;
@@ -118,17 +117,17 @@ public:
// restrictions (4, 8 or 16 byte aligned), and zero is usually not allowed.
// This function should return true if "cfa" is valid call frame address for
// the ABI, and false otherwise. This is used by the generic stack frame
- // unwinding
- // code to help determine when a stack ends.
+ // unwinding code to help determine when a stack ends.
virtual bool CallFrameAddressIsValid(lldb::addr_t cfa) = 0;
- // Validates a possible PC value and returns true if an opcode can be at "pc".
+ // Validates a possible PC value and returns true if an opcode can be at
+ // "pc".
virtual bool CodeAddressIsValid(lldb::addr_t pc) = 0;
virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) {
- // Some targets might use bits in a code address to indicate
- // a mode switch. ARM uses bit zero to signify a code address is
- // thumb, so any ARM ABI plug-ins would strip those bits.
+ // Some targets might use bits in a code address to indicate a mode switch.
+ // ARM uses bit zero to signify a code address is thumb, so any ARM ABI
+ // plug-ins would strip those bits.
return pc;
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h b/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h
index b5890662d4e5..de9c4e233b0c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h
@@ -48,24 +48,21 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class DynamicLoader DynamicLoader.h "lldb/Target/DynamicLoader.h"
-/// @brief A plug-in interface definition class for dynamic loaders.
+/// A plug-in interface definition class for dynamic loaders.
///
/// Dynamic loader plug-ins track image (shared library) loading and
-/// unloading. The class is initialized given a live process that is
-/// halted at its entry point or just after attaching.
+/// unloading. The class is initialized given a live process that is halted at
+/// its entry point or just after attaching.
///
-/// Dynamic loader plug-ins can track the process by registering
-/// callbacks using the:
-/// Process::RegisterNotificationCallbacks (const Notifications&)
+/// Dynamic loader plug-ins can track the process by registering callbacks
+/// using the: Process::RegisterNotificationCallbacks (const Notifications&)
/// function.
///
-/// Breakpoints can also be set in the process which can register
-/// functions that get called using:
-/// Process::BreakpointSetCallback (lldb::user_id_t, BreakpointHitCallback, void
-/// *).
-/// These breakpoint callbacks return a boolean value that indicates if
-/// the process should continue or halt and should return the global
-/// setting for this using:
+/// Breakpoints can also be set in the process which can register functions
+/// that get called using: Process::BreakpointSetCallback (lldb::user_id_t,
+/// BreakpointHitCallback, void *). These breakpoint callbacks return a
+/// boolean value that indicates if the process should continue or halt and
+/// should return the global setting for this using:
/// DynamicLoader::StopWhenImagesChange() const.
//----------------------------------------------------------------------
class DynamicLoader : public PluginInterface {
@@ -73,9 +70,8 @@ public:
//------------------------------------------------------------------
/// Find a dynamic loader plugin for a given process.
///
- /// Scans the installed DynamicLoader plug-ins and tries to find
- /// an instance that can be used to track image changes in \a
- /// process.
+ /// Scans the installed DynamicLoader plug-ins and tries to find an instance
+ /// that can be used to track image changes in \a process.
///
/// @param[in] process
/// The process for which to try and locate a dynamic loader
@@ -95,45 +91,44 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is virtual since this class is designed to be
- /// inherited from by the plug-in instance.
+ /// The destructor is virtual since this class is designed to be inherited
+ /// from by the plug-in instance.
//------------------------------------------------------------------
virtual ~DynamicLoader() override;
//------------------------------------------------------------------
/// Called after attaching a process.
///
- /// Allow DynamicLoader plug-ins to execute some code after
- /// attaching to a process.
+ /// Allow DynamicLoader plug-ins to execute some code after attaching to a
+ /// process.
//------------------------------------------------------------------
virtual void DidAttach() = 0;
//------------------------------------------------------------------
/// Called after launching a process.
///
- /// Allow DynamicLoader plug-ins to execute some code after
- /// the process has stopped for the first time on launch.
+ /// Allow DynamicLoader plug-ins to execute some code after the process has
+ /// stopped for the first time on launch.
//------------------------------------------------------------------
virtual void DidLaunch() = 0;
//------------------------------------------------------------------
- /// Helper function that can be used to detect when a process has
- /// called exec and is now a new and different process. This can
- /// be called when necessary to try and detect the exec. The process
- /// might be able to answer this question, but sometimes it might
- /// not be able and the dynamic loader often knows what the program
- /// entry point is. So the process and the dynamic loader can work
- /// together to detect this.
+ /// Helper function that can be used to detect when a process has called
+ /// exec and is now a new and different process. This can be called when
+ /// necessary to try and detect the exec. The process might be able to
+ /// answer this question, but sometimes it might not be able and the dynamic
+ /// loader often knows what the program entry point is. So the process and
+ /// the dynamic loader can work together to detect this.
//------------------------------------------------------------------
virtual bool ProcessDidExec() { return false; }
//------------------------------------------------------------------
/// Get whether the process should stop when images change.
///
- /// When images (executables and shared libraries) get loaded or
- /// unloaded, often debug sessions will want to try and resolve or
- /// unresolve breakpoints that are set in these images. Any
- /// breakpoints set by DynamicLoader plug-in instances should
- /// return this value to ensure consistent debug session behaviour.
+ /// When images (executables and shared libraries) get loaded or unloaded,
+ /// often debug sessions will want to try and resolve or unresolve
+ /// breakpoints that are set in these images. Any breakpoints set by
+ /// DynamicLoader plug-in instances should return this value to ensure
+ /// consistent debug session behaviour.
///
/// @return
/// Returns \b true if the process should stop when images
@@ -144,11 +139,11 @@ public:
//------------------------------------------------------------------
/// Set whether the process should stop when images change.
///
- /// When images (executables and shared libraries) get loaded or
- /// unloaded, often debug sessions will want to try and resolve or
- /// unresolve breakpoints that are set in these images. The default
- /// is set so that the process stops when images change, but this
- /// can be overridden using this function callback.
+ /// When images (executables and shared libraries) get loaded or unloaded,
+ /// often debug sessions will want to try and resolve or unresolve
+ /// breakpoints that are set in these images. The default is set so that the
+ /// process stops when images change, but this can be overridden using this
+ /// function callback.
///
/// @param[in] stop
/// Boolean value that indicates whether the process should stop
@@ -157,8 +152,8 @@ public:
void SetStopWhenImagesChange(bool stop);
//------------------------------------------------------------------
- /// Provides a plan to step through the dynamic loader trampoline
- /// for the current state of \a thread.
+ /// Provides a plan to step through the dynamic loader trampoline for the
+ /// current state of \a thread.
///
///
/// @param[in] stop_others
@@ -173,12 +168,9 @@ public:
//------------------------------------------------------------------
/// Some dynamic loaders provide features where there are a group of symbols
- /// "equivalent to"
- /// a given symbol one of which will be chosen when the symbol is bound. If
- /// you want to
- /// set a breakpoint on one of these symbols, you really need to set it on all
- /// the
- /// equivalent symbols.
+ /// "equivalent to" a given symbol one of which will be chosen when the
+ /// symbol is bound. If you want to set a breakpoint on one of these
+ /// symbols, you really need to set it on all the equivalent symbols.
///
///
/// @param[in] original_symbol
@@ -201,13 +193,12 @@ public:
}
//------------------------------------------------------------------
- /// Ask if it is ok to try and load or unload an shared library
- /// (image).
+ /// Ask if it is ok to try and load or unload an shared library (image).
///
- /// The dynamic loader often knows when it would be ok to try and
- /// load or unload a shared library. This function call allows the
- /// dynamic loader plug-ins to check any current dyld state to make
- /// sure it is an ok time to load a shared library.
+ /// The dynamic loader often knows when it would be ok to try and load or
+ /// unload a shared library. This function call allows the dynamic loader
+ /// plug-ins to check any current dyld state to make sure it is an ok time
+ /// to load a shared library.
///
/// @return
/// \b true if it is currently ok to try and load a shared
@@ -216,20 +207,20 @@ public:
virtual Status CanLoadImage() = 0;
//------------------------------------------------------------------
- /// Ask if the eh_frame information for the given SymbolContext should
- /// be relied on even when it's the first frame in a stack unwind.
+ /// Ask if the eh_frame information for the given SymbolContext should be
+ /// relied on even when it's the first frame in a stack unwind.
///
- /// The CFI instructions from the eh_frame section are normally only
- /// valid at call sites -- places where a program could throw an
- /// exception and need to unwind out. But some Modules may be known
- /// to the system as having reliable eh_frame information at all call
- /// sites. This would be the case if the Module's contents are largely
- /// hand-written assembly with hand-written eh_frame information.
- /// Normally when unwinding from a function at the beginning of a stack
- /// unwind lldb will examine the assembly instructions to understand
- /// how the stack frame is set up and where saved registers are stored.
- /// But with hand-written assembly this is not reliable enough -- we need
- /// to consult those function's hand-written eh_frame information.
+ /// The CFI instructions from the eh_frame section are normally only valid
+ /// at call sites -- places where a program could throw an exception and
+ /// need to unwind out. But some Modules may be known to the system as
+ /// having reliable eh_frame information at all call sites. This would be
+ /// the case if the Module's contents are largely hand-written assembly with
+ /// hand-written eh_frame information. Normally when unwinding from a
+ /// function at the beginning of a stack unwind lldb will examine the
+ /// assembly instructions to understand how the stack frame is set up and
+ /// where saved registers are stored. But with hand-written assembly this is
+ /// not reliable enough -- we need to consult those function's hand-written
+ /// eh_frame information.
///
/// @return
/// \b True if the symbol context should use eh_frame instructions
@@ -271,17 +262,17 @@ public:
//------------------------------------------------------------------
/// Get information about the shared cache for a process, if possible.
///
- /// On some systems (e.g. Darwin based systems), a set of libraries
- /// that are common to most processes may be put in a single region
- /// of memory and mapped into every process, this is called the
- /// shared cache, as a performance optimization.
+ /// On some systems (e.g. Darwin based systems), a set of libraries that are
+ /// common to most processes may be put in a single region of memory and
+ /// mapped into every process, this is called the shared cache, as a
+ /// performance optimization.
///
/// Many targets will not have the concept of a shared cache.
///
- /// Depending on how the DynamicLoader gathers information about the
- /// shared cache, it may be able to only return basic information -
- /// like the UUID of the cache - or it may be able to return additional
- /// information about the cache.
+ /// Depending on how the DynamicLoader gathers information about the shared
+ /// cache, it may be able to only return basic information - like the UUID
+ /// of the cache - or it may be able to return additional information about
+ /// the cache.
///
/// @param[out] base_address
/// The base address (load address) of the shared cache.
@@ -356,8 +347,8 @@ protected:
// Return -1 if the read fails, otherwise return the result as an int64_t.
int64_t ReadUnsignedIntWithSizeInBytes(lldb::addr_t addr, int size_in_bytes);
- // Read a pointer from memory at the given addr.
- // Return LLDB_INVALID_ADDRESS if the read fails.
+ // Read a pointer from memory at the given addr. Return LLDB_INVALID_ADDRESS
+ // if the read fails.
lldb::addr_t ReadPointer(lldb::addr_t addr);
// Calls into the Process protected method LoadOperatingSystemPlugin:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h b/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h
index 04af3ebc278d..70eba3654dec 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h
@@ -22,61 +22,59 @@
namespace lldb_private {
//===----------------------------------------------------------------------===//
-/// Execution context objects refer to objects in the execution of the
-/// program that is being debugged. The consist of one or more of the
-/// following objects: target, process, thread, and frame. Many objects
-/// in the debugger need to track different executions contexts. For
-/// example, a local function variable might have an execution context
-/// that refers to a stack frame. A global or static variable might
-/// refer to a target since a stack frame isn't required in order to
-/// evaluate a global or static variable (a process isn't necessarily
-/// needed for a global variable since we might be able to read the
-/// variable value from a data section in one of the object files in
+/// Execution context objects refer to objects in the execution of the program
+/// that is being debugged. The consist of one or more of the following
+/// objects: target, process, thread, and frame. Many objects in the debugger
+/// need to track different executions contexts. For example, a local function
+/// variable might have an execution context that refers to a stack frame. A
+/// global or static variable might refer to a target since a stack frame
+/// isn't required in order to evaluate a global or static variable (a process
+/// isn't necessarily needed for a global variable since we might be able to
+/// read the variable value from a data section in one of the object files in
/// a target). There are two types of objects that hold onto execution
-/// contexts: ExecutionContextRef and ExecutionContext. Both of these
-/// objects are described below.
+/// contexts: ExecutionContextRef and ExecutionContext. Both of these objects
+/// are described below.
///
-/// Not all objects in an ExectionContext objects will be valid. If you want
-/// to refer strongly (ExectionContext) or weakly (ExectionContextRef) to
-/// a process, then only the process and target references will be valid.
-/// For threads, only the thread, process and target references will be
-/// filled in. For frames, all of the objects will be filled in.
+/// Not all objects in an ExecutionContext objects will be valid. If you want
+/// to refer strongly (ExecutionContext) or weakly (ExecutionContextRef) to a
+/// process, then only the process and target references will be valid. For
+/// threads, only the thread, process and target references will be filled in.
+/// For frames, all of the objects will be filled in.
///
-/// These classes are designed to be used as baton objects that get passed
-/// to a wide variety of functions that require execution contexts.
+/// These classes are designed to be used as baton objects that get passed to
+/// a wide variety of functions that require execution contexts.
//===----------------------------------------------------------------------===//
//----------------------------------------------------------------------
/// @class ExecutionContextRef ExecutionContext.h
/// "lldb/Target/ExecutionContext.h"
-/// @brief A class that holds a weak reference to an execution context.
+/// A class that holds a weak reference to an execution context.
///
-/// ExecutionContextRef objects are designed to hold onto an execution
-/// context that might change over time. For example, if an object wants
-/// to refer to a stack frame, it should hold onto an ExecutionContextRef
-/// to a frame object. The backing object that represents the stack frame
-/// might change over time and instances of this object can track the logical
-/// object that refers to a frame even if it does change.
+/// ExecutionContextRef objects are designed to hold onto an execution context
+/// that might change over time. For example, if an object wants to refer to a
+/// stack frame, it should hold onto an ExecutionContextRef to a frame object.
+/// The backing object that represents the stack frame might change over time
+/// and instances of this object can track the logical object that refers to a
+/// frame even if it does change.
///
/// These objects also don't keep execution objects around longer than they
-/// should since they use weak pointers. For example if an object refers
-/// to a stack frame and a stack frame is no longer in a thread, then a
-/// ExecutionContextRef object that refers to that frame will not be able
-/// to get a shared pointer to those objects since they are no longer around.
+/// should since they use weak pointers. For example if an object refers to a
+/// stack frame and a stack frame is no longer in a thread, then a
+/// ExecutionContextRef object that refers to that frame will not be able to
+/// get a shared pointer to those objects since they are no longer around.
///
-/// ExecutionContextRef objects can also be used as objects in classes
-/// that want to track a "previous execution context". Since the weak
-/// references to the execution objects (target, process, thread and frame)
-/// don't keep these objects around, they are safe to keep around.
+/// ExecutionContextRef objects can also be used as objects in classes that
+/// want to track a "previous execution context". Since the weak references to
+/// the execution objects (target, process, thread and frame) don't keep these
+/// objects around, they are safe to keep around.
///
-/// The general rule of thumb is all long lived objects that want to
-/// refer to execution contexts should use ExecutionContextRef objects.
-/// The ExecutionContext class is used to temporarily get shared
-/// pointers to any execution context objects that are still around
-/// so they are guaranteed to exist during a function that requires the
-/// objects. ExecutionContext objects should NOT be used for long term
-/// storage since they will keep objects alive with extra shared pointer
-/// references to these objects.
+/// The general rule of thumb is all long lived objects that want to refer to
+/// execution contexts should use ExecutionContextRef objects. The
+/// ExecutionContext class is used to temporarily get shared pointers to any
+/// execution context objects that are still around so they are guaranteed to
+/// exist during a function that requires the objects. ExecutionContext
+/// objects should NOT be used for long term storage since they will keep
+/// objects alive with extra shared pointer references to these objects.
//----------------------------------------------------------------------
class ExecutionContextRef {
public:
@@ -93,9 +91,9 @@ public:
//------------------------------------------------------------------
/// Construct using an ExecutionContext object that might be nullptr.
///
- /// If \a exe_ctx_ptr is valid, then make weak references to any
- /// valid objects in the ExecutionContext, otherwise no weak
- /// references to any execution context objects will be made.
+ /// If \a exe_ctx_ptr is valid, then make weak references to any valid
+ /// objects in the ExecutionContext, otherwise no weak references to any
+ /// execution context objects will be made.
//------------------------------------------------------------------
ExecutionContextRef(const ExecutionContext *exe_ctx_ptr);
@@ -107,38 +105,37 @@ public:
ExecutionContextRef(const ExecutionContext &exe_ctx);
//------------------------------------------------------------------
- /// Construct using the target and all the selected items inside of it
- /// (the process and its selected thread, and the thread's selected
- /// frame). If there is no selected thread, default to the first thread
- /// If there is no selected frame, default to the first frame.
+ /// Construct using the target and all the selected items inside of it (the
+ /// process and its selected thread, and the thread's selected frame). If
+ /// there is no selected thread, default to the first thread If there is no
+ /// selected frame, default to the first frame.
//------------------------------------------------------------------
ExecutionContextRef(Target *target, bool adopt_selected);
//------------------------------------------------------------------
/// Construct using an execution context scope.
///
- /// If the ExecutionContextScope object is valid and refers to a frame,
- /// make weak references too the frame, thread, process and target.
- /// If the ExecutionContextScope object is valid and refers to a thread,
- /// make weak references too the thread, process and target.
- /// If the ExecutionContextScope object is valid and refers to a process,
- /// make weak references too the process and target.
- /// If the ExecutionContextScope object is valid and refers to a target,
- /// make weak references too the target.
+ /// If the ExecutionContextScope object is valid and refers to a frame, make
+ /// weak references too the frame, thread, process and target. If the
+ /// ExecutionContextScope object is valid and refers to a thread, make weak
+ /// references too the thread, process and target. If the
+ /// ExecutionContextScope object is valid and refers to a process, make weak
+ /// references too the process and target. If the ExecutionContextScope
+ /// object is valid and refers to a target, make weak references too the
+ /// target.
//------------------------------------------------------------------
ExecutionContextRef(ExecutionContextScope *exe_scope);
//------------------------------------------------------------------
/// Construct using an execution context scope.
///
- /// If the ExecutionContextScope object refers to a frame,
- /// make weak references too the frame, thread, process and target.
- /// If the ExecutionContextScope object refers to a thread,
- /// make weak references too the thread, process and target.
- /// If the ExecutionContextScope object refers to a process,
- /// make weak references too the process and target.
- /// If the ExecutionContextScope object refers to a target,
- /// make weak references too the target.
+ /// If the ExecutionContextScope object refers to a frame, make weak
+ /// references too the frame, thread, process and target. If the
+ /// ExecutionContextScope object refers to a thread, make weak references
+ /// too the thread, process and target. If the ExecutionContextScope object
+ /// refers to a process, make weak references too the process and target. If
+ /// the ExecutionContextScope object refers to a target, make weak
+ /// references too the target.
//------------------------------------------------------------------
ExecutionContextRef(ExecutionContextScope &exe_scope);
@@ -167,33 +164,33 @@ public:
void Clear();
//------------------------------------------------------------------
- /// Set accessor that creates a weak reference to the target
- /// referenced in \a target_sp.
+ /// Set accessor that creates a weak reference to the target referenced in
+ /// \a target_sp.
///
- /// If \a target_sp is valid this object will create a weak
- /// reference to that object, otherwise any previous target weak
- /// reference contained in this object will be reset.
+ /// If \a target_sp is valid this object will create a weak reference to
+ /// that object, otherwise any previous target weak reference contained in
+ /// this object will be reset.
///
- /// Only the weak reference to the target will be updated, no other
- /// weak references will be modified. If you want this execution
- /// context to make a weak reference to the target's process, use
- /// the ExecutionContextRef::SetContext() functions.
+ /// Only the weak reference to the target will be updated, no other weak
+ /// references will be modified. If you want this execution context to make
+ /// a weak reference to the target's process, use the
+ /// ExecutionContextRef::SetContext() functions.
///
/// @see ExecutionContextRef::SetContext(const lldb::TargetSP &, bool)
//------------------------------------------------------------------
void SetTargetSP(const lldb::TargetSP &target_sp);
//------------------------------------------------------------------
- /// Set accessor that creates a weak reference to the process
- /// referenced in \a process_sp.
+ /// Set accessor that creates a weak reference to the process referenced in
+ /// \a process_sp.
///
- /// If \a process_sp is valid this object will create a weak
- /// reference to that object, otherwise any previous process weak
- /// reference contained in this object will be reset.
+ /// If \a process_sp is valid this object will create a weak reference to
+ /// that object, otherwise any previous process weak reference contained in
+ /// this object will be reset.
///
- /// Only the weak reference to the process will be updated, no other
- /// weak references will be modified. If you want this execution
- /// context to make a weak reference to the target, use the
+ /// Only the weak reference to the process will be updated, no other weak
+ /// references will be modified. If you want this execution context to make
+ /// a weak reference to the target, use the
/// ExecutionContextRef::SetContext() functions.
///
/// @see ExecutionContextRef::SetContext(const lldb::ProcessSP &)
@@ -201,34 +198,34 @@ public:
void SetProcessSP(const lldb::ProcessSP &process_sp);
//------------------------------------------------------------------
- /// Set accessor that creates a weak reference to the thread
- /// referenced in \a thread_sp.
+ /// Set accessor that creates a weak reference to the thread referenced in
+ /// \a thread_sp.
///
- /// If \a thread_sp is valid this object will create a weak
- /// reference to that object, otherwise any previous thread weak
- /// reference contained in this object will be reset.
+ /// If \a thread_sp is valid this object will create a weak reference to
+ /// that object, otherwise any previous thread weak reference contained in
+ /// this object will be reset.
///
- /// Only the weak reference to the thread will be updated, no other
- /// weak references will be modified. If you want this execution
- /// context to make a weak reference to the thread's process and
- /// target, use the ExecutionContextRef::SetContext() functions.
+ /// Only the weak reference to the thread will be updated, no other weak
+ /// references will be modified. If you want this execution context to make
+ /// a weak reference to the thread's process and target, use the
+ /// ExecutionContextRef::SetContext() functions.
///
/// @see ExecutionContextRef::SetContext(const lldb::ThreadSP &)
//------------------------------------------------------------------
void SetThreadSP(const lldb::ThreadSP &thread_sp);
//------------------------------------------------------------------
- /// Set accessor that creates a weak reference to the frame
- /// referenced in \a frame_sp.
+ /// Set accessor that creates a weak reference to the frame referenced in \a
+ /// frame_sp.
///
- /// If \a frame_sp is valid this object will create a weak
- /// reference to that object, otherwise any previous frame weak
- /// reference contained in this object will be reset.
+ /// If \a frame_sp is valid this object will create a weak reference to that
+ /// object, otherwise any previous frame weak reference contained in this
+ /// object will be reset.
///
- /// Only the weak reference to the frame will be updated, no other
- /// weak references will be modified. If you want this execution
- /// context to make a weak reference to the frame's thread, process
- /// and target, use the ExecutionContextRef::SetContext() functions.
+ /// Only the weak reference to the frame will be updated, no other weak
+ /// references will be modified. If you want this execution context to make
+ /// a weak reference to the frame's thread, process and target, use the
+ /// ExecutionContextRef::SetContext() functions.
///
/// @see ExecutionContextRef::SetContext(const lldb::StackFrameSP &)
//------------------------------------------------------------------
@@ -281,28 +278,25 @@ public:
//------------------------------------------------------------------
/// Create an ExecutionContext object from this object.
///
- /// Create strong references to any execution context objects that
- /// are still valid. Any of the returned shared pointers in the
- /// ExecutionContext objects is not guaranteed to be valid.
- /// @returns
+ /// Create strong references to any execution context objects that are still
+ /// valid. Any of the returned shared pointers in the ExecutionContext
+ /// objects is not guaranteed to be valid. @returns
/// An execution context object that has strong references to
/// any valid weak references in this object.
//------------------------------------------------------------------
ExecutionContext Lock(bool thread_and_frame_only_if_stopped) const;
//------------------------------------------------------------------
- /// Returns true if this object has a weak reference to a thread.
- /// The return value is only an indication of whether this object has
- /// a weak reference and does not indicate whether the weak reference
- /// is valid or not.
+ /// Returns true if this object has a weak reference to a thread. The return
+ /// value is only an indication of whether this object has a weak reference
+ /// and does not indicate whether the weak reference is valid or not.
//------------------------------------------------------------------
bool HasThreadRef() const { return m_tid != LLDB_INVALID_THREAD_ID; }
//------------------------------------------------------------------
- /// Returns true if this object has a weak reference to a frame.
- /// The return value is only an indication of whether this object has
- /// a weak reference and does not indicate whether the weak reference
- /// is valid or not.
+ /// Returns true if this object has a weak reference to a frame. The return
+ /// value is only an indication of whether this object has a weak reference
+ /// and does not indicate whether the weak reference is valid or not.
//------------------------------------------------------------------
bool HasFrameRef() const { return m_stack_id.IsValid(); }
@@ -327,25 +321,25 @@ protected:
};
//----------------------------------------------------------------------
-/// @class ExecutionContext ExecutionContext.h "lldb/Target/ExecutionContext.h"
-/// @brief A class that contains an execution context.
+/// @class ExecutionContext ExecutionContext.h
+/// "lldb/Target/ExecutionContext.h"
+/// A class that contains an execution context.
///
-/// This baton object can be passed into any function that requires
-/// a context that specifies a target, process, thread and frame.
-/// These objects are designed to be used for short term execution
-/// context object storage while a function might be trying to evaluate
-/// something that requires a thread or frame. ExecutionContextRef
-/// objects can be used to initialize one of these objects to turn
-/// the weak execution context object references to the target, process,
-/// thread and frame into strong references (shared pointers) so that
-/// functions can guarantee that these objects won't go away in the
+/// This baton object can be passed into any function that requires a context
+/// that specifies a target, process, thread and frame. These objects are
+/// designed to be used for short term execution context object storage while
+/// a function might be trying to evaluate something that requires a thread or
+/// frame. ExecutionContextRef objects can be used to initialize one of these
+/// objects to turn the weak execution context object references to the
+/// target, process, thread and frame into strong references (shared pointers)
+/// so that functions can guarantee that these objects won't go away in the
/// middle of a function.
///
-/// ExecutionContext objects should be used as short lived objects
-/// (typically on the stack) in order to lock down an execution context
-/// for local use and for passing down to other functions that also
-/// require specific contexts. They should NOT be used for long term
-/// storage, for long term storage use ExecutionContextRef objects.
+/// ExecutionContext objects should be used as short lived objects (typically
+/// on the stack) in order to lock down an execution context for local use and
+/// for passing down to other functions that also require specific contexts.
+/// They should NOT be used for long term storage, for long term storage use
+/// ExecutionContextRef objects.
//----------------------------------------------------------------------
class ExecutionContext {
public:
@@ -384,8 +378,7 @@ public:
bool thread_and_frame_only_if_stopped = false);
// These two variants take in a locker, and grab the target, lock the API
- // mutex into locker, then
- // fill in the rest of the shared pointers.
+ // mutex into locker, then fill in the rest of the shared pointers.
ExecutionContext(const ExecutionContextRef &exe_ctx_ref,
std::unique_lock<std::recursive_mutex> &locker);
ExecutionContext(const ExecutionContextRef *exe_ctx_ref,
@@ -441,14 +434,14 @@ public:
/// Returns a pointer to the target object.
///
/// The returned pointer might be nullptr. Calling HasTargetScope(),
- /// HasProcessScope(), HasThreadScope(), or HasFrameScope()
- /// can help to pre-validate this pointer so that this accessor can
- /// freely be used without having to check for nullptr each time.
+ /// HasProcessScope(), HasThreadScope(), or HasFrameScope() can help to pre-
+ /// validate this pointer so that this accessor can freely be used without
+ /// having to check for nullptr each time.
///
- /// @see ExecutionContext::HasTargetScope() const
- /// @see ExecutionContext::HasProcessScope() const
- /// @see ExecutionContext::HasThreadScope() const
- /// @see ExecutionContext::HasFrameScope() const
+ /// @see ExecutionContext::HasTargetScope() const @see
+ /// ExecutionContext::HasProcessScope() const @see
+ /// ExecutionContext::HasThreadScope() const @see
+ /// ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
Target *GetTargetPtr() const;
@@ -456,13 +449,13 @@ public:
/// Returns a pointer to the process object.
///
/// The returned pointer might be nullptr. Calling HasProcessScope(),
- /// HasThreadScope(), or HasFrameScope() can help to pre-validate
- /// this pointer so that this accessor can freely be used without
- /// having to check for nullptr each time.
+ /// HasThreadScope(), or HasFrameScope() can help to pre-validate this
+ /// pointer so that this accessor can freely be used without having to check
+ /// for nullptr each time.
///
- /// @see ExecutionContext::HasProcessScope() const
- /// @see ExecutionContext::HasThreadScope() const
- /// @see ExecutionContext::HasFrameScope() const
+ /// @see ExecutionContext::HasProcessScope() const @see
+ /// ExecutionContext::HasThreadScope() const @see
+ /// ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
Process *GetProcessPtr() const;
@@ -470,21 +463,21 @@ public:
/// Returns a pointer to the thread object.
///
/// The returned pointer might be nullptr. Calling HasThreadScope() or
- /// HasFrameScope() can help to pre-validate this pointer so that
- /// this accessor can freely be used without having to check for
- /// nullptr each time.
+ /// HasFrameScope() can help to pre-validate this pointer so that this
+ /// accessor can freely be used without having to check for nullptr each
+ /// time.
///
- /// @see ExecutionContext::HasThreadScope() const
- /// @see ExecutionContext::HasFrameScope() const
+ /// @see ExecutionContext::HasThreadScope() const @see
+ /// ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
Thread *GetThreadPtr() const { return m_thread_sp.get(); }
//------------------------------------------------------------------
/// Returns a pointer to the frame object.
///
- /// The returned pointer might be nullptr. Calling HasFrameScope(),
- /// can help to pre-validate this pointer so that this accessor can
- /// freely be used without having to check for nullptr each time.
+ /// The returned pointer might be nullptr. Calling HasFrameScope(), can help
+ /// to pre-validate this pointer so that this accessor can freely be used
+ /// without having to check for nullptr each time.
///
/// @see ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
@@ -494,14 +487,13 @@ public:
/// Returns a reference to the target object.
///
/// Clients should call HasTargetScope(), HasProcessScope(),
- /// HasThreadScope(), or HasFrameScope() prior to calling this
- /// function to ensure that this ExecutionContext object contains
- /// a valid target.
+ /// HasThreadScope(), or HasFrameScope() prior to calling this function to
+ /// ensure that this ExecutionContext object contains a valid target.
///
- /// @see ExecutionContext::HasTargetScope() const
- /// @see ExecutionContext::HasProcessScope() const
- /// @see ExecutionContext::HasThreadScope() const
- /// @see ExecutionContext::HasFrameScope() const
+ /// @see ExecutionContext::HasTargetScope() const @see
+ /// ExecutionContext::HasProcessScope() const @see
+ /// ExecutionContext::HasThreadScope() const @see
+ /// ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
Target &GetTargetRef() const;
@@ -509,33 +501,32 @@ public:
/// Returns a reference to the process object.
///
/// Clients should call HasProcessScope(), HasThreadScope(), or
- /// HasFrameScope() prior to calling this function to ensure that
- /// this ExecutionContext object contains a valid target.
+ /// HasFrameScope() prior to calling this function to ensure that this
+ /// ExecutionContext object contains a valid target.
///
- /// @see ExecutionContext::HasProcessScope() const
- /// @see ExecutionContext::HasThreadScope() const
- /// @see ExecutionContext::HasFrameScope() const
+ /// @see ExecutionContext::HasProcessScope() const @see
+ /// ExecutionContext::HasThreadScope() const @see
+ /// ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
Process &GetProcessRef() const;
//------------------------------------------------------------------
/// Returns a reference to the thread object.
///
- /// Clients should call HasThreadScope(), or HasFrameScope() prior
- /// to calling this function to ensure that this ExecutionContext
- /// object contains a valid target.
+ /// Clients should call HasThreadScope(), or HasFrameScope() prior to
+ /// calling this function to ensure that this ExecutionContext object
+ /// contains a valid target.
///
- /// @see ExecutionContext::HasThreadScope() const
- /// @see ExecutionContext::HasFrameScope() const
+ /// @see ExecutionContext::HasThreadScope() const @see
+ /// ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
Thread &GetThreadRef() const;
//------------------------------------------------------------------
/// Returns a reference to the thread object.
///
- /// Clients should call HasFrameScope() prior to calling this
- /// function to ensure that this ExecutionContext object contains
- /// a valid target.
+ /// Clients should call HasFrameScope() prior to calling this function to
+ /// ensure that this ExecutionContext object contains a valid target.
///
/// @see ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
@@ -596,8 +587,8 @@ public:
void SetTargetPtr(Target *target);
//------------------------------------------------------------------
- /// Set accessor to set only the process shared pointer from a
- /// process pointer.
+ /// Set accessor to set only the process shared pointer from a process
+ /// pointer.
//------------------------------------------------------------------
void SetProcessPtr(Process *process);
@@ -608,50 +599,47 @@ public:
void SetThreadPtr(Thread *thread);
//------------------------------------------------------------------
- /// Set accessor to set only the frame shared pointer from a frame
- /// pointer.
+ /// Set accessor to set only the frame shared pointer from a frame pointer.
//------------------------------------------------------------------
void SetFramePtr(StackFrame *frame);
//------------------------------------------------------------------
// Set the execution context using a target shared pointer.
//
- // If "target_sp" is valid, sets the target context to match and
- // if "get_process" is true, sets the process shared pointer if
- // the target currently has a process.
+ // If "target_sp" is valid, sets the target context to match and if
+ // "get_process" is true, sets the process shared pointer if the target
+ // currently has a process.
//------------------------------------------------------------------
void SetContext(const lldb::TargetSP &target_sp, bool get_process);
//------------------------------------------------------------------
// Set the execution context using a process shared pointer.
//
- // If "process_sp" is valid, then set the process and target in this
- // context. Thread and frame contexts will be cleared.
- // If "process_sp" is not valid, all shared pointers are reset.
+ // If "process_sp" is valid, then set the process and target in this context.
+ // Thread and frame contexts will be cleared. If "process_sp" is not valid,
+ // all shared pointers are reset.
//------------------------------------------------------------------
void SetContext(const lldb::ProcessSP &process_sp);
//------------------------------------------------------------------
// Set the execution context using a thread shared pointer.
//
- // If "thread_sp" is valid, then set the thread, process and target
- // in this context. The frame context will be cleared.
- // If "thread_sp" is not valid, all shared pointers are reset.
+ // If "thread_sp" is valid, then set the thread, process and target in this
+ // context. The frame context will be cleared. If "thread_sp" is not valid,
+ // all shared pointers are reset.
//------------------------------------------------------------------
void SetContext(const lldb::ThreadSP &thread_sp);
//------------------------------------------------------------------
// Set the execution context using a frame shared pointer.
//
- // If "frame_sp" is valid, then set the frame, thread, process and
- // target in this context
- // If "frame_sp" is not valid, all shared pointers are reset.
+ // If "frame_sp" is valid, then set the frame, thread, process and target in
+ // this context If "frame_sp" is not valid, all shared pointers are reset.
//------------------------------------------------------------------
void SetContext(const lldb::StackFrameSP &frame_sp);
//------------------------------------------------------------------
- /// Returns true the ExecutionContext object contains a valid
- /// target.
+ /// Returns true the ExecutionContext object contains a valid target.
///
/// This function can be called after initializing an ExecutionContext
/// object, and if it returns true, calls to GetTargetPtr() and
@@ -660,36 +648,35 @@ public:
bool HasTargetScope() const;
//------------------------------------------------------------------
- /// Returns true the ExecutionContext object contains a valid
- /// target and process.
+ /// Returns true the ExecutionContext object contains a valid target and
+ /// process.
///
/// This function can be called after initializing an ExecutionContext
/// object, and if it returns true, calls to GetTargetPtr() and
- /// GetTargetRef(), GetProcessPtr(), and GetProcessRef(), do not
- /// need to be checked for validity.
+ /// GetTargetRef(), GetProcessPtr(), and GetProcessRef(), do not need to be
+ /// checked for validity.
//------------------------------------------------------------------
bool HasProcessScope() const;
//------------------------------------------------------------------
- /// Returns true the ExecutionContext object contains a valid
- /// target, process, and thread.
+ /// Returns true the ExecutionContext object contains a valid target,
+ /// process, and thread.
///
/// This function can be called after initializing an ExecutionContext
- /// object, and if it returns true, calls to GetTargetPtr(),
- /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(),
- /// and GetThreadRef() do not need to be checked for validity.
+ /// object, and if it returns true, calls to GetTargetPtr(), GetTargetRef(),
+ /// GetProcessPtr(), GetProcessRef(), GetThreadPtr(), and GetThreadRef() do
+ /// not need to be checked for validity.
//------------------------------------------------------------------
bool HasThreadScope() const;
//------------------------------------------------------------------
- /// Returns true the ExecutionContext object contains a valid
- /// target, process, thread and frame.
+ /// Returns true the ExecutionContext object contains a valid target,
+ /// process, thread and frame.
///
/// This function can be called after initializing an ExecutionContext
- /// object, and if it returns true, calls to GetTargetPtr(),
- /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(),
- /// GetThreadRef(), GetFramePtr(), and GetFrameRef() do not need
- /// to be checked for validity.
+ /// object, and if it returns true, calls to GetTargetPtr(), GetTargetRef(),
+ /// GetProcessPtr(), GetProcessRef(), GetThreadPtr(), GetThreadRef(),
+ /// GetFramePtr(), and GetFrameRef() do not need to be checked for validity.
//------------------------------------------------------------------
bool HasFrameScope() const;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContextScope.h b/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContextScope.h
index 36d3d9de49b0..b73ca576bd8a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContextScope.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContextScope.h
@@ -20,22 +20,21 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ExecutionContextScope ExecutionContextScope.h
-/// "lldb/Symbol/ExecutionContextScope.h"
-/// @brief Inherit from this if your object can reconstruct its
+/// "lldb/Symbol/ExecutionContextScope.h" Inherit from this if your object can
+/// reconstruct its
/// execution context.
///
-/// Many objects that have pointers back to parent execution context
-/// objects can inherit from this pure virtual class can reconstruct
-/// their execution context without having to keep a complete
-/// ExecutionContext object in the object state. Examples of these
-/// objects include: Process, Thread, RegisterContext and StackFrame.
+/// Many objects that have pointers back to parent execution context objects
+/// can inherit from this pure virtual class can reconstruct their execution
+/// context without having to keep a complete ExecutionContext object in the
+/// object state. Examples of these objects include: Process, Thread,
+/// RegisterContext and StackFrame.
///
-/// Objects can contain a valid pointer to an instance of this so they
-/// can reconstruct the execution context.
+/// Objects can contain a valid pointer to an instance of this so they can
+/// reconstruct the execution context.
///
-/// Objects that adhere to this protocol can reconstruct enough of a
-/// execution context to allow functions that take a execution contexts
-/// to be called.
+/// Objects that adhere to this protocol can reconstruct enough of a execution
+/// context to allow functions that take a execution contexts to be called.
//----------------------------------------------------------------------
class ExecutionContextScope {
public:
@@ -52,9 +51,9 @@ public:
//------------------------------------------------------------------
/// Reconstruct the object's execution context into \a sc.
///
- /// The object should fill in as much of the ExecutionContextScope as it
- /// can so function calls that require a execution context can be made
- /// for the given object.
+ /// The object should fill in as much of the ExecutionContextScope as it can
+ /// so function calls that require a execution context can be made for the
+ /// given object.
///
/// @param[out] exe_ctx
/// A reference to an execution context object that gets filled
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h b/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h
index 97f2a9796a80..56f1417eddb0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h
@@ -19,21 +19,21 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class JITLoader JITLoader.h "lldb/Target/JITLoader.h"
-/// @brief A plug-in interface definition class for JIT loaders.
+/// A plug-in interface definition class for JIT loaders.
///
-/// Plugins of this kind listen for code generated at runtime in the
-/// target. They are very similar to dynamic loader, with the difference
-/// that they do not have information about the target's dyld and
-/// that there may be multiple JITLoader plugins per process, while
-/// there is at most one DynamicLoader.
+/// Plugins of this kind listen for code generated at runtime in the target.
+/// They are very similar to dynamic loader, with the difference that they do
+/// not have information about the target's dyld and that there may be
+/// multiple JITLoader plugins per process, while there is at most one
+/// DynamicLoader.
//----------------------------------------------------------------------
class JITLoader : public PluginInterface {
public:
//------------------------------------------------------------------
/// Find a JIT loader plugin for a given process.
///
- /// Scans the installed DynamicLoader plug-ins and tries to find
- /// all applicable instances for the current process.
+ /// Scans the installed DynamicLoader plug-ins and tries to find all
+ /// applicable instances for the current process.
///
/// @param[in] process
/// The process for which to try and locate a JIT loader
@@ -52,22 +52,22 @@ public:
//------------------------------------------------------------------
/// Called after attaching a process.
///
- /// Allow JITLoader plug-ins to execute some code after
- /// attaching to a process.
+ /// Allow JITLoader plug-ins to execute some code after attaching to a
+ /// process.
//------------------------------------------------------------------
virtual void DidAttach() = 0;
//------------------------------------------------------------------
/// Called after launching a process.
///
- /// Allow JITLoader plug-ins to execute some code after
- /// the process has stopped for the first time on launch.
+ /// Allow JITLoader plug-ins to execute some code after the process has
+ /// stopped for the first time on launch.
//------------------------------------------------------------------
virtual void DidLaunch() = 0;
//------------------------------------------------------------------
- /// Called after a new shared object has been loaded so that it can
- /// be probed for JIT entry point hooks.
+ /// Called after a new shared object has been loaded so that it can be
+ /// probed for JIT entry point hooks.
//------------------------------------------------------------------
virtual void ModulesDidLoad(lldb_private::ModuleList &module_list) = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Language.h b/contrib/llvm/tools/lldb/include/lldb/Target/Language.h
index f81679f78129..dd7db26f3ba6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Language.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Language.h
@@ -184,19 +184,16 @@ public:
virtual const char *GetLanguageSpecificTypeLookupHelp();
// if an individual data formatter can apply to several types and cross a
- // language boundary
- // it makes sense for individual languages to want to customize the printing
- // of values of that
- // type by appending proper prefix/suffix information in language-specific
- // ways
+ // language boundary it makes sense for individual languages to want to
+ // customize the printing of values of that type by appending proper
+ // prefix/suffix information in language-specific ways
virtual bool GetFormatterPrefixSuffix(ValueObject &valobj,
ConstString type_hint,
std::string &prefix,
std::string &suffix);
// if a language has a custom format for printing variable declarations that
- // it wants LLDB to honor
- // it should return an appropriate closure here
+ // it wants LLDB to honor it should return an appropriate closure here
virtual DumpValueObjectOptions::DeclPrintingHelper GetDeclPrintingHelper();
virtual LazyBool IsLogicalTrue(ValueObject &valobj, Status &error);
@@ -206,11 +203,9 @@ public:
virtual bool IsNilReference(ValueObject &valobj);
// for a ValueObject of some "reference type", if the language provides a
- // technique
- // to decide whether the reference has ever been assigned to some object, this
- // method
- // will return true if such detection is possible, and if the reference has
- // never been assigned
+ // technique to decide whether the reference has ever been assigned to some
+ // object, this method will return true if such detection is possible, and if
+ // the reference has never been assigned
virtual bool IsUninitializedReference(ValueObject &valobj);
virtual bool GetFunctionDisplayName(const SymbolContext *sc,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h
index 98db941669c7..6537a8f6dd55 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h
@@ -85,26 +85,23 @@ public:
Address &address,
Value::ValueType &value_type) = 0;
- // This call should return a CompilerType given a generic type name
- // and an ExecutionContextScope in which one can actually fetch
- // any specialization information required.
+ // This call should return a CompilerType given a generic type name and an
+ // ExecutionContextScope in which one can actually fetch any specialization
+ // information required.
virtual CompilerType GetConcreteType(ExecutionContextScope *exe_scope,
ConstString abstract_type_name) {
return CompilerType();
}
// This should be a fast test to determine whether it is likely that this
- // value would
- // have a dynamic type.
+ // value would have a dynamic type.
virtual bool CouldHaveDynamicValue(ValueObject &in_value) = 0;
// The contract for GetDynamicTypeAndAddress() is to return a "bare-bones"
- // dynamic type
- // For instance, given a Base* pointer, GetDynamicTypeAndAddress() will return
- // the type of
- // Derived, not Derived*. The job of this API is to correct this misalignment
- // between the
- // static type and the discovered dynamic type
+ // dynamic type For instance, given a Base* pointer,
+ // GetDynamicTypeAndAddress() will return the type of Derived, not Derived*.
+ // The job of this API is to correct this misalignment between the static
+ // type and the discovered dynamic type
virtual TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
ValueObject &static_value) = 0;
@@ -144,18 +141,16 @@ public:
virtual void ModulesDidLoad(const ModuleList &module_list) {}
- // Called by the Clang expression evaluation engine to allow runtimes to alter
- // the set of target options provided to
- // the compiler.
- // If the options prototype is modified, runtimes must return true, false
- // otherwise.
+ // Called by the Clang expression evaluation engine to allow runtimes to
+ // alter the set of target options provided to the compiler. If the options
+ // prototype is modified, runtimes must return true, false otherwise.
virtual bool GetOverrideExprOptions(clang::TargetOptions &prototype) {
return false;
}
// Called by ClangExpressionParser::PrepareForExecution to query for any
- // custom LLVM IR passes
- // that need to be run before an expression is assembled and run.
+ // custom LLVM IR passes that need to be run before an expression is
+ // assembled and run.
virtual bool GetIRPasses(LLVMUserExpression::IRPasses &custom_passes) {
return false;
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Memory.h b/contrib/llvm/tools/lldb/include/lldb/Target/Memory.h
index af6be15df9fb..16d7b256a78e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Memory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Memory.h
@@ -120,8 +120,8 @@ protected:
//----------------------------------------------------------------------
// A class that can track allocated memory and give out allocated memory
-// without us having to make an allocate/deallocate call every time we
-// need some memory in a process that is being debugged.
+// without us having to make an allocate/deallocate call every time we need
+// some memory in a process that is being debugged.
//----------------------------------------------------------------------
class AllocatedMemoryCache {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/MemoryRegionInfo.h b/contrib/llvm/tools/lldb/include/lldb/Target/MemoryRegionInfo.h
index 0824b2442acc..505ecfcfc5ae 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -25,7 +25,7 @@ public:
MemoryRegionInfo()
: m_range(), m_read(eDontKnow), m_write(eDontKnow), m_execute(eDontKnow),
- m_mapped(eDontKnow) {}
+ m_mapped(eDontKnow), m_flash(eDontKnow), m_blocksize(0) {}
~MemoryRegionInfo() {}
@@ -58,9 +58,17 @@ public:
void SetName(const char *name) { m_name = ConstString(name); }
+ OptionalBool GetFlash() const { return m_flash; }
+
+ void SetFlash(OptionalBool val) { m_flash = val; }
+
+ lldb::offset_t GetBlocksize() const { return m_blocksize; }
+
+ void SetBlocksize(lldb::offset_t blocksize) { m_blocksize = blocksize; }
+
//----------------------------------------------------------------------
- // Get permissions as a uint32_t that is a mask of one or more bits from
- // the lldb::Permissions
+ // Get permissions as a uint32_t that is a mask of one or more bits from the
+ // lldb::Permissions
//----------------------------------------------------------------------
uint32_t GetLLDBPermissions() const {
uint32_t permissions = 0;
@@ -74,8 +82,8 @@ public:
}
//----------------------------------------------------------------------
- // Set permissions from a uint32_t that contains one or more bits from
- // the lldb::Permissions
+ // Set permissions from a uint32_t that contains one or more bits from the
+ // lldb::Permissions
//----------------------------------------------------------------------
void SetLLDBPermissions(uint32_t permissions) {
m_read = (permissions & lldb::ePermissionsReadable) ? eYes : eNo;
@@ -98,6 +106,8 @@ protected:
OptionalBool m_execute;
OptionalBool m_mapped;
ConstString m_name;
+ OptionalBool m_flash;
+ lldb::offset_t m_blocksize;
};
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ModuleCache.h b/contrib/llvm/tools/lldb/include/lldb/Target/ModuleCache.h
index 4959ee8ea0a3..a060937e0614 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ModuleCache.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ModuleCache.h
@@ -28,10 +28,10 @@ class UUID;
//----------------------------------------------------------------------
/// @class ModuleCache ModuleCache.h "lldb/Target/ModuleCache.h"
-/// @brief A module cache class.
+/// A module cache class.
///
-/// Caches locally modules that are downloaded from remote targets.
-/// Each cached module maintains 2 views:
+/// Caches locally modules that are downloaded from remote targets. Each
+/// cached module maintains 2 views:
/// - UUID view:
/// /${CACHE_ROOT}/${PLATFORM_NAME}/.cache/${UUID}/${MODULE_FILENAME}
/// - Sysroot view:
@@ -42,7 +42,8 @@ class UUID;
///
/// Example:
/// UUID view :
-/// /tmp/lldb/remote-linux/.cache/30C94DC6-6A1F-E951-80C3-D68D2B89E576-D5AE213C/libc.so.6
+/// /tmp/lldb/remote-
+/// linux/.cache/30C94DC6-6A1F-E951-80C3-D68D2B89E576-D5AE213C/libc.so.6
/// Sysroot view: /tmp/lldb/remote-linux/ubuntu/lib/x86_64-linux-gnu/libc.so.6
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h
index 97a2a731581a..6f8354ea3a27 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h
@@ -48,10 +48,9 @@ public:
class ClassDescriptor;
typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP;
- // the information that we want to support retrieving from an ObjC class
- // this needs to be pure virtual since there are at least 2 different
- // implementations
- // of the runtime, and more might come
+ // the information that we want to support retrieving from an ObjC class this
+ // needs to be pure virtual since there are at least 2 different
+ // implementations of the runtime, and more might come
class ClassDescriptor {
public:
ClassDescriptor()
@@ -66,8 +65,8 @@ public:
virtual ClassDescriptorSP GetMetaclass() const = 0;
- // virtual if any implementation has some other version-specific rules
- // but for the known v1/v2 this is all that needs to be done
+ // virtual if any implementation has some other version-specific rules but
+ // for the known v1/v2 this is all that needs to be done
virtual bool IsKVO() {
if (m_is_kvo == eLazyBoolCalculate) {
const char *class_name = GetClassName().AsCString();
@@ -78,8 +77,8 @@ public:
return (m_is_kvo == eLazyBoolYes);
}
- // virtual if any implementation has some other version-specific rules
- // but for the known v1/v2 this is all that needs to be done
+ // virtual if any implementation has some other version-specific rules but
+ // for the known v1/v2 this is all that needs to be done
virtual bool IsCFType() {
if (m_is_cf == eLazyBoolCalculate) {
const char *class_name = GetClassName().AsCString();
@@ -268,15 +267,14 @@ public:
virtual DeclVendor *GetDeclVendor() { return nullptr; }
// Finds the byte offset of the child_type ivar in parent_type. If it can't
- // find the
- // offset, returns LLDB_INVALID_IVAR_OFFSET.
+ // find the offset, returns LLDB_INVALID_IVAR_OFFSET.
virtual size_t GetByteOffsetForIvar(CompilerType &parent_qual_type,
const char *ivar_name);
- // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol),
- // try to determine from the runtime what the value of that symbol would be.
- // Useful when the underlying binary is stripped.
+ // Given the name of an Objective-C runtime symbol (e.g., ivar offset
+ // symbol), try to determine from the runtime what the value of that symbol
+ // would be. Useful when the underlying binary is stripped.
virtual lldb::addr_t LookupRuntimeSymbol(const ConstString &name) {
return LLDB_INVALID_ADDRESS;
}
@@ -334,8 +332,7 @@ protected:
private:
// We keep a map of <Class,Selector>->Implementation so we don't have to call
- // the resolver
- // function over and over.
+ // the resolver function over and over.
// FIXME: We need to watch for the loading of Protocols, and flush the cache
// for any
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h b/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h
index 24ded3f69723..fe4fdee182f4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h
@@ -22,13 +22,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class OperatingSystem OperatingSystem.h "lldb/Target/OperatingSystem.h"
-/// @brief A plug-in interface definition class for halted OS helpers.
+/// A plug-in interface definition class for halted OS helpers.
///
/// Halted OS plug-ins can be used by any process to locate and create
/// OS objects, like threads, during the lifetime of a debug session.
/// This is commonly used when attaching to an operating system that is
-/// halted, such as when debugging over JTAG or connecting to low level
-/// kernel debug services.
+/// halted, such as when debugging over JTAG or connecting to low level kernel
+/// debug services.
//----------------------------------------------------------------------
class OperatingSystem : public PluginInterface {
@@ -36,9 +36,8 @@ public:
//------------------------------------------------------------------
/// Find a halted OS plugin for a given process.
///
- /// Scans the installed OperatingSystem plug-ins and tries to find
- /// an instance that matches the current target triple and
- /// executable.
+ /// Scans the installed OperatingSystem plug-ins and tries to find an
+ /// instance that matches the current target triple and executable.
///
/// @param[in] process
/// The process for which to try and locate a halted OS
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/PathMappingList.h b/contrib/llvm/tools/lldb/include/lldb/Target/PathMappingList.h
index b1b551f2d24d..a5ee3265a223 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/PathMappingList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/PathMappingList.h
@@ -90,7 +90,7 @@ public:
bool RemapPath(llvm::StringRef path, std::string &new_path) const;
bool RemapPath(const char *, std::string &) const = delete;
- bool ReverseRemapPath(const ConstString &path, ConstString &new_path) const;
+ bool ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const;
//------------------------------------------------------------------
/// Finds a source file given a file spec using the path remappings.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h b/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h
index 6288a3ab684f..217b945d29cd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h
@@ -27,12 +27,10 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-public.h"
-
-// TODO pull NativeDelegate class out of NativeProcessProtocol so we
-// can just forward ref the NativeDelegate rather than include it here.
-#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "llvm/Support/VersionTuple.h"
namespace lldb_private {
@@ -57,7 +55,7 @@ typedef llvm::SmallVector<lldb::addr_t, 6> MmapArgList;
//----------------------------------------------------------------------
/// @class Platform Platform.h "lldb/Target/Platform.h"
-/// @brief A plug-in interface definition class for debug platform that
+/// A plug-in interface definition class for debug platform that
/// includes many platform abilities such as:
/// @li getting platform information such as supported architectures,
/// supported binary file formats and more
@@ -78,8 +76,8 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is virtual since this class is designed to be
- /// inherited from by the plug-in instance.
+ /// The destructor is virtual since this class is designed to be inherited
+ /// from by the plug-in instance.
//------------------------------------------------------------------
~Platform() override;
@@ -92,13 +90,13 @@ public:
//------------------------------------------------------------------
/// Get the native host platform plug-in.
///
- /// There should only be one of these for each host that LLDB runs
- /// upon that should be statically compiled in and registered using
- /// preprocessor macros or other similar build mechanisms in a
+ /// There should only be one of these for each host that LLDB runs upon that
+ /// should be statically compiled in and registered using preprocessor
+ /// macros or other similar build mechanisms in a
/// PlatformSubclass::Initialize() function.
///
- /// This platform will be used as the default platform when launching
- /// or attaching to processes unless another platform is specified.
+ /// This platform will be used as the default platform when launching or
+ /// attaching to processes unless another platform is specified.
//------------------------------------------------------------------
static lldb::PlatformSP GetHostPlatform();
@@ -127,8 +125,8 @@ public:
//------------------------------------------------------------------
/// Find a platform plugin for a given process.
///
- /// Scans the installed Platform plug-ins and tries to find
- /// an instance that can be used for \a process
+ /// Scans the installed Platform plug-ins and tries to find an instance that
+ /// can be used for \a process
///
/// @param[in] process
/// The process for which to try and locate a platform
@@ -142,19 +140,17 @@ public:
// FindPlugin (Process *process, const ConstString &plugin_name);
//------------------------------------------------------------------
- /// Set the target's executable based off of the existing
- /// architecture information in \a target given a path to an
- /// executable \a exe_file.
+ /// Set the target's executable based off of the existing architecture
+ /// information in \a target given a path to an executable \a exe_file.
///
- /// Each platform knows the architectures that it supports and can
- /// select the correct architecture slice within \a exe_file by
- /// inspecting the architecture in \a target. If the target had an
- /// architecture specified, then in can try and obey that request
- /// and optionally fail if the architecture doesn't match up.
- /// If no architecture is specified, the platform should select the
- /// default architecture from \a exe_file. Any application bundles
- /// or executable wrappers can also be inspected for the actual
- /// application binary within the bundle that should be used.
+ /// Each platform knows the architectures that it supports and can select
+ /// the correct architecture slice within \a exe_file by inspecting the
+ /// architecture in \a target. If the target had an architecture specified,
+ /// then in can try and obey that request and optionally fail if the
+ /// architecture doesn't match up. If no architecture is specified, the
+ /// platform should select the default architecture from \a exe_file. Any
+ /// application bundles or executable wrappers can also be inspected for the
+ /// actual application binary within the bundle that should be used.
///
/// @return
/// Returns \b true if this Platform plug-in was able to find
@@ -167,10 +163,10 @@ public:
//------------------------------------------------------------------
/// Find a symbol file given a symbol file module specification.
///
- /// Each platform might have tricks to find symbol files for an
- /// executable given information in a symbol file ModuleSpec. Some
- /// platforms might also support symbol files that are bundles and
- /// know how to extract the right symbol file given a bundle.
+ /// Each platform might have tricks to find symbol files for an executable
+ /// given information in a symbol file ModuleSpec. Some platforms might also
+ /// support symbol files that are bundles and know how to extract the right
+ /// symbol file given a bundle.
///
/// @param[in] target
/// The target in which we are trying to resolve the symbol file.
@@ -215,9 +211,8 @@ public:
FileSpec &sym_file);
//------------------------------------------------------------------
- /// Resolves the FileSpec to a (possibly) remote path. Remote
- /// platforms must override this to resolve to a path on the remote
- /// side.
+ /// Resolves the FileSpec to a (possibly) remote path. Remote platforms must
+ /// override this to resolve to a path on the remote side.
//------------------------------------------------------------------
virtual bool ResolveRemotePath(const FileSpec &platform_path,
FileSpec &resolved_platform_path);
@@ -225,17 +220,15 @@ public:
//------------------------------------------------------------------
/// Get the OS version from a connected platform.
///
- /// Some platforms might not be connected to a remote platform, but
- /// can figure out the OS version for a process. This is common for
- /// simulator platforms that will run native programs on the current
- /// host, but the simulator might be simulating a different OS. The
- /// \a process parameter might be specified to help to determine
- /// the OS version.
+ /// Some platforms might not be connected to a remote platform, but can
+ /// figure out the OS version for a process. This is common for simulator
+ /// platforms that will run native programs on the current host, but the
+ /// simulator might be simulating a different OS. The \a process parameter
+ /// might be specified to help to determine the OS version.
//------------------------------------------------------------------
- virtual bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update,
- Process *process = nullptr);
+ virtual llvm::VersionTuple GetOSVersion(Process *process = nullptr);
- bool SetOSVersion(uint32_t major, uint32_t minor, uint32_t update);
+ bool SetOSVersion(llvm::VersionTuple os_version);
bool GetOSBuildString(std::string &s);
@@ -253,19 +246,19 @@ public:
//------------------------------------------------------------------
/// Report the current status for this platform.
///
- /// The returned string usually involves returning the OS version
- /// (if available), and any SDK directory that might be being used
- /// for local file caching, and if connected a quick blurb about
- /// what this platform is connected to.
+ /// The returned string usually involves returning the OS version (if
+ /// available), and any SDK directory that might be being used for local
+ /// file caching, and if connected a quick blurb about what this platform is
+ /// connected to.
//------------------------------------------------------------------
virtual void GetStatus(Stream &strm);
//------------------------------------------------------------------
// Subclasses must be able to fetch the current OS version
//
- // Remote classes must be connected for this to succeed. Local
- // subclasses don't need to override this function as it will just
- // call the HostInfo::GetOSVersion().
+ // Remote classes must be connected for this to succeed. Local subclasses
+ // don't need to override this function as it will just call the
+ // HostInfo::GetOSVersion().
//------------------------------------------------------------------
virtual bool GetRemoteOSVersion() { return false; }
@@ -295,8 +288,8 @@ public:
//------------------------------------------------------------------
/// Locate a file for a platform.
///
- /// The default implementation of this function will return the same
- /// file patch in \a local_file as was in \a platform_file.
+ /// The default implementation of this function will return the same file
+ /// patch in \a local_file as was in \a platform_file.
///
/// @param[in] platform_file
/// The platform file path to locate and cache locally.
@@ -326,8 +319,8 @@ public:
//----------------------------------------------------------------------
// Locate the scripting resource given a module specification.
//
- // Locating the file should happen only on the local computer or using
- // the current computers global settings.
+ // Locating the file should happen only on the local computer or using the
+ // current computers global settings.
//----------------------------------------------------------------------
virtual FileSpecList
LocateExecutableScriptingResources(Target *target, Module &module,
@@ -347,8 +340,8 @@ public:
virtual Status DisconnectRemote();
//------------------------------------------------------------------
- /// Get the platform's supported architectures in the order in which
- /// they should be searched.
+ /// Get the platform's supported architectures in the order in which they
+ /// should be searched.
///
/// @param[in] idx
/// A zero based architecture index
@@ -368,14 +361,14 @@ public:
BreakpointSite *bp_site);
//------------------------------------------------------------------
- /// Launch a new process on a platform, not necessarily for
- /// debugging, it could be just for running the process.
+ /// Launch a new process on a platform, not necessarily for debugging, it
+ /// could be just for running the process.
//------------------------------------------------------------------
virtual Status LaunchProcess(ProcessLaunchInfo &launch_info);
//------------------------------------------------------------------
- /// Perform expansion of the command-line for this launch info
- /// This can potentially involve wildcard expansion
+ /// Perform expansion of the command-line for this launch info This can
+ /// potentially involve wildcard expansion
// environment variable replacement, and whatever other
// argument magic the platform defines as part of its typical
// user experience
@@ -388,28 +381,27 @@ public:
virtual Status KillProcess(const lldb::pid_t pid);
//------------------------------------------------------------------
- /// Lets a platform answer if it is compatible with a given
- /// architecture and the target triple contained within.
+ /// Lets a platform answer if it is compatible with a given architecture and
+ /// the target triple contained within.
//------------------------------------------------------------------
virtual bool IsCompatibleArchitecture(const ArchSpec &arch,
bool exact_arch_match,
ArchSpec *compatible_arch_ptr);
//------------------------------------------------------------------
- /// Not all platforms will support debugging a process by spawning
- /// somehow halted for a debugger (specified using the
- /// "eLaunchFlagDebug" launch flag) and then attaching. If your
- /// platform doesn't support this, override this function and return
- /// false.
+ /// Not all platforms will support debugging a process by spawning somehow
+ /// halted for a debugger (specified using the "eLaunchFlagDebug" launch
+ /// flag) and then attaching. If your platform doesn't support this,
+ /// override this function and return false.
//------------------------------------------------------------------
virtual bool CanDebugProcess() { return true; }
//------------------------------------------------------------------
- /// Subclasses do not need to implement this function as it uses
- /// the Platform::LaunchProcess() followed by Platform::Attach ().
- /// Remote platforms will want to subclass this function in order
- /// to be able to intercept STDIO and possibly launch a separate
- /// process that will debug the debuggee.
+ /// Subclasses do not need to implement this function as it uses the
+ /// Platform::LaunchProcess() followed by Platform::Attach (). Remote
+ /// platforms will want to subclass this function in order to be able to
+ /// intercept STDIO and possibly launch a separate process that will debug
+ /// the debuggee.
//------------------------------------------------------------------
virtual lldb::ProcessSP
DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
@@ -426,11 +418,11 @@ public:
//------------------------------------------------------------------
/// Attach to an existing process using a process ID.
///
- /// Each platform subclass needs to implement this function and
- /// attempt to attach to the process with the process ID of \a pid.
- /// The platform subclass should return an appropriate ProcessSP
- /// subclass that is attached to the process, or an empty shared
- /// pointer with an appropriate error.
+ /// Each platform subclass needs to implement this function and attempt to
+ /// attach to the process with the process ID of \a pid. The platform
+ /// subclass should return an appropriate ProcessSP subclass that is
+ /// attached to the process, or an empty shared pointer with an appropriate
+ /// error.
///
/// @param[in] pid
/// The process ID that we should attempt to attach to.
@@ -451,12 +443,11 @@ public:
//------------------------------------------------------------------
/// Attach to an existing process by process name.
///
- /// This function is not meant to be overridden by Process
- /// subclasses. It will first call
- /// Process::WillAttach (const char *) and if that returns \b
- /// true, Process::DoAttach (const char *) will be called to
- /// actually do the attach. If DoAttach returns \b true, then
- /// Process::DidAttach() will be called.
+ /// This function is not meant to be overridden by Process subclasses. It
+ /// will first call Process::WillAttach (const char *) and if that returns
+ /// \b true, Process::DoAttach (const char *) will be called to actually do
+ /// the attach. If DoAttach returns \b true, then Process::DidAttach() will
+ /// be called.
///
/// @param[in] process_name
/// A process name to match against the current process list.
@@ -471,8 +462,8 @@ public:
// Status &error) = 0;
//------------------------------------------------------------------
- // The base class Platform will take care of the host platform.
- // Subclasses will need to fill in the remote case.
+ // The base class Platform will take care of the host platform. Subclasses
+ // will need to fill in the remote case.
//------------------------------------------------------------------
virtual uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &proc_infos);
@@ -480,15 +471,15 @@ public:
virtual bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info);
//------------------------------------------------------------------
- // Set a breakpoint on all functions that can end up creating a thread
- // for this platform. This is needed when running expressions and
- // also for process control.
+ // Set a breakpoint on all functions that can end up creating a thread for
+ // this platform. This is needed when running expressions and also for
+ // process control.
//------------------------------------------------------------------
virtual lldb::BreakpointSP SetThreadCreationBreakpoint(Target &target);
//------------------------------------------------------------------
- // Given a target, find the local SDK directory if one exists on the
- // current host.
+ // Given a target, find the local SDK directory if one exists on the current
+ // host.
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetSDKDirectory(lldb_private::Target &target) {
@@ -517,9 +508,9 @@ public:
}
//---------------------------------------------------------------------------
- /// If the triple contains not specify the vendor, os, and environment parts,
- /// we "augment" these using information from the platform and return the
- /// resulting ArchSpec object.
+ /// If the triple contains not specify the vendor, os, and environment
+ /// parts, we "augment" these using information from the platform and return
+ /// the resulting ArchSpec object.
//---------------------------------------------------------------------------
ArchSpec GetAugmentedArchSpec(llvm::StringRef triple);
@@ -537,8 +528,8 @@ public:
void SetSDKBuild(const ConstString &sdk_build) { m_sdk_build = sdk_build; }
- // Override this to return true if your platform supports Clang modules.
- // You may also need to override AddClangModuleCompilationOptions to pass the
+ // Override this to return true if your platform supports Clang modules. You
+ // may also need to override AddClangModuleCompilationOptions to pass the
// right Clang flags for your platform.
virtual bool SupportsModules() { return false; }
@@ -553,9 +544,8 @@ public:
bool SetWorkingDirectory(const FileSpec &working_dir);
// There may be modules that we don't want to find by default for operations
- // like "setting breakpoint by name".
- // The platform will return "true" from this call if the passed in module
- // happens to be one of these.
+ // like "setting breakpoint by name". The platform will return "true" from
+ // this call if the passed in module happens to be one of these.
virtual bool
ModuleIsExcludedForUnconstrainedSearches(Target &target,
@@ -610,11 +600,11 @@ public:
//----------------------------------------------------------------------
/// Install a file or directory to the remote system.
///
- /// Install is similar to Platform::PutFile(), but it differs in that if
- /// an application/framework/shared library is installed on a remote
- /// platform and the remote platform requires something to be done to
- /// register the application/framework/shared library, then this extra
- /// registration can be done.
+ /// Install is similar to Platform::PutFile(), but it differs in that if an
+ /// application/framework/shared library is installed on a remote platform
+ /// and the remote platform requires something to be done to register the
+ /// application/framework/shared library, then this extra registration can
+ /// be done.
///
/// @param[in] src
/// The source file/directory to install on the remote system.
@@ -633,7 +623,7 @@ public:
//----------------------------------------------------------------------
virtual Status Install(const FileSpec &src, const FileSpec &dst);
- virtual size_t GetEnvironment(StringList &environment);
+ virtual Environment GetEnvironment();
virtual bool GetFileExists(const lldb_private::FileSpec &file_spec);
@@ -687,8 +677,7 @@ public:
// the process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec); // Timeout in seconds to wait for shell program to
- // finish
+ const Timeout<std::micro> &timeout);
virtual void SetLocalCacheDirectory(const char *local);
@@ -710,12 +699,12 @@ public:
//------------------------------------------------------------------
/// Locate a queue name given a thread's qaddr
///
- /// On a system using libdispatch ("Grand Central Dispatch") style
- /// queues, a thread may be associated with a GCD queue or not,
- /// and a queue may be associated with multiple threads.
- /// The process/thread must provide a way to find the "dispatch_qaddr"
- /// for each thread, and from that dispatch_qaddr this Platform method
- /// will locate the queue name and provide that.
+ /// On a system using libdispatch ("Grand Central Dispatch") style queues, a
+ /// thread may be associated with a GCD queue or not, and a queue may be
+ /// associated with multiple threads. The process/thread must provide a way
+ /// to find the "dispatch_qaddr" for each thread, and from that
+ /// dispatch_qaddr this Platform method will locate the queue name and
+ /// provide that.
///
/// @param[in] process
/// A process is required for reading memory.
@@ -736,12 +725,12 @@ public:
//------------------------------------------------------------------
/// Locate a queue ID given a thread's qaddr
///
- /// On a system using libdispatch ("Grand Central Dispatch") style
- /// queues, a thread may be associated with a GCD queue or not,
- /// and a queue may be associated with multiple threads.
- /// The process/thread must provide a way to find the "dispatch_qaddr"
- /// for each thread, and from that dispatch_qaddr this Platform method
- /// will locate the queue ID and provide that.
+ /// On a system using libdispatch ("Grand Central Dispatch") style queues, a
+ /// thread may be associated with a GCD queue or not, and a queue may be
+ /// associated with multiple threads. The process/thread must provide a way
+ /// to find the "dispatch_qaddr" for each thread, and from that
+ /// dispatch_qaddr this Platform method will locate the queue ID and provide
+ /// that.
///
/// @param[in] process
/// A process is required for reading memory.
@@ -761,12 +750,12 @@ public:
//------------------------------------------------------------------
/// Provide a list of trap handler function names for this platform
///
- /// The unwinder needs to treat trap handlers specially -- the stack
- /// frame may not be aligned correctly for a trap handler (the kernel
- /// often won't perturb the stack pointer, or won't re-align it properly,
- /// in the process of calling the handler) and the frame above the handler
- /// needs to be treated by the unwinder's "frame 0" rules instead of its
- /// "middle of the stack frame" rules.
+ /// The unwinder needs to treat trap handlers specially -- the stack frame
+ /// may not be aligned correctly for a trap handler (the kernel often won't
+ /// perturb the stack pointer, or won't re-align it properly, in the process
+ /// of calling the handler) and the frame above the handler needs to be
+ /// treated by the unwinder's "frame 0" rules instead of its "middle of the
+ /// stack frame" rules.
///
/// In a user process debugging scenario, the list of trap handlers is
/// typically just "_sigtramp".
@@ -782,12 +771,11 @@ public:
virtual const std::vector<ConstString> &GetTrapHandlerSymbolNames();
//------------------------------------------------------------------
- /// Find a support executable that may not live within in the
- /// standard locations related to LLDB.
+ /// Find a support executable that may not live within in the standard
+ /// locations related to LLDB.
///
- /// Executable might exist within the Platform SDK directories, or
- /// in standard tool directories within the current IDE that is
- /// running LLDB.
+ /// Executable might exist within the Platform SDK directories, or in
+ /// standard tool directories within the current IDE that is running LLDB.
///
/// @param[in] basename
/// The basename of the executable to locate in the current
@@ -801,19 +789,17 @@ public:
//------------------------------------------------------------------
/// Allow the platform to set preferred memory cache line size. If non-zero
- /// (and the user
- /// has not set cache line size explicitly), this value will be used as the
- /// cache line
- /// size for memory reads.
+ /// (and the user has not set cache line size explicitly), this value will
+ /// be used as the cache line size for memory reads.
//------------------------------------------------------------------
virtual uint32_t GetDefaultMemoryCacheLineSize() { return 0; }
//------------------------------------------------------------------
/// Load a shared library into this process.
///
- /// Try and load a shared library into the current process. This
- /// call might fail in the dynamic loader plug-in says it isn't safe
- /// to try and load shared libraries at the moment.
+ /// Try and load a shared library into the current process. This call might
+ /// fail in the dynamic loader plug-in says it isn't safe to try and load
+ /// shared libraries at the moment.
///
/// @param[in] process
/// The process to load the image.
@@ -846,9 +832,49 @@ public:
const lldb_private::FileSpec &remote_file,
lldb_private::Status &error);
+ //------------------------------------------------------------------
+ /// Load a shared library specified by base name into this process,
+ /// looking by hand along a set of paths.
+ ///
+ /// @param[in] process
+ /// The process to load the image.
+ ///
+ /// @param[in] library_name
+ /// The name of the library to look for. If library_name is an
+ /// absolute path, the basename will be extracted and searched for
+ /// along the paths. This emulates the behavior of the loader when
+ /// given an install name and a set (e.g. DYLD_LIBRARY_PATH provided) of
+ /// alternate paths.
+ ///
+ /// @param[in] path_list
+ /// The list of paths to use to search for the library. First
+ /// match wins.
+ ///
+ /// @param[out] error
+ /// An error object that gets filled in with any errors that
+ /// might occur when trying to load the shared library.
+ ///
+ /// @param[out] loaded_path
+ /// If non-null, the path to the dylib that was successfully loaded
+ /// is stored in this path.
+ ///
+ /// @return
+ /// A token that represents the shared library which can be
+ /// passed to UnloadImage. A value of
+ /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
+ /// library can't be opened.
+ //------------------------------------------------------------------
+ uint32_t LoadImageUsingPaths(lldb_private::Process *process,
+ const lldb_private::FileSpec &library_name,
+ const std::vector<std::string> &paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_path);
+
virtual uint32_t DoLoadImage(lldb_private::Process *process,
const lldb_private::FileSpec &remote_file,
- lldb_private::Status &error);
+ const std::vector<std::string> *paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_path = nullptr);
virtual Status UnloadImage(lldb_private::Process *process,
uint32_t image_token);
@@ -856,8 +882,8 @@ public:
//------------------------------------------------------------------
/// Connect to all processes waiting for a debugger to attach
///
- /// If the platform have a list of processes waiting for a debugger
- /// to connect to them then connect to all of these pending processes.
+ /// If the platform have a list of processes waiting for a debugger to
+ /// connect to them then connect to all of these pending processes.
///
/// @param[in] debugger
/// The debugger used for the connect.
@@ -874,11 +900,11 @@ public:
protected:
bool m_is_host;
- // Set to true when we are able to actually set the OS version while
- // being connected. For remote platforms, we might set the version ahead
- // of time before we actually connect and this version might change when
- // we actually connect to a remote platform. For the host platform this
- // will be set to the once we call HostInfo::GetOSVersion().
+ // Set to true when we are able to actually set the OS version while being
+ // connected. For remote platforms, we might set the version ahead of time
+ // before we actually connect and this version might change when we actually
+ // connect to a remote platform. For the host platform this will be set to
+ // the once we call HostInfo::GetOSVersion().
bool m_os_version_set_while_connected;
bool m_system_arch_set_while_connected;
ConstString
@@ -888,9 +914,7 @@ protected:
// modules that have no install path set
std::string m_remote_url;
std::string m_name;
- uint32_t m_major_os_version;
- uint32_t m_minor_os_version;
- uint32_t m_update_os_version;
+ llvm::VersionTuple m_os_version;
ArchSpec
m_system_arch; // The architecture of the kernel or the remote platform
typedef std::map<uint32_t, ConstString> IDToNameMap;
@@ -915,23 +939,22 @@ protected:
//------------------------------------------------------------------
/// Ask the Platform subclass to fill in the list of trap handler names
///
- /// For most Unix user process environments, this will be a single
- /// function name, _sigtramp. More specialized environments may have
- /// additional handler names. The unwinder code needs to know when a
- /// trap handler is on the stack because the unwind rules for the frame
- /// that caused the trap are different.
+ /// For most Unix user process environments, this will be a single function
+ /// name, _sigtramp. More specialized environments may have additional
+ /// handler names. The unwinder code needs to know when a trap handler is
+ /// on the stack because the unwind rules for the frame that caused the trap
+ /// are different.
///
- /// The base class Platform ivar m_trap_handlers should be updated by
- /// the Platform subclass when this method is called. If there are no
+ /// The base class Platform ivar m_trap_handlers should be updated by the
+ /// Platform subclass when this method is called. If there are no
/// predefined trap handlers, this method may be a no-op.
//------------------------------------------------------------------
virtual void CalculateTrapHandlerSymbolNames() = 0;
const char *GetCachedUserName(uint32_t uid) {
std::lock_guard<std::mutex> guard(m_mutex);
- // return the empty string if our string is NULL
- // so we can tell when things were in the negative
- // cached (didn't find a valid user name, don't keep
+ // return the empty string if our string is NULL so we can tell when things
+ // were in the negative cached (didn't find a valid user name, don't keep
// trying)
const auto pos = m_uid_map.find(uid);
return ((pos != m_uid_map.end()) ? pos->second.AsCString("") : nullptr);
@@ -961,9 +984,8 @@ protected:
const char *GetCachedGroupName(uint32_t gid) {
std::lock_guard<std::mutex> guard(m_mutex);
- // return the empty string if our string is NULL
- // so we can tell when things were in the negative
- // cached (didn't find a valid group name, don't keep
+ // return the empty string if our string is NULL so we can tell when things
+ // were in the negative cached (didn't find a valid group name, don't keep
// trying)
const auto pos = m_gid_map.find(gid);
return ((pos != m_gid_map.end()) ? pos->second.AsCString("") : nullptr);
@@ -1057,11 +1079,10 @@ public:
//------------------------------------------------------------------
/// Select the active platform.
///
- /// In order to debug remotely, other platform's can be remotely
- /// connected to and set as the selected platform for any subsequent
- /// debugging. This allows connection to remote targets and allows
- /// the ability to discover process info, launch and attach to remote
- /// processes.
+ /// In order to debug remotely, other platform's can be remotely connected
+ /// to and set as the selected platform for any subsequent debugging. This
+ /// allows connection to remote targets and allows the ability to discover
+ /// process info, launch and attach to remote processes.
//------------------------------------------------------------------
lldb::PlatformSP GetSelectedPlatform() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Process.h b/contrib/llvm/tools/lldb/include/lldb/Target/Process.h
index 16f37f4dd5dc..66ac5a692522 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Process.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Process.h
@@ -38,6 +38,7 @@
#include "lldb/Host/HostThread.h"
#include "lldb/Host/ProcessRunLock.h"
#include "lldb/Interpreter/Options.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Target/Memory.h"
@@ -53,6 +54,7 @@
#include "lldb/lldb-private.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/VersionTuple.h"
namespace lldb_private {
@@ -113,8 +115,8 @@ typedef std::shared_ptr<ProcessProperties> ProcessPropertiesSP;
//----------------------------------------------------------------------
// ProcessInstanceInfo
//
-// Describes an existing process and any discoverable information that
-// pertains to that process.
+// Describes an existing process and any discoverable information that pertains
+// to that process.
//----------------------------------------------------------------------
class ProcessInstanceInfo : public ProcessInfo {
public:
@@ -278,7 +280,8 @@ protected:
class ProcessLaunchCommandOptions : public Options {
public:
ProcessLaunchCommandOptions() : Options() {
- // Keep default values of all options in one place: OptionParsingStarting ()
+ // Keep default values of all options in one place: OptionParsingStarting
+ // ()
OptionParsingStarting(nullptr);
}
@@ -316,7 +319,8 @@ public:
NameMatch process_name_match_type)
: m_match_info(), m_name_match_type(process_name_match_type),
m_match_all_users(false) {
- m_match_info.GetExecutableFile().SetFile(process_name, false);
+ m_match_info.GetExecutableFile().SetFile(process_name, false,
+ FileSpec::Style::native);
}
ProcessInstanceInfo &GetProcessInfo() { return m_match_info; }
@@ -388,10 +392,8 @@ protected:
};
// This class tracks the Modification state of the process. Things that can
-// currently modify
-// the program are running the program (which will up the StopID) and writing
-// memory (which
-// will up the MemoryID.)
+// currently modify the program are running the program (which will up the
+// StopID) and writing memory (which will up the MemoryID.)
// FIXME: Should we also include modification of register states?
class ProcessModID {
@@ -498,7 +500,7 @@ inline bool operator!=(const ProcessModID &lhs, const ProcessModID &rhs) {
//----------------------------------------------------------------------
/// @class Process Process.h "lldb/Target/Process.h"
-/// @brief A plug-in interface definition class for debugging a process.
+/// A plug-in interface definition class for debugging a process.
//----------------------------------------------------------------------
class Process : public std::enable_shared_from_this<Process>,
public ProcessProperties,
@@ -539,12 +541,11 @@ public:
enum Warnings { eWarningsOptimization = 1 };
typedef Range<lldb::addr_t, lldb::addr_t> LoadRange;
- // We use a read/write lock to allow on or more clients to
- // access the process state while the process is stopped (reader).
- // We lock the write lock to control access to the process
- // while it is running (readers, or clients that want the process
- // stopped can block waiting for the process to stop, or just
- // try to lock it to see if they can immediately access the stopped
+ // We use a read/write lock to allow on or more clients to access the process
+ // state while the process is stopped (reader). We lock the write lock to
+ // control access to the process while it is running (readers, or clients
+ // that want the process stopped can block waiting for the process to stop,
+ // or just try to lock it to see if they can immediately access the stopped
// process. If the try read lock fails, then the process is running.
typedef ProcessRunLock::ProcessRunLocker StopLocker;
@@ -560,8 +561,8 @@ public:
/// A notification structure that can be used by clients to listen
/// for changes in a process's lifetime.
///
-/// @see RegisterNotificationCallbacks (const Notifications&)
-/// @see UnregisterNotificationCallbacks (const Notifications&)
+/// @see RegisterNotificationCallbacks (const Notifications&) @see
+/// UnregisterNotificationCallbacks (const Notifications&)
//------------------------------------------------------------------
#ifndef SWIG
typedef struct {
@@ -657,8 +658,8 @@ public:
Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
//------------------------------------------------------------------
- /// Construct with a shared pointer to a target, the Process listener,
- /// and the appropriate UnixSignalsSP for the process.
+ /// Construct with a shared pointer to a target, the Process listener, and
+ /// the appropriate UnixSignalsSP for the process.
//------------------------------------------------------------------
Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
const lldb::UnixSignalsSP &unix_signals_sp);
@@ -666,8 +667,8 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is virtual since this class is designed to be
- /// inherited from by the plug-in instance.
+ /// The destructor is virtual since this class is designed to be inherited
+ /// from by the plug-in instance.
//------------------------------------------------------------------
~Process() override;
@@ -678,12 +679,12 @@ public:
static const ProcessPropertiesSP &GetGlobalProperties();
//------------------------------------------------------------------
- /// Find a Process plug-in that can debug \a module using the
- /// currently selected architecture.
+ /// Find a Process plug-in that can debug \a module using the currently
+ /// selected architecture.
///
- /// Scans all loaded plug-in interfaces that implement versions of
- /// the Process plug-in interface and returns the first instance
- /// that can debug the file.
+ /// Scans all loaded plug-in interfaces that implement versions of the
+ /// Process plug-in interface and returns the first instance that can debug
+ /// the file.
///
/// @param[in] module_sp
/// The module shared pointer that this process will debug.
@@ -704,11 +705,10 @@ public:
/// Static function that can be used with the \b host function
/// Host::StartMonitoringChildProcess ().
///
- /// This function can be used by lldb_private::Process subclasses
- /// when they want to watch for a local process and have its exit
- /// status automatically set when the host child process exits.
- /// Subclasses should call Host::StartMonitoringChildProcess ()
- /// with:
+ /// This function can be used by lldb_private::Process subclasses when they
+ /// want to watch for a local process and have its exit status automatically
+ /// set when the host child process exits. Subclasses should call
+ /// Host::StartMonitoringChildProcess () with:
/// callback = Process::SetHostProcessExitStatus
/// pid = Process::GetID()
/// monitor_signals = false
@@ -728,9 +728,9 @@ public:
//------------------------------------------------------------------
/// Check if a plug-in instance can debug the file in \a module.
///
- /// Each plug-in is given a chance to say whether it can debug
- /// the file in \a module. If the Process plug-in instance can
- /// debug a file on the current system, it should return \b true.
+ /// Each plug-in is given a chance to say whether it can debug the file in
+ /// \a module. If the Process plug-in instance can debug a file on the
+ /// current system, it should return \b true.
///
/// @return
/// Returns \b true if this Process plug-in instance can
@@ -742,8 +742,8 @@ public:
//------------------------------------------------------------------
/// This object is about to be destroyed, do any necessary cleanup.
///
- /// Subclasses that override this method should always call this
- /// superclass method.
+ /// Subclasses that override this method should always call this superclass
+ /// method.
//------------------------------------------------------------------
virtual void Finalize();
@@ -757,13 +757,13 @@ public:
bool IsValid() const { return !m_finalize_called; }
//------------------------------------------------------------------
- /// Return a multi-word command object that can be used to expose
- /// plug-in specific commands.
+ /// Return a multi-word command object that can be used to expose plug-in
+ /// specific commands.
///
/// This object will be used to resolve plug-in commands and can be
/// triggered by a call to:
///
- /// (lldb) process commmand <args>
+ /// (lldb) process command <args>
///
/// @return
/// A CommandObject which can be one of the concrete subclasses
@@ -775,16 +775,15 @@ public:
//------------------------------------------------------------------
/// Launch a new process.
///
- /// Launch a new process by spawning a new process using the
- /// target object's executable module's file as the file to launch.
+ /// Launch a new process by spawning a new process using the target object's
+ /// executable module's file as the file to launch.
///
- /// This function is not meant to be overridden by Process
- /// subclasses. It will first call Process::WillLaunch (Module *)
- /// and if that returns \b true, Process::DoLaunch (Module*,
- /// char const *[],char const *[],const char *,const char *,
- /// const char *) will be called to actually do the launching. If
- /// DoLaunch returns \b true, then Process::DidLaunch() will be
- /// called.
+ /// This function is not meant to be overridden by Process subclasses. It
+ /// will first call Process::WillLaunch (Module *) and if that returns \b
+ /// true, Process::DoLaunch (Module*, char const *[],char const *[],const
+ /// char *,const char *, const char *) will be called to actually do the
+ /// launching. If DoLaunch returns \b true, then Process::DidLaunch() will
+ /// be called.
///
/// @param[in] launch_info
/// Details regarding the environment, STDIN/STDOUT/STDERR
@@ -807,13 +806,48 @@ public:
}
//------------------------------------------------------------------
+ // FUTURE WORK: GetLoadImageUtilityFunction are the first use we've
+ // had of having other plugins cache data in the Process. This is handy for
+ // long-living plugins - like the Platform - which manage interactions whose
+ // lifetime is governed by the Process lifetime. If we find we need to do
+ // this more often, we should construct a general solution to the problem.
+ // The consensus suggestion was that we have a token based registry in the
+ // Process. Some undecided questions are (1) who manages the tokens. It's
+ // probably best that you add the element and get back a token that
+ // represents it. That will avoid collisions. But there may be some utility
+ // in the registerer controlling the token? (2) whether the thing added
+ // should be simply owned by Process, and just go away when it does (3)
+ // whether the registree should be notified of the Process' demise.
+ //
+ // We are postponing designing this till we have at least a second use case.
+ //------------------------------------------------------------------
+ //------------------------------------------------------------------
+ /// Get the cached UtilityFunction that assists in loading binary images
+ /// into the process.
+ ///
+ /// @param[in] platform
+ /// The platform fetching the UtilityFunction.
+ /// @param[in] factory
+ /// A function that will be called only once per-process in a
+ /// thread-safe way to create the UtilityFunction if it has not
+ /// been initialized yet.
+ ///
+ /// @return
+ /// The cached utility function or null if the platform is not the
+ /// same as the target's platform.
+ //------------------------------------------------------------------
+ UtilityFunction *GetLoadImageUtilityFunction(
+ Platform *platform,
+ llvm::function_ref<std::unique_ptr<UtilityFunction>()> factory);
+
+ //------------------------------------------------------------------
/// Get the dynamic loader plug-in for this process.
///
- /// The default action is to let the DynamicLoader plug-ins check
- /// the main executable and the DynamicLoader will select itself
- /// automatically. Subclasses can override this if inspecting the
- /// executable is not desired, or if Process subclasses can only
- /// use a specific DynamicLoader plug-in.
+ /// The default action is to let the DynamicLoader plug-ins check the main
+ /// executable and the DynamicLoader will select itself automatically.
+ /// Subclasses can override this if inspecting the executable is not
+ /// desired, or if Process subclasses can only use a specific DynamicLoader
+ /// plug-in.
//------------------------------------------------------------------
virtual DynamicLoader *GetDynamicLoader();
@@ -828,11 +862,11 @@ public:
virtual const lldb::DataBufferSP GetAuxvData();
//------------------------------------------------------------------
- /// Sometimes processes know how to retrieve and load shared libraries.
- /// This is normally done by DynamicLoader plug-ins, but sometimes the
- /// connection to the process allows retrieving this information. The
- /// dynamic loader plug-ins can use this function if they can't
- /// determine the current shared library load state.
+ /// Sometimes processes know how to retrieve and load shared libraries. This
+ /// is normally done by DynamicLoader plug-ins, but sometimes the connection
+ /// to the process allows retrieving this information. The dynamic loader
+ /// plug-ins can use this function if they can't determine the current
+ /// shared library load state.
///
/// @return
/// The number of shared libraries that were loaded
@@ -857,11 +891,10 @@ public:
//------------------------------------------------------------------
/// Attach to an existing process using the process attach info.
///
- /// This function is not meant to be overridden by Process
- /// subclasses. It will first call WillAttach (lldb::pid_t)
- /// or WillAttach (const char *), and if that returns \b
- /// true, DoAttach (lldb::pid_t) or DoAttach (const char *) will
- /// be called to actually do the attach. If DoAttach returns \b
+ /// This function is not meant to be overridden by Process subclasses. It
+ /// will first call WillAttach (lldb::pid_t) or WillAttach (const char *),
+ /// and if that returns \b true, DoAttach (lldb::pid_t) or DoAttach (const
+ /// char *) will be called to actually do the attach. If DoAttach returns \b
/// true, then Process::DidAttach() will be called.
///
/// @param[in] pid
@@ -896,12 +929,11 @@ public:
//------------------------------------------------------------------
/// Get the image information address for the current process.
///
- /// Some runtimes have system functions that can help dynamic
- /// loaders locate the dynamic loader information needed to observe
- /// shared libraries being loaded or unloaded. This function is
- /// in the Process interface (as opposed to the DynamicLoader
- /// interface) to ensure that remote debugging can take advantage of
- /// this functionality.
+ /// Some runtimes have system functions that can help dynamic loaders locate
+ /// the dynamic loader information needed to observe shared libraries being
+ /// loaded or unloaded. This function is in the Process interface (as
+ /// opposed to the DynamicLoader interface) to ensure that remote debugging
+ /// can take advantage of this functionality.
///
/// @return
/// The address of the dynamic loader information, or
@@ -913,17 +945,16 @@ public:
//------------------------------------------------------------------
/// Called when the process is about to broadcast a public stop.
///
- /// There are public and private stops. Private stops are when the
- /// process is doing things like stepping and the client doesn't
- /// need to know about starts and stop that implement a thread plan.
- /// Single stepping over a source line in code might end up being
- /// implemented by one or more process starts and stops. Public stops
- /// are when clients will be notified that the process is stopped.
- /// These events typically trigger UI updates (thread stack frames to
- /// be displayed, variables to be displayed, and more). This function
- /// can be overriden and allows process subclasses to do something
- /// before the eBroadcastBitStateChanged event is sent to public
- /// clients.
+ /// There are public and private stops. Private stops are when the process
+ /// is doing things like stepping and the client doesn't need to know about
+ /// starts and stop that implement a thread plan. Single stepping over a
+ /// source line in code might end up being implemented by one or more
+ /// process starts and stops. Public stops are when clients will be notified
+ /// that the process is stopped. These events typically trigger UI updates
+ /// (thread stack frames to be displayed, variables to be displayed, and
+ /// more). This function can be overriden and allows process subclasses to
+ /// do something before the eBroadcastBitStateChanged event is sent to
+ /// public clients.
//------------------------------------------------------------------
virtual void WillPublicStop() {}
@@ -946,8 +977,8 @@ public:
//------------------------------------------------------------------
/// Unregister for process and thread notifications.
///
-/// Clients can unregister notification callbacks by passing a copy of
-/// the original baton and callbacks in \a callbacks.
+/// Clients can unregister notification callbacks by passing a copy of the
+/// original baton and callbacks in \a callbacks.
///
/// @param[in] callbacks
/// A structure that contains the notification baton and
@@ -967,25 +998,24 @@ public:
// Built in Process Control functions
//==================================================================
//------------------------------------------------------------------
- /// Resumes all of a process's threads as configured using the
- /// Thread run control functions.
+ /// Resumes all of a process's threads as configured using the Thread run
+ /// control functions.
///
- /// Threads for a process should be updated with one of the run
- /// control actions (resume, step, or suspend) that they should take
- /// when the process is resumed. If no run control action is given
- /// to a thread it will be resumed by default.
+ /// Threads for a process should be updated with one of the run control
+ /// actions (resume, step, or suspend) that they should take when the
+ /// process is resumed. If no run control action is given to a thread it
+ /// will be resumed by default.
///
- /// This function is not meant to be overridden by Process
- /// subclasses. This function will take care of disabling any
- /// breakpoints that threads may be stopped at, single stepping, and
- /// re-enabling breakpoints, and enabling the basic flow control
- /// that the plug-in instances need not worry about.
+ /// This function is not meant to be overridden by Process subclasses. This
+ /// function will take care of disabling any breakpoints that threads may be
+ /// stopped at, single stepping, and re-enabling breakpoints, and enabling
+ /// the basic flow control that the plug-in instances need not worry about.
///
- /// N.B. This function also sets the Write side of the Run Lock,
- /// which is unset when the corresponding stop event is pulled off
- /// the Public Event Queue. If you need to resume the process without
- /// setting the Run Lock, use PrivateResume (though you should only do
- /// that from inside the Process class.
+ /// N.B. This function also sets the Write side of the Run Lock, which is
+ /// unset when the corresponding stop event is pulled off the Public Event
+ /// Queue. If you need to resume the process without setting the Run Lock,
+ /// use PrivateResume (though you should only do that from inside the
+ /// Process class.
///
/// @return
/// Returns an error object.
@@ -1001,11 +1031,10 @@ public:
//------------------------------------------------------------------
/// Halts a running process.
///
- /// This function is not meant to be overridden by Process
- /// subclasses.
- /// If the process is successfully halted, a eStateStopped
- /// process event with GetInterrupted will be broadcast. If false, we will
- /// halt the process with no events generated by the halt.
+ /// This function is not meant to be overridden by Process subclasses. If
+ /// the process is successfully halted, a eStateStopped process event with
+ /// GetInterrupted will be broadcast. If false, we will halt the process
+ /// with no events generated by the halt.
///
/// @param[in] clear_thread_plans
/// If true, when the process stops, clear all thread plans.
@@ -1023,8 +1052,7 @@ public:
//------------------------------------------------------------------
/// Detaches from a running or stopped process.
///
- /// This function is not meant to be overridden by Process
- /// subclasses.
+ /// This function is not meant to be overridden by Process subclasses.
///
/// @param[in] keep_stopped
/// If true, don't resume the process on detach.
@@ -1035,11 +1063,10 @@ public:
Status Detach(bool keep_stopped);
//------------------------------------------------------------------
- /// Kills the process and shuts down all threads that were spawned
- /// to track and monitor the process.
+ /// Kills the process and shuts down all threads that were spawned to track
+ /// and monitor the process.
///
- /// This function is not meant to be overridden by Process
- /// subclasses.
+ /// This function is not meant to be overridden by Process subclasses.
///
/// @param[in] force_kill
/// Whether lldb should force a kill (instead of a detach) from
@@ -1057,8 +1084,7 @@ public:
//------------------------------------------------------------------
/// Sends a process a UNIX signal \a signal.
///
- /// This function is not meant to be overridden by Process
- /// subclasses.
+ /// This function is not meant to be overridden by Process subclasses.
///
/// @return
/// Returns an error object.
@@ -1076,8 +1102,7 @@ public:
//------------------------------------------------------------------
/// Called before attaching to a process.
///
- /// Allow Process plug-ins to execute some code before attaching a
- /// process.
+ /// Allow Process plug-ins to execute some code before attaching a process.
///
/// @return
/// Returns an error object.
@@ -1087,8 +1112,7 @@ public:
//------------------------------------------------------------------
/// Called before attaching to a process.
///
- /// Allow Process plug-ins to execute some code before attaching a
- /// process.
+ /// Allow Process plug-ins to execute some code before attaching a process.
///
/// @return
/// Returns an error object.
@@ -1173,33 +1197,31 @@ public:
/// If you can figure out the process architecture after attach, fill it
/// in here.
///
- /// Allow Process plug-ins to execute some code after attaching to
- /// a process.
+ /// Allow Process plug-ins to execute some code after attaching to a
+ /// process.
//------------------------------------------------------------------
virtual void DidAttach(ArchSpec &process_arch) { process_arch.Clear(); }
//------------------------------------------------------------------
/// Called after a process re-execs itself.
///
- /// Allow Process plug-ins to execute some code after a process has
- /// exec'ed itself. Subclasses typically should override DoDidExec()
- /// as the lldb_private::Process class needs to remove its dynamic
- /// loader, runtime, ABI and other plug-ins, as well as unload all
- /// shared libraries.
+ /// Allow Process plug-ins to execute some code after a process has exec'ed
+ /// itself. Subclasses typically should override DoDidExec() as the
+ /// lldb_private::Process class needs to remove its dynamic loader, runtime,
+ /// ABI and other plug-ins, as well as unload all shared libraries.
//------------------------------------------------------------------
virtual void DidExec();
//------------------------------------------------------------------
- /// Subclasses of Process should implement this function if they
- /// need to do anything after a process exec's itself.
+ /// Subclasses of Process should implement this function if they need to do
+ /// anything after a process exec's itself.
//------------------------------------------------------------------
virtual void DoDidExec() {}
//------------------------------------------------------------------
/// Called before launching to a process.
///
- /// Allow Process plug-ins to execute some code before launching a
- /// process.
+ /// Allow Process plug-ins to execute some code before launching a process.
///
/// @return
/// Returns an error object.
@@ -1209,9 +1231,9 @@ public:
//------------------------------------------------------------------
/// Launch a new process.
///
- /// Launch a new process by spawning a new process using
- /// \a exe_module's file as the file to launch. Launch details are
- /// provided in \a launch_info.
+ /// Launch a new process by spawning a new process using \a exe_module's
+ /// file as the file to launch. Launch details are provided in \a
+ /// launch_info.
///
/// @param[in] exe_module
/// The module from which to extract the file specification and
@@ -1236,16 +1258,14 @@ public:
//------------------------------------------------------------------
/// Called after launching a process.
///
- /// Allow Process plug-ins to execute some code after launching
- /// a process.
+ /// Allow Process plug-ins to execute some code after launching a process.
//------------------------------------------------------------------
virtual void DidLaunch() {}
//------------------------------------------------------------------
/// Called before resuming to a process.
///
- /// Allow Process plug-ins to execute some code before resuming a
- /// process.
+ /// Allow Process plug-ins to execute some code before resuming a process.
///
/// @return
/// Returns an error object.
@@ -1253,13 +1273,13 @@ public:
virtual Status WillResume() { return Status(); }
//------------------------------------------------------------------
- /// Resumes all of a process's threads as configured using the
- /// Thread run control functions.
+ /// Resumes all of a process's threads as configured using the Thread run
+ /// control functions.
///
- /// Threads for a process should be updated with one of the run
- /// control actions (resume, step, or suspend) that they should take
- /// when the process is resumed. If no run control action is given
- /// to a thread it will be resumed by default.
+ /// Threads for a process should be updated with one of the run control
+ /// actions (resume, step, or suspend) that they should take when the
+ /// process is resumed. If no run control action is given to a thread it
+ /// will be resumed by default.
///
/// @return
/// Returns \b true if the process successfully resumes using
@@ -1280,16 +1300,14 @@ public:
//------------------------------------------------------------------
/// Called after resuming a process.
///
- /// Allow Process plug-ins to execute some code after resuming
- /// a process.
+ /// Allow Process plug-ins to execute some code after resuming a process.
//------------------------------------------------------------------
virtual void DidResume() {}
//------------------------------------------------------------------
/// Called before halting to a process.
///
- /// Allow Process plug-ins to execute some code before halting a
- /// process.
+ /// Allow Process plug-ins to execute some code before halting a process.
///
/// @return
/// Returns an error object.
@@ -1300,13 +1318,10 @@ public:
/// Halts a running process.
///
/// DoHalt must produce one and only one stop StateChanged event if it
- /// actually
- /// stops the process. If the stop happens through some natural event (for
- /// instance a SIGSTOP), then forwarding that event will do. Otherwise, you
- /// must
- /// generate the event manually. This function is called from the context of
- /// the
- /// private state thread.
+ /// actually stops the process. If the stop happens through some natural
+ /// event (for instance a SIGSTOP), then forwarding that event will do.
+ /// Otherwise, you must generate the event manually. This function is called
+ /// from the context of the private state thread.
///
/// @param[out] caused_stop
/// If true, then this Halt caused the stop, otherwise, the
@@ -1327,16 +1342,15 @@ public:
//------------------------------------------------------------------
/// Called after halting a process.
///
- /// Allow Process plug-ins to execute some code after halting
- /// a process.
+ /// Allow Process plug-ins to execute some code after halting a process.
//------------------------------------------------------------------
virtual void DidHalt() {}
//------------------------------------------------------------------
/// Called before detaching from a process.
///
- /// Allow Process plug-ins to execute some code before detaching
- /// from a process.
+ /// Allow Process plug-ins to execute some code before detaching from a
+ /// process.
///
/// @return
/// Returns an error object.
@@ -1361,8 +1375,8 @@ public:
//------------------------------------------------------------------
/// Called after detaching from a process.
///
- /// Allow Process plug-ins to execute some code after detaching
- /// from a process.
+ /// Allow Process plug-ins to execute some code after detaching from a
+ /// process.
//------------------------------------------------------------------
virtual void DidDetach() {}
@@ -1371,8 +1385,8 @@ public:
//------------------------------------------------------------------
/// Called before sending a signal to a process.
///
- /// Allow Process plug-ins to execute some code before sending a
- /// signal to a process.
+ /// Allow Process plug-ins to execute some code before sending a signal to a
+ /// process.
///
/// @return
/// Returns no error if it is safe to proceed with a call to
@@ -1406,8 +1420,8 @@ public:
//------------------------------------------------------------------
/// Called after sending a signal to a process.
///
- /// Allow Process plug-ins to execute some code after sending a
- /// signal to a process.
+ /// Allow Process plug-ins to execute some code after sending a signal to a
+ /// process.
//------------------------------------------------------------------
virtual void DidSignal() {}
@@ -1417,45 +1431,28 @@ public:
/// event is taken from the queue...
///
/// This callback is called as the event
- /// is about to be queued up to allow Process plug-ins to execute
- /// some code prior to clients being notified that a process was
- /// stopped. Common operations include updating the thread list,
- /// invalidating any thread state (registers, stack, etc) prior to
- /// letting the notification go out.
+ /// is about to be queued up to allow Process plug-ins to execute some code
+ /// prior to clients being notified that a process was stopped. Common
+ /// operations include updating the thread list, invalidating any thread
+ /// state (registers, stack, etc) prior to letting the notification go out.
///
//------------------------------------------------------------------
virtual void RefreshStateAfterStop() = 0;
//------------------------------------------------------------------
- /// Sometimes the connection to a process can detect the host OS
- /// version that the process is running on. The current platform
- /// should be checked first in case the platform is connected, but
- /// clients can fall back onto this function if the platform fails
- /// to identify the host OS version. The platform should be checked
- /// first in case you are running a simulator platform that might
- /// itself be running natively, but have different heuristics for
- /// figuring out which OS is is emulating.
- ///
- /// @param[out] major
- /// The major OS version, or UINT32_MAX if it can't be determined
- ///
- /// @param[out] minor
- /// The minor OS version, or UINT32_MAX if it can't be determined
- ///
- /// @param[out] update
- /// The update OS version, or UINT32_MAX if it can't be determined
+ /// Sometimes the connection to a process can detect the host OS version
+ /// that the process is running on. The current platform should be checked
+ /// first in case the platform is connected, but clients can fall back onto
+ /// this function if the platform fails to identify the host OS version. The
+ /// platform should be checked first in case you are running a simulator
+ /// platform that might itself be running natively, but have different
+ /// heuristics for figuring out which OS is is emulating.
///
/// @return
- /// Returns \b true if the host OS version info was filled in
- /// and \b false otherwise.
+ /// Returns the version tuple of the host OS. In case of failure an empty
+ /// VersionTuple is returner.
//------------------------------------------------------------------
- virtual bool GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) {
- major = UINT32_MAX;
- minor = UINT32_MAX;
- update = UINT32_MAX;
- return false;
- }
+ virtual llvm::VersionTuple GetHostOSVersion() { return llvm::VersionTuple(); }
//------------------------------------------------------------------
/// Get the target object pointer for this module.
@@ -1464,7 +1461,7 @@ public:
/// A Target object pointer to the target that owns this
/// module.
//------------------------------------------------------------------
- Target &GetTarget() { return *m_target_sp.lock(); }
+ Target &GetTarget() { return *m_target_wp.lock(); }
//------------------------------------------------------------------
/// Get the const target object pointer for this module.
@@ -1473,17 +1470,17 @@ public:
/// A const Target object pointer to the target that owns this
/// module.
//------------------------------------------------------------------
- const Target &GetTarget() const { return *m_target_sp.lock(); }
+ const Target &GetTarget() const { return *m_target_wp.lock(); }
//------------------------------------------------------------------
/// Flush all data in the process.
///
- /// Flush the memory caches, all threads, and any other cached data
- /// in the process.
+ /// Flush the memory caches, all threads, and any other cached data in the
+ /// process.
///
- /// This function can be called after a world changing event like
- /// adding a new symbol file, or after the process makes a large
- /// context switch (from boot ROM to booted into an OS).
+ /// This function can be called after a world changing event like adding a
+ /// new symbol file, or after the process makes a large context switch (from
+ /// boot ROM to booted into an OS).
//------------------------------------------------------------------
void Flush();
@@ -1516,22 +1513,23 @@ public:
//------------------------------------------------------------------
// Notify this process class that modules got loaded.
//
- // If subclasses override this method, they must call this version
- // before doing anything in the subclass version of the function.
+ // If subclasses override this method, they must call this version before
+ // doing anything in the subclass version of the function.
//------------------------------------------------------------------
virtual void ModulesDidLoad(ModuleList &module_list);
//------------------------------------------------------------------
/// Retrieve the list of shared libraries that are loaded for this process
- /// This method is used on pre-macOS 10.12, pre-iOS 10, pre-tvOS 10,
- /// pre-watchOS 3 systems. The following two methods are for newer versions
- /// of those OSes.
+ /// This method is used on pre-macOS 10.12, pre-iOS 10, pre-tvOS 10, pre-
+ /// watchOS 3 systems. The following two methods are for newer versions of
+ /// those OSes.
///
/// For certain platforms, the time it takes for the DynamicLoader plugin to
/// read all of the shared libraries out of memory over a slow communication
/// channel may be too long. In that instance, the gdb-remote stub may be
- /// able to retrieve the necessary information about the solibs out of memory
- /// and return a concise summary sufficient for the DynamicLoader plugin.
+ /// able to retrieve the necessary information about the solibs out of
+ /// memory and return a concise summary sufficient for the DynamicLoader
+ /// plugin.
///
/// @param [in] image_list_address
/// The address where the table of shared libraries is stored in memory,
@@ -1555,16 +1553,14 @@ public:
}
// On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can
- // return
- // the full list of loaded shared libraries without needing any input.
+ // return the full list of loaded shared libraries without needing any input.
virtual lldb_private::StructuredData::ObjectSP
GetLoadedDynamicLibrariesInfos() {
return StructuredData::ObjectSP();
}
// On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can
- // return
- // information about binaries given their load addresses.
+ // return information about binaries given their load addresses.
virtual lldb_private::StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos(
const std::vector<lldb::addr_t> &load_addresses) {
return StructuredData::ObjectSP();
@@ -1574,21 +1570,20 @@ public:
// Get information about the library shared cache, if that exists
//
// On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can
- // return
- // information about the library shared cache (a set of standard libraries
- // that are
- // loaded at the same location for all processes on a system) in use.
+ // return information about the library shared cache (a set of standard
+ // libraries that are loaded at the same location for all processes on a
+ // system) in use.
//------------------------------------------------------------------
virtual lldb_private::StructuredData::ObjectSP GetSharedCacheInfo() {
return StructuredData::ObjectSP();
}
//------------------------------------------------------------------
- /// Print a user-visible warning about a module being built with optimization
+ /// Print a user-visible warning about a module being built with
+ /// optimization
///
- /// Prints a async warning message to the user one time per Module
- /// where a function is found that was compiled with optimization, per
- /// Process.
+ /// Prints a async warning message to the user one time per Module where a
+ /// function is found that was compiled with optimization, per Process.
///
/// @param [in] sc
/// A SymbolContext with eSymbolContextFunction and eSymbolContextModule
@@ -1648,13 +1643,12 @@ public:
//------------------------------------------------------------------
/// Set accessor for the process exit status (return code).
///
- /// Sometimes a child exits and the exit can be detected by global
- /// functions (signal handler for SIGCHLD for example). This
- /// accessor allows the exit status to be set from an external
- /// source.
+ /// Sometimes a child exits and the exit can be detected by global functions
+ /// (signal handler for SIGCHLD for example). This accessor allows the exit
+ /// status to be set from an external source.
///
- /// Setting this will cause a eStateExited event to be posted to
- /// the process event queue.
+ /// Setting this will cause a eStateExited event to be posted to the process
+ /// event queue.
///
/// @param[in] exit_status
/// The value for the process's return code.
@@ -1673,11 +1667,10 @@ public:
virtual bool IsAlive();
//------------------------------------------------------------------
- /// Before lldb detaches from a process, it warns the user that they are about
- /// to lose their debug session.
- /// In some cases, this warning doesn't need to be emitted -- for instance,
- /// with core file debugging where
- /// the user can reconstruct the "state" by simply re-running the debugger on
+ /// Before lldb detaches from a process, it warns the user that they are
+ /// about to lose their debug session. In some cases, this warning doesn't
+ /// need to be emitted -- for instance, with core file debugging where the
+ /// user can reconstruct the "state" by simply re-running the debugger on
/// the core file.
///
/// @return
@@ -1688,10 +1681,9 @@ public:
//------------------------------------------------------------------
/// Actually do the reading of memory from a process.
///
- /// Subclasses must override this function and can return fewer
- /// bytes than requested when memory requests are too large. This
- /// class will break up the memory requests and keep advancing the
- /// arguments along as needed.
+ /// Subclasses must override this function and can return fewer bytes than
+ /// requested when memory requests are too large. This class will break up
+ /// the memory requests and keep advancing the arguments along as needed.
///
/// @param[in] vm_addr
/// A virtual load address that indicates where to start reading
@@ -1704,8 +1696,15 @@ public:
/// A byte buffer that is at least \a size bytes long that
/// will receive the memory bytes.
///
+ /// @param[out] error
+ /// An error that indicates the success or failure of this
+ /// operation. If error indicates success (error.Success()),
+ /// then the value returned can be trusted, otherwise zero
+ /// will be returned.
+ ///
/// @return
/// The number of bytes that were actually read into \a buf.
+ /// Zero is returned in the case of an error.
//------------------------------------------------------------------
virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
Status &error) = 0;
@@ -1713,13 +1712,12 @@ public:
//------------------------------------------------------------------
/// Read of memory from a process.
///
- /// This function will read memory from the current process's
- /// address space and remove any traps that may have been inserted
- /// into the memory.
+ /// This function will read memory from the current process's address space
+ /// and remove any traps that may have been inserted into the memory.
///
- /// This function is not meant to be overridden by Process
- /// subclasses, the subclasses should implement
- /// Process::DoReadMemory (lldb::addr_t, size_t, void *).
+ /// This function is not meant to be overridden by Process subclasses, the
+ /// subclasses should implement Process::DoReadMemory (lldb::addr_t, size_t,
+ /// void *).
///
/// @param[in] vm_addr
/// A virtual load address that indicates where to start reading
@@ -1732,12 +1730,18 @@ public:
/// @param[in] size
/// The number of bytes to read.
///
+ /// @param[out] error
+ /// An error that indicates the success or failure of this
+ /// operation. If error indicates success (error.Success()),
+ /// then the value returned can be trusted, otherwise zero
+ /// will be returned.
+ ///
/// @return
/// The number of bytes that were actually read into \a buf. If
/// the returned number is greater than zero, yet less than \a
/// size, then this function will get called again with \a
/// vm_addr, \a buf, and \a size updated appropriately. Zero is
- /// returned to indicate an error.
+ /// returned in the case of an error.
//------------------------------------------------------------------
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
Status &error);
@@ -1745,12 +1749,12 @@ public:
//------------------------------------------------------------------
/// Read a NULL terminated string from memory
///
- /// This function will read a cache page at a time until a NULL
- /// string terminator is found. It will stop reading if an aligned
- /// sequence of NULL termination \a type_width bytes is not found
- /// before reading \a cstr_max_len bytes. The results are always
- /// guaranteed to be NULL terminated, and that no more than
- /// (max_bytes - type_width) bytes will be read.
+ /// This function will read a cache page at a time until a NULL string
+ /// terminator is found. It will stop reading if an aligned sequence of NULL
+ /// termination \a type_width bytes is not found before reading \a
+ /// cstr_max_len bytes. The results are always guaranteed to be NULL
+ /// terminated, and that no more than (max_bytes - type_width) bytes will be
+ /// read.
///
/// @param[in] vm_addr
/// The virtual load address to start the memory read.
@@ -1779,9 +1783,9 @@ public:
///
/// This function will read a cache page at a time until the NULL
/// C string terminator is found. It will stop reading if the NULL
- /// termination byte isn't found before reading \a cstr_max_len
- /// bytes, and the results are always guaranteed to be NULL
- /// terminated (at most cstr_max_len - 1 bytes will be read).
+ /// termination byte isn't found before reading \a cstr_max_len bytes, and
+ /// the results are always guaranteed to be NULL terminated (at most
+ /// cstr_max_len - 1 bytes will be read).
//------------------------------------------------------------------
size_t ReadCStringFromMemory(lldb::addr_t vm_addr, char *cstr,
size_t cstr_max_len, Status &error);
@@ -1793,8 +1797,8 @@ public:
Status &error);
//------------------------------------------------------------------
- /// Reads an unsigned integer of the specified byte size from
- /// process memory.
+ /// Reads an unsigned integer of the specified byte size from process
+ /// memory.
///
/// @param[in] load_addr
/// A load address of the integer to read.
@@ -1862,13 +1866,12 @@ public:
//------------------------------------------------------------------
/// Write all or part of a scalar value to memory.
///
- /// The value contained in \a scalar will be swapped to match the
- /// byte order of the process that is being debugged. If \a size is
- /// less than the size of scalar, the least significant \a size bytes
- /// from scalar will be written. If \a size is larger than the byte
- /// size of scalar, then the extra space will be padded with zeros
- /// and the scalar value will be placed in the least significant
- /// bytes in memory.
+ /// The value contained in \a scalar will be swapped to match the byte order
+ /// of the process that is being debugged. If \a size is less than the size
+ /// of scalar, the least significant \a size bytes from scalar will be
+ /// written. If \a size is larger than the byte size of scalar, then the
+ /// extra space will be padded with zeros and the scalar value will be
+ /// placed in the least significant bytes in memory.
///
/// @param[in] vm_addr
/// A virtual load address that indicates where to start writing
@@ -1901,13 +1904,13 @@ public:
//------------------------------------------------------------------
/// Write memory to a process.
///
- /// This function will write memory to the current process's
- /// address space and maintain any traps that might be present due
- /// to software breakpoints.
+ /// This function will write memory to the current process's address space
+ /// and maintain any traps that might be present due to software
+ /// breakpoints.
///
- /// This function is not meant to be overridden by Process
- /// subclasses, the subclasses should implement
- /// Process::DoWriteMemory (lldb::addr_t, size_t, void *).
+ /// This function is not meant to be overridden by Process subclasses, the
+ /// subclasses should implement Process::DoWriteMemory (lldb::addr_t,
+ /// size_t, void *).
///
/// @param[in] vm_addr
/// A virtual load address that indicates where to start writing
@@ -1930,9 +1933,9 @@ public:
//------------------------------------------------------------------
/// Actually allocate memory in the process.
///
- /// This function will allocate memory in the process's address
- /// space. This can't rely on the generic function calling mechanism,
- /// since that requires this function.
+ /// This function will allocate memory in the process's address space. This
+ /// can't rely on the generic function calling mechanism, since that
+ /// requires this function.
///
/// @param[in] size
/// The size of the allocation requested.
@@ -1950,12 +1953,14 @@ public:
return LLDB_INVALID_ADDRESS;
}
+ virtual Status WriteObjectFile(std::vector<ObjectFile::LoadableData> entries);
+
//------------------------------------------------------------------
/// The public interface to allocating memory in the process.
///
- /// This function will allocate memory in the process's address
- /// space. This can't rely on the generic function calling mechanism,
- /// since that requires this function.
+ /// This function will allocate memory in the process's address space. This
+ /// can't rely on the generic function calling mechanism, since that
+ /// requires this function.
///
/// @param[in] size
/// The size of the allocation requested.
@@ -1979,9 +1984,9 @@ public:
/// The public interface to allocating memory in the process, this also
/// clears the allocated memory.
///
- /// This function will allocate memory in the process's address
- /// space. This can't rely on the generic function calling mechanism,
- /// since that requires this function.
+ /// This function will allocate memory in the process's address space. This
+ /// can't rely on the generic function calling mechanism, since that
+ /// requires this function.
///
/// @param[in] size
/// The size of the allocation requested.
@@ -2023,18 +2028,18 @@ public:
/// Locate the memory region that contains load_addr.
///
/// If load_addr is within the address space the process has mapped
- /// range_info will be filled in with the start and end of that range
- /// as well as the permissions for that range and range_info.GetMapped
- /// will return true.
+ /// range_info will be filled in with the start and end of that range as
+ /// well as the permissions for that range and range_info.GetMapped will
+ /// return true.
///
- /// If load_addr is outside any mapped region then range_info will
- /// have its start address set to load_addr and the end of the
- /// range will indicate the start of the next mapped range or be
- /// set to LLDB_INVALID_ADDRESS if there are no valid mapped ranges
- /// between load_addr and the end of the process address space.
+ /// If load_addr is outside any mapped region then range_info will have its
+ /// start address set to load_addr and the end of the range will indicate
+ /// the start of the next mapped range or be set to LLDB_INVALID_ADDRESS if
+ /// there are no valid mapped ranges between load_addr and the end of the
+ /// process address space.
///
- /// GetMemoryRegionInfo will only return an error if it is
- /// unimplemented for the current process.
+ /// GetMemoryRegionInfo will only return an error if it is unimplemented for
+ /// the current process.
///
/// @param[in] load_addr
/// The load address to query the range_info for.
@@ -2087,9 +2092,9 @@ public:
//------------------------------------------------------------------
/// Attempt to get the attributes for a region of memory in the process.
///
- /// It may be possible for the remote debug server to inspect attributes
- /// for a region of memory in the process, such as whether there is a
- /// valid page of memory at a given address or whether that page is
+ /// It may be possible for the remote debug server to inspect attributes for
+ /// a region of memory in the process, such as whether there is a valid page
+ /// of memory at a given address or whether that page is
/// readable/writable/executable by the process.
///
/// @param[in] load_addr
@@ -2109,8 +2114,8 @@ public:
uint32_t &permissions);
//------------------------------------------------------------------
- /// Determines whether executing JIT-compiled code in this process
- /// is possible.
+ /// Determines whether executing JIT-compiled code in this process is
+ /// possible.
///
/// @return
/// True if execution of JIT code is possible; false otherwise.
@@ -2118,8 +2123,7 @@ public:
bool CanJIT();
//------------------------------------------------------------------
- /// Sets whether executing JIT-compiled code in this process
- /// is possible.
+ /// Sets whether executing JIT-compiled code in this process is possible.
///
/// @param[in] can_jit
/// True if execution of JIT code is possible; false otherwise.
@@ -2127,8 +2131,8 @@ public:
void SetCanJIT(bool can_jit);
//------------------------------------------------------------------
- /// Determines whether executing function calls using the interpreter
- /// is possible for this process.
+ /// Determines whether executing function calls using the interpreter is
+ /// possible for this process.
///
/// @return
/// True if possible; false otherwise.
@@ -2136,8 +2140,8 @@ public:
bool CanInterpretFunctionCalls() { return m_can_interpret_function_calls; }
//------------------------------------------------------------------
- /// Sets whether executing function calls using the interpreter
- /// is possible for this process.
+ /// Sets whether executing function calls using the interpreter is possible
+ /// for this process.
///
/// @param[in] can_interpret_function_calls
/// True if possible; false otherwise.
@@ -2147,8 +2151,8 @@ public:
}
//------------------------------------------------------------------
- /// Sets whether executing code in this process is possible.
- /// This could be either through JIT or interpreting.
+ /// Sets whether executing code in this process is possible. This could be
+ /// either through JIT or interpreting.
///
/// @param[in] can_run_code
/// True if execution of code is possible; false otherwise.
@@ -2158,8 +2162,8 @@ public:
//------------------------------------------------------------------
/// Actually deallocate memory in the process.
///
- /// This function will deallocate memory in the process's address
- /// space that was allocated with AllocateMemory.
+ /// This function will deallocate memory in the process's address space that
+ /// was allocated with AllocateMemory.
///
/// @param[in] ptr
/// A return value from AllocateMemory, pointing to the memory you
@@ -2179,8 +2183,8 @@ public:
//------------------------------------------------------------------
/// The public interface to deallocating memory in the process.
///
- /// This function will deallocate memory in the process's address
- /// space that was allocated with AllocateMemory.
+ /// This function will deallocate memory in the process's address space that
+ /// was allocated with AllocateMemory.
///
/// @param[in] ptr
/// A return value from AllocateMemory, pointing to the memory you
@@ -2194,20 +2198,19 @@ public:
//------------------------------------------------------------------
/// Get any available STDOUT.
///
- /// Calling this method is a valid operation only if all of the
- /// following conditions are true:
- /// 1) The process was launched, and not attached to.
- /// 2) The process was not launched with eLaunchFlagDisableSTDIO.
- /// 3) The process was launched without supplying a valid file path
+ /// Calling this method is a valid operation only if all of the following
+ /// conditions are true: 1) The process was launched, and not attached to.
+ /// 2) The process was not launched with eLaunchFlagDisableSTDIO. 3) The
+ /// process was launched without supplying a valid file path
/// for STDOUT.
///
- /// Note that the implementation will probably need to start a read
- /// thread in the background to make sure that the pipe is drained
- /// and the STDOUT buffered appropriately, to prevent the process
- /// from deadlocking trying to write to a full buffer.
+ /// Note that the implementation will probably need to start a read thread
+ /// in the background to make sure that the pipe is drained and the STDOUT
+ /// buffered appropriately, to prevent the process from deadlocking trying
+ /// to write to a full buffer.
///
- /// Events will be queued indicating that there is STDOUT available
- /// that can be retrieved using this function.
+ /// Events will be queued indicating that there is STDOUT available that can
+ /// be retrieved using this function.
///
/// @param[out] buf
/// A buffer that will receive any STDOUT bytes that are
@@ -2226,20 +2229,19 @@ public:
//------------------------------------------------------------------
/// Get any available STDERR.
///
- /// Calling this method is a valid operation only if all of the
- /// following conditions are true:
- /// 1) The process was launched, and not attached to.
- /// 2) The process was not launched with eLaunchFlagDisableSTDIO.
- /// 3) The process was launched without supplying a valid file path
+ /// Calling this method is a valid operation only if all of the following
+ /// conditions are true: 1) The process was launched, and not attached to.
+ /// 2) The process was not launched with eLaunchFlagDisableSTDIO. 3) The
+ /// process was launched without supplying a valid file path
/// for STDERR.
///
- /// Note that the implementation will probably need to start a read
- /// thread in the background to make sure that the pipe is drained
- /// and the STDERR buffered appropriately, to prevent the process
- /// from deadlocking trying to write to a full buffer.
+ /// Note that the implementation will probably need to start a read thread
+ /// in the background to make sure that the pipe is drained and the STDERR
+ /// buffered appropriately, to prevent the process from deadlocking trying
+ /// to write to a full buffer.
///
- /// Events will be queued indicating that there is STDERR available
- /// that can be retrieved using this function.
+ /// Events will be queued indicating that there is STDERR available that can
+ /// be retrieved using this function.
///
/// @param[in] buf
/// A buffer that will receive any STDERR bytes that are
@@ -2258,11 +2260,10 @@ public:
//------------------------------------------------------------------
/// Puts data into this process's STDIN.
///
- /// Calling this method is a valid operation only if all of the
- /// following conditions are true:
- /// 1) The process was launched, and not attached to.
- /// 2) The process was not launched with eLaunchFlagDisableSTDIO.
- /// 3) The process was launched without supplying a valid file path
+ /// Calling this method is a valid operation only if all of the following
+ /// conditions are true: 1) The process was launched, and not attached to.
+ /// 2) The process was not launched with eLaunchFlagDisableSTDIO. 3) The
+ /// process was launched without supplying a valid file path
/// for STDIN.
///
/// @param[in] buf
@@ -2320,9 +2321,9 @@ public:
}
// This is implemented completely using the lldb::Process API. Subclasses
- // don't need to implement this function unless the standard flow of
- // read existing opcode, write breakpoint opcode, verify breakpoint opcode
- // doesn't work for a specific process plug-in.
+ // don't need to implement this function unless the standard flow of read
+ // existing opcode, write breakpoint opcode, verify breakpoint opcode doesn't
+ // work for a specific process plug-in.
virtual Status EnableSoftwareBreakpoint(BreakpointSite *bp_site);
// This is implemented completely using the lldb::Process API. Subclasses
@@ -2346,8 +2347,8 @@ public:
Status EnableBreakpointSiteByID(lldb::user_id_t break_id);
- // BreakpointLocations use RemoveOwnerFromBreakpointSite to remove
- // themselves from the owner's list of this breakpoint sites.
+ // BreakpointLocations use RemoveOwnerFromBreakpointSite to remove themselves
+ // from the owner's list of this breakpoint sites.
void RemoveOwnerFromBreakpointSite(lldb::user_id_t owner_id,
lldb::user_id_t owner_loc_id,
lldb::BreakpointSiteSP &bp_site_sp);
@@ -2369,11 +2370,10 @@ public:
ThreadList &GetThreadList() { return m_thread_list; }
- // When ExtendedBacktraces are requested, the HistoryThreads that are
- // created need an owner -- they're saved here in the Process. The
- // threads in this list are not iterated over - driver programs need to
- // request the extended backtrace calls starting from a root concrete
- // thread one by one.
+ // When ExtendedBacktraces are requested, the HistoryThreads that are created
+ // need an owner -- they're saved here in the Process. The threads in this
+ // list are not iterated over - driver programs need to request the extended
+ // backtrace calls starting from a root concrete thread one by one.
ThreadList &GetExtendedThreadList() { return m_extended_thread_list; }
ThreadList::ThreadIterable Threads() { return m_thread_list.Threads(); }
@@ -2385,10 +2385,9 @@ public:
// Returns true if an index id has been assigned to a thread.
bool HasAssignedIndexIDToThread(uint64_t sb_thread_id);
- // Given a thread_id, it will assign a more reasonable index id for display to
- // the user.
- // If the thread_id has previously been assigned, the same index id will be
- // used.
+ // Given a thread_id, it will assign a more reasonable index id for display
+ // to the user. If the thread_id has previously been assigned, the same index
+ // id will be used.
uint32_t AssignIndexIDToThread(uint64_t thread_id);
//------------------------------------------------------------------
@@ -2413,13 +2412,11 @@ public:
lldb::StateType GetNextEvent(lldb::EventSP &event_sp);
// Returns the process state when it is stopped. If specified, event_sp_ptr
- // is set to the event which triggered the stop. If wait_always = false,
- // and the process is already stopped, this function returns immediately.
- // If the process is hijacked and use_run_lock is true (the default), then
- // this
+ // is set to the event which triggered the stop. If wait_always = false, and
+ // the process is already stopped, this function returns immediately. If the
+ // process is hijacked and use_run_lock is true (the default), then this
// function releases the run lock after the stop. Setting use_run_lock to
- // false
- // will avoid this behavior.
+ // false will avoid this behavior.
lldb::StateType
WaitForProcessToStop(const Timeout<std::micro> &timeout,
lldb::EventSP *event_sp_ptr = nullptr,
@@ -2433,14 +2430,13 @@ public:
/// Waits for the process state to be running within a given msec timeout.
///
/// The main purpose of this is to implement an interlock waiting for
- /// HandlePrivateEvent
- /// to push an IOHandler.
+ /// HandlePrivateEvent to push an IOHandler.
///
- /// @param[in] timeout_msec
+ /// @param[in] timeout
/// The maximum time length to wait for the process to transition to the
- /// eStateRunning state, specified in milliseconds.
+ /// eStateRunning state.
//--------------------------------------------------------------------------------------
- void SyncIOHandler(uint32_t iohandler_id, uint64_t timeout_msec);
+ void SyncIOHandler(uint32_t iohandler_id, const Timeout<std::micro> &timeout);
lldb::StateType GetStateChangedEvents(
lldb::EventSP &event_sp, const Timeout<std::micro> &timeout,
@@ -2448,8 +2444,8 @@ public:
hijack_listener); // Pass an empty ListenerSP to use builtin listener
//--------------------------------------------------------------------------------------
- /// Centralize the code that handles and prints descriptions for process state
- /// changes.
+ /// Centralize the code that handles and prints descriptions for process
+ /// state changes.
///
/// @param[in] event_sp
/// The process state changed event
@@ -2494,8 +2490,8 @@ public:
/// event, then make a new listener, set to listen to process events, and
/// then call this with that listener. Then you will have to wait on that
/// listener explicitly for events (rather than using the GetNextEvent &
- /// WaitFor*
- /// calls above. Be sure to call RestoreProcessEvents when you are done.
+ /// WaitFor* calls above. Be sure to call RestoreProcessEvents when you are
+ /// done.
///
/// @param[in] listener
/// This is the new listener to whom all process events will be delivered.
@@ -2577,27 +2573,26 @@ public:
void SetSTDIOFileDescriptor(int file_descriptor);
//------------------------------------------------------------------
- // Add a permanent region of memory that should never be read or
- // written to. This can be used to ensure that memory reads or writes
- // to certain areas of memory never end up being sent to the
- // DoReadMemory or DoWriteMemory functions which can improve
- // performance.
+ // Add a permanent region of memory that should never be read or written to.
+ // This can be used to ensure that memory reads or writes to certain areas of
+ // memory never end up being sent to the DoReadMemory or DoWriteMemory
+ // functions which can improve performance.
//------------------------------------------------------------------
void AddInvalidMemoryRegion(const LoadRange &region);
//------------------------------------------------------------------
- // Remove a permanent region of memory that should never be read or
- // written to that was previously added with AddInvalidMemoryRegion.
+ // Remove a permanent region of memory that should never be read or written
+ // to that was previously added with AddInvalidMemoryRegion.
//------------------------------------------------------------------
bool RemoveInvalidMemoryRange(const LoadRange &region);
//------------------------------------------------------------------
// If the setup code of a thread plan needs to do work that might involve
- // calling a function in the target, it should not do that work directly
- // in one of the thread plan functions (DidPush/WillResume) because
- // such work needs to be handled carefully. Instead, put that work in
- // a PreResumeAction callback, and register it with the process. It will
- // get done before the actual "DoResume" gets called.
+ // calling a function in the target, it should not do that work directly in
+ // one of the thread plan functions (DidPush/WillResume) because such work
+ // needs to be handled carefully. Instead, put that work in a
+ // PreResumeAction callback, and register it with the process. It will get
+ // done before the actual "DoResume" gets called.
//------------------------------------------------------------------
typedef bool(PreResumeActionCallback)(void *);
@@ -2623,10 +2618,10 @@ public:
GetInstrumentationRuntime(lldb::InstrumentationRuntimeType type);
//------------------------------------------------------------------
- /// Try to fetch the module specification for a module with the
- /// given file name and architecture. Process sub-classes have to
- /// override this method if they support platforms where the
- /// Platform object can't get the module spec for all module.
+ /// Try to fetch the module specification for a module with the given file
+ /// name and architecture. Process sub-classes have to override this method
+ /// if they support platforms where the Platform object can't get the module
+ /// spec for all module.
///
/// @param[in] module_file_spec
/// The file name of the module to get specification for.
@@ -2650,8 +2645,8 @@ public:
//------------------------------------------------------------------
/// Try to find the load address of a file.
- /// The load address is defined as the address of the first memory
- /// region what contains data mapped from the specified file.
+ /// The load address is defined as the address of the first memory region
+ /// what contains data mapped from the specified file.
///
/// @param[in] file
/// The name of the file whose load address we are looking for
@@ -2678,12 +2673,11 @@ public:
//------------------------------------------------------------------
/// Find the next branch instruction to set a breakpoint on
///
- /// When instruction stepping through a source line, instead of
- /// stepping through each instruction, we can put a breakpoint on
- /// the next branch instruction (within the range of instructions
- /// we are stepping through) and continue the process to there,
- /// yielding significant performance benefits over instruction
- /// stepping.
+ /// When instruction stepping through a source line, instead of stepping
+ /// through each instruction, we can put a breakpoint on the next branch
+ /// instruction (within the range of instructions we are stepping through)
+ /// and continue the process to there, yielding significant performance
+ /// benefits over instruction stepping.
///
/// @param[in] default_stop_addr
/// The address of the instruction where lldb would put a
@@ -2710,8 +2704,8 @@ public:
/// The default implementation here will always return an error indiciating
/// the feature is unsupported.
///
- /// StructuredDataPlugin implementations will call this to configure
- /// a feature that has been reported as being supported.
+ /// StructuredDataPlugin implementations will call this to configure a
+ /// feature that has been reported as being supported.
///
/// @param[in] type_name
/// The StructuredData type name as previously discovered by
@@ -2733,13 +2727,12 @@ public:
const StructuredData::ObjectSP &config_sp);
//------------------------------------------------------------------
- /// Broadcasts the given structured data object from the given
- /// plugin.
+ /// Broadcasts the given structured data object from the given plugin.
///
- /// StructuredDataPlugin instances can use this to optionally
- /// broadcast any of their data if they want to make it available
- /// for clients. The data will come in on the structured data
- /// event bit (eBroadcastBitStructuredData).
+ /// StructuredDataPlugin instances can use this to optionally broadcast any
+ /// of their data if they want to make it available for clients. The data
+ /// will come in on the structured data event bit
+ /// (eBroadcastBitStructuredData).
///
/// @param[in] object_sp
/// The structured data object to broadcast.
@@ -2752,12 +2745,12 @@ public:
const lldb::StructuredDataPluginSP &plugin_sp);
//------------------------------------------------------------------
- /// Returns the StructuredDataPlugin associated with a given type
- /// name, if there is one.
+ /// Returns the StructuredDataPlugin associated with a given type name, if
+ /// there is one.
///
/// There will only be a plugin for a given StructuredDataType if the
- /// debugged process monitor claims that the feature is supported.
- /// This is one way to tell whether a feature is available.
+ /// debugged process monitor claims that the feature is supported. This is
+ /// one way to tell whether a feature is available.
///
/// @return
/// The plugin if one is available for the specified feature;
@@ -2767,17 +2760,14 @@ public:
GetStructuredDataPlugin(const ConstString &type_name) const;
//------------------------------------------------------------------
- /// Starts tracing with the configuration provided in options. To
- /// enable tracing on the complete process the thread_id in the
- /// options should be set to LLDB_INVALID_THREAD_ID. The API returns
- /// a user_id which is needed by other API's that manipulate the
- /// trace instance.
- /// The handling of erroneous or unsupported configuration is left
- /// to the trace technology implementations in the server, as they
- /// could be returned as an error, or rounded to a valid
- /// configuration to start tracing. In the later case the
- /// GetTraceConfig should supply the actual used trace
- /// configuration.
+ /// Starts tracing with the configuration provided in options. To enable
+ /// tracing on the complete process the thread_id in the options should be
+ /// set to LLDB_INVALID_THREAD_ID. The API returns a user_id which is needed
+ /// by other API's that manipulate the trace instance. The handling of
+ /// erroneous or unsupported configuration is left to the trace technology
+ /// implementations in the server, as they could be returned as an error, or
+ /// rounded to a valid configuration to start tracing. In the later case the
+ /// GetTraceConfig should supply the actual used trace configuration.
//------------------------------------------------------------------
virtual lldb::user_id_t StartTrace(const TraceOptions &options,
Status &error) {
@@ -2786,25 +2776,23 @@ public:
}
//------------------------------------------------------------------
- /// Stops the tracing instance leading to deletion of the trace
- /// data. The tracing instance is identified by the user_id which
- /// is obtained when tracing was started from the StartTrace.
- /// In case tracing of the complete process needs to be stopped
- /// the thread_id should be set to LLDB_INVALID_THREAD_ID.
- /// In the other case that tracing on an individual thread needs
- /// to be stopped a thread_id can be supplied.
+ /// Stops the tracing instance leading to deletion of the trace data. The
+ /// tracing instance is identified by the user_id which is obtained when
+ /// tracing was started from the StartTrace. In case tracing of the complete
+ /// process needs to be stopped the thread_id should be set to
+ /// LLDB_INVALID_THREAD_ID. In the other case that tracing on an individual
+ /// thread needs to be stopped a thread_id can be supplied.
//------------------------------------------------------------------
virtual Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
return Status("Not implemented");
}
//------------------------------------------------------------------
- /// Provides the trace data as raw bytes. A buffer needs to be
- /// supplied to copy the trace data. The exact behavior of this API
- /// may vary across trace technology, as some may support partial
- /// reading of the trace data from a specified offset while some
- /// may not. The thread_id should be used to select a particular
- /// thread for trace extraction.
+ /// Provides the trace data as raw bytes. A buffer needs to be supplied to
+ /// copy the trace data. The exact behavior of this API may vary across
+ /// trace technology, as some may support partial reading of the trace data
+ /// from a specified offset while some may not. The thread_id should be used
+ /// to select a particular thread for trace extraction.
//------------------------------------------------------------------
virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
llvm::MutableArrayRef<uint8_t> &buffer,
@@ -2823,12 +2811,12 @@ public:
//------------------------------------------------------------------
/// API to obtain the trace configuration used by a trace instance.
- /// Configurations that may be specific to some trace technology
- /// should be stored in the custom parameters. The options are
- /// transported to the server, which shall interpret accordingly.
- /// The thread_id can be specified in the options to obtain the
- /// configuration used by a specific thread. The thread_id specified
- /// should also match the uid otherwise an error will be returned.
+ /// Configurations that may be specific to some trace technology should be
+ /// stored in the custom parameters. The options are transported to the
+ /// server, which shall interpret accordingly. The thread_id can be
+ /// specified in the options to obtain the configuration used by a specific
+ /// thread. The thread_id specified should also match the uid otherwise an
+ /// error will be returned.
//------------------------------------------------------------------
virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) {
return Status("Not implemented");
@@ -2840,8 +2828,8 @@ protected:
lldb::StateType GetPrivateState();
//------------------------------------------------------------------
- /// The "private" side of resuming a process. This doesn't alter the
- /// state of m_run_lock, but just causes the process to resume.
+ /// The "private" side of resuming a process. This doesn't alter the state
+ /// of m_run_lock, but just causes the process to resume.
///
/// @return
/// An Status object describing the success or failure of the resume.
@@ -2858,16 +2846,16 @@ protected:
///
/// A facility for printing a warning to the user once per repeat_key.
///
- /// warning_type is from the Process::Warnings enums.
- /// repeat_key is a pointer value that will be used to ensure that the
- /// warning message is not printed multiple times. For instance, with a
- /// warning about a function being optimized, you can pass the CompileUnit
- /// pointer to have the warning issued for only the first function in a
- /// CU, or the Function pointer to have it issued once for every function,
- /// or a Module pointer to have it issued once per Module.
+ /// warning_type is from the Process::Warnings enums. repeat_key is a
+ /// pointer value that will be used to ensure that the warning message is
+ /// not printed multiple times. For instance, with a warning about a
+ /// function being optimized, you can pass the CompileUnit pointer to have
+ /// the warning issued for only the first function in a CU, or the Function
+ /// pointer to have it issued once for every function, or a Module pointer
+ /// to have it issued once per Module.
///
- /// Classes outside Process should call a specific PrintWarning method
- /// so that the warning strings are all centralized in Process, instead of
+ /// Classes outside Process should call a specific PrintWarning method so
+ /// that the warning strings are all centralized in Process, instead of
/// calling PrintWarning() directly.
///
/// @param [in] warning_type
@@ -2885,15 +2873,14 @@ protected:
const char *fmt, ...) __attribute__((format(printf, 4, 5)));
//------------------------------------------------------------------
- // NextEventAction provides a way to register an action on the next
- // event that is delivered to this process. There is currently only
- // one next event action allowed in the process at one time. If a
- // new "NextEventAction" is added while one is already present, the
- // old action will be discarded (with HandleBeingUnshipped called
- // after it is discarded.)
+ // NextEventAction provides a way to register an action on the next event
+ // that is delivered to this process. There is currently only one next event
+ // action allowed in the process at one time. If a new "NextEventAction" is
+ // added while one is already present, the old action will be discarded (with
+ // HandleBeingUnshipped called after it is discarded.)
//
- // If you want to resume the process as a result of a resume action,
- // call RequestResume, don't call Resume directly.
+ // If you want to resume the process as a result of a resume action, call
+ // RequestResume, don't call Resume directly.
//------------------------------------------------------------------
class NextEventAction {
public:
@@ -2949,18 +2936,17 @@ protected:
void ForceNextEventDelivery() { m_force_next_event_delivery = true; }
//------------------------------------------------------------------
- /// Loads any plugins associated with asynchronous structured data
- /// and maps the relevant supported type name to the plugin.
+ /// Loads any plugins associated with asynchronous structured data and maps
+ /// the relevant supported type name to the plugin.
///
- /// Processes can receive asynchronous structured data from the
- /// process monitor. This method will load and map any structured
- /// data plugins that support the given set of supported type names.
- /// Later, if any of these features are enabled, the process monitor
- /// is free to generate asynchronous structured data. The data must
- /// come in as a single \b StructuredData::Dictionary. That dictionary
- /// must have a string field named 'type', with a value that equals
- /// the relevant type name string (one of the values in
- /// \b supported_type_names).
+ /// Processes can receive asynchronous structured data from the process
+ /// monitor. This method will load and map any structured data plugins that
+ /// support the given set of supported type names. Later, if any of these
+ /// features are enabled, the process monitor is free to generate
+ /// asynchronous structured data. The data must come in as a single \b
+ /// StructuredData::Dictionary. That dictionary must have a string field
+ /// named 'type', with a value that equals the relevant type name string
+ /// (one of the values in \b supported_type_names).
///
/// @param[in] supported_type_names
/// An array of zero or more type names. Each must be unique.
@@ -2973,10 +2959,9 @@ protected:
//------------------------------------------------------------------
/// Route the incoming structured data dictionary to the right plugin.
///
- /// The incoming structured data must be a dictionary, and it must
- /// have a key named 'type' that stores a string value. The string
- /// value must be the name of the structured data feature that
- /// knows how to handle it.
+ /// The incoming structured data must be a dictionary, and it must have a
+ /// key named 'type' that stores a string value. The string value must be
+ /// the name of the structured data feature that knows how to handle it.
///
/// @param[in] object_sp
/// When non-null and pointing to a dictionary, the 'type'
@@ -3022,7 +3007,7 @@ protected:
//------------------------------------------------------------------
// Member variables
//------------------------------------------------------------------
- std::weak_ptr<Target> m_target_sp; ///< The target that owns this process.
+ std::weak_ptr<Target> m_target_wp; ///< The target that owns this process.
ThreadSafeValue<lldb::StateType> m_public_state;
ThreadSafeValue<lldb::StateType>
m_private_state; // The actual state of our process
@@ -3107,11 +3092,11 @@ protected:
bool m_currently_handling_do_on_removals;
bool m_resume_requested; // If m_currently_handling_event or
// m_currently_handling_do_on_removals are true,
- // Resume will only request a resume, using this flag
- // to check.
+ // Resume will only request a resume, using this
+ // flag to check.
bool m_finalizing; // This is set at the beginning of Process::Finalize() to
- // stop functions from looking up or creating things during
- // a finalize call
+ // stop functions from looking up or creating things
+ // during a finalize call
bool m_finalize_called; // This is set at the end of Process::Finalize()
bool m_clear_thread_plans_on_stop;
bool m_force_next_event_delivery;
@@ -3129,6 +3114,9 @@ protected:
StructuredDataPluginMap m_structured_data_plugin_map;
enum { eCanJITDontKnow = 0, eCanJITYes, eCanJITNo } m_can_jit;
+
+ std::unique_ptr<UtilityFunction> m_dlopen_utility_func_up;
+ std::once_flag m_dlopen_utility_func_flag_once;
size_t RemoveBreakpointOpcodesFromBuffer(lldb::addr_t addr, size_t size,
uint8_t *buf) const;
@@ -3160,12 +3148,9 @@ private:
static lldb::thread_result_t PrivateStateThread(void *arg);
// The starts up the private state thread that will watch for events from the
- // debugee.
- // Pass true for is_secondary_thread in the case where you have to temporarily
- // spin up a
- // secondary state thread to handle events from a hand-called function on the
- // primary
- // private state thread.
+ // debugee. Pass true for is_secondary_thread in the case where you have to
+ // temporarily spin up a secondary state thread to handle events from a hand-
+ // called function on the primary private state thread.
lldb::thread_result_t RunPrivateStateThread(bool is_secondary_thread);
@@ -3178,8 +3163,7 @@ protected:
const Timeout<std::micro> &timeout);
// This waits for both the state change broadcaster, and the control
- // broadcaster.
- // If control_only, it only waits for the control broadcaster.
+ // broadcaster. If control_only, it only waits for the control broadcaster.
bool GetEventsPrivate(lldb::EventSP &event_sp,
const Timeout<std::micro> &timeout, bool control_only);
@@ -3220,14 +3204,12 @@ protected:
private:
//------------------------------------------------------------------
- /// This is the part of the event handling that for a process event.
- /// It decides what to do with the event and returns true if the
- /// event needs to be propagated to the user, and false otherwise.
- /// If the event is not propagated, this call will most likely set
- /// the target to executing again.
- /// There is only one place where this call should be called,
- /// HandlePrivateEvent.
- /// Don't call it from anywhere else...
+ /// This is the part of the event handling that for a process event. It
+ /// decides what to do with the event and returns true if the event needs to
+ /// be propagated to the user, and false otherwise. If the event is not
+ /// propagated, this call will most likely set the target to executing
+ /// again. There is only one place where this call should be called,
+ /// HandlePrivateEvent. Don't call it from anywhere else...
///
/// @param[in] event_ptr
/// This is the event we are handling.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ProcessInfo.h b/contrib/llvm/tools/lldb/include/lldb/Target/ProcessInfo.h
index 4077abf89baf..0e0d8548feb6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ProcessInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ProcessInfo.h
@@ -11,8 +11,9 @@
#define liblldb_ProcessInfo_h_
// LLDB headers
-#include "lldb/Interpreter/Args.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/Environment.h"
#include "lldb/Utility/FileSpec.h"
namespace lldb_private {
@@ -20,9 +21,9 @@ namespace lldb_private {
// ProcessInfo
//
// A base class for information for a process. This can be used to fill
-// out information for a process prior to launching it, or it can be
-// used for an instance of a process and can be filled in with the
-// existing values for that process.
+// out information for a process prior to launching it, or it can be used for
+// an instance of a process and can be filled in with the existing values for
+// that process.
//----------------------------------------------------------------------
class ProcessInfo {
public:
@@ -81,18 +82,16 @@ public:
void SetArguments(char const **argv, bool first_arg_is_executable);
- Args &GetEnvironmentEntries() { return m_environment; }
-
- const Args &GetEnvironmentEntries() const { return m_environment; }
+ Environment &GetEnvironment() { return m_environment; }
+ const Environment &GetEnvironment() const { return m_environment; }
protected:
FileSpec m_executable;
std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
- // Not all process plug-ins support specifying an argv[0]
- // that differs from the resolved platform executable
- // (which is in m_executable)
+ // Not all process plug-ins support specifying an argv[0] that differs from
+ // the resolved platform executable (which is in m_executable)
Args m_arguments; // All program arguments except argv[0]
- Args m_environment;
+ Environment m_environment;
uint32_t m_uid;
uint32_t m_gid;
ArchSpec m_arch;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ProcessLaunchInfo.h b/contrib/llvm/tools/lldb/include/lldb/Target/ProcessLaunchInfo.h
index fc715f28544d..92c517a3e460 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ProcessLaunchInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ProcessLaunchInfo.h
@@ -107,13 +107,18 @@ public:
return m_monitor_callback;
}
+ /// A Monitor callback which does not take any action on process events. Use
+ /// this if you don't need to take any particular action when the process
+ /// terminates, but you still need to reap it.
+ static bool NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal,
+ int status);
+
bool GetMonitorSignals() const { return m_monitor_signals; }
// If the LaunchInfo has a monitor callback, then arrange to monitor the
- // process.
- // Return true if the LaunchInfo has taken care of monitoring the process, and
- // false if the
- // caller might want to monitor the process themselves.
+ // process. Return true if the LaunchInfo has taken care of monitoring the
+ // process, and false if the caller might want to monitor the process
+ // themselves.
bool MonitorProcess() const;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ProcessStructReader.h b/contrib/llvm/tools/lldb/include/lldb/Target/ProcessStructReader.h
index cfc8fe11a39a..8f1445ae8c1b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ProcessStructReader.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ProcessStructReader.h
@@ -16,6 +16,7 @@
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Status.h"
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Queue.h b/contrib/llvm/tools/lldb/include/lldb/Target/Queue.h
index 2df4d54a89b6..62cc3ccf2e2f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Queue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Queue.h
@@ -22,15 +22,14 @@ namespace lldb_private {
//------------------------------------------------------------------
// Queue:
-// This class represents a libdispatch aka Grand Central Dispatch
-// queue in the process.
+// This class represents a libdispatch aka Grand Central Dispatch queue in the
+// process.
//
// A program using libdispatch will create queues, put work items
-// (functions, blocks) on the queues. The system will create /
-// reassign pthreads to execute the work items for the queues. A
-// serial queue will be associated with a single thread (or possibly
-// no thread, if it is not doing any work). A concurrent queue may
-// be associated with multiple threads.
+// (functions, blocks) on the queues. The system will create / reassign
+// pthreads to execute the work items for the queues. A serial queue will be
+// associated with a single thread (or possibly no thread, if it is not doing
+// any work). A concurrent queue may be associated with multiple threads.
//------------------------------------------------------------------
class Queue : public std::enable_shared_from_this<Queue> {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h b/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h
index acbf94e1b0f9..76bcea36a2fa 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h
@@ -29,12 +29,11 @@ namespace lldb_private {
//------------------------------------------------------------------
// QueueItem:
-// This class represents a work item enqueued on a libdispatch aka
-// Grand Central Dispatch (GCD) queue. Most often, this will be a
-// function or block.
-// "enqueued" here means that the work item has been added to a queue
-// but it has not yet started executing. When it is "dequeued",
-// execution of the item begins.
+// This class represents a work item enqueued on a libdispatch aka Grand
+// Central Dispatch (GCD) queue. Most often, this will be a function or block.
+// "enqueued" here means that the work item has been added to a queue but it
+// has not yet started executing. When it is "dequeued", execution of the item
+// begins.
//------------------------------------------------------------------
class QueueItem : public std::enable_shared_from_this<QueueItem> {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/QueueList.h b/contrib/llvm/tools/lldb/include/lldb/Target/QueueList.h
index 91cf3eb6d4c2..b35de13aa1e5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/QueueList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/QueueList.h
@@ -21,12 +21,11 @@ namespace lldb_private {
//------------------------------------------------------------------
// QueueList:
-// This is the container for libdispatch aka Grand Central Dispatch
-// Queue objects.
+// This is the container for libdispatch aka Grand Central Dispatch Queue
+// objects.
//
-// Each Process will have a QueueList. When the process execution is
-// paused, the QueueList may be populated with Queues by the
-// SystemRuntime.
+// Each Process will have a QueueList. When the process execution is paused,
+// the QueueList may be populated with Queues by the SystemRuntime.
//------------------------------------------------------------------
class QueueList {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterCheckpoint.h b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterCheckpoint.h
index 578cf25eef25..e4b407124c9f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterCheckpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterCheckpoint.h
@@ -16,20 +16,19 @@
namespace lldb_private {
-// Inherit from UserID in case pushing/popping all register values can be
-// done using a 64 bit integer that holds a baton/cookie instead of actually
-// having to read all register values into a buffer
+// Inherit from UserID in case pushing/popping all register values can be done
+// using a 64 bit integer that holds a baton/cookie instead of actually having
+// to read all register values into a buffer
class RegisterCheckpoint : public UserID {
public:
enum class Reason {
// An expression is about to be run on the thread if the protocol that
// talks to the debuggee supports checkpointing the registers using a
- // push/pop then the UserID base class in the RegisterCheckpoint can
- // be used to store the baton/cookie that refers to the remote saved
- // state.
+ // push/pop then the UserID base class in the RegisterCheckpoint can be
+ // used to store the baton/cookie that refers to the remote saved state.
eExpression,
- // The register checkpoint wants the raw register bytes, so they must
- // be read into m_data_sp, or the save/restore checkpoint should fail.
+ // The register checkpoint wants the raw register bytes, so they must be
+ // read into m_data_sp, or the save/restore checkpoint should fail.
eDataBackup
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h
index c438a0cd12cf..73a2930fd2b5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h
@@ -63,16 +63,14 @@ public:
}
// These two functions are used to implement "push" and "pop" of register
- // states. They are used primarily
- // for expression evaluation, where we need to push a new state (storing the
- // old one in data_sp) and then
- // restoring the original state by passing the data_sp we got from
- // ReadAllRegisters to WriteAllRegisterValues.
- // ReadAllRegisters will do what is necessary to return a coherent set of
- // register values for this thread, which
- // may mean e.g. interrupting a thread that is sitting in a kernel trap. That
- // is a somewhat disruptive operation,
- // so these API's should only be used when this behavior is needed.
+ // states. They are used primarily for expression evaluation, where we need
+ // to push a new state (storing the old one in data_sp) and then restoring
+ // the original state by passing the data_sp we got from ReadAllRegisters to
+ // WriteAllRegisterValues. ReadAllRegisters will do what is necessary to
+ // return a coherent set of register values for this thread, which may mean
+ // e.g. interrupting a thread that is sitting in a kernel trap. That is a
+ // somewhat disruptive operation, so these API's should only be used when
+ // this behavior is needed.
virtual bool
ReadAllRegisterValues(lldb_private::RegisterCheckpoint &reg_checkpoint);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterNumber.h b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterNumber.h
index 5649c8022ee7..1a0ab49bdce3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterNumber.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterNumber.h
@@ -26,8 +26,8 @@ public:
// This constructor plus the init() method below allow for the placeholder
// creation of an invalid object initially, possibly to be filled in. It
- // would be more consistent to have three Set* methods to set the three
- // data that the object needs.
+ // would be more consistent to have three Set* methods to set the three data
+ // that the object needs.
RegisterNumber();
void init(lldb_private::Thread &thread, lldb::RegisterKind kind,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadHistory.h b/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadHistory.h
index e1db141ea9e3..0ed335a9d040 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadHistory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadHistory.h
@@ -23,8 +23,8 @@ namespace lldb_private {
class SectionLoadHistory {
public:
enum : unsigned {
- // Pass eStopIDNow to any function that takes a stop ID to get
- // the current value.
+ // Pass eStopIDNow to any function that takes a stop ID to get the current
+ // value.
eStopIDNow = UINT32_MAX
};
//------------------------------------------------------------------
@@ -33,8 +33,8 @@ public:
SectionLoadHistory() : m_stop_id_to_section_load_list(), m_mutex() {}
~SectionLoadHistory() {
- // Call clear since this takes a lock and clears the section load list
- // in case another thread is currently using this section load list
+ // Call clear since this takes a lock and clears the section load list in
+ // case another thread is currently using this section load list
Clear();
}
@@ -59,14 +59,14 @@ public:
bool warn_multiple = false);
// The old load address should be specified when unloading to ensure we get
- // the correct instance of the section as a shared library could be loaded
- // at more than one location.
+ // the correct instance of the section as a shared library could be loaded at
+ // more than one location.
bool SetSectionUnloaded(uint32_t stop_id, const lldb::SectionSP &section_sp,
lldb::addr_t load_addr);
// Unload all instances of a section. This function can be used on systems
- // that don't support multiple copies of the same shared library to be
- // loaded at the same time.
+ // that don't support multiple copies of the same shared library to be loaded
+ // at the same time.
size_t SetSectionUnloaded(uint32_t stop_id,
const lldb::SectionSP &section_sp);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h b/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h
index beb345b71290..1156c686df17 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h
@@ -34,8 +34,8 @@ public:
SectionLoadList(const SectionLoadList &rhs);
~SectionLoadList() {
- // Call clear since this takes a lock and clears the section load list
- // in case another thread is currently using this section load list
+ // Call clear since this takes a lock and clears the section load list in
+ // case another thread is currently using this section load list
Clear();
}
@@ -55,14 +55,14 @@ public:
bool warn_multiple = false);
// The old load address should be specified when unloading to ensure we get
- // the correct instance of the section as a shared library could be loaded
- // at more than one location.
+ // the correct instance of the section as a shared library could be loaded at
+ // more than one location.
bool SetSectionUnloaded(const lldb::SectionSP &section_sp,
lldb::addr_t load_addr);
// Unload all instances of a section. This function can be used on systems
- // that don't support multiple copies of the same shared library to be
- // loaded at the same time.
+ // that don't support multiple copies of the same shared library to be loaded
+ // at the same time.
size_t SetSectionUnloaded(const lldb::SectionSP &section_sp);
void Dump(Stream &s, Target *target);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h b/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h
index d97043578ce9..ce9b16227672 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h
@@ -32,7 +32,7 @@ namespace lldb_private {
/// @class StackFrame StackFrame.h "lldb/Target/StackFrame.h"
///
-/// @brief This base class provides an interface to stack frames.
+/// This base class provides an interface to stack frames.
///
/// StackFrames may have a Canonical Frame Address (CFA) or not.
/// A frame may have a plain pc value or it may have a pc value + stop_id
@@ -59,10 +59,10 @@ public:
///
/// This is the one constructor that doesn't take a RegisterContext
/// parameter. This ctor may be called when creating a history StackFrame;
- /// these are used if we've collected a stack trace of pc addresses at
- /// some point in the past. We may only have pc values. We may have pc
- /// values and the stop_id when the stack trace was recorded. We may have a
- /// CFA, or more likely, we won't.
+ /// these are used if we've collected a stack trace of pc addresses at some
+ /// point in the past. We may only have pc values. We may have pc values
+ /// and the stop_id when the stack trace was recorded. We may have a CFA,
+ /// or more likely, we won't.
///
/// @param [in] thread_sp
/// The Thread that this frame belongs to.
@@ -165,9 +165,9 @@ public:
/// Provide a SymbolContext for this StackFrame's current pc value.
///
/// The StackFrame maintains this SymbolContext and adds additional
- /// information
- /// to it on an as-needed basis. This helps to avoid different functions
- /// looking up symbolic information for a given pc value multiple times.
+ /// information to it on an as-needed basis. This helps to avoid different
+ /// functions looking up symbolic information for a given pc value multiple
+ /// times.
///
/// @params [in] resolve_scope
/// Flags from the SymbolContextItem enumerated type which specify what
@@ -182,9 +182,9 @@ public:
//------------------------------------------------------------------
/// Return the Canonical Frame Address (DWARF term) for this frame.
///
- /// The CFA is typically the value of the stack pointer register before
- /// the call invocation is made. It will not change during the lifetime
- /// of a stack frame. It is often not the same thing as the frame pointer
+ /// The CFA is typically the value of the stack pointer register before the
+ /// call invocation is made. It will not change during the lifetime of a
+ /// stack frame. It is often not the same thing as the frame pointer
/// register value.
///
/// Live StackFrames will always have a CFA but other types of frames may
@@ -220,9 +220,8 @@ public:
//------------------------------------------------------------------
/// Get the current lexical scope block for this StackFrame, if possible.
///
- /// If debug information is available for this stack frame, return a
- /// pointer to the innermost lexical Block that the frame is currently
- /// executing.
+ /// If debug information is available for this stack frame, return a pointer
+ /// to the innermost lexical Block that the frame is currently executing.
///
/// @return
/// A pointer to the current Block. nullptr is returned if this can
@@ -251,11 +250,12 @@ public:
}
//------------------------------------------------------------------
- /// Retrieve the list of variables that are in scope at this StackFrame's pc.
+ /// Retrieve the list of variables that are in scope at this StackFrame's
+ /// pc.
///
/// A frame that is not live may return an empty VariableList for a given
- /// pc value even though variables would be available at this point if
- /// it were a live stack frame.
+ /// pc value even though variables would be available at this point if it
+ /// were a live stack frame.
///
/// @param[in] get_file_globals
/// Whether to also retrieve compilation-unit scoped variables
@@ -268,11 +268,12 @@ public:
VariableList *GetVariableList(bool get_file_globals);
//------------------------------------------------------------------
- /// Retrieve the list of variables that are in scope at this StackFrame's pc.
+ /// Retrieve the list of variables that are in scope at this StackFrame's
+ /// pc.
///
/// A frame that is not live may return an empty VariableListSP for a
- /// given pc value even though variables would be available at this point
- /// if it were a live stack frame.
+ /// given pc value even though variables would be available at this point if
+ /// it were a live stack frame.
///
/// @param[in] get_file_globals
/// Whether to also retrieve compilation-unit scoped variables
@@ -287,8 +288,8 @@ public:
bool must_have_valid_location = false);
//------------------------------------------------------------------
- /// Create a ValueObject for a variable name / pathname, possibly
- /// including simple dereference/child selection syntax.
+ /// Create a ValueObject for a variable name / pathname, possibly including
+ /// simple dereference/child selection syntax.
///
/// @param[in] var_expr
/// The string specifying a variable to base the VariableObject off
@@ -327,8 +328,8 @@ public:
bool HasDebugInformation();
//------------------------------------------------------------------
- /// Return the disassembly for the instructions of this StackFrame's function
- /// as a single C string.
+ /// Return the disassembly for the instructions of this StackFrame's
+ /// function as a single C string.
///
/// @return
// C string with the assembly instructions for this function.
@@ -366,8 +367,8 @@ public:
void Dump(Stream *strm, bool show_frame_index, bool show_fullpaths);
//------------------------------------------------------------------
- /// Print a description of this stack frame and/or the source context/assembly
- /// for this stack frame.
+ /// Print a description of this stack frame and/or the source
+ /// context/assembly for this stack frame.
///
/// @param[in] strm
/// The Stream to send the output to.
@@ -392,9 +393,9 @@ public:
bool show_unique = false, const char *frame_marker = nullptr);
//------------------------------------------------------------------
- /// Query whether this frame is a concrete frame on the call stack,
- /// or if it is an inlined frame derived from the debug information
- /// and presented by the debugger.
+ /// Query whether this frame is a concrete frame on the call stack, or if it
+ /// is an inlined frame derived from the debug information and presented by
+ /// the debugger.
///
/// @return
/// true if this is an inlined frame.
@@ -402,7 +403,8 @@ public:
bool IsInlined();
//------------------------------------------------------------------
- /// Query this frame to find what frame it is in this Thread's StackFrameList.
+ /// Query this frame to find what frame it is in this Thread's
+ /// StackFrameList.
///
/// @return
/// StackFrame index 0 indicates the currently-executing function. Inline
@@ -411,8 +413,8 @@ public:
uint32_t GetFrameIndex() const;
//------------------------------------------------------------------
- /// Query this frame to find what frame it is in this Thread's StackFrameList,
- /// not counting inlined frames.
+ /// Query this frame to find what frame it is in this Thread's
+ /// StackFrameList, not counting inlined frames.
///
/// @return
/// StackFrame index 0 indicates the currently-executing function. Inline
@@ -442,8 +444,7 @@ public:
//------------------------------------------------------------------
/// Add an arbitrary Variable object (e.g. one that specifics a global or
- /// static)
- /// to a StackFrame's list of ValueObjects.
+ /// static) to a StackFrame's list of ValueObjects.
///
/// @params [in] variable_sp
/// The Variable to base this ValueObject on
@@ -460,8 +461,8 @@ public:
lldb::DynamicValueType use_dynamic);
//------------------------------------------------------------------
- /// Query this frame to determine what the default language should be
- /// when parsing expressions given the execution context.
+ /// Query this frame to determine what the default language should be when
+ /// parsing expressions given the execution context.
///
/// @return
/// The language of the frame if known, else lldb::eLanguageTypeUnknown.
@@ -469,8 +470,7 @@ public:
lldb::LanguageType GetLanguage();
// similar to GetLanguage(), but is allowed to take a potentially incorrect
- // guess
- // if exact information is not available
+ // guess if exact information is not available
lldb::LanguageType GuessLanguage();
//------------------------------------------------------------------
@@ -488,8 +488,8 @@ public:
//------------------------------------------------------------------
/// Attempt to reconstruct the ValueObject for the address contained in a
- /// given register plus an offset. The ExpressionPath should indicate how to
- /// get to this value using "frame variable."
+ /// given register plus an offset. The ExpressionPath should indicate how
+ /// to get to this value using "frame variable."
///
/// @params [in] reg
/// The name of the register.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h b/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h
index 7b7e9e5187b6..51e51a6c0741 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h
@@ -81,20 +81,20 @@ protected:
lldb::addr_t
m_pc; // The pc value for the function/symbol for this frame. This will
// only get used if the symbol scope is nullptr (the code where we are
- // stopped is not represented by any function or symbol in any
- // shared library).
+ // stopped is not represented by any function or symbol in any shared
+ // library).
lldb::addr_t m_cfa; // The call frame address (stack pointer) value
// at the beginning of the function that uniquely
- // identifies this frame (along with m_symbol_scope below)
+ // identifies this frame (along with m_symbol_scope
+ // below)
SymbolContextScope *
m_symbol_scope; // If nullptr, there is no block or symbol for this frame.
// If not nullptr, this will either be the scope for the
- // lexical block for the frame, or the scope
- // for the symbol. Symbol context scopes are
- // always be unique pointers since the are part
- // of the Block and Symbol objects and can easily
- // be used to tell if a stack ID is the same as
- // another.
+ // lexical block for the frame, or the scope for the
+ // symbol. Symbol context scopes are always be unique
+ // pointers since the are part of the Block and Symbol
+ // objects and can easily be used to tell if a stack ID
+ // is the same as another.
};
bool operator==(const StackID &lhs, const StackID &rhs);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h b/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h
index c99877cbd8ab..b25bf7dd3d5d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h
@@ -40,12 +40,10 @@ public:
lldb::ThreadSP GetThread() const { return m_thread_wp.lock(); }
- // The value of the StopInfo depends on the StopReason.
- // StopReason Meaning
- // ----------------------------------------------
- // eStopReasonBreakpoint BreakpointSiteID
- // eStopReasonSignal Signal number
- // eStopReasonWatchpoint WatchpointLocationID
+ // The value of the StopInfo depends on the StopReason. StopReason
+ // Meaning ----------------------------------------------
+ // eStopReasonBreakpoint BreakpointSiteID eStopReasonSignal
+ // Signal number eStopReasonWatchpoint WatchpointLocationID
// eStopReasonPlanComplete No significance
uint64_t GetValue() const { return m_value; }
@@ -53,10 +51,8 @@ public:
virtual lldb::StopReason GetStopReason() const = 0;
// ShouldStopSynchronous will get called before any thread plans are
- // consulted, and if it says we should
- // resume the target, then we will just immediately resume. This should not
- // run any code in or resume the
- // target.
+ // consulted, and if it says we should resume the target, then we will just
+ // immediately resume. This should not run any code in or resume the target.
virtual bool ShouldStopSynchronous(Event *event_ptr) { return true; }
@@ -88,14 +84,11 @@ public:
virtual bool IsValidForOperatingSystemThread(Thread &thread) { return true; }
// Sometimes the thread plan logic will know that it wants a given stop to
- // stop or not,
- // regardless of what the ordinary logic for that StopInfo would dictate. The
- // main example
- // of this is the ThreadPlanCallFunction, which for instance knows - based on
- // how that particular
- // expression was executed - whether it wants all breakpoints to auto-continue
- // or not.
- // Use OverrideShouldStop on the StopInfo to implement this.
+ // stop or not, regardless of what the ordinary logic for that StopInfo would
+ // dictate. The main example of this is the ThreadPlanCallFunction, which
+ // for instance knows - based on how that particular expression was executed
+ // - whether it wants all breakpoints to auto-continue or not. Use
+ // OverrideShouldStop on the StopInfo to implement this.
void OverrideShouldStop(bool override_value) {
m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo;
@@ -159,15 +152,13 @@ protected:
virtual bool DoShouldNotify(Event *event_ptr) { return false; }
- // Stop the thread by default. Subclasses can override this to allow
- // the thread to continue if desired. The ShouldStop method should not do
- // anything
- // that might run code. If you need to run code when deciding whether to stop
- // at this StopInfo, that must be done in the PerformAction.
+ // Stop the thread by default. Subclasses can override this to allow the
+ // thread to continue if desired. The ShouldStop method should not do
+ // anything that might run code. If you need to run code when deciding
+ // whether to stop at this StopInfo, that must be done in the PerformAction.
// The PerformAction will always get called before the ShouldStop. This is
- // done by the
- // ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs to consult
- // this later on.
+ // done by the ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs
+ // to consult this later on.
virtual bool ShouldStop(Event *event_ptr) { return true; }
//------------------------------------------------------------------
@@ -185,14 +176,13 @@ protected:
StructuredData::ObjectSP
m_extended_info; // The extended info for this stop info
- // This determines whether the target has run since this stop info.
- // N.B. running to evaluate a user expression does not count.
+ // This determines whether the target has run since this stop info. N.B.
+ // running to evaluate a user expression does not count.
bool HasTargetRunSinceMe();
// MakeStopInfoValid is necessary to allow saved stop infos to resurrect
- // themselves as valid.
- // It should only be used by Thread::RestoreThreadStateFromCheckpoint and to
- // make sure the one-step
+ // themselves as valid. It should only be used by
+ // Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step
// needed for before-the-fact watchpoints does not prevent us from stopping
void MakeStopInfoValid();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h
index 8c6c2ece967f..06cc3ec2d012 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h
@@ -29,20 +29,20 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class SystemRuntime SystemRuntime.h "lldb/Target/SystemRuntime.h"
-/// @brief A plug-in interface definition class for system runtimes.
+/// A plug-in interface definition class for system runtimes.
///
/// The system runtime plugins can collect information from the system
-/// libraries during a Process' lifetime and provide information about
-/// how objects/threads were originated.
+/// libraries during a Process' lifetime and provide information about how
+/// objects/threads were originated.
///
-/// For instance, a system runtime plugin use a breakpoint when threads
-/// are created to record the backtrace of where that thread was created.
-/// Later, when backtracing the created thread, it could extend the backtrace
-/// to show where it was originally created from.
+/// For instance, a system runtime plugin use a breakpoint when threads are
+/// created to record the backtrace of where that thread was created. Later,
+/// when backtracing the created thread, it could extend the backtrace to show
+/// where it was originally created from.
///
-/// The plugin will insert its own breakpoint when Created and start collecting
-/// information. Later when it comes time to augment a Thread, it can be
-/// asked to provide that information.
+/// The plugin will insert its own breakpoint when Created and start
+/// collecting information. Later when it comes time to augment a Thread, it
+/// can be asked to provide that information.
///
//----------------------------------------------------------------------
@@ -51,9 +51,8 @@ public:
//------------------------------------------------------------------
/// Find a system runtime plugin for a given process.
///
- /// Scans the installed SystemRuntime plugins and tries to find
- /// an instance that can be used to track image changes in \a
- /// process.
+ /// Scans the installed SystemRuntime plugins and tries to find an instance
+ /// that can be used to track image changes in \a process.
///
/// @param[in] process
/// The process for which to try and locate a system runtime
@@ -69,60 +68,60 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// The destructor is virtual since this class is designed to be
- /// inherited by the plug-in instance.
+ /// The destructor is virtual since this class is designed to be inherited
+ /// by the plug-in instance.
//------------------------------------------------------------------
~SystemRuntime() override;
//------------------------------------------------------------------
/// Called after attaching to a process.
///
- /// Allow the SystemRuntime plugin to execute some code after attaching
- /// to a process.
+ /// Allow the SystemRuntime plugin to execute some code after attaching to a
+ /// process.
//------------------------------------------------------------------
virtual void DidAttach();
//------------------------------------------------------------------
/// Called after launching a process.
///
- /// Allow the SystemRuntime plugin to execute some code after launching
- /// a process.
+ /// Allow the SystemRuntime plugin to execute some code after launching a
+ /// process.
//------------------------------------------------------------------
virtual void DidLaunch();
//------------------------------------------------------------------
/// Called when modules have been loaded in the process.
///
- /// Allow the SystemRuntime plugin to enable logging features in the
- /// system runtime libraries.
+ /// Allow the SystemRuntime plugin to enable logging features in the system
+ /// runtime libraries.
//------------------------------------------------------------------
virtual void ModulesDidLoad(lldb_private::ModuleList &module_list);
//------------------------------------------------------------------
/// Called before detaching from a process.
///
- /// This will give a SystemRuntime plugin a chance to free any resources
- /// in the inferior process before we detach.
+ /// This will give a SystemRuntime plugin a chance to free any resources in
+ /// the inferior process before we detach.
//------------------------------------------------------------------
virtual void Detach();
//------------------------------------------------------------------
- /// Return a list of thread origin extended backtraces that may
- /// be available.
+ /// Return a list of thread origin extended backtraces that may be
+ /// available.
///
/// A System Runtime may be able to provide a backtrace of when this
- /// thread was originally created. Furthermore, it may be able to
- /// provide that extended backtrace for different styles of creation.
- /// On a system with both pthreads and libdispatch, aka Grand Central
- /// Dispatch, queues, the system runtime may be able to provide the
- /// pthread creation of the thread and it may also be able to provide
- /// the backtrace of when this GCD queue work block was enqueued.
- /// The caller may request these different origins by name.
- ///
- /// The names will be provided in the order that they are most likely
- /// to be requested. For instance, a most natural order may be to
- /// request the GCD libdispatch queue origin. If there is none, then
- /// request the pthread origin.
+ /// thread was originally created. Furthermore, it may be able to provide
+ /// that extended backtrace for different styles of creation. On a system
+ /// with both pthreads and libdispatch, aka Grand Central Dispatch, queues,
+ /// the system runtime may be able to provide the pthread creation of the
+ /// thread and it may also be able to provide the backtrace of when this GCD
+ /// queue work block was enqueued. The caller may request these different
+ /// origins by name.
+ ///
+ /// The names will be provided in the order that they are most likely to be
+ /// requested. For instance, a most natural order may be to request the GCD
+ /// libdispatch queue origin. If there is none, then request the pthread
+ /// origin.
///
/// @return
/// A vector of ConstStrings with names like "pthread" or "libdispatch".
@@ -135,13 +134,12 @@ public:
/// Return a Thread which shows the origin of this thread's creation.
///
/// This likely returns a HistoryThread which shows how thread was
- /// originally created (e.g. "pthread" type), or how the work that
- /// is currently executing on it was originally enqueued (e.g.
- /// "libdispatch" type).
+ /// originally created (e.g. "pthread" type), or how the work that is
+ /// currently executing on it was originally enqueued (e.g. "libdispatch"
+ /// type).
///
- /// There may be a chain of thread-origins; it may be informative to
- /// the end user to query the returned ThreadSP for its origins as
- /// well.
+ /// There may be a chain of thread-origins; it may be informative to the end
+ /// user to query the returned ThreadSP for its origins as well.
///
/// @param [in] thread
/// The thread to examine.
@@ -168,8 +166,8 @@ public:
/// a libdispatch queue in the future, or it represents a function/block
/// that is currently executing on a thread.
///
- /// This method will report a thread backtrace of the function that
- /// enqueued it originally, if possible.
+ /// This method will report a thread backtrace of the function that enqueued
+ /// it originally, if possible.
///
/// @param [in] queue_item_sp
/// The QueueItem that we are getting an extended backtrace for.
@@ -189,10 +187,11 @@ public:
}
//------------------------------------------------------------------
- /// Populate the Process' QueueList with libdispatch / GCD queues that exist.
+ /// Populate the Process' QueueList with libdispatch / GCD queues that
+ /// exist.
///
- /// When process execution is paused, the SystemRuntime may be called to fill
- /// in the list of Queues that currently exist.
+ /// When process execution is paused, the SystemRuntime may be called to
+ /// fill in the list of Queues that currently exist.
///
/// @param [out] queue_list
/// This QueueList will be cleared, and any queues that currently exist
@@ -205,12 +204,10 @@ public:
/// Get the queue name for a thread given a thread's dispatch_qaddr.
///
/// On systems using libdispatch queues, a thread may be associated with a
- /// queue.
- /// There will be a call to get the thread's dispatch_qaddr. At the
- /// dispatch_qaddr
- /// we will find the address of this thread's dispatch_queue_t structure.
- /// Given the address of the dispatch_queue_t structure for a thread,
- /// get the queue name and return it.
+ /// queue. There will be a call to get the thread's dispatch_qaddr. At the
+ /// dispatch_qaddr we will find the address of this thread's
+ /// dispatch_queue_t structure. Given the address of the dispatch_queue_t
+ /// structure for a thread, get the queue name and return it.
///
/// @param [in] dispatch_qaddr
/// The address of the dispatch_qaddr pointer for this thread.
@@ -229,12 +226,10 @@ public:
/// dispatch_qaddr.
///
/// On systems using libdispatch queues, a thread may be associated with a
- /// queue.
- /// There will be a call to get the thread's dispatch_qaddr. At the
- /// dispatch_qaddr
- /// we will find the address of this thread's dispatch_queue_t structure.
- /// Given the address of the dispatch_queue_t structure for a thread,
- /// get the queue ID and return it.
+ /// queue. There will be a call to get the thread's dispatch_qaddr. At the
+ /// dispatch_qaddr we will find the address of this thread's
+ /// dispatch_queue_t structure. Given the address of the dispatch_queue_t
+ /// structure for a thread, get the queue ID and return it.
///
/// @param [in] dispatch_qaddr
/// The address of the dispatch_qaddr pointer for this thread.
@@ -252,10 +247,8 @@ public:
/// dispatch_qaddr.
///
/// On systems using libdispatch queues, a thread may be associated with a
- /// queue.
- /// There will be a call to get the thread's dispatch_qaddr.
- /// Given the thread's dispatch_qaddr, find the libdispatch_queue_t address
- /// and
+ /// queue. There will be a call to get the thread's dispatch_qaddr. Given
+ /// the thread's dispatch_qaddr, find the libdispatch_queue_t address and
/// return it.
///
/// @param [in] dispatch_qaddr
@@ -274,8 +267,8 @@ public:
/// Retrieve the Queue kind for the queue at a thread's dispatch_qaddr.
///
/// Retrieve the Queue kind - either eQueueKindSerial or
- /// eQueueKindConcurrent, indicating that this queue processes work
- /// items serially or concurrently.
+ /// eQueueKindConcurrent, indicating that this queue processes work items
+ /// serially or concurrently.
///
/// @return
/// The Queue kind, if it could be read, else eQueueKindUnknown.
@@ -288,8 +281,8 @@ public:
/// Get the pending work items for a libdispatch Queue
///
/// If this system/process is using libdispatch and the runtime can do so,
- /// retrieve the list of pending work items for the specified Queue and
- /// add it to the Queue.
+ /// retrieve the list of pending work items for the specified Queue and add
+ /// it to the Queue.
///
/// @param [in] queue
/// The queue of interest.
@@ -300,8 +293,8 @@ public:
/// Complete the fields in a QueueItem
///
/// PopulatePendingItemsForQueue() may not fill in all of the QueueItem
- /// details; when the remaining fields are needed, they will be
- /// fetched by call this method.
+ /// details; when the remaining fields are needed, they will be fetched by
+ /// call this method.
///
/// @param [in] queue_item
/// The QueueItem that we will be completing.
@@ -316,8 +309,7 @@ public:
//------------------------------------------------------------------
/// Add key-value pairs to the StructuredData dictionary object with
/// information debugserver may need when constructing the
- /// jThreadExtendedInfo
- /// packet.
+ /// jThreadExtendedInfo packet.
///
/// @param [out] dict
/// Dictionary to which key-value pairs should be added; they will
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Target.h b/contrib/llvm/tools/lldb/include/lldb/Target/Target.h
index a5d200069810..75af8e80d2e5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Target.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Target.h
@@ -35,6 +35,7 @@
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/SectionLoadHistory.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-public.h"
@@ -102,9 +103,6 @@ public:
const char *GetDisassemblyFlavor() const;
- // void
- // SetDisassemblyFlavor(const char *flavor);
-
InlineStrategy GetInlineStrategy() const;
llvm::StringRef GetArg0() const;
@@ -115,9 +113,8 @@ public:
void SetRunArguments(const Args &args);
- size_t GetEnvironmentAsArgs(Args &env) const;
-
- void SetEnvironmentFromArgs(const Args &env);
+ Environment GetEnvironment() const;
+ void SetEnvironment(Environment env);
bool GetSkipPrologue() const;
@@ -235,8 +232,8 @@ class EvaluateExpressionOptions {
public:
// MSVC has a bug here that reports C4268: 'const' static/global data
// initialized with compiler generated default constructor fills the object
-// with zeros.
-// Confirmed that MSVC is *not* zero-initializing, it's just a bogus warning.
+// with zeros. Confirmed that MSVC is *not* zero-initializing, it's just a
+// bogus warning.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4268)
@@ -353,8 +350,7 @@ public:
}
// Allows the expression contents to be remapped to point to the specified
- // file and line
- // using #line directives.
+ // file and line using #line directives.
void SetPoundLine(const char *path, uint32_t line) const {
if (path && path[0]) {
m_pound_line_file = path;
@@ -401,8 +397,8 @@ private:
Timeout<std::micro> m_one_thread_timeout = llvm::None;
lldb::ExpressionCancelCallback m_cancel_callback = nullptr;
void *m_cancel_callback_baton = nullptr;
- // If m_pound_line_file is not empty and m_pound_line_line is non-zero,
- // use #line %u "%s" before the expression content to remap where the source
+ // If m_pound_line_file is not empty and m_pound_line_line is non-zero, use
+ // #line %u "%s" before the expression content to remap where the source
// originates
mutable std::string m_pound_line_file;
mutable uint32_t m_pound_line_line;
@@ -490,9 +486,6 @@ public:
static void SetDefaultArchitecture(const ArchSpec &arch);
- // void
- // UpdateInstanceName ();
-
lldb::ModuleSP GetSharedModule(const ModuleSpec &module_spec,
Status *error_ptr = nullptr);
@@ -563,9 +556,8 @@ public:
LazyBool move_to_nearest_code);
// Use this to create breakpoint that matches regex against the source lines
- // in files given in source_file_list:
- // If function_names is non-empty, also filter by function after the matches
- // are made.
+ // in files given in source_file_list: If function_names is non-empty, also
+ // filter by function after the matches are made.
lldb::BreakpointSP CreateSourceRegexBreakpoint(
const FileSpecList *containingModules,
const FileSpecList *source_file_list,
@@ -589,8 +581,8 @@ public:
// Use this to create a function breakpoint by regexp in
// containingModule/containingSourceFiles, or all modules if it is nullptr
- // When "skip_prologue is set to eLazyBoolCalculate, we use the current target
- // setting, else we use the values passed in
+ // When "skip_prologue is set to eLazyBoolCalculate, we use the current
+ // target setting, else we use the values passed in
lldb::BreakpointSP CreateFuncRegexBreakpoint(
const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles, RegularExpression &func_regexp,
@@ -598,10 +590,10 @@ public:
bool internal, bool request_hardware);
// Use this to create a function breakpoint by name in containingModule, or
- // all modules if it is nullptr
- // When "skip_prologue is set to eLazyBoolCalculate, we use the current target
- // setting, else we use the values passed in.
- // func_name_type_mask is or'ed values from the FunctionNameType enum.
+ // all modules if it is nullptr When "skip_prologue is set to
+ // eLazyBoolCalculate, we use the current target setting, else we use the
+ // values passed in. func_name_type_mask is or'ed values from the
+ // FunctionNameType enum.
lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const char *func_name,
@@ -618,11 +610,10 @@ public:
Status *additional_args_error = nullptr);
// This is the same as the func_name breakpoint except that you can specify a
- // vector of names. This is cheaper
- // than a regular expression breakpoint in the case where you just want to set
- // a breakpoint on a set of names
- // you already know.
- // func_name_type_mask is or'ed values from the FunctionNameType enum.
+ // vector of names. This is cheaper than a regular expression breakpoint in
+ // the case where you just want to set a breakpoint on a set of names you
+ // already know. func_name_type_mask is or'ed values from the
+ // FunctionNameType enum.
lldb::BreakpointSP
CreateBreakpoint(const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
@@ -741,14 +732,14 @@ public:
/// Take \a load_addr and potentially add any address bits that are
/// needed to make the address callable. For ARM this can set bit
/// zero (if it already isn't) if \a load_addr is a thumb function.
- /// If \a addr_class is set to eAddressClassInvalid, then the address
+ /// If \a addr_class is set to AddressClass::eInvalid, then the address
/// adjustment will always happen. If it is set to an address class
/// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
/// returned.
//------------------------------------------------------------------
lldb::addr_t GetCallableLoadAddress(
lldb::addr_t load_addr,
- lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
+ AddressClass addr_class = AddressClass::eInvalid) const;
//------------------------------------------------------------------
/// Get \a load_addr as an opcode for this target.
@@ -757,22 +748,20 @@ public:
/// needed to make the address point to an opcode. For ARM this can
/// clear bit zero (if it already isn't) if \a load_addr is a
/// thumb function and load_addr is in code.
- /// If \a addr_class is set to eAddressClassInvalid, then the address
+ /// If \a addr_class is set to AddressClass::eInvalid, then the address
/// adjustment will always happen. If it is set to an address class
/// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
/// returned.
//------------------------------------------------------------------
lldb::addr_t GetOpcodeLoadAddress(
lldb::addr_t load_addr,
- lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
-
- // Get load_addr as breakable load address for this target.
- // Take a addr and check if for any reason there is a better address than this
- // to put a breakpoint on.
- // If there is then return that address.
- // For MIPS, if instruction at addr is a delay slot instruction then this
- // method will find the address of its
- // previous instruction and return that address.
+ AddressClass addr_class = AddressClass::eInvalid) const;
+
+ // Get load_addr as breakable load address for this target. Take a addr and
+ // check if for any reason there is a better address than this to put a
+ // breakpoint on. If there is then return that address. For MIPS, if
+ // instruction at addr is a delay slot instruction then this method will find
+ // the address of its previous instruction and return that address.
lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr);
void ModulesDidLoad(ModuleList &module_list);
@@ -949,7 +938,7 @@ public:
bool MergeArchitecture(const ArchSpec &arch_spec);
- Architecture *GetArchitecturePlugin() { return m_arch.GetPlugin(); }
+ Architecture *GetArchitecturePlugin() const { return m_arch.GetPlugin(); }
Debugger &GetDebugger() { return m_debugger; }
@@ -957,12 +946,12 @@ public:
Status &error);
// Reading memory through the target allows us to skip going to the process
- // for reading memory if possible and it allows us to try and read from
- // any constant sections in our object files on disk. If you always want
- // live program memory, read straight from the process. If you possibly
- // want to read from const sections in object files, read from the target.
- // This version of ReadMemory will try and read memory from the process
- // if the process is alive. The order is:
+ // for reading memory if possible and it allows us to try and read from any
+ // constant sections in our object files on disk. If you always want live
+ // program memory, read straight from the process. If you possibly want to
+ // read from const sections in object files, read from the target. This
+ // version of ReadMemory will try and read memory from the process if the
+ // process is alive. The order is:
// 1 - if (prefer_file_cache == true) then read from object file cache
// 2 - if there is a valid process, try and read from its memory
// 3 - if (prefer_file_cache == false) then read from object file cache
@@ -993,13 +982,6 @@ public:
return m_section_load_history.GetCurrentSectionLoadList();
}
- // const SectionLoadList&
- // GetSectionLoadList() const
- // {
- // return const_cast<SectionLoadHistory
- // *>(&m_section_load_history)->GetCurrentSectionLoadList();
- // }
-
static Target *GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr,
const SymbolContext *sc_ptr);
@@ -1025,9 +1007,8 @@ public:
PersistentExpressionState *
GetPersistentExpressionStateForLanguage(lldb::LanguageType language);
- // Creates a UserExpression for the given language, the rest of the parameters
- // have the
- // same meaning as for the UserExpression constructor.
+ // Creates a UserExpression for the given language, the rest of the
+ // parameters have the same meaning as for the UserExpression constructor.
// Returns a new-ed object which the caller owns.
UserExpression *GetUserExpressionForLanguage(
@@ -1035,10 +1016,9 @@ public:
Expression::ResultType desired_type,
const EvaluateExpressionOptions &options, Status &error);
- // Creates a FunctionCaller for the given language, the rest of the parameters
- // have the
- // same meaning as for the FunctionCaller constructor. Since a FunctionCaller
- // can't be
+ // Creates a FunctionCaller for the given language, the rest of the
+ // parameters have the same meaning as for the FunctionCaller constructor.
+ // Since a FunctionCaller can't be
// IR Interpreted, it makes no sense to call this with an
// ExecutionContextScope that lacks
// a Process.
@@ -1051,8 +1031,7 @@ public:
const char *name, Status &error);
// Creates a UtilityFunction for the given language, the rest of the
- // parameters have the
- // same meaning as for the UtilityFunction constructor.
+ // parameters have the same meaning as for the UtilityFunction constructor.
// Returns a new-ed object which the caller owns.
UtilityFunction *GetUtilityFunctionForLanguage(const char *expr,
@@ -1065,8 +1044,8 @@ public:
lldb::ClangASTImporterSP GetClangASTImporter();
//----------------------------------------------------------------------
- // Install any files through the platform that need be to installed
- // prior to launching or attaching.
+ // Install any files through the platform that need be to installed prior to
+ // launching or attaching.
//----------------------------------------------------------------------
Status Install(ProcessLaunchInfo *launch_info);
@@ -1091,10 +1070,10 @@ public:
void ClearAllLoadedSections();
// Since expressions results can persist beyond the lifetime of a process,
- // and the const expression results are available after a process is gone,
- // we provide a way for expressions to be evaluated from the Target itself.
- // If an expression is going to be run, then it should have a frame filled
- // in in th execution context.
+ // and the const expression results are available after a process is gone, we
+ // provide a way for expressions to be evaluated from the Target itself. If
+ // an expression is going to be run, then it should have a frame filled in in
+ // th execution context.
lldb::ExpressionResults EvaluateExpression(
llvm::StringRef expression, ExecutionContextScope *exe_scope,
lldb::ValueObjectSP &result_valobj_sp,
@@ -1103,6 +1082,11 @@ public:
lldb::ExpressionVariableSP GetPersistentVariable(const ConstString &name);
+ /// Return the next available number for numbered persistent variables.
+ unsigned GetNextPersistentVariableIndex() {
+ return m_next_persistent_variable_index++;
+ }
+
lldb::addr_t GetPersistentSymbol(const ConstString &name);
//------------------------------------------------------------------
@@ -1148,17 +1132,15 @@ public:
bool m_active;
// Use CreateStopHook to make a new empty stop hook. The GetCommandPointer
- // and fill it with commands,
- // and SetSpecifier to set the specifier shared pointer (can be null, that
- // will match anything.)
+ // and fill it with commands, and SetSpecifier to set the specifier shared
+ // pointer (can be null, that will match anything.)
StopHook(lldb::TargetSP target_sp, lldb::user_id_t uid);
friend class Target;
};
typedef std::shared_ptr<StopHook> StopHookSP;
- // Add an empty stop hook to the Target's stop hook list, and returns a shared
- // pointer to it in new_hook.
- // Returns the id of the new hook.
+ // Add an empty stop hook to the Target's stop hook list, and returns a
+ // shared pointer to it in new_hook. Returns the id of the new hook.
StopHookSP CreateStopHook();
void RunStopHooks();
@@ -1173,9 +1155,6 @@ public:
bool GetSuppressStopHooks() { return m_suppress_stop_hooks; }
- // StopHookSP &
- // GetStopHookByIndex (size_t index);
- //
bool RemoveStopHookByID(lldb::user_id_t uid);
void RemoveAllStopHooks();
@@ -1275,9 +1254,9 @@ protected:
lldb::BreakpointSP m_last_created_breakpoint;
WatchpointList m_watchpoint_list;
lldb::WatchpointSP m_last_created_watchpoint;
- // We want to tightly control the process destruction process so
- // we can correctly tear down everything that we need to, so the only
- // class that knows about the process lifespan is this target class.
+ // We want to tightly control the process destruction process so we can
+ // correctly tear down everything that we need to, so the only class that
+ // knows about the process lifespan is this target class.
lldb::ProcessSP m_process_sp;
lldb::SearchFilterSP m_search_filter_sp;
PathMappingList m_image_search_paths;
@@ -1297,10 +1276,33 @@ protected:
bool m_valid;
bool m_suppress_stop_hooks;
bool m_is_dummy_target;
+ unsigned m_next_persistent_variable_index = 0;
static void ImageSearchPathsChanged(const PathMappingList &path_list,
void *baton);
+ //------------------------------------------------------------------
+ // Utilities for `statistics` command.
+ //------------------------------------------------------------------
+private:
+ std::vector<uint32_t> m_stats_storage;
+ bool m_collecting_stats = false;
+
+public:
+ void SetCollectingStats(bool v) { m_collecting_stats = v; }
+
+ bool GetCollectingStats() { return m_collecting_stats; }
+
+ void IncrementStats(lldb_private::StatisticKind key) {
+ if (!GetCollectingStats())
+ return;
+ lldbassert(key < lldb_private::StatisticKind::StatisticMax &&
+ "invalid statistics!");
+ m_stats_storage[key] += 1;
+ }
+
+ std::vector<uint32_t> GetStatistics() { return m_stats_storage; }
+
private:
//------------------------------------------------------------------
/// Construct with optional file and arch.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h b/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h
index 1b0b6ef557e8..9ce73e0cbeff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h
@@ -214,8 +214,8 @@ public:
// This function is called on all the threads before "ShouldResume" and
// "WillResume" in case a thread needs to change its state before the
- // ThreadList polls all the threads to figure out which ones actually
- // will get to run and how.
+ // ThreadList polls all the threads to figure out which ones actually will
+ // get to run and how.
void SetupForResume();
// Do not override this function, it is for thread plan logic only
@@ -224,8 +224,8 @@ public:
// Override this to do platform specific tasks before resume.
virtual void WillResume(lldb::StateType resume_state) {}
- // This clears generic thread state after a resume. If you subclass this,
- // be sure to call it.
+ // This clears generic thread state after a resume. If you subclass this, be
+ // sure to call it.
virtual void DidResume();
// This notifies the thread when a private stop occurs.
@@ -244,14 +244,10 @@ public:
void Flush();
// Return whether this thread matches the specification in ThreadSpec. This
- // is a virtual
- // method because at some point we may extend the thread spec with a platform
- // specific
- // dictionary of attributes, which then only the platform specific Thread
- // implementation
- // would know how to match. For now, this just calls through to the
- // ThreadSpec's
- // ThreadPassesBasicTests method.
+ // is a virtual method because at some point we may extend the thread spec
+ // with a platform specific dictionary of attributes, which then only the
+ // platform specific Thread implementation would know how to match. For now,
+ // this just calls through to the ThreadSpec's ThreadPassesBasicTests method.
virtual bool MatchesSpec(const ThreadSpec *spec);
lldb::StopInfoSP GetStopInfo();
@@ -261,9 +257,8 @@ public:
bool StopInfoIsUpToDate() const;
// This sets the stop reason to a "blank" stop reason, so you can call
- // functions on the thread
- // without having the called function run with whatever stop reason you
- // stopped with.
+ // functions on the thread without having the called function run with
+ // whatever stop reason you stopped with.
void SetStopInfoToNothing();
bool ThreadStoppedForAReason();
@@ -492,16 +487,15 @@ public:
virtual void ClearBackingThread() {
// Subclasses can use this function if a thread is actually backed by
// another thread. This is currently used for the OperatingSystem plug-ins
- // where they might have a thread that is in memory, yet its registers
- // are available through the lldb_private::Thread subclass for the current
+ // where they might have a thread that is in memory, yet its registers are
+ // available through the lldb_private::Thread subclass for the current
// lldb_private::Process class. Since each time the process stops the
- // backing
- // threads for memory threads can change, we need a way to clear the backing
- // thread for all memory threads each time we stop.
+ // backing threads for memory threads can change, we need a way to clear
+ // the backing thread for all memory threads each time we stop.
}
- // If stop_format is true, this will be the form used when we print stop info.
- // If false, it will be the form we use for thread list and co.
+ // If stop_format is true, this will be the form used when we print stop
+ // info. If false, it will be the form we use for thread list and co.
void DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
bool stop_format);
@@ -607,30 +601,24 @@ public:
// Thread Plan Providers:
// This section provides the basic thread plans that the Process control
// machinery uses to run the target. ThreadPlan.h provides more details on
- // how this mechanism works.
- // The thread provides accessors to a set of plans that perform basic
- // operations.
- // The idea is that particular Platform plugins can override these methods to
- // provide the implementation of these basic operations appropriate to their
- // environment.
+ // how this mechanism works. The thread provides accessors to a set of plans
+ // that perform basic operations. The idea is that particular Platform
+ // plugins can override these methods to provide the implementation of these
+ // basic operations appropriate to their environment.
//
// NB: All the QueueThreadPlanXXX providers return Shared Pointers to
// Thread plans. This is useful so that you can modify the plans after
// creation in ways specific to that plan type. Also, it is often necessary
- // for
- // ThreadPlans that utilize other ThreadPlans to implement their task to keep
- // a shared
- // pointer to the sub-plan.
- // But besides that, the shared pointers should only be held onto by entities
- // who live no longer
- // than the thread containing the ThreadPlan.
+ // for ThreadPlans that utilize other ThreadPlans to implement their task to
+ // keep a shared pointer to the sub-plan. But besides that, the shared
+ // pointers should only be held onto by entities who live no longer than the
+ // thread containing the ThreadPlan.
// FIXME: If this becomes a problem, we can make a version that just returns a
// pointer,
// which it is clearly unsafe to hold onto, and a shared pointer version, and
- // only allow
- // ThreadPlan and Co. to use the latter. That is made more annoying to do
- // because there's
- // no elegant way to friend a method to all sub-classes of a given class.
+ // only allow ThreadPlan and Co. to use the latter. That is made more
+ // annoying to do because there's no elegant way to friend a method to all
+ // sub-classes of a given class.
//
//------------------------------------------------------------------
@@ -717,9 +705,8 @@ public:
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
// Helper function that takes a LineEntry to step, insted of an AddressRange.
- // This may combine multiple
- // LineEntries of the same source line number to step over a longer address
- // range in a single operation.
+ // This may combine multiple LineEntries of the same source line number to
+ // step over a longer address range in a single operation.
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
@@ -779,9 +766,8 @@ public:
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
// Helper function that takes a LineEntry to step, insted of an AddressRange.
- // This may combine multiple
- // LineEntries of the same source line number to step over a longer address
- // range in a single operation.
+ // This may combine multiple LineEntries of the same source line number to
+ // step over a longer address range in a single operation.
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
@@ -1115,23 +1101,22 @@ public:
void SetTracer(lldb::ThreadPlanTracerSP &tracer_sp);
//------------------------------------------------------------------
- // Get the thread index ID. The index ID that is guaranteed to not
- // be re-used by a process. They start at 1 and increase with each
- // new thread. This allows easy command line access by a unique ID
- // that is easier to type than the actual system thread ID.
+ // Get the thread index ID. The index ID that is guaranteed to not be re-used
+ // by a process. They start at 1 and increase with each new thread. This
+ // allows easy command line access by a unique ID that is easier to type than
+ // the actual system thread ID.
//------------------------------------------------------------------
uint32_t GetIndexID() const;
//------------------------------------------------------------------
// Get the originating thread's index ID.
- // In the case of an "extended" thread -- a thread which represents
- // the stack that enqueued/spawned work that is currently executing --
- // we need to provide the IndexID of the thread that actually did
- // this work. We don't want to just masquerade as that thread's IndexID
- // by using it in our own IndexID because that way leads to madness -
- // but the driver program which is iterating over extended threads
- // may ask for the OriginatingThreadID to display that information
- // to the user.
+ // In the case of an "extended" thread -- a thread which represents the stack
+ // that enqueued/spawned work that is currently executing -- we need to
+ // provide the IndexID of the thread that actually did this work. We don't
+ // want to just masquerade as that thread's IndexID by using it in our own
+ // IndexID because that way leads to madness - but the driver program which
+ // is iterating over extended threads may ask for the OriginatingThreadID to
+ // display that information to the user.
// Normal threads will return the same thing as GetIndexID();
//------------------------------------------------------------------
virtual uint32_t GetExtendedBacktraceOriginatingIndexID() {
@@ -1139,10 +1124,10 @@ public:
}
//------------------------------------------------------------------
- // The API ID is often the same as the Thread::GetID(), but not in
- // all cases. Thread::GetID() is the user visible thread ID that
- // clients would want to see. The API thread ID is the thread ID
- // that is used when sending data to/from the debugging protocol.
+ // The API ID is often the same as the Thread::GetID(), but not in all cases.
+ // Thread::GetID() is the user visible thread ID that clients would want to
+ // see. The API thread ID is the thread ID that is used when sending data
+ // to/from the debugging protocol.
//------------------------------------------------------------------
virtual lldb::user_id_t GetProtocolID() const { return GetID(); }
@@ -1171,9 +1156,9 @@ public:
uint32_t num_frames_with_source);
// We need a way to verify that even though we have a thread in a shared
- // pointer that the object itself is still valid. Currently this won't be
- // the case if DestroyThread() was called. DestroyThread is called when
- // a thread has been removed from the Process' thread list.
+ // pointer that the object itself is still valid. Currently this won't be the
+ // case if DestroyThread() was called. DestroyThread is called when a thread
+ // has been removed from the Process' thread list.
bool IsValid() const { return !m_destroy_called; }
// Sets and returns a valid stop info based on the process stop ID and the
@@ -1194,8 +1179,8 @@ public:
//----------------------------------------------------------------------
// Ask the thread subclass to set its stop info.
//
- // Thread subclasses should call Thread::SetStopInfo(...) with the
- // reason the thread stopped.
+ // Thread subclasses should call Thread::SetStopInfo(...) with the reason the
+ // thread stopped.
//
// @return
// True if Thread::SetStopInfo(...) was called, false otherwise.
@@ -1206,10 +1191,10 @@ public:
// Gets the temporary resume state for a thread.
//
// This value gets set in each thread by complex debugger logic in
- // Thread::ShouldResume() and an appropriate thread resume state will get
- // set in each thread every time the process is resumed prior to calling
- // Process::DoResume(). The lldb_private::Process subclass should adhere
- // to the thread resume state request which will be one of:
+ // Thread::ShouldResume() and an appropriate thread resume state will get set
+ // in each thread every time the process is resumed prior to calling
+ // Process::DoResume(). The lldb_private::Process subclass should adhere to
+ // the thread resume state request which will be one of:
//
// eStateRunning - thread will resume when process is resumed
// eStateStepping - thread should step 1 instruction and stop when process
@@ -1257,10 +1242,9 @@ protected:
friend class StackFrame;
friend class OperatingSystem;
- // This is necessary to make sure thread assets get destroyed while the thread
- // is still in good shape
- // to call virtual thread methods. This must be called by classes that derive
- // from Thread in their destructor.
+ // This is necessary to make sure thread assets get destroyed while the
+ // thread is still in good shape to call virtual thread methods. This must
+ // be called by classes that derive from Thread in their destructor.
virtual void DestroyThread();
void PushPlan(lldb::ThreadPlanSP &plan_sp);
@@ -1286,8 +1270,7 @@ protected:
virtual bool IsOperatingSystemPluginThread() const { return false; }
// Subclasses that have a way to get an extended info dictionary for this
- // thread should
- // fill
+ // thread should fill
virtual lldb_private::StructuredData::ObjectSP FetchThreadExtendedInfo() {
return StructuredData::ObjectSP();
}
@@ -1307,7 +1290,8 @@ protected:
lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread
uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is
// valid. Can use this so you know that
- // the thread's m_stop_info_sp is current and you don't have to fetch it again
+ // the thread's m_stop_info_sp is current and you don't have to fetch it
+ // again
uint32_t m_stop_info_override_stop_id; // The stop ID containing the last time
// the stop info was checked against
// the stop info override
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadCollection.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadCollection.h
index e3965b57e7a6..dd5e81c1af48 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadCollection.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadCollection.h
@@ -39,9 +39,9 @@ public:
void InsertThread(const lldb::ThreadSP &thread_sp, uint32_t idx);
- // Note that "idx" is not the same as the "thread_index". It is a zero
- // based index to accessing the current threads, whereas "thread_index"
- // is a unique index assigned
+ // Note that "idx" is not the same as the "thread_index". It is a zero based
+ // index to accessing the current threads, whereas "thread_index" is a unique
+ // index assigned
lldb::ThreadSP GetThreadAtIndex(uint32_t idx);
virtual ThreadIterable Threads() {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h
index 2ebcd0b0e2c9..6285cb1e0fb4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h
@@ -43,9 +43,8 @@ public:
lldb::ThreadSP GetSelectedThread();
// Manage the thread to use for running expressions. This is usually the
- // Selected thread,
- // but sometimes (e.g. when evaluating breakpoint conditions & stop hooks) it
- // isn't.
+ // Selected thread, but sometimes (e.g. when evaluating breakpoint conditions
+ // & stop hooks) it isn't.
class ExpressionExecutionThreadPusher {
public:
ExpressionExecutionThreadPusher(ThreadList &thread_list, lldb::tid_t tid)
@@ -83,9 +82,9 @@ public:
void Destroy();
- // Note that "idx" is not the same as the "thread_index". It is a zero
- // based index to accessing the current threads, whereas "thread_index"
- // is a unique index assigned
+ // Note that "idx" is not the same as the "thread_index". It is a zero based
+ // index to accessing the current threads, whereas "thread_index" is a unique
+ // index assigned
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update = true);
lldb::ThreadSP FindThreadByID(lldb::tid_t tid, bool can_update = true);
@@ -102,6 +101,8 @@ public:
lldb::ThreadSP GetThreadSPForThreadPtr(Thread *thread_ptr);
+ lldb::ThreadSP GetBackingThread(const lldb::ThreadSP &real_thread);
+
bool ShouldStop(Event *event_ptr);
Vote ShouldReportStop(Event *event_ptr);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h
index acc63ffe562b..7591fa9c9d07 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h
@@ -340,9 +340,8 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
public:
typedef enum { eAllThreads, eSomeThreads, eThisThread } ThreadScope;
- // We use these enums so that we can cast a base thread plan to it's real type
- // without having to resort
- // to dynamic casting.
+ // We use these enums so that we can cast a base thread plan to it's real
+ // type without having to resort to dynamic casting.
typedef enum {
eKindGeneric,
eKindNull,
@@ -432,9 +431,8 @@ public:
virtual bool ShouldAutoContinue(Event *event_ptr) { return false; }
- // Whether a "stop class" event should be reported to the "outside world". In
- // general
- // if a thread plan is active, events should not be reported.
+ // Whether a "stop class" event should be reported to the "outside world".
+ // In general if a thread plan is active, events should not be reported.
virtual Vote ShouldReportStop(Event *event_ptr);
@@ -445,8 +443,7 @@ public:
virtual bool StopOthers();
// This is the wrapper for DoWillResume that does generic ThreadPlan logic,
- // then
- // calls DoWillResume.
+ // then calls DoWillResume.
bool WillResume(lldb::StateType resume_state, bool current_plan);
virtual bool WillStop() = 0;
@@ -468,8 +465,8 @@ public:
virtual bool MischiefManaged();
virtual void ThreadDestroyed() {
- // Any cleanup that a plan might want to do in case the thread goes away
- // in the middle of the plan being queued on a thread can be done here.
+ // Any cleanup that a plan might want to do in case the thread goes away in
+ // the middle of the plan being queued on a thread can be done here.
}
bool GetPrivate() { return m_plan_private; }
@@ -509,39 +506,35 @@ public:
}
// Some thread plans hide away the actual stop info which caused any
- // particular stop. For
- // instance the ThreadPlanCallFunction restores the original stop reason so
- // that stopping and
- // calling a few functions won't lose the history of the run.
- // This call can be implemented to get you back to the real stop info.
+ // particular stop. For instance the ThreadPlanCallFunction restores the
+ // original stop reason so that stopping and calling a few functions won't
+ // lose the history of the run. This call can be implemented to get you back
+ // to the real stop info.
virtual lldb::StopInfoSP GetRealStopInfo() { return m_thread.GetStopInfo(); }
// If the completion of the thread plan stepped out of a function, the return
- // value of the function
- // might have been captured by the thread plan (currently only
- // ThreadPlanStepOut does this.)
- // If so, the ReturnValueObject can be retrieved from here.
+ // value of the function might have been captured by the thread plan
+ // (currently only ThreadPlanStepOut does this.) If so, the ReturnValueObject
+ // can be retrieved from here.
virtual lldb::ValueObjectSP GetReturnValueObject() {
return lldb::ValueObjectSP();
}
// If the thread plan managing the evaluation of a user expression lives
- // longer than the command
- // that instigated the expression (generally because the expression evaluation
- // hit a breakpoint, and
- // the user regained control at that point) a subsequent process control
- // command step/continue/etc. might
- // complete the expression evaluations. If so, the result of the expression
- // evaluation will show up here.
+ // longer than the command that instigated the expression (generally because
+ // the expression evaluation hit a breakpoint, and the user regained control
+ // at that point) a subsequent process control command step/continue/etc.
+ // might complete the expression evaluations. If so, the result of the
+ // expression evaluation will show up here.
virtual lldb::ExpressionVariableSP GetExpressionVariable() {
return lldb::ExpressionVariableSP();
}
- // If a thread plan stores the state before it was run, then you might
- // want to restore the state when it is done. This will do that job.
- // This is mostly useful for artificial plans like CallFunction plans.
+ // If a thread plan stores the state before it was run, then you might want
+ // to restore the state when it is done. This will do that job. This is
+ // mostly useful for artificial plans like CallFunction plans.
virtual bool RestoreThreadState() {
// Nothing to do in general.
@@ -585,8 +578,7 @@ protected:
ThreadPlan *GetPreviousPlan() { return m_thread.GetPreviousPlan(this); }
// This forwards the private Thread::GetPrivateStopInfo which is generally
- // what
- // ThreadPlan's need to know.
+ // what ThreadPlan's need to know.
lldb::StopInfoSP GetPrivateStopInfo() {
return m_thread.GetPrivateStopInfo();
@@ -638,10 +630,10 @@ private:
//----------------------------------------------------------------------
// ThreadPlanNull:
-// Threads are assumed to always have at least one plan on the plan stack.
-// This is put on the plan stack when a thread is destroyed so that if you
-// accidentally access a thread after it is destroyed you won't crash.
-// But asking questions of the ThreadPlanNull is definitely an error.
+// Threads are assumed to always have at least one plan on the plan stack. This
+// is put on the plan stack when a thread is destroyed so that if you
+// accidentally access a thread after it is destroyed you won't crash. But
+// asking questions of the ThreadPlanNull is definitely an error.
//----------------------------------------------------------------------
class ThreadPlanNull : public ThreadPlan {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h
index 1c75b0a3645c..56bfc819320c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h
@@ -24,9 +24,8 @@ namespace lldb_private {
class ThreadPlanCallFunction : public ThreadPlan {
// Create a thread plan to call a function at the address passed in the
- // "function"
- // argument. If you plan to call GetReturnValueObject, then pass in the
- // return type, otherwise just pass in an invalid CompilerType.
+ // "function" argument. If you plan to call GetReturnValueObject, then pass
+ // in the return type, otherwise just pass in an invalid CompilerType.
public:
ThreadPlanCallFunction(Thread &thread, const Address &function,
const CompilerType &return_type,
@@ -69,27 +68,23 @@ public:
return m_return_valobj_sp;
}
- // Return the stack pointer that the function received
- // on entry. Any stack address below this should be
- // considered invalid after the function has been
- // cleaned up.
+ // Return the stack pointer that the function received on entry. Any stack
+ // address below this should be considered invalid after the function has
+ // been cleaned up.
lldb::addr_t GetFunctionStackPointer() { return m_function_sp; }
- // Classes that derive from FunctionCaller, and implement
- // their own WillPop methods should call this so that the
- // thread state gets restored if the plan gets discarded.
+ // Classes that derive from FunctionCaller, and implement their own WillPop
+ // methods should call this so that the thread state gets restored if the
+ // plan gets discarded.
void WillPop() override;
// If the thread plan stops mid-course, this will be the stop reason that
- // interrupted us.
- // Once DoTakedown is called, this will be the real stop reason at the end of
- // the function call.
- // If it hasn't been set for one or the other of these reasons, we'll return
- // the PrivateStopReason.
- // This is needed because we want the CallFunction thread plans not to show up
- // as the stop reason.
- // But if something bad goes wrong, it is nice to be able to tell the user
- // what really happened.
+ // interrupted us. Once DoTakedown is called, this will be the real stop
+ // reason at the end of the function call. If it hasn't been set for one or
+ // the other of these reasons, we'll return the PrivateStopReason. This is
+ // needed because we want the CallFunction thread plans not to show up as the
+ // stop reason. But if something bad goes wrong, it is nice to be able to
+ // tell the user what really happened.
lldb::StopInfoSP GetRealStopInfo() override {
if (m_real_stop_info_sp)
@@ -140,9 +135,9 @@ protected:
Thread::ThreadStateCheckpoint m_stored_thread_state;
lldb::StopInfoSP
m_real_stop_info_sp; // In general we want to hide call function
- // thread plans, but for reporting purposes,
- // it's nice to know the real stop reason.
- // This gets set in DoTakedown.
+ // thread plans, but for reporting purposes, it's
+ // nice to know the real stop reason. This gets set
+ // in DoTakedown.
StreamString m_constructor_errors;
lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer,
// use the ABI to extract values when
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
index 1c67ddd5cdda..d58f7f050dbe 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
@@ -27,11 +27,9 @@ namespace lldb_private {
class ThreadPlanCallFunctionUsingABI : public ThreadPlanCallFunction {
// Create a thread plan to call a function at the address passed in the
- // "function"
- // argument, this function is executed using register manipulation instead of
- // JIT.
- // Class derives from ThreadPlanCallFunction and differs by calling a
- // alternative
+ // "function" argument, this function is executed using register manipulation
+ // instead of JIT. Class derives from ThreadPlanCallFunction and differs by
+ // calling a alternative
// ABI interface ABI::PrepareTrivialCall() which provides more detailed
// information.
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
index 60c0e3866707..030d5e434bd9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
@@ -19,20 +19,16 @@
namespace lldb_private {
// This is an interface that ThreadPlans can adopt to allow flexible
-// modifications of the behavior
-// when a thread plan comes to a place where it would ordinarily stop. If such
-// modification makes
-// sense for your plan, inherit from this class, and when you would be about to
-// stop (in your ShouldStop
-// method), call InvokeShouldStopHereCallback, passing in the frame comparison
-// between where the step operation
-// started and where you arrived. If it returns true, then QueueStepOutFromHere
-// will queue the plan
-// to execute instead of stopping.
+// modifications of the behavior when a thread plan comes to a place where it
+// would ordinarily stop. If such modification makes sense for your plan,
+// inherit from this class, and when you would be about to stop (in your
+// ShouldStop method), call InvokeShouldStopHereCallback, passing in the frame
+// comparison between where the step operation started and where you arrived.
+// If it returns true, then QueueStepOutFromHere will queue the plan to execute
+// instead of stopping.
//
// The classic example of the use of this is ThreadPlanStepInRange not stopping
-// in frames that have
-// no debug information.
+// in frames that have no debug information.
//
// This class also defines a set of flags to control general aspects of this
// "ShouldStop" behavior.
@@ -82,11 +78,9 @@ public:
virtual ~ThreadPlanShouldStopHere();
// Set the ShouldStopHere callbacks. Pass in null to clear them and have no
- // special behavior (though you
- // can also call ClearShouldStopHereCallbacks for that purpose. If you pass
- // in a valid pointer, it will
- // adopt the non-null fields, and any null fields will be set to the default
- // values.
+ // special behavior (though you can also call ClearShouldStopHereCallbacks
+ // for that purpose. If you pass in a valid pointer, it will adopt the non-
+ // null fields, and any null fields will be set to the default values.
void
SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks *callbacks,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
index 969c008f67d1..e799ec5a44ff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
@@ -31,6 +31,7 @@ public:
bool StopOthers() override;
lldb::StateType GetPlanRunState() override;
bool WillStop() override;
+ void WillPop() override;
bool MischiefManaged() override;
void ThreadDestroyed() override;
void SetAutoContinue(bool do_it);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h
index ffb27d02e2d0..65bc1671cb1e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h
@@ -58,10 +58,9 @@ protected:
size_t &insn_offset);
// Pushes a plan to proceed through the next section of instructions in the
- // range - usually just a RunToAddress
- // plan to run to the next branch. Returns true if it pushed such a plan. If
- // there was no available 'quick run'
- // plan, then just single step.
+ // range - usually just a RunToAddress plan to run to the next branch.
+ // Returns true if it pushed such a plan. If there was no available 'quick
+ // run' plan, then just single step.
bool SetNextBranchBreakpoint();
void ClearNextBranchBreakpoint();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h b/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h
index a209f3549aed..7ec683585f8e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h
@@ -63,8 +63,7 @@ public:
// These provide an iterator through the signals available on this system.
// Call GetFirstSignalNumber to get the first entry, then iterate on
- // GetNextSignalNumber
- // till you get back LLDB_INVALID_SIGNAL_NUMBER.
+ // GetNextSignalNumber till you get back LLDB_INVALID_SIGNAL_NUMBER.
int32_t GetFirstSignalNumber() const;
int32_t GetNextSignalNumber(int32_t current_signal) const;
@@ -76,13 +75,10 @@ public:
ConstString GetShortName(ConstString name) const;
// We assume that the elements of this object are constant once it is
- // constructed,
- // since a process should never need to add or remove symbols as it runs. So
- // don't
- // call these functions anywhere but the constructor of your subclass of
- // UnixSignals or in
- // your Process Plugin's GetUnixSignals method before you return the
- // UnixSignal object.
+ // constructed, since a process should never need to add or remove symbols as
+ // it runs. So don't call these functions anywhere but the constructor of
+ // your subclass of UnixSignals or in your Process Plugin's GetUnixSignals
+ // method before you return the UnixSignal object.
void AddSignal(int signo, const char *name, bool default_suppress,
bool default_stop, bool default_notify,
@@ -90,15 +86,14 @@ public:
void RemoveSignal(int signo);
- // Returns a current version of the data stored in this class.
- // Version gets incremented each time Set... method is called.
+ // Returns a current version of the data stored in this class. Version gets
+ // incremented each time Set... method is called.
uint64_t GetVersion() const;
- // Returns a vector of signals that meet criteria provided in arguments.
- // Each should_[suppress|stop|notify] flag can be
- // None - no filtering by this flag
- // true - only signals that have it set to true are returned
- // false - only signals that have it set to true are returned
+ // Returns a vector of signals that meet criteria provided in arguments. Each
+ // should_[suppress|stop|notify] flag can be None - no filtering by this
+ // flag true - only signals that have it set to true are returned false -
+ // only signals that have it set to true are returned
std::vector<int32_t> GetFilteredSignals(llvm::Optional<bool> should_suppress,
llvm::Optional<bool> should_stop,
llvm::Optional<bool> should_notify);
@@ -126,10 +121,10 @@ protected:
collection m_signals;
- // This version gets incremented every time something is changing in
- // this class, including when we call AddSignal from the constructor.
- // So after the object is constructed m_version is going to be > 0
- // if it has at least one signal registered in it.
+ // This version gets incremented every time something is changing in this
+ // class, including when we call AddSignal from the constructor. So after the
+ // object is constructed m_version is going to be > 0 if it has at least one
+ // signal registered in it.
uint64_t m_version = 0;
// GDBRemote signals need to be copyable.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h b/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h
index 5eaf2fd0e069..b5ff239f800d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h
@@ -50,6 +50,7 @@
#define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END
#define ANSI_2_CTRL(ctrl1, ctrl2) "\033["##ctrl1 ";"##ctrl2 ANSI_ESC_END
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -118,17 +119,21 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format,
break;
}
+ bool found_code = false;
for (const auto &code : codes) {
if (!right.consume_front(code.name))
continue;
if (do_color)
fmt.append(code.value);
- format = right;
+ found_code = true;
break;
}
-
- format = format.drop_front();
+ format = right;
+ // If we haven't found a valid replacement value, we just copy the string
+ // to the result without any modifications.
+ if (!found_code)
+ fmt.append(tok_hdr);
}
return fmt;
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h b/contrib/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h
index 50f69606e3df..680e9b1b9ea6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h
@@ -10,6 +10,7 @@
#ifndef LLDB_UTILITY_ARCHSPEC_H
#define LLDB_UTILITY_ARCHSPEC_H
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
@@ -23,13 +24,13 @@
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class ArchSpec ArchSpec.h "lldb/Utility/ArchSpec.h"
-/// @brief An architecture specification class.
+/// @class ArchSpec ArchSpec.h "lldb/Utility/ArchSpec.h" An architecture
+/// specification class.
///
/// A class designed to be created from a cpu type and subtype, a
-/// string representation, or an llvm::Triple. Keeping all of the
-/// conversions of strings to architecture enumeration values confined
-/// to this class allows new architecture support to be added easily.
+/// string representation, or an llvm::Triple. Keeping all of the conversions
+/// of strings to architecture enumeration values confined to this class
+/// allows new architecture support to be added easily.
//----------------------------------------------------------------------
class ArchSpec {
public:
@@ -245,16 +246,15 @@ public:
//------------------------------------------------------------------
/// Default constructor.
///
- /// Default constructor that initializes the object with invalid
- /// cpu type and subtype values.
+ /// Default constructor that initializes the object with invalid cpu type
+ /// and subtype values.
//------------------------------------------------------------------
ArchSpec();
//------------------------------------------------------------------
/// Constructor over triple.
///
- /// Constructs an ArchSpec with properties consistent with the given
- /// Triple.
+ /// Constructs an ArchSpec with properties consistent with the given Triple.
//------------------------------------------------------------------
explicit ArchSpec(const llvm::Triple &triple);
explicit ArchSpec(const char *triple_cstr);
@@ -262,8 +262,8 @@ public:
//------------------------------------------------------------------
/// Constructor over architecture name.
///
- /// Constructs an ArchSpec with properties consistent with the given
- /// object type and architecture name.
+ /// Constructs an ArchSpec with properties consistent with the given object
+ /// type and architecture name.
//------------------------------------------------------------------
explicit ArchSpec(ArchitectureType arch_type, uint32_t cpu_type,
uint32_t cpu_subtype);
@@ -284,16 +284,18 @@ public:
//---------------------------------------------------------------------------
/// Returns true if the OS, vendor and environment fields of the triple are
- /// unset. The triple is expected to be normalized (llvm::Triple::normalize).
+ /// unset. The triple is expected to be normalized
+ /// (llvm::Triple::normalize).
//---------------------------------------------------------------------------
static bool ContainsOnlyArch(const llvm::Triple &normalized_triple);
- static size_t AutoComplete(llvm::StringRef name, StringList &matches);
+ static void ListSupportedArchNames(StringList &list);
+ static size_t AutoComplete(CompletionRequest &request);
//------------------------------------------------------------------
/// Returns a static string representing the current architecture.
///
- /// @return A static string correcponding to the current
+ /// @return A static string corresponding to the current
/// architecture.
//------------------------------------------------------------------
const char *GetArchitectureName() const;
@@ -306,8 +308,8 @@ public:
bool IsMIPS() const;
//------------------------------------------------------------------
- /// Returns a string representing current architecture as a target CPU
- /// for tools like compiler, disassembler etc.
+ /// Returns a string representing current architecture as a target CPU for
+ /// tools like compiler, disassembler etc.
///
/// @return A string representing target CPU for the current
/// architecture.
@@ -329,8 +331,7 @@ public:
void Clear();
//------------------------------------------------------------------
- /// Returns the size in bytes of an address of the current
- /// architecture.
+ /// Returns the size in bytes of an address of the current architecture.
///
/// @return The byte size of an address of the current architecture.
//------------------------------------------------------------------
@@ -356,9 +357,8 @@ public:
//------------------------------------------------------------------
/// Set the distribution id of the architecture.
///
- /// This will be something like "ubuntu", "fedora", etc. on Linux.
- /// This should be the same value returned by
- /// HostInfo::GetDistributionId ().
+ /// This will be something like "ubuntu", "fedora", etc. on Linux. This
+ /// should be the same value returned by HostInfo::GetDistributionId ().
///------------------------------------------------------------------
void SetDistributionId(const char *distribution_id);
@@ -395,13 +395,12 @@ public:
//------------------------------------------------------------------
/// Merges fields from another ArchSpec into this ArchSpec.
///
- /// This will use the supplied ArchSpec to fill in any fields of
- /// the triple in this ArchSpec which were unspecified. This can
- /// be used to refine a generic ArchSpec with a more specific one.
- /// For example, if this ArchSpec's triple is something like
- /// i386-unknown-unknown-unknown, and we have a triple which is
- /// x64-pc-windows-msvc, then merging that triple into this one
- /// will result in the triple i386-pc-windows-msvc.
+ /// This will use the supplied ArchSpec to fill in any fields of the triple
+ /// in this ArchSpec which were unspecified. This can be used to refine a
+ /// generic ArchSpec with a more specific one. For example, if this
+ /// ArchSpec's triple is something like i386-unknown-unknown-unknown, and we
+ /// have a triple which is x64-pc-windows-msvc, then merging that triple
+ /// into this one will result in the triple i386-pc-windows-msvc.
///
//------------------------------------------------------------------
void MergeFrom(const ArchSpec &other);
@@ -421,16 +420,16 @@ public:
///
/// @return True if the object, and CPU were successfully set.
///
- /// As a side effect, the vendor value is usually set to unknown.
- /// The exections are
+ /// As a side effect, the vendor value is usually set to unknown. The
+ /// exceptions are
/// aarch64-apple-ios
/// arm-apple-ios
/// thumb-apple-ios
/// x86-apple-
/// x86_64-apple-
///
- /// As a side effect, the os value is usually set to unknown
- /// The exceptions are
+ /// As a side effect, the os value is usually set to unknown The exceptions
+ /// are
/// *-*-aix
/// aarch64-apple-ios
/// arm-apple-ios
@@ -456,10 +455,10 @@ public:
//------------------------------------------------------------------
/// Sets this ArchSpec's byte order.
///
- /// In the common case there is no need to call this method as the
- /// byte order can almost always be determined by the architecture.
- /// However, many CPU's are bi-endian (ARM, Alpha, PowerPC, etc)
- /// and the default/assumed byte order may be incorrect.
+ /// In the common case there is no need to call this method as the byte
+ /// order can almost always be determined by the architecture. However, many
+ /// CPU's are bi-endian (ARM, Alpha, PowerPC, etc) and the default/assumed
+ /// byte order may be incorrect.
//------------------------------------------------------------------
void SetByteOrder(lldb::ByteOrder byte_order) { m_byte_order = byte_order; }
@@ -476,28 +475,28 @@ public:
//------------------------------------------------------------------
/// Architecture data byte width accessor
///
- /// @return the size in 8-bit (host) bytes of a minimum addressable
- /// unit from the Architecture's data bus
+ /// @return the size in 8-bit (host) bytes of a minimum addressable unit
+ /// from the Architecture's data bus
//------------------------------------------------------------------
uint32_t GetDataByteSize() const;
//------------------------------------------------------------------
/// Architecture code byte width accessor
///
- /// @return the size in 8-bit (host) bytes of a minimum addressable
- /// unit from the Architecture's code bus
+ /// @return the size in 8-bit (host) bytes of a minimum addressable unit
+ /// from the Architecture's code bus
//------------------------------------------------------------------
uint32_t GetCodeByteSize() const;
//------------------------------------------------------------------
- /// Architecture tripple accessor.
+ /// Architecture triple accessor.
///
/// @return A triple describing this ArchSpec.
//------------------------------------------------------------------
llvm::Triple &GetTriple() { return m_triple; }
//------------------------------------------------------------------
- /// Architecture tripple accessor.
+ /// Architecture triple accessor.
///
/// @return A triple describing this ArchSpec.
//------------------------------------------------------------------
@@ -506,14 +505,14 @@ public:
void DumpTriple(Stream &s) const;
//------------------------------------------------------------------
- /// Architecture tripple setter.
+ /// Architecture triple setter.
///
- /// Configures this ArchSpec according to the given triple. If the
- /// triple has unknown components in all of the vendor, OS, and
- /// the optional environment field (i.e. "i386-unknown-unknown")
- /// then default values are taken from the host. Architecture and
- /// environment components are used to further resolve the CPU type
- /// and subtype, endian characteristics, etc.
+ /// Configures this ArchSpec according to the given triple. If the triple
+ /// has unknown components in all of the vendor, OS, and the optional
+ /// environment field (i.e. "i386-unknown-unknown") then default values are
+ /// taken from the host. Architecture and environment components are used
+ /// to further resolve the CPU type and subtype, endian characteristics,
+ /// etc.
///
/// @return A triple describing this ArchSpec.
//------------------------------------------------------------------
@@ -530,8 +529,8 @@ public:
lldb::ByteOrder GetDefaultEndian() const;
//------------------------------------------------------------------
- /// Returns true if 'char' is a signed type by defualt in the
- /// architecture false otherwise
+ /// Returns true if 'char' is a signed type by default in the architecture
+ /// false otherwise
///
/// @return True if 'char' is a signed type by default on the
/// architecture and false otherwise.
@@ -539,18 +538,18 @@ public:
bool CharIsSignedByDefault() const;
//------------------------------------------------------------------
- /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu
- /// type match between them.
- /// e.g. armv7s is not an exact match with armv7 - this would return false
+ /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu type
+ /// match between them. e.g. armv7s is not an exact match with armv7 - this
+ /// would return false
///
/// @return true if the two ArchSpecs match.
//------------------------------------------------------------------
bool IsExactMatch(const ArchSpec &rhs) const;
//------------------------------------------------------------------
- /// Compare an ArchSpec to another ArchSpec, requiring a compatible
- /// cpu type match between them.
- /// e.g. armv7s is compatible with armv7 - this method would return true
+ /// Compare an ArchSpec to another ArchSpec, requiring a compatible cpu type
+ /// match between them. e.g. armv7s is compatible with armv7 - this method
+ /// would return true
///
/// @return true if the two ArchSpecs are compatible
//------------------------------------------------------------------
@@ -566,12 +565,12 @@ public:
//------------------------------------------------------------------
/// Detect whether this architecture uses thumb code exclusively
///
- /// Some embedded ARM chips (e.g. the ARM Cortex M0-7 line) can
- /// only execute the Thumb instructions, never Arm. We should normally
- /// pick up arm/thumbness from their the processor status bits (cpsr/xpsr)
- /// or hints on each function - but when doing bare-boards low level
- /// debugging (especially common with these embedded processors), we may
- /// not have those things easily accessible.
+ /// Some embedded ARM chips (e.g. the ARM Cortex M0-7 line) can only execute
+ /// the Thumb instructions, never Arm. We should normally pick up
+ /// arm/thumbness from their the processor status bits (cpsr/xpsr) or hints
+ /// on each function - but when doing bare-boards low level debugging
+ /// (especially common with these embedded processors), we may not have
+ /// those things easily accessible.
///
/// @return true if this is an arm ArchSpec which can only execute Thumb
/// instructions
@@ -592,31 +591,30 @@ protected:
Core m_core = kCore_invalid;
lldb::ByteOrder m_byte_order = lldb::eByteOrderInvalid;
- // Additional arch flags which we cannot get from triple and core
- // For MIPS these are application specific extensions like
- // micromips, mips16 etc.
+ // Additional arch flags which we cannot get from triple and core For MIPS
+ // these are application specific extensions like micromips, mips16 etc.
uint32_t m_flags = 0;
ConstString m_distribution_id;
- // Called when m_def or m_entry are changed. Fills in all remaining
- // members with default values.
+ // Called when m_def or m_entry are changed. Fills in all remaining members
+ // with default values.
void CoreUpdated(bool update_triple);
};
//------------------------------------------------------------------
-/// @fn bool operator< (const ArchSpec& lhs, const ArchSpec& rhs)
-/// @brief Less than operator.
+/// @fn bool operator< (const ArchSpec& lhs, const ArchSpec& rhs) Less than
+/// operator.
///
-/// Tests two ArchSpec objects to see if \a lhs is less than \a
-/// rhs.
+/// Tests two ArchSpec objects to see if \a lhs is less than \a rhs.
///
-/// @param[in] lhs The Left Hand Side ArchSpec object to compare.
-/// @param[in] rhs The Left Hand Side ArchSpec object to compare.
+/// @param[in] lhs The Left Hand Side ArchSpec object to compare. @param[in]
+/// rhs The Left Hand Side ArchSpec object to compare.
///
/// @return true if \a lhs is less than \a rhs
//------------------------------------------------------------------
bool operator<(const ArchSpec &lhs, const ArchSpec &rhs);
+bool operator==(const ArchSpec &lhs, const ArchSpec &rhs);
bool ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, ArchSpec &arch);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Args.h
index 19d7ac418566..dec3dfaa4785 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Args.h
@@ -7,54 +7,30 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Command_h_
-#define liblldb_Command_h_
+#ifndef LLDB_UTILITY_ARGS_H
+#define LLDB_UTILITY_ARGS_H
-// C Includes
-// C++ Includes
-#include <list>
+#include "lldb/Utility/Environment.h"
+#include "lldb/lldb-private-types.h"
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include <string>
#include <utility>
#include <vector>
-// Other libraries and framework includes
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-// Project includes
-#include "lldb/Utility/Status.h"
-#include "lldb/lldb-private-types.h"
-#include "lldb/lldb-types.h"
-
namespace lldb_private {
-struct Option;
-
-typedef std::vector<std::tuple<std::string, int, std::string>> OptionArgVector;
-typedef std::shared_ptr<OptionArgVector> OptionArgVectorSP;
-
-struct OptionArgElement {
- enum { eUnrecognizedArg = -1, eBareDash = -2, eBareDoubleDash = -3 };
-
- OptionArgElement(int defs_index, int pos, int arg_pos)
- : opt_defs_index(defs_index), opt_pos(pos), opt_arg_pos(arg_pos) {}
-
- int opt_defs_index;
- int opt_pos;
- int opt_arg_pos;
-};
-
-typedef std::vector<OptionArgElement> OptionElementVector;
-
//----------------------------------------------------------------------
-/// @class Args Args.h "lldb/Interpreter/Args.h"
-/// @brief A command line argument class.
+/// @class Args Args.h "lldb/Utility/Args.h"
+/// A command line argument class.
///
-/// The Args class is designed to be fed a command line. The
-/// command line is copied into an internal buffer and then split up
-/// into arguments. Arguments are space delimited if there are no quotes
-/// (single, double, or backtick quotes) surrounding the argument. Spaces
-/// can be escaped using a \ character to avoid having to surround an
-/// argument that contains a space with quotes.
+/// The Args class is designed to be fed a command line. The command line is
+/// copied into an internal buffer and then split up into arguments. Arguments
+/// are space delimited if there are no quotes (single, double, or backtick
+/// quotes) surrounding the argument. Spaces can be escaped using a \
+/// character to avoid having to surround an argument that contains a space
+/// with quotes.
//----------------------------------------------------------------------
class Args {
public:
@@ -72,6 +48,11 @@ public:
llvm::StringRef ref;
char quote;
const char *c_str() const { return ptr.get(); }
+
+ //------------------------------------------------------------------
+ /// Returns true if this argument was quoted in any way.
+ //------------------------------------------------------------------
+ bool IsQuoted() const { return quote != '\0'; }
};
//------------------------------------------------------------------
@@ -95,6 +76,12 @@ public:
//------------------------------------------------------------------
~Args();
+ explicit Args(const Environment &env) : Args() {
+ SetArguments(const_cast<const char **>(env.getEnvp().get()));
+ }
+
+ explicit operator Environment() const { return GetConstArgumentVector(); }
+
//------------------------------------------------------------------
/// Dump all entries to the stream \a s using label \a label_name.
///
@@ -113,18 +100,17 @@ public:
//------------------------------------------------------------------
/// Sets the command string contained by this object.
///
- /// The command string will be copied and split up into arguments
- /// that can be accessed via the accessor functions.
+ /// The command string will be copied and split up into arguments that can
+ /// be accessed via the accessor functions.
///
/// @param[in] command
/// A command StringRef that will be copied and split up
/// into arguments.
///
/// @see Args::GetArgumentCount() const
- /// @see Args::GetArgumentAtIndex (size_t) const
- /// @see Args::GetArgumentVector ()
- /// @see Args::Shift ()
- /// @see Args::Unshift (const char *)
+ /// @see Args::GetArgumentAtIndex (size_t) const @see
+ /// Args::GetArgumentVector () @see Args::Shift () @see Args::Unshift (const
+ /// char *)
//------------------------------------------------------------------
void SetCommandString(llvm::StringRef command);
@@ -142,8 +128,8 @@ public:
bool empty() const { return GetArgumentCount() == 0; }
//------------------------------------------------------------------
- /// Gets the NULL terminated C string argument pointer for the
- /// argument at index \a idx.
+ /// Gets the NULL terminated C string argument pointer for the argument at
+ /// index \a idx.
///
/// @return
/// The NULL terminated C string argument pointer if \a idx is a
@@ -154,10 +140,10 @@ public:
llvm::ArrayRef<ArgEntry> entries() const { return m_entries; }
char GetArgumentQuoteCharAtIndex(size_t idx) const;
- std::vector<ArgEntry>::const_iterator begin() const {
- return m_entries.begin();
- }
- std::vector<ArgEntry>::const_iterator end() const { return m_entries.end(); }
+ using const_iterator = std::vector<ArgEntry>::const_iterator;
+
+ const_iterator begin() const { return m_entries.begin(); }
+ const_iterator end() const { return m_entries.end(); }
size_t size() const { return GetArgumentCount(); }
const ArgEntry &operator[](size_t n) const { return m_entries[n]; }
@@ -165,9 +151,9 @@ public:
//------------------------------------------------------------------
/// Gets the argument vector.
///
- /// The value returned by this function can be used by any function
- /// that takes and vector. The return value is just like \a argv
- /// in the standard C entry point function:
+ /// The value returned by this function can be used by any function that
+ /// takes and vector. The return value is just like \a argv in the standard
+ /// C entry point function:
/// \code
/// int main (int argc, const char **argv);
/// \endcode
@@ -181,9 +167,9 @@ public:
//------------------------------------------------------------------
/// Gets the argument vector.
///
- /// The value returned by this function can be used by any function
- /// that takes and vector. The return value is just like \a argv
- /// in the standard C entry point function:
+ /// The value returned by this function can be used by any function that
+ /// takes and vector. The return value is just like \a argv in the standard
+ /// C entry point function:
/// \code
/// int main (int argc, const char **argv);
/// \endcode
@@ -237,8 +223,8 @@ public:
char quote_char = '\0');
//------------------------------------------------------------------
- /// Replaces the argument value at index \a idx to \a arg_cstr
- /// if \a idx is a valid argument index.
+ /// Replaces the argument value at index \a idx to \a arg_cstr if \a idx is
+ /// a valid argument index.
///
/// @param[in] idx
/// The index of the argument that will have its value replaced.
@@ -263,11 +249,11 @@ public:
void DeleteArgumentAtIndex(size_t idx);
//------------------------------------------------------------------
- /// Sets the argument vector value, optionally copying all
- /// arguments into an internal buffer.
+ /// Sets the argument vector value, optionally copying all arguments into an
+ /// internal buffer.
///
- /// Sets the arguments to match those found in \a argv. All argument
- /// strings will be copied into an internal buffers.
+ /// Sets the arguments to match those found in \a argv. All argument strings
+ /// will be copied into an internal buffers.
//
// FIXME: Handle the quote character somehow.
//------------------------------------------------------------------
@@ -276,21 +262,20 @@ public:
void SetArguments(const char **argv);
//------------------------------------------------------------------
- /// Shifts the first argument C string value of the array off the
- /// argument array.
+ /// Shifts the first argument C string value of the array off the argument
+ /// array.
///
- /// The string value will be freed, so a copy of the string should
- /// be made by calling Args::GetArgumentAtIndex (size_t) const
- /// first and copying the returned value before calling
- /// Args::Shift().
+ /// The string value will be freed, so a copy of the string should be made
+ /// by calling Args::GetArgumentAtIndex (size_t) const first and copying the
+ /// returned value before calling Args::Shift().
///
/// @see Args::GetArgumentAtIndex (size_t) const
//------------------------------------------------------------------
void Shift();
//------------------------------------------------------------------
- /// Inserts a class owned copy of \a arg_cstr at the beginning of
- /// the argument vector.
+ /// Inserts a class owned copy of \a arg_cstr at the beginning of the
+ /// argument vector.
///
/// A copy \a arg_cstr will be made.
///
@@ -303,44 +288,6 @@ public:
void Unshift(llvm::StringRef arg_str, char quote_char = '\0');
//------------------------------------------------------------------
- /// Parse the arguments in the contained arguments.
- ///
- /// The arguments that are consumed by the argument parsing process
- /// will be removed from the argument vector. The arguments that
- /// get processed start at the second argument. The first argument
- /// is assumed to be the command and will not be touched.
- ///
- /// param[in] platform_sp
- /// The platform used for option validation. This is necessary
- /// because an empty execution_context is not enough to get us
- /// to a reasonable platform. If the platform isn't given,
- /// we'll try to get it from the execution context. If we can't
- /// get it from the execution context, we'll skip validation.
- ///
- /// param[in] require_validation
- /// When true, it will fail option parsing if validation could
- /// not occur due to not having a platform.
- ///
- /// @see class Options
- //------------------------------------------------------------------
- Status ParseOptions(Options &options, ExecutionContext *execution_context,
- lldb::PlatformSP platform_sp, bool require_validation);
-
- bool IsPositionalArgument(const char *arg);
-
- // The following works almost identically to ParseOptions, except that no
- // option is required to have arguments, and it builds up the
- // option_arg_vector as it parses the options.
-
- std::string ParseAliasOptions(Options &options, CommandReturnObject &result,
- OptionArgVector *option_arg_vector,
- llvm::StringRef raw_input_line);
-
- void ParseArgsForCompletion(Options &options,
- OptionElementVector &option_element_vector,
- uint32_t cursor_index);
-
- //------------------------------------------------------------------
// Clear the arguments.
//
// For re-setting or blanking out the list of arguments.
@@ -376,39 +323,12 @@ public:
return min <= sval64 && sval64 <= max;
}
- static lldb::addr_t StringToAddress(const ExecutionContext *exe_ctx,
- llvm::StringRef s,
- lldb::addr_t fail_value, Status *error);
-
- static bool StringToBoolean(llvm::StringRef s, bool fail_value,
- bool *success_ptr);
-
- static char StringToChar(llvm::StringRef s, char fail_value,
- bool *success_ptr);
-
- static int64_t StringToOptionEnum(llvm::StringRef s,
- OptionEnumValueElement *enum_values,
- int32_t fail_value, Status &error);
-
- static lldb::ScriptLanguage
- StringToScriptLanguage(llvm::StringRef s, lldb::ScriptLanguage fail_value,
- bool *success_ptr);
-
- // TODO: Use StringRef
- static Status StringToFormat(const char *s, lldb::Format &format,
- size_t *byte_size_ptr); // If non-NULL, then a
- // byte size can precede
- // the format character
-
static lldb::Encoding
StringToEncoding(llvm::StringRef s,
lldb::Encoding fail_value = lldb::eEncodingInvalid);
static uint32_t StringToGenericRegister(llvm::StringRef s);
- static bool StringToVersion(llvm::StringRef string, uint32_t &major,
- uint32_t &minor, uint32_t &update);
-
static const char *GetShellSafeArgument(const FileSpec &shell,
const char *unsafe_arg,
std::string &safe_arg);
@@ -423,58 +343,121 @@ public:
static void EncodeEscapeSequences(const char *src, std::string &dst);
// ExpandEscapeSequences will change a string of possibly non-printable
- // characters and expand them into text. So '\n' will turn into two characters
- // like "\n" which is suitable for human reading. When a character is not
- // printable and isn't one of the common in escape sequences listed in the
- // help for EncodeEscapeSequences, then it will be encoded as octal. Printable
- // characters are left alone.
+ // characters and expand them into text. So '\n' will turn into two
+ // characters like "\n" which is suitable for human reading. When a character
+ // is not printable and isn't one of the common in escape sequences listed in
+ // the help for EncodeEscapeSequences, then it will be encoded as octal.
+ // Printable characters are left alone.
static void ExpandEscapedCharacters(const char *src, std::string &dst);
static std::string EscapeLLDBCommandArgument(const std::string &arg,
char quote_char);
+private:
+ std::vector<ArgEntry> m_entries;
+ std::vector<char *> m_argv;
+};
+
+//----------------------------------------------------------------------
+/// @class OptionsWithRaw Args.h "lldb/Utility/Args.h"
+/// A pair of an option list with a 'raw' string as a suffix.
+///
+/// This class works similar to Args, but handles the case where we have a
+/// trailing string that shouldn't be interpreted as a list of arguments but
+/// preserved as is. It is also only useful for handling command line options
+/// (e.g. '-foo bar -i0') that start with a dash.
+///
+/// The leading option list is optional. If the first non-space character
+/// in the string starts with a dash, and the string contains an argument
+/// that is an unquoted double dash (' -- '), then everything up to the double
+/// dash is parsed as a list of arguments. Everything after the double dash
+/// is interpreted as the raw suffix string. Note that the space behind the
+/// double dash is not part of the raw suffix.
+///
+/// All strings not matching the above format as considered to be just a raw
+/// string without any options.
+///
+/// @see Args
+//----------------------------------------------------------------------
+class OptionsWithRaw {
+public:
//------------------------------------------------------------------
- /// Add or replace an environment variable with the given value.
+ /// Parse the given string as a list of optional arguments with a raw suffix.
///
- /// This command adds the environment variable if it is not already
- /// present using the given value. If the environment variable is
- /// already in the list, it replaces the first such occurrence
- /// with the new value.
+ /// See the class description for a description of the input format.
+ ///
+ /// @param[in] argument_string
+ /// The string that should be parsed.
//------------------------------------------------------------------
- void AddOrReplaceEnvironmentVariable(llvm::StringRef env_var_name,
- llvm::StringRef new_value);
+ explicit OptionsWithRaw(llvm::StringRef argument_string);
- /// Return whether a given environment variable exists.
+ //------------------------------------------------------------------
+ /// Returns true if there are any arguments before the raw suffix.
+ //------------------------------------------------------------------
+ bool HasArgs() const { return m_has_args; }
+
+ //------------------------------------------------------------------
+ /// Returns the list of arguments.
///
- /// This command treats Args like a list of environment variables,
- /// as used in ProcessLaunchInfo. It treats each argument as
- /// an {env_var_name}={value} or an {env_var_name} entry.
+ /// You can only call this method if HasArgs returns true.
+ //------------------------------------------------------------------
+ Args &GetArgs() {
+ assert(m_has_args);
+ return m_args;
+ }
+
+ //------------------------------------------------------------------
+ /// Returns the list of arguments.
///
- /// @param[in] env_var_name
- /// Specifies the name of the environment variable to check.
+ /// You can only call this method if HasArgs returns true.
+ //------------------------------------------------------------------
+ const Args &GetArgs() const {
+ assert(m_has_args);
+ return m_args;
+ }
+
+ //------------------------------------------------------------------
+ /// Returns the part of the input string that was used for parsing the
+ /// argument list. This string also includes the double dash that is used
+ /// for separating the argument list from the suffix.
///
- /// @param[out] argument_index
- /// If non-null, then when the environment variable is found,
- /// the index of the argument position will be returned in
- /// the size_t pointed to by this argument.
+ /// You can only call this method if HasArgs returns true.
+ //------------------------------------------------------------------
+ llvm::StringRef GetArgStringWithDelimiter() const {
+ assert(m_has_args);
+ return m_arg_string_with_delimiter;
+ }
+
+ //------------------------------------------------------------------
+ /// Returns the part of the input string that was used for parsing the
+ /// argument list.
///
- /// @return
- /// true if the specified env var name exists in the list in
- /// either of the above-mentioned formats; otherwise, false.
+ /// You can only call this method if HasArgs returns true.
//------------------------------------------------------------------
- bool ContainsEnvironmentVariable(llvm::StringRef env_var_name,
- size_t *argument_index = nullptr) const;
+ llvm::StringRef GetArgString() const {
+ assert(m_has_args);
+ return m_arg_string;
+ }
+
+ //------------------------------------------------------------------
+ /// Returns the raw suffix part of the parsed string.
+ //------------------------------------------------------------------
+ const std::string &GetRawPart() const { return m_suffix; }
private:
- size_t FindArgumentIndexForOption(Option *long_options,
- int long_options_index) const;
+ void SetFromString(llvm::StringRef arg_string);
- std::vector<ArgEntry> m_entries;
- std::vector<char *> m_argv;
+ /// Keeps track if we have parsed and stored any arguments.
+ bool m_has_args = false;
+ Args m_args;
+ llvm::StringRef m_arg_string;
+ llvm::StringRef m_arg_string_with_delimiter;
- void UpdateArgsAfterOptionParsing();
+ // FIXME: This should be a StringRef, but some of the calling code expect a
+ // C string here so only a real std::string is possible.
+ std::string m_suffix;
};
} // namespace lldb_private
-#endif // liblldb_Command_h_
+#endif // LLDB_UTILITY_ARGS_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Baton.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Baton.h
index 065f2960962d..59999e4697fa 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Baton.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Baton.h
@@ -23,15 +23,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Baton Baton.h "lldb/Core/Baton.h"
-/// @brief A class designed to wrap callback batons so they can cleanup
+/// A class designed to wrap callback batons so they can cleanup
/// any acquired resources
///
-/// This class is designed to be used by any objects that have a
-/// callback function that takes a baton where the baton might need to
+/// This class is designed to be used by any objects that have a callback
+/// function that takes a baton where the baton might need to
/// free/delete/close itself.
///
-/// The default behavior is to not free anything. Subclasses can
-/// free any needed resources in their destructors.
+/// The default behavior is to not free anything. Subclasses can free any
+/// needed resources in their destructors.
//----------------------------------------------------------------------
class Baton {
public:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/CleanUp.h b/contrib/llvm/tools/lldb/include/lldb/Utility/CleanUp.h
index 0d7bc8d99219..ef460ddd5e7f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/CleanUp.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/CleanUp.h
@@ -13,249 +13,31 @@
#include "lldb/lldb-public.h"
#include <functional>
-namespace lldb_utility {
+namespace lldb_private {
-//----------------------------------------------------------------------
-// Templated class that guarantees that a cleanup callback function will
-// be called. The cleanup function will be called once under the
-// following conditions:
-// - when the object goes out of scope
-// - when the user explicitly calls clean.
-// - the current value will be cleaned up when a new value is set using
-// set(T value) as long as the current value hasn't already been cleaned.
-//
-// This class is designed to be used with simple types for type T (like
-// file descriptors, opaque handles, pointers, etc). If more complex
-// type T objects are desired, we need to probably specialize this class
-// to take "const T&" for all input T parameters. Yet if a type T is
-// complex already it might be better to build the cleanup functionality
-// into T.
-//
-// The cleanup function must take one argument that is of type T.
-// The calback function return type is R. The return value is currently
-// needed for "CallbackType". If there is an easy way to get around the
-// need for the return value we can change this class.
-//
-// The two template parameters are:
-// T - The variable type of value that will be stored and used as the
-// sole argument for the cleanup callback.
-// R - The return type for the cleanup function.
-//
-// EXAMPLES
-// // Use with file handles that get opened where you want to close
-// // them. Below we use "int open(const char *path, int oflag, ...)"
-// // which returns an integer file descriptor. -1 is the invalid file
-// // descriptor so to make an object that will call "int close(int fd)"
-// // automatically we can use:
-//
-// CleanUp <int, int> fd(open("/tmp/a.txt", O_RDONLY, 0), -1, close);
-//
-// // malloc/free example
-// CleanUp <void *, void> malloced_bytes(malloc(32), NULL, free);
-//----------------------------------------------------------------------
-template <typename T, typename R = void> class CleanUp {
-public:
- typedef T value_type;
- typedef std::function<R(value_type)> CallbackType;
-
- //----------------------------------------------------------------------
- // Constructor that sets the current value only. No values are
- // considered to be invalid and the cleanup function will be called
- // regardless of the value of m_current_value.
- //----------------------------------------------------------------------
- CleanUp(value_type value, CallbackType callback)
- : m_current_value(value), m_invalid_value(), m_callback(callback),
- m_callback_called(false), m_invalid_value_is_valid(false) {}
-
- //----------------------------------------------------------------------
- // Constructor that sets the current value and also the invalid value.
- // The cleanup function will be called on "m_value" as long as it isn't
- // equal to "m_invalid_value".
- //----------------------------------------------------------------------
- CleanUp(value_type value, value_type invalid, CallbackType callback)
- : m_current_value(value), m_invalid_value(invalid), m_callback(callback),
- m_callback_called(false), m_invalid_value_is_valid(true) {}
-
- //----------------------------------------------------------------------
- // Automatically cleanup when this object goes out of scope.
- //----------------------------------------------------------------------
- ~CleanUp() { clean(); }
-
- //----------------------------------------------------------------------
- // Access the value stored in this class
- //----------------------------------------------------------------------
- value_type get() { return m_current_value; }
-
- //----------------------------------------------------------------------
- // Access the value stored in this class
- //----------------------------------------------------------------------
- const value_type get() const { return m_current_value; }
-
- //----------------------------------------------------------------------
- // Reset the owned value to "value". If a current value is valid and
- // the cleanup callback hasn't been called, the previous value will
- // be cleaned up (see void CleanUp::clean()).
- //----------------------------------------------------------------------
- void set(const value_type value) {
- // Cleanup the current value if needed
- clean();
- // Now set the new value and mark our callback as not called
- m_callback_called = false;
- m_current_value = value;
- }
-
- //----------------------------------------------------------------------
- // Checks is "m_current_value" is valid. The value is considered valid
- // no invalid value was supplied during construction of this object or
- // if an invalid value was supplied and "m_current_value" is not equal
- // to "m_invalid_value".
- //
- // Returns true if "m_current_value" is valid, false otherwise.
- //----------------------------------------------------------------------
- bool is_valid() const {
- if (m_invalid_value_is_valid)
- return m_current_value != m_invalid_value;
- return true;
- }
-
- //----------------------------------------------------------------------
- // This function will call the cleanup callback provided in the
- // constructor one time if the value is considered valid (See is_valid()).
- // This function sets m_callback_called to true so we don't call the
- // cleanup callback multiple times on the same value.
- //----------------------------------------------------------------------
- void clean() {
- if (m_callback && !m_callback_called) {
- m_callback_called = true;
- if (is_valid())
- m_callback(m_current_value);
- }
- }
+/// Run a cleanup function on scope exit unless it's explicitly disabled.
+class CleanUp {
+ std::function<void()> Clean;
- //----------------------------------------------------------------------
- // Cancels the cleanup that would have been called on "m_current_value"
- // if it was valid. This function can be used to release the value
- // contained in this object so ownership can be transferred to the caller.
- //----------------------------------------------------------------------
- value_type release() {
- m_callback_called = true;
- return m_current_value;
- }
-
-private:
- value_type m_current_value;
- const value_type m_invalid_value;
- CallbackType m_callback;
- bool m_callback_called;
- bool m_invalid_value_is_valid;
-
- // Outlaw default constructor, copy constructor and the assignment operator
- DISALLOW_COPY_AND_ASSIGN(CleanUp);
-};
-
-template <typename T, typename R, typename A0> class CleanUp2 {
public:
- typedef T value_type;
- typedef std::function<R(value_type, A0)> CallbackType;
-
- //----------------------------------------------------------------------
- // Constructor that sets the current value only. No values are
- // considered to be invalid and the cleanup function will be called
- // regardless of the value of m_current_value.
- //----------------------------------------------------------------------
- CleanUp2(value_type value, CallbackType callback, A0 arg)
- : m_current_value(value), m_invalid_value(), m_callback(callback),
- m_callback_called(false), m_invalid_value_is_valid(false),
- m_argument(arg) {}
-
- //----------------------------------------------------------------------
- // Constructor that sets the current value and also the invalid value.
- // The cleanup function will be called on "m_value" as long as it isn't
- // equal to "m_invalid_value".
- //----------------------------------------------------------------------
- CleanUp2(value_type value, value_type invalid, CallbackType callback, A0 arg)
- : m_current_value(value), m_invalid_value(invalid), m_callback(callback),
- m_callback_called(false), m_invalid_value_is_valid(true),
- m_argument(arg) {}
-
- //----------------------------------------------------------------------
- // Automatically cleanup when this object goes out of scope.
- //----------------------------------------------------------------------
- ~CleanUp2() { clean(); }
+ /// Register a cleanup function which applies \p Func to a list of arguments.
+ /// Use caution with arguments which are references: they will be copied.
+ template <typename F, typename... Args>
+ CleanUp(F &&Func, Args &&... args)
+ : Clean(std::bind(std::forward<F>(Func), std::forward<Args>(args)...)) {}
- //----------------------------------------------------------------------
- // Access the value stored in this class
- //----------------------------------------------------------------------
- value_type get() { return m_current_value; }
-
- //----------------------------------------------------------------------
- // Access the value stored in this class
- //----------------------------------------------------------------------
- const value_type get() const { return m_current_value; }
-
- //----------------------------------------------------------------------
- // Reset the owned value to "value". If a current value is valid and
- // the cleanup callback hasn't been called, the previous value will
- // be cleaned up (see void CleanUp::clean()).
- //----------------------------------------------------------------------
- void set(const value_type value) {
- // Cleanup the current value if needed
- clean();
- // Now set the new value and mark our callback as not called
- m_callback_called = false;
- m_current_value = value;
+ ~CleanUp() {
+ if (Clean)
+ Clean();
}
- //----------------------------------------------------------------------
- // Checks is "m_current_value" is valid. The value is considered valid
- // no invalid value was supplied during construction of this object or
- // if an invalid value was supplied and "m_current_value" is not equal
- // to "m_invalid_value".
- //
- // Returns true if "m_current_value" is valid, false otherwise.
- //----------------------------------------------------------------------
- bool is_valid() const {
- if (m_invalid_value_is_valid)
- return m_current_value != m_invalid_value;
- return true;
- }
-
- //----------------------------------------------------------------------
- // This function will call the cleanup callback provided in the
- // constructor one time if the value is considered valid (See is_valid()).
- // This function sets m_callback_called to true so we don't call the
- // cleanup callback multiple times on the same value.
- //----------------------------------------------------------------------
- void clean() {
- if (m_callback && !m_callback_called) {
- m_callback_called = true;
- if (is_valid())
- m_callback(m_current_value, m_argument);
- }
- }
+ /// Disable the cleanup.
+ void disable() { Clean = nullptr; }
- //----------------------------------------------------------------------
- // Cancels the cleanup that would have been called on "m_current_value"
- // if it was valid. This function can be used to release the value
- // contained in this object so ownership can be transferred to the caller.
- //----------------------------------------------------------------------
- value_type release() {
- m_callback_called = true;
- return m_current_value;
- }
-
-private:
- value_type m_current_value;
- const value_type m_invalid_value;
- CallbackType m_callback;
- bool m_callback_called;
- bool m_invalid_value_is_valid;
- A0 m_argument;
-
- // Outlaw default constructor, copy constructor and the assignment operator
- DISALLOW_COPY_AND_ASSIGN(CleanUp2);
+ // Prevent cleanups from being run more than once.
+ DISALLOW_COPY_AND_ASSIGN(CleanUp);
};
-} // namespace lldb_utility
+} // namespace lldb_private
#endif // #ifndef liblldb_CleanUp_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/CompletionRequest.h b/contrib/llvm/tools/lldb/include/lldb/Utility/CompletionRequest.h
new file mode 100644
index 000000000000..ef75474813e0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/CompletionRequest.h
@@ -0,0 +1,149 @@
+//===-- CompletionRequest.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_COMPLETIONREQUEST_H
+#define LLDB_UTILITY_COMPLETIONREQUEST_H
+
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/StringList.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class CompletionRequest CompletionRequest.h
+/// "lldb/Utility/ArgCompletionRequest.h"
+///
+/// Contains all information necessary to complete an incomplete command
+/// for the user. Will be filled with the generated completions by the different
+/// completions functions.
+///
+//----------------------------------------------------------------------
+class CompletionRequest {
+public:
+ //----------------------------------------------------------
+ /// Constructs a completion request.
+ ///
+ /// @param [in] command_line
+ /// The command line the user has typed at this point.
+ ///
+ /// @param [in] raw_cursor_pos
+ /// The position of the cursor in the command line string. Index 0 means
+ /// the cursor is at the start of the line. The completion starts from
+ /// this cursor position.
+ ///
+ /// @param [in] match_start_point
+ /// @param [in] max_return_elements
+ /// If there is a match that is expensive to compute, these are here to
+ /// allow you to compute the completions in batches. Start the
+ /// completion from match_start_point, and return match_return_elements
+ /// elements.
+ ///
+ /// @param [out] matches
+ /// A list of matches that will be filled by the different completion
+ /// handlers.
+ //----------------------------------------------------------
+ CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos,
+ int match_start_point, int max_return_elements,
+ StringList &matches);
+
+ llvm::StringRef GetRawLine() const { return m_command; }
+
+ unsigned GetRawCursorPos() const { return m_raw_cursor_pos; }
+
+ const Args &GetParsedLine() const { return m_parsed_line; }
+
+ Args &GetParsedLine() { return m_parsed_line; }
+
+ const Args &GetPartialParsedLine() const { return m_partial_parsed_line; }
+
+ void SetCursorIndex(int i) { m_cursor_index = i; }
+ int GetCursorIndex() const { return m_cursor_index; }
+
+ void SetCursorCharPosition(int pos) { m_cursor_char_position = pos; }
+ int GetCursorCharPosition() const { return m_cursor_char_position; }
+
+ int GetMatchStartPoint() const { return m_match_start_point; }
+
+ int GetMaxReturnElements() const { return m_max_return_elements; }
+
+ bool GetWordComplete() { return m_word_complete; }
+
+ void SetWordComplete(bool v) { m_word_complete = v; }
+
+ /// Adds a possible completion string. If the completion was already
+ /// suggested before, it will not be added to the list of results. A copy of
+ /// the suggested completion is stored, so the given string can be free'd
+ /// afterwards.
+ ///
+ /// @param match The suggested completion.
+ void AddCompletion(llvm::StringRef completion) {
+ // Add the completion if we haven't seen the same value before.
+ if (m_match_set.insert(completion).second)
+ m_matches->AppendString(completion);
+ }
+
+ /// Adds multiple possible completion strings.
+ ///
+ /// \param completions The list of completions.
+ ///
+ /// @see AddCompletion
+ void AddCompletions(const StringList &completions) {
+ for (std::size_t i = 0; i < completions.GetSize(); ++i)
+ AddCompletion(completions.GetStringAtIndex(i));
+ }
+
+ std::size_t GetNumberOfMatches() const { return m_matches->GetSize(); }
+
+ llvm::StringRef GetCursorArgument() const {
+ return GetParsedLine().GetArgumentAtIndex(GetCursorIndex());
+ }
+
+ llvm::StringRef GetCursorArgumentPrefix() const {
+ return GetCursorArgument().substr(0, GetCursorCharPosition());
+ }
+
+private:
+ /// The raw command line we are supposed to complete.
+ llvm::StringRef m_command;
+ /// The cursor position in m_command.
+ unsigned m_raw_cursor_pos;
+ /// The command line parsed as arguments.
+ Args m_parsed_line;
+ /// The command line until the cursor position parsed as arguments.
+ Args m_partial_parsed_line;
+ /// The index of the argument in which the completion cursor is.
+ int m_cursor_index;
+ /// The cursor position in the argument indexed by m_cursor_index.
+ int m_cursor_char_position;
+ /// If there is a match that is expensive
+ /// to compute, these are here to allow you to compute the completions in
+ /// batches. Start the completion from \amatch_start_point, and return
+ /// \amatch_return_elements elements.
+ // FIXME: These two values are not implemented.
+ int m_match_start_point;
+ int m_max_return_elements;
+ /// \btrue if this is a complete option value (a space will be inserted
+ /// after the completion.) \bfalse otherwise.
+ bool m_word_complete = false;
+
+ // Note: This list is kept private. This is by design to prevent that any
+ // completion depends on any already computed completion from another backend.
+ // Note: We don't own the list. It's owned by the creator of the
+ // CompletionRequest object.
+ StringList *m_matches;
+
+ /// List of added completions so far. Used to filter out duplicates.
+ llvm::StringSet<> m_match_set;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_COMPLETIONREQUEST_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Connection.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Connection.h
index be5641d5fa63..1b0801378f84 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Connection.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Connection.h
@@ -32,16 +32,16 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Connection Connection.h "lldb/Utility/Connection.h"
-/// @brief A communication connection class.
+/// A communication connection class.
///
/// A class that implements that actual communication functions for
-/// connecting/disconnecting, reading/writing, and waiting for bytes
-/// to become available from a two way communication connection.
+/// connecting/disconnecting, reading/writing, and waiting for bytes to become
+/// available from a two way communication connection.
///
-/// This class is designed to only do very simple communication
-/// functions. Instances can be instantiated and given to a
-/// Communication class to perform communications where clients can
-/// listen for broadcasts, and perform other higher level communications.
+/// This class is designed to only do very simple communication functions.
+/// Instances can be instantiated and given to a Communication class to
+/// perform communications where clients can listen for broadcasts, and
+/// perform other higher level communications.
//----------------------------------------------------------------------
class Connection {
public:
@@ -51,8 +51,8 @@ public:
Connection() = default;
//------------------------------------------------------------------
- /// Virtual destructor since this class gets subclassed and handed
- /// to a Communication object.
+ /// Virtual destructor since this class gets subclassed and handed to a
+ /// Communication object.
//------------------------------------------------------------------
virtual ~Connection();
@@ -79,8 +79,7 @@ public:
Status *error_ptr) = 0;
//------------------------------------------------------------------
- /// Disconnect the communications connection if one is currently
- /// connected.
+ /// Disconnect the communications connection if one is currently connected.
///
/// @param[out] error_ptr
/// A pointer to an error object that should be given an
@@ -138,8 +137,8 @@ public:
lldb::ConnectionStatus &status, Status *error_ptr) = 0;
//------------------------------------------------------------------
- /// The actual write function that attempts to write to the
- /// communications protocol.
+ /// The actual write function that attempts to write to the communications
+ /// protocol.
///
/// Subclasses must override this function.
///
@@ -190,10 +189,9 @@ public:
//------------------------------------------------------------------
/// Returns the underlying IOObject used by the Connection.
///
- /// The IOObject can be used to wait for data to become available
- /// on the connection. If the Connection does not use IOObjects (and
- /// hence does not support waiting) this function should return a
- /// null pointer.
+ /// The IOObject can be used to wait for data to become available on the
+ /// connection. If the Connection does not use IOObjects (and hence does not
+ /// support waiting) this function should return a null pointer.
///
/// @return
/// The underlying IOObject used for reading.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/ConstString.h b/contrib/llvm/tools/lldb/include/lldb/Utility/ConstString.h
index fbf1a9bf536e..98b3447abe3e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/ConstString.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/ConstString.h
@@ -26,17 +26,17 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ConstString ConstString.h "lldb/Utility/ConstString.h"
-/// @brief A uniqued constant string class.
+/// A uniqued constant string class.
///
-/// Provides an efficient way to store strings as uniqued strings. After
-/// the strings are uniqued, finding strings that are equal to one
-/// another is very fast as just the pointers need to be compared. It
-/// also allows for many common strings from many different sources to
-/// be shared to keep the memory footprint low.
+/// Provides an efficient way to store strings as uniqued strings. After the
+/// strings are uniqued, finding strings that are equal to one another is very
+/// fast as just the pointers need to be compared. It also allows for many
+/// common strings from many different sources to be shared to keep the memory
+/// footprint low.
///
-/// No reference counting is done on strings that are added to the
-/// string pool, once strings are added they are in the string pool for
-/// the life of the program.
+/// No reference counting is done on strings that are added to the string
+/// pool, once strings are added they are in the string pool for the life of
+/// the program.
//----------------------------------------------------------------------
class ConstString {
public:
@@ -74,11 +74,10 @@ public:
//------------------------------------------------------------------
/// Construct with C String value with max length
///
- /// Constructs this object with a C string with a length. If
- /// \a max_cstr_len is greater than the actual length of the string,
- /// the string length will be truncated. This allows substrings to
- /// be created without the need to NULL terminate the string as it
- /// is passed into this function.
+ /// Constructs this object with a C string with a length. If \a max_cstr_len
+ /// is greater than the actual length of the string, the string length will
+ /// be truncated. This allows substrings to be created without the need to
+ /// NULL terminate the string as it is passed into this function.
///
/// @param[in] cstr
/// A pointer to the first character in the C string. The C
@@ -99,8 +98,8 @@ public:
//------------------------------------------------------------------
/// Destructor
///
- /// Since constant string values are currently not reference counted,
- /// there isn't much to do here.
+ /// Since constant string values are currently not reference counted, there
+ /// isn't much to do here.
//------------------------------------------------------------------
~ConstString() = default;
@@ -112,8 +111,8 @@ public:
//--------------------------------------------------------------
/// C equality test.
///
- /// Two C strings are equal when they are contained in ConstString
- /// objects when their pointer values are equal to each other.
+ /// Two C strings are equal when they are contained in ConstString objects
+ /// when their pointer values are equal to each other.
///
/// @return
/// Returns \b true if the C string in \a lhs is equal to
@@ -127,8 +126,8 @@ public:
//------------------------------------------------------------------
/// Convert to bool operator.
///
- /// This allows code to check a ConstString object to see if it
- /// contains a valid string using code such as:
+ /// This allows code to check a ConstString object to see if it contains a
+ /// valid string using code such as:
///
/// @code
/// ConstString str(...);
@@ -140,7 +139,7 @@ public:
/// /b True this object contains a valid non-empty C string, \b
/// false otherwise.
//------------------------------------------------------------------
- explicit operator bool() const { return m_string && m_string[0]; }
+ explicit operator bool() const { return !IsEmpty(); }
//------------------------------------------------------------------
/// Assignment operator
@@ -161,10 +160,9 @@ public:
//------------------------------------------------------------------
/// Equal to operator
///
- /// Returns true if this string is equal to the string in \a rhs.
- /// This operation is very fast as it results in a pointer
- /// comparison since all strings are in a uniqued in a global string
- /// pool.
+ /// Returns true if this string is equal to the string in \a rhs. This
+ /// operation is very fast as it results in a pointer comparison since all
+ /// strings are in a uniqued in a global string pool.
///
/// @param[in] rhs
/// Another string object to compare this object to.
@@ -174,18 +172,17 @@ public:
/// @li \b false if this object is not equal to \a rhs.
//------------------------------------------------------------------
bool operator==(const ConstString &rhs) const {
- // We can do a pointer compare to compare these strings since they
- // must come from the same pool in order to be equal.
+ // We can do a pointer compare to compare these strings since they must
+ // come from the same pool in order to be equal.
return m_string == rhs.m_string;
}
//------------------------------------------------------------------
/// Not equal to operator
///
- /// Returns true if this string is not equal to the string in \a rhs.
- /// This operation is very fast as it results in a pointer
- /// comparison since all strings are in a uniqued in a global string
- /// pool.
+ /// Returns true if this string is not equal to the string in \a rhs. This
+ /// operation is very fast as it results in a pointer comparison since all
+ /// strings are in a uniqued in a global string pool.
///
/// @param[in] rhs
/// Another string object to compare this object to.
@@ -203,8 +200,8 @@ public:
//------------------------------------------------------------------
/// Get the string value as a C string.
///
- /// Get the value of the contained string as a NULL terminated C
- /// string value.
+ /// Get the value of the contained string as a NULL terminated C string
+ /// value.
///
/// If \a value_if_empty is nullptr, then nullptr will be returned.
///
@@ -230,11 +227,10 @@ public:
//------------------------------------------------------------------
/// Get the string value as a C string.
///
- /// Get the value of the contained string as a NULL terminated C
- /// string value. Similar to the ConstString::AsCString() function,
- /// yet this function will always return nullptr if the string is not
- /// valid. So this function is a direct accessor to the string
- /// pointer value.
+ /// Get the value of the contained string as a NULL terminated C string
+ /// value. Similar to the ConstString::AsCString() function, yet this
+ /// function will always return nullptr if the string is not valid. So this
+ /// function is a direct accessor to the string pointer value.
///
/// @return
/// Returns nullptr the string is invalid, otherwise the C string
@@ -245,8 +241,8 @@ public:
//------------------------------------------------------------------
/// Get the length in bytes of string value.
///
- /// The string pool stores the length of the string, so we can avoid
- /// calling strlen() on the pointer value with this function.
+ /// The string pool stores the length of the string, so we can avoid calling
+ /// strlen() on the pointer value with this function.
///
/// @return
/// Returns the number of bytes that this string occupies in
@@ -257,18 +253,18 @@ public:
//------------------------------------------------------------------
/// Clear this object's state.
///
- /// Clear any contained string and reset the value to the an empty
- /// string value.
+ /// Clear any contained string and reset the value to the an empty string
+ /// value.
//------------------------------------------------------------------
void Clear() { m_string = nullptr; }
//------------------------------------------------------------------
/// Equal to operator
///
- /// Returns true if this string is equal to the string in \a rhs.
- /// If case sensitive equality is tested, this operation is very
- /// fast as it results in a pointer comparison since all strings
- /// are in a uniqued in a global string pool.
+ /// Returns true if this string is equal to the string in \a rhs. If case
+ /// sensitive equality is tested, this operation is very fast as it results
+ /// in a pointer comparison since all strings are in a uniqued in a global
+ /// string pool.
///
/// @param[in] rhs
/// The Left Hand Side const ConstString object reference.
@@ -290,13 +286,13 @@ public:
//------------------------------------------------------------------
/// Compare two string objects.
///
- /// Compares the C string values contained in \a lhs and \a rhs and
- /// returns an integer result.
+ /// Compares the C string values contained in \a lhs and \a rhs and returns
+ /// an integer result.
///
/// NOTE: only call this function when you want a true string
- /// comparison. If you want string equality use the, use the ==
- /// operator as it is much more efficient. Also if you want string
- /// inequality, use the != operator for the same reasons.
+ /// comparison. If you want string equality use the, use the == operator as
+ /// it is much more efficient. Also if you want string inequality, use the
+ /// != operator for the same reasons.
///
/// @param[in] lhs
/// The Left Hand Side const ConstString object reference.
@@ -319,10 +315,9 @@ public:
//------------------------------------------------------------------
/// Dump the object description to a stream.
///
- /// Dump the string value to the stream \a s. If the contained string
- /// is empty, print \a value_if_empty to the stream instead. If
- /// \a value_if_empty is nullptr, then nothing will be dumped to the
- /// stream.
+ /// Dump the string value to the stream \a s. If the contained string is
+ /// empty, print \a value_if_empty to the stream instead. If \a
+ /// value_if_empty is nullptr, then nothing will be dumped to the stream.
///
/// @param[in] s
/// The stream that will be used to dump the object description.
@@ -353,12 +348,12 @@ public:
//------------------------------------------------------------------
/// Set the C string value.
///
- /// Set the string value in the object by uniquing the \a cstr
- /// string value in our global string pool.
+ /// Set the string value in the object by uniquing the \a cstr string value
+ /// in our global string pool.
///
- /// If the C string already exists in the global string pool, it
- /// finds the current entry and returns the existing value. If it
- /// doesn't exist, it is added to the string pool.
+ /// If the C string already exists in the global string pool, it finds the
+ /// current entry and returns the existing value. If it doesn't exist, it is
+ /// added to the string pool.
///
/// @param[in] cstr
/// A NULL terminated C string to add to the string pool.
@@ -370,12 +365,12 @@ public:
//------------------------------------------------------------------
/// Set the C string value and its mangled counterpart.
///
- /// Object files and debug symbols often use mangled string to
- /// represent the linkage name for a symbol, function or global.
- /// The string pool can efficiently store these values and their
- /// counterparts so when we run into another instance of a mangled
- /// name, we can avoid calling the name demangler over and over on
- /// the same strings and then trying to unique them.
+ /// Object files and debug symbols often use mangled string to represent the
+ /// linkage name for a symbol, function or global. The string pool can
+ /// efficiently store these values and their counterparts so when we run
+ /// into another instance of a mangled name, we can avoid calling the name
+ /// demangler over and over on the same strings and then trying to unique
+ /// them.
///
/// @param[in] demangled
/// The demangled C string to correlate with the \a mangled
@@ -389,15 +384,15 @@ public:
const ConstString &mangled);
//------------------------------------------------------------------
- /// Retrieve the mangled or demangled counterpart for a mangled
- /// or demangled ConstString.
+ /// Retrieve the mangled or demangled counterpart for a mangled or demangled
+ /// ConstString.
///
- /// Object files and debug symbols often use mangled string to
- /// represent the linkage name for a symbol, function or global.
- /// The string pool can efficiently store these values and their
- /// counterparts so when we run into another instance of a mangled
- /// name, we can avoid calling the name demangler over and over on
- /// the same strings and then trying to unique them.
+ /// Object files and debug symbols often use mangled string to represent the
+ /// linkage name for a symbol, function or global. The string pool can
+ /// efficiently store these values and their counterparts so when we run
+ /// into another instance of a mangled name, we can avoid calling the name
+ /// demangler over and over on the same strings and then trying to unique
+ /// them.
///
/// @param[in] counterpart
/// A reference to a ConstString object that might get filled in
@@ -413,14 +408,13 @@ public:
/// Set the C string value with length.
///
/// Set the string value in the object by uniquing \a cstr_len bytes
- /// starting at the \a cstr string value in our global string pool.
- /// If trim is true, then \a cstr_len indicates a maximum length of
- /// the CString and if the actual length of the string is less, then
- /// it will be trimmed.
+ /// starting at the \a cstr string value in our global string pool. If trim
+ /// is true, then \a cstr_len indicates a maximum length of the CString and
+ /// if the actual length of the string is less, then it will be trimmed.
///
- /// If the C string already exists in the global string pool, it
- /// finds the current entry and returns the existing value. If it
- /// doesn't exist, it is added to the string pool.
+ /// If the C string already exists in the global string pool, it finds the
+ /// current entry and returns the existing value. If it doesn't exist, it is
+ /// added to the string pool.
///
/// @param[in] cstr
/// A NULL terminated C string to add to the string pool.
@@ -431,20 +425,19 @@ public:
void SetCStringWithLength(const char *cstr, size_t cstr_len);
//------------------------------------------------------------------
- /// Set the C string value with the minimum length between
- /// \a fixed_cstr_len and the actual length of the C string. This
- /// can be used for data structures that have a fixed length to
- /// store a C string where the string might not be NULL terminated
- /// if the string takes the entire buffer.
+ /// Set the C string value with the minimum length between \a fixed_cstr_len
+ /// and the actual length of the C string. This can be used for data
+ /// structures that have a fixed length to store a C string where the string
+ /// might not be NULL terminated if the string takes the entire buffer.
//------------------------------------------------------------------
void SetTrimmedCStringWithLength(const char *cstr, size_t fixed_cstr_len);
//------------------------------------------------------------------
/// Get the memory cost of this object.
///
- /// Return the size in bytes that this object takes in memory. This
- /// returns the size in bytes of this object, which does not include
- /// any the shared string values it may refer to.
+ /// Return the size in bytes that this object takes in memory. This returns
+ /// the size in bytes of this object, which does not include any the shared
+ /// string values it may refer to.
///
/// @return
/// The number of bytes that this object occupies in memory.
@@ -456,9 +449,8 @@ public:
//------------------------------------------------------------------
/// Get the size in bytes of the current global string pool.
///
- /// Reports the size in bytes of all shared C string values,
- /// containers and any other values as a byte size for the
- /// entire string pool.
+ /// Reports the size in bytes of all shared C string values, containers and
+ /// any other values as a byte size for the entire string pool.
///
/// @return
/// The number of bytes that the global string pool occupies
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/DataBuffer.h b/contrib/llvm/tools/lldb/include/lldb/Utility/DataBuffer.h
index ffa71c06be80..05cb60920737 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/DataBuffer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/DataBuffer.h
@@ -22,39 +22,36 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h"
-/// @brief A pure virtual protocol class for abstracted data buffers.
+/// A pure virtual protocol class for abstracted data buffers.
///
/// DataBuffer is an abstract class that gets packaged into a shared pointer
-/// that can use to implement various ways to store data (on the heap,
-/// memory mapped, cached inferior memory). It gets used by DataExtractor
-/// so many DataExtractor objects can share the same data and sub-ranges
-/// of that shared data, and the last object that contains a reference
-/// to the shared data will free it.
+/// that can use to implement various ways to store data (on the heap, memory
+/// mapped, cached inferior memory). It gets used by DataExtractor so many
+/// DataExtractor objects can share the same data and sub-ranges of that
+/// shared data, and the last object that contains a reference to the shared
+/// data will free it.
///
/// Subclasses can implement as many different constructors or member
-/// functions that allow data to be stored in the object's buffer prior
-/// to handing the shared data to clients that use these buffers.
+/// functions that allow data to be stored in the object's buffer prior to
+/// handing the shared data to clients that use these buffers.
///
-/// All subclasses must override all of the pure virtual functions as
-/// they are used by clients to access the data. Having a common
-/// interface allows different ways of storing data, yet using it in
-/// one common way.
+/// All subclasses must override all of the pure virtual functions as they are
+/// used by clients to access the data. Having a common interface allows
+/// different ways of storing data, yet using it in one common way.
///
-/// This class currently expects all data to be available without any
-/// extra calls being made, but we can modify it to optionally get
-/// data on demand with some extra function calls to load the data
-/// before it gets accessed.
+/// This class currently expects all data to be available without any extra
+/// calls being made, but we can modify it to optionally get data on demand
+/// with some extra function calls to load the data before it gets accessed.
//----------------------------------------------------------------------
class DataBuffer {
public:
//------------------------------------------------------------------
/// Destructor
///
- /// The destructor is virtual as other classes will inherit from
- /// this class and be downcast to the DataBuffer pure virtual
- /// interface. The virtual destructor ensures that destructing the
- /// base class will destruct the class that inherited from it
- /// correctly.
+ /// The destructor is virtual as other classes will inherit from this class
+ /// and be downcast to the DataBuffer pure virtual interface. The virtual
+ /// destructor ensures that destructing the base class will destruct the
+ /// class that inherited from it correctly.
//------------------------------------------------------------------
virtual ~DataBuffer() {}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferHeap.h b/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferHeap.h
index 20e27ef8950c..d64e5b7563a9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferHeap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferHeap.h
@@ -21,14 +21,14 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class DataBufferHeap DataBufferHeap.h "lldb/Core/DataBufferHeap.h"
-/// @brief A subclass of DataBuffer that stores a data buffer on the heap.
+/// A subclass of DataBuffer that stores a data buffer on the heap.
///
-/// This class keeps its data in a heap based buffer that is owned by
-/// the object. This class is best used to store chunks of data that
-/// are created or read from sources that can't intelligently and lazily
-/// fault new data pages in. Large amounts of data that comes from files
-/// should probably use DataBufferLLVM, which can intelligently determine
-/// when memory mapping is optimal.
+/// This class keeps its data in a heap based buffer that is owned by the
+/// object. This class is best used to store chunks of data that are created
+/// or read from sources that can't intelligently and lazily fault new data
+/// pages in. Large amounts of data that comes from files should probably use
+/// DataBufferLLVM, which can intelligently determine when memory mapping is
+/// optimal.
//----------------------------------------------------------------------
class DataBufferHeap : public DataBuffer {
public:
@@ -42,8 +42,7 @@ public:
//------------------------------------------------------------------
/// Construct with size \a n and fill with \a ch.
///
- /// Initialize this class with \a n bytes and fills the buffer with
- /// \a ch.
+ /// Initialize this class with \a n bytes and fills the buffer with \a ch.
///
/// @param[in] n
/// The number of bytes that heap based buffer should contain.
@@ -67,8 +66,8 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// Virtual destructor since this class inherits from a pure virtual
- /// base class #DataBuffer.
+ /// Virtual destructor since this class inherits from a pure virtual base
+ /// class #DataBuffer.
//------------------------------------------------------------------
~DataBufferHeap() override;
@@ -90,8 +89,8 @@ public:
//------------------------------------------------------------------
/// Set the number of bytes in the data buffer.
///
- /// Sets the number of bytes that this object should be able to
- /// contain. This can be used prior to copying data into the buffer.
+ /// Sets the number of bytes that this object should be able to contain.
+ /// This can be used prior to copying data into the buffer.
///
/// @param[in] byte_size
/// The new size in bytes that this data buffer should attempt
@@ -123,8 +122,8 @@ public:
private:
//------------------------------------------------------------------
- // This object uses a std::vector<uint8_t> to store its data. This
- // takes care of free the data when the object is deleted.
+ // This object uses a std::vector<uint8_t> to store its data. This takes care
+ // of free the data when the object is deleted.
//------------------------------------------------------------------
typedef std::vector<uint8_t> buffer_t; ///< Buffer type
buffer_t m_data; ///< The heap based buffer where data is stored
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferLLVM.h b/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferLLVM.h
index 0eb229cffbe2..d76582cbf47c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferLLVM.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/DataBufferLLVM.h
@@ -40,8 +40,8 @@ public:
char *GetChars() { return reinterpret_cast<char *>(GetBytes()); }
private:
- /// \brief Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a
- /// valid pointer.
+ /// Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a valid
+ /// pointer.
explicit DataBufferLLVM(std::unique_ptr<llvm::WritableMemoryBuffer> Buffer);
std::unique_ptr<llvm::WritableMemoryBuffer> Buffer;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/DataEncoder.h b/contrib/llvm/tools/lldb/include/lldb/Utility/DataEncoder.h
index ea347d86237b..c1214705c726 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/DataEncoder.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/DataEncoder.h
@@ -23,13 +23,12 @@
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class DataEncoder DataEncoder.h "lldb/Core/DataEncoder.h"
-/// @brief An binary data encoding class.
+/// @class DataEncoder DataEncoder.h "lldb/Core/DataEncoder.h" An binary data
+/// encoding class.
///
-/// DataEncoder is a class that can encode binary data (swapping if needed)
-/// to a data buffer. The data buffer can be caller owned, or can be
-/// shared data that can be shared between multiple DataEncoder or
-/// DataEncoder instances.
+/// DataEncoder is a class that can encode binary data (swapping if needed) to
+/// a data buffer. The data buffer can be caller owned, or can be shared data
+/// that can be shared between multiple DataEncoder or DataEncoder instances.
///
/// @see DataBuffer
//----------------------------------------------------------------------
@@ -45,9 +44,8 @@ public:
//------------------------------------------------------------------
/// Construct with a buffer that is owned by the caller.
///
- /// This constructor allows us to use data that is owned by the
- /// caller. The data must stay around as long as this object is
- /// valid.
+ /// This constructor allows us to use data that is owned by the caller. The
+ /// data must stay around as long as this object is valid.
///
/// @param[in] data
/// A pointer to caller owned data.
@@ -67,10 +65,10 @@ public:
//------------------------------------------------------------------
/// Construct with shared data.
///
- /// Copies the data shared pointer which adds a reference to the
- /// contained in \a data_sp. The shared data reference is reference
- /// counted to ensure the data lives as long as anyone still has a
- /// valid shared pointer to the data in \a data_sp.
+ /// Copies the data shared pointer which adds a reference to the contained
+ /// in \a data_sp. The shared data reference is reference counted to ensure
+ /// the data lives as long as anyone still has a valid shared pointer to the
+ /// data in \a data_sp.
///
/// @param[in] data_sp
/// A shared pointer to data.
@@ -87,26 +85,24 @@ public:
//------------------------------------------------------------------
/// Destructor
///
- /// If this object contains a valid shared data reference, the
- /// reference count on the data will be decremented, and if zero,
- /// the data will be freed.
+ /// If this object contains a valid shared data reference, the reference
+ /// count on the data will be decremented, and if zero, the data will be
+ /// freed.
//------------------------------------------------------------------
~DataEncoder();
//------------------------------------------------------------------
/// Clears the object state.
///
- /// Clears the object contents back to a default invalid state, and
- /// release any references to shared data that this object may
- /// contain.
+ /// Clears the object contents back to a default invalid state, and release
+ /// any references to shared data that this object may contain.
//------------------------------------------------------------------
void Clear();
//------------------------------------------------------------------
/// Get the current address size.
///
- /// Return the size in bytes of any address values this object will
- /// extract.
+ /// Return the size in bytes of any address values this object will extract.
///
/// @return
/// The size in bytes of address values that will be extracted.
@@ -135,8 +131,7 @@ public:
//------------------------------------------------------------------
/// Get the shared data offset.
///
- /// Get the offset of the first byte of data in the shared data (if
- /// any).
+ /// Get the offset of the first byte of data in the shared data (if any).
///
/// @return
/// If this object contains shared data, this function returns
@@ -189,11 +184,10 @@ public:
//------------------------------------------------------------------
/// Encode an unsigned integer of size \a byte_size to \a offset.
///
- /// Encode a single integer value at \a offset and return the offset
- /// that follows the newly encoded integer when the data is successfully
- /// encoded into the existing data. There must be enough room in the
- /// data, else UINT32_MAX will be returned to indicate that encoding
- /// failed.
+ /// Encode a single integer value at \a offset and return the offset that
+ /// follows the newly encoded integer when the data is successfully encoded
+ /// into the existing data. There must be enough room in the data, else
+ /// UINT32_MAX will be returned to indicate that encoding failed.
///
/// @param[in] offset
/// The offset within the contained data at which to put the
@@ -233,15 +227,14 @@ public:
uint32_t PutData(uint32_t offset, const void *src, uint32_t src_len);
//------------------------------------------------------------------
- /// Encode an address in the existing buffer at \a offset bytes into
- /// the buffer.
+ /// Encode an address in the existing buffer at \a offset bytes into the
+ /// buffer.
///
- /// Encode a single address (honoring the m_addr_size member) to
- /// the data and return the next offset where subsequent data would
- /// go.
- /// pointed to by \a offset_ptr. The size of the extracted address
- /// comes from the \a m_addr_size member variable and should be
- /// set correctly prior to extracting any address values.
+ /// Encode a single address (honoring the m_addr_size member) to the data
+ /// and return the next offset where subsequent data would go. pointed to by
+ /// \a offset_ptr. The size of the extracted address comes from the \a
+ /// m_addr_size member variable and should be set correctly prior to
+ /// extracting any address values.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -259,8 +252,7 @@ public:
//------------------------------------------------------------------
/// Put a C string to \a offset.
///
- /// Encodes a C string into the existing data including the
- /// terminating
+ /// Encodes a C string into the existing data including the terminating
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -282,8 +274,8 @@ public:
//------------------------------------------------------------------
/// Set the address byte size.
///
- /// Set the size in bytes that will be used when extracting any
- /// address and pointer values from data contained in this object.
+ /// Set the size in bytes that will be used when extracting any address and
+ /// pointer values from data contained in this object.
///
/// @param[in] addr_size
/// The size in bytes to use when extracting addresses.
@@ -293,11 +285,10 @@ public:
//------------------------------------------------------------------
/// Set data with a buffer that is caller owned.
///
- /// Use data that is owned by the caller when extracting values.
- /// The data must stay around as long as this object, or any object
- /// that copies a subset of this object's data, is valid. If \a
- /// bytes is NULL, or \a length is zero, this object will contain
- /// no data.
+ /// Use data that is owned by the caller when extracting values. The data
+ /// must stay around as long as this object, or any object that copies a
+ /// subset of this object's data, is valid. If \a bytes is NULL, or \a
+ /// length is zero, this object will contain no data.
///
/// @param[in] bytes
/// A pointer to caller owned data.
@@ -316,15 +307,14 @@ public:
//------------------------------------------------------------------
/// Adopt a subset of shared data in \a data_sp.
///
- /// Copies the data shared pointer which adds a reference to the
- /// contained in \a data_sp. The shared data reference is reference
- /// counted to ensure the data lives as long as anyone still has a
- /// valid shared pointer to the data in \a data_sp. The byte order
- /// and address byte size settings remain the same. If
- /// \a offset is not a valid offset in \a data_sp, then no reference
- /// to the shared data will be added. If there are not \a length
- /// bytes available in \a data starting at \a offset, the length
- /// will be truncated to contains as many bytes as possible.
+ /// Copies the data shared pointer which adds a reference to the contained
+ /// in \a data_sp. The shared data reference is reference counted to ensure
+ /// the data lives as long as anyone still has a valid shared pointer to the
+ /// data in \a data_sp. The byte order and address byte size settings remain
+ /// the same. If \a offset is not a valid offset in \a data_sp, then no
+ /// reference to the shared data will be added. If there are not \a length
+ /// bytes available in \a data starting at \a offset, the length will be
+ /// truncated to contains as many bytes as possible.
///
/// @param[in] data_sp
/// A shared pointer to data.
@@ -344,8 +334,8 @@ public:
//------------------------------------------------------------------
/// Set the byte_order value.
///
- /// Sets the byte order of the data to extract. Extracted values
- /// will be swapped if necessary when decoding.
+ /// Sets the byte order of the data to extract. Extracted values will be
+ /// swapped if necessary when decoding.
///
/// @param[in] byte_order
/// The byte order value to use when extracting data.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/DataExtractor.h b/contrib/llvm/tools/lldb/include/lldb/Utility/DataExtractor.h
index 8107a3554422..50c88db8e358 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/DataExtractor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/DataExtractor.h
@@ -34,16 +34,16 @@ template <typename T> class SmallVectorImpl;
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class DataExtractor DataExtractor.h "lldb/Core/DataExtractor.h"
-/// @brief An data extractor class.
+/// @class DataExtractor DataExtractor.h "lldb/Core/DataExtractor.h" An data
+/// extractor class.
///
-/// DataExtractor is a class that can extract data (swapping if needed)
-/// from a data buffer. The data buffer can be caller owned, or can be
-/// shared data that can be shared between multiple DataExtractor
-/// instances. Multiple DataExtractor objects can share the same data,
-/// yet extract values in different address sizes and byte order modes.
-/// Each object can have a unique position in the shared data and extract
-/// data from different offsets.
+/// DataExtractor is a class that can extract data (swapping if needed) from a
+/// data buffer. The data buffer can be caller owned, or can be shared data
+/// that can be shared between multiple DataExtractor instances. Multiple
+/// DataExtractor objects can share the same data, yet extract values in
+/// different address sizes and byte order modes. Each object can have a
+/// unique position in the shared data and extract data from different
+/// offsets.
///
/// @see DataBuffer
//----------------------------------------------------------------------
@@ -51,7 +51,7 @@ class DataExtractor {
public:
//------------------------------------------------------------------
/// @typedef DataExtractor::Type
- /// @brief Type enumerations used in the dump routines.
+ /// Type enumerations used in the dump routines.
//------------------------------------------------------------------
typedef enum {
TypeUInt8, ///< Format output as unsigned 8 bit integers
@@ -74,9 +74,8 @@ public:
//------------------------------------------------------------------
/// Construct with a buffer that is owned by the caller.
///
- /// This constructor allows us to use data that is owned by the
- /// caller. The data must stay around as long as this object is
- /// valid.
+ /// This constructor allows us to use data that is owned by the caller. The
+ /// data must stay around as long as this object is valid.
///
/// @param[in] data
/// A pointer to caller owned data.
@@ -100,10 +99,10 @@ public:
//------------------------------------------------------------------
/// Construct with shared data.
///
- /// Copies the data shared pointer which adds a reference to the
- /// contained in \a data_sp. The shared data reference is reference
- /// counted to ensure the data lives as long as anyone still has a
- /// valid shared pointer to the data in \a data_sp.
+ /// Copies the data shared pointer which adds a reference to the contained
+ /// in \a data_sp. The shared data reference is reference counted to ensure
+ /// the data lives as long as anyone still has a valid shared pointer to the
+ /// data in \a data_sp.
///
/// @param[in] data_sp
/// A shared pointer to data.
@@ -123,16 +122,14 @@ public:
//------------------------------------------------------------------
/// Construct with a subset of \a data.
///
- /// Initialize this object with a subset of the data bytes in \a
- /// data. If \a data contains shared data, then a reference to the
- /// shared data will be added to ensure the shared data stays around
- /// as long as any objects have references to the shared data. The
- /// byte order value and the address size settings are copied from \a
- /// data. If \a offset is not a valid offset in \a data, then no
- /// reference to the shared data will be added. If there are not
- /// \a length bytes available in \a data starting at \a offset,
- /// the length will be truncated to contain as many bytes as
- /// possible.
+ /// Initialize this object with a subset of the data bytes in \a data. If \a
+ /// data contains shared data, then a reference to the shared data will be
+ /// added to ensure the shared data stays around as long as any objects have
+ /// references to the shared data. The byte order value and the address size
+ /// settings are copied from \a data. If \a offset is not a valid offset in
+ /// \a data, then no reference to the shared data will be added. If there
+ /// are not \a length bytes available in \a data starting at \a offset, the
+ /// length will be truncated to contain as many bytes as possible.
///
/// @param[in] data
/// Another DataExtractor object that contains data.
@@ -155,8 +152,8 @@ public:
/// Assignment operator.
///
/// Copies all data, byte order and address size settings from \a rhs into
- /// this object. If \a rhs contains shared data, a reference to that
- /// shared data will be added.
+ /// this object. If \a rhs contains shared data, a reference to that shared
+ /// data will be added.
///
/// @param[in] rhs
/// Another DataExtractor object to copy.
@@ -169,9 +166,9 @@ public:
//------------------------------------------------------------------
/// Destructor
///
- /// If this object contains a valid shared data reference, the
- /// reference count on the data will be decremented, and if zero,
- /// the data will be freed.
+ /// If this object contains a valid shared data reference, the reference
+ /// count on the data will be decremented, and if zero, the data will be
+ /// freed.
//------------------------------------------------------------------
virtual ~DataExtractor();
@@ -180,19 +177,17 @@ public:
//------------------------------------------------------------------
/// Clears the object state.
///
- /// Clears the object contents back to a default invalid state, and
- /// release any references to shared data that this object may
- /// contain.
+ /// Clears the object contents back to a default invalid state, and release
+ /// any references to shared data that this object may contain.
//------------------------------------------------------------------
void Clear();
//------------------------------------------------------------------
- /// Dumps the binary data as \a type objects to stream \a s (or to
- /// Log() if \a s is nullptr) starting \a offset bytes into the data
- /// and stopping after dumping \a length bytes. The offset into the
- /// data is displayed at the beginning of each line and can be
- /// offset by base address \a base_addr. \a num_per_line objects
- /// will be displayed on each line.
+ /// Dumps the binary data as \a type objects to stream \a s (or to Log() if
+ /// \a s is nullptr) starting \a offset bytes into the data and stopping
+ /// after dumping \a length bytes. The offset into the data is displayed at
+ /// the beginning of each line and can be offset by base address \a
+ /// base_addr. \a num_per_line objects will be displayed on each line.
///
/// @param[in] s
/// The stream to dump the output to. If nullptr the output will
@@ -228,29 +223,11 @@ public:
const char *type_format = nullptr) const;
//------------------------------------------------------------------
- /// Dump a UUID value at \a offset.
+ /// Extract an arbitrary number of bytes in the specified byte order.
///
- /// Dump a UUID starting at \a offset bytes into this object's data.
- /// If the stream \a s is nullptr, the output will be sent to Log().
- ///
- /// @param[in] s
- /// The stream to dump the output to. If nullptr the output will
- /// be dumped to Log().
- ///
- /// @param[in] offset
- /// The offset into the data at which to extract and dump a
- /// UUID value.
- //------------------------------------------------------------------
- void DumpUUID(Stream *s, lldb::offset_t offset) const;
-
- //------------------------------------------------------------------
- /// Extract an arbitrary number of bytes in the specified byte
- /// order.
- ///
- /// Attemps to extract \a length bytes starting at \a offset bytes
- /// into this data in the requested byte order (\a dst_byte_order)
- /// and place the results in \a dst. \a dst must be at least \a
- /// length bytes long.
+ /// Attemps to extract \a length bytes starting at \a offset bytes into this
+ /// data in the requested byte order (\a dst_byte_order) and place the
+ /// results in \a dst. \a dst must be at least \a length bytes long.
///
/// @param[in] offset
/// The offset in bytes into the contained data at which to
@@ -278,10 +255,10 @@ public:
//------------------------------------------------------------------
/// Extract an address from \a *offset_ptr.
///
- /// Extract a single address from the data and update the offset
- /// pointed to by \a offset_ptr. The size of the extracted address
- /// comes from the \a m_addr_size member variable and should be
- /// set correctly prior to extracting any address values.
+ /// Extract a single address from the data and update the offset pointed to
+ /// by \a offset_ptr. The size of the extracted address comes from the \a
+ /// m_addr_size member variable and should be set correctly prior to
+ /// extracting any address values.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -300,8 +277,7 @@ public:
//------------------------------------------------------------------
/// Get the current address size.
///
- /// Return the size in bytes of any address values this object will
- /// extract.
+ /// Return the size in bytes of any address values this object will extract.
///
/// @return
/// The size in bytes of address values that will be extracted.
@@ -319,11 +295,10 @@ public:
//------------------------------------------------------------------
/// Extract a C string from \a *offset_ptr.
///
- /// Returns a pointer to a C String from the data at the offset
- /// pointed to by \a offset_ptr. A variable length NULL terminated C
- /// string will be extracted and the \a offset_ptr will be
- /// updated with the offset of the byte that follows the NULL
- /// terminator byte.
+ /// Returns a pointer to a C String from the data at the offset pointed to
+ /// by \a offset_ptr. A variable length NULL terminated C string will be
+ /// extracted and the \a offset_ptr will be updated with the offset of the
+ /// byte that follows the NULL terminator byte.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -343,8 +318,8 @@ public:
//------------------------------------------------------------------
/// Extract a C string from \a *offset_ptr with field size \a len.
///
- /// Returns a pointer to a C String from the data at the offset
- /// pointed to by \a offset_ptr, with a field length of \a len.
+ /// Returns a pointer to a C String from the data at the offset pointed to
+ /// by \a offset_ptr, with a field length of \a len.
/// A NULL terminated C string will be extracted and the \a offset_ptr
/// will be updated with the offset of the byte that follows the fixed
/// length field.
@@ -367,10 +342,10 @@ public:
//------------------------------------------------------------------
/// Extract \a length bytes from \a *offset_ptr.
///
- /// Returns a pointer to a bytes in this object's data at the offset
- /// pointed to by \a offset_ptr. If \a length is zero or too large,
- /// then the offset pointed to by \a offset_ptr will not be updated
- /// and nullptr will be returned.
+ /// Returns a pointer to a bytes in this object's data at the offset pointed
+ /// to by \a offset_ptr. If \a length is zero or too large, then the offset
+ /// pointed to by \a offset_ptr will not be updated and nullptr will be
+ /// returned.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -414,17 +389,16 @@ public:
void *dst) const;
//------------------------------------------------------------------
- /// Copy \a dst_len bytes from \a *offset_ptr and ensure the copied
- /// data is treated as a value that can be swapped to match the
- /// specified byte order.
+ /// Copy \a dst_len bytes from \a *offset_ptr and ensure the copied data is
+ /// treated as a value that can be swapped to match the specified byte
+ /// order.
///
- /// For values that are larger than the supported integer sizes,
- /// this function can be used to extract data in a specified byte
- /// order. It can also be used to copy a smaller integer value from
- /// to a larger value. The extra bytes left over will be padded
- /// correctly according to the byte order of this object and the
- /// \a dst_byte_order. This can be very handy when say copying a
- /// partial data value into a register.
+ /// For values that are larger than the supported integer sizes, this
+ /// function can be used to extract data in a specified byte order. It can
+ /// also be used to copy a smaller integer value from to a larger value. The
+ /// extra bytes left over will be padded correctly according to the byte
+ /// order of this object and the \a dst_byte_order. This can be very handy
+ /// when say copying a partial data value into a register.
///
/// @param[in] src_offset
/// The offset into this data from which to start copying an
@@ -469,8 +443,7 @@ public:
//------------------------------------------------------------------
/// Get the shared data offset.
///
- /// Get the offset of the first byte of data in the shared data (if
- /// any).
+ /// Get the offset of the first byte of data in the shared data (if any).
///
/// @return
/// If this object contains shared data, this function returns
@@ -511,10 +484,10 @@ public:
//------------------------------------------------------------------
/// Extract an integer of size \a byte_size from \a *offset_ptr.
///
- /// Extract a single integer value and update the offset pointed to
- /// by \a offset_ptr. The size of the extracted integer is specified
- /// by the \a byte_size argument. \a byte_size must have a value
- /// >= 1 and <= 4 since the return value is only 32 bits wide.
+ /// Extract a single integer value and update the offset pointed to by \a
+ /// offset_ptr. The size of the extracted integer is specified by the \a
+ /// byte_size argument. \a byte_size must have a value >= 1 and <= 4 since
+ /// the return value is only 32 bits wide.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -532,14 +505,13 @@ public:
uint32_t GetMaxU32(lldb::offset_t *offset_ptr, size_t byte_size) const;
//------------------------------------------------------------------
- /// Extract an unsigned integer of size \a byte_size from \a
- /// *offset_ptr.
+ /// Extract an unsigned integer of size \a byte_size from \a *offset_ptr.
///
- /// Extract a single unsigned integer value and update the offset
- /// pointed to by \a offset_ptr. The size of the extracted integer
- /// is specified by the \a byte_size argument. \a byte_size must
- /// have a value greater than or equal to one and less than or equal
- /// to eight since the return value is 64 bits wide.
+ /// Extract a single unsigned integer value and update the offset pointed to
+ /// by \a offset_ptr. The size of the extracted integer is specified by the
+ /// \a byte_size argument. \a byte_size must have a value greater than or
+ /// equal to one and less than or equal to eight since the return value is
+ /// 64 bits wide.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -563,12 +535,11 @@ public:
//------------------------------------------------------------------
/// Extract an signed integer of size \a byte_size from \a *offset_ptr.
///
- /// Extract a single signed integer value (sign extending if required)
- /// and update the offset pointed to by \a offset_ptr. The size of
- /// the extracted integer is specified by the \a byte_size argument.
- /// \a byte_size must have a value greater than or equal to one and
- /// less than or equal to eight since the return value is 64 bits
- /// wide.
+ /// Extract a single signed integer value (sign extending if required) and
+ /// update the offset pointed to by \a offset_ptr. The size of the extracted
+ /// integer is specified by the \a byte_size argument. \a byte_size must
+ /// have a value greater than or equal to one and less than or equal to
+ /// eight since the return value is 64 bits wide.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -587,15 +558,15 @@ public:
int64_t GetMaxS64(lldb::offset_t *offset_ptr, size_t byte_size) const;
//------------------------------------------------------------------
- /// Extract an unsigned integer of size \a byte_size from \a
- /// *offset_ptr, then extract the bitfield from this value if
- /// \a bitfield_bit_size is non-zero.
+ /// Extract an unsigned integer of size \a byte_size from \a *offset_ptr,
+ /// then extract the bitfield from this value if \a bitfield_bit_size is
+ /// non-zero.
///
- /// Extract a single unsigned integer value and update the offset
- /// pointed to by \a offset_ptr. The size of the extracted integer
- /// is specified by the \a byte_size argument. \a byte_size must
- /// have a value greater than or equal to one and less than or equal
- /// to 8 since the return value is 64 bits wide.
+ /// Extract a single unsigned integer value and update the offset pointed to
+ /// by \a offset_ptr. The size of the extracted integer is specified by the
+ /// \a byte_size argument. \a byte_size must have a value greater than or
+ /// equal to one and less than or equal to 8 since the return value is 64
+ /// bits wide.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -627,16 +598,15 @@ public:
uint32_t bitfield_bit_offset) const;
//------------------------------------------------------------------
- /// Extract an signed integer of size \a byte_size from \a
- /// *offset_ptr, then extract and signe extend the bitfield from
- /// this value if \a bitfield_bit_size is non-zero.
+ /// Extract an signed integer of size \a byte_size from \a *offset_ptr, then
+ /// extract and signe extend the bitfield from this value if \a
+ /// bitfield_bit_size is non-zero.
///
- /// Extract a single signed integer value (sign extending if required)
- /// and update the offset pointed to by \a offset_ptr. The size of
- /// the extracted integer is specified by the \a byte_size argument.
- /// \a byte_size must have a value greater than or equal to one and
- /// less than or equal to eight since the return value is 64 bits
- /// wide.
+ /// Extract a single signed integer value (sign extending if required) and
+ /// update the offset pointed to by \a offset_ptr. The size of the extracted
+ /// integer is specified by the \a byte_size argument. \a byte_size must
+ /// have a value greater than or equal to one and less than or equal to
+ /// eight since the return value is 64 bits wide.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -670,10 +640,10 @@ public:
//------------------------------------------------------------------
/// Extract an pointer from \a *offset_ptr.
///
- /// Extract a single pointer from the data and update the offset
- /// pointed to by \a offset_ptr. The size of the extracted pointer
- /// comes from the \a m_addr_size member variable and should be
- /// set correctly prior to extracting any pointer values.
+ /// Extract a single pointer from the data and update the offset pointed to
+ /// by \a offset_ptr. The size of the extracted pointer comes from the \a
+ /// m_addr_size member variable and should be set correctly prior to
+ /// extracting any pointer values.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -699,8 +669,8 @@ public:
//------------------------------------------------------------------
/// Extract a uint8_t value from \a *offset_ptr.
///
- /// Extract a single uint8_t from the binary data at the offset
- /// pointed to by \a offset_ptr, and advance the offset on success.
+ /// Extract a single uint8_t from the binary data at the offset pointed to
+ /// by \a offset_ptr, and advance the offset on success.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -728,9 +698,9 @@ public:
//------------------------------------------------------------------
/// Extract \a count uint8_t values from \a *offset_ptr.
///
- /// Extract \a count uint8_t values from the binary data at the
- /// offset pointed to by \a offset_ptr, and advance the offset on
- /// success. The extracted values are copied into \a dst.
+ /// Extract \a count uint8_t values from the binary data at the offset
+ /// pointed to by \a offset_ptr, and advance the offset on success. The
+ /// extracted values are copied into \a dst.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -755,8 +725,8 @@ public:
//------------------------------------------------------------------
/// Extract a uint16_t value from \a *offset_ptr.
///
- /// Extract a single uint16_t from the binary data at the offset
- /// pointed to by \a offset_ptr, and update the offset on success.
+ /// Extract a single uint16_t from the binary data at the offset pointed to
+ /// by \a offset_ptr, and update the offset on success.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -773,9 +743,9 @@ public:
//------------------------------------------------------------------
/// Extract \a count uint16_t values from \a *offset_ptr.
///
- /// Extract \a count uint16_t values from the binary data at the
- /// offset pointed to by \a offset_ptr, and advance the offset on
- /// success. The extracted values are copied into \a dst.
+ /// Extract \a count uint16_t values from the binary data at the offset
+ /// pointed to by \a offset_ptr, and advance the offset on success. The
+ /// extracted values are copied into \a dst.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -800,8 +770,8 @@ public:
//------------------------------------------------------------------
/// Extract a uint32_t value from \a *offset_ptr.
///
- /// Extract a single uint32_t from the binary data at the offset
- /// pointed to by \a offset_ptr, and update the offset on success.
+ /// Extract a single uint32_t from the binary data at the offset pointed to
+ /// by \a offset_ptr, and update the offset on success.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -818,9 +788,9 @@ public:
//------------------------------------------------------------------
/// Extract \a count uint32_t values from \a *offset_ptr.
///
- /// Extract \a count uint32_t values from the binary data at the
- /// offset pointed to by \a offset_ptr, and advance the offset on
- /// success. The extracted values are copied into \a dst.
+ /// Extract \a count uint32_t values from the binary data at the offset
+ /// pointed to by \a offset_ptr, and advance the offset on success. The
+ /// extracted values are copied into \a dst.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -845,8 +815,8 @@ public:
//------------------------------------------------------------------
/// Extract a uint64_t value from \a *offset_ptr.
///
- /// Extract a single uint64_t from the binary data at the offset
- /// pointed to by \a offset_ptr, and update the offset on success.
+ /// Extract a single uint64_t from the binary data at the offset pointed to
+ /// by \a offset_ptr, and update the offset on success.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -863,9 +833,9 @@ public:
//------------------------------------------------------------------
/// Extract \a count uint64_t values from \a *offset_ptr.
///
- /// Extract \a count uint64_t values from the binary data at the
- /// offset pointed to by \a offset_ptr, and advance the offset on
- /// success. The extracted values are copied into \a dst.
+ /// Extract \a count uint64_t values from the binary data at the offset
+ /// pointed to by \a offset_ptr, and advance the offset on success. The
+ /// extracted values are copied into \a dst.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -890,10 +860,10 @@ public:
//------------------------------------------------------------------
/// Extract a signed LEB128 value from \a *offset_ptr.
///
- /// Extracts an signed LEB128 number from this object's data
- /// starting at the offset pointed to by \a offset_ptr. The offset
- /// pointed to by \a offset_ptr will be updated with the offset of
- /// the byte following the last extracted byte.
+ /// Extracts an signed LEB128 number from this object's data starting at the
+ /// offset pointed to by \a offset_ptr. The offset pointed to by \a
+ /// offset_ptr will be updated with the offset of the byte following the
+ /// last extracted byte.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -910,10 +880,10 @@ public:
//------------------------------------------------------------------
/// Extract a unsigned LEB128 value from \a *offset_ptr.
///
- /// Extracts an unsigned LEB128 number from this object's data
- /// starting at the offset pointed to by \a offset_ptr. The offset
- /// pointed to by \a offset_ptr will be updated with the offset of
- /// the byte following the last extracted byte.
+ /// Extracts an unsigned LEB128 number from this object's data starting at
+ /// the offset pointed to by \a offset_ptr. The offset pointed to by \a
+ /// offset_ptr will be updated with the offset of the byte following the
+ /// last extracted byte.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -932,9 +902,9 @@ public:
//------------------------------------------------------------------
/// Peek at a C string at \a offset.
///
- /// Peeks at a string in the contained data. No verification is done
- /// to make sure the entire string lies within the bounds of this
- /// object's data, only \a offset is verified to be a valid offset.
+ /// Peeks at a string in the contained data. No verification is done to make
+ /// sure the entire string lies within the bounds of this object's data,
+ /// only \a offset is verified to be a valid offset.
///
/// @param[in] offset
/// An offset into the data.
@@ -948,8 +918,8 @@ public:
//------------------------------------------------------------------
/// Peek at a bytes at \a offset.
///
- /// Returns a pointer to \a length bytes at \a offset as long as
- /// there are \a length bytes available starting at \a offset.
+ /// Returns a pointer to \a length bytes at \a offset as long as there are
+ /// \a length bytes available starting at \a offset.
///
/// @return
/// A non-nullptr data pointer if \a offset is a valid offset and
@@ -965,8 +935,8 @@ public:
//------------------------------------------------------------------
/// Set the address byte size.
///
- /// Set the size in bytes that will be used when extracting any
- /// address and pointer values from data contained in this object.
+ /// Set the size in bytes that will be used when extracting any address and
+ /// pointer values from data contained in this object.
///
/// @param[in] addr_size
/// The size in bytes to use when extracting addresses.
@@ -981,11 +951,10 @@ public:
//------------------------------------------------------------------
/// Set data with a buffer that is caller owned.
///
- /// Use data that is owned by the caller when extracting values.
- /// The data must stay around as long as this object, or any object
- /// that copies a subset of this object's data, is valid. If \a
- /// bytes is nullptr, or \a length is zero, this object will contain
- /// no data.
+ /// Use data that is owned by the caller when extracting values. The data
+ /// must stay around as long as this object, or any object that copies a
+ /// subset of this object's data, is valid. If \a bytes is nullptr, or \a
+ /// length is zero, this object will contain no data.
///
/// @param[in] bytes
/// A pointer to caller owned data.
@@ -1005,16 +974,14 @@ public:
//------------------------------------------------------------------
/// Adopt a subset of \a data.
///
- /// Set this object's data to be a subset of the data bytes in \a
- /// data. If \a data contains shared data, then a reference to the
- /// shared data will be added to ensure the shared data stays around
- /// as long as any objects have references to the shared data. The
- /// byte order and the address size settings are copied from \a
- /// data. If \a offset is not a valid offset in \a data, then no
- /// reference to the shared data will be added. If there are not
- /// \a length bytes available in \a data starting at \a offset,
- /// the length will be truncated to contains as many bytes as
- /// possible.
+ /// Set this object's data to be a subset of the data bytes in \a data. If
+ /// \a data contains shared data, then a reference to the shared data will
+ /// be added to ensure the shared data stays around as long as any objects
+ /// have references to the shared data. The byte order and the address size
+ /// settings are copied from \a data. If \a offset is not a valid offset in
+ /// \a data, then no reference to the shared data will be added. If there
+ /// are not \a length bytes available in \a data starting at \a offset, the
+ /// length will be truncated to contains as many bytes as possible.
///
/// @param[in] data
/// Another DataExtractor object that contains data.
@@ -1034,15 +1001,14 @@ public:
//------------------------------------------------------------------
/// Adopt a subset of shared data in \a data_sp.
///
- /// Copies the data shared pointer which adds a reference to the
- /// contained in \a data_sp. The shared data reference is reference
- /// counted to ensure the data lives as long as anyone still has a
- /// valid shared pointer to the data in \a data_sp. The byte order
- /// and address byte size settings remain the same. If
- /// \a offset is not a valid offset in \a data_sp, then no reference
- /// to the shared data will be added. If there are not \a length
- /// bytes available in \a data starting at \a offset, the length
- /// will be truncated to contains as many bytes as possible.
+ /// Copies the data shared pointer which adds a reference to the contained
+ /// in \a data_sp. The shared data reference is reference counted to ensure
+ /// the data lives as long as anyone still has a valid shared pointer to the
+ /// data in \a data_sp. The byte order and address byte size settings remain
+ /// the same. If \a offset is not a valid offset in \a data_sp, then no
+ /// reference to the shared data will be added. If there are not \a length
+ /// bytes available in \a data starting at \a offset, the length will be
+ /// truncated to contains as many bytes as possible.
///
/// @param[in] data_sp
/// A shared pointer to data.
@@ -1063,8 +1029,8 @@ public:
//------------------------------------------------------------------
/// Set the byte_order value.
///
- /// Sets the byte order of the data to extract. Extracted values
- /// will be swapped if necessary when decoding.
+ /// Sets the byte order of the data to extract. Extracted values will be
+ /// swapped if necessary when decoding.
///
/// @param[in] byte_order
/// The byte order value to use when extracting data.
@@ -1074,10 +1040,10 @@ public:
//------------------------------------------------------------------
/// Skip an LEB128 number at \a *offset_ptr.
///
- /// Skips a LEB128 number (signed or unsigned) from this object's
- /// data starting at the offset pointed to by \a offset_ptr. The
- /// offset pointed to by \a offset_ptr will be updated with the
- /// offset of the byte following the last extracted byte.
+ /// Skips a LEB128 number (signed or unsigned) from this object's data
+ /// starting at the offset pointed to by \a offset_ptr. The offset pointed
+ /// to by \a offset_ptr will be updated with the offset of the byte
+ /// following the last extracted byte.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Environment.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Environment.h
new file mode 100644
index 000000000000..ed0a36d7b3aa
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Environment.h
@@ -0,0 +1,96 @@
+//===-- Environment.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_ENVIRONMENT_H
+#define LLDB_UTILITY_ENVIRONMENT_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/FormatProviders.h"
+
+namespace lldb_private {
+
+class Environment : private llvm::StringMap<std::string> {
+ using Base = llvm::StringMap<std::string>;
+
+public:
+ class Envp {
+ public:
+ Envp(Envp &&RHS) = default;
+ Envp &operator=(Envp &&RHS) = default;
+
+ char *const *get() const { return Data; }
+ operator char *const *() const { return get(); }
+
+ private:
+ explicit Envp(const Environment &Env);
+ char *make_entry(llvm::StringRef Key, llvm::StringRef Value);
+ Envp(const Envp &) = delete;
+ Envp &operator=(const Envp &) = delete;
+ friend class Environment;
+
+ llvm::BumpPtrAllocator Allocator;
+ char **Data;
+ };
+
+ using Base::const_iterator;
+ using Base::iterator;
+ using Base::value_type;
+
+ using Base::begin;
+ using Base::clear;
+ using Base::count;
+ using Base::empty;
+ using Base::end;
+ using Base::erase;
+ using Base::find;
+ using Base::insert;
+ using Base::lookup;
+ using Base::size;
+ using Base::try_emplace;
+ using Base::operator[];
+
+ Environment() : Base() {}
+ Environment(const Environment &RHS) : Base(RHS) {}
+ Environment(Environment &&RHS) : Base(std::move(RHS)) {}
+ Environment(char *const *Env)
+ : Environment(const_cast<const char *const *>(Env)) {}
+ Environment(const char *const *Env);
+
+ Environment &operator=(Environment RHS) {
+ Base::operator=(std::move(RHS));
+ return *this;
+ }
+
+ std::pair<iterator, bool> insert(llvm::StringRef KeyEqValue) {
+ return insert(KeyEqValue.split('='));
+ }
+
+ void insert(const_iterator first, const_iterator last);
+
+ Envp getEnvp() const { return Envp(*this); }
+
+ static std::string compose(const value_type &KeyValue) {
+ return (KeyValue.first() + "=" + KeyValue.second).str();
+ }
+};
+
+} // namespace lldb_private
+
+namespace llvm {
+template <> struct format_provider<lldb_private::Environment> {
+ static void format(const lldb_private::Environment &Env, raw_ostream &Stream,
+ StringRef Style) {
+ for (const auto &KV : Env)
+ Stream << "env[" << KV.first() << "] = " << KV.second << "\n";
+ }
+};
+} // namespace llvm
+
+#endif // #ifndef LLDB_UTILITY_ENVIRONMENT_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/FileSpec.h b/contrib/llvm/tools/lldb/include/lldb/Utility/FileSpec.h
index 55d44d84087d..d062ba598ccc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/FileSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/FileSpec.h
@@ -19,9 +19,10 @@
// Project includes
#include "lldb/Utility/ConstString.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint64_t
@@ -43,37 +44,32 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class FileSpec FileSpec.h "lldb/Host/FileSpec.h"
-/// @brief A file utility class.
+/// A file utility class.
///
/// A file specification class that divides paths up into a directory
-/// and basename. These string values of the paths are put into uniqued
-/// string pools for fast comparisons and efficient memory usage.
+/// and basename. These string values of the paths are put into uniqued string
+/// pools for fast comparisons and efficient memory usage.
///
-/// Another reason the paths are split into the directory and basename
-/// is to allow efficient debugger searching. Often in a debugger the
-/// user types in the basename of the file, for example setting a
-/// breakpoint by file and line, or specifying a module (shared library)
-/// to limit the scope in which to execute a command. The user rarely
-/// types in a full path. When the paths are already split up, it makes
-/// it easy for us to compare only the basenames of a lot of file
-/// specifications without having to split up the file path each time
-/// to get to the basename.
+/// Another reason the paths are split into the directory and basename is to
+/// allow efficient debugger searching. Often in a debugger the user types in
+/// the basename of the file, for example setting a breakpoint by file and
+/// line, or specifying a module (shared library) to limit the scope in which
+/// to execute a command. The user rarely types in a full path. When the paths
+/// are already split up, it makes it easy for us to compare only the
+/// basenames of a lot of file specifications without having to split up the
+/// file path each time to get to the basename.
//----------------------------------------------------------------------
class FileSpec {
public:
- enum PathSyntax : unsigned char {
- ePathSyntaxPosix,
- ePathSyntaxWindows,
- ePathSyntaxHostNative
- };
+ using Style = llvm::sys::path::Style;
FileSpec();
//------------------------------------------------------------------
/// Constructor with path.
///
- /// Takes a path to a file which can be just a filename, or a full
- /// path. If \a path is not nullptr or empty, this function will call
+ /// Takes a path to a file which can be just a filename, or a full path. If
+ /// \a path is not nullptr or empty, this function will call
/// FileSpec::SetFile (const char *path, bool resolve).
///
/// @param[in] path
@@ -87,7 +83,7 @@ public:
/// @see FileSpec::SetFile (const char *path, bool resolve)
//------------------------------------------------------------------
explicit FileSpec(llvm::StringRef path, bool resolve_path,
- PathSyntax syntax = ePathSyntaxHostNative);
+ Style style = Style::native);
explicit FileSpec(llvm::StringRef path, bool resolve_path,
const llvm::Triple &Triple);
@@ -95,8 +91,7 @@ public:
//------------------------------------------------------------------
/// Copy constructor
///
- /// Makes a copy of the uniqued directory and filename strings from
- /// \a rhs.
+ /// Makes a copy of the uniqued directory and filename strings from \a rhs.
///
/// @param[in] rhs
/// A const FileSpec object reference to copy.
@@ -106,8 +101,8 @@ public:
//------------------------------------------------------------------
/// Copy constructor
///
- /// Makes a copy of the uniqued directory and filename strings from
- /// \a rhs if it is not nullptr.
+ /// Makes a copy of the uniqued directory and filename strings from \a rhs
+ /// if it is not nullptr.
///
/// @param[in] rhs
/// A const FileSpec object pointer to copy if non-nullptr.
@@ -126,8 +121,7 @@ public:
//------------------------------------------------------------------
/// Assignment operator.
///
- /// Makes a copy of the uniqued directory and filename strings from
- /// \a rhs.
+ /// Makes a copy of the uniqued directory and filename strings from \a rhs.
///
/// @param[in] rhs
/// A const FileSpec object reference to assign to this object.
@@ -185,8 +179,8 @@ public:
//------------------------------------------------------------------
/// Convert to pointer operator.
///
- /// This allows code to check a FileSpec object to see if it
- /// contains anything valid using code such as:
+ /// This allows code to check a FileSpec object to see if it contains
+ /// anything valid using code such as:
///
/// @code
/// FileSpec file_spec(...);
@@ -203,8 +197,8 @@ public:
//------------------------------------------------------------------
/// Logical NOT operator.
///
- /// This allows code to check a FileSpec object to see if it is
- /// invalid using code such as:
+ /// This allows code to check a FileSpec object to see if it is invalid
+ /// using code such as:
///
/// @code
/// FileSpec file_spec(...);
@@ -221,20 +215,19 @@ public:
//------------------------------------------------------------------
/// Clears the object state.
///
- /// Clear this object by releasing both the directory and filename
- /// string values and reverting them to empty strings.
+ /// Clear this object by releasing both the directory and filename string
+ /// values and reverting them to empty strings.
//------------------------------------------------------------------
void Clear();
//------------------------------------------------------------------
/// Compare two FileSpec objects.
///
- /// If \a full is true, then both the directory and the filename
- /// must match. If \a full is false, then the directory names for
- /// \a lhs and \a rhs are only compared if they are both not empty.
- /// This allows a FileSpec object to only contain a filename
- /// and it can match FileSpec objects that have matching
- /// filenames with different paths.
+ /// If \a full is true, then both the directory and the filename must match.
+ /// If \a full is false, then the directory names for \a lhs and \a rhs are
+ /// only compared if they are both not empty. This allows a FileSpec object
+ /// to only contain a filename and it can match FileSpec objects that have
+ /// matching filenames with different paths.
///
/// @param[in] lhs
/// A const reference to the Left Hand Side object to compare.
@@ -256,8 +249,7 @@ public:
//------------------------------------------------------------------
static int Compare(const FileSpec &lhs, const FileSpec &rhs, bool full);
- static bool Equal(const FileSpec &a, const FileSpec &b, bool full,
- bool remove_backups = false);
+ static bool Equal(const FileSpec &a, const FileSpec &b, bool full);
//------------------------------------------------------------------
/// Case sensitivity of path.
@@ -266,14 +258,14 @@ public:
/// \b true if the file path is case sensitive (POSIX), false
/// if case insensitive (Windows).
//------------------------------------------------------------------
- bool IsCaseSensitive() const { return m_syntax != ePathSyntaxWindows; }
+ bool IsCaseSensitive() const { return m_style != Style::windows; }
//------------------------------------------------------------------
/// Dump this object to a Stream.
///
- /// Dump the object to the supplied stream \a s. If the object
- /// contains a valid directory name, it will be displayed followed
- /// by a directory delimiter, and the filename.
+ /// Dump the object to the supplied stream \a s. If the object contains a
+ /// valid directory name, it will be displayed followed by a directory
+ /// delimiter, and the filename.
///
/// @param[in] s
/// The stream to which to dump the object description.
@@ -303,8 +295,8 @@ public:
/// Call into the Host to see if it can help find the file (e.g. by
/// searching paths set in the environment, etc.).
///
- /// If found, sets the value of m_directory to the directory where
- /// the file was found.
+ /// If found, sets the value of m_directory to the directory where the file
+ /// was found.
///
/// @return
/// \b true if was able to find the file using expanded search
@@ -314,14 +306,14 @@ public:
//------------------------------------------------------------------
/// Canonicalize this file path (basically running the static
- /// FileSpec::Resolve method on it). Useful if you asked us not to
- /// resolve the file path when you set the file.
+ /// FileSpec::Resolve method on it). Useful if you asked us not to resolve
+ /// the file path when you set the file.
//------------------------------------------------------------------
bool ResolvePath();
uint64_t GetByteSize() const;
- PathSyntax GetPathSyntax() const;
+ Style GetPathStyle() const;
//------------------------------------------------------------------
/// Directory string get accessor.
@@ -356,9 +348,8 @@ public:
const ConstString &GetFilename() const;
//------------------------------------------------------------------
- /// Returns true if the filespec represents an implementation source
- /// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
- /// extension).
+ /// Returns true if the filespec represents an implementation source file
+ /// (files with a ".c", ".cpp", ".m", ".mm" (many more) extension).
///
/// @return
/// \b true if the filespec represents an implementation source
@@ -387,9 +378,8 @@ public:
//------------------------------------------------------------------
/// Extract the full path to the file.
///
- /// Extract the directory and path into a fixed buffer. This is
- /// needed as the directory and path are stored in separate string
- /// values.
+ /// Extract the directory and path into a fixed buffer. This is needed as
+ /// the directory and path are stored in separate string values.
///
/// @param[out] path
/// The buffer in which to place the extracted full path.
@@ -436,10 +426,10 @@ public:
//------------------------------------------------------------------
/// Extract the extension of the file.
///
- /// Returns a ConstString that represents the extension of the filename
- /// for this FileSpec object. If this object does not represent a file,
- /// or the filename has no extension, ConstString(nullptr) is returned.
- /// The dot ('.') character is not returned as part of the extension
+ /// Returns a ConstString that represents the extension of the filename for
+ /// this FileSpec object. If this object does not represent a file, or the
+ /// filename has no extension, ConstString(nullptr) is returned. The dot
+ /// ('.') character is not returned as part of the extension
///
/// @return
/// Returns the extension of the file as a ConstString object.
@@ -450,8 +440,8 @@ public:
/// Return the filename without the extension part
///
/// Returns a ConstString that represents the filename of this object
- /// without the extension part (e.g. for a file named "foo.bar", "foo"
- /// is returned)
+ /// without the extension part (e.g. for a file named "foo.bar", "foo" is
+ /// returned)
///
/// @return
/// Returns the filename without extension
@@ -462,9 +452,8 @@ public:
//------------------------------------------------------------------
/// Return the current permissions of the path.
///
- /// Returns a bitmask for the current permissions of the file
- /// ( zero or more of the permission bits defined in
- /// File::Permissions).
+ /// Returns a bitmask for the current permissions of the file ( zero or more
+ /// of the permission bits defined in File::Permissions).
///
/// @return
/// Zero if the file doesn't exist or we are unable to get
@@ -476,9 +465,9 @@ public:
//------------------------------------------------------------------
/// Get the memory cost of this object.
///
- /// Return the size in bytes that this object takes in memory. This
- /// returns the size in bytes of this object, not any shared string
- /// values it may refer to.
+ /// Return the size in bytes that this object takes in memory. This returns
+ /// the size in bytes of this object, not any shared string values it may
+ /// refer to.
///
/// @return
/// The number of bytes that this object occupies in memory.
@@ -488,17 +477,11 @@ public:
size_t MemorySize() const;
//------------------------------------------------------------------
- /// Normalize a pathname by collapsing redundant separators and
- /// up-level references.
- //------------------------------------------------------------------
- FileSpec GetNormalizedPath() const;
-
- //------------------------------------------------------------------
/// Change the file specified with a new path.
///
- /// Update the contents of this object with a new path. The path will
- /// be split up into a directory and filename and stored as uniqued
- /// string values for quick comparison and efficient memory usage.
+ /// Update the contents of this object with a new path. The path will be
+ /// split up into a directory and filename and stored as uniqued string
+ /// values for quick comparison and efficient memory usage.
///
/// @param[in] path
/// A full, partial, or relative path to a file.
@@ -507,8 +490,7 @@ public:
/// If \b true, then we will try to resolve links the path using
/// the static FileSpec::Resolve.
//------------------------------------------------------------------
- void SetFile(llvm::StringRef path, bool resolve_path,
- PathSyntax syntax = ePathSyntaxHostNative);
+ void SetFile(llvm::StringRef path, bool resolve_path, Style style);
void SetFile(llvm::StringRef path, bool resolve_path,
const llvm::Triple &Triple);
@@ -518,11 +500,11 @@ public:
//------------------------------------------------------------------
/// Set if the file path has been resolved or not.
///
- /// If you know a file path is already resolved and avoided passing
- /// a \b true parameter for any functions that take a "bool
- /// resolve_path" parameter, you can set the value manually using
- /// this call to make sure we don't try and resolve it later, or try
- /// and resolve a path that has already been resolved.
+ /// If you know a file path is already resolved and avoided passing a \b
+ /// true parameter for any functions that take a "bool resolve_path"
+ /// parameter, you can set the value manually using this call to make sure
+ /// we don't try and resolve it later, or try and resolve a path that has
+ /// already been resolved.
///
/// @param[in] is_resolved
/// A boolean value that will replace the current value that
@@ -549,7 +531,14 @@ public:
void AppendPathComponent(llvm::StringRef component);
void AppendPathComponent(const FileSpec &new_path);
- void RemoveLastPathComponent();
+ //------------------------------------------------------------------
+ /// Removes the last path component by replacing the current path with its
+ /// parent. When the current path has no parent, this is a no-op.
+ ///
+ /// @return
+ /// A boolean value indicating whether the path was updated.
+ //------------------------------------------------------------------
+ bool RemoveLastPathComponent();
ConstString GetLastPathComponent() const;
@@ -576,13 +565,17 @@ public:
protected:
//------------------------------------------------------------------
+ // Convenience method for setting the file without changing the style.
+ //------------------------------------------------------------------
+ void SetFile(llvm::StringRef path, bool resolve_path);
+
+ //------------------------------------------------------------------
// Member variables
//------------------------------------------------------------------
ConstString m_directory; ///< The uniqued directory path
ConstString m_filename; ///< The uniqued filename path
mutable bool m_is_resolved = false; ///< True if this path has been resolved.
- PathSyntax
- m_syntax; ///< The syntax that this path uses (e.g. Windows / Posix)
+ Style m_style; ///< The syntax that this path uses (e.g. Windows / Posix)
};
//----------------------------------------------------------------------
@@ -616,6 +609,6 @@ template <> struct format_provider<lldb_private::FileSpec> {
static void format(const lldb_private::FileSpec &F, llvm::raw_ostream &Stream,
StringRef Style);
};
-}
+} // namespace llvm
#endif // liblldb_FileSpec_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Flags.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Flags.h
index 1b303858b1c1..5ef6122d1146 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Flags.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Flags.h
@@ -17,10 +17,10 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Flags Flags.h "lldb/Utility/Flags.h"
-/// @brief A class to manage flags.
+/// A class to manage flags.
///
-/// The Flags class managed flag bits and allows testing and
-/// modification of individual or multiple flag bits.
+/// The Flags class managed flag bits and allows testing and modification of
+/// individual or multiple flag bits.
//----------------------------------------------------------------------
class Flags {
public:
@@ -32,8 +32,8 @@ public:
//----------------------------------------------------------------------
/// Construct with initial flag bit values.
///
- /// Constructs this object with \a mask as the initial value for all
- /// of the flags.
+ /// Constructs this object with \a mask as the initial value for all of the
+ /// flags.
///
/// @param[in] mask
/// The initial value for all flags.
@@ -64,8 +64,7 @@ public:
ValueType Get() const { return m_flags; }
//----------------------------------------------------------------------
- /// Return the number of flags that can be represented in this
- /// object.
+ /// Return the number of flags that can be represented in this object.
///
/// @return
/// The maximum number bits in this flag object.
@@ -95,8 +94,7 @@ public:
}
//----------------------------------------------------------------------
- /// Set one or more flags by logical OR'ing \a mask with the current
- /// flags.
+ /// Set one or more flags by logical OR'ing \a mask with the current flags.
///
/// @param[in] mask
/// A bitfield containing one or more flags.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/History.h b/contrib/llvm/tools/lldb/include/lldb/Utility/History.h
deleted file mode 100644
index c6882b65fd8e..000000000000
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/History.h
+++ /dev/null
@@ -1,136 +0,0 @@
-//===-- History.h -----------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_History_h_
-#define lldb_History_h_
-
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-
-// C++ Includes
-#include <mutex>
-#include <stack>
-#include <string>
-
-#include <stddef.h> // for size_t
-#include <stdint.h>
-
-namespace lldb_private {
-class Stream;
-}
-
-namespace lldb_private {
-
-//----------------------------------------------------------------------
-/// @class HistorySource History.h "lldb/Core/History.h"
-/// @brief A class that defines history events.
-//----------------------------------------------------------------------
-
-class HistorySource {
-public:
- typedef const void *HistoryEvent;
-
- HistorySource() : m_mutex(), m_events() {}
-
- virtual ~HistorySource() {}
-
- // Create a new history event. Subclasses should use any data or members
- // in the subclass of this class to produce a history event and push it
- // onto the end of the history stack.
-
- virtual HistoryEvent CreateHistoryEvent() = 0;
-
- virtual void DeleteHistoryEvent(HistoryEvent event) = 0;
-
- virtual void DumpHistoryEvent(Stream &strm, HistoryEvent event) = 0;
-
- virtual size_t GetHistoryEventCount() = 0;
-
- virtual HistoryEvent GetHistoryEventAtIndex(uint32_t idx) = 0;
-
- virtual HistoryEvent GetCurrentHistoryEvent() = 0;
-
- // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs.
- virtual int CompareHistoryEvents(const HistoryEvent lhs,
- const HistoryEvent rhs) = 0;
-
- virtual bool IsCurrentHistoryEvent(const HistoryEvent event) = 0;
-
-private:
- typedef std::stack<HistoryEvent> collection;
-
- std::recursive_mutex m_mutex;
- collection m_events;
-
- DISALLOW_COPY_AND_ASSIGN(HistorySource);
-};
-
-//----------------------------------------------------------------------
-/// @class HistorySourceUInt History.h "lldb/Core/History.h"
-/// @brief A class that defines history events that are represented by
-/// unsigned integers.
-///
-/// Any history event that is defined by a unique monotonically
-/// increasing unsigned integer
-//----------------------------------------------------------------------
-
-class HistorySourceUInt : public HistorySource {
- HistorySourceUInt(const char *id_name, uintptr_t start_value = 0u)
- : HistorySource(), m_name(id_name), m_curr_id(start_value) {}
-
- ~HistorySourceUInt() override {}
-
- // Create a new history event. Subclasses should use any data or members
- // in the subclass of this class to produce a history event and push it
- // onto the end of the history stack.
-
- HistoryEvent CreateHistoryEvent() override {
- ++m_curr_id;
- return (HistoryEvent)m_curr_id;
- }
-
- void DeleteHistoryEvent(HistoryEvent event) override {
- // Nothing to delete, the event contains the integer
- }
-
- void DumpHistoryEvent(Stream &strm, HistoryEvent event) override;
-
- size_t GetHistoryEventCount() override { return m_curr_id; }
-
- HistoryEvent GetHistoryEventAtIndex(uint32_t idx) override {
- return (HistoryEvent)((uintptr_t)idx);
- }
-
- HistoryEvent GetCurrentHistoryEvent() override {
- return (HistoryEvent)m_curr_id;
- }
-
- // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs.
- int CompareHistoryEvents(const HistoryEvent lhs,
- const HistoryEvent rhs) override {
- uintptr_t lhs_uint = (uintptr_t)lhs;
- uintptr_t rhs_uint = (uintptr_t)rhs;
- if (lhs_uint < rhs_uint)
- return -1;
- if (lhs_uint > rhs_uint)
- return +1;
- return 0;
- }
-
- bool IsCurrentHistoryEvent(const HistoryEvent event) override {
- return (uintptr_t)event == m_curr_id;
- }
-
-protected:
- std::string m_name; // The name of the history unsigned integer
- uintptr_t m_curr_id; // The current value of the history unsigned unteger
-};
-
-} // namespace lldb_private
-
-#endif // lldb_History_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h b/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h
index 8bf9c4b37b02..6fe1945ea227 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h
@@ -79,9 +79,8 @@ public:
// SFINAE to avoid having ambiguous overloads because of the implicit type
// promotion. If we
// would have constructors only with int64_t, uint64_t and double types then
- // constructing a
- // JSONNumber from an int32_t (or any other similar type) would fail to
- // compile.
+ // constructing a JSONNumber from an int32_t (or any other similar type)
+ // would fail to compile.
template <typename T, typename std::enable_if<
std::is_integral<T>::value &&
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h
index 80a80fc16485..62776bdb281b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h" // for StringMap
#include "llvm/ADT/StringRef.h" // for StringRef, StringLiteral
+#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/RWMutex.h"
@@ -73,10 +74,10 @@ public:
: log_ptr(nullptr), categories(categories),
default_flags(default_flags) {}
- // This function is safe to call at any time
- // If the channel is disabled after (or concurrently with) this function
- // returning a non-null Log pointer, it is still safe to attempt to write to
- // the Log object -- the output will be discarded.
+ // This function is safe to call at any time If the channel is disabled
+ // after (or concurrently with) this function returning a non-null Log
+ // pointer, it is still safe to attempt to write to the Log object -- the
+ // output will be discarded.
Log *GetLogIfAll(uint32_t mask) {
Log *log = log_ptr.load(std::memory_order_relaxed);
if (log && log->GetMask().AllSet(mask))
@@ -84,10 +85,10 @@ public:
return nullptr;
}
- // This function is safe to call at any time
- // If the channel is disabled after (or concurrently with) this function
- // returning a non-null Log pointer, it is still safe to attempt to write to
- // the Log object -- the output will be discarded.
+ // This function is safe to call at any time If the channel is disabled
+ // after (or concurrently with) this function returning a non-null Log
+ // pointer, it is still safe to attempt to write to the Log object -- the
+ // output will be discarded.
Log *GetLogIfAny(uint32_t mask) {
Log *log = log_ptr.load(std::memory_order_relaxed);
if (log && log->GetMask().AnySet(mask))
@@ -140,6 +141,15 @@ public:
Format(file, function, llvm::formatv(format, std::forward<Args>(args)...));
}
+ template <typename... Args>
+ void FormatError(llvm::Error error, llvm::StringRef file,
+ llvm::StringRef function, const char *format,
+ Args &&... args) {
+ Format(file, function,
+ llvm::formatv(format, llvm::toString(std::move(error)),
+ std::forward<Args>(args)...));
+ }
+
void Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
void VAPrintf(const char *format, va_list args);
@@ -161,8 +171,8 @@ public:
private:
Channel &m_channel;
- // The mutex makes sure enable/disable operations are thread-safe. The options
- // and mask variables are atomic to enable their reading in
+ // The mutex makes sure enable/disable operations are thread-safe. The
+ // options and mask variables are atomic to enable their reading in
// Channel::GetLogIfAny without taking the mutex to speed up the fast path.
// Their modification however, is still protected by this mutex.
llvm::sys::RWMutex m_mutex;
@@ -208,14 +218,27 @@ private:
do { \
::lldb_private::Log *log_private = (log); \
if (log_private) \
- log_private->Format(__FILE__, __FUNCTION__, __VA_ARGS__); \
+ log_private->Format(__FILE__, __func__, __VA_ARGS__); \
} while (0)
#define LLDB_LOGV(log, ...) \
do { \
::lldb_private::Log *log_private = (log); \
if (log_private && log_private->GetVerbose()) \
- log_private->Format(__FILE__, __FUNCTION__, __VA_ARGS__); \
+ log_private->Format(__FILE__, __func__, __VA_ARGS__); \
+ } while (0)
+
+// Write message to log, if error is set. In the log message refer to the error
+// with {0}. Error is cleared regardless of whether logging is enabled.
+#define LLDB_LOG_ERROR(log, error, ...) \
+ do { \
+ ::lldb_private::Log *log_private = (log); \
+ ::llvm::Error error_private = (error); \
+ if (log_private && error_private) { \
+ log_private->FormatError(::std::move(error_private), __FILE__, __func__, \
+ __VA_ARGS__); \
+ } else \
+ ::llvm::consumeError(::std::move(error_private)); \
} while (0)
#endif // LLDB_UTILITY_LOG_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/RegularExpression.h b/contrib/llvm/tools/lldb/include/lldb/Utility/RegularExpression.h
index dba7001ce0fa..6048fcc610a3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/RegularExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/RegularExpression.h
@@ -52,11 +52,11 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class RegularExpression RegularExpression.h
/// "lldb/Utility/RegularExpression.h"
-/// @brief A C++ wrapper class for regex.
+/// A C++ wrapper class for regex.
///
-/// This regular expression class wraps the posix regex functions
-/// \c regcomp(), \c regerror(), \c regexec(), and \c regfree() from
-/// the header file in \c /usr/include/regex\.h.
+/// This regular expression class wraps the posix regex functions \c
+/// regcomp(), \c regerror(), \c regexec(), and \c regfree() from the header
+/// file in \c /usr/include/regex\.h.
//----------------------------------------------------------------------
class RegularExpression {
public:
@@ -98,8 +98,8 @@ public:
//------------------------------------------------------------------
/// Default constructor.
///
- /// The default constructor that initializes the object state such
- /// that it contains no compiled regular expression.
+ /// The default constructor that initializes the object state such that it
+ /// contains no compiled regular expression.
//------------------------------------------------------------------
RegularExpression();
@@ -108,8 +108,8 @@ public:
//------------------------------------------------------------------
/// Destructor.
///
- /// Any previously compiled regular expression contained in this
- /// object will be freed.
+ /// Any previously compiled regular expression contained in this object will
+ /// be freed.
//------------------------------------------------------------------
~RegularExpression();
@@ -120,12 +120,11 @@ public:
//------------------------------------------------------------------
/// Compile a regular expression.
///
- /// Compile a regular expression using the supplied regular
- /// expression text. The compiled regular expression lives
- /// in this object so that it can be readily used for regular
- /// expression matches. Execute() can be called after the regular
- /// expression is compiled. Any previously compiled regular
- /// expression contained in this object will be freed.
+ /// Compile a regular expression using the supplied regular expression text.
+ /// The compiled regular expression lives in this object so that it can be
+ /// readily used for regular expression matches. Execute() can be called
+ /// after the regular expression is compiled. Any previously compiled
+ /// regular expression contained in this object will be freed.
///
/// @param[in] re
/// A NULL terminated C string that represents the regular
@@ -141,11 +140,11 @@ public:
//------------------------------------------------------------------
/// Executes a regular expression.
///
- /// Execute a regular expression match using the compiled regular
- /// expression that is already in this object against the match
- /// string \a s. If any parens are used for regular expression
- /// matches \a match_count should indicate the number of regmatch_t
- /// values that are present in \a match_ptr.
+ /// Execute a regular expression match using the compiled regular expression
+ /// that is already in this object against the match string \a s. If any
+ /// parens are used for regular expression matches \a match_count should
+ /// indicate the number of regmatch_t values that are present in \a
+ /// match_ptr.
///
/// @param[in] string
/// The string to match against the compile regular expression.
@@ -167,8 +166,8 @@ public:
//------------------------------------------------------------------
/// Free the compiled regular expression.
///
- /// If this object contains a valid compiled regular expression,
- /// this function will free any resources it was consuming.
+ /// If this object contains a valid compiled regular expression, this
+ /// function will free any resources it was consuming.
//------------------------------------------------------------------
void Free();
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/SafeMachO.h b/contrib/llvm/tools/lldb/include/lldb/Utility/SafeMachO.h
index 791410a38b34..1565b313f42b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/SafeMachO.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/SafeMachO.h
@@ -9,18 +9,15 @@
#ifndef liblldb_SafeMachO_h_
#define liblldb_SafeMachO_h_
-// This header file is required to work around collisions between the defines in
-// mach/machine.h, and enum members
-// of the same name in llvm's MachO.h. If you want to use llvm/Support/MachO.h,
-// use this file instead.
-// The caveats are:
-// 1) You can only use the MachO.h enums, you can't use the defines. That won't
-// make a difference since the values
+// This header file is required to work around collisions between the defines
+// in mach/machine.h, and enum members of the same name in llvm's MachO.h. If
+// you want to use llvm/Support/MachO.h, use this file instead. The caveats
+// are: 1) You can only use the MachO.h enums, you can't use the defines. That
+// won't make a difference since the values
// are the same.
// 2) If you need any header file that relies on mach/machine.h, you must
-// include that first.
-// 3) This isn't a total solution, it doesn't undef every define that MachO.h
-// has borrowed from various system headers,
+// include that first. 3) This isn't a total solution, it doesn't undef every
+// define that MachO.h has borrowed from various system headers,
// only the ones that come from mach/machine.h because that is the one we
// ended up pulling in from various places.
//
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/SelectHelper.h b/contrib/llvm/tools/lldb/include/lldb/Utility/SelectHelper.h
index 12950d032fb6..004952f1c598 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/SelectHelper.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/SelectHelper.h
@@ -23,32 +23,31 @@ public:
// Defaults to infinite wait for select unless you call SetTimeout()
SelectHelper();
- // Call SetTimeout() before calling SelectHelper::Select() to set the
- // timeout based on the current time + the timeout. This allows multiple
- // calls to SelectHelper::Select() without having to worry about the
- // absolute timeout as this class manages to set the relative timeout
- // correctly.
+ // Call SetTimeout() before calling SelectHelper::Select() to set the timeout
+ // based on the current time + the timeout. This allows multiple calls to
+ // SelectHelper::Select() without having to worry about the absolute timeout
+ // as this class manages to set the relative timeout correctly.
void SetTimeout(const std::chrono::microseconds &timeout);
- // Call the FDSet*() functions before calling SelectHelper::Select() to
- // set the file descriptors that we will watch for when calling
- // select. This will cause FD_SET() to be called prior to calling select
- // using the "fd" provided.
+ // Call the FDSet*() functions before calling SelectHelper::Select() to set
+ // the file descriptors that we will watch for when calling select. This will
+ // cause FD_SET() to be called prior to calling select using the "fd"
+ // provided.
void FDSetRead(lldb::socket_t fd);
void FDSetWrite(lldb::socket_t fd);
void FDSetError(lldb::socket_t fd);
- // Call the FDIsSet*() functions after calling SelectHelper::Select()
- // to check which file descriptors are ready for read/write/error. This
- // will contain the result of FD_ISSET after calling select for a given
- // file descriptor.
+ // Call the FDIsSet*() functions after calling SelectHelper::Select() to
+ // check which file descriptors are ready for read/write/error. This will
+ // contain the result of FD_ISSET after calling select for a given file
+ // descriptor.
bool FDIsSetRead(lldb::socket_t fd) const;
bool FDIsSetWrite(lldb::socket_t fd) const;
bool FDIsSetError(lldb::socket_t fd) const;
- // Call the system's select() to wait for descriptors using
- // timeout provided in a call the SelectHelper::SetTimeout(),
- // or infinite wait if no timeout was set.
+ // Call the system's select() to wait for descriptors using timeout provided
+ // in a call the SelectHelper::SetTimeout(), or infinite wait if no timeout
+ // was set.
lldb_private::Status Select();
protected:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h b/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h
index b01f702c2787..61b9804ad335 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h
@@ -15,6 +15,8 @@
#include "llvm/ADT/SmallPtrSet.h"
+#include <mutex>
+
namespace lldb_private {
namespace imp {
@@ -48,9 +50,9 @@ public:
delete object;
}
- // Decrement refcount should have been called on this ClusterManager,
- // and it should have locked the mutex, now we will unlock it before
- // we destroy it...
+ // Decrement refcount should have been called on this ClusterManager, and
+ // it should have locked the mutex, now we will unlock it before we destroy
+ // it...
m_mutex.unlock();
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h b/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
index 41fa0c8121d8..691c92afaaae 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
@@ -14,9 +14,9 @@
// C++ Includes
#include <memory>
-// Microsoft Visual C++ currently does not enable std::atomic to work
-// in CLR mode - as such we need to "hack around it" for MSVC++ builds only
-// using Windows specific intrinsics instead of the C++11 atomic support
+// Microsoft Visual C++ currently does not enable std::atomic to work in CLR
+// mode - as such we need to "hack around it" for MSVC++ builds only using
+// Windows specific intrinsics instead of the C++11 atomic support
#ifdef _MSC_VER
#include <intrin.h>
#else
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Status.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Status.h
index 8c3e009a8c2e..3bd2cd5b3b41 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Status.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Status.h
@@ -28,30 +28,27 @@ class raw_ostream;
namespace lldb_private {
//----------------------------------------------------------------------
-/// @class Status Status.h "lldb/Utility/Status.h"
-/// @brief An error handling class.
+/// @class Status Status.h "lldb/Utility/Status.h" An error handling class.
///
/// This class is designed to be able to hold any error code that can be
-/// encountered on a given platform. The errors are stored as a value
-/// of type Status::ValueType. This value should be large enough to hold
-/// any and all errors that the class supports. Each error has an
-/// associated type that is of type lldb::ErrorType. New types
-/// can be added to support new error types, and architecture specific
-/// types can be enabled. In the future we may wish to switch to a
-/// registration mechanism where new error types can be registered at
-/// runtime instead of a hard coded scheme.
+/// encountered on a given platform. The errors are stored as a value of type
+/// Status::ValueType. This value should be large enough to hold any and all
+/// errors that the class supports. Each error has an associated type that is
+/// of type lldb::ErrorType. New types can be added to support new error
+/// types, and architecture specific types can be enabled. In the future we
+/// may wish to switch to a registration mechanism where new error types can
+/// be registered at runtime instead of a hard coded scheme.
///
-/// All errors in this class also know how to generate a string
-/// representation of themselves for printing results and error codes.
-/// The string value will be fetched on demand and its string value will
-/// be cached until the error is cleared of the value of the error
-/// changes.
+/// All errors in this class also know how to generate a string representation
+/// of themselves for printing results and error codes. The string value will
+/// be fetched on demand and its string value will be cached until the error
+/// is cleared of the value of the error changes.
//----------------------------------------------------------------------
class Status {
public:
//------------------------------------------------------------------
- /// Every error value that this object can contain needs to be able
- /// to fit into ValueType.
+ /// Every error value that this object can contain needs to be able to fit
+ /// into ValueType.
//------------------------------------------------------------------
typedef uint32_t ValueType;
@@ -98,11 +95,10 @@ public:
//------------------------------------------------------------------
/// Get the error string associated with the current error.
//
- /// Gets the error value as a NULL terminated C string. The error
- /// string will be fetched and cached on demand. The error string
- /// will be retrieved from a callback that is appropriate for the
- /// type of the error and will be cached until the error value is
- /// changed or cleared.
+ /// Gets the error value as a NULL terminated C string. The error string
+ /// will be fetched and cached on demand. The error string will be retrieved
+ /// from a callback that is appropriate for the type of the error and will
+ /// be cached until the error value is changed or cleared.
///
/// @return
/// The error as a NULL terminated C string value if the error
@@ -114,8 +110,8 @@ public:
//------------------------------------------------------------------
/// Clear the object state.
///
- /// Reverts the state of this object to contain a generic success
- /// value and frees any cached error string value.
+ /// Reverts the state of this object to contain a generic success value and
+ /// frees any cached error string value.
//------------------------------------------------------------------
void Clear();
@@ -147,8 +143,8 @@ public:
//------------------------------------------------------------------
/// Set accessor from a kern_return_t.
///
- /// Set accesssor for the error value to \a err and the error type
- /// to \c MachKernel.
+ /// Set accesssor for the error value to \a err and the error type to \c
+ /// MachKernel.
///
/// @param[in] err
/// A mach error code.
@@ -163,8 +159,8 @@ public:
//------------------------------------------------------------------
/// Set accesssor with an error value and type.
///
- /// Set accesssor for the error value to \a err and the error type
- /// to \a type.
+ /// Set accesssor for the error value to \a err and the error type to \a
+ /// type.
///
/// @param[in] err
/// A mach error code.
@@ -177,28 +173,28 @@ public:
//------------------------------------------------------------------
/// Set the current error to errno.
///
- /// Update the error value to be \c errno and update the type to
- /// be \c Status::POSIX.
+ /// Update the error value to be \c errno and update the type to be \c
+ /// Status::POSIX.
//------------------------------------------------------------------
void SetErrorToErrno();
//------------------------------------------------------------------
/// Set the current error to a generic error.
///
- /// Update the error value to be \c LLDB_GENERIC_ERROR and update the
- /// type to be \c Status::Generic.
+ /// Update the error value to be \c LLDB_GENERIC_ERROR and update the type
+ /// to be \c Status::Generic.
//------------------------------------------------------------------
void SetErrorToGenericError();
//------------------------------------------------------------------
/// Set the current error string to \a err_str.
///
- /// Set accessor for the error string value for a generic errors,
- /// or to supply additional details above and beyond the standard
- /// error strings that the standard type callbacks typically
- /// provide. This allows custom strings to be supplied as an
- /// error explanation. The error string value will remain until the
- /// error value is cleared or a new error value/type is assigned.
+ /// Set accessor for the error string value for a generic errors, or to
+ /// supply additional details above and beyond the standard error strings
+ /// that the standard type callbacks typically provide. This allows custom
+ /// strings to be supplied as an error explanation. The error string value
+ /// will remain until the error value is cleared or a new error value/type
+ /// is assigned.
///
/// @param err_str
/// The new custom error string to copy and cache.
@@ -224,8 +220,8 @@ public:
//------------------------------------------------------------------
/// Test for success condition.
///
- /// Returns true if the error code in this object is considered a
- /// successful return value.
+ /// Returns true if the error code in this object is considered a successful
+ /// return value.
///
/// @return
/// \b true if this object contains an value that describes
@@ -236,8 +232,8 @@ public:
//------------------------------------------------------------------
/// Test for a failure due to a generic interrupt.
///
- /// Returns true if the error code in this object was caused by an interrupt.
- /// At present only supports Posix EINTR.
+ /// Returns true if the error code in this object was caused by an
+ /// interrupt. At present only supports Posix EINTR.
///
/// @return
/// \b true if this object contains an value that describes
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Stream.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Stream.h
index 5a00f0a50ca3..4930521d9497 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Stream.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Stream.h
@@ -25,7 +25,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class Stream Stream.h "lldb/Utility/Stream.h"
-/// @brief A stream class that can stream formatted output to a file.
+/// A stream class that can stream formatted output to a file.
//----------------------------------------------------------------------
class Stream {
public:
@@ -40,15 +40,14 @@ public:
//------------------------------------------------------------------
/// Construct with flags and address size and byte order.
///
- /// Construct with dump flags \a flags and the default address
- /// size. \a flags can be any of the above enumeration logical OR'ed
- /// together.
+ /// Construct with dump flags \a flags and the default address size. \a
+ /// flags can be any of the above enumeration logical OR'ed together.
//------------------------------------------------------------------
Stream(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order);
//------------------------------------------------------------------
- /// Construct a default Stream, not binary, host byte order and
- /// host addr size.
+ /// Construct a default Stream, not binary, host byte order and host addr
+ /// size.
///
//------------------------------------------------------------------
Stream();
@@ -65,16 +64,15 @@ public:
//------------------------------------------------------------------
/// Flush the stream.
///
- /// Subclasses should flush the stream to make any output appear
- /// if the stream has any buffering.
+ /// Subclasses should flush the stream to make any output appear if the
+ /// stream has any buffering.
//------------------------------------------------------------------
virtual void Flush() = 0;
//------------------------------------------------------------------
/// Output character bytes to the stream.
///
- /// Appends \a src_len characters from the buffer \a src to the
- /// stream.
+ /// Appends \a src_len characters from the buffer \a src to the stream.
///
/// @param[in] src
/// A buffer containing at least \a src_len bytes of data.
@@ -95,8 +93,8 @@ public:
//------------------------------------------------------------------
/// Set the byte_order value.
///
- /// Sets the byte order of the data to extract. Extracted values
- /// will be swapped if necessary when decoding.
+ /// Sets the byte order of the data to extract. Extracted values will be
+ /// swapped if necessary when decoding.
///
/// @param[in] byte_order
/// The byte order value to use when extracting data.
@@ -107,9 +105,8 @@ public:
lldb::ByteOrder SetByteOrder(lldb::ByteOrder byte_order);
//------------------------------------------------------------------
- /// Format a C string from a printf style format and variable
- /// arguments and encode and append the resulting C string as hex
- /// bytes.
+ /// Format a C string from a printf style format and variable arguments and
+ /// encode and append the resulting C string as hex bytes.
///
/// @param[in] format
/// A printf style format string.
@@ -124,9 +121,8 @@ public:
__attribute__((__format__(__printf__, 2, 3)));
//------------------------------------------------------------------
- /// Format a C string from a printf style format and variable
- /// arguments and encode and append the resulting C string as hex
- /// bytes.
+ /// Format a C string from a printf style format and variable arguments and
+ /// encode and append the resulting C string as hex bytes.
///
/// @param[in] format
/// A printf style format string.
@@ -163,8 +159,8 @@ public:
size_t PutPointer(void *ptr);
- // Append \a src_len bytes from \a src to the stream as hex characters
- // (two ascii characters per byte of input data)
+ // Append \a src_len bytes from \a src to the stream as hex characters (two
+ // ascii characters per byte of input data)
size_t
PutBytesAsRawHex8(const void *src, size_t src_len,
lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid,
@@ -314,8 +310,8 @@ public:
//------------------------------------------------------------------
/// Output an address value to this stream.
///
- /// Put an address \a addr out to the stream with optional \a prefix
- /// and \a suffix strings.
+ /// Put an address \a addr out to the stream with optional \a prefix and \a
+ /// suffix strings.
///
/// @param[in] addr
/// An address value.
@@ -335,8 +331,8 @@ public:
//------------------------------------------------------------------
/// Output an address range to this stream.
///
- /// Put an address range \a lo_addr - \a hi_addr out to the stream
- /// with optional \a prefix and \a suffix strings.
+ /// Put an address range \a lo_addr - \a hi_addr out to the stream with
+ /// optional \a prefix and \a suffix strings.
///
/// @param[in] lo_addr
/// The start address of the address range.
@@ -415,8 +411,8 @@ public:
//------------------------------------------------------------------
/// Indent the current line in the stream.
///
- /// Indent the current line using the current indentation level and
- /// print an optional string following the indentation spaces.
+ /// Indent the current line using the current indentation level and print an
+ /// optional string following the indentation spaces.
///
/// @param[in] s
/// A C string to print following the indentation. If nullptr, just
@@ -438,8 +434,8 @@ public:
//------------------------------------------------------------------
/// Output an offset value.
///
- /// Put an offset \a uval out to the stream using the printf format
- /// in \a format.
+ /// Put an offset \a uval out to the stream using the printf format in \a
+ /// format.
///
/// @param[in] offset
/// The offset value.
@@ -472,8 +468,8 @@ public:
//------------------------------------------------------------------
/// Output a quoted C string value to the stream.
///
- /// Print a double quoted NULL terminated C string to the stream
- /// using the printf format in \a format.
+ /// Print a double quoted NULL terminated C string to the stream using the
+ /// printf format in \a format.
///
/// @param[in] cstr
/// A NULL terminated C string value.
@@ -503,8 +499,8 @@ public:
//------------------------------------------------------------------
/// Output a SLEB128 number to the stream.
///
- /// Put an SLEB128 \a uval out to the stream using the printf format
- /// in \a format.
+ /// Put an SLEB128 \a uval out to the stream using the printf format in \a
+ /// format.
///
/// @param[in] uval
/// A uint64_t value that was extracted as a SLEB128 value.
@@ -517,8 +513,8 @@ public:
//------------------------------------------------------------------
/// Output a ULEB128 number to the stream.
///
- /// Put an ULEB128 \a uval out to the stream using the printf format
- /// in \a format.
+ /// Put an ULEB128 \a uval out to the stream using the printf format in \a
+ /// format.
///
/// @param[in] uval
/// A uint64_t value that was extracted as a ULEB128 value.
@@ -528,8 +524,6 @@ public:
//------------------------------------------------------------------
size_t PutULEB128(uint64_t uval);
- static void UnitTest(Stream *s);
-
protected:
//------------------------------------------------------------------
// Member variables
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h b/contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h
index 676178a0fe75..569ba1979978 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h
@@ -61,10 +61,9 @@ public:
std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
collection::iterator pos, end;
for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
- // Allow for our collection to contain NULL streams. This allows
- // the StreamTee to be used with hard coded indexes for clients
- // that might want N total streams with only a few that are set
- // to valid values.
+ // Allow for our collection to contain NULL streams. This allows the
+ // StreamTee to be used with hard coded indexes for clients that might
+ // want N total streams with only a few that are set to valid values.
Stream *strm = pos->get();
if (strm)
strm->Flush();
@@ -79,10 +78,9 @@ public:
size_t min_bytes_written = SIZE_MAX;
collection::iterator pos, end;
for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
- // Allow for our collection to contain NULL streams. This allows
- // the StreamTee to be used with hard coded indexes for clients
- // that might want N total streams with only a few that are set
- // to valid values.
+ // Allow for our collection to contain NULL streams. This allows the
+ // StreamTee to be used with hard coded indexes for clients that might
+ // want N total streams with only a few that are set to valid values.
Stream *strm = pos->get();
if (strm) {
const size_t bytes_written = strm->Write(s, length);
@@ -121,10 +119,9 @@ public:
void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
- // Resize our stream vector as necessary to fit as many streams
- // as needed. This also allows this class to be used with hard
- // coded indexes that can be used contain many streams, not all
- // of which are valid.
+ // Resize our stream vector as necessary to fit as many streams as needed.
+ // This also allows this class to be used with hard coded indexes that can
+ // be used contain many streams, not all of which are valid.
if (idx >= m_streams.size())
m_streams.resize(idx + 1);
m_streams[idx] = stream_sp;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h b/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h
index 311cec87e695..4b75d5c5484d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h
@@ -41,8 +41,8 @@ public:
m_index = 0;
}
- // Returns true if the file position is still valid for the data
- // contained in this string extractor object.
+ // Returns true if the file position is still valid for the data contained in
+ // this string extractor object.
bool IsGood() const { return m_index != UINT64_MAX; }
uint64_t GetFilePos() const { return m_index; }
@@ -129,9 +129,9 @@ protected:
//------------------------------------------------------------------
std::string m_packet; // The string in which to extract data.
uint64_t m_index; // When extracting data from a packet, this index
- // will march along as things get extracted. If set
- // to UINT64_MAX the end of the packet data was
- // reached when decoding information
+ // will march along as things get extracted. If set to
+ // UINT64_MAX the end of the packet data was reached
+ // when decoding information
};
#endif // utility_StringExtractor_h_
diff --git a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h b/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
index f4ed642a706e..93e760b88112 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef utility_StringExtractorGDBRemote_h_
-#define utility_StringExtractorGDBRemote_h_
+#ifndef LLDB_UTILITY_STRINGEXTRACTORGDBREMOTE_H
+#define LLDB_UTILITY_STRINGEXTRACTORGDBREMOTE_H
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
@@ -188,8 +188,8 @@ public:
bool IsErrorResponse() const;
- // Returns zero if the packet isn't a EXX packet where XX are two hex
- // digits. Otherwise the error encoded in XX is returned.
+ // Returns zero if the packet isn't a EXX packet where XX are two hex digits.
+ // Otherwise the error encoded in XX is returned.
uint8_t GetError();
lldb_private::Status GetStatus();
@@ -201,4 +201,4 @@ protected:
void *m_validator_baton;
};
-#endif // utility_StringExtractorGDBRemote_h_
+#endif // LLDB_UTILITY_STRINGEXTRACTORGDBREMOTE_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/StringList.h b/contrib/llvm/tools/lldb/include/lldb/Utility/StringList.h
index 6553e5dfdfb9..1cb68885e771 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/StringList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/StringList.h
@@ -100,20 +100,17 @@ public:
// Copy assignment for a vector of strings
StringList &operator=(const std::vector<std::string> &rhs);
- // This string list contains a list of valid auto completion
- // strings, and the "s" is passed in. "matches" is filled in
- // with zero or more string values that start with "s", and
- // the first string to exactly match one of the string
- // values in this collection, will have "exact_matches_idx"
- // filled in to match the index, or "exact_matches_idx" will
- // have SIZE_MAX
+ // This string list contains a list of valid auto completion strings, and the
+ // "s" is passed in. "matches" is filled in with zero or more string values
+ // that start with "s", and the first string to exactly match one of the
+ // string values in this collection, will have "exact_matches_idx" filled in
+ // to match the index, or "exact_matches_idx" will have SIZE_MAX
size_t AutoComplete(llvm::StringRef s, StringList &matches,
size_t &exact_matches_idx) const;
// Dump the StringList to the given lldb_private::Log, `log`, one item per
- // line.
- // If given, `name` will be used to identify the start and end of the list in
- // the output.
+ // line. If given, `name` will be used to identify the start and end of the
+ // list in the output.
virtual void LogDump(Log *log, const char *name = nullptr);
// Static helper to convert an iterable of strings to a StringList, and then
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/StructuredData.h b/contrib/llvm/tools/lldb/include/lldb/Utility/StructuredData.h
index 2ea5fb98e055..d3ebab16f51d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/StructuredData.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/StructuredData.h
@@ -38,17 +38,17 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class StructuredData StructuredData.h "lldb/Utility/StructuredData.h"
-/// @brief A class which can hold structured data
+/// A class which can hold structured data
///
-/// The StructuredData class is designed to hold the data from a JSON
-/// or plist style file -- a serialized data structure with dictionaries
-/// (maps, hashes), arrays, and concrete values like integers, floating
-/// point numbers, strings, booleans.
+/// The StructuredData class is designed to hold the data from a JSON or plist
+/// style file -- a serialized data structure with dictionaries (maps,
+/// hashes), arrays, and concrete values like integers, floating point
+/// numbers, strings, booleans.
///
-/// StructuredData does not presuppose any knowledge of the schema for
-/// the data it is holding; it can parse JSON data, for instance, and
-/// other parts of lldb can iterate through the parsed data set to find
-/// keys and values that may be present.
+/// StructuredData does not presuppose any knowledge of the schema for the
+/// data it is holding; it can parse JSON data, for instance, and other parts
+/// of lldb can iterate through the parsed data set to find keys and values
+/// that may be present.
//----------------------------------------------------------------------
class StructuredData {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/TildeExpressionResolver.h b/contrib/llvm/tools/lldb/include/lldb/Utility/TildeExpressionResolver.h
index 84620320c7ac..ae6b4073f6aa 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/TildeExpressionResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/TildeExpressionResolver.h
@@ -22,7 +22,7 @@ class TildeExpressionResolver {
public:
virtual ~TildeExpressionResolver();
- /// \brief Resolve a Tilde Expression contained according to bash rules.
+ /// Resolve a Tilde Expression contained according to bash rules.
///
/// \param Expr Contains the tilde expression to resolve. A valid tilde
/// expression must begin with a tilde and contain only non
@@ -35,7 +35,7 @@ public:
virtual bool ResolveExact(llvm::StringRef Expr,
llvm::SmallVectorImpl<char> &Output) = 0;
- /// \brief Auto-complete a tilde expression with all matching values.
+ /// Auto-complete a tilde expression with all matching values.
///
/// \param Expr Contains the tilde expression prefix to resolve. See
/// ResolveExact() for validity rules.
@@ -48,8 +48,8 @@ public:
virtual bool ResolvePartial(llvm::StringRef Expr,
llvm::StringSet<> &Output) = 0;
- /// \brief Resolve an entire path that begins with a tilde expression,
- /// replacing the username portion with the matched result.
+ /// Resolve an entire path that begins with a tilde expression, replacing
+ /// the username portion with the matched result.
bool ResolveFullPath(llvm::StringRef Expr,
llvm::SmallVectorImpl<char> &Output);
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Timeout.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Timeout.h
index 7b627a45fc63..ecb33b346e96 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Timeout.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Timeout.h
@@ -22,9 +22,9 @@ namespace lldb_private {
// from Timeout<std::milli> to Timeout<std::micro>.
//
// The intended meaning of the values is:
-// - llvm::None - no timeout, the call should wait forever
-// - 0 - poll, only complete the call if it will not block
-// - >0 - wait for a given number of units for the result
+// - llvm::None - no timeout, the call should wait forever - 0 - poll, only
+// complete the call if it will not block - >0 - wait for a given number of
+// units for the result
template <typename Ratio>
class Timeout : public llvm::Optional<std::chrono::duration<int64_t, Ratio>> {
private:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Timer.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Timer.h
index c06ac17d344d..2c1e984837c2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Timer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Timer.h
@@ -20,7 +20,7 @@ class Stream;
//----------------------------------------------------------------------
/// @class Timer Timer.h "lldb/Utility/Timer.h"
-/// @brief A timer class that simplifies common timing metrics.
+/// A timer class that simplifies common timing metrics.
//----------------------------------------------------------------------
class Timer {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/UUID.h b/contrib/llvm/tools/lldb/include/lldb/Utility/UUID.h
index 5e64e9079789..d42c88862bfa 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/UUID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/UUID.h
@@ -15,6 +15,7 @@
#include <stddef.h>
#include <stdint.h>
#include <string>
+#include "llvm/ADT/ArrayRef.h"
namespace llvm {
class StringRef;
@@ -26,36 +27,49 @@ namespace lldb_private {
class UUID {
public:
- // Most UUIDs are 16 bytes, but some Linux build-ids (SHA1) are 20.
- typedef uint8_t ValueType[20];
-
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- UUID();
- UUID(const UUID &rhs);
- UUID(const void *uuid_bytes, uint32_t num_uuid_bytes);
-
- ~UUID();
-
- const UUID &operator=(const UUID &rhs);
-
- void Clear();
+ UUID() = default;
+
+ /// Creates a UUID from the data pointed to by the bytes argument. No special
+ /// significance is attached to any of the values.
+ static UUID fromData(const void *bytes, uint32_t num_bytes) {
+ if (bytes)
+ return fromData({reinterpret_cast<const uint8_t *>(bytes), num_bytes});
+ return UUID();
+ }
+
+ /// Creates a uuid from the data pointed to by the bytes argument. No special
+ /// significance is attached to any of the values.
+ static UUID fromData(llvm::ArrayRef<uint8_t> bytes) { return UUID(bytes); }
+
+ /// Creates a UUID from the data pointed to by the bytes argument. Data
+ /// consisting purely of zero bytes is treated as an invalid UUID.
+ static UUID fromOptionalData(const void *bytes, uint32_t num_bytes) {
+ if (bytes)
+ return fromOptionalData(
+ {reinterpret_cast<const uint8_t *>(bytes), num_bytes});
+ return UUID();
+ }
+
+ /// Creates a UUID from the data pointed to by the bytes argument. Data
+ /// consisting purely of zero bytes is treated as an invalid UUID.
+ static UUID fromOptionalData(llvm::ArrayRef<uint8_t> bytes) {
+ if (llvm::all_of(bytes, [](uint8_t b) { return b == 0; }))
+ return UUID();
+ return UUID(bytes);
+ }
+
+ void Clear() { m_bytes.clear(); }
void Dump(Stream *s) const;
- const void *GetBytes() const;
+ llvm::ArrayRef<uint8_t> GetBytes() const { return m_bytes; }
- size_t GetByteSize() const;
+ explicit operator bool() const { return IsValid(); }
+ bool IsValid() const { return !m_bytes.empty(); }
- bool IsValid() const;
-
- bool SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes = 16);
-
- std::string GetAsString(const char *separator = nullptr) const;
+ std::string GetAsString(llvm::StringRef separator = "-") const;
size_t SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes = 16);
- size_t SetFromCString(const char *c_str, uint32_t num_uuid_bytes = 16);
// Decode as many UUID bytes (up to 16) as possible from the C string "cstr"
// This is used for auto completion where a partial UUID might have been
@@ -77,25 +91,34 @@ public:
/// The original string, with all decoded bytes removed.
//------------------------------------------------------------------
static llvm::StringRef
- DecodeUUIDBytesFromString(llvm::StringRef str, ValueType &uuid_bytes,
- uint32_t &bytes_decoded,
+ DecodeUUIDBytesFromString(llvm::StringRef str,
+ llvm::SmallVectorImpl<uint8_t> &uuid_bytes,
uint32_t num_uuid_bytes = 16);
-protected:
- //------------------------------------------------------------------
- // Classes that inherit from UUID can see and modify these
- //------------------------------------------------------------------
- uint32_t m_num_uuid_bytes; // Should be 16 or 20
- ValueType m_uuid;
+private:
+ UUID(llvm::ArrayRef<uint8_t> bytes) : m_bytes(bytes.begin(), bytes.end()) {}
+
+ // GNU ld generates 20-byte build-ids. Size chosen to avoid heap allocations
+ // for this case.
+ llvm::SmallVector<uint8_t, 20> m_bytes;
+
+ friend bool operator==(const UUID &LHS, const UUID &RHS) {
+ return LHS.m_bytes == RHS.m_bytes;
+ }
+ friend bool operator!=(const UUID &LHS, const UUID &RHS) {
+ return !(LHS == RHS);
+ }
+ friend bool operator<(const UUID &LHS, const UUID &RHS) {
+ return LHS.m_bytes < RHS.m_bytes;
+ }
+ friend bool operator<=(const UUID &LHS, const UUID &RHS) {
+ return !(RHS < LHS);
+ }
+ friend bool operator>(const UUID &LHS, const UUID &RHS) { return RHS < LHS; }
+ friend bool operator>=(const UUID &LHS, const UUID &RHS) {
+ return !(LHS < RHS);
+ }
};
-
-bool operator==(const UUID &lhs, const UUID &rhs);
-bool operator!=(const UUID &lhs, const UUID &rhs);
-bool operator<(const UUID &lhs, const UUID &rhs);
-bool operator<=(const UUID &lhs, const UUID &rhs);
-bool operator>(const UUID &lhs, const UUID &rhs);
-bool operator>=(const UUID &lhs, const UUID &rhs);
-
} // namespace lldb_private
#endif // LLDB_UTILITY_UUID_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/UserID.h b/contrib/llvm/tools/lldb/include/lldb/Utility/UserID.h
index b178efd44fe4..9e15e6a43c6c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/UserID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/UserID.h
@@ -20,14 +20,14 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class UserID UserID.h "lldb/Core/UserID.h"
-/// @brief A mix in class that contains a generic user ID.
+/// A mix in class that contains a generic user ID.
///
-/// UserID is designed as a mix in class that can contain an integer
-/// based unique identifier for a variety of objects in lldb.
+/// UserID is designed as a mix in class that can contain an integer based
+/// unique identifier for a variety of objects in lldb.
///
-/// The value for this identifier is chosen by each parser plug-in. A
-/// value should be chosen that makes sense for each kind of object
-/// and should allow quick access to further and more in depth parsing.
+/// The value for this identifier is chosen by each parser plug-in. A value
+/// should be chosen that makes sense for each kind of object and should allow
+/// quick access to further and more in depth parsing.
///
/// Symbol table entries can use this to store the original symbol table
/// index, functions can use it to store the symbol table index or the
@@ -68,11 +68,9 @@ struct UserID {
void SetID(lldb::user_id_t uid) { m_uid = uid; }
//------------------------------------------------------------------
- /// Unary predicate function object that can search for a matching
- /// user ID.
+ /// Unary predicate function object that can search for a matching user ID.
///
- /// Function object that can be used on any class that inherits
- /// from UserID:
+ /// Function object that can be used on any class that inherits from UserID:
/// \code
/// iterator pos;
/// pos = std::find_if (coll.begin(), coll.end(), UserID::IDMatches(blockID));
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/VMRange.h b/contrib/llvm/tools/lldb/include/lldb/Utility/VMRange.h
index f03a1b0c1f97..0e696907baa7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/VMRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/VMRange.h
@@ -87,24 +87,6 @@ public:
void Dump(Stream *s, lldb::addr_t base_addr = 0,
uint32_t addr_width = 8) const;
- class ValueInRangeUnaryPredicate {
- public:
- ValueInRangeUnaryPredicate(lldb::addr_t value) : _value(value) {}
- bool operator()(const VMRange &range) const {
- return range.Contains(_value);
- }
- lldb::addr_t _value;
- };
-
- class RangeInRangeUnaryPredicate {
- public:
- RangeInRangeUnaryPredicate(VMRange range) : _range(range) {}
- bool operator()(const VMRange &range) const {
- return range.Contains(_range);
- }
- const VMRange &_range;
- };
-
static bool ContainsValue(const VMRange::collection &coll,
lldb::addr_t value);
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h b/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h
index a1318f4412e9..edb70be09fd9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h
@@ -12,7 +12,7 @@
#include "lldb/lldb-types.h"
-#if defined(_MSC_VER)
+#if defined(_WIN32)
#if defined(EXPORT_LIBLLDB)
#define LLDB_API __declspec(dllexport)
#elif defined(IMPORT_LIBLLDB)
@@ -20,7 +20,7 @@
#else
#define LLDB_API
#endif
-#else // defined (_MSC_VER)
+#else // defined (_WIN32)
#define LLDB_API
#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h b/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h
index 760e12b0e799..a1f730379534 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h
@@ -21,8 +21,8 @@
// warning, as it's part of -Wmicrosoft which also catches a whole slew of
// other useful issues.
//
-// To make matters worse, early versions of SWIG don't recognize the syntax
-// of specifying the underlying type of an enum (and Python doesn't care anyway)
+// To make matters worse, early versions of SWIG don't recognize the syntax of
+// specifying the underlying type of an enum (and Python doesn't care anyway)
// so we need a way to specify the underlying type when the enum is being used
// from C++ code, but just use a regular enum when swig is pre-processing.
#define FLAGS_ENUM(Name) enum Name : unsigned
@@ -44,6 +44,9 @@ enum StateType {
///launched or attached to anything yet
eStateAttaching, ///< Process is currently trying to attach
eStateLaunching, ///< Process is in the process of launching
+ // The state changes eStateAttaching and eStateLaunching are both sent while the
+ // private state thread is either not yet started or paused. For that reason, they
+ // should only be signaled as public state changes, and not private state changes.
eStateStopped, ///< Process or thread is stopped and can be examined.
eStateRunning, ///< Process or thread is running and can't be examined.
eStateStepping, ///< Process or thread is in the process of stepping and can
@@ -193,9 +196,8 @@ enum ScriptLanguage {
//----------------------------------------------------------------------
// Register numbering types
-// See RegisterContext::ConvertRegisterKindToRegisterNumber to convert
-// any of these to the lldb internal register numbering scheme
-// (eRegisterKindLLDB).
+// See RegisterContext::ConvertRegisterKindToRegisterNumber to convert any of
+// these to the lldb internal register numbering scheme (eRegisterKindLLDB).
//----------------------------------------------------------------------
enum RegisterKind {
eRegisterKindEHFrame = 0, // the register numbers seen in eh_frame
@@ -445,8 +447,8 @@ enum LanguageType {
// Vendor Extensions
// Note: Language::GetNameForLanguageType
// assumes these can be used as indexes into array language_names, and
- // Language::SetLanguageFromCString and Language::AsCString
- // assume these can be used as indexes into array g_languages.
+ // Language::SetLanguageFromCString and Language::AsCString assume these can
+ // be used as indexes into array g_languages.
eLanguageTypeMipsAssembler = 0x0024, ///< Mips_Assembler.
eLanguageTypeExtRenderScript = 0x0025, ///< RenderScript.
eNumLanguageTypes
@@ -624,7 +626,7 @@ enum SectionType {
eSectionTypeDebug,
eSectionTypeZeroFill,
eSectionTypeDataObjCMessageRefs, // Pointer to function pointer + selector
- eSectionTypeDataObjCCFStrings, // Objective C const CFString/NSString objects
+ eSectionTypeDataObjCCFStrings, // Objective-C const CFString/NSString objects
eSectionTypeDWARFDebugAbbrev,
eSectionTypeDWARFDebugAddr,
eSectionTypeDWARFDebugAranges,
@@ -656,6 +658,9 @@ enum SectionType {
eSectionTypeGoSymtab,
eSectionTypeAbsoluteAddress, // Dummy section for symbols with absolute
// address
+ eSectionTypeDWARFGNUDebugAltLink,
+ eSectionTypeDWARFDebugTypes, // DWARF .debug_types section
+ eSectionTypeDWARFDebugNames, // DWARF v5 .debug_names
eSectionTypeOther
};
@@ -670,10 +675,10 @@ FLAGS_ENUM(FunctionNameType){
(1u << 1), // Automatically figure out which FunctionNameType
// bits to set based on the function name.
eFunctionNameTypeFull = (1u << 2), // The function name.
- // For C this is the same as just the name of the function
- // For C++ this is the mangled or demangled version of the mangled name.
- // For ObjC this is the full function signature with the + or
- // - and the square brackets and the class and selector
+ // For C this is the same as just the name of the function For C++ this is
+ // the mangled or demangled version of the mangled name. For ObjC this is
+ // the full function signature with the + or - and the square brackets and
+ // the class and selector
eFunctionNameTypeBase = (1u << 3), // The function name only, no namespaces
// or arguments and no class
// methods or selectors will be searched.
@@ -772,8 +777,8 @@ enum TemplateArgumentKind {
};
//----------------------------------------------------------------------
-// Options that can be set for a formatter to alter its behavior
-// Not all of these are applicable to all formatter types
+// Options that can be set for a formatter to alter its behavior Not all of
+// these are applicable to all formatter types
//----------------------------------------------------------------------
FLAGS_ENUM(TypeOptions){eTypeOptionNone = (0u),
eTypeOptionCascade = (1u << 0),
@@ -784,23 +789,22 @@ FLAGS_ENUM(TypeOptions){eTypeOptionNone = (0u),
eTypeOptionShowOneLiner = (1u << 5),
eTypeOptionHideNames = (1u << 6),
eTypeOptionNonCacheable = (1u << 7),
- eTypeOptionHideEmptyAggregates = (1u << 8)};
+ eTypeOptionHideEmptyAggregates = (1u << 8),
+ eTypeOptionFrontEndWantsDereference = (1u << 9)
+};
//----------------------------------------------------------------------
-// This is the return value for frame comparisons. If you are comparing frame A
-// to frame B
-// the following cases arise:
-// 1) When frame A pushes frame B (or a frame that ends up pushing B) A is Older
-// than B.
-// 2) When frame A pushed frame B (or if frame A is on the stack but B is not) A
-// is Younger than B
-// 3) When frame A and frame B have the same StackID, they are Equal.
-// 4) When frame A and frame B have the same immediate parent frame, but are not
-// equal, the comparison yields
+// This is the return value for frame comparisons. If you are comparing frame
+// A to frame B the following cases arise: 1) When frame A pushes frame B (or a
+// frame that ends up pushing B) A is Older than B. 2) When frame A pushed
+// frame B (or if frame A is on the stack but B is not) A is Younger than B 3)
+// When frame A and frame B have the same StackID, they are Equal. 4) When
+// frame A and frame B have the same immediate parent frame, but are not equal,
+// the comparison yields
// SameParent.
// 5) If the two frames are on different threads or processes the comparison is
-// Invalid
-// 6) If for some reason we can't figure out what went on, we return Unknown.
+// Invalid 6) If for some reason we can't figure out what went on, we return
+// Unknown.
//----------------------------------------------------------------------
enum FrameComparison {
eFrameCompareInvalid,
@@ -812,31 +816,10 @@ enum FrameComparison {
};
//----------------------------------------------------------------------
-// Address Class
-//
-// A way of classifying an address used for disassembling and setting
-// breakpoints. Many object files can track exactly what parts of their
-// object files are code, data and other information. This is of course
-// above and beyond just looking at the section types. For example, code
-// might contain PC relative data and the object file might be able to
-// tell us that an address in code is data.
-//----------------------------------------------------------------------
-enum AddressClass {
- eAddressClassInvalid,
- eAddressClassUnknown,
- eAddressClassCode,
- eAddressClassCodeAlternateISA,
- eAddressClassData,
- eAddressClassDebug,
- eAddressClassRuntime
-};
-
-//----------------------------------------------------------------------
// File Permissions
//
-// Designed to mimic the unix file permission bits so they can be
-// used with functions that set 'mode_t' to certain values for
-// permissions.
+// Designed to mimic the unix file permission bits so they can be used with
+// functions that set 'mode_t' to certain values for permissions.
//----------------------------------------------------------------------
FLAGS_ENUM(FilePermissions){
eFilePermissionsUserRead = (1u << 8), eFilePermissionsUserWrite = (1u << 7),
@@ -896,8 +879,8 @@ FLAGS_ENUM(FilePermissions){
//----------------------------------------------------------------------
// Queue work item types
//
-// The different types of work that can be enqueued on a libdispatch
-// aka Grand Central Dispatch (GCD) queue.
+// The different types of work that can be enqueued on a libdispatch aka Grand
+// Central Dispatch (GCD) queue.
//----------------------------------------------------------------------
enum QueueItemKind {
eQueueItemKindUnknown = 0,
@@ -931,8 +914,8 @@ enum ExpressionEvaluationPhase {
//----------------------------------------------------------------------
// Watchpoint Kind
-// Indicates what types of events cause the watchpoint to fire.
-// Used by Native*Protocol-related classes.
+// Indicates what types of events cause the watchpoint to fire. Used by Native
+// *Protocol-related classes.
//----------------------------------------------------------------------
FLAGS_ENUM(WatchpointKind){eWatchpointKindWrite = (1u << 0),
eWatchpointKindRead = (1u << 1)};
@@ -947,9 +930,9 @@ enum GdbSignal {
};
//----------------------------------------------------------------------
-// Used with SBHost::GetPath (lldb::PathType) to find files that are
-// related to LLDB on the current host machine. Most files are relative
-// to LLDB or are in known locations.
+// Used with SBHost::GetPath (lldb::PathType) to find files that are related to
+// LLDB on the current host machine. Most files are relative to LLDB or are in
+// known locations.
//----------------------------------------------------------------------
enum PathType {
ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB
@@ -1008,58 +991,54 @@ FLAGS_ENUM(CommandFlags){
//----------------------------------------------------------------------
// eCommandRequiresTarget
//
- // Ensures a valid target is contained in m_exe_ctx prior to executing
- // the command. If a target doesn't exist or is invalid, the command
- // will fail and CommandObject::GetInvalidTargetDescription() will be
- // returned as the error. CommandObject subclasses can override the
- // virtual function for GetInvalidTargetDescription() to provide custom
- // strings when needed.
+ // Ensures a valid target is contained in m_exe_ctx prior to executing the
+ // command. If a target doesn't exist or is invalid, the command will fail
+ // and CommandObject::GetInvalidTargetDescription() will be returned as the
+ // error. CommandObject subclasses can override the virtual function for
+ // GetInvalidTargetDescription() to provide custom strings when needed.
//----------------------------------------------------------------------
eCommandRequiresTarget = (1u << 0),
//----------------------------------------------------------------------
// eCommandRequiresProcess
//
- // Ensures a valid process is contained in m_exe_ctx prior to executing
- // the command. If a process doesn't exist or is invalid, the command
- // will fail and CommandObject::GetInvalidProcessDescription() will be
- // returned as the error. CommandObject subclasses can override the
- // virtual function for GetInvalidProcessDescription() to provide custom
- // strings when needed.
+ // Ensures a valid process is contained in m_exe_ctx prior to executing the
+ // command. If a process doesn't exist or is invalid, the command will fail
+ // and CommandObject::GetInvalidProcessDescription() will be returned as
+ // the error. CommandObject subclasses can override the virtual function
+ // for GetInvalidProcessDescription() to provide custom strings when
+ // needed.
//----------------------------------------------------------------------
eCommandRequiresProcess = (1u << 1),
//----------------------------------------------------------------------
// eCommandRequiresThread
//
- // Ensures a valid thread is contained in m_exe_ctx prior to executing
- // the command. If a thread doesn't exist or is invalid, the command
- // will fail and CommandObject::GetInvalidThreadDescription() will be
- // returned as the error. CommandObject subclasses can override the
- // virtual function for GetInvalidThreadDescription() to provide custom
- // strings when needed.
+ // Ensures a valid thread is contained in m_exe_ctx prior to executing the
+ // command. If a thread doesn't exist or is invalid, the command will fail
+ // and CommandObject::GetInvalidThreadDescription() will be returned as the
+ // error. CommandObject subclasses can override the virtual function for
+ // GetInvalidThreadDescription() to provide custom strings when needed.
//----------------------------------------------------------------------
eCommandRequiresThread = (1u << 2),
//----------------------------------------------------------------------
// eCommandRequiresFrame
//
- // Ensures a valid frame is contained in m_exe_ctx prior to executing
- // the command. If a frame doesn't exist or is invalid, the command
- // will fail and CommandObject::GetInvalidFrameDescription() will be
- // returned as the error. CommandObject subclasses can override the
- // virtual function for GetInvalidFrameDescription() to provide custom
- // strings when needed.
+ // Ensures a valid frame is contained in m_exe_ctx prior to executing the
+ // command. If a frame doesn't exist or is invalid, the command will fail
+ // and CommandObject::GetInvalidFrameDescription() will be returned as the
+ // error. CommandObject subclasses can override the virtual function for
+ // GetInvalidFrameDescription() to provide custom strings when needed.
//----------------------------------------------------------------------
eCommandRequiresFrame = (1u << 3),
//----------------------------------------------------------------------
// eCommandRequiresRegContext
//
- // Ensures a valid register context (from the selected frame if there
- // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
- // is available from m_exe_ctx prior to executing the command. If a
- // target doesn't exist or is invalid, the command will fail and
- // CommandObject::GetInvalidRegContextDescription() will be returned as
- // the error. CommandObject subclasses can override the virtual function
- // for GetInvalidRegContextDescription() to provide custom strings when
- // needed.
+ // Ensures a valid register context (from the selected frame if there is a
+ // frame in m_exe_ctx, or from the selected thread from m_exe_ctx) is
+ // available from m_exe_ctx prior to executing the command. If a target
+ // doesn't exist or is invalid, the command will fail and
+ // CommandObject::GetInvalidRegContextDescription() will be returned as the
+ // error. CommandObject subclasses can override the virtual function for
+ // GetInvalidRegContextDescription() to provide custom strings when needed.
//----------------------------------------------------------------------
eCommandRequiresRegContext = (1u << 4),
//----------------------------------------------------------------------
@@ -1073,15 +1052,15 @@ FLAGS_ENUM(CommandFlags){
//----------------------------------------------------------------------
// eCommandProcessMustBeLaunched
//
- // Verifies that there is a launched process in m_exe_ctx, if there
- // isn't, the command will fail with an appropriate error message.
+ // Verifies that there is a launched process in m_exe_ctx, if there isn't,
+ // the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eCommandProcessMustBeLaunched = (1u << 6),
//----------------------------------------------------------------------
// eCommandProcessMustBePaused
//
- // Verifies that there is a paused process in m_exe_ctx, if there
- // isn't, the command will fail with an appropriate error message.
+ // Verifies that there is a paused process in m_exe_ctx, if there isn't,
+ // the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eCommandProcessMustBePaused = (1u << 7)};
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h b/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h
index a324edf9da3b..e3964268dfda 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h
@@ -76,6 +76,7 @@ class ConnectionFileDescriptor;
class ConstString;
class CXXSyntheticChildren;
class DWARFCallFrameInfo;
+class DWARFDataExtractor;
class DWARFExpression;
class DataBuffer;
class DataEncoder;
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-defines.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-defines.h
index 22172366c259..9b6594422e82 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-defines.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-defines.h
@@ -23,7 +23,7 @@
#endif
/// \macro LLVM_FALLTHROUGH
-/// \brief Marks an empty statement preceding a deliberate switch fallthrough.
+/// Marks an empty statement preceding a deliberate switch fallthrough.
#if __has_cpp_attribute(clang::fallthrough)
#define LLVM_FALLTHROUGH [[clang::fallthrough]]
#else
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h
index 983ddf3d23d6..c25f285c9713 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h
@@ -43,6 +43,26 @@ typedef enum AddressType {
} AddressType;
//----------------------------------------------------------------------
+// Address Class
+//
+// A way of classifying an address used for disassembling and setting
+// breakpoints. Many object files can track exactly what parts of their object
+// files are code, data and other information. This is of course above and
+// beyond just looking at the section types. For example, code might contain PC
+// relative data and the object file might be able to tell us that an address
+// in code is data.
+//----------------------------------------------------------------------
+enum class AddressClass {
+ eInvalid,
+ eUnknown,
+ eCode,
+ eCodeAlternateISA,
+ eData,
+ eDebug,
+ eRuntime
+};
+
+//----------------------------------------------------------------------
// Votes - Need a tri-state, yes, no, no opinion...
//----------------------------------------------------------------------
typedef enum Vote { eVoteNo = -1, eVoteNoOpinion = 0, eVoteYes = 1 } Vote;
@@ -105,9 +125,9 @@ typedef enum SortOrder {
} SortOrder;
//----------------------------------------------------------------------
-// LazyBool is for boolean values that need to be calculated lazily.
-// Values start off set to eLazyBoolCalculate, and then they can be
-// calculated once and set to eLazyBoolNo or eLazyBoolYes.
+// LazyBool is for boolean values that need to be calculated lazily. Values
+// start off set to eLazyBoolCalculate, and then they can be calculated once
+// and set to eLazyBoolNo or eLazyBoolYes.
//----------------------------------------------------------------------
typedef enum LazyBool {
eLazyBoolCalculate = -1,
@@ -217,8 +237,7 @@ enum class LineStatus {
enum class TypeValidatorResult : bool { Success = true, Failure = false };
//----------------------------------------------------------------------
-// Enumerations that can be used to specify scopes types when looking up
-// types.
+// Enumerations that can be used to specify scopes types when looking up types.
//----------------------------------------------------------------------
enum class CompilerContextKind {
Invalid = 0,
@@ -234,6 +253,35 @@ enum class CompilerContextKind {
Typedef
};
+//----------------------------------------------------------------------
+// Enumerations that can be used to specify the kind of metric we're looking at
+// when collecting stats.
+//----------------------------------------------------------------------
+enum StatisticKind {
+ ExpressionSuccessful = 0,
+ ExpressionFailure = 1,
+ FrameVarSuccess = 2,
+ FrameVarFailure = 3,
+ StatisticMax = 4
+};
+
+
+inline std::string GetStatDescription(lldb_private::StatisticKind K) {
+ switch (K) {
+ case StatisticKind::ExpressionSuccessful:
+ return "Number of expr evaluation successes";
+ case StatisticKind::ExpressionFailure:
+ return "Number of expr evaluation failures";
+ case StatisticKind::FrameVarSuccess:
+ return "Number of frame var successes";
+ case StatisticKind::FrameVarFailure:
+ return "Number of frame var failures";
+ case StatisticKind::StatisticMax:
+ return "";
+ }
+ llvm_unreachable("Statistic not registered!");
+}
+
} // namespace lldb_private
namespace llvm {
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-forward.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-forward.h
index ea122525ef90..65d303281164 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-forward.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-forward.h
@@ -15,8 +15,8 @@
#include <memory>
namespace lldb_private {
-// ---------------------------------------------------------------
-// Class forward decls.
+// --------------------------------------------------------------- Class
+// forward decls.
// ---------------------------------------------------------------
class NativeBreakpoint;
class NativeBreakpointList;
@@ -26,8 +26,7 @@ class NativeThreadProtocol;
class ResumeActionList;
class UnixSignals;
-// ---------------------------------------------------------------
-// SP/WP decls.
+// --------------------------------------------------------------- SP/WP decls.
// ---------------------------------------------------------------
typedef std::shared_ptr<NativeBreakpoint> NativeBreakpointSP;
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h
index fd21641218fb..7ba7350e868c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h
@@ -30,9 +30,8 @@ typedef llvm::sys::DynamicLibrary (*LoadPluginCallbackType)(
const lldb::DebuggerSP &debugger_sp, const FileSpec &spec, Status &error);
//----------------------------------------------------------------------
-// Every register is described in detail including its name, alternate
-// name (optional), encoding, size in bytes and the default display
-// format.
+// Every register is described in detail including its name, alternate name
+// (optional), encoding, size in bytes and the default display format.
//----------------------------------------------------------------------
struct RegisterInfo {
const char *name; // Name of this register, can't be NULL
@@ -41,28 +40,29 @@ struct RegisterInfo {
uint32_t byte_offset; // The byte offset in the register context data where
// this register's value is found.
// This is optional, and can be 0 if a particular RegisterContext does not
- // need to
- // address its registers by byte offset.
+ // need to address its registers by byte offset.
lldb::Encoding encoding; // Encoding of the register bits
lldb::Format format; // Default display format
uint32_t kinds[lldb::kNumRegisterKinds]; // Holds all of the various register
// numbers for all register kinds
uint32_t *value_regs; // List of registers (terminated with
- // LLDB_INVALID_REGNUM). If this value is not
- // null, all registers in this list will be read first, at which point the
- // value
- // for this register will be valid. For example, the value list for ah
- // would be eax (x86) or rax (x64).
+ // LLDB_INVALID_REGNUM). If this value is not null,
+ // all registers in this list will be read first, at
+ // which point the value for this register will be
+ // valid. For example, the value list for ah would be
+ // eax (x86) or rax (x64).
uint32_t *invalidate_regs; // List of registers (terminated with
// LLDB_INVALID_REGNUM). If this value is not
- // null, all registers in this list will be invalidated when the value of this
- // register changes. For example, the invalidate list for eax would be rax
- // ax, ah, and al.
+ // null, all registers in this list will be
+ // invalidated when the value of this register
+ // changes. For example, the invalidate list for
+ // eax would be rax ax, ah, and al.
const uint8_t *dynamic_size_dwarf_expr_bytes; // A DWARF expression that when
// evaluated gives
// the byte size of this register.
size_t dynamic_size_dwarf_len; // The length of the DWARF expression in bytes
- // in the dynamic_size_dwarf_expr_bytes member.
+ // in the dynamic_size_dwarf_expr_bytes
+ // member.
llvm::ArrayRef<uint8_t> data(const uint8_t *context_base) const {
return llvm::ArrayRef<uint8_t>(context_base + byte_offset, byte_size);
@@ -85,8 +85,8 @@ struct RegisterSet {
// values in this array are
// *indices* (not register numbers) into a particular RegisterContext's
// register array. For example, if eax is defined at index 4 for a
- // particular RegisterContext, eax would be included in this RegisterSet
- // by adding the value 4. Not by adding the value lldb_eax_i386.
+ // particular RegisterContext, eax would be included in this RegisterSet by
+ // adding the value 4. Not by adding the value lldb_eax_i386.
};
struct OptionEnumValueElement {
@@ -112,7 +112,8 @@ struct OptionDefinition {
int short_option; // Single character for this option.
int option_has_arg; // no_argument, required_argument or optional_argument
OptionValidator *validator; // If non-NULL, option is valid iff
- // |validator->IsValid()|, otherwise always valid.
+ // |validator->IsValid()|, otherwise always
+ // valid.
OptionEnumValueElement *enum_values; // If non-NULL an array of enum values.
uint32_t completion_type; // Cookie the option class can use to do define the
// argument completion.
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-types.h b/contrib/llvm/tools/lldb/include/lldb/lldb-types.h
index fc445f55a9e5..79f441569304 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-types.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-types.h
@@ -31,8 +31,8 @@
//----------------------------------------------------------------------
// TODO: Add a bunch of ifdefs to determine the host system and what
-// things should be defined. Currently MacOSX is being assumed by default
-// since that is what lldb was first developed for.
+// things should be defined. Currently MacOSX is being assumed by default since
+// that is what lldb was first developed for.
#ifdef _WIN32
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-versioning.h b/contrib/llvm/tools/lldb/include/lldb/lldb-versioning.h
index b0af5dc64b47..9d5fd164119e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-versioning.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-versioning.h
@@ -100,8 +100,8 @@
*/
// if you want the version checking to work on other OS/compiler, define
-// appropriate IMPL_DEPRECATED/IMPL_TOONEW
-// and define LLDB_API_CHECK_VERSIONING_WORKS when you are ready to go live
+// appropriate IMPL_DEPRECATED/IMPL_TOONEW and define
+// LLDB_API_CHECK_VERSIONING_WORKS when you are ready to go live
#if defined(__APPLE__) && defined(__clang__)
#define LLDB_API_IMPL_DEPRECATED __attribute__((deprecated))
#define LLDB_API_IMPL_TOONEW __attribute__((unavailable))
diff --git a/contrib/llvm/tools/lldb/include/lldb/module.modulemap b/contrib/llvm/tools/lldb/include/lldb/module.modulemap
new file mode 100644
index 000000000000..cec0428c1840
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/module.modulemap
@@ -0,0 +1,139 @@
+
+module lldb_API {
+ requires cplusplus
+
+ umbrella "API"
+ module * { export * }
+}
+
+module lldb_Host {
+ requires cplusplus
+
+ // Because we have OS-specific headers in Host, we just list
+ // all OS-independent headers here that will include the correct
+ // OS-specific header for us.
+ module ConnectionFileDescriptor { header "Host/ConnectionFileDescriptor.h" export * }
+ module Debug { header "Host/Debug.h" export * }
+ module Editline { header "Host/Editline.h" export * }
+ module FileCache { header "Host/FileCache.h" export * }
+ module File { header "Host/File.h" export * }
+ module FileSystem { header "Host/FileSystem.h" export * }
+ module HostGetOpt { header "Host/HostGetOpt.h" export * }
+ module Host { header "Host/Host.h" export * }
+ module HostInfoBase { header "Host/HostInfoBase.h" export * }
+ module HostInfo { header "Host/HostInfo.h" export * }
+ module HostNativeProcessBase { header "Host/HostNativeProcessBase.h" export * }
+ module HostNativeProcess { header "Host/HostNativeProcess.h" export * }
+ module HostNativeThreadBase { header "Host/HostNativeThreadBase.h" export * }
+ module HostNativeThreadForward { header "Host/HostNativeThreadForward.h" export * }
+ module HostNativeThread { header "Host/HostNativeThread.h" export * }
+ module HostProcess { header "Host/HostProcess.h" export * }
+ module HostThread { header "Host/HostThread.h" export * }
+ module LockFileBase { header "Host/LockFileBase.h" export * }
+ module LockFile { header "Host/LockFile.h" export * }
+ module MainLoopBase { header "Host/MainLoopBase.h" export * }
+ module MainLoop { header "Host/MainLoop.h" export * }
+ module MonitoringProcessLauncher { header "Host/MonitoringProcessLauncher.h" export * }
+ module OptionParser { header "Host/OptionParser.h" export * }
+ module PipeBase { header "Host/PipeBase.h" export * }
+ module Pipe { header "Host/Pipe.h" export * }
+ module PosixApi { header "Host/PosixApi.h" export * }
+ module Predicate { header "Host/Predicate.h" export * }
+ module ProcessLauncher { header "Host/ProcessLauncher.h" export * }
+ module ProcessRunLock { header "Host/ProcessRunLock.h" export * }
+ module PseudoTerminal { header "Host/PseudoTerminal.h" export * }
+ module SocketAddress { header "Host/SocketAddress.h" export * }
+ module Socket { header "Host/Socket.h" export * }
+ module StringConvert { header "Host/StringConvert.h" export * }
+ module Symbols { header "Host/Symbols.h" export * }
+ module TaskPool { header "Host/TaskPool.h" export * }
+ module Terminal { header "Host/Terminal.h" export * }
+ module ThreadLauncher { header "Host/ThreadLauncher.h" export * }
+ module Time { header "Host/Time.h" export * }
+ module XML { header "Host/XML.h" export * }
+
+ export *
+}
+
+module lldb_Initialization {
+ requires cplusplus
+
+ umbrella "Initialization"
+ module * { export * }
+}
+
+
+module lldb_Wrapper {
+
+ module lldb_Breakpoint {
+ requires cplusplus
+
+ umbrella "Breakpoint"
+ module * { export * }
+ }
+
+ module lldb_Core {
+ requires cplusplus
+
+ umbrella "Core"
+ module * { export * }
+ }
+
+ module lldb_DataFormatters {
+ requires cplusplus
+
+ umbrella "DataFormatters"
+ module * { export * }
+ }
+
+ module lldb_Expression {
+ requires cplusplus
+
+ umbrella "Expression"
+ module * { export * }
+ // TODO: This file includes a non-public header.
+ exclude header "Expression/REPL.h"
+ }
+
+ module lldb_Interpreter {
+ requires cplusplus
+
+ umbrella "Interpreter"
+ module * { export * }
+ }
+
+ module lldb_Symbol {
+ requires cplusplus
+
+ umbrella "Symbol"
+ module * { export * }
+ }
+ module lldb_Target {
+ requires cplusplus
+
+ umbrella "Target"
+ module * { export * }
+ }
+}
+
+
+module lldb_Utility {
+ requires cplusplus
+
+ umbrella "Utility"
+ module * { export * }
+
+ module lldb_defines { header "lldb-defines.h" export * }
+ module lldb_enumerations { header "lldb-enumerations.h" export * }
+ module lldb_forward { header "lldb-forward.h" export * }
+ module lldb_private_enumerations { header "lldb-private-enumerations.h" export * }
+ module lldb_private_defines { header "lldb-private-defines.h" export * }
+ module lldb_private_forward { header "lldb-private-forward.h" export * }
+ module lldb_private { header "lldb-private.h" export * }
+ module lldb_private_interfaces { header "lldb-private-interfaces.h" export * }
+ module lldb_private_types { header "lldb-private-types.h" export * }
+ module lldb_public { header "lldb-public.h" export * }
+ module lldb_types { header "lldb-types.h" export * }
+ module lldb_versioning { header "lldb-versioning.h" export * }
+
+}
diff --git a/contrib/llvm/tools/lldb/source/API/SBAddress.cpp b/contrib/llvm/tools/lldb/source/API/SBAddress.cpp
index a3493d7c743f..d12197e66ddd 100644
--- a/contrib/llvm/tools/lldb/source/API/SBAddress.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBAddress.cpp
@@ -120,10 +120,9 @@ void SBAddress::SetLoadAddress(lldb::addr_t load_addr, lldb::SBTarget &target) {
else
m_opaque_ap->Clear();
- // Check if we weren't were able to resolve a section offset address.
- // If we weren't it is ok, the load address might be a location on the
- // stack or heap, so we should just have an address with no section and
- // a valid offset
+ // Check if we weren't were able to resolve a section offset address. If we
+ // weren't it is ok, the load address might be a location on the stack or
+ // heap, so we should just have an address with no section and a valid offset
if (!m_opaque_ap->IsValid())
m_opaque_ap->SetOffset(load_addr);
}
@@ -163,9 +162,8 @@ Address &SBAddress::ref() {
}
const Address &SBAddress::ref() const {
- // This object should already have checked with "IsValid()"
- // prior to calling this function. In case you didn't we will assert
- // and die to let you know.
+ // This object should already have checked with "IsValid()" prior to calling
+ // this function. In case you didn't we will assert and die to let you know.
assert(m_opaque_ap.get());
return *m_opaque_ap;
}
@@ -242,9 +240,3 @@ SBLineEntry SBAddress::GetLineEntry() {
}
return sb_line_entry;
}
-
-AddressClass SBAddress::GetAddressClass() {
- if (m_opaque_ap->IsValid())
- return m_opaque_ap->GetAddressClass();
- return eAddressClassInvalid;
-}
diff --git a/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp b/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp
index e6500c468ec5..d6cb212dedf8 100644
--- a/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp
@@ -26,14 +26,16 @@ SBAttachInfo::SBAttachInfo(lldb::pid_t pid)
SBAttachInfo::SBAttachInfo(const char *path, bool wait_for)
: m_opaque_sp(new ProcessAttachInfo()) {
if (path && path[0])
- m_opaque_sp->GetExecutableFile().SetFile(path, false);
+ m_opaque_sp->GetExecutableFile().SetFile(path, false,
+ FileSpec::Style::native);
m_opaque_sp->SetWaitForLaunch(wait_for);
}
SBAttachInfo::SBAttachInfo(const char *path, bool wait_for, bool async)
: m_opaque_sp(new ProcessAttachInfo()) {
if (path && path[0])
- m_opaque_sp->GetExecutableFile().SetFile(path, false);
+ m_opaque_sp->GetExecutableFile().SetFile(path, false,
+ FileSpec::Style::native);
m_opaque_sp->SetWaitForLaunch(wait_for);
m_opaque_sp->SetAsync(async);
}
@@ -77,7 +79,8 @@ void SBAttachInfo::SetProcessPluginName(const char *plugin_name) {
void SBAttachInfo::SetExecutable(const char *path) {
if (path && path[0])
- m_opaque_sp->GetExecutableFile().SetFile(path, false);
+ m_opaque_sp->GetExecutableFile().SetFile(path, false,
+ FileSpec::Style::native);
else
m_opaque_sp->GetExecutableFile().Clear();
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBBreakpointName.cpp b/contrib/llvm/tools/lldb/source/API/SBBreakpointName.cpp
index 2205280b9e5f..a6742e3b89ec 100644
--- a/contrib/llvm/tools/lldb/source/API/SBBreakpointName.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBBreakpointName.cpp
@@ -52,8 +52,8 @@ public:
bool operator==(const SBBreakpointNameImpl &rhs);
bool operator!=(const SBBreakpointNameImpl &rhs);
- // For now we take a simple approach and only keep the name, and relook
- // up the location when we need it.
+ // For now we take a simple approach and only keep the name, and relook up
+ // the location when we need it.
TargetSP GetTarget() const {
return m_target_wp.lock();
@@ -115,8 +115,7 @@ SBBreakpointName::SBBreakpointName() {}
SBBreakpointName::SBBreakpointName(SBTarget &sb_target, const char *name)
{
m_impl_up.reset(new SBBreakpointNameImpl(sb_target, name));
- // Call FindBreakpointName here to make sure the name is valid, reset if
- // not:
+ // Call FindBreakpointName here to make sure the name is valid, reset if not:
BreakpointName *bp_name = GetBreakpointName();
if (!bp_name)
m_impl_up.reset();
@@ -133,8 +132,7 @@ SBBreakpointName::SBBreakpointName(SBBreakpoint &sb_bkpt, const char *name)
m_impl_up.reset(new SBBreakpointNameImpl(target.shared_from_this(), name));
- // Call FindBreakpointName here to make sure the name is valid, reset if
- // not:
+ // Call FindBreakpointName here to make sure the name is valid, reset if not:
BreakpointName *bp_name = GetBreakpointName();
if (!bp_name) {
m_impl_up.reset();
diff --git a/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp
index c9bb8f65fa2e..cbb514abb6fe 100644
--- a/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp
@@ -272,8 +272,8 @@ int SBCommandInterpreter::HandleCompletion(
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
int num_completions = 0;
- // Sanity check the arguments that are passed in:
- // cursor & last_char have to be within the current_line.
+ // Sanity check the arguments that are passed in: cursor & last_char have to
+ // be within the current_line.
if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
return 0;
@@ -379,6 +379,23 @@ void SBCommandInterpreter::SetPromptOnQuit(bool b) {
m_opaque_ptr->SetPromptOnQuit(b);
}
+void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
+ if (m_opaque_ptr)
+ m_opaque_ptr->AllowExitCodeOnQuit(allow);
+}
+
+bool SBCommandInterpreter::HasCustomQuitExitCode() {
+ bool exited = false;
+ if (m_opaque_ptr)
+ m_opaque_ptr->GetQuitExitCode(exited);
+ return exited;
+}
+
+int SBCommandInterpreter::GetQuitStatus() {
+ bool exited = false;
+ return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
+}
+
void SBCommandInterpreter::ResolveCommand(const char *command_line,
SBCommandReturnObject &result) {
result.Clear();
diff --git a/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp b/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
index d3294dab582d..a651141003a4 100644
--- a/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
@@ -11,6 +11,9 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+
+#include "SystemInitializerFull.h"
+
#include "lldb/API/SBDebugger.h"
#include "lldb/lldb-private.h"
@@ -35,7 +38,6 @@
#include "lldb/API/SBTypeNameSpecifier.h"
#include "lldb/API/SBTypeSummary.h"
#include "lldb/API/SBTypeSynthetic.h"
-#include "lldb/API/SystemInitializerFull.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
@@ -43,12 +45,14 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Host/XML.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Utility/Args.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -166,14 +170,10 @@ SBDebugger SBDebugger::Create(bool source_init_files,
SBDebugger debugger;
// Currently we have issues if this function is called simultaneously on two
- // different
- // threads. The issues mainly revolve around the fact that the
- // lldb_private::FormatManager
- // uses global collections and having two threads parsing the .lldbinit files
- // can cause
- // mayhem. So to get around this for now we need to use a mutex to prevent bad
- // things
- // from happening.
+ // different threads. The issues mainly revolve around the fact that the
+ // lldb_private::FormatManager uses global collections and having two threads
+ // parsing the .lldbinit files can cause mayhem. So to get around this for
+ // now we need to use a mutex to prevent bad things from happening.
static std::recursive_mutex g_mutex;
std::lock_guard<std::recursive_mutex> guard(g_mutex);
@@ -218,10 +218,10 @@ void SBDebugger::Destroy(SBDebugger &debugger) {
}
void SBDebugger::MemoryPressureDetected() {
- // Since this function can be call asynchronously, we allow it to be
- // non-mandatory. We have seen deadlocks with this function when called
- // so we need to safeguard against this until we can determine what is
- // causing the deadlocks.
+ // Since this function can be call asynchronously, we allow it to be non-
+ // mandatory. We have seen deadlocks with this function when called so we
+ // need to safeguard against this until we can determine what is causing the
+ // deadlocks.
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
const bool mandatory = false;
@@ -254,9 +254,9 @@ void SBDebugger::SkipAppInitFiles(bool b) {
m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles(b);
}
-// Shouldn't really be settable after initialization as this could cause lots of
-// problems; don't want users
-// trying to switch modes in the middle of a debugging session.
+// Shouldn't really be settable after initialization as this could cause lots
+// of problems; don't want users trying to switch modes in the middle of a
+// debugging session.
void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
@@ -479,8 +479,8 @@ bool SBDebugger::SetDefaultArchitecture(const char *arch_name) {
ScriptLanguage
SBDebugger::GetScriptingLanguage(const char *script_language_name) {
if (!script_language_name) return eScriptLanguageDefault;
- return Args::StringToScriptLanguage(llvm::StringRef(script_language_name),
- eScriptLanguageDefault, nullptr);
+ return OptionArgParser::ToScriptLanguage(
+ llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr);
}
const char *SBDebugger::GetVersionString() {
@@ -491,6 +491,38 @@ const char *SBDebugger::StateAsCString(StateType state) {
return lldb_private::StateAsCString(state);
}
+static void AddBoolConfigEntry(StructuredData::Dictionary &dict,
+ llvm::StringRef name, bool value,
+ llvm::StringRef description) {
+ auto entry_up = llvm::make_unique<StructuredData::Dictionary>();
+ entry_up->AddBooleanItem("value", value);
+ entry_up->AddStringItem("description", description);
+ dict.AddItem(name, std::move(entry_up));
+}
+
+static void AddLLVMTargets(StructuredData::Dictionary &dict) {
+ auto array_up = llvm::make_unique<StructuredData::Array>();
+#define LLVM_TARGET(target) \
+ array_up->AddItem(llvm::make_unique<StructuredData::String>(#target));
+#include "llvm/Config/Targets.def"
+ auto entry_up = llvm::make_unique<StructuredData::Dictionary>();
+ entry_up->AddItem("value", std::move(array_up));
+ entry_up->AddStringItem("description", "A list of configured LLVM targets.");
+ dict.AddItem("targets", std::move(entry_up));
+}
+
+SBStructuredData SBDebugger::GetBuildConfiguration() {
+ auto config_up = llvm::make_unique<StructuredData::Dictionary>();
+ AddBoolConfigEntry(
+ *config_up, "xml", XMLDocument::XMLEnabled(),
+ "A boolean value that indicates if XML support is enabled in LLDB");
+ AddLLVMTargets(*config_up);
+
+ SBStructuredData data;
+ data.m_impl_up->SetObjectSP(std::move(config_up));
+ return data;
+}
+
bool SBDebugger::StateIsRunningState(StateType state) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
diff --git a/contrib/llvm/tools/lldb/source/API/SBEvent.cpp b/contrib/llvm/tools/lldb/source/API/SBEvent.cpp
index 17a16ffd0481..65eb71c09285 100644
--- a/contrib/llvm/tools/lldb/source/API/SBEvent.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBEvent.cpp
@@ -146,8 +146,8 @@ void SBEvent::reset(Event *event_ptr) {
}
bool SBEvent::IsValid() const {
- // Do NOT use m_opaque_ptr directly!!! Must use the SBEvent::get()
- // accessor. See comments in SBEvent::get()....
+ // Do NOT use m_opaque_ptr directly!!! Must use the SBEvent::get() accessor.
+ // See comments in SBEvent::get()....
return SBEvent::get() != NULL;
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBFrame.cpp b/contrib/llvm/tools/lldb/source/API/SBFrame.cpp
index 684a707dda94..5762a75f33d6 100644
--- a/contrib/llvm/tools/lldb/source/API/SBFrame.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBFrame.cpp
@@ -419,7 +419,7 @@ addr_t SBFrame::GetPC() const {
frame = exe_ctx.GetFramePtr();
if (frame) {
addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
- target, eAddressClassCode);
+ target, AddressClass::eCode);
} else {
if (log)
log->Printf("SBFrame::GetPC () => error: could not reconstruct frame "
diff --git a/contrib/llvm/tools/lldb/source/API/SBHostOS.cpp b/contrib/llvm/tools/lldb/source/API/SBHostOS.cpp
index 90b75a6ecd7b..e56951df43be 100644
--- a/contrib/llvm/tools/lldb/source/API/SBHostOS.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBHostOS.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLDB_DISABLE_PYTHON
+#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
+#endif
+
#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBError.h"
#include "lldb/Host/Host.h"
@@ -17,6 +21,11 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "Plugins/ExpressionParser/Clang/ClangHost.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
+#endif
+
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
@@ -30,19 +39,45 @@ SBFileSpec SBHostOS::GetProgramFileSpec() {
}
SBFileSpec SBHostOS::GetLLDBPythonPath() {
- SBFileSpec sb_lldb_python_filespec;
- FileSpec lldb_python_spec;
- if (HostInfo::GetLLDBPath(ePathTypePythonDir, lldb_python_spec)) {
- sb_lldb_python_filespec.SetFileSpec(lldb_python_spec);
- }
- return sb_lldb_python_filespec;
+ return GetLLDBPath(ePathTypePythonDir);
}
SBFileSpec SBHostOS::GetLLDBPath(lldb::PathType path_type) {
- SBFileSpec sb_fspec;
FileSpec fspec;
- if (HostInfo::GetLLDBPath(path_type, fspec))
- sb_fspec.SetFileSpec(fspec);
+ switch (path_type) {
+ case ePathTypeLLDBShlibDir:
+ fspec = HostInfo::GetShlibDir();
+ break;
+ case ePathTypeSupportExecutableDir:
+ fspec = HostInfo::GetSupportExeDir();
+ break;
+ case ePathTypeHeaderDir:
+ fspec = HostInfo::GetHeaderDir();
+ break;
+ case ePathTypePythonDir:
+#ifndef LLDB_DISABLE_PYTHON
+ fspec = ScriptInterpreterPython::GetPythonDir();
+#endif
+ break;
+ case ePathTypeLLDBSystemPlugins:
+ fspec = HostInfo::GetSystemPluginDir();
+ break;
+ case ePathTypeLLDBUserPlugins:
+ fspec = HostInfo::GetUserPluginDir();
+ break;
+ case ePathTypeLLDBTempSystemDir:
+ fspec = HostInfo::GetProcessTempDir();
+ break;
+ case ePathTypeGlobalLLDBTempSystemDir:
+ fspec = HostInfo::GetGlobalTempDir();
+ break;
+ case ePathTypeClangDir:
+ fspec = GetClangResourceDir();
+ break;
+ }
+
+ SBFileSpec sb_fspec;
+ sb_fspec.SetFileSpec(fspec);
return sb_fspec;
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp b/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp
index 1cca8db2afe8..462f08288092 100644
--- a/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp
@@ -27,12 +27,11 @@
#include "lldb/Utility/DataExtractor.h"
//----------------------------------------------------------------------
-// We recently fixed a leak in one of the Instruction subclasses where
-// the instruction will only hold a weak reference to the disassembler
-// to avoid a cycle that was keeping both objects alive (leak) and we
-// need the InstructionImpl class to make sure our public API behaves
-// as users would expect. Calls in our public API allow clients to do
-// things like:
+// We recently fixed a leak in one of the Instruction subclasses where the
+// instruction will only hold a weak reference to the disassembler to avoid a
+// cycle that was keeping both objects alive (leak) and we need the
+// InstructionImpl class to make sure our public API behaves as users would
+// expect. Calls in our public API allow clients to do things like:
//
// 1 lldb::SBInstruction inst;
// 2 inst = target.ReadInstructions(pc, 1).GetInstructionAtIndex(0)
@@ -40,12 +39,12 @@
// 4 ...
//
// There was a temporary lldb::DisassemblerSP object created in the
-// SBInstructionList that was returned by lldb.target.ReadInstructions()
-// that will go away after line 2 but the "inst" object should be able
-// to still answer questions about itself. So we make sure that any
-// SBInstruction objects that are given out have a strong reference to
-// the disassembler and the instruction so that the object can live and
-// successfully respond to all queries.
+// SBInstructionList that was returned by lldb.target.ReadInstructions() that
+// will go away after line 2 but the "inst" object should be able to still
+// answer questions about itself. So we make sure that any SBInstruction
+// objects that are given out have a strong reference to the disassembler and
+// the instruction so that the object can live and successfully respond to all
+// queries.
//----------------------------------------------------------------------
class InstructionImpl {
public:
@@ -275,10 +274,3 @@ bool SBInstruction::TestEmulation(lldb::SBStream &output_stream,
return inst_sp->TestEmulation(output_stream.get(), test_file);
return false;
}
-
-lldb::AddressClass SBInstruction::GetAddressClass() {
- lldb::InstructionSP inst_sp(GetOpaque());
- if (inst_sp)
- return inst_sp->GetAddressClass();
- return eAddressClassInvalid;
-}
diff --git a/contrib/llvm/tools/lldb/source/API/SBInstructionList.cpp b/contrib/llvm/tools/lldb/source/API/SBInstructionList.cpp
index 3edb9eae98c1..29e0c96075fd 100644
--- a/contrib/llvm/tools/lldb/source/API/SBInstructionList.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBInstructionList.cpp
@@ -92,8 +92,8 @@ bool SBInstructionList::GetDescription(lldb::SBStream &description) {
if (m_opaque_sp) {
size_t num_instructions = GetSize();
if (num_instructions) {
- // Call the ref() to make sure a stream is created if one deesn't
- // exist already inside description...
+ // Call the ref() to make sure a stream is created if one deesn't exist
+ // already inside description...
Stream &sref = description.ref();
const uint32_t max_opcode_byte_size =
m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
diff --git a/contrib/llvm/tools/lldb/source/API/SBLaunchInfo.cpp b/contrib/llvm/tools/lldb/source/API/SBLaunchInfo.cpp
index 5f5afccee680..aa1759ab3d00 100644
--- a/contrib/llvm/tools/lldb/source/API/SBLaunchInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBLaunchInfo.cpp
@@ -16,8 +16,26 @@
using namespace lldb;
using namespace lldb_private;
+class lldb_private::SBLaunchInfoImpl : public ProcessLaunchInfo {
+public:
+ SBLaunchInfoImpl()
+ : ProcessLaunchInfo(), m_envp(GetEnvironment().getEnvp()) {}
+
+ const char *const *GetEnvp() const { return m_envp; }
+ void RegenerateEnvp() { m_envp = GetEnvironment().getEnvp(); }
+
+ SBLaunchInfoImpl &operator=(const ProcessLaunchInfo &rhs) {
+ ProcessLaunchInfo::operator=(rhs);
+ RegenerateEnvp();
+ return *this;
+ }
+
+private:
+ Environment::Envp m_envp;
+};
+
SBLaunchInfo::SBLaunchInfo(const char **argv)
- : m_opaque_sp(new ProcessLaunchInfo()) {
+ : m_opaque_sp(new SBLaunchInfoImpl()) {
m_opaque_sp->GetFlags().Reset(eLaunchFlagDebug | eLaunchFlagDisableASLR);
if (argv && argv[0])
m_opaque_sp->GetArguments().SetArguments(argv);
@@ -25,12 +43,14 @@ SBLaunchInfo::SBLaunchInfo(const char **argv)
SBLaunchInfo::~SBLaunchInfo() {}
-lldb_private::ProcessLaunchInfo &SBLaunchInfo::ref() { return *m_opaque_sp; }
-
const lldb_private::ProcessLaunchInfo &SBLaunchInfo::ref() const {
return *m_opaque_sp;
}
+void SBLaunchInfo::set_ref(const ProcessLaunchInfo &info) {
+ *m_opaque_sp = info;
+}
+
lldb::pid_t SBLaunchInfo::GetProcessID() { return m_opaque_sp->GetProcessID(); }
uint32_t SBLaunchInfo::GetUserID() { return m_opaque_sp->GetUserID(); }
@@ -83,23 +103,22 @@ void SBLaunchInfo::SetArguments(const char **argv, bool append) {
}
uint32_t SBLaunchInfo::GetNumEnvironmentEntries() {
- return m_opaque_sp->GetEnvironmentEntries().GetArgumentCount();
+ return m_opaque_sp->GetEnvironment().size();
}
const char *SBLaunchInfo::GetEnvironmentEntryAtIndex(uint32_t idx) {
- return m_opaque_sp->GetEnvironmentEntries().GetArgumentAtIndex(idx);
+ if (idx > GetNumEnvironmentEntries())
+ return nullptr;
+ return m_opaque_sp->GetEnvp()[idx];
}
void SBLaunchInfo::SetEnvironmentEntries(const char **envp, bool append) {
- if (append) {
- if (envp)
- m_opaque_sp->GetEnvironmentEntries().AppendArguments(envp);
- } else {
- if (envp)
- m_opaque_sp->GetEnvironmentEntries().SetArguments(envp);
- else
- m_opaque_sp->GetEnvironmentEntries().Clear();
- }
+ Environment env(envp);
+ if (append)
+ m_opaque_sp->GetEnvironment().insert(env.begin(), env.end());
+ else
+ m_opaque_sp->GetEnvironment() = env;
+ m_opaque_sp->RegenerateEnvp();
}
void SBLaunchInfo::Clear() { m_opaque_sp->Clear(); }
@@ -129,8 +148,8 @@ void SBLaunchInfo::SetProcessPluginName(const char *plugin_name) {
}
const char *SBLaunchInfo::GetShell() {
- // Constify this string so that it is saved in the string pool. Otherwise
- // it would be freed when this function goes out of scope.
+ // Constify this string so that it is saved in the string pool. Otherwise it
+ // would be freed when this function goes out of scope.
ConstString shell(m_opaque_sp->GetShell().GetPath().c_str());
return shell.AsCString();
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBModule.cpp b/contrib/llvm/tools/lldb/source/API/SBModule.cpp
index 17f3dcc5656d..3dd99d5321b4 100644
--- a/contrib/llvm/tools/lldb/source/API/SBModule.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBModule.cpp
@@ -144,7 +144,7 @@ const uint8_t *SBModule::GetUUIDBytes() const {
const uint8_t *uuid_bytes = NULL;
ModuleSP module_sp(GetSP());
if (module_sp)
- uuid_bytes = (const uint8_t *)module_sp->GetUUID().GetBytes();
+ uuid_bytes = module_sp->GetUUID().GetBytes().data();
if (log) {
if (uuid_bytes) {
@@ -165,11 +165,10 @@ const char *SBModule::GetUUIDString() const {
const char *uuid_cstr = NULL;
ModuleSP module_sp(GetSP());
if (module_sp) {
- // We are going to return a "const char *" value through the public
- // API, so we need to constify it so it gets added permanently the
- // string pool and then we don't need to worry about the lifetime of the
- // string as it will never go away once it has been put into the ConstString
- // string pool
+ // We are going to return a "const char *" value through the public API, so
+ // we need to constify it so it gets added permanently the string pool and
+ // then we don't need to worry about the lifetime of the string as it will
+ // never go away once it has been put into the ConstString string pool
uuid_cstr = ConstString(module_sp->GetUUID().GetAsString()).GetCString();
}
@@ -254,6 +253,17 @@ SBCompileUnit SBModule::GetCompileUnitAtIndex(uint32_t index) {
return sb_cu;
}
+SBSymbolContextList
+SBModule::FindCompileUnits(const SBFileSpec &sb_file_spec) {
+ SBSymbolContextList sb_sc_list;
+ const ModuleSP module_sp(GetSP());
+ if (sb_file_spec.IsValid() && module_sp) {
+ const bool append = true;
+ module_sp->FindCompileUnits(*sb_file_spec, append, *sb_sc_list);
+ }
+ return sb_sc_list;
+}
+
static Symtab *GetUnifiedSymbolTable(const lldb::ModuleSP &module_sp) {
if (module_sp) {
SymbolVendor *symbols = module_sp->GetSymbolVendor();
@@ -368,7 +378,7 @@ SBValueList SBModule::FindGlobalVariables(SBTarget &target, const char *name,
if (name && module_sp) {
VariableList variable_list;
const uint32_t match_count = module_sp->FindGlobalVariables(
- ConstString(name), NULL, false, max_matches, variable_list);
+ ConstString(name), NULL, max_matches, variable_list);
if (match_count > 0) {
for (uint32_t i = 0; i < match_count; ++i) {
@@ -515,9 +525,9 @@ const char *SBModule::GetTriple() {
ModuleSP module_sp(GetSP());
if (module_sp) {
std::string triple(module_sp->GetArchitecture().GetTriple().str());
- // Unique the string so we don't run into ownership issues since
- // the const strings put the string into the string pool once and
- // the strings never comes out
+ // Unique the string so we don't run into ownership issues since the const
+ // strings put the string into the string pool once and the strings never
+ // comes out
ConstString const_triple(triple.c_str());
return const_triple.GetCString();
}
@@ -532,16 +542,29 @@ uint32_t SBModule::GetAddressByteSize() {
}
uint32_t SBModule::GetVersion(uint32_t *versions, uint32_t num_versions) {
- ModuleSP module_sp(GetSP());
- if (module_sp)
- return module_sp->GetVersion(versions, num_versions);
- else {
- if (versions && num_versions) {
- for (uint32_t i = 0; i < num_versions; ++i)
- versions[i] = UINT32_MAX;
- }
- return 0;
- }
+ llvm::VersionTuple version;
+ if (ModuleSP module_sp = GetSP())
+ version = module_sp->GetVersion();
+ uint32_t result = 0;
+ if (!version.empty())
+ ++result;
+ if (version.getMinor())
+ ++result;
+ if(version.getSubminor())
+ ++result;
+
+ if (!versions)
+ return result;
+
+ if (num_versions > 0)
+ versions[0] = version.empty() ? UINT32_MAX : version.getMajor();
+ if (num_versions > 1)
+ versions[1] = version.getMinor().getValueOr(UINT32_MAX);
+ if (num_versions > 2)
+ versions[2] = version.getSubminor().getValueOr(UINT32_MAX);
+ for (uint32_t i = 3; i < num_versions; ++i)
+ versions[i] = UINT32_MAX;
+ return result;
}
lldb::SBFileSpec SBModule::GetSymbolFileSpec() const {
diff --git a/contrib/llvm/tools/lldb/source/API/SBModuleSpec.cpp b/contrib/llvm/tools/lldb/source/API/SBModuleSpec.cpp
index a1c08865c6a4..afabd9ace2b9 100644
--- a/contrib/llvm/tools/lldb/source/API/SBModuleSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBModuleSpec.cpp
@@ -70,9 +70,9 @@ void SBModuleSpec::SetObjectName(const char *name) {
const char *SBModuleSpec::GetTriple() {
std::string triple(m_opaque_ap->GetArchitecture().GetTriple().str());
- // Unique the string so we don't run into ownership issues since
- // the const strings put the string into the string pool once and
- // the strings never comes out
+ // Unique the string so we don't run into ownership issues since the const
+ // strings put the string into the string pool once and the strings never
+ // comes out
ConstString const_triple(triple.c_str());
return const_triple.GetCString();
}
@@ -82,15 +82,16 @@ void SBModuleSpec::SetTriple(const char *triple) {
}
const uint8_t *SBModuleSpec::GetUUIDBytes() {
- return (const uint8_t *)m_opaque_ap->GetUUID().GetBytes();
+ return m_opaque_ap->GetUUID().GetBytes().data();
}
size_t SBModuleSpec::GetUUIDLength() {
- return m_opaque_ap->GetUUID().GetByteSize();
+ return m_opaque_ap->GetUUID().GetBytes().size();
}
bool SBModuleSpec::SetUUIDBytes(const uint8_t *uuid, size_t uuid_len) {
- return m_opaque_ap->GetUUID().SetBytes(uuid, uuid_len);
+ m_opaque_ap->GetUUID() = UUID::fromOptionalData(uuid, uuid_len);
+ return m_opaque_ap->GetUUID().IsValid();
}
bool SBModuleSpec::GetDescription(lldb::SBStream &description) {
diff --git a/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp b/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
index 7ec43f13021f..5f29f0033988 100644
--- a/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
@@ -13,10 +13,10 @@
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBUnixSignals.h"
#include "lldb/Host/File.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Status.h"
#include "llvm/Support/FileSystem.h"
@@ -53,8 +53,7 @@ struct PlatformConnectOptions {
//----------------------------------------------------------------------
struct PlatformShellCommand {
PlatformShellCommand(const char *shell_command = NULL)
- : m_command(), m_working_dir(), m_status(0), m_signo(0),
- m_timeout_sec(UINT32_MAX) {
+ : m_command(), m_working_dir(), m_status(0), m_signo(0) {
if (shell_command && shell_command[0])
m_command = shell_command;
}
@@ -66,7 +65,7 @@ struct PlatformShellCommand {
std::string m_output;
int m_status;
int m_signo;
- uint32_t m_timeout_sec;
+ Timeout<std::ratio<1>> m_timeout = llvm::None;
};
//----------------------------------------------------------------------
// SBPlatformConnectOptions
@@ -182,11 +181,16 @@ void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {
}
uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {
- return m_opaque_ptr->m_timeout_sec;
+ if (m_opaque_ptr->m_timeout)
+ return m_opaque_ptr->m_timeout->count();
+ return UINT32_MAX;
}
void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {
- m_opaque_ptr->m_timeout_sec = sec;
+ if (sec == UINT32_MAX)
+ m_opaque_ptr->m_timeout = llvm::None;
+ else
+ m_opaque_ptr->m_timeout = std::chrono::seconds(sec);
}
int SBPlatformShellCommand::GetSignal() { return m_opaque_ptr->m_signo; }
@@ -271,7 +275,7 @@ void SBPlatform::DisconnectRemote() {
bool SBPlatform::IsConnected() {
PlatformSP platform_sp(GetSP());
if (platform_sp)
- platform_sp->IsConnected();
+ return platform_sp->IsConnected();
return false;
}
@@ -326,27 +330,24 @@ const char *SBPlatform::GetHostname() {
}
uint32_t SBPlatform::GetOSMajorVersion() {
- uint32_t major, minor, update;
- PlatformSP platform_sp(GetSP());
- if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
- return major;
- return UINT32_MAX;
+ llvm::VersionTuple version;
+ if (PlatformSP platform_sp = GetSP())
+ version = platform_sp->GetOSVersion();
+ return version.empty() ? UINT32_MAX : version.getMajor();
}
uint32_t SBPlatform::GetOSMinorVersion() {
- uint32_t major, minor, update;
- PlatformSP platform_sp(GetSP());
- if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
- return minor;
- return UINT32_MAX;
+ llvm::VersionTuple version;
+ if (PlatformSP platform_sp = GetSP())
+ version = platform_sp->GetOSVersion();
+ return version.getMinor().getValueOr(UINT32_MAX);
}
uint32_t SBPlatform::GetOSUpdateVersion() {
- uint32_t major, minor, update;
- PlatformSP platform_sp(GetSP());
- if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
- return update;
- return UINT32_MAX;
+ llvm::VersionTuple version;
+ if (PlatformSP platform_sp = GetSP())
+ version = platform_sp->GetOSVersion();
+ return version.getSubminor().getValueOr(UINT32_MAX);
}
SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
@@ -405,18 +406,20 @@ SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
if (working_dir)
shell_command.SetWorkingDirectory(working_dir);
}
- return platform_sp->RunShellCommand(
- command, FileSpec{working_dir, false},
- &shell_command.m_opaque_ptr->m_status,
- &shell_command.m_opaque_ptr->m_signo,
- &shell_command.m_opaque_ptr->m_output,
- shell_command.m_opaque_ptr->m_timeout_sec);
+ return platform_sp->RunShellCommand(command, FileSpec{working_dir, false},
+ &shell_command.m_opaque_ptr->m_status,
+ &shell_command.m_opaque_ptr->m_signo,
+ &shell_command.m_opaque_ptr->m_output,
+ shell_command.m_opaque_ptr->m_timeout);
});
}
SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {
return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
- return platform_sp->LaunchProcess(launch_info.ref());
+ ProcessLaunchInfo info = launch_info.ref();
+ Status error = platform_sp->LaunchProcess(info);
+ launch_info.set_ref(info);
+ return error;
});
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBProcess.cpp b/contrib/llvm/tools/lldb/source/API/SBProcess.cpp
index e08a7f4b08e0..4d5ddc86ccf9 100644
--- a/contrib/llvm/tools/lldb/source/API/SBProcess.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBProcess.cpp
@@ -20,13 +20,13 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
@@ -140,7 +140,7 @@ bool SBProcess::RemoteLaunch(char const **argv, char const **envp,
if (argv)
launch_info.GetArguments().AppendArguments(argv);
if (envp)
- launch_info.GetEnvironmentEntries().SetArguments(envp);
+ launch_info.GetEnvironment() = Environment(envp);
error.SetError(process_sp->Launch(launch_info));
} else {
error.SetErrorString("must be in eStateConnected to call RemoteLaunch");
@@ -896,8 +896,7 @@ SBProcess SBProcess::GetProcessFromEvent(const SBEvent &event) {
ProcessSP process_sp =
Process::ProcessEventData::GetProcessFromEvent(event.get());
if (!process_sp) {
- // StructuredData events also know the process they come from.
- // Try that.
+ // StructuredData events also know the process they come from. Try that.
process_sp = EventDataStructuredData::GetProcessFromEvent(event.get());
}
@@ -1188,6 +1187,57 @@ uint32_t SBProcess::LoadImage(const lldb::SBFileSpec &sb_local_image_spec,
return LLDB_INVALID_IMAGE_TOKEN;
}
+uint32_t SBProcess::LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
+ SBStringList &paths,
+ lldb::SBFileSpec &loaded_path,
+ lldb::SBError &error) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ ProcessSP process_sp(GetSP());
+ if (process_sp) {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+ if (log)
+ log->Printf("SBProcess(%p)::LoadImageUsingPaths() => "
+ "calling Platform::LoadImageUsingPaths for: %s",
+ static_cast<void *>(process_sp.get()),
+ image_spec.GetFilename());
+
+ std::lock_guard<std::recursive_mutex> guard(
+ process_sp->GetTarget().GetAPIMutex());
+ PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
+ size_t num_paths = paths.GetSize();
+ std::vector<std::string> paths_vec;
+ paths_vec.reserve(num_paths);
+ for (size_t i = 0; i < num_paths; i++)
+ paths_vec.push_back(paths.GetStringAtIndex(i));
+ FileSpec loaded_spec;
+
+ uint32_t token = platform_sp->LoadImageUsingPaths(process_sp.get(),
+ *image_spec,
+ paths_vec,
+ error.ref(),
+ &loaded_spec);
+ if (token != LLDB_INVALID_IMAGE_TOKEN)
+ loaded_path = loaded_spec;
+ return token;
+ } else {
+ if (log)
+ log->Printf("SBProcess(%p)::LoadImageUsingPaths() => error: "
+ "process is running",
+ static_cast<void *>(process_sp.get()));
+ error.SetErrorString("process is running");
+ }
+ } else {
+ if (log)
+ log->Printf("SBProcess(%p)::LoadImageUsingPaths() => error: "
+ "called with invalid process",
+ static_cast<void *>(process_sp.get()));
+ error.SetErrorString("process is invalid");
+ }
+
+ return LLDB_INVALID_IMAGE_TOKEN;
+}
+
lldb::SBError SBProcess::UnloadImage(uint32_t image_token) {
lldb::SBError sb_error;
ProcessSP process_sp(GetSP());
diff --git a/contrib/llvm/tools/lldb/source/API/SBQueueItem.cpp b/contrib/llvm/tools/lldb/source/API/SBQueueItem.cpp
index 87ba73f9e6d3..aac5844240fb 100644
--- a/contrib/llvm/tools/lldb/source/API/SBQueueItem.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBQueueItem.cpp
@@ -112,8 +112,7 @@ SBThread SBQueueItem::GetExtendedBacktraceThread(const char *type) {
thread_sp = m_queue_item_sp->GetExtendedBacktraceThread(type_const);
if (thread_sp) {
// Save this in the Process' ExtendedThreadList so a strong pointer
- // retains the
- // object
+ // retains the object
process_sp->GetExtendedThreadList().AddThread(thread_sp);
result.SetThread(thread_sp);
if (log) {
diff --git a/contrib/llvm/tools/lldb/source/API/SBStream.cpp b/contrib/llvm/tools/lldb/source/API/SBStream.cpp
index 159ec07e4e02..d1af77a40fa3 100644
--- a/contrib/llvm/tools/lldb/source/API/SBStream.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBStream.cpp
@@ -26,8 +26,8 @@ SBStream::~SBStream() {}
bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); }
-// If this stream is not redirected to a file, it will maintain a local
-// cache for the stream data which can be accessed using this accessor.
+// If this stream is not redirected to a file, it will maintain a local cache
+// for the stream data which can be accessed using this accessor.
const char *SBStream::GetData() {
if (m_is_file || m_opaque_ap.get() == NULL)
return NULL;
@@ -35,9 +35,8 @@ const char *SBStream::GetData() {
return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
}
-// If this stream is not redirected to a file, it will maintain a local
-// cache for the stream output whose length can be accessed using this
-// accessor.
+// If this stream is not redirected to a file, it will maintain a local cache
+// for the stream output whose length can be accessed using this accessor.
size_t SBStream::GetSize() {
if (m_is_file || m_opaque_ap.get() == NULL)
return 0;
diff --git a/contrib/llvm/tools/lldb/source/API/SBTarget.cpp b/contrib/llvm/tools/lldb/source/API/SBTarget.cpp
index 2c1c6bcac71b..550d336906d3 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTarget.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTarget.cpp
@@ -23,6 +23,7 @@
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBSymbolContextList.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
@@ -38,11 +39,11 @@
#include "lldb/Core/STLUtils.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Host/Host.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -58,11 +59,12 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
-#include "../source/Commands/CommandObjectBreakpoint.h"
+#include "Commands/CommandObjectBreakpoint.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
@@ -82,8 +84,8 @@ Status AttachToProcess(ProcessAttachInfo &attach_info, Target &target) {
const auto state = process_sp->GetState();
if (process_sp->IsAlive() && state == eStateConnected) {
// If we are already connected, then we have already specified the
- // listener, so if a valid listener is supplied, we need to error out
- // to let the client know.
+ // listener, so if a valid listener is supplied, we need to error out to
+ // let the client know.
if (attach_info.GetListener())
return Status("process is connected and already has a listener, pass "
"empty listener");
@@ -181,7 +183,31 @@ SBDebugger SBTarget::GetDebugger() const {
return debugger;
}
+SBStructuredData SBTarget::GetStatistics() {
+ SBStructuredData data;
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return data;
+
+ auto stats_up = llvm::make_unique<StructuredData::Dictionary>();
+ int i = 0;
+ for (auto &Entry : target_sp->GetStatistics()) {
+ std::string Desc = lldb_private::GetStatDescription(
+ static_cast<lldb_private::StatisticKind>(i));
+ stats_up->AddIntegerItem(Desc, Entry);
+ i += 1;
+ }
+
+ data.m_impl_up->SetObjectSP(std::move(stats_up));
+ return data;
+}
+
SBProcess SBTarget::LoadCore(const char *core_file) {
+ lldb::SBError error; // Ignored
+ return LoadCore(core_file, error);
+}
+
+SBProcess SBTarget::LoadCore(const char *core_file, lldb::SBError &error) {
SBProcess sb_process;
TargetSP target_sp(GetSP());
if (target_sp) {
@@ -189,9 +215,14 @@ SBProcess SBTarget::LoadCore(const char *core_file) {
ProcessSP process_sp(target_sp->CreateProcess(
target_sp->GetDebugger().GetListener(), "", &filespec));
if (process_sp) {
- process_sp->LoadCore();
- sb_process.SetSP(process_sp);
+ error.SetError(process_sp->LoadCore());
+ if (error.Success())
+ sb_process.SetSP(process_sp);
+ } else {
+ error.SetErrorString("Failed to create the process");
}
+ } else {
+ error.SetErrorString("SBTarget is invalid");
}
return sb_process;
}
@@ -267,8 +298,8 @@ SBProcess SBTarget::Launch(SBListener &listener, char const **argv,
if (state == eStateConnected) {
// If we are already connected, then we have already specified the
- // listener, so if a valid listener is supplied, we need to error out
- // to let the client know.
+ // listener, so if a valid listener is supplied, we need to error out to
+ // let the client know.
if (listener.IsValid()) {
error.SetErrorString("process is connected and already has a listener, "
"pass empty listener");
@@ -290,7 +321,7 @@ SBProcess SBTarget::Launch(SBListener &listener, char const **argv,
if (argv)
launch_info.GetArguments().AppendArguments(argv);
if (envp)
- launch_info.GetEnvironmentEntries().SetArguments(envp);
+ launch_info.GetEnvironment() = Environment(envp);
if (listener.IsValid())
launch_info.SetListener(listener.GetSP());
@@ -340,7 +371,7 @@ SBProcess SBTarget::Launch(SBLaunchInfo &sb_launch_info, SBError &error) {
}
}
- lldb_private::ProcessLaunchInfo &launch_info = sb_launch_info.ref();
+ lldb_private::ProcessLaunchInfo launch_info = sb_launch_info.ref();
if (!launch_info.GetExecutableFile()) {
Module *exe_module = target_sp->GetExecutableModulePointer();
@@ -353,6 +384,7 @@ SBProcess SBTarget::Launch(SBLaunchInfo &sb_launch_info, SBError &error) {
launch_info.GetArchitecture() = arch_spec;
error.SetError(target_sp->Launch(launch_info, NULL));
+ sb_launch_info.set_ref(launch_info);
sb_process.SetSP(target_sp->GetProcessSP());
} else {
error.SetErrorString("SBTarget is invalid");
@@ -469,7 +501,8 @@ lldb::SBProcess SBTarget::AttachToProcessWithName(
if (name && target_sp) {
ProcessAttachInfo attach_info;
- attach_info.GetExecutableFile().SetFile(name, false);
+ attach_info.GetExecutableFile().SetFile(name, false,
+ FileSpec::Style::native);
attach_info.SetWaitForLaunch(wait_for);
if (listener.IsValid())
attach_info.SetListener(listener.GetSP());
@@ -1436,10 +1469,10 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
if (target_sp) {
ModuleSpec module_spec;
if (path)
- module_spec.GetFileSpec().SetFile(path, false);
+ module_spec.GetFileSpec().SetFile(path, false, FileSpec::Style::native);
if (uuid_cstr)
- module_spec.GetUUID().SetFromCString(uuid_cstr);
+ module_spec.GetUUID().SetFromStringRef(uuid_cstr);
if (triple)
module_spec.GetArchitecture() = Platform::GetAugmentedArchSpec(
@@ -1448,7 +1481,8 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
module_spec.GetArchitecture() = target_sp->GetArchitecture();
if (symfile)
- module_spec.GetSymbolFileSpec().SetFile(symfile, false);
+ module_spec.GetSymbolFileSpec().SetFile(symfile, false,
+ FileSpec::Style::native);
sb_module.SetSP(target_sp->GetSharedModule(module_spec));
}
@@ -1510,6 +1544,18 @@ SBModule SBTarget::FindModule(const SBFileSpec &sb_file_spec) {
return sb_module;
}
+SBSymbolContextList
+SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) {
+ SBSymbolContextList sb_sc_list;
+ const TargetSP target_sp(GetSP());
+ if (target_sp && sb_file_spec.IsValid()) {
+ const bool append = true;
+ target_sp->GetImages().FindCompileUnits(*sb_file_spec,
+ append, *sb_sc_list);
+ }
+ return sb_sc_list;
+}
+
lldb::ByteOrder SBTarget::GetByteOrder() {
TargetSP target_sp(GetSP());
if (target_sp)
@@ -1521,9 +1567,9 @@ const char *SBTarget::GetTriple() {
TargetSP target_sp(GetSP());
if (target_sp) {
std::string triple(target_sp->GetArchitecture().GetTriple().str());
- // Unique the string so we don't run into ownership issues since
- // the const strings put the string into the string pool once and
- // the strings never comes out
+ // Unique the string so we don't run into ownership issues since the const
+ // strings put the string into the string pool once and the strings never
+ // comes out
ConstString const_triple(triple.c_str());
return const_triple.GetCString();
}
@@ -1673,8 +1719,8 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) {
}
}
- // Didn't find the type in the symbols; try the Objective-C runtime
- // if one is installed
+ // Didn't find the type in the symbols; try the Objective-C runtime if one
+ // is installed
ProcessSP process_sp(target_sp->GetProcessSP());
@@ -1782,9 +1828,8 @@ SBValueList SBTarget::FindGlobalVariables(const char *name,
TargetSP target_sp(GetSP());
if (name && target_sp) {
VariableList variable_list;
- const bool append = true;
const uint32_t match_count = target_sp->GetImages().FindGlobalVariables(
- ConstString(name), append, max_matches, variable_list);
+ ConstString(name), max_matches, variable_list);
if (match_count > 0) {
ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
@@ -1811,23 +1856,22 @@ SBValueList SBTarget::FindGlobalVariables(const char *name,
if (name && target_sp) {
llvm::StringRef name_ref(name);
VariableList variable_list;
- const bool append = true;
std::string regexstr;
uint32_t match_count;
switch (matchtype) {
case eMatchTypeNormal:
match_count = target_sp->GetImages().FindGlobalVariables(
- ConstString(name), append, max_matches, variable_list);
+ ConstString(name), max_matches, variable_list);
break;
case eMatchTypeRegex:
match_count = target_sp->GetImages().FindGlobalVariables(
- RegularExpression(name_ref), append, max_matches, variable_list);
+ RegularExpression(name_ref), max_matches, variable_list);
break;
case eMatchTypeStartsWith:
regexstr = llvm::Regex::escape(name) + ".*";
match_count = target_sp->GetImages().FindGlobalVariables(
- RegularExpression(regexstr), append, max_matches, variable_list);
+ RegularExpression(regexstr), max_matches, variable_list);
break;
}
@@ -2195,7 +2239,7 @@ lldb::SBLaunchInfo SBTarget::GetLaunchInfo() const {
lldb::SBLaunchInfo launch_info(NULL);
TargetSP target_sp(GetSP());
if (target_sp)
- launch_info.ref() = m_opaque_sp->GetProcessLaunchInfo();
+ launch_info.set_ref(m_opaque_sp->GetProcessLaunchInfo());
return launch_info;
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBThread.cpp b/contrib/llvm/tools/lldb/source/API/SBThread.cpp
index b34489603c8a..0d25b85f57d2 100644
--- a/contrib/llvm/tools/lldb/source/API/SBThread.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBThread.cpp
@@ -615,8 +615,7 @@ SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
}
// User level plans should be Master Plans so they can be interrupted, other
- // plans executed, and
- // then a "continue" will resume the plan.
+ // plans executed, and then a "continue" will resume the plan.
if (new_plan != NULL) {
new_plan->SetIsMasterPlan(true);
new_plan->SetOkayToDiscard(false);
@@ -634,6 +633,11 @@ SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
}
void SBThread::StepOver(lldb::RunMode stop_other_threads) {
+ SBError error; // Ignored
+ StepOver(stop_other_threads, error);
+}
+
+void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
@@ -644,28 +648,29 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads) {
static_cast<void *>(exe_ctx.GetThreadPtr()),
Thread::RunModeAsCString(stop_other_threads));
- if (exe_ctx.HasThreadScope()) {
- Thread *thread = exe_ctx.GetThreadPtr();
- bool abort_other_plans = false;
- StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
-
- ThreadPlanSP new_plan_sp;
- if (frame_sp) {
- if (frame_sp->HasDebugInformation()) {
- const LazyBool avoid_no_debug = eLazyBoolCalculate;
- SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
- new_plan_sp = thread->QueueThreadPlanForStepOverRange(
- abort_other_plans, sc.line_entry, sc, stop_other_threads,
- avoid_no_debug);
- } else {
- new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, stop_other_threads);
- }
- }
+ if (!exe_ctx.HasThreadScope()) {
+ error.SetErrorString("this SBThread object is invalid");
+ return;
+ }
+
+ Thread *thread = exe_ctx.GetThreadPtr();
+ bool abort_other_plans = false;
+ StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
- // This returns an error, we should use it!
- ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ ThreadPlanSP new_plan_sp;
+ if (frame_sp) {
+ if (frame_sp->HasDebugInformation()) {
+ const LazyBool avoid_no_debug = eLazyBoolCalculate;
+ SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+ new_plan_sp = thread->QueueThreadPlanForStepOverRange(
+ abort_other_plans, sc.line_entry, sc, stop_other_threads,
+ avoid_no_debug);
+ } else {
+ new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
+ true, abort_other_plans, stop_other_threads);
+ }
}
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
void SBThread::StepInto(lldb::RunMode stop_other_threads) {
@@ -674,7 +679,7 @@ void SBThread::StepInto(lldb::RunMode stop_other_threads) {
void SBThread::StepInto(const char *target_name,
lldb::RunMode stop_other_threads) {
- SBError error;
+ SBError error; // Ignored
StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
}
@@ -692,41 +697,48 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line,
target_name ? target_name : "<NULL>",
Thread::RunModeAsCString(stop_other_threads));
- if (exe_ctx.HasThreadScope()) {
- bool abort_other_plans = false;
+ if (!exe_ctx.HasThreadScope()) {
+ error.SetErrorString("this SBThread object is invalid");
+ return;
+ }
- Thread *thread = exe_ctx.GetThreadPtr();
- StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
- ThreadPlanSP new_plan_sp;
+ bool abort_other_plans = false;
- if (frame_sp && frame_sp->HasDebugInformation()) {
- SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
- AddressRange range;
- if (end_line == LLDB_INVALID_LINE_NUMBER)
- range = sc.line_entry.range;
- else {
- if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
- return;
- }
-
- const LazyBool step_out_avoids_code_without_debug_info =
- eLazyBoolCalculate;
- const LazyBool step_in_avoids_code_without_debug_info =
- eLazyBoolCalculate;
- new_plan_sp = thread->QueueThreadPlanForStepInRange(
- abort_other_plans, range, sc, target_name, stop_other_threads,
- step_in_avoids_code_without_debug_info,
- step_out_avoids_code_without_debug_info);
- } else {
- new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, stop_other_threads);
+ Thread *thread = exe_ctx.GetThreadPtr();
+ StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
+ ThreadPlanSP new_plan_sp;
+
+ if (frame_sp && frame_sp->HasDebugInformation()) {
+ SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+ AddressRange range;
+ if (end_line == LLDB_INVALID_LINE_NUMBER)
+ range = sc.line_entry.range;
+ else {
+ if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
+ return;
}
- error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ const LazyBool step_out_avoids_code_without_debug_info =
+ eLazyBoolCalculate;
+ const LazyBool step_in_avoids_code_without_debug_info =
+ eLazyBoolCalculate;
+ new_plan_sp = thread->QueueThreadPlanForStepInRange(
+ abort_other_plans, range, sc, target_name, stop_other_threads,
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info);
+ } else {
+ new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
+ false, abort_other_plans, stop_other_threads);
}
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
void SBThread::StepOut() {
+ SBError error; // Ignored
+ StepOut(error);
+}
+
+void SBThread::StepOut(SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
@@ -736,23 +748,30 @@ void SBThread::StepOut() {
log->Printf("SBThread(%p)::StepOut ()",
static_cast<void *>(exe_ctx.GetThreadPtr()));
- if (exe_ctx.HasThreadScope()) {
- bool abort_other_plans = false;
- bool stop_other_threads = false;
+ if (!exe_ctx.HasThreadScope()) {
+ error.SetErrorString("this SBThread object is invalid");
+ return;
+ }
- Thread *thread = exe_ctx.GetThreadPtr();
+ bool abort_other_plans = false;
+ bool stop_other_threads = false;
+
+ Thread *thread = exe_ctx.GetThreadPtr();
- const LazyBool avoid_no_debug = eLazyBoolCalculate;
- ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
- abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
- eVoteNoOpinion, 0, avoid_no_debug));
+ const LazyBool avoid_no_debug = eLazyBoolCalculate;
+ ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
+ abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
+ eVoteNoOpinion, 0, avoid_no_debug));
- // This returns an error, we should use it!
- ResumeNewPlan(exe_ctx, new_plan_sp.get());
- }
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
-void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
+void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
+ SBError error; // Ignored
+ StepOutOfFrame(sb_frame, error);
+}
+
+void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
@@ -763,6 +782,7 @@ void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
log->Printf(
"SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
static_cast<void *>(exe_ctx.GetThreadPtr()));
+ error.SetErrorString("passed invalid SBFrame object");
return;
}
@@ -775,27 +795,36 @@ void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
}
- if (exe_ctx.HasThreadScope()) {
- bool abort_other_plans = false;
- bool stop_other_threads = false;
- Thread *thread = exe_ctx.GetThreadPtr();
- if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
- log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another "
- "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
- static_cast<void *>(exe_ctx.GetThreadPtr()),
- sb_frame.GetThread().GetThreadID(), thread->GetID());
- }
-
- ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
- abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
- eVoteNoOpinion, frame_sp->GetFrameIndex()));
+ if (!exe_ctx.HasThreadScope()) {
+ error.SetErrorString("this SBThread object is invalid");
+ return;
+ }
- // This returns an error, we should use it!
- ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ bool abort_other_plans = false;
+ bool stop_other_threads = false;
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
+ log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another "
+ "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
+ static_cast<void *>(exe_ctx.GetThreadPtr()),
+ sb_frame.GetThread().GetThreadID(), thread->GetID());
+ error.SetErrorString("passed a frame from another thread");
+ return;
}
+
+ ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
+ abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
+ eVoteNoOpinion, frame_sp->GetFrameIndex()));
+
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
void SBThread::StepInstruction(bool step_over) {
+ SBError error; // Ignored
+ StepInstruction(step_over, error);
+}
+
+void SBThread::StepInstruction(bool step_over, SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
@@ -805,17 +834,24 @@ void SBThread::StepInstruction(bool step_over) {
log->Printf("SBThread(%p)::StepInstruction (step_over=%i)",
static_cast<void *>(exe_ctx.GetThreadPtr()), step_over);
- if (exe_ctx.HasThreadScope()) {
- Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP new_plan_sp(
- thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true));
-
- // This returns an error, we should use it!
- ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ if (!exe_ctx.HasThreadScope()) {
+ error.SetErrorString("this SBThread object is invalid");
+ return;
}
+
+ Thread *thread = exe_ctx.GetThreadPtr();
+ ThreadPlanSP new_plan_sp(
+ thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true));
+
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
void SBThread::RunToAddress(lldb::addr_t addr) {
+ SBError error; // Ignored
+ RunToAddress(addr, error);
+}
+
+void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
@@ -825,20 +861,22 @@ void SBThread::RunToAddress(lldb::addr_t addr) {
log->Printf("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
static_cast<void *>(exe_ctx.GetThreadPtr()), addr);
- if (exe_ctx.HasThreadScope()) {
- bool abort_other_plans = false;
- bool stop_other_threads = true;
+ if (!exe_ctx.HasThreadScope()) {
+ error.SetErrorString("this SBThread object is invalid");
+ return;
+ }
- Address target_addr(addr);
+ bool abort_other_plans = false;
+ bool stop_other_threads = true;
- Thread *thread = exe_ctx.GetThreadPtr();
+ Address target_addr(addr);
+
+ Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
- abort_other_plans, target_addr, stop_other_threads));
+ ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
+ abort_other_plans, target_addr, stop_other_threads));
- // This returns an error, we should use it!
- ResumeNewPlan(exe_ctx, new_plan_sp.get());
- }
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
}
SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
@@ -911,8 +949,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
// Grab the current function, then we will make sure the "until" address is
// within the function. We discard addresses that are out of the current
// function, and then if there are no addresses remaining, give an
- // appropriate
- // error message.
+ // appropriate error message.
bool all_in_function = true;
AddressRange fun_range = frame_sc.function->GetAddressRange();
@@ -1084,6 +1121,11 @@ SBError SBThread::UnwindInnermostExpression() {
}
bool SBThread::Suspend() {
+ SBError error; // Ignored
+ return Suspend(error);
+}
+
+bool SBThread::Suspend(SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
@@ -1095,11 +1137,13 @@ bool SBThread::Suspend() {
exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
result = true;
} else {
+ error.SetErrorString("process is running");
if (log)
log->Printf("SBThread(%p)::Suspend() => error: process is running",
static_cast<void *>(exe_ctx.GetThreadPtr()));
}
- }
+ } else
+ error.SetErrorString("this SBThread object is invalid");
if (log)
log->Printf("SBThread(%p)::Suspend() => %i",
static_cast<void *>(exe_ctx.GetThreadPtr()), result);
@@ -1107,6 +1151,11 @@ bool SBThread::Suspend() {
}
bool SBThread::Resume() {
+ SBError error; // Ignored
+ return Resume(error);
+}
+
+bool SBThread::Resume(SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
std::unique_lock<std::recursive_mutex> lock;
ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
@@ -1119,11 +1168,13 @@ bool SBThread::Resume() {
exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
result = true;
} else {
+ error.SetErrorString("process is running");
if (log)
log->Printf("SBThread(%p)::Resume() => error: process is running",
static_cast<void *>(exe_ctx.GetThreadPtr()));
}
- }
+ } else
+ error.SetErrorString("this SBThread object is invalid");
if (log)
log->Printf("SBThread(%p)::Resume() => %i",
static_cast<void *>(exe_ctx.GetThreadPtr()), result);
@@ -1374,8 +1425,7 @@ SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
runtime->GetExtendedBacktraceThread(real_thread, type_const));
if (new_thread_sp) {
// Save this in the Process' ExtendedThreadList so a strong
- // pointer retains the
- // object.
+ // pointer retains the object.
process->GetExtendedThreadList().AddThread(new_thread_sp);
sb_origin_thread.SetThread(new_thread_sp);
if (log) {
diff --git a/contrib/llvm/tools/lldb/source/API/SBThreadPlan.cpp b/contrib/llvm/tools/lldb/source/API/SBThreadPlan.cpp
index a19023f66de2..131f84195908 100644
--- a/contrib/llvm/tools/lldb/source/API/SBThreadPlan.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBThreadPlan.cpp
@@ -138,8 +138,7 @@ bool SBThreadPlan::IsValid() {
// plans...
//
// FIXME, you should only be able to queue thread plans from inside the methods
-// of a
-// Scripted Thread Plan. Need a way to enforce that.
+// of a Scripted Thread Plan. Need a way to enforce that.
SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address,
diff --git a/contrib/llvm/tools/lldb/source/API/SBType.cpp b/contrib/llvm/tools/lldb/source/API/SBType.cpp
index 80d48754c89b..e199b7a33e48 100644
--- a/contrib/llvm/tools/lldb/source/API/SBType.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBType.cpp
@@ -88,9 +88,9 @@ TypeImpl &SBType::ref() {
}
const TypeImpl &SBType::ref() const {
- // "const SBAddress &addr" should already have checked "addr.IsValid()"
- // prior to calling this function. In case you didn't we will assert
- // and die to let you know.
+ // "const SBAddress &addr" should already have checked "addr.IsValid()" prior
+ // to calling this function. In case you didn't we will assert and die to let
+ // you know.
assert(m_opaque_sp.get());
return *m_opaque_sp;
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp b/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp
index 38e7cca35dfd..30414bd728cb 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp
@@ -341,9 +341,9 @@ bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name,
// FIXME: we need to iterate over all the Debugger objects and have each of
// them contain a copy of the function
// since we currently have formatters live in a global space, while Python
- // code lives in a specific Debugger-related environment
- // this should eventually be fixed by deciding a final location in the LLDB
- // object space for formatters
+ // code lives in a specific Debugger-related environment this should
+ // eventually be fixed by deciding a final location in the LLDB object space
+ // for formatters
if (summary.IsFunctionCode()) {
const void *name_token =
(const void *)ConstString(type_name.GetName()).GetCString();
@@ -453,9 +453,9 @@ bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name,
// FIXME: we need to iterate over all the Debugger objects and have each of
// them contain a copy of the function
// since we currently have formatters live in a global space, while Python
- // code lives in a specific Debugger-related environment
- // this should eventually be fixed by deciding a final location in the LLDB
- // object space for formatters
+ // code lives in a specific Debugger-related environment this should
+ // eventually be fixed by deciding a final location in the LLDB object space
+ // for formatters
if (synth.IsClassCode()) {
const void *name_token =
(const void *)ConstString(type_name.GetName()).GetCString();
diff --git a/contrib/llvm/tools/lldb/source/API/SBValue.cpp b/contrib/llvm/tools/lldb/source/API/SBValue.cpp
index b6f044c61a78..a270c0471e9f 100644
--- a/contrib/llvm/tools/lldb/source/API/SBValue.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBValue.cpp
@@ -89,16 +89,13 @@ public:
// FIXME: This check is necessary but not sufficient. We for sure don't
// want to touch SBValues whose owning
// targets have gone away. This check is a little weak in that it
- // enforces that restriction when you call
- // IsValid, but since IsValid doesn't lock the target, you have no
- // guarantee that the SBValue won't go
- // invalid after you call this...
- // Also, an SBValue could depend on data from one of the modules in the
- // target, and those could go away
- // independently of the target, for instance if a module is unloaded. But
- // right now, neither SBValues
- // nor ValueObjects know which modules they depend on. So I have no good
- // way to make that check without
+ // enforces that restriction when you call IsValid, but since IsValid
+ // doesn't lock the target, you have no guarantee that the SBValue won't
+ // go invalid after you call this... Also, an SBValue could depend on
+ // data from one of the modules in the target, and those could go away
+ // independently of the target, for instance if a module is unloaded.
+ // But right now, neither SBValues nor ValueObjects know which modules
+ // they depend on. So I have no good way to make that check without
// tracking that in all the ValueObject subclasses.
TargetSP target_sp = m_valobj_sp->GetTargetSP();
if (target_sp && target_sp->IsValid())
@@ -129,9 +126,9 @@ public:
ProcessSP process_sp(value_sp->GetProcessSP());
if (process_sp && !stop_locker.TryLock(&process_sp->GetRunLock())) {
- // We don't allow people to play around with ValueObject if the process is
- // running.
- // If you want to look at values, pause the process, then look.
+ // We don't allow people to play around with ValueObject if the process
+ // is running. If you want to look at values, pause the process, then
+ // look.
if (log)
log->Printf("SBValue(%p)::GetSP() => error: process is running",
static_cast<void *>(value_sp.get()));
@@ -171,10 +168,8 @@ public:
// All the derived values that we would make from the m_valobj_sp will share
// the ExecutionContext with m_valobj_sp, so we don't need to do the
- // calculations
- // in GetSP to return the Target, Process, Thread or Frame. It is convenient
- // to
- // provide simple accessors for these, which I do here.
+ // calculations in GetSP to return the Target, Process, Thread or Frame. It
+ // is convenient to provide simple accessors for these, which I do here.
TargetSP GetTargetSP() {
if (m_valobj_sp)
return m_valobj_sp->GetTargetSP();
@@ -242,9 +237,9 @@ SBValue &SBValue::operator=(const SBValue &rhs) {
SBValue::~SBValue() {}
bool SBValue::IsValid() {
- // If this function ever changes to anything that does more than just
- // check if the opaque shared pointer is non NULL, then we need to update
- // all "if (m_opaque_sp)" code in this file.
+ // If this function ever changes to anything that does more than just check
+ // if the opaque shared pointer is non NULL, then we need to update all "if
+ // (m_opaque_sp)" code in this file.
return m_opaque_sp.get() != NULL && m_opaque_sp->IsValid() &&
m_opaque_sp->GetRootSP().get() != NULL;
}
@@ -1397,11 +1392,9 @@ lldb::SBAddress SBValue::GetAddress() {
if (module_sp)
module_sp->ResolveFileAddress(value, addr);
} else if (addr_type == eAddressTypeLoad) {
- // no need to check the return value on this.. if it can actually do the
- // resolve
- // addr will be in the form (section,offset), otherwise it will simply
- // be returned
- // as (NULL, value)
+ // no need to check the return value on this.. if it can actually do
+ // the resolve addr will be in the form (section,offset), otherwise it
+ // will simply be returned as (NULL, value)
addr.SetLoadAddress(value, target_sp.get());
}
}
diff --git a/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp b/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp
index 2ffd8ee5db67..8c4e12ded996 100644
--- a/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp
@@ -11,7 +11,7 @@
#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
#endif
-#include "lldb/API/SystemInitializerFull.h"
+#include "SystemInitializerFull.h"
#include "lldb/API/SBCommandInterpreter.h"
@@ -51,6 +51,7 @@
#endif // LLDB_ENABLE_ALL
#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
#include "Plugins/Architecture/Arm/ArchitectureArm.h"
+#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h"
#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
#ifdef LLDB_ENABLE_ALL
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h"
@@ -62,6 +63,7 @@
#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
#endif // LLDB_ENABLE_ALL
#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
+#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h"
#include "Plugins/InstrumentationRuntime/ASan/ASanRuntime.h"
#include "Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.h"
#ifdef LLDB_ENABLE_ALL
@@ -86,7 +88,10 @@
#include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h"
#endif // LLDB_ENABLE_ALL
#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#ifdef LLDB_ENABLE_ALL
+#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
+#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
#include "Plugins/OperatingSystem/Go/OperatingSystemGo.h"
#include "Plugins/OperatingSystem/Python/OperatingSystemPython.h"
#include "Plugins/Platform/Android/PlatformAndroid.h"
@@ -105,6 +110,7 @@
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
#ifdef LLDB_ENABLE_ALL
+#include "Plugins/Process/mach-core/ProcessMachCore.h"
#include "Plugins/Process/minidump/ProcessMinidump.h"
#endif // LLDB_ENABLE_ALL
#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
@@ -130,7 +136,6 @@
#include "Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h"
#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
#include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h"
-#include "Plugins/Process/mach-core/ProcessMachCore.h"
#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h"
#endif
#ifdef LLDB_ENABLE_ALL
@@ -166,11 +171,10 @@ extern "C" void init_lldb(void);
#define LLDBSwigPyInit init_lldb
#endif
-// these are the Pythonic implementations of the required callbacks
-// these are scripting-language specific, which is why they belong here
-// we still need to use function pointers to them instead of relying
-// on linkage-time resolution because the SWIG stuff and this file
-// get built at different times
+// these are the Pythonic implementations of the required callbacks these are
+// scripting-language specific, which is why they belong here we still need to
+// use function pointers to them instead of relying on linkage-time resolution
+// because the SWIG stuff and this file get built at different times
extern "C" bool LLDBSwigPythonBreakpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &sb_frame,
@@ -280,6 +284,13 @@ SystemInitializerFull::~SystemInitializerFull() {}
void SystemInitializerFull::Initialize() {
SystemInitializerCommon::Initialize();
+
+ ObjectFileELF::Initialize();
+#ifdef LLDB_ENABLE_ALL
+ ObjectFileMachO::Initialize();
+ ObjectFilePECOFF::Initialize();
+#endif // LLDB_ENABLE_ALL
+
ScriptInterpreterNone::Initialize();
#ifndef LLDB_DISABLE_PYTHON
@@ -292,10 +303,9 @@ void SystemInitializerFull::Initialize() {
#if !defined(LLDB_DISABLE_PYTHON)
InitializeSWIG();
- // ScriptInterpreterPython::Initialize() depends on things like HostInfo being
- // initialized
- // so it can compute the python directory etc, so we need to do this after
- // SystemInitializerCommon::Initialize().
+ // ScriptInterpreterPython::Initialize() depends on things like HostInfo
+ // being initialized so it can compute the python directory etc, so we need
+ // to do this after SystemInitializerCommon::Initialize().
ScriptInterpreterPython::Initialize();
#endif
@@ -347,12 +357,14 @@ void SystemInitializerFull::Initialize() {
#endif // LLDB_ENABLE_ALL
ArchitectureArm::Initialize();
+ ArchitecturePPC64::Initialize();
DisassemblerLLVMC::Initialize();
JITLoaderGDB::Initialize();
ProcessElfCore::Initialize();
#ifdef LLDB_ENABLE_ALL
+ ProcessMachCore::Initialize();
minidump::ProcessMinidump::Initialize();
#endif // LLDB_ENABLE_ALL
MemoryHistoryASan::Initialize();
@@ -372,6 +384,7 @@ void SystemInitializerFull::Initialize() {
UnwindAssemblyInstEmulation::Initialize();
UnwindAssembly_x86::Initialize();
EmulateInstructionARM64::Initialize();
+ EmulateInstructionPPC64::Initialize();
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
#ifdef LLDB_ENABLE_ALL
@@ -401,7 +414,6 @@ void SystemInitializerFull::Initialize() {
#if defined(__APPLE__)
SymbolVendorMacOSX::Initialize();
ProcessKDP::Initialize();
- ProcessMachCore::Initialize();
PlatformAppleTVSimulator::Initialize();
PlatformAppleWatchSimulator::Initialize();
PlatformRemoteAppleTV::Initialize();
@@ -409,8 +421,8 @@ void SystemInitializerFull::Initialize() {
DynamicLoaderDarwinKernel::Initialize();
#endif
- // This plugin is valid on any host that talks to a Darwin remote.
- // It shouldn't be limited to __APPLE__.
+ // This plugin is valid on any host that talks to a Darwin remote. It
+ // shouldn't be limited to __APPLE__.
#ifdef LLDB_ENABLE_ALL
StructuredDataDarwinLog::Initialize();
#endif // LLDB_ENABLE_ALL
@@ -434,8 +446,8 @@ void SystemInitializerFull::Initialize() {
// Scan for any system or user LLDB plug-ins
PluginManager::Initialize();
- // The process settings need to know about installed plug-ins, so the Settings
- // must be initialized
+ // The process settings need to know about installed plug-ins, so the
+ // Settings must be initialized
// AFTER PluginManager::Initialize is called.
Debugger::SettingsInitialize();
@@ -501,6 +513,7 @@ void SystemInitializerFull::Terminate() {
JITLoaderGDB::Terminate();
ProcessElfCore::Terminate();
#ifdef LLDB_ENABLE_ALL
+ ProcessMachCore::Terminate();
minidump::ProcessMinidump::Terminate();
#endif // LLDB_ENABLE_ALL
MemoryHistoryASan::Terminate();
@@ -519,6 +532,7 @@ void SystemInitializerFull::Terminate() {
UnwindAssembly_x86::Terminate();
UnwindAssemblyInstEmulation::Terminate();
EmulateInstructionARM64::Terminate();
+ EmulateInstructionPPC64::Terminate();
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
#ifdef LLDB_ENABLE_ALL
@@ -540,7 +554,6 @@ void SystemInitializerFull::Terminate() {
#if defined(__APPLE__)
DynamicLoaderDarwinKernel::Terminate();
- ProcessMachCore::Terminate();
ProcessKDP::Terminate();
SymbolVendorMacOSX::Terminate();
PlatformAppleTVSimulator::Terminate();
@@ -591,6 +604,12 @@ void SystemInitializerFull::Terminate() {
PlatformDarwinKernel::Terminate();
#endif
+ ObjectFileELF::Terminate();
+#ifdef LLDB_ENABLE_ALL
+ ObjectFileMachO::Terminate();
+ ObjectFilePECOFF::Terminate();
+#endif // LLDB_ENABLE_ALL
+
// Now shutdown the common parts, in reverse order.
SystemInitializerCommon::Terminate();
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h b/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.h
index 9cfc6896da61..9cfc6896da61 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h
+++ b/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.h
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp
index 3f6c63e1e5ba..1dc029654bfc 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp
@@ -23,6 +23,7 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
@@ -284,13 +285,13 @@ void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) {
m_locations.RemoveInvalidLocations(arch);
}
-// For each of the overall options we need to decide how they propagate to
-// the location options. This will determine the precedence of options on
-// the breakpoint vs. its locations.
+// For each of the overall options we need to decide how they propagate to the
+// location options. This will determine the precedence of options on the
+// breakpoint vs. its locations.
-// Disable at the breakpoint level should override the location settings.
-// That way you can conveniently turn off a whole breakpoint without messing
-// up the individual settings.
+// Disable at the breakpoint level should override the location settings. That
+// way you can conveniently turn off a whole breakpoint without messing up the
+// individual settings.
void Breakpoint::SetEnabled(bool enable) {
if (enable == m_options_up->IsEnabled())
@@ -330,10 +331,8 @@ bool Breakpoint::IgnoreCountShouldStop() {
uint32_t ignore = GetIgnoreCount();
if (ignore != 0) {
// When we get here we know the location that caused the stop doesn't have
- // an ignore count,
- // since by contract we call it first... So we don't have to find &
- // decrement it, we only have
- // to decrement our own ignore count.
+ // an ignore count, since by contract we call it first... So we don't have
+ // to find & decrement it, we only have to decrement our own ignore count.
DecrementIgnoreCount();
return false;
} else
@@ -430,8 +429,8 @@ const char *Breakpoint::GetConditionText() const {
// This function is used when "baton" doesn't need to be freed
void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,
bool is_synchronous) {
- // The default "Baton" class will keep a copy of "baton" and won't free
- // or delete it when it goes goes out of scope.
+ // The default "Baton" class will keep a copy of "baton" and won't free or
+ // delete it when it goes goes out of scope.
m_options_up->SetCallback(callback, std::make_shared<UntypedBaton>(baton),
is_synchronous);
@@ -477,8 +476,7 @@ void Breakpoint::ResolveBreakpointInModules(ModuleList &module_list,
bool send_event) {
if (m_resolver_sp) {
// If this is not an internal breakpoint, set up to record the new
- // locations, then dispatch
- // an event with the new locations.
+ // locations, then dispatch an event with the new locations.
if (!IsInternal() && send_event) {
BreakpointEventData *new_locations_event = new BreakpointEventData(
eBreakpointEventTypeLocationsAdded, shared_from_this());
@@ -516,8 +514,8 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,
std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
if (load) {
// The logic for handling new modules is:
- // 1) If the filter rejects this module, then skip it.
- // 2) Run through the current location list and if there are any locations
+ // 1) If the filter rejects this module, then skip it. 2) Run through the
+ // current location list and if there are any locations
// for that module, we mark the module as "seen" and we don't try to
// re-resolve
// breakpoint locations for that module.
@@ -527,20 +525,37 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,
ModuleList new_modules; // We'll stuff the "unseen" modules in this list,
// and then resolve
- // them after the locations pass. Have to do it this way because
- // resolving breakpoints will add new locations potentially.
+ // them after the locations pass. Have to do it this way because resolving
+ // breakpoints will add new locations potentially.
for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
bool seen = false;
if (!m_filter_sp->ModulePasses(module_sp))
continue;
+ BreakpointLocationCollection locations_with_no_section;
for (BreakpointLocationSP break_loc_sp :
m_locations.BreakpointLocations()) {
+
+ // If the section for this location was deleted, that means it's Module
+ // has gone away but somebody forgot to tell us. Let's clean it up
+ // here.
+ Address section_addr(break_loc_sp->GetAddress());
+ if (section_addr.SectionWasDeleted()) {
+ locations_with_no_section.Add(break_loc_sp);
+ continue;
+ }
+
if (!break_loc_sp->IsEnabled())
continue;
- SectionSP section_sp(break_loc_sp->GetAddress().GetSection());
- if (!section_sp || section_sp->GetModule() == module_sp) {
+
+ SectionSP section_sp(section_addr.GetSection());
+
+ // If we don't have a Section, that means this location is a raw
+ // address that we haven't resolved to a section yet. So we'll have to
+ // look in all the new modules to resolve this location. Otherwise, if
+ // it was set in this module, re-resolve it here.
+ if (section_sp && section_sp->GetModule() == module_sp) {
if (!seen)
seen = true;
@@ -552,6 +567,11 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,
}
}
}
+
+ size_t num_to_delete = locations_with_no_section.GetSize();
+
+ for (size_t i = 0; i < num_to_delete; i++)
+ m_locations.RemoveLocation(locations_with_no_section.GetByIndex(i));
if (!seen)
new_modules.AppendIfNeeded(module_sp);
@@ -583,10 +603,9 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,
BreakpointLocationSP break_loc_sp(m_locations.GetByIndex(loc_idx));
SectionSP section_sp(break_loc_sp->GetAddress().GetSection());
if (section_sp && section_sp->GetModule() == module_sp) {
- // Remove this breakpoint since the shared library is
- // unloaded, but keep the breakpoint location around
- // so we always get complete hit count and breakpoint
- // lifetime info
+ // Remove this breakpoint since the shared library is unloaded, but
+ // keep the breakpoint location around so we always get complete
+ // hit count and breakpoint lifetime info
break_loc_sp->ClearBreakpointSite();
if (removed_locations_event) {
removed_locations_event->GetBreakpointLocationCollection().Add(
@@ -614,7 +633,8 @@ static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc,
bool equivalent_scs = false;
if (old_sc.module_sp.get() == new_sc.module_sp.get()) {
- // If these come from the same module, we can directly compare the pointers:
+ // If these come from the same module, we can directly compare the
+ // pointers:
if (old_sc.comp_unit && new_sc.comp_unit &&
(old_sc.comp_unit == new_sc.comp_unit)) {
if (old_sc.function && new_sc.function &&
@@ -671,15 +691,13 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
temp_list.Append(new_module_sp);
ResolveBreakpointInModules(temp_list);
} else {
- // First search the new module for locations.
- // Then compare this with the old list, copy over locations that "look the
- // same"
- // Then delete the old locations.
- // Finally remember to post the creation event.
+ // First search the new module for locations. Then compare this with the
+ // old list, copy over locations that "look the same" Then delete the old
+ // locations. Finally remember to post the creation event.
//
- // Two locations are the same if they have the same comp unit & function (by
- // name) and there are the same number
- // of locations in the old function as in the new one.
+ // Two locations are the same if they have the same comp unit & function
+ // (by name) and there are the same number of locations in the old function
+ // as in the new one.
ModuleList temp_list;
temp_list.Append(new_module_sp);
@@ -692,8 +710,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
if (num_new_locations > 0) {
// Break out the case of one location -> one location since that's the
- // most common one, and there's no need
- // to build up the structures needed for the merge in that case.
+ // most common one, and there's no need to build up the structures needed
+ // for the merge in that case.
if (num_new_locations == 1 && num_old_locations == 1) {
bool equivalent_locations = false;
SymbolContext old_sc, new_sc;
@@ -716,8 +734,7 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
}
} else {
// We don't want to have to keep computing the SymbolContexts for these
- // addresses over and over,
- // so lets get them up front:
+ // addresses over and over, so lets get them up front:
typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap;
IDToSCMap old_sc_map;
@@ -740,7 +757,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
lldb::break_id_t old_id = old_sc_map.begin()->first;
SymbolContext &old_sc = old_sc_map.begin()->second;
- // Count the number of entries equivalent to this SC for the old list:
+ // Count the number of entries equivalent to this SC for the old
+ // list:
std::vector<lldb::break_id_t> old_id_vec;
old_id_vec.push_back(old_id);
@@ -760,17 +778,15 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
}
// Alright, if we have the same number of potentially equivalent
- // locations in the old
- // and new modules, we'll just map them one to one in ascending ID
- // order (assuming the
- // resolver's order would match the equivalent ones.
- // Otherwise, we'll dump all the old ones, and just take the new ones,
- // erasing the elements
- // from both maps as we go.
+ // locations in the old and new modules, we'll just map them one to
+ // one in ascending ID order (assuming the resolver's order would
+ // match the equivalent ones. Otherwise, we'll dump all the old ones,
+ // and just take the new ones, erasing the elements from both maps as
+ // we go.
if (old_id_vec.size() == new_id_vec.size()) {
- sort(old_id_vec.begin(), old_id_vec.end());
- sort(new_id_vec.begin(), new_id_vec.end());
+ llvm::sort(old_id_vec.begin(), old_id_vec.end());
+ llvm::sort(new_id_vec.begin(), new_id_vec.end());
size_t num_elements = old_id_vec.size();
for (size_t idx = 0; idx < num_elements; idx++) {
BreakpointLocationSP old_loc_sp =
@@ -798,11 +814,9 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
}
// Now remove the remaining old locations, and cons up a removed locations
- // event.
- // Note, we don't put the new locations that were swapped with an old
- // location on the locations_to_remove
- // list, so we don't need to worry about telling the world about removing a
- // location we didn't tell them
+ // event. Note, we don't put the new locations that were swapped with an
+ // old location on the locations_to_remove list, so we don't need to worry
+ // about telling the world about removing a location we didn't tell them
// about adding.
BreakpointEventData *locations_event;
@@ -838,8 +852,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
void Breakpoint::Dump(Stream *) {}
size_t Breakpoint::GetNumResolvedLocations() const {
- // Return the number of breakpoints that are actually resolved and set
- // down in the inferior process.
+ // Return the number of breakpoints that are actually resolved and set down
+ // in the inferior process.
return m_locations.GetNumResolvedLocations();
}
@@ -866,9 +880,8 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
const size_t num_resolved_locations = GetNumResolvedLocations();
// They just made the breakpoint, they don't need to be told HOW they made
- // it...
- // Also, we'll print the breakpoint number differently depending on whether
- // there is 1 or more locations.
+ // it... Also, we'll print the breakpoint number differently depending on
+ // whether there is 1 or more locations.
if (level != eDescriptionLevelInitial) {
s->Printf("%i: ", GetID());
GetResolverDescription(s);
@@ -885,8 +898,7 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
(uint64_t)num_resolved_locations, GetHitCount());
} else {
// Don't print the pending notification for exception resolvers since we
- // don't generally
- // know how to set them until the target is run.
+ // don't generally know how to set them until the target is run.
if (m_resolver_sp->getResolverID() !=
BreakpointResolver::ExceptionResolver)
s->Printf(", locations = 0 (pending)");
@@ -942,8 +954,7 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
}
// The brief description is just the location name (1.2 or whatever). That's
- // pointless to
- // show in the breakpoint's description, so suppress it.
+ // pointless to show in the breakpoint's description, so suppress it.
if (show_locations && level != lldb::eDescriptionLevelBrief) {
s->IndentMore();
for (size_t i = 0; i < num_locations; ++i) {
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp
index b80106546822..3f72f2052b52 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp
@@ -29,10 +29,9 @@ BreakpointID::~BreakpointID() = default;
static llvm::StringRef g_range_specifiers[] = {"-", "to", "To", "TO"};
// Tells whether or not STR is valid to use between two strings representing
-// breakpoint IDs, to
-// indicate a range of breakpoint IDs. This is broken out into a separate
-// function so that we can
-// easily change or add to the format for specifying ID ranges at a later date.
+// breakpoint IDs, to indicate a range of breakpoint IDs. This is broken out
+// into a separate function so that we can easily change or add to the format
+// for specifying ID ranges at a later date.
bool BreakpointID::IsRangeIdentifier(llvm::StringRef str) {
for (auto spec : g_range_specifiers) {
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp
index 6d610d512f3b..bc4c2a111fd4 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -16,9 +16,9 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -89,14 +89,13 @@ bool BreakpointIDList::FindBreakpointID(const char *bp_id_str,
return FindBreakpointID(*bp_id, position);
}
-void BreakpointIDList::InsertStringArray(const char **string_array,
- size_t array_size,
- CommandReturnObject &result) {
- if (string_array == nullptr)
+void BreakpointIDList::InsertStringArray(
+ llvm::ArrayRef<const char *> string_array, CommandReturnObject &result) {
+ if(string_array.empty())
return;
- for (uint32_t i = 0; i < array_size; ++i) {
- auto bp_id = BreakpointID::ParseCanonicalReference(string_array[i]);
+ for (const char *str : string_array) {
+ auto bp_id = BreakpointID::ParseCanonicalReference(str);
if (bp_id.hasValue())
m_breakpoint_ids.push_back(*bp_id);
}
@@ -237,13 +236,13 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
}
// We have valid range starting & ending breakpoint IDs. Go through all
- // the breakpoints in the target and find all the breakpoints that fit
- // into this range, and add them to new_args.
+ // the breakpoints in the target and find all the breakpoints that fit into
+ // this range, and add them to new_args.
// Next check to see if we have location id's. If so, make sure the
- // start_bp_id and end_bp_id are for the same breakpoint; otherwise we
- // have an illegal range: breakpoint id ranges that specify bp locations
- // are NOT allowed to cross major bp id numbers.
+ // start_bp_id and end_bp_id are for the same breakpoint; otherwise we have
+ // an illegal range: breakpoint id ranges that specify bp locations are NOT
+ // allowed to cross major bp id numbers.
if ((start_loc_id != LLDB_INVALID_BREAK_ID) ||
(end_loc_id != LLDB_INVALID_BREAK_ID)) {
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointList.cpp
index 01ac59f0a903..4a49b1e105ab 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointList.cpp
@@ -99,7 +99,7 @@ void BreakpointList::RemoveAll(bool notify) {
void BreakpointList::RemoveAllowed(bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
+
bp_collection::iterator pos, end = m_breakpoints.end();
if (notify) {
for (pos = m_breakpoints.begin(); pos != end; ++pos) {
@@ -116,10 +116,12 @@ void BreakpointList::RemoveAllowed(bool notify) {
}
pos = m_breakpoints.begin();
while ( pos != end) {
- if((*pos)->AllowDelete())
- pos = m_breakpoints.erase(pos);
- else
- pos++;
+ auto bp = *pos;
+ if (bp->AllowDelete()) {
+ bp->ClearAllBreakpointSites();
+ pos = m_breakpoints.erase(pos);
+ } else
+ pos++;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp
index f59c334fe5c8..932147703304 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -110,8 +110,8 @@ void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
if (thread_id != LLDB_INVALID_THREAD_ID)
GetLocationOptions()->SetThreadID(thread_id);
else {
- // If we're resetting this to an invalid thread id, then
- // don't make an options pointer just to do that.
+ // If we're resetting this to an invalid thread id, then don't make an
+ // options pointer just to do that.
if (m_options_ap.get() != nullptr)
m_options_ap->SetThreadID(thread_id);
}
@@ -132,8 +132,8 @@ void BreakpointLocation::SetThreadIndex(uint32_t index) {
if (index != 0)
GetLocationOptions()->GetThreadSpec()->SetIndex(index);
else {
- // If we're resetting this to an invalid thread id, then
- // don't make an options pointer just to do that.
+ // If we're resetting this to an invalid thread id, then don't make an
+ // options pointer just to do that.
if (m_options_ap.get() != nullptr)
m_options_ap->GetThreadSpec()->SetIndex(index);
}
@@ -154,8 +154,8 @@ void BreakpointLocation::SetThreadName(const char *thread_name) {
if (thread_name != nullptr)
GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
else {
- // If we're resetting this to an invalid thread id, then
- // don't make an options pointer just to do that.
+ // If we're resetting this to an invalid thread id, then don't make an
+ // options pointer just to do that.
if (m_options_ap.get() != nullptr)
m_options_ap->GetThreadSpec()->SetName(thread_name);
}
@@ -176,8 +176,8 @@ void BreakpointLocation::SetQueueName(const char *queue_name) {
if (queue_name != nullptr)
GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
else {
- // If we're resetting this to an invalid thread id, then
- // don't make an options pointer just to do that.
+ // If we're resetting this to an invalid thread id, then don't make an
+ // options pointer just to do that.
if (m_options_ap.get() != nullptr)
m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
}
@@ -203,8 +203,8 @@ bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
void *baton, bool is_synchronous) {
- // The default "Baton" class will keep a copy of "baton" and won't free
- // or delete it when it goes goes out of scope.
+ // The default "Baton" class will keep a copy of "baton" and won't free or
+ // delete it when it goes goes out of scope.
GetLocationOptions()->SetCallback(
callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
@@ -283,8 +283,7 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
}
// We need to make sure the user sees any parse errors in their condition, so
- // we'll hook the
- // constructor errors up to the debugger's Async I/O.
+ // we'll hook the constructor errors up to the debugger's Async I/O.
ValueObjectSP result_value_sp;
@@ -372,9 +371,9 @@ bool BreakpointLocation::IgnoreCountShouldStop() {
}
BreakpointOptions *BreakpointLocation::GetLocationOptions() {
- // If we make the copy we don't copy the callbacks because that is potentially
- // expensive and we don't want to do that for the simple case where someone is
- // just disabling the location.
+ // If we make the copy we don't copy the callbacks because that is
+ // potentially expensive and we don't want to do that for the simple case
+ // where someone is just disabling the location.
if (m_options_ap.get() == nullptr)
m_options_ap.reset(
new BreakpointOptions(false));
@@ -479,9 +478,8 @@ bool BreakpointLocation::ClearBreakpointSite() {
if (m_bp_site_sp.get()) {
ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
// If the process exists, get it to remove the owner, it will remove the
- // physical implementation
- // of the breakpoint as well if there are no more owners. Otherwise just
- // remove this owner.
+ // physical implementation of the breakpoint as well if there are no more
+ // owners. Otherwise just remove this owner.
if (process_sp)
process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
GetID(), m_bp_site_sp);
@@ -499,8 +497,8 @@ void BreakpointLocation::GetDescription(Stream *s,
SymbolContext sc;
// If the description level is "initial" then the breakpoint is printing out
- // our initial state,
- // and we should let it decide how it wants to print our label.
+ // our initial state, and we should let it decide how it wants to print our
+ // label.
if (level != eDescriptionLevelInitial) {
s->Indent();
BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
index 1e4b4412a427..23ca89da6ce1 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
@@ -49,12 +49,12 @@ bool BreakpointLocationList::ShouldStop(StoppointCallbackContext *context,
BreakpointLocationSP bp = FindByID(break_id);
if (bp) {
// Let the BreakpointLocation decide if it should stop here (could not have
- // reached it's target hit count yet, or it could have a callback
- // that decided it shouldn't stop (shared library loads/unloads).
+ // reached it's target hit count yet, or it could have a callback that
+ // decided it shouldn't stop (shared library loads/unloads).
return bp->ShouldStop(context);
}
- // We should stop here since this BreakpointLocation isn't valid anymore or it
- // doesn't exist.
+ // We should stop here since this BreakpointLocation isn't valid anymore or
+ // it doesn't exist.
return true;
}
@@ -246,10 +246,10 @@ bool BreakpointLocationList::RemoveLocation(
m_address_to_location.erase(bp_loc_sp->GetAddress());
- collection::iterator pos, end = m_locations.end();
- for (pos = m_locations.begin(); pos != end; ++pos) {
- if ((*pos).get() == bp_loc_sp.get()) {
- m_locations.erase(pos);
+ size_t num_locations = m_locations.size();
+ for (size_t idx = 0; idx < num_locations; idx++) {
+ if (m_locations[idx].get() == bp_loc_sp.get()) {
+ RemoveLocationByIndex(idx);
return true;
}
}
@@ -257,17 +257,23 @@ bool BreakpointLocationList::RemoveLocation(
return false;
}
+void BreakpointLocationList::RemoveLocationByIndex(size_t idx) {
+ assert (idx < m_locations.size());
+ m_address_to_location.erase(m_locations[idx]->GetAddress());
+ m_locations.erase(m_locations.begin() + idx);
+}
+
void BreakpointLocationList::RemoveInvalidLocations(const ArchSpec &arch) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
size_t idx = 0;
- // Don't cache m_location.size() as it will change since we might
- // remove locations from our vector...
+ // Don't cache m_location.size() as it will change since we might remove
+ // locations from our vector...
while (idx < m_locations.size()) {
BreakpointLocation *bp_loc = m_locations[idx].get();
if (bp_loc->GetAddress().SectionWasDeleted()) {
// Section was deleted which means this breakpoint comes from a module
// that is no longer valid, so we should remove it.
- m_locations.erase(m_locations.begin() + idx);
+ RemoveLocationByIndex(idx);
continue;
}
if (arch.IsValid()) {
@@ -276,12 +282,13 @@ void BreakpointLocationList::RemoveInvalidLocations(const ArchSpec &arch) {
if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) {
// The breakpoint was in a module whose architecture is no longer
// compatible with "arch", so we need to remove it
- m_locations.erase(m_locations.begin() + idx);
+ RemoveLocationByIndex(idx);
continue;
}
}
}
- // Only increment the index if we didn't remove the locations at index "idx"
+ // Only increment the index if we didn't remove the locations at index
+ // "idx"
++idx;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
index 662b288794d3..b5869fc34dfc 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -425,10 +425,9 @@ void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
const lldb::BatonSP &callback_baton_sp,
bool callback_is_synchronous) {
// FIXME: This seems unsafe. If BatonSP actually *is* a CommandBaton, but
- // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we
- // will set m_baton_is_command_baton to false, which is incorrect.
- // One possible solution is to make the base Baton class provide a method
- // such as:
+ // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will
+ // set m_baton_is_command_baton to false, which is incorrect. One possible
+ // solution is to make the base Baton class provide a method such as:
// virtual StringRef getBatonId() const { return ""; }
// and have CommandBaton override this to return something unique, and then
// check for it here. Another option might be to make Baton using the llvm
@@ -470,12 +469,18 @@ const Baton *BreakpointOptions::GetBaton() const {
bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id) {
- if (m_callback && context->is_synchronous == IsCallbackSynchronous()) {
- return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
+ if (m_callback) {
+ if (context->is_synchronous == IsCallbackSynchronous()) {
+ return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
: nullptr,
context, break_id, break_loc_id);
- } else
- return true;
+ } else if (IsCallbackSynchronous()) {
+ // If a synchronous callback is called at async time, it should not say
+ // to stop.
+ return false;
+ }
+ }
+ return true;
}
bool BreakpointOptions::HasCallback() const {
@@ -526,7 +531,10 @@ const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
ThreadSpec *BreakpointOptions::GetThreadSpec() {
if (m_thread_spec_ap.get() == nullptr)
+ {
+ m_set_flags.Set(eThreadSpec);
m_thread_spec_ap.reset(new ThreadSpec());
+ }
return m_thread_spec_ap.get();
}
@@ -545,8 +553,7 @@ void BreakpointOptions::SetThreadSpec(
void BreakpointOptions::GetDescription(Stream *s,
lldb::DescriptionLevel level) const {
// Figure out if there are any options not at their default value, and only
- // print
- // anything if there are:
+ // print anything if there are:
if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
(GetThreadSpecNoCreate() != nullptr &&
@@ -651,8 +658,7 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction(
CommandReturnObject result;
Debugger &debugger = target->GetDebugger();
// Rig up the results secondary output stream to the debugger's, so the
- // output will come out synchronously
- // if the debugger is set up that way.
+ // output will come out synchronously if the debugger is set up that way.
StreamSP output_stream(debugger.GetAsyncOutputStream());
StreamSP error_stream(debugger.GetAsyncErrorStream());
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolver.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolver.cpp
index 31aefb08f976..6ab578dd8576 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolver.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolver.cpp
@@ -15,8 +15,8 @@
// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
-// Have to include the other breakpoint resolver types here so the static create
-// from StructuredData can call them.
+// Have to include the other breakpoint resolver types here so the static
+// create from StructuredData can call them.
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
@@ -212,8 +212,7 @@ void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
sc_list.RemoveContextAtIndex(current_idx);
// ResolveSymbolContext will always return a number that is >= the line
- // number you pass in.
- // So the smaller line number is always better.
+ // number you pass in. So the smaller line number is always better.
if (sc.line_entry.line < closest_line_number)
closest_line_number = sc.line_entry.line;
} else
@@ -234,8 +233,7 @@ void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
}
// Next go through and see if there are line table entries that are
- // contiguous, and if so keep only the
- // first of the contiguous range:
+ // contiguous, and if so keep only the first of the contiguous range:
current_idx = 0;
std::map<Block *, lldb::addr_t> blocks_with_breakpoints;
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
index 32f2045ed59a..d4647e2c589d 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
@@ -66,7 +66,7 @@ BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData(
error.SetErrorString("BRA::CFSD: Couldn't read module name entry.");
return nullptr;
}
- module_filespec.SetFile(module_name, false);
+ module_filespec.SetFile(module_name, false, FileSpec::Style::native);
}
return new BreakpointResolverAddress(bkpt, address, module_filespec);
}
@@ -100,11 +100,10 @@ BreakpointResolverAddress::SerializeToStructuredData() {
}
void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) {
- // If the address is not section relative, then we should not try to
- // re-resolve it, it is just some
- // random address and we wouldn't know what to do on reload. But if it is
- // section relative, we need to
- // re-resolve it since the section it's in may have shifted on re-run.
+ // If the address is not section relative, then we should not try to re-
+ // resolve it, it is just some random address and we wouldn't know what to do
+ // on reload. But if it is section relative, we need to re-resolve it since
+ // the section it's in may have shifted on re-run.
bool re_resolve = false;
if (m_addr.GetSection() || m_module_filespec)
re_resolve = true;
@@ -137,8 +136,8 @@ BreakpointResolverAddress::SearchCallback(SearchFilter &filter,
if (filter.AddressPasses(m_addr)) {
if (m_breakpoint->GetNumLocations() == 0) {
// If the address is just an offset, and we're given a module, see if we
- // can find the appropriate module
- // loaded in the binary, and fix up m_addr to use that.
+ // can find the appropriate module loaded in the binary, and fix up
+ // m_addr to use that.
if (!m_addr.IsSectionOffset() && m_module_filespec) {
Target &target = m_breakpoint->GetTarget();
ModuleSpec module_spec(m_module_filespec);
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
index 780d25db9ccb..ecef88eb9989 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -110,20 +110,40 @@ BreakpointResolverFileLine::SerializeToStructuredData() {
// Filter the symbol context list to remove contexts where the line number was
// moved into a new function. We do this conservatively, so if e.g. we cannot
-// resolve the function in the context (which can happen in case of
-// line-table-only debug info), we leave the context as is. The trickiest part
-// here is handling inlined functions -- in this case we need to make sure we
-// look at the declaration line of the inlined function, NOT the function it was
+// resolve the function in the context (which can happen in case of line-table-
+// only debug info), we leave the context as is. The trickiest part here is
+// handling inlined functions -- in this case we need to make sure we look at
+// the declaration line of the inlined function, NOT the function it was
// inlined into.
-void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) {
+void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list,
+ bool is_relative) {
if (m_exact_match)
return; // Nothing to do. Contexts are precise.
+ llvm::StringRef relative_path;
+ if (is_relative)
+ relative_path = m_file_spec.GetDirectory().GetStringRef();
+
Log * log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
for(uint32_t i = 0; i < sc_list.GetSize(); ++i) {
SymbolContext sc;
sc_list.GetContextAtIndex(i, sc);
- if (! sc.block)
+ if (is_relative) {
+ // If the path was relative, make sure any matches match as long as the
+ // relative parts of the path match the path from support files
+ auto sc_dir = sc.line_entry.file.GetDirectory().GetStringRef();
+ if (!sc_dir.endswith(relative_path)) {
+ // We had a relative path specified and the relative directory doesn't
+ // match so remove this one
+ LLDB_LOG(log, "removing not matching relative path {0} since it "
+ "doesn't end with {1}", sc_dir, relative_path);
+ sc_list.RemoveContextAtIndex(i);
+ --i;
+ continue;
+ }
+ }
+
+ if (!sc.block)
continue;
FileSpec file;
@@ -179,33 +199,38 @@ BreakpointResolverFileLine::SearchCallback(SearchFilter &filter,
assert(m_breakpoint != NULL);
// There is a tricky bit here. You can have two compilation units that
- // #include the same file, and in one of them the function at m_line_number is
- // used (and so code and a line entry for it is generated) but in the other it
- // isn't. If we considered the CU's independently, then in the second
- // inclusion, we'd move the breakpoint to the next function that actually
- // generated code in the header file. That would end up being confusing. So
- // instead, we do the CU iterations by hand here, then scan through the
- // complete list of matches, and figure out the closest line number match, and
- // only set breakpoints on that match.
-
- // Note also that if file_spec only had a file name and not a directory, there
- // may be many different file spec's in the resultant list. The closest line
- // match for one will not be right for some totally different file. So we go
- // through the match list and pull out the sets that have the same file spec
- // in their line_entry and treat each set separately.
+ // #include the same file, and in one of them the function at m_line_number
+ // is used (and so code and a line entry for it is generated) but in the
+ // other it isn't. If we considered the CU's independently, then in the
+ // second inclusion, we'd move the breakpoint to the next function that
+ // actually generated code in the header file. That would end up being
+ // confusing. So instead, we do the CU iterations by hand here, then scan
+ // through the complete list of matches, and figure out the closest line
+ // number match, and only set breakpoints on that match.
+
+ // Note also that if file_spec only had a file name and not a directory,
+ // there may be many different file spec's in the resultant list. The
+ // closest line match for one will not be right for some totally different
+ // file. So we go through the match list and pull out the sets that have the
+ // same file spec in their line_entry and treat each set separately.
+
+ FileSpec search_file_spec = m_file_spec;
+ const bool is_relative = m_file_spec.IsRelative();
+ if (is_relative)
+ search_file_spec.GetDirectory().Clear();
const size_t num_comp_units = context.module_sp->GetNumCompileUnits();
for (size_t i = 0; i < num_comp_units; i++) {
CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i));
if (cu_sp) {
if (filter.CompUnitPasses(*cu_sp))
- cu_sp->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines,
+ cu_sp->ResolveSymbolContext(search_file_spec, m_line_number, m_inlines,
m_exact_match, eSymbolContextEverything,
sc_list);
}
}
- FilterContexts(sc_list);
+ FilterContexts(sc_list, is_relative);
StreamString s;
s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"),
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp
index 468de35db0ee..ba277ae2655e 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -16,11 +16,13 @@
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Architecture.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -239,9 +241,8 @@ void BreakpointResolverName::AddNameLookup(const ConstString &name,
// FIXME: Right now we look at the module level, and call the module's
// "FindFunctions".
// Greg says he will add function tables, maybe at the CompileUnit level to
-// accelerate function
-// lookup. At that point, we should switch the depth to CompileUnit, and look
-// in these tables.
+// accelerate function lookup. At that point, we should switch the depth to
+// CompileUnit, and look in these tables.
Searcher::CallbackReturn
BreakpointResolverName::SearchCallback(SearchFilter &filter,
@@ -299,8 +300,8 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter,
break;
}
- // If the filter specifies a Compilation Unit, remove the ones that don't pass
- // at this point.
+ // If the filter specifies a Compilation Unit, remove the ones that don't
+ // pass at this point.
if (filter_by_cu || filter_by_language) {
uint32_t num_functions = func_list.GetSize();
@@ -365,6 +366,12 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter,
sc.symbol->GetPrologueByteSize();
if (prologue_byte_size)
break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
+ else {
+ const Architecture *arch =
+ m_breakpoint->GetTarget().GetArchitecturePlugin();
+ if (arch)
+ arch->AdjustBreakpointAddress(*sc.symbol, break_addr);
+ }
}
}
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSiteList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSiteList.cpp
index 87ce292feb8e..9bb9aa366106 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSiteList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSiteList.cpp
@@ -24,8 +24,7 @@ BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {}
BreakpointSiteList::~BreakpointSiteList() {}
// Add breakpoint site to the list. However, if the element already exists in
-// the
-// list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
+// the list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) {
lldb::addr_t bp_site_load_addr = bp->GetLoadAddress();
@@ -45,8 +44,8 @@ bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context,
BreakpointSiteSP site_sp(FindByID(site_id));
if (site_sp) {
// Let the BreakpointSite decide if it should stop here (could not have
- // reached it's target hit count yet, or it could have a callback
- // that decided it shouldn't stop (shared library loads/unloads).
+ // reached it's target hit count yet, or it could have a callback that
+ // decided it shouldn't stop (shared library loads/unloads).
return site_sp->ShouldStop(context);
}
// We should stop here since this BreakpointSite isn't valid anymore or it
@@ -60,7 +59,8 @@ lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) {
// PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
return bp.get()->GetID();
}
- // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64
+ // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8"
+ // PRIx64
// " ) => NONE", __FUNCTION__, (uint64_t)addr);
return LLDB_INVALID_BREAK_ID;
}
@@ -185,10 +185,9 @@ bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound,
if (lower == m_bp_site_list.end() || (*lower).first >= upper_bound)
return false;
- // This is one tricky bit. The breakpoint might overlap the bottom end of the
- // range. So we grab the
- // breakpoint prior to the lower bound, and check that that + its byte size
- // isn't in our range.
+ // This is one tricky bit. The breakpoint might overlap the bottom end of
+ // the range. So we grab the breakpoint prior to the lower bound, and check
+ // that that + its byte size isn't in our range.
if (lower != m_bp_site_list.begin()) {
collection::const_iterator prev_pos = lower;
prev_pos--;
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp
index a141a6b5c2f9..7a936d1fb130 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp
@@ -59,8 +59,8 @@ Watchpoint::~Watchpoint() = default;
// This function is used when "baton" doesn't need to be freed
void Watchpoint::SetCallback(WatchpointHitCallback callback, void *baton,
bool is_synchronous) {
- // The default "Baton" class will keep a copy of "baton" and won't free
- // or delete it when it goes goes out of scope.
+ // The default "Baton" class will keep a copy of "baton" and won't free or
+ // delete it when it goes goes out of scope.
m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton),
is_synchronous);
@@ -103,8 +103,8 @@ bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) {
Address watch_address(GetLoadAddress());
if (!m_type.IsValid()) {
// Don't know how to report new & old values, since we couldn't make a
- // scalar type for this watchpoint.
- // This works around an assert in ValueObjectMemory::Create.
+ // scalar type for this watchpoint. This works around an assert in
+ // ValueObjectMemory::Create.
// FIXME: This should not happen, but if it does in some case we care about,
// we can go grab the value raw and print it as unsigned.
return false;
@@ -217,11 +217,9 @@ void Watchpoint::DumpWithLevel(Stream *s,
bool Watchpoint::IsEnabled() const { return m_enabled; }
// Within StopInfo.cpp, we purposely turn on the ephemeral mode right before
-// temporarily disable the watchpoint
-// in order to perform possible watchpoint actions without triggering further
-// watchpoint events.
-// After the temporary disabled watchpoint is enabled, we then turn off the
-// ephemeral mode.
+// temporarily disable the watchpoint in order to perform possible watchpoint
+// actions without triggering further watchpoint events. After the temporary
+// disabled watchpoint is enabled, we then turn off the ephemeral mode.
void Watchpoint::TurnOnEphemeralMode() { m_is_ephemeral = true; }
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
index 6ec3bd09c142..6497780084d9 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
@@ -203,9 +203,9 @@ bool WatchpointList::ShouldStop(StoppointCallbackContext *context,
WatchpointSP wp_sp = FindByID(watch_id);
if (wp_sp) {
- // Let the Watchpoint decide if it should stop here (could not have
- // reached it's target hit count yet, or it could have a callback
- // that decided it shouldn't stop.
+ // Let the Watchpoint decide if it should stop here (could not have reached
+ // it's target hit count yet, or it could have a callback that decided it
+ // shouldn't stop.
return wp_sp->ShouldStop(context);
}
// We should stop here since this Watchpoint isn't valid anymore or it
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp
index 558ebc51008c..402fee943a02 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp
@@ -143,8 +143,7 @@ void WatchpointOptions::GetCallbackDescription(
void WatchpointOptions::GetDescription(Stream *s,
lldb::DescriptionLevel level) const {
// Figure out if there are any options not at their default value, and only
- // print
- // anything if there are:
+ // print anything if there are:
if ((GetThreadSpecNoCreate() != nullptr &&
GetThreadSpecNoCreate()->HasSpecification())) {
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandCompletions.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandCompletions.cpp
index 34cad970ff6e..7b351c50dc69 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandCompletions.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandCompletions.cpp
@@ -23,14 +23,13 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSystem.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/CleanUp.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/TildeExpressionResolver.h"
@@ -58,9 +57,7 @@ CommandCompletions::CommonCompletionElement
bool CommandCompletions::InvokeCommonCompletionCallbacks(
CommandInterpreter &interpreter, uint32_t completion_mask,
- llvm::StringRef completion_str, int match_start_point,
- int max_return_elements, SearchFilter *searcher, bool &word_complete,
- StringList &matches) {
+ CompletionRequest &request, SearchFilter *searcher) {
bool handled = false;
if (completion_mask & eCustomCompletion)
@@ -73,25 +70,18 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
g_common_completions[i].type &&
g_common_completions[i].callback != nullptr) {
handled = true;
- g_common_completions[i].callback(interpreter, completion_str,
- match_start_point, max_return_elements,
- searcher, word_complete, matches);
+ g_common_completions[i].callback(interpreter, request, searcher);
}
}
return handled;
}
int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point,
- int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- StringList &matches) {
- word_complete = true;
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ request.SetWordComplete(true);
// Find some way to switch "include support files..."
- SourceFileCompleter completer(interpreter, false, partial_file_name,
- match_start_point, max_return_elements,
- matches);
+ SourceFileCompleter completer(interpreter, false, request);
if (searcher == nullptr) {
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
@@ -100,12 +90,11 @@ int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
} else {
completer.DoCompletion(searcher);
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
- bool only_directories, bool &saw_directory,
- StringList &matches,
+ bool only_directories, StringList &matches,
TildeExpressionResolver &Resolver) {
matches.Clear();
@@ -114,7 +103,7 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
partial_name.toVector(CompletionBuffer);
if (CompletionBuffer.size() >= PATH_MAX)
- return 0;
+ return matches.GetSize();
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
@@ -139,33 +128,37 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
// but after that, we're done regardless of any matches.
if (FirstSep == llvm::StringRef::npos) {
llvm::StringSet<> MatchSet;
- saw_directory = Resolver.ResolvePartial(Username, MatchSet);
+ Resolver.ResolvePartial(Username, MatchSet);
for (const auto &S : MatchSet) {
Resolved = S.getKey();
path::append(Resolved, path::get_separator());
matches.AppendString(Resolved);
}
- saw_directory = (matches.GetSize() > 0);
}
return matches.GetSize();
}
- // If there was no trailing slash, then we're done as soon as we resolve the
- // expression to the correct directory. Otherwise we need to continue
+ // If there was no trailing slash, then we're done as soon as we resolve
+ // the expression to the correct directory. Otherwise we need to continue
// looking for matches within that directory.
if (FirstSep == llvm::StringRef::npos) {
// Make sure it ends with a separator.
path::append(CompletionBuffer, path::get_separator());
- saw_directory = true;
matches.AppendString(CompletionBuffer);
- return 1;
+ return matches.GetSize();
}
// We want to keep the form the user typed, so we special case this to
// search in the fully resolved directory, but CompletionBuffer keeps the
// unmodified form that the user typed.
Storage = Resolved;
- SearchDir = Resolved;
+ llvm::StringRef RemainderDir = path::parent_path(Remainder);
+ if (!RemainderDir.empty()) {
+ // Append the remaining path to the resolved directory.
+ Storage.append(path::get_separator());
+ Storage.append(RemainderDir);
+ }
+ SearchDir = Storage;
} else {
SearchDir = path::parent_path(CompletionBuffer);
}
@@ -222,7 +215,6 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
CompletionBuffer.append(Name);
if (is_dir) {
- saw_directory = true;
path::append(CompletionBuffer, path::get_separator());
}
@@ -232,52 +224,46 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
return matches.GetSize();
}
+static int DiskFilesOrDirectories(CompletionRequest &request,
+ bool only_directories) {
+ request.SetWordComplete(false);
+ StandardTildeExpressionResolver resolver;
+ StringList matches;
+ DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories,
+ matches, resolver);
+ request.AddCompletions(matches);
+ return request.GetNumberOfMatches();
+}
+
int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point,
- int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- StringList &matches) {
- word_complete = false;
- StandardTildeExpressionResolver Resolver;
- return DiskFiles(partial_file_name, matches, Resolver);
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ return DiskFilesOrDirectories(request, /*only_dirs*/ false);
}
int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
StringList &matches,
TildeExpressionResolver &Resolver) {
- bool word_complete;
- int ret_val = DiskFilesOrDirectories(partial_file_name, false, word_complete,
- matches, Resolver);
- return ret_val;
+ return DiskFilesOrDirectories(partial_file_name, false, matches, Resolver);
}
-int CommandCompletions::DiskDirectories(
- CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements, SearchFilter *searcher,
- bool &word_complete, StringList &matches) {
- word_complete = false;
- StandardTildeExpressionResolver Resolver;
- return DiskDirectories(partial_file_name, matches, Resolver);
+int CommandCompletions::DiskDirectories(CommandInterpreter &interpreter,
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ return DiskFilesOrDirectories(request, /*only_dirs*/ true);
}
int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
StringList &matches,
TildeExpressionResolver &Resolver) {
- bool word_complete;
- int ret_val = DiskFilesOrDirectories(partial_file_name, true, word_complete,
- matches, Resolver);
- return ret_val;
+ return DiskFilesOrDirectories(partial_file_name, true, matches, Resolver);
}
int CommandCompletions::Modules(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- StringList &matches) {
- word_complete = true;
- ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
- max_return_elements, matches);
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ request.SetWordComplete(true);
+ ModuleCompleter completer(interpreter, request);
if (searcher == nullptr) {
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
@@ -286,17 +272,14 @@ int CommandCompletions::Modules(CommandInterpreter &interpreter,
} else {
completer.DoCompletion(searcher);
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
int CommandCompletions::Symbols(CommandInterpreter &interpreter,
- llvm::StringRef partial_file_name,
- int match_start_point, int max_return_elements,
- SearchFilter *searcher, bool &word_complete,
- StringList &matches) {
- word_complete = true;
- SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
- max_return_elements, matches);
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ request.SetWordComplete(true);
+ SymbolCompleter completer(interpreter, request);
if (searcher == nullptr) {
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
@@ -305,13 +288,12 @@ int CommandCompletions::Symbols(CommandInterpreter &interpreter,
} else {
completer.DoCompletion(searcher);
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
-int CommandCompletions::SettingsNames(
- CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
- int match_start_point, int max_return_elements, SearchFilter *searcher,
- bool &word_complete, StringList &matches) {
+int CommandCompletions::SettingsNames(CommandInterpreter &interpreter,
+ CompletionRequest &request,
+ SearchFilter *searcher) {
// Cache the full setting name list
static StringList g_property_names;
if (g_property_names.GetSize() == 0) {
@@ -327,47 +309,42 @@ int CommandCompletions::SettingsNames(
}
size_t exact_matches_idx = SIZE_MAX;
- const size_t num_matches = g_property_names.AutoComplete(
- partial_setting_name, matches, exact_matches_idx);
- word_complete = exact_matches_idx != SIZE_MAX;
- return num_matches;
+ StringList matches;
+ g_property_names.AutoComplete(request.GetCursorArgumentPrefix(), matches,
+ exact_matches_idx);
+ request.SetWordComplete(exact_matches_idx != SIZE_MAX);
+ request.AddCompletions(matches);
+ return request.GetNumberOfMatches();
}
-int CommandCompletions::PlatformPluginNames(
- CommandInterpreter &interpreter, llvm::StringRef partial_name,
- int match_start_point, int max_return_elements, SearchFilter *searcher,
- bool &word_complete, lldb_private::StringList &matches) {
- const uint32_t num_matches =
- PluginManager::AutoCompletePlatformName(partial_name, matches);
- word_complete = num_matches == 1;
- return num_matches;
+int CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter,
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ StringList new_matches;
+ std::size_t num_matches = PluginManager::AutoCompletePlatformName(
+ request.GetCursorArgumentPrefix(), new_matches);
+ request.SetWordComplete(num_matches == 1);
+ request.AddCompletions(new_matches);
+ return request.GetNumberOfMatches();
}
-int CommandCompletions::ArchitectureNames(
- CommandInterpreter &interpreter, llvm::StringRef partial_name,
- int match_start_point, int max_return_elements, SearchFilter *searcher,
- bool &word_complete, lldb_private::StringList &matches) {
- const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
- word_complete = num_matches == 1;
+int CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter,
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ const uint32_t num_matches = ArchSpec::AutoComplete(request);
+ request.SetWordComplete(num_matches == 1);
return num_matches;
}
-int CommandCompletions::VariablePath(
- CommandInterpreter &interpreter, llvm::StringRef partial_name,
- int match_start_point, int max_return_elements, SearchFilter *searcher,
- bool &word_complete, lldb_private::StringList &matches) {
- return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
- matches, word_complete);
+int CommandCompletions::VariablePath(CommandInterpreter &interpreter,
+ CompletionRequest &request,
+ SearchFilter *searcher) {
+ return Variable::AutoComplete(interpreter.GetExecutionContext(), request);
}
CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
- llvm::StringRef completion_str,
- int match_start_point,
- int max_return_elements,
- StringList &matches)
- : m_interpreter(interpreter), m_completion_str(completion_str),
- m_match_start_point(match_start_point),
- m_max_return_elements(max_return_elements), m_matches(matches) {}
+ CompletionRequest &request)
+ : m_interpreter(interpreter), m_request(request) {}
CommandCompletions::Completer::~Completer() = default;
@@ -377,13 +354,10 @@ CommandCompletions::Completer::~Completer() = default;
CommandCompletions::SourceFileCompleter::SourceFileCompleter(
CommandInterpreter &interpreter, bool include_support_files,
- llvm::StringRef completion_str, int match_start_point,
- int max_return_elements, StringList &matches)
- : CommandCompletions::Completer(interpreter, completion_str,
- match_start_point, max_return_elements,
- matches),
+ CompletionRequest &request)
+ : CommandCompletions::Completer(interpreter, request),
m_include_support_files(include_support_files), m_matching_files() {
- FileSpec partial_spec(m_completion_str, false);
+ FileSpec partial_spec(m_request.GetCursorArgumentPrefix(), false);
m_file_name = partial_spec.GetFilename().GetCString();
m_dir_name = partial_spec.GetDirectory().GetCString();
}
@@ -443,10 +417,10 @@ CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
filter->Search(*this);
// Now convert the filelist to completions:
for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
- m_matches.AppendString(
+ m_request.AddCompletion(
m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
}
- return m_matches.GetSize();
+ return m_request.GetNumberOfMatches();
}
//----------------------------------------------------------------------
@@ -461,15 +435,12 @@ static bool regex_chars(const char comp) {
}
CommandCompletions::SymbolCompleter::SymbolCompleter(
- CommandInterpreter &interpreter, llvm::StringRef completion_str,
- int match_start_point, int max_return_elements, StringList &matches)
- : CommandCompletions::Completer(interpreter, completion_str,
- match_start_point, max_return_elements,
- matches) {
+ CommandInterpreter &interpreter, CompletionRequest &request)
+ : CommandCompletions::Completer(interpreter, request) {
std::string regex_str;
- if (!completion_str.empty()) {
+ if (!m_request.GetCursorArgumentPrefix().empty()) {
regex_str.append("^");
- regex_str.append(completion_str);
+ regex_str.append(m_request.GetCursorArgumentPrefix());
} else {
// Match anything since the completion string is empty
regex_str.append(".");
@@ -515,21 +486,18 @@ size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
filter->Search(*this);
collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
for (pos = m_match_set.begin(); pos != end; pos++)
- m_matches.AppendString((*pos).GetCString());
+ m_request.AddCompletion((*pos).GetCString());
- return m_matches.GetSize();
+ return m_request.GetNumberOfMatches();
}
//----------------------------------------------------------------------
// ModuleCompleter
//----------------------------------------------------------------------
CommandCompletions::ModuleCompleter::ModuleCompleter(
- CommandInterpreter &interpreter, llvm::StringRef completion_str,
- int match_start_point, int max_return_elements, StringList &matches)
- : CommandCompletions::Completer(interpreter, completion_str,
- match_start_point, max_return_elements,
- matches) {
- FileSpec partial_spec(m_completion_str, false);
+ CommandInterpreter &interpreter, CompletionRequest &request)
+ : CommandCompletions::Completer(interpreter, request) {
+ FileSpec partial_spec(m_request.GetCursorArgumentPrefix(), false);
m_file_name = partial_spec.GetFilename().GetCString();
m_dir_name = partial_spec.GetDirectory().GetCString();
}
@@ -557,7 +525,7 @@ Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
match = false;
if (match) {
- m_matches.AppendString(cur_file_name);
+ m_request.AddCompletion(cur_file_name);
}
}
return Searcher::eCallbackReturnContinue;
@@ -565,5 +533,5 @@ Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
filter->Search(*this);
- return m_matches.GetSize();
+ return m_request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.cpp
index 1114a511aa07..047575278faa 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.cpp
@@ -13,11 +13,11 @@
// Other libraries and framework includes
// Project includes
#include "CommandObjectApropos.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -53,8 +53,8 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) {
if (argc == 1) {
auto search_word = args[0].ref;
if (!search_word.empty()) {
- // The bulk of the work must be done inside the Command Interpreter, since
- // the command dictionary is private.
+ // The bulk of the work must be done inside the Command Interpreter,
+ // since the command dictionary is private.
StringList commands_found;
StringList commands_help;
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp
deleted file mode 100644
index 92c2107dc33c..000000000000
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "CommandObjectArgs.h"
-#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Variable.h"
-#include "lldb/Target/ABI.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-
-#include "llvm/ADT/StringSwitch.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-// This command is a toy. I'm just using it to have a way to construct the
-// arguments to
-// calling functions.
-//
-
-static OptionDefinition g_arg_options[] = {
- // clang-format off
- { LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation." },
- // clang-format on
-};
-
-CommandObjectArgs::CommandOptions::CommandOptions(
- CommandInterpreter &interpreter)
- : Options() {
- // Keep only one place to reset the values to their defaults
- OptionParsingStarting(nullptr);
-}
-
-CommandObjectArgs::CommandOptions::~CommandOptions() = default;
-
-Status CommandObjectArgs::CommandOptions::SetOptionValue(
- uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) {
- Status error;
-
- const int short_option = m_getopt_table[option_idx].val;
- error.SetErrorStringWithFormat("invalid short option character '%c'",
- short_option);
-
- return error;
-}
-
-void CommandObjectArgs::CommandOptions::OptionParsingStarting(
- ExecutionContext *execution_context) {}
-
-llvm::ArrayRef<OptionDefinition>
-CommandObjectArgs::CommandOptions::GetDefinitions() {
- return llvm::makeArrayRef(g_arg_options);
-}
-
-CommandObjectArgs::CommandObjectArgs(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "args",
- "When stopped at the start of a function, reads "
- "function arguments of type (u?)int(8|16|32|64)_t, "
- "(void|char)*",
- "args"),
- m_options(interpreter) {}
-
-CommandObjectArgs::~CommandObjectArgs() = default;
-
-Options *CommandObjectArgs::GetOptions() { return &m_options; }
-
-bool CommandObjectArgs::DoExecute(Args &args, CommandReturnObject &result) {
- ConstString target_triple;
-
- Process *process = m_exe_ctx.GetProcessPtr();
- if (!process) {
- result.AppendError("Args found no process.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const ABI *abi = process->GetABI().get();
- if (!abi) {
- result.AppendError("The current process has no ABI.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (args.empty()) {
- result.AppendError("args requires at least one argument");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- Thread *thread = m_exe_ctx.GetThreadPtr();
-
- if (!thread) {
- result.AppendError("args found no thread.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame();
- if (!thread_cur_frame) {
- result.AppendError("The current thread has no current frame.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- ModuleSP thread_module_sp(
- thread_cur_frame->GetFrameCodeAddress().GetModule());
- if (!thread_module_sp) {
- result.AppendError("The PC has no associated module.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- TypeSystem *type_system =
- thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
- if (type_system == nullptr) {
- result.AppendError("Unable to create C type system.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- ValueList value_list;
-
- for (auto &arg_entry : args.entries()) {
- llvm::StringRef arg_type = arg_entry.ref;
- Value value;
- value.SetValueType(Value::eValueTypeScalar);
- CompilerType compiler_type;
-
- std::size_t int_pos = arg_type.find("int");
- if (int_pos != llvm::StringRef::npos) {
- Encoding encoding = eEncodingSint;
-
- int width = 0;
-
- if (int_pos > 1) {
- result.AppendErrorWithFormat("Invalid format: %s.\n",
- arg_entry.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- if (int_pos == 1 && arg_type[0] != 'u') {
- result.AppendErrorWithFormat("Invalid format: %s.\n",
- arg_entry.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- if (arg_type[0] == 'u') {
- encoding = eEncodingUint;
- }
-
- llvm::StringRef width_spec = arg_type.drop_front(int_pos + 3);
-
- auto exp_result = llvm::StringSwitch<llvm::Optional<int>>(width_spec)
- .Case("8_t", 8)
- .Case("16_t", 16)
- .Case("32_t", 32)
- .Case("64_t", 64)
- .Default(llvm::None);
- if (!exp_result.hasValue()) {
- result.AppendErrorWithFormat("Invalid format: %s.\n",
- arg_entry.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- width = *exp_result;
-
- compiler_type =
- type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width);
-
- if (!compiler_type.IsValid()) {
- result.AppendErrorWithFormat(
- "Couldn't get Clang type for format %s (%s integer, width %d).\n",
- arg_entry.c_str(),
- (encoding == eEncodingSint ? "signed" : "unsigned"), width);
-
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- } else if (arg_type == "void*") {
- compiler_type =
- type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType();
- } else if (arg_type == "char*") {
- compiler_type =
- type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType();
- } else {
- result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- value.SetCompilerType(compiler_type);
- value_list.PushValue(value);
- }
-
- if (!abi->GetArgumentValues(*thread, value_list)) {
- result.AppendError("Couldn't get argument values");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- result.GetOutputStream().Printf("Arguments : \n");
-
- for (auto entry : llvm::enumerate(args.entries())) {
- result.GetOutputStream().Printf(
- "%" PRIu64 " (%s): ", (uint64_t)entry.index(), entry.value().c_str());
- value_list.GetValueAtIndex(entry.index())->Dump(&result.GetOutputStream());
- result.GetOutputStream().Printf("\n");
- }
-
- return result.Succeeded();
-}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h
deleted file mode 100644
index aa7d2411adc8..000000000000
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===-- CommandObjectArgs.h -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_CommandObjectArgs_h_
-#define liblldb_CommandObjectArgs_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Interpreter/CommandObject.h"
-#include "lldb/Interpreter/Options.h"
-
-namespace lldb_private {
-
-class CommandObjectArgs : public CommandObjectParsed {
-public:
- class CommandOptions : public Options {
- public:
- CommandOptions(CommandInterpreter &interpreter);
-
- ~CommandOptions() override;
-
- Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override;
-
- void OptionParsingStarting(ExecutionContext *execution_context) override;
-
- llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- };
-
- CommandObjectArgs(CommandInterpreter &interpreter);
-
- ~CommandObjectArgs() override;
-
- Options *GetOptions() override;
-
-protected:
- CommandOptions m_options;
-
- bool DoExecute(Args &command, CommandReturnObject &result) override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_CommandObjectArgs_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 5a175d61060e..fb0553e482db 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -22,6 +22,7 @@
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
@@ -84,8 +85,8 @@ public:
switch (short_option) {
case 'c':
- // Normally an empty breakpoint condition marks is as unset.
- // But we need to say it was passed in.
+ // Normally an empty breakpoint condition marks is as unset. But we need
+ // to say it was passed in.
m_bp_opts.SetCondition(option_arg.str().c_str());
m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
break;
@@ -100,7 +101,7 @@ public:
break;
case 'G': {
bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
if (success) {
m_bp_opts.SetAutoContinue(value);
} else
@@ -121,7 +122,7 @@ public:
break;
case 'o': {
bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
if (success) {
m_bp_opts.SetOneShot(value);
} else
@@ -262,8 +263,9 @@ static OptionDefinition g_breakpoint_set_options[] = {
"#included, set target.inline-breakpoint-strategy to \"always\"." },
{ LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
- // Comment out this option for the moment, as we don't actually use it, but will in the future.
- // This way users won't see it, but the infrastructure is left in place.
+ // Comment out this option for the moment, as we don't actually use it, but
+ // will in the future. This way users won't see it, but the infrastructure is
+ // left in place.
// { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
// "Set the breakpoint by source location at this particular column."},
@@ -281,7 +283,7 @@ static OptionDefinition g_breakpoint_set_options[] = {
{ LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
"functions. Can be repeated multiple times." },
{ LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
- "namespaces and all arguments, and for Objective C this means a full function "
+ "namespaces and all arguments, and for Objective-C this means a full function "
"prototype with class and selector. Can be repeated multiple times to make "
"one breakpoint for multiple names." },
{ LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
@@ -377,8 +379,8 @@ public:
switch (short_option) {
case 'a': {
- m_load_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
} break;
case 'A':
@@ -442,7 +444,7 @@ public:
case 'h': {
bool success;
- m_catch_bp = Args::StringToBoolean(option_arg, true, &success);
+ m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat(
"Invalid boolean value for on-catch option: '%s'",
@@ -456,7 +458,7 @@ public:
case 'K': {
bool success;
bool value;
- value = Args::StringToBoolean(option_arg, true, &success);
+ value = OptionArgParser::ToBoolean(option_arg, true, &success);
if (value)
m_skip_prologue = eLazyBoolYes;
else
@@ -485,7 +487,7 @@ public:
case 'm': {
bool success;
bool value;
- value = Args::StringToBoolean(option_arg, true, &success);
+ value = OptionArgParser::ToBoolean(option_arg, true, &success);
if (value)
m_move_to_nearest_code = eLazyBoolYes;
else
@@ -519,8 +521,8 @@ public:
case 'R': {
lldb::addr_t tmp_offset_addr;
- tmp_offset_addr =
- Args::StringToAddress(execution_context, option_arg, 0, &error);
+ tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
+ option_arg, 0, &error);
if (error.Success())
m_offset_addr = tmp_offset_addr;
} break;
@@ -549,7 +551,7 @@ public:
case 'w': {
bool success;
- m_throw_bp = Args::StringToBoolean(option_arg, true, &success);
+ m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat(
"Invalid boolean value for on-throw option: '%s'",
@@ -853,9 +855,9 @@ protected:
output_stream.Printf("Breakpoint set in dummy target, will get copied "
"into future targets.\n");
else {
- // Don't print out this warning for exception breakpoints. They can get
- // set before the target is set, but we won't know how to actually set
- // the breakpoint till we run.
+ // Don't print out this warning for exception breakpoints. They can
+ // get set before the target is set, but we won't know how to actually
+ // set the breakpoint till we run.
if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
"actual locations.\n");
@@ -874,8 +876,8 @@ private:
bool GetDefaultFile(Target *target, FileSpec &file,
CommandReturnObject &result) {
uint32_t default_line;
- // First use the Source Manager's default file.
- // Then use the current stack frame's file.
+ // First use the Source Manager's default file. Then use the current stack
+ // frame's file.
if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
if (cur_frame == nullptr) {
@@ -1451,7 +1453,8 @@ protected:
return false;
}
- // The following are the various types of breakpoints that could be cleared:
+ // The following are the various types of breakpoints that could be
+ // cleared:
// 1). -f -l (clearing breakpoint by source location)
BreakpointClearType break_type = eClearTypeInvalid;
@@ -1783,7 +1786,7 @@ public:
switch (short_option) {
case 'L': {
bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
if (success) {
m_permissions.SetAllowList(value);
} else
@@ -1793,7 +1796,7 @@ public:
} break;
case 'A': {
bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
if (success) {
m_permissions.SetAllowDisable(value);
} else
@@ -1803,7 +1806,7 @@ public:
} break;
case 'D': {
bool value, success;
- value = Args::StringToBoolean(option_arg, false, &success);
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
if (success) {
m_permissions.SetAllowDelete(value);
} else
@@ -1897,8 +1900,8 @@ protected:
return false;
}
}
- // Now configure them, we already pre-checked the names so we don't need
- // to check the error:
+ // Now configure them, we already pre-checked the names so we don't need to
+ // check the error:
BreakpointSP bp_sp;
if (m_bp_id.m_breakpoint.OptionWasSet())
{
@@ -2559,11 +2562,10 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
}
// Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
- // directly from the old ARGS to
- // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
- // generate a list of strings for
- // all the breakpoint ids in the range, and shove all of those breakpoint id
- // strings into TEMP_ARGS.
+ // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
+ // id range strings over; instead generate a list of strings for all the
+ // breakpoint ids in the range, and shove all of those breakpoint id strings
+ // into TEMP_ARGS.
BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
purpose, result, temp_args);
@@ -2571,18 +2573,15 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
// NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
// BreakpointIDList:
- valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
- temp_args.GetArgumentCount(), result);
+ valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
- // At this point, all of the breakpoint ids that the user passed in have been
- // converted to breakpoint IDs
- // and put into valid_ids.
+ // At this point, all of the breakpoint ids that the user passed in have
+ // been converted to breakpoint IDs and put into valid_ids.
if (result.Succeeded()) {
// Now that we've converted everything from args into a list of breakpoint
- // ids, go through our tentative list
- // of breakpoint id's and verify that they correspond to valid/currently set
- // breakpoints.
+ // ids, go through our tentative list of breakpoint id's and verify that
+ // they correspond to valid/currently set breakpoints.
const size_t count = valid_ids->GetSize();
for (size_t i = 0; i < count; ++i) {
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index 170cb8513116..f2546cbed848 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -22,6 +22,7 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -293,7 +294,7 @@ are no syntax errors may indicate that a function was declared but never called.
break;
case 's':
- m_script_language = (lldb::ScriptLanguage)Args::StringToOptionEnum(
+ m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
option_arg, g_breakpoint_add_options[option_idx].enum_values,
eScriptLanguageNone, error);
@@ -307,7 +308,8 @@ are no syntax errors may indicate that a function was declared but never called.
case 'e': {
bool success = false;
- m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
+ m_stop_on_error =
+ OptionArgParser::ToBoolean(option_arg, false, &success);
if (!success)
error.SetErrorStringWithFormat(
"invalid value for stop-on-error: \"%s\"",
@@ -410,8 +412,8 @@ protected:
} else {
BreakpointLocationSP bp_loc_sp(
bp->FindLocationByID(cur_bp_id.GetLocationID()));
- // This breakpoint does have an associated location.
- // Get its breakpoint options.
+ // This breakpoint does have an associated location. Get its
+ // breakpoint options.
if (bp_loc_sp)
bp_options = bp_loc_sp->GetLocationOptions();
}
@@ -420,9 +422,9 @@ protected:
}
}
- // If we are using script language, get the script interpreter
- // in order to set or collect command callback. Otherwise, call
- // the methods associated with this object.
+ // If we are using script language, get the script interpreter in order
+ // to set or collect command callback. Otherwise, call the methods
+ // associated with this object.
if (m_options.m_use_script_language) {
ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
// Special handling for one-liner specified inline.
@@ -454,16 +456,15 @@ private:
std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the
// breakpoint options that
// we are currently
- // collecting commands for. In the CollectData... calls we need
- // to hand this off to the IOHandler, which may run asynchronously.
- // So we have to have some way to keep it alive, and not leak it.
- // Making it an ivar of the command object, which never goes away
- // achieves this. Note that if we were able to run
- // the same command concurrently in one interpreter we'd have to
- // make this "per invocation". But there are many more reasons
- // why it is not in general safe to do that in lldb at present,
- // so it isn't worthwhile to come up with a more complex mechanism
- // to address this particular weakness right now.
+ // collecting commands for. In the CollectData... calls we need to hand this
+ // off to the IOHandler, which may run asynchronously. So we have to have
+ // some way to keep it alive, and not leak it. Making it an ivar of the
+ // command object, which never goes away achieves this. Note that if we were
+ // able to run the same command concurrently in one interpreter we'd have to
+ // make this "per invocation". But there are many more reasons why it is not
+ // in general safe to do that in lldb at present, so it isn't worthwhile to
+ // come up with a more complex mechanism to address this particular weakness
+ // right now.
static const char *g_reader_instructions;
};
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
index c9d71a65754b..333f72056cbc 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
@@ -18,16 +18,17 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectRegexCommand.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/StringList.h"
using namespace lldb;
@@ -234,20 +235,13 @@ public:
return "";
}
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- auto completion_str = input[cursor_index].ref;
- completion_str = completion_str.take_front(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str, match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
Options *GetOptions() override { return &m_options; }
@@ -330,9 +324,8 @@ protected:
m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
} else {
- // No options were set, inherit any settings from nested "command
- // source" commands,
- // or set to sane default settings...
+ // No options were set, inherit any settings from nested "command source"
+ // commands, or set to sane default settings...
CommandInterpreterRunOptions options;
m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
}
@@ -543,9 +536,9 @@ rather than using a positional placeholder:"
~CommandObjectCommandsAlias() override = default;
protected:
- bool DoExecute(const char *raw_command_line,
+ bool DoExecute(llvm::StringRef raw_command_line,
CommandReturnObject &result) override {
- if (!raw_command_line || !raw_command_line[0]) {
+ if (raw_command_line.empty()) {
result.AppendError("'command alias' requires at least two arguments");
return false;
}
@@ -553,42 +546,13 @@ protected:
ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
m_option_group.NotifyOptionParsingStarting(&exe_ctx);
- const char *remainder = nullptr;
-
- if (raw_command_line[0] == '-') {
- // We have some options and these options MUST end with --.
- const char *end_options = nullptr;
- const char *s = raw_command_line;
- while (s && s[0]) {
- end_options = ::strstr(s, "--");
- if (end_options) {
- end_options += 2; // Get past the "--"
- if (::isspace(end_options[0])) {
- remainder = end_options;
- while (::isspace(*remainder))
- ++remainder;
- break;
- }
- }
- s = end_options;
- }
-
- if (end_options) {
- Args args(
- llvm::StringRef(raw_command_line, end_options - raw_command_line));
- if (!ParseOptions(args, result))
- return false;
+ OptionsWithRaw args_with_suffix(raw_command_line);
+ const char *remainder = args_with_suffix.GetRawPart().c_str();
- Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
- if (error.Fail()) {
- result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- }
- if (nullptr == remainder)
- remainder = raw_command_line;
+ if (args_with_suffix.HasArgs())
+ if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
+ m_option_group, exe_ctx))
+ return false;
llvm::StringRef raw_command_string(remainder);
Args args(raw_command_string);
@@ -613,8 +577,7 @@ protected:
}
// Strip the new alias name off 'raw_command_string' (leave it on args,
- // which gets passed to 'Execute', which
- // does the stripping itself.
+ // which gets passed to 'Execute', which does the stripping itself.
size_t pos = raw_command_string.find(alias_command);
if (pos == 0) {
raw_command_string = raw_command_string.substr(alias_command.size());
@@ -652,9 +615,8 @@ protected:
return false;
} else if (!cmd_obj->WantsRawCommandString()) {
// Note that args was initialized with the original command, and has not
- // been updated to this point.
- // Therefore can we pass it to the version of Execute that does not
- // need/expect raw input in the alias.
+ // been updated to this point. Therefore can we pass it to the version of
+ // Execute that does not need/expect raw input in the alias.
return HandleAliasingNormalCommand(args, result);
} else {
return HandleAliasingRawCommand(alias_command, raw_command_string,
@@ -1128,8 +1090,8 @@ protected:
return error;
}
const size_t first_separator_char_pos = 1;
- // use the char that follows 's' as the regex separator character
- // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
+ // use the char that follows 's' as the regex separator character so we can
+ // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
const char separator_char = regex_sed[first_separator_char_pos];
const size_t second_separator_char_pos =
regex_sed.find(separator_char, first_separator_char_pos + 1);
@@ -1158,8 +1120,7 @@ protected:
}
if (third_separator_char_pos != regex_sed_size - 1) {
- // Make sure that everything that follows the last regex
- // separator char
+ // Make sure that everything that follows the last regex separator char
if (regex_sed.find_first_not_of("\t\n\v\f\r ",
third_separator_char_pos + 1) !=
std::string::npos) {
@@ -1307,7 +1268,7 @@ public:
}
protected:
- bool DoExecute(const char *raw_command_line,
+ bool DoExecute(llvm::StringRef raw_command_line,
CommandReturnObject &result) override {
ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
@@ -1396,7 +1357,7 @@ public:
}
protected:
- bool DoExecute(const char *raw_command_line,
+ bool DoExecute(llvm::StringRef raw_command_line,
CommandReturnObject &result) override {
ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
@@ -1462,20 +1423,13 @@ public:
~CommandObjectCommandsScriptImport() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- llvm::StringRef completion_str = input[cursor_index].ref;
- completion_str = completion_str.take_front(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str, match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
Options *GetOptions() override { return &m_options; }
@@ -1540,10 +1494,11 @@ protected:
// FIXME: this is necessary because CommandObject::CheckRequirements()
// assumes that commands won't ever be recursively invoked, but it's
// actually possible to craft a Python script that does other "command
- // script imports" in __lldb_init_module the real fix is to have recursive
- // commands possible with a CommandInvocation object separate from the
- // CommandObject itself, so that recursive command invocations won't stomp
- // on each other (wrt to execution contents, options, and more)
+ // script imports" in __lldb_init_module the real fix is to have
+ // recursive commands possible with a CommandInvocation object separate
+ // from the CommandObject itself, so that recursive command invocations
+ // won't stomp on each other (wrt to execution contents, options, and
+ // more)
m_exe_ctx.Clear();
if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
entry.c_str(), m_options.m_allow_reload, init_session, error)) {
@@ -1639,7 +1594,7 @@ protected:
break;
case 's':
m_synchronicity =
- (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
+ (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
if (!error.Success())
error.SetErrorStringWithFormat(
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp
index 31c54b7d433b..519e5e2dcdb0 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -20,6 +20,7 @@
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
@@ -101,14 +102,14 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
break;
case 's': {
- start_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ start_addr = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
if (start_addr != LLDB_INVALID_ADDRESS)
some_location_specified = true;
} break;
case 'e': {
- end_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ end_addr = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
if (end_addr != LLDB_INVALID_ADDRESS)
some_location_specified = true;
} break;
@@ -125,8 +126,8 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
case 'l':
frame_line = true;
- // Disassemble the current source line kind of implies showing mixed
- // source code context.
+ // Disassemble the current source line kind of implies showing mixed source
+ // code context.
show_mixed = true;
some_location_specified = true;
break;
@@ -160,15 +161,14 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
case 'A':
if (execution_context) {
- auto target_sp =
- execution_context ? execution_context->GetTargetSP() : TargetSP();
- auto platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
- arch = Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
+ const auto &target_sp = execution_context->GetTargetSP();
+ auto platform_ptr = target_sp ? target_sp->GetPlatform().get() : nullptr;
+ arch = Platform::GetAugmentedArchSpec(platform_ptr, option_arg);
}
break;
case 'a': {
- symbol_containing_addr = Args::StringToAddress(
+ symbol_containing_addr = OptionArgParser::ToAddress(
execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
if (symbol_containing_addr != LLDB_INVALID_ADDRESS) {
some_location_specified = true;
@@ -204,10 +204,9 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
execution_context ? execution_context->GetTargetPtr() : nullptr;
// This is a hack till we get the ability to specify features based on
- // architecture. For now GetDisassemblyFlavor
- // is really only valid for x86 (and for the llvm assembler plugin, but I'm
- // papering over that since that is the
- // only disassembler plugin we have...
+ // architecture. For now GetDisassemblyFlavor is really only valid for x86
+ // (and for the llvm assembler plugin, but I'm papering over that since that
+ // is the only disassembler plugin we have...
if (target) {
if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
target->GetArchitecture().GetTriple().getArch() ==
@@ -374,8 +373,8 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
}
}
- // Did the "m_options.frame_line" find a valid range already? If so
- // skip the rest...
+ // Did the "m_options.frame_line" find a valid range already? If so skip
+ // the rest...
if (range.GetByteSize() == 0) {
if (m_options.at_pc) {
if (frame == nullptr) {
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
index 01ca31111555..08959ff8473d 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
@@ -27,6 +27,7 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Language.h"
@@ -88,7 +89,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
case 'a': {
bool success;
bool result;
- result = Args::StringToBoolean(option_arg, true, &success);
+ result = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat(
"invalid all-threads value setting: \"%s\"",
@@ -99,7 +100,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
case 'i': {
bool success;
- bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+ bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
if (success)
ignore_breakpoints = tmp_value;
else
@@ -111,7 +112,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
case 'j': {
bool success;
- bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+ bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
if (success)
allow_jit = tmp_value;
else
@@ -131,7 +132,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
case 'u': {
bool success;
- bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+ bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
if (success)
unwind_on_error = tmp_value;
else
@@ -146,8 +147,8 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
break;
}
- m_verbosity =
- (LanguageRuntimeDescriptionDisplayVerbosity)Args::StringToOptionEnum(
+ m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity)
+ OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
if (!error.Success())
error.SetErrorStringWithFormat(
@@ -167,7 +168,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
case 'X': {
bool success;
- bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+ bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
if (success)
auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
else
@@ -317,13 +318,13 @@ CanBeUsedForElementCountPrinting(ValueObject &valobj) {
return Status();
}
-bool CommandObjectExpression::EvaluateExpression(const char *expr,
+bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
Stream *output_stream,
Stream *error_stream,
CommandReturnObject *result) {
- // Don't use m_exe_ctx as this might be called asynchronously
- // after the command object DoExecute has finished when doing
- // multi-line expression that use an input reader...
+ // Don't use m_exe_ctx as this might be called asynchronously after the
+ // command object DoExecute has finished when doing multi-line expression
+ // that use an input reader...
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
@@ -362,8 +363,8 @@ bool CommandObjectExpression::EvaluateExpression(const char *expr,
if (m_command_options.top_level)
options.SetExecutionPolicy(eExecutionPolicyTopLevel);
- // If there is any chance we are going to stop and want to see
- // what went wrong with our expression, we should generate debug info
+ // If there is any chance we are going to stop and want to see what went
+ // wrong with our expression, we should generate debug info
if (!m_command_options.ignore_breakpoints ||
!m_command_options.unwind_on_error)
options.SetGenerateDebugInfo(true);
@@ -474,9 +475,8 @@ bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler,
// An empty lines is used to indicate the end of input
const size_t num_lines = lines.GetSize();
if (num_lines > 0 && lines[num_lines - 1].empty()) {
- // Remove the last empty line from "lines" so it doesn't appear
- // in our resulting input and return true to indicate we are done
- // getting lines
+ // Remove the last empty line from "lines" so it doesn't appear in our
+ // resulting input and return true to indicate we are done getting lines
lines.PopBack();
return true;
}
@@ -508,125 +508,91 @@ void CommandObjectExpression::GetMultilineExpression() {
debugger.PushIOHandler(io_handler_sp);
}
-bool CommandObjectExpression::DoExecute(const char *command,
+bool CommandObjectExpression::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
m_fixed_expression.clear();
auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
m_option_group.NotifyOptionParsingStarting(&exe_ctx);
- const char *expr = nullptr;
-
- if (command[0] == '\0') {
+ if (command.empty()) {
GetMultilineExpression();
return result.Succeeded();
}
- if (command[0] == '-') {
- // We have some options and these options MUST end with --.
- const char *end_options = nullptr;
- const char *s = command;
- while (s && s[0]) {
- end_options = ::strstr(s, "--");
- if (end_options) {
- end_options += 2; // Get past the "--"
- if (::isspace(end_options[0])) {
- expr = end_options;
- while (::isspace(*expr))
- ++expr;
- break;
- }
- }
- s = end_options;
- }
-
- if (end_options) {
- Args args(llvm::StringRef(command, end_options - command));
- if (!ParseOptions(args, result))
- return false;
-
- Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
- if (error.Fail()) {
- result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_repl_option.GetOptionValue().GetCurrentValue()) {
- Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
- if (target) {
- // Drop into REPL
- m_expr_lines.clear();
- m_expr_line_count = 0;
-
- Debugger &debugger = target->GetDebugger();
-
- // Check if the LLDB command interpreter is sitting on top of a REPL
- // that
- // launched it...
- if (debugger.CheckTopIOHandlerTypes(
- IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL)) {
- // the LLDB command interpreter is sitting on top of a REPL that
- // launched it,
- // so just say the command interpreter is done and fall back to the
- // existing REPL
- m_interpreter.GetIOHandler(false)->SetIsDone(true);
- } else {
- // We are launching the REPL on top of the current LLDB command
- // interpreter,
- // so just push one
- bool initialize = false;
- Status repl_error;
- REPLSP repl_sp(target->GetREPL(
- repl_error, m_command_options.language, nullptr, false));
-
- if (!repl_sp) {
- initialize = true;
- repl_sp = target->GetREPL(repl_error, m_command_options.language,
- nullptr, true);
- if (!repl_error.Success()) {
- result.SetError(repl_error);
- return result.Succeeded();
- }
+ OptionsWithRaw args(command);
+ llvm::StringRef expr = args.GetRawPart();
+
+ if (args.HasArgs()) {
+ if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx))
+ return false;
+
+ if (m_repl_option.GetOptionValue().GetCurrentValue()) {
+ Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
+ if (target) {
+ // Drop into REPL
+ m_expr_lines.clear();
+ m_expr_line_count = 0;
+
+ Debugger &debugger = target->GetDebugger();
+
+ // Check if the LLDB command interpreter is sitting on top of a REPL
+ // that launched it...
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
+ IOHandler::Type::REPL)) {
+ // the LLDB command interpreter is sitting on top of a REPL that
+ // launched it, so just say the command interpreter is done and
+ // fall back to the existing REPL
+ m_interpreter.GetIOHandler(false)->SetIsDone(true);
+ } else {
+ // We are launching the REPL on top of the current LLDB command
+ // interpreter, so just push one
+ bool initialize = false;
+ Status repl_error;
+ REPLSP repl_sp(target->GetREPL(repl_error, m_command_options.language,
+ nullptr, false));
+
+ if (!repl_sp) {
+ initialize = true;
+ repl_sp = target->GetREPL(repl_error, m_command_options.language,
+ nullptr, true);
+ if (!repl_error.Success()) {
+ result.SetError(repl_error);
+ return result.Succeeded();
}
+ }
- if (repl_sp) {
- if (initialize) {
- repl_sp->SetCommandOptions(m_command_options);
- repl_sp->SetFormatOptions(m_format_options);
- repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
- }
+ if (repl_sp) {
+ if (initialize) {
+ repl_sp->SetCommandOptions(m_command_options);
+ repl_sp->SetFormatOptions(m_format_options);
+ repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
+ }
- IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
+ IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
- io_handler_sp->SetIsDone(false);
+ io_handler_sp->SetIsDone(false);
- debugger.PushIOHandler(io_handler_sp);
- } else {
- repl_error.SetErrorStringWithFormat(
- "Couldn't create a REPL for %s",
- Language::GetNameForLanguageType(m_command_options.language));
- result.SetError(repl_error);
- return result.Succeeded();
- }
+ debugger.PushIOHandler(io_handler_sp);
+ } else {
+ repl_error.SetErrorStringWithFormat(
+ "Couldn't create a REPL for %s",
+ Language::GetNameForLanguageType(m_command_options.language));
+ result.SetError(repl_error);
+ return result.Succeeded();
}
}
}
- // No expression following options
- else if (expr == nullptr || expr[0] == '\0') {
- GetMultilineExpression();
- return result.Succeeded();
- }
+ }
+ // No expression following options
+ else if (expr.empty()) {
+ GetMultilineExpression();
+ return result.Succeeded();
}
}
- if (expr == nullptr)
- expr = command;
-
+ Target *target = GetSelectedOrDummyTarget();
if (EvaluateExpression(expr, &(result.GetOutputStream()),
&(result.GetErrorStream()), &result)) {
- Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
- if (!target)
- target = GetDummyTarget();
if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) {
CommandHistory &history = m_interpreter.GetCommandHistory();
@@ -634,18 +600,21 @@ bool CommandObjectExpression::DoExecute(const char *command,
// for expr???)
// If we can it would be nice to show that.
std::string fixed_command("expression ");
- if (expr == command)
- fixed_command.append(m_fixed_expression);
- else {
+ if (args.HasArgs()) {
// Add in any options that might have been in the original command:
- fixed_command.append(command, expr - command);
+ fixed_command.append(args.GetArgStringWithDelimiter());
+ fixed_command.append(m_fixed_expression);
+ } else
fixed_command.append(m_fixed_expression);
- }
history.AppendString(fixed_command);
}
+ // Increment statistics to record this expression evaluation success.
+ target->IncrementStats(StatisticKind::ExpressionSuccessful);
return true;
}
+ // Increment statistics to record this expression evaluation failure.
+ target->IncrementStats(StatisticKind::ExpressionFailure);
result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h
index 0cf2a7263d52..710f87140977 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h
@@ -72,9 +72,9 @@ protected:
bool IOHandlerIsInputComplete(IOHandler &io_handler,
StringList &lines) override;
- bool DoExecute(const char *command, CommandReturnObject &result) override;
+ bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override;
- bool EvaluateExpression(const char *expr, Stream *output_stream,
+ bool EvaluateExpression(llvm::StringRef expr, Stream *output_stream,
Stream *error_stream,
CommandReturnObject *result = NULL);
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
index 0bcc35062968..64de14f2edbf 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
@@ -24,7 +24,6 @@
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
@@ -44,6 +43,7 @@
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
@@ -342,8 +342,8 @@ protected:
frame_idx += m_options.relative_frame_offset;
else {
if (frame_idx == 0) {
- // If you are already at the bottom of the stack, then just warn and
- // don't reset the frame.
+ // If you are already at the bottom of the stack, then just warn
+ // and don't reset the frame.
result.AppendError("Already at the bottom of the stack.");
result.SetStatus(eReturnStatusFailed);
return false;
@@ -463,21 +463,14 @@ public:
Options *GetOptions() override { return &m_option_group; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
// Arguments are the standard source file completer.
- auto completion_str = input[cursor_index].ref;
- completion_str = completion_str.take_front(cursor_char_position);
-
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
- completion_str, match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
@@ -504,16 +497,15 @@ protected:
}
bool DoExecute(Args &command, CommandReturnObject &result) override {
- // No need to check "frame" for validity as eCommandRequiresFrame ensures it
- // is valid
+ // No need to check "frame" for validity as eCommandRequiresFrame ensures
+ // it is valid
StackFrame *frame = m_exe_ctx.GetFramePtr();
Stream &s = result.GetOutputStream();
// Be careful about the stack frame, if any summary formatter runs code, it
- // might clear the StackFrameList
- // for the thread. So hold onto a shared pointer to the frame so it stays
- // alive.
+ // might clear the StackFrameList for the thread. So hold onto a shared
+ // pointer to the frame so it stays alive.
VariableList *variable_list =
frame->GetVariableList(m_option_variable.show_globals);
@@ -547,8 +539,8 @@ protected:
if (!command.empty()) {
VariableList regex_var_list;
- // If we have any args to the variable command, we will make
- // variable objects from them...
+ // If we have any args to the variable command, we will make variable
+ // objects from them...
for (auto &entry : command) {
if (m_option_variable.use_regex) {
const size_t regex_start_index = regex_var_list.GetSize();
@@ -620,9 +612,6 @@ protected:
if (!scope_string.empty())
s.PutCString(scope_string);
-
- // if (format != eFormatDefault)
- // valobj_sp->SetFormat (format);
if (m_option_variable.show_decl && var_sp &&
var_sp->GetDeclaration().GetFile()) {
var_sp->GetDeclaration().DumpStopContext(&s, false);
@@ -680,14 +669,13 @@ protected:
if (m_option_variable.show_scope)
scope_string = GetScopeString(var_sp).str();
- // Use the variable object code to make sure we are
- // using the same APIs as the public API will be
- // using...
+ // Use the variable object code to make sure we are using the same
+ // APIs as the public API will be using...
valobj_sp = frame->GetValueObjectForFrameVariable(
var_sp, m_varobj_options.use_dynamic);
if (valobj_sp) {
- // When dumping all variables, don't print any variables
- // that are not in scope to avoid extra unneeded output
+ // When dumping all variables, don't print any variables that are
+ // not in scope to avoid extra unneeded output
if (valobj_sp->IsInScope()) {
if (!valobj_sp->GetTargetSP()
->GetDisplayRuntimeSupportValues() &&
@@ -723,7 +711,14 @@ protected:
m_interpreter.TruncationWarningGiven();
}
- return result.Succeeded();
+ // Increment statistics.
+ bool res = result.Succeeded();
+ Target *target = GetSelectedOrDummyTarget();
+ if (res)
+ target->IncrementStats(StatisticKind::FrameVarSuccess);
+ else
+ target->IncrementStats(StatisticKind::FrameVarFailure);
+ return res;
}
protected:
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.cpp
index 99e9d7b3abd4..903c6011b03f 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.cpp
@@ -89,10 +89,9 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {
CommandObject *cmd_obj;
const size_t argc = command.GetArgumentCount();
- // 'help' doesn't take any arguments, other than command names. If argc is 0,
- // we show the user
- // all commands (aliases and user commands if asked for). Otherwise every
- // argument must be the name of a command or a sub-command.
+ // 'help' doesn't take any arguments, other than command names. If argc is
+ // 0, we show the user all commands (aliases and user commands if asked for).
+ // Otherwise every argument must be the name of a command or a sub-command.
if (argc == 0) {
uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
if (m_options.m_show_aliases)
@@ -210,34 +209,24 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {
return result.Succeeded();
}
-int CommandObjectHelp::HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches) {
+int CommandObjectHelp::HandleCompletion(CompletionRequest &request) {
// Return the completions of the commands in the help system:
- if (cursor_index == 0) {
- return m_interpreter.HandleCompletionMatches(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ if (request.GetCursorIndex() == 0) {
+ return m_interpreter.HandleCompletionMatches(request);
} else {
- CommandObject *cmd_obj = m_interpreter.GetCommandObject(input[0].ref);
+ CommandObject *cmd_obj =
+ m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref);
// The command that they are getting help on might be ambiguous, in which
- // case we should complete that,
- // otherwise complete with the command the user is getting help on...
+ // case we should complete that, otherwise complete with the command the
+ // user is getting help on...
if (cmd_obj) {
- input.Shift();
- cursor_index--;
- return cmd_obj->HandleCompletion(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ request.GetParsedLine().Shift();
+ request.SetCursorIndex(request.GetCursorIndex() - 1);
+ return cmd_obj->HandleCompletion(request);
} else {
- return m_interpreter.HandleCompletionMatches(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ return m_interpreter.HandleCompletionMatches(request);
}
}
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h
index f1f87f8e63cc..c78682dead1f 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h
@@ -30,10 +30,7 @@ public:
~CommandObjectHelp() override;
- int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) override;
+ int HandleCompletion(CompletionRequest &request) override;
static void GenerateAdditionalHelpAvenuesMessage(
Stream *s, llvm::StringRef command, llvm::StringRef prefix,
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp
index ef82d07f15fb..1389ff2bde02 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp
@@ -16,9 +16,9 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -26,6 +26,7 @@
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
@@ -100,7 +101,7 @@ public:
switch (short_option) {
case 'f':
- log_file.SetFile(option_arg, true);
+ log_file.SetFile(option_arg, true, FileSpec::Style::native);
break;
case 't':
log_options |= LLDB_LOG_OPTION_THREADSAFE;
@@ -345,7 +346,7 @@ protected:
}
} else if (sub_command.equals_lower("increment")) {
bool success;
- bool increment = Args::StringToBoolean(param, false, &success);
+ bool increment = OptionArgParser::ToBoolean(param, false, &success);
if (success) {
Timer::SetQuiet(!increment);
result.SetStatus(eReturnStatusSuccessFinishNoResult);
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
index 8f4c186a8d69..e4a49e55857d 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
@@ -24,9 +24,9 @@
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupOutputFile.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
@@ -40,6 +40,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/StreamString.h"
@@ -553,8 +554,8 @@ protected:
lldb::addr_t addr;
size_t total_byte_size = 0;
if (argc == 0) {
- // Use the last address and byte size and all options as they were
- // if no options have been set
+ // Use the last address and byte size and all options as they were if no
+ // options have been set
addr = m_next_addr;
total_byte_size = m_prev_byte_size;
clang_ast_type = m_prev_clang_ast_type;
@@ -573,8 +574,8 @@ protected:
// TODO For non-8-bit byte addressable architectures this needs to be
// revisited to fully support all lldb's range of formatting options.
- // Furthermore code memory reads (for those architectures) will not
- // be correctly formatted even w/o formatting options.
+ // Furthermore code memory reads (for those architectures) will not be
+ // correctly formatted even w/o formatting options.
size_t item_byte_size =
target->GetArchitecture().GetDataByteSize() > 1
? target->GetArchitecture().GetDataByteSize()
@@ -590,8 +591,8 @@ protected:
}
if (argc > 0)
- addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
- LLDB_INVALID_ADDRESS, &error);
+ addr = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref,
+ LLDB_INVALID_ADDRESS, &error);
if (addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid start address expression.");
@@ -601,7 +602,7 @@ protected:
}
if (argc == 2) {
- lldb::addr_t end_addr = Args::StringToAddress(
+ lldb::addr_t end_addr = OptionArgParser::ToAddress(
&m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, nullptr);
if (end_addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid end address expression.");
@@ -843,16 +844,14 @@ protected:
if (!m_format_options.GetCountValue().OptionWasSet() || item_count == 1) {
// this turns requests such as
// memory read -fc -s10 -c1 *charPtrPtr
- // which make no sense (what is a char of size 10?)
- // into a request for fetching 10 chars of size 1 from the same memory
- // location
+ // which make no sense (what is a char of size 10?) into a request for
+ // fetching 10 chars of size 1 from the same memory location
format = eFormatCharArray;
item_count = item_byte_size;
item_byte_size = 1;
} else {
- // here we passed a count, and it was not 1
- // so we have a byte_size and a count
- // we could well multiply those, but instead let's just fail
+ // here we passed a count, and it was not 1 so we have a byte_size and
+ // a count we could well multiply those, but instead let's just fail
result.AppendErrorWithFormat(
"reading memory as characters of size %" PRIu64 " is not supported",
(uint64_t)item_byte_size);
@@ -1036,13 +1035,13 @@ protected:
}
Status error;
- lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
- LLDB_INVALID_ADDRESS, &error);
+ lldb::addr_t low_addr = OptionArgParser::ToAddress(
+ &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error);
if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) {
result.AppendError("invalid low address");
return false;
}
- lldb::addr_t high_addr = Args::StringToAddress(
+ lldb::addr_t high_addr = OptionArgParser::ToAddress(
&m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, &error);
if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) {
result.AppendError("invalid high address");
@@ -1210,7 +1209,7 @@ public:
switch (short_option) {
case 'i':
- m_infile.SetFile(option_value, true);
+ m_infile.SetFile(option_value, true, FileSpec::Style::native);
if (!m_infile.Exists()) {
m_infile.Clear();
error.SetErrorStringWithFormat("input file does not exist: '%s'",
@@ -1345,8 +1344,8 @@ protected:
size_t item_byte_size = byte_size_value.GetCurrentValue();
Status error;
- lldb::addr_t addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
- LLDB_INVALID_ADDRESS, &error);
+ lldb::addr_t addr = OptionArgParser::ToAddress(
+ &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error);
if (addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid address expression\n");
@@ -1469,7 +1468,7 @@ protected:
break;
}
case eFormatBoolean:
- uval64 = Args::StringToBoolean(entry.ref, false, &success);
+ uval64 = OptionArgParser::ToBoolean(entry.ref, false, &success);
if (!success) {
result.AppendErrorWithFormat(
"'%s' is not a valid boolean string value.\n", entry.c_str());
@@ -1642,8 +1641,8 @@ protected:
}
Status error;
- lldb::addr_t addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
- LLDB_INVALID_ADDRESS, &error);
+ lldb::addr_t addr = OptionArgParser::ToAddress(
+ &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error);
if (addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid address expression");
@@ -1709,10 +1708,10 @@ protected:
m_cmd_name.c_str(), m_cmd_syntax.c_str());
result.SetStatus(eReturnStatusFailed);
} else {
- auto load_addr_str = command[0].ref;
if (command.GetArgumentCount() == 1) {
- load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_str,
- LLDB_INVALID_ADDRESS, &error);
+ auto load_addr_str = command[0].ref;
+ load_addr = OptionArgParser::ToAddress(&m_exe_ctx, load_addr_str,
+ LLDB_INVALID_ADDRESS, &error);
if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) {
result.AppendErrorWithFormat(
"invalid address argument \"%s\": %s\n", command[0].c_str(),
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
index 0d0aa108a4ce..19fcf60e557c 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
@@ -55,8 +55,7 @@ CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
if (num_matches == 1) {
// Cleaner, but slightly less efficient would be to call back into this
- // function, since I now
- // know I have an exact match...
+ // function, since I now know I have an exact match...
sub_cmd = matches->GetStringAtIndex(0);
pos = m_subcommand_dict.find(sub_cmd);
@@ -121,8 +120,8 @@ bool CommandObjectMultiword::Execute(const char *args_string,
CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
if (sub_cmd_obj != nullptr) {
// Now call CommandObject::Execute to process options in `rest_of_line`.
- // From there the command-specific version of Execute will be called,
- // with the processed arguments.
+ // From there the command-specific version of Execute will be called, with
+ // the processed arguments.
args.Shift();
sub_cmd_obj->Execute(args_string, result);
@@ -144,7 +143,7 @@ bool CommandObjectMultiword::Execute(const char *args_string,
if (num_subcmd_matches > 0) {
error_msg.append(" Possible completions:");
- for (size_t i = 0; i < num_subcmd_matches; i++) {
+ for (size_t i = 0; i < matches.GetSize(); i++) {
error_msg.append("\n\t");
error_msg.append(matches.GetStringAtIndex(i));
}
@@ -156,8 +155,8 @@ bool CommandObjectMultiword::Execute(const char *args_string,
}
void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
- // First time through here, generate the help text for the object and
- // push it to the return result object as well
+ // First time through here, generate the help text for the object and push it
+ // to the return result object as well
CommandObject::GenerateHelpText(output_stream);
output_stream.PutCString("\nThe following subcommands are supported:\n\n");
@@ -187,51 +186,47 @@ void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
"'help <command> <subcommand>'.\n");
}
-int CommandObjectMultiword::HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches) {
+int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
// Any of the command matches will provide a complete word, otherwise the
// individual completers will override this.
- word_complete = true;
+ request.SetWordComplete(true);
- auto arg0 = input[0].ref;
- if (cursor_index == 0) {
- AddNamesMatchingPartialString(m_subcommand_dict, arg0, matches);
+ auto arg0 = request.GetParsedLine()[0].ref;
+ if (request.GetCursorIndex() == 0) {
+ StringList new_matches;
+ AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches);
+ request.AddCompletions(new_matches);
- if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != nullptr &&
- (arg0 == matches.GetStringAtIndex(0))) {
+ if (new_matches.GetSize() == 1 &&
+ new_matches.GetStringAtIndex(0) != nullptr &&
+ (arg0 == new_matches.GetStringAtIndex(0))) {
StringList temp_matches;
CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
if (cmd_obj != nullptr) {
- if (input.GetArgumentCount() == 1) {
- word_complete = true;
+ if (request.GetParsedLine().GetArgumentCount() == 1) {
+ request.SetWordComplete(true);
} else {
- matches.DeleteStringAtIndex(0);
- input.Shift();
- cursor_char_position = 0;
- input.AppendArgument(llvm::StringRef());
- return cmd_obj->HandleCompletion(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ request.GetParsedLine().Shift();
+ request.SetCursorCharPosition(0);
+ request.GetParsedLine().AppendArgument(llvm::StringRef());
+ return cmd_obj->HandleCompletion(request);
}
}
}
- return matches.GetSize();
+ return new_matches.GetSize();
} else {
- CommandObject *sub_command_object = GetSubcommandObject(arg0, &matches);
+ StringList new_matches;
+ CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);
if (sub_command_object == nullptr) {
- return matches.GetSize();
+ request.AddCompletions(new_matches);
+ return request.GetNumberOfMatches();
} else {
// Remove the one match that we got from calling GetSubcommandObject.
- matches.DeleteStringAtIndex(0);
- input.Shift();
- cursor_index--;
- return sub_command_object->HandleCompletion(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ new_matches.DeleteStringAtIndex(0);
+ request.AddCompletions(new_matches);
+ request.GetParsedLine().Shift();
+ request.SetCursorIndex(request.GetCursorIndex() - 1);
+ return sub_command_object->HandleCompletion(request);
}
}
}
@@ -371,31 +366,18 @@ Options *CommandObjectProxy::GetOptions() {
return nullptr;
}
-int CommandObjectProxy::HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches) {
+int CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
CommandObject *proxy_command = GetProxyCommandObject();
if (proxy_command)
- return proxy_command->HandleCompletion(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
- matches.Clear();
+ return proxy_command->HandleCompletion(request);
return 0;
}
int CommandObjectProxy::HandleArgumentCompletion(
- Args &input, int &cursor_index, int &cursor_char_position,
- OptionElementVector &opt_element_vector, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
+ CompletionRequest &request, OptionElementVector &opt_element_vector) {
CommandObject *proxy_command = GetProxyCommandObject();
if (proxy_command)
- return proxy_command->HandleArgumentCompletion(
- input, cursor_index, cursor_char_position, opt_element_vector,
- match_start_point, max_return_elements, word_complete, matches);
- matches.Clear();
+ return proxy_command->HandleArgumentCompletion(request, opt_element_vector);
return 0;
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp
index 8ed003767d58..22a9a169c7c8 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -18,7 +18,6 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionValidators.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -27,6 +26,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "llvm/ADT/SmallString.h"
@@ -178,17 +178,10 @@ public:
~CommandObjectPlatformSelect() override = default;
- int HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
-
- CommandCompletions::PlatformPluginNames(
- GetCommandInterpreter(), completion_str.c_str(), match_start_point,
- max_return_elements, nullptr, word_complete, matches);
- return matches.GetSize();
+ int HandleCompletion(CompletionRequest &request) override {
+ CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request,
+ nullptr);
+ return request.GetNumberOfMatches();
}
Options *GetOptions() override { return &m_option_group; }
@@ -385,8 +378,8 @@ protected:
Status error;
if (platform_sp->IsConnected()) {
- // Cache the instance name if there is one since we are
- // about to disconnect and the name might go with it.
+ // Cache the instance name if there is one since we are about to
+ // disconnect and the name might go with it.
const char *hostname_cstr = platform_sp->GetHostname();
std::string hostname;
if (hostname_cstr)
@@ -867,8 +860,8 @@ public:
// argument entry.
arg2.push_back(file_arg_host);
- // Push the data for the first and the second arguments into the m_arguments
- // vector.
+ // Push the data for the first and the second arguments into the
+ // m_arguments vector.
m_arguments.push_back(arg1);
m_arguments.push_back(arg2);
}
@@ -1059,8 +1052,8 @@ protected:
if (argc > 0) {
if (m_options.launch_info.GetExecutableFile()) {
- // We already have an executable file, so we will use this
- // and all arguments to this function are extra arguments
+ // We already have an executable file, so we will use this and all
+ // arguments to this function are extra arguments
m_options.launch_info.GetArguments().AppendArguments(args);
} else {
// We don't have any file yet, so the first argument is our
@@ -1342,32 +1335,32 @@ protected:
} break;
case 'n':
- match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
- false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ option_arg, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::Equals);
break;
case 'e':
- match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
- false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ option_arg, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::EndsWith);
break;
case 's':
- match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
- false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ option_arg, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::StartsWith);
break;
case 'c':
- match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
- false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ option_arg, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::Contains);
break;
case 'r':
- match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
- false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ option_arg, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::RegularExpression);
break;
@@ -1536,7 +1529,8 @@ public:
break;
case 'n':
- attach_info.GetExecutableFile().SetFile(option_arg, false);
+ attach_info.GetExecutableFile().SetFile(option_arg, false,
+ FileSpec::Style::native);
break;
case 'w':
@@ -1560,11 +1554,8 @@ public:
}
bool HandleOptionArgumentCompletion(
- Args &input, int cursor_index, int char_pos,
- OptionElementVector &opt_element_vector, int opt_element_index,
- int match_start_point, int max_return_elements,
- CommandInterpreter &interpreter, bool &word_complete,
- StringList &matches) override {
+ CompletionRequest &request, OptionElementVector &opt_element_vector,
+ int opt_element_index, CommandInterpreter &interpreter) override {
int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
@@ -1574,11 +1565,10 @@ public:
// Are we in the name?
// Look to see if there is a -P argument provided, and if so use that
- // plugin, otherwise
- // use the default plugin.
+ // plugin, otherwise use the default plugin.
const char *partial_name = nullptr;
- partial_name = input.GetArgumentAtIndex(opt_arg_pos);
+ partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
PlatformSP platform_sp(interpreter.GetPlatform(true));
if (platform_sp) {
@@ -1586,16 +1576,16 @@ public:
ProcessInstanceInfoMatch match_info;
if (partial_name) {
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- partial_name, false);
+ partial_name, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::StartsWith);
}
platform_sp->FindProcesses(match_info, process_infos);
const uint32_t num_matches = process_infos.GetSize();
if (num_matches > 0) {
for (uint32_t i = 0; i < num_matches; ++i) {
- matches.AppendString(
+ request.AddCompletion(llvm::StringRef(
process_infos.GetProcessNameAtIndex(i),
- process_infos.GetProcessNameLengthAtIndex(i));
+ process_infos.GetProcessNameLengthAtIndex(i)));
}
}
}
@@ -1693,7 +1683,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), timeout(10) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -1709,11 +1699,13 @@ public:
switch (short_option) {
case 't':
- timeout = 10;
- if (option_arg.getAsInteger(10, timeout))
+ uint32_t timeout_sec;
+ if (option_arg.getAsInteger(10, timeout_sec))
error.SetErrorStringWithFormat(
"could not convert \"%s\" to a numeric value.",
option_arg.str().c_str());
+ else
+ timeout = std::chrono::seconds(timeout_sec);
break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'",
@@ -1726,7 +1718,7 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {}
- uint32_t timeout;
+ Timeout<std::micro> timeout = std::chrono::seconds(10);
};
CommandObjectPlatformShell(CommandInterpreter &interpreter)
@@ -1739,47 +1731,24 @@ public:
Options *GetOptions() override { return &m_options; }
- bool DoExecute(const char *raw_command_line,
+ bool DoExecute(llvm::StringRef raw_command_line,
CommandReturnObject &result) override {
ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
m_options.NotifyOptionParsingStarting(&exe_ctx);
- const char *expr = nullptr;
// Print out an usage syntax on an empty command line.
- if (raw_command_line[0] == '\0') {
+ if (raw_command_line.empty()) {
result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
return true;
}
- if (raw_command_line[0] == '-') {
- // We have some options and these options MUST end with --.
- const char *end_options = nullptr;
- const char *s = raw_command_line;
- while (s && s[0]) {
- end_options = ::strstr(s, "--");
- if (end_options) {
- end_options += 2; // Get past the "--"
- if (::isspace(end_options[0])) {
- expr = end_options;
- while (::isspace(*expr))
- ++expr;
- break;
- }
- }
- s = end_options;
- }
-
- if (end_options) {
- Args args(
- llvm::StringRef(raw_command_line, end_options - raw_command_line));
- if (!ParseOptions(args, result))
- return false;
- }
- }
+ OptionsWithRaw args(raw_command_line);
+ const char *expr = args.GetRawPart().c_str();
- if (expr == nullptr)
- expr = raw_command_line;
+ if (args.HasArgs())
+ if (!ParseOptions(args.GetArgs(), result))
+ return false;
PlatformSP platform_sp(
m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp
index 7e1b7f61f766..13ef6b227c5b 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp
@@ -42,20 +42,13 @@ public:
~CommandObjectPluginLoad() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- auto completion_str = input[cursor_index].ref;
- completion_str = completion_str.take_front(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str, match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp
index 9fbdd7630548..eb5a19aa4d39 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp
@@ -21,9 +21,9 @@
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -31,6 +31,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -133,20 +134,14 @@ public:
~CommandObjectProcessLaunch() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
Options *GetOptions() override { return &m_options; }
@@ -179,18 +174,18 @@ protected:
llvm::StringRef target_settings_argv0 = target->GetArg0();
// Determine whether we will disable ASLR or leave it in the default state
- // (i.e. enabled if the platform supports it).
- // First check if the process launch options explicitly turn on/off
+ // (i.e. enabled if the platform supports it). First check if the process
+ // launch options explicitly turn on/off
// disabling ASLR. If so, use that setting;
// otherwise, use the 'settings target.disable-aslr' setting.
bool disable_aslr = false;
if (m_options.disable_aslr != eLazyBoolCalculate) {
- // The user specified an explicit setting on the process launch line. Use
- // it.
+ // The user specified an explicit setting on the process launch line.
+ // Use it.
disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
} else {
- // The user did not explicitly specify whether to disable ASLR. Fall back
- // to the target.disable-aslr setting.
+ // The user did not explicitly specify whether to disable ASLR. Fall
+ // back to the target.disable-aslr setting.
disable_aslr = target->GetDisableASLR();
}
@@ -205,11 +200,7 @@ protected:
if (target->GetDisableSTDIO())
m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
- Args environment;
- target->GetEnvironmentAsArgs(environment);
- if (environment.GetArgumentCount() > 0)
- m_options.launch_info.GetEnvironmentEntries().AppendArguments(
- environment);
+ m_options.launch_info.GetEnvironment() = target->GetEnvironment();
if (!target_settings_argv0.empty()) {
m_options.launch_info.GetArguments().AppendArgument(
@@ -237,11 +228,10 @@ protected:
ProcessSP process_sp(target->GetProcessSP());
if (process_sp) {
// There is a race condition where this thread will return up the call
- // stack to the main command
- // handler and show an (lldb) prompt before HandlePrivateEvent (from
- // PrivateStateThread) has
- // a chance to call PushProcessIOHandler().
- process_sp->SyncIOHandler(0, 2000);
+ // stack to the main command handler and show an (lldb) prompt before
+ // HandlePrivateEvent (from PrivateStateThread) has a chance to call
+ // PushProcessIOHandler().
+ process_sp->SyncIOHandler(0, std::chrono::seconds(2));
llvm::StringRef data = stream.GetString();
if (!data.empty())
@@ -362,7 +352,8 @@ public:
break;
case 'n':
- attach_info.GetExecutableFile().SetFile(option_arg, false);
+ attach_info.GetExecutableFile().SetFile(option_arg, false,
+ FileSpec::Style::native);
break;
case 'w':
@@ -390,11 +381,8 @@ public:
}
bool HandleOptionArgumentCompletion(
- Args &input, int cursor_index, int char_pos,
- OptionElementVector &opt_element_vector, int opt_element_index,
- int match_start_point, int max_return_elements,
- CommandInterpreter &interpreter, bool &word_complete,
- StringList &matches) override {
+ CompletionRequest &request, OptionElementVector &opt_element_vector,
+ int opt_element_index, CommandInterpreter &interpreter) override {
int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
@@ -404,11 +392,10 @@ public:
// Are we in the name?
// Look to see if there is a -P argument provided, and if so use that
- // plugin, otherwise
- // use the default plugin.
+ // plugin, otherwise use the default plugin.
const char *partial_name = nullptr;
- partial_name = input.GetArgumentAtIndex(opt_arg_pos);
+ partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
PlatformSP platform_sp(interpreter.GetPlatform(true));
if (platform_sp) {
@@ -416,16 +403,16 @@ public:
ProcessInstanceInfoMatch match_info;
if (partial_name) {
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- partial_name, false);
+ partial_name, false, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::StartsWith);
}
platform_sp->FindProcesses(match_info, process_infos);
const size_t num_matches = process_infos.GetSize();
if (num_matches > 0) {
for (size_t i = 0; i < num_matches; ++i) {
- matches.AppendString(
+ request.AddCompletion(llvm::StringRef(
process_infos.GetProcessNameAtIndex(i),
- process_infos.GetProcessNameLengthAtIndex(i));
+ process_infos.GetProcessNameLengthAtIndex(i)));
}
}
}
@@ -456,10 +443,9 @@ protected:
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
// N.B. The attach should be synchronous. It doesn't help much to get the
- // prompt back between initiating the attach
- // and the target actually stopping. So even if the interpreter is set to
- // be asynchronous, we wait for the stop
- // ourselves here.
+ // prompt back between initiating the attach and the target actually
+ // stopping. So even if the interpreter is set to be asynchronous, we wait
+ // for the stop ourselves here.
StateType state = eStateInvalid;
Process *process = m_exe_ctx.GetProcessPtr();
@@ -485,9 +471,8 @@ protected:
}
// Record the old executable module, we want to issue a warning if the
- // process of attaching changed the
- // current executable (like somebody said "file foo" then attached to a PID
- // whose executable was bar.)
+ // process of attaching changed the current executable (like somebody said
+ // "file foo" then attached to a PID whose executable was bar.)
ModuleSP old_exec_module_sp = target->GetExecutableModule();
ArchSpec old_arch_spec = target->GetArchitecture();
@@ -556,8 +541,8 @@ protected:
target->GetArchitecture().GetTriple().getTriple().c_str());
}
- // This supports the use-case scenario of immediately continuing the process
- // once attached.
+ // This supports the use-case scenario of immediately continuing the
+ // process once attached.
if (m_options.attach_info.GetContinueOnceAttached())
m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
@@ -695,11 +680,10 @@ protected:
if (error.Success()) {
// There is a race condition where this thread will return up the call
- // stack to the main command
- // handler and show an (lldb) prompt before HandlePrivateEvent (from
- // PrivateStateThread) has
- // a chance to call PushProcessIOHandler().
- process->SyncIOHandler(iohandler_id, 2000);
+ // stack to the main command handler and show an (lldb) prompt before
+ // HandlePrivateEvent (from PrivateStateThread) has a chance to call
+ // PushProcessIOHandler().
+ process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
process->GetID());
@@ -760,7 +744,7 @@ public:
case 's':
bool tmp_result;
bool success;
- tmp_result = Args::StringToBoolean(option_arg, false, &success);
+ tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
if (!success)
error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
option_arg.str().c_str());
@@ -991,7 +975,7 @@ public:
case 'i':
do_install = true;
if (!option_arg.empty())
- install_path.SetFile(option_arg, false);
+ install_path.SetFile(option_arg, false, FileSpec::Style::native);
break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'",
@@ -1444,7 +1428,7 @@ public:
bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
bool okay = true;
bool success = false;
- bool tmp_value = Args::StringToBoolean(option, false, &success);
+ bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
if (success && tmp_value)
real_value = 1;
@@ -1563,8 +1547,7 @@ protected:
int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
// Casting the actions as bools here should be okay, because
- // VerifyCommandOptionValue guarantees
- // the value is either 0 or 1.
+ // VerifyCommandOptionValue guarantees the value is either 0 or 1.
if (stop_action != -1)
signals_sp->SetShouldStop(signo, stop_action);
if (pass_action != -1) {
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp
index be55dab61683..37ed12be358f 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp
@@ -16,6 +16,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/StreamString.h"
using namespace lldb;
using namespace lldb_private;
@@ -26,14 +27,13 @@ using namespace lldb_private;
CommandObjectQuit::CommandObjectQuit(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.",
- "quit") {}
+ "quit [exit-code]") {}
CommandObjectQuit::~CommandObjectQuit() {}
-// returns true if there is at least one alive process
-// is_a_detach will be true if all alive processes will be detached when you
-// quit
-// and false if at least one process will be killed instead
+// returns true if there is at least one alive process is_a_detach will be true
+// if all alive processes will be detached when you quit and false if at least
+// one process will be killed instead
bool CommandObjectQuit::ShouldAskForConfirmation(bool &is_a_detach) {
if (m_interpreter.GetPromptOnQuit() == false)
return false;
@@ -78,6 +78,41 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) {
return false;
}
}
+
+ if (command.GetArgumentCount() > 1) {
+ result.AppendError("Too many arguments for 'quit'. Only an optional exit "
+ "code is allowed");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() > 1) {
+ result.AppendError("Too many arguments for 'quit'. Only an optional exit "
+ "code is allowed");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ // We parse the exit code argument if there is one.
+ if (command.GetArgumentCount() == 1) {
+ llvm::StringRef arg = command.GetArgumentAtIndex(0);
+ int exit_code;
+ if (arg.getAsInteger(/*autodetect radix*/ 0, exit_code)) {
+ lldb_private::StreamString s;
+ std::string arg_str = arg.str();
+ s.Printf("Couldn't parse '%s' as integer for exit code.", arg_str.data());
+ result.AppendError(s.GetString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ if (!m_interpreter.SetQuitExitCode(exit_code)) {
+ result.AppendError("The current driver doesn't allow custom exit codes"
+ " for the quit command.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
const uint32_t event_type =
CommandInterpreter::eBroadcastBitQuitCommandReceived;
m_interpreter.BroadcastEvent(event_type);
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp
index d535742016ac..4dadc5d68d20 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp
@@ -9,10 +9,10 @@
#include "CommandObjectRegister.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
@@ -25,6 +25,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "llvm/Support/Errno.h"
@@ -92,8 +93,8 @@ public:
bool prefix_with_altname = (bool)m_command_options.alternate_name;
bool prefix_with_name = !prefix_with_altname;
- reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname,
- m_format_options.GetFormat(), 8);
+ DumpRegisterValue(reg_value, &strm, reg_info, prefix_with_name,
+ prefix_with_altname, m_format_options.GetFormat(), 8);
if ((reg_info->encoding == eEncodingUint) ||
(reg_info->encoding == eEncodingSint)) {
Process *process = exe_ctx.GetProcessPtr();
@@ -192,8 +193,8 @@ protected:
num_register_sets = reg_ctx->GetRegisterSetCount();
for (set_idx = 0; set_idx < num_register_sets; ++set_idx) {
- // When dump_all_sets option is set, dump primitive as well as derived
- // registers.
+ // When dump_all_sets option is set, dump primitive as well as
+ // derived registers.
DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx,
!m_command_options.dump_all_sets.GetCurrentValue());
}
@@ -209,8 +210,8 @@ protected:
result.SetStatus(eReturnStatusFailed);
} else {
for (auto &entry : command) {
- // in most LLDB commands we accept $rbx as the name for register RBX -
- // and here we would reject it and non-existant. we should be more
+ // in most LLDB commands we accept $rbx as the name for register RBX
+ // - and here we would reject it and non-existant. we should be more
// consistent towards the user and allow them to say reg read $rbx -
// internally, however, we should be strict and not allow ourselves
// to call our registers $rbx in our own API
@@ -350,11 +351,11 @@ protected:
auto reg_name = command[0].ref;
auto value_str = command[1].ref;
- // in most LLDB commands we accept $rbx as the name for register RBX - and
- // here we would reject it and non-existant. we should be more consistent
- // towards the user and allow them to say reg write $rbx - internally,
- // however, we should be strict and not allow ourselves to call our
- // registers $rbx in our own API
+ // in most LLDB commands we accept $rbx as the name for register RBX -
+ // and here we would reject it and non-existant. we should be more
+ // consistent towards the user and allow them to say reg write $rbx -
+ // internally, however, we should be strict and not allow ourselves to
+ // call our registers $rbx in our own API
reg_name.consume_front("$");
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
@@ -365,8 +366,8 @@ protected:
Status error(reg_value.SetValueFromString(reg_info, value_str));
if (error.Success()) {
if (reg_ctx->WriteRegister(reg_info, reg_value)) {
- // Toss all frames and anything else in the thread
- // after a register has been written.
+ // Toss all frames and anything else in the thread after a register
+ // has been written.
m_exe_ctx.GetThreadRef().Flush();
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp
index d42466cd13b1..3db1e35cd702 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp
@@ -133,32 +133,27 @@ insert-before or insert-after.");
bool m_global;
};
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
- const size_t argc = input.GetArgumentCount();
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+
+ const size_t argc = request.GetParsedLine().GetArgumentCount();
const char *arg = nullptr;
int setting_var_idx;
- for (setting_var_idx = 1; setting_var_idx < static_cast<int>(argc);
+ for (setting_var_idx = 0; setting_var_idx < static_cast<int>(argc);
++setting_var_idx) {
- arg = input.GetArgumentAtIndex(setting_var_idx);
+ arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
if (arg && arg[0] != '-')
break; // We found our setting variable name index
}
- if (cursor_index == setting_var_idx) {
+ if (request.GetCursorIndex() == setting_var_idx) {
// Attempting to complete setting variable name
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
+ request, nullptr);
} else {
- arg = input.GetArgumentAtIndex(cursor_index);
+ arg =
+ request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
if (arg) {
if (arg[0] == '-') {
@@ -166,24 +161,23 @@ insert-before or insert-after.");
} else {
// Complete setting value
const char *setting_var_name =
- input.GetArgumentAtIndex(setting_var_idx);
+ request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
Status error;
lldb::OptionValueSP value_sp(
m_interpreter.GetDebugger().GetPropertyValue(
&m_exe_ctx, setting_var_name, false, error));
if (value_sp) {
- value_sp->AutoComplete(m_interpreter, completion_str.c_str(),
- match_start_point, max_return_elements,
- word_complete, matches);
+ value_sp->AutoComplete(m_interpreter, request);
}
}
}
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
Args cmd_args(command);
// Process possible options.
@@ -220,10 +214,8 @@ protected:
if (error.Success()) {
// FIXME this is the same issue as the one in commands script import
// we could be setting target.load-script-from-symbol-file which would
- // cause
- // Python scripts to be loaded, which could run LLDB commands
- // (e.g. settings set target.process.python-os-plugin-path) and cause a
- // crash
+ // cause Python scripts to be loaded, which could run LLDB commands (e.g.
+ // settings set target.process.python-os-plugin-path) and cause a crash
// if we did not clear the command's exe_ctx first
ExecutionContext exe_ctx(m_exe_ctx);
m_exe_ctx.Clear();
@@ -274,20 +266,13 @@ public:
~CommandObjectSettingsShow() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
@@ -347,20 +332,13 @@ public:
~CommandObjectSettingsList() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
@@ -442,26 +420,19 @@ public:
~CommandObjectSettingsRemove() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
- // Attempting to complete variable name
- if (cursor_index < 2)
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ if (request.GetCursorIndex() < 2)
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
Args cmd_args(command);
@@ -564,27 +535,21 @@ public:
// !WantsRawCommandString.
bool WantsCompletion() override { return true; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
// Attempting to complete variable name
- if (cursor_index < 2)
+ if (request.GetCursorIndex() < 2)
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
+ request, nullptr);
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
Args cmd_args(command);
@@ -670,27 +635,21 @@ public:
// !WantsRawCommandString.
bool WantsCompletion() override { return true; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
// Attempting to complete variable name
- if (cursor_index < 2)
+ if (request.GetCursorIndex() < 2)
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
+ request, nullptr);
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
Args cmd_args(command);
@@ -781,27 +740,21 @@ public:
// !WantsRawCommandString.
bool WantsCompletion() override { return true; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
// Attempting to complete variable name
- if (cursor_index < 2)
+ if (request.GetCursorIndex() < 2)
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
+ request, nullptr);
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
Args cmd_args(command);
@@ -881,27 +834,21 @@ public:
// !WantsRawCommandString.
bool WantsCompletion() override { return true; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
// Attempting to complete variable name
- if (cursor_index < 2)
+ if (request.GetCursorIndex() < 2)
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
+ request, nullptr);
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
Args cmd_args(command);
const size_t argc = cmd_args.GetArgumentCount();
@@ -920,8 +867,8 @@ protected:
return false;
}
- // Do not perform cmd_args.Shift() since StringRef is manipulating the
- // raw character string later on.
+ // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
+ // character string later on.
// Split the raw command into var_name and value pair.
llvm::StringRef raw_str(command);
@@ -968,23 +915,16 @@ public:
~CommandObjectSettingsClear() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
// Attempting to complete variable name
- if (cursor_index < 2)
+ if (request.GetCursorIndex() < 2)
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
- completion_str.c_str(), match_start_point, max_return_elements,
- nullptr, word_complete, matches);
+ request, nullptr);
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
protected:
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp
index 066cc59c5c31..19e2e441c241 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp
@@ -22,6 +22,7 @@
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
@@ -91,8 +92,8 @@ class CommandObjectSourceInfo : public CommandObjectParsed {
break;
case 'a': {
- address = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ address = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
} break;
case 's':
modules.push_back(std::string(option_arg));
@@ -147,16 +148,13 @@ public:
Options *GetOptions() override { return &m_options; }
protected:
- // Dump the line entries in each symbol context.
- // Return the number of entries found.
- // If module_list is set, only dump lines contained in one of the modules.
- // If file_spec is set, only dump lines in the file.
- // If the start_line option was specified, don't print lines less than
- // start_line.
+ // Dump the line entries in each symbol context. Return the number of entries
+ // found. If module_list is set, only dump lines contained in one of the
+ // modules. If file_spec is set, only dump lines in the file. If the
+ // start_line option was specified, don't print lines less than start_line.
// If the end_line option was specified, don't print lines greater than
- // end_line.
- // If the num_lines option was specified, dont print more than num_lines
- // entries.
+ // end_line. If the num_lines option was specified, dont print more than
+ // num_lines entries.
uint32_t DumpLinesInSymbolContexts(Stream &strm,
const SymbolContextList &sc_list,
const ModuleList &module_list,
@@ -221,14 +219,11 @@ protected:
}
// Dump the requested line entries for the file in the compilation unit.
- // Return the number of entries found.
- // If module_list is set, only dump lines contained in one of the modules.
- // If the start_line option was specified, don't print lines less than
- // start_line.
- // If the end_line option was specified, don't print lines greater than
- // end_line.
- // If the num_lines option was specified, dont print more than num_lines
- // entries.
+ // Return the number of entries found. If module_list is set, only dump lines
+ // contained in one of the modules. If the start_line option was specified,
+ // don't print lines less than start_line. If the end_line option was
+ // specified, don't print lines greater than end_line. If the num_lines
+ // option was specified, dont print more than num_lines entries.
uint32_t DumpFileLinesInCompUnit(Stream &strm, Module *module,
CompileUnit *cu, const FileSpec &file_spec) {
uint32_t start_line = m_options.start_line;
@@ -258,8 +253,8 @@ protected:
while (true) {
LineEntry line_entry;
- // Find the lowest index of a line entry with a line equal to
- // or higher than 'line'.
+ // Find the lowest index of a line entry with a line equal to or
+ // higher than 'line'.
uint32_t start_idx = 0;
start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec,
/*exact=*/false, &line_entry);
@@ -270,7 +265,8 @@ protected:
if (end_line > 0 && line_entry.line > end_line)
break;
- // Loop through to find any other entries for this line, dumping each.
+ // Loop through to find any other entries for this line, dumping
+ // each.
line = line_entry.line;
do {
num_matches++;
@@ -304,22 +300,18 @@ protected:
return num_matches;
}
- // Dump the requested line entries for the file in the module.
- // Return the number of entries found.
- // If module_list is set, only dump lines contained in one of the modules.
- // If the start_line option was specified, don't print lines less than
- // start_line.
- // If the end_line option was specified, don't print lines greater than
- // end_line.
- // If the num_lines option was specified, dont print more than num_lines
- // entries.
+ // Dump the requested line entries for the file in the module. Return the
+ // number of entries found. If module_list is set, only dump lines contained
+ // in one of the modules. If the start_line option was specified, don't print
+ // lines less than start_line. If the end_line option was specified, don't
+ // print lines greater than end_line. If the num_lines option was specified,
+ // dont print more than num_lines entries.
uint32_t DumpFileLinesInModule(Stream &strm, Module *module,
const FileSpec &file_spec) {
uint32_t num_matches = 0;
if (module) {
// Look through all the compilation units (CUs) in this module for ones
- // that
- // contain lines of code from this source file.
+ // that contain lines of code from this source file.
for (size_t i = 0; i < module->GetNumCompileUnits(); i++) {
// Look for a matching source file in this CU.
CompUnitSP cu_sp(module->GetCompileUnitAtIndex(i));
@@ -333,10 +325,8 @@ protected:
}
// Given an address and a list of modules, append the symbol contexts of all
- // line entries
- // containing the address found in the modules and return the count of
- // matches. If none
- // is found, return an error in 'error_strm'.
+ // line entries containing the address found in the modules and return the
+ // count of matches. If none is found, return an error in 'error_strm'.
size_t GetSymbolContextsForAddress(const ModuleList &module_list,
lldb::addr_t addr,
SymbolContextList &sc_list,
@@ -346,8 +336,8 @@ protected:
assert(module_list.GetSize() > 0);
Target *target = m_exe_ctx.GetTargetPtr();
if (target->GetSectionLoadList().IsEmpty()) {
- // The target isn't loaded yet, we need to lookup the file address in
- // all modules. Note: the module list option does not apply to addresses.
+ // The target isn't loaded yet, we need to lookup the file address in all
+ // modules. Note: the module list option does not apply to addresses.
const size_t num_modules = module_list.GetSize();
for (size_t i = 0; i < num_modules; ++i) {
ModuleSP module_sp(module_list.GetModuleAtIndex(i));
@@ -369,8 +359,8 @@ protected:
" not found in any modules.\n",
addr);
} else {
- // The target has some things loaded, resolve this address to a
- // compile unit + file + line and display
+ // The target has some things loaded, resolve this address to a compile
+ // unit + file + line and display
if (target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
ModuleSP module_sp(so_addr.GetModule());
// Check to make sure this module is in our list.
@@ -408,8 +398,8 @@ protected:
return num_matches;
}
- // Dump the line entries found in functions matching the name specified in the
- // option.
+ // Dump the line entries found in functions matching the name specified in
+ // the option.
bool DumpLinesInFunctions(CommandReturnObject &result) {
SymbolContextList sc_list_funcs;
ConstString name(m_options.symbol_name.c_str());
@@ -709,8 +699,8 @@ class CommandObjectSourceList : public CommandObjectParsed {
break;
case 'a': {
- address = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ address = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
} break;
case 's':
modules.push_back(std::string(option_arg));
@@ -773,9 +763,9 @@ public:
const char *GetRepeatCommand(Args &current_command_args,
uint32_t index) override {
- // This is kind of gross, but the command hasn't been parsed yet so we can't
- // look at the option values for this invocation... I have to scan the
- // arguments directly.
+ // This is kind of gross, but the command hasn't been parsed yet so we
+ // can't look at the option values for this invocation... I have to scan
+ // the arguments directly.
auto iter =
llvm::find_if(current_command_args, [](const Args::ArgEntry &e) {
return e.ref == "-r" || e.ref == "--reverse";
@@ -863,11 +853,9 @@ protected:
}
// This is a little hacky, but the first line table entry for a function
- // points to the "{" that
- // starts the function block. It would be nice to actually get the
- // function
- // declaration in there too. So back up a bit, but not further than what
- // you're going to display.
+ // points to the "{" that starts the function block. It would be nice to
+ // actually get the function declaration in there too. So back up a bit,
+ // but not further than what you're going to display.
uint32_t extra_lines;
if (m_options.num_lines >= 10)
extra_lines = 5;
@@ -880,8 +868,7 @@ protected:
line_no = start_line - extra_lines;
// For fun, if the function is shorter than the number of lines we're
- // supposed to display,
- // only display the function...
+ // supposed to display, only display the function...
if (end_line != 0) {
if (m_options.num_lines > end_line - line_no)
m_options.num_lines = end_line - line_no + extra_lines;
@@ -912,14 +899,13 @@ protected:
return 0;
}
- // From Jim: The FindMatchingFunctions / FindMatchingFunctionSymbols functions
- // "take a possibly empty vector of strings which are names of modules, and
- // run the two search functions on the subset of the full module list that
- // matches the strings in the input vector". If we wanted to put these
- // somewhere,
- // there should probably be a module-filter-list that can be passed to the
- // various ModuleList::Find* calls, which would either be a vector of string
- // names or a ModuleSpecList.
+ // From Jim: The FindMatchingFunctions / FindMatchingFunctionSymbols
+ // functions "take a possibly empty vector of strings which are names of
+ // modules, and run the two search functions on the subset of the full module
+ // list that matches the strings in the input vector". If we wanted to put
+ // these somewhere, there should probably be a module-filter-list that can be
+ // passed to the various ModuleList::Find* calls, which would either be a
+ // vector of string names or a ModuleSpecList.
size_t FindMatchingFunctions(Target *target, const ConstString &name,
SymbolContextList &sc_list) {
// Displaying the source for a symbol:
@@ -996,8 +982,7 @@ protected:
size_t num_matches = FindMatchingFunctions(target, name, sc_list);
if (!num_matches) {
// If we didn't find any functions with that name, try searching for
- // symbols
- // that line up exactly with function addresses.
+ // symbols that line up exactly with function addresses.
SymbolContextList sc_list_symbols;
size_t num_symbol_matches =
FindMatchingFunctionSymbols(target, name, sc_list_symbols);
@@ -1064,8 +1049,8 @@ protected:
SymbolContextList sc_list;
if (target->GetSectionLoadList().IsEmpty()) {
- // The target isn't loaded yet, we need to lookup the file address
- // in all modules
+ // The target isn't loaded yet, we need to lookup the file address in
+ // all modules
const ModuleList &module_list = target->GetImages();
const size_t num_modules = module_list.GetSize();
for (size_t i = 0; i < num_modules; ++i) {
@@ -1090,8 +1075,8 @@ protected:
return false;
}
} else {
- // The target has some things loaded, resolve this address to a
- // compile unit + file + line and display
+ // The target has some things loaded, resolve this address to a compile
+ // unit + file + line and display
if (target->GetSectionLoadList().ResolveLoadAddress(m_options.address,
so_addr)) {
ModuleSP module_sp(so_addr.GetModule());
@@ -1168,11 +1153,10 @@ protected:
}
}
} else if (m_options.file_name.empty()) {
- // Last valid source manager context, or the current frame if no
- // valid last context in source manager.
- // One little trick here, if you type the exact same list command twice in
- // a row, it is
- // more likely because you typed it once, then typed it again
+ // Last valid source manager context, or the current frame if no valid
+ // last context in source manager. One little trick here, if you type the
+ // exact same list command twice in a row, it is more likely because you
+ // typed it once, then typed it again
if (m_options.start_line == 0) {
if (target->GetSourceManager().DisplayMoreWithLineNumbers(
&result.GetOutputStream(), m_options.num_lines,
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.cpp
new file mode 100644
index 000000000000..9225a94b70d3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.cpp
@@ -0,0 +1,107 @@
+//===-- CommandObjectStats.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectStats.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class CommandObjectStatsEnable : public CommandObjectParsed {
+public:
+ CommandObjectStatsEnable(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "enable",
+ "Enable statistics collection", nullptr,
+ eCommandProcessMustBePaused) {}
+
+ ~CommandObjectStatsEnable() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Target *target = GetSelectedOrDummyTarget();
+
+ if (target->GetCollectingStats()) {
+ result.AppendError("statistics already enabled");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ target->SetCollectingStats(true);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectStatsDisable : public CommandObjectParsed {
+public:
+ CommandObjectStatsDisable(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "disable",
+ "Disable statistics collection", nullptr,
+ eCommandProcessMustBePaused) {}
+
+ ~CommandObjectStatsDisable() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Target *target = GetSelectedOrDummyTarget();
+
+ if (!target->GetCollectingStats()) {
+ result.AppendError("need to enable statistics before disabling them");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ target->SetCollectingStats(false);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectStatsDump : public CommandObjectParsed {
+public:
+ CommandObjectStatsDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "dump", "Dump statistics results",
+ nullptr, eCommandProcessMustBePaused) {}
+
+ ~CommandObjectStatsDump() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Target *target = GetSelectedOrDummyTarget();
+
+ uint32_t i = 0;
+ for (auto &stat : target->GetStatistics()) {
+ result.AppendMessageWithFormat(
+ "%s : %u\n",
+ lldb_private::GetStatDescription(static_cast<lldb_private::StatisticKind>(i))
+ .c_str(),
+ stat);
+ i += 1;
+ }
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+CommandObjectStats::CommandObjectStats(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "statistics",
+ "Print statistics about a debugging session",
+ "statistics <subcommand> [<subcommand-options>]") {
+ LoadSubCommand("enable",
+ CommandObjectSP(new CommandObjectStatsEnable(interpreter)));
+ LoadSubCommand("disable",
+ CommandObjectSP(new CommandObjectStatsDisable(interpreter)));
+ LoadSubCommand("dump",
+ CommandObjectSP(new CommandObjectStatsDump(interpreter)));
+}
+
+CommandObjectStats::~CommandObjectStats() = default;
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.h
new file mode 100644
index 000000000000..3c5c2c04db1f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectStats.h
@@ -0,0 +1,25 @@
+//===-- CommandObjectStats.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectStats_h_
+#define liblldb_CommandObjectStats_h_
+
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+class CommandObjectStats : public CommandObjectMultiword {
+public:
+ CommandObjectStats(CommandInterpreter &interpreter);
+
+ ~CommandObjectStats() override;
+};
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectLanguage_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.cpp
deleted file mode 100644
index 2b83b1b8786b..000000000000
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-//===-- CommandObjectSyntax.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "CommandObjectSyntax.h"
-#include "CommandObjectHelp.h"
-#include "lldb/Interpreter/Args.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/Options.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-//-------------------------------------------------------------------------
-// CommandObjectSyntax
-//-------------------------------------------------------------------------
-
-CommandObjectSyntax::CommandObjectSyntax(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "syntax",
- "Shows the correct syntax for a given debugger command.",
- "syntax <command>") {
- CommandArgumentEntry arg;
- CommandArgumentData command_arg;
-
- // Define the first (and only) variant of this arg.
- command_arg.arg_type = eArgTypeCommandName;
- command_arg.arg_repetition = eArgRepeatPlain;
-
- // There is only one variant this argument could be; put it into the argument
- // entry.
- arg.push_back(command_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back(arg);
-}
-
-CommandObjectSyntax::~CommandObjectSyntax() = default;
-
-bool CommandObjectSyntax::DoExecute(Args &command,
- CommandReturnObject &result) {
- CommandObject::CommandMap::iterator pos;
- CommandObject *cmd_obj;
- const size_t argc = command.GetArgumentCount();
-
- if (argc == 0) {
- result.AppendError("Must call 'syntax' with a valid command.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- cmd_obj = m_interpreter.GetCommandObject(command[0].ref);
- bool all_okay = llvm::all_of(
- command.entries().drop_front(), [&cmd_obj](const Args::ArgEntry &e) {
- if (!cmd_obj || !cmd_obj->IsMultiwordObject())
- return false;
-
- if (!(cmd_obj = cmd_obj->GetSubcommandObject(e.ref)))
- return false;
-
- return true;
- });
-
- if (!all_okay) {
- std::string cmd_string;
- command.GetCommandString(cmd_string);
-
- StreamString error_msg_stream;
- const bool generate_apropos = true;
- const bool generate_type_lookup = false;
- CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
- &error_msg_stream, cmd_string, "", "", generate_apropos,
- generate_type_lookup);
- result.AppendErrorWithFormat("%s", error_msg_stream.GetData());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- Stream &output_strm = result.GetOutputStream();
- if (cmd_obj->GetOptions() != nullptr) {
- output_strm.Printf("\nSyntax: %s\n", cmd_obj->GetSyntax().str().c_str());
- output_strm.Printf(
- "(Try 'help %s' for more information on command options syntax.)\n",
- cmd_obj->GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- } else {
- output_strm.Printf("\nSyntax: %s\n", cmd_obj->GetSyntax().str().c_str());
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- }
-
- return result.Succeeded();
-}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h
deleted file mode 100644
index b65e9b1b750b..000000000000
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===-- CommandObjectSyntax.h -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_CommandObjectSyntax_h_
-#define liblldb_CommandObjectSyntax_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Interpreter/CommandObject.h"
-
-namespace lldb_private {
-
-//-------------------------------------------------------------------------
-// CommandObjectSyntax
-//-------------------------------------------------------------------------
-
-class CommandObjectSyntax : public CommandObjectParsed {
-public:
- CommandObjectSyntax(CommandInterpreter &interpreter);
-
- ~CommandObjectSyntax() override;
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_CommandObjectSyntax_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp
index c83061d8de74..8be43cbf9bb0 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp
@@ -21,9 +21,9 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupArchitecture.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupFile.h"
@@ -45,10 +45,12 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Timer.h"
#include "llvm/Support/FileSystem.h"
@@ -193,20 +195,13 @@ public:
Options *GetOptions() override { return &m_option_group; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
@@ -256,7 +251,7 @@ protected:
FileSpec file_spec;
if (file_path)
- file_spec.SetFile(file_path, true);
+ file_spec.SetFile(file_path, true, FileSpec::Style::native);
bool must_set_platform_path = false;
@@ -272,10 +267,8 @@ protected:
if (target_sp) {
// Only get the platform after we create the target because we might
- // have
- // switched platforms depending on what the arguments were to
- // CreateTarget()
- // we can't rely on the selected platform.
+ // have switched platforms depending on what the arguments were to
+ // CreateTarget() we can't rely on the selected platform.
PlatformSP platform_sp = target_sp->GetPlatform();
@@ -366,8 +359,8 @@ protected:
&core_file));
if (process_sp) {
- // Seems weird that we Launch a core file, but that is
- // what we do!
+ // Seems weird that we Launch a core file, but that is what we
+ // do!
error = process_sp->LoadCore();
if (error.Fail()) {
@@ -616,8 +609,8 @@ protected:
target_list.DeleteTarget(target_sp);
target_sp->Destroy();
}
- // If "--clean" was specified, prune any orphaned shared modules from
- // the global shared module list
+ // If "--clean" was specified, prune any orphaned shared modules from the
+ // global shared module list
if (m_cleanup_option.GetOptionValue()) {
const bool mandatory = true;
ModuleList::RemoveOrphanSharedModules(mandatory);
@@ -752,7 +745,7 @@ public:
VariableList &variable_list) {
Target *target = static_cast<Target *>(baton);
if (target) {
- return target->GetImages().FindGlobalVariables(ConstString(name), true,
+ return target->GetImages().FindGlobalVariables(ConstString(name),
UINT32_MAX, variable_list);
}
return 0;
@@ -818,8 +811,8 @@ protected:
return false;
}
use_var_name = true;
- matches = target->GetImages().FindGlobalVariables(
- regex, true, UINT32_MAX, variable_list);
+ matches = target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
+ variable_list);
} else {
Status error(Variable::GetValuesForVariableExpressionPath(
arg, m_exe_ctx.GetBestExecutionContextScope(),
@@ -947,8 +940,8 @@ protected:
llvm::StringRef(
".")); // Any global with at least one character
VariableList variable_list;
- sc.module_sp->FindGlobalVariables(all_globals_regex, append,
- UINT32_MAX, variable_list);
+ sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
+ variable_list);
DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
}
}
@@ -995,10 +988,9 @@ public:
new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
- // There are two required arguments that must always occur together, i.e. an
- // argument "pair". Because they
- // must always occur together, they are treated as two variants of one
- // argument rather than two independent
+ // There are two required arguments that must always occur together, i.e.
+ // an argument "pair". Because they must always occur together, they are
+ // treated as two variants of one argument rather than two independent
// arguments. Push them both into the first argument position for
// m_arguments...
@@ -1109,10 +1101,9 @@ public:
new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
- // There are two required arguments that must always occur together, i.e. an
- // argument "pair". Because they
- // must always occur together, they are treated as two variants of one
- // argument rather than two independent
+ // There are two required arguments that must always occur together, i.e.
+ // an argument "pair". Because they must always occur together, they are
+ // treated as two variants of one argument rather than two independent
// arguments. Push them both into the same argument position for
// m_arguments...
@@ -1386,7 +1377,12 @@ static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
strm.EOL();
}
ObjectFile *objfile = module->GetObjectFile();
- objfile->Dump(&strm);
+ if (objfile)
+ objfile->Dump(&strm);
+ else {
+ strm.Format("No object file for module: {0:F}\n",
+ module->GetFileSpec());
+ }
}
}
strm.IndentLess();
@@ -1632,8 +1628,8 @@ static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
strm.PutCString(":\n");
for (TypeSP type_sp : type_list.Types()) {
if (type_sp) {
- // Resolve the clang type so that any forward references
- // to types that haven't yet been parsed will get parsed.
+ // Resolve the clang type so that any forward references to types
+ // that haven't yet been parsed will get parsed.
type_sp->GetFullCompilerType();
type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
// Print all typedef chains
@@ -1683,8 +1679,8 @@ static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
TypeSP type_sp(type_list.GetTypeAtIndex(0));
if (type_sp) {
- // Resolve the clang type so that any forward references
- // to types that haven't yet been parsed will get parsed.
+ // Resolve the clang type so that any forward references to types that
+ // haven't yet been parsed will get parsed.
type_sp->GetFullCompilerType();
type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
// Print all typedef chains
@@ -1762,9 +1758,8 @@ static size_t FindModulesByName(Target *target, const char *module_name,
const size_t num_matches =
target->GetImages().FindModules(module_spec, module_list);
- // Not found in our module list for our target, check the main
- // shared module list in case it is a extra file used somewhere
- // else
+ // Not found in our module list for our target, check the main shared
+ // module list in case it is a extra file used somewhere else
if (num_matches == 0) {
module_spec.GetArchitecture() = target->GetArchitecture();
ModuleList::FindSharedModules(module_spec, module_list);
@@ -1809,21 +1804,13 @@ public:
~CommandObjectTargetModulesModuleAutoComplete() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- // Arguments are the standard module completer.
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
- GetCommandInterpreter(), CommandCompletions::eModuleCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
+ nullptr);
+ return request.GetNumberOfMatches();
}
};
@@ -1858,21 +1845,13 @@ public:
~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- // Arguments are the standard source file completer.
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
};
@@ -1982,7 +1961,7 @@ public:
switch (short_option) {
case 's':
- m_sort_order = (SortOrder)Args::StringToOptionEnum(
+ m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values,
eSortOrderNone, error);
break;
@@ -2408,20 +2387,13 @@ public:
Options *GetOptions() override { return &m_option_group; }
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
protected:
@@ -2604,8 +2576,7 @@ protected:
ModuleSpec module_spec;
bool search_using_module_spec = false;
- // Allow "load" option to work without --file or --uuid
- // option.
+ // Allow "load" option to work without --file or --uuid option.
if (load) {
if (!m_file_option.GetOptionValue().OptionWasSet() &&
!m_uuid_option_group.GetOptionValue().OptionWasSet()) {
@@ -2746,11 +2717,34 @@ protected:
process->Flush();
}
if (load) {
- Status error = module->LoadInMemory(*target, set_pc);
+ ProcessSP process = target->CalculateProcess();
+ Address file_entry = objfile->GetEntryPointAddress();
+ if (!process) {
+ result.AppendError("No process");
+ return false;
+ }
+ if (set_pc && !file_entry.IsValid()) {
+ result.AppendError("No entry address in object file");
+ return false;
+ }
+ std::vector<ObjectFile::LoadableData> loadables(
+ objfile->GetLoadableData(*target));
+ if (loadables.size() == 0) {
+ result.AppendError("No loadable sections");
+ return false;
+ }
+ Status error = process->WriteObjectFile(std::move(loadables));
if (error.Fail()) {
result.AppendError(error.AsCString());
return false;
}
+ if (set_pc) {
+ ThreadList &thread_list = process->GetThreadList();
+ ThreadSP curr_thread(thread_list.GetSelectedThread());
+ RegisterContextSP reg_context(
+ curr_thread->GetRegisterContext());
+ reg_context->SetPC(file_entry.GetLoadAddress(target));
+ }
}
} else {
module->GetFileSpec().GetPath(path, sizeof(path));
@@ -2861,8 +2855,8 @@ public:
if (short_option == 'g') {
m_use_global_module_list = true;
} else if (short_option == 'a') {
- m_module_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ m_module_addr = OptionArgParser::ToAddress(
+ execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
} else {
unsigned long width = 0;
option_arg.getAsInteger(0, width);
@@ -2904,9 +2898,8 @@ protected:
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
const bool use_global_module_list = m_options.m_use_global_module_list;
// Define a local module list here to ensure it lives longer than any
- // "locker"
- // object which might lock its contents below (through the "module_list_ptr"
- // variable).
+ // "locker" object which might lock its contents below (through the
+ // "module_list_ptr" variable).
ModuleList module_list;
if (target == nullptr && !use_global_module_list) {
result.AppendError("invalid target, create a debug target using the "
@@ -2954,10 +2947,9 @@ protected:
size_t num_modules = 0;
// This locker will be locked on the mutex in module_list_ptr if it is
- // non-nullptr.
- // Otherwise it will lock the AllocationModuleCollectionMutex when
- // accessing
- // the global module list directly.
+ // non-nullptr. Otherwise it will lock the
+ // AllocationModuleCollectionMutex when accessing the global module list
+ // directly.
std::unique_lock<std::recursive_mutex> guard(
Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
@@ -3227,8 +3219,8 @@ public:
case 'a': {
m_str = option_arg;
m_type = eLookupTypeAddress;
- m_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
if (m_addr == LLDB_INVALID_ADDRESS)
error.SetErrorStringWithFormat("invalid address string '%s'",
option_arg.str().c_str());
@@ -3543,8 +3535,8 @@ public:
switch (short_option) {
case 'a': {
m_type = eLookupTypeAddress;
- m_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
} break;
case 'o':
@@ -3559,7 +3551,7 @@ public:
break;
case 'f':
- m_file.SetFile(option_arg, false);
+ m_file.SetFile(option_arg, false, FileSpec::Style::native);
m_type = eLookupTypeFileLine;
break;
@@ -3805,9 +3797,9 @@ protected:
if (command.GetArgumentCount() == 0) {
ModuleSP current_module;
- // Where it is possible to look in the current symbol context
- // first, try that. If this search was successful and --all
- // was not passed, don't print anything else.
+ // Where it is possible to look in the current symbol context first,
+ // try that. If this search was successful and --all was not passed,
+ // don't print anything else.
if (LookupHere(m_interpreter, result, syntax_error)) {
result.GetOutputStream().EOL();
num_successful_lookups++;
@@ -3989,20 +3981,13 @@ public:
~CommandObjectTargetSymbolsAdd() override = default;
- int HandleArgumentCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point, int max_return_elements,
- bool &word_complete,
- StringList &matches) override {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index));
- completion_str.erase(cursor_char_position);
-
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
- completion_str.c_str(), match_start_point, max_return_elements, nullptr,
- word_complete, matches);
- return matches.GetSize();
+ request, nullptr);
+ return request.GetNumberOfMatches();
}
Options *GetOptions() override { return &m_option_group; }
@@ -4019,10 +4004,9 @@ protected:
if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
}
- // We now have a module that represents a symbol file
- // that can be used for a module that might exist in the
- // current target, so we need to find that module in the
- // target
+ // We now have a module that represents a symbol file that can be used
+ // for a module that might exist in the current target, so we need to
+ // find that module in the target
ModuleList matching_module_list;
size_t num_matches = 0;
@@ -4048,8 +4032,7 @@ protected:
if (num_matches == 0) {
// No matches yet, iterate through the module specs to find a UUID
- // value that
- // we can match up to an image in our target
+ // value that we can match up to an image in our target
const size_t num_symfile_module_specs =
symfile_module_specs.GetSize();
for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
@@ -4069,8 +4052,8 @@ protected:
}
}
- // Just try to match up the file by basename if we have no matches at this
- // point
+ // Just try to match up the file by basename if we have no matches at
+ // this point
if (num_matches == 0)
num_matches =
target->GetImages().FindModules(module_spec, matching_module_list);
@@ -4082,7 +4065,8 @@ protected:
if (!filename_no_extension)
break;
- // Check if there was no extension to strip and the basename is the same
+ // Check if there was no extension to strip and the basename is the
+ // same
if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
break;
@@ -4101,9 +4085,9 @@ protected:
} else if (num_matches == 1) {
ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
- // The module has not yet created its symbol vendor, we can just
- // give the existing target module the symfile path to use for
- // when it decides to create it!
+ // The module has not yet created its symbol vendor, we can just give
+ // the existing target module the symfile path to use for when it
+ // decides to create it!
module_sp->SetSymbolFileFileSpec(symbol_fspec);
SymbolVendor *symbol_vendor =
@@ -4121,8 +4105,8 @@ protected:
"symbol file '%s' has been added to '%s'\n", symfile_path,
module_fs.GetPath().c_str());
- // Let clients know something changed in the module
- // if it is currently loaded
+ // Let clients know something changed in the module if it is
+ // currently loaded
ModuleList module_list;
module_list.Append(module_sp);
target->SymbolsDidLoad(module_list);
@@ -4298,7 +4282,8 @@ protected:
for (auto &entry : args.entries()) {
if (!entry.ref.empty()) {
- module_spec.GetSymbolFileSpec().SetFile(entry.ref, true);
+ module_spec.GetSymbolFileSpec().SetFile(entry.ref, true,
+ FileSpec::Style::native);
if (file_option_set) {
module_spec.GetFileSpec() =
m_file_option.GetOptionValue().GetCurrentValue();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
index b68aa920b582..3be559963df1 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
@@ -21,6 +21,7 @@
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
@@ -103,8 +104,8 @@ public:
}
// Use tids instead of ThreadSPs to prevent deadlocking problems which
- // result from JIT-ing
- // code while iterating over the (locked) ThreadSP list.
+ // result from JIT-ing code while iterating over the (locked) ThreadSP
+ // list.
std::vector<lldb::tid_t> tids;
if (all_threads || m_unique_stacks) {
@@ -195,11 +196,10 @@ protected:
//
// If you return false, the iteration will stop, otherwise it will proceed.
// The result is set to m_success_return (defaults to
- // eReturnStatusSuccessFinishResult) before the iteration,
- // so you only need to set the return status in HandleOneThread if you want to
- // indicate an error.
- // If m_add_return is true, a blank line will be inserted between each of the
- // listings (except the last one.)
+ // eReturnStatusSuccessFinishResult) before the iteration, so you only need
+ // to set the return status in HandleOneThread if you want to indicate an
+ // error. If m_add_return is true, a blank line will be inserted between each
+ // of the listings (except the last one.)
virtual bool HandleOneThread(lldb::tid_t, CommandReturnObject &result) = 0;
@@ -290,7 +290,7 @@ public:
case 'e': {
bool success;
m_extended_backtrace =
- Args::StringToBoolean(option_arg, false, &success);
+ OptionArgParser::ToBoolean(option_arg, false, &success);
if (!success)
error.SetErrorStringWithFormat(
"invalid boolean value for option '%c'", short_option);
@@ -447,7 +447,8 @@ public:
switch (short_option) {
case 'a': {
bool success;
- bool avoid_no_debug = Args::StringToBoolean(option_arg, true, &success);
+ bool avoid_no_debug =
+ OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat(
"invalid boolean value for option '%c'", short_option);
@@ -459,7 +460,8 @@ public:
case 'A': {
bool success;
- bool avoid_no_debug = Args::StringToBoolean(option_arg, true, &success);
+ bool avoid_no_debug =
+ OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat(
"invalid boolean value for option '%c'", short_option);
@@ -483,7 +485,7 @@ public:
case 'm': {
OptionEnumValueElement *enum_values =
GetDefinitions()[option_idx].enum_values;
- m_run_mode = (lldb::RunMode)Args::StringToOptionEnum(
+ m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
option_arg, enum_values, eOnlyDuringStepping, error);
} break;
@@ -644,8 +646,7 @@ protected:
const lldb::RunMode stop_other_threads = m_options.m_run_mode;
// This is a bit unfortunate, but not all the commands in this command
- // object support
- // only while stepping, so I use the bool for them.
+ // object support only while stepping, so I use the bool for them.
bool bool_stop_other_threads;
if (m_options.m_run_mode == eAllThreads)
bool_stop_other_threads = false;
@@ -750,8 +751,8 @@ protected:
}
// If we got a new plan, then set it to be a master plan (User level Plans
- // should be master plans
- // so that they can be interruptible). Then resume the process.
+ // should be master plans so that they can be interruptible). Then resume
+ // the process.
if (new_plan_sp) {
new_plan_sp->SetIsMasterPlan(true);
@@ -782,11 +783,10 @@ protected:
}
// There is a race condition where this thread will return up the call
- // stack to the main command handler
- // and show an (lldb) prompt before HandlePrivateEvent (from
- // PrivateStateThread) has
- // a chance to call PushProcessIOHandler().
- process->SyncIOHandler(iohandler_id, 2000);
+ // stack to the main command handler and show an (lldb) prompt before
+ // HandlePrivateEvent (from PrivateStateThread) has a chance to call
+ // PushProcessIOHandler().
+ process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
if (synchronous_execution) {
// If any state changed events had anything to say, add that to the
@@ -867,9 +867,9 @@ public:
(state == eStateSuspended)) {
const size_t argc = command.GetArgumentCount();
if (argc > 0) {
- // These two lines appear at the beginning of both blocks in
- // this if..else, but that is because we need to release the
- // lock before calling process->Resume below.
+ // These two lines appear at the beginning of both blocks in this
+ // if..else, but that is because we need to release the lock before
+ // calling process->Resume below.
std::lock_guard<std::recursive_mutex> guard(
process->GetThreadList().GetMutex());
const uint32_t num_threads = process->GetThreadList().GetSize();
@@ -928,9 +928,9 @@ public:
process->GetID());
}
} else {
- // These two lines appear at the beginning of both blocks in
- // this if..else, but that is because we need to release the
- // lock before calling process->Resume below.
+ // These two lines appear at the beginning of both blocks in this
+ // if..else, but that is because we need to release the lock before
+ // calling process->Resume below.
std::lock_guard<std::recursive_mutex> guard(
process->GetThreadList().GetMutex());
const uint32_t num_threads = process->GetThreadList().GetSize();
@@ -1030,7 +1030,7 @@ public:
switch (short_option) {
case 'a': {
- lldb::addr_t tmp_addr = Args::StringToAddress(
+ lldb::addr_t tmp_addr = OptionArgParser::ToAddress(
execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
if (error.Success())
m_until_addrs.push_back(tmp_addr);
@@ -1052,7 +1052,7 @@ public:
case 'm': {
OptionEnumValueElement *enum_values =
GetDefinitions()[option_idx].enum_values;
- lldb::RunMode run_mode = (lldb::RunMode)Args::StringToOptionEnum(
+ lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
option_arg, enum_values, eOnlyDuringStepping, error);
if (error.Success()) {
@@ -1192,8 +1192,8 @@ protected:
ThreadPlanSP new_plan_sp;
if (frame->HasDebugInformation()) {
- // Finally we got here... Translate the given line number to a bunch of
- // addresses:
+ // Finally we got here... Translate the given line number to a bunch
+ // of addresses:
SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit));
LineTable *line_table = nullptr;
if (sc.comp_unit)
@@ -1272,10 +1272,9 @@ protected:
abort_other_plans, &address_list.front(), address_list.size(),
m_options.m_stop_others, m_options.m_frame_idx);
// User level plans should be master plans so they can be interrupted
- // (e.g. by hitting a breakpoint)
- // and other plans executed by the user (stepping around the breakpoint)
- // and then a "continue"
- // will resume the original plan.
+ // (e.g. by hitting a breakpoint) and other plans executed by the user
+ // (stepping around the breakpoint) and then a "continue" will resume
+ // the original plan.
new_plan_sp->SetIsMasterPlan(true);
new_plan_sp->SetOkayToDiscard(false);
} else {
@@ -1541,7 +1540,8 @@ public:
switch (short_option) {
case 'x': {
bool success;
- bool tmp_value = Args::StringToBoolean(option_arg, false, &success);
+ bool tmp_value =
+ OptionArgParser::ToBoolean(option_arg, false, &success);
if (success)
m_from_expression = tmp_value;
else {
@@ -1603,12 +1603,13 @@ public:
Options *GetOptions() override { return &m_options; }
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
// I am going to handle this by hand, because I don't want you to have to
// say:
// "thread return -- -5".
- if (command[0] == '-' && command[1] == 'x') {
- if (command && command[2] != '\0')
+ if (command.startswith("-x")) {
+ if (command.size() != 2U)
result.AppendWarning("Return values ignored when returning from user "
"called expressions");
@@ -1645,7 +1646,7 @@ protected:
return false;
}
- if (command && command[0] != '\0') {
+ if (!command.empty()) {
Target *target = m_exe_ctx.GetTargetPtr();
EvaluateExpressionOptions options;
@@ -1737,8 +1738,8 @@ public:
return Status("invalid line offset: '%s'.", option_arg.str().c_str());
break;
case 'a':
- m_load_addr = Args::StringToAddress(execution_context, option_arg,
- LLDB_INVALID_ADDRESS, &error);
+ m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
+ LLDB_INVALID_ADDRESS, &error);
break;
case 'r':
m_force = true;
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp
index 2d4271cab362..6bcc334198fc 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp
@@ -24,6 +24,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueLanguage.h"
@@ -329,7 +330,7 @@ private:
switch (short_option) {
case 'C':
- m_cascade = Args::StringToBoolean(option_arg, true, &success);
+ m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("invalid value for cascade: %s",
option_arg.str().c_str());
@@ -571,7 +572,7 @@ private:
switch (short_option) {
case 'C':
- m_cascade = Args::StringToBoolean(option_value, true, &success);
+ m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
if (!success)
error.SetErrorStringWithFormat("invalid value for cascade: %s",
option_value.str().c_str());
@@ -1252,7 +1253,7 @@ Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
switch (short_option) {
case 'C':
- m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success));
+ m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
if (!success)
error.SetErrorStringWithFormat("invalid value for cascade: %s",
option_arg.str().c_str());
@@ -1420,8 +1421,8 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
return result.Succeeded();
}
- // if I am here, script_format must point to something good, so I can add that
- // as a script summary to all interested parties
+ // if I am here, script_format must point to something good, so I can add
+ // that as a script summary to all interested parties
Status error;
@@ -2520,7 +2521,7 @@ private:
switch (short_option) {
case 'C':
- m_cascade = Args::StringToBoolean(option_arg, true, &success);
+ m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("invalid value for cascade: %s",
option_arg.str().c_str());
@@ -2756,9 +2757,8 @@ static OptionDefinition g_type_lookup_options[] = {
class CommandObjectTypeLookup : public CommandObjectRaw {
protected:
// this function is allowed to do a more aggressive job at guessing languages
- // than the expression parser
- // is comfortable with - so leave the original call alone and add one that is
- // specific to type lookup
+ // than the expression parser is comfortable with - so leave the original
+ // call alone and add one that is specific to type lookup
lldb::LanguageType GuessLanguage(StackFrame *frame) {
lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
@@ -2862,9 +2862,9 @@ public:
return m_cmd_help_long;
}
- bool DoExecute(const char *raw_command_line,
+ bool DoExecute(llvm::StringRef raw_command_line,
CommandReturnObject &result) override {
- if (!raw_command_line || !raw_command_line[0]) {
+ if (raw_command_line.empty()) {
result.SetError(
"type lookup cannot be invoked without a type name as argument");
return false;
@@ -2873,42 +2873,13 @@ public:
auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
m_option_group.NotifyOptionParsingStarting(&exe_ctx);
- const char *name_of_type = nullptr;
-
- if (raw_command_line[0] == '-') {
- // We have some options and these options MUST end with --.
- const char *end_options = nullptr;
- const char *s = raw_command_line;
- while (s && s[0]) {
- end_options = ::strstr(s, "--");
- if (end_options) {
- end_options += 2; // Get past the "--"
- if (::isspace(end_options[0])) {
- name_of_type = end_options;
- while (::isspace(*name_of_type))
- ++name_of_type;
- break;
- }
- }
- s = end_options;
- }
+ OptionsWithRaw args(raw_command_line);
+ const char *name_of_type = args.GetRawPart().c_str();
- if (end_options) {
- Args args(
- llvm::StringRef(raw_command_line, end_options - raw_command_line));
- if (!ParseOptions(args, result))
- return false;
-
- Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
- if (error.Fail()) {
- result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- }
- if (nullptr == name_of_type)
- name_of_type = raw_command_line;
+ if (args.HasArgs())
+ if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
+ exe_ctx))
+ return false;
// TargetSP
// target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
@@ -2933,9 +2904,8 @@ public:
}
// This is not the most efficient way to do this, but we support very few
- // languages
- // so the cost of the sort is going to be dwarfed by the actual lookup
- // anyway
+ // languages so the cost of the sort is going to be dwarfed by the actual
+ // lookup anyway
if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
guessed_language = GuessLanguage(frame);
if (guessed_language != eLanguageTypeUnknown) {
@@ -3024,7 +2994,8 @@ public:
~CommandObjectFormatterInfo() override = default;
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
Thread *thread = GetDefaultThread();
if (!thread) {
@@ -3047,16 +3018,16 @@ protected:
m_discovery_function(*result_valobj_sp);
if (formatter_sp) {
std::string description(formatter_sp->GetDescription());
- result.AppendMessageWithFormat(
- "%s applied to (%s) %s is: %s\n", m_formatter_name.c_str(),
- result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
- command, description.c_str());
+ result.GetOutputStream()
+ << m_formatter_name << " applied to ("
+ << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
+ << ") " << command << " is: " << description << "\n";
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
} else {
- result.AppendMessageWithFormat(
- "no %s applies to (%s) %s\n", m_formatter_name.c_str(),
- result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
- command);
+ result.GetOutputStream()
+ << "no " << m_formatter_name << " applies to ("
+ << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
+ << ") " << command << "\n";
result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
}
return true;
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
index 9c84c992e715..96ae18b35743 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -74,8 +74,8 @@ static int32_t WithRSAIndex(llvm::StringRef Arg) {
return -1;
}
-// Return true if wp_ids is successfully populated with the watch ids.
-// False otherwise.
+// Return true if wp_ids is successfully populated with the watch ids. False
+// otherwise.
bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
// Pre-condition: args.GetArgumentCount() > 0.
@@ -111,8 +111,8 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
if (!second.empty())
StrRefArgs.push_back(second);
}
- // Now process the canonical list and fill in the vector of uint32_t's.
- // If there is any error, return false and the client should ignore wp_ids.
+ // Now process the canonical list and fill in the vector of uint32_t's. If
+ // there is any error, return false and the client should ignore wp_ids.
uint32_t beg, end, id;
size_t size = StrRefArgs.size();
bool in_range = false;
@@ -838,7 +838,7 @@ protected:
VariableList &variable_list) {
Target *target = static_cast<Target *>(baton);
if (target) {
- return target->GetImages().FindGlobalVariables(ConstString(name), true,
+ return target->GetImages().FindGlobalVariables(ConstString(name),
UINT32_MAX, variable_list);
}
return 0;
@@ -848,8 +848,8 @@ protected:
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
StackFrame *frame = m_exe_ctx.GetFramePtr();
- // If no argument is present, issue an error message. There's no way to set
- // a watchpoint.
+ // If no argument is present, issue an error message. There's no way to
+ // set a watchpoint.
if (command.GetArgumentCount() <= 0) {
result.GetErrorStream().Printf("error: required argument missing; "
"specify your program variable to watch "
@@ -863,8 +863,8 @@ protected:
m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
}
- // We passed the sanity check for the command.
- // Proceed to set the watchpoint now.
+ // We passed the sanity check for the command. Proceed to set the
+ // watchpoint now.
lldb::addr_t addr = 0;
size_t size = 0;
@@ -1026,7 +1026,7 @@ Examples:
Options *GetOptions() override { return &m_option_group; }
protected:
- bool DoExecute(const char *raw_command,
+ bool DoExecute(llvm::StringRef raw_command,
CommandReturnObject &result) override {
auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
m_option_group.NotifyOptionParsingStarting(
@@ -1035,46 +1035,18 @@ protected:
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
StackFrame *frame = m_exe_ctx.GetFramePtr();
- Args command(raw_command);
- const char *expr = nullptr;
- if (raw_command[0] == '-') {
- // We have some options and these options MUST end with --.
- const char *end_options = nullptr;
- const char *s = raw_command;
- while (s && s[0]) {
- end_options = ::strstr(s, "--");
- if (end_options) {
- end_options += 2; // Get past the "--"
- if (::isspace(end_options[0])) {
- expr = end_options;
- while (::isspace(*expr))
- ++expr;
- break;
- }
- }
- s = end_options;
- }
+ OptionsWithRaw args(raw_command);
- if (end_options) {
- Args args(llvm::StringRef(raw_command, end_options - raw_command));
- if (!ParseOptions(args, result))
- return false;
-
- Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
- if (error.Fail()) {
- result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- }
+ llvm::StringRef expr = args.GetRawPart();
- if (expr == nullptr)
- expr = raw_command;
+ if (args.HasArgs())
+ if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
+ exe_ctx))
+ return false;
- // If no argument is present, issue an error message. There's no way to set
- // a watchpoint.
- if (command.GetArgumentCount() == 0) {
+ // If no argument is present, issue an error message. There's no way to
+ // set a watchpoint.
+ if (raw_command.trim().empty()) {
result.GetErrorStream().Printf("error: required argument missing; "
"specify an expression to evaulate into "
"the address to watch for\n");
@@ -1087,8 +1059,8 @@ protected:
m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
}
- // We passed the sanity check for the command.
- // Proceed to set the watchpoint now.
+ // We passed the sanity check for the command. Proceed to set the
+ // watchpoint now.
lldb::addr_t addr = 0;
size_t size = 0;
@@ -1107,7 +1079,7 @@ protected:
if (expr_result != eExpressionCompleted) {
result.GetErrorStream().Printf(
"error: expression evaluation of address to watch failed\n");
- result.GetErrorStream().Printf("expression evaluated: %s\n", expr);
+ result.GetErrorStream() << "expression evaluated: \n" << expr << "\n";
result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index ec7e4a1f9cde..74015a433831 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -22,6 +22,7 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -253,11 +254,10 @@ are no syntax errors may indicate that a function was declared but never called.
std::unique_ptr<WatchpointOptions::CommandData> data_ap(
new WatchpointOptions::CommandData());
- // It's necessary to set both user_source and script_source to the oneliner.
- // The former is used to generate callback description (as in watchpoint
- // command list)
- // while the latter is used for Python to interpret during the actual
- // callback.
+ // It's necessary to set both user_source and script_source to the
+ // oneliner. The former is used to generate callback description (as in
+ // watchpoint command list) while the latter is used for Python to
+ // interpret during the actual callback.
data_ap->user_source.AppendString(oneliner);
data_ap->script_source.assign(oneliner);
data_ap->stop_on_error = m_options.m_stop_on_error;
@@ -286,8 +286,8 @@ are no syntax errors may indicate that a function was declared but never called.
CommandReturnObject result;
Debugger &debugger = target->GetDebugger();
// Rig up the results secondary output stream to the debugger's, so the
- // output will come out synchronously
- // if the debugger is set up that way.
+ // output will come out synchronously if the debugger is set up that
+ // way.
StreamSP output_stream(debugger.GetAsyncOutputStream());
StreamSP error_stream(debugger.GetAsyncErrorStream());
@@ -331,7 +331,7 @@ are no syntax errors may indicate that a function was declared but never called.
break;
case 's':
- m_script_language = (lldb::ScriptLanguage)Args::StringToOptionEnum(
+ m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values,
eScriptLanguageNone, error);
@@ -341,7 +341,8 @@ are no syntax errors may indicate that a function was declared but never called.
case 'e': {
bool success = false;
- m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
+ m_stop_on_error =
+ OptionArgParser::ToBoolean(option_arg, false, &success);
if (!success)
error.SetErrorStringWithFormat(
"invalid value for stop-on-error: \"%s\"",
@@ -439,20 +440,19 @@ protected:
if (wp_options == nullptr)
continue;
- // If we are using script language, get the script interpreter
- // in order to set or collect command callback. Otherwise, call
- // the methods associated with this object.
+ // If we are using script language, get the script interpreter in order
+ // to set or collect command callback. Otherwise, call the methods
+ // associated with this object.
if (m_options.m_use_script_language) {
// Special handling for one-liner specified inline.
if (m_options.m_use_one_liner) {
m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback(
wp_options, m_options.m_one_liner.c_str());
}
- // Special handling for using a Python function by name
- // instead of extending the watchpoint callback data structures, we
- // just automatize
- // what the user would do manually: make their watchpoint command be a
- // function call
+ // Special handling for using a Python function by name instead of
+ // extending the watchpoint callback data structures, we just
+ // automatize what the user would do manually: make their watchpoint
+ // command be a function call
else if (!m_options.m_function_name.empty()) {
std::string oneliner(m_options.m_function_name);
oneliner += "(frame, wp, internal_dict)";
@@ -669,7 +669,7 @@ CommandObjectWatchpointCommand::CommandObjectWatchpointCommand(
: CommandObjectMultiword(
interpreter, "command",
"Commands for adding, removing and examining LLDB commands "
- "executed when the watchpoint is hit (watchpoint 'commmands').",
+ "executed when the watchpoint is hit (watchpoint 'commands').",
"command <sub-command> [<sub-command-options>] <watchpoint-id>") {
CommandObjectSP add_command_object(
new CommandObjectWatchpointCommandAdd(interpreter));
diff --git a/contrib/llvm/tools/lldb/source/Core/Address.cpp b/contrib/llvm/tools/lldb/source/Core/Address.cpp
index 54b485ce0354..f183245f7d36 100644
--- a/contrib/llvm/tools/lldb/source/Core/Address.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Address.cpp
@@ -141,8 +141,8 @@ static bool ReadAddress(ExecutionContextScope *exe_scope,
deref_so_addr))
return true;
} else {
- // If we were not running, yet able to read an integer, we must
- // have a module
+ // If we were not running, yet able to read an integer, we must have a
+ // module
ModuleSP module_sp(address.GetModule());
assert(module_sp);
@@ -151,8 +151,8 @@ static bool ReadAddress(ExecutionContextScope *exe_scope,
}
// We couldn't make "deref_addr" into a section offset value, but we were
- // able to read the address, so we return a section offset address with
- // no section and "deref_addr" as the offset (address).
+ // able to read the address, so we return a section offset address with no
+ // section and "deref_addr" as the offset (address).
deref_so_addr.SetRawAddress(deref_addr);
return true;
}
@@ -278,12 +278,12 @@ addr_t Address::GetFileAddress() const {
// Section isn't resolved, we can't return a valid file address
return LLDB_INVALID_ADDRESS;
}
- // We have a valid file range, so we can return the file based
- // address by adding the file base address to our offset
+ // We have a valid file range, so we can return the file based address by
+ // adding the file base address to our offset
return sect_file_addr + m_offset;
} else if (SectionWasDeletedPrivate()) {
- // Used to have a valid section but it got deleted so the
- // offset doesn't mean anything without the section
+ // Used to have a valid section but it got deleted so the offset doesn't
+ // mean anything without the section
return LLDB_INVALID_ADDRESS;
}
// No section, we just return the offset since it is the value in this case
@@ -297,21 +297,21 @@ addr_t Address::GetLoadAddress(Target *target) const {
addr_t sect_load_addr = section_sp->GetLoadBaseAddress(target);
if (sect_load_addr != LLDB_INVALID_ADDRESS) {
- // We have a valid file range, so we can return the file based
- // address by adding the file base address to our offset
+ // We have a valid file range, so we can return the file based address
+ // by adding the file base address to our offset
return sect_load_addr + m_offset;
}
}
} else if (SectionWasDeletedPrivate()) {
- // Used to have a valid section but it got deleted so the
- // offset doesn't mean anything without the section
+ // Used to have a valid section but it got deleted so the offset doesn't
+ // mean anything without the section
return LLDB_INVALID_ADDRESS;
} else {
// We don't have a section so the offset is the load address
return m_offset;
}
- // The section isn't resolved or an invalid target was passed in
- // so we can't return a valid load address.
+ // The section isn't resolved or an invalid target was passed in so we can't
+ // return a valid load address.
return LLDB_INVALID_ADDRESS;
}
@@ -351,7 +351,7 @@ addr_t Address::GetOpcodeLoadAddress(Target *target,
AddressClass addr_class) const {
addr_t code_addr = GetLoadAddress(target);
if (code_addr != LLDB_INVALID_ADDRESS) {
- if (addr_class == eAddressClassInvalid)
+ if (addr_class == AddressClass::eInvalid)
addr_class = GetAddressClass();
code_addr = target->GetOpcodeLoadAddress(code_addr, addr_class);
}
@@ -363,7 +363,7 @@ bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,
bool allow_section_end) {
if (SetLoadAddress(load_addr, target, allow_section_end)) {
if (target) {
- if (addr_class == eAddressClassInvalid)
+ if (addr_class == AddressClass::eInvalid)
addr_class = GetAddressClass();
m_offset = target->GetOpcodeLoadAddress(m_offset, addr_class);
}
@@ -375,16 +375,15 @@ bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,
bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
DumpStyle fallback_style, uint32_t addr_size) const {
// If the section was nullptr, only load address is going to work unless we
- // are
- // trying to deref a pointer
+ // are trying to deref a pointer
SectionSP section_sp(GetSection());
if (!section_sp && style != DumpStyleResolvedPointerDescription)
style = DumpStyleLoadAddress;
ExecutionContext exe_ctx(exe_scope);
Target *target = exe_ctx.GetTargetPtr();
- // If addr_byte_size is UINT32_MAX, then determine the correct address
- // byte size for the process or default to the size of addr_t
+ // If addr_byte_size is UINT32_MAX, then determine the correct address byte
+ // size for the process or default to the size of addr_t
if (addr_size == UINT32_MAX) {
if (target)
addr_size = target->GetArchitecture().GetAddressByteSize();
@@ -439,7 +438,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
/*
* MIPS:
* Display address in compressed form for MIPS16 or microMIPS
- * if the address belongs to eAddressClassCodeAlternateISA.
+ * if the address belongs to AddressClass::eCodeAlternateISA.
*/
if (target) {
const llvm::Triple::ArchType llvm_arch =
@@ -651,15 +650,15 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
}
}
if (show_stop_context) {
- // We have a function or a symbol from the same
- // sections as this address.
+ // We have a function or a symbol from the same sections as this
+ // address.
sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,
show_module, show_inlined_frames,
show_function_arguments, show_function_name);
} else {
- // We found a symbol but it was in a different
- // section so it isn't the symbol we should be
- // showing, just show the section name + offset
+ // We found a symbol but it was in a different section so it
+ // isn't the symbol we should be showing, just show the section
+ // name + offset
Dump(s, exe_scope, DumpStyleSectionNameOffset);
}
}
@@ -680,10 +679,10 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
module_sp->ResolveSymbolContextForAddress(
*this, eSymbolContextEverything | eSymbolContextVariable, sc);
if (sc.symbol) {
- // If we have just a symbol make sure it is in the same section
- // as our address. If it isn't, then we might have just found
- // the last symbol that came before the address that we are
- // looking up that has nothing to do with our address lookup.
+ // If we have just a symbol make sure it is in the same section as
+ // our address. If it isn't, then we might have just found the last
+ // symbol that came before the address that we are looking up that
+ // has nothing to do with our address lookup.
if (sc.symbol->ValueIsAddress() &&
sc.symbol->GetAddressRef().GetSection() != GetSection())
sc.symbol = nullptr;
@@ -771,14 +770,11 @@ bool Address::SectionWasDeletedPrivate() const {
lldb::SectionWP empty_section_wp;
// If either call to "std::weak_ptr::owner_before(...) value returns true,
- // this
- // indicates that m_section_wp once contained (possibly still does) a
- // reference
- // to a valid shared pointer. This helps us know if we had a valid reference
- // to
- // a section which is now invalid because the module it was in was
- // unloaded/deleted,
- // or if the address doesn't have a valid reference to a section.
+ // this indicates that m_section_wp once contained (possibly still does) a
+ // reference to a valid shared pointer. This helps us know if we had a valid
+ // reference to a section which is now invalid because the module it was in
+ // was unloaded/deleted, or if the address doesn't have a valid reference to
+ // a section.
return empty_section_wp.owner_before(m_section_wp) ||
m_section_wp.owner_before(empty_section_wp);
}
@@ -914,8 +910,8 @@ int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) {
return -1;
if (a_module > b_module)
return +1;
- // Modules are the same, just compare the file address since they should
- // be unique
+ // Modules are the same, just compare the file address since they should be
+ // unique
addr_t a_file_addr = a.GetFileAddress();
addr_t b_file_addr = b.GetFileAddress();
if (a_file_addr < b_file_addr)
@@ -926,24 +922,23 @@ int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) {
}
size_t Address::MemorySize() const {
- // Noting special for the memory size of a single Address object,
- // it is just the size of itself.
+ // Noting special for the memory size of a single Address object, it is just
+ // the size of itself.
return sizeof(Address);
}
//----------------------------------------------------------------------
// NOTE: Be careful using this operator. It can correctly compare two
-// addresses from the same Module correctly. It can't compare two
-// addresses from different modules in any meaningful way, but it will
-// compare the module pointers.
+// addresses from the same Module correctly. It can't compare two addresses
+// from different modules in any meaningful way, but it will compare the module
+// pointers.
//
// To sum things up:
-// - works great for addresses within the same module
-// - it works for addresses across multiple modules, but don't expect the
+// - works great for addresses within the same module - it works for addresses
+// across multiple modules, but don't expect the
// address results to make much sense
//
-// This basically lets Address objects be used in ordered collection
-// classes.
+// This basically lets Address objects be used in ordered collection classes.
//----------------------------------------------------------------------
bool lldb_private::operator<(const Address &lhs, const Address &rhs) {
@@ -955,8 +950,8 @@ bool lldb_private::operator<(const Address &lhs, const Address &rhs) {
// Addresses are in the same module, just compare the file addresses
return lhs.GetFileAddress() < rhs.GetFileAddress();
} else {
- // The addresses are from different modules, just use the module
- // pointer value to get consistent ordering
+ // The addresses are from different modules, just use the module pointer
+ // value to get consistent ordering
return lhs_module < rhs_module;
}
}
@@ -970,8 +965,8 @@ bool lldb_private::operator>(const Address &lhs, const Address &rhs) {
// Addresses are in the same module, just compare the file addresses
return lhs.GetFileAddress() > rhs.GetFileAddress();
} else {
- // The addresses are from different modules, just use the module
- // pointer value to get consistent ordering
+ // The addresses are from different modules, just use the module pointer
+ // value to get consistent ordering
return lhs_module > rhs_module;
}
}
@@ -997,7 +992,7 @@ AddressClass Address::GetAddressClass() const {
return obj_file->GetAddressClass(GetFileAddress());
}
}
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
}
bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,
diff --git a/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp b/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
index 9935362e0e98..c3dab6d10810 100644
--- a/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
@@ -62,9 +62,8 @@ AddressResolverName::~AddressResolverName() = default;
// FIXME: Right now we look at the module level, and call the module's
// "FindFunctions".
// Greg says he will add function tables, maybe at the CompileUnit level to
-// accelerate function
-// lookup. At that point, we should switch the depth to CompileUnit, and look
-// in these tables.
+// accelerate function lookup. At that point, we should switch the depth to
+// CompileUnit, and look in these tables.
Searcher::CallbackReturn
AddressResolverName::SearchCallback(SearchFilter &filter,
diff --git a/contrib/llvm/tools/lldb/source/Core/Broadcaster.cpp b/contrib/llvm/tools/lldb/source/Core/Broadcaster.cpp
index 7a4932c4987e..198434b46c29 100644
--- a/contrib/llvm/tools/lldb/source/Core/Broadcaster.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Broadcaster.cpp
@@ -74,9 +74,8 @@ Broadcaster::BroadcasterImpl::GetListeners() {
void Broadcaster::BroadcasterImpl::Clear() {
std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
- // Make sure the listener forgets about this broadcaster. We do
- // this in the broadcaster in case the broadcaster object initiates
- // the removal.
+ // Make sure the listener forgets about this broadcaster. We do this in the
+ // broadcaster in case the broadcaster object initiates the removal.
for (auto &pair : GetListeners())
pair.first->BroadcasterWillDestruct(&m_broadcaster);
diff --git a/contrib/llvm/tools/lldb/source/Core/Communication.cpp b/contrib/llvm/tools/lldb/source/Core/Communication.cpp
index 38ab902ab4b7..5ca338639de0 100644
--- a/contrib/llvm/tools/lldb/source/Core/Communication.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Communication.cpp
@@ -97,15 +97,15 @@ ConnectionStatus Communication::Disconnect(Status *error_ptr) {
lldb::ConnectionSP connection_sp(m_connection_sp);
if (connection_sp) {
ConnectionStatus status = connection_sp->Disconnect(error_ptr);
- // We currently don't protect connection_sp with any mutex for
- // multi-threaded environments. So lets not nuke our connection class
- // without putting some multi-threaded protections in. We also probably
- // don't want to pay for the overhead it might cause if every time we
- // access the connection we have to take a lock.
+ // We currently don't protect connection_sp with any mutex for multi-
+ // threaded environments. So lets not nuke our connection class without
+ // putting some multi-threaded protections in. We also probably don't want
+ // to pay for the overhead it might cause if every time we access the
+ // connection we have to take a lock.
//
- // This unique pointer will cleanup after itself when this object goes away,
- // so there is no need to currently have it destroy itself immediately
- // upon disconnnect.
+ // This unique pointer will cleanup after itself when this object goes
+ // away, so there is no need to currently have it destroy itself
+ // immediately upon disconnect.
// connection_sp.reset();
return status;
}
@@ -240,8 +240,8 @@ bool Communication::JoinReadThread(Status *error_ptr) {
size_t Communication::GetCachedBytes(void *dst, size_t dst_len) {
std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex);
if (!m_bytes.empty()) {
- // If DST is nullptr and we have a thread, then return the number
- // of bytes that are available so the caller can call again
+ // If DST is nullptr and we have a thread, then return the number of bytes
+ // that are available so the caller can call again
if (dst == nullptr)
return m_bytes.size();
@@ -337,8 +337,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
case eConnectionStatusInterrupted: // Synchronization signal from
// SynchronizeWithReadThread()
// The connection returns eConnectionStatusInterrupted only when there is
- // no
- // input pending to be read, so we can signal that.
+ // no input pending to be read, so we can signal that.
comm->BroadcastEvent(eBroadcastBitNoMorePendingInput);
break;
case eConnectionStatusNoConnection: // No connection
diff --git a/contrib/llvm/tools/lldb/source/Core/Debugger.cpp b/contrib/llvm/tools/lldb/source/Core/Debugger.cpp
index 75b762f085cb..972d0bc0a6d7 100644
--- a/contrib/llvm/tools/lldb/source/Core/Debugger.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Debugger.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Listener.h" // for Listener
#include "lldb/Core/Mangled.h" // for Mangled
+#include "lldb/Core/ModuleList.h" // for Mangled
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamAsynchronousIO.h"
@@ -47,7 +48,7 @@
#include "lldb/Utility/StreamCallback.h"
#include "lldb/Utility/StreamString.h"
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
#endif
@@ -166,13 +167,15 @@ OptionEnumValueElement g_language_enumerators[] = {
"}${addr-file-or-load}{ " \
"<${function.concrete-only-addr-offset-no-padding}>}: "
-// gdb's disassembly format can be emulated with
-// ${current-pc-arrow}${addr-file-or-load}{
-// <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}:
+// gdb's disassembly format can be emulated with ${current-pc-arrow}${addr-
+// file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-
+// offset-no-padding}>}:
// lldb's original format for disassembly would look like this format string -
-// {${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow}
-// }{${addr-file-or-load}}:
+// {${function.initial-function}{${module.file.basename}`}{${function.name-
+// without-
+// args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
+// without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
#define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
#define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
@@ -589,9 +592,9 @@ bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
return true;
}
} else {
- // The g_load_plugin_callback is registered in SBDebugger::Initialize()
- // and if the public API layer isn't available (code is linking against
- // all of the internal LLDB static libraries), then we can't load plugins
+ // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
+ // if the public API layer isn't available (code is linking against all of
+ // the internal LLDB static libraries), then we can't load plugins
error.SetErrorString("Public API layer is not available");
}
return false;
@@ -602,8 +605,8 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
const FileSpec &file_spec) {
Status error;
- static ConstString g_dylibext("dylib");
- static ConstString g_solibext("so");
+ static ConstString g_dylibext(".dylib");
+ static ConstString g_solibext(".so");
if (!baton)
return FileSpec::eEnumerateDirectoryResultQuit;
@@ -611,8 +614,8 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
Debugger *debugger = (Debugger *)baton;
namespace fs = llvm::sys::fs;
- // If we have a regular file, a symbolic link or unknown file type, try
- // and process the file. We must handle unknown as sometimes the directory
+ // If we have a regular file, a symbolic link or unknown file type, try and
+ // process the file. We must handle unknown as sometimes the directory
// enumeration might be enumerating a file system that doesn't have correct
// file type information.
if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
@@ -632,9 +635,9 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
} else if (ft == fs::file_type::directory_file ||
ft == fs::file_type::symlink_file ||
ft == fs::file_type::type_unknown) {
- // Try and recurse into anything that a directory or symbolic link.
- // We must also do this for unknown as sometimes the directory enumeration
- // might be enumerating a file system that doesn't have correct file type
+ // Try and recurse into anything that a directory or symbolic link. We must
+ // also do this for unknown as sometimes the directory enumeration might be
+ // enumerating a file system that doesn't have correct file type
// information.
return FileSpec::eEnumerateDirectoryResultEnter;
}
@@ -643,19 +646,18 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
}
void Debugger::InstanceInitialize() {
- FileSpec dir_spec;
const bool find_directories = true;
const bool find_files = true;
const bool find_other = true;
char dir_path[PATH_MAX];
- if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
+ if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
find_other, LoadPluginCallback, this);
}
}
- if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
+ if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
find_other, LoadPluginCallback, this);
@@ -774,6 +776,9 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
m_collection_sp->AppendProperty(
ConstString("platform"), ConstString("Platform settings."), true,
Platform::GetGlobalPlatformProperties()->GetValueProperties());
+ m_collection_sp->AppendProperty(
+ ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
+ true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
if (m_command_interpreter_ap) {
m_collection_sp->AppendProperty(
ConstString("interpreter"),
@@ -796,10 +801,9 @@ Debugger::~Debugger() { Clear(); }
void Debugger::Clear() {
//----------------------------------------------------------------------
- // Make sure we call this function only once. With the C++ global
- // destructor chain having a list of debuggers and with code that can be
- // running on other threads, we need to ensure this doesn't happen
- // multiple times.
+ // Make sure we call this function only once. With the C++ global destructor
+ // chain having a list of debuggers and with code that can be running on
+ // other threads, we need to ensure this doesn't happen multiple times.
//
// The following functions call Debugger::Clear():
// Debugger::~Debugger();
@@ -824,8 +828,7 @@ void Debugger::Clear() {
m_broadcaster_manager_sp->Clear();
// Close the input file _before_ we close the input read communications
- // class
- // as it does NOT own the input file, our m_input_file does.
+ // class as it does NOT own the input file, our m_input_file does.
m_terminal_state.Clear();
if (m_input_file_sp)
m_input_file_sp->GetFile().Close();
@@ -861,8 +864,8 @@ void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
if (!in_file.IsValid())
in_file.SetStream(stdin, true);
- // Save away the terminal state if that is relevant, so that we can restore it
- // in RestoreInputState.
+ // Save away the terminal state if that is relevant, so that we can restore
+ // it in RestoreInputState.
SaveInputTerminalState();
}
@@ -876,8 +879,8 @@ void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
if (!out_file.IsValid())
out_file.SetStream(stdout, false);
- // do not create the ScriptInterpreter just for setting the output file handle
- // as the constructor will know how to do the right thing on its own
+ // do not create the ScriptInterpreter just for setting the output file
+ // handle as the constructor will know how to do the right thing on its own
const bool can_create = false;
ScriptInterpreter *script_interpreter =
GetCommandInterpreter().GetScriptInterpreter(can_create);
@@ -1023,11 +1026,10 @@ void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
StreamFileSP &out,
StreamFileSP &err) {
- // Before an IOHandler runs, it must have in/out/err streams.
- // This function is called when one ore more of the streams
- // are nullptr. We use the top input reader's in/out/err streams,
- // or fall back to the debugger file handles, or we fall back
- // onto stdin/stdout/stderr as a last resort.
+ // Before an IOHandler runs, it must have in/out/err streams. This function
+ // is called when one ore more of the streams are nullptr. We use the top
+ // input reader's in/out/err streams, or fall back to the debugger file
+ // handles, or we fall back onto stdin/stdout/stderr as a last resort.
std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
@@ -1083,8 +1085,8 @@ void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
m_input_reader_stack.Push(reader_sp);
reader_sp->Activate();
- // Interrupt the top input reader to it will exit its Run() function
- // and let this new input reader take over
+ // Interrupt the top input reader to it will exit its Run() function and let
+ // this new input reader take over
if (top_reader_sp) {
top_reader_sp->Deactivate();
top_reader_sp->Cancel();
@@ -1097,8 +1099,8 @@ bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
- // The reader on the stop of the stack is done, so let the next
- // read on the stack refresh its prompt and if there is one...
+ // The reader on the stop of the stack is done, so let the next read on the
+ // stack refresh its prompt and if there is one...
if (m_input_reader_stack.IsEmpty())
return false;
@@ -1193,8 +1195,8 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
}
}
}
- // The first context on a list of instructions will have a prev_sc that
- // has no Function or Symbol -- if SymbolContext had an IsValid() method, it
+ // The first context on a list of instructions will have a prev_sc that has
+ // no Function or Symbol -- if SymbolContext had an IsValid() method, it
// would return false. But we do get a prev_sc pointer.
if ((sc && (sc->function || sc->symbol)) && prev_sc &&
(prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
@@ -1238,8 +1240,8 @@ bool Debugger::EnableLog(llvm::StringRef channel,
if (log_options & LLDB_LOG_OPTION_APPEND)
flags |= llvm::sys::fs::F_Append;
int FD;
- if (std::error_code ec =
- llvm::sys::fs::openFileForWrite(log_file, FD, flags)) {
+ if (std::error_code ec = llvm::sys::fs::openFileForWrite(
+ log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) {
error_stream << "Unable to open log file: " << ec.message();
return false;
}
@@ -1460,8 +1462,8 @@ void Debugger::HandleProcessEvent(const EventSP &event_sp) {
}
void Debugger::HandleThreadEvent(const EventSP &event_sp) {
- // At present the only thread event we handle is the Frame Changed event,
- // and all we do for that is just reprint the thread status for that thread.
+ // At present the only thread event we handle is the Frame Changed event, and
+ // all we do for that is just reprint the thread status for that thread.
using namespace lldb;
const uint32_t event_type = event_sp->GetType();
const bool stop_format = true;
@@ -1514,8 +1516,8 @@ void Debugger::DefaultEventHandler() {
CommandInterpreter::eBroadcastBitAsynchronousOutputData |
CommandInterpreter::eBroadcastBitAsynchronousErrorData);
- // Let the thread that spawned us know that we have started up and
- // that we are now listening to all required events so no events get missed
+ // Let the thread that spawned us know that we have started up and that we
+ // are now listening to all required events so no events get missed
m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
bool done = false;
@@ -1580,27 +1582,28 @@ lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
bool Debugger::StartEventHandlerThread() {
if (!m_event_handler_thread.IsJoinable()) {
- // We must synchronize with the DefaultEventHandler() thread to ensure
- // it is up and running and listening to events before we return from
- // this function. We do this by listening to events for the
+ // We must synchronize with the DefaultEventHandler() thread to ensure it
+ // is up and running and listening to events before we return from this
+ // function. We do this by listening to events for the
// eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
- ListenerSP listener_sp(
- Listener::MakeListener("lldb.debugger.event-handler"));
+ ConstString full_name("lldb.debugger.event-handler");
+ ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
listener_sp->StartListeningForEvents(&m_sync_broadcaster,
eBroadcastBitEventThreadIsListening);
+ auto thread_name =
+ full_name.GetLength() < llvm::get_max_thread_name_length() ?
+ full_name.AsCString() : "dbg.evt-handler";
+
// Use larger 8MB stack for this thread
- m_event_handler_thread = ThreadLauncher::LaunchThread(
- "lldb.debugger.event-handler", EventHandlerThread, this, nullptr,
- g_debugger_event_thread_stack_bytes);
-
- // Make sure DefaultEventHandler() is running and listening to events before
- // we return
- // from this function. We are only listening for events of type
- // eBroadcastBitEventThreadIsListening so we don't need to check the event,
- // we just need
- // to wait an infinite amount of time for it (nullptr timeout as the first
- // parameter)
+ m_event_handler_thread = ThreadLauncher::LaunchThread(thread_name,
+ EventHandlerThread, this, nullptr, g_debugger_event_thread_stack_bytes);
+
+ // Make sure DefaultEventHandler() is running and listening to events
+ // before we return from this function. We are only listening for events of
+ // type eBroadcastBitEventThreadIsListening so we don't need to check the
+ // event, we just need to wait an infinite amount of time for it (nullptr
+ // timeout as the first parameter)
lldb::EventSP event_sp;
listener_sp->GetEvent(event_sp, llvm::None);
}
diff --git a/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp b/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp
index 6d463d552da6..d41a19465280 100644
--- a/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp
@@ -96,8 +96,8 @@ DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp,
const char *plugin_name) {
if (target_sp && flavor == nullptr) {
// FIXME - we don't have the mechanism in place to do per-architecture
- // settings. But since we know that for now
- // we only support flavors on x86 & x86_64,
+ // settings. But since we know that for now we only support flavors on x86
+ // & x86_64,
if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
arch.GetTriple().getArch() == llvm::Triple::x86_64)
flavor = target_sp->GetDisassemblyFlavor();
@@ -108,19 +108,19 @@ DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp,
static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr,
Address &resolved_addr) {
if (!addr.IsSectionOffset()) {
- // If we weren't passed in a section offset address range,
- // try and resolve it to something
+ // If we weren't passed in a section offset address range, try and resolve
+ // it to something
Target *target = exe_ctx.GetTargetPtr();
if (target) {
- if (target->GetSectionLoadList().IsEmpty()) {
- target->GetImages().ResolveFileAddress(addr.GetOffset(), resolved_addr);
- } else {
- target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(),
- resolved_addr);
- }
- // We weren't able to resolve the address, just treat it as a
- // raw address
- if (resolved_addr.IsValid())
+ bool is_resolved =
+ target->GetSectionLoadList().IsEmpty() ?
+ target->GetImages().ResolveFileAddress(addr.GetOffset(),
+ resolved_addr) :
+ target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(),
+ resolved_addr);
+
+ // We weren't able to resolve the address, just treat it as a raw address
+ if (is_resolved && resolved_addr.IsValid())
return;
}
}
@@ -410,15 +410,13 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
disassembly_format = &format;
}
- // First pass: step through the list of instructions,
- // find how long the initial addresses strings are, insert padding
- // in the second pass so the opcodes all line up nicely.
+ // First pass: step through the list of instructions, find how long the
+ // initial addresses strings are, insert padding in the second pass so the
+ // opcodes all line up nicely.
// Also build up the source line mapping if this is mixed source & assembly
- // mode.
- // Calculate the source line for each assembly instruction (eliding inlined
- // functions
- // which the user wants to skip).
+ // mode. Calculate the source line for each assembly instruction (eliding
+ // inlined functions which the user wants to skip).
std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
Symbol *previous_symbol = nullptr;
@@ -495,17 +493,13 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
if (mixed_source_and_assembly) {
// If we've started a new function (non-inlined), print all of the
- // source lines from the
- // function declaration until the first line table entry - typically
- // the opening curly brace of
- // the function.
+ // source lines from the function declaration until the first line
+ // table entry - typically the opening curly brace of the function.
if (previous_symbol != sc.symbol) {
- // The default disassembly format puts an extra blank line between
- // functions - so
- // when we're displaying the source context for a function, we
- // don't want to add
- // a blank line after the source context or we'll end up with two
- // of them.
+ // The default disassembly format puts an extra blank line
+ // between functions - so when we're displaying the source
+ // context for a function, we don't want to add a blank line
+ // after the source context or we'll end up with two of them.
if (previous_symbol != nullptr)
source_lines_to_display.print_source_context_end_eol = false;
@@ -520,9 +514,9 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
func_decl_line);
if (func_decl_file == prologue_end_line.file ||
func_decl_file == prologue_end_line.original_file) {
- // Add all the lines between the function declaration
- // and the first non-prologue source line to the list
- // of lines to print.
+ // Add all the lines between the function declaration and
+ // the first non-prologue source line to the list of lines
+ // to print.
for (uint32_t lineno = func_decl_line;
lineno <= prologue_end_line.line; lineno++) {
SourceLine this_line;
@@ -530,8 +524,8 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
this_line.line = lineno;
source_lines_to_display.lines.push_back(this_line);
}
- // Mark the last line as the "current" one. Usually
- // this is the open curly brace.
+ // Mark the last line as the "current" one. Usually this
+ // is the open curly brace.
if (source_lines_to_display.lines.size() > 0)
source_lines_to_display.current_source_line =
source_lines_to_display.lines.size() - 1;
@@ -542,8 +536,8 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
current_source_line_range);
}
- // If we've left a previous source line's address range, print a new
- // source line
+ // If we've left a previous source line's address range, print a
+ // new source line
if (!current_source_line_range.ContainsFileAddress(addr)) {
sc.GetAddressRange(scope, 0, use_inline_block_range,
current_source_line_range);
@@ -558,8 +552,8 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
// Only print this source line if it is different from the
// last source line we printed. There may have been inlined
// functions between these lines that we elided, resulting in
- // the same line being printed twice in a row for a contiguous
- // block of assembly instructions.
+ // the same line being printed twice in a row for a
+ // contiguous block of assembly instructions.
if (this_line != previous_line) {
std::vector<uint32_t> previous_lines;
@@ -683,7 +677,7 @@ Instruction::Instruction(const Address &address, AddressClass addr_class)
Instruction::~Instruction() = default;
AddressClass Instruction::GetAddressClass() {
- if (m_address_class == eAddressClassInvalid)
+ if (m_address_class == AddressClass::eInvalid)
m_address_class = m_address.GetAddressClass();
return m_address_class;
}
@@ -710,16 +704,16 @@ void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
if (show_bytes) {
if (m_opcode.GetType() == Opcode::eTypeBytes) {
- // x86_64 and i386 are the only ones that use bytes right now so
- // pad out the byte dump to be able to always show 15 bytes (3 chars each)
- // plus a space
+ // x86_64 and i386 are the only ones that use bytes right now so pad out
+ // the byte dump to be able to always show 15 bytes (3 chars each) plus a
+ // space
if (max_opcode_byte_size > 0)
m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
else
m_opcode.Dump(&ss, 15 * 3 + 1);
} else {
- // Else, we have ARM or MIPS which can show up to a uint32_t
- // 0x00000000 (10 spaces) plus two for padding...
+ // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000
+ // (10 spaces) plus two for padding...
if (max_opcode_byte_size > 0)
m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
else
@@ -903,7 +897,8 @@ OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) {
option_value_sp.reset();
return option_value_sp;
}
- // We've used the data_type to read an array; re-set the type to Invalid
+ // We've used the data_type to read an array; re-set the type to
+ // Invalid
data_type = OptionValue::eTypeInvalid;
} else if ((value[0] == '0') && (value[1] == 'x')) {
value_sp = std::make_shared<OptionValueUInt64>(0, 0);
@@ -1107,9 +1102,9 @@ InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
}
}
- // Hexagon needs the first instruction of the packet with the branch.
- // Go backwards until we find an instruction marked end-of-packet, or
- // until we hit start.
+ // Hexagon needs the first instruction of the packet with the branch. Go
+ // backwards until we find an instruction marked end-of-packet, or until we
+ // hit start.
if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) {
// If we didn't find a branch, find the last packet start.
if (next_branch == UINT32_MAX) {
@@ -1128,8 +1123,8 @@ InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
// If we have an error reading memory, return start
if (!error.Success())
return start;
- // check if this is the last instruction in a packet
- // bits 15:14 will be 11b or 00b for a duplex
+ // check if this is the last instruction in a packet bits 15:14 will be
+ // 11b or 00b for a duplex
if (((inst_bytes & 0xC000) == 0xC000) ||
((inst_bytes & 0xC000) == 0x0000)) {
// instruction after this should be the start of next packet
@@ -1257,8 +1252,7 @@ Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
m_flavor.assign(flavor);
// If this is an arm variant that can only include thumb (T16, T32)
- // instructions, force the arch triple to be "thumbv.." instead of
- // "armv..."
+ // instructions, force the arch triple to be "thumbv.." instead of "armv..."
if (arch.IsAlwaysThumbInstructions()) {
std::string thumb_arch_name(arch.GetTriple().getArchName().str());
// Replace "arm" with "thumb" so we get all thumb variants correct
@@ -1285,7 +1279,7 @@ const InstructionList &Disassembler::GetInstructionList() const {
//----------------------------------------------------------------------
PseudoInstruction::PseudoInstruction()
- : Instruction(Address(), eAddressClassUnknown), m_description() {}
+ : Instruction(Address(), AddressClass::eUnknown), m_description() {}
PseudoInstruction::~PseudoInstruction() = default;
diff --git a/contrib/llvm/tools/lldb/source/Core/DumpDataExtractor.cpp b/contrib/llvm/tools/lldb/source/Core/DumpDataExtractor.cpp
index e564e86478fc..049f4d3805a1 100644
--- a/contrib/llvm/tools/lldb/source/Core/DumpDataExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/DumpDataExtractor.cpp
@@ -239,8 +239,8 @@ lldb::offset_t lldb_private::DumpDataExtractor(
if (item_byte_size <= 8) {
uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
- // Avoid std::bitset<64>::to_string() since it is missing in
- // earlier C++ libraries
+ // Avoid std::bitset<64>::to_string() since it is missing in earlier
+ // C++ libraries
std::string binary_value(64, '0');
std::bitset<64> bits(uval64);
for (uint32_t i = 0; i < 64; ++i)
@@ -263,8 +263,8 @@ lldb::offset_t lldb_private::DumpDataExtractor(
s->Printf("%2.2x", DE.GetU8(&offset));
}
- // Put an extra space between the groups of bytes if more than one
- // is being dumped in a group (item_byte_size is more than 1).
+ // Put an extra space between the groups of bytes if more than one is
+ // being dumped in a group (item_byte_size is more than 1).
if (item_byte_size > 1)
s->PutChar(' ');
break;
@@ -279,8 +279,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
return offset;
}
- // If we are only printing one character surround it with single
- // quotes
+ // If we are only printing one character surround it with single quotes
if (item_count == 1 && item_format == eFormatChar)
s->PutChar('\'');
@@ -583,8 +582,10 @@ lldb::offset_t lldb_private::DumpDataExtractor(
} else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) {
const auto &semantics =
ast->getFloatTypeSemantics(ast->LongDoubleTy);
- const auto byte_size =
- (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
+
+ offset_t byte_size = item_byte_size;
+ if (&semantics == &llvm::APFloatBase::x87DoubleExtended())
+ byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
llvm::APInt apint;
if (GetAPInt(DE, &offset, byte_size, apint)) {
@@ -691,10 +692,9 @@ lldb::offset_t lldb_private::DumpDataExtractor(
break;
// please keep the single-item formats below in sync with
- // FormatManager::GetSingleItemFormat
- // if you fail to do so, users will start getting different outputs
- // depending on internal
- // implementation details they should not care about ||
+ // FormatManager::GetSingleItemFormat if you fail to do so, users will
+ // start getting different outputs depending on internal implementation
+ // details they should not care about ||
case eFormatVectorOfChar: // ||
s->PutChar('{'); // \/
offset =
diff --git a/contrib/llvm/tools/lldb/source/Core/DumpRegisterValue.cpp b/contrib/llvm/tools/lldb/source/Core/DumpRegisterValue.cpp
new file mode 100644
index 000000000000..99334ca78a6d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Core/DumpRegisterValue.cpp
@@ -0,0 +1,79 @@
+//===-- DumpRegisterValue.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DumpRegisterValue.h"
+#include "lldb/Core/DumpDataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-private-types.h"
+
+using namespace lldb;
+
+bool lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream *s,
+ const RegisterInfo *reg_info,
+ bool prefix_with_name,
+ bool prefix_with_alt_name, Format format,
+ uint32_t reg_name_right_align_at) {
+ DataExtractor data;
+ if (reg_val.GetData(data)) {
+ bool name_printed = false;
+ // For simplicity, alignment of the register name printing applies only in
+ // the most common case where:
+ //
+ // prefix_with_name^prefix_with_alt_name is true
+ //
+ StreamString format_string;
+ if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))
+ format_string.Printf("%%%us", reg_name_right_align_at);
+ else
+ format_string.Printf("%%s");
+ std::string fmt = format_string.GetString();
+ if (prefix_with_name) {
+ if (reg_info->name) {
+ s->Printf(fmt.c_str(), reg_info->name);
+ name_printed = true;
+ } else if (reg_info->alt_name) {
+ s->Printf(fmt.c_str(), reg_info->alt_name);
+ prefix_with_alt_name = false;
+ name_printed = true;
+ }
+ }
+ if (prefix_with_alt_name) {
+ if (name_printed)
+ s->PutChar('/');
+ if (reg_info->alt_name) {
+ s->Printf(fmt.c_str(), reg_info->alt_name);
+ name_printed = true;
+ } else if (!name_printed) {
+ // No alternate name but we were asked to display a name, so show the
+ // main name
+ s->Printf(fmt.c_str(), reg_info->name);
+ name_printed = true;
+ }
+ }
+ if (name_printed)
+ s->PutCString(" = ");
+
+ if (format == eFormatDefault)
+ format = reg_info->format;
+
+ DumpDataExtractor(data, s,
+ 0, // Offset in "data"
+ format, // Format to use when dumping
+ reg_info->byte_size, // item_byte_size
+ 1, // item_count
+ UINT32_MAX, // num_per_line
+ LLDB_INVALID_ADDRESS, // base_addr
+ 0, // item_bit_size
+ 0); // item_bit_offset
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp b/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp
index 5477498dadc8..16f1ffca1a20 100644
--- a/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp
@@ -64,8 +64,8 @@ DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
DynamicLoader::~DynamicLoader() = default;
//----------------------------------------------------------------------
-// Accessosors to the global setting as to whether to stop at image
-// (shared library) loading/unloading.
+// Accessosors to the global setting as to whether to stop at image (shared
+// library) loading/unloading.
//----------------------------------------------------------------------
bool DynamicLoader::GetStopWhenImagesChange() const {
@@ -86,8 +86,8 @@ ModuleSP DynamicLoader::GetTargetExecutable() {
executable->GetArchitecture());
auto module_sp = std::make_shared<Module>(module_spec);
- // Check if the executable has changed and set it to the target executable
- // if they differ.
+ // Check if the executable has changed and set it to the target
+ // executable if they differ.
if (module_sp && module_sp->GetUUID().IsValid() &&
executable->GetUUID().IsValid()) {
if (module_sp->GetUUID() != executable->GetUUID())
@@ -99,8 +99,8 @@ ModuleSP DynamicLoader::GetTargetExecutable() {
if (!executable) {
executable = target.GetSharedModule(module_spec);
if (executable.get() != target.GetExecutableModulePointer()) {
- // Don't load dependent images since we are in dyld where we will know
- // and find out about all images that are loaded
+ // Don't load dependent images since we are in dyld where we will
+ // know and find out about all images that are loaded
const bool get_dependent_images = false;
target.SetExecutableModule(executable, get_dependent_images);
}
@@ -177,8 +177,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
bool check_alternative_file_name = true;
if (base_addr_is_offset) {
// Try to fetch the load address of the file from the process as we need
- // absolute load
- // address to read the file out of the memory instead of a load bias.
+ // absolute load address to read the file out of the memory instead of a
+ // load bias.
bool is_loaded = false;
lldb::addr_t load_addr;
Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
@@ -188,9 +188,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
}
}
- // We failed to find the module based on its name. Lets try to check if we can
- // find a
- // different name based on the memory region info.
+ // We failed to find the module based on its name. Lets try to check if we
+ // can find a different name based on the memory region info.
if (check_alternative_file_name) {
MemoryRegionInfo memory_info;
Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
diff --git a/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp b/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp
index 2ee2c79de270..469022119c9e 100644
--- a/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp
@@ -10,6 +10,7 @@
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Address.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/StreamFile.h"
@@ -361,7 +362,7 @@ bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction,
const RegisterValue &reg_value) {
StreamFile strm(stdout, false);
strm.Printf(" Write to Register (name = %s, value = ", reg_info->name);
- reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+ DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
strm.PutCString(", context = ");
context.Dump(strm, instruction);
strm.EOL();
diff --git a/contrib/llvm/tools/lldb/source/Core/Event.cpp b/contrib/llvm/tools/lldb/source/Core/Event.cpp
index 8d351d8ba1a5..3ebad7acdef7 100644
--- a/contrib/llvm/tools/lldb/source/Core/Event.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Event.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/Event.h"
#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Stream.h"
@@ -134,14 +133,13 @@ const ConstString &EventDataBytes::GetFlavor() const {
void EventDataBytes::Dump(Stream *s) const {
size_t num_printable_chars =
std::count_if(m_bytes.begin(), m_bytes.end(), isprint);
- if (num_printable_chars == m_bytes.size()) {
- s->Printf("\"%s\"", m_bytes.c_str());
- } else if (!m_bytes.empty()) {
- DataExtractor data;
- data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder());
- DumpDataExtractor(data, s, 0, eFormatBytes, 1, m_bytes.size(), 32,
- LLDB_INVALID_ADDRESS, 0, 0);
- }
+ if (num_printable_chars == m_bytes.size())
+ s->Format("\"{0}\"", m_bytes);
+ else
+ s->Format("{0:$[ ]@[x-2]}", llvm::make_range(
+ reinterpret_cast<const uint8_t *>(m_bytes.data()),
+ reinterpret_cast<const uint8_t *>(m_bytes.data() +
+ m_bytes.size())));
}
const void *EventDataBytes::GetBytes() const {
diff --git a/contrib/llvm/tools/lldb/source/Core/FileLineResolver.cpp b/contrib/llvm/tools/lldb/source/Core/FileLineResolver.cpp
index 36f37f4a14d5..7f0f440252e7 100644
--- a/contrib/llvm/tools/lldb/source/Core/FileLineResolver.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/FileLineResolver.cpp
@@ -54,8 +54,8 @@ FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context,
while (file_idx != UINT32_MAX) {
line_table->FineLineEntriesForFileIndex(file_idx, append,
m_sc_list);
- // Get the next file index in case we have multiple file
- // entries for the same file
+ // Get the next file index in case we have multiple file entries
+ // for the same file
file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1,
m_file_spec, false);
}
diff --git a/contrib/llvm/tools/lldb/source/Core/FileSpecList.cpp b/contrib/llvm/tools/lldb/source/Core/FileSpecList.cpp
index 5b0bdac654e1..66e27b197447 100644
--- a/contrib/llvm/tools/lldb/source/Core/FileSpecList.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/FileSpecList.cpp
@@ -42,11 +42,10 @@ void FileSpecList::Append(const FileSpec &file_spec) {
}
//------------------------------------------------------------------
-// Only append the "file_spec" if this list doesn't already contain
-// it.
+// Only append the "file_spec" if this list doesn't already contain it.
//
-// Returns true if "file_spec" was added, false if this list already
-// contained a copy of "file_spec".
+// Returns true if "file_spec" was added, false if this list already contained
+// a copy of "file_spec".
//------------------------------------------------------------------
bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) {
collection::iterator end = m_files.end();
@@ -75,18 +74,18 @@ void FileSpecList::Dump(Stream *s, const char *separator_cstr) const {
}
//------------------------------------------------------------------
-// Find the index of the file in the file spec list that matches
-// "file_spec" starting "start_idx" entries into the file spec list.
+// Find the index of the file in the file spec list that matches "file_spec"
+// starting "start_idx" entries into the file spec list.
//
-// Returns the valid index of the file that matches "file_spec" if
-// it is found, else std::numeric_limits<uint32_t>::max() is returned.
+// Returns the valid index of the file that matches "file_spec" if it is found,
+// else std::numeric_limits<uint32_t>::max() is returned.
//------------------------------------------------------------------
size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
- bool full, bool remove_dots) const {
+ bool full) const {
const size_t num_files = m_files.size();
- // When looking for files, we will compare only the filename if the
- // FILE_SPEC argument is empty
+ // When looking for files, we will compare only the filename if the FILE_SPEC
+ // argument is empty
bool compare_filename_only = file_spec.GetDirectory().IsEmpty();
for (size_t idx = start_idx; idx < num_files; ++idx) {
@@ -96,7 +95,7 @@ size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
return idx;
} else {
- if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots))
+ if (FileSpec::Equal(m_files[idx], file_spec, full))
return idx;
}
}
@@ -106,8 +105,8 @@ size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
}
//------------------------------------------------------------------
-// Returns the FileSpec object at index "idx". If "idx" is out of
-// range, then an empty FileSpec object will be returned.
+// Returns the FileSpec object at index "idx". If "idx" is out of range, then
+// an empty FileSpec object will be returned.
//------------------------------------------------------------------
const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const {
if (idx < m_files.size())
@@ -123,11 +122,10 @@ const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const {
}
//------------------------------------------------------------------
-// Return the size in bytes that this object takes in memory. This
-// returns the size in bytes of this object's member variables and
-// any FileSpec objects its member variables contain, the result
-// doesn't not include the string values for the directories any
-// filenames as those are in shared string pools.
+// Return the size in bytes that this object takes in memory. This returns the
+// size in bytes of this object's member variables and any FileSpec objects its
+// member variables contain, the result doesn't not include the string values
+// for the directories any filenames as those are in shared string pools.
//------------------------------------------------------------------
size_t FileSpecList::MemorySize() const {
size_t mem_size = sizeof(FileSpecList);
diff --git a/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp b/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp
index 0cb74cc7658d..743c7c404994 100644
--- a/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h" // for AddressRange
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/RegisterValue.h" // for RegisterValue
#include "lldb/Core/ValueObject.h"
@@ -467,10 +468,9 @@ static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
if (sc->function) {
func_addr = sc->function->GetAddressRange().GetBaseAddress();
if (sc->block && !concrete_only) {
- // Check to make sure we aren't in an inline
- // function. If we are, use the inline block
- // range that contains "format_addr" since
- // blocks can be discontiguous.
+ // Check to make sure we aren't in an inline function. If we are, use
+ // the inline block range that contains "format_addr" since blocks
+ // can be discontiguous.
Block *inline_block = sc->block->GetContainingInlinedBlock();
AddressRange inline_range;
if (inline_block &&
@@ -622,7 +622,7 @@ static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
if (reg_info) {
RegisterValue reg_value;
if (reg_ctx->ReadRegister(reg_info, reg_value)) {
- reg_value.Dump(&s, reg_info, false, false, format);
+ DumpRegisterValue(reg_value, &s, reg_info, false, false, format);
return true;
}
}
@@ -822,8 +822,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
if (do_deref_pointer && !is_array_range) {
// I have not deref-ed yet, let's do it
// this happens when we are not going through
- // GetValueForVariableExpressionPath
- // to get to the target ValueObject
+ // GetValueForVariableExpressionPath to get to the target ValueObject
Status error;
target = target->Dereference(error).get();
if (error.Fail()) {
@@ -842,9 +841,9 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
return false;
}
- // we do not want to use the summary for a bitfield of type T:n
- // if we were originally dealing with just a T - that would get
- // us into an endless recursion
+ // we do not want to use the summary for a bitfield of type T:n if we were
+ // originally dealing with just a T - that would get us into an endless
+ // recursion
if (target->IsBitfield() && was_var_indexed) {
// TODO: check for a (T:n)-specific summary - we should still obey that
StreamString bitfield_name;
@@ -905,8 +904,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
}
// if directly trying to print ${var}, and this is an aggregate, display a
- // nice
- // type @ location message
+ // nice type @ location message
if (is_aggregate && was_plain_var) {
s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
return true;
@@ -1021,7 +1019,7 @@ static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
if (reg_info) {
RegisterValue reg_value;
if (reg_ctx->ReadRegister(reg_info, reg_value)) {
- reg_value.Dump(&s, reg_info, false, false, format);
+ DumpRegisterValue(reg_value, &s, reg_info, false, false, format);
return true;
}
}
@@ -1142,8 +1140,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
if (!success)
break;
}
- // Only if all items in a scope succeed, then do we
- // print the output into the main stream
+ // Only if all items in a scope succeed, then do we print the output into
+ // the main stream
if (success)
s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
}
@@ -1206,9 +1204,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
// Watch for the special "tid" format...
if (entry.printf_format == "tid") {
// TODO(zturner): Rather than hardcoding this to be platform
- // specific, it should be controlled by a
- // setting and the default value of the setting can be different
- // depending on the platform.
+ // specific, it should be controlled by a setting and the default
+ // value of the setting can be different depending on the platform.
Target &target = thread->GetProcess()->GetTarget();
ArchSpec arch(target.GetArchitecture());
llvm::Triple::OSType ostype = arch.IsValid()
@@ -1914,9 +1911,9 @@ static Status ParseEntry(const llvm::StringRef &format_str,
error.SetErrorStringWithFormat("%s", error_strm.GetData());
} else if (sep_char == ':') {
// Any value whose separator is a with a ':' means this value has a
- // string argument
- // that needs to be stored in the entry (like "${script.var:}").
- // In this case the string value is the empty string which is ok.
+ // string argument that needs to be stored in the entry (like
+ // "${script.var:}"). In this case the string value is the empty
+ // string which is ok.
} else {
error.SetErrorStringWithFormat("%s", "invalid entry definitions");
}
@@ -1926,8 +1923,7 @@ static Status ParseEntry(const llvm::StringRef &format_str,
error = ParseEntry(value, entry_def, entry);
} else if (sep_char == ':') {
// Any value whose separator is a with a ':' means this value has a
- // string argument
- // that needs to be stored in the entry (like
+ // string argument that needs to be stored in the entry (like
// "${script.var:modulename.function}")
entry.string = value.str();
} else {
@@ -2065,17 +2061,17 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
case '0':
// 1 to 3 octal chars
{
- // Make a string that can hold onto the initial zero char,
- // up to 3 octal digits, and a terminating NULL.
+ // Make a string that can hold onto the initial zero char, up to 3
+ // octal digits, and a terminating NULL.
char oct_str[5] = {0, 0, 0, 0, 0};
int i;
for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
oct_str[i] = format[i];
- // We don't want to consume the last octal character since
- // the main for loop will do this for us, so we advance p by
- // one less than i (even if i is zero)
+ // We don't want to consume the last octal character since the main
+ // for loop will do this for us, so we advance p by one less than i
+ // (even if i is zero)
format = format.drop_front(i);
unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
if (octal_value <= UINT8_MAX) {
@@ -2115,8 +2111,8 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
break;
default:
- // Just desensitize any other character by just printing what
- // came after the '\'
+ // Just desensitize any other character by just printing what came
+ // after the '\'
parent_entry.AppendChar(desens_char);
break;
}
@@ -2142,10 +2138,9 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
if (!variable_format.empty()) {
entry.printf_format = variable_format.str();
- // If the format contains a '%' we are going to assume this is
- // a printf style format. So if you want to format your thread ID
- // using "0x%llx" you can use:
- // ${thread.id%0x%llx}
+ // If the format contains a '%' we are going to assume this is a
+ // printf style format. So if you want to format your thread ID
+ // using "0x%llx" you can use: ${thread.id%0x%llx}
//
// If there is no '%' in the format, then it is assumed to be a
// LLDB format name, or one of the extended formats specified in
@@ -2264,9 +2259,9 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
return error;
}
}
- // Check if this entry just wants to insert a constant string
- // value into the parent_entry, if so, insert the string with
- // AppendText, else append the entry to the parent_entry.
+ // Check if this entry just wants to insert a constant string value
+ // into the parent_entry, if so, insert the string with AppendText,
+ // else append the entry to the parent_entry.
if (entry.type == Entry::Type::InsertString)
parent_entry.AppendText(entry.string.c_str());
else
@@ -2350,12 +2345,11 @@ static void AddMatches(const FormatEntity::Entry::Definition *def,
}
}
-size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) {
- word_complete = false;
- str = str.drop_front(match_start_point);
- matches.Clear();
+size_t FormatEntity::AutoComplete(CompletionRequest &request) {
+ llvm::StringRef str = request.GetCursorArgumentPrefix().str();
+
+ request.SetWordComplete(false);
+ str = str.drop_front(request.GetMatchStartPoint());
const size_t dollar_pos = str.rfind('$');
if (dollar_pos == llvm::StringRef::npos)
@@ -2365,7 +2359,7 @@ size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point,
if (dollar_pos == str.size() - 1) {
std::string match = str.str();
match.append("{");
- matches.AppendString(match);
+ request.AddCompletion(match);
return 1;
}
@@ -2383,8 +2377,10 @@ size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point,
llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
if (partial_variable.empty()) {
// Suggest all top level entites as we are just past "${"
- AddMatches(&g_root, str, llvm::StringRef(), matches);
- return matches.GetSize();
+ StringList new_matches;
+ AddMatches(&g_root, str, llvm::StringRef(), new_matches);
+ request.AddCompletions(new_matches);
+ return request.GetNumberOfMatches();
}
// We have a partially specified variable, find it
@@ -2400,19 +2396,23 @@ size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point,
// Exact match
if (n > 0) {
// "${thread.info" <TAB>
- matches.AppendString(MakeMatch(str, "."));
+ request.AddCompletion(MakeMatch(str, "."));
} else {
// "${thread.id" <TAB>
- matches.AppendString(MakeMatch(str, "}"));
- word_complete = true;
+ request.AddCompletion(MakeMatch(str, "}"));
+ request.SetWordComplete(true);
}
} else if (remainder.equals(".")) {
// "${thread." <TAB>
- AddMatches(entry_def, str, llvm::StringRef(), matches);
+ StringList new_matches;
+ AddMatches(entry_def, str, llvm::StringRef(), new_matches);
+ request.AddCompletions(new_matches);
} else {
// We have a partial match
// "${thre" <TAB>
- AddMatches(entry_def, str, remainder, matches);
+ StringList new_matches;
+ AddMatches(entry_def, str, remainder, new_matches);
+ request.AddCompletions(new_matches);
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp b/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp
index 103b5ecde94a..e7ebeea1b88d 100644
--- a/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp
@@ -67,6 +67,7 @@
#include <assert.h> // for assert
#include <ctype.h> // for isspace
#include <errno.h> // for EINTR, errno
+#include <locale.h> // for setlocale
#include <stdint.h> // for uint32_t, UINT32_MAX
#include <stdio.h> // for size_t, fprintf, feof
#include <string.h> // for strlen
@@ -238,27 +239,21 @@ int IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler,
matches);
case Completion::Expression: {
- bool word_complete = false;
- const char *word_start = cursor;
- if (cursor > current_line)
- --word_start;
- while (word_start > current_line && !isspace(*word_start))
- --word_start;
+ CompletionRequest request(current_line, current_line - cursor,
+ skip_first_n_matches, max_matches, matches);
CommandCompletions::InvokeCommonCompletionCallbacks(
io_handler.GetDebugger().GetCommandInterpreter(),
- CommandCompletions::eVariablePathCompletion, word_start,
- skip_first_n_matches, max_matches, nullptr, word_complete, matches);
+ CommandCompletions::eVariablePathCompletion, request, nullptr);
- size_t num_matches = matches.GetSize();
+ size_t num_matches = request.GetNumberOfMatches();
if (num_matches > 0) {
std::string common_prefix;
matches.LongestCommonPrefix(common_prefix);
- const size_t partial_name_len = strlen(word_start);
+ const size_t partial_name_len = request.GetCursorArgumentPrefix().size();
- // If we matched a unique single command, add a space...
- // Only do this if the completer told us this was a complete word,
- // however...
- if (num_matches == 1 && word_complete) {
+ // If we matched a unique single command, add a space... Only do this if
+ // the completer told us this was a complete word, however...
+ if (num_matches == 1 && request.GetWordComplete()) {
common_prefix.push_back(' ');
}
common_prefix.erase(0, partial_name_len);
@@ -320,8 +315,7 @@ IOHandlerEditline::IOHandlerEditline(
const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
if (indent_chars) {
// The delegate does support indentation, hook it up so when any
- // indentation
- // character is typed, the delegate gets a chance to fix it
+ // indentation character is typed, the delegate gets a chance to fix it
m_editline_ap->SetFixIndentationCallback(FixIndentationCallback, this,
indent_chars);
}
@@ -407,8 +401,8 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
}
}
m_editing = false;
- // We might have gotten a newline on a line by itself
- // make sure to return true in this case.
+ // We might have gotten a newline on a line by itself make sure to return
+ // true in this case.
return got_line;
} else {
// No more input file, we are done...
@@ -544,9 +538,8 @@ bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
return success;
}
-// Each IOHandler gets to run until it is done. It should read data
-// from the "in" and place output into "out" and "err and return
-// when done.
+// Each IOHandler gets to run until it is done. It should read data from the
+// "in" and place output into "out" and "err and return when done.
void IOHandlerEditline::Run() {
std::string line;
while (IsActive()) {
@@ -634,8 +627,7 @@ void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) {
}
}
-// we may want curses to be disabled for some builds
-// for instance, windows
+// we may want curses to be disabled for some builds for instance, windows
#ifndef LLDB_DISABLE_CURSES
#define KEY_RETURN 10
@@ -737,9 +729,8 @@ struct Rect {
origin.y += h;
}
- // Return a status bar rectangle which is the last line of
- // this rectangle. This rectangle will be modified to not
- // include the status bar area.
+ // Return a status bar rectangle which is the last line of this rectangle.
+ // This rectangle will be modified to not include the status bar area.
Rect MakeStatusBar() {
Rect status_bar;
if (size.height > 1) {
@@ -752,9 +743,8 @@ struct Rect {
return status_bar;
}
- // Return a menubar rectangle which is the first line of
- // this rectangle. This rectangle will be modified to not
- // include the menubar area.
+ // Return a menubar rectangle which is the first line of this rectangle. This
+ // rectangle will be modified to not include the menubar area.
Rect MakeMenuBar() {
Rect menubar;
if (size.height > 1) {
@@ -1203,12 +1193,10 @@ public:
return result;
}
- // Then check for any windows that want any keys
- // that weren't handled. This is typically only
- // for a menubar.
- // Make a copy of the subwindows in case any HandleChar()
- // functions muck with the subwindows. If we don't do this,
- // we can crash when iterating over the subwindows.
+ // Then check for any windows that want any keys that weren't handled. This
+ // is typically only for a menubar. Make a copy of the subwindows in case
+ // any HandleChar() functions muck with the subwindows. If we don't do
+ // this, we can crash when iterating over the subwindows.
Windows subwindows(m_subwindows);
for (auto subwindow_sp : subwindows) {
if (!subwindow_sp->m_can_activate) {
@@ -1395,8 +1383,8 @@ public:
}
MenuActionResult Action() {
- // Call the recursive action so it can try to handle it
- // with the menu delegate, and if not, try our parent menu
+ // Call the recursive action so it can try to handle it with the menu
+ // delegate, and if not, try our parent menu
return ActionPrivate(*this);
}
@@ -1665,9 +1653,9 @@ HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
}
if (run_menu_sp) {
- // Run the action on this menu in case we need to populate the
- // menu with dynamic content and also in case check marks, and
- // any other menu decorations need to be calculated
+ // Run the action on this menu in case we need to populate the menu with
+ // dynamic content and also in case check marks, and any other menu
+ // decorations need to be calculated
if (run_menu_sp->Action() == MenuActionResult::Quit)
return eQuitApplication;
@@ -1781,12 +1769,11 @@ public:
bool done = false;
int delay_in_tenths_of_a_second = 1;
- // Alas the threading model in curses is a bit lame so we need to
- // resort to polling every 0.5 seconds. We could poll for stdin
- // ourselves and then pass the keys down but then we need to
- // translate all of the escape sequences ourselves. So we resort to
- // polling for input because we need to receive async process events
- // while in this loop.
+ // Alas the threading model in curses is a bit lame so we need to resort to
+ // polling every 0.5 seconds. We could poll for stdin ourselves and then
+ // pass the keys down but then we need to translate all of the escape
+ // sequences ourselves. So we resort to polling for input because we need
+ // to receive async process events while in this loop.
halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths
// of seconds seconds when calling
@@ -1807,9 +1794,9 @@ public:
while (!done) {
if (update) {
m_window_sp->Draw(false);
- // All windows should be calling Window::DeferredRefresh() instead
- // of Window::Refresh() so we can do a single update and avoid
- // any screen blinking
+ // All windows should be calling Window::DeferredRefresh() instead of
+ // Window::Refresh() so we can do a single update and avoid any screen
+ // blinking
update_panels();
// Cursor hiding isn't working on MacOSX, so hide it in the top left
@@ -1821,8 +1808,8 @@ public:
}
#if defined(__APPLE__)
- // Terminal.app doesn't map its function keys correctly, F1-F4 default to:
- // \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
+ // Terminal.app doesn't map its function keys correctly, F1-F4 default
+ // to: \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
// possible
int ch;
if (escape_chars.empty())
@@ -1985,8 +1972,8 @@ struct Row {
parent->DrawTreeForChild(window, this, 0);
if (might_have_children) {
- // It we can get UTF8 characters to work we should try to use the "symbol"
- // UTF8 string below
+ // It we can get UTF8 characters to work we should try to use the
+ // "symbol" UTF8 string below
// const char *symbol = "";
// if (row.expanded)
// symbol = "\xe2\x96\xbd ";
@@ -1994,14 +1981,14 @@ struct Row {
// symbol = "\xe2\x96\xb7 ";
// window.PutCString (symbol);
- // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
- // 'v' or '>' character...
+ // The ACS_DARROW and ACS_RARROW don't look very nice they are just a 'v'
+ // or '>' character...
// if (expanded)
// window.PutChar (ACS_DARROW);
// else
// window.PutChar (ACS_RARROW);
- // Since we can't find any good looking right arrow/down arrow
- // symbols, just use a diamond...
+ // Since we can't find any good looking right arrow/down arrow symbols,
+ // just use a diamond...
window.PutChar(ACS_DIAMOND);
window.PutChar(ACS_HLINE);
}
@@ -2101,9 +2088,8 @@ public:
const bool expanded = IsExpanded();
- // The root item must calculate its children,
- // or we must calculate the number of children
- // if the item is expanded
+ // The root item must calculate its children, or we must calculate the
+ // number of children if the item is expanded
if (m_parent == nullptr || expanded)
GetNumChildren();
@@ -2136,8 +2122,7 @@ public:
if (m_might_have_children) {
// It we can get UTF8 characters to work we should try to use the
- // "symbol"
- // UTF8 string below
+ // "symbol" UTF8 string below
// const char *symbol = "";
// if (row.expanded)
// symbol = "\xe2\x96\xbd ";
@@ -2151,8 +2136,8 @@ public:
// window.PutChar (ACS_DARROW);
// else
// window.PutChar (ACS_RARROW);
- // Since we can't find any good looking right arrow/down arrow
- // symbols, just use a diamond...
+ // Since we can't find any good looking right arrow/down arrow symbols,
+ // just use a diamond...
window.PutChar(ACS_DIAMOND);
window.PutChar(ACS_HLINE);
}
@@ -2175,8 +2160,8 @@ public:
if (IsExpanded()) {
for (auto &item : m_children) {
- // If we displayed all the rows and item.Draw() returns
- // false we are done drawing and can exit this for loop
+ // If we displayed all the rows and item.Draw() returns false we are
+ // done drawing and can exit this for loop
if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx,
num_rows_left))
break;
@@ -2286,10 +2271,9 @@ public:
m_num_rows = 0;
m_root.CalculateRowIndexes(m_num_rows);
- // If we unexpanded while having something selected our
- // total number of rows is less than the num visible rows,
- // then make sure we show all the rows by setting the first
- // visible row accordingly.
+ // If we unexpanded while having something selected our total number of
+ // rows is less than the num visible rows, then make sure we show all the
+ // rows by setting the first visible row accordingly.
if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
m_first_visible_row = 0;
@@ -2695,10 +2679,9 @@ public:
const int num_visible_rows = NumVisibleRows();
const int num_rows = CalculateTotalNumberRows(m_rows);
- // If we unexpanded while having something selected our
- // total number of rows is less than the num visible rows,
- // then make sure we show all the rows by setting the first
- // visible row accordingly.
+ // If we unexpanded while having something selected our total number of
+ // rows is less than the num visible rows, then make sure we show all the
+ // rows by setting the first visible row accordingly.
if (m_first_visible_row > 0 && num_rows < num_visible_rows)
m_first_visible_row = 0;
@@ -2714,8 +2697,8 @@ public:
// Get the selected row
m_selected_row = GetRowForRowIndex(m_selected_row_idx);
- // Keep the cursor on the selected row so the highlight and the cursor
- // are always on the same line
+ // Keep the cursor on the selected row so the highlight and the cursor are
+ // always on the same line
if (m_selected_row)
window.MoveCursor(m_selected_row->x, m_selected_row->y);
@@ -3127,8 +3110,8 @@ public:
if (process && process->IsAlive())
return true; // Don't do any updating if we are running
else {
- // Update the values with an empty list if there
- // is no process or the process isn't alive anymore
+ // Update the values with an empty list if there is no process or the
+ // process isn't alive anymore
SetValues(value_list);
}
}
@@ -3392,8 +3375,8 @@ HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window,
if (num_lines <= num_visible_lines) {
done = true;
- // If we have all lines visible and don't need scrolling, then any
- // key press will cause us to exit
+ // If we have all lines visible and don't need scrolling, then any key
+ // press will cause us to exit
} else {
switch (key) {
case KEY_UP:
@@ -3606,8 +3589,8 @@ public:
case eMenuID_Process: {
// Populate the menu with all of the threads if the process is stopped
- // when
- // the Process menu gets selected and is about to display its submenu.
+ // when the Process menu gets selected and is about to display its
+ // submenu.
Menus &submenus = menu.GetSubmenus();
ExecutionContext exe_ctx =
m_debugger.GetCommandInterpreter().GetExecutionContext();
@@ -3642,8 +3625,8 @@ public:
nullptr, menu_char, thread_sp->GetID())));
}
} else if (submenus.size() > 7) {
- // Remove the separator and any other thread submenu items
- // that were previously added
+ // Remove the separator and any other thread submenu items that were
+ // previously added
submenus.erase(submenus.begin() + 7, submenus.end());
}
// Since we are adding and removing items we need to recalculate the name
@@ -3671,8 +3654,8 @@ public:
registers_bounds.size.width = source_bounds.size.width;
registers_window_sp->SetBounds(registers_bounds);
} else {
- // We have no registers window showing so give the bottom
- // area back to the source view
+ // We have no registers window showing so give the bottom area back
+ // to the source view
source_window_sp->Resize(source_bounds.size.width,
source_bounds.size.height +
variables_bounds.size.height);
@@ -3721,8 +3704,8 @@ public:
registers_window_sp->GetWidth(),
variables_bounds.size.height);
} else {
- // We have no variables window showing so give the bottom
- // area back to the source view
+ // We have no variables window showing so give the bottom area back
+ // to the source view
source_window_sp->Resize(source_bounds.size.width,
source_bounds.size.height +
registers_window_sp->GetHeight());
@@ -3731,9 +3714,9 @@ public:
} else {
Rect new_regs_rect;
if (variables_window_sp) {
- // We have a variables window, split it into two columns
- // where the left hand side will be the variables and the
- // right hand side will be the registers
+ // We have a variables window, split it into two columns where the
+ // left hand side will be the variables and the right hand side will
+ // be the registers
const Rect variables_bounds = variables_window_sp->GetBounds();
Rect new_vars_rect;
variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect,
@@ -3945,8 +3928,8 @@ public:
m_selected_line = m_pc_line;
if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file)) {
- // Same file, nothing to do, we should either have the
- // lines or not (source file missing)
+ // Same file, nothing to do, we should either have the lines or not
+ // (source file missing)
if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) {
if (m_selected_line >= m_first_visible_line + num_visible_lines)
m_first_visible_line = m_selected_line - 10;
@@ -4627,8 +4610,8 @@ void IOHandlerCursesGUI::Activate() {
WindowSP menubar_window_sp =
main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
- // Let the menubar get keys if the active window doesn't handle the
- // keys that are typed so it can respond to menubar key presses.
+ // Let the menubar get keys if the active window doesn't handle the keys
+ // that are typed so it can respond to menubar key presses.
menubar_window_sp->SetCanBeActive(
false); // Don't let the menubar become the active window
menubar_window_sp->SetDelegate(menubar_sp);
diff --git a/contrib/llvm/tools/lldb/source/Core/Listener.cpp b/contrib/llvm/tools/lldb/source/Core/Listener.cpp
index 1afa11649b59..a39ce6121b32 100644
--- a/contrib/llvm/tools/lldb/source/Core/Listener.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Listener.cpp
@@ -304,11 +304,9 @@ bool Listener::FindNextEventInternal(
if (remove) {
m_events.erase(pos);
- // Unlock the event queue here. We've removed this event and are about to
- // return
- // it so it should be okay to get the next event off the queue here - and
- // it might
- // be useful to do that in the "DoOnRemoval".
+ // Unlock the event queue here. We've removed this event and are about
+ // to return it so it should be okay to get the next event off the queue
+ // here - and it might be useful to do that in the "DoOnRemoval".
lock.unlock();
event_sp->DoOnRemoval();
}
@@ -434,8 +432,8 @@ Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp,
if (!manager_sp)
return 0;
- // The BroadcasterManager mutex must be locked before m_broadcasters_mutex
- // to avoid violating the lock hierarchy (manager before broadcasters).
+ // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
+ // avoid violating the lock hierarchy (manager before broadcasters).
std::lock_guard<std::recursive_mutex> manager_guard(
manager_sp->m_manager_mutex);
std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
diff --git a/contrib/llvm/tools/lldb/source/Core/Mangled.cpp b/contrib/llvm/tools/lldb/source/Core/Mangled.cpp
index 211a0c32cee7..545ac51c870f 100644
--- a/contrib/llvm/tools/lldb/source/Core/Mangled.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Mangled.cpp
@@ -16,34 +16,24 @@
#pragma comment(lib, "dbghelp.lib")
#endif
-#ifdef LLDB_USE_BUILTIN_DEMANGLER
-// Provide a fast-path demangler implemented in FastDemangle.cpp until it can
-// replace the existing C++ demangler with a complete implementation
-#include "lldb/Utility/FastDemangle.h"
-#include "llvm/Demangle/Demangle.h"
-#else
-// FreeBSD9-STABLE requires this to know about size_t in cxxabi.
-#include <cstddef>
-#include <cxxabi.h>
-#endif
-
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
-#include "lldb/lldb-enumerations.h" // for LanguageType
+#include "lldb/lldb-enumerations.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
-#include "llvm/Support/Compiler.h" // for LLVM_PRETT...
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Demangle/Demangle.h"
+#include "llvm/Support/Compiler.h"
-#include <mutex> // for mutex, loc...
-#include <string> // for string
-#include <utility> // for pair
+#include <mutex>
+#include <string>
+#include <utility>
#include <stdlib.h>
#include <string.h>
@@ -90,10 +80,8 @@ get_demangled_name_without_arguments(ConstString mangled,
g_most_recent_mangled_to_name_sans_args;
// Need to have the mangled & demangled names we're currently examining as
- // statics
- // so we can return a const ref to them at the end of the func if we don't
- // have
- // anything better.
+ // statics so we can return a const ref to them at the end of the func if we
+ // don't have anything better.
static ConstString g_last_mangled;
static ConstString g_last_demangled;
@@ -142,8 +130,8 @@ get_demangled_name_without_arguments(ConstString mangled,
Mangled::Mangled() : m_mangled(), m_demangled() {}
//----------------------------------------------------------------------
-// Constructor with an optional string and a boolean indicating if it is
-// the mangled version.
+// Constructor with an optional string and a boolean indicating if it is the
+// mangled version.
//----------------------------------------------------------------------
Mangled::Mangled(const ConstString &s, bool mangled)
: m_mangled(), m_demangled() {
@@ -172,8 +160,8 @@ Mangled::Mangled(llvm::StringRef name) {
Mangled::~Mangled() {}
//----------------------------------------------------------------------
-// Convert to pointer operator. This allows code to check any Mangled
-// objects to see if they contain anything valid using code such as:
+// Convert to pointer operator. This allows code to check any Mangled objects
+// to see if they contain anything valid using code such as:
//
// Mangled mangled(...);
// if (mangled)
@@ -184,8 +172,8 @@ Mangled::operator void *() const {
}
//----------------------------------------------------------------------
-// Logical NOT operator. This allows code to check any Mangled
-// objects to see if they are invalid using code such as:
+// Logical NOT operator. This allows code to check any Mangled objects to see
+// if they are invalid using code such as:
//
// Mangled mangled(...);
// if (!file_spec)
@@ -211,9 +199,8 @@ int Mangled::Compare(const Mangled &a, const Mangled &b) {
}
//----------------------------------------------------------------------
-// Set the string value in this objects. If "mangled" is true, then
-// the mangled named is set with the new value in "s", else the
-// demangled name is set.
+// Set the string value in this objects. If "mangled" is true, then the mangled
+// named is set with the new value in "s", else the demangled name is set.
//----------------------------------------------------------------------
void Mangled::SetValue(const ConstString &s, bool mangled) {
if (s) {
@@ -246,16 +233,15 @@ void Mangled::SetValue(const ConstString &name) {
}
//----------------------------------------------------------------------
-// Generate the demangled name on demand using this accessor. Code in
-// this class will need to use this accessor if it wishes to decode
-// the demangled name. The result is cached and will be kept until a
-// new string value is supplied to this object, or until the end of the
-// object's lifetime.
+// Generate the demangled name on demand using this accessor. Code in this
+// class will need to use this accessor if it wishes to decode the demangled
+// name. The result is cached and will be kept until a new string value is
+// supplied to this object, or until the end of the object's lifetime.
//----------------------------------------------------------------------
const ConstString &
Mangled::GetDemangledName(lldb::LanguageType language) const {
- // Check to make sure we have a valid mangled name and that we
- // haven't already decoded our mangled name.
+ // Check to make sure we have a valid mangled name and that we haven't
+ // already decoded our mangled name.
if (m_mangled && !m_demangled) {
// We need to generate and cache the demangled name.
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
@@ -299,19 +285,15 @@ Mangled::GetDemangledName(lldb::LanguageType language) const {
break;
}
case eManglingSchemeItanium: {
-#ifdef LLDB_USE_BUILTIN_DEMANGLER
- if (log)
- log->Printf("demangle itanium: %s", mangled_name);
- // Try to use the fast-path demangler first for the
- // performance win, falling back to the full demangler only
- // when necessary
- demangled_name = FastDemangle(mangled_name, m_mangled.GetLength());
- if (!demangled_name)
- demangled_name =
- llvm::itaniumDemangle(mangled_name, NULL, NULL, NULL);
-#else
- demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
-#endif
+ llvm::ItaniumPartialDemangler IPD;
+ bool demangle_err = IPD.partialDemangle(mangled_name);
+ if (!demangle_err) {
+ // Default buffer and size (realloc is used in case it's too small).
+ size_t demangled_size = 80;
+ demangled_name = static_cast<char *>(::malloc(demangled_size));
+ demangled_name = IPD.finishDemangle(demangled_name, &demangled_size);
+ }
+
if (log) {
if (demangled_name)
log->Printf("demangled itanium: %s -> \"%s\"", mangled_name,
@@ -331,8 +313,8 @@ Mangled::GetDemangledName(lldb::LanguageType language) const {
}
}
if (!m_demangled) {
- // Set the demangled string to the empty string to indicate we
- // tried to parse it once and failed.
+ // Set the demangled string to the empty string to indicate we tried to
+ // parse it once and failed.
m_demangled.SetCString("");
}
}
@@ -370,8 +352,8 @@ ConstString Mangled::GetName(lldb::LanguageType language,
return get_demangled_name_without_arguments(m_mangled, demangled);
}
if (preference == ePreferDemangled) {
- // Call the accessor to make sure we get a demangled name in case
- // it hasn't been demangled yet...
+ // Call the accessor to make sure we get a demangled name in case it hasn't
+ // been demangled yet...
if (demangled)
return demangled;
return m_mangled;
@@ -380,8 +362,8 @@ ConstString Mangled::GetName(lldb::LanguageType language,
}
//----------------------------------------------------------------------
-// Dump a Mangled object to stream "s". We don't force our
-// demangled name to be computed currently (we don't use the accessor).
+// Dump a Mangled object to stream "s". We don't force our demangled name to be
+// computed currently (we don't use the accessor).
//----------------------------------------------------------------------
void Mangled::Dump(Stream *s) const {
if (m_mangled) {
@@ -394,8 +376,8 @@ void Mangled::Dump(Stream *s) const {
}
//----------------------------------------------------------------------
-// Dumps a debug version of this string with extra object and state
-// information to stream "s".
+// Dumps a debug version of this string with extra object and state information
+// to stream "s".
//----------------------------------------------------------------------
void Mangled::DumpDebug(Stream *s) const {
s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
@@ -406,21 +388,21 @@ void Mangled::DumpDebug(Stream *s) const {
}
//----------------------------------------------------------------------
-// Return the size in byte that this object takes in memory. The size
-// includes the size of the objects it owns, and not the strings that
-// it references because they are shared strings.
+// Return the size in byte that this object takes in memory. The size includes
+// the size of the objects it owns, and not the strings that it references
+// because they are shared strings.
//----------------------------------------------------------------------
size_t Mangled::MemorySize() const {
return m_mangled.MemorySize() + m_demangled.MemorySize();
}
//----------------------------------------------------------------------
-// We "guess" the language because we can't determine a symbol's language
-// from it's name. For example, a Pascal symbol can be mangled using the
-// C++ Itanium scheme, and defined in a compilation unit within the same
-// module as other C++ units. In addition, different targets could have
-// different ways of mangling names from a given language, likewise the
-// compilation units within those targets.
+// We "guess" the language because we can't determine a symbol's language from
+// it's name. For example, a Pascal symbol can be mangled using the C++
+// Itanium scheme, and defined in a compilation unit within the same module as
+// other C++ units. In addition, different targets could have different ways
+// of mangling names from a given language, likewise the compilation units
+// within those targets.
//----------------------------------------------------------------------
lldb::LanguageType Mangled::GuessLanguage() const {
ConstString mangled = GetMangledName();
@@ -433,7 +415,7 @@ lldb::LanguageType Mangled::GuessLanguage() const {
return lldb::eLanguageTypeObjC;
}
} else {
- // ObjC names aren't really mangled, so they won't necessarily be in the
+ // ObjC names aren't really mangled, so they won't necessarily be in the
// mangled name slot.
ConstString demangled_name = GetDemangledName(lldb::eLanguageTypeUnknown);
if (demangled_name
diff --git a/contrib/llvm/tools/lldb/source/Core/Module.cpp b/contrib/llvm/tools/lldb/source/Core/Module.cpp
index 8f80be45f1b0..3b1a4fd7be0f 100644
--- a/contrib/llvm/tools/lldb/source/Core/Module.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Module.cpp
@@ -38,6 +38,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h" // for GetLogIfAn...
#include "lldb/Utility/RegularExpression.h"
@@ -46,13 +47,12 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
#endif
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
-#include "Plugins/ObjectFile/JIT/ObjectFileJIT.h"
#include "llvm/ADT/STLExtras.h" // for make_unique
#include "llvm/Support/Compiler.h" // for LLVM_PRETT...
@@ -79,21 +79,17 @@ class VariableList;
using namespace lldb;
using namespace lldb_private;
-// Shared pointers to modules track module lifetimes in
-// targets and in the global module, but this collection
-// will track all module objects that are still alive
+// Shared pointers to modules track module lifetimes in targets and in the
+// global module, but this collection will track all module objects that are
+// still alive
typedef std::vector<Module *> ModuleCollection;
static ModuleCollection &GetModuleCollection() {
// This module collection needs to live past any module, so we could either
- // make it a
- // shared pointer in each module or just leak is. Since it is only an empty
- // vector by
- // the time all the modules have gone away, we just leak it for now. If we
- // decide this
- // is a big problem we can introduce a Finalize method that will tear
- // everything down in
- // a predictable order.
+ // make it a shared pointer in each module or just leak is. Since it is only
+ // an empty vector by the time all the modules have gone away, we just leak
+ // it for now. If we decide this is a big problem we can introduce a
+ // Finalize method that will tear everything down in a predictable order.
static ModuleCollection *g_module_collection = nullptr;
if (g_module_collection == nullptr)
@@ -104,9 +100,9 @@ static ModuleCollection &GetModuleCollection() {
std::recursive_mutex &Module::GetAllocationModuleCollectionMutex() {
// NOTE: The mutex below must be leaked since the global module list in
- // the ModuleList class will get torn at some point, and we can't know
- // if it will tear itself down before the "g_module_collection_mutex" below
- // will. So we leak a Mutex object below to safeguard against that
+ // the ModuleList class will get torn at some point, and we can't know if it
+ // will tear itself down before the "g_module_collection_mutex" below will.
+ // So we leak a Mutex object below to safeguard against that
static std::recursive_mutex *g_module_collection_mutex = nullptr;
if (g_module_collection_mutex == nullptr)
@@ -151,8 +147,8 @@ Module::Module(const ModuleSpec &module_spec)
: module_spec.GetObjectName().AsCString(""),
module_spec.GetObjectName().IsEmpty() ? "" : ")");
- // First extract all module specifications from the file using the local
- // file path. If there are no specifications, then don't fill anything in
+ // First extract all module specifications from the file using the local file
+ // path. If there are no specifications, then don't fill anything in
ModuleSpecList modules_specs;
if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0,
modules_specs) == 0)
@@ -160,9 +156,8 @@ Module::Module(const ModuleSpec &module_spec)
// Now make sure that one of the module specifications matches what we just
// extract. We might have a module specification that specifies a file
- // "/usr/lib/dyld"
- // with UUID XXX, but we might have a local version of "/usr/lib/dyld" that
- // has
+ // "/usr/lib/dyld" with UUID XXX, but we might have a local version of
+ // "/usr/lib/dyld" that has
// UUID YYY and we don't want those to match. If they don't match, just don't
// fill any ivars in so we don't accidentally grab the wrong file later since
// they don't match...
@@ -177,8 +172,8 @@ Module::Module(const ModuleSpec &module_spec)
m_mod_time =
FileSystem::GetModificationTime(matching_module_spec.GetFileSpec());
- // Copy the architecture from the actual spec if we got one back, else use the
- // one that was specified
+ // Copy the architecture from the actual spec if we got one back, else use
+ // the one that was specified
if (matching_module_spec.GetArchitecture().IsValid())
m_arch = matching_module_spec.GetArchitecture();
else if (module_spec.GetArchitecture().IsValid())
@@ -210,9 +205,9 @@ Module::Module(const ModuleSpec &module_spec)
else
m_object_name = module_spec.GetObjectName();
- // Always trust the object offset (file offset) and object modification
- // time (for mod time in a BSD static archive) of from the matching
- // module specification
+ // Always trust the object offset (file offset) and object modification time
+ // (for mod time in a BSD static archive) of from the matching module
+ // specification
m_object_offset = matching_module_spec.GetObjectOffset();
m_object_mod_time = matching_module_spec.GetObjectModificationTime();
}
@@ -253,8 +248,8 @@ Module::Module()
}
Module::~Module() {
- // Lock our module down while we tear everything down to make sure
- // we don't get any access to the module while it is being destroyed
+ // Lock our module down while we tear everything down to make sure we don't
+ // get any access to the module while it is being destroyed
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// Scope for locker below...
{
@@ -308,9 +303,8 @@ ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp,
m_object_name.SetString(s.GetString());
// Once we get the object file, update our module with the object
- // file's
- // architecture since it might differ in vendor/os if some parts were
- // unknown.
+ // file's architecture since it might differ in vendor/os if some
+ // parts were unknown.
m_objfile_sp->GetArchitecture(m_arch);
} else {
error.SetErrorString("unable to find suitable object file plug-in");
@@ -327,20 +321,30 @@ ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp,
}
const lldb_private::UUID &Module::GetUUID() {
- if (!m_did_parse_uuid.load()) {
+ if (!m_did_set_uuid.load()) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (!m_did_parse_uuid.load()) {
+ if (!m_did_set_uuid.load()) {
ObjectFile *obj_file = GetObjectFile();
if (obj_file != nullptr) {
obj_file->GetUUID(&m_uuid);
- m_did_parse_uuid = true;
+ m_did_set_uuid = true;
}
}
}
return m_uuid;
}
+void Module::SetUUID(const lldb_private::UUID &uuid) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (!m_did_set_uuid) {
+ m_uuid = uuid;
+ m_did_set_uuid = true;
+ } else {
+ lldbassert(0 && "Attempting to overwrite the existing module UUID");
+ }
+}
+
TypeSystem *Module::GetTypeSystemForLanguage(LanguageType language) {
return m_type_system_map.GetTypeSystemForLanguage(language, this, true);
}
@@ -441,8 +445,8 @@ uint32_t Module::ResolveSymbolContextForAddress(
// Make sure the section matches this module before we try and match anything
if (section_sp && section_sp->GetModule().get() == this) {
- // If the section offset based address resolved itself, then this
- // is the right module.
+ // If the section offset based address resolved itself, then this is the
+ // right module.
sc.module_sp = shared_from_this();
resolved_flags |= eSymbolContextModule;
@@ -450,8 +454,8 @@ uint32_t Module::ResolveSymbolContextForAddress(
if (!sym_vendor)
return resolved_flags;
- // Resolve the compile unit, function, block, line table or line
- // entry if requested.
+ // Resolve the compile unit, function, block, line table or line entry if
+ // requested.
if (resolve_scope & eSymbolContextCompUnit ||
resolve_scope & eSymbolContextFunction ||
resolve_scope & eSymbolContextBlock ||
@@ -461,8 +465,8 @@ uint32_t Module::ResolveSymbolContextForAddress(
sym_vendor->ResolveSymbolContext(so_addr, resolve_scope, sc);
}
- // Resolve the symbol if requested, but don't re-look it up if we've already
- // found it.
+ // Resolve the symbol if requested, but don't re-look it up if we've
+ // already found it.
if (resolve_scope & eSymbolContextSymbol &&
!(resolved_flags & eSymbolContextSymbol)) {
Symtab *symtab = sym_vendor->GetSymtab();
@@ -491,12 +495,11 @@ uint32_t Module::ResolveSymbolContextForAddress(
if (sc.symbol) {
if (sc.symbol->IsSynthetic()) {
- // We have a synthetic symbol so lets check if the object file
- // from the symbol file in the symbol vendor is different than
- // the object file for the module, and if so search its symbol
- // table to see if we can come up with a better symbol. For example
- // dSYM files on MacOSX have an unstripped symbol table inside of
- // them.
+ // We have a synthetic symbol so lets check if the object file from
+ // the symbol file in the symbol vendor is different than the
+ // object file for the module, and if so search its symbol table to
+ // see if we can come up with a better symbol. For example dSYM
+ // files on MacOSX have an unstripped symbol table inside of them.
ObjectFile *symtab_objfile = symtab->GetObjectFile();
if (symtab_objfile && symtab_objfile->IsStripped()) {
SymbolFile *symfile = sym_vendor->GetSymbolFile();
@@ -522,10 +525,8 @@ uint32_t Module::ResolveSymbolContextForAddress(
}
// For function symbols, so_addr may be off by one. This is a convention
- // consistent
- // with FDE row indices in eh_frame sections, but requires extra logic here
- // to permit
- // symbol lookup for disassembly and unwind.
+ // consistent with FDE row indices in eh_frame sections, but requires extra
+ // logic here to permit symbol lookup for disassembly and unwind.
if (resolve_scope & eSymbolContextSymbol &&
!(resolved_flags & eSymbolContextSymbol) && resolve_tail_call_address &&
so_addr.IsSectionOffset()) {
@@ -542,10 +543,9 @@ uint32_t Module::ResolveSymbolContextForAddress(
if (addr_range.GetBaseAddress().GetSection() ==
so_addr.GetSection()) {
// If the requested address is one past the address range of a
- // function (i.e. a tail call),
- // or the decremented address is the start of a function (i.e. some
- // forms of trampoline),
- // indicate that the symbol has been resolved.
+ // function (i.e. a tail call), or the decremented address is the
+ // start of a function (i.e. some forms of trampoline), indicate
+ // that the symbol has been resolved.
if (so_addr.GetOffset() ==
addr_range.GetBaseAddress().GetOffset() ||
so_addr.GetOffset() ==
@@ -599,21 +599,21 @@ uint32_t Module::ResolveSymbolContextsForFileSpec(const FileSpec &file_spec,
size_t Module::FindGlobalVariables(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- bool append, size_t max_matches,
+ size_t max_matches,
VariableList &variables) {
SymbolVendor *symbols = GetSymbolVendor();
if (symbols)
- return symbols->FindGlobalVariables(name, parent_decl_ctx, append,
- max_matches, variables);
+ return symbols->FindGlobalVariables(name, parent_decl_ctx, max_matches,
+ variables);
return 0;
}
-size_t Module::FindGlobalVariables(const RegularExpression &regex, bool append,
+size_t Module::FindGlobalVariables(const RegularExpression &regex,
size_t max_matches,
VariableList &variables) {
SymbolVendor *symbols = GetSymbolVendor();
if (symbols)
- return symbols->FindGlobalVariables(regex, append, max_matches, variables);
+ return symbols->FindGlobalVariables(regex, max_matches, variables);
return 0;
}
@@ -677,25 +677,22 @@ Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask,
if (name_type_mask & eFunctionNameTypeMethod ||
name_type_mask & eFunctionNameTypeBase) {
// If they've asked for a CPP method or function name and it can't be
- // that, we don't
- // even need to search for CPP methods or names.
+ // that, we don't even need to search for CPP methods or names.
CPlusPlusLanguage::MethodName cpp_method(name);
if (cpp_method.IsValid()) {
basename = cpp_method.GetBasename();
if (!cpp_method.GetQualifiers().empty()) {
// There is a "const" or other qualifier following the end of the
- // function parens,
- // this can't be a eFunctionNameTypeBase
+ // function parens, this can't be a eFunctionNameTypeBase
m_name_type_mask &= ~(eFunctionNameTypeBase);
if (m_name_type_mask == eFunctionNameTypeNone)
return;
}
} else {
// If the CPP method parser didn't manage to chop this up, try to fill
- // in the base name if we can.
- // If a::b::c is passed in, we need to just look up "c", and then we'll
- // filter the result later.
+ // in the base name if we can. If a::b::c is passed in, we need to just
+ // look up "c", and then we'll filter the result later.
CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
basename);
}
@@ -724,19 +721,15 @@ Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask,
}
if (!basename.empty()) {
- // The name supplied was a partial C++ path like "a::count". In this case we
- // want to do a
- // lookup on the basename "count" and then make sure any matching results
- // contain "a::count"
- // so that it would match "b::a::count" and "a::count". This is why we set
- // "match_name_after_lookup"
- // to true
+ // The name supplied was a partial C++ path like "a::count". In this case
+ // we want to do a lookup on the basename "count" and then make sure any
+ // matching results contain "a::count" so that it would match "b::a::count"
+ // and "a::count". This is why we set "match_name_after_lookup" to true
m_lookup_name.SetString(basename);
m_match_name_after_lookup = true;
} else {
// The name is already correct, just use the exact name as supplied, and we
- // won't need
- // to check if any matches contain "name"
+ // won't need to check if any matches contain "name"
m_lookup_name = name;
m_match_name_after_lookup = false;
}
@@ -770,8 +763,8 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
while (i < sc_list.GetSize()) {
if (!sc_list.GetContextAtIndex(i, sc))
break;
- // Make sure the mangled and demangled names don't match before we try
- // to pull anything out
+ // Make sure the mangled and demangled names don't match before we try to
+ // pull anything out
ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled));
ConstString full_name(sc.GetFunctionName());
if (mangled_name != m_name && full_name != m_name)
@@ -867,7 +860,8 @@ size_t Module::FindFunctions(const RegularExpression &regex,
if (symbols) {
symbols->FindFunctions(regex, include_inlines, append, sc_list);
- // Now check our symbol table for symbols that are code symbols if requested
+ // Now check our symbol table for symbols that are code symbols if
+ // requested
if (include_symbols) {
Symtab *symtab = symbols->GetSymtab();
if (symtab) {
@@ -882,7 +876,8 @@ size_t Module::FindFunctions(const RegularExpression &regex,
size_t num_functions_added_to_sc_list =
end_functions_added_index - start_size;
if (num_functions_added_to_sc_list == 0) {
- // No functions were added, just symbols, so we can just append them
+ // No functions were added, just symbols, so we can just append
+ // them
for (size_t i = 0; i < num_matches; ++i) {
sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
SymbolType sym_type = sc.symbol->GetType();
@@ -1001,6 +996,7 @@ size_t Module::FindTypes(
const bool append = true;
TypeClass type_class = eTypeClassAny;
TypeMap typesmap;
+
if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename,
type_class)) {
// Check if "name" starts with "::" which means the qualified type starts
@@ -1019,17 +1015,23 @@ size_t Module::FindTypes(
} else {
// The type is not in a namespace/class scope, just search for it by
// basename
- if (type_class != eTypeClassAny) {
+ if (type_class != eTypeClassAny && !type_basename.empty()) {
// The "type_name_cstr" will have been modified if we have a valid type
- // class
- // prefix (like "struct", "class", "union", "typedef" etc).
+ // class prefix (like "struct", "class", "union", "typedef" etc).
FindTypes_Impl(sc, ConstString(type_basename), nullptr, append,
- max_matches, searched_symbol_files, typesmap);
- typesmap.RemoveMismatchedTypes(type_class);
+ UINT_MAX, searched_symbol_files, typesmap);
+ typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
+ exact_match);
num_matches = typesmap.GetSize();
} else {
- num_matches = FindTypes_Impl(sc, name, nullptr, append, max_matches,
+ num_matches = FindTypes_Impl(sc, name, nullptr, append, UINT_MAX,
searched_symbol_files, typesmap);
+ if (exact_match) {
+ std::string name_str(name.AsCString(""));
+ typesmap.RemoveMismatchedTypes(type_scope, name_str, type_class,
+ exact_match);
+ num_matches = typesmap.GetSize();
+ }
}
}
if (num_matches > 0)
@@ -1057,8 +1059,8 @@ SymbolVendor *Module::GetSymbolVendor(bool can_create,
void Module::SetFileSpecAndObjectName(const FileSpec &file,
const ConstString &object_name) {
- // Container objects whose paths do not specify a file directly can call
- // this function to correct the file and object names.
+ // Container objects whose paths do not specify a file directly can call this
+ // function to correct the file and object names.
m_file = file;
m_mod_time = FileSystem::GetModificationTime(file);
m_object_name = object_name;
@@ -1258,12 +1260,10 @@ ObjectFile *Module::GetObjectFile() {
file_size - m_object_offset, data_sp, data_offset);
if (m_objfile_sp) {
// Once we get the object file, update our module with the object
- // file's
- // architecture since it might differ in vendor/os if some parts were
- // unknown. But since the matching arch might already be more
- // specific
- // than the generic COFF architecture, only merge in those values that
- // overwrite unspecified unknown values.
+ // file's architecture since it might differ in vendor/os if some
+ // parts were unknown. But since the matching arch might already be
+ // more specific than the generic COFF architecture, only merge in
+ // those values that overwrite unspecified unknown values.
ArchSpec new_arch;
m_objfile_sp->GetArchitecture(new_arch);
m_arch.MergeFrom(new_arch);
@@ -1278,7 +1278,7 @@ ObjectFile *Module::GetObjectFile() {
}
SectionList *Module::GetSectionList() {
- // Populate m_unified_sections_ap with sections from objfile.
+ // Populate m_sections_ap with sections from objfile.
if (!m_sections_ap) {
ObjectFile *obj_file = GetObjectFile();
if (obj_file != nullptr)
@@ -1297,7 +1297,6 @@ void Module::SectionFileAddressesChanged() {
}
SectionList *Module::GetUnifiedSectionList() {
- // Populate m_unified_sections_ap with sections from objfile.
if (!m_sections_ap)
m_sections_ap = llvm::make_unique<SectionList>();
return m_sections_ap.get();
@@ -1428,9 +1427,8 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) {
if (section_list && symbol_file) {
ObjectFile *obj_file = symbol_file->GetObjectFile();
// Make sure we have an object file and that the symbol vendor's objfile
- // isn't
- // the same as the module's objfile before we remove any sections for
- // it...
+ // isn't the same as the module's objfile before we remove any sections
+ // for it...
if (obj_file) {
// Check to make sure we aren't trying to specify the file we already
// have
@@ -1445,8 +1443,7 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) {
obj_file->ClearSymtab();
// The symbol file might be a directory bundle ("/tmp/a.out.dSYM")
- // instead
- // of a full path to the symbol file within the bundle
+ // instead of a full path to the symbol file within the bundle
// ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to
// check this
@@ -1473,8 +1470,7 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) {
}
}
// Keep all old symbol files around in case there are any lingering type
- // references in
- // any SBValue objects that might have been handed out.
+ // references in any SBValue objects that might have been handed out.
m_old_symfiles.push_back(std::move(m_symfile_ap));
}
m_symfile_spec = file;
@@ -1644,37 +1640,10 @@ bool Module::RemapSourceFile(llvm::StringRef path,
return m_source_mappings.RemapPath(path, new_path);
}
-uint32_t Module::GetVersion(uint32_t *versions, uint32_t num_versions) {
- ObjectFile *obj_file = GetObjectFile();
- if (obj_file)
- return obj_file->GetVersion(versions, num_versions);
-
- if (versions != nullptr && num_versions != 0) {
- for (uint32_t i = 0; i < num_versions; ++i)
- versions[i] = LLDB_INVALID_MODULE_VERSION;
- }
- return 0;
-}
-
-ModuleSP
-Module::CreateJITModule(const lldb::ObjectFileJITDelegateSP &delegate_sp) {
- if (delegate_sp) {
- // Must create a module and place it into a shared pointer before
- // we can create an object file since it has a std::weak_ptr back
- // to the module, so we need to control the creation carefully in
- // this static function
- ModuleSP module_sp(new Module());
- module_sp->m_objfile_sp =
- std::make_shared<ObjectFileJIT>(module_sp, delegate_sp);
- if (module_sp->m_objfile_sp) {
- // Once we get the object file, update our module with the object file's
- // architecture since it might differ in vendor/os if some parts were
- // unknown.
- module_sp->m_objfile_sp->GetArchitecture(module_sp->m_arch);
- }
- return module_sp;
- }
- return ModuleSP();
+llvm::VersionTuple Module::GetVersion() {
+ if (ObjectFile *obj_file = GetObjectFile())
+ return obj_file->GetVersion();
+ return llvm::VersionTuple();
}
bool Module::GetIsDynamicLinkEditor() {
@@ -1685,7 +1654,3 @@ bool Module::GetIsDynamicLinkEditor() {
return false;
}
-
-Status Module::LoadInMemory(Target &target, bool set_pc) {
- return m_objfile_sp->LoadInMemory(target, set_pc);
-}
diff --git a/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp b/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp
index 3970052b7bf3..d2896da1adca 100644
--- a/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp
@@ -13,6 +13,9 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Symbols.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/OptionValueFileSpec.h"
+#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h" // for SymbolContextList, SymbolCon...
#include "lldb/Symbol/VariableList.h"
@@ -23,7 +26,7 @@
#include "lldb/Utility/UUID.h" // for UUID, operator!=, operator==
#include "lldb/lldb-defines.h" // for LLDB_INVALID_INDEX32
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
#endif
@@ -31,6 +34,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h" // for fs
+#include "clang/Driver/Driver.h"
#include <chrono> // for operator!=, time_point
#include <memory> // for shared_ptr
@@ -60,6 +64,51 @@ class TypeList;
using namespace lldb;
using namespace lldb_private;
+namespace {
+
+PropertyDefinition g_properties[] = {
+ {"enable-external-lookup", OptionValue::eTypeBoolean, true, true, nullptr,
+ nullptr,
+ "Control the use of external tools or libraries to locate symbol files. "
+ "On macOS, Spotlight is used to locate a matching .dSYM bundle based on "
+ "the UUID of the executable."},
+ {"clang-modules-cache-path", OptionValue::eTypeFileSpec, true, 0, nullptr,
+ nullptr,
+ "The path to the clang modules cache directory (-fmodules-cache-path)."},
+ {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+
+enum { ePropertyEnableExternalLookup, ePropertyClangModulesCachePath };
+
+} // namespace
+
+ModuleListProperties::ModuleListProperties() {
+ m_collection_sp.reset(new OptionValueProperties(ConstString("symbols")));
+ m_collection_sp->Initialize(g_properties);
+
+ llvm::SmallString<128> path;
+ clang::driver::Driver::getDefaultModuleCachePath(path);
+ SetClangModulesCachePath(path);
+}
+
+bool ModuleListProperties::GetEnableExternalLookup() const {
+ const uint32_t idx = ePropertyEnableExternalLookup;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+FileSpec ModuleListProperties::GetClangModulesCachePath() const {
+ return m_collection_sp
+ ->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false,
+ ePropertyClangModulesCachePath)
+ ->GetCurrentValue();
+}
+
+bool ModuleListProperties::SetClangModulesCachePath(llvm::StringRef path) {
+ return m_collection_sp->SetPropertyAtIndexAsString(
+ nullptr, ePropertyClangModulesCachePath, path);
+}
+
+
ModuleList::ModuleList()
: m_modules(), m_modules_mutex(), m_notifier(nullptr) {}
@@ -83,8 +132,8 @@ const ModuleList &ModuleList::operator=(const ModuleList &rhs) {
// in thread A: | in thread B:
// x = y; | y = x;
//
- // This establishes correct(same) lock taking order and thus
- // avoids priority inversion.
+ // This establishes correct(same) lock taking order and thus avoids
+ // priority inversion.
if (uintptr_t(this) > uintptr_t(&rhs)) {
std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex);
std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex);
@@ -383,27 +432,26 @@ size_t ModuleList::FindCompileUnits(const FileSpec &path, bool append,
return sc_list.GetSize();
}
-size_t ModuleList::FindGlobalVariables(const ConstString &name, bool append,
+size_t ModuleList::FindGlobalVariables(const ConstString &name,
size_t max_matches,
VariableList &variable_list) const {
size_t initial_size = variable_list.GetSize();
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
collection::const_iterator pos, end = m_modules.end();
for (pos = m_modules.begin(); pos != end; ++pos) {
- (*pos)->FindGlobalVariables(name, nullptr, append, max_matches,
- variable_list);
+ (*pos)->FindGlobalVariables(name, nullptr, max_matches, variable_list);
}
return variable_list.GetSize() - initial_size;
}
size_t ModuleList::FindGlobalVariables(const RegularExpression &regex,
- bool append, size_t max_matches,
+ size_t max_matches,
VariableList &variable_list) const {
size_t initial_size = variable_list.GetSize();
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
collection::const_iterator pos, end = m_modules.end();
for (pos = m_modules.begin(); pos != end; ++pos) {
- (*pos)->FindGlobalVariables(regex, append, max_matches, variable_list);
+ (*pos)->FindGlobalVariables(regex, max_matches, variable_list);
}
return variable_list.GetSize() - initial_size;
}
@@ -496,8 +544,8 @@ ModuleList::FindTypes(const SymbolContext &sc, const ConstString &name,
size_t total_matches = 0;
collection::const_iterator pos, end = m_modules.end();
if (sc.module_sp) {
- // The symbol context "sc" contains a module so we want to search that
- // one first if it is in our list...
+ // The symbol context "sc" contains a module so we want to search that one
+ // first if it is in our list...
for (pos = m_modules.begin(); pos != end; ++pos) {
if (sc.module_sp.get() == (*pos).get()) {
total_matches +=
@@ -514,8 +562,8 @@ ModuleList::FindTypes(const SymbolContext &sc, const ConstString &name,
SymbolContext world_sc;
for (pos = m_modules.begin(); pos != end; ++pos) {
// Search the module if the module is not equal to the one in the symbol
- // context "sc". If "sc" contains a empty module shared pointer, then
- // the comparison will always be true (valid_module_ptr != nullptr).
+ // context "sc". If "sc" contains a empty module shared pointer, then the
+ // comparison will always be true (valid_module_ptr != nullptr).
if (sc.module_sp.get() != (*pos).get())
total_matches +=
(*pos)->FindTypes(world_sc, name, name_is_fully_qualified,
@@ -673,17 +721,32 @@ size_t ModuleList::GetIndexForModule(const Module *module) const {
return LLDB_INVALID_INDEX32;
}
-static ModuleList &GetSharedModuleList() {
- static ModuleList *g_shared_module_list = nullptr;
+namespace {
+struct SharedModuleListInfo {
+ ModuleList module_list;
+ ModuleListProperties module_list_properties;
+};
+}
+static SharedModuleListInfo &GetSharedModuleListInfo()
+{
+ static SharedModuleListInfo *g_shared_module_list_info = nullptr;
static llvm::once_flag g_once_flag;
llvm::call_once(g_once_flag, []() {
// NOTE: Intentionally leak the module list so a program doesn't have to
// cleanup all modules and object files as it exits. This just wastes time
// doing a bunch of cleanup that isn't required.
- if (g_shared_module_list == nullptr)
- g_shared_module_list = new ModuleList(); // <--- Intentional leak!!!
+ if (g_shared_module_list_info == nullptr)
+ g_shared_module_list_info = new SharedModuleListInfo();
});
- return *g_shared_module_list;
+ return *g_shared_module_list_info;
+}
+
+static ModuleList &GetSharedModuleList() {
+ return GetSharedModuleListInfo().module_list;
+}
+
+ModuleListProperties &ModuleList::GetGlobalModuleListProperties() {
+ return GetSharedModuleListInfo().module_list_properties;
}
bool ModuleList::ModuleIsInCache(const Module *module_ptr) {
@@ -727,8 +790,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
const ArchSpec &arch = module_spec.GetArchitecture();
// Make sure no one else can try and get or create a module while this
- // function is actively working on it by doing an extra lock on the
- // global mutex list.
+ // function is actively working on it by doing an extra lock on the global
+ // mutex list.
if (!always_create) {
ModuleList matching_module_list;
const size_t num_matching_modules =
@@ -751,8 +814,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
shared_module_list.Remove(module_sp);
module_sp.reset();
} else {
- // The module matches and the module was not modified from
- // when it was last loaded.
+ // The module matches and the module was not modified from when it
+ // was last loaded.
return error;
}
}
@@ -763,12 +826,12 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
return error;
module_sp.reset(new Module(module_spec));
- // Make sure there are a module and an object file since we can specify
- // a valid file path with an architecture that might not be in that file.
- // By getting the object file we can guarantee that the architecture matches
+ // Make sure there are a module and an object file since we can specify a
+ // valid file path with an architecture that might not be in that file. By
+ // getting the object file we can guarantee that the architecture matches
if (module_sp->GetObjectFile()) {
- // If we get in here we got the correct arch, now we just need
- // to verify the UUID if one was given
+ // If we get in here we got the correct arch, now we just need to verify
+ // the UUID if one was given
if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
module_sp.reset();
} else {
@@ -807,8 +870,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
resolved_module_spec.GetFileSpec() = search_path_spec;
module_sp.reset(new Module(resolved_module_spec));
if (module_sp->GetObjectFile()) {
- // If we get in here we got the correct arch, now we just need
- // to verify the UUID if one was given
+ // If we get in here we got the correct arch, now we just need to
+ // verify the UUID if one was given
if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
module_sp.reset();
} else {
@@ -833,8 +896,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
// we now have to use more extreme measures to try and find the appropriate
// module.
- // Fixup the incoming path in case the path points to a valid file, yet
- // the arch or UUID (if one was passed in) don't match.
+ // Fixup the incoming path in case the path points to a valid file, yet the
+ // arch or UUID (if one was passed in) don't match.
ModuleSpec located_binary_modulespec =
Symbols::LocateExecutableObjectFile(module_spec);
@@ -871,8 +934,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
}
// Make sure no one else can try and get or create a module while this
- // function is actively working on it by doing an extra lock on the
- // global mutex list.
+ // function is actively working on it by doing an extra lock on the global
+ // mutex list.
ModuleSpec platform_module_spec(module_spec);
platform_module_spec.GetFileSpec() =
located_binary_modulespec.GetFileSpec();
@@ -903,8 +966,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
if (!module_sp) {
module_sp.reset(new Module(platform_module_spec));
- // Make sure there are a module and an object file since we can specify
- // a valid file path with an architecture that might not be in that file.
+ // Make sure there are a module and an object file since we can specify a
+ // valid file path with an architecture that might not be in that file.
// By getting the object file we can guarantee that the architecture
// matches
if (module_sp && module_sp->GetObjectFile()) {
diff --git a/contrib/llvm/tools/lldb/source/Core/Opcode.cpp b/contrib/llvm/tools/lldb/source/Core/Opcode.cpp
index b4e691c1ddcd..d15fdb3b17be 100644
--- a/contrib/llvm/tools/lldb/source/Core/Opcode.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Opcode.cpp
@@ -52,8 +52,8 @@ int Opcode::Dump(Stream *s, uint32_t min_byte_width) {
break;
}
- // Add spaces to make sure bytes dispay comes out even in case opcodes
- // aren't all the same size
+ // Add spaces to make sure bytes dispay comes out even in case opcodes aren't
+ // all the same size
if (static_cast<uint32_t>(bytes_written) < min_byte_width)
bytes_written = s->Printf("%*s", min_byte_width - bytes_written, "");
return bytes_written;
diff --git a/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp b/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp
index a49fbc3f90fe..55affb6a1030 100644
--- a/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp
@@ -17,7 +17,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringList.h" // for StringList
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
#endif
@@ -96,8 +96,8 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
Status error;
namespace fs = llvm::sys::fs;
- // If we have a regular file, a symbolic link or unknown file type, try
- // and process the file. We must handle unknown as sometimes the directory
+ // If we have a regular file, a symbolic link or unknown file type, try and
+ // process the file. We must handle unknown as sometimes the directory
// enumeration might be enumerating a file system that doesn't have correct
// file type information.
if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
@@ -128,17 +128,14 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate"));
} else {
// The initialize function returned FALSE which means the plug-in
- // might not be
- // compatible, or might be too new or too old, or might not want to
- // run on this
- // machine. Set it to a default-constructed instance to invalidate
- // it.
+ // might not be compatible, or might be too new or too old, or might
+ // not want to run on this machine. Set it to a default-constructed
+ // instance to invalidate it.
plugin_info = PluginInfo();
}
- // Regardless of success or failure, cache the plug-in load
- // in our plug-in info so we don't try to load it again and
- // again.
+ // Regardless of success or failure, cache the plug-in load in our
+ // plug-in info so we don't try to load it again and again.
SetPluginInfo(plugin_file_spec, plugin_info);
return FileSpec::eEnumerateDirectoryResultNext;
@@ -148,9 +145,9 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
if (ft == fs::file_type::directory_file ||
ft == fs::file_type::symlink_file || ft == fs::file_type::type_unknown) {
- // Try and recurse into anything that a directory or symbolic link.
- // We must also do this for unknown as sometimes the directory enumeration
- // might be enumerating a file system that doesn't have correct file type
+ // Try and recurse into anything that a directory or symbolic link. We must
+ // also do this for unknown as sometimes the directory enumeration might be
+ // enumerating a file system that doesn't have correct file type
// information.
return FileSpec::eEnumerateDirectoryResultEnter;
}
@@ -160,19 +157,18 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
void PluginManager::Initialize() {
#if 1
- FileSpec dir_spec;
const bool find_directories = true;
const bool find_files = true;
const bool find_other = true;
char dir_path[PATH_MAX];
- if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
+ if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
find_other, LoadPluginCallback, nullptr);
}
}
- if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
+ if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
find_other, LoadPluginCallback, nullptr);
@@ -187,8 +183,8 @@ void PluginManager::Terminate() {
PluginTerminateMap::const_iterator pos, end = plugin_map.end();
for (pos = plugin_map.begin(); pos != end; ++pos) {
- // Call the plug-in "void LLDBPluginTerminate (void)" function if there
- // is one (if the symbol was not nullptr).
+ // Call the plug-in "void LLDBPluginTerminate (void)" function if there is
+ // one (if the symbol was not nullptr).
if (pos->second.library.isValid()) {
if (pos->second.plugin_term_callback)
pos->second.plugin_term_callback();
@@ -2397,8 +2393,8 @@ static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPlugins(
}
// This is deprecated way to register plugin specific settings. e.g.
-// "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME"
-// and Platform generic settings would be under "platform.SETTINGNAME".
+// "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME" and Platform
+// generic settings would be under "platform.SETTINGNAME".
static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle(
Debugger &debugger, const ConstString &plugin_type_name,
const ConstString &plugin_type_desc, bool can_create) {
diff --git a/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp b/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp
index f64c14019cc6..4f908609dde9 100644
--- a/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp
@@ -9,9 +9,8 @@
#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Scalar.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
@@ -34,67 +33,6 @@
using namespace lldb;
using namespace lldb_private;
-bool RegisterValue::Dump(Stream *s, const RegisterInfo *reg_info,
- bool prefix_with_name, bool prefix_with_alt_name,
- Format format,
- uint32_t reg_name_right_align_at) const {
- DataExtractor data;
- if (GetData(data)) {
- bool name_printed = false;
- // For simplicity, alignment of the register name printing applies only
- // in the most common case where:
- //
- // prefix_with_name^prefix_with_alt_name is true
- //
- StreamString format_string;
- if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))
- format_string.Printf("%%%us", reg_name_right_align_at);
- else
- format_string.Printf("%%s");
- std::string fmt = format_string.GetString();
- if (prefix_with_name) {
- if (reg_info->name) {
- s->Printf(fmt.c_str(), reg_info->name);
- name_printed = true;
- } else if (reg_info->alt_name) {
- s->Printf(fmt.c_str(), reg_info->alt_name);
- prefix_with_alt_name = false;
- name_printed = true;
- }
- }
- if (prefix_with_alt_name) {
- if (name_printed)
- s->PutChar('/');
- if (reg_info->alt_name) {
- s->Printf(fmt.c_str(), reg_info->alt_name);
- name_printed = true;
- } else if (!name_printed) {
- // No alternate name but we were asked to display a name, so show the
- // main name
- s->Printf(fmt.c_str(), reg_info->name);
- name_printed = true;
- }
- }
- if (name_printed)
- s->PutCString(" = ");
-
- if (format == eFormatDefault)
- format = reg_info->format;
-
- DumpDataExtractor(data, s,
- 0, // Offset in "data"
- format, // Format to use when dumping
- reg_info->byte_size, // item_byte_size
- 1, // item_count
- UINT32_MAX, // num_per_line
- LLDB_INVALID_ADDRESS, // base_addr
- 0, // item_bit_size
- 0); // item_bit_offset
- return true;
- }
- return false;
-}
-
bool RegisterValue::GetData(DataExtractor &data) const {
return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;
}
@@ -375,9 +313,9 @@ static bool ParseVectorEncoding(const RegisterInfo *reg_info,
std::vector<uint8_t> bytes;
unsigned byte = 0;
- // Using radix auto-sensing by passing 0 as the radix.
- // Keep on processing the vector elements as long as the parsing succeeds and
- // the vector size is < byte_size.
+ // Using radix auto-sensing by passing 0 as the radix. Keep on processing the
+ // vector elements as long as the parsing succeeds and the vector size is <
+ // byte_size.
while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) {
bytes.push_back(byte);
std::tie(car, cdr) = cdr.split(Sep);
@@ -812,10 +750,9 @@ bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) {
void RegisterValue::SetBytes(const void *bytes, size_t length,
lldb::ByteOrder byte_order) {
- // If this assertion fires off we need to increase the size of
- // buffer.bytes, or make it something that is allocated on
- // the heap. Since the data buffer is in a union, we can't make it
- // a collection class like SmallVector...
+ // If this assertion fires off we need to increase the size of buffer.bytes,
+ // or make it something that is allocated on the heap. Since the data buffer
+ // is in a union, we can't make it a collection class like SmallVector...
if (bytes && length > 0) {
assert(length <= sizeof(buffer.bytes) &&
"Storing too many bytes in a RegisterValue.");
diff --git a/contrib/llvm/tools/lldb/source/Core/Scalar.cpp b/contrib/llvm/tools/lldb/source/Core/Scalar.cpp
index 630083bae930..6a7186969ef2 100644
--- a/contrib/llvm/tools/lldb/source/Core/Scalar.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Scalar.cpp
@@ -9,7 +9,6 @@
#include "lldb/Core/Scalar.h"
-#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Status.h"
@@ -25,8 +24,8 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Promote to max type currently follows the ANSI C rule for type
-// promotion in expressions.
+// Promote to max type currently follows the ANSI C rule for type promotion in
+// expressions.
//----------------------------------------------------------------------
static Scalar::Type PromoteToMaxType(
const Scalar &lhs, // The const left hand side object
@@ -41,10 +40,9 @@ static Scalar::Type PromoteToMaxType(
// lhs/rhs will get promoted)
) {
Scalar result;
- // Initialize the promoted values for both the right and left hand side values
- // to be the objects themselves. If no promotion is needed (both right and
- // left
- // have the same type), then the temp_value will not get used.
+ // Initialize the promoted values for both the right and left hand side
+ // values to be the objects themselves. If no promotion is needed (both right
+ // and left have the same type), then the temp_value will not get used.
promoted_lhs_ptr = &lhs;
promoted_rhs_ptr = &rhs;
// Extract the types of both the right and left hand side values
@@ -128,14 +126,13 @@ bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
if (limit_byte_size < byte_size) {
if (endian::InlHostByteOrder() == eByteOrderLittle) {
- // On little endian systems if we want fewer bytes from the
- // current type we just specify fewer bytes since the LSByte
- // is first...
+ // On little endian systems if we want fewer bytes from the current
+ // type we just specify fewer bytes since the LSByte is first...
byte_size = limit_byte_size;
} else if (endian::InlHostByteOrder() == eByteOrderBig) {
- // On big endian systems if we want fewer bytes from the
- // current type have to advance our initial byte pointer and
- // trim down the number of bytes since the MSByte is first
+ // On big endian systems if we want fewer bytes from the current type
+ // have to advance our initial byte pointer and trim down the number of
+ // bytes since the MSByte is first
bytes += byte_size - limit_byte_size;
byte_size = limit_byte_size;
}
@@ -164,9 +161,8 @@ const void *Scalar::GetBytes() const {
case e_slonglong:
case e_ulonglong:
bytes = reinterpret_cast<const uint8_t *>(m_integer.getRawData());
- // getRawData always returns a pointer to an uint64_t. If we have a smaller
- // type,
- // we need to update the pointer on big-endian systems.
+ // getRawData always returns a pointer to an uint64_t. If we have a
+ // smaller type, we need to update the pointer on big-endian systems.
if (endian::InlHostByteOrder() == eByteOrderBig) {
size_t byte_size = m_integer.getBitWidth() / 8;
if (byte_size < 8)
@@ -491,20 +487,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -551,20 +551,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -607,20 +611,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -659,20 +667,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -707,20 +719,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -751,20 +767,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -795,20 +815,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -835,20 +859,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -875,20 +903,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, true,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -911,20 +943,24 @@ bool Scalar::Promote(Scalar::Type type) {
success = true;
break;
case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
+ m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
+ m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended());
+ m_float.convertFromAPInt(m_integer, false,
+ llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@@ -948,20 +984,19 @@ bool Scalar::Promote(Scalar::Type type) {
success = true;
break;
case e_double:
- m_float = llvm::APFloat((float_t)m_float.convertToFloat());
+ m_float = llvm::APFloat((double_t)m_float.convertToFloat());
success = true;
break;
- case e_long_double:
- if (m_ieee_quad)
- m_float =
- llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
- m_float.bitcastToAPInt());
+ case e_long_double: {
+ bool ignore;
+ m_float.convert(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended(),
+ llvm::APFloat::rmNearestTiesToEven, &ignore);
success = true;
break;
}
+ }
break;
case e_double:
@@ -982,16 +1017,15 @@ bool Scalar::Promote(Scalar::Type type) {
case e_double:
success = true;
break;
- case e_long_double:
- if (m_ieee_quad)
- m_float =
- llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
- m_float.bitcastToAPInt());
+ case e_long_double: {
+ bool ignore;
+ m_float.convert(m_ieee_quad ? llvm::APFloat::IEEEquad()
+ : llvm::APFloat::x87DoubleExtended(),
+ llvm::APFloat::rmNearestTiesToEven, &ignore);
success = true;
break;
}
+ }
break;
case e_long_double:
@@ -1088,253 +1122,6 @@ Scalar::Type Scalar::GetValueTypeForFloatWithByteSize(size_t byte_size) {
return e_void;
}
-bool Scalar::Cast(Scalar::Type type) {
- bool success = false;
- switch (m_type) {
- case e_void:
- break;
-
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong:
- case e_slonglong:
- case e_ulonglong:
- case e_sint128:
- case e_uint128:
- case e_sint256:
- case e_uint256:
- switch (type) {
- case e_void:
- break;
- case e_sint:
- m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8);
- success = true;
- break;
-
- case e_uint:
- m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8);
- success = true;
- break;
-
- case e_slong:
- m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8);
- success = true;
- break;
-
- case e_ulong:
- m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8);
- success = true;
- break;
-
- case e_slonglong:
- m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8);
- success = true;
- break;
-
- case e_ulonglong:
- m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8);
- success = true;
- break;
-
- case e_sint128:
- m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128);
- success = true;
- break;
-
- case e_uint128:
- m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128);
- success = true;
- break;
-
- case e_sint256:
- m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256);
- success = true;
- break;
-
- case e_uint256:
- m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256);
- success = true;
- break;
-
- case e_float:
- m_float = llvm::APFloat(m_integer.bitsToFloat());
- success = true;
- break;
-
- case e_double:
- m_float = llvm::APFloat(m_integer.bitsToDouble());
- success = true;
- break;
-
- case e_long_double:
- if (m_ieee_quad)
- m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
- success = true;
- break;
- }
- break;
-
- case e_float:
- switch (type) {
- case e_void:
- break;
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong:
- case e_slonglong:
- case e_ulonglong:
- case e_sint128:
- case e_uint128:
- case e_sint256:
- case e_uint256:
- m_integer = m_float.bitcastToAPInt();
- success = true;
- break;
- case e_float:
- m_float = llvm::APFloat(m_float.convertToFloat());
- success = true;
- break;
- case e_double:
- m_float = llvm::APFloat(m_float.convertToFloat());
- success = true;
- break;
- case e_long_double:
- if (m_ieee_quad)
- m_float =
- llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
- m_float.bitcastToAPInt());
- success = true;
- break;
- }
- break;
-
- case e_double:
- switch (type) {
- case e_void:
- break;
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong:
- case e_slonglong:
- case e_ulonglong:
- case e_sint128:
- case e_uint128:
- case e_sint256:
- case e_uint256:
- m_integer = m_float.bitcastToAPInt();
- success = true;
- break;
- case e_float:
- m_float = llvm::APFloat(m_float.convertToDouble());
- success = true;
- break;
- case e_double:
- m_float = llvm::APFloat(m_float.convertToDouble());
- success = true;
- break;
- case e_long_double:
- if (m_ieee_quad)
- m_float =
- llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
- else
- m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
- m_float.bitcastToAPInt());
- success = true;
- break;
- }
- break;
-
- case e_long_double:
- switch (type) {
- case e_void:
- break;
- case e_sint:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8);
- success = true;
- break;
-
- case e_uint:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8);
- success = true;
- break;
-
- case e_slong:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8);
- success = true;
- break;
-
- case e_ulong:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8);
- success = true;
- break;
-
- case e_slonglong:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8);
- success = true;
- break;
-
- case e_ulonglong:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8);
- success = true;
- break;
-
- case e_sint128:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128);
- success = true;
- break;
-
- case e_uint128:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128);
- success = true;
- break;
-
- case e_sint256:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256);
- success = true;
- break;
-
- case e_uint256:
- m_integer = m_float.bitcastToAPInt();
- m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256);
- success = true;
- break;
-
- case e_float:
- m_float = llvm::APFloat(m_float.convertToFloat());
- success = true;
- break;
- case e_double:
- m_float = llvm::APFloat(m_float.convertToFloat());
- success = true;
- break;
- case e_long_double:
- success = true;
- break;
- }
- break;
- }
-
- if (success)
- m_type = type;
- return success;
-}
-
bool Scalar::MakeSigned() {
bool success = false;
@@ -1397,38 +1184,38 @@ bool Scalar::MakeUnsigned() {
case e_void:
break;
case e_sint:
+ m_type = e_uint;
success = true;
break;
case e_uint:
- m_type = e_uint;
success = true;
break;
case e_slong:
+ m_type = e_ulong;
success = true;
break;
case e_ulong:
- m_type = e_ulong;
success = true;
break;
case e_slonglong:
+ m_type = e_ulonglong;
success = true;
break;
case e_ulonglong:
- m_type = e_ulonglong;
success = true;
break;
case e_sint128:
+ m_type = e_uint128;
success = true;
break;
case e_uint128:
- m_type = e_uint128;
success = true;
break;
case e_sint256:
+ m_type = e_uint256;
success = true;
break;
case e_uint256:
- m_type = e_uint256;
success = true;
break;
case e_float:
@@ -1819,7 +1606,7 @@ float Scalar::Float(float fail_value) const {
case e_uint128:
case e_sint256:
case e_uint256:
- return m_integer.bitsToFloat();
+ return llvm::APIntOps::RoundAPIntToFloat(m_integer);
case e_float:
return m_float.convertToFloat();
case e_double:
@@ -1845,7 +1632,7 @@ double Scalar::Double(double fail_value) const {
case e_uint128:
case e_sint256:
case e_uint256:
- return m_integer.bitsToDouble();
+ return llvm::APIntOps::RoundAPIntToDouble(m_integer);
case e_float:
return (double_t)m_float.convertToFloat();
case e_double:
@@ -1871,7 +1658,7 @@ long double Scalar::LongDouble(long double fail_value) const {
case e_uint128:
case e_sint256:
case e_uint256:
- return (long_double_t)m_integer.bitsToDouble();
+ return (long_double_t)llvm::APIntOps::RoundAPIntToDouble(m_integer);
case e_float:
return (long_double_t)m_float.convertToFloat();
case e_double:
@@ -2266,7 +2053,7 @@ const Scalar lldb_private::operator/(const Scalar &lhs, const Scalar &rhs) {
case Scalar::e_float:
case Scalar::e_double:
case Scalar::e_long_double:
- if (b->m_float.isZero()) {
+ if (!b->m_float.isZero()) {
result.m_float = a->m_float / b->m_float;
return result;
}
@@ -2274,8 +2061,7 @@ const Scalar lldb_private::operator/(const Scalar &lhs, const Scalar &rhs) {
}
}
// For division only, the only way it should make it here is if a promotion
- // failed,
- // or if we are trying to do a divide by zero.
+ // failed, or if we are trying to do a divide by zero.
result.m_type = Scalar::e_void;
return result;
}
@@ -2467,17 +2253,15 @@ Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
error.SetErrorString("Invalid c-string value string.");
return error;
}
- bool success = false;
switch (encoding) {
case eEncodingInvalid:
error.SetErrorString("Invalid encoding.");
break;
case eEncodingUint:
- if (byte_size <= sizeof(unsigned long long)) {
- uint64_t uval64 =
- StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
- if (!success)
+ if (byte_size <= sizeof(uint64_t)) {
+ uint64_t uval64;
+ if (!llvm::to_integer(value_str, uval64))
error.SetErrorStringWithFormat(
"'%s' is not a valid unsigned integer string value", value_str);
else if (!UIntValueIsValidForSize(uval64, byte_size))
@@ -2513,10 +2297,9 @@ Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
break;
case eEncodingSint:
- if (byte_size <= sizeof(long long)) {
- uint64_t sval64 =
- StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
- if (!success)
+ if (byte_size <= sizeof(int64_t)) {
+ int64_t sval64;
+ if (!llvm::to_integer(value_str, sval64))
error.SetErrorStringWithFormat(
"'%s' is not a valid signed integer string value", value_str);
else if (!SIntValueIsValidForSize(sval64, byte_size))
diff --git a/contrib/llvm/tools/lldb/source/Core/Section.cpp b/contrib/llvm/tools/lldb/source/Core/Section.cpp
index c9faf9f89157..d9c5d32ee13c 100644
--- a/contrib/llvm/tools/lldb/source/Core/Section.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Section.cpp
@@ -27,8 +27,8 @@ class DataExtractor;
using namespace lldb;
using namespace lldb_private;
-static const char *GetSectionTypeAsCString(lldb::SectionType sect_type) {
- switch (sect_type) {
+const char *Section::GetTypeAsCString() const {
+ switch (m_type) {
case eSectionTypeInvalid:
return "invalid";
case eSectionTypeCode:
@@ -89,6 +89,10 @@ static const char *GetSectionTypeAsCString(lldb::SectionType sect_type) {
return "dwarf-str";
case eSectionTypeDWARFDebugStrOffsets:
return "dwarf-str-offsets";
+ case eSectionTypeDWARFDebugTypes:
+ return "dwarf-types";
+ case eSectionTypeDWARFDebugNames:
+ return "dwarf-names";
case eSectionTypeELFSymbolTable:
return "elf-symbol-table";
case eSectionTypeELFDynamicSymbols:
@@ -117,6 +121,8 @@ static const char *GetSectionTypeAsCString(lldb::SectionType sect_type) {
return "go-symtab";
case eSectionTypeAbsoluteAddress:
return "absolute";
+ case eSectionTypeDWARFGNUDebugAltLink:
+ return "dwarf-gnu-debugaltlink";
case eSectionTypeOther:
return "regular";
}
@@ -175,9 +181,9 @@ Section::~Section() {
addr_t Section::GetFileAddress() const {
SectionSP parent_sp(GetParent());
if (parent_sp) {
- // This section has a parent which means m_file_addr is an offset into
- // the parent section, so the file address for this section is the file
- // address of the parent plus the offset
+ // This section has a parent which means m_file_addr is an offset into the
+ // parent section, so the file address for this section is the file address
+ // of the parent plus the offset
return parent_sp->GetFileAddress() + m_file_addr;
}
// This section has no parent, so m_file_addr is the file base address
@@ -283,8 +289,7 @@ int Section::Compare(const Section &a, const Section &b) {
void Section::Dump(Stream *s, Target *target, uint32_t depth) const {
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
- s->Printf("0x%8.8" PRIx64 " %-16s ", GetID(),
- GetSectionTypeAsCString(m_type));
+ s->Printf("0x%8.8" PRIx64 " %-16s ", GetID(), GetTypeAsCString());
bool resolved = true;
addr_t addr = LLDB_INVALID_ADDRESS;
@@ -326,10 +331,11 @@ void Section::DumpName(Stream *s) const {
// The top most section prints the module basename
const char *name = NULL;
ModuleSP module_sp(GetModule());
- const FileSpec &file_spec = m_obj_file->GetFileSpec();
- if (m_obj_file)
+ if (m_obj_file) {
+ const FileSpec &file_spec = m_obj_file->GetFileSpec();
name = file_spec.GetFilename().AsCString();
+ }
if ((!name || !name[0]) && module_sp)
name = module_sp->GetFileSpec().GetFilename().AsCString();
if (name && name[0])
@@ -556,10 +562,8 @@ SectionSP SectionList::FindSectionContainingFileAddress(addr_t vm_addr,
Section *sect = sect_iter->get();
if (sect->ContainsFileAddress(vm_addr)) {
// The file address is in this section. We need to make sure one of our
- // child
- // sections doesn't contain this address as well as obeying the depth
- // limit
- // that was passed in.
+ // child sections doesn't contain this address as well as obeying the
+ // depth limit that was passed in.
if (depth > 0)
sect_sp = sect->GetChildren().FindSectionContainingFileAddress(
vm_addr, depth - 1);
diff --git a/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp b/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp
index b284ff1dbaaa..a6afd64f3054 100644
--- a/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp
@@ -109,8 +109,8 @@ static bool should_show_stop_column_with_ansi(DebuggerSP debugger_sp) {
if (!debugger_sp)
return false;
- // We don't use ANSI stop column formatting if the debugger doesn't think
- // it should be using color.
+ // We don't use ANSI stop column formatting if the debugger doesn't think it
+ // should be using color.
if (!debugger_sp->GetUseColor())
return false;
@@ -128,8 +128,8 @@ static bool should_show_stop_column_with_caret(DebuggerSP debugger_sp) {
if (!debugger_sp)
return false;
- // If we're asked to show the first available of ANSI or caret, then
- // we do show the caret when ANSI is not available.
+ // If we're asked to show the first available of ANSI or caret, then we do
+ // show the caret when ANSI is not available.
const auto value = debugger_sp->GetStopShowColumn();
if ((value == eStopShowColumnAnsiOrCaret) && !debugger_sp->GetUseColor())
return true;
@@ -255,9 +255,9 @@ size_t SourceManager::DisplayMoreWithLineNumbers(
if (m_last_line > 0) {
if (reverse) {
- // If this is the first time we've done a reverse, then back up one more
- // time so we end
- // up showing the chunk before the last one we've shown:
+ // If this is the first time we've done a reverse, then back up one
+ // more time so we end up showing the chunk before the last one we've
+ // shown:
if (m_last_line > m_last_count)
m_last_line -= m_last_count;
else
@@ -299,10 +299,9 @@ bool SourceManager::GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line) {
if (target_sp) {
// If nobody has set the default file and line then try here. If there's
- // no executable, then we
- // will try again later when there is one. Otherwise, if we can't find it
- // we won't look again,
- // somebody will have to set it (for instance when we stop somewhere...)
+ // no executable, then we will try again later when there is one.
+ // Otherwise, if we can't find it we won't look again, somebody will have
+ // to set it (for instance when we stop somewhere...)
Module *executable_ptr = target_sp->GetExecutableModulePointer();
if (executable_ptr) {
SymbolContextList sc_list;
@@ -410,9 +409,7 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec,
FileSpec new_file_spec;
// Check target specific source remappings first, then fall back to
// modules objects can have individual path remappings that were
- // detected
- // when the debug info for a module was found.
- // then
+ // detected when the debug info for a module was found. then
if (target->GetSourcePathMap().FindFile(m_file_spec, new_file_spec) ||
target->GetImages().FindSourceFile(m_file_spec, new_file_spec)) {
m_file_spec = new_file_spec;
@@ -538,8 +535,8 @@ size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
if (column && (column < count)) {
auto debugger_sp = m_debugger_wp.lock();
if (should_show_stop_column_with_ansi(debugger_sp) && debugger_sp) {
- // Check if we have any ANSI codes with which to mark this column.
- // If not, no need to do this work.
+ // Check if we have any ANSI codes with which to mark this column. If
+ // not, no need to do this work.
auto ansi_prefix_entry = debugger_sp->GetStopShowColumnAnsiPrefix();
auto ansi_suffix_entry = debugger_sp->GetStopShowColumnAnsiSuffix();
diff --git a/contrib/llvm/tools/lldb/source/Core/Value.cpp b/contrib/llvm/tools/lldb/source/Core/Value.cpp
index d415f1b09eb7..254c9008babb 100644
--- a/contrib/llvm/tools/lldb/source/Core/Value.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Value.cpp
@@ -365,11 +365,10 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
if (process == NULL || !process->IsAlive()) {
Target *target = exe_ctx->GetTargetPtr();
if (target) {
- // Allow expressions to run and evaluate things when the target
- // has memory sections loaded. This allows you to use "target modules
- // load"
- // to load your executable and any shared libraries, then execute
- // commands where you can look at types in data sections.
+ // Allow expressions to run and evaluate things when the target has
+ // memory sections loaded. This allows you to use "target modules
+ // load" to load your executable and any shared libraries, then
+ // execute commands where you can look at types in data sections.
const SectionLoadList &target_sections = target->GetSectionLoadList();
if (!target_sections.IsEmpty()) {
address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
@@ -406,8 +405,8 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
error.SetErrorString("invalid file address");
} else {
if (module == NULL) {
- // The only thing we can currently lock down to a module so that
- // we can resolve a file address, is a variable.
+ // The only thing we can currently lock down to a module so that we
+ // can resolve a file address, is a variable.
Variable *variable = GetVariable();
if (variable) {
SymbolContext var_sc;
@@ -541,12 +540,11 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
} else if ((address_type == eAddressTypeLoad) ||
(address_type == eAddressTypeFile)) {
if (file_so_addr.IsValid()) {
- // We have a file address that we were able to translate into a
- // section offset address so we might be able to read this from
- // the object files if we don't have a live process. Lets always
- // try and read from the process if we have one though since we
- // want to read the actual value by setting "prefer_file_cache"
- // to false.
+ // We have a file address that we were able to translate into a section
+ // offset address so we might be able to read this from the object
+ // files if we don't have a live process. Lets always try and read from
+ // the process if we have one though since we want to read the actual
+ // value by setting "prefer_file_cache" to false.
const bool prefer_file_cache = false;
if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache,
dst, byte_size,
@@ -555,10 +553,10 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
"read memory from 0x%" PRIx64 " failed", (uint64_t)address);
}
} else {
- // The execution context might have a NULL process, but it
- // might have a valid process in the exe_ctx->target, so use
- // the ExecutionContext::GetProcess accessor to ensure we
- // get the process if there is one.
+ // The execution context might have a NULL process, but it might have a
+ // valid process in the exe_ctx->target, so use the
+ // ExecutionContext::GetProcess accessor to ensure we get the process
+ // if there is one.
Process *process = exe_ctx->GetProcessPtr();
if (process) {
@@ -671,6 +669,25 @@ const char *Value::GetContextTypeAsCString(ContextType context_type) {
return "???";
}
+void Value::ConvertToLoadAddress(Module *module, Target *target) {
+ if (!module || !target || (GetValueType() != eValueTypeFileAddress))
+ return;
+
+ lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ if (file_addr == LLDB_INVALID_ADDRESS)
+ return;
+
+ Address so_addr;
+ if (!module->ResolveFileAddress(file_addr, so_addr))
+ return;
+ lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ return;
+
+ SetValueType(Value::eValueTypeLoadAddress);
+ GetScalar() = load_addr;
+}
+
ValueList::ValueList(const ValueList &rhs) { m_values = rhs.m_values; }
const ValueList &ValueList::operator=(const ValueList &rhs) {
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp
index c09139fe2b09..244ea2936fb4 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectSyntheticFilter.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/DumpValueObjectOptions.h" // for DumpValueObj...
#include "lldb/DataFormatters/FormatManager.h" // for FormatManager
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/TypeFormat.h" // for TypeFormatImpl_F...
@@ -146,16 +147,15 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
if (update_format)
did_change_formats = UpdateFormatsIfNeeded();
- // If this is a constant value, then our success is predicated on whether
- // we have an error or not
+ // If this is a constant value, then our success is predicated on whether we
+ // have an error or not
if (GetIsConstant()) {
// if you are constant, things might still have changed behind your back
// (e.g. you are a frozen object and things have changed deeper than you
- // cared to freeze-dry yourself)
- // in this case, your value has not changed, but "computed" entries might
- // have, so you might now have
- // a different summary, or a different object description. clear these so we
- // will recompute them
+ // cared to freeze-dry yourself) in this case, your value has not changed,
+ // but "computed" entries might have, so you might now have a different
+ // summary, or a different object description. clear these so we will
+ // recompute them
if (update_format && !did_change_formats)
ClearUserVisibleData(eClearUserVisibleDataItemsSummary |
eClearUserVisibleDataItemsDescription);
@@ -167,8 +167,8 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
if (NeedsUpdating()) {
m_update_point.SetUpdated();
- // Save the old value using swap to avoid a string copy which
- // also will clear our m_value_str
+ // Save the old value using swap to avoid a string copy which also will
+ // clear our m_value_str
if (m_value_str.empty()) {
m_old_value_valid = false;
} else {
@@ -215,8 +215,8 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
if (first_update)
SetValueDidChange(false);
else if (!m_value_did_change && success == false) {
- // The value wasn't gotten successfully, so we mark this
- // as changed if the value used to be valid and now isn't
+ // The value wasn't gotten successfully, so we mark this as changed if
+ // the value used to be valid and now isn't
SetValueDidChange(value_was_valid);
} else if (need_compare_checksums) {
SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],
@@ -261,8 +261,7 @@ bool ValueObject::UpdateFormatsIfNeeded() {
void ValueObject::SetNeedsUpdate() {
m_update_point.SetNeedsUpdate();
// We have to clear the value string here so ConstResult children will notice
- // if their values are
- // changed by hand (i.e. with SetValueAsCString).
+ // if their values are changed by hand (i.e. with SetValueAsCString).
ClearUserVisibleData(eClearUserVisibleDataItemsValue);
}
@@ -556,9 +555,9 @@ size_t ValueObject::GetIndexOfChildWithName(const ConstString &name) {
ValueObjectSP ValueObject::GetChildMemberWithName(const ConstString &name,
bool can_create) {
- // when getting a child by name, it could be buried inside some base
- // classes (which really aren't part of the expression path), so we
- // need a vector of indexes that can get us down to the correct child
+ // when getting a child by name, it could be buried inside some base classes
+ // (which really aren't part of the expression path), so we need a vector of
+ // indexes that can get us down to the correct child
ValueObjectSP child_sp;
// We may need to update our value if we are dynamic
@@ -682,8 +681,8 @@ bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
const TypeSummaryOptions &options) {
destination.clear();
- // ideally we would like to bail out if passing NULL, but if we do so
- // we end up not providing the summary for function pointers anymore
+ // ideally we would like to bail out if passing NULL, but if we do so we end
+ // up not providing the summary for function pointers anymore
if (/*summary_ptr == NULL ||*/ m_is_getting_summary)
return false;
@@ -695,9 +694,8 @@ bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
actual_options.SetLanguage(GetPreferredDisplayLanguage());
// this is a hot path in code and we prefer to avoid setting this string all
- // too often also clearing out other
- // information that we might care to see in a crash log. might be useful in
- // very specific situations though.
+ // too often also clearing out other information that we might care to see in
+ // a crash log. might be useful in very specific situations though.
/*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
Summary provider's description is %s",
GetTypeName().GetCString(),
@@ -925,7 +923,8 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
break;
}
- // If we have reached this point, then we have successfully changed the value.
+ // If we have reached this point, then we have successfully changed the
+ // value.
SetNeedsUpdate();
return true;
}
@@ -1010,9 +1009,9 @@ ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
DataExtractor data;
if (cstr_len > 0 && honor_array) {
// I am using GetPointeeData() here to abstract the fact that some
- // ValueObjects are actually frozen pointers in the host
- // but the pointed-to data lives in the debuggee, and GetPointeeData()
- // automatically takes care of this
+ // ValueObjects are actually frozen pointers in the host but the pointed-
+ // to data lives in the debuggee, and GetPointeeData() automatically
+ // takes care of this
GetPointeeData(data, 0, cstr_len);
if ((bytes_read = data.GetByteSize()) > 0) {
@@ -1031,9 +1030,9 @@ ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
int cstr_len_displayed = -1;
bool capped_cstr = false;
// I am using GetPointeeData() here to abstract the fact that some
- // ValueObjects are actually frozen pointers in the host
- // but the pointed-to data lives in the debuggee, and GetPointeeData()
- // automatically takes care of this
+ // ValueObjects are actually frozen pointers in the host but the pointed-
+ // to data lives in the debuggee, and GetPointeeData() automatically
+ // takes care of this
while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
total_bytes_read += bytes_read;
const char *cstr = data.PeekCStr(0);
@@ -1175,8 +1174,8 @@ const char *ValueObject::GetValueAsCString() {
format_sp.reset(new TypeFormatImpl_Format(my_format));
if (GetValueAsCString(*format_sp.get(), m_value_str)) {
if (!m_value_did_change && m_old_value_valid) {
- // The value was gotten successfully, so we consider the
- // value as changed if the value string differs
+ // The value was gotten successfully, so we consider the value as
+ // changed if the value string differs
SetValueDidChange(m_old_value_str != m_value_str);
}
}
@@ -1187,8 +1186,8 @@ const char *ValueObject::GetValueAsCString() {
return m_value_str.c_str();
}
-// if > 8bytes, 0 is returned. this method should mostly be used
-// to read address values out of pointers
+// if > 8bytes, 0 is returned. this method should mostly be used to read
+// address values out of pointers
uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
// If our byte size is zero this is an aggregate type that has children
if (CanProvideValue()) {
@@ -1224,10 +1223,9 @@ int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
}
// if any more "special cases" are added to
-// ValueObject::DumpPrintableRepresentation() please keep
-// this call up to date by returning true for your new special cases. We will
-// eventually move
-// to checking this call result before trying to display special cases
+// ValueObject::DumpPrintableRepresentation() please keep this call up to date
+// by returning true for your new special cases. We will eventually move to
+// checking this call result before trying to display special cases
bool ValueObject::HasSpecialPrintableRepresentation(
ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
Flags flags(GetTypeInfo());
@@ -1276,8 +1274,7 @@ bool ValueObject::DumpPrintableRepresentation(
if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
// when being asked to get a printable display an array or pointer type
- // directly,
- // try to "do the right thing"
+ // directly, try to "do the right thing"
if (IsCStringContainer(true) &&
(custom_format == eFormatCString ||
@@ -1309,8 +1306,8 @@ bool ValueObject::DumpPrintableRepresentation(
if (custom_format == eFormatEnum)
return false;
- // this only works for arrays, because I have no way to know when
- // the pointed memory ends, and no special \0 end of data marker
+ // this only works for arrays, because I have no way to know when the
+ // pointed memory ends, and no special \0 end of data marker
if (flags.Test(eTypeIsArray)) {
if ((custom_format == eFormatBytes) ||
(custom_format == eFormatBytesWithASCII)) {
@@ -1406,8 +1403,8 @@ bool ValueObject::DumpPrintableRepresentation(
llvm::StringRef str;
// this is a local stream that we are using to ensure that the data pointed
- // to by cstr survives long enough for us to copy it to its destination - it
- // is necessary to have this temporary storage area for cases where our
+ // to by cstr survives long enough for us to copy it to its destination -
+ // it is necessary to have this temporary storage area for cases where our
// desired output is not backed by some other longer-term storage
StreamString strm;
@@ -1485,9 +1482,9 @@ bool ValueObject::DumpPrintableRepresentation(
s.PutCString("<no printable representation>");
}
- // we should only return false here if we could not do *anything*
- // even if we have an error message as output, that's a success
- // from our callers' perspective, so return true
+ // we should only return false here if we could not do *anything* even if
+ // we have an error message as output, that's a success from our callers'
+ // perspective, so return true
var_success = true;
if (custom_format != eFormatInvalid)
@@ -1590,9 +1587,8 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
switch (value_type) {
case Value::eValueTypeLoadAddress: {
// If it is a load address, then the scalar value is the storage
- // location
- // of the data, and we have to shove this value down to that load
- // location.
+ // location of the data, and we have to shove this value down to that
+ // load location.
ExecutionContext exe_ctx(GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
if (process) {
@@ -1639,7 +1635,8 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
return false;
}
- // If we have reached this point, then we have successfully changed the value.
+ // If we have reached this point, then we have successfully changed the
+ // value.
SetNeedsUpdate();
return true;
}
@@ -1734,16 +1731,14 @@ bool ValueObject::IsUninitializedReference() {
return false;
}
-// This allows you to create an array member using and index
-// that doesn't not fall in the normal bounds of the array.
-// Many times structure can be defined as:
-// struct Collection
-// {
+// This allows you to create an array member using and index that doesn't not
+// fall in the normal bounds of the array. Many times structure can be defined
+// as: struct Collection {
// uint32_t item_count;
// Item item_array[0];
// };
-// The size of the "item_array" is 1, but many times in practice
-// there are more items in "item_array".
+// The size of the "item_array" is 1, but many times in practice there are more
+// items in "item_array".
ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
bool can_create) {
@@ -1752,13 +1747,13 @@ ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
char index_str[64];
snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index);
ConstString index_const_str(index_str);
- // Check if we have already created a synthetic array member in this
- // valid object. If we have we will re-use it.
+ // Check if we have already created a synthetic array member in this valid
+ // object. If we have we will re-use it.
synthetic_child_sp = GetSyntheticChild(index_const_str);
if (!synthetic_child_sp) {
ValueObject *synthetic_child;
- // We haven't made a synthetic array member for INDEX yet, so
- // lets make one and cache it for any future reference.
+ // We haven't made a synthetic array member for INDEX yet, so lets make
+ // one and cache it for any future reference.
synthetic_child = CreateChildAtIndex(0, true, index);
// Cache the value if we got one back...
@@ -1780,8 +1775,8 @@ ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
char index_str[64];
snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to);
ConstString index_const_str(index_str);
- // Check if we have already created a synthetic array member in this
- // valid object. If we have we will re-use it.
+ // Check if we have already created a synthetic array member in this valid
+ // object. If we have we will re-use it.
synthetic_child_sp = GetSyntheticChild(index_const_str);
if (!synthetic_child_sp) {
uint32_t bit_field_size = to - from + 1;
@@ -1789,8 +1784,8 @@ ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
bit_field_offset =
GetByteSize() * 8 - bit_field_size - bit_field_offset;
- // We haven't made a synthetic array member for INDEX yet, so
- // lets make one and cache it for any future reference.
+ // We haven't made a synthetic array member for INDEX yet, so lets make
+ // one and cache it for any future reference.
ValueObjectChild *synthetic_child = new ValueObjectChild(
*this, GetCompilerType(), index_const_str, GetByteSize(), 0,
bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid,
@@ -1820,8 +1815,8 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
name_const_str.SetCString(name_str);
}
- // Check if we have already created a synthetic array member in this
- // valid object. If we have we will re-use it.
+ // Check if we have already created a synthetic array member in this valid
+ // object. If we have we will re-use it.
synthetic_child_sp = GetSyntheticChild(name_const_str);
if (synthetic_child_sp.get())
@@ -1858,8 +1853,8 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
name_const_str.SetCString(name_str);
}
- // Check if we have already created a synthetic array member in this
- // valid object. If we have we will re-use it.
+ // Check if we have already created a synthetic array member in this valid
+ // object. If we have we will re-use it.
synthetic_child_sp = GetSyntheticChild(name_const_str);
if (synthetic_child_sp.get())
@@ -1884,11 +1879,10 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
return synthetic_child_sp;
}
-// your expression path needs to have a leading . or ->
-// (unless it somehow "looks like" an array, in which case it has
-// a leading [ symbol). while the [ is meaningful and should be shown
-// to the user, . and -> are just parser design, but by no means
-// added information for the user.. strip them off
+// your expression path needs to have a leading . or -> (unless it somehow
+// "looks like" an array, in which case it has a leading [ symbol). while the [
+// is meaningful and should be shown to the user, . and -> are just parser
+// design, but by no means added information for the user.. strip them off
static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
if (!expression || !expression[0])
return expression;
@@ -1904,12 +1898,12 @@ ValueObject::GetSyntheticExpressionPathChild(const char *expression,
bool can_create) {
ValueObjectSP synthetic_child_sp;
ConstString name_const_string(expression);
- // Check if we have already created a synthetic array member in this
- // valid object. If we have we will re-use it.
+ // Check if we have already created a synthetic array member in this valid
+ // object. If we have we will re-use it.
synthetic_child_sp = GetSyntheticChild(name_const_string);
if (!synthetic_child_sp) {
- // We haven't made a synthetic array member for expression yet, so
- // lets make one and cache it for any future reference.
+ // We haven't made a synthetic array member for expression yet, so lets
+ // make one and cache it for any future reference.
synthetic_child_sp = GetValueForExpressionPath(
expression, NULL, NULL,
GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
@@ -2055,10 +2049,9 @@ bool ValueObject::IsBaseClass(uint32_t &depth) {
void ValueObject::GetExpressionPath(Stream &s, bool qualify_cxx_base_classes,
GetExpressionPathFormat epformat) {
// synthetic children do not actually "exist" as part of the hierarchy, and
- // sometimes they are consed up in ways
- // that don't make sense from an underlying language/API standpoint. So, use a
- // special code path here to return
- // something that can hopefully be used in expression
+ // sometimes they are consed up in ways that don't make sense from an
+ // underlying language/API standpoint. So, use a special code path here to
+ // return something that can hopefully be used in expression
if (m_is_synthetic_children_generated) {
UpdateValueIfNeeded();
@@ -2092,11 +2085,10 @@ void ValueObject::GetExpressionPath(Stream &s, bool qualify_cxx_base_classes,
if (is_deref_of_parent &&
epformat == eGetExpressionPathFormatDereferencePointers) {
// this is the original format of GetExpressionPath() producing code like
- // *(a_ptr).memberName, which is entirely
- // fine, until you put this into
+ // *(a_ptr).memberName, which is entirely fine, until you put this into
// StackFrame::GetValueForVariableExpressionPath() which prefers to see
- // a_ptr->memberName.
- // the eHonorPointers mode is meant to produce strings in this latter format
+ // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
+ // in this latter format
s.PutCString("*(");
}
@@ -2105,9 +2097,9 @@ void ValueObject::GetExpressionPath(Stream &s, bool qualify_cxx_base_classes,
if (parent)
parent->GetExpressionPath(s, qualify_cxx_base_classes, epformat);
- // if we are a deref_of_parent just because we are synthetic array
- // members made up to allow ptr[%d] syntax to work in variable
- // printing, then add our name ([%d]) to the expression path
+ // if we are a deref_of_parent just because we are synthetic array members
+ // made up to allow ptr[%d] syntax to work in variable printing, then add our
+ // name ([%d]) to the expression path
if (m_is_array_item_for_pointer &&
epformat == eGetExpressionPathFormatHonorPointers)
s.PutCString(m_name.AsCString());
@@ -2355,8 +2347,8 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
}
// if we are here and options.m_no_synthetic_children is true,
- // child_valobj_sp is going to be a NULL SP,
- // so we hit the "else" branch, and return an error
+ // child_valobj_sp is going to be a NULL SP, so we hit the "else"
+ // branch, and return an error
if (child_valobj_sp.get()) // if it worked, just return
{
*reason_to_stop =
@@ -2424,8 +2416,8 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
}
// if we are here and options.m_no_synthetic_children is true,
- // child_valobj_sp is going to be a NULL SP,
- // so we hit the "else" branch, and return an error
+ // child_valobj_sp is going to be a NULL SP, so we hit the "else"
+ // branch, and return an error
if (child_valobj_sp.get()) // if it worked, move on
{
root = child_valobj_sp;
@@ -2506,8 +2498,8 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
assert(!bracket_expr.empty());
if (!bracket_expr.contains('-')) {
- // if no separator, this is of the form [N]. Note that this cannot
- // be an unbounded range of the form [], because that case was handled
+ // if no separator, this is of the form [N]. Note that this cannot be
+ // an unbounded range of the form [], because that case was handled
// above with an unconditional return.
unsigned long index = 0;
if (bracket_expr.getAsInteger(0, index)) {
@@ -2631,8 +2623,8 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
return nullptr;
}
- // if we are here, then root itself is a synthetic VO.. should be good
- // to go
+ // if we are here, then root itself is a synthetic VO.. should be
+ // good to go
if (!root) {
*reason_to_stop =
@@ -3031,20 +3023,17 @@ ValueObject::EvaluationPoint::EvaluationPoint(
ValueObject::EvaluationPoint::~EvaluationPoint() {}
// This function checks the EvaluationPoint against the current process state.
-// If the current
-// state matches the evaluation point, or the evaluation point is already
-// invalid, then we return
-// false, meaning "no change". If the current state is different, we update our
-// state, and return
-// true meaning "yes, change". If we did see a change, we also set
-// m_needs_update to true, so
-// future calls to NeedsUpdate will return true.
-// exe_scope will be set to the current execution context scope.
+// If the current state matches the evaluation point, or the evaluation point
+// is already invalid, then we return false, meaning "no change". If the
+// current state is different, we update our state, and return true meaning
+// "yes, change". If we did see a change, we also set m_needs_update to true,
+// so future calls to NeedsUpdate will return true. exe_scope will be set to
+// the current execution context scope.
bool ValueObject::EvaluationPoint::SyncWithProcessState(
bool accept_invalid_exe_ctx) {
- // Start with the target, if it is NULL, then we're obviously not going to get
- // any further:
+ // Start with the target, if it is NULL, then we're obviously not going to
+ // get any further:
const bool thread_and_frame_only_if_stopped = true;
ExecutionContext exe_ctx(
m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
@@ -3061,8 +3050,8 @@ bool ValueObject::EvaluationPoint::SyncWithProcessState(
ProcessModID current_mod_id = process->GetModID();
// If the current stop id is 0, either we haven't run yet, or the process
- // state has been cleared.
- // In either case, we aren't going to be able to sync with the process state.
+ // state has been cleared. In either case, we aren't going to be able to sync
+ // with the process state.
if (current_mod_id.GetStopID() == 0)
return false;
@@ -3070,8 +3059,8 @@ bool ValueObject::EvaluationPoint::SyncWithProcessState(
const bool was_valid = m_mod_id.IsValid();
if (was_valid) {
if (m_mod_id == current_mod_id) {
- // Everything is already up to date in this object, no need to
- // update the execution context scope.
+ // Everything is already up to date in this object, no need to update the
+ // execution context scope.
changed = false;
} else {
m_mod_id = current_mod_id;
@@ -3081,10 +3070,9 @@ bool ValueObject::EvaluationPoint::SyncWithProcessState(
}
// Now re-look up the thread and frame in case the underlying objects have
- // gone away & been recreated.
- // That way we'll be sure to return a valid exe_scope.
- // If we used to have a thread or a frame but can't find it anymore, then mark
- // ourselves as invalid.
+ // gone away & been recreated. That way we'll be sure to return a valid
+ // exe_scope. If we used to have a thread or a frame but can't find it
+ // anymore, then mark ourselves as invalid.
if (!accept_invalid_exe_ctx) {
if (m_exe_ctx_ref.HasThreadRef()) {
@@ -3299,11 +3287,9 @@ void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
}
bool ValueObject::CanProvideValue() {
- // we need to support invalid types as providers of values because some
- // bare-board
- // debugging scenarios have no notion of types, but still manage to have raw
- // numeric
- // values for things like registers. sigh.
+ // we need to support invalid types as providers of values because some bare-
+ // board debugging scenarios have no notion of types, but still manage to
+ // have raw numeric values for things like registers. sigh.
const CompilerType &type(GetCompilerType());
return (false == type.IsValid()) ||
(0 != (type.GetTypeInfo() & eTypeHasValue));
@@ -3326,7 +3312,9 @@ ValueObjectSP ValueObject::Persist() {
if (!persistent_state)
return nullptr;
- ConstString name(persistent_state->GetNextPersistentVariableName());
+ auto prefix = persistent_state->GetPersistentVariablePrefix();
+ ConstString name =
+ persistent_state->GetNextPersistentVariableName(*target_sp, prefix);
ValueObjectSP const_result_sp =
ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp
index a489bdc74f5f..e0978f692bc5 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp
@@ -71,9 +71,9 @@ bool ValueObjectCast::UpdateValue() {
m_value.SetCompilerType(compiler_type);
SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren());
if (!CanProvideValue()) {
- // this value object represents an aggregate type whose
- // children have values, but this object does not. So we
- // say we are changed if our location has changed.
+ // this value object represents an aggregate type whose children have
+ // values, but this object does not. So we say we are changed if our
+ // location has changed.
SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
m_value.GetScalar() != old_value.GetScalar());
}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
index 591bc21711ae..019daa2fd3d2 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
@@ -172,8 +172,8 @@ bool ValueObjectChild::UpdateValue() {
} else if (addr == 0) {
m_error.SetErrorString("parent is NULL");
} else {
- // Set this object's scalar value to the address of its
- // value by adding its byte offset to the parent address
+ // Set this object's scalar value to the address of its value by
+ // adding its byte offset to the parent address
m_value.GetScalar() += GetByteOffset();
}
} break;
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
index 0013d0dbf740..e9b48310b0c6 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -122,8 +122,8 @@ bool ValueObjectDynamicValue::UpdateValue() {
return false;
}
- // Setting our type_sp to NULL will route everything back through our
- // parent which is equivalent to not using dynamic values.
+ // Setting our type_sp to NULL will route everything back through our parent
+ // which is equivalent to not using dynamic values.
if (m_use_dynamic == lldb::eNoDynamicValues) {
m_dynamic_type_info.Clear();
return true;
@@ -173,8 +173,7 @@ bool ValueObjectDynamicValue::UpdateValue() {
}
// Getting the dynamic value may have run the program a bit, and so marked us
- // as needing updating, but we really
- // don't...
+ // as needing updating, but we really don't...
m_update_point.SetUpdated();
@@ -192,8 +191,8 @@ bool ValueObjectDynamicValue::UpdateValue() {
}
// If we don't have a dynamic type, then make ourselves just a echo of our
- // parent.
- // Or we could return false, and make ourselves an echo of our parent?
+ // parent. Or we could return false, and make ourselves an echo of our
+ // parent?
if (!found_dynamic_type) {
if (m_dynamic_type_info)
SetValueDidChange(true);
@@ -248,14 +247,14 @@ bool ValueObjectDynamicValue::UpdateValue() {
static_cast<void *>(this), GetTypeName().GetCString());
if (m_address.IsValid() && m_dynamic_type_info) {
- // The variable value is in the Scalar value inside the m_value.
- // We can point our m_data right to it.
+ // The variable value is in the Scalar value inside the m_value. We can
+ // point our m_data right to it.
m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
if (m_error.Success()) {
if (!CanProvideValue()) {
- // this value object represents an aggregate type whose
- // children have values, but this object does not. So we
- // say we are changed if our location has changed.
+ // this value object represents an aggregate type whose children have
+ // values, but this object does not. So we say we are changed if our
+ // location has changed.
SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
m_value.GetScalar() != old_value.GetScalar());
}
@@ -287,13 +286,11 @@ bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
return false;
}
- // if we are at an offset from our parent, in order to set ourselves correctly
- // we would need
- // to change the new value so that it refers to the correct dynamic type. we
- // choose not to deal
- // with that - if anything more than a value overwrite is required, you should
- // be using the
- // expression parser instead of the value editing facility
+ // if we are at an offset from our parent, in order to set ourselves
+ // correctly we would need to change the new value so that it refers to the
+ // correct dynamic type. we choose not to deal with that - if anything more
+ // than a value overwrite is required, you should be using the expression
+ // parser instead of the value editing facility
if (my_value != parent_value) {
// but NULL'ing out a value should always be allowed
if (strcmp(value_str, "0")) {
@@ -322,13 +319,11 @@ bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
return false;
}
- // if we are at an offset from our parent, in order to set ourselves correctly
- // we would need
- // to change the new value so that it refers to the correct dynamic type. we
- // choose not to deal
- // with that - if anything more than a value overwrite is required, you should
- // be using the
- // expression parser instead of the value editing facility
+ // if we are at an offset from our parent, in order to set ourselves
+ // correctly we would need to change the new value so that it refers to the
+ // correct dynamic type. we choose not to deal with that - if anything more
+ // than a value overwrite is required, you should be using the expression
+ // parser instead of the value editing facility
if (my_value != parent_value) {
// but NULL'ing out a value should always be allowed
lldb::offset_t offset = 0;
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectList.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectList.cpp
index 00aee798c0e3..0dd07252888f 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectList.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectList.cpp
@@ -87,8 +87,8 @@ ValueObjectSP ValueObjectList::FindValueObjectByUID(lldb::user_id_t uid) {
collection::iterator pos, end = m_value_objects.end();
for (pos = m_value_objects.begin(); pos != end; ++pos) {
- // Watch out for NULL objects in our list as the list
- // might get resized to a specific size and lazily filled in
+ // Watch out for NULL objects in our list as the list might get resized to
+ // a specific size and lazily filled in
ValueObject *valobj = (*pos).get();
if (valobj && valobj->GetID() == uid) {
valobj_sp = *pos;
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp
index e26900014c9d..3e71fea6bb35 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp
@@ -165,21 +165,20 @@ bool ValueObjectMemory::UpdateValue() {
llvm_unreachable("Unhandled expression result value kind...");
case Value::eValueTypeScalar:
- // The variable value is in the Scalar value inside the m_value.
- // We can point our m_data right to it.
+ // The variable value is in the Scalar value inside the m_value. We can
+ // point our m_data right to it.
m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
break;
case Value::eValueTypeFileAddress:
case Value::eValueTypeLoadAddress:
case Value::eValueTypeHostAddress:
- // The DWARF expression result was an address in the inferior
- // process. If this variable is an aggregate type, we just need
- // the address as the main value as all child variable objects
- // will rely upon this location and add an offset and then read
- // their own values as needed. If this variable is a simple
- // type, we read all data for it into m_data.
- // Make sure this type has a value before we try and read it
+ // The DWARF expression result was an address in the inferior process. If
+ // this variable is an aggregate type, we just need the address as the
+ // main value as all child variable objects will rely upon this location
+ // and add an offset and then read their own values as needed. If this
+ // variable is a simple type, we read all data for it into m_data. Make
+ // sure this type has a value before we try and read it
// If we have a file address, convert it to a load address if we can.
if (value_type == Value::eValueTypeFileAddress &&
@@ -192,14 +191,14 @@ bool ValueObjectMemory::UpdateValue() {
}
if (!CanProvideValue()) {
- // this value object represents an aggregate type whose
- // children have values, but this object does not. So we
- // say we are changed if our location has changed.
+ // this value object represents an aggregate type whose children have
+ // values, but this object does not. So we say we are changed if our
+ // location has changed.
SetValueDidChange(value_type != old_value.GetValueType() ||
m_value.GetScalar() != old_value.GetScalar());
} else {
- // Copy the Value and set the context to use our Variable
- // so it can extract read its value into m_data appropriately
+ // Copy the Value and set the context to use our Variable so it can
+ // extract read its value into m_data appropriately
Value value(m_value);
if (m_type_sp)
value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index 87310c423cb8..044387a4ae12 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -129,7 +129,19 @@ lldb::ValueType ValueObjectSynthetic::GetValueType() const {
}
void ValueObjectSynthetic::CreateSynthFilter() {
- m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
+ ValueObject *valobj_for_frontend = m_parent;
+ if (m_synth_sp->WantsDereference())
+ {
+ CompilerType type = m_parent->GetCompilerType();
+ if (type.IsValid() && type.IsPointerOrReferenceType())
+ {
+ Status error;
+ lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
+ if (error.Success())
+ valobj_for_frontend = deref_sp.get();
+ }
+ }
+ m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
if (!m_synth_filter_ap.get())
m_synth_filter_ap = llvm::make_unique<DummySyntheticFrontEnd>(*m_parent);
}
@@ -171,10 +183,9 @@ bool ValueObjectSynthetic::UpdateValue() {
m_children_byindex.Clear();
m_name_toindex.Clear();
// usually, an object's value can change but this does not alter its
- // children count
- // for a synthetic VO that might indeed happen, so we need to tell the upper
- // echelons
- // that they need to come back to us asking for children
+ // children count for a synthetic VO that might indeed happen, so we need
+ // to tell the upper echelons that they need to come back to us asking for
+ // children
m_children_count_valid = false;
m_synthetic_children_cache.Clear();
m_synthetic_children_count = UINT32_MAX;
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp
index 8436ba529a54..bfe5c3de7fbf 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp
@@ -175,9 +175,8 @@ bool ValueObjectVariable::UpdateValue() {
switch (value_type) {
case Value::eValueTypeFileAddress:
// If this type is a pointer, then its children will be considered load
- // addresses
- // if the pointer or reference is dereferenced, but only if the process
- // is alive.
+ // addresses if the pointer or reference is dereferenced, but only if
+ // the process is alive.
//
// There could be global variables like in the following code:
// struct LinkedListNode { Foo* foo; LinkedListNode* next; };
@@ -187,14 +186,11 @@ bool ValueObjectVariable::UpdateValue() {
// LinkedListNode g_first_node = { &g_foo1, &g_second_node };
//
// When we aren't running, we should be able to look at these variables
- // using
- // the "target variable" command. Children of the "g_first_node" always
- // will
- // be of the same address type as the parent. But children of the "next"
- // member of
- // LinkedListNode will become load addresses if we have a live process,
- // or remain
- // what a file address if it what a file address.
+ // using the "target variable" command. Children of the "g_first_node"
+ // always will be of the same address type as the parent. But children
+ // of the "next" member of LinkedListNode will become load addresses if
+ // we have a live process, or remain what a file address if it what a
+ // file address.
if (process_is_alive && is_pointer_or_ref)
SetAddressTypeOfChildren(eAddressTypeLoad);
else
@@ -202,12 +198,10 @@ bool ValueObjectVariable::UpdateValue() {
break;
case Value::eValueTypeHostAddress:
// Same as above for load addresses, except children of pointer or refs
- // are always
- // load addresses. Host addresses are used to store freeze dried
- // variables. If this
- // type is a struct, the entire struct contents will be copied into the
- // heap of the
- // LLDB process, but we do not currrently follow any pointers.
+ // are always load addresses. Host addresses are used to store freeze
+ // dried variables. If this type is a struct, the entire struct
+ // contents will be copied into the heap of the
+ // LLDB process, but we do not currently follow any pointers.
if (is_pointer_or_ref)
SetAddressTypeOfChildren(eAddressTypeLoad);
else
@@ -224,8 +218,8 @@ bool ValueObjectVariable::UpdateValue() {
case Value::eValueTypeVector:
// fall through
case Value::eValueTypeScalar:
- // The variable value is in the Scalar value inside the m_value.
- // We can point our m_data right to it.
+ // The variable value is in the Scalar value inside the m_value. We can
+ // point our m_data right to it.
m_error =
m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
break;
@@ -233,44 +227,26 @@ bool ValueObjectVariable::UpdateValue() {
case Value::eValueTypeFileAddress:
case Value::eValueTypeLoadAddress:
case Value::eValueTypeHostAddress:
- // The DWARF expression result was an address in the inferior
- // process. If this variable is an aggregate type, we just need
- // the address as the main value as all child variable objects
- // will rely upon this location and add an offset and then read
- // their own values as needed. If this variable is a simple
- // type, we read all data for it into m_data.
- // Make sure this type has a value before we try and read it
+ // The DWARF expression result was an address in the inferior process.
+ // If this variable is an aggregate type, we just need the address as
+ // the main value as all child variable objects will rely upon this
+ // location and add an offset and then read their own values as needed.
+ // If this variable is a simple type, we read all data for it into
+ // m_data. Make sure this type has a value before we try and read it
// If we have a file address, convert it to a load address if we can.
- if (value_type == Value::eValueTypeFileAddress && process_is_alive) {
- lldb::addr_t file_addr =
- m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- if (file_addr != LLDB_INVALID_ADDRESS) {
- SymbolContext var_sc;
- variable->CalculateSymbolContext(&var_sc);
- if (var_sc.module_sp) {
- ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
- if (objfile) {
- Address so_addr(file_addr, objfile->GetSectionList());
- lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
- if (load_addr != LLDB_INVALID_ADDRESS) {
- m_value.SetValueType(Value::eValueTypeLoadAddress);
- m_value.GetScalar() = load_addr;
- }
- }
- }
- }
- }
+ if (value_type == Value::eValueTypeFileAddress && process_is_alive)
+ m_value.ConvertToLoadAddress(GetModule().get(), target);
if (!CanProvideValue()) {
- // this value object represents an aggregate type whose
- // children have values, but this object does not. So we
- // say we are changed if our location has changed.
+ // this value object represents an aggregate type whose children have
+ // values, but this object does not. So we say we are changed if our
+ // location has changed.
SetValueDidChange(value_type != old_value.GetValueType() ||
m_value.GetScalar() != old_value.GetScalar());
} else {
- // Copy the Value and set the context to use our Variable
- // so it can extract read its value into m_data appropriately
+ // Copy the Value and set the context to use our Variable so it can
+ // extract read its value into m_data appropriately
Value value(m_value);
value.SetContext(Value::eContextTypeVariable, variable);
m_error =
@@ -299,14 +275,13 @@ bool ValueObjectVariable::IsInScope() {
if (frame) {
return m_variable_sp->IsInScope(frame);
} else {
- // This ValueObject had a frame at one time, but now we
- // can't locate it, so return false since we probably aren't
- // in scope.
+ // This ValueObject had a frame at one time, but now we can't locate it,
+ // so return false since we probably aren't in scope.
return false;
}
}
- // We have a variable that wasn't tied to a frame, which
- // means it is a global and is always in scope.
+ // We have a variable that wasn't tied to a frame, which means it is a global
+ // and is always in scope.
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp
index 7619b6f6f82b..bafee1799b80 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp
@@ -494,8 +494,8 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
if (valobj.GetNumChildren() == 0)
return false;
- // ask the type if it has any opinion about this
- // eLazyBoolCalculate == no opinion; other values should be self explanatory
+ // ask the type if it has any opinion about this eLazyBoolCalculate == no
+ // opinion; other values should be self explanatory
CompilerType compiler_type(valobj.GetCompilerType());
if (compiler_type.IsValid()) {
switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) {
@@ -532,8 +532,7 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
}
// if we decided to define synthetic children for a type, we probably care
- // enough
- // to show them, but avoid nesting children in children
+ // enough to show them, but avoid nesting children in children
if (child_sp->GetSyntheticChildren().get() != nullptr) {
ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
// wait.. wat? just get out of here..
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp
index 84143a541087..89d7a95069ca 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp
@@ -26,9 +26,8 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-// we define this for all values of type but only implement it for those we care
-// about
-// that's good because we get linker errors for any unsupported type
+// we define this for all values of type but only implement it for those we
+// care about that's good because we get linker errors for any unsupported type
template <lldb_private::formatters::StringPrinter::StringElementType type>
static StringPrinter::StringPrinterBufferPointer<>
GetPrintableImpl(uint8_t *buffer, uint8_t *buffer_end, uint8_t *&next);
@@ -163,8 +162,8 @@ GetPrintableImpl<StringPrinter::StringElementType::UTF8>(uint8_t *buffer,
(unsigned char)*(buffer + 2), (unsigned char)*(buffer + 3));
break;
default:
- // this is probably some bogus non-character thing
- // just print it as-is and hope to sync up again soon
+ // this is probably some bogus non-character thing just print it as-is and
+ // hope to sync up again soon
retval = {buffer, 1};
next = buffer + 1;
return retval;
@@ -223,9 +222,9 @@ GetPrintableImpl<StringPrinter::StringElementType::UTF8>(uint8_t *buffer,
return retval;
}
-// Given a sequence of bytes, this function returns:
-// a sequence of bytes to actually print out + a length
-// the following unscanned position of the buffer is in next
+// Given a sequence of bytes, this function returns: a sequence of bytes to
+// actually print out + a length the following unscanned position of the buffer
+// is in next
static StringPrinter::StringPrinterBufferPointer<>
GetPrintable(StringPrinter::StringElementType type, uint8_t *buffer,
uint8_t *buffer_end, uint8_t *&next) {
@@ -321,8 +320,7 @@ static bool DumpUTFBufferToStream(
(llvm::UTF8 *)utf8_data_buffer_sp->GetBytes();
} else {
// just copy the pointers - the cast is necessary to make the compiler
- // happy
- // but this should only happen if we are reading UTF8 data
+ // happy but this should only happen if we are reading UTF8 data
utf8_data_ptr = const_cast<llvm::UTF8 *>(
reinterpret_cast<const llvm::UTF8 *>(data_ptr));
utf8_data_end_ptr = const_cast<llvm::UTF8 *>(
@@ -344,8 +342,8 @@ static bool DumpUTFBufferToStream(
}
// since we tend to accept partial data (and even partially malformed data)
- // we might end up with no NULL terminator before the end_ptr
- // hence we need to take a slower route and ensure we stay within boundaries
+ // we might end up with no NULL terminator before the end_ptr hence we need
+ // to take a slower route and ensure we stay within boundaries
for (; utf8_data_ptr < utf8_data_end_ptr;) {
if (zero_is_terminator && !*utf8_data_ptr)
break;
@@ -472,8 +470,8 @@ bool StringPrinter::ReadStringAndDumpToStream<
}
// since we tend to accept partial data (and even partially malformed data)
- // we might end up with no NULL terminator before the end_ptr
- // hence we need to take a slower route and ensure we stay within boundaries
+ // we might end up with no NULL terminator before the end_ptr hence we need
+ // to take a slower route and ensure we stay within boundaries
for (uint8_t *data = buffer_sp->GetBytes(); *data && (data < data_end);) {
if (escape_non_printables) {
uint8_t *next_data = nullptr;
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
index 333fe91b76db..7902ccb47771 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
@@ -111,12 +111,12 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
valobj->GetBitfieldBitSize(), // Bitfield bit size
valobj->GetBitfieldBitOffset(), // Bitfield bit offset
exe_scope);
- // Given that we do not want to set the ValueObject's m_error
- // for a formatting error (or else we wouldn't be able to reformat
- // until a next update), an empty string is treated as a "false"
- // return from here, but that's about as severe as we get
- // CompilerType::DumpTypeValue() should always return
- // something, even if that something is an error message
+ // Given that we do not want to set the ValueObject's m_error for a
+ // formatting error (or else we wouldn't be able to reformat until a
+ // next update), an empty string is treated as a "false" return from
+ // here, but that's about as severe as we get
+ // CompilerType::DumpTypeValue() should always return something, even
+ // if that something is an error message
dest = sstr.GetString();
}
}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 863ff3af12e8..43e91a2b6c92 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -244,8 +244,8 @@ void ValueObjectPrinter::PrintDecl() {
// always show the type at the root level if it is invalid
if (show_type) {
- // Some ValueObjects don't have types (like registers sets). Only print
- // the type if there is one to print
+ // Some ValueObjects don't have types (like registers sets). Only print the
+ // type if there is one to print
ConstString type_name;
if (m_compiler_type.IsValid()) {
if (m_options.m_use_type_display_name)
@@ -402,12 +402,10 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
}
if (m_error.size()) {
// we need to support scenarios in which it is actually fine for a value
- // to have no type
- // but - on the other hand - if we get an error *AND* have no type, we try
- // to get out
- // gracefully, since most often that combination means "could not resolve
- // a type"
- // and the default failure mode is quite ugly
+ // to have no type but - on the other hand - if we get an error *AND*
+ // have no type, we try to get out gracefully, since most often that
+ // combination means "could not resolve a type" and the default failure
+ // mode is quite ugly
if (!m_compiler_type.IsValid()) {
m_stream->Printf(" <could not resolve type>");
return false;
@@ -416,10 +414,10 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
error_printed = true;
m_stream->Printf(" <%s>\n", m_error.c_str());
} else {
- // Make sure we have a value and make sure the summary didn't
- // specify that the value should not be printed - and do not print
- // the value if this thing is nil
- // (but show the value if the user passes a format explicitly)
+ // Make sure we have a value and make sure the summary didn't specify
+ // that the value should not be printed - and do not print the value if
+ // this thing is nil (but show the value if the user passes a format
+ // explicitly)
TypeSummaryImpl *entry = GetSummaryFormatter();
if (!IsNil() && !IsUninitialized() && !m_value.empty() &&
(entry == NULL || (entry->DoesPrintValue(m_valobj) ||
@@ -494,8 +492,8 @@ bool ValueObjectPrinter::ShouldPrintChildren(
if (is_uninit)
return false;
- // if the user has specified an element count, always print children
- // as it is explicit user demand being honored
+ // if the user has specified an element count, always print children as it is
+ // explicit user demand being honored
if (m_options.m_pointer_as_array)
return true;
@@ -505,17 +503,16 @@ bool ValueObjectPrinter::ShouldPrintChildren(
return false;
if (is_failed_description || m_curr_depth < m_options.m_max_depth) {
- // We will show children for all concrete types. We won't show
- // pointer contents unless a pointer depth has been specified.
- // We won't reference contents unless the reference is the
- // root object (depth of zero).
+ // We will show children for all concrete types. We won't show pointer
+ // contents unless a pointer depth has been specified. We won't reference
+ // contents unless the reference is the root object (depth of zero).
- // Use a new temporary pointer depth in case we override the
- // current pointer depth below...
+ // Use a new temporary pointer depth in case we override the current
+ // pointer depth below...
if (is_ptr || is_ref) {
- // We have a pointer or reference whose value is an address.
- // Make sure that address is not NULL
+ // We have a pointer or reference whose value is an address. Make sure
+ // that address is not NULL
AddressType ptr_address_type;
if (m_valobj->GetPointerValue(&ptr_address_type) == 0)
return false;
@@ -523,10 +520,10 @@ bool ValueObjectPrinter::ShouldPrintChildren(
const bool is_root_level = m_curr_depth == 0;
if (is_ref && is_root_level) {
- // If this is the root object (depth is zero) that we are showing
- // and it is a reference, and no pointer depth has been supplied
- // print out what it references. Don't do this at deeper depths
- // otherwise we can end up with infinite recursion...
+ // If this is the root object (depth is zero) that we are showing and
+ // it is a reference, and no pointer depth has been supplied print out
+ // what it references. Don't do this at deeper depths otherwise we can
+ // end up with infinite recursion...
return true;
}
@@ -759,8 +756,7 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
bool summary_printed) {
// this flag controls whether we tried to display a description for this
- // object and failed
- // if that happens, we want to display the children, if any
+ // object and failed if that happens, we want to display the children, if any
bool is_failed_description =
!PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp
index 4fb92cad3988..d85a7e674177 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp
@@ -157,9 +157,8 @@ static lldb::Format GetItemFormatForFormat(lldb::Format format,
case lldb::eFormatDefault: {
// special case the (default, char) combination to actually display as an
- // integer value
- // most often, you won't want to see the ASCII characters... (and if you do,
- // eFormatChar is a keystroke away)
+ // integer value most often, you won't want to see the ASCII characters...
+ // (and if you do, eFormatChar is a keystroke away)
bool is_char = element_type.IsCharType();
bool is_signed = false;
element_type.IsIntegerType(is_signed);
diff --git a/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp
index 14011aece7c9..55eb65f32b5a 100644
--- a/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp
@@ -15,6 +15,7 @@
// C++ Includes
#include <vector>
+#include "lldb/Core/Module.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
@@ -37,13 +38,13 @@
#include "lldb/Target/StackID.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h"
+#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
using namespace lldb;
using namespace lldb_private;
static lldb::addr_t
-ReadAddressFromDebugAddrSection(const DWARFCompileUnit *dwarf_cu,
+ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu,
uint32_t index) {
uint32_t index_size = dwarf_cu->GetAddressByteSize();
dw_offset_t addr_base = dwarf_cu->GetAddrBase();
@@ -55,7 +56,7 @@ ReadAddressFromDebugAddrSection(const DWARFCompileUnit *dwarf_cu,
//----------------------------------------------------------------------
// DWARFExpression constructor
//----------------------------------------------------------------------
-DWARFExpression::DWARFExpression(DWARFCompileUnit *dwarf_cu)
+DWARFExpression::DWARFExpression(DWARFUnit *dwarf_cu)
: m_module_wp(), m_data(), m_dwarf_cu(dwarf_cu),
m_reg_kind(eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS) {}
@@ -66,7 +67,7 @@ DWARFExpression::DWARFExpression(const DWARFExpression &rhs)
DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
const DataExtractor &data,
- DWARFCompileUnit *dwarf_cu,
+ DWARFUnit *dwarf_cu,
lldb::offset_t data_offset,
lldb::offset_t data_length)
: m_module_wp(), m_data(data, data_offset, data_length),
@@ -147,13 +148,13 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset,
break;
case lldb::eDescriptionLevelBrief:
- if (offset > start_offset)
+ if (op_offset > start_offset)
s->PutChar(' ');
break;
case lldb::eDescriptionLevelFull:
case lldb::eDescriptionLevelVerbose:
- if (offset > start_offset)
+ if (op_offset > start_offset)
s->EOL();
s->Indent();
if (level == lldb::eDescriptionLevelFull)
@@ -172,34 +173,34 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset,
*s << "DW_OP_deref";
break; // 0x06
case DW_OP_const1u:
- s->Printf("DW_OP_const1u(0x%2.2x) ", m_data.GetU8(&offset));
+ s->Printf("DW_OP_const1u(0x%2.2x)", m_data.GetU8(&offset));
break; // 0x08 1 1-byte constant
case DW_OP_const1s:
- s->Printf("DW_OP_const1s(0x%2.2x) ", m_data.GetU8(&offset));
+ s->Printf("DW_OP_const1s(0x%2.2x)", m_data.GetU8(&offset));
break; // 0x09 1 1-byte constant
case DW_OP_const2u:
- s->Printf("DW_OP_const2u(0x%4.4x) ", m_data.GetU16(&offset));
+ s->Printf("DW_OP_const2u(0x%4.4x)", m_data.GetU16(&offset));
break; // 0x0a 1 2-byte constant
case DW_OP_const2s:
- s->Printf("DW_OP_const2s(0x%4.4x) ", m_data.GetU16(&offset));
+ s->Printf("DW_OP_const2s(0x%4.4x)", m_data.GetU16(&offset));
break; // 0x0b 1 2-byte constant
case DW_OP_const4u:
- s->Printf("DW_OP_const4u(0x%8.8x) ", m_data.GetU32(&offset));
+ s->Printf("DW_OP_const4u(0x%8.8x)", m_data.GetU32(&offset));
break; // 0x0c 1 4-byte constant
case DW_OP_const4s:
- s->Printf("DW_OP_const4s(0x%8.8x) ", m_data.GetU32(&offset));
+ s->Printf("DW_OP_const4s(0x%8.8x)", m_data.GetU32(&offset));
break; // 0x0d 1 4-byte constant
case DW_OP_const8u:
- s->Printf("DW_OP_const8u(0x%16.16" PRIx64 ") ", m_data.GetU64(&offset));
+ s->Printf("DW_OP_const8u(0x%16.16" PRIx64 ")", m_data.GetU64(&offset));
break; // 0x0e 1 8-byte constant
case DW_OP_const8s:
- s->Printf("DW_OP_const8s(0x%16.16" PRIx64 ") ", m_data.GetU64(&offset));
+ s->Printf("DW_OP_const8s(0x%16.16" PRIx64 ")", m_data.GetU64(&offset));
break; // 0x0f 1 8-byte constant
case DW_OP_constu:
- s->Printf("DW_OP_constu(0x%" PRIx64 ") ", m_data.GetULEB128(&offset));
+ s->Printf("DW_OP_constu(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
break; // 0x10 1 ULEB128 constant
case DW_OP_consts:
- s->Printf("DW_OP_consts(0x%" PRId64 ") ", m_data.GetSLEB128(&offset));
+ s->Printf("DW_OP_consts(0x%" PRId64 ")", m_data.GetSLEB128(&offset));
break; // 0x11 1 SLEB128 constant
case DW_OP_dup:
s->PutCString("DW_OP_dup");
@@ -211,7 +212,7 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset,
s->PutCString("DW_OP_over");
break; // 0x14
case DW_OP_pick:
- s->Printf("DW_OP_pick(0x%2.2x) ", m_data.GetU8(&offset));
+ s->Printf("DW_OP_pick(0x%2.2x)", m_data.GetU8(&offset));
break; // 0x15 1 1-byte stack index
case DW_OP_swap:
s->PutCString("DW_OP_swap");
@@ -253,7 +254,7 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset,
s->PutCString("DW_OP_plus");
break; // 0x22
case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend
- s->Printf("DW_OP_plus_uconst(0x%" PRIx64 ") ",
+ s->Printf("DW_OP_plus_uconst(0x%" PRIx64 ")",
m_data.GetULEB128(&offset));
break;
@@ -679,8 +680,8 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
error_ptr->Clear();
return true;
} else {
- // If we get this error, then we need to implement a value
- // buffer in the dwarf expression evaluation function...
+ // If we get this error, then we need to implement a value buffer in
+ // the dwarf expression evaluation function...
if (error_ptr)
error_ptr->SetErrorStringWithFormat(
"register %s can't be converted to a scalar value",
@@ -991,17 +992,17 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
if (op == DW_OP_addr) {
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
- // We have to make a copy of the data as we don't know if this
- // data is from a read only memory mapped buffer, so we duplicate
- // all of the data first, then modify it, and if all goes well,
- // we then replace the data for this expression
+ // We have to make a copy of the data as we don't know if this data is
+ // from a read only memory mapped buffer, so we duplicate all of the data
+ // first, then modify it, and if all goes well, we then replace the data
+ // for this expression
// So first we copy the data into a heap buffer
std::unique_ptr<DataBufferHeap> head_data_ap(
new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize()));
- // Make en encoder so we can write the address into the buffer using
- // the correct byte order (endianness)
+ // Make en encoder so we can write the address into the buffer using the
+ // correct byte order (endianness)
DataEncoder encoder(head_data_ap->GetBytes(), head_data_ap->GetByteSize(),
m_data.GetByteOrder(), addr_byte_size);
@@ -1009,9 +1010,8 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
if (encoder.PutMaxU64(offset, addr_byte_size, file_addr) == UINT32_MAX)
return false;
- // All went well, so now we can reset the data using a shared
- // pointer to the heap data so "m_data" will now correctly
- // manage the heap data.
+ // All went well, so now we can reset the data using a shared pointer to
+ // the heap data so "m_data" will now correctly manage the heap data.
m_data.SetData(DataBufferSP(head_data_ap.release()));
return true;
} else {
@@ -1025,9 +1025,9 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
}
bool DWARFExpression::ContainsThreadLocalStorage() const {
- // We are assuming for now that any thread local variable will not
- // have a location list. This has been true for all thread local
- // variables we have seen so far produced by any compiler.
+ // We are assuming for now that any thread local variable will not have a
+ // location list. This has been true for all thread local variables we have
+ // seen so far produced by any compiler.
if (IsLocationList())
return false;
lldb::offset_t offset = 0;
@@ -1048,24 +1048,24 @@ bool DWARFExpression::LinkThreadLocalStorage(
lldb::ModuleSP new_module_sp,
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
&link_address_callback) {
- // We are assuming for now that any thread local variable will not
- // have a location list. This has been true for all thread local
- // variables we have seen so far produced by any compiler.
+ // We are assuming for now that any thread local variable will not have a
+ // location list. This has been true for all thread local variables we have
+ // seen so far produced by any compiler.
if (IsLocationList())
return false;
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
- // We have to make a copy of the data as we don't know if this
- // data is from a read only memory mapped buffer, so we duplicate
- // all of the data first, then modify it, and if all goes well,
- // we then replace the data for this expression
+ // We have to make a copy of the data as we don't know if this data is from a
+ // read only memory mapped buffer, so we duplicate all of the data first,
+ // then modify it, and if all goes well, we then replace the data for this
+ // expression
// So first we copy the data into a heap buffer
std::shared_ptr<DataBufferHeap> heap_data_sp(
new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize()));
- // Make en encoder so we can write the address into the buffer using
- // the correct byte order (endianness)
+ // Make en encoder so we can write the address into the buffer using the
+ // correct byte order (endianness)
DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(),
m_data.GetByteOrder(), addr_byte_size);
@@ -1080,8 +1080,7 @@ bool DWARFExpression::LinkThreadLocalStorage(
switch (op) {
case DW_OP_const4u:
// Remember the const offset in case we later have a
- // DW_OP_form_tls_address
- // or DW_OP_GNU_push_tls_address
+ // DW_OP_form_tls_address or DW_OP_GNU_push_tls_address
const_offset = offset;
const_value = m_data.GetU32(&offset);
decoded_data = true;
@@ -1090,8 +1089,7 @@ bool DWARFExpression::LinkThreadLocalStorage(
case DW_OP_const8u:
// Remember the const offset in case we later have a
- // DW_OP_form_tls_address
- // or DW_OP_GNU_push_tls_address
+ // DW_OP_form_tls_address or DW_OP_GNU_push_tls_address
const_offset = offset;
const_value = m_data.GetU64(&offset);
decoded_data = true;
@@ -1101,21 +1099,15 @@ bool DWARFExpression::LinkThreadLocalStorage(
case DW_OP_form_tls_address:
case DW_OP_GNU_push_tls_address:
// DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded
- // by
- // a file address on the stack. We assume that DW_OP_const4u or
- // DW_OP_const8u
- // is used for these values, and we check that the last opcode we got
- // before
- // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can
- // link
- // the value accodingly. For Darwin, the value in the DW_OP_const4u or
- // DW_OP_const8u is the file address of a structure that contains a
- // function
- // pointer, the pthread key and the offset into the data pointed to by the
- // pthread key. So we must link this address and also set the module of
- // this
- // expression to the new_module_sp so we can resolve the file address
- // correctly
+ // by a file address on the stack. We assume that DW_OP_const4u or
+ // DW_OP_const8u is used for these values, and we check that the last
+ // opcode we got before either of these was DW_OP_const4u or
+ // DW_OP_const8u. If so, then we can link the value accodingly. For
+ // Darwin, the value in the DW_OP_const4u or DW_OP_const8u is the file
+ // address of a structure that contains a function pointer, the pthread
+ // key and the offset into the data pointed to by the pthread key. So we
+ // must link this address and also set the module of this expression to
+ // the new_module_sp so we can resolve the file address correctly
if (const_byte_size > 0) {
lldb::addr_t linked_file_addr = link_address_callback(const_value);
if (linked_file_addr == LLDB_INVALID_ADDRESS)
@@ -1144,8 +1136,8 @@ bool DWARFExpression::LinkThreadLocalStorage(
}
// If we linked the TLS address correctly, update the module so that when the
- // expression
- // is evaluated it can resolve the file address to a load address and read the
+ // expression is evaluated it can resolve the file address to a load address
+ // and read the
// TLS data
m_module_wp = new_module_sp;
m_data.SetData(heap_data_sp);
@@ -1323,7 +1315,7 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
bool DWARFExpression::Evaluate(
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
- DWARFCompileUnit *dwarf_cu, const lldb::offset_t opcodes_offset,
+ DWARFUnit *dwarf_cu, const lldb::offset_t opcodes_offset,
const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind,
const Value *initial_value_ptr, const Value *object_address_ptr,
Value &result, Status *error_ptr) {
@@ -1383,6 +1375,7 @@ bool DWARFExpression::Evaluate(
}
log->Printf("0x%8.8" PRIx64 ": %s", op_offset, DW_OP_value_to_name(op));
}
+
switch (op) {
//----------------------------------------------------------------------
// The DW_OP_addr operation has a single operand that encodes a machine
@@ -1391,17 +1384,22 @@ bool DWARFExpression::Evaluate(
case DW_OP_addr:
stack.push_back(Scalar(opcodes.GetAddress(&offset)));
stack.back().SetValueType(Value::eValueTypeFileAddress);
+ // Convert the file address to a load address, so subsequent
+ // DWARF operators can operate on it.
+ if (frame)
+ stack.back().ConvertToLoadAddress(module_sp.get(),
+ frame->CalculateTarget().get());
break;
//----------------------------------------------------------------------
// The DW_OP_addr_sect_offset4 is used for any location expressions in
// shared libraries that have a location like:
// DW_OP_addr(0x1000)
- // If this address resides in a shared library, then this virtual
- // address won't make sense when it is evaluated in the context of a
- // running process where shared libraries have been slid. To account for
- // this, this new address type where we can store the section pointer
- // and a 4 byte offset.
+ // If this address resides in a shared library, then this virtual address
+ // won't make sense when it is evaluated in the context of a running
+ // process where shared libraries have been slid. To account for this, this
+ // new address type where we can store the section pointer and a 4 byte
+ // offset.
//----------------------------------------------------------------------
// case DW_OP_addr_sect_offset4:
// {
@@ -1436,9 +1434,9 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_deref
// OPERANDS: none
// DESCRIPTION: Pops the top stack entry and treats it as an address.
- // The value retrieved from that address is pushed. The size of the
- // data retrieved from the dereferenced address is the size of an
- // address on the target machine.
+ // The value retrieved from that address is pushed. The size of the data
+ // retrieved from the dereferenced address is the size of an address on the
+ // target machine.
//----------------------------------------------------------------------
case DW_OP_deref: {
if (stack.empty()) {
@@ -1455,6 +1453,33 @@ bool DWARFExpression::Evaluate(
stack.back().GetScalar() = ptr;
stack.back().ClearContext();
} break;
+ case Value::eValueTypeFileAddress: {
+ auto file_addr = stack.back().GetScalar().ULongLong(
+ LLDB_INVALID_ADDRESS);
+ if (!module_sp) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "need module to resolve file address for DW_OP_deref");
+ return false;
+ }
+ Address so_addr;
+ if (!module_sp->ResolveFileAddress(file_addr, so_addr)) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "failed to resolve file address in module");
+ return false;
+ }
+ addr_t load_Addr = so_addr.GetLoadAddress(exe_ctx->GetTargetPtr());
+ if (load_Addr == LLDB_INVALID_ADDRESS) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "failed to resolve load address");
+ return false;
+ }
+ stack.back().GetScalar() = load_Addr;
+ stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ // Fall through to load address code below...
+ } LLVM_FALLTHROUGH;
case Value::eValueTypeLoadAddress:
if (exe_ctx) {
if (process) {
@@ -1500,13 +1525,13 @@ bool DWARFExpression::Evaluate(
// 1 - uint8_t that specifies the size of the data to dereference.
// DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top
// stack entry and treats it as an address. The value retrieved from that
- // address is pushed. In the DW_OP_deref_size operation, however, the
- // size in bytes of the data retrieved from the dereferenced address is
+ // address is pushed. In the DW_OP_deref_size operation, however, the size
+ // in bytes of the data retrieved from the dereferenced address is
// specified by the single operand. This operand is a 1-byte unsigned
// integral constant whose value may not be larger than the size of an
- // address on the target machine. The data retrieved is zero extended
- // to the size of an address on the target machine before being pushed
- // on the expression stack.
+ // address on the target machine. The data retrieved is zero extended to
+ // the size of an address on the target machine before being pushed on the
+ // expression stack.
//----------------------------------------------------------------------
case DW_OP_deref_size: {
if (stack.empty()) {
@@ -1525,8 +1550,7 @@ bool DWARFExpression::Evaluate(
// I can't decide whether the size operand should apply to the bytes in
// their
// lldb-host endianness or the target endianness.. I doubt this'll ever
- // come up
- // but I'll opt for assuming big endian regardless.
+ // come up but I'll opt for assuming big endian regardless.
switch (size) {
case 1:
ptr = ptr & 0xff;
@@ -1622,18 +1646,17 @@ bool DWARFExpression::Evaluate(
// OPERANDS: 1
// 1 - uint8_t that specifies the size of the data to dereference.
// DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at
- // the top of the stack is treated as an address. The second stack
- // entry is treated as an "address space identifier" for those
- // architectures that support multiple address spaces. The top two
- // stack elements are popped, a data item is retrieved through an
- // implementation-defined address calculation and pushed as the new
- // stack top. In the DW_OP_xderef_size operation, however, the size in
- // bytes of the data retrieved from the dereferenced address is
- // specified by the single operand. This operand is a 1-byte unsigned
- // integral constant whose value may not be larger than the size of an
- // address on the target machine. The data retrieved is zero extended
- // to the size of an address on the target machine before being pushed
- // on the expression stack.
+ // the top of the stack is treated as an address. The second stack entry is
+ // treated as an "address space identifier" for those architectures that
+ // support multiple address spaces. The top two stack elements are popped,
+ // a data item is retrieved through an implementation-defined address
+ // calculation and pushed as the new stack top. In the DW_OP_xderef_size
+ // operation, however, the size in bytes of the data retrieved from the
+ // dereferenced address is specified by the single operand. This operand is
+ // a 1-byte unsigned integral constant whose value may not be larger than
+ // the size of an address on the target machine. The data retrieved is zero
+ // extended to the size of an address on the target machine before being
+ // pushed on the expression stack.
//----------------------------------------------------------------------
case DW_OP_xderef_size:
if (error_ptr)
@@ -1643,13 +1666,13 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_xderef
// OPERANDS: none
// DESCRIPTION: Provides an extended dereference mechanism. The entry at
- // the top of the stack is treated as an address. The second stack entry
- // is treated as an "address space identifier" for those architectures
- // that support multiple address spaces. The top two stack elements are
- // popped, a data item is retrieved through an implementation-defined
- // address calculation and pushed as the new stack top. The size of the
- // data retrieved from the dereferenced address is the size of an address
- // on the target machine.
+ // the top of the stack is treated as an address. The second stack entry is
+ // treated as an "address space identifier" for those architectures that
+ // support multiple address spaces. The top two stack elements are popped,
+ // a data item is retrieved through an implementation-defined address
+ // calculation and pushed as the new stack top. The size of the data
+ // retrieved from the dereferenced address is the size of an address on the
+ // target machine.
//----------------------------------------------------------------------
case DW_OP_xderef:
if (error_ptr)
@@ -1661,16 +1684,13 @@ bool DWARFExpression::Evaluate(
//
// Opcode Operand 1
// --------------- ----------------------------------------------------
- // DW_OP_const1u 1-byte unsigned integer constant
- // DW_OP_const1s 1-byte signed integer constant
- // DW_OP_const2u 2-byte unsigned integer constant
- // DW_OP_const2s 2-byte signed integer constant
- // DW_OP_const4u 4-byte unsigned integer constant
- // DW_OP_const4s 4-byte signed integer constant
- // DW_OP_const8u 8-byte unsigned integer constant
- // DW_OP_const8s 8-byte signed integer constant
- // DW_OP_constu unsigned LEB128 integer constant
- // DW_OP_consts signed LEB128 integer constant
+ // DW_OP_const1u 1-byte unsigned integer constant DW_OP_const1s
+ // 1-byte signed integer constant DW_OP_const2u 2-byte unsigned integer
+ // constant DW_OP_const2s 2-byte signed integer constant DW_OP_const4u
+ // 4-byte unsigned integer constant DW_OP_const4s 4-byte signed integer
+ // constant DW_OP_const8u 8-byte unsigned integer constant DW_OP_const8s
+ // 8-byte signed integer constant DW_OP_constu unsigned LEB128 integer
+ // constant DW_OP_consts signed LEB128 integer constant
//----------------------------------------------------------------------
case DW_OP_const1u:
stack.push_back(Scalar((uint8_t)opcodes.GetU8(&offset)));
@@ -1789,9 +1809,9 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_rot
// OPERANDS: none
// DESCRIPTION: Rotates the first three stack entries. The entry at
- // the top of the stack becomes the third stack entry, the second
- // entry becomes the top of the stack, and the third entry becomes
- // the second entry.
+ // the top of the stack becomes the third stack entry, the second entry
+ // becomes the top of the stack, and the third entry becomes the second
+ // entry.
//----------------------------------------------------------------------
case DW_OP_rot:
if (stack.size() < 3) {
@@ -1853,8 +1873,8 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_div
// OPERANDS: none
// DESCRIPTION: pops the top two stack values, divides the former second
- // entry by the former top of the stack using signed division, and
- // pushes the result.
+ // entry by the former top of the stack using signed division, and pushes
+ // the result.
//----------------------------------------------------------------------
case DW_OP_div:
if (stack.size() < 2) {
@@ -1905,8 +1925,8 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_mod
// OPERANDS: none
// DESCRIPTION: pops the top two stack values and pushes the result of
- // the calculation: former second stack entry modulo the former top of
- // the stack.
+ // the calculation: former second stack entry modulo the former top of the
+ // stack.
//----------------------------------------------------------------------
case DW_OP_mod:
if (stack.size() < 2) {
@@ -2050,8 +2070,8 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_shl
// OPERANDS: none
// DESCRIPTION: pops the top two stack entries, shifts the former
- // second entry left by the number of bits specified by the former top
- // of the stack, and pushes the result.
+ // second entry left by the number of bits specified by the former top of
+ // the stack, and pushes the result.
//----------------------------------------------------------------------
case DW_OP_shl:
if (stack.size() < 2) {
@@ -2096,8 +2116,8 @@ bool DWARFExpression::Evaluate(
// OPERANDS: none
// DESCRIPTION: pops the top two stack entries, shifts the former second
// entry right arithmetically (divide the magnitude by 2, keep the same
- // sign for the result) by the number of bits specified by the former
- // top of the stack, and pushes the result.
+ // sign for the result) by the number of bits specified by the former top
+ // of the stack, and pushes the result.
//----------------------------------------------------------------------
case DW_OP_shra:
if (stack.size() < 2) {
@@ -2136,8 +2156,8 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_skip
// OPERANDS: int16_t
// DESCRIPTION: An unconditional branch. Its single operand is a 2-byte
- // signed integer constant. The 2-byte constant is the number of bytes
- // of the DWARF expression to skip forward or backward from the current
+ // signed integer constant. The 2-byte constant is the number of bytes of
+ // the DWARF expression to skip forward or backward from the current
// operation, beginning after the 2-byte constant.
//----------------------------------------------------------------------
case DW_OP_skip: {
@@ -2156,11 +2176,10 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_bra
// OPERANDS: int16_t
// DESCRIPTION: A conditional branch. Its single operand is a 2-byte
- // signed integer constant. This operation pops the top of stack. If
- // the value popped is not the constant 0, the 2-byte constant operand
- // is the number of bytes of the DWARF expression to skip forward or
- // backward from the current operation, beginning after the 2-byte
- // constant.
+ // signed integer constant. This operation pops the top of stack. If the
+ // value popped is not the constant 0, the 2-byte constant operand is the
+ // number of bytes of the DWARF expression to skip forward or backward from
+ // the current operation, beginning after the 2-byte constant.
//----------------------------------------------------------------------
case DW_OP_bra:
if (stack.empty()) {
@@ -2537,15 +2556,15 @@ bool DWARFExpression::Evaluate(
// OPERANDS: 1
// ULEB128: byte size of the piece
// DESCRIPTION: The operand describes the size in bytes of the piece of
- // the object referenced by the DWARF expression whose result is at the
- // top of the stack. If the piece is located in a register, but does not
- // occupy the entire register, the placement of the piece within that
- // register is defined by the ABI.
+ // the object referenced by the DWARF expression whose result is at the top
+ // of the stack. If the piece is located in a register, but does not occupy
+ // the entire register, the placement of the piece within that register is
+ // defined by the ABI.
//
- // Many compilers store a single variable in sets of registers, or store
- // a variable partially in memory and partially in registers.
- // DW_OP_piece provides a way of describing how large a part of a
- // variable a particular DWARF expression refers to.
+ // Many compilers store a single variable in sets of registers, or store a
+ // variable partially in memory and partially in registers. DW_OP_piece
+ // provides a way of describing how large a part of a variable a particular
+ // DWARF expression refers to.
//----------------------------------------------------------------------
case DW_OP_piece: {
const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
@@ -2555,8 +2574,8 @@ bool DWARFExpression::Evaluate(
if (stack.empty()) {
// In a multi-piece expression, this means that the current piece is
- // not available.
- // Fill with zeros for now by resizing the data and appending it
+ // not available. Fill with zeros for now by resizing the data and
+ // appending it
curr_piece.ResizeData(piece_byte_size);
::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
pieces.AppendDataToHostBuffer(curr_piece);
@@ -2646,9 +2665,9 @@ bool DWARFExpression::Evaluate(
// Check if this is the first piece?
if (op_piece_offset == 0) {
- // This is the first piece, we should push it back onto the stack so
- // subsequent
- // pieces will be able to access this piece and add to it
+ // This is the first piece, we should push it back onto the stack
+ // so subsequent pieces will be able to access this piece and add
+ // to it
if (pieces.AppendDataToHostBuffer(curr_piece) == 0) {
if (error_ptr)
error_ptr->SetErrorString("failed to append piece data");
@@ -2706,7 +2725,7 @@ bool DWARFExpression::Evaluate(
if (error_ptr) {
error_ptr->SetErrorStringWithFormat(
"unable to extract DW_OP_bit_piece(bit_size = %" PRIu64
- ", bit_offset = %" PRIu64 ") from an addresss value.",
+ ", bit_offset = %" PRIu64 ") from an address value.",
piece_bit_size, piece_bit_offset);
}
return false;
@@ -2727,11 +2746,11 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_push_object_address
// OPERANDS: none
// DESCRIPTION: Pushes the address of the object currently being
- // evaluated as part of evaluation of a user presented expression.
- // This object may correspond to an independent variable described by
- // its own DIE or it may be a component of an array, structure, or class
- // whose address has been dynamically determined by an earlier step
- // during user expression evaluation.
+ // evaluated as part of evaluation of a user presented expression. This
+ // object may correspond to an independent variable described by its own
+ // DIE or it may be a component of an array, structure, or class whose
+ // address has been dynamically determined by an earlier step during user
+ // expression evaluation.
//----------------------------------------------------------------------
case DW_OP_push_object_address:
if (object_address_ptr)
@@ -2749,21 +2768,20 @@ bool DWARFExpression::Evaluate(
// OPERANDS:
// uint16_t compile unit relative offset of a DIE
// DESCRIPTION: Performs subroutine calls during evaluation
- // of a DWARF expression. The operand is the 2-byte unsigned offset
- // of a debugging information entry in the current compilation unit.
+ // of a DWARF expression. The operand is the 2-byte unsigned offset of a
+ // debugging information entry in the current compilation unit.
//
// Operand interpretation is exactly like that for DW_FORM_ref2.
//
- // This operation transfers control of DWARF expression evaluation
- // to the DW_AT_location attribute of the referenced DIE. If there is
- // no such attribute, then there is no effect. Execution of the DWARF
- // expression of a DW_AT_location attribute may add to and/or remove from
- // values on the stack. Execution returns to the point following the call
- // when the end of the attribute is reached. Values on the stack at the
- // time of the call may be used as parameters by the called expression
- // and values left on the stack by the called expression may be used as
- // return values by prior agreement between the calling and called
- // expressions.
+ // This operation transfers control of DWARF expression evaluation to the
+ // DW_AT_location attribute of the referenced DIE. If there is no such
+ // attribute, then there is no effect. Execution of the DWARF expression of
+ // a DW_AT_location attribute may add to and/or remove from values on the
+ // stack. Execution returns to the point following the call when the end of
+ // the attribute is reached. Values on the stack at the time of the call
+ // may be used as parameters by the called expression and values left on
+ // the stack by the called expression may be used as return values by prior
+ // agreement between the calling and called expressions.
//----------------------------------------------------------------------
case DW_OP_call2:
if (error_ptr)
@@ -2774,22 +2792,21 @@ bool DWARFExpression::Evaluate(
// OPERANDS: 1
// uint32_t compile unit relative offset of a DIE
// DESCRIPTION: Performs a subroutine call during evaluation of a DWARF
- // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset
- // of a debugging information entry in the current compilation unit.
+ // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset of
+ // a debugging information entry in the current compilation unit.
//
// Operand interpretation DW_OP_call4 is exactly like that for
// DW_FORM_ref4.
//
- // This operation transfers control of DWARF expression evaluation
- // to the DW_AT_location attribute of the referenced DIE. If there is
- // no such attribute, then there is no effect. Execution of the DWARF
- // expression of a DW_AT_location attribute may add to and/or remove from
- // values on the stack. Execution returns to the point following the call
- // when the end of the attribute is reached. Values on the stack at the
- // time of the call may be used as parameters by the called expression
- // and values left on the stack by the called expression may be used as
- // return values by prior agreement between the calling and called
- // expressions.
+ // This operation transfers control of DWARF expression evaluation to the
+ // DW_AT_location attribute of the referenced DIE. If there is no such
+ // attribute, then there is no effect. Execution of the DWARF expression of
+ // a DW_AT_location attribute may add to and/or remove from values on the
+ // stack. Execution returns to the point following the call when the end of
+ // the attribute is reached. Values on the stack at the time of the call
+ // may be used as parameters by the called expression and values left on
+ // the stack by the called expression may be used as return values by prior
+ // agreement between the calling and called expressions.
//----------------------------------------------------------------------
case DW_OP_call4:
if (error_ptr)
@@ -2800,9 +2817,8 @@ bool DWARFExpression::Evaluate(
// OPCODE: DW_OP_stack_value
// OPERANDS: None
// DESCRIPTION: Specifies that the object does not exist in memory but
- // rather is a constant value. The value from the top of the stack is
- // the value to be used. This is the actual object value and not the
- // location.
+ // rather is a constant value. The value from the top of the stack is the
+ // value to be used. This is the actual object value and not the location.
//----------------------------------------------------------------------
case DW_OP_stack_value:
stack.back().SetValueType(Value::eValueTypeScalar);
@@ -2841,8 +2857,8 @@ bool DWARFExpression::Evaluate(
// opcode, DW_OP_GNU_push_tls_address)
// OPERANDS: none
// DESCRIPTION: Pops a TLS offset from the stack, converts it to
- // an address in the current thread's thread-local storage block,
- // and pushes it on the stack.
+ // an address in the current thread's thread-local storage block, and
+ // pushes it on the stack.
//----------------------------------------------------------------------
case DW_OP_form_tls_address:
case DW_OP_GNU_push_tls_address: {
@@ -2893,8 +2909,8 @@ bool DWARFExpression::Evaluate(
// OPERANDS: 1
// ULEB128: index to the .debug_addr section
// DESCRIPTION: Pushes an address to the stack from the .debug_addr
- // section with the base address specified by the DW_AT_addr_base
- // attribute and the 0 based index is the ULEB128 encoded index.
+ // section with the base address specified by the DW_AT_addr_base attribute
+ // and the 0 based index is the ULEB128 encoded index.
//----------------------------------------------------------------------
case DW_OP_GNU_addr_index: {
if (!dwarf_cu) {
@@ -2984,7 +3000,7 @@ bool DWARFExpression::Evaluate(
return true; // Return true on success
}
-size_t DWARFExpression::LocationListSize(const DWARFCompileUnit *dwarf_cu,
+size_t DWARFExpression::LocationListSize(const DWARFUnit *dwarf_cu,
const DataExtractor &debug_loc_data,
lldb::offset_t offset) {
const lldb::offset_t debug_loc_offset = offset;
@@ -3008,7 +3024,7 @@ size_t DWARFExpression::LocationListSize(const DWARFCompileUnit *dwarf_cu,
}
bool DWARFExpression::AddressRangeForLocationListEntry(
- const DWARFCompileUnit *dwarf_cu, const DataExtractor &debug_loc_data,
+ const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data,
lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) {
if (!debug_loc_data.ValidOffset(*offset_ptr))
return false;
@@ -3242,11 +3258,11 @@ bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data,
}
void DWARFExpression::PrintDWARFLocationList(
- Stream &s, const DWARFCompileUnit *cu, const DataExtractor &debug_loc_data,
+ Stream &s, const DWARFUnit *cu, const DataExtractor &debug_loc_data,
lldb::offset_t offset) {
uint64_t start_addr, end_addr;
- uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
- s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
+ uint32_t addr_size = DWARFUnit::GetAddressByteSize(cu);
+ s.SetAddressByteSize(DWARFUnit::GetAddressByteSize(cu));
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
while (debug_loc_data.ValidOffset(offset)) {
start_addr = debug_loc_data.GetMaxU64(&offset, addr_size);
diff --git a/contrib/llvm/tools/lldb/source/Expression/DiagnosticManager.cpp b/contrib/llvm/tools/lldb/source/Expression/DiagnosticManager.cpp
index ae20feb910dd..a98d30339b4a 100644
--- a/contrib/llvm/tools/lldb/source/Expression/DiagnosticManager.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/DiagnosticManager.cpp
@@ -22,9 +22,8 @@ void DiagnosticManager::Dump(Log *log) {
std::string str = GetString();
- // GetString() puts a separator after each diagnostic.
- // We want to remove the last '\n' because log->PutCString will add one for
- // us.
+ // GetString() puts a separator after each diagnostic. We want to remove the
+ // last '\n' because log->PutCString will add one for us.
if (str.size() && str.back() == '\n') {
str.pop_back();
diff --git a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp
index d60a12888065..abbb332fac48 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp
@@ -93,15 +93,15 @@ public:
m_state = CURRENT_FILE_POPPED;
}
- // An entry is valid if it occurs before the current line in
- // the current file.
+ // An entry is valid if it occurs before the current line in the current
+ // file.
bool IsValidEntry(uint32_t line) {
switch (m_state) {
case CURRENT_FILE_NOT_YET_PUSHED:
return true;
case CURRENT_FILE_PUSHED:
- // If we are in file included in the current file,
- // the entry should be added.
+ // If we are in file included in the current file, the entry should be
+ // added.
if (m_file_stack.back() != m_current_file)
return true;
diff --git a/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp b/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp
index a97180029a84..bce9a87bfb47 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp
@@ -9,6 +9,7 @@
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
using namespace lldb_private;
@@ -69,8 +70,8 @@ void PersistentExpressionState::RegisterExecutionUnit(
execution_unit_sp->GetJittedGlobalVariables()) {
if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS) {
// Demangle the name before inserting it, so that lookups by the ConstStr
- // of the demangled name
- // will find the mangled one (needed for looking up metadata pointers.)
+ // of the demangled name will find the mangled one (needed for looking up
+ // metadata pointers.)
Mangled mangler(global_var.m_name);
mangler.GetDemangledName(lldb::eLanguageTypeUnknown);
m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr;
@@ -80,3 +81,13 @@ void PersistentExpressionState::RegisterExecutionUnit(
}
}
}
+
+ConstString PersistentExpressionState::GetNextPersistentVariableName(
+ Target &target, llvm::StringRef Prefix) {
+ llvm::SmallString<64> name;
+ {
+ llvm::raw_svector_ostream os(name);
+ os << Prefix << target.GetNextPersistentVariableIndex();
+ }
+ return ConstString(name);
+}
diff --git a/contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp b/contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp
index 6f60f8bf9c13..9742ed0b270e 100644
--- a/contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp
@@ -48,7 +48,8 @@ FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope,
m_function_return_type(return_type),
m_wrapper_function_name("__lldb_caller_function"),
m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(),
- m_arg_values(arg_value_list), m_compiled(false), m_JITted(false) {
+ m_struct_valid(false), m_arg_values(arg_value_list), m_compiled(false),
+ m_JITted(false) {
m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
// Can't make a FunctionCaller without a process.
assert(m_jit_process_wp.lock());
@@ -90,8 +91,12 @@ bool FunctionCaller::WriteFunctionWrapper(
m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
can_interpret, eExecutionPolicyAlways));
- if (!jit_error.Success())
+ if (!jit_error.Success()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "Error in PrepareForExecution: %s.",
+ jit_error.AsCString());
return false;
+ }
if (m_parser->GetGenerateDebugInfo()) {
lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
@@ -318,9 +323,9 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction(
DiagnosticManager &diagnostic_manager, Value &results) {
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
- // FunctionCaller::ExecuteFunction execution is always just to get the result.
- // Do make sure we ignore
- // breakpoints, unwind on error, and don't try to debug it.
+ // FunctionCaller::ExecuteFunction execution is always just to get the
+ // result. Do make sure we ignore breakpoints, unwind on error, and don't try
+ // to debug it.
EvaluateExpressionOptions real_options = options;
real_options.SetDebug(false);
real_options.SetUnwindOnError(true);
@@ -355,9 +360,8 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction(
return lldb::eExpressionSetupError;
// We need to make sure we record the fact that we are running an expression
- // here
- // otherwise this fact will fail to be recorded when fetching an Objective-C
- // object description
+ // here otherwise this fact will fail to be recorded when fetching an
+ // Objective-C object description
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp
index 0c8cba2050c0..e0a7dca4113d 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp
@@ -109,17 +109,17 @@ static std::string PrintValue(llvm::Value *V, bool truncate = false) {
//----------------------------------------------------------------------
/// @class Instrumenter IRDynamicChecks.cpp
-/// @brief Finds and instruments individual LLVM IR instructions
+/// Finds and instruments individual LLVM IR instructions
///
-/// When instrumenting LLVM IR, it is frequently desirable to first search
-/// for instructions, and then later modify them. This way iterators
-/// remain intact, and multiple passes can look at the same code base without
+/// When instrumenting LLVM IR, it is frequently desirable to first search for
+/// instructions, and then later modify them. This way iterators remain
+/// intact, and multiple passes can look at the same code base without
/// treading on each other's toes.
///
/// The Instrumenter class implements this functionality. A client first
-/// calls Inspect on a function, which populates a list of instructions to
-/// be instrumented. Then, later, when all passes' Inspect functions have
-/// been called, the client calls Instrument, which adds the desired
+/// calls Inspect on a function, which populates a list of instructions to be
+/// instrumented. Then, later, when all passes' Inspect functions have been
+/// called, the client calls Instrument, which adds the desired
/// instrumentation.
///
/// A subclass of Instrumenter must override InstrumentInstruction, which
@@ -200,8 +200,8 @@ protected:
}
//------------------------------------------------------------------
- /// Determine whether a single instruction is interesting to
- /// instrument, and, if so, call RegisterInstruction
+ /// Determine whether a single instruction is interesting to instrument,
+ /// and, if so, call RegisterInstruction
///
/// @param[in] i
/// The instruction to be inspected.
@@ -250,8 +250,8 @@ protected:
}
//------------------------------------------------------------------
- /// Build a function pointer for a function with signature
- /// void (*)(uint8_t*) with a given address
+ /// Build a function pointer for a function with signature void
+ /// (*)(uint8_t*) with a given address
///
/// @param[in] start_address
/// The address of the function.
@@ -275,8 +275,8 @@ protected:
}
//------------------------------------------------------------------
- /// Build a function pointer for a function with signature
- /// void (*)(uint8_t*, uint8_t*) with a given address
+ /// Build a function pointer for a function with signature void
+ /// (*)(uint8_t*, uint8_t*) with a given address
///
/// @param[in] start_address
/// The address of the function.
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp b/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
index be53f37e0bcc..e34a4c7fac52 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
@@ -33,6 +33,7 @@
#include "lldb/Utility/Log.h"
#include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "lldb/../../source/Plugins/ObjectFile/JIT/ObjectFileJIT.h"
using namespace lldb_private;
@@ -362,13 +363,10 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
ReportAllocations(*m_execution_engine_ap);
// We have to do this after calling ReportAllocations because for the MCJIT,
- // getGlobalValueAddress
- // will cause the JIT to perform all relocations. That can only be done once,
- // and has to happen
- // after we do the remapping from local -> remote.
- // That means we don't know the local address of the Variables, but we don't
- // need that for anything,
- // so that's okay.
+ // getGlobalValueAddress will cause the JIT to perform all relocations. That
+ // can only be done once, and has to happen after we do the remapping from
+ // local -> remote. That means we don't know the local address of the
+ // Variables, but we don't need that for anything, so that's okay.
std::function<void(llvm::GlobalValue &)> RegisterOneValue = [this](
llvm::GlobalValue &val) {
@@ -379,8 +377,8 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
// This is a really unfortunae API that sometimes returns local addresses
- // and sometimes returns remote addresses, based on whether
- // the variable was relocated during ReportAllocations or not.
+ // and sometimes returns remote addresses, based on whether the variable
+ // was relocated during ReportAllocations or not.
if (remote_addr == LLDB_INVALID_ADDRESS) {
remote_addr = var_ptr_addr;
@@ -584,33 +582,9 @@ lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
default:
break;
}
- } else if (name.startswith("__apple_") || name.startswith(".apple_")) {
-#if 0
- const uint32_t name_idx = name[0] == '_' ? 8 : 7;
- llvm::StringRef apple_name(name.substr(name_idx));
- switch (apple_name[0])
- {
- case 'n':
- if (apple_name.equals("names"))
- sect_type = lldb::eSectionTypeDWARFAppleNames;
- else if (apple_name.equals("namespac") || apple_name.equals("namespaces"))
- sect_type = lldb::eSectionTypeDWARFAppleNamespaces;
- break;
- case 't':
- if (apple_name.equals("types"))
- sect_type = lldb::eSectionTypeDWARFAppleTypes;
- break;
- case 'o':
- if (apple_name.equals("objc"))
- sect_type = lldb::eSectionTypeDWARFAppleObjC;
- break;
- default:
- break;
- }
-#else
+ } else if (name.startswith("__apple_") || name.startswith(".apple_"))
sect_type = lldb::eSectionTypeInvalid;
-#endif
- } else if (name.equals("__objc_imageinfo"))
+ else if (name.equals("__objc_imageinfo"))
sect_type = lldb::eSectionTypeOther;
}
return sect_type;
@@ -906,8 +880,8 @@ lldb::addr_t IRExecutionUnit::FindInSymbols(
if (get_external_load_address(load_address, sc_list, sc)) {
return load_address;
}
- // if there are any searches we try after this, add an sc_list.Clear() in an
- // "else" clause here
+ // if there are any searches we try after this, add an sc_list.Clear() in
+ // an "else" clause here
if (best_internal_load_address != LLDB_INVALID_ADDRESS) {
return best_internal_load_address;
@@ -1124,6 +1098,7 @@ bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp,
case lldb::eSectionTypeDWARFAppleTypes:
case lldb::eSectionTypeDWARFAppleNamespaces:
case lldb::eSectionTypeDWARFAppleObjC:
+ case lldb::eSectionTypeDWARFGNUDebugAltLink:
error.Clear();
break;
default:
@@ -1251,15 +1226,18 @@ bool IRExecutionUnit::GetArchitecture(lldb_private::ArchSpec &arch) {
lldb::ModuleSP IRExecutionUnit::GetJITModule() {
ExecutionContext exe_ctx(GetBestExecutionContextScope());
Target *target = exe_ctx.GetTargetPtr();
- if (target) {
- lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule(
- std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(
- shared_from_this()));
- if (jit_module_sp) {
- bool changed = false;
- jit_module_sp->SetLoadAddress(*target, 0, true, changed);
- }
- return jit_module_sp;
- }
- return lldb::ModuleSP();
+ if (!target)
+ return nullptr;
+
+ auto Delegate = std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(
+ shared_from_this());
+
+ lldb::ModuleSP jit_module_sp =
+ lldb_private::Module::CreateModuleFromObjectFile<ObjectFileJIT>(Delegate);
+ if (!jit_module_sp)
+ return nullptr;
+
+ bool changed = false;
+ jit_module_sp->SetLoadAddress(*target, 0, true, changed);
+ return jit_module_sp;
}
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp b/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp
index a809bff20039..abf86b739f07 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp
@@ -154,16 +154,10 @@ public:
switch (type_size) {
case 1:
- scalar = (uint8_t)u64value;
- break;
case 2:
- scalar = (uint16_t)u64value;
- break;
case 4:
- scalar = (uint32_t)u64value;
- break;
case 8:
- scalar = (uint64_t)u64value;
+ scalar = llvm::APInt(type_size*8, u64value);
break;
default:
return false;
@@ -1567,8 +1561,8 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
return false;
}
- // Push all function arguments to the argument list that will
- // be passed to the call function thread plan
+ // Push all function arguments to the argument list that will be passed
+ // to the call function thread plan
for (int i = 0; i < numArgs; i++) {
// Get details of this argument
llvm::Value *arg_op = call_inst->getArgOperand(i);
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp b/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp
index 817c75e66a3b..1953e80852ff 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp
@@ -49,8 +49,8 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
//
// The memory returned by this function will never be written to. The only
// point is that it should not shadow process memory if possible, so that
- // expressions processing real values from the process do not use the
- // wrong data.
+ // expressions processing real values from the process do not use the wrong
+ // data.
//
// If the process can in fact allocate memory (CanJIT() lets us know this)
// then this can be accomplished just be allocating memory in the inferior.
@@ -93,8 +93,8 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
}
// Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
- // regions, walk forward through memory until a region is found that
- // has adequate space for our allocation.
+ // regions, walk forward through memory until a region is found that has
+ // adequate space for our allocation.
if (process_is_alive) {
const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8
? 0xffffffffffffffffull
@@ -188,16 +188,12 @@ bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
// Since we only know that the returned interval begins at a location greater
- // than or
- // equal to where the given interval begins, it's possible that the given
- // interval
- // intersects either the returned interval or the previous interval. Thus, we
- // need to
- // check both. Note that we only need to check these two intervals. Since all
- // intervals
- // are disjoint it is not possible that an adjacent interval does not
- // intersect, but a
- // non-adjacent interval does intersect.
+ // than or equal to where the given interval begins, it's possible that the
+ // given interval intersects either the returned interval or the previous
+ // interval. Thus, we need to check both. Note that we only need to check
+ // these two intervals. Since all intervals are disjoint it is not possible
+ // that an adjacent interval does not intersect, but a non-adjacent interval
+ // does intersect.
if (iter != m_allocations.end()) {
if (AllocationsIntersect(addr, size, iter->second.m_process_start,
iter->second.m_size))
@@ -217,16 +213,15 @@ bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
lldb::addr_t addr2, size_t size2) {
// Given two half open intervals [A, B) and [X, Y), the only 6 permutations
- // that satisfy
- // A<B and X<Y are the following:
+ // that satisfy A<B and X<Y are the following:
// A B X Y
// A X B Y (intersects)
// A X Y B (intersects)
// X A B Y (intersects)
// X A Y B (intersects)
// X Y A B
- // The first is B <= X, and the last is Y <= A.
- // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
+ // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
+ // || Y <= A)), or (X < B && A < Y)
return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
}
@@ -306,15 +301,21 @@ lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
- size_t alignment_mask = alignment - 1;
size_t allocation_size;
- if (size == 0)
+ if (size == 0) {
+ // FIXME: Malloc(0) should either return an invalid address or assert, in
+ // order to cut down on unnecessary allocations.
allocation_size = alignment;
- else
- allocation_size = (size & alignment_mask)
- ? ((size + alignment) & (~alignment_mask))
- : size;
+ } else {
+ // Round up the requested size to an aligned value.
+ allocation_size = llvm::alignTo(size, alignment);
+
+ // The process page cache does not see the requested alignment. We can't
+ // assume its result will be any more than 1-byte aligned. To work around
+ // this, request `alignment - 1` additional bytes.
+ allocation_size += alignment - 1;
+ }
switch (policy) {
default:
diff --git a/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp
index 83acb8249ba6..fc32bfbd37a2 100644
--- a/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp
@@ -74,9 +74,8 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
lldb::UserExpressionSP &shared_ptr_to_me,
lldb::ExpressionVariableSP &result) {
// The expression log is quite verbose, and if you're just tracking the
- // execution of the
- // expression, it's quite convenient to have these logs come out with the STEP
- // log as well.
+ // execution of the expression, it's quite convenient to have these logs come
+ // out with the STEP log as well.
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
LIBLLDB_LOG_STEP));
diff --git a/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp b/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
index 39fc5c8c2539..74a965e015ce 100644
--- a/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
@@ -77,7 +77,8 @@ public:
void MakeAllocation(IRMemoryMap &map, Status &err) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- // Allocate a spare memory area to store the persistent variable's contents.
+ // Allocate a spare memory area to store the persistent variable's
+ // contents.
Status allocate_error;
const bool zero_memory = false;
@@ -230,8 +231,8 @@ public:
ExpressionVariable::EVIsProgramReference &&
!m_persistent_variable_sp->m_live_sp) {
// If the reference comes from the program, then the
- // ClangExpressionVariable's
- // live variable data hasn't been set up yet. Do this now.
+ // ClangExpressionVariable's live variable data hasn't been set up yet.
+ // Do this now.
lldb::addr_t location;
Status read_error;
@@ -256,10 +257,8 @@ public:
frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
location <= frame_top) {
// If the variable is resident in the stack frame created by the
- // expression,
- // then it cannot be relied upon to stay around. We treat it as
- // needing
- // reallocation.
+ // expression, then it cannot be relied upon to stay around. We
+ // treat it as needing reallocation.
m_persistent_variable_sp->m_flags |=
ExpressionVariable::EVIsLLDBAllocated;
m_persistent_variable_sp->m_flags |=
@@ -889,9 +888,11 @@ public:
return;
}
- ConstString name = m_delegate
- ? m_delegate->GetName()
- : persistent_state->GetNextPersistentVariableName();
+ ConstString name =
+ m_delegate
+ ? m_delegate->GetName()
+ : persistent_state->GetNextPersistentVariableName(
+ *target_sp, persistent_state->GetPersistentVariablePrefix());
lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
diff --git a/contrib/llvm/tools/lldb/source/Expression/REPL.cpp b/contrib/llvm/tools/lldb/source/Expression/REPL.cpp
index 84a6405f3268..a441e381985c 100644
--- a/contrib/llvm/tools/lldb/source/Expression/REPL.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/REPL.cpp
@@ -61,10 +61,8 @@ lldb::REPLSP REPL::Create(Status &err, lldb::LanguageType language,
std::string REPL::GetSourcePath() {
ConstString file_basename = GetSourceFileBasename();
-
- FileSpec tmpdir_file_spec;
- if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir,
- tmpdir_file_spec)) {
+ FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
+ if (tmpdir_file_spec) {
tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());
m_repl_source_path = tmpdir_file_spec.GetPath();
} else {
@@ -243,10 +241,8 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) {
// We typed "quit" or an alias to quit so we need to check if the
// command interpreter is above us and tell it that it is done as
- // well
- // so we don't drop back into the command interpreter if we have
- // already
- // quit
+ // well so we don't drop back into the command interpreter if we
+ // have already quit
lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
if (io_handler_sp)
io_handler_sp->SetIsDone(true);
@@ -444,8 +440,8 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
}
}
- // Don't complain about the REPL process going away if we are in the process
- // of quitting.
+ // Don't complain about the REPL process going away if we are in the
+ // process of quitting.
if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
error_sp->Printf(
"error: REPL process is no longer alive, exiting REPL\n");
@@ -542,11 +538,9 @@ Status REPL::RunLoop() {
debugger.PushIOHandler(io_handler_sp);
- // Check if we are in dedicated REPL mode where LLDB was start with the
- // "--repl" option
- // from the command line. Currently we know this by checking if the debugger
- // already
- // has a IOHandler thread.
+ // Check if we are in dedicated REPL mode where LLDB was start with the "--
+ // repl" option from the command line. Currently we know this by checking if
+ // the debugger already has a IOHandler thread.
if (!debugger.HasIOHandlerThread()) {
// The debugger doesn't have an existing IOHandler thread, so this must be
// dedicated REPL mode...
@@ -566,8 +560,8 @@ Status REPL::RunLoop() {
io_handler_sp->WaitForPop();
if (m_dedicated_repl_mode) {
- // If we were in dedicated REPL mode we would have started the
- // IOHandler thread, and we should kill our process
+ // If we were in dedicated REPL mode we would have started the IOHandler
+ // thread, and we should kill our process
lldb::ProcessSP process_sp = m_target.GetProcessSP();
if (process_sp && process_sp->IsAlive())
process_sp->Destroy(false);
diff --git a/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp
index 3386bc4577ae..34945fdcbfa1 100644
--- a/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp
@@ -179,9 +179,8 @@ lldb::ExpressionResults UserExpression::Evaluate(
execution_policy = eExecutionPolicyNever;
// We need to set the expression execution thread here, turns out parse can
- // call functions in the process of
- // looking up symbols, which will escape the context set by exe_ctx passed to
- // Execute.
+ // call functions in the process of looking up symbols, which will escape the
+ // context set by exe_ctx passed to Execute.
lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
thread_sp);
@@ -198,9 +197,9 @@ lldb::ExpressionResults UserExpression::Evaluate(
else
full_prefix = option_prefix;
- // If the language was not specified in the expression command,
- // set it to the language in the target's properties if
- // specified, else default to the langage for the frame.
+ // If the language was not specified in the expression command, set it to the
+ // language in the target's properties if specified, else default to the
+ // langage for the frame.
if (language == lldb::eLanguageTypeUnknown) {
if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
language = target->GetLanguage();
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp b/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
index 7b580dde656a..329c0c1f3b70 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
@@ -33,8 +33,8 @@ using namespace lldb_private::line_editor;
// doesn't explicitly initialize the curses termcap library, which it gets away
// with until TERM is set to VT100 where it stumbles over an implementation
// assumption that may not exist on other platforms. The setupterm() function
-// would normally require headers that don't work gracefully in this context, so
-// the function declaraction has been hoisted here.
+// would normally require headers that don't work gracefully in this context,
+// so the function declaraction has been hoisted here.
#if defined(__APPLE__)
extern "C" {
int setupterm(char *term, int fildes, int *errret);
@@ -43,12 +43,10 @@ int setupterm(char *term, int fildes, int *errret);
#endif
// Editline uses careful cursor management to achieve the illusion of editing a
-// multi-line block of text
-// with a single line editor. Preserving this illusion requires fairly careful
-// management of cursor
-// state. Read and understand the relationship between DisplayInput(),
-// MoveCursor(), SetCurrentLine(),
-// and SaveEditedLine() before making changes.
+// multi-line block of text with a single line editor. Preserving this
+// illusion requires fairly careful management of cursor state. Read and
+// understand the relationship between DisplayInput(), MoveCursor(),
+// SetCurrentLine(), and SaveEditedLine() before making changes.
#define ESCAPE "\x1b"
#define ANSI_FAINT ESCAPE "[2m"
@@ -70,8 +68,7 @@ int setupterm(char *term, int fildes, int *errret);
#define EditLineStringFormatSpec "%s"
// use #defines so wide version functions and structs will resolve to old
-// versions
-// for case of libedit not built with wide char support
+// versions for case of libedit not built with wide char support
#define history_w history
#define history_winit history_init
#define history_wend history_end
@@ -145,10 +142,8 @@ bool IsInputPending(FILE *file) {
// FIXME: This will be broken on Windows if we ever re-enable Editline. You
// can't use select
// on something that isn't a socket. This will have to be re-written to not
- // use a FILE*, but
- // instead use some kind of yet-to-be-created abstraction that select-like
- // functionality on
- // non-socket objects.
+ // use a FILE*, but instead use some kind of yet-to-be-created abstraction
+ // that select-like functionality on non-socket objects.
const int fd = fileno(file);
SelectHelper select_helper;
select_helper.SetTimeout(std::chrono::microseconds(0));
@@ -160,13 +155,13 @@ namespace lldb_private {
namespace line_editor {
typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP;
-// EditlineHistory objects are sometimes shared between multiple
-// Editline instances with the same program name.
+// EditlineHistory objects are sometimes shared between multiple Editline
+// instances with the same program name.
class EditlineHistory {
private:
- // Use static GetHistory() function to get a EditlineHistorySP to one of these
- // objects
+ // Use static GetHistory() function to get a EditlineHistorySP to one of
+ // these objects
EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries)
: m_history(NULL), m_event(), m_prefix(prefix), m_path() {
m_history = history_winit();
@@ -436,11 +431,10 @@ unsigned char Editline::RecallHistory(bool earlier) {
if (history_w(pHistory, &history_event, H_FIRST) == -1)
return CC_ERROR;
- // Save any edits to the "live" entry in case we return by moving forward in
- // history
- // (it would be more bash-like to save over any current entry, but libedit
- // doesn't
- // offer the ability to add entries anywhere except the end.)
+ // Save any edits to the "live" entry in case we return by moving forward
+ // in history (it would be more bash-like to save over any current entry,
+ // but libedit doesn't offer the ability to add entries anywhere except the
+ // end.)
SaveEditedLine();
m_live_history_lines = m_input_lines;
m_in_history = true;
@@ -466,8 +460,7 @@ unsigned char Editline::RecallHistory(bool earlier) {
DisplayInput();
// Prepare to edit the last line when moving to previous entry, or the first
- // line
- // when moving to next entry
+ // line when moving to next entry
SetCurrentLine(m_current_line_index =
earlier ? (int)m_input_lines.size() - 1 : 0);
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
@@ -490,8 +483,8 @@ int Editline::GetCharacter(EditLineGetCharType *c) {
}
if (m_multiline_enabled) {
- // Detect when the number of rows used for this input line changes due to an
- // edit
+ // Detect when the number of rows used for this input line changes due to
+ // an edit
int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth());
int new_line_rows = (lineLength / m_terminal_width) + 1;
if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) {
@@ -510,12 +503,10 @@ int Editline::GetCharacter(EditLineGetCharType *c) {
char ch = 0;
// This mutex is locked by our caller (GetLine). Unlock it while we read a
- // character
- // (blocking operation), so we do not hold the mutex indefinitely. This
- // gives a chance
- // for someone to interrupt us. After Read returns, immediately lock the
- // mutex again and
- // check if we were interrupted.
+ // character (blocking operation), so we do not hold the mutex
+ // indefinitely. This gives a chance for someone to interrupt us. After
+ // Read returns, immediately lock the mutex again and check if we were
+ // interrupted.
m_output_mutex.unlock();
int read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL);
m_output_mutex.lock();
@@ -614,7 +605,8 @@ unsigned char Editline::EndOrAddLineCommand(int ch) {
// Save any edits to this line
SaveEditedLine();
- // If this is the end of the last line, consider whether to add a line instead
+ // If this is the end of the last line, consider whether to add a line
+ // instead
const LineInfoW *info = el_wline(m_editline);
if (m_current_line_index == m_input_lines.size() - 1 &&
info->cursor == info->lastchar) {
@@ -653,8 +645,8 @@ unsigned char Editline::DeleteNextCharCommand(int ch) {
return CC_REFRESH;
}
- // Fail when at the end of the last line, except when ^D is pressed on
- // the line is empty, in which case it is treated as EOF
+ // Fail when at the end of the last line, except when ^D is pressed on the
+ // line is empty, in which case it is treated as EOF
if (m_current_line_index == m_input_lines.size() - 1) {
if (ch == 4 && info->buffer == info->lastchar) {
fprintf(m_output_file, "^D\n");
@@ -685,7 +677,8 @@ unsigned char Editline::DeleteNextCharCommand(int ch) {
unsigned char Editline::DeletePreviousCharCommand(int ch) {
LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
- // Just delete the previous character normally when not at the start of a line
+ // Just delete the previous character normally when not at the start of a
+ // line
if (info->cursor > info->buffer) {
el_deletestr(m_editline, 1);
return CC_REFRESH;
@@ -709,8 +702,7 @@ unsigned char Editline::DeletePreviousCharCommand(int ch) {
DisplayInput(m_current_line_index);
// Put the cursor back where libedit expects it to be before returning to
- // editing
- // by telling libedit about the newly inserted text
+ // editing by telling libedit about the newly inserted text
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
el_winsertstr(m_editline, priorLine.c_str());
return CC_REDISPLAY;
@@ -762,7 +754,8 @@ unsigned char Editline::NextLineCommand(int ch) {
EditLineStringType(indentation, EditLineCharType(' ')));
}
- // Move down past the current line using newlines to force scrolling if needed
+ // Move down past the current line using newlines to force scrolling if
+ // needed
SetCurrentLine(m_current_line_index + 1);
const LineInfoW *info = el_wline(m_editline);
int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth());
@@ -824,8 +817,7 @@ unsigned char Editline::FixIndentationCommand(int ch) {
DisplayInput(m_current_line_index);
// Reposition the cursor back on the original line and prepare to restart
- // editing
- // with a new cursor position
+ // editing with a new cursor position
SetCurrentLine(m_current_line_index);
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
m_revert_cursor_index = cursor_position + indent_correction;
@@ -945,9 +937,9 @@ void Editline::ConfigureEditor(bool multiline) {
m_multiline_enabled = multiline;
if (m_editline) {
- // Disable edit mode to stop the terminal from flushing all input
- // during the call to el_end() since we expect to have multiple editline
- // instances in this program.
+ // Disable edit mode to stop the terminal from flushing all input during
+ // the call to el_end() since we expect to have multiple editline instances
+ // in this program.
el_set(m_editline, EL_EDITMODE, 0);
el_end(m_editline);
}
@@ -973,7 +965,8 @@ void Editline::ConfigureEditor(bool multiline) {
return Editline::InstanceFor(editline)->GetCharacter(c);
}));
- // Commands used for multiline support, registered whether or not they're used
+ // Commands used for multiline support, registered whether or not they're
+ // used
el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"),
EditLineConstString("Insert a line break"),
(EditlineCommandCallbackType)([](EditLine *editline, int ch) {
@@ -1031,13 +1024,11 @@ void Editline::ConfigureEditor(bool multiline) {
return Editline::InstanceFor(editline)->FixIndentationCommand(ch);
}));
- // Register the complete callback under two names for compatibility with older
- // clients using
- // custom .editrc files (largely because libedit has a bad bug where if you
- // have a bind command
- // that tries to bind to a function name that doesn't exist, it can corrupt
- // the heap and
- // crash your process later.)
+ // Register the complete callback under two names for compatibility with
+ // older clients using custom .editrc files (largely because libedit has a
+ // bad bug where if you have a bind command that tries to bind to a function
+ // name that doesn't exist, it can corrupt the heap and crash your process
+ // later.)
EditlineCommandCallbackType complete_callback = [](EditLine *editline,
int ch) {
return Editline::InstanceFor(editline)->TabCommand(ch);
@@ -1118,8 +1109,7 @@ void Editline::ConfigureEditor(bool multiline) {
NULL);
// Escape is absorbed exiting edit mode, so re-register important
- // sequences
- // without the prefix
+ // sequences without the prefix
el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL);
el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL);
el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL);
@@ -1176,18 +1166,18 @@ Editline::Editline(const char *editline_name, FILE *input_file,
Editline::~Editline() {
if (m_editline) {
- // Disable edit mode to stop the terminal from flushing all input
- // during the call to el_end() since we expect to have multiple editline
- // instances in this program.
+ // Disable edit mode to stop the terminal from flushing all input during
+ // the call to el_end() since we expect to have multiple editline instances
+ // in this program.
el_set(m_editline, EL_EDITMODE, 0);
el_end(m_editline);
m_editline = nullptr;
}
- // EditlineHistory objects are sometimes shared between multiple
- // Editline instances with the same program name. So just release
- // our shared pointer and if we are the last owner, it will save the
- // history to the history save file automatically.
+ // EditlineHistory objects are sometimes shared between multiple Editline
+ // instances with the same program name. So just release our shared pointer
+ // and if we are the last owner, it will save the history to the history save
+ // file automatically.
m_history_sp.reset();
}
@@ -1313,8 +1303,8 @@ bool Editline::GetLines(int first_line_number, StringList &lines,
bool &interrupted) {
ConfigureEditor(true);
- // Print the initial input lines, then move the cursor back up to the start of
- // input
+ // Print the initial input lines, then move the cursor back up to the start
+ // of input
SetBaseLineNumber(first_line_number);
m_input_lines = std::vector<EditLineStringType>();
m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
diff --git a/contrib/llvm/tools/lldb/source/Host/common/File.cpp b/contrib/llvm/tools/lldb/source/Host/common/File.cpp
index 6ee4e894756b..3c3d55df2207 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/File.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/File.cpp
@@ -100,7 +100,7 @@ int File::GetDescriptor() const {
// Don't open the file descriptor if we don't need to, just get it from the
// stream if we have one.
if (StreamIsValid()) {
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
return _fileno(m_stream);
#else
return fileno(m_stream);
@@ -126,8 +126,8 @@ FILE *File::GetStream() {
const char *mode = GetStreamOpenModeFromOptions(m_options);
if (mode) {
if (!m_should_close_fd) {
-// We must duplicate the file descriptor if we don't own it because
-// when you call fdopen, the stream will own the fd
+// We must duplicate the file descriptor if we don't own it because when you
+// call fdopen, the stream will own the fd
#ifdef _WIN32
m_descriptor = ::_dup(GetDescriptor());
#else
@@ -139,8 +139,8 @@ FILE *File::GetStream() {
m_stream =
llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode);
- // If we got a stream, then we own the stream and should no
- // longer own the descriptor because fclose() will close it for us
+ // If we got a stream, then we own the stream and should no longer own
+ // the descriptor because fclose() will close it for us
if (m_stream) {
m_own_stream = true;
@@ -315,7 +315,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const {
if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
error.SetErrorToErrno();
else
- file_spec.SetFile(path, false);
+ file_spec.SetFile(path, false, FileSpec::Style::native);
} else {
error.SetErrorString("invalid file handle");
}
@@ -330,7 +330,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const {
error.SetErrorToErrno();
else {
path[len] = '\0';
- file_spec.SetFile(path, false);
+ file_spec.SetFile(path, false, FileSpec::Style::native);
}
}
#else
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Host.cpp b/contrib/llvm/tools/lldb/source/Host/common/Host.cpp
index 97581185ad9e..d2848254779e 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Host.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Host.cpp
@@ -59,7 +59,6 @@
#include "lldb/Target/FileAction.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/UnixSignals.h"
-#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
@@ -120,9 +119,8 @@ HostThread Host::StartMonitoringChildProcess(
#ifndef __linux__
//------------------------------------------------------------------
-// Scoped class that will disable thread canceling when it is
-// constructed, and exception safely restore the previous value it
-// when it goes out of scope.
+// Scoped class that will disable thread canceling when it is constructed, and
+// exception safely restore the previous value it when it goes out of scope.
//------------------------------------------------------------------
class ScopedPThreadCancelDisabler {
public:
@@ -271,8 +269,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) {
__FUNCTION__, arg);
break;
}
- // If the callback returns true, it means this process should
- // exit
+ // If the callback returns true, it means this process should exit
if (callback_return) {
if (log)
log->Printf("%s (arg = %p) thread exiting because callback "
@@ -423,7 +420,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
Dl_info info;
if (::dladdr(host_addr, &info)) {
if (info.dli_fname)
- module_filespec.SetFile(info.dli_fname, true);
+ module_filespec.SetFile(info.dli_fname, true, FileSpec::Style::native);
}
#endif
return module_filespec;
@@ -466,15 +463,17 @@ MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid,
Status Host::RunShellCommand(const char *command, const FileSpec &working_dir,
int *status_ptr, int *signo_ptr,
std::string *command_output_ptr,
- uint32_t timeout_sec, bool run_in_default_shell) {
+ const Timeout<std::micro> &timeout,
+ bool run_in_default_shell) {
return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr,
- command_output_ptr, timeout_sec, run_in_default_shell);
+ command_output_ptr, timeout, run_in_default_shell);
}
Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
int *status_ptr, int *signo_ptr,
std::string *command_output_ptr,
- uint32_t timeout_sec, bool run_in_default_shell) {
+ const Timeout<std::micro> &timeout,
+ bool run_in_default_shell) {
Status error;
ProcessLaunchInfo launch_info;
launch_info.SetArchitecture(HostInfo::GetArchitecture());
@@ -498,11 +497,10 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
llvm::SmallString<PATH_MAX> output_file_path;
if (command_output_ptr) {
- // Create a temporary file to get the stdout/stderr and redirect the
- // output of the command into this file. We will later read this file
- // if all goes well and fill the data into "command_output_ptr"
- FileSpec tmpdir_file_spec;
- if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) {
+ // Create a temporary file to get the stdout/stderr and redirect the output
+ // of the command into this file. We will later read this file if all goes
+ // well and fill the data into "command_output_ptr"
+ if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%");
llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(),
output_file_path);
@@ -539,18 +537,14 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
error.SetErrorString("failed to get process ID");
if (error.Success()) {
- bool timed_out = false;
- shell_info_sp->process_reaped.WaitForValueEqualTo(
- true, std::chrono::seconds(timeout_sec), &timed_out);
- if (timed_out) {
+ if (!shell_info_sp->process_reaped.WaitForValueEqualTo(true, timeout)) {
error.SetErrorString("timed out waiting for shell command to complete");
// Kill the process since it didn't complete within the timeout specified
Kill(pid, SIGKILL);
// Wait for the monitor callback to get the message
- timed_out = false;
shell_info_sp->process_reaped.WaitForValueEqualTo(
- true, std::chrono::seconds(1), &timed_out);
+ true, std::chrono::seconds(1));
} else {
if (status_ptr)
*status_ptr = shell_info_sp->status;
@@ -581,7 +575,8 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
return error;
}
-// The functions below implement process launching for non-Apple-based platforms
+// The functions below implement process launching for non-Apple-based
+// platforms
#if !defined(__APPLE__)
Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
std::unique_ptr<ProcessLauncher> delegate_launcher;
@@ -596,8 +591,7 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
HostProcess process = launcher.LaunchProcess(launch_info, error);
// TODO(zturner): It would be better if the entire HostProcess were returned
- // instead of writing
- // it into this structure.
+ // instead of writing it into this structure.
launch_info.SetProcessID(process.GetProcessId());
return error;
diff --git a/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp b/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
index aff887f9f1d2..4de6953a91e3 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
@@ -33,19 +33,19 @@ using namespace lldb_private;
namespace {
//----------------------------------------------------------------------
-// The HostInfoBaseFields is a work around for windows not supporting
-// static variables correctly in a thread safe way. Really each of the
-// variables in HostInfoBaseFields should live in the functions in which
-// they are used and each one should be static, but the work around is
-// in place to avoid this restriction. Ick.
+// The HostInfoBaseFields is a work around for windows not supporting static
+// variables correctly in a thread safe way. Really each of the variables in
+// HostInfoBaseFields should live in the functions in which they are used and
+// each one should be static, but the work around is in place to avoid this
+// restriction. Ick.
//----------------------------------------------------------------------
struct HostInfoBaseFields {
~HostInfoBaseFields() {
if (m_lldb_process_tmp_dir.Exists()) {
// Remove the LLDB temporary directory if we have one. Set "recurse" to
- // true to all files that were created for the LLDB process can be cleaned
- // up.
+ // true to all files that were created for the LLDB process can be
+ // cleaned up.
llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
}
}
@@ -58,7 +58,6 @@ struct HostInfoBaseFields {
FileSpec m_lldb_so_dir;
FileSpec m_lldb_support_exe_dir;
FileSpec m_lldb_headers_dir;
- FileSpec m_lldb_python_dir;
FileSpec m_lldb_clang_resource_dir;
FileSpec m_lldb_system_plugin_dir;
FileSpec m_lldb_user_plugin_dir;
@@ -111,152 +110,88 @@ llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKi
.Default(llvm::None);
}
-bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {
- file_spec.Clear();
+FileSpec HostInfoBase::GetShlibDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
+ });
+ return success ? g_fields->m_lldb_so_dir : FileSpec();
+}
-#if defined(LLDB_DISABLE_PYTHON)
- if (type == lldb::ePathTypePythonDir)
- return false;
-#endif
-
- FileSpec *result = nullptr;
- switch (type) {
- case lldb::ePathTypeLLDBShlibDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success =
- HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'",
- g_fields->m_lldb_so_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_so_dir;
- } break;
- case lldb::ePathTypeSupportExecutableDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeSupportExeDirectory(
- g_fields->m_lldb_support_exe_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf(
- "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
- g_fields->m_lldb_support_exe_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_support_exe_dir;
- } break;
- case lldb::ePathTypeHeaderDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'",
- g_fields->m_lldb_headers_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_headers_dir;
- } break;
- case lldb::ePathTypePythonDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'",
- g_fields->m_lldb_python_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_python_dir;
- } break;
- case lldb::ePathTypeClangDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success =
- HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf(
- "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'",
- g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_clang_resource_dir;
- } break;
- case lldb::ePathTypeLLDBSystemPlugins: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeSystemPluginsDirectory(
- g_fields->m_lldb_system_plugin_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf(
- "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
- g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_system_plugin_dir;
- } break;
- case lldb::ePathTypeLLDBUserPlugins: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeUserPluginsDirectory(
- g_fields->m_lldb_user_plugin_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf(
- "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
- g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_user_plugin_dir;
- } break;
- case lldb::ePathTypeLLDBTempSystemDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeProcessTempFileDirectory(
- g_fields->m_lldb_process_tmp_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf(
- "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'",
- g_fields->m_lldb_process_tmp_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_process_tmp_dir;
- } break;
- case lldb::ePathTypeGlobalLLDBTempSystemDir: {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeGlobalTempFileDirectory(
- g_fields->m_lldb_global_tmp_dir);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (log)
- log->Printf("HostInfoBase::GetLLDBPath("
- "ePathTypeGlobalLLDBTempSystemDir) => '%s'",
- g_fields->m_lldb_global_tmp_dir.GetPath().c_str());
- });
- if (success)
- result = &g_fields->m_lldb_global_tmp_dir;
- } break;
- }
+FileSpec HostInfoBase::GetSupportExeDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success =
+ HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
+ });
+ return success ? g_fields->m_lldb_support_exe_dir : FileSpec();
+}
- if (!result)
- return false;
- file_spec = *result;
- return true;
+FileSpec HostInfoBase::GetHeaderDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
+ });
+ return success ? g_fields->m_lldb_headers_dir : FileSpec();
+}
+
+FileSpec HostInfoBase::GetSystemPluginDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success = HostInfo::ComputeSystemPluginsDirectory(
+ g_fields->m_lldb_system_plugin_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "system plugin dir -> `{0}`",
+ g_fields->m_lldb_system_plugin_dir);
+ });
+ return success ? g_fields->m_lldb_system_plugin_dir : FileSpec();
+}
+
+FileSpec HostInfoBase::GetUserPluginDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success =
+ HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
+ });
+ return success ? g_fields->m_lldb_user_plugin_dir : FileSpec();
+}
+
+FileSpec HostInfoBase::GetProcessTempDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success = HostInfo::ComputeProcessTempFileDirectory(
+ g_fields->m_lldb_process_tmp_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "process temp dir -> `{0}`",
+ g_fields->m_lldb_process_tmp_dir);
+ });
+ return success ? g_fields->m_lldb_process_tmp_dir : FileSpec();
+}
+
+FileSpec HostInfoBase::GetGlobalTempDir() {
+ static llvm::once_flag g_once_flag;
+ static bool success = false;
+ llvm::call_once(g_once_flag, []() {
+ success = HostInfo::ComputeGlobalTempFileDirectory(
+ g_fields->m_lldb_global_tmp_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
+ });
+ return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
}
ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
@@ -282,14 +217,12 @@ ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
// To get paths related to LLDB we get the path to the executable that
- // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
- // on linux this is assumed to be the "lldb" main executable. If LLDB on
- // linux is actually in a shared library (liblldb.so) then this function will
- // need to be modified to "do the right thing".
+ // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
+ // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
- FileSpec lldb_file_spec(
- Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(
- reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
+ FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(
+ reinterpret_cast<void *>(reinterpret_cast<intptr_t>(
+ HostInfoBase::ComputeSharedLibraryDirectory))));
// This is necessary because when running the testsuite the shlib might be a
// symbolic link inside the Python resource dir.
@@ -302,7 +235,8 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
}
bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
- return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
+ file_spec = GetShlibDir();
+ return bool(file_spec);
}
bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
@@ -353,11 +287,9 @@ bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
return false;
}
-bool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; }
-
bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
- // TODO(zturner): Figure out how to compute the user plugins directory for all
- // platforms.
+ // TODO(zturner): Figure out how to compute the user plugins directory for
+ // all platforms.
return false;
}
@@ -375,6 +307,7 @@ void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
case llvm::Triple::aarch64:
case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
case llvm::Triple::x86_64:
arch_64.SetTriple(triple);
arch_32.SetTriple(triple.get32BitArchVariant());
diff --git a/contrib/llvm/tools/lldb/source/Host/common/MainLoop.cpp b/contrib/llvm/tools/lldb/source/Host/common/MainLoop.cpp
index 6cbb5a842562..65158c942934 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/MainLoop.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/MainLoop.cpp
@@ -26,7 +26,7 @@
#if HAVE_SYS_EVENT_H
#include <sys/event.h>
-#elif defined(LLVM_ON_WIN32)
+#elif defined(_WIN32)
#include <winsock2.h>
#elif defined(__ANDROID__)
#include <sys/syscall.h>
@@ -34,14 +34,14 @@
#include <poll.h>
#endif
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
#define POLL WSAPoll
#else
#define POLL poll
#endif
#if SIGNAL_POLLING_UNSUPPORTED
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
typedef int sigset_t;
typedef int siginfo_t;
#endif
@@ -209,8 +209,8 @@ Status MainLoop::RunImpl::Poll() {
void MainLoop::RunImpl::ProcessEvents() {
#ifdef __ANDROID__
- // Collect first all readable file descriptors into a separate vector and then
- // iterate over it to invoke callbacks. Iterating directly over
+ // Collect first all readable file descriptors into a separate vector and
+ // then iterate over it to invoke callbacks. Iterating directly over
// loop.m_read_fds is not possible because the callbacks can modify the
// container which could invalidate the iterator.
std::vector<IOObject::WaitableHandle> fds;
@@ -262,7 +262,7 @@ MainLoop::~MainLoop() {
MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
const Callback &callback,
Status &error) {
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
return nullptr;
@@ -285,8 +285,7 @@ MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
}
// We shall block the signal, then install the signal handler. The signal will
-// be unblocked in
-// the Run() function to check for signal delivery.
+// be unblocked in the Run() function to check for signal delivery.
MainLoop::SignalHandleUP
MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
#ifdef SIGNAL_POLLING_UNSUPPORTED
@@ -321,9 +320,9 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
assert(ret == 0);
#endif
- // If we're using kqueue, the signal needs to be unblocked in order to recieve
- // it. If using pselect/ppoll, we need to block it, and later unblock it as a
- // part of the system call.
+ // If we're using kqueue, the signal needs to be unblocked in order to
+ // recieve it. If using pselect/ppoll, we need to block it, and later unblock
+ // it as a part of the system call.
ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK,
&new_action.sa_mask, &old_set);
assert(ret == 0 && "pthread_sigmask failed");
diff --git a/contrib/llvm/tools/lldb/source/Host/common/MonitoringProcessLauncher.cpp b/contrib/llvm/tools/lldb/source/Host/common/MonitoringProcessLauncher.cpp
index f1fcd0b44c15..76c11454f573 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/MonitoringProcessLauncher.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/MonitoringProcessLauncher.cpp
@@ -8,11 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/MonitoringProcessLauncher.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostProcess.h"
-#include "lldb/Target/Platform.h"
-#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
@@ -32,36 +28,23 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info,
ProcessLaunchInfo resolved_info(launch_info);
error.Clear();
- char exe_path[PATH_MAX];
-
- PlatformSP host_platform_sp(Platform::GetHostPlatform());
-
- const ArchSpec &arch_spec = resolved_info.GetArchitecture();
FileSpec exe_spec(resolved_info.GetExecutableFile());
llvm::sys::fs::file_status stats;
status(exe_spec.GetPath(), stats);
- if (!is_regular_file(stats)) {
- ModuleSpec module_spec(exe_spec, arch_spec);
- lldb::ModuleSP exe_module_sp;
- error =
- host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL);
-
- if (error.Fail())
- return HostProcess();
-
- if (exe_module_sp) {
- exe_spec = exe_module_sp->GetFileSpec();
- status(exe_spec.GetPath(), stats);
- }
+ if (!exists(stats)) {
+ exe_spec.ResolvePath();
+ status(exe_spec.GetPath(), stats);
+ }
+ if (!exists(stats)) {
+ exe_spec.ResolveExecutableLocation();
+ status(exe_spec.GetPath(), stats);
}
- if (exists(stats)) {
- exe_spec.GetPath(exe_path, sizeof(exe_path));
- } else {
- resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
- error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path);
+ if (!exists(stats)) {
+ error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'",
+ exe_spec);
return HostProcess();
}
@@ -74,18 +57,9 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info,
if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- Host::MonitorChildProcessCallback callback =
- launch_info.GetMonitorProcessCallback();
-
- bool monitor_signals = false;
- if (callback) {
- // If the ProcessLaunchInfo specified a callback, use that.
- monitor_signals = launch_info.GetMonitorSignals();
- } else {
- callback = Process::SetProcessExitStatus;
- }
-
- process.StartMonitoring(callback, monitor_signals);
+ assert(launch_info.GetMonitorProcessCallback());
+ process.StartMonitoring(launch_info.GetMonitorProcessCallback(),
+ launch_info.GetMonitorSignals());
if (log)
log->PutCString("started monitoring child process.");
} else {
diff --git a/contrib/llvm/tools/lldb/source/Host/common/NativeBreakpointList.cpp b/contrib/llvm/tools/lldb/source/Host/common/NativeBreakpointList.cpp
index ce5eb94a8d1f..cfcbe0831064 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/NativeBreakpointList.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/NativeBreakpointList.cpp
@@ -104,8 +104,8 @@ Status NativeBreakpointList::DecRef(lldb::addr_t addr) {
return error;
}
- // Breakpoint has no more references. Disable it if it's not
- // already disabled.
+ // Breakpoint has no more references. Disable it if it's not already
+ // disabled.
if (log)
log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
" -- removing due to no remaining references",
diff --git a/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp b/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp
index 1fcb11b8b6f5..3e8648f81473 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -8,14 +8,11 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/Host/common/SoftwareBreakpoint.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/Process.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/lldb-enumerations.h"
@@ -139,29 +136,28 @@ NativeProcessProtocol::GetHardwareDebugSupportInfo() const {
Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size,
uint32_t watch_flags,
bool hardware) {
- // This default implementation assumes setting the watchpoint for
- // the process will require setting the watchpoint for each of the
- // threads. Furthermore, it will track watchpoints set for the
- // process and will add them to each thread that is attached to
- // via the (FIXME implement) OnThreadAttached () method.
+ // This default implementation assumes setting the watchpoint for the process
+ // will require setting the watchpoint for each of the threads. Furthermore,
+ // it will track watchpoints set for the process and will add them to each
+ // thread that is attached to via the (FIXME implement) OnThreadAttached ()
+ // method.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
// Update the thread list
UpdateThreads();
- // Keep track of the threads we successfully set the watchpoint
- // for. If one of the thread watchpoint setting operations fails,
- // back off and remove the watchpoint for all the threads that
- // were successfully set so we get back to a consistent state.
+ // Keep track of the threads we successfully set the watchpoint for. If one
+ // of the thread watchpoint setting operations fails, back off and remove the
+ // watchpoint for all the threads that were successfully set so we get back
+ // to a consistent state.
std::vector<NativeThreadProtocol *> watchpoint_established_threads;
- // Tell each thread to set a watchpoint. In the event that
- // hardware watchpoints are requested but the SetWatchpoint fails,
- // try to set a software watchpoint as a fallback. It's
- // conceivable that if there are more threads than hardware
- // watchpoints available, some of the threads will fail to set
- // hardware watchpoints while software ones may be available.
+ // Tell each thread to set a watchpoint. In the event that hardware
+ // watchpoints are requested but the SetWatchpoint fails, try to set a
+ // software watchpoint as a fallback. It's conceivable that if there are
+ // more threads than hardware watchpoints available, some of the threads will
+ // fail to set hardware watchpoints while software ones may be available.
std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
for (const auto &thread : m_threads) {
assert(thread && "thread list should not have a NULL thread!");
@@ -169,8 +165,8 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size,
Status thread_error =
thread->SetWatchpoint(addr, size, watch_flags, hardware);
if (thread_error.Fail() && hardware) {
- // Try software watchpoints since we failed on hardware watchpoint setting
- // and we may have just run out of hardware watchpoints.
+ // Try software watchpoints since we failed on hardware watchpoint
+ // setting and we may have just run out of hardware watchpoints.
thread_error = thread->SetWatchpoint(addr, size, watch_flags, false);
if (thread_error.Success())
LLDB_LOG(log,
@@ -178,13 +174,12 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size,
}
if (thread_error.Success()) {
- // Remember that we set this watchpoint successfully in
- // case we need to clear it later.
+ // Remember that we set this watchpoint successfully in case we need to
+ // clear it later.
watchpoint_established_threads.push_back(thread.get());
} else {
- // Unset the watchpoint for each thread we successfully
- // set so that we get back to a consistent state of "not
- // set" for the watchpoint.
+ // Unset the watchpoint for each thread we successfully set so that we
+ // get back to a consistent state of "not set" for the watchpoint.
for (auto unwatch_thread_sp : watchpoint_established_threads) {
Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr);
if (remove_error.Fail())
@@ -210,9 +205,9 @@ Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) {
const Status thread_error = thread->RemoveWatchpoint(addr);
if (thread_error.Fail()) {
- // Keep track of the first thread error if any threads
- // fail. We want to try to remove the watchpoint from
- // every thread, though, even if one or more have errors.
+ // Keep track of the first thread error if any threads fail. We want to
+ // try to remove the watchpoint from every thread, though, even if one or
+ // more have errors.
if (!overall_error.Fail())
overall_error = thread_error;
}
@@ -228,9 +223,9 @@ NativeProcessProtocol::GetHardwareBreakpointMap() const {
Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr,
size_t size) {
- // This default implementation assumes setting a hardware breakpoint for
- // this process will require setting same hardware breakpoint for each
- // of its existing threads. New thread will do the same once created.
+ // This default implementation assumes setting a hardware breakpoint for this
+ // process will require setting same hardware breakpoint for each of its
+ // existing threads. New thread will do the same once created.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
// Update the thread list
@@ -256,13 +251,13 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr,
Status thread_error = thread->SetHardwareBreakpoint(addr, size);
if (thread_error.Success()) {
- // Remember that we set this breakpoint successfully in
- // case we need to clear it later.
+ // Remember that we set this breakpoint successfully in case we need to
+ // clear it later.
breakpoint_established_threads.push_back(thread.get());
} else {
- // Unset the breakpoint for each thread we successfully
- // set so that we get back to a consistent state of "not
- // set" for this hardware breakpoint.
+ // Unset the breakpoint for each thread we successfully set so that we
+ // get back to a consistent state of "not set" for this hardware
+ // breakpoint.
for (auto rollback_thread_sp : breakpoint_established_threads) {
Status remove_error =
rollback_thread_sp->RemoveHardwareBreakpoint(addr);
@@ -322,8 +317,8 @@ bool NativeProcessProtocol::UnregisterNativeDelegate(
remove(m_delegates.begin(), m_delegates.end(), &native_delegate),
m_delegates.end());
- // We removed the delegate if the count of delegates shrank after
- // removing all copies of the given native_delegate from the vector.
+ // We removed the delegate if the count of delegates shrank after removing
+ // all copies of the given native_delegate from the vector.
return m_delegates.size() < initial_size;
}
@@ -412,8 +407,8 @@ void NativeProcessProtocol::SetState(lldb::StateType state,
// Give process a chance to do any stop id bump processing, such as
// clearing cached data that is invalidated each time the process runs.
- // Note if/when we support some threads running, we'll end up needing
- // to manage this per thread and per process.
+ // Note if/when we support some threads running, we'll end up needing to
+ // manage this per thread and per process.
DoStopIDBumped(m_stop_id);
}
@@ -431,26 +426,4 @@ void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) {
// Default implementation does nothing.
}
-Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid,
- ArchSpec &arch) {
- // Grab process info for the running process.
- ProcessInstanceInfo process_info;
- if (!Host::GetProcessInfo(pid, process_info))
- return Status("failed to get process info");
-
- // Resolve the executable module.
- ModuleSpecList module_specs;
- if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0,
- 0, module_specs))
- return Status("failed to get module specifications");
- lldbassert(module_specs.GetSize() == 1);
-
- arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture();
- if (arch.IsValid())
- return Status();
- else
- return Status(
- "failed to retrieve a valid architecture from the exe module");
-}
-
NativeProcessProtocol::Factory::~Factory() = default;
diff --git a/contrib/llvm/tools/lldb/source/Host/common/NativeRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Host/common/NativeRegisterContext.cpp
index 60eaebdc94cd..49b8284da970 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/NativeRegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/NativeRegisterContext.cpp
@@ -28,13 +28,12 @@ NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread)
NativeRegisterContext::~NativeRegisterContext() {}
// FIXME revisit invalidation, process stop ids, etc. Right now we don't
-// support caching in NativeRegisterContext. We can do this later by
-// utilizing NativeProcessProtocol::GetStopID () and adding a stop id to
+// support caching in NativeRegisterContext. We can do this later by utilizing
+// NativeProcessProtocol::GetStopID () and adding a stop id to
// NativeRegisterContext.
// void
-// NativeRegisterContext::InvalidateIfNeeded (bool force)
-// {
+// NativeRegisterContext::InvalidateIfNeeded (bool force) {
// ProcessSP process_sp (m_thread.GetProcess());
// bool invalidate = force;
// uint32_t process_stop_id = UINT32_MAX;
@@ -365,8 +364,8 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory(
// We now have a memory buffer that contains the part or all of the register
// value. Set the register value using this memory data.
// TODO: we might need to add a parameter to this function in case the byte
- // order of the memory data doesn't match the process. For now we are assuming
- // they are the same.
+ // order of the memory data doesn't match the process. For now we are
+ // assuming they are the same.
reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(),
error);
@@ -385,8 +384,7 @@ Status NativeRegisterContext::WriteRegisterValueToMemory(
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
- // assuming
- // they are the same.
+ // assuming they are the same.
const size_t bytes_copied = reg_value.GetAsMemoryData(
reg_info, dst, dst_len, process.GetByteOrder(), error);
diff --git a/contrib/llvm/tools/lldb/source/Host/common/NativeThreadProtocol.cpp b/contrib/llvm/tools/lldb/source/Host/common/NativeThreadProtocol.cpp
index 3f3915e006da..0c648e40eb5c 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/NativeThreadProtocol.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/NativeThreadProtocol.cpp
@@ -19,36 +19,3 @@ using namespace lldb_private;
NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol &process,
lldb::tid_t tid)
: m_process(process), m_tid(tid) {}
-
-Status NativeThreadProtocol::ReadRegister(uint32_t reg,
- RegisterValue &reg_value) {
- NativeRegisterContext &register_context = GetRegisterContext();
-
- const RegisterInfo *const reg_info =
- register_context.GetRegisterInfoAtIndex(reg);
- if (!reg_info)
- return Status("no register info for reg num %" PRIu32, reg);
-
- return register_context.ReadRegister(reg_info, reg_value);
- ;
-}
-
-Status NativeThreadProtocol::WriteRegister(uint32_t reg,
- const RegisterValue &reg_value) {
- NativeRegisterContext& register_context = GetRegisterContext();
-
- const RegisterInfo *const reg_info =
- register_context.GetRegisterInfoAtIndex(reg);
- if (!reg_info)
- return Status("no register info for reg num %" PRIu32, reg);
-
- return register_context.WriteRegister(reg_info, reg_value);
-}
-
-Status NativeThreadProtocol::SaveAllRegisters(lldb::DataBufferSP &data_sp) {
- return GetRegisterContext().WriteAllRegisterValues(data_sp);
-}
-
-Status NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) {
- return GetRegisterContext().ReadAllRegisterValues(data_sp);
-}
diff --git a/contrib/llvm/tools/lldb/source/Host/common/PseudoTerminal.cpp b/contrib/llvm/tools/lldb/source/Host/common/PseudoTerminal.cpp
index 9657cb6523dc..c9b290078e18 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/PseudoTerminal.cpp
@@ -35,10 +35,10 @@ PseudoTerminal::PseudoTerminal()
//----------------------------------------------------------------------
// Destructor
//
-// The destructor will close the master and slave file descriptors
-// if they are valid and ownership has not been released using the
-// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor()
-// member functions.
+// The destructor will close the master and slave file descriptors if they are
+// valid and ownership has not been released using the
+// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() member
+// functions.
//----------------------------------------------------------------------
PseudoTerminal::~PseudoTerminal() {
CloseMasterFileDescriptor();
@@ -66,15 +66,14 @@ void PseudoTerminal::CloseSlaveFileDescriptor() {
}
//----------------------------------------------------------------------
-// Open the first available pseudo terminal with OFLAG as the
-// permissions. The file descriptor is stored in this object and can
-// be accessed with the MasterFileDescriptor() accessor. The
-// ownership of the master file descriptor can be released using
-// the ReleaseMasterFileDescriptor() accessor. If this object has
-// a valid master files descriptor when its destructor is called, it
-// will close the master file descriptor, therefore clients must
-// call ReleaseMasterFileDescriptor() if they wish to use the master
-// file descriptor after this object is out of scope or destroyed.
+// Open the first available pseudo terminal with OFLAG as the permissions. The
+// file descriptor is stored in this object and can be accessed with the
+// MasterFileDescriptor() accessor. The ownership of the master file descriptor
+// can be released using the ReleaseMasterFileDescriptor() accessor. If this
+// object has a valid master files descriptor when its destructor is called, it
+// will close the master file descriptor, therefore clients must call
+// ReleaseMasterFileDescriptor() if they wish to use the master file descriptor
+// after this object is out of scope or destroyed.
//
// RETURNS:
// True when successful, false indicating an error occurred.
@@ -118,12 +117,12 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
}
//----------------------------------------------------------------------
-// Open the slave pseudo terminal for the current master pseudo
-// terminal. A master pseudo terminal should already be valid prior to
-// calling this function (see OpenFirstAvailableMaster()).
-// The file descriptor is stored this object's member variables and can
-// be accessed via the GetSlaveFileDescriptor(), or released using the
-// ReleaseSlaveFileDescriptor() member function.
+// Open the slave pseudo terminal for the current master pseudo terminal. A
+// master pseudo terminal should already be valid prior to calling this
+// function (see OpenFirstAvailableMaster()). The file descriptor is stored
+// this object's member variables and can be accessed via the
+// GetSlaveFileDescriptor(), or released using the ReleaseSlaveFileDescriptor()
+// member function.
//
// RETURNS:
// True when successful, false indicating an error occurred.
@@ -152,8 +151,8 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
}
//----------------------------------------------------------------------
-// Get the name of the slave pseudo terminal. A master pseudo terminal
-// should already be valid prior to calling this function (see
+// Get the name of the slave pseudo terminal. A master pseudo terminal should
+// already be valid prior to calling this function (see
// OpenFirstAvailableMaster()).
//
// RETURNS:
@@ -185,18 +184,16 @@ const char *PseudoTerminal::GetSlaveName(char *error_str,
// Fork a child process and have its stdio routed to a pseudo terminal.
//
// In the parent process when a valid pid is returned, the master file
-// descriptor can be used as a read/write access to stdio of the
-// child process.
+// descriptor can be used as a read/write access to stdio of the child process.
//
-// In the child process the stdin/stdout/stderr will already be routed
-// to the slave pseudo terminal and the master file descriptor will be
-// closed as it is no longer needed by the child process.
+// In the child process the stdin/stdout/stderr will already be routed to the
+// slave pseudo terminal and the master file descriptor will be closed as it is
+// no longer needed by the child process.
//
-// This class will close the file descriptors for the master/slave
-// when the destructor is called, so be sure to call
-// ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any
-// file descriptors are going to be used past the lifespan of this
-// object.
+// This class will close the file descriptors for the master/slave when the
+// destructor is called, so be sure to call ReleaseMasterFileDescriptor() or
+// ReleaseSlaveFileDescriptor() if any file descriptors are going to be used
+// past the lifespan of this object.
//
// RETURNS:
// in the parent process: the pid of the child, or -1 if fork fails
@@ -261,49 +258,47 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
}
//----------------------------------------------------------------------
-// The master file descriptor accessor. This object retains ownership
-// of the master file descriptor when this accessor is used. Use
-// ReleaseMasterFileDescriptor() if you wish this object to release
-// ownership of the master file descriptor.
+// The master file descriptor accessor. This object retains ownership of the
+// master file descriptor when this accessor is used. Use
+// ReleaseMasterFileDescriptor() if you wish this object to release ownership
+// of the master file descriptor.
//
-// Returns the master file descriptor, or -1 if the master file
-// descriptor is not currently valid.
+// Returns the master file descriptor, or -1 if the master file descriptor is
+// not currently valid.
//----------------------------------------------------------------------
int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; }
//----------------------------------------------------------------------
// The slave file descriptor accessor.
//
-// Returns the slave file descriptor, or -1 if the slave file
-// descriptor is not currently valid.
+// Returns the slave file descriptor, or -1 if the slave file descriptor is not
+// currently valid.
//----------------------------------------------------------------------
int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; }
//----------------------------------------------------------------------
-// Release ownership of the master pseudo terminal file descriptor
-// without closing it. The destructor for this class will close the
-// master file descriptor if the ownership isn't released using this
-// call and the master file descriptor has been opened.
+// Release ownership of the master pseudo terminal file descriptor without
+// closing it. The destructor for this class will close the master file
+// descriptor if the ownership isn't released using this call and the master
+// file descriptor has been opened.
//----------------------------------------------------------------------
int PseudoTerminal::ReleaseMasterFileDescriptor() {
- // Release ownership of the master pseudo terminal file
- // descriptor without closing it. (the destructor for this
- // class will close it otherwise!)
+ // Release ownership of the master pseudo terminal file descriptor without
+ // closing it. (the destructor for this class will close it otherwise!)
int fd = m_master_fd;
m_master_fd = invalid_fd;
return fd;
}
//----------------------------------------------------------------------
-// Release ownership of the slave pseudo terminal file descriptor
-// without closing it. The destructor for this class will close the
-// slave file descriptor if the ownership isn't released using this
-// call and the slave file descriptor has been opened.
+// Release ownership of the slave pseudo terminal file descriptor without
+// closing it. The destructor for this class will close the slave file
+// descriptor if the ownership isn't released using this call and the slave
+// file descriptor has been opened.
//----------------------------------------------------------------------
int PseudoTerminal::ReleaseSlaveFileDescriptor() {
- // Release ownership of the slave pseudo terminal file
- // descriptor without closing it (the destructor for this
- // class will close it otherwise!)
+ // Release ownership of the slave pseudo terminal file descriptor without
+ // closing it (the destructor for this class will close it otherwise!)
int fd = m_slave_fd;
m_slave_fd = invalid_fd;
return fd;
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp
index 4c23e4eb560c..875291bc115f 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp
@@ -160,18 +160,17 @@ Status Socket::TcpListen(llvm::StringRef host_and_port,
error = listen_socket->Listen(host_and_port, backlog);
if (error.Success()) {
- // We were asked to listen on port zero which means we
- // must now read the actual port that was given to us
- // as port zero is a special code for "find an open port
- // for me".
+ // We were asked to listen on port zero which means we must now read the
+ // actual port that was given to us as port zero is a special code for
+ // "find an open port for me".
if (port == 0)
port = listen_socket->GetLocalPortNumber();
- // Set the port predicate since when doing a listen://<host>:<port>
- // it often needs to accept the incoming connection which is a blocking
- // system call. Allowing access to the bound port using a predicate allows
- // us to wait for the port predicate to be set to a non-zero value from
- // another thread in an efficient manor.
+ // Set the port predicate since when doing a listen://<host>:<port> it
+ // often needs to accept the incoming connection which is a blocking system
+ // call. Allowing access to the bound port using a predicate allows us to
+ // wait for the port predicate to be set to a non-zero value from another
+ // thread in an efficient manor.
if (predicate)
predicate->SetValue(port, eBroadcastAlways);
socket = listen_socket.release();
@@ -282,8 +281,7 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
}
// If this was unsuccessful, then check if it's simply a signed 32-bit
- // integer, representing
- // a port with an empty host.
+ // integer, representing a port with an empty host.
host_str.clear();
port_str.clear();
bool ok = false;
@@ -436,8 +434,8 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr,
error.Clear();
#if defined(ANDROID_USE_ACCEPT_WORKAROUND)
// Hack:
- // This enables static linking lldb-server to an API 21 libc, but still having
- // it run on older devices. It is necessary because API 21 libc's
+ // This enables static linking lldb-server to an API 21 libc, but still
+ // having it run on older devices. It is necessary because API 21 libc's
// implementation of accept() uses the accept4 syscall(), which is not
// available in older kernels. Using an older libc would fix this issue, but
// introduce other ones, as the old libraries were quite buggy.
diff --git a/contrib/llvm/tools/lldb/source/Host/common/SoftwareBreakpoint.cpp b/contrib/llvm/tools/lldb/source/Host/common/SoftwareBreakpoint.cpp
index 14dbafd94c03..353dadf6ce6d 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/SoftwareBreakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/SoftwareBreakpoint.cpp
@@ -17,9 +17,8 @@
using namespace lldb_private;
-// -------------------------------------------------------------------
-// static members
-// -------------------------------------------------------------------
+// ------------------------------------------------------------------- static
+// members -------------------------------------------------------------------
Status SoftwareBreakpoint::CreateSoftwareBreakpoint(
NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint,
@@ -34,8 +33,7 @@ Status SoftwareBreakpoint::CreateSoftwareBreakpoint(
__FUNCTION__);
// Ask the NativeProcessProtocol subclass to fill in the correct software
- // breakpoint
- // trap for the breakpoint site.
+ // breakpoint trap for the breakpoint site.
size_t bp_opcode_size = 0;
const uint8_t *bp_opcode_bytes = NULL;
Status error = process.GetSoftwareBreakpointTrapOpcode(
@@ -98,9 +96,8 @@ Status SoftwareBreakpoint::CreateSoftwareBreakpoint(
log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS",
__FUNCTION__, addr);
- // Set the breakpoint and verified it was written properly. Now
- // create a breakpoint remover that understands how to undo this
- // breakpoint.
+ // Set the breakpoint and verified it was written properly. Now create a
+ // breakpoint remover that understands how to undo this breakpoint.
breakpoint_sp.reset(new SoftwareBreakpoint(process, addr, saved_opcode_bytes,
bp_opcode_bytes, bp_opcode_size));
return Status();
@@ -280,8 +277,8 @@ Status SoftwareBreakpoint::DoDisable() {
// Make sure the breakpoint opcode exists at this address
if (::memcmp(curr_break_op, m_trap_opcodes, m_opcode_size) == 0) {
break_op_found = true;
- // We found a valid breakpoint opcode at this address, now restore
- // the saved opcode.
+ // We found a valid breakpoint opcode at this address, now restore the
+ // saved opcode.
size_t bytes_written = 0;
error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size,
bytes_written);
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp b/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp
index 3f70fdc4bf95..d7e0c13112aa 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Symbols.h"
-#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
@@ -91,7 +91,7 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
::strncat(path, exec_fspec->GetFilename().AsCString(),
sizeof(path) - strlen(path) - 1);
- dsym_fspec.SetFile(path, false);
+ dsym_fspec.SetFile(path, false, FileSpec::Style::native);
ModuleSpecList module_specs;
ModuleSpec matched_module_spec;
@@ -111,15 +111,15 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
// Add a ".dSYM" name to each directory component of the path,
// stripping off components. e.g. we may have a binary like
- // /S/L/F/Foundation.framework/Versions/A/Foundation
- // and
+ // /S/L/F/Foundation.framework/Versions/A/Foundation and
// /S/L/F/Foundation.framework.dSYM
//
- // so we'll need to start with /S/L/F/Foundation.framework/Versions/A,
- // add the .dSYM part to the "A", and if that doesn't exist, strip off
- // the "A" and try it again with "Versions", etc., until we find a
- // dSYM bundle or we've stripped off enough path components that
- // there's no need to continue.
+ // so we'll need to start with
+ // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the
+ // "A", and if that doesn't exist, strip off the "A" and try it again
+ // with "Versions", etc., until we find a dSYM bundle or we've
+ // stripped off enough path components that there's no need to
+ // continue.
for (int i = 0; i < 4; i++) {
// Does this part of the path have a "." character - could it be a
@@ -131,7 +131,8 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
dsym_fspec = parent_dirs;
dsym_fspec.RemoveLastPathComponent();
- // If the current directory name is "Foundation.framework", see if
+ // If the current directory name is "Foundation.framework", see
+ // if
// "Foundation.framework.dSYM/Contents/Resources/DWARF/Foundation"
// exists & has the right uuid.
std::string dsym_fn = fn;
@@ -222,14 +223,18 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
Target::GetDefaultDebugFileSearchPaths());
// Add module directory.
- const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory();
+ FileSpec module_file_spec = module_spec.GetFileSpec();
+ // We keep the unresolved pathname if it fails.
+ FileSystem::ResolveSymbolicLink(module_file_spec, module_file_spec);
+
+ const ConstString &file_dir = module_file_spec.GetDirectory();
debug_file_search_paths.AppendIfUnique(
FileSpec(file_dir.AsCString("."), true));
// Add current working directory.
debug_file_search_paths.AppendIfUnique(FileSpec(".", true));
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
#if defined(__NetBSD__)
// Add /usr/libdata/debug directory.
debug_file_search_paths.AppendIfUnique(
@@ -238,7 +243,7 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
// Add /usr/lib/debug directory.
debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true));
#endif
-#endif // LLVM_ON_WIN32
+#endif // _WIN32
std::string uuid_str;
const UUID &module_uuid = module_spec.GetUUID();
@@ -246,6 +251,8 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
// Some debug files are stored in the .build-id directory like this:
// /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
uuid_str = module_uuid.GetAsString("");
+ std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),
+ ::tolower);
uuid_str.insert(2, 1, '/');
uuid_str = uuid_str + ".debug";
}
@@ -275,7 +282,7 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
FileSpec file_spec(filename, true);
if (llvm::sys::fs::equivalent(file_spec.GetPath(),
- module_spec.GetFileSpec().GetPath()))
+ module_file_spec.GetPath()))
continue;
if (file_spec.Exists()) {
@@ -287,10 +294,9 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
if (num_specs == 1) {
ModuleSpec mspec;
if (specs.GetModuleSpecAtIndex(0, mspec)) {
- // Skip the uuids check if module_uuid is invalid.
- // For example, this happens for *.dwp files since
- // at the moment llvm-dwp doesn't output build ids,
- // nor does binutils dwp.
+ // Skip the uuids check if module_uuid is invalid. For example,
+ // this happens for *.dwp files since at the moment llvm-dwp
+ // doesn't output build ids, nor does binutils dwp.
if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())
return file_spec;
}
diff --git a/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp b/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
index f896944bb1b3..1a10336f1dfc 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
@@ -26,11 +26,11 @@
#include <sys/socket.h>
#endif
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include <winsock2.h>
#endif
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
#define CLOSE_SOCKET closesocket
typedef const char *set_socket_option_arg_type;
#else
diff --git a/contrib/llvm/tools/lldb/source/Host/common/TaskPool.cpp b/contrib/llvm/tools/lldb/source/Host/common/TaskPool.cpp
index 156a07942998..c54b9a8ae56b 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/TaskPool.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/TaskPool.cpp
@@ -49,8 +49,8 @@ void TaskPool::AddTaskImpl(std::function<void()> &&task_fn) {
TaskPoolImpl::TaskPoolImpl() : m_thread_count(0) {}
unsigned GetHardwareConcurrencyHint() {
- // std::thread::hardware_concurrency may return 0
- // if the value is not well defined or not computable.
+ // std::thread::hardware_concurrency may return 0 if the value is not well
+ // defined or not computable.
static const unsigned g_hardware_concurrency =
std::max(1u, std::thread::hardware_concurrency());
return g_hardware_concurrency;
@@ -64,9 +64,8 @@ void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) {
if (m_thread_count < GetHardwareConcurrencyHint()) {
m_thread_count++;
// Note that this detach call needs to happen with the m_tasks_mutex held.
- // This prevents the thread
- // from exiting prematurely and triggering a linux libc bug
- // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951).
+ // This prevents the thread from exiting prematurely and triggering a linux
+ // libc bug (https://sourceware.org/bugzilla/show_bug.cgi?id=19951).
lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr,
this, nullptr, min_stack_size)
.Release();
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Terminal.cpp b/contrib/llvm/tools/lldb/source/Host/common/Terminal.cpp
index 022b3fa50a8f..be912fbe6155 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Terminal.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Terminal.cpp
@@ -9,6 +9,7 @@
#include "lldb/Host/Terminal.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/PosixApi.h"
#include "llvm/ADT/STLExtras.h"
@@ -107,9 +108,9 @@ void TerminalState::Clear() {
}
//----------------------------------------------------------------------
-// Save the current state of the TTY for the file descriptor "fd"
-// and if "save_process_group" is true, attempt to save the process
-// group info for the TTY.
+// Save the current state of the TTY for the file descriptor "fd" and if
+// "save_process_group" is true, attempt to save the process group info for the
+// TTY.
//----------------------------------------------------------------------
bool TerminalState::Save(int fd, bool save_process_group) {
m_tty.SetFileDescriptor(fd);
@@ -142,8 +143,8 @@ bool TerminalState::Save(int fd, bool save_process_group) {
}
//----------------------------------------------------------------------
-// Restore the state of the TTY using the cached values from a
-// previous call to Save().
+// Restore the state of the TTY using the cached values from a previous call to
+// Save().
//----------------------------------------------------------------------
bool TerminalState::Restore() const {
#ifndef LLDB_DISABLE_POSIX
@@ -173,8 +174,8 @@ bool TerminalState::Restore() const {
}
//----------------------------------------------------------------------
-// Returns true if this object has valid saved TTY state settings
-// that can be used to restore a previous state.
+// Returns true if this object has valid saved TTY state settings that can be
+// used to restore a previous state.
//----------------------------------------------------------------------
bool TerminalState::IsValid() const {
return m_tty.FileDescriptorIsValid() &&
@@ -236,21 +237,20 @@ bool TerminalStateSwitcher::Restore(uint32_t idx) const {
m_ttystates[idx].IsValid())
return true;
- // Set the state to match the index passed in and only update the
- // current state if there are no errors.
+ // Set the state to match the index passed in and only update the current
+ // state if there are no errors.
if (m_ttystates[idx].Restore()) {
m_currentState = idx;
return true;
}
- // We failed to set the state. The tty state was invalid or not
- // initialized.
+ // We failed to set the state. The tty state was invalid or not initialized.
return false;
}
//------------------------------------------------------------------
-// Save the state at index "idx" for file descriptor "fd" and
-// save the process group if requested.
+// Save the state at index "idx" for file descriptor "fd" and save the process
+// group if requested.
//
// Returns true if the restore was successful, false otherwise.
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp b/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp
index 21dacbc626ee..96bcc6a150a9 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp
@@ -69,8 +69,8 @@ Status UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
return error;
- // At this point we have setup the receive port, now we need to
- // setup the UDP send socket
+ // At this point we have setup the receive port, now we need to setup the UDP
+ // send socket
struct addrinfo hints;
struct addrinfo *service_info_list = nullptr;
diff --git a/contrib/llvm/tools/lldb/source/Host/common/XML.cpp b/contrib/llvm/tools/lldb/source/Host/common/XML.cpp
index c3169bd6e08d..7468a3d7ac65 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/XML.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/XML.cpp
@@ -151,6 +151,18 @@ llvm::StringRef XMLNode::GetAttributeValue(const char *name,
return llvm::StringRef();
}
+bool XMLNode::GetAttributeValueAsUnsigned(const char *name, uint64_t &value,
+ uint64_t fail_value, int base) const {
+#if defined(LIBXML2_DEFINED)
+ llvm::StringRef str_value = GetAttributeValue(name, "");
+#else
+ llvm::StringRef str_value;
+#endif
+ bool success = false;
+ value = StringConvert::ToUInt64(str_value.data(), fail_value, base, &success);
+ return success;
+}
+
void XMLNode::ForEachChildNode(NodeCallback const &callback) const {
#if defined(LIBXML2_DEFINED)
if (IsValid())
@@ -240,8 +252,8 @@ void XMLNode::ForEachSiblingElementWithName(
if (node->type != XML_ELEMENT_NODE)
continue;
- // If name is nullptr, we take all nodes of type "t", else
- // just the ones whose name matches
+ // If name is nullptr, we take all nodes of type "t", else just the ones
+ // whose name matches
if (name) {
if (strcmp((const char *)node->name, name) != 0)
continue; // Name mismatch, ignore this one
diff --git a/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp b/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
index 124a8a760133..87552bc2a27e 100644
--- a/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
@@ -26,12 +26,9 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Module.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
-#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
@@ -78,9 +75,11 @@ GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
size_t pathname_len = sizeof(pathname);
mib[2] = KERN_PROC_PATHNAME;
if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0)
- process_info.GetExecutableFile().SetFile(pathname, false);
+ process_info.GetExecutableFile().SetFile(pathname, false,
+ FileSpec::Style::native);
else
- process_info.GetExecutableFile().SetFile(cstr, false);
+ process_info.GetExecutableFile().SetFile(cstr, false,
+ FileSpec::Style::native);
if (!(match_info_ptr == NULL ||
NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
@@ -195,9 +194,8 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
continue;
// Every thread is a process in FreeBSD, but all the threads of a single
- // process have the same pid. Do not store the process info in the
- // result list if a process with given identifier is already registered
- // there.
+ // process have the same pid. Do not store the process info in the result
+ // list if a process with given identifier is already registered there.
bool already_registered = false;
for (uint32_t pi = 0;
!already_registered && (const int)kinfo.ki_numthreads > 1 &&
@@ -243,14 +241,7 @@ bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
return false;
}
-size_t Host::GetEnvironment(StringList &env) {
- char **host_env = environ;
- char *env_entry;
- size_t i;
- for (i = 0; (env_entry = host_env[i]) != NULL; ++i)
- env.AppendString(env_entry);
- return i;
-}
+Environment Host::GetEnvironment() { return Environment(environ); }
Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
return Status("unimplemented");
diff --git a/contrib/llvm/tools/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp b/contrib/llvm/tools/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
index 9c82fcca7563..18eae3eb7606 100644
--- a/contrib/llvm/tools/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
@@ -18,16 +18,17 @@
using namespace lldb_private;
-bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) {
+llvm::VersionTuple HostInfoFreeBSD::GetOSVersion() {
struct utsname un;
::memset(&un, 0, sizeof(utsname));
if (uname(&un) < 0)
- return false;
+ return llvm::VersionTuple();
- int status = sscanf(un.release, "%u.%u", &major, &minor);
- return status == 2;
+ unsigned major, minor;
+ if (2 == sscanf(un.release, "%u.%u", &major, &minor))
+ return llvm::VersionTuple(major, minor);
+ return llvm::VersionTuple();
}
bool HostInfoFreeBSD::GetOSBuildString(std::string &s) {
@@ -68,9 +69,9 @@ FileSpec HostInfoFreeBSD::GetProgramFileSpec() {
if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) {
char *exe_path = new char[exe_path_size];
if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec.SetFile(exe_path, false);
+ g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native);
delete[] exe_path;
}
}
return g_program_filespec;
-} \ No newline at end of file
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp b/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp
index d927f95f0675..bfd5a74ffcc2 100644
--- a/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp
@@ -25,12 +25,9 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Module.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
-#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
@@ -48,14 +45,7 @@ extern char **environ;
using namespace lldb;
using namespace lldb_private;
-size_t Host::GetEnvironment(StringList &env) {
- char **host_env = environ;
- char *env_entry;
- size_t i;
- for (i = 0; (env_entry = host_env[i]) != NULL; ++i)
- env.AppendString(env_entry);
- return i;
-}
+Environment Host::GetEnvironment() { return Environment(environ); }
static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
ProcessInstanceInfo &process_info) {
@@ -80,7 +70,8 @@ static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
if (!cstr)
return false;
- process_info.GetExecutableFile().SetFile(cstr, false);
+ process_info.GetExecutableFile().SetFile(cstr, false,
+ FileSpec::Style::native);
if (!(match_info_ptr == NULL ||
NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
@@ -202,9 +193,8 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
continue;
// Every thread is a process in NetBSD, but all the threads of a single
- // process have the same pid. Do not store the process info in the
- // result list if a process with given identifier is already registered
- // there.
+ // process have the same pid. Do not store the process info in the result
+ // list if a process with given identifier is already registered there.
if (proc_kinfo[i].p_nlwps > 1) {
bool already_registered = false;
for (size_t pi = 0; pi < process_infos.GetSize(); pi++) {
diff --git a/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
index 428183bbe2c3..dfbce310509d 100644
--- a/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
@@ -21,30 +21,26 @@
using namespace lldb_private;
-bool HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) {
+llvm::VersionTuple HostInfoNetBSD::GetOSVersion() {
struct utsname un;
::memset(&un, 0, sizeof(un));
if (::uname(&un) < 0)
- return false;
+ return llvm::VersionTuple();
/* Accept versions like 7.99.21 and 6.1_STABLE */
+ uint32_t major, minor, update;
int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major,
&minor, &update);
switch (status) {
- case 0:
- return false;
case 1:
- minor = 0;
- /* FALLTHROUGH */
+ return llvm::VersionTuple(major);
case 2:
- update = 0;
- /* FALLTHROUGH */
+ return llvm::VersionTuple(major, minor);
case 3:
- default:
- return true;
+ return llvm::VersionTuple(major, minor, update);
}
+ return llvm::VersionTuple();
}
bool HostInfoNetBSD::GetOSBuildString(std::string &s) {
@@ -89,7 +85,7 @@ FileSpec HostInfoNetBSD::GetProgramFileSpec() {
len = sizeof(path);
if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1) {
- g_program_filespec.SetFile(path, false);
+ g_program_filespec.SetFile(path, false, FileSpec::Style::native);
}
}
return g_program_filespec;
diff --git a/contrib/llvm/tools/lldb/source/Host/openbsd/Host.cpp b/contrib/llvm/tools/lldb/source/Host/openbsd/Host.cpp
index 0535256b9aa1..49e9c290a027 100644
--- a/contrib/llvm/tools/lldb/source/Host/openbsd/Host.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/openbsd/Host.cpp
@@ -22,12 +22,9 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Module.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
-#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
@@ -45,16 +42,17 @@ extern char **environ;
using namespace lldb;
using namespace lldb_private;
-size_t Host::GetEnvironment(StringList &env) {
+Environment Host::GetEnvironment() {
+ Environment env;
char *v;
char **var = environ;
for (; var != NULL && *var != NULL; ++var) {
v = strchr(*var, (int)'-');
if (v == NULL)
continue;
- env.AppendString(v);
+ env.insert(v);
}
- return env.GetSize();
+ return env;
}
static bool
@@ -74,7 +72,8 @@ GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
cstr = data.GetCStr(&offset);
if (cstr) {
- process_info.GetExecutableFile().SetFile(cstr, false);
+ process_info.GetExecutableFile().SetFile(cstr, false,
+ FileSpec::Style::native);
if (!(match_info_ptr == NULL ||
NameMatches(
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index 3797650105ce..c21bb786a896 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -189,15 +189,14 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
}
#ifndef LLDB_DISABLE_POSIX
else if ((addr = GetURLAddress(path, FD_SCHEME))) {
- // Just passing a native file descriptor within this current process
- // that is already opened (possibly from a service or other source).
+ // Just passing a native file descriptor within this current process that
+ // is already opened (possibly from a service or other source).
int fd = -1;
if (!addr->getAsInteger(0, fd)) {
- // We have what looks to be a valid file descriptor, but we
- // should make sure it is. We currently are doing this by trying to
- // get the flags from the file descriptor and making sure it
- // isn't a bad fd.
+ // We have what looks to be a valid file descriptor, but we should make
+ // sure it is. We currently are doing this by trying to get the flags
+ // from the file descriptor and making sure it isn't a bad fd.
errno = 0;
int flags = ::fcntl(fd, F_GETFL, 0);
if (flags == -1 || errno == EBADF) {
@@ -208,20 +207,18 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
m_write_sp.reset();
return eConnectionStatusError;
} else {
- // Don't take ownership of a file descriptor that gets passed
- // to us since someone else opened the file descriptor and
- // handed it to us.
+ // Don't take ownership of a file descriptor that gets passed to us
+ // since someone else opened the file descriptor and handed it to us.
// TODO: Since are using a URL to open connection we should
- // eventually parse options using the web standard where we
- // have "fd://123?opt1=value;opt2=value" and we can have an
- // option be "owns=1" or "owns=0" or something like this to
- // allow us to specify this. For now, we assume we must
- // assume we don't own it.
+ // eventually parse options using the web standard where we have
+ // "fd://123?opt1=value;opt2=value" and we can have an option be
+ // "owns=1" or "owns=0" or something like this to allow us to specify
+ // this. For now, we assume we must assume we don't own it.
std::unique_ptr<TCPSocket> tcp_socket;
tcp_socket.reset(new TCPSocket(fd, false, false));
- // Try and get a socket option from this file descriptor to
- // see if this is a socket and set m_is_socket accordingly.
+ // Try and get a socket option from this file descriptor to see if
+ // this is a socket and set m_is_socket accordingly.
int resuse;
bool is_socket =
!!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse);
@@ -320,13 +317,11 @@ ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) {
m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
static_cast<Socket &>(*m_read_sp).PreDisconnect();
- // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite
- // likely
- // because somebody is doing a blocking read on our file descriptor. If
- // that's the case,
- // then send the "q" char to the command file channel so the read will wake up
- // and the connection
- // will then know to shut down.
+ // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is
+ // quite likely because somebody is doing a blocking read on our file
+ // descriptor. If that's the case, then send the "q" char to the command
+ // file channel so the read will wake up and the connection will then know to
+ // shut down.
m_shutting_down = true;
@@ -430,11 +425,11 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len,
case EINVAL: // The pointer associated with fildes was negative.
case EIO: // An I/O error occurred while reading from the file system.
// The process group is orphaned.
- // The file is a regular file, nbyte is greater than 0,
- // the starting position is before the end-of-file, and
- // the starting position is greater than or equal to the
- // offset maximum established for the open file
- // descriptor associated with fildes.
+ // The file is a regular file, nbyte is greater than 0, the
+ // starting position is before the end-of-file, and the
+ // starting position is greater than or equal to the offset
+ // maximum established for the open file descriptor
+ // associated with fildes.
case EISDIR: // An attempt is made to read a directory.
case ENOBUFS: // An attempt to allocate a memory buffer fails.
case ENOMEM: // Insufficient memory is available.
@@ -550,15 +545,15 @@ ConnectionStatus
ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,
Status *error_ptr) {
// Don't need to take the mutex here separately since we are only called from
- // Read. If we
- // ever get used more generally we will need to lock here as well.
+ // Read. If we ever get used more generally we will need to lock here as
+ // well.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION));
LLDB_LOG(log, "this = {0}, timeout = {1}", this, timeout);
- // Make a copy of the file descriptors to make sure we don't
- // have another thread change these values out from under us
- // and cause problems in the loop below where like in FS_SET()
+ // Make a copy of the file descriptors to make sure we don't have another
+ // thread change these values out from under us and cause problems in the
+ // loop below where like in FS_SET()
const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle();
const int pipe_fd = m_pipe.GetReadFileDescriptor();
@@ -570,10 +565,9 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,
select_helper.FDSetRead(handle);
#if defined(_MSC_VER)
// select() won't accept pipes on Windows. The entire Windows codepath
- // needs to be
- // converted over to using WaitForMultipleObjects and event HANDLEs, but for
- // now at least
- // this will allow ::select() to not return an error.
+ // needs to be converted over to using WaitForMultipleObjects and event
+ // HANDLEs, but for now at least this will allow ::select() to not return
+ // an error.
const bool have_pipe_fd = false;
#else
const bool have_pipe_fd = pipe_fd >= 0;
@@ -603,11 +597,10 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,
return eConnectionStatusTimedOut;
case EAGAIN: // The kernel was (perhaps temporarily) unable to
- // allocate the requested number of file descriptors,
- // or we have non-blocking IO
+ // allocate the requested number of file descriptors, or
+ // we have non-blocking IO
case EINTR: // A signal was delivered before the time limit
- // expired and before any of the selected events
- // occurred.
+ // expired and before any of the selected events occurred.
break; // Lets keep reading to until we timeout
}
} else {
@@ -615,8 +608,8 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,
return eConnectionStatusSuccess;
if (select_helper.FDIsSetRead(pipe_fd)) {
- // There is an interrupt or exit command in the command pipe
- // Read the data from that pipe:
+ // There is an interrupt or exit command in the command pipe Read the
+ // data from that pipe:
char c;
ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1);
@@ -753,14 +746,10 @@ ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s,
return eConnectionStatusSuccess;
}
-uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) {
- uint16_t bound_port = 0;
- if (timeout_sec == UINT32_MAX)
- m_port_predicate.WaitForValueNotEqualTo(0, bound_port);
- else
- m_port_predicate.WaitForValueNotEqualTo(0, bound_port,
- std::chrono::seconds(timeout_sec));
- return bound_port;
+uint16_t
+ConnectionFileDescriptor::GetListeningPort(const Timeout<std::micro> &timeout) {
+ auto Result = m_port_predicate.WaitForValueNotEqualTo(0, timeout);
+ return Result ? *Result : 0;
}
bool ConnectionFileDescriptor::GetChildProcessesInherit() const {
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp b/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
index 3ece0677f991..60be642df608 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
@@ -16,11 +16,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-#ifdef __linux__
-#include <linux/magic.h>
-#include <sys/mount.h>
-#include <sys/statfs.h>
-#endif
#if defined(__NetBSD__)
#include <sys/statvfs.h>
#endif
@@ -52,7 +47,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
error.SetErrorToErrno();
else {
buf[count] = '\0'; // Success
- dst.SetFile(buf, false);
+ dst.SetFile(buf, false, FileSpec::Style::native);
}
return error;
}
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp
index da9e1fb366cc..62c70fa3edc1 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp
@@ -7,15 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#if !defined(LLDB_DISABLE_PYTHON)
-#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
-#endif
-
#include "lldb/Host/posix/HostInfoPosix.h"
#include "lldb/Utility/Log.h"
-#include "clang/Basic/Version.h"
-#include "clang/Config/config.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Path.h"
@@ -103,8 +97,7 @@ const char *HostInfoPosix::LookupGroupName(uint32_t gid,
}
} else {
// The threadsafe version isn't currently working for me on darwin, but the
- // non-threadsafe version
- // is, so I am calling it below.
+ // non-threadsafe version is, so I am calling it below.
group_info_ptr = ::getgrgid(gid);
if (group_info_ptr) {
group_name.assign(group_info_ptr->gr_name);
@@ -132,8 +125,8 @@ bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec,
llvm::StringRef dir) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- FileSpec lldb_file_spec;
- if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
+ FileSpec lldb_file_spec = GetShlibDir();
+ if (!lldb_file_spec)
return false;
std::string raw_path = lldb_file_spec.GetPath();
@@ -141,8 +134,8 @@ bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec,
llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);
// Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with
- // */bin as the base directory for helper exe programs. This will fail if the
- // /lib and /bin directories are rooted in entirely different trees.
+ // */bin as the base directory for helper exe programs. This will fail if
+ // the /lib and /bin directories are rooted in entirely different trees.
if (log)
log->Printf("HostInfoPosix::ComputePathRelativeToLibrary() attempting to "
"derive the %s path from this path: %s",
@@ -169,59 +162,12 @@ bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) {
return ComputePathRelativeToLibrary(file_spec, "/bin");
}
-bool HostInfoPosix::ComputeClangDirectory(FileSpec &file_spec) {
- return ComputePathRelativeToLibrary(
- file_spec, (llvm::Twine("/lib") + CLANG_LIBDIR_SUFFIX + "/clang/" +
- CLANG_VERSION_STRING)
- .str());
-}
-
bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) {
FileSpec temp_file("/opt/local/include/lldb", false);
file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
return true;
}
-bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) {
-#ifndef LLDB_DISABLE_PYTHON
- FileSpec lldb_file_spec;
- if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
- return false;
-
- char raw_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
-#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
- // Build the path by backing out of the lib dir, then building
- // with whatever the real python interpreter uses. (e.g. lib
- // for most, lib64 on RHEL x86_64).
- char python_path[PATH_MAX];
- ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path,
- LLDB_PYTHON_RELATIVE_LIBDIR);
-
- char final_path[PATH_MAX];
- realpath(python_path, final_path);
- file_spec.GetDirectory().SetCString(final_path);
-
- return true;
-#else
- llvm::SmallString<256> python_version_dir;
- llvm::raw_svector_ostream os(python_version_dir);
- os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION
- << "/site-packages";
-
- // We may get our string truncated. Should we protect this with an assert?
- ::strncat(raw_path, python_version_dir.c_str(),
- sizeof(raw_path) - strlen(raw_path) - 1);
-
- file_spec.GetDirectory().SetCString(raw_path);
- return true;
-#endif
-#else
- return false;
-#endif
-}
-
bool HostInfoPosix::GetEnvironmentVar(const std::string &var_name,
std::string &var) {
if (const char *pvar = ::getenv(var_name.c_str())) {
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/HostThreadPosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/HostThreadPosix.cpp
index 71abb76dc600..13de42f763ec 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/HostThreadPosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/HostThreadPosix.cpp
@@ -41,14 +41,11 @@ Status HostThreadPosix::Join(lldb::thread_result_t *result) {
Status HostThreadPosix::Cancel() {
Status error;
if (IsJoinable()) {
-#ifndef __ANDROID__
#ifndef __FreeBSD__
llvm_unreachable("someone is calling HostThread::Cancel()");
-#endif
+#else
int err = ::pthread_cancel(m_thread);
error.SetError(err, eErrorTypePOSIX);
-#else
- error.SetErrorString("HostThreadPosix::Cancel() not supported on Android");
#endif
}
return error;
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp
index da99fd702424..b321cad64275 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp
@@ -127,18 +127,14 @@ Status PipePosix::CreateWithUniqueName(llvm::StringRef prefix,
llvm::SmallVectorImpl<char> &name) {
llvm::SmallString<PATH_MAX> named_pipe_path;
llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str());
- FileSpec tmpdir_file_spec;
- tmpdir_file_spec.Clear();
- if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) {
- tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str());
- } else {
+ FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
+ if (!tmpdir_file_spec)
tmpdir_file_spec.AppendPathComponent("/tmp");
- tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str());
- }
+ tmpdir_file_spec.AppendPathComponent(pipe_spec);
// It's possible that another process creates the target path after we've
- // verified it's available but before we create it, in which case we
- // should try again.
+ // verified it's available but before we create it, in which case we should
+ // try again.
Status error;
do {
llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(),
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/contrib/llvm/tools/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
index ac1d9011c2b7..46ce3e3d224f 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
@@ -38,17 +38,12 @@
using namespace lldb;
using namespace lldb_private;
-static void FixupEnvironment(Args &env) {
+static void FixupEnvironment(Environment &env) {
#ifdef __ANDROID__
// If there is no PATH variable specified inside the environment then set the
// path to /system/bin. It is required because the default path used by
// execve() is wrong on android.
- static const char *path = "PATH=";
- for (auto &entry : env.entries()) {
- if (entry.ref.startswith(path))
- return;
- }
- env.AppendArgument(llvm::StringRef("PATH=/system/bin"));
+ env.try_emplace("PATH", "/system/bin");
#endif
}
@@ -95,10 +90,6 @@ static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd,
static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
const ProcessLaunchInfo &info) {
- // Do not inherit setgid powers.
- if (setgid(getgid()) != 0)
- ExitWithError(error_fd, "setgid");
-
if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) {
if (setpgid(0, 0) != 0)
ExitWithError(error_fd, "setpgid");
@@ -132,23 +123,26 @@ static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
ExitWithError(error_fd, "chdir");
DisableASLRIfRequested(error_fd, info);
- Args env = info.GetEnvironmentEntries();
+ Environment env = info.GetEnvironment();
FixupEnvironment(env);
- const char **envp = env.GetConstArgumentVector();
+ Environment::Envp envp = env.getEnvp();
- // Clear the signal mask to prevent the child from being affected by
- // any masking done by the parent.
+ // Clear the signal mask to prevent the child from being affected by any
+ // masking done by the parent.
sigset_t set;
if (sigemptyset(&set) != 0 ||
pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
ExitWithError(error_fd, "pthread_sigmask");
if (info.GetFlags().Test(eLaunchFlagDebug)) {
+ // Do not inherit setgid powers.
+ if (setgid(getgid()) != 0)
+ ExitWithError(error_fd, "setgid");
+
// HACK:
// Close everything besides stdin, stdout, and stderr that has no file
// action to avoid leaking. Only do this when debugging, as elsewhere we
- // actually rely on
- // passing open descriptors to child processes.
+ // actually rely on passing open descriptors to child processes.
for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd)
if (!info.GetFileActionForFD(fd) && fd != error_fd)
close(fd);
@@ -159,26 +153,20 @@ static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
}
// Execute. We should never return...
- execve(argv[0], const_cast<char *const *>(argv),
- const_cast<char *const *>(envp));
+ execve(argv[0], const_cast<char *const *>(argv), envp);
#if defined(__linux__)
if (errno == ETXTBSY) {
- // On android M and earlier we can get this error because the adb deamon can
- // hold a write
- // handle on the executable even after it has finished uploading it. This
- // state lasts
- // only a short time and happens only when there are many concurrent adb
- // commands being
- // issued, such as when running the test suite. (The file remains open when
- // someone does
- // an "adb shell" command in the fork() child before it has had a chance to
- // exec.) Since
- // this state should clear up quickly, wait a while and then give it one
- // more go.
+ // On android M and earlier we can get this error because the adb deamon
+ // can hold a write handle on the executable even after it has finished
+ // uploading it. This state lasts only a short time and happens only when
+ // there are many concurrent adb commands being issued, such as when
+ // running the test suite. (The file remains open when someone does an "adb
+ // shell" command in the fork() child before it has had a chance to exec.)
+ // Since this state should clear up quickly, wait a while and then give it
+ // one more go.
usleep(50000);
- execve(argv[0], const_cast<char *const *>(argv),
- const_cast<char *const *>(envp));
+ execve(argv[0], const_cast<char *const *>(argv), envp);
}
#endif
diff --git a/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp b/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp
index c1993a69e050..b52e8e6f25e6 100644
--- a/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp
+++ b/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp
@@ -16,20 +16,12 @@
#ifdef LLDB_ENABLE_ALL
#include "Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h"
#endif // LLDB_ENABLE_ALL
-#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
-#ifdef LLDB_ENABLE_ALL
-#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
-#endif // LLDB_ENABLE_ALL
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
-#if defined(__APPLE__)
-#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
-#endif
-
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#endif
@@ -39,7 +31,6 @@
#include "lldb/Host/windows/windows.h"
#endif
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetSelect.h"
#include <string>
@@ -73,9 +64,6 @@ void SystemInitializerCommon::Initialize() {
}
#endif
-#if not defined(__APPLE__)
- llvm::EnablePrettyStackTrace();
-#endif
Log::Initialize();
HostInfo::Initialize();
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
@@ -85,10 +73,6 @@ void SystemInitializerCommon::Initialize() {
// Initialize plug-ins
ObjectContainerBSDArchive::Initialize();
- ObjectFileELF::Initialize();
-#ifdef LLDB_ENABLE_ALL
- ObjectFilePECOFF::Initialize();
-#endif // LLDB_ENABLE_ALL
EmulateInstructionARM::Initialize();
EmulateInstructionMIPS::Initialize();
@@ -101,9 +85,6 @@ void SystemInitializerCommon::Initialize() {
ObjectContainerUniversalMachO::Initialize();
#endif // LLDB_ENABLE_ALL
-#if defined(__APPLE__)
- ObjectFileMachO::Initialize();
-#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
ProcessPOSIXLog::Initialize();
#endif
@@ -116,10 +97,6 @@ void SystemInitializerCommon::Terminate() {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
ObjectContainerBSDArchive::Terminate();
- ObjectFileELF::Terminate();
-#ifdef LLDB_ENABLE_ALL
- ObjectFilePECOFF::Terminate();
-#endif // LLDB_ENABLE_ALL
EmulateInstructionARM::Terminate();
EmulateInstructionMIPS::Terminate();
@@ -128,9 +105,6 @@ void SystemInitializerCommon::Terminate() {
#ifdef LLDB_ENABLE_ALL
ObjectContainerUniversalMachO::Terminate();
#endif // LLDB_ENABLE_ALL
-#if defined(__APPLE__)
- ObjectFileMachO::Terminate();
-#endif
#if defined(_MSC_VER)
ProcessWindowsLog::Terminate();
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
deleted file mode 100644
index 07e5191f898a..000000000000
--- a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
+++ /dev/null
@@ -1,1500 +0,0 @@
-//===-- Args.cpp ------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <cstdlib>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/Options.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/StreamString.h"
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-// A helper function for argument parsing.
-// Parses the initial part of the first argument using normal double quote
-// rules:
-// backslash escapes the double quote and itself. The parsed string is appended
-// to the second
-// argument. The function returns the unparsed portion of the string, starting
-// at the closing
-// quote.
-static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
- std::string &result) {
- // Inside double quotes, '\' and '"' are special.
- static const char *k_escapable_characters = "\"\\";
- while (true) {
- // Skip over over regular characters and append them.
- size_t regular = quoted.find_first_of(k_escapable_characters);
- result += quoted.substr(0, regular);
- quoted = quoted.substr(regular);
-
- // If we have reached the end of string or the closing quote, we're done.
- if (quoted.empty() || quoted.front() == '"')
- break;
-
- // We have found a backslash.
- quoted = quoted.drop_front();
-
- if (quoted.empty()) {
- // A lone backslash at the end of string, let's just append it.
- result += '\\';
- break;
- }
-
- // If the character after the backslash is not a whitelisted escapable
- // character, we
- // leave the character sequence untouched.
- if (strchr(k_escapable_characters, quoted.front()) == nullptr)
- result += '\\';
-
- result += quoted.front();
- quoted = quoted.drop_front();
- }
-
- return quoted;
-}
-
-static size_t ArgvToArgc(const char **argv) {
- if (!argv)
- return 0;
- size_t count = 0;
- while (*argv++)
- ++count;
- return count;
-}
-
-// A helper function for SetCommandString. Parses a single argument from the
-// command string, processing quotes and backslashes in a shell-like manner.
-// The function returns a tuple consisting of the parsed argument, the quote
-// char used, and the unparsed portion of the string starting at the first
-// unqouted, unescaped whitespace character.
-static std::tuple<std::string, char, llvm::StringRef>
-ParseSingleArgument(llvm::StringRef command) {
- // Argument can be split into multiple discontiguous pieces, for example:
- // "Hello ""World"
- // this would result in a single argument "Hello World" (without the quotes)
- // since the quotes would be removed and there is not space between the
- // strings.
- std::string arg;
-
- // Since we can have multiple quotes that form a single command
- // in a command like: "Hello "world'!' (which will make a single
- // argument "Hello world!") we remember the first quote character
- // we encounter and use that for the quote character.
- char first_quote_char = '\0';
-
- bool arg_complete = false;
- do {
- // Skip over over regular characters and append them.
- size_t regular = command.find_first_of(" \t\"'`\\");
- arg += command.substr(0, regular);
- command = command.substr(regular);
-
- if (command.empty())
- break;
-
- char special = command.front();
- command = command.drop_front();
- switch (special) {
- case '\\':
- if (command.empty()) {
- arg += '\\';
- break;
- }
-
- // If the character after the backslash is not a whitelisted escapable
- // character, we
- // leave the character sequence untouched.
- if (strchr(" \t\\'\"`", command.front()) == nullptr)
- arg += '\\';
-
- arg += command.front();
- command = command.drop_front();
-
- break;
-
- case ' ':
- case '\t':
- // We are not inside any quotes, we just found a space after an
- // argument. We are done.
- arg_complete = true;
- break;
-
- case '"':
- case '\'':
- case '`':
- // We found the start of a quote scope.
- if (first_quote_char == '\0')
- first_quote_char = special;
-
- if (special == '"')
- command = ParseDoubleQuotes(command, arg);
- else {
- // For single quotes, we simply skip ahead to the matching quote
- // character
- // (or the end of the string).
- size_t quoted = command.find(special);
- arg += command.substr(0, quoted);
- command = command.substr(quoted);
- }
-
- // If we found a closing quote, skip it.
- if (!command.empty())
- command = command.drop_front();
-
- break;
- }
- } while (!arg_complete);
-
- return std::make_tuple(arg, first_quote_char, command);
-}
-
-Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) {
- size_t size = str.size();
- ptr.reset(new char[size + 1]);
-
- ::memcpy(data(), str.data() ? str.data() : "", size);
- ptr[size] = 0;
- ref = llvm::StringRef(c_str(), size);
-}
-
-//----------------------------------------------------------------------
-// Args constructor
-//----------------------------------------------------------------------
-Args::Args(llvm::StringRef command) { SetCommandString(command); }
-
-Args::Args(const Args &rhs) { *this = rhs; }
-
-Args::Args(const StringList &list) : Args() {
- for(size_t i = 0; i < list.GetSize(); ++i)
- AppendArgument(list[i]);
-}
-
-Args &Args::operator=(const Args &rhs) {
- Clear();
-
- m_argv.clear();
- m_entries.clear();
- for (auto &entry : rhs.m_entries) {
- m_entries.emplace_back(entry.ref, entry.quote);
- m_argv.push_back(m_entries.back().data());
- }
- m_argv.push_back(nullptr);
- return *this;
-}
-
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-Args::~Args() {}
-
-void Args::Dump(Stream &s, const char *label_name) const {
- if (!label_name)
- return;
-
- int i = 0;
- for (auto &entry : m_entries) {
- s.Indent();
- s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref);
- }
- s.Format("{0}[{1}]=NULL\n", label_name, i);
- s.EOL();
-}
-
-bool Args::GetCommandString(std::string &command) const {
- command.clear();
-
- for (size_t i = 0; i < m_entries.size(); ++i) {
- if (i > 0)
- command += ' ';
- command += m_entries[i].ref;
- }
-
- return !m_entries.empty();
-}
-
-bool Args::GetQuotedCommandString(std::string &command) const {
- command.clear();
-
- for (size_t i = 0; i < m_entries.size(); ++i) {
- if (i > 0)
- command += ' ';
-
- if (m_entries[i].quote) {
- command += m_entries[i].quote;
- command += m_entries[i].ref;
- command += m_entries[i].quote;
- } else {
- command += m_entries[i].ref;
- }
- }
-
- return !m_entries.empty();
-}
-
-void Args::SetCommandString(llvm::StringRef command) {
- Clear();
- m_argv.clear();
-
- static const char *k_space_separators = " \t";
- command = command.ltrim(k_space_separators);
- std::string arg;
- char quote;
- while (!command.empty()) {
- std::tie(arg, quote, command) = ParseSingleArgument(command);
- m_entries.emplace_back(arg, quote);
- m_argv.push_back(m_entries.back().data());
- command = command.ltrim(k_space_separators);
- }
- m_argv.push_back(nullptr);
-}
-
-void Args::UpdateArgsAfterOptionParsing() {
- assert(!m_argv.empty());
- assert(m_argv.back() == nullptr);
-
- // Now m_argv might be out of date with m_entries, so we need to fix that.
- // This happens because getopt_long_only may permute the order of the
- // arguments in argv, so we need to re-order the quotes and the refs array
- // to match.
- for (size_t i = 0; i < m_argv.size() - 1; ++i) {
- const char *argv = m_argv[i];
- auto pos =
- std::find_if(m_entries.begin() + i, m_entries.end(),
- [argv](const ArgEntry &D) { return D.c_str() == argv; });
- assert(pos != m_entries.end());
- size_t distance = std::distance(m_entries.begin(), pos);
- if (i == distance)
- continue;
-
- assert(distance > i);
-
- std::swap(m_entries[i], m_entries[distance]);
- assert(m_entries[i].ref.data() == m_argv[i]);
- }
- m_entries.resize(m_argv.size() - 1);
-}
-
-size_t Args::GetArgumentCount() const { return m_entries.size(); }
-
-const char *Args::GetArgumentAtIndex(size_t idx) const {
- if (idx < m_argv.size())
- return m_argv[idx];
- return nullptr;
-}
-
-char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
- if (idx < m_entries.size())
- return m_entries[idx].quote;
- return '\0';
-}
-
-char **Args::GetArgumentVector() {
- assert(!m_argv.empty());
- // TODO: functions like execve and posix_spawnp exhibit undefined behavior
- // when argv or envp is null. So the code below is actually wrong. However,
- // other code in LLDB depends on it being null. The code has been acting this
- // way for some time, so it makes sense to leave it this way until someone
- // has the time to come along and fix it.
- return (m_argv.size() > 1) ? m_argv.data() : nullptr;
-}
-
-const char **Args::GetConstArgumentVector() const {
- assert(!m_argv.empty());
- return (m_argv.size() > 1) ? const_cast<const char **>(m_argv.data())
- : nullptr;
-}
-
-void Args::Shift() {
- // Don't pop the last NULL terminator from the argv array
- if (m_entries.empty())
- return;
- m_argv.erase(m_argv.begin());
- m_entries.erase(m_entries.begin());
-}
-
-void Args::Unshift(llvm::StringRef arg_str, char quote_char) {
- InsertArgumentAtIndex(0, arg_str, quote_char);
-}
-
-void Args::AppendArguments(const Args &rhs) {
- assert(m_argv.size() == m_entries.size() + 1);
- assert(m_argv.back() == nullptr);
- m_argv.pop_back();
- for (auto &entry : rhs.m_entries) {
- m_entries.emplace_back(entry.ref, entry.quote);
- m_argv.push_back(m_entries.back().data());
- }
- m_argv.push_back(nullptr);
-}
-
-void Args::AppendArguments(const char **argv) {
- size_t argc = ArgvToArgc(argv);
-
- assert(m_argv.size() == m_entries.size() + 1);
- assert(m_argv.back() == nullptr);
- m_argv.pop_back();
- for (auto arg : llvm::makeArrayRef(argv, argc)) {
- m_entries.emplace_back(arg, '\0');
- m_argv.push_back(m_entries.back().data());
- }
-
- m_argv.push_back(nullptr);
-}
-
-void Args::AppendArgument(llvm::StringRef arg_str, char quote_char) {
- InsertArgumentAtIndex(GetArgumentCount(), arg_str, quote_char);
-}
-
-void Args::InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
- char quote_char) {
- assert(m_argv.size() == m_entries.size() + 1);
- assert(m_argv.back() == nullptr);
-
- if (idx > m_entries.size())
- return;
- m_entries.emplace(m_entries.begin() + idx, arg_str, quote_char);
- m_argv.insert(m_argv.begin() + idx, m_entries[idx].data());
-}
-
-void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
- char quote_char) {
- assert(m_argv.size() == m_entries.size() + 1);
- assert(m_argv.back() == nullptr);
-
- if (idx >= m_entries.size())
- return;
-
- if (arg_str.size() > m_entries[idx].ref.size()) {
- m_entries[idx] = ArgEntry(arg_str, quote_char);
- m_argv[idx] = m_entries[idx].data();
- } else {
- const char *src_data = arg_str.data() ? arg_str.data() : "";
- ::memcpy(m_entries[idx].data(), src_data, arg_str.size());
- m_entries[idx].ptr[arg_str.size()] = 0;
- m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size());
- }
-}
-
-void Args::DeleteArgumentAtIndex(size_t idx) {
- if (idx >= m_entries.size())
- return;
-
- m_argv.erase(m_argv.begin() + idx);
- m_entries.erase(m_entries.begin() + idx);
-}
-
-void Args::SetArguments(size_t argc, const char **argv) {
- Clear();
-
- auto args = llvm::makeArrayRef(argv, argc);
- m_entries.resize(argc);
- m_argv.resize(argc + 1);
- for (size_t i = 0; i < args.size(); ++i) {
- char quote =
- ((args[i][0] == '\'') || (args[i][0] == '"') || (args[i][0] == '`'))
- ? args[i][0]
- : '\0';
-
- m_entries[i] = ArgEntry(args[i], quote);
- m_argv[i] = m_entries[i].data();
- }
-}
-
-void Args::SetArguments(const char **argv) {
- SetArguments(ArgvToArgc(argv), argv);
-}
-
-Status Args::ParseOptions(Options &options, ExecutionContext *execution_context,
- PlatformSP platform_sp, bool require_validation) {
- StreamString sstr;
- Status error;
- Option *long_options = options.GetLongOptions();
- if (long_options == nullptr) {
- error.SetErrorStringWithFormat("invalid long options");
- return error;
- }
-
- for (int i = 0; long_options[i].definition != nullptr; ++i) {
- if (long_options[i].flag == nullptr) {
- if (isprint8(long_options[i].val)) {
- sstr << (char)long_options[i].val;
- switch (long_options[i].definition->option_has_arg) {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ':';
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
- }
- std::unique_lock<std::mutex> lock;
- OptionParser::Prepare(lock);
- int val;
- while (1) {
- int long_options_index = -1;
- val = OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
- sstr.GetString(), long_options,
- &long_options_index);
- if (val == -1)
- break;
-
- // Did we get an error?
- if (val == '?') {
- error.SetErrorStringWithFormat("unknown or ambiguous option");
- break;
- }
- // The option auto-set itself
- if (val == 0)
- continue;
-
- ((Options *)&options)->OptionSeen(val);
-
- // Lookup the long option index
- if (long_options_index == -1) {
- for (int i = 0; long_options[i].definition || long_options[i].flag ||
- long_options[i].val;
- ++i) {
- if (long_options[i].val == val) {
- long_options_index = i;
- break;
- }
- }
- }
- // Call the callback with the option
- if (long_options_index >= 0 &&
- long_options[long_options_index].definition) {
- const OptionDefinition *def = long_options[long_options_index].definition;
-
- if (!platform_sp) {
- // User did not pass in an explicit platform. Try to grab
- // from the execution context.
- TargetSP target_sp =
- execution_context ? execution_context->GetTargetSP() : TargetSP();
- platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
- }
- OptionValidator *validator = def->validator;
-
- if (!platform_sp && require_validation) {
- // Caller requires validation but we cannot validate as we
- // don't have the mandatory platform against which to
- // validate.
- error.SetErrorString("cannot validate options: "
- "no platform available");
- return error;
- }
-
- bool validation_failed = false;
- if (platform_sp) {
- // Ensure we have an execution context, empty or not.
- ExecutionContext dummy_context;
- ExecutionContext *exe_ctx_p =
- execution_context ? execution_context : &dummy_context;
- if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
- validation_failed = true;
- error.SetErrorStringWithFormat("Option \"%s\" invalid. %s",
- def->long_option,
- def->validator->LongConditionString());
- }
- }
-
- // As long as validation didn't fail, we set the option value.
- if (!validation_failed)
- error = options.SetOptionValue(
- long_options_index,
- (def->option_has_arg == OptionParser::eNoArgument)
- ? nullptr
- : OptionParser::GetOptionArgument(),
- execution_context);
- } else {
- error.SetErrorStringWithFormat("invalid option with value '%i'", val);
- }
- if (error.Fail())
- break;
- }
-
- // Update our ARGV now that get options has consumed all the options
- m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
- UpdateArgsAfterOptionParsing();
- return error;
-}
-
-void Args::Clear() {
- m_entries.clear();
- m_argv.clear();
- m_argv.push_back(nullptr);
-}
-
-lldb::addr_t Args::StringToAddress(const ExecutionContext *exe_ctx,
- llvm::StringRef s, lldb::addr_t fail_value,
- Status *error_ptr) {
- bool error_set = false;
- if (s.empty()) {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
- s.str().c_str());
- return fail_value;
- }
-
- llvm::StringRef sref = s;
-
- lldb::addr_t addr = LLDB_INVALID_ADDRESS;
- if (!s.getAsInteger(0, addr)) {
- if (error_ptr)
- error_ptr->Clear();
- return addr;
- }
-
- // Try base 16 with no prefix...
- if (!s.getAsInteger(16, addr)) {
- if (error_ptr)
- error_ptr->Clear();
- return addr;
- }
-
- Target *target = nullptr;
- if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
- s.str().c_str());
- return fail_value;
- }
-
- lldb::ValueObjectSP valobj_sp;
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetKeepInMemory(false);
- options.SetTryAllThreads(true);
-
- ExpressionResults expr_result =
- target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options);
-
- bool success = false;
- if (expr_result == eExpressionCompleted) {
- if (valobj_sp)
- valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
- valobj_sp->GetDynamicValueType(), true);
- // Get the address to watch.
- if (valobj_sp)
- addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
- if (success) {
- if (error_ptr)
- error_ptr->Clear();
- return addr;
- } else {
- if (error_ptr) {
- error_set = true;
- error_ptr->SetErrorStringWithFormat(
- "address expression \"%s\" resulted in a value whose type "
- "can't be converted to an address: %s",
- s.str().c_str(), valobj_sp->GetTypeName().GetCString());
- }
- }
-
- } else {
- // Since the compiler can't handle things like "main + 12" we should
- // try to do this for now. The compiler doesn't like adding offsets
- // to function pointer types.
- static RegularExpression g_symbol_plus_offset_regex(
- "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
- RegularExpression::Match regex_match(3);
- if (g_symbol_plus_offset_regex.Execute(sref, &regex_match)) {
- uint64_t offset = 0;
- bool add = true;
- std::string name;
- std::string str;
- if (regex_match.GetMatchAtIndex(s, 1, name)) {
- if (regex_match.GetMatchAtIndex(s, 2, str)) {
- add = str[0] == '+';
-
- if (regex_match.GetMatchAtIndex(s, 3, str)) {
- if (!llvm::StringRef(str).getAsInteger(0, offset)) {
- Status error;
- addr = StringToAddress(exe_ctx, name.c_str(),
- LLDB_INVALID_ADDRESS, &error);
- if (addr != LLDB_INVALID_ADDRESS) {
- if (add)
- return addr + offset;
- else
- return addr - offset;
- }
- }
- }
- }
- }
- }
-
- if (error_ptr) {
- error_set = true;
- error_ptr->SetErrorStringWithFormat(
- "address expression \"%s\" evaluation failed", s.str().c_str());
- }
- }
-
- if (error_ptr) {
- if (!error_set)
- error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
- s.str().c_str());
- }
- return fail_value;
-}
-
-const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
- bool return_null_if_empty) {
- static const char *k_white_space = " \t\v";
- if (!s.empty()) {
- if (leading) {
- size_t pos = s.find_first_not_of(k_white_space);
- if (pos == std::string::npos)
- s.clear();
- else if (pos > 0)
- s.erase(0, pos);
- }
-
- if (trailing) {
- size_t rpos = s.find_last_not_of(k_white_space);
- if (rpos != std::string::npos && rpos + 1 < s.size())
- s.erase(rpos + 1);
- }
- }
- if (return_null_if_empty && s.empty())
- return nullptr;
- return s.c_str();
-}
-
-bool Args::StringToBoolean(llvm::StringRef ref, bool fail_value,
- bool *success_ptr) {
- if (success_ptr)
- *success_ptr = true;
- ref = ref.trim();
- if (ref.equals_lower("false") || ref.equals_lower("off") ||
- ref.equals_lower("no") || ref.equals_lower("0")) {
- return false;
- } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
- ref.equals_lower("yes") || ref.equals_lower("1")) {
- return true;
- }
- if (success_ptr)
- *success_ptr = false;
- return fail_value;
-}
-
-char Args::StringToChar(llvm::StringRef s, char fail_value, bool *success_ptr) {
- if (success_ptr)
- *success_ptr = false;
- if (s.size() != 1)
- return fail_value;
-
- if (success_ptr)
- *success_ptr = true;
- return s[0];
-}
-
-bool Args::StringToVersion(llvm::StringRef string, uint32_t &major,
- uint32_t &minor, uint32_t &update) {
- major = UINT32_MAX;
- minor = UINT32_MAX;
- update = UINT32_MAX;
-
- if (string.empty())
- return false;
-
- llvm::StringRef major_str, minor_str, update_str;
-
- std::tie(major_str, minor_str) = string.split('.');
- std::tie(minor_str, update_str) = minor_str.split('.');
- if (major_str.getAsInteger(10, major))
- return false;
- if (!minor_str.empty() && minor_str.getAsInteger(10, minor))
- return false;
- if (!update_str.empty() && update_str.getAsInteger(10, update))
- return false;
-
- return true;
-}
-
-const char *Args::GetShellSafeArgument(const FileSpec &shell,
- const char *unsafe_arg,
- std::string &safe_arg) {
- struct ShellDescriptor {
- ConstString m_basename;
- const char *m_escapables;
- };
-
- static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
- {ConstString("tcsh"), " '\"<>()&$"},
- {ConstString("sh"), " '\"<>()&"}};
-
- // safe minimal set
- const char *escapables = " '\"";
-
- if (auto basename = shell.GetFilename()) {
- for (const auto &Shell : g_Shells) {
- if (Shell.m_basename == basename) {
- escapables = Shell.m_escapables;
- break;
- }
- }
- }
-
- safe_arg.assign(unsafe_arg);
- size_t prev_pos = 0;
- while (prev_pos < safe_arg.size()) {
- // Escape spaces and quotes
- size_t pos = safe_arg.find_first_of(escapables, prev_pos);
- if (pos != std::string::npos) {
- safe_arg.insert(pos, 1, '\\');
- prev_pos = pos + 2;
- } else
- break;
- }
- return safe_arg.c_str();
-}
-
-int64_t Args::StringToOptionEnum(llvm::StringRef s,
- OptionEnumValueElement *enum_values,
- int32_t fail_value, Status &error) {
- error.Clear();
- if (!enum_values) {
- error.SetErrorString("invalid enumeration argument");
- return fail_value;
- }
-
- if (s.empty()) {
- error.SetErrorString("empty enumeration string");
- return fail_value;
- }
-
- for (int i = 0; enum_values[i].string_value != nullptr; i++) {
- llvm::StringRef this_enum(enum_values[i].string_value);
- if (this_enum.startswith(s))
- return enum_values[i].value;
- }
-
- StreamString strm;
- strm.PutCString("invalid enumeration value, valid values are: ");
- for (int i = 0; enum_values[i].string_value != nullptr; i++) {
- strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
- }
- error.SetErrorString(strm.GetString());
- return fail_value;
-}
-
-lldb::ScriptLanguage
-Args::StringToScriptLanguage(llvm::StringRef s, lldb::ScriptLanguage fail_value,
- bool *success_ptr) {
- if (success_ptr)
- *success_ptr = true;
-
- if (s.equals_lower("python"))
- return eScriptLanguagePython;
- if (s.equals_lower("default"))
- return eScriptLanguageDefault;
- if (s.equals_lower("none"))
- return eScriptLanguageNone;
-
- if (success_ptr)
- *success_ptr = false;
- return fail_value;
-}
-
-Status Args::StringToFormat(const char *s, lldb::Format &format,
- size_t *byte_size_ptr) {
- format = eFormatInvalid;
- Status error;
-
- if (s && s[0]) {
- if (byte_size_ptr) {
- if (isdigit(s[0])) {
- char *format_char = nullptr;
- unsigned long byte_size = ::strtoul(s, &format_char, 0);
- if (byte_size != ULONG_MAX)
- *byte_size_ptr = byte_size;
- s = format_char;
- } else
- *byte_size_ptr = 0;
- }
-
- const bool partial_match_ok = true;
- if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
- StreamString error_strm;
- error_strm.Printf(
- "Invalid format character or name '%s'. Valid values are:\n", s);
- for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
- char format_char = FormatManager::GetFormatAsFormatChar(f);
- if (format_char)
- error_strm.Printf("'%c' or ", format_char);
-
- error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
- error_strm.EOL();
- }
-
- if (byte_size_ptr)
- error_strm.PutCString(
- "An optional byte size can precede the format character.\n");
- error.SetErrorString(error_strm.GetString());
- }
-
- if (error.Fail())
- return error;
- } else {
- error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
- }
- return error;
-}
-
-lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
- lldb::Encoding fail_value) {
- return llvm::StringSwitch<lldb::Encoding>(s)
- .Case("uint", eEncodingUint)
- .Case("sint", eEncodingSint)
- .Case("ieee754", eEncodingIEEE754)
- .Case("vector", eEncodingVector)
- .Default(fail_value);
-}
-
-uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
- if (s.empty())
- return LLDB_INVALID_REGNUM;
- uint32_t result = llvm::StringSwitch<uint32_t>(s)
- .Case("pc", LLDB_REGNUM_GENERIC_PC)
- .Case("sp", LLDB_REGNUM_GENERIC_SP)
- .Case("fp", LLDB_REGNUM_GENERIC_FP)
- .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
- .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
- .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
- .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
- .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
- .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
- .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
- .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
- .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
- .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
- .Default(LLDB_INVALID_REGNUM);
- return result;
-}
-
-void Args::AddOrReplaceEnvironmentVariable(llvm::StringRef env_var_name,
- llvm::StringRef new_value) {
- if (env_var_name.empty())
- return;
-
- // Build the new entry.
- std::string var_string(env_var_name);
- if (!new_value.empty()) {
- var_string += "=";
- var_string += new_value;
- }
-
- size_t index = 0;
- if (ContainsEnvironmentVariable(env_var_name, &index)) {
- ReplaceArgumentAtIndex(index, var_string);
- return;
- }
-
- // We didn't find it. Append it instead.
- AppendArgument(var_string);
-}
-
-bool Args::ContainsEnvironmentVariable(llvm::StringRef env_var_name,
- size_t *argument_index) const {
- // Validate args.
- if (env_var_name.empty())
- return false;
-
- // Check each arg to see if it matches the env var name.
- for (auto arg : llvm::enumerate(m_entries)) {
- llvm::StringRef name, value;
- std::tie(name, value) = arg.value().ref.split('=');
- if (name != env_var_name)
- continue;
-
- if (argument_index)
- *argument_index = arg.index();
- return true;
- }
-
- // We didn't find a match.
- return false;
-}
-
-size_t Args::FindArgumentIndexForOption(Option *long_options,
- int long_options_index) const {
- char short_buffer[3];
- char long_buffer[255];
- ::snprintf(short_buffer, sizeof(short_buffer), "-%c",
- long_options[long_options_index].val);
- ::snprintf(long_buffer, sizeof(long_buffer), "--%s",
- long_options[long_options_index].definition->long_option);
-
- for (auto entry : llvm::enumerate(m_entries)) {
- if (entry.value().ref.startswith(short_buffer) ||
- entry.value().ref.startswith(long_buffer))
- return entry.index();
- }
-
- return size_t(-1);
-}
-
-bool Args::IsPositionalArgument(const char *arg) {
- if (arg == nullptr)
- return false;
-
- bool is_positional = true;
- const char *cptr = arg;
-
- if (cptr[0] == '%') {
- ++cptr;
- while (isdigit(cptr[0]))
- ++cptr;
- if (cptr[0] != '\0')
- is_positional = false;
- } else
- is_positional = false;
-
- return is_positional;
-}
-
-std::string Args::ParseAliasOptions(Options &options,
- CommandReturnObject &result,
- OptionArgVector *option_arg_vector,
- llvm::StringRef raw_input_string) {
- std::string result_string(raw_input_string);
- StreamString sstr;
- int i;
- Option *long_options = options.GetLongOptions();
-
- if (long_options == nullptr) {
- result.AppendError("invalid long options");
- result.SetStatus(eReturnStatusFailed);
- return result_string;
- }
-
- for (i = 0; long_options[i].definition != nullptr; ++i) {
- if (long_options[i].flag == nullptr) {
- sstr << (char)long_options[i].val;
- switch (long_options[i].definition->option_has_arg) {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ":";
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
-
- std::unique_lock<std::mutex> lock;
- OptionParser::Prepare(lock);
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- int val;
- while (1) {
- int long_options_index = -1;
- val = OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
- sstr.GetString(), long_options,
- &long_options_index);
-
- if (val == -1)
- break;
-
- if (val == '?') {
- result.AppendError("unknown or ambiguous option");
- result.SetStatus(eReturnStatusFailed);
- break;
- }
-
- if (val == 0)
- continue;
-
- options.OptionSeen(val);
-
- // Look up the long option index
- if (long_options_index == -1) {
- for (int j = 0; long_options[j].definition || long_options[j].flag ||
- long_options[j].val;
- ++j) {
- if (long_options[j].val == val) {
- long_options_index = j;
- break;
- }
- }
- }
-
- // See if the option takes an argument, and see if one was supplied.
- if (long_options_index == -1) {
- result.AppendErrorWithFormat("Invalid option with value '%c'.\n", val);
- result.SetStatus(eReturnStatusFailed);
- return result_string;
- }
-
- StreamString option_str;
- option_str.Printf("-%c", val);
- const OptionDefinition *def = long_options[long_options_index].definition;
- int has_arg =
- (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
-
- const char *option_arg = nullptr;
- switch (has_arg) {
- case OptionParser::eRequiredArgument:
- if (OptionParser::GetOptionArgument() == nullptr) {
- result.AppendErrorWithFormat(
- "Option '%s' is missing argument specifier.\n",
- option_str.GetData());
- result.SetStatus(eReturnStatusFailed);
- return result_string;
- }
- LLVM_FALLTHROUGH;
- case OptionParser::eOptionalArgument:
- option_arg = OptionParser::GetOptionArgument();
- LLVM_FALLTHROUGH;
- case OptionParser::eNoArgument:
- break;
- default:
- result.AppendErrorWithFormat("error with options table; invalid value "
- "in has_arg field for option '%c'.\n",
- val);
- result.SetStatus(eReturnStatusFailed);
- return result_string;
- }
- if (!option_arg)
- option_arg = "<no-argument>";
- option_arg_vector->emplace_back(option_str.GetString(), has_arg,
- option_arg);
-
- // Find option in the argument list; also see if it was supposed to take
- // an argument and if one was supplied. Remove option (and argument, if
- // given) from the argument list. Also remove them from the
- // raw_input_string, if one was passed in.
- size_t idx = FindArgumentIndexForOption(long_options, long_options_index);
- if (idx == size_t(-1))
- continue;
-
- if (!result_string.empty()) {
- auto tmp_arg = m_entries[idx].ref;
- size_t pos = result_string.find(tmp_arg);
- if (pos != std::string::npos)
- result_string.erase(pos, tmp_arg.size());
- }
- ReplaceArgumentAtIndex(idx, llvm::StringRef());
- if ((long_options[long_options_index].definition->option_has_arg !=
- OptionParser::eNoArgument) &&
- (OptionParser::GetOptionArgument() != nullptr) &&
- (idx + 1 < GetArgumentCount()) &&
- (m_entries[idx + 1].ref == OptionParser::GetOptionArgument())) {
- if (result_string.size() > 0) {
- auto tmp_arg = m_entries[idx + 1].ref;
- size_t pos = result_string.find(tmp_arg);
- if (pos != std::string::npos)
- result_string.erase(pos, tmp_arg.size());
- }
- ReplaceArgumentAtIndex(idx + 1, llvm::StringRef());
- }
- }
- return result_string;
-}
-
-void Args::ParseArgsForCompletion(Options &options,
- OptionElementVector &option_element_vector,
- uint32_t cursor_index) {
- StreamString sstr;
- Option *long_options = options.GetLongOptions();
- option_element_vector.clear();
-
- if (long_options == nullptr) {
- return;
- }
-
- // Leading : tells getopt to return a : for a missing option argument AND
- // to suppress error messages.
-
- sstr << ":";
- for (int i = 0; long_options[i].definition != nullptr; ++i) {
- if (long_options[i].flag == nullptr) {
- sstr << (char)long_options[i].val;
- switch (long_options[i].definition->option_has_arg) {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ":";
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
-
- std::unique_lock<std::mutex> lock;
- OptionParser::Prepare(lock);
- OptionParser::EnableError(false);
-
- int val;
- auto opt_defs = options.GetDefinitions();
-
- // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the
- // options to the front. So we have to build another Arg and pass that to
- // OptionParser::Parse so it doesn't change the one we have.
-
- std::vector<char *> dummy_vec = m_argv;
-
- bool failed_once = false;
- uint32_t dash_dash_pos = -1;
-
- while (1) {
- bool missing_argument = false;
- int long_options_index = -1;
-
- val = OptionParser::Parse(dummy_vec.size() - 1, &dummy_vec[0],
- sstr.GetString(), long_options,
- &long_options_index);
-
- if (val == -1) {
- // When we're completing a "--" which is the last option on line,
- if (failed_once)
- break;
-
- failed_once = true;
-
- // If this is a bare "--" we mark it as such so we can complete it
- // successfully later.
- // Handling the "--" is a little tricky, since that may mean end of
- // options or arguments, or the
- // user might want to complete options by long name. I make this work by
- // checking whether the
- // cursor is in the "--" argument, and if so I assume we're completing the
- // long option, otherwise
- // I let it pass to OptionParser::Parse which will terminate the option
- // parsing.
- // Note, in either case we continue parsing the line so we can figure out
- // what other options
- // were passed. This will be useful when we come to restricting
- // completions based on what other
- // options we've seen on the line.
-
- if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
- dummy_vec.size() - 1 &&
- (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
- dash_dash_pos = OptionParser::GetOptionIndex() - 1;
- if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) ==
- cursor_index) {
- option_element_vector.push_back(
- OptionArgElement(OptionArgElement::eBareDoubleDash,
- OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eBareDoubleDash));
- continue;
- } else
- break;
- } else
- break;
- } else if (val == '?') {
- option_element_vector.push_back(
- OptionArgElement(OptionArgElement::eUnrecognizedArg,
- OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eUnrecognizedArg));
- continue;
- } else if (val == 0) {
- continue;
- } else if (val == ':') {
- // This is a missing argument.
- val = OptionParser::GetOptionErrorCause();
- missing_argument = true;
- }
-
- ((Options *)&options)->OptionSeen(val);
-
- // Look up the long option index
- if (long_options_index == -1) {
- for (int j = 0; long_options[j].definition || long_options[j].flag ||
- long_options[j].val;
- ++j) {
- if (long_options[j].val == val) {
- long_options_index = j;
- break;
- }
- }
- }
-
- // See if the option takes an argument, and see if one was supplied.
- if (long_options_index >= 0) {
- int opt_defs_index = -1;
- for (size_t i = 0; i < opt_defs.size(); i++) {
- if (opt_defs[i].short_option != val)
- continue;
- opt_defs_index = i;
- break;
- }
-
- const OptionDefinition *def = long_options[long_options_index].definition;
- int has_arg =
- (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
- switch (has_arg) {
- case OptionParser::eNoArgument:
- option_element_vector.push_back(OptionArgElement(
- opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
- break;
- case OptionParser::eRequiredArgument:
- if (OptionParser::GetOptionArgument() != nullptr) {
- int arg_index;
- if (missing_argument)
- arg_index = -1;
- else
- arg_index = OptionParser::GetOptionIndex() - 1;
-
- option_element_vector.push_back(OptionArgElement(
- opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
- } else {
- option_element_vector.push_back(OptionArgElement(
- opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
- }
- break;
- case OptionParser::eOptionalArgument:
- if (OptionParser::GetOptionArgument() != nullptr) {
- option_element_vector.push_back(OptionArgElement(
- opt_defs_index, OptionParser::GetOptionIndex() - 2,
- OptionParser::GetOptionIndex() - 1));
- } else {
- option_element_vector.push_back(OptionArgElement(
- opt_defs_index, OptionParser::GetOptionIndex() - 2,
- OptionParser::GetOptionIndex() - 1));
- }
- break;
- default:
- // The options table is messed up. Here we'll just continue
- option_element_vector.push_back(
- OptionArgElement(OptionArgElement::eUnrecognizedArg,
- OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eUnrecognizedArg));
- break;
- }
- } else {
- option_element_vector.push_back(
- OptionArgElement(OptionArgElement::eUnrecognizedArg,
- OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eUnrecognizedArg));
- }
- }
-
- // Finally we have to handle the case where the cursor index points at a
- // single "-". We want to mark that in
- // the option_element_vector, but only if it is not after the "--". But it
- // turns out that OptionParser::Parse just ignores
- // an isolated "-". So we have to look it up by hand here. We only care if
- // it is AT the cursor position.
- // Note, a single quoted dash is not the same as a single dash...
-
- const ArgEntry &cursor = m_entries[cursor_index];
- if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
- cursor_index < dash_dash_pos) &&
- cursor.quote == '\0' && cursor.ref == "-") {
- option_element_vector.push_back(
- OptionArgElement(OptionArgElement::eBareDash, cursor_index,
- OptionArgElement::eBareDash));
- }
-}
-
-void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
- dst.clear();
- if (src) {
- for (const char *p = src; *p != '\0'; ++p) {
- size_t non_special_chars = ::strcspn(p, "\\");
- if (non_special_chars > 0) {
- dst.append(p, non_special_chars);
- p += non_special_chars;
- if (*p == '\0')
- break;
- }
-
- if (*p == '\\') {
- ++p; // skip the slash
- switch (*p) {
- case 'a':
- dst.append(1, '\a');
- break;
- case 'b':
- dst.append(1, '\b');
- break;
- case 'f':
- dst.append(1, '\f');
- break;
- case 'n':
- dst.append(1, '\n');
- break;
- case 'r':
- dst.append(1, '\r');
- break;
- case 't':
- dst.append(1, '\t');
- break;
- case 'v':
- dst.append(1, '\v');
- break;
- case '\\':
- dst.append(1, '\\');
- break;
- case '\'':
- dst.append(1, '\'');
- break;
- case '"':
- dst.append(1, '"');
- break;
- case '0':
- // 1 to 3 octal chars
- {
- // Make a string that can hold onto the initial zero char,
- // up to 3 octal digits, and a terminating NULL.
- char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
-
- int i;
- for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
- oct_str[i] = p[i];
-
- // We don't want to consume the last octal character since
- // the main for loop will do this for us, so we advance p by
- // one less than i (even if i is zero)
- p += i - 1;
- unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
- if (octal_value <= UINT8_MAX) {
- dst.append(1, (char)octal_value);
- }
- }
- break;
-
- case 'x':
- // hex number in the format
- if (isxdigit(p[1])) {
- ++p; // Skip the 'x'
-
- // Make a string that can hold onto two hex chars plus a
- // NULL terminator
- char hex_str[3] = {*p, '\0', '\0'};
- if (isxdigit(p[1])) {
- ++p; // Skip the first of the two hex chars
- hex_str[1] = *p;
- }
-
- unsigned long hex_value = strtoul(hex_str, nullptr, 16);
- if (hex_value <= UINT8_MAX)
- dst.append(1, (char)hex_value);
- } else {
- dst.append(1, 'x');
- }
- break;
-
- default:
- // Just desensitize any other character by just printing what
- // came after the '\'
- dst.append(1, *p);
- break;
- }
- }
- }
- }
-}
-
-void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
- dst.clear();
- if (src) {
- for (const char *p = src; *p != '\0'; ++p) {
- if (isprint8(*p))
- dst.append(1, *p);
- else {
- switch (*p) {
- case '\a':
- dst.append("\\a");
- break;
- case '\b':
- dst.append("\\b");
- break;
- case '\f':
- dst.append("\\f");
- break;
- case '\n':
- dst.append("\\n");
- break;
- case '\r':
- dst.append("\\r");
- break;
- case '\t':
- dst.append("\\t");
- break;
- case '\v':
- dst.append("\\v");
- break;
- case '\'':
- dst.append("\\'");
- break;
- case '"':
- dst.append("\\\"");
- break;
- case '\\':
- dst.append("\\\\");
- break;
- default: {
- // Just encode as octal
- dst.append("\\0");
- char octal_str[32];
- snprintf(octal_str, sizeof(octal_str), "%o", *p);
- dst.append(octal_str);
- } break;
- }
- }
- }
- }
-}
-
-std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
- char quote_char) {
- const char *chars_to_escape = nullptr;
- switch (quote_char) {
- case '\0':
- chars_to_escape = " \t\\'\"`";
- break;
- case '\'':
- chars_to_escape = "";
- break;
- case '"':
- chars_to_escape = "$\"`\\";
- break;
- default:
- assert(false && "Unhandled quote character");
- }
-
- std::string res;
- res.reserve(arg.size());
- for (char c : arg) {
- if (::strchr(chars_to_escape, c))
- res.push_back('\\');
- res.push_back(c);
- }
- return res;
-}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandAlias.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandAlias.cpp
index 2db7460611ca..a4b0a0c55c0e 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandAlias.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandAlias.cpp
@@ -40,12 +40,17 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
ExecutionContext exe_ctx =
cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();
options->NotifyOptionParsingStarting(&exe_ctx);
- args.Unshift(llvm::StringRef("dummy_arg"));
- options_string = args.ParseAliasOptions(*options, result, option_arg_vector,
- options_args);
- args.Shift();
- if (result.Succeeded())
- options->VerifyPartialOptions(result);
+
+ llvm::Expected<Args> args_or =
+ options->ParseAlias(args, option_arg_vector, options_string);
+ if (!args_or) {
+ result.AppendError(toString(args_or.takeError()));
+ result.AppendError("Unable to create requested alias.\n");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ args = std::move(*args_or);
+ options->VerifyPartialOptions(result);
if (!result.Succeeded() &&
result.GetStatus() != lldb::eReturnStatusStarted) {
result.AppendError("Unable to create requested alias.\n");
@@ -109,26 +114,17 @@ bool CommandAlias::WantsCompletion() {
return false;
}
-int CommandAlias::HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) {
+int CommandAlias::HandleCompletion(CompletionRequest &request) {
if (IsValid())
- return m_underlying_command_sp->HandleCompletion(
- input, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ return m_underlying_command_sp->HandleCompletion(request);
return -1;
}
int CommandAlias::HandleArgumentCompletion(
- Args &input, int &cursor_index, int &cursor_char_position,
- OptionElementVector &opt_element_vector, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
+ CompletionRequest &request, OptionElementVector &opt_element_vector) {
if (IsValid())
return m_underlying_command_sp->HandleArgumentCompletion(
- input, cursor_index, cursor_char_position, opt_element_vector,
- match_start_point, max_return_elements, word_complete, matches);
+ request, opt_element_vector);
return -1;
}
@@ -191,8 +187,8 @@ bool CommandAlias::IsDashDashCommand() {
}
}
- // if this is a nested alias, it may be adding arguments on top of an
- // already dash-dash alias
+ // if this is a nested alias, it may be adding arguments on top of an already
+ // dash-dash alias
if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
m_is_dashdash_alias =
(GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes
@@ -223,8 +219,7 @@ std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() {
}
// allow CommandAlias objects to provide their own help, but fallback to the
-// info
-// for the underlying command if no customization has been provided
+// info for the underlying command if no customization has been provided
void CommandAlias::SetHelp(llvm::StringRef str) {
this->CommandObject::SetHelp(str);
m_did_set_help = true;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
index 8dc5637b6e4e..64d2c3222fb6 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -14,32 +14,31 @@
#include "CommandObjectScript.h"
#include "lldb/Interpreter/CommandObjectRegexCommand.h"
-#include "../Commands/CommandObjectApropos.h"
-#include "../Commands/CommandObjectArgs.h"
-#include "../Commands/CommandObjectBreakpoint.h"
-#include "../Commands/CommandObjectBugreport.h"
-#include "../Commands/CommandObjectCommands.h"
-#include "../Commands/CommandObjectDisassemble.h"
-#include "../Commands/CommandObjectExpression.h"
-#include "../Commands/CommandObjectFrame.h"
-#include "../Commands/CommandObjectGUI.h"
-#include "../Commands/CommandObjectHelp.h"
-#include "../Commands/CommandObjectLanguage.h"
-#include "../Commands/CommandObjectLog.h"
-#include "../Commands/CommandObjectMemory.h"
-#include "../Commands/CommandObjectPlatform.h"
-#include "../Commands/CommandObjectPlugin.h"
-#include "../Commands/CommandObjectProcess.h"
-#include "../Commands/CommandObjectQuit.h"
-#include "../Commands/CommandObjectRegister.h"
-#include "../Commands/CommandObjectSettings.h"
-#include "../Commands/CommandObjectSource.h"
-#include "../Commands/CommandObjectSyntax.h"
-#include "../Commands/CommandObjectTarget.h"
-#include "../Commands/CommandObjectThread.h"
-#include "../Commands/CommandObjectType.h"
-#include "../Commands/CommandObjectVersion.h"
-#include "../Commands/CommandObjectWatchpoint.h"
+#include "Commands/CommandObjectApropos.h"
+#include "Commands/CommandObjectBreakpoint.h"
+#include "Commands/CommandObjectBugreport.h"
+#include "Commands/CommandObjectCommands.h"
+#include "Commands/CommandObjectDisassemble.h"
+#include "Commands/CommandObjectExpression.h"
+#include "Commands/CommandObjectFrame.h"
+#include "Commands/CommandObjectGUI.h"
+#include "Commands/CommandObjectHelp.h"
+#include "Commands/CommandObjectLanguage.h"
+#include "Commands/CommandObjectLog.h"
+#include "Commands/CommandObjectMemory.h"
+#include "Commands/CommandObjectPlatform.h"
+#include "Commands/CommandObjectPlugin.h"
+#include "Commands/CommandObjectProcess.h"
+#include "Commands/CommandObjectQuit.h"
+#include "Commands/CommandObjectRegister.h"
+#include "Commands/CommandObjectSettings.h"
+#include "Commands/CommandObjectSource.h"
+#include "Commands/CommandObjectStats.h"
+#include "Commands/CommandObjectTarget.h"
+#include "Commands/CommandObjectThread.h"
+#include "Commands/CommandObjectType.h"
+#include "Commands/CommandObjectVersion.h"
+#include "Commands/CommandObjectWatchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
@@ -55,20 +54,18 @@
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Utility/CleanUp.h"
-
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
@@ -147,6 +144,26 @@ void CommandInterpreter::SetPromptOnQuit(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
+void CommandInterpreter::AllowExitCodeOnQuit(bool allow) {
+ m_allow_exit_code = allow;
+ if (!allow)
+ m_quit_exit_code.reset();
+}
+
+bool CommandInterpreter::SetQuitExitCode(int exit_code) {
+ if (!m_allow_exit_code)
+ return false;
+ m_quit_exit_code = exit_code;
+ return true;
+}
+
+int CommandInterpreter::GetQuitExitCode(bool &exited) const {
+ exited = m_quit_exit_code.hasValue();
+ if (exited)
+ return *m_quit_exit_code;
+ return 0;
+}
+
void CommandInterpreter::ResolveCommand(const char *command_line,
CommandReturnObject &result) {
std::string command = command_line;
@@ -428,6 +445,7 @@ void CommandInterpreter::LoadCommandDictionary() {
CommandObjectSP(new CommandObjectMultiwordSettings(*this));
m_command_dict["source"] =
CommandObjectSP(new CommandObjectMultiwordSource(*this));
+ m_command_dict["statistics"] = CommandObjectSP(new CommandObjectStats(*this));
m_command_dict["target"] =
CommandObjectSP(new CommandObjectMultiwordTarget(*this));
m_command_dict["thread"] =
@@ -460,7 +478,7 @@ void CommandInterpreter::LoadCommandDictionary() {
std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_ap(
new CommandObjectRegexCommand(
*this, "_regexp-break",
- "Set a breakpoint using one of several shorthand formats.\n",
+ "Set a breakpoint using one of several shorthand formats.",
"\n"
"_regexp-break <filename>:<linenum>\n"
" main.c:12 // Break at line 12 of "
@@ -509,7 +527,7 @@ void CommandInterpreter::LoadCommandDictionary() {
std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_ap(
new CommandObjectRegexCommand(
*this, "_regexp-tbreak",
- "Set a one-shot breakpoint using one of several shorthand formats.\n",
+ "Set a one-shot breakpoint using one of several shorthand formats.",
"\n"
"_regexp-break <filename>:<linenum>\n"
" main.c:12 // Break at line 12 of "
@@ -545,7 +563,7 @@ void CommandInterpreter::LoadCommandDictionary() {
// sure to increase the size of this buffer.
char buffer[1024];
int num_printed =
- snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
+ snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o 1");
lldbassert(num_printed < 1024);
UNUSED_IF_ASSERT_DISABLED(num_printed);
success =
@@ -683,10 +701,9 @@ void CommandInterpreter::LoadCommandDictionary() {
"bt [<digit> | all]", 2, 0, false));
if (bt_regex_cmd_ap.get()) {
// accept but don't document "bt -c <number>" -- before bt was a regex
- // command if you wanted to backtrace
- // three frames you would do "bt -c 3" but the intention is to have this
- // emulate the gdb "bt" command and
- // so now "bt 3" is the preferred form, in line with gdb.
+ // command if you wanted to backtrace three frames you would do "bt -c 3"
+ // but the intention is to have this emulate the gdb "bt" command and so
+ // now "bt 3" is the preferred form, in line with gdb.
if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$",
"thread backtrace -c %1") &&
bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$",
@@ -827,9 +844,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str,
unsigned int num_user_matches = 0;
// Look through the command dictionaries one by one, and if we get only one
- // match from any of
- // them in toto, then return that, otherwise return an empty CommandObjectSP
- // and the list of matches.
+ // match from any of them in toto, then return that, otherwise return an
+ // empty CommandObjectSP and the list of matches.
if (HasCommands()) {
num_cmd_matches =
@@ -955,10 +971,9 @@ CommandObjectSP CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str,
CommandObjectSP cmd_obj_sp = GetCommandSP(llvm::StringRef(cmd_words.GetArgumentAtIndex(0)),
include_aliases, true, nullptr);
if (cmd_obj_sp.get() != nullptr) {
- // Loop through the rest of the words in the command (everything passed in
- // was supposed to be part of a
- // command name), and find the appropriate sub-command SP for each command
- // word....
+ // Loop through the rest of the words in the command (everything passed
+ // in was supposed to be part of a command name), and find the
+ // appropriate sub-command SP for each command word....
size_t end = cmd_words.GetArgumentCount();
for (size_t j = 1; j < end; ++j) {
if (cmd_obj_sp->IsMultiwordObject()) {
@@ -988,8 +1003,7 @@ CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
GetCommandSP(cmd_str, false, true, matches).get();
// If we didn't find an exact match to the command string in the commands,
- // look in
- // the aliases.
+ // look in the aliases.
if (command_obj)
return command_obj;
@@ -1004,8 +1018,7 @@ CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
command_obj = GetCommandSP(cmd_str, false, false, nullptr).get();
// Finally, if there wasn't an inexact match among the commands, look for an
- // inexact
- // match in both the commands and aliases.
+ // inexact match in both the commands and aliases.
if (command_obj) {
if (matches)
@@ -1168,8 +1181,8 @@ void CommandInterpreter::GetHelp(CommandReturnObject &result,
CommandObject *CommandInterpreter::GetCommandObjectForCommand(
llvm::StringRef &command_string) {
// This function finds the final, lowest-level, alias-resolved command object
- // whose 'Execute' function will
- // eventually be invoked by the given command line.
+ // whose 'Execute' function will eventually be invoked by the given command
+ // line.
CommandObject *cmd_obj = nullptr;
size_t start = command_string.find_first_not_of(k_white_space);
@@ -1240,8 +1253,8 @@ static size_t FindArgumentTerminator(const std::string &s) {
break;
if (pos > 0) {
if (isspace(s[pos - 1])) {
- // Check if the string ends "\s--" (where \s is a space character)
- // or if we have "\s--\s".
+ // Check if the string ends "\s--" (where \s is a space character) or
+ // if we have "\s--\s".
if ((pos + 2 >= s_len) || isspace(s[pos + 2])) {
return pos;
}
@@ -1376,20 +1389,19 @@ CommandObject *CommandInterpreter::BuildAliasResult(
}
Status CommandInterpreter::PreprocessCommand(std::string &command) {
- // The command preprocessor needs to do things to the command
- // line before any parsing of arguments or anything else is done.
- // The only current stuff that gets preprocessed is anything enclosed
- // in backtick ('`') characters is evaluated as an expression and
- // the result of the expression must be a scalar that can be substituted
- // into the command. An example would be:
+ // The command preprocessor needs to do things to the command line before any
+ // parsing of arguments or anything else is done. The only current stuff that
+ // gets preprocessed is anything enclosed in backtick ('`') characters is
+ // evaluated as an expression and the result of the expression must be a
+ // scalar that can be substituted into the command. An example would be:
// (lldb) memory read `$rsp + 20`
Status error; // Status for any expressions that might not evaluate
size_t start_backtick;
size_t pos = 0;
while ((start_backtick = command.find('`', pos)) != std::string::npos) {
if (start_backtick > 0 && command[start_backtick - 1] == '\\') {
- // The backtick was preceded by a '\' character, remove the slash
- // and don't treat the backtick as the start of an expression
+ // The backtick was preceded by a '\' character, remove the slash and
+ // don't treat the backtick as the start of an expression
command.erase(start_backtick - 1, 1);
// No need to add one to start_backtick since we just deleted a char
pos = start_backtick;
@@ -1408,8 +1420,8 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) {
ExecutionContext exe_ctx(GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
// Get a dummy target to allow for calculator mode while processing
- // backticks.
- // This also helps break the infinite loop caused when target is null.
+ // backticks. This also helps break the infinite loop caused when
+ // target is null.
if (!target)
target = m_debugger.GetDummyTarget();
if (target) {
@@ -1561,8 +1573,8 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
const char *k_space_characters = "\t\n\v\f\r ";
size_t non_space = command_string.find_first_not_of(k_space_characters);
- // Check for empty line or comment line (lines whose first
- // non-space character is the comment character for this interpreter)
+ // Check for empty line or comment line (lines whose first non-space
+ // character is the comment character for this interpreter)
if (non_space == std::string::npos)
empty_command = true;
else if (command_string[non_space] == m_comment_char)
@@ -1635,8 +1647,8 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
// Although the user may have abbreviated the command, the command_string now
- // has the command expanded to the full name. For example, if the input
- // was "br s -n main", command_string is now "breakpoint set -n main".
+ // has the command expanded to the full name. For example, if the input was
+ // "br s -n main", command_string is now "breakpoint set -n main".
if (log) {
llvm::StringRef command_name = cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
log->Printf("HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
@@ -1650,8 +1662,8 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
// Phase 2.
// Take care of things like setting up the history command & calling the
- // appropriate Execute method on the
- // CommandObject, with the appropriate arguments.
+ // appropriate Execute method on the CommandObject, with the appropriate
+ // arguments.
if (cmd_obj != nullptr) {
if (add_to_history) {
@@ -1681,36 +1693,6 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
remainder.c_str());
cmd_obj->Execute(remainder.c_str(), result);
- } else {
- // We didn't find the first command object, so complete the first argument.
- Args command_args(command_string);
- StringList matches;
- int num_matches;
- int cursor_index = 0;
- int cursor_char_position = strlen(command_args.GetArgumentAtIndex(0));
- bool word_complete;
- num_matches = HandleCompletionMatches(command_args, cursor_index,
- cursor_char_position, 0, -1,
- word_complete, matches);
-
- if (num_matches > 0) {
- std::string error_msg;
- error_msg.assign("ambiguous command '");
- error_msg.append(command_args.GetArgumentAtIndex(0));
- error_msg.append("'.");
-
- error_msg.append(" Possible completions:");
- for (int i = 0; i < num_matches; i++) {
- error_msg.append("\n\t");
- error_msg.append(matches.GetStringAtIndex(i));
- }
- error_msg.append("\n");
- result.AppendRawError(error_msg.c_str());
- } else
- result.AppendErrorWithFormat("Unrecognized command '%s'.\n",
- command_args.GetArgumentAtIndex(0));
-
- result.SetStatus(eReturnStatusFailed);
}
if (log)
@@ -1720,60 +1702,58 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
return result.Succeeded();
}
-int CommandInterpreter::HandleCompletionMatches(
- Args &parsed_line, int &cursor_index, int &cursor_char_position,
- int match_start_point, int max_return_elements, bool &word_complete,
- StringList &matches) {
+int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
int num_command_matches = 0;
bool look_for_subcommand = false;
// For any of the command completions a unique match will be a complete word.
- word_complete = true;
+ request.SetWordComplete(true);
- if (cursor_index == -1) {
+ if (request.GetCursorIndex() == -1) {
// We got nothing on the command line, so return the list of commands
bool include_aliases = true;
+ StringList new_matches;
num_command_matches =
- GetCommandNamesMatchingPartialString("", include_aliases, matches);
- } else if (cursor_index == 0) {
+ GetCommandNamesMatchingPartialString("", include_aliases, new_matches);
+ request.AddCompletions(new_matches);
+ } else if (request.GetCursorIndex() == 0) {
// The cursor is in the first argument, so just do a lookup in the
// dictionary.
- CommandObject *cmd_obj =
- GetCommandObject(parsed_line.GetArgumentAtIndex(0), &matches);
- num_command_matches = matches.GetSize();
+ StringList new_matches;
+ CommandObject *cmd_obj = GetCommandObject(
+ request.GetParsedLine().GetArgumentAtIndex(0), &new_matches);
if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() &&
- matches.GetStringAtIndex(0) != nullptr &&
- strcmp(parsed_line.GetArgumentAtIndex(0),
- matches.GetStringAtIndex(0)) == 0) {
- if (parsed_line.GetArgumentCount() == 1) {
- word_complete = true;
+ new_matches.GetStringAtIndex(0) != nullptr &&
+ strcmp(request.GetParsedLine().GetArgumentAtIndex(0),
+ new_matches.GetStringAtIndex(0)) == 0) {
+ if (request.GetParsedLine().GetArgumentCount() == 1) {
+ request.SetWordComplete(true);
} else {
look_for_subcommand = true;
num_command_matches = 0;
- matches.DeleteStringAtIndex(0);
- parsed_line.AppendArgument(llvm::StringRef());
- cursor_index++;
- cursor_char_position = 0;
+ new_matches.DeleteStringAtIndex(0);
+ request.GetParsedLine().AppendArgument(llvm::StringRef());
+ request.SetCursorIndex(request.GetCursorIndex() + 1);
+ request.SetCursorCharPosition(0);
}
}
+ request.AddCompletions(new_matches);
+ num_command_matches = request.GetNumberOfMatches();
}
- if (cursor_index > 0 || look_for_subcommand) {
+ if (request.GetCursorIndex() > 0 || look_for_subcommand) {
// We are completing further on into a commands arguments, so find the
- // command and tell it
- // to complete the command.
- // First see if there is a matching initial command:
+ // command and tell it to complete the command. First see if there is a
+ // matching initial command:
CommandObject *command_object =
- GetCommandObject(parsed_line.GetArgumentAtIndex(0));
+ GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0));
if (command_object == nullptr) {
return 0;
} else {
- parsed_line.Shift();
- cursor_index--;
- num_command_matches = command_object->HandleCompletion(
- parsed_line, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+ request.GetParsedLine().Shift();
+ request.SetCursorIndex(request.GetCursorIndex() - 1);
+ num_command_matches = command_object->HandleCompletion(request);
}
}
@@ -1783,24 +1763,19 @@ int CommandInterpreter::HandleCompletionMatches(
int CommandInterpreter::HandleCompletion(
const char *current_line, const char *cursor, const char *last_char,
int match_start_point, int max_return_elements, StringList &matches) {
- // We parse the argument up to the cursor, so the last argument in parsed_line
- // is
- // the one containing the cursor, and the cursor is after the last character.
- Args parsed_line(llvm::StringRef(current_line, last_char - current_line));
- Args partial_parsed_line(
- llvm::StringRef(current_line, cursor - current_line));
+ llvm::StringRef command_line(current_line, last_char - current_line);
+ CompletionRequest request(command_line, cursor - current_line,
+ match_start_point, max_return_elements, matches);
// Don't complete comments, and if the line we are completing is just the
- // history repeat character,
- // substitute the appropriate history line.
- const char *first_arg = parsed_line.GetArgumentAtIndex(0);
+ // history repeat character, substitute the appropriate history line.
+ const char *first_arg = request.GetParsedLine().GetArgumentAtIndex(0);
if (first_arg) {
if (first_arg[0] == m_comment_char)
return 0;
else if (first_arg[0] == CommandHistory::g_repeat_char) {
if (auto hist_str = m_command_history.FindString(first_arg)) {
- matches.Clear();
matches.InsertStringAtIndex(0, *hist_str);
return -2;
} else
@@ -1808,74 +1783,31 @@ int CommandInterpreter::HandleCompletion(
}
}
- int num_args = partial_parsed_line.GetArgumentCount();
- int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
- int cursor_char_position;
-
- if (cursor_index == -1)
- cursor_char_position = 0;
- else
- cursor_char_position =
- strlen(partial_parsed_line.GetArgumentAtIndex(cursor_index));
-
- if (cursor > current_line && cursor[-1] == ' ') {
- // We are just after a space. If we are in an argument, then we will
- // continue
- // parsing, but if we are between arguments, then we have to complete
- // whatever the next
- // element would be.
- // We can distinguish the two cases because if we are in an argument (e.g.
- // because the space is
- // protected by a quote) then the space will also be in the parsed
- // argument...
-
- const char *current_elem =
- partial_parsed_line.GetArgumentAtIndex(cursor_index);
- if (cursor_char_position == 0 ||
- current_elem[cursor_char_position - 1] != ' ') {
- parsed_line.InsertArgumentAtIndex(cursor_index + 1, llvm::StringRef(),
- '\0');
- cursor_index++;
- cursor_char_position = 0;
- }
- }
-
- int num_command_matches;
-
- matches.Clear();
-
// Only max_return_elements == -1 is supported at present:
lldbassert(max_return_elements == -1);
- bool word_complete;
- num_command_matches = HandleCompletionMatches(
- parsed_line, cursor_index, cursor_char_position, match_start_point,
- max_return_elements, word_complete, matches);
+
+ int num_command_matches = HandleCompletionMatches(request);
if (num_command_matches <= 0)
return num_command_matches;
- if (num_args == 0) {
+ if (request.GetParsedLine().GetArgumentCount() == 0) {
// If we got an empty string, insert nothing.
matches.InsertStringAtIndex(0, "");
} else {
// Now figure out if there is a common substring, and if so put that in
- // element 0, otherwise
- // put an empty string in element 0.
- std::string command_partial_str;
- if (cursor_index >= 0)
- command_partial_str =
- parsed_line[cursor_index].ref.take_front(cursor_char_position);
+ // element 0, otherwise put an empty string in element 0.
+ std::string command_partial_str = request.GetCursorArgumentPrefix().str();
std::string common_prefix;
matches.LongestCommonPrefix(common_prefix);
const size_t partial_name_len = command_partial_str.size();
common_prefix.erase(0, partial_name_len);
- // If we matched a unique single command, add a space...
- // Only do this if the completer told us this was a complete word,
- // however...
- if (num_command_matches == 1 && word_complete) {
- char quote_char = parsed_line[cursor_index].quote;
+ // If we matched a unique single command, add a space... Only do this if
+ // the completer told us this was a complete word, however...
+ if (num_command_matches == 1 && request.GetWordComplete()) {
+ char quote_char = request.GetParsedLine()[request.GetCursorIndex()].quote;
common_prefix =
Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
if (quote_char != '\0')
@@ -1951,8 +1883,8 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
if (option_arg_vector_sp.get()) {
if (wants_raw_input) {
// We have a command that both has command options and takes raw input.
- // Make *sure* it has a
- // " -- " in the right place in the raw_input_string.
+ // Make *sure* it has a " -- " in the right place in the
+ // raw_input_string.
size_t pos = raw_input_string.find(" -- ");
if (pos == std::string::npos) {
// None found; assume it goes at the beginning of the raw input string
@@ -2036,10 +1968,9 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
} else {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
// This alias was not created with any options; nothing further needs to be
- // done, unless it is a command that
- // wants raw input, in which case we need to clear the rest of the data from
- // cmd_args, since its in the raw
- // input string.
+ // done, unless it is a command that wants raw input, in which case we need
+ // to clear the rest of the data from cmd_args, since its in the raw input
+ // string.
if (wants_raw_input) {
cmd_args.Clear();
cmd_args.SetArguments(new_args.GetArgumentCount(),
@@ -2069,7 +2000,8 @@ int CommandInterpreter::GetOptionArgumentPosition(const char *in_string) {
while (isdigit(cptr[0]))
++cptr;
- // We've gotten to the end of the digits; are we at the end of the string?
+ // We've gotten to the end of the digits; are we at the end of the
+ // string?
if (cptr[0] == '\0')
position = atoi(start);
}
@@ -2117,16 +2049,16 @@ void CommandInterpreter::SourceInitFile(bool in_cwd,
return;
}
} else if (should_load == eLoadCWDlldbinitTrue) {
- init_file.SetFile("./.lldbinit", true);
+ init_file.SetFile("./.lldbinit", true, FileSpec::Style::native);
}
}
} else {
- // If we aren't looking in the current working directory we are looking
- // in the home directory. We will first see if there is an application
- // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
- // "-" and the name of the program. If this file doesn't exist, we fall
- // back to just the "~/.lldbinit" file. We also obey any requests to not
- // load the init files.
+ // If we aren't looking in the current working directory we are looking in
+ // the home directory. We will first see if there is an application
+ // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a "-"
+ // and the name of the program. If this file doesn't exist, we fall back to
+ // just the "~/.lldbinit" file. We also obey any requests to not load the
+ // init files.
llvm::SmallString<64> home_dir_path;
llvm::sys::path::home_directory(home_dir_path);
FileSpec profilePath(home_dir_path.c_str(), false);
@@ -2141,19 +2073,19 @@ void CommandInterpreter::SourceInitFile(bool in_cwd,
char program_init_file_name[PATH_MAX];
::snprintf(program_init_file_name, sizeof(program_init_file_name),
"%s-%s", init_file_path.c_str(), program_name);
- init_file.SetFile(program_init_file_name, true);
+ init_file.SetFile(program_init_file_name, true,
+ FileSpec::Style::native);
if (!init_file.Exists())
init_file.Clear();
}
}
if (!init_file && !m_skip_lldbinit_files)
- init_file.SetFile(init_file_path, false);
+ init_file.SetFile(init_file_path, false, FileSpec::Style::native);
}
// If the file exists, tell HandleCommand to 'source' it; this will do the
- // actual broadcasting
- // of the commands back to any appropriate listener (see
+ // actual broadcasting of the commands back to any appropriate listener (see
// CommandObjectSource::Execute for more details).
if (init_file.Exists()) {
@@ -2199,15 +2131,14 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
size_t num_lines = commands.GetSize();
// If we are going to continue past a "continue" then we need to run the
- // commands synchronously.
- // Make sure you reset this value anywhere you return from the function.
+ // commands synchronously. Make sure you reset this value anywhere you return
+ // from the function.
bool old_async_execution = m_debugger.GetAsyncExecution();
// If we've been given an execution context, set it at the start, but don't
- // keep resetting it or we will
- // cause series of commands that change the context, then do an operation that
- // relies on that context to fail.
+ // keep resetting it or we will cause series of commands that change the
+ // context, then do an operation that relies on that context to fail.
if (override_context != nullptr)
UpdateExecutionContext(override_context);
@@ -2232,9 +2163,8 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
// HandleCommand() since we updated our context already.
// We might call into a regex or alias command, in which case the
- // add_to_history will get lost. This
- // m_command_source_depth dingus is the way we turn off adding to the
- // history in that case, so set it up here.
+ // add_to_history will get lost. This m_command_source_depth dingus is the
+ // way we turn off adding to the history in that case, so set it up here.
if (!options.GetAddToHistory())
m_command_source_depth++;
bool success =
@@ -2275,18 +2205,17 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
if (result.GetImmediateErrorStream())
result.GetImmediateErrorStream()->Flush();
- // N.B. Can't depend on DidChangeProcessState, because the state coming into
- // the command execution
- // could be running (for instance in Breakpoint Commands.
- // So we check the return value to see if it is has running in it.
+ // N.B. Can't depend on DidChangeProcessState, because the state coming
+ // into the command execution could be running (for instance in Breakpoint
+ // Commands. So we check the return value to see if it is has running in
+ // it.
if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
(tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) {
if (options.GetStopOnContinue()) {
// If we caused the target to proceed, and we're going to stop in that
- // case, set the
- // status in our real result before returning. This is an error if the
- // continue was not the
- // last command in the set of commands to be run.
+ // case, set the status in our real result before returning. This is
+ // an error if the continue was not the last command in the set of
+ // commands to be run.
if (idx != num_lines - 1)
result.AppendErrorWithFormat(
"Aborting reading of commands after command #%" PRIu64
@@ -2434,8 +2363,8 @@ void CommandInterpreter::HandleCommandsFromFile(
cmd_file_path.c_str());
}
- // Used for inheriting the right settings when "command source" might have
- // nested "command source" commands
+ // Used for inheriting the right settings when "command source" might
+ // have nested "command source" commands
lldb::StreamFileSP empty_stream_sp;
m_command_source_flags.push_back(flags);
IOHandlerSP io_handler_sp(new IOHandlerEditline(
@@ -2748,18 +2677,14 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
if (is_interactive == false) {
// When we are not interactive, don't execute blank lines. This will happen
// sourcing a commands file. We don't want blank lines to repeat the
- // previous
- // command and cause any errors to occur (like redefining an alias, get an
- // error
- // and stop parsing the commands file).
+ // previous command and cause any errors to occur (like redefining an
+ // alias, get an error and stop parsing the commands file).
if (line.empty())
return;
// When using a non-interactive file handle (like when sourcing commands
- // from a file)
- // we need to echo the command out so we don't just see the command output
- // and no
- // command...
+ // from a file) we need to echo the command out so we don't just see the
+ // command output and no command...
if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(),
line.c_str());
@@ -2916,13 +2841,13 @@ bool CommandInterpreter::IsActive() {
lldb::IOHandlerSP
CommandInterpreter::GetIOHandler(bool force_create,
CommandInterpreterRunOptions *options) {
- // Always re-create the IOHandlerEditline in case the input
- // changed. The old instance might have had a non-interactive
- // input and now it does or vice versa.
+ // Always re-create the IOHandlerEditline in case the input changed. The old
+ // instance might have had a non-interactive input and now it does or vice
+ // versa.
if (force_create || !m_command_io_handler_sp) {
- // Always re-create the IOHandlerEditline in case the input
- // changed. The old instance might have had a non-interactive
- // input and now it does or vice versa.
+ // Always re-create the IOHandlerEditline in case the input changed. The
+ // old instance might have had a non-interactive input and now it does or
+ // vice versa.
uint32_t flags = 0;
if (options) {
@@ -2956,8 +2881,8 @@ CommandInterpreter::GetIOHandler(bool force_create,
void CommandInterpreter::RunCommandInterpreter(
bool auto_handle_events, bool spawn_thread,
CommandInterpreterRunOptions &options) {
- // Always re-create the command interpreter when we run it in case
- // any file handles have changed.
+ // Always re-create the command interpreter when we run it in case any file
+ // handles have changed.
bool force_create = true;
m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
m_stopped_for_crash = false;
@@ -3009,8 +2934,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
actual_cmd_name_len = cmd_obj->GetCommandName().size();
}
} else {
- if (!cmd_obj)
- cmd_obj = GetCommandObject(next_word, &matches);
if (cmd_obj) {
llvm::StringRef cmd_name = cmd_obj->GetCommandName();
actual_cmd_name_len += cmd_name.size();
@@ -3025,8 +2948,8 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
CommandObject *sub_cmd_obj =
cmd_obj->GetSubcommandObject(next_word.c_str());
if (sub_cmd_obj) {
- // The subcommand's name includes the parent command's name,
- // so restart rather than append to the revised_command_line.
+ // The subcommand's name includes the parent command's name, so
+ // restart rather than append to the revised_command_line.
llvm::StringRef sub_cmd_name = sub_cmd_obj->GetCommandName();
actual_cmd_name_len = sub_cmd_name.size() + 1;
revised_command_line.Clear();
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
index 98a6a941864e..324b0b511220 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
@@ -90,8 +90,8 @@ void CommandObject::SetHelpLong(llvm::StringRef str) { m_cmd_help_long = str; }
void CommandObject::SetSyntax(llvm::StringRef str) { m_cmd_syntax = str; }
Options *CommandObject::GetOptions() {
- // By default commands don't have options unless this virtual function
- // is overridden by base classes.
+ // By default commands don't have options unless this virtual function is
+ // overridden by base classes.
return nullptr;
}
@@ -104,20 +104,16 @@ bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
options->NotifyOptionParsingStarting(&exe_ctx);
- // ParseOptions calls getopt_long_only, which always skips the zero'th item
- // in the array and starts at position 1,
- // so we need to push a dummy value into position zero.
- args.Unshift(llvm::StringRef("dummy_string"));
const bool require_validation = true;
- error = args.ParseOptions(*options, &exe_ctx,
- GetCommandInterpreter().GetPlatform(true),
- require_validation);
+ llvm::Expected<Args> args_or = options->Parse(
+ args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
+ require_validation);
- // The "dummy_string" will have already been removed by ParseOptions,
- // so no need to remove it.
-
- if (error.Success())
+ if (args_or) {
+ args = std::move(*args_or);
error = options->NotifyOptionParsingFinished(&exe_ctx);
+ } else
+ error = args_or.takeError();
if (error.Success()) {
if (options->VerifyOptions(result))
@@ -142,10 +138,10 @@ bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
bool CommandObject::CheckRequirements(CommandReturnObject &result) {
#ifdef LLDB_CONFIGURATION_DEBUG
- // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
- // has shared pointers to the target, process, thread and frame and we don't
- // want any CommandObject instances to keep any of these objects around
- // longer than for a single command. Every command should call
+ // Nothing should be stored in m_exe_ctx between running commands as
+ // m_exe_ctx has shared pointers to the target, process, thread and frame and
+ // we don't want any CommandObject instances to keep any of these objects
+ // around longer than for a single command. Every command should call
// CommandObject::Cleanup() after it has completed
assert(m_exe_ctx.GetTargetPtr() == NULL);
assert(m_exe_ctx.GetProcessPtr() == NULL);
@@ -153,9 +149,9 @@ bool CommandObject::CheckRequirements(CommandReturnObject &result) {
assert(m_exe_ctx.GetFramePtr() == NULL);
#endif
- // Lock down the interpreter's execution context prior to running the
- // command so we guarantee the selected target, process, thread and frame
- // can't go away during the execution
+ // Lock down the interpreter's execution context prior to running the command
+ // so we guarantee the selected target, process, thread and frame can't go
+ // away during the execution
m_exe_ctx = m_interpreter.GetExecutionContext();
const uint32_t flags = GetFlags().Get();
@@ -264,19 +260,13 @@ void CommandObject::Cleanup() {
m_api_locker.unlock();
}
-int CommandObject::HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete, StringList &matches) {
+int CommandObject::HandleCompletion(CompletionRequest &request) {
// Default implementation of WantsCompletion() is !WantsRawCommandString().
- // Subclasses who want raw command string but desire, for example,
- // argument completion should override WantsCompletion() to return true,
- // instead.
+ // Subclasses who want raw command string but desire, for example, argument
+ // completion should override WantsCompletion() to return true, instead.
if (WantsRawCommandString() && !WantsCompletion()) {
// FIXME: Abstract telling the completion to insert the completion
// character.
- matches.Clear();
return -1;
} else {
// Can we do anything generic with the options?
@@ -285,34 +275,17 @@ int CommandObject::HandleCompletion(Args &input, int &cursor_index,
OptionElementVector opt_element_vector;
if (cur_options != nullptr) {
- // Re-insert the dummy command name string which will have been
- // stripped off:
- input.Unshift(llvm::StringRef("dummy-string"));
- cursor_index++;
-
- // I stick an element on the end of the input, because if the last element
- // is option that requires an argument, getopt_long_only will freak out.
-
- input.AppendArgument(llvm::StringRef("<FAKE-VALUE>"));
-
- input.ParseArgsForCompletion(*cur_options, opt_element_vector,
- cursor_index);
+ opt_element_vector = cur_options->ParseForCompletion(
+ request.GetParsedLine(), request.GetCursorIndex());
- input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
-
- bool handled_by_options;
- handled_by_options = cur_options->HandleOptionCompletion(
- input, opt_element_vector, cursor_index, cursor_char_position,
- match_start_point, max_return_elements, GetCommandInterpreter(),
- word_complete, matches);
+ bool handled_by_options = cur_options->HandleOptionCompletion(
+ request, opt_element_vector, GetCommandInterpreter());
if (handled_by_options)
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
// If we got here, the last word is not an option or an option argument.
- return HandleArgumentCompletion(
- input, cursor_index, cursor_char_position, opt_element_vector,
- match_start_point, max_return_elements, word_complete, matches);
+ return HandleArgumentCompletion(request, opt_element_vector);
}
}
@@ -351,6 +324,22 @@ bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
return found_word;
}
+bool CommandObject::ParseOptionsAndNotify(Args &args,
+ CommandReturnObject &result,
+ OptionGroupOptions &group_options,
+ ExecutionContext &exe_ctx) {
+ if (!ParseOptions(args, result))
+ return false;
+
+ Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
+ if (error.Fail()) {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ return true;
+}
+
int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
CommandObject::CommandArgumentEntry *
@@ -441,9 +430,10 @@ OptSetFiltered(uint32_t opt_set_mask,
return ret_val;
}
-// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means take
-// all the argument data into account. On rare cases where some argument sticks
-// with certain option sets, this function returns the option set filtered args.
+// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
+// take all the argument data into account. On rare cases where some argument
+// sticks with certain option sets, this function returns the option set
+// filtered args.
void CommandObject::GetFormattedCommandArguments(Stream &str,
uint32_t opt_set_mask) {
int num_args = m_arguments.size();
@@ -483,8 +473,7 @@ void CommandObject::GetFormattedCommandArguments(Stream &str,
first_name, second_name);
break;
// Explicitly test for all the rest of the cases, so if new types get
- // added we will notice the
- // missing case statement(s).
+ // added we will notice the missing case statement(s).
case eArgRepeatPlain:
case eArgRepeatOptional:
case eArgRepeatPlus:
@@ -520,8 +509,7 @@ void CommandObject::GetFormattedCommandArguments(Stream &str,
str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
break;
// Explicitly test for all the rest of the cases, so if new types get
- // added we will notice the
- // missing case statement(s).
+ // added we will notice the missing case statement(s).
case eArgRepeatPairPlain:
case eArgRepeatPairOptional:
case eArgRepeatPairPlus:
@@ -529,8 +517,8 @@ void CommandObject::GetFormattedCommandArguments(Stream &str,
case eArgRepeatPairRange:
case eArgRepeatPairRangeOptional:
// These should not be hit, as they should pass the IsPairType test
- // above, and control should
- // have gone into the other branch of the if statement.
+ // above, and control should have gone into the other branch of the if
+ // statement.
break;
}
}
@@ -874,9 +862,8 @@ void CommandObject::GenerateHelpText(Stream &output_strm) {
if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
if (WantsRawCommandString() && !WantsCompletion()) {
// Emit the message about using ' -- ' between the end of the command
- // options and the raw input
- // conditionally, i.e., only if the command object does not want
- // completion.
+ // options and the raw input conditionally, i.e., only if the command
+ // object does not want completion.
interpreter.OutputFormattedHelpText(
output_strm, "", "",
"\nImportant Note: Because this command takes 'raw' input, if you "
@@ -916,8 +903,8 @@ void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg,
id_range_arg.arg_repetition = eArgRepeatOptional;
// The first (and only) argument for this command could be either an id or an
- // id_range.
- // Push both variants into the entry for the first argument for this command.
+ // id_range. Push both variants into the entry for the first argument for
+ // this command.
arg.push_back(id_arg);
arg.push_back(id_range_arg);
}
@@ -1021,7 +1008,8 @@ static llvm::StringRef arch_helper() {
static StreamString g_archs_help;
if (g_archs_help.Empty()) {
StringList archs;
- ArchSpec::AutoComplete(llvm::StringRef(), archs);
+
+ ArchSpec::ListSupportedArchNames(archs);
g_archs_help.Printf("These are the supported architecture names:\n");
archs.Join("\n", g_archs_help);
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
index 79d3bb1b5bee..ec89ad8fb162 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
@@ -35,53 +35,47 @@ CommandObjectRegexCommand::CommandObjectRegexCommand(
//----------------------------------------------------------------------
CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
-bool CommandObjectRegexCommand::DoExecute(const char *command,
+bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
- if (command) {
- EntryCollection::const_iterator pos, end = m_entries.end();
- for (pos = m_entries.begin(); pos != end; ++pos) {
- RegularExpression::Match regex_match(m_max_matches);
+ EntryCollection::const_iterator pos, end = m_entries.end();
+ for (pos = m_entries.begin(); pos != end; ++pos) {
+ RegularExpression::Match regex_match(m_max_matches);
- if (pos->regex.Execute(command, &regex_match)) {
- std::string new_command(pos->command);
- std::string match_str;
- char percent_var[8];
- size_t idx, percent_var_idx;
- for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
- if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
- const int percent_var_len =
- ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
- for (idx = 0; (percent_var_idx = new_command.find(
- percent_var, idx)) != std::string::npos;) {
- new_command.erase(percent_var_idx, percent_var_len);
- new_command.insert(percent_var_idx, match_str);
- idx += percent_var_idx + match_str.size();
- }
+ if (pos->regex.Execute(command, &regex_match)) {
+ std::string new_command(pos->command);
+ std::string match_str;
+ char percent_var[8];
+ size_t idx, percent_var_idx;
+ for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
+ if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
+ const int percent_var_len =
+ ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
+ for (idx = 0; (percent_var_idx = new_command.find(
+ percent_var, idx)) != std::string::npos;) {
+ new_command.erase(percent_var_idx, percent_var_len);
+ new_command.insert(percent_var_idx, match_str);
+ idx += percent_var_idx + match_str.size();
}
}
- // Interpret the new command and return this as the result!
- if (m_interpreter.GetExpandRegexAliases())
- result.GetOutputStream().Printf("%s\n", new_command.c_str());
- // Pass in true for "no context switching". The command that called us
- // should have set up the context
- // appropriately, we shouldn't have to redo that.
- return m_interpreter.HandleCommand(new_command.c_str(),
- eLazyBoolCalculate, result, nullptr,
- true, true);
}
+ // Interpret the new command and return this as the result!
+ if (m_interpreter.GetExpandRegexAliases())
+ result.GetOutputStream().Printf("%s\n", new_command.c_str());
+ // Pass in true for "no context switching". The command that called us
+ // should have set up the context appropriately, we shouldn't have to
+ // redo that.
+ return m_interpreter.HandleCommand(
+ new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
}
- result.SetStatus(eReturnStatusFailed);
- if (!GetSyntax().empty())
- result.AppendError(GetSyntax());
- else
- result.AppendErrorWithFormat("Command contents '%s' failed to match any "
- "regular expression in the '%s' regex "
- "command.\n",
- command, m_cmd_name.c_str());
- return false;
}
- result.AppendError("empty command passed to regular expression command");
result.SetStatus(eReturnStatusFailed);
+ if (!GetSyntax().empty())
+ result.AppendError(GetSyntax());
+ else
+ result.GetOutputStream() << "Command contents '" << command
+ << "' failed to match any "
+ "regular expression in the '"
+ << m_cmd_name << "' regex ";
return false;
}
@@ -99,23 +93,13 @@ bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
return false;
}
-int CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches) {
+int CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
if (m_completion_type_mask) {
- std::string completion_str(input.GetArgumentAtIndex(cursor_index),
- cursor_char_position);
CommandCompletions::InvokeCommonCompletionCallbacks(
- GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(),
- match_start_point, max_return_elements, nullptr, word_complete,
- matches);
- return matches.GetSize();
+ GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
+ return request.GetNumberOfMatches();
} else {
- matches.Clear();
- word_complete = false;
+ request.SetWordComplete(false);
}
return 0;
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp
index 0891298c5ac0..fa1516df60c9 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp
@@ -18,10 +18,10 @@
#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -40,7 +40,7 @@ CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter,
CommandObjectScript::~CommandObjectScript() {}
-bool CommandObjectScript::DoExecute(const char *command,
+bool CommandObjectScript::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
#ifdef LLDB_DISABLE_PYTHON
// if we ever support languages other than Python this simple #ifdef won't
@@ -69,7 +69,7 @@ bool CommandObjectScript::DoExecute(const char *command,
// for formatting.. make sure we keep up to
// date with it
- if (command == nullptr || command[0] == '\0') {
+ if (command.empty()) {
script_interpreter->ExecuteInterpreterLoop();
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
index 2c05ca9468d8..7a61b06e5b04 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
@@ -30,7 +30,7 @@ public:
~CommandObjectScript() override;
protected:
- bool DoExecute(const char *command, CommandReturnObject &result) override;
+ bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override;
};
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
index 75c02588066c..7c06e22c3909 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -25,8 +25,8 @@ static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s,
if (s.empty()) {
add_newline = add_newline_if_empty;
} else {
- // We already checked for empty above, now make sure there is a newline
- // in the error, and if there isn't one, add one.
+ // We already checked for empty above, now make sure there is a newline in
+ // the error, and if there isn't one, add one.
strm.Write(s.c_str(), s.size());
const char last_char = *s.rbegin();
@@ -127,8 +127,8 @@ void CommandReturnObject::SetError(llvm::StringRef error_str) {
SetStatus(eReturnStatusFailed);
}
-// Similar to AppendError, but do not prepend 'Status: ' to message, and
-// don't append "\n" to the end of it.
+// Similar to AppendError, but do not prepend 'Status: ' to message, and don't
+// append "\n" to the end of it.
void CommandReturnObject::AppendRawError(llvm::StringRef in_string) {
if (in_string.empty())
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionArgParser.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionArgParser.cpp
new file mode 100644
index 000000000000..3bd3af8fc50e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionArgParser.cpp
@@ -0,0 +1,253 @@
+//===-- OptionArgParser.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value,
+ bool *success_ptr) {
+ if (success_ptr)
+ *success_ptr = true;
+ ref = ref.trim();
+ if (ref.equals_lower("false") || ref.equals_lower("off") ||
+ ref.equals_lower("no") || ref.equals_lower("0")) {
+ return false;
+ } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
+ ref.equals_lower("yes") || ref.equals_lower("1")) {
+ return true;
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+char OptionArgParser::ToChar(llvm::StringRef s, char fail_value,
+ bool *success_ptr) {
+ if (success_ptr)
+ *success_ptr = false;
+ if (s.size() != 1)
+ return fail_value;
+
+ if (success_ptr)
+ *success_ptr = true;
+ return s[0];
+}
+
+int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s,
+ OptionEnumValueElement *enum_values,
+ int32_t fail_value, Status &error) {
+ error.Clear();
+ if (!enum_values) {
+ error.SetErrorString("invalid enumeration argument");
+ return fail_value;
+ }
+
+ if (s.empty()) {
+ error.SetErrorString("empty enumeration string");
+ return fail_value;
+ }
+
+ for (int i = 0; enum_values[i].string_value != nullptr; i++) {
+ llvm::StringRef this_enum(enum_values[i].string_value);
+ if (this_enum.startswith(s))
+ return enum_values[i].value;
+ }
+
+ StreamString strm;
+ strm.PutCString("invalid enumeration value, valid values are: ");
+ for (int i = 0; enum_values[i].string_value != nullptr; i++) {
+ strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
+ }
+ error.SetErrorString(strm.GetString());
+ return fail_value;
+}
+
+Status OptionArgParser::ToFormat(const char *s, lldb::Format &format,
+ size_t *byte_size_ptr) {
+ format = eFormatInvalid;
+ Status error;
+
+ if (s && s[0]) {
+ if (byte_size_ptr) {
+ if (isdigit(s[0])) {
+ char *format_char = nullptr;
+ unsigned long byte_size = ::strtoul(s, &format_char, 0);
+ if (byte_size != ULONG_MAX)
+ *byte_size_ptr = byte_size;
+ s = format_char;
+ } else
+ *byte_size_ptr = 0;
+ }
+
+ const bool partial_match_ok = true;
+ if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
+ StreamString error_strm;
+ error_strm.Printf(
+ "Invalid format character or name '%s'. Valid values are:\n", s);
+ for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
+ char format_char = FormatManager::GetFormatAsFormatChar(f);
+ if (format_char)
+ error_strm.Printf("'%c' or ", format_char);
+
+ error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
+ error_strm.EOL();
+ }
+
+ if (byte_size_ptr)
+ error_strm.PutCString(
+ "An optional byte size can precede the format character.\n");
+ error.SetErrorString(error_strm.GetString());
+ }
+
+ if (error.Fail())
+ return error;
+ } else {
+ error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
+ }
+ return error;
+}
+
+lldb::ScriptLanguage OptionArgParser::ToScriptLanguage(
+ llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) {
+ if (success_ptr)
+ *success_ptr = true;
+
+ if (s.equals_lower("python"))
+ return eScriptLanguagePython;
+ if (s.equals_lower("default"))
+ return eScriptLanguageDefault;
+ if (s.equals_lower("none"))
+ return eScriptLanguageNone;
+
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx,
+ llvm::StringRef s,
+ lldb::addr_t fail_value,
+ Status *error_ptr) {
+ bool error_set = false;
+ if (s.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
+ s.str().c_str());
+ return fail_value;
+ }
+
+ llvm::StringRef sref = s;
+
+ lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+ if (!s.getAsInteger(0, addr)) {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr;
+ }
+
+ // Try base 16 with no prefix...
+ if (!s.getAsInteger(16, addr)) {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr;
+ }
+
+ Target *target = nullptr;
+ if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
+ s.str().c_str());
+ return fail_value;
+ }
+
+ lldb::ValueObjectSP valobj_sp;
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(false);
+ options.SetTryAllThreads(true);
+
+ ExpressionResults expr_result =
+ target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options);
+
+ bool success = false;
+ if (expr_result == eExpressionCompleted) {
+ if (valobj_sp)
+ valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
+ valobj_sp->GetDynamicValueType(), true);
+ // Get the address to watch.
+ if (valobj_sp)
+ addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
+ if (success) {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr;
+ } else {
+ if (error_ptr) {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat(
+ "address expression \"%s\" resulted in a value whose type "
+ "can't be converted to an address: %s",
+ s.str().c_str(), valobj_sp->GetTypeName().GetCString());
+ }
+ }
+
+ } else {
+ // Since the compiler can't handle things like "main + 12" we should try to
+ // do this for now. The compiler doesn't like adding offsets to function
+ // pointer types.
+ static RegularExpression g_symbol_plus_offset_regex(
+ "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
+ RegularExpression::Match regex_match(3);
+ if (g_symbol_plus_offset_regex.Execute(sref, &regex_match)) {
+ uint64_t offset = 0;
+ bool add = true;
+ std::string name;
+ std::string str;
+ if (regex_match.GetMatchAtIndex(s, 1, name)) {
+ if (regex_match.GetMatchAtIndex(s, 2, str)) {
+ add = str[0] == '+';
+
+ if (regex_match.GetMatchAtIndex(s, 3, str)) {
+ if (!llvm::StringRef(str).getAsInteger(0, offset)) {
+ Status error;
+ addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS,
+ &error);
+ if (addr != LLDB_INVALID_ADDRESS) {
+ if (add)
+ return addr + offset;
+ else
+ return addr - offset;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (error_ptr) {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat(
+ "address expression \"%s\" evaluation failed", s.str().c_str());
+ }
+ }
+
+ if (error_ptr) {
+ if (!error_set)
+ error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
+ s.str().c_str());
+ }
+ return fail_value;
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp
index 5fd4ce7aecfa..e3759f2e60a1 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp
@@ -45,8 +45,8 @@ Status OptionGroupBoolean::SetOptionValue(uint32_t option_idx,
ExecutionContext *execution_context) {
Status error;
if (m_option_definition.option_has_arg == OptionParser::eNoArgument) {
- // Not argument, toggle the default value and mark the option as having been
- // set
+ // Not argument, toggle the default value and mark the option as having
+ // been set
m_value.SetCurrentValue(!m_value.GetDefaultValue());
m_value.SetOptionWasSet();
} else {
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp
index 75d8df950f18..b64c19324810 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp
@@ -102,8 +102,8 @@ Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,
// We the first character of the "gdb_format_str" is not the
// NULL terminator, we didn't consume the entire string and
- // something is wrong. Also, if none of the format, size or count
- // was specified correctly, then abort.
+ // something is wrong. Also, if none of the format, size or count was
+ // specified correctly, then abort.
if (!gdb_format_str.empty() ||
(format == eFormatInvalid && byte_size == 0 && count == 0)) {
// Nothing got set correctly
@@ -112,9 +112,8 @@ Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,
return error;
}
- // At least one of the format, size or count was set correctly.
- // Anything that wasn't set correctly should be set to the
- // previous default
+ // At least one of the format, size or count was set correctly. Anything
+ // that wasn't set correctly should be set to the previous default
if (format == eFormatInvalid)
ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
byte_size);
@@ -127,9 +126,8 @@ Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,
ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
byte_size);
} else {
- // Byte size is disabled, make sure it wasn't specified
- // but if this is an address, it's actually necessary to
- // specify one so don't error out
+ // Byte size is disabled, make sure it wasn't specified but if this is an
+ // address, it's actually necessary to specify one so don't error out
if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
error.SetErrorString(
"this command doesn't support specifying a byte size");
@@ -235,10 +233,9 @@ bool OptionGroupFormat::ParserGDBFormatLetter(
case 'w':
case 'g':
{
- // Size isn't used for printing instructions, so if a size is specified, and
- // the previous format was
- // 'i', then we should reset it to the default ('x'). Otherwise we'll
- // continue to print as instructions,
+ // Size isn't used for printing instructions, so if a size is specified,
+ // and the previous format was 'i', then we should reset it to the
+ // default ('x'). Otherwise we'll continue to print as instructions,
// which isn't expected.
if (format_letter == 'b')
byte_size = 1;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp
index 5747c6a8815d..47974276c8c0 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp
@@ -44,10 +44,8 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions(
if (platform_sp) {
interpreter.GetDebugger().GetPlatformList().Append(platform_sp,
make_selected);
- if (m_os_version_major != UINT32_MAX) {
- platform_sp->SetOSVersion(m_os_version_major, m_os_version_minor,
- m_os_version_update);
- }
+ if (!m_os_version.empty())
+ platform_sp->SetOSVersion(m_os_version);
if (m_sdk_sysroot)
platform_sp->SetSDKRootDirectory(m_sdk_sysroot);
@@ -64,9 +62,7 @@ void OptionGroupPlatform::OptionParsingStarting(
m_platform_name.clear();
m_sdk_sysroot.Clear();
m_sdk_build.Clear();
- m_os_version_major = UINT32_MAX;
- m_os_version_minor = UINT32_MAX;
- m_os_version_update = UINT32_MAX;
+ m_os_version = llvm::VersionTuple();
}
static OptionDefinition g_option_table[] = {
@@ -108,10 +104,9 @@ OptionGroupPlatform::SetOptionValue(uint32_t option_idx,
break;
case 'v':
- if (!Args::StringToVersion(option_arg, m_os_version_major,
- m_os_version_minor, m_os_version_update))
- error.SetErrorStringWithFormat("invalid version string '%s'",
- option_arg.str().c_str());
+ if (m_os_version.tryParse(option_arg))
+ error.SetErrorStringWithFormatv("invalid version string '{0}'",
+ option_arg);
break;
case 'b':
@@ -143,17 +138,8 @@ bool OptionGroupPlatform::PlatformMatches(
if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory())
return false;
- if (m_os_version_major != UINT32_MAX) {
- uint32_t major, minor, update;
- if (platform_sp->GetOSVersion(major, minor, update)) {
- if (m_os_version_major != major)
- return false;
- if (m_os_version_minor != minor)
- return false;
- if (m_os_version_update != update)
- return false;
- }
- }
+ if (!m_os_version.empty() && m_os_version != platform_sp->GetOSVersion())
+ return false;
return true;
}
return false;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index ce27d948c93c..54b45c29c70d 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -16,6 +16,7 @@
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
#include "llvm/ADT/ArrayRef.h"
@@ -85,8 +86,8 @@ Status OptionGroupValueObjectDisplay::SetOptionValue(
switch (short_option) {
case 'd': {
int32_t result;
- result =
- Args::StringToOptionEnum(option_arg, g_dynamic_value_types, 2, error);
+ result = OptionArgParser::ToOptionEnum(option_arg, g_dynamic_value_types, 2,
+ error);
if (error.Success())
use_dynamic = (lldb::DynamicValueType)result;
} break;
@@ -144,14 +145,14 @@ Status OptionGroupValueObjectDisplay::SetOptionValue(
break;
case 'S':
- use_synth = Args::StringToBoolean(option_arg, true, &success);
+ use_synth = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("invalid synthetic-type '%s'",
option_arg.str().c_str());
break;
case 'V':
- run_validator = Args::StringToBoolean(option_arg, true, &success);
+ run_validator = OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("invalid validate '%s'",
option_arg.str().c_str());
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp
index 0793d3731446..7b7a62be8743 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp
@@ -132,12 +132,12 @@ void OptionGroupVariable::OptionParsingStarting(
llvm::ArrayRef<OptionDefinition> OptionGroupVariable::GetDefinitions() {
auto result = llvm::makeArrayRef(g_variable_options);
- // Show the "--no-args", "--no-locals" and "--show-globals"
- // options if we are showing frame specific options
+ // Show the "--no-args", "--no-locals" and "--show-globals" options if we are
+ // showing frame specific options
if (include_frame_options)
return result;
- // Skip the "--no-args", "--no-locals" and "--show-globals"
- // options if we are not showing frame specific options (globals only)
+ // Skip the "--no-args", "--no-locals" and "--show-globals" options if we are
+ // not showing frame specific options (globals only)
return result.drop_front(NUM_FRAME_OPTS);
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
index dd4b8c86c910..0431fefaa7f9 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/lldb-enumerations.h"
using namespace lldb;
@@ -65,7 +65,7 @@ OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx,
switch (short_option) {
case 'w': {
WatchType tmp_watch_type;
- tmp_watch_type = (WatchType)Args::StringToOptionEnum(
+ tmp_watch_type = (WatchType)OptionArgParser::ToOptionEnum(
option_arg, g_option_table[option_idx].enum_values, 0, error);
if (error.Success()) {
watch_type = tmp_watch_type;
@@ -74,7 +74,7 @@ OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx,
break;
}
case 's':
- watch_size = (uint32_t)Args::StringToOptionEnum(
+ watch_size = (uint32_t)OptionArgParser::ToOptionEnum(
option_arg, g_option_table[option_idx].enum_values, 0, error);
break;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp
index afcace2567ce..c3f363b05988 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp
@@ -20,9 +20,8 @@ using namespace lldb;
using namespace lldb_private;
//-------------------------------------------------------------------------
-// Get this value as a uint64_t value if it is encoded as a boolean,
-// uint64_t or int64_t. Other types will cause "fail_value" to be
-// returned
+// Get this value as a uint64_t value if it is encoded as a boolean, uint64_t
+// or int64_t. Other types will cause "fail_value" to be returned
//-------------------------------------------------------------------------
uint64_t OptionValue::GetUInt64Value(uint64_t fail_value, bool *success_ptr) {
if (success_ptr)
@@ -508,8 +507,8 @@ const char *OptionValue::GetBuiltinTypeAsCString(Type t) {
lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask(
const char *value_cstr, uint32_t type_mask, Status &error) {
- // If only 1 bit is set in the type mask for a dictionary or array
- // then we know how to decode a value from a cstring
+ // If only 1 bit is set in the type mask for a dictionary or array then we
+ // know how to decode a value from a cstring
lldb::OptionValueSP value_sp;
switch (type_mask) {
case 1u << eTypeArch:
@@ -574,12 +573,9 @@ bool OptionValue::DumpQualifiedName(Stream &strm) const {
}
size_t OptionValue::AutoComplete(CommandInterpreter &interpreter,
- llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete,
- StringList &matches) {
- word_complete = false;
- matches.Clear();
- return matches.GetSize();
+ CompletionRequest &request) {
+ request.SetWordComplete(false);
+ return request.GetNumberOfMatches();
}
Status OptionValue::SetValueFromString(llvm::StringRef value,
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp
index 1d920a114723..d4f1fcb8a70a 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp
@@ -15,9 +15,9 @@
// Project includes
#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -74,13 +74,10 @@ lldb::OptionValueSP OptionValueArch::DeepCopy() const {
}
size_t OptionValueArch::AutoComplete(CommandInterpreter &interpreter,
- llvm::StringRef s, int match_start_point,
- int max_return_elements,
- bool &word_complete, StringList &matches) {
- word_complete = false;
- matches.Clear();
+ CompletionRequest &request) {
+ request.SetWordComplete(false);
CommandCompletions::InvokeCommonCompletionCallbacks(
- interpreter, CommandCompletions::eArchitectureCompletion, s,
- match_start_point, max_return_elements, nullptr, word_complete, matches);
- return matches.GetSize();
+ interpreter, CommandCompletions::eArchitectureCompletion, request,
+ nullptr);
+ return request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp
index 8edec77f9d2d..26e438548ea3 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp
@@ -13,7 +13,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp
index 8b62070352a6..d3fd1cb5db48 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp
index 2cb84cd6abb3..94c774d69111 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/PosixApi.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
#include "llvm/ADT/STLExtras.h"
@@ -47,7 +47,7 @@ Status OptionValueBoolean::SetValueFromString(llvm::StringRef value_str,
case eVarSetOperationReplace:
case eVarSetOperationAssign: {
bool success = false;
- bool value = Args::StringToBoolean(value_str, false, &success);
+ bool value = OptionArgParser::ToBoolean(value_str, false, &success);
if (success) {
m_value_was_set = true;
m_current_value = value;
@@ -76,23 +76,21 @@ lldb::OptionValueSP OptionValueBoolean::DeepCopy() const {
return OptionValueSP(new OptionValueBoolean(*this));
}
-size_t OptionValueBoolean::AutoComplete(
- CommandInterpreter &interpreter, llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
- word_complete = false;
- matches.Clear();
+size_t OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) {
+ request.SetWordComplete(false);
static const llvm::StringRef g_autocomplete_entries[] = {
"true", "false", "on", "off", "yes", "no", "1", "0"};
auto entries = llvm::makeArrayRef(g_autocomplete_entries);
// only suggest "true" or "false" by default
- if (s.empty())
+ if (request.GetCursorArgumentPrefix().empty())
entries = entries.take_front(2);
for (auto entry : entries) {
- if (entry.startswith_lower(s))
- matches.AppendString(entry);
+ if (entry.startswith_lower(request.GetCursorArgumentPrefix()))
+ request.AddCompletion(entry);
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp
index 27684a27264d..21fe88014724 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp
@@ -13,7 +13,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
#include "llvm/ADT/STLExtras.h"
@@ -47,7 +47,7 @@ Status OptionValueChar::SetValueFromString(llvm::StringRef value,
case eVarSetOperationReplace:
case eVarSetOperationAssign: {
bool success = false;
- char char_value = Args::StringToChar(value, '\0', &success);
+ char char_value = OptionArgParser::ToChar(value, '\0', &success);
if (success) {
m_current_value = char_value;
m_value_was_set = true;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp
index a57ede486319..2e8a8427237b 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -16,8 +16,8 @@
// Project includes
#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Utility/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -128,9 +128,7 @@ Status OptionValueDictionary::SetArgs(const Args &args,
if (key.front() == '[') {
// Key name starts with '[', so the key value must be in single or
- // double quotes like:
- // ['<key>']
- // ["<key>"]
+ // double quotes like: ['<key>'] ["<key>"]
if ((key.size() > 2) && (key.back() == ']')) {
// Strip leading '[' and trailing ']'
key = key.substr(1, key.size() - 2);
@@ -286,8 +284,8 @@ OptionValueDictionary::GetValueForKey(const ConstString &key) const {
bool OptionValueDictionary::SetValueForKey(const ConstString &key,
const lldb::OptionValueSP &value_sp,
bool can_replace) {
- // Make sure the value_sp object is allowed to contain
- // values of the type passed in...
+ // Make sure the value_sp object is allowed to contain values of the type
+ // passed in...
if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
if (!can_replace) {
collection::const_iterator pos = m_values.find(key);
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp
index 9510f4a671d1..c7cbcab7fcc8 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp
@@ -109,23 +109,21 @@ lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const {
return OptionValueSP(new OptionValueEnumeration(*this));
}
-size_t OptionValueEnumeration::AutoComplete(
- CommandInterpreter &interpreter, llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
- word_complete = false;
- matches.Clear();
+size_t OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) {
+ request.SetWordComplete(false);
const uint32_t num_enumerators = m_enumerations.GetSize();
- if (!s.empty()) {
+ if (!request.GetCursorArgumentPrefix().empty()) {
for (size_t i = 0; i < num_enumerators; ++i) {
llvm::StringRef name = m_enumerations.GetCStringAtIndex(i).GetStringRef();
- if (name.startswith(s))
- matches.AppendString(name);
+ if (name.startswith(request.GetCursorArgumentPrefix()))
+ request.AddCompletion(name);
}
} else {
// only suggest "true" or "false" by default
for (size_t i = 0; i < num_enumerators; ++i)
- matches.AppendString(m_enumerations.GetCStringAtIndex(i).GetStringRef());
+ request.AddCompletion(m_enumerations.GetCStringAtIndex(i).GetStringRef());
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp
index 7d17ddec4f9c..2b93628679ce 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp
@@ -12,9 +12,9 @@
#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/FileSystem.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBufferLLVM.h"
using namespace lldb;
@@ -67,18 +67,15 @@ Status OptionValueFileSpec::SetValueFromString(llvm::StringRef value,
case eVarSetOperationAssign:
if (value.size() > 0) {
// The setting value may have whitespace, double-quotes, or single-quotes
- // around the file
- // path to indicate that internal spaces are not word breaks. Strip off
- // any ws & quotes
- // from the start and end of the file path - we aren't doing any word //
- // breaking here so
- // the quoting is unnecessary. NB this will cause a problem if someone
- // tries to specify
+ // around the file path to indicate that internal spaces are not word
+ // breaks. Strip off any ws & quotes from the start and end of the file
+ // path - we aren't doing any word // breaking here so the quoting is
+ // unnecessary. NB this will cause a problem if someone tries to specify
// a file path that legitimately begins or ends with a " or ' character,
// or whitespace.
value = value.trim("\"' \t");
m_value_was_set = true;
- m_current_value.SetFile(value.str(), m_resolve);
+ m_current_value.SetFile(value.str(), m_resolve, FileSpec::Style::native);
m_data_sp.reset();
m_data_mod_time = llvm::sys::TimePoint<>();
NotifyValueChanged();
@@ -102,15 +99,12 @@ lldb::OptionValueSP OptionValueFileSpec::DeepCopy() const {
return OptionValueSP(new OptionValueFileSpec(*this));
}
-size_t OptionValueFileSpec::AutoComplete(
- CommandInterpreter &interpreter, llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
- word_complete = false;
- matches.Clear();
+size_t OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) {
+ request.SetWordComplete(false);
CommandCompletions::InvokeCommonCompletionCallbacks(
- interpreter, m_completion_mask, s, match_start_point, max_return_elements,
- nullptr, word_complete, matches);
- return matches.GetSize();
+ interpreter, m_completion_mask, request, nullptr);
+ return request.GetNumberOfMatches();
}
const lldb::DataBufferSP &OptionValueFileSpec::GetFileContents() {
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp
index 7773bdc5ea9c..7fdc3c780239 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp
index 24dd8fd5f71c..1837804a4622 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
@@ -43,7 +43,7 @@ Status OptionValueFormat::SetValueFromString(llvm::StringRef value,
case eVarSetOperationReplace:
case eVarSetOperationAssign: {
Format new_format;
- error = Args::StringToFormat(value.str().c_str(), new_format, nullptr);
+ error = OptionArgParser::ToFormat(value.str().c_str(), new_format, nullptr);
if (error.Success()) {
m_value_was_set = true;
m_current_value = new_format;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormatEntity.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormatEntity.cpp
index e9431d4562ec..ce1a84e8dece 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormatEntity.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormatEntity.cpp
@@ -64,12 +64,10 @@ Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
case eVarSetOperationReplace:
case eVarSetOperationAssign: {
// Check if the string starts with a quote character after removing leading
- // and trailing spaces.
- // If it does start with a quote character, make sure it ends with the same
- // quote character
- // and remove the quotes before we parse the format string. If the string
- // doesn't start with
- // a quote, leave the string alone and parse as is.
+ // and trailing spaces. If it does start with a quote character, make sure
+ // it ends with the same quote character and remove the quotes before we
+ // parse the format string. If the string doesn't start with a quote, leave
+ // the string alone and parse as is.
llvm::StringRef trimmed_value_str = value_str.trim();
if (!trimmed_value_str.empty()) {
const char first_char = trimmed_value_str[0];
@@ -107,9 +105,7 @@ lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const {
return OptionValueSP(new OptionValueFormatEntity(*this));
}
-size_t OptionValueFormatEntity::AutoComplete(
- CommandInterpreter &interpreter, llvm::StringRef s, int match_start_point,
- int max_return_elements, bool &word_complete, StringList &matches) {
- return FormatEntity::AutoComplete(s, match_start_point, max_return_elements,
- word_complete, matches);
+size_t OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter,
+ CompletionRequest &request) {
+ return FormatEntity::AutoComplete(request);
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp
index 3290e88c1815..1a82329bf0f3 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp
@@ -14,8 +14,8 @@
// Other libraries and framework includes
// Project includes
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/Language.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp
index 5f805720bd3f..8390a8cf5aba 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
index ae7669605592..c1887f34b712 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -16,9 +16,9 @@
#include "lldb/Utility/Flags.h"
#include "lldb/Core/UserSettingsController.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Interpreter/Property.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
@@ -35,15 +35,13 @@ OptionValueProperties::OptionValueProperties(
m_name(global_properties.m_name),
m_properties(global_properties.m_properties),
m_name_to_index(global_properties.m_name_to_index) {
- // We now have an exact copy of "global_properties". We need to now
- // find all non-global settings and copy the property values so that
- // all non-global settings get new OptionValue instances created for
- // them.
+ // We now have an exact copy of "global_properties". We need to now find all
+ // non-global settings and copy the property values so that all non-global
+ // settings get new OptionValue instances created for them.
const size_t num_properties = m_properties.size();
for (size_t i = 0; i < num_properties; ++i) {
// Duplicate any values that are not global when constructing properties
- // from
- // a global copy
+ // from a global copy
if (m_properties[i].IsGlobal() == false) {
lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
m_properties[i].SetOptionValue(new_value_sp);
@@ -157,15 +155,13 @@ OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
case '{':
// Predicate matching for predicates like
// "<setting-name>{<predicate>}"
- // strings are parsed by the current OptionValueProperties subclass
- // to mean whatever they want to. For instance a subclass of
- // OptionValueProperties for a lldb_private::Target might implement:
- // "target.run-args{arch==i386}" -- only set run args if the arch is
- // i386
- // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the
- // path matches
- // "target.run-args{basename==test&&arch==x86_64}" -- only set run args
- // if executable basename is "test" and arch is "x86_64"
+ // strings are parsed by the current OptionValueProperties subclass to mean
+ // whatever they want to. For instance a subclass of OptionValueProperties
+ // for a lldb_private::Target might implement: "target.run-
+ // args{arch==i386}" -- only set run args if the arch is i386 "target
+ // .run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path
+ // matches "target.run-args{basename==test&&arch==x86_64}" -- only set run
+ // args if executable basename is "test" and arch is "x86_64"
if (sub_name[1]) {
llvm::StringRef predicate_start = sub_name.drop_front();
size_t pos = predicate_start.find_first_of('}');
@@ -189,9 +185,8 @@ OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
break;
case '[':
- // Array or dictionary access for subvalues like:
- // "[12]" -- access 12th array element
- // "['hello']" -- dictionary access of key named hello
+ // Array or dictionary access for subvalues like: "[12]" -- access
+ // 12th array element "['hello']" -- dictionary access of key named hello
return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
default:
@@ -207,12 +202,23 @@ Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
llvm::StringRef value) {
Status error;
const bool will_modify = true;
+ llvm::SmallVector<llvm::StringRef, 8> components;
+ name.split(components, '.');
+ bool name_contains_experimental = false;
+ for (const auto &part : components)
+ if (Properties::IsSettingExperimental(part))
+ name_contains_experimental = true;
+
+
lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
if (value_sp)
error = value_sp->SetValueFromString(value, op);
else {
- if (error.AsCString() == nullptr)
+ // Don't set an error if the path contained .experimental. - those are
+ // allowed to be missing and should silently fail.
+ if (name_contains_experimental == false && error.AsCString() == nullptr) {
error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
+ }
}
return error;
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp
index 9dbcd58dc3e9..ddd1b9662ca3 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp
@@ -21,7 +21,8 @@ using namespace lldb_private;
void OptionValueSInt64::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) {
- // printf ("%p: DumpValue (exe_ctx=%p, strm, mask) m_current_value = %" PRIi64
+ // printf ("%p: DumpValue (exe_ctx=%p, strm, mask) m_current_value = %"
+ // PRIi64
// "\n", this, exe_ctx, m_current_value);
if (dump_mask & eDumpOptionType)
strm.Printf("(%s)", GetTypeAsCString());
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp
index 1d7332dd41a6..8383b531270b 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp
@@ -15,7 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp
index bec04cba8c37..355e07bb2b5f 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp
@@ -43,7 +43,7 @@ Status OptionValueUUID::SetValueFromString(llvm::StringRef value,
case eVarSetOperationReplace:
case eVarSetOperationAssign: {
- if (m_uuid.SetFromCString(value.str().c_str()) == 0)
+ if (m_uuid.SetFromStringRef(value) == 0)
error.SetErrorStringWithFormat("invalid uuid string value '%s'",
value.str().c_str());
else {
@@ -68,40 +68,29 @@ lldb::OptionValueSP OptionValueUUID::DeepCopy() const {
}
size_t OptionValueUUID::AutoComplete(CommandInterpreter &interpreter,
- llvm::StringRef s, int match_start_point,
- int max_return_elements,
- bool &word_complete, StringList &matches) {
- word_complete = false;
- matches.Clear();
+ CompletionRequest &request) {
+ request.SetWordComplete(false);
ExecutionContext exe_ctx(interpreter.GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
if (target) {
- const size_t num_modules = target->GetImages().GetSize();
- if (num_modules > 0) {
- UUID::ValueType uuid_bytes;
- uint32_t num_bytes_decoded = 0;
- UUID::DecodeUUIDBytesFromString(s, uuid_bytes, num_bytes_decoded);
+ auto prefix = request.GetCursorArgumentPrefix();
+ llvm::SmallVector<uint8_t, 20> uuid_bytes;
+ if (UUID::DecodeUUIDBytesFromString(prefix, uuid_bytes).empty()) {
+ const size_t num_modules = target->GetImages().GetSize();
for (size_t i = 0; i < num_modules; ++i) {
ModuleSP module_sp(target->GetImages().GetModuleAtIndex(i));
if (module_sp) {
const UUID &module_uuid = module_sp->GetUUID();
if (module_uuid.IsValid()) {
- bool add_uuid = false;
- if (num_bytes_decoded == 0)
- add_uuid = true;
- else
- add_uuid = ::memcmp(module_uuid.GetBytes(), uuid_bytes,
- num_bytes_decoded) == 0;
- if (add_uuid) {
- std::string uuid_str;
- uuid_str = module_uuid.GetAsString();
- if (!uuid_str.empty())
- matches.AppendString(uuid_str.c_str());
+ llvm::ArrayRef<uint8_t> module_bytes = module_uuid.GetBytes();
+ if (module_bytes.size() >= uuid_bytes.size() &&
+ module_bytes.take_front(uuid_bytes.size()).equals(uuid_bytes)) {
+ request.AddCompletion(module_uuid.GetAsString());
}
}
}
}
}
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
index f8b1a8d6beba..c9567e91f6b8 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
@@ -115,13 +115,12 @@ bool Options::VerifyOptions(CommandReturnObject &result) {
int num_levels = GetRequiredOptions().size();
if (num_levels) {
for (int i = 0; i < num_levels && !options_are_valid; ++i) {
- // This is the correct set of options if: 1). m_seen_options contains all
- // of m_required_options[i]
- // (i.e. all the required options at this level are a subset of
- // m_seen_options); AND
- // 2). { m_seen_options - m_required_options[i] is a subset of
- // m_options_options[i] (i.e. all the rest of
- // m_seen_options are in the set of optional options at this level.
+ // This is the correct set of options if: 1). m_seen_options contains
+ // all of m_required_options[i] (i.e. all the required options at this
+ // level are a subset of m_seen_options); AND 2). { m_seen_options -
+ // m_required_options[i] is a subset of m_options_options[i] (i.e. all
+ // the rest of m_seen_options are in the set of optional options at this
+ // level.
// Check to see if all of m_required_options[i] are a subset of
// m_seen_options
@@ -152,8 +151,7 @@ bool Options::VerifyOptions(CommandReturnObject &result) {
}
// This is called in the Options constructor, though we could call it lazily if
-// that ends up being
-// a performance problem.
+// that ends up being a performance problem.
void Options::BuildValidOptionSets() {
// Check to see if we already did this.
@@ -265,13 +263,11 @@ Option *Options::GetLongOptions() {
}
// This function takes INDENT, which tells how many spaces to output at the
-// front of each line; SPACES, which is
-// a string containing 80 spaces; and TEXT, which is the text that is to be
-// output. It outputs the text, on
+// front of each line; SPACES, which is a string containing 80 spaces; and
+// TEXT, which is the text that is to be output. It outputs the text, on
// multiple lines if necessary, to RESULT, with INDENT spaces at the front of
-// each line. It breaks lines on spaces,
-// tabs or newlines, shortening the line if necessary to not break in the middle
-// of a word. It assumes that each
+// each line. It breaks lines on spaces, tabs or newlines, shortening the line
+// if necessary to not break in the middle of a word. It assumes that each
// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
void Options::OutputFormattedUsageText(Stream &strm,
@@ -421,8 +417,8 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
strm.IndentMore(2);
- // First, show each usage level set of options, e.g. <cmd>
- // [options-for-level-0]
+ // First, show each usage level set of options, e.g. <cmd> [options-for-
+ // level-0]
// <cmd>
// [options-for-level-1]
// etc.
@@ -449,9 +445,9 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
if (cmd)
cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
- // First go through and print all options that take no arguments as
- // a single string. If a command has "-a" "-b" and "-c", this will show
- // up as [-abc]
+ // First go through and print all options that take no arguments as a
+ // single string. If a command has "-a" "-b" and "-c", this will show up
+ // as [-abc]
std::set<int> options;
std::set<int>::const_iterator options_pos, options_end;
@@ -554,24 +550,23 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
// help text
// This variable is used to keep track of which options' info we've printed
- // out, because some options can be in
- // more than one usage level, but we only want to print the long form of its
- // information once.
+ // out, because some options can be in more than one usage level, but we
+ // only want to print the long form of its information once.
std::multimap<int, uint32_t> options_seen;
strm.IndentMore(5);
// Put the unique command options in a vector & sort it, so we can output
- // them alphabetically (by short_option)
- // when writing out detailed help for each option.
+ // them alphabetically (by short_option) when writing out detailed help for
+ // each option.
i = 0;
for (auto &def : opt_defs)
options_seen.insert(std::make_pair(def.short_option, i++));
- // Go through the unique'd and alphabetically sorted vector of options, find
- // the table entry for each option
- // and write out the detailed help information for that option.
+ // Go through the unique'd and alphabetically sorted vector of options,
+ // find the table entry for each option and write out the detailed help
+ // information for that option.
bool first_option_printed = false;
@@ -627,14 +622,10 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
}
// This function is called when we have been given a potentially incomplete set
-// of
-// options, such as when an alias has been defined (more options might be added
-// at
-// at the time the alias is invoked). We need to verify that the options in the
-// set
-// m_seen_options are all part of a set that may be used together, but
-// m_seen_options
-// may be missing some of the "required" options.
+// of options, such as when an alias has been defined (more options might be
+// added at at the time the alias is invoked). We need to verify that the
+// options in the set m_seen_options are all part of a set that may be used
+// together, but m_seen_options may be missing some of the "required" options.
bool Options::VerifyPartialOptions(CommandReturnObject &result) {
bool options_are_valid = false;
@@ -643,10 +634,8 @@ bool Options::VerifyPartialOptions(CommandReturnObject &result) {
if (num_levels) {
for (int i = 0; i < num_levels && !options_are_valid; ++i) {
// In this case we are treating all options as optional rather than
- // required.
- // Therefore a set of options is correct if m_seen_options is a subset of
- // the
- // union of m_required_options and m_optional_options.
+ // required. Therefore a set of options is correct if m_seen_options is a
+ // subset of the union of m_required_options and m_optional_options.
OptionSet union_set;
OptionsSetUnion(GetRequiredOptions()[i], GetOptionalOptions()[i],
union_set);
@@ -658,28 +647,26 @@ bool Options::VerifyPartialOptions(CommandReturnObject &result) {
return options_are_valid;
}
-bool Options::HandleOptionCompletion(
- Args &input, OptionElementVector &opt_element_vector, int cursor_index,
- int char_pos, int match_start_point, int max_return_elements,
- CommandInterpreter &interpreter, bool &word_complete,
- lldb_private::StringList &matches) {
- word_complete = true;
+bool Options::HandleOptionCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector,
+ CommandInterpreter &interpreter) {
+ request.SetWordComplete(true);
// For now we just scan the completions to see if the cursor position is in
// an option or its argument. Otherwise we'll call HandleArgumentCompletion.
- // In the future we can use completion to validate options as well if we want.
+ // In the future we can use completion to validate options as well if we
+ // want.
auto opt_defs = GetDefinitions();
- std::string cur_opt_std_str(input.GetArgumentAtIndex(cursor_index));
- cur_opt_std_str.erase(char_pos);
+ std::string cur_opt_std_str = request.GetCursorArgumentPrefix().str();
const char *cur_opt_str = cur_opt_std_str.c_str();
for (size_t i = 0; i < opt_element_vector.size(); i++) {
int opt_pos = opt_element_vector[i].opt_pos;
int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
int opt_defs_index = opt_element_vector[i].opt_defs_index;
- if (opt_pos == cursor_index) {
+ if (opt_pos == request.GetCursorIndex()) {
// We're completing the option itself.
if (opt_defs_index == OptionArgElement::eBareDash) {
@@ -693,7 +680,7 @@ bool Options::HandleOptionCompletion(
if (!def.short_option)
continue;
opt_str[1] = def.short_option;
- matches.AppendString(opt_str);
+ request.AddCompletion(opt_str);
}
return true;
@@ -705,25 +692,23 @@ bool Options::HandleOptionCompletion(
full_name.erase(full_name.begin() + 2, full_name.end());
full_name.append(def.long_option);
- matches.AppendString(full_name.c_str());
+ request.AddCompletion(full_name.c_str());
}
return true;
} else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) {
- // We recognized it, if it an incomplete long option, complete it anyway
- // (getopt_long_only is
- // happy with shortest unique string, but it's still a nice thing to
- // do.) Otherwise return
- // The string so the upper level code will know this is a full match and
- // add the " ".
+ // We recognized it, if it an incomplete long option, complete it
+ // anyway (getopt_long_only is happy with shortest unique string, but
+ // it's still a nice thing to do.) Otherwise return The string so the
+ // upper level code will know this is a full match and add the " ".
if (cur_opt_str && strlen(cur_opt_str) > 2 && cur_opt_str[0] == '-' &&
cur_opt_str[1] == '-' &&
strcmp(opt_defs[opt_defs_index].long_option, cur_opt_str) != 0) {
std::string full_name("--");
full_name.append(opt_defs[opt_defs_index].long_option);
- matches.AppendString(full_name.c_str());
+ request.AddCompletion(full_name.c_str());
return true;
} else {
- matches.AppendString(input.GetArgumentAtIndex(cursor_index));
+ request.AddCompletion(request.GetCursorArgument());
return true;
}
} else {
@@ -731,9 +716,8 @@ bool Options::HandleOptionCompletion(
// Check to see if they are writing a long option & complete it.
// I think we will only get in here if the long option table has two
// elements
- // that are not unique up to this point. getopt_long_only does shortest
- // unique match
- // for long options already.
+ // that are not unique up to this point. getopt_long_only does
+ // shortest unique match for long options already.
if (cur_opt_str && strlen(cur_opt_str) > 2 && cur_opt_str[0] == '-' &&
cur_opt_str[1] == '-') {
@@ -744,32 +728,23 @@ bool Options::HandleOptionCompletion(
if (strstr(def.long_option, cur_opt_str + 2) == def.long_option) {
std::string full_name("--");
full_name.append(def.long_option);
- // The options definitions table has duplicates because of the
- // way the grouping information is stored, so only add once.
- bool duplicate = false;
- for (size_t k = 0; k < matches.GetSize(); k++) {
- if (matches.GetStringAtIndex(k) == full_name) {
- duplicate = true;
- break;
- }
- }
- if (!duplicate)
- matches.AppendString(full_name.c_str());
+ request.AddCompletion(full_name.c_str());
}
}
}
return true;
}
- } else if (opt_arg_pos == cursor_index) {
- // Okay the cursor is on the completion of an argument.
- // See if it has a completion, otherwise return no matches.
+ } else if (opt_arg_pos == request.GetCursorIndex()) {
+ // Okay the cursor is on the completion of an argument. See if it has a
+ // completion, otherwise return no matches.
+ CompletionRequest subrequest = request;
+ subrequest.SetCursorCharPosition(subrequest.GetCursorArgument().size());
if (opt_defs_index != -1) {
- HandleOptionArgumentCompletion(
- input, cursor_index, strlen(input.GetArgumentAtIndex(cursor_index)),
- opt_element_vector, i, match_start_point, max_return_elements,
- interpreter, word_complete, matches);
+ HandleOptionArgumentCompletion(subrequest, opt_element_vector, i,
+ interpreter);
+ request.SetWordComplete(subrequest.GetWordComplete());
return true;
} else {
// No completion callback means no completions...
@@ -785,11 +760,8 @@ bool Options::HandleOptionCompletion(
}
bool Options::HandleOptionArgumentCompletion(
- Args &input, int cursor_index, int char_pos,
- OptionElementVector &opt_element_vector, int opt_element_index,
- int match_start_point, int max_return_elements,
- CommandInterpreter &interpreter, bool &word_complete,
- lldb_private::StringList &matches) {
+ CompletionRequest &request, OptionElementVector &opt_element_vector,
+ int opt_element_index, CommandInterpreter &interpreter) {
auto opt_defs = GetDefinitions();
std::unique_ptr<SearchFilter> filter_ap;
@@ -801,22 +773,23 @@ bool Options::HandleOptionArgumentCompletion(
OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
if (enum_values != nullptr) {
bool return_value = false;
- std::string match_string(input.GetArgumentAtIndex(opt_arg_pos),
- input.GetArgumentAtIndex(opt_arg_pos) + char_pos);
+ std::string match_string(
+ request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos),
+ request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos) +
+ request.GetCursorCharPosition());
for (int i = 0; enum_values[i].string_value != nullptr; i++) {
if (strstr(enum_values[i].string_value, match_string.c_str()) ==
enum_values[i].string_value) {
- matches.AppendString(enum_values[i].string_value);
+ request.AddCompletion(enum_values[i].string_value);
return_value = true;
}
}
return return_value;
}
- // If this is a source file or symbol type completion, and there is a
- // -shlib option somewhere in the supplied arguments, then make a search
- // filter
- // for that shared library.
+ // If this is a source file or symbol type completion, and there is a -shlib
+ // option somewhere in the supplied arguments, then make a search filter for
+ // that shared library.
// FIXME: Do we want to also have an "OptionType" so we don't have to match
// string names?
@@ -852,7 +825,8 @@ bool Options::HandleOptionArgumentCompletion(
// restrict it to that shared library.
if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 &&
cur_arg_pos != -1) {
- const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
+ const char *module_name =
+ request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
if (module_name) {
FileSpec module_spec(module_name, false);
lldb::TargetSP target_sp =
@@ -867,9 +841,7 @@ bool Options::HandleOptionArgumentCompletion(
}
return CommandCompletions::InvokeCommonCompletionCallbacks(
- interpreter, completion_mask, input.GetArgumentAtIndex(opt_arg_pos),
- match_start_point, max_return_elements, filter_ap.get(), word_complete,
- matches);
+ interpreter, completion_mask, request, filter_ap.get());
}
void OptionGroupOptions::Append(OptionGroup *group) {
@@ -908,8 +880,8 @@ void OptionGroupOptions::Finalize() {
Status OptionGroupOptions::SetOptionValue(uint32_t option_idx,
llvm::StringRef option_value,
ExecutionContext *execution_context) {
- // After calling OptionGroupOptions::Append(...), you must finalize the groups
- // by calling OptionGroupOptions::Finlize()
+ // After calling OptionGroupOptions::Append(...), you must finalize the
+ // groups by calling OptionGroupOptions::Finlize()
assert(m_did_finalize);
Status error;
if (option_idx < m_option_infos.size()) {
@@ -951,3 +923,525 @@ OptionGroupOptions::OptionParsingFinished(ExecutionContext *execution_context) {
}
return error;
}
+
+// OptionParser permutes the arguments while processing them, so we create a
+// temporary array holding to avoid modification of the input arguments. The
+// options themselves are never modified, but the API expects a char * anyway,
+// hence the const_cast.
+static std::vector<char *> GetArgvForParsing(const Args &args) {
+ std::vector<char *> result;
+ // OptionParser always skips the first argument as it is based on getopt().
+ result.push_back(const_cast<char *>("<FAKE-ARG0>"));
+ for (const Args::ArgEntry &entry : args)
+ result.push_back(const_cast<char *>(entry.c_str()));
+ return result;
+}
+
+// Given a permuted argument, find it's position in the original Args vector.
+static Args::const_iterator FindOriginalIter(const char *arg,
+ const Args &original) {
+ return llvm::find_if(
+ original, [arg](const Args::ArgEntry &D) { return D.c_str() == arg; });
+}
+
+// Given a permuted argument, find it's index in the original Args vector.
+static size_t FindOriginalIndex(const char *arg, const Args &original) {
+ return std::distance(original.begin(), FindOriginalIter(arg, original));
+}
+
+// Construct a new Args object, consisting of the entries from the original
+// arguments, but in the permuted order.
+static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
+ const Args &original) {
+ Args result;
+ for (const char *arg : parsed) {
+ auto pos = FindOriginalIter(arg, original);
+ assert(pos != original.end());
+ result.AppendArgument(pos->ref, pos->quote);
+ }
+ return result;
+}
+
+static size_t FindArgumentIndexForOption(const Args &args,
+ const Option &long_option) {
+ std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
+ std::string long_opt =
+ llvm::formatv("--{0}", long_option.definition->long_option);
+ for (const auto &entry : llvm::enumerate(args)) {
+ if (entry.value().ref.startswith(short_opt) ||
+ entry.value().ref.startswith(long_opt))
+ return entry.index();
+ }
+
+ return size_t(-1);
+}
+
+llvm::Expected<Args> Options::ParseAlias(const Args &args,
+ OptionArgVector *option_arg_vector,
+ std::string &input_line) {
+ StreamString sstr;
+ int i;
+ Option *long_options = GetLongOptions();
+
+ if (long_options == nullptr) {
+ return llvm::make_error<llvm::StringError>("Invalid long options",
+ llvm::inconvertibleErrorCode());
+ }
+
+ for (i = 0; long_options[i].definition != nullptr; ++i) {
+ if (long_options[i].flag == nullptr) {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].definition->option_has_arg) {
+ default:
+ case OptionParser::eNoArgument:
+ break;
+ case OptionParser::eRequiredArgument:
+ sstr << ":";
+ break;
+ case OptionParser::eOptionalArgument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+
+ Args args_copy = args;
+ std::vector<char *> argv = GetArgvForParsing(args);
+
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
+ int val;
+ while (1) {
+ int long_options_index = -1;
+ val = OptionParser::Parse(argv.size(), &*argv.begin(), sstr.GetString(),
+ long_options, &long_options_index);
+
+ if (val == -1)
+ break;
+
+ if (val == '?') {
+ return llvm::make_error<llvm::StringError>(
+ "Unknown or ambiguous option", llvm::inconvertibleErrorCode());
+ }
+
+ if (val == 0)
+ continue;
+
+ OptionSeen(val);
+
+ // Look up the long option index
+ if (long_options_index == -1) {
+ for (int j = 0; long_options[j].definition || long_options[j].flag ||
+ long_options[j].val;
+ ++j) {
+ if (long_options[j].val == val) {
+ long_options_index = j;
+ break;
+ }
+ }
+ }
+
+ // See if the option takes an argument, and see if one was supplied.
+ if (long_options_index == -1) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Invalid option with value '{0}'.", char(val)).str(),
+ llvm::inconvertibleErrorCode());
+ }
+
+ StreamString option_str;
+ option_str.Printf("-%c", val);
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ int has_arg =
+ (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+
+ const char *option_arg = nullptr;
+ switch (has_arg) {
+ case OptionParser::eRequiredArgument:
+ if (OptionParser::GetOptionArgument() == nullptr) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Option '{0}' is missing argument specifier.",
+ option_str.GetString())
+ .str(),
+ llvm::inconvertibleErrorCode());
+ }
+ LLVM_FALLTHROUGH;
+ case OptionParser::eOptionalArgument:
+ option_arg = OptionParser::GetOptionArgument();
+ LLVM_FALLTHROUGH;
+ case OptionParser::eNoArgument:
+ break;
+ default:
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("error with options table; invalid value in has_arg "
+ "field for option '{0}'.",
+ char(val))
+ .str(),
+ llvm::inconvertibleErrorCode());
+ }
+ if (!option_arg)
+ option_arg = "<no-argument>";
+ option_arg_vector->emplace_back(option_str.GetString(), has_arg,
+ option_arg);
+
+ // Find option in the argument list; also see if it was supposed to take an
+ // argument and if one was supplied. Remove option (and argument, if
+ // given) from the argument list. Also remove them from the
+ // raw_input_string, if one was passed in.
+ size_t idx =
+ FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
+ if (idx == size_t(-1))
+ continue;
+
+ if (!input_line.empty()) {
+ auto tmp_arg = args_copy[idx].ref;
+ size_t pos = input_line.find(tmp_arg);
+ if (pos != std::string::npos)
+ input_line.erase(pos, tmp_arg.size());
+ }
+ args_copy.DeleteArgumentAtIndex(idx);
+ if ((long_options[long_options_index].definition->option_has_arg !=
+ OptionParser::eNoArgument) &&
+ (OptionParser::GetOptionArgument() != nullptr) &&
+ (idx < args_copy.GetArgumentCount()) &&
+ (args_copy[idx].ref == OptionParser::GetOptionArgument())) {
+ if (input_line.size() > 0) {
+ auto tmp_arg = args_copy[idx].ref;
+ size_t pos = input_line.find(tmp_arg);
+ if (pos != std::string::npos)
+ input_line.erase(pos, tmp_arg.size());
+ }
+ args_copy.DeleteArgumentAtIndex(idx);
+ }
+ }
+
+ return std::move(args_copy);
+}
+
+OptionElementVector Options::ParseForCompletion(const Args &args,
+ uint32_t cursor_index) {
+ OptionElementVector option_element_vector;
+ StreamString sstr;
+ Option *long_options = GetLongOptions();
+ option_element_vector.clear();
+
+ if (long_options == nullptr)
+ return option_element_vector;
+
+ // Leading : tells getopt to return a : for a missing option argument AND to
+ // suppress error messages.
+
+ sstr << ":";
+ for (int i = 0; long_options[i].definition != nullptr; ++i) {
+ if (long_options[i].flag == nullptr) {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].definition->option_has_arg) {
+ default:
+ case OptionParser::eNoArgument:
+ break;
+ case OptionParser::eRequiredArgument:
+ sstr << ":";
+ break;
+ case OptionParser::eOptionalArgument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
+ OptionParser::EnableError(false);
+
+ int val;
+ auto opt_defs = GetDefinitions();
+
+ std::vector<char *> dummy_vec = GetArgvForParsing(args);
+
+ // I stick an element on the end of the input, because if the last element
+ // is option that requires an argument, getopt_long_only will freak out.
+ dummy_vec.push_back(const_cast<char *>("<FAKE-VALUE>"));
+
+ bool failed_once = false;
+ uint32_t dash_dash_pos = -1;
+
+ while (1) {
+ bool missing_argument = false;
+ int long_options_index = -1;
+
+ val = OptionParser::Parse(dummy_vec.size(), &dummy_vec[0], sstr.GetString(),
+ long_options, &long_options_index);
+
+ if (val == -1) {
+ // When we're completing a "--" which is the last option on line,
+ if (failed_once)
+ break;
+
+ failed_once = true;
+
+ // If this is a bare "--" we mark it as such so we can complete it
+ // successfully later. Handling the "--" is a little tricky, since that
+ // may mean end of options or arguments, or the user might want to
+ // complete options by long name. I make this work by checking whether
+ // the cursor is in the "--" argument, and if so I assume we're
+ // completing the long option, otherwise I let it pass to
+ // OptionParser::Parse which will terminate the option parsing. Note, in
+ // either case we continue parsing the line so we can figure out what
+ // other options were passed. This will be useful when we come to
+ // restricting completions based on what other options we've seen on the
+ // line.
+
+ if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
+ dummy_vec.size() &&
+ (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
+ dash_dash_pos = FindOriginalIndex(
+ dummy_vec[OptionParser::GetOptionIndex() - 1], args);
+ if (dash_dash_pos == cursor_index) {
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eBareDoubleDash, dash_dash_pos,
+ OptionArgElement::eBareDoubleDash));
+ continue;
+ } else
+ break;
+ } else
+ break;
+ } else if (val == '?') {
+ option_element_vector.push_back(OptionArgElement(
+ OptionArgElement::eUnrecognizedArg,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args),
+ OptionArgElement::eUnrecognizedArg));
+ continue;
+ } else if (val == 0) {
+ continue;
+ } else if (val == ':') {
+ // This is a missing argument.
+ val = OptionParser::GetOptionErrorCause();
+ missing_argument = true;
+ }
+
+ OptionSeen(val);
+
+ // Look up the long option index
+ if (long_options_index == -1) {
+ for (int j = 0; long_options[j].definition || long_options[j].flag ||
+ long_options[j].val;
+ ++j) {
+ if (long_options[j].val == val) {
+ long_options_index = j;
+ break;
+ }
+ }
+ }
+
+ // See if the option takes an argument, and see if one was supplied.
+ if (long_options_index >= 0) {
+ int opt_defs_index = -1;
+ for (size_t i = 0; i < opt_defs.size(); i++) {
+ if (opt_defs[i].short_option != val)
+ continue;
+ opt_defs_index = i;
+ break;
+ }
+
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ int has_arg =
+ (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+ switch (has_arg) {
+ case OptionParser::eNoArgument:
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args),
+ 0));
+ break;
+ case OptionParser::eRequiredArgument:
+ if (OptionParser::GetOptionArgument() != nullptr) {
+ int arg_index;
+ if (missing_argument)
+ arg_index = -1;
+ else
+ arg_index = OptionParser::GetOptionIndex() - 2;
+
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
+ args),
+ arg_index));
+ } else {
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args),
+ -1));
+ }
+ break;
+ case OptionParser::eOptionalArgument:
+ if (OptionParser::GetOptionArgument() != nullptr) {
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
+ args),
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args)));
+ } else {
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
+ args),
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args)));
+ }
+ break;
+ default:
+ // The options table is messed up. Here we'll just continue
+ option_element_vector.push_back(OptionArgElement(
+ OptionArgElement::eUnrecognizedArg,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args),
+ OptionArgElement::eUnrecognizedArg));
+ break;
+ }
+ } else {
+ option_element_vector.push_back(OptionArgElement(
+ OptionArgElement::eUnrecognizedArg,
+ FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
+ args),
+ OptionArgElement::eUnrecognizedArg));
+ }
+ }
+
+ // Finally we have to handle the case where the cursor index points at a
+ // single "-". We want to mark that in the option_element_vector, but only
+ // if it is not after the "--". But it turns out that OptionParser::Parse
+ // just ignores an isolated "-". So we have to look it up by hand here. We
+ // only care if it is AT the cursor position. Note, a single quoted dash is
+ // not the same as a single dash...
+
+ const Args::ArgEntry &cursor = args[cursor_index];
+ if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
+ cursor_index < dash_dash_pos) &&
+ !cursor.IsQuoted() && cursor.ref == "-") {
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eBareDash, cursor_index,
+ OptionArgElement::eBareDash));
+ }
+ return option_element_vector;
+}
+
+llvm::Expected<Args> Options::Parse(const Args &args,
+ ExecutionContext *execution_context,
+ lldb::PlatformSP platform_sp,
+ bool require_validation) {
+ StreamString sstr;
+ Status error;
+ Option *long_options = GetLongOptions();
+ if (long_options == nullptr) {
+ return llvm::make_error<llvm::StringError>("Invalid long options.",
+ llvm::inconvertibleErrorCode());
+ }
+
+ for (int i = 0; long_options[i].definition != nullptr; ++i) {
+ if (long_options[i].flag == nullptr) {
+ if (isprint8(long_options[i].val)) {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].definition->option_has_arg) {
+ default:
+ case OptionParser::eNoArgument:
+ break;
+ case OptionParser::eRequiredArgument:
+ sstr << ':';
+ break;
+ case OptionParser::eOptionalArgument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+ }
+ std::vector<char *> argv = GetArgvForParsing(args);
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
+ int val;
+ while (1) {
+ int long_options_index = -1;
+ val = OptionParser::Parse(argv.size(), &*argv.begin(), sstr.GetString(),
+ long_options, &long_options_index);
+ if (val == -1)
+ break;
+
+ // Did we get an error?
+ if (val == '?') {
+ error.SetErrorStringWithFormat("unknown or ambiguous option");
+ break;
+ }
+ // The option auto-set itself
+ if (val == 0)
+ continue;
+
+ OptionSeen(val);
+
+ // Lookup the long option index
+ if (long_options_index == -1) {
+ for (int i = 0; long_options[i].definition || long_options[i].flag ||
+ long_options[i].val;
+ ++i) {
+ if (long_options[i].val == val) {
+ long_options_index = i;
+ break;
+ }
+ }
+ }
+ // Call the callback with the option
+ if (long_options_index >= 0 &&
+ long_options[long_options_index].definition) {
+ const OptionDefinition *def = long_options[long_options_index].definition;
+
+ if (!platform_sp) {
+ // User did not pass in an explicit platform. Try to grab from the
+ // execution context.
+ TargetSP target_sp =
+ execution_context ? execution_context->GetTargetSP() : TargetSP();
+ platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
+ }
+ OptionValidator *validator = def->validator;
+
+ if (!platform_sp && require_validation) {
+ // Caller requires validation but we cannot validate as we don't have
+ // the mandatory platform against which to validate.
+ return llvm::make_error<llvm::StringError>(
+ "cannot validate options: no platform available",
+ llvm::inconvertibleErrorCode());
+ }
+
+ bool validation_failed = false;
+ if (platform_sp) {
+ // Ensure we have an execution context, empty or not.
+ ExecutionContext dummy_context;
+ ExecutionContext *exe_ctx_p =
+ execution_context ? execution_context : &dummy_context;
+ if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
+ validation_failed = true;
+ error.SetErrorStringWithFormat("Option \"%s\" invalid. %s",
+ def->long_option,
+ def->validator->LongConditionString());
+ }
+ }
+
+ // As long as validation didn't fail, we set the option value.
+ if (!validation_failed)
+ error =
+ SetOptionValue(long_options_index,
+ (def->option_has_arg == OptionParser::eNoArgument)
+ ? nullptr
+ : OptionParser::GetOptionArgument(),
+ execution_context);
+ } else {
+ error.SetErrorStringWithFormat("invalid option with value '%i'", val);
+ }
+ if (error.Fail())
+ return error.ToError();
+ }
+
+ argv.erase(argv.begin(), argv.begin() + OptionParser::GetOptionIndex());
+ return ReconstituteArgsAfterParsing(argv, args);
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
index 5bac5ea0002f..369029bc570d 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Target/Language.h"
@@ -53,7 +54,7 @@ Property::Property(const PropertyDefinition &definition)
// "definition.default_cstr_value" as a string value that represents the
// default value.
if (definition.default_cstr_value)
- m_value_sp.reset(new OptionValueBoolean(Args::StringToBoolean(
+ m_value_sp.reset(new OptionValueBoolean(OptionArgParser::ToBoolean(
llvm::StringRef(definition.default_cstr_value), false, nullptr)));
else
m_value_sp.reset(
@@ -62,7 +63,8 @@ Property::Property(const PropertyDefinition &definition)
case OptionValue::eTypeChar: {
llvm::StringRef s(definition.default_cstr_value ? definition.default_cstr_value : "");
- m_value_sp = std::make_shared<OptionValueChar>(Args::StringToChar(s, '\0', nullptr));
+ m_value_sp = std::make_shared<OptionValueChar>(
+ OptionArgParser::ToChar(s, '\0', nullptr));
break;
}
case OptionValue::eTypeDictionary:
@@ -75,8 +77,7 @@ Property::Property(const PropertyDefinition &definition)
// "definition.default_uint_value" is the default enumeration value if
// "definition.default_cstr_value" is NULL, otherwise interpret
// "definition.default_cstr_value" as a string value that represents the
- // default
- // value.
+ // default value.
{
OptionValueEnumeration *enum_value = new OptionValueEnumeration(
definition.enum_values, definition.default_uint_value);
@@ -87,10 +88,10 @@ Property::Property(const PropertyDefinition &definition)
llvm::StringRef(definition.default_cstr_value))
.Success()) {
enum_value->SetDefaultValue(enum_value->GetCurrentValue());
- // Call Clear() since we don't want the value to appear as
- // having been set since we called SetValueFromString() above.
- // Clear will set the current value to the default and clear
- // the boolean that says that the value has been set.
+ // Call Clear() since we don't want the value to appear as having
+ // been set since we called SetValueFromString() above. Clear will
+ // set the current value to the default and clear the boolean that
+ // says that the value has been set.
enum_value->Clear();
}
}
@@ -99,8 +100,7 @@ Property::Property(const PropertyDefinition &definition)
case OptionValue::eTypeFileSpec: {
// "definition.default_uint_value" represents if the
- // "definition.default_cstr_value" should
- // be resolved or not
+ // "definition.default_cstr_value" should be resolved or not
const bool resolve = definition.default_uint_value != 0;
m_value_sp.reset(new OptionValueFileSpec(
FileSpec(definition.default_cstr_value, resolve), resolve));
@@ -115,16 +115,14 @@ Property::Property(const PropertyDefinition &definition)
case OptionValue::eTypeFormat:
// "definition.default_uint_value" is the default format enumeration value
- // if
- // "definition.default_cstr_value" is NULL, otherwise interpret
+ // if "definition.default_cstr_value" is NULL, otherwise interpret
// "definition.default_cstr_value" as a string value that represents the
- // default
- // value.
+ // default value.
{
Format new_format = eFormatInvalid;
if (definition.default_cstr_value)
- Args::StringToFormat(definition.default_cstr_value, new_format,
- nullptr);
+ OptionArgParser::ToFormat(definition.default_cstr_value, new_format,
+ nullptr);
else
new_format = (Format)definition.default_uint_value;
m_value_sp.reset(new OptionValueFormat(new_format));
@@ -132,12 +130,10 @@ Property::Property(const PropertyDefinition &definition)
break;
case OptionValue::eTypeLanguage:
- // "definition.default_uint_value" is the default language enumeration value
- // if
- // "definition.default_cstr_value" is NULL, otherwise interpret
+ // "definition.default_uint_value" is the default language enumeration
+ // value if "definition.default_cstr_value" is NULL, otherwise interpret
// "definition.default_cstr_value" as a string value that represents the
- // default
- // value.
+ // default value.
{
LanguageType new_lang = eLanguageTypeUnknown;
if (definition.default_cstr_value)
@@ -158,8 +154,7 @@ Property::Property(const PropertyDefinition &definition)
case OptionValue::eTypePathMap:
// "definition.default_uint_value" tells us if notifications should occur
- // for
- // path mappings
+ // for path mappings
m_value_sp.reset(
new OptionValuePathMappings(definition.default_uint_value != 0));
break;
@@ -175,8 +170,7 @@ Property::Property(const PropertyDefinition &definition)
// "definition.default_uint_value" is the default integer value if
// "definition.default_cstr_value" is NULL, otherwise interpret
// "definition.default_cstr_value" as a string value that represents the
- // default
- // value.
+ // default value.
m_value_sp.reset(new OptionValueSInt64(
definition.default_cstr_value
? StringConvert::ToSInt64(definition.default_cstr_value)
@@ -187,8 +181,7 @@ Property::Property(const PropertyDefinition &definition)
// "definition.default_uint_value" is the default unsigned integer value if
// "definition.default_cstr_value" is NULL, otherwise interpret
// "definition.default_cstr_value" as a string value that represents the
- // default
- // value.
+ // default value.
m_value_sp.reset(new OptionValueUInt64(
definition.default_cstr_value
? StringConvert::ToUInt64(definition.default_cstr_value)
@@ -201,15 +194,15 @@ Property::Property(const PropertyDefinition &definition)
{
UUID uuid;
if (definition.default_cstr_value)
- uuid.SetFromCString(definition.default_cstr_value);
+ uuid.SetFromStringRef(definition.default_cstr_value);
m_value_sp.reset(new OptionValueUUID(uuid));
}
break;
case OptionValue::eTypeString:
- // "definition.default_uint_value" can contain the string option flags OR'ed
- // together
- // "definition.default_cstr_value" can contain a default string value
+ // "definition.default_uint_value" can contain the string option flags
+ // OR'ed together "definition.default_cstr_value" can contain a default
+ // string value
{
OptionValueString *string_value =
new OptionValueString(definition.default_cstr_value);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 1bd1c1bf8dd4..e0e293d7ae68 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -1466,8 +1466,8 @@ bool ABIMacOSX_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
@@ -1589,10 +1589,8 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl(
case 128:
if (IsArmv7kProcess()) {
// "A composite type not larger than 16 bytes is returned in r0-r3. The
- // format is
- // as if the result had been stored in memory at a word-aligned address
- // and then
- // loaded into r0-r3 with an ldm instruction"
+ // format is as if the result had been stored in memory at a word-
+ // aligned address and then loaded into r0-r3 with an ldm instruction"
{
const RegisterInfo *r1_reg_info =
reg_ctx->GetRegisterInfoByName("r1", 0);
@@ -1756,10 +1754,8 @@ Status ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
}
} else if (num_bytes <= 16 && IsArmv7kProcess()) {
// "A composite type not larger than 16 bytes is returned in r0-r3. The
- // format is
- // as if the result had been stored in memory at a word-aligned address
- // and then
- // loaded into r0-r3 with an ldm instruction"
+ // format is as if the result had been stored in memory at a word-aligned
+ // address and then loaded into r0-r3 with an ldm instruction"
const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index e301b21d542a..85f864ec7561 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -1760,8 +1760,8 @@ bool ABIMacOSX_arm64::GetArgumentValues(Thread &thread,
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
@@ -2022,10 +2022,9 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
}
// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
-// registers x19 through x28 and sp are callee preserved.
-// v8-v15 are non-volatile (and specifically only the lower 8 bytes of these
-// regs),
-// the rest of the fp/SIMD registers are volatile.
+// registers x19 through x28 and sp are callee preserved. v8-v15 are non-
+// volatile (and specifically only the lower 8 bytes of these regs), the rest
+// of the fp/SIMD registers are volatile.
// We treat x29 as callee preserved also, else the unwinder won't try to
// retrieve fp saves.
@@ -2209,14 +2208,14 @@ static bool LoadValueFromConsecutiveGPRRegisters(
} else {
const RegisterInfo *reg_info = nullptr;
if (is_return_value) {
- // We are assuming we are decoding this immediately after returning
- // from a function call and that the address of the structure is in x8
+ // We are assuming we are decoding this immediately after returning from
+ // a function call and that the address of the structure is in x8
reg_info = reg_ctx->GetRegisterInfoByName("x8", 0);
} else {
// We are assuming we are stopped at the first instruction in a function
- // and that the ABI is being respected so all parameters appear where they
- // should be (functions with no external linkage can legally violate the
- // ABI).
+ // and that the ABI is being respected so all parameters appear where
+ // they should be (functions with no external linkage can legally violate
+ // the ABI).
if (NGRN >= 8)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 716a73b854b3..9e5e39ec28ca 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -736,10 +736,10 @@ bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
- // When writing a register value down to memory, the register info used
- // to write memory just needs to have the correct size of a 32 bit register,
- // the actual register it pertains to is not important, just the size needs
- // to be correct. Here we use "eax"...
+ // When writing a register value down to memory, the register info used to
+ // write memory just needs to have the correct size of a 32 bit register, the
+ // actual register it pertains to is not important, just the size needs to be
+ // correct. Here we use "eax"...
const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
if (!reg_info_32)
return false; // TODO this should actually never happen
@@ -828,8 +828,8 @@ bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type(value->GetCompilerType());
if (compiler_type) {
bool is_signed;
@@ -1075,12 +1075,13 @@ bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
}
// v.
-// http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
+// http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130
+// -IA-
+// 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
//
// This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
-// Calling Conventions")
-// says that the following registers on i386 are preserved aka non-volatile aka
-// callee-saved:
+// Calling Conventions") says that the following registers on i386 are
+// preserved aka non-volatile aka callee-saved:
//
// ebx, ebp, esi, edi, esp
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
index 882d5cd23e58..af7ac469e6db 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -1470,8 +1470,8 @@ bool ABISysV_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
index dbe333c4649e..2c221689954c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
@@ -1763,8 +1763,8 @@ bool ABISysV_arm64::GetArgumentValues(Thread &thread, ValueList &values) const {
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
@@ -1994,10 +1994,9 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
}
// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
-// registers x19 through x28 and sp are callee preserved.
-// v8-v15 are non-volatile (and specifically only the lower 8 bytes of these
-// regs),
-// the rest of the fp/SIMD registers are volatile.
+// registers x19 through x28 and sp are callee preserved. v8-v15 are non-
+// volatile (and specifically only the lower 8 bytes of these regs), the rest
+// of the fp/SIMD registers are volatile.
// We treat x29 as callee preserved also, else the unwinder won't try to
// retrieve fp saves.
@@ -2020,10 +2019,10 @@ bool ABISysV_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) {
if (name[0] == 'x' || name[0] == 'r') {
// Volatile registers: x0-x18
- // Although documentation says only x19-28 + sp are callee saved
- // We ll also have to treat x30 as non-volatile.
- // Each dwarf frame has its own value of lr.
- // Return false for the non-volatile gpr regs, true for everything else
+ // Although documentation says only x19-28 + sp are callee saved We ll
+ // also have to treat x30 as non-volatile. Each dwarf frame has its own
+ // value of lr. Return false for the non-volatile gpr regs, true for
+ // everything else
switch (name[1]) {
case '1':
switch (name[2]) {
@@ -2180,14 +2179,14 @@ static bool LoadValueFromConsecutiveGPRRegisters(
} else {
const RegisterInfo *reg_info = nullptr;
if (is_return_value) {
- // We are assuming we are decoding this immediately after returning
- // from a function call and that the address of the structure is in x8
+ // We are assuming we are decoding this immediately after returning from
+ // a function call and that the address of the structure is in x8
reg_info = reg_ctx->GetRegisterInfoByName("x8", 0);
} else {
// We are assuming we are stopped at the first instruction in a function
- // and that the ABI is being respected so all parameters appear where they
- // should be (functions with no external linkage can legally violate the
- // ABI).
+ // and that the ABI is being respected so all parameters appear where
+ // they should be (functions with no external linkage can legally violate
+ // the ABI).
if (NGRN >= 8)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index 74274f08b24f..a30416cf5a8e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -1214,8 +1214,8 @@ ValueObjectSP ABISysV_hexagon::GetReturnValueObjectImpl(
return return_valobj_sp;
}
-// called when we are on the first instruction of a new function
-// for hexagon the return address is in RA (R31)
+// called when we are on the first instruction of a new function for hexagon
+// the return address is in RA (R31)
bool ABISysV_hexagon::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindGeneric);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
index d799c587dd07..e7ddfccea338 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -3,8 +3,7 @@
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
-// License.
-// See LICENSE.TXT for details.
+// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
#include "ABISysV_i386.h"
@@ -56,8 +55,8 @@ using namespace lldb_private;
// DWARF Register Number Mapping
// See Table 2.14 of the reference document (specified on top of this file)
-// Comment: Table 2.14 is followed till 'mm' entries.
-// After that, all entries are ignored here.
+// Comment: Table 2.14 is followed till 'mm' entries. After that, all entries
+// are ignored here.
enum dwarf_regnums {
dwarf_eax = 0,
@@ -228,12 +227,10 @@ bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
- // While using register info to write a register value to memory, the register
- // info
- // just needs to have the correct size of a 32 bit register, the actual
- // register it
- // pertains to is not important, just the size needs to be correct.
- // "eax" is used here for this purpose.
+ // While using register info to write a register value to memory, the
+ // register info just needs to have the correct size of a 32 bit register,
+ // the actual register it pertains to is not important, just the size needs
+ // to be correct. "eax" is used here for this purpose.
const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
if (!reg_info_32)
return false; // TODO this should actually never happen
@@ -364,8 +361,8 @@ Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
}
// Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
- // The terminology 'Fundamental Data Types' used here is adopted from
- // Table 2.1 of the reference document (specified on top of this file)
+ // The terminology 'Fundamental Data Types' used here is adopted from Table
+ // 2.1 of the reference document (specified on top of this file)
if (type_flags & eTypeIsPointer) // 'Pointer'
{
@@ -390,8 +387,8 @@ Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
default:
break;
case 16:
- // For clang::BuiltinType::UInt128 & Int128
- // ToDo: Need to decide how to handle it
+ // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
+ // handle it
break;
case 8: {
uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
@@ -470,8 +467,8 @@ Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
error.SetErrorString("Implementation is missing for this clang type.");
}
} else {
- // Neither 'Integral' nor 'Floating Point'. If flow reaches here
- // then check type_flags. This type_flags is not a valid type.
+ // Neither 'Integral' nor 'Floating Point'. If flow reaches here then
+ // check type_flags. This type_flags is not a valid type.
error.SetErrorString("Invalid clang type");
}
} else {
@@ -508,8 +505,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
// Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
- // The terminology 'Fundamental Data Types' used here is adopted from
- // Table 2.1 of the reference document (specified on top of this file)
+ // The terminology 'Fundamental Data Types' used here is adopted from Table
+ // 2.1 of the reference document (specified on top of this file)
if (type_flags & eTypeIsPointer) // 'Pointer'
{
@@ -543,8 +540,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
break;
case 16:
- // For clang::BuiltinType::UInt128 & Int128
- // ToDo: Need to decide how to handle it
+ // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
+ // handle it
break;
case 8:
@@ -612,8 +609,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
success = true;
} else if (byte_size == 8) // double is 8 bytes
{
- // On Android Platform: long double is also 8 bytes
- // It will be handled here only.
+ // On Android Platform: long double is also 8 bytes It will be
+ // handled here only.
double value_double = (double)value_long_double;
value.GetScalar() = value_double;
success = true;
@@ -639,8 +636,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
}
} else // Neither 'Integral' nor 'Floating Point'
{
- // If flow reaches here then check type_flags
- // This type_flags is unhandled
+ // If flow reaches here then check type_flags This type_flags is
+ // unhandled
}
} else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
{
@@ -797,9 +794,9 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
return true;
}
-// According to "Register Usage" in reference document (specified on top
-// of this source file) ebx, ebp, esi, edi and esp registers are preserved
-// i.e. non-volatile i.e. callee-saved on i386
+// According to "Register Usage" in reference document (specified on top of
+// this source file) ebx, ebp, esi, edi and esp registers are preserved i.e.
+// non-volatile i.e. callee-saved on i386
bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (!reg_info)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
index 95e2a7b0afeb..ce02f8677a63 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
@@ -698,8 +698,8 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
if (log)
log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
- // All callers of position independent functions must place the address of the
- // called function in t9 (r25)
+ // All callers of position independent functions must place the address of
+ // the called function in t9 (r25)
if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
return false;
@@ -867,8 +867,8 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
UINT32_MAX;
value.GetScalar() = ptr;
} else if (return_compiler_type.IsAggregateType()) {
- // Structure/Vector is always passed in memory and pointer to that memory is
- // passed in r2.
+ // Structure/Vector is always passed in memory and pointer to that memory
+ // is passed in r2.
uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
reg_ctx->GetRegisterInfoByName("r2", 0), 0);
// We have got the address. Create a memory object out of it
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
index 749e170fa17d..b958abf25637 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -661,8 +661,8 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp,
if (log)
log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
- // All callers of position independent functions must place the address of the
- // called function in t9 (r25)
+ // All callers of position independent functions must place the address of
+ // the called function in t9 (r25)
if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
return false;
@@ -1035,10 +1035,9 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
}
}
- // If we reach here, it means this structure either contains more than two
- // fields or
- // it contains at least one non floating point type.
- // In that case, all fields are returned in GP return registers.
+ // If we reach here, it means this structure either contains more than
+ // two fields or it contains at least one non floating point type. In
+ // that case, all fields are returned in GP return registers.
for (uint32_t idx = 0; idx < num_children; idx++) {
uint64_t field_bit_offset = 0;
bool is_signed;
@@ -1049,8 +1048,8 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
const size_t field_byte_width =
field_compiler_type.GetByteSize(nullptr);
- // if we don't know the size of the field (e.g. invalid type), just bail
- // out
+ // if we don't know the size of the field (e.g. invalid type), just
+ // bail out
if (field_byte_width == 0)
break;
@@ -1078,16 +1077,15 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
}
}
// We already have consumed at-least 8 bytes that means r2 is done,
- // and this field will be in r3.
- // Check if this field can fit in r3.
+ // and this field will be in r3. Check if this field can fit in r3.
else if (integer_bytes + field_byte_width + padding <= 16) {
integer_bytes = integer_bytes + field_byte_width + padding;
use_r3 = 1;
} else {
- // There isn't any space left for this field, this should not happen
- // as we have already checked
- // the overall size is not greater than 16 bytes. For now, return a
- // nullptr return value object.
+ // There isn't any space left for this field, this should not
+ // happen as we have already checked the overall size is not
+ // greater than 16 bytes. For now, return a nullptr return value
+ // object.
return return_valobj_sp;
}
}
@@ -1123,15 +1121,16 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
sucess = 1;
}
if (sucess) {
- // The result is in our data buffer. Create a variable object out of it
+ // The result is in our data buffer. Create a variable object out of
+ // it
return_valobj_sp = ValueObjectConstResult::Create(
&thread, return_compiler_type, ConstString(""), return_ext);
}
return return_valobj_sp;
}
- // Any structure/vector greater than 16 bytes in size is returned in memory.
- // The pointer to that memory is returned in r2.
+ // Any structure/vector greater than 16 bytes in size is returned in
+ // memory. The pointer to that memory is returned in r2.
uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
reg_ctx->GetRegisterInfoByName("r2", 0), 0);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
index 2fee176739f3..e93dcdbe1a59 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -402,8 +402,8 @@ bool ABISysV_ppc::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -501,8 +501,8 @@ Status ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -735,10 +735,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
copy_from_offset = integer_bytes - 8;
integer_bytes += field_byte_width;
} else {
- // The last field didn't fit. I can't see how that would happen w/o
- // the overall size being
- // greater than 16 bytes. For now, return a nullptr return value
- // object.
+ // The last field didn't fit. I can't see how that would happen
+ // w/o the overall size being greater than 16 bytes. For now,
+ // return a nullptr return value object.
return return_valobj_sp;
}
} else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
@@ -751,10 +750,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
fp_bytes += field_byte_width;
} else if (field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
- // with another float, we'll
- // be stuffed into an xmm register with it. If we are in an
- // "eightbyte" with one or more ints,
- // then we will be stuffed into the appropriate GPR with them.
+ // with another float, we'll be stuffed into an xmm register with
+ // it. If we are in an "eightbyte" with one or more ints, then we
+ // will be stuffed into the appropriate GPR with them.
bool in_gpr;
if (field_byte_offset % 8 == 0) {
// We are at the beginning of one of the eightbytes, so check the
@@ -776,9 +774,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
}
}
} else if (field_byte_offset % 4 == 0) {
- // We are inside of an eightbyte, so see if the field before us is
- // floating point:
- // This could happen if somebody put padding in the structure.
+ // We are inside of an eightbyte, so see if the field before us
+ // is floating point: This could happen if somebody put padding
+ // in the structure.
if (idx == 0)
in_gpr = false;
else {
@@ -819,9 +817,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
}
}
- // These two tests are just sanity checks. If I somehow get the
- // type calculation wrong above it is better to just return nothing
- // than to assert or crash.
+ // These two tests are just sanity checks. If I somehow get the type
+ // calculation wrong above it is better to just return nothing than to
+ // assert or crash.
if (!copy_from_extractor)
return return_valobj_sp;
if (copy_from_offset + field_byte_width >
@@ -845,9 +843,8 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
// FIXME: This is just taking a guess, r3 may very well no longer hold the
// return storage location.
// If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
+ // check to see if it uses a memory return, and if we are at the first
+ // instruction and if so stash away the return location. Then we would
// only return the memory return value if we know it is valid.
if (is_memory) {
@@ -918,9 +915,9 @@ bool ABISysV_ppc::RegisterIsVolatile(const RegisterInfo *reg_info) {
// See "Register Usage" in the
// "System V Application Binary Interface"
-// "64-bit PowerPC ELF Application Binary Interface Supplement"
-// current version is 1.9 released 2004 at
-// http://refspecs.linuxfoundation.org/ELF/ppc/PPC-elf64abi-1.9.pdf
+// "64-bit PowerPC ELF Application Binary Interface Supplement" current version
+// is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc/PPC-
+// elf64abi-1.9.pdf
bool ABISysV_ppc::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (reg_info) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
index 0348853c7fa0..d0140a0c894a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -16,6 +16,8 @@
#include "llvm/ADT/Triple.h"
// Project includes
+#include "Utility/PPC64LE_DWARF_Registers.h"
+#include "Utility/PPC64_DWARF_Registers.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
@@ -23,6 +25,7 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -34,201 +37,48 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
-using namespace lldb;
-using namespace lldb_private;
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
-enum dwarf_regnums {
- dwarf_r0 = 0,
- dwarf_r1,
- dwarf_r2,
- dwarf_r3,
- dwarf_r4,
- dwarf_r5,
- dwarf_r6,
- dwarf_r7,
- dwarf_r8,
- dwarf_r9,
- dwarf_r10,
- dwarf_r11,
- dwarf_r12,
- dwarf_r13,
- dwarf_r14,
- dwarf_r15,
- dwarf_r16,
- dwarf_r17,
- dwarf_r18,
- dwarf_r19,
- dwarf_r20,
- dwarf_r21,
- dwarf_r22,
- dwarf_r23,
- dwarf_r24,
- dwarf_r25,
- dwarf_r26,
- dwarf_r27,
- dwarf_r28,
- dwarf_r29,
- dwarf_r30,
- dwarf_r31,
- dwarf_f0,
- dwarf_f1,
- dwarf_f2,
- dwarf_f3,
- dwarf_f4,
- dwarf_f5,
- dwarf_f6,
- dwarf_f7,
- dwarf_f8,
- dwarf_f9,
- dwarf_f10,
- dwarf_f11,
- dwarf_f12,
- dwarf_f13,
- dwarf_f14,
- dwarf_f15,
- dwarf_f16,
- dwarf_f17,
- dwarf_f18,
- dwarf_f19,
- dwarf_f20,
- dwarf_f21,
- dwarf_f22,
- dwarf_f23,
- dwarf_f24,
- dwarf_f25,
- dwarf_f26,
- dwarf_f27,
- dwarf_f28,
- dwarf_f29,
- dwarf_f30,
- dwarf_f31,
- dwarf_cr,
- dwarf_fpscr,
- dwarf_xer = 101,
- dwarf_lr = 108,
- dwarf_ctr,
- dwarf_pc,
- dwarf_cfa,
-};
+#define DECLARE_REGISTER_INFOS_PPC64_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64.h"
+#undef DECLARE_REGISTER_INFOS_PPC64_STRUCT
-// Note that the size and offset will be updated by platform-specific classes.
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { \
- #reg, alt, 8, 0, eEncodingUint, eFormatHex, {kind1, kind2, kind3, kind4 }, \
- nullptr, nullptr, nullptr, 0 \
- }
+#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
+#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
-static const RegisterInfo g_register_infos[] = {
- // General purpose registers. eh_frame, DWARF,
- // Generic, Process Plugin
- DEFINE_GPR(r0, nullptr, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r2, nullptr, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r3, "arg1", dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r4, "arg2", dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r5, "arg3", dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r6, "arg4", dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r7, "arg5", dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r8, "arg6", dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r9, "arg7", dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r10, "arg8", dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r11, nullptr, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r12, nullptr, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r13, nullptr, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r14, nullptr, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r15, nullptr, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r16, nullptr, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r17, nullptr, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r18, nullptr, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r19, nullptr, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r20, nullptr, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r21, nullptr, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r22, nullptr, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r23, nullptr, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r24, nullptr, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r25, nullptr, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r26, nullptr, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r27, nullptr, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r28, nullptr, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r29, nullptr, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r30, nullptr, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r31, nullptr, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC,
- LLDB_INVALID_REGNUM),
- {nullptr,
- nullptr,
- 8,
- 0,
- eEncodingUint,
- eFormatHex,
- {dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
- nullptr,
- nullptr,
- nullptr,
- 0}};
-
-static const uint32_t k_num_register_infos =
- llvm::array_lengthof(g_register_infos);
+using namespace lldb;
+using namespace lldb_private;
const lldb_private::RegisterInfo *
ABISysV_ppc64::GetRegisterInfoArray(uint32_t &count) {
- count = k_num_register_infos;
- return g_register_infos;
+ if (GetByteOrder() == lldb::eByteOrderLittle) {
+ count = llvm::array_lengthof(g_register_infos_ppc64le);
+ return g_register_infos_ppc64le;
+ } else {
+ count = llvm::array_lengthof(g_register_infos_ppc64);
+ return g_register_infos_ppc64;
+ }
}
size_t ABISysV_ppc64::GetRedZoneSize() const { return 224; }
+lldb::ByteOrder ABISysV_ppc64::GetByteOrder() const {
+ return GetProcessSP()->GetByteOrder();
+}
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
ABISP
-ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
- if (arch.GetTriple().getArch() == llvm::Triple::ppc64) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_ppc64(process_sp));
- return g_abi_sp;
+ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp,
+ const ArchSpec &arch) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64 ||
+ arch.GetTriple().getArch() == llvm::Triple::ppc64le) {
+ return ABISP(new ABISysV_ppc64(process_sp));
}
return ABISP();
}
@@ -280,28 +130,68 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp,
sp &= ~(0xfull); // 16-byte alignment
- sp -= 8;
+ sp -= 544; // allocate frame to save TOC, RA and SP.
Status error;
+ uint64_t reg_value;
const RegisterInfo *pc_reg_info =
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
const RegisterInfo *sp_reg_info =
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
ProcessSP process_sp(thread.GetProcess());
+ const RegisterInfo *lr_reg_info =
+ reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoAtIndex(2);
+ const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12);
- RegisterValue reg_value;
-
+ // Save return address onto the stack.
if (log)
log->Printf("Pushing the return address onto the stack: 0x%" PRIx64
- ": 0x%" PRIx64,
+ "(+16): 0x%" PRIx64,
(uint64_t)sp, (uint64_t)return_addr);
+ if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error))
+ return false;
- // Save return address onto the stack
- if (!process_sp->WritePointerToMemory(sp, return_addr, error))
+ // Write the return address to link register.
+ if (log)
+ log->Printf("Writing LR: 0x%" PRIx64, (uint64_t)return_addr);
+ if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr))
return false;
- // %r1 is set to the actual stack value.
+ // Write target address to %r12 register.
+ if (log)
+ log->Printf("Writing R12: 0x%" PRIx64, (uint64_t)func_addr);
+ if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr))
+ return false;
+
+ // Read TOC pointer value.
+ reg_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
+
+ // Write TOC pointer onto the stack.
+ uint64_t stack_offset;
+ if (GetByteOrder() == lldb::eByteOrderLittle)
+ stack_offset = 24;
+ else
+ stack_offset = 40;
+
+ if (log)
+ log->Printf("Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64,
+ (uint64_t)(sp + stack_offset), (int)stack_offset,
+ (uint64_t)reg_value);
+ if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error))
+ return false;
+
+ // Read the current SP value.
+ reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0);
+
+ // Save current SP onto the stack.
+ if (log)
+ log->Printf("Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp,
+ (uint64_t)reg_value);
+ if (!process_sp->WritePointerToMemory(sp, reg_value, error))
+ return false;
+ // %r1 is set to the actual stack value.
if (log)
log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
@@ -365,34 +255,23 @@ bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!sp)
return false;
- addr_t current_stack_argument = sp + 48; // jump over return address
+ uint64_t stack_offset;
+ if (GetByteOrder() == lldb::eByteOrderLittle)
+ stack_offset = 32;
+ else
+ stack_offset = 48;
+ // jump over return address.
+ addr_t current_stack_argument = sp + stack_offset;
uint32_t argument_register_ids[8];
- argument_register_ids[0] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[1] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[2] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[3] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[4] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[5] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[6] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[7] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)
- ->kinds[eRegisterKindLLDB];
+ for (size_t i = 0; i < 8; ++i) {
+ argument_register_ids[i] =
+ reg_ctx
+ ->GetRegisterInfo(eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_ARG1 + i)
+ ->kinds[eRegisterKindLLDB];
+ }
unsigned int current_argument_register = 0;
@@ -402,8 +281,8 @@ bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -501,8 +380,8 @@ Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -510,367 +389,584 @@ Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
return error;
}
-ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple(
- Thread &thread, CompilerType &return_compiler_type) const {
- ValueObjectSP return_valobj_sp;
- Value value;
+//
+// ReturnValueExtractor
+//
- if (!return_compiler_type)
- return return_valobj_sp;
+namespace {
+
+#define LOG_PREFIX "ReturnValueExtractor: "
+
+class ReturnValueExtractor {
+ // This class represents a register, from which data may be extracted.
+ //
+ // It may be constructed by directly specifying its index (where 0 is the
+ // first register used to return values) or by specifying the offset of a
+ // given struct field, in which case the appropriated register index will be
+ // calculated.
+ class Register {
+ public:
+ enum Type {
+ GPR, // General Purpose Register
+ FPR // Floating Point Register
+ };
+
+ // main constructor
+ //
+ // offs - field offset in struct
+ Register(Type ty, uint32_t index, uint32_t offs, RegisterContext *reg_ctx,
+ ByteOrder byte_order)
+ : m_index(index), m_offs(offs % sizeof(uint64_t)),
+ m_avail(sizeof(uint64_t) - m_offs), m_type(ty), m_reg_ctx(reg_ctx),
+ m_byte_order(byte_order) {}
+
+ // explicit index, no offset
+ Register(Type ty, uint32_t index, RegisterContext *reg_ctx,
+ ByteOrder byte_order)
+ : Register(ty, index, 0, reg_ctx, byte_order) {}
+
+ // GPR, calculate index from offs
+ Register(uint32_t offs, RegisterContext *reg_ctx, ByteOrder byte_order)
+ : Register(GPR, offs / sizeof(uint64_t), offs, reg_ctx, byte_order) {}
+
+ uint32_t Index() const { return m_index; }
+
+ // register offset where data is located
+ uint32_t Offs() const { return m_offs; }
+
+ // available bytes in this register
+ uint32_t Avail() const { return m_avail; }
+
+ bool IsValid() const {
+ if (m_index > 7) {
+ LLDB_LOG(m_log, LOG_PREFIX
+ "No more than 8 registers should be used to return values");
+ return false;
+ }
+ return true;
+ }
- // value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetCompilerType(return_compiler_type);
+ std::string GetName() const {
+ if (m_type == GPR)
+ return ("r" + llvm::Twine(m_index + 3)).str();
+ else
+ return ("f" + llvm::Twine(m_index + 1)).str();
+ }
- RegisterContext *reg_ctx = thread.GetRegisterContext().get();
- if (!reg_ctx)
- return return_valobj_sp;
-
- const uint32_t type_flags = return_compiler_type.GetTypeInfo();
- if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
-
- bool success = false;
- if (type_flags & eTypeIsInteger) {
- // Extract the register context so we can read arguments from registers
-
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
- reg_ctx->GetRegisterInfoByName("r3", 0), 0);
- const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
- default:
- break;
-
- case sizeof(uint64_t):
- if (is_signed)
- value.GetScalar() = (int64_t)(raw_value);
- else
- value.GetScalar() = (uint64_t)(raw_value);
- success = true;
- break;
-
- case sizeof(uint32_t):
- if (is_signed)
- value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
- else
- value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
- success = true;
- break;
-
- case sizeof(uint16_t):
- if (is_signed)
- value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
- else
- value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
- success = true;
- break;
-
- case sizeof(uint8_t):
- if (is_signed)
- value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
- else
- value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
- success = true;
- break;
+ // get raw register data
+ bool GetRawData(uint64_t &raw_data) {
+ const RegisterInfo *reg_info =
+ m_reg_ctx->GetRegisterInfoByName(GetName());
+ if (!reg_info) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get RegisterInfo");
+ return false;
}
- } else if (type_flags & eTypeIsFloat) {
- if (type_flags & eTypeIsComplex) {
- // Don't handle complex yet.
- } else {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size <= sizeof(long double)) {
- const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
- RegisterValue f1_value;
- if (reg_ctx->ReadRegister(f1_info, f1_value)) {
- DataExtractor data;
- if (f1_value.GetData(data)) {
- lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
- value.GetScalar() = (float)data.GetFloat(&offset);
- success = true;
- } else if (byte_size == sizeof(double)) {
- value.GetScalar() = (double)data.GetDouble(&offset);
- success = true;
- }
- }
- }
- }
+
+ RegisterValue reg_val;
+ if (!m_reg_ctx->ReadRegister(reg_info, reg_val)) {
+ LLDB_LOG(m_log, LOG_PREFIX "ReadRegister() failed");
+ return false;
}
+
+ Status error;
+ uint32_t rc = reg_val.GetAsMemoryData(
+ reg_info, &raw_data, sizeof(raw_data), m_byte_order, error);
+ if (rc != sizeof(raw_data)) {
+ LLDB_LOG(m_log, LOG_PREFIX "GetAsMemoryData() failed");
+ return false;
+ }
+
+ return true;
}
- if (success)
- return_valobj_sp = ValueObjectConstResult::Create(
- thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
- } else if (type_flags & eTypeIsPointer) {
- unsigned r3_id =
- reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
- value.GetScalar() =
- (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
- value.SetValueType(Value::eValueTypeScalar);
- return_valobj_sp = ValueObjectConstResult::Create(
- thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
- } else if (type_flags & eTypeIsVector) {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size > 0) {
- const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0);
- if (altivec_reg) {
- if (byte_size <= altivec_reg->byte_size) {
- ProcessSP process_sp(thread.GetProcess());
- if (process_sp) {
- std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
- const ByteOrder byte_order = process_sp->GetByteOrder();
- RegisterValue reg_value;
- if (reg_ctx->ReadRegister(altivec_reg, reg_value)) {
- Status error;
- if (reg_value.GetAsMemoryData(
- altivec_reg, heap_data_ap->GetBytes(),
- heap_data_ap->GetByteSize(), byte_order, error)) {
- DataExtractor data(DataBufferSP(heap_data_ap.release()),
- byte_order, process_sp->GetTarget()
- .GetArchitecture()
- .GetAddressByteSize());
- return_valobj_sp = ValueObjectConstResult::Create(
- &thread, return_compiler_type, ConstString(""), data);
- }
- }
- }
+ private:
+ uint32_t m_index;
+ uint32_t m_offs;
+ uint32_t m_avail;
+ Type m_type;
+ RegisterContext *m_reg_ctx;
+ ByteOrder m_byte_order;
+ Log *m_log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ };
+
+ Register GetGPR(uint32_t index) const {
+ return Register(Register::GPR, index, m_reg_ctx, m_byte_order);
+ }
+
+ Register GetFPR(uint32_t index) const {
+ return Register(Register::FPR, index, m_reg_ctx, m_byte_order);
+ }
+
+ Register GetGPRByOffs(uint32_t offs) const {
+ return Register(offs, m_reg_ctx, m_byte_order);
+ }
+
+public:
+ // factory
+ static llvm::Expected<ReturnValueExtractor> Create(Thread &thread,
+ CompilerType &type) {
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return llvm::make_error<llvm::StringError>(
+ LOG_PREFIX "Failed to get RegisterContext",
+ llvm::inconvertibleErrorCode());
+
+ ProcessSP process_sp = thread.GetProcess();
+ if (!process_sp)
+ return llvm::make_error<llvm::StringError>(
+ LOG_PREFIX "GetProcess() failed", llvm::inconvertibleErrorCode());
+
+ return ReturnValueExtractor(thread, type, reg_ctx, process_sp);
+ }
+
+ // main method: get value of the type specified at construction time
+ ValueObjectSP GetValue() {
+ const uint32_t type_flags = m_type.GetTypeInfo();
+
+ // call the appropriate type handler
+ ValueSP value_sp;
+ ValueObjectSP valobj_sp;
+ if (type_flags & eTypeIsScalar) {
+ if (type_flags & eTypeIsInteger) {
+ value_sp = GetIntegerValue(0);
+ } else if (type_flags & eTypeIsFloat) {
+ if (type_flags & eTypeIsComplex) {
+ LLDB_LOG(m_log, LOG_PREFIX "Complex numbers are not supported yet");
+ return ValueObjectSP();
+ } else {
+ value_sp = GetFloatValue(m_type, 0);
}
}
+ } else if (type_flags & eTypeIsPointer) {
+ value_sp = GetPointerValue(0);
}
+
+ if (value_sp) {
+ valobj_sp = ValueObjectConstResult::Create(
+ m_thread.GetStackFrameAtIndex(0).get(), *value_sp, ConstString(""));
+ } else if (type_flags & eTypeIsVector) {
+ valobj_sp = GetVectorValueObject();
+ } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) {
+ valobj_sp = GetStructValueObject();
+ }
+
+ return valobj_sp;
}
- return return_valobj_sp;
-}
+private:
+ // data
+ Thread &m_thread;
+ CompilerType &m_type;
+ uint64_t m_byte_size;
+ std::unique_ptr<DataBufferHeap> m_data_ap;
+ int32_t m_src_offs = 0;
+ int32_t m_dst_offs = 0;
+ bool m_packed = false;
+ Log *m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ RegisterContext *m_reg_ctx;
+ ProcessSP m_process_sp;
+ ByteOrder m_byte_order;
+ uint32_t m_addr_size;
+
+ // methods
+
+ // constructor
+ ReturnValueExtractor(Thread &thread, CompilerType &type,
+ RegisterContext *reg_ctx, ProcessSP process_sp)
+ : m_thread(thread), m_type(type),
+ m_byte_size(m_type.GetByteSize(nullptr)),
+ m_data_ap(new DataBufferHeap(m_byte_size, 0)), m_reg_ctx(reg_ctx),
+ m_process_sp(process_sp), m_byte_order(process_sp->GetByteOrder()),
+ m_addr_size(
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize()) {}
+
+ // build a new scalar value
+ ValueSP NewScalarValue(CompilerType &type) {
+ ValueSP value_sp(new Value);
+ value_sp->SetCompilerType(type);
+ value_sp->SetValueType(Value::eValueTypeScalar);
+ return value_sp;
+ }
-ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl(
- Thread &thread, CompilerType &return_compiler_type) const {
- ValueObjectSP return_valobj_sp;
-
- if (!return_compiler_type)
- return return_valobj_sp;
-
- ExecutionContext exe_ctx(thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
- if (return_valobj_sp)
- return return_valobj_sp;
-
- RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
- if (!reg_ctx_sp)
- return return_valobj_sp;
-
- const size_t bit_width = return_compiler_type.GetBitSize(&thread);
- if (return_compiler_type.IsAggregateType()) {
- Target *target = exe_ctx.GetTargetPtr();
- bool is_memory = true;
- if (bit_width <= 128) {
- ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
- DataBufferSP data_sp(new DataBufferHeap(16, 0));
- DataExtractor return_ext(data_sp, target_byte_order,
- target->GetArchitecture().GetAddressByteSize());
-
- const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
- const RegisterInfo *rdx_info =
- reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
-
- RegisterValue r3_value, rdx_value;
- reg_ctx_sp->ReadRegister(r3_info, r3_value);
- reg_ctx_sp->ReadRegister(rdx_info, rdx_value);
-
- DataExtractor r3_data, rdx_data;
-
- r3_value.GetData(r3_data);
- rdx_value.GetData(rdx_data);
-
- uint32_t fp_bytes =
- 0; // Tracks how much of the xmm registers we've consumed so far
- uint32_t integer_bytes =
- 0; // Tracks how much of the r3/rds registers we've consumed so far
-
- const uint32_t num_children = return_compiler_type.GetNumFields();
-
- // Since we are in the small struct regime, assume we are not in memory.
- is_memory = false;
-
- for (uint32_t idx = 0; idx < num_children; idx++) {
- std::string name;
- uint64_t field_bit_offset = 0;
- bool is_signed;
- bool is_complex;
- uint32_t count;
-
- CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
- idx, name, &field_bit_offset, nullptr, nullptr);
- const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
-
- // If there are any unaligned fields, this is stored in memory.
- if (field_bit_offset % field_bit_width != 0) {
- is_memory = true;
- break;
+ // get an integer value in the specified register
+ ValueSP GetIntegerValue(uint32_t reg_index) {
+ uint64_t raw_value;
+ auto reg = GetGPR(reg_index);
+ if (!reg.GetRawData(raw_value))
+ return ValueSP();
+
+ // build value from data
+ ValueSP value_sp(NewScalarValue(m_type));
+
+ uint32_t type_flags = m_type.GetTypeInfo();
+ bool is_signed = (type_flags & eTypeIsSigned) != 0;
+
+ switch (m_byte_size) {
+ case sizeof(uint64_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int64_t)(raw_value);
+ else
+ value_sp->GetScalar() = (uint64_t)(raw_value);
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value_sp->GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value_sp->GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value_sp->GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ break;
+
+ default:
+ llvm_unreachable("Invalid integer size");
+ }
+
+ return value_sp;
+ }
+
+ // get a floating point value on the specified register
+ ValueSP GetFloatValue(CompilerType &type, uint32_t reg_index) {
+ uint64_t raw_data;
+ auto reg = GetFPR(reg_index);
+ if (!reg.GetRawData(raw_data))
+ return ValueSP();
+
+ // build value from data
+ ValueSP value_sp(NewScalarValue(type));
+
+ DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size);
+
+ offset_t offset = 0;
+ size_t byte_size = type.GetByteSize(nullptr);
+ switch (byte_size) {
+ case sizeof(float):
+ value_sp->GetScalar() = (float)de.GetDouble(&offset);
+ break;
+
+ case sizeof(double):
+ value_sp->GetScalar() = de.GetDouble(&offset);
+ break;
+
+ default:
+ llvm_unreachable("Invalid floating point size");
+ }
+
+ return value_sp;
+ }
+
+ // get pointer value from register
+ ValueSP GetPointerValue(uint32_t reg_index) {
+ uint64_t raw_data;
+ auto reg = GetGPR(reg_index);
+ if (!reg.GetRawData(raw_data))
+ return ValueSP();
+
+ // build value from raw data
+ ValueSP value_sp(NewScalarValue(m_type));
+ value_sp->GetScalar() = raw_data;
+ return value_sp;
+ }
+
+ // build the ValueObject from our data buffer
+ ValueObjectSP BuildValueObject() {
+ DataExtractor de(DataBufferSP(m_data_ap.release()), m_byte_order,
+ m_addr_size);
+ return ValueObjectConstResult::Create(&m_thread, m_type, ConstString(""),
+ de);
+ }
+
+ // get a vector return value
+ ValueObjectSP GetVectorValueObject() {
+ const uint32_t MAX_VRS = 2;
+
+ // get first V register used to return values
+ const RegisterInfo *vr[MAX_VRS];
+ vr[0] = m_reg_ctx->GetRegisterInfoByName("vr2");
+ if (!vr[0]) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr2 RegisterInfo");
+ return ValueObjectSP();
+ }
+
+ const uint32_t vr_size = vr[0]->byte_size;
+ size_t vrs = 1;
+ if (m_byte_size > 2 * vr_size) {
+ LLDB_LOG(
+ m_log, LOG_PREFIX
+ "Returning vectors that don't fit in 2 VR regs is not supported");
+ return ValueObjectSP();
+ }
+
+ // load vr3, if needed
+ if (m_byte_size > vr_size) {
+ vrs++;
+ vr[1] = m_reg_ctx->GetRegisterInfoByName("vr3");
+ if (!vr[1]) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr3 RegisterInfo");
+ return ValueObjectSP();
+ }
+ }
+
+ // Get the whole contents of vector registers and let the logic here
+ // arrange the data properly.
+
+ RegisterValue vr_val[MAX_VRS];
+ Status error;
+ std::unique_ptr<DataBufferHeap> vr_data(
+ new DataBufferHeap(vrs * vr_size, 0));
+
+ for (uint32_t i = 0; i < vrs; i++) {
+ if (!m_reg_ctx->ReadRegister(vr[i], vr_val[i])) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to read vector register contents");
+ return ValueObjectSP();
+ }
+ if (!vr_val[i].GetAsMemoryData(vr[i], vr_data->GetBytes() + i * vr_size,
+ vr_size, m_byte_order, error)) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to extract vector register bytes");
+ return ValueObjectSP();
+ }
+ }
+
+ // The compiler generated code seems to always put the vector elements at
+ // the end of the vector register, in case they don't occupy all of it.
+ // This offset variable handles this.
+ uint32_t offs = 0;
+ if (m_byte_size < vr_size)
+ offs = vr_size - m_byte_size;
+
+ // copy extracted data to our buffer
+ memcpy(m_data_ap->GetBytes(), vr_data->GetBytes() + offs, m_byte_size);
+ return BuildValueObject();
+ }
+
+ // get a struct return value
+ ValueObjectSP GetStructValueObject() {
+ // case 1: get from stack
+ if (m_byte_size > 2 * sizeof(uint64_t)) {
+ uint64_t addr;
+ auto reg = GetGPR(0);
+ if (!reg.GetRawData(addr))
+ return ValueObjectSP();
+
+ Status error;
+ size_t rc = m_process_sp->ReadMemory(addr, m_data_ap->GetBytes(),
+ m_byte_size, error);
+ if (rc != m_byte_size) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to read memory pointed by r3");
+ return ValueObjectSP();
+ }
+ return BuildValueObject();
+ }
+
+ // get number of children
+ const bool omit_empty_base_classes = true;
+ uint32_t n = m_type.GetNumChildren(omit_empty_base_classes);
+ if (!n) {
+ LLDB_LOG(m_log, LOG_PREFIX "No children found in struct");
+ return ValueObjectSP();
+ }
+
+ // case 2: homogeneous double or float aggregate
+ CompilerType elem_type;
+ if (m_type.IsHomogeneousAggregate(&elem_type)) {
+ uint32_t type_flags = elem_type.GetTypeInfo();
+ uint64_t elem_size = elem_type.GetByteSize(nullptr);
+ if (type_flags & eTypeIsComplex || !(type_flags & eTypeIsFloat)) {
+ LLDB_LOG(m_log,
+ LOG_PREFIX "Unexpected type found in homogeneous aggregate");
+ return ValueObjectSP();
+ }
+
+ for (uint32_t i = 0; i < n; i++) {
+ ValueSP val_sp = GetFloatValue(elem_type, i);
+ if (!val_sp)
+ return ValueObjectSP();
+
+ // copy to buffer
+ Status error;
+ size_t rc = val_sp->GetScalar().GetAsMemoryData(
+ m_data_ap->GetBytes() + m_dst_offs, elem_size, m_byte_order, error);
+ if (rc != elem_size) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get float data");
+ return ValueObjectSP();
}
+ m_dst_offs += elem_size;
+ }
+ return BuildValueObject();
+ }
- uint32_t field_byte_width = field_bit_width / 8;
- uint32_t field_byte_offset = field_bit_offset / 8;
-
- DataExtractor *copy_from_extractor = nullptr;
- uint32_t copy_from_offset = 0;
-
- if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
- field_compiler_type.IsPointerType()) {
- if (integer_bytes < 8) {
- if (integer_bytes + field_byte_width <= 8) {
- // This is in RAX, copy from register to our result structure:
- copy_from_extractor = &r3_data;
- copy_from_offset = integer_bytes;
- integer_bytes += field_byte_width;
- } else {
- // The next field wouldn't fit in the remaining space, so we
- // pushed it to rdx.
- copy_from_extractor = &rdx_data;
- copy_from_offset = 0;
- integer_bytes = 8 + field_byte_width;
- }
- } else if (integer_bytes + field_byte_width <= 16) {
- copy_from_extractor = &rdx_data;
- copy_from_offset = integer_bytes - 8;
- integer_bytes += field_byte_width;
- } else {
- // The last field didn't fit. I can't see how that would happen w/o
- // the overall size being
- // greater than 16 bytes. For now, return a nullptr return value
- // object.
- return return_valobj_sp;
- }
- } else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
- // Structs with long doubles are always passed in memory.
- if (field_bit_width == 128) {
- is_memory = true;
+ // case 3: get from GPRs
+
+ // first, check if this is a packed struct or not
+ ClangASTContext *ast =
+ llvm::dyn_cast<ClangASTContext>(m_type.GetTypeSystem());
+ if (ast) {
+ clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(m_type);
+
+ if (record_decl) {
+ auto attrs = record_decl->attrs();
+ for (const auto &attr : attrs) {
+ if (attr->getKind() == clang::attr::Packed) {
+ m_packed = true;
break;
- } else if (field_bit_width == 64) {
- copy_from_offset = 0;
- fp_bytes += field_byte_width;
- } else if (field_bit_width == 32) {
- // This one is kind of complicated. If we are in an "eightbyte"
- // with another float, we'll
- // be stuffed into an xmm register with it. If we are in an
- // "eightbyte" with one or more ints,
- // then we will be stuffed into the appropriate GPR with them.
- bool in_gpr;
- if (field_byte_offset % 8 == 0) {
- // We are at the beginning of one of the eightbytes, so check the
- // next element (if any)
- if (idx == num_children - 1)
- in_gpr = false;
- else {
- uint64_t next_field_bit_offset = 0;
- CompilerType next_field_compiler_type =
- return_compiler_type.GetFieldAtIndex(idx + 1, name,
- &next_field_bit_offset,
- nullptr, nullptr);
- if (next_field_compiler_type.IsIntegerOrEnumerationType(
- is_signed))
- in_gpr = true;
- else {
- copy_from_offset = 0;
- in_gpr = false;
- }
- }
- } else if (field_byte_offset % 4 == 0) {
- // We are inside of an eightbyte, so see if the field before us is
- // floating point:
- // This could happen if somebody put padding in the structure.
- if (idx == 0)
- in_gpr = false;
- else {
- uint64_t prev_field_bit_offset = 0;
- CompilerType prev_field_compiler_type =
- return_compiler_type.GetFieldAtIndex(idx - 1, name,
- &prev_field_bit_offset,
- nullptr, nullptr);
- if (prev_field_compiler_type.IsIntegerOrEnumerationType(
- is_signed))
- in_gpr = true;
- else {
- copy_from_offset = 4;
- in_gpr = false;
- }
- }
- } else {
- is_memory = true;
- continue;
- }
-
- // Okay, we've figured out whether we are in GPR or XMM, now figure
- // out which one.
- if (in_gpr) {
- if (integer_bytes < 8) {
- // This is in RAX, copy from register to our result structure:
- copy_from_extractor = &r3_data;
- copy_from_offset = integer_bytes;
- integer_bytes += field_byte_width;
- } else {
- copy_from_extractor = &rdx_data;
- copy_from_offset = integer_bytes - 8;
- integer_bytes += field_byte_width;
- }
- } else {
- fp_bytes += field_byte_width;
- }
}
}
-
- // These two tests are just sanity checks. If I somehow get the
- // type calculation wrong above it is better to just return nothing
- // than to assert or crash.
- if (!copy_from_extractor)
- return return_valobj_sp;
- if (copy_from_offset + field_byte_width >
- copy_from_extractor->GetByteSize())
- return return_valobj_sp;
-
- copy_from_extractor->CopyByteOrderedData(
- copy_from_offset, field_byte_width,
- data_sp->GetBytes() + field_byte_offset, field_byte_width,
- target_byte_order);
}
+ }
- if (!is_memory) {
- // The result is in our data buffer. Let's make a variable object out
- // of it:
- return_valobj_sp = ValueObjectConstResult::Create(
- &thread, return_compiler_type, ConstString(""), return_ext);
- }
+ LLDB_LOG(m_log, LOG_PREFIX "{0} struct",
+ m_packed ? "packed" : "not packed");
+
+ for (uint32_t i = 0; i < n; i++) {
+ std::string name;
+ uint32_t size;
+ GetChildType(i, name, size);
+ // NOTE: the offset returned by GetChildCompilerTypeAtIndex()
+ // can't be used because it never considers alignment bytes
+ // between struct fields.
+ LLDB_LOG(m_log, LOG_PREFIX "field={0}, size={1}", name, size);
+ if (!ExtractField(size))
+ return ValueObjectSP();
}
- // FIXME: This is just taking a guess, r3 may very well no longer hold the
- // return storage location.
- // If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
- // only return the memory return value if we know it is valid.
-
- if (is_memory) {
- unsigned r3_id =
- reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
- lldb::addr_t storage_addr =
- (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id,
- 0);
- return_valobj_sp = ValueObjectMemory::Create(
- &thread, "", Address(storage_addr, nullptr), return_compiler_type);
+ return BuildValueObject();
+ }
+
+ // extract 'size' bytes at 'offs' from GPRs
+ bool ExtractFromRegs(int32_t offs, uint32_t size, void *buf) {
+ while (size) {
+ auto reg = GetGPRByOffs(offs);
+ if (!reg.IsValid())
+ return false;
+
+ uint32_t n = std::min(reg.Avail(), size);
+ uint64_t raw_data;
+
+ if (!reg.GetRawData(raw_data))
+ return false;
+
+ memcpy(buf, (char *)&raw_data + reg.Offs(), n);
+ offs += n;
+ size -= n;
+ buf = (char *)buf + n;
}
+ return true;
}
- return return_valobj_sp;
+ // extract one field from GPRs and put it in our buffer
+ bool ExtractField(uint32_t size) {
+ auto reg = GetGPRByOffs(m_src_offs);
+ if (!reg.IsValid())
+ return false;
+
+ // handle padding
+ if (!m_packed) {
+ uint32_t n = m_src_offs % size;
+
+ // not 'size' bytes aligned
+ if (n) {
+ LLDB_LOG(m_log,
+ LOG_PREFIX "Extracting {0} alignment bytes at offset {1}", n,
+ m_src_offs);
+ // get alignment bytes
+ if (!ExtractFromRegs(m_src_offs, n, m_data_ap->GetBytes() + m_dst_offs))
+ return false;
+ m_src_offs += n;
+ m_dst_offs += n;
+ }
+ }
+
+ // get field
+ LLDB_LOG(m_log, LOG_PREFIX "Extracting {0} field bytes at offset {1}", size,
+ m_src_offs);
+ if (!ExtractFromRegs(m_src_offs, size, m_data_ap->GetBytes() + m_dst_offs))
+ return false;
+ m_src_offs += size;
+ m_dst_offs += size;
+ return true;
+ }
+
+ // get child
+ CompilerType GetChildType(uint32_t i, std::string &name, uint32_t &size) {
+ // GetChild constant inputs
+ const bool transparent_pointers = false;
+ const bool omit_empty_base_classes = true;
+ const bool ignore_array_bounds = false;
+ // GetChild output params
+ int32_t child_offs;
+ uint32_t child_bitfield_bit_size;
+ uint32_t child_bitfield_bit_offset;
+ bool child_is_base_class;
+ bool child_is_deref_of_parent;
+ ValueObject *valobj = nullptr;
+ uint64_t language_flags;
+ ExecutionContext exe_ctx;
+ m_thread.CalculateExecutionContext(exe_ctx);
+
+ return m_type.GetChildCompilerTypeAtIndex(
+ &exe_ctx, i, transparent_pointers, omit_empty_base_classes,
+ ignore_array_bounds, name, size, child_offs, child_bitfield_bit_size,
+ child_bitfield_bit_offset, child_is_base_class,
+ child_is_deref_of_parent, valobj, language_flags);
+ }
+};
+
+#undef LOG_PREFIX
+
+} // anonymous namespace
+
+ValueObjectSP
+ABISysV_ppc64::GetReturnValueObjectSimple(Thread &thread,
+ CompilerType &type) const {
+ if (!type)
+ return ValueObjectSP();
+
+ auto exp_extractor = ReturnValueExtractor::Create(thread, type);
+ if (!exp_extractor) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ LLDB_LOG_ERROR(log, exp_extractor.takeError(),
+ "Extracting return value failed: {0}");
+ return ValueObjectSP();
+ }
+
+ return exp_extractor.get().GetValue();
+}
+
+ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl(
+ Thread &thread, CompilerType &return_compiler_type) const {
+ return GetReturnValueObjectSimple(thread, return_compiler_type);
}
bool ABISysV_ppc64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
- uint32_t lr_reg_num = dwarf_lr;
- uint32_t sp_reg_num = dwarf_r1;
- uint32_t pc_reg_num = dwarf_pc;
+ uint32_t lr_reg_num;
+ uint32_t sp_reg_num;
+ uint32_t pc_reg_num;
+
+ if (GetByteOrder() == lldb::eByteOrderLittle) {
+ lr_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le;
+ sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le;
+ pc_reg_num = ppc64le_dwarf::dwarf_pc_ppc64le;
+ } else {
+ lr_reg_num = ppc64_dwarf::dwarf_lr_ppc64;
+ sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64;
+ pc_reg_num = ppc64_dwarf::dwarf_pc_ppc64;
+ }
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -893,23 +989,33 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
- uint32_t sp_reg_num = dwarf_r1;
- uint32_t pc_reg_num = dwarf_lr;
+ uint32_t sp_reg_num;
+ uint32_t pc_reg_num;
+ uint32_t cr_reg_num;
- UnwindPlan::RowSP row(new UnwindPlan::Row);
+ if (GetByteOrder() == lldb::eByteOrderLittle) {
+ sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le;
+ pc_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le;
+ cr_reg_num = ppc64le_dwarf::dwarf_cr_ppc64le;
+ } else {
+ sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64;
+ pc_reg_num = ppc64_dwarf::dwarf_lr_ppc64;
+ cr_reg_num = ppc64_dwarf::dwarf_cr_ppc64;
+ }
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
- row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(cr_reg_num, ptr_size, true);
unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("ppc64 default unwind plan");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(dwarf_lr);
+ unwind_plan.SetReturnAddressRegister(pc_reg_num);
return true;
}
@@ -919,10 +1025,9 @@ bool ABISysV_ppc64::RegisterIsVolatile(const RegisterInfo *reg_info) {
// See "Register Usage" in the
// "System V Application Binary Interface"
-// "64-bit PowerPC ELF Application Binary Interface Supplement"
-// current version is 1.9 released 2004 at
-// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf
-
+// "64-bit PowerPC ELF Application Binary Interface Supplement" current version
+// is 2 released 2015 at
+// https://members.openpowerfoundation.org/document/dl/576
bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (reg_info) {
// Preserved registers are :
@@ -954,7 +1059,7 @@ bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
return true;
if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
- return true;
+ return false;
if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
index 21608a5c1cdd..52765a773c0b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
@@ -108,6 +108,8 @@ private:
ABISysV_ppc64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) {
// Call CreateInstance instead.
}
+
+ lldb::ByteOrder GetByteOrder() const;
};
#endif // liblldb_ABISysV_ppc64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
index 967e407188fa..31e2825c0fa2 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
@@ -380,8 +380,8 @@ bool ABISysV_s390x::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -483,8 +483,8 @@ Status ABISysV_s390x::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -618,9 +618,8 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectImpl(
// FIXME: This is just taking a guess, r2 may very well no longer hold the
// return storage location.
// If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
+ // check to see if it uses a memory return, and if we are at the first
+ // instruction and if so stash away the return location. Then we would
// only return the memory return value if we know it is valid.
unsigned r2_id =
@@ -654,8 +653,8 @@ bool ABISysV_s390x::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
}
bool ABISysV_s390x::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
- // There's really no default way to unwind on s390x.
- // Trust the .eh_frame CFI, which should always be good.
+ // There's really no default way to unwind on s390x. Trust the .eh_frame CFI,
+ // which should always be good.
return false;
}
@@ -663,8 +662,8 @@ bool ABISysV_s390x::GetFallbackRegisterLocation(
const RegisterInfo *reg_info,
UnwindPlan::Row::RegisterLocation &unwind_regloc) {
// If a volatile register is being requested, we don't want to forward the
- // next frame's register contents
- // up the stack -- the register is not retrievable at this frame.
+ // next frame's register contents up the stack -- the register is not
+ // retrievable at this frame.
if (RegisterIsVolatile(reg_info)) {
unwind_regloc.SetUndefined();
return true;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index 41d146f24526..36ae3a49827c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -1267,8 +1267,8 @@ bool ABISysV_x86_64::GetArgumentValues(Thread &thread,
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -1371,8 +1371,8 @@ Status ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -1624,8 +1624,8 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
idx, name, &field_bit_offset, nullptr, nullptr);
const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
- // if we don't know the size of the field (e.g. invalid type), just bail
- // out
+ // if we don't know the size of the field (e.g. invalid type), just
+ // bail out
if (field_bit_width == 0)
break;
@@ -1661,10 +1661,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
copy_from_offset = integer_bytes - 8;
integer_bytes += field_byte_width;
} else {
- // The last field didn't fit. I can't see how that would happen w/o
- // the overall size being
- // greater than 16 bytes. For now, return a nullptr return value
- // object.
+ // The last field didn't fit. I can't see how that would happen
+ // w/o the overall size being greater than 16 bytes. For now,
+ // return a nullptr return value object.
return return_valobj_sp;
}
} else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
@@ -1683,10 +1682,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
fp_bytes += field_byte_width;
} else if (field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
- // with another float, we'll
- // be stuffed into an xmm register with it. If we are in an
- // "eightbyte" with one or more ints,
- // then we will be stuffed into the appropriate GPR with them.
+ // with another float, we'll be stuffed into an xmm register with
+ // it. If we are in an "eightbyte" with one or more ints, then we
+ // will be stuffed into the appropriate GPR with them.
bool in_gpr;
if (field_byte_offset % 8 == 0) {
// We are at the beginning of one of the eightbytes, so check the
@@ -1708,9 +1706,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
}
}
} else if (field_byte_offset % 4 == 0) {
- // We are inside of an eightbyte, so see if the field before us is
- // floating point:
- // This could happen if somebody put padding in the structure.
+ // We are inside of an eightbyte, so see if the field before us
+ // is floating point: This could happen if somebody put padding
+ // in the structure.
if (idx == 0)
in_gpr = false;
else {
@@ -1756,9 +1754,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
}
}
- // These two tests are just sanity checks. If I somehow get the
- // type calculation wrong above it is better to just return nothing
- // than to assert or crash.
+ // These two tests are just sanity checks. If I somehow get the type
+ // calculation wrong above it is better to just return nothing than to
+ // assert or crash.
if (!copy_from_extractor)
return return_valobj_sp;
if (copy_from_offset + field_byte_width >
@@ -1782,9 +1780,8 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
// FIXME: This is just taking a guess, rax may very well no longer hold the
// return storage location.
// If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
+ // check to see if it uses a memory return, and if we are at the first
+ // instruction and if so stash away the return location. Then we would
// only return the memory return value if we know it is valid.
if (is_memory) {
@@ -1858,12 +1855,11 @@ bool ABISysV_x86_64::RegisterIsVolatile(const RegisterInfo *reg_info) {
// See "Register Usage" in the
// "System V Application Binary Interface"
-// "AMD64 Architecture Processor Supplement"
-// (or "x86-64(tm) Architecture Processor Supplement" in earlier revisions)
-// (this doc is also commonly referred to as the x86-64/AMD64 psABI)
-// Edited by Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
-// current version is 0.99.6 released 2012-07-02 at
-// http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf
+// "AMD64 Architecture Processor Supplement" (or "x86-64(tm) Architecture
+// Processor Supplement" in earlier revisions) (this doc is also commonly
+// referred to as the x86-64/AMD64 psABI) Edited by Michael Matz, Jan Hubicka,
+// Andreas Jaeger, and Mark Mitchell current version is 0.99.6 released
+// 2012-07-02 at http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf
// It's being revised & updated at https://github.com/hjl-tools/x86-psABI/
bool ABISysV_x86_64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
index abac6d3001af..1b7ecc88c35e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
@@ -41,32 +41,32 @@ std::unique_ptr<Architecture> ArchitectureArm::Create(const ArchSpec &arch) {
ConstString ArchitectureArm::GetPluginName() { return GetPluginNameStatic(); }
uint32_t ArchitectureArm::GetPluginVersion() { return 1; }
-void ArchitectureArm::OverrideStopInfo(Thread &thread) {
- // We need to check if we are stopped in Thumb mode in a IT instruction
- // and detect if the condition doesn't pass. If this is the case it means
- // we won't actually execute this instruction. If this happens we need to
- // clear the stop reason to no thread plans think we are stopped for a
- // reason and the plans should keep going.
+void ArchitectureArm::OverrideStopInfo(Thread &thread) const {
+ // We need to check if we are stopped in Thumb mode in a IT instruction and
+ // detect if the condition doesn't pass. If this is the case it means we
+ // won't actually execute this instruction. If this happens we need to clear
+ // the stop reason to no thread plans think we are stopped for a reason and
+ // the plans should keep going.
//
// We do this because when single stepping many ARM processes, debuggers
- // often use the BVR/BCR registers that says "stop when the PC is not
- // equal to its current value". This method of stepping means we can end
- // up stopping on instructions inside an if/then block that wouldn't get
- // executed. By fixing this we can stop the debugger from seeming like
- // you stepped through both the "if" _and_ the "else" clause when source
- // level stepping because the debugger stops regardless due to the BVR/BCR
+ // often use the BVR/BCR registers that says "stop when the PC is not equal
+ // to its current value". This method of stepping means we can end up
+ // stopping on instructions inside an if/then block that wouldn't get
+ // executed. By fixing this we can stop the debugger from seeming like you
+ // stepped through both the "if" _and_ the "else" clause when source level
+ // stepping because the debugger stops regardless due to the BVR/BCR
// triggering a stop.
//
- // It also means we can set breakpoints on instructions inside an an
- // if/then block and correctly skip them if we use the BKPT instruction.
- // The ARM and Thumb BKPT instructions are unconditional even when executed
- // in a Thumb IT block.
+ // It also means we can set breakpoints on instructions inside an an if/then
+ // block and correctly skip them if we use the BKPT instruction. The ARM and
+ // Thumb BKPT instructions are unconditional even when executed in a Thumb IT
+ // block.
//
- // If your debugger inserts software traps in ARM/Thumb code, it will
- // need to use 16 and 32 bit instruction for 16 and 32 bit thumb
- // instructions respectively. If your debugger inserts a 16 bit thumb
- // trap on top of a 32 bit thumb instruction for an opcode that is inside
- // an if/then, it will change the it/then to conditionally execute your
+ // If your debugger inserts software traps in ARM/Thumb code, it will need to
+ // use 16 and 32 bit instruction for 16 and 32 bit thumb instructions
+ // respectively. If your debugger inserts a 16 bit thumb trap on top of a 32
+ // bit thumb instruction for an opcode that is inside an if/then, it will
+ // change the it/then to conditionally execute your
// 16 bit trap and then cause your program to crash if it executes the
// trailing 16 bits (the second half of the 32 bit thumb instruction you
// partially overwrote).
@@ -85,23 +85,20 @@ void ArchitectureArm::OverrideStopInfo(Thread &thread) {
const uint32_t ISETSTATE = J << 1 | T;
if (ISETSTATE == 0) {
// NOTE: I am pretty sure we want to enable the code below
-// that detects when we stop on an instruction in ARM mode
-// that is conditional and the condition doesn't pass. This
-// can happen if you set a breakpoint on an instruction that
-// is conditional. We currently will _always_ stop on the
-// instruction which is bad. You can also run into this while
-// single stepping and you could appear to run code in the "if"
-// and in the "else" clause because it would stop at all of the
-// conditional instructions in both.
-// In such cases, we really don't want to stop at this location.
+// that detects when we stop on an instruction in ARM mode that is conditional
+// and the condition doesn't pass. This can happen if you set a breakpoint on
+// an instruction that is conditional. We currently will _always_ stop on the
+// instruction which is bad. You can also run into this while single stepping
+// and you could appear to run code in the "if" and in the "else" clause
+// because it would stop at all of the conditional instructions in both. In
+// such cases, we really don't want to stop at this location.
// I will check with the lldb-dev list first before I enable this.
#if 0
- // ARM mode: check for condition on intsruction
+ // ARM mode: check for condition on instruction
const addr_t pc = reg_ctx_sp->GetPC();
Status error;
- // If we fail to read the opcode we will get UINT64_MAX as the
- // result in "opcode" which we can use to detect if we read a
- // valid opcode.
+ // If we fail to read the opcode we will get UINT64_MAX as the result in
+ // "opcode" which we can use to detect if we read a valid opcode.
const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error);
if (opcode <= UINT32_MAX)
{
@@ -109,8 +106,8 @@ void ArchitectureArm::OverrideStopInfo(Thread &thread) {
if (!ARMConditionPassed(condition, cpsr))
{
// We ARE stopped on an ARM instruction whose condition doesn't
- // pass so this instruction won't get executed.
- // Regardless of why it stopped, we need to clear the stop info
+ // pass so this instruction won't get executed. Regardless of why
+ // it stopped, we need to clear the stop info
thread.SetStopInfo (StopInfoSP());
}
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.h b/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.h
index 9ce6c69ef271..484c4a52fcc6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.h
@@ -23,7 +23,7 @@ public:
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
- void OverrideStopInfo(Thread &thread) override;
+ void OverrideStopInfo(Thread &thread) const override;
private:
static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp
new file mode 100644
index 000000000000..619de093aacc
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp
@@ -0,0 +1,69 @@
+//===-- ArchitecturePPC64.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ArchSpec.h"
+
+#include "llvm/BinaryFormat/ELF.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+ConstString ArchitecturePPC64::GetPluginNameStatic() {
+ return ConstString("ppc64");
+}
+
+void ArchitecturePPC64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "PPC64-specific algorithms",
+ &ArchitecturePPC64::Create);
+}
+
+void ArchitecturePPC64::Terminate() {
+ PluginManager::UnregisterPlugin(&ArchitecturePPC64::Create);
+}
+
+std::unique_ptr<Architecture> ArchitecturePPC64::Create(const ArchSpec &arch) {
+ if ((arch.GetMachine() != llvm::Triple::ppc64 &&
+ arch.GetMachine() != llvm::Triple::ppc64le) ||
+ arch.GetTriple().getObjectFormat() != llvm::Triple::ObjectFormatType::ELF)
+ return nullptr;
+ return std::unique_ptr<Architecture>(new ArchitecturePPC64());
+}
+
+ConstString ArchitecturePPC64::GetPluginName() { return GetPluginNameStatic(); }
+uint32_t ArchitecturePPC64::GetPluginVersion() { return 1; }
+
+static int32_t GetLocalEntryOffset(const Symbol &sym) {
+ unsigned char other = sym.GetFlags() >> 8 & 0xFF;
+ return llvm::ELF::decodePPC64LocalEntryOffset(other);
+}
+
+size_t ArchitecturePPC64::GetBytesToSkip(Symbol &func,
+ const Address &curr_addr) const {
+ if (curr_addr.GetFileAddress() ==
+ func.GetFileAddress() + GetLocalEntryOffset(func))
+ return func.GetPrologueByteSize();
+ return 0;
+}
+
+void ArchitecturePPC64::AdjustBreakpointAddress(const Symbol &func,
+ Address &addr) const {
+ int32_t loffs = GetLocalEntryOffset(func);
+ if (!loffs)
+ return;
+
+ addr.SetOffset(addr.GetOffset() + loffs);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h b/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h
new file mode 100644
index 000000000000..95638853ad3d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h
@@ -0,0 +1,44 @@
+//===-- ArchitecturePPC64.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGIN_ARCHITECTURE_PPC64_H
+#define LLDB_PLUGIN_ARCHITECTURE_PPC64_H
+
+#include "lldb/Core/Architecture.h"
+
+namespace lldb_private {
+
+class ArchitecturePPC64 : public Architecture {
+public:
+ static ConstString GetPluginNameStatic();
+ static void Initialize();
+ static void Terminate();
+
+ ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+
+ void OverrideStopInfo(Thread &thread) const override {}
+
+ //------------------------------------------------------------------
+ /// This method compares current address with current function's
+ /// local entry point, returning the bytes to skip if they match.
+ //------------------------------------------------------------------
+ size_t GetBytesToSkip(Symbol &func, const Address &curr_addr) const override;
+
+ void AdjustBreakpointAddress(const Symbol &func,
+ Address &addr) const override;
+
+private:
+ static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
+ ArchitecturePPC64() = default;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_PLUGIN_ARCHITECTURE_PPC64_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/CMakeLists.txt b/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/CMakeLists.txt
new file mode 100644
index 000000000000..2cba112cf882
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Architecture/PPC64/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginArchitecturePPC64 PLUGIN
+ ArchitecturePPC64.cpp
+
+ LINK_LIBS
+ lldbPluginProcessUtility
+ lldbCore
+ lldbTarget
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index a61abb9898ac..9b381dd3b96c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -10,6 +10,9 @@
// C Includes
// C++ Includes
// Project includes
+#include "DisassemblerLLVMC.h"
+
+// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -27,9 +30,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
-// Other libraries and framework includes
-#include "DisassemblerLLVMC.h"
-
#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -41,13 +41,47 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Stream.h"
-
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
+class DisassemblerLLVMC::MCDisasmInstance {
+public:
+ static std::unique_ptr<MCDisasmInstance>
+ Create(const char *triple, const char *cpu, const char *features_str,
+ unsigned flavor, DisassemblerLLVMC &owner);
+
+ ~MCDisasmInstance() = default;
+
+ uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,
+ lldb::addr_t pc, llvm::MCInst &mc_inst) const;
+ void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string,
+ std::string &comments_string);
+ void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style);
+ bool CanBranch(llvm::MCInst &mc_inst) const;
+ bool HasDelaySlot(llvm::MCInst &mc_inst) const;
+ bool IsCall(llvm::MCInst &mc_inst) const;
+
+private:
+ MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
+ std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
+ std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
+ std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
+ std::unique_ptr<llvm::MCContext> &&context_up,
+ std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
+ std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up);
+
+ std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up;
+ std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up;
+ std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up;
+ std::unique_ptr<llvm::MCContext> m_context_up;
+ std::unique_ptr<llvm::MCDisassembler> m_disasm_up;
+ std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up;
+};
+
class InstructionLLVMC : public lldb_private::Instruction {
public:
InstructionLLVMC(DisassemblerLLVMC &disasm,
@@ -72,7 +106,7 @@ public:
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
@@ -107,7 +141,7 @@ public:
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
@@ -132,19 +166,19 @@ public:
return m_has_delay_slot == eLazyBoolYes;
}
- DisassemblerLLVMC::LLVMCDisassembler *GetDisasmToUse(bool &is_alternate_isa) {
+ DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) {
is_alternate_isa = false;
std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
if (disasm_sp) {
- if (disasm_sp->m_alternate_disasm_ap.get() != NULL) {
+ if (disasm_sp->m_alternate_disasm_up) {
const AddressClass address_class = GetAddressClass();
- if (address_class == eAddressClassCodeAlternateISA) {
+ if (address_class == AddressClass::eCodeAlternateISA) {
is_alternate_isa = true;
- return disasm_sp->m_alternate_disasm_ap.get();
+ return disasm_sp->m_alternate_disasm_up.get();
}
}
- return disasm_sp->m_disasm_ap.get();
+ return disasm_sp->m_disasm_up.get();
}
return nullptr;
}
@@ -197,7 +231,7 @@ public:
}
if (!got_op) {
bool is_alternate_isa = false;
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const llvm::Triple::ArchType machine = arch.GetMachine();
@@ -264,12 +298,12 @@ public:
std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
if (disasm_sp) {
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr;
- if (address_class == eAddressClassCodeAlternateISA)
- mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get();
+ if (address_class == AddressClass::eCodeAlternateISA)
+ mc_disasm_ptr = disasm_sp->m_alternate_disasm_up.get();
else
- mc_disasm_ptr = disasm_sp->m_disasm_ap.get();
+ mc_disasm_ptr = disasm_sp->m_disasm_up.get();
lldb::addr_t pc = m_address.GetFileAddress();
m_using_file_addr = true;
@@ -850,7 +884,7 @@ public:
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
@@ -881,80 +915,103 @@ protected:
bool m_using_file_addr;
};
-DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler(
- const char *triple, const char *cpu, const char *features_str,
- unsigned flavor, DisassemblerLLVMC &owner)
- : m_is_valid(true) {
+std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>
+DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu,
+ const char *features_str,
+ unsigned flavor,
+ DisassemblerLLVMC &owner) {
+ using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>;
+
std::string Status;
const llvm::Target *curr_target =
llvm::TargetRegistry::lookupTarget(triple, Status);
- if (!curr_target) {
- m_is_valid = false;
- return;
- }
+ if (!curr_target)
+ return Instance();
- m_instr_info_ap.reset(curr_target->createMCInstrInfo());
- m_reg_info_ap.reset(curr_target->createMCRegInfo(triple));
-
- m_subtarget_info_ap.reset(
- curr_target->createMCSubtargetInfo(triple, cpu, features_str));
+ std::unique_ptr<llvm::MCInstrInfo> instr_info_up(
+ curr_target->createMCInstrInfo());
+ if (!instr_info_up)
+ return Instance();
- std::unique_ptr<llvm::MCRegisterInfo> reg_info(
+ std::unique_ptr<llvm::MCRegisterInfo> reg_info_up(
curr_target->createMCRegInfo(triple));
- m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple));
+ if (!reg_info_up)
+ return Instance();
- if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL ||
- m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL) {
- m_is_valid = false;
- return;
- }
-
- m_context_ap.reset(
- new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0));
-
- m_disasm_ap.reset(curr_target->createMCDisassembler(
- *m_subtarget_info_ap.get(), *m_context_ap.get()));
- if (m_disasm_ap.get() && m_context_ap.get()) {
- std::unique_ptr<llvm::MCRelocationInfo> RelInfo(
- curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
- if (!RelInfo) {
- m_is_valid = false;
- return;
- }
- std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
- curr_target->createMCSymbolizer(
- triple, NULL, DisassemblerLLVMC::SymbolLookupCallback,
- (void *)&owner, m_context_ap.get(), std::move(RelInfo)));
- m_disasm_ap->setSymbolizer(std::move(symbolizer_up));
-
- unsigned asm_printer_variant;
- if (flavor == ~0U)
- asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
- else {
- asm_printer_variant = flavor;
- }
-
- m_instr_printer_ap.reset(curr_target->createMCInstPrinter(
- llvm::Triple{triple}, asm_printer_variant, *m_asm_info_ap.get(),
- *m_instr_info_ap.get(), *m_reg_info_ap.get()));
- if (m_instr_printer_ap.get() == NULL) {
- m_disasm_ap.reset();
- m_is_valid = false;
- }
- } else
- m_is_valid = false;
+ std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up(
+ curr_target->createMCSubtargetInfo(triple, cpu, features_str));
+ if (!subtarget_info_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
+ curr_target->createMCAsmInfo(*reg_info_up, triple));
+ if (!asm_info_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCContext> context_up(
+ new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), 0));
+ if (!context_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCDisassembler> disasm_up(
+ curr_target->createMCDisassembler(*subtarget_info_up, *context_up));
+ if (!disasm_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCRelocationInfo> rel_info_up(
+ curr_target->createMCRelocationInfo(triple, *context_up));
+ if (!rel_info_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
+ curr_target->createMCSymbolizer(
+ triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner,
+ context_up.get(), std::move(rel_info_up)));
+ disasm_up->setSymbolizer(std::move(symbolizer_up));
+
+ unsigned asm_printer_variant =
+ flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor;
+
+ std::unique_ptr<llvm::MCInstPrinter> instr_printer_up(
+ curr_target->createMCInstPrinter(llvm::Triple{triple},
+ asm_printer_variant, *asm_info_up,
+ *instr_info_up, *reg_info_up));
+ if (!instr_printer_up)
+ return Instance();
+
+ return Instance(
+ new MCDisasmInstance(std::move(instr_info_up), std::move(reg_info_up),
+ std::move(subtarget_info_up), std::move(asm_info_up),
+ std::move(context_up), std::move(disasm_up),
+ std::move(instr_printer_up)));
}
-DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;
+DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance(
+ std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
+ std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
+ std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
+ std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
+ std::unique_ptr<llvm::MCContext> &&context_up,
+ std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
+ std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up)
+ : m_instr_info_up(std::move(instr_info_up)),
+ m_reg_info_up(std::move(reg_info_up)),
+ m_subtarget_info_up(std::move(subtarget_info_up)),
+ m_asm_info_up(std::move(asm_info_up)),
+ m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)),
+ m_instr_printer_up(std::move(instr_printer_up)) {
+ assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up &&
+ m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up);
+}
-uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst(
+uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst(
const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc,
- llvm::MCInst &mc_inst) {
+ llvm::MCInst &mc_inst) const {
llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
llvm::MCDisassembler::DecodeStatus status;
uint64_t new_inst_size;
- status = m_disasm_ap->getInstruction(mc_inst, new_inst_size, data, pc,
+ status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc,
llvm::nulls(), llvm::nulls());
if (status == llvm::MCDisassembler::Success)
return new_inst_size;
@@ -962,16 +1019,16 @@ uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst(
return 0;
}
-void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst(
+void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst(
llvm::MCInst &mc_inst, std::string &inst_string,
std::string &comments_string) {
llvm::raw_string_ostream inst_stream(inst_string);
llvm::raw_string_ostream comments_stream(comments_string);
- m_instr_printer_ap->setCommentStream(comments_stream);
- m_instr_printer_ap->printInst(&mc_inst, inst_stream, llvm::StringRef(),
- *m_subtarget_info_ap);
- m_instr_printer_ap->setCommentStream(llvm::nulls());
+ m_instr_printer_up->setCommentStream(comments_stream);
+ m_instr_printer_up->printInst(&mc_inst, inst_stream, llvm::StringRef(),
+ *m_subtarget_info_up);
+ m_instr_printer_up->setCommentStream(llvm::nulls());
comments_stream.flush();
static std::string g_newlines("\r\n");
@@ -985,30 +1042,32 @@ void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst(
}
}
-void DisassemblerLLVMC::LLVMCDisassembler::SetStyle(
+void DisassemblerLLVMC::MCDisasmInstance::SetStyle(
bool use_hex_immed, HexImmediateStyle hex_style) {
- m_instr_printer_ap->setPrintImmHex(use_hex_immed);
+ m_instr_printer_up->setPrintImmHex(use_hex_immed);
switch (hex_style) {
case eHexStyleC:
- m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::C);
+ m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C);
break;
case eHexStyleAsm:
- m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::Asm);
+ m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm);
break;
}
}
-bool DisassemblerLLVMC::LLVMCDisassembler::CanBranch(llvm::MCInst &mc_inst) {
- return m_instr_info_ap->get(mc_inst.getOpcode())
- .mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
+bool DisassemblerLLVMC::MCDisasmInstance::CanBranch(
+ llvm::MCInst &mc_inst) const {
+ return m_instr_info_up->get(mc_inst.getOpcode())
+ .mayAffectControlFlow(mc_inst, *m_reg_info_up);
}
-bool DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot(llvm::MCInst &mc_inst) {
- return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();
+bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot(
+ llvm::MCInst &mc_inst) const {
+ return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot();
}
-bool DisassemblerLLVMC::LLVMCDisassembler::IsCall(llvm::MCInst &mc_inst) {
- return m_instr_info_ap->get(mc_inst.getOpcode()).isCall();
+bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const {
+ return m_instr_info_up->get(mc_inst.getOpcode()).isCall();
}
DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
@@ -1023,8 +1082,7 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
llvm::Triple triple = arch.GetTriple();
// So far the only supported flavor is "intel" on x86. The base class will
- // set this
- // correctly coming in.
+ // set this correctly coming in.
if (triple.getArch() == llvm::Triple::x86 ||
triple.getArch() == llvm::Triple::x86_64) {
if (m_flavor == "intel") {
@@ -1048,12 +1106,10 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
}
// If no sub architecture specified then use the most recent arm architecture
- // so the
- // disassembler will return all instruction. Without it we will see a lot of
- // unknow opcode
- // in case the code uses instructions which are not available in the oldest
- // arm version
- // (used when no sub architecture is specified)
+ // so the disassembler will return all instruction. Without it we will see a
+ // lot of unknow opcode in case the code uses instructions which are not
+ // available in the oldest arm version (used when no sub architecture is
+ // specified)
if (triple.getArch() == llvm::Triple::arm &&
triple.getSubArch() == llvm::Triple::NoSubArch)
triple.setArchName("armv8.2a");
@@ -1127,20 +1183,16 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
features_str += "+dspr2,";
}
- // If any AArch64 variant, enable the ARMv8.2 ISA
- // extensions so we can disassemble newer instructions.
+ // If any AArch64 variant, enable the ARMv8.2 ISA extensions so we can
+ // disassemble newer instructions.
if (triple.getArch() == llvm::Triple::aarch64)
features_str += "+v8.2a";
- m_disasm_ap.reset(new LLVMCDisassembler(triple_str, cpu, features_str.c_str(),
- flavor, *this));
- if (!m_disasm_ap->IsValid()) {
- // We use m_disasm_ap.get() to tell whether we are valid or not, so if this
- // isn't good for some reason,
- // we reset it, and then we won't be valid and FindPlugin will fail and we
- // won't get used.
- m_disasm_ap.reset();
- }
+ // We use m_disasm_ap.get() to tell whether we are valid or not, so if this
+ // isn't good for some reason, we won't be valid and FindPlugin will fail and
+ // we won't get used.
+ m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(),
+ flavor, *this);
llvm::Triple::ArchType llvm_arch = triple.getArch();
@@ -1148,12 +1200,11 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
// thumb instruction disassembler.
if (llvm_arch == llvm::Triple::arm) {
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
- m_alternate_disasm_ap.reset(
- new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this));
- if (!m_alternate_disasm_ap->IsValid()) {
- m_disasm_ap.reset();
- m_alternate_disasm_ap.reset();
- }
+ m_alternate_disasm_up =
+ MCDisasmInstance::Create(thumb_triple.c_str(), "", "", flavor, *this);
+ if (!m_alternate_disasm_up)
+ m_disasm_up.reset();
+
} else if (llvm_arch == llvm::Triple::mips ||
llvm_arch == llvm::Triple::mipsel ||
llvm_arch == llvm::Triple::mips64 ||
@@ -1165,12 +1216,10 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
else if (arch_flags & ArchSpec::eMIPSAse_micromips)
features_str += "+micromips,";
- m_alternate_disasm_ap.reset(new LLVMCDisassembler(
- triple_str, cpu, features_str.c_str(), flavor, *this));
- if (!m_alternate_disasm_ap->IsValid()) {
- m_disasm_ap.reset();
- m_alternate_disasm_ap.reset();
- }
+ m_alternate_disasm_up = MCDisasmInstance::Create(
+ triple_str, cpu, features_str.c_str(), flavor, *this);
+ if (!m_alternate_disasm_up)
+ m_disasm_up.reset();
}
}
@@ -1208,9 +1257,9 @@ size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr,
while (data_cursor < data_byte_size &&
instructions_parsed < num_instructions) {
- AddressClass address_class = eAddressClassCode;
+ AddressClass address_class = AddressClass::eCode;
- if (m_alternate_disasm_ap.get() != NULL)
+ if (m_alternate_disasm_up)
address_class = inst_addr.GetAddressClass();
InstructionSP inst_sp(
@@ -1285,6 +1334,8 @@ bool DisassemblerLLVMC::FlavorValidForArchSpec(
return false;
}
+bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); }
+
int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size,
int tag_type, void *tag_bug) {
switch (tag_type) {
@@ -1337,8 +1388,8 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
}
}
- // If the "value" address (the target address we're symbolicating)
- // is inside the same SymbolContext as the current instruction pc
+ // If the "value" address (the target address we're symbolicating) is
+ // inside the same SymbolContext as the current instruction pc
// (pc_so_addr), don't print the full function name - just print it
// with DumpStyleNoFunctionName style, e.g. "<+36>".
if (format_omitting_current_func_name) {
@@ -1353,9 +1404,8 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
if (!ss.GetString().empty()) {
// If Address::Dump returned a multi-line description, most commonly
- // seen when we
- // have multiple levels of inlined functions at an address, only show
- // the first line.
+ // seen when we have multiple levels of inlined functions at an
+ // address, only show the first line.
std::string str = ss.GetString();
size_t first_eol_char = str.find_first_of("\r\n");
if (first_eol_char != std::string::npos) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index 26bed7ee0d7b..b7e9ccb34701 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -16,62 +16,14 @@
#include <mutex>
#include <string>
-// Other libraries and framework includes
-#include "llvm-c/Disassembler.h"
-
// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/PluginManager.h"
-// Opaque references to C++ Objects in LLVM's MC.
-namespace llvm {
-class MCContext;
-class MCInst;
-class MCInstrInfo;
-class MCRegisterInfo;
-class MCDisassembler;
-class MCInstPrinter;
-class MCAsmInfo;
-class MCSubtargetInfo;
-} // namespace llvm
-
class InstructionLLVMC;
class DisassemblerLLVMC : public lldb_private::Disassembler {
- // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB),
- // and there's a bit of goo to set up and own
- // in the MC disassembler world, I added this class to manage the actual
- // disassemblers.
- class LLVMCDisassembler {
- public:
- LLVMCDisassembler(const char *triple, const char *cpu,
- const char *features_str, unsigned flavor,
- DisassemblerLLVMC &owner);
-
- ~LLVMCDisassembler();
-
- uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,
- lldb::addr_t pc, llvm::MCInst &mc_inst);
- void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string,
- std::string &comments_string);
- void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style);
- bool CanBranch(llvm::MCInst &mc_inst);
- bool HasDelaySlot(llvm::MCInst &mc_inst);
- bool IsCall(llvm::MCInst &mc_inst);
- bool IsValid() { return m_is_valid; }
-
- private:
- bool m_is_valid;
- std::unique_ptr<llvm::MCContext> m_context_ap;
- std::unique_ptr<llvm::MCAsmInfo> m_asm_info_ap;
- std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_ap;
- std::unique_ptr<llvm::MCInstrInfo> m_instr_info_ap;
- std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_ap;
- std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_ap;
- std::unique_ptr<llvm::MCDisassembler> m_disasm_ap;
- };
-
public:
DisassemblerLLVMC(const lldb_private::ArchSpec &arch,
const char *flavor /* = NULL */);
@@ -108,9 +60,7 @@ protected:
bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch,
const char *flavor) override;
- bool IsValid() {
- return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid());
- }
+ bool IsValid() const;
int OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, int TagType,
void *TagBug);
@@ -145,8 +95,12 @@ protected:
std::mutex m_mutex;
bool m_data_from_file;
- std::unique_ptr<LLVMCDisassembler> m_disasm_ap;
- std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
+ // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB),
+ // and there's a bit of goo to set up and own in the MC disassembler world,
+ // this class was added to manage the actual disassemblers.
+ class MCDisasmInstance;
+ std::unique_ptr<MCDisasmInstance> m_disasm_up;
+ std::unique_ptr<MCDisasmInstance> m_alternate_disasm_up;
};
#endif // liblldb_DisassemblerLLVM_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index d0d60017e869..5ca20229d018 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -127,8 +127,8 @@ void DynamicLoaderHexagonDYLD::DidAttach() {
executable = GetTargetExecutable();
- // Find the difference between the desired load address in the elf file
- // and the real load address in memory
+ // Find the difference between the desired load address in the elf file and
+ // the real load address in memory
load_offset = ComputeLoadOffset();
// Check that there is a valid executable
@@ -157,10 +157,10 @@ void DynamicLoaderHexagonDYLD::DidAttach() {
// Callback for the target to give it the loaded module list
m_process->GetTarget().ModulesDidLoad(module_list);
- // Try to set a breakpoint at the rendezvous breakpoint.
- // DidLaunch uses ProbeEntry() instead. That sets a breakpoint,
- // at the dyld breakpoint address, with a callback so that when hit,
- // the dyld structure can be parsed.
+ // Try to set a breakpoint at the rendezvous breakpoint. DidLaunch uses
+ // ProbeEntry() instead. That sets a breakpoint, at the dyld breakpoint
+ // address, with a callback so that when hit, the dyld structure can be
+ // parsed.
if (!SetRendezvousBreakpoint()) {
// fail
}
@@ -203,8 +203,8 @@ ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() {
// TODO: What case is this code used?
executable = target.GetSharedModule(module_spec);
if (executable.get() != target.GetExecutableModulePointer()) {
- // Don't load dependent images since we are in dyld where we will know
- // and find out about all images that are loaded
+ // Don't load dependent images since we are in dyld where we will know and
+ // find out about all images that are loaded
const bool get_dependent_images = false;
target.SetExecutableModule(executable, get_dependent_images);
}
@@ -270,9 +270,8 @@ bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() {
// This is the original code, which want to look in the rendezvous structure
// to find the breakpoint address. Its backwards for us, since we can easily
- // find the breakpoint address, since it is exported in our executable.
- // We however know that we cant read the Rendezvous structure until we have
- // hit
+ // find the breakpoint address, since it is exported in our executable. We
+ // however know that we cant read the Rendezvous structure until we have hit
// the breakpoint once.
const ConstString dyldBpName("_rtld_debug_state");
addr_t break_addr = findSymbolAddress(m_process, dyldBpName);
@@ -326,8 +325,8 @@ bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit(
DynamicLoaderHexagonDYLD *dyld_instance = nullptr;
dyld_instance = static_cast<DynamicLoaderHexagonDYLD *>(baton);
- // if the dyld_instance is still not valid then
- // try to locate it on the symbol table
+ // if the dyld_instance is still not valid then try to locate it on the
+ // symbol table
if (!dyld_instance->m_rendezvous.IsValid()) {
Process *proc = dyld_instance->m_process;
@@ -480,8 +479,8 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() {
return;
}
- // The rendezvous class doesn't enumerate the main module, so track
- // that ourselves here.
+ // The rendezvous class doesn't enumerate the main module, so track that
+ // ourselves here.
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
@@ -517,12 +516,11 @@ addr_t DynamicLoaderHexagonDYLD::ComputeLoadOffset() {
return 0;
}
-// Here we must try to read the entry point directly from
-// the elf header. This is possible if the process is not
-// relocatable or dynamically linked.
+// Here we must try to read the entry point directly from the elf header. This
+// is possible if the process is not relocatable or dynamically linked.
//
-// an alternative is to look at the PC if we can be sure
-// that we have connected when the process is at the entry point.
+// an alternative is to look at the PC if we can be sure that we have connected
+// when the process is at the entry point.
// I dont think that is reliable for us.
addr_t DynamicLoaderHexagonDYLD::GetEntryPoint() {
if (m_entry_point != LLDB_INVALID_ADDRESS)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
index c49cdc2f11b1..d5f60e07bd77 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
@@ -115,8 +115,8 @@ bool HexagonDYLDRendezvous::UpdateSOEntries() {
if (m_current.map_addr == 0)
return false;
- // When the previous and current states are consistent this is the first
- // time we have been asked to update. Just take a snapshot of the currently
+ // When the previous and current states are consistent this is the first time
+ // we have been asked to update. Just take a snapshot of the currently
// loaded modules.
if (m_previous.state == eConsistent && m_current.state == eConsistent)
return TakeSnapshot(m_soentries);
@@ -126,8 +126,8 @@ bool HexagonDYLDRendezvous::UpdateSOEntries() {
if (m_current.state == eAdd || m_current.state == eDelete) {
// this is a fudge so that we can clear the assert below.
m_previous.state = eConsistent;
- // We hit this assert on the 2nd run of this function after running the calc
- // example
+ // We hit this assert on the 2nd run of this function after running the
+ // calc example
assert(m_previous.state == eConsistent);
m_soentries.clear();
m_added_soentries.clear();
@@ -159,9 +159,9 @@ bool HexagonDYLDRendezvous::UpdateSOEntriesForAddition() {
if (!ReadSOEntryFromMemory(cursor, entry))
return false;
- // Only add shared libraries and not the executable.
- // On Linux this is indicated by an empty path in the entry.
- // On FreeBSD it is the name of the executable.
+ // Only add shared libraries and not the executable. On Linux this is
+ // indicated by an empty path in the entry. On FreeBSD it is the name of
+ // the executable.
if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
continue;
@@ -204,9 +204,9 @@ bool HexagonDYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
if (!ReadSOEntryFromMemory(cursor, entry))
return false;
- // Only add shared libraries and not the executable.
- // On Linux this is indicated by an empty path in the entry.
- // On FreeBSD it is the name of the executable.
+ // Only add shared libraries and not the executable. On Linux this is
+ // indicated by an empty path in the entry. On FreeBSD it is the name of
+ // the executable.
if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
continue;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
index b68f89b9ce83..bdf6bae75197 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
@@ -11,8 +11,10 @@
#define liblldb_HexagonDYLDRendezvous_H_
// C Includes
+#include <limits.h> // for PATH_MAX
// C++ Includes
#include <list>
+#include <map>
#include <string>
// Other libraries and framework includes
@@ -24,12 +26,12 @@ class Process;
}
/// @class HexagonDYLDRendezvous
-/// @brief Interface to the runtime linker.
+/// Interface to the runtime linker.
///
/// A structure is present in a processes memory space which is updated by the
-/// runtime liker each time a module is loaded or unloaded. This class provides
-/// an interface to this structure and maintains a consistent snapshot of the
-/// currently loaded modules.
+/// runtime liker each time a module is loaded or unloaded. This class
+/// provides an interface to this structure and maintains a consistent
+/// snapshot of the currently loaded modules.
class HexagonDYLDRendezvous {
// This structure is used to hold the contents of the debug rendezvous
@@ -124,7 +126,7 @@ public:
void DumpToLog(lldb_private::Log *log) const;
- /// @brief Constants describing the state of the rendezvous.
+ /// Constants describing the state of the rendezvous.
///
/// @see GetState().
enum RendezvousState {
@@ -133,8 +135,8 @@ public:
eDelete,
};
- /// @brief Structure representing the shared objects currently loaded into
- /// the inferior process.
+ /// Structure representing the shared objects currently loaded into the
+ /// inferior process.
///
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
@@ -198,7 +200,8 @@ protected:
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
- /// List of SOEntry's added to the link map since the last call to Resolve().
+ /// List of SOEntry's added to the link map since the last call to
+ /// Resolve().
SOEntryList m_added_soentries;
/// List of SOEntry's removed from the link map since the last call to
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
index cf9da0808357..3b06fe18f0c6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
@@ -22,12 +22,12 @@ class DataExtractor;
}
/// @class AuxVector
-/// @brief Represents a processes auxiliary vector.
+/// Represents a processes auxiliary vector.
///
/// When a process is loaded on Linux a vector of values is placed onto the
-/// stack communicating operating system specific information. On construction
-/// this class locates and parses this information and provides a simple
-/// read-only interface to the entries found.
+/// stack communicating operating system specific information. On
+/// construction this class locates and parses this information and provides a
+/// simple read-only interface to the entries found.
class AuxVector {
public:
@@ -41,8 +41,9 @@ public:
};
/// Constants describing the type of entry.
- /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information.
- /// Added AUXV prefix to avoid potential conflicts with system-defined macros
+ /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX
+ /// information. Added AUXV prefix to avoid potential conflicts with system-
+ /// defined macros
enum EntryType {
AUXV_AT_NULL = 0, ///< End of auxv.
AUXV_AT_IGNORE = 1, ///< Ignore entry.
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index e601d64f0d8d..b1513b51a90a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -45,8 +45,8 @@ static addr_t ResolveRendezvousAddress(Process *process) {
if (log)
log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
- // If the process fails to return an address, fall back to seeing if the local
- // object file can help us find it.
+ // If the process fails to return an address, fall back to seeing if the
+ // local object file can help us find it.
if (info_location == LLDB_INVALID_ADDRESS) {
Target *target = &process->GetTarget();
if (target) {
@@ -190,8 +190,8 @@ bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) {
if (!fromRemote && m_current.map_addr == 0)
return false;
- // When the previous and current states are consistent this is the first
- // time we have been asked to update. Just take a snapshot of the currently
+ // When the previous and current states are consistent this is the first time
+ // we have been asked to update. Just take a snapshot of the currently
// loaded modules.
if (m_previous.state == eConsistent && m_current.state == eConsistent)
return fromRemote ? SaveSOEntriesFromRemote(module_list)
@@ -200,9 +200,9 @@ bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) {
// If we are about to add or remove a shared object clear out the current
// state and take a snapshot of the currently loaded images.
if (m_current.state == eAdd || m_current.state == eDelete) {
- // Some versions of the android dynamic linker might send two
- // notifications with state == eAdd back to back. Ignore them
- // until we get an eConsistent notification.
+ // Some versions of the android dynamic linker might send two notifications
+ // with state == eAdd back to back. Ignore them until we get an eConsistent
+ // notification.
if (!(m_previous.state == eConsistent ||
(m_previous.state == eAdd && m_current.state == eDelete)))
return false;
@@ -243,7 +243,7 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo(
entry.base_addr = base_addr;
entry.dyn_addr = dyn_addr;
- entry.file_spec.SetFile(name, false);
+ entry.file_spec.SetFile(name, false, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, name);
@@ -449,16 +449,13 @@ std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {
}
// Returns true if the load bias reported by the linker is incorrect for the
-// given entry. This
-// function is used to handle cases where we want to work around a bug in the
-// system linker.
+// given entry. This function is used to handle cases where we want to work
+// around a bug in the system linker.
static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
// On Android L (API 21, 22) the load address of the "/system/bin/linker"
- // isn't filled in
- // correctly.
- uint32_t os_major = 0, os_minor = 0, os_update = 0;
+ // isn't filled in correctly.
+ unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
if (target.GetArchitecture().GetTriple().isAndroid() &&
- target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) &&
(os_major == 21 || os_major == 22) &&
(file_path == "/system/bin/linker" ||
file_path == "/system/bin/linker64")) {
@@ -471,8 +468,7 @@ static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
std::string const &file_path) {
// If the load bias reported by the linker is incorrect then fetch the load
- // address of the file
- // from the proc file system.
+ // address of the file from the proc file system.
if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) {
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
bool is_loaded = false;
@@ -491,8 +487,8 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
if (!(addr = ReadPointer(addr, &entry.base_addr)))
return false;
- // mips adds an extra load offset field to the link map struct on
- // FreeBSD and NetBSD (need to validate other OSes).
+ // mips adds an extra load offset field to the link map struct on FreeBSD and
+ // NetBSD (need to validate other OSes).
// http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
@@ -521,7 +517,7 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
return false;
std::string file_path = ReadStringFromMemory(entry.path_addr);
- entry.file_spec.SetFile(file_path, false);
+ entry.file_spec.SetFile(file_path, false, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, file_path);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 295ae55e1b85..a7071801f569 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -29,12 +29,12 @@ class Process;
}
/// @class DYLDRendezvous
-/// @brief Interface to the runtime linker.
+/// Interface to the runtime linker.
///
/// A structure is present in a processes memory space which is updated by the
-/// runtime liker each time a module is loaded or unloaded. This class provides
-/// an interface to this structure and maintains a consistent snapshot of the
-/// currently loaded modules.
+/// runtime liker each time a module is loaded or unloaded. This class
+/// provides an interface to this structure and maintains a consistent
+/// snapshot of the currently loaded modules.
class DYLDRendezvous {
// This structure is used to hold the contents of the debug rendezvous
@@ -119,13 +119,13 @@ public:
void DumpToLog(lldb_private::Log *log) const;
- /// @brief Constants describing the state of the rendezvous.
+ /// Constants describing the state of the rendezvous.
///
/// @see GetState().
enum RendezvousState { eConsistent, eAdd, eDelete };
- /// @brief Structure representing the shared objects currently loaded into
- /// the inferior process.
+ /// Structure representing the shared objects currently loaded into the
+ /// inferior process.
///
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
@@ -194,7 +194,8 @@ protected:
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
- /// List of SOEntry's added to the link map since the last call to Resolve().
+ /// List of SOEntry's added to the link map since the last call to
+ /// Resolve().
SOEntryList m_added_soentries;
/// List of SOEntry's removed from the link map since the last call to
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index a7afeb6d68c3..26825d879f04 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -79,7 +79,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
: DynamicLoader(process), m_rendezvous(process),
m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS),
m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID),
- m_vdso_base(LLDB_INVALID_ADDRESS) {}
+ m_vdso_base(LLDB_INVALID_ADDRESS),
+ m_interpreter_base(LLDB_INVALID_ADDRESS) {}
DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() {
if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
@@ -117,7 +118,7 @@ void DynamicLoaderPOSIXDYLD::DidAttach() {
: "<null executable>",
load_offset);
- EvalVdsoStatus();
+ EvalSpecialModulesStatus();
// if we dont have a load address we cant re-base
bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true;
@@ -152,31 +153,10 @@ void DynamicLoaderPOSIXDYLD::DidAttach() {
UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset,
true);
- // When attaching to a target, there are two possible states:
- // (1) We already crossed the entry point and therefore the rendezvous
- // structure is ready to be used and we can load the list of modules
- // and place the rendezvous breakpoint.
- // (2) We didn't cross the entry point yet, so these structures are not
- // ready; we should behave as if we just launched the target and
- // call ProbeEntry(). This will place a breakpoint on the entry
- // point which itself will be hit after the rendezvous structure is
- // set up and will perform actions described in (1).
- if (m_rendezvous.Resolve()) {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64
- " rendezvous could resolve: attach assuming dynamic loader "
- "info is available now",
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
- LoadAllCurrentModules();
- SetRendezvousBreakpoint();
- } else {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64
- " rendezvous could not yet resolve: adding breakpoint to "
- "catch future rendezvous setup",
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+ LoadAllCurrentModules();
+ if (!SetRendezvousBreakpoint()) {
+ // If we cannot establish rendezvous breakpoint right now we'll try again
+ // at entry point.
ProbeEntry();
}
@@ -207,7 +187,7 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() {
executable = GetTargetExecutable();
load_offset = ComputeLoadOffset();
- EvalVdsoStatus();
+ EvalSpecialModulesStatus();
if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) {
ModuleList module_list;
@@ -217,8 +197,14 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() {
if (log)
log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()",
__FUNCTION__);
- ProbeEntry();
+ if (!SetRendezvousBreakpoint()) {
+ // If we cannot establish rendezvous breakpoint right now we'll try again
+ // at entry point.
+ ProbeEntry();
+ }
+
+ LoadVDSO();
m_process->GetTarget().ModulesDidLoad(module_list);
}
}
@@ -273,11 +259,11 @@ void DynamicLoaderPOSIXDYLD::ProbeEntry() {
}
// The runtime linker has run and initialized the rendezvous structure once the
-// process has hit its entry point. When we hit the corresponding breakpoint we
-// interrogate the rendezvous structure to get the load addresses of all
+// process has hit its entry point. When we hit the corresponding breakpoint
+// we interrogate the rendezvous structure to get the load addresses of all
// dependent modules for the process. Similarly, we can discover the runtime
-// linker function and setup a breakpoint to notify us of any dynamically loaded
-// modules (via dlopen).
+// linker function and setup a breakpoint to notify us of any dynamically
+// loaded modules (via dlopen).
bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
void *baton, StoppointCallbackContext *context, user_id_t break_id,
user_id_t break_loc_id) {
@@ -295,13 +281,11 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
: LLDB_INVALID_PROCESS_ID);
// Disable the breakpoint --- if a stop happens right after this, which we've
- // seen on occasion, we don't
- // want the breakpoint stepping thread-plan logic to show a breakpoint
- // instruction at the disassembled
- // entry point to the program. Disabling it prevents it. (One-shot is not
- // enough - one-shot removal logic
- // only happens after the breakpoint goes public, which wasn't happening in
- // our scenario).
+ // seen on occasion, we don't want the breakpoint stepping thread-plan logic
+ // to show a breakpoint instruction at the disassembled entry point to the
+ // program. Disabling it prevents it. (One-shot is not enough - one-shot
+ // removal logic only happens after the breakpoint goes public, which wasn't
+ // happening in our scenario).
if (dyld_instance->m_process) {
BreakpointSP breakpoint_sp =
dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id);
@@ -329,38 +313,77 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
return false; // Continue running.
}
-void DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
+bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
+ LLDB_LOG(log,
+ "Rendezvous breakpoint breakpoint id {0} for pid {1}"
+ "is already set.",
+ m_dyld_bid,
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+ return true;
+ }
- addr_t break_addr = m_rendezvous.GetBreakAddress();
+ addr_t break_addr;
Target &target = m_process->GetTarget();
-
- if (m_dyld_bid == LLDB_INVALID_BREAK_ID) {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
- " setting rendezvous break address at 0x%" PRIx64,
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
- break_addr);
- Breakpoint *dyld_break =
- target.CreateBreakpoint(break_addr, true, false).get();
- dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
- dyld_break->SetBreakpointKind("shared-library-event");
- m_dyld_bid = dyld_break->GetID();
+ BreakpointSP dyld_break;
+ if (m_rendezvous.IsValid()) {
+ break_addr = m_rendezvous.GetBreakAddress();
+ LLDB_LOG(log, "Setting rendezvous break address for pid {0} at {1:x}",
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
+ break_addr);
+ dyld_break = target.CreateBreakpoint(break_addr, true, false);
} else {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
- " reusing break id %" PRIu32 ", address at 0x%" PRIx64,
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
- m_dyld_bid, break_addr);
+ LLDB_LOG(log, "Rendezvous structure is not set up yet. "
+ "Trying to locate rendezvous breakpoint in the interpreter "
+ "by symbol name.");
+ ModuleSP interpreter = LoadInterpreterModule();
+ if (!interpreter) {
+ LLDB_LOG(log, "Can't find interpreter, rendezvous breakpoint isn't set.");
+ return false;
+ }
+
+ // Function names from different dynamic loaders that are known to be used
+ // as rendezvous between the loader and debuggers.
+ static std::vector<std::string> DebugStateCandidates{
+ "_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",
+ "r_debug_state", "_r_debug_state", "_rtld_debug_state",
+ };
+
+ FileSpecList containingModules;
+ containingModules.Append(interpreter->GetFileSpec());
+ dyld_break = target.CreateBreakpoint(
+ &containingModules, nullptr /* containingSourceFiles */,
+ DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
+ 0, /* offset */
+ eLazyBoolNo, /* skip_prologue */
+ true, /* internal */
+ false /* request_hardware */);
+ }
+
+ if (dyld_break->GetNumResolvedLocations() != 1) {
+ LLDB_LOG(
+ log,
+ "Rendezvous breakpoint has abnormal number of"
+ " resolved locations ({0}) in pid {1}. It's supposed to be exactly 1.",
+ dyld_break->GetNumResolvedLocations(),
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+
+ target.RemoveBreakpointByID(dyld_break->GetID());
+ return false;
}
- // Make sure our breakpoint is at the right address.
- assert(target.GetBreakpointByID(m_dyld_bid)
- ->FindLocationByAddress(break_addr)
- ->GetBreakpoint()
- .GetID() == m_dyld_bid);
+ BreakpointLocationSP location = dyld_break->GetLocationAtIndex(0);
+ LLDB_LOG(log,
+ "Successfully set rendezvous breakpoint at address {0:x} "
+ "for pid {1}",
+ location->GetLoadAddress(),
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+
+ dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+ dyld_break->SetBreakpointKind("shared-library-event");
+ m_dyld_bid = dyld_break->GetID();
+ return true;
}
bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(
@@ -485,7 +508,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
return thread_plan_sp;
}
-void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) {
+void DynamicLoaderPOSIXDYLD::LoadVDSO() {
if (m_vdso_base == LLDB_INVALID_ADDRESS)
return;
@@ -506,13 +529,40 @@ void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) {
}
}
+ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
+ if (m_interpreter_base == LLDB_INVALID_ADDRESS)
+ return nullptr;
+
+ MemoryRegionInfo info;
+ Target &target = m_process->GetTarget();
+ Status status = m_process->GetMemoryRegionInfo(m_interpreter_base, info);
+ if (status.Fail() || info.GetMapped() != MemoryRegionInfo::eYes ||
+ info.GetName().IsEmpty()) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ LLDB_LOG(log, "Failed to get interpreter region info: {0}", status);
+ return nullptr;
+ }
+
+ FileSpec file(info.GetName().GetCString(), false);
+ ModuleSpec module_spec(file, target.GetArchitecture());
+
+ if (ModuleSP module_sp = target.GetSharedModule(module_spec)) {
+ UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
+ false);
+ return module_sp;
+ }
+ return nullptr;
+}
+
void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
DYLDRendezvous::iterator I;
DYLDRendezvous::iterator E;
ModuleList module_list;
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ LoadVDSO();
if (!m_rendezvous.Resolve()) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD "
"rendezvous address",
@@ -520,11 +570,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
return;
}
- // The rendezvous class doesn't enumerate the main module, so track
- // that ourselves here.
+ // The rendezvous class doesn't enumerate the main module, so track that
+ // ourselves here.
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
- LoadVDSO(module_list);
std::vector<FileSpec> module_names;
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
@@ -536,6 +585,8 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
ModuleSP module_sp =
LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get()) {
+ LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}",
+ I->file_spec.GetFilename());
module_list.Append(module_sp);
} else {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
@@ -575,11 +626,14 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() {
return m_load_offset;
}
-void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() {
- AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR);
-
- if (I != m_auxv->end())
+void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() {
+ auto I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR);
+ if (I != m_auxv->end() && I->value != 0)
m_vdso_base = I->value;
+
+ I = m_auxv->FindEntry(AuxVector::AUXV_AT_BASE);
+ if (I != m_auxv->end() && I->value != 0)
+ m_interpreter_base = I->value;
}
addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 2e9670587e66..0456baf4a658 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -85,13 +85,17 @@ protected:
/// mapped to the address space
lldb::addr_t m_vdso_base;
+ /// Contains AT_BASE, which means a dynamic loader has been
+ /// mapped to the address space
+ lldb::addr_t m_interpreter_base;
+
/// Loaded module list. (link map for each module)
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>>
m_loaded_modules;
- /// Enables a breakpoint on a function called by the runtime
+ /// If possible sets a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
- virtual void SetRendezvousBreakpoint();
+ bool SetRendezvousBreakpoint();
/// Callback routine which updates the current list of loaded modules based
/// on the information supplied by the runtime linker.
@@ -138,7 +142,11 @@ protected:
/// of all dependent modules.
virtual void LoadAllCurrentModules();
- void LoadVDSO(lldb_private::ModuleList &modules);
+ void LoadVDSO();
+
+ // Loading an interpreter module (if present) assumming m_interpreter_base
+ // already points to its base address.
+ lldb::ModuleSP LoadInterpreterModule();
/// Computes a value for m_load_offset returning the computed address on
/// success and LLDB_INVALID_ADDRESS on failure.
@@ -148,9 +156,10 @@ protected:
/// success and LLDB_INVALID_ADDRESS on failure.
lldb::addr_t GetEntryPoint();
- /// Evaluate if Aux vectors contain vDSO information
+ /// Evaluate if Aux vectors contain vDSO and LD information
/// in case they do, read and assign the address to m_vdso_base
- void EvalVdsoStatus();
+ /// and m_interpreter_base.
+ void EvalSpecialModulesStatus();
/// Loads Module from inferior process.
void ResolveExecutableModule(lldb::ModuleSP &module_sp);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
index 291695cb68c1..2960e3939461 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
@@ -19,9 +19,9 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Create an instance of this class. This function is filled into
-// the plugin info class that gets handed out by the plugin factory and
-// allows the lldb to instantiate an instance of this class.
+// Create an instance of this class. This function is filled into the plugin
+// info class that gets handed out by the plugin factory and allows the lldb to
+// instantiate an instance of this class.
//----------------------------------------------------------------------
DynamicLoader *DynamicLoaderStatic::CreateInstance(Process *process,
bool force) {
@@ -97,17 +97,17 @@ void DynamicLoaderStatic::LoadAllImagesAtFileAddresses() {
if (section_list) {
// All sections listed in the dyld image info structure will all
// either be fixed up already, or they will all be off by a single
- // slide amount that is determined by finding the first segment
- // that is at file offset zero which also has bytes (a file size
- // that is greater than zero) in the object file.
+ // slide amount that is determined by finding the first segment that
+ // is at file offset zero which also has bytes (a file size that is
+ // greater than zero) in the object file.
// Determine the slide amount (if any)
const size_t num_sections = section_list->GetSize();
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find the
- // first section that starts of file offset zero and that
- // has bytes in the file...
+ // Iterate through the object file sections to find the first
+ // section that starts of file offset zero and that has bytes in
+ // the file...
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp) {
if (m_process->GetTarget().SetSectionLoadAddress(
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index 9e6a2f3acafe..fa49a51f32a6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -226,8 +226,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
return true;
// In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off
- // if that's the
- // case.
+ // if that's the case.
do {
ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
@@ -242,8 +241,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
} while (0);
// is_lvalue is used to record whether the expression returns an assignable
- // Lvalue or an
- // Rvalue. This is relevant because they are handled differently.
+ // Lvalue or an Rvalue. This is relevant because they are handled
+ // differently.
//
// For Lvalues
//
@@ -293,9 +292,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
//
// - During dematerialization, $0 is ignored.
- bool is_lvalue = (last_expr->getValueKind() == VK_LValue ||
- last_expr->getValueKind() == VK_XValue) &&
- (last_expr->getObjectKind() == OK_Ordinary);
+ bool is_lvalue = last_expr->getValueKind() == VK_LValue &&
+ last_expr->getObjectKind() == OK_Ordinary;
QualType expr_qual_type = last_expr->getType();
const clang::Type *expr_type = expr_qual_type.getTypePtr();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
index c0e6c0358a23..859a1dfa5f73 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
@@ -18,18 +18,17 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ASTResultSynthesizer ASTResultSynthesizer.h
-/// "lldb/Expression/ASTResultSynthesizer.h"
-/// @brief Adds a result variable declaration to the ASTs for an expression.
+/// "lldb/Expression/ASTResultSynthesizer.h" Adds a result variable
+/// declaration to the ASTs for an expression.
///
/// Users expect the expression "i + 3" to return a result, even if a result
/// variable wasn't specifically declared. To fulfil this requirement, LLDB
-/// adds
-/// a result variable to the expression, transforming it to
-/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the
+/// adds a result variable to the expression, transforming it to "int
+/// $__lldb_expr_result = i + 3." The IR transformers ensure that the
/// resulting variable is mapped to the right piece of memory.
-/// ASTResultSynthesizer's job is to add the variable and its initialization to
-/// the ASTs for the expression, and it does so by acting as a SemaConsumer for
-/// Clang.
+/// ASTResultSynthesizer's job is to add the variable and its initialization
+/// to the ASTs for the expression, and it does so by acting as a SemaConsumer
+/// for Clang.
//----------------------------------------------------------------------
class ASTResultSynthesizer : public clang::SemaConsumer {
public:
@@ -68,8 +67,8 @@ public:
void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
- /// Examine a list of Decls to find the function $__lldb_expr and
- /// transform its code
+ /// Examine a list of Decls to find the function $__lldb_expr and transform
+ /// its code
///
/// @param[in] D
/// The list of Decls to search. These may contain LinkageSpecDecls,
@@ -124,8 +123,8 @@ public:
private:
//----------------------------------------------------------------------
- /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing
- /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on
+ /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing as
+ /// necessary through LinkageSpecDecls, and calling SynthesizeResult on
/// anything that was found
///
/// @param[in] D
@@ -164,8 +163,8 @@ private:
bool SynthesizeBodyResult(clang::CompoundStmt *Body, clang::DeclContext *DC);
//----------------------------------------------------------------------
- /// Given a DeclContext for a function or method, find all types
- /// declared in the context and record any persistent types found.
+ /// Given a DeclContext for a function or method, find all types declared in
+ /// the context and record any persistent types found.
///
/// @param[in] FunDeclCtx
/// The context for the function to process.
@@ -173,8 +172,8 @@ private:
void RecordPersistentTypes(clang::DeclContext *FunDeclCtx);
//----------------------------------------------------------------------
- /// Given a TypeDecl, if it declares a type whose name starts with a
- /// dollar sign, register it as a pointer type in the target's scratch
+ /// Given a TypeDecl, if it declares a type whose name starts with a dollar
+ /// sign, register it as a pointer type in the target's scratch
/// AST context.
///
/// @param[in] Body
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
index 63e3161cae85..65f4b00a8651 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
@@ -20,20 +20,19 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ASTStructExtractor ASTStructExtractor.h
-/// "lldb/Expression/ASTStructExtractor.h"
-/// @brief Extracts and describes the argument structure for a wrapped function.
+/// "lldb/Expression/ASTStructExtractor.h" Extracts and describes the argument
+/// structure for a wrapped function.
///
/// This pass integrates with ClangFunctionCaller, which calls functions with
-/// custom
-/// sets of arguments. To avoid having to implement the full calling convention
-/// for the target's architecture, ClangFunctionCaller writes a simple wrapper
-/// function that takes a pointer to an argument structure that contains room
-/// for the address of the function to be called, the values of all its
-/// arguments, and room for the function's return value.
+/// custom sets of arguments. To avoid having to implement the full calling
+/// convention for the target's architecture, ClangFunctionCaller writes a
+/// simple wrapper function that takes a pointer to an argument structure that
+/// contains room for the address of the function to be called, the values of
+/// all its arguments, and room for the function's return value.
///
-/// The definition of this struct is itself in the body of the wrapper function,
-/// so Clang does the structure layout itself. ASTStructExtractor reads through
-/// the AST for the wrapper function and finds the struct.
+/// The definition of this struct is itself in the body of the wrapper
+/// function, so Clang does the structure layout itself. ASTStructExtractor
+/// reads through the AST for the wrapper function and finds the struct.
//----------------------------------------------------------------------
class ASTStructExtractor : public clang::SemaConsumer {
public:
@@ -73,8 +72,8 @@ public:
void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
- /// Examine a list of Decls to find the function $__lldb_expr and
- /// transform its code
+ /// Examine a list of Decls to find the function $__lldb_expr and transform
+ /// its code
///
/// @param[in] D
/// The list of Decls to search. These may contain LinkageSpecDecls,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 7f031356b3c3..d98a2b25fbb7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -33,8 +33,8 @@ using namespace clang;
using namespace lldb_private;
//------------------------------------------------------------------
-// Scoped class that will remove an active lexical decl from the set
-// when it goes out of scope.
+// Scoped class that will remove an active lexical decl from the set when it
+// goes out of scope.
//------------------------------------------------------------------
namespace {
class ScopedLexicalDeclEraser {
@@ -141,8 +141,8 @@ ClangASTSource::~ClangASTSource() {
m_ast_importer_sp->ForgetDestination(m_ast_context);
// We are in the process of destruction, don't create clang ast context on
- // demand
- // by passing false to Target::GetScratchClangASTContext(create_on_demand).
+ // demand by passing false to
+ // Target::GetScratchClangASTContext(create_on_demand).
ClangASTContext *scratch_clang_ast_context =
m_target->GetScratchClangASTContext(false);
@@ -231,8 +231,8 @@ bool ClangASTSource::FindExternalVisibleDeclsByName(
}
if (!GetLookupsEnabled()) {
- // Wait until we see a '$' at the start of a name before we start doing
- // any lookups so we can avoid lookup up all of the builtin types.
+ // Wait until we see a '$' at the start of a name before we start doing any
+ // lookups so we can avoid lookup up all of the builtin types.
if (!decl_name.empty() && decl_name[0] == '$') {
SetLookupsEnabled(true);
} else {
@@ -297,8 +297,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
}
if (!m_ast_importer_sp->CompleteTagDecl(tag_decl)) {
- // We couldn't complete the type. Maybe there's a definition
- // somewhere else that can be completed.
+ // We couldn't complete the type. Maybe there's a definition somewhere
+ // else that can be completed.
if (log)
log->Printf(" CTD[%u] Type could not be completed in the module in "
@@ -398,8 +398,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
const_cast<TagDecl *>(tag_type->getDecl());
// We have found a type by basename and we need to make sure the decl
- // contexts
- // are the same before we can try to complete this type with another
+ // contexts are the same before we can try to complete this type with
+ // another
if (!ClangASTContext::DeclsAreEquivalent(tag_decl, candidate_tag_decl))
continue;
@@ -861,13 +861,16 @@ void ClangASTSource::FindExternalVisibleDecls(
TypeList types;
SymbolContext null_sc;
- const bool exact_match = false;
+ const bool exact_match = true;
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
if (module_sp && namespace_decl)
module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
- else
- m_target->GetImages().FindTypes(null_sc, name, exact_match, 1,
+ else {
+ SymbolContext sc;
+ sc.module_sp = module_sp;
+ m_target->GetImages().FindTypes(sc, name, exact_match, 1,
searched_symbol_files, types);
+ }
if (size_t num_types = types.GetSize()) {
for (size_t ti = 0; ti < num_types; ++ti) {
@@ -1243,8 +1246,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
break;
// Fall back and check for methods in categories. If we find methods this
- // way, we need to check that they're actually in
- // categories on the desired class.
+ // way, we need to check that they're actually in categories on the desired
+ // class.
SymbolContextList candidate_sc_list;
@@ -1591,8 +1594,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
do {
// Check the runtime only if the debug information didn't have a complete
- // interface
- // and nothing was in the modules.
+ // interface and nothing was in the modules.
lldb::ProcessSP process(m_target->GetProcessSP());
@@ -1645,12 +1647,9 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map,
ClangASTSource &source) {
// When importing fields into a new record, clang has a hard requirement that
// fields be imported in field offset order. Since they are stored in a
- // DenseMap
- // with a pointer as the key type, this means we cannot simply iterate over
- // the
- // map, as the order will be non-deterministic. Instead we have to sort by
- // the offset
- // and then insert in sorted order.
+ // DenseMap with a pointer as the key type, this means we cannot simply
+ // iterate over the map, as the order will be non-deterministic. Instead we
+ // have to sort by the offset and then insert in sorted order.
typedef llvm::DenseMap<const D *, O> MapType;
typedef typename MapType::value_type PairType;
std::vector<PairType> sorted_items;
@@ -2051,9 +2050,8 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
if (copied_qual_type.getAsOpaquePtr() &&
copied_qual_type->getCanonicalTypeInternal().isNull())
- // this shouldn't happen, but we're hardening because the AST importer seems
- // to be generating bad types
- // on occasion.
+ // this shouldn't happen, but we're hardening because the AST importer
+ // seems to be generating bad types on occasion.
return CompilerType();
return CompilerType(m_ast_context, copied_qual_type);
@@ -2156,6 +2154,18 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
log->Printf("Function type wasn't a FunctionProtoType");
}
+ // If this is an operator (e.g. operator new or operator==), only insert the
+ // declaration we inferred from the symbol if we can provide the correct
+ // number of arguments. We shouldn't really inject random decl(s) for
+ // functions that are analyzed semantically in a special way, otherwise we
+ // will crash in clang.
+ clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
+ if (func_proto_type &&
+ ClangASTContext::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
+ if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(
+ false, op_kind, func_proto_type->getNumParams()))
+ return NULL;
+ }
m_decls.push_back(func_decl);
return func_decl;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 6f72ad92dc8c..a42422b0f97f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -25,14 +25,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"
-/// @brief Provider for named objects defined in the debug info for Clang
+/// Provider for named objects defined in the debug info for Clang
///
-/// As Clang parses an expression, it may encounter names that are not
-/// defined inside the expression, including variables, functions, and
-/// types. Clang knows the name it is looking for, but nothing else.
-/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl)
-/// to Clang for these names, consulting the ClangExpressionDeclMap to do
-/// the actual lookups.
+/// As Clang parses an expression, it may encounter names that are not defined
+/// inside the expression, including variables, functions, and types. Clang
+/// knows the name it is looking for, but nothing else. The ExternalSemaSource
+/// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these
+/// names, consulting the ClangExpressionDeclMap to do the actual lookups.
//----------------------------------------------------------------------
class ClangASTSource : public ClangExternalASTSourceCommon,
public ClangASTImporter::MapCompleter {
@@ -78,8 +77,8 @@ public:
//------------------------------------------------------------------
/// Look up all Decls that match a particular name. Only handles
/// Identifiers and DeclContexts that are either NamespaceDecls or
- /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with
- /// the result.
+ /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with the
+ /// result.
///
/// The work for this function is done by
/// void FindExternalVisibleDecls (NameSearchContext &);
@@ -173,8 +172,8 @@ public:
//------------------------------------------------------------------
/// Called on entering a translation unit. Tells Clang by calling
- /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage()
- /// that this object has something to say about undefined names.
+ /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that
+ /// this object has something to say about undefined names.
///
/// @param[in] ASTConsumer
/// Unused.
@@ -186,8 +185,8 @@ public:
//
//------------------------------------------------------------------
- /// Look up the modules containing a given namespace and put the
- /// appropriate entries in the namespace map.
+ /// Look up the modules containing a given namespace and put the appropriate
+ /// entries in the namespace map.
///
/// @param[in] namespace_map
/// The map to be completed.
@@ -231,11 +230,10 @@ public:
//----------------------------------------------------------------------
/// @class ClangASTSourceProxy ClangASTSource.h
- /// "lldb/Expression/ClangASTSource.h"
- /// @brief Proxy for ClangASTSource
+ /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
///
- /// Clang AST contexts like to own their AST sources, so this is a
- /// state-free proxy object.
+ /// Clang AST contexts like to own their AST sources, so this is a state-
+ /// free proxy object.
//----------------------------------------------------------------------
class ClangASTSourceProxy : public ClangExternalASTSourceCommon {
public:
@@ -298,8 +296,8 @@ public:
protected:
//------------------------------------------------------------------
- /// Look for the complete version of an Objective-C interface, and
- /// return it if found.
+ /// Look for the complete version of an Objective-C interface, and return it
+ /// if found.
///
/// @param[in] interface_decl
/// An ObjCInterfaceDecl that may not be the complete one.
@@ -312,8 +310,8 @@ protected:
GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl);
//------------------------------------------------------------------
- /// Find all entities matching a given name in a given module,
- /// using a NameSearchContext to make Decls for them.
+ /// Find all entities matching a given name in a given module, using a
+ /// NameSearchContext to make Decls for them.
///
/// @param[in] context
/// The NameSearchContext that can construct Decls for this name.
@@ -474,8 +472,9 @@ protected:
};
//----------------------------------------------------------------------
-/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h"
-/// @brief Container for all objects relevant to a single name lookup
+/// @class NameSearchContext ClangASTSource.h
+/// "lldb/Expression/ClangASTSource.h" Container for all objects relevant to a
+/// single name lookup
///
/// LLDB needs to create Decls for entities it finds. This class communicates
/// what name is being searched for and provides helper functions to construct
@@ -532,8 +531,8 @@ struct NameSearchContext {
}
//------------------------------------------------------------------
- /// Create a VarDecl with the name being searched for and the provided
- /// type and register it in the right places.
+ /// Create a VarDecl with the name being searched for and the provided type
+ /// and register it in the right places.
///
/// @param[in] type
/// The opaque QualType for the VarDecl being registered.
@@ -541,8 +540,8 @@ struct NameSearchContext {
clang::NamedDecl *AddVarDecl(const CompilerType &type);
//------------------------------------------------------------------
- /// Create a FunDecl with the name being searched for and the provided
- /// type and register it in the right places.
+ /// Create a FunDecl with the name being searched for and the provided type
+ /// and register it in the right places.
///
/// @param[in] type
/// The opaque QualType for the FunDecl being registered.
@@ -553,15 +552,14 @@ struct NameSearchContext {
clang::NamedDecl *AddFunDecl(const CompilerType &type, bool extern_c = false);
//------------------------------------------------------------------
- /// Create a FunDecl with the name being searched for and generic
- /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the
- /// right places.
+ /// Create a FunDecl with the name being searched for and generic type (i.e.
+ /// intptr_t NAME_GOES_HERE(...)) and register it in the right places.
//------------------------------------------------------------------
clang::NamedDecl *AddGenericFunDecl();
//------------------------------------------------------------------
- /// Create a TypeDecl with the name being searched for and the provided
- /// type and register it in the right places.
+ /// Create a TypeDecl with the name being searched for and the provided type
+ /// and register it in the right places.
///
/// @param[in] compiler_type
/// The opaque QualType for the TypeDecl being registered.
@@ -569,8 +567,8 @@ struct NameSearchContext {
clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type);
//------------------------------------------------------------------
- /// Add Decls from the provided DeclContextLookupResult to the list
- /// of results.
+ /// Add Decls from the provided DeclContextLookupResult to the list of
+ /// results.
///
/// @param[in] result
/// The DeclContextLookupResult, usually returned as the result
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 07ff2e97aac7..0811a7999920 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -213,8 +213,8 @@ private:
m_exporter.getFromContext().getSourceManager().getFileID(loc);
if (file != m_file)
return false;
- // We are assuming the Decl was parsed in this very expression, so it should
- // not have external storage.
+ // We are assuming the Decl was parsed in this very expression, so it
+ // should not have external storage.
lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage());
return true;
}
@@ -591,8 +591,8 @@ bool ClangExpressionDeclMap::GetFunctionInfo(const NamedDecl *decl,
if (!entity)
return false;
- // We know m_parser_vars is valid since we searched for the variable by
- // its NamedDecl
+ // We know m_parser_vars is valid since we searched for the variable by its
+ // NamedDecl
ClangExpressionVariable::ParserVars *parser_vars =
entity->GetParserVars(GetParserID());
@@ -720,9 +720,9 @@ lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
VariableList vars;
if (module && namespace_decl)
- module->FindGlobalVariables(name, namespace_decl, true, -1, vars);
+ module->FindGlobalVariables(name, namespace_decl, -1, vars);
else
- target.GetImages().FindGlobalVariables(name, true, -1, vars);
+ target.GetImages().FindGlobalVariables(name, -1, vars);
if (vars.GetSize()) {
if (type) {
@@ -867,8 +867,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
if (IgnoreName(name, false))
return;
- // Only look for functions by name out in our symbols if the function
- // doesn't start with our phony prefix of '$'
+ // Only look for functions by name out in our symbols if the function doesn't
+ // start with our phony prefix of '$'
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
SymbolContext sym_ctx;
@@ -977,13 +977,11 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
m_struct_vars->m_object_pointer_type = self_user_type;
}
} else {
- // This branch will get hit if we are executing code in the context of a
- // function that
- // claims to have an object pointer (through DW_AT_object_pointer?) but
- // is not formally a
- // method of the class. In that case, just look up the "this" variable
- // in the current
- // scope and use its type.
+ // This branch will get hit if we are executing code in the context of
+ // a function that claims to have an object pointer (through
+ // DW_AT_object_pointer?) but is not formally a method of the class.
+ // In that case, just look up the "this" variable in the current scope
+ // and use its type.
// FIXME: This code is formally correct, but clang doesn't currently
// emit DW_AT_object_pointer
// for C++ so it hasn't actually been tested.
@@ -1093,13 +1091,11 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
return;
} else {
- // This branch will get hit if we are executing code in the context of a
- // function that
- // claims to have an object pointer (through DW_AT_object_pointer?) but
- // is not formally a
- // method of the class. In that case, just look up the "self" variable
- // in the current
- // scope and use its type.
+ // This branch will get hit if we are executing code in the context of
+ // a function that claims to have an object pointer (through
+ // DW_AT_object_pointer?) but is not formally a method of the class.
+ // In that case, just look up the "self" variable in the current scope
+ // and use its type.
VariableList *vars = frame->GetVariableList(false);
@@ -1217,9 +1213,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
vars->GetVariableAtIndex(i)->GetDecl();
// Search for declarations matching the name. Do not include imported
- // decls
- // in the search if we are looking for decls in the artificial namespace
- // $__lldb_local_vars.
+ // decls in the search if we are looking for decls in the artificial
+ // namespace $__lldb_local_vars.
std::vector<CompilerDecl> found_decls =
compiler_decl_context.FindDeclByName(name,
namespace_decl.IsValid());
@@ -1285,15 +1280,15 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
append, sc_list);
}
- // If we found more than one function, see if we can use the
- // frame's decl context to remove functions that are shadowed
- // by other functions which match in type but are nearer in scope.
+ // If we found more than one function, see if we can use the frame's decl
+ // context to remove functions that are shadowed by other functions which
+ // match in type but are nearer in scope.
//
// AddOneFunction will not add a function whose type has already been
- // added, so if there's another function in the list with a matching
- // type, check to see if their decl context is a parent of the current
- // frame's or was imported via a and using statement, and pick the
- // best match according to lookup rules.
+ // added, so if there's another function in the list with a matching type,
+ // check to see if their decl context is a parent of the current frame's or
+ // was imported via a and using statement, and pick the best match
+ // according to lookup rules.
if (sc_list.GetSize() > 1) {
// Collect some info about our frame's context.
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
@@ -1321,11 +1316,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
SymbolContext m_sym_ctx;
};
- // First, symplify things by looping through the symbol contexts
- // to remove unwanted functions and separate out the functions we
- // want to compare and prune into a separate list.
- // Cache the info needed about the function declarations in a
- // vector for efficiency.
+ // First, symplify things by looping through the symbol contexts to
+ // remove unwanted functions and separate out the functions we want to
+ // compare and prune into a separate list. Cache the info needed about
+ // the function declarations in a vector for efficiency.
SymbolContextList sc_sym_list;
uint32_t num_indices = sc_list.GetSize();
std::vector<FuncDeclInfo> fdi_cache;
@@ -1335,16 +1329,16 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(index, sym_ctx);
- // We don't know enough about symbols to compare them,
- // but we should keep them in the list.
+ // We don't know enough about symbols to compare them, but we should
+ // keep them in the list.
Function *function = sym_ctx.function;
if (!function) {
sc_sym_list.Append(sym_ctx);
continue;
}
// Filter out functions without declaration contexts, as well as
- // class/instance methods, since they'll be skipped in the
- // code that follows anyway.
+ // class/instance methods, since they'll be skipped in the code that
+ // follows anyway.
CompilerDeclContext func_decl_context = function->GetDeclContext();
if (!func_decl_context ||
func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
@@ -1363,11 +1357,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
fdi.m_copied_type = copied_func_type;
fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
if (fdi.m_copied_type && func_decl_context) {
- // Call CountDeclLevels to get the number of parent scopes we
- // have to look through before we find the function declaration.
- // When comparing functions of the same type, the one with a
- // lower count will be closer to us in the lookup scope and
- // shadows the other.
+ // Call CountDeclLevels to get the number of parent scopes we have
+ // to look through before we find the function declaration. When
+ // comparing functions of the same type, the one with a lower count
+ // will be closer to us in the lookup scope and shadows the other.
clang::DeclContext *func_decl_ctx =
(clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
fdi.m_decl_lvl = ast->CountDeclLevels(
@@ -1536,9 +1529,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
if (target && !context.m_found.variable && !namespace_decl) {
- // We couldn't find a non-symbol variable for this. Now we'll hunt for
- // a generic
- // data symbol, and -- if it is found -- treat it as a variable.
+ // We couldn't find a non-symbol variable for this. Now we'll hunt for a
+ // generic data symbol, and -- if it is found -- treat it as a variable.
Status error;
const Symbol *data_symbol =
@@ -2116,7 +2108,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
parser_vars->m_llvm_value = NULL;
if (log) {
- ASTDumper ast_dumper(function_decl);
+ std::string function_str =
+ function_decl ? ASTDumper(function_decl).GetCString() : "nullptr";
StreamString ss;
@@ -2127,7 +2120,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
log->Printf(
" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s",
current_id, (function ? "specific" : "generic"), decl_name.c_str(),
- ss.GetData(), ast_dumper.GetCString());
+ ss.GetData(), function_str.c_str());
}
}
@@ -2165,7 +2158,7 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
CXXMethodDecl *method_decl =
ClangASTContext::GetASTContext(m_ast_context)
->AddMethodToCXXRecordType(
- copied_clang_type.GetOpaqueQualType(), "$__lldb_expr",
+ copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", NULL,
method_type, lldb::eAccessPublic, is_virtual, is_static,
is_inline, is_explicit, is_attr_used, is_artificial);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index d163ad4f7e29..b67387930190 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -36,29 +36,28 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h
-/// "lldb/Expression/ClangExpressionDeclMap.h"
-/// @brief Manages named entities that are defined in LLDB's debug information.
+/// "lldb/Expression/ClangExpressionDeclMap.h" Manages named entities that are
+/// defined in LLDB's debug information.
///
/// The Clang parser uses the ClangASTSource as an interface to request named
/// entities from outside an expression. The ClangASTSource reports back,
-/// listing
-/// all possible objects corresponding to a particular name. But it in turn
-/// relies on ClangExpressionDeclMap, which performs several important
+/// listing all possible objects corresponding to a particular name. But it
+/// in turn relies on ClangExpressionDeclMap, which performs several important
/// functions.
///
-/// First, it records what variables and functions were looked up and what Decls
-/// were returned for them.
+/// First, it records what variables and functions were looked up and what
+/// Decls were returned for them.
///
/// Second, it constructs a struct on behalf of IRForTarget, recording which
-/// variables should be placed where and relaying this information back so that
-/// IRForTarget can generate context-independent code.
+/// variables should be placed where and relaying this information back so
+/// that IRForTarget can generate context-independent code.
///
/// Third, it "materializes" this struct on behalf of the expression command,
/// finding the current values of each variable and placing them into the
/// struct so that it can be passed to the JITted version of the IR.
///
-/// Fourth and finally, it "dematerializes" the struct after the JITted code has
-/// has executed, placing the new values back where it found the old ones.
+/// Fourth and finally, it "dematerializes" the struct after the JITted code
+/// has has executed, placing the new values back where it found the old ones.
//----------------------------------------------------------------------
class ClangExpressionDeclMap : public ClangASTSource {
public:
@@ -169,8 +168,8 @@ public:
lldb::offset_t alignment);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Finalize the struct, laying out the position
- /// of each object in it.
+ /// [Used by IRForTarget] Finalize the struct, laying out the position of
+ /// each object in it.
///
/// @return
/// True on success; false otherwise.
@@ -178,8 +177,8 @@ public:
bool DoStructLayout();
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get general information about the laid-out
- /// struct after DoStructLayout() has been called.
+ /// [Used by IRForTarget] Get general information about the laid-out struct
+ /// after DoStructLayout() has been called.
///
/// @param[out] num_elements
/// The number of elements in the struct.
@@ -197,8 +196,8 @@ public:
lldb::offset_t &alignment);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get specific information about one field
- /// of the laid-out struct after DoStructLayout() has been called.
+ /// [Used by IRForTarget] Get specific information about one field of the
+ /// laid-out struct after DoStructLayout() has been called.
///
/// @param[out] decl
/// The parsed Decl for the field, as generated by ClangASTSource
@@ -232,8 +231,7 @@ public:
uint32_t index);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get information about a function given its
- /// Decl.
+ /// [Used by IRForTarget] Get information about a function given its Decl.
///
/// @param[in] decl
/// The parsed Decl for the Function, as generated by ClangASTSource
@@ -248,8 +246,8 @@ public:
bool GetFunctionInfo(const clang::NamedDecl *decl, uint64_t &ptr);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get the address of a symbol given nothing
- /// but its name.
+ /// [Used by IRForTarget] Get the address of a symbol given nothing but its
+ /// name.
///
/// @param[in] target
/// The target to find the symbol in. If not provided,
@@ -303,8 +301,8 @@ public:
TargetInfo GetTargetInfo();
//------------------------------------------------------------------
- /// [Used by ClangASTSource] Find all entities matching a given name,
- /// using a NameSearchContext to make Decls for them.
+ /// [Used by ClangASTSource] Find all entities matching a given name, using
+ /// a NameSearchContext to make Decls for them.
///
/// @param[in] context
/// The NameSearchContext that can construct Decls for this name.
@@ -442,14 +440,13 @@ private:
void DisableStructVars() { m_struct_vars.reset(); }
//----------------------------------------------------------------------
- /// Get this parser's ID for use in extracting parser- and JIT-specific
- /// data from persistent variables.
+ /// Get this parser's ID for use in extracting parser- and JIT-specific data
+ /// from persistent variables.
//----------------------------------------------------------------------
uint64_t GetParserID() { return (uint64_t) this; }
//------------------------------------------------------------------
- /// Given a target, find a variable that matches the given name and
- /// type.
+ /// Given a target, find a variable that matches the given name and type.
///
/// @param[in] target
/// The target to use as a basis for finding the variable.
@@ -477,8 +474,8 @@ private:
TypeFromUser *type = NULL);
//------------------------------------------------------------------
- /// Get the value of a variable in a given execution context and return
- /// the associated Types if needed.
+ /// Get the value of a variable in a given execution context and return the
+ /// associated Types if needed.
///
/// @param[in] var
/// The variable to evaluate.
@@ -524,8 +521,8 @@ private:
lldb::ValueObjectSP valobj, unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given
- /// persistent variable, and put it in the list of found entities.
+ /// Use the NameSearchContext to generate a Decl for the given persistent
+ /// variable, and put it in the list of found entities.
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
@@ -542,9 +539,8 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given LLDB
- /// symbol (treated as a variable), and put it in the list of found
- /// entities.
+ /// Use the NameSearchContext to generate a Decl for the given LLDB symbol
+ /// (treated as a variable), and put it in the list of found entities.
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
@@ -556,9 +552,9 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given
- /// function. (Functions are not placed in the Tuple list.) Can
- /// handle both fully typed functions and generic functions.
+ /// Use the NameSearchContext to generate a Decl for the given function.
+ /// (Functions are not placed in the Tuple list.) Can handle both fully
+ /// typed functions and generic functions.
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
@@ -575,8 +571,7 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given
- /// register.
+ /// Use the NameSearchContext to generate a Decl for the given register.
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
@@ -588,8 +583,8 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given
- /// type. (Types are not placed in the Tuple list.)
+ /// Use the NameSearchContext to generate a Decl for the given type. (Types
+ /// are not placed in the Tuple list.)
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
@@ -601,8 +596,8 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Generate a Decl for "*this" and add a member function declaration
- /// to it for the expression, then report it.
+ /// Generate a Decl for "*this" and add a member function declaration to it
+ /// for the expression, then report it.
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index d9e53074b3fb..c5406fcc3340 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -182,8 +182,7 @@ public:
m_manager->AddDiagnostic(new_diagnostic);
// Don't store away warning fixits, since the compiler doesn't have
- // enough
- // context in an expression for the warning to be useful.
+ // enough context in an expression for the warning to be useful.
// FIXME: Should we try to filter out FixIts that apply to our generated
// code, and not the user's expression?
if (severity == eDiagnosticSeverityError) {
@@ -226,10 +225,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_code_generator(), m_pp_callbacks(nullptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- // We can't compile expressions without a target. So if the exe_scope is null
- // or doesn't have a target,
- // then we just need to get out of here. I'll lldb_assert and not make any of
- // the compiler objects since
+ // We can't compile expressions without a target. So if the exe_scope is
+ // null or doesn't have a target, then we just need to get out of here. I'll
+ // lldb_assert and not make any of the compiler objects since
// I can't return errors directly from the constructor. Further calls will
// check if the compiler was made and
// bag out if it wasn't.
@@ -262,14 +260,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
const auto target_machine = target_arch.GetMachine();
- // If the expression is being evaluated in the context of an existing
- // stack frame, we introspect to see if the language runtime is available.
+ // If the expression is being evaluated in the context of an existing stack
+ // frame, we introspect to see if the language runtime is available.
lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame();
lldb::ProcessSP process_sp = exe_scope->CalculateProcess();
- // Make sure the user hasn't provided a preferred execution language
- // with `expression --language X -- ...`
+ // Make sure the user hasn't provided a preferred execution language with
+ // `expression --language X -- ...`
if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown)
frame_lang = frame_sp->GetLanguage();
@@ -281,8 +279,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
}
// 2. Configure the compiler with a set of default options that are
- // appropriate
- // for most situations.
+ // appropriate for most situations.
if (target_arch.IsValid()) {
std::string triple = target_arch.GetTriple().str();
m_compiler->getTargetOpts().Triple = triple;
@@ -292,19 +289,17 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
} else {
// If we get here we don't have a valid target and just have to guess.
// Sometimes this will be ok to just use the host target triple (when we
- // evaluate say "2+3", but other
- // expressions like breakpoint conditions and other things that _are_ target
- // specific really shouldn't just be
- // using the host triple. In such a case the language runtime should expose
- // an overridden options set (3),
- // below.
+ // evaluate say "2+3", but other expressions like breakpoint conditions and
+ // other things that _are_ target specific really shouldn't just be using
+ // the host triple. In such a case the language runtime should expose an
+ // overridden options set (3), below.
m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
if (log)
log->Printf("Using default target triple of %s",
m_compiler->getTargetOpts().Triple.c_str());
}
- // Now add some special fixes for known architectures:
- // Any arm32 iOS environment, but not on arm64
+ // Now add some special fixes for known architectures: Any arm32 iOS
+ // environment, but not on arm64
if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) {
@@ -317,8 +312,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getTargetOpts().Features.push_back("+sse2");
}
- // Set the target CPU to generate code for.
- // This will be empty for any CPU that doesn't really need to make a special
+ // Set the target CPU to generate code for. This will be empty for any CPU
+ // that doesn't really need to make a special
// CPU string.
m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU();
@@ -328,11 +323,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getTargetOpts().ABI = abi;
// 3. Now allow the runtime to provide custom configuration options for the
- // target.
- // In this case, a specialized language runtime is available and we can query
- // it for extra options.
- // For 99% of use cases, this will not be needed and should be provided when
- // basic platform detection is not enough.
+ // target. In this case, a specialized language runtime is available and we
+ // can query it for extra options. For 99% of use cases, this will not be
+ // needed and should be provided when basic platform detection is not enough.
if (lang_rt)
overridden_target_opts =
lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts());
@@ -378,9 +371,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
case lldb::eLanguageTypeC11:
// FIXME: the following language option is a temporary workaround,
// to "ask for C, get C++."
- // For now, the expression parser must use C++ anytime the
- // language is a C family language, because the expression parser
- // uses features of C++ to capture values.
+ // For now, the expression parser must use C++ anytime the language is a C
+ // family language, because the expression parser uses features of C++ to
+ // capture values.
m_compiler->getLangOpts().CPlusPlus = true;
break;
case lldb::eLanguageTypeObjC:
@@ -392,10 +385,10 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
// Clang now sets as default C++14 as the default standard (with
// GNU extensions), so we do the same here to avoid mismatches that
- // cause compiler error when evaluating expressions (e.g. nullptr
- // not found as it's a C++11 feature). Currently lldb evaluates
- // C++14 as C++11 (see two lines below) so we decide to be consistent
- // with that, but this could be re-evaluated in the future.
+ // cause compiler error when evaluating expressions (e.g. nullptr not found
+ // as it's a C++11 feature). Currently lldb evaluates C++14 as C++11 (see
+ // two lines below) so we decide to be consistent with that, but this could
+ // be re-evaluated in the future.
m_compiler->getLangOpts().CPlusPlus11 = true;
break;
case lldb::eLanguageTypeC_plus_plus:
@@ -407,8 +400,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
case lldb::eLanguageTypeC_plus_plus_03:
m_compiler->getLangOpts().CPlusPlus = true;
// FIXME: the following language option is a temporary workaround,
- // to "ask for C++, get ObjC++". Apple hopes to remove this requirement
- // on non-Apple platforms, but for now it is needed.
+ // to "ask for C++, get ObjC++". Apple hopes to remove this requirement on
+ // non-Apple platforms, but for now it is needed.
m_compiler->getLangOpts().ObjC1 = true;
break;
case lldb::eLanguageTypeObjC_plus_plus:
@@ -434,10 +427,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
ArchSpec(m_compiler->getTargetOpts().Triple.c_str())
.CharIsSignedByDefault();
- // Spell checking is a nice feature, but it ends up completing a
- // lot of types that we didn't strictly speaking need to complete.
- // As a result, we spend a long time parsing and importing debug
- // information.
+ // Spell checking is a nice feature, but it ends up completing a lot of types
+ // that we didn't strictly speaking need to complete. As a result, we spend a
+ // long time parsing and importing debug information.
m_compiler->getLangOpts().SpellChecking = false;
if (process_sp && m_compiler->getLangOpts().ObjC1) {
@@ -513,8 +505,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
}
- // 8. Most of this we get from the CompilerInstance, but we
- // also want to give the context an ExternalASTSource.
+ // 8. Most of this we get from the CompilerInstance, but we also want to give
+ // the context an ExternalASTSource.
m_selector_table.reset(new SelectorTable());
m_builtin_context.reset(new Builtin::Context());
@@ -569,9 +561,7 @@ unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) {
codegenoptions::FullDebugInfo) {
int temp_fd = -1;
llvm::SmallString<PATH_MAX> result_path;
- FileSpec tmpdir_file_spec;
- if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir,
- tmpdir_file_spec)) {
+ if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
std::string temp_source_path = tmpdir_file_spec.GetPath();
llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
@@ -811,7 +801,7 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution(
{
auto lang = m_expr.Language();
if (log)
- log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__,
+ log->Printf("%s - Current expression language is %s\n", __FUNCTION__,
Language::GetNameForLanguageType(lang));
lldb::ProcessSP process_sp = exe_ctx.GetProcessSP();
if (process_sp && lang != lldb::eLanguageTypeUnknown) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
index 41f290f2e127..4058ec1270b3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -26,14 +26,14 @@ class IRExecutionUnit;
//----------------------------------------------------------------------
/// @class ClangExpressionParser ClangExpressionParser.h
-/// "lldb/Expression/ClangExpressionParser.h"
-/// @brief Encapsulates an instance of Clang that can parse expressions.
+/// "lldb/Expression/ClangExpressionParser.h" Encapsulates an instance of
+/// Clang that can parse expressions.
///
/// ClangExpressionParser is responsible for preparing an instance of
/// ClangExpression for execution. ClangExpressionParser uses ClangExpression
/// as a glorified parameter list, performing the required parsing and
-/// conversion to formats (DWARF bytecode, or JIT compiled machine code)
-/// that can be executed.
+/// conversion to formats (DWARF bytecode, or JIT compiled machine code) that
+/// can be executed.
//----------------------------------------------------------------------
class ClangExpressionParser : public ExpressionParser {
public:
@@ -59,8 +59,8 @@ public:
~ClangExpressionParser() override;
//------------------------------------------------------------------
- /// Parse a single expression and convert it to IR using Clang. Don't
- /// wrap the expression in anything at all.
+ /// Parse a single expression and convert it to IR using Clang. Don't wrap
+ /// the expression in anything at all.
///
/// @param[in] diagnostic_manager
/// The diagnostic manager to report errors to.
@@ -74,8 +74,8 @@ public:
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override;
//------------------------------------------------------------------
- /// Ready an already-parsed expression for execution, possibly
- /// evaluating it statically.
+ /// Ready an already-parsed expression for execution, possibly evaluating it
+ /// statically.
///
/// @param[out] func_addr
/// The address to which the function has been written.
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index baa80d7ba0d4..7d5ced5b4705 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -41,27 +41,25 @@ class ValueObjectConstResult;
//----------------------------------------------------------------------
/// @class ClangExpressionVariable ClangExpressionVariable.h
-/// "lldb/Expression/ClangExpressionVariable.h"
-/// @brief Encapsulates one variable for the expression parser.
+/// "lldb/Expression/ClangExpressionVariable.h" Encapsulates one variable for
+/// the expression parser.
///
/// The expression parser uses variables in three different contexts:
///
-/// First, it stores persistent variables along with the process for use
-/// in expressions. These persistent variables contain their own data
-/// and are typed.
+/// First, it stores persistent variables along with the process for use in
+/// expressions. These persistent variables contain their own data and are
+/// typed.
///
-/// Second, in an interpreted expression, it stores the local variables
-/// for the expression along with the expression. These variables
-/// contain their own data and are typed.
+/// Second, in an interpreted expression, it stores the local variables for
+/// the expression along with the expression. These variables contain their
+/// own data and are typed.
///
-/// Third, in a JIT-compiled expression, it stores the variables that
-/// the expression needs to have materialized and dematerialized at each
-/// execution. These do not contain their own data but are named and
-/// typed.
+/// Third, in a JIT-compiled expression, it stores the variables that the
+/// expression needs to have materialized and dematerialized at each
+/// execution. These do not contain their own data but are named and typed.
///
-/// This class supports all of these use cases using simple type
-/// polymorphism, and provides necessary support methods. Its interface
-/// is RTTI-neutral.
+/// This class supports all of these use cases using simple type polymorphism,
+/// and provides necessary support methods. Its interface is RTTI-neutral.
//----------------------------------------------------------------------
class ClangExpressionVariable : public ExpressionVariable {
public:
@@ -79,8 +77,8 @@ public:
lldb::ByteOrder byte_order, uint32_t addr_byte_size);
//----------------------------------------------------------------------
- /// Utility functions for dealing with ExpressionVariableLists in
- /// Clang-specific ways
+ /// Utility functions for dealing with ExpressionVariableLists in Clang-
+ /// specific ways
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -112,9 +110,9 @@ public:
}
//----------------------------------------------------------------------
- /// If the variable contains its own data, make a Value point at it.
- /// If \a exe_ctx in not NULL, the value will be resolved in with
- /// that execution context.
+ /// If the variable contains its own data, make a Value point at it. If \a
+ /// exe_ctx in not NULL, the value will be resolved in with that execution
+ /// context.
///
/// @param[in] value
/// The value to point at the data.
@@ -156,8 +154,8 @@ private:
public:
//----------------------------------------------------------------------
- /// Make this variable usable by the parser by allocating space for
- /// parser-specific variables
+ /// Make this variable usable by the parser by allocating space for parser-
+ /// specific variables
//----------------------------------------------------------------------
void EnableParserVars(uint64_t parser_id) {
m_parser_vars.insert(std::make_pair(parser_id, ParserVars()));
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index a26ceda82d5f..e3e0ed49181e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -101,14 +101,12 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
m_wrapper_function_text.append(" (*fn_ptr) (");
// Get the number of arguments. If we have a function type and it is
- // prototyped,
- // trust that, otherwise use the values we were given.
+ // prototyped, trust that, otherwise use the values we were given.
// FIXME: This will need to be extended to handle Variadic functions. We'll
// need
// to pull the defined arguments out of the function, then add the types from
- // the
- // arguments list for the variable arguments.
+ // the arguments list for the variable arguments.
uint32_t num_args = UINT32_MAX;
bool trust_function = false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
index 0596d8fde7b9..438cf0c713da 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -31,8 +31,8 @@ class ClangExpressionParser;
//----------------------------------------------------------------------
/// @class ClangFunctionCaller ClangFunctionCaller.h
-/// "lldb/Expression/ClangFunctionCaller.h"
-/// @brief Encapsulates a function that can be called.
+/// "lldb/Expression/ClangFunctionCaller.h" Encapsulates a function that can
+/// be called.
///
/// A given ClangFunctionCaller object can handle a single function signature.
/// Once constructed, it can set up any number of concurrent calls to
@@ -56,8 +56,8 @@ class ClangExpressionParser;
/// If you need to call the function on the thread plan stack, you can also
/// call InsertFunction() followed by GetThreadPlanToCallFunction().
///
-/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
-/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
+/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed a
+/// pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
/// and its address returned in that variable.
///
/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
@@ -79,8 +79,8 @@ class ClangFunctionCaller : public FunctionCaller {
ClangExpressionDeclMap *DeclMap() override { return NULL; }
//------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
+ /// Return the object that the parser should allow to access ASTs. May be
+ /// NULL if the ASTs do not need to be transformed.
///
/// @param[in] passthrough
/// The ASTConsumer that the returned transformer should send
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
new file mode 100644
index 000000000000..4251d2ee75b9
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
@@ -0,0 +1,142 @@
+//===-- ClangHost.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangHost.h"
+
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Threading.h"
+
+// Project includes
+#include "lldb/Host/HostInfo.h"
+#if !defined(_WIN32)
+#include "lldb/Host/posix/HostInfoPosix.h"
+#endif
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
+
+#include <string>
+
+using namespace lldb_private;
+
+#if defined(_WIN32)
+static bool ComputeClangDirectory(FileSpec &file_spec) { return false; }
+#else
+static bool DefaultComputeClangDirectory(FileSpec &file_spec) {
+ return HostInfoPosix::ComputePathRelativeToLibrary(
+ file_spec, (llvm::Twine("/lib") + CLANG_LIBDIR_SUFFIX + "/clang/" +
+ CLANG_VERSION_STRING)
+ .str());
+}
+
+#if defined(__APPLE__)
+
+static bool VerifyClangPath(const llvm::Twine &clang_path) {
+ if (llvm::sys::fs::is_directory(clang_path))
+ return true;
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (log)
+ log->Printf("VerifyClangPath(): "
+ "failed to stat clang resource directory at \"%s\"",
+ clang_path.str().c_str());
+ return false;
+}
+
+bool lldb_private::ComputeClangDirectory(FileSpec &lldb_shlib_spec,
+ FileSpec &file_spec, bool verify) {
+ std::string raw_path = lldb_shlib_spec.GetPath();
+
+ auto rev_it = llvm::sys::path::rbegin(raw_path);
+ auto r_end = llvm::sys::path::rend(raw_path);
+
+ // Check for a Posix-style build of LLDB.
+ while (rev_it != r_end) {
+ if (*rev_it == "LLDB.framework")
+ break;
+ ++rev_it;
+ }
+
+ if (rev_it == r_end)
+ return DefaultComputeClangDirectory(file_spec);
+
+ // Inside Xcode and in Xcode toolchains LLDB is always in lockstep
+ // with the Swift compiler, so it can reuse its Clang resource
+ // directory. This allows LLDB and the Swift compiler to share the
+ // same Clang module cache.
+ llvm::SmallString<256> clang_path;
+ const char *swift_clang_resource_dir = "usr/lib/swift/clang";
+ auto parent = std::next(rev_it);
+ if (parent != r_end && *parent == "SharedFrameworks") {
+ // This is the top-level LLDB in the Xcode.app bundle.
+ // E.g., "Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A"
+ raw_path.resize(parent - r_end);
+ llvm::sys::path::append(clang_path, raw_path,
+ "Developer/Toolchains/XcodeDefault.xctoolchain",
+ swift_clang_resource_dir);
+ if (!verify || VerifyClangPath(clang_path)) {
+ file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native);
+ return true;
+ }
+ } else if (parent != r_end && *parent == "PrivateFrameworks" &&
+ std::distance(parent, r_end) > 2) {
+ ++parent;
+ ++parent;
+ if (*parent == "System") {
+ // This is LLDB inside an Xcode toolchain.
+ // E.g., "Xcode.app/Contents/Developer/Toolchains/" \
+ // "My.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework"
+ raw_path.resize(parent - r_end);
+ llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir);
+ if (!verify || VerifyClangPath(clang_path)) {
+ file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native);
+ return true;
+ }
+ raw_path = lldb_shlib_spec.GetPath();
+ }
+ raw_path.resize(rev_it - r_end);
+ } else {
+ raw_path.resize(rev_it - r_end);
+ }
+
+ // Fall back to the Clang resource directory inside the framework.
+ raw_path.append("LLDB.framework/Resources/Clang");
+ file_spec.SetFile(raw_path.c_str(), true, FileSpec::Style::native);
+ return true;
+}
+
+static bool ComputeClangDirectory(FileSpec &file_spec) {
+ if (FileSpec lldb_file_spec = HostInfo::GetShlibDir())
+ return ComputeClangDirectory(lldb_file_spec, file_spec, true);
+ return false;
+}
+#else // __APPLE__
+
+// All non-Apple posix systems.
+static bool ComputeClangDirectory(FileSpec &file_spec) {
+ return DefaultComputeClangDirectory(file_spec);
+}
+#endif // __APPLE__
+#endif // _WIN32
+
+FileSpec lldb_private::GetClangResourceDir() {
+ static FileSpec g_cached_resource_dir;
+ static llvm::once_flag g_once_flag;
+ llvm::call_once(g_once_flag, []() {
+ ::ComputeClangDirectory(g_cached_resource_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (log)
+ log->Printf("GetClangResourceDir() => '%s'",
+ g_cached_resource_dir.GetPath().c_str());
+ });
+ return g_cached_resource_dir;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.h
new file mode 100644
index 000000000000..4fe423adb1a5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.h
@@ -0,0 +1,26 @@
+//===-- ClangHost.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGHOST_H
+#define LLDB_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGHOST_H
+
+namespace lldb_private {
+
+class FileSpec;
+
+#if defined(__APPLE__)
+bool ComputeClangDirectory(FileSpec &lldb_shlib_spec, FileSpec &file_spec,
+ bool verify);
+#endif
+
+FileSpec GetClangResourceDir();
+
+} // namespace lldb_private
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index b42ceb9afee8..665195f01774 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -25,8 +25,10 @@
#include "llvm/Support/Threading.h"
// Project includes
+#include "ClangHost.h"
#include "ClangModulesDeclVendor.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -39,9 +41,9 @@
using namespace lldb_private;
namespace {
-// Any Clang compiler requires a consumer for diagnostics. This one stores them
-// as strings
-// so we can provide them to the user in case a module failed to load.
+// Any Clang compiler requires a consumer for diagnostics. This one stores
+// them as strings so we can provide them to the user in case a module failed
+// to load.
class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
public:
StoringDiagnosticConsumer();
@@ -61,8 +63,7 @@ private:
};
// The private implementation of our ClangModulesDeclVendor. Contains all the
-// Clang state required
-// to load modules.
+// Clang state required to load modules.
class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
public:
ClangModulesDeclVendorImpl(
@@ -144,18 +145,6 @@ void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
}
}
-static FileSpec GetResourceDir() {
- static FileSpec g_cached_resource_dir;
-
- static llvm::once_flag g_once_flag;
-
- llvm::call_once(g_once_flag, []() {
- HostInfo::GetLLDBPath(lldb::ePathTypeClangDir, g_cached_resource_dir);
- });
-
- return g_cached_resource_dir;
-}
-
ClangModulesDeclVendor::ClangModulesDeclVendor() {}
ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
@@ -168,7 +157,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
: m_diagnostics_engine(std::move(diagnostics_engine)),
m_compiler_invocation(std::move(compiler_invocation)),
m_compiler_instance(std::move(compiler_instance)),
- m_parser(std::move(parser)) {}
+ m_parser(std::move(parser)), m_origin_map() {}
void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
std::set<ClangModulesDeclVendor::ModuleID> &exports,
@@ -590,14 +579,11 @@ ClangModulesDeclVendor::Create(Target &target) {
// Add additional search paths with { "-I", path } or { "-F", path } here.
{
- llvm::SmallString<128> DefaultModuleCache;
- const bool erased_on_reboot = false;
- llvm::sys::path::system_temp_directory(erased_on_reboot,
- DefaultModuleCache);
- llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
- llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
+ llvm::SmallString<128> path;
+ auto props = ModuleList::GetGlobalModuleListProperties();
+ props.GetClangModulesCachePath().GetPath(path);
std::string module_cache_argument("-fmodules-cache-path=");
- module_cache_argument.append(DefaultModuleCache.str().str());
+ module_cache_argument.append(path.str());
compiler_invocation_arguments.push_back(module_cache_argument);
}
@@ -613,7 +599,7 @@ ClangModulesDeclVendor::Create(Target &target) {
}
{
- FileSpec clang_resource_dir = GetResourceDir();
+ FileSpec clang_resource_dir = GetClangResourceDir();
if (llvm::sys::fs::is_directory(clang_resource_dir.GetPath())) {
compiler_invocation_arguments.push_back("-resource-dir");
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index 8ebf78409a03..bb73d55a9a41 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -10,6 +10,7 @@
#include "ClangPersistentVariables.h"
#include "lldb/Core/Value.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -52,14 +53,6 @@ void ClangPersistentVariables::RemovePersistentVariable(
m_next_persistent_variable_id--;
}
-ConstString ClangPersistentVariables::GetNextPersistentVariableName() {
- char name_cstr[256];
- ::snprintf(name_cstr, sizeof(name_cstr), "$%u",
- m_next_persistent_variable_id++);
- ConstString name(name_cstr);
- return name;
-}
-
void ClangPersistentVariables::RegisterPersistentDecl(const ConstString &name,
clang::NamedDecl *decl) {
m_persistent_decls.insert(
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index 16981a7fe14a..59126974616d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -25,9 +25,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangPersistentVariables ClangPersistentVariables.h
-/// "lldb/Expression/ClangPersistentVariables.h"
-/// @brief Manages persistent values that need to be preserved between
-/// expression invocations.
+/// "lldb/Expression/ClangPersistentVariables.h" Manages persistent values
+/// that need to be preserved between expression invocations.
///
/// A list of variables that can be accessed and updated by any expression. See
/// ClangPersistentVariable for more discussion. Also provides an increasing,
@@ -54,16 +53,11 @@ public:
const CompilerType &compiler_type, lldb::ByteOrder byte_order,
uint32_t addr_byte_size) override;
- //----------------------------------------------------------------------
- /// Return the next entry in the sequence of strings "$0", "$1", ... for
- /// use naming persistent expression convenience variables.
- ///
- /// @return
- /// A string that contains the next persistent variable name.
- //----------------------------------------------------------------------
- ConstString GetNextPersistentVariableName() override;
-
void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
+ llvm::StringRef
+ GetPersistentVariablePrefix(bool is_error) const override {
+ return "$";
+ }
void RegisterPersistentDecl(const ConstString &name, clang::NamedDecl *decl);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 18fe8b49227b..2e61f704127a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -65,7 +65,8 @@ ClangUserExpression::ClangUserExpression(
options),
m_type_system_helper(*m_target_wp.lock().get(),
options.GetExecutionPolicy() ==
- eExecutionPolicyTopLevel) {
+ eExecutionPolicyTopLevel),
+ m_result_delegate(exe_scope.CalculateTarget()) {
switch (m_language) {
case lldb::eLanguageTypeC_plus_plus:
m_allow_cxx = true;
@@ -195,12 +196,10 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
} else if (clang::FunctionDecl *function_decl =
ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) {
// We might also have a function that said in the debug information that it
- // captured an
- // object pointer. The best way to deal with getting to the ivars at
- // present is by pretending
- // that this is a method of a class in whatever runtime the debug info says
- // the object pointer
- // belongs to. Do that here.
+ // captured an object pointer. The best way to deal with getting to the
+ // ivars at present is by pretending that this is a method of a class in
+ // whatever runtime the debug info says the object pointer belongs to. Do
+ // that here.
ClangASTMetadata *metadata =
ClangASTContext::DeclContextGetMetaData(decl_context, function_decl);
@@ -290,10 +289,10 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
}
}
-// This is a really nasty hack, meant to fix Objective-C expressions of the form
-// (int)[myArray count]. Right now, because the type information for count is
-// not available, [myArray count] returns id, which can't be directly cast to
-// int without causing a clang error.
+// This is a really nasty hack, meant to fix Objective-C expressions of the
+// form (int)[myArray count]. Right now, because the type information for
+// count is not available, [myArray count] returns id, which can't be directly
+// cast to int without causing a clang error.
static void ApplyObjcCastHack(std::string &expr) {
#define OBJC_CAST_HACK_FROM "(int)["
#define OBJC_CAST_HACK_TO "(int)(long long)["
@@ -308,17 +307,23 @@ static void ApplyObjcCastHack(std::string &expr) {
#undef OBJC_CAST_HACK_FROM
}
-bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
- ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory,
- bool generate_debug_info) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+namespace {
+// Utility guard that calls a callback when going out of scope.
+class OnExit {
+public:
+ typedef std::function<void(void)> Callback;
- Status err;
+ OnExit(Callback const &callback) : m_callback(callback) {}
- InstallContext(exe_ctx);
+ ~OnExit() { m_callback(); }
+
+private:
+ Callback m_callback;
+};
+} // namespace
+bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx) {
if (Target *target = exe_ctx.GetTargetPtr()) {
if (PersistentExpressionState *persistent_state =
target->GetPersistentExpressionStateForLanguage(
@@ -335,26 +340,15 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
"error: couldn't start parsing (no target)");
return false;
}
+ return true;
+}
- ScanContext(exe_ctx, err);
-
- if (!err.Success()) {
- diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
- }
-
- ////////////////////////////////////
- // Generate the expression
- //
-
- ApplyObjcCastHack(m_expr_text);
-
- std::string prefix = m_expr_prefix;
-
+static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
if (ClangModulesDeclVendor *decl_vendor =
- m_target->GetClangModulesDeclVendor()) {
+ target->GetClangModulesDeclVendor()) {
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
llvm::cast<ClangPersistentVariables>(
- m_target->GetPersistentExpressionStateForLanguage(
+ target->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeC))
->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
@@ -363,7 +357,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
modules_for_macros.push_back(module);
}
- if (m_target->GetEnableAutoImportClangModules()) {
+ if (target->GetEnableAutoImportClangModules()) {
if (StackFrame *frame = exe_ctx.GetFramePtr()) {
if (Block *block = frame->GetFrameBlock()) {
SymbolContext sc;
@@ -380,8 +374,13 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
}
}
}
+}
- lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
+llvm::Optional<lldb::LanguageType> ClangUserExpression::GetLanguageForExpr(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown;
+
+ std::string prefix = m_expr_prefix;
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
m_transformed_text = m_expr_text;
@@ -401,9 +400,50 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
exe_ctx)) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"couldn't construct expression body");
- return false;
+ return llvm::Optional<lldb::LanguageType>();
}
}
+ return lang_type;
+}
+
+bool ClangUserExpression::PrepareForParsing(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ InstallContext(exe_ctx);
+
+ if (!SetupPersistentState(diagnostic_manager, exe_ctx))
+ return false;
+
+ Status err;
+ ScanContext(exe_ctx, err);
+
+ if (!err.Success()) {
+ diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
+ }
+
+ ////////////////////////////////////
+ // Generate the expression
+ //
+
+ ApplyObjcCastHack(m_expr_text);
+
+ SetupDeclVendor(exe_ctx, m_target);
+ return true;
+}
+
+bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ return false;
+
+ lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown;
+ if (auto new_lang = GetLanguageForExpr(diagnostic_manager, exe_ctx)) {
+ lang_type = new_lang.getValue();
+ }
if (log)
log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
@@ -427,28 +467,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
- class OnExit {
- public:
- typedef std::function<void(void)> Callback;
-
- OnExit(Callback const &callback) : m_callback(callback) {}
-
- ~OnExit() { m_callback(); }
-
- private:
- Callback m_callback;
- };
-
OnExit on_exit([this]() { ResetDeclMap(); });
if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
-
- ResetDeclMap(); // We are being careful here in the case of breakpoint
- // conditions.
-
return false;
}
@@ -463,17 +487,15 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
exe_scope = exe_ctx.GetTargetPtr();
// We use a shared pointer here so we can use the original parser - if it
- // succeeds
- // or the rewrite parser we might make if it fails. But the parser_sp will
- // never be empty.
+ // succeeds or the rewrite parser we might make if it fails. But the
+ // parser_sp will never be empty.
ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
unsigned num_errors = parser.Parse(diagnostic_manager);
// Check here for FixItHints. If there are any try to apply the fixits and
- // set the fixed text in m_fixed_text
- // before returning an error.
+ // set the fixed text in m_fixed_text before returning an error.
if (num_errors) {
if (diagnostic_manager.HasFixIts()) {
if (parser.RewriteExpression(diagnostic_manager)) {
@@ -487,16 +509,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
fixed_expression.substr(fixed_start, fixed_end - fixed_start);
}
}
-
- ResetDeclMap(); // We are being careful here in the case of breakpoint
- // conditions.
-
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
- // Prepare the output of the parser for execution, evaluating it statically if
- // possible
+ // Prepare the output of the parser for execution, evaluating it statically
+ // if possible
//
{
@@ -539,9 +557,9 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
register_execution_unit = true;
}
- // If there is more than one external function in the execution
- // unit, it needs to keep living even if it's not top level, because
- // the result could refer to that function.
+ // If there is more than one external function in the execution unit, it
+ // needs to keep living even if it's not top level, because the result
+ // could refer to that function.
if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
register_execution_unit = true;
@@ -568,10 +586,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
}
}
- ResetDeclMap(); // Make this go away since we don't need any of its state
- // after parsing. This also gets rid of any
- // ClangASTImporter::Minions.
-
if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
return true;
@@ -667,10 +681,10 @@ void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
}
}
-ClangUserExpression::ResultDelegate::ResultDelegate() {}
-
ConstString ClangUserExpression::ResultDelegate::GetName() {
- return m_persistent_state->GetNextPersistentVariableName();
+ auto prefix = m_persistent_state->GetPersistentVariablePrefix();
+ return m_persistent_state->GetNextPersistentVariableName(*m_target_sp,
+ prefix);
}
void ClangUserExpression::ResultDelegate::DidDematerialize(
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index 88a78798b657..ac363bf91747 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -35,13 +35,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangUserExpression ClangUserExpression.h
-/// "lldb/Expression/ClangUserExpression.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// "lldb/Expression/ClangUserExpression.h" Encapsulates a single expression
+/// for use with Clang
///
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command. ClangUserExpression encapsulates
-/// the objects needed to parse and interpret or JIT an expression. It
-/// uses the Clang parser to produce LLVM IR from the expression.
+/// the objects needed to parse and interpret or JIT an expression. It uses
+/// the Clang parser to produce LLVM IR from the expression.
//----------------------------------------------------------------------
class ClangUserExpression : public LLVMUserExpression {
public:
@@ -69,8 +69,8 @@ public:
bool keep_result_in_memory);
//------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
+ /// Return the object that the parser should allow to access ASTs. May be
+ /// NULL if the ASTs do not need to be transformed.
///
/// @param[in] passthrough
/// The ASTConsumer that the returned transformer should send
@@ -174,11 +174,18 @@ private:
lldb::addr_t struct_address,
DiagnosticManager &diagnostic_manager) override;
+ llvm::Optional<lldb::LanguageType> GetLanguageForExpr(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx);
+ bool SetupPersistentState(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx);
+ bool PrepareForParsing(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx);
+
ClangUserExpressionHelper m_type_system_helper;
class ResultDelegate : public Materializer::PersistentVariableDelegate {
public:
- ResultDelegate();
+ ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {}
ConstString GetName() override;
void DidDematerialize(lldb::ExpressionVariableSP &variable) override;
@@ -188,6 +195,7 @@ private:
private:
PersistentExpressionState *m_persistent_state;
lldb::ExpressionVariableSP m_variable;
+ lldb::TargetSP m_target_sp;
};
ResultDelegate m_result_delegate;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 80577199b818..a897a2b17087 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -29,15 +29,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangUtilityFunction ClangUtilityFunction.h
-/// "lldb/Expression/ClangUtilityFunction.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// "lldb/Expression/ClangUtilityFunction.h" Encapsulates a single expression
+/// for use with Clang
///
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command. ClangUtilityFunction encapsulates
/// a self-contained function meant to be used from other code. Utility
/// functions can perform error-checking for ClangUserExpressions, or can
-/// simply provide a way to push a function into the target for the debugger to
-/// call later on.
+/// simply provide a way to push a function into the target for the debugger
+/// to call later on.
//----------------------------------------------------------------------
class ClangUtilityFunction : public UtilityFunction {
public:
@@ -60,8 +60,8 @@ public:
void ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory);
//------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
+ /// Return the object that the parser should allow to access ASTs. May be
+ /// NULL if the ASTs do not need to be transformed.
///
/// @param[in] passthrough
/// The ASTConsumer that the returned transformer should send
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index 13f5657eedd8..e51c9ee07b9f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -263,8 +263,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
}
// Get the next available result name from m_decl_map and create the
- // persistent
- // variable for it
+ // persistent variable for it
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
@@ -345,9 +344,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
GlobalValue::ExternalLinkage, NULL, /* no initializer */
m_result_name.GetCString());
- // It's too late in compilation to create a new VarDecl for this, but we don't
- // need to. We point the metadata at the old VarDecl. This creates an odd
- // anomaly: a variable with a Value whose name is something like $0 and a
+ // It's too late in compilation to create a new VarDecl for this, but we
+ // don't need to. We point the metadata at the old VarDecl. This creates an
+ // odd anomaly: a variable with a Value whose name is something like $0 and a
// Decl whose name is $__lldb_expr_result. This condition is handled in
// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
// fixed up.
@@ -464,9 +463,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,
// CFAllocatorRef -> i8*
// UInt8 * -> i8*
// CFIndex -> long (i32 or i64, as appropriate; we ask the module for its
- // pointer size for now)
- // CFStringEncoding -> i32
- // Boolean -> i8
+ // pointer size for now) CFStringEncoding -> i32 Boolean -> i8
Type *arg_type_array[5];
@@ -801,9 +798,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
// Unpack the message name from the selector. In LLVM IR, an objc_msgSend
// gets represented as
//
- // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*>
- // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...)
- // ; <i8*>
+ // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> %call = call
+ // i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
//
// where %obj is the object pointer and %tmp is the selector.
//
@@ -870,7 +866,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
log->Printf("Found sel_registerName at 0x%" PRIx64,
sel_registerName_addr);
- // Build the function type: struct objc_selector *sel_registerName(uint8_t*)
+ // Build the function type: struct objc_selector
+ // *sel_registerName(uint8_t*)
// The below code would be "more correct," but in actuality what's required
// is uint8_t*
@@ -980,11 +977,10 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) {
// %struct._objc_class** @OBJC_CLASS_REFERENCES_, align 4
//
// @"OBJC_CLASS_REFERENCES_ is a bitcast of a character array called
- // @OBJC_CLASS_NAME_.
- // @OBJC_CLASS_NAME contains the string.
+ // @OBJC_CLASS_NAME_. @OBJC_CLASS_NAME contains the string.
- // Find the pointer's initializer (a ConstantExpr with opcode BitCast)
- // and get the string from its target
+ // Find the pointer's initializer (a ConstantExpr with opcode BitCast) and
+ // get the string from its target
GlobalVariable *_objc_class_references_ =
dyn_cast<GlobalVariable>(load->getPointerOperand());
@@ -1159,8 +1155,8 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
GlobalValue::ExternalLinkage, NULL, /* no initializer */
alloc->getName().str());
- // What we're going to do here is make believe this was a regular old external
- // variable. That means we need to make the metadata valid.
+ // What we're going to do here is make believe this was a regular old
+ // external variable. That means we need to make the metadata valid.
NamedMDNode *named_metadata =
m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
@@ -1175,8 +1171,7 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
named_metadata->addOperand(persistent_global_md);
// Now, since the variable is a pointer variable, we will drop in a load of
- // that
- // pointer variable.
+ // that pointer variable.
LoadInst *persistent_load = new LoadInst(persistent_global, "", alloc);
@@ -1366,16 +1361,13 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
if (name[0] == '$') {
// The $__lldb_expr_result name indicates the return value has allocated
- // as
- // a static variable. Per the comment at
- // ASTResultSynthesizer::SynthesizeBodyResult,
- // accesses to this static variable need to be redirected to the result of
- // dereferencing
- // a pointer that is passed in as one of the arguments.
+ // as a static variable. Per the comment at
+ // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static
+ // variable need to be redirected to the result of dereferencing a
+ // pointer that is passed in as one of the arguments.
//
// Consequently, when reporting the size of the type, we report a pointer
- // type pointing
- // to the type of $__lldb_expr_result, not the type itself.
+ // type pointing to the type of $__lldb_expr_result, not the type itself.
//
// We also do this for any user-declared persistent variables.
compiler_type = compiler_type.GetPointerType();
@@ -1965,12 +1957,11 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {
FunctionValueCache body_result_maker(
[this, name, offset_type, offset, argument,
value](llvm::Function *function) -> llvm::Value * {
- // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in
- // cases where the result
- // variable is an rvalue, we have to synthesize a dereference of the
- // appropriate structure
- // entry in order to produce the static variable that the AST thinks
- // it is accessing.
+ // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
+ // in cases where the result variable is an rvalue, we have to
+ // synthesize a dereference of the appropriate structure entry in
+ // order to produce the static variable that the AST thinks it is
+ // accessing.
llvm::Instruction *entry_instruction = llvm::cast<Instruction>(
m_entry_instruction_finder.GetValue(function));
@@ -2194,7 +2185,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) {
if (log)
log->Printf("RewriteObjCSelectors() failed");
- // RewriteObjCSelectors() reports its own errors, so we don't do so here
+ // RewriteObjCSelectors() reports its own errors, so we don't do so
+ // here
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index 93ce8aa44eb2..c6c44b46023c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -47,12 +47,11 @@ class IRMemoryMap;
//----------------------------------------------------------------------
/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h"
-/// @brief Transforms the IR for a function to run in the target
+/// Transforms the IR for a function to run in the target
///
-/// Once an expression has been parsed and converted to IR, it can run
-/// in two contexts: interpreted by LLDB as a DWARF location expression,
-/// or compiled by the JIT and inserted into the target process for
-/// execution.
+/// Once an expression has been parsed and converted to IR, it can run in two
+/// contexts: interpreted by LLDB as a DWARF location expression, or compiled
+/// by the JIT and inserted into the target process for execution.
///
/// IRForTarget makes the second possible, by applying a series of
/// transformations to the IR which make it relocatable. These
@@ -126,8 +125,7 @@ public:
//------------------------------------------------------------------
/// Interface stub
///
- /// Implementation of the llvm::ModulePass::assignPassManager()
- /// function.
+ /// Implementation of the llvm::ModulePass::assignPassManager() function.
//------------------------------------------------------------------
void assignPassManager(llvm::PMStack &pass_mgr_stack,
llvm::PassManagerType pass_mgr_type =
@@ -179,8 +177,8 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Get the address of a function, and a location to put the complete
- /// Value of the function if one is available.
+ /// Get the address of a function, and a location to put the complete Value
+ /// of the function if one is available.
///
/// @param[in] function
/// The function to find the location of.
@@ -204,13 +202,13 @@ private:
//------------------------------------------------------------------
/// A function-level pass to take the generated global value
- /// $__lldb_expr_result and make it into a persistent variable.
- /// Also see ASTResultSynthesizer.
+ /// $__lldb_expr_result and make it into a persistent variable. Also see
+ /// ASTResultSynthesizer.
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Find the NamedDecl corresponding to a Value. This interface is
- /// exposed for the IR interpreter.
+ /// Find the NamedDecl corresponding to a Value. This interface is exposed
+ /// for the IR interpreter.
///
/// @param[in] module
/// The module containing metadata to search
@@ -230,8 +228,8 @@ private:
//------------------------------------------------------------------
/// Set the constant result variable m_const_result to the provided
- /// constant, assuming it can be evaluated. The result variable
- /// will be reset to NULL later if the expression has side effects.
+ /// constant, assuming it can be evaluated. The result variable will be
+ /// reset to NULL later if the expression has side effects.
///
/// @param[in] initializer
/// The constant initializer for the variable.
@@ -247,8 +245,8 @@ private:
lldb_private::TypeFromParser type);
//------------------------------------------------------------------
- /// If the IR represents a cast of a variable, set m_const_result
- /// to the result of the cast. The result variable will be reset to
+ /// If the IR represents a cast of a variable, set m_const_result to the
+ /// result of the cast. The result variable will be reset to
/// NULL latger if the expression has side effects.
///
/// @param[in] type
@@ -301,10 +299,9 @@ private:
/// rewrite them to use sel_registerName instead of statically allocated
/// selectors. The reason is that the selectors are created on the
/// assumption that the Objective-C runtime will scan the appropriate
- /// section and prepare them. This doesn't happen when code is copied
- /// into the target, though, and there's no easy way to induce the
- /// runtime to scan them. So instead we get our selectors from
- /// sel_registerName.
+ /// section and prepare them. This doesn't happen when code is copied into
+ /// the target, though, and there's no easy way to induce the runtime to
+ /// scan them. So instead we get our selectors from sel_registerName.
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -359,13 +356,12 @@ private:
//------------------------------------------------------------------
/// A basic block-level pass to find all newly-declared persistent
- /// variables and register them with the ClangExprDeclMap. This
- /// allows them to be materialized and dematerialized like normal
- /// external variables. Before transformation, these persistent
- /// variables look like normal locals, so they have an allocation.
- /// This pass excises these allocations and makes references look
- /// like external references where they will be resolved -- like all
- /// other external references -- by ResolveExternals().
+ /// variables and register them with the ClangExprDeclMap. This allows them
+ /// to be materialized and dematerialized like normal external variables.
+ /// Before transformation, these persistent variables look like normal
+ /// locals, so they have an allocation. This pass excises these allocations
+ /// and makes references look like external references where they will be
+ /// resolved -- like all other external references -- by ResolveExternals().
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -389,15 +385,14 @@ private:
//------------------------------------------------------------------
/// A function-level pass to find all external variables and functions
- /// used in the IR. Each found external variable is added to the
- /// struct, and each external function is resolved in place, its call
- /// replaced with a call to a function pointer whose value is the
- /// address of the function in the target process.
+ /// used in the IR. Each found external variable is added to the struct,
+ /// and each external function is resolved in place, its call replaced with
+ /// a call to a function pointer whose value is the address of the function
+ /// in the target process.
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Write an initializer to a memory array of assumed sufficient
- /// size.
+ /// Write an initializer to a memory array of assumed sufficient size.
///
/// @param[in] data
/// A pointer to the data to write to.
@@ -504,8 +499,8 @@ private:
//------------------------------------------------------------------
/// A basic block-level pass to excise guard variables from the code.
/// The result for the function is passed through Clang as a static
- /// variable. Static variables normally have guard variables to
- /// ensure that they are only initialized once.
+ /// variable. Static variables normally have guard variables to ensure that
+ /// they are only initialized once.
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -529,9 +524,9 @@ private:
//------------------------------------------------------------------
/// A function-level pass to make all external variable references
- /// point at the correct offsets from the void* passed into the
- /// function. ClangExpressionDeclMap::DoStructLayout() must be called
- /// beforehand, so that the offsets are valid.
+ /// point at the correct offsets from the void* passed into the function.
+ /// ClangExpressionDeclMap::DoStructLayout() must be called beforehand, so
+ /// that the offsets are valid.
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -583,7 +578,8 @@ private:
llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that
///writes to the result variable. If
- /// m_has_side_effects is true, this is NULL.
+ /// m_has_side_effects is true, this is
+ /// NULL.
bool m_result_is_pointer; ///< True if the function's result in the AST is a
///pointer (see comments in
/// ASTResultSynthesizer::SynthesizeBodyResult)
@@ -594,18 +590,17 @@ private:
/// location of the static allocation.
//------------------------------------------------------------------
- /// UnfoldConstant operates on a constant [Old] which has just been
- /// replaced with a value [New]. We assume that new_value has
- /// been properly placed early in the function, in front of the
- /// first instruction in the entry basic block
- /// [FirstEntryInstruction].
+ /// UnfoldConstant operates on a constant [Old] which has just been replaced
+ /// with a value [New]. We assume that new_value has been properly placed
+ /// early in the function, in front of the first instruction in the entry
+ /// basic block [FirstEntryInstruction].
///
- /// UnfoldConstant reads through the uses of Old and replaces Old
- /// in those uses with New. Where those uses are constants, the
- /// function generates new instructions to compute the result of the
- /// new, non-constant expression and places them before
- /// FirstEntryInstruction. These instructions replace the constant
- /// uses, so UnfoldConstant calls itself recursively for those.
+ /// UnfoldConstant reads through the uses of Old and replaces Old in those
+ /// uses with New. Where those uses are constants, the function generates
+ /// new instructions to compute the result of the new, non-constant
+ /// expression and places them before FirstEntryInstruction. These
+ /// instructions replace the constant uses, so UnfoldConstant calls itself
+ /// recursively for those.
///
/// @param[in] llvm_function
/// The function currently being processed.
@@ -637,8 +632,8 @@ private:
lldb_private::Stream &error_stream);
//------------------------------------------------------------------
- /// Construct a reference to m_reloc_placeholder with a given type
- /// and offset. This typically happens after inserting data into
+ /// Construct a reference to m_reloc_placeholder with a given type and
+ /// offset. This typically happens after inserting data into
/// m_data_allocator.
///
/// @param[in] type
@@ -653,8 +648,8 @@ private:
llvm::Constant *BuildRelocation(llvm::Type *type, uint64_t offset);
//------------------------------------------------------------------
- /// Commit the allocation in m_data_allocator and use its final
- /// location to replace m_reloc_placeholder.
+ /// Commit the allocation in m_data_allocator and use its final location to
+ /// replace m_reloc_placeholder.
///
/// @param[in] module
/// The module that m_data_allocator resides in
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
index 538bd05e25f8..9c845d02bca0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
@@ -67,7 +67,9 @@ private:
size_t m_pos;
};
-GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false) {}
+GoParser::GoParser(const char *src)
+ : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID),
+ m_failed(false) {}
GoASTStmt *GoParser::Statement() {
Rule r("Statement", this);
@@ -437,8 +439,10 @@ GoASTExpr *GoParser::CompositeLit() {
if (!type)
return r.error();
GoASTCompositeLit *lit = LiteralValue();
- if (!lit)
+ if (!lit) {
+ delete type;
return r.error();
+ }
lit->SetType(type);
return lit;
}
@@ -546,6 +550,7 @@ GoASTExpr *GoParser::Arguments(GoASTExpr *e) {
GoASTExpr *GoParser::Conversion() {
Rule r("Conversion", this);
if (GoASTExpr *t = Type2()) {
+ std::unique_ptr<GoASTExpr> owner(t);
if (match(GoLexer::OP_LPAREN)) {
GoASTExpr *v = Expression();
if (!v)
@@ -555,6 +560,7 @@ GoASTExpr *GoParser::Conversion() {
return r.error();
GoASTCallExpr *call = new GoASTCallExpr(false);
call->SetFun(t);
+ owner.release();
call->AddArgs(v);
return call;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
index f4b8cfbe03d4..3a10a1dc767a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
@@ -171,12 +171,11 @@ private:
VariableSP FindGlobalVariable(TargetSP target, llvm::Twine name) {
ConstString fullname(name.str());
VariableList variable_list;
- const bool append = true;
if (!target) {
return nullptr;
}
- const uint32_t match_count = target->GetImages().FindGlobalVariables(
- fullname, append, 1, variable_list);
+ const uint32_t match_count =
+ target->GetImages().FindGlobalVariables(fullname, 1, variable_list);
if (match_count == 1) {
return variable_list.GetVariableAtIndex(0);
}
@@ -272,7 +271,8 @@ GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
PersistentExpressionState *pv =
target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
if (pv != nullptr) {
- result->SetName(pv->GetNextPersistentVariableName());
+ result->SetName(pv->GetNextPersistentVariableName(
+ *target, pv->GetPersistentVariablePrefix()));
pv->AddVariable(result);
}
return lldb::eExpressionCompleted;
@@ -400,8 +400,7 @@ ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) {
val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
else {
// When a variable is on the heap instead of the stack, go records a
- // variable
- // '&x' instead of 'x'.
+ // variable '&x' instead of 'x'.
var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
if (var_sp) {
val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
@@ -651,15 +650,6 @@ ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr(
GoPersistentExpressionState::GoPersistentExpressionState()
: PersistentExpressionState(eKindGo) {}
-ConstString GoPersistentExpressionState::GetNextPersistentVariableName() {
- char name_cstr[256];
- // We can't use the same variable format as clang.
- ::snprintf(name_cstr, sizeof(name_cstr), "$go%u",
- m_next_persistent_variable_id++);
- ConstString name(name_cstr);
- return name;
-}
-
void GoPersistentExpressionState::RemovePersistentVariable(
lldb::ExpressionVariableSP variable) {
RemoveVariable(variable);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h
index 03ceb76b8431..e2839da9bfdd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h
@@ -29,8 +29,10 @@ class GoPersistentExpressionState : public PersistentExpressionState {
public:
GoPersistentExpressionState();
- ConstString GetNextPersistentVariableName() override;
-
+ llvm::StringRef
+ GetPersistentVariablePrefix(bool is_error) const override {
+ return "$go";
+ }
void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
lldb::addr_t LookupSymbol(const ConstString &name) override {
@@ -48,12 +50,12 @@ private:
//----------------------------------------------------------------------
/// @class GoUserExpression GoUserExpression.h
-/// "lldb/Expression/GoUserExpression.h"
-/// @brief Encapsulates a single expression for use with Go
+/// "lldb/Expression/GoUserExpression.h" Encapsulates a single expression for
+/// use with Go
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. GoUserExpression encapsulates
-/// the objects needed to parse and interpret an expression.
+/// and as a backend for the expr command. GoUserExpression encapsulates the
+/// objects needed to parse and interpret an expression.
//----------------------------------------------------------------------
class GoUserExpression : public UserExpression {
public:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 262a7914d249..86744520ad63 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -258,8 +258,8 @@ static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo &reg_info) {
reg_info.name = "f7";
break;
- // Intel wireless MMX general purpose registers 0 - 7
- // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7)
+ // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
+ // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
case dwarf_wCGR0:
reg_info.name = "wCGR0/ACC0";
break;
@@ -901,7 +901,8 @@ uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
}
// Push Multiple Registers stores multiple registers to the stack, storing to
-// consecutive memory locations ending just below the address in SP, and updates
+// consecutive memory locations ending just below the address in SP, and
+// updates
// SP to point to the start of the stored data.
bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -1390,8 +1391,8 @@ bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
uint32_t imm32; // the immediate value to be written to Rd
uint32_t carry =
0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
- // for setflags == false, this value is a don't care
- // initialized to 0 to silence the static analyzer
+ // for setflags == false, this value is a don't care initialized to
+ // 0 to silence the static analyzer
bool setflags;
switch (encoding) {
case eEncodingT1:
@@ -1473,12 +1474,11 @@ bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
// MUL multiplies two register values. The least significant 32 bits of the
// result are written to the destination
// register. These 32 bits do not depend on whether the source register values
-// are considered to be signed values or
-// unsigned values.
+// are considered to be signed values or unsigned values.
//
// Optionally, it can update the condition flags based on the result. In the
-// Thumb instruction set, this option is
-// limited to only a few forms of the instruction.
+// Thumb instruction set, this option is limited to only a few forms of the
+// instruction.
bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -1606,8 +1606,8 @@ bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
}
// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
-// the destination register.
-// It can optionally update the condition flags based on the value.
+// the destination register. It can optionally update the condition flags based
+// on the value.
bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -1666,8 +1666,8 @@ bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
}
// Bitwise NOT (register) writes the bitwise inverse of a register value to the
-// destination register.
-// It can optionally update the condition flags based on the result.
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2005,9 +2005,9 @@ bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
return true;
}
-// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
-// at a PC-relative address, and changes instruction set from ARM to Thumb, or
-// from Thumb to ARM.
+// Branch with Link and Exchange Instruction Sets (immediate) calls a
+// subroutine at a PC-relative address, and changes instruction set from ARM to
+// Thumb, or from Thumb to ARM.
// BLX (immediate)
bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -2110,8 +2110,8 @@ bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
return true;
}
-// Branch with Link and Exchange (register) calls a subroutine at an address and
-// instruction set specified by a register.
+// Branch with Link and Exchange (register) calls a subroutine at an address
+// and instruction set specified by a register.
// BLX (register)
bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -2220,9 +2220,8 @@ bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
}
// Branch and Exchange Jazelle attempts to change to Jazelle state. If the
-// attempt fails, it branches to an
-// address and instruction set specified by a register as though it were a BX
-// instruction.
+// attempt fails, it branches to an address and instruction set specified by a
+// register as though it were a BX instruction.
//
// TODO: Emulate Jazelle architecture?
// We currently assume that switching to Jazelle state fails, thus
@@ -2561,8 +2560,8 @@ bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
return true;
}
-// Vector Push stores multiple extension registers to the stack.
-// It also updates SP to point to the start of the stored data.
+// Vector Push stores multiple extension registers to the stack. It also
+// updates SP to point to the start of the stored data.
bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2577,7 +2576,8 @@ bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
MemA[address,4] = S[d+r]; address = address+4;
else
for r = 0 to regs-1
- // Store as two word-aligned words in the correct order for current endianness.
+ // Store as two word-aligned words in the correct order for
+ // current endianness.
MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
address = address+8;
@@ -2653,8 +2653,8 @@ bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
return true;
}
-// Vector Pop loads multiple extension registers from the stack.
-// It also updates SP to point just above the loaded data.
+// Vector Pop loads multiple extension registers from the stack. It also
+// updates SP to point just above the loaded data.
bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2670,7 +2670,8 @@ bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
else
for r = 0 to regs-1
word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
- // Combine the word-aligned words in the correct order for current endianness.
+ // Combine the word-aligned words in the correct order for
+ // current endianness.
D[d+r] = if BigEndian() then word1:word2 else word2:word1;
}
#endif
@@ -2892,10 +2893,8 @@ bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
}
// Compare and Branch on Nonzero and Compare and Branch on Zero compare the
-// value in a register with
-// zero and conditionally branch forward a constant value. They do not affect
-// the condition flags.
-// CBNZ, CBZ
+// value in a register with zero and conditionally branch forward a constant
+// value. They do not affect the condition flags. CBNZ, CBZ
bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2938,8 +2937,8 @@ bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
return true;
}
-// Table Branch Byte causes a PC-relative forward branch using a table of single
-// byte offsets.
+// Table Branch Byte causes a PC-relative forward branch using a table of
+// single byte offsets.
// A base register provides a pointer to the table, and a second register
// supplies an index into the table.
// The branch length is twice the value of the byte returned from the table.
@@ -2948,8 +2947,8 @@ bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
// single halfword offsets.
// A base register provides a pointer to the table, and a second register
// supplies an index into the table.
-// The branch length is twice the value of the halfword returned from the table.
-// TBB, TBH
+// The branch length is twice the value of the halfword returned from the
+// table. TBB, TBH
bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2984,9 +2983,8 @@ bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
return false;
}
- // Read the address of the table from the operand register Rn.
- // The PC can be used, in which case the table immediately follows this
- // instruction.
+ // Read the address of the table from the operand register Rn. The PC can
+ // be used, in which case the table immediately follows this instruction.
uint32_t base = ReadCoreReg(Rn, &success);
if (!success)
return false;
@@ -3023,8 +3021,8 @@ bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
}
// This instruction adds an immediate value to a register value, and writes the
-// result to the destination register.
-// It can optionally update the condition flags based on the result.
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3145,8 +3143,8 @@ bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
}
// This instruction adds an immediate value to a register value, and writes the
-// result to the destination
-// register. It can optionally update the condition flags based on the result.
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3210,9 +3208,8 @@ bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
}
// This instruction adds a register value and an optionally-shifted register
-// value, and writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// value, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3350,8 +3347,8 @@ bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
}
// Compare Negative (register) adds a register value and an optionally-shifted
-// register value.
-// It updates the condition flags based on the result, and discards the result.
+// register value. It updates the condition flags based on the result, and
+// discards the result.
bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3419,8 +3416,8 @@ bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
return true;
}
-// Compare (immediate) subtracts an immediate value from a register value.
-// It updates the condition flags based on the result, and discards the result.
+// Compare (immediate) subtracts an immediate value from a register value. It
+// updates the condition flags based on the result, and discards the result.
bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3473,8 +3470,8 @@ bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
}
// Compare (register) subtracts an optionally-shifted register value from a
-// register value.
-// It updates the condition flags based on the result, and discards the result.
+// register value. It updates the condition flags based on the result, and
+// discards the result.
bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3552,10 +3549,9 @@ bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
}
// Arithmetic Shift Right (immediate) shifts a register value right by an
-// immediate number of bits,
-// shifting in copies of its sign bit, and writes the result to the destination
-// register. It can
-// optionally update the condition flags based on the result.
+// immediate number of bits, shifting in copies of its sign bit, and writes the
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3577,13 +3573,11 @@ bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
return EmulateShiftImm(opcode, encoding, SRType_ASR);
}
-// Arithmetic Shift Right (register) shifts a register value right by a variable
-// number of bits,
-// shifting in copies of its sign bit, and writes the result to the destination
-// register.
-// The variable number of bits is read from the bottom byte of a register. It
-// can optionally update
-// the condition flags based on the result.
+// Arithmetic Shift Right (register) shifts a register value right by a
+// variable number of bits, shifting in copies of its sign bit, and writes the
+// result to the destination register. The variable number of bits is read from
+// the bottom byte of a register. It can optionally update the condition flags
+// based on the result.
bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3604,10 +3598,8 @@ bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
}
// Logical Shift Left (immediate) shifts a register value left by an immediate
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. It can
-// optionally
-// update the condition flags based on the result.
+// number of bits, shifting in zeros, and writes the result to the destination
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3630,12 +3622,9 @@ bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
}
// Logical Shift Left (register) shifts a register value left by a variable
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. The
-// variable number
-// of bits is read from the bottom byte of a register. It can optionally update
-// the condition
-// flags based on the result.
+// number of bits, shifting in zeros, and writes the result to the destination
+// register. The variable number of bits is read from the bottom byte of a
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3655,11 +3644,10 @@ bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
return EmulateShiftReg(opcode, encoding, SRType_LSL);
}
-// Logical Shift Right (immediate) shifts a register value right by an immediate
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. It can
-// optionally
-// update the condition flags based on the result.
+// Logical Shift Right (immediate) shifts a register value right by an
+// immediate number of bits, shifting in zeros, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3682,12 +3670,9 @@ bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
}
// Logical Shift Right (register) shifts a register value right by a variable
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. The
-// variable number
-// of bits is read from the bottom byte of a register. It can optionally update
-// the condition
-// flags based on the result.
+// number of bits, shifting in zeros, and writes the result to the destination
+// register. The variable number of bits is read from the bottom byte of a
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3708,10 +3693,9 @@ bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
}
// Rotate Right (immediate) provides the value of the contents of a register
-// rotated by a constant value.
-// The bits that are rotated off the right end are inserted into the vacated bit
-// positions on the left.
-// It can optionally update the condition flags based on the result.
+// rotated by a constant value. The bits that are rotated off the right end are
+// inserted into the vacated bit positions on the left. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3734,12 +3718,10 @@ bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
}
// Rotate Right (register) provides the value of the contents of a register
-// rotated by a variable number of bits.
-// The bits that are rotated off the right end are inserted into the vacated bit
-// positions on the left.
-// The variable number of bits is read from the bottom byte of a register. It
-// can optionally update the condition
-// flags based on the result.
+// rotated by a variable number of bits. The bits that are rotated off the
+// right end are inserted into the vacated bit positions on the left. The
+// variable number of bits is read from the bottom byte of a register. It can
+// optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3760,8 +3742,7 @@ bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
}
// Rotate Right with Extend provides the value of the contents of a register
-// shifted right by one place,
-// with the carry flag shifted into bit [31].
+// shifted right by one place, with the carry flag shifted into bit [31].
//
// RRX can optionally update the condition flags based on the result.
// In that case, bit [0] is shifted into the carry flag.
@@ -3808,10 +3789,9 @@ bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
// A8.6.139 ROR (immediate) -- Encoding T1
ARMEncoding use_encoding = encoding;
if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
- // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding
- // to
- // have the same decoding of bit fields as the other Thumb2 shift
- // operations.
+ // Morph the T1 encoding from the ARM Architecture Manual into T2
+ // encoding to have the same decoding of bit fields as the other Thumb2
+ // shift operations.
use_encoding = eEncodingT2;
}
@@ -3950,8 +3930,7 @@ bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
// LDM loads multiple registers from consecutive memory locations, using an
// address from a base register. Optionally the address just above the highest
-// of those locations
-// can be written back to the base register.
+// of those locations can be written back to the base register.
bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4093,8 +4072,8 @@ bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
// LDMDA loads multiple registers from consecutive memory locations using an
// address from a base register.
// The consecutive memory locations end at this address and the address just
-// below the lowest of those locations
-// can optionally be written back to the base register.
+// below the lowest of those locations can optionally be written back to the
+// base register.
bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4210,8 +4189,8 @@ bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
// LDMDB loads multiple registers from consecutive memory locations using an
// address from a base register. The
// consecutive memory locations end just below this address, and the address of
-// the lowest of those locations can
-// be optionally written back to the base register.
+// the lowest of those locations can be optionally written back to the base
+// register.
bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4349,8 +4328,8 @@ bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
// LDMIB loads multiple registers from consecutive memory locations using an
// address from a base register. The
// consecutive memory locations start just above this address, and thea ddress
-// of the last of those locations can
-// optinoally be written back to the base register.
+// of the last of those locations can optinoally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4461,8 +4440,7 @@ bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
}
// Load Register (immediate) calculates an address from a base register value
-// and
-// an immediate offset, loads a word from memory, and writes to a register.
+// and an immediate offset, loads a word from memory, and writes to a register.
// LDR (immediate, Thumb)
bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -4625,8 +4603,8 @@ bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
// STM (Store Multiple Increment After) stores multiple registers to consecutive
// memory locations using an address
// from a base register. The consecutive memory locations start at this
-// address, and the address just above the last
-// of those locations can optionally be written back to the base register.
+// address, and the address just above the last of those locations can
+// optionally be written back to the base register.
bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4775,10 +4753,10 @@ bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
}
// STMDA (Store Multiple Decrement After) stores multiple registers to
-// consecutive memory locations using an address
-// from a base register. The consecutive memory locations end at this address,
-// and the address just below the lowest
-// of those locations can optionally be written back to the base register.
+// consecutive memory locations using an address from a base register. The
+// consecutive memory locations end at this address, and the address just below
+// the lowest of those locations can optionally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4897,10 +4875,10 @@ bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
}
// STMDB (Store Multiple Decrement Before) stores multiple registers to
-// consecutive memory locations using an address
-// from a base register. The consecutive memory locations end just below this
-// address, and the address of the first of
-// those locations can optionally be written back to the base register.
+// consecutive memory locations using an address from a base register. The
+// consecutive memory locations end just below this address, and the address of
+// the first of those locations can optionally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5046,10 +5024,10 @@ bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
}
// STMIB (Store Multiple Increment Before) stores multiple registers to
-// consecutive memory locations using an address
-// from a base register. The consecutive memory locations start just above this
-// address, and the address of the last
-// of those locations can optionally be written back to the base register.
+// consecutive memory locations using an address from a base register. The
+// consecutive memory locations start just above this address, and the address
+// of the last of those locations can optionally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5337,8 +5315,8 @@ bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
// STR (Store Register) calculates an address from a base register value and an
// offset register value, stores a
-// word from a register to memory. The offset register value can optionally be
-// shifted.
+// word from a register to memory. The offset register value can optionally
+// be shifted.
bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5423,7 +5401,7 @@ bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -5664,8 +5642,8 @@ bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
// STRH (register) calculates an address from a base register value and an
// offset register value, and stores a
-// halfword from a register to memory. The offset register value can be shifted
-// left by 0, 1, 2, or 3 bits.
+// halfword from a register to memory. The offset register value can be
+// shifted left by 0, 1, 2, or 3 bits.
bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5745,7 +5723,7 @@ bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -5842,10 +5820,8 @@ bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
}
// Add with Carry (immediate) adds an immediate value and the carry flag value
-// to a register value,
-// and writes the result to the destination register. It can optionally update
-// the condition flags
-// based on the result.
+// to a register value, and writes the result to the destination register. It
+// can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5911,11 +5887,10 @@ bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
return true;
}
-// Add with Carry (register) adds a register value, the carry flag value, and an
-// optionally-shifted
-// register value, and writes the result to the destination register. It can
-// optionally update the
-// condition flags based on the result.
+// Add with Carry (register) adds a register value, the carry flag value, and
+// an optionally-shifted register value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5999,9 +5974,8 @@ bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
return true;
}
-// This instruction adds an immediate value to the PC value to form a
-// PC-relative address,
-// and writes the result to the destination register.
+// This instruction adds an immediate value to the PC value to form a PC-
+// relative address, and writes the result to the destination register.
bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6063,9 +6037,8 @@ bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
}
// This instruction performs a bitwise AND of a register value and an immediate
-// value, and writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// value, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6139,10 +6112,8 @@ bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
}
// This instruction performs a bitwise AND of a register value and an
-// optionally-shifted register value,
-// and writes the result to the destination register. It can optionally update
-// the condition flags
-// based on the result.
+// optionally-shifted register value, and writes the result to the destination
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6230,10 +6201,9 @@ bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
}
// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
-// the complement of an
-// immediate value, and writes the result to the destination register. It can
-// optionally update the
-// condition flags based on the result.
+// the complement of an immediate value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6306,10 +6276,9 @@ bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
}
// Bitwise Bit Clear (register) performs a bitwise AND of a register value and
-// the complement of an
-// optionally-shifted register value, and writes the result to the destination
-// register.
-// It can optionally update the condition flags based on the result.
+// the complement of an optionally-shifted register value, and writes the
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6439,7 +6408,7 @@ bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
imm32 = Bits32(opcode, 11, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -6624,7 +6593,7 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -6661,8 +6630,8 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
addr_t offset_addr;
addr_t address;
- // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an
- // application level alias for the CPSR".
+ // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
+ // an application level alias for the CPSR".
addr_t offset =
Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
if (!success)
@@ -6968,9 +6937,8 @@ bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
}
// LDRB (register) calculates an address from a base register value and an
-// offset rigister value, loads a byte from
-// memory, zero-extends it to form a 32-bit word, and writes it to a register.
-// The offset register value can
+// offset rigister value, loads a byte from memory, zero-extends it to form a
+// 32-bit word, and writes it to a register. The offset register value can
// optionally be shifted.
bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -7049,7 +7017,7 @@ bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7132,9 +7100,8 @@ bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
// LDRH (immediate, Thumb) calculates an address from a base register value and
// an immediate offset, loads a
-// halfword from memory, zero-extends it to form a 32-bit word, and writes it to
-// a register. It can use offset,
-// post-indexed, or pre-indexed addressing.
+// halfword from memory, zero-extends it to form a 32-bit word, and writes it
+// to a register. It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7384,8 +7351,8 @@ bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
// LDRH (literal) calculates an address from a base register value and an offset
// register value, loads a halfword
// from memory, zero-extends it to form a 32-bit word, and writes it to a
-// register. The offset register value can
-// be shifted left by 0, 1, 2, or 3 bits.
+// register. The offset register value can be shifted left by 0, 1, 2, or 3
+// bits.
bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7464,7 +7431,7 @@ bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7561,8 +7528,7 @@ bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
// LDRSB (immediate) calculates an address from a base register value and an
// immediate offset, loads a byte from
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
-// It can use offset, post-indexed,
-// or pre-indexed addressing.
+// It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7643,7 +7609,7 @@ bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
uint32_t imm4L = Bits32(opcode, 3, 0);
imm32 = (imm4H << 4) | imm4L;
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7799,8 +7765,7 @@ bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
// LDRSB (register) calculates an address from a base register value and an
// offset register value, loadsa byte from
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
-// The offset register value can be
-// shifted left by 0, 1, 2, or 3 bits.
+// The offset register value can be shifted left by 0, 1, 2, or 3 bits.
bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7873,7 +7838,7 @@ bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7960,8 +7925,7 @@ bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
// LDRSH (immediate) calculates an address from a base register value and an
// immediate offset, loads a halfword from
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
-// It can use offset, post-indexed, or
-// pre-indexed addressing.
+// It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -8043,7 +8007,7 @@ bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
uint32_t imm4L = Bits32(opcode, 3, 0);
imm32 = (imm4H << 4) | imm4L;
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -8220,8 +8184,8 @@ bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
// LDRSH (register) calculates an address from a base register value and an
// offset register value, loads a halfword
// from memory, sign-extends it to form a 32-bit word, and writes it to a
-// register. The offset register value can be
-// shifted left by 0, 1, 2, or 3 bits.
+// register. The offset register value can be shifted left by 0, 1, 2, or 3
+// bits.
bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -8301,7 +8265,7 @@ bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -8879,9 +8843,8 @@ bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
}
// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
-// register value and an immediate value,
-// and writes the result to the destination register. It can optionally update
-// the condition flags based on
+// register value and an immediate value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
// the result.
bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -8957,11 +8920,10 @@ bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
return true;
}
-// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register
-// value and an
-// optionally-shifted register value, and writes the result to the destination
-// register.
-// It can optionally update the condition flags based on the result.
+// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
+// register value and an optionally-shifted register value, and writes the
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9051,10 +9013,8 @@ bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
}
// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
-// and an immediate value, and
-// writes the result to the destination register. It can optionally update the
-// condition flags based
-// on the result.
+// and an immediate value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9128,10 +9088,9 @@ bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
}
// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
-// and an optionally-shifted register
-// value, and writes the result to the destination register. It can optionally
-// update the condition flags based
-// on the result.
+// and an optionally-shifted register value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9219,9 +9178,8 @@ bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
}
// Reverse Subtract (immediate) subtracts a register value from an immediate
-// value, and writes the result to
-// the destination register. It can optionally update the condition flags based
-// on the result.
+// value, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9294,10 +9252,9 @@ bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
return true;
}
-// Reverse Subtract (register) subtracts a register value from an
-// optionally-shifted register value, and writes the
-// result to the destination register. It can optionally update the condition
-// flags based on the result.
+// Reverse Subtract (register) subtracts a register value from an optionally-
+// shifted register value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9377,10 +9334,9 @@ bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
}
// Reverse Subtract with Carry (immediate) subtracts a register value and the
-// value of NOT (Carry flag) from
-// an immediate value, and writes the result to the destination register. It can
-// optionally update the condition
-// flags based on the result.
+// value of NOT (Carry flag) from an immediate value, and writes the result to
+// the destination register. It can optionally update the condition flags based
+// on the result.
bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9440,9 +9396,8 @@ bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
}
// Reverse Subtract with Carry (register) subtracts a register value and the
-// value of NOT (Carry flag) from an
-// optionally-shifted register value, and writes the result to the destination
-// register. It can optionally update the
+// value of NOT (Carry flag) from an optionally-shifted register value, and
+// writes the result to the destination register. It can optionally update the
// condition flags based on the result.
bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -9512,7 +9467,8 @@ bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
return true;
}
-// Subtract with Carry (immediate) subtracts an immediate value and the value of
+// Subtract with Carry (immediate) subtracts an immediate value and the value
+// of
// NOT (Carry flag) from a register value, and writes the result to the
// destination register.
// It can optionally update the condition flags based on the result.
@@ -9582,8 +9538,8 @@ bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
return true;
}
-// Subtract with Carry (register) subtracts an optionally-shifted register value
-// and the value of
+// Subtract with Carry (register) subtracts an optionally-shifted register
+// value and the value of
// NOT (Carry flag) from a register value, and writes the result to the
// destination register.
// It can optionally update the condition flags based on the result.
@@ -9672,9 +9628,8 @@ bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
}
// This instruction subtracts an immediate value from a register value, and
-// writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// writes the result to the destination register. It can optionally update the
+// condition flags based on the result.
bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9766,9 +9721,8 @@ bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
}
// This instruction subtracts an immediate value from a register value, and
-// writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// writes the result to the destination register. It can optionally update the
+// condition flags based on the result.
bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9844,9 +9798,8 @@ bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
}
// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
-// register value and an
-// immediate value. It updates the condition flags based on the result, and
-// discards the result.
+// register value and an immediate value. It updates the condition flags based
+// on the result, and discards the result.
bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9904,10 +9857,8 @@ bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
}
// Test Equivalence (register) performs a bitwise exclusive OR operation on a
-// register value and an
-// optionally-shifted register value. It updates the condition flags based on
-// the result, and discards
-// the result.
+// register value and an optionally-shifted register value. It updates the
+// condition flags based on the result, and discards the result.
bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9972,8 +9923,8 @@ bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
}
// Test (immediate) performs a bitwise AND operation on a register value and an
-// immediate value.
-// It updates the condition flags based on the result, and discards the result.
+// immediate value. It updates the condition flags based on the result, and
+// discards the result.
bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10031,8 +9982,8 @@ bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
}
// Test (register) performs a bitwise AND operation on a register value and an
-// optionally-shifted register value.
-// It updates the condition flags based on the result, and discards the result.
+// optionally-shifted register value. It updates the condition flags based on
+// the result, and discards the result.
bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10403,9 +10354,8 @@ bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
- // if d == 15 then // Can only occur for ARM encoding
- // ALUWritePC(result); // setflags is always FALSE here
- // else
+ // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
+ // // setflags is always FALSE here else
// R[d] = result;
// if setflags then
// APSR.N = result<31>;
@@ -10429,10 +10379,9 @@ bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
}
// A8.6.202 STREX
-// Store Register Exclusive calculates an address from a base register value and
-// an immediate offset, and stores a
-// word from a register to memory if the executing processor has exclusive
-// access to the memory addressed.
+// Store Register Exclusive calculates an address from a base register value
+// and an immediate offset, and stores a word from a register to memory if the
+// executing processor has exclusive access to the memory addressed.
bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10457,7 +10406,8 @@ bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
switch (encoding) {
case eEncodingT1:
- // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00',
+ // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
+ // ZeroExtend(imm8:'00',
// 32);
d = Bits32(opcode, 11, 8);
t = Bits32(opcode, 15, 12);
@@ -10511,9 +10461,9 @@ bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
context.type = eContextRegisterStore;
context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
- // if ExclusiveMonitorsPass(address,4) then
- // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the
- // sake of emulation, we will say this
+ // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
+ // (address, addr_byte_size)) -- For now, for the sake of emulation, we
+ // will say this
// always return
// true.
if (true) {
@@ -10742,9 +10692,9 @@ bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
// A8.6.66 LDRD (immediate)
// Load Register Dual (immediate) calculates an address from a base register
-// value and an immediate offset, loads two
-// words from memory, and writes them to two registers. It can use offset,
-// post-indexed, or pre-indexed addressing.
+// value and an immediate offset, loads two words from memory, and writes them
+// to two registers. It can use offset, post-indexed, or pre-indexed
+// addressing.
bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10891,9 +10841,8 @@ bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
// A8.6.68 LDRD (register)
// Load Register Dual (register) calculates an address from a base register
-// value and a register offset, loads two
-// words from memory, and writes them to two registers. It can use offset,
-// post-indexed or pre-indexed addressing.
+// value and a register offset, loads two words from memory, and writes them to
+// two registers. It can use offset, post-indexed or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -11021,9 +10970,8 @@ bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
// A8.6.200 STRD (immediate)
// Store Register Dual (immediate) calculates an address from a base register
-// value and an immediate offset, and
-// stores two words from two registers to memory. It can use offset,
-// post-indexed, or pre-indexed addressing.
+// value and an immediate offset, and stores two words from two registers to
+// memory. It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -11314,8 +11262,7 @@ bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
// A8.6.319 VLDM
// Vector Load Multiple loads multiple extension registers from consecutive
-// memory locations using an address from
-// an ARM core register.
+// memory locations using an address from an ARM core register.
bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -11328,7 +11275,8 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
S[d+r] = MemA[address,4]; address = address+4;
else
word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
- // Combine the word-aligned words in the correct order for current endianness.
+ // Combine the word-aligned words in the correct order for
+ // current endianness.
D[d+r] = if BigEndian() then word1:word2 else word2:word1;
#endif
@@ -11389,8 +11337,8 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
- // !), 101 (DB with !)
- // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d =
+ // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
+ // == '1'); d =
// UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet(opcode, 23);
@@ -11519,7 +11467,8 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
if single_regs then
MemA[address,4] = S[d+r]; address = address+4;
else
- // Store as two word-aligned words in the correct order for current endianness.
+ // Store as two word-aligned words in the correct order for
+ // current endianness.
MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
address = address+8;
@@ -11582,8 +11531,8 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
- // !), 101 (DB with !)
- // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d =
+ // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
+ // == '1'); d =
// UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet(opcode, 23);
@@ -11665,8 +11614,7 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
address = address + 4;
} else {
// // Store as two word-aligned words in the correct order for current
- // endianness.
- // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
+ // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
// D[d+r]<31:0>;
// MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
// D[d+r]<63:32>;
@@ -11712,8 +11660,7 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
// A8.6.320
// This instruction loads a single extension register from memory, using an
-// address from an ARM core register, with
-// an optional offset.
+// address from an ARM core register, with an optional offset.
bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -11725,7 +11672,8 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
S[d] = MemA[address,4];
else
word1 = MemA[address,4]; word2 = MemA[address+4,4];
- // Combine the word-aligned words in the correct order for current endianness.
+ // Combine the word-aligned words in the correct order for current
+ // endianness.
D[d] = if BigEndian() then word1:word2 else word2:word1;
#endif
@@ -11839,8 +11787,7 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
// A8.6.400 VSTR
// This instruction stores a signle extension register to memory, using an
-// address from an ARM core register, with an
-// optional offset.
+// address from an ARM core register, with an optional offset.
bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -11850,7 +11797,8 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
if single_reg then
MemA[address,4] = S[d];
else
- // Store as two word-aligned words in the correct order for current endianness.
+ // Store as two word-aligned words in the correct order for current
+ // endianness.
MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
#endif
@@ -11970,10 +11918,9 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
return true;
}
-// A8.6.307 VLDI1 (multiple single elements)
-// This instruction loads elements from memory into one, two, three or four
-// registers, without de-interleaving. Every
-// element of each register is loaded.
+// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
+// from memory into one, two, three or four registers, without de-interleaving.
+// Every element of each register is loaded.
bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -12291,8 +12238,7 @@ bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
if (index > 0)
mask = mask | Bits64(all_ones, (index * esize) - 1,
0); // add 1's to the right of where 'element' goes.
- // now mask should be 0's where element goes & 1's
- // everywhere else.
+ // now mask should be 0's where element goes & 1's everywhere else.
uint64_t masked_reg =
reg_data & mask; // Take original reg value & zero out 'element' bits
@@ -12307,10 +12253,9 @@ bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
return true;
}
-// A8.6.391 VST1 (multiple single elements)
-// Vector Store (multiple single elements) stores elements to memory from one,
-// two, three, or four registers, without
-// interleaving. Every element of each register is stored.
+// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
+// elements) stores elements to memory from one, two, three, or four registers,
+// without interleaving. Every element of each register is stored.
bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -12465,8 +12410,8 @@ bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
return true;
}
-// A8.6.392 VST1 (single element from one lane)
-// This instruction stores one element to memory from one element of a register.
+// A8.6.392 VST1 (single element from one lane) This instruction stores one
+// element to memory from one element of a register.
bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -12624,9 +12569,8 @@ bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
return true;
}
-// A8.6.309 VLD1 (single element to all lanes)
-// This instruction loads one element from memory into every element of one or
-// two vectors.
+// A8.6.309 VLD1 (single element to all lanes) This instruction loads one
+// element from memory into every element of one or two vectors.
bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -12754,11 +12698,10 @@ bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
return true;
}
-// B6.2.13 SUBS PC, LR and related instructions
-// The SUBS PC, LR, #<const? instruction provides an exception return without
-// the use of the stack. It subtracts the
-// immediate constant from the LR, branches to the resulting address, and also
-// copies the SPSR to the CPSR.
+// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
+// instruction provides an exception return without the use of the stack. It
+// subtracts the immediate constant from the LR, branches to the resulting
+// address, and also copies the SPSR to the CPSR.
bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -12797,9 +12740,9 @@ bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
switch (encoding) {
case eEncodingT1:
- // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
- // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode =
- // '0010'; // = SUB
+ // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
+ // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
+ // // = SUB
n = 14;
imm32 = Bits32(opcode, 7, 0);
register_form = false;
@@ -12924,8 +12867,7 @@ bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
// CPSRWriteByInstr(SPSR[], '1111', TRUE);
// For now, in emulation mode, we don't have access to the SPSR, so we will
- // use the CPSR instead, and hope for
- // the best.
+ // use the CPSR instead, and hope for the best.
uint32_t spsr =
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
if (!success)
@@ -13946,10 +13888,10 @@ bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
else {
AddressClass addr_class = inst_addr.GetAddressClass();
- if ((addr_class == eAddressClassCode) ||
- (addr_class == eAddressClassUnknown))
+ if ((addr_class == AddressClass::eCode) ||
+ (addr_class == AddressClass::eUnknown))
m_opcode_mode = eModeARM;
- else if (addr_class == eAddressClassCodeAlternateISA)
+ else if (addr_class == AddressClass::eCodeAlternateISA)
m_opcode_mode = eModeThumb;
else
return false;
@@ -13999,8 +13941,7 @@ bool EmulateInstructionARM::ReadInstruction() {
if (!m_ignore_conditions) {
// If we are not ignoreing the conditions then init the it session from
- // the current
- // value of cpsr.
+ // the current value of cpsr.
uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
Bits32(m_opcode_cpsr, 26, 25);
if (it != 0)
@@ -14018,10 +13959,9 @@ bool EmulateInstructionARM::ReadInstruction() {
uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
- // If we are ignoring conditions, then always return true.
- // this allows us to iterate over disassembly code and still
- // emulate an instruction even if we don't have all the right
- // bits set in the CPSR register...
+ // If we are ignoring conditions, then always return true. this allows us to
+ // iterate over disassembly code and still emulate an instruction even if we
+ // don't have all the right bits set in the CPSR register...
if (m_ignore_conditions)
return true;
@@ -14225,8 +14165,8 @@ bool EmulateInstructionARM::BranchWritePC(const Context &context,
bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
addr_t target;
// If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
- // we want to record it and issue a WriteRegister callback so the clients
- // can track the mode changes accordingly.
+ // we want to record it and issue a WriteRegister callback so the clients can
+ // track the mode changes accordingly.
bool cpsr_changed = false;
if (BitIsSet(addr, 0)) {
@@ -14307,9 +14247,10 @@ bool EmulateInstructionARM::UnalignedSupport() {
return (ArchVersion() >= ARMv7);
}
-// The main addition and subtraction instructions can produce status information
-// about both unsigned carry and signed overflow conditions. This status
-// information can be used to synthesize multi-word additions and subtractions.
+// The main addition and subtraction instructions can produce status
+// information about both unsigned carry and signed overflow conditions. This
+// status information can be used to synthesize multi-word additions and
+// subtractions.
EmulateInstructionARM::AddWithCarryResult
EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
uint32_t result;
@@ -14364,9 +14305,8 @@ uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
// When executing an ARM instruction , PC reads as the address of the current
- // instruction plus 8.
- // When executing a Thumb instruction , PC reads as the address of the current
- // instruction plus 4.
+ // instruction plus 8. When executing a Thumb instruction , PC reads as the
+ // address of the current instruction plus 4.
if (num == 15) {
if (CurrentInstrSet() == eModeARM)
val += 8;
@@ -14434,8 +14374,7 @@ bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
// APSR.V = overflow
//
// Default arguments can be specified for carry and overflow parameters, which
-// means
-// not to update the respective flags.
+// means not to update the respective flags.
bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
const uint32_t carry,
const uint32_t overflow) {
@@ -14496,8 +14435,7 @@ bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
}
// Advance the ITSTATE bits to their values for the next instruction if we
- // haven't just executed
- // an IT instruction what initialized it.
+ // haven't just executed an IT instruction what initialized it.
if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
(opcode_data == nullptr ||
opcode_data->callback != &EmulateInstructionARM::EmulateIT))
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
index d2832656d906..2f484ab5ea97 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -506,8 +506,8 @@ bool EmulateInstructionARM64::UsingAArch32() {
bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,
addr_t target) {
#if 0
- // Set program counter to a new address, with a branch reason hint
- // for possible use by hardware fetching the next instruction.
+ // Set program counter to a new address, with a branch reason hint for
+ // possible use by hardware fetching the next instruction.
BranchTo(bits(N) target, BranchType branch_type)
Hint_Branch(branch_type);
if N == 32 then
@@ -555,10 +555,9 @@ bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,
}
bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) {
- // If we are ignoring conditions, then always return true.
- // this allows us to iterate over disassembly code and still
- // emulate an instruction even if we don't have all the right
- // bits set in the CPSR register...
+ // If we are ignoring conditions, then always return true. this allows us to
+ // iterate over disassembly code and still emulate an instruction even if we
+ // don't have all the right bits set in the CPSR register...
if (m_ignore_conditions)
return true;
@@ -690,8 +689,8 @@ bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) {
context.SetRegisterPlusOffset(reg_info_Rn, imm);
if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) {
- // 'mov sp, fp' - common epilogue instruction, CFA is now in terms
- // of the stack pointer, instead of frame pointer.
+ // 'mov sp, fp' - common epilogue instruction, CFA is now in terms of the
+ // stack pointer, instead of frame pointer.
context.type = EmulateInstruction::eContextRestoreStackPointer;
} else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) &&
d == gpr_sp_arm64 && !setflags) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index db3d8fc1b8ca..b65747e12890 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -1015,7 +1015,7 @@ bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
m_use_alt_disaasm = false;
if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
- if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA) {
+ if (inst_addr.GetAddressClass() == AddressClass::eCodeAlternateISA) {
Status error;
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
@@ -1044,7 +1044,7 @@ bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
return true;
} else {
/*
- * If the address class is not eAddressClassCodeAlternateISA then
+ * If the address class is not AddressClass::eCodeAlternateISA then
* the function is not microMIPS. In this case instruction size is
* always 4 bytes.
*/
@@ -1205,13 +1205,10 @@ bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {
dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
- // If immediate value is greater then 2^16 - 1 then clang generate
- // LUI, ADDIU, SUBU instructions in prolog.
- // Example
- // lui $1, 0x2
- // addiu $1, $1, -0x5920
- // subu $sp, $sp, $1
- // In this case, ADDIU dst and src will be same and not equal to sp
+ // If immediate value is greater then 2^16 - 1 then clang generate LUI,
+ // ADDIU, SUBU instructions in prolog. Example lui $1, 0x2 addiu $1, $1,
+ // -0x5920 subu $sp, $sp, $1 In this case, ADDIU dst and src will be same
+ // and not equal to sp
if (dst == src) {
Context context;
@@ -1545,8 +1542,8 @@ bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {
address = address + imm5;
// We use bad_vaddr_context to store base address which is used by H/W
- // watchpoint
- // Set the bad_vaddr register with base address used in the instruction
+ // watchpoint Set the bad_vaddr register with base address used in the
+ // instruction
bad_vaddr_context.type = eContextInvalid;
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
address);
@@ -1682,8 +1679,8 @@ bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
base_address = base_address + imm5;
// We use bad_vaddr_context to store base address which is used by H/W
- // watchpoint
- // Set the bad_vaddr register with base address used in the instruction
+ // watchpoint Set the bad_vaddr register with base address used in the
+ // instruction
bad_vaddr_context.type = eContextInvalid;
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
base_address);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index d298589afdd9..5af12ad141aa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -1091,13 +1091,10 @@ bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
- // If immediate is greater than 2^16 - 1 then clang generate
- // LUI, (D)ADDIU,(D)SUBU instructions in prolog.
- // Example
- // lui $1, 0x2
- // daddiu $1, $1, -0x5920
- // dsubu $sp, $sp, $1
- // In this case, (D)ADDIU dst and src will be same and not equal to sp
+ // If immediate is greater than 2^16 - 1 then clang generate LUI,
+ // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
+ // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
+ // same and not equal to sp
if (dst == src) {
Context context;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/CMakeLists.txt b/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/CMakeLists.txt
new file mode 100644
index 000000000000..0926433fc77c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginInstructionPPC64 PLUGIN
+ EmulateInstructionPPC64.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbInterpreter
+ lldbSymbol
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
new file mode 100644
index 000000000000..f3a9ca570a4a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
@@ -0,0 +1,406 @@
+//===-- EmulateInstructionPPC64.cpp ------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionPPC64.h"
+
+#include <stdlib.h>
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/ConstString.h"
+
+#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
+
+#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch)
+ : EmulateInstruction(arch) {}
+
+void EmulateInstructionPPC64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+}
+
+void EmulateInstructionPPC64::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString EmulateInstructionPPC64::GetPluginNameStatic() {
+ ConstString g_plugin_name("lldb.emulate-instruction.ppc64");
+ return g_plugin_name;
+}
+
+ConstString EmulateInstructionPPC64::GetPluginName() {
+ static ConstString g_plugin_name("EmulateInstructionPPC64");
+ return g_plugin_name;
+}
+
+const char *EmulateInstructionPPC64::GetPluginDescriptionStatic() {
+ return "Emulate instructions for the PPC64 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
+ InstructionType inst_type) {
+ if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
+ inst_type)) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64 ||
+ arch.GetTriple().getArch() == llvm::Triple::ppc64le) {
+ return new EmulateInstructionPPC64(arch);
+ }
+ }
+
+ return nullptr;
+}
+
+bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64)
+ return true;
+ else if (arch.GetTriple().getArch() == llvm::Triple::ppc64le)
+ return true;
+
+ return false;
+}
+
+static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo &reg_info) {
+ if (reg_num >= llvm::array_lengthof(g_register_infos_ppc64le))
+ return false;
+ reg_info = g_register_infos_ppc64le[reg_num];
+ return true;
+}
+
+bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
+ uint32_t reg_num,
+ RegisterInfo &reg_info) {
+ if (reg_kind == eRegisterKindGeneric) {
+ switch (reg_num) {
+ case LLDB_REGNUM_GENERIC_PC:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_pc_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_SP:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_r1_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_RA:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_lr_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_FLAGS:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_cr_ppc64le;
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindLLDB)
+ return LLDBTableGetRegisterInfo(reg_num, reg_info);
+ return false;
+}
+
+bool EmulateInstructionPPC64::ReadInstruction() {
+ bool success = false;
+ m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
+ LLDB_INVALID_ADDRESS, &success);
+ if (success) {
+ Context ctx;
+ ctx.type = eContextReadOpcode;
+ ctx.SetNoArgs();
+ m_opcode.SetOpcode32(ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success),
+ GetByteOrder());
+ }
+ if (!success)
+ m_addr = LLDB_INVALID_ADDRESS;
+ return success;
+}
+
+bool EmulateInstructionPPC64::CreateFunctionEntryUnwind(
+ UnwindPlan &unwind_plan) {
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind(eRegisterKindLLDB);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our previous Call Frame Address is the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset(gpr_r1_ppc64le, 0);
+
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName("EmulateInstructionPPC64");
+ unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le);
+ return true;
+}
+
+EmulateInstructionPPC64::Opcode *
+EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) {
+ static EmulateInstructionPPC64::Opcode g_opcodes[] = {
+ {0xfc0007ff, 0x7c0002a6, &EmulateInstructionPPC64::EmulateMFSPR,
+ "mfspr RT, SPR"},
+ {0xfc000003, 0xf8000000, &EmulateInstructionPPC64::EmulateSTD,
+ "std RS, DS(RA)"},
+ {0xfc000003, 0xf8000001, &EmulateInstructionPPC64::EmulateSTD,
+ "stdu RS, DS(RA)"},
+ {0xfc0007fe, 0x7c000378, &EmulateInstructionPPC64::EmulateOR,
+ "or RA, RS, RB"},
+ {0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI,
+ "addi RT, RA, SI"},
+ {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD,
+ "ld RT, DS(RA)"}};
+ static const size_t k_num_ppc_opcodes = llvm::array_lengthof(g_opcodes);
+
+ for (size_t i = 0; i < k_num_ppc_opcodes; ++i) {
+ if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
+ return &g_opcodes[i];
+ }
+ return nullptr;
+}
+
+bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) {
+ const uint32_t opcode = m_opcode.GetOpcode32();
+ // LLDB_LOG(log, "PPC64::EvaluateInstruction: opcode={0:X+8}", opcode);
+ Opcode *opcode_data = GetOpcodeForInstruction(opcode);
+ if (!opcode_data)
+ return false;
+
+ // LLDB_LOG(log, "PPC64::EvaluateInstruction: {0}", opcode_data->name);
+ const bool auto_advance_pc =
+ evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+
+ bool success = false;
+
+ uint32_t orig_pc_value = 0;
+ if (auto_advance_pc) {
+ orig_pc_value =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ // Call the Emulate... function.
+ success = (this->*opcode_data->callback)(opcode);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc) {
+ uint32_t new_pc_value =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc && (new_pc_value == orig_pc_value)) {
+ EmulateInstruction::Context context;
+ context.type = eContextAdvancePC;
+ context.SetNoArgs();
+ if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_ppc64le,
+ orig_pc_value + 4))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateMFSPR(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t spr = Bits32(opcode, 20, 11);
+
+ enum { SPR_LR = 0x100 };
+
+ // For now, we're only insterested in 'mfspr r0, lr'
+ if (rt != gpr_r0_ppc64le || spr != SPR_LR)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateMFSPR: {0:X+8}: mfspr r0, lr", m_addr);
+
+ bool success;
+ uint64_t lr =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ Context context;
+ context.type = eContextWriteRegisterRandomBits;
+ WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_r0_ppc64le, lr);
+ LLDB_LOG(log, "EmulateMFSPR: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t ds = Bits32(opcode, 15, 2);
+
+ int32_t ids = llvm::SignExtend32<16>(ds << 2);
+
+ // For now, tracking only loads from 0(r1) to r1 (0(r1) is the ABI defined
+ // location to save previous SP)
+ if (ra != gpr_r1_ppc64le || rt != gpr_r1_ppc64le || ids != 0)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra);
+
+ RegisterInfo r1_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
+ return false;
+
+ // restore SP
+ Context ctx;
+ ctx.type = eContextRestoreStackPointer;
+ ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
+
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
+ LLDB_LOG(log, "EmulateLD: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
+ uint32_t rs = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t ds = Bits32(opcode, 15, 2);
+ uint32_t u = Bits32(opcode, 1, 0);
+
+ // For now, tracking only stores to r1
+ if (ra != gpr_r1_ppc64le)
+ return false;
+ // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
+ if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
+ rs != gpr_r0_ppc64le)
+ return false;
+
+ bool success;
+ uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
+ if (!success)
+ return false;
+
+ int32_t ids = llvm::SignExtend32<16>(ds << 2);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
+ u ? "u" : "", rs, ids, ra);
+
+ // Make sure that r0 is really holding LR value (this won't catch unlikely
+ // cases, such as r0 being overwritten after mfspr)
+ uint32_t rs_num = rs;
+ if (rs == gpr_r0_ppc64le) {
+ uint64_t lr =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
+ if (!success || lr != rs_val)
+ return false;
+ rs_num = gpr_lr_ppc64le;
+ }
+
+ // set context
+ RegisterInfo rs_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, rs_num, rs_info))
+ return false;
+ RegisterInfo ra_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextPushRegisterOnStack;
+ ctx.SetRegisterToRegisterPlusOffset(rs_info, ra_info, ids);
+
+ // store
+ uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
+ if (!success)
+ return false;
+
+ lldb::addr_t addr = ra_val + ids;
+ WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
+
+ // update RA?
+ if (u) {
+ Context ctx;
+ // NOTE Currently, RA will always be equal to SP(r1)
+ ctx.type = eContextAdjustStackPointer;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
+ }
+
+ LLDB_LOG(log, "EmulateSTD: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
+ uint32_t rs = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t rb = Bits32(opcode, 15, 11);
+
+ // to be safe, process only the known 'mr r31/r30, r1' prologue instructions
+ if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
+ (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
+
+ // set context
+ RegisterInfo ra_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextSetFramePointer;
+ ctx.SetRegister(ra_info);
+
+ // move
+ bool success;
+ uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
+ if (!success)
+ return false;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
+ m_fp = ra;
+ LLDB_LOG(log, "EmulateOR: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t si = Bits32(opcode, 15, 0);
+
+ // handle stack adjustments only
+ // (this is a typical epilogue operation, with ra == r1. If it's
+ // something else, then we won't know the correct value of ra)
+ if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
+ return false;
+
+ int32_t si_val = llvm::SignExtend32<16>(si);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
+
+ // set context
+ RegisterInfo r1_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextRestoreStackPointer;
+ ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
+
+ // adjust SP
+ bool success;
+ uint64_t r1 =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
+ LLDB_LOG(log, "EmulateADDI: success!");
+ return true;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h b/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
new file mode 100644
index 000000000000..be65de9a5063
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
@@ -0,0 +1,97 @@
+//===-- EmulateInstructionPPC64.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionPPC64_h_
+#define EmulateInstructionPPC64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Interpreter/OptionValue.h"
+#include "lldb/Utility/Log.h"
+
+namespace lldb_private {
+
+class EmulateInstructionPPC64 : public EmulateInstruction {
+public:
+ EmulateInstructionPPC64(const ArchSpec &arch);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static EmulateInstruction *CreateInstance(const ArchSpec &arch,
+ InstructionType inst_type);
+
+ static bool
+ SupportsEmulatingInstructionsOfTypeStatic(InstructionType inst_type) {
+ switch (inst_type) {
+ case eInstructionTypeAny:
+ case eInstructionTypePrologueEpilogue:
+ return true;
+
+ case eInstructionTypePCModifying:
+ case eInstructionTypeAll:
+ return false;
+ }
+ return false;
+ }
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ bool SetTargetTriple(const ArchSpec &arch) override;
+
+ bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override {
+ return SupportsEmulatingInstructionsOfTypeStatic(inst_type);
+ }
+
+ bool ReadInstruction() override;
+
+ bool EvaluateInstruction(uint32_t evaluate_options) override;
+
+ bool TestEmulation(Stream *out_stream, ArchSpec &arch,
+ OptionValueDictionary *test_data) override {
+ return false;
+ }
+
+ bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num,
+ RegisterInfo &reg_info) override;
+
+ bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override;
+
+private:
+ struct Opcode {
+ uint32_t mask;
+ uint32_t value;
+ bool (EmulateInstructionPPC64::*callback)(uint32_t opcode);
+ const char *name;
+ };
+
+ uint32_t m_fp = LLDB_INVALID_REGNUM;
+
+ Opcode *GetOpcodeForInstruction(uint32_t opcode);
+
+ bool EmulateMFSPR(uint32_t opcode);
+ bool EmulateLD(uint32_t opcode);
+ bool EmulateSTD(uint32_t opcode);
+ bool EmulateOR(uint32_t opcode);
+ bool EmulateADDI(uint32_t opcode);
+};
+
+} // namespace lldb_private
+
+#endif // EmulateInstructionPPC64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
index eb238419ab18..32da327ee465 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
@@ -267,8 +267,8 @@ MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo(
new HistoryThread(*process_sp, tid, PCs, stop_id, stop_id_is_valid);
ThreadSP new_thread_sp(history_thread);
- // Save this in the Process' ExtendedThreadList so a strong pointer
- // retains the object
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains
+ // the object
process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
threads->AddThread(new_thread_sp);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
index cf9ba60c7b60..6ce50f5c6839 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
@@ -282,9 +282,8 @@ GetRenumberedThreadIds(ProcessSP process_sp, ValueObjectSP data,
} else {
// This isn't a live thread anymore. Ask process to assign a new
// Index ID (or return an old one if we've already seen this
- // thread_os_id).
- // It will also make sure that no new threads are assigned this Index
- // ID.
+ // thread_os_id). It will also make sure that no new threads are
+ // assigned this Index ID.
lldb_user_id = process_sp->AssignIndexIDToThread(thread_os_id);
}
@@ -574,7 +573,7 @@ static void GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr,
return;
VariableList var_list;
- module->FindGlobalVariables(sym_name, nullptr, true, 1U, var_list);
+ module->FindGlobalVariables(sym_name, nullptr, 1U, var_list);
if (var_list.GetSize() < 1)
return;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
index 28c28e41ef44..1e9280c8c064 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
@@ -334,8 +334,8 @@ UndefinedBehaviorSanitizerRuntime::GetBacktracesFromExtendedStopInfo(
std::string stop_reason_description = GetStopReasonDescription(info);
new_thread_sp->SetName(stop_reason_description.c_str());
- // Save this in the Process' ExtendedThreadList so a strong pointer
- // retains the object
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains
+ // the object
process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
threads->AddThread(new_thread_sp);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
index 5e8f051dec98..82b7ac1675fa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -147,9 +147,8 @@ public:
return child_sp;
}
- // return true if this object is now safe to use forever without
- // ever updating again; the typical (and tested) answer here is
- // 'false'
+ // return true if this object is now safe to use forever without ever
+ // updating again; the typical (and tested) answer here is 'false'
bool Update() override { return false; }
// maybe return false if the block pointer is, say, null
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 51ed88065c84..2c63e6467d4c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -120,10 +120,9 @@ static bool ReverseFindMatchingChars(const llvm::StringRef &s,
static bool IsTrivialBasename(const llvm::StringRef &basename) {
// Check that the basename matches with the following regular expression
- // "^~?([A-Za-z_][A-Za-z_0-9]*)$"
- // We are using a hand written implementation because it is significantly more
- // efficient then
- // using the general purpose regular expression library.
+ // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
+ // because it is significantly more efficient then using the general purpose
+ // regular expression library.
size_t idx = 0;
if (basename.size() > 0 && basename[0] == '~')
idx = 1;
@@ -151,10 +150,9 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
}
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
- // This method tries to parse simple method definitions
- // which are presumably most comman in user programs.
- // Definitions that can be parsed by this function don't have return types
- // and templates in the name.
+ // This method tries to parse simple method definitions which are presumably
+ // most comman in user programs. Definitions that can be parsed by this
+ // function don't have return types and templates in the name.
// A::B::C::fun(std::vector<T> &) const
size_t arg_start, arg_end;
llvm::StringRef full(m_full.GetCString());
@@ -251,13 +249,17 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
}
bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
- // FIXME, we should really run through all the known C++ Language plugins and
- // ask each one if
- // this is a C++ mangled name, but we can put that off till there is actually
- // more than one
- // we care about.
-
- return (name != nullptr && name[0] == '_' && name[1] == 'Z');
+ // FIXME!! we should really run through all the known C++ Language plugins
+ // and ask each one if this is a C++ mangled name
+
+ if (name == nullptr)
+ return false;
+
+ // MSVC style mangling
+ if (name[0] == '?')
+ return true;
+
+ return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
}
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
@@ -307,13 +309,15 @@ static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
// FastDemangle will call our hook for each instance of a primitive type,
// allowing us to perform substitution
- const char *const demangled =
+ char *const demangled =
FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
if (log)
log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
mangled.str().c_str(), demangled, output_buf.c_str(),
FastDemangle(output_buf.c_str()));
+ // FastDemangle malloc'd this string.
+ free(demangled);
return output_buf == mangled ? ConstString() : ConstString(output_buf);
}
@@ -419,18 +423,20 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
SyntheticChildren::Flags stl_synth_flags;
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
false);
+ SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
+ stl_deref_flags.SetFrontEndWantsDereference();
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
"libc++ std::bitset synthetic children",
- ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
"libc++ std::vector synthetic children",
- ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
@@ -453,13 +459,13 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
cpp_category_sp,
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
"libc++ std::set synthetic children",
- ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
"libc++ std::multiset synthetic children",
- ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
index aebea6ae3569..b32fe9588965 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
@@ -25,8 +25,8 @@ Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
m_next_token_index = 0;
Optional<ParsedFunction> result(None);
- // Try to parse the name as function without a return type specified
- // e.g. main(int, char*[])
+ // Try to parse the name as function without a return type specified e.g.
+ // main(int, char*[])
{
Bookmark start_position = SetBookmark();
result = ParseFunctionImpl(false);
@@ -34,8 +34,8 @@ Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
return result;
}
- // Try to parse the name as function with function pointer return type
- // e.g. void (*get_func(const char*))()
+ // Try to parse the name as function with function pointer return type e.g.
+ // void (*get_func(const char*))()
result = ParseFuncPtr(true);
if (result)
return result;
@@ -183,13 +183,13 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() {
Advance();
// Consuming template arguments is a bit trickier than consuming function
- // arguments, because '<' '>' brackets are not always trivially balanced.
- // In some rare cases tokens '<' and '>' can appear inside template arguments
- // as arithmetic or shift operators not as template brackets.
- // Examples: std::enable_if<(10u)<(64), bool>
+ // arguments, because '<' '>' brackets are not always trivially balanced. In
+ // some rare cases tokens '<' and '>' can appear inside template arguments as
+ // arithmetic or shift operators not as template brackets. Examples:
+ // std::enable_if<(10u)<(64), bool>
// f<A<operator<(X,Y)::Subclass>>
- // Good thing that compiler makes sure that really ambiguous cases of
- // '>' usage should be enclosed within '()' brackets.
+ // Good thing that compiler makes sure that really ambiguous cases of '>'
+ // usage should be enclosed within '()' brackets.
int template_counter = 1;
bool can_open_template = false;
while (HasMoreTokens() && template_counter > 0) {
@@ -208,9 +208,9 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() {
case tok::less:
// '<' is an attempt to open a subteamplte
// check if parser is at the point where it's actually possible,
- // otherwise it's just a part of an expression like 'sizeof(T)<(10)'.
- // No need to do the same for '>' because compiler actually makes sure
- // that '>' always surrounded by brackets to avoid ambiguity.
+ // otherwise it's just a part of an expression like 'sizeof(T)<(10)'. No
+ // need to do the same for '>' because compiler actually makes sure that
+ // '>' always surrounded by brackets to avoid ambiguity.
if (can_open_template)
++template_counter;
can_open_template = false;
@@ -242,8 +242,7 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() {
}
}
- assert(template_counter >= 0);
- if (template_counter > 0) {
+ if (template_counter != 0) {
return false;
}
start_position.Remove();
@@ -389,10 +388,9 @@ void CPlusPlusNameParser::SkipFunctionQualifiers() {
bool CPlusPlusNameParser::ConsumeBuiltinType() {
bool result = false;
bool continue_parsing = true;
- // Built-in types can be made of a few keywords
- // like 'unsigned long long int'. This function
- // consumes all built-in type keywords without
- // checking if they make sense like 'unsigned char void'.
+ // Built-in types can be made of a few keywords like 'unsigned long long
+ // int'. This function consumes all built-in type keywords without checking
+ // if they make sense like 'unsigned char void'.
while (continue_parsing && HasMoreTokens()) {
switch (Peek().getKind()) {
case tok::kw_short:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index f6d1f18cb596..95e02a473cd7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -123,12 +123,11 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
static ConstString g___i_("__i_");
- // this must be a ValueObject* because it is a child of the ValueObject we are
- // producing children for
- // it if were a ValueObjectSP, we would end up with a loop (iterator ->
- // synthetic -> child -> parent == iterator)
- // and that would in turn leak memory by never allowing the ValueObjects to
- // die and free their memory
+ // this must be a ValueObject* because it is a child of the ValueObject we
+ // are producing children for it if were a ValueObjectSP, we would end up
+ // with a loop (iterator -> synthetic -> child -> parent == iterator) and
+ // that would in turn leak memory by never allowing the ValueObjects to die
+ // and free their memory
m_pair_ptr = valobj_sp
->GetValueForExpressionPath(
".__i_.__ptr_->__value_", nullptr, nullptr,
@@ -386,7 +385,8 @@ enum LibcxxStringLayoutMode {
};
// this function abstracts away the layout and mode details of a libc++ string
-// and returns the address of the data and the size ready for callers to consume
+// and returns the address of the data and the size ready for callers to
+// consume
static bool ExtractLibcxxStringInfo(ValueObject &valobj,
ValueObjectSP &location_sp,
uint64_t &size) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 6407ae129ad7..6066f14b18cc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -206,8 +206,7 @@ bool AbstractListFrontEnd::HasLoop(size_t count) {
if (m_loop_detected == 0) {
// This is the first time we are being run (after the last update). Set up
- // the loop
- // invariant for the first element.
+ // the loop invariant for the first element.
m_slow_runner = ListEntry(m_head).next();
m_fast_runner = m_slow_runner.next();
m_loop_detected = 1;
@@ -215,9 +214,8 @@ bool AbstractListFrontEnd::HasLoop(size_t count) {
// Loop invariant:
// Loop detection has been run over the first m_loop_detected elements. If
- // m_slow_runner ==
- // m_fast_runner then the loop has been detected after m_loop_detected
- // elements.
+ // m_slow_runner == m_fast_runner then the loop has been detected after
+ // m_loop_detected elements.
const size_t steps_to_run = std::min(count, m_count);
while (m_loop_detected < steps_to_run && m_slow_runner && m_fast_runner &&
m_slow_runner != m_fast_runner) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index be96a6d95bcd..8f82bdcbfd59 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -382,8 +382,8 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex(
return lldb::ValueObjectSP();
}
} else {
- // because of the way our debug info is made, we need to read item 0 first
- // so that we can cache information used to generate other elements
+ // because of the way our debug info is made, we need to read item 0
+ // first so that we can cache information used to generate other elements
if (m_skip_size == UINT32_MAX)
GetChildAtIndex(0);
if (m_skip_size == UINT32_MAX) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
index b6d664df16ef..9d46e3e3ee58 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -43,6 +43,8 @@ private:
ValueObjectSP m_ptr_obj;
ValueObjectSP m_obj_obj;
ValueObjectSP m_del_obj;
+
+ ValueObjectSP GetTuple();
};
} // end of anonymous namespace
@@ -53,17 +55,36 @@ LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
Update();
}
-bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
+ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
ValueObjectSP valobj_backend_sp = m_backend.GetSP();
+
if (!valobj_backend_sp)
- return false;
+ return nullptr;
ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
if (!valobj_sp)
- return false;
+ return nullptr;
- ValueObjectSP tuple_sp =
+ ValueObjectSP obj_child_sp =
valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
+ if (!obj_child_sp)
+ return nullptr;
+
+ ValueObjectSP obj_subchild_sp =
+ obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true);
+
+ // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
+ // (for libstdc++ 6.0.23).
+ if (obj_subchild_sp) {
+ return obj_subchild_sp;
+ }
+
+ return obj_child_sp;
+}
+
+bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
+ ValueObjectSP tuple_sp = GetTuple();
+
if (!tuple_sp)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index 8f4997533212..8f278fc2d513 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -67,12 +67,12 @@ bool lldb_private::formatters::NSBundleSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "NSBundle")) {
+ if (class_name == "NSBundle") {
uint64_t offset = 5 * ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(
offset,
@@ -117,12 +117,12 @@ bool lldb_private::formatters::NSTimeZoneSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "__NSTimeZone")) {
+ if (class_name == "__NSTimeZone") {
uint64_t offset = ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(
offset, valobj.GetCompilerType(), true));
@@ -164,12 +164,12 @@ bool lldb_private::formatters::NSNotificationSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "NSConcreteNotification")) {
+ if (class_name == "NSConcreteNotification") {
uint64_t offset = ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(
offset, valobj.GetCompilerType(), true));
@@ -211,14 +211,14 @@ bool lldb_private::formatters::NSMachPortSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
uint64_t port_number = 0;
- if (!strcmp(class_name, "NSMachPort")) {
+ if (class_name == "NSMachPort") {
uint64_t offset = (ptr_size == 4 ? 12 : 20);
Status error;
port_number = process_sp->ReadUnsignedIntegerFromMemory(
@@ -259,16 +259,15 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
uint64_t count = 0;
do {
- if (!strcmp(class_name, "NSIndexSet") ||
- !strcmp(class_name, "NSMutableIndexSet")) {
+ if (class_name == "NSIndexSet" || class_name == "NSMutableIndexSet") {
Status error;
uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(
valobj_addr + ptr_size, 4, 0, error);
@@ -451,15 +450,18 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "__NSCFBoolean"))
+ if (class_name == "__NSCFBoolean")
return ObjCBooleanSummaryProvider(valobj, stream, options);
- if (!strcmp(class_name, "NSNumber") || !strcmp(class_name, "__NSCFNumber")) {
+ if (class_name == "NSDecimalNumber")
+ return NSDecimalNumberSummaryProvider(valobj, stream, options);
+
+ if (class_name == "NSNumber" || class_name == "__NSCFNumber") {
uint64_t value = 0;
uint64_t i_bits = 0;
if (descriptor->GetTaggedPointerInfo(&i_bits, &value)) {
@@ -626,6 +628,55 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
return false;
}
+bool lldb_private::formatters::NSDecimalNumberSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ Status error;
+ int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size, 1, 0, error);
+ if (error.Fail())
+ return false;
+
+ uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size + 1, 1, 0, error);
+ if (error.Fail())
+ return false;
+
+ // Fifth bit marks negativity.
+ const bool is_negative = (length_and_negative >> 4) & 1;
+
+ // Zero length and negative means NaN.
+ uint8_t length = length_and_negative & 0xf;
+ const bool is_nan = is_negative && (length == 0);
+
+ if (is_nan) {
+ stream.Printf("NaN");
+ return true;
+ }
+
+ if (length == 0) {
+ stream.Printf("0");
+ return true;
+ }
+
+ uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size + 4, 8, 0, error);
+ if (error.Fail())
+ return false;
+
+ if (is_negative)
+ stream.Printf("-");
+
+ stream.Printf("%" PRIu64 " x 10^%" PRIi8, mantissa, exponent);
+ return true;
+}
+
bool lldb_private::formatters::NSURLSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ProcessSP process_sp = valobj.GetProcessSP();
@@ -766,9 +817,9 @@ bool lldb_private::formatters::NSDateSummaryProvider(
stream.Printf("0001-12-30 00:00:00 +0000");
return true;
}
- // this snippet of code assumes that time_t == seconds since Jan-1-1970
- // this is generally true and POSIXly happy, but might break if a library
- // vendor decides to get creative
+ // this snippet of code assumes that time_t == seconds since Jan-1-1970 this
+ // is generally true and POSIXly happy, but might break if a library vendor
+ // decides to get creative
time_t epoch = GetOSXEpoch();
epoch = epoch + (time_t)date_value;
tm *tm_date = gmtime(&epoch);
@@ -871,28 +922,34 @@ bool lldb_private::formatters::NSDataSummaryProvider(
uint64_t value = 0;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name = descriptor->GetClassName().GetCString();
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "NSConcreteData") ||
- !strcmp(class_name, "NSConcreteMutableData") ||
- !strcmp(class_name, "__NSCFData")) {
- uint32_t offset = (is_64bit ? 16 : 8);
+ bool isNSConcreteData = class_name == "NSConcreteData";
+ bool isNSConcreteMutableData = class_name == "NSConcreteMutableData";
+ bool isNSCFData = class_name == "__NSCFData";
+ if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
+ uint32_t offset;
+ if (isNSConcreteData)
+ offset = is_64bit ? 8 : 4;
+ else
+ offset = is_64bit ? 16 : 8;
+
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(
valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
if (error.Fail())
return false;
- } else if (!strcmp(class_name, "_NSInlineData")) {
+ } else if (class_name == "_NSInlineData") {
uint32_t offset = (is_64bit ? 8 : 4);
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
0, error);
if (error.Fail())
return false;
- } else if (!strcmp(class_name, "_NSZeroData")) {
+ } else if (class_name == "_NSZeroData") {
value = 0;
} else
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h
index 10ff3bce3b98..0f2ca5496302 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h
@@ -32,6 +32,9 @@ bool NSDataSummaryProvider(ValueObject &valobj, Stream &stream,
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options);
+bool NSDecimalNumberSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index c564aa1a8571..5be051b46bd6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -396,6 +396,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
+ static const ConstString g_Dictionary0("__NSDictionary0");
+ static const ConstString g_DictionaryCF("__NSCFDictionary");
if (class_name.IsEmpty())
return false;
@@ -407,7 +409,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
if (error.Fail())
return false;
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
- } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
+ class_name == g_DictionaryCF) {
AppleObjCRuntime *apple_runtime =
llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
Status error;
@@ -423,17 +426,9 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
return false;
} else if (class_name == g_Dictionary1) {
value = 1;
+ } else if (class_name == g_Dictionary0) {
+ value = 0;
}
- /*else if (!strcmp(class_name,"__NSCFDictionary"))
- {
- Status error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ?
- 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x0f1f000000000000UL;
- }*/
else {
auto &map(NSDictionary_Additionals::GetAdditionalSummaries());
for (auto &candidate : map) {
@@ -491,6 +486,7 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
+ static const ConstString g_Dictionary0("__NSDictionary0");
if (class_name.IsEmpty())
return nullptr;
@@ -673,11 +669,7 @@ lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
GetIndexOfChildWithName(const ConstString &name) {
static const ConstString g_zero("[0]");
-
- if (name == g_zero)
- return 0;
-
- return UINT32_MAX;
+ return name == g_zero ? 0 : UINT32_MAX;
}
size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp
index 4365a12b54e1..77721e2db326 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp
@@ -177,12 +177,11 @@ public:
private:
// the child here can be "real" (i.e. an actual child of the root) or
- // synthetized from raw memory
- // if the former, I need to store a plain pointer to it - or else a loop of
- // references will cause this entire hierarchy of values to leak
- // if the latter, then I need to store a SharedPointer to it - so that it only
- // goes away when everyone else in the cluster goes away
- // oh joy!
+ // synthetized from raw memory if the former, I need to store a plain pointer
+ // to it - or else a loop of references will cause this entire hierarchy of
+ // values to leak if the latter, then I need to store a SharedPointer to it -
+ // so that it only goes away when everyone else in the cluster goes away oh
+ // joy!
ValueObject *m_child_ptr;
ValueObjectSP m_child_sp;
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp
index 1da4f6de19a0..c6970efae4d3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp
@@ -171,12 +171,11 @@ public:
private:
// the child here can be "real" (i.e. an actual child of the root) or
- // synthetized from raw memory
- // if the former, I need to store a plain pointer to it - or else a loop of
- // references will cause this entire hierarchy of values to leak
- // if the latter, then I need to store a SharedPointer to it - so that it only
- // goes away when everyone else in the cluster goes away
- // oh joy!
+ // synthetized from raw memory if the former, I need to store a plain pointer
+ // to it - or else a loop of references will cause this entire hierarchy of
+ // values to leak if the latter, then I need to store a SharedPointer to it -
+ // so that it only goes away when everyone else in the cluster goes away oh
+ // joy!
ValueObject *m_child_ptr;
ValueObjectSP m_child_sp;
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index fa2483ecc094..2da4bc034f32 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -269,7 +269,8 @@ bool lldb_private::formatters::NSSetSummaryProvider(
if (!class_name || !*class_name)
return false;
- if (!strcmp(class_name, "__NSSetI")) {
+ if (!strcmp(class_name, "__NSSetI") ||
+ !strcmp(class_name, "__NSOrderedSetI")) {
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
ptr_size, 0, error);
@@ -289,32 +290,7 @@ bool lldb_private::formatters::NSSetSummaryProvider(
}
if (error.Fail())
return false;
- }
- /*else if (!strcmp(class_name,"__NSCFSet"))
- {
- Status error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ?
- 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x1fff000000000000UL;
- }
- else if (!strcmp(class_name,"NSCountedSet"))
- {
- Status error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
- ptr_size, 0, error);
- if (error.Fail())
- return false;
- value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 :
- 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x1fff000000000000UL;
- }*/
- else {
+ } else {
auto &map(NSSet_Additionals::GetAdditionalSummaries());
auto iter = map.find(class_name_cs), end = map.end();
if (iter != end)
@@ -371,7 +347,8 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator(
if (!class_name || !*class_name)
return nullptr;
- if (!strcmp(class_name, "__NSSetI")) {
+ if (!strcmp(class_name, "__NSSetI") ||
+ !strcmp(class_name, "__NSOrderedSetI")) {
return (new NSSetISyntheticFrontEnd(valobj_sp));
} else if (!strcmp(class_name, "__NSSetM")) {
AppleObjCRuntime *apple_runtime =
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp
index 3b4edf68e063..0b12edb53d7a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp
@@ -256,8 +256,7 @@ bool lldb_private::formatters::NSStringSummaryProvider(
uint64_t location = valobj_addr + 2 * ptr_size;
if (!has_explicit_length) {
// in this kind of string, the byte before the string content is a length
- // byte
- // so let's try and use it to handle the embedded NUL case
+ // byte so let's try and use it to handle the embedded NUL case
Status error;
explicit_length =
process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
@@ -368,9 +367,7 @@ bool lldb_private::formatters::NSTaggedString_SummaryProvider(
}
// this is a fairly ugly trick - pretend that the numeric value is actually a
- // char*
- // this works under a few assumptions:
- // little endian architecture
+ // char* this works under a few assumptions: little endian architecture
// sizeof(uint64_t) > g_MaxNonBitmaskedLen
if (len_bits <= g_MaxNonBitmaskedLen) {
stream.Printf("%s", prefix.c_str());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index ea2eec7b33b7..47874b3be8fd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -90,9 +90,8 @@ bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
if (name.empty())
return IsValid(strict);
- // If "strict" is true. then the method must be specified with a
- // '+' or '-' at the beginning. If "strict" is false, then the '+'
- // or '-' can be omitted
+ // If "strict" is true. then the method must be specified with a '+' or '-'
+ // at the beginning. If "strict" is false, then the '+' or '-' can be omitted
bool valid_prefix = false;
if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
@@ -108,7 +107,7 @@ bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
if (valid_prefix) {
int name_len = name.size();
- // Objective C methods must have at least:
+ // Objective-C methods must have at least:
// "-[" or "+[" prefix
// One character for a class name
// One character for the space between the class name
@@ -134,8 +133,8 @@ const ConstString &ObjCLanguage::MethodName::GetClassName() {
if (paren_pos) {
m_class.SetCStringWithLength(class_start, paren_pos - class_start);
} else {
- // No '(' was found in the full name, we can definitively say
- // that our category was valid (and empty).
+ // No '(' was found in the full name, we can definitively say that our
+ // category was valid (and empty).
m_category_is_valid = true;
const char *space_pos = strchr(full, ' ');
if (space_pos) {
@@ -164,8 +163,8 @@ const ConstString &ObjCLanguage::MethodName::GetClassNameWithCategory() {
// contain a '(', then we can also fill in the m_class
if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) {
m_class = m_class_category;
- // No '(' was found in the full name, we can definitively say
- // that our category was valid (and empty).
+ // No '(' was found in the full name, we can definitively say that
+ // our category was valid (and empty).
m_category_is_valid = true;
}
}
@@ -764,6 +763,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
AddCXXSummary(
objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
"NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp,
+ lldb_private::formatters::NSNumberSummaryProvider,
+ "NSDecimalNumber summary provider",
+ ConstString("NSDecimalNumber"), appkit_flags);
AddCXXSummary(objc_category_sp,
lldb_private::formatters::NSURLSummaryProvider,
@@ -796,8 +799,8 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider,
"NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
- // CFAbsoluteTime is actually a double rather than a pointer to an object
- // we do not care about the numeric value, since it is probably meaningless to
+ // CFAbsoluteTime is actually a double rather than a pointer to an object we
+ // do not care about the numeric value, since it is probably meaningless to
// users
appkit_flags.SetDontShowValue(true);
AddCXXSummary(objc_category_sp,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index e5a459dfe861..fc661bbbf2c9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -83,26 +83,30 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
// We are a C++ class, that's good. Get the class name and look it
// up:
const char *class_name = name + strlen(vtable_demangled_prefix);
+ // We know the class name is absolute, so tell FindTypes that by
+ // prefixing it with the root namespace:
+ std::string lookup_name("::");
+ lookup_name.append(class_name);
+
type_info.SetName(class_name);
const bool exact_match = true;
TypeList class_types;
uint32_t num_matches = 0;
- // First look in the module that the vtable symbol came from
- // and look for a single exact match.
+ // First look in the module that the vtable symbol came from and
+ // look for a single exact match.
llvm::DenseSet<SymbolFile *> searched_symbol_files;
if (sc.module_sp) {
num_matches = sc.module_sp->FindTypes(
- sc, ConstString(class_name), exact_match, 1,
+ sc, ConstString(lookup_name), exact_match, 1,
searched_symbol_files, class_types);
}
- // If we didn't find a symbol, then move on to the entire
- // module list in the target and get as many unique matches
- // as possible
+ // If we didn't find a symbol, then move on to the entire module
+ // list in the target and get as many unique matches as possible
if (num_matches == 0) {
num_matches = target.GetImages().FindTypes(
- sc, ConstString(class_name), exact_match, UINT32_MAX,
+ sc, ConstString(lookup_name), exact_match, UINT32_MAX,
searched_symbol_files, class_types);
}
@@ -187,15 +191,12 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
TypeAndOrName &class_type_or_name, Address &dynamic_address,
Value::ValueType &value_type) {
// For Itanium, if the type has a vtable pointer in the object, it will be at
- // offset 0
- // in the object. That will point to the "address point" within the vtable
- // (not the beginning of the
- // vtable.) We can then look up the symbol containing this "address point"
- // and that symbol's name
- // demangled will contain the full class name.
- // The second pointer above the "address point" is the "offset_to_top". We'll
- // use that to get the
- // start of the value object which holds the dynamic type.
+ // offset 0 in the object. That will point to the "address point" within the
+ // vtable (not the beginning of the vtable.) We can then look up the symbol
+ // containing this "address point" and that symbol's name demangled will
+ // contain the full class name. The second pointer above the "address point"
+ // is the "offset_to_top". We'll use that to get the start of the value
+ // object which holds the dynamic type.
//
class_type_or_name.Clear();
@@ -230,17 +231,15 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
if (class_type_or_name) {
TypeSP type_sp = class_type_or_name.GetTypeSP();
- // There can only be one type with a given name,
- // so we've just found duplicate definitions, and this
- // one will do as well as any other.
- // We don't consider something to have a dynamic type if
- // it is the same as the static type. So compare against
- // the value we were handed.
+ // There can only be one type with a given name, so we've just found
+ // duplicate definitions, and this one will do as well as any other. We
+ // don't consider something to have a dynamic type if it is the same as
+ // the static type. So compare against the value we were handed.
if (type_sp) {
if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(),
type_sp->GetForwardCompilerType())) {
- // The dynamic type we found was the same type,
- // so we don't have a dynamic type here...
+ // The dynamic type we found was the same type, so we don't have a
+ // dynamic type here...
return false;
}
@@ -257,8 +256,8 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
if (offset_to_top == INT64_MIN)
return false;
- // So the dynamic type is a value that starts at offset_to_top
- // above the original address.
+ // So the dynamic type is a value that starts at offset_to_top above
+ // the original address.
lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(
dynamic_addr, dynamic_address)) {
@@ -280,10 +279,9 @@ TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType(
TypeAndOrName ret(type_and_or_name);
if (type_and_or_name.HasType()) {
// The type will always be the type of the dynamic object. If our parent's
- // type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If
- // a reference, then the original type
- // should be okay...
+ // type was a pointer, then our type should be a pointer to the type of the
+ // dynamic object. If a reference, then the original type should be
+ // okay...
CompilerType orig_type = type_and_or_name.GetCompilerType();
CompilerType corrected_type = orig_type;
if (static_type_flags.AllSet(eTypeIsPointer))
@@ -368,8 +366,8 @@ protected:
// the actual Mangled class should be strict about this, but on the
// command line if you're copying mangled names out of 'nm' on Darwin,
- // they will come out with an extra underscore - be willing to strip
- // this on behalf of the user. This is the moral equivalent of the -_/-n
+ // they will come out with an extra underscore - be willing to strip this
+ // on behalf of the user. This is the moral equivalent of the -_/-n
// options to c++filt
auto name = entry.ref;
if (name.startswith("__Z"))
@@ -448,13 +446,12 @@ BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) {
// One complication here is that most users DON'T want to stop at
- // __cxa_allocate_expression, but until we can do
- // anything better with predicting unwinding the expression parser does. So
- // we have two forms of the exception
- // breakpoints, one for expressions that leaves out __cxa_allocate_exception,
- // and one that includes it.
- // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint
- // in the runtime the former.
+ // __cxa_allocate_expression, but until we can do anything better with
+ // predicting unwinding the expression parser does. So we have two forms of
+ // the exception breakpoints, one for expressions that leaves out
+ // __cxa_allocate_exception, and one that includes it. The
+ // SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in
+ // the runtime the former.
static const char *g_catch_name = "__cxa_begin_catch";
static const char *g_throw_name1 = "__cxa_throw";
static const char *g_throw_name2 = "__cxa_rethrow";
@@ -517,8 +514,7 @@ void ItaniumABILanguageRuntime::SetExceptionBreakpoints() {
const bool for_expressions = true;
// For the exception breakpoints set by the Expression parser, we'll be a
- // little more aggressive and
- // stop at exception allocation as well.
+ // little more aggressive and stop at exception allocation as well.
if (m_cxx_exception_bp_sp) {
m_cxx_exception_bp_sp->SetEnabled(true);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index ecb0b64f2346..edb29e735ca9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -378,8 +378,7 @@ bool ClassDescriptorV2::Describe(
AppleObjCRuntime::ClassDescriptorSP metaclass(GetMetaclass());
// We don't care about the metaclass's superclass, or its class methods.
- // Its instance methods are
- // our class methods.
+ // Its instance methods are our class methods.
if (metaclass) {
metaclass->Describe(
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index eacc98a07193..fef42c78b24f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -54,23 +54,20 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &str, ValueObject &valobj) {
CompilerType compiler_type(valobj.GetCompilerType());
bool is_signed;
// ObjC objects can only be pointers (or numbers that actually represents
- // pointers
- // but haven't been typecast, because reasons..)
+ // pointers but haven't been typecast, because reasons..)
if (!compiler_type.IsIntegerType(is_signed) && !compiler_type.IsPointerType())
return false;
- // Make the argument list: we pass one arg, the address of our pointer, to the
- // print function.
+ // Make the argument list: we pass one arg, the address of our pointer, to
+ // the print function.
Value val;
if (!valobj.ResolveValue(val.GetScalar()))
return false;
// Value Objects may not have a process in their ExecutionContextRef. But we
- // need to have one
- // in the ref we pass down to eventually call description. Get it from the
- // target if it isn't
- // present.
+ // need to have one in the ref we pass down to eventually call description.
+ // Get it from the target if it isn't present.
ExecutionContext exe_ctx;
if (valobj.GetProcessSP()) {
exe_ctx = ExecutionContext(valobj.GetExecutionContextRef());
@@ -257,10 +254,9 @@ AppleObjCRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
TypeAndOrName ret(type_and_or_name);
if (type_and_or_name.HasType()) {
// The type will always be the type of the dynamic object. If our parent's
- // type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If
- // a reference, then the original type
- // should be okay...
+ // type was a pointer, then our type should be a pointer to the type of the
+ // dynamic object. If a reference, then the original type should be
+ // okay...
CompilerType orig_type = type_and_or_name.GetCompilerType();
CompilerType corrected_type = orig_type;
if (static_type_flags.AllSet(eTypeIsPointer))
@@ -297,16 +293,14 @@ bool AppleObjCRuntime::AppleIsModuleObjCLibrary(const ModuleSP &module_sp) {
uint32_t AppleObjCRuntime::GetFoundationVersion() {
if (!m_Foundation_major.hasValue()) {
const ModuleList &modules = m_process->GetTarget().GetImages();
- uint32_t major = UINT32_MAX;
for (uint32_t idx = 0; idx < modules.GetSize(); idx++) {
lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
if (!module_sp)
continue;
if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),
"Foundation") == 0) {
- module_sp->GetVersion(&major, 1);
- m_Foundation_major = major;
- return major;
+ m_Foundation_major = module_sp->GetVersion().getMajor();
+ return *m_Foundation_major;
}
}
return LLDB_INVALID_MODULE_VERSION;
@@ -325,8 +319,8 @@ bool AppleObjCRuntime::IsModuleObjCLibrary(const ModuleSP &module_sp) {
bool AppleObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) {
// Maybe check here and if we have a handler already, and the UUID of this
- // module is the same as the one in the
- // current module, then we don't have to reread it?
+ // module is the same as the one in the current module, then we don't have to
+ // reread it?
m_objc_trampoline_handler_ap.reset(
new AppleObjCTrampolineHandler(m_process->shared_from_this(), module_sp));
if (m_objc_trampoline_handler_ap.get() != NULL) {
@@ -365,11 +359,9 @@ AppleObjCRuntime::GetObjCVersion(Process *process, ModuleSP &objc_module_sp) {
for (size_t i = 0; i < num_images; i++) {
ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
// One tricky bit here is that we might get called as part of the initial
- // module loading, but
- // before all the pre-run libraries get winnowed from the module list. So
- // there might actually
- // be an old and incorrect ObjC library sitting around in the list, and we
- // don't want to look at that.
+ // module loading, but before all the pre-run libraries get winnowed from
+ // the module list. So there might actually be an old and incorrect ObjC
+ // library sitting around in the list, and we don't want to look at that.
// That's why we call IsLoadedInTarget.
if (AppleIsModuleObjCLibrary(module_sp) &&
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 9cac499c0ff0..5001c0461b3b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -42,8 +42,7 @@ AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process)
m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS) {}
// for V1 runtime we just try to return a class name as that is the minimum
-// level of support
-// required for the data formatters to work
+// level of support required for the data formatters to work
bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
ValueObject &in_value, lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name, Address &address,
@@ -85,7 +84,7 @@ AppleObjCRuntimeV1::CreateInstance(Process *process,
void AppleObjCRuntimeV1::Initialize() {
PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 1",
+ GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 1",
CreateInstance);
}
@@ -284,6 +283,10 @@ bool AppleObjCRuntimeV1::ClassDescriptorV1::Describe(
return false;
}
+lldb::addr_t AppleObjCRuntimeV1::GetTaggedPointerObfuscator() {
+ return 0;
+}
+
lldb::addr_t AppleObjCRuntimeV1::GetISAHashTablePointer() {
if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
ModuleSP objc_module_sp(GetObjCModule());
@@ -383,8 +386,8 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
ObjCISA isa;
if (bucket_isa_count == 1) {
- // When we only have one entry in the bucket, the bucket data is
- // the "isa"
+ // When we only have one entry in the bucket, the bucket data
+ // is the "isa"
isa = bucket_data;
if (isa) {
if (!ISAIsCached(isa)) {
@@ -402,8 +405,7 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
}
} else {
// When we have more than one entry in the bucket, the bucket
- // data is a pointer
- // to an array of "isa" values
+ // data is a pointer to an array of "isa" values
addr_t isa_addr = bucket_data;
for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count;
++isa_idx, isa_addr += addr_size) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 3dddf1b094e1..52eec0f692fb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -45,6 +45,8 @@ public:
}
}
+ lldb::addr_t GetTaggedPointerObfuscator();
+
class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor {
public:
ClassDescriptorV1(ValueObject &isa_pointer);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index bdf79f7b82bd..d217ed3ff325 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -37,6 +37,7 @@
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -76,8 +77,7 @@ static constexpr std::chrono::seconds g_utility_function_timeout(2);
static const char *g_get_dynamic_class_info_name =
"__lldb_apple_objc_v2_get_dynamic_class_info";
// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will
-// need to revert to the code above...
+// will need to revert to the code above...
static const char *g_get_dynamic_class_info_body = R"(
extern "C"
@@ -161,8 +161,7 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr
static const char *g_get_shared_cache_class_info_name =
"__lldb_apple_objc_v2_get_shared_cache_class_info";
// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will
-// need to revert to the code above...
+// will need to revert to the code above...
static const char *g_get_shared_cache_class_info_body = R"(
extern "C"
@@ -385,7 +384,9 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(),
m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS),
m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_ap(),
- m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
+ m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
+ m_hash_signature(),
m_has_object_getClass(false), m_loaded_objc_opt(false),
m_non_pointer_isa_cache_ap(
NonPointerISACache::CreateInstance(*this, objc_module_sp)),
@@ -406,10 +407,9 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
assert(m_process != NULL);
// The Runtime is attached to a particular process, you shouldn't pass in a
- // value from another process.
- // Note, however, the process might be NULL (e.g. if the value was made with
- // SBTarget::EvaluateExpression...)
- // in which case it is sufficient if the target's match:
+ // value from another process. Note, however, the process might be NULL (e.g.
+ // if the value was made with SBTarget::EvaluateExpression...) in which case
+ // it is sufficient if the target's match:
Process *process = in_value.GetProcessSP().get();
if (process)
@@ -422,8 +422,8 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
// Make sure we can have a dynamic value before starting...
if (CouldHaveDynamicValue(in_value)) {
- // First job, pull out the address at 0 offset from the object That will be
- // the ISA pointer.
+ // First job, pull out the address at 0 offset from the object That will
+ // be the ISA pointer.
ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(in_value));
if (objc_class_sp) {
const addr_t object_ptr = in_value.GetPointerValue();
@@ -682,7 +682,7 @@ protected:
if (!arg_str)
continue;
Status error;
- lldb::addr_t arg_addr = Args::StringToAddress(
+ lldb::addr_t arg_addr = OptionArgParser::ToAddress(
&exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail())
continue;
@@ -771,7 +771,7 @@ public:
void AppleObjCRuntimeV2::Initialize() {
PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 2",
+ GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 2",
CreateInstance,
[](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
@@ -870,8 +870,8 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
if (class_name && class_name[0] && ivar_name && ivar_name[0]) {
//----------------------------------------------------------------------
- // Make the objective C V2 mangled name for the ivar offset from the
- // class name and ivar name
+ // Make the objective C V2 mangled name for the ivar offset from the class
+ // name and ivar name
//----------------------------------------------------------------------
std::string buffer("OBJC_IVAR_$_");
buffer.append(class_name);
@@ -880,8 +880,8 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
ConstString ivar_const_str(buffer.c_str());
//----------------------------------------------------------------------
- // Try to get the ivar offset address from the symbol table first using
- // the name we created above
+ // Try to get the ivar offset address from the symbol table first using the
+ // name we created above
//----------------------------------------------------------------------
SymbolContextList sc_list;
Target &target = m_process->GetTarget();
@@ -914,11 +914,9 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
}
// tagged pointers are special not-a-real-pointer values that contain both type
-// and value information
-// this routine attempts to check with as little computational effort as
-// possible whether something
-// could possibly be a tagged pointer - false positives are possible but false
-// negatives shouldn't
+// and value information this routine attempts to check with as little
+// computational effort as possible whether something could possibly be a
+// tagged pointer - false positives are possible but false negatives shouldn't
bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
if (!m_tagged_pointer_vendor_ap)
return false;
@@ -950,11 +948,11 @@ public:
Status err;
// This currently holds true for all platforms we support, but we might
- // need to change this to use get the actually byte size of "unsigned"
- // from the target AST...
+ // need to change this to use get the actually byte size of "unsigned" from
+ // the target AST...
const uint32_t unsigned_byte_size = sizeof(uint32_t);
- // Skip the prototype as we don't need it (const struct +NXMapTablePrototype
- // *prototype)
+ // Skip the prototype as we don't need it (const struct
+ // +NXMapTablePrototype *prototype)
bool success = true;
if (load_addr == LLDB_INVALID_ADDRESS)
@@ -988,8 +986,8 @@ public:
return success;
}
- // const_iterator mimics NXMapState and its code comes from NXInitMapState and
- // NXNextMapState.
+ // const_iterator mimics NXMapState and its code comes from NXInitMapState
+ // and NXNextMapState.
typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
friend class const_iterator;
@@ -1132,8 +1130,8 @@ bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
return false; // Failed to parse the header, no need to update anything
}
- // Check with out current signature and return true if the count,
- // number of buckets or the hash table address changes.
+ // Check with out current signature and return true if the count, number of
+ // buckets or the hash table address changes.
if (m_count == hash_table.GetCount() &&
m_num_buckets == hash_table.GetBucketCount() &&
m_buckets_ptr == hash_table.GetBucketDataPointer()) {
@@ -1167,9 +1165,9 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
}
return nullptr;
}
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
+ // if we get an invalid VO (which might still happen when playing around with
+ // pointers returned by the expression parser, don't consider this a valid
+ // ObjC object)
if (valobj.GetCompilerType().IsValid()) {
addr_t isa_pointer = valobj.GetPointerValue();
@@ -1200,6 +1198,38 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
return objc_class_sp;
}
+lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() {
+ if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
+ return m_tagged_pointer_obfuscator;
+
+
+ Process *process = GetProcess();
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_gdb_objc_obfuscator("objc_debug_taggedpointer_obfuscator");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
+ g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
+ if (symbol) {
+ lldb::addr_t g_gdb_obj_obfuscator_ptr =
+ symbol->GetLoadAddress(&process->GetTarget());
+
+ if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
+ Status error;
+ m_tagged_pointer_obfuscator = process->ReadPointerFromMemory(
+ g_gdb_obj_obfuscator_ptr, error);
+ }
+ }
+ // If we don't have a correct value at this point, there must be no obfuscation.
+ if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
+ m_tagged_pointer_obfuscator = 0;
+
+ return m_tagged_pointer_obfuscator;
+}
+
lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
Process *process = GetProcess();
@@ -1359,8 +1389,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
- // Only dump the runtime classes from the expression evaluation if the
- // log is verbose:
+ // Only dump the runtime classes from the expression evaluation if the log is
+ // verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
@@ -1440,7 +1470,8 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
// uint32_t hash;
// } __attribute__((__packed__));
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
+ bool should_log = log && log->GetVerbose();
uint32_t num_parsed = 0;
@@ -1450,15 +1481,15 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
ObjCISA isa = data.GetPointer(&offset);
if (isa == 0) {
- if (log)
+ if (should_log)
log->Printf(
"AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
continue;
}
- // Check if we already know about this ISA, if we do, the info will
- // never change, so we can just skip it.
+ // Check if we already know about this ISA, if we do, the info will never
+ // change, so we can just skip it.
if (ISAIsCached(isa)) {
- if (log)
+ if (should_log)
log->Printf("AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
", ignoring this class info",
isa);
@@ -1469,14 +1500,14 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
ClassDescriptorSP descriptor_sp(new ClassDescriptorV2(*this, isa, NULL));
AddClass(isa, descriptor_sp, name_hash);
num_parsed++;
- if (log)
+ if (should_log)
log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64
", hash=0x%8.8x, name=%s",
isa, name_hash,
descriptor_sp->GetClassName().AsCString("<unknown>"));
}
}
- if (log)
+ if (should_log)
log->Printf("AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
num_parsed);
return num_parsed;
@@ -1607,8 +1638,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
- // Only dump the runtime classes from the expression evaluation if the
- // log is verbose:
+ // Only dump the runtime classes from the expression evaluation if the log is
+ // verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
@@ -1788,21 +1819,17 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
DescriptorMapUpdateResult dynamic_update_result =
UpdateISAToDescriptorMapDynamic(hash_table);
- // Now get the objc classes that are baked into the Objective C runtime
- // in the shared cache, but only once per process as this data never
- // changes
+ // Now get the objc classes that are baked into the Objective-C runtime in
+ // the shared cache, but only once per process as this data never changes
if (!m_loaded_objc_opt) {
// it is legitimately possible for the shared cache to be empty - in that
- // case, the dynamic hash table
- // will contain all the class information we need; the situation we're
- // trying to detect is one where
- // we aren't seeing class information from the runtime - in order to
- // detect that vs. just the shared cache
- // being empty or sparsely populated, we set an arbitrary (very low)
- // threshold for the number of classes
- // that we want to see in a "good" scenario - anything below that is
- // suspicious (Foundation alone has thousands
- // of classes)
+ // case, the dynamic hash table will contain all the class information we
+ // need; the situation we're trying to detect is one where we aren't
+ // seeing class information from the runtime - in order to detect that
+ // vs. just the shared cache being empty or sparsely populated, we set an
+ // arbitrary (very low) threshold for the number of classes that we want
+ // to see in a "good" scenario - anything below that is suspicious
+ // (Foundation alone has thousands of classes)
const uint32_t num_classes_to_warn_at = 500;
DescriptorMapUpdateResult shared_cache_update_result =
@@ -2089,8 +2116,8 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
if (error.Fail())
return new TaggedPointerVendorLegacy(runtime);
- // try to detect the "extended tagged pointer" variables - if any are missing,
- // use the non-extended vendor
+ // try to detect the "extended tagged pointer" variables - if any are
+ // missing, use the non-extended vendor
do {
auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
process, ConstString("objc_debug_taggedpointer_ext_mask"),
@@ -2143,8 +2170,8 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
} while (false);
- // we might want to have some rules to outlaw these values (e.g if the table's
- // address is zero)
+ // we might want to have some rules to outlaw these values (e.g if the
+ // table's address is zero)
return new TaggedPointerVendorRuntimeAssisted(
runtime, objc_debug_taggedpointer_mask,
@@ -2217,7 +2244,9 @@ AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
return ObjCLanguageRuntime::ClassDescriptorSP();
}
}
- return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, ptr));
+
+ lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated));
}
AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
@@ -2249,8 +2278,9 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
uint64_t data_payload;
+ uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
- if (!IsPossibleTaggedPointer(ptr))
+ if (!IsPossibleTaggedPointer(unobfuscated))
return ObjCLanguageRuntime::ClassDescriptorSP();
uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
@@ -2276,7 +2306,7 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
}
data_payload =
- (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >>
+ (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
m_objc_debug_taggedpointer_payload_rshift);
return ClassDescriptorSP(
@@ -2333,11 +2363,12 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
uint64_t data_payload;
+ uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
- if (!IsPossibleTaggedPointer(ptr))
+ if (!IsPossibleTaggedPointer(unobfuscated))
return ObjCLanguageRuntime::ClassDescriptorSP();
- if (!IsPossibleExtendedTaggedPointer(ptr))
+ if (!IsPossibleExtendedTaggedPointer(unobfuscated))
return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
@@ -2363,7 +2394,7 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
}
data_payload =
- (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >>
m_objc_debug_taggedpointer_ext_payload_rshift);
return ClassDescriptorSP(
@@ -2414,11 +2445,10 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
if ((isa & ~m_objc_debug_isa_class_mask) == 0)
return false;
- // If all of the indexed ISA variables are set, then its possible that
- // this ISA is indexed, and we should first try to get its value using
- // the index.
- // Note, we check these varaibles first as the ObjC runtime will set at
- // least one of their values to 0 if they aren't needed.
+ // If all of the indexed ISA variables are set, then its possible that this
+ // ISA is indexed, and we should first try to get its value using the index.
+ // Note, we check these varaibles first as the ObjC runtime will set at least
+ // one of their values to 0 if they aren't needed.
if (m_objc_debug_indexed_isa_magic_mask &&
m_objc_debug_indexed_isa_magic_value &&
m_objc_debug_indexed_isa_index_mask &&
@@ -2431,10 +2461,10 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
// Magic bits are correct, so try extract the index.
uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
m_objc_debug_indexed_isa_index_shift;
- // If the index is out of bounds of the length of the array then
- // check if the array has been updated. If that is the case then
- // we should try read the count again, and update the cache if the
- // count has been updated.
+ // If the index is out of bounds of the length of the array then check if
+ // the array has been updated. If that is the case then we should try
+ // read the count again, and update the cache if the count has been
+ // updated.
if (index > m_indexed_isa_cache.size()) {
if (log)
log->Printf("AOCRT::NPI (index = %" PRIu64
@@ -2459,9 +2489,9 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
(uint64_t)objc_indexed_classes_count);
if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
- // Read the class entries we don't have. We should just
- // read all of them instead of just the one we need as then
- // we can cache those we may need later.
+ // Read the class entries we don't have. We should just read all of
+ // them instead of just the one we need as then we can cache those we
+ // may need later.
auto num_new_classes =
objc_indexed_classes_count - m_indexed_isa_cache.size();
const uint32_t addr_size = process->GetAddressByteSize();
@@ -2504,8 +2534,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
return false;
}
- // Definately not an indexed ISA, so try to use a mask to extract
- // the pointer from the ISA.
+ // Definately not an indexed ISA, so try to use a mask to extract the pointer
+ // from the ISA.
if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
ret_isa = isa & m_objc_debug_isa_class_mask;
return (ret_isa != 0); // this is a pointer so 0 is not a valid value
@@ -2533,14 +2563,14 @@ bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
if (m_CFBoolean_values)
return true;
- static ConstString g_kCFBooleanFalse("kCFBooleanFalse");
- static ConstString g_kCFBooleanTrue("kCFBooleanTrue");
+ static ConstString g_kCFBooleanFalse("__kCFBooleanFalse");
+ static ConstString g_kCFBooleanTrue("__kCFBooleanTrue");
std::function<lldb::addr_t(ConstString)> get_symbol =
[this](ConstString sym) -> lldb::addr_t {
SymbolContextList sc_list;
if (GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
- g_kCFBooleanFalse, lldb::eSymbolTypeData, sc_list) == 1) {
+ sym, lldb::eSymbolTypeData, sc_list) == 1) {
SymbolContext sc;
sc_list.GetContextAtIndex(0, sc);
if (sc.symbol)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 89e81d5b181e..487b67ca6271 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -94,6 +94,8 @@ public:
return m_tagged_pointer_vendor_ap.get();
}
+ lldb::addr_t GetTaggedPointerObfuscator();
+
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
lldb::addr_t &cf_false) override;
@@ -330,6 +332,7 @@ private:
std::mutex m_get_shared_cache_class_info_args_mutex;
std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+ lldb::addr_t m_tagged_pointer_obfuscator;
lldb::addr_t m_isa_hash_table_ptr;
HashTableSignature m_hash_signature;
bool m_has_object_getClass;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index a6e9c0c16f16..c75fa71ba131 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -49,227 +49,237 @@ const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name =
const char *AppleObjCTrampolineHandler::
g_lookup_implementation_with_stret_function_code =
" \n\
-extern \"C\" \n\
-{ \n\
- extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
- extern void *class_getMethodImplementation_stret(void *objc_class, void *sel); \n\
- extern void * object_getClass (id object); \n\
- extern void * sel_getUid(char *name); \n\
- extern int printf(const char *format, ...); \n\
-} \n\
-extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
- void *sel, \n\
- int is_stret, \n\
- int is_super, \n\
- int is_super2, \n\
- int is_fixup, \n\
- int is_fixed, \n\
- int debug) \n\
-{ \n\
- struct __lldb_imp_return_struct \n\
- { \n\
- void *class_addr; \n\
- void *sel_addr; \n\
- void *impl_addr; \n\
- }; \n\
- \n\
- struct __lldb_objc_class { \n\
- void *isa; \n\
- void *super_ptr; \n\
- }; \n\
- struct __lldb_objc_super { \n\
- void *reciever; \n\
- struct __lldb_objc_class *class_ptr; \n\
- }; \n\
- struct __lldb_msg_ref { \n\
- void *dont_know; \n\
- void *sel; \n\
- }; \n\
- \n\
- struct __lldb_imp_return_struct return_struct; \n\
- \n\
- if (debug) \n\
- printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
- \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
- object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
- if (is_super) \n\
- { \n\
- if (is_super2) \n\
- { \n\
- return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
- } \n\
- else \n\
- { \n\
- return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
- } \n\
- } \n\
- else \n\
- { \n\
- // This code seems a little funny, but has its reasons... \n\
- // The call to [object class] is here because if this is a class, and has not been called into \n\
- // yet, we need to do something to force the class to initialize itself. \n\
- // Then the call to object_getClass will actually return the correct class, either the class \n\
- // if object is a class instance, or the meta-class if it is a class pointer. \n\
- void *class_ptr = (void *) [(id) object class]; \n\
- return_struct.class_addr = (id) object_getClass((id) object); \n\
- if (debug) \n\
- { \n\
- if (class_ptr == object) \n\
- { \n\
- printf (\"Found a class object, need to use the meta class %p -> %p\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- else \n\
- { \n\
- printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- } \n\
- } \n\
- \n\
- if (is_fixup) \n\
- { \n\
- if (is_fixed) \n\
- { \n\
- return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
- } \n\
- else \n\
- { \n\
- char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
- return_struct.sel_addr = sel_getUid (sel_name); \n\
- if (debug) \n\
- printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\", \n\
- return_struct.sel_addr, sel_name); \n\
- } \n\
- } \n\
- else \n\
- { \n\
- return_struct.sel_addr = sel; \n\
- } \n\
- \n\
- if (is_stret) \n\
- { \n\
- return_struct.impl_addr = class_getMethodImplementation_stret (return_struct.class_addr, \n\
- return_struct.sel_addr); \n\
- } \n\
- else \n\
- { \n\
- return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
- return_struct.sel_addr); \n\
- } \n\
- if (debug) \n\
- printf (\"\\n*** Returning implementation: %p.\\n\", return_struct.impl_addr); \n\
- \n\
- return return_struct.impl_addr; \n\
-} \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void *class_getMethodImplementation_stret(void *objc_class, \n\
+ void *sel); \n\
+ extern void * object_getClass (id object); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
+extern \"C\" void * __lldb_objc_find_implementation_for_selector ( \n\
+ void *object, \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
+ printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"\n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);\n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;\n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;\n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ // This code seems a little funny, but has its reasons... \n\
+ \n\
+ // The call to [object class] is here because if this is a \n\
+ // class, and has not been called into yet, we need to do \n\
+ // something to force the class to initialize itself. \n\
+ // Then the call to object_getClass will actually return the \n\
+ // correct class, either the class if object is a class \n\
+ // instance, or the meta-class if it is a class pointer. \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ return_struct.class_addr = (id) object_getClass((id) object); \n\
+ if (debug) \n\
+ { \n\
+ if (class_ptr == object) \n\
+ { \n\
+ printf (\"Found a class object, need to use the meta class %p -> %p\\n\",\n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\",\n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ if (is_stret) \n\
+ { \n\
+ return_struct.impl_addr = \n\
+ class_getMethodImplementation_stret (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.impl_addr = \n\
+ class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ } \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: %p.\\n\", \n\
+ return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
";
const char *
AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code =
" \n\
-extern \"C\" \n\
-{ \n\
- extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
- extern void * object_getClass (id object); \n\
- extern void * sel_getUid(char *name); \n\
- extern int printf(const char *format, ...); \n\
-} \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void * object_getClass (id object); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
- void *sel, \n\
- int is_stret, \n\
- int is_super, \n\
- int is_super2, \n\
- int is_fixup, \n\
- int is_fixed, \n\
- int debug) \n\
-{ \n\
- struct __lldb_imp_return_struct \n\
- { \n\
- void *class_addr; \n\
- void *sel_addr; \n\
- void *impl_addr; \n\
- }; \n\
- \n\
- struct __lldb_objc_class { \n\
- void *isa; \n\
- void *super_ptr; \n\
- }; \n\
- struct __lldb_objc_super { \n\
- void *reciever; \n\
- struct __lldb_objc_class *class_ptr; \n\
- }; \n\
- struct __lldb_msg_ref { \n\
- void *dont_know; \n\
- void *sel; \n\
- }; \n\
- \n\
- struct __lldb_imp_return_struct return_struct; \n\
- \n\
- if (debug) \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
- \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
- if (is_super) \n\
- { \n\
- if (is_super2) \n\
- { \n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
- } \n\
- else \n\
- { \n\
+ } \n\
+ else \n\
+ { \n\
return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
- } \n\
- } \n\
- else \n\
- { \n\
- // This code seems a little funny, but has its reasons... \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ // This code seems a little funny, but has its reasons... \n\
// The call to [object class] is here because if this is a class, and has not been called into \n\
// yet, we need to do something to force the class to initialize itself. \n\
// Then the call to object_getClass will actually return the correct class, either the class \n\
// if object is a class instance, or the meta-class if it is a class pointer. \n\
- void *class_ptr = (void *) [(id) object class]; \n\
- return_struct.class_addr = (id) object_getClass((id) object); \n\
- if (debug) \n\
- { \n\
- if (class_ptr == object) \n\
- { \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ return_struct.class_addr = (id) object_getClass((id) object); \n\
+ if (debug) \n\
+ { \n\
+ if (class_ptr == object) \n\
+ { \n\
printf (\"Found a class object, need to return the meta class %p -> %p\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- else \n\
- { \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ else \n\
+ { \n\
printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- } \n\
- } \n\
- \n\
- if (is_fixup) \n\
- { \n\
- if (is_fixed) \n\
- { \n\
- return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
- } \n\
- else \n\
- { \n\
- char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
- return_struct.sel_addr = sel_getUid (sel_name); \n\
- if (debug) \n\
- printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\", \n\
- return_struct.sel_addr, sel_name); \n\
- } \n\
- } \n\
- else \n\
- { \n\
- return_struct.sel_addr = sel; \n\
- } \n\
- \n\
- return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
- return_struct.sel_addr); \n\
- if (debug) \n\
- printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr); \n\
- \n\
- return return_struct.impl_addr; \n\
-} \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\",\n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ return_struct.impl_addr = \n\
+ class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: 0x%p.\\n\", \n\
+ return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
";
AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(
@@ -328,12 +338,11 @@ void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
// uint32_t offset
// uint32_t flags
//
- // Where offset is either 0 - in which case it is unused, or
- // it is the offset of the vtable code from the beginning of the descriptor
- // record.
- // Below, we'll convert that into an absolute code address, since I don't want
- // to have
- // to compute it over and over.
+ // Where offset is either 0 - in which case it is unused, or it is
+ // the offset of the vtable code from the beginning of the
+ // descriptor record. Below, we'll convert that into an absolute
+ // code address, since I don't want to have to compute it over and
+ // over.
// Ingest the whole descriptor array:
const lldb::addr_t desc_ptr = m_header_addr + header_size;
@@ -370,10 +379,9 @@ void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
offset = start_offset + descriptor_size;
}
- // Finally, a little bird told me that all the vtable code blocks are the same
- // size.
- // Let's compute the blocks and if they are all the same add the size to the
- // code end address:
+ // Finally, a little bird told me that all the vtable code blocks
+ // are the same size. Let's compute the blocks and if they are all
+ // the same add the size to the code end address:
lldb::addr_t code_size = 0;
bool all_the_same = true;
for (size_t i = 0; i < num_descriptors - 1; i++) {
@@ -548,9 +556,8 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines(
}
bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions() {
- // The no argument version reads the start region from the value of the
- // gdb_regions_header, and
- // gets started from there.
+ // The no argument version reads the start region from the value of
+ // the gdb_regions_header, and gets started from there.
m_regions.clear();
if (!InitializeVTableSymbols())
@@ -718,13 +725,12 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler(
g_lookup_implementation_with_stret_function_code;
}
- // Look up the addresses for the objc dispatch functions and cache them. For
- // now I'm inspecting the symbol
- // names dynamically to figure out how to dispatch to them. If it becomes
- // more complicated than this we can
- // turn the g_dispatch_functions char * array into a template table, and
- // populate the DispatchFunction map
- // from there.
+ // Look up the addresses for the objc dispatch functions and cache
+ // them. For now I'm inspecting the symbol names dynamically to
+ // figure out how to dispatch to them. If it becomes more
+ // complicated than this we can turn the g_dispatch_functions char *
+ // array into a template table, and populate the DispatchFunction
+ // map from there.
for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++) {
ConstString name_const_str(g_dispatch_functions[i].name);
@@ -732,11 +738,11 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler(
m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str,
eSymbolTypeCode);
if (msgSend_symbol && msgSend_symbol->ValueIsAddress()) {
- // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and
- // have the map be address->index.
- // Problem is we also need to lookup the dispatch function. For now we
- // could have a side table of stret & non-stret
- // dispatch functions. If that's as complex as it gets, we're fine.
+ // FIXME: Make g_dispatch_functions static table of
+ // DispatchFunctions, and have the map be address->index.
+ // Problem is we also need to lookup the dispatch function. For
+ // now we could have a side table of stret & non-stret dispatch
+ // functions. If that's as complex as it gets, we're fine.
lldb::addr_t sym_addr =
msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target);
@@ -820,11 +826,11 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
diagnostics.Clear();
- // Now write down the argument values for this particular call. This looks
- // like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we
- // allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+ // Now write down the argument values for this particular call.
+ // This looks like it might be a race condition if other threads
+ // were calling into here, but actually it isn't because we allocate
+ // a new args structure for this call by passing args_addr =
+ // LLDB_INVALID_ADDRESS...
if (!impl_function_caller->WriteFunctionArguments(
exe_ctx, args_addr, dispatch_values, diagnostics)) {
@@ -847,9 +853,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
DispatchFunction this_dispatch;
bool found_it = false;
- // First step is to look and see if we are in one of the known ObjC dispatch
- // functions. We've already compiled
- // a table of same, so consult it.
+ // First step is to look and see if we are in one of the known ObjC
+ // dispatch functions. We've already compiled a table of same, so
+ // consult it.
MsgsendMap::iterator pos;
pos = m_msgSend_map.find(curr_pc);
@@ -879,8 +885,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
if (found_it) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- // We are decoding a method dispatch.
- // First job is to pull the arguments out:
+ // We are decoding a method dispatch. First job is to pull the
+ // arguments out:
lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
@@ -906,10 +912,10 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
int obj_index;
int sel_index;
- // If this is a struct return dispatch, then the first argument is the
- // return struct pointer, and the object is the second, and the selector is
- // the third.
- // Otherwise the object is the first and the selector the second.
+ // If this is a struct return dispatch, then the first argument is
+ // the return struct pointer, and the object is the second, and
+ // the selector is the third. Otherwise the object is the first
+ // and the selector the second.
if (this_dispatch.stret_return) {
obj_index = 1;
sel_index = 2;
@@ -938,29 +944,26 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
ExecutionContext exe_ctx(thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
- // isa_addr will store the class pointer that the method is being dispatched
- // to - so either the class
- // directly or the super class if this is one of the objc_msgSendSuper
- // flavors. That's mostly used to
- // look up the class/selector pair in our cache.
+ // isa_addr will store the class pointer that the method is being
+ // dispatched to - so either the class directly or the super class
+ // if this is one of the objc_msgSendSuper flavors. That's mostly
+ // used to look up the class/selector pair in our cache.
lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t sel_addr =
argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
- // Figure out the class this is being dispatched to and see if we've already
- // cached this method call,
- // If so we can push a run-to-address plan directly. Otherwise we have to
- // figure out where
- // the implementation lives.
+ // Figure out the class this is being dispatched to and see if
+ // we've already cached this method call, If so we can push a
+ // run-to-address plan directly. Otherwise we have to figure out
+ // where the implementation lives.
if (this_dispatch.is_super) {
if (this_dispatch.is_super2) {
- // In the objc_msgSendSuper2 case, we don't get the object directly, we
- // get a structure containing
- // the object and the class to which the super message is being sent.
- // So we need to dig the super
- // out of the class and use that.
+ // In the objc_msgSendSuper2 case, we don't get the object
+ // directly, we get a structure containing the object and the
+ // class to which the super message is being sent. So we need
+ // to dig the super out of the class and use that.
Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
super_value.GetScalar() += process->GetAddressByteSize();
@@ -984,11 +987,11 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
log->Printf("Failed to extract the class value from objc_super.");
}
} else {
- // In the objc_msgSendSuper case, we don't get the object directly, we
- // get a two element structure containing
- // the object and the super class to which the super message is being
- // sent. So the class we want is
- // the second element of this structure.
+ // In the objc_msgSendSuper case, we don't get the object
+ // directly, we get a two element structure containing the
+ // object and the super class to which the super message is
+ // being sent. So the class we want is the second element of
+ // this structure.
Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
super_value.GetScalar() += process->GetAddressByteSize();
@@ -1009,9 +1012,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
// making the object value a load address value and resolving it will get
// the pointer sized data pointed to by that value...
- // Note, it isn't a fatal error not to be able to get the address from the
- // object, since this might
- // be a "tagged pointer" which isn't a real object, but rather some word
+ // Note, it isn't a fatal error not to be able to get the
+ // address from the object, since this might be a "tagged
+ // pointer" which isn't a real object, but rather some word
// length encoded dingus.
Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
@@ -1126,9 +1129,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
dispatch_values.PushValue(flag_value);
- // The step through code might have to fill in the cache, so it is not
- // safe to run only one thread.
- // So we override the stop_others value passed in to us here:
+ // The step through code might have to fill in the cache, so it
+ // is not safe to run only one thread. So we override the
+ // stop_others value passed in to us here:
const bool trampoline_stop_others = false;
ret_plan_sp.reset(new AppleThreadPlanStepThroughObjCTrampoline(
thread, this, dispatch_values, isa_addr, sel_addr,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index 316115b0dcb1..9bb1a4e0ee42 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -105,10 +105,9 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
return clang::QualType();
std::string name(ReadStructName(type));
- // We do not handle templated classes/structs at the moment.
- // If the name has a < in it, we are going to abandon this.
- // We're still obliged to parse it, so we just set a flag that
- // means "Don't actually build anything."
+ // We do not handle templated classes/structs at the moment. If the name has
+ // a < in it, we are going to abandon this. We're still obliged to parse it,
+ // so we just set a flag that means "Don't actually build anything."
const bool is_templated = name.find('<') != std::string::npos;
@@ -180,11 +179,9 @@ AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx,
// the runtime can emit these in the form of @"SomeType", giving more specifics
// this would be interesting for expression parser interop, but since we
-// actually try
-// to avoid exposing the ivar info to the expression evaluator, consume but
-// ignore the type info
-// and always return an 'id'; if anything, dynamic typing will resolve things
-// for us anyway
+// actually try to avoid exposing the ivar info to the expression evaluator,
+// consume but ignore the type info and always return an 'id'; if anything,
+// dynamic typing will resolve things for us anyway
clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type,
bool for_expression) {
@@ -197,24 +194,21 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
// We have to be careful here. We're used to seeing
// @"NSString"
// but in records it is possible that the string following an @ is the name
- // of the next field and @ means "id".
- // This is the case if anything unquoted except for "}", the end of the
- // type, or another name follows the quoted string.
+ // of the next field and @ means "id". This is the case if anything
+ // unquoted except for "}", the end of the type, or another name follows
+ // the quoted string.
//
// E.g.
// - @"NSString"@ means "id, followed by a field named NSString of type id"
- // - @"NSString"} means "a pointer to NSString and the end of the struct"
- // - @"NSString""nextField" means "a pointer to NSString and a field named
- // nextField"
- // - @"NSString" followed by the end of the string means "a pointer to
- // NSString"
+ // - @"NSString"} means "a pointer to NSString and the end of the struct" -
+ // @"NSString""nextField" means "a pointer to NSString and a field named
+ // nextField" - @"NSString" followed by the end of the string means "a
+ // pointer to NSString"
//
// As a result, the rule is: If we see @ followed by a quoted string, we
- // peek.
- // - If we see }, ), ], the end of the string, or a quote ("), the quoted
- // string is a class name.
- // - If we see anything else, the quoted string is a field name and we push
- // it back onto type.
+ // peek. - If we see }, ), ], the end of the string, or a quote ("), the
+ // quoted string is a class name. - If we see anything else, the quoted
+ // string is a field name and we push it back onto type.
name = ReadQuotedString(type);
@@ -260,9 +254,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
decl_vendor->FindDecls(ConstString(name), append, max_matches, decls);
// The user can forward-declare something that has no definition. The runtime
-// doesn't prohibit this at all.
-// This is a rare and very weird case. We keep this assert in debug builds so
-// we catch other weird cases.
+// doesn't prohibit this at all. This is a rare and very weird case. We keep
+// this assert in debug builds so we catch other weird cases.
#ifdef LLDB_CONFIGURATION_DEBUG
assert(num_types);
#else
@@ -315,8 +308,8 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
// if (!lldb_ctx)
// return clang::QualType();
// return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
- // which uses one of the constants if one is available, but we don't think all
- // this work is necessary.
+ // which uses one of the constants if one is available, but we don't think
+ // all this work is necessary.
case 'q':
return ast_ctx.LongLongTy;
case 'C':
@@ -364,11 +357,10 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
case '^': {
if (!for_expression && type.NextIf('?')) {
// if we are not supporting the concept of unknownAny, but what is being
- // created here is an unknownAny*, then
- // we can just get away with a void*
+ // created here is an unknownAny*, then we can just get away with a void*
// this is theoretically wrong (in the same sense as 'theoretically
- // nothing exists') but is way better than outright failure
- // in many practical cases
+ // nothing exists') but is way better than outright failure in many
+ // practical cases
return ast_ctx.VoidPtrTy;
} else {
clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index a295d1b4ce76..75b670739427 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -52,8 +52,8 @@ AppleThreadPlanStepThroughObjCTrampoline::
void AppleThreadPlanStepThroughObjCTrampoline::DidPush() {
// Setting up the memory space for the called function text might require
- // allocations,
- // i.e. a nested function call. This needs to be done as a PreResumeAction.
+ // allocations, i.e. a nested function call. This needs to be done as a
+ // PreResumeAction.
m_thread.GetProcess()->AddPreResumeAction(PreResumeInitializeFunctionCaller,
(void *)this);
}
@@ -110,8 +110,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop(
Event *event_ptr) {
// If we get asked to explain the stop it will be because something went
// wrong (like the implementation for selector function crashed... We're
- // going
- // to figure out what to do about that, so we do explain the stop.
+ // going to figure out what to do about that, so we do explain the stop.
return true;
}
@@ -135,8 +134,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
}
// Second stage, if all went well with the function calling, then fetch the
- // target address, and
- // queue up a "run to that address" plan.
+ // target address, and queue up a "run to that address" plan.
if (!m_run_to_sp) {
Value target_addr_value;
ExecutionContext exc_ctx;
@@ -201,8 +199,8 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
return false;
}
-// The base class MischiefManaged does some cleanup - so you have to call it
-// in your MischiefManaged derived class.
+// The base class MischiefManaged does some cleanup - so you have to call it in
+// your MischiefManaged derived class.
bool AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged() {
if (IsPlanComplete())
return true;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
index 654ac9abfcab..cbbc35f1c08a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
@@ -38,14 +38,12 @@ using namespace lldb_renderscript;
// [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang),
// the compiler frontend for RenderScript embeds an ARM specific triple in IR
-// that is shipped in the app, after
-// generating IR that has some assumptions that an ARM device is the target.
-// As the IR is then compiled on a device of unknown (at time the IR was
-// generated at least) architecture,
-// when calling RenderScript API function as part of debugger expressions, we
-// have to perform a fixup pass that
-// removes those assumptions right before the module is sent to be generated by
-// the llvm backend.
+// that is shipped in the app, after generating IR that has some assumptions
+// that an ARM device is the target. As the IR is then compiled on a device of
+// unknown (at time the IR was generated at least) architecture, when calling
+// RenderScript API function as part of debugger expressions, we have to
+// perform a fixup pass that removes those assumptions right before the module
+// is sent to be generated by the llvm backend.
namespace {
bool registerRSDefaultTargetOpts(clang::TargetOptions &proto,
@@ -107,10 +105,9 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
case llvm::Triple::ArchType::x86:
changed_module |= fixupX86FunctionCalls(module);
// For some reason this triple gets totally missed by the backend, and must
- // be set manually.
- // There a reference in bcc/Main.cpp about auto feature-detection being
- // removed from LLVM3.5, but I can't
- // see that discussion anywhere public.
+ // be set manually. There a reference in bcc/Main.cpp about auto feature-
+ // detection being removed from LLVM3.5, but I can't see that discussion
+ // anywhere public.
real_triple = "i686--linux-android";
break;
case llvm::Triple::ArchType::x86_64:
@@ -118,12 +115,12 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
break;
case llvm::Triple::ArchType::mipsel:
case llvm::Triple::ArchType::mips64el:
- // No actual IR fixup pass is needed on MIPS, but the datalayout
- // and targetmachine do need to be explicitly set.
+ // No actual IR fixup pass is needed on MIPS, but the datalayout and
+ // targetmachine do need to be explicitly set.
- // bcc explicitly compiles MIPS code to use the static relocation
- // model due to an issue with relocations in mclinker.
- // see libbcc/support/CompilerConfig.cpp for details
+ // bcc explicitly compiles MIPS code to use the static relocation model due
+ // to an issue with relocations in mclinker. see
+ // libbcc/support/CompilerConfig.cpp for details
reloc_model = llvm::Reloc::Static;
changed_module = true;
break;
@@ -146,8 +143,7 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
assert(target_machine &&
"failed to identify RenderScriptRuntime target machine");
// We've been using a triple and datalayout of some ARM variant all along,
- // so
- // we need to let the backend know that this is no longer the case.
+ // so we need to let the backend know that this is no longer the case.
if (log) {
log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__,
real_triple.str().c_str());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index ad1083be0285..4eb15369aa1e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -26,7 +26,6 @@
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -40,6 +39,7 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
@@ -312,7 +312,8 @@ bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
Status err;
- // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space)
+ // find offset to arguments on the stack (+16 to skip over a0-a3 shadow
+ // space)
uint64_t sp = ctx.reg_ctx->GetSP() + 16;
for (size_t i = 0; i < num_args; ++i) {
@@ -447,12 +448,11 @@ bool IsRenderScriptScriptModule(ModuleSP module) {
}
bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) {
- // takes an argument of the form 'num[,num][,num]'.
- // Where 'coord_s' is a comma separated 1,2 or 3-dimensional coordinate
- // with the whitespace trimmed.
- // Missing coordinates are defaulted to zero.
- // If parsing of any elements fails the contents of &coord are undefined
- // and `false` is returned, `true` otherwise
+ // takes an argument of the form 'num[,num][,num]'. Where 'coord_s' is a
+ // comma separated 1,2 or 3-dimensional coordinate with the whitespace
+ // trimmed. Missing coordinates are defaulted to zero. If parsing of any
+ // elements fails the contents of &coord are undefined and `false` is
+ // returned, `true` otherwise
RegularExpression regex;
RegularExpression::Match regex_match(3);
@@ -593,7 +593,7 @@ struct RenderScriptRuntime::Element {
empirical_type<uint32_t> datum_size; // Size of a single Element with padding
empirical_type<uint32_t> padding; // Number of padding bytes
empirical_type<uint32_t>
- array_size; // Number of items in array, only needed for strucrs
+ array_size; // Number of items in array, only needed for structs
ConstString type_name; // Name of type, only needed for structs
static const ConstString &
@@ -633,8 +633,9 @@ struct RenderScriptRuntime::AllocationDetails {
// subelements, there may be more than one instance of the ElementHeader
// struct. With this first instance being the root element, and the other
// instances being the root's descendants. To identify which instances are an
- // ElementHeader's children, each struct is immediately followed by a sequence
- // of consecutive offsets to the start of its child structs. These offsets are
+ // ElementHeader's children, each struct is immediately followed by a
+ // sequence of consecutive offsets to the start of its child structs. These
+ // offsets are
// 4 bytes in size, and the 0 offset signifies no more children.
struct FileHeader {
uint8_t ident[4]; // ASCII 'RSAD' identifying the file
@@ -653,8 +654,8 @@ struct RenderScriptRuntime::AllocationDetails {
// Monotonically increasing from 1
static uint32_t ID;
- // Maps Allocation DataType enum and vector size to printable strings
- // using mapping from RenderScript numerical types summary documentation
+ // Maps Allocation DataType enum and vector size to printable strings using
+ // mapping from RenderScript numerical types summary documentation
static const char *RsDataTypeToString[][4];
// Maps Allocation DataKind enum to printable strings
@@ -844,11 +845,10 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter,
lldb_private::SymbolContext &context,
Address *, bool) {
// We need to have access to the list of reductions currently parsed, as
- // reduce names don't actually exist as
- // symbols in a module. They are only identifiable by parsing the .rs.info
- // packet, or finding the expand symbol. We
- // therefore need access to the list of parsed rs modules to properly resolve
- // reduction names.
+ // reduce names don't actually exist as symbols in a module. They are only
+ // identifiable by parsing the .rs.info packet, or finding the expand symbol.
+ // We therefore need access to the list of parsed rs modules to properly
+ // resolve reduction names.
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
ModuleSP module = context.module_sp;
@@ -967,8 +967,8 @@ Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback(
log->Printf("%s: Placed %sbreakpoint on %s", __FUNCTION__,
new_bp ? "new " : "", k.m_name.AsCString());
- // exit after placing the first breakpoint if we do not intend to stop
- // on all kernels making up this script group
+ // exit after placing the first breakpoint if we do not intend to stop on
+ // all kernels making up this script group
if (!m_stop_on_all)
break;
}
@@ -1684,8 +1684,8 @@ void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
const ModuleSP module = rsmodule_sp->m_module;
const FileSpec &file = module->GetPlatformFileSpec();
- // Iterate over all of the scripts that we currently know of.
- // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+ // Iterate over all of the scripts that we currently know of. Note: We cant
+ // push or pop to m_scripts here or it may invalidate rs_script.
for (const auto &rs_script : m_scripts) {
// Extract the expected .so file path for this script.
std::string shared_lib;
@@ -1825,9 +1825,9 @@ const char *JITTemplate(ExpressionStrings e) {
// rsaTypeGetNativeData(Context*, Type*, void* typeData, size) Pack the
// data in the following way mHal.state.dimX; mHal.state.dimY;
- // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement; into
- // typeData Need to specify 32 or 64 bit for uint_t since this differs
- // between devices
+ // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement;
+ // into typeData Need to specify 32 or 64 bit for uint_t since this
+ // differs between devices
JIT_TEMPLATE_CONTEXT
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX
@@ -1882,10 +1882,10 @@ const char *JITTemplate(ExpressionStrings e) {
}
} // end of the anonymous namespace
-// JITs the RS runtime for the internal data pointer of an allocation. Is passed
-// x,y,z coordinates for the pointer to a specific element. Then sets the
-// data_ptr member in Allocation with the result. Returns true on success, false
-// otherwise
+// JITs the RS runtime for the internal data pointer of an allocation. Is
+// passed x,y,z coordinates for the pointer to a specific element. Then sets
+// the data_ptr member in Allocation with the result. Returns true on success,
+// false otherwise
bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc,
StackFrame *frame_ptr, uint32_t x,
uint32_t y, uint32_t z) {
@@ -1961,8 +1961,8 @@ bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc,
}
// JITs the RS runtime for information about the dimensions and type of an
-// allocation Then sets dimension and element_ptr members in Allocation with the
-// result. Returns true on success, false otherwise
+// allocation Then sets dimension and element_ptr members in Allocation with
+// the result. Returns true on success, false otherwise
bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc,
StackFrame *frame_ptr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -2245,9 +2245,8 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc,
}
// JITs the RS runtime for information about the stride between rows in the
-// allocation. This is done to detect padding, since allocated memory is 16-byte
-// aligned.
-// Returns true on success, false otherwise
+// allocation. This is done to detect padding, since allocated memory is
+// 16-byte aligned. Returns true on success, false otherwise
bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc,
StackFrame *frame_ptr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -2313,9 +2312,8 @@ bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
}
// Function attempts to set the type_name member of the paramaterised Element
-// object.
-// This string should be the name of the struct type the Element represents.
-// We need this string for pretty printing the Element to users.
+// object. This string should be the name of the struct type the Element
+// represents. We need this string for pretty printing the Element to users.
void RenderScriptRuntime::FindStructTypeName(Element &elem,
StackFrame *frame_ptr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -2330,12 +2328,11 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
VariableList var_list;
for (auto module_sp : m_rsmodules)
module_sp->m_module->FindGlobalVariables(
- RegularExpression(llvm::StringRef(".")), true, UINT32_MAX, var_list);
+ RegularExpression(llvm::StringRef(".")), UINT32_MAX, var_list);
// Iterate over all the global variables looking for one with a matching type
- // to the Element.
- // We make the assumption a match exists since there needs to be a global
- // variable to reflect the struct type back into java host code.
+ // to the Element. We make the assumption a match exists since there needs to
+ // be a global variable to reflect the struct type back into java host code.
for (uint32_t i = 0; i < var_list.GetSize(); ++i) {
const VariableSP var_sp(var_list.GetVariableAtIndex(i));
if (!var_sp)
@@ -2347,15 +2344,14 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
// Find the number of variable fields.
// If it has no fields, or more fields than our Element, then it can't be
- // the struct we're looking for.
- // Don't check for equality since RS can add extra struct members for
- // padding.
+ // the struct we're looking for. Don't check for equality since RS can add
+ // extra struct members for padding.
size_t num_children = valobj_sp->GetNumChildren();
if (num_children > elem.children.size() || num_children == 0)
continue;
- // Iterate over children looking for members with matching field names.
- // If all the field names match, this is likely the struct we want.
+ // Iterate over children looking for members with matching field names. If
+ // all the field names match, this is likely the struct we want.
// TODO: This could be made more robust by also checking children data
// sizes, or array size
bool found = true;
@@ -2404,8 +2400,8 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
}
// Function sets the datum_size member of Element. Representing the size of a
-// single instance including padding.
-// Assumes the relevant allocation information has already been jitted.
+// single instance including padding. Assumes the relevant allocation
+// information has already been jitted.
void RenderScriptRuntime::SetElementSize(Element &elem) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
const Element::DataType type = *elem.type.get();
@@ -2446,9 +2442,9 @@ void RenderScriptRuntime::SetElementSize(Element &elem) {
data_size + padding);
}
-// Given an allocation, this function copies the allocation contents from device
-// into a buffer on the heap.
-// Returning a shared pointer to the buffer containing the data.
+// Given an allocation, this function copies the allocation contents from
+// device into a buffer on the heap. Returning a shared pointer to the buffer
+// containing the data.
std::shared_ptr<uint8_t>
RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
StackFrame *frame_ptr) {
@@ -2496,9 +2492,8 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
return buffer;
}
-// Function copies data from a binary file into an allocation.
-// There is a header at the start of the file, FileHeader, before the data
-// content itself.
+// Function copies data from a binary file into an allocation. There is a
+// header at the start of the file, FileHeader, before the data content itself.
// Information from this header is used to display warnings to the user about
// incompatibilities
bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
@@ -2630,7 +2625,8 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
// Calculate size of allocation data in file
size_t size = data_sp->GetByteSize() - file_header->hdr_size;
- // Check if the target allocation and file both have the same total data size.
+ // Check if the target allocation and file both have the same total data
+ // size.
const uint32_t alloc_size = *alloc->size.get();
if (alloc_size != size) {
strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
@@ -2660,15 +2656,15 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
// Function takes as parameters a byte buffer, which will eventually be written
// to file as the element header, an offset into that buffer, and an Element
-// that will be saved into the buffer at the parametrised offset.
-// Return value is the new offset after writing the element into the buffer.
-// Elements are saved to the file as the ElementHeader struct followed by
-// offsets to the structs of all the element's children.
+// that will be saved into the buffer at the parametrised offset. Return value
+// is the new offset after writing the element into the buffer. Elements are
+// saved to the file as the ElementHeader struct followed by offsets to the
+// structs of all the element's children.
size_t RenderScriptRuntime::PopulateElementHeaders(
const std::shared_ptr<uint8_t> header_buffer, size_t offset,
const Element &elem) {
- // File struct for an element header with all the relevant details copied from
- // elem. We assume members are valid already.
+ // File struct for an element header with all the relevant details copied
+ // from elem. We assume members are valid already.
AllocationDetails::ElementHeader elem_header;
elem_header.type = *elem.type.get();
elem_header.kind = *elem.type_kind.get();
@@ -2678,9 +2674,8 @@ size_t RenderScriptRuntime::PopulateElementHeaders(
elem.array_size.isValid() ? *elem.array_size.get() : 0;
const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
- // Copy struct into buffer and advance offset
- // We assume that header_buffer has been checked for nullptr before this
- // method is called
+ // Copy struct into buffer and advance offset We assume that header_buffer
+ // has been checked for nullptr before this method is called
memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
offset += elem_header_size;
@@ -2721,8 +2716,8 @@ size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
return size;
}
-// Function copies allocation contents into a binary file. This file can then be
-// loaded later into a different allocation. There is a header, FileHeader,
+// Function copies allocation contents into a binary file. This file can then
+// be loaded later into a different allocation. There is a header, FileHeader,
// before the allocation data containing meta-data.
bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
const char *path,
@@ -2852,8 +2847,8 @@ bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
if (module_sp) {
for (const auto &rs_module : m_rsmodules) {
if (rs_module->m_module == module_sp) {
- // Check if the user has enabled automatically breaking on
- // all RS kernels.
+ // Check if the user has enabled automatically breaking on all RS
+ // kernels.
if (m_breakAllKernels)
BreakOnModuleKernels(rs_module);
@@ -2975,11 +2970,10 @@ bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines,
size_t n_lines) {
// The list of reduction kernels in the `.rs.info` symbol is of the form
// "signature - accumulatordatasize - reduction_name - initializer_name -
- // accumulator_name - combiner_name -
- // outconverter_name - halter_name"
- // Where a function is not explicitly named by the user, or is not generated
- // by the compiler, it is named "." so the
- // dash separated list should always be 8 items long
+ // accumulator_name - combiner_name - outconverter_name - halter_name" Where
+ // a function is not explicitly named by the user, or is not generated by the
+ // compiler, it is named "." so the dash separated list should always be 8
+ // items long
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
// Skip the exportReduceCount line
++lines;
@@ -3069,8 +3063,7 @@ bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines,
}
// The .rs.info symbol in renderscript modules contains a string which needs to
-// be parsed.
-// The string is basic and is parsed on a line by line basis.
+// be parsed. The string is basic and is parsed on a line by line basis.
bool RSModuleDescriptor::ParseRSInfo() {
assert(m_module);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -3137,8 +3130,8 @@ bool RSModuleDescriptor::ParseRSInfo() {
const auto handler = rs_info_handler(key);
if (handler == -1)
continue;
- // getAsInteger returns `true` on an error condition - we're only interested
- // in numeric fields at the moment
+ // getAsInteger returns `true` on an error condition - we're only
+ // interested in numeric fields at the moment
uint64_t n_lines;
if (val.getAsInteger(10, n_lines)) {
LLDB_LOGV(log, "Failed to parse non-numeric '.rs.info' section {0}",
@@ -3213,9 +3206,8 @@ void RenderScriptRuntime::DumpContexts(Stream &strm) const {
std::map<addr_t, uint64_t> contextReferences;
- // Iterate over all of the currently discovered scripts.
- // Note: We cant push or pop from m_scripts inside this loop or it may
- // invalidate script.
+ // Iterate over all of the currently discovered scripts. Note: We cant push
+ // or pop from m_scripts inside this loop or it may invalidate script.
for (const auto &script : m_scripts) {
if (!script->context.isValid())
continue;
@@ -3393,15 +3385,15 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
if ((type == Element::RS_TYPE_NONE) &&
(alloc->element.children.size() > 0) &&
(alloc->element.type_name != Element::GetFallbackStructName())) {
- // Here we are dumping an Element of struct type.
- // This is done using expression evaluation with the name of the
- // struct type and pointer to element.
- // Don't print the name of the resulting expression, since this will
- // be '$[0-9]+'
+ // Here we are dumping an Element of struct type. This is done using
+ // expression evaluation with the name of the struct type and pointer
+ // to element. Don't print the name of the resulting expression,
+ // since this will be '$[0-9]+'
DumpValueObjectOptions expr_options;
expr_options.SetHideName(true);
- // Setup expression as derefrencing a pointer cast to element address.
+ // Setup expression as dereferencing a pointer cast to element
+ // address.
char expr_char_buffer[jit_max_expr_size];
int written =
snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
@@ -3435,9 +3427,9 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
return true;
}
-// Function recalculates all our cached information about allocations by jitting
-// the RS runtime regarding each allocation we know about. Returns true if all
-// allocations could be recomputed, false otherwise.
+// Function recalculates all our cached information about allocations by
+// jitting the RS runtime regarding each allocation we know about. Returns true
+// if all allocations could be recomputed, false otherwise.
bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
StackFrame *frame_ptr) {
bool success = true;
@@ -3601,8 +3593,8 @@ void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
}
}
-// Given the name of a kernel this function creates a breakpoint using our
-// own breakpoint resolver, and returns the Breakpoint shared pointer.
+// Given the name of a kernel this function creates a breakpoint using our own
+// breakpoint resolver, and returns the Breakpoint shared pointer.
BreakpointSP
RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) {
Log *log(
@@ -3743,8 +3735,8 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
log->Printf("%s - Found .expand function '%s'", __FUNCTION__,
func_name.GetCString());
- // Get values for variables in .expand frame that tell us the current kernel
- // invocation
+ // Get values for variables in .expand frame that tell us the current
+ // kernel invocation
uint64_t x, y, z;
bool found = GetFrameVarAsUnsigned(frame_sp, x_expr, x) &&
GetFrameVarAsUnsigned(frame_sp, y_expr, y) &&
@@ -3765,12 +3757,11 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
// Callback when a kernel breakpoint hits and we're looking for a specific
// coordinate. Baton parameter contains a pointer to the target coordinate we
-// want to break on.
-// Function then checks the .expand frame for the current coordinate and breaks
-// to user if it matches.
-// Parameter 'break_id' is the id of the Breakpoint which made the callback.
-// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
-// a single logical breakpoint can have multiple addresses.
+// want to break on. Function then checks the .expand frame for the current
+// coordinate and breaks to user if it matches. Parameter 'break_id' is the id
+// of the Breakpoint which made the callback. Parameter 'break_loc_id' is the
+// id for the BreakpointLocation which was hit, a single logical breakpoint can
+// have multiple addresses.
bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
StoppointCallbackContext *ctx,
user_id_t break_id,
@@ -3845,12 +3836,10 @@ void RenderScriptRuntime::SetConditional(BreakpointSP bp, Stream &messages,
m_conditional_breaks[bp->GetID()] = std::unique_ptr<RSCoordinate>(baton);
}
-// Tries to set a breakpoint on the start of a kernel, resolved using the kernel
-// name. Argument 'coords', represents a three dimensional coordinate which can
-// be
-// used to specify a single kernel instance to break on. If this is set then we
-// add a callback
-// to the breakpoint.
+// Tries to set a breakpoint on the start of a kernel, resolved using the
+// kernel name. Argument 'coords', represents a three dimensional coordinate
+// which can be used to specify a single kernel instance to break on. If this
+// is set then we add a callback to the breakpoint.
bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target,
Stream &messages,
const char *name,
@@ -4076,7 +4065,7 @@ void RSModuleDescriptor::Dump(Stream &strm) const {
void RSGlobalDescriptor::Dump(Stream &strm) const {
strm.Indent(m_name.AsCString());
VariableList var_list;
- m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
+ m_module->m_module->FindGlobalVariables(m_name, nullptr, 1U, var_list);
if (var_list.GetSize() == 1) {
auto var = var_list.GetVariableAtIndex(0);
auto type = var->GetType();
@@ -4270,8 +4259,8 @@ public:
};
// Matching a comma separated list of known words is fairly
- // straightforward with PCRE, but we're
- // using ERE, so we end up with a little ugliness...
+ // straightforward with PCRE, but we're using ERE, so we end up with a
+ // little ugliness...
RegularExpression::Match match(/* max_matches */ 5);
RegularExpression match_type_list(
llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$"));
@@ -4661,7 +4650,7 @@ public:
switch (short_option) {
case 'f':
- m_outfile.SetFile(option_arg, true);
+ m_outfile.SetFile(option_arg, true, FileSpec::Style::native);
if (m_outfile.Exists()) {
m_outfile.Clear();
err.SetErrorStringWithFormat("file already exists: '%s'",
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
index fe4ae21a0c39..7786d686ad6a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
@@ -10,7 +10,6 @@
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -20,6 +19,7 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index 439d372fadeb..e1f8ea648414 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -46,18 +46,15 @@ bool isRSAPICall(llvm::Module &module, llvm::CallInst *call_inst) {
bool isRSLargeReturnCall(llvm::Module &module, llvm::CallInst *call_inst) {
// i686 and x86_64 returns for large vectors in the RenderScript API are not
- // handled as normal
- // register pairs, but as a hidden sret type. This is not reflected in the
- // debug info or mangled
- // symbol name, and the android ABI for x86 and x86_64, (as well as the
- // emulators) specifies there is
- // no AVX, so bcc generates an sret function because we cannot natively return
+ // handled as normal register pairs, but as a hidden sret type. This is not
+ // reflected in the debug info or mangled symbol name, and the android ABI
+ // for x86 and x86_64, (as well as the emulators) specifies there is no AVX,
+ // so bcc generates an sret function because we cannot natively return
// 256 bit vectors.
// This function simply checks whether a function has a > 128bit return type.
- // It is perhaps an
- // unreliable heuristic, and relies on bcc not generating AVX code, so if the
- // android ABI one day
- // provides for AVX, this function may go out of fashion.
+ // It is perhaps an unreliable heuristic, and relies on bcc not generating
+ // AVX code, so if the android ABI one day provides for AVX, this function
+ // may go out of fashion.
(void)module;
if (!call_inst || !call_inst->getCalledFunction())
return false;
@@ -88,12 +85,11 @@ bool isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst) {
llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
// on x86 StructReturn functions return a pointer to the return value, rather
- // than the return
- // value itself [ref](http://www.agner.org/optimize/calling_conventions.pdf
- // section 6).
- // We create a return type by getting the pointer type of the old return type,
- // and inserting a new
- // initial argument of pointer type of the original return type.
+ // than the return value itself
+ // [ref](http://www.agner.org/optimize/calling_conventions.pdf section 6). We
+ // create a return type by getting the pointer type of the old return type,
+ // and inserting a new initial argument of pointer type of the original
+ // return type.
Log *log(
GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
@@ -112,8 +108,7 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
orig_type->param_end()};
// This may not work if the function is somehow declared void as llvm is
- // strongly typed
- // and represents void* with i8*
+ // strongly typed and represents void* with i8*
assert(!orig_type->getReturnType()->isVoidTy() &&
"Cannot add StructRet attribute to void function");
llvm::PointerType *return_type_ptr_type =
@@ -126,8 +121,8 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
if (log)
log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n",
__FUNCTION__, (void *)return_type_ptr_type);
- // put the the sret pointer argument in place at the beginning of the argument
- // list.
+ // put the sret pointer argument in place at the beginning of the
+ // argument list.
params.emplace(params.begin(), return_type_ptr_type);
assert(params.size() == num_params + 1);
return llvm::FunctionType::get(return_type_ptr_type, params,
@@ -157,11 +152,9 @@ bool findRSCallSites(llvm::Module &module,
bool fixupX86StructRetCalls(llvm::Module &module) {
bool changed = false;
- // changing a basic block while iterating over it seems to have some undefined
- // behaviour
- // going on so we find all RS callsites first, then fix them up after
- // consuming
- // the iterator.
+ // changing a basic block while iterating over it seems to have some
+ // undefined behaviour going on so we find all RS callsites first, then fix
+ // them up after consuming the iterator.
std::set<llvm::CallInst *> rs_callsites;
if (!findRSCallSites(module, rs_callsites, isRSLargeReturnCall))
return false;
@@ -180,8 +173,7 @@ bool fixupX86StructRetCalls(llvm::Module &module) {
// Allocate enough space to store the return value of the original function
// we pass a pointer to this allocation as the StructRet param, and then
- // copy its
- // value into the lldb return value
+ // copy its value into the lldb return value
const llvm::DataLayout &DL = module.getDataLayout();
llvm::AllocaInst *return_value_alloc = new llvm::AllocaInst(
func->getReturnType(), DL.getAllocaAddrSpace(), "var_vector_return_alloc",
@@ -222,19 +214,15 @@ bool fixupX86StructRetCalls(llvm::Module &module) {
bool fixupRSAllocationStructByValCalls(llvm::Module &module) {
// On x86_64, calls to functions in the RS runtime that take an
- // `rs_allocation` type argument
- // are actually handled as by-ref params by bcc, but appear to be passed by
- // value by lldb (the callsite all use
- // `struct byval`).
- // On x86_64 Linux, struct arguments are transferred in registers if the
- // struct size is no bigger than
- // 128bits [ref](http://www.agner.org/optimize/calling_conventions.pdf)
- // section 7.1 "Passing and returning objects"
- // otherwise passed on the stack.
- // an object of type `rs_allocation` is actually 256bits, so should be passed
- // on the stack. However, code generated
- // by bcc actually treats formal params of type `rs_allocation` as
- // `rs_allocation *` so we need to convert the
+ // `rs_allocation` type argument are actually handled as by-ref params by
+ // bcc, but appear to be passed by value by lldb (the callsite all use
+ // `struct byval`). On x86_64 Linux, struct arguments are transferred in
+ // registers if the struct size is no bigger than 128bits
+ // [ref](http://www.agner.org/optimize/calling_conventions.pdf) section 7.1
+ // "Passing and returning objects" otherwise passed on the stack. an object
+ // of type `rs_allocation` is actually 256bits, so should be passed on the
+ // stack. However, code generated by bcc actually treats formal params of
+ // type `rs_allocation` as `rs_allocation *` so we need to convert the
// calling convention to pass by reference, and remove any hint of byval from
// formal parameters.
bool changed = false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index d7bef836d9d8..275f1fa2f70b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -89,9 +89,9 @@ ObjectContainerBSDArchive::Object::Extract(const DataExtractor &data,
str.assign((const char *)data.GetData(&offset, 16), 16);
if (str.find("#1/") == 0) {
- // If the name is longer than 16 bytes, or contains an embedded space
- // then it will use this format where the length of the name is
- // here and the name characters are after this header.
+ // If the name is longer than 16 bytes, or contains an embedded space then
+ // it will use this format where the length of the name is here and the
+ // name characters are after this header.
ar_name_len = strtoul(str.c_str() + 3, &err, 10);
} else {
// Strip off any trailing spaces.
@@ -203,8 +203,8 @@ ObjectContainerBSDArchive::Archive::FindCachedArchive(
shared_ptr archive_sp;
Archive::Map &archive_map = Archive::GetArchiveCache();
Archive::Map::iterator pos = archive_map.find(file);
- // Don't cache a value for "archive_map.end()" below since we might
- // delete an archive entry...
+ // Don't cache a value for "archive_map.end()" below since we might delete an
+ // archive entry...
while (pos != archive_map.end() && pos->first == file) {
bool match = true;
if (arch.IsValid() &&
@@ -217,14 +217,13 @@ ObjectContainerBSDArchive::Archive::FindCachedArchive(
if (pos->second->GetModificationTime() == time) {
return pos->second;
} else {
- // We have a file at the same path with the same architecture
- // whose modification time doesn't match. It doesn't make sense
- // for us to continue to use this BSD archive since we cache only
- // the object info which consists of file time info and also the
- // file offset and file size of any contained objects. Since
- // this information is now out of date, we won't get the correct
- // information if we go and extract the file data, so we should
- // remove the old and outdated entry.
+ // We have a file at the same path with the same architecture whose
+ // modification time doesn't match. It doesn't make sense for us to
+ // continue to use this BSD archive since we cache only the object info
+ // which consists of file time info and also the file offset and file
+ // size of any contained objects. Since this information is now out of
+ // date, we won't get the correct information if we go and extract the
+ // file data, so we should remove the old and outdated entry.
archive_map.erase(pos);
pos = archive_map.find(file);
continue; // Continue to next iteration so we don't increment pos
@@ -295,9 +294,9 @@ ObjectContainer *ObjectContainerBSDArchive::CreateInstance(
return nullptr;
if (data_sp) {
- // We have data, which means this is the first 512 bytes of the file
- // Check to see if the magic bytes match and if they do, read the entire
- // table of contents for the archive and cache it
+ // We have data, which means this is the first 512 bytes of the file Check
+ // to see if the magic bytes match and if they do, read the entire table of
+ // contents for the archive and cache it
DataExtractor data;
data.SetData(data_sp, data_offset, length);
if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) {
@@ -389,8 +388,8 @@ bool ObjectContainerBSDArchive::ParseHeader() {
m_file, module_sp->GetArchitecture(),
module_sp->GetModificationTime(), m_offset, m_data);
}
- // Clear the m_data that contains the entire archive
- // data and let our m_archive_sp hold onto the data.
+ // Clear the m_data that contains the entire archive data and let our
+ // m_archive_sp hold onto the data.
m_data.Clear();
}
}
@@ -453,9 +452,9 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications(
lldb::offset_t data_offset, lldb::offset_t file_offset,
lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) {
- // We have data, which means this is the first 512 bytes of the file
- // Check to see if the magic bytes match and if they do, read the entire
- // table of contents for the archive and cache it
+ // We have data, which means this is the first 512 bytes of the file Check to
+ // see if the magic bytes match and if they do, read the entire table of
+ // contents for the archive and cache it
DataExtractor data;
data.SetData(data_sp, data_offset, data_sp->GetByteSize());
if (!file || !data_sp || !ObjectContainerBSDArchive::MagicBytesMatch(data))
@@ -505,8 +504,8 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications(
const size_t end_count = specs.GetSize();
size_t num_specs_added = end_count - initial_count;
if (set_archive_arch && num_specs_added > 0) {
- // The archive was created but we didn't have an architecture
- // so we need to set it
+ // The archive was created but we didn't have an architecture so we need to
+ // set it
for (size_t i = initial_count; i < end_count; ++i) {
ModuleSpec module_spec;
if (specs.GetModuleSpecAtIndex(i, module_spec)) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index 39ea49208700..16cbb6e5753b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -140,13 +140,12 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data,
if (data.GetU32(offset, &e_flags, 1) == NULL)
return false;
- // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
- // e_shstrndx.
+ // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
if (data.GetU16(offset, &e_ehsize, 6) == NULL)
return false;
- // Initialize e_phnum, e_shnum, and e_shstrndx with the values
- // read from the header.
+ // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
+ // header.
e_phnum = e_phnum_hdr;
e_shnum = e_shnum_hdr;
e_shstrndx = e_shstrndx_hdr;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
index 4e2d3155ebb9..faaf8be99d68 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -8,14 +8,14 @@
//===----------------------------------------------------------------------===//
//
/// @file
-/// @brief Generic structures and typedefs for ELF files.
+/// Generic structures and typedefs for ELF files.
///
/// This file provides definitions for the various entities comprising an ELF
/// file. The structures are generic in the sense that they do not correspond
/// to the exact binary layout of an ELF, but can be used to hold the
/// information present in both 32 and 64 bit variants of the format. Each
-/// entity provides a \c Parse method which is capable of transparently reading
-/// both 32 and 64 bit instances of the object.
+/// entity provides a \c Parse method which is capable of transparently
+/// reading both 32 and 64 bit instances of the object.
//===----------------------------------------------------------------------===//
#ifndef liblldb_ELFHeader_h_
@@ -35,8 +35,9 @@ namespace elf {
//------------------------------------------------------------------------------
/// @name ELF type definitions.
///
-/// Types used to represent the various components of ELF structures. All types
-/// are signed or unsigned integral types wide enough to hold values from both
+/// Types used to represent the various components of ELF structures. All
+/// types are signed or unsigned integral types wide enough to hold values
+/// from both
/// 32 and 64 bit ELF variants.
//@{
typedef uint64_t elf_addr;
@@ -51,10 +52,10 @@ typedef int64_t elf_sxword;
//------------------------------------------------------------------------------
/// @class ELFHeader
-/// @brief Generic representation of an ELF file header.
+/// Generic representation of an ELF file header.
///
-/// This object is used to identify the general attributes on an ELF file and to
-/// locate additional sections within the file.
+/// This object is used to identify the general attributes on an ELF file and
+/// to locate additional sections within the file.
struct ELFHeader {
unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification.
elf_addr e_entry; ///< Virtual address program entry point.
@@ -118,9 +119,9 @@ struct ELFHeader {
bool HasHeaderExtension() const;
//--------------------------------------------------------------------------
- /// Parse an ELFHeader entry starting at position \p offset and
- /// update the data extractor with the address size and byte order
- /// attributes as defined by the header.
+ /// Parse an ELFHeader entry starting at position \p offset and update the
+ /// data extractor with the address size and byte order attributes as
+ /// defined by the header.
///
/// @param[in,out] data
/// The DataExtractor to read from. Updated with the address size and
@@ -157,8 +158,8 @@ struct ELFHeader {
private:
//--------------------------------------------------------------------------
- /// Parse an ELFHeader header extension entry. This method is called
- /// by Parse().
+ /// Parse an ELFHeader header extension entry. This method is called by
+ /// Parse().
///
/// @param[in] data
/// The DataExtractor to read from.
@@ -167,7 +168,7 @@ private:
//------------------------------------------------------------------------------
/// @class ELFSectionHeader
-/// @brief Generic representation of an ELF section header.
+/// Generic representation of an ELF section header.
struct ELFSectionHeader {
elf_word sh_name; ///< Section name string index.
elf_word sh_type; ///< Section type.
@@ -202,7 +203,7 @@ struct ELFSectionHeader {
//------------------------------------------------------------------------------
/// @class ELFProgramHeader
-/// @brief Generic representation of an ELF program header.
+/// Generic representation of an ELF program header.
struct ELFProgramHeader {
elf_word p_type; ///< Type of program segment.
elf_word p_flags; ///< Segment attributes.
@@ -235,7 +236,7 @@ struct ELFProgramHeader {
//------------------------------------------------------------------------------
/// @class ELFSymbol
-/// @brief Represents a symbol within an ELF symbol table.
+/// Represents a symbol within an ELF symbol table.
struct ELFSymbol {
elf_addr st_value; ///< Absolute or relocatable address.
elf_xword st_size; ///< Size of the symbol or zero.
@@ -288,7 +289,7 @@ struct ELFSymbol {
//------------------------------------------------------------------------------
/// @class ELFDynamic
-/// @brief Represents an entry in an ELF dynamic table.
+/// Represents an entry in an ELF dynamic table.
struct ELFDynamic {
elf_sxword d_tag; ///< Type of dynamic table entry.
union {
@@ -318,7 +319,7 @@ struct ELFDynamic {
//------------------------------------------------------------------------------
/// @class ELFRel
-/// @brief Represents a relocation entry with an implicit addend.
+/// Represents a relocation entry with an implicit addend.
struct ELFRel {
elf_addr r_offset; ///< Address of reference.
elf_xword r_info; ///< symbol index and type of relocation.
@@ -360,7 +361,7 @@ struct ELFRel {
//------------------------------------------------------------------------------
/// @class ELFRela
-/// @brief Represents a relocation entry with an explicit addend.
+/// Represents a relocation entry with an explicit addend.
struct ELFRela {
elf_addr r_offset; ///< Address of reference.
elf_xword r_info; ///< Symbol index and type of relocation.
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 36027dde0432..8701908378f1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -113,7 +113,7 @@ const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
-/// @brief Generic wrapper for ELFRel and ELFRela.
+/// Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
@@ -240,11 +240,10 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
if (data.GetU32(offset, &n_namesz, 3) == NULL)
return false;
- // The name field is required to be nul-terminated, and n_namesz
- // includes the terminating nul in observed implementations (contrary
- // to the ELF-64 spec). A special case is needed for cores generated
- // by some older Linux versions, which write a note named "CORE"
- // without a nul terminator and n_namesz = 4.
+ // The name field is required to be nul-terminated, and n_namesz includes the
+ // terminating nul in observed implementations (contrary to the ELF-64 spec).
+ // A special case is needed for cores generated by some older Linux versions,
+ // which write a note named "CORE" without a nul terminator and n_namesz = 4.
if (n_namesz == 4) {
char buf[4];
if (data.ExtractBytes(*offset, 4, data.GetByteOrder(), buf) != 4)
@@ -295,7 +294,8 @@ static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
uint32_t fileclass = header.e_ident[EI_CLASS];
- // If there aren't any elf flags available (e.g core elf file) then return default
+ // If there aren't any elf flags available (e.g core elf file) then return
+ // default
// 32 or 64 bit arch (without any architecture revision) based on object file's class.
if (header.e_type == ET_CORE) {
switch (fileclass) {
@@ -549,8 +549,8 @@ uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
DataExtractor segment_data;
if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
- // The ELF program header contained incorrect data,
- // probably corefile is incomplete or corrupted.
+ // The ELF program header contained incorrect data, probably corefile
+ // is incomplete or corrupted.
break;
}
@@ -595,8 +595,8 @@ static const char *OSABIAsCString(unsigned char osabi_byte) {
//
// WARNING : This function is being deprecated
-// It's functionality has moved to ArchSpec::SetArchitecture
-// This function is only being kept to validate the move.
+// It's functionality has moved to ArchSpec::SetArchitecture This function is
+// only being kept to validate the move.
//
// TODO : Remove this function
static bool GetOsFromOSABI(unsigned char osabi_byte,
@@ -674,29 +674,16 @@ size_t ObjectFileELF::GetModuleSpecifications(
__FUNCTION__, file.GetPath().c_str());
}
- // In case there is header extension in the section #0, the header
- // we parsed above could have sentinel values for e_phnum, e_shnum,
- // and e_shstrndx. In this case we need to reparse the header
- // with a bigger data source to get the actual values.
- size_t section_header_end = header.e_shoff + header.e_shentsize;
- if (header.HasHeaderExtension() &&
- section_header_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, section_header_end, file_offset);
- if (data_sp) {
- data.SetData(data_sp);
- lldb::offset_t header_offset = data_offset;
- header.Parse(data, &header_offset);
- }
- }
-
- // Try to get the UUID from the section list. Usually that's at the
- // end, so map the file in if we don't have it already.
- section_header_end =
- header.e_shoff + header.e_shnum * header.e_shentsize;
- if (section_header_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, section_header_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
+ data_sp = MapFileData(file, -1, file_offset);
+ if (data_sp)
+ data.SetData(data_sp);
+ // In case there is header extension in the section #0, the header we
+ // parsed above could have sentinel values for e_phnum, e_shnum, and
+ // e_shstrndx. In this case we need to reparse the header with a
+ // bigger data source to get the actual values.
+ if (header.HasHeaderExtension()) {
+ lldb::offset_t header_offset = data_offset;
+ header.Parse(data, &header_offset);
}
uint32_t gnu_debuglink_crc = 0;
@@ -733,51 +720,27 @@ size_t ObjectFileELF::GetModuleSpecifications(
// contents crc32 would be too much of luxury. Thus we will need
// to fallback to something simpler.
if (header.e_type == llvm::ELF::ET_CORE) {
- size_t program_headers_end =
- header.e_phoff + header.e_phnum * header.e_phentsize;
- if (program_headers_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, program_headers_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
- }
ProgramHeaderColl program_headers;
GetProgramHeaderInfo(program_headers, data, header);
- size_t segment_data_end = 0;
- for (ProgramHeaderCollConstIter I = program_headers.begin();
- I != program_headers.end(); ++I) {
- segment_data_end = std::max<unsigned long long>(
- I->p_offset + I->p_filesz, segment_data_end);
- }
-
- if (segment_data_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, segment_data_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
- }
-
core_notes_crc =
CalculateELFNotesSegmentsCRC32(program_headers, data);
} else {
- // Need to map entire file into memory to calculate the crc.
- data_sp = MapFileData(file, -1, file_offset);
- if (data_sp) {
- data.SetData(data_sp);
- gnu_debuglink_crc = calc_gnu_debuglink_crc32(
- data.GetDataStart(), data.GetByteSize());
- }
+ gnu_debuglink_crc = calc_gnu_debuglink_crc32(
+ data.GetDataStart(), data.GetByteSize());
}
}
+ using u32le = llvm::support::ulittle32_t;
if (gnu_debuglink_crc) {
// Use 4 bytes of crc from the .gnu_debuglink section.
- uint32_t uuidt[4] = {gnu_debuglink_crc, 0, 0, 0};
- uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data(gnu_debuglink_crc);
+ uuid = UUID::fromData(&data, sizeof(data));
} else if (core_notes_crc) {
// Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make
- // it look different form
- // .gnu_debuglink crc followed by 4 bytes of note segments crc.
- uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
- uuid.SetBytes(uuidt, sizeof(uuidt));
+ // it look different form .gnu_debuglink crc followed by 4 bytes
+ // of note segments crc.
+ u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
+ uuid = UUID::fromData(data, sizeof(data));
}
}
@@ -861,21 +824,19 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
+ // Iterate through the object file sections to find all of the sections
+ // that have SHF_ALLOC in their flag bits.
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->Test(SHF_ALLOC)) {
lldb::addr_t load_addr = section_sp->GetFileAddress();
// We don't want to update the load address of a section with type
// eSectionTypeAbsoluteAddress as they already have the absolute load
- // address
- // already specified
+ // address already specified
if (section_sp->GetType() != eSectionTypeAbsoluteAddress)
load_addr += value;
// On 32-bit systems the load address have to fit into 4 bytes. The
- // rest of
- // the bytes are the overflow from the addition.
+ // rest of the bytes are the overflow from the addition.
if (GetAddressByteSize() == 4)
load_addr &= 0xFFFFFFFF;
@@ -905,24 +866,23 @@ uint32_t ObjectFileELF::GetAddressByteSize() const {
AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
Symtab *symtab = GetSymtab();
if (!symtab)
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
- // The address class is determined based on the symtab. Ask it from the object
- // file what
- // contains the symtab information.
+ // The address class is determined based on the symtab. Ask it from the
+ // object file what contains the symtab information.
ObjectFile *symtab_objfile = symtab->GetObjectFile();
if (symtab_objfile != nullptr && symtab_objfile != this)
return symtab_objfile->GetAddressClass(file_addr);
auto res = ObjectFile::GetAddressClass(file_addr);
- if (res != eAddressClassCode)
+ if (res != AddressClass::eCode)
return res;
auto ub = m_address_class_map.upper_bound(file_addr);
if (ub == m_address_class_map.begin()) {
- // No entry in the address class map before the address. Return
- // default address class for an address in a code section.
- return eAddressClassCode;
+ // No entry in the address class map before the address. Return default
+ // address class for an address in a code section.
+ return AddressClass::eCode;
}
// Move iterator to the address class entry preceding address
@@ -950,6 +910,7 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
return false;
+ using u32le = llvm::support::ulittle32_t;
if (m_uuid.IsValid()) {
// We have the full build id uuid.
*uuid = m_uuid;
@@ -963,11 +924,11 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
if (core_notes_crc) {
- // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
- // look different form .gnu_debuglink crc - followed by 4 bytes of note
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look
+ // different form .gnu_debuglink crc - followed by 4 bytes of note
// segments crc.
- uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
- m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
+ m_uuid = UUID::fromData(data, sizeof(data));
}
} else {
if (!m_gnu_debuglink_crc)
@@ -975,8 +936,8 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
calc_gnu_debuglink_crc32(m_data.GetDataStart(), m_data.GetByteSize());
if (m_gnu_debuglink_crc) {
// Use 4 bytes of crc from the .gnu_debuglink section.
- uint32_t uuidt[4] = {m_gnu_debuglink_crc, 0, 0, 0};
- m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data(m_gnu_debuglink_crc);
+ m_uuid = UUID::fromData(&data, sizeof(data));
}
}
@@ -1034,8 +995,8 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
ELFDynamic &symbol = m_dynamic_symbols[i];
if (symbol.d_tag == DT_DEBUG) {
- // Compute the offset as the number of previous entries plus the
- // size of d_tag.
+ // Compute the offset as the number of previous entries plus the size of
+ // d_tag.
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
@@ -1314,18 +1275,16 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// Only bother processing this if we don't already have the uuid set.
if (!uuid.IsValid()) {
// 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a
- // build-id of a different
- // length. Accept it as long as it's at least 4 bytes as it will be
- // better than our own crc32.
- if (note.n_descsz >= 4 && note.n_descsz <= 20) {
- uint8_t uuidbuf[20];
- if (data.GetU8(&offset, &uuidbuf, note.n_descsz) == nullptr) {
+ // build-id of a different length. Accept it as long as it's at least
+ // 4 bytes as it will be better than our own crc32.
+ if (note.n_descsz >= 4) {
+ if (const uint8_t *buf = data.PeekData(offset, note.n_descsz)) {
+ // Save the build id as the UUID for the module.
+ uuid = UUID::fromData(buf, note.n_descsz);
+ } else {
error.SetErrorString("failed to read GNU_BUILD_ID note payload");
return error;
}
-
- // Save the build id as the UUID for the module.
- uuid.SetBytes(uuidbuf, note.n_descsz);
}
}
break;
@@ -1368,8 +1327,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
// TODO At some point the description string could be processed.
- // It could provide a steer towards the kalimba variant which
- // this ELF targets.
+ // It could provide a steer towards the kalimba variant which this ELF
+ // targets.
if (note.n_descsz) {
const char *cstr =
data.GetCStr(&offset, llvm::alignTo(note.n_descsz, 4));
@@ -1384,36 +1343,28 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// register info
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
} else if (note.n_name == LLDB_NT_OWNER_CORE) {
- // Parse the NT_FILE to look for stuff in paths to shared libraries
- // As the contents look like this in a 64 bit ELF core file:
- // count = 0x000000000000000a (10)
- // page_size = 0x0000000000001000 (4096)
- // Index start end file_ofs path
- // ===== ------------------ ------------------ ------------------
- // -------------------------------------
- // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000
- // /tmp/a.out
- // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000
- // /tmp/a.out
- // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001
- // /tmp/a.out
+ // Parse the NT_FILE to look for stuff in paths to shared libraries As
+ // the contents look like this in a 64 bit ELF core file: count =
+ // 0x000000000000000a (10) page_size = 0x0000000000001000 (4096) Index
+ // start end file_ofs path =====
+ // ------------------ ------------------ ------------------
+ // ------------------------------------- [ 0] 0x0000000000400000
+ // 0x0000000000401000 0x0000000000000000 /tmp/a.out [ 1]
+ // 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
+ // 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
// [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000
- // /lib/x86_64-linux-gnu/ld-2.19.so
- // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
- // /lib/x86_64-linux-gnu/ld-2.19.so
- // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023
- // /lib/x86_64-linux-gnu/ld-2.19.so
- // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
- // uint32_t
- // For reference: see readelf source code (in binutils).
+ // /lib/x86_64-linux-gnu/libc-2.19.so [ 4] 0x00007fa79cba8000
+ // 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-
+ // gnu/libc-2.19.so [ 5] 0x00007fa79cda7000 0x00007fa79cdab000
+ // 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so [ 6]
+ // 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64
+ // -linux-gnu/libc-2.19.so [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000
+ // 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so [ 8]
+ // 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64
+ // -linux-gnu/ld-2.19.so [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000
+ // 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so In the 32 bit ELFs
+ // the count, page_size, start, end, file_ofs are uint32_t For reference:
+ // see readelf source code (in binutils).
if (note.n_type == NT_FILE) {
uint64_t count = data.GetAddress(&offset);
const char *cstr;
@@ -1437,15 +1388,14 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
}
if (arch_spec.IsMIPS() &&
arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS)
- // In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing
- // for some cases (e.g. compile with -nostdlib)
- // Hence set OS to Linux
+ // In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing for some
+ // cases (e.g. compile with -nostdlib) Hence set OS to Linux
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
}
}
- // Calculate the offset of the next note just in case "offset" has been used
- // to poke at the contents of the note data
+ // Calculate the offset of the next note just in case "offset" has been
+ // used to poke at the contents of the note data
offset = note_offset + note.GetByteSize();
}
@@ -1545,13 +1495,12 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
header.e_ident[EI_OSABI]);
- // Validate if it is ok to remove GetOsFromOSABI.
- // Note, that now the OS is determined based on EI_OSABI flag and
- // the info extracted from ELF notes (see RefineModuleDetailsFromNote).
- // However in some cases that still might be not enough: for example
- // a shared library might not have any notes at all
- // and have EI_OSABI flag set to System V,
- // as result the OS will be set to UnknownOS.
+ // Validate if it is ok to remove GetOsFromOSABI. Note, that now the OS is
+ // determined based on EI_OSABI flag and the info extracted from ELF notes
+ // (see RefineModuleDetailsFromNote). However in some cases that still
+ // might be not enough: for example a shared library might not have any
+ // notes at all and have EI_OSABI flag set to System V, as result the OS
+ // will be set to UnknownOS.
GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
spec_ostype = arch_spec.GetTriple().getOS();
assert(spec_ostype == ostype);
@@ -1842,6 +1791,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
static ConstString g_sect_name_dwarf_debug_macro(".debug_macro");
+ static ConstString g_sect_name_dwarf_debug_names(".debug_names");
static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
@@ -1857,10 +1807,12 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
static ConstString g_sect_name_dwarf_debug_str_dwo(".debug_str.dwo");
static ConstString g_sect_name_dwarf_debug_str_offsets_dwo(
".debug_str_offsets.dwo");
+ static ConstString g_sect_name_dwarf_debug_types(".debug_types");
static ConstString g_sect_name_eh_frame(".eh_frame");
static ConstString g_sect_name_arm_exidx(".ARM.exidx");
static ConstString g_sect_name_arm_extab(".ARM.extab");
static ConstString g_sect_name_go_symtab(".gosymtab");
+ static ConstString g_sect_name_dwarf_gnu_debugaltlink(".gnu_debugaltlink");
SectionType sect_type = eSectionTypeOther;
@@ -1881,23 +1833,19 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
}
// .debug_abbrev – Abbreviations used in the .debug_info section
// .debug_aranges – Lookup table for mapping addresses to compilation
- // units
- // .debug_frame – Call frame information
- // .debug_info – The core DWARF information section
- // .debug_line – Line number information
+ // units .debug_frame – Call frame information .debug_info – The core
+ // DWARF information section .debug_line – Line number information
// .debug_loc – Location lists used in DW_AT_location attributes
- // .debug_macinfo – Macro information
- // .debug_pubnames – Lookup table for mapping object and function names to
- // compilation units
+ // .debug_macinfo – Macro information .debug_pubnames – Lookup table
+ // for mapping object and function names to compilation units
// .debug_pubtypes – Lookup table for mapping type names to compilation
- // units
- // .debug_ranges – Address ranges used in DW_AT_ranges attributes
- // .debug_str – String table used in .debug_info
- // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
- // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
- // MISSING? .debug-index -
- // http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
- // MISSING? .debug_types - Type descriptions from DWARF 4? See
+ // units .debug_ranges – Address ranges used in DW_AT_ranges attributes
+ // .debug_str – String table used in .debug_info MISSING?
+ // .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
+ // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html MISSING?
+ // .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build
+ // /gdb-add-index?pathrev=144644 MISSING? .debug_types - Type
+ // descriptions from DWARF 4? See
// http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
else if (name == g_sect_name_dwarf_debug_abbrev)
sect_type = eSectionTypeDWARFDebugAbbrev;
@@ -1919,6 +1867,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
sect_type = eSectionTypeDWARFDebugMacInfo;
else if (name == g_sect_name_dwarf_debug_macro)
sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_names)
+ sect_type = eSectionTypeDWARFDebugNames;
else if (name == g_sect_name_dwarf_debug_pubnames)
sect_type = eSectionTypeDWARFDebugPubNames;
else if (name == g_sect_name_dwarf_debug_pubtypes)
@@ -1927,6 +1877,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
sect_type = eSectionTypeDWARFDebugRanges;
else if (name == g_sect_name_dwarf_debug_str)
sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_types)
+ sect_type = eSectionTypeDWARFDebugTypes;
else if (name == g_sect_name_dwarf_debug_str_offsets)
sect_type = eSectionTypeDWARFDebugStrOffsets;
else if (name == g_sect_name_dwarf_debug_abbrev_dwo)
@@ -1951,6 +1903,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
sect_type = eSectionTypeARMextab;
else if (name == g_sect_name_go_symtab)
sect_type = eSectionTypeGoSymtab;
+ else if (name == g_sect_name_dwarf_gnu_debugaltlink)
+ sect_type = eSectionTypeDWARFGNUDebugAltLink;
const uint32_t permissions =
((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0u) |
@@ -1978,13 +1932,21 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
if (eSectionTypeOther == sect_type) {
// the kalimba toolchain assumes that ELF section names are free-form.
- // It does
- // support linkscripts which (can) give rise to various arbitrarily
- // named
- // sections being "Code" or "Data".
+ // It does support linkscripts which (can) give rise to various
+ // arbitrarily named sections being "Code" or "Data".
sect_type = kalimbaSectionType(m_header, header);
}
+ // In common case ELF code section can have arbitrary name (for example,
+ // we can specify it using section attribute for particular function) so
+ // assume that section is a code section if it has SHF_EXECINSTR flag set
+ // and has SHT_PROGBITS type.
+ if (eSectionTypeOther == sect_type &&
+ llvm::ELF::SHT_PROGBITS == header.sh_type &&
+ (header.sh_flags & SHF_EXECINSTR)) {
+ sect_type = eSectionTypeCode;
+ }
+
const uint32_t target_bytes_size =
(eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type)
? m_arch_spec.GetDataByteSize()
@@ -2024,46 +1986,16 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
}
}
- if (m_sections_ap.get()) {
- if (GetType() == eTypeDebugInfo) {
- static const SectionType g_sections[] = {
- eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
- eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
- eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
- eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc,
- eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames,
- eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
- eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable,
- };
- SectionList *elf_section_list = m_sections_ap.get();
- for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
- ++idx) {
- SectionType section_type = g_sections[idx];
- SectionSP section_sp(
- elf_section_list->FindSectionByType(section_type, true));
- if (section_sp) {
- SectionSP module_section_sp(
- unified_section_list.FindSectionByType(section_type, true));
- if (module_section_sp)
- unified_section_list.ReplaceSection(module_section_sp->GetID(),
- section_sp);
- else
- unified_section_list.AddSection(section_sp);
- }
- }
- } else {
- unified_section_list = *m_sections_ap;
- }
- }
+ // For eTypeDebugInfo files, the Symbol Vendor will take care of updating the
+ // unified section list.
+ if (GetType() != eTypeDebugInfo)
+ unified_section_list = *m_sections_ap;
}
// Find the arm/aarch64 mapping symbol character in the given symbol name.
-// Mapping symbols have the
-// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping
-// symbol prefixed by
-// an arbitrary string because if a symbol prefix added to each symbol in the
-// object file with
+// Mapping symbols have the form of "$<char>[.<any>]*". Additionally we
+// recognize cases when the mapping symbol prefixed by an arbitrary string
+// because if a symbol prefix added to each symbol in the object file with
// objcopy then the mapping symbols are also prefixed.
static char FindArmAarch64MappingSymbol(const char *symbol_name) {
if (!symbol_name)
@@ -2105,22 +2037,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
static ConstString opd_section_name(".opd"); // For ppc64
// On Android the oatdata and the oatexec symbols in the oat and odex files
- // covers the full
- // .text section what causes issues with displaying unusable symbol name to
- // the user and very
- // slow unwinding speed because the instruction emulation based unwind plans
- // try to emulate all
- // instructions in these symbols. Don't add these symbols to the symbol list
- // as they have no
- // use for the debugger and they are causing a lot of trouble.
- // Filtering can't be restricted to Android because this special object file
- // don't contain the
- // note section specifying the environment to Android but the custom extension
- // and file name
- // makes it highly unlikely that this will collide with anything else.
+ // covers the full .text section what causes issues with displaying unusable
+ // symbol name to the user and very slow unwinding speed because the
+ // instruction emulation based unwind plans try to emulate all instructions
+ // in these symbols. Don't add these symbols to the symbol list as they have
+ // no use for the debugger and they are causing a lot of trouble. Filtering
+ // can't be restricted to Android because this special object file don't
+ // contain the note section specifying the environment to Android but the
+ // custom extension and file name makes it highly unlikely that this will
+ // collide with anything else.
ConstString file_extension = m_file.GetFileNameExtension();
- bool skip_oatdata_oatexec = file_extension == ConstString("oat") ||
- file_extension == ConstString("odex");
+ bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
+ file_extension == ConstString(".odex");
ArchSpec arch;
GetArchitecture(arch);
@@ -2129,8 +2057,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
module_sp ? module_sp->GetSectionList() : nullptr;
// Local cache to avoid doing a FindSectionByName for each symbol. The "const
- // char*" key must
- // came from a ConstString object so they can be compared by pointer
+ // char*" key must came from a ConstString object so they can be compared by
+ // pointer
std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
unsigned i;
@@ -2148,8 +2076,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
continue;
// Skipping oatdata and oatexec sections if it is requested. See details
- // above the
- // definition of skip_oatdata_oatexec for the reasons.
+ // above the definition of skip_oatdata_oatexec for the reasons.
if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 ||
::strcmp(symbol_name, "oatexec") == 0))
continue;
@@ -2180,8 +2107,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
break;
case STT_OBJECT:
- // The symbol is associated with a data object, such as a variable,
- // an array, etc.
+ // The symbol is associated with a data object, such as a variable, an
+ // array, etc.
symbol_type = eSymbolTypeData;
break;
@@ -2192,13 +2119,13 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
case STT_SECTION:
// The symbol is associated with a section. Symbol table entries of
- // this type exist primarily for relocation and normally have
- // STB_LOCAL binding.
+ // this type exist primarily for relocation and normally have STB_LOCAL
+ // binding.
break;
case STT_FILE:
- // Conventionally, the symbol's name gives the name of the source
- // file associated with the object file. A file symbol has STB_LOCAL
+ // Conventionally, the symbol's name gives the name of the source file
+ // associated with the object file. A file symbol has STB_LOCAL
// binding, its section index is SHN_ABS, and it precedes the other
// STB_LOCAL symbols for the file, if it is present.
symbol_type = eSymbolTypeSourceFile;
@@ -2240,18 +2167,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'a':
// $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'b':
case 't':
// $b[.<any>]* - marks a THUMB BL instruction sequence
// $t[.<any>]* - marks a THUMB instruction sequence
m_address_class_map[symbol.st_value] =
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2265,11 +2192,11 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'x':
// $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2281,18 +2208,17 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (arch.GetMachine() == llvm::Triple::arm) {
if (symbol_type == eSymbolTypeCode) {
if (symbol.st_value & 1) {
- // Subtracting 1 from the address effectively unsets
- // the low order bit, which results in the address
- // actually pointing to the beginning of the symbol.
- // This delta will be used below in conjunction with
- // symbol.st_value to produce the final symbol_value
- // that we store in the symtab.
+ // Subtracting 1 from the address effectively unsets the low order
+ // bit, which results in the address actually pointing to the
+ // beginning of the symbol. This delta will be used below in
+ // conjunction with symbol.st_value to produce the final
+ // symbol_value that we store in the symtab.
symbol_value_offset = -1;
m_address_class_map[symbol.st_value ^ 1] =
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
} else {
// This address is ARM
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
}
}
}
@@ -2317,36 +2243,32 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
llvm_arch == llvm::Triple::mips64 ||
llvm_arch == llvm::Triple::mips64el) {
if (IS_MICROMIPS(symbol.st_other))
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
symbol.st_value = symbol.st_value & (~1ull);
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
} else {
if (symbol_type == eSymbolTypeCode)
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
else if (symbol_type == eSymbolTypeData)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
else
- m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ m_address_class_map[symbol.st_value] = AddressClass::eUnknown;
}
}
}
// symbol_value_offset may contain 0 for ARM symbols or -1 for THUMB
- // symbols. See above for
- // more details.
+ // symbols. See above for more details.
uint64_t symbol_value = symbol.st_value + symbol_value_offset;
if (symbol_section_sp == nullptr && section_idx == SHN_ABS &&
symbol.st_size != 0) {
// We don't have a section for a symbol with non-zero size. Create a new
- // section for it
- // so the address range covered by the symbol is also covered by the
- // module (represented
- // through the section list). It is needed so module lookup for the
- // addresses covered
- // by this symbol will be successfull. This case happens for absolute
- // symbols.
+ // section for it so the address range covered by the symbol is also
+ // covered by the module (represented through the section list). It is
+ // needed so module lookup for the addresses covered by this symbol will
+ // be successfull. This case happens for absolute symbols.
ConstString fake_section_name(std::string(".absolute.") + symbol_name);
symbol_section_sp =
std::make_shared<Section>(module_sp, this, SHN_ABS, fake_section_name,
@@ -2389,8 +2311,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
Mangled mangled(ConstString(symbol_bare), is_mangled);
// Now append the suffix back to mangled and unmangled names. Only do it if
- // the
- // demangling was successful (string is not empty).
+ // the demangling was successful (string is not empty).
if (has_suffix) {
llvm::StringRef suffix = symbol_ref.substr(version_pos);
@@ -2406,12 +2327,10 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
}
// In ELF all symbol should have a valid size but it is not true for some
- // function symbols
- // coming from hand written assembly. As none of the function symbol should
- // have 0 size we
- // try to calculate the size for these symbols in the symtab with saying
- // that their original
- // size is not valid.
+ // function symbols coming from hand written assembly. As none of the
+ // function symbol should have 0 size we try to calculate the size for
+ // these symbols in the symtab with saying that their original size is not
+ // valid.
bool symbol_size_valid =
symbol.st_size != 0 || symbol.getType() != STT_FUNC;
@@ -2440,8 +2359,7 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
lldb_private::Section *symtab) {
if (symtab->GetObjectFile() != this) {
// If the symbol table section is owned by a different object file, have it
- // do the
- // parsing.
+ // do the parsing.
ObjectFileELF *obj_file_elf =
static_cast<ObjectFileELF *>(symtab->GetObjectFile());
return obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);
@@ -2457,8 +2375,8 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
- // sh_link: section header index of associated string table.
- // Section ID's are ones based.
+ // sh_link: section header index of associated string table. Section ID's are
+ // ones based.
user_id_t strtab_id = symtab_hdr->sh_link + 1;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
@@ -2543,19 +2461,17 @@ unsigned ObjectFileELF::PLTRelocationType() {
return 0;
}
-// Returns the size of the normal plt entries and the offset of the first normal
-// plt entry. The
-// 0th entry in the plt table is usually a resolution entry which have different
-// size in some
-// architectures then the rest of the plt entries.
+// Returns the size of the normal plt entries and the offset of the first
+// normal plt entry. The 0th entry in the plt table is usually a resolution
+// entry which have different size in some architectures then the rest of the
+// plt entries.
static std::pair<uint64_t, uint64_t>
GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
const ELFSectionHeader *plt_hdr) {
const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
- // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16
- // bytes.
- // So round the entsize up by the alignment if addralign is set.
+ // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are
+ // 16 bytes. So round the entsize up by the alignment if addralign is set.
elf_xword plt_entsize =
plt_hdr->sh_addralign
? llvm::alignTo(plt_hdr->sh_entsize, plt_hdr->sh_addralign)
@@ -2567,12 +2483,10 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
// just in case.
if (plt_entsize <= 4) {
// The linker haven't set the plt_hdr->sh_entsize field. Try to guess the
- // size of the plt
- // entries based on the number of entries and the size of the plt section
- // with the
- // assumption that the size of the 0th entry is at least as big as the size
- // of the normal
- // entries and it isn't much bigger then that.
+ // size of the plt entries based on the number of entries and the size of
+ // the plt section with the assumption that the size of the 0th entry is at
+ // least as big as the size of the normal entries and it isn't much bigger
+ // then that.
if (plt_hdr->sh_addralign)
plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign /
(num_relocations + 1) * plt_hdr->sh_addralign;
@@ -2865,8 +2779,7 @@ Symtab *ObjectFileELF::GetSymtab() {
return NULL;
// We always want to use the main object file so we (hopefully) only have one
- // cached copy
- // of our symtab, dynamic sections, etc.
+ // cached copy of our symtab, dynamic sections, etc.
ObjectFile *module_obj_file = module_sp->GetObjectFile();
if (module_obj_file && module_obj_file != this)
return module_obj_file->GetSymtab();
@@ -2881,18 +2794,15 @@ Symtab *ObjectFileELF::GetSymtab() {
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a
- // smaller
- // version of the symtab that only contains global symbols. The information
- // found
- // in the dynsym is therefore also found in the symtab, while the reverse is
- // not
- // necessarily true.
+ // smaller version of the symtab that only contains global symbols. The
+ // information found in the dynsym is therefore also found in the symtab,
+ // while the reverse is not necessarily true.
Section *symtab =
section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
if (!symtab) {
// The symtab section is non-allocable and can be stripped, so if it
- // doesn't exist
- // then use the dynsym section which should always be there.
+ // doesn't exist then use the dynsym section which should always be
+ // there.
symtab =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
@@ -2939,8 +2849,7 @@ Symtab *ObjectFileELF::GetSymtab() {
}
// If we still don't have any symtab then create an empty instance to avoid
- // do the section
- // lookup next time.
+ // do the section lookup next time.
if (m_symtab_ap == nullptr)
m_symtab_ap.reset(new Symtab(this));
@@ -2954,8 +2863,8 @@ void ObjectFileELF::RelocateSection(lldb_private::Section *section)
{
static const char *debug_prefix = ".debug";
- // Set relocated bit so we stop getting called, regardless of
- // whether we actually relocate.
+ // Set relocated bit so we stop getting called, regardless of whether we
+ // actually relocate.
section->SetIsRelocated(true);
// We only relocate in ELF relocatable files
@@ -2998,12 +2907,10 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
return;
// First we save the new symbols into a separate list and add them to the
- // symbol table after
- // we colleced all symbols we want to add. This is neccessary because adding a
- // new symbol
- // invalidates the internal index of the symtab what causing the next lookup
- // to be slow because
- // it have to recalculate the index first.
+ // symbol table after we colleced all symbols we want to add. This is
+ // neccessary because adding a new symbol invalidates the internal index of
+ // the symtab what causing the next lookup to be slow because it have to
+ // recalculate the index first.
std::vector<Symbol> new_symbols;
eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
@@ -3197,8 +3104,8 @@ void ObjectFileELF::DumpELFProgramHeader(Stream *s,
//----------------------------------------------------------------------
// DumpELFProgramHeader_p_type
//
-// Dump an token value for the ELF program header member p_type which
-// describes the type of the program header
+// Dump an token value for the ELF program header member p_type which describes
+// the type of the program header
// ----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
const int kStrWidth = 15;
@@ -3369,8 +3276,7 @@ bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
if (CalculateType() == eTypeCoreFile &&
m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
// Core files don't have section headers yet they have PT_NOTE program
- // headers
- // that might shed more light on the architecture
+ // headers that might shed more light on the architecture
if (ParseProgramHeaders()) {
for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
@@ -3431,22 +3337,22 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
case llvm::ELF::ET_EXEC:
// 2 - Executable file
// TODO: is there any way to detect that an executable is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section headers,
+ // symbols, or any other flag bits???
return eStrataUser;
case llvm::ELF::ET_DYN:
// 3 - Shared object file
// TODO: is there any way to detect that an shared library is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section headers,
+ // symbols, or any other flag bits???
return eStrataUnknown;
case ET_CORE:
// 4 - Core file
// TODO: is there any way to detect that an core file is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section headers,
+ // symbols, or any other flag bits???
return eStrataUnknown;
default:
@@ -3491,8 +3397,9 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
size_t(section_data.GetByteSize())},
GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
if (!Decompressor) {
- LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}",
- section->GetName(), llvm::toString(Decompressor.takeError()));
+ LLDB_LOG_ERROR(log, Decompressor.takeError(),
+ "Unable to initialize decompressor for section {0}",
+ section->GetName());
return result;
}
auto buffer_sp =
@@ -3500,10 +3407,45 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
if (auto Error = Decompressor->decompress(
{reinterpret_cast<char *>(buffer_sp->GetBytes()),
size_t(buffer_sp->GetByteSize())})) {
- LLDB_LOG(log, "Decompression of section {0} failed: {1}",
- section->GetName(), llvm::toString(std::move(Error)));
+ LLDB_LOG_ERROR(log, std::move(Error), "Decompression of section {0} failed",
+ section->GetName());
return result;
}
section_data.SetData(buffer_sp);
return buffer_sp->GetByteSize();
}
+
+bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
+ size_t header_count = ParseProgramHeaders();
+ for (size_t i = 1; i <= header_count; ++i) {
+ auto header = GetProgramHeaderByIndex(i);
+ if (header->p_paddr != 0)
+ return true;
+ }
+ return false;
+}
+
+std::vector<ObjectFile::LoadableData>
+ObjectFileELF::GetLoadableData(Target &target) {
+ // Create a list of loadable data from loadable segments, using physical
+ // addresses if they aren't all null
+ std::vector<LoadableData> loadables;
+ size_t header_count = ParseProgramHeaders();
+ bool should_use_paddr = AnySegmentHasPhysicalAddress();
+ for (size_t i = 1; i <= header_count; ++i) {
+ LoadableData loadable;
+ auto header = GetProgramHeaderByIndex(i);
+ if (header->p_type != llvm::ELF::PT_LOAD)
+ continue;
+ loadable.Dest = should_use_paddr ? header->p_paddr : header->p_vaddr;
+ if (loadable.Dest == LLDB_INVALID_ADDRESS)
+ continue;
+ if (header->p_filesz == 0)
+ continue;
+ auto segment_data = GetSegmentDataByIndex(i);
+ loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
+ segment_data.GetByteSize());
+ loadables.push_back(loadable);
+ }
+ return loadables;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 2909f4e52e4a..2664595fd81d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -54,10 +54,10 @@ struct ELFNote {
//------------------------------------------------------------------------------
/// @class ObjectFileELF
-/// @brief Generic ELF object file reader.
+/// Generic ELF object file reader.
///
-/// This class provides a generic ELF (32/64 bit) reader plugin implementing the
-/// ObjectFile protocol.
+/// This class provides a generic ELF (32/64 bit) reader plugin implementing
+/// the ObjectFile protocol.
class ObjectFileELF : public lldb_private::ObjectFile {
public:
~ObjectFileELF() override;
@@ -113,7 +113,7 @@ public:
uint32_t GetAddressByteSize() const override;
- lldb::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
+ lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
lldb_private::Symtab *GetSymtab() override;
@@ -161,6 +161,11 @@ public:
void RelocateSection(lldb_private::Section *section) override;
+protected:
+
+ std::vector<LoadableData>
+ GetLoadableData(lldb_private::Target &target) override;
+
private:
ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
lldb::offset_t data_offset, const lldb_private::FileSpec *file,
@@ -186,7 +191,7 @@ private:
typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;
typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;
- typedef std::map<lldb::addr_t, lldb::AddressClass>
+ typedef std::map<lldb::addr_t, lldb_private::AddressClass>
FileAddressToAddressClassMap;
/// Version of this reader common to all plugins based on this class.
@@ -255,8 +260,8 @@ private:
uint64_t length,
lldb_private::ArchSpec &arch_spec);
- /// Parses the elf section headers and returns the uuid, debug link name, crc,
- /// archspec.
+ /// Parses the elf section headers and returns the uuid, debug link name,
+ /// crc, archspec.
static size_t GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &object_data,
const elf::ELFHeader &header,
@@ -383,6 +388,8 @@ private:
RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
lldb_private::ArchSpec &arch_spec,
lldb_private::UUID &uuid);
+
+ bool AnySegmentHasPhysicalAddress();
};
#endif // liblldb_ObjectFileELF_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index a9ab366fbf53..af040322ec52 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -65,8 +65,8 @@ ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
const FileSpec *file,
lldb::offset_t file_offset,
lldb::offset_t length) {
- // JIT'ed object file is backed by the ObjectFileJITDelegate, never
- // read from a file
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
+ // a file
return NULL;
}
@@ -74,8 +74,8 @@ ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp,
const ProcessSP &process_sp,
lldb::addr_t header_addr) {
- // JIT'ed object file is backed by the ObjectFileJITDelegate, never
- // read from memory
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
+ // memory
return NULL;
}
@@ -214,9 +214,8 @@ bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
const size_t num_sections = section_list->GetSize();
// "value" is an offset to apply to each top level segment
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all
- // of the sections that size on disk (to avoid __PAGEZERO)
- // and load them
+ // Iterate through the object file sections to find all of the sections
+ // that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->GetFileSize() > 0 &&
section_sp->IsThreadSpecific() == false) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
index 75bc518f7538..3f6083931513 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
@@ -312,8 +312,8 @@ bool OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list,
}
std::vector<Goroutine> goroutines;
// The threads that are in "new_thread_list" upon entry are the threads from
- // the
- // lldb_private::Process subclass, no memory threads will be in this list.
+ // the lldb_private::Process subclass, no memory threads will be in this
+ // list.
Status err;
for (uint64_t i = 0; i < allglen; ++i) {
@@ -402,7 +402,6 @@ lldb::ThreadSP OperatingSystemGo::CreateThread(lldb::tid_t tid,
ValueObjectSP OperatingSystemGo::FindGlobal(TargetSP target, const char *name) {
VariableList variable_list;
- const bool append = true;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
@@ -414,7 +413,7 @@ ValueObjectSP OperatingSystemGo::FindGlobal(TargetSP target, const char *name) {
}
uint32_t match_count = target->GetImages().FindGlobalVariables(
- ConstString(name), append, 1, variable_list);
+ ConstString(name), 1, variable_list);
if (match_count > 0) {
ExecutionContextScope *exe_scope = target->GetProcessSP().get();
if (exe_scope == NULL)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index b71f3cf04c33..d6252c473270 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -50,8 +50,8 @@ void OperatingSystemPython::Terminate() {
OperatingSystem *OperatingSystemPython::CreateInstance(Process *process,
bool force) {
- // Python OperatingSystem plug-ins must be requested by name, so force must be
- // true
+ // Python OperatingSystem plug-ins must be requested by name, so force must
+ // be true
FileSpec python_os_plugin_spec(process->GetPythonOSPluginPath());
if (python_os_plugin_spec && python_os_plugin_spec.Exists()) {
std::unique_ptr<OperatingSystemPython> os_ap(
@@ -156,9 +156,10 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
- // First thing we have to do is to try to get the API lock, and the run lock.
- // We're going to change the thread content of the process, and we're going
- // to use python, which requires the API lock to do it.
+ // First thing we have to do is to try to get the API lock, and the
+ // interpreter lock. We're going to change the thread content of the process,
+ // and we're going to use python, which requires the API lock to do it. We
+ // need the interpreter lock to make sure thread_info_dict stays alive.
//
// If someone already has the API lock, that is ok, we just want to avoid
// external code from making new API calls while this call is happening.
@@ -166,9 +167,10 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
// This is a recursive lock so we can grant it to any Python code called on
// the stack below us.
Target &target = m_process->GetTarget();
- std::unique_lock<std::recursive_mutex> lock(target.GetAPIMutex(),
- std::defer_lock);
- lock.try_lock();
+ std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
+ std::defer_lock);
+ api_lock.try_lock();
+ auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
if (log)
log->Printf("OperatingSystemPython::UpdateThreadList() fetching thread "
@@ -176,20 +178,16 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
m_process->GetID());
// The threads that are in "new_thread_list" upon entry are the threads from
- // the
- // lldb_private::Process subclass, no memory threads will be in this list.
-
- auto interpreter_lock =
- m_interpreter
- ->AcquireInterpreterLock(); // to make sure threads_list stays alive
+ // the lldb_private::Process subclass, no memory threads will be in this
+ // list.
StructuredData::ArraySP threads_list =
m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp);
const uint32_t num_cores = core_thread_list.GetSize(false);
// Make a map so we can keep track of which cores were used from the
- // core_thread list. Any real threads/cores that weren't used should
- // later be put back into the "new_thread_list".
+ // core_thread list. Any real threads/cores that weren't used should later be
+ // put back into the "new_thread_list".
std::vector<bool> core_used_map(num_cores, false);
if (threads_list) {
if (log) {
@@ -214,8 +212,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
// Any real core threads that didn't end up backing a memory thread should
// still be in the main thread list, and they should be inserted at the
- // beginning
- // of the list
+ // beginning of the list
uint32_t insert_idx = 0;
for (uint32_t core_idx = 0; core_idx < num_cores; ++core_idx) {
if (core_used_map[core_idx] == false) {
@@ -256,8 +253,8 @@ ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo(
// plug-in generated thread.
if (!IsOperatingSystemPluginThread(thread_sp)) {
// We have thread ID overlap between the protocol threads and the
- // operating system threads, clear the thread so we create an
- // operating system thread for this.
+ // operating system threads, clear the thread so we create an operating
+ // system thread for this.
thread_sp.reset();
}
}
@@ -301,20 +298,24 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
return reg_ctx_sp;
- // First thing we have to do is get the API lock, and the run lock. We're
- // going to change the thread
- // content of the process, and we're going to use python, which requires the
- // API lock to do it.
- // So get & hold that. This is a recursive lock so we can grant it to any
- // Python code called on the stack below us.
+ // First thing we have to do is to try to get the API lock, and the
+ // interpreter lock. We're going to change the thread content of the process,
+ // and we're going to use python, which requires the API lock to do it. We
+ // need the interpreter lock to make sure thread_info_dict stays alive.
+ //
+ // If someone already has the API lock, that is ok, we just want to avoid
+ // external code from making new API calls while this call is happening.
+ //
+ // This is a recursive lock so we can grant it to any Python code called on
+ // the stack below us.
Target &target = m_process->GetTarget();
- std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
+ std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
+ std::defer_lock);
+ api_lock.try_lock();
+ auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
- auto lock =
- m_interpreter
- ->AcquireInterpreterLock(); // to make sure python objects stays alive
if (reg_data_addr != LLDB_INVALID_ADDRESS) {
// The registers data is in contiguous memory, just create the register
// context using the address provided
@@ -326,8 +327,8 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
reg_ctx_sp.reset(new RegisterContextMemory(
*thread, 0, *GetDynamicRegisterInfo(), reg_data_addr));
} else {
- // No register data address is provided, query the python plug-in to let
- // it make up the data as it sees fit
+ // No register data address is provided, query the python plug-in to let it
+ // make up the data as it sees fit
if (log)
log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid "
"= 0x%" PRIx64 ", 0x%" PRIx64
@@ -383,18 +384,23 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
tid, context);
if (m_interpreter && m_python_object_sp) {
- // First thing we have to do is get the API lock, and the run lock. We're
- // going to change the thread
- // content of the process, and we're going to use python, which requires the
- // API lock to do it.
- // So get & hold that. This is a recursive lock so we can grant it to any
- // Python code called on the stack below us.
+ // First thing we have to do is to try to get the API lock, and the
+ // interpreter lock. We're going to change the thread content of the
+ // process, and we're going to use python, which requires the API lock to
+ // do it. We need the interpreter lock to make sure thread_info_dict stays
+ // alive.
+ //
+ // If someone already has the API lock, that is ok, we just want to avoid
+ // external code from making new API calls while this call is happening.
+ //
+ // This is a recursive lock so we can grant it to any Python code called on
+ // the stack below us.
Target &target = m_process->GetTarget();
- std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
+ std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
+ std::defer_lock);
+ api_lock.try_lock();
+ auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
- auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure
- // thread_info_dict
- // stays alive
StructuredData::DictionarySP thread_info_dict =
m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context);
std::vector<bool> core_used_map;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 73c7d21f0a06..bc8111d1078b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -32,8 +32,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from FreeBSD mman.h for use when targeting
-// remote FreeBSD systems even when host has different values.
+// Define these constants from FreeBSD mman.h for use when targeting remote
+// FreeBSD systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
@@ -60,9 +60,8 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__FreeBSD__)
- // Only accept "unknown" for the OS if the host is BSD and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is BSD and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -143,7 +142,8 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
- // If the default host architecture is 64-bit, look for a 32-bit variant
+ // If the default host architecture is 64-bit, look for a 32-bit
+ // variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
@@ -187,13 +187,10 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
@@ -228,16 +225,16 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target,
switch (target.GetArchitecture().GetMachine()) {
case llvm::Triple::arm: {
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = eAddressClassUnknown;
+ AddressClass addr_class = AddressClass::eUnknown;
if (bp_loc_sp) {
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == eAddressClassUnknown &&
+ if (addr_class == AddressClass::eUnknown &&
(bp_loc_sp->GetAddress().GetFileAddress() & 1))
- addr_class = eAddressClassCodeAlternateISA;
+ addr_class = AddressClass::eCodeAlternateISA;
}
- if (addr_class == eAddressClassCodeAlternateISA) {
+ if (addr_class == AddressClass::eCodeAlternateISA) {
// TODO: Enable when FreeBSD supports thumb breakpoints.
// FreeBSD kernel as of 10.x, does not support thumb breakpoints
return 0;
@@ -286,9 +283,9 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
if (target && error.Success()) {
debugger.GetTargetList().SetSelectedTarget(target);
- // The freebsd always currently uses the GDB remote debugger plug-in
- // so even when debugging locally we are debugging remotely!
- // Just like the darwin plugin.
+ // The freebsd always currently uses the GDB remote debugger plug-in so
+ // even when debugging locally we are debugging remotely! Just like the
+ // darwin plugin.
process_sp = target->CreateProcess(
attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index 3c78b46dce63..3aa8ecb4c228 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -30,8 +30,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from NetBSD mman.h for use when targeting
-// remote netbsd systems even when host has different values.
+// Define these constants from NetBSD mman.h for use when targeting remote
+// netbsd systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
@@ -134,7 +134,8 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
- // If the default host architecture is 64-bit, look for a 32-bit variant
+ // If the default host architecture is 64-bit, look for a 32-bit
+ // variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
@@ -160,13 +161,10 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
@@ -240,8 +238,8 @@ bool PlatformNetBSD::CanDebugProcess() {
}
// For local debugging, NetBSD will override the debug logic to use llgs-launch
-// rather than lldb-launch, llgs-attach. This differs from current lldb-launch,
-// debugserver-attach approach on MacOSX.
+// rather than lldb-launch, llgs-attach. This differs from current lldb-
+// launch, debugserver-attach approach on MacOSX.
lldb::ProcessSP
PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new
@@ -265,8 +263,8 @@ PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
- // group, since then we can handle ^C interrupts ourselves w/o having to worry
- // about the target getting them as well.
+ // group, since then we can handle ^C interrupts ourselves w/o having to
+ // worry about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
// Ensure we have a target.
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 050639aba7cc..10ca8fbfbdd7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -30,8 +30,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from OpenBSD mman.h for use when targeting
-// remote openbsd systems even when host has different values.
+// Define these constants from OpenBSD mman.h for use when targeting remote
+// openbsd systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
@@ -58,9 +58,8 @@ PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__OpenBSD__)
- // Only accept "unknown" for the OS if the host is BSD and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is BSD and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -167,13 +166,10 @@ bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index d45a54ee2499..5e7ffe71918e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -18,17 +18,22 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/DiagnosticManager.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
@@ -97,17 +102,14 @@ lldb_private::Status PlatformPOSIX::RunShellCommand(
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
if (IsHost())
return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
- command_output, timeout_sec);
+ command_output, timeout);
else {
if (m_remote_platform_sp)
- return m_remote_platform_sp->RunShellCommand(command, working_dir,
- status_ptr, signo_ptr,
- command_output, timeout_sec);
+ return m_remote_platform_sp->RunShellCommand(
+ command, working_dir, status_ptr, signo_ptr, command_output, timeout);
else
return Status("unable to run a remote command without a platform");
}
@@ -124,11 +126,12 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
ModuleSpec resolved_module_spec(module_spec);
if (IsHost()) {
- // If we have "ls" as the exe_file, resolve the executable location based on
- // the current path variables
+ // If we have "ls" as the exe_file, resolve the executable location based
+ // on the current path variables
if (!resolved_module_spec.GetFileSpec().Exists()) {
resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
- resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true,
+ FileSpec::Style::native);
}
if (!resolved_module_spec.GetFileSpec().Exists())
@@ -210,9 +213,9 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
} else {
- // No valid architecture was specified, ask the platform for
- // the architectures that we should be using (in the correct order)
- // and see if we can find a match that way
+ // No valid architecture was specified, ask the platform for the
+ // architectures that we should be using (in the correct order) and see
+ // if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
@@ -367,7 +370,8 @@ static uint32_t chown_file(Platform *platform, const char *path,
command.Printf(":%d", gid);
command.Printf("%s", path);
int status;
- platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10);
+ platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL,
+ std::chrono::seconds(10));
return status;
}
@@ -391,7 +395,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
StreamString command;
command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10);
+ RunShellCommand(command.GetData(), NULL, &status, NULL, NULL,
+ std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
if (uid == UINT32_MAX && gid == UINT32_MAX)
@@ -421,7 +426,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
if (log)
log->Printf("[PutFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60);
+ Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL,
+ std::chrono::minutes(1));
if (retcode == 0) {
// Don't chown a local file for a remote system
// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
@@ -495,7 +501,8 @@ lldb_private::Status PlatformPOSIX::GetFile(
StreamString cp_command;
cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, 10);
+ RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL,
+ std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
return Status();
@@ -516,11 +523,12 @@ lldb_private::Status PlatformPOSIX::GetFile(
if (log)
log->Printf("[GetFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60);
+ Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL,
+ std::chrono::minutes(1));
if (retcode == 0)
return Status();
- // If we are here, rsync has failed - let's try the slow way before giving
- // up
+ // If we are here, rsync has failed - let's try the slow way before
+ // giving up
}
// open src and dst
// read/write, read/write, read/write, ...
@@ -645,9 +653,10 @@ bool PlatformPOSIX::SetRemoteWorkingDirectory(const FileSpec &working_dir) {
}
bool PlatformPOSIX::GetRemoteOSVersion() {
- if (m_remote_platform_sp)
- return m_remote_platform_sp->GetOSVersion(
- m_major_os_version, m_minor_os_version, m_update_os_version);
+ if (m_remote_platform_sp) {
+ m_os_version = m_remote_platform_sp->GetOSVersion();
+ return !m_os_version.empty();
+ }
return false;
}
@@ -658,13 +667,13 @@ bool PlatformPOSIX::GetRemoteOSBuildString(std::string &s) {
return false;
}
-size_t PlatformPOSIX::GetEnvironment(StringList &env) {
+Environment PlatformPOSIX::GetEnvironment() {
if (IsRemote()) {
if (m_remote_platform_sp)
- return m_remote_platform_sp->GetEnvironment(env);
- return 0;
+ return m_remote_platform_sp->GetEnvironment();
+ return Environment();
}
- return Host::GetEnvironment(env);
+ return Host::GetEnvironment();
}
bool PlatformPOSIX::GetRemoteOSKernelDescription(std::string &s) {
@@ -861,12 +870,12 @@ PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
if (IsHost()) {
// We are going to hand this process off to debugserver which will be in
- // charge of setting the exit status.
- // We still need to reap it from lldb but if we let the monitor thread also
- // set the exit status, we set up a
- // race between debugserver & us for who will find out about the debugged
- // process's death.
- launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
+ // charge of setting the exit status. However, we still need to reap it
+ // from lldb. So, make sure we use a exit callback which does not set exit
+ // status.
+ const bool monitor_signals = false;
+ launch_info.SetMonitorProcessCallback(
+ &ProcessLaunchInfo::NoOpMonitorCallback, monitor_signals);
process_sp = Platform::DebugProcess(launch_info, debugger, target, error);
} else {
if (m_remote_platform_sp)
@@ -923,64 +932,380 @@ Status PlatformPOSIX::EvaluateLibdlExpression(
return Status();
}
+std::unique_ptr<UtilityFunction>
+PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
+ Status &error) {
+ // Remember to prepend this with the prefix from
+ // GetLibdlFunctionDeclarations. The returned values are all in
+ // __lldb_dlopen_result for consistency. The wrapper returns a void * but
+ // doesn't use it because UtilityFunctions don't work with void returns at
+ // present.
+ static const char *dlopen_wrapper_code = R"(
+ struct __lldb_dlopen_result {
+ void *image_ptr;
+ const char *error_str;
+ };
+
+ extern void *memcpy(void *, const void *, size_t size);
+ extern size_t strlen(const char *);
+
+
+ void * __lldb_dlopen_wrapper (const char *name,
+ const char *path_strings,
+ char *buffer,
+ __lldb_dlopen_result *result_ptr)
+ {
+ // This is the case where the name is the full path:
+ if (!path_strings) {
+ result_ptr->image_ptr = dlopen(name, 2);
+ if (result_ptr->image_ptr)
+ result_ptr->error_str = nullptr;
+ return nullptr;
+ }
+
+ // This is the case where we have a list of paths:
+ size_t name_len = strlen(name);
+ while (path_strings && path_strings[0] != '\0') {
+ size_t path_len = strlen(path_strings);
+ memcpy((void *) buffer, (void *) path_strings, path_len);
+ buffer[path_len] = '/';
+ char *target_ptr = buffer+path_len+1;
+ memcpy((void *) target_ptr, (void *) name, name_len + 1);
+ result_ptr->image_ptr = dlopen(buffer, 2);
+ if (result_ptr->image_ptr) {
+ result_ptr->error_str = nullptr;
+ break;
+ }
+ result_ptr->error_str = dlerror();
+ path_strings = path_strings + path_len + 1;
+ }
+ return nullptr;
+ }
+ )";
+
+ static const char *dlopen_wrapper_name = "__lldb_dlopen_wrapper";
+ Process *process = exe_ctx.GetProcessSP().get();
+ // Insert the dlopen shim defines into our generic expression:
+ std::string expr(GetLibdlFunctionDeclarations(process));
+ expr.append(dlopen_wrapper_code);
+ Status utility_error;
+ DiagnosticManager diagnostics;
+
+ std::unique_ptr<UtilityFunction> dlopen_utility_func_up(process
+ ->GetTarget().GetUtilityFunctionForLanguage(expr.c_str(),
+ eLanguageTypeObjC,
+ dlopen_wrapper_name,
+ utility_error));
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not make utility"
+ "function: %s", utility_error.AsCString());
+ return nullptr;
+ }
+ if (!dlopen_utility_func_up->Install(diagnostics, exe_ctx)) {
+ error.SetErrorStringWithFormat("dlopen error: could not install utility"
+ "function: %s",
+ diagnostics.GetString().c_str());
+ return nullptr;
+ }
+
+ Value value;
+ ValueList arguments;
+ FunctionCaller *do_dlopen_function = nullptr;
+
+ // Fetch the clang types we will need:
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ CompilerType clang_void_pointer_type
+ = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_char_pointer_type
+ = ast->GetBasicType(eBasicTypeChar).GetPointerType();
+
+ // We are passing four arguments, the basename, the list of places to look,
+ // a buffer big enough for all the path + name combos, and
+ // a pointer to the storage we've made for the result:
+ value.SetValueType(Value::eValueTypeScalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ value.SetCompilerType(clang_char_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller(
+ clang_void_pointer_type, arguments, exe_ctx.GetThreadSP(), utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not make function"
+ "caller: %s", utility_error.AsCString());
+ return nullptr;
+ }
+
+ do_dlopen_function = dlopen_utility_func_up->GetFunctionCaller();
+ if (!do_dlopen_function) {
+ error.SetErrorString("dlopen error: could not get function caller.");
+ return nullptr;
+ }
+
+ // We made a good utility function, so cache it in the process:
+ return dlopen_utility_func_up;
+}
+
uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
const lldb_private::FileSpec &remote_file,
- lldb_private::Status &error) {
- char path[PATH_MAX];
- remote_file.GetPath(path, sizeof(path));
-
- StreamString expr;
- expr.Printf(R"(
- struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
- the_result.image_ptr = dlopen ("%s", 2);
- if (the_result.image_ptr == (void *) 0x0)
- {
- the_result.error_str = dlerror();
- }
- else
- {
- the_result.error_str = (const char *) 0x0;
- }
- the_result;
- )",
- path);
- llvm::StringRef prefix = GetLibdlFunctionDeclarations(process);
- lldb::ValueObjectSP result_valobj_sp;
- error = EvaluateLibdlExpression(process, expr.GetData(), prefix,
- result_valobj_sp);
- if (error.Fail())
+ const std::vector<std::string> *paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_image) {
+ if (loaded_image)
+ loaded_image->Clear();
+
+ std::string path;
+ path = remote_file.GetPath();
+
+ ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
+ if (!thread_sp) {
+ error.SetErrorString("dlopen error: no thread available to call dlopen.");
return LLDB_INVALID_IMAGE_TOKEN;
-
- error = result_valobj_sp->GetError();
- if (error.Fail())
+ }
+
+ DiagnosticManager diagnostics;
+
+ ExecutionContext exe_ctx;
+ thread_sp->CalculateExecutionContext(exe_ctx);
+
+ Status utility_error;
+ UtilityFunction *dlopen_utility_func;
+ ValueList arguments;
+ FunctionCaller *do_dlopen_function = nullptr;
+
+ // The UtilityFunction is held in the Process. Platforms don't track the
+ // lifespan of the Targets that use them, we can't put this in the Platform.
+ dlopen_utility_func = process->GetLoadImageUtilityFunction(
+ this, [&]() -> std::unique_ptr<UtilityFunction> {
+ return MakeLoadImageUtilityFunction(exe_ctx, error);
+ });
+ // If we couldn't make it, the error will be in error, so we can exit here.
+ if (!dlopen_utility_func)
return LLDB_INVALID_IMAGE_TOKEN;
-
- Scalar scalar;
- ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
- if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) {
- error.SetErrorStringWithFormat("unable to load '%s'", path);
+
+ do_dlopen_function = dlopen_utility_func->GetFunctionCaller();
+ if (!do_dlopen_function) {
+ error.SetErrorString("dlopen error: could not get function caller.");
return LLDB_INVALID_IMAGE_TOKEN;
}
-
- addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
- if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
- return process->AddImageToken(image_ptr);
-
- if (image_ptr == 0) {
- ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
- if (error_str_sp) {
- DataBufferSP buffer_sp(new DataBufferHeap(10240, 0));
- size_t num_chars =
- error_str_sp->ReadPointedString(buffer_sp, error, 10240).first;
- if (error.Success() && num_chars > 0)
- error.SetErrorStringWithFormat("dlopen error: %s",
- buffer_sp->GetBytes());
- else
- error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
+ arguments = do_dlopen_function->GetArgumentValues();
+
+ // Now insert the path we are searching for and the result structure into the
+ // target.
+ uint32_t permissions = ePermissionsReadable|ePermissionsWritable;
+ size_t path_len = path.size() + 1;
+ lldb::addr_t path_addr = process->AllocateMemory(path_len,
+ permissions,
+ utility_error);
+ if (path_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for path: %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we deallocate the input string memory:
+ CleanUp path_cleanup([process, path_addr] {
+ process->DeallocateMemory(path_addr);
+ });
+
+ process->WriteMemory(path_addr, path.c_str(), path_len, utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not write path string:"
+ " %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make space for our return structure. It is two pointers big: the token
+ // and the error string.
+ const uint32_t addr_size = process->GetAddressByteSize();
+ lldb::addr_t return_addr = process->CallocateMemory(2*addr_size,
+ permissions,
+ utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for path: %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we deallocate the result structure memory
+ CleanUp return_cleanup([process, return_addr] {
+ process->DeallocateMemory(return_addr);
+ });
+
+ // This will be the address of the storage for paths, if we are using them,
+ // or nullptr to signal we aren't.
+ lldb::addr_t path_array_addr = 0x0;
+ llvm::Optional<CleanUp> path_array_cleanup;
+
+ // This is the address to a buffer large enough to hold the largest path
+ // conjoined with the library name we're passing in. This is a convenience
+ // to avoid having to call malloc in the dlopen function.
+ lldb::addr_t buffer_addr = 0x0;
+ llvm::Optional<CleanUp> buffer_cleanup;
+
+ // Set the values into our args and write them to the target:
+ if (paths != nullptr) {
+ // First insert the paths into the target. This is expected to be a
+ // continuous buffer with the strings laid out null terminated and
+ // end to end with an empty string terminating the buffer.
+ // We also compute the buffer's required size as we go.
+ size_t buffer_size = 0;
+ std::string path_array;
+ for (auto path : *paths) {
+ // Don't insert empty paths, they will make us abort the path
+ // search prematurely.
+ if (path.empty())
+ continue;
+ size_t path_size = path.size();
+ path_array.append(path);
+ path_array.push_back('\0');
+ if (path_size > buffer_size)
+ buffer_size = path_size;
+ }
+ path_array.push_back('\0');
+
+ path_array_addr = process->AllocateMemory(path_array.size(),
+ permissions,
+ utility_error);
+ if (path_array_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for path array: %s",
+ utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we deallocate the paths array.
+ path_array_cleanup.emplace([process, path_array_addr] {
+ process->DeallocateMemory(path_array_addr);
+ });
+
+ process->WriteMemory(path_array_addr, path_array.data(),
+ path_array.size(), utility_error);
+
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not write path array:"
+ " %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+ // Now make spaces in the target for the buffer. We need to add one for
+ // the '/' that the utility function will insert and one for the '\0':
+ buffer_size += path.size() + 2;
+
+ buffer_addr = process->AllocateMemory(buffer_size,
+ permissions,
+ utility_error);
+ if (buffer_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for buffer: %s",
+ utility_error.AsCString());
return LLDB_INVALID_IMAGE_TOKEN;
}
+
+ // Make sure we deallocate the buffer memory:
+ buffer_cleanup.emplace([process, buffer_addr] {
+ process->DeallocateMemory(buffer_addr);
+ });
}
- error.SetErrorStringWithFormat("unable to load '%s'", path);
+
+ arguments.GetValueAtIndex(0)->GetScalar() = path_addr;
+ arguments.GetValueAtIndex(1)->GetScalar() = path_array_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = buffer_addr;
+ arguments.GetValueAtIndex(3)->GetScalar() = return_addr;
+
+ lldb::addr_t func_args_addr = LLDB_INVALID_ADDRESS;
+
+ diagnostics.Clear();
+ if (!do_dlopen_function->WriteFunctionArguments(exe_ctx,
+ func_args_addr,
+ arguments,
+ diagnostics)) {
+ error.SetErrorStringWithFormat("dlopen error: could not write function "
+ "arguments: %s",
+ diagnostics.GetString().c_str());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we clean up the args structure. We can't reuse it because the
+ // Platform lives longer than the process and the Platforms don't get a
+ // signal to clean up cached data when a process goes away.
+ CleanUp args_cleanup([do_dlopen_function, &exe_ctx, func_args_addr] {
+ do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr);
+ });
+
+ // Now run the caller:
+ EvaluateExpressionOptions options;
+ options.SetExecutionPolicy(eExecutionPolicyAlways);
+ options.SetLanguage(eLanguageTypeC_plus_plus);
+ options.SetIgnoreBreakpoints(true);
+ options.SetUnwindOnError(true);
+ options.SetTrapExceptions(false); // dlopen can't throw exceptions, so
+ // don't do the work to trap them.
+ options.SetTimeout(std::chrono::seconds(2));
+
+ Value return_value;
+ // Fetch the clang types we will need:
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ CompilerType clang_void_pointer_type
+ = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ return_value.SetCompilerType(clang_void_pointer_type);
+
+ ExpressionResults results = do_dlopen_function->ExecuteFunction(
+ exe_ctx, &func_args_addr, options, diagnostics, return_value);
+ if (results != eExpressionCompleted) {
+ error.SetErrorStringWithFormat("dlopen error: failed executing "
+ "dlopen wrapper function: %s",
+ diagnostics.GetString().c_str());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Read the dlopen token from the return area:
+ lldb::addr_t token = process->ReadPointerFromMemory(return_addr,
+ utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not read the return "
+ "struct: %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // The dlopen succeeded!
+ if (token != 0x0) {
+ if (loaded_image && buffer_addr != 0x0)
+ {
+ // Capture the image which was loaded. We leave it in the buffer on
+ // exit from the dlopen function, so we can just read it from there:
+ std::string name_string;
+ process->ReadCStringFromMemory(buffer_addr, name_string, utility_error);
+ if (utility_error.Success())
+ loaded_image->SetFile(name_string, false,
+ llvm::sys::path::Style::posix);
+ }
+ return process->AddImageToken(token);
+ }
+
+ // We got an error, lets read in the error string:
+ std::string dlopen_error_str;
+ lldb::addr_t error_addr
+ = process->ReadPointerFromMemory(return_addr + addr_size, utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not read error string: "
+ "%s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ size_t num_chars = process->ReadCStringFromMemory(error_addr + addr_size,
+ dlopen_error_str,
+ utility_error);
+ if (utility_error.Success() && num_chars > 0)
+ error.SetErrorStringWithFormat("dlopen error: %s",
+ dlopen_error_str.c_str());
+ else
+ error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
+
return LLDB_INVALID_IMAGE_TOKEN;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 93bebeb332ca..cc6f7299c194 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -85,7 +85,7 @@ public:
const lldb::UnixSignalsSP &GetRemoteUnixSignals() override;
- size_t GetEnvironment(lldb_private::StringList &environment) override;
+ lldb_private::Environment GetEnvironment() override;
bool IsConnected() const override;
@@ -99,8 +99,7 @@ public:
// the process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec)
- override; // Timeout in seconds to wait for shell program to finish
+ const lldb_private::Timeout<std::micro> &timeout) override;
lldb_private::Status ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
@@ -166,7 +165,9 @@ public:
uint32_t DoLoadImage(lldb_private::Process *process,
const lldb_private::FileSpec &remote_file,
- lldb_private::Status &error) override;
+ const std::vector<std::string> *paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_image) override;
lldb_private::Status UnloadImage(lldb_private::Process *process,
uint32_t image_token) override;
@@ -201,6 +202,10 @@ protected:
llvm::StringRef expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
+ std::unique_ptr<lldb_private::UtilityFunction>
+ MakeLoadImageUtilityFunction(lldb_private::ExecutionContext &exe_ctx,
+ lldb_private::Status &error);
+
virtual
llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 759ec7fd1d29..348bb825a5c5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -118,9 +118,9 @@ Status PlatformRemoteGDBServer::ResolveExecutable(
return error;
exe_module_sp.reset();
}
- // No valid architecture was specified or the exact arch wasn't
- // found so ask the platform for the architectures that we should be
- // using (in the correct order) and see if we can find a match that way
+ // No valid architecture was specified or the exact arch wasn't found so
+ // ask the platform for the architectures that we should be using (in the
+ // correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
@@ -236,14 +236,8 @@ size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode(
}
bool PlatformRemoteGDBServer::GetRemoteOSVersion() {
- uint32_t major, minor, update;
- if (m_gdb_client.GetOSVersion(major, minor, update)) {
- m_major_os_version = major;
- m_minor_os_version = minor;
- m_update_os_version = update;
- return true;
- }
- return false;
+ m_os_version = m_gdb_client.GetOSVersion();
+ return !m_os_version.empty();
}
bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) {
@@ -277,8 +271,7 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory(
const FileSpec &working_dir) {
if (IsConnected()) {
// Clear the working directory it case it doesn't get set correctly. This
- // will
- // for use to re-read it
+ // will for use to re-read it
Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
if (log)
log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
@@ -423,16 +416,7 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
}
// Send the environment and the program + arguments after we connect
- const char **envp =
- launch_info.GetEnvironmentEntries().GetConstArgumentVector();
-
- if (envp) {
- const char *env_entry;
- for (int i = 0; (env_entry = envp[i]); ++i) {
- if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0)
- break;
- }
- }
+ m_gdb_client.SendEnvironment(launch_info.GetEnvironment());
ArchSpec arch_spec = launch_info.GetArchitecture();
const char *arch_triple = arch_spec.GetTriple().str().c_str();
@@ -549,9 +533,8 @@ bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid,
bool launch_result = false;
if (remote_triple.getVendor() == llvm::Triple::Apple &&
remote_triple.getOS() == llvm::Triple::IOS) {
- // When remote debugging to iOS, we use a USB mux that always talks
- // to localhost, so we will need the remote debugserver to accept
- // connections
+ // When remote debugging to iOS, we use a USB mux that always talks to
+ // localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
launch_result =
m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name);
@@ -731,11 +714,9 @@ Status PlatformRemoteGDBServer::RunShellCommand(
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
return m_gdb_client.RunShellCommand(command, working_dir, status_ptr,
- signo_ptr, command_output, timeout_sec);
+ signo_ptr, command_output, timeout);
}
void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
@@ -749,8 +730,8 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() {
if (m_remote_signals_sp)
return m_remote_signals_sp;
- // If packet not implemented or JSON failed to parse,
- // we'll guess the signal set based on the remote architecture.
+ // If packet not implemented or JSON failed to parse, we'll guess the signal
+ // set based on the remote architecture.
m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
StringExtractorGDBRemote response;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 210544f752e6..a31933b5d9b0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -17,7 +17,7 @@
// Other libraries and framework includes
// Project includes
-#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
+#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "lldb/Target/Platform.h"
@@ -155,8 +155,7 @@ public:
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t timeout_sec)
- override; // Timeout in seconds to wait for shell program to finish
+ const lldb_private::Timeout<std::micro> &timeout) override;
void CalculateTrapHandlerSymbolNames() override;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/CFString.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/CFString.cpp
index 84ad56774d7c..b87afe999181 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/CFString.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/CFString.cpp
@@ -91,9 +91,8 @@ const char *CFString::UTF8(std::string &str) {
return CFString::UTF8(get(), str);
}
-// Static function that puts a copy of the UTF8 contents of CF_STR into STR
-// and returns the C string pointer that is contained in STR when successful,
-// else
+// Static function that puts a copy of the UTF8 contents of CF_STR into STR and
+// returns the C string pointer that is contained in STR when successful, else
// NULL is returned. This allows the std::string parameter to own the extracted
// string,
// and also allows that string to be returned as a C string pointer that can be
@@ -120,9 +119,9 @@ const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
// Static function that puts a copy of the file system representation of CF_STR
// into STR and returns the C string pointer that is contained in STR when
-// successful, else NULL is returned. This allows the std::string parameter
-// to own the extracted string, and also allows that string to be returned as
-// a C string pointer that can be used.
+// successful, else NULL is returned. This allows the std::string parameter to
+// own the extracted string, and also allows that string to be returned as a C
+// string pointer that can be used.
const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
std::string &str) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
index 6b3d5f6c117f..95659725ce2e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
@@ -142,8 +142,8 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
}
// Use a fork that ties the child process's stdin/out/err to a pseudo
- // terminal so we can read it in our MachProcess::STDIOThread
- // as unbuffered io.
+ // terminal so we can read it in our MachProcess::STDIOThread as unbuffered
+ // io.
PseudoTerminal pty;
char fork_error[256];
memset(fork_error, 0, sizeof(fork_error));
@@ -167,12 +167,12 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
// Get BSD signals as mach exceptions.
::ptrace(PT_SIGEXC, 0, 0, 0);
- // If our parent is setgid, lets make sure we don't inherit those
- // extra powers due to nepotism.
+ // If our parent is setgid, lets make sure we don't inherit those extra
+ // powers due to nepotism.
if (::setgid(getgid()) == 0) {
- // Let the child have its own process group. We need to execute
- // this call in both the child and parent to avoid a race
- // condition between the two processes.
+ // Let the child have its own process group. We need to execute this call
+ // in both the child and parent to avoid a race condition between the two
+ // processes.
// Set the child process group to match its pid.
::setpgid(0, 0);
@@ -183,23 +183,22 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
// Turn this process into the given executable.
::execv(path, (char *const *)argv);
}
- // Exit with error code. Child process should have taken
- // over in above exec call and if the exec fails it will
- // exit the child process below.
+ // Exit with error code. Child process should have taken over in above exec
+ // call and if the exec fails it will exit the child process below.
::exit(127);
} else {
//--------------------------------------------------------------
// Parent process
//--------------------------------------------------------------
- // Let the child have its own process group. We need to execute
- // this call in both the child and parent to avoid a race condition
- // between the two processes.
+ // Let the child have its own process group. We need to execute this call
+ // in both the child and parent to avoid a race condition between the two
+ // processes.
// Set the child process group to match its pid
::setpgid(*pid, *pid);
if (pty_fd) {
- // Release our master pty file descriptor so the pty class doesn't
- // close it and so we can continue to use it in our STDIO thread
+ // Release our master pty file descriptor so the pty class doesn't close
+ // it and so we can continue to use it in our STDIO thread
*pty_fd = pty.ReleaseMasterFileDescriptor();
}
}
@@ -302,8 +301,7 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
return error;
}
- // Ensure we clean up the spawnattr structure however we exit this
- // function.
+ // Ensure we clean up the spawnattr structure however we exit this function.
std::unique_ptr<posix_spawnattr_t, int (*)(posix_spawnattr_t *)> spawnattr_up(
&attr, ::posix_spawnattr_destroy);
@@ -332,9 +330,9 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
#if !defined(__arm__)
- // We don't need to do this for ARM, and we really shouldn't now that we
- // have multiple CPU subtypes and no posix_spawnattr call that allows us
- // to set which CPU subtype to launch...
+ // We don't need to do this for ARM, and we really shouldn't now that we have
+ // multiple CPU subtypes and no posix_spawnattr call that allows us to set
+ // which CPU subtype to launch...
cpu_type_t desired_cpu_type = launch_info.GetArchitecture().GetMachOCPUType();
if (desired_cpu_type != LLDB_INVALID_CPUTYPE) {
size_t ocount = 0;
@@ -374,10 +372,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
int (*)(posix_spawn_file_actions_t *)>
file_actions_up(&file_actions, ::posix_spawn_file_actions_destroy);
- // We assume the caller has setup the file actions appropriately. We
- // are not in the business of figuring out what we really need here.
- // lldb-server will have already called FinalizeFileActions() as well
- // to button these up properly.
+ // We assume the caller has setup the file actions appropriately. We are not
+ // in the business of figuring out what we really need here. lldb-server will
+ // have already called FinalizeFileActions() as well to button these up
+ // properly.
const size_t num_actions = launch_info.GetNumFileActions();
for (size_t action_index = 0; action_index < num_actions; ++action_index) {
const FileAction *const action =
@@ -533,8 +531,8 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
if (error.Success()) {
launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
} else {
- // Reset any variables that might have been set during a failed
- // launch attempt.
+ // Reset any variables that might have been set during a failed launch
+ // attempt.
if (pty_master_fd)
*pty_master_fd = -1;
@@ -616,8 +614,8 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
if (pty_master_fd)
*pty_master_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
} else {
- // Reset any variables that might have been set during a failed
- // launch attempt.
+ // Reset any variables that might have been set during a failed launch
+ // attempt.
if (pty_master_fd)
*pty_master_fd = -1;
@@ -636,8 +634,8 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
}
if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
- // If we don't have a valid process ID and no one has set the error,
- // then return a generic error.
+ // If we don't have a valid process ID and no one has set the error, then
+ // return a generic error.
if (error.Success())
error.SetErrorStringWithFormat("%s(): failed to launch, no reason "
"specified",
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/MachException.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/MachException.cpp
index 9f5920753d68..353f2df32139 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/MachException.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/MachException.cpp
@@ -92,8 +92,6 @@ extern "C" kern_return_t catch_mach_exception_raise_state_identity(
(uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
(uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
}
- mach_port_deallocate(mach_task_self(), task_port);
- mach_port_deallocate(mach_task_self(), thread_port);
return KERN_FAILURE;
}
@@ -249,20 +247,19 @@ bool MachException::Message::CatchExceptionRaise(task_t task) {
bool success = false;
state.task_port = task;
g_message = &state;
- // The exc_server function is the MIG generated server handling function
- // to handle messages from the kernel relating to the occurrence of an
- // exception in a thread. Such messages are delivered to the exception port
- // set via thread_set_exception_ports or task_set_exception_ports. When an
- // exception occurs in a thread, the thread sends an exception message to
- // its exception port, blocking in the kernel waiting for the receipt of a
- // reply. The exc_server function performs all necessary argument handling
- // for this kernel message and calls catch_exception_raise,
- // catch_exception_raise_state or catch_exception_raise_state_identity,
- // which should handle the exception. If the called routine returns
- // KERN_SUCCESS, a reply message will be sent, allowing the thread to
- // continue from the point of the exception; otherwise, no reply message
- // is sent and the called routine must have dealt with the exception
- // thread directly.
+ // The exc_server function is the MIG generated server handling function to
+ // handle messages from the kernel relating to the occurrence of an exception
+ // in a thread. Such messages are delivered to the exception port set via
+ // thread_set_exception_ports or task_set_exception_ports. When an exception
+ // occurs in a thread, the thread sends an exception message to its exception
+ // port, blocking in the kernel waiting for the receipt of a reply. The
+ // exc_server function performs all necessary argument handling for this
+ // kernel message and calls catch_exception_raise,
+ // catch_exception_raise_state or catch_exception_raise_state_identity, which
+ // should handle the exception. If the called routine returns KERN_SUCCESS, a
+ // reply message will be sent, allowing the thread to continue from the point
+ // of the exception; otherwise, no reply message is sent and the called
+ // routine must have dealt with the exception thread directly.
if (mach_exc_server(&exc_msg.hdr, &reply_msg.hdr)) {
success = true;
} else {
@@ -385,9 +382,9 @@ Status MachException::PortInfo::Save(task_t task) {
log->Printf("MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__,
task);
- // Be careful to be able to have debugserver built on a newer OS than what
- // it is currently running on by being able to start with all exceptions
- // and back off to just what is supported on the current system
+ // Be careful to be able to have debugserver built on a newer OS than what it
+ // is currently running on by being able to start with all exceptions and
+ // back off to just what is supported on the current system
mask = LLDB_EXC_MASK;
count = (sizeof(ports) / sizeof(ports[0]));
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
index 518f0d2da4f2..3505443abcb0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
@@ -104,8 +104,8 @@ Status NativeProcessProtocol::Launch(
return error;
}
- // Finalize the processing needed to debug the launched process with
- // a NativeProcessDarwin instance.
+ // Finalize the processing needed to debug the launched process with a
+ // NativeProcessDarwin instance.
error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
if (!error.Success()) {
if (log)
@@ -194,9 +194,9 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
"mach exception port monitor thread: %s",
__FUNCTION__, error.AsCString());
- // Terminate the inferior process. There's nothing meaningful we can
- // do if we can't receive signals and exceptions. Since we launched
- // the process, it's fair game for us to kill it.
+ // Terminate the inferior process. There's nothing meaningful we can do if
+ // we can't receive signals and exceptions. Since we launched the process,
+ // it's fair game for us to kill it.
::ptrace(PT_KILL, m_pid, 0, 0);
SetState(eStateExited);
@@ -243,9 +243,9 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
}
if (TaskPortForProcessID(error) == TASK_NULL) {
- // We failed to get the task for our process ID which is bad.
- // Kill our process; otherwise, it will be stopped at the entry
- // point and get reparented to someone else and never go away.
+ // We failed to get the task for our process ID which is bad. Kill our
+ // process; otherwise, it will be stopped at the entry point and get
+ // reparented to someone else and never go away.
if (log)
log->Printf("NativeProcessDarwin::%s(): could not get task port "
"for process, sending SIGKILL and exiting: %s",
@@ -277,9 +277,9 @@ bool NativeProcessDarwin::ProcessUsingBackBoard() const {
return false;
}
-// Called by the exception thread when an exception has been received from
-// our process. The exception message is completely filled and the exception
-// data has already been copied.
+// Called by the exception thread when an exception has been received from our
+// process. The exception message is completely filled and the exception data
+// has already been copied.
void NativeProcessDarwin::ExceptionMessageReceived(
const MachException::Message &message) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
@@ -290,8 +290,8 @@ void NativeProcessDarwin::ExceptionMessageReceived(
SuspendTask();
}
- // Use a locker to automatically unlock our mutex in case of exceptions
- // Add the exception to our internal exception stack
+ // Use a locker to automatically unlock our mutex in case of exceptions Add
+ // the exception to our internal exception stack
m_exception_messages.push_back(message);
if (log)
@@ -324,13 +324,12 @@ void *NativeProcessDarwin::DoExceptionThread() {
// Ensure we don't get CPU starved.
MaybeRaiseThreadPriority();
- // We keep a count of the number of consecutive exceptions received so
- // we know to grab all exceptions without a timeout. We do this to get a
- // bunch of related exceptions on our exception port so we can process
- // then together. When we have multiple threads, we can get an exception
- // per thread and they will come in consecutively. The main loop in this
- // thread can stop periodically if needed to service things related to this
- // process.
+ // We keep a count of the number of consecutive exceptions received so we
+ // know to grab all exceptions without a timeout. We do this to get a bunch
+ // of related exceptions on our exception port so we can process then
+ // together. When we have multiple threads, we can get an exception per
+ // thread and they will come in consecutively. The main loop in this thread
+ // can stop periodically if needed to service things related to this process.
//
// [did we lose some words here?]
//
@@ -338,15 +337,15 @@ void *NativeProcessDarwin::DoExceptionThread() {
// 0 our exception port. After we get one exception, we then will use the
// MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
// exceptions for our process. After we have received the last pending
- // exception, we will get a timeout which enables us to then notify
- // our main thread that we have an exception bundle available. We then wait
- // for the main thread to tell this exception thread to start trying to get
+ // exception, we will get a timeout which enables us to then notify our main
+ // thread that we have an exception bundle available. We then wait for the
+ // main thread to tell this exception thread to start trying to get
// exceptions messages again and we start again with a mach_msg read with
// infinite timeout.
//
// We choose to park a thread on this, rather than polling, because the
- // polling is expensive. On devices, we need to minimize overhead caused
- // by the process monitor.
+ // polling is expensive. On devices, we need to minimize overhead caused by
+ // the process monitor.
uint32_t num_exceptions_received = 0;
Status error;
task_t task = m_task;
@@ -359,8 +358,7 @@ void *NativeProcessDarwin::DoExceptionThread() {
CFReleaser<SBSWatchdogAssertionRef> watchdog;
if (process->ProcessUsingSpringBoard()) {
- // Request a renewal for every 60 seconds if we attached using
- // SpringBoard.
+ // Request a renewal for every 60 seconds if we attached using SpringBoard.
watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60));
if (log)
log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
@@ -401,18 +399,18 @@ void *NativeProcessDarwin::DoExceptionThread() {
}
#endif // #ifdef WITH_BKS
- // Do we want to use a weak pointer to the NativeProcessDarwin here, in
- // which case we can guarantee we don't whack the process monitor if we
- // race between this thread and the main one on shutdown?
+ // Do we want to use a weak pointer to the NativeProcessDarwin here, in which
+ // case we can guarantee we don't whack the process monitor if we race
+ // between this thread and the main one on shutdown?
while (IsExceptionPortValid()) {
::pthread_testcancel();
MachException::Message exception_message;
if (num_exceptions_received > 0) {
- // We don't want a timeout here, just receive as many exceptions as
- // we can since we already have one. We want to get all currently
- // available exceptions for this task at once.
+ // We don't want a timeout here, just receive as many exceptions as we
+ // can since we already have one. We want to get all currently available
+ // exceptions for this task at once.
error = exception_message.Receive(
GetExceptionPort(),
MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0);
@@ -424,8 +422,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
MACH_RCV_TIMEOUT,
periodic_timeout);
} else {
- // We don't need to parse all current exceptions or stop
- // periodically, just wait for an exception forever.
+ // We don't need to parse all current exceptions or stop periodically,
+ // just wait for an exception forever.
error = exception_message.Receive(GetExceptionPort(),
MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0);
}
@@ -462,8 +460,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
__FUNCTION__);
continue;
} else {
- // The inferior task is no longer valid. Time to exit as
- // the process has gone away.
+ // The inferior task is no longer valid. Time to exit as the process
+ // has gone away.
if (log)
log->Printf("NativeProcessDarwin::%s(): the inferior task "
"has exited, and so will we...",
@@ -476,18 +474,17 @@ void *NativeProcessDarwin::DoExceptionThread() {
// We timed out when waiting for exceptions.
if (num_exceptions_received > 0) {
- // We were receiving all current exceptions with a timeout of
- // zero. It is time to go back to our normal looping mode.
+ // We were receiving all current exceptions with a timeout of zero.
+ // It is time to go back to our normal looping mode.
num_exceptions_received = 0;
- // Notify our main thread we have a complete exception message
- // bundle available. Get the possibly updated task port back
- // from the process in case we exec'ed and our task port
- // changed.
+ // Notify our main thread we have a complete exception message bundle
+ // available. Get the possibly updated task port back from the
+ // process in case we exec'ed and our task port changed.
task = ExceptionMessageBundleComplete();
- // In case we use a timeout value when getting exceptions,
- // make sure our task is still valid.
+ // In case we use a timeout value when getting exceptions, make sure
+ // our task is still valid.
if (IsTaskValid(task)) {
// Task is still ok.
if (log)
@@ -496,8 +493,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
__FUNCTION__);
continue;
} else {
- // The inferior task is no longer valid. Time to exit as
- // the process has gone away.
+ // The inferior task is no longer valid. Time to exit as the
+ // process has gone away.
if (log)
log->Printf("NativeProcessDarwin::%s(): the inferior "
"task has exited, and so will we...",
@@ -534,10 +531,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
// TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel
// when we
// all are up and running on systems that support it. The SBS framework has
- // a #define
- // that will forward SBSWatchdogAssertionRelease to
- // SBSWatchdogAssertionCancel for now
- // so it should still build either way.
+ // a #define that will forward SBSWatchdogAssertionRelease to
+ // SBSWatchdogAssertionCancel for now so it should still build either way.
DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)",
watchdog.get());
::SBSWatchdogAssertionRelease(watchdog.get());
@@ -728,8 +723,8 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
const int signo = m_exception_messages[i].state.SoftSignal();
if (signo == SIGTRAP) {
// SIGTRAP could mean that we exec'ed. We need to check the
- // dyld all_image_infos.infoArray to see if it is NULL and if
- // so, say that we exec'ed.
+ // dyld all_image_infos.infoArray to see if it is NULL and if so, say
+ // that we exec'ed.
const addr_t aii_addr = GetDYLDAllImageInfosAddress(error);
if (aii_addr == LLDB_INVALID_ADDRESS)
break;
@@ -744,12 +739,12 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
bytes_read); // #bytes read
if (read_error.Success() && (bytes_read == 4)) {
if (info_array_count == 0) {
- // We got the all infos address, and there are zero
- // entries. We think we exec'd.
+ // We got the all infos address, and there are zero entries. We
+ // think we exec'd.
m_did_exec = true;
- // Force the task port to update itself in case the
- // task port changed after exec
+ // Force the task port to update itself in case the task port
+ // changed after exec
const task_t old_task = m_task;
const bool force_update = true;
const task_t new_task = TaskPortForProcessID(error, force_update);
@@ -810,8 +805,7 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
// 4 - We might need to resume if we stopped only with the
// interrupt signal that we never handled.
if (m_auto_resume_signo != 0) {
- // Only auto_resume if we stopped with _only_ the interrupt
- // signal.
+ // Only auto_resume if we stopped with _only_ the interrupt signal.
if (num_task_exceptions == 1) {
auto_resume = true;
if (log)
@@ -831,8 +825,8 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
}
}
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list.ProcessDidStop(*this);
// Let each thread know of any exceptions
@@ -863,8 +857,8 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
// TODO - need to hook up event system here. !!!!
#if 0
// Wait for the eEventProcessRunningStateChanged event to be reset
- // before changing state to stopped to avoid race condition with
- // very fast start/stops.
+ // before changing state to stopped to avoid race condition with very
+ // fast start/stops.
struct timespec timeout;
//DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 ms
@@ -889,12 +883,12 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) {
Status error;
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Strategy: create a thread that sits on waitpid(), waiting for the
- // inferior process to die, reaping it in the process. Arrange for
- // the thread to have a pipe file descriptor that it can send a byte
- // over when the waitpid completes. Have the main loop have a read
- // object for the other side of the pipe, and have the callback for
- // the read do the process termination message sending.
+ // Strategy: create a thread that sits on waitpid(), waiting for the inferior
+ // process to die, reaping it in the process. Arrange for the thread to have
+ // a pipe file descriptor that it can send a byte over when the waitpid
+ // completes. Have the main loop have a read object for the other side of
+ // the pipe, and have the callback for the read do the process termination
+ // message sending.
// Create a single-direction communication channel.
const bool child_inherits = false;
@@ -1025,8 +1019,8 @@ void *NativeProcessDarwin::DoWaitpidThread() {
}
}
- // We should never exit as long as our child process is alive. If we
- // get here, something completely unexpected went wrong and we should exit.
+ // We should never exit as long as our child process is alive. If we get
+ // here, something completely unexpected went wrong and we should exit.
if (log)
log->Printf(
"NativeProcessDarwin::%s(): internal error: waitpid thread "
@@ -1157,8 +1151,8 @@ task_t NativeProcessDarwin::TaskPortForProcessID(Status &error,
::usleep(usec_interval);
}
- // We failed to get the task for the inferior process.
- // Ensure that it is cleared out.
+ // We failed to get the task for the inferior process. Ensure that it is
+ // cleared out.
m_task = TASK_NULL;
}
return m_task;
@@ -1196,9 +1190,9 @@ Status NativeProcessDarwin::PrivateResume() {
}
// bool stepOverBreakInstruction = step;
- // Let the thread prepare to resume and see if any threads want us to
- // step over a breakpoint instruction (ProcessWillResume will modify
- // the value of stepOverBreakInstruction).
+ // Let the thread prepare to resume and see if any threads want us to step
+ // over a breakpoint instruction (ProcessWillResume will modify the value of
+ // stepOverBreakInstruction).
m_thread_list.ProcessWillResume(*this, m_thread_actions);
// Set our state accordingly
@@ -1254,8 +1248,8 @@ Status NativeProcessDarwin::ReplyToAllExceptions() {
error = message.Reply(m_pid, m_task, thread_reply_signal);
if (error.Fail() && log) {
- // We log any error here, but we don't stop the exception
- // response handling.
+ // We log any error here, but we don't stop the exception response
+ // handling.
log->Printf("NativeProcessDarwin::%s(): failed to reply to "
"exception: %s",
__FUNCTION__, error.AsCString());
@@ -1263,8 +1257,8 @@ Status NativeProcessDarwin::ReplyToAllExceptions() {
}
}
- // Erase all exception message as we should have used and replied
- // to them all already.
+ // Erase all exception message as we should have used and replied to them all
+ // already.
m_exception_messages.clear();
return error;
}
@@ -1292,8 +1286,8 @@ Status NativeProcessDarwin::ResumeTask() {
"0x%4.4x",
__FUNCTION__, m_task);
- // Get the BasicInfo struct to verify that we're suspended before we try
- // to resume the task.
+ // Get the BasicInfo struct to verify that we're suspended before we try to
+ // resume the task.
struct task_basic_info task_info;
error = GetTaskBasicInfo(m_task, &task_info);
if (error.Fail()) {
@@ -1304,9 +1298,8 @@ Status NativeProcessDarwin::ResumeTask() {
return error;
}
- // task_resume isn't counted like task_suspend calls are, so if the
- // task is not suspended, don't try and resume it since it is already
- // running
+ // task_resume isn't counted like task_suspend calls are, so if the task is
+ // not suspended, don't try and resume it since it is already running
if (task_info.suspend_count > 0) {
auto mach_err = ::task_resume(m_task);
error.SetError(mach_err, eErrorTypeMachKernel);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h
index 649280c17a8f..0b186fd7d80c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h
@@ -43,10 +43,10 @@ class Scalar;
namespace process_darwin {
/// @class NativeProcessDarwin
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior
-/// process for debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessDarwin : public NativeProcessProtocol {
@@ -205,10 +205,10 @@ private:
// -----------------------------------------------------------------
/// Finalize the launch.
///
- /// This method associates the NativeProcessDarwin instance with
- /// the host process that was just launched. It peforms actions
- /// like attaching a listener to the inferior exception port,
- /// ptracing the process, and the like.
+ /// This method associates the NativeProcessDarwin instance with the host
+ /// process that was just launched. It peforms actions like attaching a
+ /// listener to the inferior exception port, ptracing the process, and the
+ /// like.
///
/// @param[in] launch_flavor
/// The launch flavor that was used to launch the process.
@@ -263,8 +263,8 @@ private:
task_t TaskPortForProcessID(Status &error, bool force = false) const;
- /// Attaches to an existing process. Forms the
- /// implementation of Process::DoAttach.
+ /// Attaches to an existing process. Forms the implementation of
+ /// Process::DoAttach.
void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error);
::pid_t Attach(lldb::pid_t pid, Status &error);
@@ -323,8 +323,8 @@ private:
Status GetSignalInfo(lldb::tid_t tid, void *siginfo);
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread ID to the memory pointed to
- /// by @p message.
+ /// corresponding to the given thread ID to the memory pointed to by @p
+ /// message.
Status GetEventMessage(lldb::tid_t tid, unsigned long *message);
void NotifyThreadDeath(lldb::tid_t tid);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
index 07398ab7b678..521c6d5c8fd0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
@@ -30,8 +30,8 @@ uint64_t NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID(
(thread_info_t)&tident, &tident_count);
if (mach_err != KERN_SUCCESS) {
// When we fail to get thread info for the supposed port, assume it is
- // really a globally unique thread id already, or return the best thing
- // we can, which is the thread port.
+ // really a globally unique thread id already, or return the best thing we
+ // can, which is the thread port.
return mach_port_id;
}
return tident.thread_id;
@@ -47,9 +47,9 @@ NativeThreadDarwin::NativeThreadDarwin(NativeProcessDarwin *process,
bool NativeThreadDarwin::GetIdentifierInfo() {
// Don't try to get the thread info once and cache it for the life of the
- // thread. It changes over time, for instance
- // if the thread name changes, then the thread_handle also changes... So you
- // have to refetch it every time.
+ // thread. It changes over time, for instance if the thread name changes,
+ // then the thread_handle also changes... So you have to refetch it every
+ // time.
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
kern_return_t kret = ::thread_info(m_mach_thread_port, THREAD_IDENTIFIER_INFO,
(thread_info_t)&m_ident_info, &count);
@@ -137,16 +137,16 @@ bool NativeThreadDarwin::NotifyException(MachException::Data &exc) {
// TODO implement this.
#if 0
// Allow the arch specific protocol to process (MachException::Data &)exc
- // first before possible reassignment of m_stop_exception with exc.
- // See also MachThread::GetStopException().
+ // first before possible reassignment of m_stop_exception with exc. See
+ // also MachThread::GetStopException().
bool handled = m_arch_ap->NotifyException(exc);
if (m_stop_exception.IsValid())
{
// We may have more than one exception for a thread, but we need to
- // only remember the one that we will say is the reason we stopped.
- // We may have been single stepping and also gotten a signal exception,
- // so just remember the most pertinent one.
+ // only remember the one that we will say is the reason we stopped. We
+ // may have been single stepping and also gotten a signal exception, so
+ // just remember the most pertinent one.
if (m_stop_exception.IsBreakpoint())
m_stop_exception = exc;
}
@@ -170,8 +170,8 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
if (bp)
{
- // This thread is sitting at a breakpoint, ask the breakpoint
- // if we should be stopping here.
+ // This thread is sitting at a breakpoint, ask the breakpoint if we
+ // should be stopping here.
return true;
}
else
@@ -181,11 +181,10 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
step_more = true;
return false;
}
- // The thread state is used to let us know what the thread was
- // trying to do. MachThread::ThreadWillResume() will set the
- // thread state to various values depending if the thread was
- // the current thread and if it was to be single stepped, or
- // resumed.
+ // The thread state is used to let us know what the thread was trying
+ // to do. MachThread::ThreadWillResume() will set the thread state to
+ // various values depending if the thread was the current thread and if
+ // it was to be single stepped, or resumed.
if (GetState() == eStateRunning)
{
// If our state is running, then we should continue as we are in
@@ -194,8 +193,7 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
}
else
{
- // Stop if we have any kind of valid exception for this
- // thread.
+ // Stop if we have any kind of valid exception for this thread.
if (GetStopException().IsValid())
return true;
}
@@ -209,17 +207,17 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
void NativeThreadDarwin::ThreadDidStop() {
// TODO implement this.
#if 0
- // This thread has existed prior to resuming under debug nub control,
- // and has just been stopped. Do any cleanup that needs to be done
- // after running.
+ // This thread has existed prior to resuming under debug nub control, and
+ // has just been stopped. Do any cleanup that needs to be done after
+ // running.
- // The thread state and breakpoint will still have the same values
- // as they had prior to resuming the thread, so it makes it easy to check
- // if we were trying to step a thread, or we tried to resume while being
- // at a breakpoint.
+ // The thread state and breakpoint will still have the same values as they
+ // had prior to resuming the thread, so it makes it easy to check if we
+ // were trying to step a thread, or we tried to resume while being at a
+ // breakpoint.
- // When this method gets called, the process state is still in the
- // state it was in while running so we can act accordingly.
+ // When this method gets called, the process state is still in the state it
+ // was in while running so we can act accordingly.
m_arch_ap->ThreadDidStop();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
index 7d44adeec375..4ff662e42097 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
@@ -308,8 +308,8 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
__FUNCTION__, process.GetID(), update, process.GetStopID());
if (process.GetStopID() == 0) {
- // On our first stop, we'll record details like 32/64 bitness and
- // select the proper architecture implementation.
+ // On our first stop, we'll record details like 32/64 bitness and select
+ // the proper architecture implementation.
//
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)process.GetID()};
@@ -358,9 +358,9 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
if (thread_list_count > 0) {
collection currThreads;
size_t idx;
- // Iterator through the current thread list and see which threads
- // we already have in our list (keep them), which ones we don't
- // (add them), and which ones are not around anymore (remove them).
+ // Iterator through the current thread list and see which threads we
+ // already have in our list (keep them), which ones we don't (add them),
+ // and which ones are not around anymore (remove them).
for (idx = 0; idx < thread_list_count; ++idx) {
// Get the Mach thread port.
const ::thread_t mach_port_num = thread_list[idx];
@@ -373,18 +373,18 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
// Retrieve the thread if it exists.
auto thread_sp = GetThreadByID(unique_thread_id);
if (thread_sp) {
- // We are already tracking it. Keep the existing native
- // thread instance.
+ // We are already tracking it. Keep the existing native thread
+ // instance.
currThreads.push_back(thread_sp);
} else {
- // We don't have a native thread instance for this thread.
- // Create it now.
+ // We don't have a native thread instance for this thread. Create it
+ // now.
thread_sp.reset(new NativeThreadDarwin(
&process, m_is_64_bit, unique_thread_id, mach_port_num));
- // Add the new thread regardless of its is user ready state.
- // Make sure the thread is ready to be displayed and shown
- // to users before we add this thread to our list...
+ // Add the new thread regardless of its is user ready state. Make
+ // sure the thread is ready to be displayed and shown to users before
+ // we add this thread to our list...
if (thread_sp->IsUserReady()) {
if (new_threads)
new_threads->push_back(thread_sp);
@@ -417,9 +417,9 @@ NativeThreadListDarwin::CurrentThread (MachThreadSP& thread_sp)
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
if (m_current_thread.get() == NULL)
{
- // Figure out which thread is going to be our current thread.
- // This is currently done by finding the first thread in the list
- // that has a valid exception.
+ // Figure out which thread is going to be our current thread. This is
+ // currently done by finding the first thread in the list that has a
+ // valid exception.
const size_t num_threads = m_threads.size();
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
@@ -455,8 +455,8 @@ void NativeThreadListDarwin::ProcessWillResume(
NativeProcessDarwin &process, const ResumeActionList &thread_actions) {
std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- // Update our thread list, because sometimes libdispatch or the kernel
- // will spawn threads while a task is suspended.
+ // Update our thread list, because sometimes libdispatch or the kernel will
+ // spawn threads while a task is suspended.
NativeThreadListDarwin::collection new_threads;
// TODO implement this.
@@ -489,7 +489,8 @@ void NativeThreadListDarwin::ProcessWillResume(
#if 0
DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS };
- // If we are planning to run only one thread, any new threads should be suspended.
+ // If we are planning to run only one thread, any new threads should be
+ // suspended.
if (run_one_thread)
resume_new_threads.state = eStateSuspended;
@@ -549,11 +550,11 @@ uint32_t NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process) {
}
//----------------------------------------------------------------------
-// Check each thread in our thread list to see if we should notify our
-// client of the current halt in execution.
+// Check each thread in our thread list to see if we should notify our client
+// of the current halt in execution.
//
-// Breakpoints can have callback functions associated with them than
-// can return true to stop, or false to continue executing the inferior.
+// Breakpoints can have callback functions associated with them than can return
+// true to stop, or false to continue executing the inferior.
//
// RETURNS
// true if we should stop and notify our clients
@@ -607,8 +608,9 @@ NativeThreadListDarwin::DisableHardwareBreakpoint (const DNBBreakpoint* bp) cons
return false;
}
-// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> MachProcess::EnableWatchpoint()
-// -> NativeThreadListDarwin::EnableHardwareWatchpoint().
+// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() ->
+// MachProcess::EnableWatchpoint() ->
+// NativeThreadListDarwin::EnableHardwareWatchpoint().
uint32_t
NativeThreadListDarwin::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
{
@@ -617,14 +619,16 @@ NativeThreadListDarwin::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
{
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
const size_t num_threads = m_threads.size();
- // On Mac OS X we have to prime the control registers for new threads. We do this
- // using the control register data for the first thread, for lack of a better way of choosing.
+ // On Mac OS X we have to prime the control registers for new threads.
+ // We do this using the control register data for the first thread, for
+ // lack of a better way of choosing.
bool also_set_on_task = true;
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp, also_set_on_task)) == INVALID_NUB_HW_INDEX)
{
- // We know that idx failed for some reason. Let's rollback the transaction for [0, idx).
+ // We know that idx failed for some reason. Let's rollback the
+ // transaction for [0, idx).
for (uint32_t i = 0; i < idx; ++i)
m_threads[i]->RollbackTransForHWP();
return INVALID_NUB_HW_INDEX;
@@ -647,14 +651,16 @@ NativeThreadListDarwin::DisableHardwareWatchpoint (const DNBBreakpoint* wp) cons
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
const size_t num_threads = m_threads.size();
- // On Mac OS X we have to prime the control registers for new threads. We do this
- // using the control register data for the first thread, for lack of a better way of choosing.
+ // On Mac OS X we have to prime the control registers for new threads.
+ // We do this using the control register data for the first thread, for
+ // lack of a better way of choosing.
bool also_set_on_task = true;
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task))
{
- // We know that idx failed for some reason. Let's rollback the transaction for [0, idx).
+ // We know that idx failed for some reason. Let's rollback the
+ // transaction for [0, idx).
for (uint32_t i = 0; i < idx; ++i)
m_threads[i]->RollbackTransForHWP();
return false;
@@ -675,7 +681,8 @@ NativeThreadListDarwin::NumSupportedHardwareWatchpoints () const
{
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
const size_t num_threads = m_threads.size();
- // Use an arbitrary thread to retrieve the number of supported hardware watchpoints.
+ // Use an arbitrary thread to retrieve the number of supported hardware
+ // watchpoints.
if (num_threads)
return m_threads[0]->NumSupportedHardwareWatchpoints();
return 0;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
index f1c480c813de..66d3ca77fa91 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -57,7 +57,7 @@ using namespace lldb_private;
FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
: Thread(process, tid), m_frame_ap(), m_breakpoint(),
- m_thread_name_valid(false), m_thread_name(), m_posix_thread(NULL) {
+ m_thread_name_valid(false), m_thread_name(), m_posix_thread(nullptr) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
LLDB_LOGV(log, "tid = {0}", tid);
@@ -69,15 +69,15 @@ FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) {
lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
if (wp.get() && wp->IsEnabled()) {
- // This watchpoint as been enabled; obviously this "new" thread
- // has been created since that watchpoint was enabled. Since
- // the POSIXBreakpointProtocol has yet to be initialized, its
- // m_watchpoints_initialized member will be FALSE. Attempting to
- // read the debug status register to determine if a watchpoint
- // has been hit would result in the zeroing of that register.
- // Since the active debug registers would have been cloned when
- // this thread was created, simply force the m_watchpoints_initized
- // member to TRUE and avoid resetting dr6 and dr7.
+ // This watchpoint as been enabled; obviously this "new" thread has been
+ // created since that watchpoint was enabled. Since the
+ // POSIXBreakpointProtocol has yet to be initialized, its
+ // m_watchpoints_initialized member will be FALSE. Attempting to read
+ // the debug status register to determine if a watchpoint has been hit
+ // would result in the zeroing of that register. Since the active debug
+ // registers would have been cloned when this thread was created, simply
+ // force the m_watchpoints_initized member to TRUE and avoid resetting
+ // dr6 and dr7.
GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
}
}
@@ -98,16 +98,15 @@ void FreeBSDThread::RefreshStateAfterStop() {
// context by the time this function gets called. The KDPRegisterContext
// class has been made smart enough to detect when it needs to invalidate
// which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- // if (StateIsStoppedState(GetState())
+ // register supply functions where they check the process stop ID and do the
+ // right thing. if (StateIsStoppedState(GetState())
{
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded(force);
}
}
-const char *FreeBSDThread::GetInfo() { return NULL; }
+const char *FreeBSDThread::GetInfo() { return nullptr; }
void FreeBSDThread::SetName(const char *name) {
m_thread_name_valid = (name && name[0]);
@@ -158,15 +157,15 @@ const char *FreeBSDThread::GetName() {
}
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() {
if (!m_reg_context_sp) {
- m_posix_thread = NULL;
+ m_posix_thread = nullptr;
- RegisterInfoInterface *reg_interface = NULL;
+ RegisterInfoInterface *reg_interface = nullptr;
const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
switch (target_arch.GetMachine()) {
@@ -281,7 +280,7 @@ bool FreeBSDThread::CalculateStopInfo() {
}
Unwind *FreeBSDThread::GetUnwinder() {
- if (m_unwinder_ap.get() == NULL)
+ if (!m_unwinder_ap)
m_unwinder_ap.reset(new UnwindLLDB(*this));
return m_unwinder_ap.get();
@@ -468,22 +467,19 @@ void FreeBSDThread::BreakNotify(const ProcessMessage &message) {
GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
// If the breakpoint is for this thread, then we'll report the hit, but if it
- // is for another thread,
- // we create a stop reason with should_stop=false. If there is no breakpoint
- // location, then report
- // an invalid stop reason. We don't need to worry about stepping over the
- // breakpoint here, that will
- // be taken care of when the thread resumes and notices that there's a
+ // is for another thread, we create a stop reason with should_stop=false. If
+ // there is no breakpoint location, then report an invalid stop reason. We
+ // don't need to worry about stepping over the breakpoint here, that will be
+ // taken care of when the thread resumes and notices that there's a
// breakpoint under the pc.
if (bp_site) {
lldb::break_id_t bp_id = bp_site->GetID();
// If we have an operating system plug-in, we might have set a thread
- // specific breakpoint using the
- // operating system thread ID, so we can't make any assumptions about the
- // thread ID so we must always
- // report the breakpoint regardless of the thread.
+ // specific breakpoint using the operating system thread ID, so we can't
+ // make any assumptions about the thread ID so we must always report the
+ // breakpoint regardless of the thread.
if (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != NULL)
+ GetProcess()->GetOperatingSystem() != nullptr)
SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
else {
const bool should_stop = false;
@@ -540,15 +536,14 @@ void FreeBSDThread::TraceNotify(const ProcessMessage &message) {
lldb::BreakpointSiteSP bp_site(
GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
- // If the current pc is a breakpoint site then set the StopInfo to Breakpoint.
- // Otherwise, set the StopInfo to Watchpoint or Trace.
- // If we have an operating system plug-in, we might have set a thread specific
- // breakpoint using the
- // operating system thread ID, so we can't make any assumptions about the
- // thread ID so we must always
- // report the breakpoint regardless of the thread.
+ // If the current pc is a breakpoint site then set the StopInfo to
+ // Breakpoint. Otherwise, set the StopInfo to Watchpoint or Trace. If we have
+ // an operating system plug-in, we might have set a thread specific
+ // breakpoint using the operating system thread ID, so we can't make any
+ // assumptions about the thread ID so we must always report the breakpoint
+ // regardless of the thread.
if (bp_site && (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != NULL))
+ GetProcess()->GetOperatingSystem() != nullptr))
SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(
*this, bp_site->GetID()));
else {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
index 72e846459552..c93cc4fbfd73 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -24,7 +24,7 @@ class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class FreeBSDThread
-// @brief Abstraction of a FreeBSD thread.
+// Abstraction of a FreeBSD thread.
class FreeBSDThread : public lldb_private::Thread {
public:
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
index 96861852b38e..ff3693107170 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
@@ -17,7 +17,7 @@
//===----------------------------------------------------------------------===//
/// @class POSIXStopInfo
-/// @brief Simple base class for all POSIX-specific StopInfo objects.
+/// Simple base class for all POSIX-specific StopInfo objects.
///
class POSIXStopInfo : public lldb_private::StopInfo {
public:
@@ -27,7 +27,7 @@ public:
//===----------------------------------------------------------------------===//
/// @class POSIXLimboStopInfo
-/// @brief Represents the stop state of a process ready to exit.
+/// Represents the stop state of a process ready to exit.
///
class POSIXLimboStopInfo : public POSIXStopInfo {
public:
@@ -46,7 +46,7 @@ public:
//===----------------------------------------------------------------------===//
/// @class POSIXNewThreadStopInfo
-/// @brief Represents the stop state of process when a new thread is spawned.
+/// Represents the stop state of process when a new thread is spawned.
///
class POSIXNewThreadStopInfo : public POSIXStopInfo {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index 7a937db49be0..fa0bcea8f6bd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -357,10 +357,10 @@ ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) {
file_spec = file_action->GetFileSpec();
- // By default the stdio paths passed in will be pseudo-terminal
- // (/dev/pts). If so, convert to using a different default path
- // instead to redirect I/O to the debugger console. This should
- // also handle user overrides to /dev/null or a different file.
+ // By default the stdio paths passed in will be pseudo-terminal (/dev/pts).
+ // If so, convert to using a different default path instead to redirect I/O
+ // to the debugger console. This should also handle user overrides to
+ // /dev/null or a different file.
if (!file_spec || file_spec == dbg_pts_file_spec)
file_spec = default_file_spec;
}
@@ -407,9 +407,8 @@ Status ProcessFreeBSD::DoLaunch(Module *module,
m_monitor = new ProcessMonitor(
this, module, launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
- stdin_file_spec, stdout_file_spec, stderr_file_spec, working_dir,
- launch_info, error);
+ launch_info.GetEnvironment(), stdin_file_spec, stdout_file_spec,
+ stderr_file_spec, working_dir, launch_info, error);
m_module = module;
@@ -656,19 +655,19 @@ ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite *bp_site) {
break;
case llvm::Triple::arm: {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
- // but the linux kernel does otherwise.
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
+ // linux kernel does otherwise.
static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = eAddressClassUnknown;
+ AddressClass addr_class = AddressClass::eUnknown;
if (bp_loc_sp)
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == eAddressClassCodeAlternateISA ||
- (addr_class == eAddressClassUnknown &&
+ if (addr_class == AddressClass::eCodeAlternateISA ||
+ (addr_class == AddressClass::eUnknown &&
bp_loc_sp->GetAddress().GetOffset() & 1)) {
opcode = g_thumb_breakpoint_opcode;
opcode_size = sizeof(g_thumb_breakpoint_opcode);
@@ -745,8 +744,8 @@ Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) {
wp->SetEnabled(true, notify);
return error;
} else {
- // Watchpoint enabling failed on at least one
- // of the threads so roll back all of them
+ // Watchpoint enabling failed on at least one of the threads so roll
+ // back all of them
DisableWatchpoint(wp, false);
error.SetErrorString("Setting hardware watchpoint failed");
}
@@ -813,8 +812,8 @@ Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) {
Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
Status error = GetWatchpointSupportInfo(num);
- // Watchpoints trigger and halt the inferior after
- // the corresponding instruction has been executed.
+ // Watchpoints trigger and halt the inferior after the corresponding
+ // instruction has been executed.
after = true;
return error;
}
@@ -1077,8 +1076,8 @@ Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) {
"Emulation was successful but PC wasn't updated");
next_pc = pc_it->second.GetAsUInt64();
} else if (pc_it == baton.m_register_values.end()) {
- // Emulate instruction failed and it haven't changed PC. Advance PC
- // with the size of the current opcode because the emulation of all
+ // Emulate instruction failed and it haven't changed PC. Advance PC with
+ // the size of the current opcode because the emulation of all
// PC modifying instruction should be successful. The failure most
// likely caused by a not supported instruction which don't modify PC.
next_pc =
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index c64c1ec92e24..51fdf2e5ef33 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -38,15 +38,11 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
-extern "C" {
-extern char **environ;
-}
-
using namespace lldb;
using namespace lldb_private;
-// We disable the tracing of ptrace calls for integration builds to
-// avoid the additional indirection and checks.
+// We disable the tracing of ptrace calls for integration builds to avoid the
+// additional indirection and checks.
#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
// Wrapper for ptrace to catch errors and log calls.
@@ -65,9 +61,8 @@ const char *Get_PT_IO_OP(int op) {
}
}
-// Wrapper for ptrace to catch errors and log calls.
-// Note that ptrace sets errno on error because -1 is reserved as a valid
-// result.
+// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets
+// errno on error because -1 is reserved as a valid result.
extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
const char *reqName, const char *file, int line) {
long int result;
@@ -134,8 +129,8 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
return result;
}
-// Wrapper for ptrace when logging is not required.
-// Sets errno to 0 prior to calling ptrace.
+// Wrapper for ptrace when logging is not required. Sets errno to 0 prior to
+// calling ptrace.
extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) {
long result = 0;
errno = 0;
@@ -179,8 +174,10 @@ static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr,
pi_desc.piod_addr = (void *)buf;
pi_desc.piod_len = size;
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+ if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
error.SetErrorToErrno();
+ return 0;
+ }
return pi_desc.piod_len;
}
@@ -204,15 +201,16 @@ static bool EnsureFDFlags(int fd, int flags, Status &error) {
//------------------------------------------------------------------------------
/// @class Operation
-/// @brief Represents a ProcessMonitor operation.
+/// Represents a ProcessMonitor operation.
///
-/// Under FreeBSD, it is not possible to ptrace() from any other thread but the
-/// one that spawned or attached to the process from the start. Therefore, when
-/// a ProcessMonitor is asked to deliver or change the state of an inferior
-/// process the operation must be "funneled" to a specific thread to perform the
-/// task. The Operation class provides an abstract base for all services the
-/// ProcessMonitor must perform via the single virtual function Execute, thus
-/// encapsulating the code that needs to run in the privileged context.
+/// Under FreeBSD, it is not possible to ptrace() from any other thread but
+/// the one that spawned or attached to the process from the start.
+/// Therefore, when a ProcessMonitor is asked to deliver or change the state
+/// of an inferior process the operation must be "funneled" to a specific
+/// thread to perform the task. The Operation class provides an abstract base
+/// for all services the ProcessMonitor must perform via the single virtual
+/// function Execute, thus encapsulating the code that needs to run in the
+/// privileged context.
class Operation {
public:
virtual ~Operation() {}
@@ -221,7 +219,7 @@ public:
//------------------------------------------------------------------------------
/// @class ReadOperation
-/// @brief Implements ProcessMonitor::ReadMemory.
+/// Implements ProcessMonitor::ReadMemory.
class ReadOperation : public Operation {
public:
ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &error,
@@ -247,7 +245,7 @@ void ReadOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteOperation
-/// @brief Implements ProcessMonitor::WriteMemory.
+/// Implements ProcessMonitor::WriteMemory.
class WriteOperation : public Operation {
public:
WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
@@ -273,7 +271,7 @@ void WriteOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadRegOperation
-/// @brief Implements ProcessMonitor::ReadRegisterValue.
+/// Implements ProcessMonitor::ReadRegisterValue.
class ReadRegOperation : public Operation {
public:
ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
@@ -313,7 +311,7 @@ void ReadRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteRegOperation
-/// @brief Implements ProcessMonitor::WriteRegisterValue.
+/// Implements ProcessMonitor::WriteRegisterValue.
class WriteRegOperation : public Operation {
public:
WriteRegOperation(lldb::tid_t tid, unsigned offset,
@@ -346,7 +344,7 @@ void WriteRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadDebugRegOperation
-/// @brief Implements ProcessMonitor::ReadDebugRegisterValue.
+/// Implements ProcessMonitor::ReadDebugRegisterValue.
class ReadDebugRegOperation : public Operation {
public:
ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
@@ -381,7 +379,7 @@ void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteDebugRegOperation
-/// @brief Implements ProcessMonitor::WriteDebugRegisterValue.
+/// Implements ProcessMonitor::WriteDebugRegisterValue.
class WriteDebugRegOperation : public Operation {
public:
WriteDebugRegOperation(lldb::tid_t tid, unsigned offset,
@@ -414,7 +412,7 @@ void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadGPROperation
-/// @brief Implements ProcessMonitor::ReadGPR.
+/// Implements ProcessMonitor::ReadGPR.
class ReadGPROperation : public Operation {
public:
ReadGPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -441,7 +439,7 @@ void ReadGPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadFPROperation
-/// @brief Implements ProcessMonitor::ReadFPR.
+/// Implements ProcessMonitor::ReadFPR.
class ReadFPROperation : public Operation {
public:
ReadFPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -464,7 +462,7 @@ void ReadFPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteGPROperation
-/// @brief Implements ProcessMonitor::WriteGPR.
+/// Implements ProcessMonitor::WriteGPR.
class WriteGPROperation : public Operation {
public:
WriteGPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -487,7 +485,7 @@ void WriteGPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteFPROperation
-/// @brief Implements ProcessMonitor::WriteFPR.
+/// Implements ProcessMonitor::WriteFPR.
class WriteFPROperation : public Operation {
public:
WriteFPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -510,7 +508,7 @@ void WriteFPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ResumeOperation
-/// @brief Implements ProcessMonitor::Resume.
+/// Implements ProcessMonitor::Resume.
class ResumeOperation : public Operation {
public:
ResumeOperation(uint32_t signo, bool &result)
@@ -541,7 +539,7 @@ void ResumeOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class SingleStepOperation
-/// @brief Implements ProcessMonitor::SingleStep.
+/// Implements ProcessMonitor::SingleStep.
class SingleStepOperation : public Operation {
public:
SingleStepOperation(uint32_t signo, bool &result)
@@ -569,7 +567,7 @@ void SingleStepOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class LwpInfoOperation
-/// @brief Implements ProcessMonitor::GetLwpInfo.
+/// Implements ProcessMonitor::GetLwpInfo.
class LwpInfoOperation : public Operation {
public:
LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
@@ -598,7 +596,7 @@ void LwpInfoOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ThreadSuspendOperation
-/// @brief Implements ProcessMonitor::ThreadSuspend.
+/// Implements ProcessMonitor::ThreadSuspend.
class ThreadSuspendOperation : public Operation {
public:
ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
@@ -618,7 +616,7 @@ void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class EventMessageOperation
-/// @brief Implements ProcessMonitor::GetEventMessage.
+/// Implements ProcessMonitor::GetEventMessage.
class EventMessageOperation : public Operation {
public:
EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
@@ -648,7 +646,7 @@ void EventMessageOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class KillOperation
-/// @brief Implements ProcessMonitor::Kill.
+/// Implements ProcessMonitor::Kill.
class KillOperation : public Operation {
public:
KillOperation(bool &result) : m_result(result) {}
@@ -670,7 +668,7 @@ void KillOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class DetachOperation
-/// @brief Implements ProcessMonitor::Detach.
+/// Implements ProcessMonitor::Detach.
class DetachOperation : public Operation {
public:
DetachOperation(Status &result) : m_error(result) {}
@@ -697,13 +695,14 @@ ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); }
ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
lldb_private::Module *module,
- char const **argv, char const **envp,
+ char const **argv, Environment env,
const FileSpec &stdin_file_spec,
const FileSpec &stdout_file_spec,
const FileSpec &stderr_file_spec,
const FileSpec &working_dir)
- : OperationArgs(monitor), m_module(module), m_argv(argv), m_envp(envp),
- m_stdin_file_spec(stdin_file_spec), m_stdout_file_spec(stdout_file_spec),
+ : OperationArgs(monitor), m_module(module), m_argv(argv),
+ m_env(std::move(env)), m_stdin_file_spec(stdin_file_spec),
+ m_stdout_file_spec(stdout_file_spec),
m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {}
ProcessMonitor::LaunchArgs::~LaunchArgs() {}
@@ -716,11 +715,10 @@ ProcessMonitor::AttachArgs::~AttachArgs() {}
//------------------------------------------------------------------------------
/// The basic design of the ProcessMonitor is built around two threads.
///
-/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking
-/// for changes in the debugee state. When a change is detected a
+/// One thread (@see SignalThread) simply blocks on a call to waitpid()
+/// looking for changes in the debugee state. When a change is detected a
/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This
-/// thread
-/// "drives" state changes in the debugger.
+/// thread "drives" state changes in the debugger.
///
/// The second thread (@see OperationThread) is responsible for two things 1)
/// launching or attaching to the inferior process, and then 2) servicing
@@ -728,7 +726,7 @@ ProcessMonitor::AttachArgs::~AttachArgs() {}
/// on the Operation class for more info as to why this is needed.
ProcessMonitor::ProcessMonitor(
ProcessFreeBSD *process, Module *module, const char *argv[],
- const char *envp[], const FileSpec &stdin_file_spec,
+ Environment env, const FileSpec &stdin_file_spec,
const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec,
const FileSpec &working_dir,
const lldb_private::ProcessLaunchInfo & /* launch_info */,
@@ -738,7 +736,7 @@ ProcessMonitor::ProcessMonitor(
using namespace std::placeholders;
std::unique_ptr<LaunchArgs> args(
- new LaunchArgs(this, module, argv, envp, stdin_file_spec,
+ new LaunchArgs(this, module, argv, std::move(env), stdin_file_spec,
stdout_file_spec, stderr_file_spec, working_dir));
sem_init(&m_operation_pending, 0, 0);
@@ -839,7 +837,6 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
ProcessMonitor *monitor = args->m_monitor;
ProcessFreeBSD &process = monitor->GetProcess();
const char **argv = args->m_argv;
- const char **envp = args->m_envp;
const FileSpec &stdin_file_spec = args->m_stdin_file_spec;
const FileSpec &stdout_file_spec = args->m_stdout_file_spec;
const FileSpec &stderr_file_spec = args->m_stderr_file_spec;
@@ -851,8 +848,8 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
::pid_t pid;
// Propagate the environment if one is not supplied.
- if (envp == NULL || envp[0] == NULL)
- envp = const_cast<const char **>(environ);
+ Environment::Envp envp =
+ (args->m_env.empty() ? Host::GetEnvironment() : args->m_env).getEnvp();
if ((pid = terminal.Fork(err_str, err_len)) == -1) {
args->m_error.SetErrorToGenericError();
@@ -877,9 +874,9 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
exit(ePtraceFailed);
- // terminal has already dupped the tty descriptors to stdin/out/err.
- // This closes original fd from which they were copied (and avoids
- // leaking descriptors to the debugged process.
+ // terminal has already dupped the tty descriptors to stdin/out/err. This
+ // closes original fd from which they were copied (and avoids leaking
+ // descriptors to the debugged process.
terminal.CloseSlaveFileDescriptor();
// Do not inherit setgid powers.
@@ -910,8 +907,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
exit(eChdirFailed);
// Execute. We should never return.
- execve(argv[0], const_cast<char *const *>(argv),
- const_cast<char *const *>(envp));
+ execve(argv[0], const_cast<char *const *>(argv), envp);
exit(eExecFailed);
}
@@ -1105,9 +1101,9 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
break;
case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): {
- // The inferior process is about to exit. Maintain the process in a
- // state of "limbo" until we are explicitly commanded to detach,
- // destroy, resume, etc.
+ // The inferior process is about to exit. Maintain the process in a state
+ // of "limbo" until we are explicitly commanded to detach, destroy, resume,
+ // etc.
unsigned long data = 0;
if (!monitor->GetEventMessage(tid, &data))
data = -1;
@@ -1162,8 +1158,8 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// POSIX says that process behaviour is undefined after it ignores a SIGFPE,
- // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
- // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD.
+ // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2)
+ // or raise(3). Similarly for tgkill(2) on FreeBSD.
//
// IOW, user generated signals never generate what we consider to be a
// "crash".
@@ -1199,8 +1195,8 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
} // else; Use atleast si_signo info for other si_code
}
- // Everything else is "normal" and does not require any special action on
- // our part.
+ // Everything else is "normal" and does not require any special action on our
+ // part.
return ProcessMessage::Signal(tid, signo);
}
@@ -1426,14 +1422,14 @@ void ProcessMonitor::StopMonitor() {
}
// FIXME: On Linux, when a new thread is created, we receive to notifications,
-// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
-// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
-// the new child thread indicating that it has is stopped because we attached.
-// We have no guarantee of the order in which these arrive, but we need both
-// before we are ready to proceed. We currently keep a list of threads which
-// have sent the initial SIGSTOP|SI_USER event. Then when we receive the
-// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
-// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
+// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the child
+// thread id as additional information, and (2) a SIGSTOP|SI_USER from the new
+// child thread indicating that it has is stopped because we attached. We have
+// no guarantee of the order in which these arrive, but we need both before we
+// are ready to proceed. We currently keep a list of threads which have sent
+// the initial SIGSTOP|SI_USER event. Then when we receive the
+// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not
+// occurred we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
//
// Right now, the above logic is in ProcessPOSIX, so we need a definition of
// this function in the FreeBSD ProcessMonitor implementation even if it isn't
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 0963453a31b1..1d3e2d746fa9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -32,10 +32,10 @@ class ProcessFreeBSD;
class Operation;
/// @class ProcessMonitor
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior process for
-/// debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are propagated to the associated
/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
@@ -48,7 +48,7 @@ public:
/// Launches an inferior process ready for debugging. Forms the
/// implementation of Process::DoLaunch.
ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module,
- char const *argv[], char const *envp[],
+ char const *argv[], lldb_private::Environment env,
const lldb_private::FileSpec &stdin_file_spec,
const lldb_private::FileSpec &stdout_file_spec,
const lldb_private::FileSpec &stderr_file_spec,
@@ -74,8 +74,7 @@ public:
/// standard error of this debugee. Even if stderr and stdout were
/// redirected on launch it may still happen that data is available on this
/// descriptor (if the inferior process opens /dev/tty, for example). This
- /// descriptor is
- /// closed after a call to StopMonitor().
+ /// descriptor is closed after a call to StopMonitor().
///
/// If this monitor was attached to an existing process this method returns
/// -1.
@@ -95,8 +94,8 @@ public:
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
lldb_private::Status &error);
- /// Reads the contents from the register identified by the given (architecture
- /// dependent) offset.
+ /// Reads the contents from the register identified by the given
+ /// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
@@ -215,11 +214,11 @@ private:
/// @class LauchArgs
///
- /// @brief Simple structure to pass data to the thread responsible for
- /// launching a child process.
+ /// Simple structure to pass data to the thread responsible for launching a
+ /// child process.
struct LaunchArgs : OperationArgs {
LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module,
- char const **argv, char const **envp,
+ char const **argv, lldb_private::Environment env,
const lldb_private::FileSpec &stdin_file_spec,
const lldb_private::FileSpec &stdout_file_spec,
const lldb_private::FileSpec &stderr_file_spec,
@@ -229,7 +228,7 @@ private:
lldb_private::Module *m_module; // The executable image to launch.
char const **m_argv; // Process arguments.
- char const **m_envp; // Process environment.
+ lldb_private::Environment m_env; // Process environment.
const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty.
const lldb_private::FileSpec
m_stdout_file_spec; // Redirect stdout or empty.
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
index 4ff5121bac13..b1b44e71de46 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
@@ -13,14 +13,14 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "RegisterInfoInterface.h"
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/ArchSpec.h"
//------------------------------------------------------------------------------
/// @class POSIXBreakpointProtocol
///
-/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
+/// Extends RegisterClass with a few virtual operations useful on POSIX.
class POSIXBreakpointProtocol {
public:
POSIXBreakpointProtocol() { m_watchpoints_initialized = false; }
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
index 59d42b9ad72e..8ddc253aea5d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
@@ -14,7 +14,7 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "RegisterContextPOSIX_arm.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
using namespace lldb_private;
using namespace lldb;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
index b911ee222015..734167e1fc98 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -130,14 +130,14 @@ bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
bool success = ReadRegister(full_reg, value);
if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
value.SetUInt64(value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
index bc1d4df89fc8..5cc6cd290629 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -14,7 +14,7 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "RegisterContextPOSIX_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
using namespace lldb_private;
using namespace lldb;
@@ -140,8 +140,8 @@ bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
if (success) {
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
index 4608520dba40..7db7f803b371 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -193,14 +193,14 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
bool success = ReadRegister(full_reg, value);
if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
value.SetUInt64(value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
@@ -221,7 +221,8 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
reg_info->byte_size, byte_order);
if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ // Concatenate ymm using the register halves in xmm.bytes and
+ // ymmh.bytes
if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
reg_info->byte_size, byte_order);
@@ -233,11 +234,10 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
return false;
}
- // Get pointer to m_fpr.fxsave variable and set the data from it.
- // Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)}
- // and stores them in 'm_fpr' (of type FPR structure). To extract values of
- // fpu
+ // Get pointer to m_fpr.fxsave variable and set the data from it. Byte
+ // offsets of all registers are calculated wrt 'UserArea' structure. However,
+ // ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} and stores
+ // them in 'm_fpr' (of type FPR structure). To extract values of fpu
// registers, m_fpr should be read at byte offsets calculated wrt to FPR
// structure.
@@ -299,12 +299,12 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(
return false;
}
} else {
- // Get pointer to m_fpr.fxsave variable and set the data to it.
- // Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only
- // fpu
- // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should
- // be written in m_fpr at byte offsets calculated wrt FPR structure.
+ // Get pointer to m_fpr.fxsave variable and set the data to it. Byte
+ // offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
+ // only fpu registers using ptrace(PT_SETFPREGS,..) API. Hence fpu
+ // registers should be written in m_fpr at byte offsets calculated wrt
+ // FPR structure.
// Since, FPR structure is also one of the member of UserArea structure.
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 109a0cc95957..1a4cb21d000e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -24,8 +24,7 @@
#include "llvm/Support/Errno.h"
// System includes - They have to be included after framework includes because
-// they define some
-// macros which collide with variable names in other modules
+// they define some macros which collide with variable names in other modules
// clang-format off
#include <sys/types.h>
#include <sys/ptrace.h>
@@ -93,17 +92,19 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
}
LLDB_LOG(log, "inferior started, now in stopped state");
- ArchSpec arch;
- if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
- return status.ToError();
+ ProcessInstanceInfo Info;
+ if (!Host::GetProcessInfo(pid, Info)) {
+ return llvm::make_error<StringError>("Cannot get process architecture",
+ llvm::inconvertibleErrorCode());
+ }
// Set the architecture to the exe architecture.
LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
- arch.GetArchitectureName());
+ Info.GetArchitecture().GetArchitectureName());
std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
- arch, mainloop));
+ Info.GetArchitecture(), mainloop));
status = process_up->ReinitializeThreads();
if (status.Fail())
@@ -124,15 +125,16 @@ NativeProcessNetBSD::Factory::Attach(
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
- ArchSpec arch;
- Status status = ResolveProcessArchitecture(pid, arch);
- if (!status.Success())
- return status.ToError();
+ ProcessInstanceInfo Info;
+ if (!Host::GetProcessInfo(pid, Info)) {
+ return llvm::make_error<StringError>("Cannot get process architecture",
+ llvm::inconvertibleErrorCode());
+ }
- std::unique_ptr<NativeProcessNetBSD> process_up(
- new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop));
+ std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
+ pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
- status = process_up->Attach();
+ Status status = process_up->Attach();
if (!status.Success())
return status.ToError();
@@ -349,8 +351,8 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) {
return error;
} else
LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
- // First try probing for a breakpoint at a software breakpoint location: PC
- // - breakpoint size.
+ // First try probing for a breakpoint at a software breakpoint location: PC -
+ // breakpoint size.
const lldb::addr_t initial_pc_addr =
context.GetPCfromBreakpointLocation();
lldb::addr_t breakpoint_addr = initial_pc_addr;
@@ -559,8 +561,8 @@ Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
"descending memory map entries detected, unexpected");
prev_base_address = proc_entry_info.GetRange().GetRangeBase();
UNUSED_IF_ASSERT_DISABLED(prev_base_address);
- // If the target address comes before this entry, indicate distance to
- // next region.
+ // If the target address comes before this entry, indicate distance to next
+ // region.
if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetByteSize(
@@ -579,9 +581,8 @@ Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
// parsed.
}
// If we made it here, we didn't find an entry that contained the given
- // address. Return the
- // load_addr as start and the amount of bytes betwwen load address and the
- // end of the memory as size.
+ // address. Return the load_addr as start and the amount of bytes betwwen
+ // load address and the end of the memory as size.
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
@@ -641,8 +642,8 @@ Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
free(vm);
if (m_mem_region_cache.empty()) {
- // No entries after attempting to read them. This shouldn't happen.
- // Assume we don't support map entries.
+ // No entries after attempting to read them. This shouldn't happen. Assume
+ // we don't support map entries.
LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
"for memory region metadata retrieval");
m_supports_mem_region = LazyBool::eLazyBoolNo;
@@ -778,8 +779,8 @@ Status NativeProcessNetBSD::Attach() {
return status;
int wstatus;
- // Need to use WALLSIG otherwise we receive an error with errno=ECHLD
- // At this point we should have a thread stopped if waitpid succeeds.
+ // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
+ // point we should have a thread stopped if waitpid succeeds.
if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0)
return Status(errno, eErrorTypePOSIX);
@@ -871,13 +872,13 @@ NativeProcessNetBSD::GetAuxvData() const {
*/
size_t auxv_size = 100 * sizeof(AuxInfo);
- ErrorOr<std::unique_ptr<MemoryBuffer>> buf =
- llvm::MemoryBuffer::getNewMemBuffer(auxv_size);
+ ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
+ llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
struct ptrace_io_desc io;
io.piod_op = PIOD_READ_AUXV;
io.piod_offs = 0;
- io.piod_addr = const_cast<void *>(static_cast<const void *>(buf.get()->getBufferStart()));
+ io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
io.piod_len = auxv_size;
Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
@@ -888,7 +889,7 @@ NativeProcessNetBSD::GetAuxvData() const {
if (io.piod_len < 1)
return std::error_code(ECANCELED, std::generic_category());
- return buf;
+ return std::move(buf);
}
Status NativeProcessNetBSD::ReinitializeThreads() {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 7090fce34fc9..142f74ecf194 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -20,10 +20,10 @@
namespace lldb_private {
namespace process_netbsd {
/// @class NativeProcessNetBSD
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior process for
-/// debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessNetBSD : public NativeProcessProtocol {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 347c15ae5b23..16b6f2c52dd5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -161,8 +161,8 @@ static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec &target_arch) {
assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
"Register setting path assumes this is a 64-bit host");
- // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
- // x86_64 register context.
+ // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64
+ // register context.
return new RegisterContextNetBSD_x86_64(target_arch);
}
@@ -805,8 +805,7 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
if (error.Fail())
return error;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // set bits 1, 3, 5, or 7
+ // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7
uint64_t enable_bit = 1 << (2 * wp_index);
// set bits 16-17, 20-21, 24-25, or 28-29
@@ -845,8 +844,8 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
RegisterValue reg_value;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
+ // the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
Status error = ReadRegister(reg_info_dr6, reg_value);
@@ -858,9 +857,9 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
if (error.Fail())
return false;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
- // of the debug control register (DR7)
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
+ // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
+ // (DR7)
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
error = ReadRegister(reg_info_dr7, reg_value);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
index 864418c90031..4b24d31226a9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -47,8 +47,7 @@ CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
#ifdef SI_KERNEL
case SI_KERNEL:
// Some platforms will occasionally send nonstandard spurious SI_KERNEL
- // codes.
- // One way to get this is via unaligned SIMD loads.
+ // codes. One way to get this is via unaligned SIMD loads.
return CrashReason::eInvalidAddress; // for lack of anything better
#endif
case SEGV_MAPERR:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 61e5bf4481d6..5f34e9915ede 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/StringConvert.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringExtractor.h"
@@ -20,21 +21,42 @@
using namespace lldb;
using namespace lldb_private;
-DynamicRegisterInfo::DynamicRegisterInfo()
- : m_regs(), m_sets(), m_set_reg_nums(), m_set_names(), m_value_regs_map(),
- m_invalidate_regs_map(), m_dynamic_reg_size_map(),
- m_reg_data_byte_size(0), m_finalized(false) {}
-
DynamicRegisterInfo::DynamicRegisterInfo(
const lldb_private::StructuredData::Dictionary &dict,
- const lldb_private::ArchSpec &arch)
- : m_regs(), m_sets(), m_set_reg_nums(), m_set_names(), m_value_regs_map(),
- m_invalidate_regs_map(), m_dynamic_reg_size_map(),
- m_reg_data_byte_size(0), m_finalized(false) {
+ const lldb_private::ArchSpec &arch) {
SetRegisterInfo(dict, arch);
}
-DynamicRegisterInfo::~DynamicRegisterInfo() {}
+DynamicRegisterInfo::DynamicRegisterInfo(DynamicRegisterInfo &&info) {
+ MoveFrom(std::move(info));
+}
+
+DynamicRegisterInfo &
+DynamicRegisterInfo::operator=(DynamicRegisterInfo &&info) {
+ MoveFrom(std::move(info));
+ return *this;
+}
+
+void DynamicRegisterInfo::MoveFrom(DynamicRegisterInfo &&info) {
+ m_regs = std::move(info.m_regs);
+ m_sets = std::move(info.m_sets);
+ m_set_reg_nums = std::move(info.m_set_reg_nums);
+ m_set_names = std::move(info.m_set_names);
+ m_value_regs_map = std::move(info.m_value_regs_map);
+ m_invalidate_regs_map = std::move(info.m_invalidate_regs_map);
+ m_dynamic_reg_size_map = std::move(info.m_dynamic_reg_size_map);
+
+ m_reg_data_byte_size = info.m_reg_data_byte_size;
+ m_finalized = info.m_finalized;
+
+ if (m_finalized) {
+ const size_t num_sets = m_sets.size();
+ for (size_t set = 0; set < num_sets; ++set)
+ m_sets[set].registers = m_set_reg_nums[set].data();
+ }
+
+ info.Clear();
+}
size_t
DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
@@ -44,13 +66,9 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
if (dict.GetValueForKeyAsArray("sets", sets)) {
const uint32_t num_sets = sets->GetSize();
for (uint32_t i = 0; i < num_sets; ++i) {
- llvm::StringRef set_name_str;
ConstString set_name;
- if (sets->GetItemAtIndexAsString(i, set_name_str))
- set_name.SetString(set_name_str);
- if (set_name) {
- RegisterSet new_set = {set_name.AsCString(), NULL, 0, NULL};
- m_sets.push_back(new_set);
+ if (sets->GetItemAtIndexAsString(i, set_name) && !set_name.IsEmpty()) {
+ m_sets.push_back({ set_name.AsCString(), NULL, 0, NULL });
} else {
Clear();
printf("error: register sets must have valid names\n");
@@ -59,6 +77,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
}
m_set_reg_nums.resize(m_sets.size());
}
+
StructuredData::Array *regs = nullptr;
if (!dict.GetValueForKeyAsArray("registers", regs))
return 0;
@@ -76,8 +95,8 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
return 0;
}
- // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint'
- // , 'format':'hex' , 'set': 0, 'ehframe' : 2,
+ // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16,
+ // 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2,
// 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
std::vector<uint32_t> value_regs;
@@ -102,14 +121,11 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
const ByteOrder byte_order = arch.GetByteOrder();
if (reg_info.byte_offset == UINT32_MAX) {
- // No offset for this register, see if the register has a value expression
- // which indicates this register is part of another register. Value
- // expressions
- // are things like "rax[31:0]" which state that the current register's
- // value
- // is in a concrete register "rax" in bits 31:0. If there is a value
- // expression
- // we can calculate the offset
+ // No offset for this register, see if the register has a value
+ // expression which indicates this register is part of another register.
+ // Value expressions are things like "rax[31:0]" which state that the
+ // current register's value is in a concrete register "rax" in bits 31:0.
+ // If there is a value expression we can calculate the offset
bool success = false;
llvm::StringRef slice_str;
if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr)) {
@@ -141,7 +157,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
ConstString containing_reg_name(reg_name_str);
- RegisterInfo *containing_reg_info =
+ const RegisterInfo *containing_reg_info =
GetRegisterInfo(containing_reg_name);
if (containing_reg_info) {
const uint32_t max_bit = containing_reg_info->byte_size * 8;
@@ -210,7 +226,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
ConstString composite_reg_name;
if (composite_reg_list->GetItemAtIndexAsString(
composite_idx, composite_reg_name, nullptr)) {
- RegisterInfo *composite_reg_info =
+ const RegisterInfo *composite_reg_info =
GetRegisterInfo(composite_reg_name);
if (composite_reg_info) {
composite_offset = std::min(composite_offset,
@@ -286,7 +302,8 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
llvm::StringRef format_str;
if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) {
- if (Args::StringToFormat(format_str.str().c_str(), reg_info.format, NULL)
+ if (OptionArgParser::ToFormat(format_str.str().c_str(), reg_info.format,
+ NULL)
.Fail()) {
Clear();
printf("error: invalid 'format' value in register dictionary\n");
@@ -349,7 +366,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
uint64_t invalidate_reg_num;
if (invalidate_reg_list->GetItemAtIndexAsString(
idx, invalidate_reg_name)) {
- RegisterInfo *invalidate_reg_info =
+ const RegisterInfo *invalidate_reg_info =
GetRegisterInfo(invalidate_reg_name);
if (invalidate_reg_info) {
m_invalidate_regs_map[i].push_back(
@@ -437,7 +454,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
for (size_t set = 0; set < num_sets; ++set) {
assert(m_sets.size() == m_set_reg_nums.size());
m_sets[set].num_registers = m_set_reg_nums[set].size();
- m_sets[set].registers = &m_set_reg_nums[set][0];
+ m_sets[set].registers = m_set_reg_nums[set].data();
}
// sort and unique all value registers and make sure each is terminated with
@@ -492,8 +509,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
}
// sort and unique all invalidate registers and make sure each is terminated
- // with
- // LLDB_INVALID_REGNUM
+ // with LLDB_INVALID_REGNUM
for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(),
end = m_invalidate_regs_map.end();
pos != end; ++pos) {
@@ -517,8 +533,8 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
m_regs[i].invalidate_regs = NULL;
}
- // Check if we need to automatically set the generic registers in case
- // they weren't set
+ // Check if we need to automatically set the generic registers in case they
+ // weren't set
bool generic_regs_specified = false;
for (const auto &reg : m_regs) {
if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
@@ -730,11 +746,11 @@ void DynamicRegisterInfo::Dump() const {
}
}
-lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(
- const lldb_private::ConstString &reg_name) {
+const lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(
+ const lldb_private::ConstString &reg_name) const {
for (auto &reg_info : m_regs) {
- // We can use pointer comparison since we used a ConstString to set
- // the "name" member in AddRegister()
+ // We can use pointer comparison since we used a ConstString to set the
+ // "name" member in AddRegister()
if (reg_info.name == reg_name.GetCString()) {
return &reg_info;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index 228acfbed4ee..acb3e3eb8a84 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -23,12 +23,18 @@
class DynamicRegisterInfo {
public:
- DynamicRegisterInfo();
+ DynamicRegisterInfo() = default;
DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch);
- virtual ~DynamicRegisterInfo();
+ virtual ~DynamicRegisterInfo() = default;
+
+ DynamicRegisterInfo(DynamicRegisterInfo &) = delete;
+ void operator=(DynamicRegisterInfo &) = delete;
+
+ DynamicRegisterInfo(DynamicRegisterInfo &&info);
+ DynamicRegisterInfo &operator=(DynamicRegisterInfo &&info);
size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch);
@@ -75,8 +81,10 @@ protected:
typedef std::vector<uint8_t> dwarf_opcode;
typedef std::map<uint32_t, dwarf_opcode> dynamic_reg_size_map;
- lldb_private::RegisterInfo *
- GetRegisterInfo(const lldb_private::ConstString &reg_name);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo(const lldb_private::ConstString &reg_name) const;
+
+ void MoveFrom(DynamicRegisterInfo &&info);
reg_collection m_regs;
set_collection m_sets;
@@ -85,9 +93,8 @@ protected:
reg_to_regs_map m_value_regs_map;
reg_to_regs_map m_invalidate_regs_map;
dynamic_reg_size_map m_dynamic_reg_size_map;
- size_t m_reg_data_byte_size; // The number of bytes required to store all
- // registers
- bool m_finalized;
+ size_t m_reg_data_byte_size = 0u; // The number of bytes required to store
+ // all registers
+ bool m_finalized = false;
};
-
#endif // lldb_DynamicRegisterInfo_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h
index 363ba2669637..7675a95246a7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h
@@ -29,13 +29,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class HistoryThread HistoryThread.h "HistoryThread.h"
-/// @brief A thread object representing a backtrace from a previous point in the
+/// A thread object representing a backtrace from a previous point in the
/// process execution
///
/// This subclass of Thread is used to provide a backtrace from earlier in
/// process execution. It is given a backtrace list of pc addresses and
-/// optionally a stop_id of when those pc addresses were collected, and it will
-/// create stack frames for them.
+/// optionally a stop_id of when those pc addresses were collected, and it
+/// will create stack frames for them.
//----------------------------------------------------------------------
class HistoryThread : public lldb_private::Thread {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InstructionUtils.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InstructionUtils.h
index e422a96200c8..186d525ce499 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InstructionUtils.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InstructionUtils.h
@@ -10,6 +10,9 @@
#ifndef lldb_InstructionUtils_h_
#define lldb_InstructionUtils_h_
+#include <cassert>
+#include <cstdint>
+
// Common utilities for manipulating instruction bit fields.
namespace lldb_private {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h
new file mode 100644
index 000000000000..ff57464be2de
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h
@@ -0,0 +1,26 @@
+//===-- RegisterContextDarwinConstants.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_REGISTERCONTEXTDARWINCONSTANTS_H
+#define LLDB_REGISTERCONTEXTDARWINCONSTANTS_H
+
+namespace lldb_private {
+
+/// Constants returned by various RegisterContextDarwin_*** functions.
+#ifndef KERN_SUCCESS
+#define KERN_SUCCESS 0
+#endif
+
+#ifndef KERN_INVALID_ARGUMENT
+#define KERN_INVALID_ARGUMENT 4
+#endif
+
+} // namespace lldb_private
+
+#endif // LLDB_REGISTERCONTEXTDARWINCONSTANTS_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 64a697ff53c8..5d9ff02fafdd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -7,13 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__APPLE__)
-
#include "RegisterContextDarwin_arm.h"
-
-// C Includes
-#include <mach/mach_types.h>
-#include <mach/thread_act.h>
+#include "RegisterContextDarwinConstants.h"
// C++ Includes
// Other libraries and framework includes
@@ -34,7 +29,7 @@
#endif
// Project includes
-#include "ARM_DWARF_Registers.h"
+#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
#include "llvm/ADT/STLExtras.h"
@@ -968,9 +963,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
@@ -1510,7 +1505,7 @@ uint32_t RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber(
}
uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() {
-#if defined(__arm__)
+#if defined(__APPLE__) && defined(__arm__)
// Set the init value to something that will let us know that we need to
// autodetect how many breakpoints are supported dynamically...
static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX;
@@ -1642,7 +1637,7 @@ bool RegisterContextDarwin_arm::ClearHardwareBreakpoint(uint32_t hw_index) {
}
uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() {
-#if defined(__arm__)
+#if defined(__APPLE__) && defined(__arm__)
// Set the init value to something that will let us know that we need to
// autodetect how many watchpoints are supported dynamically...
static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
@@ -1766,5 +1761,3 @@ bool RegisterContextDarwin_arm::ClearHardwareWatchpoint(uint32_t hw_index) {
}
return false;
}
-
-#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index 344c08965fad..03ce7ef9f524 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -8,14 +8,8 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__APPLE__)
-
#include "RegisterContextDarwin_arm64.h"
-
-// C Includes
-#include <mach/mach_types.h>
-#include <mach/thread_act.h>
-#include <sys/sysctl.h>
+#include "RegisterContextDarwinConstants.h"
// C++ Includes
// Other libraries and framework includes
@@ -39,7 +33,7 @@
#endif
// Project includes
-#include "ARM64_DWARF_Registers.h"
+#include "Utility/ARM64_DWARF_Registers.h"
using namespace lldb;
using namespace lldb_private;
@@ -149,9 +143,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
@@ -299,8 +293,9 @@ int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
if (log) {
for (uint32_t i = 0; i < 16; i++)
- log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u "
- "= { 0x%8.8llx, 0x%8.8llx }",
+ log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
+ " } WVR%-2u/WCR%-2u "
+ "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
}
}
@@ -921,7 +916,7 @@ uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
}
uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
-#if defined(__arm64__) || defined(__aarch64__)
+#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
// autodetect how many watchpoints are supported dynamically...
static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
if (g_num_supported_hw_watchpoints == UINT32_MAX) {
@@ -1043,5 +1038,3 @@ bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
}
return false;
}
-
-#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index c818fad9ac0e..24414211d9aa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -147,9 +147,9 @@ enum {
sizeof(RegisterContextDarwin_i386::FPU))
// These macros will auto define the register name, alt name, register size,
-// register offset, encoding, format and native register. This ensures that
-// the register state structures are defined correctly and have the correct
-// sizes and offsets.
+// register offset, encoding, format and native register. This ensures that the
+// register state structures are defined correctly and have the correct sizes
+// and offsets.
#define DEFINE_GPR(reg, alt) \
#reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *) NULL)->reg), \
GPR_OFFSET(reg), eEncodingUint, eFormatHex
@@ -464,9 +464,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
@@ -680,8 +680,7 @@ bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info,
case fpu_stmm6:
case fpu_stmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes() must be used for these
- // registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
//::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes,
//10);
return false;
@@ -695,8 +694,7 @@ bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info,
case fpu_xmm6:
case fpu_xmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes()
- // must be used for these registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
//::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes,
//16);
return false;
@@ -799,8 +797,7 @@ bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
case fpu_stmm6:
case fpu_stmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes()
- // must be used for these registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
value.GetByteSize());
return false;
@@ -814,8 +811,7 @@ bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
case fpu_xmm6:
case fpu_xmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes()
- // must be used for these registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
value.GetByteSize());
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 50e7292f86b1..ecad8240b294 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -165,9 +165,9 @@ enum ehframe_dwarf_regnums {
sizeof(RegisterContextDarwin_x86_64::FPU))
// These macros will auto define the register name, alt name, register size,
-// register offset, encoding, format and native register. This ensures that
-// the register state structures are defined correctly and have the correct
-// sizes and offsets.
+// register offset, encoding, format and native register. This ensures that the
+// register state structures are defined correctly and have the correct sizes
+// and offsets.
#define DEFINE_GPR(reg, alt) \
#reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *) NULL)->reg), \
GPR_OFFSET(reg), eEncodingUint, eFormatHex
@@ -525,9 +525,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 5435a02433ab..ba9a8071bcfb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -104,8 +104,7 @@ bool RegisterContextLLDB::IsUnwindPlanValidForCurrentPC(
}
// Initialize a RegisterContextLLDB which is the first frame of a stack -- the
-// zeroth frame or currently
-// executing frame.
+// zeroth frame or currently executing frame.
void RegisterContextLLDB::InitializeZerothFrame() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
@@ -131,25 +130,26 @@ void RegisterContextLLDB::InitializeZerothFrame() {
// Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
// this will strip bit zero in case we read a PC from memory or from the LR.
// (which would be a no-op in frame 0 where we get it from the register set,
- // but still a good idea to make the call here for other ABIs that may exist.)
+ // but still a good idea to make the call here for other ABIs that may
+ // exist.)
ABI *abi = process->GetABI().get();
if (abi)
current_pc = abi->FixCodeAddress(current_pc);
- // Initialize m_current_pc, an Address object, based on current_pc, an addr_t.
+ // Initialize m_current_pc, an Address object, based on current_pc, an
+ // addr_t.
m_current_pc.SetLoadAddress(current_pc, &process->GetTarget());
// If we don't have a Module for some reason, we're not going to find
- // symbol/function information - just
- // stick in some reasonable defaults and hope we can unwind past this frame.
+ // symbol/function information - just stick in some reasonable defaults and
+ // hope we can unwind past this frame.
ModuleSP pc_module_sp(m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp) {
UnwindLogMsg("using architectural default unwind method");
}
// We require either a symbol or function in the symbols context to be
- // successfully
- // filled in or this context is of no use to us.
+ // successfully filled in or this context is of no use to us.
const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress(
m_current_pc, resolve_scope, m_sym_ctx) &
@@ -180,18 +180,17 @@ void RegisterContextLLDB::InitializeZerothFrame() {
}
// If we were able to find a symbol/function, set addr_range to the bounds of
- // that symbol/function.
- // else treat the current pc value as the start_pc and record no offset.
+ // that symbol/function. else treat the current pc value as the start_pc and
+ // record no offset.
if (addr_range.GetBaseAddress().IsValid()) {
m_start_pc = addr_range.GetBaseAddress();
if (m_current_pc.GetSection() == m_start_pc.GetSection()) {
m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
} else if (m_current_pc.GetModule() == m_start_pc.GetModule()) {
- // This means that whatever symbol we kicked up isn't really correct
- // --- we should not cross section boundaries ... We really should NULL
- // out
- // the function/symbol in this case unless there is a bad assumption
- // here due to inlined functions?
+ // This means that whatever symbol we kicked up isn't really correct ---
+ // we should not cross section boundaries ... We really should NULL out
+ // the function/symbol in this case unless there is a bad assumption here
+ // due to inlined functions?
m_current_offset =
m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress();
}
@@ -266,8 +265,7 @@ void RegisterContextLLDB::InitializeZerothFrame() {
}
// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the
-// RegisterContextLLDB "below" it
-// to provide things like its current pc value.
+// RegisterContextLLDB "below" it to provide things like its current pc value.
void RegisterContextLLDB::InitializeNonZerothFrame() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
@@ -333,8 +331,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end);
// If we don't have a Module for some reason, we're not going to find
- // symbol/function information - just
- // stick in some reasonable defaults and hope we can unwind past this frame.
+ // symbol/function information - just stick in some reasonable defaults and
+ // hope we can unwind past this frame.
ModuleSP pc_module_sp(m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp) {
UnwindLogMsg("using architectural default unwind method");
@@ -345,12 +343,10 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
if (process->GetLoadAddressPermissions(pc, permissions) &&
(permissions & ePermissionsExecutable) == 0) {
// If this is the second frame off the stack, we may have unwound the
- // first frame
- // incorrectly. But using the architecture default unwind plan may get us
- // back on
- // track -- albeit possibly skipping a real frame. Give this frame a
- // clearly-invalid
- // pc and see if we can get any further.
+ // first frame incorrectly. But using the architecture default unwind
+ // plan may get us back on track -- albeit possibly skipping a real
+ // frame. Give this frame a clearly-invalid pc and see if we can get any
+ // further.
if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
GetNextFrame()->IsFrameZero()) {
UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable "
@@ -359,8 +355,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
(uint64_t)pc);
m_frame_type = eSkipFrame;
} else {
- // anywhere other than the second frame, a non-executable pc means we're
- // off in the weeds -- stop now.
+ // anywhere other than the second frame, a non-executable pc means
+ // we're off in the weeds -- stop now.
m_frame_type = eNotAValidFrame;
UnwindLogMsg("pc is in a non-executable section of memory and this "
"isn't the 2nd frame in the stack walk.");
@@ -399,8 +395,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
// m_cfa should point into the stack memory; if we can query memory
- // region permissions,
- // see if the memory is allocated & readable.
+ // region permissions, see if the memory is allocated & readable.
if (process->GetLoadAddressPermissions(m_cfa, permissions) &&
(permissions & ePermissionsReadable) == 0) {
m_frame_type = eNotAValidFrame;
@@ -435,19 +430,18 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
bool resolve_tail_call_address = false; // m_current_pc can be one past the
// address range of the function...
- // If the saved pc does not point to a function/symbol because it is
- // beyond the bounds of the correct function and there's no symbol there,
- // we do *not* want ResolveSymbolContextForAddress to back up the pc by 1,
- // because then we might not find the correct unwind information later.
- // Instead, let ResolveSymbolContextForAddress fail, and handle the case
- // via decr_pc_and_recompute_addr_range below.
+ // If the saved pc does not point to a function/symbol because it is beyond
+ // the bounds of the correct function and there's no symbol there, we do
+ // *not* want ResolveSymbolContextForAddress to back up the pc by 1, because
+ // then we might not find the correct unwind information later. Instead, let
+ // ResolveSymbolContextForAddress fail, and handle the case via
+ // decr_pc_and_recompute_addr_range below.
const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress(
m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address);
// We require either a symbol or function in the symbols context to be
- // successfully
- // filled in or this context is of no use to us.
+ // successfully filled in or this context is of no use to us.
if (resolve_scope & resolved_scope) {
m_sym_ctx_valid = true;
}
@@ -476,8 +470,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
decr_pc_and_recompute_addr_range = true;
// Or if we're in the middle of the stack (and not "above" an asynchronous
- // event like sigtramp),
- // and our "current" pc is the start of a function...
+ // event like sigtramp), and our "current" pc is the start of a function...
if (GetNextFrame()->m_frame_type != eTrapHandlerFrame &&
GetNextFrame()->m_frame_type != eDebuggerFrame &&
(!m_sym_ctx_valid ||
@@ -488,9 +481,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
// We need to back up the pc by 1 byte and re-search for the Symbol to handle
- // the case where the "saved pc"
- // value is pointing to the next function, e.g. if a function ends with a CALL
- // instruction.
+ // the case where the "saved pc" value is pointing to the next function, e.g.
+ // if a function ends with a CALL instruction.
// FIXME this may need to be an architectural-dependent behavior; if so we'll
// need to add a member function
// to the ABI plugin and consult that.
@@ -516,9 +508,9 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
}
- // If we were able to find a symbol/function, set addr_range_ptr to the bounds
- // of that symbol/function.
- // else treat the current pc value as the start_pc and record no offset.
+ // If we were able to find a symbol/function, set addr_range_ptr to the
+ // bounds of that symbol/function. else treat the current pc value as the
+ // start_pc and record no offset.
if (addr_range.GetBaseAddress().IsValid()) {
m_start_pc = addr_range.GetBaseAddress();
m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget());
@@ -553,9 +545,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
RegisterKind row_register_kind = eRegisterKindGeneric;
// Try to get by with just the fast UnwindPlan if possible - the full
- // UnwindPlan may be expensive to get
- // (e.g. if we have to parse the entire eh_frame section of an ObjectFile for
- // the first time.)
+ // UnwindPlan may be expensive to get (e.g. if we have to parse the entire
+ // eh_frame section of an ObjectFile for the first time.)
if (m_fast_unwind_plan_sp &&
m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
@@ -616,16 +607,14 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
bool RegisterContextLLDB::CheckIfLoopingStack() {
// If we have a bad stack setup, we can get the same CFA value multiple times
- // -- or even
- // more devious, we can actually oscillate between two CFA values. Detect that
- // here and
- // break out to avoid a possible infinite loop in lldb trying to unwind the
- // stack.
- // To detect when we have the same CFA value multiple times, we compare the
+ // -- or even more devious, we can actually oscillate between two CFA values.
+ // Detect that here and break out to avoid a possible infinite loop in lldb
+ // trying to unwind the stack. To detect when we have the same CFA value
+ // multiple times, we compare the
// CFA of the current
// frame with the 2nd next frame because in some specail case (e.g. signal
- // hanlders, hand
- // written assembly without ABI compiance) we can have 2 frames with the same
+ // hanlders, hand written assembly without ABI compiance) we can have 2
+ // frames with the same
// CFA (in theory we
// can have arbitrary number of frames with the same CFA, but more then 2 is
// very very unlikely)
@@ -734,15 +723,12 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer)
- // so the pc is 0x0
- // in the zeroth frame, we need to use the "unwind at first instruction" arch
- // default UnwindPlan
- // Also, if this Process can report on memory region attributes, any
- // non-executable region means
- // we jumped through a bad function pointer - handle the same way as 0x0.
- // Note, if we have a symbol context & a symbol, we don't want to follow this
- // code path. This is
- // for jumping to memory regions without any information available.
+ // so the pc is 0x0 in the zeroth frame, we need to use the "unwind at first
+ // instruction" arch default UnwindPlan Also, if this Process can report on
+ // memory region attributes, any non-executable region means we jumped
+ // through a bad function pointer - handle the same way as 0x0. Note, if we
+ // have a symbol context & a symbol, we don't want to follow this code path.
+ // This is for jumping to memory regions without any information available.
if ((!m_sym_ctx_valid ||
(m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) &&
@@ -780,12 +766,10 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// No FuncUnwinders available for this pc (stripped function symbols, lldb
- // could not augment its
- // function table with another source, like LC_FUNCTION_STARTS or eh_frame in
- // ObjectFileMachO).
- // See if eh_frame or the .ARM.exidx tables have unwind information for this
- // address, else fall
- // back to the architectural default unwind.
+ // could not augment its function table with another source, like
+ // LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). See if eh_frame or the
+ // .ARM.exidx tables have unwind information for this address, else fall back
+ // to the architectural default unwind.
if (!func_unwinders_sp) {
m_frame_type = eNormalFrame;
@@ -793,7 +777,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
!m_current_pc.IsValid())
return arch_default_unwind_plan_sp;
- // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+ // Even with -fomit-frame-pointer, we can try eh_frame to get back on
+ // track.
DWARFCallFrameInfo *eh_frame =
pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
if (eh_frame) {
@@ -819,11 +804,10 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// If we're in _sigtramp(), unwinding past this frame requires special
- // knowledge. On Mac OS X this knowledge
- // is properly encoded in the eh_frame section, so prefer that if available.
- // On other platforms we may need to provide a platform-specific UnwindPlan
- // which encodes the details of
- // how to unwind out of sigtramp.
+ // knowledge. On Mac OS X this knowledge is properly encoded in the eh_frame
+ // section, so prefer that if available. On other platforms we may need to
+ // provide a platform-specific UnwindPlan which encodes the details of how to
+ // unwind out of sigtramp.
if (m_frame_type == eTrapHandlerFrame && process) {
m_fast_unwind_plan_sp.reset();
unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(
@@ -835,24 +819,19 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame
- // even when it's frame zero
- // This comes up if we have hand-written functions in a Module and
- // hand-written eh_frame. The assembly
- // instruction inspection may fail and the eh_frame CFI were probably written
- // with some care to do the
- // right thing. It'd be nice if there was a way to ask the eh_frame directly
- // if it is asynchronous
- // (can be trusted at every instruction point) or synchronous (the normal case
- // - only at call sites).
+ // even when it's frame zero This comes up if we have hand-written functions
+ // in a Module and hand-written eh_frame. The assembly instruction
+ // inspection may fail and the eh_frame CFI were probably written with some
+ // care to do the right thing. It'd be nice if there was a way to ask the
+ // eh_frame directly if it is asynchronous (can be trusted at every
+ // instruction point) or synchronous (the normal case - only at call sites).
// But there is not.
if (process && process->GetDynamicLoader() &&
process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) {
// We must specifically call the GetEHFrameUnwindPlan() method here --
- // normally we would
- // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind
- // plan sourced from
- // either eh_frame (that's what we intend) or compact unwind (this won't
- // work)
+ // normally we would call GetUnwindPlanAtCallSite() -- because CallSite may
+ // return an unwind plan sourced from either eh_frame (that's what we
+ // intend) or compact unwind (this won't work)
unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(
process->GetTarget(), m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
@@ -871,22 +850,16 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
// We probably have an UnwindPlan created by inspecting assembly
- // instructions. The
- // assembly profilers work really well with compiler-generated functions
- // but hand-
- // written assembly can be problematic. We set the eh_frame based unwind
- // plan as our
- // fallback unwind plan if instruction emulation doesn't work out even
- // for non call
- // sites if it is available and use the architecture default unwind plan
- // if it is
+ // instructions. The assembly profilers work really well with compiler-
+ // generated functions but hand- written assembly can be problematic.
+ // We set the eh_frame based unwind plan as our fallback unwind plan if
+ // instruction emulation doesn't work out even for non call sites if it
+ // is available and use the architecture default unwind plan if it is
// not available. The eh_frame unwind plan is more reliable even on non
- // call sites
- // then the architecture default plan and for hand written assembly code
- // it is often
- // written in a way that it valid at all location what helps in the most
- // common
- // cases when the instruction emulation fails.
+ // call sites then the architecture default plan and for hand written
+ // assembly code it is often written in a way that it valid at all
+ // location what helps in the most common cases when the instruction
+ // emulation fails.
UnwindPlanSP call_site_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtCallSite(
process->GetTarget(), m_current_offset_backed_up_one);
@@ -919,9 +892,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// We'd prefer to use an UnwindPlan intended for call sites when we're at a
- // call site but if we've
- // struck out on that, fall back to using the non-call-site assembly
- // inspection UnwindPlan if possible.
+ // call site but if we've struck out on that, fall back to using the non-
+ // call-site assembly inspection UnwindPlan if possible.
if (process) {
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
process->GetTarget(), m_thread, m_current_offset_backed_up_one);
@@ -929,19 +901,14 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
if (unwind_plan_sp &&
unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
// We probably have an UnwindPlan created by inspecting assembly
- // instructions. The assembly
- // profilers work really well with compiler-generated functions but hand-
- // written assembly
- // can be problematic. We set the eh_frame based unwind plan as our fallback
- // unwind plan if
+ // instructions. The assembly profilers work really well with compiler-
+ // generated functions but hand- written assembly can be problematic. We
+ // set the eh_frame based unwind plan as our fallback unwind plan if
// instruction emulation doesn't work out even for non call sites if it is
- // available and use
- // the architecture default unwind plan if it is not available. The eh_frame
- // unwind plan is
- // more reliable even on non call sites then the architecture default plan
- // and for hand
- // written assembly code it is often written in a way that it valid at all
- // location what
+ // available and use the architecture default unwind plan if it is not
+ // available. The eh_frame unwind plan is more reliable even on non call
+ // sites then the architecture default plan and for hand written assembly
+ // code it is often written in a way that it valid at all location what
// helps in the most common cases when the instruction emulation fails.
UnwindPlanSP call_site_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtCallSite(
@@ -963,8 +930,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// If we're on the first instruction of a function, and we have an
- // architectural default UnwindPlan
- // for the initial instruction of a function, use that.
+ // architectural default UnwindPlan for the initial instruction of a
+ // function, use that.
if (m_current_offset_backed_up_one == 0) {
unwind_plan_sp =
func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry(
@@ -1115,12 +1082,10 @@ bool RegisterContextLLDB::IsValid() const {
}
// After the final stack frame in a stack walk we'll get one invalid
-// (eNotAValidFrame) stack frame --
-// one past the end of the stack walk. But higher-level code will need to tell
-// the differnece between
-// "the unwind plan below this frame failed" versus "we successfully completed
-// the stack walk" so
-// this method helps to disambiguate that.
+// (eNotAValidFrame) stack frame -- one past the end of the stack walk. But
+// higher-level code will need to tell the differnece between "the unwind plan
+// below this frame failed" versus "we successfully completed the stack walk"
+// so this method helps to disambiguate that.
bool RegisterContextLLDB::IsTrapHandlerFrame() const {
return m_frame_type == eTrapHandlerFrame;
@@ -1129,12 +1094,10 @@ bool RegisterContextLLDB::IsTrapHandlerFrame() const {
// A skip frame is a bogus frame on the stack -- but one where we're likely to
// find a real frame farther
// up the stack if we keep looking. It's always the second frame in an unwind
-// (i.e. the first frame after
-// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this
-// frame in some way so the
-// user knows we're displaying bad data and we may have skipped one frame of
-// their real program in the
-// process of getting back on track.
+// (i.e. the first frame after frame zero) where unwinding can be the
+// trickiest. Ideally we'll mark up this frame in some way so the user knows
+// we're displaying bad data and we may have skipped one frame of their real
+// program in the process of getting back on track.
bool RegisterContextLLDB::IsSkipFrame() const {
return m_frame_type == eSkipFrame;
@@ -1231,8 +1194,8 @@ RegisterContextLLDB::SavedLocationForRegister(
RegisterNumber return_address_reg;
// If we're fetching the saved pc and this UnwindPlan defines a
- // ReturnAddress register (e.g. lr on arm),
- // look for the return address register number in the UnwindPlan's row.
+ // ReturnAddress register (e.g. lr on arm), look for the return address
+ // register number in the UnwindPlan's row.
if (pc_regnum.IsValid() && pc_regnum == regnum &&
m_full_unwind_plan_sp->GetReturnAddressRegister() !=
LLDB_INVALID_REGNUM) {
@@ -1272,10 +1235,8 @@ RegisterContextLLDB::SavedLocationForRegister(
}
// This is frame 0 and we're retrieving the PC and it's saved in a Return
- // Address register and
- // it hasn't been saved anywhere yet -- that is, it's still live in the
- // actual register.
- // Handle this specially.
+ // Address register and it hasn't been saved anywhere yet -- that is,
+ // it's still live in the actual register. Handle this specially.
if (have_unwindplan_regloc == false && return_address_reg.IsValid() &&
IsFrameZero()) {
@@ -1298,22 +1259,18 @@ RegisterContextLLDB::SavedLocationForRegister(
}
// If this architecture stores the return address in a register (it
- // defines a Return Address register)
- // and we're on a non-zero stack frame and the Full UnwindPlan says that
- // the pc is stored in the
+ // defines a Return Address register) and we're on a non-zero stack frame
+ // and the Full UnwindPlan says that the pc is stored in the
// RA registers (e.g. lr on arm), then we know that the full unwindplan is
// not trustworthy -- this
// is an impossible situation and the instruction emulation code has
- // likely been misled.
- // If this stack frame meets those criteria, we need to throw away the
- // Full UnwindPlan that the
- // instruction emulation came up with and fall back to the architecture's
- // Default UnwindPlan so
- // the stack walk can get past this point.
+ // likely been misled. If this stack frame meets those criteria, we need
+ // to throw away the Full UnwindPlan that the instruction emulation came
+ // up with and fall back to the architecture's Default UnwindPlan so the
+ // stack walk can get past this point.
// Special note: If the Full UnwindPlan was generated from the compiler,
- // don't second-guess it
- // when we're at a call site location.
+ // don't second-guess it when we're at a call site location.
// arch_default_ra_regnum is the return address register # in the Full
// UnwindPlan register numbering
@@ -1376,11 +1333,10 @@ RegisterContextLLDB::SavedLocationForRegister(
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
if (have_unwindplan_regloc == false) {
- // If the UnwindPlan failed to give us an unwind location for this register,
- // we may be able to fall back
- // to some ABI-defined default. For example, some ABIs allow to determine
- // the caller's SP via the CFA.
- // Also, the ABI may set volatile registers to the undefined state.
+ // If the UnwindPlan failed to give us an unwind location for this
+ // register, we may be able to fall back to some ABI-defined default. For
+ // example, some ABIs allow to determine the caller's SP via the CFA. Also,
+ // the ABI may set volatile registers to the undefined state.
ABI *abi = process ? process->GetABI().get() : NULL;
if (abi) {
const RegisterInfo *reg_info =
@@ -1558,24 +1514,19 @@ RegisterContextLLDB::SavedLocationForRegister(
// TryFallbackUnwindPlan() -- this method is a little tricky.
//
// When this is called, the frame above -- the caller frame, the "previous"
-// frame --
-// is invalid or bad.
+// frame -- is invalid or bad.
//
-// Instead of stopping the stack walk here, we'll try a different UnwindPlan and
-// see
-// if we can get a valid frame above us.
+// Instead of stopping the stack walk here, we'll try a different UnwindPlan
+// and see if we can get a valid frame above us.
//
// This most often happens when an unwind plan based on assembly instruction
-// inspection
-// is not correct -- mostly with hand-written assembly functions or functions
-// where the
-// stack frame is set up "out of band", e.g. the kernel saved the register
-// context and
-// then called an asynchronous trap handler like _sigtramp.
+// inspection is not correct -- mostly with hand-written assembly functions or
+// functions where the stack frame is set up "out of band", e.g. the kernel
+// saved the register context and then called an asynchronous trap handler like
+// _sigtramp.
//
// Often in these cases, if we just do a dumb stack walk we'll get past this
-// tricky
-// frame and our usual techniques can continue to be used.
+// tricky frame and our usual techniques can continue to be used.
bool RegisterContextLLDB::TryFallbackUnwindPlan() {
if (m_fallback_unwind_plan_sp.get() == nullptr)
@@ -1591,15 +1542,13 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
}
// If a compiler generated unwind plan failed, trying the arch default
- // unwindplan
- // isn't going to do any better.
+ // unwindplan isn't going to do any better.
if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
return false;
- // Get the caller's pc value and our own CFA value.
- // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA
- // value.
- // If they're the same, then the fallback unwind plan provides no benefit.
+ // Get the caller's pc value and our own CFA value. Swap in the fallback
+ // unwind plan, re-fetch the caller's pc value and CFA value. If they're the
+ // same, then the fallback unwind plan provides no benefit.
RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
LLDB_REGNUM_GENERIC_PC);
@@ -1622,23 +1571,18 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
}
// This is a tricky wrinkle! If SavedLocationForRegister() detects a really
- // impossible
- // register location for the full unwind plan, it may call
- // ForceSwitchToFallbackUnwindPlan()
- // which in turn replaces the full unwindplan with the fallback... in short,
- // we're done,
- // we're using the fallback UnwindPlan.
- // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only
- // way it
- // became nullptr since then is via SavedLocationForRegister().
+ // impossible register location for the full unwind plan, it may call
+ // ForceSwitchToFallbackUnwindPlan() which in turn replaces the full
+ // unwindplan with the fallback... in short, we're done, we're using the
+ // fallback UnwindPlan. We checked if m_fallback_unwind_plan_sp was nullptr
+ // at the top -- the only way it became nullptr since then is via
+ // SavedLocationForRegister().
if (m_fallback_unwind_plan_sp.get() == nullptr)
return true;
// Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide
- // this isn't
- // working, we need to restore.
- // We'll also need to save & restore the value of the m_cfa ivar. Save is
- // down below a bit in 'old_cfa'.
+ // this isn't working, we need to restore. We'll also need to save & restore
+ // the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'.
UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
addr_t old_cfa = m_cfa;
@@ -2049,10 +1993,9 @@ bool RegisterContextLLDB::ReadPC(addr_t &pc) {
// A pc value of 0 or 1 is impossible in the middle of the stack -- it
// indicates the end of a stack walk.
// On the currently executing frame (or such a frame interrupted
- // asynchronously by sigtramp et al) this may
- // occur if code has jumped through a NULL pointer -- we want to be able to
- // unwind past that frame to help
- // find the bug.
+ // asynchronously by sigtramp et al) this may occur if code has jumped
+ // through a NULL pointer -- we want to be able to unwind past that frame
+ // to help find the bug.
ProcessSP process_sp (m_thread.GetProcess());
if (process_sp)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 2d24bdaed2cd..77c1bea34851 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -19,7 +19,7 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/StreamString.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -139,8 +139,8 @@ bool RegisterContextMacOSXFrameBackchain::ReadRegister(
bool RegisterContextMacOSXFrameBackchain::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
- // Not supported yet. We could easily add support for this by remembering
- // the address of each entry (it would need to be part of the cursor)
+ // Not supported yet. We could easily add support for this by remembering the
+ // address of each entry (it would need to be part of the cursor)
return false;
}
@@ -154,10 +154,10 @@ bool RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues(
bool RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues(
const lldb::DataBufferSP &data_sp) {
- // Since this class doesn't respond to "ReadAllRegisterValues()", it must
- // not have been the one that saved all the register values. So we just let
- // the thread's register context (the register context for frame zero) do
- // the writing.
+ // Since this class doesn't respond to "ReadAllRegisterValues()", it must not
+ // have been the one that saved all the register values. So we just let the
+ // thread's register context (the register context for frame zero) do the
+ // writing.
return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index 8f0dfd2a5b50..76189ea781de 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -32,9 +32,9 @@ RegisterContextMemory::RegisterContextMemory(Thread &thread,
addr_t reg_data_addr)
: RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
- // Resize our vector of bools to contain one bool for every register.
- // We will use these boolean values to know when a register value
- // is valid in m_reg_data.
+ // Resize our vector of bools to contain one bool for every register. We will
+ // use these boolean values to know when a register value is valid in
+ // m_reg_data.
const size_t num_regs = reg_infos.GetNumRegisters();
assert(num_regs > 0);
m_reg_valid.resize(num_regs);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index bb3509330eec..352e251e3b64 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,7 +21,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_arm.h"
using namespace lldb;
@@ -107,11 +107,6 @@ RegisterContextPOSIX_arm::RegisterContextPOSIX_arm(
}
::memset(&m_fpr, 0, sizeof m_fpr);
-
- // elf-core yet to support ReadFPR()
- lldb::ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() {}
@@ -142,8 +137,8 @@ size_t RegisterContextPOSIX_arm::GetGPRSize() {
const lldb_private::RegisterInfo *RegisterContextPOSIX_arm::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -199,8 +194,8 @@ bool RegisterContextPOSIX_arm::IsRegisterSetAvailable(size_t set_index) {
return set_index < k_num_register_sets;
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_arm::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 89384c8f5190..3ff93cde2347 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,7 +21,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_arm64.h"
using namespace lldb;
@@ -126,11 +126,6 @@ RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
}
::memset(&m_fpr, 0, sizeof m_fpr);
-
- // elf-core yet to support ReadFPR()
- lldb::ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() {}
@@ -162,8 +157,8 @@ size_t RegisterContextPOSIX_arm64::GetGPRSize() {
const lldb_private::RegisterInfo *
RegisterContextPOSIX_arm64::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -219,8 +214,8 @@ bool RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index) {
return set_index < k_num_register_sets;
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index 6a55947ba5c2..98d1e6fa8817 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,11 +21,10 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_mips64.h"
#include "RegisterContextFreeBSD_mips64.h"
#include "RegisterContextLinux_mips64.h"
-#include "RegisterContextLinux_mips.h"
+#include "RegisterContextLinux_mips.h"
using namespace lldb_private;
using namespace lldb;
@@ -59,11 +59,6 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(
static_cast<uint32_t>(m_registers_count[gpr_registers_count] +
m_registers_count[fpr_registers_count] +
m_registers_count[msa_registers_count]));
-
- // elf-core yet to support ReadFPR()
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {}
@@ -92,8 +87,8 @@ size_t RegisterContextPOSIX_mips64::GetGPRSize() {
const RegisterInfo *RegisterContextPOSIX_mips64::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -172,8 +167,8 @@ bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = m_num_registers;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
index c2b73e226165..9f0552539723 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -21,7 +22,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_powerpc.h"
using namespace lldb_private;
@@ -95,11 +95,6 @@ RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(
RegisterInfoInterface *register_info)
: RegisterContext(thread, concrete_frame_idx) {
m_register_info_ap.reset(register_info);
-
- // elf-core yet to support ReadFPR()
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() {}
@@ -129,8 +124,8 @@ size_t RegisterContextPOSIX_powerpc::GetGPRSize() {
const RegisterInfo *RegisterContextPOSIX_powerpc::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -181,8 +176,8 @@ bool RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
index de410f063b53..41ae5ec6b51a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,7 +21,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_ppc64le.h"
using namespace lldb_private;
@@ -117,10 +117,6 @@ RegisterContextPOSIX_ppc64le::RegisterContextPOSIX_ppc64le(
RegisterInfoInterface *register_info)
: RegisterContext(thread, concrete_frame_idx) {
m_register_info_ap.reset(register_info);
-
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
void RegisterContextPOSIX_ppc64le::InvalidateAllRegisters() {}
@@ -146,8 +142,8 @@ size_t RegisterContextPOSIX_ppc64le::GetGPRSize() {
const RegisterInfo *RegisterContextPOSIX_ppc64le::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -198,8 +194,8 @@ bool RegisterContextPOSIX_ppc64le::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_ppc64le::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
index b3365ee2f098..662ac38405ef 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
@@ -174,8 +174,8 @@ lldb::ByteOrder RegisterContextPOSIX_s390x::GetByteOrder() {
return byte_order;
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 41cec8add987..d2a06e1b7897 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -414,8 +414,8 @@ size_t RegisterContextPOSIX_x86::GetFXSAVEOffset() {
const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -531,8 +531,8 @@ bool RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 1894b5368122..5d7ad89ad394 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -19,7 +19,7 @@ namespace lldb_private {
///------------------------------------------------------------------------------
/// @class RegisterInfoInterface
///
-/// @brief RegisterInfo interface to patch RegisterInfo structure for archs.
+/// RegisterInfo interface to patch RegisterInfo structure for archs.
///------------------------------------------------------------------------------
class RegisterInfoInterface {
public:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
new file mode 100644
index 000000000000..69f00e4ba885
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
@@ -0,0 +1,331 @@
+//===-- RegisterInfos_ppc64.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef DECLARE_REGISTER_INFOS_PPC64_STRUCT
+
+// C Includes
+#include <stddef.h>
+
+// Computes the offset of the given GPR_PPC64 in the user data area.
+#define GPR_PPC64_OFFSET(regname) (offsetof(GPR_PPC64, regname))
+#define FPR_PPC64_OFFSET(regname) (offsetof(FPR_PPC64, regname) \
+ + sizeof(GPR_PPC64))
+#define VMX_PPC64_OFFSET(regname) (offsetof(VMX_PPC64, regname) \
+ + sizeof(GPR_PPC64) + sizeof(FPR_PPC64))
+#define GPR_PPC64_SIZE(regname) (sizeof(((GPR_PPC64 *)NULL)->regname))
+
+#include "Utility/PPC64_DWARF_Registers.h"
+#include "lldb-ppc64-register-enums.h"
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR_PPC64(reg, alt, lldb_kind) \
+ { \
+ #reg, alt, GPR_PPC64_SIZE(reg), GPR_PPC64_OFFSET(reg), lldb::eEncodingUint,\
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_##reg##_ppc64, \
+ ppc64_dwarf::dwarf_##reg##_ppc64, \
+ lldb_kind, \
+ LLDB_INVALID_REGNUM, \
+ gpr_##reg##_ppc64 }, \
+ NULL, NULL, NULL, 0 \
+ }
+#define DEFINE_FPR_PPC64(reg, alt, lldb_kind) \
+ { \
+#reg, alt, 8, FPR_PPC64_OFFSET(reg), lldb::eEncodingIEEE754, \
+ lldb::eFormatFloat, \
+ {ppc64_dwarf::dwarf_##reg##_ppc64, \
+ ppc64_dwarf::dwarf_##reg##_ppc64, lldb_kind, LLDB_INVALID_REGNUM, \
+ fpr_##reg##_ppc64 }, \
+ NULL, NULL, NULL, 0 \
+ }
+#define DEFINE_VMX_PPC64(reg, lldb_kind) \
+ { \
+#reg, NULL, 16, VMX_PPC64_OFFSET(reg), lldb::eEncodingVector, \
+ lldb::eFormatVectorOfUInt32, \
+ {ppc64_dwarf::dwarf_##reg##_ppc64, \
+ ppc64_dwarf::dwarf_##reg##_ppc64, lldb_kind, LLDB_INVALID_REGNUM, \
+ vmx_##reg##_ppc64 }, \
+ NULL, NULL, NULL, 0 \
+ }
+
+// General purpose registers.
+// EH_Frame, Generic, Process Plugin
+#define PPC64_REGS \
+ DEFINE_GPR_PPC64(r0, NULL, LLDB_INVALID_REGNUM) \
+ , DEFINE_GPR_PPC64(r1, "sp", LLDB_REGNUM_GENERIC_SP), \
+ DEFINE_GPR_PPC64(r2, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r3, "arg1", LLDB_REGNUM_GENERIC_ARG1), \
+ DEFINE_GPR_PPC64(r4, "arg2", LLDB_REGNUM_GENERIC_ARG2), \
+ DEFINE_GPR_PPC64(r5, "arg3", LLDB_REGNUM_GENERIC_ARG3), \
+ DEFINE_GPR_PPC64(r6, "arg4", LLDB_REGNUM_GENERIC_ARG4), \
+ DEFINE_GPR_PPC64(r7, "arg5", LLDB_REGNUM_GENERIC_ARG5), \
+ DEFINE_GPR_PPC64(r8, "arg6", LLDB_REGNUM_GENERIC_ARG6), \
+ DEFINE_GPR_PPC64(r9, "arg7", LLDB_REGNUM_GENERIC_ARG7), \
+ DEFINE_GPR_PPC64(r10, "arg8", LLDB_REGNUM_GENERIC_ARG8), \
+ DEFINE_GPR_PPC64(r11, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r12, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r13, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r14, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r15, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r16, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r17, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r18, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r19, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r20, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r21, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r22, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r23, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r24, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r25, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r26, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r27, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r28, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r29, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r30, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r31, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \
+ DEFINE_GPR_PPC64(msr, "msr", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(xer, "xer", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(lr, "lr", LLDB_REGNUM_GENERIC_RA), \
+ DEFINE_GPR_PPC64(ctr, "ctr", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(pc, "pc", LLDB_REGNUM_GENERIC_PC), \
+ DEFINE_FPR_PPC64(f0, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f1, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f2, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f3, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f4, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f5, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f6, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f7, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f8, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f9, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f10, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f11, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f12, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f13, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f14, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f15, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f16, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f17, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f18, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f19, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f20, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f21, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f22, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f23, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f24, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f25, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f26, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f27, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f28, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f29, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f30, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f31, NULL, LLDB_INVALID_REGNUM), \
+ {"fpscr", \
+ NULL, \
+ 8, \
+ FPR_PPC64_OFFSET(fpscr), \
+ lldb::eEncodingUint, \
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_fpscr_ppc64, \
+ ppc64_dwarf::dwarf_fpscr_ppc64, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, fpr_fpscr_ppc64}, \
+ NULL, \
+ NULL, \
+ NULL, \
+ 0}, \
+ DEFINE_VMX_PPC64(vr0, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr1, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr2, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr3, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr4, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr5, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr6, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr7, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr8, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr9, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr10, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr11, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr12, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr13, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr14, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr15, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr16, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr17, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr18, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr19, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr20, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr21, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr22, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr23, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr24, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr25, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr26, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr27, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr28, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr29, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr30, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr31, LLDB_INVALID_REGNUM), \
+ {"vscr", \
+ NULL, \
+ 4, \
+ VMX_PPC64_OFFSET(vscr), \
+ lldb::eEncodingUint, \
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_vscr_ppc64, ppc64_dwarf::dwarf_vscr_ppc64, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_ppc64}, \
+ NULL, \
+ NULL, \
+ NULL, \
+ 0}, \
+ {"vrsave", \
+ NULL, \
+ 4, \
+ VMX_PPC64_OFFSET(vrsave), \
+ lldb::eEncodingUint, \
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_vrsave_ppc64, \
+ ppc64_dwarf::dwarf_vrsave_ppc64, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, vmx_vrsave_ppc64}, \
+ NULL, \
+ NULL, \
+ NULL, \
+ 0}, /* */
+
+typedef struct _GPR_PPC64 {
+ uint64_t r0;
+ uint64_t r1;
+ uint64_t r2;
+ uint64_t r3;
+ uint64_t r4;
+ uint64_t r5;
+ uint64_t r6;
+ uint64_t r7;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t r16;
+ uint64_t r17;
+ uint64_t r18;
+ uint64_t r19;
+ uint64_t r20;
+ uint64_t r21;
+ uint64_t r22;
+ uint64_t r23;
+ uint64_t r24;
+ uint64_t r25;
+ uint64_t r26;
+ uint64_t r27;
+ uint64_t r28;
+ uint64_t r29;
+ uint64_t r30;
+ uint64_t r31;
+ uint64_t cr;
+ uint64_t msr;
+ uint64_t xer;
+ uint64_t lr;
+ uint64_t ctr;
+ uint64_t pc;
+ uint64_t pad[3];
+} GPR_PPC64;
+
+typedef struct _FPR_PPC64 {
+ uint64_t f0;
+ uint64_t f1;
+ uint64_t f2;
+ uint64_t f3;
+ uint64_t f4;
+ uint64_t f5;
+ uint64_t f6;
+ uint64_t f7;
+ uint64_t f8;
+ uint64_t f9;
+ uint64_t f10;
+ uint64_t f11;
+ uint64_t f12;
+ uint64_t f13;
+ uint64_t f14;
+ uint64_t f15;
+ uint64_t f16;
+ uint64_t f17;
+ uint64_t f18;
+ uint64_t f19;
+ uint64_t f20;
+ uint64_t f21;
+ uint64_t f22;
+ uint64_t f23;
+ uint64_t f24;
+ uint64_t f25;
+ uint64_t f26;
+ uint64_t f27;
+ uint64_t f28;
+ uint64_t f29;
+ uint64_t f30;
+ uint64_t f31;
+ uint64_t fpscr;
+} FPR_PPC64;
+
+typedef struct _VMX_PPC64 {
+ uint32_t vr0[4];
+ uint32_t vr1[4];
+ uint32_t vr2[4];
+ uint32_t vr3[4];
+ uint32_t vr4[4];
+ uint32_t vr5[4];
+ uint32_t vr6[4];
+ uint32_t vr7[4];
+ uint32_t vr8[4];
+ uint32_t vr9[4];
+ uint32_t vr10[4];
+ uint32_t vr11[4];
+ uint32_t vr12[4];
+ uint32_t vr13[4];
+ uint32_t vr14[4];
+ uint32_t vr15[4];
+ uint32_t vr16[4];
+ uint32_t vr17[4];
+ uint32_t vr18[4];
+ uint32_t vr19[4];
+ uint32_t vr20[4];
+ uint32_t vr21[4];
+ uint32_t vr22[4];
+ uint32_t vr23[4];
+ uint32_t vr24[4];
+ uint32_t vr25[4];
+ uint32_t vr26[4];
+ uint32_t vr27[4];
+ uint32_t vr28[4];
+ uint32_t vr29[4];
+ uint32_t vr30[4];
+ uint32_t vr31[4];
+ uint32_t pad[2];
+ uint32_t vscr[2];
+ uint32_t vrsave;
+} VMX_PPC64;
+
+
+static lldb_private::RegisterInfo g_register_infos_ppc64[] = {
+ PPC64_REGS
+};
+
+static_assert((sizeof(g_register_infos_ppc64) /
+ sizeof(g_register_infos_ppc64[0])) ==
+ k_num_registers_ppc64,
+ "g_register_infos_powerpc64 has wrong number of register infos");
+
+#undef DEFINE_FPR_PPC64
+#undef DEFINE_GPR_PPC64
+#undef DEFINE_VMX_PPC64
+
+#endif // DECLARE_REGISTER_INFOS_PPC64_STRUCT
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 3e860874183c..3dbfe611e713 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -356,8 +356,8 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
{
if (exc_sub_code == 5) {
- // On MacOSX, a SIGTRAP can signify that a process has called
- // exec, so we should check with our dynamic loader to verify.
+ // On MacOSX, a SIGTRAP can signify that a process has called exec,
+ // so we should check with our dynamic loader to verify.
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
@@ -403,10 +403,8 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (!exc_sub_code) {
// This looks like a plain trap.
// Have to check if there is a breakpoint here as well. When you
- // single-step onto a trap,
- // the single step stops you not to trap. Since we also do that
- // check below, let's just use
- // that logic.
+ // single-step onto a trap, the single step stops you not to trap.
+ // Since we also do that check below, let's just use that logic.
is_actual_breakpoint = true;
is_trace_if_actual_breakpoint_missing = true;
} else {
@@ -419,8 +417,8 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
(lldb::addr_t)exc_sub_code);
if (wp_sp && wp_sp->IsEnabled()) {
// Debugserver may piggyback the hardware index of the fired
- // watchpoint in the exception data.
- // Set the hardware index if that's the case.
+ // watchpoint in the exception data. Set the hardware index if
+ // that's the case.
if (exc_data_count >= 3)
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread,
@@ -450,16 +448,15 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a
- // known/enabled
- // data break address from our watchpoint list.
+ // known/enabled data break address from our watchpoint list.
lldb::WatchpointSP wp_sp;
if (target)
wp_sp = target->GetWatchpointList().FindByAddress(
(lldb::addr_t)exc_sub_code);
if (wp_sp && wp_sp->IsEnabled()) {
// Debugserver may piggyback the hardware index of the fired
- // watchpoint in the exception data.
- // Set the hardware index if that's the case.
+ // watchpoint in the exception data. Set the hardware index if
+ // that's the case.
if (exc_data_count >= 3)
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread,
@@ -473,9 +470,9 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
is_actual_breakpoint = true;
is_trace_if_actual_breakpoint_missing = true;
} else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
- // is currently returning this so accept it as
- // indicating a breakpoint until the kernel is
- // fixed
+ // is currently returning this so accept it
+ // as indicating a breakpoint until the
+ // kernel is fixed
{
is_actual_breakpoint = true;
is_trace_if_actual_breakpoint_missing = true;
@@ -493,16 +490,15 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a
- // known/enabled
- // data break address from our watchpoint list.
+ // known/enabled data break address from our watchpoint list.
lldb::WatchpointSP wp_sp;
if (target)
wp_sp = target->GetWatchpointList().FindByAddress(
(lldb::addr_t)exc_sub_code);
if (wp_sp && wp_sp->IsEnabled()) {
// Debugserver may piggyback the hardware index of the fired
- // watchpoint in the exception data.
- // Set the hardware index if that's the case.
+ // watchpoint in the exception data. Set the hardware index if
+ // that's the case.
if (exc_data_count >= 3)
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread,
@@ -514,8 +510,7 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
return StopInfo::CreateStopReasonToTrace(thread);
}
// It looks like exc_sub_code has the 4 bytes of the instruction that
- // triggered the
- // exception, i.e. our breakpoint opcode
+ // triggered the exception, i.e. our breakpoint opcode
is_actual_breakpoint = exc_code == 1;
break;
}
@@ -534,23 +529,21 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (process_sp)
bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp && bp_site_sp->IsEnabled()) {
- // Update the PC if we were asked to do so, but only do
- // so if we find a breakpoint that we know about cause
- // this could be a trap instruction in the code
+ // Update the PC if we were asked to do so, but only do so if we find
+ // a breakpoint that we know about cause this could be a trap
+ // instruction in the code
if (pc_decrement > 0 && adjust_pc_if_needed)
reg_ctx_sp->SetPC(pc);
// If the breakpoint is for this thread, then we'll report the hit,
- // but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
+ // but if it is for another thread, we can just report no reason. We
+ // don't need to worry about stepping over the breakpoint here, that
// will be taken care of when the thread resumes and notices that
- // there's a breakpoint under the pc.
- // If we have an operating system plug-in, we might have set a thread
- // specific breakpoint using the
+ // there's a breakpoint under the pc. If we have an operating system
+ // plug-in, we might have set a thread specific breakpoint using the
// operating system thread ID, so we can't make any assumptions about
- // the thread ID so we must always
- // report the breakpoint regardless of the thread.
+ // the thread ID so we must always report the breakpoint regardless
+ // of the thread.
if (bp_site_sp->ValidForThisThread(&thread) ||
thread.GetProcess()->GetOperatingSystem() != NULL)
return StopInfo::CreateStopReasonWithBreakpointSiteID(
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
index 5ff928c69e59..0c7c195815a4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
@@ -62,7 +62,7 @@ ThreadMemory::CreateRegisterContextForFrame(StackFrame *frame) {
reg_ctx_sp = GetRegisterContext();
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 2b34bddd90b2..55559f07f1e5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -132,16 +132,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
// We want to detect an unwind that cycles erroneously and stop backtracing.
// Don't want this maximum unwind limit to be too low -- if you have a
- // backtrace
- // with an "infinitely recursing" bug, it will crash when the stack blows out
- // and the first 35,000 frames are uninteresting - it's the top most 5 frames
- // that
- // you actually care about. So you can't just cap the unwind at 10,000 or
- // something.
- // Realistically anything over around 200,000 is going to blow out the stack
- // space.
- // If we're still unwinding at that point, we're probably never going to
- // finish.
+ // backtrace with an "infinitely recursing" bug, it will crash when the stack
+ // blows out and the first 35,000 frames are uninteresting - it's the top
+ // most 5 frames that you actually care about. So you can't just cap the
+ // unwind at 10,000 or something. Realistically anything over around 200,000
+ // is going to blow out the stack space. If we're still unwinding at that
+ // point, we're probably never going to finish.
if (cur_idx > 300000) {
if (log)
log->Printf("%*sFrame %d unwound too many frames, assuming unwind has "
@@ -152,13 +148,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
if (reg_ctx_sp.get() == NULL) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -172,15 +167,13 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (!reg_ctx_sp->IsValid()) {
- // We failed to get a valid RegisterContext.
- // See if the regctx below this on the stack has a fallback unwind plan it
- // can use.
- // Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // We failed to get a valid RegisterContext. See if the regctx below this
+ // on the stack has a fallback unwind plan it can use. Subsequent calls to
+ // TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -195,13 +188,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (!reg_ctx_sp->GetCFA(cursor_sp->cfa)) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -216,27 +208,21 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa)) {
// On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not
- // have
- // its (constructed) CFA aligned correctly -- don't do the abi alignment
- // check for
- // these.
+ // have its (constructed) CFA aligned correctly -- don't do the abi
+ // alignment check for these.
if (reg_ctx_sp->IsTrapHandlerFrame() == false) {
// See if we can find a fallback unwind plan for THIS frame. It may be
// that the UnwindPlan we're using for THIS frame was bad and gave us a
- // bad CFA.
- // If that's not it, then see if we can change the UnwindPlan for the
- // frame
- // below us ("NEXT") -- see if using that other UnwindPlan gets us a
- // better
- // unwind state.
+ // bad CFA. If that's not it, then see if we can change the UnwindPlan
+ // for the frame below us ("NEXT") -- see if using that other UnwindPlan
+ // gets us a better unwind state.
if (reg_ctx_sp->TryFallbackUnwindPlan() == false ||
reg_ctx_sp->GetCFA(cursor_sp->cfa) == false ||
abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) {
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be
- // updated. Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of
+ // prev_frame still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -259,13 +245,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (!reg_ctx_sp->ReadPC(cursor_sp->start_pc)) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -280,13 +265,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -320,13 +304,12 @@ void UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid(ABI *abi) {
CursorSP old_m_candidate_frame = m_candidate_frame;
// Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan
- // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also
- // update the cfa of Frame 0 (if required).
+ // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also update
+ // the cfa of Frame 0 (if required).
AddOneMoreFrame(abi);
- // Remove all the frames added by above function as the purpose of
- // using above function was just to check whether Unwinder of Frame 0
- // works or not.
+ // Remove all the frames added by above function as the purpose of using
+ // above function was just to check whether Unwinder of Frame 0 works or not.
for (uint32_t i = 1; i < m_frames.size(); i++)
m_frames.pop_back();
@@ -362,51 +345,44 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) {
m_frames.push_back(new_frame);
- // If we can get one more frame further then accept that we get back a correct
- // frame.
+ // If we can get one more frame further then accept that we get back a
+ // correct frame.
m_candidate_frame = GetOneMoreFrame(abi);
if (m_candidate_frame)
return true;
// We can't go further from the frame returned by GetOneMore frame. Lets try
- // to get a
- // different frame with using the fallback unwind plan.
+ // to get a different frame with using the fallback unwind plan.
if (!m_frames[m_frames.size() - 2]
->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// We don't have a valid fallback unwind plan. Accept the frame as it is.
- // This is a
- // valid situation when we are at the bottom of the stack.
+ // This is a valid situation when we are at the bottom of the stack.
return true;
}
// Remove the possibly incorrect frame from the frame list and try to add a
- // different one with
- // the newly selected fallback unwind plan.
+ // different one with the newly selected fallback unwind plan.
m_frames.pop_back();
CursorSP new_frame_v2 = GetOneMoreFrame(abi);
if (new_frame_v2 == nullptr) {
// We haven't got a new frame from the fallback unwind plan. Accept the
- // frame from the
- // original unwind plan. This is a valid situation when we are at the bottom
- // of the stack.
+ // frame from the original unwind plan. This is a valid situation when we
+ // are at the bottom of the stack.
m_frames.push_back(new_frame);
return true;
}
// Push the new frame to the list and try to continue from this frame. If we
- // can get a new frame
- // then accept it as the correct one.
+ // can get a new frame then accept it as the correct one.
m_frames.push_back(new_frame_v2);
m_candidate_frame = GetOneMoreFrame(abi);
if (m_candidate_frame) {
// If control reached here then TryFallbackUnwindPlan had succeeded for
- // Cursor::m_frames[m_frames.size() - 2].
- // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() -
- // 1] and a frame after that.
- // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was
- // already updated during TryFallbackUnwindPlan
- // call above. However, cfa field still needs to be updated. Hence updating
- // it here and then returning.
+ // Cursor::m_frames[m_frames.size() - 2]. It also succeeded to Unwind next
+ // 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that. For
+ // Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already
+ // updated during TryFallbackUnwindPlan call above. However, cfa field
+ // still needs to be updated. Hence updating it here and then returning.
if (!(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(
m_frames[m_frames.size() - 2]->cfa)))
return false;
@@ -414,8 +390,7 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) {
}
// The new frame hasn't helped in unwinding. Fall back to the original one as
- // the default unwind
- // plan is usually more reliable then the fallback one.
+ // the default unwind plan is usually more reliable then the fallback one.
m_frames.pop_back();
m_frames.push_back(new_frame);
return true;
@@ -486,10 +461,9 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
if (static_cast<size_t>(frame_num) >= m_frames.size())
return false;
- // Never interrogate more than one level while looking for the saved pc value.
- // If the value
- // isn't saved by frame_num, none of the frames lower on the stack will have a
- // useful value.
+ // Never interrogate more than one level while looking for the saved pc
+ // value. If the value isn't saved by frame_num, none of the frames lower on
+ // the stack will have a useful value.
if (pc_reg) {
UnwindLLDB::RegisterSearchResult result;
result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister(
@@ -505,8 +479,7 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
lldb_regnum, regloc);
// We descended down to the live register context aka stack frame 0 and are
- // reading the value
- // out of a live register.
+ // reading the value out of a live register.
if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound &&
regloc.type ==
UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext) {
@@ -514,11 +487,9 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
}
// If we have unwind instructions saying that register N is saved in
- // register M in the middle of
- // the stack (and N can equal M here, meaning the register was not used in
- // this function), then
- // change the register number we're looking for to M and keep looking for a
- // concrete location
+ // register M in the middle of the stack (and N can equal M here, meaning
+ // the register was not used in this function), then change the register
+ // number we're looking for to M and keep looking for a concrete location
// down the stack, or an actual value from a live RegisterContext at frame
// 0.
if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound &&
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
index 3f84649aa05f..3d1f85a3dec3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -17,6 +17,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Unwind.h"
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
index d831011cb661..2115b4e179c0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
@@ -133,8 +133,8 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386(
if (addr_range_ptr) {
if (first_frame->GetFrameCodeAddress() ==
addr_range_ptr->GetBaseAddress()) {
- // We are at the first instruction, so we can recover the
- // previous PC by dereferencing the SP
+ // We are at the first instruction, so we can recover the previous PC
+ // by dereferencing the SP
lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
// Read the real second frame return address into frame.pc
if (first_frame_sp &&
@@ -224,8 +224,8 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64(
if (addr_range_ptr) {
if (first_frame->GetFrameCodeAddress() ==
addr_range_ptr->GetBaseAddress()) {
- // We are at the first instruction, so we can recover the
- // previous PC by dereferencing the SP
+ // We are at the first instruction, so we can recover the previous PC
+ // by dereferencing the SP
lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
// Read the real second frame return address into frame.pc
if (process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc),
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h
new file mode 100644
index 000000000000..9ea81c00b666
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h
@@ -0,0 +1,139 @@
+//===-- lldb-ppc64-register-enums.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_ppc64_register_enums_h
+#define lldb_ppc64_register_enums_h
+
+// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
+
+// ---------------------------------------------------------------------------
+// Internal codes for all ppc64 registers.
+// ---------------------------------------------------------------------------
+enum {
+ k_first_gpr_ppc64,
+ gpr_r0_ppc64 = k_first_gpr_ppc64,
+ gpr_r1_ppc64,
+ gpr_r2_ppc64,
+ gpr_r3_ppc64,
+ gpr_r4_ppc64,
+ gpr_r5_ppc64,
+ gpr_r6_ppc64,
+ gpr_r7_ppc64,
+ gpr_r8_ppc64,
+ gpr_r9_ppc64,
+ gpr_r10_ppc64,
+ gpr_r11_ppc64,
+ gpr_r12_ppc64,
+ gpr_r13_ppc64,
+ gpr_r14_ppc64,
+ gpr_r15_ppc64,
+ gpr_r16_ppc64,
+ gpr_r17_ppc64,
+ gpr_r18_ppc64,
+ gpr_r19_ppc64,
+ gpr_r20_ppc64,
+ gpr_r21_ppc64,
+ gpr_r22_ppc64,
+ gpr_r23_ppc64,
+ gpr_r24_ppc64,
+ gpr_r25_ppc64,
+ gpr_r26_ppc64,
+ gpr_r27_ppc64,
+ gpr_r28_ppc64,
+ gpr_r29_ppc64,
+ gpr_r30_ppc64,
+ gpr_r31_ppc64,
+ gpr_cr_ppc64,
+ gpr_msr_ppc64,
+ gpr_xer_ppc64,
+ gpr_lr_ppc64,
+ gpr_ctr_ppc64,
+ gpr_pc_ppc64,
+ k_last_gpr_ppc64 = gpr_pc_ppc64,
+
+ k_first_fpr_ppc64,
+ fpr_f0_ppc64 = k_first_fpr_ppc64,
+ fpr_f1_ppc64,
+ fpr_f2_ppc64,
+ fpr_f3_ppc64,
+ fpr_f4_ppc64,
+ fpr_f5_ppc64,
+ fpr_f6_ppc64,
+ fpr_f7_ppc64,
+ fpr_f8_ppc64,
+ fpr_f9_ppc64,
+ fpr_f10_ppc64,
+ fpr_f11_ppc64,
+ fpr_f12_ppc64,
+ fpr_f13_ppc64,
+ fpr_f14_ppc64,
+ fpr_f15_ppc64,
+ fpr_f16_ppc64,
+ fpr_f17_ppc64,
+ fpr_f18_ppc64,
+ fpr_f19_ppc64,
+ fpr_f20_ppc64,
+ fpr_f21_ppc64,
+ fpr_f22_ppc64,
+ fpr_f23_ppc64,
+ fpr_f24_ppc64,
+ fpr_f25_ppc64,
+ fpr_f26_ppc64,
+ fpr_f27_ppc64,
+ fpr_f28_ppc64,
+ fpr_f29_ppc64,
+ fpr_f30_ppc64,
+ fpr_f31_ppc64,
+ fpr_fpscr_ppc64,
+ k_last_fpr_ppc64 = fpr_fpscr_ppc64,
+
+ k_first_vmx_ppc64,
+ vmx_vr0_ppc64 = k_first_vmx_ppc64,
+ vmx_vr1_ppc64,
+ vmx_vr2_ppc64,
+ vmx_vr3_ppc64,
+ vmx_vr4_ppc64,
+ vmx_vr5_ppc64,
+ vmx_vr6_ppc64,
+ vmx_vr7_ppc64,
+ vmx_vr8_ppc64,
+ vmx_vr9_ppc64,
+ vmx_vr10_ppc64,
+ vmx_vr11_ppc64,
+ vmx_vr12_ppc64,
+ vmx_vr13_ppc64,
+ vmx_vr14_ppc64,
+ vmx_vr15_ppc64,
+ vmx_vr16_ppc64,
+ vmx_vr17_ppc64,
+ vmx_vr18_ppc64,
+ vmx_vr19_ppc64,
+ vmx_vr20_ppc64,
+ vmx_vr21_ppc64,
+ vmx_vr22_ppc64,
+ vmx_vr23_ppc64,
+ vmx_vr24_ppc64,
+ vmx_vr25_ppc64,
+ vmx_vr26_ppc64,
+ vmx_vr27_ppc64,
+ vmx_vr28_ppc64,
+ vmx_vr29_ppc64,
+ vmx_vr30_ppc64,
+ vmx_vr31_ppc64,
+ vmx_vscr_ppc64,
+ vmx_vrsave_ppc64,
+ k_last_vmx_ppc64 = vmx_vrsave_ppc64,
+
+ k_num_registers_ppc64,
+ k_num_gpr_registers_ppc64 = k_last_gpr_ppc64 - k_first_gpr_ppc64 + 1,
+ k_num_fpr_registers_ppc64 = k_last_fpr_ppc64 - k_first_fpr_ppc64 + 1,
+ k_num_vmx_registers_ppc64 = k_last_vmx_ppc64 - k_first_vmx_ppc64 + 1,
+};
+
+#endif // #ifndef lldb_ppc64_register_enums_h
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 7d6a0c9ad2df..7bb7b72eaac1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -56,9 +56,9 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
const FileSpec *crash_file) {
lldb::ProcessSP process_sp;
if (crash_file) {
- // Read enough data for a ELF32 header or ELF64 header
- // Note: Here we care about e_type field only, so it is safe
- // to ignore possible presence of the header extension.
+ // Read enough data for a ELF32 header or ELF64 header Note: Here we care
+ // about e_type field only, so it is safe to ignore possible presence of
+ // the header extension.
const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(),
@@ -107,10 +107,10 @@ ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
//----------------------------------------------------------------------
ProcessElfCore::~ProcessElfCore() {
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
}
@@ -206,8 +206,8 @@ Status ProcessElfCore::DoLoadCore() {
m_core_range_infos.Sort();
}
- // Even if the architecture is set in the target, we need to override
- // it to match the core file which is always single arch.
+ // Even if the architecture is set in the target, we need to override it to
+ // match the core file which is always single arch.
ArchSpec arch(m_core_module_sp->GetArchitecture());
ArchSpec target_arch = GetTarget().GetArchitecture();
@@ -241,8 +241,7 @@ Status ProcessElfCore::DoLoadCore() {
}
// Core files are useless without the main executable. See if we can locate
- // the main
- // executable using data we found in the core file notes.
+ // the main executable using data we found in the core file notes.
lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
if (!exe_module_sp) {
// The first entry in the NT_FILE might be our executable
@@ -250,7 +249,8 @@ Status ProcessElfCore::DoLoadCore() {
ModuleSpec exe_module_spec;
exe_module_spec.GetArchitecture() = arch;
exe_module_spec.GetFileSpec().SetFile(
- m_nt_file_entries[0].path.GetCString(), false);
+ m_nt_file_entries[0].path.GetCString(), false,
+ FileSpec::Style::native);
if (exe_module_spec.GetFileSpec()) {
exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
if (exe_module_sp)
@@ -297,8 +297,8 @@ bool ProcessElfCore::IsAlive() { return true; }
//------------------------------------------------------------------
size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
- // Don't allow the caching that lldb_private::Process::ReadMemory does
- // since in core files we have it all cached our our core file anyway.
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // in core files we have it all cached our our core file anyway.
return DoReadMemory(addr, buf, size, error);
}
@@ -368,17 +368,18 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
lldb::addr_t bytes_left =
0; // Number of bytes available in the core file from the given address
- // Don't proceed if core file doesn't contain the actual data for this address range.
+ // Don't proceed if core file doesn't contain the actual data for this
+ // address range.
if (file_start == file_end)
return 0;
- // Figure out how many on-disk bytes remain in this segment
- // starting at the given offset
+ // Figure out how many on-disk bytes remain in this segment starting at the
+ // given offset
if (file_end > file_start + offset)
bytes_left = file_end - (file_start + offset);
- // Figure out how many bytes we need to zero-fill if we are
- // reading more bytes than available in the on-disk segment
+ // Figure out how many bytes we need to zero-fill if we are reading more
+ // bytes than available in the on-disk segment
if (bytes_to_read > bytes_left) {
zero_fill_size = bytes_to_read - bytes_left;
bytes_to_read = bytes_left;
@@ -551,8 +552,8 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
ThreadData thread_data;
for (const auto &note : notes) {
- // NetBSD per-thread information is stored in notes named
- // "NetBSD-CORE@nnn" so match on the initial part of the string.
+ // NetBSD per-thread information is stored in notes named "NetBSD-CORE@nnn"
+ // so match on the initial part of the string.
if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE"))
continue;
@@ -585,8 +586,8 @@ llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
ThreadData thread_data;
for (const auto &note : notes) {
- // OpenBSD per-thread information is stored in notes named
- // "OpenBSD@nnn" so match on the initial part of the string.
+ // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so
+ // match on the initial part of the string.
if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD"))
continue;
@@ -665,7 +666,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
Status status = prpsinfo.Parse(note.data, arch);
if (status.Fail())
return status.ToError();
- thread_data.name = prpsinfo.pr_fname;
+ thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname)));
SetID(prpsinfo.pr_pid);
break;
}
@@ -749,9 +750,9 @@ ArchSpec ProcessElfCore::GetArchitecture() {
ArchSpec target_arch = GetTarget().GetArchitecture();
arch.MergeFrom(target_arch);
- // On MIPS there is no way to differentiate betwenn 32bit and 64bit core files
- // and this information can't be merged in from the target arch so we fail
- // back to unconditionally returning the target arch in this config.
+ // On MIPS there is no way to differentiate betwenn 32bit and 64bit core
+ // files and this information can't be merged in from the target arch so we
+ // fail back to unconditionally returning the target arch in this config.
if (target_arch.IsMIPS()) {
return target_arch;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index e252b5a35e9c..532a1f5c0831 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -56,7 +56,7 @@ bool RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info,
if (IsGPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
if (reg_info->byte_size == 4 && !(arch.GetMachine() == llvm::Triple::mips64el))
// In case of 32bit core file, the register data are placed at 4 byte
- // offset.
+ // offset.
offset = offset / 2;
v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
value = v;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index a5c7ffda1da5..a1f26d52444b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -60,8 +60,8 @@ bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info,
const uint8_t *src;
size_t offset;
const size_t fxsave_offset = reg_info->byte_offset - GetFXSAVEOffset();
- // make the offset relative to the beginning of the FXSAVE structure
- // because this is the data that we have (not the entire UserArea)
+ // make the offset relative to the beginning of the FXSAVE structure because
+ // this is the data that we have (not the entire UserArea)
if (m_gpregset && reg_info->byte_offset < GetGPRSize()) {
src = m_gpregset.get();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 8d32e55ad102..0888322e17ba 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -59,16 +59,9 @@ void ThreadElfCore::RefreshStateAfterStop() {
GetRegisterContext()->InvalidateIfNeeded(false);
}
-void ThreadElfCore::ClearStackFrames() {
- Unwind *unwinder = GetUnwinder();
- if (unwinder)
- unwinder->Clear();
- Thread::ClearStackFrames();
-}
-
RegisterContextSP ThreadElfCore::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL) {
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp) {
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
}
return m_reg_context_sp;
}
@@ -88,7 +81,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
ArchSpec arch = process->GetArchitecture();
- RegisterInfoInterface *reg_interface = NULL;
+ RegisterInfoInterface *reg_interface = nullptr;
switch (arch.GetTriple().getOS()) {
case llvm::Triple::FreeBSD: {
@@ -242,8 +235,10 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
}
reg_ctx_sp = m_thread_reg_ctx_sp;
- } else if (m_unwinder_ap.get()) {
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
+ } else {
+ Unwind *unwinder = GetUnwinder();
+ if (unwinder != nullptr)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
}
@@ -300,8 +295,8 @@ Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
return error;
}
- // Read field by field to correctly account for endianess
- // of both the core dump and the platform running lldb.
+ // Read field by field to correctly account for endianess of both the core
+ // dump and the platform running lldb.
offset_t offset = 0;
si_signo = data.GetU32(&offset);
si_code = data.GetU32(&offset);
@@ -348,7 +343,7 @@ size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
return sizeof(ELFLinuxPrPsInfo);
return mips_linux_pr_psinfo_size_o32_n32;
}
-
+
switch (arch.GetCore()) {
case lldb_private::ArchSpec::eCore_s390x_generic:
case lldb_private::ArchSpec::eCore_x86_64_x86_64:
@@ -390,9 +385,9 @@ Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
pr_uid = data.GetU32(&offset);
pr_gid = data.GetU32(&offset);
} else {
- // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
- pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
- pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
+ // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
+ pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
+ pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
}
pr_pid = data.GetU32(&offset);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
index 335f698dbb24..167fd6edc4ce 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -146,8 +146,6 @@ public:
lldb::RegisterContextSP
CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
- void ClearStackFrames() override;
-
static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
const char *GetName() override {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index 4d4a4f8c5c7a..4e20b56fb111 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -109,16 +109,14 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
const bool should_stop = ShouldStop(signals, response);
response.SetFilePos(0);
- // The packet we should resume with. In the future
- // we should check our thread list and "do the right thing"
- // for new threads that show up while we stop and run async
- // packets. Setting the packet to 'c' to continue all threads
- // is the right thing to do 99.99% of the time because if a
- // thread was single stepping, and we sent an interrupt, we
- // will notice above that we didn't stop due to an interrupt
- // but stopped due to stepping and we would _not_ continue.
- // This packet may get modified by the async actions (e.g. to send a
- // signal).
+ // The packet we should resume with. In the future we should check our
+ // thread list and "do the right thing" for new threads that show up
+ // while we stop and run async packets. Setting the packet to 'c' to
+ // continue all threads is the right thing to do 99.99% of the time
+ // because if a thread was single stepping, and we sent an interrupt, we
+ // will notice above that we didn't stop due to an interrupt but stopped
+ // due to stepping and we would _not_ continue. This packet may get
+ // modified by the async actions (e.g. to send a signal).
m_continue_packet = 'c';
cont_lock.unlock();
@@ -177,6 +175,30 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
}
GDBRemoteCommunication::PacketResult
+GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async,
+ llvm::function_ref<void(llvm::StringRef)> output_callback) {
+ Lock lock(*this, send_async);
+ if (!lock) {
+ if (Log *log =
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
+ log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
+ "packet '%.*s' (send_async=%d)",
+ __FUNCTION__, int(payload.size()), payload.data(),
+ send_async);
+ return PacketResult::ErrorSendFailed;
+ }
+
+ PacketResult packet_result = SendPacketNoLock(payload);
+ if (packet_result != PacketResult::Success)
+ return packet_result;
+
+ return ReadPacketWithOutputSupport(response, GetPacketTimeout(), true,
+ output_callback);
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
llvm::StringRef payload, StringExtractorGDBRemote &response) {
PacketResult packet_result = SendPacketNoLock(payload);
@@ -239,19 +261,16 @@ bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
if (m_async_count == 0)
return true; // We were not interrupted. The process stopped on its own.
- // Older debugserver stubs (before April 2016) can return two
- // stop-reply packets in response to a ^C packet.
- // Additionally, all debugservers still return two stop replies if
- // the inferior stops due to some other reason before the remote
- // stub manages to interrupt it. We need to wait for this
- // additional packet to make sure the packet sequence does not get
- // skewed.
+ // Older debugserver stubs (before April 2016) can return two stop-reply
+ // packets in response to a ^C packet. Additionally, all debugservers still
+ // return two stop replies if the inferior stops due to some other reason
+ // before the remote stub manages to interrupt it. We need to wait for this
+ // additional packet to make sure the packet sequence does not get skewed.
StringExtractorGDBRemote extra_stop_reply_packet;
ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
- // Interrupting is typically done using SIGSTOP or SIGINT, so if
- // the process stops with some other signal, we definitely want to
- // stop.
+ // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
+ // stops with some other signal, we definitely want to stop.
const uint8_t signo = response.GetHexU8(UINT8_MAX);
if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
signo != signals.GetSignalNumberFromName("SIGINT"))
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index 2646405c9b91..3d84ce0ebe18 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -48,6 +48,11 @@ public:
StringExtractorGDBRemote &response,
bool send_async);
+ PacketResult SendPacketAndReceiveResponseWithOutputSupport(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async,
+ llvm::function_ref<void(llvm::StringRef)> output_callback);
+
bool SendvContPacket(llvm::StringRef payload,
StringExtractorGDBRemote &response);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 949cf19db658..c335b6002861 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -150,9 +150,8 @@ GDBRemoteCommunication::~GDBRemoteCommunication() {
Disconnect();
}
- // Stop the communications read thread which is used to parse all
- // incoming packets. This function will block until the read
- // thread returns.
+ // Stop the communications read thread which is used to parse all incoming
+ // packets. This function will block until the read thread returns.
if (m_read_thread_enabled)
StopReadThread();
}
@@ -217,12 +216,10 @@ GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
}
}
- // If logging was just enabled and we have history, then dump out what
- // we have to the log so we get the historical context. The Dump() call
- // that
+ // If logging was just enabled and we have history, then dump out what we
+ // have to the log so we get the historical context. The Dump() call that
// logs all of the packet will set a boolean so that we don't dump this
- // more
- // than once
+ // more than once
if (!m_history.DidDumpToLog())
m_history.Dump(log);
@@ -275,6 +272,23 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() {
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunication::ReadPacketWithOutputSupport(
+ StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
+ bool sync_on_timeout,
+ llvm::function_ref<void(llvm::StringRef)> output_callback) {
+ auto result = ReadPacket(response, timeout, sync_on_timeout);
+ while (result == PacketResult::Success && response.IsNormalResponse() &&
+ response.PeekChar() == 'O') {
+ response.GetChar();
+ std::string output;
+ if (response.GetHexByteString(output))
+ output_callback(output);
+ result = ReadPacket(response, timeout, sync_on_timeout);
+ }
+ return result;
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout,
bool sync_on_timeout) {
@@ -286,8 +300,8 @@ GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
// This function is called when a packet is requested.
// A whole packet is popped from the packet queue and returned to the caller.
-// Packets are placed into this queue from the communication read thread.
-// See GDBRemoteCommunication::AppendBytesToCache.
+// Packets are placed into this queue from the communication read thread. See
+// GDBRemoteCommunication::AppendBytesToCache.
GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::PopPacketFromQueue(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout) {
@@ -407,11 +421,9 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
break;
} else if (successful_responses == 1) {
// We got something else back as the first successful
- // response, it probably is
- // the response to the packet we actually wanted, so copy it
- // over if this
- // is the first success and continue to try to get the qEcho
- // response
+ // response, it probably is the response to the packet we
+ // actually wanted, so copy it over if this is the first
+ // success and continue to try to get the qEcho response
packet = echo_response;
got_actual_response = true;
}
@@ -424,14 +436,13 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
}
// We weren't able to sync back up with the server, we must abort
- // otherwise
- // all responses might not be from the right packets...
+ // otherwise all responses might not be from the right packets...
if (sync_success) {
// We timed out, but were able to recover
if (got_actual_response) {
// We initially timed out, but we did get a response that came in
- // before the successful
- // reply to our qEcho packet, so lets say everything is fine...
+ // before the successful reply to our qEcho packet, so lets say
+ // everything is fine...
return PacketResult::Success;
}
} else {
@@ -473,10 +484,9 @@ bool GDBRemoteCommunication::DecompressPacket() {
size_t pkt_size = m_bytes.size();
- // Smallest possible compressed packet is $N#00 - an uncompressed empty reply,
- // most commonly indicating
- // an unsupported packet. Anything less than 5 characters, it's definitely
- // not a compressed packet.
+ // Smallest possible compressed packet is $N#00 - an uncompressed empty
+ // reply, most commonly indicating an unsupported packet. Anything less than
+ // 5 characters, it's definitely not a compressed packet.
if (pkt_size < 5)
return true;
@@ -505,17 +515,15 @@ bool GDBRemoteCommunication::DecompressPacket() {
1; // The first character of the two hex checksum characters
// Normally size_of_first_packet == m_bytes.size() but m_bytes may contain
- // multiple packets.
- // size_of_first_packet is the size of the initial packet which we'll replace
- // with the decompressed
- // version of, leaving the rest of m_bytes unmodified.
+ // multiple packets. size_of_first_packet is the size of the initial packet
+ // which we'll replace with the decompressed version of, leaving the rest of
+ // m_bytes unmodified.
size_t size_of_first_packet = hash_mark_idx + 3;
// Compressed packets ("$C") start with a base10 number which is the size of
- // the uncompressed payload,
- // then a : and then the compressed data. e.g. $C1024:<binary>#00
- // Update content_start and content_length to only include the <binary> part
- // of the packet.
+ // the uncompressed payload, then a : and then the compressed data. e.g.
+ // $C1024:<binary>#00 Update content_start and content_length to only include
+ // the <binary> part of the packet.
uint64_t decompressed_bufsize = ULONG_MAX;
if (m_bytes[1] == 'C') {
@@ -564,15 +572,14 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
if (m_bytes[1] == 'N') {
- // This packet was not compressed -- delete the 'N' character at the
- // start and the packet may be processed as-is.
+ // This packet was not compressed -- delete the 'N' character at the start
+ // and the packet may be processed as-is.
m_bytes.erase(1, 1);
return true;
}
- // Reverse the gdb-remote binary escaping that was done to the compressed text
- // to
- // guard characters like '$', '#', '}', etc.
+ // Reverse the gdb-remote binary escaping that was done to the compressed
+ // text to guard characters like '$', '#', '}', etc.
std::vector<uint8_t> unescaped_content;
unescaped_content.reserve(content_length);
size_t i = content_start;
@@ -613,12 +620,10 @@ bool GDBRemoteCommunication::DecompressPacket() {
else if (m_compression_type == CompressionType::LZMA)
compression_type = COMPRESSION_LZMA;
- // If we have the expected size of the decompressed payload, we can allocate
- // the right-sized buffer and do it. If we don't have that information,
- // we'll
- // need to try decoding into a big buffer and if the buffer wasn't big
- // enough,
- // increase it and try again.
+ // If we have the expected size of the decompressed payload, we can
+ // allocate the right-sized buffer and do it. If we don't have that
+ // information, we'll need to try decoding into a big buffer and if the
+ // buffer wasn't big enough, increase it and try again.
if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {
decompressed_bytes = compression_decode_buffer(
@@ -706,9 +711,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Parse up the packets into gdb remote packets
if (!m_bytes.empty()) {
- // end_idx must be one past the last valid packet byte. Start
- // it off with an invalid value that is the same as the current
- // index.
+ // end_idx must be one past the last valid packet byte. Start it off with
+ // an invalid value that is the same as the current index.
size_t content_start = 0;
size_t content_length = 0;
size_t total_length = 0;
@@ -743,7 +747,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
checksum_idx = hash_pos + 1;
// Skip the dollar sign
content_start = 1;
- // Don't include the # in the content or the $ in the content length
+ // Don't include the # in the content or the $ in the content
+ // length
content_length = hash_pos - 1;
total_length =
@@ -757,11 +762,10 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
break;
default: {
- // We have an unexpected byte and we need to flush all bad
- // data that is in m_bytes, so we need to find the first
- // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
- // or '$' character (start of packet header) or of course,
- // the end of the data in m_bytes...
+ // We have an unexpected byte and we need to flush all bad data that is
+ // in m_bytes, so we need to find the first byte that is a '+' (ACK), '-'
+ // (NACK), \x03 (CTRL+C interrupt), or '$' character (start of packet
+ // header) or of course, the end of the data in m_bytes...
const size_t bytes_len = m_bytes.size();
bool done = false;
uint32_t idx;
@@ -802,16 +806,14 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
if (log) {
// If logging was just enabled and we have history, then dump out what
// we have to the log so we get the historical context. The Dump() call
- // that
- // logs all of the packet will set a boolean so that we don't dump this
- // more
- // than once
+ // that logs all of the packet will set a boolean so that we don't dump
+ // this more than once
if (!m_history.DidDumpToLog())
m_history.Dump(log);
bool binary = false;
- // Only detect binary for packets that start with a '$' and have a '#CC'
- // checksum
+ // Only detect binary for packets that start with a '$' and have a
+ // '#CC' checksum
if (m_bytes[0] == '$' && total_length > 4) {
for (size_t i = 0; !binary && i < total_length; ++i) {
unsigned char c = m_bytes[i];
@@ -834,8 +836,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Remove binary escaped bytes when displaying the packet...
const char ch = m_bytes[i];
if (ch == 0x7d) {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
+ // 0x7d is the escape character. The next character is to be
+ // XOR'd with 0x20.
const char escapee = m_bytes[++i] ^ 0x20;
strm.Printf("%2.2x", escapee);
} else {
@@ -863,26 +865,25 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Clear packet_str in case there is some existing data in it.
packet_str.clear();
- // Copy the packet from m_bytes to packet_str expanding the
- // run-length encoding in the process.
- // Reserve enough byte for the most common case (no RLE used)
+ // Copy the packet from m_bytes to packet_str expanding the run-length
+ // encoding in the process. Reserve enough byte for the most common case
+ // (no RLE used)
packet_str.reserve(m_bytes.length());
for (std::string::const_iterator c = m_bytes.begin() + content_start;
c != m_bytes.begin() + content_end; ++c) {
if (*c == '*') {
- // '*' indicates RLE. Next character will give us the
- // repeat count and previous character is what is to be
- // repeated.
+ // '*' indicates RLE. Next character will give us the repeat count
+ // and previous character is what is to be repeated.
char char_to_repeat = packet_str.back();
// Number of time the previous character is repeated
int repeat_count = *++c + 3 - ' ';
- // We have the char_to_repeat and repeat_count. Now push
- // it in the packet.
+ // We have the char_to_repeat and repeat_count. Now push it in the
+ // packet.
for (int i = 0; i < repeat_count; ++i)
packet_str.push_back(char_to_repeat);
} else if (*c == 0x7d) {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
+ // 0x7d is the escape character. The next character is to be XOR'd
+ // with 0x20.
char escapee = *++c ^ 0x20;
packet_str.push_back(escapee);
} else {
@@ -897,7 +898,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
if (GetSendAcks()) {
const char *packet_checksum_cstr = &m_bytes[checksum_idx];
char packet_checksum = strtol(packet_checksum_cstr, NULL, 16);
- char actual_checksum = CalculcateChecksum(packet_str);
+ char actual_checksum = CalculcateChecksum(
+ llvm::StringRef(m_bytes).slice(content_start, content_end));
success = packet_checksum == actual_checksum;
if (!success) {
if (log)
@@ -991,11 +993,12 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
char debugserver_path[PATH_MAX];
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
- // Always check to see if we have an environment override for the path
- // to the debugserver to use and use it if we do.
+ // Always check to see if we have an environment override for the path to the
+ // debugserver to use and use it if we do.
const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
if (env_debugserver_path) {
- debugserver_file_spec.SetFile(env_debugserver_path, false);
+ debugserver_file_spec.SetFile(env_debugserver_path, false,
+ FileSpec::Style::native);
if (log)
log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set "
"from environment variable: %s",
@@ -1004,10 +1007,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
debugserver_file_spec = g_debugserver_file_spec;
bool debugserver_exists = debugserver_file_spec.Exists();
if (!debugserver_exists) {
- // The debugserver binary is in the LLDB.framework/Resources
- // directory.
- if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir,
- debugserver_file_spec)) {
+ // The debugserver binary is in the LLDB.framework/Resources directory.
+ debugserver_file_spec = HostInfo::GetSupportExeDir();
+ if (debugserver_file_spec) {
debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
debugserver_exists = debugserver_file_spec.Exists();
if (debugserver_exists) {
@@ -1031,8 +1033,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
__FUNCTION__, debugserver_file_spec.GetPath().c_str());
}
// Don't cache the platform specific GDB server binary as it could
- // change
- // from platform to platform
+ // change from platform to platform
g_debugserver_file_spec.Clear();
}
}
@@ -1080,14 +1081,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
// once data is written to the pipe, debug server is up and running.
Pipe socket_pipe;
- // port is null when debug server should listen on domain socket -
- // we're not interested in port value but rather waiting for debug server
- // to become available.
+ // port is null when debug server should listen on domain socket - we're
+ // not interested in port value but rather waiting for debug server to
+ // become available.
if (pass_comm_fd == -1) {
if (url) {
-// Create a temporary file to get the stdout/stderr and redirect the
-// output of the command into this file. We will later read this file
-// if all goes well and fill the data into "command_output_ptr"
+// Create a temporary file to get the stdout/stderr and redirect the output of
+// the command into this file. We will later read this file if all goes well
+// and fill the data into "command_output_ptr"
#if defined(__APPLE__)
// Binding to port zero, we need to figure out what port it ends up
// using using a named pipe...
@@ -1120,8 +1121,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
#endif
} else {
// No host and port given, so lets listen on our end and make the
- // debugserver
- // connect to us..
+ // debugserver connect to us..
error = StartListenThread("127.0.0.1", 0);
if (error.Fail()) {
if (log)
@@ -1134,7 +1134,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
ConnectionFileDescriptor *connection =
(ConnectionFileDescriptor *)GetConnection();
// Wait for 10 seconds to resolve the bound port
- uint16_t port_ = connection->GetListeningPort(10);
+ uint16_t port_ = connection->GetListeningPort(std::chrono::seconds(10));
if (port_ > 0) {
char port_cstr[32];
snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_);
@@ -1206,11 +1206,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
}
// Copy the current environment to the gdbserver/debugserver instance
- StringList env;
- if (Host::GetEnvironment(env)) {
- for (size_t i = 0; i < env.GetSize(); ++i)
- launch_info.GetEnvironmentEntries().AppendArgument(env[i]);
- }
+ launch_info.GetEnvironment() = Host::GetEnvironment();
// Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction(STDIN_FILENO);
@@ -1327,14 +1323,11 @@ GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {
}
// This function is called via the Communications class read thread when bytes
-// become available
-// for this connection. This function will consume all incoming bytes and try to
-// parse whole
-// packets as they become available. Full packets are placed in a queue, so that
-// all packet
-// requests can simply pop from this queue. Async notification packets will be
-// dispatched
-// immediately to the ProcessGDBRemote Async thread via an event.
+// become available for this connection. This function will consume all
+// incoming bytes and try to parse whole packets as they become available. Full
+// packets are placed in a queue, so that all packet requests can simply pop
+// from this queue. Async notification packets will be dispatched immediately
+// to the ProcessGDBRemote Async thread via an event.
void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
size_t len, bool broadcast,
lldb::ConnectionStatus status) {
@@ -1343,8 +1336,8 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
while (true) {
PacketType type = CheckForPacket(bytes, len, packet);
- // scrub the data so we do not pass it back to CheckForPacket
- // on future passes of the loop
+ // scrub the data so we do not pass it back to CheckForPacket on future
+ // passes of the loop
bytes = nullptr;
len = 0;
@@ -1368,8 +1361,8 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
// put this packet into an event
const char *pdata = packet.GetStringRef().c_str();
- // as the communication class, we are a broadcaster and the
- // async thread is tuned to listen to us
+ // as the communication class, we are a broadcaster and the async thread
+ // is tuned to listen to us
BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify,
new EventDataBytes(pdata));
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index ecc9386e49c7..67796e4c61ef 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -24,10 +24,10 @@
#include "lldb/Core/Listener.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Predicate.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/lldb-public.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
namespace lldb_private {
namespace process_gdb_remote {
@@ -232,6 +232,11 @@ protected:
PacketResult ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout, bool sync_on_timeout);
+ PacketResult ReadPacketWithOutputSupport(
+ StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
+ bool sync_on_timeout,
+ llvm::function_ref<void(llvm::StringRef)> output_callback);
+
// Pop a packet from the queue in a thread safe manner
PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 867f57c475ce..c8b59d5d236b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -21,11 +21,12 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -35,8 +36,8 @@
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Config.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "llvm/ADT/StringSwitch.h"
@@ -81,6 +82,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_qXfer_libraries_read(eLazyBoolCalculate),
m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate),
m_supports_qXfer_features_read(eLazyBoolCalculate),
+ m_supports_qXfer_memory_map_read(eLazyBoolCalculate),
m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
@@ -98,12 +100,12 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
m_curr_tid_run(LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
- m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX),
- m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(),
- m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX),
- m_default_packet_timeout(0), m_max_packet_size(0),
- m_qSupported_response(), m_supported_async_json_packets_is_valid(false),
- m_supported_async_json_packets_sp() {}
+ m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(),
+ m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0),
+ m_max_packet_size(0), m_qSupported_response(),
+ m_supported_async_json_packets_is_valid(false),
+ m_supported_async_json_packets_sp(), m_qXfer_memory_map(),
+ m_qXfer_memory_map_loaded(false) {}
//----------------------------------------------------------------------
// Destructor
@@ -116,8 +118,8 @@ GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
ResetDiscoverableSettings(false);
- // Start the read thread after we send the handshake ack since if we
- // fail to send the handshake ack, there is no reason to continue...
+ // Start the read thread after we send the handshake ack since if we fail to
+ // send the handshake ack, there is no reason to continue...
if (SendAck()) {
// Wait for any responses that might have been queued up in the remote
// GDB server and flush them all
@@ -127,9 +129,9 @@ bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
packet_result = ReadPacket(response, milliseconds(10), false);
// The return value from QueryNoAckModeSupported() is true if the packet
- // was sent and _any_ response (including UNIMPLEMENTED) was received),
- // or false if no response was received. This quickly tells us if we have
- // a live connection to a remote GDB server...
+ // was sent and _any_ response (including UNIMPLEMENTED) was received), or
+ // false if no response was received. This quickly tells us if we have a
+ // live connection to a remote GDB server...
if (QueryNoAckModeSupported()) {
return true;
} else {
@@ -192,6 +194,13 @@ bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
return m_supports_qXfer_features_read == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
+ if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_memory_map_read == eLazyBoolYes;
+}
+
uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
if (m_max_packet_size == 0) {
GetRemoteQSupported();
@@ -205,9 +214,8 @@ bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
m_supports_not_sending_acks = eLazyBoolNo;
// This is the first real packet that we'll send in a debug session and it
- // may take a little
- // longer than normal to receive a reply. Wait at least 6 seconds for a
- // reply to this packet.
+ // may take a little longer than normal to receive a reply. Wait at least
+ // 6 seconds for a reply to this packet.
ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
@@ -296,6 +304,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qXfer_features_read = eLazyBoolCalculate;
+ m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
m_supports_qfProcessInfo = true;
@@ -313,9 +322,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_qSymbol_requests_done = false;
m_supports_qModuleInfo = true;
m_host_arch.Clear();
- m_os_version_major = UINT32_MAX;
- m_os_version_minor = UINT32_MAX;
- m_os_version_update = UINT32_MAX;
+ m_os_version = llvm::VersionTuple();
m_os_build.clear();
m_os_kernel.clear();
m_hostname.clear();
@@ -329,8 +336,8 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_jModulesInfo = true;
}
- // These flags should be reset when we first connect to a GDB server
- // and when our inferior process execs
+ // These flags should be reset when we first connect to a GDB server and when
+ // our inferior process execs
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_process_arch.Clear();
}
@@ -342,6 +349,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
+ m_supports_qXfer_memory_map_read = eLazyBoolNo;
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
// not, we assume no limit
@@ -361,8 +369,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
const char *response_cstr = response.GetStringRef().c_str();
// Hang on to the qSupported packet, so that platforms can do custom
- // configuration of the transport before attaching/launching the
- // process.
+ // configuration of the transport before attaching/launching the process.
m_qSupported_response = response_cstr;
if (::strstr(response_cstr, "qXfer:auxv:read+"))
@@ -377,9 +384,12 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_libraries_read = eLazyBoolYes;
if (::strstr(response_cstr, "qXfer:features:read+"))
m_supports_qXfer_features_read = eLazyBoolYes;
+ if (::strstr(response_cstr, "qXfer:memory-map:read+"))
+ m_supports_qXfer_memory_map_read = eLazyBoolYes;
// Look for a list of compressions in the features list e.g.
- // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma
+ // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
+ // deflate,lzma
const char *features_list = ::strstr(response_cstr, "qXfer:features:");
if (features_list) {
const char *compressions =
@@ -543,9 +553,8 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
}
-// Check if the target supports 'p' packet. It sends out a 'p'
-// packet and checks the response. A normal packet will tell us
-// that support is available.
+// Check if the target supports 'p' packet. It sends out a 'p' packet and
+// checks the response. A normal packet will tell us that support is available.
//
// Takes a valid thread ID because p needs to apply to a thread.
bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
@@ -600,8 +609,8 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
if (m_supports_error_string_reply == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
- // We try to enable error strings in remote packets
- // but if we fail, we just work in the older way.
+ // We try to enable error strings in remote packets but if we fail, we just
+ // work in the older way.
m_supports_error_string_reply = eLazyBoolNo;
if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
PacketResult::Success) {
@@ -715,12 +724,10 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
return m_curr_pid;
} else {
// If we don't get a response for qProcessInfo, check if $qC gives us a
- // result.
- // $qC only returns a real process id on older debugserver and lldb-platform
- // stubs.
- // The gdb remote protocol documents $qC as returning the thread id, which
- // newer
- // debugserver and lldb-gdbserver stubs return correctly.
+ // result. $qC only returns a real process id on older debugserver and
+ // lldb-platform stubs. The gdb remote protocol documents $qC as returning
+ // the thread id, which newer debugserver and lldb-gdbserver stubs return
+ // correctly.
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse("qC", response, false) ==
PacketResult::Success) {
@@ -775,8 +782,8 @@ bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
int GDBRemoteCommunicationClient::SendArgumentsPacket(
const ProcessLaunchInfo &launch_info) {
// Since we don't get the send argv0 separate from the executable path, we
- // need to
- // make sure to use the actual executable path found in the launch_info...
+ // need to make sure to use the actual executable path found in the
+ // launch_info...
std::vector<const char *> argv;
FileSpec exe_file = launch_info.GetExecutableFile();
std::string exe_path;
@@ -822,6 +829,15 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket(
return -1;
}
+int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
+ for (const auto &KV : env) {
+ int r = SendEnvironmentPacket(Environment::compose(KV).c_str());
+ if (r != 0)
+ return r;
+ }
+ return 0;
+}
+
int GDBRemoteCommunicationClient::SendEnvironmentPacket(
char const *name_equal_value) {
if (name_equal_value && name_equal_value[0]) {
@@ -925,18 +941,9 @@ int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
return -1;
}
-bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update) {
- if (GetHostInfo()) {
- if (m_os_version_major != UINT32_MAX) {
- major = m_os_version_major;
- minor = m_os_version_minor;
- update = m_os_version_update;
- return true;
- }
- }
- return false;
+llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
+ GetHostInfo();
+ return m_os_version;
}
bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) {
@@ -1199,9 +1206,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
// "version" key instead of
// "os_version"...
{
- Args::StringToVersion(value, m_os_version_major, m_os_version_minor,
- m_os_version_update);
- if (m_os_version_major != UINT32_MAX)
+ if (!m_os_version.tryParse(value))
++num_keys_decoded;
} else if (name.equals("watchpoint_exceptions_received")) {
m_watchpoints_trigger_after_instruction =
@@ -1451,7 +1456,8 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ PacketResult::Success &&
+ response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
llvm::StringRef name;
llvm::StringRef value;
addr_t addr_value = LLDB_INVALID_ADDRESS;
@@ -1527,8 +1533,134 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
if (m_supports_memory_region_info == eLazyBoolNo) {
error.SetErrorString("qMemoryRegionInfo is not supported");
}
- if (error.Fail())
- region_info.Clear();
+
+ // Try qXfer:memory-map:read to get region information not included in
+ // qMemoryRegionInfo
+ MemoryRegionInfo qXfer_region_info;
+ Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
+
+ if (error.Fail()) {
+ // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
+ // the qXfer result as a fallback
+ if (qXfer_error.Success()) {
+ region_info = qXfer_region_info;
+ error.Clear();
+ } else {
+ region_info.Clear();
+ }
+ } else if (qXfer_error.Success()) {
+ // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
+ // both regions are the same range, update the result to include the flash-
+ // memory information that is specific to the qXfer result.
+ if (region_info.GetRange() == qXfer_region_info.GetRange()) {
+ region_info.SetFlash(qXfer_region_info.GetFlash());
+ region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
+ }
+ }
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
+ lldb::addr_t addr, MemoryRegionInfo &region) {
+ Status error = LoadQXferMemoryMap();
+ if (!error.Success())
+ return error;
+ for (const auto &map_region : m_qXfer_memory_map) {
+ if (map_region.GetRange().Contains(addr)) {
+ region = map_region;
+ return error;
+ }
+ }
+ error.SetErrorString("Region not found");
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
+
+ Status error;
+
+ if (m_qXfer_memory_map_loaded)
+ // Already loaded, return success
+ return error;
+
+ if (!XMLDocument::XMLEnabled()) {
+ error.SetErrorString("XML is not supported");
+ return error;
+ }
+
+ if (!GetQXferMemoryMapReadSupported()) {
+ error.SetErrorString("Memory map is not supported");
+ return error;
+ }
+
+ std::string xml;
+ lldb_private::Status lldberr;
+ if (!ReadExtFeature(ConstString("memory-map"), ConstString(""), xml,
+ lldberr)) {
+ error.SetErrorString("Failed to read memory map");
+ return error;
+ }
+
+ XMLDocument xml_document;
+
+ if (!xml_document.ParseMemory(xml.c_str(), xml.size())) {
+ error.SetErrorString("Failed to parse memory map xml");
+ return error;
+ }
+
+ XMLNode map_node = xml_document.GetRootElement("memory-map");
+ if (!map_node) {
+ error.SetErrorString("Invalid root node in memory map xml");
+ return error;
+ }
+
+ m_qXfer_memory_map.clear();
+
+ map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
+ if (!memory_node.IsElement())
+ return true;
+ if (memory_node.GetName() != "memory")
+ return true;
+ auto type = memory_node.GetAttributeValue("type", "");
+ uint64_t start;
+ uint64_t length;
+ if (!memory_node.GetAttributeValueAsUnsigned("start", start))
+ return true;
+ if (!memory_node.GetAttributeValueAsUnsigned("length", length))
+ return true;
+ MemoryRegionInfo region;
+ region.GetRange().SetRangeBase(start);
+ region.GetRange().SetByteSize(length);
+ if (type == "rom") {
+ region.SetReadable(MemoryRegionInfo::eYes);
+ this->m_qXfer_memory_map.push_back(region);
+ } else if (type == "ram") {
+ region.SetReadable(MemoryRegionInfo::eYes);
+ region.SetWritable(MemoryRegionInfo::eYes);
+ this->m_qXfer_memory_map.push_back(region);
+ } else if (type == "flash") {
+ region.SetFlash(MemoryRegionInfo::eYes);
+ memory_node.ForEachChildElement(
+ [&region](const XMLNode &prop_node) -> bool {
+ if (!prop_node.IsElement())
+ return true;
+ if (prop_node.GetName() != "property")
+ return true;
+ auto propname = prop_node.GetAttributeValue("name", "");
+ if (propname == "blocksize") {
+ uint64_t blocksize;
+ if (prop_node.GetElementTextAsUnsigned(blocksize))
+ region.SetBlocksize(blocksize);
+ }
+ return true;
+ });
+ this->m_qXfer_memory_map.push_back(region);
+ }
+ return true;
+ });
+
+ m_qXfer_memory_map_loaded = true;
+
return error;
}
@@ -1585,13 +1717,13 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
Status error;
llvm::Triple::ArchType atype = arch.GetMachine();
- // we assume watchpoints will happen after running the relevant opcode
- // and we only want to override this behavior if we have explicitly
- // received a qHostInfo telling us otherwise
+ // we assume watchpoints will happen after running the relevant opcode and we
+ // only want to override this behavior if we have explicitly received a
+ // qHostInfo telling us otherwise
if (m_qHostInfo_is_valid != eLazyBoolYes) {
// On targets like MIPS and ppc64le, watchpoint exceptions are always
- // generated before the instruction is executed. The connected target
- // may not support qHostInfo or qWatchpointSupportInfo packets.
+ // generated before the instruction is executed. The connected target may
+ // not support qHostInfo or qWatchpointSupportInfo packets.
if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el ||
atype == llvm::Triple::ppc64le)
@@ -1789,11 +1921,12 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
process_info.GetArchitecture().SetTriple(triple.c_str());
} else if (name.equals("name")) {
StringExtractor extractor(value);
- // The process name from ASCII hex bytes since we can't
- // control the characters in a process name
+ // The process name from ASCII hex bytes since we can't control the
+ // characters in a process name
std::string name;
extractor.GetHexByteString(name);
- process_info.GetExecutableFile().SetFile(name, false);
+ process_info.GetExecutableFile().SetFile(name, false,
+ FileSpec::Style::native);
} else if (name.equals("cputype")) {
value.getAsInteger(0, cpu);
} else if (name.equals("cpusubtype")) {
@@ -2046,8 +2179,8 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses(
}
}
StringExtractorGDBRemote response;
- // Increase timeout as the first qfProcessInfo packet takes a long time
- // on Android. The value of 1min was arrived at empirically.
+ // Increase timeout as the first qfProcessInfo packet takes a long time on
+ // Android. The value of 1min was arrived at empirically.
ScopedTimeout timeout(*this, minutes(1));
if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
PacketResult::Success) {
@@ -2081,8 +2214,8 @@ bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
- // the hex encoded user name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
+ // the hex encoded user name and should make up the entire packet. If
+ // there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString(name) * 2 ==
response.GetStringRef().size())
return true;
@@ -2108,8 +2241,8 @@ bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
- // the hex encoded group name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
+ // the hex encoded group name and should make up the entire packet. If
+ // there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString(name) * 2 ==
response.GetStringRef().size())
return true;
@@ -2335,8 +2468,8 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer(
// Make the GDB server we launch only accept connections from this host
stream.Printf("host:%s;", hostname.c_str());
} else {
- // Make the GDB server we launch accept connections from any host since we
- // can't figure out the hostname
+ // Make the GDB server we launch accept connections from any host since
+ // we can't figure out the hostname
stream.Printf("host:*;");
}
}
@@ -2650,13 +2783,16 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
lldb_private::StreamString stream;
stream.PutCString("qPlatform_shell:");
stream.PutBytesAsRawHex8(command, strlen(command));
stream.PutChar(',');
+ uint32_t timeout_sec = UINT32_MAX;
+ if (timeout) {
+ // TODO: Use chrono version of std::ceil once c++17 is available.
+ timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
+ }
stream.PutHex32(timeout_sec);
if (working_dir) {
std::string path{working_dir.GetPath(false)};
@@ -3125,9 +3261,8 @@ bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
uint32_t save_id) {
// We use the "m_supports_QSaveRegisterState" variable here because the
- // QSaveRegisterState and QRestoreRegisterState packets must both be supported
- // in
- // order to be useful
+ // QSaveRegisterState and QRestoreRegisterState packets must both be
+ // supported in order to be useful
if (m_supports_QSaveRegisterState == eLazyBoolNo)
return false;
@@ -3406,7 +3541,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(
StringExtractor extractor(value);
std::string uuid;
extractor.GetHexByteString(uuid);
- module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2);
+ module_spec.GetUUID().SetFromStringRef(uuid, uuid.size() / 2);
} else if (name == "triple") {
StringExtractor extractor(value);
std::string triple;
@@ -3523,8 +3658,8 @@ GDBRemoteCommunicationClient::GetModulesInfo(
// query the target remote for extended information using the qXfer packet
//
-// example: object='features', annex='target.xml', out=<xml output>
-// return: 'true' on success
+// example: object='features', annex='target.xml', out=<xml output> return:
+// 'true' on success
// 'false' on failure (err set)
bool GDBRemoteCommunicationClient::ReadExtFeature(
const lldb_private::ConstString object,
@@ -3631,10 +3766,9 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
void GDBRemoteCommunicationClient::ServeSymbolLookups(
lldb_private::Process *process) {
- // Set to true once we've resolved a symbol to an address for the remote stub.
- // If we get an 'OK' response after this, the remote stub doesn't need any
- // more
- // symbols and we can stop asking.
+ // Set to true once we've resolved a symbol to an address for the remote
+ // stub. If we get an 'OK' response after this, the remote stub doesn't need
+ // any more symbols and we can stop asking.
bool symbol_response_provided = false;
// Is this the initial qSymbol:: packet?
@@ -3659,8 +3793,8 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
first_qsymbol_query = false;
if (response.IsUnsupportedResponse()) {
- // qSymbol is not supported by the current GDB server we are connected
- // to
+ // qSymbol is not supported by the current GDB server we are
+ // connected to
m_supports_qSymbol = false;
return;
} else {
@@ -3725,10 +3859,8 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
}
}
// This is the normal path where our symbol lookup was successful
- // and we want
- // to send a packet with the new symbol value and see if another
- // lookup needs to be
- // done.
+ // and we want to send a packet with the new symbol value and see
+ // if another lookup needs to be done.
// Change "packet" to contain the requested symbol value and name
packet.Clear();
@@ -3763,8 +3895,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
StructuredData::Array *
GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
if (!m_supported_async_json_packets_is_valid) {
- // Query the server for the array of supported asynchronous JSON
- // packets.
+ // Query the server for the array of supported asynchronous JSON packets.
m_supported_async_json_packets_is_valid = true;
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
@@ -3778,8 +3909,8 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
StructuredData::ParseJSON(response.GetStringRef());
if (m_supported_async_json_packets_sp &&
!m_supported_async_json_packets_sp->GetAsArray()) {
- // We were returned something other than a JSON array. This
- // is invalid. Clear it out.
+ // We were returned something other than a JSON array. This is
+ // invalid. Clear it out.
if (log)
log->Printf("GDBRemoteCommunicationClient::%s(): "
"QSupportedAsyncJSONPackets returned invalid "
@@ -3837,8 +3968,7 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
return error;
}
- // Build command: Configure{type_name}: serialized config
- // data.
+ // Build command: Configure{type_name}: serialized config data.
StreamGDBRemote stream;
stream.PutCString("QConfigure");
stream.PutCString(type_name.AsCString());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index ba67b8246398..cf1d249768d7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -121,6 +121,7 @@ public:
/// response was received.
//------------------------------------------------------------------
int SendEnvironmentPacket(char const *name_equal_value);
+ int SendEnvironment(const Environment &env);
int SendLaunchArchPacket(const char *arch);
@@ -265,7 +266,7 @@ public:
bool GetDefaultThreadId(lldb::tid_t &tid);
- bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+ llvm::VersionTuple GetOSVersion();
bool GetOSBuildString(std::string &s);
@@ -354,6 +355,8 @@ public:
bool GetQXferFeaturesReadSupported();
+ bool GetQXferMemoryMapReadSupported();
+
LazyBool SupportsAllocDeallocMemory() // const
{
// Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -401,8 +404,7 @@ public:
// the process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec); // Timeout in seconds to wait for shell program to
- // finish
+ const Timeout<std::micro> &timeout);
bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low);
@@ -544,6 +546,7 @@ protected:
LazyBool m_supports_qXfer_libraries_read;
LazyBool m_supports_qXfer_libraries_svr4_read;
LazyBool m_supports_qXfer_features_read;
+ LazyBool m_supports_qXfer_memory_map_read;
LazyBool m_supports_augmented_libraries_svr4_read;
LazyBool m_supports_jThreadExtendedInfo;
LazyBool m_supports_jLoadedDynamicLibrariesInfos;
@@ -570,9 +573,7 @@ protected:
ArchSpec m_host_arch;
ArchSpec m_process_arch;
- uint32_t m_os_version_major;
- uint32_t m_os_version_minor;
- uint32_t m_os_version_update;
+ llvm::VersionTuple m_os_version;
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
@@ -587,6 +588,9 @@ protected:
bool m_supported_async_json_packets_is_valid;
lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp;
+ std::vector<MemoryRegionInfo> m_qXfer_memory_map;
+ bool m_qXfer_memory_map_loaded;
+
bool GetCurrentProcessInfo(bool allow_lazy_pid = true);
bool GetGDBServerVersion();
@@ -609,6 +613,11 @@ protected:
llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset);
+ Status LoadQXferMemoryMap();
+
+ Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr,
+ MemoryRegionInfo &region);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 4be92b79fd1a..4fc1fc7a1964 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -19,8 +19,8 @@
// Project includes
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index a35352480040..880caacd6414 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -57,8 +57,8 @@ protected:
bool m_exit_now; // use in asynchronous handling to indicate process should
// exit.
- bool m_send_error_strings; // If the client enables this then
- // we will send error strings as well.
+ bool m_send_error_strings = false; // If the client enables this then
+ // we will send error strings as well.
PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 3cf6b8ac07b2..c5b478378faa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -28,7 +28,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
@@ -36,13 +36,14 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StreamGDBRemote.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/Triple.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#ifdef __ANDROID__
#include "lldb/Host/android/HostInfoAndroid.h"
@@ -218,12 +219,15 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
if (sub != LLDB_INVALID_CPUTYPE)
response.Printf("cpusubtype:%u;", sub);
- if (cpu == ArchSpec::kCore_arm_any) {
+ if (cpu == llvm::MachO::CPU_TYPE_ARM
+ || cpu == llvm::MachO::CPU_TYPE_ARM64) {
// Indicate the OS type.
#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
response.PutCString("ostype:tvos;");
#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
response.PutCString("ostype:watchos;");
+#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
+ response.PutCString("ostype:bridgeos;");
#else
response.PutCString("ostype:ios;");
#endif
@@ -265,19 +269,10 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
break;
}
- uint32_t major = UINT32_MAX;
- uint32_t minor = UINT32_MAX;
- uint32_t update = UINT32_MAX;
- if (HostInfo::GetOSVersion(major, minor, update)) {
- if (major != UINT32_MAX) {
- response.Printf("os_version:%u", major);
- if (minor != UINT32_MAX) {
- response.Printf(".%u", minor);
- if (update != UINT32_MAX)
- response.Printf(".%u", update);
- }
- response.PutChar(';');
- }
+ llvm::VersionTuple version = HostInfo::GetOSVersion();
+ if (!version.empty()) {
+ response.Format("os_version:{0}", version.getAsString());
+ response.PutChar(';');
}
std::string s;
@@ -295,9 +290,9 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
#if defined(__APPLE__)
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
- // For iOS devices, we are connected through a USB Mux so we never pretend
- // to actually have a hostname as far as the remote lldb that is connecting
- // to this lldb-platform is concerned
+ // For iOS devices, we are connected through a USB Mux so we never pretend to
+ // actually have a hostname as far as the remote lldb that is connecting to
+ // this lldb-platform is concerned
response.PutCString("hostname:");
response.PutCStringAsRawHex8("127.0.0.1");
response.PutChar(';');
@@ -357,7 +352,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
StringExtractor extractor(value);
std::string file;
extractor.GetHexByteString(file);
- match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ file, false, FileSpec::Style::native);
} else if (key.equals("name_match")) {
NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
.Case("equals", NameMatch::Equals)
@@ -401,7 +397,7 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
match_info.GetProcessInfo().SetEffectiveGroupID(gid);
} else if (key.equals("all_users")) {
match_info.SetMatchAllUsers(
- Args::StringToBoolean(value, false, &success));
+ OptionArgParser::ToBoolean(value, false, &success));
} else if (key.equals("triple")) {
match_info.GetProcessInfo().GetArchitecture() =
HostInfo::GetAugmentedArchSpec(value);
@@ -415,8 +411,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
}
if (Host::FindProcesses(match_info, m_proc_infos)) {
- // We found something, return the first item by calling the get
- // subsequent process info packet handler...
+ // We found something, return the first item by calling the get subsequent
+ // process info packet handler...
return Handle_qsProcessInfo(packet);
}
return SendErrorResponse(3);
@@ -731,14 +727,13 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
if (packet.GetChar() == ',') {
// FIXME: add timeout to qPlatform_shell packet
// uint32_t timeout = packet.GetHexMaxU32(false, 32);
- uint32_t timeout = 10;
if (packet.GetChar() == ',')
packet.GetHexByteString(working_dir);
int status, signo;
std::string output;
- Status err =
- Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true},
- &status, &signo, &output, timeout);
+ Status err = Host::RunShellCommand(
+ path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output,
+ std::chrono::seconds(10));
StreamGDBRemote response;
if (err.Fail()) {
response.PutCString("F,");
@@ -945,8 +940,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironment(
packet.SetFilePos(::strlen("QEnvironment:"));
const uint32_t bytes_left = packet.GetBytesLeft();
if (bytes_left > 0) {
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(
- llvm::StringRef::withNullAsEmpty(packet.Peek()));
+ m_process_launch_info.GetEnvironment().insert(packet.Peek());
return SendOKResponse();
}
return SendErrorResponse(12);
@@ -960,7 +954,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded(
if (bytes_left > 0) {
std::string str;
packet.GetHexByteString(str);
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(str);
+ m_process_launch_info.GetEnvironment().insert(str);
return SendOKResponse();
}
return SendErrorResponse(12);
@@ -981,11 +975,11 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
- // separated hex encoded argument value list, but we will stay true to the
- // documented version of the 'A' packet here...
+ // The 'A' packet is the most over designed packet ever here with redundant
+ // argument indexes, redundant argument lengths and needed hex encoded
+ // argument string values. Really all that is needed is a comma separated hex
+ // encoded argument value list, but we will stay true to the documented
+ // version of the 'A' packet here...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
int actual_arg_index = 0;
@@ -993,8 +987,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
packet.SetFilePos(1); // Skip the 'A'
bool success = true;
while (success && packet.GetBytesLeft() > 0) {
- // Decode the decimal argument string length. This length is the
- // number of hex nibbles in the argument string value.
+ // Decode the decimal argument string length. This length is the number of
+ // hex nibbles in the argument string value.
const uint32_t arg_len = packet.GetU32(UINT32_MAX);
if (arg_len == UINT32_MAX)
success = false;
@@ -1003,8 +997,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (packet.GetChar() != ',')
success = false;
else {
- // Decode the argument index. We ignore this really because
- // who would really send down the arguments in a random order???
+ // Decode the argument index. We ignore this really because who would
+ // really send down the arguments in a random order???
const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
if (arg_idx == UINT32_MAX)
success = false;
@@ -1013,9 +1007,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (packet.GetChar() != ',')
success = false;
else {
- // Decode the argument string value from hex bytes
- // back into a UTF8 string and make sure the length
- // matches the one supplied in the packet
+ // Decode the argument string value from hex bytes back into a UTF8
+ // string and make sure the length matches the one supplied in the
+ // packet
std::string arg;
if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
(arg_len / 2))
@@ -1029,7 +1023,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (success) {
if (arg_idx == 0)
- m_process_launch_info.GetExecutableFile().SetFile(arg, false);
+ m_process_launch_info.GetExecutableFile().SetFile(
+ arg, false, FileSpec::Style::native);
m_process_launch_info.GetArguments().AppendArgument(arg);
if (log)
log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"",
@@ -1254,8 +1249,8 @@ void GDBRemoteCommunicationServerCommon::
// Nothing.
break;
}
- // In case of MIPS64, pointer size is depend on ELF ABI
- // For N32 the pointer size is 4 and for N64 it is 8
+ // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer
+ // size is 4 and for N64 it is 8
std::string abi = proc_arch.GetTargetABI();
if (!abi.empty())
response.Printf("elf_abi:%s;", abi.c_str());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 32741c2404e2..50392fa38956 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -33,9 +33,9 @@
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
@@ -49,7 +49,7 @@
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -236,16 +236,15 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
m_debugged_process_up = std::move(*process_or);
}
- // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
- // as needed.
- // llgs local-process debugging may specify PTY paths, which will make these
- // file actions non-null
- // process launch -i/e/o will also make these file actions non-null
- // nullptr means that the traffic is expected to flow over gdb-remote protocol
+ // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
+ // needed. llgs local-process debugging may specify PTY paths, which will
+ // make these file actions non-null process launch -i/e/o will also make
+ // these file actions non-null nullptr means that the traffic is expected to
+ // flow over gdb-remote protocol
if (should_forward_stdio) {
// nullptr means it's not redirected to file or pty (in case of LLGS local)
- // at least one of stdio will be transferred pty<->gdb-remote
- // we need to give the pty master handle to this object to read and/or write
+ // at least one of stdio will be transferred pty<->gdb-remote we need to
+ // give the pty master handle to this object to read and/or write
LLDB_LOG(log,
"pid = {0}: setting up stdout/stderr redirection via $O "
"gdb-remote commands",
@@ -291,7 +290,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
// else.
if (m_debugged_process_up &&
m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
- return Status("cannot attach to a process %" PRIu64
+ return Status("cannot attach to process %" PRIu64
" when another process with pid %" PRIu64
" is being debugged.",
pid, m_debugged_process_up->GetID());
@@ -410,8 +409,8 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
- // Expedite all registers in the first register set (i.e. should be GPRs) that
- // are not contained in other registers.
+ // Expedite all registers in the first register set (i.e. should be GPRs)
+ // that are not contained in other registers.
const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
if (!reg_set_p)
return nullptr;
@@ -420,8 +419,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
uint32_t reg_num = *reg_num_p;
#else
// Expedite only a couple of registers until we figure out why sending
- // registers is
- // expensive.
+ // registers is expensive.
static const uint32_t k_expedited_registers[] = {
LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};
@@ -595,8 +593,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
return SendErrorResponse(52);
// FIXME implement register handling for exec'd inferiors.
- // if (tid_stop_info.reason == eStopReasonExec)
- // {
+ // if (tid_stop_info.reason == eStopReasonExec) {
// const bool force = true;
// InitializeRegisters(force);
// }
@@ -633,14 +630,14 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutChar(';');
}
- // If a 'QListThreadsInStopReply' was sent to enable this feature, we
- // will send all thread IDs back in the "threads" key whose value is
- // a list of hex thread IDs separated by commas:
+ // If a 'QListThreadsInStopReply' was sent to enable this feature, we will
+ // send all thread IDs back in the "threads" key whose value is a list of hex
+ // thread IDs separated by commas:
// "threads:10a,10b,10c;"
- // This will save the debugger from having to send a pair of qfThreadInfo
- // and qsThreadInfo packets, but it also might take a lot of room in the
- // stop reply packet, so it must be enabled only on systems where there
- // are no limits on packet lengths.
+ // This will save the debugger from having to send a pair of qfThreadInfo and
+ // qsThreadInfo packets, but it also might take a lot of room in the stop
+ // reply packet, so it must be enabled only on systems where there are no
+ // limits on packet lengths.
if (m_list_threads_in_stop_reply) {
response.PutCString("threads:");
@@ -655,12 +652,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
}
response.PutChar(';');
- // Include JSON info that describes the stop reason for any threads
- // that actually have stop reasons. We use the new "jstopinfo" key
- // whose values is hex ascii JSON that contains the thread IDs
- // thread stop info only for threads that have stop reasons. Only send
- // this if we have more than one thread otherwise this packet has all
- // the info it needs.
+ // Include JSON info that describes the stop reason for any threads that
+ // actually have stop reasons. We use the new "jstopinfo" key whose values
+ // is hex ascii JSON that contains the thread IDs thread stop info only for
+ // threads that have stop reasons. Only send this if we have more than one
+ // thread otherwise this packet has all the info it needs.
if (thread_index > 0) {
const bool threads_with_valid_stop_info_only = true;
JSONArray::SP threads_info_sp = GetJSONThreadsInfo(
@@ -806,8 +802,8 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
__FUNCTION__, process->GetID());
}
- // Close the pipe to the inferior terminal i/o if we launched it
- // and set one up.
+ // Close the pipe to the inferior terminal i/o if we launched it and set one
+ // up.
MaybeCloseInferiorTerminalConnection();
// We are ready to exit the debug monitor.
@@ -823,8 +819,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
if (log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- // Send the stop reason unless this is the stop after the
- // launch or attach.
+ // Send the stop reason unless this is the stop after the launch or attach.
switch (m_inferior_prev_state) {
case eStateLaunching:
case eStateAttaching:
@@ -859,13 +854,11 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
break;
case StateType::eStateStopped:
- // Make sure we get all of the pending stdout/stderr from the inferior
- // and send it to the lldb host before we send the state change
- // notification
+ // Make sure we get all of the pending stdout/stderr from the inferior and
+ // send it to the lldb host before we send the state change notification
SendProcessOutput();
// Then stop the forwarding, so that any late output (see llvm.org/pr25652)
- // does not
- // interfere with our protocol.
+ // does not interfere with our protocol.
StopSTDIOForwarding();
HandleInferiorState_Stopped(process);
break;
@@ -1287,8 +1280,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
(m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
+ // Make sure we set the current thread so g and p packets return the data the
+ // gdb will expect.
lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
SetCurrentThreadID(tid);
@@ -1397,10 +1390,9 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
Status error;
// We have two branches: what to do if a continue thread is specified (in
- // which case we target
- // sending the signal to that thread), or when we don't have a continue thread
- // set (in which
- // case we send a signal to the process).
+ // which case we target sending the signal to that thread), or when we don't
+ // have a continue thread set (in which case we send a signal to the
+ // process).
// TODO discuss with Greg Clayton, make sure this makes sense.
@@ -1639,8 +1631,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateStopped:
case eStateCrashed: {
lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
+ // Make sure we set the current thread so g and p packets return the data
+ // the gdb will expect.
SetCurrentThreadID(tid);
return SendStopReplyPacketForThread(tid);
}
@@ -2043,9 +2035,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
return SendErrorResponse(0x47);
}
- // The dwarf expression are evaluate on host site
- // which may cause register size to change
- // Hence the reg_size may not be same as reg_info->bytes_size
+ // The dwarf expression are evaluate on host site which may cause register
+ // size to change Hence the reg_size may not be same as reg_info->bytes_size
if ((reg_size != reg_info->byte_size) &&
!(reg_info->dynamic_size_dwarf_expr_bytes)) {
return SendIllFormedResponse(packet, "P packet register size is incorrect");
@@ -2376,10 +2367,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Currently only the NativeProcessProtocol knows if it can handle a
- // qMemoryRegionInfoSupported
- // request, but we're not guaranteed to be attached to a process. For now
- // we'll assume the
- // client only asks this when a process is being debugged.
+ // qMemoryRegionInfoSupported request, but we're not guaranteed to be
+ // attached to a process. For now we'll assume the client only asks this
+ // when a process is being debugged.
// Ensure we have a process running; otherwise, we can't figure this out
// since we won't have a NativeProcessProtocol.
@@ -2670,8 +2660,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
}
// We first try to use a continue thread id. If any one or any all set, use
- // the current thread.
- // Bail out if we don't have a thread id.
+ // the current thread. Bail out if we don't have a thread id.
lldb::tid_t tid = GetContinueThreadID();
if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
tid = GetCurrentThreadID();
@@ -2935,7 +2924,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to "
"pid %" PRIu64 ": %s\n",
__FUNCTION__, pid, error.AsCString());
- return SendErrorResponse(0x01);
+ return SendErrorResponse(error);
}
// Notify we attached by sending a stop packet.
@@ -3093,8 +3082,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
std::vector<int> signals;
packet.SetFilePos(strlen("QPassSignals:"));
- // Read sequence of hex signal numbers divided by a semicolon and
- // optionally spaces.
+ // Read sequence of hex signal numbers divided by a semicolon and optionally
+ // spaces.
while (packet.GetBytesLeft() > 0) {
int signal = packet.GetS32(-1, 16);
if (signal < 0)
@@ -3154,8 +3143,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
return nullptr;
// If the client hasn't asked for thread suffix support, there will not be a
- // thread suffix.
- // Use the current thread in that case.
+ // thread suffix. Use the current thread in that case.
if (!m_thread_suffix_supported) {
const lldb::tid_t current_tid = GetCurrentThreadID();
if (current_tid == LLDB_INVALID_THREAD_ID)
@@ -3201,9 +3189,9 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
- // Use whatever the debug process says is the current thread id
- // since the protocol either didn't specify or specified we want
- // any/all threads marked as the current thread.
+ // Use whatever the debug process says is the current thread id since the
+ // protocol either didn't specify or specified we want any/all threads
+ // marked as the current thread.
if (!m_debugged_process_up)
return LLDB_INVALID_THREAD_ID;
return m_debugged_process_up->GetCurrentThreadID();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 04ed9d704e13..26e28a900320 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -14,6 +14,7 @@
// C Includes
// C++ Includes
#include <chrono>
+#include <csignal>
#include <cstring>
#include <mutex>
#include <sstream>
@@ -38,7 +39,7 @@
#include "lldb/Utility/UriParser.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -101,11 +102,11 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
if (port == UINT16_MAX)
port = GetNextAvailablePort();
- // Spawn a new thread to accept the port that gets bound after
- // binding to port 0 (zero).
+ // Spawn a new thread to accept the port that gets bound after binding to
+ // port 0 (zero).
- // ignore the hostname send from the remote end, just use the ip address
- // that we're currently communicating with as the hostname
+ // ignore the hostname send from the remote end, just use the ip address that
+ // we're currently communicating with as the hostname
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
@@ -116,8 +117,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
if (log)
log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
- // Do not run in a new session so that it can not linger after the
- // platform closes.
+ // Do not run in a new session so that it can not linger after the platform
+ // closes.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
debugserver_launch_info.SetMonitorProcessCallback(
std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
@@ -170,8 +171,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
#ifdef _WIN32
return SendErrorResponse(9);
#else
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
+ // Spawn a local debugserver as a platform so we can then attach or launch a
+ // process...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
@@ -259,8 +260,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
- // verify that we know anything about this pid.
- // Scope for locker
+ // verify that we know anything about this pid. Scope for locker
{
std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
@@ -306,8 +306,8 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
return true;
}
- // the launched process still lives. Now try killing it again,
- // this time with an unblockable signal.
+ // the launched process still lives. Now try killing it again, this time
+ // with an unblockable signal.
Host::Kill(pid, SIGKILL);
for (size_t i = 0; i < 10; ++i) {
@@ -321,8 +321,7 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
usleep(10000);
}
- // check one more time after the final usleep
- // Scope for locker
+ // check one more time after the final usleep Scope for locker
{
std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
@@ -389,14 +388,13 @@ GDBRemoteCommunicationServerPlatform::Handle_qC(
StreamString response;
response.Printf("QC%" PRIx64, pid);
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
- // launching another process. In order to launch a process a bunch or
- // packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
- // then need to know when to clear this information. Currently we are
- // selecting the 'qC' packet as that packet which seems to make the most
- // sense.
+ // If we launch a process and this GDB server is acting as a platform, then
+ // we need to clear the process launch state so we can start launching
+ // another process. In order to launch a process a bunch or packets need to
+ // be sent: environment packets, working directory, disable ASLR, and many
+ // more settings. When we launch a process we then need to know when to clear
+ // this information. Currently we are selecting the 'qC' packet as that
+ // packet which seems to make the most sense.
if (pid != LLDB_INVALID_PROCESS_ID) {
m_process_launch_info.Clear();
}
@@ -445,9 +443,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
return Status("%s: no process command line specified to launch",
__FUNCTION__);
- // specify the process monitor if not already set. This should
- // generally be what happens since we need to reap started
- // processes.
+ // specify the process monitor if not already set. This should generally be
+ // what happens since we need to reap started processes.
if (!m_process_launch_info.GetMonitorProcessCallback())
m_process_launch_info.SetMonitorProcessCallback(
std::bind(
@@ -466,8 +463,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
m_process_launch_info.GetProcessID());
- // add to list of spawned processes. On an lldb-gdbserver, we
- // would expect there to be only one.
+ // add to list of spawned processes. On an lldb-gdbserver, we would expect
+ // there to be only one.
const auto pid = m_process_launch_info.GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID) {
// add to spawned pids
@@ -537,7 +534,7 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
if (domainsocket_dir_env != nullptr)
g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
else
- HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
+ g_domainsocket_dir = HostInfo::GetProcessTempDir();
});
return g_domainsocket_dir;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index e418deee01f3..07dab751f4b9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -25,7 +25,7 @@
#include "ThreadGDBRemote.h"
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -39,9 +39,9 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext(
GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
: RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
- // Resize our vector of bools to contain one bool for every register.
- // We will use these boolean values to know when a register value
- // is valid in m_reg_data.
+ // Resize our vector of bools to contain one bool for every register. We will
+ // use these boolean values to know when a register value is valid in
+ // m_reg_data.
m_reg_valid.resize(reg_info.GetNumRegisters());
// Make a heap based buffer that is big enough to store all registers
@@ -119,8 +119,8 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(
if (success) {
SetRegisterIsValid(reg, true);
} else if (data.size() > 0) {
- // Only set register is valid to false if we copied some bytes, else
- // leave it as it was.
+ // Only set register is valid to false if we copied some bytes, else leave
+ // it as it was.
SetRegisterIsValid(reg, false);
}
return success;
@@ -133,11 +133,9 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
return false;
// Early in process startup, we can get a thread that has an invalid byte
- // order
- // because the process hasn't been completely set up yet (see the ctor where
- // the
- // byte order is setfrom the process). If that's the case, we can't set the
- // value here.
+ // order because the process hasn't been completely set up yet (see the ctor
+ // where the byte order is setfrom the process). If that's the case, we
+ // can't set the value here.
if (m_reg_data.GetByteOrder() == eByteOrderInvalid) {
return false;
}
@@ -149,8 +147,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *));
// If our register context and our register info disagree, which should never
- // happen, don't
- // overwrite past the end of the buffer.
+ // happen, don't overwrite past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
@@ -219,8 +216,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
}
if (reg_info->value_regs) {
// Process this composite register request by delegating to the
- // constituent
- // primordial registers.
+ // constituent primordial registers.
// Index of the primordial register.
bool success = true;
@@ -228,8 +224,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
const uint32_t prim_reg = reg_info->value_regs[idx];
if (prim_reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
+ // We have a valid primordial register as our constituent. Grab the
+ // corresponding register info.
const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
if (prim_reg_info == NULL)
success = false;
@@ -242,8 +238,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
if (success) {
// If we reach this point, all primordial register requests have
- // succeeded.
- // Validate this composite register.
+ // succeeded. Validate this composite register.
SetRegisterIsValid(reg_info, true);
}
} else {
@@ -262,16 +257,14 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
reg_info->byte_offset + reg_info->byte_size);
#endif
// If our register context and our register info disagree, which should
- // never happen, don't
- // read past the end of the buffer.
+ // never happen, don't read past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
- // If we aren't extracting into our own buffer (which
- // only happens when this function is called from
- // ReadRegisterValue(uint32_t, Scalar&)) then
- // we transfer bytes from our buffer into the data
- // buffer that was passed in
+ // If we aren't extracting into our own buffer (which only happens when
+ // this function is called from ReadRegisterValue(uint32_t, Scalar&)) then
+ // we transfer bytes from our buffer into the data buffer that was passed
+ // in
data.SetByteOrder(m_reg_data.GetByteOrder());
data.SetData(m_reg_data, reg_info->byte_offset, reg_info->byte_size);
@@ -321,8 +314,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
#endif
// If our register context and our register info disagree, which should never
- // happen, don't
- // overwrite past the end of the buffer.
+ // happen, don't overwrite past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
@@ -358,12 +350,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
bool success = true;
if (reg_info->value_regs) {
- // This register is part of another register. In this case we read the
- // actual
- // register data for any "value_regs", and once all that data is read,
- // we will
- // have enough data in our register context bytes for the value of
- // this register
+ // This register is part of another register. In this case we read
+ // the actual register data for any "value_regs", and once all that
+ // data is read, we will have enough data in our register context
+ // bytes for the value of this register
// Invalidate this composite register first.
@@ -371,8 +361,8 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
const uint32_t reg = reg_info->value_regs[idx];
if (reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
+ // We have a valid primordial register as our constituent. Grab the
+ // corresponding register info.
const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
if (value_reg_info == NULL)
success = false;
@@ -385,8 +375,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
}
// Check if writing this register will invalidate any other register
- // values?
- // If so, invalidate them
+ // values? If so, invalidate them
if (reg_info->invalidate_regs) {
for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
reg != LLDB_INVALID_REGNUM;
@@ -548,26 +537,22 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
return true;
uint32_t num_restored = 0;
- // We need to manually go through all of the registers and
- // restore them manually
+ // We need to manually go through all of the registers and restore them
+ // manually
DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(),
m_reg_data.GetAddressByteSize());
const RegisterInfo *reg_info;
- // The g packet contents may either include the slice registers (registers
- // defined in
- // terms of other registers, e.g. eax is a subset of rax) or not. The
- // slice registers
- // should NOT be in the g packet, but some implementations may incorrectly
- // include them.
+ // The g packet contents may either include the slice registers
+ // (registers defined in terms of other registers, e.g. eax is a subset
+ // of rax) or not. The slice registers should NOT be in the g packet,
+ // but some implementations may incorrectly include them.
//
// If the slice registers are included in the packet, we must step over
- // the slice registers
- // when parsing the packet -- relying on the RegisterInfo byte_offset
- // field would be incorrect.
- // If the slice registers are not included, then using the byte_offset
- // values into the
+ // the slice registers when parsing the packet -- relying on the
+ // RegisterInfo byte_offset field would be incorrect. If the slice
+ // registers are not included, then using the byte_offset values into the
// data buffer is the best way to find individual register values.
uint64_t size_including_slice_registers = 0;
@@ -591,21 +576,17 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
} else if (size_not_including_slice_registers ==
restore_data.GetByteSize()) {
// The size of the packet is the same as concatenating all of the
- // registers sequentially,
- // skipping the slice registers
+ // registers sequentially, skipping the slice registers
use_byte_offset_into_buffer = true;
} else if (size_including_slice_registers == restore_data.GetByteSize()) {
// The slice registers are present in the packet (when they shouldn't
- // be).
- // Don't try to use the RegisterInfo byte_offset into the restore_data,
- // it will
- // point to the wrong place.
+ // be). Don't try to use the RegisterInfo byte_offset into the
+ // restore_data, it will point to the wrong place.
use_byte_offset_into_buffer = false;
} else {
// None of our expected sizes match the actual g packet data we're
- // looking at.
- // The most conservative approach here is to use the running total byte
- // offset.
+ // looking at. The most conservative approach here is to use the
+ // running total byte offset.
use_byte_offset_into_buffer = false;
}
@@ -664,11 +645,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
if (reg_info->value_regs) // skip registers that are slices of real
// registers
continue;
- // Skip the fpsr and fpcr floating point status/control register writing
- // to
- // work around a bug in an older version of debugserver that would lead
- // to
- // register context corruption when writing fpsr/fpcr.
+ // Skip the fpsr and fpcr floating point status/control register
+ // writing to work around a bug in an older version of debugserver that
+ // would lead to register context corruption when writing fpsr/fpcr.
if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 ||
strcmp(reg_info->name, "fpcr") == 0)) {
continue;
@@ -752,8 +731,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
static uint32_t g_q14_regs[] = {71, 72, LLDB_INVALID_REGNUM}; // (d28, d29)
static uint32_t g_q15_regs[] = {73, 74, LLDB_INVALID_REGNUM}; // (d30, d31)
- // This is our array of composite registers, with each element coming from the
- // above register mappings.
+ // This is our array of composite registers, with each element coming from
+ // the above register mappings.
static uint32_t *g_composites[] = {
g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs,
g_d6_regs, g_d7_regs, g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs,
@@ -884,21 +863,17 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
if (from_scratch) {
// Calculate the offsets of the registers
// Note that the layout of the "composite" registers (d0-d15 and q0-q15)
- // which comes after the
- // "primordial" registers is important. This enables us to calculate the
- // offset of the composite
- // register by using the offset of its first primordial register. For
- // example, to calculate the
- // offset of q0, use s0's offset.
+ // which comes after the "primordial" registers is important. This enables
+ // us to calculate the offset of the composite register by using the offset
+ // of its first primordial register. For example, to calculate the offset
+ // of q0, use s0's offset.
if (g_register_infos[2].byte_offset == 0) {
uint32_t byte_offset = 0;
for (i = 0; i < num_registers; ++i) {
// For primordial registers, increment the byte_offset by the byte_size
- // to arrive at the
- // byte_offset for the next register. Otherwise, we have a composite
- // register whose
- // offset can be calculated by consulting the offset of its first
- // primordial register.
+ // to arrive at the byte_offset for the next register. Otherwise, we
+ // have a composite register whose offset can be calculated by
+ // consulting the offset of its first primordial register.
if (!g_register_infos[i].value_regs) {
g_register_infos[i].byte_offset = byte_offset;
byte_offset += g_register_infos[i].byte_size;
@@ -933,8 +908,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
// First we need to validate that all registers that we already have match
- // the non composite regs.
- // If so, then we can add the registers, else we need to bail
+ // the non composite regs. If so, then we can add the registers, else we
+ // need to bail
bool match = true;
if (num_dynamic_regs == num_common_regs) {
for (i = 0; match && i < num_dynamic_regs; ++i) {
@@ -970,9 +945,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
// Find a matching primordial register info entry.
if (reg_info && reg_info->name &&
::strcasecmp(reg_info->name, reg_name) == 0) {
- // The name matches the existing primordial entry.
- // Find and assign the offset, and then add this composite
- // register entry.
+ // The name matches the existing primordial entry. Find and
+ // assign the offset, and then add this composite register entry.
g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
name.SetCString(g_comp_register_infos[i].name);
AddRegister(g_comp_register_infos[i], name, alt_name,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 55b1950d678b..13ef8e9503f3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -24,6 +24,7 @@
// C++ Includes
#include <algorithm>
+#include <csignal>
#include <map>
#include <mutex>
#include <sstream>
@@ -46,11 +47,11 @@
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/XML.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -59,10 +60,12 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StreamString.h"
@@ -79,8 +82,8 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Host.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Threading.h"
@@ -93,11 +96,11 @@ using namespace lldb_private::process_gdb_remote;
namespace lldb {
// Provide a function that can easily dump the packet history if we know a
-// ProcessGDBRemote * value (which we can get from logs or from debugging).
-// We need the function in the lldb namespace so it makes it into the final
+// ProcessGDBRemote * value (which we can get from logs or from debugging). We
+// need the function in the lldb namespace so it makes it into the final
// executable since the LLDB shared library only exports stuff in the lldb
-// namespace. This allows you to attach with a debugger and call this
-// function and get the packet history dumped to a file.
+// namespace. This allows you to attach with a debugger and call this function
+// and get the packet history dumped to a file.
void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
StreamFile strm;
Status error(strm.GetFile().Open(path, File::eOpenOptionWrite |
@@ -160,8 +163,8 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
} // anonymous namespace end
// TODO Randomly assigning a port is unsafe. We should get an unused
-// ephemeral port from the kernel and make sure we reserve it before passing
-// it to debugserver.
+// ephemeral port from the kernel and make sure we reserve it before passing it
+// to debugserver.
#if defined(__APPLE__)
#define LOW_PORT (IPPORT_RESERVED)
@@ -235,8 +238,8 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
}
return exe_module->GetFileSpec().Exists();
}
- // However, if there is no executable module, we return true since we might be
- // preparing to attach.
+ // However, if there is no executable module, we return true since we might
+ // be preparing to attach.
return true;
}
@@ -258,7 +261,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_addr_to_mmap_size(), m_thread_create_bp_sp(),
m_waiting_for_attach(false), m_destroy_tried_resuming(false),
m_command_sp(), m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID) {
+ m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false),
+ m_erased_flash_ranges() {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
"async thread should exit");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
@@ -301,17 +305,16 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
ProcessGDBRemote::~ProcessGDBRemote() {
// m_mach_process.UnregisterNotificationCallbacks (this);
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
- // The general Finalize is going to try to destroy the process and that SHOULD
- // shut down the async thread. However, if we don't kill it it will get
- // stranded and
- // its connection will go away so when it wakes up it will crash. So kill it
- // for sure here.
+ // The general Finalize is going to try to destroy the process and that
+ // SHOULD shut down the async thread. However, if we don't kill it it will
+ // get stranded and its connection will go away so when it wakes up it will
+ // crash. So kill it for sure here.
StopAsyncThread();
KillDebugserverProcess();
}
@@ -370,8 +373,7 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition(
}
// If the remote stub didn't give us eh_frame or DWARF register numbers for a
-// register,
-// see if the ABI can provide them.
+// register, see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
ConstString reg_name, ABISP abi_sp) {
@@ -424,9 +426,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
m_register_info.Clear();
- // Check if qHostInfo specified a specific packet timeout for this connection.
- // If so then lets update our setting so the user knows what the timeout is
- // and can see it.
+ // Check if qHostInfo specified a specific packet timeout for this
+ // connection. If so then lets update our setting so the user knows what the
+ // timeout is and can see it.
const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
if (host_packet_timeout > std::chrono::seconds(0)) {
GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout.count());
@@ -533,7 +535,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
reg_info.encoding = encoding;
} else if (name.equals("format")) {
Format format = eFormatInvalid;
- if (Args::StringToFormat(value.str().c_str(), format, NULL)
+ if (OptionArgParser::ToFormat(value.str().c_str(), format, NULL)
.Success())
reg_info.format = format;
else {
@@ -598,10 +600,8 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
}
// We have to make a temporary ABI here, and not use the GetABI because
- // this code
- // gets called in DidAttach, when the target architecture (and
- // consequently the ABI we'll get from
- // the process) may be wrong.
+ // this code gets called in DidAttach, when the target architecture
+ // (and consequently the ABI we'll get from the process) may be wrong.
ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);
AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
@@ -622,9 +622,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
// We didn't get anything if the accumulated reg_num is zero. See if we are
// debugging ARM and fill with a hard coded register set until we can get an
- // updated debugserver down on the devices.
- // On the other hand, if the accumulated reg_num is positive, see if we can
- // add composite registers to the existing primordial ones.
+ // updated debugserver down on the devices. On the other hand, if the
+ // accumulated reg_num is positive, see if we can add composite registers to
+ // the existing primordial ones.
bool from_scratch = (m_register_info.GetNumRegisters() == 0);
if (!target_arch.IsValid()) {
@@ -671,9 +671,8 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
if (pid == LLDB_INVALID_PROCESS_ID) {
- // We don't have a valid process ID, so note that we are connected
- // and could now request to launch or attach, or get remote process
- // listings...
+ // We don't have a valid process ID, so note that we are connected and
+ // could now request to launch or attach, or get remote process listings...
SetPrivateState(eStateConnected);
} else {
// We have a valid process
@@ -723,7 +722,8 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
if (error.Success() && !GetTarget().GetArchitecture().IsValid() &&
m_gdb_comm.GetHostArchitecture().IsValid()) {
- // Prefer the *process'* architecture over that of the *host*, if available.
+ // Prefer the *process'* architecture over that of the *host*, if
+ // available.
if (m_gdb_comm.GetProcessArchitecture().IsValid())
GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
else
@@ -802,8 +802,8 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
if (stdin_file_spec || disable_stdio) {
- // the inferior will be reading stdin from the specified file
- // or stdio is completely disabled
+ // the inferior will be reading stdin from the specified file or stdio is
+ // completely disabled
m_stdin_forward = false;
} else {
m_stdin_forward = true;
@@ -826,11 +826,14 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
if (disable_stdio) {
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
- stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
if (!stdout_file_spec)
- stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
if (!stderr_file_spec)
- stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
} else if (platform_sp && platform_sp->IsHost()) {
// If the debugserver is local and we aren't disabling STDIO, lets use
// a pseudo terminal to instead of relying on the 'O' packets for stdio
@@ -890,16 +893,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
}
// Send the environment and the program + arguments after we connect
- const Args &environment = launch_info.GetEnvironmentEntries();
- if (environment.GetArgumentCount()) {
- size_t num_environment_entries = environment.GetArgumentCount();
- for (size_t i = 0; i < num_environment_entries; ++i) {
- const char *env_entry = environment.GetArgumentAtIndex(i);
- if (env_entry == NULL ||
- m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
- break;
- }
- }
+ m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());
{
// Scope for the scoped timeout object
@@ -1006,16 +1000,15 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
return error;
}
- // Start the communications read thread so all incoming data can be
- // parsed into packets and queued as they arrive.
+ // Start the communications read thread so all incoming data can be parsed
+ // into packets and queued as they arrive.
if (GetTarget().GetNonStopModeEnabled())
m_gdb_comm.StartReadThread();
- // We always seem to be able to open a connection to a local port
- // so we need to make sure we can then send data to it. If we can't
- // then we aren't actually connected to anything, so try and do the
- // handshake with the remote GDB server and make sure that goes
- // alright.
+ // We always seem to be able to open a connection to a local port so we need
+ // to make sure we can then send data to it. If we can't then we aren't
+ // actually connected to anything, so try and do the handshake with the
+ // remote GDB server and make sure that goes alright.
if (!m_gdb_comm.HandshakeWithServer(&error)) {
m_gdb_comm.Disconnect();
if (error.Success())
@@ -1057,9 +1050,9 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
// See if the GDB server supports the qHostInfo information
- // See if the GDB server supports the qProcessInfo packet, if so
- // prefer that over the Host information as it will be more specific
- // to our process.
+ // See if the GDB server supports the qProcessInfo packet, if so prefer
+ // that over the Host information as it will be more specific to our
+ // process.
const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
if (remote_process_arch.IsValid()) {
@@ -1104,9 +1097,8 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
// architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared
- // libraries
- // it has, so we really need to take the remote host architecture as our
- // defacto architecture in this case.
+ // libraries it has, so we really need to take the remote host
+ // architecture as our defacto architecture in this case.
if ((process_arch.GetMachine() == llvm::Triple::arm ||
process_arch.GetMachine() == llvm::Triple::thumb) &&
@@ -1152,14 +1144,14 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
? target_arch.GetTriple().getTriple().c_str()
: "<null>");
} else {
- // The target doesn't have a valid architecture yet, set it from
- // the architecture we got from the remote GDB server
+ // The target doesn't have a valid architecture yet, set it from the
+ // architecture we got from the remote GDB server
GetTarget().SetArchitecture(process_arch);
}
}
- // Find out which StructuredDataPlugins are supported by the
- // debug monitor. These plugins transmit data over async $J packets.
+ // Find out which StructuredDataPlugins are supported by the debug monitor.
+ // These plugins transmit data over async $J packets.
auto supported_packets_array =
m_gdb_comm.GetSupportedStructuredDataPlugins();
if (supported_packets_array)
@@ -1367,9 +1359,9 @@ Status ProcessGDBRemote::DoResume() {
continue_packet_error = true;
if (continue_packet_error) {
- // Either no vCont support, or we tried to use part of the vCont
- // packet that wasn't supported by the remote GDB server.
- // We need to try and make a simple packet that can do our continue
+ // Either no vCont support, or we tried to use part of the vCont packet
+ // that wasn't supported by the remote GDB server. We need to try and
+ // make a simple packet that can do our continue
const size_t num_continue_c_tids = m_continue_c_tids.size();
const size_t num_continue_C_tids = m_continue_C_tids.size();
const size_t num_continue_s_tids = m_continue_s_tids.size();
@@ -1396,11 +1388,10 @@ Status ProcessGDBRemote::DoResume() {
const int continue_signo = m_continue_C_tids.front().second;
// Only one thread is continuing
if (num_continue_C_tids > 1) {
- // More that one thread with a signal, yet we don't have
- // vCont support and we are being asked to resume each
- // thread with a signal, we need to make sure they are
- // all the same signal, or we can't issue the continue
- // accurately with the current support...
+ // More that one thread with a signal, yet we don't have vCont
+ // support and we are being asked to resume each thread with a
+ // signal, we need to make sure they are all the same signal, or we
+ // can't issue the continue accurately with the current support...
if (num_continue_C_tids > 1) {
continue_packet_error = false;
for (size_t i = 1; i < m_continue_C_tids.size(); ++i) {
@@ -1534,7 +1525,6 @@ void ProcessGDBRemote::ClearThreadIDList() {
size_t
ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
m_thread_ids.clear();
- m_thread_pcs.clear();
size_t comma_pos;
lldb::tid_t tid;
while ((comma_pos = value.find(',')) != std::string::npos) {
@@ -1677,9 +1667,8 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
}
}
- // Whatever that is left in old_thread_list_copy are not
- // present in new_thread_list. Remove non-existent threads from internal id
- // table.
+ // Whatever that is left in old_thread_list_copy are not present in
+ // new_thread_list. Remove non-existent threads from internal id table.
size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
for (size_t i = 0; i < old_num_thread_ids; i++) {
ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
@@ -1740,12 +1729,11 @@ bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
return true;
// See if we got thread stop info for any threads valid stop info reasons
- // threads
- // via the "jstopinfo" packet stop reply packet key/value pair?
+ // threads via the "jstopinfo" packet stop reply packet key/value pair?
if (m_jstopinfo_sp) {
// If we have "jstopinfo" then we have stop descriptions for all threads
- // that have stop reasons, and if there is no entry for a thread, then
- // it has no stop reason.
+ // that have stop reasons, and if there is no entry for a thread, then it
+ // has no stop reason.
thread->GetRegisterContext()->InvalidateIfNeeded(true);
if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
thread->SetStopInfo(StopInfoSP());
@@ -1773,9 +1761,8 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (tid != LLDB_INVALID_THREAD_ID) {
// Scope for "locker" below
{
- // m_thread_list_real does have its own mutex, but we need to
- // hold onto the mutex between the call to
- // m_thread_list_real.FindThreadByID(...)
+ // m_thread_list_real does have its own mutex, but we need to hold onto
+ // the mutex between the call to m_thread_list_real.FindThreadByID(...)
// and the m_thread_list_real.AddThread(...) so it doesn't change on us
std::lock_guard<std::recursive_mutex> guard(
m_thread_list_real.GetMutex());
@@ -1829,10 +1816,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (!thread_sp->StopInfoIsUpToDate()) {
thread_sp->SetStopInfo(StopInfoSP());
// If there's a memory thread backed by this thread, we need to use it
- // to calcualte StopInfo.
- ThreadSP memory_thread_sp =
- m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
- if (memory_thread_sp)
+ // to calculate StopInfo.
+ if (ThreadSP memory_thread_sp =
+ m_thread_list.GetBackingThread(thread_sp))
thread_sp = memory_thread_sp;
if (exc_type != 0) {
@@ -1854,9 +1840,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
->GetBreakpointSiteList()
.FindByAddress(pc);
- // If the current pc is a breakpoint site then the StopInfo should
- // be set to Breakpoint
- // Otherwise, it will be set to Trace.
+ // If the current pc is a breakpoint site then the StopInfo
+ // should be set to Breakpoint Otherwise, it will be set to
+ // Trace.
if (bp_site_sp &&
bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
@@ -1873,11 +1859,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
.FindByAddress(pc);
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the
- // hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices
- // that there's a breakpoint under the pc.
+ // hit, but if it is for another thread, we can just report no
+ // reason. We don't need to worry about stepping over the
+ // breakpoint here, that will be taken care of when the thread
+ // resumes and notices that there's a breakpoint under the pc.
handled = true;
if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
@@ -1939,13 +1924,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
pc);
// If the current pc is a breakpoint site then the StopInfo should
- // be set to Breakpoint
- // even though the remote stub did not set it as such. This can
- // happen when
- // the thread is involuntarily interrupted (e.g. due to stops on
- // other
- // threads) just as it is about to execute the breakpoint
- // instruction.
+ // be set to Breakpoint even though the remote stub did not set it
+ // as such. This can happen when the thread is involuntarily
+ // interrupted (e.g. due to stops on other threads) just as it is
+ // about to execute the breakpoint instruction.
if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
@@ -1967,11 +1949,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the
- // hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices
- // that there's a breakpoint under the pc.
+ // hit, but if it is for another thread, we can just report no
+ // reason. We don't need to worry about stepping over the
+ // breakpoint here, that will be taken care of when the thread
+ // resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
if (m_breakpoint_pc_offset != 0)
thread_sp->GetRegisterContext()->SetPC(pc);
@@ -1984,8 +1965,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
}
} else {
// If we were stepping then assume the stop was the result of
- // the trace. If we were
- // not stepping then report the SIGTRAP.
+ // the trace. If we were not stepping then report the SIGTRAP.
// FIXME: We are still missing the case where we single step
// over a trap instruction.
if (thread_sp->GetTemporaryResumeState() == eStateStepping)
@@ -2180,15 +2160,15 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
switch (stop_type) {
case 'T':
case 'S': {
- // This is a bit of a hack, but is is required. If we did exec, we
- // need to clear our thread lists and also know to rebuild our dynamic
- // register info before we lookup and threads and populate the expedited
- // register values so we need to know this right away so we can cleanup
- // and update our registers.
+ // This is a bit of a hack, but is is required. If we did exec, we need to
+ // clear our thread lists and also know to rebuild our dynamic register
+ // info before we lookup and threads and populate the expedited register
+ // values so we need to know this right away so we can cleanup and update
+ // our registers.
const uint32_t stop_id = GetStopID();
if (stop_id == 0) {
- // Our first stop, make sure we have a process ID, and also make
- // sure we know about our registers
+ // Our first stop, make sure we have a process ID, and also make sure we
+ // know about our registers
if (GetID() == LLDB_INVALID_PROCESS_ID) {
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
@@ -2234,8 +2214,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
m_thread_ids.clear();
// A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
+ // process that includes the thread for this stop reply packet
lldb::tid_t tid;
while (!value.empty()) {
llvm::StringRef tid_str;
@@ -2247,8 +2226,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
} else if (key.compare("thread-pcs") == 0) {
m_thread_pcs.clear();
// A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
+ // process that includes the thread for this stop reply packet
lldb::addr_t pc;
while (!value.empty()) {
llvm::StringRef pc_str;
@@ -2300,13 +2278,10 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
desc_extractor.GetHexByteString(description);
} else if (key.compare("memory") == 0) {
// Expedited memory. GDB servers can choose to send back expedited
- // memory
- // that can populate the L1 memory cache in the process so that things
- // like
- // the frame pointer backchain can be expedited. This will help stack
- // backtracing be more efficient by not having to send as many memory
- // read
- // requests down the remote GDB server.
+ // memory that can populate the L1 memory cache in the process so that
+ // things like the frame pointer backchain can be expedited. This will
+ // help stack backtracing be more efficient by not having to send as
+ // many memory read requests down the remote GDB server.
// Key/value pair format: memory:<addr>=<bytes>;
// <addr> is a number whose base will be interpreted by the prefix:
@@ -2358,7 +2333,8 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
if (tid == LLDB_INVALID_THREAD_ID) {
// A thread id may be invalid if the response is old style 'S' packet
// which does not provide the
- // thread information. So update the thread list and choose the first one.
+ // thread information. So update the thread list and choose the first
+ // one.
UpdateThreadIDList();
if (!m_thread_ids.empty()) {
@@ -2391,9 +2367,9 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_thread_ids.clear();
m_thread_pcs.clear();
- // Set the thread stop info. It might have a "threads" key whose value is
- // a list of all thread IDs in the current process, so m_thread_ids might
- // get set.
+ // Set the thread stop info. It might have a "threads" key whose value is a
+ // list of all thread IDs in the current process, so m_thread_ids might get
+ // set.
// Scope for the lock
{
@@ -2424,8 +2400,8 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_initial_tid = LLDB_INVALID_THREAD_ID;
}
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list_real.RefreshStateAfterStop();
}
@@ -2433,8 +2409,8 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) {
Status error;
if (m_public_state.GetValue() == eStateAttaching) {
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
+ // We are being asked to halt during an attach. We need to just close our
+ // file handle and debugserver will go away, and we can be done...
m_gdb_comm.Disconnect();
} else
caused_stop = m_gdb_comm.Interrupt();
@@ -2478,31 +2454,24 @@ Status ProcessGDBRemote::DoDestroy() {
#ifdef LLDB_ENABLE_ALL // XXX Currently no iOS target support on FreeBSD
// There is a bug in older iOS debugservers where they don't shut down the
- // process
- // they are debugging properly. If the process is sitting at a breakpoint or
- // an exception,
- // this can cause problems with restarting. So we check to see if any of our
- // threads are stopped
- // at a breakpoint, and if so we remove all the breakpoints, resume the
- // process, and THEN
- // destroy it again.
+ // process they are debugging properly. If the process is sitting at a
+ // breakpoint or an exception, this can cause problems with restarting. So
+ // we check to see if any of our threads are stopped at a breakpoint, and if
+ // so we remove all the breakpoints, resume the process, and THEN destroy it
+ // again.
//
// Note, we don't have a good way to test the version of debugserver, but I
- // happen to know that
- // the set of all the iOS debugservers which don't support
- // GetThreadSuffixSupported() and that of
- // the debugservers with this bug are equal. There really should be a better
- // way to test this!
+ // happen to know that the set of all the iOS debugservers which don't
+ // support GetThreadSuffixSupported() and that of the debugservers with this
+ // bug are equal. There really should be a better way to test this!
//
// We also use m_destroy_tried_resuming to make sure we only do this once, if
- // we resume and then halt and
- // get called here to destroy again and we're still at a breakpoint or
- // exception, then we should
- // just do the straight-forward kill.
+ // we resume and then halt and get called here to destroy again and we're
+ // still at a breakpoint or exception, then we should just do the straight-
+ // forward kill.
//
// And of course, if we weren't able to stop the process by the time we get
- // here, it isn't
- // necessary (or helpful) to do any of this.
+ // here, it isn't necessary (or helpful) to do any of this.
if (!m_gdb_comm.GetThreadSuffixSupported() &&
m_public_state.GetValue() != eStateRunning) {
@@ -2517,9 +2486,8 @@ Status ProcessGDBRemote::DoDestroy() {
"destroy once already, not doing it again.");
} else {
// At present, the plans are discarded and the breakpoints disabled
- // Process::Destroy,
- // but we really need it to happen here and it doesn't matter if we do
- // it twice.
+ // Process::Destroy, but we really need it to happen here and it
+ // doesn't matter if we do it twice.
m_thread_list.DiscardThreadPlans();
DisableAllBreakpointSites();
@@ -2556,12 +2524,11 @@ Status ProcessGDBRemote::DoDestroy() {
m_destroy_tried_resuming = true;
// If we are going to run again before killing, it would be good to
- // suspend all the threads
- // before resuming so they won't get into more trouble. Sadly, for
- // the threads stopped with
- // the breakpoint or exception, the exception doesn't get cleared if
- // it is suspended, so we do
- // have to run the risk of letting those threads proceed a bit.
+ // suspend all the threads before resuming so they won't get into
+ // more trouble. Sadly, for the threads stopped with the breakpoint
+ // or exception, the exception doesn't get cleared if it is
+ // suspended, so we do have to run the risk of letting those threads
+ // proceed a bit.
{
std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
@@ -2609,17 +2576,14 @@ Status ProcessGDBRemote::DoDestroy() {
if (packet_cmd == 'W' || packet_cmd == 'X') {
#if defined(__APPLE__)
// For Native processes on Mac OS X, we launch through the Host
- // Platform, then hand the process off
- // to debugserver, which becomes the parent process through
- // "PT_ATTACH". Then when we go to kill
- // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we
- // call waitpid which returns
- // with no error and the correct status. But amusingly enough that
- // doesn't seem to actually reap
+ // Platform, then hand the process off to debugserver, which becomes
+ // the parent process through "PT_ATTACH". Then when we go to kill
+ // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then
+ // we call waitpid which returns with no error and the correct
+ // status. But amusingly enough that doesn't seem to actually reap
// the process, but instead it is left around as a Zombie. Probably
- // the kernel is in the process of
- // switching ownership back to lldb which was the original parent, and
- // gets confused in the handoff.
+ // the kernel is in the process of switching ownership back to lldb
+ // which was the original parent, and gets confused in the handoff.
// Anyway, so call waitpid here to finally reap it.
PlatformSP platform_sp(GetTarget().GetPlatform());
if (platform_sp && platform_sp->IsHost()) {
@@ -2691,9 +2655,8 @@ void ProcessGDBRemote::SetLastStopPacket(
if (GetTarget().GetNonStopModeEnabled() == false)
m_stop_packet_stack.clear();
- // Add this stop packet to the stop packet stack
- // This stack will get popped and examined when we switch to the
- // Stopped state
+ // Add this stop packet to the stop packet stack This stack will get popped
+ // and examined when we switch to the Stopped state
m_stop_packet_stack.push_back(response);
}
}
@@ -2725,12 +2688,11 @@ addr_t ProcessGDBRemote::GetImageInfoAddress() {
}
void ProcessGDBRemote::WillPublicStop() {
- // See if the GDB remote client supports the JSON threads info.
- // If so, we gather stop info for all threads, expedited registers,
- // expedited memory, runtime queue information (iOS and MacOSX only),
- // and more. Expediting memory will help stack backtracing be much
- // faster. Expediting registers will make sure we don't have to read
- // the thread registers for GPRs.
+ // See if the GDB remote client supports the JSON threads info. If so, we
+ // gather stop info for all threads, expedited registers, expedited memory,
+ // runtime queue information (iOS and MacOSX only), and more. Expediting
+ // memory will help stack backtracing be much faster. Expediting registers
+ // will make sure we don't have to read the thread registers for GPRs.
m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
if (m_jthreadsinfo_sp) {
@@ -2780,14 +2742,13 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
error.Clear();
if (binary_memory_read) {
// The lower level GDBRemoteCommunication packet receive layer has
- // already de-quoted any
- // 0x7d character escaping that was present in the packet
+ // already de-quoted any 0x7d character escaping that was present in
+ // the packet
size_t data_received_size = response.GetBytesLeft();
if (data_received_size > size) {
// Don't write past the end of BUF if the remote debug server gave us
- // too
- // much data for some reason.
+ // too much data for some reason.
data_received_size = size;
}
memcpy(buf, response.GetStringRef().data(), data_received_size);
@@ -2811,6 +2772,145 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
return 0;
}
+Status ProcessGDBRemote::WriteObjectFile(
+ std::vector<ObjectFile::LoadableData> entries) {
+ Status error;
+ // Sort the entries by address because some writes, like those to flash
+ // memory, must happen in order of increasing address.
+ std::stable_sort(
+ std::begin(entries), std::end(entries),
+ [](const ObjectFile::LoadableData a, const ObjectFile::LoadableData b) {
+ return a.Dest < b.Dest;
+ });
+ m_allow_flash_writes = true;
+ error = Process::WriteObjectFile(entries);
+ if (error.Success())
+ error = FlashDone();
+ else
+ // Even though some of the writing failed, try to send a flash done if some
+ // of the writing succeeded so the flash state is reset to normal, but
+ // don't stomp on the error status that was set in the write failure since
+ // that's the one we want to report back.
+ FlashDone();
+ m_allow_flash_writes = false;
+ return error;
+}
+
+bool ProcessGDBRemote::HasErased(FlashRange range) {
+ auto size = m_erased_flash_ranges.GetSize();
+ for (size_t i = 0; i < size; ++i)
+ if (m_erased_flash_ranges.GetEntryAtIndex(i)->Contains(range))
+ return true;
+ return false;
+}
+
+Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) {
+ Status status;
+
+ MemoryRegionInfo region;
+ status = GetMemoryRegionInfo(addr, region);
+ if (!status.Success())
+ return status;
+
+ // The gdb spec doesn't say if erasures are allowed across multiple regions,
+ // but we'll disallow it to be safe and to keep the logic simple by worring
+ // about only one region's block size. DoMemoryWrite is this function's
+ // primary user, and it can easily keep writes within a single memory region
+ if (addr + size > region.GetRange().GetRangeEnd()) {
+ status.SetErrorString("Unable to erase flash in multiple regions");
+ return status;
+ }
+
+ uint64_t blocksize = region.GetBlocksize();
+ if (blocksize == 0) {
+ status.SetErrorString("Unable to erase flash because blocksize is 0");
+ return status;
+ }
+
+ // Erasures can only be done on block boundary adresses, so round down addr
+ // and round up size
+ lldb::addr_t block_start_addr = addr - (addr % blocksize);
+ size += (addr - block_start_addr);
+ if ((size % blocksize) != 0)
+ size += (blocksize - size % blocksize);
+
+ FlashRange range(block_start_addr, size);
+
+ if (HasErased(range))
+ return status;
+
+ // We haven't erased the entire range, but we may have erased part of it.
+ // (e.g., block A is already erased and range starts in A and ends in B). So,
+ // adjust range if necessary to exclude already erased blocks.
+ if (!m_erased_flash_ranges.IsEmpty()) {
+ // Assuming that writes and erasures are done in increasing addr order,
+ // because that is a requirement of the vFlashWrite command. Therefore, we
+ // only need to look at the last range in the list for overlap.
+ const auto &last_range = *m_erased_flash_ranges.Back();
+ if (range.GetRangeBase() < last_range.GetRangeEnd()) {
+ auto overlap = last_range.GetRangeEnd() - range.GetRangeBase();
+ // overlap will be less than range.GetByteSize() or else HasErased()
+ // would have been true
+ range.SetByteSize(range.GetByteSize() - overlap);
+ range.SetRangeBase(range.GetRangeBase() + overlap);
+ }
+ }
+
+ StreamString packet;
+ packet.Printf("vFlashErase:%" PRIx64 ",%" PRIx64, range.GetRangeBase(),
+ (uint64_t)range.GetByteSize());
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_erased_flash_ranges.Insert(range, true);
+ } else {
+ if (response.IsErrorResponse())
+ status.SetErrorStringWithFormat("flash erase failed for 0x%" PRIx64,
+ addr);
+ else if (response.IsUnsupportedResponse())
+ status.SetErrorStringWithFormat("GDB server does not support flashing");
+ else
+ status.SetErrorStringWithFormat(
+ "unexpected response to GDB server flash erase packet '%s': '%s'",
+ packet.GetData(), response.GetStringRef().c_str());
+ }
+ } else {
+ status.SetErrorStringWithFormat("failed to send packet: '%s'",
+ packet.GetData());
+ }
+ return status;
+}
+
+Status ProcessGDBRemote::FlashDone() {
+ Status status;
+ // If we haven't erased any blocks, then we must not have written anything
+ // either, so there is no need to actually send a vFlashDone command
+ if (m_erased_flash_ranges.IsEmpty())
+ return status;
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_erased_flash_ranges.Clear();
+ } else {
+ if (response.IsErrorResponse())
+ status.SetErrorStringWithFormat("flash done failed");
+ else if (response.IsUnsupportedResponse())
+ status.SetErrorStringWithFormat("GDB server does not support flashing");
+ else
+ status.SetErrorStringWithFormat(
+ "unexpected response to GDB server flash done packet: '%s'",
+ response.GetStringRef().c_str());
+ }
+ } else {
+ status.SetErrorStringWithFormat("failed to send flash done packet");
+ }
+ return status;
+}
+
size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size_t size, Status &error) {
GetMaxMemorySize();
@@ -2823,10 +2923,33 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size = max_memory_size;
}
- StreamString packet;
- packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
+ StreamGDBRemote packet;
+
+ MemoryRegionInfo region;
+ Status region_status = GetMemoryRegionInfo(addr, region);
+
+ bool is_flash =
+ region_status.Success() && region.GetFlash() == MemoryRegionInfo::eYes;
+
+ if (is_flash) {
+ if (!m_allow_flash_writes) {
+ error.SetErrorString("Writing to flash memory is not allowed");
+ return 0;
+ }
+ // Keep the write within a flash memory region
+ if (addr + size > region.GetRange().GetRangeEnd())
+ size = region.GetRange().GetRangeEnd() - addr;
+ // Flash memory must be erased before it can be written
+ error = FlashErase(addr, size);
+ if (!error.Success())
+ return 0;
+ packet.Printf("vFlashWrite:%" PRIx64 ":", addr);
+ packet.PutEscapedBytes(buf, size);
+ } else {
+ packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ }
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
true) ==
@@ -2922,8 +3045,8 @@ Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {
switch (supported) {
case eLazyBoolCalculate:
- // We should never be deallocating memory without allocating memory
- // first so we should never get eLazyBoolCalculate
+ // We should never be deallocating memory without allocating memory first
+ // so we should never get eLazyBoolCalculate
error.SetErrorString(
"tried to deallocate memory without ever allocating memory");
break;
@@ -2995,18 +3118,14 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
// SupportsGDBStoppointPacket() simply checks a boolean, indicating if this
- // breakpoint type
- // is supported by the remote stub. These are set to true by default, and
- // later set to false
- // only after we receive an unimplemented response when sending a breakpoint
- // packet. This means
- // initially that unless we were specifically instructed to use a hardware
- // breakpoint, LLDB will
- // attempt to set a software breakpoint. HardwareRequired() also queries a
- // boolean variable which
- // indicates if the user specifically asked for hardware breakpoints. If true
- // then we will
- // skip over software breakpoints.
+ // breakpoint type is supported by the remote stub. These are set to true by
+ // default, and later set to false only after we receive an unimplemented
+ // response when sending a breakpoint packet. This means initially that
+ // unless we were specifically instructed to use a hardware breakpoint, LLDB
+ // will attempt to set a software breakpoint. HardwareRequired() also queries
+ // a boolean variable which indicates if the user specifically asked for
+ // hardware breakpoints. If true then we will skip over software
+ // breakpoints.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) &&
(!bp_site->HardwareRequired())) {
// Try to send off a software breakpoint packet ($Z0)
@@ -3019,19 +3138,14 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
return error;
}
- // SendGDBStoppointTypePacket() will return an error if it was unable to set
- // this
- // breakpoint. We need to differentiate between a error specific to placing
- // this breakpoint
- // or if we have learned that this breakpoint type is unsupported. To do
- // this, we
- // must test the support boolean for this breakpoint type to see if it now
- // indicates that
- // this breakpoint type is unsupported. If they are still supported then we
- // should return
+ // SendGDBStoppointTypePacket() will return an error if it was unable to
+ // set this breakpoint. We need to differentiate between a error specific
+ // to placing this breakpoint or if we have learned that this breakpoint
+ // type is unsupported. To do this, we must test the support boolean for
+ // this breakpoint type to see if it now indicates that this breakpoint
+ // type is unsupported. If they are still supported then we should return
// with the error code. If they are now unsupported, then we would like to
- // fall through
- // and try another form of breakpoint.
+ // fall through and try another form of breakpoint.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
if (error_no != UINT8_MAX)
error.SetErrorStringWithFormat(
@@ -3042,21 +3156,18 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
}
// We reach here when software breakpoints have been found to be
- // unsupported. For future
- // calls to set a breakpoint, we will not attempt to set a breakpoint with a
- // type that is
- // known not to be supported.
+ // unsupported. For future calls to set a breakpoint, we will not attempt
+ // to set a breakpoint with a type that is known not to be supported.
if (log)
log->Printf("Software breakpoints are unsupported");
// So we will fall through and try a hardware breakpoint
}
- // The process of setting a hardware breakpoint is much the same as above. We
- // check the
- // supported boolean for this breakpoint type, and if it is thought to be
- // supported then we
- // will try to set this breakpoint with a hardware breakpoint.
+ // The process of setting a hardware breakpoint is much the same as above.
+ // We check the supported boolean for this breakpoint type, and if it is
+ // thought to be supported then we will try to set this breakpoint with a
+ // hardware breakpoint.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
// Try to send off a hardware breakpoint packet ($Z1)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
@@ -3098,8 +3209,8 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
return error;
}
- // As a last resort we want to place a manual breakpoint. An instruction
- // is placed into the process memory using memory write packets.
+ // As a last resort we want to place a manual breakpoint. An instruction is
+ // placed into the process memory using memory write packets.
return EnableSoftwareBreakpoint(bp_site);
}
@@ -3229,10 +3340,9 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) {
log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
watchID, (uint64_t)addr);
- // See also 'class WatchpointSentry' within StopInfo.cpp.
- // This disabling attempt might come from the user-supplied actions, we'll
- // route it in order for
- // the watchpoint object to intelligently process this action.
+ // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling
+ // attempt might come from the user-supplied actions, we'll route it in
+ // order for the watchpoint object to intelligently process this action.
wp->SetEnabled(false, notify);
return error;
}
@@ -3317,8 +3427,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
static FileSpec g_debugserver_file_spec;
ProcessLaunchInfo debugserver_launch_info;
- // Make debugserver run in its own session so signals generated by
- // special terminal key sequences (^C) don't affect debugserver.
+ // Make debugserver run in its own session so signals generated by special
+ // terminal key sequences (^C) don't affect debugserver.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
const std::weak_ptr<ProcessGDBRemote> this_wp =
@@ -3329,27 +3439,22 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
int communication_fd = -1;
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Auto close the sockets we might open up unless everything goes OK. This
- // helps us not leak file descriptors when things go wrong.
- lldb_utility::CleanUp<int, int> our_socket(-1, -1, close);
- lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close);
-
// Use a socketpair on non-Windows systems for security and performance
// reasons.
- {
- int sockets[2]; /* the pair of socket descriptors */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
- error.SetErrorToErrno();
- return error;
- }
-
- our_socket.set(sockets[0]);
- gdb_socket.set(sockets[1]);
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
+ error.SetErrorToErrno();
+ return error;
}
+ int our_socket = sockets[0];
+ int gdb_socket = sockets[1];
+ CleanUp cleanup_our(close, our_socket);
+ CleanUp cleanup_gdb(close, gdb_socket);
+
// Don't let any child processes inherit our communication socket
- SetCloexecFlag(our_socket.get());
- communication_fd = gdb_socket.get();
+ SetCloexecFlag(our_socket);
+ communication_fd = gdb_socket;
#endif
error = m_gdb_comm.StartDebugserverProcess(
@@ -3363,10 +3468,10 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Our process spawned correctly, we can now set our connection to use our
- // end of the socket pair
- m_gdb_comm.SetConnection(
- new ConnectionFileDescriptor(our_socket.release(), true));
+ // Our process spawned correctly, we can now set our connection to use
+ // our end of the socket pair
+ cleanup_our.disable();
+ m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true));
#endif
StartAsyncThread();
}
@@ -3381,9 +3486,9 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
}
if (m_gdb_comm.IsConnected()) {
- // Finish the connection process by doing the handshake without connecting
- // (send NULL URL)
- ConnectToDebugserver("");
+ // Finish the connection process by doing the handshake without
+ // connecting (send NULL URL)
+ error = ConnectToDebugserver("");
} else {
error.SetErrorString("connection failed");
}
@@ -3397,8 +3502,8 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
int signo, // Zero for no signal
int exit_status // Exit value of process if signal is zero
) {
- // "debugserver_pid" argument passed in is the process ID for
- // debugserver that we are tracking...
+ // "debugserver_pid" argument passed in is the process ID for debugserver
+ // that we are tracking...
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
const bool handled = true;
@@ -3414,12 +3519,12 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
return handled;
- // Sleep for a half a second to make sure our inferior process has
- // time to set its exit status before we set it incorrectly when
- // both the debugserver and the inferior process shut down.
+ // Sleep for a half a second to make sure our inferior process has time to
+ // set its exit status before we set it incorrectly when both the debugserver
+ // and the inferior process shut down.
usleep(500000);
- // If our process hasn't yet exited, debugserver might have died.
- // If the process did exit, then we are reaping it.
+ // If our process hasn't yet exited, debugserver might have died. If the
+ // process did exit, then we are reaping it.
const StateType state = process_sp->GetState();
if (state != eStateInvalid && state != eStateUnloaded &&
@@ -3442,8 +3547,8 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
process_sp->SetExitStatus(-1, error_str);
}
- // Debugserver has exited we need to let our ProcessGDBRemote
- // know that it no longer has a debugserver instance
+ // Debugserver has exited we need to let our ProcessGDBRemote know that it no
+ // longer has a debugserver instance
process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
return handled;
}
@@ -3533,10 +3638,9 @@ bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) {
// check for more stop reasons
HandleStopReplySequence();
- // if the process is stopped then we need to fake a resume
- // so that we can stop properly with the new break. This
- // is possible due to SetPrivateState() broadcasting the
- // state change as a side effect.
+ // if the process is stopped then we need to fake a resume so that we can
+ // stop properly with the new break. This is possible due to
+ // SetPrivateState() broadcasting the state change as a side effect.
if (GetPrivateState() == lldb::StateType::eStateStopped) {
SetPrivateState(lldb::StateType::eStateRunning);
}
@@ -3609,12 +3713,11 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
response);
// We need to immediately clear the thread ID list so we are sure
- // to get a valid list of threads.
- // The thread ID list might be contained within the "response", or
- // the stop reply packet that
+ // to get a valid list of threads. The thread ID list might be
+ // contained within the "response", or the stop reply packet that
// caused the stop. So clear it now before we give the stop reply
- // packet to the process
- // using the process->SetLastStopPacket()...
+ // packet to the process using the
+ // process->SetLastStopPacket()...
process->ClearThreadIDList();
switch (stop_state) {
@@ -3651,17 +3754,14 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
// Check to see if we were trying to attach and if we got back
// the "E87" error code from debugserver -- this indicates that
// the process is not debuggable. Return a slightly more
- // helpful
- // error message about why the attach failed.
+ // helpful error message about why the attach failed.
if (::strstr(continue_cstr, "vAttach") != NULL &&
response.GetError() == 0x87) {
process->SetExitStatus(-1, "cannot attach to process due to "
"System Integrity Protection");
- }
- // E01 code from vAttach means that the attach failed
- if (::strstr(continue_cstr, "vAttach") != NULL &&
- response.GetError() == 0x1) {
- process->SetExitStatus(-1, "unable to attach");
+ } else if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetStatus().Fail()) {
+ process->SetExitStatus(-1, response.GetStatus().AsCString());
} else {
process->SetExitStatus(-1, "lost connection");
}
@@ -3773,8 +3873,8 @@ Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOG(log, "Check if need to update ignored signals");
- // QPassSignals package is not supported by the server,
- // there is no way we can ignore any signals on server side.
+ // QPassSignals package is not supported by the server, there is no way we
+ // can ignore any signals on server side.
if (!m_gdb_comm.GetQPassSignalsSupported())
return Status();
@@ -3898,9 +3998,9 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -3970,9 +4070,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -4003,9 +4103,9 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -4030,14 +4130,14 @@ Status ProcessGDBRemote::ConfigureStructuredData(
return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
}
-// Establish the largest memory read/write payloads we should use.
-// If the remote stub has a max packet size, stay under that size.
+// Establish the largest memory read/write payloads we should use. If the
+// remote stub has a max packet size, stay under that size.
//
-// If the remote stub's max packet size is crazy large, use a
-// reasonable largeish default.
+// If the remote stub's max packet size is crazy large, use a reasonable
+// largeish default.
//
-// If the remote stub doesn't advertise a max packet size, use a
-// conservative default.
+// If the remote stub doesn't advertise a max packet size, use a conservative
+// default.
void ProcessGDBRemote::GetMaxMemorySize() {
const uint64_t reasonable_largeish_default = 128 * 1024;
@@ -4049,15 +4149,15 @@ void ProcessGDBRemote::GetMaxMemorySize() {
// Save the stub's claimed maximum packet size
m_remote_stub_max_memory_size = stub_max_size;
- // Even if the stub says it can support ginormous packets,
- // don't exceed our reasonable largeish default packet size.
+ // Even if the stub says it can support ginormous packets, don't exceed
+ // our reasonable largeish default packet size.
if (stub_max_size > reasonable_largeish_default) {
stub_max_size = reasonable_largeish_default;
}
- // Memory packet have other overheads too like Maddr,size:#NN
- // Instead of calculating the bytes taken by size and addr every
- // time, we take a maximum guess here.
+ // Memory packet have other overheads too like Maddr,size:#NN Instead of
+ // calculating the bytes taken by size and addr every time, we take a
+ // maximum guess here.
if (stub_max_size > 70)
stub_max_size -= 32 + 32 + 6;
else {
@@ -4144,13 +4244,8 @@ void ProcessGDBRemote::PrefetchModuleSpecs(
}
}
-bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) {
- if (m_gdb_comm.GetOSVersion(major, minor, update))
- return true;
- // We failed to get the host OS version, defer to the base
- // implementation to correctly invalidate the arguments.
- return Process::GetHostOSVersion(major, minor, update);
+llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() {
+ return m_gdb_comm.GetOSVersion();
}
namespace {
@@ -4241,7 +4336,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
} else if (name == "format") {
format_set = true;
Format format = eFormatInvalid;
- if (Args::StringToFormat(value.data(), format, NULL).Success())
+ if (OptionArgParser::ToFormat(value.data(), format, NULL).Success())
reg_info.format = format;
else if (value == "vector-sint8")
reg_info.format = eFormatVectorOfSInt8;
@@ -4315,8 +4410,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
}
// Only update the register set name if we didn't get a "reg_set"
+ // attribute. "set_name" will be empty if we didn't have a "reg_set"
// attribute.
- // "set_name" will be empty if we didn't have a "reg_set" attribute.
if (!set_name && !gdb_group.empty())
set_name.SetCString(gdb_group.c_str());
@@ -4343,8 +4438,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
} // namespace {}
-// query the target of gdb-remote for extended target information
-// return: 'true' on success
+// query the target of gdb-remote for extended target information return:
+// 'true' on success
// 'false' on failure
bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
// Make sure LLDB has an XML parser it can use first
@@ -4413,15 +4508,27 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
return true; // Keep iterating through all children of the target_node
});
+ // If the target.xml includes an architecture entry like
+ // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi)
+ // <architecture>arm</architecture> (seen from Segger JLink on unspecified arm board)
+ // use that if we don't have anything better.
+ if (!arch_to_use.IsValid() && !target_info.arch.empty()) {
+ if (target_info.arch == "i386:x86-64")
+ {
+ // We don't have any information about vendor or OS.
+ arch_to_use.SetTriple("x86_64--");
+ GetTarget().MergeArchitecture(arch_to_use);
+ }
+ }
+
// Initialize these outside of ParseRegisters, since they should not be
// reset inside each include feature
uint32_t cur_reg_num = 0;
uint32_t reg_offset = 0;
- // Don't use Process::GetABI, this code gets called from DidAttach, and in
- // that context we haven't
- // set the Target's architecture yet, so the ABI is also potentially
- // incorrect.
+ // Don't use Process::GetABI, this code gets called from DidAttach, and
+ // in that context we haven't set the Target's architecture yet, so the
+ // ABI is also potentially incorrect.
ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use);
for (auto &feature_node : feature_nodes) {
ParseRegisters(feature_node, target_info, this->m_register_info,
@@ -4762,8 +4869,8 @@ void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) {
// do anything
Process::ModulesDidLoad(module_list);
- // After loading shared libraries, we can ask our remote GDB server if
- // it needs any symbols.
+ // After loading shared libraries, we can ask our remote GDB server if it
+ // needs any symbols.
m_gdb_comm.ServeSymbolLookups(this);
}
@@ -4821,8 +4928,8 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
has_used_usec = true;
usec_value.getAsInteger(0, curr_used_usec);
} else {
- // We didn't find what we want, it is probably
- // an older version. Bail out.
+ // We didn't find what we want, it is probably an older version. Bail
+ // out.
profileDataExtractor.SetFilePos(input_file_pos);
}
}
@@ -4844,8 +4951,8 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));
if (good_first_time || good_subsequent_time) {
- // We try to avoid doing too many index id reservation,
- // resulting in fast increase of index ids.
+ // We try to avoid doing too many index id reservation, resulting in
+ // fast increase of index ids.
output_stream << name << ":";
int32_t index_id = AssignIndexIDToThread(thread_id);
@@ -4896,7 +5003,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
if (!packet.consume_front(s_async_json_packet_prefix)) {
if (log) {
log->Printf(
- "GDBRemoteCommmunicationClientBase::%s() received $J packet "
+ "GDBRemoteCommunicationClientBase::%s() received $J packet "
"but was not a StructuredData packet: packet starts with "
"%s",
__FUNCTION__,
@@ -4905,8 +5012,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
return StructuredData::ObjectSP();
}
- // This is an asynchronous JSON packet, destined for a
- // StructuredDataPlugin.
+ // This is an asynchronous JSON packet, destined for a StructuredDataPlugin.
StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet);
if (log) {
if (json_sp) {
@@ -5141,8 +5247,9 @@ public:
~CommandObjectProcessGDBRemotePacketMonitor() {}
- bool DoExecute(const char *command, CommandReturnObject &result) override {
- if (command == NULL || command[0] == '\0') {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
+ if (command.empty()) {
result.AppendErrorWithFormat("'%s' takes a command string argument",
m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
@@ -5154,14 +5261,15 @@ public:
if (process) {
StreamString packet;
packet.PutCString("qRcmd,");
- packet.PutBytesAsRawHex8(command, strlen(command));
+ packet.PutBytesAsRawHex8(command.data(), command.size());
bool send_async = true;
StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(
- packet.GetString(), response, send_async);
- result.SetStatus(eReturnStatusSuccessFinishResult);
Stream &output_strm = result.GetOutputStream();
+ process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport(
+ packet.GetString(), response, send_async,
+ [&output_strm](llvm::StringRef output) { output_strm << output; });
+ result.SetStatus(eReturnStatusSuccessFinishResult);
output_strm.Printf(" packet: %s\n", packet.GetData());
const std::string &response_str = response.GetStringRef();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 42d1c4ecd666..45bb2d4c28e7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -144,6 +144,9 @@ public:
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
+ Status
+ WriteObjectFile(std::vector<ObjectFile::LoadableData> entries) override;
+
size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size,
Status &error) override;
@@ -214,8 +217,7 @@ public:
void PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs,
const llvm::Triple &triple) override;
- bool GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) override;
+ llvm::VersionTuple GetHostOSVersion() override;
size_t LoadModules(LoadedModuleInfoList &module_list) override;
@@ -302,6 +304,11 @@ protected:
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_allow_flash_writes;
+ using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;
+ using FlashRange = FlashRangeVector::Entry;
+ FlashRangeVector m_erased_flash_ranges;
+
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
@@ -408,6 +415,12 @@ protected:
Status UpdateAutomaticSignalFiltering() override;
+ Status FlashErase(lldb::addr_t addr, size_t size);
+
+ Status FlashDone();
+
+ bool HasErased(FlashRange range);
+
private:
//------------------------------------------------------------------
// For ProcessGDBRemote only
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 27dd03bfc7bc..a525c16b9f13 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -24,7 +24,7 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -55,7 +55,7 @@ ThreadGDBRemote::~ThreadGDBRemote() {
const char *ThreadGDBRemote::GetName() {
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
@@ -80,10 +80,9 @@ void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name,
const char *ThreadGDBRemote::GetQueueName() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid()) {
if (m_dispatch_queue_name.empty())
return nullptr;
@@ -110,15 +109,14 @@ const char *ThreadGDBRemote::GetQueueName() {
return m_dispatch_queue_name.c_str();
}
}
- return NULL;
+ return nullptr;
}
QueueKind ThreadGDBRemote::GetQueueKind() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid()) {
return m_queue_kind;
}
@@ -141,10 +139,9 @@ QueueKind ThreadGDBRemote::GetQueueKind() {
queue_id_t ThreadGDBRemote::GetQueueID() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid())
return m_queue_serial_number;
@@ -275,11 +272,11 @@ void ThreadGDBRemote::RefreshStateAfterStop() {
// Invalidate all registers in our register context. We don't set "force" to
// true because the stop reply packet might have had some register values
// that were expedited and these will already be copied into the register
- // context by the time this function gets called. The GDBRemoteRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
+ // context by the time this function gets called. The
+ // GDBRemoteRegisterContext class has been made smart enough to detect when
+ // it needs to invalidate which registers are valid by putting hooks in the
+ // register read and register supply functions where they check the process
+ // stop ID and do the right thing.
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded(force);
}
@@ -292,8 +289,8 @@ void ThreadGDBRemote::Dump(Log *log, uint32_t index) {}
bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; }
lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
@@ -310,7 +307,8 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not supported.
+ // read_all_registers_at_once will be true if 'p' packet is not
+ // supported.
bool read_all_registers_at_once =
!gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
reg_ctx_sp.reset(new GDBRemoteRegisterContext(
@@ -319,7 +317,7 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
}
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 36350fdb6398..9a979335e99e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -14,10 +14,13 @@
// Other libraries and framework includes
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/LLDBAssert.h"
// C includes
// C++ includes
+#include <algorithm>
#include <map>
+#include <vector>
using namespace lldb_private;
using namespace minidump;
@@ -27,47 +30,11 @@ MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) {
if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) {
return llvm::None;
}
-
- llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(),
- sizeof(MinidumpHeader));
- const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
-
- if (header == nullptr) {
- return llvm::None;
- }
-
- lldb::offset_t directory_list_offset = header->stream_directory_rva;
- // check if there is enough data for the parsing of the directory list
- if ((directory_list_offset +
- sizeof(MinidumpDirectory) * header->streams_count) >
- data_buf_sp->GetByteSize()) {
- return llvm::None;
- }
-
- const MinidumpDirectory *directory = nullptr;
- Status error;
- llvm::ArrayRef<uint8_t> directory_data(
- data_buf_sp->GetBytes() + directory_list_offset,
- sizeof(MinidumpDirectory) * header->streams_count);
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map;
-
- for (uint32_t i = 0; i < header->streams_count; ++i) {
- error = consumeObject(directory_data, directory);
- if (error.Fail()) {
- return llvm::None;
- }
- directory_map[static_cast<const uint32_t>(directory->stream_type)] =
- directory->location;
- }
-
- return MinidumpParser(data_buf_sp, header, std::move(directory_map));
+ return MinidumpParser(data_buf_sp);
}
-MinidumpParser::MinidumpParser(
- const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map)
- : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) {
-}
+MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp)
+ : m_data_sp(data_buf_sp) {}
llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
@@ -96,6 +63,31 @@ llvm::Optional<std::string> MinidumpParser::GetMinidumpString(uint32_t rva) {
return parseMinidumpString(arr_ref);
}
+UUID MinidumpParser::GetModuleUUID(const MinidumpModule *module) {
+ auto cv_record =
+ GetData().slice(module->CV_record.rva, module->CV_record.data_size);
+
+ // Read the CV record signature
+ const llvm::support::ulittle32_t *signature = nullptr;
+ Status error = consumeObject(cv_record, signature);
+ if (error.Fail())
+ return UUID();
+
+ const CvSignature cv_signature =
+ static_cast<CvSignature>(static_cast<const uint32_t>(*signature));
+
+ if (cv_signature == CvSignature::Pdb70) {
+ // PDB70 record
+ const CvRecordPdb70 *pdb70_uuid = nullptr;
+ Status error = consumeObject(cv_record, pdb70_uuid);
+ if (!error.Fail())
+ return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
+ } else if (cv_signature == CvSignature::ElfBuildId)
+ return UUID::fromData(cv_record);
+
+ return UUID();
+}
+
llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ThreadList);
@@ -115,12 +107,12 @@ MinidumpParser::GetThreadContext(const MinidumpThread &td) {
llvm::ArrayRef<uint8_t>
MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
- // On Windows, a 32-bit process can run on a 64-bit machine under
- // WOW64. If the minidump was captured with a 64-bit debugger, then
- // the CONTEXT we just grabbed from the mini_dump_thread is the one
- // for the 64-bit "native" process rather than the 32-bit "guest"
- // process we care about. In this case, we can get the 32-bit CONTEXT
- // from the TEB (Thread Environment Block) of the 64-bit process.
+ // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. If
+ // the minidump was captured with a 64-bit debugger, then the CONTEXT we just
+ // grabbed from the mini_dump_thread is the one for the 64-bit "native"
+ // process rather than the 32-bit "guest" process we care about. In this
+ // case, we can get the 32-bit CONTEXT from the TEB (Thread Environment
+ // Block) of the 64-bit process.
auto teb_mem = GetMemory(td.teb, sizeof(TEB64));
if (teb_mem.empty())
return {};
@@ -130,9 +122,9 @@ MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
if (error.Fail())
return {};
- // Slot 1 of the thread-local storage in the 64-bit TEB points to a
- // structure that includes the 32-bit CONTEXT (after a ULONG).
- // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx
+ // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure
+ // that includes the 32-bit CONTEXT (after a ULONG). See:
+ // https://msdn.microsoft.com/en-us/library/ms681670.aspx
auto context =
GetMemory(wow64teb->tls_slots[1] + 4, sizeof(MinidumpContext_x86_32));
if (context.size() < sizeof(MinidumpContext_x86_32))
@@ -334,10 +326,10 @@ MinidumpParser::FindMemoryRange(lldb::addr_t addr) {
}
}
- // Some Minidumps have a Memory64ListStream that captures all the heap
- // memory (full-memory Minidumps). We can't exactly use the same loop as
- // above, because the Minidump uses slightly different data structures to
- // describe those
+ // Some Minidumps have a Memory64ListStream that captures all the heap memory
+ // (full-memory Minidumps). We can't exactly use the same loop as above,
+ // because the Minidump uses slightly different data structures to describe
+ // those
if (!data64.empty()) {
llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
@@ -377,8 +369,8 @@ llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
return {};
// There's at least some overlap between the beginning of the desired range
- // (addr) and the current range. Figure out where the overlap begins and
- // how much overlap there is.
+ // (addr) and the current range. Figure out where the overlap begins and how
+ // much overlap there is.
const size_t offset = addr - range->start;
@@ -456,3 +448,109 @@ MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
// appear truncated.
return info;
}
+
+Status MinidumpParser::Initialize() {
+ Status error;
+
+ lldbassert(m_directory_map.empty());
+
+ llvm::ArrayRef<uint8_t> header_data(m_data_sp->GetBytes(),
+ sizeof(MinidumpHeader));
+ const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
+ if (header == nullptr) {
+ error.SetErrorString("invalid minidump: can't parse the header");
+ return error;
+ }
+
+ // A minidump without at least one stream is clearly ill-formed
+ if (header->streams_count == 0) {
+ error.SetErrorString("invalid minidump: no streams present");
+ return error;
+ }
+
+ struct FileRange {
+ uint32_t offset = 0;
+ uint32_t size = 0;
+
+ FileRange(uint32_t offset, uint32_t size) : offset(offset), size(size) {}
+ uint32_t end() const { return offset + size; }
+ };
+
+ const uint32_t file_size = m_data_sp->GetByteSize();
+
+ // Build a global minidump file map, checking for:
+ // - overlapping streams/data structures
+ // - truncation (streams pointing past the end of file)
+ std::vector<FileRange> minidump_map;
+
+ // Add the minidump header to the file map
+ if (sizeof(MinidumpHeader) > file_size) {
+ error.SetErrorString("invalid minidump: truncated header");
+ return error;
+ }
+ minidump_map.emplace_back( 0, sizeof(MinidumpHeader) );
+
+ // Add the directory entries to the file map
+ FileRange directory_range(header->stream_directory_rva,
+ header->streams_count *
+ sizeof(MinidumpDirectory));
+ if (directory_range.end() > file_size) {
+ error.SetErrorString("invalid minidump: truncated streams directory");
+ return error;
+ }
+ minidump_map.push_back(directory_range);
+
+ // Parse stream directory entries
+ llvm::ArrayRef<uint8_t> directory_data(
+ m_data_sp->GetBytes() + directory_range.offset, directory_range.size);
+ for (uint32_t i = 0; i < header->streams_count; ++i) {
+ const MinidumpDirectory *directory_entry = nullptr;
+ error = consumeObject(directory_data, directory_entry);
+ if (error.Fail())
+ return error;
+ if (directory_entry->stream_type == 0) {
+ // Ignore dummy streams (technically ill-formed, but a number of
+ // existing minidumps seem to contain such streams)
+ if (directory_entry->location.data_size == 0)
+ continue;
+ error.SetErrorString("invalid minidump: bad stream type");
+ return error;
+ }
+ // Update the streams map, checking for duplicate stream types
+ if (!m_directory_map
+ .insert({directory_entry->stream_type, directory_entry->location})
+ .second) {
+ error.SetErrorString("invalid minidump: duplicate stream type");
+ return error;
+ }
+ // Ignore the zero-length streams for layout checks
+ if (directory_entry->location.data_size != 0) {
+ minidump_map.emplace_back(directory_entry->location.rva,
+ directory_entry->location.data_size);
+ }
+ }
+
+ // Sort the file map ranges by start offset
+ std::sort(minidump_map.begin(), minidump_map.end(),
+ [](const FileRange &a, const FileRange &b) {
+ return a.offset < b.offset;
+ });
+
+ // Check for overlapping streams/data structures
+ for (size_t i = 1; i < minidump_map.size(); ++i) {
+ const auto &prev_range = minidump_map[i - 1];
+ if (prev_range.end() > minidump_map[i].offset) {
+ error.SetErrorString("invalid minidump: overlapping streams");
+ return error;
+ }
+ }
+
+ // Check for streams past the end of file
+ const auto &last_range = minidump_map.back();
+ if (last_range.end() > file_size) {
+ error.SetErrorString("invalid minidump: truncated stream");
+ return error;
+ }
+
+ return error;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index b7329ffc0028..49b1eef14de5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -17,6 +17,7 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Status.h"
+#include "lldb/Utility/UUID.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -54,6 +55,8 @@ public:
llvm::Optional<std::string> GetMinidumpString(uint32_t rva);
+ UUID GetModuleUUID(const MinidumpModule* module);
+
llvm::ArrayRef<MinidumpThread> GetThreads();
llvm::ArrayRef<uint8_t> GetThreadContext(const MinidumpThread &td);
@@ -86,14 +89,15 @@ public:
llvm::Optional<MemoryRegionInfo> GetMemoryRegionInfo(lldb::addr_t);
+ // Perform consistency checks and initialize internal data structures
+ Status Initialize();
+
+private:
+ MinidumpParser(const lldb::DataBufferSP &data_buf_sp);
+
private:
lldb::DataBufferSP m_data_sp;
- const MinidumpHeader *m_header;
llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
-
- MinidumpParser(
- const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map);
};
} // end namespace minidump
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
index 24ce3f94c094..049704ba80ca 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
@@ -33,9 +33,6 @@ const MinidumpHeader *MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data) {
version != MinidumpHeaderConstants::Version)
return nullptr;
- // TODO check for max number of streams ?
- // TODO more sanity checks ?
-
return header;
}
@@ -44,19 +41,23 @@ llvm::Optional<std::string>
lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) {
std::string result;
- const uint32_t *source_length;
- Status error = consumeObject(data, source_length);
- if (error.Fail() || *source_length > data.size() || *source_length % 2 != 0)
+ const uint32_t *source_length_ptr;
+ Status error = consumeObject(data, source_length_ptr);
+
+ // Copy non-aligned source_length data into aligned memory.
+ uint32_t source_length;
+ std::memcpy(&source_length, source_length_ptr, sizeof(source_length));
+
+ if (error.Fail() || source_length > data.size() || source_length % 2 != 0)
return llvm::None;
auto source_start = reinterpret_cast<const llvm::UTF16 *>(data.data());
- // source_length is the length of the string in bytes
- // we need the length of the string in UTF-16 characters/code points (16 bits
- // per char)
- // that's why it's divided by 2
- const auto source_end = source_start + (*source_length) / 2;
+ // source_length is the length of the string in bytes we need the length of
+ // the string in UTF-16 characters/code points (16 bits per char) that's why
+ // it's divided by 2
+ const auto source_end = source_start + source_length / 2;
// resize to worst case length
- result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * (*source_length) / 2);
+ result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length / 2);
auto result_start = reinterpret_cast<llvm::UTF8 *>(&result[0]);
const auto result_end = result_start + result.size();
llvm::ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end,
@@ -80,11 +81,17 @@ const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) {
llvm::ArrayRef<MinidumpThread>
MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) {
+ const auto orig_size = data.size();
const llvm::support::ulittle32_t *thread_count;
Status error = consumeObject(data, thread_count);
if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size())
return {};
+ // Compilers might end up padding an extra 4 bytes depending on how the
+ // structure is padded by the compiler and the #pragma pack settings.
+ if (4 + *thread_count * sizeof(MinidumpThread) < orig_size)
+ data = data.drop_front(4);
+
return llvm::ArrayRef<MinidumpThread>(
reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count);
}
@@ -156,12 +163,17 @@ const MinidumpModule *MinidumpModule::Parse(llvm::ArrayRef<uint8_t> &data) {
llvm::ArrayRef<MinidumpModule>
MinidumpModule::ParseModuleList(llvm::ArrayRef<uint8_t> &data) {
-
+ const auto orig_size = data.size();
const llvm::support::ulittle32_t *modules_count;
Status error = consumeObject(data, modules_count);
if (error.Fail() || *modules_count * sizeof(MinidumpModule) > data.size())
return {};
-
+
+ // Compilers might end up padding an extra 4 bytes depending on how the
+ // structure is padded by the compiler and the #pragma pack settings.
+ if (4 + *modules_count * sizeof(MinidumpModule) < orig_size)
+ data = data.drop_front(4);
+
return llvm::ArrayRef<MinidumpModule>(
reinterpret_cast<const MinidumpModule *>(data.data()), *modules_count);
}
@@ -179,11 +191,17 @@ MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) {
llvm::ArrayRef<MinidumpMemoryDescriptor>
MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
+ const auto orig_size = data.size();
const llvm::support::ulittle32_t *mem_ranges_count;
Status error = consumeObject(data, mem_ranges_count);
if (error.Fail() ||
*mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size())
return {};
+
+ // Compilers might end up padding an extra 4 bytes depending on how the
+ // structure is padded by the compiler and the #pragma pack settings.
+ if (4 + *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) < orig_size)
+ data = data.drop_front(4);
return llvm::makeArrayRef(
reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()),
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.h
index 6de4f55a769d..e83089865b9e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.h
@@ -43,6 +43,21 @@ enum class MinidumpHeaderConstants : uint32_t {
};
+enum class CvSignature : uint32_t {
+ Pdb70 = 0x53445352, // RSDS
+ ElfBuildId = 0x4270454c, // BpEL (Breakpad/Crashpad minidumps)
+};
+
+// Reference:
+// https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html
+struct CvRecordPdb70 {
+ uint8_t Uuid[16];
+ llvm::support::ulittle32_t Age;
+ // char PDBFileName[];
+};
+static_assert(sizeof(CvRecordPdb70) == 20,
+ "sizeof CvRecordPdb70 is not correct!");
+
// Reference:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx
enum class MinidumpStreamType : uint32_t {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index d4d65c044eab..b43f22382eac 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/State.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/DataBufferLLVM.h"
@@ -31,9 +32,56 @@
// C includes
// C++ includes
+using namespace lldb;
using namespace lldb_private;
using namespace minidump;
+//------------------------------------------------------------------
+/// A placeholder module used for minidumps, where the original
+/// object files may not be available (so we can't parse the object
+/// files to extract the set of sections/segments)
+///
+/// This placeholder module has a single synthetic section (.module_image)
+/// which represents the module memory range covering the whole module.
+//------------------------------------------------------------------
+class PlaceholderModule : public Module {
+public:
+ PlaceholderModule(const ModuleSpec &module_spec) :
+ Module(module_spec.GetFileSpec(), module_spec.GetArchitecture()) {
+ if (module_spec.GetUUID().IsValid())
+ SetUUID(module_spec.GetUUID());
+ }
+
+ // Creates a synthetic module section covering the whole module image (and
+ // sets the section load address as well)
+ void CreateImageSection(const MinidumpModule *module, Target& target) {
+ const ConstString section_name(".module_image");
+ lldb::SectionSP section_sp(new Section(
+ shared_from_this(), // Module to which this section belongs.
+ nullptr, // ObjectFile
+ 0, // Section ID.
+ section_name, // Section name.
+ eSectionTypeContainer, // Section type.
+ module->base_of_image, // VM address.
+ module->size_of_image, // VM size in bytes of this section.
+ 0, // Offset of this section in the file.
+ module->size_of_image, // Size of the section as found in the file.
+ 12, // Alignment of the section (log2)
+ 0, // Flags for this section.
+ 1)); // Number of host bytes per target byte
+ section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable);
+ GetSectionList()->AddSection(section_sp);
+ target.GetSectionLoadList().SetSectionLoadAddress(
+ section_sp, module->base_of_image);
+ }
+
+ ObjectFile *GetObjectFile() override { return nullptr; }
+
+ SectionList *GetSectionList() override {
+ return Module::GetUnifiedSectionList();
+ }
+};
+
ConstString ProcessMinidump::GetPluginNameStatic() {
static ConstString g_name("minidump");
return g_name;
@@ -57,7 +105,7 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp,
if (!DataPtr)
return nullptr;
- assert(DataPtr->GetByteSize() == header_size);
+ lldbassert(DataPtr->GetByteSize() == header_size);
// first, only try to parse the header, beacuse we need to be fast
llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData();
@@ -92,10 +140,10 @@ ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,
ProcessMinidump::~ProcessMinidump() {
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
}
@@ -116,10 +164,29 @@ void ProcessMinidump::Terminate() {
Status ProcessMinidump::DoLoadCore() {
Status error;
+ // Minidump parser initialization & consistency checks
+ error = m_minidump_parser.Initialize();
+ if (error.Fail())
+ return error;
+
+ // Do we support the minidump's architecture?
+ ArchSpec arch = GetArchitecture();
+ switch (arch.GetMachine()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ // supported
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unsupported minidump architecture: %s",
+ arch.GetArchitectureName());
+ return error;
+ }
+
m_thread_list = m_minidump_parser.GetThreads();
m_active_exception = m_minidump_parser.GetExceptionStream();
ReadModuleList();
- GetTarget().SetArchitecture(GetArchitecture());
+ GetTarget().SetArchitecture(arch);
llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid();
if (!pid) {
@@ -185,8 +252,8 @@ bool ProcessMinidump::WarnBeforeDetach() const { return false; }
size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
- // Don't allow the caching that lldb_private::Process::ReadMemory does
- // since we have it all cached in our dump file anyway.
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // we have it all cached in our dump file anyway.
return DoReadMemory(addr, buf, size, error);
}
@@ -276,12 +343,25 @@ void ProcessMinidump::ReadModuleList() {
m_is_wow64 = true;
}
- const auto file_spec = FileSpec(name.getValue(), true);
- ModuleSpec module_spec = file_spec;
+ const auto uuid = m_minidump_parser.GetModuleUUID(module);
+ const auto file_spec =
+ FileSpec(name.getValue(), true, GetArchitecture().GetTriple());
+ ModuleSpec module_spec(file_spec, uuid);
Status error;
lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
if (!module_sp || error.Fail()) {
- continue;
+ // We failed to locate a matching local object file. Fortunately, the
+ // minidump format encodes enough information about each module's memory
+ // range to allow us to create placeholder modules.
+ //
+ // This enables most LLDB functionality involving address-to-module
+ // translations (ex. identifing the module for a stack frame PC) and
+ // modules/sections commands (ex. target modules list, ...)
+ auto placeholder_module =
+ std::make_shared<PlaceholderModule>(module_spec);
+ placeholder_module->CreateImageSection(module, GetTarget());
+ module_sp = placeholder_module;
+ GetTarget().GetImages().Append(module_sp);
}
if (log) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 4b91d1ba396a..d65ada9009a7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -61,6 +61,8 @@ public:
uint32_t GetPluginVersion() override;
+ SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
Status DoDestroy() override;
void RefreshStateAfterStop() override;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
index 9ec9f4344613..4bd4c6a029a0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -27,7 +27,7 @@ ScriptInterpreterNone::ScriptInterpreterNone(CommandInterpreter &interpreter)
ScriptInterpreterNone::~ScriptInterpreterNone() {}
-bool ScriptInterpreterNone::ExecuteOneLine(const char *command,
+bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *,
const ExecuteScriptOptions &) {
m_interpreter.GetDebugger().GetErrorFile()->PutCString(
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
index d66b2f07310c..824579472b5e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
@@ -25,7 +25,7 @@ public:
~ScriptInterpreterNone() override;
bool ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
void ExecuteInterpreterLoop() override;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 966bdff3ad95..90d8ab97fb73 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -1,5 +1,4 @@
-//===-- PythonDataObjects.cpp ------------------------------------*- C++
-//-*-===//
+//===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -123,21 +122,20 @@ PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
}
PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
- // Resolve the name in the context of the specified object. If,
- // for example, `this` refers to a PyModule, then this will look for
- // `name` in this module. If `this` refers to a PyType, then it will
- // resolve `name` as an attribute of that type. If `this` refers to
- // an instance of an object, then it will resolve `name` as the value
- // of the specified field.
+ // Resolve the name in the context of the specified object. If, for example,
+ // `this` refers to a PyModule, then this will look for `name` in this
+ // module. If `this` refers to a PyType, then it will resolve `name` as an
+ // attribute of that type. If `this` refers to an instance of an object,
+ // then it will resolve `name` as the value of the specified field.
//
// This function handles dotted names so that, for example, if `m_py_obj`
- // refers to the `sys` module, and `name` == "path.append", then it
- // will find the function `sys.path.append`.
+ // refers to the `sys` module, and `name` == "path.append", then it will find
+ // the function `sys.path.append`.
size_t dot_pos = name.find_first_of('.');
if (dot_pos == llvm::StringRef::npos) {
- // No dots in the name, we should be able to find the value immediately
- // as an attribute of `m_py_obj`.
+ // No dots in the name, we should be able to find the value immediately as
+ // an attribute of `m_py_obj`.
return GetAttributeValue(name);
}
@@ -230,8 +228,8 @@ bool PythonBytes::Check(PyObject *py_obj) {
}
void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonBytes::Check(py_obj)) {
@@ -240,8 +238,7 @@ void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -303,8 +300,8 @@ bool PythonByteArray::Check(PyObject *py_obj) {
}
void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonByteArray::Check(py_obj)) {
@@ -313,8 +310,7 @@ void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -378,8 +374,8 @@ bool PythonString::Check(PyObject *py_obj) {
}
void PythonString::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonString::Check(py_obj)) {
@@ -394,8 +390,7 @@ void PythonString::Reset(PyRefType type, PyObject *py_obj) {
result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
#endif
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -404,14 +399,16 @@ llvm::StringRef PythonString::GetString() const {
return llvm::StringRef();
Py_ssize_t size;
- char *c;
+ const char *data;
#if PY_MAJOR_VERSION >= 3
- c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
+ data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
#else
+ char *c;
PyString_AsStringAndSize(m_py_obj, &c, &size);
+ data = c;
#endif
- return llvm::StringRef(c, size);
+ return llvm::StringRef(data, size);
}
size_t PythonString::GetSize() const {
@@ -466,8 +463,8 @@ bool PythonInteger::Check(PyObject *py_obj) {
return false;
#if PY_MAJOR_VERSION >= 3
- // Python 3 does not have PyInt_Check. There is only one type of
- // integral value, long.
+ // Python 3 does not have PyInt_Check. There is only one type of integral
+ // value, long.
return PyLong_Check(py_obj);
#else
return PyLong_Check(py_obj) || PyInt_Check(py_obj);
@@ -475,8 +472,8 @@ bool PythonInteger::Check(PyObject *py_obj) {
}
void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonInteger::Check(py_obj)) {
@@ -485,13 +482,13 @@ void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
}
#if PY_MAJOR_VERSION < 3
- // Always store this as a PyLong, which makes interoperability between
- // Python 2.x and Python 3.x easier. This is only necessary in 2.x,
- // since 3.x doesn't even have a PyInt.
+ // Always store this as a PyLong, which makes interoperability between Python
+ // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x
+ // doesn't even have a PyInt.
if (PyInt_Check(py_obj)) {
// Since we converted the original object to a different type, the new
- // object is an owned object regardless of the ownership semantics requested
- // by the user.
+ // object is an owned object regardless of the ownership semantics
+ // requested by the user.
result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
}
#endif
@@ -500,8 +497,7 @@ void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
"Couldn't get a PyLong from this PyObject");
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -513,10 +509,9 @@ int64_t PythonInteger::GetInteger() const {
int overflow = 0;
int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
if (overflow != 0) {
- // We got an integer that overflows, like 18446744072853913392L
- // we can't use PyLong_AsLongLong() as it will return
- // 0xffffffffffffffff. If we use the unsigned long long
- // it will work as expected.
+ // We got an integer that overflows, like 18446744072853913392L we can't
+ // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
+ // use the unsigned long long it will work as expected.
const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
result = static_cast<int64_t>(uval);
}
@@ -563,8 +558,8 @@ bool PythonList::Check(PyObject *py_obj) {
}
void PythonList::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonList::Check(py_obj)) {
@@ -573,8 +568,7 @@ void PythonList::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -668,8 +662,8 @@ bool PythonTuple::Check(PyObject *py_obj) {
}
void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonTuple::Check(py_obj)) {
@@ -678,8 +672,7 @@ void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -741,8 +734,8 @@ bool PythonDictionary::Check(PyObject *py_obj) {
}
void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonDictionary::Check(py_obj)) {
@@ -751,8 +744,7 @@ void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -833,8 +825,8 @@ bool PythonModule::Check(PyObject *py_obj) {
}
void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonModule::Check(py_obj)) {
@@ -843,8 +835,7 @@ void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -871,8 +862,8 @@ bool PythonCallable::Check(PyObject *py_obj) {
}
void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonCallable::Check(py_obj)) {
@@ -881,8 +872,7 @@ void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -963,9 +953,9 @@ bool PythonFile::Check(PyObject *py_obj) {
#else
// In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
// first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
- // over `io.open()`, which returns some object derived from `io.IOBase`.
- // As a result, the only way to detect a file in Python 3 is to check whether
- // it inherits from `io.IOBase`. Since it is possible for non-files to also
+ // over `io.open()`, which returns some object derived from `io.IOBase`. As a
+ // result, the only way to detect a file in Python 3 is to check whether it
+ // inherits from `io.IOBase`. Since it is possible for non-files to also
// inherit from `io.IOBase`, we additionally verify that it has the `fileno`
// attribute, which should guarantee that it is backed by the file system.
PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
@@ -985,8 +975,8 @@ bool PythonFile::Check(PyObject *py_obj) {
}
void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonFile::Check(py_obj)) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
index 4d956d5dbe14..d28a8033820a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
@@ -30,9 +30,9 @@ PythonExceptionState::~PythonExceptionState() {
}
void PythonExceptionState::Acquire(bool restore_on_exit) {
- // If a state is already acquired, the user needs to decide whether they
- // want to discard or restore it. Don't allow the potential silent
- // loss of a valid state.
+ // If a state is already acquired, the user needs to decide whether they want
+ // to discard or restore it. Don't allow the potential silent loss of a
+ // valid state.
assert(!IsError());
if (!HasErrorOccurred())
@@ -45,8 +45,7 @@ void PythonExceptionState::Acquire(bool restore_on_exit) {
// PyErr_Fetch clears the error flag.
assert(!HasErrorOccurred());
- // Ownership of the objects returned by `PyErr_Fetch` is transferred
- // to us.
+ // Ownership of the objects returned by `PyErr_Fetch` is transferred to us.
m_type.Reset(PyRefType::Owned, py_type);
m_value.Reset(PyRefType::Owned, py_value);
m_traceback.Reset(PyRefType::Owned, py_traceback);
@@ -56,14 +55,14 @@ void PythonExceptionState::Acquire(bool restore_on_exit) {
void PythonExceptionState::Restore() {
if (m_type.IsValid()) {
// The documentation for PyErr_Restore says "Do not pass a null type and
- // non-null value or traceback. So only restore if type was non-null
- // to begin with. In this case we're passing ownership back to Python
- // so release them all.
+ // non-null value or traceback. So only restore if type was non-null to
+ // begin with. In this case we're passing ownership back to Python so
+ // release them all.
PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
}
- // After we restore, we should not hold onto the exception state. Demand that
- // it be re-acquired.
+ // After we restore, we should not hold onto the exception state. Demand
+ // that it be re-acquired.
Discard();
}
@@ -100,10 +99,10 @@ std::string PythonExceptionState::Format() const {
if (!IsError())
return std::string();
- // It's possible that ReadPythonBacktrace generated another exception.
- // If this happens we have to clear the exception, because otherwise
- // PyObject_Str() will assert below. That's why we needed to do the
- // save / restore at the beginning of this function.
+ // It's possible that ReadPythonBacktrace generated another exception. If
+ // this happens we have to clear the exception, because otherwise
+ // PyObject_Str() will assert below. That's why we needed to do the save /
+ // restore at the beginning of this function.
PythonExceptionState bt_error_state(false);
std::string error_string;
@@ -114,8 +113,8 @@ std::string PythonExceptionState::Format() const {
// If we were able to read the backtrace, just append it.
error_stream << backtrace << "\n";
} else {
- // Otherwise, append some information about why we were unable to
- // obtain the backtrace.
+ // Otherwise, append some information about why we were unable to obtain
+ // the backtrace.
PythonString bt_error = bt_error_state.GetValue().Str();
error_stream << "An error occurred while retrieving the backtrace: "
<< bt_error.GetString() << "\n";
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 6c39690268c6..b8eb36a2baf6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -112,13 +112,12 @@ static bool g_initialized = false;
namespace {
-// Initializing Python is not a straightforward process. We cannot control what
-// external code may have done before getting to this point in LLDB, including
-// potentially having already initialized Python, so we need to do a lot of work
-// to ensure that the existing state of the system is maintained across our
-// initialization. We do this by using an RAII pattern where we save off
-// initial
-// state at the beginning, and restore it at the end
+// Initializing Python is not a straightforward process. We cannot control
+// what external code may have done before getting to this point in LLDB,
+// including potentially having already initialized Python, so we need to do a
+// lot of work to ensure that the existing state of the system is maintained
+// across our initialization. We do this by using an RAII pattern where we
+// save off initial state at the beginning, and restore it at the end
struct InitializePythonRAII {
public:
InitializePythonRAII()
@@ -210,12 +209,11 @@ bool ScriptInterpreterPython::Locker::DoAcquireLock() {
LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked",
m_GILState == PyGILState_UNLOCKED ? "un" : "");
- // we need to save the thread state when we first start the command
- // because we might decide to interrupt it while some action is taking
- // place outside of Python (e.g. printing to screen, waiting for the network,
- // ...)
- // in that case, _PyThreadState_Current will be NULL - and we would be unable
- // to set the asynchronous exception - not a desirable situation
+ // we need to save the thread state when we first start the command because
+ // we might decide to interrupt it while some action is taking place outside
+ // of Python (e.g. printing to screen, waiting for the network, ...) in that
+ // case, _PyThreadState_Current will be NULL - and we would be unable to set
+ // the asynchronous exception - not a desirable situation
m_python_interpreter->SetThreadState(PyThreadState_Get());
m_python_interpreter->IncrementLockCount();
return true;
@@ -281,17 +279,16 @@ ScriptInterpreterPython::ScriptInterpreterPython(
PyRun_SimpleString(run_string.GetData());
// Reloading modules requires a different syntax in Python 2 and Python 3.
- // This provides
- // a consistent syntax no matter what version of Python.
+ // This provides a consistent syntax no matter what version of Python.
run_string.Clear();
run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')",
m_dictionary_name.c_str());
PyRun_SimpleString(run_string.GetData());
// WARNING: temporary code that loads Cocoa formatters - this should be done
- // on a per-platform basis rather than loading the whole set
- // and letting the individual formatter classes exploit APIs to check whether
- // they can/cannot do their task
+ // on a per-platform basis rather than loading the whole set and letting the
+ // individual formatter classes exploit APIs to check whether they can/cannot
+ // do their task
run_string.Clear();
run_string.Printf(
"run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')",
@@ -314,13 +311,11 @@ ScriptInterpreterPython::ScriptInterpreterPython(
}
ScriptInterpreterPython::~ScriptInterpreterPython() {
- // the session dictionary may hold objects with complex state
- // which means that they may need to be torn down with some level of smarts
- // and that, in turn, requires a valid thread state
- // force Python to procure itself such a thread state, nuke the session
- // dictionary
- // and then release it for others to use and proceed with the rest of the
- // shutdown
+ // the session dictionary may hold objects with complex state which means
+ // that they may need to be torn down with some level of smarts and that, in
+ // turn, requires a valid thread state force Python to procure itself such a
+ // thread state, nuke the session dictionary and then release it for others
+ // to use and proceed with the rest of the shutdown
auto gil_state = PyGILState_Ensure();
m_session_dict.Reset();
PyGILState_Release(gil_state);
@@ -352,6 +347,71 @@ const char *ScriptInterpreterPython::GetPluginDescriptionStatic() {
return "Embedded Python interpreter";
}
+void ScriptInterpreterPython::ComputePythonDirForApple(
+ llvm::SmallVectorImpl<char> &path) {
+ auto style = llvm::sys::path::Style::posix;
+
+ llvm::StringRef path_ref(path.begin(), path.size());
+ auto rbegin = llvm::sys::path::rbegin(path_ref, style);
+ auto rend = llvm::sys::path::rend(path_ref);
+ auto framework = std::find(rbegin, rend, "LLDB.framework");
+ if (framework == rend) {
+ ComputePythonDirForPosix(path);
+ return;
+ }
+ path.resize(framework - rend);
+ llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
+}
+
+void ScriptInterpreterPython::ComputePythonDirForPosix(
+ llvm::SmallVectorImpl<char> &path) {
+ auto style = llvm::sys::path::Style::posix;
+#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
+ // Build the path by backing out of the lib dir, then building with whatever
+ // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL
+ // x86_64).
+ llvm::sys::path::remove_filename(path, style);
+ llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR);
+#else
+ llvm::sys::path::append(path, style,
+ "python" + llvm::Twine(PY_MAJOR_VERSION) + "." +
+ llvm::Twine(PY_MINOR_VERSION),
+ "site-packages");
+#endif
+}
+
+void ScriptInterpreterPython::ComputePythonDirForWindows(
+ llvm::SmallVectorImpl<char> &path) {
+ auto style = llvm::sys::path::Style::windows;
+ llvm::sys::path::remove_filename(path, style);
+ llvm::sys::path::append(path, style, "lib", "site-packages");
+
+ // This will be injected directly through FileSpec.GetDirectory().SetString(),
+ // so we need to normalize manually.
+ std::replace(path.begin(), path.end(), '\\', '/');
+}
+
+FileSpec ScriptInterpreterPython::GetPythonDir() {
+ static FileSpec g_spec = []() {
+ FileSpec spec = HostInfo::GetShlibDir();
+ if (!spec)
+ return FileSpec();
+ llvm::SmallString<64> path;
+ spec.GetPath(path);
+
+#if defined(__APPLE__)
+ ComputePythonDirForApple(path);
+#elif defined(_WIN32)
+ ComputePythonDirForWindows(path);
+#else
+ ComputePythonDirForPosix(path);
+#endif
+ spec.GetDirectory().SetString(path);
+ return spec;
+ }();
+ return g_spec;
+}
+
lldb_private::ConstString ScriptInterpreterPython::GetPluginName() {
return GetPluginNameStatic();
}
@@ -452,16 +512,16 @@ void ScriptInterpreterPython::ResetOutputFileHandle(FILE *fh) {}
void ScriptInterpreterPython::SaveTerminalState(int fd) {
// Python mucks with the terminal state of STDIN. If we can possibly avoid
// this by setting the file handles up correctly prior to entering the
- // interpreter we should. For now we save and restore the terminal state
- // on the input file handle.
+ // interpreter we should. For now we save and restore the terminal state on
+ // the input file handle.
m_terminal_state.Save(fd, false);
}
void ScriptInterpreterPython::RestoreTerminalState() {
// Python mucks with the terminal state of STDIN. If we can possibly avoid
// this by setting the file handles up correctly prior to entering the
- // interpreter we should. For now we save and restore the terminal state
- // on the input file handle.
+ // interpreter we should. For now we save and restore the terminal state on
+ // the input file handle.
m_terminal_state.Restore();
}
@@ -470,14 +530,11 @@ void ScriptInterpreterPython::LeaveSession() {
if (log)
log->PutCString("ScriptInterpreterPython::LeaveSession()");
- // checking that we have a valid thread state - since we use our own threading
- // and locking
- // in some (rare) cases during cleanup Python may end up believing we have no
- // thread state
- // and PyImport_AddModule will crash if that is the case - since that seems to
- // only happen
- // when destroying the SBDebugger, we can make do without clearing up stdout
- // and stderr
+ // checking that we have a valid thread state - since we use our own
+ // threading and locking in some (rare) cases during cleanup Python may end
+ // up believing we have no thread state and PyImport_AddModule will crash if
+ // that is the case - since that seems to only happen when destroying the
+ // SBDebugger, we can make do without clearing up stdout and stderr
// rdar://problem/11292882
// When the current thread state is NULL, PyThreadState_Get() issues a fatal
@@ -526,8 +583,7 @@ bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name,
bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in,
FILE *out, FILE *err) {
// If we have already entered the session, without having officially 'left'
- // it, then there is no need to
- // 'enter' it again.
+ // it, then there is no need to 'enter' it again.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
if (m_session_is_active) {
if (log)
@@ -560,8 +616,8 @@ bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in,
run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
run_string.PutCString("')");
} else {
- // If we aren't initing the globals, we should still always set the debugger
- // (since that is always unique.)
+ // If we aren't initing the globals, we should still always set the
+ // debugger (since that is always unique.)
run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
m_dictionary_name.c_str(),
GetCommandInterpreter().GetDebugger().GetID());
@@ -695,19 +751,20 @@ static void ReadThreadBytesReceived(void *baton, const void *src,
}
bool ScriptInterpreterPython::ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options) {
+ std::string command_str = command.str();
+
if (!m_valid_session)
return false;
- if (command && command[0]) {
+ if (!command.empty()) {
// We want to call run_one_line, passing in the dictionary and the command
- // string. We cannot do this through
- // PyRun_SimpleString here because the command string may contain escaped
- // characters, and putting it inside
+ // string. We cannot do this through PyRun_SimpleString here because the
+ // command string may contain escaped characters, and putting it inside
// another string to pass to PyRun_SimpleString messes up the escaping. So
- // we use the following more complicated
- // method to pass the command string directly down to Python.
+ // we use the following more complicated method to pass the command string
+ // directly down to Python.
Debugger &debugger = m_interpreter.GetDebugger();
StreamFileSP input_file_sp;
@@ -773,17 +830,14 @@ bool ScriptInterpreterPython::ExecuteOneLine(
FILE *err_file = error_file_sp->GetFile().GetStream();
bool success = false;
{
- // WARNING! It's imperative that this RAII scope be as tight as possible.
- // In particular, the
- // scope must end *before* we try to join the read thread. The reason for
- // this is that a
- // pre-requisite for joining the read thread is that we close the write
- // handle (to break the
- // pipe and cause it to wake up and exit). But acquiring the GIL as below
- // will redirect Python's
- // stdio to use this same handle. If we close the handle while Python is
- // still using it, bad
- // things will happen.
+ // WARNING! It's imperative that this RAII scope be as tight as
+ // possible. In particular, the scope must end *before* we try to join
+ // the read thread. The reason for this is that a pre-requisite for
+ // joining the read thread is that we close the write handle (to break
+ // the pipe and cause it to wake up and exit). But acquiring the GIL as
+ // below will redirect Python's stdio to use this same handle. If we
+ // close the handle while Python is still using it, bad things will
+ // happen.
Locker locker(
this,
ScriptInterpreterPython::Locker::AcquireLock |
@@ -803,7 +857,7 @@ bool ScriptInterpreterPython::ExecuteOneLine(
if (PyCallable_Check(m_run_one_line_function.get())) {
PythonObject pargs(
PyRefType::Owned,
- Py_BuildValue("(Os)", session_dict.get(), command));
+ Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
if (pargs.IsValid()) {
PythonObject return_value(
PyRefType::Owned,
@@ -827,12 +881,12 @@ bool ScriptInterpreterPython::ExecuteOneLine(
}
if (join_read_thread) {
- // Close the write end of the pipe since we are done with our
- // one line script. This should cause the read thread that
- // output_comm is using to exit
+ // Close the write end of the pipe since we are done with our one line
+ // script. This should cause the read thread that output_comm is using to
+ // exit
output_file_sp->GetFile().Close();
- // The close above should cause this thread to exit when it gets
- // to the end of file, so let it get all its data
+ // The close above should cause this thread to exit when it gets to the
+ // end of file, so let it get all its data
output_comm.JoinReadThread();
// Now we can close the read end of the pipe
output_comm.Disconnect();
@@ -842,9 +896,10 @@ bool ScriptInterpreterPython::ExecuteOneLine(
return true;
// The one-liner failed. Append the error message.
- if (result)
+ if (result) {
result->AppendErrorWithFormat(
- "python failed attempting to evaluate '%s'\n", command);
+ "python failed attempting to evaluate '%s'\n", command_str.c_str());
+ }
return false;
}
@@ -889,21 +944,18 @@ public:
ScriptInterpreterPython::Locker::FreeAcquiredLock |
ScriptInterpreterPython::Locker::TearDownSession);
- // The following call drops into the embedded interpreter loop and stays
- // there until the
- // user chooses to exit from the Python interpreter.
- // This embedded interpreter will, as any Python code that performs I/O,
- // unlock the GIL before
- // a system call that can hang, and lock it when the syscall has
- // returned.
+ // The following call drops into the embedded interpreter loop and
+ // stays there until the user chooses to exit from the Python
+ // interpreter. This embedded interpreter will, as any Python code that
+ // performs I/O, unlock the GIL before a system call that can hang, and
+ // lock it when the syscall has returned.
// We need to surround the call to the embedded interpreter with calls
- // to PyGILState_Ensure and
- // PyGILState_Release (using the Locker above). This is because Python
- // has a global lock which must be held whenever we want
- // to touch any Python objects. Otherwise, if the user calls Python
- // code, the interpreter state will be off,
- // and things could hang (it's happened before).
+ // to PyGILState_Ensure and PyGILState_Release (using the Locker
+ // above). This is because Python has a global lock which must be held
+ // whenever we want to touch any Python objects. Otherwise, if the user
+ // calls Python code, the interpreter state will be off, and things
+ // could hang (it's happened before).
StreamString run_string;
run_string.Printf("run_python_interpreter (%s)",
@@ -934,12 +986,10 @@ void ScriptInterpreterPython::ExecuteInterpreterLoop() {
Debugger &debugger = GetCommandInterpreter().GetDebugger();
// At the moment, the only time the debugger does not have an input file
- // handle is when this is called
- // directly from Python, in which case it is both dangerous and unnecessary
- // (not to mention confusing) to
- // try to embed a running interpreter loop inside the already running Python
- // interpreter loop, so we won't
- // do it.
+ // handle is when this is called directly from Python, in which case it is
+ // both dangerous and unnecessary (not to mention confusing) to try to embed
+ // a running interpreter loop inside the already running Python interpreter
+ // loop, so we won't do it.
if (!debugger.GetInputFile()->GetFile().IsValid())
return;
@@ -974,7 +1024,7 @@ bool ScriptInterpreterPython::Interrupt() {
return false;
}
bool ScriptInterpreterPython::ExecuteOneLineWithReturn(
- const char *in_string, ScriptInterpreter::ScriptReturnType return_type,
+ llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
void *ret_value, const ExecuteScriptOptions &options) {
Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock |
@@ -1009,116 +1059,111 @@ bool ScriptInterpreterPython::ExecuteOneLineWithReturn(
if (py_error.IsValid())
PyErr_Clear();
- if (in_string != nullptr) {
- { // scope for PythonInputReaderManager
- // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
- py_return.Reset(
- PyRefType::Owned,
- PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
- if (!py_return.IsValid()) {
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- py_return.Reset(PyRefType::Owned,
- PyRun_String(in_string, Py_single_input, globals.get(),
- locals.get()));
- }
+ std::string as_string = in_string.str();
+ { // scope for PythonInputReaderManager
+ // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+ py_return.Reset(PyRefType::Owned,
+ PyRun_String(as_string.c_str(), Py_eval_input,
+ globals.get(), locals.get()));
+ if (!py_return.IsValid()) {
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ py_return.Reset(PyRefType::Owned,
+ PyRun_String(as_string.c_str(), Py_single_input,
+ globals.get(), locals.get()));
}
+ }
- if (py_return.IsValid()) {
- switch (return_type) {
- case eScriptReturnTypeCharPtr: // "char *"
- {
- const char format[3] = "s#";
- success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
- break;
- }
- case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
- // Py_None
- {
- const char format[3] = "z";
- success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
- break;
- }
- case eScriptReturnTypeBool: {
- const char format[2] = "b";
- success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
- break;
- }
- case eScriptReturnTypeShortInt: {
- const char format[2] = "h";
- success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
- break;
- }
- case eScriptReturnTypeShortIntUnsigned: {
- const char format[2] = "H";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
- break;
- }
- case eScriptReturnTypeInt: {
- const char format[2] = "i";
- success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
- break;
- }
- case eScriptReturnTypeIntUnsigned: {
- const char format[2] = "I";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
- break;
- }
- case eScriptReturnTypeLongInt: {
- const char format[2] = "l";
- success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongIntUnsigned: {
- const char format[2] = "k";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongLong: {
- const char format[2] = "L";
- success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongLongUnsigned: {
- const char format[2] = "K";
- success = PyArg_Parse(py_return.get(), format,
- (unsigned long long *)ret_value);
- break;
- }
- case eScriptReturnTypeFloat: {
- const char format[2] = "f";
- success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
- break;
- }
- case eScriptReturnTypeDouble: {
- const char format[2] = "d";
- success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
- break;
- }
- case eScriptReturnTypeChar: {
- const char format[2] = "c";
- success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
- break;
- }
- case eScriptReturnTypeOpaqueObject: {
- success = true;
- PyObject *saved_value = py_return.get();
- Py_XINCREF(saved_value);
- *((PyObject **)ret_value) = saved_value;
- break;
- }
- }
-
- if (success)
- ret_success = true;
- else
- ret_success = false;
+ if (py_return.IsValid()) {
+ switch (return_type) {
+ case eScriptReturnTypeCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ break;
+ }
+ case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
+ // Py_None
+ {
+ const char format[3] = "z";
+ success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ break;
}
+ case eScriptReturnTypeBool: {
+ const char format[2] = "b";
+ success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortInt: {
+ const char format[2] = "h";
+ success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortIntUnsigned: {
+ const char format[2] = "H";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeInt: {
+ const char format[2] = "i";
+ success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeIntUnsigned: {
+ const char format[2] = "I";
+ success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongInt: {
+ const char format[2] = "l";
+ success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongIntUnsigned: {
+ const char format[2] = "k";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLong: {
+ const char format[2] = "L";
+ success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLongUnsigned: {
+ const char format[2] = "K";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeFloat: {
+ const char format[2] = "f";
+ success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeDouble: {
+ const char format[2] = "d";
+ success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeChar: {
+ const char format[2] = "c";
+ success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeOpaqueObject: {
+ success = true;
+ PyObject *saved_value = py_return.get();
+ Py_XINCREF(saved_value);
+ *((PyObject **)ret_value) = saved_value;
+ break;
+ }
+ }
+
+ ret_success = success;
}
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
@@ -1174,10 +1219,8 @@ Status ScriptInterpreterPython::ExecuteMultipleLines(
if (code_object.IsValid()) {
// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it
-// takes
-// a PyObject. They are convertible (hence the function
-// PyCode_Check(PyObject*), so
-// we have to do the cast for Python 2.x
+// takes a PyObject. They are convertible (hence the function
+// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x
#if PY_MAJOR_VERSION >= 3
PyObject *py_code_obj = code_object.get();
#else
@@ -1243,10 +1286,9 @@ Status ScriptInterpreterPython::SetBreakpointCommandCallback(
auto data_ap = llvm::make_unique<CommandDataPython>();
// Split the command_body_text into lines, and pass that to
- // GenerateBreakpointCommandCallbackData. That will
- // wrap the body in an auto-generated function, and return the function name
- // in script_source. That is what
- // the callback will actually invoke.
+ // GenerateBreakpointCommandCallbackData. That will wrap the body in an
+ // auto-generated function, and return the function name in script_source.
+ // That is what the callback will actually invoke.
data_ap->user_source.SplitIntoLines(command_body_text);
Status error = GenerateBreakpointCommandCallbackData(data_ap->user_source,
@@ -1268,9 +1310,8 @@ void ScriptInterpreterPython::SetWatchpointCommandCallback(
// It's necessary to set both user_source and script_source to the oneliner.
// The former is used to generate callback description (as in watchpoint
- // command list)
- // while the latter is used for Python to interpret during the actual
- // callback.
+ // command list) while the latter is used for Python to interpret during the
+ // actual callback.
data_ap->user_source.AppendString(oneliner);
data_ap->script_source.assign(oneliner);
@@ -1365,8 +1406,7 @@ bool ScriptInterpreterPython::GenerateTypeScriptFunction(
return false;
// Take what the user wrote, wrap it all up inside one big auto-generated
- // Python function, passing in the
- // ValueObject as parameter to the function.
+ // Python function, passing in the ValueObject as parameter to the function.
std::string auto_generated_function_name(
GenerateUniqueName("lldb_autogen_python_type_print_func",
@@ -1430,8 +1470,8 @@ bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
sstr.Printf("class %s:", auto_generated_class_name.c_str());
auto_generated_class.AppendString(sstr.GetString());
- // Wrap everything up inside the class, increasing the indentation.
- // we don't need to play any fancy indentation tricks here because there is no
+ // Wrap everything up inside the class, increasing the indentation. we don't
+ // need to play any fancy indentation tricks here because there is no
// surrounding code whose indentation we need to honor
for (int i = 0; i < num_lines; ++i) {
sstr.Clear();
@@ -1439,9 +1479,8 @@ bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
auto_generated_class.AppendString(sstr.GetString());
}
- // Verify that the results are valid Python.
- // (even though the method is ExportFunctionDefinitionToInterpreter, a class
- // will actually be exported)
+ // Verify that the results are valid Python. (even though the method is
+ // ExportFunctionDefinitionToInterpreter, a class will actually be exported)
// (TODO: rename that method to ExportDefinitionToInterpreter)
if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
return false;
@@ -1585,8 +1624,8 @@ StructuredData::ArraySP ScriptInterpreterPython::OSPlugin_ThreadsInfo(
// GetPythonValueFormatString provides a system independent type safe way to
// convert a variable's type into a python value format. Python value formats
-// are defined in terms of builtin C types and could change from system to
-// as the underlying typedef for uint* types, size_t, off_t and other values
+// are defined in terms of builtin C types and could change from system to as
+// the underlying typedef for uint* types, size_t, off_t and other values
// change.
template <typename T> const char *GetPythonValueFormatString(T t);
@@ -2044,8 +2083,7 @@ void ScriptInterpreterPython::Clear() {
ScriptInterpreterPython::Locker::FreeAcquiredLock);
// This may be called as part of Py_Finalize. In that case the modules are
- // destroyed in random
- // order and we can't guarantee that we can access these.
+ // destroyed in random order and we can't guarantee that we can access these.
if (Py_IsInitialized())
PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
"= None; lldb.thread = None; lldb.frame = None");
@@ -2615,9 +2653,9 @@ bool ScriptInterpreterPython::LoadScriptingModule(
// strip .py or .pyc extension
ConstString extension = target_file.GetFileNameExtension();
if (extension) {
- if (::strcmp(extension.GetCString(), "py") == 0)
+ if (llvm::StringRef(extension.GetCString()) == ".py")
basename.resize(basename.length() - 3);
- else if (::strcmp(extension.GetCString(), "pyc") == 0)
+ else if (llvm::StringRef(extension.GetCString()) == ".pyc")
basename.resize(basename.length() - 4);
}
} else {
@@ -2629,9 +2667,8 @@ bool ScriptInterpreterPython::LoadScriptingModule(
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')", basename.c_str());
bool does_contain = false;
- // this call will succeed if the module was ever imported in any Debugger in
- // the lifetime of the process
- // in which this LLDB framework is living
+ // this call will succeed if the module was ever imported in any Debugger
+ // in the lifetime of the process in which this LLDB framework is living
bool was_imported_globally =
(ExecuteOneLineWithReturn(
command_stream.GetData(),
@@ -2705,8 +2742,8 @@ bool ScriptInterpreterPython::IsReservedWord(const char *word) {
llvm::StringRef word_sr(word);
- // filter out a few characters that would just confuse us
- // and that are clearly not keyword material anyway
+ // filter out a few characters that would just confuse us and that are
+ // clearly not keyword material anyway
if (word_sr.find_first_of("'\"") != llvm::StringRef::npos)
return false;
@@ -2740,7 +2777,7 @@ ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() {
}
bool ScriptInterpreterPython::RunScriptBasedCommand(
- const char *impl_function, const char *args,
+ const char *impl_function, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) {
@@ -2774,9 +2811,10 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
SynchronicityHandler synch_handler(debugger_sp, synchronicity);
- ret_val =
- g_swig_call_command(impl_function, m_dictionary_name.c_str(),
- debugger_sp, args, cmd_retobj, exe_ctx_ref_sp);
+ std::string args_str = args.str();
+ ret_val = g_swig_call_command(impl_function, m_dictionary_name.c_str(),
+ debugger_sp, args_str.c_str(), cmd_retobj,
+ exe_ctx_ref_sp);
}
if (!ret_val)
@@ -2788,7 +2826,7 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
}
bool ScriptInterpreterPython::RunScriptBasedCommand(
- StructuredData::GenericSP impl_obj_sp, const char *args,
+ StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) {
@@ -2822,8 +2860,10 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
SynchronicityHandler synch_handler(debugger_sp, synchronicity);
+ std::string args_str = args.str();
ret_val = g_swig_call_command_object(impl_obj_sp->GetValue(), debugger_sp,
- args, cmd_retobj, exe_ctx_ref_sp);
+ args_str.c_str(), cmd_retobj,
+ exe_ctx_ref_sp);
}
if (!ret_val)
@@ -2834,9 +2874,9 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
return ret_val;
}
-// in Python, a special attribute __doc__ contains the docstring
-// for an object (function, method, class, ...) if any is defined
-// Otherwise, the attribute's value is None
+// in Python, a special attribute __doc__ contains the docstring for an object
+// (function, method, class, ...) if any is defined Otherwise, the attribute's
+// value is None
bool ScriptInterpreterPython::GetDocumentationForItem(const char *item,
std::string &dest) {
dest.clear();
@@ -3106,10 +3146,9 @@ void ScriptInterpreterPython::InitializePrivate() {
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
// RAII-based initialization which correctly handles multiple-initialization,
- // version-
- // specific differences among Python 2 and Python 3, and saving and restoring
- // various
- // other pieces of state that can get mucked with during initialization.
+ // version- specific differences among Python 2 and Python 3, and saving and
+ // restoring various other pieces of state that can get mucked with during
+ // initialization.
InitializePythonRAII initialize_guard;
if (g_swig_init_callback)
@@ -3121,17 +3160,13 @@ void ScriptInterpreterPython::InitializePrivate() {
PyRun_SimpleString("import sys");
AddToSysPath(AddLocation::End, ".");
- FileSpec file_spec;
// Don't denormalize paths when calling file_spec.GetPath(). On platforms
- // that use
- // a backslash as the path separator, this will result in executing python
- // code containing
- // paths with unescaped backslashes. But Python also accepts forward slashes,
- // so to make
- // life easier we just use that.
- if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
+ // that use a backslash as the path separator, this will result in executing
+ // python code containing paths with unescaped backslashes. But Python also
+ // accepts forward slashes, so to make life easier we just use that.
+ if (FileSpec file_spec = GetPythonDir())
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
- if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
+ if (FileSpec file_spec = HostInfo::GetShlibDir())
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
PyRun_SimpleString("sys.dont_write_bytecode = 1; import "
@@ -3157,30 +3192,20 @@ void ScriptInterpreterPython::AddToSysPath(AddLocation location,
PyRun_SimpleString(statement.c_str());
}
-// void
-// ScriptInterpreterPython::Terminate ()
-//{
-// // We are intentionally NOT calling Py_Finalize here (this would be the
-// logical place to call it). Calling
-// // Py_Finalize here causes test suite runs to seg fault: The test suite
-// runs in Python. It registers
-// // SBDebugger::Terminate to be called 'at_exit'. When the test suite
-// Python harness finishes up, it calls
-// // Py_Finalize, which calls all the 'at_exit' registered functions.
-// SBDebugger::Terminate calls Debugger::Terminate,
-// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate,
-// which calls
-// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we
-// end up with Py_Finalize being called from
-// // within Py_Finalize, which results in a seg fault.
-// //
-// // Since this function only gets called when lldb is shutting down and
-// going away anyway, the fact that we don't
-// // actually call Py_Finalize should not cause any problems (everything
-// should shut down/go away anyway when the
-// // process exits).
-// //
-//// Py_Finalize ();
-//}
-
-#endif // #ifdef LLDB_DISABLE_PYTHON
+// We are intentionally NOT calling Py_Finalize here (this would be the logical
+// place to call it). Calling Py_Finalize here causes test suite runs to seg
+// fault: The test suite runs in Python. It registers SBDebugger::Terminate to
+// be called 'at_exit'. When the test suite Python harness finishes up, it
+// calls Py_Finalize, which calls all the 'at_exit' registered functions.
+// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,
+// which calls ScriptInterpreter::Terminate, which calls
+// ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end
+// up with Py_Finalize being called from within Py_Finalize, which results in a
+// seg fault. Since this function only gets called when lldb is shutting down
+// and going away anyway, the fact that we don't actually call Py_Finalize
+// should not cause any problems (everything should shut down/go away anyway
+// when the process exits).
+//
+// void ScriptInterpreterPython::Terminate() { Py_Finalize (); }
+
+#endif // LLDB_DISABLE_PYTHON
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index a71fcea7519c..b13979dc069b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -151,14 +151,14 @@ public:
bool Interrupt() override;
bool ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
void ExecuteInterpreterLoop() override;
bool ExecuteOneLineWithReturn(
- const char *in_string, ScriptInterpreter::ScriptReturnType return_type,
- void *ret_value,
+ llvm::StringRef in_string,
+ ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
lldb_private::Status ExecuteMultipleLines(
@@ -259,18 +259,17 @@ public:
GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
bool
- RunScriptBasedCommand(const char *impl_function, const char *args,
+ RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj,
Status &error,
const lldb_private::ExecutionContext &exe_ctx) override;
- bool
- RunScriptBasedCommand(StructuredData::GenericSP impl_obj_sp, const char *args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject &cmd_retobj,
- Status &error,
- const lldb_private::ExecutionContext &exe_ctx) override;
+ bool RunScriptBasedCommand(
+ StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj, Status &error,
+ const lldb_private::ExecutionContext &exe_ctx) override;
Status GenerateFunction(const char *signature,
const StringList &input) override;
@@ -445,6 +444,8 @@ public:
static const char *GetPluginDescriptionStatic();
+ static FileSpec GetPythonDir();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -509,6 +510,10 @@ protected:
static void AddToSysPath(AddLocation location, std::string path);
+ static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path);
+ static void ComputePythonDirForPosix(llvm::SmallVectorImpl<char> &path);
+ static void ComputePythonDirForWindows(llvm::SmallVectorImpl<char> &path);
+
bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
void LeaveSession();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
index ee13b7a5cd1f..f929baade2e4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
@@ -1,5 +1,4 @@
-//===-- lldb-python.h --------------------------------------------*- C++
-//-*-===//
+//===-- lldb-python.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,7 +17,7 @@
// Python is disabled in this build
#else
#include "llvm/Support/Compiler.h"
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We
// need to ensure this doesn't happen. At the same time, Python.h will also try
// to redefine a bunch of stuff that PosixApi.h defines. So define it all now
diff --git a/contrib/llvm/tools/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/contrib/llvm/tools/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index 8424b55ee69c..e33e26507fb1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -23,6 +23,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Property.h"
@@ -184,10 +185,10 @@ const char *const s_filter_attributes[] = {
"message", // message contents, fully expanded
"subsystem" // subsystem of the log message
- // Consider impelmenting this action as it would be cheaper to filter.
- // "message" requires always formatting the message, which is a waste
- // of cycles if it ends up being rejected.
- // "format", // format string used to format message text
+ // Consider implementing this action as it would be cheaper to filter.
+ // "message" requires always formatting the message, which is a waste of
+ // cycles if it ends up being rejected. "format", // format string
+ // used to format message text
};
static const ConstString &GetDarwinLogTypeName() {
@@ -238,11 +239,10 @@ public:
// Indicate whether this is an accept or reject rule.
dict_p->AddBooleanItem("accept", m_accept);
- // Indicate which attribute of the message this filter references.
- // This can drop into the rule-specific DoSerialization if we get
- // to the point where not all FilterRule derived classes work on
- // an attribute. (e.g. logical and/or and other compound
- // operations).
+ // Indicate which attribute of the message this filter references. This can
+ // drop into the rule-specific DoSerialization if we get to the point where
+ // not all FilterRule derived classes work on an attribute. (e.g. logical
+ // and/or and other compound operations).
dict_p->AddStringItem("attribute", s_filter_attributes[m_attribute_index]);
// Indicate the type of the rule.
@@ -403,9 +403,9 @@ static void RegisterFilterOperations() {
// -------------------------------------------------------------------------
static OptionDefinition g_enable_option_table[] = {
- // Source stream include/exclude options (the first-level filter).
- // This one should be made as small as possible as everything that
- // goes through here must be processed by the process monitor.
+ // Source stream include/exclude options (the first-level filter). This one
+ // should be made as small as possible as everything that goes through here
+ // must be processed by the process monitor.
{LLDB_OPT_SET_ALL, false, "any-process", 'a', OptionParser::eNoArgument,
nullptr, nullptr, 0, eArgTypeNone,
"Specifies log messages from other related processes should be "
@@ -419,10 +419,10 @@ static OptionDefinition g_enable_option_table[] = {
"Specifies info-level log messages should be included."},
{LLDB_OPT_SET_ALL, false, "filter", 'f', OptionParser::eRequiredArgument,
nullptr, nullptr, 0, eArgRawInput,
- // There doesn't appear to be a great way for me to have these
- // multi-line, formatted tables in help. This looks mostly right
- // but there are extra linefeeds added at seemingly random spots,
- // and indentation isn't handled properly on those lines.
+ // There doesn't appear to be a great way for me to have these multi-line,
+ // formatted tables in help. This looks mostly right but there are extra
+ // linefeeds added at seemingly random spots, and indentation isn't
+ // handled properly on those lines.
"Appends a filter rule to the log message filter chain. Multiple "
"rules may be added by specifying this option multiple times, "
"once per filter rule. Filter rules are processed in the order "
@@ -488,11 +488,11 @@ static OptionDefinition g_enable_option_table[] = {
"a log message."},
{LLDB_OPT_SET_ALL, false, "category", 'c', OptionParser::eNoArgument,
nullptr, nullptr, 0, eArgTypeNone,
- "Include the category in the the message header when displaying "
+ "Include the category in the message header when displaying "
"a log message."},
{LLDB_OPT_SET_ALL, false, "activity-chain", 'C', OptionParser::eNoArgument,
nullptr, nullptr, 0, eArgTypeNone,
- "Include the activity parent-child chain in the the message header "
+ "Include the activity parent-child chain in the message header "
"when displaying a log message. The activity hierarchy is "
"displayed as {grandparent-activity}:"
"{parent-activity}:{activity}[:...]."},
@@ -544,7 +544,8 @@ public:
break;
case 'b':
- m_broadcast_events = Args::StringToBoolean(option_arg, true, nullptr);
+ m_broadcast_events =
+ OptionArgParser::ToBoolean(option_arg, true, nullptr);
break;
case 'c':
@@ -560,7 +561,7 @@ public:
break;
case 'e':
- m_echo_to_stderr = Args::StringToBoolean(option_arg, false, nullptr);
+ m_echo_to_stderr = OptionArgParser::ToBoolean(option_arg, false, nullptr);
break;
case 'f':
@@ -571,12 +572,12 @@ public:
break;
case 'l':
- m_live_stream = Args::StringToBoolean(option_arg, false, nullptr);
+ m_live_stream = OptionArgParser::ToBoolean(option_arg, false, nullptr);
break;
case 'n':
m_filter_fall_through_accepts =
- Args::StringToBoolean(option_arg, true, nullptr);
+ OptionArgParser::ToBoolean(option_arg, true, nullptr);
break;
case 'r':
@@ -614,7 +615,7 @@ public:
source_flags_sp->AddBooleanItem("any-process", m_include_any_process);
source_flags_sp->AddBooleanItem("debug-level", m_include_debug_level);
- // The debug-level flag, if set, implies info-level.
+ // The debug-level flag, if set, implies info-level.
source_flags_sp->AddBooleanItem("info-level", m_include_info_level ||
m_include_debug_level);
source_flags_sp->AddBooleanItem("live-stream", m_live_stream);
@@ -784,12 +785,11 @@ protected:
if (!source_name)
return;
- // Check if we're *not* using strict sources. If not,
- // then the user is going to get debug-level info
- // anyways, probably not what they're expecting.
- // Unfortunately we can only fix this by adding an
- // env var, which would have had to have happened
- // already. Thus, a warning is the best we can do here.
+ // Check if we're *not* using strict sources. If not, then the user is
+ // going to get debug-level info anyways, probably not what they're
+ // expecting. Unfortunately we can only fix this by adding an env var,
+ // which would have had to have happened already. Thus, a warning is the
+ // best we can do here.
StreamString stream;
stream.Printf("darwin-log source settings specify to exclude "
"%s messages, but setting "
@@ -803,24 +803,22 @@ protected:
}
bool DoExecute(Args &command, CommandReturnObject &result) override {
- // First off, set the global sticky state of enable/disable
- // based on this command execution.
+ // First off, set the global sticky state of enable/disable based on this
+ // command execution.
s_is_explicitly_enabled = m_enable;
- // Next, if this is an enable, save off the option data.
- // We will need it later if a process hasn't been launched or
- // attached yet.
+ // Next, if this is an enable, save off the option data. We will need it
+ // later if a process hasn't been launched or attached yet.
if (m_enable) {
- // Save off enabled configuration so we can apply these parsed
- // options the next time an attach or launch occurs.
+ // Save off enabled configuration so we can apply these parsed options
+ // the next time an attach or launch occurs.
DebuggerSP debugger_sp =
GetCommandInterpreter().GetDebugger().shared_from_this();
SetGlobalEnableOptions(debugger_sp, m_options_sp);
}
- // Now check if we have a running process. If so, we should
- // instruct the process monitor to enable/disable DarwinLog support
- // now.
+ // Now check if we have a running process. If so, we should instruct the
+ // process monitor to enable/disable DarwinLog support now.
Target *target = GetSelectedOrDummyTarget();
if (!target) {
// No target, so there is nothing more to do right now.
@@ -831,14 +829,13 @@ protected:
// Grab the active process.
auto process_sp = target->GetProcessSP();
if (!process_sp) {
- // No active process, so there is nothing more to do right
- // now.
+ // No active process, so there is nothing more to do right now.
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
}
- // If the process is no longer alive, we can't do this now.
- // We'll catch it the next time the process is started up.
+ // If the process is no longer alive, we can't do this now. We'll catch it
+ // the next time the process is started up.
if (!process_sp->IsAlive()) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
@@ -857,19 +854,17 @@ protected:
*static_cast<StructuredDataDarwinLog *>(plugin_sp.get());
if (m_enable) {
- // Hook up the breakpoint for the process that detects when
- // libtrace has been sufficiently initialized to really start
- // the os_log stream. This is insurance to assure us that
- // logging is really enabled. Requesting that logging be
- // enabled for a process before libtrace is initialized
- // results in a scenario where no errors occur, but no logging
- // is captured, either. This step is to eliminate that
- // possibility.
+ // Hook up the breakpoint for the process that detects when libtrace has
+ // been sufficiently initialized to really start the os_log stream. This
+ // is insurance to assure us that logging is really enabled. Requesting
+ // that logging be enabled for a process before libtrace is initialized
+ // results in a scenario where no errors occur, but no logging is
+ // captured, either. This step is to eliminate that possibility.
plugin.AddInitCompletionHook(*process_sp.get());
}
- // Send configuration to the feature by way of the process.
- // Construct the options we will use.
+ // Send configuration to the feature by way of the process. Construct the
+ // options we will use.
auto config_sp = m_options_sp->BuildConfigurationData(m_enable);
const Status error =
process_sp->ConfigureStructuredData(GetDarwinLogTypeName(), config_sp);
@@ -882,8 +877,8 @@ protected:
plugin.SetEnabled(false);
} else {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
- // Our configuration succeeeded, so we're enabled/disabled
- // per whichever one this command is setup to do.
+ // Our configuration succeeded, so we're enabled/disabled per whichever
+ // one this command is setup to do.
plugin.SetEnabled(m_enable);
}
return result.Succeeded();
@@ -914,8 +909,8 @@ protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
auto &stream = result.GetOutputStream();
- // Figure out if we've got a process. If so, we can tell if
- // DarwinLog is available for that process.
+ // Figure out if we've got a process. If so, we can tell if DarwinLog is
+ // available for that process.
Target *target = GetSelectedOrDummyTarget();
auto process_sp = target ? target->GetProcessSP() : ProcessSP();
if (!target || !process_sp) {
@@ -1013,13 +1008,13 @@ public:
};
EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
- // We are abusing the options data model here so that we can parse
- // options without requiring the Debugger instance.
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS);
+ // We are abusing the options data model here so that we can parse options
+ // without requiring the Debugger instance.
- // We have an empty execution context at this point. We only want
- // to parse options, and we don't need any context to do this here.
- // In fact, we want to be able to parse the enable options before having
- // any context.
+ // We have an empty execution context at this point. We only want to parse
+ // options, and we don't need any context to do this here. In fact, we want
+ // to be able to parse the enable options before having any context.
ExecutionContext exe_ctx;
EnableOptionsSP options_sp(new EnableOptions());
@@ -1044,22 +1039,23 @@ EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
options_property_sp->GetAsString()->GetCurrentValue();
Args args(enable_options);
if (args.GetArgumentCount() > 0) {
- // Eliminate the initial '--' that would be required to set the
- // settings that themselves include '-' and/or '--'.
+ // Eliminate the initial '--' that would be required to set the settings
+ // that themselves include '-' and/or '--'.
const char *first_arg = args.GetArgumentAtIndex(0);
if (first_arg && (strcmp(first_arg, "--") == 0))
args.Shift();
}
- // ParseOptions calls getopt_long_only, which always skips the zero'th item in
- // the array and starts at position 1,
- // so we need to push a dummy value into position zero.
- args.Unshift(llvm::StringRef("dummy_string"));
bool require_validation = false;
- error = args.ParseOptions(*options_sp.get(), &exe_ctx, PlatformSP(),
- require_validation);
- if (!error.Success())
+ llvm::Expected<Args> args_or =
+ options_sp->Parse(args, &exe_ctx, PlatformSP(), require_validation);
+ if (!args_or) {
+ LLDB_LOG_ERROR(
+ log, args_or.takeError(),
+ "Parsing plugin.structured-data.darwin-log.auto-enable-options value "
+ "failed: {0}");
return EnableOptionsSP();
+ }
if (!options_sp->VerifyOptions(result))
return EnableOptionsSP();
@@ -1168,9 +1164,9 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData(
return;
}
- // Broadcast the structured data event if we have that enabled.
- // This is the way that the outside world (all clients) get access
- // to this data. This plugin sets policy as to whether we do that.
+ // Broadcast the structured data event if we have that enabled. This is the
+ // way that the outside world (all clients) get access to this data. This
+ // plugin sets policy as to whether we do that.
DebuggerSP debugger_sp = process.GetTarget().GetDebugger().shared_from_this();
auto options_sp = GetGlobalEnableOptions(debugger_sp);
if (options_sp && options_sp->GetBroadcastEvents()) {
@@ -1180,8 +1176,8 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData(
process.BroadcastStructuredData(object_sp, shared_from_this());
}
- // Later, hang on to a configurable amount of these and allow commands
- // to inspect, including showing backtraces.
+ // Later, hang on to a configurable amount of these and allow commands to
+ // inspect, including showing backtraces.
}
static void SetErrorWithJSON(Status &error, const char *message,
@@ -1257,8 +1253,8 @@ Status StructuredDataDarwinLog::GetDescription(
return false;
}
- // If we haven't already grabbed the first timestamp
- // value, do that now.
+ // If we haven't already grabbed the first timestamp value, do that
+ // now.
if (!m_recorded_first_timestamp) {
uint64_t timestamp = 0;
if (event->GetValueForKeyAsInteger("timestamp", timestamp)) {
@@ -1296,8 +1292,8 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
// Check if we should enable the darwin log support on startup/attach.
if (!GetGlobalProperties()->GetEnableOnStartup() &&
!s_is_explicitly_enabled) {
- // We're neither auto-enabled or explicitly enabled, so we shouldn't
- // try to enable here.
+ // We're neither auto-enabled or explicitly enabled, so we shouldn't try to
+ // enable here.
if (log)
log->Printf("StructuredDataDarwinLog::%s not applicable, we're not "
"enabled (process uid %u)",
@@ -1317,9 +1313,9 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
}
}
- // The logging support module name, specifies the name of
- // the image name that must be loaded into the debugged process before
- // we can try to enable logging.
+ // The logging support module name, specifies the name of the image name that
+ // must be loaded into the debugged process before we can try to enable
+ // logging.
const char *logging_module_cstr =
GetGlobalProperties()->GetLoggingModuleName();
if (!logging_module_cstr || (logging_module_cstr[0] == 0)) {
@@ -1359,8 +1355,8 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
return;
}
- // Time to enqueue the breakpoint so we can wait for logging support
- // to be initialized before we try to tap the libtrace stream.
+ // Time to enqueue the breakpoint so we can wait for logging support to be
+ // initialized before we try to tap the libtrace stream.
AddInitCompletionHook(process);
if (log)
log->Printf("StructuredDataDarwinLog::%s post-init hook breakpoint "
@@ -1368,13 +1364,13 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
__FUNCTION__, logging_module_name.AsCString(),
process.GetUniqueID());
- // We need to try the enable here as well, which will succeed
- // in the event that we're attaching to (rather than launching) the
- // process and the process is already past initialization time. In that
- // case, the completion breakpoint will never get hit and therefore won't
- // start that way. It doesn't hurt much beyond a bit of bandwidth
- // if we end up doing this twice. It hurts much more if we don't get
- // the logging enabled when the user expects it.
+ // We need to try the enable here as well, which will succeed in the event
+ // that we're attaching to (rather than launching) the process and the
+ // process is already past initialization time. In that case, the completion
+ // breakpoint will never get hit and therefore won't start that way. It
+ // doesn't hurt much beyond a bit of bandwidth if we end up doing this twice.
+ // It hurts much more if we don't get the logging enabled when the user
+ // expects it.
EnableNow();
}
@@ -1411,8 +1407,7 @@ StructuredDataDarwinLog::StructuredDataDarwinLog(const ProcessWP &process_wp)
StructuredDataPluginSP
StructuredDataDarwinLog::CreateInstance(Process &process) {
- // Currently only Apple targets support the os_log/os_activity
- // protocol.
+ // Currently only Apple targets support the os_log/os_activity protocol.
if (process.GetTarget().GetArchitecture().GetTriple().getVendor() ==
llvm::Triple::VendorType::Apple) {
auto process_wp = ProcessWP(process.shared_from_this());
@@ -1459,20 +1454,20 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
Target *target) {
Status error;
- // If we're not debugging this launched process, there's nothing for us
- // to do here.
+ // If we're not debugging this launched process, there's nothing for us to do
+ // here.
if (!launch_info.GetFlags().AnySet(eLaunchFlagDebug))
return error;
// Darwin os_log() support automatically adds debug-level and info-level
// messages when a debugger is attached to a process. However, with
- // integrated suppport for debugging built into the command-line LLDB,
- // the user may specifically set to *not* include debug-level and info-level
- // content. When the user is using the integrated log support, we want
- // to put the kabosh on that automatic adding of info and debug level.
- // This is done by adding an environment variable to the process on launch.
- // (This also means it is not possible to suppress this behavior if
- // attaching to an already-running app).
+ // integrated support for debugging built into the command-line LLDB, the
+ // user may specifically set to *not* include debug-level and info-level
+ // content. When the user is using the integrated log support, we want to
+ // put the kabosh on that automatic adding of info and debug level. This is
+ // done by adding an environment variable to the process on launch. (This
+ // also means it is not possible to suppress this behavior if attaching to an
+ // already-running app).
// Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
// If the target architecture is not one that supports DarwinLog, we have
@@ -1483,20 +1478,19 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
return error;
}
- // If DarwinLog is not enabled (either by explicit user command or via
- // the auto-enable option), then we have nothing to do.
+ // If DarwinLog is not enabled (either by explicit user command or via the
+ // auto-enable option), then we have nothing to do.
if (!GetGlobalProperties()->GetEnableOnStartup() &&
!s_is_explicitly_enabled) {
// Nothing to do, DarwinLog is not enabled.
return error;
}
- // If we don't have parsed configuration info, that implies we have
- // enable-on-startup set up, but we haven't yet attempted to run the
- // enable command.
+ // If we don't have parsed configuration info, that implies we have enable-
+ // on-startup set up, but we haven't yet attempted to run the enable command.
if (!target) {
- // We really can't do this without a target. We need to be able
- // to get to the debugger to get the proper options to do this right.
+ // We really can't do this without a target. We need to be able to get to
+ // the debugger to get the proper options to do this right.
// TODO log.
error.SetErrorString("requires a target to auto-enable DarwinLog.");
return error;
@@ -1509,34 +1503,28 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
if (!options_sp || !error.Success())
return error;
- // We already parsed the options, save them now so we don't generate
- // them again until the user runs the command manually.
+ // We already parsed the options, save them now so we don't generate them
+ // again until the user runs the command manually.
SetGlobalEnableOptions(debugger_sp, options_sp);
}
- auto &env_vars = launch_info.GetEnvironmentEntries();
if (!options_sp->GetEchoToStdErr()) {
- // The user doesn't want to see os_log/NSLog messages echo to stderr.
- // That mechanism is entirely separate from the DarwinLog support.
- // By default we don't want to get it via stderr, because that would
- // be in duplicate of the explicit log support here.
+ // The user doesn't want to see os_log/NSLog messages echo to stderr. That
+ // mechanism is entirely separate from the DarwinLog support. By default we
+ // don't want to get it via stderr, because that would be in duplicate of
+ // the explicit log support here.
// Here we need to strip out any OS_ACTIVITY_DT_MODE setting to prevent
// echoing of os_log()/NSLog() to stderr in the target program.
- size_t argument_index;
- if (env_vars.ContainsEnvironmentVariable(
- llvm::StringRef("OS_ACTIVITY_DT_MODE"), &argument_index))
- env_vars.DeleteArgumentAtIndex(argument_index);
+ launch_info.GetEnvironment().erase("OS_ACTIVITY_DT_MODE");
- // We will also set the env var that tells any downstream launcher
- // from adding OS_ACTIVITY_DT_MODE.
- env_vars.AddOrReplaceEnvironmentVariable(
- llvm::StringRef("IDE_DISABLED_OS_ACTIVITY_DT_MODE"),
- llvm::StringRef("1"));
+ // We will also set the env var that tells any downstream launcher from
+ // adding OS_ACTIVITY_DT_MODE.
+ launch_info.GetEnvironment()["IDE_DISABLED_OS_ACTIVITY_DT_MODE"] = "1";
}
- // Set the OS_ACTIVITY_MODE env var appropriately to enable/disable
- // debug and info level messages.
+ // Set the OS_ACTIVITY_MODE env var appropriately to enable/disable debug and
+ // info level messages.
const char *env_var_value;
if (options_sp->GetIncludeDebugLevel())
env_var_value = "debug";
@@ -1545,10 +1533,7 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
else
env_var_value = "default";
- if (env_var_value) {
- launch_info.GetEnvironmentEntries().AddOrReplaceEnvironmentVariable(
- llvm::StringRef("OS_ACTIVITY_MODE"), llvm::StringRef(env_var_value));
- }
+ launch_info.GetEnvironment()["OS_ACTIVITY_MODE"] = env_var_value;
return error;
}
@@ -1558,8 +1543,8 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback(
lldb::user_id_t break_loc_id) {
// We hit the init function. We now want to enqueue our new thread plan,
// which will in turn enqueue a StepOut thread plan. When the StepOut
- // finishes and control returns to our new thread plan, that is the time
- // when we can execute our logic to enable the logging support.
+ // finishes and control returns to our new thread plan, that is the time when
+ // we can execute our logic to enable the logging support.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
@@ -1618,8 +1603,8 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback(
process_uid);
return;
}
- // Make sure we only call it once, just in case the
- // thread plan hits the breakpoint twice.
+ // Make sure we only call it once, just in case the thread plan hits
+ // the breakpoint twice.
if (!called_enable_method) {
if (log)
log->Printf("StructuredDataDarwinLog::post-init callback: "
@@ -1629,8 +1614,8 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback(
->EnableNow();
called_enable_method = true;
} else {
- // Our breakpoint was hit more than once. Unexpected but
- // no harm done. Log it.
+ // Our breakpoint was hit more than once. Unexpected but no harm
+ // done. Log it.
if (log)
log->Printf("StructuredDataDarwinLog::post-init callback: "
"skipping EnableNow(), already called by "
@@ -1687,8 +1672,8 @@ void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) {
m_added_breakpoint = true;
}
- // Set a breakpoint for the process that will kick in when libtrace
- // has finished its initialization.
+ // Set a breakpoint for the process that will kick in when libtrace has
+ // finished its initialization.
Target &target = process.GetTarget();
// Build up the module list.
@@ -1793,8 +1778,8 @@ StructuredDataDarwinLog::DumpHeader(Stream &output_stream,
if (header_count > 0)
stream.PutChar(',');
- // Display the activity chain, from parent-most to child-most
- // activity, separated by a colon (:).
+ // Display the activity chain, from parent-most to child-most activity,
+ // separated by a colon (:).
stream.PutCString("activity-chain=");
stream.PutCString(activity_chain);
++header_count;
@@ -1836,8 +1821,8 @@ size_t StructuredDataDarwinLog::HandleDisplayOfEvent(
// Check the type of the event.
ConstString event_type;
if (!event.GetValueForKeyAsString("type", event_type)) {
- // Hmm, we expected to get events that describe
- // what they are. Continue anyway.
+ // Hmm, we expected to get events that describe what they are. Continue
+ // anyway.
return 0;
}
@@ -1885,10 +1870,10 @@ void StructuredDataDarwinLog::EnableNow() {
log->Printf("StructuredDataDarwinLog::%s() call is for process uid %u",
__FUNCTION__, process_sp->GetUniqueID());
- // If we have configuration data, we can directly enable it now.
- // Otherwise, we need to run through the command interpreter to parse
- // the auto-run options (which is the only way we get here without having
- // already-parsed configuration data).
+ // If we have configuration data, we can directly enable it now. Otherwise,
+ // we need to run through the command interpreter to parse the auto-run
+ // options (which is the only way we get here without having already-parsed
+ // configuration data).
DebuggerSP debugger_sp =
process_sp->GetTarget().GetDebugger().shared_from_this();
if (!debugger_sp) {
@@ -1901,8 +1886,8 @@ void StructuredDataDarwinLog::EnableNow() {
auto options_sp = GetGlobalEnableOptions(debugger_sp);
if (!options_sp) {
- // We haven't run the enable command yet. Just do that now, it'll
- // take care of the rest.
+ // We haven't run the enable command yet. Just do that now, it'll take
+ // care of the rest.
auto &interpreter = debugger_sp->GetCommandInterpreter();
const bool success = RunEnableCommand(interpreter);
if (log) {
@@ -1925,8 +1910,8 @@ void StructuredDataDarwinLog::EnableNow() {
return;
}
- // We've previously been enabled. We will re-enable now with the
- // previously specified options.
+ // We've previously been enabled. We will re-enable now with the previously
+ // specified options.
auto config_sp = options_sp->BuildConfigurationData(true);
if (!config_sp) {
if (log)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
new file mode 100644
index 000000000000..db75cf9c3bb3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
@@ -0,0 +1,177 @@
+//===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Function.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
+ Module &module, DWARFDataExtractor apple_names,
+ DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
+ DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
+ auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_names, debug_str, ".apple_names");
+ if (!apple_names_table_up->IsValid())
+ apple_names_table_up.reset();
+
+ auto apple_namespaces_table_up =
+ llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_namespaces, debug_str, ".apple_namespaces");
+ if (!apple_namespaces_table_up->IsValid())
+ apple_namespaces_table_up.reset();
+
+ auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_types, debug_str, ".apple_types");
+ if (!apple_types_table_up->IsValid())
+ apple_types_table_up.reset();
+
+ auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_objc, debug_str, ".apple_objc");
+ if (!apple_objc_table_up->IsValid())
+ apple_objc_table_up.reset();
+
+ if (apple_names_table_up || apple_names_table_up || apple_types_table_up ||
+ apple_objc_table_up)
+ return llvm::make_unique<AppleDWARFIndex>(
+ module, std::move(apple_names_table_up),
+ std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
+ std::move(apple_objc_table_up));
+
+ return nullptr;
+}
+
+void AppleDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) {
+ if (m_apple_names_up)
+ m_apple_names_up->FindByName(basename.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) {
+ if (!m_apple_names_up)
+ return;
+
+ DWARFMappedHash::DIEInfoArray hash_data;
+ if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
+ DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
+}
+
+void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
+ DIEArray &offsets) {
+ if (!m_apple_names_up)
+ return;
+
+ DWARFMappedHash::DIEInfoArray hash_data;
+ if (m_apple_names_up->AppendAllDIEsInRange(
+ cu.GetOffset(), cu.GetNextCompileUnitOffset(), hash_data))
+ DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
+}
+
+void AppleDWARFIndex::GetObjCMethods(ConstString class_name,
+ DIEArray &offsets) {
+ if (m_apple_objc_up)
+ m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) {
+ if (m_apple_types_up) {
+ m_apple_types_up->FindCompleteObjCClassByName(
+ class_name.GetStringRef(), offsets, must_be_implementation);
+ }
+}
+
+void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
+ if (m_apple_types_up)
+ m_apple_types_up->FindByName(name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context,
+ DIEArray &offsets) {
+ if (!m_apple_types_up)
+ return;
+
+ Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS);
+ const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
+ DWARFMappedHash::eAtomTypeTag);
+ const bool has_qualified_name_hash =
+ m_apple_types_up->GetHeader().header_data.ContainsAtom(
+ DWARFMappedHash::eAtomTypeQualNameHash);
+ const ConstString type_name(context[0].name);
+ const dw_tag_t tag = context[0].tag;
+ if (has_tag && has_qualified_name_hash) {
+ const char *qualified_name = context.GetQualifiedName();
+ const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
+ if (log)
+ m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
+ m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
+ type_name.GetStringRef(), tag, qualified_name_hash, offsets);
+ } else if (has_tag) {
+ if (log)
+ m_module.LogMessage(log, "FindByNameAndTag()");
+ m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets);
+ } else
+ m_apple_types_up->FindByName(type_name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
+ if (m_apple_namespaces_up)
+ m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+ DIEArray offsets;
+ m_apple_names_up->FindByName(name.GetStringRef(), offsets);
+ for (const DIERef &die_ref : offsets) {
+ ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx,
+ name_type_mask, dies);
+ }
+}
+
+void AppleDWARFIndex::GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) {
+ if (!m_apple_names_up)
+ return;
+
+ DWARFMappedHash::DIEInfoArray hash_data;
+ if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
+ DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
+}
+
+void AppleDWARFIndex::ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) {
+ m_module.ReportErrorIfModifyDetected(
+ "the DWARF debug information has been modified (accelerator table had "
+ "bad die 0x%8.8x for '%s')\n",
+ offset, name.str().c_str());
+}
+
+void AppleDWARFIndex::Dump(Stream &s) {
+ if (m_apple_names_up)
+ s.PutCString(".apple_names index present\n");
+ if (m_apple_namespaces_up)
+ s.PutCString(".apple_namespaces index present\n");
+ if (m_apple_types_up)
+ s.PutCString(".apple_types index present\n");
+ if (m_apple_objc_up)
+ s.PutCString(".apple_objc index present\n");
+ // TODO: Dump index contents
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
new file mode 100644
index 000000000000..ea133d0e73cf
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
@@ -0,0 +1,64 @@
+//===-- AppleDWARFIndex.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_APPLEDWARFINDEX_H
+#define LLDB_APPLEDWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/HashedNameToDIE.h"
+
+namespace lldb_private {
+class AppleDWARFIndex : public DWARFIndex {
+public:
+ static std::unique_ptr<AppleDWARFIndex>
+ Create(Module &module, DWARFDataExtractor apple_names,
+ DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
+ DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str);
+
+ AppleDWARFIndex(
+ Module &module, std::unique_ptr<DWARFMappedHash::MemoryTable> apple_names,
+ std::unique_ptr<DWARFMappedHash::MemoryTable> apple_namespaces,
+ std::unique_ptr<DWARFMappedHash::MemoryTable> apple_types,
+ std::unique_ptr<DWARFMappedHash::MemoryTable> apple_objc)
+ : DWARFIndex(module), m_apple_names_up(std::move(apple_names)),
+ m_apple_namespaces_up(std::move(apple_namespaces)),
+ m_apple_types_up(std::move(apple_types)),
+ m_apple_objc_up(std::move(apple_objc)) {}
+
+ void Preload() override {}
+
+ void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
+ void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) override;
+ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override;
+ void GetObjCMethods(ConstString class_name, DIEArray &offsets) override;
+ void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation,
+ DIEArray &offsets) override;
+ void GetTypes(ConstString name, DIEArray &offsets) override;
+ void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
+ void GetNamespaces(ConstString name, DIEArray &offsets) override;
+ void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) override;
+ void GetFunctions(const RegularExpression &regex, DIEArray &offsets) override;
+
+ void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) override;
+ void Dump(Stream &s) override;
+
+private:
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_names_up;
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_up;
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_up;
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_up;
+};
+} // namespace lldb_private
+
+#endif // LLDB_APPLEDWARFINDEX_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
index c05444c031e6..0cd0f0c0272a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -8,17 +8,12 @@
//===----------------------------------------------------------------------===//
#include "DIERef.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFFormValue.h"
#include "SymbolFileDWARF.h"
#include "SymbolFileDWARFDebugMap.h"
-DIERef::DIERef()
- : cu_offset(DW_INVALID_OFFSET), die_offset(DW_INVALID_OFFSET) {}
-
-DIERef::DIERef(dw_offset_t c, dw_offset_t d) : cu_offset(c), die_offset(d) {}
-
DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf)
: cu_offset(DW_INVALID_OFFSET), die_offset(uid & 0xffffffff) {
SymbolFileDWARFDebugMap *debug_map = dwarf->GetDebugMapSymfile();
@@ -28,7 +23,7 @@ DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf)
if (actual_dwarf) {
DWARFDebugInfo *debug_info = actual_dwarf->DebugInfo();
if (debug_info) {
- DWARFCompileUnit *dwarf_cu =
+ DWARFUnit *dwarf_cu =
debug_info->GetCompileUnitContainingDIEOffset(die_offset);
if (dwarf_cu) {
cu_offset = dwarf_cu->GetOffset();
@@ -45,7 +40,7 @@ DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf)
DIERef::DIERef(const DWARFFormValue &form_value)
: cu_offset(DW_INVALID_OFFSET), die_offset(DW_INVALID_OFFSET) {
if (form_value.IsValid()) {
- const DWARFCompileUnit *dwarf_cu = form_value.GetCompileUnit();
+ const DWARFUnit *dwarf_cu = form_value.GetCompileUnit();
if (dwarf_cu) {
if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
cu_offset = dwarf_cu->GetBaseObjOffset();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h
index d0048d0f6d6b..cb28c890c25a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h
@@ -17,9 +17,9 @@ class DWARFFormValue;
class SymbolFileDWARF;
struct DIERef {
- DIERef();
+ DIERef() = default;
- DIERef(dw_offset_t c, dw_offset_t d);
+ DIERef(dw_offset_t c, dw_offset_t d) : cu_offset(c), die_offset(d) {}
//----------------------------------------------------------------------
// In order to properly decode a lldb::user_id_t back into a DIERef we
@@ -45,8 +45,12 @@ struct DIERef {
bool operator<(const DIERef &ref) { return die_offset < ref.die_offset; }
- dw_offset_t cu_offset;
- dw_offset_t die_offset;
+ explicit operator bool() const {
+ return cu_offset != DW_INVALID_OFFSET || die_offset != DW_INVALID_OFFSET;
+ }
+
+ dw_offset_t cu_offset = DW_INVALID_OFFSET;
+ dw_offset_t die_offset = DW_INVALID_OFFSET;
};
typedef std::vector<DIERef> DIEArray;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 54b12cfb3b8c..fe6f1be3ca48 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -10,13 +10,13 @@
#include <stdlib.h>
#include "DWARFASTParserClang.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDefines.h"
#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
#include "UniqueDWARFASTType.h"
@@ -24,7 +24,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
@@ -39,8 +38,10 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include <map>
#include <vector>
@@ -105,9 +106,9 @@ struct BitfieldInfo {
bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
if (IsValid()) {
- // This bitfield info is valid, so any subsequent bitfields
- // must not overlap and must be at a higher bit offset than
- // any previous bitfield + size.
+ // This bitfield info is valid, so any subsequent bitfields must not
+ // overlap and must be at a higher bit offset than any previous bitfield
+ // + size.
return (bit_size + bit_offset) <= next_bit_offset;
} else {
// If the this BitfieldInfo is not valid, then any offset isOK
@@ -123,57 +124,108 @@ ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {
return *m_clang_ast_importer_ap;
}
+/// Detect a forward declaration that is nested in a DW_TAG_module.
+static bool isClangModuleFwdDecl(const DWARFDIE &Die) {
+ if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
+ return false;
+ auto Parent = Die.GetParent();
+ while (Parent.IsValid()) {
+ if (Parent.Tag() == DW_TAG_module)
+ return true;
+ Parent = Parent.GetParent();
+ }
+ return false;
+}
+
TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
ModuleSP dwo_module_sp = die.GetContainingDWOModule();
- if (dwo_module_sp) {
- // This type comes from an external DWO module
- std::vector<CompilerContext> dwo_context;
- die.GetDWOContext(dwo_context);
- TypeMap dwo_types;
- if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true,
- dwo_types)) {
- const size_t num_dwo_types = dwo_types.GetSize();
- if (num_dwo_types == 1) {
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
- TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
- if (dwo_type_sp) {
- lldb_private::CompilerType dwo_type =
- dwo_type_sp->GetForwardCompilerType();
-
- lldb_private::CompilerType type =
- GetClangASTImporter().CopyType(m_ast, dwo_type);
-
- // printf ("copied_qual_type: ast = %p, clang_type = %p, name =
- // '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(),
- // external_type->GetName().GetCString());
- if (type) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- TypeSP type_sp(new Type(die.GetID(), dwarf, dwo_type_sp->GetName(),
- dwo_type_sp->GetByteSize(), NULL,
- LLDB_INVALID_UID, Type::eEncodingInvalid,
- &dwo_type_sp->GetDeclaration(), type,
- Type::eResolveStateForward));
-
- dwarf->GetTypeList()->Insert(type_sp);
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
- if (tag_decl)
- LinkDeclContextToDIE(tag_decl, die);
- else {
- clang::DeclContext *defn_decl_ctx =
- GetCachedClangDeclContextForDIE(die);
- if (defn_decl_ctx)
- LinkDeclContextToDIE(defn_decl_ctx, die);
- }
- return type_sp;
- }
- }
- }
+ if (!dwo_module_sp)
+ return TypeSP();
+
+ // This type comes from an external DWO module.
+ std::vector<CompilerContext> dwo_context;
+ die.GetDWOContext(dwo_context);
+ TypeMap dwo_types;
+
+ if (!dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true,
+ dwo_types)) {
+ if (!isClangModuleFwdDecl(die))
+ return TypeSP();
+
+ // Since this this type is defined in one of the Clang modules imported by
+ // this symbol file, search all of them.
+ auto *SymFile = die.GetCU()->GetSymbolFileDWARF();
+ for (const auto &NameModule : SymFile->getExternalTypeModules()) {
+ if (!NameModule.second)
+ continue;
+ SymbolVendor *SymVendor = NameModule.second->GetSymbolVendor();
+ if (SymVendor->FindTypes(dwo_context, true, dwo_types))
+ break;
}
}
- return TypeSP();
+
+ const size_t num_dwo_types = dwo_types.GetSize();
+ if (num_dwo_types != 1)
+ return TypeSP();
+
+ // We found a real definition for this type in the Clang module, so lets use
+ // it and cache the fact that we found a complete type for this die.
+ TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
+ if (!dwo_type_sp)
+ return TypeSP();
+
+ lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
+
+ lldb_private::CompilerType type =
+ GetClangASTImporter().CopyType(m_ast, dwo_type);
+
+ if (!type)
+ return TypeSP();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ TypeSP type_sp(new Type(
+ die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(),
+ NULL, LLDB_INVALID_UID, Type::eEncodingInvalid,
+ &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward));
+
+ dwarf->GetTypeList()->Insert(type_sp);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
+ if (tag_decl)
+ LinkDeclContextToDIE(tag_decl, die);
+ else {
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ }
+
+ return type_sp;
+}
+
+static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
+ clang::DeclContext *decl_ctx,
+ DWARFDIE die,
+ const char *type_name_cstr) {
+ auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
+ if (!tag_decl_ctx)
+ return;
+
+ // If this type was not imported from an external AST, there's nothing to do.
+ CompilerType type = ClangASTContext::GetTypeForDecl(tag_decl_ctx);
+ if (!type || !ast_importer.CanImport(type))
+ return;
+
+ auto qual_type = ClangUtil::GetQualType(type);
+ if (!ast_importer.RequireCompleteType(qual_type)) {
+ die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(
+ "Unable to complete the Decl context for DIE '%s' at offset "
+ "0x%8.8x.\nPlease file a bug report.",
+ type_name_cstr ? type_name_cstr : "", die.GetOffset());
+ // We need to make the type look complete otherwise, we might crash in
+ // Clang when adding children.
+ if (ClangASTContext::StartTagDeclarationDefinition(type))
+ ClangASTContext::CompleteTagDeclarationDefinition(type);
+ }
}
TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
@@ -198,17 +250,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
die.GetOffset(), static_cast<void *>(context),
context_die.GetOffset(), die.GetTagAsCString(), die.GetName());
}
- //
- // Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- // if (log && dwarf_cu)
- // {
- // StreamString s;
- // die->DumpLocation (this, dwarf_cu, s);
- // dwarf->GetObjectFile()->GetModule()->LogMessage (log,
- // "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
- //
- // }
-
Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
TypeList *type_list = dwarf->GetTypeList();
if (type_ptr == NULL) {
@@ -220,6 +261,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
bool is_forward_declaration = false;
DWARFAttributes attributes;
const char *type_name_cstr = NULL;
+ const char *mangled_name_cstr = NULL;
ConstString type_name_const_str;
Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
uint64_t byte_size = 0;
@@ -268,8 +310,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_name_cstr = form_value.AsCString();
// Work around a bug in llvm-gcc where they give a name to a
- // reference type which doesn't
- // include the "&"...
+ // reference type which doesn't include the "&"...
if (tag == DW_TAG_reference_type) {
if (strchr(type_name_cstr, '&') == NULL)
type_name_cstr = NULL;
@@ -295,32 +336,32 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (tag == DW_TAG_typedef && encoding_uid.IsValid()) {
- // Try to parse a typedef from the DWO file first as modules
- // can contain typedef'ed structures that have no names like:
+ // Try to parse a typedef from the DWO file first as modules can
+ // contain typedef'ed structures that have no names like:
//
// typedef struct { int a; } Foo;
//
- // In this case we will have a structure with no name and a
- // typedef named "Foo" that points to this unnamed structure.
- // The name in the typedef is the only identifier for the struct,
- // so always try to get typedefs from DWO files if possible.
+ // In this case we will have a structure with no name and a typedef
+ // named "Foo" that points to this unnamed structure. The name in the
+ // typedef is the only identifier for the struct, so always try to
+ // get typedefs from DWO files if possible.
//
- // The type_sp returned will be empty if the typedef doesn't exist
- // in a DWO file, so it is cheap to call this function just to check.
+ // The type_sp returned will be empty if the typedef doesn't exist in
+ // a DWO file, so it is cheap to call this function just to check.
//
- // If we don't do this we end up creating a TypeSP that says this
- // is a typedef to type 0x123 (the DW_AT_type value would be 0x123
- // in the DW_TAG_typedef), and this is the unnamed structure type.
- // We will have a hard time tracking down an unnammed structure
- // type in the module DWO file, so we make sure we don't get into
- // this situation by always resolving typedefs from the DWO file.
+ // If we don't do this we end up creating a TypeSP that says this is
+ // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in
+ // the DW_TAG_typedef), and this is the unnamed structure type. We
+ // will have a hard time tracking down an unnammed structure type in
+ // the module DWO file, so we make sure we don't get into this
+ // situation by always resolving typedefs from the DWO file.
const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid));
- // First make sure that the die that this is typedef'ed to _is_
- // just a declaration (DW_AT_declaration == 1), not a full definition
+ // First make sure that the die that this is typedef'ed to _is_ just
+ // a declaration (DW_AT_declaration == 1), not a full definition
// since template types can't be represented in modules since only
- // concrete instances of templates are ever emitted and modules
- // won't contain those
+ // concrete instances of templates are ever emitted and modules won't
+ // contain those
if (encoding_die &&
encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) ==
1) {
@@ -433,7 +474,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective C 'id' built-in type.",
+ "is Objective-C 'id' built-in type.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
encoding_data_type = Type::eEncodingIsUID;
@@ -444,7 +485,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective C 'Class' built-in type.",
+ "is Objective-C 'Class' built-in type.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
encoding_data_type = Type::eEncodingIsUID;
@@ -454,7 +495,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective C 'selector' built-in type.",
+ "is Objective-C 'selector' built-in type.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
encoding_data_type = Type::eEncodingIsUID;
@@ -495,17 +536,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
&decl, clang_type, resolve_state));
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
-
- // Type* encoding_type =
- // GetUniquedTypeForDIEOffset(encoding_uid, type_sp,
- // NULL, 0, 0, false);
- // if (encoding_type != NULL)
- // {
- // if (encoding_type != DIE_IS_BEING_PARSED)
- // type_sp->SetEncodingType(encoding_type);
- // else
- // m_indirect_fixups.push_back(type_sp.get());
- // }
} break;
case DW_TAG_structure_type:
@@ -517,7 +547,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
LanguageType class_language = eLanguageTypeUnknown;
bool is_complete_objc_class = false;
- // bool struct_is_class = false;
+ size_t calling_convention
+ = llvm::dwarf::CallingConvention::DW_CC_normal;
+
const size_t num_attributes = die.GetAttributes(attributes);
if (num_attributes > 0) {
uint32_t i;
@@ -528,10 +560,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_AT_decl_file:
if (die.GetCU()->DW_AT_decl_file_attributes_are_invalid()) {
// llvm-gcc outputs invalid DW_AT_decl_file attributes that
- // always
- // point to the compile unit file, so we clear this invalid
- // value
- // so that we can still unique types efficiently.
+ // always point to the compile unit file, so we clear this
+ // invalid value so that we can still unique types
+ // efficiently.
decl.SetFile(FileSpec("<invalid>", false));
} else
decl.SetFile(
@@ -572,7 +603,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_AT_APPLE_objc_complete_type:
is_complete_objc_class = form_value.Signed();
break;
-
+ case DW_AT_calling_convention:
+ calling_convention = form_value.Unsigned();
+ break;
+
case DW_AT_allocated:
case DW_AT_associated:
case DW_AT_data_location:
@@ -587,10 +621,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
}
- // UniqueDWARFASTType is large, so don't create a local variables on the
- // stack, put it on the heap. This function is often called recursively
- // and clang isn't good and sharing the stack space for variables in
- // different blocks.
+ // UniqueDWARFASTType is large, so don't create a local variables on
+ // the stack, put it on the heap. This function is often called
+ // recursively and clang isn't good and sharing the stack space for
+ // variables in different blocks.
std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(
new UniqueDWARFASTType());
@@ -601,10 +635,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
LanguageType die_language = die.GetLanguage();
if (Language::LanguageIsCPlusPlus(die_language)) {
// For C++, we rely solely upon the one definition rule that says
- // only
- // one thing can exist at a given decl context. We ignore the file
- // and
- // line that things are declared on.
+ // only one thing can exist at a given decl context. We ignore the
+ // file and line that things are declared on.
std::string qualified_name;
if (die.GetQualifiedName(qualified_name))
unique_typename = ConstString(qualified_name);
@@ -641,17 +673,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (byte_size_valid && byte_size == 0 && type_name_cstr &&
die.HasChildren() == false &&
sc.comp_unit->GetLanguage() == eLanguageTypeObjC) {
- // Work around an issue with clang at the moment where
- // forward declarations for objective C classes are emitted
- // as:
+ // Work around an issue with clang at the moment where forward
+ // declarations for objective C classes are emitted as:
// DW_TAG_structure_type [2]
// DW_AT_name( "ForwardObjcClass" )
// DW_AT_byte_size( 0x00 )
// DW_AT_decl_file( "..." )
// DW_AT_decl_line( 1 )
//
- // Note that there is no DW_AT_declaration and there are
- // no children, and the byte size is zero.
+ // Note that there is no DW_AT_declaration and there are no children,
+ // and the byte size is zero.
is_forward_declaration = true;
}
@@ -659,11 +690,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
class_language == eLanguageTypeObjC_plus_plus) {
if (!is_complete_objc_class &&
die.Supports_DW_AT_APPLE_objc_complete_type()) {
- // We have a valid eSymbolTypeObjCClass class symbol whose
- // name matches the current objective C class that we
- // are trying to find and this DIE isn't the complete
- // definition (we checked is_complete_objc_class above and
- // know it is false), so the real definition is in here somewhere
+ // We have a valid eSymbolTypeObjCClass class symbol whose name
+ // matches the current objective C class that we are trying to find
+ // and this DIE isn't the complete definition (we checked
+ // is_complete_objc_class above and know it is false), so the real
+ // definition is in here somewhere
type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE(
die, type_name_const_str, true);
@@ -671,9 +702,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
SymbolFileDWARFDebugMap *debug_map_symfile =
dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
type_sp =
debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
die, type_name_const_str, true);
@@ -690,9 +720,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_sp->GetID());
}
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this
+ // die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
return type_sp;
}
@@ -700,11 +730,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (is_forward_declaration) {
- // We have a forward declaration to a type and we need
- // to try and find a full declaration. We look in the
- // current type index just in case we have a forward
- // declaration followed by an actual declarations in the
- // DWARF. If this fails, we need to look elsewhere...
+ // We have a forward declaration to a type and we need to try and
+ // find a full declaration. We look in the current type index just in
+ // case we have a forward declaration followed by an actual
+ // declarations in the DWARF. If this fails, we need to look
+ // elsewhere...
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
@@ -730,9 +760,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
SymbolFileDWARFDebugMap *debug_map_symfile =
dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
+ // We weren't able to find a full declaration in this DWARF, see
+ // if we have a declaration anywhere else...
type_sp =
debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
die_decl_ctx);
@@ -748,9 +777,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID());
}
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(
dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID(), dwarf)));
@@ -766,9 +794,18 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (!clang_type) {
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
+
+ // If your decl context is a record that was imported from another
+ // AST context (in the gmodules case), we need to make sure the type
+ // backing the Decl is complete before adding children to it. This is
+ // not an issue in the non-gmodules case because the debug info will
+ // always contain a full definition of parent types in that case.
+ CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
+ type_name_cstr);
+
if (accessibility == eAccessNone && decl_ctx) {
- // Check the decl context that contains this class/struct/union.
- // If it is a class we must give it an accessibility.
+ // Check the decl context that contains this class/struct/union. If
+ // it is a class we must give it an accessibility.
const clang::Decl::Kind containing_decl_kind =
decl_ctx->getDeclKind();
if (DeclKindIsCXXClass(containing_decl_kind))
@@ -818,10 +855,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
class_language, &metadata);
}
}
-
+
// Store a forward declaration to this class type in case any
- // parameters in any class methods need it for the clang
- // types for function prototypes.
+ // parameters in any class methods need it for the clang types for
+ // function prototypes.
LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
byte_size, NULL, LLDB_INVALID_UID,
@@ -830,9 +867,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
- // Add our type to the unique type map so we don't
- // end up creating many copies of the same type over
- // and over in the ASTContext for our module
+ // Add our type to the unique type map so we don't end up creating many
+ // copies of the same type over and over in the ASTContext for our
+ // module
unique_ast_entry_ap->m_type_sp = type_sp;
unique_ast_entry_ap->m_die = die;
unique_ast_entry_ap->m_declaration = unique_decl;
@@ -844,8 +881,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// Check to see if the DIE actually has a definition, some version of
// GCC will
// emit DIEs with DW_AT_declaration set to true, but yet still have
- // subprogram,
- // members, or inheritance, so we can't trust it
+ // subprogram, members, or inheritance, so we can't trust it
DWARFDIE child_die = die.GetFirstChild();
while (child_die) {
switch (child_die.Tag()) {
@@ -869,10 +905,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (!is_forward_declaration) {
- // Always start the definition for a class type so that
- // if the class has child classes or types that require
- // the class to be created for use as their decl contexts
- // the class will be ready to accept these child definitions.
+ // Always start the definition for a class type so that if the class
+ // has child classes or types that require the class to be created
+ // for use as their decl contexts the class will be ready to accept
+ // these child definitions.
if (die.HasChildren() == false) {
// No children for this struct/union/class, lets finish it
if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
@@ -896,33 +932,30 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
}
} else if (clang_type_was_created) {
- // Start the definition if the class is not objective C since
- // the underlying decls respond to isCompleteDefinition(). Objective
+ // Start the definition if the class is not objective C since the
+ // underlying decls respond to isCompleteDefinition(). Objective
// C decls don't respond to isCompleteDefinition() so we can't
// start the declaration definition right away. For C++
- // class/union/structs
- // we want to start the definition in case the class is needed as
- // the
- // declaration context for a contained class or type without the
- // need
- // to complete that type..
+ // class/union/structs we want to start the definition in case the
+ // class is needed as the declaration context for a contained class
+ // or type without the need to complete that type..
if (class_language != eLanguageTypeObjC &&
class_language != eLanguageTypeObjC_plus_plus)
ClangASTContext::StartTagDeclarationDefinition(clang_type);
- // Leave this as a forward declaration until we need
- // to know the details of the type. lldb_private::Type
- // will automatically call the SymbolFile virtual function
- // "SymbolFileDWARF::CompleteType(Type *)"
- // When the definition needs to be defined.
+ // Leave this as a forward declaration until we need to know the
+ // details of the type. lldb_private::Type will automatically call
+ // the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)" When the definition
+ // needs to be defined.
assert(!dwarf->GetForwardDeclClangTypeToDie().count(
ClangUtil::RemoveFastQualifiers(clang_type)
.GetOpaqueQualType()) &&
"Type already in the forward declaration map!");
- // Can't assume m_ast.GetSymbolFile() is actually a SymbolFileDWARF,
- // it can be a
- // SymbolFileDWARFDebugMap for Apple binaries.
+ // Can't assume m_ast.GetSymbolFile() is actually a
+ // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple
+ // binaries.
dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] =
clang_type.GetOpaqueQualType();
dwarf->GetForwardDeclClangTypeToDie()
@@ -931,6 +964,19 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
}
}
+
+ // If we made a clang type, set the trivial abi if applicable: We only
+ // do this for pass by value - which implies the Trivial ABI. There
+ // isn't a way to assert that something that would normally be pass by
+ // value is pass by reference, so we ignore that attribute if set.
+ if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+ if (record_decl) {
+ record_decl->setHasTrivialSpecialMemberForCall();
+ }
+ }
+
} break;
case DW_TAG_enumeration_type: {
@@ -1008,9 +1054,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
SymbolFileDWARFDebugMap *debug_map_symfile =
dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
type_sp =
debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
die_decl_ctx);
@@ -1027,9 +1072,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_sp->GetID());
}
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this
+ // die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
clang::DeclContext *defn_decl_ctx =
GetCachedClangDeclContextForDIE(dwarf->DebugInfo()->GetDIE(
@@ -1145,9 +1190,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
- break; // mangled =
- // form_value.AsCString(&dwarf->get_debug_str_data());
- // break;
+ mangled_name_cstr = form_value.AsCString();
+ break;
case DW_AT_type:
type_die_form = form_value;
break;
@@ -1256,8 +1300,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
// Start off static. This will be set to false in
- // ParseChildParameters(...)
- // if we find a "this" parameters as the first parameter
+ // ParseChildParameters(...) if we find a "this" parameters as the
+ // first parameter
if (is_cxx_method) {
is_static = true;
}
@@ -1272,25 +1316,22 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
bool ignore_containing_context = false;
// Check for templatized class member functions. If we had any
- // DW_TAG_template_type_parameter
- // or DW_TAG_template_value_parameter the DW_TAG_subprogram DIE, then we
- // can't let this become
- // a method in a class. Why? Because templatized functions are only
- // emitted if one of the
- // templatized methods is used in the current compile unit and we will
- // end up with classes
- // that may or may not include these member functions and this means one
- // class won't match another
- // class definition and it affects our ability to use a class in the
- // clang expression parser. So
- // for the greater good, we currently must not allow any template member
- // functions in a class definition.
+ // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
+ // the DW_TAG_subprogram DIE, then we can't let this become a method in
+ // a class. Why? Because templatized functions are only emitted if one
+ // of the templatized methods is used in the current compile unit and
+ // we will end up with classes that may or may not include these member
+ // functions and this means one class won't match another class
+ // definition and it affects our ability to use a class in the clang
+ // expression parser. So for the greater good, we currently must not
+ // allow any template member functions in a class definition.
if (is_cxx_method && has_template_params) {
ignore_containing_context = true;
is_cxx_method = false;
}
- // clang_type will get the function prototype clang type after this call
+ // clang_type will get the function prototype clang type after this
+ // call
clang_type = m_ast.CreateFunctionType(
return_clang_type, function_param_types.data(),
function_param_types.size(), is_variadic, type_quals);
@@ -1318,8 +1359,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (class_opaque_type) {
// If accessibility isn't set to anything valid, assume public
- // for
- // now...
+ // for now...
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
@@ -1341,9 +1381,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
}
} else if (is_cxx_method) {
- // Look at the parent of this DIE and see if is is
- // a class or struct and see if this is actually a
- // C++ method
+ // Look at the parent of this DIE and see if is is a class or
+ // struct and see if this is actually a C++ method
Type *class_type = dwarf->ResolveType(decl_ctx_die);
if (class_type) {
bool alternate_defn = false;
@@ -1352,10 +1391,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
alternate_defn = true;
// We uniqued the parent class of this function to another
- // class
- // so we now need to associate all dies under "decl_ctx_die"
- // to
- // DIEs in the DIE for "class_type"...
+ // class so we now need to associate all dies under
+ // "decl_ctx_die" to DIEs in the DIE for "class_type"...
SymbolFileDWARF *class_symfile = NULL;
DWARFDIE class_type_die;
@@ -1381,10 +1418,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// FIXME do something with these failures that's smarter
// than
// just dropping them on the ground. Unfortunately classes
- // don't
- // like having stuff added to them after their definitions
- // are
- // complete...
+ // don't like having stuff added to them after their
+ // definitions are complete...
type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
@@ -1396,16 +1431,13 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (specification_die_form.IsValid()) {
// We have a specification which we are going to base our
- // function
- // prototype off of, so we need this type to be completed so
- // that the
- // m_die_to_decl_ctx for the method in the specification has a
- // valid
- // clang decl context.
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the specification has a valid clang decl context.
class_type->GetForwardCompilerType();
// If we have a specification, then the function type should
- // have been
- // made with the specification and not with this die.
+ // have been made with the specification and not with this
+ // die.
DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE(
DIERef(specification_die_form));
clang::DeclContext *spec_clang_decl_ctx =
@@ -1421,12 +1453,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_handled = true;
} else if (abstract_origin_die_form.IsValid()) {
// We have a specification which we are going to base our
- // function
- // prototype off of, so we need this type to be completed so
- // that the
- // m_die_to_decl_ctx for the method in the abstract origin has
- // a valid
- // clang decl context.
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the abstract origin has a valid clang decl context.
class_type->GetForwardCompilerType();
DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE(
@@ -1449,17 +1478,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (class_opaque_type.IsBeingDefined() || alternate_defn) {
if (!is_static && !die.HasChildren()) {
// We have a C++ member function with no children (this
- // pointer!)
- // and clang will get mad if we try and make a function
- // that isn't
- // well formed in the DWARF, so we will just skip it...
+ // pointer!) and clang will get mad if we try and make
+ // a function that isn't well formed in the DWARF, so
+ // we will just skip it...
type_handled = true;
} else {
bool add_method = true;
if (alternate_defn) {
// If an alternate definition for the class exists,
- // then add the method only if an
- // equivalent is not already present.
+ // then add the method only if an equivalent is not
+ // already present.
clang::CXXRecordDecl *record_decl =
m_ast.GetAsCXXRecordDecl(
class_opaque_type.GetOpaqueQualType());
@@ -1499,18 +1527,18 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
const bool is_attr_used = false;
// Neither GCC 4.2 nor clang++ currently set a valid
- // accessibility
- // in the DWARF for C++ methods... Default to public
- // for now...
+ // accessibility in the DWARF for C++ methods...
+ // Default to public for now...
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
clang::CXXMethodDecl *cxx_method_decl =
m_ast.AddMethodToCXXRecordType(
class_opaque_type.GetOpaqueQualType(),
- type_name_cstr, clang_type, accessibility,
- is_virtual, is_static, is_inline, is_explicit,
- is_attr_used, is_artificial);
+ type_name_cstr, mangled_name_cstr, clang_type,
+ accessibility, is_virtual, is_static,
+ is_inline, is_explicit, is_attr_used,
+ is_artificial);
type_handled = cxx_method_decl != NULL;
@@ -1541,25 +1569,21 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
} else {
// We were asked to parse the type for a method in a
- // class, yet the
- // class hasn't been asked to complete itself through the
- // clang::ExternalASTSource protocol, so we need to just
- // have the
- // class complete itself and do things the right way, then
- // our
+ // class, yet the class hasn't been asked to complete
+ // itself through the clang::ExternalASTSource protocol,
+ // so we need to just have the class complete itself and
+ // do things the right way, then our
// DIE should then have an entry in the
// dwarf->GetDIEToType() map. First
// we need to modify the dwarf->GetDIEToType() so it
- // doesn't think we are
- // trying to parse this DIE anymore...
+ // doesn't think we are trying to parse this DIE
+ // anymore...
dwarf->GetDIEToType()[die.GetDIE()] = NULL;
// Now we get the full type to force our class type to
- // complete itself
- // using the clang::ExternalASTSource protocol which will
- // parse all
- // base classes and all methods (including the method for
- // this DIE).
+ // complete itself using the clang::ExternalASTSource
+ // protocol which will parse all base classes and all
+ // methods (including the method for this DIE).
class_type->GetFullCompilerType();
// The type for this DIE should have been filled in the
@@ -1573,8 +1597,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// FIXME This is fixing some even uglier behavior but we
// really need to
// uniq the methods of each class as well as the class
- // itself.
- // <rdar://problem/11240464>
+ // itself. <rdar://problem/11240464>
type_handled = true;
}
}
@@ -1737,8 +1760,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
array_element_type.GetCompleteType() == false) {
ModuleSP module_sp = die.GetModule();
if (module_sp) {
- if (die.GetCU()->GetProducer() ==
- DWARFCompileUnit::eProducerClang)
+ if (die.GetCU()->GetProducer() == eProducerClang)
module_sp->ReportError(
"DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
"class/union/struct element type DIE 0x%8.8x that is a "
@@ -1760,11 +1782,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
// We have no choice other than to pretend that the element class
- // type
- // is complete. If we don't do this, clang will crash when trying
- // to layout the class. Since we provide layout assistance, all
- // ivars in this class and other classes will be fine, this is
- // the best we can do short of crashing.
+ // type is complete. If we don't do this, clang will crash when
+ // trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will be
+ // fine, this is the best we can do short of crashing.
if (ClangASTContext::StartTagDeclarationDefinition(
array_element_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(
@@ -1864,7 +1885,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != NULL && sc_parent_die) {
symbol_context_scope =
@@ -1956,6 +1978,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
const DWARFDIE &die,
ClangASTContext::TemplateParameterInfos &template_param_infos) {
const dw_tag_t tag = die.Tag();
+ bool is_template_template_argument = false;
switch (tag) {
case DW_TAG_GNU_template_parameter_pack: {
@@ -1971,11 +1994,15 @@ bool DWARFASTParserClang::ParseTemplateDIE(
}
return true;
}
+ case DW_TAG_GNU_template_template_param:
+ is_template_template_argument = true;
+ LLVM_FALLTHROUGH;
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter: {
DWARFAttributes attributes;
const size_t num_attributes = die.GetAttributes(attributes);
const char *name = nullptr;
+ const char *template_name = nullptr;
CompilerType clang_type;
uint64_t uval64 = 0;
bool uval64_valid = false;
@@ -1990,6 +2017,11 @@ bool DWARFASTParserClang::ParseTemplateDIE(
name = form_value.AsCString();
break;
+ case DW_AT_GNU_template_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ template_name = form_value.AsCString();
+ break;
+
case DW_AT_type:
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
Type *lldb_type = die.ResolveTypeUID(DIERef(form_value));
@@ -2013,7 +2045,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
if (!clang_type)
clang_type = m_ast.GetBasicType(eBasicTypeVoid);
- if (clang_type) {
+ if (!is_template_template_argument) {
bool is_signed = false;
if (name && name[0])
template_param_infos.names.push_back(name);
@@ -2033,7 +2065,10 @@ bool DWARFASTParserClang::ParseTemplateDIE(
clang::TemplateArgument(ClangUtil::GetQualType(clang_type)));
}
} else {
- return false;
+ auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name);
+ template_param_infos.names.push_back(name);
+ template_param_infos.args.push_back(
+ clang::TemplateArgument(clang::TemplateName(tplt_type)));
}
}
}
@@ -2052,7 +2087,6 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
if (!parent_die)
return false;
- Args template_parameter_names;
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
die = die.GetSibling()) {
const dw_tag_t tag = die.Tag();
@@ -2061,6 +2095,7 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
case DW_TAG_GNU_template_parameter_pack:
+ case DW_TAG_GNU_template_template_param:
ParseTemplateDIE(die, template_param_infos);
break;
@@ -2073,6 +2108,95 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
return template_param_infos.args.size() == template_param_infos.names.size();
}
+// Checks whether m1 is an overload of m2 (as opposed to an override). This is
+// called by addOverridesForMethod to distinguish overrides (which share a
+// vtable entry) from overloads (which require distinct entries).
+static bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
+ // FIXME: This should detect covariant return types, but currently doesn't.
+ lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
+ "Methods should have the same AST context");
+ clang::ASTContext &context = m1->getASTContext();
+
+ const auto *m1Type =
+ llvm::cast<clang::FunctionProtoType>(
+ context.getCanonicalType(m1->getType()));
+
+ const auto *m2Type =
+ llvm::cast<clang::FunctionProtoType>(
+ context.getCanonicalType(m2->getType()));
+
+ auto compareArgTypes =
+ [&context](const clang::QualType &m1p, const clang::QualType &m2p) {
+ return context.hasSameType(m1p.getUnqualifiedType(),
+ m2p.getUnqualifiedType());
+ };
+
+ // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
+ // as a fourth parameter to std::equal().
+ return (m1->getNumParams() != m2->getNumParams()) ||
+ !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
+ m2Type->param_type_begin(), compareArgTypes);
+}
+
+// If decl is a virtual method, walk the base classes looking for methods that
+// decl overrides. This table of overridden methods is used by IRGen to
+// determine the vtable layout for decl's parent class.
+static void addOverridesForMethod(clang::CXXMethodDecl *decl) {
+ if (!decl->isVirtual())
+ return;
+
+ clang::CXXBasePaths paths;
+
+ auto find_overridden_methods =
+ [decl](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) {
+ if (auto *base_record =
+ llvm::dyn_cast<clang::CXXRecordDecl>(
+ specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
+
+ clang::DeclarationName name = decl->getDeclName();
+
+ // If this is a destructor, check whether the base class destructor is
+ // virtual.
+ if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
+ if (auto *baseDtorDecl = base_record->getDestructor()) {
+ if (baseDtorDecl->isVirtual()) {
+ path.Decls = baseDtorDecl;
+ return true;
+ } else
+ return false;
+ }
+
+ // Otherwise, search for name in the base class.
+ for (path.Decls = base_record->lookup(name); !path.Decls.empty();
+ path.Decls = path.Decls.slice(1)) {
+ if (auto *method_decl =
+ llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
+ if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
+ path.Decls = method_decl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
+ for (auto *overridden_decl : paths.found_decls())
+ decl->addOverriddenMethod(
+ llvm::cast<clang::CXXMethodDecl>(overridden_decl));
+ }
+}
+
+// If clang_type is a CXXRecordDecl, builds the method override list for each
+// of its virtual methods.
+static void addMethodOverrides(ClangASTContext &ast, CompilerType &clang_type) {
+ if (auto *record =
+ ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()))
+ for (auto *method : record->methods())
+ addOverridesForMethod(method);
+}
+
bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
lldb_private::Type *type,
CompilerType &clang_type) {
@@ -2090,10 +2214,10 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
#if defined LLDB_CONFIGURATION_DEBUG
//----------------------------------------------------------------------
- // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES
- // environment variable can be set with one or more typenames separated
- // by ';' characters. This will cause this function to not complete any
- // types whose names match.
+ // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES environment
+ // variable can be set with one or more typenames separated by ';'
+ // characters. This will cause this function to not complete any types whose
+ // names match.
//
// Examples of setting this environment variable:
//
@@ -2144,8 +2268,8 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
LanguageType class_language = eLanguageTypeUnknown;
if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
class_language = eLanguageTypeObjC;
- // For objective C we don't start the definition when
- // the class is created.
+ // For objective C we don't start the definition when the class is
+ // created.
ClangASTContext::StartTagDeclarationDefinition(clang_type);
}
@@ -2217,29 +2341,27 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
clang::TTK_Class);
}
- // Since DW_TAG_structure_type gets used for both classes
- // and structures, we may need to set any DW_TAG_member
- // fields to have a "private" access if none was specified.
- // When we parsed the child members we tracked that actual
- // accessibility value for each DW_TAG_member in the
- // "member_accessibilities" array. If the value for the
- // member is zero, then it was set to the "default_accessibility"
- // which for structs was "public". Below we correct this
- // by setting any fields to "private" that weren't correctly
- // set.
+ // Since DW_TAG_structure_type gets used for both classes and
+ // structures, we may need to set any DW_TAG_member fields to have a
+ // "private" access if none was specified. When we parsed the child
+ // members we tracked that actual accessibility value for each
+ // DW_TAG_member in the "member_accessibilities" array. If the value
+ // for the member is zero, then it was set to the
+ // "default_accessibility" which for structs was "public". Below we
+ // correct this by setting any fields to "private" that weren't
+ // correctly set.
if (is_a_class && !member_accessibilities.empty()) {
- // This is a class and all members that didn't have
- // their access specified are private.
+ // This is a class and all members that didn't have their access
+ // specified are private.
m_ast.SetDefaultAccessForRecordFields(
m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
&member_accessibilities.front(), member_accessibilities.size());
}
if (!base_classes.empty()) {
- // Make sure all base classes refer to complete types and not
- // forward declarations. If we don't do this, clang will crash
- // with an assertion in the call to
- // clang_type.SetBaseClassesForClassType()
+ // Make sure all base classes refer to complete types and not forward
+ // declarations. If we don't do this, clang will crash with an
+ // assertion in the call to clang_type.SetBaseClassesForClassType()
for (auto &base_class : base_classes) {
clang::TypeSourceInfo *type_source_info =
base_class->getTypeSourceInfo();
@@ -2252,19 +2374,17 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
"does not have a complete definition.",
die.GetName(),
base_class_type.GetTypeName().GetCString());
- if (die.GetCU()->GetProducer() ==
- DWARFCompileUnit::eProducerClang)
+ if (die.GetCU()->GetProducer() == eProducerClang)
module->ReportError(":: Try compiling the source file with "
"-fstandalone-debug.");
// We have no choice other than to pretend that the base class
// is complete. If we don't do this, clang will crash when we
// call setBases() inside of
- // "clang_type.SetBaseClassesForClassType()"
- // below. Since we provide layout assistance, all ivars in this
- // class and other classes will be fine, this is the best we can
- // do
- // short of crashing.
+ // "clang_type.SetBaseClassesForClassType()" below. Since we
+ // provide layout assistance, all ivars in this class and other
+ // classes will be fine, this is the best we can do short of
+ // crashing.
if (ClangASTContext::StartTagDeclarationDefinition(
base_class_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(
@@ -2277,14 +2397,15 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
&base_classes.front(),
base_classes.size());
- // Clang will copy each CXXBaseSpecifier in "base_classes"
- // so we have to free them all.
+ // Clang will copy each CXXBaseSpecifier in "base_classes" so we have
+ // to free them all.
ClangASTContext::DeleteBaseClassSpecifiers(&base_classes.front(),
base_classes.size());
}
}
}
+ addMethodOverrides(m_ast, clang_type);
ClangASTContext::BuildIndirectFields(clang_type);
ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
@@ -2582,14 +2703,13 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
Mangled func_name;
if (mangled)
func_name.SetValue(ConstString(mangled), true);
- else if (die.GetParent().Tag() == DW_TAG_compile_unit &&
+ else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||
+ die.GetParent().Tag() == DW_TAG_partial_unit) &&
Language::LanguageIsCPlusPlus(die.GetLanguage()) && name &&
strcmp(name, "main") != 0) {
// If the mangled name is not present in the DWARF, generate the
- // demangled name
- // using the decl context. We skip if the function is "main" as its name
- // is
- // never mangled.
+ // demangled name using the decl context. We skip if the function is
+ // "main" as its name is never mangled.
bool is_static = false;
bool is_variadic = false;
bool has_template_params = false;
@@ -2748,8 +2868,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (form_value.BlockData()) {
Value initialValue(0);
Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data =
- die.GetDWARF()->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = die.GetData();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset =
form_value.BlockData() - debug_info_data.GetDataStart();
@@ -2763,8 +2882,8 @@ bool DWARFASTParserClang::ParseChildMembers(
}
} else {
// With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
member_byte_offset = form_value.Unsigned();
}
break;
@@ -2806,8 +2925,8 @@ bool DWARFASTParserClang::ParseChildMembers(
ConstString fixed_getter;
ConstString fixed_setter;
- // Check if the property getter/setter were provided as full
- // names. We want basenames, so we extract them.
+ // Check if the property getter/setter were provided as full names.
+ // We want basenames, so we extract them.
if (prop_getter_name && prop_getter_name[0] == '-') {
ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
@@ -2819,8 +2938,7 @@ bool DWARFASTParserClang::ParseChildMembers(
prop_setter_name = prop_setter_method.GetSelector().GetCString();
}
- // If the names haven't been provided, they need to be
- // filled in.
+ // If the names haven't been provided, they need to be filled in.
if (!prop_getter_name) {
prop_getter_name = prop_name;
@@ -2836,19 +2954,18 @@ bool DWARFASTParserClang::ParseChildMembers(
}
}
- // Clang has a DWARF generation bug where sometimes it
- // represents fields that are references with bad byte size
- // and bit size/offset information such as:
+ // Clang has a DWARF generation bug where sometimes it represents
+ // fields that are references with bad byte size and bit size/offset
+ // information such as:
//
// DW_AT_byte_size( 0x00 )
// DW_AT_bit_size( 0x40 )
// DW_AT_bit_offset( 0xffffffffffffffc0 )
//
- // So check the bit offset to make sure it is sane, and if
- // the values are not sane, remove them. If we don't do this
- // then we will end up with a crash if we try to use this
- // type in an expression when clang becomes unhappy with its
- // recycled debug info.
+ // So check the bit offset to make sure it is sane, and if the values
+ // are not sane, remove them. If we don't do this then we will end up
+ // with a crash if we try to use this type in an expression when clang
+ // becomes unhappy with its recycled debug info.
if (byte_size == 0 && bit_offset < 0) {
bit_size = 0;
@@ -2862,12 +2979,10 @@ bool DWARFASTParserClang::ParseChildMembers(
if (member_idx == 0 && !is_artificial && name &&
(strstr(name, "_vptr$") == name)) {
- // Not all compilers will mark the vtable pointer
- // member as artificial (llvm-gcc). We can't have
- // the virtual members in our classes otherwise it
- // throws off all child offsets since we end up
- // having and extra pointer sized member in our
- // class layouts.
+ // Not all compilers will mark the vtable pointer member as
+ // artificial (llvm-gcc). We can't have the virtual members in our
+ // classes otherwise it throws off all child offsets since we end up
+ // having and extra pointer sized member in our class layouts.
is_artificial = true;
}
@@ -2907,15 +3022,15 @@ bool DWARFASTParserClang::ParseChildMembers(
/////////////////////////////////////////////////////////////
// How to locate a field given the DWARF debug information
//
- // AT_byte_size indicates the size of the word in which the
- // bit offset must be interpreted.
+ // AT_byte_size indicates the size of the word in which the bit
+ // offset must be interpreted.
//
// AT_data_member_location indicates the byte offset of the
// word from the base address of the structure.
//
// AT_bit_offset indicates how many bits into the word
- // (according to the host endianness) the low-order bit of
- // the field starts. AT_bit_offset can be negative.
+ // (according to the host endianness) the low-order bit of the
+ // field starts. AT_bit_offset can be negative.
//
// AT_bit_size indicates the size of the field in bits.
/////////////////////////////////////////////////////////////
@@ -2956,12 +3071,9 @@ bool DWARFASTParserClang::ParseChildMembers(
field_bit_offset = this_field_info.bit_offset;
// If the member to be emitted did not start on a character
- // boundary and there is
- // empty space between the last field and this one, then we need
- // to emit an
- // anonymous member filling up the space up to its start. There
- // are three cases
- // here:
+ // boundary and there is empty space between the last field and
+ // this one, then we need to emit an anonymous member filling
+ // up the space up to its start. There are three cases here:
//
// 1 If the previous member ended on a character boundary, then
// we can emit an
@@ -2986,10 +3098,8 @@ bool DWARFASTParserClang::ParseChildMembers(
const uint64_t word_width = 32;
// Objective-C has invalid DW_AT_bit_offset values in older
- // versions
- // of clang, so we have to be careful and only insert unnamed
- // bitfields
- // if we have a new enough clang.
+ // versions of clang, so we have to be careful and only insert
+ // unnamed bitfields if we have a new enough clang.
bool detect_unnamed_bitfields = true;
if (class_language == eLanguageTypeObjC ||
@@ -3052,10 +3162,10 @@ bool DWARFASTParserClang::ParseChildMembers(
{
// Older versions of clang emit array[0] and array[1] in the
- // same way (<rdar://problem/12566646>).
- // If the current field is at the end of the structure, then
- // there is definitely no room for extra
- // elements and we override the type to array[0].
+ // same way (<rdar://problem/12566646>). If the current field
+ // is at the end of the structure, then there is definitely no
+ // room for extra elements and we override the type to
+ // array[0].
CompilerType member_array_element_type;
uint64_t member_array_size;
@@ -3089,8 +3199,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (ClangASTContext::IsCXXClassType(member_clang_type) &&
member_clang_type.GetCompleteType() == false) {
- if (die.GetCU()->GetProducer() ==
- DWARFCompileUnit::eProducerClang)
+ if (die.GetCU()->GetProducer() == eProducerClang)
module_sp->ReportError(
"DWARF DIE at 0x%8.8x (class %s) has a member variable "
"0x%8.8x (%s) whose type is a forward declaration, not a "
@@ -3108,12 +3217,11 @@ bool DWARFASTParserClang::ParseChildMembers(
die.GetOffset(), name,
sc.comp_unit ? sc.comp_unit->GetPath().c_str()
: "the source file");
- // We have no choice other than to pretend that the member class
- // is complete. If we don't do this, clang will crash when
- // trying
- // to layout the class. Since we provide layout assistance, all
- // ivars in this class and other classes will be fine, this is
- // the best we can do short of crashing.
+ // We have no choice other than to pretend that the member
+ // class is complete. If we don't do this, clang will crash
+ // when trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will
+ // be fine, this is the best we can do short of crashing.
if (ClangASTContext::StartTagDeclarationDefinition(
member_clang_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(
@@ -3221,8 +3329,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (form_value.BlockData()) {
Value initialValue(0);
Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data =
- die.GetDWARF()->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = die.GetData();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset =
form_value.BlockData() - debug_info_data.GetDataStart();
@@ -3235,8 +3342,8 @@ bool DWARFASTParserClang::ParseChildMembers(
}
} else {
// With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
member_byte_offset = form_value.Unsigned();
}
break;
@@ -3282,18 +3389,16 @@ bool DWARFASTParserClang::ParseChildMembers(
if (is_virtual) {
// Do not specify any offset for virtual inheritance. The DWARF
- // produced by clang doesn't
- // give us a constant offset, but gives us a DWARF expressions that
- // requires an actual object
- // in memory. the DW_AT_data_member_location for a virtual base
- // class looks like:
+ // produced by clang doesn't give us a constant offset, but gives
+ // us a DWARF expressions that requires an actual object in memory.
+ // the DW_AT_data_member_location for a virtual base class looks
+ // like:
// DW_AT_data_member_location( DW_OP_dup, DW_OP_deref,
// DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref,
// DW_OP_plus )
// Given this, there is really no valid response we can give to
- // clang for virtual base
- // class offsets, and this should eventually be removed from
- // LayoutRecordType() in the external
+ // clang for virtual base class offsets, and this should eventually
+ // be removed from LayoutRecordType() in the external
// AST source in clang.
} else {
layout_info.base_offsets.insert(std::make_pair(
@@ -3365,22 +3470,6 @@ size_t DWARFASTParserClang::ParseChildParameters(
is_artificial = form_value.Boolean();
break;
case DW_AT_location:
- // if (form_value.BlockData())
- // {
- // const DWARFDataExtractor&
- // debug_info_data = debug_info();
- // uint32_t block_length =
- // form_value.Unsigned();
- // DWARFDataExtractor
- // location(debug_info_data,
- // form_value.BlockData() -
- // debug_info_data.GetDataStart(),
- // block_length);
- // }
- // else
- // {
- // }
- // break;
case DW_AT_const_value:
case DW_AT_default_value:
case DW_AT_description:
@@ -3397,52 +3486,29 @@ size_t DWARFASTParserClang::ParseChildParameters(
}
bool skip = false;
- if (skip_artificial) {
- if (is_artificial) {
- // In order to determine if a C++ member function is
- // "const" we have to look at the const-ness of "this"...
- // Ugly, but that
- if (arg_idx == 0) {
- if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind())) {
- // Often times compilers omit the "this" name for the
- // specification DIEs, so we can't rely upon the name
- // being in the formal parameter DIE...
- if (name == NULL || ::strcmp(name, "this") == 0) {
- Type *this_type =
- die.ResolveTypeUID(DIERef(param_type_die_form));
- if (this_type) {
- uint32_t encoding_mask = this_type->GetEncodingMask();
- if (encoding_mask & Type::eEncodingIsPointerUID) {
- is_static = false;
-
- if (encoding_mask & (1u << Type::eEncodingIsConstUID))
- type_quals |= clang::Qualifiers::Const;
- if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
- type_quals |= clang::Qualifiers::Volatile;
- }
- }
- }
- }
- }
- skip = true;
- } else {
-
- // HACK: Objective C formal parameters "self" and "_cmd"
- // are not marked as artificial in the DWARF...
- CompileUnit *comp_unit = die.GetLLDBCompileUnit();
- if (comp_unit) {
- switch (comp_unit->GetLanguage()) {
- case eLanguageTypeObjC:
- case eLanguageTypeObjC_plus_plus:
- if (name && name[0] &&
- (strcmp(name, "self") == 0 || strcmp(name, "_cmd") == 0))
- skip = true;
- break;
- default:
- break;
+ if (skip_artificial && is_artificial) {
+ // In order to determine if a C++ member function is "const" we
+ // have to look at the const-ness of "this"...
+ if (arg_idx == 0 &&
+ DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()) &&
+ // Often times compilers omit the "this" name for the
+ // specification DIEs, so we can't rely upon the name being in
+ // the formal parameter DIE...
+ (name == NULL || ::strcmp(name, "this") == 0)) {
+ Type *this_type = die.ResolveTypeUID(DIERef(param_type_die_form));
+ if (this_type) {
+ uint32_t encoding_mask = this_type->GetEncodingMask();
+ if (encoding_mask & Type::eEncodingIsPointerUID) {
+ is_static = false;
+
+ if (encoding_mask & (1u << Type::eEncodingIsConstUID))
+ type_quals |= clang::Qualifiers::Const;
+ if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
+ type_quals |= clang::Qualifiers::Volatile;
}
}
}
+ skip = true;
}
if (!skip) {
@@ -3470,10 +3536,10 @@ size_t DWARFASTParserClang::ParseChildParameters(
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
case DW_TAG_GNU_template_parameter_pack:
- // The one caller of this was never using the template_param_infos,
- // and the local variable was taking up a large amount of stack space
- // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
- // the template params back, we can add them back.
+ // The one caller of this was never using the template_param_infos, and
+ // the local variable was taking up a large amount of stack space in
+ // SymbolFileDWARF::ParseType() so this was removed. If we ever need the
+ // template params back, we can add them back.
// ParseTemplateDIE (dwarf_cu, die, template_param_infos);
has_template_params = true;
break;
@@ -3692,6 +3758,7 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
bool try_parsing_type = true;
switch (die.Tag()) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
decl_ctx = m_ast.GetTranslationUnitDecl();
try_parsing_type = false;
break;
@@ -4008,8 +4075,8 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
// Now do the work of linking the DeclContexts and Types.
if (fast_path) {
- // We can do this quickly. Just run across the tables index-for-index since
- // we know each node has matching names and tags.
+ // We can do this quickly. Just run across the tables index-for-index
+ // since we know each node has matching names and tags.
for (idx = 0; idx < src_size; ++idx) {
src_die = src_name_to_die.GetValueAtIndexUnchecked(idx);
dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
@@ -4046,9 +4113,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
}
}
} else {
- // We must do this slowly. For each member of the destination, look
- // up a member in the source with the same name, check its tag, and
- // unique them if everything matches up. Report failures.
+ // We must do this slowly. For each member of the destination, look up a
+ // member in the source with the same name, check its tag, and unique them
+ // if everything matches up. Report failures.
if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) {
src_name_to_die.Sort();
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
index e04dc76d1dbe..328212e4b684 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
@@ -10,7 +10,6 @@
#include "DWARFASTParserGo.h"
#include "DWARFASTParserGo.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugInfo.h"
@@ -158,7 +157,8 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
Type *type = dwarf->ResolveTypeUID(encoding_uid);
if (type) {
if (go_kind == 0 && type->GetName() == type_name_const_str) {
- // Go emits extra typedefs as a forward declaration. Ignore these.
+ // Go emits extra typedefs as a forward declaration. Ignore
+ // these.
dwarf->m_die_to_type[die.GetDIE()] = type;
return type->shared_from_this();
}
@@ -213,10 +213,10 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
// TODO(ribrdb): Do we need this?
- // UniqueDWARFASTType is large, so don't create a local variables on the
- // stack, put it on the heap. This function is often called recursively
- // and clang isn't good and sharing the stack space for variables in
- // different blocks.
+ // UniqueDWARFASTType is large, so don't create a local variables on
+ // the stack, put it on the heap. This function is often called
+ // recursively and clang isn't good and sharing the stack space for
+ // variables in different blocks.
std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(
new UniqueDWARFASTType());
@@ -225,11 +225,10 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
dwarf->GetUniqueDWARFASTTypeMap().Find(
type_name_const_str, die, decl,
byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) {
- // We have already parsed this type or from another
- // compile unit. GCC loves to use the "one definition
- // rule" which can result in multiple definitions
- // of the same class over and over in each compile
- // unit.
+ // We have already parsed this type or from another compile unit. GCC
+ // loves to use the "one definition rule" which can result in
+ // multiple definitions of the same class over and over in each
+ // compile unit.
type_sp = unique_ast_entry_ap->m_type_sp;
if (type_sp) {
dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
@@ -255,9 +254,9 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
Type::eEncodingIsUID, &decl, compiler_type,
Type::eResolveStateForward));
- // Add our type to the unique type map so we don't
- // end up creating many copies of the same type over
- // and over in the ASTContext for our module
+ // Add our type to the unique type map so we don't end up creating many
+ // copies of the same type over and over in the ASTContext for our
+ // module
unique_ast_entry_ap->m_type_sp = type_sp;
unique_ast_entry_ap->m_die = die;
unique_ast_entry_ap->m_declaration = decl;
@@ -266,19 +265,19 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
*unique_ast_entry_ap);
if (!is_forward_declaration) {
- // Always start the definition for a class type so that
- // if the class has child classes or types that require
- // the class to be created for use as their decl contexts
- // the class will be ready to accept these child definitions.
+ // Always start the definition for a class type so that if the class
+ // has child classes or types that require the class to be created
+ // for use as their decl contexts the class will be ready to accept
+ // these child definitions.
if (die.HasChildren() == false) {
// No children for this struct/union/class, lets finish it
m_ast.CompleteStructType(compiler_type);
} else if (compiler_type_was_created) {
- // Leave this as a forward declaration until we need
- // to know the details of the type. lldb_private::Type
- // will automatically call the SymbolFile virtual function
- // "SymbolFileDWARF::CompleteType(Type *)"
- // When the definition needs to be defined.
+ // Leave this as a forward declaration until we need to know the
+ // details of the type. lldb_private::Type will automatically call
+ // the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)" When the definition
+ // needs to be defined.
dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] =
compiler_type.GetOpaqueQualType();
dwarf->m_forward_decl_clang_type_to_die[compiler_type
@@ -432,7 +431,8 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != NULL && sc_parent_die) {
symbol_context_scope =
@@ -655,8 +655,7 @@ size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc,
if (form_value.BlockData()) {
Value initialValue(0);
Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data =
- die.GetDWARF()->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = die.GetData();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset =
form_value.BlockData() - debug_info_data.GetDataStart();
@@ -670,8 +669,8 @@ size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc,
}
} else {
// With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
member_byte_offset = form_value.Unsigned();
}
break;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
index 8b5202ba265f..476394487985 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
@@ -9,7 +9,7 @@
#include "DWARFASTParserJava.h"
#include "DWARFAttribute.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDeclContext.h"
@@ -324,7 +324,8 @@ lldb::TypeSP DWARFASTParserJava::ParseTypeFromDWARF(
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = nullptr;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != nullptr && sc_parent_die) {
symbol_context_scope =
@@ -418,7 +419,7 @@ bool DWARFASTParserJava::CompleteTypeFromDWARF(
void DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die,
CompilerType &compiler_type) {
- DWARFCompileUnit *dwarf_cu = parent_die.GetCU();
+ DWARFUnit *dwarf_cu = parent_die.GetCU();
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
die = die.GetSibling()) {
switch (die.Tag()) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
index 3b1466df21b0..3ef5c2eb8626 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
@@ -98,7 +98,8 @@ lldb::TypeSP DWARFASTParserOCaml::ParseTypeFromDWARF(const SymbolContext &sc,
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = nullptr;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != nullptr && sc_parent_die) {
symbol_context_scope =
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
index e3b2279ca8fc..09cb5e14934f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
@@ -4,7 +4,6 @@
#define SymbolFileDWARF_DWARFASTParserOCaml_h_
#include "DWARFASTParser.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDebugInfo.h"
#include "DWARFDefines.h"
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index bc49fc5de2cd..a765be0b46d0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -10,6 +10,7 @@
#include "DWARFAbbreviationDeclaration.h"
#include "lldb/Core/dwarf.h"
+#include "lldb/Utility/Stream.h"
#include "DWARFFormValue.h"
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index 28e713f9beb1..b2296c455d6a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -13,8 +13,6 @@
#include "DWARFAttribute.h"
#include "SymbolFileDWARF.h"
-class DWARFCompileUnit;
-
class DWARFAbbreviationDeclaration {
public:
enum { InvalidCode = 0 };
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
index d2573f3742ba..2586d1f18530 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "DWARFAttribute.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
DWARFAttributes::DWARFAttributes() : m_infos() {}
@@ -26,7 +26,7 @@ uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
return UINT32_MAX;
}
-void DWARFAttributes::Append(const DWARFCompileUnit *cu,
+void DWARFAttributes::Append(const DWARFUnit *cu,
dw_offset_t attr_die_offset, dw_attr_t attr,
dw_form_t form) {
AttributeValue attr_value = {cu, attr_die_offset, {attr, form}};
@@ -48,12 +48,11 @@ bool DWARFAttributes::RemoveAttribute(dw_attr_t attr) {
bool DWARFAttributes::ExtractFormValueAtIndex(
uint32_t i, DWARFFormValue &form_value) const {
- const DWARFCompileUnit *cu = CompileUnitAtIndex(i);
+ const DWARFUnit *cu = CompileUnitAtIndex(i);
form_value.SetCompileUnit(cu);
form_value.SetForm(FormAtIndex(i));
lldb::offset_t offset = DIEOffsetAtIndex(i);
- return form_value.ExtractValue(
- cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset);
+ return form_value.ExtractValue(cu->GetData(), &offset);
}
uint64_t DWARFAttributes::FormValueAsUnsigned(dw_attr_t attr,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 317e710e6d94..db4324cf7725 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -14,7 +14,7 @@
#include "llvm/ADT/SmallVector.h"
#include <vector>
-class DWARFCompileUnit;
+class DWARFUnit;
class DWARFFormValue;
class DWARFAttribute {
@@ -50,9 +50,9 @@ public:
DWARFAttributes();
~DWARFAttributes();
- void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset,
+ void Append(const DWARFUnit *cu, dw_offset_t attr_die_offset,
dw_attr_t attr, dw_form_t form);
- const DWARFCompileUnit *CompileUnitAtIndex(uint32_t i) const {
+ const DWARFUnit *CompileUnitAtIndex(uint32_t i) const {
return m_infos[i].cu;
}
dw_offset_t DIEOffsetAtIndex(uint32_t i) const {
@@ -73,7 +73,7 @@ public:
protected:
struct AttributeValue {
- const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in
+ const DWARFUnit *cu; // Keep the compile unit with each attribute in
// case we have DW_FORM_ref_addr values
dw_offset_t die_offset;
DWARFAttribute attr;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
new file mode 100644
index 000000000000..077de9604f1d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
@@ -0,0 +1,193 @@
+//===-- DWARFBaseDIE.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFBaseDIE.h"
+
+#include "DWARFUnit.h"
+#include "DWARFDebugInfoEntry.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb_private;
+
+DIERef DWARFBaseDIE::GetDIERef() const {
+ if (!IsValid())
+ return DIERef();
+
+ dw_offset_t cu_offset = m_cu->GetOffset();
+ if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+ cu_offset = m_cu->GetBaseObjOffset();
+ return DIERef(cu_offset, m_die->GetOffset());
+}
+
+dw_tag_t DWARFBaseDIE::Tag() const {
+ if (m_die)
+ return m_die->Tag();
+ else
+ return 0;
+}
+
+const char *DWARFBaseDIE::GetTagAsCString() const {
+ return lldb_private::DW_TAG_value_to_name(Tag());
+}
+
+const char *DWARFBaseDIE::GetAttributeValueAsString(const dw_attr_t attr,
+ const char *fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t DWARFBaseDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr,
+ uint64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+int64_t DWARFBaseDIE::GetAttributeValueAsSigned(const dw_attr_t attr,
+ int64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t DWARFBaseDIE::GetAttributeValueAsReference(const dw_attr_t attr,
+ uint64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t DWARFBaseDIE::GetAttributeValueAsAddress(const dw_attr_t attr,
+ uint64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+lldb::user_id_t DWARFBaseDIE::GetID() const {
+ return GetDIERef().GetUID(GetDWARF());
+}
+
+const char *DWARFBaseDIE::GetName() const {
+ if (IsValid())
+ return m_die->GetName(GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+lldb::LanguageType DWARFBaseDIE::GetLanguage() const {
+ if (IsValid())
+ return m_cu->GetLanguageType();
+ else
+ return lldb::eLanguageTypeUnknown;
+}
+
+lldb::ModuleSP DWARFBaseDIE::GetModule() const {
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ return dwarf->GetObjectFile()->GetModule();
+ else
+ return lldb::ModuleSP();
+}
+
+lldb_private::CompileUnit *DWARFBaseDIE::GetLLDBCompileUnit() const {
+ if (IsValid())
+ return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
+ else
+ return nullptr;
+}
+
+dw_offset_t DWARFBaseDIE::GetOffset() const {
+ if (IsValid())
+ return m_die->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+dw_offset_t DWARFBaseDIE::GetCompileUnitRelativeOffset() const {
+ if (IsValid())
+ return m_die->GetOffset() - m_cu->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+SymbolFileDWARF *DWARFBaseDIE::GetDWARF() const {
+ if (m_cu)
+ return m_cu->GetSymbolFileDWARF();
+ else
+ return nullptr;
+}
+
+lldb_private::TypeSystem *DWARFBaseDIE::GetTypeSystem() const {
+ if (m_cu)
+ return m_cu->GetTypeSystem();
+ else
+ return nullptr;
+}
+
+DWARFASTParser *DWARFBaseDIE::GetDWARFParser() const {
+ lldb_private::TypeSystem *type_system = GetTypeSystem();
+ if (type_system)
+ return type_system->GetDWARFParser();
+ else
+ return nullptr;
+}
+
+bool DWARFBaseDIE::HasChildren() const {
+ return m_die && m_die->HasChildren();
+}
+
+bool DWARFBaseDIE::Supports_DW_AT_APPLE_objc_complete_type() const {
+ return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
+}
+
+size_t DWARFBaseDIE::GetAttributes(DWARFAttributes &attributes,
+ uint32_t depth) const {
+ if (IsValid()) {
+ return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes,
+ depth);
+ }
+ if (depth == 0)
+ attributes.Clear();
+ return 0;
+}
+
+void DWARFBaseDIE::Dump(lldb_private::Stream *s,
+ const uint32_t recurse_depth) const {
+ if (s && IsValid())
+ m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth);
+}
+
+bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) {
+ return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
+}
+
+bool operator!=(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) {
+ return !(lhs == rhs);
+}
+
+const DWARFDataExtractor &DWARFBaseDIE::GetData() const {
+ // Clients must check if this DIE is valid before calling this function.
+ assert(IsValid());
+ return m_cu->GetData();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
new file mode 100644
index 000000000000..2163a027ffbc
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -0,0 +1,157 @@
+//===-- DWARFBaseDIE.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFBaseDIE_h_
+#define SymbolFileDWARF_DWARFBaseDIE_h_
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/lldb-types.h"
+
+struct DIERef;
+class DWARFASTParser;
+class DWARFAttributes;
+class DWARFUnit;
+class DWARFDebugInfoEntry;
+class DWARFDeclContext;
+class DWARFDIECollection;
+class SymbolFileDWARF;
+
+class DWARFBaseDIE {
+public:
+ DWARFBaseDIE() : m_cu(nullptr), m_die(nullptr) {}
+
+ DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die)
+ : m_cu(cu), m_die(die) {}
+
+ DWARFBaseDIE(const DWARFUnit *cu, DWARFDebugInfoEntry *die)
+ : m_cu(const_cast<DWARFUnit *>(cu)), m_die(die) {}
+
+ DWARFBaseDIE(DWARFUnit *cu, const DWARFDebugInfoEntry *die)
+ : m_cu(cu), m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+
+ DWARFBaseDIE(const DWARFUnit *cu, const DWARFDebugInfoEntry *die)
+ : m_cu(const_cast<DWARFUnit *>(cu)),
+ m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+ explicit operator bool() const { return IsValid(); }
+
+ bool IsValid() const { return m_cu && m_die; }
+
+ bool HasChildren() const;
+
+ bool Supports_DW_AT_APPLE_objc_complete_type() const;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ SymbolFileDWARF *GetDWARF() const;
+
+ DWARFUnit *GetCU() const { return m_cu; }
+
+ DWARFDebugInfoEntry *GetDIE() const { return m_die; }
+
+ DIERef GetDIERef() const;
+
+ lldb_private::TypeSystem *GetTypeSystem() const;
+
+ DWARFASTParser *GetDWARFParser() const;
+
+ void Set(DWARFUnit *cu, DWARFDebugInfoEntry *die) {
+ if (cu && die) {
+ m_cu = cu;
+ m_die = die;
+ } else {
+ Clear();
+ }
+ }
+
+ void Clear() {
+ m_cu = nullptr;
+ m_die = nullptr;
+ }
+
+ //----------------------------------------------------------------------
+ // Get the data that contains the attribute values for this DIE. Support
+ // for .debug_types means that any DIE can have its data either in the
+ // .debug_info or the .debug_types section; this method will return the
+ // correct section data.
+ //
+ // Clients must validate that this object is valid before calling this.
+ //----------------------------------------------------------------------
+ const lldb_private::DWARFDataExtractor &GetData() const;
+
+ //----------------------------------------------------------------------
+ // Accessing information about a DIE
+ //----------------------------------------------------------------------
+ dw_tag_t Tag() const;
+
+ const char *GetTagAsCString() const;
+
+ dw_offset_t GetOffset() const;
+
+ dw_offset_t GetCompileUnitRelativeOffset() const;
+
+ //----------------------------------------------------------------------
+ // Get the LLDB user ID for this DIE. This is often just the DIE offset,
+ // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if
+ // we are doing Darwin DWARF in .o file, or DWARF stand alone debug
+ // info.
+ //----------------------------------------------------------------------
+ lldb::user_id_t GetID() const;
+
+ const char *GetName() const;
+
+ lldb::LanguageType GetLanguage() const;
+
+ lldb::ModuleSP GetModule() const;
+
+ lldb_private::CompileUnit *GetLLDBCompileUnit() const;
+
+ //----------------------------------------------------------------------
+ // Getting attribute values from the DIE.
+ //
+ // GetAttributeValueAsXXX() functions should only be used if you are
+ // looking for one or two attributes on a DIE. If you are trying to
+ // parse all attributes, use GetAttributes (...) instead
+ //----------------------------------------------------------------------
+ const char *GetAttributeValueAsString(const dw_attr_t attr,
+ const char *fail_value) const;
+
+ uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr,
+ uint64_t fail_value) const;
+
+ int64_t GetAttributeValueAsSigned(const dw_attr_t attr,
+ int64_t fail_value) const;
+
+ uint64_t GetAttributeValueAsReference(const dw_attr_t attr,
+ uint64_t fail_value) const;
+
+ uint64_t GetAttributeValueAsAddress(const dw_attr_t attr,
+ uint64_t fail_value) const;
+
+ size_t GetAttributes(DWARFAttributes &attributes, uint32_t depth = 0) const;
+
+ //----------------------------------------------------------------------
+ // Pretty printing
+ //----------------------------------------------------------------------
+
+ void Dump(lldb_private::Stream *s, const uint32_t recurse_depth) const;
+
+protected:
+ DWARFUnit *m_cu;
+ DWARFDebugInfoEntry *m_die;
+};
+
+bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs);
+bool operator!=(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs);
+
+#endif // SymbolFileDWARF_DWARFBaseDIE_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 5d7b12067263..8541f1cfe1f6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -9,48 +9,22 @@
#include "DWARFCompileUnit.h"
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Mangled.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Host/StringConvert.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/LineTable.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/Timer.h"
-
-#include "DWARFDIECollection.h"
-#include "DWARFDebugAbbrev.h"
-#include "DWARFDebugAranges.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFFormValue.h"
-#include "LogChannelDWARF.h"
-#include "NameToDIE.h"
#include "SymbolFileDWARF.h"
-#include "SymbolFileDWARFDebugMap.h"
-#include "SymbolFileDWARFDwo.h"
+#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
-using namespace std;
extern int g_verbose;
DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data)
- : m_dwarf2Data(dwarf2Data) {}
+ : DWARFUnit(dwarf2Data) {}
-DWARFCompileUnit::~DWARFCompileUnit() {}
-
-DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
- lldb::offset_t *offset_ptr) {
- DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data));
- // Out of memory?
- if (cu_sp.get() == NULL)
- return nullptr;
-
- const DWARFDataExtractor &debug_info = dwarf2Data->get_debug_info_data();
+DWARFUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
+ const DWARFDataExtractor &debug_info,
+ lldb::offset_t *offset_ptr) {
+ // std::make_shared would require the ctor to be public.
+ std::shared_ptr<DWARFCompileUnit> cu_sp(new DWARFCompileUnit(dwarf2Data));
cu_sp->m_offset = *offset_ptr;
@@ -83,259 +57,6 @@ DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
return nullptr;
}
-void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) {
- if (m_die_array.size() > 1) {
- // std::vectors never get any smaller when resized to a smaller size,
- // or when clear() or erase() are called, the size will report that it
- // is smaller, but the memory allocated remains intact (call capacity()
- // to see this). So we need to create a temporary vector and swap the
- // contents which will cause just the internal pointers to be swapped
- // so that when "tmp_array" goes out of scope, it will destroy the
- // contents.
-
- // Save at least the compile unit DIE
- DWARFDebugInfoEntry::collection tmp_array;
- m_die_array.swap(tmp_array);
- if (keep_compile_unit_die)
- m_die_array.push_back(tmp_array.front());
- }
-
- if (m_dwo_symbol_file)
- m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);
-}
-
-//----------------------------------------------------------------------
-// ParseCompileUnitDIEsIfNeeded
-//
-// Parses a compile unit and indexes its DIEs if it hasn't already been
-// done.
-//----------------------------------------------------------------------
-size_t DWARFCompileUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
- const size_t initial_die_array_size = m_die_array.size();
- if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
- return 0; // Already parsed
-
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat,
- "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
- m_offset, cu_die_only);
-
- // Set the offset to that of the first DIE and calculate the start of the
- // next compilation unit header.
- lldb::offset_t offset = GetFirstDIEOffset();
- lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
-
- DWARFDebugInfoEntry die;
- // Keep a flat array of the DIE for binary lookup by DIE offset
- if (!cu_die_only) {
- Log *log(
- LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
- if (log) {
- m_dwarf2Data->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
- log, "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at "
- ".debug_info[0x%8.8x]",
- GetOffset());
- }
- }
-
- uint32_t depth = 0;
- // We are in our compile unit, parse starting at the offset
- // we were told to parse
- const DWARFDataExtractor &debug_info_data =
- m_dwarf2Data->get_debug_info_data();
- std::vector<uint32_t> die_index_stack;
- die_index_stack.reserve(32);
- die_index_stack.push_back(0);
- bool prev_die_had_children = false;
- DWARFFormValue::FixedFormSizes fixed_form_sizes =
- DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
- m_is_dwarf64);
- while (offset < next_cu_offset &&
- die.FastExtract(debug_info_data, this, fixed_form_sizes, &offset)) {
- // if (log)
- // log->Printf("0x%8.8x: %*.*s%s%s",
- // die.GetOffset(),
- // depth * 2, depth * 2, "",
- // DW_TAG_value_to_name (die.Tag()),
- // die.HasChildren() ? " *" : "");
-
- const bool null_die = die.IsNULL();
- if (depth == 0) {
- if (initial_die_array_size == 0)
- AddCompileUnitDIE(die);
- uint64_t base_addr = die.GetAttributeValueAsAddress(
- m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
- if (base_addr == LLDB_INVALID_ADDRESS)
- base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this,
- DW_AT_entry_pc, 0);
- SetBaseAddress(base_addr);
- if (cu_die_only)
- return 1;
- } else {
- if (null_die) {
- if (prev_die_had_children) {
- // This will only happen if a DIE says is has children
- // but all it contains is a NULL tag. Since we are removing
- // the NULL DIEs from the list (saves up to 25% in C++ code),
- // we need a way to let the DIE know that it actually doesn't
- // have children.
- if (!m_die_array.empty())
- m_die_array.back().SetEmptyChildren(true);
- }
- } else {
- die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
-
- if (die_index_stack.back())
- m_die_array[die_index_stack.back()].SetSiblingIndex(
- m_die_array.size() - die_index_stack.back());
-
- // Only push the DIE if it isn't a NULL DIE
- m_die_array.push_back(die);
- }
- }
-
- if (null_die) {
- // NULL DIE.
- if (!die_index_stack.empty())
- die_index_stack.pop_back();
-
- if (depth > 0)
- --depth;
- if (depth == 0)
- break; // We are done with this compile unit!
-
- prev_die_had_children = false;
- } else {
- die_index_stack.back() = m_die_array.size() - 1;
- // Normal DIE
- const bool die_has_children = die.HasChildren();
- if (die_has_children) {
- die_index_stack.push_back(0);
- ++depth;
- }
- prev_die_had_children = die_has_children;
- }
- }
-
- // Give a little bit of info if we encounter corrupt DWARF (our offset
- // should always terminate at or before the start of the next compilation
- // unit header).
- if (offset > next_cu_offset) {
- m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning(
- "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
- "0x%8.8" PRIx64 "\n",
- GetOffset(), offset);
- }
-
- // Since std::vector objects will double their size, we really need to
- // make a new array with the perfect size so we don't end up wasting
- // space. So here we copy and swap to make sure we don't have any extra
- // memory taken up.
-
- if (m_die_array.size() < m_die_array.capacity()) {
- DWARFDebugInfoEntry::collection exact_size_die_array(m_die_array.begin(),
- m_die_array.end());
- exact_size_die_array.swap(m_die_array);
- }
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log && log->GetVerbose()) {
- StreamString strm;
- Dump(&strm);
- if (m_die_array.empty())
- strm.Printf("error: no DIE for compile unit");
- else
- m_die_array[0].Dump(m_dwarf2Data, this, strm, UINT32_MAX);
- log->PutString(strm.GetString());
- }
-
- if (!m_dwo_symbol_file)
- return m_die_array.size();
-
- DWARFCompileUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
- size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only);
- return m_die_array.size() + dwo_die_count -
- 1; // We have 2 CU die, but we want to count it only as one
-}
-
-void DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry &die) {
- assert(m_die_array.empty() && "Compile unit DIE already added");
- AddDIE(die);
-
- const DWARFDebugInfoEntry &cu_die = m_die_array.front();
- std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
- m_dwarf2Data->GetDwoSymbolFileForCompileUnit(*this, cu_die);
- if (!dwo_symbol_file)
- return;
-
- DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
- if (!dwo_cu)
- return; // Can't fetch the compile unit from the dwo file.
-
- DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
- if (!dwo_cu_die.IsValid())
- return; // Can't fetch the compile unit DIE from the dwo file.
-
- uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_GNU_dwo_id, 0);
- uint64_t sub_dwo_id =
- dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
- if (main_dwo_id != sub_dwo_id)
- return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to
- // a differectn compilation.
-
- m_dwo_symbol_file = std::move(dwo_symbol_file);
-
- dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_GNU_addr_base, 0);
- dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_GNU_ranges_base, 0);
- dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
-}
-
-dw_offset_t DWARFCompileUnit::GetAbbrevOffset() const {
- return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
-}
-
-bool DWARFCompileUnit::Verify(Stream *s) const {
- const DWARFDataExtractor &debug_info = m_dwarf2Data->get_debug_info_data();
- bool valid_offset = debug_info.ValidOffset(m_offset);
- bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1);
- bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
- bool abbr_offset_OK =
- m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset());
- bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
- if (valid_offset && length_OK && version_OK && addr_size_OK &&
- abbr_offset_OK) {
- return true;
- } else {
- s->Printf(" 0x%8.8x: ", m_offset);
- DumpDataExtractor(m_dwarf2Data->get_debug_info_data(), s, m_offset,
- lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0,
- 0);
- s->EOL();
- if (valid_offset) {
- if (!length_OK)
- s->Printf(" The length (0x%8.8x) for this compile unit is too "
- "large for the .debug_info provided.\n",
- m_length);
- if (!version_OK)
- s->Printf(" The 16 bit compile unit header version is not "
- "supported.\n");
- if (!abbr_offset_OK)
- s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) "
- "is not valid.\n",
- GetAbbrevOffset());
- if (!addr_size_OK)
- s->Printf(" The address size is unsupported: 0x%2.2x\n",
- m_addr_size);
- } else
- s->Printf(" The start offset of the compile unit header in the "
- ".debug_info is invalid.\n");
- }
- return false;
-}
-
void DWARFCompileUnit::Dump(Stream *s) const {
s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, "
"abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at "
@@ -344,768 +65,7 @@ void DWARFCompileUnit::Dump(Stream *s) const {
GetNextCompileUnitOffset());
}
-static uint8_t g_default_addr_size = 4;
-
-uint8_t DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit *cu) {
- if (cu)
- return cu->GetAddressByteSize();
- return DWARFCompileUnit::GetDefaultAddressSize();
-}
-
-bool DWARFCompileUnit::IsDWARF64(const DWARFCompileUnit *cu) {
- if (cu)
- return cu->IsDWARF64();
- return false;
-}
-
-uint8_t DWARFCompileUnit::GetDefaultAddressSize() {
- return g_default_addr_size;
-}
-
-void DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) {
- g_default_addr_size = addr_size;
-}
-
-lldb::user_id_t DWARFCompileUnit::GetID() const {
- dw_offset_t local_id =
- m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
- if (m_dwarf2Data)
- return DIERef(local_id, local_id).GetUID(m_dwarf2Data);
- else
- return local_id;
-}
-
-void DWARFCompileUnit::BuildAddressRangeTable(
- SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges) {
- // This function is usually called if there in no .debug_aranges section
- // in order to produce a compile unit level set of address ranges that
- // is accurate.
-
- size_t num_debug_aranges = debug_aranges->GetNumRanges();
-
- // First get the compile unit DIE only and check if it has a DW_AT_ranges
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
-
- const dw_offset_t cu_offset = GetOffset();
- if (die) {
- DWARFRangeList ranges;
- const size_t num_ranges =
- die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);
- if (num_ranges > 0) {
- // This compile unit has DW_AT_ranges, assume this is correct if it
- // is present since clang no longer makes .debug_aranges by default
- // and it emits DW_AT_ranges for DW_TAG_compile_units. GCC also does
- // this with recent GCC builds.
- for (size_t i = 0; i < num_ranges; ++i) {
- const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
- debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
- range.GetRangeEnd());
- }
-
- return; // We got all of our ranges from the DW_AT_ranges attribute
- }
- }
- // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
-
- // If the DIEs weren't parsed, then we don't want all dies for all compile
- // units
- // to stay loaded when they weren't needed. So we can end up parsing the DWARF
- // and then throwing them all away to keep memory usage down.
- const bool clear_dies = ExtractDIEsIfNeeded(false) > 1;
-
- die = DIEPtr();
- if (die)
- die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
-
- if (debug_aranges->GetNumRanges() == num_debug_aranges) {
- // We got nothing from the functions, maybe we have a line tables only
- // situation. Check the line tables and build the arange table from this.
- SymbolContext sc;
- sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
- if (sc.comp_unit) {
- SymbolFileDWARFDebugMap *debug_map_sym_file =
- m_dwarf2Data->GetDebugMapSymfile();
- if (debug_map_sym_file == NULL) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table) {
- LineTable::FileAddressRanges file_ranges;
- const bool append = true;
- const size_t num_ranges =
- line_table->GetContiguousFileAddressRanges(file_ranges, append);
- for (uint32_t idx = 0; idx < num_ranges; ++idx) {
- const LineTable::FileAddressRanges::Entry &range =
- file_ranges.GetEntryRef(idx);
- debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
- range.GetRangeEnd());
- }
- }
- } else
- debug_map_sym_file->AddOSOARanges(dwarf2Data, debug_aranges);
- }
- }
-
- if (debug_aranges->GetNumRanges() == num_debug_aranges) {
- // We got nothing from the functions, maybe we have a line tables only
- // situation. Check the line tables and build the arange table from this.
- SymbolContext sc;
- sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
- if (sc.comp_unit) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table) {
- LineTable::FileAddressRanges file_ranges;
- const bool append = true;
- const size_t num_ranges =
- line_table->GetContiguousFileAddressRanges(file_ranges, append);
- for (uint32_t idx = 0; idx < num_ranges; ++idx) {
- const LineTable::FileAddressRanges::Entry &range =
- file_ranges.GetEntryRef(idx);
- debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
- range.GetRangeEnd());
- }
- }
- }
- }
-
- // Keep memory down by clearing DIEs if this generate function
- // caused them to be parsed
- if (clear_dies)
- ClearDIEs(true);
-}
-
-const DWARFDebugAranges &DWARFCompileUnit::GetFunctionAranges() {
- if (m_func_aranges_ap.get() == NULL) {
- m_func_aranges_ap.reset(new DWARFDebugAranges());
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
-
- if (log) {
- m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
- log, "DWARFCompileUnit::GetFunctionAranges() for compile unit at "
- ".debug_info[0x%8.8x]",
- GetOffset());
- }
- const DWARFDebugInfoEntry *die = DIEPtr();
- if (die)
- die->BuildFunctionAddressRangeTable(m_dwarf2Data, this,
- m_func_aranges_ap.get());
-
- if (m_dwo_symbol_file) {
- DWARFCompileUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
- const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr();
- if (dwo_die)
- dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu,
- m_func_aranges_ap.get());
- }
-
- const bool minimize = false;
- m_func_aranges_ap->Sort(minimize);
- }
- return *m_func_aranges_ap.get();
-}
-
-DWARFDIE
-DWARFCompileUnit::LookupAddress(const dw_addr_t address) {
- if (DIE()) {
- const DWARFDebugAranges &func_aranges = GetFunctionAranges();
-
- // Re-check the aranges auto pointer contents in case it was created above
- if (!func_aranges.IsEmpty())
- return GetDIE(func_aranges.FindAddress(address));
- }
- return DWARFDIE();
-}
-
-//----------------------------------------------------------------------
-// Compare function DWARFDebugAranges::Range structures
-//----------------------------------------------------------------------
-static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
- const dw_offset_t die_offset) {
- return die.GetOffset() < die_offset;
-}
-
-//----------------------------------------------------------------------
-// GetDIE()
-//
-// Get the DIE (Debug Information Entry) with the specified offset by
-// first checking if the DIE is contained within this compile unit and
-// grabbing the DIE from this compile unit. Otherwise we grab the DIE
-// from the DWARF file.
-//----------------------------------------------------------------------
-DWARFDIE
-DWARFCompileUnit::GetDIE(dw_offset_t die_offset) {
- if (die_offset != DW_INVALID_OFFSET) {
- if (m_dwo_symbol_file)
- return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset);
-
- if (ContainsDIEOffset(die_offset)) {
- ExtractDIEsIfNeeded(false);
- DWARFDebugInfoEntry::iterator end = m_die_array.end();
- DWARFDebugInfoEntry::iterator pos =
- lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
- if (pos != end) {
- if (die_offset == (*pos).GetOffset())
- return DWARFDIE(this, &(*pos));
- }
- } else {
- // Don't specify the compile unit offset as we don't know it because the
- // DIE belongs to
- // a different compile unit in the same symbol file.
- return m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset);
- }
- }
- return DWARFDIE(); // Not found
-}
-
-size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag,
- DWARFDIECollection &dies,
- uint32_t depth) const {
- size_t old_size = dies.Size();
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
- for (pos = m_die_array.begin(); pos != end; ++pos) {
- if (pos->Tag() == tag)
- dies.Append(DWARFDIE(this, &(*pos)));
- }
-
- // Return the number of DIEs added to the collection
- return dies.Size() - old_size;
-}
-
-// void
-// DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx)
-//{
-// m_global_die_indexes.push_back (die_idx);
-//}
-//
-//
-// void
-// DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die)
-//{
-// // Indexes to all file level global and static variables
-// m_global_die_indexes;
-//
-// if (m_die_array.empty())
-// return;
-//
-// const DWARFDebugInfoEntry* first_die = &m_die_array[0];
-// const DWARFDebugInfoEntry* end = first_die + m_die_array.size();
-// if (first_die <= die && die < end)
-// m_global_die_indexes.push_back (die - first_die);
-//}
-
-void DWARFCompileUnit::Index(NameToDIE &func_basenames,
- NameToDIE &func_fullnames, NameToDIE &func_methods,
- NameToDIE &func_selectors,
- NameToDIE &objc_class_selectors,
- NameToDIE &globals, NameToDIE &types,
- NameToDIE &namespaces) {
- assert(!m_dwarf2Data->GetBaseCompileUnit() &&
- "DWARFCompileUnit associated with .dwo or .dwp "
- "should not be indexed directly");
-
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
- if (log) {
- m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
- log,
- "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]",
- GetOffset());
- }
-
- const LanguageType cu_language = GetLanguageType();
- DWARFFormValue::FixedFormSizes fixed_form_sizes =
- DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
- m_is_dwarf64);
-
- IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
- func_fullnames, func_methods, func_selectors,
- objc_class_selectors, globals, types, namespaces);
-
- SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
- if (dwo_symbol_file) {
- IndexPrivate(dwo_symbol_file->GetCompileUnit(), cu_language,
- fixed_form_sizes, GetOffset(), func_basenames, func_fullnames,
- func_methods, func_selectors, objc_class_selectors, globals,
- types, namespaces);
- }
-}
-
-void DWARFCompileUnit::IndexPrivate(
- DWARFCompileUnit *dwarf_cu, const LanguageType cu_language,
- const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
- const dw_offset_t cu_offset, NameToDIE &func_basenames,
- NameToDIE &func_fullnames, NameToDIE &func_methods,
- NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
- NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
- DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
- for (pos = begin; pos != end; ++pos) {
- const DWARFDebugInfoEntry &die = *pos;
-
- const dw_tag_t tag = die.Tag();
-
- switch (tag) {
- case DW_TAG_array_type:
- case DW_TAG_base_type:
- case DW_TAG_class_type:
- case DW_TAG_constant:
- case DW_TAG_enumeration_type:
- case DW_TAG_inlined_subroutine:
- case DW_TAG_namespace:
- case DW_TAG_string_type:
- case DW_TAG_structure_type:
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- case DW_TAG_unspecified_type:
- case DW_TAG_variable:
- break;
-
- default:
- continue;
- }
-
- DWARFAttributes attributes;
- const char *name = NULL;
- const char *mangled_cstr = NULL;
- bool is_declaration = false;
- // bool is_artificial = false;
- bool has_address = false;
- bool has_location_or_const_value = false;
- bool is_global_or_static_variable = false;
-
- DWARFFormValue specification_die_form;
- const size_t num_attributes =
- die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
- if (num_attributes > 0) {
- for (uint32_t i = 0; i < num_attributes; ++i) {
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- switch (attr) {
- case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- name = form_value.AsCString();
- break;
-
- case DW_AT_declaration:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- is_declaration = form_value.Unsigned() != 0;
- break;
-
- // case DW_AT_artificial:
- // if (attributes.ExtractFormValueAtIndex(i,
- // form_value))
- // is_artificial = form_value.Unsigned() != 0;
- // break;
-
- case DW_AT_MIPS_linkage_name:
- case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- mangled_cstr = form_value.AsCString();
- break;
-
- case DW_AT_low_pc:
- case DW_AT_high_pc:
- case DW_AT_ranges:
- has_address = true;
- break;
-
- case DW_AT_entry_pc:
- has_address = true;
- break;
-
- case DW_AT_location:
- case DW_AT_const_value:
- has_location_or_const_value = true;
- if (tag == DW_TAG_variable) {
- const DWARFDebugInfoEntry *parent_die = die.GetParent();
- while (parent_die != NULL) {
- switch (parent_die->Tag()) {
- case DW_TAG_subprogram:
- case DW_TAG_lexical_block:
- case DW_TAG_inlined_subroutine:
- // Even if this is a function level static, we don't add it. We
- // could theoretically
- // add these if we wanted to by introspecting into the
- // DW_AT_location and seeing
- // if the location describes a hard coded address, but we dont
- // want the performance
- // penalty of that right now.
- is_global_or_static_variable = false;
- // if
- // (attributes.ExtractFormValueAtIndex(dwarf2Data,
- // i, form_value))
- // {
- // // If we have valid block
- // data, then we have location
- // expression bytes
- // // that are fixed (not a
- // location list).
- // const uint8_t *block_data =
- // form_value.BlockData();
- // if (block_data)
- // {
- // uint32_t block_length =
- // form_value.Unsigned();
- // if (block_length == 1 +
- // attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
- // {
- // if (block_data[0] ==
- // DW_OP_addr)
- // add_die = true;
- // }
- // }
- // }
- parent_die = NULL; // Terminate the while loop.
- break;
-
- case DW_TAG_compile_unit:
- is_global_or_static_variable = true;
- parent_die = NULL; // Terminate the while loop.
- break;
-
- default:
- parent_die =
- parent_die->GetParent(); // Keep going in the while loop.
- break;
- }
- }
- }
- break;
-
- case DW_AT_specification:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- specification_die_form = form_value;
- break;
- }
- }
- }
-
- switch (tag) {
- case DW_TAG_subprogram:
- if (has_address) {
- if (name) {
- ObjCLanguage::MethodName objc_method(name, true);
- if (objc_method.IsValid(true)) {
- ConstString objc_class_name_with_category(
- objc_method.GetClassNameWithCategory());
- ConstString objc_selector_name(objc_method.GetSelector());
- ConstString objc_fullname_no_category_name(
- objc_method.GetFullNameWithoutCategory(true));
- ConstString objc_class_name_no_category(objc_method.GetClassName());
- func_fullnames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- if (objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_with_category,
- DIERef(cu_offset, die.GetOffset()));
- if (objc_class_name_no_category &&
- objc_class_name_no_category != objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_no_category,
- DIERef(cu_offset, die.GetOffset()));
- if (objc_selector_name)
- func_selectors.Insert(objc_selector_name,
- DIERef(cu_offset, die.GetOffset()));
- if (objc_fullname_no_category_name)
- func_fullnames.Insert(objc_fullname_no_category_name,
- DIERef(cu_offset, die.GetOffset()));
- }
- // If we have a mangled name, then the DW_AT_name attribute
- // is usually the method name without the class or any parameters
- const DWARFDebugInfoEntry *parent = die.GetParent();
- bool is_method = false;
- if (parent) {
- dw_tag_t parent_tag = parent->Tag();
- if (parent_tag == DW_TAG_class_type ||
- parent_tag == DW_TAG_structure_type) {
- is_method = true;
- } else {
- if (specification_die_form.IsValid()) {
- DWARFDIE specification_die =
- dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
- DIERef(specification_die_form));
- if (specification_die.GetParent().IsStructOrClass())
- is_method = true;
- }
- }
- }
-
- if (is_method)
- func_methods.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- else
- func_basenames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
-
- if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
- func_fullnames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- }
- if (mangled_cstr) {
- // Make sure our mangled name isn't the same string table entry
- // as our name. If it starts with '_', then it is ok, else compare
- // the string to make sure it isn't the same and we don't end up
- // with duplicate entries
- if (name && name != mangled_cstr &&
- ((mangled_cstr[0] == '_') ||
- (::strcmp(name, mangled_cstr) != 0))) {
- Mangled mangled(ConstString(mangled_cstr), true);
- func_fullnames.Insert(mangled.GetMangledName(),
- DIERef(cu_offset, die.GetOffset()));
- ConstString demangled = mangled.GetDemangledName(cu_language);
- if (demangled)
- func_fullnames.Insert(demangled,
- DIERef(cu_offset, die.GetOffset()));
- }
- }
- }
- break;
-
- case DW_TAG_inlined_subroutine:
- if (has_address) {
- if (name)
- func_basenames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- if (mangled_cstr) {
- // Make sure our mangled name isn't the same string table entry
- // as our name. If it starts with '_', then it is ok, else compare
- // the string to make sure it isn't the same and we don't end up
- // with duplicate entries
- if (name && name != mangled_cstr &&
- ((mangled_cstr[0] == '_') ||
- (::strcmp(name, mangled_cstr) != 0))) {
- Mangled mangled(ConstString(mangled_cstr), true);
- func_fullnames.Insert(mangled.GetMangledName(),
- DIERef(cu_offset, die.GetOffset()));
- ConstString demangled = mangled.GetDemangledName(cu_language);
- if (demangled)
- func_fullnames.Insert(demangled,
- DIERef(cu_offset, die.GetOffset()));
- }
- } else
- func_fullnames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- }
- break;
-
- case DW_TAG_array_type:
- case DW_TAG_base_type:
- case DW_TAG_class_type:
- case DW_TAG_constant:
- case DW_TAG_enumeration_type:
- case DW_TAG_string_type:
- case DW_TAG_structure_type:
- case DW_TAG_subroutine_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- case DW_TAG_unspecified_type:
- if (name && !is_declaration)
- types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
- if (mangled_cstr && !is_declaration)
- types.Insert(ConstString(mangled_cstr),
- DIERef(cu_offset, die.GetOffset()));
- break;
-
- case DW_TAG_namespace:
- if (name)
- namespaces.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- break;
-
- case DW_TAG_variable:
- if (name && has_location_or_const_value && is_global_or_static_variable) {
- globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
- // Be sure to include variables by their mangled and demangled
- // names if they have any since a variable can have a basename
- // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
- // mangled name "(anonymous namespace)::i"...
-
- // Make sure our mangled name isn't the same string table entry
- // as our name. If it starts with '_', then it is ok, else compare
- // the string to make sure it isn't the same and we don't end up
- // with duplicate entries
- if (mangled_cstr && name != mangled_cstr &&
- ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
- Mangled mangled(ConstString(mangled_cstr), true);
- globals.Insert(mangled.GetMangledName(),
- DIERef(cu_offset, die.GetOffset()));
- ConstString demangled = mangled.GetDemangledName(cu_language);
- if (demangled)
- globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
- }
- }
- break;
-
- default:
- continue;
- }
- }
-}
-
-bool DWARFCompileUnit::Supports_unnamed_objc_bitfields() {
- if (GetProducer() == eProducerClang) {
- const uint32_t major_version = GetProducerVersionMajor();
- if (major_version > 425 ||
- (major_version == 425 && GetProducerVersionUpdate() >= 13))
- return true;
- else
- return false;
- }
- return true; // Assume all other compilers didn't have incorrect ObjC bitfield
- // info
-}
-
-bool DWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type() {
- if (GetProducer() == eProducerLLVMGCC)
- return false;
- return true;
-}
-
-bool DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid() {
- // llvm-gcc makes completely invalid decl file attributes and won't ever
- // be fixed, so we need to know to ignore these.
- return GetProducer() == eProducerLLVMGCC;
-}
-
-void DWARFCompileUnit::ParseProducerInfo() {
- m_producer_version_major = UINT32_MAX;
- m_producer_version_minor = UINT32_MAX;
- m_producer_version_update = UINT32_MAX;
-
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
- if (die) {
-
- const char *producer_cstr = die->GetAttributeValueAsString(
- m_dwarf2Data, this, DW_AT_producer, NULL);
- if (producer_cstr) {
- RegularExpression llvm_gcc_regex(
- llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple "
- "Inc\\. build [0-9]+\\) \\(LLVM build "
- "[\\.0-9]+\\)$"));
- if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) {
- m_producer = eProducerLLVMGCC;
- } else if (strstr(producer_cstr, "clang")) {
- static RegularExpression g_clang_version_regex(
- llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"));
- RegularExpression::Match regex_match(3);
- if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr),
- &regex_match)) {
- std::string str;
- if (regex_match.GetMatchAtIndex(producer_cstr, 1, str))
- m_producer_version_major =
- StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
- if (regex_match.GetMatchAtIndex(producer_cstr, 2, str))
- m_producer_version_minor =
- StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
- if (regex_match.GetMatchAtIndex(producer_cstr, 3, str))
- m_producer_version_update =
- StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
- }
- m_producer = eProducerClang;
- } else if (strstr(producer_cstr, "GNU"))
- m_producer = eProducerGCC;
- }
- }
- if (m_producer == eProducerInvalid)
- m_producer = eProcucerOther;
-}
-
-DWARFCompileUnit::Producer DWARFCompileUnit::GetProducer() {
- if (m_producer == eProducerInvalid)
- ParseProducerInfo();
- return m_producer;
-}
-
-uint32_t DWARFCompileUnit::GetProducerVersionMajor() {
- if (m_producer_version_major == 0)
- ParseProducerInfo();
- return m_producer_version_major;
-}
-
-uint32_t DWARFCompileUnit::GetProducerVersionMinor() {
- if (m_producer_version_minor == 0)
- ParseProducerInfo();
- return m_producer_version_minor;
-}
-
-uint32_t DWARFCompileUnit::GetProducerVersionUpdate() {
- if (m_producer_version_update == 0)
- ParseProducerInfo();
- return m_producer_version_update;
-}
-
-LanguageType DWARFCompileUnit::LanguageTypeFromDWARF(uint64_t val) {
- // Note: user languages between lo_user and hi_user
- // must be handled explicitly here.
- switch (val) {
- case DW_LANG_Mips_Assembler:
- return eLanguageTypeMipsAssembler;
- case DW_LANG_GOOGLE_RenderScript:
- return eLanguageTypeExtRenderScript;
- default:
- return static_cast<LanguageType>(val);
- }
-}
-
-LanguageType DWARFCompileUnit::GetLanguageType() {
- if (m_language_type != eLanguageTypeUnknown)
- return m_language_type;
-
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
- if (die)
- m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_language, 0));
- return m_language_type;
-}
-
-bool DWARFCompileUnit::IsDWARF64() const { return m_is_dwarf64; }
-
-bool DWARFCompileUnit::GetIsOptimized() {
- if (m_is_optimized == eLazyBoolCalculate) {
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
- if (die) {
- m_is_optimized = eLazyBoolNo;
- if (die->GetAttributeValueAsUnsigned(m_dwarf2Data, this,
- DW_AT_APPLE_optimized, 0) == 1) {
- m_is_optimized = eLazyBoolYes;
- }
- }
- }
- if (m_is_optimized == eLazyBoolYes) {
- return true;
- } else {
- return false;
- }
-}
-
-DWARFFormValue::FixedFormSizes DWARFCompileUnit::GetFixedFormSizes() {
- return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
- IsDWARF64());
-}
-
-TypeSystem *DWARFCompileUnit::GetTypeSystem() {
- if (m_dwarf2Data)
- return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType());
- else
- return nullptr;
-}
-
-void DWARFCompileUnit::SetUserData(void *d) {
- m_user_data = d;
- if (m_dwo_symbol_file)
- m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
-}
-
-void DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base,
- dw_addr_t ranges_base,
- dw_offset_t base_obj_offset) {
- m_addr_base = addr_base;
- m_ranges_base = ranges_base;
- m_base_obj_offset = base_obj_offset;
-}
-lldb::ByteOrder DWARFCompileUnit::GetByteOrder() const {
- return m_dwarf2Data->GetObjectFile()->GetByteOrder();
+const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const {
+ return m_dwarf->get_debug_info_data();
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 8ea0d6465adf..d20f31505ed4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -10,214 +10,37 @@
#ifndef SymbolFileDWARF_DWARFCompileUnit_h_
#define SymbolFileDWARF_DWARFCompileUnit_h_
-#include "DWARFDIE.h"
-#include "DWARFDebugInfoEntry.h"
-#include "lldb/lldb-enumerations.h"
+#include "DWARFUnit.h"
-class NameToDIE;
-class SymbolFileDWARF;
-class SymbolFileDWARFDwo;
-
-typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
-
-class DWARFCompileUnit {
+class DWARFCompileUnit : public DWARFUnit {
public:
- enum Producer {
- eProducerInvalid = 0,
- eProducerClang,
- eProducerGCC,
- eProducerLLVMGCC,
- eProcucerOther
- };
-
- static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data,
- lldb::offset_t *offset_ptr);
- ~DWARFCompileUnit();
-
- size_t ExtractDIEsIfNeeded(bool cu_die_only);
- DWARFDIE LookupAddress(const dw_addr_t address);
- size_t AppendDIEsWithTag(const dw_tag_t tag,
- DWARFDIECollection &matching_dies,
- uint32_t depth = UINT32_MAX) const;
- bool Verify(lldb_private::Stream *s) const;
- void Dump(lldb_private::Stream *s) const;
- // Offset of the initial length field.
- dw_offset_t GetOffset() const { return m_offset; }
- lldb::user_id_t GetID() const;
- // Size in bytes of the initial length + compile unit header.
- uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; }
- bool ContainsDIEOffset(dw_offset_t die_offset) const {
- return die_offset >= GetFirstDIEOffset() &&
- die_offset < GetNextCompileUnitOffset();
- }
- dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
- dw_offset_t GetNextCompileUnitOffset() const {
- return m_offset + (m_is_dwarf64 ? 12 : 4) + m_length;
- }
- // Size of the CU data (without initial length and without header).
- size_t GetDebugInfoSize() const {
- return (m_is_dwarf64 ? 12 : 4) + m_length - Size();
- }
- // Size of the CU data incl. header but without initial length.
- uint32_t GetLength() const { return m_length; }
- uint16_t GetVersion() const { return m_version; }
- const DWARFAbbreviationDeclarationSet *GetAbbreviations() const {
- return m_abbrevs;
- }
- dw_offset_t GetAbbrevOffset() const;
- uint8_t GetAddressByteSize() const { return m_addr_size; }
- dw_addr_t GetBaseAddress() const { return m_base_addr; }
- dw_addr_t GetAddrBase() const { return m_addr_base; }
- dw_addr_t GetRangesBase() const { return m_ranges_base; }
- void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset);
- void ClearDIEs(bool keep_compile_unit_die);
- void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
- DWARFDebugAranges *debug_aranges);
-
- lldb::ByteOrder GetByteOrder() const;
-
- lldb_private::TypeSystem *GetTypeSystem();
-
- DWARFFormValue::FixedFormSizes GetFixedFormSizes();
-
- void SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
-
- DWARFDIE
- GetCompileUnitDIEOnly() { return DWARFDIE(this, GetCompileUnitDIEPtrOnly()); }
-
- DWARFDIE
- DIE() { return DWARFDIE(this, DIEPtr()); }
-
- void AddDIE(DWARFDebugInfoEntry &die) {
- // The average bytes per DIE entry has been seen to be
- // around 14-20 so lets pre-reserve half of that since
- // we are now stripping the NULL tags.
-
- // Only reserve the memory if we are adding children of
- // the main compile unit DIE. The compile unit DIE is always
- // the first entry, so if our size is 1, then we are adding
- // the first compile unit child DIE and should reserve
- // the memory.
- if (m_die_array.empty())
- m_die_array.reserve(GetDebugInfoSize() / 24);
- m_die_array.push_back(die);
- }
-
- void AddCompileUnitDIE(DWARFDebugInfoEntry &die);
-
- bool HasDIEsParsed() const { return m_die_array.size() > 1; }
-
- DWARFDIE
- GetDIE(dw_offset_t die_offset);
-
- static uint8_t GetAddressByteSize(const DWARFCompileUnit *cu);
-
- static bool IsDWARF64(const DWARFCompileUnit *cu);
-
- static uint8_t GetDefaultAddressSize();
-
- static void SetDefaultAddressSize(uint8_t addr_size);
-
- void *GetUserData() const { return m_user_data; }
-
- void SetUserData(void *d);
-
- bool Supports_DW_AT_APPLE_objc_complete_type();
-
- bool DW_AT_decl_file_attributes_are_invalid();
-
- bool Supports_unnamed_objc_bitfields();
-
- void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
- NameToDIE &func_methods, NameToDIE &func_selectors,
- NameToDIE &objc_class_selectors, NameToDIE &globals,
- NameToDIE &types, NameToDIE &namespaces);
-
- const DWARFDebugAranges &GetFunctionAranges();
-
- SymbolFileDWARF *GetSymbolFileDWARF() const { return m_dwarf2Data; }
-
- Producer GetProducer();
-
- uint32_t GetProducerVersionMajor();
-
- uint32_t GetProducerVersionMinor();
-
- uint32_t GetProducerVersionUpdate();
-
- static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
-
- lldb::LanguageType GetLanguageType();
-
- bool IsDWARF64() const;
-
- bool GetIsOptimized();
-
- SymbolFileDWARFDwo *GetDwoSymbolFile() const {
- return m_dwo_symbol_file.get();
+ static DWARFUnitSP Extract(SymbolFileDWARF *dwarf2Data,
+ const lldb_private::DWARFDataExtractor &debug_info,
+ lldb::offset_t *offset_ptr);
+ void Dump(lldb_private::Stream *s) const override;
+
+ //------------------------------------------------------------------
+ /// Get the data that contains the DIE information for this unit.
+ ///
+ /// @return
+ /// The correct data (.debug_types for DWARF 4 and earlier, and
+ /// .debug_info for DWARF 5 and later) for the DIE information in
+ /// this unit.
+ //------------------------------------------------------------------
+ const lldb_private::DWARFDataExtractor &GetData() const override;
+
+ //------------------------------------------------------------------
+ /// Get the size in bytes of the header.
+ ///
+ /// @return
+ /// Byte size of the compile unit header
+ //------------------------------------------------------------------
+ uint32_t GetHeaderByteSize() const override {
+ return m_is_dwarf64 ? 23 : 11;
}
- dw_offset_t GetBaseObjOffset() const { return m_base_obj_offset; }
-
-protected:
- SymbolFileDWARF *m_dwarf2Data;
- std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
- const DWARFAbbreviationDeclarationSet *m_abbrevs;
- void *m_user_data = nullptr;
- DWARFDebugInfoEntry::collection
- m_die_array; // The compile unit debug information entry item
- std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; // A table similar to
- // the .debug_aranges
- // table, but this one
- // points to the exact
- // DW_TAG_subprogram
- // DIEs
- dw_addr_t m_base_addr = 0;
- // Offset of the initial length field.
- dw_offset_t m_offset;
- dw_offset_t m_length;
- uint16_t m_version;
- uint8_t m_addr_size;
- Producer m_producer = eProducerInvalid;
- uint32_t m_producer_version_major = 0;
- uint32_t m_producer_version_minor = 0;
- uint32_t m_producer_version_update = 0;
- lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown;
- bool m_is_dwarf64;
- lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
- dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
- dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
- // If this is a dwo compile unit this is the offset of the base compile unit
- // in the main object file
- dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
-
- void ParseProducerInfo();
-
- static void
- IndexPrivate(DWARFCompileUnit *dwarf_cu, const lldb::LanguageType cu_language,
- const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
- const dw_offset_t cu_offset, NameToDIE &func_basenames,
- NameToDIE &func_fullnames, NameToDIE &func_methods,
- NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
- NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
-
private:
DWARFCompileUnit(SymbolFileDWARF *dwarf2Data);
-
- const DWARFDebugInfoEntry *GetCompileUnitDIEPtrOnly() {
- ExtractDIEsIfNeeded(true);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
- }
-
- const DWARFDebugInfoEntry *DIEPtr() {
- ExtractDIEsIfNeeded(false);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
- }
-
DISALLOW_COPY_AND_ASSIGN(DWARFCompileUnit);
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 4ef2e772ea5d..d9754e911017 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -10,43 +10,27 @@
#include "DWARFDIE.h"
#include "DWARFASTParser.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIECollection.h"
-#include "DWARFDebugAbbrev.h"
-#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
-#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
-#include "DWARFFormValue.h"
-#include "SymbolFileDWARF.h"
-
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/TypeSystem.h"
+#include "DWARFUnit.h"
using namespace lldb_private;
-DIERef DWARFDIE::GetDIERef() const {
- if (!IsValid())
- return DIERef();
-
- dw_offset_t cu_offset = m_cu->GetOffset();
- if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
- cu_offset = m_cu->GetBaseObjOffset();
- return DIERef(cu_offset, m_die->GetOffset());
-}
+void DWARFDIE::ElaboratingDIEIterator::Next() {
+ assert(!m_worklist.empty() && "Incrementing end iterator?");
-dw_tag_t DWARFDIE::Tag() const {
- if (m_die)
- return m_die->Tag();
- else
- return 0;
-}
+ // Pop the current item from the list.
+ DWARFDIE die = m_worklist.back();
+ m_worklist.pop_back();
-const char *DWARFDIE::GetTagAsCString() const {
- return lldb_private::DW_TAG_value_to_name(Tag());
+ // And add back any items that elaborate it.
+ for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
+ if (DWARFDIE d = die.GetReferencedDIE(attr))
+ if (m_seen.insert(die.GetID()).second)
+ m_worklist.push_back(d);
+ }
}
DWARFDIE
@@ -91,37 +75,10 @@ DWARFDIE::GetDIE(dw_offset_t die_offset) const {
return DWARFDIE();
}
-const char *DWARFDIE::GetAttributeValueAsString(const dw_attr_t attr,
- const char *fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
-uint64_t DWARFDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr,
- uint64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
-int64_t DWARFDIE::GetAttributeValueAsSigned(const dw_attr_t attr,
- int64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
DWARFDIE
DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
if (IsValid()) {
- DWARFCompileUnit *cu = GetCU();
+ DWARFUnit *cu = GetCU();
SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF();
const bool check_specification_or_abstract_origin = true;
DWARFFormValue form_value;
@@ -132,29 +89,11 @@ DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
return DWARFDIE();
}
-uint64_t DWARFDIE::GetAttributeValueAsReference(const dw_attr_t attr,
- uint64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
-uint64_t DWARFDIE::GetAttributeValueAsAddress(const dw_attr_t attr,
- uint64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
DWARFDIE
DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
if (IsValid()) {
SymbolFileDWARF *dwarf = GetDWARF();
- DWARFCompileUnit *cu = GetCU();
+ DWARFUnit *cu = GetCU();
DWARFDebugInfoEntry *function_die = nullptr;
DWARFDebugInfoEntry *block_die = nullptr;
if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) {
@@ -171,17 +110,6 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
return DWARFDIE();
}
-lldb::user_id_t DWARFDIE::GetID() const {
- return GetDIERef().GetUID(GetDWARF());
-}
-
-const char *DWARFDIE::GetName() const {
- if (IsValid())
- return m_die->GetName(GetDWARF(), m_cu);
- else
- return nullptr;
-}
-
const char *DWARFDIE::GetMangledName() const {
if (IsValid())
return m_die->GetMangledName(GetDWARF(), m_cu);
@@ -203,28 +131,6 @@ const char *DWARFDIE::GetQualifiedName(std::string &storage) const {
return nullptr;
}
-lldb::LanguageType DWARFDIE::GetLanguage() const {
- if (IsValid())
- return m_cu->GetLanguageType();
- else
- return lldb::eLanguageTypeUnknown;
-}
-
-lldb::ModuleSP DWARFDIE::GetModule() const {
- SymbolFileDWARF *dwarf = GetDWARF();
- if (dwarf)
- return dwarf->GetObjectFile()->GetModule();
- else
- return lldb::ModuleSP();
-}
-
-lldb_private::CompileUnit *DWARFDIE::GetLLDBCompileUnit() const {
- if (IsValid())
- return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
- else
- return nullptr;
-}
-
lldb_private::Type *DWARFDIE::ResolveType() const {
if (IsValid())
return GetDWARF()->ResolveType(*this, true);
@@ -262,7 +168,7 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const {
void DWARFDIE::GetDWOContext(std::vector<CompilerContext> &context) const {
const dw_tag_t tag = Tag();
- if (tag == DW_TAG_compile_unit)
+ if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
return;
DWARFDIE parent = GetParent();
if (parent)
@@ -317,45 +223,17 @@ DWARFDIE::GetParentDeclContextDIE() const {
return DWARFDIE();
}
-dw_offset_t DWARFDIE::GetOffset() const {
- if (IsValid())
- return m_die->GetOffset();
- else
- return DW_INVALID_OFFSET;
-}
-
-dw_offset_t DWARFDIE::GetCompileUnitRelativeOffset() const {
- if (IsValid())
- return m_die->GetOffset() - m_cu->GetOffset();
- else
- return DW_INVALID_OFFSET;
-}
-
-SymbolFileDWARF *DWARFDIE::GetDWARF() const {
- if (m_cu)
- return m_cu->GetSymbolFileDWARF();
- else
- return nullptr;
-}
-
-lldb_private::TypeSystem *DWARFDIE::GetTypeSystem() const {
- if (m_cu)
- return m_cu->GetTypeSystem();
- else
- return nullptr;
-}
-
-DWARFASTParser *DWARFDIE::GetDWARFParser() const {
- lldb_private::TypeSystem *type_system = GetTypeSystem();
- if (type_system)
- return type_system->GetDWARFParser();
- else
- return nullptr;
+bool DWARFDIE::IsStructUnionOrClass() const {
+ const dw_tag_t tag = Tag();
+ return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
+ tag == DW_TAG_union_type;
}
-bool DWARFDIE::IsStructOrClass() const {
- const dw_tag_t tag = Tag();
- return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
+bool DWARFDIE::IsMethod() const {
+ for (DWARFDIE d: elaborating_dies())
+ if (d.GetParent().IsStructUnionOrClass())
+ return true;
+ return false;
}
DWARFDIE
@@ -369,7 +247,7 @@ DWARFDIE::GetContainingDWOModuleDIE() const {
const dw_tag_t tag = parent.Tag();
if (tag == DW_TAG_module)
top_module_die = parent;
- else if (tag == DW_TAG_compile_unit)
+ else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
break;
}
@@ -391,25 +269,6 @@ lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
return lldb::ModuleSP();
}
-bool DWARFDIE::HasChildren() const {
- return m_die && m_die->HasChildren();
-}
-
-bool DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type() const {
- return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
-}
-
-size_t DWARFDIE::GetAttributes(DWARFAttributes &attributes,
- uint32_t depth) const {
- if (IsValid()) {
- return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes,
- depth);
- }
- if (depth == 0)
- attributes.Clear();
- return 0;
-}
-
bool DWARFDIE::GetDIENamesAndRanges(
const char *&name, const char *&mangled, DWARFRangeList &ranges,
int &decl_file, int &decl_line, int &decl_column, int &call_file,
@@ -423,12 +282,6 @@ bool DWARFDIE::GetDIENamesAndRanges(
return false;
}
-void DWARFDIE::Dump(lldb_private::Stream *s,
- const uint32_t recurse_depth) const {
- if (s && IsValid())
- m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth);
-}
-
CompilerDecl DWARFDIE::GetDecl() const {
DWARFASTParser *dwarf_ast = GetDWARFParser();
if (dwarf_ast)
@@ -452,11 +305,3 @@ CompilerDeclContext DWARFDIE::GetContainingDeclContext() const {
else
return CompilerDeclContext();
}
-
-bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs) {
- return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
-}
-
-bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) {
- return !(lhs == rhs);
-}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 8af3015b9d76..ecbf4912634e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -10,115 +10,41 @@
#ifndef SymbolFileDWARF_DWARFDIE_h_
#define SymbolFileDWARF_DWARFDIE_h_
-#include "lldb/Core/dwarf.h"
-#include "lldb/lldb-types.h"
-
-struct DIERef;
-class DWARFASTParser;
-class DWARFAttributes;
-class DWARFCompileUnit;
-class DWARFDebugInfoEntry;
-class DWARFDeclContext;
-class DWARFDIECollection;
-class SymbolFileDWARF;
-
-class DWARFDIE {
-public:
- DWARFDIE() : m_cu(nullptr), m_die(nullptr) {}
-
- DWARFDIE(DWARFCompileUnit *cu, DWARFDebugInfoEntry *die)
- : m_cu(cu), m_die(die) {}
-
- DWARFDIE(const DWARFCompileUnit *cu, DWARFDebugInfoEntry *die)
- : m_cu(const_cast<DWARFCompileUnit *>(cu)), m_die(die) {}
+#include "DWARFBaseDIE.h"
+#include "llvm/ADT/SmallSet.h"
- DWARFDIE(DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- : m_cu(cu), m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+class DWARFDIE : public DWARFBaseDIE {
+public:
+ class ElaboratingDIEIterator;
- DWARFDIE(const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- : m_cu(const_cast<DWARFCompileUnit *>(cu)),
- m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+ using DWARFBaseDIE::DWARFBaseDIE;
//----------------------------------------------------------------------
// Tests
//----------------------------------------------------------------------
- explicit operator bool() const { return IsValid(); }
-
- bool IsValid() const { return m_cu && m_die; }
-
- bool IsStructOrClass() const;
+ bool IsStructUnionOrClass() const;
- bool HasChildren() const;
-
- bool Supports_DW_AT_APPLE_objc_complete_type() const;
+ bool IsMethod() const;
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
- SymbolFileDWARF *GetDWARF() const;
-
- DWARFCompileUnit *GetCU() const { return m_cu; }
-
- DWARFDebugInfoEntry *GetDIE() const { return m_die; }
-
- DIERef GetDIERef() const;
-
- lldb_private::TypeSystem *GetTypeSystem() const;
-
- DWARFASTParser *GetDWARFParser() const;
-
- void Set(DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) {
- if (cu && die) {
- m_cu = cu;
- m_die = die;
- } else {
- Clear();
- }
- }
-
- void Clear() {
- m_cu = nullptr;
- m_die = nullptr;
- }
-
lldb::ModuleSP GetContainingDWOModule() const;
DWARFDIE
GetContainingDWOModuleDIE() const;
- //----------------------------------------------------------------------
- // Accessing information about a DIE
- //----------------------------------------------------------------------
- dw_tag_t Tag() const;
-
- const char *GetTagAsCString() const;
-
- dw_offset_t GetOffset() const;
-
- dw_offset_t GetCompileUnitRelativeOffset() const;
+ inline llvm::iterator_range<ElaboratingDIEIterator> elaborating_dies() const;
//----------------------------------------------------------------------
- // Get the LLDB user ID for this DIE. This is often just the DIE offset,
- // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if
- // we are doing Darwin DWARF in .o file, or DWARF stand alone debug
- // info.
+ // Accessing information about a DIE
//----------------------------------------------------------------------
- lldb::user_id_t GetID() const;
-
- const char *GetName() const;
-
const char *GetMangledName() const;
const char *GetPubname() const;
const char *GetQualifiedName(std::string &storage) const;
- lldb::LanguageType GetLanguage() const;
-
- lldb::ModuleSP GetModule() const;
-
- lldb_private::CompileUnit *GetLLDBCompileUnit() const;
-
lldb_private::Type *ResolveType() const;
//----------------------------------------------------------------------
@@ -149,6 +75,7 @@ public:
//----------------------------------------------------------------------
DWARFDIE
GetDIE(dw_offset_t die_offset) const;
+ using DWARFBaseDIE::GetDIE;
DWARFDIE
LookupDeepestBlock(lldb::addr_t file_addr) const;
@@ -172,26 +99,9 @@ public:
// looking for one or two attributes on a DIE. If you are trying to
// parse all attributes, use GetAttributes (...) instead
//----------------------------------------------------------------------
- const char *GetAttributeValueAsString(const dw_attr_t attr,
- const char *fail_value) const;
-
- uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr,
- uint64_t fail_value) const;
-
- int64_t GetAttributeValueAsSigned(const dw_attr_t attr,
- int64_t fail_value) const;
-
- uint64_t GetAttributeValueAsReference(const dw_attr_t attr,
- uint64_t fail_value) const;
-
DWARFDIE
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
- uint64_t GetAttributeValueAsAddress(const dw_attr_t attr,
- uint64_t fail_value) const;
-
- size_t GetAttributes(DWARFAttributes &attributes, uint32_t depth = 0) const;
-
bool GetDIENamesAndRanges(const char *&name, const char *&mangled,
DWARFRangeList &ranges, int &decl_file,
int &decl_line, int &decl_column, int &call_file,
@@ -199,23 +109,68 @@ public:
lldb_private::DWARFExpression *frame_base) const;
//----------------------------------------------------------------------
- // Pretty printing
+ // CompilerDecl related functions
//----------------------------------------------------------------------
- void Dump(lldb_private::Stream *s, const uint32_t recurse_depth) const;
-
lldb_private::CompilerDecl GetDecl() const;
lldb_private::CompilerDeclContext GetDeclContext() const;
lldb_private::CompilerDeclContext GetContainingDeclContext() const;
+};
+
+/// Iterate through all DIEs elaborating (i.e. reachable by a chain of
+/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
+/// convenience, the starting die is included in the sequence as the first
+/// item.
+class DWARFDIE::ElaboratingDIEIterator
+ : public std::iterator<std::input_iterator_tag, DWARFDIE> {
+
+ // The operating invariant is: top of m_worklist contains the "current" item
+ // and the rest of the list are items yet to be visited. An empty worklist
+ // means we've reached the end.
+ // Infinite recursion is prevented by maintaining a list of seen DIEs.
+ // Container sizes are optimized for the case of following DW_AT_specification
+ // and DW_AT_abstract_origin just once.
+ llvm::SmallVector<DWARFDIE, 2> m_worklist;
+ llvm::SmallSet<lldb::user_id_t, 3> m_seen;
+
+ void Next();
+
+public:
+ /// An iterator starting at die d.
+ explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
-protected:
- DWARFCompileUnit *m_cu;
- DWARFDebugInfoEntry *m_die;
+ /// End marker
+ ElaboratingDIEIterator() {}
+
+ const DWARFDIE &operator*() const { return m_worklist.back(); }
+ ElaboratingDIEIterator &operator++() {
+ Next();
+ return *this;
+ }
+ ElaboratingDIEIterator operator++(int) {
+ ElaboratingDIEIterator I = *this;
+ Next();
+ return I;
+ }
+
+ friend bool operator==(const ElaboratingDIEIterator &a,
+ const ElaboratingDIEIterator &b) {
+ if (a.m_worklist.empty() || b.m_worklist.empty())
+ return a.m_worklist.empty() == b.m_worklist.empty();
+ return a.m_worklist.back() == b.m_worklist.back();
+ }
+ friend bool operator!=(const ElaboratingDIEIterator &a,
+ const ElaboratingDIEIterator &b) {
+ return !(a == b);
+ }
};
-bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs);
-bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs);
+llvm::iterator_range<DWARFDIE::ElaboratingDIEIterator>
+DWARFDIE::elaborating_dies() const {
+ return llvm::make_range(ElaboratingDIEIterator(*this),
+ ElaboratingDIEIterator());
+}
#endif // SymbolFileDWARF_DWARFDIE_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
index 0c807d7d604b..2fcdd34d532f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
@@ -22,6 +22,6 @@ DWARFDataExtractor::GetDWARFInitialLength(lldb::offset_t *offset_ptr) const {
dw_offset_t
DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const {
- return GetMaxU64(offset_ptr, m_is_dwarf64 ? 8 : 4);
+ return GetMaxU64(offset_ptr, GetDWARFSizeOfOffset());
}
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
index 46d09f1ca237..ce0bfb3931d5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -29,7 +29,7 @@ public:
dw_offset_t GetDWARFOffset(lldb::offset_t *offset_ptr) const;
size_t GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; }
-
+ size_t GetDWARFSizeOfOffset() const { return m_is_dwarf64 ? 8 : 4; }
bool IsDWARF64() const { return m_is_dwarf64; }
protected:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
index 1cf0e7eeeb60..affe4b85bdab 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
@@ -80,8 +80,8 @@ DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(
//----------------------------------------------------------------------
// DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential()
//
-// Append an abbreviation declaration with a sequential code for O(n)
-// lookups. Handy when creating an DWARFAbbreviationDeclarationSet.
+// Append an abbreviation declaration with a sequential code for O(n) lookups.
+// Handy when creating an DWARFAbbreviationDeclarationSet.
//----------------------------------------------------------------------
dw_uleb128_t DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential(
const DWARFAbbreviationDeclaration &abbrevDecl) {
@@ -115,9 +115,9 @@ void DWARFAbbreviationDeclarationSet::GetUnsupportedForms(
//----------------------------------------------------------------------
// Encode
//
-// Encode the abbreviation table onto the end of the buffer provided
-// into a byte representation as would be found in a ".debug_abbrev"
-// debug information section.
+// Encode the abbreviation table onto the end of the buffer provided into a
+// byte representation as would be found in a ".debug_abbrev" debug information
+// section.
//----------------------------------------------------------------------
// void
// DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index cecb69c8fb46..00265361f865 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -46,19 +46,17 @@ void DWARFDebugArangeSet::Compact() {
if (m_arange_descriptors.empty())
return;
- // Iterate through all arange descriptors and combine any ranges that
- // overlap or have matching boundaries. The m_arange_descriptors are assumed
- // to be in ascending order after being built by adding descriptors
- // using the AddDescriptor method.
+ // Iterate through all arange descriptors and combine any ranges that overlap
+ // or have matching boundaries. The m_arange_descriptors are assumed to be in
+ // ascending order after being built by adding descriptors using the
+ // AddDescriptor method.
uint32_t i = 0;
while (i + 1 < m_arange_descriptors.size()) {
if (m_arange_descriptors[i].end_address() >=
m_arange_descriptors[i + 1].address) {
// The current range ends at or exceeds the start of the next address
- // range.
- // Compute the max end address between the two and use that to make the
- // new
- // length.
+ // range. Compute the max end address between the two and use that to
+ // make the new length.
const dw_addr_t max_end_addr =
std::max(m_arange_descriptors[i].end_address(),
m_arange_descriptors[i + 1].end_address());
@@ -82,8 +80,8 @@ static bool DescriptorLessThan(const DWARFDebugArangeSet::Descriptor &range1,
}
//----------------------------------------------------------------------
-// Add a range descriptor and keep things sorted so we can easily
-// compact the ranges before being saved or used.
+// Add a range descriptor and keep things sorted so we can easily compact the
+// ranges before being saved or used.
//----------------------------------------------------------------------
void DWARFDebugArangeSet::AddDescriptor(
const DWARFDebugArangeSet::Descriptor &range) {
@@ -103,15 +101,14 @@ void DWARFDebugArangeSet::AddDescriptor(
// Non-contiguous entries, add this one before the found entry
m_arange_descriptors.insert(pos, range);
} else if (range_end_addr == pos->address) {
- // The top end of 'range' is the lower end of the entry
- // pointed to by 'pos'. We can combine range with the
- // entry we found by setting the starting address and
- // increasing the length since they don't overlap.
+ // The top end of 'range' is the lower end of the entry pointed to by
+ // 'pos'. We can combine range with the entry we found by setting the
+ // starting address and increasing the length since they don't overlap.
pos->address = range.address;
pos->length += range.length;
} else {
- // We can combine these two and make sure the largest end
- // address is used to make end address.
+ // We can combine these two and make sure the largest end address is
+ // used to make end address.
pos->address = range.address;
pos->length = std::max(found_end_addr, range_end_addr) - pos->address;
}
@@ -142,18 +139,18 @@ bool DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data,
// 7.20 Address Range Table
//
- // Each set of entries in the table of address ranges contained in
- // the .debug_aranges section begins with a header consisting of: a
- // 4-byte length containing the length of the set of entries for this
- // compilation unit, not including the length field itself; a 2-byte
- // version identifier containing the value 2 for DWARF Version 2; a
- // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
- // containing the size in bytes of an address (or the offset portion of
- // an address for segmented addressing) on the target system; and a
- // 1-byte unsigned integer containing the size in bytes of a segment
- // descriptor on the target system. This header is followed by a series
- // of tuples. Each tuple consists of an address and a length, each in
- // the size appropriate for an address on the target architecture.
+ // Each set of entries in the table of address ranges contained in the
+ // .debug_aranges section begins with a header consisting of: a 4-byte
+ // length containing the length of the set of entries for this compilation
+ // unit, not including the length field itself; a 2-byte version identifier
+ // containing the value 2 for DWARF Version 2; a 4-byte offset into
+ // the.debug_infosection; a 1-byte unsigned integer containing the size in
+ // bytes of an address (or the offset portion of an address for segmented
+ // addressing) on the target system; and a 1-byte unsigned integer
+ // containing the size in bytes of a segment descriptor on the target
+ // system. This header is followed by a series of tuples. Each tuple
+ // consists of an address and a length, each in the size appropriate for an
+ // address on the target architecture.
m_header.length = data.GetDWARFInitialLength(offset_ptr);
m_header.version = data.GetU16(offset_ptr);
m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
@@ -195,8 +192,8 @@ bool DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data,
arangeDescriptor.length =
data.GetMaxU64(offset_ptr, m_header.addr_size);
- // Each set of tuples is terminated by a 0 for the address and 0
- // for the length.
+ // Each set of tuples is terminated by a 0 for the address and 0 for
+ // the length.
if (arangeDescriptor.address || arangeDescriptor.length)
m_arange_descriptors.push_back(arangeDescriptor);
else
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 13c2d8726821..02f528d571b0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -18,7 +18,7 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
#include "LogChannelDWARF.h"
#include "SymbolFileDWARF.h"
@@ -82,7 +82,7 @@ bool DWARFDebugAranges::Generate(SymbolFileDWARF *dwarf2Data) {
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (cu)
cu->BuildAddressRangeTable(dwarf2Data, this);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 9c0f1d3c8905..dadc30dc918a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -72,7 +72,7 @@ DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
bool printed = false;
const size_t num_compile_units = GetNumCompileUnits();
for (size_t idx = 0; idx < num_compile_units; ++idx) {
- DWARFCompileUnit *cu = GetCompileUnitAtIndex(idx);
+ DWARFUnit *cu = GetCompileUnitAtIndex(idx);
dw_offset_t offset = cu->GetOffset();
if (cus_with_data.find(offset) == cus_with_data.end()) {
@@ -97,8 +97,10 @@ void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
if (m_compile_units.empty()) {
if (m_dwarf2Data != NULL) {
lldb::offset_t offset = 0;
- DWARFCompileUnitSP cu_sp;
- while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, &offset))) {
+ DWARFUnitSP cu_sp;
+ const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
+ while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
+ &offset))) {
m_compile_units.push_back(cu_sp);
offset = cu_sp->GetNextCompileUnitOffset();
@@ -112,16 +114,16 @@ size_t DWARFDebugInfo::GetNumCompileUnits() {
return m_compile_units.size();
}
-DWARFCompileUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) {
- DWARFCompileUnit *cu = NULL;
+DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) {
+ DWARFUnit *cu = NULL;
if (idx < GetNumCompileUnits())
cu = m_compile_units[idx].get();
return cu;
}
-bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const {
- // Not a verify efficient function, but it is handy for use in assertions
- // to make sure that a compile unit comes from a debug information file.
+bool DWARFDebugInfo::ContainsCompileUnit(const DWARFUnit *cu) const {
+ // Not a verify efficient function, but it is handy for use in assertions to
+ // make sure that a compile unit comes from a debug information file.
CompileUnitColl::const_iterator end_pos = m_compile_units.end();
CompileUnitColl::const_iterator pos;
@@ -133,13 +135,13 @@ bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const {
}
bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset(
- dw_offset_t offset, const DWARFCompileUnitSP &cu_sp) {
+ dw_offset_t offset, const DWARFUnitSP &cu_sp) {
return offset < cu_sp->GetOffset();
}
-DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
+DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
uint32_t *idx_ptr) {
- DWARFCompileUnitSP cu_sp;
+ DWARFUnitSP cu_sp;
uint32_t cu_idx = DW_INVALID_INDEX;
if (cu_offset != DW_INVALID_OFFSET) {
ParseCompileUnitHeadersIfNeeded();
@@ -170,18 +172,18 @@ DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
return cu_sp.get();
}
-DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) {
+DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) {
if (die_ref.cu_offset == DW_INVALID_OFFSET)
return GetCompileUnitContainingDIEOffset(die_ref.die_offset);
else
return GetCompileUnit(die_ref.cu_offset);
}
-DWARFCompileUnit *
+DWARFUnit *
DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) {
ParseCompileUnitHeadersIfNeeded();
- DWARFCompileUnitSP cu_sp;
+ DWARFUnitSP cu_sp;
// Watch out for single compile unit executable as they are pretty common
const size_t num_cus = m_compile_units.size();
@@ -205,7 +207,7 @@ DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) {
DWARFDIE
DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) {
- DWARFCompileUnit *cu = GetCompileUnitContainingDIEOffset(die_offset);
+ DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset);
if (cu)
return cu->GetDIE(die_offset);
return DWARFDIE();
@@ -218,275 +220,9 @@ DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) {
//----------------------------------------------------------------------
DWARFDIE
DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
- DWARFCompileUnit *cu = GetCompileUnit(die_ref);
+ DWARFUnit *cu = GetCompileUnit(die_ref);
if (cu)
return cu->GetDIE(die_ref.die_offset);
return DWARFDIE(); // Not found
}
-//----------------------------------------------------------------------
-// Parse
-//
-// Parses the .debug_info section and uses the .debug_abbrev section
-// and various other sections in the SymbolFileDWARF class and calls the
-// supplied callback function each time a compile unit header, or debug
-// information entry is successfully parsed. This function can be used
-// for different tasks such as parsing the file contents into a
-// structured data, dumping, verifying and much more.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback,
- void *userData) {
- if (dwarf2Data) {
- lldb::offset_t offset = 0;
- uint32_t depth = 0;
- DWARFDebugInfoEntry die;
-
- DWARFCompileUnitSP cu;
- while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) {
- const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
-
- depth = 0;
- // Call the callback function with no DIE pointer for the compile unit
- // and get the offset that we are to continue to parse from
- offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
-
- // Make sure we are within our compile unit
- if (offset < next_cu_offset) {
- // We are in our compile unit, parse starting at the offset
- // we were told to parse
- bool done = false;
- while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) {
- // Call the callback function with DIE pointer that falls within the
- // compile unit
- offset =
- callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
-
- if (die.IsNULL()) {
- if (depth)
- --depth;
- else
- done = true; // We are done with this compile unit!
- } else if (die.HasChildren())
- ++depth;
- }
- }
-
- // Make sure the offset returned is valid, and if not stop parsing.
- // Returning DW_INVALID_OFFSET from this callback is a good way to end
- // all parsing
- if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
- break;
-
- // Make sure we start on a proper
- offset = next_cu_offset;
- }
- }
-}
-
-typedef struct DumpInfo {
- DumpInfo(Stream *init_strm, uint32_t off, uint32_t depth)
- : strm(init_strm), die_offset(off), recurse_depth(depth),
- found_depth(UINT32_MAX), found_die(false), ancestors() {}
- Stream *strm;
- const uint32_t die_offset;
- const uint32_t recurse_depth;
- uint32_t found_depth;
- bool found_die;
- std::vector<DWARFDebugInfoEntry> ancestors;
-
- DISALLOW_COPY_AND_ASSIGN(DumpInfo);
-} DumpInfo;
-
-//----------------------------------------------------------------------
-// DumpCallback
-//
-// A callback function for the static DWARFDebugInfo::Parse() function
-// that gets called each time a compile unit header or debug information
-// entry is successfully parsed.
-//
-// This function dump DWARF information and obey recurse depth and
-// whether a single DIE is to be dumped (or all of the data).
-//----------------------------------------------------------------------
-static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu, DWARFDebugInfoEntry *die,
- const dw_offset_t next_offset,
- const uint32_t curr_depth, void *userData) {
- DumpInfo *dumpInfo = (DumpInfo *)userData;
- Stream *s = dumpInfo->strm;
- bool show_parents =
- s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
-
- if (die) {
- // Are we dumping everything?
- if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
- // Yes we are dumping everything. Obey our recurse level though
- if (curr_depth < dumpInfo->recurse_depth)
- die->Dump(dwarf2Data, cu, *s, 0);
- } else {
- // We are dumping a specific DIE entry by offset
- if (dumpInfo->die_offset == die->GetOffset()) {
- // We found the DIE we were looking for, dump it!
- if (show_parents) {
- s->SetIndentLevel(0);
- const uint32_t num_ancestors = dumpInfo->ancestors.size();
- if (num_ancestors > 0) {
- for (uint32_t i = 0; i < num_ancestors - 1; ++i) {
- dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
- s->IndentMore();
- }
- }
- }
-
- dumpInfo->found_depth = curr_depth;
-
- die->Dump(dwarf2Data, cu, *s, 0);
-
- // Note that we found the DIE we were looking for
- dumpInfo->found_die = true;
-
- // Since we are dumping a single DIE, if there are no children we are
- // done!
- if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
- return DW_INVALID_OFFSET; // Return an invalid address to end parsing
- } else if (dumpInfo->found_die) {
- // Are we done with all the children?
- if (curr_depth <= dumpInfo->found_depth)
- return DW_INVALID_OFFSET;
-
- // We have already found our DIE and are printing it's children. Obey
- // our recurse depth and return an invalid offset if we get done
- // dumping all of the children
- if (dumpInfo->recurse_depth == UINT32_MAX ||
- curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
- die->Dump(dwarf2Data, cu, *s, 0);
- } else if (dumpInfo->die_offset > die->GetOffset()) {
- if (show_parents)
- dumpInfo->ancestors.back() = *die;
- }
- }
-
- // Keep up with our indent level
- if (die->IsNULL()) {
- if (show_parents)
- dumpInfo->ancestors.pop_back();
-
- if (curr_depth <= 1)
- return cu->GetNextCompileUnitOffset();
- else
- s->IndentLess();
- } else if (die->HasChildren()) {
- if (show_parents) {
- DWARFDebugInfoEntry null_die;
- dumpInfo->ancestors.push_back(null_die);
- }
- s->IndentMore();
- }
- } else {
- if (cu == NULL)
- s->PutCString("NULL - cu");
- // We have a compile unit, reset our indent level to zero just in case
- s->SetIndentLevel(0);
-
- // See if we are dumping everything?
- if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
- // We are dumping everything
- if (cu) {
- cu->Dump(s);
- return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this
- // Compile Unit
- } else {
- return DW_INVALID_OFFSET;
- }
- } else {
- if (show_parents) {
- dumpInfo->ancestors.clear();
- dumpInfo->ancestors.resize(1);
- }
-
- // We are dumping only a single DIE possibly with it's children and
- // we must find it's compile unit before we can dump it properly
- if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) {
- // Not found, maybe the DIE offset provided wasn't correct?
- // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << "
- // was not found." << endl;
- return DW_INVALID_OFFSET;
- } else {
- // See if the DIE is in this compile unit?
- if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) {
- return next_offset;
- // // We found our compile unit that contains our DIE, just skip to
- // dumping the requested DIE...
- // return dumpInfo->die_offset;
- } else {
- // Skip to the next compile unit as the DIE isn't in the current one!
- if (cu) {
- return cu->GetNextCompileUnitOffset();
- } else {
- return DW_INVALID_OFFSET;
- }
- }
- }
- }
- }
-
- // Just return the current offset to parse the next CU or DIE entry
- return next_offset;
-}
-
-//----------------------------------------------------------------------
-// Dump
-//
-// Dump the information in the .debug_info section to the specified
-// ostream. If die_offset is valid, a single DIE will be dumped. If the
-// die_offset is invalid, all the DWARF information will be dumped. Both
-// cases will obey a "recurse_depth" or how deep to traverse into the
-// children of each DIE entry. A recurse_depth of zero will dump all
-// compile unit headers. A recurse_depth of 1 will dump all compile unit
-// headers and the DW_TAG_compile unit tags. A depth of 2 will also
-// dump all types and functions.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Dump(Stream *s, SymbolFileDWARF *dwarf2Data,
- const uint32_t die_offset,
- const uint32_t recurse_depth) {
- DumpInfo dumpInfo(s, die_offset, recurse_depth);
- s->PutCString(".debug_info contents");
- if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) {
- if (die_offset == DW_INVALID_OFFSET)
- s->PutCString(":\n");
- else {
- s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
- if (recurse_depth != UINT32_MAX)
- s->Printf(" recursing %u levels deep.", recurse_depth);
- s->EOL();
- }
- } else {
- s->PutCString(": < EMPTY >\n");
- return;
- }
- DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
-}
-
-//----------------------------------------------------------------------
-// Dump
-//
-// Dump the contents of this DWARFDebugInfo object as has been parsed
-// and/or modified after it has been parsed.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset,
- const uint32_t recurse_depth) {
- DumpInfo dumpInfo(s, die_offset, recurse_depth);
-
- s->PutCString("Dumping .debug_info section from internal representation\n");
-
- CompileUnitColl::const_iterator pos;
- uint32_t curr_depth = 0;
- ParseCompileUnitHeadersIfNeeded();
- for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) {
- DWARFCompileUnit *cu = pos->get();
- DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
-
- const DWARFDIE die = cu->DIE();
- if (die)
- die.Dump(s, recurse_depth);
- }
-}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index 14c7d767d05b..fc6085f99a21 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -13,6 +13,7 @@
#include <map>
#include <vector>
+#include "DWARFUnit.h"
#include "DWARFDIE.h"
#include "SymbolFileDWARF.h"
#include "lldb/Core/STLUtils.h"
@@ -26,7 +27,7 @@ typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
class DWARFDebugInfo {
public:
typedef dw_offset_t (*Callback)(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
DWARFDebugInfoEntry *die,
const dw_offset_t next_offset,
const uint32_t depth, void *userData);
@@ -35,22 +36,14 @@ public:
void SetDwarfData(SymbolFileDWARF *dwarf2Data);
size_t GetNumCompileUnits();
- bool ContainsCompileUnit(const DWARFCompileUnit *cu) const;
- DWARFCompileUnit *GetCompileUnitAtIndex(uint32_t idx);
- DWARFCompileUnit *GetCompileUnit(dw_offset_t cu_offset,
- uint32_t *idx_ptr = NULL);
- DWARFCompileUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset);
- DWARFCompileUnit *GetCompileUnit(const DIERef &die_ref);
+ bool ContainsCompileUnit(const DWARFUnit *cu) const;
+ DWARFUnit *GetCompileUnitAtIndex(uint32_t idx);
+ DWARFUnit *GetCompileUnit(dw_offset_t cu_offset, uint32_t *idx_ptr = NULL);
+ DWARFUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset);
+ DWARFUnit *GetCompileUnit(const DIERef &die_ref);
DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset);
DWARFDIE GetDIE(const DIERef &die_ref);
- void Dump(lldb_private::Stream *s, const uint32_t die_offset,
- const uint32_t recurse_depth);
- static void Parse(SymbolFileDWARF *parser, Callback callback, void *userData);
- static void Verify(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data);
- static void Dump(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data,
- const uint32_t die_offset, const uint32_t recurse_depth);
-
enum {
eDumpFlag_Verbose = (1 << 0), // Verbose dumping
eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type
@@ -62,9 +55,9 @@ public:
protected:
static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset,
- const DWARFCompileUnitSP &cu_sp);
+ const DWARFUnitSP &cu_sp);
- typedef std::vector<DWARFCompileUnitSP> CompileUnitColl;
+ typedef std::vector<DWARFUnitSP> CompileUnitColl;
//----------------------------------------------------------------------
// Member variables
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index f595bd83d846..d32aef6e162c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -18,7 +18,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/Stream.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
@@ -34,7 +34,7 @@ using namespace std;
extern int g_verbose;
bool DWARFDebugInfoEntry::FastExtract(
- const DWARFDataExtractor &debug_info_data, const DWARFCompileUnit *cu,
+ const DWARFDataExtractor &debug_info_data, const DWARFUnit *cu,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
lldb::offset_t *offset_ptr) {
m_offset = *offset_ptr;
@@ -189,14 +189,14 @@ bool DWARFDebugInfoEntry::FastExtract(
//----------------------------------------------------------------------
// Extract
//
-// Extract a debug info entry for a given compile unit from the
-// .debug_info and .debug_abbrev data within the SymbolFileDWARF class
-// starting at the given offset
+// Extract a debug info entry for a given compile unit from the .debug_info and
+// .debug_abbrev data within the SymbolFileDWARF class starting at the given
+// offset
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
lldb::offset_t *offset_ptr) {
- const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
// const DWARFDataExtractor& debug_str_data =
// dwarf2Data->get_debug_str_data();
const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
@@ -218,9 +218,10 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
m_tag = abbrevDecl->Tag();
m_has_children = abbrevDecl->HasChildren();
- bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;
+ bool isCompileUnitTag = (m_tag == DW_TAG_compile_unit ||
+ m_tag == DW_TAG_partial_unit);
if (cu && isCompileUnitTag)
- const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0);
+ const_cast<DWARFUnit *>(cu)->SetBaseAddress(0);
// Skip all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
@@ -235,7 +236,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
DWARFFormValue form_value(cu, form);
if (form_value.ExtractValue(debug_info_data, &offset)) {
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
- const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(
+ const_cast<DWARFUnit *>(cu)->SetBaseAddress(
form_value.Address());
}
} else {
@@ -245,8 +246,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
uint32_t form_size = 0;
switch (form) {
// Blocks if inlined data that have a length field and the data
- // bytes
- // inlined in the .debug_info
+ // bytes inlined in the .debug_info
case DW_FORM_exprloc:
case DW_FORM_block:
form_size = debug_info_data.GetULEB128(&offset);
@@ -356,11 +356,11 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// DumpAncestry
//
-// Dumps all of a debug information entries parents up until oldest and
-// all of it's attributes to the specified stream.
+// Dumps all of a debug information entries parents up until oldest and all of
+// it's attributes to the specified stream.
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const DWARFDebugInfoEntry *oldest,
Stream &s,
uint32_t recurse_depth) const {
@@ -374,11 +374,10 @@ void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data,
// GetDIENamesAndRanges
//
// Gets the valid address ranges for a given DIE by looking for a
-// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges
-// attributes.
+// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, const char *&name,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, const char *&name,
const char *&mangled, DWARFRangeList &ranges, int &decl_file,
int &decl_line, int &decl_column, int &call_file, int &call_line,
int &call_column, DWARFExpression *frame_base) const {
@@ -404,8 +403,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule();
if (abbrevDecl) {
- const DWARFDataExtractor &debug_info_data =
- dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
if (!debug_info_data.ValidOffset(offset))
return false;
@@ -451,9 +449,9 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
const DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
if (debug_ranges) {
debug_ranges->FindRanges(cu->GetRangesBase(), form_value.Unsigned(), ranges);
- // All DW_AT_ranges are relative to the base address of the
- // compile unit. We add the compile unit base address to make
- // sure all the addresses are properly fixed up.
+ // All DW_AT_ranges are relative to the base address of the compile
+ // unit. We add the compile unit base address to make sure all the
+ // addresses are properly fixed up.
ranges.Slide(cu->GetBaseAddress());
} else {
cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
@@ -582,13 +580,13 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
//----------------------------------------------------------------------
// Dump
//
-// Dumps a debug information entry and all of it's attributes to the
-// specified stream.
+// Dumps a debug information entry and all of it's attributes to the specified
+// stream.
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu, Stream &s,
+ const DWARFUnit *cu, Stream &s,
uint32_t recurse_depth) const {
- const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
lldb::offset_t offset = m_offset;
if (debug_info_data.ValidOffset(offset)) {
@@ -639,8 +637,8 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
}
void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu, Stream &s) const {
- const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly();
+ DWARFUnit *cu, Stream &s) const {
+ const DWARFBaseDIE cu_die = cu->GetUnitDIEOnly();
const char *cu_name = NULL;
if (cu_die)
cu_name = cu_die.GetName();
@@ -658,12 +656,12 @@ void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// DumpAttribute
//
-// Dumps a debug information entry attribute along with it's form. Any
-// special display of attributes is done (disassemble location lists,
-// show enumeration values for attributes, etc).
+// Dumps a debug information entry attribute along with it's form. Any special
+// display of attributes is done (disassemble location lists, show enumeration
+// values for attributes, etc).
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::DumpAttribute(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr,
Stream &s, dw_attr_t attr, dw_form_t form) {
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
@@ -714,11 +712,10 @@ void DWARFDebugInfoEntry::DumpAttribute(
(*offset_ptr) - form_value.Unsigned(),
form_value.Unsigned());
DWARFExpression::PrintDWARFExpression(
- s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
+ s, locationData, DWARFUnit::GetAddressByteSize(cu), 4, false);
} else {
- // We have a location list offset as the value that is
- // the offset into the .debug_loc section that describes
- // the value over it's lifetime
+ // We have a location list offset as the value that is the offset into
+ // the .debug_loc section that describes the value over it's lifetime
uint64_t debug_loc_offset = form_value.Unsigned();
if (dwarf2Data) {
DWARFExpression::PrintDWARFLocationList(
@@ -759,18 +756,18 @@ void DWARFDebugInfoEntry::DumpAttribute(
//----------------------------------------------------------------------
// Get all attribute values for a given DIE, including following any
-// specification or abstract origin attributes and including those in
-// the results. Any duplicate attributes will have the first instance
-// take precedence (this can happen for declaration attributes).
+// specification or abstract origin attributes and including those in the
+// results. Any duplicate attributes will have the first instance take
+// precedence (this can happen for declaration attributes).
//----------------------------------------------------------------------
size_t DWARFDebugInfoEntry::GetAttributes(
- const DWARFCompileUnit *cu, DWARFFormValue::FixedFormSizes fixed_form_sizes,
+ const DWARFUnit *cu, DWARFFormValue::FixedFormSizes fixed_form_sizes,
DWARFAttributes &attributes, uint32_t curr_depth) const {
SymbolFileDWARF *dwarf2Data = nullptr;
const DWARFAbbreviationDeclaration *abbrevDecl = nullptr;
lldb::offset_t offset = 0;
if (cu) {
- if (m_tag != DW_TAG_compile_unit) {
+ if (m_tag != DW_TAG_compile_unit && m_tag != DW_TAG_partial_unit) {
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
if (dwo_symbol_file)
return GetAttributes(dwo_symbol_file->GetCompileUnit(),
@@ -782,8 +779,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(
}
if (abbrevDecl) {
- const DWARFDataExtractor &debug_info_data =
- dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
if (fixed_form_sizes.Empty())
fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(
@@ -803,9 +799,9 @@ size_t DWARFDebugInfoEntry::GetAttributes(
case DW_AT_sibling:
case DW_AT_declaration:
if (curr_depth > 0) {
- // This attribute doesn't make sense when combined with
- // the DIE that references this DIE. We know a DIE is
- // referencing this DIE because curr_depth is not zero
+ // This attribute doesn't make sense when combined with the DIE that
+ // references this DIE. We know a DIE is referencing this DIE because
+ // curr_depth is not zero
break;
}
LLVM_FALLTHROUGH;
@@ -819,7 +815,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(
if (form_value.ExtractValue(debug_info_data, &offset)) {
dw_offset_t die_offset = form_value.Reference();
DWARFDIE spec_die =
- const_cast<DWARFCompileUnit *>(cu)->GetDIE(die_offset);
+ const_cast<DWARFUnit *>(cu)->GetDIE(die_offset);
if (spec_die)
spec_die.GetAttributes(attributes, curr_depth + 1);
}
@@ -841,17 +837,18 @@ size_t DWARFDebugInfoEntry::GetAttributes(
// GetAttributeValue
//
// Get the value of an attribute and return the .debug_info offset of the
-// attribute if it was properly extracted into form_value, or zero
-// if we fail since an offset of zero is invalid for an attribute (it
-// would be a compile unit header).
+// attribute if it was properly extracted into form_value, or zero if we fail
+// since an offset of zero is invalid for an attribute (it would be a compile
+// unit header).
//----------------------------------------------------------------------
dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, DWARFFormValue &form_value,
dw_offset_t *end_attr_offset_ptr,
bool check_specification_or_abstract_origin) const {
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
- if (dwo_symbol_file && m_tag != DW_TAG_compile_unit)
+ if (dwo_symbol_file && m_tag != DW_TAG_compile_unit &&
+ m_tag != DW_TAG_partial_unit)
return GetAttributeValue(dwo_symbol_file, dwo_symbol_file->GetCompileUnit(),
attr, form_value, end_attr_offset_ptr,
check_specification_or_abstract_origin);
@@ -864,8 +861,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
if (attr_idx != DW_INVALID_INDEX) {
- const DWARFDataExtractor &debug_info_data =
- dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
uint32_t idx = 0;
while (idx < attr_idx)
@@ -886,7 +882,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
if (check_specification_or_abstract_origin) {
if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) {
DWARFDIE die =
- const_cast<DWARFCompileUnit *>(cu)->GetDIE(form_value.Reference());
+ const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference());
if (die) {
dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr,
@@ -898,7 +894,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) {
DWARFDIE die =
- const_cast<DWARFCompileUnit *>(cu)->GetDIE(form_value.Reference());
+ const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference());
if (die) {
dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr,
@@ -912,11 +908,11 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
if (!dwo_symbol_file)
return 0;
- DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
+ DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
if (!dwo_cu)
return 0;
- DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
+ DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
if (!dwo_cu_die.IsValid())
return 0;
@@ -928,13 +924,13 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
//----------------------------------------------------------------------
// GetAttributeValueAsString
//
-// Get the value of an attribute as a string return it. The resulting
-// pointer to the string data exists within the supplied SymbolFileDWARF
-// and will only be available as long as the SymbolFileDWARF is still around
-// and it's content doesn't change.
+// Get the value of an attribute as a string return it. The resulting pointer
+// to the string data exists within the supplied SymbolFileDWARF and will only
+// be available as long as the SymbolFileDWARF is still around and it's content
+// doesn't change.
//----------------------------------------------------------------------
const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, const char *fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -950,7 +946,7 @@ const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
// Get the value of an attribute as unsigned and return it.
//----------------------------------------------------------------------
uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -966,7 +962,7 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
// Get the value of an attribute a signed value and return it.
//----------------------------------------------------------------------
int64_t DWARFDebugInfoEntry::GetAttributeValueAsSigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, int64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -979,11 +975,11 @@ int64_t DWARFDebugInfoEntry::GetAttributeValueAsSigned(
//----------------------------------------------------------------------
// GetAttributeValueAsReference
//
-// Get the value of an attribute as reference and fix up and compile
-// unit relative offsets as needed.
+// Get the value of an attribute as reference and fix up and compile unit
+// relative offsets as needed.
//----------------------------------------------------------------------
uint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -994,7 +990,7 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference(
}
uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -1007,13 +1003,13 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
//----------------------------------------------------------------------
// GetAttributeHighPC
//
-// Get the hi_pc, adding hi_pc to lo_pc when specified
-// as an <offset-from-low-pc>.
+// Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
+// pc>.
//
// Returns the hi_pc or fail_value.
//----------------------------------------------------------------------
dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t lo_pc,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t lo_pc,
uint64_t fail_value, bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr,
@@ -1031,13 +1027,13 @@ dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
//----------------------------------------------------------------------
// GetAttributeAddressRange
//
-// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified
-// as an <offset-from-low-pc>.
+// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
+// from-low-pc>.
//
// Returns true or sets lo_pc and hi_pc to fail_value.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::GetAttributeAddressRange(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t &lo_pc,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t &lo_pc,
dw_addr_t &hi_pc, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value,
@@ -1054,7 +1050,7 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange(
}
size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin) const {
ranges.Clear();
@@ -1083,23 +1079,23 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
//----------------------------------------------------------------------
// GetName
//
-// Get value of the DW_AT_name attribute and return it if one exists,
-// else return NULL.
+// Get value of the DW_AT_name attribute and return it if one exists, else
+// return NULL.
//----------------------------------------------------------------------
const char *DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const {
+ const DWARFUnit *cu) const {
return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
}
//----------------------------------------------------------------------
// GetMangledName
//
-// Get value of the DW_AT_MIPS_linkage_name attribute and return it if
-// one exists, else return the value of the DW_AT_name attribute
+// Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
+// exists, else return the value of the DW_AT_name attribute
//----------------------------------------------------------------------
const char *
DWARFDebugInfoEntry::GetMangledName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
bool substitute_name_allowed) const {
const char *name = nullptr;
@@ -1123,11 +1119,11 @@ DWARFDebugInfoEntry::GetMangledName(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// GetPubname
//
-// Get value the name for a DIE as it should appear for a
-// .debug_pubnames or .debug_pubtypes section.
+// Get value the name for a DIE as it should appear for a .debug_pubnames or
+// .debug_pubtypes section.
//----------------------------------------------------------------------
const char *DWARFDebugInfoEntry::GetPubname(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const {
+ const DWARFUnit *cu) const {
const char *name = nullptr;
if (!dwarf2Data)
return name;
@@ -1149,14 +1145,13 @@ const char *DWARFDebugInfoEntry::GetPubname(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// GetName
//
-// Get value of the DW_AT_name attribute for a debug information entry
-// that exists at offset "die_offset" and place that value into the
-// supplied stream object. If the DIE is a NULL object "NULL" is placed
-// into the stream, and if no DW_AT_name attribute exists for the DIE
-// then nothing is printed.
+// Get value of the DW_AT_name attribute for a debug information entry that
+// exists at offset "die_offset" and place that value into the supplied stream
+// object. If the DIE is a NULL object "NULL" is placed into the stream, and if
+// no DW_AT_name attribute exists for the DIE then nothing is printed.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const dw_offset_t die_offset, Stream &s) {
if (dwarf2Data == NULL) {
s.PutCString("NULL");
@@ -1184,13 +1179,12 @@ bool DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// AppendTypeName
//
-// Follows the type name definition down through all needed tags to
-// end up with a fully qualified type name and dump the results to
-// the supplied stream. This is used to show the name of types given
-// a type identifier.
+// Follows the type name definition down through all needed tags to end up with
+// a fully qualified type name and dump the results to the supplied stream.
+// This is used to show the name of types given a type identifier.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const dw_offset_t die_offset,
Stream &s) {
if (dwarf2Data == NULL) {
@@ -1318,7 +1312,7 @@ bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data,
// BuildAddressRangeTable
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::BuildAddressRangeTable(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const {
if (m_tag) {
if (m_tag == DW_TAG_subprogram) {
@@ -1343,13 +1337,13 @@ void DWARFDebugInfoEntry::BuildAddressRangeTable(
//----------------------------------------------------------------------
// BuildFunctionAddressRangeTable
//
-// This function is very similar to the BuildAddressRangeTable function
-// except that the actual DIE offset for the function is placed in the
-// table instead of the compile unit offset (which is the way the
-// standard .debug_aranges section does it).
+// This function is very similar to the BuildAddressRangeTable function except
+// that the actual DIE offset for the function is placed in the table instead
+// of the compile unit offset (which is the way the standard .debug_aranges
+// section does it).
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const {
if (m_tag) {
if (m_tag == DW_TAG_subprogram) {
@@ -1372,21 +1366,22 @@ void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
}
void DWARFDebugInfoEntry::GetDeclContextDIEs(
- DWARFCompileUnit *cu, DWARFDIECollection &decl_context_dies) const {
+ DWARFUnit *cu, DWARFDIECollection &decl_context_dies) const {
DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
die.GetDeclContextDIEs(decl_context_dies);
}
void DWARFDebugInfoEntry::GetDWARFDeclContext(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
DWARFDeclContext &dwarf_decl_ctx) const {
const dw_tag_t tag = Tag();
- if (tag != DW_TAG_compile_unit) {
+ if (tag != DW_TAG_compile_unit && tag != DW_TAG_partial_unit) {
dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu));
DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(dwarf2Data, cu);
if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) {
- if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit)
+ if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit &&
+ parent_decl_ctx_die.Tag() != DW_TAG_partial_unit)
parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext(
parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(),
dwarf_decl_ctx);
@@ -1395,7 +1390,7 @@ void DWARFDebugInfoEntry::GetDWARFDeclContext(
}
bool DWARFDebugInfoEntry::MatchesDWARFDeclContext(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
const DWARFDeclContext &dwarf_decl_ctx) const {
DWARFDeclContext this_dwarf_decl_ctx;
@@ -1405,7 +1400,7 @@ bool DWARFDebugInfoEntry::MatchesDWARFDeclContext(
DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu) const {
+ DWARFUnit *cu) const {
DWARFAttributes attributes;
GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
return GetParentDeclContextDIE(dwarf2Data, cu, attributes);
@@ -1413,17 +1408,18 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
const DWARFAttributes &attributes) const {
DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
while (die) {
- // If this is the original DIE that we are searching for a declaration
- // for, then don't look in the cache as we don't want our own decl
- // context to be our decl context...
+ // If this is the original DIE that we are searching for a declaration for,
+ // then don't look in the cache as we don't want our own decl context to be
+ // our decl context...
if (die.GetDIE() != this) {
switch (die.Tag()) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
@@ -1465,7 +1461,7 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE(
}
const char *DWARFDebugInfoEntry::GetQualifiedName(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
std::string &storage) const {
DWARFAttributes attributes;
GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
@@ -1473,7 +1469,7 @@ const char *DWARFDebugInfoEntry::GetQualifiedName(SymbolFileDWARF *dwarf2Data,
}
const char *DWARFDebugInfoEntry::GetQualifiedName(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
const DWARFAttributes &attributes, std::string &storage) const {
const char *name = GetName(dwarf2Data, cu);
@@ -1529,7 +1525,7 @@ const char *DWARFDebugInfoEntry::GetQualifiedName(
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die) {
bool found_address = false;
@@ -1661,6 +1657,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
case DW_TAG_unspecified_type:
break;
case DW_TAG_partial_unit:
+ match_addr_range = true;
break;
case DW_TAG_imported_unit:
break;
@@ -1684,6 +1681,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
// puts("***MATCH***");
switch (m_tag) {
case DW_TAG_compile_unit: // File
+ case DW_TAG_partial_unit: // File
check_children = ((function_die != NULL) || (block_die != NULL));
break;
@@ -1706,10 +1704,12 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
break;
}
}
- } else { // compile units may not have a valid high/low pc when there
+ } else {
+ // Compile units may not have a valid high/low pc when there
// are address gaps in subroutines so we must always search
- // if there is no valid high and low PC
- check_children = (m_tag == DW_TAG_compile_unit) &&
+ // if there is no valid high and low PC.
+ check_children = (m_tag == DW_TAG_compile_unit ||
+ m_tag == DW_TAG_partial_unit) &&
((function_die != NULL) || (block_die != NULL));
}
} else {
@@ -1719,15 +1719,16 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
DWARFRangeList ranges;
DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
- // All DW_AT_ranges are relative to the base address of the
- // compile unit. We add the compile unit base address to make
- // sure all the addresses are properly fixed up.
+ // All DW_AT_ranges are relative to the base address of the compile
+ // unit. We add the compile unit base address to make sure all the
+ // addresses are properly fixed up.
ranges.Slide(cu->GetBaseAddress());
if (ranges.FindEntryThatContains(address)) {
found_address = true;
// puts("***MATCH***");
switch (m_tag) {
case DW_TAG_compile_unit: // File
+ case DW_TAG_partial_unit: // File
check_children = ((function_die != NULL) || (block_die != NULL));
break;
@@ -1772,7 +1773,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
const DWARFAbbreviationDeclaration *
DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
lldb::offset_t &offset) const {
if (dwarf2Data) {
offset = GetOffset();
@@ -1782,11 +1783,10 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(
const DWARFAbbreviationDeclaration *abbrev_decl =
abbrev_set->GetAbbreviationDeclaration(m_abbr_idx);
if (abbrev_decl) {
- // Make sure the abbreviation code still matches. If it doesn't and
- // the DWARF data was mmap'ed, the backing file might have been modified
+ // Make sure the abbreviation code still matches. If it doesn't and the
+ // DWARF data was mmap'ed, the backing file might have been modified
// which is bad news.
- const uint64_t abbrev_code =
- dwarf2Data->get_debug_info_data().GetULEB128(&offset);
+ const uint64_t abbrev_code = cu->GetData().GetULEB128(&offset);
if (abbrev_decl->Code() == abbrev_code)
return abbrev_decl;
@@ -1825,3 +1825,15 @@ void DWARFDebugInfoEntry::DumpDIECollection(
die_ref.HasChildren() ? " *" : "");
}
}
+
+bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
+ return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
+ m_sibling_idx == rhs.m_sibling_idx &&
+ m_empty_children == rhs.m_empty_children &&
+ m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
+ m_tag == rhs.m_tag;
+}
+
+bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
+ return !(*this == rhs);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 89450d327adf..97cb3046eb3e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -60,128 +60,132 @@ public:
m_empty_children(false), m_abbr_idx(0), m_has_children(false),
m_tag(0) {}
+ explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
+ bool operator==(const DWARFDebugInfoEntry &rhs) const;
+ bool operator!=(const DWARFDebugInfoEntry &rhs) const;
+
void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const;
void BuildFunctionAddressRangeTable(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const;
bool FastExtract(const lldb_private::DWARFDataExtractor &debug_info_data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
lldb::offset_t *offset_ptr);
- bool Extract(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ bool Extract(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
lldb::offset_t *offset_ptr);
bool LookupAddress(const dw_addr_t address, SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die);
- size_t GetAttributes(const DWARFCompileUnit *cu,
+ size_t GetAttributes(const DWARFUnit *cu,
DWARFFormValue::FixedFormSizes fixed_form_sizes,
DWARFAttributes &attrs,
uint32_t curr_depth = 0)
const; // "curr_depth" for internal use only, don't set this yourself!!!
dw_offset_t
- GetAttributeValue(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ GetAttributeValue(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, DWARFFormValue &formValue,
dw_offset_t *end_attr_offset_ptr = nullptr,
bool check_specification_or_abstract_origin = false) const;
const char *GetAttributeValueAsString(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, const char *fail_value,
bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsUnsigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsReference(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
int64_t GetAttributeValueAsSigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, int64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsAddress(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
dw_addr_t
- GetAttributeHighPC(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ GetAttributeHighPC(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
dw_addr_t lo_pc, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
bool GetAttributeAddressRange(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t &lo_pc,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t &lo_pc,
dw_addr_t &hi_pc, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
size_t GetAttributeAddressRanges(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin = false) const;
const char *GetName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const;
+ const DWARFUnit *cu) const;
const char *GetMangledName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
bool substitute_name_allowed = true) const;
const char *GetPubname(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const;
+ const DWARFUnit *cu) const;
- static bool GetName(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ static bool GetName(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_offset_t die_offset, lldb_private::Stream &s);
static bool AppendTypeName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const dw_offset_t die_offset,
lldb_private::Stream &s);
const char *GetQualifiedName(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
std::string &storage) const;
const char *GetQualifiedName(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
const DWARFAttributes &attributes,
std::string &storage) const;
static bool OffsetLessThan(const DWARFDebugInfoEntry &a,
const DWARFDebugInfoEntry &b);
- void Dump(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ void Dump(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
lldb_private::Stream &s, uint32_t recurse_depth) const;
- void DumpAncestry(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ void DumpAncestry(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const DWARFDebugInfoEntry *oldest, lldb_private::Stream &s,
uint32_t recurse_depth) const;
static void
- DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const lldb_private::DWARFDataExtractor &debug_info_data,
lldb::offset_t *offset_ptr, lldb_private::Stream &s,
dw_attr_t attr, dw_form_t form);
// This one dumps the comp unit name, objfile name and die offset for this die
// so the stream S.
- void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
lldb_private::Stream &s) const;
bool
- GetDIENamesAndRanges(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ GetDIENamesAndRanges(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const char *&name, const char *&mangled,
DWARFRangeList &rangeList, int &decl_file,
int &decl_line, int &decl_column, int &call_file,
@@ -190,7 +194,7 @@ public:
const DWARFAbbreviationDeclaration *
GetAbbreviationDeclarationPtr(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
lldb::offset_t &offset) const;
dw_tag_t Tag() const { return m_tag; }
@@ -229,20 +233,20 @@ public:
return (HasChildren() && !m_empty_children) ? this + 1 : NULL;
}
- void GetDeclContextDIEs(DWARFCompileUnit *cu,
+ void GetDeclContextDIEs(DWARFUnit *cu,
DWARFDIECollection &decl_context_dies) const;
- void GetDWARFDeclContext(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ void GetDWARFDeclContext(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
DWARFDeclContext &dwarf_decl_ctx) const;
bool MatchesDWARFDeclContext(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
const DWARFDeclContext &dwarf_decl_ctx) const;
DWARFDIE GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu) const;
+ DWARFUnit *cu) const;
DWARFDIE GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
const DWARFAttributes &attributes) const;
void SetParent(DWARFDebugInfoEntry *parent) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 694d34fc211c..317ea4c22c66 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -242,8 +242,8 @@ dw_offset_t DWARFDebugLine::DumpStatementOpcodes(
log->Printf("0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode",
op_offset, opcode);
// Length doesn't include the zero opcode byte or the length itself,
- // but
- // it does include the sub_opcode, so we have to adjust for that below
+ // but it does include the sub_opcode, so we have to adjust for that
+ // below
offset += arg_size;
break;
}
@@ -324,9 +324,9 @@ dw_offset_t DWARFDebugLine::DumpStatementOpcodes(
// Special Opcodes
default:
if (opcode < prologue.opcode_base) {
- // We have an opcode that this parser doesn't know about, skip
- // the number of ULEB128 numbers that is says to skip in the
- // prologue's standard_opcode_lengths array
+ // We have an opcode that this parser doesn't know about, skip the
+ // number of ULEB128 numbers that is says to skip in the prologue's
+ // standard_opcode_lengths array
uint8_t n = prologue.standard_opcode_lengths[opcode - 1];
log->Printf("0x%8.8x: Special : Unknown skipping %u ULEB128 values.",
op_offset, n);
@@ -357,9 +357,9 @@ dw_offset_t DWARFDebugLine::DumpStatementOpcodes(
//----------------------------------------------------------------------
// Parse
//
-// Parse the entire line table contents calling callback each time a
-// new prologue is parsed and every time a new row is to be added to
-// the line table.
+// Parse the entire line table contents calling callback each time a new
+// prologue is parsed and every time a new row is to be added to the line
+// table.
//----------------------------------------------------------------------
void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data,
DWARFDebugLine::State::Callback callback,
@@ -444,7 +444,7 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
bool DWARFDebugLine::ParseSupportFiles(
const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
- const char *cu_comp_dir, dw_offset_t stmt_list,
+ const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list,
FileSpecList &support_files) {
lldb::offset_t offset = stmt_list;
@@ -463,7 +463,7 @@ bool DWARFDebugLine::ParseSupportFiles(
for (uint32_t file_idx = 1;
prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx) {
if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
- file_spec.SetFile(remapped_file, false);
+ file_spec.SetFile(remapped_file, false, FileSpec::Style::native);
support_files.Append(file_spec);
}
return true;
@@ -472,9 +472,9 @@ bool DWARFDebugLine::ParseSupportFiles(
//----------------------------------------------------------------------
// ParseStatementTable
//
-// Parse a single line table (prologue and all rows) and call the
-// callback function once for the prologue (row in state will be zero)
-// and each time a row is to be added to the line table.
+// Parse a single line table (prologue and all rows) and call the callback
+// function once for the prologue (row in state will be zero) and each time a
+// row is to be added to the line table.
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
@@ -511,8 +511,8 @@ bool DWARFDebugLine::ParseStatementTable(
uint8_t opcode = debug_line_data.GetU8(offset_ptr);
if (opcode == 0) {
- // Extended Opcodes always start with a zero opcode followed by
- // a uleb128 length so you can skip ones you don't know about
+ // Extended Opcodes always start with a zero opcode followed by a uleb128
+ // length so you can skip ones you don't know about
lldb::offset_t ext_offset = *offset_ptr;
dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr);
dw_offset_t arg_size = len - (*offset_ptr - ext_offset);
@@ -522,12 +522,12 @@ bool DWARFDebugLine::ParseStatementTable(
switch (sub_opcode) {
case DW_LNE_end_sequence:
// Set the end_sequence register of the state machine to true and
- // append a row to the matrix using the current values of the
- // state-machine registers. Then reset the registers to the initial
- // values specified above. Every statement program sequence must end
- // with a DW_LNE_end_sequence instruction which creates a row whose
- // address is that of the byte after the last target machine instruction
- // of the sequence.
+ // append a row to the matrix using the current values of the state-
+ // machine registers. Then reset the registers to the initial values
+ // specified above. Every statement program sequence must end with a
+ // DW_LNE_end_sequence instruction which creates a row whose address is
+ // that of the byte after the last target machine instruction of the
+ // sequence.
state.end_sequence = true;
state.AppendRowToMatrix(*offset_ptr);
state.Reset();
@@ -537,8 +537,8 @@ bool DWARFDebugLine::ParseStatementTable(
// Takes a single relocatable address as an operand. The size of the
// operand is the size appropriate to hold an address on the target
// machine. Set the address register to the value given by the
- // relocatable address. All of the other statement program opcodes
- // that affect the address register add a delta to it. This instruction
+ // relocatable address. All of the other statement program opcodes that
+ // affect the address register add a delta to it. This instruction
// stores a relocatable value into it instead.
if (arg_size == 4)
state.address = debug_line_data.GetU32(offset_ptr);
@@ -549,24 +549,24 @@ bool DWARFDebugLine::ParseStatementTable(
case DW_LNE_define_file:
// Takes 4 arguments. The first is a null terminated string containing
// a source file name. The second is an unsigned LEB128 number
- // representing
- // the directory index of the directory in which the file was found. The
- // third is an unsigned LEB128 number representing the time of last
- // modification of the file. The fourth is an unsigned LEB128 number
- // representing the length in bytes of the file. The time and length
- // fields may contain LEB128(0) if the information is not available.
+ // representing the directory index of the directory in which the file
+ // was found. The third is an unsigned LEB128 number representing the
+ // time of last modification of the file. The fourth is an unsigned
+ // LEB128 number representing the length in bytes of the file. The time
+ // and length fields may contain LEB128(0) if the information is not
+ // available.
//
// The directory index represents an entry in the include_directories
- // section of the statement program prologue. The index is LEB128(0)
- // if the file was found in the current directory of the compilation,
+ // section of the statement program prologue. The index is LEB128(0) if
+ // the file was found in the current directory of the compilation,
// LEB128(1) if it was found in the first directory in the
// include_directories section, and so on. The directory index is
// ignored for file names that represent full path names.
//
// The files are numbered, starting at 1, in the order in which they
- // appear; the names in the prologue come before names defined by
- // the DW_LNE_define_file instruction. These numbers are used in the
- // file register of the state machine.
+ // appear; the names in the prologue come before names defined by the
+ // DW_LNE_define_file instruction. These numbers are used in the file
+ // register of the state machine.
{
FileNameEntry fileEntry;
fileEntry.name = debug_line_data.GetCStr(offset_ptr);
@@ -578,8 +578,9 @@ bool DWARFDebugLine::ParseStatementTable(
break;
default:
- // Length doesn't include the zero opcode byte or the length itself, but
- // it does include the sub_opcode, so we have to adjust for that below
+ // Length doesn't include the zero opcode byte or the length itself,
+ // but it does include the sub_opcode, so we have to adjust for that
+ // below
(*offset_ptr) += arg_size;
break;
}
@@ -587,23 +588,23 @@ bool DWARFDebugLine::ParseStatementTable(
switch (opcode) {
// Standard Opcodes
case DW_LNS_copy:
- // Takes no arguments. Append a row to the matrix using the
- // current values of the state-machine registers. Then set
- // the basic_block register to false.
+ // Takes no arguments. Append a row to the matrix using the current
+ // values of the state-machine registers. Then set the basic_block
+ // register to false.
state.AppendRowToMatrix(*offset_ptr);
break;
case DW_LNS_advance_pc:
// Takes a single unsigned LEB128 operand, multiplies it by the
- // min_inst_length field of the prologue, and adds the
- // result to the address register of the state machine.
+ // min_inst_length field of the prologue, and adds the result to the
+ // address register of the state machine.
state.address +=
debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length;
break;
case DW_LNS_advance_line:
- // Takes a single signed LEB128 operand and adds that value to
- // the line register of the state machine.
+ // Takes a single signed LEB128 operand and adds that value to the line
+ // register of the state machine.
state.line += debug_line_data.GetSLEB128(offset_ptr);
break;
@@ -614,35 +615,35 @@ bool DWARFDebugLine::ParseStatementTable(
break;
case DW_LNS_set_column:
- // Takes a single unsigned LEB128 operand and stores it in the
- // column register of the state machine.
+ // Takes a single unsigned LEB128 operand and stores it in the column
+ // register of the state machine.
state.column = debug_line_data.GetULEB128(offset_ptr);
break;
case DW_LNS_negate_stmt:
- // Takes no arguments. Set the is_stmt register of the state
- // machine to the logical negation of its current value.
+ // Takes no arguments. Set the is_stmt register of the state machine to
+ // the logical negation of its current value.
state.is_stmt = !state.is_stmt;
break;
case DW_LNS_set_basic_block:
- // Takes no arguments. Set the basic_block register of the
- // state machine to true
+ // Takes no arguments. Set the basic_block register of the state
+ // machine to true
state.basic_block = true;
break;
case DW_LNS_const_add_pc:
- // Takes no arguments. Add to the address register of the state
- // machine the address increment value corresponding to special
- // opcode 255. The motivation for DW_LNS_const_add_pc is this:
- // when the statement program needs to advance the address by a
- // small amount, it can use a single special opcode, which occupies
- // a single byte. When it needs to advance the address by up to
- // twice the range of the last special opcode, it can use
- // DW_LNS_const_add_pc followed by a special opcode, for a total
- // of two bytes. Only if it needs to advance the address by more
- // than twice that range will it need to use both DW_LNS_advance_pc
- // and a special opcode, requiring three or more bytes.
+ // Takes no arguments. Add to the address register of the state machine
+ // the address increment value corresponding to special opcode 255. The
+ // motivation for DW_LNS_const_add_pc is this: when the statement
+ // program needs to advance the address by a small amount, it can use a
+ // single special opcode, which occupies a single byte. When it needs
+ // to advance the address by up to twice the range of the last special
+ // opcode, it can use DW_LNS_const_add_pc followed by a special opcode,
+ // for a total of two bytes. Only if it needs to advance the address by
+ // more than twice that range will it need to use both
+ // DW_LNS_advance_pc and a special opcode, requiring three or more
+ // bytes.
{
uint8_t adjust_opcode = 255 - prologue->opcode_base;
dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) *
@@ -652,40 +653,40 @@ bool DWARFDebugLine::ParseStatementTable(
break;
case DW_LNS_fixed_advance_pc:
- // Takes a single uhalf operand. Add to the address register of
- // the state machine the value of the (unencoded) operand. This
- // is the only extended opcode that takes an argument that is not
- // a variable length number. The motivation for DW_LNS_fixed_advance_pc
- // is this: existing assemblers cannot emit DW_LNS_advance_pc or
- // special opcodes because they cannot encode LEB128 numbers or
- // judge when the computation of a special opcode overflows and
- // requires the use of DW_LNS_advance_pc. Such assemblers, however,
- // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
+ // Takes a single uhalf operand. Add to the address register of the
+ // state machine the value of the (unencoded) operand. This is the only
+ // extended opcode that takes an argument that is not a variable length
+ // number. The motivation for DW_LNS_fixed_advance_pc is this: existing
+ // assemblers cannot emit DW_LNS_advance_pc or special opcodes because
+ // they cannot encode LEB128 numbers or judge when the computation of a
+ // special opcode overflows and requires the use of DW_LNS_advance_pc.
+ // Such assemblers, however, can use DW_LNS_fixed_advance_pc instead,
+ // sacrificing compression.
state.address += debug_line_data.GetU16(offset_ptr);
break;
case DW_LNS_set_prologue_end:
- // Takes no arguments. Set the prologue_end register of the
- // state machine to true
+ // Takes no arguments. Set the prologue_end register of the state
+ // machine to true
state.prologue_end = true;
break;
case DW_LNS_set_epilogue_begin:
- // Takes no arguments. Set the basic_block register of the
- // state machine to true
+ // Takes no arguments. Set the basic_block register of the state
+ // machine to true
state.epilogue_begin = true;
break;
case DW_LNS_set_isa:
- // Takes a single unsigned LEB128 operand and stores it in the
- // column register of the state machine.
+ // Takes a single unsigned LEB128 operand and stores it in the column
+ // register of the state machine.
state.isa = debug_line_data.GetULEB128(offset_ptr);
break;
default:
- // Handle any unknown standard opcodes here. We know the lengths
- // of such opcodes because they are specified in the prologue
- // as a multiple of LEB128 operands for each opcode.
+ // Handle any unknown standard opcodes here. We know the lengths of
+ // such opcodes because they are specified in the prologue as a
+ // multiple of LEB128 operands for each opcode.
{
uint8_t i;
assert(static_cast<size_t>(opcode - 1) <
@@ -702,32 +703,32 @@ bool DWARFDebugLine::ParseStatementTable(
// A special opcode value is chosen based on the amount that needs
// to be added to the line and address registers. The maximum line
- // increment for a special opcode is the value of the line_base
- // field in the header, plus the value of the line_range field,
- // minus 1 (line base + line range - 1). If the desired line
- // increment is greater than the maximum line increment, a standard
- // opcode must be used instead of a special opcode. The "address
- // advance" is calculated by dividing the desired address increment
- // by the minimum_instruction_length field from the header. The
- // special opcode is then calculated using the following formula:
+ // increment for a special opcode is the value of the line_base field in
+ // the header, plus the value of the line_range field, minus 1 (line base
+ // + line range - 1). If the desired line increment is greater than the
+ // maximum line increment, a standard opcode must be used instead of a
+ // special opcode. The "address advance" is calculated by dividing the
+ // desired address increment by the minimum_instruction_length field from
+ // the header. The special opcode is then calculated using the following
+ // formula:
//
// opcode = (desired line increment - line_base) + (line_range * address
// advance) + opcode_base
//
- // If the resulting opcode is greater than 255, a standard opcode
- // must be used instead.
+ // If the resulting opcode is greater than 255, a standard opcode must be
+ // used instead.
//
- // To decode a special opcode, subtract the opcode_base from the
- // opcode itself to give the adjusted opcode. The amount to
- // increment the address register is the result of the adjusted
- // opcode divided by the line_range multiplied by the
- // minimum_instruction_length field from the header. That is:
+ // To decode a special opcode, subtract the opcode_base from the opcode
+ // itself to give the adjusted opcode. The amount to increment the
+ // address register is the result of the adjusted opcode divided by the
+ // line_range multiplied by the minimum_instruction_length field from the
+ // header. That is:
//
// address increment = (adjusted opcode / line_range) *
// minimum_instruction_length
//
- // The amount to increment the line register is the line_base plus
- // the result of the adjusted opcode modulo the line_range. That is:
+ // The amount to increment the line register is the line_base plus the
+ // result of the adjusted opcode modulo the line_range. That is:
//
// line increment = line_base + (adjusted opcode % line_range)
@@ -755,8 +756,8 @@ static void ParseStatementTableCallback(dw_offset_t offset,
void *userData) {
DWARFDebugLine::LineTable *line_table = (DWARFDebugLine::LineTable *)userData;
if (state.row == DWARFDebugLine::State::StartParsingLineTable) {
- // Just started parsing the line table, so lets keep a reference to
- // the prologue using the supplied shared pointer
+ // Just started parsing the line table, so lets keep a reference to the
+ // prologue using the supplied shared pointer
line_table->prologue = state.prologue;
} else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) {
// Done parsing line table, nothing to do for the cleanup
@@ -769,8 +770,8 @@ static void ParseStatementTableCallback(dw_offset_t offset,
//----------------------------------------------------------------------
// ParseStatementTable
//
-// Parse a line table at offset and populate the LineTable class with
-// the prologue and all rows.
+// Parse a line table at offset and populate the LineTable class with the
+// prologue and all rows.
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
@@ -861,11 +862,11 @@ void DWARFDebugLine::Prologue::Dump(Log *log) {
// buff.Append8(0); // Terminate the file names section with empty string
//}
-bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir,
- FileSpec &file) const {
+bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx,
+ const lldb_private::FileSpec &comp_dir, FileSpec &file) const {
uint32_t idx = file_idx - 1; // File indexes are 1 based...
if (idx < file_names.size()) {
- file.SetFile(file_names[idx].name, false);
+ file.SetFile(file_names[idx].name, false, FileSpec::Style::native);
if (file.IsRelative()) {
if (file_names[idx].dir_idx > 0) {
const uint32_t dir_idx = file_names[idx].dir_idx - 1;
@@ -876,7 +877,7 @@ bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir,
}
}
- if (comp_dir && comp_dir[0])
+ if (comp_dir)
file.PrependPathComponent(comp_dir);
}
return true;
@@ -936,11 +937,10 @@ uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address,
if (address < cu_high_pc)
return rows.size() - 1;
} else {
- // Rely on fact that we are using a std::vector and we can do
- // pointer arithmetic to find the row index (which will be one less
- // that what we found since it will find the first position after
- // the current address) since std::vector iterators are just
- // pointers to the container type.
+ // Rely on fact that we are using a std::vector and we can do pointer
+ // arithmetic to find the row index (which will be one less that what we
+ // found since it will find the first position after the current address)
+ // since std::vector iterators are just pointers to the container type.
index = pos - begin_pos;
if (pos->address > address) {
if (index > 0)
@@ -1005,9 +1005,9 @@ static bool AddressLessThan(const DWARFDebugLine::Row &a,
return a.address < b.address;
}
-// Insert a row at the correct address if the addresses can be out of
-// order which can only happen when we are linking a line table that
-// may have had it's contents rearranged.
+// Insert a row at the correct address if the addresses can be out of order
+// which can only happen when we are linking a line table that may have had
+// it's contents rearranged.
void DWARFDebugLine::Row::Insert(Row::collection &state_coll,
const Row &state) {
// If we don't have anything yet, or if the address of the last state in our
@@ -1020,12 +1020,12 @@ void DWARFDebugLine::Row::Insert(Row::collection &state_coll,
state_coll.begin(), state_coll.end(), state, AddressLessThan));
// If the addresses are equal, we can safely replace the previous entry
- // with the current one if the one it is replacing is an end_sequence entry.
- // We currently always place an extra end sequence when ever we exit a valid
- // address range for a function in case the functions get rearranged by
- // optimizations or by order specifications. These extra end sequences will
- // disappear by getting replaced with valid consecutive entries within a
- // compile unit if there are no gaps.
+ // with the current one if the one it is replacing is an end_sequence
+ // entry. We currently always place an extra end sequence when ever we exit
+ // a valid address range for a function in case the functions get
+ // rearranged by optimizations or by order specifications. These extra end
+ // sequences will disappear by getting replaced with valid consecutive
+ // entries within a compile unit if there are no gaps.
if (range.first == range.second) {
state_coll.insert(range.first, state);
} else {
@@ -1065,10 +1065,9 @@ void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); }
// DWARFDebugLine::State::AppendRowToMatrix
//----------------------------------------------------------------------
void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) {
- // Each time we are to add an entry into the line table matrix
- // call the callback function so that someone can do something with
- // the current state of the state machine (like build a line table
- // or dump the line table!)
+ // Each time we are to add an entry into the line table matrix call the
+ // callback function so that someone can do something with the current state
+ // of the state machine (like build a line table or dump the line table!)
if (log) {
if (row == 0) {
log->PutCString("Address Line Column File ISA Flags");
@@ -1088,8 +1087,8 @@ void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) {
// DWARFDebugLine::State::Finalize
//----------------------------------------------------------------------
void DWARFDebugLine::State::Finalize(dw_offset_t offset) {
- // Call the callback with a special row state when we are done parsing a
- // line table
+ // Call the callback with a special row state when we are done parsing a line
+ // table
row = DoneParsingLineTable;
if (callback)
callback(offset, *this, callbackUserData);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index ea02cfed6e01..3ab15ac59028 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -90,7 +90,7 @@ public:
include_directories.clear();
file_names.clear();
}
- bool GetFile(uint32_t file_idx, const char *comp_dir,
+ bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir,
lldb_private::FileSpec &file) const;
};
@@ -199,7 +199,8 @@ public:
static bool
ParseSupportFiles(const lldb::ModuleSP &module_sp,
const lldb_private::DWARFDataExtractor &debug_line_data,
- const char *cu_comp_dir, dw_offset_t stmt_list,
+ const lldb_private::FileSpec &cu_comp_dir,
+ dw_offset_t stmt_list,
lldb_private::FileSpecList &support_files);
static bool
ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
deleted file mode 100644
index 766899c497b0..000000000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFDebugPubnames.h"
-
-#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/Timer.h"
-
-#include "DWARFCompileUnit.h"
-#include "DWARFDIECollection.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFFormValue.h"
-#include "LogChannelDWARF.h"
-#include "SymbolFileDWARF.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-DWARFDebugPubnames::DWARFDebugPubnames() : m_sets() {}
-
-bool DWARFDebugPubnames::Extract(const DWARFDataExtractor &data) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
- (uint64_t)data.GetByteSize());
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
- if (log)
- log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
- (uint64_t)data.GetByteSize());
-
- if (data.ValidOffset(0)) {
- lldb::offset_t offset = 0;
-
- DWARFDebugPubnamesSet set;
- while (data.ValidOffset(offset)) {
- if (set.Extract(data, &offset)) {
- m_sets.push_back(set);
- offset = set.GetOffsetOfNextEntry();
- } else
- break;
- }
- if (log)
- Dump(log);
- return true;
- }
- return false;
-}
-
-bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF *dwarf2Data) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "DWARFDebugPubnames::GeneratePubnames (data = %p)",
- static_cast<void *>(dwarf2Data));
-
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
- if (log)
- log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
- static_cast<void *>(dwarf2Data));
-
- m_sets.clear();
- DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
- if (debug_info) {
- uint32_t cu_idx = 0;
- const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
- for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
-
- DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
-
- DWARFFormValue::FixedFormSizes fixed_form_sizes =
- DWARFFormValue::GetFixedFormSizesForAddressSize(
- cu->GetAddressByteSize(), cu->IsDWARF64());
-
- bool clear_dies = cu->ExtractDIEsIfNeeded(false) > 1;
-
- DWARFDIECollection dies;
- const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_subprogram, dies) +
- cu->AppendDIEsWithTag(DW_TAG_variable, dies);
-
- dw_offset_t cu_offset = cu->GetOffset();
- DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
- cu->GetNextCompileUnitOffset() -
- cu_offset);
-
- size_t die_idx;
- for (die_idx = 0; die_idx < die_count; ++die_idx) {
- DWARFDIE die = dies.GetDIEAtIndex(die_idx);
- DWARFAttributes attributes;
- const char *name = NULL;
- const char *mangled = NULL;
- bool add_die = false;
- const size_t num_attributes = die.GetDIE()->GetAttributes(
- die.GetCU(), fixed_form_sizes, attributes);
- if (num_attributes > 0) {
- uint32_t i;
-
- dw_tag_t tag = die.Tag();
-
- for (i = 0; i < num_attributes; ++i) {
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- switch (attr) {
- case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- name = form_value.AsCString();
- break;
-
- case DW_AT_MIPS_linkage_name:
- case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- mangled = form_value.AsCString();
- break;
-
- case DW_AT_low_pc:
- case DW_AT_ranges:
- case DW_AT_entry_pc:
- if (tag == DW_TAG_subprogram)
- add_die = true;
- break;
-
- case DW_AT_location:
- if (tag == DW_TAG_variable) {
- DWARFDIE parent_die = die.GetParent();
- while (parent_die) {
- switch (parent_die.Tag()) {
- case DW_TAG_subprogram:
- case DW_TAG_lexical_block:
- case DW_TAG_inlined_subroutine:
- // Even if this is a function level static, we don't add it.
- // We could theoretically
- // add these if we wanted to by introspecting into the
- // DW_AT_location and seeing
- // if the location describes a hard coded address, but we
- // don't want the performance
- // penalty of that right now.
- add_die = false;
- parent_die.Clear(); // Terminate the while loop.
- break;
-
- case DW_TAG_compile_unit:
- add_die = true;
- parent_die.Clear(); // Terminate the while loop.
- break;
-
- default:
- parent_die =
- parent_die.GetParent(); // Keep going in the while loop.
- break;
- }
- }
- }
- break;
- }
- }
- }
-
- if (add_die && (name || mangled)) {
- pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(),
- mangled ? mangled : name);
- }
- }
-
- if (pubnames_set.NumDescriptors() > 0) {
- m_sets.push_back(pubnames_set);
- }
-
- // Keep memory down by clearing DIEs if this generate function
- // caused them to be parsed
- if (clear_dies)
- cu->ClearDIEs(true);
- }
- }
- if (m_sets.empty())
- return false;
- if (log)
- Dump(log);
- return true;
-}
-
-bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data) {
- m_sets.clear();
- DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
- if (debug_info) {
- uint32_t cu_idx = 0;
- const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
- for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- DWARFDIECollection dies;
- const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_base_type, dies);
- dw_offset_t cu_offset = cu->GetOffset();
- DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
- cu->GetNextCompileUnitOffset() -
- cu_offset);
-
- size_t die_idx;
- for (die_idx = 0; die_idx < die_count; ++die_idx) {
- DWARFDIE die = dies.GetDIEAtIndex(die_idx);
- const char *name = die.GetName();
-
- if (name)
- pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
- }
-
- if (pubnames_set.NumDescriptors() > 0) {
- m_sets.push_back(pubnames_set);
- }
- }
- }
- return !m_sets.empty();
-}
-
-void DWARFDebugPubnames::Dump(Log *s) const {
- if (m_sets.empty())
- s->PutCString("< EMPTY >\n");
- else {
- const_iterator pos;
- const_iterator end = m_sets.end();
-
- for (pos = m_sets.begin(); pos != end; ++pos)
- (*pos).Dump(s);
- }
-}
-
-bool DWARFDebugPubnames::Find(const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offsets) const {
- const_iterator pos;
- const_iterator end = m_sets.end();
-
- die_offsets.clear();
-
- for (pos = m_sets.begin(); pos != end; ++pos) {
- (*pos).Find(name, ignore_case, die_offsets);
- }
-
- return !die_offsets.empty();
-}
-
-bool DWARFDebugPubnames::Find(const RegularExpression &regex,
- std::vector<dw_offset_t> &die_offsets) const {
- const_iterator pos;
- const_iterator end = m_sets.end();
-
- die_offsets.clear();
-
- for (pos = m_sets.begin(); pos != end; ++pos) {
- (*pos).Find(regex, die_offsets);
- }
-
- return !die_offsets.empty();
-}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
deleted file mode 100644
index 57dabade012c..000000000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- DWARFDebugPubnames.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFDebugPubnames_h_
-#define SymbolFileDWARF_DWARFDebugPubnames_h_
-
-#include "SymbolFileDWARF.h"
-
-#include <list>
-
-#include "DWARFDebugPubnamesSet.h"
-
-class DWARFDebugPubnames {
-public:
- DWARFDebugPubnames();
- bool Extract(const lldb_private::DWARFDataExtractor &data);
- bool GeneratePubnames(SymbolFileDWARF *dwarf2Data);
- bool GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data);
-
- void Dump(lldb_private::Log *s) const;
- bool Find(const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offset_coll) const;
- bool Find(const lldb_private::RegularExpression &regex,
- std::vector<dw_offset_t> &die_offsets) const;
-
-protected:
- typedef std::list<DWARFDebugPubnamesSet> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
-
- collection m_sets;
-};
-
-#endif // SymbolFileDWARF_DWARFDebugPubnames_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
deleted file mode 100644
index 21e2482783a1..000000000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFDebugPubnamesSet.h"
-
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/RegularExpression.h"
-
-#include "SymbolFileDWARF.h"
-
-using namespace lldb_private;
-
-DWARFDebugPubnamesSet::DWARFDebugPubnamesSet()
- : m_offset(DW_INVALID_OFFSET), m_header(), m_descriptors(),
- m_name_to_descriptor_index() {}
-
-DWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset,
- dw_offset_t cu_die_offset,
- dw_offset_t cu_die_length)
- : m_offset(debug_aranges_offset), m_header(), m_descriptors(),
- m_name_to_descriptor_index() {
- m_header.length =
- 10; // set the length to only include the header right for now
- m_header.version = 2; // The DWARF version number
- m_header.die_offset = cu_die_offset; // compile unit .debug_info offset
- m_header.die_length = cu_die_length; // compile unit .debug_info length
-}
-
-void DWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset,
- const char *name) {
- if (name && name[0]) {
- // Adjust our header length
- m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
- Descriptor pubnameDesc(cu_rel_offset, name);
- m_descriptors.push_back(pubnameDesc);
- }
-}
-
-void DWARFDebugPubnamesSet::Clear() {
- m_offset = DW_INVALID_OFFSET;
- m_header.length = 10;
- m_header.version = 2;
- m_header.die_offset = DW_INVALID_OFFSET;
- m_header.die_length = 0;
- m_descriptors.clear();
-}
-
-//----------------------------------------------------------------------
-// InitNameIndexes
-//----------------------------------------------------------------------
-void DWARFDebugPubnamesSet::InitNameIndexes() const {
- // Create the name index vector to be able to quickly search by name
- const size_t count = m_descriptors.size();
- for (uint32_t idx = 0; idx < count; ++idx) {
- const char *name = m_descriptors[idx].name.c_str();
- if (name && name[0])
- m_name_to_descriptor_index.insert(
- cstr_to_index_mmap::value_type(name, idx));
- }
-}
-
-bool DWARFDebugPubnamesSet::Extract(const DWARFDataExtractor &data,
- lldb::offset_t *offset_ptr) {
- if (data.ValidOffset(*offset_ptr)) {
- m_descriptors.clear();
- m_offset = *offset_ptr;
- m_header.length = data.GetDWARFInitialLength(offset_ptr);
- m_header.version = data.GetU16(offset_ptr);
- m_header.die_offset = data.GetDWARFOffset(offset_ptr);
- m_header.die_length = data.GetDWARFOffset(offset_ptr);
-
- Descriptor pubnameDesc;
- while (data.ValidOffset(*offset_ptr)) {
- pubnameDesc.offset = data.GetDWARFOffset(offset_ptr);
-
- if (pubnameDesc.offset) {
- const char *name = data.GetCStr(offset_ptr);
- if (name && name[0]) {
- pubnameDesc.name = name;
- m_descriptors.push_back(pubnameDesc);
- }
- } else
- break; // We are done if we get a zero 4 byte offset
- }
-
- return !m_descriptors.empty();
- }
- return false;
-}
-
-dw_offset_t DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const {
- return m_offset + m_header.length + 4;
-}
-
-void DWARFDebugPubnamesSet::Dump(Log *log) const {
- log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, "
- "die_offset = 0x%8.8x, die_length = 0x%8.8x",
- m_header.length, m_header.version, m_header.die_offset,
- m_header.die_length);
-
- bool verbose = log->GetVerbose();
-
- DescriptorConstIter pos;
- DescriptorConstIter end = m_descriptors.end();
- for (pos = m_descriptors.begin(); pos != end; ++pos) {
- if (verbose)
- log->Printf("0x%8.8x + 0x%8.8x = 0x%8.8x: %s", pos->offset,
- m_header.die_offset, pos->offset + m_header.die_offset,
- pos->name.c_str());
- else
- log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset,
- pos->name.c_str());
- }
-}
-
-void DWARFDebugPubnamesSet::Find(
- const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offset_coll) const {
- if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
- InitNameIndexes();
-
- std::pair<cstr_to_index_mmap::const_iterator,
- cstr_to_index_mmap::const_iterator>
- range(m_name_to_descriptor_index.equal_range(name));
- for (cstr_to_index_mmap::const_iterator pos = range.first;
- pos != range.second; ++pos)
- die_offset_coll.push_back(m_header.die_offset +
- m_descriptors[(*pos).second].offset);
-}
-
-void DWARFDebugPubnamesSet::Find(
- const RegularExpression &regex,
- std::vector<dw_offset_t> &die_offset_coll) const {
- DescriptorConstIter pos;
- DescriptorConstIter end = m_descriptors.end();
- for (pos = m_descriptors.begin(); pos != end; ++pos) {
- if (regex.Execute(pos->name))
- die_offset_coll.push_back(m_header.die_offset + pos->offset);
- }
-}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
deleted file mode 100644
index 6e7d3f38aa85..000000000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//===-- DWARFDebugPubnamesSet.h ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFDebugPubnamesSet_h_
-#define SymbolFileDWARF_DWARFDebugPubnamesSet_h_
-
-#include "SymbolFileDWARF.h"
-#include <map>
-#include <string>
-#include <vector>
-#if __cplusplus >= 201103L || defined(_MSC_VER)
-#include <unordered_map>
-#else
-#include <ext/hash_map>
-#endif
-
-#include "lldb/Core/STLUtils.h"
-
-class DWARFDebugPubnamesSet {
-public:
- struct Header {
- uint32_t length; // length of the set of entries for this compilation unit,
- // not including the length field itself
- uint16_t version; // The DWARF version number
- uint32_t die_offset; // compile unit .debug_info offset
- uint32_t die_length; // compile unit .debug_info length
- Header()
- : length(10), version(2), die_offset(DW_INVALID_OFFSET), die_length(0) {
- }
- };
-
- struct Descriptor {
- Descriptor() : offset(), name() {}
-
- Descriptor(dw_offset_t the_offset, const char *the_name)
- : offset(the_offset), name(the_name ? the_name : "") {}
-
- dw_offset_t offset;
- std::string name;
- };
-
- DWARFDebugPubnamesSet();
- DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset,
- dw_offset_t cu_die_offset, dw_offset_t die_length);
- dw_offset_t GetOffset() const { return m_offset; }
- void SetOffset(dw_offset_t offset) { m_offset = offset; }
- DWARFDebugPubnamesSet::Header &GetHeader() { return m_header; }
- const DWARFDebugPubnamesSet::Header &GetHeader() const { return m_header; }
- const DWARFDebugPubnamesSet::Descriptor *GetDescriptor(uint32_t i) const {
- if (i < m_descriptors.size())
- return &m_descriptors[i];
- return NULL;
- }
- uint32_t NumDescriptors() const { return m_descriptors.size(); }
- void AddDescriptor(dw_offset_t cu_rel_offset, const char *name);
- void Clear();
- bool Extract(const lldb_private::DWARFDataExtractor &debug_pubnames_data,
- lldb::offset_t *offset_ptr);
- void Dump(lldb_private::Log *s) const;
- void InitNameIndexes() const;
- void Find(const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offset_coll) const;
- void Find(const lldb_private::RegularExpression &regex,
- std::vector<dw_offset_t> &die_offsets) const;
- dw_offset_t GetOffsetOfNextEntry() const;
-
-protected:
- typedef std::vector<Descriptor> DescriptorColl;
- typedef DescriptorColl::iterator DescriptorIter;
- typedef DescriptorColl::const_iterator DescriptorConstIter;
-
- dw_offset_t m_offset;
- Header m_header;
-#if __cplusplus >= 201103L || defined(_MSC_VER)
- typedef std::unordered_multimap<const char *, uint32_t,
- std::hash<const char *>,
- CStringEqualBinaryPredicate>
- cstr_to_index_mmap;
-#else
- typedef __gnu_cxx::hash_multimap<const char *, uint32_t,
- __gnu_cxx::hash<const char *>,
- CStringEqualBinaryPredicate>
- cstr_to_index_mmap;
-#endif
- DescriptorColl m_descriptors;
- mutable cstr_to_index_mmap m_name_to_descriptor_index;
-};
-
-#endif // SymbolFileDWARF_DWARFDebugPubnamesSet_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index a8c48b7f2f84..89e27efb3cc2 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -89,8 +89,8 @@ void DWARFDebugRanges::Dump(Stream &s,
debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
- // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits
- // of ones
+ // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of
+ // ones
if (begin == 0xFFFFFFFFull && addr_size == 4)
begin = LLDB_INVALID_ADDRESS;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
index 79f2f221696b..dbaf0b0ed127 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
@@ -67,8 +67,8 @@ bool DWARFDeclContext::operator==(const DWARFDeclContext &rhs) const {
// First compare the tags before we do expensive name compares
for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos) {
if (pos->tag != rhs_pos->tag) {
- // Check for DW_TAG_structure_type and DW_TAG_class_type as they are often
- // used interchangeably in GCC
+ // Check for DW_TAG_structure_type and DW_TAG_class_type as they are
+ // often used interchangeably in GCC
if (pos->tag == DW_TAG_structure_type &&
rhs_pos->tag == DW_TAG_class_type)
continue;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
index 2ff0fe3aac41..1d927ba3bca3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
@@ -473,16 +473,6 @@ const char *DW_ORD_value_to_name(uint32_t val) {
return llvmstr.data();
}
-const char *DW_DSC_value_to_name(uint32_t val) {
- static char invalid[100];
- llvm::StringRef llvmstr = llvm::dwarf::DiscriminantString(val);
- if (llvmstr.empty()) {
- snprintf(invalid, sizeof(invalid), "Unknown DW_DSC constant: 0x%x", val);
- return invalid;
- }
- return llvmstr.data();
-}
-
const char *DW_LNS_value_to_name(uint32_t val) {
static char invalid[100];
llvm::StringRef llvmstr = llvm::dwarf::LNStandardString(val);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
index 038f5706c060..926f83b3564a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -58,8 +58,6 @@ const char *DW_INL_value_to_name(uint32_t val);
const char *DW_ORD_value_to_name(uint32_t val);
-const char *DW_DSC_value_to_name(uint32_t val);
-
const char *DW_LNS_value_to_name(uint32_t val);
const char *DW_LNE_value_to_name(uint32_t val);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index a21e313c2f81..4fde5748d3f3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -12,10 +12,10 @@
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/Stream.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFFormValue.h"
-class DWARFCompileUnit;
+class DWARFUnit;
using namespace lldb_private;
@@ -154,7 +154,7 @@ DWARFFormValue::GetFixedFormSizesForAddressSize(uint8_t addr_size,
DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {}
-DWARFFormValue::DWARFFormValue(const DWARFCompileUnit *cu, dw_form_t form)
+DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form)
: m_cu(cu), m_form(form), m_value() {}
void DWARFFormValue::Clear() {
@@ -177,7 +177,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
case DW_FORM_addr:
assert(m_cu);
m_value.value.uval = data.GetMaxU64(
- offset_ptr, DWARFCompileUnit::GetAddressByteSize(m_cu));
+ offset_ptr, DWARFUnit::GetAddressByteSize(m_cu));
break;
case DW_FORM_block2:
m_value.value.uval = data.GetU16(offset_ptr);
@@ -220,7 +220,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
case DW_FORM_strp:
assert(m_cu);
m_value.value.uval =
- data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);
+ data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
break;
// case DW_FORM_APPLE_db_str:
case DW_FORM_udata:
@@ -258,7 +258,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
case DW_FORM_sec_offset:
assert(m_cu);
m_value.value.uval =
- data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);
+ data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
break;
case DW_FORM_flag_present:
m_value.value.uval = 1;
@@ -296,11 +296,11 @@ bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
bool DWARFFormValue::SkipValue(dw_form_t form,
const DWARFDataExtractor &debug_info_data,
lldb::offset_t *offset_ptr,
- const DWARFCompileUnit *cu) {
+ const DWARFUnit *cu) {
uint8_t ref_addr_size;
switch (form) {
- // Blocks if inlined data that have a length field and the data bytes
- // inlined in the .debug_info
+ // Blocks if inlined data that have a length field and the data bytes inlined
+ // in the .debug_info
case DW_FORM_exprloc:
case DW_FORM_block: {
dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr);
@@ -330,7 +330,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
// Compile unit address sized values
case DW_FORM_addr:
- *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
+ *offset_ptr += DWARFUnit::GetAddressByteSize(cu);
return true;
case DW_FORM_ref_addr:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 2aa7460c4910..ef1a693b37c9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -13,7 +13,7 @@
#include "DWARFDataExtractor.h"
#include <stddef.h> // for NULL
-class DWARFCompileUnit;
+class DWARFUnit;
class DWARFFormValue {
public:
@@ -55,9 +55,9 @@ public:
};
DWARFFormValue();
- DWARFFormValue(const DWARFCompileUnit *cu, dw_form_t form);
- const DWARFCompileUnit *GetCompileUnit() const { return m_cu; }
- void SetCompileUnit(const DWARFCompileUnit *cu) { m_cu = cu; }
+ DWARFFormValue(const DWARFUnit *cu, dw_form_t form);
+ const DWARFUnit *GetCompileUnit() const { return m_cu; }
+ void SetCompileUnit(const DWARFUnit *cu) { m_cu = cu; }
dw_form_t Form() const { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType &Value() const { return m_value; }
@@ -79,7 +79,7 @@ public:
lldb::offset_t *offset_ptr) const;
static bool SkipValue(const dw_form_t form,
const lldb_private::DWARFDataExtractor &debug_info_data,
- lldb::offset_t *offset_ptr, const DWARFCompileUnit *cu);
+ lldb::offset_t *offset_ptr, const DWARFUnit *cu);
static bool IsBlockForm(const dw_form_t form);
static bool IsDataForm(const dw_form_t form);
static FixedFormSizes GetFixedFormSizesForAddressSize(uint8_t addr_size,
@@ -89,7 +89,7 @@ public:
static bool FormIsSupported(dw_form_t form);
protected:
- const DWARFCompileUnit *m_cu; // Compile unit for this form
+ const DWARFUnit *m_cu; // Compile unit for this form
dw_form_t m_form; // Form for this value
ValueType m_value; // Contains all data for the form
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
new file mode 100644
index 000000000000..4577f0557a1d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -0,0 +1,68 @@
+//===-- DWARFIndex.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+DWARFIndex::~DWARFIndex() = default;
+
+void DWARFIndex::ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+ DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+ DWARFDIE die = info.GetDIE(ref);
+ if (!die) {
+ ReportInvalidDIEOffset(ref.die_offset, name);
+ return;
+ }
+
+ // Exit early if we're searching exclusively for methods or selectors and
+ // we have a context specified (no methods in namespaces).
+ uint32_t looking_for_nonmethods =
+ name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector);
+ if (!looking_for_nonmethods && parent_decl_ctx.IsValid())
+ return;
+
+ // Otherwise, we need to also check that the context matches. If it does not
+ // match, we do nothing.
+ if (!SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+ return;
+
+ // In case of a full match, we just insert everything we find.
+ if (name_type_mask & eFunctionNameTypeFull) {
+ dies.push_back(die);
+ return;
+ }
+
+ // If looking for ObjC selectors, we need to also check if the name is a
+ // possible selector.
+ if (name_type_mask & eFunctionNameTypeSelector &&
+ ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) {
+ dies.push_back(die);
+ return;
+ }
+
+ bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod;
+ bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase;
+ if (looking_for_methods || looking_for_functions) {
+ // If we're looking for either methods or functions, we definitely want this
+ // die. Otherwise, only keep it if the die type matches what we are
+ // searching for.
+ if ((looking_for_methods && looking_for_functions) ||
+ looking_for_methods == die.IsMethod())
+ dies.push_back(die);
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
new file mode 100644
index 000000000000..77af67b8e60f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -0,0 +1,69 @@
+//===-- DWARFIndex.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_DWARFINDEX_H
+#define LLDB_DWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DIERef.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"
+
+class DWARFDebugInfo;
+class DWARFDeclContext;
+class DWARFDIE;
+
+namespace lldb_private {
+class DWARFIndex {
+public:
+ DWARFIndex(Module &module) : m_module(module) {}
+ virtual ~DWARFIndex();
+
+ virtual void Preload() = 0;
+
+ /// Finds global variables with the given base name. Any additional filtering
+ /// (e.g., to only retrieve variables from a given context) should be done by
+ /// the consumer.
+ virtual void GetGlobalVariables(ConstString basename, DIEArray &offsets) = 0;
+
+ virtual void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) = 0;
+ virtual void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) = 0;
+ virtual void GetObjCMethods(ConstString class_name, DIEArray &offsets) = 0;
+ virtual void GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) = 0;
+ virtual void GetTypes(ConstString name, DIEArray &offsets) = 0;
+ virtual void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) = 0;
+ virtual void GetNamespaces(ConstString name, DIEArray &offsets) = 0;
+ virtual void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) = 0;
+ virtual void GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) = 0;
+
+ virtual void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) = 0;
+ virtual void Dump(Stream &s) = 0;
+
+protected:
+ Module &m_module;
+
+ /// Helper function implementing common logic for processing function dies. If
+ /// the function given by "ref" matches search criteria given by
+ /// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies"
+ /// vector.
+ void ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+ DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask, std::vector<DWARFDIE> &dies);
+};
+} // namespace lldb_private
+
+#endif // LLDB_DWARFINDEX_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
new file mode 100644
index 000000000000..f44b2bb97b2b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -0,0 +1,755 @@
+//===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFUnit.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Host/StringConvert.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/Timer.h"
+
+#include "DWARFDIECollection.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "SymbolFileDWARFDwo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+extern int g_verbose;
+
+DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf)
+ : m_dwarf(dwarf), m_cancel_scopes(false) {}
+
+DWARFUnit::~DWARFUnit() {}
+
+//----------------------------------------------------------------------
+// Parses first DIE of a compile unit.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractUnitDIEIfNeeded() {
+ {
+ llvm::sys::ScopedReader lock(m_first_die_mutex);
+ if (m_first_die)
+ return; // Already parsed
+ }
+ llvm::sys::ScopedWriter lock(m_first_die_mutex);
+ if (m_first_die)
+ return; // Already parsed
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset);
+
+ // Set the offset to that of the first DIE and calculate the start of the
+ // next compilation unit header.
+ lldb::offset_t offset = GetFirstDIEOffset();
+
+ // We are in our compile unit, parse starting at the offset we were told to
+ // parse
+ const DWARFDataExtractor &data = GetData();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+ if (offset < GetNextCompileUnitOffset() &&
+ m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) {
+ AddUnitDIE(m_first_die);
+ return;
+ }
+
+ ExtractDIEsEndCheck(offset);
+}
+
+//----------------------------------------------------------------------
+// Parses a compile unit and indexes its DIEs if it hasn't already been done.
+// It will leave this compile unit extracted forever.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsIfNeeded() {
+ m_cancel_scopes = true;
+
+ {
+ llvm::sys::ScopedReader lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return; // Already parsed
+ }
+ llvm::sys::ScopedWriter lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return; // Already parsed
+
+ ExtractDIEsRWLocked();
+}
+
+//----------------------------------------------------------------------
+// Parses a compile unit and indexes its DIEs if it hasn't already been done.
+// It will clear this compile unit after returned instance gets out of scope,
+// no other ScopedExtractDIEs instance is running for this compile unit
+// and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs
+// lifetime.
+//----------------------------------------------------------------------
+DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() {
+ ScopedExtractDIEs scoped(this);
+
+ {
+ llvm::sys::ScopedReader lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return scoped; // Already parsed
+ }
+ llvm::sys::ScopedWriter lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return scoped; // Already parsed
+
+ // Otherwise m_die_array would be already populated.
+ lldbassert(!m_cancel_scopes);
+
+ ExtractDIEsRWLocked();
+ scoped.m_clear_dies = true;
+ return scoped;
+}
+
+DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit *cu) : m_cu(cu) {
+ lldbassert(m_cu);
+ m_cu->m_die_array_scoped_mutex.lock_shared();
+}
+
+DWARFUnit::ScopedExtractDIEs::~ScopedExtractDIEs() {
+ if (!m_cu)
+ return;
+ m_cu->m_die_array_scoped_mutex.unlock_shared();
+ if (!m_clear_dies || m_cu->m_cancel_scopes)
+ return;
+ // Be sure no other ScopedExtractDIEs is running anymore.
+ llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex);
+ llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex);
+ if (m_cu->m_cancel_scopes)
+ return;
+ m_cu->ClearDIEsRWLocked();
+}
+
+DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs)
+ : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) {
+ rhs.m_cu = nullptr;
+}
+
+DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=(
+ DWARFUnit::ScopedExtractDIEs &&rhs) {
+ m_cu = rhs.m_cu;
+ rhs.m_cu = nullptr;
+ m_clear_dies = rhs.m_clear_dies;
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Parses a compile unit and indexes its DIEs, m_die_array_mutex must be
+// held R/W and m_die_array must be empty.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsRWLocked() {
+ llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex);
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset);
+
+ // Set the offset to that of the first DIE and calculate the start of the
+ // next compilation unit header.
+ lldb::offset_t offset = GetFirstDIEOffset();
+ lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
+
+ DWARFDebugInfoEntry die;
+ // Keep a flat array of the DIE for binary lookup by DIE offset
+ Log *log(
+ LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
+ if (log) {
+ m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log,
+ "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at "
+ ".debug_info[0x%8.8x]",
+ GetOffset());
+ }
+
+ uint32_t depth = 0;
+ // We are in our compile unit, parse starting at the offset we were told to
+ // parse
+ const DWARFDataExtractor &data = GetData();
+ std::vector<uint32_t> die_index_stack;
+ die_index_stack.reserve(32);
+ die_index_stack.push_back(0);
+ bool prev_die_had_children = false;
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+ while (offset < next_cu_offset &&
+ die.FastExtract(data, this, fixed_form_sizes, &offset)) {
+ // if (log)
+ // log->Printf("0x%8.8x: %*.*s%s%s",
+ // die.GetOffset(),
+ // depth * 2, depth * 2, "",
+ // DW_TAG_value_to_name (die.Tag()),
+ // die.HasChildren() ? " *" : "");
+
+ const bool null_die = die.IsNULL();
+ if (depth == 0) {
+ assert(m_die_array.empty() && "Compile unit DIE already added");
+
+ // The average bytes per DIE entry has been seen to be around 14-20 so
+ // lets pre-reserve half of that since we are now stripping the NULL
+ // tags.
+
+ // Only reserve the memory if we are adding children of the main
+ // compile unit DIE. The compile unit DIE is always the first entry, so
+ // if our size is 1, then we are adding the first compile unit child
+ // DIE and should reserve the memory.
+ m_die_array.reserve(GetDebugInfoSize() / 24);
+ m_die_array.push_back(die);
+
+ if (!m_first_die)
+ AddUnitDIE(m_die_array.front());
+ } else {
+ if (null_die) {
+ if (prev_die_had_children) {
+ // This will only happen if a DIE says is has children but all it
+ // contains is a NULL tag. Since we are removing the NULL DIEs from
+ // the list (saves up to 25% in C++ code), we need a way to let the
+ // DIE know that it actually doesn't have children.
+ if (!m_die_array.empty())
+ m_die_array.back().SetEmptyChildren(true);
+ }
+ } else {
+ die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
+
+ if (die_index_stack.back())
+ m_die_array[die_index_stack.back()].SetSiblingIndex(
+ m_die_array.size() - die_index_stack.back());
+
+ // Only push the DIE if it isn't a NULL DIE
+ m_die_array.push_back(die);
+ }
+ }
+
+ if (null_die) {
+ // NULL DIE.
+ if (!die_index_stack.empty())
+ die_index_stack.pop_back();
+
+ if (depth > 0)
+ --depth;
+ if (depth == 0)
+ break; // We are done with this compile unit!
+
+ prev_die_had_children = false;
+ } else {
+ die_index_stack.back() = m_die_array.size() - 1;
+ // Normal DIE
+ const bool die_has_children = die.HasChildren();
+ if (die_has_children) {
+ die_index_stack.push_back(0);
+ ++depth;
+ }
+ prev_die_had_children = die_has_children;
+ }
+ }
+
+ if (!m_die_array.empty()) {
+ lldbassert(!m_first_die || m_first_die == m_die_array.front());
+ m_first_die = m_die_array.front();
+ }
+
+ m_die_array.shrink_to_fit();
+
+ ExtractDIEsEndCheck(offset);
+
+ if (m_dwo_symbol_file) {
+ DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ dwo_cu->ExtractDIEsIfNeeded();
+ }
+}
+
+//--------------------------------------------------------------------------
+// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded().
+//--------------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const {
+ // Give a little bit of info if we encounter corrupt DWARF (our offset should
+ // always terminate at or before the start of the next compilation unit
+ // header).
+ if (offset > GetNextCompileUnitOffset()) {
+ m_dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
+ "0x%8.8" PRIx64 "\n",
+ GetOffset(), offset);
+ }
+
+ Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+ if (log && log->GetVerbose()) {
+ StreamString strm;
+ Dump(&strm);
+ if (m_die_array.empty())
+ strm.Printf("error: no DIE for compile unit");
+ else
+ m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX);
+ log->PutString(strm.GetString());
+ }
+}
+
+// m_die_array_mutex must be already held as read/write.
+void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
+ uint64_t base_addr = cu_die.GetAttributeValueAsAddress(
+ m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ if (base_addr == LLDB_INVALID_ADDRESS)
+ base_addr = cu_die.GetAttributeValueAsAddress(
+ m_dwarf, this, DW_AT_entry_pc, 0);
+ SetBaseAddress(base_addr);
+
+ std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
+ m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die);
+ if (!dwo_symbol_file)
+ return;
+
+ DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
+ if (!dwo_cu)
+ return; // Can't fetch the compile unit from the dwo file.
+
+ DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
+ if (!dwo_cu_die.IsValid())
+ return; // Can't fetch the compile unit DIE from the dwo file.
+
+ uint64_t main_dwo_id =
+ cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0);
+ uint64_t sub_dwo_id =
+ dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
+ if (main_dwo_id != sub_dwo_id)
+ return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to
+ // a differectn compilation.
+
+ m_dwo_symbol_file = std::move(dwo_symbol_file);
+
+ dw_addr_t addr_base =
+ cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0);
+ dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
+ m_dwarf, this, DW_AT_GNU_ranges_base, 0);
+ dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
+}
+
+DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
+ if (DIE()) {
+ const DWARFDebugAranges &func_aranges = GetFunctionAranges();
+
+ // Re-check the aranges auto pointer contents in case it was created above
+ if (!func_aranges.IsEmpty())
+ return GetDIE(func_aranges.FindAddress(address));
+ }
+ return DWARFDIE();
+}
+
+size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
+ DWARFDIECollection &dies,
+ uint32_t depth) const {
+ size_t old_size = dies.Size();
+ {
+ llvm::sys::ScopedReader lock(m_die_array_mutex);
+ DWARFDebugInfoEntry::const_iterator pos;
+ DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+ for (pos = m_die_array.begin(); pos != end; ++pos) {
+ if (pos->Tag() == tag)
+ dies.Append(DWARFDIE(this, &(*pos)));
+ }
+ }
+
+ // Return the number of DIEs added to the collection
+ return dies.Size() - old_size;
+}
+
+
+lldb::user_id_t DWARFUnit::GetID() const {
+ dw_offset_t local_id =
+ m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
+ if (m_dwarf)
+ return DIERef(local_id, local_id).GetUID(m_dwarf);
+ else
+ return local_id;
+}
+
+dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const {
+ return m_offset + GetLengthByteSize() + GetLength();
+}
+
+size_t DWARFUnit::GetDebugInfoSize() const {
+ return GetLengthByteSize() + GetLength() - GetHeaderByteSize();
+}
+
+const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const {
+ return m_abbrevs;
+}
+
+dw_offset_t DWARFUnit::GetAbbrevOffset() const {
+ return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
+}
+
+void DWARFUnit::SetAddrBase(dw_addr_t addr_base,
+ dw_addr_t ranges_base,
+ dw_offset_t base_obj_offset) {
+ m_addr_base = addr_base;
+ m_ranges_base = ranges_base;
+ m_base_obj_offset = base_obj_offset;
+}
+
+// It may be called only with m_die_array_mutex held R/W.
+void DWARFUnit::ClearDIEsRWLocked() {
+ m_die_array.clear();
+ m_die_array.shrink_to_fit();
+
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked();
+}
+
+void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf,
+ DWARFDebugAranges *debug_aranges) {
+ // This function is usually called if there in no .debug_aranges section in
+ // order to produce a compile unit level set of address ranges that is
+ // accurate.
+
+ size_t num_debug_aranges = debug_aranges->GetNumRanges();
+
+ // First get the compile unit DIE only and check if it has a DW_AT_ranges
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+
+ const dw_offset_t cu_offset = GetOffset();
+ if (die) {
+ DWARFRangeList ranges;
+ const size_t num_ranges =
+ die->GetAttributeAddressRanges(dwarf, this, ranges, false);
+ if (num_ranges > 0) {
+ // This compile unit has DW_AT_ranges, assume this is correct if it is
+ // present since clang no longer makes .debug_aranges by default and it
+ // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with
+ // recent GCC builds.
+ for (size_t i = 0; i < num_ranges; ++i) {
+ const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
+ debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
+ range.GetRangeEnd());
+ }
+
+ return; // We got all of our ranges from the DW_AT_ranges attribute
+ }
+ }
+ // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
+
+ // If the DIEs weren't parsed, then we don't want all dies for all compile
+ // units to stay loaded when they weren't needed. So we can end up parsing
+ // the DWARF and then throwing them all away to keep memory usage down.
+ ScopedExtractDIEs clear_dies(ExtractDIEsScoped());
+
+ die = DIEPtr();
+ if (die)
+ die->BuildAddressRangeTable(dwarf, this, debug_aranges);
+
+ if (debug_aranges->GetNumRanges() == num_debug_aranges) {
+ // We got nothing from the functions, maybe we have a line tables only
+ // situation. Check the line tables and build the arange table from this.
+ SymbolContext sc;
+ sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this);
+ if (sc.comp_unit) {
+ SymbolFileDWARFDebugMap *debug_map_sym_file =
+ m_dwarf->GetDebugMapSymfile();
+ if (debug_map_sym_file == NULL) {
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table) {
+ LineTable::FileAddressRanges file_ranges;
+ const bool append = true;
+ const size_t num_ranges =
+ line_table->GetContiguousFileAddressRanges(file_ranges, append);
+ for (uint32_t idx = 0; idx < num_ranges; ++idx) {
+ const LineTable::FileAddressRanges::Entry &range =
+ file_ranges.GetEntryRef(idx);
+ debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
+ range.GetRangeEnd());
+ }
+ }
+ } else
+ debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges);
+ }
+ }
+
+ if (debug_aranges->GetNumRanges() == num_debug_aranges) {
+ // We got nothing from the functions, maybe we have a line tables only
+ // situation. Check the line tables and build the arange table from this.
+ SymbolContext sc;
+ sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this);
+ if (sc.comp_unit) {
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table) {
+ LineTable::FileAddressRanges file_ranges;
+ const bool append = true;
+ const size_t num_ranges =
+ line_table->GetContiguousFileAddressRanges(file_ranges, append);
+ for (uint32_t idx = 0; idx < num_ranges; ++idx) {
+ const LineTable::FileAddressRanges::Entry &range =
+ file_ranges.GetEntryRef(idx);
+ debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
+ range.GetRangeEnd());
+ }
+ }
+ }
+ }
+}
+
+lldb::ByteOrder DWARFUnit::GetByteOrder() const {
+ return m_dwarf->GetObjectFile()->GetByteOrder();
+}
+
+TypeSystem *DWARFUnit::GetTypeSystem() {
+ if (m_dwarf)
+ return m_dwarf->GetTypeSystemForLanguage(GetLanguageType());
+ else
+ return nullptr;
+}
+
+DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() {
+ return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+}
+
+void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
+ const dw_offset_t die_offset) {
+ return die.GetOffset() < die_offset;
+}
+
+//----------------------------------------------------------------------
+// GetDIE()
+//
+// Get the DIE (Debug Information Entry) with the specified offset by first
+// checking if the DIE is contained within this compile unit and grabbing the
+// DIE from this compile unit. Otherwise we grab the DIE from the DWARF file.
+//----------------------------------------------------------------------
+DWARFDIE
+DWARFUnit::GetDIE(dw_offset_t die_offset) {
+ if (die_offset != DW_INVALID_OFFSET) {
+ if (GetDwoSymbolFile())
+ return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset);
+
+ if (ContainsDIEOffset(die_offset)) {
+ ExtractDIEsIfNeeded();
+ DWARFDebugInfoEntry::const_iterator end = m_die_array.cend();
+ DWARFDebugInfoEntry::const_iterator pos =
+ lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset);
+ if (pos != end) {
+ if (die_offset == (*pos).GetOffset())
+ return DWARFDIE(this, &(*pos));
+ }
+ } else {
+ // Don't specify the compile unit offset as we don't know it because the
+ // DIE belongs to
+ // a different compile unit in the same symbol file.
+ return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset);
+ }
+ }
+ return DWARFDIE(); // Not found
+}
+
+uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
+ if (cu)
+ return cu->GetAddressByteSize();
+ return DWARFUnit::GetDefaultAddressSize();
+}
+
+bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) {
+ if (cu)
+ return cu->IsDWARF64();
+ return false;
+}
+
+uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; }
+
+void *DWARFUnit::GetUserData() const { return m_user_data; }
+
+void DWARFUnit::SetUserData(void *d) {
+ m_user_data = d;
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
+}
+
+bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() {
+ if (GetProducer() == eProducerLLVMGCC)
+ return false;
+ return true;
+}
+
+bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
+ // llvm-gcc makes completely invalid decl file attributes and won't ever be
+ // fixed, so we need to know to ignore these.
+ return GetProducer() == eProducerLLVMGCC;
+}
+
+bool DWARFUnit::Supports_unnamed_objc_bitfields() {
+ if (GetProducer() == eProducerClang) {
+ const uint32_t major_version = GetProducerVersionMajor();
+ if (major_version > 425 ||
+ (major_version == 425 && GetProducerVersionUpdate() >= 13))
+ return true;
+ else
+ return false;
+ }
+ return true; // Assume all other compilers didn't have incorrect ObjC bitfield
+ // info
+}
+
+SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; }
+
+void DWARFUnit::ParseProducerInfo() {
+ m_producer_version_major = UINT32_MAX;
+ m_producer_version_minor = UINT32_MAX;
+ m_producer_version_update = UINT32_MAX;
+
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (die) {
+
+ const char *producer_cstr =
+ die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL);
+ if (producer_cstr) {
+ RegularExpression llvm_gcc_regex(
+ llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple "
+ "Inc\\. build [0-9]+\\) \\(LLVM build "
+ "[\\.0-9]+\\)$"));
+ if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) {
+ m_producer = eProducerLLVMGCC;
+ } else if (strstr(producer_cstr, "clang")) {
+ static RegularExpression g_clang_version_regex(
+ llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"));
+ RegularExpression::Match regex_match(3);
+ if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr),
+ &regex_match)) {
+ std::string str;
+ if (regex_match.GetMatchAtIndex(producer_cstr, 1, str))
+ m_producer_version_major =
+ StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
+ if (regex_match.GetMatchAtIndex(producer_cstr, 2, str))
+ m_producer_version_minor =
+ StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
+ if (regex_match.GetMatchAtIndex(producer_cstr, 3, str))
+ m_producer_version_update =
+ StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
+ }
+ m_producer = eProducerClang;
+ } else if (strstr(producer_cstr, "GNU"))
+ m_producer = eProducerGCC;
+ }
+ }
+ if (m_producer == eProducerInvalid)
+ m_producer = eProcucerOther;
+}
+
+DWARFProducer DWARFUnit::GetProducer() {
+ if (m_producer == eProducerInvalid)
+ ParseProducerInfo();
+ return m_producer;
+}
+
+uint32_t DWARFUnit::GetProducerVersionMajor() {
+ if (m_producer_version_major == 0)
+ ParseProducerInfo();
+ return m_producer_version_major;
+}
+
+uint32_t DWARFUnit::GetProducerVersionMinor() {
+ if (m_producer_version_minor == 0)
+ ParseProducerInfo();
+ return m_producer_version_minor;
+}
+
+uint32_t DWARFUnit::GetProducerVersionUpdate() {
+ if (m_producer_version_update == 0)
+ ParseProducerInfo();
+ return m_producer_version_update;
+}
+LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) {
+ // Note: user languages between lo_user and hi_user must be handled
+ // explicitly here.
+ switch (val) {
+ case DW_LANG_Mips_Assembler:
+ return eLanguageTypeMipsAssembler;
+ case DW_LANG_GOOGLE_RenderScript:
+ return eLanguageTypeExtRenderScript;
+ default:
+ return static_cast<LanguageType>(val);
+ }
+}
+
+LanguageType DWARFUnit::GetLanguageType() {
+ if (m_language_type != eLanguageTypeUnknown)
+ return m_language_type;
+
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (die)
+ m_language_type = LanguageTypeFromDWARF(
+ die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0));
+ return m_language_type;
+}
+
+bool DWARFUnit::GetIsOptimized() {
+ if (m_is_optimized == eLazyBoolCalculate) {
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (die) {
+ m_is_optimized = eLazyBoolNo;
+ if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized,
+ 0) == 1) {
+ m_is_optimized = eLazyBoolYes;
+ }
+ }
+ }
+ return m_is_optimized == eLazyBoolYes;
+}
+
+SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
+ return m_dwo_symbol_file.get();
+}
+
+dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; }
+
+const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
+ if (m_func_aranges_ap.get() == NULL) {
+ m_func_aranges_ap.reset(new DWARFDebugAranges());
+ Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
+
+ if (log) {
+ m_dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "DWARFUnit::GetFunctionAranges() for compile unit at "
+ ".debug_info[0x%8.8x]",
+ GetOffset());
+ }
+ const DWARFDebugInfoEntry *die = DIEPtr();
+ if (die)
+ die->BuildFunctionAddressRangeTable(m_dwarf, this,
+ m_func_aranges_ap.get());
+
+ if (m_dwo_symbol_file) {
+ DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr();
+ if (dwo_die)
+ dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu,
+ m_func_aranges_ap.get());
+ }
+
+ const bool minimize = false;
+ m_func_aranges_ap->Sort(minimize);
+ }
+ return *m_func_aranges_ap.get();
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
new file mode 100644
index 000000000000..3cc24d4202b8
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -0,0 +1,250 @@
+//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFUnit_h_
+#define SymbolFileDWARF_DWARFUnit_h_
+
+#include "DWARFDIE.h"
+#include "DWARFDebugInfoEntry.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/Support/RWMutex.h"
+#include <atomic>
+
+class DWARFUnit;
+class DWARFCompileUnit;
+class NameToDIE;
+class SymbolFileDWARF;
+class SymbolFileDWARFDwo;
+
+typedef std::shared_ptr<DWARFUnit> DWARFUnitSP;
+
+enum DWARFProducer {
+ eProducerInvalid = 0,
+ eProducerClang,
+ eProducerGCC,
+ eProducerLLVMGCC,
+ eProcucerOther
+};
+
+class DWARFUnit {
+ using die_iterator_range =
+ llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;
+
+public:
+ virtual ~DWARFUnit();
+
+ void ExtractUnitDIEIfNeeded();
+ void ExtractDIEsIfNeeded();
+
+ class ScopedExtractDIEs {
+ DWARFUnit *m_cu;
+ public:
+ bool m_clear_dies = false;
+ ScopedExtractDIEs(DWARFUnit *cu);
+ ~ScopedExtractDIEs();
+ DISALLOW_COPY_AND_ASSIGN(ScopedExtractDIEs);
+ ScopedExtractDIEs(ScopedExtractDIEs &&rhs);
+ ScopedExtractDIEs &operator=(ScopedExtractDIEs &&rhs);
+ };
+ ScopedExtractDIEs ExtractDIEsScoped();
+
+ DWARFDIE LookupAddress(const dw_addr_t address);
+ size_t AppendDIEsWithTag(const dw_tag_t tag,
+ DWARFDIECollection &matching_dies,
+ uint32_t depth = UINT32_MAX) const;
+ bool Verify(lldb_private::Stream *s) const;
+ virtual void Dump(lldb_private::Stream *s) const = 0;
+ //------------------------------------------------------------------
+ /// Get the data that contains the DIE information for this unit.
+ ///
+ /// This will return the correct bytes that contain the data for
+ /// this DWARFUnit. It could be .debug_info or .debug_types
+ /// depending on where the data for this unit originates.
+ ///
+ /// @return
+ /// The correct data for the DIE information in this unit.
+ //------------------------------------------------------------------
+ virtual const lldb_private::DWARFDataExtractor &GetData() const = 0;
+ //------------------------------------------------------------------
+ /// Get the size in bytes of the compile unit header.
+ ///
+ /// @return
+ /// Byte size of the compile unit header
+ //------------------------------------------------------------------
+ virtual uint32_t GetHeaderByteSize() const = 0;
+ // Offset of the initial length field.
+ dw_offset_t GetOffset() const { return m_offset; }
+ lldb::user_id_t GetID() const;
+ //------------------------------------------------------------------
+ /// Get the size in bytes of the length field in the header.
+ ///
+ /// In DWARF32 this is just 4 bytes, and DWARF64 it is 12 where 4
+ /// are 0xFFFFFFFF followed by the actual 64 bit length.
+ ///
+ /// @return
+ /// Byte size of the compile unit header length field
+ //------------------------------------------------------------------
+ size_t GetLengthByteSize() const { return IsDWARF64() ? 12 : 4; }
+
+ bool ContainsDIEOffset(dw_offset_t die_offset) const {
+ return die_offset >= GetFirstDIEOffset() &&
+ die_offset < GetNextCompileUnitOffset();
+ }
+ dw_offset_t GetFirstDIEOffset() const {
+ return m_offset + GetHeaderByteSize();
+ }
+ dw_offset_t GetNextCompileUnitOffset() const;
+ // Size of the CU data (without initial length and without header).
+ size_t GetDebugInfoSize() const;
+ // Size of the CU data incl. header but without initial length.
+ uint32_t GetLength() const { return m_length; }
+ uint16_t GetVersion() const { return m_version; }
+ const DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
+ dw_offset_t GetAbbrevOffset() const;
+ uint8_t GetAddressByteSize() const { return m_addr_size; }
+ dw_addr_t GetBaseAddress() const { return m_base_addr; }
+ dw_addr_t GetAddrBase() const { return m_addr_base; }
+ dw_addr_t GetRangesBase() const { return m_ranges_base; }
+ void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base,
+ dw_offset_t base_obj_offset);
+ void BuildAddressRangeTable(SymbolFileDWARF *dwarf,
+ DWARFDebugAranges *debug_aranges);
+
+ lldb::ByteOrder GetByteOrder() const;
+
+ lldb_private::TypeSystem *GetTypeSystem();
+
+ const DWARFDebugAranges &GetFunctionAranges();
+
+ DWARFFormValue::FixedFormSizes GetFixedFormSizes();
+
+ void SetBaseAddress(dw_addr_t base_addr);
+
+ DWARFBaseDIE GetUnitDIEOnly() { return DWARFDIE(this, GetUnitDIEPtrOnly()); }
+
+ DWARFDIE DIE() { return DWARFDIE(this, DIEPtr()); }
+
+ DWARFDIE GetDIE(dw_offset_t die_offset);
+
+ static uint8_t GetAddressByteSize(const DWARFUnit *cu);
+
+ static bool IsDWARF64(const DWARFUnit *cu);
+
+ static uint8_t GetDefaultAddressSize();
+
+ void *GetUserData() const;
+
+ void SetUserData(void *d);
+
+ bool Supports_DW_AT_APPLE_objc_complete_type();
+
+ bool DW_AT_decl_file_attributes_are_invalid();
+
+ bool Supports_unnamed_objc_bitfields();
+
+ SymbolFileDWARF *GetSymbolFileDWARF() const;
+
+ DWARFProducer GetProducer();
+
+ uint32_t GetProducerVersionMajor();
+
+ uint32_t GetProducerVersionMinor();
+
+ uint32_t GetProducerVersionUpdate();
+
+ static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
+
+ lldb::LanguageType GetLanguageType();
+
+ bool IsDWARF64() const { return m_is_dwarf64; }
+
+ bool GetIsOptimized();
+
+ SymbolFileDWARFDwo *GetDwoSymbolFile() const;
+
+ dw_offset_t GetBaseObjOffset() const;
+
+ die_iterator_range dies() {
+ ExtractDIEsIfNeeded();
+ return die_iterator_range(m_die_array.begin(), m_die_array.end());
+ }
+
+protected:
+ DWARFUnit(SymbolFileDWARF *dwarf);
+
+ SymbolFileDWARF *m_dwarf = nullptr;
+ std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
+ const DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr;
+ void *m_user_data = nullptr;
+ // The compile unit debug information entry item
+ DWARFDebugInfoEntry::collection m_die_array;
+ mutable llvm::sys::RWMutex m_die_array_mutex;
+ // It is used for tracking of ScopedExtractDIEs instances.
+ mutable llvm::sys::RWMutex m_die_array_scoped_mutex;
+ // ScopedExtractDIEs instances should not call ClearDIEsRWLocked()
+ // as someone called ExtractDIEsIfNeeded().
+ std::atomic<bool> m_cancel_scopes;
+ // GetUnitDIEPtrOnly() needs to return pointer to the first DIE.
+ // But the first element of m_die_array after ExtractUnitDIEIfNeeded()
+ // would possibly move in memory after later ExtractDIEsIfNeeded().
+ DWARFDebugInfoEntry m_first_die;
+ llvm::sys::RWMutex m_first_die_mutex;
+ // A table similar to the .debug_aranges table, but this one points to the
+ // exact DW_TAG_subprogram DIEs
+ std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap;
+ dw_addr_t m_base_addr = 0;
+ dw_offset_t m_length = 0;
+ uint16_t m_version = 0;
+ uint8_t m_addr_size = 0;
+ DWARFProducer m_producer = eProducerInvalid;
+ uint32_t m_producer_version_major = 0;
+ uint32_t m_producer_version_minor = 0;
+ uint32_t m_producer_version_update = 0;
+ lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown;
+ bool m_is_dwarf64 = false;
+ lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
+ dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
+ dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
+ // If this is a dwo compile unit this is the offset of the base compile unit
+ // in the main object file
+ dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
+
+ // Offset of the initial length field.
+ dw_offset_t m_offset;
+
+private:
+ void ParseProducerInfo();
+ void ExtractDIEsRWLocked();
+ void ClearDIEsRWLocked();
+
+ // Get the DWARF unit DWARF debug informration entry. Parse the single DIE
+ // if needed.
+ const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
+ ExtractUnitDIEIfNeeded();
+ // m_first_die_mutex is not required as m_first_die is never cleared.
+ if (!m_first_die)
+ return NULL;
+ return &m_first_die;
+ }
+
+ // Get all DWARF debug informration entries. Parse all DIEs if needed.
+ const DWARFDebugInfoEntry *DIEPtr() {
+ ExtractDIEsIfNeeded();
+ if (m_die_array.empty())
+ return NULL;
+ return &m_die_array[0];
+ }
+
+ void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
+ void ExtractDIEsEndCheck(lldb::offset_t offset) const;
+
+ DISALLOW_COPY_AND_ASSIGN(DWARFUnit);
+};
+
+#endif // SymbolFileDWARF_DWARFUnit_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
new file mode 100644
index 000000000000..614ff470d161
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -0,0 +1,272 @@
+//===-- DebugNamesDWARFIndex.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
+#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Stream.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) {
+ return llvm::DWARFDataExtractor(
+ llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
+ data.GetByteSize()),
+ data.GetByteOrder() == eByteOrderLittle, data.GetAddressByteSize());
+}
+
+llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
+DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
+ DWARFDataExtractor debug_str,
+ DWARFDebugInfo *debug_info) {
+ if (!debug_info) {
+ return llvm::make_error<llvm::StringError>("debug info null",
+ llvm::inconvertibleErrorCode());
+ }
+ auto index_up =
+ llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str));
+ if (llvm::Error E = index_up->extract())
+ return std::move(E);
+
+ return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
+ module, std::move(index_up), debug_names, debug_str, *debug_info));
+}
+
+llvm::DenseSet<dw_offset_t>
+DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
+ llvm::DenseSet<dw_offset_t> result;
+ for (const DebugNames::NameIndex &ni : debug_names) {
+ for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
+ result.insert(ni.getCUOffset(cu));
+ }
+ return result;
+}
+
+DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
+ llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
+ if (!cu_offset)
+ return DIERef();
+
+ DWARFUnit *cu = m_debug_info.GetCompileUnit(*cu_offset);
+ if (!cu)
+ return DIERef();
+
+ // This initializes the DWO symbol file. It's not possible for
+ // GetDwoSymbolFile to call this automatically because of mutual recursion
+ // between this and DWARFDebugInfoEntry::GetAttributeValue.
+ cu->ExtractUnitDIEIfNeeded();
+ uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset;
+
+ if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
+ return DIERef(*cu_offset, die_bias + *die_offset);
+
+ return DIERef();
+}
+
+void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
+ DIEArray &offsets) {
+ if (DIERef ref = ToDIERef(entry))
+ offsets.push_back(ref);
+}
+
+void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
+ const DebugNames::NameIndex &ni,
+ llvm::StringRef name) {
+ // Ignore SentinelErrors, log everything else.
+ LLDB_LOG_ERROR(
+ LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS),
+ handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
+ "Failed to parse index entries for index at {1:x}, name {2}: {0}",
+ ni.getUnitOffset(), name);
+}
+
+void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename,
+ DIEArray &offsets) {
+ m_fallback.GetGlobalVariables(basename, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(basename.GetStringRef())) {
+ if (entry.tag() != DW_TAG_variable)
+ continue;
+
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) {
+ m_fallback.GetGlobalVariables(regex, offsets);
+
+ for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
+ for (DebugNames::NameTableEntry nte: ni) {
+ if (!regex.Execute(nte.getString()))
+ continue;
+
+ uint32_t entry_offset = nte.getEntryOffset();
+ llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
+ for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
+ if (entry_or->tag() != DW_TAG_variable)
+ continue;
+
+ Append(*entry_or, offsets);
+ }
+ MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
+ }
+ }
+}
+
+void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
+ DIEArray &offsets) {
+ m_fallback.GetGlobalVariables(cu, offsets);
+
+ uint64_t cu_offset = cu.GetOffset();
+ for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
+ for (DebugNames::NameTableEntry nte: ni) {
+ uint32_t entry_offset = nte.getEntryOffset();
+ llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
+ for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
+ if (entry_or->tag() != DW_TAG_variable)
+ continue;
+ if (entry_or->getCUOffset() != cu_offset)
+ continue;
+
+ Append(*entry_or, offsets);
+ }
+ MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
+ }
+ }
+}
+
+void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) {
+ m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets);
+
+ // Keep a list of incomplete types as fallback for when we don't find the
+ // complete type.
+ DIEArray incomplete_types;
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(class_name.GetStringRef())) {
+ if (entry.tag() != DW_TAG_structure_type &&
+ entry.tag() != DW_TAG_class_type)
+ continue;
+
+ DIERef ref = ToDIERef(entry);
+ if (!ref)
+ continue;
+
+ DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset);
+ if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
+ incomplete_types.push_back(ref);
+ continue;
+ }
+
+ // FIXME: We should return DWARFDIEs so we don't have to resolve it twice.
+ DWARFDIE die = m_debug_info.GetDIE(ref);
+ if (!die)
+ continue;
+
+ if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
+ // If we find the complete version we're done.
+ offsets.push_back(ref);
+ return;
+ } else {
+ incomplete_types.push_back(ref);
+ }
+ }
+
+ offsets.insert(offsets.end(), incomplete_types.begin(),
+ incomplete_types.end());
+}
+
+void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
+ m_fallback.GetTypes(name, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(name.GetStringRef())) {
+ if (isType(entry.tag()))
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetTypes(const DWARFDeclContext &context,
+ DIEArray &offsets) {
+ m_fallback.GetTypes(context, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(context[0].name)) {
+ if (entry.tag() == context[0].tag)
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
+ m_fallback.GetNamespaces(name, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(name.GetStringRef())) {
+ if (entry.tag() == DW_TAG_namespace)
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetFunctions(
+ ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+
+ m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, dies);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(name.GetStringRef())) {
+ Tag tag = entry.tag();
+ if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
+ continue;
+
+ if (DIERef ref = ToDIERef(entry))
+ ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx,
+ name_type_mask, dies);
+ }
+}
+
+void DebugNamesDWARFIndex::GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) {
+ m_fallback.GetFunctions(regex, offsets);
+
+ for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
+ for (DebugNames::NameTableEntry nte: ni) {
+ if (!regex.Execute(nte.getString()))
+ continue;
+
+ uint32_t entry_offset = nte.getEntryOffset();
+ llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
+ for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
+ Tag tag = entry_or->tag();
+ if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
+ continue;
+
+ Append(*entry_or, offsets);
+ }
+ MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
+ }
+ }
+}
+
+void DebugNamesDWARFIndex::Dump(Stream &s) {
+ m_fallback.Dump(s);
+
+ std::string data;
+ llvm::raw_string_ostream os(data);
+ m_debug_names_up->dump(os);
+ s.PutCString(os.str());
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
new file mode 100644
index 000000000000..30423c7ca2a2
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -0,0 +1,83 @@
+//===-- DebugNamesDWARFIndex.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_DEBUGNAMESDWARFINDEX_H
+#define LLDB_DEBUGNAMESDWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+#include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
+#include "lldb/Utility/ConstString.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+
+namespace lldb_private {
+class DebugNamesDWARFIndex : public DWARFIndex {
+public:
+ static llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
+ Create(Module &module, DWARFDataExtractor debug_names,
+ DWARFDataExtractor debug_str, DWARFDebugInfo *debug_info);
+
+ void Preload() override { m_fallback.Preload(); }
+
+ void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
+ void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) override;
+ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override;
+ void GetObjCMethods(ConstString class_name, DIEArray &offsets) override {}
+ void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation,
+ DIEArray &offsets) override;
+ void GetTypes(ConstString name, DIEArray &offsets) override;
+ void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
+ void GetNamespaces(ConstString name, DIEArray &offsets) override;
+ void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) override;
+ void GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) override;
+
+ void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) override {}
+ void Dump(Stream &s) override;
+
+private:
+ DebugNamesDWARFIndex(Module &module,
+ std::unique_ptr<llvm::DWARFDebugNames> debug_names_up,
+ DWARFDataExtractor debug_names_data,
+ DWARFDataExtractor debug_str_data,
+ DWARFDebugInfo &debug_info)
+ : DWARFIndex(module), m_debug_info(debug_info),
+ m_debug_names_data(debug_names_data), m_debug_str_data(debug_str_data),
+ m_debug_names_up(std::move(debug_names_up)),
+ m_fallback(module, &debug_info, GetUnits(*m_debug_names_up)) {}
+
+ DWARFDebugInfo &m_debug_info;
+
+ // LLVM DWARFDebugNames will hold a non-owning reference to this data, so keep
+ // track of the ownership here.
+ DWARFDataExtractor m_debug_names_data;
+ DWARFDataExtractor m_debug_str_data;
+
+ using DebugNames = llvm::DWARFDebugNames;
+ std::unique_ptr<DebugNames> m_debug_names_up;
+ ManualDWARFIndex m_fallback;
+
+ DIERef ToDIERef(const DebugNames::Entry &entry);
+ void Append(const DebugNames::Entry &entry, DIEArray &offsets);
+
+ static void MaybeLogLookupError(llvm::Error error,
+ const DebugNames::NameIndex &ni,
+ llvm::StringRef name);
+
+ static llvm::DenseSet<dw_offset_t> GetUnits(const DebugNames &debug_names);
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_DEBUGNAMESDWARFINDEX_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
index cb1e5c185613..36211a08557e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -75,15 +75,14 @@ void DWARFMappedHash::ExtractClassOrStructDIEArray(
die_tag == DW_TAG_structure_type) {
if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) {
if (return_implementation_only_if_available) {
- // We found the one true definition for this class, so
- // only return that
+ // We found the one true definition for this class, so only return
+ // that
die_offsets.clear();
die_offsets.emplace_back(die_info_array[i].cu_offset,
die_info_array[i].offset);
return;
} else {
- // Put the one true definition as the first entry so it
- // matches first
+ // Put the one true definition as the first entry so it matches first
die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset,
die_info_array[i].offset);
}
@@ -137,9 +136,8 @@ DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t c, dw_offset_t o, dw_tag_t t,
DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset)
: die_base_offset(_die_base_offset), atoms(), atom_mask(0),
min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) {
- // Define an array of DIE offsets by first defining an array,
- // and then define the atom type for the array, in this case
- // we have an array of DIE offsets
+ // Define an array of DIE offsets by first defining an array, and then define
+ // the atom type for the array, in this case we have an array of DIE offsets
AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4);
}
@@ -239,8 +237,7 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data,
size_t DWARFMappedHash::Prologue::GetByteSize() const {
// Add an extra count to the atoms size for the zero termination Atom that
- // gets
- // written to disk
+ // gets written to disk
return sizeof(die_base_offset) + sizeof(uint32_t) +
atoms.size() * sizeof(Atom);
}
@@ -379,17 +376,18 @@ bool DWARFMappedHash::MemoryTable::ReadHashData(uint32_t hash_data_offset,
DWARFMappedHash::MemoryTable::Result
DWARFMappedHash::MemoryTable::GetHashDataForName(
- const char *name, lldb::offset_t *hash_data_offset_ptr, Pair &pair) const {
+ llvm::StringRef name, lldb::offset_t *hash_data_offset_ptr,
+ Pair &pair) const {
pair.key = m_data.GetU32(hash_data_offset_ptr);
pair.value.clear();
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
+ // If the key is zero, this terminates our chain of HashData objects for this
+ // hash value.
if (pair.key == 0)
return eResultEndOfHashData;
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
+ // There definitely should be a string for this string offset, if there
+ // isn't, there is something wrong, return and error
const char *strp_cstr = m_string_table.PeekCStr(pair.key);
if (strp_cstr == NULL) {
*hash_data_offset_ptr = UINT32_MAX;
@@ -402,22 +400,21 @@ DWARFMappedHash::MemoryTable::GetHashDataForName(
if (count > 0 &&
m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr,
min_total_hash_data_size)) {
- // We have at least one HashData entry, and we have enough
- // data to parse at least "count" HashData entries.
+ // We have at least one HashData entry, and we have enough data to parse at
+ // least "count" HashData entries.
// First make sure the entire C string matches...
- const bool match = strcmp(name, strp_cstr) == 0;
+ const bool match = name == strp_cstr;
if (!match && m_header.header_data.HashDataHasFixedByteSize()) {
- // If the string doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
+ // If the string doesn't match and we have fixed size data, we can just
+ // add the total byte size of all HashData objects to the hash data
+ // offset and be done...
*hash_data_offset_ptr += min_total_hash_data_size;
} else {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
+ // If the string does match, or we don't have fixed size data then we
+ // need to read the hash data as a stream. If the string matches we also
+ // append all HashData objects to the value array.
for (uint32_t i = 0; i < count; ++i) {
DIEInfo die_info;
if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) {
@@ -431,16 +428,15 @@ DWARFMappedHash::MemoryTable::GetHashDataForName(
}
}
}
- // Return the correct response depending on if the string matched
- // or not...
+ // Return the correct response depending on if the string matched or not...
if (match)
return eResultKeyMatch; // The key (cstring) matches and we have lookup
// results!
else
return eResultKeyMismatch; // The key doesn't match, this function will
// get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
+ // again for the next key/value or the key terminator which in our case is
+ // a zero .debug_str offset.
} else {
*hash_data_offset_ptr = UINT32_MAX;
return eResultError;
@@ -452,13 +448,13 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
const lldb_private::RegularExpression &regex,
lldb::offset_t *hash_data_offset_ptr, Pair &pair) const {
pair.key = m_data.GetU32(hash_data_offset_ptr);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
+ // If the key is zero, this terminates our chain of HashData objects for this
+ // hash value.
if (pair.key == 0)
return eResultEndOfHashData;
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
+ // There definitely should be a string for this string offset, if there
+ // isn't, there is something wrong, return and error
const char *strp_cstr = m_string_table.PeekCStr(pair.key);
if (strp_cstr == NULL)
return eResultError;
@@ -472,15 +468,14 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
const bool match = regex.Execute(llvm::StringRef(strp_cstr));
if (!match && m_header.header_data.HashDataHasFixedByteSize()) {
- // If the regex doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
+ // If the regex doesn't match and we have fixed size data, we can just
+ // add the total byte size of all HashData objects to the hash data
+ // offset and be done...
*hash_data_offset_ptr += min_total_hash_data_size;
} else {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
+ // If the string does match, or we don't have fixed size data then we
+ // need to read the hash data as a stream. If the string matches we also
+ // append all HashData objects to the value array.
for (uint32_t i = 0; i < count; ++i) {
DIEInfo die_info;
if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) {
@@ -494,16 +489,15 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
}
}
}
- // Return the correct response depending on if the string matched
- // or not...
+ // Return the correct response depending on if the string matched or not...
if (match)
return eResultKeyMatch; // The key (cstring) matches and we have lookup
// results!
else
return eResultKeyMismatch; // The key doesn't match, this function will
// get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
+ // again for the next key/value or the key terminator which in our case is
+ // a zero .debug_str offset.
} else {
*hash_data_offset_ptr = UINT32_MAX;
return eResultError;
@@ -528,8 +522,7 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex(
switch (hash_result) {
case eResultKeyMatch:
case eResultKeyMismatch:
- // Whether we matches or not, it doesn't matter, we
- // keep looking.
+ // Whether we matches or not, it doesn't matter, we keep looking.
break;
case eResultEndOfHashData:
@@ -552,8 +545,8 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsInRange(
lldb::offset_t hash_data_offset = GetHashDataOffset(offset_idx);
while (!done && hash_data_offset != UINT32_MAX) {
KeyType key = m_data.GetU32(&hash_data_offset);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
+ // If the key is zero, this terminates our chain of HashData objects for
+ // this hash value.
if (key == 0)
break;
@@ -573,9 +566,9 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsInRange(
return die_info_array.size();
}
-size_t DWARFMappedHash::MemoryTable::FindByName(const char *name,
+size_t DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name,
DIEArray &die_offsets) {
- if (!name || !name[0])
+ if (name.empty())
return 0;
DIEInfoArray die_info_array;
@@ -584,7 +577,7 @@ size_t DWARFMappedHash::MemoryTable::FindByName(const char *name,
return die_info_array.size();
}
-size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(const char *name,
+size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(llvm::StringRef name,
const dw_tag_t tag,
DIEArray &die_offsets) {
DIEInfoArray die_info_array;
@@ -594,8 +587,8 @@ size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(const char *name,
}
size_t DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash(
- const char *name, const dw_tag_t tag, const uint32_t qualified_name_hash,
- DIEArray &die_offsets) {
+ llvm::StringRef name, const dw_tag_t tag,
+ const uint32_t qualified_name_hash, DIEArray &die_offsets) {
DIEInfoArray die_info_array;
if (FindByName(name, die_info_array))
DWARFMappedHash::ExtractDIEArray(die_info_array, tag, qualified_name_hash,
@@ -604,22 +597,21 @@ size_t DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash(
}
size_t DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName(
- const char *name, DIEArray &die_offsets, bool must_be_implementation) {
+ llvm::StringRef name, DIEArray &die_offsets, bool must_be_implementation) {
DIEInfoArray die_info_array;
if (FindByName(name, die_info_array)) {
if (must_be_implementation &&
GetHeader().header_data.ContainsAtom(eAtomTypeTypeFlags)) {
- // If we have two atoms, then we have the DIE offset and
- // the type flags so we can find the objective C class
- // efficiently.
+ // If we have two atoms, then we have the DIE offset and the type flags
+ // so we can find the objective C class efficiently.
DWARFMappedHash::ExtractTypesFromDIEArray(die_info_array, UINT32_MAX,
eTypeFlagClassIsImplementation,
die_offsets);
} else {
- // We don't only want the one true definition, so try and see
- // what we can find, and only return class or struct DIEs.
- // If we do have the full implementation, then return it alone,
- // else return all possible matches.
+ // We don't only want the one true definition, so try and see what we can
+ // find, and only return class or struct DIEs. If we do have the full
+ // implementation, then return it alone, else return all possible
+ // matches.
const bool return_implementation_only_if_available = true;
DWARFMappedHash::ExtractClassOrStructDIEArray(
die_info_array, return_implementation_only_if_available, die_offsets);
@@ -628,9 +620,9 @@ size_t DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName(
return die_offsets.size();
}
-size_t DWARFMappedHash::MemoryTable::FindByName(const char *name,
+size_t DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name,
DIEInfoArray &die_info_array) {
- if (!name || !name[0])
+ if (name.empty())
return 0;
Pair kv_pair;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index 959517529e52..17600df2edd4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -21,10 +21,6 @@
#include "DWARFFormValue.h"
#include "NameToDIE.h"
-class SymbolFileDWARF;
-class DWARFCompileUnit;
-class DWARFDebugInfoEntry;
-
class DWARFMappedHash {
public:
enum AtomType : uint16_t {
@@ -136,17 +132,17 @@ public:
const uint32_t die_offset_end,
DIEInfoArray &die_info_array) const;
- size_t FindByName(const char *name, DIEArray &die_offsets);
+ size_t FindByName(llvm::StringRef name, DIEArray &die_offsets);
- size_t FindByNameAndTag(const char *name, const dw_tag_t tag,
+ size_t FindByNameAndTag(llvm::StringRef name, const dw_tag_t tag,
DIEArray &die_offsets);
- size_t
- FindByNameAndTagAndQualifiedNameHash(const char *name, const dw_tag_t tag,
- const uint32_t qualified_name_hash,
- DIEArray &die_offsets);
+ size_t FindByNameAndTagAndQualifiedNameHash(
+ llvm::StringRef name, const dw_tag_t tag,
+ const uint32_t qualified_name_hash, DIEArray &die_offsets);
- size_t FindCompleteObjCClassByName(const char *name, DIEArray &die_offsets,
+ size_t FindCompleteObjCClassByName(llvm::StringRef name,
+ DIEArray &die_offsets,
bool must_be_implementation);
protected:
@@ -154,14 +150,14 @@ public:
const lldb_private::RegularExpression &regex,
lldb::offset_t *hash_data_offset_ptr, Pair &pair) const;
- size_t FindByName(const char *name, DIEInfoArray &die_info_array);
+ size_t FindByName(llvm::StringRef name, DIEInfoArray &die_info_array);
- Result GetHashDataForName(const char *name,
+ Result GetHashDataForName(llvm::StringRef name,
lldb::offset_t *hash_data_offset_ptr,
Pair &pair) const override;
- const lldb_private::DWARFDataExtractor &m_data;
- const lldb_private::DWARFDataExtractor &m_string_table;
+ lldb_private::DWARFDataExtractor m_data;
+ lldb_private::DWARFDataExtractor m_string_table;
std::string m_name;
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
new file mode 100644
index 000000000000..6438f02fe8ec
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -0,0 +1,488 @@
+//===-- ManualDWARFIndex.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Host/TaskPool.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/Timer.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+void ManualDWARFIndex::Index() {
+ if (!m_debug_info)
+ return;
+
+ DWARFDebugInfo &debug_info = *m_debug_info;
+ m_debug_info = nullptr;
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%p", static_cast<void *>(&debug_info));
+
+ std::vector<DWARFUnit *> units_to_index;
+ units_to_index.reserve(debug_info.GetNumCompileUnits());
+ for (size_t U = 0; U < debug_info.GetNumCompileUnits(); ++U) {
+ DWARFUnit *unit = debug_info.GetCompileUnitAtIndex(U);
+ if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0)
+ units_to_index.push_back(unit);
+ }
+ if (units_to_index.empty())
+ return;
+
+ std::vector<IndexSet> sets(units_to_index.size());
+
+ //----------------------------------------------------------------------
+ // Keep memory down by clearing DIEs for any compile units if indexing
+ // caused us to load the compile unit's DIEs.
+ //----------------------------------------------------------------------
+ std::vector<llvm::Optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies(
+ units_to_index.size());
+ auto parser_fn = [&](size_t cu_idx) {
+ IndexUnit(*units_to_index[cu_idx], sets[cu_idx]);
+ };
+
+ auto extract_fn = [&units_to_index, &clear_cu_dies](size_t cu_idx) {
+ clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
+ };
+
+ // Create a task runner that extracts dies for each DWARF compile unit in a
+ // separate thread
+ //----------------------------------------------------------------------
+ // First figure out which compile units didn't have their DIEs already
+ // parsed and remember this. If no DIEs were parsed prior to this index
+ // function call, we are going to want to clear the CU dies after we are
+ // done indexing to make sure we don't pull in all DWARF dies, but we need
+ // to wait until all compile units have been indexed in case a DIE in one
+ // compile unit refers to another and the indexes accesses those DIEs.
+ //----------------------------------------------------------------------
+ TaskMapOverInt(0, units_to_index.size(), extract_fn);
+
+ // Now create a task runner that can index each DWARF compile unit in a
+ // separate thread so we can index quickly.
+
+ TaskMapOverInt(0, units_to_index.size(), parser_fn);
+
+ auto finalize_fn = [this, &sets](NameToDIE(IndexSet::*index)) {
+ NameToDIE &result = m_set.*index;
+ for (auto &set : sets)
+ result.Append(set.*index);
+ result.Finalize();
+ };
+
+ TaskPool::RunTasks([&]() { finalize_fn(&IndexSet::function_basenames); },
+ [&]() { finalize_fn(&IndexSet::function_fullnames); },
+ [&]() { finalize_fn(&IndexSet::function_methods); },
+ [&]() { finalize_fn(&IndexSet::function_selectors); },
+ [&]() { finalize_fn(&IndexSet::objc_class_selectors); },
+ [&]() { finalize_fn(&IndexSet::globals); },
+ [&]() { finalize_fn(&IndexSet::types); },
+ [&]() { finalize_fn(&IndexSet::namespaces); });
+}
+
+void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, IndexSet &set) {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS);
+
+ if (log) {
+ m_module.LogMessage(
+ log, "ManualDWARFIndex::IndexUnit for compile unit at .debug_info[0x%8.8x]",
+ unit.GetOffset());
+ }
+
+ const LanguageType cu_language = unit.GetLanguageType();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes = unit.GetFixedFormSizes();
+
+ IndexUnitImpl(unit, cu_language, fixed_form_sizes, unit.GetOffset(), set);
+
+ SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile();
+ if (dwo_symbol_file && dwo_symbol_file->GetCompileUnit()) {
+ IndexUnitImpl(*dwo_symbol_file->GetCompileUnit(), cu_language,
+ fixed_form_sizes, unit.GetOffset(), set);
+ }
+}
+
+void ManualDWARFIndex::IndexUnitImpl(
+ DWARFUnit &unit, const LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
+ const dw_offset_t cu_offset, IndexSet &set) {
+ for (const DWARFDebugInfoEntry &die : unit.dies()) {
+ const dw_tag_t tag = die.Tag();
+
+ switch (tag) {
+ case DW_TAG_array_type:
+ case DW_TAG_base_type:
+ case DW_TAG_class_type:
+ case DW_TAG_constant:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_namespace:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ case DW_TAG_unspecified_type:
+ case DW_TAG_variable:
+ break;
+
+ default:
+ continue;
+ }
+
+ DWARFAttributes attributes;
+ const char *name = NULL;
+ const char *mangled_cstr = NULL;
+ bool is_declaration = false;
+ // bool is_artificial = false;
+ bool has_address = false;
+ bool has_location_or_const_value = false;
+ bool is_global_or_static_variable = false;
+
+ DWARFFormValue specification_die_form;
+ const size_t num_attributes =
+ die.GetAttributes(&unit, fixed_form_sizes, attributes);
+ if (num_attributes > 0) {
+ for (uint32_t i = 0; i < num_attributes; ++i) {
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ switch (attr) {
+ case DW_AT_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
+ break;
+
+ case DW_AT_declaration:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ is_declaration = form_value.Unsigned() != 0;
+ break;
+
+ // case DW_AT_artificial:
+ // if (attributes.ExtractFormValueAtIndex(i,
+ // form_value))
+ // is_artificial = form_value.Unsigned() != 0;
+ // break;
+
+ case DW_AT_MIPS_linkage_name:
+ case DW_AT_linkage_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ mangled_cstr = form_value.AsCString();
+ break;
+
+ case DW_AT_low_pc:
+ case DW_AT_high_pc:
+ case DW_AT_ranges:
+ has_address = true;
+ break;
+
+ case DW_AT_entry_pc:
+ has_address = true;
+ break;
+
+ case DW_AT_location:
+ case DW_AT_const_value:
+ has_location_or_const_value = true;
+ if (tag == DW_TAG_variable) {
+ const DWARFDebugInfoEntry *parent_die = die.GetParent();
+ while (parent_die != NULL) {
+ switch (parent_die->Tag()) {
+ case DW_TAG_subprogram:
+ case DW_TAG_lexical_block:
+ case DW_TAG_inlined_subroutine:
+ // Even if this is a function level static, we don't add it. We
+ // could theoretically add these if we wanted to by
+ // introspecting into the DW_AT_location and seeing if the
+ // location describes a hard coded address, but we don't want
+ // the performance penalty of that right now.
+ is_global_or_static_variable = false;
+ // if (attributes.ExtractFormValueAtIndex(dwarf, i,
+ // form_value)) {
+ // // If we have valid block data, then we have location
+ // // expression bytesthat are fixed (not a location list).
+ // const uint8_t *block_data = form_value.BlockData();
+ // if (block_data) {
+ // uint32_t block_length = form_value.Unsigned();
+ // if (block_length == 1 +
+ // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) {
+ // if (block_data[0] == DW_OP_addr)
+ // add_die = true;
+ // }
+ // }
+ // }
+ parent_die = NULL; // Terminate the while loop.
+ break;
+
+ case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
+ is_global_or_static_variable = true;
+ parent_die = NULL; // Terminate the while loop.
+ break;
+
+ default:
+ parent_die =
+ parent_die->GetParent(); // Keep going in the while loop.
+ break;
+ }
+ }
+ }
+ break;
+
+ case DW_AT_specification:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ specification_die_form = form_value;
+ break;
+ }
+ }
+ }
+
+ switch (tag) {
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ if (has_address) {
+ if (name) {
+ ObjCLanguage::MethodName objc_method(name, true);
+ if (objc_method.IsValid(true)) {
+ ConstString objc_class_name_with_category(
+ objc_method.GetClassNameWithCategory());
+ ConstString objc_selector_name(objc_method.GetSelector());
+ ConstString objc_fullname_no_category_name(
+ objc_method.GetFullNameWithoutCategory(true));
+ ConstString objc_class_name_no_category(objc_method.GetClassName());
+ set.function_fullnames.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_class_name_with_category)
+ set.objc_class_selectors.Insert(
+ objc_class_name_with_category,
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_class_name_no_category &&
+ objc_class_name_no_category != objc_class_name_with_category)
+ set.objc_class_selectors.Insert(
+ objc_class_name_no_category,
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_selector_name)
+ set.function_selectors.Insert(objc_selector_name,
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_fullname_no_category_name)
+ set.function_fullnames.Insert(objc_fullname_no_category_name,
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ // If we have a mangled name, then the DW_AT_name attribute is
+ // usually the method name without the class or any parameters
+ bool is_method = DWARFDIE(&unit, &die).IsMethod();
+
+ if (is_method)
+ set.function_methods.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ else
+ set.function_basenames.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+
+ if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
+ set.function_fullnames.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ if (mangled_cstr) {
+ // Make sure our mangled name isn't the same string table entry as
+ // our name. If it starts with '_', then it is ok, else compare the
+ // string to make sure it isn't the same and we don't end up with
+ // duplicate entries
+ if (name && name != mangled_cstr &&
+ ((mangled_cstr[0] == '_') ||
+ (::strcmp(name, mangled_cstr) != 0))) {
+ set.function_fullnames.Insert(ConstString(mangled_cstr),
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_array_type:
+ case DW_TAG_base_type:
+ case DW_TAG_class_type:
+ case DW_TAG_constant:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ case DW_TAG_unspecified_type:
+ if (name && !is_declaration)
+ set.types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
+ if (mangled_cstr && !is_declaration)
+ set.types.Insert(ConstString(mangled_cstr),
+ DIERef(cu_offset, die.GetOffset()));
+ break;
+
+ case DW_TAG_namespace:
+ if (name)
+ set.namespaces.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ break;
+
+ case DW_TAG_variable:
+ if (name && has_location_or_const_value && is_global_or_static_variable) {
+ set.globals.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ // Be sure to include variables by their mangled and demangled names if
+ // they have any since a variable can have a basename "i", a mangled
+ // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
+ // "(anonymous namespace)::i"...
+
+ // Make sure our mangled name isn't the same string table entry as our
+ // name. If it starts with '_', then it is ok, else compare the string
+ // to make sure it isn't the same and we don't end up with duplicate
+ // entries
+ if (mangled_cstr && name != mangled_cstr &&
+ ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
+ set.globals.Insert(ConstString(mangled_cstr),
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ }
+ break;
+
+ default:
+ continue;
+ }
+ }
+}
+
+void ManualDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) {
+ Index();
+ m_set.globals.Find(basename, offsets);
+}
+
+void ManualDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) {
+ Index();
+ m_set.globals.Find(regex, offsets);
+}
+
+void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
+ DIEArray &offsets) {
+ Index();
+ m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets);
+}
+
+void ManualDWARFIndex::GetObjCMethods(ConstString class_name,
+ DIEArray &offsets) {
+ Index();
+ m_set.objc_class_selectors.Find(class_name, offsets);
+}
+
+void ManualDWARFIndex::GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) {
+ Index();
+ m_set.types.Find(class_name, offsets);
+}
+
+void ManualDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
+ Index();
+ m_set.types.Find(name, offsets);
+}
+
+void ManualDWARFIndex::GetTypes(const DWARFDeclContext &context,
+ DIEArray &offsets) {
+ Index();
+ m_set.types.Find(ConstString(context[0].name), offsets);
+}
+
+void ManualDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
+ Index();
+ m_set.namespaces.Find(name, offsets);
+}
+
+void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+ Index();
+
+ if (name_type_mask & eFunctionNameTypeFull) {
+ DIEArray offsets;
+ m_set.function_basenames.Find(name, offsets);
+ m_set.function_methods.Find(name, offsets);
+ m_set.function_fullnames.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ DWARFDIE die = info.GetDIE(die_ref);
+ if (!die)
+ continue;
+ if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+ dies.push_back(die);
+ }
+ }
+ if (name_type_mask & eFunctionNameTypeBase) {
+ DIEArray offsets;
+ m_set.function_basenames.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ DWARFDIE die = info.GetDIE(die_ref);
+ if (!die)
+ continue;
+ if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+ dies.push_back(die);
+ }
+ offsets.clear();
+ }
+
+ if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) {
+ DIEArray offsets;
+ m_set.function_methods.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ if (DWARFDIE die = info.GetDIE(die_ref))
+ dies.push_back(die);
+ }
+ }
+
+ if (name_type_mask & eFunctionNameTypeSelector &&
+ !parent_decl_ctx.IsValid()) {
+ DIEArray offsets;
+ m_set.function_selectors.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ if (DWARFDIE die = info.GetDIE(die_ref))
+ dies.push_back(die);
+ }
+ }
+}
+
+void ManualDWARFIndex::GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) {
+ Index();
+
+ m_set.function_basenames.Find(regex, offsets);
+ m_set.function_fullnames.Find(regex, offsets);
+}
+
+void ManualDWARFIndex::Dump(Stream &s) {
+ s.Format("Manual DWARF index for ({0}) '{1:F}':",
+ m_module.GetArchitecture().GetArchitectureName(),
+ m_module.GetObjectFile()->GetFileSpec());
+ s.Printf("\nFunction basenames:\n");
+ m_set.function_basenames.Dump(&s);
+ s.Printf("\nFunction fullnames:\n");
+ m_set.function_fullnames.Dump(&s);
+ s.Printf("\nFunction methods:\n");
+ m_set.function_methods.Dump(&s);
+ s.Printf("\nFunction selectors:\n");
+ m_set.function_selectors.Dump(&s);
+ s.Printf("\nObjective-C class selectors:\n");
+ m_set.objc_class_selectors.Dump(&s);
+ s.Printf("\nGlobals and statics:\n");
+ m_set.globals.Dump(&s);
+ s.Printf("\nTypes:\n");
+ m_set.types.Dump(&s);
+ s.Printf("\nNamespaces:\n");
+ m_set.namespaces.Dump(&s);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
new file mode 100644
index 000000000000..79ab1d95b380
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -0,0 +1,75 @@
+//===-- ManulaDWARFIndex.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_MANUALDWARFINDEX_H
+#define LLDB_MANUALDWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/NameToDIE.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace lldb_private {
+class ManualDWARFIndex : public DWARFIndex {
+public:
+ ManualDWARFIndex(Module &module, DWARFDebugInfo *debug_info,
+ llvm::DenseSet<dw_offset_t> units_to_avoid = {})
+ : DWARFIndex(module), m_debug_info(debug_info),
+ m_units_to_avoid(std::move(units_to_avoid)) {}
+
+ void Preload() override { Index(); }
+
+ void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
+ void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) override;
+ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override;
+ void GetObjCMethods(ConstString class_name, DIEArray &offsets) override;
+ void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation,
+ DIEArray &offsets) override;
+ void GetTypes(ConstString name, DIEArray &offsets) override;
+ void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
+ void GetNamespaces(ConstString name, DIEArray &offsets) override;
+ void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) override;
+ void GetFunctions(const RegularExpression &regex, DIEArray &offsets) override;
+
+ void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) override {}
+ void Dump(Stream &s) override;
+
+private:
+ struct IndexSet {
+ NameToDIE function_basenames;
+ NameToDIE function_fullnames;
+ NameToDIE function_methods;
+ NameToDIE function_selectors;
+ NameToDIE objc_class_selectors;
+ NameToDIE globals;
+ NameToDIE types;
+ NameToDIE namespaces;
+ };
+ void Index();
+ void IndexUnit(DWARFUnit &unit, IndexSet &set);
+
+ static void
+ IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
+ const dw_offset_t cu_offset, IndexSet &set);
+
+ /// Non-null value means we haven't built the index yet.
+ DWARFDebugInfo *m_debug_info;
+ /// Which dwarf units should we skip while building the index.
+ llvm::DenseSet<dw_offset_t> m_units_to_avoid;
+
+ IndexSet m_set;
+};
+} // namespace lldb_private
+
+#endif // LLDB_MANUALDWARFINDEX_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index c97680eda0fe..c8d6bba16976 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -14,7 +14,6 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
#include "SymbolFileDWARF.h"
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index f149ec354f08..ac320ac52b08 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -27,6 +27,7 @@
#include "lldb/Utility/Timer.h"
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
@@ -49,27 +50,24 @@
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
-
#include "lldb/Target/Language.h"
-#include "lldb/Host/TaskPool.h"
-
+#include "AppleDWARFIndex.h"
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugLine.h"
#include "DWARFDebugMacro.h"
-#include "DWARFDebugPubnames.h"
#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
#include "DWARFFormValue.h"
+#include "DWARFUnit.h"
+#include "DebugNamesDWARFIndex.h"
#include "LogChannelDWARF.h"
+#include "ManualDWARFIndex.h"
#include "SymbolFileDWARFDebugMap.h"
#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDwp.h"
@@ -115,11 +113,20 @@ namespace {
PropertyDefinition g_properties[] = {
{"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr,
- nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic "
- "links will be resolved at DWARF parse time."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ nullptr,
+ "If the DW_AT_comp_dir matches any of these paths the symbolic "
+ "links will be resolved at DWARF parse time."},
+ {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr,
+ nullptr,
+ "Ignore indexes present in the object files and always index DWARF "
+ "manually."},
+ {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr},
+};
-enum { ePropertySymLinkPaths };
+enum {
+ ePropertySymLinkPaths,
+ ePropertyIgnoreIndexes,
+};
class PluginProperties : public Properties {
public:
@@ -139,6 +146,11 @@ public:
assert(option_value);
return option_value->GetCurrentValue();
}
+
+ bool IgnoreFileIndexes() const {
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, ePropertyIgnoreIndexes, false);
+ }
};
typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP;
@@ -165,8 +177,8 @@ static const char *removeHostnameFromPathname(const char *path_from_dwarf) {
return path_from_dwarf;
}
- // check whether we have a windows path, and so the first character
- // is a drive-letter not a hostname.
+ // check whether we have a windows path, and so the first character is a
+ // drive-letter not a hostname.
if (colon_pos == path_from_dwarf + 1 && isalpha(*path_from_dwarf) &&
strlen(path_from_dwarf) > 2 && '\\' == path_from_dwarf[2]) {
return path_from_dwarf;
@@ -175,41 +187,42 @@ static const char *removeHostnameFromPathname(const char *path_from_dwarf) {
return colon_pos + 1;
}
-static const char *resolveCompDir(const char *path_from_dwarf) {
+static FileSpec resolveCompDir(const char *path_from_dwarf) {
if (!path_from_dwarf)
- return nullptr;
+ return FileSpec();
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
const char *local_path = removeHostnameFromPathname(path_from_dwarf);
if (!local_path)
- return nullptr;
+ return FileSpec();
bool is_symlink = false;
- FileSpec local_path_spec(local_path, false);
+ // Always normalize our compile unit directory to get rid of redundant
+ // slashes and other path anomalies before we use it for path prepending
+ FileSpec local_spec(local_path, false);
const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i),
- local_path_spec, true);
+ local_spec, true);
if (!is_symlink)
- return local_path;
+ return local_spec;
namespace fs = llvm::sys::fs;
- if (fs::get_file_type(local_path_spec.GetPath(), false) !=
+ if (fs::get_file_type(local_spec.GetPath(), false) !=
fs::file_type::symlink_file)
- return local_path;
+ return local_spec;
- FileSpec resolved_local_path_spec;
- const auto error =
- FileSystem::Readlink(local_path_spec, resolved_local_path_spec);
+ FileSpec resolved_symlink;
+ const auto error = FileSystem::Readlink(local_spec, resolved_symlink);
if (error.Success())
- return resolved_local_path_spec.GetCString();
+ return resolved_symlink;
- return nullptr;
+ return local_spec;
}
-DWARFCompileUnit *SymbolFileDWARF::GetBaseCompileUnit() {
+DWARFUnit *SymbolFileDWARF::GetBaseCompileUnit() {
return nullptr;
}
@@ -334,7 +347,7 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope,
TypeSet type_set;
CompileUnit *comp_unit = NULL;
- DWARFCompileUnit *dwarf_cu = NULL;
+ DWARFUnit *dwarf_cu = NULL;
if (sc_scope)
comp_unit = sc_scope->CalculateSymbolContextCompileUnit();
@@ -382,6 +395,7 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
switch (tag) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
case DW_TAG_lexical_block:
@@ -392,20 +406,16 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
}
SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
- : SymbolFile(objfile), UserID(0), // Used by SymbolFileDWARFDebugMap to when
- // this class parses .o files to contain
- // the .o file index/ID
+ : SymbolFile(objfile), UserID(uint64_t(DW_INVALID_OFFSET)
+ << 32), // Used by SymbolFileDWARFDebugMap to
+ // when this class parses .o files to
+ // contain the .o file index/ID
m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
- m_line(), m_apple_names_ap(), m_apple_types_ap(), m_apple_namespaces_ap(),
- m_apple_objc_ap(), m_function_basename_index(),
- m_function_fullname_index(), m_function_method_index(),
- m_function_selector_index(), m_objc_class_selectors_index(),
- m_global_index(), m_type_index(), m_namespace_index(), m_indexed(false),
- m_using_apple_tables(false), m_fetched_external_modules(false),
+ m_line(), m_fetched_external_modules(false),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
m_unique_ast_type_map() {}
@@ -438,6 +448,7 @@ TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
}
void SymbolFileDWARF::InitializeObject() {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
ModuleSP module_sp(m_obj_file->GetModule());
if (module_sp) {
const SectionList *section_list = module_sp->GetSectionList();
@@ -448,45 +459,38 @@ void SymbolFileDWARF::InitializeObject() {
m_obj_file->ReadSectionData(section, m_dwarf_data);
}
- get_apple_names_data();
- if (m_data_apple_names.m_data.GetByteSize() > 0) {
- m_apple_names_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_names.m_data, get_debug_str_data(), ".apple_names"));
- if (m_apple_names_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_names_ap.reset();
- }
- get_apple_types_data();
- if (m_data_apple_types.m_data.GetByteSize() > 0) {
- m_apple_types_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_types.m_data, get_debug_str_data(), ".apple_types"));
- if (m_apple_types_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_types_ap.reset();
- }
+ if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) {
+ DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
+ LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
+ LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
+ LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
+ LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);
- get_apple_namespaces_data();
- if (m_data_apple_namespaces.m_data.GetByteSize() > 0) {
- m_apple_namespaces_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_namespaces.m_data, get_debug_str_data(),
- ".apple_namespaces"));
- if (m_apple_namespaces_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_namespaces_ap.reset();
- }
+ m_index = AppleDWARFIndex::Create(
+ *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
+ apple_types, apple_objc, get_debug_str_data());
- get_apple_objc_data();
- if (m_data_apple_objc.m_data.GetByteSize() > 0) {
- m_apple_objc_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_objc.m_data, get_debug_str_data(), ".apple_objc"));
- if (m_apple_objc_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_objc_ap.reset();
+ if (m_index)
+ return;
+
+ DWARFDataExtractor debug_names;
+ LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
+ if (debug_names.GetByteSize() > 0) {
+ llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
+ DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
+ debug_names, get_debug_str_data(),
+ DebugInfo());
+ if (index_or) {
+ m_index = std::move(*index_or);
+ return;
+ }
+ LLDB_LOG_ERROR(log, index_or.takeError(),
+ "Unable to read .debug_names data: {0}");
+ }
}
+
+ m_index = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(),
+ DebugInfo());
}
bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
@@ -501,15 +505,14 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
if (section_list == NULL)
return 0;
- // On non Apple platforms we might have .debug_types debug info that
- // is created by using "-fdebug-types-section". LLDB currently will try
- // to load this debug info, but it causes crashes during debugging when
- // types are missing since it doesn't know how to parse the info in
- // the .debug_types type units. This causes all complex debug info
- // types to be unresolved. Because this causes LLDB to crash and since
- // it really doesn't provide a solid debuggiung experience, we should
- // disable trying to debug this kind of DWARF until support gets
- // added or deprecated.
+ // On non Apple platforms we might have .debug_types debug info that is
+ // created by using "-fdebug-types-section". LLDB currently will try to
+ // load this debug info, but it causes crashes during debugging when types
+ // are missing since it doesn't know how to parse the info in the
+ // .debug_types type units. This causes all complex debug info types to be
+ // unresolved. Because this causes LLDB to crash and since it really
+ // doesn't provide a solid debuggiung experience, we should disable trying
+ // to debug this kind of DWARF until support gets added or deprecated.
if (section_list->FindSectionByName(ConstString(".debug_types"))) {
m_obj_file->GetModule()->ReportWarning(
"lldb doesn’t support .debug_types debug info");
@@ -561,10 +564,10 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
if (symfile_dir_cstr) {
if (strcasestr(symfile_dir_cstr, ".dsym")) {
if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo) {
- // We have a dSYM file that didn't have a any debug info.
- // If the string table has a size of 1, then it was made from
- // an executable with no debug info, or from an executable that
- // was stripped.
+ // We have a dSYM file that didn't have a any debug info. If the
+ // string table has a size of 1, then it was made from an
+ // executable with no debug info, or from an executable that was
+ // stripped.
section =
section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true)
.get();
@@ -664,6 +667,10 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_offsets_data() {
m_data_debug_str_offsets);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types);
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() {
return GetCachedSectionData(eSectionTypeDWARFAppleNames, m_data_apple_names);
}
@@ -681,6 +688,11 @@ const DWARFDataExtractor &SymbolFileDWARF::get_apple_objc_data() {
return GetCachedSectionData(eSectionTypeDWARFAppleObjC, m_data_apple_objc);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_gnu_debugaltlink() {
+ return GetCachedSectionData(eSectionTypeDWARFGNUDebugAltLink,
+ m_data_gnu_debugaltlink);
+}
+
DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
if (m_abbr.get() == NULL) {
const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
@@ -716,17 +728,17 @@ const DWARFDebugInfo *SymbolFileDWARF::DebugInfo() const {
return m_info.get();
}
-DWARFCompileUnit *
+DWARFUnit *
SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) {
if (!comp_unit)
return nullptr;
DWARFDebugInfo *info = DebugInfo();
if (info) {
- // Just a normal DWARF file whose user ID for the compile unit is
- // the DWARF offset itself
+ // Just a normal DWARF file whose user ID for the compile unit is the DWARF
+ // offset itself
- DWARFCompileUnit *dwarf_cu =
+ DWARFUnit *dwarf_cu =
info->GetCompileUnit((dw_offset_t)comp_unit->GetID());
if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
dwarf_cu->SetUserData(comp_unit);
@@ -753,7 +765,7 @@ const DWARFDebugRanges *SymbolFileDWARF::DebugRanges() const {
return m_ranges.get();
}
-lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) {
CompUnitSP cu_sp;
if (dwarf_cu) {
@@ -772,13 +784,13 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
} else {
ModuleSP module_sp(m_obj_file->GetModule());
if (module_sp) {
- const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE cu_die = dwarf_cu->DIE();
if (cu_die) {
FileSpec cu_file_spec{cu_die.GetName(), false};
if (cu_file_spec) {
// If we have a full path to the compile unit, we don't need to
- // resolve
- // the file. This can be expensive e.g. when the source files are
+ // resolve the file. This can be expensive e.g. when the source
+ // files are
// NFS mounted.
if (cu_file_spec.IsRelative()) {
const char *cu_comp_dir{
@@ -789,10 +801,11 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
std::string remapped_file;
if (module_sp->RemapSourceFile(cu_file_spec.GetPath(),
remapped_file))
- cu_file_spec.SetFile(remapped_file, false);
+ cu_file_spec.SetFile(remapped_file, false,
+ FileSpec::Style::native);
}
- LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(
+ LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
bool is_optimized = dwarf_cu->GetIsOptimized();
@@ -801,10 +814,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
cu_language, is_optimized ? eLazyBoolYes : eLazyBoolNo));
if (cu_sp) {
// If we just created a compile unit with an invalid file spec,
- // try and get the
- // first entry in the supports files from the line table as that
- // should be the
- // compile unit.
+ // try and get the first entry in the supports files from the
+ // line table as that should be the compile unit.
if (!cu_file_spec) {
cu_file_spec = cu_sp->GetSupportFiles().GetFileSpecAtIndex(1);
if (cu_file_spec) {
@@ -843,7 +854,7 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
CompUnitSP cu_sp;
DWARFDebugInfo *info = DebugInfo();
if (info) {
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu)
cu_sp = ParseCompileUnit(dwarf_cu, cu_idx);
}
@@ -876,7 +887,7 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) {
lldb::LanguageType
SymbolFileDWARF::ParseCompileUnitLanguage(const SymbolContext &sc) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
return dwarf_cu->GetLanguageType();
else
@@ -886,7 +897,7 @@ SymbolFileDWARF::ParseCompileUnitLanguage(const SymbolContext &sc) {
size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
assert(sc.comp_unit);
size_t functions_added = 0;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
DWARFDIECollection function_dies;
const size_t num_functions =
@@ -907,12 +918,12 @@ size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
const SymbolContext &sc, FileSpecList &support_files) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
- const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly();
if (cu_die) {
- const char *cu_comp_dir = resolveCompDir(
+ FileSpec cu_comp_dir = resolveCompDir(
cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(
DW_AT_stmt_list, DW_INVALID_OFFSET);
@@ -931,7 +942,7 @@ bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
bool SymbolFileDWARF::ParseCompileUnitIsOptimized(
const lldb_private::SymbolContext &sc) {
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
return dwarf_cu->GetIsOptimized();
return false;
@@ -941,14 +952,14 @@ bool SymbolFileDWARF::ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
if (ClangModulesDeclVendor::LanguageSupportsClangModules(
sc.comp_unit->GetLanguage())) {
UpdateExternalModuleListIfNeeded();
if (sc.comp_unit) {
- const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE die = dwarf_cu->DIE();
if (die) {
for (DWARFDIE child_die = die.GetFirstChild(); child_die;
@@ -998,8 +1009,7 @@ static void ParseDWARFLineTableCallback(dw_offset_t offset,
(ParseDWARFLineTableCallbackInfo *)userData;
LineTable *line_table = info->line_table;
- // If this is our first time here, we need to create a
- // sequence container.
+ // If this is our first time here, we need to create a sequence container.
if (!info->sequence_ap.get()) {
info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
assert(info->sequence_ap.get());
@@ -1022,9 +1032,9 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
if (sc.comp_unit->GetLineTable() != NULL)
return true;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
- const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
if (dwarf_cu_die) {
const dw_offset_t cu_line_offset =
dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list,
@@ -1063,10 +1073,10 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
&info);
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile) {
- // We have an object file that has a line table with addresses
- // that are not linked. We need to link the line table and convert
- // the addresses that are relative to the .o file into addresses
- // for the main executable.
+ // We have an object file that has a line table with addresses that
+ // are not linked. We need to link the line table and convert the
+ // addresses that are relative to the .o file into addresses for
+ // the main executable.
sc.comp_unit->SetLineTable(
debug_map_symfile->LinkOSOLineTable(this, line_table_ap.get()));
} else {
@@ -1105,11 +1115,11 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) {
bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu == nullptr)
return false;
- const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
if (!dwarf_cu_die)
return false;
@@ -1142,9 +1152,9 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
case DW_TAG_lexical_block: {
Block *block = NULL;
if (tag == DW_TAG_subprogram) {
- // Skip any DW_TAG_subprogram DIEs that are inside
- // of a normal or inlined functions. These will be
- // parsed on their own as separate entities.
+ // Skip any DW_TAG_subprogram DIEs that are inside of a normal or
+ // inlined functions. These will be parsed on their own as separate
+ // entities.
if (depth > 0)
break;
@@ -1172,18 +1182,14 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
assert(subprogram_low_pc == LLDB_INVALID_ADDRESS);
subprogram_low_pc = ranges.GetMinRangeBase(0);
} else if (tag == DW_TAG_inlined_subroutine) {
- // We get called here for inlined subroutines in two ways.
- // The first time is when we are making the Function object
- // for this inlined concrete instance. Since we're creating a top
- // level block at
+ // We get called here for inlined subroutines in two ways. The first
+ // time is when we are making the Function object for this inlined
+ // concrete instance. Since we're creating a top level block at
// here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we
- // need to
- // adjust the containing address.
- // The second time is when we are parsing the blocks inside the
- // function that contains
- // the inlined concrete instance. Since these will be blocks inside
- // the containing "real"
- // function the offset will be for that function.
+ // need to adjust the containing address. The second time is when we
+ // are parsing the blocks inside the function that contains the
+ // inlined concrete instance. Since these will be blocks inside the
+ // containing "real" function the offset will be for that function.
if (subprogram_low_pc == LLDB_INVALID_ADDRESS) {
subprogram_low_pc = ranges.GetMinRangeBase(0);
}
@@ -1238,9 +1244,9 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
break;
}
- // Only parse siblings of the block if we are not at depth zero. A depth
- // of zero indicates we are currently parsing the top level
- // DW_TAG_subprogram DIE
+ // Only parse siblings of the block if we are not at depth zero. A depth of
+ // zero indicates we are currently parsing the top level DW_TAG_subprogram
+ // DIE
if (depth == 0)
die.Clear();
@@ -1286,12 +1292,12 @@ void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
}
SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
- // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API
- // we must make sure we use the correct DWARF file when resolving things.
- // On MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
- // SymbolFileDWARF classes, one for each .o file. We can often end up
- // with references to other DWARF objects and we must be ready to receive
- // a "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
+ // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
+ // must make sure we use the correct DWARF file when resolving things. On
+ // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
+ // SymbolFileDWARF classes, one for each .o file. We can often end up with
+ // references to other DWARF objects and we must be ready to receive a
+ // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
// instance.
SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile();
if (debug_map)
@@ -1302,12 +1308,12 @@ SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
DWARFDIE
SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
- // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API
- // we must make sure we use the correct DWARF file when resolving things.
- // On MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
- // SymbolFileDWARF classes, one for each .o file. We can often end up
- // with references to other DWARF objects and we must be ready to receive
- // a "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
+ // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
+ // must make sure we use the correct DWARF file when resolving things. On
+ // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
+ // SymbolFileDWARF classes, one for each .o file. We can often end up with
+ // references to other DWARF objects and we must be ready to receive a
+ // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
// instance.
SymbolFileDWARF *dwarf = GetDWARFForUID(uid);
if (dwarf)
@@ -1316,9 +1322,9 @@ SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
}
CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE die = GetDIEFromUID(type_uid);
if (die)
return die.GetDecl();
@@ -1327,9 +1333,9 @@ CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
CompilerDeclContext
SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE die = GetDIEFromUID(type_uid);
if (die)
return die.GetDeclContext();
@@ -1338,9 +1344,9 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
CompilerDeclContext
SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE die = GetDIEFromUID(type_uid);
if (die)
return die.GetContainingDeclContext();
@@ -1348,9 +1354,9 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
}
Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE type_die = GetDIEFromUID(type_uid);
if (type_die)
return type_die.ResolveType();
@@ -1371,9 +1377,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
- // We might be coming in in the middle of a type tree (a class
- // within a class, an enum within a class), so parse any needed
- // parent DIEs before we get to this one...
+ // We might be coming in in the middle of a type tree (a class within a
+ // class, an enum within a class), so parse any needed parent DIEs before
+ // we get to this one...
DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(die);
if (decl_ctx_die) {
if (log) {
@@ -1401,8 +1407,8 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
}
// This function is used when SymbolFileDWARFDebugMap owns a bunch of
-// SymbolFileDWARF objects to detect if this DWARF file is the one that
-// can resolve a compiler_type.
+// SymbolFileDWARF objects to detect if this DWARF file is the one that can
+// resolve a compiler_type.
bool SymbolFileDWARF::HasForwardDeclForClangType(
const CompilerType &compiler_type) {
CompilerType compiler_type_no_qualifiers =
@@ -1448,12 +1454,10 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
if (dwarf_die) {
- // Once we start resolving this type, remove it from the forward declaration
- // map in case anyone child members or other types require this type to get
- // resolved.
- // The type will get resolved when all of the calls to
- // SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
- // are done.
+ // Once we start resolving this type, remove it from the forward
+ // declaration map in case anyone child members or other types require this
+ // type to get resolved. The type will get resolved when all of the calls
+ // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
GetForwardDeclClangTypeToDie().erase(die_it);
Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
@@ -1494,12 +1498,12 @@ Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
}
CompileUnit *
-SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu,
+SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) {
// Check if the symbol vendor already knows about this compile unit?
if (dwarf_cu->GetUserData() == NULL) {
- // The symbol vendor doesn't know about this compile unit, we
- // need to parse and add it to the symbol vendor object.
+ // The symbol vendor doesn't know about this compile unit, we need to parse
+ // and add it to the symbol vendor object.
return ParseCompileUnit(dwarf_cu, cu_idx).get();
}
return (CompileUnit *)dwarf_cu->GetUserData();
@@ -1508,15 +1512,7 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu,
size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name,
DIEArray &method_die_offsets) {
method_die_offsets.clear();
- if (m_using_apple_tables) {
- if (m_apple_objc_ap.get())
- m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
- } else {
- if (!m_indexed)
- Index();
-
- m_objc_class_selectors_index.Find(class_name, method_die_offsets);
- }
+ m_index->GetObjCMethods(class_name, method_die_offsets);
return method_die_offsets.size();
}
@@ -1560,9 +1556,9 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
- DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) {
+ DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) {
// If we are using a dSYM file, we never want the standard DWO files since
- // the -gmodule support uses the same DWO machanism to specify full debug
+ // the -gmodules support uses the same DWO machanism to specify full debug
// info files for modules.
if (GetDebugMapSymfile())
return nullptr;
@@ -1589,7 +1585,7 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
if (!comp_dir)
return nullptr;
- dwo_file.SetFile(comp_dir, true);
+ dwo_file.SetFile(comp_dir, true, FileSpec::Style::native);
dwo_file.AppendPathComponent(dwo_name);
}
@@ -1617,9 +1613,9 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
if (die && die.HasChildren() == false) {
const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
@@ -1632,35 +1628,35 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
if (dwo_path) {
ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, false,
+ FileSpec::Style::native);
if (dwo_module_spec.GetFileSpec().IsRelative()) {
const char *comp_dir =
die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
if (comp_dir) {
- dwo_module_spec.GetFileSpec().SetFile(comp_dir, true);
+ dwo_module_spec.GetFileSpec().SetFile(comp_dir, true,
+ FileSpec::Style::native);
dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
}
}
dwo_module_spec.GetArchitecture() =
m_obj_file->GetModule()->GetArchitecture();
- // When LLDB loads "external" modules it looks at the
- // presence of DW_AT_GNU_dwo_name.
- // However, when the already created module
- // (corresponding to .dwo itself) is being processed,
- // it will see the presence of DW_AT_GNU_dwo_name
- // (which contains the name of dwo file) and
- // will try to call ModuleList::GetSharedModule again.
- // In some cases (i.e. for empty files) Clang 4.0
- // generates a *.dwo file which has DW_AT_GNU_dwo_name,
- // but no DW_AT_comp_dir. In this case the method
- // ModuleList::GetSharedModule will fail and
- // the warning will be printed. However, as one can notice
- // in this case we don't actually need to try to load the already
- // loaded module (corresponding to .dwo) so we simply skip it.
+ // When LLDB loads "external" modules it looks at the presence of
+ // DW_AT_GNU_dwo_name. However, when the already created module
+ // (corresponding to .dwo itself) is being processed, it will see
+ // the presence of DW_AT_GNU_dwo_name (which contains the name of
+ // dwo file) and will try to call ModuleList::GetSharedModule
+ // again. In some cases (i.e. for empty files) Clang 4.0 generates
+ // a *.dwo file which has DW_AT_GNU_dwo_name, but no
+ // DW_AT_comp_dir. In this case the method
+ // ModuleList::GetSharedModule will fail and the warning will be
+ // printed. However, as one can notice in this case we don't
+ // actually need to try to load the already loaded module
+ // (corresponding to .dwo) so we simply skip it.
if (m_obj_file->GetFileSpec()
.GetFileNameExtension()
- .GetStringRef() == "dwo" &&
+ .GetStringRef() == ".dwo" &&
llvm::StringRef(m_obj_file->GetFileSpec().GetPath())
.endswith(dwo_module_spec.GetFileSpec().GetPath())) {
continue;
@@ -1751,13 +1747,11 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
const dw_offset_t cu_offset =
debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr);
if (cu_offset == DW_INVALID_OFFSET) {
- // Global variables are not in the compile unit address ranges. The only
- // way to
- // currently find global variables is to iterate over the
- // .debug_pubnames or the
- // __apple_names table and find all items in there that point to
- // DW_TAG_variable
- // DIEs and then find the address that matches.
+ // Global variables are not in the compile unit address ranges. The
+ // only way to currently find global variables is to iterate over the
+ // .debug_pubnames or the __apple_names table and find all items in
+ // there that point to DW_TAG_variable DIEs and then find the address
+ // that matches.
if (resolve_scope & eSymbolContextVariable) {
GlobalVariableMap &map = GetGlobalAranges();
const GlobalVariableMap::Entry *entry =
@@ -1774,7 +1768,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
}
} else {
uint32_t cu_idx = DW_INVALID_INDEX;
- DWARFCompileUnit *dwarf_cu =
+ DWARFUnit *dwarf_cu =
debug_info->GetCompileUnit(cu_offset, &cu_idx);
if (dwarf_cu) {
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
@@ -1825,13 +1819,10 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table != NULL) {
// And address that makes it into this function should be in
- // terms
- // of this debug file if there is no debug map, or it will be an
- // address in the .o file which needs to be fixed up to be in
- // terms
- // of the debug map executable. Either way, calling
- // FixupAddress()
- // will work for us.
+ // terms of this debug file if there is no debug map, or it
+ // will be an address in the .o file which needs to be fixed up
+ // to be in terms of the debug map executable. Either way,
+ // calling FixupAddress() will work for us.
Address exe_so_addr(so_addr);
if (FixupAddress(exe_so_addr)) {
if (line_table->FindLineEntryByAddress(exe_so_addr,
@@ -1845,11 +1836,11 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
if (force_check_line_table &&
!(resolved & eSymbolContextLineEntry)) {
// We might have had a compile unit that had discontiguous
- // address ranges where the gaps are symbols that don't have
- // any debug info. Discontiguous compile unit address ranges
- // should only happen when there aren't other functions from
- // other compile units in these gaps. This helps keep the size
- // of the aranges down.
+ // address ranges where the gaps are symbols that don't have any
+ // debug info. Discontiguous compile unit address ranges should
+ // only happen when there aren't other functions from other
+ // compile units in these gaps. This helps keep the size of the
+ // aranges down.
sc.comp_unit = NULL;
resolved &= ~eSymbolContextCompUnit;
}
@@ -1876,7 +1867,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
DWARFDebugInfo *debug_info = DebugInfo();
if (debug_info) {
uint32_t cu_idx;
- DWARFCompileUnit *dwarf_cu = NULL;
+ DWARFUnit *dwarf_cu = NULL;
for (cu_idx = 0;
(dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL;
@@ -1891,8 +1882,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
if (sc.comp_unit) {
uint32_t file_idx = UINT32_MAX;
- // If we are looking for inline functions only and we don't
- // find it in the support files, we are done.
+ // If we are looking for inline functions only and we don't find it
+ // in the support files, we are done.
if (check_inlines) {
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
1, file_spec, true);
@@ -1904,8 +1895,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table != NULL && line != 0) {
- // We will have already looked up the file index if
- // we are searching for inline entries.
+ // We will have already looked up the file index if we are
+ // searching for inline entries.
if (!check_inlines)
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
1, file_spec, true);
@@ -1962,16 +1953,14 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call
- // sites
- // by file and line and if the file spec matches that of the
- // compile unit
+ // sites by file and line and if the file spec matches that of
+ // the compile unit
sc_list.Append(sc);
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call
- // sites
- // by file and line and if the file spec matches that of the
- // compile unit
+ // sites by file and line and if the file spec matches that of
+ // the compile unit
sc_list.Append(sc);
}
@@ -1988,143 +1977,15 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
void SymbolFileDWARF::PreloadSymbols() {
std::lock_guard<std::recursive_mutex> guard(
GetObjectFile()->GetModule()->GetMutex());
- Index();
-}
-
-void SymbolFileDWARF::Index() {
- if (m_indexed)
- return;
- m_indexed = true;
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat, "SymbolFileDWARF::Index (%s)",
- GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>"));
-
- DWARFDebugInfo *debug_info = DebugInfo();
- if (debug_info) {
- const uint32_t num_compile_units = GetNumCompileUnits();
- if (num_compile_units == 0)
- return;
-
- std::vector<NameToDIE> function_basename_index(num_compile_units);
- std::vector<NameToDIE> function_fullname_index(num_compile_units);
- std::vector<NameToDIE> function_method_index(num_compile_units);
- std::vector<NameToDIE> function_selector_index(num_compile_units);
- std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
- std::vector<NameToDIE> global_index(num_compile_units);
- std::vector<NameToDIE> type_index(num_compile_units);
- std::vector<NameToDIE> namespace_index(num_compile_units);
-
- // std::vector<bool> might be implemented using bit test-and-set, so use
- // uint8_t instead.
- std::vector<uint8_t> clear_cu_dies(num_compile_units, false);
- auto parser_fn = [debug_info, &function_basename_index,
- &function_fullname_index, &function_method_index,
- &function_selector_index, &objc_class_selectors_index,
- &global_index, &type_index,
- &namespace_index](size_t cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- if (dwarf_cu) {
- dwarf_cu->Index(
- function_basename_index[cu_idx], function_fullname_index[cu_idx],
- function_method_index[cu_idx], function_selector_index[cu_idx],
- objc_class_selectors_index[cu_idx], global_index[cu_idx],
- type_index[cu_idx], namespace_index[cu_idx]);
- }
- };
-
- auto extract_fn = [debug_info, &clear_cu_dies](size_t cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- if (dwarf_cu) {
- // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the
- // DIEs for a compile unit have already been parsed.
- if (dwarf_cu->ExtractDIEsIfNeeded(false) > 1)
- clear_cu_dies[cu_idx] = true;
- }
- };
-
- // Create a task runner that extracts dies for each DWARF compile unit in a
- // separate thread
- //----------------------------------------------------------------------
- // First figure out which compile units didn't have their DIEs already
- // parsed and remember this. If no DIEs were parsed prior to this index
- // function call, we are going to want to clear the CU dies after we
- // are done indexing to make sure we don't pull in all DWARF dies, but
- // we need to wait until all compile units have been indexed in case
- // a DIE in one compile unit refers to another and the indexes accesses
- // those DIEs.
- //----------------------------------------------------------------------
- TaskMapOverInt(0, num_compile_units, extract_fn);
-
- // Now create a task runner that can index each DWARF compile unit in a
- // separate
- // thread so we can index quickly.
-
- TaskMapOverInt(0, num_compile_units, parser_fn);
-
- auto finalize_fn = [](NameToDIE &index, std::vector<NameToDIE> &srcs) {
- for (auto &src : srcs)
- index.Append(src);
- index.Finalize();
- };
-
- TaskPool::RunTasks(
- [&]() {
- finalize_fn(m_function_basename_index, function_basename_index);
- },
- [&]() {
- finalize_fn(m_function_fullname_index, function_fullname_index);
- },
- [&]() { finalize_fn(m_function_method_index, function_method_index); },
- [&]() {
- finalize_fn(m_function_selector_index, function_selector_index);
- },
- [&]() {
- finalize_fn(m_objc_class_selectors_index, objc_class_selectors_index);
- },
- [&]() { finalize_fn(m_global_index, global_index); },
- [&]() { finalize_fn(m_type_index, type_index); },
- [&]() { finalize_fn(m_namespace_index, namespace_index); });
-
- //----------------------------------------------------------------------
- // Keep memory down by clearing DIEs for any compile units if indexing
- // caused us to load the compile unit's DIEs.
- //----------------------------------------------------------------------
- for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- if (clear_cu_dies[cu_idx])
- debug_info->GetCompileUnitAtIndex(cu_idx)->ClearDIEs(true);
- }
-
-#if defined(ENABLE_DEBUG_PRINTF)
- StreamFile s(stdout, false);
- s.Printf("DWARF index for '%s':",
- GetObjectFile()->GetFileSpec().GetPath().c_str());
- s.Printf("\nFunction basenames:\n");
- m_function_basename_index.Dump(&s);
- s.Printf("\nFunction fullnames:\n");
- m_function_fullname_index.Dump(&s);
- s.Printf("\nFunction methods:\n");
- m_function_method_index.Dump(&s);
- s.Printf("\nFunction selectors:\n");
- m_function_selector_index.Dump(&s);
- s.Printf("\nObjective C class selectors:\n");
- m_objc_class_selectors_index.Dump(&s);
- s.Printf("\nGlobals and statics:\n");
- m_global_index.Dump(&s);
- s.Printf("\nTypes:\n");
- m_type_index.Dump(&s);
- s.Printf("\nNamespaces:\n");
- m_namespace_index.Dump(&s);
-#endif
- }
+ m_index->Preload();
}
bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
const lldb_private::CompilerDeclContext *decl_ctx) {
if (decl_ctx == nullptr || !decl_ctx->IsValid()) {
- // Invalid namespace decl which means we aren't matching only things
- // in this symbol file, so return true to indicate it matches this
- // symbol file.
+ // Invalid namespace decl which means we aren't matching only things in
+ // this symbol file, so return true to indicate it matches this symbol
+ // file.
return true;
}
@@ -2146,14 +2007,15 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
uint32_t SymbolFileDWARF::FindGlobalVariables(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches, VariableList &variables) {
+ uint32_t max_matches, VariableList &variables) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log)
GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
- "parent_decl_ctx=%p, append=%u, max_matches=%u, variables)",
- name.GetCString(), static_cast<const void *>(parent_decl_ctx), append,
+ log,
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
+ "parent_decl_ctx=%p, max_matches=%u, variables)",
+ name.GetCString(), static_cast<const void *>(parent_decl_ctx),
max_matches);
if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
@@ -2163,42 +2025,28 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
if (info == NULL)
return 0;
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
- DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
- const char *name_cstr = name.GetCString();
- llvm::StringRef basename;
- llvm::StringRef context;
-
- if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
- basename))
- basename = name_cstr;
+ llvm::StringRef basename;
+ llvm::StringRef context;
- m_apple_names_ap->FindByName(basename.data(), die_offsets);
- }
- } else {
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
-
- m_global_index.Find(name, die_offsets);
- }
+ if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(),
+ context, basename))
+ basename = name.GetStringRef();
+ DIEArray die_offsets;
+ m_index->GetGlobalVariables(ConstString(basename), die_offsets);
const size_t num_die_matches = die_offsets.size();
if (num_die_matches) {
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert(sc.module_sp);
+ // Loop invariant: Variables up to this index have been checked for context
+ // matches.
+ uint32_t pruned_idx = original_size;
+
bool done = false;
for (size_t i = 0; i < num_die_matches && !done; ++i) {
const DIERef &die_ref = die_offsets[i];
@@ -2229,18 +2077,21 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false,
&variables);
+ while (pruned_idx < variables.GetSize()) {
+ VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx);
+ if (var_sp->GetName().GetStringRef().contains(name.GetStringRef()))
+ ++pruned_idx;
+ else
+ variables.RemoveVariableAtIndex(pruned_idx);
+ }
if (variables.GetSize() - original_size >= max_matches)
done = true;
} break;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
}
@@ -2249,54 +2100,37 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
const uint32_t num_matches = variables.GetSize() - original_size;
if (log && num_matches > 0) {
GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
- "parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u",
- name.GetCString(), static_cast<const void *>(parent_decl_ctx), append,
+ log,
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
+ "parent_decl_ctx=%p, max_matches=%u, variables) => %u",
+ name.GetCString(), static_cast<const void *>(parent_decl_ctx),
max_matches, num_matches);
}
return num_matches;
}
uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
VariableList &variables) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log) {
GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, "
- "max_matches=%u, variables)",
- regex.GetText().str().c_str(), append, max_matches);
+ log,
+ "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", "
+ "max_matches=%u, variables)",
+ regex.GetText().str().c_str(), max_matches);
}
DWARFDebugInfo *info = DebugInfo();
if (info == NULL)
return 0;
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
- DWARFMappedHash::DIEInfoArray hash_data_array;
- if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex(regex,
- hash_data_array))
- DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
- }
- } else {
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
-
- m_global_index.Find(regex, die_offsets);
- }
+ m_index->GetGlobalVariables(regex, die_offsets);
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
@@ -2315,14 +2149,8 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
if (variables.GetSize() - original_size >= max_matches)
break;
- } else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for regex '%s')\n",
- die_ref.die_offset, regex.GetText().str().c_str());
- }
- }
+ } else
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset, regex.GetText());
}
}
@@ -2330,13 +2158,6 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
return variables.GetSize() - original_size;
}
-bool SymbolFileDWARF::ResolveFunction(const DIERef &die_ref,
- bool include_inlines,
- SymbolContextList &sc_list) {
- DWARFDIE die = DebugInfo()->GetDIE(die_ref);
- return ResolveFunction(die, include_inlines, sc_list);
-}
-
bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
bool include_inlines,
SymbolContextList &sc_list) {
@@ -2390,54 +2211,11 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
return false;
}
-void SymbolFileDWARF::FindFunctions(const ConstString &name,
- const NameToDIE &name_to_die,
- bool include_inlines,
- SymbolContextList &sc_list) {
- DIEArray die_offsets;
- if (name_to_die.Find(name, die_offsets)) {
- ParseFunctions(die_offsets, include_inlines, sc_list);
- }
-}
-
-void SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
- const NameToDIE &name_to_die,
- bool include_inlines,
- SymbolContextList &sc_list) {
- DIEArray die_offsets;
- if (name_to_die.Find(regex, die_offsets)) {
- ParseFunctions(die_offsets, include_inlines, sc_list);
- }
-}
-
-void SymbolFileDWARF::FindFunctions(
- const RegularExpression &regex,
- const DWARFMappedHash::MemoryTable &memory_table, bool include_inlines,
- SymbolContextList &sc_list) {
- DIEArray die_offsets;
- DWARFMappedHash::DIEInfoArray hash_data_array;
- if (memory_table.AppendAllDIEsThatMatchingRegex(regex, hash_data_array)) {
- DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
- ParseFunctions(die_offsets, include_inlines, sc_list);
- }
-}
-
-void SymbolFileDWARF::ParseFunctions(const DIEArray &die_offsets,
- bool include_inlines,
- SymbolContextList &sc_list) {
- const size_t num_matches = die_offsets.size();
- if (num_matches) {
- for (size_t i = 0; i < num_matches; ++i)
- ResolveFunction(die_offsets[i], include_inlines, sc_list);
- }
-}
-
bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx,
const DWARFDIE &die) {
// If we have no parent decl context to match this DIE matches, and if the
- // parent
- // decl context isn't valid, we aren't trying to look for any particular decl
- // context so any die matches.
+ // parent decl context isn't valid, we aren't trying to look for any
+ // particular decl context so any die matches.
if (decl_ctx == nullptr || !decl_ctx->IsValid())
return true;
@@ -2486,10 +2264,8 @@ SymbolFileDWARF::FindFunctions(const ConstString &name,
if (name.IsEmpty())
return 0;
- // Remember how many sc_list are in the list before we search in case
- // we are appending the results to a variable list.
-
- const char *name_cstr = name.GetCString();
+ // Remember how many sc_list are in the list before we search in case we are
+ // appending the results to a variable list.
const uint32_t original_size = sc_list.GetSize();
@@ -2497,228 +2273,17 @@ SymbolFileDWARF::FindFunctions(const ConstString &name,
if (info == NULL)
return 0;
- std::set<const DWARFDebugInfoEntry *> resolved_dies;
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
-
- DIEArray die_offsets;
-
- uint32_t num_matches = 0;
-
- if (name_type_mask & eFunctionNameTypeFull) {
- // If they asked for the full name, match what they typed. At some
- // point we may
- // want to canonicalize this (strip double spaces, etc. For now, we
- // just add all the
- // dies that we find by exact match.
- num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
- for (uint32_t i = 0; i < num_matches; i++) {
- const DIERef &die_ref = die_offsets[i];
- DWARFDIE die = info->GetDIE(die_ref);
- if (die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- continue; // The containing decl contexts don't match
-
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- } else {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')",
- die_ref.die_offset, name_cstr);
- }
- }
- }
-
- if (name_type_mask & eFunctionNameTypeSelector) {
- if (parent_decl_ctx && parent_decl_ctx->IsValid())
- return 0; // no selectors in namespaces
-
- num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
- // Now make sure these are actually ObjC methods. In this case we can
- // simply look up the name,
- // and if it is an ObjC method name, we're good.
+ llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
+ DIEArray offsets;
+ CompilerDeclContext empty_decl_ctx;
+ if (!parent_decl_ctx)
+ parent_decl_ctx = &empty_decl_ctx;
- for (uint32_t i = 0; i < num_matches; i++) {
- const DIERef &die_ref = die_offsets[i];
- DWARFDIE die = info->GetDIE(die_ref);
- if (die) {
- const char *die_name = die.GetName();
- if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) {
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- }
- } else {
- GetObjectFile()->GetModule()->ReportError(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')",
- die_ref.die_offset, name_cstr);
- }
- }
- die_offsets.clear();
- }
-
- if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) ||
- name_type_mask & eFunctionNameTypeBase) {
- // The apple_names table stores just the "base name" of C++ methods in
- // the table. So we have to
- // extract the base name, look that up, and if there is any other
- // information in the name we were
- // passed in we have to post-filter based on that.
-
- // FIXME: Arrange the logic above so that we don't calculate the base
- // name twice:
- num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
-
- for (uint32_t i = 0; i < num_matches; i++) {
- const DIERef &die_ref = die_offsets[i];
- DWARFDIE die = info->GetDIE(die_ref);
- if (die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- continue; // The containing decl contexts don't match
-
- // If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() &&
- ResolveFunction(die, include_inlines, sc_list)) {
- bool keep_die = true;
- if ((name_type_mask &
- (eFunctionNameTypeBase | eFunctionNameTypeMethod)) !=
- (eFunctionNameTypeBase | eFunctionNameTypeMethod)) {
- // We are looking for either basenames or methods, so we need to
- // trim out the ones we won't want by looking at the type
- SymbolContext sc;
- if (sc_list.GetLastContext(sc)) {
- if (sc.block) {
- // We have an inlined function
- } else if (sc.function) {
- Type *type = sc.function->GetType();
-
- if (type) {
- CompilerDeclContext decl_ctx =
- GetDeclContextContainingUID(type->GetID());
- if (decl_ctx.IsStructUnionOrClass()) {
- if (name_type_mask & eFunctionNameTypeBase) {
- sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
- keep_die = false;
- }
- } else {
- if (name_type_mask & eFunctionNameTypeMethod) {
- sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
- keep_die = false;
- }
- }
- } else {
- GetObjectFile()->GetModule()->ReportWarning(
- "function at die offset 0x%8.8x had no function type",
- die_ref.die_offset);
- }
- }
- }
- }
- if (keep_die)
- resolved_dies.insert(die.GetDIE());
- }
- } else {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')",
- die_ref.die_offset, name_cstr);
- }
- }
- die_offsets.clear();
- }
- }
- } else {
-
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
-
- if (name_type_mask & eFunctionNameTypeFull) {
- FindFunctions(name, m_function_fullname_index, include_inlines, sc_list);
-
- // FIXME Temporary workaround for global/anonymous namespace
- // functions debugging FreeBSD and Linux binaries.
- // If we didn't find any functions in the global namespace try
- // looking in the basename index but ignore any returned
- // functions that have a namespace but keep functions which
- // have an anonymous namespace
- // TODO: The arch in the object file isn't correct for MSVC
- // binaries on windows, we should find a way to make it
- // correct and handle those symbols as well.
- if (sc_list.GetSize() == original_size) {
- ArchSpec arch;
- if (!parent_decl_ctx && GetObjectFile()->GetArchitecture(arch) &&
- arch.GetTriple().isOSBinFormatELF()) {
- SymbolContextList temp_sc_list;
- FindFunctions(name, m_function_basename_index, include_inlines,
- temp_sc_list);
- SymbolContext sc;
- for (uint32_t i = 0; i < temp_sc_list.GetSize(); i++) {
- if (temp_sc_list.GetContextAtIndex(i, sc)) {
- ConstString mangled_name =
- sc.GetFunctionName(Mangled::ePreferMangled);
- ConstString demangled_name =
- sc.GetFunctionName(Mangled::ePreferDemangled);
- // Mangled names on Linux and FreeBSD are of the form:
- // _ZN18function_namespace13function_nameEv.
- if (strncmp(mangled_name.GetCString(), "_ZN", 3) ||
- !strncmp(demangled_name.GetCString(), "(anonymous namespace)",
- 21)) {
- sc_list.Append(sc);
- }
- }
- }
- }
- }
- }
- DIEArray die_offsets;
- if (name_type_mask & eFunctionNameTypeBase) {
- uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
- for (uint32_t i = 0; i < num_base; i++) {
- DWARFDIE die = info->GetDIE(die_offsets[i]);
- if (die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- continue; // The containing decl contexts don't match
-
- // If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- }
- }
- die_offsets.clear();
- }
-
- if (name_type_mask & eFunctionNameTypeMethod) {
- if (parent_decl_ctx && parent_decl_ctx->IsValid())
- return 0; // no methods in namespaces
-
- uint32_t num_base = m_function_method_index.Find(name, die_offsets);
- {
- for (uint32_t i = 0; i < num_base; i++) {
- DWARFDIE die = info->GetDIE(die_offsets[i]);
- if (die) {
- // If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- }
- }
- }
- die_offsets.clear();
- }
-
- if ((name_type_mask & eFunctionNameTypeSelector) &&
- (!parent_decl_ctx || !parent_decl_ctx->IsValid())) {
- FindFunctions(name, m_function_selector_index, include_inlines, sc_list);
- }
+ std::vector<DWARFDIE> dies;
+ m_index->GetFunctions(name, *info, *parent_decl_ctx, name_type_mask, dies);
+ for (const DWARFDIE &die: dies) {
+ if (resolved_dies.insert(die.GetDIE()).second)
+ ResolveFunction(die, include_inlines, sc_list);
}
// Return the number of variable that were appended to the list
@@ -2755,21 +2320,26 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
if (!append)
sc_list.Clear();
- // Remember how many sc_list are in the list before we search in case
- // we are appending the results to a variable list.
- uint32_t original_size = sc_list.GetSize();
+ DWARFDebugInfo *info = DebugInfo();
+ if (!info)
+ return 0;
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get())
- FindFunctions(regex, *m_apple_names_ap, include_inlines, sc_list);
- } else {
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
+ // Remember how many sc_list are in the list before we search in case we are
+ // appending the results to a variable list.
+ uint32_t original_size = sc_list.GetSize();
- FindFunctions(regex, m_function_basename_index, include_inlines, sc_list);
+ DIEArray offsets;
+ m_index->GetFunctions(regex, offsets);
- FindFunctions(regex, m_function_fullname_index, include_inlines, sc_list);
+ llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
+ for (DIERef ref : offsets) {
+ DWARFDIE die = info->GetDIE(ref);
+ if (!die) {
+ m_index->ReportInvalidDIEOffset(ref.die_offset, regex.GetText());
+ continue;
+ }
+ if (resolved_dies.insert(die.GetDIE()).second)
+ ResolveFunction(die, include_inlines, sc_list);
}
// Return the number of variable that were appended to the list
@@ -2785,7 +2355,7 @@ void SymbolFileDWARF::GetMangledNamesForFunction(
num_comp_units = info->GetNumCompileUnits();
for (uint32_t i = 0; i < num_comp_units; i++) {
- DWARFCompileUnit *cu = info->GetCompileUnitAtIndex(i);
+ DWARFUnit *cu = info->GetCompileUnitAtIndex(i);
if (cu == nullptr)
continue;
@@ -2847,19 +2417,7 @@ uint32_t SymbolFileDWARF::FindTypes(
return 0;
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const char *name_cstr = name.GetCString();
- m_apple_types_ap->FindByName(name_cstr, die_offsets);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(name, die_offsets);
- }
-
+ m_index->GetTypes(name, die_offsets);
const size_t num_die_matches = die_offsets.size();
if (num_die_matches) {
@@ -2881,12 +2439,8 @@ uint32_t SymbolFileDWARF::FindTypes(
break;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
const uint32_t num_matches = types.GetSize() - initial_types_size;
@@ -2935,25 +2489,13 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
if (context.empty())
return 0;
- DIEArray die_offsets;
-
ConstString name = context.back().name;
if (!name)
return 0;
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const char *name_cstr = name.GetCString();
- m_apple_types_ap->FindByName(name_cstr, die_offsets);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(name, die_offsets);
- }
-
+ DIEArray die_offsets;
+ m_index->GetTypes(name, die_offsets);
const size_t num_die_matches = die_offsets.size();
if (num_die_matches) {
@@ -2976,12 +2518,8 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
++num_matches;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
return num_matches;
@@ -3008,21 +2546,7 @@ SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
DWARFDebugInfo *info = DebugInfo();
if (info) {
DIEArray die_offsets;
-
- // Index if we already haven't to make sure the compile units
- // get indexed and make their global DIE index list
- if (m_using_apple_tables) {
- if (m_apple_namespaces_ap.get()) {
- const char *name_cstr = name.GetCString();
- m_apple_namespaces_ap->FindByName(name_cstr, die_offsets);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_namespace_index.Find(name, die_offsets);
- }
-
+ m_index->GetNamespaces(name, die_offsets);
const size_t num_matches = die_offsets.size();
if (num_matches) {
for (size_t i = 0; i < num_matches; ++i) {
@@ -3040,13 +2564,8 @@ SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
break;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified "
- "(.apple_namespaces accelerator table had bad die 0x%8.8x for "
- "'%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
}
@@ -3105,6 +2624,7 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) {
if (orig_die != die) {
switch (die.Tag()) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
@@ -3159,16 +2679,14 @@ SymbolFileDWARF::GetObjCClassSymbol(const ConstString &objc_class_name) {
}
// Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If
-// they don't
-// then we can end up looking through all class types for a complete type and
-// never find
-// the full definition. We need to know if this attribute is supported, so we
-// determine
-// this here and cache th result. We also need to worry about the debug map
+// they don't then we can end up looking through all class types for a complete
+// type and never find the full definition. We need to know if this attribute
+// is supported, so we determine this here and cache th result. We also need to
+// worry about the debug map
// DWARF file
// if we are doing darwin DWARF in .o file debugging.
bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(
- DWARFCompileUnit *cu) {
+ DWARFUnit *cu) {
if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type())
@@ -3177,7 +2695,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(
DWARFDebugInfo *debug_info = DebugInfo();
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu != cu &&
dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) {
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
@@ -3204,19 +2722,7 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
return type_sp;
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const char *name_cstr = type_name.GetCString();
- m_apple_types_ap->FindCompleteObjCClassByName(name_cstr, die_offsets,
- must_be_implementation);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(type_name, die_offsets);
- }
+ m_index->GetCompleteObjCClass(type_name, must_be_implementation, die_offsets);
const size_t num_matches = die_offsets.size();
@@ -3228,7 +2734,8 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
if (type_die) {
bool try_resolving_type = false;
- // Don't try and resolve the DIE we are looking for with the DIE itself!
+ // Don't try and resolve the DIE we are looking for with the DIE
+ // itself!
if (type_die != die) {
switch (type_die.Tag()) {
case DW_TAG_class_type:
@@ -3264,12 +2771,8 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
}
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, type_name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ type_name.GetStringRef());
}
}
}
@@ -3277,16 +2780,15 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
}
//----------------------------------------------------------------------
-// This function helps to ensure that the declaration contexts match for
-// two different DIEs. Often times debug information will refer to a
-// forward declaration of a type (the equivalent of "struct my_struct;".
-// There will often be a declaration of that type elsewhere that has the
-// full definition. When we go looking for the full type "my_struct", we
-// will find one or more matches in the accelerator tables and we will
-// then need to make sure the type was in the same declaration context
-// as the original DIE. This function can efficiently compare two DIEs
-// and will return true when the declaration context matches, and false
-// when they don't.
+// This function helps to ensure that the declaration contexts match for two
+// different DIEs. Often times debug information will refer to a forward
+// declaration of a type (the equivalent of "struct my_struct;". There will
+// often be a declaration of that type elsewhere that has the full definition.
+// When we go looking for the full type "my_struct", we will find one or more
+// matches in the accelerator tables and we will then need to make sure the
+// type was in the same declaration context as the original DIE. This function
+// can efficiently compare two DIEs and will return true when the declaration
+// context matches, and false when they don't.
//----------------------------------------------------------------------
bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
const DWARFDIE &die2) {
@@ -3295,32 +2797,31 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
DWARFDIECollection decl_ctx_1;
DWARFDIECollection decl_ctx_2;
- // The declaration DIE stack is a stack of the declaration context
- // DIEs all the way back to the compile unit. If a type "T" is
- // declared inside a class "B", and class "B" is declared inside
- // a class "A" and class "A" is in a namespace "lldb", and the
- // namespace is in a compile unit, there will be a stack of DIEs:
+ // The declaration DIE stack is a stack of the declaration context DIEs all
+ // the way back to the compile unit. If a type "T" is declared inside a class
+ // "B", and class "B" is declared inside a class "A" and class "A" is in a
+ // namespace "lldb", and the namespace is in a compile unit, there will be a
+ // stack of DIEs:
//
// [0] DW_TAG_class_type for "B"
// [1] DW_TAG_class_type for "A"
// [2] DW_TAG_namespace for "lldb"
- // [3] DW_TAG_compile_unit for the source file.
+ // [3] DW_TAG_compile_unit or DW_TAG_partial_unit for the source file.
//
- // We grab both contexts and make sure that everything matches
- // all the way back to the compiler unit.
+ // We grab both contexts and make sure that everything matches all the way
+ // back to the compiler unit.
// First lets grab the decl contexts for both DIEs
die1.GetDeclContextDIEs(decl_ctx_1);
die2.GetDeclContextDIEs(decl_ctx_2);
- // Make sure the context arrays have the same size, otherwise
- // we are done
+ // Make sure the context arrays have the same size, otherwise we are done
const size_t count1 = decl_ctx_1.Size();
const size_t count2 = decl_ctx_2.Size();
if (count1 != count2)
return false;
- // Make sure the DW_TAG values match all the way back up the
- // compile unit. If they don't, then we are done.
+ // Make sure the DW_TAG values match all the way back up the compile unit. If
+ // they don't, then we are done.
DWARFDIE decl_ctx_die1;
DWARFDIE decl_ctx_die2;
size_t i;
@@ -3333,25 +2834,28 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
#if defined LLDB_CONFIGURATION_DEBUG
// Make sure the top item in the decl context die array is always
- // DW_TAG_compile_unit. If it isn't then something went wrong in
- // the DWARFDIE::GetDeclContextDIEs() function...
- assert(decl_ctx_1.GetDIEAtIndex(count1 - 1).Tag() == DW_TAG_compile_unit);
+ // DW_TAG_compile_unit or DW_TAG_partial_unit. If it isn't then
+ // something went wrong in the DWARFDIE::GetDeclContextDIEs()
+ // function.
+ dw_tag_t cu_tag = decl_ctx_1.GetDIEAtIndex(count1 - 1).Tag();
+ UNUSED_IF_ASSERT_DISABLED(cu_tag);
+ assert(cu_tag == DW_TAG_compile_unit || cu_tag == DW_TAG_partial_unit);
#endif
- // Always skip the compile unit when comparing by only iterating up to
- // "count - 1". Here we compare the names as we go.
+ // Always skip the compile unit when comparing by only iterating up to "count
+ // - 1". Here we compare the names as we go.
for (i = 0; i < count1 - 1; i++) {
decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex(i);
decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex(i);
const char *name1 = decl_ctx_die1.GetName();
const char *name2 = decl_ctx_die2.GetName();
- // If the string was from a DW_FORM_strp, then the pointer will often
- // be the same!
+ // If the string was from a DW_FORM_strp, then the pointer will often be
+ // the same!
if (name1 == name2)
continue;
- // Name pointers are not equal, so only compare the strings
- // if both are not NULL.
+ // Name pointers are not equal, so only compare the strings if both are not
+ // NULL.
if (name1 && name2) {
// If the strings don't compare, we are done...
if (strcmp(name1, name2) != 0)
@@ -3361,8 +2865,8 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
return false;
}
}
- // We made it through all of the checks and the declaration contexts
- // are equal.
+ // We made it through all of the checks and the declaration contexts are
+ // equal.
return true;
}
@@ -3387,47 +2891,12 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
}
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const bool has_tag =
- m_apple_types_ap->GetHeader().header_data.ContainsAtom(
- DWARFMappedHash::eAtomTypeTag);
- const bool has_qualified_name_hash =
- m_apple_types_ap->GetHeader().header_data.ContainsAtom(
- DWARFMappedHash::eAtomTypeQualNameHash);
- if (has_tag && has_qualified_name_hash) {
- const char *qualified_name = dwarf_decl_ctx.GetQualifiedName();
- const uint32_t qualified_name_hash =
- MappedHash::HashStringUsingDJB(qualified_name);
- if (log)
- GetObjectFile()->GetModule()->LogMessage(
- log, "FindByNameAndTagAndQualifiedNameHash()");
- m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash(
- type_name.GetCString(), tag, qualified_name_hash, die_offsets);
- } else if (has_tag) {
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log,
- "FindByNameAndTag()");
- m_apple_types_ap->FindByNameAndTag(type_name.GetCString(), tag,
- die_offsets);
- } else {
- m_apple_types_ap->FindByName(type_name.GetCString(), die_offsets);
- }
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(type_name, die_offsets);
- }
-
+ m_index->GetTypes(dwarf_decl_ctx, die_offsets);
const size_t num_matches = die_offsets.size();
- // Get the type system that we are looking to find a type for. We will use
- // this
- // to ensure any matches we find are in a language that this type system
- // supports
+ // Get the type system that we are looking to find a type for. We will
+ // use this to ensure any matches we find are in a language that this
+ // type system supports
const LanguageType language = dwarf_decl_ctx.GetLanguage();
TypeSystem *type_system = (language == eLanguageTypeUnknown)
? nullptr
@@ -3440,10 +2909,8 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
if (type_die) {
// Make sure type_die's langauge matches the type system we are
- // looking for.
- // We don't want to find a "Foo" type from Java if we are looking
- // for a "Foo"
- // type for C, C++, ObjC, or ObjC++.
+ // looking for. We don't want to find a "Foo" type from Java if we
+ // are looking for a "Foo" type for C, C++, ObjC, or ObjC++.
if (type_system &&
!type_system->SupportsLanguage(type_die.GetLanguage()))
continue;
@@ -3457,24 +2924,23 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
// The tags match, lets try resolving this type
try_resolving_type = true;
} else {
- // The tags don't match, but we need to watch our for a
- // forward declaration for a struct and ("struct foo")
- // ends up being a class ("class foo { ... };") or
- // vice versa.
+ // The tags don't match, but we need to watch our for a forward
+ // declaration for a struct and ("struct foo") ends up being a
+ // class ("class foo { ... };") or vice versa.
switch (type_tag) {
case DW_TAG_class_type:
- // We had a "class foo", see if we ended up with a "struct foo {
- // ... };"
+ // We had a "class foo", see if we ended up with a "struct foo
+ // { ... };"
try_resolving_type = (tag == DW_TAG_structure_type);
break;
case DW_TAG_structure_type:
- // We had a "struct foo", see if we ended up with a "class foo {
- // ... };"
+ // We had a "struct foo", see if we ended up with a "class foo
+ // { ... };"
try_resolving_type = (tag == DW_TAG_class_type);
break;
default:
- // Tags don't match, don't event try to resolve
- // using this type whose name matches....
+ // Tags don't match, don't event try to resolve using this type
+ // whose name matches....
break;
}
}
@@ -3515,12 +2981,8 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
}
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, type_name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ type_name.GetStringRef());
}
}
}
@@ -3606,7 +3068,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc,
size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc) {
assert(sc.comp_unit && sc.function);
size_t functions_added = 0;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
const dw_offset_t function_die_offset = sc.function->GetID();
DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset);
@@ -3623,7 +3085,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) {
// At least a compile unit must be valid
assert(sc.comp_unit);
size_t types_added = 0;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
if (sc.function) {
dw_offset_t function_die_offset = sc.function->GetID();
@@ -3662,7 +3124,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
return num_variables;
}
} else if (sc.comp_unit) {
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());
+ DWARFUnit *dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());
if (dwarf_cu == NULL)
return 0;
@@ -3675,25 +3137,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
sc.comp_unit->SetVariableList(variables);
DIEArray die_offsets;
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
- DWARFMappedHash::DIEInfoArray hash_data_array;
- if (m_apple_names_ap->AppendAllDIEsInRange(
- dwarf_cu->GetOffset(), dwarf_cu->GetNextCompileUnitOffset(),
- hash_data_array)) {
- DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
- }
- }
- } else {
- // Index if we already haven't to make sure the compile units
- // get indexed and make their global DIE index list
- if (!m_indexed)
- Index();
-
- m_global_index.FindAllEntriesForCompileUnit(dwarf_cu->GetOffset(),
- die_offsets);
- }
-
+ m_index->GetGlobalVariables(*dwarf_cu, die_offsets);
const size_t num_matches = die_offsets.size();
if (num_matches) {
for (size_t i = 0; i < num_matches; ++i) {
@@ -3706,14 +3150,8 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
variables->AddVariableIfUnique(var_sp);
++vars_added;
}
- } else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified "
- "(.apple_names accelerator table had bad die 0x%8.8x)\n",
- die_ref.die_offset);
- }
- }
+ } else
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset, "");
}
}
}
@@ -3796,7 +3234,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
location_is_const_value_data = true;
// The constant value will be either a block, a data value or a
// string.
- const DWARFDataExtractor &debug_info_data = get_debug_info_data();
+ auto debug_info_data = die.GetData();
if (DWARFFormValue::IsBlockForm(form_value.Form())) {
// Retrieve the value as a block expression.
uint32_t block_offset =
@@ -3853,13 +3291,12 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
location_is_const_value_data = false;
has_explicit_location = true;
if (DWARFFormValue::IsBlockForm(form_value.Form())) {
- const DWARFDataExtractor &debug_info_data = get_debug_info_data();
+ auto data = die.GetData();
uint32_t block_offset =
- form_value.BlockData() - debug_info_data.GetDataStart();
+ form_value.BlockData() - data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- location.CopyOpcodeData(module, get_debug_info_data(),
- block_offset, block_length);
+ location.CopyOpcodeData(module, data, block_offset, block_length);
} else {
const DWARFDataExtractor &debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
@@ -3902,10 +3339,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
// TODO: Handle the case when DW_AT_start_scope have form
// constant. The
// dwarf spec is a bit ambiguous about what is the expected
- // behavior in
- // case the enclosing block have a non coninious address range and
- // the
- // DW_AT_start_scope entry have a form constant.
+ // behavior in case the enclosing block have a non coninious
+ // address range and the DW_AT_start_scope entry have a form
+ // constant.
GetObjectFile()->GetModule()->ReportWarning(
"0x%8.8" PRIx64
": DW_AT_start_scope has unsupported form type (0x%x)\n",
@@ -3937,7 +3373,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
const dw_tag_t parent_tag = die.GetParent().Tag();
bool is_static_member =
- parent_tag == DW_TAG_compile_unit &&
+ (parent_tag == DW_TAG_compile_unit ||
+ parent_tag == DW_TAG_partial_unit) &&
(parent_context_die.Tag() == DW_TAG_class_type ||
parent_context_die.Tag() == DW_TAG_structure_type);
@@ -3949,17 +3386,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
bool has_explicit_mangled = mangled != nullptr;
if (!mangled) {
// LLDB relies on the mangled name (DW_TAG_linkage_name or
- // DW_AT_MIPS_linkage_name) to
- // generate fully qualified names of global variables with commands like
- // "frame var j".
- // For example, if j were an int variable holding a value 4 and declared
- // in a namespace
- // B which in turn is contained in a namespace A, the command "frame var
- // j" returns
- // "(int) A::B::j = 4". If the compiler does not emit a linkage name, we
- // should be able
- // to generate a fully qualified name from the declaration context.
- if (parent_tag == DW_TAG_compile_unit &&
+ // DW_AT_MIPS_linkage_name) to generate fully qualified names
+ // of global variables with commands like "frame var j". For
+ // example, if j were an int variable holding a value 4 and
+ // declared in a namespace B which in turn is contained in a
+ // namespace A, the command "frame var j" returns
+ // "(int) A::B::j = 4".
+ // If the compiler does not emit a linkage name, we should be
+ // able to generate a fully qualified name from the
+ // declaration context.
+ if ((parent_tag == DW_TAG_compile_unit ||
+ parent_tag == DW_TAG_partial_unit) &&
Language::LanguageIsCPlusPlus(die.GetLanguage())) {
DWARFDeclContext decl_ctx;
@@ -4007,24 +3444,21 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
scope = eValueTypeVariableStatic;
if (debug_map_symfile) {
- // When leaving the DWARF in the .o files on darwin,
- // when we have a global variable that wasn't initialized,
- // the .o file might not have allocated a virtual
- // address for the global variable. In this case it will
- // have created a symbol for the global variable
- // that is undefined/data and external and the value will
- // be the byte size of the variable. When we do the
- // address map in SymbolFileDWARFDebugMap we rely on
- // having an address, we need to do some magic here
- // so we can get the correct address for our global
- // variable. The address for all of these entries
- // will be zero, and there will be an undefined symbol
- // in this object file, and the executable will have
- // a matching symbol with a good address. So here we
- // dig up the correct address and replace it in the
- // location for the variable, and set the variable's
- // symbol context scope to be that of the main executable
- // so the file address will resolve correctly.
+ // When leaving the DWARF in the .o files on darwin, when we have a
+ // global variable that wasn't initialized, the .o file might not
+ // have allocated a virtual address for the global variable. In
+ // this case it will have created a symbol for the global variable
+ // that is undefined/data and external and the value will be the
+ // byte size of the variable. When we do the address map in
+ // SymbolFileDWARFDebugMap we rely on having an address, we need to
+ // do some magic here so we can get the correct address for our
+ // global variable. The address for all of these entries will be
+ // zero, and there will be an undefined symbol in this object file,
+ // and the executable will have a matching symbol with a good
+ // address. So here we dig up the correct address and replace it in
+ // the location for the variable, and set the variable's symbol
+ // context scope to be that of the main executable so the file
+ // address will resolve correctly.
bool linked_oso_file_addr = false;
if (is_external && location_DW_OP_addr == 0) {
// we have a possible uninitialized extern global
@@ -4056,8 +3490,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
if (!linked_oso_file_addr) {
// The DW_OP_addr is not zero, but it contains a .o file address
- // which
- // needs to be linked up correctly.
+ // which needs to be linked up correctly.
const lldb::addr_t exe_file_addr =
debug_map_symfile->LinkOSOFileAddress(this,
location_DW_OP_addr);
@@ -4127,16 +3560,16 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
var_sp->SetLocationIsConstantValueData(location_is_const_value_data);
} else {
- // Not ready to parse this variable yet. It might be a global
- // or static variable that is in a function scope and the function
- // in the symbol context wasn't filled in yet
+ // Not ready to parse this variable yet. It might be a global or static
+ // variable that is in a function scope and the function in the symbol
+ // context wasn't filled in yet
return var_sp;
}
}
- // Cache var_sp even if NULL (the variable was just a specification or
- // was missing vital information to be able to be displayed in the debugger
- // (missing location due to optimization, etc)) so we don't re-parse
- // this DIE over and over later...
+ // Cache var_sp even if NULL (the variable was just a specification or was
+ // missing vital information to be able to be displayed in the debugger
+ // (missing location due to optimization, etc)) so we don't re-parse this
+ // DIE over and over later...
GetDIEToVariable()[die.GetDIE()] = var_sp;
if (spec_die)
GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
@@ -4217,11 +3650,11 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
dw_tag_t parent_tag = sc_parent_die.Tag();
switch (parent_tag) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
if (sc.comp_unit != NULL) {
variable_list_sp = sc.comp_unit->GetVariableList(false);
if (variable_list_sp.get() == NULL) {
variable_list_sp.reset(new VariableList());
- sc.comp_unit->SetVariableList(variable_list_sp);
}
} else {
GetObjectFile()->GetModule()->ReportError(
@@ -4243,8 +3676,8 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
Block *block = sc.function->GetBlock(true).FindBlockByID(
sc_parent_die.GetID());
if (block == NULL) {
- // This must be a specification or abstract origin with
- // a concrete block counterpart in the current function. We need
+ // This must be a specification or abstract origin with a
+ // concrete block counterpart in the current function. We need
// to find the concrete block so we can correctly add the
// variable to it
const DWARFDIE concrete_block_die =
@@ -4310,30 +3743,7 @@ ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); }
uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; }
-void SymbolFileDWARF::DumpIndexes() {
- StreamFile s(stdout, false);
-
- s.Printf(
- "DWARF index for (%s) '%s':",
- GetObjectFile()->GetModule()->GetArchitecture().GetArchitectureName(),
- GetObjectFile()->GetFileSpec().GetPath().c_str());
- s.Printf("\nFunction basenames:\n");
- m_function_basename_index.Dump(&s);
- s.Printf("\nFunction fullnames:\n");
- m_function_fullname_index.Dump(&s);
- s.Printf("\nFunction methods:\n");
- m_function_method_index.Dump(&s);
- s.Printf("\nFunction selectors:\n");
- m_function_selector_index.Dump(&s);
- s.Printf("\nObjective C class selectors:\n");
- m_objc_class_selectors_index.Dump(&s);
- s.Printf("\nGlobals and statics:\n");
- m_global_index.Dump(&s);
- s.Printf("\nTypes:\n");
- m_type_index.Dump(&s);
- s.Printf("\nNamespaces:\n");
- m_namespace_index.Dump(&s);
-}
+void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); }
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 6902dc0333d2..a5f2ac8f3e7d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -38,8 +38,7 @@
// Project includes
#include "DWARFDataExtractor.h"
#include "DWARFDefines.h"
-#include "HashedNameToDIE.h"
-#include "NameToDIE.h"
+#include "DWARFIndex.h"
#include "UniqueDWARFASTType.h"
//----------------------------------------------------------------------
@@ -54,7 +53,6 @@ class DWARFDebugAranges;
class DWARFDebugInfo;
class DWARFDebugInfoEntry;
class DWARFDebugLine;
-class DWARFDebugPubnames;
class DWARFDebugRanges;
class DWARFDeclContext;
class DWARFDIECollection;
@@ -72,7 +70,7 @@ public:
friend class SymbolFileDWARFDwo;
friend class DebugMapModule;
friend struct DIERef;
- friend class DWARFCompileUnit;
+ friend class DWARFUnit;
friend class DWARFDIE;
friend class DWARFASTParserClang;
friend class DWARFASTParserGo;
@@ -181,11 +179,11 @@ public:
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t
@@ -247,10 +245,12 @@ public:
const lldb_private::DWARFDataExtractor &get_debug_ranges_data();
const lldb_private::DWARFDataExtractor &get_debug_str_data();
const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
+ const lldb_private::DWARFDataExtractor &get_debug_types_data();
const lldb_private::DWARFDataExtractor &get_apple_names_data();
const lldb_private::DWARFDataExtractor &get_apple_types_data();
const lldb_private::DWARFDataExtractor &get_apple_namespaces_data();
const lldb_private::DWARFDataExtractor &get_apple_objc_data();
+ const lldb_private::DWARFDataExtractor &get_gnu_debugaltlink();
DWARFDebugAbbrev *DebugAbbrev();
@@ -273,19 +273,19 @@ public:
HasForwardDeclForClangType(const lldb_private::CompilerType &compiler_type);
lldb_private::CompileUnit *
- GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu,
+ GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx = UINT32_MAX);
virtual size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name,
DIEArray &method_die_offsets);
- bool Supports_DW_AT_APPLE_objc_complete_type(DWARFCompileUnit *cu);
+ bool Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu);
lldb_private::DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset);
static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die);
- virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+ virtual lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx);
virtual lldb_private::DWARFExpression::LocationListFormat
@@ -293,16 +293,30 @@ public:
lldb::ModuleSP GetDWOModule(lldb_private::ConstString name);
+ typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
+ ExternalTypeModuleMap;
+
+ /// Return the list of Clang modules imported by this SymbolFile.
+ const ExternalTypeModuleMap& getExternalTypeModules() const {
+ return m_external_type_modules;
+ }
+
virtual DWARFDIE GetDIE(const DIERef &die_ref);
virtual std::unique_ptr<SymbolFileDWARFDwo>
- GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu,
+ GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
const DWARFDebugInfoEntry &cu_die);
// For regular SymbolFileDWARF instances the method returns nullptr,
// for the instances of the subclass SymbolFileDWARFDwo
// the method returns a pointer to the base compile unit.
- virtual DWARFCompileUnit *GetBaseCompileUnit();
+ virtual DWARFUnit *GetBaseCompileUnit();
+
+ static bool
+ DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ const DWARFDIE &die);
+
+ void Dump(lldb_private::Stream &s) override;
protected:
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
@@ -331,14 +345,10 @@ protected:
bool DeclContextMatchesThisSymbolFile(
const lldb_private::CompilerDeclContext *decl_ctx);
- bool
- DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
- const DWARFDIE &die);
-
- virtual DWARFCompileUnit *
+ virtual DWARFUnit *
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
- DWARFCompileUnit *GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit *prev_cu);
+ DWARFUnit *GetNextUnparsedDWARFCompileUnit(DWARFUnit *prev_cu);
bool GetFunction(const DWARFDIE &die, lldb_private::SymbolContext &sc);
@@ -375,25 +385,9 @@ protected:
bool ClassOrStructIsVirtual(const DWARFDIE &die);
// Given a die_offset, figure out the symbol context representing that die.
- bool ResolveFunction(const DIERef &die_ref, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
lldb_private::SymbolContextList &sc_list);
- void FindFunctions(const lldb_private::ConstString &name,
- const NameToDIE &name_to_die, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
- void FindFunctions(const lldb_private::RegularExpression &regex,
- const NameToDIE &name_to_die, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
- void FindFunctions(const lldb_private::RegularExpression &regex,
- const DWARFMappedHash::MemoryTable &memory_table,
- bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
virtual lldb::TypeSP
FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx);
@@ -404,16 +398,9 @@ protected:
lldb_private::Symbol *
GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name);
- void ParseFunctions(const DIEArray &die_offsets, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
lldb::TypeSP GetTypeForDIE(const DWARFDIE &die,
bool resolve_function_context = false);
- void Index();
-
- void DumpIndexes();
-
void SetDebugMapModule(const lldb::ModuleSP &module_sp) {
m_debug_map_module_wp = module_sp;
}
@@ -439,9 +426,6 @@ protected:
typedef std::set<lldb_private::Type *> TypeSet;
- typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
- ExternalTypeModuleMap;
-
void GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset,
dw_offset_t max_die_offset, uint32_t type_mask,
TypeSet &type_set);
@@ -487,10 +471,12 @@ protected:
DWARFDataSegment m_data_debug_ranges;
DWARFDataSegment m_data_debug_str;
DWARFDataSegment m_data_debug_str_offsets;
+ DWARFDataSegment m_data_debug_types;
DWARFDataSegment m_data_apple_names;
DWARFDataSegment m_data_apple_types;
DWARFDataSegment m_data_apple_namespaces;
DWARFDataSegment m_data_apple_objc;
+ DWARFDataSegment m_data_gnu_debugaltlink;
// The unique pointer items below are generated on demand if and when someone
// accesses
@@ -498,10 +484,6 @@ protected:
std::unique_ptr<DWARFDebugAbbrev> m_abbr;
std::unique_ptr<DWARFDebugInfo> m_info;
std::unique_ptr<DWARFDebugLine> m_line;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_names_ap;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP>
@@ -509,17 +491,8 @@ protected:
DebugMacrosMap m_debug_macros_map;
ExternalTypeModuleMap m_external_type_modules;
- NameToDIE m_function_basename_index; // All concrete functions
- NameToDIE m_function_fullname_index; // All concrete functions
- NameToDIE m_function_method_index; // All inlined functions
- NameToDIE
- m_function_selector_index; // All method names for functions of classes
- NameToDIE m_objc_class_selectors_index; // Given a class name, find all
- // selectors for the class
- NameToDIE m_global_index; // Global and static variables
- NameToDIE m_type_index; // All type DIE offsets
- NameToDIE m_namespace_index; // All type DIE offsets
- bool m_indexed : 1, m_using_apple_tables : 1, m_fetched_external_modules : 1;
+ std::unique_ptr<lldb_private::DWARFIndex> m_index;
+ bool m_fetched_external_modules : 1;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
typedef std::shared_ptr<std::set<DIERef>> DIERefSetSP;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index eabff86a5428..39c70d146524 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -44,10 +44,8 @@ using namespace lldb;
using namespace lldb_private;
// Subclass lldb_private::Module so we can intercept the
-// "Module::GetObjectFile()"
-// (so we can fixup the object file sections) and also for
-// "Module::GetSymbolVendor()"
-// (so we can fixup the symbol file id.
+// "Module::GetObjectFile()" (so we can fixup the object file sections) and
+// also for "Module::GetSymbolVendor()" (so we can fixup the symbol file id.
const SymbolFileDWARFDebugMap::FileRangeMap &
SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
@@ -84,8 +82,8 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
/// const uint32_t fun_resolve_flags = SymbolContext::Module |
/// eSymbolContextCompUnit | eSymbolContextFunction;
// SectionList *oso_sections = oso_objfile->Sections();
- // Now we need to make sections that map from zero based object
- // file addresses to where things ended up in the main executable.
+ // Now we need to make sections that map from zero based object file
+ // addresses to where things ended up in the main executable.
assert(comp_unit_info->first_symbol_index != UINT32_MAX);
// End index is one past the last valid symbol index
@@ -104,9 +102,9 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
break;
case eSymbolTypeCode: {
- // For each N_FUN, or function that we run into in the debug map
- // we make a new section that we add to the sections found in the
- // .o file. This new section has the file address set to what the
+ // For each N_FUN, or function that we run into in the debug map we
+ // make a new section that we add to the sections found in the .o
+ // file. This new section has the file address set to what the
// addresses are in the .o file, and the load address is adjusted
// to match where it ended up in the final executable! We do this
// before we parse any dwarf info so that when it goes get parsed
@@ -129,21 +127,21 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
} break;
case eSymbolTypeData: {
- // For each N_GSYM we remap the address for the global by making
- // a new section that we add to the sections found in the .o file.
- // This new section has the file address set to what the
- // addresses are in the .o file, and the load address is adjusted
- // to match where it ended up in the final executable! We do this
- // before we parse any dwarf info so that when it goes get parsed
- // all section/offset addresses that get registered will resolve
+ // For each N_GSYM we remap the address for the global by making a
+ // new section that we add to the sections found in the .o file.
+ // This new section has the file address set to what the addresses
+ // are in the .o file, and the load address is adjusted to match
+ // where it ended up in the final executable! We do this before we
+ // parse any dwarf info so that when it goes get parsed all
+ // section/offset addresses that get registered will resolve
// correctly to the new addresses in the main executable. We
// initially set the section size to be 1 byte, but will need to
// fix up these addresses further after all globals have been
// parsed to span the gaps, or we can find the global variable
// sizes from the DWARF info as we are parsing.
- // Next we find the non-stab entry that corresponds to the N_GSYM in
- // the .o file
+ // Next we find the non-stab entry that corresponds to the N_GSYM
+ // in the .o file
Symbol *oso_gsym_symbol =
oso_symtab->FindFirstSymbolWithNameAndType(
exe_symbol->GetMangled().GetName(lldb::eLanguageTypeUnknown,
@@ -198,9 +196,9 @@ public:
SymbolVendor *symbol_vendor =
Module::GetSymbolVendor(can_create, feedback_strm);
if (symbol_vendor) {
- // Set a pointer to this class to set our OSO DWARF file know
- // that the DWARF is being used along with a debug map and that
- // it will have the remapped sections that we do below.
+ // Set a pointer to this class to set our OSO DWARF file know that
+ // the DWARF is being used along with a debug map and that it will
+ // have the remapped sections that we do below.
SymbolFileDWARF *oso_symfile =
SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(
symbol_vendor->GetSymbolFile());
@@ -292,8 +290,8 @@ void SymbolFileDWARFDebugMap::InitOSO() {
// In order to get the abilities of this plug-in, we look at the list of
// N_OSO entries (object files) from the symbol table and make sure that
- // these files exist and also contain valid DWARF. If we get any of that
- // then we return the abilities of the first N_OSO's DWARF.
+ // these files exist and also contain valid DWARF. If we get any of that then
+ // we return the abilities of the first N_OSO's DWARF.
Symtab *symtab = m_obj_file->GetSymtab();
if (symtab) {
@@ -303,10 +301,10 @@ void SymbolFileDWARFDebugMap::InitOSO() {
// When a mach-o symbol is encoded, the n_type field is encoded in bits
// 23:16, and the n_desc field is encoded in bits 15:0.
//
- // To find all N_OSO entries that are part of the DWARF + debug map
- // we find only object file symbols with the flags value as follows:
- // bits 23:16 == 0x66 (N_OSO)
- // bits 15: 0 == 0x0001 (specifies this is a debug map object file)
+ // To find all N_OSO entries that are part of the DWARF + debug map we find
+ // only object file symbols with the flags value as follows: bits 23:16 ==
+ // 0x66 (N_OSO) bits 15: 0 == 0x0001 (specifies this is a debug map object
+ // file)
const uint32_t k_oso_symbol_flags_value = 0x660001u;
const uint32_t oso_index_count =
@@ -353,7 +351,7 @@ void SymbolFileDWARFDebugMap::InitOSO() {
so_symbol->GetType() == eSymbolTypeSourceFile &&
oso_symbol->GetType() == eSymbolTypeObjectFile) {
m_compile_unit_infos[i].so_file.SetFile(
- so_symbol->GetName().AsCString(), false);
+ so_symbol->GetName().AsCString(), false, FileSpec::Style::native);
m_compile_unit_infos[i].oso_path = oso_symbol->GetName();
m_compile_unit_infos[i].oso_mod_time =
llvm::sys::toTimePoint(oso_symbol->GetIntegerValue(0));
@@ -413,13 +411,15 @@ Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) {
Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
CompileUnitInfo *comp_unit_info) {
if (!comp_unit_info->oso_sp) {
- auto pos = m_oso_map.find(comp_unit_info->oso_path);
+ auto pos = m_oso_map.find(
+ {comp_unit_info->oso_path, comp_unit_info->oso_mod_time});
if (pos != m_oso_map.end()) {
comp_unit_info->oso_sp = pos->second;
} else {
ObjectFile *obj_file = GetObjectFile();
comp_unit_info->oso_sp.reset(new OSOInfo());
- m_oso_map[comp_unit_info->oso_path] = comp_unit_info->oso_sp;
+ m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] =
+ comp_unit_info->oso_sp;
const char *oso_path = comp_unit_info->oso_path.GetCString();
FileSpec oso_file(oso_path, false);
ConstString oso_object;
@@ -443,16 +443,15 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
return NULL;
}
}
- // Always create a new module for .o files. Why? Because we
- // use the debug map, to add new sections to each .o file and
- // even though a .o file might not have changed, the sections
- // that get added to the .o file can change.
+ // Always create a new module for .o files. Why? Because we use the debug
+ // map, to add new sections to each .o file and even though a .o file
+ // might not have changed, the sections that get added to the .o file can
+ // change.
ArchSpec oso_arch;
// Only adopt the architecture from the module (not the vendor or OS)
- // since .o files for "i386-apple-ios" will historically show up as
- // "i386-apple-macosx"
- // due to the lack of a LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
- // load command...
+ // since .o files for "i386-apple-ios" will historically show up as "i386
+ // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or
+ // LC_VERSION_MIN_IPHONEOS load command...
oso_arch.SetTriple(m_obj_file->GetModule()
->GetArchitecture()
.GetTriple()
@@ -546,8 +545,8 @@ SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo(
uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() {
// In order to get the abilities of this plug-in, we look at the list of
// N_OSO entries (object files) from the symbol table and make sure that
- // these files exist and also contain valid DWARF. If we get any of that
- // then we return the abilities of the first N_OSO's DWARF.
+ // these files exist and also contain valid DWARF. If we get any of that then
+ // we return the abilities of the first N_OSO's DWARF.
const uint32_t oso_index_count = GetNumCompileUnits();
if (oso_index_count > 0) {
@@ -576,9 +575,8 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
if (oso_module) {
FileSpec so_file_spec;
if (GetFileSpecForSO(cu_idx, so_file_spec)) {
- // User zero as the ID to match the compile unit at offset
- // zero in each .o file since each .o file can only have
- // one compile unit for now.
+ // User zero as the ID to match the compile unit at offset zero in each
+ // .o file since each .o file can only have one compile unit for now.
lldb::user_id_t cu_id = 0;
m_compile_unit_infos[cu_idx].compile_unit_sp.reset(
new CompileUnit(m_obj_file->GetModule(), NULL, so_file_spec, cu_id,
@@ -767,8 +765,8 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t i = 0; i < cu_count; ++i) {
- // If we are checking for inlines, then we need to look through all
- // compile units no matter if "file_spec" matches.
+ // If we are checking for inlines, then we need to look through all compile
+ // units no matter if "file_spec" matches.
bool resolve = check_inlines;
if (!resolve) {
@@ -805,8 +803,8 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
if (comp_unit_info) {
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
if (oso_dwarf) {
- if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, true,
- max_matches, variables))
+ if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
+ variables))
if (variables.GetSize() > max_matches)
break;
}
@@ -817,21 +815,16 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches, VariableList &variables) {
+ uint32_t max_matches, VariableList &variables) {
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
uint32_t total_matches = 0;
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
const uint32_t oso_matches = oso_dwarf->FindGlobalVariables(
- name, parent_decl_ctx, true, max_matches, variables);
+ name, parent_decl_ctx, max_matches, variables);
if (oso_matches > 0) {
total_matches += oso_matches;
@@ -843,8 +836,8 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables(
if (max_matches >= total_matches)
return true;
- // Update the max matches for any subsequent calls to find globals
- // in any other object files with DWARF
+ // Update the max matches for any subsequent calls to find globals in any
+ // other object files with DWARF
max_matches -= oso_matches;
}
@@ -857,20 +850,15 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables(
uint32_t
SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
VariableList &variables) {
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
uint32_t total_matches = 0;
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
const uint32_t oso_matches =
- oso_dwarf->FindGlobalVariables(regex, true, max_matches, variables);
+ oso_dwarf->FindGlobalVariables(regex, max_matches, variables);
if (oso_matches > 0) {
total_matches += oso_matches;
@@ -882,8 +870,8 @@ SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression &regex,
if (max_matches >= total_matches)
return true;
- // Update the max matches for any subsequent calls to find globals
- // in any other object files with DWARF
+ // Update the max matches for any subsequent calls to find globals in any
+ // other object files with DWARF
max_matches -= oso_matches;
}
@@ -965,12 +953,12 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
SymbolContextList &sc_list,
uint32_t start_idx) {
- // We found functions in .o files. Not all functions in the .o files
- // will have made it into the final output file. The ones that did
- // make it into the final output file will have a section whose module
- // matches the module from the ObjectFile for this SymbolFile. When
- // the modules don't match, then we have something that was in a
- // .o file, but doesn't map to anything in the final executable.
+ // We found functions in .o files. Not all functions in the .o files will
+ // have made it into the final output file. The ones that did make it into
+ // the final output file will have a section whose module matches the module
+ // from the ObjectFile for this SymbolFile. When the modules don't match,
+ // then we have something that was in a .o file, but doesn't map to anything
+ // in the final executable.
uint32_t i = start_idx;
while (i < sc_list.GetSize()) {
SymbolContext sc;
@@ -1101,12 +1089,12 @@ bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
const DWARFDIE &die, const ConstString &type_name,
bool must_be_implementation) {
- // If we have a debug map, we will have an Objective C symbol whose name is
+ // If we have a debug map, we will have an Objective-C symbol whose name is
// the type name and whose type is eSymbolTypeObjCClass. If we can find that
// symbol and find its containing parent, we can locate the .o file that will
// contain the implementation definition since it will be scoped inside the
- // N_SO
- // and we can then locate the SymbolFileDWARF that corresponds to that N_SO.
+ // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
+ // N_SO.
SymbolFileDWARF *oso_dwarf = NULL;
TypeSP type_sp;
ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile();
@@ -1118,8 +1106,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
Symtab::eVisibilityAny);
if (objc_class_symbol) {
// Get the N_SO symbol that contains the objective C class symbol as
- // this
- // should be the .o file that contains the real definition...
+ // this should be the .o file that contains the real definition...
const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol);
if (source_file_symbol &&
@@ -1147,10 +1134,8 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
}
// Only search all .o files for the definition if we don't need the
- // implementation
- // because otherwise, with a valid debug map we should have the ObjC class
- // symbol and
- // the code above should have found it.
+ // implementation because otherwise, with a valid debug map we should have
+ // the ObjC class symbol and the code above should have found it.
if (must_be_implementation == false) {
TypeSP type_sp;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index dcca4268b6eb..550f74a203ea 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -95,10 +95,10 @@ public:
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t
FindFunctions(const lldb_private::ConstString &name,
@@ -136,7 +136,7 @@ protected:
friend class DebugMapModule;
friend struct DIERef;
friend class DWARFASTParserClang;
- friend class DWARFCompileUnit;
+ friend class DWARFUnit;
friend class SymbolFileDWARF;
struct OSOInfo {
lldb::ModuleSP module_sp;
@@ -300,7 +300,9 @@ protected:
std::vector<CompileUnitInfo> m_compile_unit_infos;
std::vector<uint32_t> m_func_indexes; // Sorted by address
std::vector<uint32_t> m_glob_indexes;
- std::map<lldb_private::ConstString, OSOInfoSP> m_oso_map;
+ std::map<std::pair<lldb_private::ConstString, llvm::sys::TimePoint<>>,
+ OSOInfoSP>
+ m_oso_map;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
DebugMap m_debug_map;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 17c188a41a77..15fe362fa117 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -14,14 +14,14 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
using namespace lldb;
using namespace lldb_private;
SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile,
- DWARFCompileUnit *dwarf_cu)
+ DWARFUnit *dwarf_cu)
: SymbolFileDWARF(objfile.get()), m_obj_file_sp(objfile),
m_base_dwarf_cu(dwarf_cu) {
SetID(((lldb::user_id_t)dwarf_cu->GetOffset()) << 32);
@@ -52,7 +52,7 @@ void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type,
}
lldb::CompUnitSP
-SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+SymbolFileDWARFDwo::ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) {
assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit "
"called with incompatible compile "
@@ -60,7 +60,7 @@ SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX);
}
-DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() {
+DWARFUnit *SymbolFileDWARFDwo::GetCompileUnit() {
// A clang module is found via a skeleton CU, but is not a proper DWO.
// Clang modules have a .debug_info section instead of the *_dwo variant.
if (auto *section_list = m_obj_file->GetSectionList(false))
@@ -76,7 +76,7 @@ DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() {
return nullptr;
}
-DWARFCompileUnit *
+DWARFUnit *
SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) {
return GetCompileUnit();
}
@@ -122,7 +122,7 @@ lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE(
die, type_name, must_be_implementation);
}
-DWARFCompileUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() {
+DWARFUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() {
return m_base_dwarf_cu;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index b67967aafab2..483a19512a36 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -18,16 +18,16 @@
class SymbolFileDWARFDwo : public SymbolFileDWARF {
public:
- SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit *dwarf_cu);
+ SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu);
~SymbolFileDWARFDwo() override = default;
- lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+ lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) override;
- DWARFCompileUnit *GetCompileUnit();
+ DWARFUnit *GetCompileUnit();
- DWARFCompileUnit *
+ DWARFUnit *
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
lldb_private::DWARFExpression::LocationListFormat
@@ -43,12 +43,12 @@ public:
GetDIE(const DIERef &die_ref) override;
std::unique_ptr<SymbolFileDWARFDwo>
- GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu,
+ GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
const DWARFDebugInfoEntry &cu_die) override {
return nullptr;
}
- DWARFCompileUnit *GetBaseCompileUnit() override;
+ DWARFUnit *GetBaseCompileUnit() override;
protected:
void LoadSectionData(lldb::SectionType sect_type,
@@ -74,7 +74,7 @@ protected:
SymbolFileDWARF *GetBaseSymbolFile();
lldb::ObjectFileSP m_obj_file_sp;
- DWARFCompileUnit *m_base_dwarf_cu;
+ DWARFUnit *m_base_dwarf_cu;
};
#endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
index f6de1818eae0..403c10fe65ea 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
@@ -14,7 +14,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
using namespace lldb;
@@ -22,7 +22,7 @@ using namespace lldb_private;
SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
ObjectFileSP objfile,
- DWARFCompileUnit *dwarf_cu,
+ DWARFUnit *dwarf_cu,
uint64_t dwo_id)
: SymbolFileDWARFDwo(objfile, dwarf_cu), m_dwp_symfile(dwp_symfile),
m_dwo_id(dwo_id) {}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
index 00ad7aafd96b..b1b505b5899f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
@@ -20,7 +20,7 @@
class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo {
public:
SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
- lldb::ObjectFileSP objfile, DWARFCompileUnit *dwarf_cu,
+ lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu,
uint64_t dwo_id);
protected:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
index 1dc1dab34a5c..ae10e7179e33 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
@@ -85,7 +85,7 @@ SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp,
{}
std::unique_ptr<SymbolFileDWARFDwo>
-SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu,
+SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFUnit *dwarf_cu,
uint64_t dwo_id) {
return std::unique_ptr<SymbolFileDWARFDwo>(
new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id));
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
index a7372b9358b1..470d1c5b1c48 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
@@ -29,7 +29,7 @@ public:
Create(lldb::ModuleSP module_sp, const lldb_private::FileSpec &file_spec);
std::unique_ptr<SymbolFileDWARFDwo>
- GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu, uint64_t dwo_id);
+ GetSymbolFileForDwoId(DWARFUnit *dwarf_cu, uint64_t dwo_id);
bool LoadSectionData(uint64_t dwo_id, lldb::SectionType sect_type,
lldb_private::DWARFDataExtractor &data);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 8697e08dbf86..8273d975e57d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -27,8 +27,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
udt.m_byte_size == byte_size) {
// Make sure the file and line match
if (udt.m_declaration == decl) {
- // The type has the same name, and was defined on the same
- // file and line. Now verify all of the parent DIEs match.
+ // The type has the same name, and was defined on the same file and
+ // line. Now verify all of the parent DIEs match.
DWARFDIE parent_arg_die = die.GetParent();
DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
@@ -57,6 +57,7 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
} break;
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
done = true;
break;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 7802d6f0d859..8bea994aae5d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -19,19 +19,22 @@
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeSystem.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
using namespace lldb;
using namespace lldb_private;
-using namespace llvm;
using namespace llvm::pdb;
namespace {
@@ -46,7 +49,7 @@ int TranslateUdtKind(PDB_UdtType pdb_kind) {
case PDB_UdtType::Interface:
return clang::TTK_Interface;
}
- return clang::TTK_Class;
+ return -1;
}
lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
@@ -58,16 +61,146 @@ lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
case PDB_BuiltinType::Char:
return lldb::eEncodingSint;
case PDB_BuiltinType::Bool:
+ case PDB_BuiltinType::Char16:
+ case PDB_BuiltinType::Char32:
case PDB_BuiltinType::UInt:
case PDB_BuiltinType::ULong:
case PDB_BuiltinType::HResult:
+ case PDB_BuiltinType::WCharT:
return lldb::eEncodingUint;
default:
return lldb::eEncodingInvalid;
}
}
+
+lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) {
+ switch (type) {
+ case PDB_VariantType::Int8:
+ case PDB_VariantType::Int16:
+ case PDB_VariantType::Int32:
+ case PDB_VariantType::Int64:
+ return lldb::eEncodingSint;
+
+ case PDB_VariantType::UInt8:
+ case PDB_VariantType::UInt16:
+ case PDB_VariantType::UInt32:
+ case PDB_VariantType::UInt64:
+ return lldb::eEncodingUint;
+
+ default:
+ break;
+ }
+
+ return lldb::eEncodingSint;
}
+CompilerType
+GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
+ const PDBSymbolTypeBuiltin &pdb_type,
+ Encoding encoding, uint32_t width) {
+ auto *ast = clang_ast.getASTContext();
+ if (!ast)
+ return CompilerType();
+
+ switch (pdb_type.getBuiltinType()) {
+ default:
+ break;
+ case PDB_BuiltinType::None:
+ return CompilerType();
+ case PDB_BuiltinType::Void:
+ return clang_ast.GetBasicType(eBasicTypeVoid);
+ case PDB_BuiltinType::Bool:
+ return clang_ast.GetBasicType(eBasicTypeBool);
+ case PDB_BuiltinType::Long:
+ if (width == ast->getTypeSize(ast->LongTy))
+ return CompilerType(ast, ast->LongTy);
+ if (width == ast->getTypeSize(ast->LongLongTy))
+ return CompilerType(ast, ast->LongLongTy);
+ break;
+ case PDB_BuiltinType::ULong:
+ if (width == ast->getTypeSize(ast->UnsignedLongTy))
+ return CompilerType(ast, ast->UnsignedLongTy);
+ if (width == ast->getTypeSize(ast->UnsignedLongLongTy))
+ return CompilerType(ast, ast->UnsignedLongLongTy);
+ break;
+ case PDB_BuiltinType::WCharT:
+ if (width == ast->getTypeSize(ast->WCharTy))
+ return CompilerType(ast, ast->WCharTy);
+ break;
+ case PDB_BuiltinType::Char16:
+ return CompilerType(ast, ast->Char16Ty);
+ case PDB_BuiltinType::Char32:
+ return CompilerType(ast, ast->Char32Ty);
+ case PDB_BuiltinType::Float:
+ // Note: types `long double` and `double` have same bit size in MSVC and
+ // there is no information in the PDB to distinguish them. So when falling
+ // back to default search, the compiler type of `long double` will be
+ // represented by the one generated for `double`.
+ break;
+ }
+ // If there is no match on PDB_BuiltinType, fall back to default search by
+ // encoding and width only
+ return clang_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
+}
+
+ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type,
+ CompilerType &compiler_type) {
+ PDB_BuiltinType kind = pdb_type.getBuiltinType();
+ switch (kind) {
+ default:
+ break;
+ case PDB_BuiltinType::Currency:
+ return ConstString("CURRENCY");
+ case PDB_BuiltinType::Date:
+ return ConstString("DATE");
+ case PDB_BuiltinType::Variant:
+ return ConstString("VARIANT");
+ case PDB_BuiltinType::Complex:
+ return ConstString("complex");
+ case PDB_BuiltinType::Bitfield:
+ return ConstString("bitfield");
+ case PDB_BuiltinType::BSTR:
+ return ConstString("BSTR");
+ case PDB_BuiltinType::HResult:
+ return ConstString("HRESULT");
+ case PDB_BuiltinType::BCD:
+ return ConstString("BCD");
+ case PDB_BuiltinType::Char16:
+ return ConstString("char16_t");
+ case PDB_BuiltinType::Char32:
+ return ConstString("char32_t");
+ case PDB_BuiltinType::None:
+ return ConstString("...");
+ }
+ return compiler_type.GetTypeName();
+}
+
+bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) {
+ auto &raw_sym = symbol.getRawSymbol();
+ auto first_line_up = raw_sym.getSrcLineOnTypeDefn();
+
+ if (!first_line_up) {
+ auto lines_up = symbol.getSession().findLineNumbersByAddress(
+ raw_sym.getVirtualAddress(), raw_sym.getLength());
+ if (!lines_up)
+ return false;
+ first_line_up = lines_up->getNext();
+ if (!first_line_up)
+ return false;
+ }
+ uint32_t src_file_id = first_line_up->getSourceFileId();
+ auto src_file_up = symbol.getSession().getSourceFileById(src_file_id);
+ if (!src_file_up)
+ return false;
+
+ FileSpec spec(src_file_up->getFileName(), /*resolve_path*/ false);
+ decl.SetFile(spec);
+ decl.SetColumn(first_line_up->getColumnNumber());
+ decl.SetLine(first_line_up->getLineNumber());
+ return true;
+}
+} // namespace
+
PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {}
PDBASTParser::~PDBASTParser() {}
@@ -76,21 +209,27 @@ PDBASTParser::~PDBASTParser() {}
lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
// PDB doesn't maintain enough information to robustly rebuild the entire
- // tree, and this is most problematic when it comes to figure out the
- // right DeclContext to put a type in. So for now, everything goes in
- // the translation unit decl as a fully qualified type.
+ // tree, and this is most problematic when it comes to figure out the right
+ // DeclContext to put a type in. So for now, everything goes in the
+ // translation unit decl as a fully qualified type.
clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
Declaration decl;
- if (auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type)) {
+ switch (type.getSymTag()) {
+ case PDB_SymType::UDT: {
+ auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type);
+ assert(udt);
AccessType access = lldb::eAccessPublic;
PDB_UdtType udt_kind = udt->getUdtKind();
+ auto tag_type_kind = TranslateUdtKind(udt_kind);
+ if (tag_type_kind == -1)
+ return nullptr;
if (udt_kind == PDB_UdtType::Class)
access = lldb::eAccessPrivate;
CompilerType clang_type = m_ast.CreateRecordType(
- tu_decl_ctx, access, udt->getName().c_str(), TranslateUdtKind(udt_kind),
+ tu_decl_ctx, access, udt->getName().c_str(), tag_type_kind,
lldb::eLanguageTypeC_plus_plus, nullptr);
m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
@@ -100,51 +239,107 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
ConstString(udt->getName()), udt->getLength(), nullptr,
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type,
lldb_private::Type::eResolveStateForward);
- } else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type)) {
- std::string name = enum_type->getName();
+ } break;
+ case PDB_SymType::Enum: {
+ auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
+ assert(enum_type);
+ auto underlying_type_up = enum_type->getUnderlyingType();
+ if (!underlying_type_up)
+ return nullptr;
lldb::Encoding encoding =
- TranslateBuiltinEncoding(enum_type->getBuiltinType());
+ TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
+ // FIXME: Type of underlying builtin is always `Int`. We correct it with
+ // the very first enumerator's encoding if any.
+ auto first_child = enum_type->findOneChild<PDBSymbolData>();
+ if (first_child) {
+ encoding = TranslateEnumEncoding(first_child->getValue().Type);
+ }
+ std::string name = enum_type->getName();
uint64_t bytes = enum_type->getLength();
- CompilerType builtin_type =
- m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8);
+ CompilerType builtin_type;
+ if (bytes > 0)
+ builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
+ m_ast, *underlying_type_up, encoding, bytes * 8);
+ else
+ builtin_type = m_ast.GetBasicType(eBasicTypeInt);
+ // FIXME: PDB does not have information about scoped enumeration (Enum
+ // Class). Set it false for now.
+ bool isScoped = false;
CompilerType ast_enum = m_ast.CreateEnumerationType(
- name.c_str(), tu_decl_ctx, decl, builtin_type, false);
+ name.c_str(), tu_decl_ctx, decl, builtin_type, isScoped);
auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
- while (auto enum_value = enum_values->getNext()) {
- if (enum_value->getDataKind() != PDB_DataKind::Constant)
- continue;
- AddEnumValue(ast_enum, *enum_value);
+ if (enum_values) {
+ while (auto enum_value = enum_values->getNext()) {
+ if (enum_value->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ AddEnumValue(ast_enum, *enum_value);
+ }
}
+ if (ClangASTContext::StartTagDeclarationDefinition(ast_enum))
+ ClangASTContext::CompleteTagDeclarationDefinition(ast_enum);
+ GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
ast_enum, lldb_private::Type::eResolveStateFull);
- } else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type)) {
+ } break;
+ case PDB_SymType::Typedef: {
+ auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
+ assert(type_def);
lldb_private::Type *target_type =
m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
if (!target_type)
return nullptr;
std::string name = type_def->getName();
uint64_t bytes = type_def->getLength();
- if (!target_type)
- return nullptr;
CompilerType target_ast_type = target_type->GetFullCompilerType();
CompilerDeclContext target_decl_ctx =
m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
CompilerType ast_typedef =
m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
+ if (!ast_typedef)
+ return nullptr;
+
return std::make_shared<lldb_private::Type>(
type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
bytes, nullptr, target_type->GetID(),
lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
lldb_private::Type::eResolveStateFull);
- } else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
+ } break;
+ case PDB_SymType::Function:
+ case PDB_SymType::FunctionSig: {
+ std::string name;
+ PDBSymbolTypeFunctionSig *func_sig = nullptr;
+ if (auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(&type)) {
+ if (pdb_func->isCompilerGenerated())
+ return nullptr;
+
+ auto sig = pdb_func->getSignature();
+ if (!sig)
+ return nullptr;
+ func_sig = sig.release();
+ // Function type is named.
+ name = pdb_func->getName();
+ } else if (auto pdb_func_sig =
+ llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
+ func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig);
+ } else
+ llvm_unreachable("Unexpected PDB symbol!");
+
auto arg_enum = func_sig->getArguments();
uint32_t num_args = arg_enum->getChildCount();
- std::vector<CompilerType> arg_list(num_args);
- while (auto arg = arg_enum->getNext()) {
+ std::vector<CompilerType> arg_list;
+
+ bool is_variadic = func_sig->isCVarArgs();
+ // Drop last variadic argument.
+ if (is_variadic)
+ --num_args;
+ for (uint32_t arg_idx = 0; arg_idx < num_args; arg_idx++) {
+ auto arg = arg_enum->getChildAtIndex(arg_idx);
+ if (!arg)
+ break;
lldb_private::Type *arg_type =
m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
// If there's some error looking up one of the dependent types of this
@@ -154,6 +349,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
CompilerType arg_ast_type = arg_type->GetFullCompilerType();
arg_list.push_back(arg_ast_type);
}
+ lldbassert(arg_list.size() <= num_args);
+
auto pdb_return_type = func_sig->getReturnType();
lldb_private::Type *return_type =
m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
@@ -167,29 +364,109 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type_quals |= clang::Qualifiers::Const;
if (func_sig->isVolatileType())
type_quals |= clang::Qualifiers::Volatile;
- CompilerType func_sig_ast_type = m_ast.CreateFunctionType(
- return_ast_type, &arg_list[0], num_args, false, type_quals);
+ CompilerType func_sig_ast_type =
+ m_ast.CreateFunctionType(return_ast_type, arg_list.data(),
+ arg_list.size(), is_variadic, type_quals);
+ GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
- func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0,
+ type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), 0,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
func_sig_ast_type, lldb_private::Type::eResolveStateFull);
- } else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type)) {
+ } break;
+ case PDB_SymType::ArrayType: {
+ auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
+ assert(array_type);
uint32_t num_elements = array_type->getCount();
- uint32_t element_uid = array_type->getElementType()->getSymIndexId();
+ uint32_t element_uid = array_type->getElementTypeId();
uint32_t bytes = array_type->getLength();
+ // If array rank > 0, PDB gives the element type at N=0. So element type
+ // will parsed in the order N=0, N=1,..., N=rank sequentially.
lldb_private::Type *element_type =
m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
if (!element_type)
return nullptr;
- CompilerType element_ast_type = element_type->GetFullCompilerType();
- CompilerType array_ast_type =
- m_ast.CreateArrayType(element_ast_type, num_elements, false);
- return std::make_shared<lldb_private::Type>(
+
+ CompilerType element_ast_type = element_type->GetForwardCompilerType();
+ // If element type is UDT, it needs to be complete.
+ if (ClangASTContext::IsCXXClassType(element_ast_type) &&
+ element_ast_type.GetCompleteType() == false) {
+ if (ClangASTContext::StartTagDeclarationDefinition(element_ast_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(element_ast_type);
+ } else {
+ // We are not able to start defintion.
+ return nullptr;
+ }
+ }
+ CompilerType array_ast_type = m_ast.CreateArrayType(
+ element_ast_type, num_elements, /*is_gnu_vector*/ false);
+ TypeSP type_sp = std::make_shared<lldb_private::Type>(
array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
decl, array_ast_type, lldb_private::Type::eResolveStateFull);
+ type_sp->SetEncodingType(element_type);
+ return type_sp;
+ } break;
+ case PDB_SymType::BuiltinType: {
+ auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(&type);
+ assert(builtin_type);
+ PDB_BuiltinType builtin_kind = builtin_type->getBuiltinType();
+ if (builtin_kind == PDB_BuiltinType::None)
+ return nullptr;
+
+ uint64_t bytes = builtin_type->getLength();
+ Encoding encoding = TranslateBuiltinEncoding(builtin_kind);
+ CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize(
+ m_ast, *builtin_type, encoding, bytes * 8);
+
+ if (builtin_type->isConstType())
+ builtin_ast_type = builtin_ast_type.AddConstModifier();
+
+ if (builtin_type->isVolatileType())
+ builtin_ast_type = builtin_ast_type.AddVolatileModifier();
+
+ auto type_name = GetPDBBuiltinTypeName(*builtin_type, builtin_ast_type);
+
+ return std::make_shared<lldb_private::Type>(
+ builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name, bytes,
+ nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
+ builtin_ast_type, lldb_private::Type::eResolveStateFull);
+ } break;
+ case PDB_SymType::PointerType: {
+ auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
+ assert(pointer_type);
+ Type *pointee_type = m_ast.GetSymbolFile()->ResolveTypeUID(
+ pointer_type->getPointeeType()->getSymIndexId());
+ if (!pointee_type)
+ return nullptr;
+
+ CompilerType pointer_ast_type;
+ pointer_ast_type = pointee_type->GetFullCompilerType();
+ if (pointer_type->isReference())
+ pointer_ast_type = pointer_ast_type.GetLValueReferenceType();
+ else if (pointer_type->isRValueReference())
+ pointer_ast_type = pointer_ast_type.GetRValueReferenceType();
+ else
+ pointer_ast_type = pointer_ast_type.GetPointerType();
+
+ if (pointer_type->isConstType())
+ pointer_ast_type = pointer_ast_type.AddConstModifier();
+
+ if (pointer_type->isVolatileType())
+ pointer_ast_type = pointer_ast_type.AddVolatileModifier();
+
+ if (pointer_type->isRestrictedType())
+ pointer_ast_type = pointer_ast_type.AddRestrictModifier();
+
+ return std::make_shared<lldb_private::Type>(
+ pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
+ pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
+ lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
+ lldb_private::Type::eResolveStateFull);
+ } break;
+ default:
+ break;
}
return nullptr;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h
index e9ff02c0a77e..d1ac138b8115 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -19,20 +19,20 @@ class CharUnits;
class CXXRecordDecl;
class FieldDecl;
class RecordDecl;
-}
+} // namespace clang
namespace lldb_private {
class ClangASTContext;
class CompilerType;
-}
+} // namespace lldb_private
namespace llvm {
namespace pdb {
class PDBSymbol;
class PDBSymbolData;
class PDBSymbolTypeBuiltin;
-}
-}
+} // namespace pdb
+} // namespace llvm
class PDBASTParser {
public:
@@ -49,4 +49,4 @@ private:
lldb_private::ClangASTImporter m_ast_importer;
};
-#endif // SymbolFileDWARF_DWARFASTParserClang_h_
+#endif // LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
new file mode 100644
index 000000000000..69ef70cc508c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
@@ -0,0 +1,585 @@
+//===-- PDBLocationToDWARFExpression.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PDBLocationToDWARFExpression.h"
+
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamBuffer.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Utility/DataBufferHeap.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm::pdb;
+
+namespace {
+const uint32_t g_code_view_to_lldb_registers_x86[] = {
+ LLDB_INVALID_REGNUM, // CVRegNONE
+ lldb_al_i386, // CVRegAL
+ lldb_cl_i386, // CVRegCL
+ lldb_dl_i386, // CVRegDL
+ lldb_bl_i386, // CVRegBL
+ lldb_ah_i386, // CVRegAH
+ lldb_ch_i386, // CVRegCH
+ lldb_dh_i386, // CVRegDH
+ lldb_bh_i386, // CVRegBH
+ lldb_ax_i386, // CVRegAX
+ lldb_cx_i386, // CVRegCX
+ lldb_dx_i386, // CVRegDX
+ lldb_bx_i386, // CVRegBX
+ lldb_sp_i386, // CVRegSP
+ lldb_bp_i386, // CVRegBP
+ lldb_si_i386, // CVRegSI
+ lldb_di_i386, // CVRegDI
+ lldb_eax_i386, // CVRegEAX
+ lldb_ecx_i386, // CVRegECX
+ lldb_edx_i386, // CVRegEDX
+ lldb_ebx_i386, // CVRegEBX
+ lldb_esp_i386, // CVRegESP
+ lldb_ebp_i386, // CVRegEBP
+ lldb_esi_i386, // CVRegESI
+ lldb_edi_i386, // CVRegEDI
+ lldb_es_i386, // CVRegES
+ lldb_cs_i386, // CVRegCS
+ lldb_ss_i386, // CVRegSS
+ lldb_ds_i386, // CVRegDS
+ lldb_fs_i386, // CVRegFS
+ lldb_gs_i386, // CVRegGS
+ LLDB_INVALID_REGNUM, // CVRegIP
+ LLDB_INVALID_REGNUM, // CVRegFLAGS
+ lldb_eip_i386, // CVRegEIP
+ lldb_eflags_i386, // CVRegEFLAGS
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegTEMP
+ LLDB_INVALID_REGNUM, // CVRegTEMPH
+ LLDB_INVALID_REGNUM, // CVRegQUOTE
+ LLDB_INVALID_REGNUM, // CVRegPCDR3
+ LLDB_INVALID_REGNUM, // CVRegPCDR4
+ LLDB_INVALID_REGNUM, // CVRegPCDR5
+ LLDB_INVALID_REGNUM, // CVRegPCDR6
+ LLDB_INVALID_REGNUM, // CVRegPCDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegCR0
+ LLDB_INVALID_REGNUM, // CVRegCR1
+ LLDB_INVALID_REGNUM, // CVRegCR2
+ LLDB_INVALID_REGNUM, // CVRegCR3
+ LLDB_INVALID_REGNUM, // CVRegCR4
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_dr0_i386, // CVRegDR0
+ lldb_dr1_i386, // CVRegDR1
+ lldb_dr2_i386, // CVRegDR2
+ lldb_dr3_i386, // CVRegDR3
+ lldb_dr4_i386, // CVRegDR4
+ lldb_dr5_i386, // CVRegDR5
+ lldb_dr6_i386, // CVRegDR6
+ lldb_dr7_i386, // CVRegDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegGDTR
+ LLDB_INVALID_REGNUM, // CVRegGDTL
+ LLDB_INVALID_REGNUM, // CVRegIDTR
+ LLDB_INVALID_REGNUM, // CVRegIDTL
+ LLDB_INVALID_REGNUM, // CVRegLDTR
+ LLDB_INVALID_REGNUM, // CVRegTR
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO1
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO2
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO3
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO4
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO5
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO6
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO7
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO8
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_i386, // CVRegST0
+ lldb_st1_i386, // CVRegST1
+ lldb_st2_i386, // CVRegST2
+ lldb_st3_i386, // CVRegST3
+ lldb_st4_i386, // CVRegST4
+ lldb_st5_i386, // CVRegST5
+ lldb_st6_i386, // CVRegST6
+ lldb_st7_i386, // CVRegST7
+ LLDB_INVALID_REGNUM, // CVRegCTRL
+ LLDB_INVALID_REGNUM, // CVRegSTAT
+ LLDB_INVALID_REGNUM, // CVRegTAG
+ LLDB_INVALID_REGNUM, // CVRegFPIP
+ LLDB_INVALID_REGNUM, // CVRegFPCS
+ LLDB_INVALID_REGNUM, // CVRegFPDO
+ LLDB_INVALID_REGNUM, // CVRegFPDS
+ LLDB_INVALID_REGNUM, // CVRegISEM
+ LLDB_INVALID_REGNUM, // CVRegFPEIP
+ LLDB_INVALID_REGNUM, // CVRegFPEDO
+ lldb_mm0_i386, // CVRegMM0
+ lldb_mm1_i386, // CVRegMM1
+ lldb_mm2_i386, // CVRegMM2
+ lldb_mm3_i386, // CVRegMM3
+ lldb_mm4_i386, // CVRegMM4
+ lldb_mm5_i386, // CVRegMM5
+ lldb_mm6_i386, // CVRegMM6
+ lldb_mm7_i386, // CVRegMM7
+ lldb_xmm0_i386, // CVRegXMM0
+ lldb_xmm1_i386, // CVRegXMM1
+ lldb_xmm2_i386, // CVRegXMM2
+ lldb_xmm3_i386, // CVRegXMM3
+ lldb_xmm4_i386, // CVRegXMM4
+ lldb_xmm5_i386, // CVRegXMM5
+ lldb_xmm6_i386, // CVRegXMM6
+ lldb_xmm7_i386 // CVRegXMM7
+};
+
+const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
+ LLDB_INVALID_REGNUM, // CVRegNONE
+ lldb_al_x86_64, // CVRegAL
+ lldb_cl_x86_64, // CVRegCL
+ lldb_dl_x86_64, // CVRegDL
+ lldb_bl_x86_64, // CVRegBL
+ lldb_ah_x86_64, // CVRegAH
+ lldb_ch_x86_64, // CVRegCH
+ lldb_dh_x86_64, // CVRegDH
+ lldb_bh_x86_64, // CVRegBH
+ lldb_ax_x86_64, // CVRegAX
+ lldb_cx_x86_64, // CVRegCX
+ lldb_dx_x86_64, // CVRegDX
+ lldb_bx_x86_64, // CVRegBX
+ lldb_sp_x86_64, // CVRegSP
+ lldb_bp_x86_64, // CVRegBP
+ lldb_si_x86_64, // CVRegSI
+ lldb_di_x86_64, // CVRegDI
+ lldb_eax_x86_64, // CVRegEAX
+ lldb_ecx_x86_64, // CVRegECX
+ lldb_edx_x86_64, // CVRegEDX
+ lldb_ebx_x86_64, // CVRegEBX
+ lldb_esp_x86_64, // CVRegESP
+ lldb_ebp_x86_64, // CVRegEBP
+ lldb_esi_x86_64, // CVRegESI
+ lldb_edi_x86_64, // CVRegEDI
+ lldb_es_x86_64, // CVRegES
+ lldb_cs_x86_64, // CVRegCS
+ lldb_ss_x86_64, // CVRegSS
+ lldb_ds_x86_64, // CVRegDS
+ lldb_fs_x86_64, // CVRegFS
+ lldb_gs_x86_64, // CVRegGS
+ LLDB_INVALID_REGNUM, // CVRegIP
+ LLDB_INVALID_REGNUM, // CVRegFLAGS
+ LLDB_INVALID_REGNUM, // CVRegEIP
+ LLDB_INVALID_REGNUM, // CVRegEFLAGS
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegTEMP
+ LLDB_INVALID_REGNUM, // CVRegTEMPH
+ LLDB_INVALID_REGNUM, // CVRegQUOTE
+ LLDB_INVALID_REGNUM, // CVRegPCDR3
+ LLDB_INVALID_REGNUM, // CVRegPCDR4
+ LLDB_INVALID_REGNUM, // CVRegPCDR5
+ LLDB_INVALID_REGNUM, // CVRegPCDR6
+ LLDB_INVALID_REGNUM, // CVRegPCDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegCR0
+ LLDB_INVALID_REGNUM, // CVRegCR1
+ LLDB_INVALID_REGNUM, // CVRegCR2
+ LLDB_INVALID_REGNUM, // CVRegCR3
+ LLDB_INVALID_REGNUM, // CVRegCR4
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_dr0_x86_64, // CVRegDR0
+ lldb_dr1_x86_64, // CVRegDR1
+ lldb_dr2_x86_64, // CVRegDR2
+ lldb_dr3_x86_64, // CVRegDR3
+ lldb_dr4_x86_64, // CVRegDR4
+ lldb_dr5_x86_64, // CVRegDR5
+ lldb_dr6_x86_64, // CVRegDR6
+ lldb_dr7_x86_64, // CVRegDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegGDTR
+ LLDB_INVALID_REGNUM, // CVRegGDTL
+ LLDB_INVALID_REGNUM, // CVRegIDTR
+ LLDB_INVALID_REGNUM, // CVRegIDTL
+ LLDB_INVALID_REGNUM, // CVRegLDTR
+ LLDB_INVALID_REGNUM, // CVRegTR
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO1
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO2
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO3
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO4
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO5
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO6
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO7
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO8
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_x86_64, // CVRegST0
+ lldb_st1_x86_64, // CVRegST1
+ lldb_st2_x86_64, // CVRegST2
+ lldb_st3_x86_64, // CVRegST3
+ lldb_st4_x86_64, // CVRegST4
+ lldb_st5_x86_64, // CVRegST5
+ lldb_st6_x86_64, // CVRegST6
+ lldb_st7_x86_64, // CVRegST7
+ LLDB_INVALID_REGNUM, // CVRegCTRL
+ LLDB_INVALID_REGNUM, // CVRegSTAT
+ LLDB_INVALID_REGNUM, // CVRegTAG
+ LLDB_INVALID_REGNUM, // CVRegFPIP
+ LLDB_INVALID_REGNUM, // CVRegFPCS
+ LLDB_INVALID_REGNUM, // CVRegFPDO
+ LLDB_INVALID_REGNUM, // CVRegFPDS
+ LLDB_INVALID_REGNUM, // CVRegISEM
+ LLDB_INVALID_REGNUM, // CVRegFPEIP
+ LLDB_INVALID_REGNUM, // CVRegFPEDO
+ lldb_mm0_x86_64, // CVRegMM0
+ lldb_mm1_x86_64, // CVRegMM1
+ lldb_mm2_x86_64, // CVRegMM2
+ lldb_mm3_x86_64, // CVRegMM3
+ lldb_mm4_x86_64, // CVRegMM4
+ lldb_mm5_x86_64, // CVRegMM5
+ lldb_mm6_x86_64, // CVRegMM6
+ lldb_mm7_x86_64, // CVRegMM7
+ lldb_xmm0_x86_64, // CVRegXMM0
+ lldb_xmm1_x86_64, // CVRegXMM1
+ lldb_xmm2_x86_64, // CVRegXMM2
+ lldb_xmm3_x86_64, // CVRegXMM3
+ lldb_xmm4_x86_64, // CVRegXMM4
+ lldb_xmm5_x86_64, // CVRegXMM5
+ lldb_xmm6_x86_64, // CVRegXMM6
+ lldb_xmm7_x86_64, // CVRegXMM7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ lldb_mxcsr_x86_64, // CVRegMXCSR
+ LLDB_INVALID_REGNUM, // CVRegEDXEAX
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegEMM0L
+ LLDB_INVALID_REGNUM, // CVRegEMM1L
+ LLDB_INVALID_REGNUM, // CVRegEMM2L
+ LLDB_INVALID_REGNUM, // CVRegEMM3L
+ LLDB_INVALID_REGNUM, // CVRegEMM4L
+ LLDB_INVALID_REGNUM, // CVRegEMM5L
+ LLDB_INVALID_REGNUM, // CVRegEMM6L
+ LLDB_INVALID_REGNUM, // CVRegEMM7L
+ LLDB_INVALID_REGNUM, // CVRegEMM0H
+ LLDB_INVALID_REGNUM, // CVRegEMM1H
+ LLDB_INVALID_REGNUM, // CVRegEMM2H
+ LLDB_INVALID_REGNUM, // CVRegEMM3H
+ LLDB_INVALID_REGNUM, // CVRegEMM4H
+ LLDB_INVALID_REGNUM, // CVRegEMM5H
+ LLDB_INVALID_REGNUM, // CVRegEMM6H
+ LLDB_INVALID_REGNUM, // CVRegEMM7H
+ LLDB_INVALID_REGNUM, // CVRegMM00
+ LLDB_INVALID_REGNUM, // CVRegMM01
+ LLDB_INVALID_REGNUM, // CVRegMM10
+ LLDB_INVALID_REGNUM, // CVRegMM11
+ LLDB_INVALID_REGNUM, // CVRegMM20
+ LLDB_INVALID_REGNUM, // CVRegMM21
+ LLDB_INVALID_REGNUM, // CVRegMM30
+ LLDB_INVALID_REGNUM, // CVRegMM31
+ LLDB_INVALID_REGNUM, // CVRegMM40
+ LLDB_INVALID_REGNUM, // CVRegMM41
+ LLDB_INVALID_REGNUM, // CVRegMM50
+ LLDB_INVALID_REGNUM, // CVRegMM51
+ LLDB_INVALID_REGNUM, // CVRegMM60
+ LLDB_INVALID_REGNUM, // CVRegMM61
+ LLDB_INVALID_REGNUM, // CVRegMM70
+ LLDB_INVALID_REGNUM, // CVRegMM71
+ lldb_xmm8_x86_64, // CVRegXMM8
+ lldb_xmm9_x86_64, // CVRegXMM9
+ lldb_xmm10_x86_64, // CVRegXMM10
+ lldb_xmm11_x86_64, // CVRegXMM11
+ lldb_xmm12_x86_64, // CVRegXMM12
+ lldb_xmm13_x86_64, // CVRegXMM13
+ lldb_xmm14_x86_64, // CVRegXMM14
+ lldb_xmm15_x86_64, // CVRegXMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ lldb_sil_x86_64, // CVRegSIL
+ lldb_dil_x86_64, // CVRegDIL
+ lldb_bpl_x86_64, // CVRegBPL
+ lldb_spl_x86_64, // CVRegSPL
+ lldb_rax_x86_64, // CVRegRAX
+ lldb_rbx_x86_64, // CVRegRBX
+ lldb_rcx_x86_64, // CVRegRCX
+ lldb_rdx_x86_64, // CVRegRDX
+ lldb_rsi_x86_64, // CVRegRSI
+ lldb_rdi_x86_64, // CVRegRDI
+ lldb_rbp_x86_64, // CVRegRBP
+ lldb_rsp_x86_64, // CVRegRSP
+ lldb_r8_x86_64, // CVRegR8
+ lldb_r9_x86_64, // CVRegR9
+ lldb_r10_x86_64, // CVRegR10
+ lldb_r11_x86_64, // CVRegR11
+ lldb_r12_x86_64, // CVRegR12
+ lldb_r13_x86_64, // CVRegR13
+ lldb_r14_x86_64, // CVRegR14
+ lldb_r15_x86_64, // CVRegR15
+ lldb_r8l_x86_64, // CVRegR8B
+ lldb_r9l_x86_64, // CVRegR9B
+ lldb_r10l_x86_64, // CVRegR10B
+ lldb_r11l_x86_64, // CVRegR11B
+ lldb_r12l_x86_64, // CVRegR12B
+ lldb_r13l_x86_64, // CVRegR13B
+ lldb_r14l_x86_64, // CVRegR14B
+ lldb_r15l_x86_64, // CVRegR15B
+ lldb_r8w_x86_64, // CVRegR8W
+ lldb_r9w_x86_64, // CVRegR9W
+ lldb_r10w_x86_64, // CVRegR10W
+ lldb_r11w_x86_64, // CVRegR11W
+ lldb_r12w_x86_64, // CVRegR12W
+ lldb_r13w_x86_64, // CVRegR13W
+ lldb_r14w_x86_64, // CVRegR14W
+ lldb_r15w_x86_64, // CVRegR15W
+ lldb_r8d_x86_64, // CVRegR8D
+ lldb_r9d_x86_64, // CVRegR9D
+ lldb_r10d_x86_64, // CVRegR10D
+ lldb_r11d_x86_64, // CVRegR11D
+ lldb_r12d_x86_64, // CVRegR12D
+ lldb_r13d_x86_64, // CVRegR13D
+ lldb_r14d_x86_64, // CVRegR14D
+ lldb_r15d_x86_64, // CVRegR15D
+ lldb_ymm0_x86_64, // CVRegAMD64_YMM0
+ lldb_ymm1_x86_64, // CVRegAMD64_YMM1
+ lldb_ymm2_x86_64, // CVRegAMD64_YMM2
+ lldb_ymm3_x86_64, // CVRegAMD64_YMM3
+ lldb_ymm4_x86_64, // CVRegAMD64_YMM4
+ lldb_ymm5_x86_64, // CVRegAMD64_YMM5
+ lldb_ymm6_x86_64, // CVRegAMD64_YMM6
+ lldb_ymm7_x86_64, // CVRegAMD64_YMM7
+ lldb_ymm8_x86_64, // CVRegAMD64_YMM8
+ lldb_ymm9_x86_64, // CVRegAMD64_YMM9
+ lldb_ymm10_x86_64, // CVRegAMD64_YMM10
+ lldb_ymm11_x86_64, // CVRegAMD64_YMM11
+ lldb_ymm12_x86_64, // CVRegAMD64_YMM12
+ lldb_ymm13_x86_64, // CVRegAMD64_YMM13
+ lldb_ymm14_x86_64, // CVRegAMD64_YMM14
+ lldb_ymm15_x86_64, // CVRegAMD64_YMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_bnd0_x86_64, // CVRegBND0
+ lldb_bnd1_x86_64, // CVRegBND1
+ lldb_bnd2_x86_64 // CVRegBND2
+};
+
+uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
+ llvm::codeview::RegisterId register_id) {
+ switch (arch_type) {
+ case llvm::Triple::x86:
+ if (static_cast<uint16_t>(register_id) <
+ sizeof(g_code_view_to_lldb_registers_x86) /
+ sizeof(g_code_view_to_lldb_registers_x86[0]))
+ return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>(
+ register_id)];
+
+ switch (register_id) {
+ case llvm::codeview::RegisterId::CVRegMXCSR:
+ return lldb_mxcsr_i386;
+ case llvm::codeview::RegisterId::CVRegBND0:
+ return lldb_bnd0_i386;
+ case llvm::codeview::RegisterId::CVRegBND1:
+ return lldb_bnd1_i386;
+ case llvm::codeview::RegisterId::CVRegBND2:
+ return lldb_bnd2_i386;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ case llvm::Triple::x86_64:
+ if (static_cast<uint16_t>(register_id) <
+ sizeof(g_code_view_to_lldb_registers_x86_64) /
+ sizeof(g_code_view_to_lldb_registers_x86_64[0]))
+ return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>(
+ register_id)];
+
+ return LLDB_INVALID_REGNUM;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+}
+
+uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
+ if (register_id == llvm::codeview::RegisterId::CVRegVFRAME)
+ return LLDB_REGNUM_GENERIC_FP;
+
+ return LLDB_INVALID_REGNUM;
+}
+
+uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
+ llvm::codeview::RegisterId register_id,
+ RegisterKind &register_kind) {
+ register_kind = eRegisterKindLLDB;
+ uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
+ if (reg_num != LLDB_INVALID_REGNUM)
+ return reg_num;
+
+ register_kind = eRegisterKindGeneric;
+ return GetGenericRegisterNumber(register_id);
+}
+} // namespace
+
+DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module,
+ const PDBSymbolData &symbol,
+ bool &is_constant) {
+ is_constant = true;
+
+ if (!module)
+ return DWARFExpression(nullptr);
+
+ const ArchSpec &architecture = module->GetArchitecture();
+ llvm::Triple::ArchType arch_type = architecture.GetMachine();
+ ByteOrder byte_order = architecture.GetByteOrder();
+ uint32_t address_size = architecture.GetAddressByteSize();
+ uint32_t byte_size = architecture.GetDataByteSize();
+ if (byte_order == eByteOrderInvalid || address_size == 0)
+ return DWARFExpression(nullptr);
+
+ RegisterKind register_kind = eRegisterKindDWARF;
+ StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
+ switch (symbol.getLocationType()) {
+ case PDB_LocType::Static:
+ case PDB_LocType::TLS: {
+ stream.PutHex8(DW_OP_addr);
+
+ SectionList *section_list = module->GetSectionList();
+ if (!section_list)
+ return DWARFExpression(nullptr);
+
+ uint32_t section_idx = symbol.getAddressSection() - 1;
+ if (section_idx >= section_list->GetSize())
+ return DWARFExpression(nullptr);
+
+ auto section = section_list->GetSectionAtIndex(section_idx);
+ if (!section)
+ return DWARFExpression(nullptr);
+
+ uint32_t offset = symbol.getAddressOffset();
+ stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
+ byte_order);
+
+ is_constant = false;
+
+ break;
+ }
+ case PDB_LocType::RegRel: {
+ uint32_t reg_num =
+ GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return DWARFExpression(nullptr);
+
+ if (reg_num > 31) {
+ stream.PutHex8(DW_OP_bregx);
+ stream.PutULEB128(reg_num);
+ } else
+ stream.PutHex8(DW_OP_breg0 + reg_num);
+
+ int32_t offset = symbol.getOffset();
+ stream.PutSLEB128(offset);
+
+ is_constant = false;
+
+ break;
+ }
+ case PDB_LocType::Enregistered: {
+ uint32_t reg_num =
+ GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return DWARFExpression(nullptr);
+
+ if (reg_num > 31) {
+ stream.PutHex8(DW_OP_regx);
+ stream.PutULEB128(reg_num);
+ } else
+ stream.PutHex8(DW_OP_reg0 + reg_num);
+
+ is_constant = false;
+
+ break;
+ }
+ case PDB_LocType::Constant: {
+ Variant value = symbol.getValue();
+ stream.PutRawBytes(&value.Value, sizeof(value.Value),
+ endian::InlHostByteOrder());
+ break;
+ }
+ default:
+ return DWARFExpression(nullptr);
+ }
+
+ DataBufferSP buffer =
+ std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
+ DataExtractor extractor(buffer, byte_order, address_size, byte_size);
+ DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
+ result.SetRegisterKind(register_kind);
+
+ return result;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
new file mode 100644
index 000000000000..37b80dfccb84
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
@@ -0,0 +1,45 @@
+//===-- PDBLocationToDWARFExpression.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_
+#define lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_
+
+#include "lldb/Core/Module.h"
+
+namespace lldb_private {
+class DWARFExpression;
+}
+
+namespace llvm {
+namespace pdb {
+class PDBSymbolData;
+}
+} // namespace llvm
+
+//------------------------------------------------------------------------------
+/// Converts a location information from a PDB symbol to a DWARF expression
+///
+/// @param[in] module
+/// The module \a symbol belongs to.
+///
+/// @param[in] symbol
+/// The symbol with a location information to convert.
+///
+/// @param[out] is_constant
+/// Set to \b true if the result expression is a constant value data,
+/// and \b false if it is a DWARF bytecode.
+///
+/// @return
+/// The DWARF expression corresponding to the location data of \a symbol.
+//------------------------------------------------------------------------------
+lldb_private::DWARFExpression
+ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module,
+ const llvm::pdb::PDBSymbolData &symbol,
+ bool &is_constant);
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index de9b9f024fc7..05f3017819fa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -18,16 +18,21 @@
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/Variable.h"
#include "lldb/Utility/RegularExpression.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/IPDBTable.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
@@ -35,14 +40,18 @@
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
+#include "Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h"
#include <regex>
+using namespace lldb;
using namespace lldb_private;
using namespace llvm::pdb;
@@ -63,7 +72,7 @@ bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
return ((requested_line == 0 || actual_line == requested_line) &&
addr_length > 0);
}
-}
+} // namespace
void SymbolFilePDB::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
@@ -92,7 +101,8 @@ SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
}
SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
- : SymbolFile(object_file), m_cached_compile_unit_count(0) {}
+ : SymbolFile(object_file), m_session_up(), m_global_scope_up(),
+ m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {}
SymbolFilePDB::~SymbolFilePDB() {}
@@ -116,15 +126,14 @@ uint32_t SymbolFilePDB::CalculateAbilities() {
if (!symfile)
return 0;
error = loadDataForPDB(PDB_ReaderType::DIA,
- llvm::StringRef(symfile.GetPath()),
- m_session_up);
+ llvm::StringRef(symfile.GetPath()), m_session_up);
if (error) {
llvm::consumeError(std::move(error));
return 0;
}
}
}
- if (!m_session_up.get())
+ if (!m_session_up)
return 0;
auto enum_tables_up = m_session_up->getEnumTables();
@@ -138,13 +147,14 @@ uint32_t SymbolFilePDB::CalculateAbilities() {
case PDB_TableType::Symbols:
// This table represents a store of symbols with types listed in
// PDBSym_Type
- abilities |= (CompileUnits | Functions | Blocks |
- GlobalVariables | LocalVariables | VariableTypes);
+ abilities |= (CompileUnits | Functions | Blocks | GlobalVariables |
+ LocalVariables | VariableTypes);
break;
case PDB_TableType::LineNumbers:
abilities |= LineTables;
break;
- default: break;
+ default:
+ break;
}
}
return abilities;
@@ -152,41 +162,88 @@ uint32_t SymbolFilePDB::CalculateAbilities() {
void SymbolFilePDB::InitializeObject() {
lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
+ lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS);
m_session_up->setLoadAddress(obj_load_address);
+ if (!m_global_scope_up)
+ m_global_scope_up = m_session_up->getGlobalScope();
+ lldbassert(m_global_scope_up.get());
TypeSystem *type_system =
GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
ClangASTContext *clang_type_system =
llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ lldbassert(clang_type_system);
m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(
type_system, clang_type_system->GetTranslationUnitDecl());
}
uint32_t SymbolFilePDB::GetNumCompileUnits() {
if (m_cached_compile_unit_count == 0) {
- auto global = m_session_up->getGlobalScope();
- auto compilands = global->findAllChildren<PDBSymbolCompiland>();
+ auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
+ if (!compilands)
+ return 0;
+
+ // The linker could link *.dll (compiland language = LINK), or import
+ // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be
+ // found as a child of the global scope (PDB executable). Usually, such
+ // compilands contain `thunk` symbols in which we are not interested for
+ // now. However we still count them in the compiland list. If we perform
+ // any compiland related activity, like finding symbols through
+ // llvm::pdb::IPDBSession methods, such compilands will all be searched
+ // automatically no matter whether we include them or not.
m_cached_compile_unit_count = compilands->getChildCount();
// The linker can inject an additional "dummy" compilation unit into the
// PDB. Ignore this special compile unit for our purposes, if it is there.
// It is always the last one.
- auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
- std::string name = last_cu->getName();
+ auto last_compiland_up =
+ compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
+ lldbassert(last_compiland_up.get());
+ std::string name = last_compiland_up->getName();
if (name == "* Linker *")
--m_cached_compile_unit_count;
}
return m_cached_compile_unit_count;
}
-lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
- auto global = m_session_up->getGlobalScope();
- auto compilands = global->findAllChildren<PDBSymbolCompiland>();
- auto cu = compilands->getChildAtIndex(index);
+void SymbolFilePDB::GetCompileUnitIndex(
+ const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) {
+ auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
+ if (!results_up)
+ return;
+ auto uid = pdb_compiland.getSymIndexId();
+ for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
+ auto compiland_up = results_up->getChildAtIndex(cu_idx);
+ if (!compiland_up)
+ continue;
+ if (compiland_up->getSymIndexId() == uid) {
+ index = cu_idx;
+ return;
+ }
+ }
+ index = UINT32_MAX;
+ return;
+}
- uint32_t id = cu->getSymIndexId();
+std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
+SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) {
+ return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid);
+}
- return ParseCompileUnitForSymIndex(id);
+lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
+ if (index >= GetNumCompileUnits())
+ return CompUnitSP();
+
+ // Assuming we always retrieve same compilands listed in same order through
+ // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a
+ // compile unit makes no sense.
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
+ if (!results)
+ return CompUnitSP();
+ auto compiland_up = results->getChildAtIndex(index);
+ if (!compiland_up)
+ return CompUnitSP();
+ return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index);
}
lldb::LanguageType
@@ -196,24 +253,71 @@ SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
if (!sc.comp_unit)
return lldb::eLanguageTypeUnknown;
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
- sc.comp_unit->GetID());
- if (!cu)
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
return lldb::eLanguageTypeUnknown;
- auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
+ auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
if (!details)
return lldb::eLanguageTypeUnknown;
return TranslateLanguage(details->getLanguage());
}
+lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(
+ const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) {
+ lldbassert(sc.comp_unit && sc.module_sp.get());
+
+ auto file_vm_addr = pdb_func.getVirtualAddress();
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ return nullptr;
+
+ auto func_length = pdb_func.getLength();
+ AddressRange func_range =
+ AddressRange(file_vm_addr, func_length, sc.module_sp->GetSectionList());
+ if (!func_range.GetBaseAddress().IsValid())
+ return nullptr;
+
+ lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId());
+ if (!func_type)
+ return nullptr;
+
+ user_id_t func_type_uid = pdb_func.getSignatureId();
+
+ Mangled mangled = GetMangledForPDBFunc(pdb_func);
+
+ FunctionSP func_sp =
+ std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(),
+ func_type_uid, mangled, func_type, func_range);
+
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+}
+
size_t SymbolFilePDB::ParseCompileUnitFunctions(
const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ lldbassert(sc.comp_unit);
+ size_t func_added = 0;
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
+ return 0;
+ auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>();
+ if (!results_up)
+ return 0;
+ while (auto pdb_func_up = results_up->getNext()) {
+ auto func_sp =
+ sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId());
+ if (!func_sp) {
+ if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, sc))
+ ++func_added;
+ }
+ }
+ return func_added;
}
bool SymbolFilePDB::ParseCompileUnitLineTable(
const lldb_private::SymbolContext &sc) {
+ lldbassert(sc.comp_unit);
+ if (sc.comp_unit->GetLineTable())
+ return true;
return ParseCompileUnitLineTable(sc, 0);
}
@@ -226,26 +330,29 @@ bool SymbolFilePDB::ParseCompileUnitDebugMacros(
bool SymbolFilePDB::ParseCompileUnitSupportFiles(
const lldb_private::SymbolContext &sc,
lldb_private::FileSpecList &support_files) {
- if (!sc.comp_unit)
- return false;
+ lldbassert(sc.comp_unit);
// In theory this is unnecessary work for us, because all of this information
// is easily (and quickly) accessible from DebugInfoPDB, so caching it a
// second time seems like a waste. Unfortunately, there's no good way around
// this short of a moderate refactor since SymbolVendor depends on being able
// to cache this list.
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
- sc.comp_unit->GetID());
- if (!cu)
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
return false;
- auto files = m_session_up->getSourceFilesForCompiland(*cu);
+ auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
if (!files || files->getChildCount() == 0)
return false;
while (auto file = files->getNext()) {
- FileSpec spec(file->getFileName(), false);
- support_files.Append(spec);
+ FileSpec spec(file->getFileName(), false, FileSpec::Style::windows);
+ support_files.AppendIfUnique(spec);
}
+
+ // LLDB uses the DWARF-like file numeration (one based),
+ // the zeroth file is the compile unit itself
+ support_files.Insert(0, *sc.comp_unit);
+
return true;
}
@@ -256,21 +363,178 @@ bool SymbolFilePDB::ParseImportedModules(
return false;
}
+static size_t ParseFunctionBlocksForPDBSymbol(
+ const lldb_private::SymbolContext &sc, uint64_t func_file_vm_addr,
+ const llvm::pdb::PDBSymbol *pdb_symbol, lldb_private::Block *parent_block,
+ bool is_top_parent) {
+ assert(pdb_symbol && parent_block);
+
+ size_t num_added = 0;
+ switch (pdb_symbol->getSymTag()) {
+ case PDB_SymType::Block:
+ case PDB_SymType::Function: {
+ Block *block = nullptr;
+ auto &raw_sym = pdb_symbol->getRawSymbol();
+ if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) {
+ if (pdb_func->hasNoInlineAttribute())
+ break;
+ if (is_top_parent)
+ block = parent_block;
+ else
+ break;
+ } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) {
+ auto uid = pdb_symbol->getSymIndexId();
+ if (parent_block->FindBlockByID(uid))
+ break;
+ if (raw_sym.getVirtualAddress() < func_file_vm_addr)
+ break;
+
+ auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId());
+ parent_block->AddChild(block_sp);
+ block = block_sp.get();
+ } else
+ llvm_unreachable("Unexpected PDB symbol!");
+
+ block->AddRange(Block::Range(
+ raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength()));
+ block->FinalizeRanges();
+ ++num_added;
+
+ auto results_up = pdb_symbol->findAllChildren();
+ if (!results_up)
+ break;
+ while (auto symbol_up = results_up->getNext()) {
+ num_added += ParseFunctionBlocksForPDBSymbol(
+ sc, func_file_vm_addr, symbol_up.get(), block, false);
+ }
+ } break;
+ default:
+ break;
+ }
+ return num_added;
+}
+
size_t
SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ lldbassert(sc.comp_unit && sc.function);
+ size_t num_added = 0;
+ auto uid = sc.function->GetID();
+ auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
+ if (!pdb_func_up)
+ return 0;
+ Block &parent_block = sc.function->GetBlock(false);
+ num_added =
+ ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(),
+ pdb_func_up.get(), &parent_block, true);
+ return num_added;
}
size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ lldbassert(sc.module_sp.get());
+ if (!sc.comp_unit)
+ return 0;
+
+ size_t num_added = 0;
+ auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland)
+ return 0;
+
+ auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) {
+ std::unique_ptr<IPDBEnumSymbols> results;
+ PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
+ PDB_SymType::UDT};
+ for (auto tag : tags_to_search) {
+ results = raw_sym.findAllChildren(tag);
+ if (!results || results->getChildCount() == 0)
+ continue;
+ while (auto symbol = results->getNext()) {
+ switch (symbol->getSymTag()) {
+ case PDB_SymType::Enum:
+ case PDB_SymType::UDT:
+ case PDB_SymType::Typedef:
+ break;
+ default:
+ continue;
+ }
+
+ // This should cause the type to get cached and stored in the `m_types`
+ // lookup.
+ if (!ResolveTypeUID(symbol->getSymIndexId()))
+ continue;
+
+ ++num_added;
+ }
+ }
+ };
+
+ if (sc.function) {
+ auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
+ sc.function->GetID());
+ if (!pdb_func)
+ return 0;
+ ParseTypesByTagFn(*pdb_func);
+ } else {
+ ParseTypesByTagFn(*compiland);
+
+ // Also parse global types particularly coming from this compiland.
+ // Unfortunately, PDB has no compiland information for each global type. We
+ // have to parse them all. But ensure we only do this once.
+ static bool parse_all_global_types = false;
+ if (!parse_all_global_types) {
+ ParseTypesByTagFn(*m_global_scope_up);
+ parse_all_global_types = true;
+ }
+ }
+ return num_added;
}
size_t
SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ if (!sc.comp_unit)
+ return 0;
+
+ size_t num_added = 0;
+ if (sc.function) {
+ auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
+ sc.function->GetID());
+ if (!pdb_func)
+ return 0;
+
+ num_added += ParseVariables(sc, *pdb_func);
+ sc.function->GetBlock(false).SetDidParseVariables(true, true);
+ } else if (sc.comp_unit) {
+ auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland)
+ return 0;
+
+ if (sc.comp_unit->GetVariableList(false))
+ return 0;
+
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
+ if (results && results->getChildCount()) {
+ while (auto result = results->getNext()) {
+ auto cu_id = result->getCompilandId();
+ // FIXME: We are not able to determine variable's compile unit.
+ if (cu_id == 0)
+ continue;
+
+ if (cu_id == sc.comp_unit->GetID())
+ num_added += ParseVariables(sc, *result);
+ }
+ }
+
+ // FIXME: A `file static` or `global constant` variable appears both in
+ // compiland's children and global scope's children with unexpectedly
+ // different symbol's Id making it ambiguous.
+
+ // FIXME: 'local constant', for example, const char var[] = "abc", declared
+ // in a function scope, can't be found in PDB.
+
+ // Parse variables in this compiland.
+ num_added += ParseVariables(sc, *compiland);
+ }
+
+ return num_added;
}
lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -294,8 +558,12 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
return nullptr;
lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
- if (result.get())
+ if (result) {
m_types.insert(std::make_pair(type_uid, result));
+ auto type_list = GetTypeList();
+ if (type_list)
+ type_list->Insert(result);
+ }
return result.get();
}
@@ -328,12 +596,62 @@ uint32_t
SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
uint32_t resolve_scope,
lldb_private::SymbolContext &sc) {
- return uint32_t();
+ uint32_t resolved_flags = 0;
+ if (resolve_scope & eSymbolContextCompUnit ||
+ resolve_scope & eSymbolContextVariable ||
+ resolve_scope & eSymbolContextFunction ||
+ resolve_scope & eSymbolContextBlock ||
+ resolve_scope & eSymbolContextLineEntry) {
+ auto cu_sp = GetCompileUnitContainsAddress(so_addr);
+ if (!cu_sp) {
+ if (resolved_flags | eSymbolContextVariable) {
+ // TODO: Resolve variables
+ }
+ return 0;
+ }
+ sc.comp_unit = cu_sp.get();
+ resolved_flags |= eSymbolContextCompUnit;
+ lldbassert(sc.module_sp == cu_sp->GetModule());
+ }
+
+ if (resolve_scope & eSymbolContextFunction) {
+ addr_t file_vm_addr = so_addr.GetFileAddress();
+ auto symbol_up =
+ m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function);
+ if (symbol_up) {
+ auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
+ assert(pdb_func);
+ auto func_uid = pdb_func->getSymIndexId();
+ sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
+ if (sc.function == nullptr)
+ sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+ if (sc.function) {
+ resolved_flags |= eSymbolContextFunction;
+ if (resolve_scope & eSymbolContextBlock) {
+ Block &block = sc.function->GetBlock(true);
+ sc.block = block.FindBlockByID(sc.function->GetID());
+ if (sc.block)
+ resolved_flags |= eSymbolContextBlock;
+ }
+ }
+ }
+ }
+
+ if (resolve_scope & eSymbolContextLineEntry) {
+ if (auto *line_table = sc.comp_unit->GetLineTable()) {
+ Address addr(so_addr);
+ if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
+ resolved_flags |= eSymbolContextLineEntry;
+ }
+ }
+
+ return resolved_flags;
}
uint32_t SymbolFilePDB::ResolveSymbolContext(
const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) {
+ const size_t old_size = sc_list.GetSize();
if (resolve_scope & lldb::eSymbolContextCompUnit) {
// Locate all compilation units with line numbers referencing the specified
// file. For example, if `file_spec` is <vector>, then this should return
@@ -342,56 +660,498 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
auto compilands = m_session_up->findCompilandsForSourceFile(
file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
+ if (!compilands)
+ return 0;
+
// For each one, either find its previously parsed data or parse it afresh
// and add it to the symbol context list.
while (auto compiland = compilands->getNext()) {
- // If we're not checking inlines, then don't add line information for this
- // file unless the FileSpec matches.
+ // If we're not checking inlines, then don't add line information for
+ // this file unless the FileSpec matches. For inline functions, we don't
+ // have to match the FileSpec since they could be defined in headers
+ // other than file specified in FileSpec.
if (!check_inlines) {
- // `getSourceFileName` returns the basename of the original source file
- // used to generate this compiland. It does not return the full path.
- // Currently the only way to get that is to do a basename lookup to get
- // the IPDBSourceFile, but this is ambiguous in the case of two source
- // files with the same name contributing to the same compiland. This is
- // a moderately extreme edge case, so we consider this OK for now,
- // although we need to find a long-term solution.
- std::string source_file = compiland->getSourceFileName();
- auto pdb_file = m_session_up->findOneSourceFile(
- compiland.get(), source_file,
- PDB_NameSearchFlags::NS_CaseInsensitive);
- source_file = pdb_file->getFileName();
- FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows);
- if (!file_spec.FileEquals(this_spec))
+ std::string source_file = compiland->getSourceFileFullPath();
+ if (source_file.empty())
+ continue;
+ FileSpec this_spec(source_file, false, FileSpec::Style::windows);
+ bool need_full_match = !file_spec.GetDirectory().IsEmpty();
+ if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0)
continue;
}
SymbolContext sc;
- auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId());
+ auto cu = ParseCompileUnitForUID(compiland->getSymIndexId());
+ if (!cu)
+ continue;
sc.comp_unit = cu.get();
sc.module_sp = cu->GetModule();
- sc_list.Append(sc);
// If we were asked to resolve line entries, add all entries to the line
// table that match the requested line (or all lines if `line` == 0).
- if (resolve_scope & lldb::eSymbolContextLineEntry)
- ParseCompileUnitLineTable(sc, line);
+ if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock |
+ eSymbolContextLineEntry)) {
+ bool has_line_table = ParseCompileUnitLineTable(sc, line);
+
+ if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) {
+ // The query asks for line entries, but we can't get them for the
+ // compile unit. This is not normal for `line` = 0. So just assert
+ // it.
+ assert(line && "Couldn't get all line entries!\n");
+
+ // Current compiland does not have the requested line. Search next.
+ continue;
+ }
+
+ if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
+ if (!has_line_table)
+ continue;
+
+ auto *line_table = sc.comp_unit->GetLineTable();
+ lldbassert(line_table);
+
+ uint32_t num_line_entries = line_table->GetSize();
+ // Skip the terminal line entry.
+ --num_line_entries;
+
+ // If `line `!= 0, see if we can resolve function for each line entry
+ // in the line table.
+ for (uint32_t line_idx = 0; line && line_idx < num_line_entries;
+ ++line_idx) {
+ if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry))
+ continue;
+
+ auto file_vm_addr =
+ sc.line_entry.range.GetBaseAddress().GetFileAddress();
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ continue;
+
+ auto symbol_up = m_session_up->findSymbolByAddress(
+ file_vm_addr, PDB_SymType::Function);
+ if (symbol_up) {
+ auto func_uid = symbol_up->getSymIndexId();
+ sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
+ if (sc.function == nullptr) {
+ auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
+ assert(pdb_func);
+ sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+ }
+ if (sc.function && (resolve_scope & eSymbolContextBlock)) {
+ Block &block = sc.function->GetBlock(true);
+ sc.block = block.FindBlockByID(sc.function->GetID());
+ }
+ }
+ sc_list.Append(sc);
+ }
+ } else if (has_line_table) {
+ // We can parse line table for the compile unit. But no query to
+ // resolve function or block. We append `sc` to the list anyway.
+ sc_list.Append(sc);
+ }
+ } else {
+ // No query for line entry, function or block. But we have a valid
+ // compile unit, append `sc` to the list.
+ sc_list.Append(sc);
+ }
}
}
- return sc_list.GetSize();
+ return sc_list.GetSize() - old_size;
+}
+
+std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) {
+ std::string decorated_name;
+ auto vm_addr = pdb_data.getVirtualAddress();
+ if (vm_addr != LLDB_INVALID_ADDRESS && vm_addr) {
+ auto result_up =
+ m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol);
+ if (result_up) {
+ while (auto symbol_up = result_up->getNext()) {
+ if (symbol_up->getRawSymbol().getVirtualAddress() == vm_addr) {
+ decorated_name = symbol_up->getRawSymbol().getName();
+ break;
+ }
+ }
+ }
+ }
+ if (!decorated_name.empty())
+ return decorated_name;
+
+ return std::string();
+}
+
+VariableSP SymbolFilePDB::ParseVariableForPDBData(
+ const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbolData &pdb_data) {
+ VariableSP var_sp;
+ uint32_t var_uid = pdb_data.getSymIndexId();
+ auto result = m_variables.find(var_uid);
+ if (result != m_variables.end())
+ return result->second;
+
+ ValueType scope = eValueTypeInvalid;
+ bool is_static_member = false;
+ bool is_external = false;
+ bool is_artificial = false;
+
+ switch (pdb_data.getDataKind()) {
+ case PDB_DataKind::Global:
+ scope = eValueTypeVariableGlobal;
+ is_external = true;
+ break;
+ case PDB_DataKind::Local:
+ scope = eValueTypeVariableLocal;
+ break;
+ case PDB_DataKind::FileStatic:
+ scope = eValueTypeVariableStatic;
+ break;
+ case PDB_DataKind::StaticMember:
+ is_static_member = true;
+ scope = eValueTypeVariableStatic;
+ break;
+ case PDB_DataKind::Member:
+ scope = eValueTypeVariableStatic;
+ break;
+ case PDB_DataKind::Param:
+ scope = eValueTypeVariableArgument;
+ break;
+ case PDB_DataKind::Constant:
+ scope = eValueTypeConstResult;
+ break;
+ default:
+ break;
+ }
+
+ switch (pdb_data.getLocationType()) {
+ case PDB_LocType::TLS:
+ scope = eValueTypeVariableThreadLocal;
+ break;
+ case PDB_LocType::RegRel: {
+ // It is a `this` pointer.
+ if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) {
+ scope = eValueTypeVariableArgument;
+ is_artificial = true;
+ }
+ } break;
+ default:
+ break;
+ }
+
+ Declaration decl;
+ if (!is_artificial && !pdb_data.isCompilerGenerated()) {
+ if (auto lines = pdb_data.getLineNumbers()) {
+ if (auto first_line = lines->getNext()) {
+ uint32_t src_file_id = first_line->getSourceFileId();
+ auto src_file = m_session_up->getSourceFileById(src_file_id);
+ if (src_file) {
+ FileSpec spec(src_file->getFileName(), /*resolve_path*/ false);
+ decl.SetFile(spec);
+ decl.SetColumn(first_line->getColumnNumber());
+ decl.SetLine(first_line->getLineNumber());
+ }
+ }
+ }
+ }
+
+ Variable::RangeList ranges;
+ SymbolContextScope *context_scope = sc.comp_unit;
+ if (scope == eValueTypeVariableLocal) {
+ if (sc.function) {
+ context_scope = sc.function->GetBlock(true).FindBlockByID(
+ pdb_data.getClassParentId());
+ if (context_scope == nullptr)
+ context_scope = sc.function;
+ }
+ }
+
+ SymbolFileTypeSP type_sp =
+ std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId());
+
+ auto var_name = pdb_data.getName();
+ auto mangled = GetMangledForPDBData(pdb_data);
+ auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
+
+ bool is_constant;
+ DWARFExpression location = ConvertPDBLocationToDWARFExpression(
+ GetObjectFile()->GetModule(), pdb_data, is_constant);
+
+ var_sp = std::make_shared<Variable>(
+ var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
+ ranges, &decl, location, is_external, is_artificial, is_static_member);
+ var_sp->SetLocationIsConstantValueData(is_constant);
+
+ m_variables.insert(std::make_pair(var_uid, var_sp));
+ return var_sp;
+}
+
+size_t
+SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbol &pdb_symbol,
+ lldb_private::VariableList *variable_list) {
+ size_t num_added = 0;
+
+ if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) {
+ VariableListSP local_variable_list_sp;
+
+ auto result = m_variables.find(pdb_data->getSymIndexId());
+ if (result != m_variables.end()) {
+ if (variable_list)
+ variable_list->AddVariableIfUnique(result->second);
+ } else {
+ // Prepare right VariableList for this variable.
+ if (auto lexical_parent = pdb_data->getLexicalParent()) {
+ switch (lexical_parent->getSymTag()) {
+ case PDB_SymType::Exe:
+ assert(sc.comp_unit);
+ LLVM_FALLTHROUGH;
+ case PDB_SymType::Compiland: {
+ if (sc.comp_unit) {
+ local_variable_list_sp = sc.comp_unit->GetVariableList(false);
+ if (!local_variable_list_sp) {
+ local_variable_list_sp = std::make_shared<VariableList>();
+ sc.comp_unit->SetVariableList(local_variable_list_sp);
+ }
+ }
+ } break;
+ case PDB_SymType::Block:
+ case PDB_SymType::Function: {
+ if (sc.function) {
+ Block *block = sc.function->GetBlock(true).FindBlockByID(
+ lexical_parent->getSymIndexId());
+ if (block) {
+ local_variable_list_sp = block->GetBlockVariableList(false);
+ if (!local_variable_list_sp) {
+ local_variable_list_sp = std::make_shared<VariableList>();
+ block->SetVariableList(local_variable_list_sp);
+ }
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+
+ if (local_variable_list_sp) {
+ if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) {
+ local_variable_list_sp->AddVariableIfUnique(var_sp);
+ if (variable_list)
+ variable_list->AddVariableIfUnique(var_sp);
+ ++num_added;
+ }
+ }
+ }
+ }
+
+ if (auto results = pdb_symbol.findAllChildren()) {
+ while (auto result = results->getNext())
+ num_added += ParseVariables(sc, *result, variable_list);
+ }
+
+ return num_added;
}
uint32_t SymbolFilePDB::FindGlobalVariables(
const lldb_private::ConstString &name,
- const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
uint32_t max_matches, lldb_private::VariableList &variables) {
- return uint32_t();
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return 0;
+ if (name.IsEmpty())
+ return 0;
+
+ auto results =
+ m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(),
+ PDB_NameSearchFlags::NS_CaseSensitive);
+ if (!results)
+ return 0;
+
+ uint32_t matches = 0;
+ size_t old_size = variables.GetSize();
+ while (auto result = results->getNext()) {
+ auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get());
+ if (max_matches > 0 && matches >= max_matches)
+ break;
+
+ SymbolContext sc;
+ sc.module_sp = m_obj_file->GetModule();
+ lldbassert(sc.module_sp.get());
+
+ sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+ // FIXME: We are not able to determine the compile unit.
+ if (sc.comp_unit == nullptr)
+ continue;
+
+ ParseVariables(sc, *pdb_data, &variables);
+ matches = variables.GetSize() - old_size;
+ }
+
+ return matches;
}
uint32_t
SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) {
- return uint32_t();
+ if (!regex.IsValid())
+ return 0;
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
+ if (!results)
+ return 0;
+
+ uint32_t matches = 0;
+ size_t old_size = variables.GetSize();
+ while (auto pdb_data = results->getNext()) {
+ if (max_matches > 0 && matches >= max_matches)
+ break;
+
+ auto var_name = pdb_data->getName();
+ if (var_name.empty())
+ continue;
+ if (!regex.Execute(var_name))
+ continue;
+ SymbolContext sc;
+ sc.module_sp = m_obj_file->GetModule();
+ lldbassert(sc.module_sp.get());
+
+ sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+ // FIXME: We are not able to determine the compile unit.
+ if (sc.comp_unit == nullptr)
+ continue;
+
+ ParseVariables(sc, *pdb_data, &variables);
+ matches = variables.GetSize() - old_size;
+ }
+
+ return matches;
+}
+
+bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) {
+ lldb_private::SymbolContext sc;
+ sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get();
+ if (!sc.comp_unit)
+ return false;
+ sc.module_sp = sc.comp_unit->GetModule();
+ sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc);
+ if (!sc.function)
+ return false;
+
+ sc_list.Append(sc);
+ return true;
+}
+
+bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) {
+ auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
+ if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute()))
+ return false;
+ return ResolveFunction(*pdb_func_up, include_inlines, sc_list);
+}
+
+void SymbolFilePDB::CacheFunctionNames() {
+ if (!m_func_full_names.IsEmpty())
+ return;
+
+ std::map<uint64_t, uint32_t> addr_ids;
+
+ if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) {
+ while (auto pdb_func_up = results_up->getNext()) {
+ if (pdb_func_up->isCompilerGenerated())
+ continue;
+
+ auto name = pdb_func_up->getName();
+ auto demangled_name = pdb_func_up->getUndecoratedName();
+ if (name.empty() && demangled_name.empty())
+ continue;
+
+ auto uid = pdb_func_up->getSymIndexId();
+ if (!demangled_name.empty() && pdb_func_up->getVirtualAddress())
+ addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid));
+
+ if (auto parent = pdb_func_up->getClassParent()) {
+
+ // PDB have symbols for class/struct methods or static methods in Enum
+ // Class. We won't bother to check if the parent is UDT or Enum here.
+ m_func_method_names.Append(ConstString(name), uid);
+
+ ConstString cstr_name(name);
+
+ // To search a method name, like NS::Class:MemberFunc, LLDB searches
+ // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does
+ // not have inforamtion of this, we extract base names and cache them
+ // by our own effort.
+ llvm::StringRef basename;
+ CPlusPlusLanguage::MethodName cpp_method(cstr_name);
+ if (cpp_method.IsValid()) {
+ llvm::StringRef context;
+ basename = cpp_method.GetBasename();
+ if (basename.empty())
+ CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(),
+ context, basename);
+ }
+
+ if (!basename.empty())
+ m_func_base_names.Append(ConstString(basename), uid);
+ else {
+ m_func_base_names.Append(ConstString(name), uid);
+ }
+
+ if (!demangled_name.empty())
+ m_func_full_names.Append(ConstString(demangled_name), uid);
+
+ } else {
+ // Handle not-method symbols.
+
+ // The function name might contain namespace, or its lexical scope. It
+ // is not safe to get its base name by applying same scheme as we deal
+ // with the method names.
+ // FIXME: Remove namespace if function is static in a scope.
+ m_func_base_names.Append(ConstString(name), uid);
+
+ if (name == "main") {
+ m_func_full_names.Append(ConstString(name), uid);
+
+ if (!demangled_name.empty() && name != demangled_name) {
+ m_func_full_names.Append(ConstString(demangled_name), uid);
+ m_func_base_names.Append(ConstString(demangled_name), uid);
+ }
+ } else if (!demangled_name.empty()) {
+ m_func_full_names.Append(ConstString(demangled_name), uid);
+ } else {
+ m_func_full_names.Append(ConstString(name), uid);
+ }
+ }
+ }
+ }
+
+ if (auto results_up =
+ m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) {
+ while (auto pub_sym_up = results_up->getNext()) {
+ if (!pub_sym_up->isFunction())
+ continue;
+ auto name = pub_sym_up->getName();
+ if (name.empty())
+ continue;
+
+ if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) {
+ auto vm_addr = pub_sym_up->getVirtualAddress();
+
+ // PDB public symbol has mangled name for its associated function.
+ if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) {
+ // Cache mangled name.
+ m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]);
+ }
+ }
+ }
+ }
+ // Sort them before value searching is working properly
+ m_func_full_names.Sort();
+ m_func_full_names.SizeToFit();
+ m_func_method_names.Sort();
+ m_func_method_names.SizeToFit();
+ m_func_base_names.Sort();
+ m_func_base_names.SizeToFit();
}
uint32_t SymbolFilePDB::FindFunctions(
@@ -399,14 +1159,77 @@ uint32_t SymbolFilePDB::FindFunctions(
const lldb_private::CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask, bool include_inlines, bool append,
lldb_private::SymbolContextList &sc_list) {
- return uint32_t();
+ if (!append)
+ sc_list.Clear();
+ lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0);
+
+ if (name_type_mask == eFunctionNameTypeNone)
+ return 0;
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return 0;
+ if (name.IsEmpty())
+ return 0;
+
+ auto old_size = sc_list.GetSize();
+ if (name_type_mask & eFunctionNameTypeFull ||
+ name_type_mask & eFunctionNameTypeBase ||
+ name_type_mask & eFunctionNameTypeMethod) {
+ CacheFunctionNames();
+
+ std::set<uint32_t> resolved_ids;
+ auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids,
+ this](UniqueCStringMap<uint32_t> &Names) {
+ std::vector<uint32_t> ids;
+ if (Names.GetValues(name, ids)) {
+ for (auto id : ids) {
+ if (resolved_ids.find(id) == resolved_ids.end()) {
+ if (ResolveFunction(id, include_inlines, sc_list))
+ resolved_ids.insert(id);
+ }
+ }
+ }
+ };
+ if (name_type_mask & eFunctionNameTypeFull) {
+ ResolveFn(m_func_full_names);
+ }
+ if (name_type_mask & eFunctionNameTypeBase) {
+ ResolveFn(m_func_base_names);
+ }
+ if (name_type_mask & eFunctionNameTypeMethod) {
+ ResolveFn(m_func_method_names);
+ }
+ }
+ return sc_list.GetSize() - old_size;
}
uint32_t
SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex,
bool include_inlines, bool append,
lldb_private::SymbolContextList &sc_list) {
- return uint32_t();
+ if (!append)
+ sc_list.Clear();
+ if (!regex.IsValid())
+ return 0;
+
+ auto old_size = sc_list.GetSize();
+ CacheFunctionNames();
+
+ std::set<uint32_t> resolved_ids;
+ auto ResolveFn = [&regex, include_inlines, &sc_list, &resolved_ids,
+ this](UniqueCStringMap<uint32_t> &Names) {
+ std::vector<uint32_t> ids;
+ if (Names.GetValues(regex, ids)) {
+ for (auto id : ids) {
+ if (resolved_ids.find(id) == resolved_ids.end())
+ if (ResolveFunction(id, include_inlines, sc_list))
+ resolved_ids.insert(id);
+ }
+ }
+ };
+ ResolveFn(m_func_full_names);
+ ResolveFn(m_func_base_names);
+
+ return sc_list.GetSize() - old_size;
}
void SymbolFilePDB::GetMangledNamesForFunction(
@@ -424,6 +1247,8 @@ uint32_t SymbolFilePDB::FindTypes(
types.Clear();
if (!name)
return 0;
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return 0;
searched_symbol_files.clear();
searched_symbol_files.insert(this);
@@ -432,14 +1257,13 @@ uint32_t SymbolFilePDB::FindTypes(
// There is an assumption 'name' is not a regex
FindTypesByName(name_str, max_matches, types);
-
+
return types.GetSize();
}
-void
-SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
- uint32_t max_matches,
- lldb_private::TypeMap &types) {
+void SymbolFilePDB::FindTypesByRegex(
+ const lldb_private::RegularExpression &regex, uint32_t max_matches,
+ lldb_private::TypeMap &types) {
// When searching by regex, we need to go out of our way to limit the search
// space as much as possible since this searches EVERYTHING in the PDB,
// manually doing regex comparisons. PDB library isn't optimized for regex
@@ -448,13 +1272,15 @@ SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
// and do a regex comparison against each of them.
PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
PDB_SymType::UDT};
- auto global = m_session_up->getGlobalScope();
std::unique_ptr<IPDBEnumSymbols> results;
uint32_t matches = 0;
for (auto tag : tags_to_search) {
- results = global->findAllChildren(tag);
+ results = m_global_scope_up->findAllChildren(tag);
+ if (!results)
+ continue;
+
while (auto result = results->getNext()) {
if (max_matches > 0 && matches >= max_matches)
break;
@@ -493,10 +1319,13 @@ SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
void SymbolFilePDB::FindTypesByName(const std::string &name,
uint32_t max_matches,
lldb_private::TypeMap &types) {
- auto global = m_session_up->getGlobalScope();
std::unique_ptr<IPDBEnumSymbols> results;
- results = global->findChildren(PDB_SymType::None, name,
- PDB_NameSearchFlags::NS_Default);
+ if (name.empty())
+ return;
+ results = m_global_scope_up->findChildren(PDB_SymType::None, name,
+ PDB_NameSearchFlags::NS_Default);
+ if (!results)
+ return;
uint32_t matches = 0;
@@ -509,8 +1338,8 @@ void SymbolFilePDB::FindTypesByName(const std::string &name,
case PDB_SymType::Typedef:
break;
default:
- // We're looking only for types that have names. Skip symbols, as well as
- // unnamed types such as arrays, pointers, etc.
+ // We're looking only for types that have names. Skip symbols, as well
+ // as unnamed types such as arrays, pointers, etc.
continue;
}
@@ -533,12 +1362,87 @@ size_t SymbolFilePDB::FindTypes(
return 0;
}
-lldb_private::TypeList *SymbolFilePDB::GetTypeList() { return nullptr; }
+lldb_private::TypeList *SymbolFilePDB::GetTypeList() {
+ return m_obj_file->GetModule()->GetTypeList();
+}
+
+void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
+ uint32_t type_mask,
+ TypeCollection &type_collection) {
+ bool can_parse = false;
+ switch (pdb_symbol.getSymTag()) {
+ case PDB_SymType::ArrayType:
+ can_parse = ((type_mask & eTypeClassArray) != 0);
+ break;
+ case PDB_SymType::BuiltinType:
+ can_parse = ((type_mask & eTypeClassBuiltin) != 0);
+ break;
+ case PDB_SymType::Enum:
+ can_parse = ((type_mask & eTypeClassEnumeration) != 0);
+ break;
+ case PDB_SymType::Function:
+ case PDB_SymType::FunctionSig:
+ can_parse = ((type_mask & eTypeClassFunction) != 0);
+ break;
+ case PDB_SymType::PointerType:
+ can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer |
+ eTypeClassMemberPointer)) != 0);
+ break;
+ case PDB_SymType::Typedef:
+ can_parse = ((type_mask & eTypeClassTypedef) != 0);
+ break;
+ case PDB_SymType::UDT: {
+ auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol);
+ assert(udt);
+ can_parse = (udt->getUdtKind() != PDB_UdtType::Interface &&
+ ((type_mask & (eTypeClassClass | eTypeClassStruct |
+ eTypeClassUnion)) != 0));
+ } break;
+ default:
+ break;
+ }
+
+ if (can_parse) {
+ if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) {
+ auto result =
+ std::find(type_collection.begin(), type_collection.end(), type);
+ if (result == type_collection.end())
+ type_collection.push_back(type);
+ }
+ }
+
+ auto results_up = pdb_symbol.findAllChildren();
+ while (auto symbol_up = results_up->getNext())
+ GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection);
+}
size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
uint32_t type_mask,
lldb_private::TypeList &type_list) {
- return size_t();
+ TypeCollection type_collection;
+ uint32_t old_size = type_list.GetSize();
+ CompileUnit *cu =
+ sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr;
+ if (cu) {
+ auto compiland_up = GetPDBCompilandByUID(cu->GetID());
+ if (!compiland_up)
+ return 0;
+ GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
+ } else {
+ for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
+ auto cu_sp = ParseCompileUnitAtIndex(cu_idx);
+ if (cu_sp) {
+ if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID()))
+ GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
+ }
+ }
+ }
+
+ for (auto type : type_collection) {
+ type->GetForwardCompilerType();
+ type_list.Insert(type->shared_from_this());
+ }
+ return type_list.GetSize() - old_size;
}
lldb_private::TypeSystem *
@@ -570,65 +1474,78 @@ const IPDBSession &SymbolFilePDB::GetPDBSession() const {
return *m_session_up;
}
-lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id) {
+lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id,
+ uint32_t index) {
auto found_cu = m_comp_units.find(id);
if (found_cu != m_comp_units.end())
return found_cu->second;
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(id);
-
- // `getSourceFileName` returns the basename of the original source file used
- // to generate this compiland. It does not return the full path. Currently
- // the only way to get that is to do a basename lookup to get the
- // IPDBSourceFile, but this is ambiguous in the case of two source files with
- // the same name contributing to the same compiland. This is a moderately
- // extreme edge case, so we consider this OK for now, although we need to find
- // a long-term solution.
- auto file =
- m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(),
- PDB_NameSearchFlags::NS_CaseInsensitive);
- std::string path = file->getFileName();
+ auto compiland_up = GetPDBCompilandByUID(id);
+ if (!compiland_up)
+ return CompUnitSP();
lldb::LanguageType lang;
- auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
+ auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
if (!details)
lang = lldb::eLanguageTypeC_plus_plus;
else
lang = TranslateLanguage(details->getLanguage());
+ if (lang == lldb::LanguageType::eLanguageTypeUnknown)
+ return CompUnitSP();
+
+ std::string path = compiland_up->getSourceFileFullPath();
+ if (path.empty())
+ return CompUnitSP();
+
// Don't support optimized code for now, DebugInfoPDB does not return this
// information.
LazyBool optimized = eLazyBoolNo;
- auto result = std::make_shared<CompileUnit>(
- m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized);
- m_comp_units.insert(std::make_pair(id, result));
- return result;
+ auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr,
+ path.c_str(), id, lang, optimized);
+
+ if (!cu_sp)
+ return CompUnitSP();
+
+ m_comp_units.insert(std::make_pair(id, cu_sp));
+ if (index == UINT32_MAX)
+ GetCompileUnitIndex(*compiland_up, index);
+ lldbassert(index != UINT32_MAX);
+ m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index,
+ cu_sp);
+ return cu_sp;
}
bool SymbolFilePDB::ParseCompileUnitLineTable(
const lldb_private::SymbolContext &sc, uint32_t match_line) {
- auto global = m_session_up->getGlobalScope();
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
- sc.comp_unit->GetID());
+ lldbassert(sc.comp_unit);
+
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
+ return false;
// LineEntry needs the *index* of the file into the list of support files
// returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us
- // a globally unique idenfitifier in the namespace of the PDB. So, we have to
- // do a mapping so that we can hand out indices.
+ // a globally unique idenfitifier in the namespace of the PDB. So, we have
+ // to do a mapping so that we can hand out indices.
llvm::DenseMap<uint32_t, uint32_t> index_map;
- BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
+ BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map);
auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
- // Find contributions to `cu` from all source and header files.
+ // Find contributions to `compiland` from all source and header files.
std::string path = sc.comp_unit->GetPath();
- auto files = m_session_up->getSourceFilesForCompiland(*cu);
+ auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
+ if (!files)
+ return false;
- // For each source and header file, create a LineSequence for contributions to
- // the cu from that file, and add the sequence.
+ // For each source and header file, create a LineSequence for contributions
+ // to the compiland from that file, and add the sequence.
while (auto file = files->getNext()) {
std::unique_ptr<LineSequence> sequence(
line_table->CreateLineSequenceContainer());
- auto lines = m_session_up->findLineNumbers(*cu, *file);
+ auto lines = m_session_up->findLineNumbers(*compiland_up, *file);
+ if (!lines)
+ continue;
int entry_count = lines->getChildCount();
uint64_t prev_addr;
@@ -646,8 +1563,8 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
uint32_t col = line->getColumnNumber();
uint32_t source_idx = index_map[source_id];
- // There was a gap between the current entry and the previous entry if the
- // addresses don't perfectly line up.
+ // There was a gap between the current entry and the previous entry if
+ // the addresses don't perfectly line up.
bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
// Before inserting the current entry, insert a terminal entry at the end
@@ -657,6 +1574,9 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
line_table->AppendLineEntryToSequence(
sequence.get(), prev_addr + prev_length, prev_line, 0,
prev_source_idx, false, false, false, false, true);
+
+ line_table->InsertSequence(sequence.release());
+ sequence.reset(line_table->CreateLineSequenceContainer());
}
if (ShouldAddLine(match_line, lno, length)) {
@@ -667,10 +1587,12 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
if (func) {
auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
- is_prologue = (addr == prologue->getVirtualAddress());
+ if (prologue)
+ is_prologue = (addr == prologue->getVirtualAddress());
auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
- is_epilogue = (addr == epilogue->getVirtualAddress());
+ if (epilogue)
+ is_epilogue = (addr == epilogue->getVirtualAddress());
}
line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
@@ -694,23 +1616,134 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
line_table->InsertSequence(sequence.release());
}
- sc.comp_unit->SetLineTable(line_table.release());
- return true;
+ if (line_table->GetSize()) {
+ sc.comp_unit->SetLineTable(line_table.release());
+ return true;
+ }
+ return false;
}
void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
- const PDBSymbolCompiland &cu,
+ const PDBSymbolCompiland &compiland,
llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
- // This is a hack, but we need to convert the source id into an index into the
- // support files array. We don't want to do path comparisons to avoid
+ // This is a hack, but we need to convert the source id into an index into
+ // the support files array. We don't want to do path comparisons to avoid
// basename / full path issues that may or may not even be a problem, so we
// use the globally unique source file identifiers. Ideally we could use the
// global identifiers everywhere, but LineEntry currently assumes indices.
- auto source_files = m_session_up->getSourceFilesForCompiland(cu);
- int index = 0;
+ auto source_files = m_session_up->getSourceFilesForCompiland(compiland);
+ if (!source_files)
+ return;
+
+ // LLDB uses the DWARF-like file numeration (one based)
+ int index = 1;
while (auto file = source_files->getNext()) {
uint32_t source_id = file->getUniqueId();
index_map[source_id] = index++;
}
}
+
+lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress(
+ const lldb_private::Address &so_addr) {
+ lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ return nullptr;
+
+ // If it is a PDB function's vm addr, this is the first sure bet.
+ if (auto lines =
+ m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) {
+ if (auto first_line = lines->getNext())
+ return ParseCompileUnitForUID(first_line->getCompilandId());
+ }
+
+ // Otherwise we resort to section contributions.
+ if (auto sec_contribs = m_session_up->getSectionContribs()) {
+ while (auto section = sec_contribs->getNext()) {
+ auto va = section->getVirtualAddress();
+ if (file_vm_addr >= va && file_vm_addr < va + section->getLength())
+ return ParseCompileUnitForUID(section->getCompilandId());
+ }
+ }
+ return nullptr;
+}
+
+Mangled
+SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) {
+ Mangled mangled;
+ auto func_name = pdb_func.getName();
+ auto func_undecorated_name = pdb_func.getUndecoratedName();
+ std::string func_decorated_name;
+
+ // Seek from public symbols for non-static function's decorated name if any.
+ // For static functions, they don't have undecorated names and aren't exposed
+ // in Public Symbols either.
+ if (!func_undecorated_name.empty()) {
+ auto result_up = m_global_scope_up->findChildren(
+ PDB_SymType::PublicSymbol, func_undecorated_name,
+ PDB_NameSearchFlags::NS_UndecoratedName);
+ if (result_up) {
+ while (auto symbol_up = result_up->getNext()) {
+ // For a public symbol, it is unique.
+ lldbassert(result_up->getChildCount() == 1);
+ if (auto *pdb_public_sym =
+ llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>(
+ symbol_up.get())) {
+ if (pdb_public_sym->isFunction()) {
+ func_decorated_name = pdb_public_sym->getName();
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!func_decorated_name.empty()) {
+ mangled.SetMangledName(ConstString(func_decorated_name));
+
+ // For MSVC, format of C funciton's decorated name depends on calling
+ // conventon. Unfortunately none of the format is recognized by current
+ // LLDB. For example, `_purecall` is a __cdecl C function. From PDB,
+ // `__purecall` is retrieved as both its decorated and undecorated name
+ // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall`
+ // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix).
+ // Mangled::GetDemangledName method will fail internally and caches an
+ // empty string as its undecorated name. So we will face a contradition
+ // here for the same symbol:
+ // non-empty undecorated name from PDB
+ // empty undecorated name from LLDB
+ if (!func_undecorated_name.empty() &&
+ mangled.GetDemangledName(mangled.GuessLanguage()).IsEmpty())
+ mangled.SetDemangledName(ConstString(func_undecorated_name));
+
+ // LLDB uses several flags to control how a C++ decorated name is
+ // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the
+ // yielded name could be different from what we retrieve from
+ // PDB source unless we also apply same flags in getting undecorated
+ // name through PDBSymbolFunc::getUndecoratedNameEx method.
+ if (!func_undecorated_name.empty() &&
+ mangled.GetDemangledName(mangled.GuessLanguage()) !=
+ ConstString(func_undecorated_name))
+ mangled.SetDemangledName(ConstString(func_undecorated_name));
+ } else if (!func_undecorated_name.empty()) {
+ mangled.SetDemangledName(ConstString(func_undecorated_name));
+ } else if (!func_name.empty())
+ mangled.SetValue(ConstString(func_name), false);
+
+ return mangled;
+}
+
+bool SymbolFilePDB::DeclContextMatchesThisSymbolFile(
+ const lldb_private::CompilerDeclContext *decl_ctx) {
+ if (decl_ctx == nullptr || !decl_ctx->IsValid())
+ return true;
+
+ TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem();
+ if (!decl_ctx_type_system)
+ return false;
+ TypeSystem *type_system = GetTypeSystemForLanguage(
+ decl_ctx_type_system->GetMinimumLanguage(nullptr));
+ if (decl_ctx_type_system == type_system)
+ return true; // The type systems match, return true
+
+ return false;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index eef96be8d1fe..96b62d68a6c2 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -10,12 +10,15 @@
#ifndef lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
#define lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
+#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Utility/UserID.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
class SymbolFilePDB : public lldb_private::SymbolFile {
public:
@@ -108,11 +111,11 @@ public:
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t
@@ -141,8 +144,7 @@ public:
bool append, lldb_private::TypeMap &types) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,
- uint32_t max_matches,
- lldb_private::TypeMap &types);
+ uint32_t max_matches, lldb_private::TypeMap &types);
lldb_private::TypeList *GetTypeList() override;
@@ -167,25 +169,76 @@ public:
const llvm::pdb::IPDBSession &GetPDBSession() const;
private:
- lldb::CompUnitSP ParseCompileUnitForSymIndex(uint32_t id);
+ lldb::CompUnitSP ParseCompileUnitForUID(uint32_t id,
+ uint32_t index = UINT32_MAX);
bool ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc,
uint32_t match_line);
void BuildSupportFileIdToSupportFileIndexMap(
- const llvm::pdb::PDBSymbolCompiland &cu,
+ const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
llvm::DenseMap<uint32_t, uint32_t> &index_map) const;
void FindTypesByName(const std::string &name, uint32_t max_matches,
lldb_private::TypeMap &types);
+ std::string GetMangledForPDBData(const llvm::pdb::PDBSymbolData &pdb_data);
+
+ lldb::VariableSP
+ ParseVariableForPDBData(const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbolData &pdb_data);
+
+ size_t ParseVariables(const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbol &pdb_data,
+ lldb_private::VariableList *variable_list = nullptr);
+
+ lldb::CompUnitSP
+ GetCompileUnitContainsAddress(const lldb_private::Address &so_addr);
+
+ typedef std::vector<lldb_private::Type *> TypeCollection;
+
+ void GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
+ uint32_t type_mask,
+ TypeCollection &type_collection);
+
+ lldb_private::Function *
+ ParseCompileUnitFunctionForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func,
+ const lldb_private::SymbolContext &sc);
+
+ void GetCompileUnitIndex(const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
+ uint32_t &index);
+
+ std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
+ GetPDBCompilandByUID(uint32_t uid);
+
+ lldb_private::Mangled
+ GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func);
+
+ bool ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list);
+
+ bool ResolveFunction(uint32_t uid, bool include_inlines,
+ lldb_private::SymbolContextList &sc_list);
+
+ void CacheFunctionNames();
+
+ bool DeclContextMatchesThisSymbolFile(
+ const lldb_private::CompilerDeclContext *decl_ctx);
+
llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units;
llvm::DenseMap<uint32_t, lldb::TypeSP> m_types;
+ llvm::DenseMap<uint32_t, lldb::VariableSP> m_variables;
std::vector<lldb::TypeSP> m_builtin_types;
std::unique_ptr<llvm::pdb::IPDBSession> m_session_up;
+ std::unique_ptr<llvm::pdb::PDBSymbolExe> m_global_scope_up;
uint32_t m_cached_compile_unit_count;
std::unique_ptr<lldb_private::CompilerDeclContext> m_tu_decl_ctx_up;
+
+ lldb_private::UniqueCStringMap<uint32_t> m_func_full_names;
+ lldb_private::UniqueCStringMap<uint32_t> m_func_base_names;
+ lldb_private::UniqueCStringMap<uint32_t> m_func_method_names;
};
#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index dbc1b9ee5470..64e2daf60ee5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -63,9 +63,9 @@ uint32_t SymbolFileSymtab::CalculateAbilities() {
const Symtab *symtab = m_obj_file->GetSymtab();
if (symtab) {
//----------------------------------------------------------------------
- // The snippet of code below will get the indexes the module symbol
- // table entries that are code, data, or function related (debug info),
- // sort them by value (address) and dump the sorted symbols.
+ // The snippet of code below will get the indexes the module symbol table
+ // entries that are code, data, or function related (debug info), sort
+ // them by value (address) and dump the sorted symbols.
//----------------------------------------------------------------------
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile,
m_source_indexes)) {
@@ -105,24 +105,21 @@ uint32_t SymbolFileSymtab::CalculateAbilities() {
}
uint32_t SymbolFileSymtab::GetNumCompileUnits() {
- // If we don't have any source file symbols we will just have one compile unit
- // for
- // the entire object file
+ // If we don't have any source file symbols we will just have one compile
+ // unit for the entire object file
if (m_source_indexes.empty())
return 0;
// If we have any source file symbols we will logically organize the object
- // symbols
- // using these.
+ // symbols using these.
return m_source_indexes.size();
}
CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) {
CompUnitSP cu_sp;
- // If we don't have any source file symbols we will just have one compile unit
- // for
- // the entire object file
+ // If we don't have any source file symbols we will just have one compile
+ // unit for the entire object file
if (idx < m_source_indexes.size()) {
const Symbol *cu_symbol =
m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
@@ -152,13 +149,12 @@ size_t SymbolFileSymtab::ParseCompileUnitFunctions(const SymbolContext &sc) {
//
// const uint32_t prefix_len = strlen(prefix);
- // If we don't have any source file symbols we will just have one compile unit
- // for
- // the entire object file
+ // If we don't have any source file symbols we will just have one compile
+ // unit for the entire object file
if (m_source_indexes.empty()) {
- // The only time we will have a user ID of zero is when we don't have
- // and source file symbols and we declare one compile unit for the
- // entire object file
+ // The only time we will have a user ID of zero is when we don't have and
+ // source file symbols and we declare one compile unit for the entire
+ // object file
if (!m_func_indexes.empty()) {
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index a25119684c28..d24510966878 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -57,9 +57,9 @@ const char *SymbolVendorELF::GetPluginDescriptionStatic() {
//----------------------------------------------------------------------
// CreateInstance
//
-// Platforms can register a callback to use when creating symbol
-// vendors to allow for complex debug information file setups, and to
-// also allow for finding separate debug information files.
+// Platforms can register a callback to use when creating symbol vendors to
+// allow for complex debug information file setups, and to also allow for
+// finding separate debug information files.
//----------------------------------------------------------------------
SymbolVendor *
SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
@@ -112,11 +112,9 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(),
dsym_file_data_sp, dsym_file_data_offset);
if (dsym_objfile_sp) {
- // This objfile is for debugging purposes. Sadly, ObjectFileELF won't be
- // able
- // to figure this out consistently as the symbol file may not have
- // stripped the
- // code sections, etc.
+ // This objfile is for debugging purposes. Sadly, ObjectFileELF won't
+ // be able to figure this out consistently as the symbol file may not
+ // have stripped the code sections, etc.
dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);
SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp);
@@ -134,7 +132,7 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable,
+ eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,
};
for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
++idx) {
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index f8aca4d1283b..54e182b30b6f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/DumpDataExtractor.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/ExecutionContext.h"
@@ -58,8 +59,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid() &&
m_inst_emulator_ap.get()) {
- // The instruction emulation subclass setup the unwind plan for the
- // first instruction.
+ // The instruction emulation subclass setup the unwind plan for the first
+ // instruction.
m_inst_emulator_ap->CreateFunctionEntryUnwind(unwind_plan);
// CreateFunctionEntryUnwind should have created the first row. If it
@@ -90,9 +91,9 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
m_register_values.clear();
m_pushed_regs.clear();
- // Initialize the CFA with a known value. In the 32 bit case
- // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
- // We use the address byte size to be safe for any future address sizes
+ // Initialize the CFA with a known value. In the 32 bit case it will be
+ // 0x80000000, and in the 64 bit case 0x8000000000000000. We use the
+ // address byte size to be safe for any future address sizes
m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
RegisterValue cfa_reg_value;
cfa_reg_value.SetUInt(m_initial_sp, m_cfa_reg_info.byte_size);
@@ -105,14 +106,12 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
Instruction *inst = inst_list.GetInstructionAtIndex(0).get();
const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress();
- // Map for storing the unwind plan row and the value of the registers at
- // a given offset.
- // When we see a forward branch we add a new entry to this map with the
- // actual unwind plan
- // row and register context for the target address of the branch as the
- // current data have
- // to be valid for the target address of the branch too if we are in the
- // same function.
+ // Map for storing the unwind plan row and the value of the registers
+ // at a given offset. When we see a forward branch we add a new entry
+ // to this map with the actual unwind plan row and register context for
+ // the target address of the branch as the current data have to be
+ // valid for the target address of the branch too if we are in the same
+ // function.
std::map<lldb::addr_t, std::pair<UnwindPlan::RowSP, RegisterValueMap>>
saved_unwind_states;
@@ -128,15 +127,14 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
saved_unwind_states.insert({0, {last_row, m_register_values}});
// cache the pc register number (in whatever register numbering this
- // UnwindPlan uses) for
- // quick reference during instruction parsing.
+ // UnwindPlan uses) for quick reference during instruction parsing.
RegisterInfo pc_reg_info;
m_inst_emulator_ap->GetRegisterInfo(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info);
// cache the return address register number (in whatever register
- // numbering this UnwindPlan uses) for
- // quick reference during instruction parsing.
+ // numbering this UnwindPlan uses) for quick reference during
+ // instruction parsing.
RegisterInfo ra_reg_info;
m_inst_emulator_ap->GetRegisterInfo(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info);
@@ -160,12 +158,11 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
"Unwind row for the function entry missing");
--it; // Move it to the row corresponding to the current offset
- // If the offset of m_curr_row don't match with the offset we see in
- // saved_unwind_states
- // then we have to update m_curr_row and m_register_values based on
- // the saved values. It
- // is happenning after we processed an epilogue and a return to
- // caller instruction.
+ // If the offset of m_curr_row don't match with the offset we see
+ // in saved_unwind_states then we have to update m_curr_row and
+ // m_register_values based on the saved values. It is happening
+ // after we processed an epilogue and a return to caller
+ // instruction.
if (it->second.first->GetOffset() != m_curr_row->GetOffset()) {
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *it->second.first;
@@ -181,10 +178,9 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
if (m_inst_emulator_ap->GetInstructionCondition() !=
EmulateInstruction::UnconditionalCondition &&
saved_unwind_states.count(current_offset) == 0) {
- // If we don't have a saved row for the current offset then save
- // our
- // current state because we will have to restore it after the
- // conditional block.
+ // If we don't have a saved row for the current offset then
+ // save our current state because we will have to restore it
+ // after the conditional block.
auto new_row =
std::make_shared<UnwindPlan::Row>(*m_curr_row.get());
saved_unwind_states.insert(
@@ -192,8 +188,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
}
// If the last instruction was conditional with a different
- // condition
- // then the then current condition then restore the condition.
+ // condition then the then current condition then restore the
+ // condition.
if (last_condition !=
EmulateInstruction::UnconditionalCondition) {
const auto &saved_state =
@@ -211,7 +207,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
replace_existing);
}
- // We are starting a new conditional block at the catual offset
+ // We are starting a new conditional block at the actual offset
condition_block_start_offset = current_offset;
}
@@ -230,8 +226,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
eEmulateInstructionOptionIgnoreConditions);
// If the current instruction is a branch forward then save the
- // current CFI information
- // for the offset where we are branching.
+ // current CFI information for the offset where we are branching.
if (m_forward_branch_offset != 0 &&
range.ContainsFileAddress(inst->GetAddress().GetFileAddress() +
m_forward_branch_offset)) {
@@ -247,8 +242,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
// Were there any changes to the CFI while evaluating this
// instruction?
if (m_curr_row_modified) {
- // Save the modified row if we don't already have a CFI row in the
- // currennt address
+ // Save the modified row if we don't already have a CFI row in
+ // the current address
if (saved_unwind_states.count(
current_offset + inst->GetOpcode().GetByteSize()) == 0) {
m_curr_row->SetOffset(current_offset +
@@ -492,7 +487,7 @@ bool UnwindAssemblyInstEmulation::ReadRegister(EmulateInstruction *instruction,
strm.Printf("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => "
"synthetic_value = %i, value = ",
reg_info->name, synthetic);
- reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+ DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
log->PutString(strm.GetString());
}
return true;
@@ -518,7 +513,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
strm.Printf(
"UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ",
reg_info->name);
- reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+ DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
strm.PutCString(", context = ");
context.Dump(strm, instruction);
log->PutString(strm.GetString());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index b8dcd99a53e7..327d0b0e4f71 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -86,12 +86,10 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
LLDB_REGNUM_GENERIC_PC);
// Does this UnwindPlan describe the prologue? I want to see that the CFA is
- // set
- // in terms of the stack pointer plus an offset, and I want to see that rip is
- // retrieved at the CFA-wordsize.
- // If there is no description of the prologue, don't try to augment this
- // eh_frame
- // unwinder code, fall back to assembly parsing instead.
+ // set in terms of the stack pointer plus an offset, and I want to see that
+ // rip is retrieved at the CFA-wordsize. If there is no description of the
+ // prologue, don't try to augment this eh_frame unwinder code, fall back to
+ // assembly parsing instead.
if (first_row->GetCFAValue().GetValueType() !=
UnwindPlan::Row::CFAValue::isRegisterPlusOffset ||
@@ -110,14 +108,13 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
return false;
}
- // It looks like the prologue is described.
- // Is the epilogue described? If it is, no need to do any augmentation.
+ // It looks like the prologue is described. Is the epilogue described? If it
+ // is, no need to do any augmentation.
if (first_row != last_row &&
first_row->GetOffset() != last_row->GetOffset()) {
- // The first & last row have the same CFA register
- // and the same CFA offset value
- // and the CFA register is esp/rsp (the stack pointer).
+ // The first & last row have the same CFA register and the same CFA offset
+ // value and the CFA register is esp/rsp (the stack pointer).
// We're checking that both of them have an unwind rule like "CFA=esp+4" or
// CFA+rsp+8".
@@ -128,8 +125,8 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
last_row->GetCFAValue().GetRegisterNumber() &&
first_row->GetCFAValue().GetOffset() ==
last_row->GetCFAValue().GetOffset()) {
- // Get the register locations for eip/rip from the first & last rows.
- // Are they both CFA plus an offset? Is it the same offset?
+ // Get the register locations for eip/rip from the first & last rows. Are
+ // they both CFA plus an offset? Is it the same offset?
UnwindPlan::Row::RegisterLocation last_row_pc_loc;
if (last_row->GetRegisterInfo(
@@ -139,12 +136,10 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
first_row_pc_loc.GetOffset() == last_row_pc_loc.GetOffset()) {
// One last sanity check: Is the unwind rule for getting the caller
- // pc value
- // "deref the CFA-4" or "deref the CFA-8"?
+ // pc value "deref the CFA-4" or "deref the CFA-8"?
// If so, we have an UnwindPlan that already describes the epilogue
- // and we don't need
- // to modify it at all.
+ // and we don't need to modify it at all.
if (first_row_pc_loc.GetOffset() == -wordsize) {
do_augment_unwindplan = false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index aa15063ac0dc..10a56980594f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -246,8 +246,7 @@ void x86AssemblyInspectionEngine::Initialize(
}
// This function expects an x86 native register number (i.e. the bits stripped
-// out of the
-// actual instruction), not an lldb register number.
+// out of the actual instruction), not an lldb register number.
//
// FIXME: This is ABI dependent, it shouldn't be hardcoded here.
@@ -321,15 +320,14 @@ bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
// pushl imm8(%esp)
//
-// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)'
-// (same byte pattern for 'pushq 0x20(%rsp)' in an x86_64 program)
+// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' (same byte pattern for 'pushq
+// 0x20(%rsp)' in an x86_64 program)
//
-// 0xff (with opcode bits '6' in next byte, PUSH r/m32)
-// 0x74 (ModR/M byte with three bits used to specify the opcode)
+// 0xff (with opcode bits '6' in next byte, PUSH r/m32) 0x74 (ModR/M byte with
+// three bits used to specify the opcode)
// mod == b01, opcode == b110, R/M == b100
// "+disp8"
-// 0x24 (SIB byte - scaled index = 0, r32 == esp)
-// 0x20 imm8 value
+// 0x24 (SIB byte - scaled index = 0, r32 == esp) 0x20 imm8 value
bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
if (*m_cur_insn == 0xff) {
@@ -337,9 +335,8 @@ bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
if (opcode == 6) {
// I'm only looking for 0xff /6 here - I
- // don't really care what value is being pushed,
- // just that we're pushing a 32/64 bit value on
- // to the stack is enough.
+ // don't really care what value is being pushed, just that we're pushing
+ // a 32/64 bit value on to the stack is enough.
return true;
}
}
@@ -377,8 +374,8 @@ bool x86AssemblyInspectionEngine::push_reg_p(int &regno) {
return false;
}
-// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
-// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
+// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] movl %esp, %ebp [0x8b
+// 0xec] or [0x89 0xe5]
bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
uint8_t *p = m_cur_insn;
if (m_wordsize == 8 && *p == 0x48)
@@ -529,16 +526,16 @@ bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() {
(*(p + 3) == 0x0) && (*(p + 4) == 0x0);
}
-// Look for an instruction sequence storing a nonvolatile register
-// on to the stack frame.
+// Look for an instruction sequence storing a nonvolatile register on to the
+// stack frame.
// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
-// The offset value returned in rbp_offset will be positive --
-// but it must be subtraced from the frame base register to get
-// the actual location. The positive value returned for the offset
-// is a convention used elsewhere for CFA offsets et al.
+// The offset value returned in rbp_offset will be positive -- but it must be
+// subtraced from the frame base register to get the actual location. The
+// positive value returned for the offset is a convention used elsewhere for
+// CFA offsets et al.
bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
int &regno, int &rbp_offset) {
@@ -550,8 +547,8 @@ bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
src_reg_prefix_bit = REX_W_SRCREG(*p) << 3;
target_reg_prefix_bit = REX_W_DSTREG(*p) << 3;
if (target_reg_prefix_bit == 1) {
- // rbp/ebp don't need a prefix bit - we know this isn't the
- // reg we care about.
+ // rbp/ebp don't need a prefix bit - we know this isn't the reg we care
+ // about.
return false;
}
p++;
@@ -671,18 +668,16 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
*newrow = *row.get();
row.reset(newrow);
- // Track which registers have been saved so far in the prologue.
- // If we see another push of that register, it's not part of the prologue.
- // The register numbers used here are the machine register #'s
- // (i386_register_numbers, x86_64_register_numbers).
+ // Track which registers have been saved so far in the prologue. If we see
+ // another push of that register, it's not part of the prologue. The register
+ // numbers used here are the machine register #'s (i386_register_numbers,
+ // x86_64_register_numbers).
std::vector<bool> saved_registers(32, false);
// Once the prologue has completed we'll save a copy of the unwind
- // instructions
- // If there is an epilogue in the middle of the function, after that epilogue
- // we'll reinstate
- // the unwind setup -- we assume that some code path jumps over the
- // mid-function epilogue
+ // instructions If there is an epilogue in the middle of the function, after
+ // that epilogue we'll reinstate the unwind setup -- we assume that some code
+ // path jumps over the mid-function epilogue
UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
@@ -723,9 +718,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
// This is the start() function (or a pthread equivalent), it starts with a
- // pushl $0x0 which puts the
- // saved pc value of 0 on the stack. In this case we want to pretend we
- // didn't see a stack movement at all --
+ // pushl $0x0 which puts the saved pc value of 0 on the stack. In this
+ // case we want to pretend we didn't see a stack movement at all --
// normally the saved pc value is already on the stack by the time the
// function starts executing.
else if (push_0_pattern_p()) {
@@ -733,9 +727,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
else if (push_reg_p(machine_regno)) {
current_sp_bytes_offset_from_cfa += m_wordsize;
- // the PUSH instruction has moved the stack pointer - if the CFA is set in
- // terms of the stack pointer,
- // we need to add a new row of instructions.
+ // the PUSH instruction has moved the stack pointer - if the CFA is set
+ // in terms of the stack pointer, we need to add a new row of
+ // instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
row_updated = true;
@@ -772,8 +766,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
// the POP instruction has moved the stack pointer - if the CFA is set in
- // terms of the stack pointer,
- // we need to add a new row of instructions.
+ // terms of the stack pointer, we need to add a new row of instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
row->GetCFAValue().SetIsRegisterPlusOffset(
m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
@@ -790,13 +783,13 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
}
- // The LEAVE instruction moves the value from rbp into rsp and pops
- // a value off the stack into rbp (restoring the caller's rbp value).
- // It is the opposite of ENTER, or 'push rbp, mov rsp rbp'.
+ // The LEAVE instruction moves the value from rbp into rsp and pops a value
+ // off the stack into rbp (restoring the caller's rbp value). It is the
+ // opposite of ENTER, or 'push rbp, mov rsp rbp'.
else if (leave_pattern_p()) {
// We're going to copy the value in rbp into rsp, so re-set the sp offset
- // based on the CFAValue. Also, adjust it to recognize that we're popping
- // the saved rbp value off the stack.
+ // based on the CFAValue. Also, adjust it to recognize that we're
+ // popping the saved rbp value off the stack.
current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
current_sp_bytes_offset_from_cfa -= m_wordsize;
row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
@@ -822,12 +815,11 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::Row::RegisterLocation regloc;
- // stack_offset for 'movq %r15, -80(%rbp)' will be 80.
- // In the Row, we want to express this as the offset from the CFA. If the
- // frame base
- // is rbp (like the above instruction), the CFA offset for rbp is probably
- // 16. So we
- // want to say that the value is stored at the CFA address - 96.
+ // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
+ // want to express this as the offset from the CFA. If the frame base is
+ // rbp (like the above instruction), the CFA offset for rbp is probably
+ // 16. So we want to say that the value is stored at the CFA address -
+ // 96.
regloc.SetAtCFAPlusOffset(
-(stack_offset + row->GetCFAValue().GetOffset()));
@@ -879,8 +871,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (ret_pattern_p() && prologue_completed_row.get()) {
- // Reinstate the saved prologue setup for any instructions
- // that come after the ret instruction
+ // Reinstate the saved prologue setup for any instructions that come
+ // after the ret instruction
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *prologue_completed_row.get();
@@ -960,16 +952,15 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
if (!addr_start.IsValid())
return false;
- // We either need a live RegisterContext, or we need the UnwindPlan to already
- // be in the lldb register numbering scheme.
+ // We either need a live RegisterContext, or we need the UnwindPlan to
+ // already be in the lldb register numbering scheme.
if (reg_ctx.get() == nullptr &&
unwind_plan.GetRegisterKind() != eRegisterKindLLDB)
return false;
// Is original unwind_plan valid?
- // unwind_plan should have at least one row which is ABI-default (CFA register
- // is sp),
- // and another row in mid-function.
+ // unwind_plan should have at least one row which is ABI-default (CFA
+ // register is sp), and another row in mid-function.
if (unwind_plan.GetRowCount() < 2)
return false;
@@ -994,11 +985,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
m_cur_insn = data + offset;
- // After a mid-function epilogue we will need to re-insert the original unwind
- // rules
- // so unwinds work for the remainder of the function. These aren't common
- // with clang/gcc
- // on x86 but it is possible.
+ // After a mid-function epilogue we will need to re-insert the original
+ // unwind rules so unwinds work for the remainder of the function. These
+ // aren't common with clang/gcc on x86 but it is possible.
bool reinstate_unwind_state = false;
while (offset < size) {
@@ -1015,8 +1004,7 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
offset += insn_len;
m_cur_insn = data + offset;
- // offset is pointing beyond the bounds of the
- // function; stop looping.
+ // offset is pointing beyond the bounds of the function; stop looping.
if (offset >= size)
continue;
@@ -1044,9 +1032,8 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
}
if (row_id == 0) {
- // If we are here, compiler didn't generate CFI for prologue.
- // This won't happen to GCC or clang.
- // In this case, bail out directly.
+ // If we are here, compiler didn't generate CFI for prologue. This won't
+ // happen to GCC or clang. In this case, bail out directly.
return false;
}
@@ -1086,10 +1073,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
}
if (pop_reg_p(regno)) {
// Technically, this might be a nonvolatile register recover in
- // epilogue.
- // We should reset RegisterInfo for the register.
- // But in practice, previous rule for the register is still valid...
- // So we ignore this case.
+ // epilogue. We should reset RegisterInfo for the register. But in
+ // practice, previous rule for the register is still valid... So we
+ // ignore this case.
row->SetOffset(offset);
row->GetCFAValue().IncOffset(-m_wordsize);
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
index 4da307bf0c32..6dcad62f2f9d 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
@@ -65,17 +65,16 @@ ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx,
}
// Sort the entries in the exidx section. The entries should be sorted inside
- // the section but
- // some old compiler isn't sorted them.
+ // the section but some old compiler isn't sorted them.
std::sort(m_exidx_entries.begin(), m_exidx_entries.end());
}
ArmUnwindInfo::~ArmUnwindInfo() {}
-// Read a byte from the unwind instruction stream with the given offset.
-// Custom function is required because have to red in order of significance
-// within their containing
-// word (most significant byte first) and in increasing word address order.
+// Read a byte from the unwind instruction stream with the given offset. Custom
+// function is required because have to red in order of significance within
+// their containing word (most significant byte first) and in increasing word
+// address order.
uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data,
uint16_t offset) const {
uint32_t value = data[offset / 4];
@@ -276,8 +275,8 @@ bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr,
return false;
} else if ((byte1 & 0xff) == 0xc8) {
// 11001000 sssscccc
- // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as
- // if) by FSTMFDD (see remarks d,e)
+ // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved
+ // (as if) by FSTMFDD (see remarks d,e)
if (byte_offset >= byte_count)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Block.cpp b/contrib/llvm/tools/lldb/source/Symbol/Block.cpp
index 648d8ee48bf5..46f875fca776 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Block.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Block.cpp
@@ -60,8 +60,7 @@ void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
if (depth < 0) {
Block *parent = GetParent();
if (parent) {
- // We have a depth that is less than zero, print our parent blocks
- // first
+ // We have a depth that is less than zero, print our parent blocks first
parent->Dump(s, base_addr, depth + 1, show_context);
}
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp
index 5fa4060ce72c..a7578de0dcac 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp
@@ -140,8 +140,8 @@ static ClangASTMap &GetASTMap() {
return *g_map_ptr;
}
-static bool IsOperator(const char *name,
- clang::OverloadedOperatorKind &op_kind) {
+bool ClangASTContext::IsOperator(const char *name,
+ clang::OverloadedOperatorKind &op_kind) {
if (name == nullptr || name[0] == '\0')
return false;
@@ -165,8 +165,8 @@ static bool IsOperator(const char *name,
#undef OPERATOR_PREFIX
#undef OPERATOR_PREFIX_LENGTH
- // This is an operator, set the overloaded operator kind to invalid
- // in case this is a conversion operator...
+ // This is an operator, set the overloaded operator kind to invalid in case
+ // this is a conversion operator...
op_kind = clang::NUM_OVERLOADED_OPERATORS;
switch (post_op_name[0]) {
@@ -377,9 +377,9 @@ ClangASTContext::ConvertAccessTypeToAccessSpecifier(AccessType access) {
static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
// FIXME: Cleanup per-file based stuff.
- // Set some properties which depend solely on the input kind; it would be nice
- // to move these to the language standard, and have the driver resolve the
- // input kind + language standard.
+ // Set some properties which depend solely on the input kind; it would be
+ // nice to move these to the language standard, and have the driver resolve
+ // the input kind + language standard.
if (IK.getLanguage() == InputKind::Asm) {
Opts.AsmPreprocessor = 1;
} else if (IK.isObjectiveC()) {
@@ -410,6 +410,9 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
case InputKind::ObjCXX:
LangStd = LangStandard::lang_gnucxx98;
break;
+ case InputKind::HIP:
+ LangStd = LangStandard::lang_hip;
+ break;
}
}
@@ -439,8 +442,8 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
Opts.setValueVisibilityMode(DefaultVisibility);
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
- // is specified, or -std is set to a conforming mode.
+ // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs is
+ // specified, or -std is set to a conforming mode.
Opts.Trigraphs = !Opts.GNUMode;
Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault();
Opts.OptimizeSize = 0;
@@ -661,8 +664,8 @@ ASTContext *ClangASTContext::getASTContext() {
m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false);
// This can be NULL if we don't know anything about the architecture or if
- // the
- // target for an architecture isn't enabled in the llvm/clang that we built
+ // the target for an architecture isn't enabled in the llvm/clang that we
+ // built
TargetInfo *target_info = getTargetInfo();
if (target_info)
m_ast_ap->InitBuiltinTypes(*target_info);
@@ -1253,8 +1256,8 @@ CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) {
}
CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) {
- // No need to call the getASTContext() accessor (which can create the AST
- // if it isn't created yet, because we can't have created a decl in this
+ // No need to call the getASTContext() accessor (which can create the AST if
+ // it isn't created yet, because we can't have created a decl in this
// AST if our AST didn't already exist...
ASTContext *ast = &decl->getASTContext();
if (ast)
@@ -1263,8 +1266,8 @@ CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) {
}
CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) {
- // No need to call the getASTContext() accessor (which can create the AST
- // if it isn't created yet, because we can't have created a decl in this
+ // No need to call the getASTContext() accessor (which can create the AST if
+ // it isn't created yet, because we can't have created a decl in this
// AST if our AST didn't already exist...
ASTContext *ast = &decl->getASTContext();
if (ast)
@@ -1293,9 +1296,9 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
}
// NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
- // we will need to update this code. I was told to currently always use
- // the CXXRecordDecl class since we often don't know from debug information
- // if something is struct or a class, so we default to always use the more
+ // we will need to update this code. I was told to currently always use the
+ // CXXRecordDecl class since we often don't know from debug information if
+ // something is struct or a class, so we default to always use the more
// complete definition just in case.
bool is_anonymous = (!name) || (!name[0]);
@@ -1390,7 +1393,7 @@ static TemplateParameterList *CreateTemplateParameterList(
clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl(
clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl,
const char *name, const TemplateParameterInfos &template_param_infos) {
- // /// \brief Create a function template node.
+ // /// Create a function template node.
ASTContext *ast = getASTContext();
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
@@ -1484,6 +1487,29 @@ ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl(
return class_template_decl;
}
+TemplateTemplateParmDecl *
+ClangASTContext::CreateTemplateTemplateParmDecl(const char *template_name) {
+ ASTContext *ast = getASTContext();
+
+ auto *decl_ctx = ast->getTranslationUnitDecl();
+
+ IdentifierInfo &identifier_info = ast->Idents.get(template_name);
+ llvm::SmallVector<NamedDecl *, 8> template_param_decls;
+
+ ClangASTContext::TemplateParameterInfos template_param_infos;
+ TemplateParameterList *template_param_list = CreateTemplateParameterList(
+ ast, template_param_infos, template_param_decls);
+
+ // LLDB needs to create those decls only to be able to display a
+ // type that includes a template template argument. Only the name matters for
+ // this purpose, so we use dummy values for the other characterisitcs of the
+ // type.
+ return TemplateTemplateParmDecl::Create(
+ *ast, decl_ctx, SourceLocation(),
+ /*Depth*/ 0, /*Position*/ 0,
+ /*IsParameterPack*/ false, &identifier_info, template_param_list);
+}
+
ClassTemplateSpecializationDecl *
ClangASTContext::CreateClassTemplateSpecializationDecl(
DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
@@ -1625,7 +1651,7 @@ bool ClangASTContext::RecordHasFields(const RecordDecl *record_decl) {
return false;
}
-#pragma mark Objective C Classes
+#pragma mark Objective-C Classes
CompilerType ClangASTContext::CreateObjCClass(const char *name,
DeclContext *decl_ctx,
@@ -1909,11 +1935,10 @@ ClangASTContext::GetDeclarationName(const char *name,
return DeclarationName(&getASTContext()->Idents.get(
name)); // Not operator, but a regular function.
- // Check the number of operator parameters. Sometimes we have
- // seen bad DWARF that doesn't correctly describe operators and
- // if we try to create a method and add it to the class, clang
- // will assert and crash, so we need to make sure things are
- // acceptable.
+ // Check the number of operator parameters. Sometimes we have seen bad DWARF
+ // that doesn't correctly describe operators and if we try to create a method
+ // and add it to the class, clang will assert and crash, so we need to make
+ // sure things are acceptable.
clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type));
const clang::FunctionProtoType *function_type =
llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr());
@@ -2123,51 +2148,6 @@ ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
return CompilerType();
}
-// Disable this for now since I can't seem to get a nicely formatted float
-// out of the APFloat class without just getting the float, double or quad
-// and then using a formatted print on it which defeats the purpose. We ideally
-// would like to get perfect string values for any kind of float semantics
-// so we can support remote targets. The code below also requires a patch to
-// llvm::APInt.
-// bool
-// ClangASTContext::ConvertFloatValueToString (ASTContext *ast,
-// lldb::opaque_compiler_type_t clang_type, const uint8_t* bytes, size_t
-// byte_size, int apint_byte_order, std::string &float_str)
-//{
-// uint32_t count = 0;
-// bool is_complex = false;
-// if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex))
-// {
-// unsigned num_bytes_per_float = byte_size / count;
-// unsigned num_bits_per_float = num_bytes_per_float * 8;
-//
-// float_str.clear();
-// uint32_t i;
-// for (i=0; i<count; i++)
-// {
-// APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float,
-// (APInt::ByteOrder)apint_byte_order);
-// bool is_ieee = false;
-// APFloat ap_float(ap_int, is_ieee);
-// char s[1024];
-// unsigned int hex_digits = 0;
-// bool upper_case = false;
-//
-// if (ap_float.convertToHexString(s, hex_digits, upper_case,
-// APFloat::rmNearestTiesToEven) > 0)
-// {
-// if (i > 0)
-// float_str.append(", ");
-// float_str.append(s);
-// if (i == 1 && is_complex)
-// float_str.append(1, 'i');
-// }
-// }
-// return !float_str.empty();
-// }
-// return false;
-//}
-
CompilerType ClangASTContext::GetIntTypeFromBitSize(clang::ASTContext *ast,
size_t bit_size,
bool is_signed) {
@@ -2268,8 +2248,8 @@ bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl,
if (lhs_decl_kind == rhs_decl_kind) {
//------------------------------------------------------------------
- // Now check that the decl contexts kinds are all equivalent
- // before we have to check any names of the decl contexts...
+ // Now check that the decl contexts kinds are all equivalent before we
+ // have to check any names of the decl contexts...
//------------------------------------------------------------------
clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
@@ -2311,8 +2291,8 @@ bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl,
return false;
//--------------------------------------------------------------
- // We know that the decl context kinds all match, so now we need
- // to make sure the names match as well
+ // We know that the decl context kinds all match, so now we need to
+ // make sure the names match as well
//--------------------------------------------------------------
lhs_decl_ctx = lhs_decl->getDeclContext();
rhs_decl_ctx = rhs_decl->getDeclContext();
@@ -2582,8 +2562,7 @@ static bool GetCompleteQualType(clang::ASTContext *ast,
clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
// We currently can't complete objective C types through the newly added
- // ASTContext
- // because it only supports TagDecl objects right now...
+ // ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
if (class_interface_decl->getDefinition())
return true;
@@ -2903,8 +2882,8 @@ bool ClangASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer)) {
if (pointee_or_element_clang_type.IsCharType()) {
if (type_flags.Test(eTypeIsArray)) {
- // We know the size of the array and it could be a C string
- // since it is an array of characters
+ // We know the size of the array and it could be a C string since it is
+ // an array of characters
length = llvm::cast<clang::ConstantArrayType>(
GetCanonicalQualType(type).getTypePtr())
->getSize()
@@ -3644,9 +3623,8 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
if (success) {
// Check to make sure what we are pointing too is a possible dynamic C++
- // type
- // We currently accept any "void *" (in case we have a class that has been
- // watered down to an opaque pointer) and virtual C++ classes.
+ // type We currently accept any "void *" (in case we have a class that
+ // has been watered down to an opaque pointer) and virtual C++ classes.
const clang::Type::TypeClass pointee_type_class =
pointee_qual_type.getCanonicalType()->getTypeClass();
switch (pointee_type_class) {
@@ -3966,7 +3944,10 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
case clang::Type::DependentTemplateSpecialization:
return eTypeIsTemplate;
case clang::Type::Decltype:
- return 0;
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType())
+ .GetTypeInfo(pointee_or_element_clang_type);
case clang::Type::Enum:
if (pointee_or_element_clang_type)
@@ -4048,9 +4029,16 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
->getUnderlyingType())
.GetTypeInfo(pointee_or_element_clang_type);
case clang::Type::TypeOfExpr:
- return 0;
+ return CompilerType(getASTContext(),
+ llvm::cast<clang::TypeOfExprType>(qual_type)
+ ->getUnderlyingExpr()
+ ->getType())
+ .GetTypeInfo(pointee_or_element_clang_type);
case clang::Type::TypeOf:
- return 0;
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType())
+ .GetTypeInfo(pointee_or_element_clang_type);
case clang::Type::UnresolvedUsing:
return 0;
@@ -4180,6 +4168,8 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
return lldb::eTypeClassArray;
case clang::Type::DependentSizedExtVector:
return lldb::eTypeClassVector;
+ case clang::Type::DependentVector:
+ return lldb::eTypeClassVector;
case clang::Type::ExtVector:
return lldb::eTypeClassVector;
case clang::Type::Vector:
@@ -4257,11 +4247,21 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
break;
case clang::Type::TypeOfExpr:
- break;
+ return CompilerType(getASTContext(),
+ llvm::cast<clang::TypeOfExprType>(qual_type)
+ ->getUnderlyingExpr()
+ ->getType())
+ .GetTypeClass();
case clang::Type::TypeOf:
- break;
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType())
+ .GetTypeClass();
case clang::Type::Decltype:
- break;
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType())
+ .GetTypeClass();
case clang::Type::TemplateSpecialization:
break;
case clang::Type::DeducedTemplateSpecialization:
@@ -4778,9 +4778,8 @@ ClangASTContext::CreateTypedef(lldb::opaque_compiler_type_t type,
}
// Check whether this declaration is an anonymous struct, union, or enum,
- // hidden behind a typedef. If so, we
- // try to check whether we have a typedef tag to attach to the original
- // record declaration
+ // hidden behind a typedef. If so, we try to check whether we have a
+ // typedef tag to attach to the original record declaration
if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl())
tdecl->setTypedefNameForAnonDecl(decl);
@@ -4905,6 +4904,7 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::Type::ConstantArray:
break;
+ case clang::Type::DependentVector:
case clang::Type::ExtVector:
case clang::Type::Vector:
// TODO: Set this to more than one???
@@ -4919,8 +4919,6 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::Char_S:
case clang::BuiltinType::SChar:
case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
case clang::BuiltinType::Short:
case clang::BuiltinType::Int:
case clang::BuiltinType::Long:
@@ -4931,6 +4929,9 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::Char_U:
case clang::BuiltinType::UChar:
case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char8:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
case clang::BuiltinType::UShort:
case clang::BuiltinType::UInt:
case clang::BuiltinType::ULong:
@@ -4938,6 +4939,33 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::UInt128:
return lldb::eEncodingUint;
+ // Fixed point types. Note that they are currently ignored.
+ case clang::BuiltinType::ShortAccum:
+ case clang::BuiltinType::Accum:
+ case clang::BuiltinType::LongAccum:
+ case clang::BuiltinType::UShortAccum:
+ case clang::BuiltinType::UAccum:
+ case clang::BuiltinType::ULongAccum:
+ case clang::BuiltinType::ShortFract:
+ case clang::BuiltinType::Fract:
+ case clang::BuiltinType::LongFract:
+ case clang::BuiltinType::UShortFract:
+ case clang::BuiltinType::UFract:
+ case clang::BuiltinType::ULongFract:
+ case clang::BuiltinType::SatShortAccum:
+ case clang::BuiltinType::SatAccum:
+ case clang::BuiltinType::SatLongAccum:
+ case clang::BuiltinType::SatUShortAccum:
+ case clang::BuiltinType::SatUAccum:
+ case clang::BuiltinType::SatULongAccum:
+ case clang::BuiltinType::SatShortFract:
+ case clang::BuiltinType::SatFract:
+ case clang::BuiltinType::SatLongFract:
+ case clang::BuiltinType::SatUShortFract:
+ case clang::BuiltinType::SatUFract:
+ case clang::BuiltinType::SatULongFract:
+ break;
+
case clang::BuiltinType::Half:
case clang::BuiltinType::Float:
case clang::BuiltinType::Float16:
@@ -5006,9 +5034,8 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
break;
}
break;
- // All pointer types are represented as unsigned integer encodings.
- // We may nee to add a eEncodingPointer if we ever need to know the
- // difference
+ // All pointer types are represented as unsigned integer encodings. We may
+ // nee to add a eEncodingPointer if we ever need to know the difference
case clang::Type::ObjCObjectPointer:
case clang::Type::BlockPointer:
case clang::Type::Pointer:
@@ -5062,7 +5089,22 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
return CompilerType(getASTContext(),
llvm::cast<clang::ParenType>(qual_type)->desugar())
.GetEncoding(count);
-
+ case clang::Type::TypeOfExpr:
+ return CompilerType(getASTContext(),
+ llvm::cast<clang::TypeOfExprType>(qual_type)
+ ->getUnderlyingExpr()
+ ->getType())
+ .GetEncoding(count);
+ case clang::Type::TypeOf:
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType())
+ .GetEncoding(count);
+ case clang::Type::Decltype:
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType())
+ .GetEncoding(count);
case clang::Type::DependentSizedArray:
case clang::Type::DependentSizedExtVector:
case clang::Type::UnresolvedUsing:
@@ -5076,9 +5118,6 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::Type::PackExpansion:
case clang::Type::ObjCObject:
- case clang::Type::TypeOfExpr:
- case clang::Type::TypeOf:
- case clang::Type::Decltype:
case clang::Type::TemplateSpecialization:
case clang::Type::DeducedTemplateSpecialization:
case clang::Type::Atomic:
@@ -5120,6 +5159,7 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
case clang::Type::ConstantArray:
return lldb::eFormatVoid; // no value
+ case clang::Type::DependentVector:
case clang::Type::ExtVector:
case clang::Type::Vector:
break;
@@ -5216,6 +5256,22 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
getASTContext(),
llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())
.GetFormat();
+ case clang::Type::TypeOfExpr:
+ return CompilerType(getASTContext(),
+ llvm::cast<clang::TypeOfExprType>(qual_type)
+ ->getUnderlyingExpr()
+ ->getType())
+ .GetFormat();
+ case clang::Type::TypeOf:
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType())
+ .GetFormat();
+ case clang::Type::Decltype:
+ return CompilerType(
+ getASTContext(),
+ llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType())
+ .GetFormat();
case clang::Type::DependentSizedArray:
case clang::Type::DependentSizedExtVector:
case clang::Type::UnresolvedUsing:
@@ -5229,9 +5285,6 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
case clang::Type::PackExpansion:
case clang::Type::ObjCObject:
- case clang::Type::TypeOfExpr:
- case clang::Type::TypeOf:
- case clang::Type::Decltype:
case clang::Type::TemplateSpecialization:
case clang::Type::DeducedTemplateSpecialization:
case clang::Type::Atomic:
@@ -5300,10 +5353,9 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl) {
if (omit_empty_base_classes) {
- // Check each base classes to see if it or any of its
- // base classes contain any fields. This can help
- // limit the noise in variable views by not having to
- // show base classes that contain no members.
+ // Check each base classes to see if it or any of its base classes
+ // contain any fields. This can help limit the noise in variable
+ // views by not having to show base classes that contain no members.
clang::CXXRecordDecl::base_class_const_iterator base_class,
base_class_end;
for (base_class = cxx_record_decl->bases_begin(),
@@ -5396,8 +5448,8 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
CompilerType(getASTContext(), pointee_type)
.GetNumChildren(omit_empty_base_classes);
if (num_pointee_children == 0) {
- // We have a pointer to a pointee type that claims it has no children.
- // We will want to look at
+ // We have a pointer to a pointee type that claims it has no children. We
+ // will want to look at
num_children = GetNumPointeeChildren(pointee_type);
} else
num_children = num_pointee_children;
@@ -6266,11 +6318,15 @@ uint32_t ClangASTContext::GetNumPointeeChildren(clang::QualType type) {
return GetNumPointeeChildren(
llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType());
case clang::Type::TypeOfExpr:
- return 0;
+ return GetNumPointeeChildren(llvm::cast<clang::TypeOfExprType>(qual_type)
+ ->getUnderlyingExpr()
+ ->getType());
case clang::Type::TypeOf:
- return 0;
+ return GetNumPointeeChildren(
+ llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType());
case clang::Type::Decltype:
- return 0;
+ return GetNumPointeeChildren(
+ llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType());
case clang::Type::Record:
return 0;
case clang::Type::Enum:
@@ -6587,15 +6643,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
child_byte_size = ivar_type_info.Width / 8;
// Figure out the field offset within the current
- // struct/union/class type
- // For ObjC objects, we can't trust the bit offset we get from
- // the Clang AST, since
- // that doesn't account for the space taken up by unbacked
- // properties, or from
- // the changing size of base classes that are newer than this
- // class.
- // So if we have a process around that we can ask about this
- // object, do so.
+ // struct/union/class type For ObjC objects, we can't trust the
+ // bit offset we get from the Clang AST, since that doesn't
+ // account for the space taken up by unbacked properties, or
+ // from the changing size of base classes that are newer than
+ // this class. So if we have a process around that we can ask
+ // about this object, do so.
child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
Process *process = nullptr;
if (exe_ctx)
@@ -6623,9 +6676,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
}
// Note, the ObjC Ivar Byte offset is just that, it doesn't
- // account for the bit offset
- // of a bitfield within its containing object. So regardless of
- // where we get the byte
+ // account for the bit offset of a bitfield within its
+ // containing object. So regardless of where we get the byte
// offset from, we still need to get the bit offset for
// bitfields from the layout.
@@ -6897,8 +6949,8 @@ static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl,
}
// Look for a child member (doesn't include base classes, but it does include
-// their members) in the type hierarchy. Returns an index path into "clang_type"
-// on how to reach the appropriate member.
+// their members) in the type hierarchy. Returns an index path into
+// "clang_type" on how to reach the appropriate member.
//
// class A
// {
@@ -6921,16 +6973,13 @@ static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl,
// "m_b" in it:
//
// With omit_empty_base_classes == false we would get an integer array back
-// with:
-// { 1, 1 }
-// The first index 1 is the child index for "class A" within class C
-// The second index 1 is the child index for "m_b" within class A
+// with: { 1, 1 } The first index 1 is the child index for "class A" within
+// class C The second index 1 is the child index for "m_b" within class A
//
-// With omit_empty_base_classes == true we would get an integer array back with:
-// { 0, 1 }
-// The first index 0 is the child index for "class A" within class C (since
-// class B doesn't have any members it doesn't count)
-// The second index 1 is the child index for "m_b" within class A
+// With omit_empty_base_classes == true we would get an integer array back
+// with: { 0, 1 } The first index 0 is the child index for "class A" within
+// class C (since class B doesn't have any members it doesn't count) The second
+// index 1 is the child index for "m_b" within class A
size_t ClangASTContext::GetIndexOfChildMemberWithName(
lldb::opaque_compiler_type_t type, const char *name,
@@ -7065,9 +7114,9 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
}
if (superclass_interface_decl) {
- // The super class index is always zero for ObjC classes,
- // so we push it onto the child indexes in case we find
- // an ivar in our superclass...
+ // The super class index is always zero for ObjC classes, so we
+ // push it onto the child indexes in case we find an ivar in our
+ // superclass...
child_indexes.push_back(0);
CompilerType superclass_clang_type(
@@ -7075,14 +7124,13 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
superclass_interface_decl));
if (superclass_clang_type.GetIndexOfChildMemberWithName(
name, omit_empty_base_classes, child_indexes)) {
- // We did find an ivar in a superclass so just
- // return the results!
+ // We did find an ivar in a superclass so just return the
+ // results!
return child_indexes.size();
}
- // We didn't find an ivar matching "name" in our
- // superclass, pop the superclass zero index that
- // we pushed on above.
+ // We didn't find an ivar matching "name" in our superclass, pop
+ // the superclass zero index that we pushed on above.
child_indexes.pop_back();
}
}
@@ -7675,8 +7723,8 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
clang::ICIS_NoInit); // HasInit
if (!name) {
- // Determine whether this field corresponds to an anonymous
- // struct or union.
+ // Determine whether this field corresponds to an anonymous struct or
+ // union.
if (const clang::TagType *TagT =
field->getType()->getAs<clang::TagType>()) {
if (clang::RecordDecl *Rec =
@@ -7820,8 +7868,8 @@ void ClangASTContext::BuildIndirectFields(const CompilerType &type) {
}
}
- // Check the last field to see if it has an incomplete array type as its
- // last member and if it does, the tell the record decl about it
+ // Check the last field to see if it has an incomplete array type as its last
+ // member and if it does, the tell the record decl about it
if (last_field_pos != field_end_pos) {
if (last_field_pos->getType()->isIncompleteArrayType())
record_decl->hasFlexibleArrayMember();
@@ -7887,7 +7935,7 @@ clang::VarDecl *ClangASTContext::AddVariableToRecordType(
}
clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
- lldb::opaque_compiler_type_t type, const char *name,
+ lldb::opaque_compiler_type_t type, const char *name, const char *mangled_name,
const CompilerType &method_clang_type, lldb::AccessType access,
bool is_virtual, bool is_static, bool is_inline, bool is_explicit,
bool is_attr_used, bool is_artificial) {
@@ -7955,11 +8003,10 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
if (IsOperator(name, op_kind)) {
if (op_kind != clang::NUM_OVERLOADED_OPERATORS) {
- // Check the number of operator parameters. Sometimes we have
- // seen bad DWARF that doesn't correctly describe operators and
- // if we try to create a method and add it to the class, clang
- // will assert and crash, so we need to make sure things are
- // acceptable.
+ // Check the number of operator parameters. Sometimes we have seen bad
+ // DWARF that doesn't correctly describe operators and if we try to
+ // create a method and add it to the class, clang will assert and
+ // crash, so we need to make sure things are acceptable.
const bool is_method = true;
if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(
is_method, op_kind, num_params))
@@ -8007,6 +8054,11 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
if (is_attr_used)
cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext()));
+ if (mangled_name != NULL) {
+ cxx_method_decl->addAttr(
+ clang::AsmLabelAttr::CreateImplicit(*getASTContext(), mangled_name));
+ }
+
// Populate the method decl with parameter decls
llvm::SmallVector<clang::ParmVarDecl *, 12> params;
@@ -8634,8 +8686,8 @@ bool ClangASTContext::CompleteTagDeclarationDefinition(
clang::QualType qual_type(ClangUtil::GetQualType(type));
if (!qual_type.isNull()) {
// Make sure we use the same methodology as
- // ClangASTContext::StartTagDeclarationDefinition()
- // as to how we start/end the definition. Previously we were calling
+ // ClangASTContext::StartTagDeclarationDefinition() as to how we start/end
+ // the definition. Previously we were calling
const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
if (tag_type) {
clang::TagDecl *tag_decl = tag_type->getDecl();
@@ -8905,9 +8957,8 @@ void ClangASTContext::DumpValue(
for (field = record_decl->field_begin(),
field_end = record_decl->field_end();
field != field_end; ++field, ++field_idx, ++child_idx) {
- // Print the starting squiggly bracket (if this is the
- // first member) or comma (for member 2 and beyond) for
- // the struct/union/class member.
+ // Print the starting squiggly bracket (if this is the first member) or
+ // comma (for member 2 and beyond) for the struct/union/class member.
if (child_idx == 0)
s->PutChar('{');
else
@@ -8918,8 +8969,8 @@ void ClangASTContext::DumpValue(
clang::QualType field_type = field->getType();
// Print the member type if requested
- // Figure out the type byte size (field_type_info.first) and
- // alignment (field_type_info.second) from the AST context.
+ // Figure out the type byte size (field_type_info.first) and alignment
+ // (field_type_info.second) from the AST context.
clang::TypeInfo field_type_info =
getASTContext()->getTypeInfo(field_type);
assert(field_idx < record_layout.getFieldCount());
@@ -8990,8 +9041,8 @@ void ClangASTContext::DumpValue(
return;
}
}
- // If we have gotten here we didn't get find the enumerator in the
- // enum decl, so just print the integer.
+ // If we have gotten here we didn't get find the enumerator in the enum
+ // decl, so just print the integer.
s->Printf("%" PRIi64, enum_value);
}
return;
@@ -9029,9 +9080,8 @@ void ClangASTContext::DumpValue(
lldb::Format element_format = element_clang_type.GetFormat();
for (element_idx = 0; element_idx < element_count; ++element_idx) {
- // Print the starting squiggly bracket (if this is the
- // first member) or comman (for member 2 and beyong) for
- // the struct/union/class member.
+ // Print the starting squiggly bracket (if this is the first member) or
+ // comman (for member 2 and beyong) for the struct/union/class member.
if (element_idx == 0)
s->PutChar('{');
else
@@ -9227,8 +9277,8 @@ bool ClangASTContext::DumpTypeValue(
} break;
case clang::Type::Enum:
- // If our format is enum or default, show the enumeration value as
- // its enumeration string value, else just display it as requested.
+ // If our format is enum or default, show the enumeration value as its
+ // enumeration string value, else just display it as requested.
if ((format == eFormatEnum || format == eFormatDefault) &&
GetCompleteType(type)) {
const clang::EnumType *enutype =
@@ -9520,9 +9570,9 @@ void ClangASTContext::DumpTypeName(const CompilerType &type) {
if (objc_class_type) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
- // We currently can't complete objective C types through the newly added
- // ASTContext
- // because it only supports TagDecl objects right now...
+ // We currently can't complete objective C types through the newly
+ // added ASTContext because it only supports TagDecl objects right
+ // now...
if (class_interface_decl)
printf("@class %s", class_interface_decl->getName().str().c_str());
}
@@ -9782,15 +9832,12 @@ std::vector<CompilerDecl> ClangASTContext::DeclContextFindDeclByName(
// Look for child_decl_ctx's lookup scope in frame_decl_ctx and its parents,
// and return the number of levels it took to find it, or
-// LLDB_INVALID_DECL_LEVEL
-// if not found. If the decl was imported via a using declaration, its name
-// and/or
-// type, if set, will be used to check that the decl found in the scope is a
-// match.
+// LLDB_INVALID_DECL_LEVEL if not found. If the decl was imported via a using
+// declaration, its name and/or type, if set, will be used to check that the
+// decl found in the scope is a match.
//
// The optional name is required by languages (like C++) to handle using
-// declarations
-// like:
+// declarations like:
//
// void poo();
// namespace ns {
@@ -9819,14 +9866,10 @@ std::vector<CompilerDecl> ClangASTContext::DeclContextFindDeclByName(
//
// NOTE: Because file statics are at the TranslationUnit along with globals, a
// function at file scope will return the same level as a function at global
-// scope.
-// Ideally we'd like to treat the file scope as an additional scope just below
-// the
-// global scope. More work needs to be done to recognise that, if the decl
-// we're
-// trying to look up is static, we should compare its source file with that of
-// the
-// current scope and return a lower number for it.
+// scope. Ideally we'd like to treat the file scope as an additional scope just
+// below the global scope. More work needs to be done to recognise that, if
+// the decl we're trying to look up is static, we should compare its source
+// file with that of the current scope and return a lower number for it.
uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
clang::DeclContext *child_decl_ctx,
ConstString *child_name,
@@ -9855,10 +9898,8 @@ uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
continue;
// Currently DWARF has one shared translation unit for all Decls at top
- // level, so this
- // would erroneously find using statements anywhere. So don't look at
- // the top-level
- // translation unit.
+ // level, so this would erroneously find using statements anywhere. So
+ // don't look at the top-level translation unit.
// TODO fix this and add a testcase that depends on it.
if (llvm::isa<clang::TranslationUnitDecl>(it->second))
@@ -10090,4 +10131,3 @@ ClangASTContextForExpressions::GetMergerUnchecked() {
lldbassert(m_scratch_ast_source_ap != nullptr);
return m_scratch_ast_source_ap->GetMergerUnchecked();
}
-
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp
index 72ccaed43eaa..ea3b141c9e74 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp
@@ -354,8 +354,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
// We currently can't complete objective C types through the newly added
- // ASTContext
- // because it only supports TagDecl objects right now...
+ // ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
if (ResolveDeclOrigin(class_interface_decl, NULL, NULL))
return true;
@@ -431,8 +430,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
// We currently can't complete objective C types through the newly added
- // ASTContext
- // because it only supports TagDecl objects right now...
+ // ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
if (ResolveDeclOrigin(class_interface_decl, NULL, NULL))
return CompleteAndFetchChildren(qual_type);
@@ -896,9 +894,9 @@ void ClangASTImporter::Minion::ImportDefinitionTo(clang::Decl *to,
}
}
- // If we're dealing with an Objective-C class, ensure that the inheritance has
- // been set up correctly. The ASTImporter may not do this correctly if the
- // class was originally sourced from symbols.
+ // If we're dealing with an Objective-C class, ensure that the inheritance
+ // has been set up correctly. The ASTImporter may not do this correctly if
+ // the class was originally sourced from symbols.
if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) {
do {
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp
index df71b17c09d0..7dda877582cc 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp
@@ -262,8 +262,7 @@ void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
if (m_unwindinfo_data_computed == false) {
if (m_section_sp->IsEncrypted()) {
// Can't get section contents of a protected/encrypted section until we
- // have a live
- // process and can read them out of memory.
+ // have a live process and can read them out of memory.
if (process_sp.get() == nullptr)
return;
m_section_contents_if_encrypted.reset(
@@ -329,11 +328,10 @@ void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
return;
}
- // Parse the basic information from the indexes
- // We wait to scan the second level page info until it's needed
+ // Parse the basic information from the indexes We wait to scan the second
+ // level page info until it's needed
- // struct unwind_info_section_header_index_entry
- // {
+ // struct unwind_info_section_header_index_entry {
// uint32_t functionOffset;
// uint32_t secondLevelPagesSectionOffset;
// uint32_t lsdaIndexArraySectionOffset;
@@ -388,8 +386,7 @@ void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
uint32_t CompactUnwindInfo::GetLSDAForFunctionOffset(uint32_t lsda_offset,
uint32_t lsda_count,
uint32_t function_offset) {
- // struct unwind_info_section_header_lsda_index_entry
- // {
+ // struct unwind_info_section_header_lsda_index_entry {
// uint32_t functionOffset;
// uint32_t lsdaOffset;
// };
@@ -419,8 +416,7 @@ lldb::offset_t CompactUnwindInfo::BinarySearchRegularSecondPage(
uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset,
uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) {
// typedef uint32_t compact_unwind_encoding_t;
- // struct unwind_info_regular_second_level_entry
- // {
+ // struct unwind_info_regular_second_level_entry {
// uint32_t functionOffset;
// compact_unwind_encoding_t encoding;
@@ -539,9 +535,9 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
auto next_it = it + 1;
if (next_it != m_indexes.end()) {
- // initialize the function offset end range to be the start of the
- // next index offset. If we find an entry which is at the end of
- // the index table, this will establish the range end.
+ // initialize the function offset end range to be the start of the next
+ // index offset. If we find an entry which is at the end of the index
+ // table, this will establish the range end.
unwind_info.valid_range_offset_end = next_it->function_offset;
}
@@ -554,15 +550,13 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED
if (kind == UNWIND_SECOND_LEVEL_REGULAR) {
- // struct unwind_info_regular_second_level_page_header
- // {
+ // struct unwind_info_regular_second_level_page_header {
// uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
// uint16_t entryPageOffset;
// uint16_t entryCount;
// typedef uint32_t compact_unwind_encoding_t;
- // struct unwind_info_regular_second_level_entry
- // {
+ // struct unwind_info_regular_second_level_entry {
// uint32_t functionOffset;
// compact_unwind_encoding_t encoding;
@@ -612,8 +606,7 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
}
return true;
} else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) {
- // struct unwind_info_compressed_second_level_page_header
- // {
+ // struct unwind_info_compressed_second_level_page_header {
// uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
// uint16_t entryPageOffset; // offset from this 2nd lvl page
// idx to array of entries
@@ -721,8 +714,8 @@ enum x86_64_eh_regnum {
// enough
};
-// Convert the compact_unwind_info.h register numbering scheme
-// to eRegisterKindEHFrame (eh_frame) register numbering scheme.
+// Convert the compact_unwind_info.h register numbering scheme to
+// eRegisterKindEHFrame (eh_frame) register numbering scheme.
uint32_t translate_to_eh_frame_regnum_x86_64(uint32_t unwind_regno) {
switch (unwind_regno) {
case UNWIND_X86_64_REG_RBX:
@@ -802,9 +795,8 @@ bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
case UNWIND_X86_64_MODE_STACK_IND: {
// The clang in Xcode 6 is emitting incorrect compact unwind encodings for
- // this
- // style of unwind. It was fixed in llvm r217020.
- // The clang in Xcode 7 has this fixed.
+ // this style of unwind. It was fixed in llvm r217020. The clang in Xcode
+ // 7 has this fixed.
return false;
} break;
@@ -861,17 +853,17 @@ bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
if (register_count > 0) {
- // We need to include (up to) 6 registers in 10 bits.
- // That would be 18 bits if we just used 3 bits per reg to indicate
- // the order they're saved on the stack.
+ // We need to include (up to) 6 registers in 10 bits. That would be 18
+ // bits if we just used 3 bits per reg to indicate the order they're
+ // saved on the stack.
//
// This is done with Lehmer code permutation, e.g. see
- // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
+ // http://stackoverflow.com/questions/1506078/fast-permutation-number-
+ // permutation-mapping-algorithms
int permunreg[6] = {0, 0, 0, 0, 0, 0};
- // This decodes the variable-base number in the 10 bits
- // and gives us the Lehmer code sequence which can then
- // be decoded.
+ // This decodes the variable-base number in the 10 bits and gives us the
+ // Lehmer code sequence which can then be decoded.
switch (register_count) {
case 6:
@@ -923,8 +915,8 @@ bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
break;
}
- // Decode the Lehmer code for this permutation of
- // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
+ // Decode the Lehmer code for this permutation of the registers v.
+ // http://en.wikipedia.org/wiki/Lehmer_code
int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
@@ -993,8 +985,8 @@ enum i386_eh_regnum {
// enough
};
-// Convert the compact_unwind_info.h register numbering scheme
-// to eRegisterKindEHFrame (eh_frame) register numbering scheme.
+// Convert the compact_unwind_info.h register numbering scheme to
+// eRegisterKindEHFrame (eh_frame) register numbering scheme.
uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) {
switch (unwind_regno) {
case UNWIND_X86_REG_EBX:
@@ -1123,17 +1115,17 @@ bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
if (register_count > 0) {
- // We need to include (up to) 6 registers in 10 bits.
- // That would be 18 bits if we just used 3 bits per reg to indicate
- // the order they're saved on the stack.
+ // We need to include (up to) 6 registers in 10 bits. That would be 18
+ // bits if we just used 3 bits per reg to indicate the order they're
+ // saved on the stack.
//
// This is done with Lehmer code permutation, e.g. see
- // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
+ // http://stackoverflow.com/questions/1506078/fast-permutation-number-
+ // permutation-mapping-algorithms
int permunreg[6] = {0, 0, 0, 0, 0, 0};
- // This decodes the variable-base number in the 10 bits
- // and gives us the Lehmer code sequence which can then
- // be decoded.
+ // This decodes the variable-base number in the 10 bits and gives us the
+ // Lehmer code sequence which can then be decoded.
switch (register_count) {
case 6:
@@ -1185,8 +1177,8 @@ bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
break;
}
- // Decode the Lehmer code for this permutation of
- // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
+ // Decode the Lehmer code for this permutation of the registers v.
+ // http://en.wikipedia.org/wiki/Lehmer_code
int registers[6] = {UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE,
UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE,
@@ -1260,14 +1252,10 @@ enum arm64_eh_regnum {
pc = 32,
// Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s
- // for the 64-bit
- // fp regs. Normally in DWARF it's context sensitive - so it knows it is
- // fetching a
- // 32- or 64-bit quantity from reg v8 to indicate s0 or d0 - but the unwinder
- // is operating
- // at a lower level and we'd try to fetch 128 bits if we were told that v8
- // were stored on
- // the stack...
+ // for the 64-bit fp regs. Normally in DWARF it's context sensitive - so it
+ // knows it is fetching a 32- or 64-bit quantity from reg v8 to indicate s0
+ // or d0 - but the unwinder is operating at a lower level and we'd try to
+ // fetch 128 bits if we were told that v8 were stored on the stack...
v8 = 72,
v9 = 73,
v10 = 74,
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp
index 8ba83d438803..a4f0d4231e2f 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp
@@ -67,10 +67,10 @@ void CompileUnit::GetDescription(Stream *s,
}
//----------------------------------------------------------------------
-// Dump the current contents of this object. No functions that cause on
-// demand parsing of functions, globals, statics are called, so this
-// is a good function to call to get an idea of the current contents of
-// the CompileUnit object.
+// Dump the current contents of this object. No functions that cause on demand
+// parsing of functions, globals, statics are called, so this is a good
+// function to call to get an idea of the current contents of the CompileUnit
+// object.
//----------------------------------------------------------------------
void CompileUnit::Dump(Stream *s, bool show_context) const {
const char *language = Language::GetNameForLanguageType(m_language);
@@ -118,28 +118,27 @@ FunctionSP CompileUnit::GetFunctionAtIndex(size_t idx) {
}
//----------------------------------------------------------------------
-// Find functions using the Mangled::Tokens token list. This
-// function currently implements an interactive approach designed to find
-// all instances of certain functions. It isn't designed to the
-// quickest way to lookup functions as it will need to iterate through
-// all functions and see if they match, though it does provide a powerful
-// and context sensitive way to search for all functions with a certain
-// name, all functions in a namespace, or all functions of a template
-// type. See Mangled::Tokens::Parse() comments for more information.
+// Find functions using the Mangled::Tokens token list. This function currently
+// implements an interactive approach designed to find all instances of certain
+// functions. It isn't designed to the quickest way to lookup functions as it
+// will need to iterate through all functions and see if they match, though it
+// does provide a powerful and context sensitive way to search for all
+// functions with a certain name, all functions in a namespace, or all
+// functions of a template type. See Mangled::Tokens::Parse() comments for more
+// information.
//
-// The function prototype will need to change to return a list of
-// results. It was originally used to help debug the Mangled class
-// and the Mangled::Tokens::MatchesQuery() function and it currently
-// will print out a list of matching results for the functions that
-// are currently in this compile unit.
+// The function prototype will need to change to return a list of results. It
+// was originally used to help debug the Mangled class and the
+// Mangled::Tokens::MatchesQuery() function and it currently will print out a
+// list of matching results for the functions that are currently in this
+// compile unit.
//
// A FindFunctions method should be called prior to this that takes
-// a regular function name (const char * or ConstString as a parameter)
-// before resorting to this slower but more complete function. The
-// other FindFunctions method should be able to take advantage of any
-// accelerator tables available in the debug information (which is
-// parsed by the SymbolFile parser plug-ins and registered with each
-// Module).
+// a regular function name (const char * or ConstString as a parameter) before
+// resorting to this slower but more complete function. The other FindFunctions
+// method should be able to take advantage of any accelerator tables available
+// in the debug information (which is parsed by the SymbolFile parser plug-ins
+// and registered with each Module).
//----------------------------------------------------------------------
// void
// CompileUnit::FindFunctions(const Mangled::Tokens& tokens)
@@ -283,13 +282,12 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
bool exact, uint32_t resolve_scope,
SymbolContextList &sc_list) {
// First find all of the file indexes that match our "file_spec". If
- // "file_spec" has an empty directory, then only compare the basenames
- // when finding file indexes
+ // "file_spec" has an empty directory, then only compare the basenames when
+ // finding file indexes
std::vector<uint32_t> file_indexes;
const bool full_match = (bool)file_spec.GetDirectory();
- const bool remove_backup_dots = true;
bool file_spec_matches_cu_file_spec =
- FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots);
+ FileSpec::Equal(file_spec, *this, full_match);
// If we are not looking for inlined functions and our file spec doesn't
// match then we are done...
@@ -297,11 +295,10 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
return 0;
uint32_t file_idx =
- GetSupportFiles().FindFileIndex(1, file_spec, true, remove_backup_dots);
+ GetSupportFiles().FindFileIndex(1, file_spec, true);
while (file_idx != UINT32_MAX) {
file_indexes.push_back(file_idx);
- file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true,
- remove_backup_dots);
+ file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true);
}
const size_t num_file_indexes = file_indexes.size();
@@ -321,23 +318,23 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line_idx;
if (num_file_indexes == 1) {
- // We only have a single support file that matches, so use
- // the line table function that searches for a line entries
- // that match a single support file index
+ // We only have a single support file that matches, so use the line
+ // table function that searches for a line entries that match a single
+ // support file index
LineEntry line_entry;
line_idx = line_table->FindLineEntryIndexByFileIndex(
0, file_indexes.front(), line, exact, &line_entry);
- // If "exact == true", then "found_line" will be the same
- // as "line". If "exact == false", the "found_line" will be the
- // closest line entry with a line number greater than "line" and
- // we will use this for our subsequent line exact matches below.
+ // If "exact == true", then "found_line" will be the same as "line". If
+ // "exact == false", the "found_line" will be the closest line entry
+ // with a line number greater than "line" and we will use this for our
+ // subsequent line exact matches below.
found_line = line_entry.line;
while (line_idx != UINT32_MAX) {
- // If they only asked for the line entry, then we're done, we can just
- // copy that over.
- // But if they wanted more than just the line number, fill it in.
+ // If they only asked for the line entry, then we're done, we can
+ // just copy that over. But if they wanted more than just the line
+ // number, fill it in.
if (resolve_scope == eSymbolContextLineEntry) {
sc.line_entry = line_entry;
} else {
@@ -351,17 +348,17 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
&line_entry);
}
} else {
- // We found multiple support files that match "file_spec" so use
- // the line table function that searches for a line entries
- // that match a multiple support file indexes.
+ // We found multiple support files that match "file_spec" so use the
+ // line table function that searches for a line entries that match a
+ // multiple support file indexes.
LineEntry line_entry;
line_idx = line_table->FindLineEntryIndexByFileIndex(
0, file_indexes, line, exact, &line_entry);
- // If "exact == true", then "found_line" will be the same
- // as "line". If "exact == false", the "found_line" will be the
- // closest line entry with a line number greater than "line" and
- // we will use this for our subsequent line exact matches below.
+ // If "exact == true", then "found_line" will be the same as "line". If
+ // "exact == false", the "found_line" will be the closest line entry
+ // with a line number greater than "line" and we will use this for our
+ // subsequent line exact matches below.
found_line = line_entry.line;
while (line_idx != UINT32_MAX) {
@@ -379,8 +376,8 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
}
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
- // only append the context if we aren't looking for inline call sites
- // by file and line and if the file spec matches that of the compile unit
+ // only append the context if we aren't looking for inline call sites by
+ // file and line and if the file spec matches that of the compile unit
sc_list.Append(sc);
}
return sc_list.GetSize() - prev_size;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp
index 5d845361b03c..2dd1d3ebd04b 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp
@@ -638,8 +638,8 @@ CompilerType CompilerType::GetChildCompilerTypeAtIndex(
}
// Look for a child member (doesn't include base classes, but it does include
-// their members) in the type hierarchy. Returns an index path into "clang_type"
-// on how to reach the appropriate member.
+// their members) in the type hierarchy. Returns an index path into
+// "clang_type" on how to reach the appropriate member.
//
// class A
// {
@@ -662,16 +662,13 @@ CompilerType CompilerType::GetChildCompilerTypeAtIndex(
// "m_b" in it:
//
// With omit_empty_base_classes == false we would get an integer array back
-// with:
-// { 1, 1 }
-// The first index 1 is the child index for "class A" within class C
-// The second index 1 is the child index for "m_b" within class A
+// with: { 1, 1 } The first index 1 is the child index for "class A" within
+// class C The second index 1 is the child index for "m_b" within class A
//
-// With omit_empty_base_classes == true we would get an integer array back with:
-// { 0, 1 }
-// The first index 0 is the child index for "class A" within class C (since
-// class B doesn't have any members it doesn't count)
-// The second index 1 is the child index for "m_b" within class A
+// With omit_empty_base_classes == true we would get an integer array back
+// with: { 0, 1 } The first index 0 is the child index for "class A" within
+// class C (since class B doesn't have any members it doesn't count) The second
+// index 1 is the child index for "m_b" within class A
size_t CompilerType::GetIndexOfChildMemberWithName(
const char *name, bool omit_empty_base_classes,
@@ -987,8 +984,8 @@ bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx,
if (!IsValid())
return false;
- // Can't convert a file address to anything valid without more
- // context (which Module it came from)
+ // Can't convert a file address to anything valid without more context (which
+ // Module it came from)
if (address_type == eAddressTypeFile)
return false;
@@ -1029,8 +1026,8 @@ bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx,
if (!IsValid())
return false;
- // Can't convert a file address to anything valid without more
- // context (which Module it came from)
+ // Can't convert a file address to anything valid without more context (which
+ // Module it came from)
if (address_type == eAddressTypeFile)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index 572648d05f09..1bf9ff99e015 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -27,8 +27,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// GetDwarfEHPtr
//
-// Used for calls when the value type is specified by a DWARF EH Frame
-// pointer encoding.
+// Used for calls when the value type is specified by a DWARF EH Frame pointer
+// encoding.
//----------------------------------------------------------------------
static uint64_t
GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr,
@@ -83,8 +83,8 @@ GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr,
break;
case DW_EH_PE_aligned: {
- // SetPointerSize should be called prior to extracting these so the
- // pointer size is cached
+ // SetPointerSize should be called prior to extracting these so the pointer
+ // size is cached
assert(addr_size != 0);
if (addr_size) {
// Align to a address size boundary first
@@ -154,8 +154,8 @@ DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile,
bool DWARFCallFrameInfo::GetUnwindPlan(Address addr, UnwindPlan &unwind_plan) {
FDEEntryMap::Entry fde_entry;
- // Make sure that the Address we're searching for is the same object file
- // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
+ // Make sure that the Address we're searching for is the same object file as
+ // this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
ModuleSP module_sp = addr.GetModule();
if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
module_sp->GetObjectFile() != &m_objfile)
@@ -168,8 +168,8 @@ bool DWARFCallFrameInfo::GetUnwindPlan(Address addr, UnwindPlan &unwind_plan) {
bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {
- // Make sure that the Address we're searching for is the same object file
- // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
+ // Make sure that the Address we're searching for is the same object file as
+ // this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
ModuleSP module_sp = addr.GetModule();
if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
module_sp->GetObjectFile() != &m_objfile)
@@ -291,8 +291,8 @@ DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
return nullptr;
}
- // m_cfi_data uses address size from target architecture of the process
- // may ignore these fields?
+ // m_cfi_data uses address size from target architecture of the process may
+ // ignore these fields?
if (m_type == DWARF && cie_sp->version >= CFI_VERSION4) {
cie_sp->address_size = m_cfi_data.GetU8(&offset);
cie_sp->segment_size = m_cfi_data.GetU8(&offset);
@@ -307,15 +307,15 @@ DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
: m_cfi_data.GetU8(&offset);
if (cie_sp->augmentation[0]) {
- // Get the length of the eh_frame augmentation data
- // which starts with a ULEB128 length in bytes
+ // Get the length of the eh_frame augmentation data which starts with a
+ // ULEB128 length in bytes
const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset);
const size_t aug_data_end = offset + aug_data_len;
const size_t aug_str_len = strlen(cie_sp->augmentation);
// A 'z' may be present as the first character of the string.
- // If present, the Augmentation Data field shall be present.
- // The contents of the Augmentation Data shall be interpreted
- // according to other characters in the Augmentation String.
+ // If present, the Augmentation Data field shall be present. The contents
+ // of the Augmentation Data shall be interpreted according to other
+ // characters in the Augmentation String.
if (cie_sp->augmentation[0] == 'z') {
// Extract the Augmentation Data
size_t aug_str_idx = 0;
@@ -323,31 +323,27 @@ DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
char aug = cie_sp->augmentation[aug_str_idx];
switch (aug) {
case 'L':
- // Indicates the presence of one argument in the
- // Augmentation Data of the CIE, and a corresponding
- // argument in the Augmentation Data of the FDE. The
- // argument in the Augmentation Data of the CIE is
- // 1-byte and represents the pointer encoding used
- // for the argument in the Augmentation Data of the
- // FDE, which is the address of a language-specific
- // data area (LSDA). The size of the LSDA pointer is
- // specified by the pointer encoding used.
+ // Indicates the presence of one argument in the Augmentation Data
+ // of the CIE, and a corresponding argument in the Augmentation
+ // Data of the FDE. The argument in the Augmentation Data of the
+ // CIE is 1-byte and represents the pointer encoding used for the
+ // argument in the Augmentation Data of the FDE, which is the
+ // address of a language-specific data area (LSDA). The size of the
+ // LSDA pointer is specified by the pointer encoding used.
cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset);
break;
case 'P':
- // Indicates the presence of two arguments in the
- // Augmentation Data of the CIE. The first argument
- // is 1-byte and represents the pointer encoding
- // used for the second argument, which is the
- // address of a personality routine handler. The
- // size of the personality routine pointer is
- // specified by the pointer encoding used.
+ // Indicates the presence of two arguments in the Augmentation Data
+ // of the CIE. The first argument is 1-byte and represents the
+ // pointer encoding used for the second argument, which is the
+ // address of a personality routine handler. The size of the
+ // personality routine pointer is specified by the pointer encoding
+ // used.
//
- // The address of the personality function will
- // be stored at this location. Pre-execution, it
- // will be all zero's so don't read it until we're
- // trying to do an unwind & the reloc has been
+ // The address of the personality function will be stored at this
+ // location. Pre-execution, it will be all zero's so don't read it
+ // until we're trying to do an unwind & the reloc has been
// resolved.
{
uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
@@ -360,22 +356,21 @@ DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
case 'R':
// A 'R' may be present at any position after the
- // first character of the string. The Augmentation
- // Data shall include a 1 byte argument that
- // represents the pointer encoding for the address
- // pointers used in the FDE.
- // Example: 0x1B == DW_EH_PE_pcrel | DW_EH_PE_sdata4
+ // first character of the string. The Augmentation Data shall
+ // include a 1 byte argument that represents the pointer encoding
+ // for the address pointers used in the FDE. Example: 0x1B ==
+ // DW_EH_PE_pcrel | DW_EH_PE_sdata4
cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset);
break;
}
}
} else if (strcmp(cie_sp->augmentation, "eh") == 0) {
- // If the Augmentation string has the value "eh", then
- // the EH Data field shall be present
+ // If the Augmentation string has the value "eh", then the EH Data
+ // field shall be present
}
- // Set the offset to be the end of the augmentation data just in case
- // we didn't understand any of the data.
+ // Set the offset to be the end of the augmentation data just in case we
+ // didn't understand any of the data.
offset = (uint32_t)aug_data_end;
}
@@ -408,10 +403,8 @@ void DWARFCallFrameInfo::GetCFIData() {
}
}
// Scan through the eh_frame or debug_frame section looking for FDEs and noting
-// the start/end addresses
-// of the functions and a pointer back to the function's FDE for later
-// expansion.
-// Internalize CIEs as we come across them.
+// the start/end addresses of the functions and a pointer back to the
+// function's FDE for later expansion. Internalize CIEs as we come across them.
void DWARFCallFrameInfo::GetFDEIndex() {
if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
@@ -469,8 +462,8 @@ void DWARFCallFrameInfo::GetFDEIndex() {
}
// An FDE entry contains CIE_pointer in debug_frame in same place as cie_id
- // in eh_frame. CIE_pointer is an offset into the .debug_frame section.
- // So, variable cie_offset should be equal to cie_id for debug_frame.
+ // in eh_frame. CIE_pointer is an offset into the .debug_frame section. So,
+ // variable cie_offset should be equal to cie_id for debug_frame.
// FDE entries with cie_id == 0 shouldn't be ignored for it.
if ((cie_id == 0 && m_type == EH) || cie_id == UINT32_MAX || len == 0) {
auto cie_sp = ParseCIE(current_entry);
@@ -556,9 +549,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
// FDE entries with zeroth cie_offset may occur for debug_frame.
assert(!(m_type == EH && 0 == cie_offset) && cie_offset != UINT32_MAX);
- // Translate the CIE_id from the eh_frame format, which
- // is relative to the FDE offset, into a __eh_frame section
- // offset
+ // Translate the CIE_id from the eh_frame format, which is relative to the
+ // FDE offset, into a __eh_frame section offset
if (m_type == EH) {
unwind_plan.SetSourceName("eh_frame CFI");
cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
@@ -652,10 +644,10 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
case DW_CFA_advance_loc: // (Row Creation Instruction)
{ // 0x40 - high 2 bits are 0x1, lower 6 bits are delta
// takes a single argument that represents a constant delta. The
- // required action is to create a new table row with a location
- // value that is computed by taking the current entry's location
- // value and adding (delta * code_align). All other
- // values in the new row are initially identical to the current row.
+ // required action is to create a new table row with a location value
+ // that is computed by taking the current entry's location value and
+ // adding (delta * code_align). All other values in the new row are
+ // initially identical to the current row.
unwind_plan.AppendRow(row);
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *row.get();
@@ -670,11 +662,10 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
// required action is to change the rule for the indicated register
// to the rule assigned it by the initial_instructions in the CIE.
uint32_t reg_num = extended_opcode;
- // We only keep enough register locations around to
- // unwind what is in our thread, and these are organized
- // by the register index in that state, so we need to convert our
- // eh_frame register number from the EH frame info, to a register
- // index
+ // We only keep enough register locations around to unwind what is in
+ // our thread, and these are organized by the register index in that
+ // state, so we need to convert our eh_frame register number from the
+ // EH frame info, to a register index
if (unwind_plan.IsValidRowIndex(0) &&
unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
@@ -756,8 +747,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
case DW_CFA_remember_state: // 0xA
{
// These instructions define a stack of information. Encountering the
- // DW_CFA_remember_state instruction means to save the rules for every
- // register on the current row on the stack. Encountering the
+ // DW_CFA_remember_state instruction means to save the rules for
+ // every register on the current row on the stack. Encountering the
// DW_CFA_restore_state instruction means to pop the set of rules off
// the stack and place them in the current row. (This operation is
// useful for compilers that move epilogue code into the body of a
@@ -772,8 +763,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
case DW_CFA_restore_state: // 0xB
{
// These instructions define a stack of information. Encountering the
- // DW_CFA_remember_state instruction means to save the rules for every
- // register on the current row on the stack. Encountering the
+ // DW_CFA_remember_state instruction means to save the rules for
+ // every register on the current row on the stack. Encountering the
// DW_CFA_restore_state instruction means to pop the set of rules off
// the stack and place them in the current row. (This operation is
// useful for compilers that move epilogue code into the body of a
@@ -798,10 +789,9 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
case DW_CFA_GNU_args_size: // 0x2e
{
// The DW_CFA_GNU_args_size instruction takes an unsigned LEB128
- // operand
- // representing an argument size. This instruction specifies the total
- // of
- // the size of the arguments which have been pushed onto the stack.
+ // operand representing an argument size. This instruction specifies
+ // the total of the size of the arguments which have been pushed onto
+ // the stack.
// TODO: Figure out how we should handle this.
m_cfi_data.GetULEB128(&offset);
@@ -834,9 +824,9 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
// register
// takes two arguments: an unsigned LEB128 constant representing a
// factored offset and a register number. The required action is to
- // change the rule for the register indicated by the register number
- // to be an offset(N) rule with a value of
- // (N = factored offset * data_align).
+ // change the rule for the register indicated by the register number to
+ // be an offset(N) rule with a value of (N = factored offset *
+ // data_align).
uint8_t reg_num = extended_opcode;
int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
reg_location.SetAtCFAPlusOffset(op_offset);
@@ -851,8 +841,8 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_offset_extended: // 0x5
{
- // takes two unsigned LEB128 arguments representing a register number
- // and a factored offset. This instruction is identical to DW_CFA_offset
+ // takes two unsigned LEB128 arguments representing a register number and
+ // a factored offset. This instruction is identical to DW_CFA_offset
// except for the encoding and size of the register argument.
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
@@ -888,9 +878,9 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_register: // 0x9
{
- // takes two unsigned LEB128 arguments representing register numbers.
- // The required action is to set the rule for the first register to be
- // the second register.
+ // takes two unsigned LEB128 arguments representing register numbers. The
+ // required action is to set the rule for the first register to be the
+ // second register.
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
UnwindPlan::Row::RegisterLocation reg_location;
@@ -901,10 +891,9 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_def_cfa: // 0xC (CFA Definition Instruction)
{
- // Takes two unsigned LEB128 operands representing a register
- // number and a (non-factored) offset. The required action
- // is to define the current CFA rule to use the provided
- // register and offset.
+ // Takes two unsigned LEB128 operands representing a register number and
+ // a (non-factored) offset. The required action is to define the current
+ // CFA rule to use the provided register and offset.
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);
@@ -914,8 +903,8 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_def_cfa_register: // 0xD (CFA Definition Instruction)
{
// takes a single unsigned LEB128 argument representing a register
- // number. The required action is to define the current CFA rule to
- // use the provided register (but to keep the old offset).
+ // number. The required action is to define the current CFA rule to use
+ // the provided register (but to keep the old offset).
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
row.GetCFAValue().SetIsRegisterPlusOffset(reg_num,
row.GetCFAValue().GetOffset());
@@ -924,10 +913,9 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_def_cfa_offset: // 0xE (CFA Definition Instruction)
{
- // Takes a single unsigned LEB128 operand representing a
- // (non-factored) offset. The required action is to define
- // the current CFA rule to use the provided offset (but
- // to keep the old register).
+ // Takes a single unsigned LEB128 operand representing a (non-factored)
+ // offset. The required action is to define the current CFA rule to use
+ // the provided offset (but to keep the old register).
int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
row.GetCFAValue().SetIsRegisterPlusOffset(
row.GetCFAValue().GetRegisterNumber(), op_offset);
@@ -945,14 +933,13 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_expression: // 0x10
{
- // Takes two operands: an unsigned LEB128 value representing
- // a register number, and a DW_FORM_block value representing a DWARF
- // expression. The required action is to change the rule for the
- // register indicated by the register number to be an expression(E)
- // rule where E is the DWARF expression. That is, the DWARF
- // expression computes the address. The value of the CFA is
- // pushed on the DWARF evaluation stack prior to execution of
- // the DWARF expression.
+ // Takes two operands: an unsigned LEB128 value representing a register
+ // number, and a DW_FORM_block value representing a DWARF expression. The
+ // required action is to change the rule for the register indicated by
+ // the register number to be an expression(E) rule where E is the DWARF
+ // expression. That is, the DWARF expression computes the address. The
+ // value of the CFA is pushed on the DWARF evaluation stack prior to
+ // execution of the DWARF expression.
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
const uint8_t *block_data =
@@ -965,10 +952,10 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_offset_extended_sf: // 0x11
{
- // takes two operands: an unsigned LEB128 value representing a
- // register number and a signed LEB128 factored offset. This
- // instruction is identical to DW_CFA_offset_extended except
- // that the second operand is signed and factored.
+ // takes two operands: an unsigned LEB128 value representing a register
+ // number and a signed LEB128 factored offset. This instruction is
+ // identical to DW_CFA_offset_extended except that the second operand is
+ // signed and factored.
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
UnwindPlan::Row::RegisterLocation reg_location;
@@ -979,10 +966,10 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_def_cfa_sf: // 0x12 (CFA Definition Instruction)
{
- // Takes two operands: an unsigned LEB128 value representing
- // a register number and a signed LEB128 factored offset.
- // This instruction is identical to DW_CFA_def_cfa except
- // that the second operand is signed and factored.
+ // Takes two operands: an unsigned LEB128 value representing a register
+ // number and a signed LEB128 factored offset. This instruction is
+ // identical to DW_CFA_def_cfa except that the second operand is signed
+ // and factored.
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);
@@ -991,9 +978,9 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_def_cfa_offset_sf: // 0x13 (CFA Definition Instruction)
{
- // takes a signed LEB128 operand representing a factored
- // offset. This instruction is identical to DW_CFA_def_cfa_offset
- // except that the operand is signed and factored.
+ // takes a signed LEB128 operand representing a factored offset. This
+ // instruction is identical to DW_CFA_def_cfa_offset except that the
+ // operand is signed and factored.
int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
uint32_t cfa_regnum = row.GetCFAValue().GetRegisterNumber();
row.GetCFAValue().SetIsRegisterPlusOffset(cfa_regnum, op_offset);
@@ -1003,9 +990,9 @@ bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
case DW_CFA_val_expression: // 0x16
{
// takes two operands: an unsigned LEB128 value representing a register
- // number, and a DW_FORM_block value representing a DWARF expression.
- // The required action is to change the rule for the register indicated
- // by the register number to be a val_expression(E) rule where E is the
+ // number, and a DW_FORM_block value representing a DWARF expression. The
+ // required action is to change the rule for the register indicated by
+ // the register number to be a val_expression(E) rule where E is the
// DWARF expression. That is, the DWARF expression computes the value of
// the given register. The value of the CFA is pushed on the DWARF
// evaluation stack prior to execution of the DWARF expression.
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp b/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp
index 7cee6c5a3ef3..83df578da2e3 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp
@@ -91,7 +91,7 @@ bool lldb_private::operator==(const Declaration &lhs, const Declaration &rhs) {
return lhs.GetFile() == rhs.GetFile();
#else
if (lhs.GetLine() == rhs.GetLine())
- return FileSpec::Equal(lhs.GetFile(), rhs.GetFile(), true, true);
+ return FileSpec::Equal(lhs.GetFile(), rhs.GetFile(), true);
#endif
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp b/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
index b9f50cd1b12f..2384d35e3d36 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
@@ -174,10 +174,9 @@ UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target,
m_tried_unwind_plan_eh_frame_augmented)
return m_unwind_plan_eh_frame_augmented_sp;
- // Only supported on x86 architectures where we get eh_frame from the compiler
- // that describes
- // the prologue instructions perfectly, and sometimes the epilogue
- // instructions too.
+ // Only supported on x86 architectures where we get eh_frame from the
+ // compiler that describes the prologue instructions perfectly, and sometimes
+ // the epilogue instructions too.
if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
@@ -194,8 +193,7 @@ UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target,
m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan));
// Augment the eh_frame instructions with epilogue descriptions if necessary
- // so the
- // UnwindPlan can be used at any instruction in the function.
+ // so the UnwindPlan can be used at any instruction in the function.
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
if (assembly_profiler_sp) {
@@ -238,7 +236,8 @@ FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread,
new UnwindPlan(*debug_frame_plan));
// Augment the debug_frame instructions with epilogue descriptions if
- // necessary so the UnwindPlan can be used at any instruction in the function.
+ // necessary so the UnwindPlan can be used at any instruction in the
+ // function.
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
if (assembly_profiler_sp) {
@@ -275,8 +274,7 @@ UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
// This method compares the pc unwind rule in the first row of two UnwindPlans.
// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
-// sp"),
-// then it will return LazyBoolTrue.
+// sp"), then it will return LazyBoolTrue.
LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
LazyBool plans_are_identical = eLazyBoolCalculate;
@@ -320,22 +318,22 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
UnwindPlanSP assembly_sp =
GetAssemblyUnwindPlan(target, thread, current_offset);
- // This point of this code is to detect when a function is using a
- // non-standard ABI, and the eh_frame correctly describes that alternate ABI.
+ // This point of this code is to detect when a function is using a non-
+ // standard ABI, and the eh_frame correctly describes that alternate ABI.
// This is addressing a specific situation on x86_64 linux systems where one
// function in a library pushes a value on the stack and jumps to another
- // function. So using an assembly instruction based unwind will not work when
- // you're in the second function - the stack has been modified in a non-ABI
- // way. But we have eh_frame that correctly describes how to unwind from this
- // location. So we're looking to see if the initial pc register save location
- // from the eh_frame is different from the assembly unwind, the arch default
- // unwind, and the arch default at initial function entry.
+ // function. So using an assembly instruction based unwind will not work
+ // when you're in the second function - the stack has been modified in a non-
+ // ABI way. But we have eh_frame that correctly describes how to unwind from
+ // this location. So we're looking to see if the initial pc register save
+ // location from the eh_frame is different from the assembly unwind, the arch
+ // default unwind, and the arch default at initial function entry.
//
// We may have eh_frame that describes the entire function -- or we may have
// eh_frame that only describes the unwind after the prologue has executed --
// so we need to check both the arch default (once the prologue has executed)
- // and the arch default at initial function entry. And we may be running on a
- // target where we have only some of the assembly/arch default unwind plans
+ // and the arch default at initial function entry. And we may be running on
+ // a target where we have only some of the assembly/arch default unwind plans
// available.
if (CompareUnwindPlansForIdenticalInitialPCLocation(
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Function.cpp b/contrib/llvm/tools/lldb/source/Symbol/Function.cpp
index 9464cef0bc73..f642c186a19f 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Function.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Function.cpp
@@ -24,9 +24,8 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Basic function information is contained in the FunctionInfo class.
-// It is designed to contain the name, linkage name, and declaration
-// location.
+// Basic function information is contained in the FunctionInfo class. It is
+// designed to contain the name, linkage name, and declaration location.
//----------------------------------------------------------------------
FunctionInfo::FunctionInfo(const char *name, const Declaration *decl_ptr)
: m_name(name), m_declaration(decl_ptr) {}
@@ -188,8 +187,7 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) {
source_file.Clear();
// The -1 is kind of cheesy, but I want to get the last line entry for the
- // given function, not the
- // first entry of the next.
+ // given function, not the first entry of the next.
Address scratch_addr(GetAddressRange().GetBaseAddress());
scratch_addr.SetOffset(scratch_addr.GetOffset() +
GetAddressRange().GetByteSize() - 1);
@@ -331,9 +329,8 @@ size_t Function::MemorySize() const {
bool Function::GetIsOptimized() {
bool result = false;
- // Currently optimization is only indicted by the
- // vendor extension DW_AT_APPLE_optimized which
- // is set on a compile unit level.
+ // Currently optimization is only indicted by the vendor extension
+ // DW_AT_APPLE_optimized which is set on a compile unit level.
if (m_comp_unit) {
result = m_comp_unit->GetIsOptimized();
}
@@ -441,11 +438,11 @@ uint32_t Function::GetPrologueByteSize() {
}
}
- // If we didn't find the end of the prologue in the line tables,
- // then just use the end address of the first line table entry
+ // If we didn't find the end of the prologue in the line tables, then
+ // just use the end address of the first line table entry
if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) {
- // Check the first few instructions and look for one that has
- // a line number that's different than the first entry.
+ // Check the first few instructions and look for one that has a line
+ // number that's different than the first entry.
uint32_t last_line_entry_idx = first_line_entry_idx + 6;
for (uint32_t idx = first_line_entry_idx + 1;
idx < last_line_entry_idx; ++idx) {
@@ -498,8 +495,8 @@ uint32_t Function::GetPrologueByteSize() {
}
}
- // Verify that this prologue end file address in the function's
- // address range just to be sure
+ // Verify that this prologue end file address in the function's address
+ // range just to be sure
if (func_start_file_addr < prologue_end_file_addr &&
prologue_end_file_addr < func_end_file_addr) {
m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp
index 6761a605e46b..da5c82b2cb55 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp
@@ -667,8 +667,7 @@ GoASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
}
// Returns -1 if this isn't a function of if the function doesn't have a
-// prototype
-// Returns a value >= 0 if there is a prototype.
+// prototype Returns a value >= 0 if there is a prototype.
int GoASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) {
return GetNumberOfFunctionArguments(type);
}
@@ -1008,8 +1007,8 @@ CompilerType GoASTContext::GetChildCompilerTypeAtIndex(
return CompilerType();
}
-// Lookup a child given a name. This function will match base class names
-// and member member names in "clang_type" only, not descendants.
+// Lookup a child given a name. This function will match base class names and
+// member member names in "clang_type" only, not descendants.
uint32_t
GoASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
@@ -1048,8 +1047,8 @@ size_t GoASTContext::GetIndexOfChildMemberWithName(
return 1;
}
-// Converts "s" to a floating point value and place resulting floating
-// point bytes in the "dst" buffer.
+// Converts "s" to a floating point value and place resulting floating point
+// bytes in the "dst" buffer.
size_t
GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
const char *s, uint8_t *dst,
@@ -1080,9 +1079,8 @@ void GoASTContext::DumpValue(lldb::opaque_compiler_type_t type,
uint32_t field_idx = 0;
for (auto *field = st->GetField(field_idx); field != nullptr;
field_idx++) {
- // Print the starting squiggly bracket (if this is the
- // first member) or comma (for member 2 and beyond) for
- // the struct/union/class member.
+ // Print the starting squiggly bracket (if this is the first member) or
+ // comma (for member 2 and beyond) for the struct/union/class member.
if (field_idx == 0)
s->PutChar('{');
else
@@ -1137,9 +1135,8 @@ void GoASTContext::DumpValue(lldb::opaque_compiler_type_t type,
uint64_t element_idx;
for (element_idx = 0; element_idx < a->GetLength(); ++element_idx) {
- // Print the starting squiggly bracket (if this is the
- // first member) or comman (for member 2 and beyong) for
- // the struct/union/class member.
+ // Print the starting squiggly bracket (if this is the first member) or
+ // comman (for member 2 and beyong) for the struct/union/class member.
if (element_idx == 0)
s->PutChar('{');
else
diff --git a/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp b/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp
index 691afdf5ed06..21aa2557518d 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp
@@ -170,9 +170,9 @@ int LineEntry::Compare(const LineEntry &a, const LineEntry &b) {
if (a_byte_size > b_byte_size)
return +1;
- // Check for an end sequence entry mismatch after we have determined
- // that the address values are equal. If one of the items is an end
- // sequence, we don't care about the line, file, or column info.
+ // Check for an end sequence entry mismatch after we have determined that the
+ // address values are equal. If one of the items is an end sequence, we don't
+ // care about the line, file, or column info.
if (a.is_terminal_entry > b.is_terminal_entry)
return -1;
if (a.is_terminal_entry < b.is_terminal_entry)
@@ -192,8 +192,8 @@ int LineEntry::Compare(const LineEntry &a, const LineEntry &b) {
}
AddressRange LineEntry::GetSameLineContiguousAddressRange() const {
- // Add each LineEntry's range to complete_line_range until we find
- // a different file / line number.
+ // Add each LineEntry's range to complete_line_range until we find a
+ // different file / line number.
AddressRange complete_line_range = range;
while (true) {
@@ -206,9 +206,8 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange() const {
if (next_line_sc.line_entry.IsValid() &&
next_line_sc.line_entry.range.GetByteSize() > 0 &&
original_file == next_line_sc.line_entry.original_file) {
- // Include any line 0 entries - they indicate that this is
- // compiler-generated code
- // that does not correspond to user source code.
+ // Include any line 0 entries - they indicate that this is compiler-
+ // generated code that does not correspond to user source code.
if (next_line_sc.line_entry.line == 0) {
complete_line_range.SetByteSize(
complete_line_range.GetByteSize() +
@@ -217,10 +216,9 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange() const {
}
if (line == next_line_sc.line_entry.line) {
- // next_line_sc is the same file & line as this LineEntry, so extend our
- // AddressRange by its size and continue to see if there are more
- // LineEntries
- // that we can combine.
+ // next_line_sc is the same file & line as this LineEntry, so extend
+ // our AddressRange by its size and continue to see if there are more
+ // LineEntries that we can combine.
complete_line_range.SetByteSize(
complete_line_range.GetByteSize() +
next_line_sc.line_entry.range.GetByteSize());
diff --git a/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp b/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp
index 3cb305302927..06e30219f09a 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp
@@ -73,30 +73,24 @@ void LineTable::AppendLineEntryToSequence(
is_terminal_entry);
entry_collection &entries = seq->m_entries;
// Replace the last entry if the address is the same, otherwise append it. If
- // we have multiple
- // line entries at the same address, this indicates illegal DWARF so this
- // "fixes" the line table
- // to be correct. If not fixed this can cause a line entry's address that when
- // resolved back to
- // a symbol context, could resolve to a different line entry. We really want a
+ // we have multiple line entries at the same address, this indicates illegal
+ // DWARF so this "fixes" the line table to be correct. If not fixed this can
+ // cause a line entry's address that when resolved back to a symbol context,
+ // could resolve to a different line entry. We really want a
// 1 to 1 mapping
- // here to avoid these kinds of inconsistencies. We will need tor revisit this
- // if the DWARF line
- // tables are updated to allow multiple entries at the same address legally.
+ // here to avoid these kinds of inconsistencies. We will need tor revisit
+ // this if the DWARF line tables are updated to allow multiple entries at the
+ // same address legally.
if (!entries.empty() && entries.back().file_addr == file_addr) {
// GCC don't use the is_prologue_end flag to mark the first instruction
// after the prologue.
// Instead of it it is issuing a line table entry for the first instruction
- // of the prologue
- // and one for the first instruction after the prologue. If the size of the
- // prologue is 0
- // instruction then the 2 line entry will have the same file address.
- // Removing it will remove
- // our ability to properly detect the location of the end of prologe so we
- // set the prologue_end
- // flag to preserve this information (setting the prologue_end flag for an
- // entry what is after
- // the prologue end don't have any effect)
+ // of the prologue and one for the first instruction after the prologue. If
+ // the size of the prologue is 0 instruction then the 2 line entry will
+ // have the same file address. Removing it will remove our ability to
+ // properly detect the location of the end of prologe so we set the
+ // prologue_end flag to preserve this information (setting the prologue_end
+ // flag for an entry what is after the prologue end don't have any effect)
entry.is_prologue_end = entry.file_idx == entries.back().file_idx;
entries.back() = entry;
} else
@@ -200,14 +194,13 @@ bool LineTable::FindLineEntryByAddress(const Address &so_addr,
if (pos->file_addr != search_entry.file_addr)
--pos;
else if (pos->file_addr == search_entry.file_addr) {
- // If this is a termination entry, it shouldn't match since
- // entries with the "is_terminal_entry" member set to true
- // are termination entries that define the range for the
- // previous entry.
+ // If this is a termination entry, it shouldn't match since entries
+ // with the "is_terminal_entry" member set to true are termination
+ // entries that define the range for the previous entry.
if (pos->is_terminal_entry) {
- // The matching entry is a terminal entry, so we skip
- // ahead to the next entry to see if there is another
- // entry following this one whose section/offset matches.
+ // The matching entry is a terminal entry, so we skip ahead to
+ // the next entry to see if there is another entry following this
+ // one whose section/offset matches.
++pos;
if (pos != end_pos) {
if (pos->file_addr != search_entry.file_addr)
@@ -216,9 +209,8 @@ bool LineTable::FindLineEntryByAddress(const Address &so_addr,
}
if (pos != end_pos) {
- // While in the same section/offset backup to find the first
- // line entry that matches the address in case there are
- // multiple
+ // While in the same section/offset backup to find the first line
+ // entry that matches the address in case there are multiple
while (pos != begin_pos) {
entry_collection::const_iterator prev_pos = pos - 1;
if (prev_pos->file_addr == search_entry.file_addr &&
@@ -232,16 +224,15 @@ bool LineTable::FindLineEntryByAddress(const Address &so_addr,
}
else
{
- // There might be code in the containing objfile before the first line
- // table entry. Make sure that does not get considered part of the first
- // line table entry.
+ // There might be code in the containing objfile before the first
+ // line table entry. Make sure that does not get considered part of
+ // the first line table entry.
if (pos->file_addr > so_addr.GetFileAddress())
return false;
}
// Make sure we have a valid match and that the match isn't a
- // terminating
- // entry for a previous line...
+ // terminating entry for a previous line...
if (pos != end_pos && pos->is_terminal_entry == false) {
uint32_t match_idx = std::distance(begin_pos, pos);
success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
@@ -304,8 +295,7 @@ uint32_t LineTable::FindLineEntryIndexByFileIndex(
continue;
// Exact match always wins. Otherwise try to find the closest line > the
- // desired
- // line.
+ // desired line.
// FIXME: Maybe want to find the line closest before and the line closest
// after and
// if they're not in the same function, don't return a match.
@@ -349,8 +339,7 @@ uint32_t LineTable::FindLineEntryIndexByFileIndex(uint32_t start_idx,
continue;
// Exact match always wins. Otherwise try to find the closest line > the
- // desired
- // line.
+ // desired line.
// FIXME: Maybe want to find the line closest before and the line closest
// after and
// if they're not in the same function, don't return a match.
@@ -389,8 +378,8 @@ size_t LineTable::FineLineEntriesForFileIndex(uint32_t file_idx, bool append,
SymbolContext sc(m_comp_unit);
for (size_t idx = 0; idx < count; ++idx) {
- // Skip line table rows that terminate the previous row (is_terminal_entry
- // is non-zero)
+ // Skip line table rows that terminate the previous row
+ // (is_terminal_entry is non-zero)
if (m_entries[idx].is_terminal_entry)
continue;
@@ -497,10 +486,9 @@ LineTable *LineTable::LinkLineTable(const FileRangeMap &file_range_map) {
terminate_previous_entry = prev_entry_was_linked;
}
} else if (prev_entry_was_linked) {
- // This entry doesn't have a remapping and it needs to be removed.
- // Watch out in case we need to terminate a previous entry needs to
- // be terminated now that one line entry in a sequence is not longer
- // valid.
+ // This entry doesn't have a remapping and it needs to be removed. Watch
+ // out in case we need to terminate a previous entry needs to be
+ // terminated now that one line entry in a sequence is not longer valid.
if (!sequence.m_entries.empty() &&
!sequence.m_entries.back().is_terminal_entry) {
terminate_previous_entry = true;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp b/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp
index 2129a4463cdd..59012b1f8261 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Symbol/ObjectFile.h"
-#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
@@ -16,7 +15,6 @@
#include "lldb/Symbol/ObjectContainer.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBuffer.h"
@@ -51,10 +49,9 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
const bool file_exists = file->Exists();
if (!data_sp) {
- // We have an object name which most likely means we have
- // a .o file in a static archive (.a file). Try and see if
- // we have a cached archive first without reading any data
- // first
+ // We have an object name which most likely means we have a .o file in
+ // a static archive (.a file). Try and see if we have a cached archive
+ // first without reading any data first
if (file_exists && module_sp->GetObjectName()) {
for (uint32_t idx = 0;
(create_object_container_callback =
@@ -73,10 +70,10 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
return object_file_sp;
}
}
- // Ok, we didn't find any containers that have a named object, now
- // lets read the first 512 bytes from the file so the object file
- // and object container plug-ins can use these bytes to see if they
- // can parse this file.
+ // Ok, we didn't find any containers that have a named object, now lets
+ // read the first 512 bytes from the file so the object file and object
+ // container plug-ins can use these bytes to see if they can parse this
+ // file.
if (file_size > 0) {
data_sp =
DataBufferLLVM::CreateSliceFromPath(file->GetPath(), 512, file_offset);
@@ -99,11 +96,12 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
file = &archive_file;
module_sp->SetFileSpecAndObjectName(archive_file, archive_object);
// Check if this is a object container by iterating through all
- // object
- // container plugin instances and then trying to get an object file
- // from the container plugins since we had a name. Also, don't read
+ // object container plugin instances and then trying to get an
+ // object file from the container plugins since we had a name.
+ // Also, don't read
// ANY data in case there is data cached in the container plug-ins
- // (like BSD archives caching the contained objects within an file).
+ // (like BSD archives caching the contained objects within an
+ // file).
for (uint32_t idx = 0;
(create_object_container_callback =
PluginManager::GetObjectContainerCreateCallbackAtIndex(
@@ -120,8 +118,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
if (object_file_sp.get())
return object_file_sp;
}
- // We failed to find any cached object files in the container
- // plug-ins, so lets read the first 512 bytes and try again below...
+ // We failed to find any cached object files in the container plug-
+ // ins, so lets read the first 512 bytes and try again below...
data_sp = DataBufferLLVM::CreateSliceFromPath(archive_file.GetPath(),
512, file_offset);
}
@@ -129,8 +127,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
}
if (data_sp && data_sp->GetByteSize() > 0) {
- // Check if this is a normal object file by iterating through
- // all object file plugin instances.
+ // Check if this is a normal object file by iterating through all
+ // object file plugin instances.
ObjectFileCreateInstance create_object_file_callback;
for (uint32_t idx = 0;
(create_object_file_callback =
@@ -143,9 +141,9 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
return object_file_sp;
}
- // Check if this is a object container by iterating through
- // all object container plugin instances and then trying to get
- // an object file from the container.
+ // Check if this is a object container by iterating through all object
+ // container plugin instances and then trying to get an object file
+ // from the container.
for (uint32_t idx = 0;
(create_object_container_callback =
PluginManager::GetObjectContainerCreateCallbackAtIndex(
@@ -164,8 +162,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
}
}
}
- // We didn't find it, so clear our shared pointer in case it
- // contains anything and return an empty shared pointer
+ // We didn't find it, so clear our shared pointer in case it contains
+ // anything and return an empty shared pointer
object_file_sp.reset();
return object_file_sp;
}
@@ -186,8 +184,8 @@ ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp,
static_cast<void *>(process_sp.get()), header_addr);
uint32_t idx;
- // Check if this is a normal object file by iterating through
- // all object file plugin instances.
+ // Check if this is a normal object file by iterating through all object
+ // file plugin instances.
ObjectFileCreateMemoryInstance create_callback;
for (idx = 0;
(create_callback =
@@ -201,8 +199,8 @@ ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp,
}
}
- // We didn't find it, so clear our shared pointer in case it
- // contains anything and return an empty shared pointer
+ // We didn't find it, so clear our shared pointer in case it contains
+ // anything and return an empty shared pointer
object_file_sp.reset();
return object_file_sp;
}
@@ -326,11 +324,11 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
const SectionType section_type = section_sp->GetType();
switch (section_type) {
case eSectionTypeInvalid:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSectionTypeCode:
- return eAddressClassCode;
+ return AddressClass::eCode;
case eSectionTypeContainer:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSectionTypeData:
case eSectionTypeDataCString:
case eSectionTypeDataCStringPointers:
@@ -343,7 +341,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
case eSectionTypeDataObjCMessageRefs:
case eSectionTypeDataObjCCFStrings:
case eSectionTypeGoSymtab:
- return eAddressClassData;
+ return AddressClass::eData;
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
case eSectionTypeDWARFDebugAddr:
@@ -355,33 +353,34 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
case eSectionTypeDWARFDebugLoc:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
+ case eSectionTypeDWARFDebugNames:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
case eSectionTypeDWARFDebugStr:
case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
case eSectionTypeDWARFAppleNamespaces:
case eSectionTypeDWARFAppleObjC:
- return eAddressClassDebug;
+ case eSectionTypeDWARFGNUDebugAltLink:
+ return AddressClass::eDebug;
case eSectionTypeEHFrame:
case eSectionTypeARMexidx:
case eSectionTypeARMextab:
case eSectionTypeCompactUnwind:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSectionTypeELFSymbolTable:
case eSectionTypeELFDynamicSymbols:
case eSectionTypeELFRelocationEntries:
case eSectionTypeELFDynamicLinkInfo:
case eSectionTypeOther:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSectionTypeAbsoluteAddress:
// In case of absolute sections decide the address class based on
- // the symbol
- // type because the section type isn't specify if it is a code or a
- // data
- // section.
+ // the symbol type because the section type isn't specify if it is
+ // a code or a data section.
break;
}
}
@@ -390,67 +389,67 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
const SymbolType symbol_type = symbol->GetType();
switch (symbol_type) {
case eSymbolTypeAny:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeAbsolute:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeCode:
- return eAddressClassCode;
+ return AddressClass::eCode;
case eSymbolTypeTrampoline:
- return eAddressClassCode;
+ return AddressClass::eCode;
case eSymbolTypeResolver:
- return eAddressClassCode;
+ return AddressClass::eCode;
case eSymbolTypeData:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeRuntime:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeException:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeSourceFile:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeHeaderFile:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeObjectFile:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeCommonBlock:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeBlock:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeLocal:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeParam:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeVariable:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeVariableType:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeLineEntry:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeLineHeader:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeScopeBegin:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeScopeEnd:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeAdditional:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeCompiler:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeInstrumentation:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeUndefined:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeObjCClass:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeObjCMetaClass:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeObjCIVar:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeReExported:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
}
}
}
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
}
DataBufferSP ObjectFile::ReadMemory(const ProcessSP &process_sp,
@@ -470,16 +469,14 @@ DataBufferSP ObjectFile::ReadMemory(const ProcessSP &process_sp,
size_t ObjectFile::GetData(lldb::offset_t offset, size_t length,
DataExtractor &data) const {
// The entire file has already been mmap'ed into m_data, so just copy from
- // there
- // as the back mmap buffer will be shared with shared pointers.
+ // there as the back mmap buffer will be shared with shared pointers.
return data.SetData(m_data, offset, length);
}
size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length,
void *dst) const {
// The entire file has already been mmap'ed into m_data, so just copy from
- // there
- // Note that the data remains in target byte order.
+ // there Note that the data remains in target byte order.
return m_data.CopyData(offset, length, dst);
}
@@ -559,8 +556,8 @@ size_t ObjectFile::ReadSectionData(Section *section,
return GetData(section->GetFileOffset(), section->GetFileSize(),
section_data);
} else {
- // The object file now contains a full mmap'ed copy of the object file data,
- // so just use this
+ // The object file now contains a full mmap'ed copy of the object file
+ // data, so just use this
if (!section->IsRelocated())
RelocateSection(section);
@@ -581,7 +578,7 @@ bool ObjectFile::SplitArchivePathWithObject(const char *path_with_object,
std::string obj;
if (regex_match.GetMatchAtIndex(path_with_object, 1, path) &&
regex_match.GetMatchAtIndex(path_with_object, 2, obj)) {
- archive_file.SetFile(path, false);
+ archive_file.SetFile(path, false, FileSpec::Style::native);
archive_object.SetCString(obj.c_str());
if (must_exist && !archive_file.Exists())
return false;
@@ -648,41 +645,31 @@ ConstString ObjectFile::GetNextSyntheticSymbolName() {
return ConstString(ss.GetString());
}
-Status ObjectFile::LoadInMemory(Target &target, bool set_pc) {
- Status error;
- ProcessSP process = target.CalculateProcess();
- if (!process)
- return Status("No Process");
- if (set_pc && !GetEntryPointAddress().IsValid())
- return Status("No entry address in object file");
-
+std::vector<ObjectFile::LoadableData>
+ObjectFile::GetLoadableData(Target &target) {
+ std::vector<LoadableData> loadables;
SectionList *section_list = GetSectionList();
if (!section_list)
- return Status("No section in object file");
+ return loadables;
+ // Create a list of loadable data from loadable sections
size_t section_count = section_list->GetNumSections(0);
for (size_t i = 0; i < section_count; ++i) {
+ LoadableData loadable;
SectionSP section_sp = section_list->GetSectionAtIndex(i);
- addr_t addr = target.GetSectionLoadList().GetSectionLoadAddress(section_sp);
- if (addr != LLDB_INVALID_ADDRESS) {
- DataExtractor section_data;
- // We can skip sections like bss
- if (section_sp->GetFileSize() == 0)
- continue;
- section_sp->GetSectionData(section_data);
- lldb::offset_t written = process->WriteMemory(
- addr, section_data.GetDataStart(), section_data.GetByteSize(), error);
- if (written != section_data.GetByteSize())
- return error;
- }
- }
- if (set_pc) {
- ThreadList &thread_list = process->GetThreadList();
- ThreadSP curr_thread(thread_list.GetSelectedThread());
- RegisterContextSP reg_context(curr_thread->GetRegisterContext());
- Address file_entry = GetEntryPointAddress();
- reg_context->SetPC(file_entry.GetLoadAddress(&target));
+ loadable.Dest =
+ target.GetSectionLoadList().GetSectionLoadAddress(section_sp);
+ if (loadable.Dest == LLDB_INVALID_ADDRESS)
+ continue;
+ // We can skip sections like bss
+ if (section_sp->GetFileSize() == 0)
+ continue;
+ DataExtractor section_data;
+ section_sp->GetSectionData(section_data);
+ loadable.Contents = llvm::ArrayRef<uint8_t>(section_data.GetDataStart(),
+ section_data.GetByteSize());
+ loadables.push_back(loadable);
}
- return error;
+ return loadables;
}
void ObjectFile::RelocateSection(lldb_private::Section *section)
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp b/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp
index ab297ef330f2..69fd5424bd9a 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp
@@ -122,9 +122,9 @@ ConstString Symbol::GetDisplayName() const {
ConstString Symbol::GetReExportedSymbolName() const {
if (m_type == eSymbolTypeReExported) {
- // For eSymbolTypeReExported, the "const char *" from a ConstString
- // is used as the offset in the address range base address. We can
- // then make this back into a string that is the re-exported name.
+ // For eSymbolTypeReExported, the "const char *" from a ConstString is used
+ // as the offset in the address range base address. We can then make this
+ // back into a string that is the re-exported name.
intptr_t str_ptr = m_addr_range.GetBaseAddress().GetOffset();
if (str_ptr != 0)
return ConstString((const char *)str_ptr);
@@ -136,9 +136,9 @@ ConstString Symbol::GetReExportedSymbolName() const {
FileSpec Symbol::GetReExportedSymbolSharedLibrary() const {
if (m_type == eSymbolTypeReExported) {
- // For eSymbolTypeReExported, the "const char *" from a ConstString
- // is used as the offset in the address range base address. We can
- // then make this back into a string that is the re-exported name.
+ // For eSymbolTypeReExported, the "const char *" from a ConstString is used
+ // as the offset in the address range base address. We can then make this
+ // back into a string that is the re-exported name.
intptr_t str_ptr = m_addr_range.GetByteSize();
if (str_ptr != 0)
return FileSpec((const char *)str_ptr, false);
@@ -148,15 +148,15 @@ FileSpec Symbol::GetReExportedSymbolSharedLibrary() const {
void Symbol::SetReExportedSymbolName(const ConstString &name) {
SetType(eSymbolTypeReExported);
- // For eSymbolTypeReExported, the "const char *" from a ConstString
- // is used as the offset in the address range base address.
+ // For eSymbolTypeReExported, the "const char *" from a ConstString is used
+ // as the offset in the address range base address.
m_addr_range.GetBaseAddress().SetOffset((uintptr_t)name.GetCString());
}
bool Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec) {
if (m_type == eSymbolTypeReExported) {
- // For eSymbolTypeReExported, the "const char *" from a ConstString
- // is used as the offset in the address range base address.
+ // For eSymbolTypeReExported, the "const char *" from a ConstString is used
+ // as the offset in the address range base address.
m_addr_range.SetByteSize(
(uintptr_t)ConstString(fspec.GetPath().c_str()).GetCString());
return true;
@@ -262,9 +262,8 @@ uint32_t Symbol::GetPrologueByteSize() {
Function *function = base_address.CalculateSymbolContextFunction();
if (function) {
// Functions have line entries which can also potentially have end of
- // prologue information.
- // So if this symbol points to a function, use the prologue information
- // from there.
+ // prologue information. So if this symbol points to a function, use
+ // the prologue information from there.
m_type_data = function->GetPrologueByteSize();
} else {
ModuleSP module_sp(base_address.GetModule());
@@ -280,10 +279,9 @@ uint32_t Symbol::GetPrologueByteSize() {
Address addr(base_address);
addr.Slide(m_type_data);
- // Check the first few instructions and look for one that has a line
- // number that is
- // different than the first entry. This is also done in
- // Function::GetPrologueByteSize().
+ // Check the first few instructions and look for one that has a
+ // line number that is different than the first entry. This is also
+ // done in Function::GetPrologueByteSize().
uint16_t total_offset = m_type_data;
for (int idx = 0; idx < 6; ++idx) {
SymbolContext sc_temp;
@@ -293,8 +291,8 @@ uint32_t Symbol::GetPrologueByteSize() {
if (!(resolved_flags & eSymbolContextLineEntry))
break;
- // If this line number is different than our first one, use it and
- // we're done.
+ // If this line number is different than our first one, use it
+ // and we're done.
if (sc_temp.line_entry.line != sc.line_entry.line) {
m_type_data = total_offset;
break;
@@ -309,12 +307,10 @@ uint32_t Symbol::GetPrologueByteSize() {
}
// Sanity check - this may be a function in the middle of code that
- // has debug information, but
- // not for this symbol. So the line entries surrounding us won't
- // lie inside our function.
- // In that case, the line entry will be bigger than we are, so we do
- // that quick check and
- // if that is true, we just return 0.
+ // has debug information, but not for this symbol. So the line
+ // entries surrounding us won't lie inside our function. In that
+ // case, the line entry will be bigger than we are, so we do that
+ // quick check and if that is true, we just return 0.
if (m_type_data >= m_addr_range.GetByteSize())
m_type_data = 0;
} else {
@@ -420,9 +416,9 @@ Symbol *Symbol::ResolveReExportedSymbolInModuleSpec(
// Try searching for the module file spec first using the full path
module_sp = target.GetImages().FindFirstModule(module_spec);
if (!module_sp) {
- // Next try and find the module by basename in case environment
- // variables or other runtime trickery causes shared libraries
- // to be loaded from alternate paths
+ // Next try and find the module by basename in case environment variables
+ // or other runtime trickery causes shared libraries to be loaded from
+ // alternate paths
module_spec.GetFileSpec().GetDirectory().Clear();
module_sp = target.GetImages().FindFirstModule(module_spec);
}
@@ -430,8 +426,7 @@ Symbol *Symbol::ResolveReExportedSymbolInModuleSpec(
if (module_sp) {
// There should not be cycles in the reexport list, but we don't want to
- // crash if there are so make sure
- // we haven't seen this before:
+ // crash if there are so make sure we haven't seen this before:
if (!seen_modules.AppendIfNeeded(module_sp))
return nullptr;
@@ -449,8 +444,8 @@ Symbol *Symbol::ResolveReExportedSymbolInModuleSpec(
}
}
// If we didn't find the symbol in this module, it may be because this
- // module re-exports some
- // whole other library. We have to search those as well:
+ // module re-exports some whole other library. We have to search those as
+ // well:
seen_modules.Append(module_sp);
FileSpecList reexported_libraries =
diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
index 4ac35010c74c..8716f50a384d 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
@@ -359,8 +359,7 @@ void SymbolContext::Dump(Stream *s, Target *target) const {
if (block != nullptr)
*s << " {0x" << block->GetID() << '}';
// Dump the block and pass it a negative depth to we print all the parent
- // blocks
- // if (block != NULL)
+ // blocks if (block != NULL)
// block->Dump(s, function->GetFileAddress(), INT_MIN);
s->EOL();
s->Indent();
@@ -468,27 +467,27 @@ bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc,
if (block) {
// const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
- // In order to get the parent of an inlined function we first need to
- // see if we are in an inlined block as "this->block" could be an
- // inlined block, or a parent of "block" could be. So lets check if
- // this block or one of this blocks parents is an inlined function.
+ // In order to get the parent of an inlined function we first need to see
+ // if we are in an inlined block as "this->block" could be an inlined
+ // block, or a parent of "block" could be. So lets check if this block or
+ // one of this blocks parents is an inlined function.
Block *curr_inlined_block = block->GetContainingInlinedBlock();
if (curr_inlined_block) {
- // "this->block" is contained in an inline function block, so to
- // get the scope above the inlined block, we get the parent of the
- // inlined block itself
+ // "this->block" is contained in an inline function block, so to get the
+ // scope above the inlined block, we get the parent of the inlined block
+ // itself
Block *next_frame_block = curr_inlined_block->GetParent();
// Now calculate the symbol context of the containing block
next_frame_block->CalculateSymbolContext(&next_frame_sc);
// If we get here we weren't able to find the return line entry using the
- // nesting of the blocks and
- // the line table. So just use the call site info from our inlined block.
+ // nesting of the blocks and the line table. So just use the call site
+ // info from our inlined block.
AddressRange range;
if (curr_inlined_block->GetRangeContainingAddress(curr_frame_pc, range)) {
- // To see there this new frame block it, we need to look at the
- // call site information from
+ // To see there this new frame block it, we need to look at the call
+ // site information from
const InlineFunctionInfo *curr_inlined_block_inlined_info =
curr_inlined_block->GetInlinedFunctionInfo();
next_frame_pc = range.GetBaseAddress();
@@ -550,22 +549,22 @@ bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc,
Block *SymbolContext::GetFunctionBlock() {
if (function) {
if (block) {
- // If this symbol context has a block, check to see if this block
- // is itself, or is contained within a block with inlined function
- // information. If so, then the inlined block is the block that
- // defines the function.
+ // If this symbol context has a block, check to see if this block is
+ // itself, or is contained within a block with inlined function
+ // information. If so, then the inlined block is the block that defines
+ // the function.
Block *inlined_block = block->GetContainingInlinedBlock();
if (inlined_block)
return inlined_block;
- // The block in this symbol context is not inside an inlined
- // block, so the block that defines the function is the function's
- // top level block, which is returned below.
+ // The block in this symbol context is not inside an inlined block, so
+ // the block that defines the function is the function's top level block,
+ // which is returned below.
}
- // There is no block information in this symbol context, so we must
- // assume that the block that is desired is the top level block of
- // the function itself.
+ // There is no block information in this symbol context, so we must assume
+ // that the block that is desired is the top level block of the function
+ // itself.
return &function->GetBlock(true);
}
return nullptr;
@@ -594,8 +593,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
isInlinedblock = true;
//----------------------------------------------------------------------
- // Find all types that match the current block if we have one and put
- // them first in the list. Keep iterating up through all blocks.
+ // Find all types that match the current block if we have one and put them
+ // first in the list. Keep iterating up through all blocks.
//----------------------------------------------------------------------
while (curr_block != nullptr && !isInlinedblock) {
type_map.ForEach(
@@ -606,8 +605,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
return true; // Keep iterating
});
- // Remove any entries that are now in "type_list" from "type_map"
- // since we can't remove from type_map while iterating
+ // Remove any entries that are now in "type_list" from "type_map" since we
+ // can't remove from type_map while iterating
type_list.ForEach([&type_map](const lldb::TypeSP &type_sp) -> bool {
type_map.Remove(type_sp);
return true; // Keep iterating
@@ -615,8 +614,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
curr_block = curr_block->GetParent();
}
//----------------------------------------------------------------------
- // Find all types that match the current function, if we have onem, and
- // put them next in the list.
+ // Find all types that match the current function, if we have onem, and put
+ // them next in the list.
//----------------------------------------------------------------------
if (function != nullptr && !type_map.Empty()) {
const size_t old_type_list_size = type_list.GetSize();
@@ -627,8 +626,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
return true; // Keep iterating
});
- // Remove any entries that are now in "type_list" from "type_map"
- // since we can't remove from type_map while iterating
+ // Remove any entries that are now in "type_list" from "type_map" since we
+ // can't remove from type_map while iterating
const size_t new_type_list_size = type_list.GetSize();
if (new_type_list_size > old_type_list_size) {
for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
@@ -636,8 +635,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
}
}
//----------------------------------------------------------------------
- // Find all types that match the current compile unit, if we have one,
- // and put them next in the list.
+ // Find all types that match the current compile unit, if we have one, and
+ // put them next in the list.
//----------------------------------------------------------------------
if (comp_unit != nullptr && !type_map.Empty()) {
const size_t old_type_list_size = type_list.GetSize();
@@ -649,8 +648,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
return true; // Keep iterating
});
- // Remove any entries that are now in "type_list" from "type_map"
- // since we can't remove from type_map while iterating
+ // Remove any entries that are now in "type_list" from "type_map" since we
+ // can't remove from type_map while iterating
const size_t new_type_list_size = type_list.GetSize();
if (new_type_list_size > old_type_list_size) {
for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
@@ -658,8 +657,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
}
}
//----------------------------------------------------------------------
- // Find all types that match the current module, if we have one, and put
- // them next in the list.
+ // Find all types that match the current module, if we have one, and put them
+ // next in the list.
//----------------------------------------------------------------------
if (module_sp && !type_map.Empty()) {
const size_t old_type_list_size = type_list.GetSize();
@@ -669,8 +668,8 @@ void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
type_list.Insert(type_sp);
return true; // Keep iterating
});
- // Remove any entries that are now in "type_list" from "type_map"
- // since we can't remove from type_map while iterating
+ // Remove any entries that are now in "type_list" from "type_map" since we
+ // can't remove from type_map while iterating
const size_t new_type_list_size = type_list.GetSize();
if (new_type_list_size > old_type_list_size) {
for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
@@ -831,9 +830,9 @@ SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error)
case eSymbolTypeObjCMetaClass:
case eSymbolTypeObjCIVar:
if (symbol->GetDemangledNameIsSynthesized()) {
- // If the demangled name was synthesized, then don't use it
- // for expressions. Only let the symbol match if the mangled
- // named matches for these symbols.
+ // If the demangled name was synthesized, then don't use it for
+ // expressions. Only let the symbol match if the mangled named
+ // matches for these symbols.
if (symbol->GetMangled().GetMangledName() != name)
break;
}
@@ -861,8 +860,8 @@ SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error)
target.GetImages().FindFirstModule(reexport_module_spec);
}
}
- // Don't allow us to try and resolve a re-exported symbol if it is
- // the same as the current symbol
+ // Don't allow us to try and resolve a re-exported symbol if it
+ // is the same as the current symbol
if (name == symbol->GetReExportedSymbolName() &&
module == reexport_module_sp.get())
return nullptr;
@@ -1012,9 +1011,8 @@ bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
} break;
case eFileSpecified:
// CompUnits can't necessarily be resolved here, since an inlined function
- // might show up in
- // a number of CompUnits. Instead we just convert to a FileSpec and store
- // it away.
+ // might show up in a number of CompUnits. Instead we just convert to a
+ // FileSpec and store it away.
m_file_spec_ap.reset(new FileSpec(spec_string, false));
m_type |= eFileSpecified;
break;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp
index eb20b80f4916..6b4da9c53009 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp
@@ -30,8 +30,7 @@ SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) {
if (obj_file != nullptr) {
// We need to test the abilities of this section list. So create what it
- // would
- // be with this new obj_file.
+ // would be with this new obj_file.
lldb::ModuleSP module_sp(obj_file->GetModule());
if (module_sp) {
// Default to the main module section list.
@@ -60,16 +59,16 @@ SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) {
if (sym_file_abilities > best_symfile_abilities) {
best_symfile_abilities = sym_file_abilities;
best_symfile_ap.reset(curr_symfile_ap.release());
- // If any symbol file parser has all of the abilities, then
- // we should just stop looking.
+ // If any symbol file parser has all of the abilities, then we should
+ // just stop looking.
if ((kAllAbilities & sym_file_abilities) == kAllAbilities)
break;
}
}
}
if (best_symfile_ap.get()) {
- // Let the winning symbol file parser initialize itself more
- // completely now that it has been chosen
+ // Let the winning symbol file parser initialize itself more completely
+ // now that it has been chosen
best_symfile_ap->InitializeObject();
}
}
@@ -97,19 +96,16 @@ uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec,
return 0;
}
-uint32_t SymbolFile::FindGlobalVariables(
- const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches, VariableList &variables) {
- if (!append)
- variables.Clear();
+uint32_t
+SymbolFile::FindGlobalVariables(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ uint32_t max_matches, VariableList &variables) {
return 0;
}
uint32_t SymbolFile::FindGlobalVariables(const RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
VariableList &variables) {
- if (!append)
- variables.Clear();
return 0;
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp
index f5a08739f24d..245f7bbf8add 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp
@@ -26,9 +26,9 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// FindPlugin
//
-// Platforms can register a callback to use when creating symbol
-// vendors to allow for complex debug information file setups, and to
-// also allow for finding separate debug information files.
+// Platforms can register a callback to use when creating symbol vendors to
+// allow for complex debug information file setups, and to also allow for
+// finding separate debug information files.
//----------------------------------------------------------------------
SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp,
lldb_private::Stream *feedback_strm) {
@@ -45,8 +45,8 @@ SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp,
return instance_ap.release();
}
}
- // The default implementation just tries to create debug information using the
- // file representation for the module.
+ // The default implementation just tries to create debug information using
+ // the file representation for the module.
instance_ap.reset(new SymbolVendor(module_sp));
if (instance_ap.get()) {
ObjectFile *objfile = module_sp->GetObjectFile();
@@ -88,11 +88,11 @@ bool SymbolVendor::SetCompileUnitAtIndex(size_t idx, const CompUnitSP &cu_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
const size_t num_compile_units = GetNumCompileUnits();
if (idx < num_compile_units) {
- // Fire off an assertion if this compile unit already exists for now.
- // The partial parsing should take care of only setting the compile
- // unit once, so if this assertion fails, we need to make sure that
- // we don't have a race condition, or have a second parse of the same
- // compile unit.
+ // Fire off an assertion if this compile unit already exists for now. The
+ // partial parsing should take care of only setting the compile unit
+ // once, so if this assertion fails, we need to make sure that we don't
+ // have a race condition, or have a second parse of the same compile
+ // unit.
assert(m_compile_units[idx].get() == nullptr);
m_compile_units[idx] = cu_sp;
return true;
@@ -111,10 +111,10 @@ size_t SymbolVendor::GetNumCompileUnits() {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_compile_units.empty()) {
if (m_sym_file_ap.get()) {
- // Resize our array of compile unit shared pointers -- which will
- // each remain NULL until someone asks for the actual compile unit
- // information. When this happens, the symbol file will be asked
- // to parse this compile unit information.
+ // Resize our array of compile unit shared pointers -- which will each
+ // remain NULL until someone asks for the actual compile unit
+ // information. When this happens, the symbol file will be asked to
+ // parse this compile unit information.
m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits());
}
}
@@ -260,28 +260,28 @@ uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec,
return 0;
}
-size_t SymbolVendor::FindGlobalVariables(
- const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- bool append, size_t max_matches, VariableList &variables) {
+size_t
+SymbolVendor::FindGlobalVariables(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ size_t max_matches, VariableList &variables) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx, append,
+ return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx,
max_matches, variables);
}
return 0;
}
size_t SymbolVendor::FindGlobalVariables(const RegularExpression &regex,
- bool append, size_t max_matches,
+ size_t max_matches,
VariableList &variables) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches,
- variables);
+ return m_sym_file_ap->FindGlobalVariables(regex, max_matches, variables);
}
return 0;
}
@@ -392,6 +392,8 @@ void SymbolVendor::Dump(Stream *s) {
}
}
s->EOL();
+ if (m_sym_file_ap)
+ m_sym_file_ap->Dump(*s);
s->IndentMore();
m_type_list.Dump(s, show_context);
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
index 4ac30649110f..c502b18555f0 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
@@ -100,9 +100,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
} break;
case eSortOrderByName: {
- // Although we maintain a lookup by exact name map, the table
- // isn't sorted by name. So we must make the ordered symbol list
- // up ourselves.
+ // Although we maintain a lookup by exact name map, the table isn't
+ // sorted by name. So we must make the ordered symbol list up ourselves.
s->PutCString(" (sorted by name):\n");
DumpSymbolHeader(s);
typedef std::multimap<const char *, const Symbol *,
@@ -228,8 +227,8 @@ void Symtab::InitNameIndexes() {
m_name_to_index.Reserve(num_symbols);
#else
// TODO: benchmark this to see if we save any memory. Otherwise we
- // will always keep the memory reserved in the vector unless we pull
- // some STL swap magic and then recopy...
+ // will always keep the memory reserved in the vector unless we pull some
+ // STL swap magic and then recopy...
uint32_t actual_count = 0;
for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
pos != end; ++pos) {
@@ -255,11 +254,10 @@ void Symtab::InitNameIndexes() {
for (entry.value = 0; entry.value < num_symbols; ++entry.value) {
const Symbol *symbol = &m_symbols[entry.value];
- // Don't let trampolines get into the lookup by name map
- // If we ever need the trampoline symbols to be searchable by name
- // we can remove this and then possibly add a new bool to any of the
- // Symtab functions that lookup symbols by name to indicate if they
- // want trampolines.
+ // Don't let trampolines get into the lookup by name map If we ever need
+ // the trampoline symbols to be searchable by name we can remove this and
+ // then possibly add a new bool to any of the Symtab functions that
+ // lookup symbols by name to indicate if they want trampolines.
if (symbol->IsTrampoline())
continue;
@@ -293,10 +291,9 @@ void Symtab::InitNameIndexes() {
mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
entry.cstring = ConstString(cxx_method.GetBasename());
if (entry.cstring) {
- // ConstString objects permanently store the string in the pool so
- // calling
- // GetCString() on the value gets us a const char * that will
- // never go away
+ // ConstString objects permanently store the string in the pool
+ // so calling GetCString() on the value gets us a const char *
+ // that will never go away
const char *const_context =
ConstString(cxx_method.GetContext()).GetCString();
@@ -312,25 +309,25 @@ void Symtab::InitNameIndexes() {
if (entry_ref[0] == '~' ||
!cxx_method.GetQualifiers().empty()) {
// The first character of the demangled basename is '~' which
- // means we have a class destructor. We can use this information
- // to help us know what is a class and what isn't.
+ // means we have a class destructor. We can use this
+ // information to help us know what is a class and what
+ // isn't.
if (class_contexts.find(const_context) == class_contexts.end())
class_contexts.insert(const_context);
m_method_to_index.Append(entry);
} else {
if (class_contexts.find(const_context) !=
class_contexts.end()) {
- // The current decl context is in our "class_contexts" which
- // means
- // this is a method on a class
+ // The current decl context is in our "class_contexts"
+ // which means this is a method on a class
m_method_to_index.Append(entry);
} else {
- // We don't know if this is a function basename or a method,
- // so put it into a temporary collection so once we are done
- // we can look in class_contexts to see if each entry is a
- // class
- // or just a function and will put any remaining items into
- // m_method_to_index or m_basename_to_index as needed
+ // We don't know if this is a function basename or a
+ // method, so put it into a temporary collection so once we
+ // are done we can look in class_contexts to see if each
+ // entry is a class or just a function and will put any
+ // remaining items into m_method_to_index or
+ // m_basename_to_index as needed
mangled_name_to_index.Append(entry);
symbol_contexts[entry.value] = const_context;
}
@@ -354,9 +351,8 @@ void Symtab::InitNameIndexes() {
}
}
- // If the demangled name turns out to be an ObjC name, and
- // is a category name, add the version without categories to the index
- // too.
+ // If the demangled name turns out to be an ObjC name, and is a category
+ // name, add the version without categories to the index too.
ObjCLanguage::MethodName objc_method(entry.cstring.GetStringRef(), true);
if (objc_method.IsValid(true)) {
entry.cstring = objc_method.GetSelector();
@@ -383,8 +379,7 @@ void Symtab::InitNameIndexes() {
m_method_to_index.Append(entry);
} else {
// If we got here, we have something that had a context (was inside
- // a namespace or class)
- // yet we don't know if the entry
+ // a namespace or class) yet we don't know if the entry
m_method_to_index.Append(entry);
m_basename_to_index.Append(entry);
}
@@ -520,20 +515,15 @@ struct SymbolIndexComparator {
std::vector<lldb::addr_t> &addr_cache;
// Getting from the symbol to the Address to the File Address involves some
- // work.
- // Since there are potentially many symbols here, and we're using this for
- // sorting so
- // we're going to be computing the address many times, cache that in
- // addr_cache.
- // The array passed in has to be the same size as the symbols array passed
- // into the
- // member variable symbols, and should be initialized with
- // LLDB_INVALID_ADDRESS.
+ // work. Since there are potentially many symbols here, and we're using this
+ // for sorting so we're going to be computing the address many times, cache
+ // that in addr_cache. The array passed in has to be the same size as the
+ // symbols array passed into the member variable symbols, and should be
+ // initialized with LLDB_INVALID_ADDRESS.
// NOTE: You have to make addr_cache externally and pass it in because
// std::stable_sort
// makes copies of the comparator it is initially passed in, and you end up
- // spending
- // huge amounts of time copying this array...
+ // spending huge amounts of time copying this array...
SymbolIndexComparator(const std::vector<Symbol> &s,
std::vector<lldb::addr_t> &a)
@@ -584,8 +574,7 @@ void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
// NOTE: The use of std::stable_sort instead of std::sort here is strictly for
// performance,
// not correctness. The indexes vector tends to be "close" to sorted, which
- // the
- // stable sort handles better.
+ // the stable sort handles better.
std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
@@ -752,14 +741,14 @@ Symtab::FindAllSymbolsWithNameAndType(const ConstString &name,
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
- // Initialize all of the lookup by name indexes before converting NAME
- // to a uniqued string NAME_STR below.
+ // Initialize all of the lookup by name indexes before converting NAME to a
+ // uniqued string NAME_STR below.
if (!m_name_indexes_computed)
InitNameIndexes();
if (name) {
- // The string table did have a string that matched, but we need
- // to check the symbols and match the symbol_type if any was given.
+ // The string table did have a string that matched, but we need to check
+ // the symbols and match the symbol_type if any was given.
AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
}
return symbol_indexes.size();
@@ -772,14 +761,14 @@ size_t Symtab::FindAllSymbolsWithNameAndType(
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
- // Initialize all of the lookup by name indexes before converting NAME
- // to a uniqued string NAME_STR below.
+ // Initialize all of the lookup by name indexes before converting NAME to a
+ // uniqued string NAME_STR below.
if (!m_name_indexes_computed)
InitNameIndexes();
if (name) {
- // The string table did have a string that matched, but we need
- // to check the symbols and match the symbol_type if any was given.
+ // The string table did have a string that matched, but we need to check
+ // the symbols and match the symbol_type if any was given.
AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
symbol_visibility, symbol_indexes);
}
@@ -810,8 +799,8 @@ Symbol *Symtab::FindFirstSymbolWithNameAndType(const ConstString &name,
if (name) {
std::vector<uint32_t> matching_indexes;
- // The string table did have a string that matched, but we need
- // to check the symbols and match the symbol_type if any was given.
+ // The string table did have a string that matched, but we need to check
+ // the symbols and match the symbol_type if any was given.
if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
symbol_visibility,
matching_indexes)) {
@@ -835,8 +824,8 @@ typedef struct {
addr_t match_offset;
} SymbolSearchInfo;
-// Add all the section file start address & size to the RangeVector,
-// recusively adding any children sections.
+// Add all the section file start address & size to the RangeVector, recusively
+// adding any children sections.
static void AddSectionsToRangeMap(SectionList *sectlist,
RangeVector<addr_t, addr_t> &section_ranges) {
const int num_sections = sectlist->GetNumSections(0);
@@ -885,9 +874,9 @@ void Symtab::InitAddressIndexes() {
// Create a RangeVector with the start & size of all the sections for
// this objfile. We'll need to check this for any FileRangeToIndexMap
- // entries with an uninitialized size, which could potentially be a
- // large number so reconstituting the weak pointer is busywork when it
- // is invariant information.
+ // entries with an uninitialized size, which could potentially be a large
+ // number so reconstituting the weak pointer is busywork when it is
+ // invariant information.
SectionList *sectlist = m_objfile->GetSectionList();
RangeVector<addr_t, addr_t> section_ranges;
if (sectlist) {
@@ -922,9 +911,8 @@ void Symtab::InitAddressIndexes() {
if (next_base_addr > curr_base_addr) {
addr_t size_to_next_symbol = next_base_addr - curr_base_addr;
- // Take the difference between this symbol and the next one as its
- // size,
- // if it is less than the size of the section.
+ // Take the difference between this symbol and the next one as
+ // its size, if it is less than the size of the section.
if (sym_size == 0 || size_to_next_symbol < sym_size) {
sym_size = size_to_next_symbol;
}
@@ -958,8 +946,7 @@ void Symtab::CalculateSymbolSizes() {
for (size_t i = 0; i < num_entries; ++i) {
// The entries in the m_file_addr_to_index have calculated the sizes
- // already
- // so we will use this size if we need to.
+ // already so we will use this size if we need to.
const FileRangeToIndexMap::Entry &entry =
m_file_addr_to_index.GetEntryRef(i);
@@ -1086,8 +1073,8 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name,
}
if (name_type_mask & eFunctionNameTypeBase) {
- // From mangled names we can't tell what is a basename and what
- // is a method name, so we just treat them the same
+ // From mangled names we can't tell what is a basename and what is a method
+ // name, so we just treat them the same
if (!m_name_indexes_computed)
InitNameIndexes();
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Type.cpp b/contrib/llvm/tools/lldb/source/Symbol/Type.cpp
index 53bf3e850055..b62c55f76e2b 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Type.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Type.cpp
@@ -387,8 +387,8 @@ bool Type::DumpValueInMemory(ExecutionContext *exe_ctx, Stream *s,
bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr,
AddressType address_type, DataExtractor &data) {
if (address_type == eAddressTypeFile) {
- // Can't convert a file address to anything valid without more
- // context (which Module it came from)
+ // Can't convert a file address to anything valid without more context
+ // (which Module it came from)
return false;
}
@@ -533,10 +533,8 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
}
// When we have a EncodingUID, our "m_flags.compiler_type_resolve_state" is
- // set to eResolveStateUnresolved
- // so we need to update it to say that we now have a forward declaration
- // since that is what we created
- // above.
+ // set to eResolveStateUnresolved so we need to update it to say that we
+ // now have a forward declaration since that is what we created above.
if (m_compiler_type.IsValid())
m_flags.compiler_type_resolve_state = eResolveStateForward;
}
@@ -556,8 +554,8 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
}
}
- // If we have an encoding type, then we need to make sure it is
- // resolved appropriately.
+ // If we have an encoding type, then we need to make sure it is resolved
+ // appropriately.
if (m_encoding_uid != LLDB_INVALID_UID) {
if (encoding_type == nullptr)
encoding_type = GetEncodingType();
@@ -847,35 +845,26 @@ TypeImpl &TypeImpl::operator=(const TypeImpl &rhs) {
}
bool TypeImpl::CheckModule(lldb::ModuleSP &module_sp) const {
- // Check if we have a module for this type. If we do and the shared pointer is
- // can be successfully initialized with m_module_wp, return true. Else return
- // false
- // if we didn't have a module, or if we had a module and it has been deleted.
- // Any
- // functions doing anything with a TypeSP in this TypeImpl class should call
- // this
- // function and only do anything with the ivars if this function returns true.
- // If
- // we have a module, the "module_sp" will be filled in with a strong reference
- // to the
- // module so that the module will at least stay around long enough for the
- // type
- // query to succeed.
+ // Check if we have a module for this type. If we do and the shared pointer
+ // is can be successfully initialized with m_module_wp, return true. Else
+ // return false if we didn't have a module, or if we had a module and it has
+ // been deleted. Any functions doing anything with a TypeSP in this TypeImpl
+ // class should call this function and only do anything with the ivars if
+ // this function returns true. If we have a module, the "module_sp" will be
+ // filled in with a strong reference to the module so that the module will at
+ // least stay around long enough for the type query to succeed.
module_sp = m_module_wp.lock();
if (!module_sp) {
lldb::ModuleWP empty_module_wp;
// If either call to "std::weak_ptr::owner_before(...) value returns true,
- // this
- // indicates that m_module_wp once contained (possibly still does) a
- // reference
- // to a valid shared pointer. This helps us know if we had a valid reference
- // to
- // a section which is now invalid because the module it was in was deleted
+ // this indicates that m_module_wp once contained (possibly still does) a
+ // reference to a valid shared pointer. This helps us know if we had a
+ // valid reference to a section which is now invalid because the module it
+ // was in was deleted
if (empty_module_wp.owner_before(m_module_wp) ||
m_module_wp.owner_before(empty_module_wp)) {
// m_module_wp had a valid reference to a module, but all strong
- // references
- // have been released and the module has been deleted
+ // references have been released and the module has been deleted
return false;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp b/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
index 4fcaff3daf90..4a0a06f3e8e3 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
@@ -32,7 +32,8 @@ TypeList::TypeList() : m_types() {}
TypeList::~TypeList() {}
void TypeList::Insert(const TypeSP &type_sp) {
- // Just push each type on the back for now. We will worry about uniquing later
+ // Just push each type on the back for now. We will worry about uniquing
+ // later
if (type_sp)
m_types.push_back(type_sp);
}
@@ -76,6 +77,7 @@ uint32_t TypeList::GetSize() const { return m_types.size(); }
TypeSP TypeList::GetTypeAtIndex(uint32_t idx) {
iterator pos, end;
uint32_t i = idx;
+ assert(i < GetSize() && "Accessing past the end of a TypeList");
for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) {
if (i == 0)
return *pos;
@@ -123,10 +125,10 @@ void TypeList::RemoveMismatchedTypes(const char *qualified_typename,
void TypeList::RemoveMismatchedTypes(const std::string &type_scope,
const std::string &type_basename,
TypeClass type_class, bool exact_match) {
- // Our "collection" type currently is a std::map which doesn't
- // have any good way to iterate and remove items from the map
- // so we currently just make a new list and add all of the matching
- // types to it, and then swap it into m_types at the end
+ // Our "collection" type currently is a std::map which doesn't have any good
+ // way to iterate and remove items from the map so we currently just make a
+ // new list and add all of the matching types to it, and then swap it into
+ // m_types at the end
collection matching_types;
iterator pos, end = m_types.end();
@@ -161,19 +163,15 @@ void TypeList::RemoveMismatchedTypes(const std::string &type_scope,
if (type_scope_pos == match_type_scope_size - type_scope_size) {
if (type_scope_pos >= 2) {
// Our match scope ends with the type scope we were looking
- // for,
- // but we need to make sure what comes before the matching
- // type scope is a namespace boundary in case we are trying to
- // match:
- // type_basename = "d"
- // type_scope = "b::c::"
+ // for, but we need to make sure what comes before the
+ // matching type scope is a namespace boundary in case we are
+ // trying to match: type_basename = "d" type_scope = "b::c::"
// We want to match:
// match_type_scope "a::b::c::"
// But not:
// match_type_scope "a::bb::c::"
// So below we make sure what comes before "b::c::" in
- // match_type_scope
- // is "::", or the namespace boundary
+ // match_type_scope is "::", or the namespace boundary
if (match_type_scope[type_scope_pos - 1] == ':' &&
match_type_scope[type_scope_pos - 2] == ':') {
keep_match = true;
@@ -184,9 +182,8 @@ void TypeList::RemoveMismatchedTypes(const std::string &type_scope,
}
}
} else {
- // The type we are currently looking at doesn't exists
- // in a namespace or class, so it only matches if there
- // is no type scope...
+ // The type we are currently looking at doesn't exists in a namespace
+ // or class, so it only matches if there is no type scope...
keep_match =
type_scope.empty() && type_basename.compare(match_type_name) == 0;
}
@@ -203,10 +200,10 @@ void TypeList::RemoveMismatchedTypes(TypeClass type_class) {
if (type_class == eTypeClassAny)
return;
- // Our "collection" type currently is a std::map which doesn't
- // have any good way to iterate and remove items from the map
- // so we currently just make a new list and add all of the matching
- // types to it, and then swap it into m_types at the end
+ // Our "collection" type currently is a std::map which doesn't have any good
+ // way to iterate and remove items from the map so we currently just make a
+ // new list and add all of the matching types to it, and then swap it into
+ // m_types at the end
collection matching_types;
iterator pos, end = m_types.end();
diff --git a/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp b/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp
index 40c6558d5825..2838039ad603 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp
@@ -45,7 +45,8 @@ TypeMap::TypeMap() : m_types() {}
TypeMap::~TypeMap() {}
void TypeMap::Insert(const TypeSP &type_sp) {
- // Just push each type on the back for now. We will worry about uniquing later
+ // Just push each type on the back for now. We will worry about uniquing
+ // later
if (type_sp)
m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
}
@@ -167,10 +168,10 @@ void TypeMap::RemoveMismatchedTypes(const char *qualified_typename,
void TypeMap::RemoveMismatchedTypes(const std::string &type_scope,
const std::string &type_basename,
TypeClass type_class, bool exact_match) {
- // Our "collection" type currently is a std::map which doesn't
- // have any good way to iterate and remove items from the map
- // so we currently just make a new list and add all of the matching
- // types to it, and then swap it into m_types at the end
+ // Our "collection" type currently is a std::map which doesn't have any good
+ // way to iterate and remove items from the map so we currently just make a
+ // new list and add all of the matching types to it, and then swap it into
+ // m_types at the end
collection matching_types;
iterator pos, end = m_types.end();
@@ -205,19 +206,15 @@ void TypeMap::RemoveMismatchedTypes(const std::string &type_scope,
if (type_scope_pos == match_type_scope_size - type_scope_size) {
if (type_scope_pos >= 2) {
// Our match scope ends with the type scope we were looking
- // for,
- // but we need to make sure what comes before the matching
- // type scope is a namespace boundary in case we are trying to
- // match:
- // type_basename = "d"
- // type_scope = "b::c::"
+ // for, but we need to make sure what comes before the
+ // matching type scope is a namespace boundary in case we are
+ // trying to match: type_basename = "d" type_scope = "b::c::"
// We want to match:
// match_type_scope "a::b::c::"
// But not:
// match_type_scope "a::bb::c::"
// So below we make sure what comes before "b::c::" in
- // match_type_scope
- // is "::", or the namespace boundary
+ // match_type_scope is "::", or the namespace boundary
if (match_type_scope[type_scope_pos - 1] == ':' &&
match_type_scope[type_scope_pos - 2] == ':') {
keep_match = true;
@@ -228,9 +225,8 @@ void TypeMap::RemoveMismatchedTypes(const std::string &type_scope,
}
}
} else {
- // The type we are currently looking at doesn't exists
- // in a namespace or class, so it only matches if there
- // is no type scope...
+ // The type we are currently looking at doesn't exists in a namespace
+ // or class, so it only matches if there is no type scope...
keep_match =
type_scope.empty() && type_basename.compare(match_type_name) == 0;
}
@@ -247,10 +243,10 @@ void TypeMap::RemoveMismatchedTypes(TypeClass type_class) {
if (type_class == eTypeClassAny)
return;
- // Our "collection" type currently is a std::map which doesn't
- // have any good way to iterate and remove items from the map
- // so we currently just make a new list and add all of the matching
- // types to it, and then swap it into m_types at the end
+ // Our "collection" type currently is a std::map which doesn't have any good
+ // way to iterate and remove items from the map so we currently just make a
+ // new list and add all of the matching types to it, and then swap it into
+ // m_types at the end
collection matching_types;
iterator pos, end = m_types.end();
diff --git a/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp b/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp
index 4c0014348c42..23ca1324ab06 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp
@@ -46,8 +46,7 @@ operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
}
// This function doesn't copy the dwarf expression bytes; they must remain in
-// allocated
-// memory for the lifespan of this UnwindPlan object.
+// allocated memory for the lifespan of this UnwindPlan object.
void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
const uint8_t *opcodes, uint32_t len) {
m_type = atDWARFExpression;
@@ -56,8 +55,7 @@ void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
}
// This function doesn't copy the dwarf expression bytes; they must remain in
-// allocated
-// memory for the lifespan of this UnwindPlan object.
+// allocated memory for the lifespan of this UnwindPlan object.
void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression(
const uint8_t *opcodes, uint32_t len) {
m_type = isDWARFExpression;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp b/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp
index 405d57754ea5..7f98eaca2521 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp
@@ -20,10 +20,9 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
-// There is one UnwindTable object per ObjectFile.
-// It contains a list of Unwind objects -- one per function, populated lazily --
-// for the ObjectFile.
-// Each Unwind object has multiple UnwindPlans for different scenarios.
+// There is one UnwindTable object per ObjectFile. It contains a list of Unwind
+// objects -- one per function, populated lazily -- for the ObjectFile. Each
+// Unwind object has multiple UnwindPlans for different scenarios.
using namespace lldb;
using namespace lldb_private;
@@ -33,8 +32,7 @@ UnwindTable::UnwindTable(ObjectFile &objfile)
m_eh_frame_up(), m_compact_unwind_up(), m_arm_unwind_up() {}
// We can't do some of this initialization when the ObjectFile is running its
-// ctor; delay doing it
-// until needed for something.
+// ctor; delay doing it until needed for something.
void UnwindTable::Initialize() {
if (m_initialized)
@@ -134,10 +132,9 @@ UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr,
}
// Ignore any existing FuncUnwinders for this function, create a new one and
-// don't add it to the
-// UnwindTable. This is intended for use by target modules show-unwind where we
-// want to create
-// new UnwindPlans, not re-use existing ones.
+// don't add it to the UnwindTable. This is intended for use by target modules
+// show-unwind where we want to create new UnwindPlans, not re-use existing
+// ones.
FuncUnwindersSP
UnwindTable::GetUncachedFuncUnwindersContainingAddress(const Address &addr,
SymbolContext &sc) {
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp b/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp
index 1957bcef1f3a..af84872a97a0 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp
@@ -239,9 +239,8 @@ bool Variable::LocationIsValidForFrame(StackFrame *frame) {
target_sp.get());
if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
return false;
- // It is a location list. We just need to tell if the location
- // list contains the current address when converted to a load
- // address
+ // It is a location list. We just need to tell if the location list
+ // contains the current address when converted to a load address
return m_location.LocationListContainsAddress(
loclist_base_load_addr,
frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get()));
@@ -251,8 +250,8 @@ bool Variable::LocationIsValidForFrame(StackFrame *frame) {
}
bool Variable::LocationIsValidForAddress(const Address &address) {
- // Be sure to resolve the address to section offset prior to
- // calling this function.
+ // Be sure to resolve the address to section offset prior to calling this
+ // function.
if (address.IsSectionOffset()) {
SymbolContext sc;
CalculateSymbolContext(&sc);
@@ -268,9 +267,8 @@ bool Variable::LocationIsValidForAddress(const Address &address) {
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
return false;
- // It is a location list. We just need to tell if the location
- // list contains the current address when converted to a load
- // address
+ // It is a location list. We just need to tell if the location list
+ // contains the current address when converted to a load address
return m_location.LocationListContainsAddress(loclist_base_file_addr,
address.GetFileAddress());
}
@@ -294,8 +292,8 @@ bool Variable::IsInScope(StackFrame *frame) {
case eValueTypeVariableArgument:
case eValueTypeVariableLocal:
if (frame) {
- // We don't have a location list, we just need to see if the block
- // that this variable was defined in is currently
+ // We don't have a location list, we just need to see if the block that
+ // this variable was defined in is currently
Block *deepest_frame_block =
frame->GetSymbolContext(eSymbolContextBlock).block;
if (deepest_frame_block) {
@@ -313,8 +311,7 @@ bool Variable::IsInScope(StackFrame *frame) {
return false;
// If no scope range is specified then it means that the scope is the
- // same as the
- // scope of the enclosing lexical block.
+ // same as the scope of the enclosing lexical block.
if (m_scope_range.IsEmpty())
return true;
@@ -455,8 +452,8 @@ Status Variable::GetValuesForVariableExpressionPath(
}
bool Variable::DumpLocationForAddress(Stream *s, const Address &address) {
- // Be sure to resolve the address to section offset prior to
- // calling this function.
+ // Be sure to resolve the address to section offset prior to calling this
+ // function.
if (address.IsSectionOffset()) {
SymbolContext sc;
CalculateSymbolContext(&sc);
@@ -647,11 +644,12 @@ static void PrivateAutoComplete(
break;
case '-':
- if (partial_path[1] == '>' && !prefix_path.str().empty()) {
+ if (partial_path.size() > 1 && partial_path[1] == '>' &&
+ !prefix_path.str().empty()) {
switch (type_class) {
case lldb::eTypeClassPointer: {
CompilerType pointee_type(compiler_type.GetPointeeType());
- if (partial_path[2]) {
+ if (partial_path.size() > 2 && partial_path[2]) {
// If there is more after the "->", then search deeper
PrivateAutoComplete(
frame, partial_path.substr(2), prefix_path + "->",
@@ -675,7 +673,7 @@ static void PrivateAutoComplete(
case lldb::eTypeClassUnion:
case lldb::eTypeClassStruct:
case lldb::eTypeClassClass:
- if (partial_path[1]) {
+ if (partial_path.size() > 1 && partial_path[1]) {
// If there is more after the ".", then search deeper
PrivateAutoComplete(frame, partial_path.substr(1),
prefix_path + ".", compiler_type, matches,
@@ -759,13 +757,15 @@ static void PrivateAutoComplete(
}
size_t Variable::AutoComplete(const ExecutionContext &exe_ctx,
- llvm::StringRef partial_path, StringList &matches,
- bool &word_complete) {
- word_complete = false;
+ CompletionRequest &request) {
CompilerType compiler_type;
- PrivateAutoComplete(exe_ctx.GetFramePtr(), partial_path, "", compiler_type,
- matches, word_complete);
+ bool word_complete = false;
+ StringList matches;
+ PrivateAutoComplete(exe_ctx.GetFramePtr(), request.GetCursorArgumentPrefix(),
+ "", compiler_type, matches, word_complete);
+ request.SetWordComplete(word_complete);
+ request.AddCompletions(matches);
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ABI.cpp b/contrib/llvm/tools/lldb/source/Target/ABI.cpp
index 72f58be5a3d4..8d4513ad6811 100644
--- a/contrib/llvm/tools/lldb/source/Target/ABI.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ABI.cpp
@@ -102,15 +102,18 @@ ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
// work.
if (persistent) {
+ Target &target = *thread.CalculateTarget();
PersistentExpressionState *persistent_expression_state =
- thread.CalculateTarget()->GetPersistentExpressionStateForLanguage(
+ target.GetPersistentExpressionStateForLanguage(
ast_type.GetMinimumLanguage());
if (!persistent_expression_state)
return ValueObjectSP();
- ConstString persistent_variable_name(
- persistent_expression_state->GetNextPersistentVariableName());
+ auto prefix = persistent_expression_state->GetPersistentVariablePrefix();
+ ConstString persistent_variable_name =
+ persistent_expression_state->GetNextPersistentVariableName(target,
+ prefix);
lldb::ValueObjectSP const_valobj_sp;
@@ -193,18 +196,18 @@ bool ABI::PrepareTrivialCall(Thread &thread, lldb::addr_t sp,
bool ABI::GetFallbackRegisterLocation(
const RegisterInfo *reg_info,
UnwindPlan::Row::RegisterLocation &unwind_regloc) {
- // Did the UnwindPlan fail to give us the caller's stack pointer?
- // The stack pointer is defined to be the same as THIS frame's CFA, so return
- // the CFA value as
- // the caller's stack pointer. This is true on x86-32/x86-64 at least.
+ // Did the UnwindPlan fail to give us the caller's stack pointer? The stack
+ // pointer is defined to be the same as THIS frame's CFA, so return the CFA
+ // value as the caller's stack pointer. This is true on x86-32/x86-64 at
+ // least.
if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP) {
unwind_regloc.SetIsCFAPlusOffset(0);
return true;
}
// If a volatile register is being requested, we don't want to forward the
- // next frame's register contents
- // up the stack -- the register is not retrievable at this frame.
+ // next frame's register contents up the stack -- the register is not
+ // retrievable at this frame.
if (RegisterIsVolatile(reg_info)) {
unwind_regloc.SetUndefined();
return true;
diff --git a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
index 3643c1590421..73c64916cf1f 100644
--- a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
@@ -369,15 +369,14 @@ ExecutionContext &ExecutionContext::operator=(const ExecutionContext &rhs) {
bool ExecutionContext::operator==(const ExecutionContext &rhs) const {
// Check that the frame shared pointers match, or both are valid and their
- // stack
- // IDs match since sometimes we get new objects that represent the same
+ // stack IDs match since sometimes we get new objects that represent the same
// frame within a thread.
if ((m_frame_sp == rhs.m_frame_sp) ||
(m_frame_sp && rhs.m_frame_sp &&
m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) {
- // Check that the thread shared pointers match, or both are valid and
- // their thread IDs match since sometimes we get new objects that
- // represent the same thread within a process.
+ // Check that the thread shared pointers match, or both are valid and their
+ // thread IDs match since sometimes we get new objects that represent the
+ // same thread within a process.
if ((m_thread_sp == rhs.m_thread_sp) ||
(m_thread_sp && rhs.m_thread_sp &&
m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) {
@@ -596,9 +595,9 @@ lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {
lldb::ThreadSP thread_sp(m_thread_wp.lock());
if (m_tid != LLDB_INVALID_THREAD_ID) {
- // We check if the thread has been destroyed in cases where clients
- // might still have shared pointer to a thread, but the thread is
- // not valid anymore (not part of the process)
+ // We check if the thread has been destroyed in cases where clients might
+ // still have shared pointer to a thread, but the thread is not valid
+ // anymore (not part of the process)
if (!thread_sp || !thread_sp->IsValid()) {
lldb::ProcessSP process_sp(GetProcessSP());
if (process_sp && process_sp->IsValid()) {
@@ -608,9 +607,8 @@ lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {
}
}
- // Check that we aren't about to return an invalid thread sp. We might return
- // a nullptr thread_sp,
- // but don't return an invalid one.
+ // Check that we aren't about to return an invalid thread sp. We might
+ // return a nullptr thread_sp, but don't return an invalid one.
if (thread_sp && !thread_sp->IsValid())
thread_sp.reset();
diff --git a/contrib/llvm/tools/lldb/source/Target/Memory.cpp b/contrib/llvm/tools/lldb/source/Target/Memory.cpp
index ced359418682..ad1b4093155d 100644
--- a/contrib/llvm/tools/lldb/source/Target/Memory.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Memory.cpp
@@ -133,12 +133,12 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
Status &error) {
size_t bytes_left = dst_len;
- // Check the L1 cache for a range that contain the entire memory read.
- // If we find a range in the L1 cache that does, we use it. Else we fall
- // back to reading memory in m_L2_cache_line_byte_size byte sized chunks.
- // The L1 cache contains chunks of memory that are not required to be
- // m_L2_cache_line_byte_size bytes in size, so we don't try anything
- // tricky when reading from them (no partial reads from the L1 cache).
+ // Check the L1 cache for a range that contain the entire memory read. If we
+ // find a range in the L1 cache that does, we use it. Else we fall back to
+ // reading memory in m_L2_cache_line_byte_size byte sized chunks. The L1
+ // cache contains chunks of memory that are not required to be
+ // m_L2_cache_line_byte_size bytes in size, so we don't try anything tricky
+ // when reading from them (no partial reads from the L1 cache).
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_L1_cache.empty()) {
@@ -155,11 +155,11 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
}
}
- // If this memory read request is larger than the cache line size, then
- // we (1) try to read as much of it at once as possible, and (2) don't
- // add the data to the memory cache. We don't want to split a big read
- // up into more separate reads than necessary, and with a large memory read
- // request, it is unlikely that the caller function will ask for the next
+ // If this memory read request is larger than the cache line size, then we
+ // (1) try to read as much of it at once as possible, and (2) don't add the
+ // data to the memory cache. We don't want to split a big read up into more
+ // separate reads than necessary, and with a large memory read request, it is
+ // unlikely that the caller function will ask for the next
// 4 bytes after the large memory read - so there's little benefit to saving
// it in the cache.
if (dst && dst_len > m_L2_cache_line_byte_size) {
@@ -218,9 +218,9 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
bytes_left -= curr_read_size;
curr_addr += curr_read_size;
- // We have a cache page that succeeded to read some bytes
- // but not an entire page. If this happens, we must cap
- // off how much data we are able to read...
+ // We have a cache page that succeeded to read some bytes but not
+ // an entire page. If this happens, we must cap off how much data
+ // we are able to read...
if (pos->second->GetByteSize() != cache_line_byte_size)
return dst_len - bytes_left;
}
@@ -277,8 +277,8 @@ lldb::addr_t AllocatedBlock::ReserveBlock(uint32_t size) {
if (range_size >= size)
{
// We found a free block that is big enough for our data. Figure out how
- // many chunks we will need and calculate the resulting block size we will
- // reserve.
+ // many chunks we will need and calculate the resulting block size we
+ // will reserve.
addr_t addr = free_block.GetRangeBase();
size_t num_chunks = CalculateChunksNeededForSize(size);
lldb::addr_t block_size = num_chunks * m_chunk_size;
@@ -296,8 +296,8 @@ lldb::addr_t AllocatedBlock::ReserveBlock(uint32_t size) {
// Make the new allocated range and add it to the allocated ranges.
Range<lldb::addr_t, uint32_t> reserved_block(free_block);
reserved_block.SetByteSize(block_size);
- // Insert the reserved range and don't combine it with other blocks
- // in the reserved blocks list.
+ // Insert the reserved range and don't combine it with other blocks in
+ // the reserved blocks list.
m_reserved_blocks.Insert(reserved_block, false);
// Adjust the free range in place since we won't change the sorted
// ordering of the m_free_blocks list.
diff --git a/contrib/llvm/tools/lldb/source/Target/ModuleCache.cpp b/contrib/llvm/tools/lldb/source/Target/ModuleCache.cpp
index 2b654772639a..19adfbabe277 100644
--- a/contrib/llvm/tools/lldb/source/Target/ModuleCache.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ModuleCache.cpp
@@ -312,9 +312,8 @@ Status ModuleCache::GetAndPut(const FileSpec &root_dir_spec,
llvm::FileRemover tmp_symfile_remover(tmp_download_sym_file_spec.GetPath());
if (error.Fail())
// Failed to download a symfile but fetching the module was successful. The
- // module might
- // contain the necessary symbols and the debugging is also possible without
- // a symfile.
+ // module might contain the necessary symbols and the debugging is also
+ // possible without a symfile.
return Status();
error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec,
diff --git a/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
index d3cc7c019dce..b1fcee6db63b 100644
--- a/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
@@ -23,6 +23,7 @@
#include "lldb/Utility/Timer.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DJB.h"
using namespace lldb;
using namespace lldb_private;
@@ -45,8 +46,7 @@ bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
if (isa != 0) {
m_isa_to_descriptor[isa] = descriptor_sp;
// class_name is assumed to be valid
- m_hash_to_isa_map.insert(
- std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa));
+ m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa));
return true;
}
return false;
@@ -170,8 +170,7 @@ ObjCLanguageRuntime::GetDescriptorIterator(const ConstString &name) {
UpdateISAToDescriptorMap();
if (m_hash_to_isa_map.empty()) {
// No name hashes were provided, we need to just linearly power through
- // the
- // names and find a match
+ // the names and find a match
for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
pos != end; ++pos) {
if (pos->second->GetClassName() == name)
@@ -180,8 +179,7 @@ ObjCLanguageRuntime::GetDescriptorIterator(const ConstString &name) {
} else {
// Name hashes were provided, so use them to efficiently lookup name to
// isa/descriptor
- const uint32_t name_hash =
- MappedHash::HashStringUsingDJB(name.GetCString());
+ const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
std::pair<HashToISAIterator, HashToISAIterator> range =
m_hash_to_isa_map.equal_range(name_hash);
for (HashToISAIterator range_pos = range.first; range_pos != range.second;
@@ -240,9 +238,9 @@ ObjCLanguageRuntime::GetClassDescriptorFromClassName(
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) {
ClassDescriptorSP objc_class_sp;
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
+ // if we get an invalid VO (which might still happen when playing around with
+ // pointers returned by the expression parser, don't consider this a valid
+ // ObjC object)
if (valobj.GetCompilerType().IsValid()) {
addr_t isa_pointer = valobj.GetPointerValue();
if (isa_pointer != LLDB_INVALID_ADDRESS) {
diff --git a/contrib/llvm/tools/lldb/source/Target/PathMappingList.cpp b/contrib/llvm/tools/lldb/source/Target/PathMappingList.cpp
index 782c6e49623c..778728eebb09 100644
--- a/contrib/llvm/tools/lldb/source/Target/PathMappingList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/PathMappingList.cpp
@@ -14,6 +14,7 @@
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-private-enumerations.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Utility/FileSpec.h"
@@ -23,6 +24,22 @@
using namespace lldb;
using namespace lldb_private;
+namespace {
+ // We must normalize our path pairs that we store because if we don't then
+ // things won't always work. We found a case where if we did:
+ // (lldb) settings set target.source-map . /tmp
+ // We would store a path pairs of "." and "/tmp" as raw strings. If the debug
+ // info contains "./foo/bar.c", the path will get normalized to "foo/bar.c".
+ // When PathMappingList::RemapPath() is called, it expects the path to start
+ // with the raw path pair, which doesn't work anymore because the paths have
+ // been normalized when the debug info was loaded. So we need to store
+ // nomalized path pairs to ensure things match up.
+ ConstString NormalizePath(const ConstString &path) {
+ // If we use "path" to construct a FileSpec, it will normalize the path for
+ // us. We then grab the string and turn it back into a ConstString.
+ return ConstString(FileSpec(path.GetStringRef(), false).GetPath());
+ }
+}
//----------------------------------------------------------------------
// PathMappingList constructor
//----------------------------------------------------------------------
@@ -52,7 +69,7 @@ PathMappingList::~PathMappingList() = default;
void PathMappingList::Append(const ConstString &path,
const ConstString &replacement, bool notify) {
++m_mod_id;
- m_pairs.push_back(pair(path, replacement));
+ m_pairs.emplace_back(pair(NormalizePath(path), NormalizePath(replacement)));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
}
@@ -77,7 +94,8 @@ void PathMappingList::Insert(const ConstString &path,
insert_iter = m_pairs.end();
else
insert_iter = m_pairs.begin() + index;
- m_pairs.insert(insert_iter, pair(path, replacement));
+ m_pairs.emplace(insert_iter, pair(NormalizePath(path),
+ NormalizePath(replacement)));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
}
@@ -88,7 +106,7 @@ bool PathMappingList::Replace(const ConstString &path,
if (index >= m_pairs.size())
return false;
++m_mod_id;
- m_pairs[index] = pair(path, replacement);
+ m_pairs[index] = pair(NormalizePath(path), NormalizePath(replacement));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
return true;
@@ -134,22 +152,10 @@ void PathMappingList::Clear(bool notify) {
bool PathMappingList::RemapPath(const ConstString &path,
ConstString &new_path) const {
- const char *path_cstr = path.GetCString();
- // CLEANUP: Convert this function to use StringRefs internally instead
- // of raw c-strings.
- if (!path_cstr)
- return false;
-
- const_iterator pos, end = m_pairs.end();
- for (pos = m_pairs.begin(); pos != end; ++pos) {
- const size_t prefixLen = pos->first.GetLength();
-
- if (::strncmp(pos->first.GetCString(), path_cstr, prefixLen) == 0) {
- std::string new_path_str(pos->second.GetCString());
- new_path_str.append(path.GetCString() + prefixLen);
- new_path.SetCString(new_path_str.c_str());
- return true;
- }
+ std::string remapped;
+ if (RemapPath(path.GetStringRef(), remapped)) {
+ new_path.SetString(remapped);
+ return true;
}
return false;
}
@@ -158,34 +164,41 @@ bool PathMappingList::RemapPath(llvm::StringRef path,
std::string &new_path) const {
if (m_pairs.empty() || path.empty())
return false;
-
- const_iterator pos, end = m_pairs.end();
- for (pos = m_pairs.begin(); pos != end; ++pos) {
- if (!path.consume_front(pos->first.GetStringRef()))
- continue;
-
- new_path = pos->second.GetStringRef();
- new_path.append(path);
+ LazyBool path_is_relative = eLazyBoolCalculate;
+ for (const auto &it : m_pairs) {
+ auto prefix = it.first.GetStringRef();
+ if (!path.consume_front(prefix)) {
+ // Relative paths won't have a leading "./" in them unless "." is the
+ // only thing in the relative path so we need to work around "."
+ // carefully.
+ if (prefix != ".")
+ continue;
+ // We need to figure out if the "path" argument is relative. If it is,
+ // then we should remap, else skip this entry.
+ if (path_is_relative == eLazyBoolCalculate) {
+ path_is_relative = FileSpec(path, false).IsRelative() ? eLazyBoolYes :
+ eLazyBoolNo;
+ }
+ if (!path_is_relative)
+ continue;
+ }
+ FileSpec remapped(it.second.GetStringRef(), false);
+ remapped.AppendPathComponent(path);
+ new_path = remapped.GetPath();
return true;
}
return false;
}
-bool PathMappingList::ReverseRemapPath(const ConstString &path,
- ConstString &new_path) const {
- const char *path_cstr = path.GetCString();
- if (!path_cstr)
- return false;
-
+bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const {
+ std::string path = file.GetPath();
+ llvm::StringRef path_ref(path);
for (const auto &it : m_pairs) {
- // FIXME: This should be using FileSpec API's to do the path appending.
- const size_t prefixLen = it.second.GetLength();
- if (::strncmp(it.second.GetCString(), path_cstr, prefixLen) == 0) {
- std::string new_path_str(it.first.GetCString());
- new_path_str.append(path.GetCString() + prefixLen);
- new_path.SetCString(new_path_str.c_str());
- return true;
- }
+ if (!path_ref.consume_front(it.second.GetStringRef()))
+ continue;
+ fixed.SetFile(it.first.GetStringRef(), false, FileSpec::Style::native);
+ fixed.AppendPathComponent(path_ref);
+ return true;
}
return false;
}
@@ -203,7 +216,8 @@ bool PathMappingList::FindFile(const FileSpec &orig_spec,
if (orig_path_len >= prefix_len) {
if (::strncmp(pos->first.GetCString(), orig_path, prefix_len) == 0) {
- new_spec.SetFile(pos->second.GetCString(), false);
+ new_spec.SetFile(pos->second.GetCString(), false,
+ FileSpec::Style::native);
new_spec.AppendPathComponent(orig_path + prefix_len);
if (new_spec.Exists())
return true;
@@ -277,7 +291,8 @@ bool PathMappingList::GetPathsAtIndex(uint32_t idx, ConstString &path,
return false;
}
-uint32_t PathMappingList::FindIndexForPath(const ConstString &path) const {
+uint32_t PathMappingList::FindIndexForPath(const ConstString &orig_path) const {
+ const ConstString path = NormalizePath(orig_path);
const_iterator pos;
const_iterator begin = m_pairs.begin();
const_iterator end = m_pairs.end();
diff --git a/contrib/llvm/tools/lldb/source/Target/Platform.cpp b/contrib/llvm/tools/lldb/source/Target/Platform.cpp
index 5d60bb791555..5ae556ecc02a 100644
--- a/contrib/llvm/tools/lldb/source/Target/Platform.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Platform.cpp
@@ -10,6 +10,7 @@
// C Includes
// C++ Includes
#include <algorithm>
+#include <csignal>
#include <fstream>
#include <vector>
@@ -45,8 +46,8 @@
#include "llvm/Support/FileSystem.h"
-// Define these constants from POSIX mman.h rather than include the file
-// so that they will be correct even when compiled on Linux.
+// Define these constants from POSIX mman.h rather than include the file so
+// that they will be correct even when compiled on Linux.
#define MAP_PRIVATE 2
#define MAP_ANON 0x1000
@@ -55,8 +56,8 @@ using namespace lldb_private;
static uint32_t g_initialize_count = 0;
-// Use a singleton function for g_local_platform_sp to avoid init
-// constructors since LLDB is often part of a shared library
+// Use a singleton function for g_local_platform_sp to avoid init constructors
+// since LLDB is often part of a shared library
static PlatformSP &GetHostPlatformSP() {
static PlatformSP g_platform_sp;
return g_platform_sp;
@@ -368,13 +369,11 @@ ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef trip
Platform::Platform(bool is_host)
: m_is_host(is_host), m_os_version_set_while_connected(false),
m_system_arch_set_while_connected(false), m_sdk_sysroot(), m_sdk_build(),
- m_working_dir(), m_remote_url(), m_name(), m_major_os_version(UINT32_MAX),
- m_minor_os_version(UINT32_MAX), m_update_os_version(UINT32_MAX),
- m_system_arch(), m_mutex(), m_uid_map(), m_gid_map(),
- m_max_uid_name_len(0), m_max_gid_name_len(0), m_supports_rsync(false),
- m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
- m_ignores_remote_hostname(false), m_trap_handlers(),
- m_calculated_trap_handlers(false),
+ m_working_dir(), m_remote_url(), m_name(), m_system_arch(), m_mutex(),
+ m_uid_map(), m_gid_map(), m_max_uid_name_len(0), m_max_gid_name_len(0),
+ m_supports_rsync(false), m_rsync_opts(), m_rsync_prefix(),
+ m_supports_ssh(false), m_ssh_opts(), m_ignores_remote_hostname(false),
+ m_trap_handlers(), m_calculated_trap_handlers(false),
m_module_cache(llvm::make_unique<ModuleCache>()) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
if (log)
@@ -394,9 +393,6 @@ Platform::~Platform() {
}
void Platform::GetStatus(Stream &strm) {
- uint32_t major = UINT32_MAX;
- uint32_t minor = UINT32_MAX;
- uint32_t update = UINT32_MAX;
std::string s;
strm.Printf(" Platform: %s\n", GetPluginName().GetCString());
@@ -409,12 +405,9 @@ void Platform::GetStatus(Stream &strm) {
}
}
- if (GetOSVersion(major, minor, update)) {
- strm.Printf("OS Version: %u", major);
- if (minor != UINT32_MAX)
- strm.Printf(".%u", minor);
- if (update != UINT32_MAX)
- strm.Printf(".%u", update);
+ llvm::VersionTuple os_version = GetOSVersion();
+ if (!os_version.empty()) {
+ strm.Format("OS Version: {0}", os_version.getAsString());
if (GetOSBuildString(s))
strm.Printf(" (%s)", s.c_str());
@@ -446,17 +439,14 @@ void Platform::GetStatus(Stream &strm) {
strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
}
-bool Platform::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update,
- Process *process) {
+llvm::VersionTuple Platform::GetOSVersion(Process *process) {
std::lock_guard<std::mutex> guard(m_mutex);
- bool success = m_major_os_version != UINT32_MAX;
if (IsHost()) {
- if (!success) {
+ if (m_os_version.empty()) {
// We have a local host platform
- success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version,
- m_update_os_version);
- m_os_version_set_while_connected = success;
+ m_os_version = HostInfo::GetOSVersion();
+ m_os_version_set_while_connected = !m_os_version.empty();
}
} else {
// We have a remote platform. We can only fetch the remote
@@ -466,11 +456,10 @@ bool Platform::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update,
const bool is_connected = IsConnected();
bool fetch = false;
- if (success) {
- // We have valid OS version info, check to make sure it wasn't
- // manually set prior to connecting. If it was manually set prior
- // to connecting, then lets fetch the actual OS version info
- // if we are now connected.
+ if (!m_os_version.empty()) {
+ // We have valid OS version info, check to make sure it wasn't manually
+ // set prior to connecting. If it was manually set prior to connecting,
+ // then lets fetch the actual OS version info if we are now connected.
if (is_connected && !m_os_version_set_while_connected)
fetch = true;
} else {
@@ -478,22 +467,18 @@ bool Platform::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update,
fetch = is_connected;
}
- if (fetch) {
- success = GetRemoteOSVersion();
- m_os_version_set_while_connected = success;
- }
+ if (fetch)
+ m_os_version_set_while_connected = GetRemoteOSVersion();
}
- if (success) {
- major = m_major_os_version;
- minor = m_minor_os_version;
- update = m_update_os_version;
- } else if (process) {
- // Check with the process in case it can answer the question if
- // a process was provided
- return process->GetHostOSVersion(major, minor, update);
+ if (!m_os_version.empty())
+ return m_os_version;
+ if (process) {
+ // Check with the process in case it can answer the question if a process
+ // was provided
+ return process->GetHostOSVersion();
}
- return success;
+ return llvm::VersionTuple();
}
bool Platform::GetOSBuildString(std::string &s) {
@@ -577,8 +562,8 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
// now recurse
std::string src_dir_path(src.GetPath());
- // Make a filespec that only fills in the directory of a FileSpec so
- // when we enumerate we can quickly fill in the filename for dst copies
+ // Make a filespec that only fills in the directory of a FileSpec so when
+ // we enumerate we can quickly fill in the filename for dst copies
FileSpec recurse_dst;
recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr,
@@ -656,9 +641,9 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') {
fixed_dst.GetDirectory() = dst.GetDirectory();
}
- // If the fixed destination file doesn't have a directory yet,
- // then we must have a relative path. We will resolve this relative
- // path against the platform's working directory
+ // If the fixed destination file doesn't have a directory yet, then we
+ // must have a relative path. We will resolve this relative path against
+ // the platform's working directory
if (!fixed_dst.GetDirectory()) {
FileSpec relative_spec;
std::string path;
@@ -859,26 +844,22 @@ const char *Platform::GetGroupName(uint32_t gid) {
return nullptr;
}
-bool Platform::SetOSVersion(uint32_t major, uint32_t minor, uint32_t update) {
+bool Platform::SetOSVersion(llvm::VersionTuple version) {
if (IsHost()) {
- // We don't need anyone setting the OS version for the host platform,
- // we should be able to figure it out by calling
- // HostInfo::GetOSVersion(...).
+ // We don't need anyone setting the OS version for the host platform, we
+ // should be able to figure it out by calling HostInfo::GetOSVersion(...).
return false;
} else {
- // We have a remote platform, allow setting the target OS version if
- // we aren't connected, since if we are connected, we should be able to
+ // We have a remote platform, allow setting the target OS version if we
+ // aren't connected, since if we are connected, we should be able to
// request the remote OS version from the connected platform.
if (IsConnected())
return false;
else {
- // We aren't connected and we might want to set the OS version
- // ahead of time before we connect so we can peruse files and
- // use a local SDK or PDK cache of support files to disassemble
- // or do other things.
- m_major_os_version = major;
- m_minor_os_version = minor;
- m_update_os_version = update;
+ // We aren't connected and we might want to set the OS version ahead of
+ // time before we connect so we can peruse files and use a local SDK or
+ // PDK cache of support files to disassemble or do other things.
+ m_os_version = version;
return true;
}
}
@@ -896,9 +877,9 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
module_search_paths_ptr, nullptr,
nullptr);
} else {
- // No valid architecture was specified, ask the platform for
- // the architectures that we should be using (in the correct order)
- // and see if we can find a match that way
+ // No valid architecture was specified, ask the platform for the
+ // architectures that we should be using (in the correct order) and see
+ // if we can find a match that way
ModuleSpec arch_module_spec(module_spec);
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, arch_module_spec.GetArchitecture());
@@ -942,18 +923,17 @@ const ArchSpec &Platform::GetSystemArchitecture() {
m_system_arch_set_while_connected = m_system_arch.IsValid();
}
} else {
- // We have a remote platform. We can only fetch the remote
- // system architecture if we are connected, and we don't want to do it
- // more than once.
+ // We have a remote platform. We can only fetch the remote system
+ // architecture if we are connected, and we don't want to do it more than
+ // once.
const bool is_connected = IsConnected();
bool fetch = false;
if (m_system_arch.IsValid()) {
- // We have valid OS version info, check to make sure it wasn't
- // manually set prior to connecting. If it was manually set prior
- // to connecting, then lets fetch the actual OS version info
- // if we are now connected.
+ // We have valid OS version info, check to make sure it wasn't manually
+ // set prior to connecting. If it was manually set prior to connecting,
+ // then lets fetch the actual OS version info if we are now connected.
if (is_connected && !m_system_arch_set_while_connected)
fetch = true;
} else {
@@ -1025,8 +1005,8 @@ Status Platform::DisconnectRemote() {
bool Platform::GetProcessInfo(lldb::pid_t pid,
ProcessInstanceInfo &process_info) {
- // Take care of the host case so that each subclass can just
- // call this function to get the host functionality.
+ // Take care of the host case so that each subclass can just call this
+ // function to get the host functionality.
if (IsHost())
return Host::GetProcessInfo(pid, process_info);
return false;
@@ -1034,8 +1014,8 @@ bool Platform::GetProcessInfo(lldb::pid_t pid,
uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &process_infos) {
- // Take care of the host case so that each subclass can just
- // call this function to get the host functionality.
+ // Take care of the host case so that each subclass can just call this
+ // function to get the host functionality.
uint32_t match_count = 0;
if (IsHost())
match_count = Host::FindProcesses(match_info, process_infos);
@@ -1048,8 +1028,8 @@ Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {
if (log)
log->Printf("Platform::%s()", __FUNCTION__);
- // Take care of the host case so that each subclass can just
- // call this function to get the host functionality.
+ // Take care of the host case so that each subclass can just call this
+ // function to get the host functionality.
if (IsHost()) {
if (::getenv("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY);
@@ -1106,8 +1086,7 @@ Status Platform::KillProcess(const lldb::pid_t pid) {
log->Printf("Platform::%s, pid %" PRIu64, __FUNCTION__, pid);
// Try to find a process plugin to handle this Kill request. If we can't,
- // fall back to
- // the default OS implementation.
+ // fall back to the default OS implementation.
size_t num_debuggers = Debugger::GetNumDebuggers();
for (size_t didx = 0; didx < num_debuggers; ++didx) {
DebuggerSP debugger = Debugger::GetDebuggerAtIndex(didx);
@@ -1142,23 +1121,22 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
// Make sure we stop at the entry point
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
- // group, since then we can handle ^C interrupts ourselves w/o having to worry
- // about the target getting them as well.
+ // group, since then we can handle ^C interrupts ourselves w/o having to
+ // worry about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
// Allow any StructuredData process-bound plugins to adjust the launch info
// if needed
size_t i = 0;
bool iteration_complete = false;
- // Note iteration can't simply go until a nullptr callback is returned, as
- // it is valid for a plugin to not supply a filter.
+ // Note iteration can't simply go until a nullptr callback is returned, as it
+ // is valid for a plugin to not supply a filter.
auto get_filter_func = PluginManager::GetStructuredDataFilterCallbackAtIndex;
for (auto filter_callback = get_filter_func(i, iteration_complete);
!iteration_complete;
filter_callback = get_filter_func(++i, iteration_complete)) {
if (filter_callback) {
- // Give this ProcessLaunchInfo filter a chance to adjust the launch
- // info.
+ // Give this ProcessLaunchInfo filter a chance to adjust the launch info.
error = (*filter_callback)(launch_info, target);
if (!error.Success()) {
if (log)
@@ -1191,10 +1169,10 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
// process if this happens.
process_sp->SetShouldDetach(false);
- // If we didn't have any file actions, the pseudo terminal might
- // have been used where the slave side was given as the file to
- // open for stdin/out/err after we have already opened the master
- // so we can read/write stdin/out/err.
+ // If we didn't have any file actions, the pseudo terminal might have
+ // been used where the slave side was given as the file to open for
+ // stdin/out/err after we have already opened the master so we can
+ // read/write stdin/out/err.
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
@@ -1313,8 +1291,8 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
offset += bytes_written;
if (bytes_written != bytes_read) {
- // We didn't write the correct number of bytes, so adjust
- // the file position in the source file we are reading from...
+ // We didn't write the correct number of bytes, so adjust the file
+ // position in the source file we are reading from...
source_file.SeekFromStart(offset);
}
}
@@ -1373,12 +1351,10 @@ lldb_private::Status Platform::RunShellCommand(
// process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
if (IsHost())
return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
- command_output, timeout_sec);
+ command_output, timeout);
else
return Status("unimplemented");
}
@@ -1539,10 +1515,7 @@ lldb_private::Status OptionGroupPlatformCaching::SetOptionValue(
return error;
}
-size_t Platform::GetEnvironment(StringList &environment) {
- environment.Clear();
- return false;
-}
+Environment Platform::GetEnvironment() { return Environment(); }
const std::vector<ConstString> &Platform::GetTrapHandlerSymbolNames() {
if (!m_calculated_trap_handlers) {
@@ -1602,9 +1575,9 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
if (module_spec.GetArchitecture().IsValid() == false) {
Status error;
- // No valid architecture was specified, ask the platform for
- // the architectures that we should be using (in the correct order)
- // and see if we can find a match that way
+ // No valid architecture was specified, ask the platform for the
+ // architectures that we should be using (in the correct order) and see if
+ // we can find a match that way
ModuleSpec arch_module_spec(module_spec);
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, arch_module_spec.GetArchitecture());
@@ -1765,7 +1738,7 @@ uint32_t Platform::LoadImage(lldb_private::Process *process,
if (error.Fail())
return LLDB_INVALID_IMAGE_TOKEN;
}
- return DoLoadImage(process, remote_file, error);
+ return DoLoadImage(process, remote_file, nullptr, error);
}
if (local_file) {
@@ -1778,12 +1751,12 @@ uint32_t Platform::LoadImage(lldb_private::Process *process,
if (error.Fail())
return LLDB_INVALID_IMAGE_TOKEN;
}
- return DoLoadImage(process, target_file, error);
- }
+ return DoLoadImage(process, target_file, nullptr, error);
+ }
if (remote_file) {
// Only remote file was specified so we don't have to do any copying
- return DoLoadImage(process, remote_file, error);
+ return DoLoadImage(process, remote_file, nullptr, error);
}
error.SetErrorString("Neither local nor remote file was specified");
@@ -1792,11 +1765,30 @@ uint32_t Platform::LoadImage(lldb_private::Process *process,
uint32_t Platform::DoLoadImage(lldb_private::Process *process,
const lldb_private::FileSpec &remote_file,
- lldb_private::Status &error) {
+ const std::vector<std::string> *paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_image) {
error.SetErrorString("LoadImage is not supported on the current platform");
return LLDB_INVALID_IMAGE_TOKEN;
}
+uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,
+ const lldb_private::FileSpec &remote_filename,
+ const std::vector<std::string> &paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_path)
+{
+ FileSpec file_to_use;
+ if (remote_filename.IsAbsolute())
+ file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
+ false,
+ remote_filename.GetPathStyle());
+ else
+ file_to_use = remote_filename;
+
+ return DoLoadImage(process, file_to_use, &paths, error, loaded_path);
+}
+
Status Platform::UnloadImage(lldb_private::Process *process,
uint32_t image_token) {
return Status("UnloadImage is not supported on the current platform");
@@ -1855,22 +1847,22 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
// TODO: support big-endian arm and thumb trap codes.
case llvm::Triple::arm: {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
- // but the linux kernel does otherwise.
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
+ // linux kernel does otherwise.
static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = eAddressClassUnknown;
+ AddressClass addr_class = AddressClass::eUnknown;
if (bp_loc_sp) {
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == eAddressClassUnknown &&
+ if (addr_class == AddressClass::eUnknown &&
(bp_loc_sp->GetAddress().GetFileAddress() & 1))
- addr_class = eAddressClassCodeAlternateISA;
+ addr_class = AddressClass::eCodeAlternateISA;
}
- if (addr_class == eAddressClassCodeAlternateISA) {
+ if (addr_class == AddressClass::eCodeAlternateISA) {
trap_opcode = g_thumb_breakpoint_opcode;
trap_opcode_size = sizeof(g_thumb_breakpoint_opcode);
} else {
diff --git a/contrib/llvm/tools/lldb/source/Target/Process.cpp b/contrib/llvm/tools/lldb/source/Target/Process.cpp
index 8fb149fab063..c3d8abc9f78d 100644
--- a/contrib/llvm/tools/lldb/source/Target/Process.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Process.cpp
@@ -30,6 +30,7 @@
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
@@ -39,6 +40,7 @@
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
@@ -88,19 +90,18 @@ public:
ProcessOptionValueProperties(const ConstString &name)
: OptionValueProperties(name) {}
- // This constructor is used when creating ProcessOptionValueProperties when it
- // is part of a new lldb_private::Process instance. It will copy all current
- // global property values as needed
+ // This constructor is used when creating ProcessOptionValueProperties when
+ // it is part of a new lldb_private::Process instance. It will copy all
+ // current global property values as needed
ProcessOptionValueProperties(ProcessProperties *global_properties)
: OptionValueProperties(*global_properties->GetValueProperties()) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
uint32_t idx) const override {
- // When getting the value for a key from the process options, we will always
- // try and grab the setting from the current process if there is one. Else
- // we just
- // use the one from this instance.
+ // When getting the value for a key from the process options, we will
+ // always try and grab the setting from the current process if there is
+ // one. Else we just use the one from this instance.
if (exe_ctx) {
Process *process = exe_ctx->GetProcessPtr();
if (process) {
@@ -307,16 +308,7 @@ void ProcessInstanceInfo::Dump(Stream &s, Platform *platform) const {
}
}
- const uint32_t envc = m_environment.GetArgumentCount();
- if (envc > 0) {
- for (uint32_t i = 0; i < envc; i++) {
- const char *env = m_environment.GetArgumentAtIndex(i);
- if (i < 10)
- s.Printf(" env[%u] = %s\n", i, env);
- else
- s.Printf("env[%u] = %s\n", i, env);
- }
- }
+ s.Format("{0}", m_environment);
if (m_arch.IsValid()) {
s.Printf(" arch = ");
@@ -498,7 +490,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
{
bool success;
const bool disable_aslr_arg =
- Args::StringToBoolean(option_arg, true, &success);
+ OptionArgParser::ToBoolean(option_arg, true, &success);
if (success)
disable_aslr = disable_aslr_arg ? eLazyBoolYes : eLazyBoolNo;
else
@@ -511,7 +503,8 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'X': // shell expand args.
{
bool success;
- const bool expand_args = Args::StringToBoolean(option_arg, true, &success);
+ const bool expand_args =
+ OptionArgParser::ToBoolean(option_arg, true, &success);
if (success)
launch_info.SetShellExpandArguments(expand_args);
else
@@ -529,7 +522,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
break;
case 'v':
- launch_info.GetEnvironmentEntries().AppendArgument(option_arg);
+ launch_info.GetEnvironment().insert(option_arg);
break;
default:
@@ -732,7 +725,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
: ProcessProperties(this), UserID(LLDB_INVALID_PROCESS_ID),
Broadcaster((target_sp->GetDebugger().GetBroadcasterManager()),
Process::GetStaticBroadcasterClass().AsCString()),
- m_target_sp(target_sp), m_public_state(eStateUnloaded),
+ m_target_wp(target_sp), m_public_state(eStateUnloaded),
m_private_state(eStateUnloaded),
m_private_state_broadcaster(nullptr,
"lldb.process.internal_state_broadcaster"),
@@ -815,8 +808,8 @@ Process::~Process() {
StopPrivateStateThread();
// ThreadList::Clear() will try to acquire this process's mutex, so
- // explicitly clear the thread list here to ensure that the mutex
- // is not destroyed before the thread list.
+ // explicitly clear the thread list here to ensure that the mutex is not
+ // destroyed before the thread list.
m_thread_list.Clear();
}
@@ -854,13 +847,12 @@ void Process::Finalize() {
// Clear our broadcaster before we proceed with destroying
Broadcaster::Clear();
- // Do any cleanup needed prior to being destructed... Subclasses
- // that override this method should call this superclass method as well.
+ // Do any cleanup needed prior to being destructed... Subclasses that
+ // override this method should call this superclass method as well.
// We need to destroy the loader before the derived Process class gets
- // destroyed
- // since it is very likely that undoing the loader will require access to the
- // real process.
+ // destroyed since it is very likely that undoing the loader will require
+ // access to the real process.
m_dynamic_checkers_ap.reset();
m_abi_sp.reset();
m_os_ap.reset();
@@ -880,8 +872,8 @@ void Process::Finalize() {
m_language_runtimes.clear();
m_instrumentation_runtimes.clear();
m_next_event_action_ap.reset();
- // Clear the last natural stop ID since it has a strong
- // reference to this process
+ // Clear the last natural stop ID since it has a strong reference to this
+ // process
m_mod_id.SetStopEventForLastNaturalStopID(EventSP());
//#ifdef LLDB_CONFIGURATION_DEBUG
// StreamFile s(stdout, false);
@@ -937,14 +929,11 @@ void Process::SynchronouslyNotifyStateChanged(StateType state) {
// FIXME: We need to do some work on events before the general Listener sees
// them.
// For instance if we are continuing from a breakpoint, we need to ensure that
-// we do
-// the little "insert real insn, step & stop" trick. But we can't do that when
-// the
-// event is delivered by the broadcaster - since that is done on the thread that
-// is
-// waiting for new events, so if we needed more than one event for our handling,
-// we would
-// stall. So instead we do it when we fetch the event off of the queue.
+// we do the little "insert real insn, step & stop" trick. But we can't do
+// that when the event is delivered by the broadcaster - since that is done on
+// the thread that is waiting for new events, so if we needed more than one
+// event for our handling, we would stall. So instead we do it when we fetch
+// the event off of the queue.
//
StateType Process::GetNextEvent(EventSP &event_sp) {
@@ -958,21 +947,25 @@ StateType Process::GetNextEvent(EventSP &event_sp) {
return state;
}
-void Process::SyncIOHandler(uint32_t iohandler_id, uint64_t timeout_msec) {
+void Process::SyncIOHandler(uint32_t iohandler_id,
+ const Timeout<std::micro> &timeout) {
// don't sync (potentially context switch) in case where there is no process
// IO
if (!m_process_input_reader)
return;
- uint32_t new_iohandler_id = 0;
- m_iohandler_sync.WaitForValueNotEqualTo(
- iohandler_id, new_iohandler_id, std::chrono::milliseconds(timeout_msec));
+ auto Result = m_iohandler_sync.WaitForValueNotEqualTo(iohandler_id, timeout);
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("Process::%s waited for m_iohandler_sync to change from %u, "
- "new value is %u",
- __FUNCTION__, iohandler_id, new_iohandler_id);
+ if (Result) {
+ LLDB_LOG(
+ log,
+ "waited from m_iohandler_sync to change from {0}. New value is {1}.",
+ iohandler_id, *Result);
+ } else {
+ LLDB_LOG(log, "timed out waiting for m_iohandler_sync to change from {0}.",
+ iohandler_id);
+ }
}
StateType Process::WaitForProcessToStop(const Timeout<std::micro> &timeout,
@@ -980,15 +973,13 @@ StateType Process::WaitForProcessToStop(const Timeout<std::micro> &timeout,
ListenerSP hijack_listener_sp,
Stream *stream, bool use_run_lock) {
// We can't just wait for a "stopped" event, because the stopped event may
- // have restarted the target.
- // We have to actually check each event, and in the case of a stopped event
- // check the restarted flag
- // on the event.
+ // have restarted the target. We have to actually check each event, and in
+ // the case of a stopped event check the restarted flag on the event.
if (event_sp_ptr)
event_sp_ptr->reset();
StateType state = GetState();
- // If we are exited or detached, we won't ever get back to any
- // other valid state...
+ // If we are exited or detached, we won't ever get back to any other valid
+ // state...
if (state == eStateDetached || state == eStateExited)
return state;
@@ -1154,10 +1145,8 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp,
case eStopReasonSignal: {
// Don't select a signal thread if we weren't going to stop at
- // that
- // signal. We have to have had another reason for stopping here,
- // and
- // the user doesn't want to see this thread.
+ // that signal. We have to have had another reason for stopping
+ // here, and the user doesn't want to see this thread.
uint64_t signo = thread->GetStopInfo()->GetValue();
if (process_sp->GetUnixSignals()->GetShouldStop(signo)) {
if (!other_thread)
@@ -1197,10 +1186,9 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp,
}
}
// Drop the ThreadList mutex by here, since GetThreadStatus below might
- // have to run code,
- // e.g. for Data formatters, and if we hold the ThreadList mutex, then the
- // process is going to
- // have a hard time restarting the process.
+ // have to run code, e.g. for Data formatters, and if we hold the
+ // ThreadList mutex, then the process is going to have a hard time
+ // restarting the process.
if (stream) {
Debugger &debugger = process_sp->GetTarget().GetDebugger();
if (debugger.GetTargetList().GetSelectedTarget().get() ==
@@ -1388,8 +1376,8 @@ bool Process::SetExitStatus(int status, const char *cstr) {
else
m_exit_string.clear();
- // Clear the last natural stop ID since it has a strong
- // reference to this process
+ // Clear the last natural stop ID since it has a strong reference to this
+ // process
m_mod_id.SetStopEventForLastNaturalStopID(EventSP());
SetPrivateState(eStateExited);
@@ -1416,9 +1404,9 @@ bool Process::IsAlive() {
}
}
-// This static callback can be used to watch for local child processes on
-// the current host. The child process exits, the process will be
-// found in the global target list (we want to be completely sure that the
+// This static callback can be used to watch for local child processes on the
+// current host. The child process exits, the process will be found in the
+// global target list (we want to be completely sure that the
// lldb_private::Process doesn't go away before we can deliver the signal.
bool Process::SetProcessExitStatus(
lldb::pid_t pid, bool exited,
@@ -1455,20 +1443,19 @@ void Process::UpdateThreadListIfNeeded() {
const StateType state = GetPrivateState();
if (StateIsStoppedState(state, true)) {
std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- // m_thread_list does have its own mutex, but we need to
- // hold onto the mutex between the call to UpdateThreadList(...)
- // and the os->UpdateThreadList(...) so it doesn't change on us
+ // m_thread_list does have its own mutex, but we need to hold onto the
+ // mutex between the call to UpdateThreadList(...) and the
+ // os->UpdateThreadList(...) so it doesn't change on us
ThreadList &old_thread_list = m_thread_list;
ThreadList real_thread_list(this);
ThreadList new_thread_list(this);
- // Always update the thread list with the protocol specific
- // thread list, but only update if "true" is returned
+ // Always update the thread list with the protocol specific thread list,
+ // but only update if "true" is returned
if (UpdateThreadList(m_thread_list_real, real_thread_list)) {
// Don't call into the OperatingSystem to update the thread list if we
- // are shutting down, since
- // that may call back into the SBAPI's, requiring the API lock which is
- // already held by whoever is
- // shutting us down, causing a deadlock.
+ // are shutting down, since that may call back into the SBAPI's,
+ // requiring the API lock which is already held by whoever is shutting
+ // us down, causing a deadlock.
OperatingSystem *os = GetOperatingSystem();
if (os && !m_destroy_in_process) {
// Clear any old backing threads where memory threads might have been
@@ -1478,12 +1465,9 @@ void Process::UpdateThreadListIfNeeded() {
old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread();
// Turn off dynamic types to ensure we don't run any expressions.
- // Objective C
- // can run an expression to determine if a SBValue is a dynamic type
- // or not
- // and we need to avoid this. OperatingSystem plug-ins can't run
- // expressions
- // that require running code...
+ // Objective-C can run an expression to determine if a SBValue is a
+ // dynamic type or not and we need to avoid this. OperatingSystem
+ // plug-ins can't run expressions that require running code...
Target &target = GetTarget();
const lldb::DynamicValueType saved_prefer_dynamic =
@@ -1592,9 +1576,9 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
const StateType old_state = m_public_state.GetValue();
m_public_state.SetValue(new_state);
- // On the transition from Run to Stopped, we unlock the writer end of the
- // run lock. The lock gets locked in Resume, which is the public API
- // to tell the program to run.
+ // On the transition from Run to Stopped, we unlock the writer end of the run
+ // lock. The lock gets locked in Resume, which is the public API to tell the
+ // program to run.
if (!StateChangedIsExternallyHijacked()) {
if (new_state == eStateDetached) {
if (log)
@@ -1707,17 +1691,16 @@ void Process::SetPrivateState(StateType new_state) {
new Event(eBroadcastBitStateChanged,
new ProcessEventData(shared_from_this(), new_state)));
if (StateIsStoppedState(new_state, false)) {
- // Note, this currently assumes that all threads in the list
- // stop when the process stops. In the future we will want to
- // support a debugging model where some threads continue to run
- // while others are stopped. When that happens we will either need
- // a way for the thread list to identify which threads are stopping
- // or create a special thread list containing only threads which
- // actually stopped.
+ // Note, this currently assumes that all threads in the list stop when
+ // the process stops. In the future we will want to support a debugging
+ // model where some threads continue to run while others are stopped.
+ // When that happens we will either need a way for the thread list to
+ // identify which threads are stopping or create a special thread list
+ // containing only threads which actually stopped.
//
- // The process plugin is responsible for managing the actual
- // behavior of the threads and should have stopped any threads
- // that are going to stop before we get here.
+ // The process plugin is responsible for managing the actual behavior of
+ // the threads and should have stopped any threads that are going to stop
+ // before we get here.
m_thread_list.DidStop();
m_mod_id.BumpStopID();
@@ -1890,8 +1873,8 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner,
break;
}
- // Reset the IsIndirect flag here, in case the location changes from
- // pointing to a indirect symbol to a regular symbol.
+ // Reset the IsIndirect flag here, in case the location changes from pointing
+ // to a indirect symbol to a regular symbol.
owner->SetIsIndirect(false);
if (owner->ShouldResolveIndirectFunctions()) {
@@ -1921,8 +1904,7 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner,
BreakpointSiteSP bp_site_sp;
// Look up this breakpoint site. If it exists, then add this new owner,
- // otherwise
- // create a new breakpoint site and add it.
+ // otherwise create a new breakpoint site and add it.
bp_site_sp = m_breakpoint_site_list.FindByAddress(load_addr);
@@ -2170,7 +2152,8 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) {
return error;
}
-// Uncomment to verify memory caching works after making changes to caching code
+// Uncomment to verify memory caching works after making changes to caching
+// code
//#define VERIFY_MEMORY_READS
size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) {
@@ -2224,8 +2207,8 @@ size_t Process::ReadCStringFromMemory(addr_t addr, std::string &out_str,
if (length == 0)
break;
out_str.append(buf, length);
- // If we got "length - 1" bytes, we didn't get the whole C string, we
- // need to read some more characters
+ // If we got "length - 1" bytes, we didn't get the whole C string, we need
+ // to read some more characters
if (length == sizeof(buf) - 1)
curr_addr += length;
else
@@ -2238,7 +2221,8 @@ size_t Process::ReadStringFromMemory(addr_t addr, char *dst, size_t max_bytes,
Status &error, size_t type_width) {
size_t total_bytes_read = 0;
if (dst && max_bytes && type_width && max_bytes >= type_width) {
- // Ensure a null terminator independent of the number of bytes that is read.
+ // Ensure a null terminator independent of the number of bytes that is
+ // read.
memset(dst, 0, max_bytes);
size_t bytes_left = max_bytes - type_width;
@@ -2285,8 +2269,7 @@ size_t Process::ReadStringFromMemory(addr_t addr, char *dst, size_t max_bytes,
}
// Deprecated in favor of ReadStringFromMemory which has wchar support and
-// correct code to find
-// null terminators.
+// correct code to find null terminators.
size_t Process::ReadCStringFromMemory(addr_t addr, char *dst,
size_t dst_max_len,
Status &result_error) {
@@ -2460,16 +2443,16 @@ size_t Process::WriteMemory(addr_t addr, const void *buf, size_t size,
// Check for bytes before this breakpoint
const addr_t curr_addr = addr + bytes_written;
if (intersect_addr > curr_addr) {
- // There are some bytes before this breakpoint that we need to
- // just write to memory
+ // There are some bytes before this breakpoint that we need to just
+ // write to memory
size_t curr_size = intersect_addr - curr_addr;
size_t curr_bytes_written = WriteMemoryPrivate(
curr_addr, ubuf + bytes_written, curr_size, error);
bytes_written += curr_bytes_written;
if (curr_bytes_written != curr_size) {
- // We weren't able to write all of the requested bytes, we
- // are done looping and will return the number of bytes that
- // we have written so far.
+ // We weren't able to write all of the requested bytes, we are
+ // done looping and will return the number of bytes that we have
+ // written so far.
if (error.Success())
error.SetErrorToGenericError();
}
@@ -2542,11 +2525,24 @@ size_t Process::ReadScalarIntegerFromMemory(addr_t addr, uint32_t byte_size,
return 0;
}
+Status Process::WriteObjectFile(std::vector<ObjectFile::LoadableData> entries) {
+ Status error;
+ for (const auto &Entry : entries) {
+ WriteMemory(Entry.Dest, Entry.Contents.data(), Entry.Contents.size(),
+ error);
+ if (!error.Success())
+ break;
+ }
+ return error;
+}
+
#define USE_ALLOCATE_MEMORY_CACHE 1
addr_t Process::AllocateMemory(size_t size, uint32_t permissions,
Status &error) {
- if (GetPrivateState() != eStateStopped)
+ if (GetPrivateState() != eStateStopped) {
+ error.SetErrorToGenericError();
return LLDB_INVALID_ADDRESS;
+ }
#if defined(USE_ALLOCATE_MEMORY_CACHE)
return m_allocated_memory_cache.AllocateMemory(size, permissions, error);
@@ -2692,8 +2688,7 @@ StateType
Process::WaitForProcessStopPrivate(EventSP &event_sp,
const Timeout<std::micro> &timeout) {
StateType state;
- // Now wait for the process to launch and return control to us, and then
- // call DidLaunch:
+
while (true) {
event_sp.reset();
state = GetStateChangedEventsPrivate(event_sp, timeout);
@@ -2771,11 +2766,14 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) {
}
} else {
EventSP event_sp;
+
+ // Now wait for the process to launch and return control to us, and then call
+ // DidLaunch:
StateType state = WaitForProcessStopPrivate(event_sp, seconds(10));
if (state == eStateInvalid || !event_sp) {
- // We were able to launch the process, but we failed to
- // catch the initial stop.
+ // We were able to launch the process, but we failed to catch the
+ // initial stop.
error.SetErrorString("failed to catch stop after launch");
SetExitStatus(0, "failed to catch stop after launch");
Destroy(false);
@@ -2795,18 +2793,15 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) {
if (!m_os_ap)
LoadOperatingSystemPlugin(false);
- // We successfully launched the process and stopped,
- // now it the right time to set up signal filters before resuming.
+ // We successfully launched the process and stopped, now it the
+ // right time to set up signal filters before resuming.
UpdateAutomaticSignalFiltering();
// Note, the stop event was consumed above, but not handled. This
- // was done
- // to give DidLaunch a chance to run. The target is either stopped
- // or crashed.
- // Directly set the state. This is done to prevent a stop message
- // with a bunch
- // of spurious output on thread status, as well as not pop a
- // ProcessIOHandler.
+ // was done to give DidLaunch a chance to run. The target is either
+ // stopped or crashed. Directly set the state. This is done to
+ // prevent a stop message with a bunch of spurious output on thread
+ // status, as well as not pop a ProcessIOHandler.
SetPublicState(state, false);
if (PrivateStateThreadIsValid())
@@ -2815,15 +2810,13 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) {
StartPrivateStateThread();
// Target was stopped at entry as was intended. Need to notify the
- // listeners
- // about it.
+ // listeners about it.
if (state == eStateStopped &&
launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
HandlePrivateEvent(event_sp);
} else if (state == eStateExited) {
// We exited while trying to launch somehow. Don't call DidLaunch
- // as that's
- // not likely to work, and return an invalid pid.
+ // as that's not likely to work, and return an invalid pid.
HandlePrivateEvent(event_sp);
}
}
@@ -2862,14 +2855,13 @@ Status Process::LoadCore() {
LoadOperatingSystemPlugin(false);
// We successfully loaded a core file, now pretend we stopped so we can
- // show all of the threads in the core file and explore the crashed
- // state.
+ // show all of the threads in the core file and explore the crashed state.
SetPrivateState(eStateStopped);
- // Wait indefinitely for a stopped event since we just posted one above...
+ // Wait for a stopped event since we just posted one above...
lldb::EventSP event_sp;
- listener_sp->GetEvent(event_sp, llvm::None);
- StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());
+ StateType state =
+ WaitForProcessToStop(seconds(10), &event_sp, true, listener_sp);
if (!StateIsStoppedState(state, false)) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -2939,8 +2931,8 @@ Process::AttachCompletionHandler::PerformAction(lldb::EventSP &event_sp) {
// During attach, prior to sending the eStateStopped event,
// lldb_private::Process subclasses must set the new process ID.
assert(m_process->GetID() != LLDB_INVALID_PROCESS_ID);
- // We don't want these events to be reported, so go set the ShouldReportStop
- // here:
+ // We don't want these events to be reported, so go set the
+ // ShouldReportStop here:
m_process->GetThreadList().SetShouldReportStop(eVoteNo);
if (m_exec_count > 0) {
@@ -3134,8 +3126,8 @@ void Process::CompleteAttach() {
}
// We just attached. If we have a platform, ask it for the process
- // architecture, and if it isn't
- // the same as the one we've already set, switch architectures.
+ // architecture, and if it isn't the same as the one we've already set,
+ // switch architectures.
PlatformSP platform_sp(GetTarget().GetPlatform());
assert(platform_sp);
if (platform_sp) {
@@ -3272,21 +3264,20 @@ Status Process::PrivateResume() {
m_mod_id.GetStopID(), StateAsCString(m_public_state.GetValue()),
StateAsCString(m_private_state.GetValue()));
- // If signals handing status changed we might want to update
- // our signal filters before resuming.
+ // If signals handing status changed we might want to update our signal
+ // filters before resuming.
UpdateAutomaticSignalFiltering();
Status error(WillResume());
// Tell the process it is about to resume before the thread list
if (error.Success()) {
- // Now let the thread list know we are about to resume so it
- // can let all of our threads know that they are about to be
- // resumed. Threads will each be called with
- // Thread::WillResume(StateType) where StateType contains the state
- // that they are supposed to have when the process is resumed
- // (suspended/running/stepping). Threads should also check
- // their resume signal in lldb::Thread::GetResumeSignal()
- // to see if they are supposed to start back up with a signal.
+ // Now let the thread list know we are about to resume so it can let all of
+ // our threads know that they are about to be resumed. Threads will each be
+ // called with Thread::WillResume(StateType) where StateType contains the
+ // state that they are supposed to have when the process is resumed
+ // (suspended/running/stepping). Threads should also check their resume
+ // signal in lldb::Thread::GetResumeSignal() to see if they are supposed to
+ // start back up with a signal.
if (m_thread_list.WillResume()) {
// Last thing, do the PreResumeActions.
if (!RunPreResumeActions()) {
@@ -3303,11 +3294,10 @@ Status Process::PrivateResume() {
}
}
} else {
- // Somebody wanted to run without running (e.g. we were faking a step from
- // one frame of a set of inlined
- // frames that share the same PC to another.) So generate a continue & a
- // stopped event,
- // and let the world handle them.
+ // Somebody wanted to run without running (e.g. we were faking a step
+ // from one frame of a set of inlined frames that share the same PC to
+ // another.) So generate a continue & a stopped event, and let the world
+ // handle them.
if (log)
log->Printf(
"Process::PrivateResume() asked to simulate a start & stop.");
@@ -3325,9 +3315,8 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
if (!StateIsRunningState(m_public_state.GetValue()))
return Status("Process is not running.");
- // Don't clear the m_clear_thread_plans_on_stop, only set it to true if
- // in case it was already set and some thread plan logic calls halt on its
- // own.
+ // Don't clear the m_clear_thread_plans_on_stop, only set it to true if in
+ // case it was already set and some thread plan logic calls halt on its own.
m_clear_thread_plans_on_stop |= clear_thread_plans;
ListenerSP halt_listener_sp(
@@ -3339,8 +3328,8 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
SendAsyncInterrupt();
if (m_public_state.GetValue() == eStateAttaching) {
- // Don't hijack and eat the eStateExited as the code that was doing
- // the attach will be waiting for this event...
+ // Don't hijack and eat the eStateExited as the code that was doing the
+ // attach will be waiting for this event...
RestoreProcessEvents();
SetExitStatus(SIGKILL, "Cancelled async attach.");
Destroy(false);
@@ -3366,8 +3355,8 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) {
Status error;
// Check both the public & private states here. If we're hung evaluating an
- // expression, for instance, then
- // the public state will be stopped, but we still need to interrupt.
+ // expression, for instance, then the public state will be stopped, but we
+ // still need to interrupt.
if (m_public_state.GetValue() == eStateRunning ||
m_private_state.GetValue() == eStateRunning) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -3387,10 +3376,9 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) {
RestoreProcessEvents();
// If the process exited while we were waiting for it to stop, put the
- // exited event into
- // the shared pointer passed in and return. Our caller doesn't need to do
- // anything else, since
- // they don't have a process anymore...
+ // exited event into the shared pointer passed in and return. Our caller
+ // doesn't need to do anything else, since they don't have a process
+ // anymore...
if (state == eStateExited || m_private_state.GetValue() == eStateExited) {
if (log)
@@ -3405,9 +3393,8 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) {
log->Printf("Process::%s() failed to stop, state is: %s", __FUNCTION__,
StateAsCString(state));
// If we really couldn't stop the process then we should just error out
- // here, but if the
- // lower levels just bobbled sending the event and we really are stopped,
- // then continue on.
+ // here, but if the lower levels just bobbled sending the event and we
+ // really are stopped, then continue on.
StateType private_state = m_private_state.GetValue();
if (private_state != eStateStopped) {
return Status(
@@ -3455,20 +3442,18 @@ Status Process::Detach(bool keep_stopped) {
}
m_destroy_in_process = false;
- // If we exited when we were waiting for a process to stop, then
- // forward the event here so we don't lose the event
+ // If we exited when we were waiting for a process to stop, then forward the
+ // event here so we don't lose the event
if (exit_event_sp) {
- // Directly broadcast our exited event because we shut down our
- // private state thread above
+ // Directly broadcast our exited event because we shut down our private
+ // state thread above
BroadcastEvent(exit_event_sp);
}
// If we have been interrupted (to kill us) in the middle of running, we may
- // not end up propagating
- // the last events through the event system, in which case we might strand the
- // write lock. Unlock
- // it here so when we do to tear down the process we don't get an error
- // destroying the lock.
+ // not end up propagating the last events through the event system, in which
+ // case we might strand the write lock. Unlock it here so when we do to tear
+ // down the process we don't get an error destroying the lock.
m_public_run_lock.SetStopped();
return error;
@@ -3477,9 +3462,8 @@ Status Process::Detach(bool keep_stopped) {
Status Process::Destroy(bool force_kill) {
// Tell ourselves we are in the process of destroying the process, so that we
- // don't do any unnecessary work
- // that might hinder the destruction. Remember to set this back to false when
- // we are done. That way if the attempt
+ // don't do any unnecessary work that might hinder the destruction. Remember
+ // to set this back to false when we are done. That way if the attempt
// failed and the process stays around for some reason it won't be in a
// confused state.
@@ -3502,12 +3486,11 @@ Status Process::Destroy(bool force_kill) {
}
if (m_public_state.GetValue() != eStateRunning) {
- // Ditch all thread plans, and remove all our breakpoints: in case we have
- // to restart the target to
- // kill it, we don't want it hitting a breakpoint...
- // Only do this if we've stopped, however, since if we didn't manage to
- // halt it above, then
- // we're not going to have much luck doing this now.
+ // Ditch all thread plans, and remove all our breakpoints: in case we
+ // have to restart the target to kill it, we don't want it hitting a
+ // breakpoint... Only do this if we've stopped, however, since if we
+ // didn't manage to halt it above, then we're not going to have much luck
+ // doing this now.
m_thread_list.DiscardThreadPlans();
DisableAllBreakpointSites();
}
@@ -3527,20 +3510,18 @@ Status Process::Destroy(bool force_kill) {
m_process_input_reader.reset();
}
- // If we exited when we were waiting for a process to stop, then
- // forward the event here so we don't lose the event
+ // If we exited when we were waiting for a process to stop, then forward
+ // the event here so we don't lose the event
if (exit_event_sp) {
- // Directly broadcast our exited event because we shut down our
- // private state thread above
+ // Directly broadcast our exited event because we shut down our private
+ // state thread above
BroadcastEvent(exit_event_sp);
}
- // If we have been interrupted (to kill us) in the middle of running, we may
- // not end up propagating
- // the last events through the event system, in which case we might strand
- // the write lock. Unlock
- // it here so when we do to tear down the process we don't get an error
- // destroying the lock.
+ // If we have been interrupted (to kill us) in the middle of running, we
+ // may not end up propagating the last events through the event system, in
+ // which case we might strand the write lock. Unlock it here so when we do
+ // to tear down the process we don't get an error destroying the lock.
m_public_run_lock.SetStopped();
}
@@ -3607,11 +3588,11 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
break;
case eStateRunning:
case eStateStepping:
- // If we've started the target running, we handle the cases where we
- // are already running and where there is a transition from stopped to
- // running differently.
- // running -> running: Automatically suppress extra running events
- // stopped -> running: Report except when there is one or more no votes
+ // If we've started the target running, we handle the cases where we are
+ // already running and where there is a transition from stopped to running
+ // differently. running -> running: Automatically suppress extra running
+ // events stopped -> running: Report except when there is one or more no
+ // votes
// and no yes votes.
SynchronouslyNotifyStateChanged(state);
if (m_force_next_event_delivery)
@@ -3625,11 +3606,10 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
break;
default:
// TODO: make this work correctly. For now always report
- // run if we aren't running so we don't miss any running
- // events. If I run the lldb/test/thread/a.out file and
- // break at main.cpp:58, run and hit the breakpoints on
- // multiple threads, then somehow during the stepping over
- // of all breakpoints no run gets reported.
+ // run if we aren't running so we don't miss any running events. If I
+ // run the lldb/test/thread/a.out file and break at main.cpp:58, run
+ // and hit the breakpoints on multiple threads, then somehow during the
+ // stepping over of all breakpoints no run gets reported.
// This is a transition from stop to run.
switch (m_thread_list.ShouldReportRun(event_ptr)) {
@@ -3648,11 +3628,10 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
case eStateStopped:
case eStateCrashed:
case eStateSuspended:
- // We've stopped. First see if we're going to restart the target.
- // If we are going to stop, then we always broadcast the event.
- // If we aren't going to stop, let the thread plans decide if we're going to
- // report this event.
- // If no thread has an opinion, we don't report it.
+ // We've stopped. First see if we're going to restart the target. If we
+ // are going to stop, then we always broadcast the event. If we aren't
+ // going to stop, let the thread plans decide if we're going to report this
+ // event. If no thread has an opinion, we don't report it.
m_stdio_communication.SynchronizeWithReadThread();
RefreshStateAfterStop();
@@ -3662,8 +3641,7 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
"interrupt, state: %s",
static_cast<void *>(event_ptr), StateAsCString(state));
// Even though we know we are going to stop, we should let the threads
- // have a look at the stop,
- // so they can properly set their state.
+ // have a look at the stop, so they can properly set their state.
m_thread_list.ShouldStop(event_ptr);
return_value = true;
} else {
@@ -3671,10 +3649,8 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
bool should_resume = false;
// It makes no sense to ask "ShouldStop" if we've already been
- // restarted...
- // Asking the thread list is also not likely to go well, since we are
- // running again.
- // So in that case just report the event.
+ // restarted... Asking the thread list is also not likely to go well,
+ // since we are running again. So in that case just report the event.
if (!was_restarted)
should_resume = !m_thread_list.ShouldStop(event_ptr);
@@ -3717,16 +3693,13 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
m_force_next_event_delivery = false;
// We do some coalescing of events (for instance two consecutive running
- // events get coalesced.)
- // But we only coalesce against events we actually broadcast. So we use
- // m_last_broadcast_state
- // to track that. NB - you can't use "m_public_state.GetValue()" for that
- // purpose, as was originally done,
- // because the PublicState reflects the last event pulled off the queue, and
- // there may be several
- // events stacked up on the queue unserviced. So the PublicState may not
- // reflect the last broadcasted event
- // yet. m_last_broadcast_state gets updated here.
+ // events get coalesced.) But we only coalesce against events we actually
+ // broadcast. So we use m_last_broadcast_state to track that. NB - you
+ // can't use "m_public_state.GetValue()" for that purpose, as was originally
+ // done, because the PublicState reflects the last event pulled off the
+ // queue, and there may be several events stacked up on the queue unserviced.
+ // So the PublicState may not reflect the last broadcasted event yet.
+ // m_last_broadcast_state gets updated here.
if (return_value)
m_last_broadcast_state = state;
@@ -3752,8 +3725,8 @@ bool Process::StartPrivateStateThread(bool is_secondary_thread) {
if (!is_secondary_thread && already_running)
return true;
- // Create a thread that watches our internal state and controls which
- // events make it to clients (into the DCProcess event queue).
+ // Create a thread that watches our internal state and controls which events
+ // make it to clients (into the DCProcess event queue).
char thread_name[1024];
uint32_t max_len = llvm::get_max_thread_name_length();
if (max_len > 0 && max_len <= 30) {
@@ -3818,10 +3791,10 @@ void Process::ControlPrivateStateThread(uint32_t signal) {
// Signal the private state thread
if (m_private_state_thread.IsJoinable()) {
// Broadcast the event.
- // It is important to do this outside of the if below, because
- // it's possible that the thread state is invalid but that the
- // thread is waiting on a control event instead of simply being
- // on its way out (this should not happen, but it apparently can).
+ // It is important to do this outside of the if below, because it's
+ // possible that the thread state is invalid but that the thread is waiting
+ // on a control event instead of simply being on its way out (this should
+ // not happen, but it apparently can).
if (log)
log->Printf("Sending control event of type: %d.", signal);
std::shared_ptr<EventDataReceipt> event_receipt_sp(new EventDataReceipt());
@@ -3832,14 +3805,13 @@ void Process::ControlPrivateStateThread(uint32_t signal) {
bool receipt_received = false;
if (PrivateStateThreadIsValid()) {
while (!receipt_received) {
- bool timed_out = false;
- // Check for a receipt for 2 seconds and then check if the private state
- // thread is still around.
- receipt_received = event_receipt_sp->WaitForEventReceived(
- std::chrono::seconds(2), &timed_out);
+ // Check for a receipt for 2 seconds and then check if the private
+ // state thread is still around.
+ receipt_received =
+ event_receipt_sp->WaitForEventReceived(std::chrono::seconds(2));
if (!receipt_received) {
- // Check if the private state thread is still around. If it isn't then
- // we are done waiting
+ // Check if the private state thread is still around. If it isn't
+ // then we are done waiting
if (!PrivateStateThreadIsValid())
break; // Private state thread exited or is exiting, we are done
}
@@ -3889,9 +3861,9 @@ void Process::HandlePrivateEvent(EventSP &event_sp) {
break;
case NextEventAction::eEventActionExit:
- // Handle Exiting Here. If we already got an exited event,
- // we should just propagate it. Otherwise, swallow this event,
- // and set our state to exit so the next event will kill us.
+ // Handle Exiting Here. If we already got an exited event, we should
+ // just propagate it. Otherwise, swallow this event, and set our state
+ // to exit so the next event will kill us.
if (new_state != eStateExited) {
// FIXME: should cons up an exited event, and discard this one.
SetExitStatus(0, m_next_event_action_ap->GetExitString());
@@ -3917,9 +3889,9 @@ void Process::HandlePrivateEvent(EventSP &event_sp) {
}
Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
if (StateIsRunningState(new_state)) {
- // Only push the input handler if we aren't fowarding events,
- // as this means the curses GUI is in use...
- // Or don't push it if we are launching since it will come up stopped.
+ // Only push the input handler if we aren't fowarding events, as this
+ // means the curses GUI is in use... Or don't push it if we are launching
+ // since it will come up stopped.
if (!GetTarget().GetDebugger().IsForwardingEvents() &&
new_state != eStateLaunching && new_state != eStateAttaching) {
PushProcessIOHandler();
@@ -3931,27 +3903,26 @@ void Process::HandlePrivateEvent(EventSP &event_sp) {
}
} else if (StateIsStoppedState(new_state, false)) {
if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get())) {
- // If the lldb_private::Debugger is handling the events, we don't
- // want to pop the process IOHandler here, we want to do it when
- // we receive the stopped event so we can carefully control when
- // the process IOHandler is popped because when we stop we want to
- // display some text stating how and why we stopped, then maybe some
- // process/thread/frame info, and then we want the "(lldb) " prompt
- // to show up. If we pop the process IOHandler here, then we will
- // cause the command interpreter to become the top IOHandler after
- // the process pops off and it will update its prompt right away...
- // See the Debugger.cpp file where it calls the function as
+ // If the lldb_private::Debugger is handling the events, we don't want
+ // to pop the process IOHandler here, we want to do it when we receive
+ // the stopped event so we can carefully control when the process
+ // IOHandler is popped because when we stop we want to display some
+ // text stating how and why we stopped, then maybe some
+ // process/thread/frame info, and then we want the "(lldb) " prompt to
+ // show up. If we pop the process IOHandler here, then we will cause
+ // the command interpreter to become the top IOHandler after the
+ // process pops off and it will update its prompt right away... See the
+ // Debugger.cpp file where it calls the function as
// "process_sp->PopProcessIOHandler()" to see where I am talking about.
// Otherwise we end up getting overlapping "(lldb) " prompts and
// garbled output.
//
// If we aren't handling the events in the debugger (which is indicated
- // by "m_target.GetDebugger().IsHandlingEvents()" returning false) or we
- // are hijacked, then we always pop the process IO handler manually.
+ // by "m_target.GetDebugger().IsHandlingEvents()" returning false) or
+ // we are hijacked, then we always pop the process IO handler manually.
// Hijacking happens when the internal process state thread is running
- // thread plans, or when commands want to run in synchronous mode
- // and they call "process->WaitForProcessToStop()". An example of
- // something
+ // thread plans, or when commands want to run in synchronous mode and
+ // they call "process->WaitForProcessToStop()". An example of something
// that will hijack the events is a simple expression:
//
// (lldb) expr (int)puts("hello")
@@ -4054,23 +4025,19 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) {
") failed to halt the process: %s",
__FUNCTION__, static_cast<void *>(this), GetID(),
error.AsCString());
- // Halt should generate a stopped event. Make a note of the fact that we
- // were
- // doing the interrupt, so we can set the interrupted flag after we
- // receive the
- // event. We deliberately set this to true even if HaltPrivate failed,
- // so that we
- // can interrupt on the next natural stop.
+ // Halt should generate a stopped event. Make a note of the fact that
+ // we were doing the interrupt, so we can set the interrupted flag
+ // after we receive the event. We deliberately set this to true even if
+ // HaltPrivate failed, so that we can interrupt on the next natural
+ // stop.
interrupt_requested = true;
} else {
// This can happen when someone (e.g. Process::Halt) sees that we are
- // running and
- // sends an interrupt request, but the process actually stops before we
- // receive
- // it. In that case, we can just ignore the request. We use
- // m_last_broadcast_state, because the Stopped event may not have been
- // popped of
- // the event queue yet, which is when the public state gets updated.
+ // running and sends an interrupt request, but the process actually
+ // stops before we receive it. In that case, we can just ignore the
+ // request. We use m_last_broadcast_state, because the Stopped event
+ // may not have been popped of the event queue yet, which is when the
+ // public state gets updated.
if (log)
log->Printf(
"Process::%s ignoring interrupt as we have already stopped.",
@@ -4092,8 +4059,7 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) {
if (interrupt_requested) {
if (StateIsStoppedState(internal_state, true)) {
// We requested the interrupt, so mark this as such in the stop event
- // so
- // clients can tell an interrupted process from a natural stop
+ // so clients can tell an interrupted process from a natural stop
ProcessEventData::SetInterruptedInEvent(event_sp.get(), true);
interrupt_requested = false;
} else if (log) {
@@ -4124,10 +4090,8 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) {
__FUNCTION__, static_cast<void *>(this), GetID());
// If we are a secondary thread, then the primary thread we are working for
- // will have already
- // acquired the public_run_lock, and isn't done with what it was doing yet, so
- // don't
- // try to change it on the way out.
+ // will have already acquired the public_run_lock, and isn't done with what
+ // it was doing yet, so don't try to change it on the way out.
if (!is_secondary_thread)
m_public_run_lock.SetStopped();
return NULL;
@@ -4167,14 +4131,12 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
return;
// This function gets called twice for each event, once when the event gets
- // pulled
- // off of the private process event queue, and then any number of times, first
- // when it gets pulled off of
- // the public event queue, then other times when we're pretending that this is
- // where we stopped at the
- // end of expression evaluation. m_update_state is used to distinguish these
- // three cases; it is 0 when we're just pulling it off for private handling,
- // and > 1 for expression evaluation, and we don't want to do the breakpoint
+ // pulled off of the private process event queue, and then any number of
+ // times, first when it gets pulled off of the public event queue, then other
+ // times when we're pretending that this is where we stopped at the end of
+ // expression evaluation. m_update_state is used to distinguish these three
+ // cases; it is 0 when we're just pulling it off for private handling, and >
+ // 1 for expression evaluation, and we don't want to do the breakpoint
// command handling then.
if (m_update_state != 1)
return;
@@ -4183,16 +4145,15 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
m_state, Process::ProcessEventData::GetRestartedFromEvent(event_ptr));
if (m_state == eStateStopped && !m_restarted) {
- // Let process subclasses know we are about to do a public stop and
- // do anything they might need to in order to speed up register and
- // memory accesses.
+ // Let process subclasses know we are about to do a public stop and do
+ // anything they might need to in order to speed up register and memory
+ // accesses.
process_sp->WillPublicStop();
}
// If this is a halt event, even if the halt stopped with some reason other
- // than a plain interrupt (e.g. we had
- // already stopped for a breakpoint when the halt request came through) don't
- // do the StopInfo actions, as they may
+ // than a plain interrupt (e.g. we had already stopped for a breakpoint when
+ // the halt request came through) don't do the StopInfo actions, as they may
// end up restarting the process.
if (m_interrupted)
return;
@@ -4204,37 +4165,32 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
uint32_t idx;
// The actions might change one of the thread's stop_info's opinions about
- // whether we should
- // stop the process, so we need to query that as we go.
+ // whether we should stop the process, so we need to query that as we go.
// One other complication here, is that we try to catch any case where the
- // target has run (except for expressions)
- // and immediately exit, but if we get that wrong (which is possible) then
- // the thread list might have changed, and
- // that would cause our iteration here to crash. We could make a copy of
- // the thread list, but we'd really like
- // to also know if it has changed at all, so we make up a vector of the
- // thread ID's and check what we get back
- // against this list & bag out if anything differs.
+ // target has run (except for expressions) and immediately exit, but if we
+ // get that wrong (which is possible) then the thread list might have
+ // changed, and that would cause our iteration here to crash. We could
+ // make a copy of the thread list, but we'd really like to also know if it
+ // has changed at all, so we make up a vector of the thread ID's and check
+ // what we get back against this list & bag out if anything differs.
std::vector<uint32_t> thread_index_array(num_threads);
for (idx = 0; idx < num_threads; ++idx)
thread_index_array[idx] =
curr_thread_list.GetThreadAtIndex(idx)->GetIndexID();
// Use this to track whether we should continue from here. We will only
- // continue the target running if
- // no thread says we should stop. Of course if some thread's PerformAction
- // actually sets the target running,
- // then it doesn't matter what the other threads say...
+ // continue the target running if no thread says we should stop. Of course
+ // if some thread's PerformAction actually sets the target running, then it
+ // doesn't matter what the other threads say...
bool still_should_stop = false;
// Sometimes - for instance if we have a bug in the stub we are talking to,
- // we stop but no thread has a
- // valid stop reason. In that case we should just stop, because we have no
- // way of telling what the right
- // thing to do is, and it's better to let the user decide than continue
- // behind their backs.
+ // we stop but no thread has a valid stop reason. In that case we should
+ // just stop, because we have no way of telling what the right thing to do
+ // is, and it's better to let the user decide than continue behind their
+ // backs.
bool does_anybody_have_an_opinion = false;
@@ -4271,13 +4227,11 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
stop_info_sp->GetOverriddenShouldStopValue();
} else {
stop_info_sp->PerformAction(event_ptr);
- // The stop action might restart the target. If it does, then we want
- // to mark that in the
- // event so that whoever is receiving it will know to wait for the
- // running event and reflect
- // that state appropriately.
- // We also need to stop processing actions, since they aren't
- // expecting the target to be running.
+ // The stop action might restart the target. If it does, then we
+ // want to mark that in the event so that whoever is receiving it
+ // will know to wait for the running event and reflect that state
+ // appropriately. We also need to stop processing actions, since they
+ // aren't expecting the target to be running.
// FIXME: we might have run.
if (stop_info_sp->HasTargetRunSinceMe()) {
@@ -4297,12 +4251,12 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
if (!still_should_stop && does_anybody_have_an_opinion) {
// We've been asked to continue, so do that here.
SetRestarted(true);
- // Use the public resume method here, since this is just
- // extending a public resume.
+ // Use the public resume method here, since this is just extending a
+ // public resume.
process_sp->PrivateResume();
} else {
- // If we didn't restart, run the Stop Hooks here:
- // They might also restart the target, so watch for that.
+ // If we didn't restart, run the Stop Hooks here: They might also
+ // restart the target, so watch for that.
process_sp->GetTarget().RunStopHooks();
if (process_sp->GetPrivateState() == eStateRunning)
SetRestarted(true);
@@ -4423,7 +4377,7 @@ bool Process::ProcessEventData::SetUpdateStateOnRemoval(Event *event_ptr) {
return false;
}
-lldb::TargetSP Process::CalculateTarget() { return m_target_sp.lock(); }
+lldb::TargetSP Process::CalculateTarget() { return m_target_wp.lock(); }
void Process::CalculateExecutionContext(ExecutionContext &exe_ctx) {
exe_ctx.SetTargetPtr(&GetTarget());
@@ -4574,9 +4528,8 @@ public:
~IOHandlerProcessSTDIO() override = default;
- // Each IOHandler gets to run until it is done. It should read data
- // from the "in" and place output into "out" and "err and return
- // when done.
+ // Each IOHandler gets to run until it is done. It should read data from the
+ // "in" and place output into "out" and "err and return when done.
void Run() override {
if (!m_read_file.IsValid() || !m_write_file.IsValid() ||
!m_pipe.CanRead() || !m_pipe.CanWrite()) {
@@ -4640,9 +4593,8 @@ public:
void Cancel() override {
SetIsDone(true);
// Only write to our pipe to cancel if we are in
- // IOHandlerProcessSTDIO::Run().
- // We can end up with a python command that is being run from the command
- // interpreter:
+ // IOHandlerProcessSTDIO::Run(). We can end up with a python command that
+ // is being run from the command interpreter:
//
// (lldb) step_process_thousands_of_times
//
@@ -4659,12 +4611,11 @@ public:
}
bool Interrupt() override {
- // Do only things that are safe to do in an interrupt context (like in
- // a SIGINT handler), like write 1 byte to a file descriptor. This will
+ // Do only things that are safe to do in an interrupt context (like in a
+ // SIGINT handler), like write 1 byte to a file descriptor. This will
// interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
// that was written to the pipe and then call
- // m_process->SendAsyncInterrupt()
- // from a much safer location in code.
+ // m_process->SendAsyncInterrupt() from a much safer location in code.
if (m_active) {
char ch = 'i'; // Send 'i' for interrupt
size_t bytes_written = 0;
@@ -4672,16 +4623,13 @@ public:
return result.Success();
} else {
// This IOHandler might be pushed on the stack, but not being run
- // currently
- // so do the right thing if we aren't actively watching for STDIN by
- // sending
- // the interrupt to the process. Otherwise the write to the pipe above
- // would
- // do nothing. This can happen when the command interpreter is running and
- // gets a "expression ...". It will be on the IOHandler thread and sending
- // the input is complete to the delegate which will cause the expression
- // to
- // run, which will push the process IO handler, but not run it.
+ // currently so do the right thing if we aren't actively watching for
+ // STDIN by sending the interrupt to the process. Otherwise the write to
+ // the pipe above would do nothing. This can happen when the command
+ // interpreter is running and gets a "expression ...". It will be on the
+ // IOHandler thread and sending the input is complete to the delegate
+ // which will cause the expression to run, which will push the process IO
+ // handler, but not run it.
if (StateIsRunningState(m_process->GetState())) {
m_process->SendAsyncInterrupt();
@@ -4756,12 +4704,10 @@ void Process::SettingsInitialize() { Thread::SettingsInitialize(); }
void Process::SettingsTerminate() { Thread::SettingsTerminate(); }
namespace {
-// RestorePlanState is used to record the "is private", "is master" and "okay to
-// discard" fields of
-// the plan we are running, and reset it on Clean or on destruction.
-// It will only reset the state once, so you can call Clean and then monkey with
-// the state and it
-// won't get reset on you again.
+// RestorePlanState is used to record the "is private", "is master" and "okay
+// to discard" fields of the plan we are running, and reset it on Clean or on
+// destruction. It will only reset the state once, so you can call Clean and
+// then monkey with the state and it won't get reset on you again.
class RestorePlanState {
public:
@@ -4817,8 +4763,8 @@ GetOneThreadExpressionTimeout(const EvaluateExpressionOptions &options) {
static Timeout<std::micro>
GetExpressionTimeout(const EvaluateExpressionOptions &options,
bool before_first_timeout) {
- // If we are going to run all threads the whole time, or if we are only
- // going to run one thread, we can just return the overall timeout.
+ // If we are going to run all threads the whole time, or if we are only going
+ // to run one thread, we can just return the overall timeout.
if (!options.GetStopOthers() || !options.GetTryAllThreads())
return options.GetTimeout();
@@ -4855,7 +4801,8 @@ HandleStoppedEvent(Thread &thread, const ThreadPlanSP &thread_plan_sp,
if (!options.DoesIgnoreBreakpoints()) {
// Restore the plan state and then force Private to false. We are going
// to stop because of this plan so we need it to become a public plan or
- // it won't report correctly when we continue to its termination later on.
+ // it won't report correctly when we continue to its termination later
+ // on.
restorer.Clean();
thread_plan_sp->SetPrivate(false);
event_to_broadcast_sp = event_sp;
@@ -4910,23 +4857,20 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
// We need to change some of the thread plan attributes for the thread plan
- // runner. This will restore them
- // when we are done:
+ // runner. This will restore them when we are done:
RestorePlanState thread_plan_restorer(thread_plan_sp);
- // We rely on the thread plan we are running returning "PlanCompleted" if when
- // it successfully completes.
- // For that to be true the plan can't be private - since private plans
- // suppress themselves in the
- // GetCompletedPlan call.
+ // We rely on the thread plan we are running returning "PlanCompleted" if
+ // when it successfully completes. For that to be true the plan can't be
+ // private - since private plans suppress themselves in the GetCompletedPlan
+ // call.
thread_plan_sp->SetPrivate(false);
// The plans run with RunThreadPlan also need to be terminal master plans or
- // when they are done we will end
- // up asking the plan above us whether we should stop, which may give the
- // wrong answer.
+ // when they are done we will end up asking the plan above us whether we
+ // should stop, which may give the wrong answer.
thread_plan_sp->SetIsMasterPlan(true);
thread_plan_sp->SetOkayToDiscard(false);
@@ -4953,8 +4897,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
}
- // Make sure the timeout values make sense. The one thread timeout needs to be
- // smaller than the overall timeout.
+ // Make sure the timeout values make sense. The one thread timeout needs to
+ // be smaller than the overall timeout.
if (options.GetOneThreadTimeout() && options.GetTimeout() &&
*options.GetTimeout() < *options.GetOneThreadTimeout()) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
@@ -4966,8 +4910,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
StackID ctx_frame_id = selected_frame_sp->GetStackID();
// N.B. Running the target may unset the currently selected thread and frame.
- // We don't want to do that either,
- // so we should arrange to reset them as well.
+ // We don't want to do that either, so we should arrange to reset them as
+ // well.
lldb::ThreadSP selected_thread_sp = GetThreadList().GetSelectedThread();
@@ -4988,11 +4932,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
LIBLLDB_LOG_PROCESS));
if (m_private_state_thread.EqualsThread(Host::GetCurrentThread())) {
// Yikes, we are running on the private state thread! So we can't wait for
- // public events on this thread, since
- // we are the thread that is generating public events.
- // The simplest thing to do is to spin up a temporary thread to handle
- // private state thread events while
- // we are fielding public events here.
+ // public events on this thread, since we are the thread that is generating
+ // public events. The simplest thing to do is to spin up a temporary thread
+ // to handle private state thread events while we are fielding public
+ // events here.
if (log)
log->Printf("Running thread plan on private state thread, spinning up "
"another state thread to handle the events.");
@@ -5000,15 +4943,12 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
backup_private_state_thread = m_private_state_thread;
// One other bit of business: we want to run just this thread plan and
- // anything it pushes, and then stop,
- // returning control here.
- // But in the normal course of things, the plan above us on the stack would
- // be given a shot at the stop
- // event before deciding to stop, and we don't want that. So we insert a
- // "stopper" base plan on the stack
- // before the plan we want to run. Since base plans always stop and return
- // control to the user, that will
- // do just what we want.
+ // anything it pushes, and then stop, returning control here. But in the
+ // normal course of things, the plan above us on the stack would be given a
+ // shot at the stop event before deciding to stop, and we don't want that.
+ // So we insert a "stopper" base plan on the stack before the plan we want
+ // to run. Since base plans always stop and return control to the user,
+ // that will do just what we want.
stopper_base_plan_sp.reset(new ThreadPlanBase(*thread));
thread->QueueThreadPlan(stopper_base_plan_sp, false);
// Have to make sure our public state is stopped, since otherwise the
@@ -5024,15 +4964,13 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
thread_plan_sp, false); // This used to pass "true" does that make sense?
if (options.GetDebug()) {
- // In this case, we aren't actually going to run, we just want to stop right
- // away.
- // Flush this thread so we will refetch the stacks and show the correct
- // backtrace.
+ // In this case, we aren't actually going to run, we just want to stop
+ // right away. Flush this thread so we will refetch the stacks and show the
+ // correct backtrace.
// FIXME: To make this prettier we should invent some stop reason for this,
// but that
// is only cosmetic, and this functionality is only of use to lldb
- // developers who can
- // live with not pretty...
+ // developers who can live with not pretty...
thread->Flush();
return eExpressionStoppedForDebug;
}
@@ -5044,12 +4982,11 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
{
// This process event hijacker Hijacks the Public events and its destructor
- // makes sure that the process events get
- // restored on exit to the function.
+ // makes sure that the process events get restored on exit to the function.
//
// If the event needs to propagate beyond the hijacker (e.g., the process
- // exits during execution), then the event
- // is put into event_to_broadcast_sp for rebroadcasting.
+ // exits during execution), then the event is put into
+ // event_to_broadcast_sp for rebroadcasting.
ProcessEventHijacker run_thread_plan_hijacker(*this, listener_sp);
@@ -5084,10 +5021,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
options.GetStopOthers(), options.GetTryAllThreads(),
before_first_timeout);
- // This isn't going to work if there are unfetched events on the queue.
- // Are there cases where we might want to run the remaining events here, and
- // then try to
- // call the function? That's probably being too tricky for our own good.
+ // This isn't going to work if there are unfetched events on the queue. Are
+ // there cases where we might want to run the remaining events here, and
+ // then try to call the function? That's probably being too tricky for our
+ // own good.
Event *other_events = listener_sp->PeekAtNextEvent();
if (other_events != nullptr) {
@@ -5098,32 +5035,29 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
// We also need to make sure that the next event is delivered. We might be
- // calling a function as part of
- // a thread plan, in which case the last delivered event could be the
- // running event, and we don't want
- // event coalescing to cause us to lose OUR running event...
+ // calling a function as part of a thread plan, in which case the last
+ // delivered event could be the running event, and we don't want event
+ // coalescing to cause us to lose OUR running event...
ForceNextEventDelivery();
// This while loop must exit out the bottom, there's cleanup that we need to do
-// when we are done.
-// So don't call return anywhere within it.
+// when we are done. So don't call return anywhere within it.
#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
- // It's pretty much impossible to write test cases for things like:
- // One thread timeout expires, I go to halt, but the process already stopped
- // on the function call stop breakpoint. Turning on this define will make
- // us not
- // fetch the first event till after the halt. So if you run a quick
- // function, it will have
- // completed, and the completion event will be waiting, when you interrupt
- // for halt.
- // The expression evaluation should still succeed.
+ // It's pretty much impossible to write test cases for things like: One
+ // thread timeout expires, I go to halt, but the process already stopped on
+ // the function call stop breakpoint. Turning on this define will make us
+ // not fetch the first event till after the halt. So if you run a quick
+ // function, it will have completed, and the completion event will be
+ // waiting, when you interrupt for halt. The expression evaluation should
+ // still succeed.
bool miss_first_event = true;
#endif
while (true) {
- // We usually want to resume the process if we get to the top of the loop.
- // The only exception is if we get two running events with no intervening
- // stop, which can happen, we will just wait for then next stop event.
+ // We usually want to resume the process if we get to the top of the
+ // loop. The only exception is if we get two running events with no
+ // intervening stop, which can happen, we will just wait for then next
+ // stop event.
if (log)
log->Printf("Top of while loop: do_resume: %i handle_running_event: %i "
"before_first_timeout: %i.",
@@ -5182,9 +5116,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
if (restarted) {
// This is probably an overabundance of caution, I don't think I
- // should ever get a stopped & restarted
- // event here. But if I do, the best thing is to Halt and then get
- // out of here.
+ // should ever get a stopped & restarted event here. But if I do,
+ // the best thing is to Halt and then get out of here.
const bool clear_thread_plans = false;
const bool use_run_lock = false;
Halt(clear_thread_plans, use_run_lock);
@@ -5200,14 +5133,11 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
if (log)
log->PutCString("Process::RunThreadPlan(): resuming succeeded.");
- // We need to call the function synchronously, so spin waiting for it to
- // return.
- // If we get interrupted while executing, we're going to lose our
- // context, and
- // won't be able to gather the result at this point.
- // We set the timeout AFTER the resume, since the resume takes some time
- // and we
- // don't want to charge that to the timeout.
+ // We need to call the function synchronously, so spin waiting for it
+ // to return. If we get interrupted while executing, we're going to
+ // lose our context, and won't be able to gather the result at this
+ // point. We set the timeout AFTER the resume, since the resume takes
+ // some time and we don't want to charge that to the timeout.
} else {
if (log)
log->PutCString("Process::RunThreadPlan(): waiting for next event.");
@@ -5299,9 +5229,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
case lldb::eStateRunning:
// This shouldn't really happen, but sometimes we do get two
- // running events without an
- // intervening stop, and in that case we should just go back to
- // waiting for the stop.
+ // running events without an intervening stop, and in that case
+ // we should just go back to waiting for the stop.
do_resume = false;
keep_going = true;
handle_running_event = false;
@@ -5336,10 +5265,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
break;
}
} else {
- // If we didn't get an event that means we've timed out...
- // We will interrupt the process here. Depending on what we were asked
- // to do we will
- // either exit, or try with all threads running for the same timeout.
+ // If we didn't get an event that means we've timed out... We will
+ // interrupt the process here. Depending on what we were asked to do
+ // we will either exit, or try with all threads running for the same
+ // timeout.
if (log) {
if (options.GetTryAllThreads()) {
@@ -5357,14 +5286,13 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
// It is possible that between the time we issued the Halt, and we get
- // around to calling Halt the target
- // could have stopped. That's fine, Halt will figure that out and send
- // the appropriate Stopped event.
+ // around to calling Halt the target could have stopped. That's fine,
+ // Halt will figure that out and send the appropriate Stopped event.
// BUT it is also possible that we stopped & restarted (e.g. hit a
// signal with "stop" set to false.) In
// that case, we'll get the stopped & restarted event, and we should go
- // back to waiting for the Halt's
- // stopped event. That's what this while loop does.
+ // back to waiting for the Halt's stopped event. That's what this
+ // while loop does.
bool back_to_top = true;
uint32_t try_halt_again = 0;
@@ -5413,8 +5341,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
// Between the time we initiated the Halt and the time we
- // delivered it, the process could have
- // already finished its job. Check that here:
+ // delivered it, the process could have already finished its
+ // job. Check that here:
const bool handle_interrupts = false;
if (auto result = HandleStoppedEvent(
*thread, thread_plan_sp, thread_plan_restorer, event_sp,
@@ -5477,8 +5405,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
} // END WAIT LOOP
- // If we had to start up a temporary private state thread to run this thread
- // plan, shut it down now.
+ // If we had to start up a temporary private state thread to run this
+ // thread plan, shut it down now.
if (backup_private_state_thread.IsJoinable()) {
StopPrivateStateThread();
Status error;
@@ -5498,11 +5426,9 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
log->PutString(s.GetString());
}
// Restore the thread state if we are going to discard the plan execution.
- // There are three cases where this
- // could happen:
- // 1) The execution successfully completed
- // 2) We hit a breakpoint, and ignore_breakpoints was true
- // 3) We got some other error, and discard_on_error was true
+ // There are three cases where this could happen: 1) The execution
+ // successfully completed 2) We hit a breakpoint, and ignore_breakpoints
+ // was true 3) We got some other error, and discard_on_error was true
bool should_unwind = (return_value == eExpressionInterrupted &&
options.DoesUnwindOnError()) ||
(return_value == eExpressionHitBreakpoint &&
@@ -5642,18 +5568,15 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
// Thread we ran the function in may have gone away because we ran the
- // target
- // Check that it's still there, and if it is put it back in the context.
- // Also restore the
- // frame in the context if it is still present.
+ // target Check that it's still there, and if it is put it back in the
+ // context. Also restore the frame in the context if it is still present.
thread = GetThreadList().FindThreadByIndexID(thread_idx_id, true).get();
if (thread) {
exe_ctx.SetFrameSP(thread->GetFrameWithStackID(ctx_frame_id));
}
// Also restore the current process'es selected frame & thread, since this
- // function calling may
- // be done behind the user's back.
+ // function calling may be done behind the user's back.
if (selected_tid != LLDB_INVALID_THREAD_ID) {
if (GetThreadList().SetSelectedThreadByIndexID(selected_tid) &&
@@ -5744,10 +5667,9 @@ size_t Process::GetThreadStatus(Stream &strm,
size_t num_thread_infos_dumped = 0;
// You can't hold the thread list lock while calling Thread::GetStatus. That
- // very well might run code (e.g. if we need it
- // to get return values or arguments.) For that to work the process has to be
- // able to acquire it. So instead copy the thread
- // ID's, and look them up one by one:
+ // very well might run code (e.g. if we need it to get return values or
+ // arguments.) For that to work the process has to be able to acquire it.
+ // So instead copy the thread ID's, and look them up one by one:
uint32_t num_threads;
std::vector<lldb::tid_t> thread_id_array;
@@ -5860,12 +5782,12 @@ void Process::DidExec() {
DoDidExec();
CompleteAttach();
// Flush the process (threads and all stack frames) after running
- // CompleteAttach()
- // in case the dynamic loader loaded things in new locations.
+ // CompleteAttach() in case the dynamic loader loaded things in new
+ // locations.
Flush();
- // After we figure out what was loaded/unloaded in CompleteAttach,
- // we need to let the target know so it can do any cleanup it needs to.
+ // After we figure out what was loaded/unloaded in CompleteAttach, we need to
+ // let the target know so it can do any cleanup it needs to.
target.DidExec();
}
@@ -5916,17 +5838,17 @@ void Process::ModulesDidLoad(ModuleList &module_list) {
runtime->ModulesDidLoad(module_list);
}
- // Let any language runtimes we have already created know
- // about the modules that loaded.
+ // Let any language runtimes we have already created know about the modules
+ // that loaded.
- // Iterate over a copy of this language runtime list in case
- // the language runtime ModulesDidLoad somehow causes the language
- // riuntime to be unloaded.
+ // Iterate over a copy of this language runtime list in case the language
+ // runtime ModulesDidLoad somehow causes the language riuntime to be
+ // unloaded.
LanguageRuntimeCollection language_runtimes(m_language_runtimes);
for (const auto &pair : language_runtimes) {
- // We must check language_runtime_sp to make sure it is not
- // nullptr as we might cache the fact that we didn't have a
- // language runtime for a language.
+ // We must check language_runtime_sp to make sure it is not nullptr as we
+ // might cache the fact that we didn't have a language runtime for a
+ // language.
LanguageRuntimeSP language_runtime_sp = pair.second;
if (language_runtime_sp)
language_runtime_sp->ModulesDidLoad(module_list);
@@ -6126,9 +6048,9 @@ Process::GetMemoryRegions(std::vector<lldb::MemoryRegionInfoSP> &region_list) {
Status
Process::ConfigureStructuredData(const ConstString &type_name,
const StructuredData::ObjectSP &config_sp) {
- // If you get this, the Process-derived class needs to implement a method
- // to enable an already-reported asynchronous structured data feature.
- // See ProcessGDBRemote for an example implementation over gdb-remote.
+ // If you get this, the Process-derived class needs to implement a method to
+ // enable an already-reported asynchronous structured data feature. See
+ // ProcessGDBRemote for an example implementation over gdb-remote.
return Status("unimplemented");
}
@@ -6170,23 +6092,27 @@ void Process::MapSupportedStructuredDataPlugins(
return true;
});
- // For each StructuredDataPlugin, if the plugin handles any of the
- // types in the supported_type_names, map that type name to that plugin.
- uint32_t plugin_index = 0;
- for (auto create_instance =
+ // For each StructuredDataPlugin, if the plugin handles any of the types in
+ // the supported_type_names, map that type name to that plugin. Stop when
+ // we've consumed all the type names.
+ // FIXME: should we return an error if there are type names nobody
+ // supports?
+ for (uint32_t plugin_index = 0; !const_type_names.empty(); plugin_index++) {
+ auto create_instance =
PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(
plugin_index);
- create_instance && !const_type_names.empty(); ++plugin_index) {
+ if (!create_instance)
+ break;
+
// Create the plugin.
StructuredDataPluginSP plugin_sp = (*create_instance)(*this);
if (!plugin_sp) {
- // This plugin doesn't think it can work with the process.
- // Move on to the next.
+ // This plugin doesn't think it can work with the process. Move on to the
+ // next.
continue;
}
- // For any of the remaining type names, map any that this plugin
- // supports.
+ // For any of the remaining type names, map any that this plugin supports.
std::vector<ConstString> names_to_remove;
for (auto &type_name : const_type_names) {
if (plugin_sp->SupportsStructuredDataType(type_name)) {
@@ -6213,8 +6139,8 @@ bool Process::RouteAsyncStructuredData(
if (!object_sp)
return false;
- // The contract is this must be a dictionary, so we can look up the
- // routing key via the top-level 'type' string value within the dictionary.
+ // The contract is this must be a dictionary, so we can look up the routing
+ // key via the top-level 'type' string value within the dictionary.
StructuredData::Dictionary *dictionary = object_sp->GetAsDictionary();
if (!dictionary)
return false;
@@ -6241,3 +6167,13 @@ Status Process::UpdateAutomaticSignalFiltering() {
// No automatic signal filtering to speak of.
return Status();
}
+
+UtilityFunction *Process::GetLoadImageUtilityFunction(
+ Platform *platform,
+ llvm::function_ref<std::unique_ptr<UtilityFunction>()> factory) {
+ if (platform != GetTarget().GetPlatform().get())
+ return nullptr;
+ std::call_once(m_dlopen_utility_func_flag_once,
+ [&] { m_dlopen_utility_func_up = factory(); });
+ return m_dlopen_utility_func_up.get();
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/ProcessInfo.cpp b/contrib/llvm/tools/lldb/source/Target/ProcessInfo.cpp
index 0d986bc76914..ac0350686706 100644
--- a/contrib/llvm/tools/lldb/source/Target/ProcessInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ProcessInfo.cpp
@@ -35,7 +35,7 @@ ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
void ProcessInfo::Clear() {
m_executable.Clear();
m_arguments.Clear();
- m_environment.Clear();
+ m_environment.clear();
m_uid = UINT32_MAX;
m_gid = UINT32_MAX;
m_arch.Clear();
@@ -59,8 +59,7 @@ void ProcessInfo::Dump(Stream &s, Platform *platform) const {
s << "Arguments:\n";
m_arguments.Dump(s);
- s << "Environment:\n";
- m_environment.Dump(s, "env");
+ s.Format("Environment:\n{0}", m_environment);
}
void ProcessInfo::SetExecutableFile(const FileSpec &exe_file,
@@ -94,11 +93,11 @@ void ProcessInfo::SetArguments(char const **argv,
if (first_arg_is_executable) {
const char *first_arg = m_arguments.GetArgumentAtIndex(0);
if (first_arg) {
- // Yes the first argument is an executable, set it as the executable
- // in the launch options. Don't resolve the file path as the path
- // could be a remote platform path
+ // Yes the first argument is an executable, set it as the executable in
+ // the launch options. Don't resolve the file path as the path could be a
+ // remote platform path
const bool resolve = false;
- m_executable.SetFile(first_arg, resolve);
+ m_executable.SetFile(first_arg, resolve, FileSpec::Style::native);
}
}
}
@@ -111,11 +110,11 @@ void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {
if (first_arg_is_executable) {
const char *first_arg = m_arguments.GetArgumentAtIndex(0);
if (first_arg) {
- // Yes the first argument is an executable, set it as the executable
- // in the launch options. Don't resolve the file path as the path
- // could be a remote platform path
+ // Yes the first argument is an executable, set it as the executable in
+ // the launch options. Don't resolve the file path as the path could be a
+ // remote platform path
const bool resolve = false;
- m_executable.SetFile(first_arg, resolve);
+ m_executable.SetFile(first_arg, resolve, FileSpec::Style::native);
}
}
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp b/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp
index 284df9fd8b58..9569750bc5fd 100644
--- a/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp
@@ -189,6 +189,13 @@ void ProcessLaunchInfo::SetMonitorProcessCallback(
m_monitor_signals = monitor_signals;
}
+bool ProcessLaunchInfo::NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal, int status) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS);
+ LLDB_LOG(log, "pid = {0}, exited = {1}, signal = {2}, status = {3}", pid,
+ exited, signal, status);
+ return true;
+}
+
bool ProcessLaunchInfo::MonitorProcess() const {
if (m_monitor_callback && ProcessIDIsValid()) {
Host::StartMonitoringChildProcess(m_monitor_callback, GetProcessID(),
@@ -210,8 +217,7 @@ void ProcessLaunchInfo::FinalizeFileActions(Target *target,
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
// If nothing for stdin or stdout or stderr was specified, then check the
- // process for any default
- // settings that were set with "settings set"
+ // process for any default settings that were set with "settings set"
if (GetFileActionForFD(STDIN_FILENO) == nullptr ||
GetFileActionForFD(STDOUT_FILENO) == nullptr ||
GetFileActionForFD(STDERR_FILENO) == nullptr) {
@@ -221,8 +227,8 @@ void ProcessLaunchInfo::FinalizeFileActions(Target *target,
__FUNCTION__);
if (m_flags.Test(eLaunchFlagLaunchInTTY)) {
- // Do nothing, if we are launching in a remote terminal
- // no file actions should be done at all.
+ // Do nothing, if we are launching in a remote terminal no file actions
+ // should be done at all.
return;
}
@@ -235,16 +241,15 @@ void ProcessLaunchInfo::FinalizeFileActions(Target *target,
AppendSuppressFileAction(STDOUT_FILENO, false, true);
AppendSuppressFileAction(STDERR_FILENO, false, true);
} else {
- // Check for any values that might have gotten set with any of:
- // (lldb) settings set target.input-path
- // (lldb) settings set target.output-path
+ // Check for any values that might have gotten set with any of: (lldb)
+ // settings set target.input-path (lldb) settings set target.output-path
// (lldb) settings set target.error-path
FileSpec in_file_spec;
FileSpec out_file_spec;
FileSpec err_file_spec;
if (target) {
- // Only override with the target settings if we don't already have
- // an action for in, out or error
+ // Only override with the target settings if we don't already have an
+ // action for in, out or error
if (GetFileActionForFD(STDIN_FILENO) == nullptr)
in_file_spec = target->GetStandardInputPath();
if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
@@ -295,9 +300,9 @@ void ProcessLaunchInfo::FinalizeFileActions(Target *target,
int open_flags = O_RDWR | O_NOCTTY;
#if !defined(_WIN32)
- // We really shouldn't be specifying platform specific flags
- // that are intended for a system call in generic code. But
- // this will have to do for now.
+ // We really shouldn't be specifying platform specific flags that are
+ // intended for a system call in generic code. But this will have to
+ // do for now.
open_flags |= O_CLOEXEC;
#endif
if (m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
@@ -351,14 +356,13 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
StreamString shell_command;
if (will_debug) {
- // Add a modified PATH environment variable in case argv[0]
- // is a relative path.
+ // Add a modified PATH environment variable in case argv[0] is a
+ // relative path.
const char *argv0 = argv[0];
FileSpec arg_spec(argv0, false);
if (arg_spec.IsRelative()) {
- // We have a relative path to our executable which may not work if
- // we just try to run "a.out" (without it being converted to
- // "./a.out")
+ // We have a relative path to our executable which may not work if we
+ // just try to run "a.out" (without it being converted to "./a.out")
FileSpec working_dir = GetWorkingDirectory();
// Be sure to put quotes around PATH's value in case any paths have
// spaces...
@@ -410,8 +414,8 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
}
if (first_arg_is_full_shell_command) {
- // There should only be one argument that is the shell command itself to
- // be used as is
+ // There should only be one argument that is the shell command itself
+ // to be used as is
if (argv[0] && !argv[1])
shell_command.Printf("%s", argv[0]);
else
diff --git a/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp b/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp
index 28beb7bcb5e8..eaec03d9b595 100644
--- a/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp
@@ -76,8 +76,7 @@ RegisterContext::UpdateDynamicRegisterSize(const lldb_private::ArchSpec &arch,
ExecutionContext exe_ctx(CalculateThread());
// In MIPS, the floating point registers size is depends on FR bit of SR
- // register.
- // if SR.FR == 1 then all floating point registers are 64 bits.
+ // register. if SR.FR == 1 then all floating point registers are 64 bits.
// else they are all 32 bits.
int expr_result;
@@ -136,7 +135,7 @@ uint64_t RegisterContext::GetPC(uint64_t fail_value) {
if (target_sp) {
Target *target = target_sp.get();
if (target)
- pc = target->GetOpcodeLoadAddress(pc, eAddressClassCode);
+ pc = target->GetOpcodeLoadAddress(pc, AddressClass::eCode);
}
}
@@ -262,8 +261,7 @@ bool RegisterContext::CopyFromRegisterContext(lldb::RegisterContextSP context) {
RegisterValue reg_value;
// If we can reconstruct the register from the frame we are copying from,
- // then do so, otherwise
- // use the value from frame 0.
+ // then do so, otherwise use the value from frame 0.
if (context->ReadRegister(reg_info, reg_value)) {
WriteRegister(reg_info, reg_value);
} else if (frame_zero_context->ReadRegister(reg_info, reg_value)) {
@@ -355,12 +353,11 @@ Status RegisterContext::ReadRegisterValueFromMemory(
return error;
}
- // We now have a memory buffer that contains the part or all of the register
- // value. Set the register value using this memory data.
+ // We now have a memory buffer that contains the part or all of the
+ // register value. Set the register value using this memory data.
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
- // assuming
- // they are the same.
+ // assuming they are the same.
reg_value.SetFromMemoryData(reg_info, src, src_len,
process_sp->GetByteOrder(), error);
} else
@@ -381,8 +378,7 @@ Status RegisterContext::WriteRegisterValueToMemory(
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
- // assuming
- // they are the same.
+ // assuming they are the same.
const uint32_t bytes_copied = reg_value.GetAsMemoryData(
reg_info, dst, dst_len, process_sp->GetByteOrder(), error);
@@ -431,9 +427,9 @@ ThreadSP RegisterContext::CalculateThread() {
}
StackFrameSP RegisterContext::CalculateStackFrame() {
- // Register contexts might belong to many frames if we have inlined
- // functions inside a frame since all inlined functions share the
- // same registers, so we can't definitively say which frame we come from...
+ // Register contexts might belong to many frames if we have inlined functions
+ // inside a frame since all inlined functions share the same registers, so we
+ // can't definitively say which frame we come from...
return StackFrameSP();
}
diff --git a/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp b/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp
index 740f48bc829c..5844da5d41e9 100644
--- a/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp
@@ -43,13 +43,12 @@ SectionLoadHistory::GetSectionLoadListForStopID(uint32_t stop_id,
if (!m_stop_id_to_section_load_list.empty()) {
if (read_only) {
// The section load list is for reading data only so we don't need to
- // create
- // a new SectionLoadList for the current stop ID, just return the section
- // load list for the stop ID that is equal to or less than the current
- // stop ID
+ // create a new SectionLoadList for the current stop ID, just return the
+ // section load list for the stop ID that is equal to or less than the
+ // current stop ID
if (stop_id == eStopIDNow) {
- // If we are asking for the latest and greatest value, it is always
- // at the end of our list because that will be the highest stop ID.
+ // If we are asking for the latest and greatest value, it is always at
+ // the end of our list because that will be the highest stop ID.
StopIDToSectionLoadList::reverse_iterator rpos =
m_stop_id_to_section_load_list.rbegin();
return rpos->second.get();
@@ -70,10 +69,8 @@ SectionLoadHistory::GetSectionLoadListForStopID(uint32_t stop_id,
assert(stop_id != eStopIDNow);
// We are updating the section load list (not read only), so if the stop
- // ID
- // passed in isn't the same as the last stop ID in our collection, then
- // create
- // a new node using the current stop ID
+ // ID passed in isn't the same as the last stop ID in our collection,
+ // then create a new node using the current stop ID
StopIDToSectionLoadList::iterator pos =
m_stop_id_to_section_load_list.lower_bound(stop_id);
if (pos != m_stop_id_to_section_load_list.end() &&
diff --git a/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp b/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp
index 31ccf17369db..6839aaccaa52 100644
--- a/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp
@@ -97,12 +97,12 @@ bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP &section,
// we have multiple load addresses that correspond to a section, we will
// always attribute the section to the be last section that claims it
// exists at that address. Sometimes it is ok for more that one section
- // to be loaded at a specific load address, and other times it isn't.
- // The "warn_multiple" parameter tells us if we should warn in this case
- // or not. The DynamicLoader plug-in subclasses should know which
- // sections should warn and which shouldn't (darwin shared cache modules
- // all shared the same "__LINKEDIT" sections, so the dynamic loader can
- // pass false for "warn_multiple").
+ // to be loaded at a specific load address, and other times it isn't. The
+ // "warn_multiple" parameter tells us if we should warn in this case or
+ // not. The DynamicLoader plug-in subclasses should know which sections
+ // should warn and which shouldn't (darwin shared cache modules all
+ // shared the same "__LINKEDIT" sections, so the dynamic loader can pass
+ // false for "warn_multiple").
if (warn_multiple && section != ats_pos->second) {
ModuleSP module_sp(section->GetModule());
if (module_sp) {
@@ -228,8 +228,8 @@ bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr,
}
}
} else {
- // There are no entries that have an address that is >= load_addr,
- // so we need to check the last entry on our collection.
+ // There are no entries that have an address that is >= load_addr, so we
+ // need to check the last entry on our collection.
addr_to_sect_collection::const_reverse_iterator rpos =
m_addr_to_sect.rbegin();
if (load_addr >= rpos->first) {
diff --git a/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp b/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp
index dd44eac8e50c..2b9260f95f3f 100644
--- a/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp
@@ -60,8 +60,8 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
m_is_history_frame(is_history_frame), m_variable_list_sp(),
m_variable_list_value_objects(), m_disassembly(), m_mutex() {
// If we don't have a CFA value, use the frame index for our StackID so that
- // recursive
- // functions properly aren't confused with one another on a history stack.
+ // recursive functions properly aren't confused with one another on a history
+ // stack.
if (m_is_history_frame && !m_cfa_is_valid) {
m_id.SetCFA(m_frame_index);
}
@@ -136,17 +136,17 @@ StackFrame::~StackFrame() = default;
StackID &StackFrame::GetStackID() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- // Make sure we have resolved the StackID object's symbol context scope if
- // we already haven't looked it up.
+ // Make sure we have resolved the StackID object's symbol context scope if we
+ // already haven't looked it up.
if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) {
if (m_id.GetSymbolContextScope()) {
- // We already have a symbol context scope, we just don't have our
- // flag bit set.
+ // We already have a symbol context scope, we just don't have our flag
+ // bit set.
m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);
} else {
- // Calculate the frame block and use this for the stack ID symbol
- // context scope if we have one.
+ // Calculate the frame block and use this for the stack ID symbol context
+ // scope if we have one.
SymbolContextScope *scope = GetFrameBlock();
if (scope == nullptr) {
// We don't have a block, so use the symbol
@@ -194,7 +194,7 @@ const Address &StackFrame::GetFrameCodeAddress() {
const bool allow_section_end = true;
if (m_frame_code_addr.SetOpcodeLoadAddress(
m_frame_code_addr.GetOffset(), target_sp.get(),
- eAddressClassCode, allow_section_end)) {
+ AddressClass::eCode, allow_section_end)) {
ModuleSP module_sp(m_frame_code_addr.GetModule());
if (module_sp) {
m_sc.module_sp = module_sp;
@@ -247,13 +247,13 @@ Block *StackFrame::GetFrameBlock() {
if (m_sc.block) {
Block *inline_block = m_sc.block->GetContainingInlinedBlock();
if (inline_block) {
- // Use the block with the inlined function info
- // as the frame block we want this frame to have only the variables
- // for the inlined function and its non-inlined block child blocks.
+ // Use the block with the inlined function info as the frame block we
+ // want this frame to have only the variables for the inlined function
+ // and its non-inlined block child blocks.
return inline_block;
} else {
- // This block is not contained within any inlined function blocks
- // with so we want to use the top most function block.
+ // This block is not contained within any inlined function blocks with so
+ // we want to use the top most function block.
return &m_sc.function->GetBlock(false);
}
}
@@ -263,8 +263,8 @@ Block *StackFrame::GetFrameBlock() {
//----------------------------------------------------------------------
// Get the symbol context if we already haven't done so by resolving the
// PC address as much as possible. This way when we pass around a
-// StackFrame object, everyone will have as much information as
-// possible and no one will ever have to look things up manually.
+// StackFrame object, everyone will have as much information as possible and no
+// one will ever have to look things up manually.
//----------------------------------------------------------------------
const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
@@ -279,15 +279,15 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
resolved |= eSymbolContextTarget;
}
- // Resolve our PC to section offset if we haven't already done so
- // and if we don't have a module. The resolved address section will
- // contain the module to which it belongs
+ // Resolve our PC to section offset if we haven't already done so and if we
+ // don't have a module. The resolved address section will contain the
+ // module to which it belongs
if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
GetFrameCodeAddress();
- // If this is not frame zero, then we need to subtract 1 from the PC
- // value when doing address lookups since the PC will be on the
- // instruction following the function call instruction...
+ // If this is not frame zero, then we need to subtract 1 from the PC value
+ // when doing address lookups since the PC will be on the instruction
+ // following the function call instruction...
Address lookup_addr(GetFrameCodeAddress());
if (m_frame_index > 0 && lookup_addr.IsValid()) {
@@ -296,10 +296,9 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
lookup_addr.SetOffset(offset - 1);
} else {
- // lookup_addr is the start of a section. We need
- // do the math on the actual load address and re-compute
- // the section. We're working with a 'noreturn' function
- // at the end of a section.
+ // lookup_addr is the start of a section. We need do the math on the
+ // actual load address and re-compute the section. We're working with
+ // a 'noreturn' function at the end of a section.
ThreadSP thread_sp(GetThread());
if (thread_sp) {
TargetSP target_sp(thread_sp->CalculateTarget());
@@ -315,9 +314,9 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
}
if (m_sc.module_sp) {
- // We have something in our stack frame symbol context, lets check
- // if we haven't already tried to lookup one of those things. If we
- // haven't then we will do the query.
+ // We have something in our stack frame symbol context, lets check if we
+ // haven't already tried to lookup one of those things. If we haven't
+ // then we will do the query.
uint32_t actual_resolve_scope = 0;
@@ -367,17 +366,16 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
}
if (actual_resolve_scope) {
- // We might be resolving less information than what is already
- // in our current symbol context so resolve into a temporary
- // symbol context "sc" so we don't clear out data we have
- // already found in "m_sc"
+ // We might be resolving less information than what is already in our
+ // current symbol context so resolve into a temporary symbol context
+ // "sc" so we don't clear out data we have already found in "m_sc"
SymbolContext sc;
// Set flags that indicate what we have tried to resolve
resolved |= m_sc.module_sp->ResolveSymbolContextForAddress(
lookup_addr, actual_resolve_scope, sc);
- // Only replace what we didn't already have as we may have
- // information for an inlined function scope that won't match
- // what a standard lookup by address would match
+ // Only replace what we didn't already have as we may have information
+ // for an inlined function scope that won't match what a standard
+ // lookup by address would match
if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr)
m_sc.comp_unit = sc.comp_unit;
if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr)
@@ -404,9 +402,9 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
// Update our internal flags so we remember what we have tried to locate so
// we don't have to keep trying when more calls to this function are made.
- // We might have dug up more information that was requested (for example
- // if we were asked to only get the block, we will have gotten the
- // compile unit, and function) so set any additional bits that we resolved
+ // We might have dug up more information that was requested (for example if
+ // we were asked to only get the block, we will have gotten the compile
+ // unit, and function) so set any additional bits that we resolved
m_flags.Set(resolve_scope | resolved);
}
@@ -546,8 +544,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
}
if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) {
- // Check for direct ivars access which helps us with implicit
- // access to ivars with the "this->" or "self->"
+ // Check for direct ivars access which helps us with implicit access to
+ // ivars with the "this->" or "self->"
GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock);
lldb::LanguageType method_language = eLanguageTypeUnknown;
bool is_instance_method = false;
@@ -622,9 +620,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
valobj_sp->GetCompilerType().GetTypeInfo(nullptr);
if ((pointer_type_flags & eTypeIsObjC) &&
(pointer_type_flags & eTypeIsPointer)) {
- // This was an objective C object pointer and
- // it was requested we skip any fragile ivars
- // so return nothing here
+ // This was an objective C object pointer and it was requested we
+ // skip any fragile ivars so return nothing here
return ValueObjectSP();
}
}
@@ -659,15 +656,14 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-[")));
if (check_ptr_vs_member) {
- // We either have a pointer type and need to verify
- // valobj_sp is a pointer, or we have a member of a
- // class/union/struct being accessed with the . syntax
- // and need to verify we don't have a pointer.
+ // We either have a pointer type and need to verify valobj_sp is a
+ // pointer, or we have a member of a class/union/struct being accessed
+ // with the . syntax and need to verify we don't have a pointer.
const bool actual_is_ptr = valobj_sp->IsPointerType();
if (actual_is_ptr != expr_is_ptr) {
- // Incorrect use of "." with a pointer, or "->" with
- // a class/union/struct instance or reference.
+ // Incorrect use of "." with a pointer, or "->" with a
+ // class/union/struct instance or reference.
valobj_sp->GetExpressionPath(var_expr_path_strm, false);
if (actual_is_ptr)
error.SetErrorStringWithFormat(
@@ -697,10 +693,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
// No child member with name "child_name"
if (synthetically_added_instance_object) {
// We added a "this->" or "self->" to the beginning of the
- // expression
- // and this is the first pointer ivar access, so just return
- // the normal
- // error
+ // expression and this is the first pointer ivar access, so just
+ // return the normal error
error.SetErrorStringWithFormat(
"no variable or instance variable named '%s' found in "
"this frame",
@@ -735,8 +729,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
} break;
case '[': {
- // Array member access, or treating pointer as an array
- // Need at least two brackets and a number
+ // Array member access, or treating pointer as an array Need at least two
+ // brackets and a number
if (var_expr.size() <= 2) {
error.SetErrorStringWithFormat(
"invalid square bracket encountered after \"%s\" in \"%s\"",
@@ -790,11 +784,10 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
deref = false;
} else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&
deref) {
- // what we have is *arr[low]. the most similar C++ syntax is
- // to get arr[0]
- // (an operation that is equivalent to deref-ing arr)
- // and extract bit low out of it. reading array item low
- // would be done by saying arr[low], without a deref * sign
+ // what we have is *arr[low]. the most similar C++ syntax is to get
+ // arr[0] (an operation that is equivalent to deref-ing arr) and
+ // extract bit low out of it. reading array item low would be done by
+ // saying arr[low], without a deref * sign
Status error;
ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true));
if (error.Fail()) {
@@ -828,8 +821,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
return ValueObjectSP();
} else if (is_objc_pointer) {
- // dereferencing ObjC variables is not valid.. so let's try
- // and recur to synthetic children
+ // dereferencing ObjC variables is not valid.. so let's try and
+ // recur to synthetic children
ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
if (!synthetic /* no synthetic */
|| synthetic == valobj_sp) /* synthetic is the same as
@@ -874,9 +867,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
}
} else if (valobj_sp->GetCompilerType().IsArrayType(
nullptr, nullptr, &is_incomplete_array)) {
- // Pass false to dynamic_value here so we can tell the
- // difference between
- // no dynamic value and no member of this type...
+ // Pass false to dynamic_value here so we can tell the difference
+ // between no dynamic value and no member of this type...
child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true);
if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))
child_valobj_sp =
@@ -976,8 +968,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
// what we have is *ptr[low-high]. the most similar C++ syntax is to
// deref ptr and extract bits low thru high out of it. reading array
- // items low thru high would be done by saying ptr[low-high], without
- // a deref * sign
+ // items low thru high would be done by saying ptr[low-high], without a
+ // deref * sign
Status error;
ValueObjectSP temp(valobj_sp->Dereference(error));
if (error.Fail()) {
@@ -991,10 +983,10 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
valobj_sp = temp;
deref = false;
} else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {
- // what we have is *arr[low-high]. the most similar C++ syntax is to get
- // arr[0] (an operation that is equivalent to deref-ing arr) and extract
- // bits low thru high out of it. reading array items low thru high would
- // be done by saying arr[low-high], without a deref * sign
+ // what we have is *arr[low-high]. the most similar C++ syntax is to
+ // get arr[0] (an operation that is equivalent to deref-ing arr) and
+ // extract bits low thru high out of it. reading array items low thru
+ // high would be done by saying arr[low-high], without a deref * sign
Status error;
ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true));
if (error.Fail()) {
@@ -1091,8 +1083,8 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
if (m_sc.function->GetFrameBaseExpression().Evaluate(
&exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr,
expr_value, &m_frame_base_error) == false) {
- // We should really have an error if evaluate returns, but in case
- // we don't, lets set the error to something at least.
+ // We should really have an error if evaluate returns, but in case we
+ // don't, lets set the error to something at least.
if (m_frame_base_error.Success())
m_frame_base_error.SetErrorString(
"Evaluation of the frame base expression failed.");
@@ -1420,8 +1412,8 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
ValueObjectSP &base,
int64_t offset) {
// base is a pointer to something
- // offset is the thing to add to the pointer
- // We return the most sensible ValueObject for the result of *(base+offset)
+ // offset is the thing to add to the pointer We return the most sensible
+ // ValueObject for the result of *(base+offset)
if (!base->IsPointerOrReferenceType()) {
return ValueObjectSP();
@@ -1486,8 +1478,8 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
//
// f, a pointer to a struct, is known to be at -0x8(%rbp).
//
- // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at +18
- // that assigns to rdi, and calls itself recursively for that dereference
+ // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at
+ // +18 that assigns to rdi, and calls itself recursively for that dereference
// DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at
// +14 that assigns to rdi, and calls itself recursively for that
// derefernece
@@ -1533,9 +1525,9 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {
// This is not an exact algorithm, and it sacrifices accuracy for
- // generality. Recognizing "mov" and "ld" instructions –– and which are
- // their source and destination operands -- is something the disassembler
- // should do for us.
+ // generality. Recognizing "mov" and "ld" instructions –– and which
+ // are their source and destination operands -- is something the
+ // disassembler should do for us.
InstructionSP instruction_sp =
disassembler.GetInstructionList().GetInstructionAtIndex(ii);
diff --git a/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp b/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp
index be7fa8001212..2380a91df41d 100644
--- a/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp
@@ -51,8 +51,8 @@ StackFrameList::StackFrameList(Thread &thread,
}
StackFrameList::~StackFrameList() {
- // Call clear since this takes a lock and clears the stack frame list
- // in case another thread is currently using this stack frame list
+ // Call clear since this takes a lock and clears the stack frame list in case
+ // another thread is currently using this stack frame list
Clear();
}
@@ -95,13 +95,12 @@ void StackFrameList::ResetCurrentInlinedDepth() {
log->Printf(
"ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
} else {
- // We only need to do something special about inlined blocks when we
- // are at the beginning of an inlined function:
+ // We only need to do something special about inlined blocks when we are
+ // at the beginning of an inlined function:
// FIXME: We probably also have to do something special if the PC is at
// the END
// of an inlined function, which coincides with the end of either its
- // containing
- // function or another inlined function.
+ // containing function or another inlined function.
lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
Block *block_ptr = m_frames[0]->GetFrameBlock();
@@ -114,19 +113,15 @@ void StackFrameList::ResetCurrentInlinedDepth() {
containing_range)) {
if (pc_as_address == containing_range.GetBaseAddress()) {
// If we got here because of a breakpoint hit, then set the inlined
- // depth depending on where
- // the breakpoint was set.
- // If we got here because of a crash, then set the inlined depth to
- // the deepest most block.
- // Otherwise, we stopped here naturally as the result of a step, so
- // set ourselves in the
- // containing frame of the whole set of nested inlines, so the user
- // can then "virtually"
- // step into the frames one by one, or next over the whole mess.
- // Note: We don't have to handle being somewhere in the middle of
- // the stack here, since
- // ResetCurrentInlinedDepth doesn't get called if there is a valid
- // inlined depth set.
+ // depth depending on where the breakpoint was set. If we got here
+ // because of a crash, then set the inlined depth to the deepest
+ // most block. Otherwise, we stopped here naturally as the result
+ // of a step, so set ourselves in the containing frame of the whole
+ // set of nested inlines, so the user can then "virtually" step
+ // into the frames one by one, or next over the whole mess. Note:
+ // We don't have to handle being somewhere in the middle of the
+ // stack here, since ResetCurrentInlinedDepth doesn't get called if
+ // there is a valid inlined depth set.
StopInfoSP stop_info_sp = m_thread.GetStopInfo();
if (stop_info_sp) {
switch (stop_info_sp->GetStopReason()) {
@@ -134,7 +129,8 @@ void StackFrameList::ResetCurrentInlinedDepth() {
case eStopReasonException:
case eStopReasonExec:
case eStopReasonSignal:
- // In all these cases we want to stop in the deepest most frame.
+ // In all these cases we want to stop in the deepest most
+ // frame.
m_current_inlined_pc = curr_pc;
m_current_inlined_depth = 0;
break;
@@ -142,17 +138,14 @@ void StackFrameList::ResetCurrentInlinedDepth() {
// FIXME: Figure out what this break point is doing, and set the
// inline depth
// appropriately. Be careful to take into account breakpoints
- // that implement
- // step over prologue, since that should do the default
- // calculation.
- // For now, if the breakpoints corresponding to this hit are all
- // internal,
+ // that implement step over prologue, since that should do the
+ // default calculation. For now, if the breakpoints
+ // corresponding to this hit are all internal,
// I set the stop location to the top of the inlined stack,
// since that will make
- // things like stepping over prologues work right. But if there
- // are any non-internal
- // breakpoints I do to the bottom of the stack, since that was
- // the old behavior.
+ // things like stepping over prologues work right. But if
+ // there are any non-internal breakpoints I do to the bottom of
+ // the stack, since that was the old behavior.
uint32_t bp_site_id = stop_info_sp->GetValue();
BreakpointSiteSP bp_site_sp(
m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
@@ -177,10 +170,9 @@ void StackFrameList::ResetCurrentInlinedDepth() {
LLVM_FALLTHROUGH;
default: {
// Otherwise, we should set ourselves at the container of the
- // inlining, so that the
- // user can descend into them.
- // So first we check whether we have more than one inlined block
- // sharing this PC:
+ // inlining, so that the user can descend into them. So first
+ // we check whether we have more than one inlined block sharing
+ // this PC:
int num_inlined_functions = 0;
for (Block *container_ptr = block_ptr->GetInlinedParent();
@@ -250,13 +242,11 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
#if defined(DEBUG_STACK_FRAMES)
StreamFile s(stdout, false);
#endif
- // If we are hiding some frames from the outside world, we need to add those
- // onto the total count of
- // frames to fetch. However, we don't need to do that if end_idx is 0 since
- // in that case we always
- // get the first concrete frame and all the inlined frames below it... And
- // of course, if end_idx is
- // UINT32_MAX that means get all, so just do that...
+ // If we are hiding some frames from the outside world, we need to add
+ // those onto the total count of frames to fetch. However, we don't need
+ // to do that if end_idx is 0 since in that case we always get the first
+ // concrete frame and all the inlined frames below it... And of course, if
+ // end_idx is UINT32_MAX that means get all, so just do that...
uint32_t inlined_depth = 0;
if (end_idx > 0 && end_idx != UINT32_MAX) {
@@ -273,17 +263,17 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
lldb::addr_t pc = LLDB_INVALID_ADDRESS;
lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
if (idx == 0) {
- // We might have already created frame zero, only create it
- // if we need to
+ // We might have already created frame zero, only create it if we need
+ // to
if (m_frames.empty()) {
RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
if (reg_ctx_sp) {
const bool success =
unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- // There shouldn't be any way not to get the frame info for frame 0.
- // But if the unwinder can't make one, lets make one by hand with
- // the
+ // There shouldn't be any way not to get the frame info for frame
+ // 0. But if the unwinder can't make one, lets make one by hand
+ // with the
// SP as the CFA and see if that gets any further.
if (!success) {
cfa = reg_ctx_sp->GetSP();
@@ -323,22 +313,20 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
if (unwind_block) {
Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
TargetSP target_sp = m_thread.CalculateTarget();
- // Be sure to adjust the frame address to match the address
- // that was used to lookup the symbol context above. If we are
- // in the first concrete frame, then we lookup using the current
- // address, else we decrement the address by one to get the correct
- // location.
+ // Be sure to adjust the frame address to match the address that was
+ // used to lookup the symbol context above. If we are in the first
+ // concrete frame, then we lookup using the current address, else we
+ // decrement the address by one to get the correct location.
if (idx > 0) {
if (curr_frame_address.GetOffset() == 0) {
// If curr_frame_address points to the first address in a section
- // then after
- // adjustment it will point to an other section. In that case
- // resolve the
- // address again to the correct section plus offset form.
+ // then after adjustment it will point to an other section. In that
+ // case resolve the address again to the correct section plus
+ // offset form.
addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
- target_sp.get(), eAddressClassCode);
+ target_sp.get(), AddressClass::eCode);
curr_frame_address.SetOpcodeLoadAddress(
- load_addr - 1, target_sp.get(), eAddressClassCode);
+ load_addr - 1, target_sp.get(), AddressClass::eCode);
} else {
curr_frame_address.Slide(-1);
}
@@ -414,8 +402,8 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
break;
prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
- // Now copy the fixed up previous frame into the current frames
- // so the pointer doesn't change
+ // Now copy the fixed up previous frame into the current frames so the
+ // pointer doesn't change
m_frames[curr_frame_idx] = prev_frame_sp;
// curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
@@ -495,9 +483,8 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
if (frame_sp)
return frame_sp;
- // GetFramesUpTo will fill m_frames with as many frames as you asked for,
- // if there are that many. If there weren't then you asked for too many
- // frames.
+ // GetFramesUpTo will fill m_frames with as many frames as you asked for, if
+ // there are that many. If there weren't then you asked for too many frames.
GetFramesUpTo(idx);
if (idx < m_frames.size()) {
if (m_show_inlined_frames) {
@@ -519,8 +506,8 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
Function *function =
frame_sp->GetSymbolContext(eSymbolContextFunction).function;
if (function) {
- // When we aren't showing inline functions we always use
- // the top most function block as the scope.
+ // When we aren't showing inline functions we always use the top
+ // most function block as the scope.
frame_sp->SetSymbolContextScope(&function->GetBlock(false));
} else {
// Set the symbol scope from the symbol regardless if it is nullptr
@@ -534,9 +521,8 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
}
} else if (original_idx == 0) {
// There should ALWAYS be a frame at index 0. If something went wrong with
- // the CurrentInlinedDepth such that
- // there weren't as many frames as we thought taking that into account, then
- // reset the current inlined depth
+ // the CurrentInlinedDepth such that there weren't as many frames as we
+ // thought taking that into account, then reset the current inlined depth
// and return the real zeroth frame.
if (m_frames.empty()) {
// Why do we have a thread with zero frames, that should not ever
@@ -554,11 +540,11 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
StackFrameSP
StackFrameList::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
// First try assuming the unwind index is the same as the frame index. The
- // unwind index is always greater than or equal to the frame index, so it
- // is a good place to start. If we have inlined frames we might have 5
- // concrete frames (frame unwind indexes go from 0-4), but we might have 15
- // frames after we make all the inlined frames. Most of the time the unwind
- // frame index (or the concrete frame index) is the same as the frame index.
+ // unwind index is always greater than or equal to the frame index, so it is
+ // a good place to start. If we have inlined frames we might have 5 concrete
+ // frames (frame unwind indexes go from 0-4), but we might have 15 frames
+ // after we make all the inlined frames. Most of the time the unwind frame
+ // index (or the concrete frame index) is the same as the frame index.
uint32_t frame_idx = unwind_idx;
StackFrameSP frame_sp(GetFrameAtIndex(frame_idx));
while (frame_sp) {
@@ -719,9 +705,9 @@ void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_ap,
#if defined(DEBUG_STACK_FRAMES)
s.PutCString("No previous frames, so use current frames...\n");
#endif
- // We either don't have any previous frames, or since we have more than
- // one current frames it means we have all the frames and can safely
- // replace our previous frames.
+ // We either don't have any previous frames, or since we have more than one
+ // current frames it means we have all the frames and can safely replace
+ // our previous frames.
prev_sp.reset(curr_ap.release());
return;
}
@@ -733,8 +719,8 @@ void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_ap,
s.PutCString(
"We have more than one current frame, so use current frames...\n");
#endif
- // We have more than one current frames it means we have all the frames
- // and can safely replace our previous frames.
+ // We have more than one current frames it means we have all the frames and
+ // can safely replace our previous frames.
prev_sp.reset(curr_ap.release());
#if defined(DEBUG_STACK_FRAMES)
diff --git a/contrib/llvm/tools/lldb/source/Target/StackID.cpp b/contrib/llvm/tools/lldb/source/Target/StackID.cpp
index 889cf89b9be7..341c902af995 100644
--- a/contrib/llvm/tools/lldb/source/Target/StackID.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StackID.cpp
@@ -69,12 +69,11 @@ bool lldb_private::operator<(const StackID &lhs, const StackID &rhs) {
// FIXME: We are assuming that the stacks grow downward in memory. That's not
// necessary, but true on
// all the machines we care about at present. If this changes, we'll have to
- // deal with that. The ABI is the
- // agent who knows this ordering, but the StackID has no access to the ABI.
- // The most straightforward way
- // to handle this is to add a "m_grows_downward" bool to the StackID, and set
- // it in the constructor.
- // But I'm not going to waste a bool per StackID on this till we need it.
+ // deal with that. The ABI is the agent who knows this ordering, but the
+ // StackID has no access to the ABI. The most straightforward way to handle
+ // this is to add a "m_grows_downward" bool to the StackID, and set it in the
+ // constructor. But I'm not going to waste a bool per StackID on this till we
+ // need it.
if (lhs_cfa != rhs_cfa)
return lhs_cfa < rhs_cfa;
diff --git a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
index 652ad8a05445..f8b17dc10eca 100644
--- a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
@@ -63,12 +63,10 @@ bool StopInfo::HasTargetRunSinceMe() {
return true;
} else if (ret_type == eStateStopped) {
// This is a little tricky. We want to count "run and stopped again
- // before you could
- // ask this question as a "TRUE" answer to HasTargetRunSinceMe. But we
- // don't want to
- // include any running of the target done for expressions. So we track
- // both resumes,
- // and resumes caused by expressions, and check if there are any resumes
+ // before you could ask this question as a "TRUE" answer to
+ // HasTargetRunSinceMe. But we don't want to include any running of the
+ // target done for expressions. So we track both resumes, and resumes
+ // caused by expressions, and check if there are any resumes
// NOT caused
// by expressions.
@@ -199,8 +197,7 @@ public:
if (bp_site_sp) {
StreamString strm;
// If we have just hit an internal breakpoint, and it has a kind
- // description, print that instead of the
- // full breakpoint printing:
+ // description, print that instead of the full breakpoint printing:
if (bp_site_sp->IsInternal()) {
size_t num_owners = bp_site_sp->GetNumberOfOwners();
for (size_t idx = 0; idx < num_owners; idx++) {
@@ -258,9 +255,9 @@ public:
protected:
bool ShouldStop(Event *event_ptr) override {
- // This just reports the work done by PerformAction or the synchronous stop.
- // It should
- // only ever get called after they have had a chance to run.
+ // This just reports the work done by PerformAction or the synchronous
+ // stop. It should only ever get called after they have had a chance to
+ // run.
assert(m_should_stop_is_valid);
return m_should_stop;
}
@@ -293,54 +290,47 @@ protected:
if (bp_site_sp) {
// Let's copy the owners list out of the site and store them in a local
- // list. That way if
- // one of the breakpoint actions changes the site, then we won't be
- // operating on a bad list.
+ // list. That way if one of the breakpoint actions changes the site,
+ // then we won't be operating on a bad list.
BreakpointLocationCollection site_locations;
size_t num_owners = bp_site_sp->CopyOwnersList(site_locations);
if (num_owners == 0) {
m_should_stop = true;
} else {
- // We go through each location, and test first its precondition - this
- // overrides everything. Note,
- // we only do this once per breakpoint - not once per location...
- // Then check the condition. If the condition says to stop,
- // then we run the callback for that location. If that callback says
- // to stop as well, then
- // we set m_should_stop to true; we are going to stop.
- // But we still want to give all the breakpoints whose conditions say
- // we are going to stop a
- // chance to run their callbacks.
- // Of course if any callback restarts the target by putting "continue"
- // in the callback, then
+ // We go through each location, and test first its precondition -
+ // this overrides everything. Note, we only do this once per
+ // breakpoint - not once per location... Then check the condition.
+ // If the condition says to stop, then we run the callback for that
+ // location. If that callback says to stop as well, then we set
+ // m_should_stop to true; we are going to stop. But we still want to
+ // give all the breakpoints whose conditions say we are going to stop
+ // a chance to run their callbacks. Of course if any callback
+ // restarts the target by putting "continue" in the callback, then
// we're going to restart, without running the rest of the callbacks.
- // And in this case we will
- // end up not stopping even if another location said we should stop.
- // But that's better than not
- // running all the callbacks.
+ // And in this case we will end up not stopping even if another
+ // location said we should stop. But that's better than not running
+ // all the callbacks.
m_should_stop = false;
// We don't select threads as we go through them testing breakpoint
- // conditions and running commands.
- // So we need to set the thread for expression evaluation here:
+ // conditions and running commands. So we need to set the thread for
+ // expression evaluation here:
ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);
ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
Process *process = exe_ctx.GetProcessPtr();
if (process->GetModIDRef().IsLastResumeForUserExpression()) {
// If we are in the middle of evaluating an expression, don't run
- // asynchronous breakpoint commands or
- // expressions. That could lead to infinite recursion if the
- // command or condition re-calls the function
- // with this breakpoint.
+ // asynchronous breakpoint commands or expressions. That could
+ // lead to infinite recursion if the command or condition re-calls
+ // the function with this breakpoint.
// TODO: We can keep a list of the breakpoints we've seen while
// running expressions in the nested
// PerformAction calls that can arise when the action runs a
- // function that hits another breakpoint,
- // and only stop running commands when we see the same breakpoint
- // hit a second time.
+ // function that hits another breakpoint, and only stop running
+ // commands when we see the same breakpoint hit a second time.
m_should_stop_is_valid = true;
if (log)
@@ -377,12 +367,11 @@ protected:
StoppointCallbackContext context(event_ptr, exe_ctx, false);
// For safety's sake let's also grab an extra reference to the
- // breakpoint owners of the locations we're
- // going to examine, since the locations are going to have to get back
- // to their breakpoints, and the
- // locations don't keep their owners alive. I'm just sticking the
- // BreakpointSP's in a vector since
- // I'm only using it to locally increment their retain counts.
+ // breakpoint owners of the locations we're going to examine, since
+ // the locations are going to have to get back to their breakpoints,
+ // and the locations don't keep their owners alive. I'm just
+ // sticking the BreakpointSP's in a vector since I'm only using it to
+ // locally increment their retain counts.
std::vector<lldb::BreakpointSP> location_owners;
@@ -404,8 +393,8 @@ protected:
continue;
// The breakpoint site may have many locations associated with it,
- // not all of them valid for
- // this thread. Skip the ones that aren't:
+ // not all of them valid for this thread. Skip the ones that
+ // aren't:
if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) {
if (log) {
log->Printf("Breakpoint %s hit on thread 0x%llx but it was not "
@@ -419,8 +408,7 @@ protected:
internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
// First run the precondition, but since the precondition is per
- // breakpoint, only run it once
- // per breakpoint.
+ // breakpoint, only run it once per breakpoint.
std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
precondition_breakpoints.insert(
bp_loc_sp->GetBreakpoint().GetID());
@@ -433,9 +421,8 @@ protected:
continue;
// Next run the condition for the breakpoint. If that says we
- // should stop, then we'll run
- // the callback for the breakpoint. If the callback says we
- // shouldn't stop that will win.
+ // should stop, then we'll run the callback for the breakpoint. If
+ // the callback says we shouldn't stop that will win.
if (bp_loc_sp->GetConditionText() != nullptr) {
Status condition_error;
@@ -470,9 +457,8 @@ protected:
}
if (!condition_says_stop) {
// We don't want to increment the hit count of breakpoints if
- // the condition fails.
- // We've already bumped it by the time we get here, so undo
- // the bump:
+ // the condition fails. We've already bumped it by the time
+ // we get here, so undo the bump:
bp_loc_sp->UndoBumpHitCount();
continue;
}
@@ -524,8 +510,8 @@ protected:
thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
bp_loc_sp->GetBreakpoint().GetID());
}
- // Also make sure that the callback hasn't continued the target.
- // If it did, when we'll set m_should_start to false and get out of
+ // Also make sure that the callback hasn't continued the target. If
+ // it did, when we'll set m_should_start to false and get out of
// here.
if (HasTargetRunSinceMe()) {
m_should_stop = false;
@@ -551,13 +537,13 @@ protected:
if ((m_should_stop == false || internal_breakpoint)
&& thread_sp->CompletedPlanOverridesBreakpoint()) {
- // Override should_stop decision when we have
- // completed step plan additionally to the breakpoint
+ // Override should_stop decision when we have completed step plan
+ // additionally to the breakpoint
m_should_stop = true;
- // Here we clean the preset stop info so the next
- // GetStopInfo call will find the appropriate stop info,
- // which should be the stop info related to the completed plan
+ // Here we clean the preset stop info so the next GetStopInfo call will
+ // find the appropriate stop info, which should be the stop info
+ // related to the completed plan
thread_sp->ResetStopInfo();
}
@@ -652,8 +638,8 @@ public:
protected:
bool ShouldStopSynchronous(Event *event_ptr) override {
- // ShouldStop() method is idempotent and should not affect hit count.
- // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
+ // ShouldStop() method is idempotent and should not affect hit count. See
+ // Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
// -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()->
// Thread::ShouldStop()->ThreadPlanBase::ShouldStop()->
// StopInfoWatchpoint::ShouldStop() and
@@ -689,9 +675,9 @@ protected:
}
bool ShouldStop(Event *event_ptr) override {
- // This just reports the work done by PerformAction or the synchronous stop.
- // It should
- // only ever get called after they have had a chance to run.
+ // This just reports the work done by PerformAction or the synchronous
+ // stop. It should only ever get called after they have had a chance to
+ // run.
assert(m_should_stop_is_valid);
return m_should_stop;
}
@@ -699,8 +685,8 @@ protected:
void PerformAction(Event *event_ptr) override {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS);
// We're going to calculate if we should stop or not in some way during the
- // course of
- // this code. Also by default we're going to stop, so set that here.
+ // course of this code. Also by default we're going to stop, so set that
+ // here.
m_should_stop = true;
@@ -716,10 +702,8 @@ protected:
{
// check if this process is running on an architecture where
- // watchpoints trigger
- // before the associated instruction runs. if so, disable the WP,
- // single-step and then
- // re-enable the watchpoint
+ // watchpoints trigger before the associated instruction runs. if so,
+ // disable the WP, single-step and then re-enable the watchpoint
if (process_sp) {
uint32_t num;
bool wp_triggers_after;
@@ -727,10 +711,9 @@ protected:
if (process_sp->GetWatchpointSupportInfo(num, wp_triggers_after)
.Success()) {
if (!wp_triggers_after) {
- // We need to preserve the watch_index before watchpoint
- // is disable. Since Watchpoint::SetEnabled will clear the
- // watch index.
- // This will fix TestWatchpointIter failure
+ // We need to preserve the watch_index before watchpoint is
+ // disable. Since Watchpoint::SetEnabled will clear the watch
+ // index. This will fix TestWatchpointIter failure
Watchpoint *wp = wp_sp.get();
uint32_t watch_index = wp->GetHardwareIndex();
process_sp->DisableWatchpoint(wp, false);
@@ -759,8 +742,8 @@ protected:
}
// This sentry object makes sure the current watchpoint is disabled
- // while performing watchpoint actions,
- // and it is then enabled after we are finished.
+ // while performing watchpoint actions, and it is then enabled after we
+ // are finished.
WatchpointSentry sentry(process_sp, wp_sp);
/*
@@ -789,16 +772,13 @@ protected:
// TODO: This condition should be checked in the synchronous part of the
// watchpoint code
// (Watchpoint::ShouldStop), so that we avoid pulling an event even if
- // the watchpoint fails
- // the ignore count condition. It is moved here temporarily, because for
- // archs with
- // watchpoint_exceptions_received=before, the code in the previous lines
- // takes care of moving
- // the inferior to next PC. We have to check the ignore count condition
- // after this is done,
- // otherwise we will hit same watchpoint multiple times until we pass
- // ignore condition, but we
- // won't actually be ignoring them.
+ // the watchpoint fails the ignore count condition. It is moved here
+ // temporarily, because for archs with
+ // watchpoint_exceptions_received=before, the code in the previous
+ // lines takes care of moving the inferior to next PC. We have to check
+ // the ignore count condition after this is done, otherwise we will hit
+ // same watchpoint multiple times until we pass ignore condition, but
+ // we won't actually be ignoring them.
if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount())
m_should_stop = false;
@@ -824,9 +804,9 @@ protected:
if (result_value_sp->ResolveValue(scalar_value)) {
if (scalar_value.ULongLong(1) == 0) {
// We have been vetoed. This takes precedence over querying
- // the watchpoint whether it should stop (aka ignore count and
- // friends). See also StopInfoWatchpoint::ShouldStop() as
- // well as Process::ProcessEventData::DoOnRemoval().
+ // the watchpoint whether it should stop (aka ignore count
+ // and friends). See also StopInfoWatchpoint::ShouldStop()
+ // as well as Process::ProcessEventData::DoOnRemoval().
m_should_stop = false;
} else
m_should_stop = true;
@@ -877,9 +857,8 @@ protected:
debugger.SetAsyncExecution(old_async);
- // Also make sure that the callback hasn't continued the target.
- // If it did, when we'll set m_should_stop to false and get out of
- // here.
+ // Also make sure that the callback hasn't continued the target. If
+ // it did, when we'll set m_should_stop to false and get out of here.
if (HasTargetRunSinceMe())
m_should_stop = false;
diff --git a/contrib/llvm/tools/lldb/source/Target/Target.cpp b/contrib/llvm/tools/lldb/source/Target/Target.cpp
index fdc10cf48275..3f70741713fb 100644
--- a/contrib/llvm/tools/lldb/source/Target/Target.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Target.cpp
@@ -87,13 +87,14 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
Broadcaster(debugger.GetBroadcasterManager(),
Target::GetStaticBroadcasterClass().AsCString()),
ExecutionContextScope(), m_debugger(debugger), m_platform_sp(platform_sp),
- m_mutex(), m_arch(target_arch),
- m_images(this), m_section_load_history(), m_breakpoint_list(false),
- m_internal_breakpoint_list(true), m_watchpoint_list(), m_process_sp(),
- m_search_filter_sp(), m_image_search_paths(ImageSearchPathsChanged, this),
- m_ast_importer_sp(), m_source_manager_ap(), m_stop_hooks(),
- m_stop_hook_next_id(0), m_valid(true), m_suppress_stop_hooks(false),
- m_is_dummy_target(is_dummy_target)
+ m_mutex(), m_arch(target_arch), m_images(this), m_section_load_history(),
+ m_breakpoint_list(false), m_internal_breakpoint_list(true),
+ m_watchpoint_list(), m_process_sp(), m_search_filter_sp(),
+ m_image_search_paths(ImageSearchPathsChanged, this), m_ast_importer_sp(),
+ m_source_manager_ap(), m_stop_hooks(), m_stop_hook_next_id(0),
+ m_valid(true), m_suppress_stop_hooks(false),
+ m_is_dummy_target(is_dummy_target),
+ m_stats_storage(static_cast<int>(StatisticKind::StatisticMax))
{
SetEventName(eBroadcastBitBreakpointChanged, "breakpoint-changed");
@@ -327,11 +328,7 @@ BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
bool hardware,
LazyBool move_to_nearest_code) {
FileSpec remapped_file;
- ConstString remapped_path;
- if (GetSourcePathMap().ReverseRemapPath(ConstString(file.GetPath().c_str()),
- remapped_path))
- remapped_file.SetFile(remapped_path.AsCString(), true);
- else
+ if (!GetSourcePathMap().ReverseRemapPath(file, remapped_file))
remapped_file = file;
if (check_inlines == eLazyBoolCalculate) {
@@ -381,8 +378,8 @@ BreakpointSP Target::CreateBreakpoint(lldb::addr_t addr, bool internal,
// Check for any reason we want to move this breakpoint to other address.
addr = GetBreakableLoadAddress(addr);
- // Attempt to resolve our load address if possible, though it is ok if
- // it doesn't resolve to section/offset.
+ // Attempt to resolve our load address if possible, though it is ok if it
+ // doesn't resolve to section/offset.
// Try and resolve as a load address if possible
GetSectionLoadList().ResolveLoadAddress(addr, so_addr);
@@ -536,8 +533,7 @@ SearchFilterSP Target::GetSearchFilterForModuleAndCUList(
SearchFilterSP filter_sp;
if (containingModules == nullptr) {
// We could make a special "CU List only SearchFilter". Better yet was if
- // these could be composable,
- // but that will take a little reworking.
+ // these could be composable, but that will take a little reworking.
filter_sp.reset(new SearchFilterByModuleListAndCU(
shared_from_this(), FileSpecList(), *containingSourceFiles));
@@ -743,8 +739,8 @@ static bool CheckIfWatchpointsExhausted(Target *target, Status &error) {
return true;
}
-// See also Watchpoint::SetWatchpointType(uint32_t type) and
-// the OptionGroupWatchpoint::WatchType enum type.
+// See also Watchpoint::SetWatchpointType(uint32_t type) and the
+// OptionGroupWatchpoint::WatchType enum type.
WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
const CompilerType *type, uint32_t kind,
Status &error) {
@@ -775,8 +771,8 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
if (!CheckIfWatchpointsExhausted(this, error))
return wp_sp;
- // Currently we only support one watchpoint per address, with total number
- // of watchpoints limited by the hardware which the inferior is running on.
+ // Currently we only support one watchpoint per address, with total number of
+ // watchpoints limited by the hardware which the inferior is running on.
// Grab the list mutex while doing operations.
const bool notify = false; // Don't notify about all the state changes we do
@@ -813,9 +809,8 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
wp_sp->GetID());
if (error.Fail()) {
- // Enabling the watchpoint on the device side failed.
- // Remove the said watchpoint from the list maintained by the target
- // instance.
+ // Enabling the watchpoint on the device side failed. Remove the said
+ // watchpoint from the list maintained by the target instance.
m_watchpoint_list.Remove(wp_sp->GetID(), true);
// See if we could provide more helpful error message.
if (!OptionGroupWatchpoint::IsWatchSizeSupported(size))
@@ -1027,8 +1022,7 @@ Status Target::SerializeBreakpointsToFile(const FileSpec &file,
Breakpoint *bp = GetBreakpointByID(bp_id).get();
StructuredData::ObjectSP bkpt_save_sp = bp->SerializeToStructuredData();
// If the user explicitly asked to serialize a breakpoint, and we
- // can't, then
- // raise an error:
+ // can't, then raise an error:
if (!bkpt_save_sp) {
error.SetErrorStringWithFormat("Unable to serialize breakpoint %d",
bp_id);
@@ -1141,8 +1135,8 @@ bool Target::RemoveAllWatchpoints(bool end_to_end) {
return true; // Success!
}
-// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end to
-// end operations.
+// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end
+// to end operations.
bool Target::DisableAllWatchpoints(bool end_to_end) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
if (log)
@@ -1171,8 +1165,8 @@ bool Target::DisableAllWatchpoints(bool end_to_end) {
return true; // Success!
}
-// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end to
-// end operations.
+// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end
+// to end operations.
bool Target::EnableAllWatchpoints(bool end_to_end) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
if (log)
@@ -1235,8 +1229,8 @@ bool Target::ClearAllWatchpointHistoricValues() {
return true; // Success!
}
-// Assumption: Caller holds the list mutex lock for m_watchpoint_list
-// during these operations.
+// Assumption: Caller holds the list mutex lock for m_watchpoint_list during
+// these operations.
bool Target::IgnoreAllWatchpoints(uint32_t ignore_count) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
if (log)
@@ -1459,7 +1453,8 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) {
if (compatible_local_arch || missing_local_arch) {
// If we haven't got a valid arch spec, or the architectures are compatible
- // update the architecture, unless the one we already have is more specified
+ // update the architecture, unless the one we already have is more
+ // specified
if (replace_local_arch)
m_arch = other;
LLDB_LOG(log, "set architecture to {0} ({1})",
@@ -1502,8 +1497,8 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) {
bool Target::MergeArchitecture(const ArchSpec &arch_spec) {
if (arch_spec.IsValid()) {
if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
- // The current target arch is compatible with "arch_spec", see if we
- // can improve our current architecture using bits from "arch_spec"
+ // The current target arch is compatible with "arch_spec", see if we can
+ // improve our current architecture using bits from "arch_spec"
// Merge bits from arch_spec into "merged_arch" and set our architecture
ArchSpec merged_arch(m_arch.GetSpec());
@@ -1662,8 +1657,8 @@ size_t Target::ReadMemory(const Address &addr, bool prefer_file_cache,
lldb::addr_t *load_addr_ptr) {
error.Clear();
- // if we end up reading this from process memory, we will fill this
- // with the actual load address
+ // if we end up reading this from process memory, we will fill this with the
+ // actual load address
if (load_addr_ptr)
*load_addr_ptr = LLDB_INVALID_ADDRESS;
@@ -1675,16 +1670,16 @@ size_t Target::ReadMemory(const Address &addr, bool prefer_file_cache,
if (!addr.IsSectionOffset()) {
SectionLoadList &section_load_list = GetSectionLoadList();
if (section_load_list.IsEmpty()) {
- // No sections are loaded, so we must assume we are not running
- // yet and anything we are given is a file address.
+ // No sections are loaded, so we must assume we are not running yet and
+ // anything we are given is a file address.
file_addr = addr.GetOffset(); // "addr" doesn't have a section, so its
// offset is the file address
m_images.ResolveFileAddress(file_addr, resolved_addr);
} else {
- // We have at least one section loaded. This can be because
- // we have manually loaded some sections with "target modules load ..."
- // or because we have have a live process that has sections loaded
- // through the dynamic loader
+ // We have at least one section loaded. This can be because we have
+ // manually loaded some sections with "target modules load ..." or
+ // because we have have a live process that has sections loaded through
+ // the dynamic loader
load_addr = addr.GetOffset(); // "addr" doesn't have a section, so its
// offset is the load address
section_load_list.ResolveLoadAddress(load_addr, resolved_addr);
@@ -1731,19 +1726,19 @@ size_t Target::ReadMemory(const Address &addr, bool prefer_file_cache,
*load_addr_ptr = load_addr;
return bytes_read;
}
- // If the address is not section offset we have an address that
- // doesn't resolve to any address in any currently loaded shared
- // libraries and we failed to read memory so there isn't anything
- // more we can do. If it is section offset, we might be able to
- // read cached memory from the object file.
+ // If the address is not section offset we have an address that doesn't
+ // resolve to any address in any currently loaded shared libraries and we
+ // failed to read memory so there isn't anything more we can do. If it is
+ // section offset, we might be able to read cached memory from the object
+ // file.
if (!resolved_addr.IsSectionOffset())
return 0;
}
}
if (!prefer_file_cache && resolved_addr.IsSectionOffset()) {
- // If we didn't already try and read from the object file cache, then
- // try it after failing to read from the process.
+ // If we didn't already try and read from the object file cache, then try
+ // it after failing to read from the process.
return ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
}
return 0;
@@ -1760,8 +1755,8 @@ size_t Target::ReadCStringFromMemory(const Address &addr, std::string &out_str,
if (length == 0)
break;
out_str.append(buf, length);
- // If we got "length - 1" bytes, we didn't get the whole C string, we
- // need to read some more characters
+ // If we got "length - 1" bytes, we didn't get the whole C string, we need
+ // to read some more characters
if (length == sizeof(buf) - 1)
curr_addr += length;
else
@@ -1782,9 +1777,9 @@ size_t Target::ReadCStringFromMemory(const Address &addr, char *dst,
addr_t curr_addr = addr.GetLoadAddress(this);
Address address(addr);
- // We could call m_process_sp->GetMemoryCacheLineSize() but I don't
- // think this really needs to be tied to the memory cache subsystem's
- // cache line size, so leave this as a fixed constant.
+ // We could call m_process_sp->GetMemoryCacheLineSize() but I don't think
+ // this really needs to be tied to the memory cache subsystem's cache line
+ // size, so leave this as a fixed constant.
const size_t cache_line_size = 512;
size_t bytes_left = dst_max_len - 1;
@@ -1875,18 +1870,18 @@ bool Target::ReadPointerFromMemory(const Address &addr, bool prefer_file_cache,
if (pointer_vm_addr != LLDB_INVALID_ADDRESS) {
SectionLoadList &section_load_list = GetSectionLoadList();
if (section_load_list.IsEmpty()) {
- // No sections are loaded, so we must assume we are not running
- // yet and anything we are given is a file address.
+ // No sections are loaded, so we must assume we are not running yet and
+ // anything we are given is a file address.
m_images.ResolveFileAddress(pointer_vm_addr, pointer_addr);
} else {
- // We have at least one section loaded. This can be because
- // we have manually loaded some sections with "target modules load ..."
- // or because we have have a live process that has sections loaded
- // through the dynamic loader
+ // We have at least one section loaded. This can be because we have
+ // manually loaded some sections with "target modules load ..." or
+ // because we have have a live process that has sections loaded through
+ // the dynamic loader
section_load_list.ResolveLoadAddress(pointer_vm_addr, pointer_addr);
}
- // We weren't able to resolve the pointer value, so just return
- // an address with no section
+ // We weren't able to resolve the pointer value, so just return an
+ // address with no section
if (!pointer_addr.IsValid())
pointer_addr.SetOffset(pointer_vm_addr);
return true;
@@ -1902,9 +1897,8 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
Status error;
// First see if we already have this module in our module list. If we do,
- // then we're done, we don't need
- // to consult the shared modules list. But only do this if we are passed a
- // UUID.
+ // then we're done, we don't need to consult the shared modules list. But
+ // only do this if we are passed a UUID.
if (module_spec.GetUUID().IsValid())
module_sp = m_images.FindFirstModule(module_spec);
@@ -1959,8 +1953,8 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
}
// We found a module that wasn't in our target list. Let's make sure that
- // there wasn't an equivalent
- // module in the list already, and if there was, let's remove it.
+ // there wasn't an equivalent module in the list already, and if there was,
+ // let's remove it.
if (module_sp) {
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile) {
@@ -1994,18 +1988,14 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
return ModuleSP();
}
// GetSharedModule is not guaranteed to find the old shared module, for
- // instance
- // in the common case where you pass in the UUID, it is only going to
- // find the one
- // module matching the UUID. In fact, it has no good way to know what
- // the "old module"
- // relevant to this target is, since there might be many copies of a
- // module with this file spec
- // in various running debug sessions, but only one of them will belong
- // to this target.
- // So let's remove the UUID from the module list, and look in the
- // target's module list.
- // Only do this if there is SOMETHING else in the module spec...
+ // instance in the common case where you pass in the UUID, it is only
+ // going to find the one module matching the UUID. In fact, it has no
+ // good way to know what the "old module" relevant to this target is,
+ // since there might be many copies of a module with this file spec in
+ // various running debug sessions, but only one of them will belong to
+ // this target. So let's remove the UUID from the module list, and look
+ // in the target's module list. Only do this if there is SOMETHING else
+ // in the module spec...
if (!old_module_sp) {
if (module_spec.GetUUID().IsValid() &&
!module_spec.GetFileSpec().GetFilename().IsEmpty() &&
@@ -2285,8 +2275,8 @@ ExpressionResults Target::EvaluateExpression(
if (expr.empty())
return execution_results;
- // We shouldn't run stop hooks in expressions.
- // Be sure to reset this if you return anywhere within this function.
+ // We shouldn't run stop hooks in expressions. Be sure to reset this if you
+ // return anywhere within this function.
bool old_suppress_value = m_suppress_stop_hooks;
m_suppress_stop_hooks = true;
@@ -2300,8 +2290,8 @@ ExpressionResults Target::EvaluateExpression(
CalculateExecutionContext(exe_ctx);
}
- // Make sure we aren't just trying to see the value of a persistent
- // variable (something like "$0")
+ // Make sure we aren't just trying to see the value of a persistent variable
+ // (something like "$0")
lldb::ExpressionVariableSP persistent_var_sp;
// Only check for persistent variables the expression starts with a '$'
if (expr[0] == '$')
@@ -2368,16 +2358,16 @@ lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
switch (addr_class) {
- case eAddressClassData:
- case eAddressClassDebug:
+ case AddressClass::eData:
+ case AddressClass::eDebug:
return LLDB_INVALID_ADDRESS;
- case eAddressClassUnknown:
- case eAddressClassInvalid:
- case eAddressClassCode:
- case eAddressClassCodeAlternateISA:
- case eAddressClassRuntime:
- if ((code_addr & 2ull) || (addr_class == eAddressClassCodeAlternateISA))
+ case AddressClass::eUnknown:
+ case AddressClass::eInvalid:
+ case AddressClass::eCode:
+ case AddressClass::eCodeAlternateISA:
+ case AddressClass::eRuntime:
+ if ((code_addr & 2ull) || (addr_class == AddressClass::eCodeAlternateISA))
code_addr |= 1ull;
break;
}
@@ -2386,25 +2376,24 @@ lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class) {
- case eAddressClassData:
- case eAddressClassDebug:
+ case AddressClass::eData:
+ case AddressClass::eDebug:
return LLDB_INVALID_ADDRESS;
- case eAddressClassUnknown:
- case eAddressClassInvalid:
- case eAddressClassCode:
- case eAddressClassCodeAlternateISA:
- case eAddressClassRuntime:
+ case AddressClass::eUnknown:
+ case AddressClass::eInvalid:
+ case AddressClass::eCode:
+ case AddressClass::eCodeAlternateISA:
+ case AddressClass::eRuntime:
// Check if bit zero it no set?
if ((code_addr & 1ull) == 0) {
// Bit zero isn't set, check if the address is a multiple of 2?
if (code_addr & 2ull) {
// The address is a multiple of 2 so it must be thumb, set bit zero
code_addr |= 1ull;
- } else if (addr_class == eAddressClassCodeAlternateISA) {
+ } else if (addr_class == AddressClass::eCodeAlternateISA) {
// We checked the address and the address claims to be the alternate
- // ISA
- // which means thumb, so set bit zero.
+ // ISA which means thumb, so set bit zero.
code_addr |= 1ull;
}
}
@@ -2429,15 +2418,15 @@ lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr,
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class) {
- case eAddressClassData:
- case eAddressClassDebug:
+ case AddressClass::eData:
+ case AddressClass::eDebug:
return LLDB_INVALID_ADDRESS;
- case eAddressClassInvalid:
- case eAddressClassUnknown:
- case eAddressClassCode:
- case eAddressClassCodeAlternateISA:
- case eAddressClassRuntime:
+ case AddressClass::eInvalid:
+ case AddressClass::eUnknown:
+ case AddressClass::eCode:
+ case AddressClass::eCodeAlternateISA:
+ case AddressClass::eRuntime:
opcode_addr &= ~(1ull);
break;
}
@@ -2470,8 +2459,8 @@ lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) {
SectionLoadList &section_load_list = GetSectionLoadList();
if (section_load_list.IsEmpty())
- // No sections are loaded, so we must assume we are not running yet
- // and need to operate only on file address.
+ // No sections are loaded, so we must assume we are not running yet and
+ // need to operate only on file address.
m_images.ResolveFileAddress(addr, resolved_addr);
else
section_load_list.ResolveLoadAddress(addr, resolved_addr);
@@ -2546,30 +2535,29 @@ lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) {
} else if (i == 2) {
// Here we may get one 4-byte instruction or two 2-byte instructions.
if (num_insns == 2) {
- // Looks like there are two 2-byte instructions above our breakpoint
- // target address.
- // Now the upper 2-byte instruction is either a valid 2-byte
- // instruction or could be a part of it's upper 4-byte instruction.
- // In both cases we don't care because in this case lower 2-byte
- // instruction is definitely a valid instruction
- // and whatever i=1 iteration has found out is true.
+ // Looks like there are two 2-byte instructions above our
+ // breakpoint target address. Now the upper 2-byte instruction is
+ // either a valid 2-byte instruction or could be a part of it's
+ // upper 4-byte instruction. In both cases we don't care because in
+ // this case lower 2-byte instruction is definitely a valid
+ // instruction and whatever i=1 iteration has found out is true.
inst_to_choose = 1;
break;
} else if (insn_size == 4) {
// This instruction claims its a valid 4-byte instruction. But it
- // could be a part of it's upper 4-byte instruction.
- // Lets try scanning upper 2 bytes to verify this.
+ // could be a part of it's upper 4-byte instruction. Lets try
+ // scanning upper 2 bytes to verify this.
instruction_list.Append(prev_insn);
inst_to_choose = 2;
}
} else if (i == 3) {
if (insn_size == 4)
// FIXME: We reached here that means instruction at [target - 4] has
- // already claimed to be a 4-byte instruction,
- // and now instruction at [target - 6] is also claiming that it's a
- // 4-byte instruction. This can not be true.
- // In this case we can not decide the valid previous instruction so
- // we let lldb set the breakpoint at the address given by user.
+ // already claimed to be a 4-byte instruction, and now instruction
+ // at [target - 6] is also claiming that it's a 4-byte instruction.
+ // This can not be true. In this case we can not decide the valid
+ // previous instruction so we let lldb set the breakpoint at the
+ // address given by user.
inst_to_choose = 0;
else
// This is straight-forward
@@ -2685,8 +2673,8 @@ void Target::RunStopHooks() {
return;
// <rdar://problem/12027563> make sure we check that we are not stopped
- // because of us running a user expression
- // since in that case we do not want to run the stop-hooks
+ // because of us running a user expression since in that case we do not want
+ // to run the stop-hooks
if (m_process_sp->GetModIDRef().IsLastResumeForUserExpression())
return;
@@ -2975,18 +2963,16 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
launch_info.GetFlags().Set(eLaunchFlagDebug);
// Get the value of synchronous execution here. If you wait till after you
- // have started to
- // run, then you could have hit a breakpoint, whose command might switch the
- // value, and
- // then you'll pick up that incorrect value.
+ // have started to run, then you could have hit a breakpoint, whose command
+ // might switch the value, and then you'll pick up that incorrect value.
Debugger &debugger = GetDebugger();
const bool synchronous_execution =
debugger.GetCommandInterpreter().GetSynchronous();
PlatformSP platform_sp(GetPlatform());
- // Finalize the file actions, and if none were given, default to opening
- // up a pseudo terminal
+ // Finalize the file actions, and if none were given, default to opening up a
+ // pseudo terminal
const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false;
if (log)
log->Printf("Target::%s have platform=%s, platform_sp->IsHost()=%s, "
@@ -3025,10 +3011,10 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
GetPlatform()->DebugProcess(launch_info, debugger, this, error);
// Cleanup the old process since someone might still have a strong
- // reference to this process and we would like to allow it to cleanup
- // as much as it can without the object being destroyed. We try to
- // lock the shared pointer and if that works, then someone else still
- // has a strong reference to the process.
+ // reference to this process and we would like to allow it to cleanup as
+ // much as it can without the object being destroyed. We try to lock the
+ // shared pointer and if that works, then someone else still has a strong
+ // reference to the process.
ProcessSP old_process_sp(process_wp.lock());
if (old_process_sp)
@@ -3152,8 +3138,8 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
const ModuleSP old_exec_module_sp = GetExecutableModule();
- // If no process info was specified, then use the target executable
- // name as the process to attach to by default
+ // If no process info was specified, then use the target executable name as
+ // the process to attach to by default
if (!attach_info.ProcessInfoSpecified()) {
if (old_exec_module_sp)
attach_info.GetExecutableFile().GetFilename() =
@@ -3580,9 +3566,8 @@ public:
bool will_modify,
uint32_t idx) const override {
// When getting the value for a key from the target options, we will always
- // try and grab the setting from the current target if there is one. Else we
- // just
- // use the one from this instance.
+ // try and grab the setting from the current target if there is one. Else
+ // we just use the one from this instance.
if (idx == ePropertyEnvVars)
GetHostEnvironmentIfNeeded();
@@ -3611,36 +3596,19 @@ protected:
nullptr, idx, g_properties[idx].default_uint_value != 0)) {
PlatformSP platform_sp(m_target->GetPlatform());
if (platform_sp) {
- StringList env;
- if (platform_sp->GetEnvironment(env)) {
- OptionValueDictionary *env_dict =
- GetPropertyAtIndexAsOptionValueDictionary(nullptr,
- ePropertyEnvVars);
- if (env_dict) {
- const bool can_replace = false;
- const size_t envc = env.GetSize();
- for (size_t idx = 0; idx < envc; idx++) {
- const char *env_entry = env.GetStringAtIndex(idx);
- if (env_entry) {
- const char *equal_pos = ::strchr(env_entry, '=');
- ConstString key;
- // It is ok to have environment variables with no values
- const char *value = nullptr;
- if (equal_pos) {
- key.SetCStringWithLength(env_entry,
- equal_pos - env_entry);
- if (equal_pos[1])
- value = equal_pos + 1;
- } else {
- key.SetCString(env_entry);
- }
- // Don't allow existing keys to be replaced with ones we get
- // from the platform environment
- env_dict->SetValueForKey(
- key, OptionValueSP(new OptionValueString(value)),
- can_replace);
- }
- }
+ Environment env = platform_sp->GetEnvironment();
+ OptionValueDictionary *env_dict =
+ GetPropertyAtIndexAsOptionValueDictionary(nullptr,
+ ePropertyEnvVars);
+ if (env_dict) {
+ const bool can_replace = false;
+ for (const auto &KV : env) {
+ // Don't allow existing keys to be replaced with ones we get
+ // from the platform environment
+ env_dict->SetValueForKey(
+ ConstString(KV.first()),
+ OptionValueSP(new OptionValueString(KV.second.c_str())),
+ can_replace);
}
}
}
@@ -3690,8 +3658,8 @@ TargetProperties::TargetProperties(Target *target)
m_collection_sp.reset(
new TargetOptionValueProperties(target, Target::GetGlobalProperties()));
- // Set callbacks to update launch_info whenever "settins set" updated any of
- // these properties
+ // Set callbacks to update launch_info whenever "settins set" updated any
+ // of these properties
m_collection_sp->SetValueChangedCallback(
ePropertyArg0, TargetProperties::Arg0ValueChangedCallback, this);
m_collection_sp->SetValueChangedCallback(
@@ -3906,15 +3874,19 @@ void TargetProperties::SetRunArguments(const Args &args) {
m_launch_info.GetArguments() = args;
}
-size_t TargetProperties::GetEnvironmentAsArgs(Args &env) const {
+Environment TargetProperties::GetEnvironment() const {
+ // TODO: Get rid of the Args intermediate step
+ Args env;
const uint32_t idx = ePropertyEnvVars;
- return m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, env);
+ m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, env);
+ return Environment(env);
}
-void TargetProperties::SetEnvironmentFromArgs(const Args &env) {
+void TargetProperties::SetEnvironment(Environment env) {
+ // TODO: Get rid of the Args intermediate step
const uint32_t idx = ePropertyEnvVars;
- m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, env);
- m_launch_info.GetEnvironmentEntries() = env;
+ m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, Args(env));
+ m_launch_info.GetEnvironment() = std::move(env);
}
bool TargetProperties::GetSkipPrologue() const {
@@ -4152,7 +4124,7 @@ void TargetProperties::SetProcessLaunchInfo(
m_launch_info = launch_info;
SetArg0(launch_info.GetArg0());
SetRunArguments(launch_info.GetArguments());
- SetEnvironmentFromArgs(launch_info.GetEnvironmentEntries());
+ SetEnvironment(launch_info.GetEnvironment());
const FileAction *input_file_action =
launch_info.GetFileActionForFD(STDIN_FILENO);
if (input_file_action) {
@@ -4193,9 +4165,7 @@ void TargetProperties::EnvVarsValueChangedCallback(void *target_property_ptr,
OptionValue *) {
TargetProperties *this_ =
reinterpret_cast<TargetProperties *>(target_property_ptr);
- Args args;
- if (this_->GetEnvironmentAsArgs(args))
- this_->m_launch_info.GetEnvironmentEntries() = args;
+ this_->m_launch_info.GetEnvironment() = this_->GetEnvironment();
}
void TargetProperties::InputPathValueChangedCallback(void *target_property_ptr,
diff --git a/contrib/llvm/tools/lldb/source/Target/TargetList.cpp b/contrib/llvm/tools/lldb/source/Target/TargetList.cpp
index 5c652aced39f..b9c852b414e2 100644
--- a/contrib/llvm/tools/lldb/source/Target/TargetList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/TargetList.cpp
@@ -84,9 +84,9 @@ Status TargetList::CreateTargetInternal(
Status error;
PlatformSP platform_sp;
- // This is purposely left empty unless it is specified by triple_cstr.
- // If not initialized via triple_cstr, then the currently selected platform
- // will set the architecture correctly.
+ // This is purposely left empty unless it is specified by triple_cstr. If not
+ // initialized via triple_cstr, then the currently selected platform will set
+ // the architecture correctly.
const ArchSpec arch(triple_str);
if (!triple_str.empty()) {
if (!arch.IsValid()) {
@@ -102,7 +102,7 @@ Status TargetList::CreateTargetInternal(
CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
- // let's see if there is already an existing plaform before we go creating
+ // let's see if there is already an existing platform before we go creating
// another...
platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
@@ -120,11 +120,11 @@ Status TargetList::CreateTargetInternal(
if (!user_exe_path.empty()) {
ModuleSpecList module_specs;
ModuleSpec module_spec;
- module_spec.GetFileSpec().SetFile(user_exe_path, true);
+ module_spec.GetFileSpec().SetFile(user_exe_path, true,
+ FileSpec::Style::native);
// Resolve the executable in case we are given a path to a application
- // bundle
- // like a .app bundle on MacOSX
+ // bundle like a .app bundle on MacOSX
Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
lldb::offset_t file_offset = 0;
@@ -140,7 +140,8 @@ Status TargetList::CreateTargetInternal(
if (platform_arch.IsCompatibleMatch(
matching_module_spec.GetArchitecture())) {
// If the OS or vendor weren't specified, then adopt the module's
- // architecture so that the platform matching can be more accurate
+ // architecture so that the platform matching can be more
+ // accurate
if (!platform_arch.TripleOSWasSpecified() ||
!platform_arch.TripleVendorWasSpecified()) {
prefer_platform_arch = true;
@@ -194,7 +195,8 @@ Status TargetList::CreateTargetInternal(
}
}
- // Next check the host platform it if wasn't already checked above
+ // Next check the host platform it if wasn't already checked
+ // above
if (host_platform_sp &&
(!platform_sp ||
host_platform_sp->GetName() != platform_sp->GetName())) {
@@ -231,7 +233,7 @@ Status TargetList::CreateTargetInternal(
}
if (platform_ptr) {
- // All platforms for all modules in the exectuable match, so we can
+ // All platforms for all modules in the executable match, so we can
// select this platform
platform_sp = platforms.front();
} else if (more_than_one_platforms == false) {
@@ -275,8 +277,7 @@ Status TargetList::CreateTargetInternal(
}
} else if (platform_arch.IsValid()) {
// if "arch" isn't valid, yet "platform_arch" is, it means we have an
- // executable file with
- // a single architecture which should be used
+ // executable file with a single architecture which should be used
ArchSpec fixed_platform_arch;
if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
&fixed_platform_arch)) {
@@ -367,16 +368,12 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
user_exe_path_is_bundle = true;
if (file.IsRelative() && !user_exe_path.empty()) {
- // Ignore paths that start with "./" and "../"
- if (!user_exe_path.startswith("./") && !user_exe_path.startswith("../")) {
- llvm::SmallString<64> cwd;
- if (! llvm::sys::fs::current_path(cwd)) {
- cwd += '/';
- cwd += user_exe_path;
- FileSpec cwd_file(cwd, false);
- if (cwd_file.Exists())
- file = cwd_file;
- }
+ llvm::SmallString<64> cwd;
+ if (! llvm::sys::fs::current_path(cwd)) {
+ FileSpec cwd_file(cwd.c_str(), false);
+ cwd_file.AppendPathComponent(file);
+ if (cwd_file.Exists())
+ file = cwd_file;
}
}
@@ -410,8 +407,8 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
sizeof(resolved_bundle_exe_path));
}
} else {
- // No file was specified, just create an empty target with any arch
- // if a valid arch was specified
+ // No file was specified, just create an empty target with any arch if a
+ // valid arch was specified
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
}
diff --git a/contrib/llvm/tools/lldb/source/Target/Thread.cpp b/contrib/llvm/tools/lldb/source/Target/Thread.cpp
index 217cbccedf6e..5ac1de7ae01b 100644
--- a/contrib/llvm/tools/lldb/source/Target/Thread.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Thread.cpp
@@ -105,9 +105,8 @@ public:
bool will_modify,
uint32_t idx) const override {
// When getting the value for a key from the thread options, we will always
- // try and grab the setting from the current thread if there is one. Else we
- // just
- // use the one from this instance.
+ // try and grab the setting from the current thread if there is one. Else
+ // we just use the one from this instance.
if (exe_ctx) {
Thread *thread = exe_ctx->GetThreadPtr();
if (thread) {
@@ -275,8 +274,8 @@ Thread::~Thread() {
void Thread::DestroyThread() {
// Tell any plans on the plan stacks that the thread is being destroyed since
- // any plans that have a thread go away in the middle of might need
- // to do cleanup, or in some cases NOT do cleanup...
+ // any plans that have a thread go away in the middle of might need to do
+ // cleanup, or in some cases NOT do cleanup...
for (auto plan : m_plan_stack)
plan->ThreadDestroyed();
@@ -291,11 +290,10 @@ void Thread::DestroyThread() {
m_discarded_plan_stack.clear();
m_completed_plan_stack.clear();
- // Push a ThreadPlanNull on the plan stack. That way we can continue assuming
- // that the
- // plan stack is never empty, but if somebody errantly asks questions of a
- // destroyed thread
- // without checking first whether it is destroyed, they won't crash.
+ // Push a ThreadPlanNull on the plan stack. That way we can continue
+ // assuming that the plan stack is never empty, but if somebody errantly asks
+ // questions of a destroyed thread without checking first whether it is
+ // destroyed, they won't crash.
ThreadPlanSP null_plan_sp(new ThreadPlanNull(*this));
m_plan_stack.push_back(null_plan_sp);
@@ -385,11 +383,10 @@ lldb::StopInfoSP Thread::GetStopInfo() {
ProcessSP process_sp(GetProcess());
const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;
- // Here we select the stop info according to priorirty:
- // - m_stop_info_sp (if not trace) - preset value
- // - completed plan stop info - new value with plan from completed plan stack
- // - m_stop_info_sp (trace stop reason is OK now)
- // - ask GetPrivateStopInfo to set stop info
+ // Here we select the stop info according to priorirty: - m_stop_info_sp (if
+ // not trace) - preset value - completed plan stop info - new value with plan
+ // from completed plan stack - m_stop_info_sp (trace stop reason is OK now) -
+ // ask GetPrivateStopInfo to set stop info
bool have_valid_stop_info = m_stop_info_sp &&
m_stop_info_sp ->IsValid() &&
@@ -432,17 +429,17 @@ lldb::StopInfoSP Thread::GetPrivateStopInfo() {
}
}
- // The stop info can be manually set by calling Thread::SetStopInfo()
- // prior to this function ever getting called, so we can't rely on
- // "m_stop_info_stop_id != process_stop_id" as the condition for
- // the if statement below, we must also check the stop info to see
- // if we need to override it. See the header documentation in
- // Process::GetStopInfoOverrideCallback() for more information on
- // the stop info override callback.
+ // The stop info can be manually set by calling Thread::SetStopInfo() prior
+ // to this function ever getting called, so we can't rely on
+ // "m_stop_info_stop_id != process_stop_id" as the condition for the if
+ // statement below, we must also check the stop info to see if we need to
+ // override it. See the header documentation in
+ // Process::GetStopInfoOverrideCallback() for more information on the stop
+ // info override callback.
if (m_stop_info_override_stop_id != process_stop_id) {
m_stop_info_override_stop_id = process_stop_id;
if (m_stop_info_sp) {
- if (Architecture *arch =
+ if (const Architecture *arch =
process_sp->GetTarget().GetArchitecturePlugin())
arch->OverrideStopInfo(*this);
}
@@ -509,9 +506,8 @@ void Thread::SetShouldReportStop(Vote vote) {
void Thread::SetStopInfoToNothing() {
// Note, we can't just NULL out the private reason, or the native thread
- // implementation will try to
- // go calculate it again. For now, just set it to a Unix Signal with an
- // invalid signal number.
+ // implementation will try to go calculate it again. For now, just set it to
+ // a Unix Signal with an invalid signal number.
SetStopInfo(
StopInfo::CreateStopReasonWithSignal(*this, LLDB_INVALID_SIGNAL_NUMBER));
}
@@ -604,10 +600,8 @@ void Thread::WillStop() {
void Thread::SetupForResume() {
if (GetResumeState() != eStateSuspended) {
// If we're at a breakpoint push the step-over breakpoint plan. Do this
- // before
- // telling the current plan it will resume, since we might change what the
- // current
- // plan is.
+ // before telling the current plan it will resume, since we might change
+ // what the current plan is.
lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
if (reg_ctx_sp) {
@@ -615,9 +609,8 @@ void Thread::SetupForResume() {
BreakpointSiteSP bp_site_sp =
GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc);
if (bp_site_sp) {
- // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target
- // may not require anything
- // special to step over a breakpoint.
+ // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the
+ // target may not require anything special to step over a breakpoint.
ThreadPlan *cur_plan = GetCurrentPlan();
@@ -669,11 +662,9 @@ bool Thread::ShouldResume(StateType resume_state) {
GetPrivateStopInfo();
// This is a little dubious, but we are trying to limit how often we actually
- // fetch stop info from
- // the target, 'cause that slows down single stepping. So assume that if we
- // got to the point where
- // we're about to resume, and we haven't yet had to fetch the stop reason,
- // then it doesn't need to know
+ // fetch stop info from the target, 'cause that slows down single stepping.
+ // So assume that if we got to the point where we're about to resume, and we
+ // haven't yet had to fetch the stop reason, then it doesn't need to know
// about the fact that we are resuming...
const uint32_t process_stop_id = GetProcess()->GetStopID();
if (m_stop_info_stop_id == process_stop_id &&
@@ -684,9 +675,9 @@ bool Thread::ShouldResume(StateType resume_state) {
}
// Tell all the plans that we are about to resume in case they need to clear
- // any state.
- // We distinguish between the plan on the top of the stack and the lower
- // plans in case a plan needs to do any special business before it runs.
+ // any state. We distinguish between the plan on the top of the stack and the
+ // lower plans in case a plan needs to do any special business before it
+ // runs.
bool need_to_resume = false;
ThreadPlan *plan_ptr = GetCurrentPlan();
@@ -698,8 +689,7 @@ bool Thread::ShouldResume(StateType resume_state) {
}
// If the WillResume for the plan says we are faking a resume, then it will
- // have set an appropriate stop info.
- // In that case, don't reset it here.
+ // have set an appropriate stop info. In that case, don't reset it here.
if (need_to_resume && resume_state != eStateSuspended) {
m_stop_info_sp.reset();
@@ -743,9 +733,8 @@ bool Thread::ShouldStop(Event *event_ptr) {
}
// Based on the current thread plan and process stop info, check if this
- // thread caused the process to stop. NOTE: this must take place before
- // the plan is moved from the current plan stack to the completed plan
- // stack.
+ // thread caused the process to stop. NOTE: this must take place before the
+ // plan is moved from the current plan stack to the completed plan stack.
if (!ThreadStoppedForAReason()) {
if (log)
log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
@@ -775,10 +764,9 @@ bool Thread::ShouldStop(Event *event_ptr) {
current_plan->DoTraceLog();
// First query the stop info's ShouldStopSynchronous. This handles
- // "synchronous" stop reasons, for example the breakpoint
- // command on internal breakpoints. If a synchronous stop reason says we
- // should not stop, then we don't have to
- // do any more work on this stop.
+ // "synchronous" stop reasons, for example the breakpoint command on internal
+ // breakpoints. If a synchronous stop reason says we should not stop, then
+ // we don't have to do any more work on this stop.
StopInfoSP private_stop_info(GetPrivateStopInfo());
if (private_stop_info &&
!private_stop_info->ShouldStopSynchronous(event_ptr)) {
@@ -788,8 +776,8 @@ bool Thread::ShouldStop(Event *event_ptr) {
return false;
}
- // If we've already been restarted, don't query the plans since the state they
- // would examine is not current.
+ // If we've already been restarted, don't query the plans since the state
+ // they would examine is not current.
if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr))
return false;
@@ -798,12 +786,10 @@ bool Thread::ShouldStop(Event *event_ptr) {
GetStackFrameList()->CalculateCurrentInlinedDepth();
// If the base plan doesn't understand why we stopped, then we have to find a
- // plan that does.
- // If that plan is still working, then we don't need to do any more work. If
- // the plan that explains
- // the stop is done, then we should pop all the plans below it, and pop it,
- // and then let the plans above it decide
- // whether they still need to do more work.
+ // plan that does. If that plan is still working, then we don't need to do
+ // any more work. If the plan that explains the stop is done, then we should
+ // pop all the plans below it, and pop it, and then let the plans above it
+ // decide whether they still need to do more work.
bool done_processing_current_plan = false;
@@ -812,16 +798,16 @@ bool Thread::ShouldStop(Event *event_ptr) {
done_processing_current_plan = true;
should_stop = false;
} else {
- // If the current plan doesn't explain the stop, then find one that
- // does and let it handle the situation.
+ // If the current plan doesn't explain the stop, then find one that does
+ // and let it handle the situation.
ThreadPlan *plan_ptr = current_plan;
while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
if (plan_ptr->PlanExplainsStop(event_ptr)) {
should_stop = plan_ptr->ShouldStop(event_ptr);
- // plan_ptr explains the stop, next check whether plan_ptr is done, if
- // so, then we should take it
- // and all the plans below it off the stack.
+ // plan_ptr explains the stop, next check whether plan_ptr is done,
+ // if so, then we should take it and all the plans below it off the
+ // stack.
if (plan_ptr->MischiefManaged()) {
// We're going to pop the plans up to and including the plan that
@@ -833,9 +819,9 @@ bool Thread::ShouldStop(Event *event_ptr) {
current_plan->WillStop();
PopPlan();
} while ((current_plan = GetCurrentPlan()) != prev_plan_ptr);
- // Now, if the responsible plan was not "Okay to discard" then we're
- // done,
- // otherwise we forward this to the next plan in the stack below.
+ // Now, if the responsible plan was not "Okay to discard" then
+ // we're done, otherwise we forward this to the next plan in the
+ // stack below.
done_processing_current_plan =
(plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard());
} else
@@ -860,9 +846,9 @@ bool Thread::ShouldStop(Event *event_ptr) {
if (log)
log->Printf("Base plan says should stop: %i.", should_stop);
} else {
- // Otherwise, don't let the base plan override what the other plans say to
- // do, since
- // presumably if there were other plans they would know what to do...
+ // Otherwise, don't let the base plan override what the other plans say
+ // to do, since presumably if there were other plans they would know what
+ // to do...
while (1) {
if (PlanIsBasePlan(current_plan))
break;
@@ -875,9 +861,8 @@ bool Thread::ShouldStop(Event *event_ptr) {
if (should_stop)
current_plan->WillStop();
- // If a Master Plan wants to stop, and wants to stick on the stack, we
- // let it.
- // Otherwise, see if the plan's parent wants to stop.
+ // If a Master Plan wants to stop, and wants to stick on the stack,
+ // we let it. Otherwise, see if the plan's parent wants to stop.
if (should_stop && current_plan->IsMasterPlan() &&
!current_plan->OkayToDiscard()) {
@@ -902,18 +887,16 @@ bool Thread::ShouldStop(Event *event_ptr) {
}
// One other potential problem is that we set up a master plan, then stop in
- // before it is complete - for instance
- // by hitting a breakpoint during a step-over - then do some step/finish/etc
- // operations that wind up
- // past the end point condition of the initial plan. We don't want to strand
- // the original plan on the stack,
- // This code clears stale plans off the stack.
+ // before it is complete - for instance by hitting a breakpoint during a
+ // step-over - then do some step/finish/etc operations that wind up past the
+ // end point condition of the initial plan. We don't want to strand the
+ // original plan on the stack, This code clears stale plans off the stack.
if (should_stop) {
ThreadPlan *plan_ptr = GetCurrentPlan();
- // Discard the stale plans and all plans below them in the stack,
- // plus move the completed plans to the completed plan stack
+ // Discard the stale plans and all plans below them in the stack, plus move
+ // the completed plans to the completed plan stack
while (!PlanIsBasePlan(plan_ptr)) {
bool stale = plan_ptr->IsPlanStale();
ThreadPlan *examined_plan = plan_ptr;
@@ -928,8 +911,9 @@ bool Thread::ShouldStop(Event *event_ptr) {
DiscardPlan();
}
if (examined_plan->IsPlanComplete()) {
- // plan is complete but does not explain the stop (example: step to a line
- // with breakpoint), let us move the plan to completed_plan_stack anyway
+ // plan is complete but does not explain the stop (example: step to a
+ // line with breakpoint), let us move the plan to
+ // completed_plan_stack anyway
PopPlan();
} else
DiscardPlan();
@@ -1097,8 +1081,8 @@ void Thread::DiscardPlan() {
}
ThreadPlan *Thread::GetCurrentPlan() {
- // There will always be at least the base plan. If somebody is mucking with a
- // thread with an empty plan stack, we should assert right away.
+ // There will always be at least the base plan. If somebody is mucking with
+ // a thread with an empty plan stack, we should assert right away.
return m_plan_stack.empty() ? nullptr : m_plan_stack.back().get();
}
@@ -1212,8 +1196,7 @@ void Thread::SetTracer(lldb::ThreadPlanTracerSP &tracer_sp) {
bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t thread_index) {
// Count the user thread plans from the back end to get the number of the one
- // we want
- // to discard:
+ // we want to discard:
uint32_t idx = 0;
ThreadPlan *up_to_plan_ptr = nullptr;
@@ -1249,8 +1232,7 @@ void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
int stack_size = m_plan_stack.size();
// If the input plan is nullptr, discard all plans. Otherwise make sure this
- // plan is in the
- // stack, and if so discard up to and including it.
+ // plan is in the stack, and if so discard up to and including it.
if (up_to_plan_ptr == nullptr) {
for (int i = stack_size - 1; i > 0; i--)
@@ -1314,8 +1296,7 @@ void Thread::DiscardThreadPlans(bool force) {
// Now discard the master plan itself.
// The bottom-most plan never gets discarded. "OkayToDiscard" for it
- // means
- // discard it's dependent plans, but not it...
+ // means discard it's dependent plans, but not it...
if (master_plan_idx > 0) {
DiscardPlan();
}
@@ -1340,8 +1321,7 @@ Status Thread::UnwindInnermostExpression() {
int stack_size = m_plan_stack.size();
// If the input plan is nullptr, discard all plans. Otherwise make sure this
- // plan is in the
- // stack, and if so discard up to and including it.
+ // plan is in the stack, and if so discard up to and including it.
for (int i = stack_size - 1; i > 0; i--) {
if (m_plan_stack[i]->GetKind() == ThreadPlan::eKindCallFunction) {
@@ -1380,7 +1360,8 @@ ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
return thread_plan_sp;
}
-// Call the QueueThreadPlanForStepOverRange method which takes an address range.
+// Call the QueueThreadPlanForStepOverRange method which takes an address
+// range.
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
@@ -1500,11 +1481,9 @@ lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name));
QueueThreadPlan(thread_plan_sp, abort_other_plans);
// This seems a little funny, but I don't want to have to split up the
- // constructor and the
- // DidPush in the scripted plan, that seems annoying.
- // That means the constructor has to be in DidPush.
- // So I have to validate the plan AFTER pushing it, and then take it off
- // again...
+ // constructor and the DidPush in the scripted plan, that seems annoying.
+ // That means the constructor has to be in DidPush. So I have to validate the
+ // plan AFTER pushing it, and then take it off again...
if (!thread_plan_sp->ValidatePlan(nullptr)) {
DiscardThreadPlansUpToPlan(thread_plan_sp);
return ThreadPlanSP();
@@ -1701,10 +1680,9 @@ Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
return return_error;
}
- // Now write the return registers for the chosen frame:
- // Note, we can't use ReadAllRegisterValues->WriteAllRegisterValues, since the
- // read & write
- // cook their data
+ // Now write the return registers for the chosen frame: Note, we can't use
+ // ReadAllRegisterValues->WriteAllRegisterValues, since the read & write cook
+ // their data
StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(0);
if (youngest_frame_sp) {
@@ -1754,13 +1732,11 @@ Status Thread::JumpToLine(const FileSpec &file, uint32_t line,
target->GetImages().FindAddressesForLine(target_sp, file, line, sc.function,
within_function, outside_function);
- // If possible, we try and stay within the current function.
- // Within a function, we accept multiple locations (optimized code may do
- // this,
- // there's no solution here so we do the best we can).
- // However if we're trying to leave the function, we don't know how to pick
- // the
- // right location, so if there's more than one then we bail.
+ // If possible, we try and stay within the current function. Within a
+ // function, we accept multiple locations (optimized code may do this,
+ // there's no solution here so we do the best we can). However if we're
+ // trying to leave the function, we don't know how to pick the right
+ // location, so if there's more than one then we bail.
if (!within_function.empty())
candidates = within_function;
else if (outside_function.size() == 1 && can_leave_function)
@@ -1836,8 +1812,8 @@ lldb::addr_t Thread::GetThreadPointer() { return LLDB_INVALID_ADDRESS; }
addr_t Thread::GetThreadLocalData(const ModuleSP module,
lldb::addr_t tls_file_addr) {
- // The default implementation is to ask the dynamic loader for it.
- // This can be overridden for specific platforms.
+ // The default implementation is to ask the dynamic loader for it. This can
+ // be overridden for specific platforms.
DynamicLoader *loader = GetProcess()->GetDynamicLoader();
if (loader)
return loader->GetThreadLocalData(module, shared_from_this(),
@@ -2096,10 +2072,8 @@ void Thread::Flush() {
bool Thread::IsStillAtLastBreakpointHit() {
// If we are currently stopped at a breakpoint, always return that stopinfo
- // and don't reset it.
- // This allows threads to maintain their breakpoint stopinfo, such as when
- // thread-stepping in
- // multithreaded programs.
+ // and don't reset it. This allows threads to maintain their breakpoint
+ // stopinfo, such as when thread-stepping in multithreaded programs.
if (m_stop_info_sp) {
StopReason stop_reason = m_stop_info_sp->GetStopReason();
if (stop_reason == lldb::eStopReasonBreakpoint) {
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
index 4cf8f9061a89..ee57a401f742 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
@@ -40,8 +40,8 @@ ThreadList::ThreadList(const ThreadList &rhs)
const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
if (this != &rhs) {
- // Lock both mutexes to make sure neither side changes anyone on us
- // while the assignment occurs
+ // Lock both mutexes to make sure neither side changes anyone on us while
+ // the assignment occurs
std::lock_guard<std::recursive_mutex> guard(GetMutex());
std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex());
@@ -54,9 +54,8 @@ const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
}
ThreadList::~ThreadList() {
- // Clear the thread list. Clear will take the mutex lock
- // which will ensure that if anyone is using the list
- // they won't get it removed while using it.
+ // Clear the thread list. Clear will take the mutex lock which will ensure
+ // that if anyone is using the list they won't get it removed while using it.
Clear();
}
@@ -195,6 +194,20 @@ ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
return thread_sp;
}
+ThreadSP ThreadList::GetBackingThread(const ThreadSP &real_thread) {
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
+
+ ThreadSP thread_sp;
+ const uint32_t num_threads = m_threads.size();
+ for (uint32_t idx = 0; idx < num_threads; ++idx) {
+ if (m_threads[idx]->GetBackingThread() == real_thread) {
+ thread_sp = m_threads[idx];
+ break;
+ }
+ }
+ return thread_sp;
+}
+
ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) {
std::lock_guard<std::recursive_mutex> guard(GetMutex());
@@ -217,13 +230,13 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- // The ShouldStop method of the threads can do a whole lot of work,
- // figuring out whether the thread plan conditions are met. So we don't want
- // to keep the ThreadList locked the whole time we are doing this.
+ // The ShouldStop method of the threads can do a whole lot of work, figuring
+ // out whether the thread plan conditions are met. So we don't want to keep
+ // the ThreadList locked the whole time we are doing this.
// FIXME: It is possible that running code could cause new threads
- // to be created. If that happens, we will miss asking them whether
- // they should stop. This is not a big deal since we haven't had
- // a chance to hang any interesting operations on those threads yet.
+ // to be created. If that happens, we will miss asking them whether they
+ // should stop. This is not a big deal since we haven't had a chance to hang
+ // any interesting operations on those threads yet.
collection threads_copy;
{
@@ -233,25 +246,21 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
m_process->UpdateThreadListIfNeeded();
for (lldb::ThreadSP thread_sp : m_threads) {
// This is an optimization... If we didn't let a thread run in between
- // the previous stop and this
- // one, we shouldn't have to consult it for ShouldStop. So just leave it
- // off the list we are going to
- // inspect.
- // On Linux, if a thread-specific conditional breakpoint was hit, it won't
- // necessarily be the thread
- // that hit the breakpoint itself that evaluates the conditional
- // expression, so the thread that hit
- // the breakpoint could still be asked to stop, even though it hasn't been
- // allowed to run since the
- // previous stop.
+ // the previous stop and this one, we shouldn't have to consult it for
+ // ShouldStop. So just leave it off the list we are going to inspect. On
+ // Linux, if a thread-specific conditional breakpoint was hit, it won't
+ // necessarily be the thread that hit the breakpoint itself that
+ // evaluates the conditional expression, so the thread that hit the
+ // breakpoint could still be asked to stop, even though it hasn't been
+ // allowed to run since the previous stop.
if (thread_sp->GetTemporaryResumeState() != eStateSuspended ||
thread_sp->IsStillAtLastBreakpointHit())
threads_copy.push_back(thread_sp);
}
// It is possible the threads we were allowing to run all exited and then
- // maybe the user interrupted
- // or something, then fall back on looking at all threads:
+ // maybe the user interrupted or something, then fall back on looking at
+ // all threads:
if (threads_copy.size() == 0)
threads_copy = m_threads;
@@ -282,12 +291,11 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
}
// Now we run through all the threads and get their stop info's. We want to
- // make sure to do this first before
- // we start running the ShouldStop, because one thread's ShouldStop could
- // destroy information (like deleting a
- // thread specific breakpoint another thread had stopped at) which could lead
- // us to compute the StopInfo incorrectly.
- // We don't need to use it here, we just want to make sure it gets computed.
+ // make sure to do this first before we start running the ShouldStop, because
+ // one thread's ShouldStop could destroy information (like deleting a thread
+ // specific breakpoint another thread had stopped at) which could lead us to
+ // compute the StopInfo incorrectly. We don't need to use it here, we just
+ // want to make sure it gets computed.
for (pos = threads_copy.begin(); pos != end; ++pos) {
ThreadSP thread_sp(*pos);
@@ -298,27 +306,24 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
ThreadSP thread_sp(*pos);
// We should never get a stop for which no thread had a stop reason, but
- // sometimes we do see this -
- // for instance when we first connect to a remote stub. In that case we
- // should stop, since we can't figure out
- // the right thing to do and stopping gives the user control over what to do
- // in this instance.
+ // sometimes we do see this - for instance when we first connect to a
+ // remote stub. In that case we should stop, since we can't figure out the
+ // right thing to do and stopping gives the user control over what to do in
+ // this instance.
//
// Note, this causes a problem when you have a thread specific breakpoint,
- // and a bunch of threads hit the breakpoint,
- // but not the thread which we are waiting for. All the threads that are
- // not "supposed" to hit the breakpoint
- // are marked as having no stop reason, which is right, they should not show
- // a stop reason. But that triggers this
- // code and causes us to stop seemingly for no reason.
+ // and a bunch of threads hit the breakpoint, but not the thread which we
+ // are waiting for. All the threads that are not "supposed" to hit the
+ // breakpoint are marked as having no stop reason, which is right, they
+ // should not show a stop reason. But that triggers this code and causes
+ // us to stop seemingly for no reason.
//
// Since the only way we ever saw this error was on first attach, I'm only
- // going to trigger set did_anybody_stop_for_a_reason
- // to true unless this is the first stop.
+ // going to trigger set did_anybody_stop_for_a_reason to true unless this
+ // is the first stop.
//
// If this becomes a problem, we'll have to have another StopReason like
- // "StopInfoHidden" which will look invalid
- // everywhere but at this check.
+ // "StopInfoHidden" which will look invalid everywhere but at this check.
if (thread_sp->GetProcess()->GetStopID() > 1)
did_anybody_stop_for_a_reason = true;
@@ -365,8 +370,8 @@ Vote ThreadList::ShouldReportStop(Event *event_ptr) {
log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__,
(uint64_t)m_threads.size());
- // Run through the threads and ask whether we should report this event.
- // For stopping, a YES vote wins over everything. A NO vote wins over NO
+ // Run through the threads and ask whether we should report this event. For
+ // stopping, a YES vote wins over everything. A NO vote wins over NO
// opinion.
for (pos = m_threads.begin(); pos != end; ++pos) {
ThreadSP thread_sp(*pos);
@@ -413,8 +418,8 @@ Vote ThreadList::ShouldReportRun(Event *event_ptr) {
m_process->UpdateThreadListIfNeeded();
collection::iterator pos, end = m_threads.end();
- // Run through the threads and ask whether we should report this event.
- // The rule is NO vote wins over everything, a YES vote wins over no opinion.
+ // Run through the threads and ask whether we should report this event. The
+ // rule is NO vote wins over everything, a YES vote wins over no opinion.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -471,8 +476,8 @@ void ThreadList::RefreshStateAfterStop() {
}
void ThreadList::DiscardThreadPlans() {
- // You don't need to update the thread list here, because only threads
- // that you currently know about have any thread plans.
+ // You don't need to update the thread list here, because only threads that
+ // you currently know about have any thread plans.
std::lock_guard<std::recursive_mutex> guard(GetMutex());
collection::iterator pos, end = m_threads.end();
@@ -481,9 +486,9 @@ void ThreadList::DiscardThreadPlans() {
}
bool ThreadList::WillResume() {
- // Run through the threads and perform their momentary actions.
- // But we only do this for threads that are running, user suspended
- // threads stay where they are.
+ // Run through the threads and perform their momentary actions. But we only
+ // do this for threads that are running, user suspended threads stay where
+ // they are.
std::lock_guard<std::recursive_mutex> guard(GetMutex());
m_process->UpdateThreadListIfNeeded();
@@ -491,14 +496,11 @@ bool ThreadList::WillResume() {
collection::iterator pos, end = m_threads.end();
// See if any thread wants to run stopping others. If it does, then we won't
- // setup the other threads for resume, since they aren't going to get a chance
- // to run. This is necessary because the SetupForResume might add
- // "StopOthers"
- // plans which would then get to be part of the who-gets-to-run negotiation,
- // but
- // they're coming in after the fact, and the threads that are already set up
- // should
- // take priority.
+ // setup the other threads for resume, since they aren't going to get a
+ // chance to run. This is necessary because the SetupForResume might add
+ // "StopOthers" plans which would then get to be part of the who-gets-to-run
+ // negotiation, but they're coming in after the fact, and the threads that
+ // are already set up should take priority.
bool wants_solo_run = false;
@@ -530,11 +532,9 @@ bool ThreadList::WillResume() {
}
// Give all the threads that are likely to run a last chance to set up their
- // state before we
- // negotiate who is actually going to get a chance to run...
+ // state before we negotiate who is actually going to get a chance to run...
// Don't set to resume suspended threads, and if any thread wanted to stop
- // others, only
- // call setup on the threads that request StopOthers...
+ // others, only call setup on the threads that request StopOthers...
for (pos = m_threads.begin(); pos != end; ++pos) {
if ((*pos)->GetResumeState() != eStateSuspended &&
@@ -636,13 +636,12 @@ void ThreadList::DidStop() {
std::lock_guard<std::recursive_mutex> guard(GetMutex());
collection::iterator pos, end = m_threads.end();
for (pos = m_threads.begin(); pos != end; ++pos) {
- // Notify threads that the process just stopped.
- // Note, this currently assumes that all threads in the list
- // stop when the process stops. In the future we will want to support
- // a debugging model where some threads continue to run while others
- // are stopped. We either need to handle that somehow here or
- // create a special thread list containing only threads which will
- // stop in the code that calls this method (currently
+ // Notify threads that the process just stopped. Note, this currently
+ // assumes that all threads in the list stop when the process stops. In
+ // the future we will want to support a debugging model where some threads
+ // continue to run while others are stopped. We either need to handle that
+ // somehow here or create a special thread list containing only threads
+ // which will stop in the code that calls this method (currently
// Process::SetPrivateState).
ThreadSP thread_sp(*pos);
if (StateIsRunningState(thread_sp->GetState()))
@@ -703,8 +702,8 @@ void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
void ThreadList::Update(ThreadList &rhs) {
if (this != &rhs) {
- // Lock both mutexes to make sure neither side changes anyone on us
- // while the assignment occurs
+ // Lock both mutexes to make sure neither side changes anyone on us while
+ // the assignment occurs
std::lock_guard<std::recursive_mutex> guard(GetMutex());
m_process = rhs.m_process;
@@ -712,13 +711,12 @@ void ThreadList::Update(ThreadList &rhs) {
m_threads.swap(rhs.m_threads);
m_selected_tid = rhs.m_selected_tid;
- // Now we look for threads that we are done with and
- // make sure to clear them up as much as possible so
- // anyone with a shared pointer will still have a reference,
- // but the thread won't be of much use. Using std::weak_ptr
- // for all backward references (such as a thread to a process)
- // will eventually solve this issue for us, but for now, we
- // need to work around the issue
+ // Now we look for threads that we are done with and make sure to clear
+ // them up as much as possible so anyone with a shared pointer will still
+ // have a reference, but the thread won't be of much use. Using
+ // std::weak_ptr for all backward references (such as a thread to a
+ // process) will eventually solve this issue for us, but for now, we need
+ // to work around the issue
collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) {
const lldb::tid_t tid = (*rhs_pos)->GetID();
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp
index 27c9e2aa9c00..31ee1e922494 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp
@@ -100,8 +100,8 @@ bool ThreadPlan::StopOthers() {
}
void ThreadPlan::SetStopOthers(bool new_value) {
- // SetStopOthers doesn't work up the hierarchy. You have to set the
- // explicit ThreadPlan you want to affect.
+ // SetStopOthers doesn't work up the hierarchy. You have to set the explicit
+ // ThreadPlan you want to affect.
}
bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanBase.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanBase.cpp
index d1c2f6dd1206..65b114584177 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanBase.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanBase.cpp
@@ -28,8 +28,8 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// ThreadPlanBase: This one always stops, and never has anything particular
-// to do.
+// ThreadPlanBase: This one always stops, and never has anything particular to
+// do.
// FIXME: The "signal handling" policies should probably go here.
//----------------------------------------------------------------------
@@ -59,8 +59,8 @@ void ThreadPlanBase::GetDescription(Stream *s, lldb::DescriptionLevel level) {
bool ThreadPlanBase::ValidatePlan(Stream *error) { return true; }
bool ThreadPlanBase::DoPlanExplainsStop(Event *event_ptr) {
- // The base plan should defer to its tracer, since by default it
- // always handles the stop.
+ // The base plan should defer to its tracer, since by default it always
+ // handles the stop.
if (TracerExplainsStop())
return false;
else
@@ -99,10 +99,9 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
case eStopReasonBreakpoint:
case eStopReasonWatchpoint:
if (stop_info_sp->ShouldStopSynchronous(event_ptr)) {
- // If we are going to stop for a breakpoint, then unship the other plans
- // at this point. Don't force the discard, however, so Master plans can
- // stay
- // in place if they want to.
+ // If we are going to stop for a breakpoint, then unship the other
+ // plans at this point. Don't force the discard, however, so Master
+ // plans can stay in place if they want to.
if (log)
log->Printf(
"Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64
@@ -112,9 +111,8 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
return true;
}
// If we aren't going to stop at this breakpoint, and it is internal,
- // don't report this stop or the subsequent running event.
- // Otherwise we will post the stopped & running, but the stopped event
- // will get marked
+ // don't report this stop or the subsequent running event. Otherwise we
+ // will post the stopped & running, but the stopped event will get marked
// with "restarted" so the UI will know to wait and expect the consequent
// "running".
if (stop_info_sp->ShouldNotify(event_ptr)) {
@@ -131,10 +129,9 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
break;
case eStopReasonException:
- // If we crashed, discard thread plans and stop. Don't force the discard,
- // however,
- // since on rerun the target may clean up this exception and continue
- // normally from there.
+ // If we crashed, discard thread plans and stop. Don't force the
+ // discard, however, since on rerun the target may clean up this
+ // exception and continue normally from there.
if (log)
log->Printf(
"Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64
@@ -144,10 +141,9 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
return true;
case eStopReasonExec:
- // If we crashed, discard thread plans and stop. Don't force the discard,
- // however,
- // since on rerun the target may clean up this exception and continue
- // normally from there.
+ // If we crashed, discard thread plans and stop. Don't force the
+ // discard, however, since on rerun the target may clean up this
+ // exception and continue normally from there.
if (log)
log->Printf(
"Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64
@@ -198,8 +194,7 @@ bool ThreadPlanBase::WillStop() { return true; }
bool ThreadPlanBase::DoWillResume(lldb::StateType resume_state,
bool current_plan) {
// Reset these to the default values so we don't set them wrong, then not get
- // asked
- // for a while, then return the wrong answer.
+ // asked for a while, then return the wrong answer.
m_run_vote = eVoteNoOpinion;
m_stop_vote = eVoteNo;
return true;
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp
index e3b9ae15dc95..18beda42fb64 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -15,6 +15,7 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
@@ -56,8 +57,7 @@ bool ThreadPlanCallFunction::ConstructorSetup(
m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
// If we can't read memory at the point of the process where we are planning
- // to put our function, we're
- // not going to get any further...
+ // to put our function, we're not going to get any further...
Status error;
process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
if (!error.Success()) {
@@ -187,7 +187,8 @@ void ThreadPlanCallFunction::ReportRegisterState(const char *message) {
reg_idx < num_registers; ++reg_idx) {
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
if (reg_ctx->ReadRegister(reg_info, reg_value)) {
- reg_value.Dump(&strm, reg_info, true, false, eFormatDefault);
+ DumpRegisterValue(reg_value, &strm, reg_info, true, false,
+ eFormatDefault);
strm.EOL();
}
}
@@ -278,9 +279,8 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
LIBLLDB_LOG_PROCESS));
m_real_stop_info_sp = GetPrivateStopInfo();
- // If our subplan knows why we stopped, even if it's done (which would forward
- // the question to us)
- // we answer yes.
+ // If our subplan knows why we stopped, even if it's done (which would
+ // forward the question to us) we answer yes.
if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr)) {
SetPlanComplete();
return true;
@@ -302,8 +302,8 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
return true;
// One more quirk here. If this event was from Halt interrupting the target,
- // then we should not consider
- // ourselves complete. Return true to acknowledge the stop.
+ // then we should not consider ourselves complete. Return true to
+ // acknowledge the stop.
if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
if (log)
log->Printf("ThreadPlanCallFunction::PlanExplainsStop: The event is an "
@@ -312,8 +312,8 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
}
// We control breakpoints separately from other "stop reasons." So first,
// check the case where we stopped for an internal breakpoint, in that case,
- // continue on.
- // If it is not an internal breakpoint, consult m_ignore_breakpoints.
+ // continue on. If it is not an internal breakpoint, consult
+ // m_ignore_breakpoints.
if (stop_reason == eStopReasonBreakpoint) {
ProcessSP process_sp(m_thread.CalculateProcess());
@@ -364,15 +364,13 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
// should be propagated up the stack.
return false;
} else {
- // If the subplan is running, any crashes are attributable to us.
- // If we want to discard the plan, then we say we explain the stop
- // but if we are going to be discarded, let whoever is above us
- // explain the stop.
- // But don't discard the plan if the stop would restart itself (for instance
- // if it is a
- // signal that is set not to stop. Check that here first. We just say we
- // explain the stop
- // but aren't done and everything will continue on from there.
+ // If the subplan is running, any crashes are attributable to us. If we
+ // want to discard the plan, then we say we explain the stop but if we are
+ // going to be discarded, let whoever is above us explain the stop. But
+ // don't discard the plan if the stop would restart itself (for instance if
+ // it is a signal that is set not to stop. Check that here first. We just
+ // say we explain the stop but aren't done and everything will continue on
+ // from there.
if (m_real_stop_info_sp &&
m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) {
@@ -385,8 +383,8 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
bool ThreadPlanCallFunction::ShouldStop(Event *event_ptr) {
// We do some computation in DoPlanExplainsStop that may or may not set the
- // plan as complete.
- // We need to do that here to make sure our state is correct.
+ // plan as complete. We need to do that here to make sure our state is
+ // correct.
DoPlanExplainsStop(event_ptr);
if (IsPlanComplete()) {
@@ -405,9 +403,8 @@ void ThreadPlanCallFunction::DidPush() {
//#define SINGLE_STEP_EXPRESSIONS
// Now set the thread state to "no reason" so we don't run with whatever
- // signal was outstanding...
- // Wait till the plan is pushed so we aren't changing the stop info till we're
- // about to run.
+ // signal was outstanding... Wait till the plan is pushed so we aren't
+ // changing the stop info till we're about to run.
GetThread().SetStopInfoToNothing();
@@ -483,10 +480,9 @@ bool ThreadPlanCallFunction::BreakpointsExplainStop() {
SetPlanComplete(false);
- // If the user has set the ObjC language breakpoint, it would normally get
- // priority over our internal
- // catcher breakpoint, but in this case we can't let that happen, so force
- // the ShouldStop here.
+ // If the user has set the ObjC language breakpoint, it would normally
+ // get priority over our internal catcher breakpoint, but in this case we
+ // can't let that happen, so force the ShouldStop here.
stop_info_sp->OverrideShouldStop(true);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp
index 0dae98f03ef5..e8ea73f3c6a0 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp
@@ -23,8 +23,8 @@ ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(
}
void ThreadPlanCallOnFunctionExit::DidPush() {
- // We now want to queue the "step out" thread plan so it executes
- // and completes.
+ // We now want to queue the "step out" thread plan so it executes and
+ // completes.
// Set stop vote to eVoteNo.
m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
@@ -59,9 +59,9 @@ bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) {
}
bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
- // If this is where we find out that an internal stop came in, then:
- // Check if the step-out plan completed. If it did, then we want to
- // run the callback here (our reason for living...)
+ // If this is where we find out that an internal stop came in, then: Check if
+ // the step-out plan completed. If it did, then we want to run the callback
+ // here (our reason for living...)
if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) {
m_callback();
@@ -71,8 +71,8 @@ bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
// Indicate that this plan is done and can be discarded.
SetPlanComplete();
- // We're done now, but we want to return false so that we
- // don't cause the thread to really stop.
+ // We're done now, but we want to return false so that we don't cause the
+ // thread to really stop.
}
return false;
@@ -80,21 +80,20 @@ bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
bool ThreadPlanCallOnFunctionExit::WillStop() {
// The code looks like the return value is ignored via ThreadList::
- // ShouldStop().
- // This is called when we really are going to stop. We don't care
- // and don't need to do anything here.
+ // ShouldStop(). This is called when we really are going to stop. We don't
+ // care and don't need to do anything here.
return false;
}
bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) {
- // We don't ever explain a stop. The only stop that is relevant
- // to us directly is the step_out plan we added to do the heavy lifting
- // of getting us past the current method.
+ // We don't ever explain a stop. The only stop that is relevant to us
+ // directly is the step_out plan we added to do the heavy lifting of getting
+ // us past the current method.
return false;
}
lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() {
- // This value doesn't matter - we'll never be the top thread plan, so
- // nobody will ask us this question.
+ // This value doesn't matter - we'll never be the top thread plan, so nobody
+ // will ask us this question.
return eStateRunning;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp
index 15cbd0baa9a6..7bf0dd39993e 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp
@@ -44,8 +44,8 @@ ThreadPlanCallUserExpression::ThreadPlanCallUserExpression(
lldb::UserExpressionSP &user_expression_sp)
: ThreadPlanCallFunction(thread, function, CompilerType(), args, options),
m_user_expression_sp(user_expression_sp) {
- // User expressions are generally "User generated" so we should set them up to
- // stop when done.
+ // User expressions are generally "User generated" so we should set them up
+ // to stop when done.
SetIsMasterPlan(true);
SetOkayToDiscard(false);
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanPython.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanPython.cpp
index af5c76518382..7796b8a0ab20 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanPython.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanPython.cpp
@@ -59,8 +59,7 @@ bool ThreadPlanPython::ValidatePlan(Stream *error) {
void ThreadPlanPython::DidPush() {
// We set up the script side in DidPush, so that it can push other plans in
- // the constructor,
- // and doesn't have to care about the details of DidPush.
+ // the constructor, and doesn't have to care about the details of DidPush.
if (!m_class_name.empty()) {
ScriptInterpreter *script_interp = m_thread.GetProcess()
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
index 44de724b608c..6d1a8b5c27ff 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
@@ -133,8 +133,7 @@ void ThreadPlanRunToAddress::GetDescription(Stream *s,
}
bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
- // If we couldn't set the breakpoint for some reason, then this won't
- // work.
+ // If we couldn't set the breakpoint for some reason, then this won't work.
bool all_bps_good = true;
size_t num_break_ids = m_break_ids.size();
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
index 42aaa4227cf9..c7afe0d9a8a7 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
@@ -86,8 +86,8 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
// Always avoid code with line number 0.
// FIXME: At present the ShouldStop and the StepFromHere calculate this
// independently. If this ever
- // becomes expensive (this one isn't) we can try to have this set a state that
- // the StepFromHere can use.
+ // becomes expensive (this one isn't) we can try to have this set a state
+ // that the StepFromHere can use.
if (frame) {
SymbolContext sc;
sc = frame->GetSymbolContext(eSymbolContextLineEntry);
@@ -104,9 +104,8 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
const bool stop_others = false;
const size_t frame_index = 0;
ThreadPlanSP return_plan_sp;
- // If we are stepping through code at line number 0, then we need to step over
- // this range. Otherwise
- // we will step out.
+ // If we are stepping through code at line number 0, then we need to step
+ // over this range. Otherwise we will step out.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
@@ -119,8 +118,7 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
AddressRange range = sc.line_entry.range;
// If the whole function is marked line 0 just step out, that's easier &
- // faster than continuing
- // to step through it.
+ // faster than continuing to step through it.
bool just_step_out = false;
if (sc.symbol && sc.symbol->ValueIsAddress()) {
Address symbol_end = sc.symbol->GetAddress();
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
index 6c5a9954f23f..6405c135a33e 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -12,11 +12,13 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Core/Architecture.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanStepOut.h"
@@ -33,8 +35,7 @@ uint32_t ThreadPlanStepInRange::s_default_flag_values =
//----------------------------------------------------------------------
// ThreadPlanStepInRange: Step through a stack range, either stepping over or
-// into
-// based on the value of \a type.
+// into based on the value of \a type.
//----------------------------------------------------------------------
ThreadPlanStepInRange::ThreadPlanStepInRange(
@@ -162,15 +163,14 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
if (m_virtual_step) {
// If we've just completed a virtual step, all we need to do is check for a
- // ShouldStopHere plan, and otherwise
- // we're done.
+ // ShouldStopHere plan, and otherwise we're done.
// FIXME - This can be both a step in and a step out. Probably should
// record which in the m_virtual_step.
m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
} else {
// Stepping through should be done running other threads in general, since
- // we're setting a breakpoint and
- // continuing. So only stop others if we are explicitly told to do so.
+ // we're setting a breakpoint and continuing. So only stop others if we
+ // are explicitly told to do so.
bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
@@ -183,9 +183,8 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// A caveat to this is if we think the frame is older but we're actually
// in a trampoline.
// I'm going to make the assumption that you wouldn't RETURN to a
- // trampoline. So if we are
- // in a trampoline we think the frame is older because the trampoline
- // confused the backtracer.
+ // trampoline. So if we are in a trampoline we think the frame is older
+ // because the trampoline confused the backtracer.
m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
stop_others);
if (!m_sub_plan_sp) {
@@ -202,19 +201,15 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
"Thought I stepped out, but in fact arrived at a trampoline.");
}
} else if (frame_order == eFrameCompareEqual && InSymbol()) {
- // If we are not in a place we should step through, we're done.
- // One tricky bit here is that some stubs don't push a frame, so we have
- // to check
- // both the case of a frame that is younger, or the same as this frame.
- // However, if the frame is the same, and we are still in the symbol we
- // started
- // in, the we don't need to do this. This first check isn't strictly
- // necessary,
- // but it is more efficient.
+ // If we are not in a place we should step through, we're done. One
+ // tricky bit here is that some stubs don't push a frame, so we have to
+ // check both the case of a frame that is younger, or the same as this
+ // frame. However, if the frame is the same, and we are still in the
+ // symbol we started in, the we don't need to do this. This first check
+ // isn't strictly necessary, but it is more efficient.
// If we're still in the range, keep going, either by running to the next
- // branch breakpoint, or by
- // stepping.
+ // branch breakpoint, or by stepping.
if (InRange()) {
SetNextBranchBreakpoint();
return false;
@@ -242,15 +237,13 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
log->Printf("No step through plan found.");
}
- // If not, give the "should_stop" callback a chance to push a plan to get us
- // out of here.
- // But only do that if we actually have stepped in.
+ // If not, give the "should_stop" callback a chance to push a plan to get
+ // us out of here. But only do that if we actually have stepped in.
if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
// If we've stepped in and we are going to stop here, check to see if we
- // were asked to
- // run past the prologue, and if so do that.
+ // were asked to run past the prologue, and if so do that.
if (!m_sub_plan_sp && frame_order == eFrameCompareYounger &&
m_step_past_prologue) {
@@ -277,6 +270,17 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
bytes_to_skip = sc.symbol->GetPrologueByteSize();
}
+ if (bytes_to_skip == 0 && sc.symbol) {
+ TargetSP target = m_thread.CalculateTarget();
+ const Architecture *arch = target->GetArchitecturePlugin();
+ if (arch) {
+ Address curr_sec_addr;
+ target->GetSectionLoadList().ResolveLoadAddress(curr_addr,
+ curr_sec_addr);
+ bytes_to_skip = arch->GetBytesToSkip(*sc.symbol, curr_sec_addr);
+ }
+ }
+
if (bytes_to_skip != 0) {
func_start_address.Slide(bytes_to_skip);
log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP);
@@ -400,8 +404,8 @@ bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
SymbolContext sc = frame->GetSymbolContext(
eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);
if (sc.symbol != nullptr) {
- // First try an exact match, since that's cheap with ConstStrings. Then
- // do a strstr compare.
+ // First try an exact match, since that's cheap with ConstStrings.
+ // Then do a strstr compare.
if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) {
should_stop_here = true;
} else {
@@ -436,25 +440,19 @@ bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
bool ThreadPlanStepInRange::DoPlanExplainsStop(Event *event_ptr) {
// We always explain a stop. Either we've just done a single step, in which
- // case we'll do our ordinary processing, or we stopped for some
- // reason that isn't handled by our sub-plans, in which case we want to just
- // stop right
- // away.
- // In general, we don't want to mark the plan as complete for unexplained
- // stops.
- // For instance, if you step in to some code with no debug info, so you step
- // out
- // and in the course of that hit a breakpoint, then you want to stop & show
- // the user
- // the breakpoint, but not unship the step in plan, since you still may want
- // to complete that
- // plan when you continue. This is particularly true when doing "step in to
- // target function."
+ // case we'll do our ordinary processing, or we stopped for some reason that
+ // isn't handled by our sub-plans, in which case we want to just stop right
+ // away. In general, we don't want to mark the plan as complete for
+ // unexplained stops. For instance, if you step in to some code with no debug
+ // info, so you step out and in the course of that hit a breakpoint, then you
+ // want to stop & show the user the breakpoint, but not unship the step in
+ // plan, since you still may want to complete that plan when you continue.
+ // This is particularly true when doing "step in to target function."
// stepping.
//
- // The only variation is that if we are doing "step by running to next branch"
- // in which case
- // if we hit our branch breakpoint we don't set the plan to complete.
+ // The only variation is that if we are doing "step by running to next
+ // branch" in which case if we hit our branch breakpoint we don't set the
+ // plan to complete.
bool return_value = false;
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
index ca45960e1ed5..dd8f129a935b 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -76,8 +76,8 @@ void ThreadPlanStepInstruction::GetDescription(Stream *s,
}
bool ThreadPlanStepInstruction::ValidatePlan(Stream *error) {
- // Since we read the instruction we're stepping over from the thread,
- // this plan will always work.
+ // Since we read the instruction we're stepping over from the thread, this
+ // plan will always work.
return true;
}
@@ -106,8 +106,8 @@ bool ThreadPlanStepInstruction::IsPlanStale() {
return (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr);
} else if (cur_frame_id < m_stack_id) {
// If the current frame is younger than the start frame and we are stepping
- // over, then we need to continue,
- // but if we are doing just one step, we're done.
+ // over, then we need to continue, but if we are doing just one step, we're
+ // done.
return !m_step_over;
} else {
if (log) {
@@ -140,8 +140,7 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
return true;
} else {
// We are still stepping, reset the start pc, and in case we've
- // stepped out,
- // reset the current stack id.
+ // stepped out, reset the current stack id.
SetUpState();
return false;
}
@@ -154,9 +153,8 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
if (return_frame->GetStackID() != m_parent_frame_id ||
m_start_has_symbol) {
// next-instruction shouldn't step out of inlined functions. But we
- // may have stepped into a
- // real function that starts with an inlined function, and we do want
- // to step out of that...
+ // may have stepped into a real function that starts with an inlined
+ // function, and we do want to step out of that...
if (cur_frame_sp->IsInlined()) {
StackFrameSP parent_frame_sp =
@@ -190,9 +188,8 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
log->Printf("%s.", s.GetData());
}
- // StepInstruction should probably have the tri-state RunMode, but for
- // now it is safer to
- // run others.
+ // StepInstruction should probably have the tri-state RunMode, but
+ // for now it is safer to run others.
const bool stop_others = false;
m_thread.QueueThreadPlanForStepOutNoShouldStop(
false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0);
@@ -222,8 +219,7 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
return true;
} else {
// We are still stepping, reset the start pc, and in case we've stepped
- // in or out,
- // reset the current stack id.
+ // in or out, reset the current stack id.
SetUpState();
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp
index 6b6ed06e9b37..f2db6e4b6f42 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -63,17 +63,14 @@ ThreadPlanStepOut::ThreadPlanStepOut(
m_step_out_to_id = return_frame_sp->GetStackID();
m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
- // If the frame directly below the one we are returning to is inlined, we have
- // to be
- // a little more careful. It is non-trivial to determine the real "return
- // code address" for
- // an inlined frame, so we have to work our way to that frame and then step
- // out.
+ // If the frame directly below the one we are returning to is inlined, we
+ // have to be a little more careful. It is non-trivial to determine the real
+ // "return code address" for an inlined frame, so we have to work our way to
+ // that frame and then step out.
if (immediate_return_from_sp && immediate_return_from_sp->IsInlined()) {
if (frame_idx > 0) {
// First queue a plan that gets us to this inlined frame, and when we get
- // there we'll queue a second
- // plan that walks us out of this frame.
+ // there we'll queue a second plan that walks us out of this frame.
m_step_out_to_inline_plan_sp.reset(new ThreadPlanStepOut(
m_thread, nullptr, false, stop_others, eVoteNoOpinion, eVoteNoOpinion,
frame_idx - 1, eLazyBoolNo, continue_to_next_branch));
@@ -81,8 +78,8 @@ ThreadPlanStepOut::ThreadPlanStepOut(
->SetShouldStopHereCallbacks(nullptr, nullptr);
m_step_out_to_inline_plan_sp->SetPrivate(true);
} else {
- // If we're already at the inlined frame we're stepping through, then just
- // do that now.
+ // If we're already at the inlined frame we're stepping through, then
+ // just do that now.
QueueInlinedStepPlan(false);
}
} else if (return_frame_sp) {
@@ -217,8 +214,8 @@ bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
}
bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
- // If the step out plan is done, then we just need to step through the inlined
- // frame.
+ // If the step out plan is done, then we just need to step through the
+ // inlined frame.
if (m_step_out_to_inline_plan_sp) {
return m_step_out_to_inline_plan_sp->MischiefManaged();
} else if (m_step_through_inline_plan_sp) {
@@ -233,15 +230,14 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
}
// We don't explain signals or breakpoints (breakpoints that handle stepping
- // in or
- // out will be handled by a child plan.
+ // in or out will be handled by a child plan.
StopInfoSP stop_info_sp = GetPrivateStopInfo();
if (stop_info_sp) {
StopReason reason = stop_info_sp->GetStopReason();
if (reason == eStopReasonBreakpoint) {
- // If this is OUR breakpoint, we're fine, otherwise we don't know why this
- // happened...
+ // If this is OUR breakpoint, we're fine, otherwise we don't know why
+ // this happened...
BreakpointSiteSP site_sp(
m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
stop_info_sp->GetValue()));
@@ -268,11 +264,10 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
}
// If there was only one owner, then we're done. But if we also hit
- // some
- // user breakpoint on our way out, we should mark ourselves as done, but
- // also not claim to explain the stop, since it is more important to
- // report
- // the user breakpoint than the step out completion.
+ // some user breakpoint on our way out, we should mark ourselves as
+ // done, but also not claim to explain the stop, since it is more
+ // important to report the user breakpoint than the step out
+ // completion.
if (site_sp->GetNumberOfOwners() == 1)
return true;
@@ -320,9 +315,8 @@ bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) {
done = !(frame_zero_id < m_step_out_to_id);
}
- // The normal step out computations think we are done, so all we need to do is
- // consult the ShouldStopHere,
- // and we are done.
+ // The normal step out computations think we are done, so all we need to do
+ // is consult the ShouldStopHere, and we are done.
if (done) {
if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
@@ -377,8 +371,7 @@ bool ThreadPlanStepOut::MischiefManaged() {
// I also check the stack depth, since if we've blown past the breakpoint
// for some
// reason and we're now stopping for some other reason altogether, then
- // we're done
- // with this step out operation.
+ // we're done with this step out operation.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
if (log)
@@ -397,10 +390,8 @@ bool ThreadPlanStepOut::MischiefManaged() {
bool ThreadPlanStepOut::QueueInlinedStepPlan(bool queue_now) {
// Now figure out the range of this inlined block, and set up a "step through
- // range"
- // plan for that. If we've been provided with a context, then use the block
- // in that
- // context.
+ // range" plan for that. If we've been provided with a context, then use the
+ // block in that context.
StackFrameSP immediate_return_from_sp(m_thread.GetStackFrameAtIndex(0));
if (!immediate_return_from_sp)
return false;
@@ -477,8 +468,8 @@ void ThreadPlanStepOut::CalculateReturnValue() {
}
bool ThreadPlanStepOut::IsPlanStale() {
- // If we are still lower on the stack than the frame we are returning to, then
- // there's something for us to do. Otherwise, we're stale.
+ // If we are still lower on the stack than the frame we are returning to,
+ // then there's something for us to do. Otherwise, we're stale.
StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
return !(frame_zero_id < m_step_out_to_id);
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
index 3896a0b24714..7497dbff1729 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -31,8 +31,8 @@ ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint(Thread &thread)
ThreadPlan::eKindStepOverBreakpoint, "Step over breakpoint trap",
thread, eVoteNo,
eVoteNoOpinion), // We need to report the run since this happens
- // first in the thread plan stack when stepping
- // over a breakpoint
+ // first in the thread plan stack when stepping over
+ // a breakpoint
m_breakpoint_addr(LLDB_INVALID_ADDRESS),
m_auto_continue(false), m_reenabled_breakpoint_site(false)
@@ -57,42 +57,58 @@ bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) {
StopInfoSP stop_info_sp = GetPrivateStopInfo();
if (stop_info_sp) {
// It's a little surprising that we stop here for a breakpoint hit.
- // However, when you single step ONTO a breakpoint
- // we still want to call that a breakpoint hit, and trigger the actions,
- // etc. Otherwise you would see the
+ // However, when you single step ONTO a breakpoint we still want to call
+ // that a breakpoint hit, and trigger the actions, etc. Otherwise you
+ // would see the
// PC at the breakpoint without having triggered the actions, then you'd
// continue, the PC wouldn't change,
- // and you'd see the breakpoint hit, which would be odd.
- // So the lower levels fake "step onto breakpoint address" and return that
- // as a breakpoint. So our trace
- // step COULD appear as a breakpoint hit if the next instruction also
- // contained a breakpoint.
+ // and you'd see the breakpoint hit, which would be odd. So the lower
+ // levels fake "step onto breakpoint address" and return that as a
+ // breakpoint. So our trace step COULD appear as a breakpoint hit if the
+ // next instruction also contained a breakpoint.
StopReason reason = stop_info_sp->GetStopReason();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+
+ if (log)
+ log->Printf("Step over breakpoint stopped for reason: %s.",
+ Thread::StopReasonAsCString(reason));
+
switch (reason) {
- case eStopReasonTrace:
- case eStopReasonNone:
- return true;
- case eStopReasonBreakpoint:
- // It's a little surprising that we stop here for a breakpoint hit.
- // However, when you single step ONTO a
- // breakpoint we still want to call that a breakpoint hit, and trigger the
- // actions, etc. Otherwise you
- // would see the PC at the breakpoint without having triggered the
- // actions, then you'd continue, the PC
- // wouldn't change, and you'd see the breakpoint hit, which would be odd.
- // So the lower levels fake "step onto breakpoint address" and return that
- // as a breakpoint hit. So our trace
- // step COULD appear as a breakpoint hit if the next instruction also
- // contained a breakpoint. We don't want
- // to handle that, since we really don't know what to do with breakpoint
- // hits. But make sure we don't set
- // ourselves to auto-continue or we'll wrench control away from the plans
- // that can deal with this.
- SetAutoContinue(false);
- return false;
- default:
- return false;
+ case eStopReasonTrace:
+ case eStopReasonNone:
+ return true;
+ case eStopReasonBreakpoint:
+ {
+ // It's a little surprising that we stop here for a breakpoint hit.
+ // However, when you single step ONTO a breakpoint we still want to call
+ // that a breakpoint hit, and trigger the actions, etc. Otherwise you
+ // would see the PC at the breakpoint without having triggered the
+ // actions, then you'd continue, the PC wouldn't change, and you'd see
+ // the breakpoint hit, which would be odd. So the lower levels fake
+ // "step onto breakpoint address" and return that as a breakpoint hit.
+ // So our trace step COULD appear as a breakpoint hit if the next
+ // instruction also contained a breakpoint. We don't want to handle
+ // that, since we really don't know what to do with breakpoint hits.
+ // But make sure we don't set ourselves to auto-continue or we'll wrench
+ // control away from the plans that can deal with this.
+ // Be careful, however, as we may have "seen a breakpoint under the PC
+ // because we stopped without changing the PC, in which case we do want
+ // to re-claim this stop so we'll try again.
+ lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
+
+ if (pc_addr == m_breakpoint_addr) {
+ if (log)
+ log->Printf("Got breakpoint stop reason but pc: 0x%" PRIx64
+ "hasn't changed.", pc_addr);
+ return true;
+ }
+
+ SetAutoContinue(false);
+ return false;
+ }
+ default:
+ return false;
}
}
return false;
@@ -114,8 +130,10 @@ bool ThreadPlanStepOverBreakpoint::DoWillResume(StateType resume_state,
BreakpointSiteSP bp_site_sp(
m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress(
m_breakpoint_addr));
- if (bp_site_sp && bp_site_sp->IsEnabled())
+ if (bp_site_sp && bp_site_sp->IsEnabled()) {
m_thread.GetProcess()->DisableBreakpointSite(bp_site_sp.get());
+ m_reenabled_breakpoint_site = false;
+ }
}
return true;
}
@@ -125,13 +143,16 @@ bool ThreadPlanStepOverBreakpoint::WillStop() {
return true;
}
+void ThreadPlanStepOverBreakpoint::WillPop() {
+ ReenableBreakpointSite();
+}
+
bool ThreadPlanStepOverBreakpoint::MischiefManaged() {
lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
if (pc_addr == m_breakpoint_addr) {
// If we are still at the PC of our breakpoint, then for some reason we
- // didn't
- // get a chance to run.
+ // didn't get a chance to run.
return false;
} else {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp
index d5778fb5e8d7..b88d25b707eb 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp
@@ -32,8 +32,7 @@ uint32_t ThreadPlanStepOverRange::s_default_flag_values = 0;
//----------------------------------------------------------------------
// ThreadPlanStepOverRange: Step through a stack range, either stepping over or
-// into
-// based on the value of \a type.
+// into based on the value of \a type.
//----------------------------------------------------------------------
ThreadPlanStepOverRange::ThreadPlanStepOverRange(
@@ -91,21 +90,17 @@ void ThreadPlanStepOverRange::SetupAvoidNoDebug(
else
GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
// Step Over plans should always avoid no-debug on step in. Seems like you
- // shouldn't
- // have to say this, but a tail call looks more like a step in that a step
- // out, so
- // we want to catch this case.
+ // shouldn't have to say this, but a tail call looks more like a step in that
+ // a step out, so we want to catch this case.
GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
}
bool ThreadPlanStepOverRange::IsEquivalentContext(
const SymbolContext &context) {
- // Match as much as is specified in the m_addr_context:
- // This is a fairly loose sanity check. Note, sometimes the target doesn't
- // get filled
- // in so I left out the target check. And sometimes the module comes in as
- // the .o file from the
- // inlined range, so I left that out too...
+ // Match as much as is specified in the m_addr_context: This is a fairly
+ // loose sanity check. Note, sometimes the target doesn't get filled in so I
+ // left out the target check. And sometimes the module comes in as the .o
+ // file from the inlined range, so I left that out too...
if (m_addr_context.comp_unit) {
if (m_addr_context.comp_unit != context.comp_unit)
return false;
@@ -113,8 +108,8 @@ bool ThreadPlanStepOverRange::IsEquivalentContext(
if (m_addr_context.function != context.function)
return false;
// It is okay to return to a different block of a straight function, we
- // only have to
- // be more careful if returning from one inlined block to another.
+ // only have to be more careful if returning from one inlined block to
+ // another.
if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
context.block->GetInlinedFunctionInfo() == nullptr)
return true;
@@ -140,8 +135,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
}
// If we're out of the range but in the same frame or in our caller's frame
- // then we should stop.
- // When stepping out we only stop others if we are forcing running one thread.
+ // then we should stop. When stepping out we only stop others if we are
+ // forcing running one thread.
bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
ThreadPlanSP new_plan_sp;
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
@@ -152,11 +147,9 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// A caveat to this is if we think the frame is older but we're actually in
// a trampoline.
// I'm going to make the assumption that you wouldn't RETURN to a
- // trampoline. So if we are
- // in a trampoline we think the frame is older because the trampoline
- // confused the backtracer.
- // As below, we step through first, and then try to figure out how to get
- // back out again.
+ // trampoline. So if we are in a trampoline we think the frame is older
+ // because the trampoline confused the backtracer. As below, we step
+ // through first, and then try to figure out how to get back out again.
new_plan_sp =
m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
@@ -166,8 +159,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
"Thought I stepped out, but in fact arrived at a trampoline.");
} else if (frame_order == eFrameCompareYounger) {
// Make sure we really are in a new frame. Do that by unwinding and seeing
- // if the
- // start function really is our start function...
+ // if the start function really is our start function...
for (uint32_t i = 1;; ++i) {
StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
if (!older_frame_sp) {
@@ -200,28 +192,23 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (!InSymbol()) {
// This one is a little tricky. Sometimes we may be in a stub or
- // something similar,
- // in which case we need to get out of there. But if we are in a stub
- // then it's
- // likely going to be hard to get out from here. It is probably easiest
- // to step into the
- // stub, and then it will be straight-forward to step out.
+ // something similar, in which case we need to get out of there. But if
+ // we are in a stub then it's likely going to be hard to get out from
+ // here. It is probably easiest to step into the stub, and then it will
+ // be straight-forward to step out.
new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
stop_others);
} else {
- // The current clang (at least through 424) doesn't always get the address
- // range for the
- // DW_TAG_inlined_subroutines right, so that when you leave the inlined
- // range the line table says
- // you are still in the source file of the inlining function. This is
- // bad, because now you are missing
- // the stack frame for the function containing the inlining, and if you
- // sensibly do "finish" to get
- // out of this function you will instead exit the containing function.
- // To work around this, we check whether we are still in the source file
- // we started in, and if not assume
- // it is an error, and push a plan to get us out of this line and back to
- // the containing file.
+ // The current clang (at least through 424) doesn't always get the
+ // address range for the DW_TAG_inlined_subroutines right, so that when
+ // you leave the inlined range the line table says you are still in the
+ // source file of the inlining function. This is bad, because now you
+ // are missing the stack frame for the function containing the inlining,
+ // and if you sensibly do "finish" to get out of this function you will
+ // instead exit the containing function. To work around this, we check
+ // whether we are still in the source file we started in, and if not
+ // assume it is an error, and push a plan to get us out of this line and
+ // back to the containing file.
if (m_addr_context.line_entry.IsValid()) {
SymbolContext sc;
@@ -244,14 +231,11 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
bool step_past_remaining_inline = false;
if (entry_idx > 0) {
// We require the previous line entry and the current line
- // entry come
- // from the same file.
- // The other requirement is that the previous line table entry
- // be part of an
- // inlined block, we don't want to step past cases where
- // people have inlined
- // some code fragment by using #include <source-fragment.c>
- // directly.
+ // entry come from the same file. The other requirement is
+ // that the previous line table entry be part of an inlined
+ // block, we don't want to step past cases where people have
+ // inlined some code fragment by using #include <source-
+ // fragment.c> directly.
LineEntry prev_line_entry;
if (line_table->GetLineEntryAtIndex(entry_idx - 1,
prev_line_entry) &&
@@ -338,8 +322,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (!new_plan_sp) {
// For efficiencies sake, we know we're done here so we don't have to do
- // this
- // calculation again in MischiefManaged.
+ // this calculation again in MischiefManaged.
SetPlanComplete();
return true;
} else
@@ -347,16 +330,12 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
}
bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
- // For crashes, breakpoint hits, signals, etc, let the base plan (or some plan
- // above us)
- // handle the stop. That way the user can see the stop, step around, and then
- // when they
- // are done, continue and have their step complete. The exception is if we've
- // hit our
- // "run to next branch" breakpoint.
- // Note, unlike the step in range plan, we don't mark ourselves complete if we
- // hit an
- // unexplained breakpoint/crash.
+ // For crashes, breakpoint hits, signals, etc, let the base plan (or some
+ // plan above us) handle the stop. That way the user can see the stop, step
+ // around, and then when they are done, continue and have their step
+ // complete. The exception is if we've hit our "run to next branch"
+ // breakpoint. Note, unlike the step in range plan, we don't mark ourselves
+ // complete if we hit an unexplained breakpoint/crash.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
StopInfoSP stop_info_sp = GetPrivateStopInfo();
@@ -387,8 +366,8 @@ bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
m_first_resume = false;
if (resume_state == eStateStepping && current_plan) {
// See if we are about to step over an inlined call in the middle of the
- // inlined stack, if so figure
- // out its extents and reset our range to step over that.
+ // inlined stack, if so figure out its extents and reset our range to
+ // step over that.
bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
if (in_inlined_stack) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp
index 09e606f490a6..5a71119015eb 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -31,8 +31,8 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// ThreadPlanStepRange: Step through a stack range, either stepping over or into
-// based on the value of \a type.
+// ThreadPlanStepRange: Step through a stack range, either stepping over or
+// into based on the value of \a type.
//----------------------------------------------------------------------
ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name,
@@ -74,15 +74,14 @@ Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
}
void ThreadPlanStepRange::AddRange(const AddressRange &new_range) {
- // For now I'm just adding the ranges. At some point we may want to
- // condense the ranges if they overlap, though I don't think it is likely
- // to be very important.
+ // For now I'm just adding the ranges. At some point we may want to condense
+ // the ranges if they overlap, though I don't think it is likely to be very
+ // important.
m_address_ranges.push_back(new_range);
// Fill the slot for this address range with an empty DisassemblerSP in the
- // instruction ranges. I want the
- // indices to match, but I don't want to do the work to disassemble this range
- // if I don't step into it.
+ // instruction ranges. I want the indices to match, but I don't want to do
+ // the work to disassemble this range if I don't step into it.
m_instruction_ranges.push_back(DisassemblerSP());
}
@@ -158,12 +157,11 @@ bool ThreadPlanStepRange::InRange() {
} else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(
m_thread.CalculateTarget().get()) != pc_load_addr) {
// Another thing that sometimes happens here is that we step out of
- // one line into the MIDDLE of another
- // line. So far I mostly see this due to bugs in the debug
- // information.
- // But we probably don't want to be in the middle of a line range, so
- // in that case reset the stepping
- // range to the line we've stepped into the middle of and continue.
+ // one line into the MIDDLE of another line. So far I mostly see
+ // this due to bugs in the debug information. But we probably don't
+ // want to be in the middle of a line range, so in that case reset
+ // the stepping range to the line we've stepped into the middle of
+ // and continue.
m_addr_context = new_context;
m_address_ranges.clear();
AddRange(m_addr_context.line_entry.range);
@@ -260,9 +258,8 @@ InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
return nullptr;
else {
// Find where we are in the instruction list as well. If we aren't at
- // an instruction,
- // return nullptr. In this case, we're probably lost, and shouldn't try
- // to do anything fancy.
+ // an instruction, return nullptr. In this case, we're probably lost,
+ // and shouldn't try to do anything fancy.
insn_offset =
m_instruction_ranges[i]
@@ -297,8 +294,7 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
// Stepping through ranges using breakpoints doesn't work yet, but with this
- // off we fall back to instruction
- // single stepping.
+ // off we fall back to instruction single stepping.
if (!m_use_fast_step)
return false;
@@ -383,9 +379,8 @@ bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop(
size_t num_owners = bp_site_sp->GetNumberOfOwners();
bool explains_stop = true;
// If all the owners are internal, then we are probably just stepping over
- // this range from multiple threads,
- // or multiple frames, so we want to continue. If one is not internal, then
- // we should not explain the stop,
+ // this range from multiple threads, or multiple frames, so we want to
+ // continue. If one is not internal, then we should not explain the stop,
// and let the user breakpoint handle the stop.
for (size_t i = 0; i < num_owners; i++) {
if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) {
@@ -418,8 +413,8 @@ bool ThreadPlanStepRange::MischiefManaged() {
// I do this check first because we might have stepped somewhere that will
// fool InRange into
// thinking it needs to step past the end of that line. This happens, for
- // instance, when stepping
- // over inlined code that is in the middle of the current line.
+ // instance, when stepping over inlined code that is in the middle of the
+ // current line.
if (!m_no_more_plans)
return false;
@@ -457,8 +452,8 @@ bool ThreadPlanStepRange::IsPlanStale() {
}
return true;
} else if (frame_order == eFrameCompareEqual && InSymbol()) {
- // If we are not in a place we should step through, we've gotten stale.
- // One tricky bit here is that some stubs don't push a frame, so we should.
+ // If we are not in a place we should step through, we've gotten stale. One
+ // tricky bit here is that some stubs don't push a frame, so we should.
// check that we are in the same symbol.
if (!InRange()) {
// Set plan Complete when we reach next instruction just after the range
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
index 46aadb00f2ab..c039a32f5515 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
@@ -26,9 +26,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// ThreadPlanStepThrough: If the current instruction is a trampoline, step
-// through it
-// If it is the beginning of the prologue of a function, step through that as
-// well.
+// through it If it is the beginning of the prologue of a function, step
+// through that as well.
// FIXME: At present only handles DYLD trampolines.
//----------------------------------------------------------------------
@@ -49,9 +48,8 @@ ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
m_start_address = GetThread().GetRegisterContext()->GetPC(0);
// We are going to return back to the concrete frame 1, we might pass by
- // some inlined code that we're in
- // the middle of by doing this, but it's easier than trying to figure out
- // where the inlined code might return to.
+ // some inlined code that we're in the middle of by doing this, but it's
+ // easier than trying to figure out where the inlined code might return to.
StackFrameSP return_frame_sp = m_thread.GetFrameWithStackID(m_stack_id);
@@ -136,10 +134,8 @@ bool ThreadPlanStepThrough::ValidatePlan(Stream *error) {
bool ThreadPlanStepThrough::DoPlanExplainsStop(Event *event_ptr) {
// If we have a sub-plan, it will have been asked first if we explain the
- // stop, and
- // we won't get asked. The only time we would be the one directly asked this
- // question
- // is if we hit our backstop breakpoint.
+ // stop, and we won't get asked. The only time we would be the one directly
+ // asked this question is if we hit our backstop breakpoint.
return HitOurBackstopBreakpoint();
}
@@ -156,8 +152,7 @@ bool ThreadPlanStepThrough::ShouldStop(Event *event_ptr) {
}
// If we don't have a sub-plan, then we're also done (can't see how we would
- // ever get here
- // without a plan, but just in case.
+ // ever get here without a plan, but just in case.
if (!m_sub_plan_sp) {
SetPlanComplete();
@@ -165,15 +160,13 @@ bool ThreadPlanStepThrough::ShouldStop(Event *event_ptr) {
}
// If the current sub plan is not done, we don't want to stop. Actually, we
- // probably won't
- // ever get here in this state, since we generally won't get asked any
- // questions if out
- // current sub-plan is not done...
+ // probably won't ever get here in this state, since we generally won't get
+ // asked any questions if out current sub-plan is not done...
if (!m_sub_plan_sp->IsPlanComplete())
return false;
- // If our current sub plan failed, then let's just run to our backstop. If we
- // can't do that then just stop.
+ // If our current sub plan failed, then let's just run to our backstop. If
+ // we can't do that then just stop.
if (!m_sub_plan_sp->PlanSucceeded()) {
if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
m_sub_plan_sp.reset();
@@ -185,8 +178,7 @@ bool ThreadPlanStepThrough::ShouldStop(Event *event_ptr) {
}
// Next see if there is a specific step through plan at our current pc (these
- // might
- // chain, for instance stepping through a dylib trampoline to the objc
+ // might chain, for instance stepping through a dylib trampoline to the objc
// dispatch function...)
LookForPlanToStepThroughFromCurrentPC();
if (m_sub_plan_sp) {
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp
index 01f5f948a28c..9984ee925c86 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp
@@ -151,8 +151,8 @@ void ThreadPlanStepUntil::AnalyzeStop() {
StopReason reason = stop_info_sp->GetStopReason();
if (reason == eStopReasonBreakpoint) {
- // If this is OUR breakpoint, we're fine, otherwise we don't know why this
- // happened...
+ // If this is OUR breakpoint, we're fine, otherwise we don't know why
+ // this happened...
BreakpointSiteSP this_site =
m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
stop_info_sp->GetValue());
@@ -163,18 +163,13 @@ void ThreadPlanStepUntil::AnalyzeStop() {
if (this_site->IsBreakpointAtThisSite(m_return_bp_id)) {
// If we are at our "step out" breakpoint, and the stack depth has
- // shrunk, then
- // this is indeed our stop.
- // If the stack depth has grown, then we've hit our step out breakpoint
- // recursively.
- // If we are the only breakpoint at that location, then we do explain
- // the stop, and
- // we'll just continue.
- // If there was another breakpoint here, then we don't explain the stop,
- // but we won't
- // mark ourselves Completed, because maybe that breakpoint will
- // continue, and then
- // we'll finish the "until".
+ // shrunk, then this is indeed our stop. If the stack depth has grown,
+ // then we've hit our step out breakpoint recursively. If we are the
+ // only breakpoint at that location, then we do explain the stop, and
+ // we'll just continue. If there was another breakpoint here, then we
+ // don't explain the stop, but we won't mark ourselves Completed,
+ // because maybe that breakpoint will continue, and then we'll finish
+ // the "until".
bool done;
StackID cur_frame_zero_id;
@@ -209,8 +204,8 @@ void ThreadPlanStepUntil::AnalyzeStop() {
else {
StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1);
- // But if we can't even unwind one frame we should just get out of
- // here & stop...
+ // But if we can't even unwind one frame we should just get out
+ // of here & stop...
if (older_frame_sp) {
const SymbolContext &older_context =
older_frame_sp->GetSymbolContext(eSymbolContextEverything);
@@ -230,8 +225,8 @@ void ThreadPlanStepUntil::AnalyzeStop() {
// Otherwise we've hit this breakpoint recursively. If we're the
// only breakpoint here, then we do explain the stop, and we'll
- // continue.
- // If not then we should let higher plans handle this stop.
+ // continue. If not then we should let higher plans handle this
+ // stop.
if (this_site->GetNumberOfOwners() == 1)
m_explains_stop = true;
else {
@@ -242,8 +237,8 @@ void ThreadPlanStepUntil::AnalyzeStop() {
}
}
}
- // If we get here we haven't hit any of our breakpoints, so let the higher
- // plans take care of the stop.
+ // If we get here we haven't hit any of our breakpoints, so let the
+ // higher plans take care of the stop.
m_explains_stop = false;
return;
} else if (IsUsuallyUnexplainedStopReason(reason)) {
@@ -256,16 +251,15 @@ void ThreadPlanStepUntil::AnalyzeStop() {
bool ThreadPlanStepUntil::DoPlanExplainsStop(Event *event_ptr) {
// We don't explain signals or breakpoints (breakpoints that handle stepping
- // in or
- // out will be handled by a child plan.
+ // in or out will be handled by a child plan.
AnalyzeStop();
return m_explains_stop;
}
bool ThreadPlanStepUntil::ShouldStop(Event *event_ptr) {
- // If we've told our self in ExplainsStop that we plan to continue, then
- // do so here. Otherwise, as long as this thread has stopped for a reason,
- // we will stop.
+ // If we've told our self in ExplainsStop that we plan to continue, then do
+ // so here. Otherwise, as long as this thread has stopped for a reason, we
+ // will stop.
StopInfoSP stop_info_sp = GetPrivateStopInfo();
if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone)
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
index 5057ca0a711b..acbbd4d8bcc2 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
@@ -217,7 +218,8 @@ void ThreadPlanAssemblyTracer::Log() {
reg_value != m_register_values[reg_num]) {
if (reg_value.GetType() != RegisterValue::eTypeInvalid) {
stream->PutCString("\n\t");
- reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
+ DumpRegisterValue(reg_value, stream, reg_info, true, false,
+ eFormatDefault);
}
}
m_register_values[reg_num] = reg_value;
diff --git a/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp b/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp
index 150c6619859f..9cfb1b74adee 100644
--- a/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp
@@ -66,9 +66,8 @@ UnixSignals::~UnixSignals() = default;
void UnixSignals::Reset() {
// This builds one standard set of Unix Signals. If yours aren't quite in
- // this
- // order, you can either subclass this class, and use Add & Remove to change
- // them
+ // this order, you can either subclass this class, and use Add & Remove to
+ // change them
// or you can subclass and build them afresh in your constructor;
//
// Note: the signals below are the Darwin signals. Do not change these!
@@ -306,8 +305,8 @@ UnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress,
bool signal_notify = false;
GetSignalInfo(signo, signal_suppress, signal_stop, signal_notify);
- // If any of filtering conditions are not met,
- // we move on to the next signal.
+ // If any of filtering conditions are not met, we move on to the next
+ // signal.
if (should_suppress.hasValue() &&
signal_suppress != should_suppress.getValue())
continue;
diff --git a/contrib/llvm/tools/lldb/source/Utility/ArchSpec.cpp b/contrib/llvm/tools/lldb/source/Utility/ArchSpec.cpp
index a10fe78260bb..1c50c313e0d1 100644
--- a/contrib/llvm/tools/lldb/source/Utility/ArchSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/ArchSpec.cpp
@@ -9,6 +9,7 @@
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/Stream.h" // for Stream
#include "lldb/Utility/StringList.h"
@@ -223,8 +224,8 @@ static const CoreDefinition g_core_definitions[] = {
"kalimba5"}};
// Ensure that we have an entry in the g_core_definitions for each core. If you
-// comment out an entry above,
-// you will need to comment out the corresponding ArchSpec::Core enumeration.
+// comment out an entry above, you will need to comment out the corresponding
+// ArchSpec::Core enumeration.
static_assert(sizeof(g_core_definitions) / sizeof(CoreDefinition) ==
ArchSpec::kNumCores,
"make sure we have one core definition for each core");
@@ -244,17 +245,24 @@ struct ArchDefinition {
const char *name;
};
-size_t ArchSpec::AutoComplete(llvm::StringRef name, StringList &matches) {
- if (!name.empty()) {
+void ArchSpec::ListSupportedArchNames(StringList &list) {
+ for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
+ list.AppendString(g_core_definitions[i].name);
+}
+
+size_t ArchSpec::AutoComplete(CompletionRequest &request) {
+ if (!request.GetCursorArgumentPrefix().empty()) {
for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) {
- if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith, name))
- matches.AppendString(g_core_definitions[i].name);
+ if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith,
+ request.GetCursorArgumentPrefix()))
+ request.AddCompletion(g_core_definitions[i].name);
}
} else {
- for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
- matches.AppendString(g_core_definitions[i].name);
+ StringList matches;
+ ListSupportedArchNames(matches);
+ request.AddCompletions(matches);
}
- return matches.GetSize();
+ return request.GetNumberOfMatches();
}
#define CPU_ANY (UINT32_MAX)
@@ -890,7 +898,12 @@ void ArchSpec::MergeFrom(const ArchSpec &other) {
GetTriple().setOS(other.GetTriple().getOS());
if (GetTriple().getArch() == llvm::Triple::UnknownArch) {
GetTriple().setArch(other.GetTriple().getArch());
- UpdateCore();
+
+ // MachO unknown64 isn't really invalid as the debugger can still obtain
+ // information from the binary, e.g. line tables. As such, we don't update
+ // the core here.
+ if (other.GetCore() != eCore_uknownMach64)
+ UpdateCore();
}
if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
!TripleVendorWasSpecified()) {
@@ -898,9 +911,8 @@ void ArchSpec::MergeFrom(const ArchSpec &other) {
GetTriple().setEnvironment(other.GetTriple().getEnvironment());
}
// If this and other are both arm ArchSpecs and this ArchSpec is a generic
- // "some kind of arm"
- // spec but the other ArchSpec is a specific arm core, adopt the specific arm
- // core.
+ // "some kind of arm" spec but the other ArchSpec is a specific arm core,
+ // adopt the specific arm core.
if (GetTriple().getArch() == llvm::Triple::arm &&
other.GetTriple().getArch() == llvm::Triple::arm &&
IsCompatibleMatch(other) && GetCore() == ArchSpec::eCore_arm_generic &&
@@ -926,24 +938,21 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu,
if (core_def) {
m_core = core_def->core;
update_triple = false;
- // Always use the architecture name because it might be more descriptive
- // than the architecture enum ("armv7" -> llvm::Triple::arm).
+ // Always use the architecture name because it might be more
+ // descriptive than the architecture enum ("armv7" ->
+ // llvm::Triple::arm).
m_triple.setArchName(llvm::StringRef(core_def->name));
if (arch_type == eArchTypeMachO) {
m_triple.setVendor(llvm::Triple::Apple);
// Don't set the OS. It could be simulator, macosx, ios, watchos,
- // tvos. We could
- // get close with the cpu type - but we can't get it right all of the
- // time. Better
- // to leave this unset so other sections of code will set it when they
- // have more
- // information.
+ // tvos. We could get close with the cpu type - but we can't get it
+ // right all of the time. Better to leave this unset so other
+ // sections of code will set it when they have more information.
// NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets
// the OSName to
// "unknown" and the ArchSpec::TripleVendorWasSpecified() method says
- // that any
- // OSName setting means it was specified.
+ // that any OSName setting means it was specified.
} else if (arch_type == eArchTypeELF) {
switch (os) {
case llvm::ELF::ELFOSABI_AIX:
@@ -972,10 +981,15 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu,
m_triple.setVendor(llvm::Triple::UnknownVendor);
m_triple.setOS(llvm::Triple::UnknownOS);
}
- // Fall back onto setting the machine type if the arch by name failed...
+ // Fall back onto setting the machine type if the arch by name
+ // failed...
if (m_triple.getArch() == llvm::Triple::UnknownArch)
m_triple.setArch(core_def->machine);
}
+ } else {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Unable to find a core definition for cpu 0x%" PRIx32 " sub %" PRId32, cpu, sub);
}
}
CoreUpdated(update_triple);
@@ -1015,10 +1029,9 @@ static bool isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs,
return true;
// If one of the environment is Android and the other one is EABI then they
- // are considered to
- // be compatible. This is required as a workaround for shared libraries
- // compiled for Android
- // without the NOTE section indicating that they are using the Android ABI.
+ // are considered to be compatible. This is required as a workaround for
+ // shared libraries compiled for Android without the NOTE section indicating
+ // that they are using the Android ABI.
if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) ||
(rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) ||
(lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) ||
@@ -1050,8 +1063,8 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
if (lhs_triple_vendor != rhs_triple_vendor) {
const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified();
const bool lhs_vendor_specified = TripleVendorWasSpecified();
- // Both architectures had the vendor specified, so if they aren't
- // equal then we return false
+ // Both architectures had the vendor specified, so if they aren't equal
+ // then we return false
if (rhs_vendor_specified && lhs_vendor_specified)
return false;
@@ -1066,8 +1079,8 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
if (lhs_triple_os != rhs_triple_os) {
const bool rhs_os_specified = rhs.TripleOSWasSpecified();
const bool lhs_os_specified = TripleOSWasSpecified();
- // Both architectures had the OS specified, so if they aren't
- // equal then we return false
+ // Both architectures had the OS specified, so if they aren't equal then
+ // we return false
if (rhs_os_specified && lhs_os_specified)
return false;
@@ -1094,9 +1107,9 @@ void ArchSpec::UpdateCore() {
const CoreDefinition *core_def = FindCoreDefinition(arch_name);
if (core_def) {
m_core = core_def->core;
- // Set the byte order to the default byte order for an architecture.
- // This can be modified if needed for cases when cores handle both
- // big and little endian
+ // Set the byte order to the default byte order for an architecture. This
+ // can be modified if needed for cases when cores handle both big and
+ // little endian
m_byte_order = core_def->default_byte_order;
} else {
Clear();
@@ -1193,9 +1206,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
break;
// v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- // Cortex-M0 - ARMv6-M - armv6m
- // Cortex-M3 - ARMv7-M - armv7m
- // Cortex-M4 - ARMv7E-M - armv7em
+ // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 -
+ // ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7em:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
@@ -1211,9 +1223,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
break;
// v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- // Cortex-M0 - ARMv6-M - armv6m
- // Cortex-M3 - ARMv7-M - armv7m
- // Cortex-M4 - ARMv7E-M - armv7em
+ // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 -
+ // ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7m:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
@@ -1411,6 +1422,11 @@ bool lldb_private::operator<(const ArchSpec &lhs, const ArchSpec &rhs) {
return lhs_core < rhs_core;
}
+
+bool lldb_private::operator==(const ArchSpec &lhs, const ArchSpec &rhs) {
+ return lhs.GetCore() == rhs.GetCore();
+}
+
bool ArchSpec::IsFullySpecifiedTriple() const {
const auto &user_specified_triple = GetTriple();
@@ -1456,9 +1472,8 @@ bool ArchSpec::IsAlwaysThumbInstructions() const {
// Cortex-M0 through Cortex-M7 are ARM processor cores which can only
// execute thumb instructions. We map the cores to arch names like this:
//
- // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m
- // Cortex-M3: armv7m
- // Cortex-M4, Cortex-M7: armv7em
+ // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m Cortex-M3: armv7m Cortex-M4,
+ // Cortex-M7: armv7em
if (GetCore() == ArchSpec::Core::eCore_arm_armv7m ||
GetCore() == ArchSpec::Core::eCore_arm_armv7em ||
diff --git a/contrib/llvm/tools/lldb/source/Utility/Args.cpp b/contrib/llvm/tools/lldb/source/Utility/Args.cpp
new file mode 100644
index 000000000000..3b5cf1715fb3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/Args.cpp
@@ -0,0 +1,726 @@
+//===-- Args.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StringList.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// A helper function for argument parsing.
+// Parses the initial part of the first argument using normal double quote
+// rules: backslash escapes the double quote and itself. The parsed string is
+// appended to the second argument. The function returns the unparsed portion
+// of the string, starting at the closing quote.
+static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
+ std::string &result) {
+ // Inside double quotes, '\' and '"' are special.
+ static const char *k_escapable_characters = "\"\\";
+ while (true) {
+ // Skip over over regular characters and append them.
+ size_t regular = quoted.find_first_of(k_escapable_characters);
+ result += quoted.substr(0, regular);
+ quoted = quoted.substr(regular);
+
+ // If we have reached the end of string or the closing quote, we're done.
+ if (quoted.empty() || quoted.front() == '"')
+ break;
+
+ // We have found a backslash.
+ quoted = quoted.drop_front();
+
+ if (quoted.empty()) {
+ // A lone backslash at the end of string, let's just append it.
+ result += '\\';
+ break;
+ }
+
+ // If the character after the backslash is not a whitelisted escapable
+ // character, we leave the character sequence untouched.
+ if (strchr(k_escapable_characters, quoted.front()) == nullptr)
+ result += '\\';
+
+ result += quoted.front();
+ quoted = quoted.drop_front();
+ }
+
+ return quoted;
+}
+
+static size_t ArgvToArgc(const char **argv) {
+ if (!argv)
+ return 0;
+ size_t count = 0;
+ while (*argv++)
+ ++count;
+ return count;
+}
+
+// Trims all whitespace that can separate command line arguments from the left
+// side of the string.
+static llvm::StringRef ltrimForArgs(llvm::StringRef str) {
+ static const char *k_space_separators = " \t";
+ return str.ltrim(k_space_separators);
+}
+
+// A helper function for SetCommandString. Parses a single argument from the
+// command string, processing quotes and backslashes in a shell-like manner.
+// The function returns a tuple consisting of the parsed argument, the quote
+// char used, and the unparsed portion of the string starting at the first
+// unqouted, unescaped whitespace character.
+static std::tuple<std::string, char, llvm::StringRef>
+ParseSingleArgument(llvm::StringRef command) {
+ // Argument can be split into multiple discontiguous pieces, for example:
+ // "Hello ""World"
+ // this would result in a single argument "Hello World" (without the quotes)
+ // since the quotes would be removed and there is not space between the
+ // strings.
+ std::string arg;
+
+ // Since we can have multiple quotes that form a single command in a command
+ // like: "Hello "world'!' (which will make a single argument "Hello world!")
+ // we remember the first quote character we encounter and use that for the
+ // quote character.
+ char first_quote_char = '\0';
+
+ bool arg_complete = false;
+ do {
+ // Skip over over regular characters and append them.
+ size_t regular = command.find_first_of(" \t\"'`\\");
+ arg += command.substr(0, regular);
+ command = command.substr(regular);
+
+ if (command.empty())
+ break;
+
+ char special = command.front();
+ command = command.drop_front();
+ switch (special) {
+ case '\\':
+ if (command.empty()) {
+ arg += '\\';
+ break;
+ }
+
+ // If the character after the backslash is not a whitelisted escapable
+ // character, we leave the character sequence untouched.
+ if (strchr(" \t\\'\"`", command.front()) == nullptr)
+ arg += '\\';
+
+ arg += command.front();
+ command = command.drop_front();
+
+ break;
+
+ case ' ':
+ case '\t':
+ // We are not inside any quotes, we just found a space after an argument.
+ // We are done.
+ arg_complete = true;
+ break;
+
+ case '"':
+ case '\'':
+ case '`':
+ // We found the start of a quote scope.
+ if (first_quote_char == '\0')
+ first_quote_char = special;
+
+ if (special == '"')
+ command = ParseDoubleQuotes(command, arg);
+ else {
+ // For single quotes, we simply skip ahead to the matching quote
+ // character (or the end of the string).
+ size_t quoted = command.find(special);
+ arg += command.substr(0, quoted);
+ command = command.substr(quoted);
+ }
+
+ // If we found a closing quote, skip it.
+ if (!command.empty())
+ command = command.drop_front();
+
+ break;
+ }
+ } while (!arg_complete);
+
+ return std::make_tuple(arg, first_quote_char, command);
+}
+
+Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) {
+ size_t size = str.size();
+ ptr.reset(new char[size + 1]);
+
+ ::memcpy(data(), str.data() ? str.data() : "", size);
+ ptr[size] = 0;
+ ref = llvm::StringRef(c_str(), size);
+}
+
+//----------------------------------------------------------------------
+// Args constructor
+//----------------------------------------------------------------------
+Args::Args(llvm::StringRef command) { SetCommandString(command); }
+
+Args::Args(const Args &rhs) { *this = rhs; }
+
+Args::Args(const StringList &list) : Args() {
+ for (size_t i = 0; i < list.GetSize(); ++i)
+ AppendArgument(list[i]);
+}
+
+Args &Args::operator=(const Args &rhs) {
+ Clear();
+
+ m_argv.clear();
+ m_entries.clear();
+ for (auto &entry : rhs.m_entries) {
+ m_entries.emplace_back(entry.ref, entry.quote);
+ m_argv.push_back(m_entries.back().data());
+ }
+ m_argv.push_back(nullptr);
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Args::~Args() {}
+
+void Args::Dump(Stream &s, const char *label_name) const {
+ if (!label_name)
+ return;
+
+ int i = 0;
+ for (auto &entry : m_entries) {
+ s.Indent();
+ s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref);
+ }
+ s.Format("{0}[{1}]=NULL\n", label_name, i);
+ s.EOL();
+}
+
+bool Args::GetCommandString(std::string &command) const {
+ command.clear();
+
+ for (size_t i = 0; i < m_entries.size(); ++i) {
+ if (i > 0)
+ command += ' ';
+ command += m_entries[i].ref;
+ }
+
+ return !m_entries.empty();
+}
+
+bool Args::GetQuotedCommandString(std::string &command) const {
+ command.clear();
+
+ for (size_t i = 0; i < m_entries.size(); ++i) {
+ if (i > 0)
+ command += ' ';
+
+ if (m_entries[i].quote) {
+ command += m_entries[i].quote;
+ command += m_entries[i].ref;
+ command += m_entries[i].quote;
+ } else {
+ command += m_entries[i].ref;
+ }
+ }
+
+ return !m_entries.empty();
+}
+
+void Args::SetCommandString(llvm::StringRef command) {
+ Clear();
+ m_argv.clear();
+
+ command = ltrimForArgs(command);
+ std::string arg;
+ char quote;
+ while (!command.empty()) {
+ std::tie(arg, quote, command) = ParseSingleArgument(command);
+ m_entries.emplace_back(arg, quote);
+ m_argv.push_back(m_entries.back().data());
+ command = ltrimForArgs(command);
+ }
+ m_argv.push_back(nullptr);
+}
+
+size_t Args::GetArgumentCount() const { return m_entries.size(); }
+
+const char *Args::GetArgumentAtIndex(size_t idx) const {
+ if (idx < m_argv.size())
+ return m_argv[idx];
+ return nullptr;
+}
+
+char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
+ if (idx < m_entries.size())
+ return m_entries[idx].quote;
+ return '\0';
+}
+
+char **Args::GetArgumentVector() {
+ assert(!m_argv.empty());
+ // TODO: functions like execve and posix_spawnp exhibit undefined behavior
+ // when argv or envp is null. So the code below is actually wrong. However,
+ // other code in LLDB depends on it being null. The code has been acting
+ // this way for some time, so it makes sense to leave it this way until
+ // someone has the time to come along and fix it.
+ return (m_argv.size() > 1) ? m_argv.data() : nullptr;
+}
+
+const char **Args::GetConstArgumentVector() const {
+ assert(!m_argv.empty());
+ return (m_argv.size() > 1) ? const_cast<const char **>(m_argv.data())
+ : nullptr;
+}
+
+void Args::Shift() {
+ // Don't pop the last NULL terminator from the argv array
+ if (m_entries.empty())
+ return;
+ m_argv.erase(m_argv.begin());
+ m_entries.erase(m_entries.begin());
+}
+
+void Args::Unshift(llvm::StringRef arg_str, char quote_char) {
+ InsertArgumentAtIndex(0, arg_str, quote_char);
+}
+
+void Args::AppendArguments(const Args &rhs) {
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+ m_argv.pop_back();
+ for (auto &entry : rhs.m_entries) {
+ m_entries.emplace_back(entry.ref, entry.quote);
+ m_argv.push_back(m_entries.back().data());
+ }
+ m_argv.push_back(nullptr);
+}
+
+void Args::AppendArguments(const char **argv) {
+ size_t argc = ArgvToArgc(argv);
+
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+ m_argv.pop_back();
+ for (auto arg : llvm::makeArrayRef(argv, argc)) {
+ m_entries.emplace_back(arg, '\0');
+ m_argv.push_back(m_entries.back().data());
+ }
+
+ m_argv.push_back(nullptr);
+}
+
+void Args::AppendArgument(llvm::StringRef arg_str, char quote_char) {
+ InsertArgumentAtIndex(GetArgumentCount(), arg_str, quote_char);
+}
+
+void Args::InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
+ char quote_char) {
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+
+ if (idx > m_entries.size())
+ return;
+ m_entries.emplace(m_entries.begin() + idx, arg_str, quote_char);
+ m_argv.insert(m_argv.begin() + idx, m_entries[idx].data());
+}
+
+void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
+ char quote_char) {
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+
+ if (idx >= m_entries.size())
+ return;
+
+ if (arg_str.size() > m_entries[idx].ref.size()) {
+ m_entries[idx] = ArgEntry(arg_str, quote_char);
+ m_argv[idx] = m_entries[idx].data();
+ } else {
+ const char *src_data = arg_str.data() ? arg_str.data() : "";
+ ::memcpy(m_entries[idx].data(), src_data, arg_str.size());
+ m_entries[idx].ptr[arg_str.size()] = 0;
+ m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size());
+ }
+}
+
+void Args::DeleteArgumentAtIndex(size_t idx) {
+ if (idx >= m_entries.size())
+ return;
+
+ m_argv.erase(m_argv.begin() + idx);
+ m_entries.erase(m_entries.begin() + idx);
+}
+
+void Args::SetArguments(size_t argc, const char **argv) {
+ Clear();
+
+ auto args = llvm::makeArrayRef(argv, argc);
+ m_entries.resize(argc);
+ m_argv.resize(argc + 1);
+ for (size_t i = 0; i < args.size(); ++i) {
+ char quote =
+ ((args[i][0] == '\'') || (args[i][0] == '"') || (args[i][0] == '`'))
+ ? args[i][0]
+ : '\0';
+
+ m_entries[i] = ArgEntry(args[i], quote);
+ m_argv[i] = m_entries[i].data();
+ }
+}
+
+void Args::SetArguments(const char **argv) {
+ SetArguments(ArgvToArgc(argv), argv);
+}
+
+void Args::Clear() {
+ m_entries.clear();
+ m_argv.clear();
+ m_argv.push_back(nullptr);
+}
+
+const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
+ bool return_null_if_empty) {
+ static const char *k_white_space = " \t\v";
+ if (!s.empty()) {
+ if (leading) {
+ size_t pos = s.find_first_not_of(k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos > 0)
+ s.erase(0, pos);
+ }
+
+ if (trailing) {
+ size_t rpos = s.find_last_not_of(k_white_space);
+ if (rpos != std::string::npos && rpos + 1 < s.size())
+ s.erase(rpos + 1);
+ }
+ }
+ if (return_null_if_empty && s.empty())
+ return nullptr;
+ return s.c_str();
+}
+
+const char *Args::GetShellSafeArgument(const FileSpec &shell,
+ const char *unsafe_arg,
+ std::string &safe_arg) {
+ struct ShellDescriptor {
+ ConstString m_basename;
+ const char *m_escapables;
+ };
+
+ static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
+ {ConstString("tcsh"), " '\"<>()&$"},
+ {ConstString("sh"), " '\"<>()&"}};
+
+ // safe minimal set
+ const char *escapables = " '\"";
+
+ if (auto basename = shell.GetFilename()) {
+ for (const auto &Shell : g_Shells) {
+ if (Shell.m_basename == basename) {
+ escapables = Shell.m_escapables;
+ break;
+ }
+ }
+ }
+
+ safe_arg.assign(unsafe_arg);
+ size_t prev_pos = 0;
+ while (prev_pos < safe_arg.size()) {
+ // Escape spaces and quotes
+ size_t pos = safe_arg.find_first_of(escapables, prev_pos);
+ if (pos != std::string::npos) {
+ safe_arg.insert(pos, 1, '\\');
+ prev_pos = pos + 2;
+ } else
+ break;
+ }
+ return safe_arg.c_str();
+}
+
+lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
+ lldb::Encoding fail_value) {
+ return llvm::StringSwitch<lldb::Encoding>(s)
+ .Case("uint", eEncodingUint)
+ .Case("sint", eEncodingSint)
+ .Case("ieee754", eEncodingIEEE754)
+ .Case("vector", eEncodingVector)
+ .Default(fail_value);
+}
+
+uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
+ if (s.empty())
+ return LLDB_INVALID_REGNUM;
+ uint32_t result = llvm::StringSwitch<uint32_t>(s)
+ .Case("pc", LLDB_REGNUM_GENERIC_PC)
+ .Case("sp", LLDB_REGNUM_GENERIC_SP)
+ .Case("fp", LLDB_REGNUM_GENERIC_FP)
+ .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
+ .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
+ .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
+ .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
+ .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
+ .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
+ .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
+ .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
+ .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
+ .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
+ .Default(LLDB_INVALID_REGNUM);
+ return result;
+}
+
+void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
+ dst.clear();
+ if (src) {
+ for (const char *p = src; *p != '\0'; ++p) {
+ size_t non_special_chars = ::strcspn(p, "\\");
+ if (non_special_chars > 0) {
+ dst.append(p, non_special_chars);
+ p += non_special_chars;
+ if (*p == '\0')
+ break;
+ }
+
+ if (*p == '\\') {
+ ++p; // skip the slash
+ switch (*p) {
+ case 'a':
+ dst.append(1, '\a');
+ break;
+ case 'b':
+ dst.append(1, '\b');
+ break;
+ case 'f':
+ dst.append(1, '\f');
+ break;
+ case 'n':
+ dst.append(1, '\n');
+ break;
+ case 'r':
+ dst.append(1, '\r');
+ break;
+ case 't':
+ dst.append(1, '\t');
+ break;
+ case 'v':
+ dst.append(1, '\v');
+ break;
+ case '\\':
+ dst.append(1, '\\');
+ break;
+ case '\'':
+ dst.append(1, '\'');
+ break;
+ case '"':
+ dst.append(1, '"');
+ break;
+ case '0':
+ // 1 to 3 octal chars
+ {
+ // Make a string that can hold onto the initial zero char, up to 3
+ // octal digits, and a terminating NULL.
+ char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
+
+ int i;
+ for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
+ oct_str[i] = p[i];
+
+ // We don't want to consume the last octal character since the main
+ // for loop will do this for us, so we advance p by one less than i
+ // (even if i is zero)
+ p += i - 1;
+ unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
+ if (octal_value <= UINT8_MAX) {
+ dst.append(1, (char)octal_value);
+ }
+ }
+ break;
+
+ case 'x':
+ // hex number in the format
+ if (isxdigit(p[1])) {
+ ++p; // Skip the 'x'
+
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = {*p, '\0', '\0'};
+ if (isxdigit(p[1])) {
+ ++p; // Skip the first of the two hex chars
+ hex_str[1] = *p;
+ }
+
+ unsigned long hex_value = strtoul(hex_str, nullptr, 16);
+ if (hex_value <= UINT8_MAX)
+ dst.append(1, (char)hex_value);
+ } else {
+ dst.append(1, 'x');
+ }
+ break;
+
+ default:
+ // Just desensitize any other character by just printing what came
+ // after the '\'
+ dst.append(1, *p);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
+ dst.clear();
+ if (src) {
+ for (const char *p = src; *p != '\0'; ++p) {
+ if (isprint(*p))
+ dst.append(1, *p);
+ else {
+ switch (*p) {
+ case '\a':
+ dst.append("\\a");
+ break;
+ case '\b':
+ dst.append("\\b");
+ break;
+ case '\f':
+ dst.append("\\f");
+ break;
+ case '\n':
+ dst.append("\\n");
+ break;
+ case '\r':
+ dst.append("\\r");
+ break;
+ case '\t':
+ dst.append("\\t");
+ break;
+ case '\v':
+ dst.append("\\v");
+ break;
+ case '\'':
+ dst.append("\\'");
+ break;
+ case '"':
+ dst.append("\\\"");
+ break;
+ case '\\':
+ dst.append("\\\\");
+ break;
+ default: {
+ // Just encode as octal
+ dst.append("\\0");
+ char octal_str[32];
+ snprintf(octal_str, sizeof(octal_str), "%o", *p);
+ dst.append(octal_str);
+ } break;
+ }
+ }
+ }
+ }
+}
+
+std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
+ char quote_char) {
+ const char *chars_to_escape = nullptr;
+ switch (quote_char) {
+ case '\0':
+ chars_to_escape = " \t\\'\"`";
+ break;
+ case '\'':
+ chars_to_escape = "";
+ break;
+ case '"':
+ chars_to_escape = "$\"`\\";
+ break;
+ default:
+ assert(false && "Unhandled quote character");
+ }
+
+ std::string res;
+ res.reserve(arg.size());
+ for (char c : arg) {
+ if (::strchr(chars_to_escape, c))
+ res.push_back('\\');
+ res.push_back(c);
+ }
+ return res;
+}
+
+OptionsWithRaw::OptionsWithRaw(llvm::StringRef arg_string) {
+ SetFromString(arg_string);
+}
+
+void OptionsWithRaw::SetFromString(llvm::StringRef arg_string) {
+ const llvm::StringRef original_args = arg_string;
+
+ arg_string = ltrimForArgs(arg_string);
+ std::string arg;
+ char quote;
+
+ // If the string doesn't start with a dash, we just have no options and just
+ // a raw part.
+ if (!arg_string.startswith("-")) {
+ m_suffix = original_args;
+ return;
+ }
+
+ bool found_suffix = false;
+
+ while (!arg_string.empty()) {
+ // The length of the prefix before parsing.
+ std::size_t prev_prefix_length = original_args.size() - arg_string.size();
+
+ // Parse the next argument from the remaining string.
+ std::tie(arg, quote, arg_string) = ParseSingleArgument(arg_string);
+
+ // If we get an unquoted '--' argument, then we reached the suffix part
+ // of the command.
+ Args::ArgEntry entry(arg, quote);
+ if (!entry.IsQuoted() && arg == "--") {
+ // The remaining line is the raw suffix, and the line we parsed so far
+ // needs to be interpreted as arguments.
+ m_has_args = true;
+ m_suffix = arg_string;
+ found_suffix = true;
+
+ // The length of the prefix after parsing.
+ std::size_t prefix_length = original_args.size() - arg_string.size();
+
+ // Take the string we know contains all the arguments and actually parse
+ // it as proper arguments.
+ llvm::StringRef prefix = original_args.take_front(prev_prefix_length);
+ m_args = Args(prefix);
+ m_arg_string = prefix;
+
+ // We also record the part of the string that contains the arguments plus
+ // the delimiter.
+ m_arg_string_with_delimiter = original_args.take_front(prefix_length);
+
+ // As the rest of the string became the raw suffix, we are done here.
+ break;
+ }
+
+ arg_string = ltrimForArgs(arg_string);
+ }
+
+ // If we didn't find a suffix delimiter, the whole string is the raw suffix.
+ if (!found_suffix) {
+ found_suffix = true;
+ m_suffix = original_args;
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Utility/CompletionRequest.cpp b/contrib/llvm/tools/lldb/source/Utility/CompletionRequest.cpp
new file mode 100644
index 000000000000..c88747e2abe3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/CompletionRequest.cpp
@@ -0,0 +1,60 @@
+//===-- CompletionRequest.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/CompletionRequest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CompletionRequest::CompletionRequest(llvm::StringRef command_line,
+ unsigned raw_cursor_pos,
+ int match_start_point,
+ int max_return_elements,
+ StringList &matches)
+ : m_command(command_line), m_raw_cursor_pos(raw_cursor_pos),
+ m_match_start_point(match_start_point),
+ m_max_return_elements(max_return_elements), m_matches(&matches) {
+ matches.Clear();
+
+ // We parse the argument up to the cursor, so the last argument in
+ // parsed_line is the one containing the cursor, and the cursor is after the
+ // last character.
+ m_parsed_line = Args(command_line);
+ m_partial_parsed_line = Args(command_line.substr(0, raw_cursor_pos));
+
+ m_cursor_index = m_partial_parsed_line.GetArgumentCount() - 1;
+
+ if (m_cursor_index == -1)
+ m_cursor_char_position = 0;
+ else
+ m_cursor_char_position =
+ strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index));
+
+ matches.Clear();
+
+ const char *cursor = command_line.data() + raw_cursor_pos;
+ if (raw_cursor_pos > 0 && cursor[-1] == ' ') {
+ // We are just after a space. If we are in an argument, then we will
+ // continue parsing, but if we are between arguments, then we have to
+ // complete whatever the next element would be. We can distinguish the two
+ // cases because if we are in an argument (e.g. because the space is
+ // protected by a quote) then the space will also be in the parsed
+ // argument...
+
+ const char *current_elem =
+ m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index);
+ if (m_cursor_char_position == 0 ||
+ current_elem[m_cursor_char_position - 1] != ' ') {
+ m_parsed_line.InsertArgumentAtIndex(m_cursor_index + 1, llvm::StringRef(),
+ '\0');
+ m_cursor_index++;
+ m_cursor_char_position = 0;
+ }
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Utility/ConstString.cpp b/contrib/llvm/tools/lldb/source/Utility/ConstString.cpp
index 49cf8a6d864d..5ef4b2faa3b8 100644
--- a/contrib/llvm/tools/lldb/source/Utility/ConstString.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/ConstString.cpp
@@ -11,10 +11,10 @@
#include "lldb/Utility/Stream.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator.h" // for iterator_facade_base
#include "llvm/Support/Allocator.h" // for BumpPtrAllocator
+#include "llvm/Support/DJB.h" // for djbHash
#include "llvm/Support/FormatProviders.h" // for format_provider
#include "llvm/Support/RWMutex.h"
#include "llvm/Support/Threading.h"
@@ -43,8 +43,8 @@ public:
static size_t GetConstCStringLength(const char *ccstr) {
if (ccstr != nullptr) {
- // Since the entry is read only, and we derive the entry entirely from the
- // pointer, we don't need the lock.
+ // Since the entry is read only, and we derive the entry entirely from
+ // the pointer, we don't need the lock.
const StringPoolEntryType &entry = GetStringMapEntryFromKeyData(ccstr);
return entry.getKey().size();
}
@@ -155,9 +155,8 @@ public:
}
//------------------------------------------------------------------
- // Return the size in bytes that this object and any items in its
- // collection of uniqued strings + data count values takes in
- // memory.
+ // Return the size in bytes that this object and any items in its collection
+ // of uniqued strings + data count values takes in memory.
//------------------------------------------------------------------
size_t MemorySize() const {
size_t mem_size = sizeof(Pool);
@@ -171,7 +170,7 @@ public:
protected:
uint8_t hash(const llvm::StringRef &s) const {
- uint32_t h = llvm::HashString(s);
+ uint32_t h = llvm::djbHash(s);
return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff;
}
@@ -184,15 +183,14 @@ protected:
};
//----------------------------------------------------------------------
-// Frameworks and dylibs aren't supposed to have global C++
-// initializers so we hide the string pool in a static function so
-// that it will get initialized on the first call to this static
-// function.
+// Frameworks and dylibs aren't supposed to have global C++ initializers so we
+// hide the string pool in a static function so that it will get initialized on
+// the first call to this static function.
//
-// Note, for now we make the string pool a pointer to the pool, because
-// we can't guarantee that some objects won't get destroyed after the
-// global destructor chain is run, and trying to make sure no destructors
-// touch ConstStrings is difficult. So we leak the pool instead.
+// Note, for now we make the string pool a pointer to the pool, because we
+// can't guarantee that some objects won't get destroyed after the global
+// destructor chain is run, and trying to make sure no destructors touch
+// ConstStrings is difficult. So we leak the pool instead.
//----------------------------------------------------------------------
static Pool &StringPool() {
static llvm::once_flag g_pool_initialization_flag;
@@ -246,8 +244,8 @@ bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs,
return true;
// Since the pointers weren't equal, and identical ConstStrings always have
- // identical pointers,
- // the result must be false for case sensitive equality test.
+ // identical pointers, the result must be false for case sensitive equality
+ // test.
if (case_sensitive)
return false;
diff --git a/contrib/llvm/tools/lldb/source/Utility/DataBufferHeap.cpp b/contrib/llvm/tools/lldb/source/Utility/DataBufferHeap.cpp
index aa1c3d37ae62..e686ee8d35e5 100644
--- a/contrib/llvm/tools/lldb/source/Utility/DataBufferHeap.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/DataBufferHeap.cpp
@@ -22,8 +22,7 @@ using namespace lldb_private;
DataBufferHeap::DataBufferHeap() : m_data() {}
//----------------------------------------------------------------------
-// Initialize this class with "n" characters and fill the buffer
-// with "ch".
+// Initialize this class with "n" characters and fill the buffer with "ch".
//----------------------------------------------------------------------
DataBufferHeap::DataBufferHeap(lldb::offset_t n, uint8_t ch) : m_data() {
if (n < m_data.max_size())
@@ -31,8 +30,7 @@ DataBufferHeap::DataBufferHeap(lldb::offset_t n, uint8_t ch) : m_data() {
}
//----------------------------------------------------------------------
-// Initialize this class with a copy of the "n" bytes from the "bytes"
-// buffer.
+// Initialize this class with a copy of the "n" bytes from the "bytes" buffer.
//----------------------------------------------------------------------
DataBufferHeap::DataBufferHeap(const void *src, lldb::offset_t src_len)
: m_data() {
@@ -40,22 +38,21 @@ DataBufferHeap::DataBufferHeap(const void *src, lldb::offset_t src_len)
}
//----------------------------------------------------------------------
-// Virtual destructor since this class inherits from a pure virtual
-// base class.
+// Virtual destructor since this class inherits from a pure virtual base class.
//----------------------------------------------------------------------
DataBufferHeap::~DataBufferHeap() = default;
//----------------------------------------------------------------------
-// Return a pointer to the bytes owned by this object, or nullptr if
-// the object contains no bytes.
+// Return a pointer to the bytes owned by this object, or nullptr if the object
+// contains no bytes.
//----------------------------------------------------------------------
uint8_t *DataBufferHeap::GetBytes() {
return (m_data.empty() ? nullptr : m_data.data());
}
//----------------------------------------------------------------------
-// Return a const pointer to the bytes owned by this object, or nullptr
-// if the object contains no bytes.
+// Return a const pointer to the bytes owned by this object, or nullptr if the
+// object contains no bytes.
//----------------------------------------------------------------------
const uint8_t *DataBufferHeap::GetBytes() const {
return (m_data.empty() ? nullptr : m_data.data());
@@ -67,8 +64,8 @@ const uint8_t *DataBufferHeap::GetBytes() const {
uint64_t DataBufferHeap::GetByteSize() const { return m_data.size(); }
//----------------------------------------------------------------------
-// Sets the number of bytes that this object should be able to
-// contain. This can be used prior to copying data into the buffer.
+// Sets the number of bytes that this object should be able to contain. This
+// can be used prior to copying data into the buffer.
//----------------------------------------------------------------------
uint64_t DataBufferHeap::SetByteSize(uint64_t new_size) {
m_data.resize(new_size);
diff --git a/contrib/llvm/tools/lldb/source/Utility/DataEncoder.cpp b/contrib/llvm/tools/lldb/source/Utility/DataEncoder.cpp
index 433a15bc9523..7edee3c2f279 100644
--- a/contrib/llvm/tools/lldb/source/Utility/DataEncoder.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/DataEncoder.cpp
@@ -34,8 +34,8 @@ DataEncoder::DataEncoder()
m_data_sp() {}
//----------------------------------------------------------------------
-// This constructor allows us to use data that is owned by someone else.
-// The data must stay around as long as this object is valid.
+// This constructor allows us to use data that is owned by someone else. The
+// data must stay around as long as this object is valid.
//----------------------------------------------------------------------
DataEncoder::DataEncoder(void *data, uint32_t length, ByteOrder endian,
uint8_t addr_size)
@@ -43,11 +43,10 @@ DataEncoder::DataEncoder(void *data, uint32_t length, ByteOrder endian,
m_byte_order(endian), m_addr_size(addr_size), m_data_sp() {}
//----------------------------------------------------------------------
-// Make a shared pointer reference to the shared data in "data_sp" and
-// set the endian swapping setting to "swap", and the address size to
-// "addr_size". The shared data reference will ensure the data lives
-// as long as any DataEncoder objects exist that have a reference to
-// this data.
+// Make a shared pointer reference to the shared data in "data_sp" and set the
+// endian swapping setting to "swap", and the address size to "addr_size". The
+// shared data reference will ensure the data lives as long as any DataEncoder
+// objects exist that have a reference to this data.
//----------------------------------------------------------------------
DataEncoder::DataEncoder(const DataBufferSP &data_sp, ByteOrder endian,
uint8_t addr_size)
@@ -59,9 +58,8 @@ DataEncoder::DataEncoder(const DataBufferSP &data_sp, ByteOrder endian,
DataEncoder::~DataEncoder() = default;
//------------------------------------------------------------------
-// Clears the object contents back to a default invalid state, and
-// release any references to shared data that this object may
-// contain.
+// Clears the object contents back to a default invalid state, and release any
+// references to shared data that this object may contain.
//------------------------------------------------------------------
void DataEncoder::Clear() {
m_start = nullptr;
@@ -72,8 +70,8 @@ void DataEncoder::Clear() {
}
//------------------------------------------------------------------
-// If this object contains shared data, this function returns the
-// offset into that shared data. Else zero is returned.
+// If this object contains shared data, this function returns the offset into
+// that shared data. Else zero is returned.
//------------------------------------------------------------------
size_t DataEncoder::GetSharedDataOffset() const {
if (m_start != nullptr) {
@@ -90,13 +88,12 @@ size_t DataEncoder::GetSharedDataOffset() const {
}
//----------------------------------------------------------------------
-// Set the data with which this object will extract from to data
-// starting at BYTES and set the length of the data to LENGTH bytes
-// long. The data is externally owned must be around at least as
-// long as this object points to the data. No copy of the data is
-// made, this object just refers to this data and can extract from
-// it. If this object refers to any shared data upon entry, the
-// reference to that data will be released. Is SWAP is set to true,
+// Set the data with which this object will extract from to data starting at
+// BYTES and set the length of the data to LENGTH bytes long. The data is
+// externally owned must be around at least as long as this object points to
+// the data. No copy of the data is made, this object just refers to this data
+// and can extract from it. If this object refers to any shared data upon
+// entry, the reference to that data will be released. Is SWAP is set to true,
// any data extracted will be endian swapped.
//----------------------------------------------------------------------
uint32_t DataEncoder::SetData(void *bytes, uint32_t length, ByteOrder endian) {
@@ -113,18 +110,17 @@ uint32_t DataEncoder::SetData(void *bytes, uint32_t length, ByteOrder endian) {
}
//----------------------------------------------------------------------
-// Assign the data for this object to be a subrange of the shared
-// data in "data_sp" starting "data_offset" bytes into "data_sp"
-// and ending "data_length" bytes later. If "data_offset" is not
-// a valid offset into "data_sp", then this object will contain no
-// bytes. If "data_offset" is within "data_sp" yet "data_length" is
-// too large, the length will be capped at the number of bytes
-// remaining in "data_sp". A ref counted pointer to the data in
-// "data_sp" will be made in this object IF the number of bytes this
-// object refers to in greater than zero (if at least one byte was
-// available starting at "data_offset") to ensure the data stays
-// around as long as it is needed. The address size and endian swap
-// settings will remain unchanged from their current settings.
+// Assign the data for this object to be a subrange of the shared data in
+// "data_sp" starting "data_offset" bytes into "data_sp" and ending
+// "data_length" bytes later. If "data_offset" is not a valid offset into
+// "data_sp", then this object will contain no bytes. If "data_offset" is
+// within "data_sp" yet "data_length" is too large, the length will be capped
+// at the number of bytes remaining in "data_sp". A ref counted pointer to the
+// data in "data_sp" will be made in this object IF the number of bytes this
+// object refers to in greater than zero (if at least one byte was available
+// starting at "data_offset") to ensure the data stays around as long as it is
+// needed. The address size and endian swap settings will remain unchanged from
+// their current settings.
//----------------------------------------------------------------------
uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset,
uint32_t data_length) {
@@ -149,8 +145,8 @@ uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset,
uint32_t new_size = GetByteSize();
- // Don't hold a shared pointer to the data buffer if we don't share
- // any valid bytes in the shared buffer.
+ // Don't hold a shared pointer to the data buffer if we don't share any valid
+ // bytes in the shared buffer.
if (new_size == 0)
m_data_sp.reset();
@@ -158,8 +154,8 @@ uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset,
}
//----------------------------------------------------------------------
-// Extract a single unsigned char from the binary data and update
-// the offset pointed to by "offset_ptr".
+// Extract a single unsigned char from the binary data and update the offset
+// pointed to by "offset_ptr".
//
// RETURNS the byte that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -208,12 +204,12 @@ uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) {
}
//----------------------------------------------------------------------
-// Extract a single integer value from the data and update the offset
-// pointed to by "offset_ptr". The size of the extracted integer
-// is specified by the "byte_size" argument. "byte_size" should have
-// a value >= 1 and <= 8 since the return value is only 64 bits
-// wide. Any "byte_size" values less than 1 or greater than 8 will
-// result in nothing being extracted, and zero being returned.
+// Extract a single integer value from the data and update the offset pointed
+// to by "offset_ptr". The size of the extracted integer is specified by the
+// "byte_size" argument. "byte_size" should have a value >= 1 and <= 8 since
+// the return value is only 64 bits wide. Any "byte_size" values less than 1 or
+// greater than 8 will result in nothing being extracted, and zero being
+// returned.
//
// RETURNS the integer value that was extracted, or zero on failure.
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Utility/DataExtractor.cpp b/contrib/llvm/tools/lldb/source/Utility/DataExtractor.cpp
index 84c5f8191521..947232943aa7 100644
--- a/contrib/llvm/tools/lldb/source/Utility/DataExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/DataExtractor.cpp
@@ -126,8 +126,8 @@ DataExtractor::DataExtractor()
m_data_sp(), m_target_byte_size(1) {}
//----------------------------------------------------------------------
-// This constructor allows us to use data that is owned by someone else.
-// The data must stay around as long as this object is valid.
+// This constructor allows us to use data that is owned by someone else. The
+// data must stay around as long as this object is valid.
//----------------------------------------------------------------------
DataExtractor::DataExtractor(const void *data, offset_t length,
ByteOrder endian, uint32_t addr_size,
@@ -143,11 +143,10 @@ DataExtractor::DataExtractor(const void *data, offset_t length,
}
//----------------------------------------------------------------------
-// Make a shared pointer reference to the shared data in "data_sp" and
-// set the endian swapping setting to "swap", and the address size to
-// "addr_size". The shared data reference will ensure the data lives
-// as long as any DataExtractor objects exist that have a reference to
-// this data.
+// Make a shared pointer reference to the shared data in "data_sp" and set the
+// endian swapping setting to "swap", and the address size to "addr_size". The
+// shared data reference will ensure the data lives as long as any
+// DataExtractor objects exist that have a reference to this data.
//----------------------------------------------------------------------
DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
uint32_t addr_size,
@@ -162,11 +161,11 @@ DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
}
//----------------------------------------------------------------------
-// Initialize this object with a subset of the data bytes in "data".
-// If "data" contains shared data, then a reference to this shared
-// data will added and the shared data will stay around as long
-// as any object contains a reference to that data. The endian
-// swap and address size settings are copied from "data".
+// Initialize this object with a subset of the data bytes in "data". If "data"
+// contains shared data, then a reference to this shared data will added and
+// the shared data will stay around as long as any object contains a reference
+// to that data. The endian swap and address size settings are copied from
+// "data".
//----------------------------------------------------------------------
DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset,
offset_t length, uint32_t target_byte_size /*=1*/)
@@ -210,9 +209,8 @@ const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) {
DataExtractor::~DataExtractor() = default;
//------------------------------------------------------------------
-// Clears the object contents back to a default invalid state, and
-// release any references to shared data that this object may
-// contain.
+// Clears the object contents back to a default invalid state, and release any
+// references to shared data that this object may contain.
//------------------------------------------------------------------
void DataExtractor::Clear() {
m_start = nullptr;
@@ -223,8 +221,8 @@ void DataExtractor::Clear() {
}
//------------------------------------------------------------------
-// If this object contains shared data, this function returns the
-// offset into that shared data. Else zero is returned.
+// If this object contains shared data, this function returns the offset into
+// that shared data. Else zero is returned.
//------------------------------------------------------------------
size_t DataExtractor::GetSharedDataOffset() const {
if (m_start != nullptr) {
@@ -241,13 +239,12 @@ size_t DataExtractor::GetSharedDataOffset() const {
}
//----------------------------------------------------------------------
-// Set the data with which this object will extract from to data
-// starting at BYTES and set the length of the data to LENGTH bytes
-// long. The data is externally owned must be around at least as
-// long as this object points to the data. No copy of the data is
-// made, this object just refers to this data and can extract from
-// it. If this object refers to any shared data upon entry, the
-// reference to that data will be released. Is SWAP is set to true,
+// Set the data with which this object will extract from to data starting at
+// BYTES and set the length of the data to LENGTH bytes long. The data is
+// externally owned must be around at least as long as this object points to
+// the data. No copy of the data is made, this object just refers to this data
+// and can extract from it. If this object refers to any shared data upon
+// entry, the reference to that data will be released. Is SWAP is set to true,
// any data extracted will be endian swapped.
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
@@ -265,18 +262,16 @@ lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
}
//----------------------------------------------------------------------
-// Assign the data for this object to be a subrange in "data"
-// starting "data_offset" bytes into "data" and ending "data_length"
-// bytes later. If "data_offset" is not a valid offset into "data",
-// then this object will contain no bytes. If "data_offset" is
-// within "data" yet "data_length" is too large, the length will be
-// capped at the number of bytes remaining in "data". If "data"
-// contains a shared pointer to other data, then a ref counted
-// pointer to that data will be made in this object. If "data"
-// doesn't contain a shared pointer to data, then the bytes referred
-// to in "data" will need to exist at least as long as this object
-// refers to those bytes. The address size and endian swap settings
-// are copied from the current values in "data".
+// Assign the data for this object to be a subrange in "data" starting
+// "data_offset" bytes into "data" and ending "data_length" bytes later. If
+// "data_offset" is not a valid offset into "data", then this object will
+// contain no bytes. If "data_offset" is within "data" yet "data_length" is too
+// large, the length will be capped at the number of bytes remaining in "data".
+// If "data" contains a shared pointer to other data, then a ref counted
+// pointer to that data will be made in this object. If "data" doesn't contain
+// a shared pointer to data, then the bytes referred to in "data" will need to
+// exist at least as long as this object refers to those bytes. The address
+// size and endian swap settings are copied from the current values in "data".
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
offset_t data_offset,
@@ -303,18 +298,17 @@ lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
}
//----------------------------------------------------------------------
-// Assign the data for this object to be a subrange of the shared
-// data in "data_sp" starting "data_offset" bytes into "data_sp"
-// and ending "data_length" bytes later. If "data_offset" is not
-// a valid offset into "data_sp", then this object will contain no
-// bytes. If "data_offset" is within "data_sp" yet "data_length" is
-// too large, the length will be capped at the number of bytes
-// remaining in "data_sp". A ref counted pointer to the data in
-// "data_sp" will be made in this object IF the number of bytes this
-// object refers to in greater than zero (if at least one byte was
-// available starting at "data_offset") to ensure the data stays
-// around as long as it is needed. The address size and endian swap
-// settings will remain unchanged from their current settings.
+// Assign the data for this object to be a subrange of the shared data in
+// "data_sp" starting "data_offset" bytes into "data_sp" and ending
+// "data_length" bytes later. If "data_offset" is not a valid offset into
+// "data_sp", then this object will contain no bytes. If "data_offset" is
+// within "data_sp" yet "data_length" is too large, the length will be capped
+// at the number of bytes remaining in "data_sp". A ref counted pointer to the
+// data in "data_sp" will be made in this object IF the number of bytes this
+// object refers to in greater than zero (if at least one byte was available
+// starting at "data_offset") to ensure the data stays around as long as it is
+// needed. The address size and endian swap settings will remain unchanged from
+// their current settings.
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
offset_t data_offset,
@@ -340,8 +334,8 @@ lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
size_t new_size = GetByteSize();
- // Don't hold a shared pointer to the data buffer if we don't share
- // any valid bytes in the shared buffer.
+ // Don't hold a shared pointer to the data buffer if we don't share any valid
+ // bytes in the shared buffer.
if (new_size == 0)
m_data_sp.reset();
@@ -349,8 +343,8 @@ lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
}
//----------------------------------------------------------------------
-// Extract a single unsigned char from the binary data and update
-// the offset pointed to by "offset_ptr".
+// Extract a single unsigned char from the binary data and update the offset
+// pointed to by "offset_ptr".
//
// RETURNS the byte that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -362,13 +356,12 @@ uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extract "count" unsigned chars from the binary data and update the
-// offset pointed to by "offset_ptr". The extracted data is copied into
-// "dst".
+// Extract "count" unsigned chars from the binary data and update the offset
+// pointed to by "offset_ptr". The extracted data is copied into "dst".
//
// RETURNS the non-nullptr buffer pointer upon successful extraction of
-// all the requested bytes, or nullptr when the data is not available in
-// the buffer due to being out of bounds, or insufficient data.
+// all the requested bytes, or nullptr when the data is not available in the
+// buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
uint32_t count) const {
@@ -384,8 +377,8 @@ void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
}
//----------------------------------------------------------------------
-// Extract a single uint16_t from the data and update the offset
-// pointed to by "offset_ptr".
+// Extract a single uint16_t from the data and update the offset pointed to by
+// "offset_ptr".
//
// RETURNS the uint16_t that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -432,13 +425,12 @@ uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extract "count" uint16_t values from the binary data and update
-// the offset pointed to by "offset_ptr". The extracted data is
-// copied into "dst".
+// Extract "count" uint16_t values from the binary data and update the offset
+// pointed to by "offset_ptr". The extracted data is copied into "dst".
//
// RETURNS the non-nullptr buffer pointer upon successful extraction of
-// all the requested bytes, or nullptr when the data is not available
-// in the buffer due to being out of bounds, or insufficient data.
+// all the requested bytes, or nullptr when the data is not available in the
+// buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
uint32_t count) const {
@@ -465,8 +457,8 @@ void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
}
//----------------------------------------------------------------------
-// Extract a single uint32_t from the data and update the offset
-// pointed to by "offset_ptr".
+// Extract a single uint32_t from the data and update the offset pointed to by
+// "offset_ptr".
//
// RETURNS the uint32_t that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -484,13 +476,12 @@ uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extract "count" uint32_t values from the binary data and update
-// the offset pointed to by "offset_ptr". The extracted data is
-// copied into "dst".
+// Extract "count" uint32_t values from the binary data and update the offset
+// pointed to by "offset_ptr". The extracted data is copied into "dst".
//
// RETURNS the non-nullptr buffer pointer upon successful extraction of
-// all the requested bytes, or nullptr when the data is not available
-// in the buffer due to being out of bounds, or insufficient data.
+// all the requested bytes, or nullptr when the data is not available in the
+// buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
uint32_t count) const {
@@ -517,8 +508,8 @@ void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
}
//----------------------------------------------------------------------
-// Extract a single uint64_t from the data and update the offset
-// pointed to by "offset_ptr".
+// Extract a single uint64_t from the data and update the offset pointed to by
+// "offset_ptr".
//
// RETURNS the uint64_t that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -538,9 +529,9 @@ uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const {
//----------------------------------------------------------------------
// GetU64
//
-// Get multiple consecutive 64 bit values. Return true if the entire
-// read succeeds and increment the offset pointed to by offset_ptr, else
-// return false and leave the offset pointed to by offset_ptr unchanged.
+// Get multiple consecutive 64 bit values. Return true if the entire read
+// succeeds and increment the offset pointed to by offset_ptr, else return
+// false and leave the offset pointed to by offset_ptr unchanged.
//----------------------------------------------------------------------
void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst,
uint32_t count) const {
@@ -708,10 +699,10 @@ long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const {
}
//------------------------------------------------------------------
-// Extract a single address from the data and update the offset
-// pointed to by "offset_ptr". The size of the extracted address
-// comes from the "this->m_addr_size" member variable and should be
-// set correctly prior to extracting any address values.
+// Extract a single address from the data and update the offset pointed to by
+// "offset_ptr". The size of the extracted address comes from the
+// "this->m_addr_size" member variable and should be set correctly prior to
+// extracting any address values.
//
// RETURNS the address that was extracted, or zero on failure.
//------------------------------------------------------------------
@@ -730,10 +721,10 @@ uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const {
}
//------------------------------------------------------------------
-// Extract a single pointer from the data and update the offset
-// pointed to by "offset_ptr". The size of the extracted pointer
-// comes from the "this->m_addr_size" member variable and should be
-// set correctly prior to extracting any pointer values.
+// Extract a single pointer from the data and update the offset pointed to by
+// "offset_ptr". The size of the extracted pointer comes from the
+// "this->m_addr_size" member variable and should be set correctly prior to
+// extracting any pointer values.
//
// RETURNS the pointer that was extracted, or zero on failure.
//------------------------------------------------------------------
@@ -804,9 +795,9 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
const uint8_t *src = (const uint8_t *)PeekData(src_offset, src_len);
if (src) {
if (dst_len >= src_len) {
- // We are copying the entire value from src into dst.
- // Calculate how many, if any, zeroes we need for the most
- // significant bytes if "dst_len" is greater than "src_len"...
+ // We are copying the entire value from src into dst. Calculate how many,
+ // if any, zeroes we need for the most significant bytes if "dst_len" is
+ // greater than "src_len"...
const size_t num_zeroes = dst_len - src_len;
if (dst_byte_order == eByteOrderBig) {
// Big endian, so we lead with zeroes...
@@ -863,15 +854,13 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
}
//----------------------------------------------------------------------
-// Extracts a variable length NULL terminated C string from
-// the data at the offset pointed to by "offset_ptr". The
-// "offset_ptr" will be updated with the offset of the byte that
-// follows the NULL terminator byte.
+// Extracts a variable length NULL terminated C string from the data at the
+// offset pointed to by "offset_ptr". The "offset_ptr" will be updated with
+// the offset of the byte that follows the NULL terminator byte.
//
-// If the offset pointed to by "offset_ptr" is out of bounds, or if
-// "length" is non-zero and there aren't enough available
-// bytes, nullptr will be returned and "offset_ptr" will not be
-// updated.
+// If the offset pointed to by "offset_ptr" is out of bounds, or if "length" is
+// non-zero and there aren't enough available bytes, nullptr will be returned
+// and "offset_ptr" will not be updated.
//----------------------------------------------------------------------
const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
const char *cstr = (const char *)PeekData(*offset_ptr, 1);
@@ -890,23 +879,21 @@ const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
}
// We reached the end of the data without finding a NULL C string
- // terminator. Fall through and return nullptr otherwise anyone that
- // would have used the result as a C string can wander into
- // unknown memory...
+ // terminator. Fall through and return nullptr otherwise anyone that would
+ // have used the result as a C string can wander into unknown memory...
}
return nullptr;
}
//----------------------------------------------------------------------
-// Extracts a NULL terminated C string from the fixed length field of
-// length "len" at the offset pointed to by "offset_ptr".
-// The "offset_ptr" will be updated with the offset of the byte that
-// follows the fixed length field.
+// Extracts a NULL terminated C string from the fixed length field of length
+// "len" at the offset pointed to by "offset_ptr". The "offset_ptr" will be
+// updated with the offset of the byte that follows the fixed length field.
//
-// If the offset pointed to by "offset_ptr" is out of bounds, or if
-// the offset plus the length of the field is out of bounds, or if the
-// field does not contain a NULL terminator byte, nullptr will be returned
-// and "offset_ptr" will not be updated.
+// If the offset pointed to by "offset_ptr" is out of bounds, or if the offset
+// plus the length of the field is out of bounds, or if the field does not
+// contain a NULL terminator byte, nullptr will be returned and "offset_ptr"
+// will not be updated.
//----------------------------------------------------------------------
const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
const char *cstr = (const char *)PeekData(*offset_ptr, len);
@@ -921,22 +908,22 @@ const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
}
//------------------------------------------------------------------
-// Peeks at a string in the contained data. No verification is done
-// to make sure the entire string lies within the bounds of this
-// object's data, only "offset" is verified to be a valid offset.
+// Peeks at a string in the contained data. No verification is done to make
+// sure the entire string lies within the bounds of this object's data, only
+// "offset" is verified to be a valid offset.
//
-// Returns a valid C string pointer if "offset" is a valid offset in
-// this object's data, else nullptr is returned.
+// Returns a valid C string pointer if "offset" is a valid offset in this
+// object's data, else nullptr is returned.
//------------------------------------------------------------------
const char *DataExtractor::PeekCStr(offset_t offset) const {
return (const char *)PeekData(offset, 1);
}
//----------------------------------------------------------------------
-// Extracts an unsigned LEB128 number from this object's data
-// starting at the offset pointed to by "offset_ptr". The offset
-// pointed to by "offset_ptr" will be updated with the offset of the
-// byte following the last extracted byte.
+// Extracts an unsigned LEB128 number from this object's data starting at the
+// offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
+// will be updated with the offset of the byte following the last extracted
+// byte.
//
// Returned the extracted integer value.
//----------------------------------------------------------------------
@@ -968,10 +955,10 @@ uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extracts an signed LEB128 number from this object's data
-// starting at the offset pointed to by "offset_ptr". The offset
-// pointed to by "offset_ptr" will be updated with the offset of the
-// byte following the last extracted byte.
+// Extracts an signed LEB128 number from this object's data starting at the
+// offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
+// will be updated with the offset of the byte following the last extracted
+// byte.
//
// Returned the extracted integer value.
//----------------------------------------------------------------------
@@ -1010,10 +997,10 @@ int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Skips a ULEB128 number (signed or unsigned) from this object's
-// data starting at the offset pointed to by "offset_ptr". The
-// offset pointed to by "offset_ptr" will be updated with the offset
-// of the byte following the last extracted byte.
+// Skips a ULEB128 number (signed or unsigned) from this object's data starting
+// at the offset pointed to by "offset_ptr". The offset pointed to by
+// "offset_ptr" will be updated with the offset of the byte following the last
+// extracted byte.
//
// Returns the number of bytes consumed during the extraction.
//----------------------------------------------------------------------
@@ -1036,15 +1023,14 @@ uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
//----------------------------------------------------------------------
// Dumps bytes from this object's data to the stream "s" starting
-// "start_offset" bytes into this data, and ending with the byte
-// before "end_offset". "base_addr" will be added to the offset
-// into the dumped data when showing the offset into the data in the
-// output information. "num_per_line" objects of type "type" will
-// be dumped with the option to override the format for each object
-// with "type_format". "type_format" is a printf style formatting
-// string. If "type_format" is nullptr, then an appropriate format
-// string will be used for the supplied "type". If the stream "s"
-// is nullptr, then the output will be send to Log().
+// "start_offset" bytes into this data, and ending with the byte before
+// "end_offset". "base_addr" will be added to the offset into the dumped data
+// when showing the offset into the data in the output information.
+// "num_per_line" objects of type "type" will be dumped with the option to
+// override the format for each object with "type_format". "type_format" is a
+// printf style formatting string. If "type_format" is nullptr, then an
+// appropriate format string will be used for the supplied "type". If the
+// stream "s" is nullptr, then the output will be send to Log().
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
offset_t length, uint64_t base_addr,
@@ -1107,24 +1093,6 @@ lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
return offset; // Return the offset at which we ended up
}
-//----------------------------------------------------------------------
-// DumpUUID
-//
-// Dump out a UUID starting at 'offset' bytes into the buffer
-//----------------------------------------------------------------------
-void DataExtractor::DumpUUID(Stream *s, offset_t offset) const {
- if (s) {
- const uint8_t *uuid_data = PeekData(offset, 16);
- if (uuid_data) {
- lldb_private::UUID uuid(uuid_data, 16);
- uuid.Dump(s);
- } else {
- s->Printf("<not enough data for UUID at offset 0x%8.8" PRIx64 ">",
- offset);
- }
- }
-}
-
size_t DataExtractor::Copy(DataExtractor &dest_data) const {
if (m_data_sp) {
// we can pass along the SP to the data
diff --git a/contrib/llvm/tools/lldb/source/Utility/Environment.cpp b/contrib/llvm/tools/lldb/source/Utility/Environment.cpp
new file mode 100644
index 000000000000..ea20267a2362
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/Environment.cpp
@@ -0,0 +1,50 @@
+//===-- Environment.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Environment.h"
+
+using namespace lldb_private;
+
+char *Environment::Envp::make_entry(llvm::StringRef Key,
+ llvm::StringRef Value) {
+ const size_t size = Key.size() + 1 /*=*/ + Value.size() + 1 /*\0*/;
+ char *Result = reinterpret_cast<char *>(
+ Allocator.Allocate(sizeof(char) * size, alignof(char)));
+ char *Next = Result;
+
+ Next = std::copy(Key.begin(), Key.end(), Next);
+ *Next++ = '=';
+ Next = std::copy(Value.begin(), Value.end(), Next);
+ *Next++ = '\0';
+
+ return Result;
+}
+
+Environment::Envp::Envp(const Environment &Env) {
+ Data = reinterpret_cast<char **>(
+ Allocator.Allocate(sizeof(char *) * (Env.size() + 1), alignof(char *)));
+ char **Next = Data;
+ for (const auto &KV : Env)
+ *Next++ = make_entry(KV.first(), KV.second);
+ *Next++ = nullptr;
+}
+
+Environment::Environment(const char *const *Env) {
+ if (!Env)
+ return;
+ while (*Env)
+ insert(*Env++);
+}
+
+void Environment::insert(const_iterator first, const_iterator last) {
+ while (first != last) {
+ try_emplace(first->first(), first->second);
+ ++first;
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Utility/FastDemangle.cpp b/contrib/llvm/tools/lldb/source/Utility/FastDemangle.cpp
index 90326c5f15c3..d92670a9199b 100644
--- a/contrib/llvm/tools/lldb/source/Utility/FastDemangle.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/FastDemangle.cpp
@@ -25,7 +25,7 @@
namespace {
-/// @brief Represents the collection of qualifiers on a type
+/// Represents the collection of qualifiers on a type
enum Qualifiers {
QualifierNone = 0,
@@ -37,7 +37,7 @@ enum Qualifiers {
QualifierPointer = 32
};
-/// @brief Categorizes the recognized operators
+/// Categorizes the recognized operators
enum class OperatorKind {
Unary,
@@ -50,23 +50,23 @@ enum class OperatorKind {
NoMatch
};
-/// @brief Represents one of the recognized two-character operator
-/// abbreviations used when parsing operators as names and expressions
+/// Represents one of the recognized two-character operator abbreviations used
+/// when parsing operators as names and expressions
struct Operator {
const char *name;
OperatorKind kind;
};
-/// @brief Represents a range of characters in the output buffer, typically for
-/// use with RewriteRange()
+/// Represents a range of characters in the output buffer, typically for use
+/// with RewriteRange()
struct BufferRange {
int offset;
int length;
};
-/// @brief Transient state required while parsing a name
+/// Transient state required while parsing a name
struct NameState {
bool parse_function_params;
@@ -75,12 +75,13 @@ struct NameState {
BufferRange last_name_range;
};
-/// @brief LLDB's fast C++ demangler
+/// LLDB's fast C++ demangler
///
/// This is an incomplete implementation designed to speed up the demangling
/// process that is often a bottleneck when LLDB stops a process for the first
/// time. Where the implementation doesn't know how to demangle a symbol it
-/// fails gracefully to allow the caller to fall back to the existing demangler.
+/// fails gracefully to allow the caller to fall back to the existing
+/// demangler.
///
/// Over time the full mangling spec should be supported without compromising
/// performance for the most common cases.
@@ -91,7 +92,7 @@ public:
// Public API
//----------------------------------------------------
- /// @brief Create a SymbolDemangler
+ /// Create a SymbolDemangler
///
/// The newly created demangler allocates and owns scratch memory sufficient
/// for demangling typical symbols. Additional memory will be allocated if
@@ -107,18 +108,18 @@ public:
m_owns_m_rewrite_ranges = true;
}
- /// @brief Create a SymbolDemangler that uses provided scratch memory
+ /// Create a SymbolDemangler that uses provided scratch memory
///
/// The provided memory is not owned by the demangler. It will be
- /// overwritten during calls to GetDemangledCopy() but can be used for
- /// other purposes between calls. The provided memory will not be freed
- /// when this instance is destroyed.
+ /// overwritten during calls to GetDemangledCopy() but can be used for other
+ /// purposes between calls. The provided memory will not be freed when this
+ /// instance is destroyed.
///
/// If demangling a symbol requires additional space it will be allocated
/// and managed by the demangler instance.
///
- /// @param storage_ptr Valid pointer to at least storage_size bytes of
- /// space that the SymbolDemangler can use during demangling
+ /// @param storage_ptr Valid pointer to at least storage_size bytes of space
+ /// that the SymbolDemangler can use during demangling
///
/// @param storage_size Number of bytes of space available scratch memory
/// referenced by storage_ptr
@@ -138,8 +139,8 @@ public:
m_owns_buffer = false;
}
- /// @brief Destroys the SymbolDemangler and deallocates any scratch
- /// memory that it owns
+ /// Destroys the SymbolDemangler and deallocates any scratch memory that it
+ /// owns
~SymbolDemangler() {
if (m_owns_buffer)
@@ -153,11 +154,11 @@ public:
int highwater_buffer = 0;
#endif
- /// @brief Parses the provided mangled name and returns a newly allocated
+ /// Parses the provided mangled name and returns a newly allocated
/// demangling
///
- /// @param mangled_name Valid null-terminated C++ mangled name following
- /// the Itanium C++ ABI mangling specification as implemented by Clang
+ /// @param mangled_name Valid null-terminated C++ mangled name following the
+ /// Itanium C++ ABI mangling specification as implemented by Clang
///
/// @result Newly allocated null-terminated demangled name when demangling
/// is successful, and nullptr when demangling fails. The caller is
@@ -200,8 +201,7 @@ private:
if (growth > 1 << 20)
growth = 1 << 20;
- // ... but never grow by less than requested,
- // or 1K, whichever is greater
+ // ... but never grow by less than requested, or 1K, whichever is greater
if (min_growth < 1024)
min_growth = 1024;
if (growth < min_growth)
@@ -282,9 +282,8 @@ private:
if (index == m_rewrite_ranges_size)
break;
- // Affected ranges are either shuffled forward when after the
- // insertion but before the source, or backward when inside the
- // source
+ // Affected ranges are either shuffled forward when after the insertion
+ // but before the source, or backward when inside the source
int candidate_offset = m_rewrite_ranges[index].offset;
if (candidate_offset >= insertion_point_cookie) {
if (candidate_offset < source_range.offset) {
@@ -402,8 +401,7 @@ private:
//----------------------------------------------------
// Rewrite methods
//
- // Write another copy of content already present
- // earlier in the output buffer
+ // Write another copy of content already present earlier in the output buffer
//----------------------------------------------------
void RewriteRange(BufferRange range) {
@@ -436,11 +434,11 @@ private:
//----------------------------------------------------
// TryParse methods
//
- // Provide information with return values instead of
- // writing to the output buffer
+ // Provide information with return values instead of writing to the output
+ // buffer
//
- // Values indicating failure guarantee that the pre-
- // call m_read_ptr is unchanged
+ // Values indicating failure guarantee that the pre- call m_read_ptr is
+ // unchanged
//----------------------------------------------------
int TryParseNumber() {
@@ -820,8 +818,8 @@ private:
}
// <CV-qualifiers> ::= [r] [V] [K]
- // <ref-qualifier> ::= R # & ref-qualifier
- // <ref-qualifier> ::= O # && ref-qualifier
+ // <ref-qualifier> ::= R # & ref-qualifier <ref-qualifier>
+ // ::= O # && ref-qualifier
int TryParseQualifiers(bool allow_cv, bool allow_ro) {
int qualifiers = QualifierNone;
@@ -890,11 +888,10 @@ private:
//----------------------------------------------------
// Parse methods
//
- // Consume input starting from m_read_ptr and produce
- // buffered output at m_write_ptr
+ // Consume input starting from m_read_ptr and produce buffered output at
+ // m_write_ptr
//
- // Failures return false and may leave m_read_ptr in an
- // indeterminate state
+ // Failures return false and may leave m_read_ptr in an indeterminate state
//----------------------------------------------------
bool Parse(char character) {
@@ -932,17 +929,14 @@ private:
// <substitution> ::= S <seq-id> _
// ::= S_
- // <substitution> ::= Sa # ::std::allocator
- // <substitution> ::= Sb # ::std::basic_string
- // <substitution> ::= Ss # ::std::basic_string < char,
+ // <substitution> ::= Sa # ::std::allocator <substitution> ::= Sb #
+ // ::std::basic_string <substitution> ::= Ss # ::std::basic_string < char,
// ::std::char_traits<char>,
// ::std::allocator<char> >
// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char>
- // >
- // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char>
- // >
- // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char>
- // >
+ // > <substitution> ::= So # ::std::basic_ostream<char,
+ // std::char_traits<char> > <substitution> ::= Sd #
+ // ::std::basic_iostream<char, std::char_traits<char> >
bool ParseSubstitution() {
const char *substitution;
@@ -967,7 +961,8 @@ private:
break;
default:
// A failed attempt to parse a number will return -1 which turns out to be
- // perfect here as S_ is the first substitution, S0_ the next and so forth
+ // perfect here as S_ is the first substitution, S0_ the next and so
+ // forth
int substitution_index = TryParseBase36Number();
if (*m_read_ptr++ != '_') {
#ifdef DEBUG_FAILURES
@@ -984,17 +979,17 @@ private:
// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
//
- // <bare-function-type> ::= <signature type>+ # types are possible return
- // type, then parameter types
+ // <bare-function-type> ::= <signature type>+ # types are possible
+ // return type, then parameter types
bool ParseFunctionType(int inner_qualifiers = QualifierNone) {
#ifdef DEBUG_FAILURES
printf("*** Function types not supported\n");
#endif
// TODO: first steps toward an implementation follow, but they're far
- // from complete. Function types tend to bracket other types eg:
- // int (*)() when used as the type for "name" becomes int (*name)().
- // This makes substitution et al ... interesting.
+ // from complete. Function types tend to bracket other types eg: int (*)()
+ // when used as the type for "name" becomes int (*name)(). This makes
+ // substitution et al ... interesting.
return false;
#if 0 // TODO
@@ -1154,8 +1149,8 @@ private:
if (!Parse('_'))
return false;
- // When no number is present we get -1, which is convenient since
- // T_ is the zeroth element T0_ is element 1, and so on
+ // When no number is present we get -1, which is convenient since T_ is the
+ // zeroth element T0_ is element 1, and so on
return RewriteTemplateArg(count + 1);
}
@@ -1193,13 +1188,13 @@ private:
// ::= G <type> # imaginary (C 2000)
// ::= Dp <type> # pack expansion (C++0x)
// ::= U <source-name> <type> # vendor extended type qualifier
- // extension := U <objc-name> <objc-type> # objc-type<identifier>
- // extension := <vector-type> # <vector-type> starts with Dv
+ // extension := U <objc-name> <objc-type> # objc-type<identifier> extension
+ // := <vector-type> # <vector-type> starts with Dv
// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 +
- // <number of digits in k1> + k1
- // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name>
- // 11objc_object -> id<source-name>
+ // <number of digits in k1> + k1 <objc-type> := <source-name> #
+ // PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-
+ // name>
bool ParseType() {
#ifdef DEBUG_FAILURES
@@ -1476,8 +1471,8 @@ private:
// ::= <unnamed-type-name>
bool ParseUnqualifiedName(NameState &name_state) {
- // Note that these are detected directly in ParseNestedName for
- // performance rather than switching on the same options twice
+ // Note that these are detected directly in ParseNestedName for performance
+ // rather than switching on the same options twice
char next = *m_read_ptr;
switch (next) {
case 'C':
@@ -1943,7 +1938,8 @@ private:
break;
}
- // Record a substitution candidate for all prefixes, but not the full name
+ // Record a substitution candidate for all prefixes, but not the full
+ // name
if (suppress_substitution)
suppress_substitution = false;
else
@@ -2247,9 +2243,9 @@ private:
if (next == 'E' || next == '\0' || next == '.')
return true;
- // Clang has a bad habit of making unique manglings by just sticking numbers
- // on the end of a symbol,
- // which is ambiguous with malformed source name manglings
+ // Clang has a bad habit of making unique manglings by just sticking
+ // numbers on the end of a symbol, which is ambiguous with malformed source
+ // name manglings
const char *before_clang_uniquing_test = m_read_ptr;
if (TryParseNumber()) {
if (*m_read_ptr == '\0')
diff --git a/contrib/llvm/tools/lldb/source/Utility/FileSpec.cpp b/contrib/llvm/tools/lldb/source/Utility/FileSpec.cpp
index 72f86917b813..b6952f7e3eb0 100644
--- a/contrib/llvm/tools/lldb/source/Utility/FileSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/FileSpec.cpp
@@ -12,17 +12,15 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/TildeExpressionResolver.h"
-#include "llvm/ADT/SmallString.h" // for SmallString
-#include "llvm/ADT/SmallVector.h" // for SmallVectorTemplat...
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h" // for Triple
-#include "llvm/ADT/Twine.h" // for Twine
-#include "llvm/Config/llvm-config.h" // for LLVM_ON_WIN32
-#include "llvm/Support/ErrorOr.h" // for ErrorOr
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h" // for raw_ostream, fs
+#include "llvm/Support/raw_ostream.h"
#include <algorithm> // for replace, min, unique
#include <system_error> // for error_code
@@ -37,113 +35,35 @@ using namespace lldb_private;
namespace {
-static constexpr FileSpec::PathSyntax GetNativeSyntax() {
-#if defined(LLVM_ON_WIN32)
- return FileSpec::ePathSyntaxWindows;
+static constexpr FileSpec::Style GetNativeStyle() {
+#if defined(_WIN32)
+ return FileSpec::Style::windows;
#else
- return FileSpec::ePathSyntaxPosix;
+ return FileSpec::Style::posix;
#endif
}
-bool PathSyntaxIsPosix(FileSpec::PathSyntax syntax) {
- return (syntax == FileSpec::ePathSyntaxPosix ||
- (syntax == FileSpec::ePathSyntaxHostNative &&
- GetNativeSyntax() == FileSpec::ePathSyntaxPosix));
+bool PathStyleIsPosix(FileSpec::Style style) {
+ return (style == FileSpec::Style::posix ||
+ (style == FileSpec::Style::native &&
+ GetNativeStyle() == FileSpec::Style::posix));
}
-const char *GetPathSeparators(FileSpec::PathSyntax syntax) {
- return PathSyntaxIsPosix(syntax) ? "/" : "\\/";
+const char *GetPathSeparators(FileSpec::Style style) {
+ return llvm::sys::path::get_separator(style).data();
}
-char GetPreferredPathSeparator(FileSpec::PathSyntax syntax) {
- return GetPathSeparators(syntax)[0];
+char GetPreferredPathSeparator(FileSpec::Style style) {
+ return GetPathSeparators(style)[0];
}
-bool IsPathSeparator(char value, FileSpec::PathSyntax syntax) {
- return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\');
-}
-
-void Normalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) {
- if (PathSyntaxIsPosix(syntax))
- return;
-
- std::replace(path.begin(), path.end(), '\\', '/');
- // Windows path can have \\ slashes which can be changed by replace
- // call above to //. Here we remove the duplicate.
- auto iter = std::unique(path.begin(), path.end(), [](char &c1, char &c2) {
- return (c1 == '/' && c2 == '/');
- });
- path.erase(iter, path.end());
-}
-
-void Denormalize(llvm::SmallVectorImpl<char> &path,
- FileSpec::PathSyntax syntax) {
- if (PathSyntaxIsPosix(syntax))
+void Denormalize(llvm::SmallVectorImpl<char> &path, FileSpec::Style style) {
+ if (PathStyleIsPosix(style))
return;
std::replace(path.begin(), path.end(), '/', '\\');
}
-size_t FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) {
- if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1])
- return 0;
-
- if (str.size() > 0 && IsPathSeparator(str.back(), syntax))
- return str.size() - 1;
-
- size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1);
-
- if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos)
- pos = str.find_last_of(':', str.size() - 2);
-
- if (pos == llvm::StringRef::npos ||
- (pos == 1 && IsPathSeparator(str[0], syntax)))
- return 0;
-
- return pos + 1;
-}
-
-size_t RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) {
- // case "c:/"
- if (!PathSyntaxIsPosix(syntax) &&
- (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax)))
- return 2;
-
- // case "//"
- if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1])
- return llvm::StringRef::npos;
-
- // case "//net"
- if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] &&
- !IsPathSeparator(str[2], syntax))
- return str.find_first_of(GetPathSeparators(syntax), 2);
-
- // case "/"
- if (str.size() > 0 && IsPathSeparator(str[0], syntax))
- return 0;
-
- return llvm::StringRef::npos;
-}
-
-size_t ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) {
- size_t end_pos = FilenamePos(path, syntax);
-
- bool filename_was_sep =
- path.size() > 0 && IsPathSeparator(path[end_pos], syntax);
-
- // Skip separators except for root dir.
- size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax);
-
- while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
- IsPathSeparator(path[end_pos - 1], syntax))
- --end_pos;
-
- if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
- return llvm::StringRef::npos;
-
- return end_pos;
-}
-
} // end anonymous namespace
void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
@@ -164,28 +84,27 @@ void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
}
}
-FileSpec::FileSpec() : m_syntax(GetNativeSyntax()) {}
+FileSpec::FileSpec() : m_style(GetNativeStyle()) {}
//------------------------------------------------------------------
-// Default constructor that can take an optional full path to a
-// file on disk.
+// Default constructor that can take an optional full path to a file on disk.
//------------------------------------------------------------------
-FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, PathSyntax syntax)
- : m_syntax(syntax) {
- SetFile(path, resolve_path, syntax);
+FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, Style style)
+ : m_style(style) {
+ SetFile(path, resolve_path, style);
}
FileSpec::FileSpec(llvm::StringRef path, bool resolve_path,
const llvm::Triple &Triple)
: FileSpec{path, resolve_path,
- Triple.isOSWindows() ? ePathSyntaxWindows : ePathSyntaxPosix} {}
+ Triple.isOSWindows() ? Style::windows : Style::posix} {}
//------------------------------------------------------------------
// Copy constructor
//------------------------------------------------------------------
FileSpec::FileSpec(const FileSpec &rhs)
: m_directory(rhs.m_directory), m_filename(rhs.m_filename),
- m_is_resolved(rhs.m_is_resolved), m_syntax(rhs.m_syntax) {}
+ m_is_resolved(rhs.m_is_resolved), m_style(rhs.m_style) {}
//------------------------------------------------------------------
// Copy constructor
@@ -200,6 +119,100 @@ FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() {
//------------------------------------------------------------------
FileSpec::~FileSpec() {}
+namespace {
+//------------------------------------------------------------------
+/// Safely get a character at the specified index.
+///
+/// @param[in] path
+/// A full, partial, or relative path to a file.
+///
+/// @param[in] i
+/// An index into path which may or may not be valid.
+///
+/// @return
+/// The character at index \a i if the index is valid, or 0 if
+/// the index is not valid.
+//------------------------------------------------------------------
+inline char safeCharAtIndex(const llvm::StringRef &path, size_t i) {
+ if (i < path.size())
+ return path[i];
+ return 0;
+}
+
+//------------------------------------------------------------------
+/// Check if a path needs to be normalized.
+///
+/// Check if a path needs to be normalized. We currently consider a
+/// path to need normalization if any of the following are true
+/// - path contains "/./"
+/// - path contains "/../"
+/// - path contains "//"
+/// - path ends with "/"
+/// Paths that start with "./" or with "../" are not considered to
+/// need normalization since we aren't trying to resolve the path,
+/// we are just trying to remove redundant things from the path.
+///
+/// @param[in] path
+/// A full, partial, or relative path to a file.
+///
+/// @return
+/// Returns \b true if the path needs to be normalized.
+//------------------------------------------------------------------
+bool needsNormalization(const llvm::StringRef &path) {
+ if (path.empty())
+ return false;
+ // We strip off leading "." values so these paths need to be normalized
+ if (path[0] == '.')
+ return true;
+ for (auto i = path.find_first_of("\\/"); i != llvm::StringRef::npos;
+ i = path.find_first_of("\\/", i + 1)) {
+ const auto next = safeCharAtIndex(path, i+1);
+ switch (next) {
+ case 0:
+ // path separator char at the end of the string which should be
+ // stripped unless it is the one and only character
+ return i > 0;
+ case '/':
+ case '\\':
+ // two path separator chars in the middle of a path needs to be
+ // normalized
+ if (i > 0)
+ return true;
+ ++i;
+ break;
+
+ case '.': {
+ const auto next_next = safeCharAtIndex(path, i+2);
+ switch (next_next) {
+ default: break;
+ case 0: return true; // ends with "/."
+ case '/':
+ case '\\':
+ return true; // contains "/./"
+ case '.': {
+ const auto next_next_next = safeCharAtIndex(path, i+3);
+ switch (next_next_next) {
+ default: break;
+ case 0: return true; // ends with "/.."
+ case '/':
+ case '\\':
+ return true; // contains "/../"
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+
+}
//------------------------------------------------------------------
// Assignment operator.
//------------------------------------------------------------------
@@ -208,26 +221,25 @@ const FileSpec &FileSpec::operator=(const FileSpec &rhs) {
m_directory = rhs.m_directory;
m_filename = rhs.m_filename;
m_is_resolved = rhs.m_is_resolved;
- m_syntax = rhs.m_syntax;
+ m_style = rhs.m_style;
}
return *this;
}
+void FileSpec::SetFile(llvm::StringRef pathname, bool resolve) {
+ SetFile(pathname, resolve, m_style);
+}
+
//------------------------------------------------------------------
-// Update the contents of this object with a new path. The path will
-// be split up into a directory and filename and stored as uniqued
-// string values for quick comparison and efficient memory usage.
+// Update the contents of this object with a new path. The path will be split
+// up into a directory and filename and stored as uniqued string values for
+// quick comparison and efficient memory usage.
//------------------------------------------------------------------
-void FileSpec::SetFile(llvm::StringRef pathname, bool resolve,
- PathSyntax syntax) {
- // CLEANUP: Use StringRef for string handling. This function is kind of a
- // mess and the unclear semantics of RootDirStart and ParentPathEnd make
- // it very difficult to understand this function. There's no reason this
- // function should be particularly complicated or difficult to understand.
+void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, Style style) {
m_filename.Clear();
m_directory.Clear();
m_is_resolved = false;
- m_syntax = (syntax == ePathSyntaxHostNative) ? GetNativeSyntax() : syntax;
+ m_style = (style == Style::native) ? GetNativeStyle() : style;
if (pathname.empty())
return;
@@ -239,39 +251,41 @@ void FileSpec::SetFile(llvm::StringRef pathname, bool resolve,
m_is_resolved = true;
}
- Normalize(resolved, m_syntax);
+ // Normalize the path by removing ".", ".." and other redundant components.
+ if (needsNormalization(resolved))
+ llvm::sys::path::remove_dots(resolved, true, m_style);
- llvm::StringRef resolve_path_ref(resolved.c_str());
- size_t dir_end = ParentPathEnd(resolve_path_ref, m_syntax);
- if (dir_end == 0) {
- m_filename.SetString(resolve_path_ref);
+ // Normalize back slashes to forward slashes
+ if (m_style == Style::windows)
+ std::replace(resolved.begin(), resolved.end(), '\\', '/');
+
+ if (resolved.empty()) {
+ // If we have no path after normalization set the path to the current
+ // directory. This matches what python does and also a few other path
+ // utilities.
+ m_filename.SetString(".");
return;
}
- m_directory.SetString(resolve_path_ref.substr(0, dir_end));
-
- size_t filename_begin = dir_end;
- size_t root_dir_start = RootDirStart(resolve_path_ref, m_syntax);
- while (filename_begin != llvm::StringRef::npos &&
- filename_begin < resolve_path_ref.size() &&
- filename_begin != root_dir_start &&
- IsPathSeparator(resolve_path_ref[filename_begin], m_syntax))
- ++filename_begin;
- m_filename.SetString((filename_begin == llvm::StringRef::npos ||
- filename_begin >= resolve_path_ref.size())
- ? "."
- : resolve_path_ref.substr(filename_begin));
+ // Split path into filename and directory. We rely on the underlying char
+ // pointer to be nullptr when the components are empty.
+ llvm::StringRef filename = llvm::sys::path::filename(resolved, m_style);
+ if(!filename.empty())
+ m_filename.SetString(filename);
+ llvm::StringRef directory = llvm::sys::path::parent_path(resolved, m_style);
+ if(!directory.empty())
+ m_directory.SetString(directory);
}
void FileSpec::SetFile(llvm::StringRef path, bool resolve,
const llvm::Triple &Triple) {
return SetFile(path, resolve,
- Triple.isOSWindows() ? ePathSyntaxWindows : ePathSyntaxPosix);
+ Triple.isOSWindows() ? Style::windows : Style::posix);
}
//----------------------------------------------------------------------
-// Convert to pointer operator. This allows code to check any FileSpec
-// objects to see if they contain anything valid using code such as:
+// Convert to pointer operator. This allows code to check any FileSpec objects
+// to see if they contain anything valid using code such as:
//
// if (file_spec)
// {}
@@ -279,8 +293,8 @@ void FileSpec::SetFile(llvm::StringRef path, bool resolve,
FileSpec::operator bool() const { return m_filename || m_directory; }
//----------------------------------------------------------------------
-// Logical NOT operator. This allows code to check any FileSpec
-// objects to see if they are invalid using code such as:
+// Logical NOT operator. This allows code to check any FileSpec objects to see
+// if they are invalid using code such as:
//
// if (!file_spec)
// {}
@@ -307,12 +321,10 @@ bool FileSpec::operator==(const FileSpec &rhs) const {
return true;
// TODO: determine if we want to keep this code in here.
- // The code below was added to handle a case where we were
- // trying to set a file and line breakpoint and one path
- // was resolved, and the other not and the directory was
- // in a mount point that resolved to a more complete path:
- // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling
- // this out...
+ // The code below was added to handle a case where we were trying to set a
+ // file and line breakpoint and one path was resolved, and the other not and
+ // the directory was in a mount point that resolved to a more complete path:
+ // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling this out...
if (IsResolved() && rhs.IsResolved()) {
// Both paths are resolved, no need to look further...
return false;
@@ -324,8 +336,8 @@ bool FileSpec::operator==(const FileSpec &rhs) const {
if (!IsResolved()) {
if (resolved_lhs.ResolvePath()) {
// This path wasn't resolved but now it is. Check if the resolved
- // directory is the same as our unresolved directory, and if so,
- // we can mark this object as resolved to avoid more future resolves
+ // directory is the same as our unresolved directory, and if so, we can
+ // mark this object as resolved to avoid more future resolves
m_is_resolved = (m_directory == resolved_lhs.m_directory);
} else
return false;
@@ -335,16 +347,16 @@ bool FileSpec::operator==(const FileSpec &rhs) const {
if (!rhs.IsResolved()) {
if (resolved_rhs.ResolvePath()) {
// rhs's path wasn't resolved but now it is. Check if the resolved
- // directory is the same as rhs's unresolved directory, and if so,
- // we can mark this object as resolved to avoid more future resolves
+ // directory is the same as rhs's unresolved directory, and if so, we can
+ // mark this object as resolved to avoid more future resolves
rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory);
} else
return false;
}
- // If we reach this point in the code we were able to resolve both paths
- // and since we only resolve the paths if the basenames are equal, then
- // we can just check if both directories are equal...
+ // If we reach this point in the code we were able to resolve both paths and
+ // since we only resolve the paths if the basenames are equal, then we can
+ // just check if both directories are equal...
return DirectoryEquals(rhs);
}
@@ -369,8 +381,8 @@ Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) {
}
//------------------------------------------------------------------
-// Clear this object by releasing both the directory and filename
-// string values and making them both the empty string.
+// Clear this object by releasing both the directory and filename string values
+// and making them both the empty string.
//------------------------------------------------------------------
void FileSpec::Clear() {
m_directory.Clear();
@@ -378,15 +390,14 @@ void FileSpec::Clear() {
}
//------------------------------------------------------------------
-// Compare two FileSpec objects. If "full" is true, then both
-// the directory and the filename must match. If "full" is false,
-// then the directory names for "a" and "b" are only compared if
-// they are both non-empty. This allows a FileSpec object to only
-// contain a filename and it can match FileSpec objects that have
-// matching filenames with different paths.
+// Compare two FileSpec objects. If "full" is true, then both the directory and
+// the filename must match. If "full" is false, then the directory names for
+// "a" and "b" are only compared if they are both non-empty. This allows a
+// FileSpec object to only contain a filename and it can match FileSpec objects
+// that have matching filenames with different paths.
//
-// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b"
-// and "1" if "a" is greater than "b".
+// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b" and "1" if
+// "a" is greater than "b".
//------------------------------------------------------------------
int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
int result = 0;
@@ -396,10 +407,10 @@ int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
// If full is true, then we must compare both the directory and filename.
- // If full is false, then if either directory is empty, then we match on
- // the basename only, and if both directories have valid values, we still
- // do a full compare. This allows for matching when we just have a filename
- // in one of the FileSpec objects.
+ // If full is false, then if either directory is empty, then we match on the
+ // basename only, and if both directories have valid values, we still do a
+ // full compare. This allows for matching when we just have a filename in one
+ // of the FileSpec objects.
if (full || (a.m_directory && b.m_directory)) {
result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive);
@@ -409,118 +420,33 @@ int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive);
}
-bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full,
- bool remove_backups) {
- static ConstString g_dot_string(".");
- static ConstString g_dot_dot_string("..");
-
+bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full) {
// case sensitivity of equality test
const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive();
-
- bool filenames_equal = ConstString::Equals(a.m_filename,
- b.m_filename,
- case_sensitive);
-
- // The only way two FileSpecs can be equal if their filenames are
- // unequal is if we are removing backups and one or the other filename
- // is a backup string:
- if (!filenames_equal && !remove_backups)
- return false;
+ const bool filenames_equal = ConstString::Equals(a.m_filename,
+ b.m_filename,
+ case_sensitive);
- bool last_component_is_dot = ConstString::Equals(a.m_filename, g_dot_string)
- || ConstString::Equals(a.m_filename,
- g_dot_dot_string)
- || ConstString::Equals(b.m_filename,
- g_dot_string)
- || ConstString::Equals(b.m_filename,
- g_dot_dot_string);
-
- if (!filenames_equal && !last_component_is_dot)
+ if (!filenames_equal)
return false;
if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
return filenames_equal;
- if (remove_backups == false)
- return a == b;
-
- if (a == b)
- return true;
-
- return Equal(a.GetNormalizedPath(), b.GetNormalizedPath(), full, false);
-}
-
-FileSpec FileSpec::GetNormalizedPath() const {
- // Fast path. Do nothing if the path is not interesting.
- if (!m_directory.GetStringRef().contains(".") &&
- !m_directory.GetStringRef().contains("//") &&
- m_filename.GetStringRef() != ".." && m_filename.GetStringRef() != ".")
- return *this;
-
- llvm::SmallString<64> path, result;
- const bool normalize = false;
- GetPath(path, normalize);
- llvm::StringRef rest(path);
-
- // We will not go below root dir.
- size_t root_dir_start = RootDirStart(path, m_syntax);
- const bool absolute = root_dir_start != llvm::StringRef::npos;
- if (absolute) {
- result += rest.take_front(root_dir_start + 1);
- rest = rest.drop_front(root_dir_start + 1);
- } else {
- if (m_syntax == ePathSyntaxWindows && path.size() > 2 && path[1] == ':') {
- result += rest.take_front(2);
- rest = rest.drop_front(2);
- }
- }
-
- bool anything_added = false;
- llvm::SmallVector<llvm::StringRef, 0> components, processed;
- rest.split(components, '/', -1, false);
- processed.reserve(components.size());
- for (auto component : components) {
- if (component == ".")
- continue; // Skip these.
- if (component != "..") {
- processed.push_back(component);
- continue; // Regular file name.
- }
- if (!processed.empty()) {
- processed.pop_back();
- continue; // Dots. Go one level up if we can.
- }
- if (absolute)
- continue; // We're at the top level. Cannot go higher than that. Skip.
-
- result += component; // We're a relative path. We need to keep these.
- result += '/';
- anything_added = true;
- }
- for (auto component : processed) {
- result += component;
- result += '/';
- anything_added = true;
- }
- if (anything_added)
- result.pop_back(); // Pop last '/'.
- else if (result.empty())
- result = ".";
-
- return FileSpec(result, false, m_syntax);
+ return a == b;
}
//------------------------------------------------------------------
-// Dump the object to the supplied stream. If the object contains
-// a valid directory name, it will be displayed followed by a
-// directory delimiter, and the filename.
+// Dump the object to the supplied stream. If the object contains a valid
+// directory name, it will be displayed followed by a directory delimiter, and
+// the filename.
//------------------------------------------------------------------
void FileSpec::Dump(Stream *s) const {
if (s) {
std::string path{GetPath(true)};
s->PutCString(path);
- char path_separator = GetPreferredPathSeparator(m_syntax);
+ char path_separator = GetPreferredPathSeparator(m_style);
if (!m_filename && !path.empty() && path.back() != path_separator)
s->PutChar(path_separator);
}
@@ -557,8 +483,7 @@ bool FileSpec::ResolveExecutableLocation() {
return true;
else {
// If FindProgramByName found the file, it returns the directory +
- // filename in its return results.
- // We need to separate them.
+ // filename in its return results. We need to separate them.
FileSpec tmp_file(dir_ref.data(), false);
if (tmp_file.Exists()) {
m_directory = tmp_file.m_directory;
@@ -588,7 +513,7 @@ uint64_t FileSpec::GetByteSize() const {
return Size;
}
-FileSpec::PathSyntax FileSpec::GetPathSyntax() const { return m_syntax; }
+FileSpec::Style FileSpec::GetPathStyle() const { return m_style; }
uint32_t FileSpec::GetPermissions() const {
namespace fs = llvm::sys::fs;
@@ -620,9 +545,8 @@ ConstString &FileSpec::GetFilename() { return m_filename; }
const ConstString &FileSpec::GetFilename() const { return m_filename; }
//------------------------------------------------------------------
-// Extract the directory and path into a fixed buffer. This is
-// needed as the directory and path are stored in separate string
-// values.
+// Extract the directory and path into a fixed buffer. This is needed as the
+// directory and path are stored in separate string values.
//------------------------------------------------------------------
size_t FileSpec::GetPath(char *path, size_t path_max_len,
bool denormalize) const {
@@ -648,42 +572,30 @@ void FileSpec::GetPath(llvm::SmallVectorImpl<char> &path,
bool denormalize) const {
path.append(m_directory.GetStringRef().begin(),
m_directory.GetStringRef().end());
- if (m_directory && m_filename &&
- !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax))
- path.insert(path.end(), GetPreferredPathSeparator(m_syntax));
+ // Since the path was normalized and all paths use '/' when stored in these
+ // objects, we don't need to look for the actual syntax specific path
+ // separator, we just look for and insert '/'.
+ if (m_directory && m_filename && m_directory.GetStringRef().back() != '/' &&
+ m_filename.GetStringRef().back() != '/')
+ path.insert(path.end(), '/');
path.append(m_filename.GetStringRef().begin(),
m_filename.GetStringRef().end());
- Normalize(path, m_syntax);
if (denormalize && !path.empty())
- Denormalize(path, m_syntax);
+ Denormalize(path, m_style);
}
ConstString FileSpec::GetFileNameExtension() const {
- if (m_filename) {
- const char *filename = m_filename.GetCString();
- const char *dot_pos = strrchr(filename, '.');
- if (dot_pos && dot_pos[1] != '\0')
- return ConstString(dot_pos + 1);
- }
- return ConstString();
+ return ConstString(
+ llvm::sys::path::extension(m_filename.GetStringRef(), m_style));
}
ConstString FileSpec::GetFileNameStrippingExtension() const {
- const char *filename = m_filename.GetCString();
- if (filename == NULL)
- return ConstString();
-
- const char *dot_pos = strrchr(filename, '.');
- if (dot_pos == NULL)
- return m_filename;
-
- return ConstString(filename, dot_pos - filename);
+ return ConstString(llvm::sys::path::stem(m_filename.GetStringRef(), m_style));
}
//------------------------------------------------------------------
-// Return the size in bytes that this object takes in memory. This
-// returns the size in bytes of this object, not any shared string
-// values it may refer to.
+// Return the size in bytes that this object takes in memory. This returns the
+// size in bytes of this object, not any shared string values it may refer to.
//------------------------------------------------------------------
size_t FileSpec::MemorySize() const {
return m_filename.MemorySize() + m_directory.MemorySize();
@@ -730,91 +642,28 @@ FileSpec::CopyByAppendingPathComponent(llvm::StringRef component) const {
}
FileSpec FileSpec::CopyByRemovingLastPathComponent() const {
- // CLEANUP: Use StringRef for string handling.
- const bool resolve = false;
- if (m_filename.IsEmpty() && m_directory.IsEmpty())
- return FileSpec("", resolve);
- if (m_directory.IsEmpty())
- return FileSpec("", resolve);
- if (m_filename.IsEmpty()) {
- const char *dir_cstr = m_directory.GetCString();
- const char *last_slash_ptr = ::strrchr(dir_cstr, '/');
-
- // check for obvious cases before doing the full thing
- if (!last_slash_ptr)
- return FileSpec("", resolve);
- if (last_slash_ptr == dir_cstr)
- return FileSpec("/", resolve);
-
- size_t last_slash_pos = last_slash_ptr - dir_cstr + 1;
- ConstString new_path(dir_cstr, last_slash_pos);
- return FileSpec(new_path.GetCString(), resolve);
- } else
- return FileSpec(m_directory.GetCString(), resolve);
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ if (llvm::sys::path::has_parent_path(current_path, m_style))
+ return FileSpec(llvm::sys::path::parent_path(current_path, m_style), false,
+ m_style);
+ return *this;
}
ConstString FileSpec::GetLastPathComponent() const {
- // CLEANUP: Use StringRef for string handling.
- if (m_filename)
- return m_filename;
- if (m_directory) {
- const char *dir_cstr = m_directory.GetCString();
- const char *last_slash_ptr = ::strrchr(dir_cstr, '/');
- if (last_slash_ptr == NULL)
- return m_directory;
- if (last_slash_ptr == dir_cstr) {
- if (last_slash_ptr[1] == 0)
- return ConstString(last_slash_ptr);
- else
- return ConstString(last_slash_ptr + 1);
- }
- if (last_slash_ptr[1] != 0)
- return ConstString(last_slash_ptr + 1);
- const char *penultimate_slash_ptr = last_slash_ptr;
- while (*penultimate_slash_ptr) {
- --penultimate_slash_ptr;
- if (penultimate_slash_ptr == dir_cstr)
- break;
- if (*penultimate_slash_ptr == '/')
- break;
- }
- ConstString result(penultimate_slash_ptr + 1,
- last_slash_ptr - penultimate_slash_ptr);
- return result;
- }
- return ConstString();
-}
-
-static std::string
-join_path_components(FileSpec::PathSyntax syntax,
- const std::vector<llvm::StringRef> components) {
- std::string result;
- for (size_t i = 0; i < components.size(); ++i) {
- if (components[i].empty())
- continue;
- result += components[i];
- if (i != components.size() - 1 &&
- !IsPathSeparator(components[i].back(), syntax))
- result += GetPreferredPathSeparator(syntax);
- }
-
- return result;
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ return ConstString(llvm::sys::path::filename(current_path, m_style));
}
void FileSpec::PrependPathComponent(llvm::StringRef component) {
- if (component.empty())
- return;
-
- const bool resolve = false;
- if (m_filename.IsEmpty() && m_directory.IsEmpty()) {
- SetFile(component, resolve);
- return;
- }
-
- std::string result =
- join_path_components(m_syntax, {component, m_directory.GetStringRef(),
- m_filename.GetStringRef()});
- SetFile(result, resolve, m_syntax);
+ llvm::SmallString<64> new_path(component);
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ llvm::sys::path::append(new_path,
+ llvm::sys::path::begin(current_path, m_style),
+ llvm::sys::path::end(current_path), m_style);
+ SetFile(new_path, false, m_style);
}
void FileSpec::PrependPathComponent(const FileSpec &new_path) {
@@ -822,53 +671,24 @@ void FileSpec::PrependPathComponent(const FileSpec &new_path) {
}
void FileSpec::AppendPathComponent(llvm::StringRef component) {
- if (component.empty())
- return;
-
- component = component.drop_while(
- [this](char c) { return IsPathSeparator(c, m_syntax); });
-
- std::string result =
- join_path_components(m_syntax, {m_directory.GetStringRef(),
- m_filename.GetStringRef(), component});
-
- SetFile(result, false, m_syntax);
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ llvm::sys::path::append(current_path, m_style, component);
+ SetFile(current_path, false, m_style);
}
void FileSpec::AppendPathComponent(const FileSpec &new_path) {
return AppendPathComponent(new_path.GetPath(false));
}
-void FileSpec::RemoveLastPathComponent() {
- // CLEANUP: Use StringRef for string handling.
-
- const bool resolve = false;
- if (m_filename.IsEmpty() && m_directory.IsEmpty()) {
- SetFile("", resolve);
- return;
- }
- if (m_directory.IsEmpty()) {
- SetFile("", resolve);
- return;
+bool FileSpec::RemoveLastPathComponent() {
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ if (llvm::sys::path::has_parent_path(current_path, m_style)) {
+ SetFile(llvm::sys::path::parent_path(current_path, m_style), false);
+ return true;
}
- if (m_filename.IsEmpty()) {
- const char *dir_cstr = m_directory.GetCString();
- const char *last_slash_ptr = ::strrchr(dir_cstr, '/');
-
- // check for obvious cases before doing the full thing
- if (!last_slash_ptr) {
- SetFile("", resolve);
- return;
- }
- if (last_slash_ptr == dir_cstr) {
- SetFile("/", resolve);
- return;
- }
- size_t last_slash_pos = last_slash_ptr - dir_cstr + 1;
- ConstString new_path(dir_cstr, last_slash_pos);
- SetFile(new_path.GetCString(), resolve);
- } else
- SetFile(m_directory.GetCString(), resolve);
+ return false;
}
//------------------------------------------------------------------
/// Returns true if the filespec represents an implementation source
@@ -885,7 +705,7 @@ bool FileSpec::IsSourceImplementationFile() const {
return false;
static RegularExpression g_source_file_regex(llvm::StringRef(
- "^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|["
+ "^.([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|["
"cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO]["
"rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])"
"$"));
@@ -893,34 +713,23 @@ bool FileSpec::IsSourceImplementationFile() const {
}
bool FileSpec::IsRelative() const {
- const char *dir = m_directory.GetCString();
- llvm::StringRef directory(dir ? dir : "");
+ return !IsAbsolute();
+}
- if (directory.size() > 0) {
- if (PathSyntaxIsPosix(m_syntax)) {
- // If the path doesn't start with '/' or '~', return true
- switch (directory[0]) {
- case '/':
- case '~':
- return false;
- default:
- return true;
- }
- } else {
- if (directory.size() >= 2 && directory[1] == ':')
- return false;
- if (directory[0] == '/')
- return false;
- return true;
- }
- } else if (m_filename) {
- // No directory, just a basename, return true
+bool FileSpec::IsAbsolute() const {
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+
+ // Early return if the path is empty.
+ if (current_path.empty())
+ return false;
+
+ // We consider paths starting with ~ to be absolute.
+ if (current_path[0] == '~')
return true;
- }
- return false;
-}
-bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); }
+ return llvm::sys::path::is_absolute(current_path, m_style);
+}
void llvm::format_provider<FileSpec>::format(const FileSpec &F,
raw_ostream &Stream,
@@ -944,14 +753,13 @@ void llvm::format_provider<FileSpec>::format(const FileSpec &F,
// Style is either D or empty, either way we need to print the directory.
if (!dir.empty()) {
- // Directory is stored in normalized form, which might be different
- // than preferred form. In order to handle this, we need to cut off
- // the filename, then denormalize, then write the entire denorm'ed
- // directory.
+ // Directory is stored in normalized form, which might be different than
+ // preferred form. In order to handle this, we need to cut off the
+ // filename, then denormalize, then write the entire denorm'ed directory.
llvm::SmallString<64> denormalized_dir = dir;
- Denormalize(denormalized_dir, F.GetPathSyntax());
+ Denormalize(denormalized_dir, F.GetPathStyle());
Stream << denormalized_dir;
- Stream << GetPreferredPathSeparator(F.GetPathSyntax());
+ Stream << GetPreferredPathSeparator(F.GetPathStyle());
}
if (Style.equals_lower("D")) {
diff --git a/contrib/llvm/tools/lldb/source/Utility/History.cpp b/contrib/llvm/tools/lldb/source/Utility/History.cpp
deleted file mode 100644
index 10344b67c635..000000000000
--- a/contrib/llvm/tools/lldb/source/Utility/History.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===-- History.cpp ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/History.h"
-
-// C Includes
-#include <inttypes.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Utility/Stream.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-void HistorySourceUInt::DumpHistoryEvent(Stream &strm, HistoryEvent event) {
- strm.Printf("%s %" PRIu64, m_name.c_str(), (uint64_t)((uintptr_t)event));
-}
diff --git a/contrib/llvm/tools/lldb/source/Utility/JSON.cpp b/contrib/llvm/tools/lldb/source/Utility/JSON.cpp
index 9049f596ab9a..7d70034ccabd 100644
--- a/contrib/llvm/tools/lldb/source/Utility/JSON.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/JSON.cpp
@@ -449,8 +449,7 @@ int JSONParser::GetEscapedChar(bool &was_escaped) {
JSONValue::SP JSONParser::ParseJSONObject() {
// The "JSONParser::Token::ObjectStart" token should have already been
- // consumed
- // by the time this function is called
+ // consumed by the time this function is called
std::unique_ptr<JSONObject> dict_up(new JSONObject());
std::string value;
@@ -481,8 +480,7 @@ JSONValue::SP JSONParser::ParseJSONObject() {
JSONValue::SP JSONParser::ParseJSONArray() {
// The "JSONParser::Token::ObjectStart" token should have already been
- // consumed
- // by the time this function is called
+ // consumed by the time this function is called
std::unique_ptr<JSONArray> array_up(new JSONArray());
std::string value;
diff --git a/contrib/llvm/tools/lldb/source/Utility/Log.cpp b/contrib/llvm/tools/lldb/source/Utility/Log.cpp
index f247124f8d63..eb026fb04752 100644
--- a/contrib/llvm/tools/lldb/source/Utility/Log.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/Log.cpp
@@ -28,7 +28,7 @@
#include <utility> // for pair
#include <assert.h> // for assert
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include <process.h> // for getpid
#else
#include <unistd.h>
@@ -121,9 +121,9 @@ void Log::Printf(const char *format, ...) {
}
//----------------------------------------------------------------------
-// All logging eventually boils down to this function call. If we have
-// a callback registered, then we call the logging callback. If we have
-// a valid file handle, we also log to the file.
+// All logging eventually boils down to this function call. If we have a
+// callback registered, then we call the logging callback. If we have a valid
+// file handle, we also log to the file.
//----------------------------------------------------------------------
void Log::VAPrintf(const char *format, va_list args) {
llvm::SmallString<64> FinalMessage;
@@ -156,8 +156,7 @@ void Log::VAError(const char *format, va_list args) {
}
//----------------------------------------------------------------------
-// Printing of warnings that are not fatal only if verbose mode is
-// enabled.
+// Printing of warnings that are not fatal only if verbose mode is enabled.
//----------------------------------------------------------------------
void Log::Verbose(const char *format, ...) {
if (!GetVerbose())
@@ -287,7 +286,11 @@ void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
if (options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) {
llvm::SmallString<32> thread_name;
llvm::get_thread_name(thread_name);
- OS << llvm::formatv("{0,-16} ", thread_name);
+
+ llvm::SmallString<12> format_str;
+ llvm::raw_svector_ostream format_os(format_str);
+ format_os << "{0,-" << llvm::alignTo<16>(thread_name.size()) << "} ";
+ OS << llvm::formatv(format_str.c_str(), thread_name);
}
if (options.Test(LLDB_LOG_OPTION_BACKTRACE))
@@ -302,8 +305,8 @@ void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
}
void Log::WriteMessage(const std::string &message) {
- // Make a copy of our stream shared pointer in case someone disables our
- // log while we are logging and releases the stream
+ // Make a copy of our stream shared pointer in case someone disables our log
+ // while we are logging and releases the stream
auto stream_sp = GetStream();
if (!stream_sp)
return;
diff --git a/contrib/llvm/tools/lldb/source/Utility/PPC64_DWARF_Registers.h b/contrib/llvm/tools/lldb/source/Utility/PPC64_DWARF_Registers.h
new file mode 100644
index 000000000000..7e3619e0da4d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/PPC64_DWARF_Registers.h
@@ -0,0 +1,127 @@
+//===-- PPC64_DWARF_Registers.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_PPC64_DWARF_Registers_h_
+#define utility_PPC64_DWARF_Registers_h_
+
+#include "lldb/lldb-private.h"
+
+namespace ppc64_dwarf {
+
+enum {
+ dwarf_r0_ppc64 = 0,
+ dwarf_r1_ppc64,
+ dwarf_r2_ppc64,
+ dwarf_r3_ppc64,
+ dwarf_r4_ppc64,
+ dwarf_r5_ppc64,
+ dwarf_r6_ppc64,
+ dwarf_r7_ppc64,
+ dwarf_r8_ppc64,
+ dwarf_r9_ppc64,
+ dwarf_r10_ppc64,
+ dwarf_r11_ppc64,
+ dwarf_r12_ppc64,
+ dwarf_r13_ppc64,
+ dwarf_r14_ppc64,
+ dwarf_r15_ppc64,
+ dwarf_r16_ppc64,
+ dwarf_r17_ppc64,
+ dwarf_r18_ppc64,
+ dwarf_r19_ppc64,
+ dwarf_r20_ppc64,
+ dwarf_r21_ppc64,
+ dwarf_r22_ppc64,
+ dwarf_r23_ppc64,
+ dwarf_r24_ppc64,
+ dwarf_r25_ppc64,
+ dwarf_r26_ppc64,
+ dwarf_r27_ppc64,
+ dwarf_r28_ppc64,
+ dwarf_r29_ppc64,
+ dwarf_r30_ppc64,
+ dwarf_r31_ppc64,
+ dwarf_f0_ppc64,
+ dwarf_f1_ppc64,
+ dwarf_f2_ppc64,
+ dwarf_f3_ppc64,
+ dwarf_f4_ppc64,
+ dwarf_f5_ppc64,
+ dwarf_f6_ppc64,
+ dwarf_f7_ppc64,
+ dwarf_f8_ppc64,
+ dwarf_f9_ppc64,
+ dwarf_f10_ppc64,
+ dwarf_f11_ppc64,
+ dwarf_f12_ppc64,
+ dwarf_f13_ppc64,
+ dwarf_f14_ppc64,
+ dwarf_f15_ppc64,
+ dwarf_f16_ppc64,
+ dwarf_f17_ppc64,
+ dwarf_f18_ppc64,
+ dwarf_f19_ppc64,
+ dwarf_f20_ppc64,
+ dwarf_f21_ppc64,
+ dwarf_f22_ppc64,
+ dwarf_f23_ppc64,
+ dwarf_f24_ppc64,
+ dwarf_f25_ppc64,
+ dwarf_f26_ppc64,
+ dwarf_f27_ppc64,
+ dwarf_f28_ppc64,
+ dwarf_f29_ppc64,
+ dwarf_f30_ppc64,
+ dwarf_f31_ppc64,
+ dwarf_cr_ppc64 = 64,
+ dwarf_fpscr_ppc64,
+ dwarf_msr_ppc64,
+ dwarf_xer_ppc64 = 100,
+ dwarf_lr_ppc64 = 108,
+ dwarf_ctr_ppc64,
+ dwarf_vscr_ppc64,
+ dwarf_vrsave_ppc64 = 356,
+ dwarf_pc_ppc64,
+ dwarf_vr0_ppc64 = 1124,
+ dwarf_vr1_ppc64,
+ dwarf_vr2_ppc64,
+ dwarf_vr3_ppc64,
+ dwarf_vr4_ppc64,
+ dwarf_vr5_ppc64,
+ dwarf_vr6_ppc64,
+ dwarf_vr7_ppc64,
+ dwarf_vr8_ppc64,
+ dwarf_vr9_ppc64,
+ dwarf_vr10_ppc64,
+ dwarf_vr11_ppc64,
+ dwarf_vr12_ppc64,
+ dwarf_vr13_ppc64,
+ dwarf_vr14_ppc64,
+ dwarf_vr15_ppc64,
+ dwarf_vr16_ppc64,
+ dwarf_vr17_ppc64,
+ dwarf_vr18_ppc64,
+ dwarf_vr19_ppc64,
+ dwarf_vr20_ppc64,
+ dwarf_vr21_ppc64,
+ dwarf_vr22_ppc64,
+ dwarf_vr23_ppc64,
+ dwarf_vr24_ppc64,
+ dwarf_vr25_ppc64,
+ dwarf_vr26_ppc64,
+ dwarf_vr27_ppc64,
+ dwarf_vr28_ppc64,
+ dwarf_vr29_ppc64,
+ dwarf_vr30_ppc64,
+ dwarf_vr31_ppc64,
+};
+
+} // namespace ppc64_dwarf
+
+#endif // utility_PPC64_DWARF_Registers_h_
diff --git a/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp b/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp
index d58b315d0d1d..54f773365d99 100644
--- a/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp
@@ -14,9 +14,8 @@
#include <string>
//----------------------------------------------------------------------
-// Enable enhanced mode if it is available. This allows for things like
-// \d for digit, \s for space, and many more, but it isn't available
-// everywhere.
+// Enable enhanced mode if it is available. This allows for things like \d for
+// digit, \s for space, and many more, but it isn't available everywhere.
//----------------------------------------------------------------------
#if defined(REG_ENHANCED)
#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED)
@@ -31,8 +30,8 @@ RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() {
}
//----------------------------------------------------------------------
-// Constructor that compiles "re" using "flags" and stores the
-// resulting compiled regular expression into this object.
+// Constructor that compiles "re" using "flags" and stores the resulting
+// compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(llvm::StringRef str)
: m_re(), m_comp_err(1), m_preg() {
@@ -55,17 +54,16 @@ operator=(const RegularExpression &rhs) {
//----------------------------------------------------------------------
// Destructor
//
-// Any previously compiled regular expression contained in this
-// object will be freed.
+// Any previously compiled regular expression contained in this object will be
+// freed.
//----------------------------------------------------------------------
RegularExpression::~RegularExpression() { Free(); }
//----------------------------------------------------------------------
-// Compile a regular expression using the supplied regular
-// expression text and flags. The compiled regular expression lives
-// in this object so that it can be readily used for regular
-// expression matches. Execute() can be called after the regular
-// expression is compiled. Any previously compiled regular
+// Compile a regular expression using the supplied regular expression text and
+// flags. The compiled regular expression lives in this object so that it can
+// be readily used for regular expression matches. Execute() can be called
+// after the regular expression is compiled. Any previously compiled regular
// expression contained in this object will be freed.
//
// RETURNS
@@ -75,20 +73,19 @@ RegularExpression::~RegularExpression() { Free(); }
bool RegularExpression::Compile(llvm::StringRef str) {
Free();
- // regcomp() on darwin does not recognize "" as a valid regular expression, so
- // we substitute it with an equivalent non-empty one.
+ // regcomp() on darwin does not recognize "" as a valid regular expression,
+ // so we substitute it with an equivalent non-empty one.
m_re = str.empty() ? "()" : str;
m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS);
return m_comp_err == 0;
}
//----------------------------------------------------------------------
-// Execute a regular expression match using the compiled regular
-// expression that is already in this object against the match
-// string "s". If any parens are used for regular expression
-// matches "match_count" should indicate the number of regmatch_t
-// values that are present in "match_ptr". The regular expression
-// will be executed using the "execute_flags".
+// Execute a regular expression match using the compiled regular expression
+// that is already in this object against the match string "s". If any parens
+// are used for regular expression matches "match_count" should indicate the
+// number of regmatch_t values that are present in "match_ptr". The regular
+// expression will be executed using the "execute_flags".
//---------------------------------------------------------------------
bool RegularExpression::Execute(llvm::StringRef str, Match *match) const {
int err = 1;
@@ -159,14 +156,12 @@ bool RegularExpression::Match::GetMatchSpanningIndices(
}
//----------------------------------------------------------------------
-// Returns true if the regular expression compiled and is ready
-// for execution.
+// Returns true if the regular expression compiled and is ready for execution.
//----------------------------------------------------------------------
bool RegularExpression::IsValid() const { return m_comp_err == 0; }
//----------------------------------------------------------------------
-// Returns the text that was used to compile the current regular
-// expression.
+// Returns the text that was used to compile the current regular expression.
//----------------------------------------------------------------------
llvm::StringRef RegularExpression::GetText() const { return m_re; }
diff --git a/contrib/llvm/tools/lldb/source/Utility/SelectHelper.cpp b/contrib/llvm/tools/lldb/source/Utility/SelectHelper.cpp
index 200b2ae42759..0f6a96309504 100644
--- a/contrib/llvm/tools/lldb/source/Utility/SelectHelper.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/SelectHelper.cpp
@@ -109,8 +109,8 @@ lldb_private::Status SelectHelper::Select() {
pair.second.PrepareForSelect();
const lldb::socket_t fd = pair.first;
#if !defined(__APPLE__) && !defined(_MSC_VER)
- lldbassert(fd < FD_SETSIZE);
- if (fd >= FD_SETSIZE) {
+ lldbassert(fd < static_cast<int>(FD_SETSIZE));
+ if (fd >= static_cast<int>(FD_SETSIZE)) {
error.SetErrorStringWithFormat("%i is too large for select()", fd);
return error;
}
@@ -236,8 +236,9 @@ lldb_private::Status SelectHelper::Select() {
error.SetErrorString("timed out");
return error;
} else {
- // One or more descriptors were set, update the FDInfo::select_is_set mask
- // so users can ask the SelectHelper class so clients can call one of:
+ // One or more descriptors were set, update the FDInfo::select_is_set
+ // mask so users can ask the SelectHelper class so clients can call one
+ // of:
for (auto &pair : m_fd_map) {
const int fd = pair.first;
diff --git a/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp b/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp
index cf32b21f24a6..bdaedfb9b049 100644
--- a/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp
@@ -11,8 +11,8 @@
#if defined(ENABLE_SP_LOGGING)
-// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments
-// and allow them to be queried using a pointer by a call to:
+// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments and
+// allow them to be queried using a pointer by a call to:
#include <assert.h>
#include <execinfo.h>
@@ -96,8 +96,8 @@ extern "C" void track_sp(void *sp_this, void *ptr, long use_count) {
namespace lldb {
void dump_sp_refs(void *ptr) {
- // Use a specially crafted call to "track_sp" which will
- // dump info on all live shared pointers that reference "ptr"
+ // Use a specially crafted call to "track_sp" which will dump info on all
+ // live shared pointers that reference "ptr"
track_sp(NULL, ptr, 0);
}
}
diff --git a/contrib/llvm/tools/lldb/source/Utility/Status.cpp b/contrib/llvm/tools/lldb/source/Utility/Status.cpp
index a6a889a71e54..f6dc228391b3 100644
--- a/contrib/llvm/tools/lldb/source/Utility/Status.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/Status.cpp
@@ -107,9 +107,9 @@ const Status &Status::operator=(const Status &rhs) {
Status::~Status() = default;
//----------------------------------------------------------------------
-// Get the error value as a NULL C string. The error string will be
-// fetched and cached on demand. The cached error string value will
-// remain until the error value is changed or cleared.
+// Get the error value as a NULL C string. The error string will be fetched and
+// cached on demand. The cached error string value will remain until the error
+// value is changed or cleared.
//----------------------------------------------------------------------
const char *Status::AsCString(const char *default_error_str) const {
if (Success())
@@ -161,13 +161,13 @@ Status::ValueType Status::GetError() const { return m_code; }
ErrorType Status::GetType() const { return m_type; }
//----------------------------------------------------------------------
-// Returns true if this object contains a value that describes an
-// error or otherwise non-success result.
+// Returns true if this object contains a value that describes an error or
+// otherwise non-success result.
//----------------------------------------------------------------------
bool Status::Fail() const { return m_code != 0; }
//----------------------------------------------------------------------
-// Set accesssor for the error value to "err" and the type to
+// Set accessor for the error value to "err" and the type to
// "eErrorTypeMachKernel"
//----------------------------------------------------------------------
void Status::SetMachError(uint32_t err) {
@@ -201,7 +201,7 @@ int Status::SetExpressionErrorWithFormat(lldb::ExpressionResults result,
}
//----------------------------------------------------------------------
-// Set accesssor for the error value and type.
+// Set accessor for the error value and type.
//----------------------------------------------------------------------
void Status::SetError(ValueType err, ErrorType type) {
m_code = err;
@@ -210,8 +210,7 @@ void Status::SetError(ValueType err, ErrorType type) {
}
//----------------------------------------------------------------------
-// Update the error value to be "errno" and update the type to
-// be "POSIX".
+// Update the error value to be "errno" and update the type to be "POSIX".
//----------------------------------------------------------------------
void Status::SetErrorToErrno() {
m_code = errno;
@@ -220,8 +219,8 @@ void Status::SetErrorToErrno() {
}
//----------------------------------------------------------------------
-// Update the error value to be LLDB_GENERIC_ERROR and update the type
-// to be "Generic".
+// Update the error value to be LLDB_GENERIC_ERROR and update the type to be
+// "Generic".
//----------------------------------------------------------------------
void Status::SetErrorToGenericError() {
m_code = LLDB_GENERIC_ERROR;
@@ -230,15 +229,15 @@ void Status::SetErrorToGenericError() {
}
//----------------------------------------------------------------------
-// Set accessor for the error string value for a specific error.
-// This allows any string to be supplied as an error explanation.
-// The error string value will remain until the error value is
-// cleared or a new error value/type is assigned.
+// Set accessor for the error string value for a specific error. This allows
+// any string to be supplied as an error explanation. The error string value
+// will remain until the error value is cleared or a new error value/type is
+// assigned.
//----------------------------------------------------------------------
void Status::SetErrorString(llvm::StringRef err_str) {
if (!err_str.empty()) {
- // If we have an error string, we should always at least have an error
- // set to a generic value.
+ // If we have an error string, we should always at least have an error set
+ // to a generic value.
if (Success())
SetErrorToGenericError();
}
@@ -266,8 +265,8 @@ int Status::SetErrorStringWithFormat(const char *format, ...) {
int Status::SetErrorStringWithVarArg(const char *format, va_list args) {
if (format != nullptr && format[0]) {
- // If we have an error string, we should always at least have
- // an error set to a generic value.
+ // If we have an error string, we should always at least have an error set
+ // to a generic value.
if (Success())
SetErrorToGenericError();
@@ -282,8 +281,8 @@ int Status::SetErrorStringWithVarArg(const char *format, va_list args) {
}
//----------------------------------------------------------------------
-// Returns true if the error code in this object is considered a
-// successful return value.
+// Returns true if the error code in this object is considered a successful
+// return value.
//----------------------------------------------------------------------
bool Status::Success() const { return m_code == 0; }
diff --git a/contrib/llvm/tools/lldb/source/Utility/Stream.cpp b/contrib/llvm/tools/lldb/source/Utility/Stream.cpp
index 04edc25b2b09..7df7f7008084 100644
--- a/contrib/llvm/tools/lldb/source/Utility/Stream.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/Stream.cpp
@@ -41,14 +41,12 @@ ByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
}
//------------------------------------------------------------------
-// Put an offset "uval" out to the stream using the printf format
-// in "format".
+// Put an offset "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
//------------------------------------------------------------------
-// Put an SLEB128 "uval" out to the stream using the printf format
-// in "format".
+// Put an SLEB128 "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
size_t Stream::PutSLEB128(int64_t sval) {
size_t bytes_written = 0;
@@ -73,8 +71,7 @@ size_t Stream::PutSLEB128(int64_t sval) {
}
//------------------------------------------------------------------
-// Put an ULEB128 "uval" out to the stream using the printf format
-// in "format".
+// Put an ULEB128 "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
size_t Stream::PutULEB128(uint64_t uval) {
size_t bytes_written = 0;
@@ -109,16 +106,16 @@ size_t Stream::PutCString(llvm::StringRef str) {
}
//------------------------------------------------------------------
-// Print a double quoted NULL terminated C string to the stream
-// using the printf format in "format".
+// Print a double quoted NULL terminated C string to the stream using the
+// printf format in "format".
//------------------------------------------------------------------
void Stream::QuotedCString(const char *cstr, const char *format) {
Printf(format, cstr);
}
//------------------------------------------------------------------
-// Put an address "addr" out to the stream with optional prefix
-// and suffix strings.
+// Put an address "addr" out to the stream with optional prefix and suffix
+// strings.
//------------------------------------------------------------------
void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
const char *suffix) {
@@ -132,8 +129,8 @@ void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
}
//------------------------------------------------------------------
-// Put an address range out to the stream with optional prefix
-// and suffix strings.
+// Put an address range out to the stream with optional prefix and suffix
+// strings.
//------------------------------------------------------------------
void Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr,
uint32_t addr_size, const char *prefix,
@@ -179,8 +176,8 @@ size_t Stream::PrintfVarArg(const char *format, va_list args) {
size_t Stream::EOL() { return PutChar('\n'); }
//------------------------------------------------------------------
-// Indent the current line using the current indentation level and
-// print an optional string following the indentation spaces.
+// Indent the current line using the current indentation level and print an
+// optional string following the indentation spaces.
//------------------------------------------------------------------
size_t Stream::Indent(const char *s) {
return Printf("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
@@ -529,48 +526,3 @@ size_t Stream::PutCStringAsRawHex8(const char *s) {
m_flags.Set(eBinary);
return bytes_written;
}
-
-void Stream::UnitTest(Stream *s) {
- s->PutHex8(0x12);
-
- s->PutChar(' ');
- s->PutHex16(0x3456, endian::InlHostByteOrder());
- s->PutChar(' ');
- s->PutHex16(0x3456, eByteOrderBig);
- s->PutChar(' ');
- s->PutHex16(0x3456, eByteOrderLittle);
-
- s->PutChar(' ');
- s->PutHex32(0x789abcde, endian::InlHostByteOrder());
- s->PutChar(' ');
- s->PutHex32(0x789abcde, eByteOrderBig);
- s->PutChar(' ');
- s->PutHex32(0x789abcde, eByteOrderLittle);
-
- s->PutChar(' ');
- s->PutHex64(0x1122334455667788ull, endian::InlHostByteOrder());
- s->PutChar(' ');
- s->PutHex64(0x1122334455667788ull, eByteOrderBig);
- s->PutChar(' ');
- s->PutHex64(0x1122334455667788ull, eByteOrderLittle);
-
- const char *hola = "Hello World!!!";
- s->PutChar(' ');
- s->PutCString(hola);
-
- s->PutChar(' ');
- s->Write(hola, 5);
-
- s->PutChar(' ');
- s->PutCStringAsRawHex8(hola);
-
- s->PutChar(' ');
- s->PutCStringAsRawHex8("01234");
-
- s->PutChar(' ');
- s->Printf("pid=%i", 12733);
-
- s->PutChar(' ');
- s->PrintfAsRawHex8("pid=%i", 12733);
- s->PutChar('\n');
-}
diff --git a/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp b/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
index cf5c7e227448..7528350cf759 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
@@ -74,9 +74,8 @@ char StringExtractor::GetChar(char fail_value) {
}
//----------------------------------------------------------------------
-// If a pair of valid hex digits exist at the head of the
-// StringExtractor they are decoded into an unsigned byte and returned
-// by this function
+// If a pair of valid hex digits exist at the head of the StringExtractor they
+// are decoded into an unsigned byte and returned by this function
//
// If there is not a pair of valid hex digits at the head of the
// StringExtractor, it is left unchanged and -1 is returned
@@ -96,12 +95,12 @@ int StringExtractor::DecodeHexU8() {
}
//----------------------------------------------------------------------
-// Extract an unsigned character from two hex ASCII chars in the packet
-// string, or return fail_value on failure
+// Extract an unsigned character from two hex ASCII chars in the packet string,
+// or return fail_value on failure
//----------------------------------------------------------------------
uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
- // On success, fail_value will be overwritten with the next
- // character in the stream
+ // On success, fail_value will be overwritten with the next character in the
+ // stream
GetHexU8Ex(fail_value, set_eof_on_fail);
return fail_value;
}
@@ -307,8 +306,8 @@ size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
}
//----------------------------------------------------------------------
-// Decodes all valid hex encoded bytes at the head of the
-// StringExtractor, limited by dst_len.
+// Decodes all valid hex encoded bytes at the head of the StringExtractor,
+// limited by dst_len.
//
// Returns the number of bytes successfully decoded
//----------------------------------------------------------------------
@@ -390,9 +389,9 @@ size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
llvm::StringRef &value) {
- // Read something in the form of NNNN:VVVV; where NNNN is any character
- // that is not a colon, followed by a ':' character, then a value (one or
- // more ';' chars), followed by a ';'
+ // Read something in the form of NNNN:VVVV; where NNNN is any character that
+ // is not a colon, followed by a ':' character, then a value (one or more ';'
+ // chars), followed by a ';'
if (m_index >= m_packet.size())
return fail();
diff --git a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp
index 818347a42a2c..3cae06df3b1e 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include <ctype.h> // for isxdigit
#include <string.h>
@@ -482,10 +482,9 @@ lldb_private::Status StringExtractorGDBRemote::GetStatus() {
size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
// Just get the data bytes in the string as
- // GDBRemoteCommunication::CheckForPacket()
- // already removes any 0x7d escaped characters. If any 0x7d characters are
- // left in
- // the packet, then they are supposed to be there...
+ // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
+ // characters. If any 0x7d characters are left in the packet, then they are
+ // supposed to be there...
str.clear();
const size_t bytes_left = GetBytesLeft();
if (bytes_left > 0) {
@@ -526,9 +525,9 @@ static bool JSONResponseValidator(void *,
case StringExtractorGDBRemote::eResponse:
// JSON that is returned in from JSON query packets is currently always
- // either a dictionary which starts with a '{', or an array which
- // starts with a '['. This is a quick validator to just make sure the
- // response could be valid JSON without having to validate all of the
+ // either a dictionary which starts with a '{', or an array which starts
+ // with a '['. This is a quick validator to just make sure the response
+ // could be valid JSON without having to validate all of the
// JSON content.
switch (response.GetStringRef()[0]) {
case '{':
diff --git a/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp b/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
index 492fc585ad07..55f003f245bf 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
@@ -85,8 +85,7 @@ static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) {
static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) {
// The "JSONParser::Token::ObjectStart" token should have already been
- // consumed
- // by the time this function is called
+ // consumed by the time this function is called
auto array_up = llvm::make_unique<StructuredData::Array>();
std::string value;
@@ -162,8 +161,8 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
std::string key = match.first.str();
ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
if (value.get()) {
- // Do we have additional words to descend? If not, return the
- // value we're at right now.
+ // Do we have additional words to descend? If not, return the value
+ // we're at right now.
if (match.second.empty()) {
return value;
} else {
diff --git a/contrib/llvm/tools/lldb/source/Utility/TildeExpressionResolver.cpp b/contrib/llvm/tools/lldb/source/Utility/TildeExpressionResolver.cpp
index 64a771118d6e..ae947059d8b9 100644
--- a/contrib/llvm/tools/lldb/source/Utility/TildeExpressionResolver.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/TildeExpressionResolver.cpp
@@ -14,12 +14,11 @@
#include "llvm/ADT/STLExtras.h" // for any_of
#include "llvm/ADT/SmallVector.h" // for SmallVectorImpl
-#include "llvm/Config/llvm-config.h" // for LLVM_ON_WIN32
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h" // for fs
-#if !defined(LLVM_ON_WIN32)
+#if !defined(_WIN32)
#include <pwd.h>
#endif
@@ -49,7 +48,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr,
assert(Expr.empty() || Expr[0] == '~');
Output.clear();
-#if defined(LLVM_ON_WIN32) || defined(__ANDROID__)
+#if defined(_WIN32) || defined(__ANDROID__)
return false;
#else
if (Expr.empty())
diff --git a/contrib/llvm/tools/lldb/source/Utility/UUID.cpp b/contrib/llvm/tools/lldb/source/Utility/UUID.cpp
index 98d4c30cc7f1..623ad69ddc76 100644
--- a/contrib/llvm/tools/lldb/source/Utility/UUID.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/UUID.cpp
@@ -13,62 +13,44 @@
// Project includes
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Format.h"
// C Includes
#include <ctype.h>
#include <stdio.h>
#include <string.h>
-namespace lldb_private {
-
-UUID::UUID() { Clear(); }
-
-UUID::UUID(const UUID &rhs) {
- SetBytes(rhs.m_uuid, rhs.m_num_uuid_bytes);
-}
-
-UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) {
- SetBytes(uuid_bytes, num_uuid_bytes);
-}
-
-const UUID &UUID::operator=(const UUID &rhs) {
- if (this != &rhs) {
- m_num_uuid_bytes = rhs.m_num_uuid_bytes;
- ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid));
+using namespace lldb_private;
+
+// Whether to put a separator after count uuid bytes.
+// For the first 16 bytes we follow the traditional UUID format. After that, we
+// simply put a dash after every 6 bytes.
+static inline bool separate(size_t count) {
+ if (count >= 10)
+ return (count - 10) % 6 == 0;
+
+ switch (count) {
+ case 4:
+ case 6:
+ case 8:
+ return true;
+ default:
+ return false;
}
- return *this;
}
-UUID::~UUID() {}
-
-void UUID::Clear() {
- m_num_uuid_bytes = 16;
- ::memset(m_uuid, 0, sizeof(m_uuid));
-}
+std::string UUID::GetAsString(llvm::StringRef separator) const {
+ std::string result;
+ llvm::raw_string_ostream os(result);
-const void *UUID::GetBytes() const { return m_uuid; }
+ for (auto B : llvm::enumerate(GetBytes())) {
+ if (separate(B.index()))
+ os << separator;
-std::string UUID::GetAsString(const char *separator) const {
- std::string result;
- char buf[256];
- if (!separator)
- separator = "-";
- const uint8_t *u = (const uint8_t *)GetBytes();
- if (sizeof(buf) >
- (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2."
- "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%"
- "2.2X%2.2X%2.2X",
- u[0], u[1], u[2], u[3], separator, u[4], u[5], separator,
- u[6], u[7], separator, u[8], u[9], separator, u[10],
- u[11], u[12], u[13], u[14], u[15])) {
- result.append(buf);
- if (m_num_uuid_bytes == 20) {
- if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf),
- "%s%2.2X%2.2X%2.2X%2.2X", separator,
- u[16], u[17], u[18], u[19]))
- result.append(buf);
- }
+ os << llvm::format_hex_no_prefix(B.value(), 2, true);
}
+ os.flush();
+
return result;
}
@@ -76,40 +58,6 @@ void UUID::Dump(Stream *s) const {
s->PutCString(GetAsString().c_str());
}
-bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) {
- if (uuid_bytes) {
- switch (num_uuid_bytes) {
- case 20:
- m_num_uuid_bytes = 20;
- break;
- case 16:
- m_num_uuid_bytes = 16;
- m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0;
- break;
- default:
- // Unsupported UUID byte size
- m_num_uuid_bytes = 0;
- break;
- }
-
- if (m_num_uuid_bytes > 0) {
- ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes);
- return true;
- }
- }
- ::memset(m_uuid, 0, sizeof(m_uuid));
- return false;
-}
-
-size_t UUID::GetByteSize() const { return m_num_uuid_bytes; }
-
-bool UUID::IsValid() const {
- return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] ||
- m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] ||
- m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] ||
- m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19];
-}
-
static inline int xdigit_to_int(char ch) {
ch = tolower(ch);
if (ch >= 'a' && ch <= 'f')
@@ -117,25 +65,24 @@ static inline int xdigit_to_int(char ch) {
return ch - '0';
}
-llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
- ValueType &uuid_bytes,
- uint32_t &bytes_decoded,
- uint32_t num_uuid_bytes) {
- ::memset(uuid_bytes, 0, sizeof(uuid_bytes));
- size_t uuid_byte_idx = 0;
+llvm::StringRef
+UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
+ llvm::SmallVectorImpl<uint8_t> &uuid_bytes,
+ uint32_t num_uuid_bytes) {
+ uuid_bytes.clear();
while (!p.empty()) {
if (isxdigit(p[0]) && isxdigit(p[1])) {
int hi_nibble = xdigit_to_int(p[0]);
int lo_nibble = xdigit_to_int(p[1]);
// Translate the two hex nibble characters into a byte
- uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble;
+ uuid_bytes.push_back((hi_nibble << 4) + lo_nibble);
// Skip both hex digits
p = p.drop_front(2);
- // Increment the byte that we are decoding within the UUID value
- // and break out if we are done
- if (++uuid_byte_idx == num_uuid_bytes)
+ // Increment the byte that we are decoding within the UUID value and
+ // break out if we are done
+ if (uuid_bytes.size() == num_uuid_bytes)
break;
} else if (p.front() == '-') {
// Skip dashes
@@ -145,11 +92,6 @@ llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
break;
}
}
-
- // Clear trailing bytes to 0.
- for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++)
- uuid_bytes[i] = 0;
- bytes_decoded = uuid_byte_idx;
return p;
}
@@ -159,57 +101,17 @@ size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) {
// Skip leading whitespace characters
p = p.ltrim();
- uint32_t bytes_decoded = 0;
+ llvm::SmallVector<uint8_t, 20> bytes;
llvm::StringRef rest =
- UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes);
+ UUID::DecodeUUIDBytesFromString(p, bytes, num_uuid_bytes);
// If we successfully decoded a UUID, return the amount of characters that
// were consumed
- if (bytes_decoded == num_uuid_bytes) {
- m_num_uuid_bytes = num_uuid_bytes;
+ if (bytes.size() == num_uuid_bytes) {
+ *this = fromData(bytes);
return str.size() - rest.size();
}
// Else return zero to indicate we were not able to parse a UUID value
return 0;
}
-
-size_t UUID::SetFromCString(const char *cstr, uint32_t num_uuid_bytes) {
- if (cstr == NULL)
- return 0;
-
- return SetFromStringRef(cstr, num_uuid_bytes);
-}
-}
-
-bool lldb_private::operator==(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return ::memcmp(lhs.GetBytes(), rhs.GetBytes(),
- sizeof(lldb_private::UUID::ValueType)) == 0;
-}
-
-bool lldb_private::operator!=(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return !(lhs == rhs);
-}
-
-bool lldb_private::operator<(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return ::memcmp(lhs.GetBytes(), rhs.GetBytes(),
- sizeof(lldb_private::UUID::ValueType)) < 0;
-}
-
-bool lldb_private::operator<=(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return !(lhs > rhs);
-}
-
-bool lldb_private::operator>(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return rhs < lhs;
-}
-
-bool lldb_private::operator>=(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return !(lhs < rhs);
-}
diff --git a/contrib/llvm/tools/lldb/source/Utility/VASprintf.cpp b/contrib/llvm/tools/lldb/source/Utility/VASprintf.cpp
index e950fb75cfa0..900d9754a9b4 100644
--- a/contrib/llvm/tools/lldb/source/Utility/VASprintf.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/VASprintf.cpp
@@ -36,8 +36,8 @@ bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
}
if (size_t(length) >= buf.size()) {
- // The error formatted string didn't fit into our buffer, resize it
- // to the exact needed size, and retry
+ // The error formatted string didn't fit into our buffer, resize it to the
+ // exact needed size, and retry
buf.resize(length + 1);
length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args);
if (length < 0) {
diff --git a/contrib/llvm/tools/lldb/source/Utility/VMRange.cpp b/contrib/llvm/tools/lldb/source/Utility/VMRange.cpp
index 105b1a58c48c..7e35d3ef0c65 100644
--- a/contrib/llvm/tools/lldb/source/Utility/VMRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/VMRange.cpp
@@ -24,14 +24,16 @@ using namespace lldb_private;
bool VMRange::ContainsValue(const VMRange::collection &coll,
lldb::addr_t value) {
- ValueInRangeUnaryPredicate in_range_predicate(value);
- return llvm::find_if(coll, in_range_predicate) != coll.end();
+ return llvm::find_if(coll, [&](const VMRange &r) {
+ return r.Contains(value);
+ }) != coll.end();
}
bool VMRange::ContainsRange(const VMRange::collection &coll,
const VMRange &range) {
- RangeInRangeUnaryPredicate in_range_predicate(range);
- return llvm::find_if(coll, in_range_predicate) != coll.end();
+ return llvm::find_if(coll, [&](const VMRange &r) {
+ return r.Contains(range);
+ }) != coll.end();
}
void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const {
diff --git a/contrib/llvm/tools/lldb/tools/driver/Driver.cpp b/contrib/llvm/tools/lldb/tools/driver/Driver.cpp
index 7e1dec7a34fa..f3391a55e0d1 100644
--- a/contrib/llvm/tools/lldb/tools/driver/Driver.cpp
+++ b/contrib/llvm/tools/lldb/tools/driver/Driver.cpp
@@ -41,7 +41,10 @@
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
#include <thread>
#if !defined(__APPLE__)
@@ -866,7 +869,6 @@ SBError Driver::ParseArgs(int argc, const char *argv[], FILE *out_fh,
} else {
// Skip any options we consumed with getopt_long_only
argc -= optind;
- // argv += optind; // Commented out to keep static analyzer happy
if (argc > 0)
::fprintf(out_fh,
@@ -963,7 +965,7 @@ std::string EscapeString(std::string arg) {
return '"' + arg + '"';
}
-void Driver::MainLoop() {
+int Driver::MainLoop() {
if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) {
g_old_stdin_termios_is_valid = true;
atexit(reset_stdin_termios);
@@ -1002,6 +1004,10 @@ void Driver::MainLoop() {
result.PutOutput(m_debugger.GetOutputFileHandle());
}
+ // We allow the user to specify an exit code when calling quit which we will
+ // return when exiting.
+ m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true);
+
// Now we handle options we got from the command line
SBStream commands_stream;
@@ -1160,7 +1166,9 @@ void Driver::MainLoop() {
reset_stdin_termios();
fclose(stdin);
+ int exit_code = sb_interpreter.GetQuitStatus();
SBDebugger::Destroy(m_debugger);
+ return exit_code;
}
void Driver::ResizeWindow(unsigned short col) {
@@ -1226,6 +1234,10 @@ main(int argc, char const *argv[])
const char **argv = argvPointers.data();
#endif
+ llvm::StringRef ToolName = argv[0];
+ llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
+ llvm::PrettyStackTraceProgram X(argc, argv);
+
SBDebugger::Initialize();
SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
@@ -1238,6 +1250,7 @@ main(int argc, char const *argv[])
signal(SIGCONT, sigcont_handler);
#endif
+ int exit_code = 0;
// Create a scope for driver so that the driver object will destroy itself
// before SBDebugger::Terminate() is called.
{
@@ -1246,14 +1259,15 @@ main(int argc, char const *argv[])
bool exiting = false;
SBError error(driver.ParseArgs(argc, argv, stdout, exiting));
if (error.Fail()) {
+ exit_code = 1;
const char *error_cstr = error.GetCString();
if (error_cstr)
::fprintf(stderr, "error: %s\n", error_cstr);
} else if (!exiting) {
- driver.MainLoop();
+ exit_code = driver.MainLoop();
}
}
SBDebugger::Terminate();
- return 0;
+ return exit_code;
}
diff --git a/contrib/llvm/tools/lldb/tools/driver/Driver.h b/contrib/llvm/tools/lldb/tools/driver/Driver.h
index 2be697ccc44c..34746a239999 100644
--- a/contrib/llvm/tools/lldb/tools/driver/Driver.h
+++ b/contrib/llvm/tools/lldb/tools/driver/Driver.h
@@ -37,7 +37,10 @@ public:
virtual ~Driver();
- void MainLoop();
+ /// Runs the main loop.
+ ///
+ /// @return The exit code that the process should return.
+ int MainLoop();
lldb::SBError ParseArgs(int argc, const char *argv[], FILE *out_fh,
bool &do_exit);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp
index cd5bf27c73fe..613f005cf754 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp
@@ -214,6 +214,64 @@ void CMICmdBase::SetError(const CMIUtilString &rErrMsg) {
//++
//------------------------------------------------------------------------------------
+// Details: Short cut function to check MI command's execute status and
+// set an error in case of failure.
+// Type: Method.
+// Args: error - (R) Error description object.
+// successHandler - (R) function describing actions to execute
+// in case of success state of passed SBError object.
+// errorHandler - (R) function describing actions to execute
+// in case of fail status of passed SBError object.
+// Return: bool.
+// Throws: None.
+//--
+bool CMICmdBase::HandleSBError(const lldb::SBError &error,
+ const std::function<bool()> &successHandler,
+ const std::function<void()> &errorHandler) {
+ if (error.Success())
+ return successHandler();
+
+ SetError(error.GetCString());
+ errorHandler();
+ return MIstatus::failure;
+}
+
+//++
+//------------------------------------------------------------------------------------
+// Details: Short cut function to check MI command's execute status and
+// call specified handler function for success case.
+// Type: Method.
+// Args: error - (R) Error description object.
+// successHandler - (R) function describing actions to execute
+// in case of success state of passed SBError object.
+// Return: bool.
+// Throws: None.
+//--
+bool CMICmdBase::HandleSBErrorWithSuccess(
+ const lldb::SBError &error,
+ const std::function<bool()> &successHandler) {
+ return HandleSBError(error, successHandler);
+}
+
+//++
+//------------------------------------------------------------------------------------
+// Details: Short cut function to check MI command's execute status and
+// call specified handler function for error case.
+// Type: Method.
+// Args: error - (R) Error description object.
+// errorHandler - (R) function describing actions to execute
+// in case of fail status of passed SBError object.
+// Return: bool.
+// Throws: None.
+//--
+bool CMICmdBase::HandleSBErrorWithFailure(
+ const lldb::SBError &error,
+ const std::function<void()> &errorHandler) {
+ return HandleSBError(error, [] { return MIstatus::success; }, errorHandler);
+}
+
+//++
+//------------------------------------------------------------------------------------
// Details: Ask a command to provide its unique identifier.
// Type: Method.
// Args: A unique identifier for this command class.
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h
index 66f9fa6ee5d7..cb44504a1613 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h
@@ -11,7 +11,11 @@
// C Includes
// C++ Includes
+#include <functional> // for function
+
// Other libraries and framework includes
+#include "lldb/API/SBError.h"
+
// Project includes
#include "MICmdArgSet.h"
#include "MICmdData.h"
@@ -80,6 +84,14 @@ public:
// Methods:
protected:
void SetError(const CMIUtilString &rErrMsg);
+ bool HandleSBError(const lldb::SBError &error,
+ const std::function<bool()> &successHandler =
+ [] { return MIstatus::success; },
+ const std::function<void()> &errorHandler = [] {});
+ bool HandleSBErrorWithSuccess(const lldb::SBError &error,
+ const std::function<bool()> &successHandler);
+ bool HandleSBErrorWithFailure(const lldb::SBError &error,
+ const std::function<void()> &errorHandler);
template <class T> T *GetOption(const CMIUtilString &vStrOptionName);
bool ParseValidateCmdOptions();
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
index 020ac982d11a..caad9192366f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
@@ -148,6 +148,11 @@ bool CMICmdCmdBreakInsert::Execute() {
CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort,
m_constStrArgNamedRestrictBrkPtToThreadId);
+ // Ask LLDB for the target to check if we have valid or dummy one.
+ CMICmnLLDBDebugSessionInfo &rSessionInfo(
+ CMICmnLLDBDebugSessionInfo::Instance());
+ lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
+
m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound();
m_bBrkPtIsTemp = pArgTempBrkPt->GetFound();
m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound();
@@ -157,7 +162,12 @@ bool CMICmdCmdBreakInsert::Execute() {
nThreadGrp);
m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp);
}
- m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
+
+ if (sbTarget == rSessionInfo.GetDebugger().GetDummyTarget())
+ m_bBrkPtIsPending = true;
+ else
+ m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
+
if (pArgLocation->GetFound())
m_brkName = pArgLocation->GetValue();
else if (m_bBrkPtIsPending) {
@@ -225,9 +235,6 @@ bool CMICmdCmdBreakInsert::Execute() {
// Ask LLDB to create a breakpoint
bool bOk = MIstatus::success;
- CMICmnLLDBDebugSessionInfo &rSessionInfo(
- CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
switch (eBrkPtType) {
case eBreakPoint_ByAddress:
m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp
index 729ab3970cf1..53c2d7e621a7 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp
@@ -19,15 +19,14 @@
// CMICmdCmdDataInfoLine implementation.
// Third Party Headers:
-#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBInstruction.h"
#include "lldb/API/SBInstructionList.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBThread.h"
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Regex.h"
#include <inttypes.h> // For PRIx64
+#include <string>
// In-house headers:
#include "MICmdArgValConsume.h"
@@ -45,6 +44,13 @@
#include "MICmnLLDBUtilSBValue.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueConst.h"
+#include "Platform.h"
+
+namespace {
+CMIUtilString IntToHexAddrStr(uint32_t number) {
+ return CMIUtilString("0x" + llvm::Twine::utohexstr(number).str());
+}
+} // namespace
//++
//------------------------------------------------------------------------------------
@@ -1588,7 +1594,9 @@ CMICmdBase *CMICmdCmdDataWriteMemory::CreateSelf() {
// Throws: None.
//--
CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
- : m_constStrArgLocation("location") {
+ : m_constStrArgLocation("location"),
+ m_resultRecord(m_cmdData.strMiCmdToken,
+ CMICmnMIResultRecord::eResultClass_Done) {
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "data-info-line";
@@ -1604,7 +1612,7 @@ CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() {}
+CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() = default;
//++
//------------------------------------------------------------------------------------
@@ -1637,98 +1645,84 @@ bool CMICmdCmdDataInfoLine::ParseArgs() {
bool CMICmdCmdDataInfoLine::Execute() {
CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
+ lldb::SBLineEntry line;
+ bool found_line = false;
const CMIUtilString &strLocation(pArgLocation->GetValue());
- CMIUtilString strCmdOptionsLocation;
+ lldb::SBTarget target = CMICmnLLDBDebugSessionInfo::Instance().GetTarget();
+
if (strLocation.at(0) == '*') {
// Parse argument:
// *0x12345
- // ^^^^^^^ -- address
- const CMIUtilString strAddress(strLocation.substr(1));
- strCmdOptionsLocation =
- CMIUtilString::Format("--address %s", strAddress.c_str());
+ // ^^^^^^^^^ -- address
+ lldb::addr_t address = 0x0;
+ if (llvm::StringRef(strLocation.substr(1)).getAsInteger(0, address)) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR),
+ m_cmdData.strMiCmd.c_str(),
+ "Failed to parse address."));
+ return MIstatus::failure;
+ }
+ line = target.ResolveFileAddress(address).GetLineEntry();
+ // Check that found line is valid.
+ if (line.GetLine())
+ found_line = true;
} else {
const size_t nLineStartPos = strLocation.rfind(':');
if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) ||
(nLineStartPos == strLocation.length() - 1)) {
- SetError(
- CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT),
- m_cmdData.strMiCmd.c_str(), strLocation.c_str())
- .c_str());
+ SetError(CMIUtilString::Format(
+ MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT),
+ m_cmdData.strMiCmd.c_str(), strLocation.c_str()));
return MIstatus::failure;
}
// Parse argument:
// hello.cpp:5
// ^^^^^^^^^ -- file
// ^ -- line
- const CMIUtilString strFile(strLocation.substr(0, nLineStartPos));
- const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1));
- strCmdOptionsLocation =
- CMIUtilString::Format("--file \"%s\" --line %s",
- strFile.AddSlashes().c_str(), strLine.c_str());
+ const CMIUtilString &strFile(strLocation.substr(0, nLineStartPos));
+ uint32_t numLine = 0;
+ llvm::StringRef(strLocation.substr(nLineStartPos + 1))
+ .getAsInteger(0, numLine);
+ lldb::SBSymbolContextList sc_cu_list =
+ target.FindCompileUnits(lldb::SBFileSpec(strFile.c_str(), false));
+ for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) {
+ const lldb::SBCompileUnit &cu =
+ sc_cu_list.GetContextAtIndex(i).GetCompileUnit();
+ // Break if we have already found requested line.
+ if (found_line)
+ break;
+ for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) {
+ const lldb::SBLineEntry &curLine = cu.GetLineEntryAtIndex(j);
+ if (curLine.GetLine() == numLine) {
+ line = curLine;
+ found_line = true;
+ break;
+ }
+ }
+ }
}
- const CMIUtilString strCmd(CMIUtilString::Format(
- "target modules lookup -v %s", strCmdOptionsLocation.c_str()));
-
- CMICmnLLDBDebugSessionInfo &rSessionInfo(
- CMICmnLLDBDebugSessionInfo::Instance());
- const lldb::ReturnStatus rtn =
- rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
- strCmd.c_str(), m_lldbResult);
- MIunused(rtn);
-
- return MIstatus::success;
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: Helper function for parsing a line entry returned from lldb for the
-// command:
-// target modules lookup -v <location>
-// where the line entry is of the format:
-// LineEntry: \[0x0000000100000f37-0x0000000100000f45\):
-// /path/file:3[:1]
-// start end file
-// line column(opt)
-// Args: input - (R) Input string to parse.
-// start - (W) String representing the start address.
-// end - (W) String representing the end address.
-// file - (W) String representing the file.
-// line - (W) String representing the line.
-// Return: bool - True = input was parsed successfully, false = input could not
-// be parsed.
-// Throws: None.
-//--
-static bool ParseLLDBLineEntry(const char *input, CMIUtilString &start,
- CMIUtilString &end, CMIUtilString &file,
- CMIUtilString &line) {
- // Note: Ambiguities arise because the column is optional, and
- // because : can appear in filenames or as a byte in a multibyte
- // UTF8 character. We keep those cases to a minimum by using regex
- // to work on the string from both the left and right, so that what
- // is remains is assumed to be the filename.
-
- // Match LineEntry using regex.
- static llvm::Regex g_lineentry_nocol_regex(llvm::StringRef(
- "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$"));
- static llvm::Regex g_lineentry_col_regex(
- llvm::StringRef("^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): "
- "(.+):([0-9]+):[0-9]+$"));
- // ^1=start ^2=end ^3=f
- // ^4=line ^5=:col(opt)
-
- llvm::SmallVector<llvm::StringRef, 6> match;
-
- // First try matching the LineEntry with the column,
- // then try without the column.
- const bool ok = g_lineentry_col_regex.match(input, &match) ||
- g_lineentry_nocol_regex.match(input, &match);
- if (ok) {
- start = match[1];
- end = match[2];
- file = match[3];
- line = match[4];
+ if (!found_line) {
+ SetError(CMIUtilString::Format(
+ MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
+ "The LineEntry is absent or has an unknown format."));
+ return MIstatus::failure;
}
- return ok;
+ // Start address.
+ m_resultRecord.Add(CMICmnMIValueResult(
+ "start", CMICmnMIValueConst(IntToHexAddrStr(
+ line.GetStartAddress().GetFileAddress()))));
+ // End address.
+ m_resultRecord.Add(CMICmnMIValueResult(
+ "end", CMICmnMIValueConst(IntToHexAddrStr(
+ line.GetEndAddress().GetFileAddress()))));
+ // File.
+ std::unique_ptr<char[]> upPath(new char[PATH_MAX]);
+ line.GetFileSpec().GetPath(upPath.get(), PATH_MAX);
+ m_resultRecord.Add(CMICmnMIValueResult(
+ "file", CMICmnMIValueConst(CMIUtilString(upPath.get()))));
+ // Line.
+ m_resultRecord.Add(CMICmnMIValueResult(
+ "line", CMICmnMIValueConst(std::to_string(line.GetLine()))));
+ return MIstatus::success;
}
//++
@@ -1743,66 +1737,7 @@ static bool ParseLLDBLineEntry(const char *input, CMIUtilString &start,
// Throws: None.
//--
bool CMICmdCmdDataInfoLine::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("msg", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- return MIstatus::success;
- } else if (m_lldbResult.GetOutputSize() > 0) {
- CMIUtilString::VecString_t vecLines;
- const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
- const MIuint nLines(strLldbMsg.SplitLines(vecLines));
-
- for (MIuint i = 0; i < nLines; ++i) {
- // String looks like:
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\):
- // /path/to/file:3[:1]
- const CMIUtilString &rLine(vecLines[i]);
- CMIUtilString strStart;
- CMIUtilString strEnd;
- CMIUtilString strFile;
- CMIUtilString strLine;
-
- if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile,
- strLine))
- continue;
-
- const CMICmnMIValueConst miValueConst(strStart);
- const CMICmnMIValueResult miValueResult("start", miValueConst);
- CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
- miValueResult);
- const CMICmnMIValueConst miValueConst2(strEnd);
- const CMICmnMIValueResult miValueResult2("end", miValueConst2);
- miRecordResult.Add(miValueResult2);
- const CMICmnMIValueConst miValueConst3(strFile);
- const CMICmnMIValueResult miValueResult3("file", miValueConst3);
- miRecordResult.Add(miValueResult3);
- const CMICmnMIValueConst miValueConst4(strLine);
- const CMICmnMIValueResult miValueResult4("line", miValueConst4);
- miRecordResult.Add(miValueResult4);
-
- // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
- m_miResultRecord = miRecordResult;
-
- return MIstatus::success;
- }
- }
-
- // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is
- // absent or has an unknown format.\""
- const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
- MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
- "The LineEntry is absent or has an unknown format."));
- const CMICmnMIValueResult miValueResult("msg", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
-
+ m_miResultRecord = m_resultRecord;
return MIstatus::success;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h
index ab8d6ba5cd19..0317db11a535 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h
@@ -34,7 +34,6 @@
#pragma once
// Third party headers:
-#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBError.h"
// In-house headers:
@@ -42,6 +41,7 @@
#include "MICmnLLDBDebugSessionInfoVarObj.h"
#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
+#include "MICmnMIResultRecord.h"
//++
//============================================================================
@@ -377,6 +377,6 @@ public:
// Attributes:
private:
- lldb::SBCommandReturnObject m_lldbResult;
const CMIUtilString m_constStrArgLocation;
+ CMICmnMIResultRecord m_resultRecord;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp
index 8fa63f4d98e6..1102b952407e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp
@@ -22,6 +22,7 @@
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
+#include "lldb/API/SBThread.h"
#include "lldb/lldb-enumerations.h"
// In-house headers:
@@ -99,6 +100,19 @@ bool CMICmdCmdExecRun::ParseArgs() {
bool CMICmdCmdExecRun::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
+
+ {
+ // Check we have a valid target.
+ // Note: target created via 'file-exec-and-symbols' command.
+ lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
+ if (!sbTarget.IsValid() ||
+ sbTarget == rSessionInfo.GetDebugger().GetDummyTarget()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
+ m_cmdData.strMiCmd.c_str()));
+ return MIstatus::failure;
+ }
+ }
+
lldb::SBError error;
lldb::SBStream errMsg;
lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo();
@@ -112,21 +126,25 @@ bool CMICmdCmdExecRun::Execute() {
}
lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error);
- if ((!process.IsValid()) || (error.Fail())) {
+ if (!process.IsValid()) {
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
m_cmdData.strMiCmd.c_str(),
errMsg.GetData()));
return MIstatus::failure;
}
- if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) {
- const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
- SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
- m_cmdData.strMiCmd.c_str(),
- rErrMsg.c_str()));
- return MIstatus::failure;
- }
- return MIstatus::success;
+ const auto successHandler = [this] {
+ if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) {
+ const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
+ SetError(CMIUtilString::Format(
+ MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
+ m_cmdData.strMiCmd.c_str(), rErrMsg.c_str()));
+ return MIstatus::failure;
+ }
+ return MIstatus::success;
+ };
+
+ return HandleSBErrorWithSuccess(error, successHandler);
}
//++
@@ -142,9 +160,8 @@ bool CMICmdCmdExecRun::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecRun::Acknowledge() {
- const CMICmnMIResultRecord miRecordResult(
+ m_miResultRecord = CMICmnMIResultRecord(
m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
@@ -219,35 +236,21 @@ CMICmdCmdExecContinue::~CMICmdCmdExecContinue() {}
// Throws: None.
//--
bool CMICmdCmdExecContinue::Execute() {
- const char *pCmd = "continue";
- CMICmnLLDBDebugSessionInfo &rSessionInfo(
- CMICmnLLDBDebugSessionInfo::Instance());
- const lldb::ReturnStatus rtn =
- rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
- pCmd, m_lldbResult);
- MIunused(rtn);
-
- if (m_lldbResult.GetErrorSize() == 0) {
+ const auto successHandler = [this] {
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) {
const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
- SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
- m_cmdData.strMiCmd.c_str(),
- rErrMsg.c_str()));
+ SetError(CMIUtilString::Format(
+ MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
+ m_cmdData.strMiCmd.c_str(), rErrMsg.c_str()));
return MIstatus::failure;
}
- } else {
- // ToDo: Re-evaluate if this is required when application near finished as
- // this is parsing LLDB error message
- // which seems a hack and is code brittle
- const char *pLldbErr = m_lldbResult.GetError();
- const CMIUtilString strLldbMsg(CMIUtilString(pLldbErr).StripCREndOfLine());
- if (strLldbMsg == "error: Process must be launched.") {
- CMIDriver::Instance().SetExitApplicationFlag(true);
- }
- }
+ return MIstatus::success;
+ };
- return MIstatus::success;
+ return HandleSBErrorWithSuccess(
+ CMICmnLLDBDebugSessionInfo::Instance().GetProcess().Continue(),
+ successHandler);
}
//++
@@ -262,19 +265,8 @@ bool CMICmdCmdExecContinue::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecContinue::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
return MIstatus::success;
}
@@ -365,14 +357,22 @@ bool CMICmdCmdExecNext::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
- CMIUtilString strCmd("thread step-over");
- if (nThreadId != UINT64_MAX)
- strCmd += CMIUtilString::Format(" %llu", nThreadId);
- rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult,
- false);
- return MIstatus::success;
+ lldb::SBError error;
+ if (nThreadId != UINT64_MAX) {
+ lldb::SBThread sbThread = rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId);
+ if (!sbThread.IsValid()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
+ m_cmdData.strMiCmd.c_str(),
+ m_constStrArgThread.c_str()));
+ return MIstatus::failure;
+ }
+ sbThread.StepOver(lldb::eOnlyDuringStepping, error);
+ } else
+ rSessionInfo.GetProcess().GetSelectedThread().StepOver(
+ lldb::eOnlyDuringStepping, error);
+
+ return HandleSBError(error);
}
//++
@@ -387,21 +387,8 @@ bool CMICmdCmdExecNext::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecNext::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const char *pLldbErr = m_lldbResult.GetError();
- MIunused(pLldbErr);
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
return MIstatus::success;
}
@@ -490,14 +477,23 @@ bool CMICmdCmdExecStep::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
- CMIUtilString strCmd("thread step-in");
- if (nThreadId != UINT64_MAX)
- strCmd += CMIUtilString::Format(" %llu", nThreadId);
- rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult,
- false);
- return MIstatus::success;
+ lldb::SBError error;
+ if (nThreadId != UINT64_MAX) {
+ lldb::SBThread sbThread =
+ rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId);
+ if (!sbThread.IsValid()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
+ m_cmdData.strMiCmd.c_str(),
+ m_constStrArgThread.c_str()));
+ return MIstatus::failure;
+ }
+ sbThread.StepInto(nullptr, LLDB_INVALID_LINE_NUMBER, error);
+ } else
+ rSessionInfo.GetProcess().GetSelectedThread().StepInto(
+ nullptr, LLDB_INVALID_LINE_NUMBER, error);
+
+ return HandleSBError(error);
}
//++
@@ -512,21 +508,8 @@ bool CMICmdCmdExecStep::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecStep::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const char *pLldbErr = m_lldbResult.GetError();
- MIunused(pLldbErr);
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
return MIstatus::success;
}
@@ -616,14 +599,23 @@ bool CMICmdCmdExecNextInstruction::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
- CMIUtilString strCmd("thread step-inst-over");
- if (nThreadId != UINT64_MAX)
- strCmd += CMIUtilString::Format(" %llu", nThreadId);
- rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult,
- false);
- return MIstatus::success;
+ lldb::SBError error;
+ if (nThreadId != UINT64_MAX) {
+ lldb::SBThread sbThread =
+ rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId);
+ if (!sbThread.IsValid()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
+ m_cmdData.strMiCmd.c_str(),
+ m_constStrArgThread.c_str()));
+ return MIstatus::failure;
+ }
+ sbThread.StepInstruction(true, error);
+ } else
+ rSessionInfo.GetProcess().GetSelectedThread().StepInstruction(
+ true, error);
+
+ return HandleSBError(error);
}
//++
@@ -638,21 +630,8 @@ bool CMICmdCmdExecNextInstruction::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecNextInstruction::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const char *pLldbErr = m_lldbResult.GetError();
- MIunused(pLldbErr);
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
return MIstatus::success;
}
@@ -744,14 +723,23 @@ bool CMICmdCmdExecStepInstruction::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
- CMIUtilString strCmd("thread step-inst");
- if (nThreadId != UINT64_MAX)
- strCmd += CMIUtilString::Format(" %llu", nThreadId);
- rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult,
- false);
- return MIstatus::success;
+ lldb::SBError error;
+ if (nThreadId != UINT64_MAX) {
+ lldb::SBThread sbThread =
+ rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId);
+ if (!sbThread.IsValid()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
+ m_cmdData.strMiCmd.c_str(),
+ m_constStrArgThread.c_str()));
+ return MIstatus::failure;
+ }
+ sbThread.StepInstruction(false, error);
+ } else
+ rSessionInfo.GetProcess().GetSelectedThread().StepInstruction(
+ false, error);
+
+ return HandleSBError(error);
}
//++
@@ -766,21 +754,8 @@ bool CMICmdCmdExecStepInstruction::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecStepInstruction::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const char *pLldbErr = m_lldbResult.GetError();
- MIunused(pLldbErr);
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
return MIstatus::success;
}
@@ -868,14 +843,22 @@ bool CMICmdCmdExecFinish::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
- CMIUtilString strCmd("thread step-out");
- if (nThreadId != UINT64_MAX)
- strCmd += CMIUtilString::Format(" %llu", nThreadId);
- rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult,
- false);
- return MIstatus::success;
+ lldb::SBError error;
+ if (nThreadId != UINT64_MAX) {
+ lldb::SBThread sbThread =
+ rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId);
+ if (!sbThread.IsValid()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
+ m_cmdData.strMiCmd.c_str(),
+ m_constStrArgThread.c_str()));
+ return MIstatus::failure;
+ }
+ sbThread.StepOut(error);
+ } else
+ rSessionInfo.GetProcess().GetSelectedThread().StepOut(error);
+
+ return HandleSBError(error);
}
//++
@@ -890,21 +873,8 @@ bool CMICmdCmdExecFinish::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecFinish::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const char *pLldbErr = m_lldbResult.GetError();
- MIunused(pLldbErr);
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
return MIstatus::success;
}
@@ -965,25 +935,22 @@ CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt() {}
// Throws: None.
//--
bool CMICmdCmdExecInterrupt::Execute() {
- CMICmnLLDBDebugSessionInfo &rSessionInfo(
- CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
- CMIUtilString strCmd("process interrupt");
- const lldb::ReturnStatus status =
- rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(),
- m_lldbResult, false);
- MIunused(status);
-
- // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
- if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) {
- const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
- SetErrorDescription(
- CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
- strCmd.c_str(), rErrMsg.c_str()));
- return MIstatus::failure;
- }
+ const auto successHandler = [this] {
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) {
+ const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
+ SetErrorDescription(CMIUtilString::Format(
+ MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
+ m_cmdData.strMiCmd.c_str(),
+ rErrMsg.c_str()));
+ return MIstatus::failure;
+ }
+ return MIstatus::success;
+ };
- return MIstatus::success;
+ return HandleSBErrorWithSuccess(
+ CMICmnLLDBDebugSessionInfo::Instance().GetProcess().Stop(),
+ successHandler);
}
//++
@@ -998,19 +965,8 @@ bool CMICmdCmdExecInterrupt::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecInterrupt::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
- m_miResultRecord = miRecordResult;
- }
-
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
return MIstatus::success;
}
@@ -1130,10 +1086,8 @@ bool CMICmdCmdExecArguments::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecArguments::Acknowledge() {
- const CMICmnMIResultRecord miRecordResult(
+ m_miResultRecord = CMICmnMIResultRecord(
m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
- m_miResultRecord = miRecordResult;
-
return MIstatus::success;
}
@@ -1226,9 +1180,8 @@ bool CMICmdCmdExecAbort::Execute() {
// Throws: None.
//--
bool CMICmdCmdExecAbort::Acknowledge() {
- const CMICmnMIResultRecord miRecordResult(
+ m_miResultRecord = CMICmnMIResultRecord(
m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
- m_miResultRecord = miRecordResult;
return MIstatus::success;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h
index 46e7783c91ef..451d25e29eb1 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h
@@ -33,8 +33,6 @@
#pragma once
// Third party headers:
-#include "lldb/API/SBCommandReturnObject.h"
-
// In-house headers:
#include "MICmdBase.h"
@@ -66,7 +64,6 @@ public:
private:
const CMIUtilString m_constStrArgStart; // StopAtEntry - run to first
// instruction or main() if specified
- lldb::SBCommandReturnObject m_lldbResult;
};
//++
@@ -91,10 +88,6 @@ public:
bool Acknowledge() override;
// From CMICmnBase
/* dtor */ ~CMICmdCmdExecContinue() override;
-
- // Attributes:
-private:
- lldb::SBCommandReturnObject m_lldbResult;
};
//++
@@ -123,7 +116,6 @@ public:
// Attributes:
private:
- lldb::SBCommandReturnObject m_lldbResult;
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but
// Eclipse gives this option
};
@@ -154,7 +146,6 @@ public:
// Attributes:
private:
- lldb::SBCommandReturnObject m_lldbResult;
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but
// Eclipse gives this option
};
@@ -185,7 +176,6 @@ public:
// Attributes:
private:
- lldb::SBCommandReturnObject m_lldbResult;
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but
// Eclipse gives this option
};
@@ -216,7 +206,6 @@ public:
// Attributes:
private:
- lldb::SBCommandReturnObject m_lldbResult;
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but
// Eclipse gives this option
};
@@ -244,10 +233,6 @@ public:
bool ParseArgs() override;
// From CMICmnBase
/* dtor */ ~CMICmdCmdExecFinish() override;
-
- // Attributes:
-private:
- lldb::SBCommandReturnObject m_lldbResult;
};
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
@@ -276,10 +261,6 @@ public:
bool Acknowledge() override;
// From CMICmnBase
/* dtor */ ~CMICmdCmdExecInterrupt() override;
-
- // Attributes:
-private:
- lldb::SBCommandReturnObject m_lldbResult;
};
//++
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
index 7b302b12b607..008e98d02e74 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
@@ -10,18 +10,36 @@
// Overview: CMICmdCmdSymbolListLines implementation.
// Third Party Headers:
-#include "lldb/API/SBCommandInterpreter.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Regex.h"
+#include "llvm/ADT/Twine.h"
+#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBLineEntry.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBCompileUnit.h"
+#include "lldb/API/SBSymbolContext.h"
+#include "lldb/API/SBSymbolContextList.h"
// In-house headers:
#include "MICmdArgValFile.h"
#include "MICmdCmdSymbol.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnMIResultRecord.h"
-#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueResult.h"
+
+namespace {
+const CMICmnMIValueTuple
+CreateMITuplePCLine(const uint32_t addr, const uint32_t line_number) {
+ const CMICmnMIValueConst miValueConstAddr("0x" + llvm::Twine::utohexstr(addr).str());
+ const CMICmnMIValueConst miValueConstLine(llvm::Twine(line_number).str());
+ const CMICmnMIValueResult miValueResultAddr("pc", miValueConstAddr);
+ const CMICmnMIValueResult miValueResultLine("line", miValueConstLine);
+ CMICmnMIValueTuple miValueTuple(miValueResultAddr);
+ miValueTuple.Add(miValueResultLine);
+ return miValueTuple;
+}
+} // namespace
+
+using namespace lldb; // For operator==(const SBAddress &, const SBAddress &).
//++
//------------------------------------------------------------------------------------
@@ -32,7 +50,7 @@
// Throws: None.
//--
CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines()
- : m_constStrArgNameFile("file") {
+ : m_resultList(false), m_constStrArgNameFile("file") {
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "symbol-list-lines";
@@ -84,93 +102,51 @@ bool CMICmdCmdSymbolListLines::ParseArgs() {
bool CMICmdCmdSymbolListLines::Execute() {
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
- const CMIUtilString &strFilePath(pArgFile->GetValue());
- const CMIUtilString strCmd(CMIUtilString::Format(
- "source info --file \"%s\"", strFilePath.AddSlashes().c_str()));
-
- CMICmnLLDBDebugSessionInfo &rSessionInfo(
- CMICmnLLDBDebugSessionInfo::Instance());
- const lldb::ReturnStatus rtn =
- rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
- strCmd.c_str(), m_lldbResult);
- MIunused(rtn);
-
- return MIstatus::success;
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: Helper function for parsing the header returned from lldb for the
-// command:
-// target modules dump line-table <file>
-// where the header is of the format:
-// Line table for /path/to/file in `/path/to/module
-// Args: input - (R) Input string to parse.
-// file - (W) String representing the file.
-// Return: bool - True = input was parsed successfully, false = input could not
-// be parsed.
-// Throws: None.
-//--
-static bool ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) {
- // Match LineEntry using regex.
- static llvm::Regex g_lineentry_header_regex(llvm::StringRef(
- "^ *Lines found for file (.+) in compilation unit (.+) in `(.+)$"));
- // ^1=file ^2=cu
- // ^3=module
-
- llvm::SmallVector<llvm::StringRef, 4> match;
-
- const bool ok = g_lineentry_header_regex.match(input, &match);
- if (ok)
- file = match[1];
- return ok;
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: Helper function for parsing a line entry returned from lldb for the
-// command:
-// target modules dump line-table <file>
-// where the line entry is of the format:
-// 0x0000000100000e70: /path/to/file:3002[:4]
-// addr file line column(opt)
-// Args: input - (R) Input string to parse.
-// addr - (W) String representing the pc address.
-// file - (W) String representing the file.
-// line - (W) String representing the line.
-// Return: bool - True = input was parsed successfully, false = input could not
-// be parsed.
-// Throws: None.
-//--
-static bool ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr,
- CMIUtilString &file,
- CMIUtilString &line) {
- // Note: Ambiguities arise because the column is optional, and
- // because : can appear in filenames or as a byte in a multibyte
- // UTF8 character. We keep those cases to a minimum by using regex
- // to work on the string from both the left and right, so that what
- // is remains is assumed to be the filename.
-
- // Match LineEntry using regex.
- static llvm::Regex g_lineentry_nocol_regex(llvm::StringRef(
- "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$"));
- static llvm::Regex g_lineentry_col_regex(llvm::StringRef(
- "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$"));
- // ^1=start ^2=end ^3=f ^4=line
- // ^5=:col(opt)
-
- llvm::SmallVector<llvm::StringRef, 6> match;
+ const auto &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
+ if (rSessionInfo.GetTarget() == rSessionInfo.GetDebugger().GetDummyTarget()) {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
+ m_cmdData.strMiCmd.c_str()));
+ return MIstatus::failure;
+ }
- // First try matching the LineEntry with the column,
- // then try without the column.
- const bool ok = g_lineentry_col_regex.match(input, &match) ||
- g_lineentry_nocol_regex.match(input, &match);
- if (ok) {
- addr = match[1];
- file = match[3];
- line = match[4];
+ const lldb::SBFileSpec source_file_spec(pArgFile->GetValue().c_str(), true);
+ const char *source_file_name = source_file_spec.GetFilename();
+ const char *source_file_directory = source_file_spec.GetDirectory();
+ const bool has_path = source_file_directory;
+
+ lldb::SBSymbolContextList sc_cu_list =
+ CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindCompileUnits(
+ source_file_spec);
+
+ bool found_something = false;
+ for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) {
+ const lldb::SBCompileUnit cu =
+ sc_cu_list.GetContextAtIndex(i).GetCompileUnit();
+ for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) {
+ const lldb::SBLineEntry line = cu.GetLineEntryAtIndex(j);
+ const lldb::SBFileSpec line_spec = line.GetFileSpec();
+ if (line_spec.GetFilename() == source_file_name) {
+ if (has_path && (line_spec.GetDirectory() != source_file_directory))
+ continue;
+ // We don't need a line with start address equals to end one,
+ // so just skip it.
+ const lldb::SBAddress line_start_address = line.GetStartAddress();
+ const lldb::SBAddress line_end_address = line.GetEndAddress();
+ if (line_start_address == line_end_address)
+ continue;
+ // We have a matching line.
+ found_something = true;
+ m_resultList.Add(CreateMITuplePCLine(
+ line_start_address.GetFileAddress(),
+ line.GetLine()));
+ }
+ }
+ }
+ if (!found_something) {
+ SetError(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
+ return MIstatus::failure;
}
- return ok;
+ return MIstatus::success;
}
//++
@@ -185,71 +161,11 @@ static bool ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr,
// Throws: None.
//--
bool CMICmdCmdSymbolListLines::Acknowledge() {
- if (m_lldbResult.GetErrorSize() > 0) {
- const char *pLldbErr = m_lldbResult.GetError();
- const CMIUtilString strMsg(CMIUtilString(pLldbErr).StripCRAll());
- const CMICmnMIValueConst miValueConst(strMsg);
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
- } else {
- CMIUtilString::VecString_t vecLines;
- const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
- const MIuint nLines(strLldbMsg.SplitLines(vecLines));
-
- // Parse the file from the header.
- const CMIUtilString &rWantFile(vecLines[0]);
- CMIUtilString strWantFile;
- if (!ParseLLDBLineAddressHeader(rWantFile.c_str(), strWantFile)) {
- // Unexpected error - parsing failed.
- // MI print "%s^error,msg=\"Command '-symbol-list-lines'. Error: Line
- // address header is absent or has an unknown format.\""
- const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
- MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
- "Line address header is absent or has an unknown format."));
- const CMICmnMIValueResult miValueResult("msg", miValueConst);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
- miValueResult);
- m_miResultRecord = miRecordResult;
-
- return MIstatus::success;
- }
-
- // Parse the line address entries.
- CMICmnMIValueList miValueList(true);
- for (MIuint i = 1; i < nLines; ++i) {
- // String looks like:
- // 0x0000000100000e70: /path/to/file:3[:4]
- const CMIUtilString &rLine(vecLines[i]);
- CMIUtilString strAddr;
- CMIUtilString strFile;
- CMIUtilString strLine;
-
- if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine))
- continue;
-
- const CMICmnMIValueConst miValueConst(strAddr);
- const CMICmnMIValueResult miValueResult("pc", miValueConst);
- CMICmnMIValueTuple miValueTuple(miValueResult);
-
- const CMICmnMIValueConst miValueConst2(strLine);
- const CMICmnMIValueResult miValueResult2("line", miValueConst2);
- miValueTuple.Add(miValueResult2);
-
- miValueList.Add(miValueTuple);
- }
-
- // MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]"
- const CMICmnMIValueResult miValueResult("lines", miValueList);
- const CMICmnMIResultRecord miRecordResult(
- m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
- miValueResult);
- m_miResultRecord = miRecordResult;
- }
-
+ // MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]"
+ const CMICmnMIValueResult miValueResult("lines", m_resultList);
+ m_miResultRecord = CMICmnMIResultRecord(
+ m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
+ miValueResult);
return MIstatus::success;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h
index 56685df07d94..bd545345cf1b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h
@@ -24,10 +24,10 @@
#pragma once
// Third party headers:
-#include "lldb/API/SBCommandReturnObject.h"
// In-house headers:
#include "MICmdBase.h"
+#include "MICmnMIValueList.h"
//++
//============================================================================
@@ -55,6 +55,6 @@ public:
// Attributes:
private:
- lldb::SBCommandReturnObject m_lldbResult;
+ CMICmnMIValueList m_resultList;
const CMIUtilString m_constStrArgNameFile;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
index e5bd4c4d2bc7..a82bd682de81 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
@@ -115,7 +115,7 @@ bool CMICmdCmdTargetSelect::Execute() {
const CMIUtilString strUrl =
CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str());
- // Ask LLDB to collect to the target port
+ // Ask LLDB to connect to the target port
const char *pPlugin("gdb-remote");
lldb::SBError error;
lldb::SBProcess process = rSessionInfo.GetTarget().ConnectRemote(
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
index 6e76c23036f1..9a173d1007e2 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -871,7 +871,10 @@ lldb::SBListener &CMICmnLLDBDebugSessionInfo::GetListener() const {
// Throws: None.
//--
lldb::SBTarget CMICmnLLDBDebugSessionInfo::GetTarget() const {
- return GetDebugger().GetSelectedTarget();
+ auto target = GetDebugger().GetSelectedTarget();
+ if (target.IsValid())
+ return target;
+ return GetDebugger().GetDummyTarget();
}
//++
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
index f4773053c28d..55764511a6a9 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
@@ -14,6 +14,7 @@
#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
#include "MIUtilSingletonBase.h"
+#include "lldb/API/SBEvent.h"
// Declarations:
class CMICmnLLDBDebugSessionInfo;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp
index f96f01b65f0e..e32a816fc9f1 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp
@@ -110,6 +110,8 @@ const CMICmnResources::SRsrcTextData
{IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file "
"path to the executable i.e. '\"C:\\My "
"Dev\\foo.exe\"'."},
+ {IDE_MI_APP_ARG_SYNCHRONOUS, "--synchronous\n\tBlock until each command "
+ "has finished executing.\n\tUsed for testing only."},
{IDS_STDIN_ERR_INVALID_PROMPT,
"Stdin. Invalid prompt description '%s'"},
{IDS_STDIN_ERR_THREAD_CREATION_FAILED,
@@ -449,7 +451,7 @@ const CMICmnResources::SRsrcTextData
"'print' error. The option '%s' not found"},
{IDS_CMD_ERR_EXPR_INVALID, "Failed to evaluate expression: %s"},
{IDS_CMD_ERR_ATTACH_FAILED,
- "Command '%s'. Attach to processs failed: %s"},
+ "Command '%s'. Attach to process failed: %s"},
{IDS_CMD_ERR_ATTACH_BAD_ARGS,
"Command '%s'. Must specify either a PID or a Name"}};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h
index e9ebe7928101..8912a2b8463e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h
@@ -77,6 +77,7 @@ enum {
IDE_MI_APP_ARG_APP_LOG_DIR,
IDE_MI_APP_ARG_EXAMPLE,
IDE_MI_APP_ARG_EXECUTABLE,
+ IDE_MI_APP_ARG_SYNCHRONOUS,
IDS_STDIN_ERR_INVALID_PROMPT,
IDS_STDIN_ERR_THREAD_CREATION_FAILED,
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
index 7bd6b7b2e166..23039110b428 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
@@ -382,6 +382,7 @@ lldb::SBError CMIDriver::DoParseArgs(const int argc, const char *argv[],
// that are only handled by *this driver:
// --executable <file>
// --source <file> or -s <file>
+// --synchronous
// The application's options --interpreter and --executable in code act
// very similar.
// The --executable is necessary to differentiate whether the MI Driver
@@ -397,6 +398,7 @@ lldb::SBError CMIDriver::DoParseArgs(const int argc, const char *argv[],
// argument for a debug session. Using --interpreter on the command
// line does not
// issue additional commands to initialise a debug session.
+// Option --synchronous disables an asynchronous mode in the lldb-mi driver.
// Type: Overridden.
// Args: argc - (R) An integer that contains the count of arguments
// that follow in
@@ -469,6 +471,8 @@ lldb::SBError CMIDriver::ParseArgs(const int argc, const char *argv[],
// command line
{ // See fn description.
bHaveExecutableLongOption = true;
+ } else if (strArg.compare("--synchronous") == 0) {
+ CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().SetAsync(false);
}
}
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp
index eda67782ad67..1b3521e8f03f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp
@@ -26,13 +26,11 @@
// MICmdBase.h / .cpp
// MICmdCmd.h / .cpp
-#if defined(_MSC_VER)
-#define _INC_SIGNAL // Stop window's signal.h being included -
- // CODETAG_IOR_SIGNALS
-#endif // _MSC_VER
-
// Third party headers:
#include "lldb/API/SBHostOS.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
#include <atomic>
#include <csignal>
#include <stdio.h>
@@ -174,6 +172,10 @@ int main(int argc, char const *argv[]) {
#endif // _WIN32
#endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
+ llvm::StringRef ToolName = argv[0];
+ llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
+ llvm::PrettyStackTraceProgram X(argc, argv);
+
// *** Order is important here ***
bool bOk = DriverSystemInit();
if (!bOk) {
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
index 1ce7febc1b39..6b39832d736e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
@@ -640,6 +640,7 @@ CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions() const {
MIRSRC(IDE_MI_APP_ARG_VERSION), MIRSRC(IDE_MI_APP_ARG_VERSION_LONG),
MIRSRC(IDE_MI_APP_ARG_INTERPRETER), MIRSRC(IDE_MI_APP_ARG_SOURCE),
MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE),
+ MIRSRC(IDE_MI_APP_ARG_SYNCHRONOUS),
CMIUtilString::Format(
MIRSRC(IDE_MI_APP_ARG_APP_LOG),
CMICmnLogMediumFile::Instance().GetFileName().c_str()),
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIReadMe.txt b/contrib/llvm/tools/lldb/tools/lldb-mi/MIReadMe.txt
index bc3d4a8d5e5c..51316ed879c5 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIReadMe.txt
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIReadMe.txt
@@ -9,7 +9,7 @@ For help information on using the MI driver type at the command line:
lldb-mi --interpreter --help
-A blog about the MI Driver is available on CodePlay's website. ALthough it may not be
+A blog about the MI Driver is available on CodePlay's website. Although it may not be
completely accurate after the recent changes in lldb-mi.
http://www.codeplay.com/portal/lldb-mi-driver---part-1-introduction
@@ -19,7 +19,7 @@ used to aid the debugging of the MI Driver. It also gives warnings about
command's which do not support certain argument or options.
Note any command or text sent to the MI Driver in MI mode that is not a command
-registered in the MI Driver's Command Factory will be rejected and an error messsage
+registered in the MI Driver's Command Factory will be rejected and an error message
will be generated.
All the files prefix with MI are specifically for the MI driver code only.
@@ -29,8 +29,8 @@ File MIDriverMain.cpp contains the executables main() function.
Current limitations:
1. Not all commands and their options have been implemented. Please see
the source code for details.
-2. LLDB-MI may have additinal arguments not used in GDB MI. Please see
-MIExtesnsions.txt
+2. LLDB-MI may have additional arguments not used in GDB MI. Please see
+MIExtensions.txt
=========================================================================
The MI Driver build configuration:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h
index 82bed558a7d9..831c60aecfef 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h
@@ -9,12 +9,12 @@
#pragma once
-namespace MI {
-
// In house headers:
#include "MICmnResources.h"
#include "MIUtilString.h"
+namespace MI {
+
//++
//============================================================================
// Details: Short cut helper function to simplify repeated initialisation of
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/module.modulemap b/contrib/llvm/tools/lldb/tools/lldb-mi/module.modulemap
new file mode 100644
index 000000000000..01f6a2b79508
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/module.modulemap
@@ -0,0 +1,79 @@
+module lldb_mi {
+ module MICmdArgContext { header "MICmdArgContext.h" export * }
+ module MICmdArgSet { header "MICmdArgSet.h" export * }
+ module MICmdArgValBase { header "MICmdArgValBase.h" export * }
+ module MICmdArgValConsume { header "MICmdArgValConsume.h" export * }
+ module MICmdArgValFile { header "MICmdArgValFile.h" export * }
+ module MICmdArgValListBase { header "MICmdArgValListBase.h" export * }
+ module MICmdArgValListOfN { header "MICmdArgValListOfN.h" export * }
+ module MICmdArgValNumber { header "MICmdArgValNumber.h" export * }
+ module MICmdArgValOptionLong { header "MICmdArgValOptionLong.h" export * }
+ module MICmdArgValOptionShort { header "MICmdArgValOptionShort.h" export * }
+ module MICmdArgValPrintValues { header "MICmdArgValPrintValues.h" export * }
+ module MICmdArgValString { header "MICmdArgValString.h" export * }
+ module MICmdArgValThreadGrp { header "MICmdArgValThreadGrp.h" export * }
+ module MICmdBase { header "MICmdBase.h" export * }
+ module MICmdCmdBreak { header "MICmdCmdBreak.h" export * }
+ module MICmdCmdData { header "MICmdCmdData.h" export * }
+ module MICmdCmdEnviro { header "MICmdCmdEnviro.h" export * }
+ module MICmdCmdExec { header "MICmdCmdExec.h" export * }
+ module MICmdCmdFile { header "MICmdCmdFile.h" export * }
+ module MICmdCmdGdbInfo { header "MICmdCmdGdbInfo.h" export * }
+ module MICmdCmdGdbSet { header "MICmdCmdGdbSet.h" export * }
+ module MICmdCmdGdbShow { header "MICmdCmdGdbShow.h" export * }
+ module MICmdCmdGdbThread { header "MICmdCmdGdbThread.h" export * }
+ module MICmdCmd { header "MICmdCmd.h" export * }
+ module MICmdCmdMiscellanous { header "MICmdCmdMiscellanous.h" export * }
+ module MICmdCmdStack { header "MICmdCmdStack.h" export * }
+ module MICmdCmdSupportInfo { header "MICmdCmdSupportInfo.h" export * }
+ module MICmdCmdSupportList { header "MICmdCmdSupportList.h" export * }
+ module MICmdCmdSymbol { header "MICmdCmdSymbol.h" export * }
+ module MICmdCmdTarget { header "MICmdCmdTarget.h" export * }
+ module MICmdCmdThread { header "MICmdCmdThread.h" export * }
+ module MICmdCmdTrace { header "MICmdCmdTrace.h" export * }
+ module MICmdCmdVar { header "MICmdCmdVar.h" export * }
+ module MICmdCommands { header "MICmdCommands.h" export * }
+ module MICmdData { header "MICmdData.h" export * }
+ module MICmdFactory { header "MICmdFactory.h" export * }
+ module MICmdInterpreter { header "MICmdInterpreter.h" export * }
+ module MICmdInvoker { header "MICmdInvoker.h" export * }
+ module MICmdMgr { header "MICmdMgr.h" export * }
+ module MICmdMgrSetCmdDeleteCallback { header "MICmdMgrSetCmdDeleteCallback.h" export * }
+ module MICmnBase { header "MICmnBase.h" export * }
+ module MICmnConfig { header "MICmnConfig.h" export * }
+ module MICmnLLDBBroadcaster { header "MICmnLLDBBroadcaster.h" export * }
+ module MICmnLLDBDebugger { header "MICmnLLDBDebugger.h" export * }
+ module MICmnLLDBDebuggerHandleEvents { header "MICmnLLDBDebuggerHandleEvents.h" export * }
+ module MICmnLLDBDebugSessionInfo { header "MICmnLLDBDebugSessionInfo.h" export * }
+ module MICmnLLDBDebugSessionInfoVarObj { header "MICmnLLDBDebugSessionInfoVarObj.h" export * }
+ module MICmnLLDBProxySBValue { header "MICmnLLDBProxySBValue.h" export * }
+ module MICmnLLDBUtilSBValue { header "MICmnLLDBUtilSBValue.h" export * }
+ module MICmnLog { header "MICmnLog.h" export * }
+ module MICmnLogMediumFile { header "MICmnLogMediumFile.h" export * }
+ module MICmnMIOutOfBandRecord { header "MICmnMIOutOfBandRecord.h" export * }
+ module MICmnMIResultRecord { header "MICmnMIResultRecord.h" export * }
+ module MICmnMIValueConst { header "MICmnMIValueConst.h" export * }
+ module MICmnMIValue { header "MICmnMIValue.h" export * }
+ module MICmnMIValueList { header "MICmnMIValueList.h" export * }
+ module MICmnMIValueResult { header "MICmnMIValueResult.h" export * }
+ module MICmnMIValueTuple { header "MICmnMIValueTuple.h" export * }
+ module MICmnResources { header "MICmnResources.h" export * }
+ module MICmnStreamStderr { header "MICmnStreamStderr.h" export * }
+ module MICmnStreamStdin { header "MICmnStreamStdin.h" export * }
+ module MICmnStreamStdout { header "MICmnStreamStdout.h" export * }
+ module MICmnThreadMgrStd { header "MICmnThreadMgrStd.h" export * }
+ module MIDataTypes { header "MIDataTypes.h" export * }
+ module MIDriverBase { header "MIDriverBase.h" export * }
+ module MIDriver { header "MIDriver.h" export * }
+ module MIDriverMgr { header "MIDriverMgr.h" export * }
+ module MIUtilDateTimeStd { header "MIUtilDateTimeStd.h" export * }
+ module MIUtilDebug { header "MIUtilDebug.h" export * }
+ module MIUtilFileStd { header "MIUtilFileStd.h" export * }
+ module MIUtilMapIdToVariant { header "MIUtilMapIdToVariant.h" export * }
+ module MIUtilSingletonBase { header "MIUtilSingletonBase.h" export * }
+ module MIUtilSingletonHelper { header "MIUtilSingletonHelper.h" export * }
+ module MIUtilString { header "MIUtilString.h" export * }
+ module MIUtilThreadBaseStd { header "MIUtilThreadBaseStd.h" export * }
+ module MIUtilVariant { header "MIUtilVariant.h" export * }
+ module Platform { header "Platform.h" export * }
+}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp
index e784a3a82684..7d41b3b4c745 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp
@@ -10,7 +10,7 @@
#include "LLDBServerUtilities.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.cpp
new file mode 100644
index 000000000000..aeaf382a1dd8
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.cpp
@@ -0,0 +1,33 @@
+//===-- SystemInitializerLLGS.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemInitializerLLGS.h"
+
+#if defined(__APPLE__)
+#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
+using HostObjectFile = ObjectFileMachO;
+#elif defined(_WIN32)
+#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
+using HostObjectFile = ObjectFilePECOFF;
+#else
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+using HostObjectFile = ObjectFileELF;
+#endif
+
+using namespace lldb_private;
+
+void SystemInitializerLLGS::Initialize() {
+ SystemInitializerCommon::Initialize();
+ HostObjectFile::Initialize();
+}
+
+void SystemInitializerLLGS::Terminate() {
+ HostObjectFile::Terminate();
+ SystemInitializerCommon::Terminate();
+}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.h b/contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.h
new file mode 100644
index 000000000000..e6460a2cdd39
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/SystemInitializerLLGS.h
@@ -0,0 +1,21 @@
+//===-- SystemInitializerLLGS.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SYSTEMINITIALIZERLLGS_H
+#define LLDB_SYSTEMINITIALIZERLLGS_H
+
+#include "lldb/Initialization/SystemInitializerCommon.h"
+
+class SystemInitializerLLGS : public lldb_private::SystemInitializerCommon {
+public:
+ void Initialize() override;
+ void Terminate() override;
+};
+
+#endif // LLDB_SYSTEMINITIALIZERLLGS_H
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp
index 810cb92e4ffc..c91a8a89e46a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -188,10 +188,7 @@ void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc,
exit(1);
}
info.SetWorkingDirectory(FileSpec(cwd, true));
-
- StringList env;
- Host::GetEnvironment(env);
- info.GetEnvironmentEntries() = Args(env);
+ info.GetEnvironment() = Host::GetEnvironment();
gdb_server.SetLaunchInfo(info);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp
index ec5b781dac48..cfaf5550d096 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp
@@ -193,7 +193,7 @@ int main_platform(int argc, char *argv[]) {
case 'f': // Socket file
if (optarg && optarg[0])
- socket_file.SetFile(optarg, false);
+ socket_file.SetFile(optarg, false, FileSpec::Style::native);
break;
case 'p': {
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.cpp
index 06ef0498749a..f05c96cfaa95 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.cpp
@@ -7,12 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Initialization/SystemInitializerCommon.h"
+#include "SystemInitializerLLGS.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
#include <stdio.h>
#include <stdlib.h>
@@ -35,8 +38,8 @@ int main_gdbserver(int argc, char *argv[]);
int main_platform(int argc, char *argv[]);
static void initialize() {
- g_debugger_lifetime->Initialize(
- llvm::make_unique<lldb_private::SystemInitializerCommon>(), nullptr);
+ g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerLLGS>(),
+ nullptr);
}
static void terminate() { g_debugger_lifetime->Terminate(); }
@@ -45,6 +48,10 @@ static void terminate() { g_debugger_lifetime->Terminate(); }
// main
//----------------------------------------------------------------------
int main(int argc, char *argv[]) {
+ llvm::StringRef ToolName = argv[0];
+ llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
+ llvm::PrettyStackTraceProgram X(argc, argv);
+
int option_error = 0;
const char *progname = argv[0];
if (argc < 2) {
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.cpp b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
deleted file mode 100644
index f1a752e0790d..000000000000
--- a/contrib/llvm/tools/lli/OrcLazyJIT.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//===- OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "OrcLazyJIT.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/Support/CodeGen.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <system_error>
-
-using namespace llvm;
-
-namespace {
-
-enum class DumpKind {
- NoDump,
- DumpFuncsToStdOut,
- DumpModsToStdOut,
- DumpModsToDisk
-};
-
-} // end anonymous namespace
-
-static cl::opt<DumpKind> OrcDumpKind(
- "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),
- cl::init(DumpKind::NoDump),
- cl::values(clEnumValN(DumpKind::NoDump, "no-dump", "Don't dump anything."),
- clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
- "Dump function names to stdout."),
- clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
- "Dump modules to stdout."),
- clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
- "Dump modules to the current "
- "working directory. (WARNING: "
- "will overwrite existing files).")),
- cl::Hidden);
-
-static cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
- cl::desc("Try to inline stubs"),
- cl::init(true), cl::Hidden);
-
-OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
- switch (OrcDumpKind) {
- case DumpKind::NoDump:
- return [](std::shared_ptr<Module> M) { return M; };
-
- case DumpKind::DumpFuncsToStdOut:
- return [](std::shared_ptr<Module> M) {
- printf("[ ");
-
- for (const auto &F : *M) {
- if (F.isDeclaration())
- continue;
-
- if (F.hasName()) {
- std::string Name(F.getName());
- printf("%s ", Name.c_str());
- } else
- printf("<anon> ");
- }
-
- printf("]\n");
- return M;
- };
-
- case DumpKind::DumpModsToStdOut:
- return [](std::shared_ptr<Module> M) {
- outs() << "----- Module Start -----\n" << *M
- << "----- Module End -----\n";
-
- return M;
- };
-
- case DumpKind::DumpModsToDisk:
- return [](std::shared_ptr<Module> M) {
- std::error_code EC;
- raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
- sys::fs::F_Text);
- if (EC) {
- errs() << "Couldn't open " << M->getModuleIdentifier()
- << " for dumping.\nError:" << EC.message() << "\n";
- exit(1);
- }
- Out << *M;
- return M;
- };
- }
- llvm_unreachable("Unknown DumpKind");
-}
-
-// Defined in lli.cpp.
-CodeGenOpt::Level getOptLevel();
-
-template <typename PtrTy>
-static PtrTy fromTargetAddress(JITTargetAddress Addr) {
- return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
-}
-
-int llvm::runOrcLazyJIT(std::vector<std::unique_ptr<Module>> Ms,
- const std::vector<std::string> &Args) {
- // Add the program's symbols into the JIT's search space.
- if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
- errs() << "Error loading program symbols.\n";
- return 1;
- }
-
- // Grab a target machine and try to build a factory function for the
- // target-specific Orc callback manager.
- EngineBuilder EB;
- EB.setOptLevel(getOptLevel());
- auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
- Triple T(TM->getTargetTriple());
- auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
-
- // If we couldn't build the factory function then there must not be a callback
- // manager for this target. Bail out.
- if (!CompileCallbackMgr) {
- errs() << "No callback manager available for target '"
- << TM->getTargetTriple().str() << "'.\n";
- return 1;
- }
-
- auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
-
- // If we couldn't build a stubs-manager-builder for this target then bail out.
- if (!IndirectStubsMgrBuilder) {
- errs() << "No indirect stubs manager available for target '"
- << TM->getTargetTriple().str() << "'.\n";
- return 1;
- }
-
- // Everything looks good. Build the JIT.
- OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
- std::move(IndirectStubsMgrBuilder),
- OrcInlineStubs);
-
- // Add the module, look up main and run it.
- for (auto &M : Ms)
- cantFail(J.addModule(std::shared_ptr<Module>(std::move(M))));
-
- if (auto MainSym = J.findSymbol("main")) {
- typedef int (*MainFnPtr)(int, const char*[]);
- std::vector<const char *> ArgV;
- for (auto &Arg : Args)
- ArgV.push_back(Arg.c_str());
- auto Main = fromTargetAddress<MainFnPtr>(cantFail(MainSym.getAddress()));
- return Main(ArgV.size(), (const char**)ArgV.data());
- } else if (auto Err = MainSym.takeError())
- logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
- else
- errs() << "Could not find main function.\n";
-
- return 1;
-}
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.h b/contrib/llvm/tools/lli/OrcLazyJIT.h
deleted file mode 100644
index a5cc804bb045..000000000000
--- a/contrib/llvm/tools/lli/OrcLazyJIT.h
+++ /dev/null
@@ -1,201 +0,0 @@
-//===- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and
-// lazily compile modules.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H
-#define LLVM_TOOLS_LLI_ORCLAZYJIT_H
-
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
-#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
-#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
-#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
-#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/GlobalValue.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include <algorithm>
-#include <functional>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-class OrcLazyJIT {
-public:
-
- using CompileCallbackMgr = orc::JITCompileCallbackManager;
- using ObjLayerT = orc::RTDyldObjectLinkingLayer;
- using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
- using TransformFtor =
- std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
- using IRDumpLayerT = orc::IRTransformLayer<CompileLayerT, TransformFtor>;
- using CODLayerT = orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr>;
- using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
- using ModuleHandleT = CODLayerT::ModuleHandleT;
-
- OrcLazyJIT(std::unique_ptr<TargetMachine> TM,
- std::unique_ptr<CompileCallbackMgr> CCMgr,
- IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
- bool InlineStubs)
- : TM(std::move(TM)), DL(this->TM->createDataLayout()),
- CCMgr(std::move(CCMgr)),
- ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
- CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
- IRDumpLayer(CompileLayer, createDebugDumper()),
- CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr,
- std::move(IndirectStubsMgrBuilder), InlineStubs),
- CXXRuntimeOverrides(
- [this](const std::string &S) { return mangle(S); }) {}
-
- ~OrcLazyJIT() {
- // Run any destructors registered with __cxa_atexit.
- CXXRuntimeOverrides.runDestructors();
- // Run any IR destructors.
- for (auto &DtorRunner : IRStaticDestructorRunners)
- if (auto Err = DtorRunner.runViaLayer(CODLayer)) {
- // FIXME: OrcLazyJIT should probably take a "shutdownError" callback to
- // report these errors on.
- report_fatal_error(std::move(Err));
- }
- }
-
- Error addModule(std::shared_ptr<Module> M) {
- if (M->getDataLayout().isDefault())
- M->setDataLayout(DL);
-
- // Rename, bump linkage and record static constructors and destructors.
- // We have to do this before we hand over ownership of the module to the
- // JIT.
- std::vector<std::string> CtorNames, DtorNames;
- {
- unsigned CtorId = 0, DtorId = 0;
- for (auto Ctor : orc::getConstructors(*M)) {
- std::string NewCtorName = ("$static_ctor." + Twine(CtorId++)).str();
- Ctor.Func->setName(NewCtorName);
- Ctor.Func->setLinkage(GlobalValue::ExternalLinkage);
- Ctor.Func->setVisibility(GlobalValue::HiddenVisibility);
- CtorNames.push_back(mangle(NewCtorName));
- }
- for (auto Dtor : orc::getDestructors(*M)) {
- std::string NewDtorName = ("$static_dtor." + Twine(DtorId++)).str();
- Dtor.Func->setLinkage(GlobalValue::ExternalLinkage);
- Dtor.Func->setVisibility(GlobalValue::HiddenVisibility);
- DtorNames.push_back(mangle(Dtor.Func->getName()));
- Dtor.Func->setName(NewDtorName);
- }
- }
-
- // Symbol resolution order:
- // 1) Search the JIT symbols.
- // 2) Check for C++ runtime overrides.
- // 3) Search the host process (LLI)'s symbol table.
- if (!ModulesHandle) {
- auto Resolver =
- orc::createLambdaResolver(
- [this](const std::string &Name) -> JITSymbol {
- if (auto Sym = CODLayer.findSymbol(Name, true))
- return Sym;
- return CXXRuntimeOverrides.searchOverrides(Name);
- },
- [](const std::string &Name) {
- if (auto Addr =
- RTDyldMemoryManager::getSymbolAddressInProcess(Name))
- return JITSymbol(Addr, JITSymbolFlags::Exported);
- return JITSymbol(nullptr);
- }
- );
-
- // Add the module to the JIT.
- if (auto ModulesHandleOrErr =
- CODLayer.addModule(std::move(M), std::move(Resolver)))
- ModulesHandle = std::move(*ModulesHandleOrErr);
- else
- return ModulesHandleOrErr.takeError();
-
- } else if (auto Err = CODLayer.addExtraModule(*ModulesHandle, std::move(M)))
- return Err;
-
- // Run the static constructors, and save the static destructor runner for
- // execution when the JIT is torn down.
- orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames),
- *ModulesHandle);
- if (auto Err = CtorRunner.runViaLayer(CODLayer))
- return Err;
-
- IRStaticDestructorRunners.emplace_back(std::move(DtorNames),
- *ModulesHandle);
-
- return Error::success();
- }
-
- JITSymbol findSymbol(const std::string &Name) {
- return CODLayer.findSymbol(mangle(Name), true);
- }
-
- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) {
- return CODLayer.findSymbolIn(H, mangle(Name), true);
- }
-
-private:
- std::string mangle(const std::string &Name) {
- std::string MangledName;
- {
- raw_string_ostream MangledNameStream(MangledName);
- Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
- }
- return MangledName;
- }
-
- static std::set<Function*> extractSingleFunction(Function &F) {
- std::set<Function*> Partition;
- Partition.insert(&F);
- return Partition;
- }
-
- static TransformFtor createDebugDumper();
-
- std::unique_ptr<TargetMachine> TM;
- DataLayout DL;
- SectionMemoryManager CCMgrMemMgr;
-
- std::unique_ptr<CompileCallbackMgr> CCMgr;
- ObjLayerT ObjectLayer;
- CompileLayerT CompileLayer;
- IRDumpLayerT IRDumpLayer;
- CODLayerT CODLayer;
-
- orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
- std::vector<orc::CtorDtorRunner<CODLayerT>> IRStaticDestructorRunners;
- llvm::Optional<CODLayerT::ModuleHandleT> ModulesHandle;
-};
-
-int runOrcLazyJIT(std::vector<std::unique_ptr<Module>> Ms,
- const std::vector<std::string> &Args);
-
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_LLI_ORCLAZYJIT_H
diff --git a/contrib/llvm/tools/lli/RemoteJITUtils.h b/contrib/llvm/tools/lli/RemoteJITUtils.h
index 4e948413865c..944881070c70 100644
--- a/contrib/llvm/tools/lli/RemoteJITUtils.h
+++ b/contrib/llvm/tools/lli/RemoteJITUtils.h
@@ -84,7 +84,7 @@ public:
this->MemMgr = std::move(MemMgr);
}
- void setResolver(std::shared_ptr<JITSymbolResolver> Resolver) {
+ void setResolver(std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
this->Resolver = std::move(Resolver);
}
@@ -145,7 +145,7 @@ public:
private:
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr;
- std::shared_ptr<JITSymbolResolver> Resolver;
+ std::shared_ptr<LegacyJITSymbolResolver> Resolver;
};
}
diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp
index a33c51d77877..1940dbd848cc 100644
--- a/contrib/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm/tools/lli/lli.cpp
@@ -13,18 +13,20 @@
//
//===----------------------------------------------------------------------===//
-#include "OrcLazyJIT.h"
#include "RemoteJITUtils.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
#include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
@@ -33,6 +35,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
@@ -40,18 +43,18 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PluginLoader.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h"
#include <cerrno>
@@ -176,6 +179,28 @@ namespace {
cl::desc("Generate software floating point library calls"),
cl::init(false));
+ enum class DumpKind {
+ NoDump,
+ DumpFuncsToStdOut,
+ DumpModsToStdOut,
+ DumpModsToDisk
+ };
+
+ cl::opt<DumpKind> OrcDumpKind(
+ "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),
+ cl::init(DumpKind::NoDump),
+ cl::values(clEnumValN(DumpKind::NoDump, "no-dump",
+ "Don't dump anything."),
+ clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
+ "Dump function names to stdout."),
+ clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
+ "Dump modules to stdout."),
+ clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
+ "Dump modules to the current "
+ "working directory. (WARNING: "
+ "will overwrite existing files).")),
+ cl::Hidden);
+
ExitOnError ExitOnErr;
}
@@ -295,7 +320,7 @@ static void addCygMingExtraModule(ExecutionEngine &EE, LLVMContext &Context,
CodeGenOpt::Level getOptLevel() {
switch (OptLevel) {
default:
- errs() << "lli: Invalid optimization level.\n";
+ WithColor::error(errs(), "lli") << "invalid optimization level.\n";
exit(1);
case '0': return CodeGenOpt::None;
case '1': return CodeGenOpt::Less;
@@ -312,14 +337,14 @@ static void reportError(SMDiagnostic Err, const char *ProgName) {
exit(1);
}
+int runOrcLazyJIT(LLVMContext &Ctx, std::vector<std::unique_ptr<Module>> Ms,
+ const std::vector<std::string> &Args);
+
//===----------------------------------------------------------------------===//
// main Driver function
//
int main(int argc, char **argv, char * const *envp) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
-
- atexit(llvm_shutdown); // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
if (argc > 1)
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
@@ -358,7 +383,7 @@ int main(int argc, char **argv, char * const *envp) {
Args.push_back(InputFile);
for (auto &Arg : InputArgv)
Args.push_back(Arg);
- return runOrcLazyJIT(std::move(Ms), Args);
+ return runOrcLazyJIT(Context, std::move(Ms), Args);
}
if (EnableCacheManager) {
@@ -378,8 +403,8 @@ int main(int argc, char **argv, char * const *envp) {
std::string ErrorMsg;
EngineBuilder builder(std::move(Owner));
builder.setMArch(MArch);
- builder.setMCPU(MCPU);
- builder.setMAttrs(MAttrs);
+ builder.setMCPU(getCPUStr());
+ builder.setMAttrs(getFeatureList());
if (RelocModel.getNumOccurrences())
builder.setRelocationModel(RelocModel);
if (CMModel.getNumOccurrences())
@@ -407,8 +432,8 @@ int main(int argc, char **argv, char * const *envp) {
builder.setMCJITMemoryManager(
std::unique_ptr<RTDyldMemoryManager>(RTDyldMM));
} else if (RemoteMCJIT) {
- errs() << "error: Remote process execution does not work with the "
- "interpreter.\n";
+ WithColor::error(errs(), argv[0])
+ << "remote process execution does not work with the interpreter.\n";
exit(1);
}
@@ -423,9 +448,10 @@ int main(int argc, char **argv, char * const *envp) {
std::unique_ptr<ExecutionEngine> EE(builder.create());
if (!EE) {
if (!ErrorMsg.empty())
- errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
+ WithColor::error(errs(), argv[0])
+ << "error creating EE: " << ErrorMsg << "\n";
else
- errs() << argv[0] << ": unknown error creating EE!\n";
+ WithColor::error(errs(), argv[0]) << "unknown error creating EE!\n";
exit(1);
}
@@ -496,9 +522,13 @@ int main(int argc, char **argv, char * const *envp) {
JITEventListener::createOProfileJITEventListener());
EE->RegisterJITEventListener(
JITEventListener::createIntelJITEventListener());
+ if (!RemoteMCJIT)
+ EE->RegisterJITEventListener(
+ JITEventListener::createPerfJITEventListener());
if (!NoLazyCompilation && RemoteMCJIT) {
- errs() << "warning: remote mcjit does not support lazy compilation\n";
+ WithColor::warning(errs(), argv[0])
+ << "remote mcjit does not support lazy compilation\n";
NoLazyCompilation = true;
}
EE->DisableLazyCompilation(NoLazyCompilation);
@@ -524,7 +554,8 @@ int main(int argc, char **argv, char * const *envp) {
//
Function *EntryFn = Mod->getFunction(EntryFunc);
if (!EntryFn) {
- errs() << '\'' << EntryFunc << "\' function not found in module.\n";
+ WithColor::error(errs(), argv[0])
+ << '\'' << EntryFunc << "\' function not found in module.\n";
return -1;
}
@@ -537,16 +568,19 @@ int main(int argc, char **argv, char * const *envp) {
// remote JIT on Unix platforms.
if (RemoteMCJIT) {
#ifndef LLVM_ON_UNIX
- errs() << "Warning: host does not support external remote targets.\n"
- << " Defaulting to local execution\n";
+ WithColor::warning(errs(), argv[0])
+ << "host does not support external remote targets.\n";
+ WithColor::note() << "defaulting to local execution\n";
return -1;
#else
if (ChildExecPath.empty()) {
- errs() << "-remote-mcjit requires -mcjit-remote-process.\n";
+ WithColor::error(errs(), argv[0])
+ << "-remote-mcjit requires -mcjit-remote-process.\n";
exit(1);
} else if (!sys::fs::can_execute(ChildExecPath)) {
- errs() << "Unable to find usable child executable: '" << ChildExecPath
- << "'\n";
+ WithColor::error(errs(), argv[0])
+ << "unable to find usable child executable: '" << ChildExecPath
+ << "'\n";
return -1;
}
#endif
@@ -586,10 +620,11 @@ int main(int argc, char **argv, char * const *envp) {
ResultGV.IntVal = APInt(32, Result);
Args.push_back(ResultGV);
EE->runFunction(ExitF, Args);
- errs() << "ERROR: exit(" << Result << ") returned!\n";
+ WithColor::error(errs(), argv[0]) << "exit(" << Result << ") returned!\n";
abort();
} else {
- errs() << "ERROR: exit defined with wrong prototype!\n";
+ WithColor::error(errs(), argv[0])
+ << "exit defined with wrong prototype!\n";
abort();
}
} else {
@@ -602,13 +637,15 @@ int main(int argc, char **argv, char * const *envp) {
// Lanch the remote process and get a channel to it.
std::unique_ptr<FDRawChannel> C = launchRemote();
if (!C) {
- errs() << "Failed to launch remote JIT.\n";
+ WithColor::error(errs(), argv[0]) << "failed to launch remote JIT.\n";
exit(1);
}
// Create a remote target client running over the channel.
+ llvm::orc::ExecutionSession ES;
+ ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); });
typedef orc::remote::OrcRemoteTargetClient MyRemote;
- auto R = ExitOnErr(MyRemote::Create(*C, ExitOnErr));
+ auto R = ExitOnErr(MyRemote::Create(*C, ES));
// Create a remote memory manager.
auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager());
@@ -632,8 +669,8 @@ int main(int argc, char **argv, char * const *envp) {
// FIXME: argv and envp handling.
JITTargetAddress Entry = EE->getFunctionAddress(EntryFn->getName().str());
EE->finalizeObject();
- DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
- << format("%llx", Entry) << "\n");
+ LLVM_DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
+ << format("%llx", Entry) << "\n");
Result = ExitOnErr(R->callIntVoid(Entry));
// Like static constructors, the remote target MCJIT support doesn't handle
@@ -651,6 +688,130 @@ int main(int argc, char **argv, char * const *envp) {
return Result;
}
+static orc::IRTransformLayer2::TransformFunction createDebugDumper() {
+ switch (OrcDumpKind) {
+ case DumpKind::NoDump:
+ return [](std::unique_ptr<Module> M) { return M; };
+
+ case DumpKind::DumpFuncsToStdOut:
+ return [](std::unique_ptr<Module> M) {
+ printf("[ ");
+
+ for (const auto &F : *M) {
+ if (F.isDeclaration())
+ continue;
+
+ if (F.hasName()) {
+ std::string Name(F.getName());
+ printf("%s ", Name.c_str());
+ } else
+ printf("<anon> ");
+ }
+
+ printf("]\n");
+ return M;
+ };
+
+ case DumpKind::DumpModsToStdOut:
+ return [](std::unique_ptr<Module> M) {
+ outs() << "----- Module Start -----\n"
+ << *M << "----- Module End -----\n";
+
+ return M;
+ };
+
+ case DumpKind::DumpModsToDisk:
+ return [](std::unique_ptr<Module> M) {
+ std::error_code EC;
+ raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC, sys::fs::F_Text);
+ if (EC) {
+ errs() << "Couldn't open " << M->getModuleIdentifier()
+ << " for dumping.\nError:" << EC.message() << "\n";
+ exit(1);
+ }
+ Out << *M;
+ return M;
+ };
+ }
+ llvm_unreachable("Unknown DumpKind");
+}
+
+int runOrcLazyJIT(LLVMContext &Ctx, std::vector<std::unique_ptr<Module>> Ms,
+ const std::vector<std::string> &Args) {
+ // Bail out early if no modules loaded.
+ if (Ms.empty())
+ return 0;
+
+ // Add lli's symbols into the JIT's search space.
+ std::string ErrMsg;
+ sys::DynamicLibrary LibLLI =
+ sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg);
+ if (!LibLLI.isValid()) {
+ errs() << "Error loading lli symbols: " << ErrMsg << ".\n";
+ return 1;
+ }
+
+ const auto &TT = Ms.front()->getTargetTriple();
+ orc::JITTargetMachineBuilder TMD =
+ TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())
+ : orc::JITTargetMachineBuilder(Triple(TT));
+
+ TMD.setArch(MArch)
+ .setCPU(getCPUStr())
+ .addFeatures(getFeatureList())
+ .setRelocationModel(RelocModel.getNumOccurrences()
+ ? Optional<Reloc::Model>(RelocModel)
+ : None)
+ .setCodeModel(CMModel.getNumOccurrences()
+ ? Optional<CodeModel::Model>(CMModel)
+ : None);
+ auto TM = ExitOnErr(TMD.createTargetMachine());
+ auto DL = TM->createDataLayout();
+ auto ES = llvm::make_unique<orc::ExecutionSession>();
+ auto J =
+ ExitOnErr(orc::LLLazyJIT::Create(std::move(ES), std::move(TM), DL, Ctx));
+
+ auto Dump = createDebugDumper();
+
+ J->setLazyCompileTransform(
+ [&](std::unique_ptr<Module> M) {
+ if (verifyModule(*M, &dbgs())) {
+ dbgs() << "Bad module: " << *M << "\n";
+ exit(1);
+ }
+ return Dump(std::move(M));
+ });
+ J->getMainVSO().setFallbackDefinitionGenerator(
+ orc::DynamicLibraryFallbackGenerator(
+ std::move(LibLLI), DL, [](orc::SymbolStringPtr) { return true; }));
+
+ orc::MangleAndInterner Mangle(J->getExecutionSession(), DL);
+ orc::LocalCXXRuntimeOverrides2 CXXRuntimeOverrides;
+ ExitOnErr(CXXRuntimeOverrides.enable(J->getMainVSO(), Mangle));
+
+ for (auto &M : Ms) {
+ orc::makeAllSymbolsExternallyAccessible(*M);
+ ExitOnErr(J->addLazyIRModule(std::move(M)));
+ }
+
+ ExitOnErr(J->runConstructors());
+
+ auto MainSym = ExitOnErr(J->lookup("main"));
+ typedef int (*MainFnPtr)(int, const char *[]);
+ std::vector<const char *> ArgV;
+ for (auto &Arg : Args)
+ ArgV.push_back(Arg.c_str());
+ auto Main =
+ reinterpret_cast<MainFnPtr>(static_cast<uintptr_t>(MainSym.getAddress()));
+ auto Result = Main(ArgV.size(), (const char **)ArgV.data());
+
+ ExitOnErr(J->runDestructors());
+
+ CXXRuntimeOverrides.runDestructors();
+
+ return Result;
+}
+
std::unique_ptr<FDRawChannel> launchRemote() {
#ifndef LLVM_ON_UNIX
llvm_unreachable("launchRemote not supported on non-Unix platforms");
diff --git a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
index ae7d1a7f1b7a..64be08ff946a 100644
--- a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -15,8 +15,6 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
-#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/MachO.h"
@@ -26,15 +24,17 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
+#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
@@ -47,10 +47,74 @@ using namespace llvm;
// The name this program was invoked as.
static StringRef ToolName;
+// The basename of this program.
+static StringRef Stem;
+
+const char RanlibHelp[] = R"(
+OVERVIEW: LLVM Ranlib (llvm-ranlib)
+
+ This program generates an index to speed access to archives
+
+USAGE: llvm-ranlib <archive-file>
+
+OPTIONS:
+ -help - Display available options
+ -version - Display the version of this program
+)";
+
+const char ArHelp[] = R"(
+OVERVIEW: LLVM Archiver
+
+USAGE: llvm-ar [options] [-]<operation>[modifiers] [relpos] <archive> [files]
+ llvm-ar -M [<mri-script]
+
+OPTIONS:
+ --format - Archive format to create
+ =default - default
+ =gnu - gnu
+ =darwin - darwin
+ =bsd - bsd
+ --plugin=<string> - Ignored for compatibility
+ --help - Display available options
+ --version - Display the version of this program
+
+OPERATIONS:
+ d - delete [files] from the archive
+ m - move [files] in the archive
+ p - print [files] found in the archive
+ q - quick append [files] to the archive
+ r - replace or insert [files] into the archive
+ s - act as ranlib
+ t - display contents of archive
+ x - extract [files] from the archive
+
+MODIFIERS:
+ [a] - put [files] after [relpos]
+ [b] - put [files] before [relpos] (same as [i])
+ [c] - do not warn if archive had to be created
+ [D] - use zero for timestamps and uids/gids (default)
+ [i] - put [files] before [relpos] (same as [b])
+ [l] - ignored for compatibility
+ [o] - preserve original dates
+ [s] - create an archive index (cf. ranlib)
+ [S] - do not build a symbol table
+ [T] - create a thin archive
+ [u] - update only [files] newer than archive contents
+ [U] - use actual timestamps and uids/gids
+ [v] - be verbose about actions taken
+)";
+
+void printHelpMessage() {
+ if (Stem.contains_lower("ranlib"))
+ outs() << RanlibHelp;
+ else if (Stem.contains_lower("ar"))
+ outs() << ArHelp;
+}
+
// Show the error message and exit.
LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) {
errs() << ToolName << ": " << Error << ".\n";
- cl::PrintHelpMessage();
+ printHelpMessage();
exit(1);
}
@@ -76,55 +140,18 @@ static void failIfError(Error E, Twine Context = "") {
});
}
-// llvm-ar/llvm-ranlib remaining positional arguments.
-static cl::list<std::string>
- RestOfArgs(cl::Positional, cl::ZeroOrMore,
- cl::desc("[relpos] [count] <archive-file> [members]..."));
+static SmallVector<const char *, 256> PositionalArgs;
-static cl::opt<bool> MRI("M", cl::desc(""));
-static cl::opt<std::string> Plugin("plugin", cl::desc("plugin (ignored for compatibility"));
+static bool MRI;
namespace {
-enum Format { Default, GNU, BSD, DARWIN };
+enum Format { Default, GNU, BSD, DARWIN, Unknown };
}
-static cl::opt<Format>
- FormatOpt("format", cl::desc("Archive format to create"),
- cl::values(clEnumValN(Default, "default", "default"),
- clEnumValN(GNU, "gnu", "gnu"),
- clEnumValN(DARWIN, "darwin", "darwin"),
- clEnumValN(BSD, "bsd", "bsd")));
+static Format FormatType = Default;
static std::string Options;
-// Provide additional help output explaining the operations and modifiers of
-// llvm-ar. This object instructs the CommandLine library to print the text of
-// the constructor when the --help option is given.
-static cl::extrahelp MoreHelp(
- "\nOPERATIONS:\n"
- " d[NsS] - delete file(s) from the archive\n"
- " m[abiSs] - move file(s) in the archive\n"
- " p[kN] - print file(s) found in the archive\n"
- " q[ufsS] - quick append file(s) to the archive\n"
- " r[abfiuRsS] - replace or insert file(s) into the archive\n"
- " t - display contents of archive\n"
- " x[No] - extract file(s) from the archive\n"
- "\nMODIFIERS (operation specific):\n"
- " [a] - put file(s) after [relpos]\n"
- " [b] - put file(s) before [relpos] (same as [i])\n"
- " [i] - put file(s) before [relpos] (same as [b])\n"
- " [o] - preserve original dates\n"
- " [s] - create an archive index (cf. ranlib)\n"
- " [S] - do not build a symbol table\n"
- " [T] - create a thin archive\n"
- " [u] - update only files newer than archive contents\n"
- "\nMODIFIERS (generic):\n"
- " [c] - do not warn if the library had to be created\n"
- " [v] - be verbose about actions taken\n"
-);
-
-static const char OptionChars[] = "dmpqrtxabiosSTucv";
-
// This enumeration delineates the kinds of operations on an archive
// that are permitted.
enum ArchiveOperation {
@@ -166,30 +193,23 @@ static std::vector<StringRef> Members;
// Extract the member filename from the command line for the [relpos] argument
// associated with a, b, and i modifiers
static void getRelPos() {
- if(RestOfArgs.size() == 0)
+ if (PositionalArgs.size() == 0)
fail("Expected [relpos] for a, b, or i modifier");
- RelPos = RestOfArgs[0];
- RestOfArgs.erase(RestOfArgs.begin());
-}
-
-static void getOptions() {
- if(RestOfArgs.size() == 0)
- fail("Expected options");
- Options = RestOfArgs[0];
- RestOfArgs.erase(RestOfArgs.begin());
+ RelPos = PositionalArgs[0];
+ PositionalArgs.erase(PositionalArgs.begin());
}
// Get the archive file name from the command line
static void getArchive() {
- if(RestOfArgs.size() == 0)
+ if (PositionalArgs.size() == 0)
fail("An archive name must be specified");
- ArchiveName = RestOfArgs[0];
- RestOfArgs.erase(RestOfArgs.begin());
+ ArchiveName = PositionalArgs[0];
+ PositionalArgs.erase(PositionalArgs.begin());
}
-// Copy over remaining items in RestOfArgs to our Members vector
+// Copy over remaining items in PositionalArgs to our Members vector
static void getMembers() {
- for (auto &Arg : RestOfArgs)
+ for (auto &Arg : PositionalArgs)
Members.push_back(Arg);
}
@@ -200,13 +220,11 @@ static void runMRIScript();
// modifier/operation pairs have not been violated.
static ArchiveOperation parseCommandLine() {
if (MRI) {
- if (!RestOfArgs.empty())
+ if (!PositionalArgs.empty() || !Options.empty())
fail("Cannot mix -M and other options");
runMRIScript();
}
- getOptions();
-
// Keep track of number of operations. We can only specify one
// per execution.
unsigned NumOperations = 0;
@@ -370,6 +388,7 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
int FD;
failIfError(sys::fs::openFileForWrite(sys::path::filename(Name), FD,
+ sys::fs::CD_CreateAlways,
sys::fs::F_None, Mode),
Name);
@@ -651,7 +670,7 @@ performWriteOperation(ArchiveOperation Operation,
NewMembers = computeNewArchiveMembers(Operation, OldArchive);
object::Archive::Kind Kind;
- switch (FormatOpt) {
+ switch (FormatType) {
case Default:
if (Thin)
Kind = object::Archive::K_GNU;
@@ -677,6 +696,8 @@ performWriteOperation(ArchiveOperation Operation,
fail("Only the gnu format has a thin mode");
Kind = object::Archive::K_DARWIN;
break;
+ case Unknown:
+ llvm_unreachable("");
}
Error E =
@@ -758,7 +779,7 @@ static int performOperation(ArchiveOperation Operation,
}
static void runMRIScript() {
- enum class MRICommand { AddLib, AddMod, Create, Save, End, Invalid };
+ enum class MRICommand { AddLib, AddMod, Create, Delete, Save, End, Invalid };
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getSTDIN();
failIfError(Buf.getError());
@@ -779,6 +800,7 @@ static void runMRIScript() {
.Case("addlib", MRICommand::AddLib)
.Case("addmod", MRICommand::AddMod)
.Case("create", MRICommand::Create)
+ .Case("delete", MRICommand::Delete)
.Case("save", MRICommand::Save)
.Case("end", MRICommand::End)
.Default(MRICommand::Invalid);
@@ -813,6 +835,12 @@ static void runMRIScript() {
fail("File already saved");
ArchiveName = Rest;
break;
+ case MRICommand::Delete: {
+ StringRef Name = sys::path::filename(Rest);
+ llvm::erase_if(NewMembers,
+ [=](NewArchiveMember &M) { return M.MemberName == Name; });
+ break;
+ }
case MRICommand::Save:
Saved = true;
break;
@@ -829,67 +857,113 @@ static void runMRIScript() {
exit(0);
}
-static int ar_main() {
- // Do our own parsing of the command line because the CommandLine utility
- // can't handle the grouped positional parameters without a dash.
+static bool handleGenericOption(StringRef arg) {
+ if (arg == "-help" || arg == "--help") {
+ printHelpMessage();
+ return true;
+ }
+ if (arg == "-version" || arg == "--version") {
+ cl::PrintVersionMessage();
+ return true;
+ }
+ return false;
+}
+
+static int ar_main(int argc, char **argv) {
+ SmallVector<const char *, 0> Argv(argv, argv + argc);
+ BumpPtrAllocator Alloc;
+ StringSaver Saver(Alloc);
+ cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
+ for(size_t i = 1; i < Argv.size(); ++i) {
+ StringRef Arg = Argv[i];
+ const char *match;
+ auto MatchFlagWithArg = [&](const char *expected) {
+ size_t len = strlen(expected);
+ if (Arg == expected) {
+ if (++i >= Argv.size())
+ fail(std::string(expected) + " requires an argument");
+ match = Argv[i];
+ return true;
+ }
+ if (Arg.startswith(expected) && Arg.size() > len &&
+ Arg[len] == '=') {
+ match = Arg.data() + len + 1;
+ return true;
+ }
+ return false;
+ };
+ if (handleGenericOption(Argv[i]))
+ return 0;
+ if (Arg == "--") {
+ for(; i < Argv.size(); ++i)
+ PositionalArgs.push_back(Argv[i]);
+ break;
+ }
+ if (Arg[0] == '-') {
+ if (Arg.startswith("--"))
+ Arg = Argv[i] + 2;
+ else
+ Arg = Argv[i] + 1;
+ if (Arg == "M") {
+ MRI = true;
+ } else if (MatchFlagWithArg("format")) {
+ FormatType = StringSwitch<Format>(match)
+ .Case("default", Default)
+ .Case("gnu", GNU)
+ .Case("darwin", DARWIN)
+ .Case("bsd", BSD)
+ .Default(Unknown);
+ if (FormatType == Unknown)
+ fail(std::string("Invalid format ") + match);
+ } else if (MatchFlagWithArg("plugin")) {
+ // Ignored.
+ } else {
+ Options += Argv[i] + 1;
+ }
+ } else if (Options.empty()) {
+ Options += Argv[i];
+ } else {
+ PositionalArgs.push_back(Argv[i]);
+ }
+ }
ArchiveOperation Operation = parseCommandLine();
return performOperation(Operation, nullptr);
}
-static int ranlib_main() {
- if (RestOfArgs.size() != 1)
- fail(ToolName + " takes just one archive as an argument");
- ArchiveName = RestOfArgs[0];
+static int ranlib_main(int argc, char **argv) {
+ bool ArchiveSpecified = false;
+ for(int i = 1; i < argc; ++i) {
+ if (handleGenericOption(argv[i])) {
+ return 0;
+ } else {
+ if (ArchiveSpecified)
+ fail("Exactly one archive should be specified");
+ ArchiveSpecified = true;
+ ArchiveName = argv[i];
+ }
+ }
return performOperation(CreateSymTab, nullptr);
}
int main(int argc, char **argv) {
+ InitLLVM X(argc, argv);
ToolName = argv[0];
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
- StringRef Stem = sys::path::stem(ToolName);
- if (Stem.find("dlltool") != StringRef::npos)
+ Stem = sys::path::stem(ToolName);
+ if (Stem.contains_lower("dlltool"))
return dlltoolDriverMain(makeArrayRef(argv, argc));
- if (Stem.find("ranlib") == StringRef::npos &&
- Stem.find("lib") != StringRef::npos)
- return libDriverMain(makeArrayRef(argv, argc));
+ if (Stem.contains_lower("ranlib"))
+ return ranlib_main(argc, argv);
- for (int i = 1; i < argc; i++) {
- // If an argument starts with a dash and only contains chars
- // that belong to the options chars set, remove the dash.
- // We can't handle it after the command line options parsing
- // is done, since it will error out on an unrecognized string
- // starting with a dash.
- // Make sure this doesn't match the actual llvm-ar specific options
- // that start with a dash.
- StringRef S = argv[i];
- if (S.startswith("-") &&
- S.find_first_not_of(OptionChars, 1) == StringRef::npos) {
- argv[i]++;
- break;
- }
- if (S == "--")
- break;
- }
+ if (Stem.contains_lower("lib"))
+ return libDriverMain(makeArrayRef(argv, argc));
- // Have the command line options parsed and handle things
- // like --help and --version.
- cl::ParseCommandLineOptions(argc, argv,
- "LLVM Archiver (llvm-ar)\n\n"
- " This program archives bitcode files into single libraries\n"
- );
-
- if (Stem.find("ranlib") != StringRef::npos)
- return ranlib_main();
- if (Stem.find("ar") != StringRef::npos)
- return ar_main();
+ if (Stem.contains_lower("ar"))
+ return ar_main(argc, argv);
fail("Not ranlib, ar, lib or dlltool!");
}
diff --git a/contrib/llvm/tools/llvm-as/llvm-as.cpp b/contrib/llvm/tools/llvm-as/llvm-as.cpp
index 9f0f162b74f8..bb4233aa9ba0 100644
--- a/contrib/llvm/tools/llvm-as/llvm-as.cpp
+++ b/contrib/llvm/tools/llvm-as/llvm-as.cpp
@@ -19,12 +19,12 @@
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -59,7 +59,12 @@ static cl::opt<bool> PreserveBitcodeUseListOrder(
cl::desc("Preserve use-list order when writing LLVM bitcode."),
cl::init(true), cl::Hidden);
-static void WriteOutputFile(const Module *M) {
+static cl::opt<std::string> ClDataLayout("data-layout",
+ cl::desc("data layout string to use"),
+ cl::value_desc("layout-string"),
+ cl::init(""));
+
+static void WriteOutputFile(const Module *M, const ModuleSummaryIndex *Index) {
// Infer the output filename if needed.
if (OutputFilename.empty()) {
if (InputFilename == "-") {
@@ -79,30 +84,44 @@ static void WriteOutputFile(const Module *M) {
exit(1);
}
- if (Force || !CheckBitcodeOutputToConsole(Out->os(), true))
- WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder, nullptr,
- EmitModuleHash);
+ if (Force || !CheckBitcodeOutputToConsole(Out->os(), true)) {
+ const ModuleSummaryIndex *IndexToWrite = nullptr;
+ // Don't attempt to write a summary index unless it contains any entries.
+ // Otherwise we get an empty summary section.
+ if (Index && Index->begin() != Index->end())
+ IndexToWrite = Index;
+ if (!IndexToWrite || (M && (!M->empty() || !M->global_empty())))
+ // If we have a non-empty Module, then we write the Module plus
+ // any non-null Index along with it as a per-module Index.
+ // If both are empty, this will give an empty module block, which is
+ // the expected behavior.
+ WriteBitcodeToFile(*M, Out->os(), PreserveBitcodeUseListOrder,
+ IndexToWrite, EmitModuleHash);
+ else
+ // Otherwise, with an empty Module but non-empty Index, we write a
+ // combined index.
+ WriteIndexToFile(*IndexToWrite, Out->os());
+ }
// Declare success.
Out->keep();
}
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
LLVMContext Context;
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n");
// Parse the file now...
SMDiagnostic Err;
- std::unique_ptr<Module> M =
- parseAssemblyFile(InputFilename, Err, Context, nullptr, !DisableVerify);
+ auto ModuleAndIndex = parseAssemblyFileWithIndex(
+ InputFilename, Err, Context, nullptr, !DisableVerify, ClDataLayout);
+ std::unique_ptr<Module> M = std::move(ModuleAndIndex.Mod);
if (!M.get()) {
Err.print(argv[0], errs());
return 1;
}
+ std::unique_ptr<ModuleSummaryIndex> Index = std::move(ModuleAndIndex.Index);
if (!DisableVerify) {
std::string ErrorStr;
@@ -113,13 +132,17 @@ int main(int argc, char **argv) {
errs() << OS.str();
return 1;
}
+ // TODO: Implement and call summary index verifier.
}
- if (DumpAsm)
+ if (DumpAsm) {
errs() << "Here's the assembly:\n" << *M.get();
+ if (Index.get() && Index->begin() != Index->end())
+ Index->print(errs());
+ }
if (!DisableOutput)
- WriteOutputFile(M.get());
+ WriteOutputFile(M.get(), Index.get());
return 0;
}
diff --git a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 7f20e136eefd..1939dc6440fe 100644
--- a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -33,11 +33,11 @@
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SHA1.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -75,7 +75,9 @@ namespace {
/// CurStreamTypeType - A type for CurStreamType
enum CurStreamTypeType {
UnknownBitstream,
- LLVMIRBitstream
+ LLVMIRBitstream,
+ ClangSerializedASTBitstream,
+ ClangSerializedDiagnosticsBitstream,
};
}
@@ -306,6 +308,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
return nullptr;
STRINGIFY_CODE(FS, PERMODULE)
STRINGIFY_CODE(FS, PERMODULE_PROFILE)
+ STRINGIFY_CODE(FS, PERMODULE_RELBF)
STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
STRINGIFY_CODE(FS, COMBINED)
STRINGIFY_CODE(FS, COMBINED_PROFILE)
@@ -314,6 +317,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FS, COMBINED_ALIAS)
STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
STRINGIFY_CODE(FS, VERSION)
+ STRINGIFY_CODE(FS, FLAGS)
STRINGIFY_CODE(FS, TYPE_TESTS)
STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS)
STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS)
@@ -322,6 +326,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FS, VALUE_GUID)
STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
+ STRINGIFY_CODE(FS, TYPE_ID)
}
case bitc::METADATA_ATTACHMENT_ID:
switch(CodeID) {
@@ -442,7 +447,7 @@ static std::map<unsigned, PerBlockIDStats> BlockIDStats;
/// ReportError - All bitcode analysis errors go through this function, making this a
/// good place to breakpoint if debugging.
static bool ReportError(const Twine &Err) {
- errs() << Err << "\n";
+ WithColor::error() << Err << "\n";
return true;
}
@@ -597,7 +602,7 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
++BlockStats.NumRecords;
StringRef Blob;
- unsigned CurrentRecordPos = Stream.GetCurrentBitNo();
+ uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
// Increment the # occurrences of this code.
@@ -694,7 +699,7 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
std::string Str;
bool ArrayIsPrintable = true;
for (unsigned j = i - 1, je = Record.size(); j != je; ++j) {
- if (!isprint(static_cast<unsigned char>(Record[j]))) {
+ if (!isPrint(static_cast<unsigned char>(Record[j]))) {
ArrayIsPrintable = false;
break;
}
@@ -714,7 +719,7 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
} else {
bool BlobIsPrintable = true;
for (unsigned i = 0, e = Blob.size(); i != e; ++i)
- if (!isprint(static_cast<unsigned char>(Blob[i]))) {
+ if (!isPrint(static_cast<unsigned char>(Blob[i]))) {
BlobIsPrintable = false;
break;
}
@@ -743,6 +748,35 @@ static void PrintSize(uint64_t Bits) {
(double)Bits/8, (unsigned long)(Bits/32));
}
+static CurStreamTypeType ReadSignature(BitstreamCursor &Stream) {
+ char Signature[6];
+ Signature[0] = Stream.Read(8);
+ Signature[1] = Stream.Read(8);
+
+ // Autodetect the file contents, if it is one we know.
+ if (Signature[0] == 'C' && Signature[1] == 'P') {
+ Signature[2] = Stream.Read(8);
+ Signature[3] = Stream.Read(8);
+ if (Signature[2] == 'C' && Signature[3] == 'H')
+ return ClangSerializedASTBitstream;
+ } else if (Signature[0] == 'D' && Signature[1] == 'I') {
+ Signature[2] = Stream.Read(8);
+ Signature[3] = Stream.Read(8);
+ if (Signature[2] == 'A' && Signature[3] == 'G')
+ return ClangSerializedDiagnosticsBitstream;
+ } else {
+ Signature[2] = Stream.Read(4);
+ Signature[3] = Stream.Read(4);
+ Signature[4] = Stream.Read(4);
+ Signature[5] = Stream.Read(4);
+ if (Signature[0] == 'B' && Signature[1] == 'C' &&
+ Signature[2] == 0x0 && Signature[3] == 0xC &&
+ Signature[4] == 0xE && Signature[5] == 0xD)
+ return LLVMIRBitstream;
+ }
+ return UnknownBitstream;
+}
+
static bool openBitcodeFile(StringRef Path,
std::unique_ptr<MemoryBuffer> &MemBuf,
BitstreamCursor &Stream,
@@ -786,22 +820,7 @@ static bool openBitcodeFile(StringRef Path,
}
Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
-
- // Read the stream signature.
- char Signature[6];
- Signature[0] = Stream.Read(8);
- Signature[1] = Stream.Read(8);
- Signature[2] = Stream.Read(4);
- Signature[3] = Stream.Read(4);
- Signature[4] = Stream.Read(4);
- Signature[5] = Stream.Read(4);
-
- // Autodetect the file contents, if it is one we know.
- CurStreamType = UnknownBitstream;
- if (Signature[0] == 'B' && Signature[1] == 'C' &&
- Signature[2] == 0x0 && Signature[3] == 0xC &&
- Signature[4] == 0xE && Signature[5] == 0xD)
- CurStreamType = LLVMIRBitstream;
+ CurStreamType = ReadSignature(Stream);
return false;
}
@@ -870,8 +889,18 @@ static int AnalyzeBitcode() {
outs() << "\n";
outs() << " Stream type: ";
switch (CurStreamType) {
- case UnknownBitstream: outs() << "unknown\n"; break;
- case LLVMIRBitstream: outs() << "LLVM IR\n"; break;
+ case UnknownBitstream:
+ outs() << "unknown\n";
+ break;
+ case LLVMIRBitstream:
+ outs() << "LLVM IR\n";
+ break;
+ case ClangSerializedASTBitstream:
+ outs() << "Clang Serialized AST\n";
+ break;
+ case ClangSerializedDiagnosticsBitstream:
+ outs() << "Clang Serialized Diagnostics\n";
+ break;
}
outs() << " # Toplevel Blocks: " << NumTopBlocks << "\n";
outs() << "\n";
@@ -961,11 +990,7 @@ static int AnalyzeBitcode() {
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
-
return AnalyzeBitcode();
}
diff --git a/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp b/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp
index c5ea50bff273..e93b63d388e0 100644
--- a/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CoverageExporterJson.h"
#include "CoverageFilters.h"
#include "CoverageReport.h"
#include "CoverageSummaryInfo.h"
@@ -32,8 +33,8 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/Threading.h"
#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Support/ToolOutputFile.h"
#include <functional>
@@ -48,83 +49,84 @@ void exportCoverageDataToJson(const coverage::CoverageMapping &CoverageMapping,
raw_ostream &OS);
namespace {
-/// \brief The implementation of the coverage tool.
+/// The implementation of the coverage tool.
class CodeCoverageTool {
public:
enum Command {
- /// \brief The show command.
+ /// The show command.
Show,
- /// \brief The report command.
+ /// The report command.
Report,
- /// \brief The export command.
+ /// The export command.
Export
};
int run(Command Cmd, int argc, const char **argv);
private:
- /// \brief Print the error message to the error output stream.
+ /// Print the error message to the error output stream.
void error(const Twine &Message, StringRef Whence = "");
- /// \brief Print the warning message to the error output stream.
+ /// Print the warning message to the error output stream.
void warning(const Twine &Message, StringRef Whence = "");
- /// \brief Convert \p Path into an absolute path and append it to the list
+ /// Convert \p Path into an absolute path and append it to the list
/// of collected paths.
void addCollectedPath(const std::string &Path);
- /// \brief If \p Path is a regular file, collect the path. If it's a
+ /// If \p Path is a regular file, collect the path. If it's a
/// directory, recursively collect all of the paths within the directory.
void collectPaths(const std::string &Path);
- /// \brief Return a memory buffer for the given source file.
+ /// Return a memory buffer for the given source file.
ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile);
- /// \brief Create source views for the expansions of the view.
+ /// Create source views for the expansions of the view.
void attachExpansionSubViews(SourceCoverageView &View,
ArrayRef<ExpansionRecord> Expansions,
const CoverageMapping &Coverage);
- /// \brief Create the source view of a particular function.
+ /// Create the source view of a particular function.
std::unique_ptr<SourceCoverageView>
createFunctionView(const FunctionRecord &Function,
const CoverageMapping &Coverage);
- /// \brief Create the main source view of a particular source file.
+ /// Create the main source view of a particular source file.
std::unique_ptr<SourceCoverageView>
createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage);
- /// \brief Load the coverage mapping data. Return nullptr if an error occurred.
+ /// Load the coverage mapping data. Return nullptr if an error occurred.
std::unique_ptr<CoverageMapping> load();
- /// \brief Create a mapping from files in the Coverage data to local copies
+ /// Create a mapping from files in the Coverage data to local copies
/// (path-equivalence).
void remapPathNames(const CoverageMapping &Coverage);
- /// \brief Remove input source files which aren't mapped by \p Coverage.
+ /// Remove input source files which aren't mapped by \p Coverage.
void removeUnmappedInputs(const CoverageMapping &Coverage);
- /// \brief If a demangler is available, demangle all symbol names.
+ /// If a demangler is available, demangle all symbol names.
void demangleSymbols(const CoverageMapping &Coverage);
- /// \brief Write out a source file view to the filesystem.
+ /// Write out a source file view to the filesystem.
void writeSourceFileView(StringRef SourceFile, CoverageMapping *Coverage,
CoveragePrinter *Printer, bool ShowFilenames);
typedef llvm::function_ref<int(int, const char **)> CommandLineParserType;
- int show(int argc, const char **argv,
- CommandLineParserType commandLineParser);
-
- int report(int argc, const char **argv,
+ int doShow(int argc, const char **argv,
CommandLineParserType commandLineParser);
- int export_(int argc, const char **argv,
- CommandLineParserType commandLineParser);
+ int doReport(int argc, const char **argv,
+ CommandLineParserType commandLineParser);
+
+ int doExport(int argc, const char **argv,
+ CommandLineParserType commandLineParser);
std::vector<StringRef> ObjectFilenames;
CoverageViewOptions ViewOpts;
CoverageFiltersMatchAll Filters;
+ CoverageFilters IgnoreFilenameFilters;
/// The path to the indexed profile.
std::string PGOFilename;
@@ -188,7 +190,8 @@ void CodeCoverageTool::addCollectedPath(const std::string &Path) {
return;
}
sys::path::remove_dots(EffectivePath, /*remove_dot_dots=*/true);
- SourceFiles.emplace_back(EffectivePath.str());
+ if (!IgnoreFilenameFilters.matchesFilename(EffectivePath))
+ SourceFiles.emplace_back(EffectivePath.str());
}
void CodeCoverageTool::collectPaths(const std::string &Path) {
@@ -198,7 +201,7 @@ void CodeCoverageTool::collectPaths(const std::string &Path) {
if (PathRemapping)
addCollectedPath(Path);
else
- error("Missing source file", Path);
+ warning("Source file doesn't exist, proceeded by ignoring it.", Path);
return;
}
@@ -210,12 +213,16 @@ void CodeCoverageTool::collectPaths(const std::string &Path) {
if (llvm::sys::fs::is_directory(Status)) {
std::error_code EC;
for (llvm::sys::fs::recursive_directory_iterator F(Path, EC), E;
- F != E && !EC; F.increment(EC)) {
+ F != E; F.increment(EC)) {
+
+ if (EC) {
+ warning(EC.message(), F->path());
+ continue;
+ }
+
if (llvm::sys::fs::is_regular_file(F->path()))
addCollectedPath(F->path());
}
- if (EC)
- warning(EC.message(), Path);
}
}
@@ -471,14 +478,13 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {
OutputTOF.os().close();
// Invoke the demangler.
- std::vector<const char *> ArgsV;
- for (const std::string &Arg : ViewOpts.DemanglerOpts)
- ArgsV.push_back(Arg.c_str());
- ArgsV.push_back(nullptr);
+ std::vector<StringRef> ArgsV;
+ for (StringRef Arg : ViewOpts.DemanglerOpts)
+ ArgsV.push_back(Arg);
Optional<StringRef> Redirects[] = {InputPath.str(), OutputPath.str(), {""}};
std::string ErrMsg;
- int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(),
- /*env=*/nullptr, Redirects, /*secondsToWait=*/0,
+ int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV,
+ /*env=*/None, Redirects, /*secondsToWait=*/0,
/*memoryLimit=*/0, &ErrMsg);
if (RC) {
error(ErrMsg, ViewOpts.DemanglerOpts[0]);
@@ -592,6 +598,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"regular expression"),
cl::ZeroOrMore, cl::cat(FilteringCategory));
+ cl::list<std::string> IgnoreFilenameRegexFilters(
+ "ignore-filename-regex", cl::Optional,
+ cl::desc("Skip source code files with file paths that match the given "
+ "regular expression"),
+ cl::ZeroOrMore, cl::cat(FilteringCategory));
+
cl::opt<double> RegionCoverageLtFilter(
"region-coverage-lt", cl::Optional,
cl::desc("Show code coverage only for functions with region coverage "
@@ -636,6 +648,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"summary-only", cl::Optional,
cl::desc("Export only summary information for each source file"));
+ cl::opt<unsigned> NumThreads(
+ "num-threads", cl::init(0),
+ cl::desc("Number of merge threads to use (default: autodetect)"));
+ cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
+ cl::aliasopt(NumThreads));
+
auto commandLineParser = [&, this](int argc, const char **argv) -> int {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
ViewOpts.Debug = DebugDump;
@@ -703,6 +721,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
llvm::make_unique<NameRegexCoverageFilter>(Regex));
Filters.push_back(std::move(NameFilterer));
}
+
if (RegionCoverageLtFilter.getNumOccurrences() ||
RegionCoverageGtFilter.getNumOccurrences() ||
LineCoverageLtFilter.getNumOccurrences() ||
@@ -723,6 +742,11 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
Filters.push_back(std::move(StatFilterer));
}
+ // Create the ignore filename filters.
+ for (const auto &RE : IgnoreFilenameRegexFilters)
+ IgnoreFilenameFilters.push_back(
+ llvm::make_unique<NameRegexCoverageFilter>(RE));
+
if (!Arches.empty()) {
for (const std::string &Arch : Arches) {
if (Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) {
@@ -737,6 +761,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
}
}
+ // IgnoreFilenameFilters are applied even when InputSourceFiles specified.
for (const std::string &File : InputSourceFiles)
collectPaths(File);
@@ -749,23 +774,24 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
ViewOpts.ShowRegionSummary = RegionSummary;
ViewOpts.ShowInstantiationSummary = InstantiationSummary;
ViewOpts.ExportSummaryOnly = SummaryOnly;
+ ViewOpts.NumThreads = NumThreads;
return 0;
};
switch (Cmd) {
case Show:
- return show(argc, argv, commandLineParser);
+ return doShow(argc, argv, commandLineParser);
case Report:
- return report(argc, argv, commandLineParser);
+ return doReport(argc, argv, commandLineParser);
case Export:
- return export_(argc, argv, commandLineParser);
+ return doExport(argc, argv, commandLineParser);
}
return 0;
}
-int CodeCoverageTool::show(int argc, const char **argv,
- CommandLineParserType commandLineParser) {
+int CodeCoverageTool::doShow(int argc, const char **argv,
+ CommandLineParserType commandLineParser) {
cl::OptionCategory ViewCategory("Viewing options");
@@ -808,12 +834,6 @@ int CodeCoverageTool::show(int argc, const char **argv,
"project-title", cl::Optional,
cl::desc("Set project title for the coverage report"));
- cl::opt<unsigned> NumThreads(
- "num-threads", cl::init(0),
- cl::desc("Number of merge threads to use (default: autodetect)"));
- cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
- cl::aliasopt(NumThreads));
-
auto Err = commandLineParser(argc, argv);
if (Err)
return Err;
@@ -856,8 +876,10 @@ int CodeCoverageTool::show(int argc, const char **argv,
if (SourceFiles.empty())
// Get the source files from the function coverage mapping.
- for (StringRef Filename : Coverage->getUniqueSourceFiles())
- SourceFiles.push_back(Filename);
+ for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
+ if (!IgnoreFilenameFilters.matchesFilename(Filename))
+ SourceFiles.push_back(Filename);
+ }
// Create an index out of the source files.
if (ViewOpts.hasOutputDirectory()) {
@@ -910,6 +932,8 @@ int CodeCoverageTool::show(int argc, const char **argv,
(SourceFiles.size() != 1) || ViewOpts.hasOutputDirectory() ||
(ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML);
+ auto NumThreads = ViewOpts.NumThreads;
+
// If NumThreads is not specified, auto-detect a good default.
if (NumThreads == 0)
NumThreads =
@@ -932,8 +956,8 @@ int CodeCoverageTool::show(int argc, const char **argv,
return 0;
}
-int CodeCoverageTool::report(int argc, const char **argv,
- CommandLineParserType commandLineParser) {
+int CodeCoverageTool::doReport(int argc, const char **argv,
+ CommandLineParserType commandLineParser) {
cl::opt<bool> ShowFunctionSummaries(
"show-functions", cl::Optional, cl::init(false),
cl::desc("Show coverage summaries for each function"));
@@ -954,7 +978,7 @@ int CodeCoverageTool::report(int argc, const char **argv,
CoverageReport Report(ViewOpts, *Coverage.get());
if (!ShowFunctionSummaries) {
if (SourceFiles.empty())
- Report.renderFileReports(llvm::outs());
+ Report.renderFileReports(llvm::outs(), IgnoreFilenameFilters);
else
Report.renderFileReports(llvm::outs(), SourceFiles);
} else {
@@ -969,8 +993,8 @@ int CodeCoverageTool::report(int argc, const char **argv,
return 0;
}
-int CodeCoverageTool::export_(int argc, const char **argv,
- CommandLineParserType commandLineParser) {
+int CodeCoverageTool::doExport(int argc, const char **argv,
+ CommandLineParserType commandLineParser) {
auto Err = commandLineParser(argc, argv);
if (Err)
@@ -987,7 +1011,12 @@ int CodeCoverageTool::export_(int argc, const char **argv,
return 1;
}
- exportCoverageDataToJson(*Coverage.get(), ViewOpts, outs());
+ auto Exporter = CoverageExporterJson(*Coverage.get(), ViewOpts, outs());
+
+ if (SourceFiles.empty())
+ Exporter.renderRoot(IgnoreFilenameFilters);
+ else
+ Exporter.renderRoot(SourceFiles);
return 0;
}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageExporter.h b/contrib/llvm/tools/llvm-cov/CoverageExporter.h
new file mode 100644
index 000000000000..884fba96d618
--- /dev/null
+++ b/contrib/llvm/tools/llvm-cov/CoverageExporter.h
@@ -0,0 +1,52 @@
+//===- CoverageExporter.h - Code coverage exporter ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class defines a code coverage exporter interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_COV_COVERAGEEXPORTER_H
+#define LLVM_COV_COVERAGEEXPORTER_H
+
+#include "CoverageFilters.h"
+#include "CoverageSummaryInfo.h"
+#include "CoverageViewOptions.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
+
+namespace llvm {
+
+/// Exports the code coverage information.
+class CoverageExporter {
+protected:
+ /// The full CoverageMapping object to export.
+ const coverage::CoverageMapping &Coverage;
+
+ /// The options passed to the tool.
+ const CoverageViewOptions &Options;
+
+ /// Output stream to print JSON to.
+ raw_ostream &OS;
+
+ CoverageExporter(const coverage::CoverageMapping &CoverageMapping,
+ const CoverageViewOptions &Options, raw_ostream &OS)
+ : Coverage(CoverageMapping), Options(Options), OS(OS) {}
+
+public:
+ virtual ~CoverageExporter(){};
+
+ /// Render the CoverageMapping object.
+ virtual void renderRoot(const CoverageFilters &IgnoreFilenameFilters) = 0;
+
+ /// Render the CoverageMapping object for specified source files.
+ virtual void renderRoot(const std::vector<std::string> &SourceFiles) = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_COV_COVERAGEEXPORTER_H
diff --git a/contrib/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/contrib/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 7b700908968d..56c3a0003b02 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/contrib/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -41,394 +41,346 @@
//
//===----------------------------------------------------------------------===//
+#include "CoverageExporterJson.h"
#include "CoverageReport.h"
-#include "CoverageSummaryInfo.h"
-#include "CoverageViewOptions.h"
-#include "llvm/ProfileData/Coverage/CoverageMapping.h"
-#include <stack>
-/// \brief The semantic version combined as a string.
+/// The semantic version combined as a string.
#define LLVM_COVERAGE_EXPORT_JSON_STR "2.0.0"
-/// \brief Unique type identifier for JSON coverage export.
+/// Unique type identifier for JSON coverage export.
#define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export"
using namespace llvm;
-using namespace coverage;
-class CoverageExporterJson {
- const CoverageViewOptions &Options;
-
- /// \brief Output stream to print JSON to.
- raw_ostream &OS;
-
- /// \brief The full CoverageMapping object to export.
- const CoverageMapping &Coverage;
-
- /// \brief States that the JSON rendering machine can be in.
- enum JsonState { None, NonEmptyElement, EmptyElement };
-
- /// \brief Tracks state of the JSON output.
- std::stack<JsonState> State;
-
- /// \brief Emit a serialized scalar.
- void emitSerialized(const int64_t Value) { OS << Value; }
-
- /// \brief Emit a serialized string.
- void emitSerialized(const std::string &Value) {
- OS << "\"";
- for (char C : Value) {
- if (C != '\\')
- OS << C;
- else
- OS << "\\\\";
- }
- OS << "\"";
- }
-
- /// \brief Emit a comma if there is a previous element to delimit.
- void emitComma() {
- if (State.top() == JsonState::NonEmptyElement) {
- OS << ",";
- } else if (State.top() == JsonState::EmptyElement) {
- State.pop();
- assert((State.size() >= 1) && "Closed too many JSON elements");
- State.push(JsonState::NonEmptyElement);
- }
- }
-
- /// \brief Emit a starting dictionary/object character.
- void emitDictStart() {
- emitComma();
- State.push(JsonState::EmptyElement);
- OS << "{";
- }
-
- /// \brief Emit a dictionary/object key but no value.
- void emitDictKey(const std::string &Key) {
- emitComma();
- emitSerialized(Key);
- OS << ":";
- State.pop();
- assert((State.size() >= 1) && "Closed too many JSON elements");
+CoverageExporterJson::CoverageExporterJson(
+ const coverage::CoverageMapping &CoverageMapping,
+ const CoverageViewOptions &Options, raw_ostream &OS)
+ : CoverageExporter(CoverageMapping, Options, OS) {
+ State.push(JsonState::None);
+}
- // We do not want to emit a comma after this key.
- State.push(JsonState::EmptyElement);
- }
+void CoverageExporterJson::emitSerialized(const int64_t Value) { OS << Value; }
- /// \brief Emit a dictionary/object key/value pair.
- template <typename V>
- void emitDictElement(const std::string &Key, const V &Value) {
- emitComma();
- emitSerialized(Key);
- OS << ":";
- emitSerialized(Value);
+void CoverageExporterJson::emitSerialized(const std::string &Value) {
+ OS << "\"";
+ for (char C : Value) {
+ if (C != '\\')
+ OS << C;
+ else
+ OS << "\\\\";
}
+ OS << "\"";
+}
- /// \brief Emit a closing dictionary/object character.
- void emitDictEnd() {
+void CoverageExporterJson::emitComma() {
+ if (State.top() == JsonState::NonEmptyElement) {
+ OS << ",";
+ } else if (State.top() == JsonState::EmptyElement) {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
- OS << "}";
- }
-
- /// \brief Emit a starting array character.
- void emitArrayStart() {
- emitComma();
- State.push(JsonState::EmptyElement);
- OS << "[";
- }
-
- /// \brief Emit an array element.
- template <typename V> void emitArrayElement(const V &Value) {
- emitComma();
- emitSerialized(Value);
+ State.push(JsonState::NonEmptyElement);
}
+}
- /// \brief emit a closing array character.
- void emitArrayEnd() {
- State.pop();
- assert((State.size() >= 1) && "Closed too many JSON elements");
- OS << "]";
- }
+void CoverageExporterJson::emitDictStart() {
+ emitComma();
+ State.push(JsonState::EmptyElement);
+ OS << "{";
+}
- /// \brief Render the CoverageMapping object.
- void renderRoot() {
- // Start Root of JSON object.
- emitDictStart();
+void CoverageExporterJson::emitDictKey(const std::string &Key) {
+ emitComma();
+ emitSerialized(Key);
+ OS << ":";
+ State.pop();
+ assert((State.size() >= 1) && "Closed too many JSON elements");
- emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
- emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
- emitDictKey("data");
+ // We do not want to emit a comma after this key.
+ State.push(JsonState::EmptyElement);
+}
- // Start List of Exports.
- emitArrayStart();
+void CoverageExporterJson::emitDictEnd() {
+ State.pop();
+ assert((State.size() >= 1) && "Closed too many JSON elements");
+ OS << "}";
+}
- // Start Export.
- emitDictStart();
+void CoverageExporterJson::emitArrayStart() {
+ emitComma();
+ State.push(JsonState::EmptyElement);
+ OS << "[";
+}
- emitDictKey("files");
+void CoverageExporterJson::emitArrayEnd() {
+ State.pop();
+ assert((State.size() >= 1) && "Closed too many JSON elements");
+ OS << "]";
+}
- FileCoverageSummary Totals = FileCoverageSummary("Totals");
- std::vector<std::string> SourceFiles;
- for (StringRef SF : Coverage.getUniqueSourceFiles())
+void CoverageExporterJson::renderRoot(
+ const CoverageFilters &IgnoreFilenameFilters) {
+ std::vector<std::string> SourceFiles;
+ for (StringRef SF : Coverage.getUniqueSourceFiles()) {
+ if (!IgnoreFilenameFilters.matchesFilename(SF))
SourceFiles.emplace_back(SF);
- auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
- SourceFiles, Options);
- renderFiles(SourceFiles, FileReports);
-
- // Skip functions-level information for summary-only export mode.
- if (!Options.ExportSummaryOnly) {
- emitDictKey("functions");
- renderFunctions(Coverage.getCoveredFunctions());
- }
-
- emitDictKey("totals");
- renderSummary(Totals);
-
- // End Export.
- emitDictEnd();
-
- // End List of Exports.
- emitArrayEnd();
-
- // End Root of JSON Object.
- emitDictEnd();
-
- assert((State.top() == JsonState::None) &&
- "All Elements In JSON were Closed");
}
+ renderRoot(SourceFiles);
+}
- /// \brief Render an array of all the given functions.
- void
- renderFunctions(const iterator_range<FunctionRecordIterator> &Functions) {
- // Start List of Functions.
- emitArrayStart();
-
- for (const auto &Function : Functions) {
- // Start Function.
- emitDictStart();
-
- emitDictElement("name", Function.Name);
- emitDictElement("count", Function.ExecutionCount);
- emitDictKey("regions");
-
- renderRegions(Function.CountedRegions);
+void CoverageExporterJson::renderRoot(
+ const std::vector<std::string> &SourceFiles) {
+ // Start Root of JSON object.
+ emitDictStart();
- emitDictKey("filenames");
+ emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
+ emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
+ emitDictKey("data");
- // Start Filenames for Function.
- emitArrayStart();
+ // Start List of Exports.
+ emitArrayStart();
- for (const auto &FileName : Function.Filenames)
- emitArrayElement(FileName);
+ // Start Export.
+ emitDictStart();
- // End Filenames for Function.
- emitArrayEnd();
+ emitDictKey("files");
- // End Function.
- emitDictEnd();
- }
+ FileCoverageSummary Totals = FileCoverageSummary("Totals");
+ auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
+ SourceFiles, Options);
+ renderFiles(SourceFiles, FileReports);
- // End List of Functions.
- emitArrayEnd();
+ // Skip functions-level information for summary-only export mode.
+ if (!Options.ExportSummaryOnly) {
+ emitDictKey("functions");
+ renderFunctions(Coverage.getCoveredFunctions());
}
- /// \brief Render an array of all the source files, also pass back a Summary.
- void renderFiles(ArrayRef<std::string> SourceFiles,
- ArrayRef<FileCoverageSummary> FileReports) {
- // Start List of Files.
- emitArrayStart();
-
- for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) {
- // Render the file.
- auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]);
- renderFile(FileCoverage, FileReports[I]);
- }
+ emitDictKey("totals");
+ renderSummary(Totals);
- // End List of Files.
- emitArrayEnd();
- }
+ // End Export.
+ emitDictEnd();
- /// \brief Render a single file.
- void renderFile(const CoverageData &FileCoverage,
- const FileCoverageSummary &FileReport) {
- // Start File.
- emitDictStart();
+ // End List of Exports.
+ emitArrayEnd();
- emitDictElement("filename", FileCoverage.getFilename());
+ // End Root of JSON Object.
+ emitDictEnd();
- // Skip segments and expansions for summary-only export mode.
- if (!Options.ExportSummaryOnly) {
- emitDictKey("segments");
+ assert((State.top() == JsonState::None) &&
+ "All Elements In JSON were Closed");
+}
- // Start List of Segments.
- emitArrayStart();
+void CoverageExporterJson::renderFunctions(
+ const iterator_range<coverage::FunctionRecordIterator> &Functions) {
+ // Start List of Functions.
+ emitArrayStart();
- for (const auto &Segment : FileCoverage)
- renderSegment(Segment);
+ for (const auto &Function : Functions) {
+ // Start Function.
+ emitDictStart();
- // End List of Segments.
- emitArrayEnd();
+ emitDictElement("name", Function.Name);
+ emitDictElement("count", Function.ExecutionCount);
+ emitDictKey("regions");
- emitDictKey("expansions");
+ renderRegions(Function.CountedRegions);
- // Start List of Expansions.
- emitArrayStart();
+ emitDictKey("filenames");
- for (const auto &Expansion : FileCoverage.getExpansions())
- renderExpansion(Expansion);
+ // Start Filenames for Function.
+ emitArrayStart();
- // End List of Expansions.
- emitArrayEnd();
- }
+ for (const auto &FileName : Function.Filenames)
+ emitArrayElement(FileName);
- emitDictKey("summary");
- renderSummary(FileReport);
+ // End Filenames for Function.
+ emitArrayEnd();
- // End File.
+ // End Function.
emitDictEnd();
}
- /// \brief Render a CoverageSegment.
- void renderSegment(const CoverageSegment &Segment) {
- // Start Segment.
- emitArrayStart();
+ // End List of Functions.
+ emitArrayEnd();
+}
- emitArrayElement(Segment.Line);
- emitArrayElement(Segment.Col);
- emitArrayElement(Segment.Count);
- emitArrayElement(Segment.HasCount);
- emitArrayElement(Segment.IsRegionEntry);
+void CoverageExporterJson::renderFiles(
+ ArrayRef<std::string> SourceFiles,
+ ArrayRef<FileCoverageSummary> FileReports) {
+ // Start List of Files.
+ emitArrayStart();
- // End Segment.
- emitArrayEnd();
+ for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) {
+ renderFile(SourceFiles[I], FileReports[I]);
}
- /// \brief Render an ExpansionRecord.
- void renderExpansion(const ExpansionRecord &Expansion) {
- // Start Expansion.
- emitDictStart();
-
- // Mark the beginning and end of this expansion in the source file.
- emitDictKey("source_region");
- renderRegion(Expansion.Region);
+ // End List of Files.
+ emitArrayEnd();
+}
- // Enumerate the coverage information for the expansion.
- emitDictKey("target_regions");
- renderRegions(Expansion.Function.CountedRegions);
+void CoverageExporterJson::renderFile(const std::string &Filename,
+ const FileCoverageSummary &FileReport) {
+ // Start File.
+ emitDictStart();
- emitDictKey("filenames");
- // Start List of Filenames to map the fileIDs.
- emitArrayStart();
- for (const auto &Filename : Expansion.Function.Filenames)
- emitArrayElement(Filename);
- // End List of Filenames.
- emitArrayEnd();
+ emitDictElement("filename", Filename);
- // End Expansion.
- emitDictEnd();
+ if (!Options.ExportSummaryOnly) {
+ // Calculate and render detailed coverage information for given file.
+ auto FileCoverage = Coverage.getCoverageForFile(Filename);
+ renderFileCoverage(FileCoverage, FileReport);
}
- /// \brief Render a list of CountedRegions.
- void renderRegions(ArrayRef<CountedRegion> Regions) {
- // Start List of Regions.
- emitArrayStart();
+ emitDictKey("summary");
+ renderSummary(FileReport);
- for (const auto &Region : Regions)
- renderRegion(Region);
+ // End File.
+ emitDictEnd();
+}
- // End List of Regions.
- emitArrayEnd();
- }
- /// \brief Render a single CountedRegion.
- void renderRegion(const CountedRegion &Region) {
- // Start CountedRegion.
- emitArrayStart();
+void CoverageExporterJson::renderFileCoverage(
+ const coverage::CoverageData &FileCoverage,
+ const FileCoverageSummary &FileReport) {
+ emitDictKey("segments");
- emitArrayElement(Region.LineStart);
- emitArrayElement(Region.ColumnStart);
- emitArrayElement(Region.LineEnd);
- emitArrayElement(Region.ColumnEnd);
- emitArrayElement(Region.ExecutionCount);
- emitArrayElement(Region.FileID);
- emitArrayElement(Region.ExpandedFileID);
- emitArrayElement(Region.Kind);
+ // Start List of Segments.
+ emitArrayStart();
- // End CountedRegion.
- emitArrayEnd();
- }
+ for (const auto &Segment : FileCoverage)
+ renderSegment(Segment);
- /// \brief Render a FileCoverageSummary.
- void renderSummary(const FileCoverageSummary &Summary) {
- // Start Summary for the file.
- emitDictStart();
+ // End List of Segments.
+ emitArrayEnd();
- emitDictKey("lines");
+ emitDictKey("expansions");
- // Start Line Coverage Summary.
- emitDictStart();
- emitDictElement("count", Summary.LineCoverage.getNumLines());
- emitDictElement("covered", Summary.LineCoverage.getCovered());
- emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
- // End Line Coverage Summary.
- emitDictEnd();
+ // Start List of Expansions.
+ emitArrayStart();
- emitDictKey("functions");
+ for (const auto &Expansion : FileCoverage.getExpansions())
+ renderExpansion(Expansion);
- // Start Function Coverage Summary.
- emitDictStart();
- emitDictElement("count", Summary.FunctionCoverage.getNumFunctions());
- emitDictElement("covered", Summary.FunctionCoverage.getExecuted());
- emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
- // End Function Coverage Summary.
- emitDictEnd();
+ // End List of Expansions.
+ emitArrayEnd();
+}
- emitDictKey("instantiations");
+void CoverageExporterJson::renderSegment(
+ const coverage::CoverageSegment &Segment) {
+ // Start Segment.
+ emitArrayStart();
- // Start Instantiation Coverage Summary.
- emitDictStart();
- emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions());
- emitDictElement("covered", Summary.InstantiationCoverage.getExecuted());
- emitDictElement("percent",
- Summary.InstantiationCoverage.getPercentCovered());
- // End Function Coverage Summary.
- emitDictEnd();
+ emitArrayElement(Segment.Line);
+ emitArrayElement(Segment.Col);
+ emitArrayElement(Segment.Count);
+ emitArrayElement(Segment.HasCount);
+ emitArrayElement(Segment.IsRegionEntry);
- emitDictKey("regions");
+ // End Segment.
+ emitArrayEnd();
+}
- // Start Region Coverage Summary.
- emitDictStart();
- emitDictElement("count", Summary.RegionCoverage.getNumRegions());
- emitDictElement("covered", Summary.RegionCoverage.getCovered());
- emitDictElement("notcovered",
- Summary.RegionCoverage.getNumRegions() -
- Summary.RegionCoverage.getCovered());
- emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
- // End Region Coverage Summary.
- emitDictEnd();
+void CoverageExporterJson::renderExpansion(
+ const coverage::ExpansionRecord &Expansion) {
+ // Start Expansion.
+ emitDictStart();
+
+ // Mark the beginning and end of this expansion in the source file.
+ emitDictKey("source_region");
+ renderRegion(Expansion.Region);
+
+ // Enumerate the coverage information for the expansion.
+ emitDictKey("target_regions");
+ renderRegions(Expansion.Function.CountedRegions);
+
+ emitDictKey("filenames");
+ // Start List of Filenames to map the fileIDs.
+ emitArrayStart();
+ for (const auto &Filename : Expansion.Function.Filenames)
+ emitArrayElement(Filename);
+ // End List of Filenames.
+ emitArrayEnd();
+
+ // End Expansion.
+ emitDictEnd();
+}
- // End Summary for the file.
- emitDictEnd();
- }
+void CoverageExporterJson::renderRegions(
+ ArrayRef<coverage::CountedRegion> Regions) {
+ // Start List of Regions.
+ emitArrayStart();
-public:
- CoverageExporterJson(const CoverageMapping &CoverageMapping,
- const CoverageViewOptions &Options, raw_ostream &OS)
- : Options(Options), OS(OS), Coverage(CoverageMapping) {
- State.push(JsonState::None);
- }
+ for (const auto &Region : Regions)
+ renderRegion(Region);
- /// \brief Print the CoverageMapping.
- void print() { renderRoot(); }
-};
+ // End List of Regions.
+ emitArrayEnd();
+}
-/// \brief Export the given CoverageMapping to a JSON Format.
-void exportCoverageDataToJson(const CoverageMapping &CoverageMapping,
- const CoverageViewOptions &Options,
- raw_ostream &OS) {
- auto Exporter = CoverageExporterJson(CoverageMapping, Options, OS);
+void CoverageExporterJson::renderRegion(const coverage::CountedRegion &Region) {
+ // Start CountedRegion.
+ emitArrayStart();
+
+ emitArrayElement(Region.LineStart);
+ emitArrayElement(Region.ColumnStart);
+ emitArrayElement(Region.LineEnd);
+ emitArrayElement(Region.ColumnEnd);
+ emitArrayElement(Region.ExecutionCount);
+ emitArrayElement(Region.FileID);
+ emitArrayElement(Region.ExpandedFileID);
+ emitArrayElement(Region.Kind);
+
+ // End CountedRegion.
+ emitArrayEnd();
+}
- Exporter.print();
+void CoverageExporterJson::renderSummary(const FileCoverageSummary &Summary) {
+ // Start Summary for the file.
+ emitDictStart();
+
+ emitDictKey("lines");
+
+ // Start Line Coverage Summary.
+ emitDictStart();
+ emitDictElement("count", Summary.LineCoverage.getNumLines());
+ emitDictElement("covered", Summary.LineCoverage.getCovered());
+ emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
+ // End Line Coverage Summary.
+ emitDictEnd();
+
+ emitDictKey("functions");
+
+ // Start Function Coverage Summary.
+ emitDictStart();
+ emitDictElement("count", Summary.FunctionCoverage.getNumFunctions());
+ emitDictElement("covered", Summary.FunctionCoverage.getExecuted());
+ emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
+ // End Function Coverage Summary.
+ emitDictEnd();
+
+ emitDictKey("instantiations");
+
+ // Start Instantiation Coverage Summary.
+ emitDictStart();
+ emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions());
+ emitDictElement("covered", Summary.InstantiationCoverage.getExecuted());
+ emitDictElement("percent", Summary.InstantiationCoverage.getPercentCovered());
+ // End Function Coverage Summary.
+ emitDictEnd();
+
+ emitDictKey("regions");
+
+ // Start Region Coverage Summary.
+ emitDictStart();
+ emitDictElement("count", Summary.RegionCoverage.getNumRegions());
+ emitDictElement("covered", Summary.RegionCoverage.getCovered());
+ emitDictElement("notcovered", Summary.RegionCoverage.getNumRegions() -
+ Summary.RegionCoverage.getCovered());
+ emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
+ // End Region Coverage Summary.
+ emitDictEnd();
+
+ // End Summary for the file.
+ emitDictEnd();
}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageExporterJson.h b/contrib/llvm/tools/llvm-cov/CoverageExporterJson.h
new file mode 100644
index 000000000000..f88dffa0ebea
--- /dev/null
+++ b/contrib/llvm/tools/llvm-cov/CoverageExporterJson.h
@@ -0,0 +1,112 @@
+//===- CoverageExporterJson.h - Code coverage JSON exporter ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements a code coverage exporter for JSON format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_COV_COVERAGEEXPORTERJSON_H
+#define LLVM_COV_COVERAGEEXPORTERJSON_H
+
+#include "CoverageExporter.h"
+#include <stack>
+
+namespace llvm {
+
+class CoverageExporterJson : public CoverageExporter {
+ /// States that the JSON rendering machine can be in.
+ enum JsonState { None, NonEmptyElement, EmptyElement };
+
+ /// Tracks state of the JSON output.
+ std::stack<JsonState> State;
+
+ /// Emit a serialized scalar.
+ void emitSerialized(const int64_t Value);
+
+ /// Emit a serialized string.
+ void emitSerialized(const std::string &Value);
+
+ /// Emit a comma if there is a previous element to delimit.
+ void emitComma();
+
+ /// Emit a starting dictionary/object character.
+ void emitDictStart();
+
+ /// Emit a dictionary/object key but no value.
+ void emitDictKey(const std::string &Key);
+
+ /// Emit a dictionary/object key/value pair.
+ template <typename V>
+ void emitDictElement(const std::string &Key, const V &Value) {
+ emitComma();
+ emitSerialized(Key);
+ OS << ":";
+ emitSerialized(Value);
+ }
+
+ /// Emit a closing dictionary/object character.
+ void emitDictEnd();
+
+ /// Emit a starting array character.
+ void emitArrayStart();
+
+ /// Emit an array element.
+ template <typename V> void emitArrayElement(const V &Value) {
+ emitComma();
+ emitSerialized(Value);
+ }
+
+ /// emit a closing array character.
+ void emitArrayEnd();
+
+ /// Render an array of all the given functions.
+ void renderFunctions(
+ const iterator_range<coverage::FunctionRecordIterator> &Functions);
+
+ /// Render an array of all the source files, also pass back a Summary.
+ void renderFiles(ArrayRef<std::string> SourceFiles,
+ ArrayRef<FileCoverageSummary> FileReports);
+
+ /// Render a single file.
+ void renderFile(const std::string &Filename,
+ const FileCoverageSummary &FileReport);
+
+ /// Render summary for a single file.
+ void renderFileCoverage(const coverage::CoverageData &FileCoverage,
+ const FileCoverageSummary &FileReport);
+
+ /// Render a CoverageSegment.
+ void renderSegment(const coverage::CoverageSegment &Segment);
+
+ /// Render an ExpansionRecord.
+ void renderExpansion(const coverage::ExpansionRecord &Expansion);
+
+ /// Render a list of CountedRegions.
+ void renderRegions(ArrayRef<coverage::CountedRegion> Regions);
+
+ /// Render a single CountedRegion.
+ void renderRegion(const coverage::CountedRegion &Region);
+
+ /// Render a FileCoverageSummary.
+ void renderSummary(const FileCoverageSummary &Summary);
+
+public:
+ CoverageExporterJson(const coverage::CoverageMapping &CoverageMapping,
+ const CoverageViewOptions &Options, raw_ostream &OS);
+
+ /// Render the CoverageMapping object.
+ void renderRoot(const CoverageFilters &IgnoreFilenameFilters) override;
+
+ /// Render the CoverageMapping object for specified source files.
+ void renderRoot(const std::vector<std::string> &SourceFiles) override;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_COV_COVERAGEEXPORTERJSON_H
diff --git a/contrib/llvm/tools/llvm-cov/CoverageFilters.cpp b/contrib/llvm/tools/llvm-cov/CoverageFilters.cpp
index 441179601dcc..4dd0f552c7e0 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageFilters.cpp
+++ b/contrib/llvm/tools/llvm-cov/CoverageFilters.cpp
@@ -30,6 +30,10 @@ bool NameRegexCoverageFilter::matches(
return llvm::Regex(Regex).match(Function.Name);
}
+bool NameRegexCoverageFilter::matchesFilename(StringRef Filename) const {
+ return llvm::Regex(Regex).match(Filename);
+}
+
bool NameWhitelistCoverageFilter::matches(
const coverage::CoverageMapping &,
const coverage::FunctionRecord &Function) const {
@@ -63,6 +67,14 @@ bool CoverageFilters::matches(const coverage::CoverageMapping &CM,
return false;
}
+bool CoverageFilters::matchesFilename(StringRef Filename) const {
+ for (const auto &Filter : Filters) {
+ if (Filter->matchesFilename(Filename))
+ return true;
+ }
+ return false;
+}
+
bool CoverageFiltersMatchAll::matches(
const coverage::CoverageMapping &CM,
const coverage::FunctionRecord &Function) const {
diff --git a/contrib/llvm/tools/llvm-cov/CoverageFilters.h b/contrib/llvm/tools/llvm-cov/CoverageFilters.h
index aeaf61de1730..6424ca5a8081 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageFilters.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageFilters.h
@@ -22,19 +22,24 @@
namespace llvm {
-/// \brief Matches specific functions that pass the requirement of this filter.
+/// Matches specific functions that pass the requirement of this filter.
class CoverageFilter {
public:
virtual ~CoverageFilter() {}
- /// \brief Return true if the function passes the requirements of this filter.
+ /// Return true if the function passes the requirements of this filter.
virtual bool matches(const coverage::CoverageMapping &CM,
const coverage::FunctionRecord &Function) const {
return true;
}
+
+ /// Return true if the filename passes the requirements of this filter.
+ virtual bool matchesFilename(StringRef Filename) const {
+ return true;
+ }
};
-/// \brief Matches functions that contain a specific string in their name.
+/// Matches functions that contain a specific string in their name.
class NameCoverageFilter : public CoverageFilter {
StringRef Name;
@@ -45,7 +50,7 @@ public:
const coverage::FunctionRecord &Function) const override;
};
-/// \brief Matches functions whose name matches a certain regular expression.
+/// Matches functions whose name matches a certain regular expression.
class NameRegexCoverageFilter : public CoverageFilter {
StringRef Regex;
@@ -54,9 +59,11 @@ public:
bool matches(const coverage::CoverageMapping &CM,
const coverage::FunctionRecord &Function) const override;
+
+ bool matchesFilename(StringRef Filename) const override;
};
-/// \brief Matches functions whose name appears in a SpecialCaseList in the
+/// Matches functions whose name appears in a SpecialCaseList in the
/// whitelist_fun section.
class NameWhitelistCoverageFilter : public CoverageFilter {
const SpecialCaseList &Whitelist;
@@ -69,7 +76,7 @@ public:
const coverage::FunctionRecord &Function) const override;
};
-/// \brief Matches numbers that pass a certain threshold.
+/// Matches numbers that pass a certain threshold.
template <typename T> class StatisticThresholdFilter {
public:
enum Operation { LessThan, GreaterThan };
@@ -81,7 +88,7 @@ protected:
StatisticThresholdFilter(Operation Op, T Threshold)
: Op(Op), Threshold(Threshold) {}
- /// \brief Return true if the given number is less than
+ /// Return true if the given number is less than
/// or greater than the certain threshold.
bool PassesThreshold(T Value) const {
switch (Op) {
@@ -94,7 +101,7 @@ protected:
}
};
-/// \brief Matches functions whose region coverage percentage
+/// Matches functions whose region coverage percentage
/// is above/below a certain percentage.
class RegionCoverageFilter : public CoverageFilter,
public StatisticThresholdFilter<double> {
@@ -106,7 +113,7 @@ public:
const coverage::FunctionRecord &Function) const override;
};
-/// \brief Matches functions whose line coverage percentage
+/// Matches functions whose line coverage percentage
/// is above/below a certain percentage.
class LineCoverageFilter : public CoverageFilter,
public StatisticThresholdFilter<double> {
@@ -118,7 +125,7 @@ public:
const coverage::FunctionRecord &Function) const override;
};
-/// \brief A collection of filters.
+/// A collection of filters.
/// Matches functions that match any filters contained
/// in an instance of this class.
class CoverageFilters : public CoverageFilter {
@@ -126,16 +133,18 @@ protected:
std::vector<std::unique_ptr<CoverageFilter>> Filters;
public:
- /// \brief Append a filter to this collection.
+ /// Append a filter to this collection.
void push_back(std::unique_ptr<CoverageFilter> Filter);
bool empty() const { return Filters.empty(); }
bool matches(const coverage::CoverageMapping &CM,
const coverage::FunctionRecord &Function) const override;
+
+ bool matchesFilename(StringRef Filename) const override;
};
-/// \brief A collection of filters.
+/// A collection of filters.
/// Matches functions that match all of the filters contained
/// in an instance of this class.
class CoverageFiltersMatchAll : public CoverageFilters {
diff --git a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
index 9c553a7f64c7..607a3ceb30cb 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -16,13 +16,15 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/Threading.h"
#include <numeric>
using namespace llvm;
namespace {
-/// \brief Helper struct which prints trimmed and aligned columns.
+/// Helper struct which prints trimmed and aligned columns.
struct Column {
enum TrimKind { NoTrim, WidthTrim, RightTrim };
@@ -89,7 +91,7 @@ size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10,
16, 16, 10, 12, 18, 10};
size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
-/// \brief Adjust column widths to fit long file paths and function names.
+/// Adjust column widths to fit long file paths and function names.
void adjustColumnWidths(ArrayRef<StringRef> Files,
ArrayRef<StringRef> Functions) {
for (StringRef Filename : Files)
@@ -99,7 +101,7 @@ void adjustColumnWidths(ArrayRef<StringRef> Files,
std::max(FunctionReportColumns[0], Funcname.size());
}
-/// \brief Prints a horizontal divider long enough to cover the given column
+/// Prints a horizontal divider long enough to cover the given column
/// widths.
void renderDivider(ArrayRef<size_t> ColumnWidths, raw_ostream &OS) {
size_t Length = std::accumulate(ColumnWidths.begin(), ColumnWidths.end(), 0);
@@ -107,7 +109,7 @@ void renderDivider(ArrayRef<size_t> ColumnWidths, raw_ostream &OS) {
OS << '-';
}
-/// \brief Return the color which correponds to the coverage percentage of a
+/// Return the color which correponds to the coverage percentage of a
/// certain metric.
template <typename T>
raw_ostream::Colors determineCoveragePercentageColor(const T &Info) {
@@ -117,7 +119,7 @@ raw_ostream::Colors determineCoveragePercentageColor(const T &Info) {
: raw_ostream::RED;
}
-/// \brief Get the number of redundant path components in each path in \p Paths.
+/// Get the number of redundant path components in each path in \p Paths.
unsigned getNumRedundantPathComponents(ArrayRef<std::string> Paths) {
// To start, set the number of redundant path components to the maximum
// possible value.
@@ -146,7 +148,7 @@ unsigned getNumRedundantPathComponents(ArrayRef<std::string> Paths) {
return NumRedundant;
}
-/// \brief Determine the length of the longest redundant prefix of the paths in
+/// Determine the length of the longest redundant prefix of the paths in
/// \p Paths.
unsigned getRedundantPrefixLen(ArrayRef<std::string> Paths) {
// If there's at most one path, no path components are redundant.
@@ -319,50 +321,72 @@ void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
}
}
+void CoverageReport::prepareSingleFileReport(const StringRef Filename,
+ const coverage::CoverageMapping *Coverage,
+ const CoverageViewOptions &Options, const unsigned LCP,
+ FileCoverageSummary *FileReport, const CoverageFilter *Filters) {
+ for (const auto &Group : Coverage->getInstantiationGroups(Filename)) {
+ std::vector<FunctionCoverageSummary> InstantiationSummaries;
+ for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
+ if (!Filters->matches(*Coverage, *F))
+ continue;
+ auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F);
+ FileReport->addInstantiation(InstantiationSummary);
+ InstantiationSummaries.push_back(InstantiationSummary);
+ }
+ if (InstantiationSummaries.empty())
+ continue;
+
+ auto GroupSummary =
+ FunctionCoverageSummary::get(Group, InstantiationSummaries);
+
+ if (Options.Debug)
+ outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
+ << "size = " << Group.size() << "\n";
+
+ FileReport->addFunction(GroupSummary);
+ }
+}
+
std::vector<FileCoverageSummary> CoverageReport::prepareFileReports(
const coverage::CoverageMapping &Coverage, FileCoverageSummary &Totals,
ArrayRef<std::string> Files, const CoverageViewOptions &Options,
const CoverageFilter &Filters) {
- std::vector<FileCoverageSummary> FileReports;
unsigned LCP = getRedundantPrefixLen(Files);
+ auto NumThreads = Options.NumThreads;
- for (StringRef Filename : Files) {
- FileCoverageSummary Summary(Filename.drop_front(LCP));
-
- for (const auto &Group : Coverage.getInstantiationGroups(Filename)) {
- std::vector<FunctionCoverageSummary> InstantiationSummaries;
- for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
- if (!Filters.matches(Coverage, *F))
- continue;
- auto InstantiationSummary = FunctionCoverageSummary::get(Coverage, *F);
- Summary.addInstantiation(InstantiationSummary);
- Totals.addInstantiation(InstantiationSummary);
- InstantiationSummaries.push_back(InstantiationSummary);
- }
- if (InstantiationSummaries.empty())
- continue;
-
- auto GroupSummary =
- FunctionCoverageSummary::get(Group, InstantiationSummaries);
+ // If NumThreads is not specified, auto-detect a good default.
+ if (NumThreads == 0)
+ NumThreads =
+ std::max(1U, std::min(llvm::heavyweight_hardware_concurrency(),
+ unsigned(Files.size())));
- if (Options.Debug)
- outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
- << "size = " << Group.size() << "\n";
+ ThreadPool Pool(NumThreads);
- Summary.addFunction(GroupSummary);
- Totals.addFunction(GroupSummary);
- }
+ std::vector<FileCoverageSummary> FileReports;
+ FileReports.reserve(Files.size());
- FileReports.push_back(Summary);
+ for (StringRef Filename : Files) {
+ FileReports.emplace_back(Filename.drop_front(LCP));
+ Pool.async(&CoverageReport::prepareSingleFileReport, Filename,
+ &Coverage, Options, LCP, &FileReports.back(), &Filters);
}
+ Pool.wait();
+
+ for (const auto &FileReport : FileReports)
+ Totals += FileReport;
return FileReports;
}
-void CoverageReport::renderFileReports(raw_ostream &OS) const {
+void CoverageReport::renderFileReports(
+ raw_ostream &OS, const CoverageFilters &IgnoreFilenameFilters) const {
std::vector<std::string> UniqueSourceFiles;
- for (StringRef SF : Coverage.getUniqueSourceFiles())
- UniqueSourceFiles.emplace_back(SF.str());
+ for (StringRef SF : Coverage.getUniqueSourceFiles()) {
+ // Apply ignore source files filters.
+ if (!IgnoreFilenameFilters.matchesFilename(SF))
+ UniqueSourceFiles.emplace_back(SF.str());
+ }
renderFileReports(OS, UniqueSourceFiles);
}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageReport.h b/contrib/llvm/tools/llvm-cov/CoverageReport.h
index 1c9e68e832f3..4a6527e9fe5d 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageReport.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageReport.h
@@ -1,4 +1,4 @@
-//===- CoverageReport.h - Code coverage report ---------------------------===//
+//===- CoverageReport.h - Code coverage report ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,7 +20,7 @@
namespace llvm {
-/// \brief Displays the code coverage report.
+/// Displays the code coverage report.
class CoverageReport {
const CoverageViewOptions &Options;
const coverage::CoverageMapping &Coverage;
@@ -44,8 +44,17 @@ public:
const CoverageViewOptions &Options,
const CoverageFilter &Filters = CoverageFiltersMatchAll());
+ static void
+ prepareSingleFileReport(const StringRef Filename,
+ const coverage::CoverageMapping *Coverage,
+ const CoverageViewOptions &Options,
+ const unsigned LCP,
+ FileCoverageSummary *FileReport,
+ const CoverageFilter *Filters);
+
/// Render file reports for every unique file in the coverage mapping.
- void renderFileReports(raw_ostream &OS) const;
+ void renderFileReports(raw_ostream &OS,
+ const CoverageFilters &IgnoreFilenameFilters) const;
/// Render file reports for the files specified in \p Files.
void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files) const;
diff --git a/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 8eae0b7fec97..0845e2ce2e77 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -20,12 +20,12 @@
namespace llvm {
-/// \brief Provides information about region coverage for a function/file.
+/// Provides information about region coverage for a function/file.
class RegionCoverageInfo {
- /// \brief The number of regions that were executed at least once.
+ /// The number of regions that were executed at least once.
size_t Covered;
- /// \brief The total number of regions in a function/file.
+ /// The total number of regions in a function/file.
size_t NumRegions;
public:
@@ -61,12 +61,12 @@ public:
}
};
-/// \brief Provides information about line coverage for a function/file.
+/// Provides information about line coverage for a function/file.
class LineCoverageInfo {
- /// \brief The number of lines that were executed at least once.
+ /// The number of lines that were executed at least once.
size_t Covered;
- /// \brief The total number of lines in a function/file.
+ /// The total number of lines in a function/file.
size_t NumLines;
public:
@@ -102,12 +102,12 @@ public:
}
};
-/// \brief Provides information about function coverage for a file.
+/// Provides information about function coverage for a file.
class FunctionCoverageInfo {
- /// \brief The number of functions that were executed.
+ /// The number of functions that were executed.
size_t Executed;
- /// \brief The total number of functions in this file.
+ /// The total number of functions in this file.
size_t NumFunctions;
public:
@@ -116,6 +116,12 @@ public:
FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
: Executed(Executed), NumFunctions(NumFunctions) {}
+ FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) {
+ Executed += RHS.Executed;
+ NumFunctions += RHS.NumFunctions;
+ return *this;
+ }
+
void addFunction(bool Covered) {
if (Covered)
++Executed;
@@ -136,7 +142,7 @@ public:
}
};
-/// \brief A summary of function's code coverage.
+/// A summary of function's code coverage.
struct FunctionCoverageSummary {
std::string Name;
uint64_t ExecutionCount;
@@ -152,7 +158,7 @@ struct FunctionCoverageSummary {
: Name(Name), ExecutionCount(ExecutionCount),
RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) {}
- /// \brief Compute the code coverage summary for the given function coverage
+ /// Compute the code coverage summary for the given function coverage
/// mapping record.
static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
const coverage::FunctionRecord &Function);
@@ -164,7 +170,7 @@ struct FunctionCoverageSummary {
ArrayRef<FunctionCoverageSummary> Summaries);
};
-/// \brief A summary of file's code coverage.
+/// A summary of file's code coverage.
struct FileCoverageSummary {
StringRef Name;
RegionCoverageInfo RegionCoverage;
@@ -176,6 +182,14 @@ struct FileCoverageSummary {
: Name(Name), RegionCoverage(), LineCoverage(), FunctionCoverage(),
InstantiationCoverage() {}
+ FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
+ RegionCoverage += RHS.RegionCoverage;
+ LineCoverage += RHS.LineCoverage;
+ FunctionCoverage += RHS.FunctionCoverage;
+ InstantiationCoverage += RHS.InstantiationCoverage;
+ return *this;
+ }
+
void addFunction(const FunctionCoverageSummary &Function) {
RegionCoverage += Function.RegionCoverage;
LineCoverage += Function.LineCoverage;
@@ -187,11 +201,11 @@ struct FileCoverageSummary {
}
};
-/// \brief A cache for demangled symbols.
+/// A cache for demangled symbols.
struct DemangleCache {
StringMap<std::string> DemangledNames;
- /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym.
+ /// Demangle \p Sym if possible. Otherwise, just return \p Sym.
StringRef demangle(StringRef Sym) const {
const auto DemangledName = DemangledNames.find(Sym);
if (DemangledName == DemangledNames.end())
diff --git a/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h b/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h
index 17614c4e9ba2..20085a957bb5 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -10,12 +10,13 @@
#ifndef LLVM_COV_COVERAGEVIEWOPTIONS_H
#define LLVM_COV_COVERAGEVIEWOPTIONS_H
+#include "llvm/Config/llvm-config.h"
#include "RenderingSupport.h"
#include <vector>
namespace llvm {
-/// \brief The options for displaying the code coverage information.
+/// The options for displaying the code coverage information.
struct CoverageViewOptions {
enum class OutputFormat {
Text,
@@ -39,26 +40,27 @@ struct CoverageViewOptions {
uint32_t TabSize;
std::string ProjectTitle;
std::string CreatedTimeStr;
+ unsigned NumThreads;
- /// \brief Change the output's stream color if the colors are enabled.
+ /// Change the output's stream color if the colors are enabled.
ColoredRawOstream colored_ostream(raw_ostream &OS,
raw_ostream::Colors Color) const {
return llvm::colored_ostream(OS, Color, Colors);
}
- /// \brief Check if an output directory has been specified.
+ /// Check if an output directory has been specified.
bool hasOutputDirectory() const { return !ShowOutputDirectory.empty(); }
- /// \brief Check if a demangler has been specified.
+ /// Check if a demangler has been specified.
bool hasDemangler() const { return !DemanglerOpts.empty(); }
- /// \brief Check if a project title has been specified.
+ /// Check if a project title has been specified.
bool hasProjectTitle() const { return !ProjectTitle.empty(); }
- /// \brief Check if the created time of the profile data file is available.
+ /// Check if the created time of the profile data file is available.
bool hasCreatedTime() const { return !CreatedTimeStr.empty(); }
- /// \brief Get the LLVM version string.
+ /// Get the LLVM version string.
std::string getLLVMVersionString() const {
std::string VersionString = "Generated by llvm-cov -- llvm version ";
VersionString += LLVM_VERSION_STRING;
diff --git a/contrib/llvm/tools/llvm-cov/RenderingSupport.h b/contrib/llvm/tools/llvm-cov/RenderingSupport.h
index aa70fbc23e3c..2cfe24919142 100644
--- a/contrib/llvm/tools/llvm-cov/RenderingSupport.h
+++ b/contrib/llvm/tools/llvm-cov/RenderingSupport.h
@@ -15,7 +15,7 @@
namespace llvm {
-/// \brief A helper class that resets the output stream's color if needed
+/// A helper class that resets the output stream's color if needed
/// when destroyed.
class ColoredRawOstream {
ColoredRawOstream(const ColoredRawOstream &OS) = delete;
@@ -45,7 +45,7 @@ inline raw_ostream &operator<<(const ColoredRawOstream &OS, T &&Value) {
return OS.OS << std::forward<T>(Value);
}
-/// \brief Change the color of the output stream if the `IsColorUsed` flag
+/// Change the color of the output stream if the `IsColorUsed` flag
/// is true. Returns an object that resets the color when destroyed.
inline ColoredRawOstream colored_ostream(raw_ostream &OS,
raw_ostream::Colors Color,
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp b/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp
index 8c39dab580de..a5a8fa9a4814 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -65,7 +65,8 @@ CoveragePrinter::createOutputStream(StringRef Path, StringRef Extension,
return errorCodeToError(E);
std::error_code E;
- raw_ostream *RawStream = new raw_fd_ostream(FullPath, E, sys::fs::F_RW);
+ raw_ostream *RawStream =
+ new raw_fd_ostream(FullPath, E, sys::fs::FA_Read | sys::fs::FA_Write);
auto OS = CoveragePrinter::OwnedStream(RawStream);
if (E)
return errorCodeToError(E);
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageView.h b/contrib/llvm/tools/llvm-cov/SourceCoverageView.h
index 7f58ea5d7be8..e3a2f9e5c0b4 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -27,7 +27,7 @@ using namespace coverage;
class CoverageFiltersMatchAll;
class SourceCoverageView;
-/// \brief A view that represents a macro or include expansion.
+/// A view that represents a macro or include expansion.
struct ExpansionView {
CounterMappingRegion Region;
std::unique_ptr<SourceCoverageView> View;
@@ -52,7 +52,7 @@ struct ExpansionView {
}
};
-/// \brief A view that represents a function instantiation.
+/// A view that represents a function instantiation.
struct InstantiationView {
StringRef FunctionName;
unsigned Line;
@@ -68,7 +68,7 @@ struct InstantiationView {
}
};
-/// \brief A file manager that handles format-aware file creation.
+/// A file manager that handles format-aware file creation.
class CoveragePrinter {
public:
struct StreamDestructor {
@@ -82,18 +82,18 @@ protected:
CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
- /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
+ /// Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
/// false, skip the ToplevelDir component. If \p Relative is false, skip the
/// OutputDir component.
std::string getOutputPath(StringRef Path, StringRef Extension,
bool InToplevel, bool Relative = true) const;
- /// \brief If directory output is enabled, create a file in that directory
+ /// If directory output is enabled, create a file in that directory
/// at the path given by getOutputPath(). Otherwise, return stdout.
Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
bool InToplevel) const;
- /// \brief Return the sub-directory name for file coverage reports.
+ /// Return the sub-directory name for file coverage reports.
static StringRef getCoverageDir() { return "coverage"; }
public:
@@ -105,14 +105,14 @@ public:
/// @name File Creation Interface
/// @{
- /// \brief Create a file to print a coverage view into.
+ /// Create a file to print a coverage view into.
virtual Expected<OwnedStream> createViewFile(StringRef Path,
bool InToplevel) = 0;
- /// \brief Close a file which has been used to print a coverage view.
+ /// Close a file which has been used to print a coverage view.
virtual void closeViewFile(OwnedStream OS) = 0;
- /// \brief Create an index which lists reports for the given source files.
+ /// Create an index which lists reports for the given source files.
virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
const CoverageMapping &Coverage,
const CoverageFiltersMatchAll &Filters) = 0;
@@ -120,7 +120,7 @@ public:
/// @}
};
-/// \brief A code coverage view of a source file or function.
+/// A code coverage view of a source file or function.
///
/// A source coverage view and its nested sub-views form a file-oriented
/// representation of code coverage data. This view can be printed out by a
@@ -161,73 +161,73 @@ protected:
/// @name Rendering Interface
/// @{
- /// \brief Render a header for the view.
+ /// Render a header for the view.
virtual void renderViewHeader(raw_ostream &OS) = 0;
- /// \brief Render a footer for the view.
+ /// Render a footer for the view.
virtual void renderViewFooter(raw_ostream &OS) = 0;
- /// \brief Render the source name for the view.
+ /// Render the source name for the view.
virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
- /// \brief Render the line prefix at the given \p ViewDepth.
+ /// Render the line prefix at the given \p ViewDepth.
virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
- /// \brief Render the line suffix at the given \p ViewDepth.
+ /// Render the line suffix at the given \p ViewDepth.
virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
- /// \brief Render a view divider at the given \p ViewDepth.
+ /// Render a view divider at the given \p ViewDepth.
virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
- /// \brief Render a source line with highlighting.
+ /// Render a source line with highlighting.
virtual void renderLine(raw_ostream &OS, LineRef L,
const LineCoverageStats &LCS, unsigned ExpansionCol,
unsigned ViewDepth) = 0;
- /// \brief Render the line's execution count column.
+ /// Render the line's execution count column.
virtual void renderLineCoverageColumn(raw_ostream &OS,
const LineCoverageStats &Line) = 0;
- /// \brief Render the line number column.
+ /// Render the line number column.
virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
- /// \brief Render all the region's execution counts on a line.
+ /// Render all the region's execution counts on a line.
virtual void renderRegionMarkers(raw_ostream &OS,
const LineCoverageStats &Line,
unsigned ViewDepth) = 0;
- /// \brief Render the site of an expansion.
+ /// Render the site of an expansion.
virtual void renderExpansionSite(raw_ostream &OS, LineRef L,
const LineCoverageStats &LCS,
unsigned ExpansionCol,
unsigned ViewDepth) = 0;
- /// \brief Render an expansion view and any nested views.
+ /// Render an expansion view and any nested views.
virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
unsigned ViewDepth) = 0;
- /// \brief Render an instantiation view and any nested views.
+ /// Render an instantiation view and any nested views.
virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
unsigned ViewDepth) = 0;
- /// \brief Render \p Title, a project title if one is available, and the
+ /// Render \p Title, a project title if one is available, and the
/// created time.
virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
- /// \brief Render the table header for a given source file.
+ /// Render the table header for a given source file.
virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
unsigned IndentLevel) = 0;
/// @}
- /// \brief Format a count using engineering notation with 3 significant
+ /// Format a count using engineering notation with 3 significant
/// digits.
static std::string formatCount(uint64_t N);
- /// \brief Check if region marker output is expected for a line.
+ /// Check if region marker output is expected for a line.
bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const;
- /// \brief Check if there are any sub-views attached to this view.
+ /// Check if there are any sub-views attached to this view.
bool hasSubViews() const;
SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
@@ -243,20 +243,20 @@ public:
virtual ~SourceCoverageView() {}
- /// \brief Return the source name formatted for the host OS.
+ /// Return the source name formatted for the host OS.
std::string getSourceName() const;
const CoverageViewOptions &getOptions() const { return Options; }
- /// \brief Add an expansion subview to this view.
+ /// Add an expansion subview to this view.
void addExpansion(const CounterMappingRegion &Region,
std::unique_ptr<SourceCoverageView> View);
- /// \brief Add a function instantiation subview to this view.
+ /// Add a function instantiation subview to this view.
void addInstantiation(StringRef FunctionName, unsigned Line,
std::unique_ptr<SourceCoverageView> View);
- /// \brief Print the code coverage information for a specific portion of a
+ /// Print the code coverage information for a specific portion of a
/// source file to the output stream.
void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
bool ShowTitle, unsigned ViewDepth = 0);
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index e45c6f4cb473..acb67aa5cfc7 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -25,31 +25,29 @@ namespace {
// Return a string with the special characters in \p Str escaped.
std::string escape(StringRef Str, const CoverageViewOptions &Opts) {
- std::string Result;
+ std::string TabExpandedResult;
unsigned ColNum = 0; // Record the column number.
for (char C : Str) {
- ++ColNum;
- if (C == '&')
- Result += "&amp;";
- else if (C == '<')
- Result += "&lt;";
- else if (C == '>')
- Result += "&gt;";
- else if (C == '\"')
- Result += "&quot;";
- else if (C == '\n' || C == '\r') {
- Result += C;
- ColNum = 0;
- } else if (C == '\t') {
- // Replace '\t' with TabSize spaces.
- unsigned NumSpaces = Opts.TabSize - (--ColNum % Opts.TabSize);
+ if (C == '\t') {
+ // Replace '\t' with up to TabSize spaces.
+ unsigned NumSpaces = Opts.TabSize - (ColNum % Opts.TabSize);
for (unsigned I = 0; I < NumSpaces; ++I)
- Result += "&nbsp;";
+ TabExpandedResult += ' ';
ColNum += NumSpaces;
- } else
- Result += C;
+ } else {
+ TabExpandedResult += C;
+ if (C == '\n' || C == '\r')
+ ColNum = 0;
+ else
+ ++ColNum;
+ }
+ }
+ std::string EscapedHTML;
+ {
+ raw_string_ostream OS{EscapedHTML};
+ printHTMLEscaped(TabExpandedResult, OS);
}
- return Result;
+ return EscapedHTML;
}
// Create a \p Name tag around \p Str, and optionally set its \p ClassName.
@@ -116,24 +114,39 @@ table {
background: #ffffff;
border: 1px solid #dbdbdb;
}
+.light-row-bold {
+ background: #ffffff;
+ border: 1px solid #dbdbdb;
+ font-weight: bold;
+}
.column-entry {
- text-align: right;
+ text-align: left;
}
-.column-entry-left {
+.column-entry-bold {
+ font-weight: bold;
text-align: left;
}
.column-entry-yellow {
- text-align: right;
+ text-align: left;
background-color: #ffffd0;
}
+.column-entry-yellow:hover {
+ background-color: #fffff0;
+}
.column-entry-red {
- text-align: right;
+ text-align: left;
background-color: #ffd0d0;
}
+.column-entry-red:hover {
+ background-color: #fff0f0;
+}
.column-entry-green {
- text-align: right;
+ text-align: left;
background-color: #d0ffd0;
}
+.column-entry-green:hover {
+ background-color: #f0fff0;
+}
.line-number {
text-align: right;
color: #aaa;
@@ -184,10 +197,14 @@ table {
}
th, td {
vertical-align: top;
- padding: 2px 5px;
+ padding: 2px 8px;
border-collapse: collapse;
border-right: solid 1px #eee;
border-left: solid 1px #eee;
+ text-align: left;
+}
+td pre {
+ display: inline-block;
}
td:first-child {
border-left: none;
@@ -195,6 +212,9 @@ td:first-child {
td:last-child {
border-right: none;
}
+tr:hover {
+ background-color: #f0f0f0;
+}
)";
const char *EndHeader = "</head>";
@@ -287,13 +307,14 @@ void CoveragePrinterHTML::closeViewFile(OwnedStream OS) {
static void emitColumnLabelsForIndex(raw_ostream &OS,
const CoverageViewOptions &Opts) {
SmallVector<std::string, 4> Columns;
- Columns.emplace_back(tag("td", "Filename", "column-entry-left"));
- Columns.emplace_back(tag("td", "Function Coverage", "column-entry"));
+ Columns.emplace_back(tag("td", "Filename", "column-entry-bold"));
+ Columns.emplace_back(tag("td", "Function Coverage", "column-entry-bold"));
if (Opts.ShowInstantiationSummary)
- Columns.emplace_back(tag("td", "Instantiation Coverage", "column-entry"));
- Columns.emplace_back(tag("td", "Line Coverage", "column-entry"));
+ Columns.emplace_back(
+ tag("td", "Instantiation Coverage", "column-entry-bold"));
+ Columns.emplace_back(tag("td", "Line Coverage", "column-entry-bold"));
if (Opts.ShowRegionSummary)
- Columns.emplace_back(tag("td", "Region Coverage", "column-entry"));
+ Columns.emplace_back(tag("td", "Region Coverage", "column-entry-bold"));
OS << tag("tr", join(Columns.begin(), Columns.end(), ""));
}
@@ -339,7 +360,7 @@ void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,
// Simplify the display file path, and wrap it in a link if requested.
std::string Filename;
if (IsTotals) {
- Filename = "TOTALS";
+ Filename = SF;
} else {
Filename = buildLinkToFile(SF, FCS);
}
@@ -360,7 +381,10 @@ void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,
FCS.RegionCoverage.getNumRegions(),
FCS.RegionCoverage.getPercentCovered());
- OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row");
+ if (IsTotals)
+ OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row-bold");
+ else
+ OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row");
}
Error CoveragePrinterHTML::createIndexFile(
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.h b/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
index 91b4ad4e220c..cb41fcaf37b9 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
@@ -22,7 +22,7 @@ using namespace coverage;
struct FileCoverageSummary;
-/// \brief A coverage printer for html output.
+/// A coverage printer for html output.
class CoveragePrinterHTML : public CoveragePrinter {
public:
Expected<OwnedStream> createViewFile(StringRef Path,
@@ -45,7 +45,7 @@ private:
const FileCoverageSummary &FCS) const;
};
-/// \brief A code coverage view which supports html-based rendering.
+/// A code coverage view which supports html-based rendering.
class SourceCoverageViewHTML : public SourceCoverageView {
void renderViewHeader(raw_ostream &OS) override;
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 2480ee9f416a..aac70baed613 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -51,13 +51,13 @@ namespace {
static const unsigned LineCoverageColumnWidth = 7;
static const unsigned LineNumberColumnWidth = 5;
-/// \brief Get the width of the leading columns.
+/// Get the width of the leading columns.
unsigned getCombinedColumnWidth(const CoverageViewOptions &Opts) {
return (Opts.ShowLineStats ? LineCoverageColumnWidth + 1 : 0) +
(Opts.ShowLineNumbers ? LineNumberColumnWidth + 1 : 0);
}
-/// \brief The width of the line that is used to divide between the view and
+/// The width of the line that is used to divide between the view and
/// the subviews.
unsigned getDividerWidth(const CoverageViewOptions &Opts) {
return getCombinedColumnWidth(Opts) + 4;
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.h b/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.h
index cabf91975df3..a46f35cc6495 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.h
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageViewText.h
@@ -20,7 +20,7 @@ namespace llvm {
using namespace coverage;
-/// \brief A coverage printer for text output.
+/// A coverage printer for text output.
class CoveragePrinterText : public CoveragePrinter {
public:
Expected<OwnedStream> createViewFile(StringRef Path,
@@ -36,7 +36,7 @@ public:
: CoveragePrinter(Opts) {}
};
-/// \brief A code coverage view which supports text-based rendering.
+/// A code coverage view which supports text-based rendering.
class SourceCoverageViewText : public SourceCoverageView {
void renderViewHeader(raw_ostream &OS) override;
diff --git a/contrib/llvm/tools/llvm-cov/TestingSupport.cpp b/contrib/llvm/tools/llvm-cov/TestingSupport.cpp
index 4713d75f17dd..e07abdbd17f1 100644
--- a/contrib/llvm/tools/llvm-cov/TestingSupport.cpp
+++ b/contrib/llvm/tools/llvm-cov/TestingSupport.cpp
@@ -75,8 +75,7 @@ int convertForTestingMain(int argc, const char *argv[]) {
return 1;
int FD;
- if (auto Err =
- sys::fs::openFileForWrite(OutputFilename, FD, sys::fs::F_None)) {
+ if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) {
errs() << "error: " << Err.message() << "\n";
return 1;
}
diff --git a/contrib/llvm/tools/llvm-cov/llvm-cov.cpp b/contrib/llvm/tools/llvm-cov/llvm-cov.cpp
index 158415870250..4c3b574451c3 100644
--- a/contrib/llvm/tools/llvm-cov/llvm-cov.cpp
+++ b/contrib/llvm/tools/llvm-cov/llvm-cov.cpp
@@ -14,32 +14,31 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
using namespace llvm;
-/// \brief The main entry point for the 'show' subcommand.
+/// The main entry point for the 'show' subcommand.
int showMain(int argc, const char *argv[]);
-/// \brief The main entry point for the 'report' subcommand.
+/// The main entry point for the 'report' subcommand.
int reportMain(int argc, const char *argv[]);
-/// \brief The main entry point for the 'export' subcommand.
+/// The main entry point for the 'export' subcommand.
int exportMain(int argc, const char *argv[]);
-/// \brief The main entry point for the 'convert-for-testing' subcommand.
+/// The main entry point for the 'convert-for-testing' subcommand.
int convertForTestingMain(int argc, const char *argv[]);
-/// \brief The main entry point for the gcov compatible coverage tool.
+/// The main entry point for the gcov compatible coverage tool.
int gcovMain(int argc, const char *argv[]);
-/// \brief Top level help.
+/// Top level help.
static int helpMain(int argc, const char *argv[]) {
errs() << "Usage: llvm-cov {export|gcov|report|show} [OPTION]...\n\n"
<< "Shows code coverage information.\n\n"
@@ -52,17 +51,14 @@ static int helpMain(int argc, const char *argv[]) {
return 0;
}
-/// \brief Top level version information.
+/// Top level version information.
static int versionMain(int argc, const char *argv[]) {
cl::PrintVersionMessage();
return 0;
}
int main(int argc, const char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
// If argv[0] is or ends with 'gcov', always be gcov compatible
if (sys::path::stem(argv[0]).endswith_lower("gcov"))
diff --git a/contrib/llvm/tools/llvm-cxxdump/Error.cpp b/contrib/llvm/tools/llvm-cxxdump/Error.cpp
index d59547e3a2ce..54207fad32af 100644
--- a/contrib/llvm/tools/llvm-cxxdump/Error.cpp
+++ b/contrib/llvm/tools/llvm-cxxdump/Error.cpp
@@ -1,4 +1,4 @@
-//===- Error.cxx - system_error extensions for llvm-cxxdump -----*- C++ -*-===//
+//===- Error.cpp - system_error extensions for llvm-cxxdump -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
index 9b687e4fbe22..09e40d9b0db7 100644
--- a/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
+++ b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -20,9 +20,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
@@ -533,9 +531,7 @@ static void dumpInput(StringRef File) {
}
int main(int argc, const char *argv[]) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y;
+ InitLLVM X(argc, argv);
// Initialize targets.
llvm::InitializeAllTargetInfos();
diff --git a/contrib/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/contrib/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 9c6a1612fa08..afc1e4a8d128 100644
--- a/contrib/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/contrib/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -9,8 +9,7 @@
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <iostream>
@@ -81,8 +80,7 @@ static void demangle(llvm::raw_ostream &OS, const std::string &Mangled) {
}
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "llvm symbol undecoration tool\n");
diff --git a/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp b/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp
index 95a63d7f9c83..af0a055ea21f 100644
--- a/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp
+++ b/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp
@@ -303,6 +303,26 @@ class FunctionDifferenceEngine {
if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0));
return false;
+ } else if (isa<IndirectBrInst>(L)) {
+ IndirectBrInst *LI = cast<IndirectBrInst>(L);
+ IndirectBrInst *RI = cast<IndirectBrInst>(R);
+ if (LI->getNumDestinations() != RI->getNumDestinations()) {
+ if (Complain) Engine.log("indirectbr # of destinations differ");
+ return true;
+ }
+
+ if (!equivalentAsOperands(LI->getAddress(), RI->getAddress())) {
+ if (Complain) Engine.log("indirectbr addresses differ");
+ return true;
+ }
+
+ if (TryUnify) {
+ for (unsigned i = 0; i < LI->getNumDestinations(); i++) {
+ tryUnify(LI->getDestination(i), RI->getDestination(i));
+ }
+ }
+ return false;
+
} else if (isa<SwitchInst>(L)) {
SwitchInst *LI = cast<SwitchInst>(L);
SwitchInst *RI = cast<SwitchInst>(R);
@@ -377,9 +397,9 @@ class FunctionDifferenceEngine {
return equivalentAsOperands(cast<ConstantExpr>(L),
cast<ConstantExpr>(R));
- // Nulls of the "same type" don't always actually have the same
+ // Constants of the "same type" don't always actually have the same
// type; I don't know why. Just white-list them.
- if (isa<ConstantPointerNull>(L))
+ if (isa<ConstantPointerNull>(L) || isa<UndefValue>(L) || isa<ConstantAggregateZero>(L))
return true;
// Block addresses only match if we've already encountered the
@@ -388,6 +408,19 @@ class FunctionDifferenceEngine {
return Blocks[cast<BlockAddress>(L)->getBasicBlock()]
== cast<BlockAddress>(R)->getBasicBlock();
+ // If L and R are ConstantVectors, compare each element
+ if (isa<ConstantVector>(L)) {
+ ConstantVector *CVL = cast<ConstantVector>(L);
+ ConstantVector *CVR = cast<ConstantVector>(R);
+ if (CVL->getType()->getNumElements() != CVR->getType()->getNumElements())
+ return false;
+ for (unsigned i = 0; i < CVL->getType()->getNumElements(); i++) {
+ if (!equivalentAsOperands(CVL->getOperand(i), CVR->getOperand(i)))
+ return false;
+ }
+ return true;
+ }
+
return false;
}
diff --git a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
index c91aa1c71a15..8143a2a5a934 100644
--- a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -16,24 +16,23 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
#include <system_error>
using namespace llvm;
@@ -129,10 +128,10 @@ struct LLVMDisDiagnosticHandler : public DiagnosticHandler {
raw_ostream &OS = errs();
OS << Prefix << ": ";
switch (DI.getSeverity()) {
- case DS_Error: OS << "error: "; break;
- case DS_Warning: OS << "warning: "; break;
+ case DS_Error: WithColor::error(OS); break;
+ case DS_Warning: WithColor::warning(OS); break;
case DS_Remark: OS << "remark: "; break;
- case DS_Note: OS << "note: "; break;
+ case DS_Note: WithColor::note(OS); break;
}
DiagnosticPrinterRawOStream DP(OS);
@@ -148,33 +147,29 @@ struct LLVMDisDiagnosticHandler : public DiagnosticHandler {
static ExitOnError ExitOnErr;
-static std::unique_ptr<Module> openInputFile(LLVMContext &Context) {
- std::unique_ptr<MemoryBuffer> MB =
- ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename)));
- std::unique_ptr<Module> M = ExitOnErr(getOwningLazyBitcodeModule(
- std::move(MB), Context,
- /*ShouldLazyLoadMetadata=*/true, SetImporting));
- if (MaterializeMetadata)
- ExitOnErr(M->materializeMetadata());
- else
- ExitOnErr(M->materializeAll());
- return M;
-}
-
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
ExitOnErr.setBanner(std::string(argv[0]) + ": error: ");
LLVMContext Context;
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
Context.setDiagnosticHandler(
llvm::make_unique<LLVMDisDiagnosticHandler>(argv[0]));
cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
- std::unique_ptr<Module> M = openInputFile(Context);
+ std::unique_ptr<MemoryBuffer> MB =
+ ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename)));
+ std::unique_ptr<Module> M = ExitOnErr(getLazyBitcodeModule(
+ *MB, Context, /*ShouldLazyLoadMetadata=*/true, SetImporting));
+ if (MaterializeMetadata)
+ ExitOnErr(M->materializeMetadata());
+ else
+ ExitOnErr(M->materializeAll());
+
+ BitcodeLTOInfo LTOInfo = ExitOnErr(getBitcodeLTOInfo(*MB));
+ std::unique_ptr<ModuleSummaryIndex> Index;
+ if (LTOInfo.HasSummary)
+ Index = ExitOnErr(getModuleSummaryIndex(*MB));
// Just use stdout. We won't actually print anything on it.
if (DontPrint)
@@ -203,8 +198,11 @@ int main(int argc, char **argv) {
Annotator.reset(new CommentWriter());
// All that llvm-dis does is write the assembly to a file.
- if (!DontPrint)
+ if (!DontPrint) {
M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);
+ if (Index)
+ Index->print(Out->os());
+ }
// Declare success.
Out->keep();
diff --git a/contrib/llvm/tools/llvm-dwarfdump/Statistics.cpp b/contrib/llvm/tools/llvm-dwarfdump/Statistics.cpp
index 9a7454a52624..5af853d4ef28 100644
--- a/contrib/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/contrib/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -34,8 +34,14 @@ struct GlobalStats {
/// Extract the low pc from a Die.
static uint64_t getLowPC(DWARFDie Die) {
- if (Die.getAddressRanges().size())
- return Die.getAddressRanges()[0].LowPC;
+ auto RangesOrError = Die.getAddressRanges();
+ DWARFAddressRangesVector Ranges;
+ if (RangesOrError)
+ Ranges = RangesOrError.get();
+ else
+ llvm::consumeError(RangesOrError.takeError());
+ if (Ranges.size())
+ return Ranges[0].LowPC;
return dwarf::toAddress(Die.find(dwarf::DW_AT_low_pc), 0);
}
@@ -137,7 +143,13 @@ static void collectStatsRecursive(DWARFDie Die, std::string Prefix,
}
// PC Ranges.
- auto Ranges = Die.getAddressRanges();
+ auto RangesOrError = Die.getAddressRanges();
+ if (!RangesOrError) {
+ llvm::consumeError(RangesOrError.takeError());
+ return;
+ }
+
+ auto Ranges = RangesOrError.get();
uint64_t BytesInThisScope = 0;
for (auto Range : Ranges)
BytesInThisScope += Range.HighPC - Range.LowPC;
@@ -165,11 +177,11 @@ static void collectStatsRecursive(DWARFDie Die, std::string Prefix,
/// \{
static void printDatum(raw_ostream &OS, const char *Key, StringRef Value) {
OS << ",\"" << Key << "\":\"" << Value << '"';
- DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
+ LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
}
static void printDatum(raw_ostream &OS, const char *Key, uint64_t Value) {
OS << ",\"" << Key << "\":" << Value;
- DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
+ LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
}
/// \}
@@ -206,8 +218,9 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
VarWithLoc += Stats.TotalVarWithLoc + Constants;
VarTotal += TotalVars + Constants;
VarUnique += Stats.VarsInFunction.size();
- DEBUG(for (auto V : Stats.VarsInFunction)
- llvm::dbgs() << Entry.getKey() << ": " << V << "\n");
+ LLVM_DEBUG(for (auto V
+ : Stats.VarsInFunction) llvm::dbgs()
+ << Entry.getKey() << ": " << V << "\n");
NumFunctions += Stats.IsFunction;
NumInlinedFunctions += Stats.IsFunction * Stats.NumFnInlined;
}
@@ -215,8 +228,8 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
// Print summary.
OS.SetBufferSize(1024);
OS << "{\"version\":\"" << Version << '"';
- DEBUG(llvm::dbgs() << "Variable location quality metrics\n";
- llvm::dbgs() << "---------------------------------\n");
+ LLVM_DEBUG(llvm::dbgs() << "Variable location quality metrics\n";
+ llvm::dbgs() << "---------------------------------\n");
printDatum(OS, "file", Filename.str());
printDatum(OS, "format", FormatName);
printDatum(OS, "source functions", NumFunctions);
@@ -228,7 +241,7 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
GlobalStats.ScopeBytesFromFirstDefinition);
printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
OS << "}\n";
- DEBUG(
+ LLVM_DEBUG(
llvm::dbgs() << "Total Availability: "
<< (int)std::round((VarWithLoc * 100.0) / VarTotal) << "%\n";
llvm::dbgs() << "PC Ranges covered: "
diff --git a/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 12c005de6005..d75f33906098 100644
--- a/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -22,14 +22,13 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -310,6 +309,62 @@ static void filterByName(const StringSet<> &Names,
}
+static void getDies(DWARFContext &DICtx, const AppleAcceleratorTable &Accel,
+ StringRef Name, SmallVectorImpl<DWARFDie> &Dies) {
+ for (const auto &Entry : Accel.equal_range(Name)) {
+ if (llvm::Optional<uint64_t> Off = Entry.getDIESectionOffset()) {
+ if (DWARFDie Die = DICtx.getDIEForOffset(*Off))
+ Dies.push_back(Die);
+ }
+ }
+}
+
+static DWARFDie toDie(const DWARFDebugNames::Entry &Entry,
+ DWARFContext &DICtx) {
+ llvm::Optional<uint64_t> CUOff = Entry.getCUOffset();
+ llvm::Optional<uint64_t> Off = Entry.getDIEUnitOffset();
+ if (!CUOff || !Off)
+ return DWARFDie();
+
+ DWARFCompileUnit *CU = DICtx.getCompileUnitForOffset(*CUOff);
+ if (!CU)
+ return DWARFDie();
+
+ if (llvm::Optional<uint64_t> DWOId = CU->getDWOId()) {
+ // This is a skeleton unit. Look up the DIE in the DWO unit.
+ CU = DICtx.getDWOCompileUnitForHash(*DWOId);
+ if (!CU)
+ return DWARFDie();
+ }
+
+ return CU->getDIEForOffset(CU->getOffset() + *Off);
+}
+
+static void getDies(DWARFContext &DICtx, const DWARFDebugNames &Accel,
+ StringRef Name, SmallVectorImpl<DWARFDie> &Dies) {
+ for (const auto &Entry : Accel.equal_range(Name)) {
+ if (DWARFDie Die = toDie(Entry, DICtx))
+ Dies.push_back(Die);
+ }
+}
+
+/// Print only DIEs that have a certain name.
+static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
+ raw_ostream &OS) {
+ SmallVector<DWARFDie, 4> Dies;
+ for (const auto &Name : Names) {
+ getDies(DICtx, DICtx.getAppleNames(), Name, Dies);
+ getDies(DICtx, DICtx.getAppleTypes(), Name, Dies);
+ getDies(DICtx, DICtx.getAppleNamespaces(), Name, Dies);
+ getDies(DICtx, DICtx.getDebugNames(), Name, Dies);
+ }
+ llvm::sort(Dies.begin(), Dies.end());
+ Dies.erase(std::unique(Dies.begin(), Dies.end()), Dies.end());
+
+ for (DWARFDie Die : Dies)
+ Die.dump(OS, 0, getDumpOpts());
+}
+
/// Handle the --lookup option and dump the DIEs and line info for the given
/// address.
static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) {
@@ -361,28 +416,8 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename,
// Handle the --find option and lower it to --debug-info=<offset>.
if (!Find.empty()) {
- DumpOffsets[DIDT_ID_DebugInfo] = [&]() -> llvm::Optional<uint64_t> {
- for (auto Name : Find) {
- auto find = [&](const DWARFAcceleratorTable &Accel)
- -> llvm::Optional<uint64_t> {
- for (auto Entry : Accel.equal_range(Name))
- for (auto Atom : Entry)
- if (auto Offset = Atom.getAsSectionOffset())
- return Offset;
- return None;
- };
- if (auto Offset = find(DICtx.getAppleNames()))
- return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
- if (auto Offset = find(DICtx.getAppleTypes()))
- return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
- if (auto Offset = find(DICtx.getAppleNamespaces()))
- return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
- }
- return None;
- }();
- // Early exit if --find was specified but the current file doesn't have it.
- if (!DumpOffsets[DIDT_ID_DebugInfo])
- return true;
+ filterByAccelName(Find, DICtx, OS);
+ return true;
}
// Dump the complete DWARF structure.
@@ -477,6 +512,8 @@ static bool handleFile(StringRef Filename, HandlerFn HandleObj,
static std::vector<std::string> expandBundle(const std::string &InputPath) {
std::vector<std::string> BundlePaths;
SmallString<256> BundlePath(InputPath);
+ // Normalize input path. This is necessary to accept `bundle.dSYM/`.
+ sys::path::remove_dots(BundlePath);
// Manually open up the bundle to avoid introducing additional dependencies.
if (sys::fs::is_directory(BundlePath) &&
sys::path::extension(BundlePath) == ".dSYM") {
@@ -505,15 +542,12 @@ static std::vector<std::string> expandBundle(const std::string &InputPath) {
}
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
- HideUnrelatedOptions({&DwarfDumpCategory, &SectionCategory});
+ HideUnrelatedOptions({&DwarfDumpCategory, &SectionCategory, &ColorCategory});
cl::ParseCommandLineOptions(
argc, argv,
"pretty-print DWARF debug information in object files"
@@ -565,7 +599,7 @@ int main(int argc, char **argv) {
ShowChildren = true;
// Defaults to a.out if no filenames specified.
- if (InputFilenames.size() == 0)
+ if (InputFilenames.empty())
InputFilenames.push_back("a.out");
// Expand any .dSYM bundles to the individual object files contained therein.
diff --git a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
index c39ffa58fbf7..94aaa2f52eb5 100644
--- a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
@@ -25,10 +25,8 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -67,6 +65,12 @@ ExtractRegExpFuncs("rfunc", cl::desc("Specify function(s) to extract using a "
"regular expression"),
cl::ZeroOrMore, cl::value_desc("rfunction"));
+// ExtractBlocks - The blocks to extract from the module.
+static cl::list<std::string>
+ ExtractBlocks("bb",
+ cl::desc("Specify <function, basic block> pairs to extract"),
+ cl::ZeroOrMore, cl::value_desc("function:bb"));
+
// ExtractAlias - The alias to extract from the module.
static cl::list<std::string>
ExtractAliases("alias", cl::desc("Specify alias to extract"),
@@ -107,12 +111,9 @@ static cl::opt<bool> PreserveAssemblyUseListOrder(
cl::init(false), cl::Hidden);
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
LLVMContext Context;
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
// Use lazy loading, since we only care about selected global values.
@@ -228,6 +229,32 @@ int main(int argc, char **argv) {
}
}
+ // Figure out which BasicBlocks we should extract.
+ SmallVector<BasicBlock *, 4> BBs;
+ for (StringRef StrPair : ExtractBlocks) {
+ auto BBInfo = StrPair.split(':');
+ // Get the function.
+ Function *F = M->getFunction(BBInfo.first);
+ if (!F) {
+ errs() << argv[0] << ": program doesn't contain a function named '"
+ << BBInfo.first << "'!\n";
+ return 1;
+ }
+ // Do not materialize this function.
+ GVs.insert(F);
+ // Get the basic block.
+ auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) {
+ return BB.getName().equals(BBInfo.second);
+ });
+ if (Res == F->end()) {
+ errs() << argv[0] << ": function " << F->getName()
+ << " doesn't contain a basic block named '" << BBInfo.second
+ << "'!\n";
+ return 1;
+ }
+ BBs.push_back(&*Res);
+ }
+
// Use *argv instead of argv[0] to work around a wrong GCC warning.
ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: ");
@@ -286,6 +313,14 @@ int main(int argc, char **argv) {
ExitOnErr(M->materializeAll());
}
+ // Extract the specified basic blocks from the module and erase the existing
+ // functions.
+ if (!ExtractBlocks.empty()) {
+ legacy::PassManager PM;
+ PM.add(createBlockExtractorPass(BBs, true));
+ PM.run(*M);
+ }
+
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
legacy::PassManager Passes;
diff --git a/contrib/llvm/tools/llvm-link/llvm-link.cpp b/contrib/llvm/tools/llvm-link/llvm-link.cpp
index 50f506aeaae9..b7a888375b3d 100644
--- a/contrib/llvm/tools/llvm-link/llvm-link.cpp
+++ b/contrib/llvm/tools/llvm-link/llvm-link.cpp
@@ -26,13 +26,12 @@
#include "llvm/Linker/Linker.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Transforms/IPO/FunctionImport.h"
#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
@@ -120,7 +119,8 @@ static std::unique_ptr<Module> loadFile(const char *argv0,
LLVMContext &Context,
bool MaterializeMetadata = true) {
SMDiagnostic Err;
- if (Verbose) errs() << "Loading '" << FN << "'\n";
+ if (Verbose)
+ errs() << "Loading '" << FN << "'\n";
std::unique_ptr<Module> Result;
if (DisableLazyLoad)
Result = parseIRFile(FN, Err, Context);
@@ -188,12 +188,12 @@ struct LLVMLinkDiagnosticHandler : public DiagnosticHandler {
unsigned Severity = DI.getSeverity();
switch (Severity) {
case DS_Error:
- errs() << "ERROR: ";
+ WithColor::error();
break;
case DS_Warning:
if (SuppressWarnings)
return true;
- errs() << "WARNING: ";
+ WithColor::warning();
break;
case DS_Remark:
case DS_Note:
@@ -238,8 +238,8 @@ static bool importFunctions(const char *argv0, Module &DestModule) {
auto &SrcModule = ModuleLoaderCache(argv0, FileName);
if (verifyModule(SrcModule, &errs())) {
- errs() << argv0 << ": " << FileName
- << ": error: input module is broken!\n";
+ errs() << argv0 << ": " << FileName;
+ WithColor::error() << "input module is broken!\n";
return false;
}
@@ -262,7 +262,7 @@ static bool importFunctions(const char *argv0, Module &DestModule) {
errs() << "Importing " << FunctionName << " from " << FileName << "\n";
auto &Entry = ImportList[FileName];
- Entry.insert(std::make_pair(F->getGUID(), /* (Unused) threshold */ 1.0));
+ Entry.insert(F->getGUID());
}
auto CachedModuleLoader = [&](StringRef Identifier) {
return ModuleLoaderCache.takeModule(Identifier);
@@ -283,7 +283,8 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
for (const auto &File : Files) {
std::unique_ptr<Module> M = loadFile(argv0, File, Context);
if (!M.get()) {
- errs() << argv0 << ": error loading file '" << File << "'\n";
+ errs() << argv0 << ": ";
+ WithColor::error() << " loading file '" << File << "'\n";
return false;
}
@@ -291,7 +292,8 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
// doing that debug metadata in the src module might already be pointing to
// the destination.
if (DisableDITypeMap && verifyModule(*M, &errs())) {
- errs() << argv0 << ": " << File << ": error: input module is broken!\n";
+ errs() << argv0 << ": " << File << ": ";
+ WithColor::error() << "input module is broken!\n";
return false;
}
@@ -345,16 +347,12 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
}
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
-
+ InitLLVM X(argc, argv);
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
LLVMContext Context;
Context.setDiagnosticHandler(
llvm::make_unique<LLVMLinkDiagnosticHandler>(), true);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
if (!DisableDITypeMap)
@@ -380,25 +378,28 @@ int main(int argc, char **argv) {
if (!importFunctions(argv[0], *Composite))
return 1;
- if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
+ if (DumpAsm)
+ errs() << "Here's the assembly:\n" << *Composite;
std::error_code EC;
ToolOutputFile Out(OutputFilename, EC, sys::fs::F_None);
if (EC) {
- errs() << EC.message() << '\n';
+ WithColor::error() << EC.message() << '\n';
return 1;
}
if (verifyModule(*Composite, &errs())) {
- errs() << argv[0] << ": error: linked module is broken!\n";
+ errs() << argv[0] << ": ";
+ WithColor::error() << "linked module is broken!\n";
return 1;
}
- if (Verbose) errs() << "Writing bitcode...\n";
+ if (Verbose)
+ errs() << "Writing bitcode...\n";
if (OutputAssembly) {
Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder);
} else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
- WriteBitcodeToFile(Composite.get(), Out.os(), PreserveBitcodeUseListOrder);
+ WriteBitcodeToFile(*Composite, Out.os(), PreserveBitcodeUseListOrder);
// Declare success.
Out.keep();
diff --git a/contrib/llvm/tools/llvm-lto/llvm-lto.cpp b/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
index 7d71a3e8dfe3..75668a9dd8b6 100644
--- a/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -22,7 +22,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
@@ -40,11 +40,9 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -157,7 +155,16 @@ static cl::opt<std::string>
ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
static cl::opt<int>
- ThinLTOCachePruningInterval("thinlto-cache-pruning-interval", cl::desc("Set ThinLTO cache pruning interval."));
+ ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
+ cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
+
+static cl::opt<int>
+ ThinLTOCacheMaxSizeBytes("thinlto-cache-max-size-bytes",
+ cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
+
+static cl::opt<int>
+ ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
+ cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
static cl::opt<std::string> ThinLTOSaveTempsPrefix(
"thinlto-save-temps",
@@ -343,7 +350,7 @@ void printIndexStats() {
}
}
-/// \brief List symbols in each IR file.
+/// List symbols in each IR file.
///
/// The main point here is to provide lit-testable coverage for the LTOModule
/// functionality that's exposed by the C API to list symbols. Moreover, this
@@ -367,13 +374,13 @@ static void listSymbols(const TargetOptions &Options) {
/// This is meant to enable testing of ThinLTO combined index generation,
/// currently available via the gold plugin via -thinlto.
static void createCombinedModuleSummaryIndex() {
- ModuleSummaryIndex CombinedIndex;
+ ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
uint64_t NextModuleId = 0;
for (auto &Filename : InputFilenames) {
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
std::unique_ptr<MemoryBuffer> MB =
ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
- ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, ++NextModuleId));
+ ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, NextModuleId++));
}
std::error_code EC;
assert(!OutputFilename.empty());
@@ -462,7 +469,7 @@ static void writeModuleToFile(Module &TheModule, StringRef Filename) {
raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
error(EC, "error opening the file '" + Filename + "'");
maybeVerifyModule(TheModule);
- WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
+ WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
}
class ThinLTOProcessing {
@@ -474,6 +481,8 @@ public:
ThinGenerator.setTargetOptions(Options);
ThinGenerator.setCacheDir(ThinLTOCacheDir);
ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
+ ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
+ ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
ThinGenerator.setFreestanding(EnableFreestanding);
// Add all the exported symbols to the table of symbols to preserve.
@@ -788,11 +797,7 @@ private:
} // end namespace thinlto
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
-
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
if (OptLevel < '0' || OptLevel > '3')
diff --git a/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp b/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 70aae0f41507..442973f90209 100644
--- a/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -17,7 +17,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/LTO/Caching.h"
#include "llvm/LTO/LTO.h"
@@ -113,6 +113,9 @@ static cl::opt<bool>
DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
cl::desc("Print pass management debugging information"));
+static cl::opt<std::string>
+ StatsFile("stats-file", cl::desc("Filename to write statistics to"));
+
static void check(Error E, std::string Msg) {
if (!E)
return;
@@ -189,7 +192,8 @@ static int run(int argc, char **argv) {
DiagnosticPrinterRawOStream DP(errs());
DI.print(DP);
errs() << '\n';
- exit(1);
+ if (DI.getSeverity() == DS_Error)
+ exit(1);
};
Conf.CPU = MCPU;
@@ -240,10 +244,15 @@ static int run(int argc, char **argv) {
Conf.OverrideTriple = OverrideTriple;
Conf.DefaultTriple = DefaultTriple;
+ Conf.StatsFile = StatsFile;
ThinBackend Backend;
if (ThinLTODistributedIndexes)
- Backend = createWriteIndexesThinBackend("", "", true, "");
+ Backend = createWriteIndexesThinBackend(/* OldPrefix */ "",
+ /* NewPrefix */ "",
+ /* ShouldEmitImportsFiles */ true,
+ /* LinkedObjectsFile */ nullptr,
+ /* OnWrite */ {});
else
Backend = createInProcessThinBackend(Threads);
LTO Lto(std::move(Conf), std::move(Backend));
@@ -296,8 +305,7 @@ static int run(int argc, char **argv) {
return llvm::make_unique<lto::NativeObjectStream>(std::move(S));
};
- auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB,
- StringRef Path) {
+ auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
*AddStream(Task)->OS << MB->getBuffer();
};
diff --git a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
index 3987be2bd688..f494d02f3bca 100644
--- a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -20,34 +20,38 @@
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/MC/MCTargetOptionsCommandFlags.def"
+#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
using namespace llvm;
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
-static cl::opt<std::string>
-OutputFilename("o", cl::desc("Output filename"),
- cl::value_desc("filename"));
+static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
+ cl::value_desc("filename"),
+ cl::init("-"));
+
+static cl::opt<std::string> SplitDwarfFile("split-dwarf-file",
+ cl::desc("DWO output filename"),
+ cl::value_desc("filename"));
static cl::opt<bool>
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
@@ -148,6 +152,11 @@ static cl::opt<std::string>
DebugCompilationDir("fdebug-compilation-dir",
cl::desc("Specifies the debug info's compilation dir"));
+static cl::list<std::string>
+DebugPrefixMap("fdebug-prefix-map",
+ cl::desc("Map file source paths in debug info"),
+ cl::value_desc("= separated key-value pairs"));
+
static cl::opt<std::string>
MainFileName("main-file-name",
cl::desc("Specifies the name we should consider the input file"));
@@ -188,7 +197,7 @@ static const Target *GetTarget(const char *ProgName) {
const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
Error);
if (!TheTarget) {
- errs() << ProgName << ": " << Error;
+ WithColor::error(errs(), ProgName) << Error;
return nullptr;
}
@@ -197,15 +206,11 @@ static const Target *GetTarget(const char *ProgName) {
return TheTarget;
}
-static std::unique_ptr<ToolOutputFile> GetOutputStream() {
- if (OutputFilename == "")
- OutputFilename = "-";
-
+static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path) {
std::error_code EC;
- auto Out =
- llvm::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None);
+ auto Out = llvm::make_unique<ToolOutputFile>(Path, EC, sys::fs::F_None);
if (EC) {
- errs() << EC.message() << '\n';
+ WithColor::error() << EC.message() << '\n';
return nullptr;
}
@@ -238,144 +243,10 @@ static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI,
bool Error = false;
while (Lexer.Lex().isNot(AsmToken::Eof)) {
- const AsmToken &Tok = Lexer.getTok();
-
- switch (Tok.getKind()) {
- default:
- SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning,
- "unknown token");
+ Lexer.getTok().dump(OS);
+ OS << "\n";
+ if (Lexer.getTok().getKind() == AsmToken::Error)
Error = true;
- break;
- case AsmToken::Error:
- Error = true; // error already printed.
- break;
- case AsmToken::Identifier:
- OS << "identifier: " << Lexer.getTok().getString();
- break;
- case AsmToken::Integer:
- OS << "int: " << Lexer.getTok().getString();
- break;
- case AsmToken::Real:
- OS << "real: " << Lexer.getTok().getString();
- break;
- case AsmToken::String:
- OS << "string: " << Lexer.getTok().getString();
- break;
-
- case AsmToken::Amp: OS << "Amp"; break;
- case AsmToken::AmpAmp: OS << "AmpAmp"; break;
- case AsmToken::At: OS << "At"; break;
- case AsmToken::Caret: OS << "Caret"; break;
- case AsmToken::Colon: OS << "Colon"; break;
- case AsmToken::Comma: OS << "Comma"; break;
- case AsmToken::Dollar: OS << "Dollar"; break;
- case AsmToken::Dot: OS << "Dot"; break;
- case AsmToken::EndOfStatement: OS << "EndOfStatement"; break;
- case AsmToken::Eof: OS << "Eof"; break;
- case AsmToken::Equal: OS << "Equal"; break;
- case AsmToken::EqualEqual: OS << "EqualEqual"; break;
- case AsmToken::Exclaim: OS << "Exclaim"; break;
- case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break;
- case AsmToken::Greater: OS << "Greater"; break;
- case AsmToken::GreaterEqual: OS << "GreaterEqual"; break;
- case AsmToken::GreaterGreater: OS << "GreaterGreater"; break;
- case AsmToken::Hash: OS << "Hash"; break;
- case AsmToken::LBrac: OS << "LBrac"; break;
- case AsmToken::LCurly: OS << "LCurly"; break;
- case AsmToken::LParen: OS << "LParen"; break;
- case AsmToken::Less: OS << "Less"; break;
- case AsmToken::LessEqual: OS << "LessEqual"; break;
- case AsmToken::LessGreater: OS << "LessGreater"; break;
- case AsmToken::LessLess: OS << "LessLess"; break;
- case AsmToken::Minus: OS << "Minus"; break;
- case AsmToken::Percent: OS << "Percent"; break;
- case AsmToken::Pipe: OS << "Pipe"; break;
- case AsmToken::PipePipe: OS << "PipePipe"; break;
- case AsmToken::Plus: OS << "Plus"; break;
- case AsmToken::RBrac: OS << "RBrac"; break;
- case AsmToken::RCurly: OS << "RCurly"; break;
- case AsmToken::RParen: OS << "RParen"; break;
- case AsmToken::Slash: OS << "Slash"; break;
- case AsmToken::Star: OS << "Star"; break;
- case AsmToken::Tilde: OS << "Tilde"; break;
- case AsmToken::PercentCall16:
- OS << "PercentCall16";
- break;
- case AsmToken::PercentCall_Hi:
- OS << "PercentCall_Hi";
- break;
- case AsmToken::PercentCall_Lo:
- OS << "PercentCall_Lo";
- break;
- case AsmToken::PercentDtprel_Hi:
- OS << "PercentDtprel_Hi";
- break;
- case AsmToken::PercentDtprel_Lo:
- OS << "PercentDtprel_Lo";
- break;
- case AsmToken::PercentGot:
- OS << "PercentGot";
- break;
- case AsmToken::PercentGot_Disp:
- OS << "PercentGot_Disp";
- break;
- case AsmToken::PercentGot_Hi:
- OS << "PercentGot_Hi";
- break;
- case AsmToken::PercentGot_Lo:
- OS << "PercentGot_Lo";
- break;
- case AsmToken::PercentGot_Ofst:
- OS << "PercentGot_Ofst";
- break;
- case AsmToken::PercentGot_Page:
- OS << "PercentGot_Page";
- break;
- case AsmToken::PercentGottprel:
- OS << "PercentGottprel";
- break;
- case AsmToken::PercentGp_Rel:
- OS << "PercentGp_Rel";
- break;
- case AsmToken::PercentHi:
- OS << "PercentHi";
- break;
- case AsmToken::PercentHigher:
- OS << "PercentHigher";
- break;
- case AsmToken::PercentHighest:
- OS << "PercentHighest";
- break;
- case AsmToken::PercentLo:
- OS << "PercentLo";
- break;
- case AsmToken::PercentNeg:
- OS << "PercentNeg";
- break;
- case AsmToken::PercentPcrel_Hi:
- OS << "PercentPcrel_Hi";
- break;
- case AsmToken::PercentPcrel_Lo:
- OS << "PercentPcrel_Lo";
- break;
- case AsmToken::PercentTlsgd:
- OS << "PercentTlsgd";
- break;
- case AsmToken::PercentTlsldm:
- OS << "PercentTlsldm";
- break;
- case AsmToken::PercentTprel_Hi:
- OS << "PercentTprel_Hi";
- break;
- case AsmToken::PercentTprel_Lo:
- OS << "PercentTprel_Lo";
- break;
- }
-
- // Print the token string.
- OS << " (\"";
- OS.write_escaped(Tok.getString());
- OS << "\")\n";
}
return Error;
@@ -388,12 +259,13 @@ static int fillCommandLineSymbols(MCAsmParser &Parser) {
auto Val = Pair.second;
if (Sym.empty() || Val.empty()) {
- errs() << "error: defsym must be of the form: sym=value: " << I << "\n";
+ WithColor::error() << "defsym must be of the form: sym=value: " << I
+ << "\n";
return 1;
}
int64_t Value;
if (Val.getAsInteger(0, Value)) {
- errs() << "error: Value is not an integer: " << Val << "\n";
+ WithColor::error() << "value is not an integer: " << Val << "\n";
return 1;
}
Parser.getContext().setSymbolValue(Parser.getStreamer(), Sym, Value);
@@ -411,8 +283,8 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget,
TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
if (!TAP) {
- errs() << ProgName
- << ": error: this target does not support assembly parsing.\n";
+ WithColor::error(errs(), ProgName)
+ << "this target does not support assembly parsing.\n";
return 1;
}
@@ -428,10 +300,7 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget,
}
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
@@ -460,7 +329,8 @@ int main(int argc, char **argv) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
MemoryBuffer::getFileOrSTDIN(InputFilename);
if (std::error_code EC = BufferPtr.getError()) {
- errs() << InputFilename << ": " << EC.message() << '\n';
+ WithColor::error(errs(), ProgName)
+ << InputFilename << ": " << EC.message() << '\n';
return 1;
}
MemoryBuffer *Buffer = BufferPtr->get();
@@ -484,8 +354,8 @@ int main(int argc, char **argv) {
if (CompressDebugSections != DebugCompressionType::None) {
if (!zlib::isAvailable()) {
- errs() << ProgName
- << ": build tools with zlib to enable -compress-debug-sections";
+ WithColor::error(errs(), ProgName)
+ << "build tools with zlib to enable -compress-debug-sections";
return 1;
}
MAI->setCompressDebugSections(CompressDebugSections);
@@ -522,8 +392,24 @@ int main(int argc, char **argv) {
if (!sys::fs::current_path(CWD))
Ctx.setCompilationDir(CWD);
}
+ for (const auto &Arg : DebugPrefixMap) {
+ const auto &KV = StringRef(Arg).split('=');
+ Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
+ }
if (!MainFileName.empty())
Ctx.setMainFileName(MainFileName);
+ if (GenDwarfForAssembly && DwarfVersion >= 5) {
+ // DWARF v5 needs the root file as well as the compilation directory.
+ // If we find a '.file 0' directive that will supersede these values.
+ MD5 Hash;
+ MD5::MD5Result *Cksum =
+ (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
+ Hash.update(Buffer->getBuffer());
+ Hash.final(*Cksum);
+ Ctx.setMCLineTableRootFile(
+ /*CUID=*/0, Ctx.getCompilationDir(),
+ !MainFileName.empty() ? MainFileName : InputFilename, Cksum, None);
+ }
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -534,10 +420,21 @@ int main(int argc, char **argv) {
FeaturesStr = Features.getString();
}
- std::unique_ptr<ToolOutputFile> Out = GetOutputStream();
+ std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename);
if (!Out)
return 1;
+ std::unique_ptr<ToolOutputFile> DwoOut;
+ if (!SplitDwarfFile.empty()) {
+ if (FileType != OFT_ObjectFile) {
+ WithColor::error() << "dwo output only supported with object files\n";
+ return 1;
+ }
+ DwoOut = GetOutputStream(SplitDwarfFile);
+ if (!DwoOut)
+ return 1;
+ }
+
std::unique_ptr<buffer_ostream> BOS;
raw_pwrite_stream *OS = &Out->os();
std::unique_ptr<MCStreamer> Str;
@@ -552,8 +449,8 @@ int main(int argc, char **argv) {
*MAI, *MCII, *MRI);
if (!IP) {
- errs()
- << "error: unable to create instruction printer for target triple '"
+ WithColor::error()
+ << "unable to create instruction printer for target triple '"
<< TheTriple.normalize() << "' with assembly variant "
<< OutputAsmVariant << ".\n";
return 1;
@@ -563,16 +460,17 @@ int main(int argc, char **argv) {
IP->setPrintImmHex(PrintImmHex);
// Set up the AsmStreamer.
- MCCodeEmitter *CE = nullptr;
- MCAsmBackend *MAB = nullptr;
- if (ShowEncoding) {
- CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
- }
+ std::unique_ptr<MCCodeEmitter> CE;
+ if (ShowEncoding)
+ CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
+
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
auto FOut = llvm::make_unique<formatted_raw_ostream>(*OS);
- Str.reset(TheTarget->createAsmStreamer(
- Ctx, std::move(FOut), /*asmverbose*/ true,
- /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst));
+ Str.reset(
+ TheTarget->createAsmStreamer(Ctx, std::move(FOut), /*asmverbose*/ true,
+ /*useDwarfDirectory*/ true, IP,
+ std::move(CE), std::move(MAB), ShowInst));
} else if (FileType == OFT_Null) {
Str.reset(TheTarget->createNullStreamer(Ctx));
@@ -590,7 +488,9 @@ int main(int argc, char **argv) {
MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
Str.reset(TheTarget->createMCObjectStreamer(
- TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB), *OS,
+ TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
+ DwoOut ? MAB->createDwoObjectWriter(*OS, DwoOut->os())
+ : MAB->createObjectWriter(*OS),
std::unique_ptr<MCCodeEmitter>(CE), *STI, MCOptions.MCRelaxAll,
MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false));
@@ -598,6 +498,9 @@ int main(int argc, char **argv) {
Str->InitSections(true);
}
+ // Use Assembler information for parsing.
+ Str->setUseAssemblerInfoForParsing(true);
+
int Res = 1;
bool disassemble = false;
switch (Action) {
@@ -622,6 +525,10 @@ int main(int argc, char **argv) {
*Buffer, SrcMgr, Out->os());
// Keep output if no errors.
- if (Res == 0) Out->keep();
+ if (Res == 0) {
+ Out->keep();
+ if (DwoOut)
+ DwoOut->keep();
+ }
return Res;
}
diff --git a/contrib/llvm/tools/llvm-mca/CodeRegion.cpp b/contrib/llvm/tools/llvm-mca/CodeRegion.cpp
new file mode 100644
index 000000000000..896865996504
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/CodeRegion.cpp
@@ -0,0 +1,66 @@
+//===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements methods from the CodeRegions interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "CodeRegion.h"
+
+using namespace llvm;
+
+namespace mca {
+
+bool CodeRegion::isLocInRange(SMLoc Loc) const {
+ if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
+ return false;
+ if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
+ return false;
+ return true;
+}
+
+void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {
+ assert(!Regions.empty() && "Missing Default region");
+ const CodeRegion &CurrentRegion = *Regions.back();
+ if (CurrentRegion.startLoc().isValid() && !CurrentRegion.endLoc().isValid()) {
+ SM.PrintMessage(Loc, SourceMgr::DK_Warning,
+ "Ignoring invalid region start");
+ return;
+ }
+
+ // Remove the default region if there are user defined regions.
+ if (!CurrentRegion.startLoc().isValid())
+ Regions.erase(Regions.begin());
+ addRegion(Description, Loc);
+}
+
+void CodeRegions::endRegion(SMLoc Loc) {
+ assert(!Regions.empty() && "Missing Default region");
+ CodeRegion &CurrentRegion = *Regions.back();
+ if (CurrentRegion.endLoc().isValid()) {
+ SM.PrintMessage(Loc, SourceMgr::DK_Warning, "Ignoring invalid region end");
+ return;
+ }
+
+ CurrentRegion.setEndLocation(Loc);
+}
+
+void CodeRegions::addInstruction(std::unique_ptr<const MCInst> Instruction) {
+ const SMLoc &Loc = Instruction->getLoc();
+ const auto It =
+ std::find_if(Regions.rbegin(), Regions.rend(),
+ [Loc](const std::unique_ptr<CodeRegion> &Region) {
+ return Region->isLocInRange(Loc);
+ });
+ if (It != Regions.rend())
+ (*It)->addInstruction(std::move(Instruction));
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/CodeRegion.h b/contrib/llvm/tools/llvm-mca/CodeRegion.h
new file mode 100644
index 000000000000..7f0025e4884c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/CodeRegion.h
@@ -0,0 +1,131 @@
+//===-------------------------- CodeRegion.h -------------------*- C++ -* -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements class CodeRegion and CodeRegions.
+///
+/// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
+/// comment directives.
+///
+/// # LLVM-MCA-BEGIN foo
+/// ... ## asm
+/// # LLVM-MCA-END
+///
+/// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a
+/// new region of code.
+/// A comment starting with substring LLVM-MCA-END marks the end of the
+/// last-seen region of code.
+///
+/// Code regions are not allowed to overlap. Each region can have a optional
+/// description; internally, regions are described by a range of source
+/// locations (SMLoc objects).
+///
+/// An instruction (a MCInst) is added to a region R only if its location is in
+/// range [R.RangeStart, R.RangeEnd].
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H
+#define LLVM_TOOLS_LLVM_MCA_CODEREGION_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SourceMgr.h"
+#include <vector>
+
+namespace mca {
+
+/// A region of assembly code.
+///
+/// It identifies a sequence of machine instructions.
+class CodeRegion {
+ // An optional descriptor for this region.
+ llvm::StringRef Description;
+ // Instructions that form this region.
+ std::vector<std::unique_ptr<const llvm::MCInst>> Instructions;
+ // Source location range.
+ llvm::SMLoc RangeStart;
+ llvm::SMLoc RangeEnd;
+
+ CodeRegion(const CodeRegion &) = delete;
+ CodeRegion &operator=(const CodeRegion &) = delete;
+
+public:
+ CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start)
+ : Description(Desc), RangeStart(Start), RangeEnd() {}
+
+ void addInstruction(std::unique_ptr<const llvm::MCInst> Instruction) {
+ Instructions.emplace_back(std::move(Instruction));
+ }
+
+ llvm::SMLoc startLoc() const { return RangeStart; }
+ llvm::SMLoc endLoc() const { return RangeEnd; }
+
+ void setEndLocation(llvm::SMLoc End) { RangeEnd = End; }
+ bool empty() const { return Instructions.empty(); }
+ bool isLocInRange(llvm::SMLoc Loc) const;
+
+ const std::vector<std::unique_ptr<const llvm::MCInst>> &
+ getInstructions() const {
+ return Instructions;
+ }
+
+ llvm::StringRef getDescription() const { return Description; }
+};
+
+class CodeRegions {
+ // A source manager. Used by the tool to generate meaningful warnings.
+ llvm::SourceMgr &SM;
+
+ std::vector<std::unique_ptr<CodeRegion>> Regions;
+
+ // Construct a new region of code guarded by LLVM-MCA comments.
+ void addRegion(llvm::StringRef Description, llvm::SMLoc Loc) {
+ Regions.emplace_back(llvm::make_unique<CodeRegion>(Description, Loc));
+ }
+
+ CodeRegions(const CodeRegions &) = delete;
+ CodeRegions &operator=(const CodeRegions &) = delete;
+
+public:
+ typedef std::vector<std::unique_ptr<CodeRegion>>::iterator iterator;
+ typedef std::vector<std::unique_ptr<CodeRegion>>::const_iterator
+ const_iterator;
+
+ iterator begin() { return Regions.begin(); }
+ iterator end() { return Regions.end(); }
+ const_iterator begin() const { return Regions.cbegin(); }
+ const_iterator end() const { return Regions.cend(); }
+
+ void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+ void endRegion(llvm::SMLoc Loc);
+ void addInstruction(std::unique_ptr<const llvm::MCInst> Instruction);
+
+ CodeRegions(llvm::SourceMgr &S) : SM(S) {
+ // Create a default region for the input code sequence.
+ addRegion("Default", llvm::SMLoc());
+ }
+
+ const std::vector<std::unique_ptr<const llvm::MCInst>> &
+ getInstructionSequence(unsigned Idx) const {
+ return Regions[Idx]->getInstructions();
+ }
+
+ bool empty() const {
+ return std::all_of(Regions.begin(), Regions.end(),
+ [](const std::unique_ptr<CodeRegion> &Region) {
+ return Region->empty();
+ });
+ }
+};
+
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/Context.cpp b/contrib/llvm/tools/llvm-mca/Context.cpp
new file mode 100644
index 000000000000..685714e64b92
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Context.cpp
@@ -0,0 +1,63 @@
+//===---------------------------- Context.cpp -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a class for holding ownership of various simulated
+/// hardware units. A Context also provides a utility routine for constructing
+/// a default out-of-order pipeline with fetch, dispatch, execute, and retire
+/// stages).
+///
+//===----------------------------------------------------------------------===//
+
+#include "Context.h"
+#include "DispatchStage.h"
+#include "ExecuteStage.h"
+#include "FetchStage.h"
+#include "RegisterFile.h"
+#include "RetireControlUnit.h"
+#include "RetireStage.h"
+#include "Scheduler.h"
+
+namespace mca {
+
+using namespace llvm;
+
+std::unique_ptr<Pipeline>
+Context::createDefaultPipeline(const PipelineOptions &Opts, InstrBuilder &IB,
+ SourceMgr &SrcMgr) {
+ const MCSchedModel &SM = STI.getSchedModel();
+
+ // Create the hardware units defining the backend.
+ auto RCU = llvm::make_unique<RetireControlUnit>(SM);
+ auto PRF = llvm::make_unique<RegisterFile>(SM, MRI, Opts.RegisterFileSize);
+ auto HWS = llvm::make_unique<Scheduler>(
+ SM, Opts.LoadQueueSize, Opts.StoreQueueSize, Opts.AssumeNoAlias);
+
+ // Create the pipeline and its stages.
+ auto P = llvm::make_unique<Pipeline>();
+ auto F = llvm::make_unique<FetchStage>(IB, SrcMgr);
+ auto D = llvm::make_unique<DispatchStage>(
+ STI, MRI, Opts.RegisterFileSize, Opts.DispatchWidth, *RCU, *PRF, *HWS);
+ auto R = llvm::make_unique<RetireStage>(*RCU, *PRF);
+ auto E = llvm::make_unique<ExecuteStage>(*RCU, *HWS);
+
+ // Add the hardware to the context.
+ addHardwareUnit(std::move(RCU));
+ addHardwareUnit(std::move(PRF));
+ addHardwareUnit(std::move(HWS));
+
+ // Build the pipeline.
+ P->appendStage(std::move(F));
+ P->appendStage(std::move(D));
+ P->appendStage(std::move(R));
+ P->appendStage(std::move(E));
+ return P;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/Context.h b/contrib/llvm/tools/llvm-mca/Context.h
new file mode 100644
index 000000000000..cf483fa7b37d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Context.h
@@ -0,0 +1,68 @@
+//===---------------------------- Context.h ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a class for holding ownership of various simulated
+/// hardware units. A Context also provides a utility routine for constructing
+/// a default out-of-order pipeline with fetch, dispatch, execute, and retire
+/// stages).
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_CONTEXT_H
+#define LLVM_TOOLS_LLVM_MCA_CONTEXT_H
+#include "HardwareUnit.h"
+#include "InstrBuilder.h"
+#include "Pipeline.h"
+#include "SourceMgr.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSchedule.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include <memory>
+
+namespace mca {
+
+/// This is a convenience struct to hold the parameters necessary for creating
+/// the pre-built "default" out-of-order pipeline.
+struct PipelineOptions {
+ PipelineOptions(unsigned DW, unsigned RFS, unsigned LQS, unsigned SQS,
+ bool NoAlias)
+ : DispatchWidth(DW), RegisterFileSize(RFS), LoadQueueSize(LQS),
+ StoreQueueSize(SQS), AssumeNoAlias(NoAlias) {}
+ unsigned DispatchWidth;
+ unsigned RegisterFileSize;
+ unsigned LoadQueueSize;
+ unsigned StoreQueueSize;
+ bool AssumeNoAlias;
+};
+
+class Context {
+ llvm::SmallVector<std::unique_ptr<HardwareUnit>, 4> Hardware;
+ const llvm::MCRegisterInfo &MRI;
+ const llvm::MCSubtargetInfo &STI;
+
+public:
+ Context(const llvm::MCRegisterInfo &R, const llvm::MCSubtargetInfo &S)
+ : MRI(R), STI(S) {}
+ Context(const Context &C) = delete;
+ Context &operator=(const Context &C) = delete;
+
+ void addHardwareUnit(std::unique_ptr<HardwareUnit> H) {
+ Hardware.push_back(std::move(H));
+ }
+
+ /// Construct a basic pipeline for simulating an out-of-order pipeline.
+ /// This pipeline consists of Fetch, Dispatch, Execute, and Retire stages.
+ std::unique_ptr<Pipeline> createDefaultPipeline(const PipelineOptions &Opts,
+ InstrBuilder &IB,
+ SourceMgr &SrcMgr);
+};
+
+} // namespace mca
+#endif // LLVM_TOOLS_LLVM_MCA_CONTEXT_H
diff --git a/contrib/llvm/tools/llvm-mca/DispatchStage.cpp b/contrib/llvm/tools/llvm-mca/DispatchStage.cpp
new file mode 100644
index 000000000000..1f508886c298
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/DispatchStage.cpp
@@ -0,0 +1,153 @@
+//===--------------------- DispatchStage.cpp --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file models the dispatch component of an instruction pipeline.
+///
+/// The DispatchStage is responsible for updating instruction dependencies
+/// and communicating to the simulated instruction scheduler that an instruction
+/// is ready to be scheduled for execution.
+///
+//===----------------------------------------------------------------------===//
+
+#include "DispatchStage.h"
+#include "HWEventListener.h"
+#include "Scheduler.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
+ ArrayRef<unsigned> UsedRegs) {
+ LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: #" << IR << '\n');
+ notifyEvent<HWInstructionEvent>(HWInstructionDispatchedEvent(IR, UsedRegs));
+}
+
+bool DispatchStage::checkPRF(const InstRef &IR) {
+ SmallVector<unsigned, 4> RegDefs;
+ for (const std::unique_ptr<WriteState> &RegDef :
+ IR.getInstruction()->getDefs())
+ RegDefs.emplace_back(RegDef->getRegisterID());
+
+ const unsigned RegisterMask = PRF.isAvailable(RegDefs);
+ // A mask with all zeroes means: register files are available.
+ if (RegisterMask) {
+ notifyEvent<HWStallEvent>(
+ HWStallEvent(HWStallEvent::RegisterFileStall, IR));
+ return false;
+ }
+
+ return true;
+}
+
+bool DispatchStage::checkRCU(const InstRef &IR) {
+ const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
+ if (RCU.isAvailable(NumMicroOps))
+ return true;
+ notifyEvent<HWStallEvent>(
+ HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
+ return false;
+}
+
+bool DispatchStage::checkScheduler(const InstRef &IR) {
+ HWStallEvent::GenericEventType Event;
+ const bool Ready = SC.canBeDispatched(IR, Event);
+ if (!Ready)
+ notifyEvent<HWStallEvent>(HWStallEvent(Event, IR));
+ return Ready;
+}
+
+void DispatchStage::updateRAWDependencies(ReadState &RS,
+ const MCSubtargetInfo &STI) {
+ SmallVector<WriteRef, 4> DependentWrites;
+
+ collectWrites(DependentWrites, RS.getRegisterID());
+ RS.setDependentWrites(DependentWrites.size());
+ // We know that this read depends on all the writes in DependentWrites.
+ // For each write, check if we have ReadAdvance information, and use it
+ // to figure out in how many cycles this read becomes available.
+ const ReadDescriptor &RD = RS.getDescriptor();
+ const MCSchedModel &SM = STI.getSchedModel();
+ const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
+ for (WriteRef &WR : DependentWrites) {
+ WriteState &WS = *WR.getWriteState();
+ unsigned WriteResID = WS.getWriteResourceID();
+ int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
+ WS.addUser(&RS, ReadAdvance);
+ }
+}
+
+void DispatchStage::dispatch(InstRef IR) {
+ assert(!CarryOver && "Cannot dispatch another instruction!");
+ Instruction &IS = *IR.getInstruction();
+ const InstrDesc &Desc = IS.getDesc();
+ const unsigned NumMicroOps = Desc.NumMicroOps;
+ if (NumMicroOps > DispatchWidth) {
+ assert(AvailableEntries == DispatchWidth);
+ AvailableEntries = 0;
+ CarryOver = NumMicroOps - DispatchWidth;
+ } else {
+ assert(AvailableEntries >= NumMicroOps);
+ AvailableEntries -= NumMicroOps;
+ }
+
+ // A dependency-breaking instruction doesn't have to wait on the register
+ // input operands, and it is often optimized at register renaming stage.
+ // Update RAW dependencies if this instruction is not a dependency-breaking
+ // instruction. A dependency-breaking instruction is a zero-latency
+ // instruction that doesn't consume hardware resources.
+ // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
+ bool IsDependencyBreaking = IS.isDependencyBreaking();
+ for (std::unique_ptr<ReadState> &RS : IS.getUses())
+ if (RS->isImplicitRead() || !IsDependencyBreaking)
+ updateRAWDependencies(*RS, STI);
+
+ // By default, a dependency-breaking zero-latency instruction is expected to
+ // be optimized at register renaming stage. That means, no physical register
+ // is allocated to the instruction.
+ bool ShouldAllocateRegisters =
+ !(Desc.isZeroLatency() && IsDependencyBreaking);
+ SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
+ for (std::unique_ptr<WriteState> &WS : IS.getDefs()) {
+ PRF.addRegisterWrite(WriteRef(IR.first, WS.get()), RegisterFiles,
+ ShouldAllocateRegisters);
+ }
+
+ // Reserve slots in the RCU, and notify the instruction that it has been
+ // dispatched to the schedulers for execution.
+ IS.dispatch(RCU.reserveSlot(IR, NumMicroOps));
+
+ // Notify listeners of the "instruction dispatched" event.
+ notifyInstructionDispatched(IR, RegisterFiles);
+}
+
+void DispatchStage::cycleStart() {
+ AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
+ CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
+}
+
+bool DispatchStage::execute(InstRef &IR) {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
+ return false;
+ dispatch(IR);
+ return true;
+}
+
+#ifndef NDEBUG
+void DispatchStage::dump() const {
+ PRF.dump();
+ RCU.dump();
+}
+#endif
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/DispatchStage.h b/contrib/llvm/tools/llvm-mca/DispatchStage.h
new file mode 100644
index 000000000000..4262a241c08c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/DispatchStage.h
@@ -0,0 +1,106 @@
+//===----------------------- DispatchStage.h --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file models the dispatch component of an instruction pipeline.
+///
+/// The DispatchStage is responsible for updating instruction dependencies
+/// and communicating to the simulated instruction scheduler that an instruction
+/// is ready to be scheduled for execution.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_DISPATCH_STAGE_H
+#define LLVM_TOOLS_LLVM_MCA_DISPATCH_STAGE_H
+
+#include "HWEventListener.h"
+#include "Instruction.h"
+#include "RegisterFile.h"
+#include "RetireControlUnit.h"
+#include "Stage.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+namespace mca {
+
+class Scheduler;
+
+// Implements the hardware dispatch logic.
+//
+// This class is responsible for the dispatch stage, in which instructions are
+// dispatched in groups to the Scheduler. An instruction can be dispatched if
+// the following conditions are met:
+// 1) There are enough entries in the reorder buffer (see class
+// RetireControlUnit) to write the opcodes associated with the instruction.
+// 2) There are enough physical registers to rename output register operands.
+// 3) There are enough entries available in the used buffered resource(s).
+//
+// The number of micro opcodes that can be dispatched in one cycle is limited by
+// the value of field 'DispatchWidth'. A "dynamic dispatch stall" occurs when
+// processor resources are not available. Dispatch stall events are counted
+// during the entire execution of the code, and displayed by the performance
+// report when flag '-dispatch-stats' is specified.
+//
+// If the number of micro opcodes exceedes DispatchWidth, then the instruction
+// is dispatched in multiple cycles.
+class DispatchStage : public Stage {
+ unsigned DispatchWidth;
+ unsigned AvailableEntries;
+ unsigned CarryOver;
+ const llvm::MCSubtargetInfo &STI;
+ RetireControlUnit &RCU;
+ RegisterFile &PRF;
+ Scheduler &SC;
+
+ bool checkRCU(const InstRef &IR);
+ bool checkPRF(const InstRef &IR);
+ bool checkScheduler(const InstRef &IR);
+ void dispatch(InstRef IR);
+ void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI);
+
+ void notifyInstructionDispatched(const InstRef &IR,
+ llvm::ArrayRef<unsigned> UsedPhysRegs);
+
+ bool isAvailable(unsigned NumEntries) const {
+ return NumEntries <= AvailableEntries || AvailableEntries == DispatchWidth;
+ }
+
+ bool canDispatch(const InstRef &IR) {
+ assert(isAvailable(IR.getInstruction()->getDesc().NumMicroOps));
+ return checkRCU(IR) && checkPRF(IR) && checkScheduler(IR);
+ }
+
+ void collectWrites(llvm::SmallVectorImpl<WriteRef> &Vec,
+ unsigned RegID) const {
+ return PRF.collectWrites(Vec, RegID);
+ }
+
+public:
+ DispatchStage(const llvm::MCSubtargetInfo &Subtarget,
+ const llvm::MCRegisterInfo &MRI, unsigned RegisterFileSize,
+ unsigned MaxDispatchWidth, RetireControlUnit &R,
+ RegisterFile &F, Scheduler &Sched)
+ : DispatchWidth(MaxDispatchWidth), AvailableEntries(MaxDispatchWidth),
+ CarryOver(0U), STI(Subtarget), RCU(R), PRF(F), SC(Sched) {}
+
+ // We can always try to dispatch, so returning false is okay in this case.
+ // The retire stage, which controls the RCU, might have items to complete but
+ // RetireStage::hasWorkToComplete will check for that case.
+ virtual bool hasWorkToComplete() const override final { return false; }
+ virtual void cycleStart() override final;
+ virtual bool execute(InstRef &IR) override final;
+ void notifyDispatchStall(const InstRef &IR, unsigned EventType);
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_DISPATCH_STAGE_H
diff --git a/contrib/llvm/tools/llvm-mca/DispatchStatistics.cpp b/contrib/llvm/tools/llvm-mca/DispatchStatistics.cpp
new file mode 100644
index 000000000000..4bddbef9a0c8
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/DispatchStatistics.cpp
@@ -0,0 +1,71 @@
+//===--------------------- DispatchStatistics.cpp ---------------------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the DispatchStatistics interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "DispatchStatistics.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+namespace mca {
+
+void DispatchStatistics::onEvent(const HWStallEvent &Event) {
+ if (Event.Type < HWStallEvent::LastGenericEvent)
+ HWStalls[Event.Type]++;
+}
+
+void DispatchStatistics::onEvent(const HWInstructionEvent &Event) {
+ if (Event.Type == HWInstructionEvent::Dispatched)
+ ++NumDispatched;
+}
+
+void DispatchStatistics::printDispatchHistogram(llvm::raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ TempStream << "\n\nDispatch Logic - "
+ << "number of cycles where we saw N instructions dispatched:\n";
+ TempStream << "[# dispatched], [# cycles]\n";
+ for (const std::pair<unsigned, unsigned> &Entry : DispatchGroupSizePerCycle) {
+ TempStream << " " << Entry.first << ", " << Entry.second
+ << " ("
+ << format("%.1f", ((double)Entry.second / NumCycles) * 100.0)
+ << "%)\n";
+ }
+
+ TempStream.flush();
+ OS << Buffer;
+}
+
+void DispatchStatistics::printDispatchStalls(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ TempStream << "\n\nDynamic Dispatch Stall Cycles:\n";
+ TempStream << "RAT - Register unavailable: "
+ << HWStalls[HWStallEvent::RegisterFileStall];
+ TempStream << "\nRCU - Retire tokens unavailable: "
+ << HWStalls[HWStallEvent::RetireControlUnitStall];
+ TempStream << "\nSCHEDQ - Scheduler full: "
+ << HWStalls[HWStallEvent::SchedulerQueueFull];
+ TempStream << "\nLQ - Load queue full: "
+ << HWStalls[HWStallEvent::LoadQueueFull];
+ TempStream << "\nSQ - Store queue full: "
+ << HWStalls[HWStallEvent::StoreQueueFull];
+ TempStream << "\nGROUP - Static restrictions on the dispatch group: "
+ << HWStalls[HWStallEvent::DispatchGroupStall];
+ TempStream << '\n';
+ TempStream.flush();
+ OS << Buffer;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/DispatchStatistics.h b/contrib/llvm/tools/llvm-mca/DispatchStatistics.h
new file mode 100644
index 000000000000..1e389d54766b
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/DispatchStatistics.h
@@ -0,0 +1,84 @@
+//===--------------------- DispatchStatistics.h -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements a view that prints a few statistics related to the
+/// dispatch logic. It collects and analyzes instruction dispatch events as
+/// well as static/dynamic dispatch stall events.
+///
+/// Example:
+/// ========
+///
+/// Dynamic Dispatch Stall Cycles:
+/// RAT - Register unavailable: 0
+/// RCU - Retire tokens unavailable: 0
+/// SCHEDQ - Scheduler full: 42
+/// LQ - Load queue full: 0
+/// SQ - Store queue full: 0
+/// GROUP - Static restrictions on the dispatch group: 0
+///
+///
+/// Dispatch Logic - number of cycles where we saw N instructions dispatched:
+/// [# dispatched], [# cycles]
+/// 0, 15 (11.5%)
+/// 2, 4 (3.1%)
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_DISPATCHVIEW_H
+#define LLVM_TOOLS_LLVM_MCA_DISPATCHVIEW_H
+
+#include "View.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include <map>
+
+namespace mca {
+
+class DispatchStatistics : public View {
+ unsigned NumDispatched;
+ unsigned NumCycles;
+
+ // Counts dispatch stall events caused by unavailability of resources. There
+ // is one counter for every generic stall kind (see class HWStallEvent).
+ llvm::SmallVector<unsigned, 8> HWStalls;
+
+ using Histogram = std::map<unsigned, unsigned>;
+ Histogram DispatchGroupSizePerCycle;
+
+ void updateHistograms() {
+ DispatchGroupSizePerCycle[NumDispatched]++;
+ NumDispatched = 0;
+ }
+
+ void printDispatchHistogram(llvm::raw_ostream &OS) const;
+
+ void printDispatchStalls(llvm::raw_ostream &OS) const;
+
+public:
+ DispatchStatistics()
+ : NumDispatched(0), NumCycles(0),
+ HWStalls(HWStallEvent::LastGenericEvent) {}
+
+ void onEvent(const HWStallEvent &Event) override;
+
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ void onCycleBegin() override { NumCycles++; }
+
+ void onCycleEnd() override { updateHistograms(); }
+
+ void printView(llvm::raw_ostream &OS) const override {
+ printDispatchStalls(OS);
+ printDispatchHistogram(OS);
+ }
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/ExecuteStage.cpp b/contrib/llvm/tools/llvm-mca/ExecuteStage.cpp
new file mode 100644
index 000000000000..437f864b072c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/ExecuteStage.cpp
@@ -0,0 +1,210 @@
+//===---------------------- ExecuteStage.cpp --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the execution stage of an instruction pipeline.
+///
+/// The ExecuteStage is responsible for managing the hardware scheduler
+/// and issuing notifications that an instruction has been executed.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ExecuteStage.h"
+#include "Scheduler.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+using namespace llvm;
+
+// Reclaim the simulated resources used by the scheduler.
+void ExecuteStage::reclaimSchedulerResources() {
+ SmallVector<ResourceRef, 8> ResourcesFreed;
+ HWS.reclaimSimulatedResources(ResourcesFreed);
+ for (const ResourceRef &RR : ResourcesFreed)
+ notifyResourceAvailable(RR);
+}
+
+// Update the scheduler's instruction queues.
+void ExecuteStage::updateSchedulerQueues() {
+ SmallVector<InstRef, 4> InstructionIDs;
+ HWS.updateIssuedQueue(InstructionIDs);
+ for (const InstRef &IR : InstructionIDs)
+ notifyInstructionExecuted(IR);
+ InstructionIDs.clear();
+
+ HWS.updatePendingQueue(InstructionIDs);
+ for (const InstRef &IR : InstructionIDs)
+ notifyInstructionReady(IR);
+}
+
+// Issue instructions that are waiting in the scheduler's ready queue.
+void ExecuteStage::issueReadyInstructions() {
+ SmallVector<InstRef, 4> InstructionIDs;
+ InstRef IR = HWS.select();
+ while (IR.isValid()) {
+ SmallVector<std::pair<ResourceRef, double>, 4> Used;
+ HWS.issueInstruction(IR, Used);
+
+ // Reclaim instruction resources and perform notifications.
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ notifyReleasedBuffers(Desc.Buffers);
+ notifyInstructionIssued(IR, Used);
+ if (IR.getInstruction()->isExecuted())
+ notifyInstructionExecuted(IR);
+
+ // Instructions that have been issued during this cycle might have unblocked
+ // other dependent instructions. Dependent instructions may be issued during
+ // this same cycle if operands have ReadAdvance entries. Promote those
+ // instructions to the ReadyQueue and tell to the caller that we need
+ // another round of 'issue()'.
+ HWS.promoteToReadyQueue(InstructionIDs);
+ for (const InstRef &I : InstructionIDs)
+ notifyInstructionReady(I);
+ InstructionIDs.clear();
+
+ // Select the next instruction to issue.
+ IR = HWS.select();
+ }
+}
+
+// The following routine is the maintenance routine of the ExecuteStage.
+// It is responsible for updating the hardware scheduler (HWS), including
+// reclaiming the HWS's simulated hardware resources, as well as updating the
+// HWS's queues.
+//
+// This routine also processes the instructions that are ready for issuance.
+// These instructions are managed by the HWS's ready queue and can be accessed
+// via the Scheduler::select() routine.
+//
+// Notifications are issued to this stage's listeners when instructions are
+// moved between the HWS's queues. In particular, when an instruction becomes
+// ready or executed.
+void ExecuteStage::cycleStart() {
+ reclaimSchedulerResources();
+ updateSchedulerQueues();
+ issueReadyInstructions();
+}
+
+// Schedule the instruction for execution on the hardware.
+bool ExecuteStage::execute(InstRef &IR) {
+#ifndef NDEBUG
+ // Ensure that the HWS has not stored this instruction in its queues.
+ HWS.sanityCheck(IR);
+#endif
+ // Reserve a slot in each buffered resource. Also, mark units with
+ // BufferSize=0 as reserved. Resources with a buffer size of zero will only
+ // be released after MCIS is issued, and all the ResourceCycles for those
+ // units have been consumed.
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ HWS.reserveBuffers(Desc.Buffers);
+ notifyReservedBuffers(Desc.Buffers);
+
+ // Obtain a slot in the LSU. If we cannot reserve resources, return true, so
+ // that succeeding stages can make progress.
+ if (!HWS.reserveResources(IR))
+ return true;
+
+ // If we did not return early, then the scheduler is ready for execution.
+ notifyInstructionReady(IR);
+
+ // Don't add a zero-latency instruction to the Wait or Ready queue.
+ // A zero-latency instruction doesn't consume any scheduler resources. That is
+ // because it doesn't need to be executed, and it is often removed at register
+ // renaming stage. For example, register-register moves are often optimized at
+ // register renaming stage by simply updating register aliases. On some
+ // targets, zero-idiom instructions (for example: a xor that clears the value
+ // of a register) are treated specially, and are often eliminated at register
+ // renaming stage.
+ //
+ // Instructions that use an in-order dispatch/issue processor resource must be
+ // issued immediately to the pipeline(s). Any other in-order buffered
+ // resources (i.e. BufferSize=1) is consumed.
+ //
+ // If we cannot issue immediately, the HWS will add IR to its ready queue for
+ // execution later, so we must return early here.
+ if (!HWS.issueImmediately(IR))
+ return true;
+
+ LLVM_DEBUG(dbgs() << "[SCHEDULER] Instruction #" << IR
+ << " issued immediately\n");
+
+ // Issue IR. The resources for this issuance will be placed in 'Used.'
+ SmallVector<std::pair<ResourceRef, double>, 4> Used;
+ HWS.issueInstruction(IR, Used);
+
+ // Perform notifications.
+ notifyReleasedBuffers(Desc.Buffers);
+ notifyInstructionIssued(IR, Used);
+ if (IR.getInstruction()->isExecuted())
+ notifyInstructionExecuted(IR);
+
+ return true;
+}
+
+void ExecuteStage::notifyInstructionExecuted(const InstRef &IR) {
+ HWS.onInstructionExecuted(IR);
+ LLVM_DEBUG(dbgs() << "[E] Instruction Executed: #" << IR << '\n');
+ notifyEvent<HWInstructionEvent>(
+ HWInstructionEvent(HWInstructionEvent::Executed, IR));
+ RCU.onInstructionExecuted(IR.getInstruction()->getRCUTokenID());
+}
+
+void ExecuteStage::notifyInstructionReady(const InstRef &IR) {
+ LLVM_DEBUG(dbgs() << "[E] Instruction Ready: #" << IR << '\n');
+ notifyEvent<HWInstructionEvent>(
+ HWInstructionEvent(HWInstructionEvent::Ready, IR));
+}
+
+void ExecuteStage::notifyResourceAvailable(const ResourceRef &RR) {
+ LLVM_DEBUG(dbgs() << "[E] Resource Available: [" << RR.first << '.'
+ << RR.second << "]\n");
+ for (HWEventListener *Listener : getListeners())
+ Listener->onResourceAvailable(RR);
+}
+
+void ExecuteStage::notifyInstructionIssued(
+ const InstRef &IR, ArrayRef<std::pair<ResourceRef, double>> Used) {
+ LLVM_DEBUG({
+ dbgs() << "[E] Instruction Issued: #" << IR << '\n';
+ for (const std::pair<ResourceRef, unsigned> &Resource : Used) {
+ dbgs() << "[E] Resource Used: [" << Resource.first.first << '.'
+ << Resource.first.second << "], ";
+ dbgs() << "cycles: " << Resource.second << '\n';
+ }
+ });
+ notifyEvent<HWInstructionEvent>(HWInstructionIssuedEvent(IR, Used));
+}
+
+void ExecuteStage::notifyReservedBuffers(ArrayRef<uint64_t> Buffers) {
+ if (Buffers.empty())
+ return;
+
+ SmallVector<unsigned, 4> BufferIDs(Buffers.begin(), Buffers.end());
+ std::transform(Buffers.begin(), Buffers.end(), BufferIDs.begin(),
+ [&](uint64_t Op) { return HWS.getResourceID(Op); });
+ for (HWEventListener *Listener : getListeners())
+ Listener->onReservedBuffers(BufferIDs);
+}
+
+void ExecuteStage::notifyReleasedBuffers(ArrayRef<uint64_t> Buffers) {
+ if (Buffers.empty())
+ return;
+
+ SmallVector<unsigned, 4> BufferIDs(Buffers.begin(), Buffers.end());
+ std::transform(Buffers.begin(), Buffers.end(), BufferIDs.begin(),
+ [&](uint64_t Op) { return HWS.getResourceID(Op); });
+ for (HWEventListener *Listener : getListeners())
+ Listener->onReleasedBuffers(BufferIDs);
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/ExecuteStage.h b/contrib/llvm/tools/llvm-mca/ExecuteStage.h
new file mode 100644
index 000000000000..4914a9373e7c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/ExecuteStage.h
@@ -0,0 +1,67 @@
+//===---------------------- ExecuteStage.h ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the execution stage of an instruction pipeline.
+///
+/// The ExecuteStage is responsible for managing the hardware scheduler
+/// and issuing notifications that an instruction has been executed.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_EXECUTE_STAGE_H
+#define LLVM_TOOLS_LLVM_MCA_EXECUTE_STAGE_H
+
+#include "Instruction.h"
+#include "RetireControlUnit.h"
+#include "Scheduler.h"
+#include "Stage.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace mca {
+
+class ExecuteStage : public Stage {
+ // Owner will go away when we move listeners/eventing to the stages.
+ RetireControlUnit &RCU;
+ Scheduler &HWS;
+
+ // The following routines are used to maintain the HWS.
+ void reclaimSchedulerResources();
+ void updateSchedulerQueues();
+ void issueReadyInstructions();
+
+public:
+ ExecuteStage(RetireControlUnit &R, Scheduler &S) : Stage(), RCU(R), HWS(S) {}
+ ExecuteStage(const ExecuteStage &Other) = delete;
+ ExecuteStage &operator=(const ExecuteStage &Other) = delete;
+
+ // The ExecuteStage will always complete all of its work per call to
+ // execute(), so it is never left in a 'to-be-processed' state.
+ virtual bool hasWorkToComplete() const override final { return false; }
+
+ virtual void cycleStart() override final;
+ virtual bool execute(InstRef &IR) override final;
+
+ void
+ notifyInstructionIssued(const InstRef &IR,
+ llvm::ArrayRef<std::pair<ResourceRef, double>> Used);
+ void notifyInstructionExecuted(const InstRef &IR);
+ void notifyInstructionReady(const InstRef &IR);
+ void notifyResourceAvailable(const ResourceRef &RR);
+
+ // Notify listeners that buffered resources were consumed.
+ void notifyReservedBuffers(llvm::ArrayRef<uint64_t> Buffers);
+
+ // Notify listeners that buffered resources were freed.
+ void notifyReleasedBuffers(llvm::ArrayRef<uint64_t> Buffers);
+};
+
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_EXECUTE_STAGE_H
diff --git a/contrib/llvm/tools/llvm-mca/FetchStage.cpp b/contrib/llvm/tools/llvm-mca/FetchStage.cpp
new file mode 100644
index 000000000000..3da117c0abc1
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/FetchStage.cpp
@@ -0,0 +1,46 @@
+//===---------------------- FetchStage.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the Fetch stage of an instruction pipeline. Its sole
+/// purpose in life is to produce instructions for the rest of the pipeline.
+///
+//===----------------------------------------------------------------------===//
+
+#include "FetchStage.h"
+
+namespace mca {
+
+bool FetchStage::hasWorkToComplete() const { return SM.hasNext(); }
+
+bool FetchStage::execute(InstRef &IR) {
+ if (!SM.hasNext())
+ return false;
+ const SourceRef SR = SM.peekNext();
+ std::unique_ptr<Instruction> I = IB.createInstruction(*SR.second);
+ IR = InstRef(SR.first, I.get());
+ Instructions[IR.getSourceIndex()] = std::move(I);
+ return true;
+}
+
+void FetchStage::postExecute() { SM.updateNext(); }
+
+void FetchStage::cycleEnd() {
+ // Find the first instruction which hasn't been retired.
+ const InstMap::iterator It =
+ llvm::find_if(Instructions, [](const InstMap::value_type &KeyValuePair) {
+ return !KeyValuePair.second->isRetired();
+ });
+
+ // Erase instructions up to the first that hasn't been retired.
+ if (It != Instructions.begin())
+ Instructions.erase(Instructions.begin(), It);
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/FetchStage.h b/contrib/llvm/tools/llvm-mca/FetchStage.h
new file mode 100644
index 000000000000..620075d24fea
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/FetchStage.h
@@ -0,0 +1,45 @@
+//===---------------------- FetchStage.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the Fetch stage of an instruction pipeline. Its sole
+/// purpose in life is to produce instructions for the rest of the pipeline.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_FETCH_STAGE_H
+#define LLVM_TOOLS_LLVM_MCA_FETCH_STAGE_H
+
+#include "InstrBuilder.h"
+#include "SourceMgr.h"
+#include "Stage.h"
+#include <map>
+
+namespace mca {
+
+class FetchStage : public Stage {
+ using InstMap = std::map<unsigned, std::unique_ptr<Instruction>>;
+ InstMap Instructions;
+ InstrBuilder &IB;
+ SourceMgr &SM;
+
+public:
+ FetchStage(InstrBuilder &IB, SourceMgr &SM) : IB(IB), SM(SM) {}
+ FetchStage(const FetchStage &Other) = delete;
+ FetchStage &operator=(const FetchStage &Other) = delete;
+
+ bool hasWorkToComplete() const override final;
+ bool execute(InstRef &IR) override final;
+ void postExecute() override final;
+ void cycleEnd() override final;
+};
+
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_FETCH_STAGE_H
diff --git a/contrib/llvm/tools/llvm-mca/HWEventListener.cpp b/contrib/llvm/tools/llvm-mca/HWEventListener.cpp
new file mode 100644
index 000000000000..f27a04a9a980
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/HWEventListener.cpp
@@ -0,0 +1,21 @@
+//===----------------------- HWEventListener.cpp ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a vtable anchor for class HWEventListener.
+///
+//===----------------------------------------------------------------------===//
+
+#include "HWEventListener.h"
+
+namespace mca {
+
+// Anchor the vtable here.
+void HWEventListener::anchor() {}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/HWEventListener.h b/contrib/llvm/tools/llvm-mca/HWEventListener.h
new file mode 100644
index 000000000000..aa3e6dcf19a0
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/HWEventListener.h
@@ -0,0 +1,141 @@
+//===----------------------- HWEventListener.h ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the main interface for hardware event listeners.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_HWEVENTLISTENER_H
+#define LLVM_TOOLS_LLVM_MCA_HWEVENTLISTENER_H
+
+#include "Instruction.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <utility>
+
+namespace mca {
+
+// An HWInstructionEvent represents state changes of instructions that
+// listeners might be interested in. Listeners can choose to ignore any event
+// they are not interested in.
+class HWInstructionEvent {
+public:
+ // This is the list of event types that are shared by all targets, that
+ // generic subtarget-agnostic classes (e.g., Pipeline, HWInstructionEvent,
+ // ...) and generic Views can manipulate.
+ // Subtargets are free to define additional event types, that are goin to be
+ // handled by generic components as opaque values, but can still be
+ // emitted by subtarget-specific pipeline stages (e.g., ExecuteStage,
+ // DispatchStage, ...) and interpreted by subtarget-specific EventListener
+ // implementations.
+ enum GenericEventType {
+ Invalid = 0,
+ // Events generated by the Retire Control Unit.
+ Retired,
+ // Events generated by the Scheduler.
+ Ready,
+ Issued,
+ Executed,
+ // Events generated by the Dispatch logic.
+ Dispatched,
+
+ LastGenericEventType,
+ };
+
+ HWInstructionEvent(unsigned type, const InstRef &Inst)
+ : Type(type), IR(Inst) {}
+
+ // The event type. The exact meaning depends on the subtarget.
+ const unsigned Type;
+
+ // The instruction this event was generated for.
+ const InstRef &IR;
+};
+
+class HWInstructionIssuedEvent : public HWInstructionEvent {
+public:
+ using ResourceRef = std::pair<uint64_t, uint64_t>;
+ HWInstructionIssuedEvent(const InstRef &IR,
+ llvm::ArrayRef<std::pair<ResourceRef, double>> UR)
+ : HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {}
+
+ llvm::ArrayRef<std::pair<ResourceRef, double>> UsedResources;
+};
+
+class HWInstructionDispatchedEvent : public HWInstructionEvent {
+public:
+ HWInstructionDispatchedEvent(const InstRef &IR, llvm::ArrayRef<unsigned> Regs)
+ : HWInstructionEvent(HWInstructionEvent::Dispatched, IR),
+ UsedPhysRegs(Regs) {}
+ // Number of physical register allocated for this instruction. There is one
+ // entry per register file.
+ llvm::ArrayRef<unsigned> UsedPhysRegs;
+};
+
+class HWInstructionRetiredEvent : public HWInstructionEvent {
+public:
+ HWInstructionRetiredEvent(const InstRef &IR, llvm::ArrayRef<unsigned> Regs)
+ : HWInstructionEvent(HWInstructionEvent::Retired, IR),
+ FreedPhysRegs(Regs) {}
+ // Number of register writes that have been architecturally committed. There
+ // is one entry per register file.
+ llvm::ArrayRef<unsigned> FreedPhysRegs;
+};
+
+// A HWStallEvent represents a pipeline stall caused by the lack of hardware
+// resources.
+class HWStallEvent {
+public:
+ enum GenericEventType {
+ Invalid = 0,
+ // Generic stall events generated by the DispatchStage.
+ RegisterFileStall,
+ RetireControlUnitStall,
+ // Generic stall events generated by the Scheduler.
+ DispatchGroupStall,
+ SchedulerQueueFull,
+ LoadQueueFull,
+ StoreQueueFull,
+ LastGenericEvent
+ };
+
+ HWStallEvent(unsigned type, const InstRef &Inst) : Type(type), IR(Inst) {}
+
+ // The exact meaning of the stall event type depends on the subtarget.
+ const unsigned Type;
+
+ // The instruction this event was generated for.
+ const InstRef &IR;
+};
+
+class HWEventListener {
+public:
+ // Generic events generated by the pipeline.
+ virtual void onCycleBegin() {}
+ virtual void onCycleEnd() {}
+
+ virtual void onEvent(const HWInstructionEvent &Event) {}
+ virtual void onEvent(const HWStallEvent &Event) {}
+
+ using ResourceRef = std::pair<uint64_t, uint64_t>;
+ virtual void onResourceAvailable(const ResourceRef &RRef) {}
+
+ // Events generated by the Scheduler when buffered resources are
+ // consumed/freed.
+ virtual void onReservedBuffers(llvm::ArrayRef<unsigned> Buffers) {}
+ virtual void onReleasedBuffers(llvm::ArrayRef<unsigned> Buffers) {}
+
+ virtual ~HWEventListener() {}
+
+private:
+ virtual void anchor();
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/HardwareUnit.cpp b/contrib/llvm/tools/llvm-mca/HardwareUnit.cpp
new file mode 100644
index 000000000000..103cde9afcc8
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/HardwareUnit.cpp
@@ -0,0 +1,23 @@
+//===------------------------- HardwareUnit.cpp -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the anchor for the base class that describes
+/// simulated hardware units.
+///
+//===----------------------------------------------------------------------===//
+
+#include "HardwareUnit.h"
+
+namespace mca {
+
+// Pin the vtable with this method.
+HardwareUnit::~HardwareUnit() = default;
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/HardwareUnit.h b/contrib/llvm/tools/llvm-mca/HardwareUnit.h
new file mode 100644
index 000000000000..e8c496ab967a
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/HardwareUnit.h
@@ -0,0 +1,31 @@
+//===-------------------------- HardwareUnit.h ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a base class for describing a simulated hardware
+/// unit. These units are used to construct a simulated backend.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_HARDWAREUNIT_H
+#define LLVM_TOOLS_LLVM_MCA_HARDWAREUNIT_H
+
+namespace mca {
+
+class HardwareUnit {
+ HardwareUnit(const HardwareUnit &H) = delete;
+ HardwareUnit &operator=(const HardwareUnit &H) = delete;
+
+public:
+ HardwareUnit() = default;
+ virtual ~HardwareUnit();
+};
+
+} // namespace mca
+#endif // LLVM_TOOLS_LLVM_MCA_HARDWAREUNIT_H
diff --git a/contrib/llvm/tools/llvm-mca/InstrBuilder.cpp b/contrib/llvm/tools/llvm-mca/InstrBuilder.cpp
new file mode 100644
index 000000000000..053b7b4e8175
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/InstrBuilder.cpp
@@ -0,0 +1,469 @@
+//===--------------------- InstrBuilder.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the InstrBuilder interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "InstrBuilder.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+using namespace llvm;
+
+static void initializeUsedResources(InstrDesc &ID,
+ const MCSchedClassDesc &SCDesc,
+ const MCSubtargetInfo &STI,
+ ArrayRef<uint64_t> ProcResourceMasks) {
+ const MCSchedModel &SM = STI.getSchedModel();
+
+ // Populate resources consumed.
+ using ResourcePlusCycles = std::pair<uint64_t, ResourceUsage>;
+ std::vector<ResourcePlusCycles> Worklist;
+
+ // Track cycles contributed by resources that are in a "Super" relationship.
+ // This is required if we want to correctly match the behavior of method
+ // SubtargetEmitter::ExpandProcResource() in Tablegen. When computing the set
+ // of "consumed" processor resources and resource cycles, the logic in
+ // ExpandProcResource() doesn't update the number of resource cycles
+ // contributed by a "Super" resource to a group.
+ // We need to take this into account when we find that a processor resource is
+ // part of a group, and it is also used as the "Super" of other resources.
+ // This map stores the number of cycles contributed by sub-resources that are
+ // part of a "Super" resource. The key value is the "Super" resource mask ID.
+ DenseMap<uint64_t, unsigned> SuperResources;
+
+ for (unsigned I = 0, E = SCDesc.NumWriteProcResEntries; I < E; ++I) {
+ const MCWriteProcResEntry *PRE = STI.getWriteProcResBegin(&SCDesc) + I;
+ const MCProcResourceDesc &PR = *SM.getProcResource(PRE->ProcResourceIdx);
+ uint64_t Mask = ProcResourceMasks[PRE->ProcResourceIdx];
+ if (PR.BufferSize != -1)
+ ID.Buffers.push_back(Mask);
+ CycleSegment RCy(0, PRE->Cycles, false);
+ Worklist.emplace_back(ResourcePlusCycles(Mask, ResourceUsage(RCy)));
+ if (PR.SuperIdx) {
+ uint64_t Super = ProcResourceMasks[PR.SuperIdx];
+ SuperResources[Super] += PRE->Cycles;
+ }
+ }
+
+ // Sort elements by mask popcount, so that we prioritize resource units over
+ // resource groups, and smaller groups over larger groups.
+ llvm::sort(Worklist.begin(), Worklist.end(),
+ [](const ResourcePlusCycles &A, const ResourcePlusCycles &B) {
+ unsigned popcntA = countPopulation(A.first);
+ unsigned popcntB = countPopulation(B.first);
+ if (popcntA < popcntB)
+ return true;
+ if (popcntA > popcntB)
+ return false;
+ return A.first < B.first;
+ });
+
+ uint64_t UsedResourceUnits = 0;
+
+ // Remove cycles contributed by smaller resources.
+ for (unsigned I = 0, E = Worklist.size(); I < E; ++I) {
+ ResourcePlusCycles &A = Worklist[I];
+ if (!A.second.size()) {
+ A.second.NumUnits = 0;
+ A.second.setReserved();
+ ID.Resources.emplace_back(A);
+ continue;
+ }
+
+ ID.Resources.emplace_back(A);
+ uint64_t NormalizedMask = A.first;
+ if (countPopulation(A.first) == 1) {
+ UsedResourceUnits |= A.first;
+ } else {
+ // Remove the leading 1 from the resource group mask.
+ NormalizedMask ^= PowerOf2Floor(NormalizedMask);
+ }
+
+ for (unsigned J = I + 1; J < E; ++J) {
+ ResourcePlusCycles &B = Worklist[J];
+ if ((NormalizedMask & B.first) == NormalizedMask) {
+ B.second.CS.Subtract(A.second.size() - SuperResources[A.first]);
+ if (countPopulation(B.first) > 1)
+ B.second.NumUnits++;
+ }
+ }
+ }
+
+ // A SchedWrite may specify a number of cycles in which a resource group
+ // is reserved. For example (on target x86; cpu Haswell):
+ //
+ // SchedWriteRes<[HWPort0, HWPort1, HWPort01]> {
+ // let ResourceCycles = [2, 2, 3];
+ // }
+ //
+ // This means:
+ // Resource units HWPort0 and HWPort1 are both used for 2cy.
+ // Resource group HWPort01 is the union of HWPort0 and HWPort1.
+ // Since this write touches both HWPort0 and HWPort1 for 2cy, HWPort01
+ // will not be usable for 2 entire cycles from instruction issue.
+ //
+ // On top of those 2cy, SchedWriteRes explicitly specifies an extra latency
+ // of 3 cycles for HWPort01. This tool assumes that the 3cy latency is an
+ // extra delay on top of the 2 cycles latency.
+ // During those extra cycles, HWPort01 is not usable by other instructions.
+ for (ResourcePlusCycles &RPC : ID.Resources) {
+ if (countPopulation(RPC.first) > 1 && !RPC.second.isReserved()) {
+ // Remove the leading 1 from the resource group mask.
+ uint64_t Mask = RPC.first ^ PowerOf2Floor(RPC.first);
+ if ((Mask & UsedResourceUnits) == Mask)
+ RPC.second.setReserved();
+ }
+ }
+
+ LLVM_DEBUG({
+ for (const std::pair<uint64_t, ResourceUsage> &R : ID.Resources)
+ dbgs() << "\t\tMask=" << R.first << ", cy=" << R.second.size() << '\n';
+ for (const uint64_t R : ID.Buffers)
+ dbgs() << "\t\tBuffer Mask=" << R << '\n';
+ });
+}
+
+static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc,
+ const MCSchedClassDesc &SCDesc,
+ const MCSubtargetInfo &STI) {
+ if (MCDesc.isCall()) {
+ // We cannot estimate how long this call will take.
+ // Artificially set an arbitrarily high latency (100cy).
+ ID.MaxLatency = 100U;
+ return;
+ }
+
+ int Latency = MCSchedModel::computeInstrLatency(STI, SCDesc);
+ // If latency is unknown, then conservatively assume a MaxLatency of 100cy.
+ ID.MaxLatency = Latency < 0 ? 100U : static_cast<unsigned>(Latency);
+}
+
+void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
+ unsigned SchedClassID) {
+ const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
+ const MCSchedModel &SM = STI.getSchedModel();
+ const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
+
+ // These are for now the (strong) assumptions made by this algorithm:
+ // * The number of explicit and implicit register definitions in a MCInst
+ // matches the number of explicit and implicit definitions according to
+ // the opcode descriptor (MCInstrDesc).
+ // * Register definitions take precedence over register uses in the operands
+ // list.
+ // * If an opcode specifies an optional definition, then the optional
+ // definition is always the last operand in the sequence, and it can be
+ // set to zero (i.e. "no register").
+ //
+ // These assumptions work quite well for most out-of-order in-tree targets
+ // like x86. This is mainly because the vast majority of instructions is
+ // expanded to MCInst using a straightforward lowering logic that preserves
+ // the ordering of the operands.
+ unsigned NumExplicitDefs = MCDesc.getNumDefs();
+ unsigned NumImplicitDefs = MCDesc.getNumImplicitDefs();
+ unsigned NumWriteLatencyEntries = SCDesc.NumWriteLatencyEntries;
+ unsigned TotalDefs = NumExplicitDefs + NumImplicitDefs;
+ if (MCDesc.hasOptionalDef())
+ TotalDefs++;
+ ID.Writes.resize(TotalDefs);
+ // Iterate over the operands list, and skip non-register operands.
+ // The first NumExplictDefs register operands are expected to be register
+ // definitions.
+ unsigned CurrentDef = 0;
+ unsigned i = 0;
+ for (; i < MCI.getNumOperands() && CurrentDef < NumExplicitDefs; ++i) {
+ const MCOperand &Op = MCI.getOperand(i);
+ if (!Op.isReg())
+ continue;
+
+ WriteDescriptor &Write = ID.Writes[CurrentDef];
+ Write.OpIndex = i;
+ if (CurrentDef < NumWriteLatencyEntries) {
+ const MCWriteLatencyEntry &WLE =
+ *STI.getWriteLatencyEntry(&SCDesc, CurrentDef);
+ // Conservatively default to MaxLatency.
+ Write.Latency =
+ WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
+ Write.SClassOrWriteResourceID = WLE.WriteResourceID;
+ } else {
+ // Assign a default latency for this write.
+ Write.Latency = ID.MaxLatency;
+ Write.SClassOrWriteResourceID = 0;
+ }
+ Write.IsOptionalDef = false;
+ LLVM_DEBUG({
+ dbgs() << "\t\t[Def] OpIdx=" << Write.OpIndex
+ << ", Latency=" << Write.Latency
+ << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n';
+ });
+ CurrentDef++;
+ }
+
+ if (CurrentDef != NumExplicitDefs)
+ llvm::report_fatal_error(
+ "error: Expected more register operand definitions. ");
+
+ CurrentDef = 0;
+ for (CurrentDef = 0; CurrentDef < NumImplicitDefs; ++CurrentDef) {
+ unsigned Index = NumExplicitDefs + CurrentDef;
+ WriteDescriptor &Write = ID.Writes[Index];
+ Write.OpIndex = ~CurrentDef;
+ Write.RegisterID = MCDesc.getImplicitDefs()[CurrentDef];
+ if (Index < NumWriteLatencyEntries) {
+ const MCWriteLatencyEntry &WLE =
+ *STI.getWriteLatencyEntry(&SCDesc, Index);
+ // Conservatively default to MaxLatency.
+ Write.Latency =
+ WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
+ Write.SClassOrWriteResourceID = WLE.WriteResourceID;
+ } else {
+ // Assign a default latency for this write.
+ Write.Latency = ID.MaxLatency;
+ Write.SClassOrWriteResourceID = 0;
+ }
+
+ Write.IsOptionalDef = false;
+ assert(Write.RegisterID != 0 && "Expected a valid phys register!");
+ LLVM_DEBUG({
+ dbgs() << "\t\t[Def] OpIdx=" << Write.OpIndex
+ << ", PhysReg=" << MRI.getName(Write.RegisterID)
+ << ", Latency=" << Write.Latency
+ << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n';
+ });
+ }
+
+ if (MCDesc.hasOptionalDef()) {
+ // Always assume that the optional definition is the last operand of the
+ // MCInst sequence.
+ const MCOperand &Op = MCI.getOperand(MCI.getNumOperands() - 1);
+ if (i == MCI.getNumOperands() || !Op.isReg())
+ llvm::report_fatal_error(
+ "error: expected a register operand for an optional "
+ "definition. Instruction has not be correctly analyzed.\n",
+ false);
+
+ WriteDescriptor &Write = ID.Writes[TotalDefs - 1];
+ Write.OpIndex = MCI.getNumOperands() - 1;
+ // Assign a default latency for this write.
+ Write.Latency = ID.MaxLatency;
+ Write.SClassOrWriteResourceID = 0;
+ Write.IsOptionalDef = true;
+ }
+}
+
+void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
+ unsigned SchedClassID) {
+ const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
+ unsigned NumExplicitDefs = MCDesc.getNumDefs();
+
+ // Skip explicit definitions.
+ unsigned i = 0;
+ for (; i < MCI.getNumOperands() && NumExplicitDefs; ++i) {
+ const MCOperand &Op = MCI.getOperand(i);
+ if (Op.isReg())
+ NumExplicitDefs--;
+ }
+
+ if (NumExplicitDefs)
+ llvm::report_fatal_error(
+ "error: Expected more register operand definitions. ", false);
+
+ unsigned NumExplicitUses = MCI.getNumOperands() - i;
+ unsigned NumImplicitUses = MCDesc.getNumImplicitUses();
+ if (MCDesc.hasOptionalDef()) {
+ assert(NumExplicitUses);
+ NumExplicitUses--;
+ }
+ unsigned TotalUses = NumExplicitUses + NumImplicitUses;
+ if (!TotalUses)
+ return;
+
+ ID.Reads.resize(TotalUses);
+ for (unsigned CurrentUse = 0; CurrentUse < NumExplicitUses; ++CurrentUse) {
+ ReadDescriptor &Read = ID.Reads[CurrentUse];
+ Read.OpIndex = i + CurrentUse;
+ Read.UseIndex = CurrentUse;
+ Read.SchedClassID = SchedClassID;
+ LLVM_DEBUG(dbgs() << "\t\t[Use] OpIdx=" << Read.OpIndex
+ << ", UseIndex=" << Read.UseIndex << '\n');
+ }
+
+ for (unsigned CurrentUse = 0; CurrentUse < NumImplicitUses; ++CurrentUse) {
+ ReadDescriptor &Read = ID.Reads[NumExplicitUses + CurrentUse];
+ Read.OpIndex = ~CurrentUse;
+ Read.UseIndex = NumExplicitUses + CurrentUse;
+ Read.RegisterID = MCDesc.getImplicitUses()[CurrentUse];
+ Read.SchedClassID = SchedClassID;
+ LLVM_DEBUG(dbgs() << "\t\t[Use] OpIdx=" << Read.OpIndex << ", RegisterID="
+ << MRI.getName(Read.RegisterID) << '\n');
+ }
+}
+
+const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
+ assert(STI.getSchedModel().hasInstrSchedModel() &&
+ "Itineraries are not yet supported!");
+
+ // Obtain the instruction descriptor from the opcode.
+ unsigned short Opcode = MCI.getOpcode();
+ const MCInstrDesc &MCDesc = MCII.get(Opcode);
+ const MCSchedModel &SM = STI.getSchedModel();
+
+ // Then obtain the scheduling class information from the instruction.
+ unsigned SchedClassID = MCDesc.getSchedClass();
+ unsigned CPUID = SM.getProcessorID();
+
+ // Try to solve variant scheduling classes.
+ if (SchedClassID) {
+ while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant())
+ SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &MCI, CPUID);
+
+ if (!SchedClassID)
+ llvm::report_fatal_error("unable to resolve this variant class.");
+ }
+
+ // Check if this instruction is supported. Otherwise, report a fatal error.
+ const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
+ if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
+ std::string ToString;
+ llvm::raw_string_ostream OS(ToString);
+ WithColor::error() << "found an unsupported instruction in the input"
+ << " assembly sequence.\n";
+ MCIP.printInst(&MCI, OS, "", STI);
+ OS.flush();
+
+ WithColor::note() << "instruction: " << ToString << '\n';
+ llvm::report_fatal_error(
+ "Don't know how to analyze unsupported instructions.");
+ }
+
+ // Create a new empty descriptor.
+ std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>();
+ ID->NumMicroOps = SCDesc.NumMicroOps;
+
+ if (MCDesc.isCall()) {
+ // We don't correctly model calls.
+ WithColor::warning() << "found a call in the input assembly sequence.\n";
+ WithColor::note() << "call instructions are not correctly modeled. "
+ << "Assume a latency of 100cy.\n";
+ }
+
+ if (MCDesc.isReturn()) {
+ WithColor::warning() << "found a return instruction in the input"
+ << " assembly sequence.\n";
+ WithColor::note() << "program counter updates are ignored.\n";
+ }
+
+ ID->MayLoad = MCDesc.mayLoad();
+ ID->MayStore = MCDesc.mayStore();
+ ID->HasSideEffects = MCDesc.hasUnmodeledSideEffects();
+
+ initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks);
+ computeMaxLatency(*ID, MCDesc, SCDesc, STI);
+ populateWrites(*ID, MCI, SchedClassID);
+ populateReads(*ID, MCI, SchedClassID);
+
+ LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n');
+ LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n');
+
+ // Now add the new descriptor.
+ SchedClassID = MCDesc.getSchedClass();
+ if (!SM.getSchedClassDesc(SchedClassID)->isVariant()) {
+ Descriptors[MCI.getOpcode()] = std::move(ID);
+ return *Descriptors[MCI.getOpcode()];
+ }
+
+ VariantDescriptors[&MCI] = std::move(ID);
+ return *VariantDescriptors[&MCI];
+}
+
+const InstrDesc &InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
+ if (Descriptors.find_as(MCI.getOpcode()) != Descriptors.end())
+ return *Descriptors[MCI.getOpcode()];
+
+ if (VariantDescriptors.find(&MCI) != VariantDescriptors.end())
+ return *VariantDescriptors[&MCI];
+
+ return createInstrDescImpl(MCI);
+}
+
+std::unique_ptr<Instruction>
+InstrBuilder::createInstruction(const MCInst &MCI) {
+ const InstrDesc &D = getOrCreateInstrDesc(MCI);
+ std::unique_ptr<Instruction> NewIS = llvm::make_unique<Instruction>(D);
+
+ // Initialize Reads first.
+ for (const ReadDescriptor &RD : D.Reads) {
+ int RegID = -1;
+ if (!RD.isImplicitRead()) {
+ // explicit read.
+ const MCOperand &Op = MCI.getOperand(RD.OpIndex);
+ // Skip non-register operands.
+ if (!Op.isReg())
+ continue;
+ RegID = Op.getReg();
+ } else {
+ // Implicit read.
+ RegID = RD.RegisterID;
+ }
+
+ // Skip invalid register operands.
+ if (!RegID)
+ continue;
+
+ // Okay, this is a register operand. Create a ReadState for it.
+ assert(RegID > 0 && "Invalid register ID found!");
+ NewIS->getUses().emplace_back(llvm::make_unique<ReadState>(RD, RegID));
+ }
+
+ // Early exit if there are no writes.
+ if (D.Writes.empty())
+ return NewIS;
+
+ // Track register writes that implicitly clear the upper portion of the
+ // underlying super-registers using an APInt.
+ APInt WriteMask(D.Writes.size(), 0);
+
+ // Now query the MCInstrAnalysis object to obtain information about which
+ // register writes implicitly clear the upper portion of a super-register.
+ MCIA.clearsSuperRegisters(MRI, MCI, WriteMask);
+
+ // Check if this is a dependency breaking instruction.
+ if (MCIA.isDependencyBreaking(STI, MCI))
+ NewIS->setDependencyBreaking();
+
+ // Initialize writes.
+ unsigned WriteIndex = 0;
+ for (const WriteDescriptor &WD : D.Writes) {
+ unsigned RegID = WD.isImplicitWrite() ? WD.RegisterID
+ : MCI.getOperand(WD.OpIndex).getReg();
+ // Check if this is a optional definition that references NoReg.
+ if (WD.IsOptionalDef && !RegID) {
+ ++WriteIndex;
+ continue;
+ }
+
+ assert(RegID && "Expected a valid register ID!");
+ NewIS->getDefs().emplace_back(llvm::make_unique<WriteState>(
+ WD, RegID, /* ClearsSuperRegs */ WriteMask[WriteIndex]));
+ ++WriteIndex;
+ }
+
+ return NewIS;
+}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/InstrBuilder.h b/contrib/llvm/tools/llvm-mca/InstrBuilder.h
new file mode 100644
index 000000000000..69a53b6fec21
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/InstrBuilder.h
@@ -0,0 +1,85 @@
+//===--------------------- InstrBuilder.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A builder class for instructions that are statically analyzed by llvm-mca.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_INSTRBUILDER_H
+#define LLVM_TOOLS_LLVM_MCA_INSTRBUILDER_H
+
+#include "Instruction.h"
+#include "Support.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+namespace mca {
+
+class DispatchUnit;
+
+/// A builder class that knows how to construct Instruction objects.
+///
+/// Every llvm-mca Instruction is described by an object of class InstrDesc.
+/// An InstrDesc describes which registers are read/written by the instruction,
+/// as well as the instruction latency and hardware resources consumed.
+///
+/// This class is used by the tool to construct Instructions and instruction
+/// descriptors (i.e. InstrDesc objects).
+/// Information from the machine scheduling model is used to identify processor
+/// resources that are consumed by an instruction.
+class InstrBuilder {
+ const llvm::MCSubtargetInfo &STI;
+ const llvm::MCInstrInfo &MCII;
+ const llvm::MCRegisterInfo &MRI;
+ const llvm::MCInstrAnalysis &MCIA;
+ llvm::MCInstPrinter &MCIP;
+ llvm::SmallVector<uint64_t, 8> ProcResourceMasks;
+
+ llvm::DenseMap<unsigned short, std::unique_ptr<const InstrDesc>> Descriptors;
+ llvm::DenseMap<const llvm::MCInst *, std::unique_ptr<const InstrDesc>>
+ VariantDescriptors;
+
+ const InstrDesc &createInstrDescImpl(const llvm::MCInst &MCI);
+ InstrBuilder(const InstrBuilder &) = delete;
+ InstrBuilder &operator=(const InstrBuilder &) = delete;
+
+ void populateWrites(InstrDesc &ID, const llvm::MCInst &MCI,
+ unsigned SchedClassID);
+ void populateReads(InstrDesc &ID, const llvm::MCInst &MCI,
+ unsigned SchedClassID);
+
+public:
+ InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
+ const llvm::MCRegisterInfo &mri,
+ const llvm::MCInstrAnalysis &mcia, llvm::MCInstPrinter &mcip)
+ : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), MCIP(mcip),
+ ProcResourceMasks(STI.getSchedModel().getNumProcResourceKinds()) {
+ computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks);
+ }
+
+ const InstrDesc &getOrCreateInstrDesc(const llvm::MCInst &MCI);
+ // Returns an array of processor resource masks.
+ // Masks are computed by function mca::computeProcResourceMasks. see
+ // Support.h for a description of how masks are computed and how masks can be
+ // used to solve set membership problems.
+ llvm::ArrayRef<uint64_t> getProcResourceMasks() const {
+ return ProcResourceMasks;
+ }
+
+ void clear() { VariantDescriptors.shrink_and_clear(); }
+
+ std::unique_ptr<Instruction> createInstruction(const llvm::MCInst &MCI);
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/Instruction.cpp b/contrib/llvm/tools/llvm-mca/Instruction.cpp
new file mode 100644
index 000000000000..0c8476705572
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Instruction.cpp
@@ -0,0 +1,177 @@
+//===--------------------- Instruction.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines abstractions used by the Pipeline to model register reads,
+// register writes and instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Instruction.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace mca {
+
+using namespace llvm;
+
+void ReadState::writeStartEvent(unsigned Cycles) {
+ assert(DependentWrites);
+ assert(CyclesLeft == UNKNOWN_CYCLES);
+
+ // This read may be dependent on more than one write. This typically occurs
+ // when a definition is the result of multiple writes where at least one
+ // write does a partial register update.
+ // The HW is forced to do some extra bookkeeping to track of all the
+ // dependent writes, and implement a merging scheme for the partial writes.
+ --DependentWrites;
+ TotalCycles = std::max(TotalCycles, Cycles);
+
+ if (!DependentWrites) {
+ CyclesLeft = TotalCycles;
+ IsReady = !CyclesLeft;
+ }
+}
+
+void WriteState::onInstructionIssued() {
+ assert(CyclesLeft == UNKNOWN_CYCLES);
+ // Update the number of cycles left based on the WriteDescriptor info.
+ CyclesLeft = getLatency();
+
+ // Now that the time left before write-back is known, notify
+ // all the users.
+ for (const std::pair<ReadState *, int> &User : Users) {
+ ReadState *RS = User.first;
+ unsigned ReadCycles = std::max(0, CyclesLeft - User.second);
+ RS->writeStartEvent(ReadCycles);
+ }
+}
+
+void WriteState::addUser(ReadState *User, int ReadAdvance) {
+ // If CyclesLeft is different than -1, then we don't need to
+ // update the list of users. We can just notify the user with
+ // the actual number of cycles left (which may be zero).
+ if (CyclesLeft != UNKNOWN_CYCLES) {
+ unsigned ReadCycles = std::max(0, CyclesLeft - ReadAdvance);
+ User->writeStartEvent(ReadCycles);
+ return;
+ }
+
+ std::pair<ReadState *, int> NewPair(User, ReadAdvance);
+ Users.insert(NewPair);
+}
+
+void WriteState::cycleEvent() {
+ // Note: CyclesLeft can be a negative number. It is an error to
+ // make it an unsigned quantity because users of this write may
+ // specify a negative ReadAdvance.
+ if (CyclesLeft != UNKNOWN_CYCLES)
+ CyclesLeft--;
+}
+
+void ReadState::cycleEvent() {
+ // Update the total number of cycles.
+ if (DependentWrites && TotalCycles) {
+ --TotalCycles;
+ return;
+ }
+
+ // Bail out immediately if we don't know how many cycles are left.
+ if (CyclesLeft == UNKNOWN_CYCLES)
+ return;
+
+ if (CyclesLeft) {
+ --CyclesLeft;
+ IsReady = !CyclesLeft;
+ }
+}
+
+#ifndef NDEBUG
+void WriteState::dump() const {
+ dbgs() << "{ OpIdx=" << WD.OpIndex << ", Lat=" << getLatency() << ", RegID "
+ << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }";
+}
+
+void WriteRef::dump() const {
+ dbgs() << "IID=" << getSourceIndex() << ' ';
+ if (isValid())
+ getWriteState()->dump();
+ else
+ dbgs() << "(null)";
+}
+#endif
+
+void Instruction::dispatch(unsigned RCUToken) {
+ assert(Stage == IS_INVALID);
+ Stage = IS_AVAILABLE;
+ RCUTokenID = RCUToken;
+
+ // Check if input operands are already available.
+ update();
+}
+
+void Instruction::execute() {
+ assert(Stage == IS_READY);
+ Stage = IS_EXECUTING;
+
+ // Set the cycles left before the write-back stage.
+ CyclesLeft = Desc.MaxLatency;
+
+ for (UniqueDef &Def : Defs)
+ Def->onInstructionIssued();
+
+ // Transition to the "executed" stage if this is a zero-latency instruction.
+ if (!CyclesLeft)
+ Stage = IS_EXECUTED;
+}
+
+void Instruction::update() {
+ assert(isDispatched() && "Unexpected instruction stage found!");
+
+ if (!llvm::all_of(Uses, [](const UniqueUse &Use) { return Use->isReady(); }))
+ return;
+
+ // A partial register write cannot complete before a dependent write.
+ auto IsDefReady = [&](const UniqueDef &Def) {
+ if (const WriteState *Write = Def->getDependentWrite()) {
+ int WriteLatency = Write->getCyclesLeft();
+ if (WriteLatency == UNKNOWN_CYCLES)
+ return false;
+ return static_cast<unsigned>(WriteLatency) < Desc.MaxLatency;
+ }
+ return true;
+ };
+
+ if (llvm::all_of(Defs, IsDefReady))
+ Stage = IS_READY;
+}
+
+void Instruction::cycleEvent() {
+ if (isReady())
+ return;
+
+ if (isDispatched()) {
+ for (UniqueUse &Use : Uses)
+ Use->cycleEvent();
+
+ update();
+ return;
+ }
+
+ assert(isExecuting() && "Instruction not in-flight?");
+ assert(CyclesLeft && "Instruction already executed?");
+ for (UniqueDef &Def : Defs)
+ Def->cycleEvent();
+ CyclesLeft--;
+ if (!CyclesLeft)
+ Stage = IS_EXECUTED;
+}
+
+const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/Instruction.h b/contrib/llvm/tools/llvm-mca/Instruction.h
new file mode 100644
index 000000000000..3b2f90528f2e
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Instruction.h
@@ -0,0 +1,434 @@
+//===--------------------- Instruction.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines abstractions used by the Pipeline to model register reads,
+/// register writes and instructions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_INSTRUCTION_H
+#define LLVM_TOOLS_LLVM_MCA_INSTRUCTION_H
+
+#include "llvm/Support/MathExtras.h"
+
+#ifndef NDEBUG
+#include "llvm/Support/raw_ostream.h"
+#endif
+
+#include <memory>
+#include <set>
+#include <vector>
+
+namespace mca {
+
+constexpr int UNKNOWN_CYCLES = -512;
+
+/// A register write descriptor.
+struct WriteDescriptor {
+ // Operand index. The index is negative for implicit writes only.
+ // For implicit writes, the actual operand index is computed performing
+ // a bitwise not of the OpIndex.
+ int OpIndex;
+ // Write latency. Number of cycles before write-back stage.
+ unsigned Latency;
+ // This field is set to a value different than zero only if this
+ // is an implicit definition.
+ unsigned RegisterID;
+ // Instruction itineraries would set this field to the SchedClass ID.
+ // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
+ // element associated to this write.
+ // When computing read latencies, this value is matched against the
+ // "ReadAdvance" information. The hardware backend may implement
+ // dedicated forwarding paths to quickly propagate write results to dependent
+ // instructions waiting in the reservation station (effectively bypassing the
+ // write-back stage).
+ unsigned SClassOrWriteResourceID;
+ // True only if this is a write obtained from an optional definition.
+ // Optional definitions are allowed to reference regID zero (i.e. "no
+ // register").
+ bool IsOptionalDef;
+
+ bool isImplicitWrite() const { return OpIndex < 0; };
+};
+
+/// A register read descriptor.
+struct ReadDescriptor {
+ // A MCOperand index. This is used by the Dispatch logic to identify register
+ // reads. Implicit reads have negative indices. The actual operand index of an
+ // implicit read is the bitwise not of field OpIndex.
+ int OpIndex;
+ // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
+ // uses always come first in the sequence of uses.
+ unsigned UseIndex;
+ // This field is only set if this is an implicit read.
+ unsigned RegisterID;
+ // Scheduling Class Index. It is used to query the scheduling model for the
+ // MCSchedClassDesc object.
+ unsigned SchedClassID;
+
+ bool isImplicitRead() const { return OpIndex < 0; };
+};
+
+class ReadState;
+
+/// Tracks uses of a register definition (e.g. register write).
+///
+/// Each implicit/explicit register write is associated with an instance of
+/// this class. A WriteState object tracks the dependent users of a
+/// register write. It also tracks how many cycles are left before the write
+/// back stage.
+class WriteState {
+ const WriteDescriptor &WD;
+ // On instruction issue, this field is set equal to the write latency.
+ // Before instruction issue, this field defaults to -512, a special
+ // value that represents an "unknown" number of cycles.
+ int CyclesLeft;
+
+ // Actual register defined by this write. This field is only used
+ // to speedup queries on the register file.
+ // For implicit writes, this field always matches the value of
+ // field RegisterID from WD.
+ unsigned RegisterID;
+
+ // True if this write implicitly clears the upper portion of RegisterID's
+ // super-registers.
+ bool ClearsSuperRegs;
+
+ // This field is set if this is a partial register write, and it has a false
+ // dependency on any previous write of the same register (or a portion of it).
+ // DependentWrite must be able to complete before this write completes, so
+ // that we don't break the WAW, and the two writes can be merged together.
+ const WriteState *DependentWrite;
+
+ // A list of dependent reads. Users is a set of dependent
+ // reads. A dependent read is added to the set only if CyclesLeft
+ // is "unknown". As soon as CyclesLeft is 'known', each user in the set
+ // gets notified with the actual CyclesLeft.
+
+ // The 'second' element of a pair is a "ReadAdvance" number of cycles.
+ std::set<std::pair<ReadState *, int>> Users;
+
+public:
+ WriteState(const WriteDescriptor &Desc, unsigned RegID,
+ bool clearsSuperRegs = false)
+ : WD(Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID),
+ ClearsSuperRegs(clearsSuperRegs), DependentWrite(nullptr) {}
+ WriteState(const WriteState &Other) = delete;
+ WriteState &operator=(const WriteState &Other) = delete;
+
+ int getCyclesLeft() const { return CyclesLeft; }
+ unsigned getWriteResourceID() const { return WD.SClassOrWriteResourceID; }
+ unsigned getRegisterID() const { return RegisterID; }
+ unsigned getLatency() const { return WD.Latency; }
+
+ void addUser(ReadState *Use, int ReadAdvance);
+ unsigned getNumUsers() const { return Users.size(); }
+ bool clearsSuperRegisters() const { return ClearsSuperRegs; }
+
+ const WriteState *getDependentWrite() const { return DependentWrite; }
+ void setDependentWrite(const WriteState *Write) { DependentWrite = Write; }
+
+ // On every cycle, update CyclesLeft and notify dependent users.
+ void cycleEvent();
+ void onInstructionIssued();
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+/// Tracks register operand latency in cycles.
+///
+/// A read may be dependent on more than one write. This occurs when some
+/// writes only partially update the register associated to this read.
+class ReadState {
+ const ReadDescriptor &RD;
+ // Physical register identified associated to this read.
+ unsigned RegisterID;
+ // Number of writes that contribute to the definition of RegisterID.
+ // In the absence of partial register updates, the number of DependentWrites
+ // cannot be more than one.
+ unsigned DependentWrites;
+ // Number of cycles left before RegisterID can be read. This value depends on
+ // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
+ // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
+ // every dependent write is known.
+ int CyclesLeft;
+ // This field is updated on every writeStartEvent(). When the number of
+ // dependent writes (i.e. field DependentWrite) is zero, this value is
+ // propagated to field CyclesLeft.
+ unsigned TotalCycles;
+ // This field is set to true only if there are no dependent writes, and
+ // there are no `CyclesLeft' to wait.
+ bool IsReady;
+
+public:
+ ReadState(const ReadDescriptor &Desc, unsigned RegID)
+ : RD(Desc), RegisterID(RegID), DependentWrites(0),
+ CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true) {}
+ ReadState(const ReadState &Other) = delete;
+ ReadState &operator=(const ReadState &Other) = delete;
+
+ const ReadDescriptor &getDescriptor() const { return RD; }
+ unsigned getSchedClass() const { return RD.SchedClassID; }
+ unsigned getRegisterID() const { return RegisterID; }
+
+ bool isReady() const { return IsReady; }
+ bool isImplicitRead() const { return RD.isImplicitRead(); }
+
+ void cycleEvent();
+ void writeStartEvent(unsigned Cycles);
+ void setDependentWrites(unsigned Writes) {
+ DependentWrites = Writes;
+ IsReady = !Writes;
+ }
+};
+
+/// A sequence of cycles.
+///
+/// This class can be used as a building block to construct ranges of cycles.
+class CycleSegment {
+ unsigned Begin; // Inclusive.
+ unsigned End; // Exclusive.
+ bool Reserved; // Resources associated to this segment must be reserved.
+
+public:
+ CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
+ : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
+
+ bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
+ bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
+ bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
+ bool overlaps(const CycleSegment &CS) const {
+ return !startsAfter(CS) && !endsBefore(CS);
+ }
+ bool isExecuting() const { return Begin == 0 && End != 0; }
+ bool isExecuted() const { return End == 0; }
+ bool operator<(const CycleSegment &Other) const {
+ return Begin < Other.Begin;
+ }
+ CycleSegment &operator--(void) {
+ if (Begin)
+ Begin--;
+ if (End)
+ End--;
+ return *this;
+ }
+
+ bool isValid() const { return Begin <= End; }
+ unsigned size() const { return End - Begin; };
+ void Subtract(unsigned Cycles) {
+ assert(End >= Cycles);
+ End -= Cycles;
+ }
+
+ unsigned begin() const { return Begin; }
+ unsigned end() const { return End; }
+ void setEnd(unsigned NewEnd) { End = NewEnd; }
+ bool isReserved() const { return Reserved; }
+ void setReserved() { Reserved = true; }
+};
+
+/// Helper used by class InstrDesc to describe how hardware resources
+/// are used.
+///
+/// This class describes how many resource units of a specific resource kind
+/// (and how many cycles) are "used" by an instruction.
+struct ResourceUsage {
+ CycleSegment CS;
+ unsigned NumUnits;
+ ResourceUsage(CycleSegment Cycles, unsigned Units = 1)
+ : CS(Cycles), NumUnits(Units) {}
+ unsigned size() const { return CS.size(); }
+ bool isReserved() const { return CS.isReserved(); }
+ void setReserved() { CS.setReserved(); }
+};
+
+/// An instruction descriptor
+struct InstrDesc {
+ std::vector<WriteDescriptor> Writes; // Implicit writes are at the end.
+ std::vector<ReadDescriptor> Reads; // Implicit reads are at the end.
+
+ // For every resource used by an instruction of this kind, this vector
+ // reports the number of "consumed cycles".
+ std::vector<std::pair<uint64_t, ResourceUsage>> Resources;
+
+ // A list of buffered resources consumed by this instruction.
+ std::vector<uint64_t> Buffers;
+ unsigned MaxLatency;
+ // Number of MicroOps for this instruction.
+ unsigned NumMicroOps;
+
+ bool MayLoad;
+ bool MayStore;
+ bool HasSideEffects;
+
+ // A zero latency instruction doesn't consume any scheduler resources.
+ bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
+};
+
+/// An instruction propagated through the simulated instruction pipeline.
+///
+/// This class is used to monitor changes to the internal state of instructions
+/// that are sent to the various components of the simulated hardware pipeline.
+class Instruction {
+ const InstrDesc &Desc;
+
+ enum InstrStage {
+ IS_INVALID, // Instruction in an invalid state.
+ IS_AVAILABLE, // Instruction dispatched but operands are not ready.
+ IS_READY, // Instruction dispatched and operands ready.
+ IS_EXECUTING, // Instruction issued.
+ IS_EXECUTED, // Instruction executed. Values are written back.
+ IS_RETIRED // Instruction retired.
+ };
+
+ // The current instruction stage.
+ enum InstrStage Stage;
+
+ // This value defaults to the instruction latency. This instruction is
+ // considered executed when field CyclesLeft goes to zero.
+ int CyclesLeft;
+
+ // Retire Unit token ID for this instruction.
+ unsigned RCUTokenID;
+
+ bool IsDepBreaking;
+
+ using UniqueDef = std::unique_ptr<WriteState>;
+ using UniqueUse = std::unique_ptr<ReadState>;
+ using VecDefs = std::vector<UniqueDef>;
+ using VecUses = std::vector<UniqueUse>;
+
+ // Output dependencies.
+ // One entry per each implicit and explicit register definition.
+ VecDefs Defs;
+
+ // Input dependencies.
+ // One entry per each implicit and explicit register use.
+ VecUses Uses;
+
+public:
+ Instruction(const InstrDesc &D)
+ : Desc(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0),
+ IsDepBreaking(false) {}
+ Instruction(const Instruction &Other) = delete;
+ Instruction &operator=(const Instruction &Other) = delete;
+
+ VecDefs &getDefs() { return Defs; }
+ const VecDefs &getDefs() const { return Defs; }
+ VecUses &getUses() { return Uses; }
+ const VecUses &getUses() const { return Uses; }
+ const InstrDesc &getDesc() const { return Desc; }
+ unsigned getRCUTokenID() const { return RCUTokenID; }
+ int getCyclesLeft() const { return CyclesLeft; }
+
+ bool isDependencyBreaking() const { return IsDepBreaking; }
+ void setDependencyBreaking() { IsDepBreaking = true; }
+
+ unsigned getNumUsers() const {
+ unsigned NumUsers = 0;
+ for (const UniqueDef &Def : Defs)
+ NumUsers += Def->getNumUsers();
+ return NumUsers;
+ }
+
+ // Transition to the dispatch stage, and assign a RCUToken to this
+ // instruction. The RCUToken is used to track the completion of every
+ // register write performed by this instruction.
+ void dispatch(unsigned RCUTokenID);
+
+ // Instruction issued. Transition to the IS_EXECUTING state, and update
+ // all the definitions.
+ void execute();
+
+ // Force a transition from the IS_AVAILABLE state to the IS_READY state if
+ // input operands are all ready. State transitions normally occur at the
+ // beginning of a new cycle (see method cycleEvent()). However, the scheduler
+ // may decide to promote instructions from the wait queue to the ready queue
+ // as the result of another issue event. This method is called every time the
+ // instruction might have changed in state.
+ void update();
+
+ bool isDispatched() const { return Stage == IS_AVAILABLE; }
+ bool isReady() const { return Stage == IS_READY; }
+ bool isExecuting() const { return Stage == IS_EXECUTING; }
+ bool isExecuted() const { return Stage == IS_EXECUTED; }
+ bool isRetired() const { return Stage == IS_RETIRED; }
+
+ void retire() {
+ assert(isExecuted() && "Instruction is in an invalid state!");
+ Stage = IS_RETIRED;
+ }
+
+ void cycleEvent();
+};
+
+/// An InstRef contains both a SourceMgr index and Instruction pair. The index
+/// is used as a unique identifier for the instruction. MCA will make use of
+/// this index as a key throughout MCA.
+class InstRef : public std::pair<unsigned, Instruction *> {
+public:
+ InstRef() : std::pair<unsigned, Instruction *>(0, nullptr) {}
+ InstRef(unsigned Index, Instruction *I)
+ : std::pair<unsigned, Instruction *>(Index, I) {}
+
+ unsigned getSourceIndex() const { return first; }
+ Instruction *getInstruction() { return second; }
+ const Instruction *getInstruction() const { return second; }
+
+ /// Returns true if this InstRef has been populated.
+ bool isValid() const { return second != nullptr; }
+
+#ifndef NDEBUG
+ void print(llvm::raw_ostream &OS) const { OS << getSourceIndex(); }
+#endif
+};
+
+#ifndef NDEBUG
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InstRef &IR) {
+ IR.print(OS);
+ return OS;
+}
+#endif
+
+/// A reference to a register write.
+///
+/// This class is mainly used by the register file to describe register
+/// mappings. It correlates a register write to the source index of the
+/// defining instruction.
+class WriteRef {
+ std::pair<unsigned, WriteState *> Data;
+ static const unsigned INVALID_IID;
+
+public:
+ WriteRef() : Data(INVALID_IID, nullptr) {}
+ WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {}
+
+ unsigned getSourceIndex() const { return Data.first; }
+ const WriteState *getWriteState() const { return Data.second; }
+ WriteState *getWriteState() { return Data.second; }
+ void invalidate() { Data = std::make_pair(INVALID_IID, nullptr); }
+
+ bool isValid() const {
+ return Data.first != INVALID_IID && Data.second != nullptr;
+ }
+ bool operator==(const WriteRef &Other) const {
+ return Data == Other.Data;
+ }
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/InstructionInfoView.cpp b/contrib/llvm/tools/llvm-mca/InstructionInfoView.cpp
new file mode 100644
index 000000000000..0e50a96d19c1
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/InstructionInfoView.cpp
@@ -0,0 +1,91 @@
+//===--------------------- InstructionInfoView.cpp --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the InstructionInfoView API.
+///
+//===----------------------------------------------------------------------===//
+
+#include "InstructionInfoView.h"
+
+namespace mca {
+
+using namespace llvm;
+
+void InstructionInfoView::printView(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ const MCSchedModel &SM = STI.getSchedModel();
+ unsigned Instructions = Source.size();
+
+ std::string Instruction;
+ raw_string_ostream InstrStream(Instruction);
+
+ TempStream << "\n\nInstruction Info:\n";
+ TempStream << "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n"
+ << "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n\n";
+
+ TempStream << "[1] [2] [3] [4] [5] [6] Instructions:\n";
+ for (unsigned I = 0, E = Instructions; I < E; ++I) {
+ const MCInst &Inst = Source.getMCInstFromIndex(I);
+ const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode());
+
+ // Obtain the scheduling class information from the instruction.
+ unsigned SchedClassID = MCDesc.getSchedClass();
+ unsigned CPUID = SM.getProcessorID();
+
+ // Try to solve variant scheduling classes.
+ while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant())
+ SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &Inst, CPUID);
+
+ const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
+ unsigned NumMicroOpcodes = SCDesc.NumMicroOps;
+ unsigned Latency = MCSchedModel::computeInstrLatency(STI, SCDesc);
+ Optional<double> RThroughput =
+ MCSchedModel::getReciprocalThroughput(STI, SCDesc);
+
+ TempStream << ' ' << NumMicroOpcodes << " ";
+ if (NumMicroOpcodes < 10)
+ TempStream << " ";
+ else if (NumMicroOpcodes < 100)
+ TempStream << ' ';
+ TempStream << Latency << " ";
+ if (Latency < 10)
+ TempStream << " ";
+ else if (Latency < 100)
+ TempStream << ' ';
+
+ if (RThroughput.hasValue()) {
+ double RT = RThroughput.getValue();
+ TempStream << format("%.2f", RT) << ' ';
+ if (RT < 10.0)
+ TempStream << " ";
+ else if (RT < 100.0)
+ TempStream << ' ';
+ } else {
+ TempStream << " - ";
+ }
+ TempStream << (MCDesc.mayLoad() ? " * " : " ");
+ TempStream << (MCDesc.mayStore() ? " * " : " ");
+ TempStream << (MCDesc.hasUnmodeledSideEffects() ? " U " : " ");
+
+ MCIP.printInst(&Inst, InstrStream, "", STI);
+ InstrStream.flush();
+
+ // Consume any tabs or spaces at the beginning of the string.
+ StringRef Str(Instruction);
+ Str = Str.ltrim();
+ TempStream << " " << Str << '\n';
+ Instruction = "";
+ }
+
+ TempStream.flush();
+ OS << Buffer;
+}
+} // namespace mca.
diff --git a/contrib/llvm/tools/llvm-mca/InstructionInfoView.h b/contrib/llvm/tools/llvm-mca/InstructionInfoView.h
new file mode 100644
index 000000000000..0770ae3d2b57
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/InstructionInfoView.h
@@ -0,0 +1,66 @@
+//===--------------------- InstructionInfoView.h ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the instruction info view.
+///
+/// The goal fo the instruction info view is to print the latency and reciprocal
+/// throughput information for every instruction in the input sequence.
+/// This section also reports extra information related to the number of micro
+/// opcodes, and opcode properties (i.e. 'MayLoad', 'MayStore', 'HasSideEffects)
+///
+/// Example:
+///
+/// Instruction Info:
+/// [1]: #uOps
+/// [2]: Latency
+/// [3]: RThroughput
+/// [4]: MayLoad
+/// [5]: MayStore
+/// [6]: HasSideEffects
+///
+/// [1] [2] [3] [4] [5] [6] Instructions:
+/// 1 2 1.00 vmulps %xmm0, %xmm1, %xmm2
+/// 1 3 1.00 vhaddps %xmm2, %xmm2, %xmm3
+/// 1 3 1.00 vhaddps %xmm3, %xmm3, %xmm4
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_INSTRUCTIONINFOVIEW_H
+#define LLVM_TOOLS_LLVM_MCA_INSTRUCTIONINFOVIEW_H
+
+#include "SourceMgr.h"
+#include "View.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+/// A view that prints out generic instruction information.
+class InstructionInfoView : public View {
+ const llvm::MCSubtargetInfo &STI;
+ const llvm::MCInstrInfo &MCII;
+ const SourceMgr &Source;
+ llvm::MCInstPrinter &MCIP;
+
+public:
+ InstructionInfoView(const llvm::MCSubtargetInfo &sti,
+ const llvm::MCInstrInfo &mcii, const SourceMgr &S,
+ llvm::MCInstPrinter &IP)
+ : STI(sti), MCII(mcii), Source(S), MCIP(IP) {}
+
+ void printView(llvm::raw_ostream &OS) const override;
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/InstructionTables.cpp b/contrib/llvm/tools/llvm-mca/InstructionTables.cpp
new file mode 100644
index 000000000000..9b9dbc37fbdb
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/InstructionTables.cpp
@@ -0,0 +1,70 @@
+//===--------------------- InstructionTables.cpp ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the method InstructionTables::execute().
+/// Method execute() prints a theoretical resource pressure distribution based
+/// on the information available in the scheduling model, and without running
+/// the pipeline.
+///
+//===----------------------------------------------------------------------===//
+
+#include "InstructionTables.h"
+
+namespace mca {
+
+using namespace llvm;
+
+bool InstructionTables::execute(InstRef &IR) {
+ ArrayRef<uint64_t> Masks = IB.getProcResourceMasks();
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ UsedResources.clear();
+
+ // Identify the resources consumed by this instruction.
+ for (const std::pair<uint64_t, ResourceUsage> Resource : Desc.Resources) {
+ // Skip zero-cycle resources (i.e., unused resources).
+ if (!Resource.second.size())
+ continue;
+ double Cycles = static_cast<double>(Resource.second.size());
+ unsigned Index = std::distance(
+ Masks.begin(), std::find(Masks.begin(), Masks.end(), Resource.first));
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(Index);
+ unsigned NumUnits = ProcResource.NumUnits;
+ if (!ProcResource.SubUnitsIdxBegin) {
+ // The number of cycles consumed by each unit.
+ Cycles /= NumUnits;
+ for (unsigned I = 0, E = NumUnits; I < E; ++I) {
+ ResourceRef ResourceUnit = std::make_pair(Index, 1U << I);
+ UsedResources.emplace_back(std::make_pair(ResourceUnit, Cycles));
+ }
+ continue;
+ }
+
+ // This is a group. Obtain the set of resources contained in this
+ // group. Some of these resources may implement multiple units.
+ // Uniformly distribute Cycles across all of the units.
+ for (unsigned I1 = 0; I1 < NumUnits; ++I1) {
+ unsigned SubUnitIdx = ProcResource.SubUnitsIdxBegin[I1];
+ const MCProcResourceDesc &SubUnit = *SM.getProcResource(SubUnitIdx);
+ // Compute the number of cycles consumed by each resource unit.
+ double RUCycles = Cycles / (NumUnits * SubUnit.NumUnits);
+ for (unsigned I2 = 0, E2 = SubUnit.NumUnits; I2 < E2; ++I2) {
+ ResourceRef ResourceUnit = std::make_pair(SubUnitIdx, 1U << I2);
+ UsedResources.emplace_back(std::make_pair(ResourceUnit, RUCycles));
+ }
+ }
+ }
+
+ // Send a fake instruction issued event to all the views.
+ HWInstructionIssuedEvent Event(IR, UsedResources);
+ notifyEvent<HWInstructionIssuedEvent>(Event);
+ return true;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/InstructionTables.h b/contrib/llvm/tools/llvm-mca/InstructionTables.h
new file mode 100644
index 000000000000..18e019988430
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/InstructionTables.h
@@ -0,0 +1,43 @@
+//===--------------------- InstructionTables.h ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements a custom stage to generate instruction tables.
+/// See the description of command-line flag -instruction-tables in
+/// docs/CommandGuide/lvm-mca.rst
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_INSTRUCTIONTABLES_H
+#define LLVM_TOOLS_LLVM_MCA_INSTRUCTIONTABLES_H
+
+#include "InstrBuilder.h"
+#include "Scheduler.h"
+#include "Stage.h"
+#include "View.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSchedule.h"
+
+namespace mca {
+
+class InstructionTables : public Stage {
+ const llvm::MCSchedModel &SM;
+ InstrBuilder &IB;
+ llvm::SmallVector<std::pair<ResourceRef, double>, 4> UsedResources;
+
+public:
+ InstructionTables(const llvm::MCSchedModel &Model, InstrBuilder &Builder)
+ : Stage(), SM(Model), IB(Builder) {}
+
+ bool hasWorkToComplete() const override final { return false; }
+ bool execute(InstRef &IR) override final;
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/LSUnit.cpp b/contrib/llvm/tools/llvm-mca/LSUnit.cpp
new file mode 100644
index 000000000000..9ee3b6171893
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/LSUnit.cpp
@@ -0,0 +1,148 @@
+//===----------------------- LSUnit.cpp --------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A Load-Store Unit for the llvm-mca tool.
+///
+//===----------------------------------------------------------------------===//
+
+#include "LSUnit.h"
+#include "Instruction.h"
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+#ifndef NDEBUG
+void LSUnit::dump() const {
+ dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n';
+ dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n';
+ dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n';
+ dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n';
+}
+#endif
+
+void LSUnit::assignLQSlot(unsigned Index) {
+ assert(!isLQFull());
+ assert(LoadQueue.count(Index) == 0);
+
+ LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index
+ << ",slot=" << LoadQueue.size() << ">\n");
+ LoadQueue.insert(Index);
+}
+
+void LSUnit::assignSQSlot(unsigned Index) {
+ assert(!isSQFull());
+ assert(StoreQueue.count(Index) == 0);
+
+ LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index
+ << ",slot=" << StoreQueue.size() << ">\n");
+ StoreQueue.insert(Index);
+}
+
+bool LSUnit::reserve(const InstRef &IR) {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ unsigned MayLoad = Desc.MayLoad;
+ unsigned MayStore = Desc.MayStore;
+ unsigned IsMemBarrier = Desc.HasSideEffects;
+ if (!MayLoad && !MayStore)
+ return false;
+
+ const unsigned Index = IR.getSourceIndex();
+ if (MayLoad) {
+ if (IsMemBarrier)
+ LoadBarriers.insert(Index);
+ assignLQSlot(Index);
+ }
+ if (MayStore) {
+ if (IsMemBarrier)
+ StoreBarriers.insert(Index);
+ assignSQSlot(Index);
+ }
+ return true;
+}
+
+bool LSUnit::isReady(const InstRef &IR) const {
+ const unsigned Index = IR.getSourceIndex();
+ bool IsALoad = LoadQueue.count(Index) != 0;
+ bool IsAStore = StoreQueue.count(Index) != 0;
+ assert((IsALoad || IsAStore) && "Instruction is not in queue!");
+
+ if (IsALoad && !LoadBarriers.empty()) {
+ unsigned LoadBarrierIndex = *LoadBarriers.begin();
+ if (Index > LoadBarrierIndex)
+ return false;
+ if (Index == LoadBarrierIndex && Index != *LoadQueue.begin())
+ return false;
+ }
+
+ if (IsAStore && !StoreBarriers.empty()) {
+ unsigned StoreBarrierIndex = *StoreBarriers.begin();
+ if (Index > StoreBarrierIndex)
+ return false;
+ if (Index == StoreBarrierIndex && Index != *StoreQueue.begin())
+ return false;
+ }
+
+ if (NoAlias && IsALoad)
+ return true;
+
+ if (StoreQueue.size()) {
+ // Check if this memory operation is younger than the older store.
+ if (Index > *StoreQueue.begin())
+ return false;
+ }
+
+ // Okay, we are older than the oldest store in the queue.
+ // If there are no pending loads, then we can say for sure that this
+ // instruction is ready.
+ if (isLQEmpty())
+ return true;
+
+ // Check if there are no older loads.
+ if (Index <= *LoadQueue.begin())
+ return true;
+
+ // There is at least one younger load.
+ return !IsAStore;
+}
+
+void LSUnit::onInstructionExecuted(const InstRef &IR) {
+ const unsigned Index = IR.getSourceIndex();
+ std::set<unsigned>::iterator it = LoadQueue.find(Index);
+ if (it != LoadQueue.end()) {
+ LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
+ << " has been removed from the load queue.\n");
+ LoadQueue.erase(it);
+ }
+
+ it = StoreQueue.find(Index);
+ if (it != StoreQueue.end()) {
+ LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
+ << " has been removed from the store queue.\n");
+ StoreQueue.erase(it);
+ }
+
+ if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) {
+ LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
+ << " has been removed from the set of store barriers.\n");
+ StoreBarriers.erase(StoreBarriers.begin());
+ }
+ if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) {
+ LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
+ << " has been removed from the set of load barriers.\n");
+ LoadBarriers.erase(LoadBarriers.begin());
+ }
+}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/LSUnit.h b/contrib/llvm/tools/llvm-mca/LSUnit.h
new file mode 100644
index 000000000000..817522190589
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/LSUnit.h
@@ -0,0 +1,147 @@
+//===------------------------- LSUnit.h --------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A Load/Store unit class that models load/store queues and that implements
+/// a simple weak memory consistency model.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_LSUNIT_H
+#define LLVM_TOOLS_LLVM_MCA_LSUNIT_H
+
+#include <set>
+
+namespace mca {
+
+class InstRef;
+struct InstrDesc;
+
+/// A Load/Store Unit implementing a load and store queues.
+///
+/// This class implements a load queue and a store queue to emulate the
+/// out-of-order execution of memory operations.
+/// Each load (or store) consumes an entry in the load (or store) queue.
+///
+/// Rules are:
+/// 1) A younger load is allowed to pass an older load only if there are no
+/// stores nor barriers in between the two loads.
+/// 2) An younger store is not allowed to pass an older store.
+/// 3) A younger store is not allowed to pass an older load.
+/// 4) A younger load is allowed to pass an older store only if the load does
+/// not alias with the store.
+///
+/// This class optimistically assumes that loads don't alias store operations.
+/// Under this assumption, younger loads are always allowed to pass older
+/// stores (this would only affects rule 4).
+/// Essentially, this LSUnit doesn't attempt to run any sort alias analysis to
+/// predict when loads and stores don't alias with eachother.
+///
+/// To enforce aliasing between loads and stores, flag `AssumeNoAlias` must be
+/// set to `false` by the constructor of LSUnit.
+///
+/// In the case of write-combining memory, rule 2. could be relaxed to allow
+/// reordering of non-aliasing store operations. At the moment, this is not
+/// allowed.
+/// To put it in another way, there is no option to specify a different memory
+/// type for memory operations (example: write-through, write-combining, etc.).
+/// Also, there is no way to weaken the memory model, and this unit currently
+/// doesn't support write-combining behavior.
+///
+/// No assumptions are made on the size of the store buffer.
+/// As mentioned before, this class doesn't perform alias analysis.
+/// Consequently, LSUnit doesn't know how to identify cases where
+/// store-to-load forwarding may occur.
+///
+/// LSUnit doesn't attempt to predict whether a load or store hits or misses
+/// the L1 cache. To be more specific, LSUnit doesn't know anything about
+/// the cache hierarchy and memory types.
+/// It only knows if an instruction "mayLoad" and/or "mayStore". For loads, the
+/// scheduling model provides an "optimistic" load-to-use latency (which usually
+/// matches the load-to-use latency for when there is a hit in the L1D).
+///
+/// Class MCInstrDesc in LLVM doesn't know about serializing operations, nor
+/// memory-barrier like instructions.
+/// LSUnit conservatively assumes that an instruction which `mayLoad` and has
+/// `unmodeled side effects` behave like a "soft" load-barrier. That means, it
+/// serializes loads without forcing a flush of the load queue.
+/// Similarly, instructions that both `mayStore` and have `unmodeled side
+/// effects` are treated like store barriers. A full memory
+/// barrier is a 'mayLoad' and 'mayStore' instruction with unmodeled side
+/// effects. This is obviously inaccurate, but this is the best that we can do
+/// at the moment.
+///
+/// Each load/store barrier consumes one entry in the load/store queue. A
+/// load/store barrier enforces ordering of loads/stores:
+/// - A younger load cannot pass a load barrier.
+/// - A younger store cannot pass a store barrier.
+///
+/// A younger load has to wait for the memory load barrier to execute.
+/// A load/store barrier is "executed" when it becomes the oldest entry in
+/// the load/store queue(s). That also means, all the older loads/stores have
+/// already been executed.
+class LSUnit {
+ // Load queue size.
+ // LQ_Size == 0 means that there are infinite slots in the load queue.
+ unsigned LQ_Size;
+
+ // Store queue size.
+ // SQ_Size == 0 means that there are infinite slots in the store queue.
+ unsigned SQ_Size;
+
+ // If true, loads will never alias with stores. This is the default.
+ bool NoAlias;
+
+ std::set<unsigned> LoadQueue;
+ std::set<unsigned> StoreQueue;
+
+ void assignLQSlot(unsigned Index);
+ void assignSQSlot(unsigned Index);
+ bool isReadyNoAlias(unsigned Index) const;
+
+ // An instruction that both 'mayStore' and 'HasUnmodeledSideEffects' is
+ // conservatively treated as a store barrier. It forces older store to be
+ // executed before newer stores are issued.
+ std::set<unsigned> StoreBarriers;
+
+ // An instruction that both 'MayLoad' and 'HasUnmodeledSideEffects' is
+ // conservatively treated as a load barrier. It forces older loads to execute
+ // before newer loads are issued.
+ std::set<unsigned> LoadBarriers;
+
+public:
+ LSUnit(unsigned LQ = 0, unsigned SQ = 0, bool AssumeNoAlias = false)
+ : LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) {}
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+ bool isSQEmpty() const { return StoreQueue.empty(); }
+ bool isLQEmpty() const { return LoadQueue.empty(); }
+ bool isSQFull() const { return SQ_Size != 0 && StoreQueue.size() == SQ_Size; }
+ bool isLQFull() const { return LQ_Size != 0 && LoadQueue.size() == LQ_Size; }
+
+ // Returns true if this instruction has been successfully enqueued.
+ bool reserve(const InstRef &IR);
+
+ // The rules are:
+ // 1. A store may not pass a previous store.
+ // 2. A load may not pass a previous store unless flag 'NoAlias' is set.
+ // 3. A load may pass a previous load.
+ // 4. A store may not pass a previous load (regardless of flag 'NoAlias').
+ // 5. A load has to wait until an older load barrier is fully executed.
+ // 6. A store has to wait until an older store barrier is fully executed.
+ bool isReady(const InstRef &IR) const;
+ void onInstructionExecuted(const InstRef &IR);
+};
+
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/Pipeline.cpp b/contrib/llvm/tools/llvm-mca/Pipeline.cpp
new file mode 100644
index 000000000000..7c937e7b48b5
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Pipeline.cpp
@@ -0,0 +1,99 @@
+//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements an ordered container of stages that simulate the
+/// pipeline of a hardware backend.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Pipeline.h"
+#include "HWEventListener.h"
+#include "llvm/CodeGen/TargetSchedule.h"
+#include "llvm/Support/Debug.h"
+
+namespace mca {
+
+#define DEBUG_TYPE "llvm-mca"
+
+using namespace llvm;
+
+void Pipeline::addEventListener(HWEventListener *Listener) {
+ if (Listener)
+ Listeners.insert(Listener);
+ for (auto &S : Stages)
+ S->addListener(Listener);
+}
+
+bool Pipeline::hasWorkToProcess() {
+ const auto It = llvm::find_if(Stages, [](const std::unique_ptr<Stage> &S) {
+ return S->hasWorkToComplete();
+ });
+ return It != Stages.end();
+}
+
+// This routine returns early if any stage returns 'false' after execute() is
+// called on it.
+bool Pipeline::executeStages(InstRef &IR) {
+ for (const std::unique_ptr<Stage> &S : Stages)
+ if (!S->execute(IR))
+ return false;
+ return true;
+}
+
+void Pipeline::preExecuteStages() {
+ for (const std::unique_ptr<Stage> &S : Stages)
+ S->preExecute();
+}
+
+void Pipeline::postExecuteStages() {
+ for (const std::unique_ptr<Stage> &S : Stages)
+ S->postExecute();
+}
+
+void Pipeline::run() {
+ while (hasWorkToProcess()) {
+ notifyCycleBegin();
+ runCycle();
+ notifyCycleEnd();
+ ++Cycles;
+ }
+}
+
+void Pipeline::runCycle() {
+ // Update the stages before we do any processing for this cycle.
+ InstRef IR;
+ for (auto &S : Stages)
+ S->cycleStart();
+
+ // Continue executing this cycle until any stage claims it cannot make
+ // progress.
+ while (true) {
+ preExecuteStages();
+ if (!executeStages(IR))
+ break;
+ postExecuteStages();
+ }
+
+ for (auto &S : Stages)
+ S->cycleEnd();
+}
+
+void Pipeline::notifyCycleBegin() {
+ LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycles << '\n');
+ for (HWEventListener *Listener : Listeners)
+ Listener->onCycleBegin();
+}
+
+void Pipeline::notifyCycleEnd() {
+ LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n\n");
+ for (HWEventListener *Listener : Listeners)
+ Listener->onCycleEnd();
+}
+} // namespace mca.
diff --git a/contrib/llvm/tools/llvm-mca/Pipeline.h b/contrib/llvm/tools/llvm-mca/Pipeline.h
new file mode 100644
index 000000000000..6916e422be39
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Pipeline.h
@@ -0,0 +1,79 @@
+//===--------------------- Pipeline.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements an ordered container of stages that simulate the
+/// pipeline of a hardware backend.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINE_H
+#define LLVM_TOOLS_LLVM_MCA_PIPELINE_H
+
+#include "Scheduler.h"
+#include "Stage.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace mca {
+
+class HWEventListener;
+class HWInstructionEvent;
+class HWStallEvent;
+
+/// A pipeline for a specific subtarget.
+///
+/// It emulates an out-of-order execution of instructions. Instructions are
+/// fetched from a MCInst sequence managed by an initial 'Fetch' stage.
+/// Instructions are firstly fetched, then dispatched to the schedulers, and
+/// then executed.
+///
+/// This class tracks the lifetime of an instruction from the moment where
+/// it gets dispatched to the schedulers, to the moment where it finishes
+/// executing and register writes are architecturally committed.
+/// In particular, it monitors changes in the state of every instruction
+/// in flight.
+///
+/// Instructions are executed in a loop of iterations. The number of iterations
+/// is defined by the SourceMgr object, which is managed by the initial stage
+/// of the instruction pipeline.
+///
+/// The Pipeline entry point is method 'run()' which executes cycles in a loop
+/// until there are new instructions to dispatch, and not every instruction
+/// has been retired.
+///
+/// Internally, the Pipeline collects statistical information in the form of
+/// histograms. For example, it tracks how the dispatch group size changes
+/// over time.
+class Pipeline {
+ Pipeline(const Pipeline &P) = delete;
+ Pipeline &operator=(const Pipeline &P) = delete;
+
+ /// An ordered list of stages that define this instruction pipeline.
+ llvm::SmallVector<std::unique_ptr<Stage>, 8> Stages;
+ std::set<HWEventListener *> Listeners;
+ unsigned Cycles;
+
+ void preExecuteStages();
+ bool executeStages(InstRef &IR);
+ void postExecuteStages();
+ void runCycle();
+
+ bool hasWorkToProcess();
+ void notifyCycleBegin();
+ void notifyCycleEnd();
+
+public:
+ Pipeline() : Cycles(0) {}
+ void appendStage(std::unique_ptr<Stage> S) { Stages.push_back(std::move(S)); }
+ void run();
+ void addEventListener(HWEventListener *Listener);
+};
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_PIPELINE_H
diff --git a/contrib/llvm/tools/llvm-mca/PipelinePrinter.cpp b/contrib/llvm/tools/llvm-mca/PipelinePrinter.cpp
new file mode 100644
index 000000000000..c5b1a12b792f
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/PipelinePrinter.cpp
@@ -0,0 +1,26 @@
+//===--------------------- PipelinePrinter.cpp ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the PipelinePrinter interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "PipelinePrinter.h"
+#include "View.h"
+
+namespace mca {
+
+using namespace llvm;
+
+void PipelinePrinter::printReport(llvm::raw_ostream &OS) const {
+ for (const auto &V : Views)
+ V->printView(OS);
+}
+} // namespace mca.
diff --git a/contrib/llvm/tools/llvm-mca/PipelinePrinter.h b/contrib/llvm/tools/llvm-mca/PipelinePrinter.h
new file mode 100644
index 000000000000..fe871414418f
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/PipelinePrinter.h
@@ -0,0 +1,52 @@
+//===--------------------- PipelinePrinter.h --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements class PipelinePrinter.
+///
+/// PipelinePrinter allows the customization of the performance report.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H
+#define LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H
+
+#include "Pipeline.h"
+#include "View.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+/// A printer class that knows how to collects statistics on the
+/// code analyzed by the llvm-mca tool.
+///
+/// This class knows how to print out the analysis information collected
+/// during the execution of the code. Internally, it delegates to other
+/// classes the task of printing out timeline information as well as
+/// resource pressure.
+class PipelinePrinter {
+ Pipeline &P;
+ llvm::SmallVector<std::unique_ptr<View>, 8> Views;
+
+public:
+ PipelinePrinter(Pipeline &pipeline) : P(pipeline) {}
+
+ void addView(std::unique_ptr<View> V) {
+ P.addEventListener(V.get());
+ Views.emplace_back(std::move(V));
+ }
+
+ void printReport(llvm::raw_ostream &OS) const;
+};
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H
diff --git a/contrib/llvm/tools/llvm-mca/RegisterFile.cpp b/contrib/llvm/tools/llvm-mca/RegisterFile.cpp
new file mode 100644
index 000000000000..44de105b8996
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RegisterFile.cpp
@@ -0,0 +1,343 @@
+//===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a register mapping file class. This class is responsible
+/// for managing hardware register files and the tracking of data dependencies
+/// between registers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "RegisterFile.h"
+#include "Instruction.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+RegisterFile::RegisterFile(const llvm::MCSchedModel &SM,
+ const llvm::MCRegisterInfo &mri, unsigned NumRegs)
+ : MRI(mri), RegisterMappings(mri.getNumRegs(),
+ {WriteRef(), {IndexPlusCostPairTy(0, 1), 0}}) {
+ initialize(SM, NumRegs);
+}
+
+void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
+ // Create a default register file that "sees" all the machine registers
+ // declared by the target. The number of physical registers in the default
+ // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
+ // means: this register file has an unbounded number of physical registers.
+ addRegisterFile({} /* all registers */, NumRegs);
+ if (!SM.hasExtraProcessorInfo())
+ return;
+
+ // For each user defined register file, allocate a RegisterMappingTracker
+ // object. The size of every register file, as well as the mapping between
+ // register files and register classes is specified via tablegen.
+ const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
+ for (unsigned I = 0, E = Info.NumRegisterFiles; I < E; ++I) {
+ const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
+ // Skip invalid register files with zero physical registers.
+ unsigned Length = RF.NumRegisterCostEntries;
+ if (!RF.NumPhysRegs)
+ continue;
+ // The cost of a register definition is equivalent to the number of
+ // physical registers that are allocated at register renaming stage.
+ const MCRegisterCostEntry *FirstElt =
+ &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
+ addRegisterFile(ArrayRef<MCRegisterCostEntry>(FirstElt, Length),
+ RF.NumPhysRegs);
+ }
+}
+
+void RegisterFile::addRegisterFile(ArrayRef<MCRegisterCostEntry> Entries,
+ unsigned NumPhysRegs) {
+ // A default register file is always allocated at index #0. That register file
+ // is mainly used to count the total number of mappings created by all
+ // register files at runtime. Users can limit the number of available physical
+ // registers in register file #0 through the command line flag
+ // `-register-file-size`.
+ unsigned RegisterFileIndex = RegisterFiles.size();
+ RegisterFiles.emplace_back(NumPhysRegs);
+
+ // Special case where there is no register class identifier in the set.
+ // An empty set of register classes means: this register file contains all
+ // the physical registers specified by the target.
+ // We optimistically assume that a register can be renamed at the cost of a
+ // single physical register. The constructor of RegisterFile ensures that
+ // a RegisterMapping exists for each logical register defined by the Target.
+ if (Entries.empty())
+ return;
+
+ // Now update the cost of individual registers.
+ for (const MCRegisterCostEntry &RCE : Entries) {
+ const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
+ for (const MCPhysReg Reg : RC) {
+ RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
+ IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
+ if (IPC.first && IPC.first != RegisterFileIndex) {
+ // The only register file that is allowed to overlap is the default
+ // register file at index #0. The analysis is inaccurate if register
+ // files overlap.
+ errs() << "warning: register " << MRI.getName(Reg)
+ << " defined in multiple register files.";
+ }
+ IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
+ Entry.RenameAs = Reg;
+
+ // Assume the same cost for each sub-register.
+ for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
+ RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
+ if (!OtherEntry.IndexPlusCost.first &&
+ (!OtherEntry.RenameAs ||
+ MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
+ OtherEntry.IndexPlusCost = IPC;
+ OtherEntry.RenameAs = Reg;
+ }
+ }
+ }
+ }
+}
+
+void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
+ MutableArrayRef<unsigned> UsedPhysRegs) {
+ unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
+ unsigned Cost = Entry.IndexPlusCost.second;
+ if (RegisterFileIndex) {
+ RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
+ RMT.NumUsedPhysRegs += Cost;
+ UsedPhysRegs[RegisterFileIndex] += Cost;
+ }
+
+ // Now update the default register mapping tracker.
+ RegisterFiles[0].NumUsedPhysRegs += Cost;
+ UsedPhysRegs[0] += Cost;
+}
+
+void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
+ MutableArrayRef<unsigned> FreedPhysRegs) {
+ unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
+ unsigned Cost = Entry.IndexPlusCost.second;
+ if (RegisterFileIndex) {
+ RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
+ RMT.NumUsedPhysRegs -= Cost;
+ FreedPhysRegs[RegisterFileIndex] += Cost;
+ }
+
+ // Now update the default register mapping tracker.
+ RegisterFiles[0].NumUsedPhysRegs -= Cost;
+ FreedPhysRegs[0] += Cost;
+}
+
+void RegisterFile::addRegisterWrite(WriteRef Write,
+ MutableArrayRef<unsigned> UsedPhysRegs,
+ bool ShouldAllocatePhysRegs) {
+ WriteState &WS = *Write.getWriteState();
+ unsigned RegID = WS.getRegisterID();
+ assert(RegID && "Adding an invalid register definition?");
+
+ LLVM_DEBUG({
+ dbgs() << "RegisterFile: addRegisterWrite [ " << Write.getSourceIndex()
+ << ", " << MRI.getName(RegID) << "]\n";
+ });
+
+ // If RenameAs is equal to RegID, then RegID is subject to register renaming
+ // and false dependencies on RegID are all eliminated.
+
+ // If RenameAs references the invalid register, then we optimistically assume
+ // that it can be renamed. In the absence of tablegen descriptors for register
+ // files, RenameAs is always set to the invalid register ID. In all other
+ // cases, RenameAs must be either equal to RegID, or it must reference a
+ // super-register of RegID.
+
+ // If RenameAs is a super-register of RegID, then a write to RegID has always
+ // a false dependency on RenameAs. The only exception is for when the write
+ // implicitly clears the upper portion of the underlying register.
+ // If a write clears its super-registers, then it is renamed as `RenameAs`.
+ const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
+ if (RRI.RenameAs && RRI.RenameAs != RegID) {
+ RegID = RRI.RenameAs;
+ const WriteRef &OtherWrite = RegisterMappings[RegID].first;
+
+ if (!WS.clearsSuperRegisters()) {
+ // The processor keeps the definition of `RegID` together with register
+ // `RenameAs`. Since this partial write is not renamed, no physical
+ // register is allocated.
+ ShouldAllocatePhysRegs = false;
+
+ if (OtherWrite.getSourceIndex() != Write.getSourceIndex()) {
+ // This partial write has a false dependency on RenameAs.
+ WS.setDependentWrite(OtherWrite.getWriteState());
+ }
+ }
+ }
+
+ // Update the mapping for register RegID including its sub-registers.
+ RegisterMappings[RegID].first = Write;
+ for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
+ RegisterMappings[*I].first = Write;
+
+ // No physical registers are allocated for instructions that are optimized in
+ // hardware. For example, zero-latency data-dependency breaking instructions
+ // don't consume physical registers.
+ if (ShouldAllocatePhysRegs)
+ allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
+
+ if (!WS.clearsSuperRegisters())
+ return;
+
+ for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
+ RegisterMappings[*I].first = Write;
+}
+
+void RegisterFile::removeRegisterWrite(const WriteState &WS,
+ MutableArrayRef<unsigned> FreedPhysRegs,
+ bool ShouldFreePhysRegs) {
+ unsigned RegID = WS.getRegisterID();
+
+ assert(RegID != 0 && "Invalidating an already invalid register?");
+ assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
+ "Invalidating a write of unknown cycles!");
+ assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
+
+ unsigned RenameAs = RegisterMappings[RegID].second.RenameAs;
+ if (RenameAs && RenameAs != RegID) {
+ RegID = RenameAs;
+
+ if (!WS.clearsSuperRegisters()) {
+ // Keep the definition of `RegID` together with register `RenameAs`.
+ ShouldFreePhysRegs = false;
+ }
+ }
+
+ if (ShouldFreePhysRegs)
+ freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
+
+ WriteRef &WR = RegisterMappings[RegID].first;
+ if (WR.getWriteState() == &WS)
+ WR.invalidate();
+
+ for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
+ WriteRef &OtherWR = RegisterMappings[*I].first;
+ if (OtherWR.getWriteState() == &WS)
+ OtherWR.invalidate();
+ }
+
+ if (!WS.clearsSuperRegisters())
+ return;
+
+ for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
+ WriteRef &OtherWR = RegisterMappings[*I].first;
+ if (OtherWR.getWriteState() == &WS)
+ OtherWR.invalidate();
+ }
+}
+
+void RegisterFile::collectWrites(SmallVectorImpl<WriteRef> &Writes,
+ unsigned RegID) const {
+ assert(RegID && RegID < RegisterMappings.size());
+ LLVM_DEBUG(dbgs() << "RegisterFile: collecting writes for register "
+ << MRI.getName(RegID) << '\n');
+ const WriteRef &WR = RegisterMappings[RegID].first;
+ if (WR.isValid())
+ Writes.push_back(WR);
+
+ // Handle potential partial register updates.
+ for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
+ const WriteRef &WR = RegisterMappings[*I].first;
+ if (WR.isValid())
+ Writes.push_back(WR);
+ }
+
+ // Remove duplicate entries and resize the input vector.
+ llvm::sort(Writes.begin(), Writes.end(),
+ [](const WriteRef &Lhs, const WriteRef &Rhs) {
+ return Lhs.getWriteState() < Rhs.getWriteState();
+ });
+ auto It = std::unique(Writes.begin(), Writes.end());
+ Writes.resize(std::distance(Writes.begin(), It));
+
+ LLVM_DEBUG({
+ for (const WriteRef &WR : Writes) {
+ const WriteState &WS = *WR.getWriteState();
+ dbgs() << "[PRF] Found a dependent use of Register "
+ << MRI.getName(WS.getRegisterID()) << " (defined by intruction #"
+ << WR.getSourceIndex() << ")\n";
+ }
+ });
+}
+
+unsigned RegisterFile::isAvailable(ArrayRef<unsigned> Regs) const {
+ SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
+
+ // Find how many new mappings must be created for each register file.
+ for (const unsigned RegID : Regs) {
+ const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
+ const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
+ if (Entry.first)
+ NumPhysRegs[Entry.first] += Entry.second;
+ NumPhysRegs[0] += Entry.second;
+ }
+
+ unsigned Response = 0;
+ for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
+ unsigned NumRegs = NumPhysRegs[I];
+ if (!NumRegs)
+ continue;
+
+ const RegisterMappingTracker &RMT = RegisterFiles[I];
+ if (!RMT.NumPhysRegs) {
+ // The register file has an unbounded number of microarchitectural
+ // registers.
+ continue;
+ }
+
+ if (RMT.NumPhysRegs < NumRegs) {
+ // The current register file is too small. This may occur if the number of
+ // microarchitectural registers in register file #0 was changed by the
+ // users via flag -reg-file-size. Alternatively, the scheduling model
+ // specified a too small number of registers for this register file.
+ report_fatal_error(
+ "Not enough microarchitectural registers in the register file");
+ }
+
+ if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
+ Response |= (1U << I);
+ }
+
+ return Response;
+}
+
+#ifndef NDEBUG
+void RegisterFile::dump() const {
+ for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
+ const RegisterMapping &RM = RegisterMappings[I];
+ if (!RM.first.getWriteState())
+ continue;
+ const RegisterRenamingInfo &RRI = RM.second;
+ dbgs() << MRI.getName(I) << ", " << I << ", PRF=" << RRI.IndexPlusCost.first
+ << ", Cost=" << RRI.IndexPlusCost.second
+ << ", RenameAs=" << RRI.RenameAs << ", ";
+ RM.first.dump();
+ dbgs() << '\n';
+ }
+
+ for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
+ dbgs() << "Register File #" << I;
+ const RegisterMappingTracker &RMT = RegisterFiles[I];
+ dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs
+ << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';
+ }
+}
+#endif
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/RegisterFile.h b/contrib/llvm/tools/llvm-mca/RegisterFile.h
new file mode 100644
index 000000000000..349e9789b6ee
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RegisterFile.h
@@ -0,0 +1,172 @@
+//===--------------------- RegisterFile.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a register mapping file class. This class is responsible
+/// for managing hardware register files and the tracking of data dependencies
+/// between registers.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H
+#define LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H
+
+#include "HardwareUnit.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSchedule.h"
+
+namespace mca {
+
+class ReadState;
+class WriteState;
+class WriteRef;
+
+/// Manages hardware register files, and tracks register definitions for
+/// register renaming purposes.
+class RegisterFile : public HardwareUnit {
+ const llvm::MCRegisterInfo &MRI;
+
+ // Each register file is associated with an instance of
+ // RegisterMappingTracker.
+ // A RegisterMappingTracker keeps track of the number of physical registers
+ // which have been dynamically allocated by the simulator.
+ struct RegisterMappingTracker {
+ // The total number of physical registers that are available in this
+ // register file for register renaming purpouses. A value of zero for this
+ // field means: this register file has an unbounded number of physical
+ // registers.
+ const unsigned NumPhysRegs;
+ // Number of physical registers that are currently in use.
+ unsigned NumUsedPhysRegs;
+
+ RegisterMappingTracker(unsigned NumPhysRegisters)
+ : NumPhysRegs(NumPhysRegisters), NumUsedPhysRegs(0) {}
+ };
+
+ // A vector of register file descriptors. This set always contains at least
+ // one entry. Entry at index #0 is reserved. That entry describes a register
+ // file with an unbounded number of physical registers that "sees" all the
+ // hardware registers declared by the target (i.e. all the register
+ // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is
+ // the target name).
+ //
+ // Users can limit the number of physical registers that are available in
+ // regsiter file #0 specifying command line flag `-register-file-size=<uint>`.
+ llvm::SmallVector<RegisterMappingTracker, 4> RegisterFiles;
+
+ // This type is used to propagate information about the owner of a register,
+ // and the cost of allocating it in the PRF. Register cost is defined as the
+ // number of physical registers consumed by the PRF to allocate a user
+ // register.
+ //
+ // For example: on X86 BtVer2, a YMM register consumes 2 128-bit physical
+ // registers. So, the cost of allocating a YMM register in BtVer2 is 2.
+ using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
+
+ // Struct RegisterRenamingInfo maps registers to register files.
+ // There is a RegisterRenamingInfo object for every register defined by
+ // the target. RegisteRenamingInfo objects are stored into vector
+ // RegisterMappings, and register IDs can be used to reference them.
+ struct RegisterRenamingInfo {
+ IndexPlusCostPairTy IndexPlusCost;
+ llvm::MCPhysReg RenameAs;
+ };
+
+ // RegisterMapping objects are mainly used to track physical register
+ // definitions. There is a RegisterMapping for every register defined by the
+ // Target. For each register, a RegisterMapping pair contains a descriptor of
+ // the last register write (in the form of a WriteRef object), as well as a
+ // RegisterRenamingInfo to quickly identify owning register files.
+ //
+ // This implementation does not allow overlapping register files. The only
+ // register file that is allowed to overlap with other register files is
+ // register file #0. If we exclude register #0, every register is "owned" by
+ // at most one register file.
+ using RegisterMapping = std::pair<WriteRef, RegisterRenamingInfo>;
+
+ // This map contains one entry for each register defined by the target.
+ std::vector<RegisterMapping> RegisterMappings;
+
+ // This method creates a new register file descriptor.
+ // The new register file owns all of the registers declared by register
+ // classes in the 'RegisterClasses' set.
+ //
+ // Processor models allow the definition of RegisterFile(s) via tablegen. For
+ // example, this is a tablegen definition for a x86 register file for
+ // XMM[0-15] and YMM[0-15], that allows up to 60 renames (each rename costs 1
+ // physical register).
+ //
+ // def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]>
+ //
+ // Here FPRegisterFile contains all the registers defined by register class
+ // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
+ // registers which can be used for register renaming purpose.
+ void
+ addRegisterFile(llvm::ArrayRef<llvm::MCRegisterCostEntry> RegisterClasses,
+ unsigned NumPhysRegs);
+
+ // Consumes physical registers in each register file specified by the
+ // `IndexPlusCostPairTy`. This method is called from `addRegisterMapping()`.
+ void allocatePhysRegs(const RegisterRenamingInfo &Entry,
+ llvm::MutableArrayRef<unsigned> UsedPhysRegs);
+
+ // Releases previously allocated physical registers from the register file(s).
+ // This method is called from `invalidateRegisterMapping()`.
+ void freePhysRegs(const RegisterRenamingInfo &Entry,
+ llvm::MutableArrayRef<unsigned> FreedPhysRegs);
+
+ // Create an instance of RegisterMappingTracker for every register file
+ // specified by the processor model.
+ // If no register file is specified, then this method creates a default
+ // register file with an unbounded number of physical registers.
+ void initialize(const llvm::MCSchedModel &SM, unsigned NumRegs);
+
+public:
+ RegisterFile(const llvm::MCSchedModel &SM, const llvm::MCRegisterInfo &mri,
+ unsigned NumRegs = 0);
+
+ // This method updates the register mappings inserting a new register
+ // definition. This method is also responsible for updating the number of
+ // allocated physical registers in each register file modified by the write.
+ // No physical regiser is allocated when flag ShouldAllocatePhysRegs is set.
+ void addRegisterWrite(WriteRef Write,
+ llvm::MutableArrayRef<unsigned> UsedPhysRegs,
+ bool ShouldAllocatePhysRegs = true);
+
+ // Removes write \param WS from the register mappings.
+ // Physical registers may be released to reflect this update.
+ void removeRegisterWrite(const WriteState &WS,
+ llvm::MutableArrayRef<unsigned> FreedPhysRegs,
+ bool ShouldFreePhysRegs = true);
+
+ // Checks if there are enough physical registers in the register files.
+ // Returns a "response mask" where each bit represents the response from a
+ // different register file. A mask of all zeroes means that all register
+ // files are available. Otherwise, the mask can be used to identify which
+ // register file was busy. This sematic allows us to classify dispatch
+ // stalls caused by the lack of register file resources.
+ //
+ // Current implementation can simulate up to 32 register files (including the
+ // special register file at index #0).
+ unsigned isAvailable(llvm::ArrayRef<unsigned> Regs) const;
+ void collectWrites(llvm::SmallVectorImpl<WriteRef> &Writes,
+ unsigned RegID) const;
+ void updateOnRead(ReadState &RS, unsigned RegID);
+
+ unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H
diff --git a/contrib/llvm/tools/llvm-mca/RegisterFileStatistics.cpp b/contrib/llvm/tools/llvm-mca/RegisterFileStatistics.cpp
new file mode 100644
index 000000000000..1b07bf9a3b33
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RegisterFileStatistics.cpp
@@ -0,0 +1,107 @@
+//===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the RegisterFileStatistics interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "RegisterFileStatistics.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+namespace mca {
+
+void RegisterFileStatistics::initializeRegisterFileInfo() {
+ const MCSchedModel &SM = STI.getSchedModel();
+ RegisterFileUsage Empty = {0, 0, 0};
+ if (!SM.hasExtraProcessorInfo()) {
+ // Assume a single register file.
+ RegisterFiles.emplace_back(Empty);
+ return;
+ }
+
+ // Initialize a RegisterFileUsage for every user defined register file, plus
+ // the default register file which is always at index #0.
+ const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();
+ // There is always an "InvalidRegisterFile" entry in tablegen. That entry can
+ // be skipped. If there are no user defined register files, then reserve a
+ // single entry for the default register file at index #0.
+ unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);
+ RegisterFiles.resize(NumRegFiles);
+ std::fill(RegisterFiles.begin(), RegisterFiles.end(), Empty);
+}
+
+void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
+ switch (Event.Type) {
+ default:
+ break;
+ case HWInstructionEvent::Retired: {
+ const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
+ for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I)
+ RegisterFiles[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
+ break;
+ }
+ case HWInstructionEvent::Dispatched: {
+ const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
+ for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I) {
+ RegisterFileUsage &RFU = RegisterFiles[I];
+ unsigned NumUsedPhysRegs = DE.UsedPhysRegs[I];
+ RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
+ RFU.TotalMappings += NumUsedPhysRegs;
+ RFU.MaxUsedMappings =
+ std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
+ }
+ }
+ }
+}
+
+void RegisterFileStatistics::printView(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+
+ TempStream << "\n\nRegister File statistics:";
+ const RegisterFileUsage &GlobalUsage = RegisterFiles[0];
+ TempStream << "\nTotal number of mappings created: "
+ << GlobalUsage.TotalMappings;
+ TempStream << "\nMax number of mappings used: "
+ << GlobalUsage.MaxUsedMappings << '\n';
+
+ for (unsigned I = 1, E = RegisterFiles.size(); I < E; ++I) {
+ const RegisterFileUsage &RFU = RegisterFiles[I];
+ // Obtain the register file descriptor from the scheduling model.
+ assert(STI.getSchedModel().hasExtraProcessorInfo() &&
+ "Unable to find register file info!");
+ const MCExtraProcessorInfo &PI =
+ STI.getSchedModel().getExtraProcessorInfo();
+ assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
+ const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
+ // Skip invalid register files.
+ if (!RFDesc.NumPhysRegs)
+ continue;
+
+ TempStream << "\n* Register File #" << I;
+ TempStream << " -- " << StringRef(RFDesc.Name) << ':';
+ TempStream << "\n Number of physical registers: ";
+ if (!RFDesc.NumPhysRegs)
+ TempStream << "unbounded";
+ else
+ TempStream << RFDesc.NumPhysRegs;
+ TempStream << "\n Total number of mappings created: "
+ << RFU.TotalMappings;
+ TempStream << "\n Max number of mappings used: "
+ << RFU.MaxUsedMappings << '\n';
+ }
+
+ TempStream.flush();
+ OS << Buffer;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/RegisterFileStatistics.h b/contrib/llvm/tools/llvm-mca/RegisterFileStatistics.h
new file mode 100644
index 000000000000..cbe816cd3332
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RegisterFileStatistics.h
@@ -0,0 +1,67 @@
+//===--------------------- RegisterFileStatistics.h -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This view collects and prints register file usage statistics.
+///
+/// Example (-mcpu=btver2):
+/// ========================
+///
+/// Register File statistics:
+/// Total number of mappings created: 6
+/// Max number of mappings used: 3
+///
+/// * Register File #1 -- FpuPRF:
+/// Number of physical registers: 72
+/// Total number of mappings created: 0
+/// Max number of mappings used: 0
+///
+/// * Register File #2 -- IntegerPRF:
+/// Number of physical registers: 64
+/// Total number of mappings created: 6
+/// Max number of mappings used: 3
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_REGISTERFILESTATISTICS_H
+#define LLVM_TOOLS_LLVM_MCA_REGISTERFILESTATISTICS_H
+
+#include "View.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+namespace mca {
+
+class RegisterFileStatistics : public View {
+ const llvm::MCSubtargetInfo &STI;
+
+ // Used to track the number of physical registers used in a register file.
+ struct RegisterFileUsage {
+ unsigned TotalMappings;
+ unsigned MaxUsedMappings;
+ unsigned CurrentlyUsedMappings;
+ };
+
+ // There is one entry for each register file implemented by the processor.
+ llvm::SmallVector<RegisterFileUsage, 4> RegisterFiles;
+
+ void initializeRegisterFileInfo();
+
+public:
+ RegisterFileStatistics(const llvm::MCSubtargetInfo &sti) : STI(sti) {
+ initializeRegisterFileInfo();
+ }
+
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ void printView(llvm::raw_ostream &OS) const override;
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/ResourcePressureView.cpp b/contrib/llvm/tools/llvm-mca/ResourcePressureView.cpp
new file mode 100644
index 000000000000..fe9d5b7fabc8
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/ResourcePressureView.cpp
@@ -0,0 +1,171 @@
+//===--------------------- ResourcePressureView.cpp -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements methods in the ResourcePressureView interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ResourcePressureView.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace mca {
+
+using namespace llvm;
+
+void ResourcePressureView::initialize() {
+ // Populate the map of resource descriptors.
+ unsigned R2VIndex = 0;
+ const MCSchedModel &SM = STI.getSchedModel();
+ for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ unsigned NumUnits = ProcResource.NumUnits;
+ // Skip groups and invalid resources with zero units.
+ if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+ continue;
+
+ Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex));
+ R2VIndex += ProcResource.NumUnits;
+ }
+
+ NumResourceUnits = R2VIndex;
+ ResourceUsage.resize(NumResourceUnits * (Source.size() + 1));
+ std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
+}
+
+void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
+ // We're only interested in Issue events.
+ if (Event.Type != HWInstructionEvent::Issued)
+ return;
+ const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
+ const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
+ for (const std::pair<ResourceRef, double> &Use : IssueEvent.UsedResources) {
+ const ResourceRef &RR = Use.first;
+ assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
+ unsigned R2VIndex = Resource2VecIndex[RR.first];
+ R2VIndex += countTrailingZeros(RR.second);
+ ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
+ ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
+ }
+}
+
+static void printColumnNames(formatted_raw_ostream &OS,
+ const MCSchedModel &SM) {
+ unsigned Column = OS.getColumn();
+ for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
+ I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ unsigned NumUnits = ProcResource.NumUnits;
+ // Skip groups and invalid resources with zero units.
+ if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+ continue;
+
+ for (unsigned J = 0; J < NumUnits; ++J) {
+ Column += 7;
+ OS << "[" << ResourceIndex;
+ if (NumUnits > 1)
+ OS << '.' << J;
+ OS << ']';
+ OS.PadToColumn(Column);
+ }
+
+ ResourceIndex++;
+ }
+}
+
+static void printResourcePressure(formatted_raw_ostream &OS, double Pressure,
+ unsigned Col) {
+ if (!Pressure || Pressure < 0.005) {
+ OS << " - ";
+ } else {
+ // Round to the value to the nearest hundredth and then print it.
+ OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100);
+ }
+ OS.PadToColumn(Col);
+}
+
+void ResourcePressureView::printResourcePressurePerIteration(
+ raw_ostream &OS, unsigned Executions) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ formatted_raw_ostream FOS(TempStream);
+
+ FOS << "\n\nResources:\n";
+ const MCSchedModel &SM = STI.getSchedModel();
+ for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
+ I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ unsigned NumUnits = ProcResource.NumUnits;
+ // Skip groups and invalid resources with zero units.
+ if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+ continue;
+
+ for (unsigned J = 0; J < NumUnits; ++J) {
+ FOS << '[' << ResourceIndex;
+ if (NumUnits > 1)
+ FOS << '.' << J;
+ FOS << ']';
+ FOS.PadToColumn(6);
+ FOS << "- " << ProcResource.Name << '\n';
+ }
+
+ ResourceIndex++;
+ }
+
+ FOS << "\n\nResource pressure per iteration:\n";
+ FOS.flush();
+ printColumnNames(FOS, SM);
+ FOS << '\n';
+ FOS.flush();
+
+ for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
+ double Usage = ResourceUsage[I + Source.size() * E];
+ printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
+ }
+
+ FOS.flush();
+ OS << Buffer;
+}
+
+void ResourcePressureView::printResourcePressurePerInstruction(
+ raw_ostream &OS, unsigned Executions) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ formatted_raw_ostream FOS(TempStream);
+
+ FOS << "\n\nResource pressure by instruction:\n";
+ printColumnNames(FOS, STI.getSchedModel());
+ FOS << "Instructions:\n";
+
+ std::string Instruction;
+ raw_string_ostream InstrStream(Instruction);
+
+ for (unsigned I = 0, E = Source.size(); I < E; ++I) {
+ for (unsigned J = 0; J < NumResourceUnits; ++J) {
+ double Usage = ResourceUsage[J + I * NumResourceUnits];
+ printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
+ }
+
+ MCIP.printInst(&Source.getMCInstFromIndex(I), InstrStream, "", STI);
+ InstrStream.flush();
+ StringRef Str(Instruction);
+
+ // Remove any tabs or spaces at the beginning of the instruction.
+ Str = Str.ltrim();
+
+ FOS << Str << '\n';
+ Instruction = "";
+
+ FOS.flush();
+ OS << Buffer;
+ Buffer = "";
+ }
+}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/ResourcePressureView.h b/contrib/llvm/tools/llvm-mca/ResourcePressureView.h
new file mode 100644
index 000000000000..fe1c6af5e6f6
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/ResourcePressureView.h
@@ -0,0 +1,109 @@
+//===--------------------- ResourcePressureView.h ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file define class ResourcePressureView.
+/// Class ResourcePressureView observes hardware events generated by
+/// the Pipeline object and collects statistics related to resource usage at
+/// instruction granularity.
+/// Resource pressure information is then printed out to a stream in the
+/// form of a table like the one from the example below:
+///
+/// Resources:
+/// [0] - JALU0
+/// [1] - JALU1
+/// [2] - JDiv
+/// [3] - JFPM
+/// [4] - JFPU0
+/// [5] - JFPU1
+/// [6] - JLAGU
+/// [7] - JSAGU
+/// [8] - JSTC
+/// [9] - JVIMUL
+///
+/// Resource pressure per iteration:
+/// [0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
+/// 0.00 0.00 0.00 0.00 2.00 2.00 0.00 0.00 0.00 0.00
+///
+/// Resource pressure by instruction:
+/// [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions:
+/// - - - - - 1.00 - - - - vpermilpd $1, %xmm0,
+/// %xmm1
+/// - - - - 1.00 - - - - - vaddps %xmm0, %xmm1,
+/// %xmm2
+/// - - - - - 1.00 - - - - vmovshdup %xmm2, %xmm3
+/// - - - - 1.00 - - - - - vaddss %xmm2, %xmm3,
+/// %xmm4
+///
+/// In this example, we have AVX code executed on AMD Jaguar (btver2).
+/// Both shuffles and vector floating point add operations on XMM registers have
+/// a reciprocal throughput of 1cy.
+/// Each add is issued to pipeline JFPU0, while each shuffle is issued to
+/// pipeline JFPU1. The overall pressure per iteration is reported by two
+/// tables: the first smaller table is the resource pressure per iteration;
+/// the second table reports resource pressure per instruction. Values are the
+/// average resource cycles consumed by an instruction.
+/// Every vector add from the example uses resource JFPU0 for an average of 1cy
+/// per iteration. Consequently, the resource pressure on JFPU0 is of 2cy per
+/// iteration.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_RESOURCEPRESSUREVIEW_H
+#define LLVM_TOOLS_LLVM_MCA_RESOURCEPRESSUREVIEW_H
+
+#include "SourceMgr.h"
+#include "View.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include <map>
+
+namespace mca {
+
+/// This class collects resource pressure statistics and it is able to print
+/// out all the collected information as a table to an output stream.
+class ResourcePressureView : public View {
+ const llvm::MCSubtargetInfo &STI;
+ llvm::MCInstPrinter &MCIP;
+ const SourceMgr &Source;
+
+ // Map to quickly obtain the ResourceUsage column index from a processor
+ // resource ID.
+ llvm::DenseMap<unsigned, unsigned> Resource2VecIndex;
+
+ // Table of resources used by instructions.
+ std::vector<double> ResourceUsage;
+ unsigned NumResourceUnits;
+
+ const llvm::MCInst &GetMCInstFromIndex(unsigned Index) const;
+ void printResourcePressurePerIteration(llvm::raw_ostream &OS,
+ unsigned Executions) const;
+ void printResourcePressurePerInstruction(llvm::raw_ostream &OS,
+ unsigned Executions) const;
+ void initialize();
+
+public:
+ ResourcePressureView(const llvm::MCSubtargetInfo &sti,
+ llvm::MCInstPrinter &Printer, const SourceMgr &SM)
+ : STI(sti), MCIP(Printer), Source(SM) {
+ initialize();
+ }
+
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ void printView(llvm::raw_ostream &OS) const override {
+ unsigned Executions = Source.getNumIterations();
+ printResourcePressurePerIteration(OS, Executions);
+ printResourcePressurePerInstruction(OS, Executions);
+ }
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/RetireControlUnit.cpp b/contrib/llvm/tools/llvm-mca/RetireControlUnit.cpp
new file mode 100644
index 000000000000..123058541f28
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RetireControlUnit.cpp
@@ -0,0 +1,87 @@
+//===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file simulates the hardware responsible for retiring instructions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "RetireControlUnit.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM)
+ : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
+ AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0) {
+ // Check if the scheduling model provides extra information about the machine
+ // processor. If so, then use that information to set the reorder buffer size
+ // and the maximum number of instructions retired per cycle.
+ if (SM.hasExtraProcessorInfo()) {
+ const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
+ if (EPI.ReorderBufferSize)
+ AvailableSlots = EPI.ReorderBufferSize;
+ MaxRetirePerCycle = EPI.MaxRetirePerCycle;
+ }
+
+ assert(AvailableSlots && "Invalid reorder buffer size!");
+ Queue.resize(AvailableSlots);
+}
+
+// Reserves a number of slots, and returns a new token.
+unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
+ unsigned NumMicroOps) {
+ assert(isAvailable(NumMicroOps));
+ unsigned NormalizedQuantity =
+ std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
+ // Zero latency instructions may have zero mOps. Artificially bump this
+ // value to 1. Although zero latency instructions don't consume scheduler
+ // resources, they still consume one slot in the retire queue.
+ NormalizedQuantity = std::max(NormalizedQuantity, 1U);
+ unsigned TokenID = NextAvailableSlotIdx;
+ Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
+ NextAvailableSlotIdx += NormalizedQuantity;
+ NextAvailableSlotIdx %= Queue.size();
+ AvailableSlots -= NormalizedQuantity;
+ return TokenID;
+}
+
+const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const {
+ return Queue[CurrentInstructionSlotIdx];
+}
+
+void RetireControlUnit::consumeCurrentToken() {
+ const RetireControlUnit::RUToken &Current = peekCurrentToken();
+ assert(Current.NumSlots && "Reserved zero slots?");
+ assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue.");
+
+ // Update the slot index to be the next item in the circular queue.
+ CurrentInstructionSlotIdx += Current.NumSlots;
+ CurrentInstructionSlotIdx %= Queue.size();
+ AvailableSlots += Current.NumSlots;
+}
+
+void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
+ assert(Queue.size() > TokenID);
+ assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid());
+ Queue[TokenID].Executed = true;
+}
+
+#ifndef NDEBUG
+void RetireControlUnit::dump() const {
+ dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
+ << ", Available Slots=" << AvailableSlots << " }\n";
+}
+#endif
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/RetireControlUnit.h b/contrib/llvm/tools/llvm-mca/RetireControlUnit.h
new file mode 100644
index 000000000000..8acc8bcc98fe
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RetireControlUnit.h
@@ -0,0 +1,98 @@
+//===---------------------- RetireControlUnit.h -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file simulates the hardware responsible for retiring instructions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H
+#define LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H
+
+#include "HardwareUnit.h"
+#include "Instruction.h"
+#include "llvm/MC/MCSchedule.h"
+#include <vector>
+
+namespace mca {
+
+/// This class tracks which instructions are in-flight (i.e., dispatched but not
+/// retired) in the OoO backend.
+//
+/// This class checks on every cycle if/which instructions can be retired.
+/// Instructions are retired in program order.
+/// In the event of an instruction being retired, the pipeline that owns
+/// this RetireControlUnit (RCU) gets notified.
+///
+/// On instruction retired, register updates are all architecturally
+/// committed, and any physicall registers previously allocated for the
+/// retired instruction are freed.
+struct RetireControlUnit : public HardwareUnit {
+ // A RUToken is created by the RCU for every instruction dispatched to the
+ // schedulers. These "tokens" are managed by the RCU in its token Queue.
+ //
+ // On every cycle ('cycleEvent'), the RCU iterates through the token queue
+ // looking for any token with its 'Executed' flag set. If a token has that
+ // flag set, then the instruction has reached the write-back stage and will
+ // be retired by the RCU.
+ //
+ // 'NumSlots' represents the number of entries consumed by the instruction in
+ // the reorder buffer. Those entries will become available again once the
+ // instruction is retired.
+ //
+ // Note that the size of the reorder buffer is defined by the scheduling
+ // model via field 'NumMicroOpBufferSize'.
+ struct RUToken {
+ InstRef IR;
+ unsigned NumSlots; // Slots reserved to this instruction.
+ bool Executed; // True if the instruction is past the WB stage.
+ };
+
+private:
+ unsigned NextAvailableSlotIdx;
+ unsigned CurrentInstructionSlotIdx;
+ unsigned AvailableSlots;
+ unsigned MaxRetirePerCycle; // 0 means no limit.
+ std::vector<RUToken> Queue;
+
+public:
+ RetireControlUnit(const llvm::MCSchedModel &SM);
+
+ bool isFull() const { return !AvailableSlots; }
+ bool isEmpty() const { return AvailableSlots == Queue.size(); }
+ bool isAvailable(unsigned Quantity = 1) const {
+ // Some instructions may declare a number of uOps which exceeds the size
+ // of the reorder buffer. To avoid problems, cap the amount of slots to
+ // the size of the reorder buffer.
+ Quantity = std::min(Quantity, static_cast<unsigned>(Queue.size()));
+ return AvailableSlots >= Quantity;
+ }
+
+ unsigned getMaxRetirePerCycle() const { return MaxRetirePerCycle; }
+
+ // Reserves a number of slots, and returns a new token.
+ unsigned reserveSlot(const InstRef &IS, unsigned NumMicroOps);
+
+ // Return the current token from the RCU's circular token queue.
+ const RUToken &peekCurrentToken() const;
+
+ // Advance the pointer to the next token in the circular token queue.
+ void consumeCurrentToken();
+
+ // Update the RCU token to represent the executed state.
+ void onInstructionExecuted(unsigned TokenID);
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H
diff --git a/contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.cpp b/contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.cpp
new file mode 100644
index 000000000000..edb855e11e84
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.cpp
@@ -0,0 +1,49 @@
+//===--------------------- RetireControlUnitStatistics.cpp ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the RetireControlUnitStatistics interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "RetireControlUnitStatistics.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+namespace mca {
+
+void RetireControlUnitStatistics::onEvent(const HWInstructionEvent &Event) {
+ if (Event.Type == HWInstructionEvent::Retired)
+ ++NumRetired;
+}
+
+void RetireControlUnitStatistics::printView(llvm::raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ TempStream << "\n\nRetire Control Unit - "
+ << "number of cycles where we saw N instructions retired:\n";
+ TempStream << "[# retired], [# cycles]\n";
+
+ for (const std::pair<unsigned, unsigned> &Entry : RetiredPerCycle) {
+ TempStream << " " << Entry.first;
+ if (Entry.first < 10)
+ TempStream << ", ";
+ else
+ TempStream << ", ";
+ TempStream << Entry.second << " ("
+ << format("%.1f", ((double)Entry.second / NumCycles) * 100.0)
+ << "%)\n";
+ }
+
+ TempStream.flush();
+ OS << Buffer;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.h b/contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.h
new file mode 100644
index 000000000000..1f03e7efe889
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RetireControlUnitStatistics.h
@@ -0,0 +1,60 @@
+//===--------------------- RetireControlUnitStatistics.h --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines class RetireControlUnitStatistics: a view that knows how
+/// to print general statistics related to the retire control unit.
+///
+/// Example:
+/// ========
+///
+/// Retire Control Unit - number of cycles where we saw N instructions retired:
+/// [# retired], [# cycles]
+/// 0, 9 (6.9%)
+/// 1, 6 (4.6%)
+/// 2, 1 (0.8%)
+/// 4, 3 (2.3%)
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_RETIRECONTROLUNITSTATISTICS_H
+#define LLVM_TOOLS_LLVM_MCA_RETIRECONTROLUNITSTATISTICS_H
+
+#include "View.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include <map>
+
+namespace mca {
+
+class RetireControlUnitStatistics : public View {
+ using Histogram = std::map<unsigned, unsigned>;
+ Histogram RetiredPerCycle;
+
+ unsigned NumRetired;
+ unsigned NumCycles;
+
+ void updateHistograms() {
+ RetiredPerCycle[NumRetired]++;
+ NumRetired = 0;
+ }
+
+public:
+ RetireControlUnitStatistics() : NumRetired(0), NumCycles(0) {}
+
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ void onCycleBegin() override { NumCycles++; }
+
+ void onCycleEnd() override { updateHistograms(); }
+
+ void printView(llvm::raw_ostream &OS) const override;
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/RetireStage.cpp b/contrib/llvm/tools/llvm-mca/RetireStage.cpp
new file mode 100644
index 000000000000..55c3b887e478
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RetireStage.cpp
@@ -0,0 +1,57 @@
+//===---------------------- RetireStage.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the retire stage of an instruction pipeline.
+/// The RetireStage represents the process logic that interacts with the
+/// simulated RetireControlUnit hardware.
+///
+//===----------------------------------------------------------------------===//
+
+#include "RetireStage.h"
+#include "HWEventListener.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+void RetireStage::cycleStart() {
+ if (RCU.isEmpty())
+ return;
+
+ const unsigned MaxRetirePerCycle = RCU.getMaxRetirePerCycle();
+ unsigned NumRetired = 0;
+ while (!RCU.isEmpty()) {
+ if (MaxRetirePerCycle != 0 && NumRetired == MaxRetirePerCycle)
+ break;
+ const RetireControlUnit::RUToken &Current = RCU.peekCurrentToken();
+ if (!Current.Executed)
+ break;
+ RCU.consumeCurrentToken();
+ notifyInstructionRetired(Current.IR);
+ NumRetired++;
+ }
+}
+
+void RetireStage::notifyInstructionRetired(const InstRef &IR) {
+ LLVM_DEBUG(dbgs() << "[E] Instruction Retired: #" << IR << '\n');
+ SmallVector<unsigned, 4> FreedRegs(PRF.getNumRegisterFiles());
+ const Instruction &Inst = *IR.getInstruction();
+ const InstrDesc &Desc = Inst.getDesc();
+
+ bool ShouldFreeRegs = !(Desc.isZeroLatency() && Inst.isDependencyBreaking());
+ for (const std::unique_ptr<WriteState> &WS : Inst.getDefs())
+ PRF.removeRegisterWrite(*WS.get(), FreedRegs, ShouldFreeRegs);
+ notifyEvent<HWInstructionEvent>(HWInstructionRetiredEvent(IR, FreedRegs));
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/RetireStage.h b/contrib/llvm/tools/llvm-mca/RetireStage.h
new file mode 100644
index 000000000000..8cf672d92c6e
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/RetireStage.h
@@ -0,0 +1,48 @@
+//===---------------------- RetireStage.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the retire stage of an instruction pipeline.
+/// The RetireStage represents the process logic that interacts with the
+/// simulated RetireControlUnit hardware.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_STAGE_H
+#define LLVM_TOOLS_LLVM_MCA_RETIRE_STAGE_H
+
+#include "RegisterFile.h"
+#include "RetireControlUnit.h"
+#include "Stage.h"
+
+namespace mca {
+
+class RetireStage : public Stage {
+ // Owner will go away when we move listeners/eventing to the stages.
+ RetireControlUnit &RCU;
+ RegisterFile &PRF;
+
+public:
+ RetireStage(RetireControlUnit &R, RegisterFile &F)
+ : Stage(), RCU(R), PRF(F) {}
+ RetireStage(const RetireStage &Other) = delete;
+ RetireStage &operator=(const RetireStage &Other) = delete;
+
+ virtual bool hasWorkToComplete() const override final {
+ return !RCU.isEmpty();
+ }
+ virtual void cycleStart() override final;
+ virtual bool execute(InstRef &IR) override final { return true; }
+ void notifyInstructionRetired(const InstRef &IR);
+ void onInstructionExecuted(unsigned TokenID);
+};
+
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_RETIRE_STAGE_H
diff --git a/contrib/llvm/tools/llvm-mca/Scheduler.cpp b/contrib/llvm/tools/llvm-mca/Scheduler.cpp
new file mode 100644
index 000000000000..975a50e4b638
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Scheduler.cpp
@@ -0,0 +1,403 @@
+//===--------------------- Scheduler.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A scheduler for processor resource units and processor resource groups.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Scheduler.h"
+#include "Support.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace mca {
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+uint64_t ResourceState::selectNextInSequence() {
+ assert(isReady());
+ uint64_t Next = getNextInSequence();
+ while (!isSubResourceReady(Next)) {
+ updateNextInSequence();
+ Next = getNextInSequence();
+ }
+ return Next;
+}
+
+#ifndef NDEBUG
+void ResourceState::dump() const {
+ dbgs() << "MASK: " << ResourceMask << ", SIZE_MASK: " << ResourceSizeMask
+ << ", NEXT: " << NextInSequenceMask << ", RDYMASK: " << ReadyMask
+ << ", BufferSize=" << BufferSize
+ << ", AvailableSlots=" << AvailableSlots
+ << ", Reserved=" << Unavailable << '\n';
+}
+#endif
+
+void ResourceManager::initialize(const llvm::MCSchedModel &SM) {
+ computeProcResourceMasks(SM, ProcResID2Mask);
+ for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I)
+ addResource(*SM.getProcResource(I), I, ProcResID2Mask[I]);
+}
+
+// Adds a new resource state in Resources, as well as a new descriptor in
+// ResourceDescriptor. Map 'Resources' allows to quickly obtain ResourceState
+// objects from resource mask identifiers.
+void ResourceManager::addResource(const MCProcResourceDesc &Desc,
+ unsigned Index, uint64_t Mask) {
+ assert(Resources.find(Mask) == Resources.end() && "Resource already added!");
+ Resources[Mask] = llvm::make_unique<ResourceState>(Desc, Index, Mask);
+}
+
+// Returns the actual resource consumed by this Use.
+// First, is the primary resource ID.
+// Second, is the specific sub-resource ID.
+std::pair<uint64_t, uint64_t> ResourceManager::selectPipe(uint64_t ResourceID) {
+ ResourceState &RS = *Resources[ResourceID];
+ uint64_t SubResourceID = RS.selectNextInSequence();
+ if (RS.isAResourceGroup())
+ return selectPipe(SubResourceID);
+ return std::pair<uint64_t, uint64_t>(ResourceID, SubResourceID);
+}
+
+void ResourceState::removeFromNextInSequence(uint64_t ID) {
+ assert(NextInSequenceMask);
+ assert(countPopulation(ID) == 1);
+ if (ID > getNextInSequence())
+ RemovedFromNextInSequence |= ID;
+ NextInSequenceMask = NextInSequenceMask & (~ID);
+ if (!NextInSequenceMask) {
+ NextInSequenceMask = ResourceSizeMask;
+ assert(NextInSequenceMask != RemovedFromNextInSequence);
+ NextInSequenceMask ^= RemovedFromNextInSequence;
+ RemovedFromNextInSequence = 0;
+ }
+}
+
+void ResourceManager::use(ResourceRef RR) {
+ // Mark the sub-resource referenced by RR as used.
+ ResourceState &RS = *Resources[RR.first];
+ RS.markSubResourceAsUsed(RR.second);
+ // If there are still available units in RR.first,
+ // then we are done.
+ if (RS.isReady())
+ return;
+
+ // Notify to other resources that RR.first is no longer available.
+ for (const std::pair<uint64_t, UniqueResourceState> &Res : Resources) {
+ ResourceState &Current = *Res.second.get();
+ if (!Current.isAResourceGroup() || Current.getResourceMask() == RR.first)
+ continue;
+
+ if (Current.containsResource(RR.first)) {
+ Current.markSubResourceAsUsed(RR.first);
+ Current.removeFromNextInSequence(RR.first);
+ }
+ }
+}
+
+void ResourceManager::release(ResourceRef RR) {
+ ResourceState &RS = *Resources[RR.first];
+ bool WasFullyUsed = !RS.isReady();
+ RS.releaseSubResource(RR.second);
+ if (!WasFullyUsed)
+ return;
+
+ for (const std::pair<uint64_t, UniqueResourceState> &Res : Resources) {
+ ResourceState &Current = *Res.second.get();
+ if (!Current.isAResourceGroup() || Current.getResourceMask() == RR.first)
+ continue;
+
+ if (Current.containsResource(RR.first))
+ Current.releaseSubResource(RR.first);
+ }
+}
+
+ResourceStateEvent
+ResourceManager::canBeDispatched(ArrayRef<uint64_t> Buffers) const {
+ ResourceStateEvent Result = ResourceStateEvent::RS_BUFFER_AVAILABLE;
+ for (uint64_t Buffer : Buffers) {
+ Result = isBufferAvailable(Buffer);
+ if (Result != ResourceStateEvent::RS_BUFFER_AVAILABLE)
+ break;
+ }
+ return Result;
+}
+
+void ResourceManager::reserveBuffers(ArrayRef<uint64_t> Buffers) {
+ for (const uint64_t R : Buffers) {
+ reserveBuffer(R);
+ ResourceState &Resource = *Resources[R];
+ if (Resource.isADispatchHazard()) {
+ assert(!Resource.isReserved());
+ Resource.setReserved();
+ }
+ }
+}
+
+void ResourceManager::releaseBuffers(ArrayRef<uint64_t> Buffers) {
+ for (const uint64_t R : Buffers)
+ releaseBuffer(R);
+}
+
+bool ResourceManager::canBeIssued(const InstrDesc &Desc) const {
+ return std::all_of(Desc.Resources.begin(), Desc.Resources.end(),
+ [&](const std::pair<uint64_t, const ResourceUsage> &E) {
+ unsigned NumUnits =
+ E.second.isReserved() ? 0U : E.second.NumUnits;
+ return isReady(E.first, NumUnits);
+ });
+}
+
+// Returns true if all resources are in-order, and there is at least one
+// resource which is a dispatch hazard (BufferSize = 0).
+bool ResourceManager::mustIssueImmediately(const InstrDesc &Desc) {
+ if (!canBeIssued(Desc))
+ return false;
+ bool AllInOrderResources = all_of(Desc.Buffers, [&](uint64_t BufferMask) {
+ const ResourceState &Resource = *Resources[BufferMask];
+ return Resource.isInOrder() || Resource.isADispatchHazard();
+ });
+ if (!AllInOrderResources)
+ return false;
+
+ return any_of(Desc.Buffers, [&](uint64_t BufferMask) {
+ return Resources[BufferMask]->isADispatchHazard();
+ });
+}
+
+void ResourceManager::issueInstruction(
+ const InstrDesc &Desc,
+ SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes) {
+ for (const std::pair<uint64_t, ResourceUsage> &R : Desc.Resources) {
+ const CycleSegment &CS = R.second.CS;
+ if (!CS.size()) {
+ releaseResource(R.first);
+ continue;
+ }
+
+ assert(CS.begin() == 0 && "Invalid {Start, End} cycles!");
+ if (!R.second.isReserved()) {
+ ResourceRef Pipe = selectPipe(R.first);
+ use(Pipe);
+ BusyResources[Pipe] += CS.size();
+ // Replace the resource mask with a valid processor resource index.
+ const ResourceState &RS = *Resources[Pipe.first];
+ Pipe.first = RS.getProcResourceID();
+ Pipes.emplace_back(
+ std::pair<ResourceRef, double>(Pipe, static_cast<double>(CS.size())));
+ } else {
+ assert((countPopulation(R.first) > 1) && "Expected a group!");
+ // Mark this group as reserved.
+ assert(R.second.isReserved());
+ reserveResource(R.first);
+ BusyResources[ResourceRef(R.first, R.first)] += CS.size();
+ }
+ }
+}
+
+void ResourceManager::cycleEvent(SmallVectorImpl<ResourceRef> &ResourcesFreed) {
+ for (std::pair<ResourceRef, unsigned> &BR : BusyResources) {
+ if (BR.second)
+ BR.second--;
+ if (!BR.second) {
+ // Release this resource.
+ const ResourceRef &RR = BR.first;
+
+ if (countPopulation(RR.first) == 1)
+ release(RR);
+
+ releaseResource(RR.first);
+ ResourcesFreed.push_back(RR);
+ }
+ }
+
+ for (const ResourceRef &RF : ResourcesFreed)
+ BusyResources.erase(RF);
+}
+
+#ifndef NDEBUG
+void Scheduler::dump() const {
+ dbgs() << "[SCHEDULER]: WaitQueue size is: " << WaitQueue.size() << '\n';
+ dbgs() << "[SCHEDULER]: ReadyQueue size is: " << ReadyQueue.size() << '\n';
+ dbgs() << "[SCHEDULER]: IssuedQueue size is: " << IssuedQueue.size() << '\n';
+ Resources->dump();
+}
+#endif
+
+bool Scheduler::canBeDispatched(const InstRef &IR,
+ HWStallEvent::GenericEventType &Event) const {
+ Event = HWStallEvent::Invalid;
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+
+ if (Desc.MayLoad && LSU->isLQFull())
+ Event = HWStallEvent::LoadQueueFull;
+ else if (Desc.MayStore && LSU->isSQFull())
+ Event = HWStallEvent::StoreQueueFull;
+ else {
+ switch (Resources->canBeDispatched(Desc.Buffers)) {
+ default:
+ return true;
+ case ResourceStateEvent::RS_BUFFER_UNAVAILABLE:
+ Event = HWStallEvent::SchedulerQueueFull;
+ break;
+ case ResourceStateEvent::RS_RESERVED:
+ Event = HWStallEvent::DispatchGroupStall;
+ }
+ }
+
+ return false;
+}
+
+void Scheduler::issueInstructionImpl(
+ InstRef &IR,
+ SmallVectorImpl<std::pair<ResourceRef, double>> &UsedResources) {
+ Instruction *IS = IR.getInstruction();
+ const InstrDesc &D = IS->getDesc();
+
+ // Issue the instruction and collect all the consumed resources
+ // into a vector. That vector is then used to notify the listener.
+ Resources->issueInstruction(D, UsedResources);
+
+ // Notify the instruction that it started executing.
+ // This updates the internal state of each write.
+ IS->execute();
+
+ if (IS->isExecuting())
+ IssuedQueue[IR.getSourceIndex()] = IS;
+}
+
+// Release the buffered resources and issue the instruction.
+void Scheduler::issueInstruction(
+ InstRef &IR,
+ SmallVectorImpl<std::pair<ResourceRef, double>> &UsedResources) {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ releaseBuffers(Desc.Buffers);
+ issueInstructionImpl(IR, UsedResources);
+}
+
+void Scheduler::promoteToReadyQueue(SmallVectorImpl<InstRef> &Ready) {
+ // Scan the set of waiting instructions and promote them to the
+ // ready queue if operands are all ready.
+ for (auto I = WaitQueue.begin(), E = WaitQueue.end(); I != E;) {
+ const unsigned IID = I->first;
+ Instruction *IS = I->second;
+
+ // Check if this instruction is now ready. In case, force
+ // a transition in state using method 'update()'.
+ if (!IS->isReady())
+ IS->update();
+
+ const InstrDesc &Desc = IS->getDesc();
+ bool IsMemOp = Desc.MayLoad || Desc.MayStore;
+ if (!IS->isReady() || (IsMemOp && !LSU->isReady({IID, IS}))) {
+ ++I;
+ continue;
+ }
+
+ Ready.emplace_back(IID, IS);
+ ReadyQueue[IID] = IS;
+ auto ToRemove = I;
+ ++I;
+ WaitQueue.erase(ToRemove);
+ }
+}
+
+InstRef Scheduler::select() {
+ // Find the oldest ready-to-issue instruction in the ReadyQueue.
+ auto It = std::find_if(ReadyQueue.begin(), ReadyQueue.end(),
+ [&](const QueueEntryTy &Entry) {
+ const InstrDesc &D = Entry.second->getDesc();
+ return Resources->canBeIssued(D);
+ });
+
+ if (It == ReadyQueue.end())
+ return {0, nullptr};
+
+ // We want to prioritize older instructions over younger instructions to
+ // minimize the pressure on the reorder buffer. We also want to
+ // rank higher the instructions with more users to better expose ILP.
+
+ // Compute a rank value based on the age of an instruction (i.e. its source
+ // index) and its number of users. The lower the rank value, the better.
+ int Rank = It->first - It->second->getNumUsers();
+ for (auto I = It, E = ReadyQueue.end(); I != E; ++I) {
+ int CurrentRank = I->first - I->second->getNumUsers();
+ if (CurrentRank < Rank) {
+ const InstrDesc &D = I->second->getDesc();
+ if (Resources->canBeIssued(D))
+ It = I;
+ }
+ }
+
+ // We found an instruction to issue.
+ InstRef IR(It->first, It->second);
+ ReadyQueue.erase(It);
+ return IR;
+}
+
+void Scheduler::updatePendingQueue(SmallVectorImpl<InstRef> &Ready) {
+ // Notify to instructions in the pending queue that a new cycle just
+ // started.
+ for (QueueEntryTy Entry : WaitQueue)
+ Entry.second->cycleEvent();
+ promoteToReadyQueue(Ready);
+}
+
+void Scheduler::updateIssuedQueue(SmallVectorImpl<InstRef> &Executed) {
+ for (auto I = IssuedQueue.begin(), E = IssuedQueue.end(); I != E;) {
+ const QueueEntryTy Entry = *I;
+ Instruction *IS = Entry.second;
+ IS->cycleEvent();
+ if (IS->isExecuted()) {
+ Executed.push_back({Entry.first, Entry.second});
+ auto ToRemove = I;
+ ++I;
+ IssuedQueue.erase(ToRemove);
+ } else {
+ LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << Entry.first
+ << " is still executing.\n");
+ ++I;
+ }
+ }
+}
+
+void Scheduler::onInstructionExecuted(const InstRef &IR) {
+ LSU->onInstructionExecuted(IR);
+}
+
+void Scheduler::reclaimSimulatedResources(SmallVectorImpl<ResourceRef> &Freed) {
+ Resources->cycleEvent(Freed);
+}
+
+bool Scheduler::reserveResources(InstRef &IR) {
+ // If necessary, reserve queue entries in the load-store unit (LSU).
+ const bool Reserved = LSU->reserve(IR);
+ if (!IR.getInstruction()->isReady() || (Reserved && !LSU->isReady(IR))) {
+ LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the Wait Queue\n");
+ WaitQueue[IR.getSourceIndex()] = IR.getInstruction();
+ return false;
+ }
+ return true;
+}
+
+bool Scheduler::issueImmediately(InstRef &IR) {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ if (!Desc.isZeroLatency() && !Resources->mustIssueImmediately(Desc)) {
+ LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR
+ << " to the Ready Queue\n");
+ ReadyQueue[IR.getSourceIndex()] = IR.getInstruction();
+ return false;
+ }
+ return true;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/Scheduler.h b/contrib/llvm/tools/llvm-mca/Scheduler.h
new file mode 100644
index 000000000000..428fbc01707d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Scheduler.h
@@ -0,0 +1,515 @@
+//===--------------------- Scheduler.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A scheduler for Processor Resource Units and Processor Resource Groups.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
+#define LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
+
+#include "HWEventListener.h"
+#include "HardwareUnit.h"
+#include "Instruction.h"
+#include "LSUnit.h"
+#include "RetireControlUnit.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include <map>
+
+namespace mca {
+
+/// Used to notify the internal state of a processor resource.
+///
+/// A processor resource is available if it is not reserved, and there are
+/// available slots in the buffer. A processor resource is unavailable if it
+/// is either reserved, or the associated buffer is full. A processor resource
+/// with a buffer size of -1 is always available if it is not reserved.
+///
+/// Values of type ResourceStateEvent are returned by method
+/// ResourceState::isBufferAvailable(), which is used to query the internal
+/// state of a resource.
+///
+/// The naming convention for resource state events is:
+/// * Event names start with prefix RS_
+/// * Prefix RS_ is followed by a string describing the actual resource state.
+enum ResourceStateEvent {
+ RS_BUFFER_AVAILABLE,
+ RS_BUFFER_UNAVAILABLE,
+ RS_RESERVED
+};
+
+/// A descriptor for processor resources.
+///
+/// Each object of class ResourceState is associated to a specific processor
+/// resource. There is an instance of this class for every processor resource
+/// defined by the scheduling model.
+/// A ResourceState dynamically tracks the availability of units of a processor
+/// resource. For example, the ResourceState of a ProcResGroup tracks the
+/// availability of resource units which are part of the group.
+///
+/// Internally, ResourceState uses a round-robin selector to identify
+/// which unit of the group shall be used next.
+class ResourceState {
+ // Index to the MCProcResourceDesc in the processor Model.
+ unsigned ProcResourceDescIndex;
+ // A resource mask. This is generated by the tool with the help of
+ // function `mca::createProcResourceMasks' (see Support.h).
+ uint64_t ResourceMask;
+
+ // A ProcResource can specify a number of units. For the purpose of dynamic
+ // scheduling, a processor resource with more than one unit behaves like a
+ // group. This field has one bit set for every unit/resource that is part of
+ // the group.
+ // For groups, this field defaults to 'ResourceMask'. For non-group
+ // resources, the number of bits set in this mask is equivalent to the
+ // number of units (i.e. field 'NumUnits' in 'ProcResourceUnits').
+ uint64_t ResourceSizeMask;
+
+ // A simple round-robin selector for processor resources.
+ // Each bit of the mask identifies a sub resource within this group.
+ //
+ // As an example, lets assume that this ResourceState describes a
+ // processor resource group composed of the following three units:
+ // ResourceA -- 0b001
+ // ResourceB -- 0b010
+ // ResourceC -- 0b100
+ //
+ // Each unit is identified by a ResourceMask which always contains a
+ // single bit set. Field NextInSequenceMask is initially set to value
+ // 0xb111. That value is obtained by OR'ing the resource masks of
+ // processor resource that are part of the group.
+ //
+ // NextInSequenceMask -- 0b111
+ //
+ // Field NextInSequenceMask is used by the resource manager (i.e.
+ // an object of class ResourceManager) to select the "next available resource"
+ // from the set. The algorithm would prioritize resources with a bigger
+ // ResourceMask value.
+ //
+ // In this example, there are three resources in the set, and 'ResourceC'
+ // has the highest mask value. The round-robin selector would firstly select
+ // 'ResourceC', then 'ResourceB', and eventually 'ResourceA'.
+ //
+ // When a resource R is used, its corresponding bit is cleared from the set.
+ //
+ // Back to the example:
+ // If 'ResourceC' is selected, then the new value of NextInSequenceMask
+ // becomes 0xb011.
+ //
+ // When NextInSequenceMask becomes zero, it is reset to its original value
+ // (in this example, that value would be 0b111).
+ uint64_t NextInSequenceMask;
+
+ // Some instructions can only be issued on very specific pipeline resources.
+ // For those instructions, we know exactly which resource would be consumed
+ // without having to dynamically select it using field 'NextInSequenceMask'.
+ //
+ // The resource mask bit associated to the (statically) selected
+ // processor resource is still cleared from the 'NextInSequenceMask'.
+ // If that bit was already zero in NextInSequenceMask, then we update
+ // mask 'RemovedFromNextInSequence'.
+ //
+ // When NextInSequenceMask is reset back to its initial value, the algorithm
+ // removes any bits which are set in RemoveFromNextInSequence.
+ uint64_t RemovedFromNextInSequence;
+
+ // A mask of ready units.
+ uint64_t ReadyMask;
+
+ // Buffered resources will have this field set to a positive number bigger
+ // than 0. A buffered resource behaves like a separate reservation station
+ // implementing its own buffer for out-of-order execution.
+ // A buffer of 1 is for units that force in-order execution.
+ // A value of 0 is treated specially. In particular, a resource with
+ // A BufferSize = 0 is for an in-order issue/dispatch resource.
+ // That means, this resource is reserved starting from the dispatch event,
+ // until all the "resource cycles" are consumed after the issue event.
+ // While this resource is reserved, no other instruction may be dispatched.
+ int BufferSize;
+
+ // Available slots in the buffer (zero, if this is not a buffered resource).
+ unsigned AvailableSlots;
+
+ // True if this is resource is currently unavailable.
+ // An instruction may "reserve" a resource for a number of cycles.
+ // During those cycles, the reserved resource cannot be used for other
+ // instructions, even if the ReadyMask is set.
+ bool Unavailable;
+
+ bool isSubResourceReady(uint64_t ID) const { return ReadyMask & ID; }
+
+ /// Returns the mask identifier of the next available resource in the set.
+ uint64_t getNextInSequence() const {
+ assert(NextInSequenceMask);
+ return llvm::PowerOf2Floor(NextInSequenceMask);
+ }
+
+ /// Returns the mask of the next available resource within the set,
+ /// and updates the resource selector.
+ void updateNextInSequence() {
+ NextInSequenceMask ^= getNextInSequence();
+ if (!NextInSequenceMask)
+ NextInSequenceMask = ResourceSizeMask;
+ }
+
+ uint64_t computeResourceSizeMaskForGroup(uint64_t ResourceMask) {
+ assert(llvm::countPopulation(ResourceMask) > 1);
+ return ResourceMask ^ llvm::PowerOf2Floor(ResourceMask);
+ }
+
+public:
+ ResourceState(const llvm::MCProcResourceDesc &Desc, unsigned Index,
+ uint64_t Mask)
+ : ProcResourceDescIndex(Index), ResourceMask(Mask) {
+ bool IsAGroup = llvm::countPopulation(ResourceMask) > 1;
+ ResourceSizeMask = IsAGroup ? computeResourceSizeMaskForGroup(ResourceMask)
+ : ((1ULL << Desc.NumUnits) - 1);
+ NextInSequenceMask = ResourceSizeMask;
+ RemovedFromNextInSequence = 0;
+ ReadyMask = ResourceSizeMask;
+ BufferSize = Desc.BufferSize;
+ AvailableSlots = BufferSize == -1 ? 0U : static_cast<unsigned>(BufferSize);
+ Unavailable = false;
+ }
+
+ unsigned getProcResourceID() const { return ProcResourceDescIndex; }
+ uint64_t getResourceMask() const { return ResourceMask; }
+ int getBufferSize() const { return BufferSize; }
+
+ bool isBuffered() const { return BufferSize > 0; }
+ bool isInOrder() const { return BufferSize == 1; }
+ bool isADispatchHazard() const { return BufferSize == 0; }
+ bool isReserved() const { return Unavailable; }
+
+ void setReserved() { Unavailable = true; }
+ void clearReserved() { Unavailable = false; }
+
+ // A resource is ready if it is not reserved, and if there are enough
+ // available units.
+ // If a resource is also a dispatch hazard, then we don't check if
+ // it is reserved because that check would always return true.
+ // A resource marked as "dispatch hazard" is always reserved at
+ // dispatch time. When this method is called, the assumption is that
+ // the user of this resource has been already dispatched.
+ bool isReady(unsigned NumUnits = 1) const {
+ return (!isReserved() || isADispatchHazard()) &&
+ llvm::countPopulation(ReadyMask) >= NumUnits;
+ }
+ bool isAResourceGroup() const {
+ return llvm::countPopulation(ResourceMask) > 1;
+ }
+
+ bool containsResource(uint64_t ID) const { return ResourceMask & ID; }
+
+ void markSubResourceAsUsed(uint64_t ID) {
+ assert(isSubResourceReady(ID));
+ ReadyMask ^= ID;
+ }
+
+ void releaseSubResource(uint64_t ID) {
+ assert(!isSubResourceReady(ID));
+ ReadyMask ^= ID;
+ }
+
+ unsigned getNumUnits() const {
+ return isAResourceGroup() ? 1U : llvm::countPopulation(ResourceSizeMask);
+ }
+
+ uint64_t selectNextInSequence();
+ void removeFromNextInSequence(uint64_t ID);
+
+ ResourceStateEvent isBufferAvailable() const {
+ if (isADispatchHazard() && isReserved())
+ return RS_RESERVED;
+ if (!isBuffered() || AvailableSlots)
+ return RS_BUFFER_AVAILABLE;
+ return RS_BUFFER_UNAVAILABLE;
+ }
+
+ void reserveBuffer() {
+ if (AvailableSlots)
+ AvailableSlots--;
+ }
+
+ void releaseBuffer() {
+ if (BufferSize > 0)
+ AvailableSlots++;
+ assert(AvailableSlots <= static_cast<unsigned>(BufferSize));
+ }
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+/// A resource unit identifier.
+///
+/// This is used to identify a specific processor resource unit using a pair
+/// of indices where the 'first' index is a processor resource mask, and the
+/// 'second' index is an index for a "sub-resource" (i.e. unit).
+typedef std::pair<uint64_t, uint64_t> ResourceRef;
+
+// First: a MCProcResourceDesc index identifying a buffered resource.
+// Second: max number of buffer entries used in this resource.
+typedef std::pair<unsigned, unsigned> BufferUsageEntry;
+
+/// A resource manager for processor resource units and groups.
+///
+/// This class owns all the ResourceState objects, and it is responsible for
+/// acting on requests from a Scheduler by updating the internal state of
+/// ResourceState objects.
+/// This class doesn't know about instruction itineraries and functional units.
+/// In future, it can be extended to support itineraries too through the same
+/// public interface.
+class ResourceManager {
+ // The resource manager owns all the ResourceState.
+ using UniqueResourceState = std::unique_ptr<ResourceState>;
+ llvm::SmallDenseMap<uint64_t, UniqueResourceState> Resources;
+
+ // Keeps track of which resources are busy, and how many cycles are left
+ // before those become usable again.
+ llvm::SmallDenseMap<ResourceRef, unsigned> BusyResources;
+
+ // A table to map processor resource IDs to processor resource masks.
+ llvm::SmallVector<uint64_t, 8> ProcResID2Mask;
+
+ // Adds a new resource state in Resources, as well as a new descriptor in
+ // ResourceDescriptor.
+ void addResource(const llvm::MCProcResourceDesc &Desc, unsigned Index,
+ uint64_t Mask);
+
+ // Populate resource descriptors.
+ void initialize(const llvm::MCSchedModel &SM);
+
+ // Returns the actual resource unit that will be used.
+ ResourceRef selectPipe(uint64_t ResourceID);
+
+ void use(ResourceRef RR);
+ void release(ResourceRef RR);
+
+ unsigned getNumUnits(uint64_t ResourceID) const {
+ assert(Resources.find(ResourceID) != Resources.end());
+ return Resources.find(ResourceID)->getSecond()->getNumUnits();
+ }
+
+ // Reserve a specific Resource kind.
+ void reserveBuffer(uint64_t ResourceID) {
+ assert(isBufferAvailable(ResourceID) ==
+ ResourceStateEvent::RS_BUFFER_AVAILABLE);
+ ResourceState &Resource = *Resources[ResourceID];
+ Resource.reserveBuffer();
+ }
+
+ void releaseBuffer(uint64_t ResourceID) {
+ Resources[ResourceID]->releaseBuffer();
+ }
+
+ ResourceStateEvent isBufferAvailable(uint64_t ResourceID) const {
+ const ResourceState &Resource = *Resources.find(ResourceID)->second;
+ return Resource.isBufferAvailable();
+ }
+
+ bool isReady(uint64_t ResourceID, unsigned NumUnits) const {
+ const ResourceState &Resource = *Resources.find(ResourceID)->second;
+ return Resource.isReady(NumUnits);
+ }
+
+public:
+ ResourceManager(const llvm::MCSchedModel &SM)
+ : ProcResID2Mask(SM.getNumProcResourceKinds()) {
+ initialize(SM);
+ }
+
+ // Returns RS_BUFFER_AVAILABLE if buffered resources are not reserved, and if
+ // there are enough available slots in the buffers.
+ ResourceStateEvent canBeDispatched(llvm::ArrayRef<uint64_t> Buffers) const;
+
+ // Return the processor resource identifier associated to this Mask.
+ unsigned resolveResourceMask(uint64_t Mask) const {
+ return Resources.find(Mask)->second->getProcResourceID();
+ }
+
+ // Consume a slot in every buffered resource from array 'Buffers'. Resource
+ // units that are dispatch hazards (i.e. BufferSize=0) are marked as reserved.
+ void reserveBuffers(llvm::ArrayRef<uint64_t> Buffers);
+
+ // Release buffer entries previously allocated by method reserveBuffers.
+ void releaseBuffers(llvm::ArrayRef<uint64_t> Buffers);
+
+ void reserveResource(uint64_t ResourceID) {
+ ResourceState &Resource = *Resources[ResourceID];
+ assert(!Resource.isReserved());
+ Resource.setReserved();
+ }
+
+ void releaseResource(uint64_t ResourceID) {
+ ResourceState &Resource = *Resources[ResourceID];
+ Resource.clearReserved();
+ }
+
+ // Returns true if all resources are in-order, and there is at least one
+ // resource which is a dispatch hazard (BufferSize = 0).
+ bool mustIssueImmediately(const InstrDesc &Desc);
+
+ bool canBeIssued(const InstrDesc &Desc) const;
+
+ void issueInstruction(
+ const InstrDesc &Desc,
+ llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
+
+ void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &ResourcesFreed);
+
+#ifndef NDEBUG
+ void dump() const {
+ for (const std::pair<uint64_t, UniqueResourceState> &Resource : Resources)
+ Resource.second->dump();
+ }
+#endif
+}; // namespace mca
+
+/// Class Scheduler is responsible for issuing instructions to pipeline
+/// resources. Internally, it delegates to a ResourceManager the management of
+/// processor resources.
+/// This class is also responsible for tracking the progress of instructions
+/// from the dispatch stage, until the write-back stage.
+///
+/// An nstruction dispatched to the Scheduler is initially placed into either
+/// the 'WaitQueue' or the 'ReadyQueue' depending on the availability of the
+/// input operands. Instructions in the WaitQueue are ordered by instruction
+/// index. An instruction is moved from the WaitQueue to the ReadyQueue when
+/// register operands become available, and all memory dependencies are met.
+/// Instructions that are moved from the WaitQueue to the ReadyQueue transition
+/// from state 'IS_AVAILABLE' to state 'IS_READY'.
+///
+/// At the beginning of each cycle, the Scheduler checks if there are
+/// instructions in the WaitQueue that can be moved to the ReadyQueue. If the
+/// ReadyQueue is not empty, then older instructions from the queue are issued
+/// to the processor pipelines, and the underlying ResourceManager is updated
+/// accordingly. The ReadyQueue is ordered by instruction index to guarantee
+/// that the first instructions in the set are also the oldest.
+///
+/// An Instruction is moved from the ReadyQueue the `IssuedQueue` when it is
+/// issued to a (one or more) pipeline(s). This event also causes an instruction
+/// state transition (i.e. from state IS_READY, to state IS_EXECUTING).
+/// An Instruction leaves the IssuedQueue when it reaches the write-back stage.
+class Scheduler : public HardwareUnit {
+ const llvm::MCSchedModel &SM;
+
+ // Hardware resources that are managed by this scheduler.
+ std::unique_ptr<ResourceManager> Resources;
+ std::unique_ptr<LSUnit> LSU;
+
+ using QueueEntryTy = std::pair<unsigned, Instruction *>;
+ std::map<unsigned, Instruction *> WaitQueue;
+ std::map<unsigned, Instruction *> ReadyQueue;
+ std::map<unsigned, Instruction *> IssuedQueue;
+
+ /// Issue an instruction without updating the ready queue.
+ void issueInstructionImpl(
+ InstRef &IR,
+ llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
+
+public:
+ Scheduler(const llvm::MCSchedModel &Model, unsigned LoadQueueSize,
+ unsigned StoreQueueSize, bool AssumeNoAlias)
+ : SM(Model), Resources(llvm::make_unique<ResourceManager>(SM)),
+ LSU(llvm::make_unique<LSUnit>(LoadQueueSize, StoreQueueSize,
+ AssumeNoAlias)) {}
+
+ /// Check if the instruction in 'IR' can be dispatched.
+ ///
+ /// The DispatchStage is responsible for querying the Scheduler before
+ /// dispatching new instructions. This routine is used for performing such
+ /// a query. If the instruction 'IR' can be dispatched, then true is
+ /// returned, otherwise false is returned with Event set to the stall type.
+ bool canBeDispatched(const InstRef &IR,
+ HWStallEvent::GenericEventType &Event) const;
+
+ /// Returns true if there is availibility for IR in the LSU.
+ bool isReady(const InstRef &IR) const { return LSU->isReady(IR); }
+
+ /// Issue an instruction. The Used container is populated with
+ /// the resource objects consumed on behalf of issuing this instruction.
+ void
+ issueInstruction(InstRef &IR,
+ llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Used);
+
+ /// This routine will attempt to issue an instruction immediately (for
+ /// zero-latency instructions).
+ ///
+ /// Returns true if the instruction is issued immediately. If this does not
+ /// occur, then the instruction will be added to the Scheduler's ReadyQueue.
+ bool issueImmediately(InstRef &IR);
+
+ /// Reserve one entry in each buffered resource.
+ void reserveBuffers(llvm::ArrayRef<uint64_t> Buffers) {
+ Resources->reserveBuffers(Buffers);
+ }
+
+ /// Release buffer entries previously allocated by method reserveBuffers.
+ void releaseBuffers(llvm::ArrayRef<uint64_t> Buffers) {
+ Resources->releaseBuffers(Buffers);
+ }
+
+ /// Update the resources managed by the scheduler.
+ /// This routine is to be called at the start of a new cycle, and is
+ /// responsible for updating scheduler resources. Resources are released
+ /// once they have been fully consumed.
+ void reclaimSimulatedResources(llvm::SmallVectorImpl<ResourceRef> &Freed);
+
+ /// Move instructions from the WaitQueue to the ReadyQueue if input operands
+ /// are all available.
+ void promoteToReadyQueue(llvm::SmallVectorImpl<InstRef> &Ready);
+
+ /// Update the ready queue.
+ void updatePendingQueue(llvm::SmallVectorImpl<InstRef> &Ready);
+
+ /// Update the issued queue.
+ void updateIssuedQueue(llvm::SmallVectorImpl<InstRef> &Executed);
+
+ /// Updates the Scheduler's resources to reflect that an instruction has just
+ /// been executed.
+ void onInstructionExecuted(const InstRef &IR);
+
+ /// Obtain the processor's resource identifier for the given
+ /// resource mask.
+ unsigned getResourceID(uint64_t Mask) {
+ return Resources->resolveResourceMask(Mask);
+ }
+
+ /// Reserve resources necessary to issue the instruction.
+ /// Returns true if the resources are ready and the (LSU) can
+ /// execute the given instruction immediately.
+ bool reserveResources(InstRef &IR);
+
+ /// Select the next instruction to issue from the ReadyQueue.
+ /// This method gives priority to older instructions.
+ InstRef select();
+
+#ifndef NDEBUG
+ // Update the ready queues.
+ void dump() const;
+
+ // This routine performs a sanity check. This routine should only be called
+ // when we know that 'IR' is not in the scheduler's instruction queues.
+ void sanityCheck(const InstRef &IR) const {
+ const unsigned Idx = IR.getSourceIndex();
+ assert(WaitQueue.find(Idx) == WaitQueue.end());
+ assert(ReadyQueue.find(Idx) == ReadyQueue.end());
+ assert(IssuedQueue.find(Idx) == IssuedQueue.end());
+ }
+#endif // !NDEBUG
+};
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
diff --git a/contrib/llvm/tools/llvm-mca/SchedulerStatistics.cpp b/contrib/llvm/tools/llvm-mca/SchedulerStatistics.cpp
new file mode 100644
index 000000000000..5c6d22a71812
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/SchedulerStatistics.cpp
@@ -0,0 +1,94 @@
+//===--------------------- SchedulerStatistics.cpp --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the SchedulerStatistics interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SchedulerStatistics.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+namespace mca {
+
+void SchedulerStatistics::onEvent(const HWInstructionEvent &Event) {
+ if (Event.Type == HWInstructionEvent::Issued)
+ ++NumIssued;
+}
+
+void SchedulerStatistics::onReservedBuffers(ArrayRef<unsigned> Buffers) {
+ for (const unsigned Buffer : Buffers) {
+ if (BufferedResources.find(Buffer) != BufferedResources.end()) {
+ BufferUsage &BU = BufferedResources[Buffer];
+ BU.SlotsInUse++;
+ BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);
+ continue;
+ }
+
+ BufferedResources.insert(
+ std::pair<unsigned, BufferUsage>(Buffer, {1U, 1U}));
+ }
+}
+
+void SchedulerStatistics::onReleasedBuffers(ArrayRef<unsigned> Buffers) {
+ for (const unsigned Buffer : Buffers) {
+ assert(BufferedResources.find(Buffer) != BufferedResources.end() &&
+ "Buffered resource not in map?");
+ BufferUsage &BU = BufferedResources[Buffer];
+ BU.SlotsInUse--;
+ }
+}
+
+void SchedulerStatistics::printSchedulerStatistics(
+ llvm::raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ TempStream << "\n\nSchedulers - number of cycles where we saw N instructions "
+ "issued:\n";
+ TempStream << "[# issued], [# cycles]\n";
+ for (const std::pair<unsigned, unsigned> &Entry : IssuedPerCycle) {
+ TempStream << " " << Entry.first << ", " << Entry.second << " ("
+ << format("%.1f", ((double)Entry.second / NumCycles) * 100)
+ << "%)\n";
+ }
+
+ TempStream.flush();
+ OS << Buffer;
+}
+
+void SchedulerStatistics::printSchedulerUsage(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ TempStream << "\n\nScheduler's queue usage:\n";
+ // Early exit if no buffered resources were consumed.
+ if (BufferedResources.empty()) {
+ TempStream << "No scheduler resources used.\n";
+ TempStream.flush();
+ OS << Buffer;
+ return;
+ }
+
+ for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ if (ProcResource.BufferSize <= 0)
+ continue;
+
+ const auto It = BufferedResources.find(I);
+ unsigned MaxUsedSlots =
+ It == BufferedResources.end() ? 0 : It->second.MaxUsedSlots;
+ TempStream << ProcResource.Name << ", " << MaxUsedSlots << '/'
+ << ProcResource.BufferSize << '\n';
+ }
+
+ TempStream.flush();
+ OS << Buffer;
+}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/SchedulerStatistics.h b/contrib/llvm/tools/llvm-mca/SchedulerStatistics.h
new file mode 100644
index 000000000000..7383c54a1615
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/SchedulerStatistics.h
@@ -0,0 +1,91 @@
+//===--------------------- SchedulerStatistics.h ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines class SchedulerStatistics. Class SchedulerStatistics is a
+/// View that listens to instruction issue events in order to print general
+/// statistics related to the hardware schedulers.
+///
+/// Example:
+/// ========
+///
+/// Schedulers - number of cycles where we saw N instructions issued:
+/// [# issued], [# cycles]
+/// 0, 7 (5.4%)
+/// 1, 4 (3.1%)
+/// 2, 8 (6.2%)
+///
+/// Scheduler's queue usage:
+/// JALU01, 0/20
+/// JFPU01, 18/18
+/// JLSAGU, 0/12
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H
+#define LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H
+
+#include "View.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include <map>
+
+namespace mca {
+
+class SchedulerStatistics : public View {
+ const llvm::MCSchedModel &SM;
+
+ using Histogram = std::map<unsigned, unsigned>;
+ Histogram IssuedPerCycle;
+
+ unsigned NumIssued;
+ unsigned NumCycles;
+
+ // Tracks the usage of a scheduler's queue.
+ struct BufferUsage {
+ unsigned SlotsInUse;
+ unsigned MaxUsedSlots;
+ };
+
+ std::map<unsigned, BufferUsage> BufferedResources;
+
+ void updateHistograms() {
+ IssuedPerCycle[NumIssued]++;
+ NumIssued = 0;
+ }
+
+ void printSchedulerStatistics(llvm::raw_ostream &OS) const;
+ void printSchedulerUsage(llvm::raw_ostream &OS) const;
+
+public:
+ SchedulerStatistics(const llvm::MCSubtargetInfo &STI)
+ : SM(STI.getSchedModel()), NumIssued(0), NumCycles(0) {}
+
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ void onCycleBegin() override { NumCycles++; }
+
+ void onCycleEnd() override { updateHistograms(); }
+
+ // Increases the number of used scheduler queue slots of every buffered
+ // resource in the Buffers set.
+ void onReservedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
+
+ // Decreases by one the number of used scheduler queue slots of every
+ // buffered resource in the Buffers set.
+ void onReleasedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
+
+ void printView(llvm::raw_ostream &OS) const override {
+ printSchedulerStatistics(OS);
+ printSchedulerUsage(OS);
+ }
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/SourceMgr.h b/contrib/llvm/tools/llvm-mca/SourceMgr.h
new file mode 100644
index 000000000000..15a85a69569f
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/SourceMgr.h
@@ -0,0 +1,63 @@
+//===--------------------- SourceMgr.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements class SourceMgr. Class SourceMgr abstracts the input
+/// code sequence (a sequence of MCInst), and assings unique identifiers to
+/// every instruction in the sequence.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_SOURCEMGR_H
+#define LLVM_TOOLS_LLVM_MCA_SOURCEMGR_H
+
+#include "llvm/MC/MCInst.h"
+#include <vector>
+
+namespace mca {
+
+typedef std::pair<unsigned, const llvm::MCInst *> SourceRef;
+
+class SourceMgr {
+ using InstVec = std::vector<std::unique_ptr<const llvm::MCInst>>;
+ const InstVec &Sequence;
+ unsigned Current;
+ unsigned Iterations;
+ static const unsigned DefaultIterations = 100;
+
+public:
+ SourceMgr(const InstVec &MCInstSequence, unsigned NumIterations)
+ : Sequence(MCInstSequence), Current(0),
+ Iterations(NumIterations ? NumIterations : DefaultIterations) {}
+
+ unsigned getCurrentIteration() const { return Current / Sequence.size(); }
+ unsigned getNumIterations() const { return Iterations; }
+ unsigned size() const { return Sequence.size(); }
+ const InstVec &getSequence() const { return Sequence; }
+
+ bool hasNext() const { return Current < (Iterations * size()); }
+ void updateNext() { Current++; }
+
+ const SourceRef peekNext() const {
+ unsigned Index = getCurrentInstructionIndex();
+ return SourceRef(Current, Sequence[Index].get());
+ }
+
+ unsigned getCurrentInstructionIndex() const {
+ return Current % Sequence.size();
+ }
+
+ const llvm::MCInst &getMCInstFromIndex(unsigned Index) const {
+ return *Sequence[Index % size()];
+ }
+
+ bool isEmpty() const { return size() == 0; }
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/Stage.cpp b/contrib/llvm/tools/llvm-mca/Stage.cpp
new file mode 100644
index 000000000000..7ead940e63c1
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Stage.cpp
@@ -0,0 +1,27 @@
+//===---------------------- Stage.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a stage.
+/// A chain of stages compose an instruction pipeline.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Stage.h"
+
+namespace mca {
+
+// Pin the vtable here in the implementation file.
+Stage::Stage() {}
+
+void Stage::addListener(HWEventListener *Listener) {
+ Listeners.insert(Listener);
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/Stage.h b/contrib/llvm/tools/llvm-mca/Stage.h
new file mode 100644
index 000000000000..9dbdcd89a33b
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Stage.h
@@ -0,0 +1,76 @@
+//===---------------------- Stage.h -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines a stage.
+/// A chain of stages compose an instruction pipeline.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_STAGE_H
+#define LLVM_TOOLS_LLVM_MCA_STAGE_H
+
+#include "HWEventListener.h"
+#include <set>
+
+namespace mca {
+
+class InstRef;
+
+class Stage {
+ Stage(const Stage &Other) = delete;
+ Stage &operator=(const Stage &Other) = delete;
+ std::set<HWEventListener *> Listeners;
+
+protected:
+ const std::set<HWEventListener *> &getListeners() const { return Listeners; }
+
+public:
+ Stage();
+ virtual ~Stage() = default;
+
+ /// Called prior to preExecute to ensure that the stage has items that it
+ /// is to process. For example, a FetchStage might have more instructions
+ /// that need to be processed, or a RCU might have items that have yet to
+ /// retire.
+ virtual bool hasWorkToComplete() const = 0;
+
+ /// Called once at the start of each cycle. This can be used as a setup
+ /// phase to prepare for the executions during the cycle.
+ virtual void cycleStart() {}
+
+ /// Called once at the end of each cycle.
+ virtual void cycleEnd() {}
+
+ /// Called prior to executing the list of stages.
+ /// This can be called multiple times per cycle.
+ virtual void preExecute() {}
+
+ /// Called as a cleanup and finalization phase after each execution.
+ /// This will only be called if all stages return a success from their
+ /// execute callback. This can be called multiple times per cycle.
+ virtual void postExecute() {}
+
+ /// The primary action that this stage performs.
+ /// Returning false prevents successor stages from having their 'execute'
+ /// routine called. This can be called multiple times during a single cycle.
+ virtual bool execute(InstRef &IR) = 0;
+
+ /// Add a listener to receive callbacks during the execution of this stage.
+ void addListener(HWEventListener *Listener);
+
+ /// Notify listeners of a particular hardware event.
+ template <typename EventT> void notifyEvent(const EventT &Event) {
+ for (HWEventListener *Listener : Listeners)
+ Listener->onEvent(Event);
+ }
+};
+
+} // namespace mca
+#endif // LLVM_TOOLS_LLVM_MCA_STAGE_H
diff --git a/contrib/llvm/tools/llvm-mca/SummaryView.cpp b/contrib/llvm/tools/llvm-mca/SummaryView.cpp
new file mode 100644
index 000000000000..01399055c4fd
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/SummaryView.cpp
@@ -0,0 +1,85 @@
+//===--------------------- SummaryView.cpp -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the functionalities used by the SummaryView to print
+/// the report information.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SummaryView.h"
+#include "Support.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Format.h"
+
+namespace mca {
+
+#define DEBUG_TYPE "llvm-mca"
+
+using namespace llvm;
+
+SummaryView::SummaryView(const llvm::MCSchedModel &Model, const SourceMgr &S,
+ unsigned Width)
+ : SM(Model), Source(S), DispatchWidth(Width), TotalCycles(0),
+ NumMicroOps(0), ProcResourceUsage(Model.getNumProcResourceKinds(), 0),
+ ProcResourceMasks(Model.getNumProcResourceKinds(), 0) {
+ computeProcResourceMasks(SM, ProcResourceMasks);
+}
+
+void SummaryView::onEvent(const HWInstructionEvent &Event) {
+ // We are only interested in the "instruction dispatched" events generated by
+ // the dispatch stage for instructions that are part of iteration #0.
+ if (Event.Type != HWInstructionEvent::Dispatched)
+ return;
+
+ if (Event.IR.getSourceIndex() >= Source.size())
+ return;
+
+ // Update the cumulative number of resource cycles based on the processor
+ // resource usage information available from the instruction descriptor. We
+ // need to compute the cumulative number of resource cycles for every
+ // processor resource which is consumed by an instruction of the block.
+ const Instruction &Inst = *Event.IR.getInstruction();
+ const InstrDesc &Desc = Inst.getDesc();
+ NumMicroOps += Desc.NumMicroOps;
+ for (const std::pair<uint64_t, const ResourceUsage> &RU : Desc.Resources) {
+ if (RU.second.size()) {
+ const auto It = find(ProcResourceMasks, RU.first);
+ assert(It != ProcResourceMasks.end() &&
+ "Invalid processor resource mask!");
+ ProcResourceUsage[std::distance(ProcResourceMasks.begin(), It)] +=
+ RU.second.size();
+ }
+ }
+}
+
+void SummaryView::printView(raw_ostream &OS) const {
+ unsigned Iterations = Source.getNumIterations();
+ unsigned Instructions = Source.size();
+ unsigned TotalInstructions = Instructions * Iterations;
+ double IPC = (double)TotalInstructions / TotalCycles;
+ double BlockRThroughput = computeBlockRThroughput(
+ SM, DispatchWidth, NumMicroOps, ProcResourceUsage);
+
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ TempStream << "Iterations: " << Iterations;
+ TempStream << "\nInstructions: " << TotalInstructions;
+ TempStream << "\nTotal Cycles: " << TotalCycles;
+ TempStream << "\nDispatch Width: " << DispatchWidth;
+ TempStream << "\nIPC: " << format("%.2f", IPC);
+
+ // Round to the block reciprocal throughput to the nearest tenth.
+ TempStream << "\nBlock RThroughput: "
+ << format("%.1f", floor((BlockRThroughput * 10) + 0.5) / 10)
+ << '\n';
+ TempStream.flush();
+ OS << Buffer;
+}
+} // namespace mca.
diff --git a/contrib/llvm/tools/llvm-mca/SummaryView.h b/contrib/llvm/tools/llvm-mca/SummaryView.h
new file mode 100644
index 000000000000..b799ce3aa747
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/SummaryView.h
@@ -0,0 +1,76 @@
+//===--------------------- SummaryView.h ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements the summary view.
+///
+/// The goal of the summary view is to give a very quick overview of the
+/// performance throughput. Below is an example of summary view:
+///
+///
+/// Iterations: 300
+/// Instructions: 900
+/// Total Cycles: 610
+/// Dispatch Width: 2
+/// IPC: 1.48
+/// Block RThroughput: 2.0
+///
+/// The summary view collects a few performance numbers. The two main
+/// performance indicators are 'Total Cycles' and IPC (Instructions Per Cycle).
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_SUMMARYVIEW_H
+#define LLVM_TOOLS_LLVM_MCA_SUMMARYVIEW_H
+
+#include "SourceMgr.h"
+#include "View.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/MC/MCSchedule.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace mca {
+
+/// A view that collects and prints a few performance numbers.
+class SummaryView : public View {
+ const llvm::MCSchedModel &SM;
+ const SourceMgr &Source;
+ const unsigned DispatchWidth;
+ unsigned TotalCycles;
+ // The total number of micro opcodes contributed by a block of instructions.
+ unsigned NumMicroOps;
+ // For each processor resource, this vector stores the cumulative number of
+ // resource cycles consumed by the analyzed code block.
+ llvm::SmallVector<unsigned, 8> ProcResourceUsage;
+
+ // Each processor resource is associated with a so-called processor resource
+ // mask. This vector allows to correlate processor resource IDs with processor
+ // resource masks. There is exactly one element per each processor resource
+ // declared by the scheduling model.
+ llvm::SmallVector<uint64_t, 8> ProcResourceMasks;
+
+ // Compute the reciprocal throughput for the analyzed code block.
+ // The reciprocal block throughput is computed as the MAX between:
+ // - NumMicroOps / DispatchWidth
+ // - Total Resource Cycles / #Units (for every resource consumed).
+ double getBlockRThroughput() const;
+
+public:
+ SummaryView(const llvm::MCSchedModel &Model, const SourceMgr &S,
+ unsigned Width);
+
+ void onCycleEnd() override { ++TotalCycles; }
+
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ void printView(llvm::raw_ostream &OS) const override;
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/Support.cpp b/contrib/llvm/tools/llvm-mca/Support.cpp
new file mode 100644
index 000000000000..8f6b8a91f38f
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Support.cpp
@@ -0,0 +1,79 @@
+//===--------------------- Support.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements a few helper functions used by various pipeline
+/// components.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Support.h"
+#include "llvm/MC/MCSchedule.h"
+
+namespace mca {
+
+using namespace llvm;
+
+void computeProcResourceMasks(const MCSchedModel &SM,
+ SmallVectorImpl<uint64_t> &Masks) {
+ unsigned ProcResourceID = 0;
+
+ // Create a unique bitmask for every processor resource unit.
+ // Skip resource at index 0, since it always references 'InvalidUnit'.
+ Masks.resize(SM.getNumProcResourceKinds());
+ for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+ const MCProcResourceDesc &Desc = *SM.getProcResource(I);
+ if (Desc.SubUnitsIdxBegin)
+ continue;
+ Masks[I] = 1ULL << ProcResourceID;
+ ProcResourceID++;
+ }
+
+ // Create a unique bitmask for every processor resource group.
+ for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+ const MCProcResourceDesc &Desc = *SM.getProcResource(I);
+ if (!Desc.SubUnitsIdxBegin)
+ continue;
+ Masks[I] = 1ULL << ProcResourceID;
+ for (unsigned U = 0; U < Desc.NumUnits; ++U) {
+ uint64_t OtherMask = Masks[Desc.SubUnitsIdxBegin[U]];
+ Masks[I] |= OtherMask;
+ }
+ ProcResourceID++;
+ }
+}
+
+double computeBlockRThroughput(const MCSchedModel &SM, unsigned DispatchWidth,
+ unsigned NumMicroOps,
+ ArrayRef<unsigned> ProcResourceUsage) {
+ // The block throughput is bounded from above by the hardware dispatch
+ // throughput. That is because the DispatchWidth is an upper bound on the
+ // number of opcodes that can be part of a single dispatch group.
+ double Max = static_cast<double>(NumMicroOps) / DispatchWidth;
+
+ // The block throughput is also limited by the amount of hardware parallelism.
+ // The number of available resource units affects the resource pressure
+ // distribution, as well as how many blocks can be executed every cycle.
+ for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+ unsigned ResourceCycles = ProcResourceUsage[I];
+ if (!ResourceCycles)
+ continue;
+
+ const MCProcResourceDesc &MCDesc = *SM.getProcResource(I);
+ double Throughput = static_cast<double>(ResourceCycles) / MCDesc.NumUnits;
+ Max = std::max(Max, Throughput);
+ }
+
+ // The block reciprocal throughput is computed as the MAX of:
+ // - (NumMicroOps / DispatchWidth)
+ // - (NumUnits / ResourceCycles) for every consumed processor resource.
+ return Max;
+}
+
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/Support.h b/contrib/llvm/tools/llvm-mca/Support.h
new file mode 100644
index 000000000000..fd8d8b5a23b3
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/Support.h
@@ -0,0 +1,58 @@
+//===--------------------- Support.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Helper functions used by various pipeline components.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_SUPPORT_H
+#define LLVM_TOOLS_LLVM_MCA_SUPPORT_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSchedule.h"
+
+namespace mca {
+
+/// Populates vector Masks with processor resource masks.
+///
+/// The number of bits set in a mask depends on the processor resource type.
+/// Each processor resource mask has at least one bit set. For groups, the
+/// number of bits set in the mask is equal to the cardinality of the group plus
+/// one. Excluding the most significant bit, the remaining bits in the mask
+/// identify processor resources that are part of the group.
+///
+/// Example:
+///
+/// ResourceA -- Mask: 0b001
+/// ResourceB -- Mask: 0b010
+/// ResourceAB -- Mask: 0b100 U (ResourceA::Mask | ResourceB::Mask) == 0b111
+///
+/// ResourceAB is a processor resource group containing ResourceA and ResourceB.
+/// Each resource mask uniquely identifies a resource; both ResourceA and
+/// ResourceB only have one bit set.
+/// ResourceAB is a group; excluding the most significant bit in the mask, the
+/// remaining bits identify the composition of the group.
+///
+/// Resource masks are used by the ResourceManager to solve set membership
+/// problems with simple bit manipulation operations.
+void computeProcResourceMasks(const llvm::MCSchedModel &SM,
+ llvm::SmallVectorImpl<uint64_t> &Masks);
+
+/// Compute the reciprocal block throughput from a set of processor resource
+/// cycles. The reciprocal block throughput is computed as the MAX between:
+/// - NumMicroOps / DispatchWidth
+/// - ProcResourceCycles / #ProcResourceUnits (for every consumed resource).
+double computeBlockRThroughput(const llvm::MCSchedModel &SM,
+ unsigned DispatchWidth, unsigned NumMicroOps,
+ llvm::ArrayRef<unsigned> ProcResourceUsage);
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/TimelineView.cpp b/contrib/llvm/tools/llvm-mca/TimelineView.cpp
new file mode 100644
index 000000000000..6e75cac0d432
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/TimelineView.cpp
@@ -0,0 +1,240 @@
+//===--------------------- TimelineView.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \brief
+///
+/// This file implements the TimelineView interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "TimelineView.h"
+
+using namespace llvm;
+
+namespace mca {
+
+void TimelineView::initialize(unsigned MaxIterations) {
+ unsigned NumInstructions =
+ AsmSequence.getNumIterations() * AsmSequence.size();
+ if (!MaxIterations)
+ MaxIterations = DEFAULT_ITERATIONS;
+ unsigned NumEntries =
+ std::min(NumInstructions, MaxIterations * AsmSequence.size());
+ Timeline.resize(NumEntries);
+ TimelineViewEntry NullTVEntry = {0, 0, 0, 0, 0};
+ std::fill(Timeline.begin(), Timeline.end(), NullTVEntry);
+
+ WaitTime.resize(AsmSequence.size());
+ WaitTimeEntry NullWTEntry = {0, 0, 0, 0};
+ std::fill(WaitTime.begin(), WaitTime.end(), NullWTEntry);
+}
+
+void TimelineView::onEvent(const HWInstructionEvent &Event) {
+ const unsigned Index = Event.IR.getSourceIndex();
+ if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
+ return;
+ switch (Event.Type) {
+ case HWInstructionEvent::Retired: {
+ TimelineViewEntry &TVEntry = Timeline[Index];
+ TVEntry.CycleRetired = CurrentCycle;
+
+ // Update the WaitTime entry which corresponds to this Index.
+ WaitTimeEntry &WTEntry = WaitTime[Index % AsmSequence.size()];
+ WTEntry.Executions++;
+ WTEntry.CyclesSpentInSchedulerQueue +=
+ TVEntry.CycleIssued - TVEntry.CycleDispatched;
+ assert(TVEntry.CycleDispatched <= TVEntry.CycleReady);
+ WTEntry.CyclesSpentInSQWhileReady +=
+ TVEntry.CycleIssued - TVEntry.CycleReady;
+ WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
+ (TVEntry.CycleRetired - 1) - TVEntry.CycleExecuted;
+ break;
+ }
+ case HWInstructionEvent::Ready:
+ Timeline[Index].CycleReady = CurrentCycle;
+ break;
+ case HWInstructionEvent::Issued:
+ Timeline[Index].CycleIssued = CurrentCycle;
+ break;
+ case HWInstructionEvent::Executed:
+ Timeline[Index].CycleExecuted = CurrentCycle;
+ break;
+ case HWInstructionEvent::Dispatched:
+ Timeline[Index].CycleDispatched = CurrentCycle;
+ break;
+ default:
+ return;
+ }
+ LastCycle = std::max(LastCycle, CurrentCycle);
+}
+
+void TimelineView::printWaitTimeEntry(formatted_raw_ostream &OS,
+ const WaitTimeEntry &Entry,
+ unsigned SourceIndex) const {
+ OS << SourceIndex << '.';
+ OS.PadToColumn(7);
+
+ if (Entry.Executions == 0) {
+ OS << "- - - - ";
+ } else {
+ double AverageTime1, AverageTime2, AverageTime3;
+ unsigned Executions = Entry.Executions;
+ AverageTime1 = (double)Entry.CyclesSpentInSchedulerQueue / Executions;
+ AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / Executions;
+ AverageTime3 = (double)Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
+
+ OS << Executions;
+ OS.PadToColumn(13);
+
+ OS << format("%.1f", floor((AverageTime1 * 10) + 0.5) / 10);
+ OS.PadToColumn(20);
+ OS << format("%.1f", floor((AverageTime2 * 10) + 0.5) / 10);
+ OS.PadToColumn(27);
+ OS << format("%.1f", floor((AverageTime3 * 10) + 0.5) / 10);
+ OS.PadToColumn(34);
+ }
+}
+
+void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
+ if (WaitTime.empty())
+ return;
+
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ formatted_raw_ostream FOS(TempStream);
+
+ FOS << "\n\nAverage Wait times (based on the timeline view):\n"
+ << "[0]: Executions\n"
+ << "[1]: Average time spent waiting in a scheduler's queue\n"
+ << "[2]: Average time spent waiting in a scheduler's queue while ready\n"
+ << "[3]: Average time elapsed from WB until retire stage\n\n";
+ FOS << " [0] [1] [2] [3]\n";
+
+ // Use a different string stream for the instruction.
+ std::string Instruction;
+ raw_string_ostream InstrStream(Instruction);
+
+ for (unsigned I = 0, E = WaitTime.size(); I < E; ++I) {
+ printWaitTimeEntry(FOS, WaitTime[I], I);
+ // Append the instruction info at the end of the line.
+ const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
+
+ MCIP.printInst(&Inst, InstrStream, "", STI);
+ InstrStream.flush();
+
+ // Consume any tabs or spaces at the beginning of the string.
+ StringRef Str(Instruction);
+ Str = Str.ltrim();
+ FOS << " " << Str << '\n';
+ FOS.flush();
+ Instruction = "";
+
+ OS << Buffer;
+ Buffer = "";
+ }
+}
+
+void TimelineView::printTimelineViewEntry(formatted_raw_ostream &OS,
+ const TimelineViewEntry &Entry,
+ unsigned Iteration,
+ unsigned SourceIndex) const {
+ if (Iteration == 0 && SourceIndex == 0)
+ OS << '\n';
+ OS << '[' << Iteration << ',' << SourceIndex << ']';
+ OS.PadToColumn(10);
+ for (unsigned I = 0, E = Entry.CycleDispatched; I < E; ++I)
+ OS << ((I % 5 == 0) ? '.' : ' ');
+ OS << TimelineView::DisplayChar::Dispatched;
+ if (Entry.CycleDispatched != Entry.CycleExecuted) {
+ // Zero latency instructions have the same value for CycleDispatched,
+ // CycleIssued and CycleExecuted.
+ for (unsigned I = Entry.CycleDispatched + 1, E = Entry.CycleIssued; I < E;
+ ++I)
+ OS << TimelineView::DisplayChar::Waiting;
+ if (Entry.CycleIssued == Entry.CycleExecuted)
+ OS << TimelineView::DisplayChar::DisplayChar::Executed;
+ else {
+ if (Entry.CycleDispatched != Entry.CycleIssued)
+ OS << TimelineView::DisplayChar::Executing;
+ for (unsigned I = Entry.CycleIssued + 1, E = Entry.CycleExecuted; I < E;
+ ++I)
+ OS << TimelineView::DisplayChar::Executing;
+ OS << TimelineView::DisplayChar::Executed;
+ }
+ }
+
+ for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
+ OS << TimelineView::DisplayChar::RetireLag;
+ OS << TimelineView::DisplayChar::Retired;
+
+ // Skip other columns.
+ for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
+ OS << ((I % 5 == 0 || I == LastCycle) ? '.' : ' ');
+}
+
+static void printTimelineHeader(formatted_raw_ostream &OS, unsigned Cycles) {
+ OS << "\n\nTimeline view:\n";
+ if (Cycles >= 10) {
+ OS.PadToColumn(10);
+ for (unsigned I = 0; I <= Cycles; ++I) {
+ if (((I / 10) & 1) == 0)
+ OS << ' ';
+ else
+ OS << I % 10;
+ }
+ OS << '\n';
+ }
+
+ OS << "Index";
+ OS.PadToColumn(10);
+ for (unsigned I = 0; I <= Cycles; ++I) {
+ if (((I / 10) & 1) == 0)
+ OS << I % 10;
+ else
+ OS << ' ';
+ }
+ OS << '\n';
+}
+
+void TimelineView::printTimeline(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream StringStream(Buffer);
+ formatted_raw_ostream FOS(StringStream);
+
+ printTimelineHeader(FOS, LastCycle);
+ FOS.flush();
+ OS << Buffer;
+
+ // Use a different string stream for the instruction.
+ std::string Instruction;
+ raw_string_ostream InstrStream(Instruction);
+
+ for (unsigned I = 0, E = Timeline.size(); I < E; ++I) {
+ Buffer = "";
+ const TimelineViewEntry &Entry = Timeline[I];
+ if (Entry.CycleRetired == 0)
+ return;
+
+ unsigned Iteration = I / AsmSequence.size();
+ unsigned SourceIndex = I % AsmSequence.size();
+ printTimelineViewEntry(FOS, Entry, Iteration, SourceIndex);
+ // Append the instruction info at the end of the line.
+ const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
+ MCIP.printInst(&Inst, InstrStream, "", STI);
+ InstrStream.flush();
+
+ // Consume any tabs or spaces at the beginning of the string.
+ StringRef Str(Instruction);
+ Str = Str.ltrim();
+ FOS << " " << Str << '\n';
+ FOS.flush();
+ Instruction = "";
+ OS << Buffer;
+ }
+}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/TimelineView.h b/contrib/llvm/tools/llvm-mca/TimelineView.h
new file mode 100644
index 000000000000..e53c23ec1cc2
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/TimelineView.h
@@ -0,0 +1,189 @@
+//===--------------------- TimelineView.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \brief
+///
+/// This file implements a timeline view for the llvm-mca tool.
+///
+/// Class TimelineView observes events generated by the pipeline. For every
+/// instruction executed by the pipeline, it stores information related to
+/// state transition. It then plots that information in the form of a table
+/// as reported by the example below:
+///
+/// Timeline view:
+/// 0123456
+/// Index 0123456789
+///
+/// [0,0] DeER . . .. vmovshdup %xmm0, %xmm1
+/// [0,1] DeER . . .. vpermilpd $1, %xmm0, %xmm2
+/// [0,2] .DeER. . .. vpermilps $231, %xmm0, %xmm5
+/// [0,3] .DeeeER . .. vaddss %xmm1, %xmm0, %xmm3
+/// [0,4] . D==eeeER. .. vaddss %xmm3, %xmm2, %xmm4
+/// [0,5] . D=====eeeER .. vaddss %xmm4, %xmm5, %xmm6
+///
+/// [1,0] . DeE------R .. vmovshdup %xmm0, %xmm1
+/// [1,1] . DeE------R .. vpermilpd $1, %xmm0, %xmm2
+/// [1,2] . DeE-----R .. vpermilps $231, %xmm0, %xmm5
+/// [1,3] . D=eeeE--R .. vaddss %xmm1, %xmm0, %xmm3
+/// [1,4] . D===eeeER .. vaddss %xmm3, %xmm2, %xmm4
+/// [1,5] . D======eeeER vaddss %xmm4, %xmm5, %xmm6
+///
+/// There is an entry for every instruction in the input assembly sequence.
+/// The first field is a pair of numbers obtained from the instruction index.
+/// The first element of the pair is the iteration index, while the second
+/// element of the pair is a sequence number (i.e. a position in the assembly
+/// sequence).
+/// The second field of the table is the actual timeline information; each
+/// column is the information related to a specific cycle of execution.
+/// The timeline of an instruction is described by a sequence of character
+/// where each character represents the instruction state at a specific cycle.
+///
+/// Possible instruction states are:
+/// D: Instruction Dispatched
+/// e: Instruction Executing
+/// E: Instruction Executed (write-back stage)
+/// R: Instruction retired
+/// =: Instruction waiting in the Scheduler's queue
+/// -: Instruction executed, waiting to retire in order.
+///
+/// dots ('.') and empty spaces are cycles where the instruction is not
+/// in-flight.
+///
+/// The last column is the assembly instruction associated to the entry.
+///
+/// Based on the timeline view information from the example, instruction 0
+/// at iteration 0 was dispatched at cycle 0, and was retired at cycle 3.
+/// Instruction [0,1] was also dispatched at cycle 0, and it retired at
+/// the same cycle than instruction [0,0].
+/// Instruction [0,4] has been dispatched at cycle 2. However, it had to
+/// wait for two cycles before being issued. That is because operands
+/// became ready only at cycle 5.
+///
+/// This view helps further understanding bottlenecks and the impact of
+/// resource pressure on the code.
+///
+/// To better understand why instructions had to wait for multiple cycles in
+/// the scheduler's queue, class TimelineView also reports extra timing info
+/// in another table named "Average Wait times" (see example below).
+///
+///
+/// Average Wait times (based on the timeline view):
+/// [0]: Executions
+/// [1]: Average time spent waiting in a scheduler's queue
+/// [2]: Average time spent waiting in a scheduler's queue while ready
+/// [3]: Average time elapsed from WB until retire stage
+///
+/// [0] [1] [2] [3]
+/// 0. 2 1.0 1.0 3.0 vmovshdup %xmm0, %xmm1
+/// 1. 2 1.0 1.0 3.0 vpermilpd $1, %xmm0, %xmm2
+/// 2. 2 1.0 1.0 2.5 vpermilps $231, %xmm0, %xmm5
+/// 3. 2 1.5 0.5 1.0 vaddss %xmm1, %xmm0, %xmm3
+/// 4. 2 3.5 0.0 0.0 vaddss %xmm3, %xmm2, %xmm4
+/// 5. 2 6.5 0.0 0.0 vaddss %xmm4, %xmm5, %xmm6
+///
+/// By comparing column [2] with column [1], we get an idea about how many
+/// cycles were spent in the scheduler's queue due to data dependencies.
+///
+/// In this example, instruction 5 spent an average of ~6 cycles in the
+/// scheduler's queue. As soon as operands became ready, the instruction
+/// was immediately issued to the pipeline(s).
+/// That is expected because instruction 5 cannot transition to the "ready"
+/// state until %xmm4 is written by instruction 4.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_TIMELINEVIEW_H
+#define LLVM_TOOLS_LLVM_MCA_TIMELINEVIEW_H
+
+#include "SourceMgr.h"
+#include "View.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+
+namespace mca {
+
+/// This class listens to instruction state transition events
+/// in order to construct a timeline information.
+///
+/// For every instruction executed by the Pipeline, this class constructs
+/// a TimelineViewEntry object. TimelineViewEntry objects are then used
+/// to print the timeline information, as well as the "average wait times"
+/// for every instruction in the input assembly sequence.
+class TimelineView : public View {
+ const llvm::MCSubtargetInfo &STI;
+ llvm::MCInstPrinter &MCIP;
+ const SourceMgr &AsmSequence;
+
+ unsigned CurrentCycle;
+ unsigned MaxCycle;
+ unsigned LastCycle;
+
+ struct TimelineViewEntry {
+ unsigned CycleDispatched;
+ unsigned CycleReady;
+ unsigned CycleIssued;
+ unsigned CycleExecuted;
+ unsigned CycleRetired;
+ };
+ std::vector<TimelineViewEntry> Timeline;
+
+ struct WaitTimeEntry {
+ unsigned Executions;
+ unsigned CyclesSpentInSchedulerQueue;
+ unsigned CyclesSpentInSQWhileReady;
+ unsigned CyclesSpentAfterWBAndBeforeRetire;
+ };
+ std::vector<WaitTimeEntry> WaitTime;
+
+ void printTimelineViewEntry(llvm::formatted_raw_ostream &OS,
+ const TimelineViewEntry &E, unsigned Iteration,
+ unsigned SourceIndex) const;
+ void printWaitTimeEntry(llvm::formatted_raw_ostream &OS,
+ const WaitTimeEntry &E, unsigned Index) const;
+
+ const unsigned DEFAULT_ITERATIONS = 10;
+
+ void initialize(unsigned MaxIterations);
+
+ // Display characters for the TimelineView report output.
+ struct DisplayChar {
+ static const char Dispatched = 'D';
+ static const char Executed = 'E';
+ static const char Retired = 'R';
+ static const char Waiting = '='; // Instruction is waiting in the scheduler.
+ static const char Executing = 'e';
+ static const char RetireLag = '-'; // The instruction is waiting to retire.
+ };
+
+public:
+ TimelineView(const llvm::MCSubtargetInfo &sti, llvm::MCInstPrinter &Printer,
+ const SourceMgr &Sequence, unsigned MaxIterations,
+ unsigned Cycles)
+ : STI(sti), MCIP(Printer), AsmSequence(Sequence), CurrentCycle(0),
+ MaxCycle(Cycles == 0 ? 80 : Cycles), LastCycle(0) {
+ initialize(MaxIterations);
+ }
+
+ // Event handlers.
+ void onCycleEnd() override { ++CurrentCycle; }
+ void onEvent(const HWInstructionEvent &Event) override;
+
+ // print functionalities.
+ void printTimeline(llvm::raw_ostream &OS) const;
+ void printAverageWaitTimes(llvm::raw_ostream &OS) const;
+ void printView(llvm::raw_ostream &OS) const override {
+ printTimeline(OS);
+ printAverageWaitTimes(OS);
+ }
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/View.cpp b/contrib/llvm/tools/llvm-mca/View.cpp
new file mode 100644
index 000000000000..390a7aeb3b9d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/View.cpp
@@ -0,0 +1,20 @@
+//===----------------------- View.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the virtual anchor method in View.h to pin the vtable.
+///
+//===----------------------------------------------------------------------===//
+
+#include "View.h"
+
+namespace mca {
+
+void View::anchor() {}
+} // namespace mca
diff --git a/contrib/llvm/tools/llvm-mca/View.h b/contrib/llvm/tools/llvm-mca/View.h
new file mode 100644
index 000000000000..9ba94a5da977
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/View.h
@@ -0,0 +1,32 @@
+//===----------------------- View.h -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the main interface for Views. Each view contributes a
+/// portion of the final report generated by the tool.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_VIEW_H
+#define LLVM_TOOLS_LLVM_MCA_VIEW_H
+
+#include "HWEventListener.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace mca {
+
+class View : public HWEventListener {
+public:
+ virtual void printView(llvm::raw_ostream &OS) const = 0;
+ virtual ~View() = default;
+ void anchor() override;
+};
+} // namespace mca
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mca/llvm-mca.cpp b/contrib/llvm/tools/llvm-mca/llvm-mca.cpp
new file mode 100644
index 000000000000..897ff232a36d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mca/llvm-mca.cpp
@@ -0,0 +1,552 @@
+//===-- llvm-mca.cpp - Machine Code Analyzer -------------------*- C++ -* -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility is a simple driver that allows static performance analysis on
+// machine code similarly to how IACA (Intel Architecture Code Analyzer) works.
+//
+// llvm-mca [options] <file-name>
+// -march <type>
+// -mcpu <cpu>
+// -o <file>
+//
+// The target defaults to the host target.
+// The cpu defaults to the 'native' host cpu.
+// The output defaults to standard output.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeRegion.h"
+#include "Context.h"
+#include "DispatchStatistics.h"
+#include "FetchStage.h"
+#include "InstructionInfoView.h"
+#include "InstructionTables.h"
+#include "Pipeline.h"
+#include "PipelinePrinter.h"
+#include "RegisterFileStatistics.h"
+#include "ResourcePressureView.h"
+#include "RetireControlUnitStatistics.h"
+#include "SchedulerStatistics.h"
+#include "SummaryView.h"
+#include "TimelineView.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+
+using namespace llvm;
+
+static cl::OptionCategory ToolOptions("Tool Options");
+static cl::OptionCategory ViewOptions("View Options");
+
+static cl::opt<std::string> InputFilename(cl::Positional,
+ cl::desc("<input file>"),
+ cl::cat(ToolOptions), cl::init("-"));
+
+static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
+ cl::init("-"), cl::cat(ToolOptions),
+ cl::value_desc("filename"));
+
+static cl::opt<std::string>
+ ArchName("march", cl::desc("Target arch to assemble for, "
+ "see -version for available targets"),
+ cl::cat(ToolOptions));
+
+static cl::opt<std::string>
+ TripleName("mtriple", cl::desc("Target triple to assemble for, "
+ "see -version for available targets"),
+ cl::cat(ToolOptions));
+
+static cl::opt<std::string>
+ MCPU("mcpu",
+ cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+ cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native"));
+
+static cl::opt<int>
+ OutputAsmVariant("output-asm-variant",
+ cl::desc("Syntax variant to use for output printing"),
+ cl::cat(ToolOptions), cl::init(-1));
+
+static cl::opt<unsigned> Iterations("iterations",
+ cl::desc("Number of iterations to run"),
+ cl::cat(ToolOptions), cl::init(0));
+
+static cl::opt<unsigned>
+ DispatchWidth("dispatch", cl::desc("Override the processor dispatch width"),
+ cl::cat(ToolOptions), cl::init(0));
+
+static cl::opt<unsigned>
+ RegisterFileSize("register-file-size",
+ cl::desc("Maximum number of physical registers which can "
+ "be used for register mappings"),
+ cl::cat(ToolOptions), cl::init(0));
+
+static cl::opt<bool>
+ PrintRegisterFileStats("register-file-stats",
+ cl::desc("Print register file statistics"),
+ cl::cat(ViewOptions), cl::init(false));
+
+static cl::opt<bool> PrintDispatchStats("dispatch-stats",
+ cl::desc("Print dispatch statistics"),
+ cl::cat(ViewOptions), cl::init(false));
+
+static cl::opt<bool>
+ PrintSummaryView("summary-view", cl::Hidden,
+ cl::desc("Print summary view (enabled by default)"),
+ cl::cat(ViewOptions), cl::init(true));
+
+static cl::opt<bool> PrintSchedulerStats("scheduler-stats",
+ cl::desc("Print scheduler statistics"),
+ cl::cat(ViewOptions), cl::init(false));
+
+static cl::opt<bool>
+ PrintRetireStats("retire-stats",
+ cl::desc("Print retire control unit statistics"),
+ cl::cat(ViewOptions), cl::init(false));
+
+static cl::opt<bool> PrintResourcePressureView(
+ "resource-pressure",
+ cl::desc("Print the resource pressure view (enabled by default)"),
+ cl::cat(ViewOptions), cl::init(true));
+
+static cl::opt<bool> PrintTimelineView("timeline",
+ cl::desc("Print the timeline view"),
+ cl::cat(ViewOptions), cl::init(false));
+
+static cl::opt<unsigned> TimelineMaxIterations(
+ "timeline-max-iterations",
+ cl::desc("Maximum number of iterations to print in timeline view"),
+ cl::cat(ViewOptions), cl::init(0));
+
+static cl::opt<unsigned> TimelineMaxCycles(
+ "timeline-max-cycles",
+ cl::desc(
+ "Maximum number of cycles in the timeline view. Defaults to 80 cycles"),
+ cl::cat(ViewOptions), cl::init(80));
+
+static cl::opt<bool>
+ AssumeNoAlias("noalias",
+ cl::desc("If set, assume that loads and stores do not alias"),
+ cl::cat(ToolOptions), cl::init(true));
+
+static cl::opt<unsigned>
+ LoadQueueSize("lqueue",
+ cl::desc("Size of the load queue (unbound by default)"),
+ cl::cat(ToolOptions), cl::init(0));
+
+static cl::opt<unsigned>
+ StoreQueueSize("squeue",
+ cl::desc("Size of the store queue (unbound by default)"),
+ cl::cat(ToolOptions), cl::init(0));
+
+static cl::opt<bool>
+ PrintInstructionTables("instruction-tables",
+ cl::desc("Print instruction tables"),
+ cl::cat(ToolOptions), cl::init(false));
+
+static cl::opt<bool> PrintInstructionInfoView(
+ "instruction-info",
+ cl::desc("Print the instruction info view (enabled by default)"),
+ cl::cat(ViewOptions), cl::init(true));
+
+static cl::opt<bool> EnableAllStats("all-stats",
+ cl::desc("Print all hardware statistics"),
+ cl::cat(ViewOptions), cl::init(false));
+
+static cl::opt<bool>
+ EnableAllViews("all-views",
+ cl::desc("Print all views including hardware statistics"),
+ cl::cat(ViewOptions), cl::init(false));
+
+namespace {
+
+const Target *getTarget(const char *ProgName) {
+ TripleName = Triple::normalize(TripleName);
+ if (TripleName.empty())
+ TripleName = Triple::normalize(sys::getDefaultTargetTriple());
+ Triple TheTriple(TripleName);
+
+ // Get the target specific parser.
+ std::string Error;
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
+ if (!TheTarget) {
+ errs() << ProgName << ": " << Error;
+ return nullptr;
+ }
+
+ // Return the found target.
+ return TheTarget;
+}
+
+// A comment consumer that parses strings.
+// The only valid tokens are strings.
+class MCACommentConsumer : public AsmCommentConsumer {
+public:
+ mca::CodeRegions &Regions;
+
+ MCACommentConsumer(mca::CodeRegions &R) : Regions(R) {}
+ void HandleComment(SMLoc Loc, StringRef CommentText) override {
+ // Skip empty comments.
+ StringRef Comment(CommentText);
+ if (Comment.empty())
+ return;
+
+ // Skip spaces and tabs
+ unsigned Position = Comment.find_first_not_of(" \t");
+ if (Position >= Comment.size())
+ // we reached the end of the comment. Bail out.
+ return;
+
+ Comment = Comment.drop_front(Position);
+ if (Comment.consume_front("LLVM-MCA-END")) {
+ Regions.endRegion(Loc);
+ return;
+ }
+
+ // Now try to parse string LLVM-MCA-BEGIN
+ if (!Comment.consume_front("LLVM-MCA-BEGIN"))
+ return;
+
+ // Skip spaces and tabs
+ Position = Comment.find_first_not_of(" \t");
+ if (Position < Comment.size())
+ Comment = Comment.drop_front(Position);
+ // Use the rest of the string as a descriptor for this code snippet.
+ Regions.beginRegion(Comment, Loc);
+ }
+};
+
+int AssembleInput(const char *ProgName, MCAsmParser &Parser,
+ const Target *TheTarget, MCSubtargetInfo &STI,
+ MCInstrInfo &MCII, MCTargetOptions &MCOptions) {
+ std::unique_ptr<MCTargetAsmParser> TAP(
+ TheTarget->createMCAsmParser(STI, Parser, MCII, MCOptions));
+
+ if (!TAP) {
+ WithColor::error() << "this target does not support assembly parsing.\n";
+ return 1;
+ }
+
+ Parser.setTargetParser(*TAP);
+ return Parser.Run(false);
+}
+
+ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {
+ if (OutputFilename == "")
+ OutputFilename = "-";
+ std::error_code EC;
+ auto Out =
+ llvm::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None);
+ if (!EC)
+ return std::move(Out);
+ return EC;
+}
+
+class MCStreamerWrapper final : public MCStreamer {
+ mca::CodeRegions &Regions;
+
+public:
+ MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
+ : MCStreamer(Context), Regions(R) {}
+
+ // We only want to intercept the emission of new instructions.
+ virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ bool /* unused */) override {
+ Regions.addInstruction(llvm::make_unique<const MCInst>(Inst));
+ }
+
+ bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
+ return true;
+ }
+
+ void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) override {}
+ void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc Loc = SMLoc()) override {}
+ void EmitGPRel32Value(const MCExpr *Value) override {}
+ void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
+ void EmitCOFFSymbolStorageClass(int StorageClass) override {}
+ void EmitCOFFSymbolType(int Type) override {}
+ void EndCOFFSymbolDef() override {}
+
+ const std::vector<std::unique_ptr<const MCInst>> &
+ GetInstructionSequence(unsigned Index) const {
+ return Regions.getInstructionSequence(Index);
+ }
+};
+} // end of anonymous namespace
+
+static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) {
+ if (!O.getNumOccurrences() || O.getPosition() < Default.getPosition())
+ O = Default.getValue();
+}
+
+static void processViewOptions() {
+ if (!EnableAllViews.getNumOccurrences() &&
+ !EnableAllStats.getNumOccurrences())
+ return;
+
+ if (EnableAllViews.getNumOccurrences()) {
+ processOptionImpl(PrintSummaryView, EnableAllViews);
+ processOptionImpl(PrintResourcePressureView, EnableAllViews);
+ processOptionImpl(PrintTimelineView, EnableAllViews);
+ processOptionImpl(PrintInstructionInfoView, EnableAllViews);
+ }
+
+ const cl::opt<bool> &Default =
+ EnableAllViews.getPosition() < EnableAllStats.getPosition()
+ ? EnableAllStats
+ : EnableAllViews;
+ processOptionImpl(PrintSummaryView, Default);
+ processOptionImpl(PrintRegisterFileStats, Default);
+ processOptionImpl(PrintDispatchStats, Default);
+ processOptionImpl(PrintSchedulerStats, Default);
+ processOptionImpl(PrintRetireStats, Default);
+}
+
+int main(int argc, char **argv) {
+ InitLLVM X(argc, argv);
+
+ // Initialize targets and assembly parsers.
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmParsers();
+
+ // Enable printing of available targets when flag --version is specified.
+ cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
+
+ cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions});
+
+ // Parse flags and initialize target options.
+ cl::ParseCommandLineOptions(argc, argv,
+ "llvm machine code performance analyzer.\n");
+
+ MCTargetOptions MCOptions;
+ MCOptions.PreserveAsmComments = false;
+
+ // Get the target from the triple. If a triple is not specified, then select
+ // the default triple for the host. If the triple doesn't correspond to any
+ // registered target, then exit with an error message.
+ const char *ProgName = argv[0];
+ const Target *TheTarget = getTarget(ProgName);
+ if (!TheTarget)
+ return 1;
+
+ // GetTarget() may replaced TripleName with a default triple.
+ // For safety, reconstruct the Triple object.
+ Triple TheTriple(TripleName);
+
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
+ MemoryBuffer::getFileOrSTDIN(InputFilename);
+ if (std::error_code EC = BufferPtr.getError()) {
+ WithColor::error() << InputFilename << ": " << EC.message() << '\n';
+ return 1;
+ }
+
+ // Apply overrides to llvm-mca specific options.
+ processViewOptions();
+
+ SourceMgr SrcMgr;
+
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
+ SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
+
+ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ assert(MRI && "Unable to create target register info!");
+
+ std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
+ assert(MAI && "Unable to create target asm info!");
+
+ MCObjectFileInfo MOFI;
+ MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr);
+ MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx);
+
+ std::unique_ptr<buffer_ostream> BOS;
+
+ mca::CodeRegions Regions(SrcMgr);
+ MCStreamerWrapper Str(Ctx, Regions);
+
+ std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
+
+ std::unique_ptr<MCInstrAnalysis> MCIA(
+ TheTarget->createMCInstrAnalysis(MCII.get()));
+
+ if (!MCPU.compare("native"))
+ MCPU = llvm::sys::getHostCPUName();
+
+ std::unique_ptr<MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, MCPU, /* FeaturesStr */ ""));
+ if (!STI->isCPUStringValid(MCPU))
+ return 1;
+
+ if (!PrintInstructionTables && !STI->getSchedModel().isOutOfOrder()) {
+ WithColor::error() << "please specify an out-of-order cpu. '" << MCPU
+ << "' is an in-order cpu.\n";
+ return 1;
+ }
+
+ if (!STI->getSchedModel().hasInstrSchedModel()) {
+ WithColor::error()
+ << "unable to find instruction-level scheduling information for"
+ << " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU
+ << "'.\n";
+
+ if (STI->getSchedModel().InstrItineraries)
+ WithColor::note()
+ << "cpu '" << MCPU << "' provides itineraries. However, "
+ << "instruction itineraries are currently unsupported.\n";
+ return 1;
+ }
+
+ std::unique_ptr<MCAsmParser> P(createMCAsmParser(SrcMgr, Ctx, Str, *MAI));
+ MCAsmLexer &Lexer = P->getLexer();
+ MCACommentConsumer CC(Regions);
+ Lexer.setCommentConsumer(&CC);
+
+ if (AssembleInput(ProgName, *P, TheTarget, *STI, *MCII, MCOptions))
+ return 1;
+
+ if (Regions.empty()) {
+ WithColor::error() << "no assembly instructions found.\n";
+ return 1;
+ }
+
+ // Now initialize the output file.
+ auto OF = getOutputStream();
+ if (std::error_code EC = OF.getError()) {
+ WithColor::error() << EC.message() << '\n';
+ return 1;
+ }
+
+ unsigned AssemblerDialect = P->getAssemblerDialect();
+ if (OutputAsmVariant >= 0)
+ AssemblerDialect = static_cast<unsigned>(OutputAsmVariant);
+ std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ Triple(TripleName), AssemblerDialect, *MAI, *MCII, *MRI));
+ if (!IP) {
+ WithColor::error()
+ << "unable to create instruction printer for target triple '"
+ << TheTriple.normalize() << "' with assembly variant "
+ << AssemblerDialect << ".\n";
+ return 1;
+ }
+
+ std::unique_ptr<llvm::ToolOutputFile> TOF = std::move(*OF);
+
+ const MCSchedModel &SM = STI->getSchedModel();
+
+ unsigned Width = SM.IssueWidth;
+ if (DispatchWidth)
+ Width = DispatchWidth;
+
+ // Create an instruction builder.
+ mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA, *IP);
+
+ // Create a context to control ownership of the pipeline hardware.
+ mca::Context MCA(*MRI, *STI);
+
+ mca::PipelineOptions PO(Width, RegisterFileSize, LoadQueueSize,
+ StoreQueueSize, AssumeNoAlias);
+
+ // Number each region in the sequence.
+ unsigned RegionIdx = 0;
+ for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) {
+ // Skip empty code regions.
+ if (Region->empty())
+ continue;
+
+ // Don't print the header of this region if it is the default region, and
+ // it doesn't have an end location.
+ if (Region->startLoc().isValid() || Region->endLoc().isValid()) {
+ TOF->os() << "\n[" << RegionIdx++ << "] Code Region";
+ StringRef Desc = Region->getDescription();
+ if (!Desc.empty())
+ TOF->os() << " - " << Desc;
+ TOF->os() << "\n\n";
+ }
+
+ mca::SourceMgr S(Region->getInstructions(),
+ PrintInstructionTables ? 1 : Iterations);
+
+ if (PrintInstructionTables) {
+ // Create a pipeline, stages, and a printer.
+ auto P = llvm::make_unique<mca::Pipeline>();
+ P->appendStage(llvm::make_unique<mca::FetchStage>(IB, S));
+ P->appendStage(llvm::make_unique<mca::InstructionTables>(SM, IB));
+ mca::PipelinePrinter Printer(*P);
+
+ // Create the views for this pipeline, execute, and emit a report.
+ if (PrintInstructionInfoView) {
+ Printer.addView(
+ llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, S, *IP));
+ }
+ Printer.addView(
+ llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S));
+ P->run();
+ Printer.printReport(TOF->os());
+ continue;
+ }
+
+ // Create a basic pipeline simulating an out-of-order backend.
+ auto P = MCA.createDefaultPipeline(PO, IB, S);
+ mca::PipelinePrinter Printer(*P);
+
+ if (PrintSummaryView)
+ Printer.addView(llvm::make_unique<mca::SummaryView>(SM, S, Width));
+
+ if (PrintInstructionInfoView)
+ Printer.addView(
+ llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, S, *IP));
+
+ if (PrintDispatchStats)
+ Printer.addView(llvm::make_unique<mca::DispatchStatistics>());
+
+ if (PrintSchedulerStats)
+ Printer.addView(llvm::make_unique<mca::SchedulerStatistics>(*STI));
+
+ if (PrintRetireStats)
+ Printer.addView(llvm::make_unique<mca::RetireControlUnitStatistics>());
+
+ if (PrintRegisterFileStats)
+ Printer.addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI));
+
+ if (PrintResourcePressureView)
+ Printer.addView(
+ llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S));
+
+ if (PrintTimelineView) {
+ Printer.addView(llvm::make_unique<mca::TimelineView>(
+ *STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles));
+ }
+
+ P->run();
+ Printer.printReport(TOF->os());
+
+ // Clear the InstrBuilder internal state in preparation for another round.
+ IB.clear();
+ }
+
+ TOF->keep();
+ return 0;
+}
diff --git a/contrib/llvm/tools/llvm-modextract/llvm-modextract.cpp b/contrib/llvm/tools/llvm-modextract/llvm-modextract.cpp
index b2d21c23a094..9fd8340505aa 100644
--- a/contrib/llvm/tools/llvm-modextract/llvm-modextract.cpp
+++ b/contrib/llvm/tools/llvm-modextract/llvm-modextract.cpp
@@ -70,7 +70,7 @@ int main(int argc, char **argv) {
}
std::unique_ptr<Module> M = ExitOnErr(Ms[ModuleIndex].parseModule(Context));
- WriteBitcodeToFile(M.get(), Out->os());
+ WriteBitcodeToFile(*M, Out->os());
Out->keep();
return 0;
diff --git a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
index b6ac9c20a946..37c1bf85809e 100644
--- a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -33,9 +33,8 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
@@ -82,6 +81,11 @@ cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
cl::aliasopt(ExternalOnly), cl::Grouping,
cl::ZeroOrMore);
+cl::opt<bool> NoWeakSymbols("no-weak",
+ cl::desc("Show only non-weak symbols"));
+cl::alias NoWeakSymbols2("W", cl::desc("Alias for --no-weak"),
+ cl::aliasopt(NoWeakSymbols), cl::Grouping);
+
cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"),
cl::Grouping);
cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"),
@@ -270,8 +274,16 @@ struct NMSymbol {
} // anonymous namespace
static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
- bool ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined);
- bool BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined);
+ bool ADefined;
+ if (A.Sym.getRawDataRefImpl().p)
+ ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined);
+ else
+ ADefined = A.TypeChar != 'U';
+ bool BDefined;
+ if (B.Sym.getRawDataRefImpl().p)
+ BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined);
+ else
+ BDefined = B.TypeChar != 'U';
return std::make_tuple(ADefined, A.Address, A.Name, A.Size) <
std::make_tuple(BDefined, B.Address, B.Name, B.Size);
}
@@ -697,7 +709,7 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
if (ReverseSort)
Cmp = [=](const NMSymbol &A, const NMSymbol &B) { return Cmp(B, A); };
- std::sort(SymbolList.begin(), SymbolList.end(), Cmp);
+ llvm::sort(SymbolList.begin(), SymbolList.end(), Cmp);
}
if (!PrintFileName) {
@@ -761,8 +773,10 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
bool Undefined = SymFlags & SymbolRef::SF_Undefined;
bool Global = SymFlags & SymbolRef::SF_Global;
+ bool Weak = SymFlags & SymbolRef::SF_Weak;
if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
- (!Global && ExternalOnly) || (SizeSort && !PrintAddress))
+ (!Global && ExternalOnly) || (SizeSort && !PrintAddress) ||
+ (Weak && NoWeakSymbols))
continue;
if (PrintFileName) {
if (!ArchitectureName.empty())
@@ -1004,6 +1018,10 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
StringRef SectionName;
Obj.getSectionName(Ref, SectionName);
StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
+ if (Obj.is64Bit() &&
+ Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&
+ SegmentName == "__TEXT_EXEC" && SectionName == "__text")
+ return 't';
if (SegmentName == "__TEXT" && SectionName == "__text")
return 't';
if (SegmentName == "__DATA" && SectionName == "__data")
@@ -1203,6 +1221,8 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
raw_string_ostream LOS(LazysNameBuffer);
std::string WeaksNameBuffer;
raw_string_ostream WOS(WeaksNameBuffer);
+ std::string FunctionStartsNameBuffer;
+ raw_string_ostream FOS(FunctionStartsNameBuffer);
if (MachO && !NoDyldInfo) {
MachO::mach_header H;
MachO::mach_header_64 H_64;
@@ -1573,6 +1593,93 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
I++;
}
}
+
+ // Trying adding symbol from the function starts table and LC_MAIN entry
+ // point.
+ SmallVector<uint64_t, 8> FoundFns;
+ uint64_t lc_main_offset = UINT64_MAX;
+ for (const auto &Command : MachO->load_commands()) {
+ if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
+ // We found a function starts segment, parse the addresses for
+ // consumption.
+ MachO::linkedit_data_command LLC =
+ MachO->getLinkeditDataLoadCommand(Command);
+
+ MachO->ReadULEB128s(LLC.dataoff, FoundFns);
+ } else if (Command.C.cmd == MachO::LC_MAIN) {
+ MachO::entry_point_command LCmain =
+ MachO->getEntryPointCommand(Command);
+ lc_main_offset = LCmain.entryoff;
+ }
+ }
+ // See if these addresses are already in the symbol table.
+ unsigned FunctionStartsAdded = 0;
+ for (uint64_t f = 0; f < FoundFns.size(); f++) {
+ bool found = false;
+ for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
+ if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress)
+ found = true;
+ }
+ // See this address is not already in the symbol table fake up an
+ // nlist for it.
+ if (!found) {
+ NMSymbol F;
+ memset(&F, '\0', sizeof(NMSymbol));
+ F.Name = "<redacted function X>";
+ F.Address = FoundFns[f] + BaseSegmentAddress;
+ F.Size = 0;
+ // There is no symbol in the nlist symbol table for this so we set
+ // Sym effectivly to null and the rest of code in here must test for
+ // it and not do things like Sym.getFlags() for it.
+ F.Sym = BasicSymbolRef();
+ F.SymFlags = 0;
+ F.NType = MachO::N_SECT;
+ F.NSect = 0;
+ StringRef SegmentName = StringRef();
+ StringRef SectionName = StringRef();
+ for (const SectionRef &Section : MachO->sections()) {
+ Section.getName(SectionName);
+ SegmentName = MachO->getSectionFinalSegmentName(
+ Section.getRawDataRefImpl());
+ F.NSect++;
+ if (F.Address >= Section.getAddress() &&
+ F.Address < Section.getAddress() + Section.getSize()) {
+ F.Section = Section;
+ break;
+ }
+ }
+ if (SegmentName == "__TEXT" && SectionName == "__text")
+ F.TypeChar = 't';
+ else if (SegmentName == "__DATA" && SectionName == "__data")
+ F.TypeChar = 'd';
+ else if (SegmentName == "__DATA" && SectionName == "__bss")
+ F.TypeChar = 'b';
+ else
+ F.TypeChar = 's';
+ F.NDesc = 0;
+ F.IndirectName = StringRef();
+ SymbolList.push_back(F);
+ if (FoundFns[f] == lc_main_offset)
+ FOS << "<redacted LC_MAIN>";
+ else
+ FOS << "<redacted function " << f << ">";
+ FOS << '\0';
+ FunctionStartsAdded++;
+ }
+ }
+ if (FunctionStartsAdded) {
+ FOS.flush();
+ const char *Q = FunctionStartsNameBuffer.c_str();
+ for (unsigned K = 0; K < FunctionStartsAdded; K++) {
+ SymbolList[I].Name = Q;
+ Q += strlen(Q) + 1;
+ if (SymbolList[I].TypeChar == 'I') {
+ SymbolList[I].IndirectName = Q;
+ Q += strlen(Q) + 1;
+ }
+ I++;
+ }
+ }
}
}
@@ -1915,11 +2022,7 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
}
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
-
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
// llvm-nm only reads binary files.
diff --git a/contrib/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/contrib/llvm/tools/llvm-objcopy/ObjcopyOpts.td
new file mode 100644
index 000000000000..2af2108d98d3
--- /dev/null
+++ b/contrib/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -0,0 +1,99 @@
+include "llvm/Option/OptParser.td"
+
+multiclass Eq<string name> {
+ def NAME: Separate<["--", "-"], name>;
+ def NAME # _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
+}
+
+def help : Flag<["-", "--"], "help">;
+defm binary_architecture : Eq<"binary-architecture">,
+ HelpText<"Used when transforming an architecture-less format (such as binary) to another format">;
+def B : JoinedOrSeparate<["-"], "B">,
+ Alias<binary_architecture>;
+defm input_target : Eq<"input-target">,
+ HelpText<"Format of the input file">,
+ Values<"binary">;
+defm output_target : Eq<"output-target">,
+ HelpText<"Format of the output file">,
+ Values<"binary">;
+def O : JoinedOrSeparate<["-"], "O">,
+ Alias<output_target>;
+defm split_dwo : Eq<"split-dwo">,
+ MetaVarName<"dwo-file">,
+ HelpText<"Equivalent to extract-dwo on the input file to <dwo-file>, then strip-dwo on the input file">;
+defm add_gnu_debuglink : Eq<"add-gnu-debuglink">,
+ MetaVarName<"debug-file">,
+ HelpText<"Add a .gnu_debuglink for <debug-file>">;
+defm remove_section : Eq<"remove-section">,
+ MetaVarName<"section">,
+ HelpText<"Remove <section>">;
+defm rename_section : Eq<"rename-section">,
+ MetaVarName<"old=new">,
+ HelpText<"Renames a section from old to new">;
+defm redefine_symbol : Eq<"redefine-sym">,
+ MetaVarName<"old=new">,
+ HelpText<"Change the name of a symbol old to new">;
+def R : JoinedOrSeparate<["-"], "R">,
+ Alias<remove_section>;
+defm keep : Eq<"keep">,
+ MetaVarName<"section">,
+ HelpText<"Keep <section>">;
+defm only_keep : Eq<"only-keep">,
+ MetaVarName<"section">,
+ HelpText<"Remove all but <section>">;
+def j : JoinedOrSeparate<["-"], "j">,
+ Alias<only_keep>;
+defm add_section : Eq<"add-section">,
+ MetaVarName<"section=file">,
+ HelpText<"Make a section named <section> with the contents of <file>.">;
+def strip_all : Flag<["-", "--"], "strip-all">,
+ HelpText<"Remove non-allocated sections other than .gnu.warning* sections">;
+def strip_all_gnu : Flag<["-", "--"], "strip-all-gnu">,
+ HelpText<"Compaitable with GNU objcopy's --strip-all">;
+def strip_debug : Flag<["-", "--"], "strip-debug">,
+ HelpText<"Remove all debug information">;
+def strip_dwo : Flag<["-", "--"], "strip-dwo">,
+ HelpText<"Remove all DWARF .dwo sections from file">;
+def strip_sections : Flag<["-", "--"], "strip-sections">,
+ HelpText<"Remove all section headers">;
+def strip_non_alloc : Flag<["-", "--"], "strip-non-alloc">,
+ HelpText<"Remove all non-allocated sections">;
+def extract_dwo : Flag<["-", "--"], "extract-dwo">,
+ HelpText<"Remove all sections that are not DWARF .dwo sections from file">;
+def localize_hidden : Flag<["-", "--"], "localize-hidden">,
+ HelpText<"Mark all symbols that have hidden or internal visibility as local">;
+defm localize_symbol : Eq<"localize-symbol">,
+ MetaVarName<"symbol">,
+ HelpText<"Mark <symbol> as local">;
+def L : JoinedOrSeparate<["-"], "L">,
+ Alias<localize_symbol>;
+defm globalize_symbol : Eq<"globalize-symbol">,
+ MetaVarName<"symbol">,
+ HelpText<"Mark <symbol> as global">;
+defm weaken_symbol : Eq<"weaken-symbol">,
+ MetaVarName<"symbol">,
+ HelpText<"Mark <symbol> as weak">;
+def W : JoinedOrSeparate<["-"], "W">,
+ Alias<weaken_symbol>;
+def weaken : Flag<["-", "--"], "weaken">,
+ HelpText<"Mark all global symbols as weak">;
+def discard_all : Flag<["-", "--"], "discard-all">,
+ HelpText<"Remove all local symbols except file and section symbols">;
+def x : Flag<["-"], "x">,
+ Alias<discard_all>;
+defm strip_symbol : Eq<"strip-symbol">,
+ MetaVarName<"symbol">,
+ HelpText<"Remove symbol <symbol>">;
+def N : JoinedOrSeparate<["-"], "N">,
+ Alias<strip_symbol>;
+defm keep_symbol : Eq<"keep-symbol">,
+ MetaVarName<"symbol">,
+ HelpText<"Do not remove symbol <symbol>">;
+def K : JoinedOrSeparate<["-"], "K">,
+ Alias<keep_symbol>;
+def only_keep_debug : Flag<["-", "--"], "only-keep-debug">,
+ HelpText<"Currently ignored. Only for compaitability with GNU objcopy.">;
+def strip_unneeded : Flag<["-", "--"], "strip-unneeded">,
+ HelpText<"Remove all symbols not needed by relocations">;
+def keep_file_symbols : Flag<["-", "--"], "keep-file-symbols">,
+ HelpText<"Do not remove file symbols">;
diff --git a/contrib/llvm/tools/llvm-objcopy/Object.cpp b/contrib/llvm/tools/llvm-objcopy/Object.cpp
index 9e82448187ea..7e88f5263a39 100644
--- a/contrib/llvm/tools/llvm-objcopy/Object.cpp
+++ b/contrib/llvm/tools/llvm-objcopy/Object.cpp
@@ -18,6 +18,7 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Path.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
@@ -26,64 +27,117 @@
#include <vector>
using namespace llvm;
+using namespace llvm::objcopy;
using namespace object;
using namespace ELF;
-template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
- using Elf_Ehdr = typename ELFT::Ehdr;
- using Elf_Phdr = typename ELFT::Phdr;
+Buffer::~Buffer() {}
- uint8_t *Buf = Out.getBufferStart();
- Buf += sizeof(Elf_Ehdr) + Index * sizeof(Elf_Phdr);
- Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(Buf);
- Phdr.p_type = Type;
- Phdr.p_flags = Flags;
- Phdr.p_offset = Offset;
- Phdr.p_vaddr = VAddr;
- Phdr.p_paddr = PAddr;
- Phdr.p_filesz = FileSize;
- Phdr.p_memsz = MemSize;
- Phdr.p_align = Align;
+void FileBuffer::allocate(size_t Size) {
+ Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
+ handleAllErrors(BufferOrErr.takeError(), [this](const ErrorInfoBase &E) {
+ error("failed to open " + getName() + ": " + E.message());
+ });
+ Buf = std::move(*BufferOrErr);
+}
+
+Error FileBuffer::commit() { return Buf->commit(); }
+
+uint8_t *FileBuffer::getBufferStart() {
+ return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
}
-void Segment::writeSegment(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart() + Offset;
- // We want to maintain segments' interstitial data and contents exactly.
- // This lets us just copy segments directly.
- std::copy(std::begin(Contents), std::end(Contents), Buf);
+void MemBuffer::allocate(size_t Size) {
+ Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName());
+}
+
+Error MemBuffer::commit() { return Error::success(); }
+
+uint8_t *MemBuffer::getBufferStart() {
+ return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
+}
+
+std::unique_ptr<WritableMemoryBuffer> MemBuffer::releaseMemoryBuffer() {
+ return std::move(Buf);
+}
+
+template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
+ using Elf_Phdr = typename ELFT::Phdr;
+
+ uint8_t *B = Buf.getBufferStart();
+ B += Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);
+ Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
+ Phdr.p_type = Seg.Type;
+ Phdr.p_flags = Seg.Flags;
+ Phdr.p_offset = Seg.Offset;
+ Phdr.p_vaddr = Seg.VAddr;
+ Phdr.p_paddr = Seg.PAddr;
+ Phdr.p_filesz = Seg.FileSize;
+ Phdr.p_memsz = Seg.MemSize;
+ Phdr.p_align = Seg.Align;
}
void SectionBase::removeSectionReferences(const SectionBase *Sec) {}
+void SectionBase::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {}
void SectionBase::initialize(SectionTableRef SecTable) {}
void SectionBase::finalize() {}
+void SectionBase::markSymbols() {}
+
+template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
+ uint8_t *B = Buf.getBufferStart();
+ B += Sec.HeaderOffset;
+ typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr *>(B);
+ Shdr.sh_name = Sec.NameIndex;
+ Shdr.sh_type = Sec.Type;
+ Shdr.sh_flags = Sec.Flags;
+ Shdr.sh_addr = Sec.Addr;
+ Shdr.sh_offset = Sec.Offset;
+ Shdr.sh_size = Sec.Size;
+ Shdr.sh_link = Sec.Link;
+ Shdr.sh_info = Sec.Info;
+ Shdr.sh_addralign = Sec.Align;
+ Shdr.sh_entsize = Sec.EntrySize;
+}
-template <class ELFT>
-void SectionBase::writeHeader(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart();
- Buf += HeaderOffset;
- typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr *>(Buf);
- Shdr.sh_name = NameIndex;
- Shdr.sh_type = Type;
- Shdr.sh_flags = Flags;
- Shdr.sh_addr = Addr;
- Shdr.sh_offset = Offset;
- Shdr.sh_size = Size;
- Shdr.sh_link = Link;
- Shdr.sh_info = Info;
- Shdr.sh_addralign = Align;
- Shdr.sh_entsize = EntrySize;
-}
-
-void Section::writeSection(FileOutputBuffer &Out) const {
- if (Type == SHT_NOBITS)
+SectionVisitor::~SectionVisitor() {}
+
+void BinarySectionWriter::visit(const SectionIndexSection &Sec) {
+ error("Cannot write symbol section index table '" + Sec.Name + "' ");
+}
+
+void BinarySectionWriter::visit(const SymbolTableSection &Sec) {
+ error("Cannot write symbol table '" + Sec.Name + "' out to binary");
+}
+
+void BinarySectionWriter::visit(const RelocationSection &Sec) {
+ error("Cannot write relocation section '" + Sec.Name + "' out to binary");
+}
+
+void BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {
+ error("Cannot write '" + Sec.Name + "' out to binary");
+}
+
+void BinarySectionWriter::visit(const GroupSection &Sec) {
+ error("Cannot write '" + Sec.Name + "' out to binary");
+}
+
+void SectionWriter::visit(const Section &Sec) {
+ if (Sec.Type == SHT_NOBITS)
return;
- uint8_t *Buf = Out.getBufferStart() + Offset;
- std::copy(std::begin(Contents), std::end(Contents), Buf);
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ std::copy(std::begin(Sec.Contents), std::end(Sec.Contents), Buf);
}
-void OwnedDataSection::writeSection(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart() + Offset;
- std::copy(std::begin(Data), std::end(Data), Buf);
+void Section::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); }
+
+void SectionWriter::visit(const OwnedDataSection &Sec) {
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ std::copy(std::begin(Sec.Data), std::end(Sec.Data), Buf);
+}
+
+void OwnedDataSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
}
void StringTableSection::addString(StringRef Name) {
@@ -97,8 +151,35 @@ uint32_t StringTableSection::findIndex(StringRef Name) const {
void StringTableSection::finalize() { StrTabBuilder.finalize(); }
-void StringTableSection::writeSection(FileOutputBuffer &Out) const {
- StrTabBuilder.write(Out.getBufferStart() + Offset);
+void SectionWriter::visit(const StringTableSection &Sec) {
+ Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset);
+}
+
+void StringTableSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
+}
+
+template <class ELFT>
+void ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ auto *IndexesBuffer = reinterpret_cast<typename ELFT::Word *>(Buf);
+ std::copy(std::begin(Sec.Indexes), std::end(Sec.Indexes), IndexesBuffer);
+}
+
+void SectionIndexSection::initialize(SectionTableRef SecTable) {
+ Size = 0;
+ setSymTab(SecTable.getSectionOfType<SymbolTableSection>(
+ Link,
+ "Link field value " + Twine(Link) + " in section " + Name + " is invalid",
+ "Link field value " + Twine(Link) + " in section " + Name +
+ " is not a symbol table"));
+ Symbols->setShndxTable(this);
+}
+
+void SectionIndexSection::finalize() { Link = Symbols->Index; }
+
+void SectionIndexSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
}
static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
@@ -119,8 +200,13 @@ static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
return false;
}
+// Large indexes force us to clarify exactly what this function should do. This
+// function should return the value that will appear in st_shndx when written
+// out.
uint16_t Symbol::getShndx() const {
if (DefinedIn != nullptr) {
+ if (DefinedIn->Index >= SHN_LORESERVE)
+ return SHN_XINDEX;
return DefinedIn->Index;
}
switch (ShndxType) {
@@ -134,11 +220,18 @@ uint16_t Symbol::getShndx() const {
case SYMBOL_HEXAGON_SCOMMON_2:
case SYMBOL_HEXAGON_SCOMMON_4:
case SYMBOL_HEXAGON_SCOMMON_8:
+ case SYMBOL_XINDEX:
return static_cast<uint16_t>(ShndxType);
}
llvm_unreachable("Symbol with invalid ShndxType encountered");
}
+void SymbolTableSection::assignIndices() {
+ uint32_t Index = 0;
+ for (auto &Sym : Symbols)
+ Sym->Index = Index++;
+}
+
void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
SectionBase *DefinedIn, uint64_t Value,
uint8_t Visibility, uint16_t Shndx,
@@ -148,6 +241,8 @@ void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
Sym.Binding = Bind;
Sym.Type = Type;
Sym.DefinedIn = DefinedIn;
+ if (DefinedIn != nullptr)
+ DefinedIn->HasSymbol = true;
if (DefinedIn == nullptr) {
if (Shndx >= SHN_LORESERVE)
Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
@@ -163,16 +258,33 @@ void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
}
void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {
+ if (SectionIndexTable == Sec)
+ SectionIndexTable = nullptr;
if (SymbolNames == Sec) {
error("String table " + SymbolNames->Name +
" cannot be removed because it is referenced by the symbol table " +
this->Name);
}
- auto Iter =
- std::remove_if(std::begin(Symbols), std::end(Symbols),
- [=](const SymPtr &Sym) { return Sym->DefinedIn == Sec; });
- Size -= (std::end(Symbols) - Iter) * this->EntrySize;
- Symbols.erase(Iter, std::end(Symbols));
+ removeSymbols([Sec](const Symbol &Sym) { return Sym.DefinedIn == Sec; });
+}
+
+void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
+ std::for_each(std::begin(Symbols) + 1, std::end(Symbols),
+ [Callable](SymPtr &Sym) { Callable(*Sym); });
+ std::stable_partition(
+ std::begin(Symbols), std::end(Symbols),
+ [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
+ assignIndices();
+}
+
+void SymbolTableSection::removeSymbols(
+ function_ref<bool(const Symbol &)> ToRemove) {
+ Symbols.erase(
+ std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
+ [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
+ std::end(Symbols));
+ Size = Symbols.size() * EntrySize;
+ assignIndices();
}
void SymbolTableSection::initialize(SectionTableRef SecTable) {
@@ -200,7 +312,17 @@ void SymbolTableSection::finalize() {
Info = MaxLocalIndex + 1;
}
-void SymbolTableSection::addSymbolNames() {
+void SymbolTableSection::prepareForLayout() {
+ // Add all potential section indexes before file layout so that the section
+ // index section has the approprite size.
+ if (SectionIndexTable != nullptr) {
+ for (const auto &Sym : Symbols) {
+ if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
+ SectionIndexTable->addIndex(Sym->DefinedIn->Index);
+ else
+ SectionIndexTable->addIndex(SHN_UNDEF);
+ }
+ }
// Add all of our strings to SymbolNames so that SymbolNames has the right
// size before layout is decided.
for (auto &Sym : Symbols)
@@ -213,13 +335,18 @@ const Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
return Symbols[Index].get();
}
+Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) {
+ return const_cast<Symbol *>(
+ static_cast<const SymbolTableSection *>(this)->getSymbolByIndex(Index));
+}
+
template <class ELFT>
-void SymbolTableSectionImpl<ELFT>::writeSection(FileOutputBuffer &Out) const {
+void ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {
uint8_t *Buf = Out.getBufferStart();
- Buf += Offset;
+ Buf += Sec.Offset;
typename ELFT::Sym *Sym = reinterpret_cast<typename ELFT::Sym *>(Buf);
// Loop though symbols setting each entry of the symbol table.
- for (auto &Symbol : Symbols) {
+ for (auto &Symbol : Sec.Symbols) {
Sym->st_name = Symbol->NameIndex;
Sym->st_value = Symbol->Value;
Sym->st_size = Symbol->Size;
@@ -231,13 +358,18 @@ void SymbolTableSectionImpl<ELFT>::writeSection(FileOutputBuffer &Out) const {
}
}
+void SymbolTableSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
+}
+
template <class SymTabType>
void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
const SectionBase *Sec) {
if (Symbols == Sec) {
- error("Symbol table " + Symbols->Name + " cannot be removed because it is "
- "referenced by the relocation "
- "section " +
+ error("Symbol table " + Symbols->Name +
+ " cannot be removed because it is "
+ "referenced by the relocation "
+ "section " +
this->Name);
}
}
@@ -252,9 +384,9 @@ void RelocSectionWithSymtabBase<SymTabType>::initialize(
" is not a symbol table"));
if (Info != SHN_UNDEF)
- setSection(SecTable.getSection(Info,
- "Info field value " + Twine(Info) +
- " in section " + Name + " is invalid"));
+ setSection(SecTable.getSection(Info, "Info field value " + Twine(Info) +
+ " in section " + Name +
+ " is invalid"));
else
setSection(nullptr);
}
@@ -267,16 +399,15 @@ void RelocSectionWithSymtabBase<SymTabType>::finalize() {
}
template <class ELFT>
-void setAddend(Elf_Rel_Impl<ELFT, false> &Rel, uint64_t Addend) {}
+static void setAddend(Elf_Rel_Impl<ELFT, false> &Rel, uint64_t Addend) {}
template <class ELFT>
-void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
+static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
Rela.r_addend = Addend;
}
-template <class ELFT>
-template <class T>
-void RelocationSection<ELFT>::writeRel(T *Buf) const {
+template <class RelRange, class T>
+static void writeRel(const RelRange &Relocations, T *Buf) {
for (const auto &Reloc : Relocations) {
Buf->r_offset = Reloc.Offset;
setAddend(*Buf, Reloc.Addend);
@@ -286,43 +417,138 @@ void RelocationSection<ELFT>::writeRel(T *Buf) const {
}
template <class ELFT>
-void RelocationSection<ELFT>::writeSection(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart() + Offset;
- if (Type == SHT_REL)
- writeRel(reinterpret_cast<Elf_Rel *>(Buf));
+void ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ if (Sec.Type == SHT_REL)
+ writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf));
else
- writeRel(reinterpret_cast<Elf_Rela *>(Buf));
+ writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf));
}
-void DynamicRelocationSection::writeSection(FileOutputBuffer &Out) const {
- std::copy(std::begin(Contents), std::end(Contents),
- Out.getBufferStart() + Offset);
+void RelocationSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
}
-void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {
- if (StrTab == Sec) {
- error("String table " + StrTab->Name + " cannot be removed because it is "
- "referenced by the section " +
+void RelocationSection::removeSymbols(
+ function_ref<bool(const Symbol &)> ToRemove) {
+ for (const Relocation &Reloc : Relocations)
+ if (ToRemove(*Reloc.RelocSymbol))
+ error("not stripping symbol `" + Reloc.RelocSymbol->Name +
+ "' because it is named in a relocation");
+}
+
+void RelocationSection::markSymbols() {
+ for (const Relocation &Reloc : Relocations)
+ Reloc.RelocSymbol->Referenced = true;
+}
+
+void SectionWriter::visit(const DynamicRelocationSection &Sec) {
+ std::copy(std::begin(Sec.Contents), std::end(Sec.Contents),
+ Out.getBufferStart() + Sec.Offset);
+}
+
+void DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
+}
+
+void Section::removeSectionReferences(const SectionBase *Sec) {
+ if (LinkSection == Sec) {
+ error("Section " + LinkSection->Name +
+ " cannot be removed because it is "
+ "referenced by the section " +
this->Name);
}
}
-bool SectionWithStrTab::classof(const SectionBase *S) {
- return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
+void GroupSection::finalize() {
+ this->Info = Sym->Index;
+ this->Link = SymTab->Index;
}
-void SectionWithStrTab::initialize(SectionTableRef SecTable) {
- auto StrTab = SecTable.getSection(Link,
- "Link field value " + Twine(Link) +
- " in section " + Name + " is invalid");
- if (StrTab->Type != SHT_STRTAB) {
- error("Link field value " + Twine(Link) + " in section " + Name +
- " is not a string table");
+void GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
+ if (ToRemove(*Sym)) {
+ error("Symbol " + Sym->Name +
+ " cannot be removed because it is "
+ "referenced by the section " +
+ this->Name + "[" + Twine(this->Index) + "]");
}
- setStrTab(StrTab);
}
-void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
+void GroupSection::markSymbols() {
+ if (Sym)
+ Sym->Referenced = true;
+}
+
+void Section::initialize(SectionTableRef SecTable) {
+ if (Link != ELF::SHN_UNDEF) {
+ LinkSection =
+ SecTable.getSection(Link, "Link field value " + Twine(Link) +
+ " in section " + Name + " is invalid");
+ if (LinkSection->Type == ELF::SHT_SYMTAB)
+ LinkSection = nullptr;
+ }
+}
+
+void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }
+
+void GnuDebugLinkSection::init(StringRef File, StringRef Data) {
+ FileName = sys::path::filename(File);
+ // The format for the .gnu_debuglink starts with the file name and is
+ // followed by a null terminator and then the CRC32 of the file. The CRC32
+ // should be 4 byte aligned. So we add the FileName size, a 1 for the null
+ // byte, and then finally push the size to alignment and add 4.
+ Size = alignTo(FileName.size() + 1, 4) + 4;
+ // The CRC32 will only be aligned if we align the whole section.
+ Align = 4;
+ Type = ELF::SHT_PROGBITS;
+ Name = ".gnu_debuglink";
+ // For sections not found in segments, OriginalOffset is only used to
+ // establish the order that sections should go in. By using the maximum
+ // possible offset we cause this section to wind up at the end.
+ OriginalOffset = std::numeric_limits<uint64_t>::max();
+ JamCRC crc;
+ crc.update(ArrayRef<char>(Data.data(), Data.size()));
+ // The CRC32 value needs to be complemented because the JamCRC dosn't
+ // finalize the CRC32 value. It also dosn't negate the initial CRC32 value
+ // but it starts by default at 0xFFFFFFFF which is the complement of zero.
+ CRC32 = ~crc.getCRC();
+}
+
+GnuDebugLinkSection::GnuDebugLinkSection(StringRef File) : FileName(File) {
+ // Read in the file to compute the CRC of it.
+ auto DebugOrErr = MemoryBuffer::getFile(File);
+ if (!DebugOrErr)
+ error("'" + File + "': " + DebugOrErr.getError().message());
+ auto Debug = std::move(*DebugOrErr);
+ init(File, Debug->getBuffer());
+}
+
+template <class ELFT>
+void ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
+ auto Buf = Out.getBufferStart() + Sec.Offset;
+ char *File = reinterpret_cast<char *>(Buf);
+ Elf_Word *CRC =
+ reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
+ *CRC = Sec.CRC32;
+ std::copy(std::begin(Sec.FileName), std::end(Sec.FileName), File);
+}
+
+void GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
+}
+
+template <class ELFT>
+void ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
+ ELF::Elf32_Word *Buf =
+ reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
+ *Buf++ = Sec.FlagWord;
+ for (const auto *S : Sec.GroupMembers)
+ support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index);
+}
+
+void GroupSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
+}
// Returns true IFF a section is wholly inside the range of a segment
static bool sectionWithinSegment(const SectionBase &Section,
@@ -345,7 +571,7 @@ static bool segmentOverlapsSegment(const Segment &Child,
Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
}
-static bool compareSegments(const Segment *A, const Segment *B) {
+static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
// Any segment without a parent segment should come before a segment
// that has a parent segment.
if (A->OriginalOffset < B->OriginalOffset)
@@ -355,14 +581,36 @@ static bool compareSegments(const Segment *A, const Segment *B) {
return A->Index < B->Index;
}
-template <class ELFT>
-void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
+static bool compareSegmentsByPAddr(const Segment *A, const Segment *B) {
+ if (A->PAddr < B->PAddr)
+ return true;
+ if (A->PAddr > B->PAddr)
+ return false;
+ return A->Index < B->Index;
+}
+
+template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
+ for (auto &Parent : Obj.segments()) {
+ // Every segment will overlap with itself but we don't want a segment to
+ // be it's own parent so we avoid that situation.
+ if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {
+ // We want a canonical "most parental" segment but this requires
+ // inspecting the ParentSegment.
+ if (compareSegmentsByOffset(&Parent, &Child))
+ if (Child.ParentSegment == nullptr ||
+ compareSegmentsByOffset(&Parent, Child.ParentSegment)) {
+ Child.ParentSegment = &Parent;
+ }
+ }
+ }
+}
+
+template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() {
uint32_t Index = 0;
for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset,
(size_t)Phdr.p_filesz};
- Segments.emplace_back(llvm::make_unique<Segment>(Data));
- Segment &Seg = *Segments.back();
+ Segment &Seg = Obj.addSegment(Data);
Seg.Type = Phdr.p_type;
Seg.Flags = Phdr.p_flags;
Seg.OriginalOffset = Phdr.p_offset;
@@ -373,58 +621,124 @@ void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
Seg.MemSize = Phdr.p_memsz;
Seg.Align = Phdr.p_align;
Seg.Index = Index++;
- for (auto &Section : Sections) {
- if (sectionWithinSegment(*Section, Seg)) {
- Seg.addSection(&*Section);
- if (!Section->ParentSegment ||
- Section->ParentSegment->Offset > Seg.Offset) {
- Section->ParentSegment = &Seg;
+ for (auto &Section : Obj.sections()) {
+ if (sectionWithinSegment(Section, Seg)) {
+ Seg.addSection(&Section);
+ if (!Section.ParentSegment ||
+ Section.ParentSegment->Offset > Seg.Offset) {
+ Section.ParentSegment = &Seg;
}
}
}
}
+
+ auto &ElfHdr = Obj.ElfHdrSegment;
+ // Creating multiple PT_PHDR segments technically is not valid, but PT_LOAD
+ // segments must not overlap, and other types fit even less.
+ ElfHdr.Type = PT_PHDR;
+ ElfHdr.Flags = 0;
+ ElfHdr.OriginalOffset = ElfHdr.Offset = 0;
+ ElfHdr.VAddr = 0;
+ ElfHdr.PAddr = 0;
+ ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
+ ElfHdr.Align = 0;
+ ElfHdr.Index = Index++;
+
+ const auto &Ehdr = *ElfFile.getHeader();
+ auto &PrHdr = Obj.ProgramHdrSegment;
+ PrHdr.Type = PT_PHDR;
+ PrHdr.Flags = 0;
+ // The spec requires us to have p_vaddr % p_align == p_offset % p_align.
+ // Whereas this works automatically for ElfHdr, here OriginalOffset is
+ // always non-zero and to ensure the equation we assign the same value to
+ // VAddr as well.
+ PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = Ehdr.e_phoff;
+ PrHdr.PAddr = 0;
+ PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
+ // The spec requires us to naturally align all the fields.
+ PrHdr.Align = sizeof(Elf_Addr);
+ PrHdr.Index = Index++;
+
// Now we do an O(n^2) loop through the segments in order to match up
// segments.
- for (auto &Child : Segments) {
- for (auto &Parent : Segments) {
- // Every segment will overlap with itself but we don't want a segment to
- // be it's own parent so we avoid that situation.
- if (&Child != &Parent && segmentOverlapsSegment(*Child, *Parent)) {
- // We want a canonical "most parental" segment but this requires
- // inspecting the ParentSegment.
- if (compareSegments(Parent.get(), Child.get()))
- if (Child->ParentSegment == nullptr ||
- compareSegments(Parent.get(), Child->ParentSegment)) {
- Child->ParentSegment = Parent.get();
- }
- }
- }
+ for (auto &Child : Obj.segments())
+ setParentSegment(Child);
+ setParentSegment(ElfHdr);
+ setParentSegment(PrHdr);
+}
+
+template <class ELFT>
+void ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) {
+ auto SecTable = Obj.sections();
+ auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
+ GroupSec->Link,
+ "Link field value " + Twine(GroupSec->Link) + " in section " +
+ GroupSec->Name + " is invalid",
+ "Link field value " + Twine(GroupSec->Link) + " in section " +
+ GroupSec->Name + " is not a symbol table");
+ auto Sym = SymTab->getSymbolByIndex(GroupSec->Info);
+ if (!Sym)
+ error("Info field value " + Twine(GroupSec->Info) + " in section " +
+ GroupSec->Name + " is not a valid symbol index");
+ GroupSec->setSymTab(SymTab);
+ GroupSec->setSymbol(Sym);
+ if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||
+ GroupSec->Contents.empty())
+ error("The content of the section " + GroupSec->Name + " is malformed");
+ const ELF::Elf32_Word *Word =
+ reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
+ const ELF::Elf32_Word *End =
+ Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
+ GroupSec->setFlagWord(*Word++);
+ for (; Word != End; ++Word) {
+ uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
+ GroupSec->addMember(SecTable.getSection(
+ Index, "Group member index " + Twine(Index) + " in section " +
+ GroupSec->Name + " is invalid"));
}
}
template <class ELFT>
-void Object<ELFT>::initSymbolTable(const object::ELFFile<ELFT> &ElfFile,
- SymbolTableSection *SymTab,
- SectionTableRef SecTable) {
+void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));
StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));
+ ArrayRef<Elf_Word> ShndxData;
- for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {
+ auto Symbols = unwrapOrError(ElfFile.symbols(&Shdr));
+ for (const auto &Sym : Symbols) {
SectionBase *DefSection = nullptr;
StringRef Name = unwrapOrError(Sym.getName(StrTabData));
- if (Sym.st_shndx >= SHN_LORESERVE) {
- if (!isValidReservedSectionIndex(Sym.st_shndx, Machine)) {
+ if (Sym.st_shndx == SHN_XINDEX) {
+ if (SymTab->getShndxTable() == nullptr)
+ error("Symbol '" + Name +
+ "' has index SHN_XINDEX but no SHT_SYMTAB_SHNDX section exists.");
+ if (ShndxData.data() == nullptr) {
+ const Elf_Shdr &ShndxSec =
+ *unwrapOrError(ElfFile.getSection(SymTab->getShndxTable()->Index));
+ ShndxData = unwrapOrError(
+ ElfFile.template getSectionContentsAsArray<Elf_Word>(&ShndxSec));
+ if (ShndxData.size() != Symbols.size())
+ error("Symbol section index table does not have the same number of "
+ "entries as the symbol table.");
+ }
+ Elf_Word Index = ShndxData[&Sym - Symbols.begin()];
+ DefSection = Obj.sections().getSection(
+ Index,
+ "Symbol '" + Name + "' has invalid section index " +
+ Twine(Index));
+ } else if (Sym.st_shndx >= SHN_LORESERVE) {
+ if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
error(
"Symbol '" + Name +
"' has unsupported value greater than or equal to SHN_LORESERVE: " +
Twine(Sym.st_shndx));
}
} else if (Sym.st_shndx != SHN_UNDEF) {
- DefSection = SecTable.getSection(
- Sym.st_shndx,
- "Symbol '" + Name + "' is defined in invalid section with index " +
- Twine(Sym.st_shndx));
+ DefSection = Obj.sections().getSection(
+ Sym.st_shndx, "Symbol '" + Name +
+ "' is defined has invalid section index " +
+ Twine(Sym.st_shndx));
}
SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
@@ -440,9 +754,9 @@ static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
ToSet = Rela.r_addend;
}
-template <class ELFT, class T>
-void initRelocations(RelocationSection<ELFT> *Relocs,
- SymbolTableSection *SymbolTable, T RelRange) {
+template <class T>
+static void initRelocations(RelocationSection *Relocs,
+ SymbolTableSection *SymbolTable, T RelRange) {
for (const auto &Rel : RelRange) {
Relocation ToAdd;
ToAdd.Offset = Rel.r_offset;
@@ -453,14 +767,14 @@ void initRelocations(RelocationSection<ELFT> *Relocs,
}
}
-SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) {
+SectionBase *SectionTableRef::getSection(uint32_t Index, Twine ErrMsg) {
if (Index == SHN_UNDEF || Index > Sections.size())
error(ErrMsg);
return Sections[Index - 1].get();
}
template <class T>
-T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
+T *SectionTableRef::getSectionOfType(uint32_t Index, Twine IndexErrMsg,
Twine TypeErrMsg) {
if (T *Sec = dyn_cast<T>(getSection(Index, IndexErrMsg)))
return Sec;
@@ -468,147 +782,221 @@ T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
}
template <class ELFT>
-std::unique_ptr<SectionBase>
-Object<ELFT>::makeSection(const object::ELFFile<ELFT> &ElfFile,
- const Elf_Shdr &Shdr) {
+SectionBase &ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
ArrayRef<uint8_t> Data;
switch (Shdr.sh_type) {
case SHT_REL:
case SHT_RELA:
if (Shdr.sh_flags & SHF_ALLOC) {
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
- return llvm::make_unique<DynamicRelocationSection>(Data);
+ return Obj.addSection<DynamicRelocationSection>(Data);
}
- return llvm::make_unique<RelocationSection<ELFT>>();
+ return Obj.addSection<RelocationSection>();
case SHT_STRTAB:
// If a string table is allocated we don't want to mess with it. That would
// mean altering the memory image. There are no special link types or
// anything so we can just use a Section.
if (Shdr.sh_flags & SHF_ALLOC) {
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
- return llvm::make_unique<Section>(Data);
+ return Obj.addSection<Section>(Data);
}
- return llvm::make_unique<StringTableSection>();
+ return Obj.addSection<StringTableSection>();
case SHT_HASH:
case SHT_GNU_HASH:
// Hash tables should refer to SHT_DYNSYM which we're not going to change.
// Because of this we don't need to mess with the hash tables either.
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
- return llvm::make_unique<Section>(Data);
+ return Obj.addSection<Section>(Data);
+ case SHT_GROUP:
+ Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
+ return Obj.addSection<GroupSection>(Data);
case SHT_DYNSYM:
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
- return llvm::make_unique<DynamicSymbolTableSection>(Data);
+ return Obj.addSection<DynamicSymbolTableSection>(Data);
case SHT_DYNAMIC:
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
- return llvm::make_unique<DynamicSection>(Data);
+ return Obj.addSection<DynamicSection>(Data);
case SHT_SYMTAB: {
- auto SymTab = llvm::make_unique<SymbolTableSectionImpl<ELFT>>();
- SymbolTable = SymTab.get();
- return std::move(SymTab);
+ auto &SymTab = Obj.addSection<SymbolTableSection>();
+ Obj.SymbolTable = &SymTab;
+ return SymTab;
+ }
+ case SHT_SYMTAB_SHNDX: {
+ auto &ShndxSection = Obj.addSection<SectionIndexSection>();
+ Obj.SectionIndexTable = &ShndxSection;
+ return ShndxSection;
}
case SHT_NOBITS:
- return llvm::make_unique<Section>(Data);
+ return Obj.addSection<Section>(Data);
default:
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
- return llvm::make_unique<Section>(Data);
+ return Obj.addSection<Section>(Data);
}
}
-template <class ELFT>
-SectionTableRef Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
+template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() {
uint32_t Index = 0;
for (const auto &Shdr : unwrapOrError(ElfFile.sections())) {
if (Index == 0) {
++Index;
continue;
}
- SecPtr Sec = makeSection(ElfFile, Shdr);
- Sec->Name = unwrapOrError(ElfFile.getSectionName(&Shdr));
- Sec->Type = Shdr.sh_type;
- Sec->Flags = Shdr.sh_flags;
- Sec->Addr = Shdr.sh_addr;
- Sec->Offset = Shdr.sh_offset;
- Sec->OriginalOffset = Shdr.sh_offset;
- Sec->Size = Shdr.sh_size;
- Sec->Link = Shdr.sh_link;
- Sec->Info = Shdr.sh_info;
- Sec->Align = Shdr.sh_addralign;
- Sec->EntrySize = Shdr.sh_entsize;
- Sec->Index = Index++;
- Sections.push_back(std::move(Sec));
- }
-
- SectionTableRef SecTable(Sections);
+ auto &Sec = makeSection(Shdr);
+ Sec.Name = unwrapOrError(ElfFile.getSectionName(&Shdr));
+ Sec.Type = Shdr.sh_type;
+ Sec.Flags = Shdr.sh_flags;
+ Sec.Addr = Shdr.sh_addr;
+ Sec.Offset = Shdr.sh_offset;
+ Sec.OriginalOffset = Shdr.sh_offset;
+ Sec.Size = Shdr.sh_size;
+ Sec.Link = Shdr.sh_link;
+ Sec.Info = Shdr.sh_info;
+ Sec.Align = Shdr.sh_addralign;
+ Sec.EntrySize = Shdr.sh_entsize;
+ Sec.Index = Index++;
+ }
+
+ // If a section index table exists we'll need to initialize it before we
+ // initialize the symbol table because the symbol table might need to
+ // reference it.
+ if (Obj.SectionIndexTable)
+ Obj.SectionIndexTable->initialize(Obj.sections());
// Now that all of the sections have been added we can fill out some extra
// details about symbol tables. We need the symbol table filled out before
// any relocations.
- if (SymbolTable) {
- SymbolTable->initialize(SecTable);
- initSymbolTable(ElfFile, SymbolTable, SecTable);
+ if (Obj.SymbolTable) {
+ Obj.SymbolTable->initialize(Obj.sections());
+ initSymbolTable(Obj.SymbolTable);
}
// Now that all sections and symbols have been added we can add
// relocations that reference symbols and set the link and info fields for
// relocation sections.
- for (auto &Section : Sections) {
- if (Section.get() == SymbolTable)
+ for (auto &Section : Obj.sections()) {
+ if (&Section == Obj.SymbolTable)
continue;
- Section->initialize(SecTable);
- if (auto RelSec = dyn_cast<RelocationSection<ELFT>>(Section.get())) {
+ Section.initialize(Obj.sections());
+ if (auto RelSec = dyn_cast<RelocationSection>(&Section)) {
auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index;
if (RelSec->Type == SHT_REL)
- initRelocations(RelSec, SymbolTable, unwrapOrError(ElfFile.rels(Shdr)));
+ initRelocations(RelSec, Obj.SymbolTable,
+ unwrapOrError(ElfFile.rels(Shdr)));
else
- initRelocations(RelSec, SymbolTable,
+ initRelocations(RelSec, Obj.SymbolTable,
unwrapOrError(ElfFile.relas(Shdr)));
+ } else if (auto GroupSec = dyn_cast<GroupSection>(&Section)) {
+ initGroupSection(GroupSec);
}
}
-
- return SecTable;
}
-template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
- const auto &ElfFile = *Obj.getELFFile();
+template <class ELFT> void ELFBuilder<ELFT>::build() {
const auto &Ehdr = *ElfFile.getHeader();
- std::copy(Ehdr.e_ident, Ehdr.e_ident + 16, Ident);
- Type = Ehdr.e_type;
- Machine = Ehdr.e_machine;
- Version = Ehdr.e_version;
- Entry = Ehdr.e_entry;
- Flags = Ehdr.e_flags;
+ std::copy(Ehdr.e_ident, Ehdr.e_ident + 16, Obj.Ident);
+ Obj.Type = Ehdr.e_type;
+ Obj.Machine = Ehdr.e_machine;
+ Obj.Version = Ehdr.e_version;
+ Obj.Entry = Ehdr.e_entry;
+ Obj.Flags = Ehdr.e_flags;
+
+ readSectionHeaders();
+ readProgramHeaders();
+
+ uint32_t ShstrIndex = Ehdr.e_shstrndx;
+ if (ShstrIndex == SHN_XINDEX)
+ ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
+
+ Obj.SectionNames =
+ Obj.sections().template getSectionOfType<StringTableSection>(
+ ShstrIndex,
+ "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
+ " in elf header " + " is invalid",
+ "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
+ " in elf header " + " is not a string table");
+}
+
+// A generic size function which computes sizes of any random access range.
+template <class R> size_t size(R &&Range) {
+ return static_cast<size_t>(std::end(Range) - std::begin(Range));
+}
+
+Writer::~Writer() {}
- SectionTableRef SecTable = readSectionHeaders(ElfFile);
- readProgramHeaders(ElfFile);
+Reader::~Reader() {}
- SectionNames = SecTable.getSectionOfType<StringTableSection>(
- Ehdr.e_shstrndx,
- "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " +
- " is invalid",
- "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " +
- " is not a string table");
+ElfType ELFReader::getElfType() const {
+ if (isa<ELFObjectFile<ELF32LE>>(Bin))
+ return ELFT_ELF32LE;
+ if (isa<ELFObjectFile<ELF64LE>>(Bin))
+ return ELFT_ELF64LE;
+ if (isa<ELFObjectFile<ELF32BE>>(Bin))
+ return ELFT_ELF32BE;
+ if (isa<ELFObjectFile<ELF64BE>>(Bin))
+ return ELFT_ELF64BE;
+ llvm_unreachable("Invalid ELFType");
}
-template <class ELFT>
-void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart();
- Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf);
- std::copy(Ident, Ident + 16, Ehdr.e_ident);
- Ehdr.e_type = Type;
- Ehdr.e_machine = Machine;
- Ehdr.e_version = Version;
- Ehdr.e_entry = Entry;
- Ehdr.e_phoff = sizeof(Elf_Ehdr);
- Ehdr.e_flags = Flags;
+std::unique_ptr<Object> ELFReader::create() const {
+ auto Obj = llvm::make_unique<Object>();
+ if (auto *o = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
+ ELFBuilder<ELF32LE> Builder(*o, *Obj);
+ Builder.build();
+ return Obj;
+ } else if (auto *o = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
+ ELFBuilder<ELF64LE> Builder(*o, *Obj);
+ Builder.build();
+ return Obj;
+ } else if (auto *o = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
+ ELFBuilder<ELF32BE> Builder(*o, *Obj);
+ Builder.build();
+ return Obj;
+ } else if (auto *o = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
+ ELFBuilder<ELF64BE> Builder(*o, *Obj);
+ Builder.build();
+ return Obj;
+ }
+ error("Invalid file type");
+}
+
+template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
+ uint8_t *B = Buf.getBufferStart();
+ Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(B);
+ std::copy(Obj.Ident, Obj.Ident + 16, Ehdr.e_ident);
+ Ehdr.e_type = Obj.Type;
+ Ehdr.e_machine = Obj.Machine;
+ Ehdr.e_version = Obj.Version;
+ Ehdr.e_entry = Obj.Entry;
+ Ehdr.e_phoff = Obj.ProgramHdrSegment.Offset;
+ Ehdr.e_flags = Obj.Flags;
Ehdr.e_ehsize = sizeof(Elf_Ehdr);
Ehdr.e_phentsize = sizeof(Elf_Phdr);
- Ehdr.e_phnum = Segments.size();
+ Ehdr.e_phnum = size(Obj.segments());
Ehdr.e_shentsize = sizeof(Elf_Shdr);
if (WriteSectionHeaders) {
- Ehdr.e_shoff = SHOffset;
- Ehdr.e_shnum = Sections.size() + 1;
- Ehdr.e_shstrndx = SectionNames->Index;
+ Ehdr.e_shoff = Obj.SHOffset;
+ // """
+ // If the number of sections is greater than or equal to
+ // SHN_LORESERVE (0xff00), this member has the value zero and the actual
+ // number of section header table entries is contained in the sh_size field
+ // of the section header at index 0.
+ // """
+ auto Shnum = size(Obj.sections()) + 1;
+ if (Shnum >= SHN_LORESERVE)
+ Ehdr.e_shnum = 0;
+ else
+ Ehdr.e_shnum = Shnum;
+ // """
+ // If the section name string table section index is greater than or equal
+ // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
+ // and the actual index of the section name string table section is
+ // contained in the sh_link field of the section header at index 0.
+ // """
+ if (Obj.SectionNames->Index >= SHN_LORESERVE)
+ Ehdr.e_shstrndx = SHN_XINDEX;
+ else
+ Ehdr.e_shstrndx = Obj.SectionNames->Index;
} else {
Ehdr.e_shoff = 0;
Ehdr.e_shnum = 0;
@@ -616,42 +1004,46 @@ void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {
}
}
-template <class ELFT>
-void Object<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
- for (auto &Phdr : Segments)
- Phdr->template writeHeader<ELFT>(Out);
+template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {
+ for (auto &Seg : Obj.segments())
+ writePhdr(Seg);
}
-template <class ELFT>
-void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
- uint8_t *Buf = Out.getBufferStart() + SHOffset;
+template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
+ uint8_t *B = Buf.getBufferStart() + Obj.SHOffset;
// This reference serves to write the dummy section header at the begining
// of the file. It is not used for anything else
- Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(Buf);
+ Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
Shdr.sh_name = 0;
Shdr.sh_type = SHT_NULL;
Shdr.sh_flags = 0;
Shdr.sh_addr = 0;
Shdr.sh_offset = 0;
- Shdr.sh_size = 0;
- Shdr.sh_link = 0;
+ // See writeEhdr for why we do this.
+ uint64_t Shnum = size(Obj.sections()) + 1;
+ if (Shnum >= SHN_LORESERVE)
+ Shdr.sh_size = Shnum;
+ else
+ Shdr.sh_size = 0;
+ // See writeEhdr for why we do this.
+ if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
+ Shdr.sh_link = Obj.SectionNames->Index;
+ else
+ Shdr.sh_link = 0;
Shdr.sh_info = 0;
Shdr.sh_addralign = 0;
Shdr.sh_entsize = 0;
- for (auto &Section : Sections)
- Section->template writeHeader<ELFT>(Out);
+ for (auto &Sec : Obj.sections())
+ writeShdr(Sec);
}
-template <class ELFT>
-void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
- for (auto &Section : Sections)
- Section->writeSection(Out);
+template <class ELFT> void ELFWriter<ELFT>::writeSectionData() {
+ for (auto &Sec : Obj.sections())
+ Sec.accept(*SecWriter);
}
-template <class ELFT>
-void Object<ELFT>::removeSections(
- std::function<bool(const SectionBase &)> ToRemove) {
+void Object::removeSections(std::function<bool(const SectionBase &)> ToRemove) {
auto Iter = std::stable_partition(
std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
@@ -665,12 +1057,10 @@ void Object<ELFT>::removeSections(
});
if (SymbolTable != nullptr && ToRemove(*SymbolTable))
SymbolTable = nullptr;
- if (ToRemove(*SectionNames)) {
- if (WriteSectionHeaders)
- error("Cannot remove " + SectionNames->Name +
- " because it is the section header string table.");
+ if (SectionNames != nullptr && ToRemove(*SectionNames))
SectionNames = nullptr;
- }
+ if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
+ SectionIndexTable = nullptr;
// Now make sure there are no remaining references to the sections that will
// be removed. Sometimes it is impossible to remove a reference so we emit
// an error here instead.
@@ -684,14 +1074,15 @@ void Object<ELFT>::removeSections(
Sections.erase(Iter, std::end(Sections));
}
-template <class ELFT>
-void Object<ELFT>::addSection(StringRef SecName, ArrayRef<uint8_t> Data) {
- auto Sec = llvm::make_unique<OwnedDataSection>(SecName, Data);
- Sec->OriginalOffset = ~0ULL;
- Sections.push_back(std::move(Sec));
+void Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
+ if (!SymbolTable)
+ return;
+
+ for (const SecPtr &Sec : Sections)
+ Sec->removeSymbols(ToRemove);
}
-template <class ELFT> void ELFObject<ELFT>::sortSections() {
+void Object::sortSections() {
// Put all sections in offset order. Maintain the ordering as closely as
// possible while meeting that demand however.
auto CompareSections = [](const SecPtr &A, const SecPtr &B) {
@@ -716,7 +1107,8 @@ static uint64_t alignToAddr(uint64_t Offset, uint64_t Addr, uint64_t Align) {
// Orders segments such that if x = y->ParentSegment then y comes before x.
static void OrderSegments(std::vector<Segment *> &Segments) {
- std::stable_sort(std::begin(Segments), std::end(Segments), compareSegments);
+ std::stable_sort(std::begin(Segments), std::end(Segments),
+ compareSegmentsByOffset);
}
// This function finds a consistent layout for a list of segments starting from
@@ -725,7 +1117,7 @@ static void OrderSegments(std::vector<Segment *> &Segments) {
static uint64_t LayoutSegments(std::vector<Segment *> &Segments,
uint64_t Offset) {
assert(std::is_sorted(std::begin(Segments), std::end(Segments),
- compareSegments));
+ compareSegmentsByOffset));
// The only way a segment should move is if a section was between two
// segments and that section was removed. If that section isn't in a segment
// then it's acceptable, but not ideal, to simply move it to after the
@@ -755,8 +1147,8 @@ static uint64_t LayoutSegments(std::vector<Segment *> &Segments,
// does not have a ParentSegment. It returns either the offset given if all
// sections had a ParentSegment or an offset one past the last section if there
// was a section that didn't have a ParentSegment.
-template <class SecPtr>
-static uint64_t LayoutSections(std::vector<SecPtr> &Sections, uint64_t Offset) {
+template <class Range>
+static uint64_t LayoutSections(Range Sections, uint64_t Offset) {
// Now the offset of every segment has been set we can assign the offsets
// of each section. For sections that are covered by a segment we should use
// the segment's original offset and the section's original offset to compute
@@ -765,106 +1157,154 @@ static uint64_t LayoutSections(std::vector<SecPtr> &Sections, uint64_t Offset) {
// covered by segments we can just bump Offset to the next valid location.
uint32_t Index = 1;
for (auto &Section : Sections) {
- Section->Index = Index++;
- if (Section->ParentSegment != nullptr) {
- auto Segment = Section->ParentSegment;
- Section->Offset =
- Segment->Offset + (Section->OriginalOffset - Segment->OriginalOffset);
+ Section.Index = Index++;
+ if (Section.ParentSegment != nullptr) {
+ auto Segment = *Section.ParentSegment;
+ Section.Offset =
+ Segment.Offset + (Section.OriginalOffset - Segment.OriginalOffset);
} else {
- Offset = alignTo(Offset, Section->Align == 0 ? 1 : Section->Align);
- Section->Offset = Offset;
- if (Section->Type != SHT_NOBITS)
- Offset += Section->Size;
+ Offset = alignTo(Offset, Section.Align == 0 ? 1 : Section.Align);
+ Section.Offset = Offset;
+ if (Section.Type != SHT_NOBITS)
+ Offset += Section.Size;
}
}
return Offset;
}
-template <class ELFT> void ELFObject<ELFT>::assignOffsets() {
+template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
// We need a temporary list of segments that has a special order to it
// so that we know that anytime ->ParentSegment is set that segment has
// already had its offset properly set.
std::vector<Segment *> OrderedSegments;
- for (auto &Segment : this->Segments)
- OrderedSegments.push_back(Segment.get());
+ for (auto &Segment : Obj.segments())
+ OrderedSegments.push_back(&Segment);
+ OrderedSegments.push_back(&Obj.ElfHdrSegment);
+ OrderedSegments.push_back(&Obj.ProgramHdrSegment);
OrderSegments(OrderedSegments);
- // The size of ELF + program headers will not change so it is ok to assume
- // that the first offset of the first segment is a good place to start
- // outputting sections. This covers both the standard case and the PT_PHDR
- // case.
- uint64_t Offset;
- if (!OrderedSegments.empty()) {
- Offset = OrderedSegments[0]->Offset;
- } else {
- Offset = sizeof(Elf_Ehdr);
- }
+ // Offset is used as the start offset of the first segment to be laid out.
+ // Since the ELF Header (ElfHdrSegment) must be at the start of the file,
+ // we start at offset 0.
+ uint64_t Offset = 0;
Offset = LayoutSegments(OrderedSegments, Offset);
- Offset = LayoutSections(this->Sections, Offset);
+ Offset = LayoutSections(Obj.sections(), Offset);
// If we need to write the section header table out then we need to align the
// Offset so that SHOffset is valid.
- if (this->WriteSectionHeaders)
+ if (WriteSectionHeaders)
Offset = alignTo(Offset, sizeof(typename ELFT::Addr));
- this->SHOffset = Offset;
+ Obj.SHOffset = Offset;
}
-template <class ELFT> size_t ELFObject<ELFT>::totalSize() const {
+template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
// We already have the section header offset so we can calculate the total
// size by just adding up the size of each section header.
- auto NullSectionSize = this->WriteSectionHeaders ? sizeof(Elf_Shdr) : 0;
- return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) +
+ auto NullSectionSize = WriteSectionHeaders ? sizeof(Elf_Shdr) : 0;
+ return Obj.SHOffset + size(Obj.sections()) * sizeof(Elf_Shdr) +
NullSectionSize;
}
-template <class ELFT> void ELFObject<ELFT>::write(FileOutputBuffer &Out) const {
- this->writeHeader(Out);
- this->writeProgramHeaders(Out);
- this->writeSectionData(Out);
- if (this->WriteSectionHeaders)
- this->writeSectionHeaders(Out);
+template <class ELFT> void ELFWriter<ELFT>::write() {
+ writeEhdr();
+ writePhdrs();
+ writeSectionData();
+ if (WriteSectionHeaders)
+ writeShdrs();
+ if (auto E = Buf.commit())
+ reportError(Buf.getName(), errorToErrorCode(std::move(E)));
}
-template <class ELFT> void ELFObject<ELFT>::finalize() {
- // Make sure we add the names of all the sections.
- if (this->SectionNames != nullptr)
- for (const auto &Section : this->Sections) {
- this->SectionNames->addString(Section->Name);
+template <class ELFT> void ELFWriter<ELFT>::finalize() {
+ // It could happen that SectionNames has been removed and yet the user wants
+ // a section header table output. We need to throw an error if a user tries
+ // to do that.
+ if (Obj.SectionNames == nullptr && WriteSectionHeaders)
+ error("Cannot write section header table because section header string "
+ "table was removed.");
+
+ Obj.sortSections();
+
+ // We need to assign indexes before we perform layout because we need to know
+ // if we need large indexes or not. We can assign indexes first and check as
+ // we go to see if we will actully need large indexes.
+ bool NeedsLargeIndexes = false;
+ if (size(Obj.sections()) >= SHN_LORESERVE) {
+ auto Sections = Obj.sections();
+ NeedsLargeIndexes =
+ std::any_of(Sections.begin() + SHN_LORESERVE, Sections.end(),
+ [](const SectionBase &Sec) { return Sec.HasSymbol; });
+ // TODO: handle case where only one section needs the large index table but
+ // only needs it because the large index table hasn't been removed yet.
+ }
+
+ if (NeedsLargeIndexes) {
+ // This means we definitely need to have a section index table but if we
+ // already have one then we should use it instead of making a new one.
+ if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
+ // Addition of a section to the end does not invalidate the indexes of
+ // other sections and assigns the correct index to the new section.
+ auto &Shndx = Obj.addSection<SectionIndexSection>();
+ Obj.SymbolTable->setShndxTable(&Shndx);
+ Shndx.setSymTab(Obj.SymbolTable);
+ }
+ } else {
+ // Since we don't need SectionIndexTable we should remove it and all
+ // references to it.
+ if (Obj.SectionIndexTable != nullptr) {
+ Obj.removeSections([this](const SectionBase &Sec) {
+ return &Sec == Obj.SectionIndexTable;
+ });
+ }
+ }
+
+ // Make sure we add the names of all the sections. Importantly this must be
+ // done after we decide to add or remove SectionIndexes.
+ if (Obj.SectionNames != nullptr)
+ for (const auto &Section : Obj.sections()) {
+ Obj.SectionNames->addString(Section.Name);
}
- // Make sure we add the names of all the symbols.
- if (this->SymbolTable != nullptr)
- this->SymbolTable->addSymbolNames();
- sortSections();
+ // Before we can prepare for layout the indexes need to be finalized.
+ uint64_t Index = 0;
+ for (auto &Sec : Obj.sections())
+ Sec.Index = Index++;
+
+ // The symbol table does not update all other sections on update. For
+ // instance, symbol names are not added as new symbols are added. This means
+ // that some sections, like .strtab, don't yet have their final size.
+ if (Obj.SymbolTable != nullptr)
+ Obj.SymbolTable->prepareForLayout();
+
assignOffsets();
// Finalize SectionNames first so that we can assign name indexes.
- if (this->SectionNames != nullptr)
- this->SectionNames->finalize();
+ if (Obj.SectionNames != nullptr)
+ Obj.SectionNames->finalize();
// Finally now that all offsets and indexes have been set we can finalize any
// remaining issues.
- uint64_t Offset = this->SHOffset + sizeof(Elf_Shdr);
- for (auto &Section : this->Sections) {
- Section->HeaderOffset = Offset;
+ uint64_t Offset = Obj.SHOffset + sizeof(Elf_Shdr);
+ for (auto &Section : Obj.sections()) {
+ Section.HeaderOffset = Offset;
Offset += sizeof(Elf_Shdr);
- if (this->WriteSectionHeaders)
- Section->NameIndex = this->SectionNames->findIndex(Section->Name);
- Section->finalize();
+ if (WriteSectionHeaders)
+ Section.NameIndex = Obj.SectionNames->findIndex(Section.Name);
+ Section.finalize();
}
-}
-template <class ELFT> size_t BinaryObject<ELFT>::totalSize() const {
- return TotalSize;
+ Buf.allocate(totalSize());
+ SecWriter = llvm::make_unique<ELFSectionWriter<ELFT>>(Buf);
}
-template <class ELFT>
-void BinaryObject<ELFT>::write(FileOutputBuffer &Out) const {
- for (auto &Section : this->Sections) {
- if ((Section->Flags & SHF_ALLOC) == 0)
+void BinaryWriter::write() {
+ for (auto &Section : Obj.sections()) {
+ if ((Section.Flags & SHF_ALLOC) == 0)
continue;
- Section->writeSection(Out);
+ Section.accept(*SecWriter);
}
+ if (auto E = Buf.commit())
+ reportError(Buf.getName(), errorToErrorCode(std::move(E)));
}
-template <class ELFT> void BinaryObject<ELFT>::finalize() {
+void BinaryWriter::finalize() {
// TODO: Create a filter range to construct OrderedSegments from so that this
// code can be deduped with assignOffsets above. This should also solve the
// todo below for LayoutSections.
@@ -873,13 +1313,25 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
// already had it's offset properly set. We only want to consider the segments
// that will affect layout of allocated sections so we only add those.
std::vector<Segment *> OrderedSegments;
- for (auto &Section : this->Sections) {
- if ((Section->Flags & SHF_ALLOC) != 0 &&
- Section->ParentSegment != nullptr) {
- OrderedSegments.push_back(Section->ParentSegment);
+ for (auto &Section : Obj.sections()) {
+ if ((Section.Flags & SHF_ALLOC) != 0 && Section.ParentSegment != nullptr) {
+ OrderedSegments.push_back(Section.ParentSegment);
}
}
- OrderSegments(OrderedSegments);
+
+ // For binary output, we're going to use physical addresses instead of
+ // virtual addresses, since a binary output is used for cases like ROM
+ // loading and physical addresses are intended for ROM loading.
+ // However, if no segment has a physical address, we'll fallback to using
+ // virtual addresses for all.
+ if (std::all_of(std::begin(OrderedSegments), std::end(OrderedSegments),
+ [](const Segment *Segment) { return Segment->PAddr == 0; }))
+ for (const auto &Segment : OrderedSegments)
+ Segment->PAddr = Segment->VAddr;
+
+ std::stable_sort(std::begin(OrderedSegments), std::end(OrderedSegments),
+ compareSegmentsByPAddr);
+
// Because we add a ParentSegment for each section we might have duplicate
// segments in OrderedSegments. If there were duplicates then LayoutSegments
// would do very strange things.
@@ -887,6 +1339,8 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
std::unique(std::begin(OrderedSegments), std::end(OrderedSegments));
OrderedSegments.erase(End, std::end(OrderedSegments));
+ uint64_t Offset = 0;
+
// Modify the first segment so that there is no gap at the start. This allows
// our layout algorithm to proceed as expected while not out writing out the
// gap at the start.
@@ -895,30 +1349,29 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
auto Sec = Seg->firstSection();
auto Diff = Sec->OriginalOffset - Seg->OriginalOffset;
Seg->OriginalOffset += Diff;
- // The size needs to be shrunk as well
+ // The size needs to be shrunk as well.
Seg->FileSize -= Diff;
- Seg->MemSize -= Diff;
- // The VAddr needs to be adjusted so that the alignment is correct as well
- Seg->VAddr += Diff;
- Seg->PAddr = Seg->VAddr;
- // We don't want this to be shifted by alignment so we need to set the
- // alignment to zero.
- Seg->Align = 0;
+ // The PAddr needs to be increased to remove the gap before the first
+ // section.
+ Seg->PAddr += Diff;
+ uint64_t LowestPAddr = Seg->PAddr;
+ for (auto &Segment : OrderedSegments) {
+ Segment->Offset = Segment->PAddr - LowestPAddr;
+ Offset = std::max(Offset, Segment->Offset + Segment->FileSize);
+ }
}
- uint64_t Offset = LayoutSegments(OrderedSegments, 0);
-
// TODO: generalize LayoutSections to take a range. Pass a special range
// constructed from an iterator that skips values for which a predicate does
// not hold. Then pass such a range to LayoutSections instead of constructing
// AllocatedSections here.
std::vector<SectionBase *> AllocatedSections;
- for (auto &Section : this->Sections) {
- if ((Section->Flags & SHF_ALLOC) == 0)
+ for (auto &Section : Obj.sections()) {
+ if ((Section.Flags & SHF_ALLOC) == 0)
continue;
- AllocatedSections.push_back(Section.get());
+ AllocatedSections.push_back(&Section);
}
- LayoutSections(AllocatedSections, Offset);
+ LayoutSections(make_pointee_range(AllocatedSections), Offset);
// Now that every section has been laid out we just need to compute the total
// file size. This might not be the same as the offset returned by
@@ -929,23 +1382,22 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
if (Section->Type != SHT_NOBITS)
TotalSize = std::max(TotalSize, Section->Offset + Section->Size);
}
+
+ Buf.allocate(TotalSize);
+ SecWriter = llvm::make_unique<BinarySectionWriter>(Buf);
}
namespace llvm {
-
-template class Object<ELF64LE>;
-template class Object<ELF64BE>;
-template class Object<ELF32LE>;
-template class Object<ELF32BE>;
-
-template class ELFObject<ELF64LE>;
-template class ELFObject<ELF64BE>;
-template class ELFObject<ELF32LE>;
-template class ELFObject<ELF32BE>;
-
-template class BinaryObject<ELF64LE>;
-template class BinaryObject<ELF64BE>;
-template class BinaryObject<ELF32LE>;
-template class BinaryObject<ELF32BE>;
-
+namespace objcopy {
+
+template class ELFBuilder<ELF64LE>;
+template class ELFBuilder<ELF64BE>;
+template class ELFBuilder<ELF32LE>;
+template class ELFBuilder<ELF32BE>;
+
+template class ELFWriter<ELF64LE>;
+template class ELFWriter<ELF64BE>;
+template class ELFWriter<ELF32LE>;
+template class ELFWriter<ELF32BE>;
+} // end namespace objcopy
} // end namespace llvm
diff --git a/contrib/llvm/tools/llvm-objcopy/Object.h b/contrib/llvm/tools/llvm-objcopy/Object.h
index 639f0f29ceba..76748d5fc641 100644
--- a/contrib/llvm/tools/llvm-objcopy/Object.h
+++ b/contrib/llvm/tools/llvm-objcopy/Object.h
@@ -16,6 +16,8 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/JamCRC.h"
#include <cstddef>
#include <cstdint>
#include <functional>
@@ -24,24 +26,209 @@
#include <vector>
namespace llvm {
+namespace objcopy {
-class FileOutputBuffer;
+class Buffer;
class SectionBase;
+class Section;
+class OwnedDataSection;
+class StringTableSection;
+class SymbolTableSection;
+class RelocationSection;
+class DynamicRelocationSection;
+class GnuDebugLinkSection;
+class GroupSection;
+class SectionIndexSection;
class Segment;
+class Object;
+struct Symbol;
class SectionTableRef {
-private:
- ArrayRef<std::unique_ptr<SectionBase>> Sections;
+ MutableArrayRef<std::unique_ptr<SectionBase>> Sections;
public:
- SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)
+ using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>;
+
+ explicit SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)
: Sections(Secs) {}
SectionTableRef(const SectionTableRef &) = default;
- SectionBase *getSection(uint16_t Index, Twine ErrMsg);
+ iterator begin() { return iterator(Sections.data()); }
+ iterator end() { return iterator(Sections.data() + Sections.size()); }
+
+ SectionBase *getSection(uint32_t Index, Twine ErrMsg);
template <class T>
- T *getSectionOfType(uint16_t Index, Twine IndexErrMsg, Twine TypeErrMsg);
+ T *getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg);
+};
+
+enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
+
+class SectionVisitor {
+public:
+ virtual ~SectionVisitor();
+
+ virtual void visit(const Section &Sec) = 0;
+ virtual void visit(const OwnedDataSection &Sec) = 0;
+ virtual void visit(const StringTableSection &Sec) = 0;
+ virtual void visit(const SymbolTableSection &Sec) = 0;
+ virtual void visit(const RelocationSection &Sec) = 0;
+ virtual void visit(const DynamicRelocationSection &Sec) = 0;
+ virtual void visit(const GnuDebugLinkSection &Sec) = 0;
+ virtual void visit(const GroupSection &Sec) = 0;
+ virtual void visit(const SectionIndexSection &Sec) = 0;
+};
+
+class SectionWriter : public SectionVisitor {
+protected:
+ Buffer &Out;
+
+public:
+ virtual ~SectionWriter(){};
+
+ void visit(const Section &Sec) override;
+ void visit(const OwnedDataSection &Sec) override;
+ void visit(const StringTableSection &Sec) override;
+ void visit(const DynamicRelocationSection &Sec) override;
+ virtual void visit(const SymbolTableSection &Sec) override = 0;
+ virtual void visit(const RelocationSection &Sec) override = 0;
+ virtual void visit(const GnuDebugLinkSection &Sec) override = 0;
+ virtual void visit(const GroupSection &Sec) override = 0;
+ virtual void visit(const SectionIndexSection &Sec) override = 0;
+
+ explicit SectionWriter(Buffer &Buf) : Out(Buf) {}
+};
+
+template <class ELFT> class ELFSectionWriter : public SectionWriter {
+private:
+ using Elf_Word = typename ELFT::Word;
+ using Elf_Rel = typename ELFT::Rel;
+ using Elf_Rela = typename ELFT::Rela;
+
+public:
+ virtual ~ELFSectionWriter() {}
+ void visit(const SymbolTableSection &Sec) override;
+ void visit(const RelocationSection &Sec) override;
+ void visit(const GnuDebugLinkSection &Sec) override;
+ void visit(const GroupSection &Sec) override;
+ void visit(const SectionIndexSection &Sec) override;
+
+ explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
+};
+
+#define MAKE_SEC_WRITER_FRIEND \
+ friend class SectionWriter; \
+ template <class ELFT> friend class ELFSectionWriter;
+
+class BinarySectionWriter : public SectionWriter {
+public:
+ virtual ~BinarySectionWriter() {}
+
+ void visit(const SymbolTableSection &Sec) override;
+ void visit(const RelocationSection &Sec) override;
+ void visit(const GnuDebugLinkSection &Sec) override;
+ void visit(const GroupSection &Sec) override;
+ void visit(const SectionIndexSection &Sec) override;
+
+ explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
+};
+
+// The class Buffer abstracts out the common interface of FileOutputBuffer and
+// WritableMemoryBuffer so that the hierarchy of Writers depends on this
+// abstract interface and doesn't depend on a particular implementation.
+// TODO: refactor the buffer classes in LLVM to enable us to use them here
+// directly.
+class Buffer {
+ StringRef Name;
+
+public:
+ virtual ~Buffer();
+ virtual void allocate(size_t Size) = 0;
+ virtual uint8_t *getBufferStart() = 0;
+ virtual Error commit() = 0;
+
+ explicit Buffer(StringRef Name) : Name(Name) {}
+ StringRef getName() const { return Name; }
+};
+
+class FileBuffer : public Buffer {
+ std::unique_ptr<FileOutputBuffer> Buf;
+
+public:
+ void allocate(size_t Size) override;
+ uint8_t *getBufferStart() override;
+ Error commit() override;
+
+ explicit FileBuffer(StringRef FileName) : Buffer(FileName) {}
+};
+
+class MemBuffer : public Buffer {
+ std::unique_ptr<WritableMemoryBuffer> Buf;
+
+public:
+ void allocate(size_t Size) override;
+ uint8_t *getBufferStart() override;
+ Error commit() override;
+
+ explicit MemBuffer(StringRef Name) : Buffer(Name) {}
+
+ std::unique_ptr<WritableMemoryBuffer> releaseMemoryBuffer();
+};
+
+class Writer {
+protected:
+ Object &Obj;
+ Buffer &Buf;
+
+public:
+ virtual ~Writer();
+ virtual void finalize() = 0;
+ virtual void write() = 0;
+
+ Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
+};
+
+template <class ELFT> class ELFWriter : public Writer {
+private:
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Phdr = typename ELFT::Phdr;
+ using Elf_Ehdr = typename ELFT::Ehdr;
+
+ void writeEhdr();
+ void writePhdr(const Segment &Seg);
+ void writeShdr(const SectionBase &Sec);
+
+ void writePhdrs();
+ void writeShdrs();
+ void writeSectionData();
+
+ void assignOffsets();
+
+ std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
+
+ size_t totalSize() const;
+
+public:
+ virtual ~ELFWriter() {}
+ bool WriteSectionHeaders = true;
+
+ void finalize() override;
+ void write() override;
+ ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
+ : Writer(Obj, Buf), WriteSectionHeaders(WSH) {}
+};
+
+class BinaryWriter : public Writer {
+private:
+ std::unique_ptr<BinarySectionWriter> SecWriter;
+
+ uint64_t TotalSize;
+
+public:
+ ~BinaryWriter() {}
+ void finalize() override;
+ void write() override;
+ BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
};
class SectionBase {
@@ -49,8 +236,9 @@ public:
StringRef Name;
Segment *ParentSegment = nullptr;
uint64_t HeaderOffset;
- uint64_t OriginalOffset;
+ uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
uint32_t Index;
+ bool HasSymbol = false;
uint64_t Addr = 0;
uint64_t Align = 1;
@@ -68,8 +256,9 @@ public:
virtual void initialize(SectionTableRef SecTable);
virtual void finalize();
virtual void removeSectionReferences(const SectionBase *Sec);
- template <class ELFT> void writeHeader(FileOutputBuffer &Out) const;
- virtual void writeSection(FileOutputBuffer &Out) const = 0;
+ virtual void removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
+ virtual void accept(SectionVisitor &Visitor) const = 0;
+ virtual void markSymbols();
};
class Segment {
@@ -102,7 +291,8 @@ public:
uint64_t OriginalOffset;
Segment *ParentSegment = nullptr;
- Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
+ explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
+ Segment() {}
const SectionBase *firstSection() const {
if (!Sections.empty())
@@ -112,22 +302,26 @@ public:
void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
- template <class ELFT> void writeHeader(FileOutputBuffer &Out) const;
- void writeSegment(FileOutputBuffer &Out) const;
};
class Section : public SectionBase {
-private:
+ MAKE_SEC_WRITER_FRIEND
+
ArrayRef<uint8_t> Contents;
+ SectionBase *LinkSection = nullptr;
public:
- Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
+ explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
- void writeSection(FileOutputBuffer &Out) const override;
+ void accept(SectionVisitor &Visitor) const override;
+ void removeSectionReferences(const SectionBase *Sec) override;
+ void initialize(SectionTableRef SecTable) override;
+ void finalize() override;
};
class OwnedDataSection : public SectionBase {
-private:
+ MAKE_SEC_WRITER_FRIEND
+
std::vector<uint8_t> Data;
public:
@@ -136,8 +330,10 @@ public:
Name = SecName;
Type = ELF::SHT_PROGBITS;
Size = Data.size();
+ OriginalOffset = std::numeric_limits<uint64_t>::max();
}
- void writeSection(FileOutputBuffer &Out) const override;
+
+ void accept(SectionVisitor &Sec) const override;
};
// There are two types of string tables that can exist, dynamic and not dynamic.
@@ -149,7 +345,8 @@ public:
// classof method checks that the particular instance is not allocated. This
// then agrees with the makeSection method used to construct most sections.
class StringTableSection : public SectionBase {
-private:
+ MAKE_SEC_WRITER_FRIEND
+
StringTableBuilder StrTabBuilder;
public:
@@ -160,7 +357,7 @@ public:
void addString(StringRef Name);
uint32_t findIndex(StringRef Name) const;
void finalize() override;
- void writeSection(FileOutputBuffer &Out) const override;
+ void accept(SectionVisitor &Visitor) const override;
static bool classof(const SectionBase *S) {
if (S->Flags & ELF::SHF_ALLOC)
@@ -181,6 +378,7 @@ enum SymbolShndxType {
SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
+ SYMBOL_XINDEX = ELF::SHN_XINDEX,
};
struct Symbol {
@@ -194,41 +392,79 @@ struct Symbol {
uint8_t Type;
uint64_t Value;
uint8_t Visibility;
+ bool Referenced = false;
uint16_t getShndx() const;
};
+class SectionIndexSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+private:
+ std::vector<uint32_t> Indexes;
+ SymbolTableSection *Symbols = nullptr;
+
+public:
+ virtual ~SectionIndexSection() {}
+ void addIndex(uint32_t Index) {
+ Indexes.push_back(Index);
+ Size += 4;
+ }
+ void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
+ void initialize(SectionTableRef SecTable) override;
+ void finalize() override;
+ void accept(SectionVisitor &Visitor) const override;
+
+ SectionIndexSection() {
+ Name = ".symtab_shndx";
+ Align = 4;
+ EntrySize = 4;
+ Type = ELF::SHT_SYMTAB_SHNDX;
+ }
+};
+
class SymbolTableSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+ void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
+ void assignIndices();
+
protected:
std::vector<std::unique_ptr<Symbol>> Symbols;
StringTableSection *SymbolNames = nullptr;
+ SectionIndexSection *SectionIndexTable = nullptr;
using SymPtr = std::unique_ptr<Symbol>;
public:
- void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
void addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility,
uint16_t Shndx, uint64_t Sz);
- void addSymbolNames();
+ void prepareForLayout();
+ // An 'empty' symbol table still contains a null symbol.
+ bool empty() const { return Symbols.size() == 1; }
+ void setShndxTable(SectionIndexSection *ShndxTable) {
+ SectionIndexTable = ShndxTable;
+ }
+ const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
const SectionBase *getStrTab() const { return SymbolNames; }
const Symbol *getSymbolByIndex(uint32_t Index) const;
+ Symbol *getSymbolByIndex(uint32_t Index);
+ void updateSymbols(function_ref<void(Symbol &)> Callable);
+
void removeSectionReferences(const SectionBase *Sec) override;
void initialize(SectionTableRef SecTable) override;
void finalize() override;
+ void accept(SectionVisitor &Visitor) const override;
+ void removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
static bool classof(const SectionBase *S) {
return S->Type == ELF::SHT_SYMTAB;
}
};
-// Only writeSection depends on the ELF type so we implement it in a subclass.
-template <class ELFT> class SymbolTableSectionImpl : public SymbolTableSection {
- void writeSection(FileOutputBuffer &Out) const override;
-};
-
struct Relocation {
- const Symbol *RelocSymbol = nullptr;
+ Symbol *RelocSymbol = nullptr;
uint64_t Offset;
uint64_t Addend;
uint32_t Type;
@@ -260,33 +496,29 @@ public:
// that code between the two symbol table types.
template <class SymTabType>
class RelocSectionWithSymtabBase : public RelocationSectionBase {
-private:
SymTabType *Symbols = nullptr;
+ void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
protected:
RelocSectionWithSymtabBase() = default;
public:
- void setSymTab(SymTabType *StrTab) { Symbols = StrTab; }
void removeSectionReferences(const SectionBase *Sec) override;
void initialize(SectionTableRef SecTable) override;
void finalize() override;
};
-template <class ELFT>
class RelocationSection
: public RelocSectionWithSymtabBase<SymbolTableSection> {
-private:
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
+ MAKE_SEC_WRITER_FRIEND
std::vector<Relocation> Relocations;
- template <class T> void writeRel(T *Buf) const;
-
public:
void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
- void writeSection(FileOutputBuffer &Out) const override;
+ void accept(SectionVisitor &Visitor) const override;
+ void removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
+ void markSymbols() override;
static bool classof(const SectionBase *S) {
if (S->Flags & ELF::SHF_ALLOC)
@@ -295,32 +527,51 @@ public:
}
};
-class SectionWithStrTab : public Section {
-private:
- const SectionBase *StrTab = nullptr;
+// TODO: The way stripping and groups interact is complicated
+// and still needs to be worked on.
+
+class GroupSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+ const SymbolTableSection *SymTab = nullptr;
+ Symbol *Sym = nullptr;
+ ELF::Elf32_Word FlagWord;
+ SmallVector<SectionBase *, 3> GroupMembers;
public:
- SectionWithStrTab(ArrayRef<uint8_t> Data) : Section(Data) {}
+ // TODO: Contents is present in several classes of the hierarchy.
+ // This needs to be refactored to avoid duplication.
+ ArrayRef<uint8_t> Contents;
- void setStrTab(const SectionBase *StringTable) { StrTab = StringTable; }
- void removeSectionReferences(const SectionBase *Sec) override;
- void initialize(SectionTableRef SecTable) override;
+ explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
+
+ void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
+ void setSymbol(Symbol *S) { Sym = S; }
+ void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
+ void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
+
+ void initialize(SectionTableRef SecTable) override{};
+ void accept(SectionVisitor &) const override;
void finalize() override;
- static bool classof(const SectionBase *S);
+ void removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
+ void markSymbols() override;
+
+ static bool classof(const SectionBase *S) {
+ return S->Type == ELF::SHT_GROUP;
+ }
};
-class DynamicSymbolTableSection : public SectionWithStrTab {
+class DynamicSymbolTableSection : public Section {
public:
- DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
+ explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
static bool classof(const SectionBase *S) {
return S->Type == ELF::SHT_DYNSYM;
}
};
-class DynamicSection : public SectionWithStrTab {
+class DynamicSection : public Section {
public:
- DynamicSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
+ explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
static bool classof(const SectionBase *S) {
return S->Type == ELF::SHT_DYNAMIC;
@@ -329,13 +580,15 @@ public:
class DynamicRelocationSection
: public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
+ MAKE_SEC_WRITER_FRIEND
+
private:
ArrayRef<uint8_t> Contents;
public:
- DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
+ explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
- void writeSection(FileOutputBuffer &Out) const override;
+ void accept(SectionVisitor &) const override;
static bool classof(const SectionBase *S) {
if (!(S->Flags & ELF::SHF_ALLOC))
@@ -344,90 +597,125 @@ public:
}
};
-template <class ELFT> class Object {
-private:
- using SecPtr = std::unique_ptr<SectionBase>;
- using SegPtr = std::unique_ptr<Segment>;
-
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Ehdr = typename ELFT::Ehdr;
- using Elf_Phdr = typename ELFT::Phdr;
-
- void initSymbolTable(const object::ELFFile<ELFT> &ElfFile,
- SymbolTableSection *SymTab, SectionTableRef SecTable);
- SecPtr makeSection(const object::ELFFile<ELFT> &ElfFile,
- const Elf_Shdr &Shdr);
- void readProgramHeaders(const object::ELFFile<ELFT> &ElfFile);
- SectionTableRef readSectionHeaders(const object::ELFFile<ELFT> &ElfFile);
+class GnuDebugLinkSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
-protected:
- StringTableSection *SectionNames = nullptr;
- SymbolTableSection *SymbolTable = nullptr;
- std::vector<SecPtr> Sections;
- std::vector<SegPtr> Segments;
+private:
+ StringRef FileName;
+ uint32_t CRC32;
- void writeHeader(FileOutputBuffer &Out) const;
- void writeProgramHeaders(FileOutputBuffer &Out) const;
- void writeSectionData(FileOutputBuffer &Out) const;
- void writeSectionHeaders(FileOutputBuffer &Out) const;
+ void init(StringRef File, StringRef Data);
public:
- uint8_t Ident[16];
- uint64_t Entry;
- uint64_t SHOffset;
- uint32_t Type;
- uint32_t Machine;
- uint32_t Version;
- uint32_t Flags;
- bool WriteSectionHeaders = true;
-
- Object(const object::ELFObjectFile<ELFT> &Obj);
- virtual ~Object() = default;
+ // If we add this section from an external source we can use this ctor.
+ explicit GnuDebugLinkSection(StringRef File);
+ void accept(SectionVisitor &Visitor) const override;
+};
- const SymbolTableSection *getSymTab() const { return SymbolTable; }
- const SectionBase *getSectionHeaderStrTab() const { return SectionNames; }
- void removeSections(std::function<bool(const SectionBase &)> ToRemove);
- void addSection(StringRef SecName, ArrayRef<uint8_t> Data);
- virtual size_t totalSize() const = 0;
- virtual void finalize() = 0;
- virtual void write(FileOutputBuffer &Out) const = 0;
+class Reader {
+public:
+ virtual ~Reader();
+ virtual std::unique_ptr<Object> create() const = 0;
};
-template <class ELFT> class ELFObject : public Object<ELFT> {
-private:
- using SecPtr = std::unique_ptr<SectionBase>;
- using SegPtr = std::unique_ptr<Segment>;
+using object::Binary;
+using object::ELFFile;
+using object::ELFObjectFile;
+using object::OwningBinary;
+template <class ELFT> class ELFBuilder {
+private:
+ using Elf_Addr = typename ELFT::Addr;
using Elf_Shdr = typename ELFT::Shdr;
using Elf_Ehdr = typename ELFT::Ehdr;
- using Elf_Phdr = typename ELFT::Phdr;
+ using Elf_Word = typename ELFT::Word;
- void sortSections();
- void assignOffsets();
+ const ELFFile<ELFT> &ElfFile;
+ Object &Obj;
+
+ void setParentSegment(Segment &Child);
+ void readProgramHeaders();
+ void initGroupSection(GroupSection *GroupSec);
+ void initSymbolTable(SymbolTableSection *SymTab);
+ void readSectionHeaders();
+ SectionBase &makeSection(const Elf_Shdr &Shdr);
public:
- ELFObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {}
+ ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj)
+ : ElfFile(*ElfObj.getELFFile()), Obj(Obj) {}
- void finalize() override;
- size_t totalSize() const override;
- void write(FileOutputBuffer &Out) const override;
+ void build();
};
-template <class ELFT> class BinaryObject : public Object<ELFT> {
+class ELFReader : public Reader {
+ Binary *Bin;
+
+public:
+ ElfType getElfType() const;
+ std::unique_ptr<Object> create() const override;
+ explicit ELFReader(Binary *B) : Bin(B){};
+};
+
+class Object {
private:
using SecPtr = std::unique_ptr<SectionBase>;
using SegPtr = std::unique_ptr<Segment>;
- uint64_t TotalSize;
+ std::vector<SecPtr> Sections;
+ std::vector<SegPtr> Segments;
public:
- BinaryObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {}
+ template <class T>
+ using Range = iterator_range<
+ pointee_iterator<typename std::vector<std::unique_ptr<T>>::iterator>>;
- void finalize() override;
- size_t totalSize() const override;
- void write(FileOutputBuffer &Out) const override;
-};
+ template <class T>
+ using ConstRange = iterator_range<pointee_iterator<
+ typename std::vector<std::unique_ptr<T>>::const_iterator>>;
+
+ // It is often the case that the ELF header and the program header table are
+ // not present in any segment. This could be a problem during file layout,
+ // because other segments may get assigned an offset where either of the
+ // two should reside, which will effectively corrupt the resulting binary.
+ // Other than that we use these segments to track program header offsets
+ // when they may not follow the ELF header.
+ Segment ElfHdrSegment;
+ Segment ProgramHdrSegment;
+ uint8_t Ident[16];
+ uint64_t Entry;
+ uint64_t SHOffset;
+ uint32_t Type;
+ uint32_t Machine;
+ uint32_t Version;
+ uint32_t Flags;
+
+ StringTableSection *SectionNames = nullptr;
+ SymbolTableSection *SymbolTable = nullptr;
+ SectionIndexSection *SectionIndexTable = nullptr;
+
+ void sortSections();
+ SectionTableRef sections() { return SectionTableRef(Sections); }
+ ConstRange<SectionBase> sections() const {
+ return make_pointee_range(Sections);
+ }
+ Range<Segment> segments() { return make_pointee_range(Segments); }
+ ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
+
+ void removeSections(std::function<bool(const SectionBase &)> ToRemove);
+ void removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
+ template <class T, class... Ts> T &addSection(Ts &&... Args) {
+ auto Sec = llvm::make_unique<T>(std::forward<Ts>(Args)...);
+ auto Ptr = Sec.get();
+ Sections.emplace_back(std::move(Sec));
+ return *Ptr;
+ }
+ Segment &addSegment(ArrayRef<uint8_t> Data) {
+ Segments.emplace_back(llvm::make_unique<Segment>(Data));
+ return *Segments.back();
+ }
+};
+} // end namespace objcopy
} // end namespace llvm
#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H
diff --git a/contrib/llvm/tools/llvm-objcopy/StripOpts.td b/contrib/llvm/tools/llvm-objcopy/StripOpts.td
new file mode 100644
index 000000000000..333b0d288efa
--- /dev/null
+++ b/contrib/llvm/tools/llvm-objcopy/StripOpts.td
@@ -0,0 +1,49 @@
+include "llvm/Option/OptParser.td"
+
+multiclass Eq<string name> {
+ def NAME: Separate<["--", "-"], name>;
+ def NAME # _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
+}
+
+def help : Flag<["-", "--"], "help">;
+
+defm output : Eq<"o">,
+ MetaVarName<"output">,
+ HelpText<"Write output to <file>">;
+
+def strip_all : Flag<["-", "--"], "strip-all">,
+ HelpText<"Remove non-allocated sections other than .gnu.warning* sections">;
+
+def strip_debug : Flag<["-", "--"], "strip-debug">,
+ HelpText<"Remove debugging symbols only">;
+
+def d : Flag<["-"], "d">,
+ Alias<strip_debug>;
+
+def g : Flag<["-"], "g">,
+ Alias<strip_debug>;
+
+def S : Flag<["-"], "S">,
+ Alias<strip_debug>;
+
+defm remove_section : Eq<"remove-section">,
+ MetaVarName<"section">,
+ HelpText<"Remove <section>">;
+
+def R : JoinedOrSeparate<["-"], "R">,
+ Alias<remove_section>;
+
+defm keep_symbol : Eq<"keep-symbol">,
+ MetaVarName<"symbol">,
+ HelpText<"Do not remove symbol <symbol>">;
+
+def K : JoinedOrSeparate<["-"], "K">,
+ Alias<keep_symbol>;
+
+def discard_all : Flag<["-", "--"], "discard-all">,
+ HelpText<"Remove all local symbols except file and section symbols">;
+def x : Flag<["-"], "x">,
+ Alias<discard_all>;
+
+def strip_unneeded : Flag<["-", "--"], "strip-unneeded">,
+ HelpText<"Remove all symbols not needed by relocations">;
diff --git a/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 20ce93bb40e8..21a1622db765 100644
--- a/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -13,10 +13,15 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
@@ -24,9 +29,8 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -39,13 +43,122 @@
#include <utility>
using namespace llvm;
+using namespace llvm::objcopy;
using namespace object;
using namespace ELF;
-// The name this program was invoked as.
-static StringRef ToolName;
+namespace {
+
+enum ObjcopyID {
+ OBJCOPY_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ OBJCOPY_##ID,
+#include "ObjcopyOpts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const OBJCOPY_##NAME[] = VALUE;
+#include "ObjcopyOpts.inc"
+#undef PREFIX
+
+static const opt::OptTable::Info ObjcopyInfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ {OBJCOPY_##PREFIX, \
+ NAME, \
+ HELPTEXT, \
+ METAVAR, \
+ OBJCOPY_##ID, \
+ opt::Option::KIND##Class, \
+ PARAM, \
+ FLAGS, \
+ OBJCOPY_##GROUP, \
+ OBJCOPY_##ALIAS, \
+ ALIASARGS, \
+ VALUES},
+#include "ObjcopyOpts.inc"
+#undef OPTION
+};
+
+class ObjcopyOptTable : public opt::OptTable {
+public:
+ ObjcopyOptTable() : OptTable(ObjcopyInfoTable, true) {}
+};
+
+enum StripID {
+ STRIP_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ STRIP_##ID,
+#include "StripOpts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const STRIP_##NAME[] = VALUE;
+#include "StripOpts.inc"
+#undef PREFIX
+
+static const opt::OptTable::Info StripInfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ {STRIP_##PREFIX, NAME, HELPTEXT, \
+ METAVAR, STRIP_##ID, opt::Option::KIND##Class, \
+ PARAM, FLAGS, STRIP_##GROUP, \
+ STRIP_##ALIAS, ALIASARGS, VALUES},
+#include "StripOpts.inc"
+#undef OPTION
+};
+
+class StripOptTable : public opt::OptTable {
+public:
+ StripOptTable() : OptTable(StripInfoTable, true) {}
+};
+
+struct CopyConfig {
+ StringRef OutputFilename;
+ StringRef InputFilename;
+ StringRef OutputFormat;
+ StringRef InputFormat;
+ StringRef BinaryArch;
+
+ StringRef SplitDWO;
+ StringRef AddGnuDebugLink;
+ std::vector<StringRef> ToRemove;
+ std::vector<StringRef> Keep;
+ std::vector<StringRef> OnlyKeep;
+ std::vector<StringRef> AddSection;
+ std::vector<StringRef> SymbolsToLocalize;
+ std::vector<StringRef> SymbolsToGlobalize;
+ std::vector<StringRef> SymbolsToWeaken;
+ std::vector<StringRef> SymbolsToRemove;
+ std::vector<StringRef> SymbolsToKeep;
+ StringMap<StringRef> SectionsToRename;
+ StringMap<StringRef> SymbolsToRename;
+ bool StripAll = false;
+ bool StripAllGNU = false;
+ bool StripDebug = false;
+ bool StripSections = false;
+ bool StripNonAlloc = false;
+ bool StripDWO = false;
+ bool StripUnneeded = false;
+ bool ExtractDWO = false;
+ bool LocalizeHidden = false;
+ bool Weaken = false;
+ bool DiscardAll = false;
+ bool OnlyKeepDebug = false;
+ bool KeepFileSymbols = false;
+};
+
+using SectionPred = std::function<bool(const SectionBase &Sec)>;
+
+} // namespace
namespace llvm {
+namespace objcopy {
+
+// The name this program was invoked as.
+StringRef ToolName;
LLVM_ATTRIBUTE_NORETURN void error(Twine Message) {
errs() << ToolName << ": " << Message << ".\n";
@@ -69,95 +182,60 @@ LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, Error E) {
exit(1);
}
+} // end namespace objcopy
} // end namespace llvm
-static cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
-static cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
- cl::init("-"));
-static cl::opt<std::string>
- OutputFormat("O", cl::desc("Set output format to one of the following:"
- "\n\tbinary"));
-static cl::list<std::string> ToRemove("remove-section",
- cl::desc("Remove <section>"),
- cl::value_desc("section"));
-static cl::alias ToRemoveA("R", cl::desc("Alias for remove-section"),
- cl::aliasopt(ToRemove));
-static cl::opt<bool> StripAll(
- "strip-all",
- cl::desc(
- "Removes non-allocated sections other than .gnu.warning* sections"));
-static cl::opt<bool>
- StripAllGNU("strip-all-gnu",
- cl::desc("Removes symbol, relocation, and debug information"));
-static cl::list<std::string> Keep("keep", cl::desc("Keep <section>"),
- cl::value_desc("section"));
-static cl::list<std::string> OnlyKeep("only-keep",
- cl::desc("Remove all but <section>"),
- cl::value_desc("section"));
-static cl::alias OnlyKeepA("j", cl::desc("Alias for only-keep"),
- cl::aliasopt(OnlyKeep));
-static cl::opt<bool> StripDebug("strip-debug",
- cl::desc("Removes all debug information"));
-static cl::opt<bool> StripSections("strip-sections",
- cl::desc("Remove all section headers"));
-static cl::opt<bool>
- StripNonAlloc("strip-non-alloc",
- cl::desc("Remove all non-allocated sections"));
-static cl::opt<bool>
- StripDWO("strip-dwo", cl::desc("Remove all DWARF .dwo sections from file"));
-static cl::opt<bool> ExtractDWO(
- "extract-dwo",
- cl::desc("Remove all sections that are not DWARF .dwo sections from file"));
-static cl::opt<std::string>
- SplitDWO("split-dwo",
- cl::desc("Equivalent to extract-dwo on the input file to "
- "<dwo-file>, then strip-dwo on the input file"),
- cl::value_desc("dwo-file"));
-static cl::list<std::string> AddSection(
- "add-section",
- cl::desc("Make a section named <section> with the contents of <file>."),
- cl::value_desc("section=file"));
-
-using SectionPred = std::function<bool(const SectionBase &Sec)>;
+static bool IsDebugSection(const SectionBase &Sec) {
+ return Sec.Name.startswith(".debug") || Sec.Name.startswith(".zdebug") ||
+ Sec.Name == ".gdb_index";
+}
-bool IsDWOSection(const SectionBase &Sec) { return Sec.Name.endswith(".dwo"); }
+static bool IsDWOSection(const SectionBase &Sec) {
+ return Sec.Name.endswith(".dwo");
+}
-template <class ELFT>
-bool OnlyKeepDWOPred(const Object<ELFT> &Obj, const SectionBase &Sec) {
+static bool OnlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
// We can't remove the section header string table.
- if (&Sec == Obj.getSectionHeaderStrTab())
+ if (&Sec == Obj.SectionNames)
return false;
// Short of keeping the string table we want to keep everything that is a DWO
// section and remove everything else.
return !IsDWOSection(Sec);
}
-template <class ELFT>
-void WriteObjectFile(const Object<ELFT> &Obj, StringRef File) {
- std::unique_ptr<FileOutputBuffer> Buffer;
- Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(File, Obj.totalSize(),
- FileOutputBuffer::F_executable);
- handleAllErrors(BufferOrErr.takeError(), [](const ErrorInfoBase &) {
- error("failed to open " + OutputFilename);
- });
- Buffer = std::move(*BufferOrErr);
-
- Obj.write(*Buffer);
- if (auto E = Buffer->commit())
- reportError(File, errorToErrorCode(std::move(E)));
+static std::unique_ptr<Writer> CreateWriter(const CopyConfig &Config,
+ Object &Obj, Buffer &Buf,
+ ElfType OutputElfType) {
+ if (Config.OutputFormat == "binary") {
+ return llvm::make_unique<BinaryWriter>(Obj, Buf);
+ }
+ // Depending on the initial ELFT and OutputFormat we need a different Writer.
+ switch (OutputElfType) {
+ case ELFT_ELF32LE:
+ return llvm::make_unique<ELFWriter<ELF32LE>>(Obj, Buf,
+ !Config.StripSections);
+ case ELFT_ELF64LE:
+ return llvm::make_unique<ELFWriter<ELF64LE>>(Obj, Buf,
+ !Config.StripSections);
+ case ELFT_ELF32BE:
+ return llvm::make_unique<ELFWriter<ELF32BE>>(Obj, Buf,
+ !Config.StripSections);
+ case ELFT_ELF64BE:
+ return llvm::make_unique<ELFWriter<ELF64BE>>(Obj, Buf,
+ !Config.StripSections);
+ }
+ llvm_unreachable("Invalid output format");
}
-template <class ELFT>
-void SplitDWOToFile(const ELFObjectFile<ELFT> &ObjFile, StringRef File) {
- // Construct a second output file for the DWO sections.
- ELFObject<ELFT> DWOFile(ObjFile);
-
- DWOFile.removeSections([&](const SectionBase &Sec) {
- return OnlyKeepDWOPred<ELFT>(DWOFile, Sec);
- });
- DWOFile.finalize();
- WriteObjectFile(DWOFile, File);
+static void SplitDWOToFile(const CopyConfig &Config, const Reader &Reader,
+ StringRef File, ElfType OutputElfType) {
+ auto DWOFile = Reader.create();
+ DWOFile->removeSections(
+ [&](const SectionBase &Sec) { return OnlyKeepDWOPred(*DWOFile, Sec); });
+ FileBuffer FB(File);
+ auto Writer = CreateWriter(Config, *DWOFile, FB, OutputElfType);
+ Writer->finalize();
+ Writer->write();
}
// This function handles the high level operations of GNU objcopy including
@@ -167,47 +245,103 @@ void SplitDWOToFile(const ELFObjectFile<ELFT> &ObjFile, StringRef File) {
// any previous removals. Lastly whether or not something is removed shouldn't
// depend a) on the order the options occur in or b) on some opaque priority
// system. The only priority is that keeps/copies overrule removes.
-template <class ELFT> void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
- std::unique_ptr<Object<ELFT>> Obj;
+static void HandleArgs(const CopyConfig &Config, Object &Obj,
+ const Reader &Reader, ElfType OutputElfType) {
- if (!OutputFormat.empty() && OutputFormat != "binary")
- error("invalid output format '" + OutputFormat + "'");
- if (!OutputFormat.empty() && OutputFormat == "binary")
- Obj = llvm::make_unique<BinaryObject<ELFT>>(ObjFile);
- else
- Obj = llvm::make_unique<ELFObject<ELFT>>(ObjFile);
+ if (!Config.SplitDWO.empty()) {
+ SplitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType);
+ }
+
+ // TODO: update or remove symbols only if there is an option that affects
+ // them.
+ if (Obj.SymbolTable) {
+ Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
+ if ((Config.LocalizeHidden &&
+ (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
+ (!Config.SymbolsToLocalize.empty() &&
+ is_contained(Config.SymbolsToLocalize, Sym.Name)))
+ Sym.Binding = STB_LOCAL;
+
+ if (!Config.SymbolsToGlobalize.empty() &&
+ is_contained(Config.SymbolsToGlobalize, Sym.Name))
+ Sym.Binding = STB_GLOBAL;
+
+ if (!Config.SymbolsToWeaken.empty() &&
+ is_contained(Config.SymbolsToWeaken, Sym.Name) &&
+ Sym.Binding == STB_GLOBAL)
+ Sym.Binding = STB_WEAK;
+
+ if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
+ Sym.getShndx() != SHN_UNDEF)
+ Sym.Binding = STB_WEAK;
+
+ const auto I = Config.SymbolsToRename.find(Sym.Name);
+ if (I != Config.SymbolsToRename.end())
+ Sym.Name = I->getValue();
+ });
+
+ // The purpose of this loop is to mark symbols referenced by sections
+ // (like GroupSection or RelocationSection). This way, we know which
+ // symbols are still 'needed' and wich are not.
+ if (Config.StripUnneeded) {
+ for (auto &Section : Obj.sections())
+ Section.markSymbols();
+ }
+
+ Obj.removeSymbols([&](const Symbol &Sym) {
+ if ((!Config.SymbolsToKeep.empty() &&
+ is_contained(Config.SymbolsToKeep, Sym.Name)) ||
+ (Config.KeepFileSymbols && Sym.Type == STT_FILE))
+ return false;
+
+ if (Config.DiscardAll && Sym.Binding == STB_LOCAL &&
+ Sym.getShndx() != SHN_UNDEF && Sym.Type != STT_FILE &&
+ Sym.Type != STT_SECTION)
+ return true;
- if (!SplitDWO.empty())
- SplitDWOToFile<ELFT>(ObjFile, SplitDWO.getValue());
+ if (Config.StripAll || Config.StripAllGNU)
+ return true;
+
+ if (!Config.SymbolsToRemove.empty() &&
+ is_contained(Config.SymbolsToRemove, Sym.Name)) {
+ return true;
+ }
+
+ if (Config.StripUnneeded && !Sym.Referenced &&
+ (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
+ Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
+ return true;
+
+ return false;
+ });
+ }
SectionPred RemovePred = [](const SectionBase &) { return false; };
// Removes:
-
- if (!ToRemove.empty()) {
- RemovePred = [&](const SectionBase &Sec) {
- return std::find(std::begin(ToRemove), std::end(ToRemove), Sec.Name) !=
- std::end(ToRemove);
+ if (!Config.ToRemove.empty()) {
+ RemovePred = [&Config](const SectionBase &Sec) {
+ return find(Config.ToRemove, Sec.Name) != Config.ToRemove.end();
};
}
- if (StripDWO || !SplitDWO.empty())
+ if (Config.StripDWO || !Config.SplitDWO.empty())
RemovePred = [RemovePred](const SectionBase &Sec) {
return IsDWOSection(Sec) || RemovePred(Sec);
};
- if (ExtractDWO)
+ if (Config.ExtractDWO)
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
- return OnlyKeepDWOPred(*Obj, Sec) || RemovePred(Sec);
+ return OnlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
};
- if (StripAllGNU)
+ if (Config.StripAllGNU)
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
if (RemovePred(Sec))
return true;
if ((Sec.Flags & SHF_ALLOC) != 0)
return false;
- if (&Sec == Obj->getSectionHeaderStrTab())
+ if (&Sec == Obj.SectionNames)
return false;
switch (Sec.Type) {
case SHT_SYMTAB:
@@ -216,36 +350,35 @@ template <class ELFT> void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
case SHT_STRTAB:
return true;
}
- return Sec.Name.startswith(".debug");
+ return IsDebugSection(Sec);
};
- if (StripSections) {
+ if (Config.StripSections) {
RemovePred = [RemovePred](const SectionBase &Sec) {
return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0;
};
- Obj->WriteSectionHeaders = false;
}
- if (StripDebug) {
+ if (Config.StripDebug) {
RemovePred = [RemovePred](const SectionBase &Sec) {
- return RemovePred(Sec) || Sec.Name.startswith(".debug");
+ return RemovePred(Sec) || IsDebugSection(Sec);
};
}
- if (StripNonAlloc)
+ if (Config.StripNonAlloc)
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
if (RemovePred(Sec))
return true;
- if (&Sec == Obj->getSectionHeaderStrTab())
+ if (&Sec == Obj.SectionNames)
return false;
return (Sec.Flags & SHF_ALLOC) == 0;
};
- if (StripAll)
+ if (Config.StripAll)
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
if (RemovePred(Sec))
return true;
- if (&Sec == Obj->getSectionHeaderStrTab())
+ if (&Sec == Obj.SectionNames)
return false;
if (Sec.Name.startswith(".gnu.warning"))
return false;
@@ -253,47 +386,65 @@ template <class ELFT> void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
};
// Explicit copies:
-
- if (!OnlyKeep.empty()) {
- RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
+ if (!Config.OnlyKeep.empty()) {
+ RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
// Explicitly keep these sections regardless of previous removes.
- if (std::find(std::begin(OnlyKeep), std::end(OnlyKeep), Sec.Name) !=
- std::end(OnlyKeep))
+ if (find(Config.OnlyKeep, Sec.Name) != Config.OnlyKeep.end())
return false;
// Allow all implicit removes.
- if (RemovePred(Sec)) {
+ if (RemovePred(Sec))
return true;
- }
// Keep special sections.
- if (Obj->getSectionHeaderStrTab() == &Sec) {
+ if (Obj.SectionNames == &Sec)
return false;
- }
- if (Obj->getSymTab() == &Sec || Obj->getSymTab()->getStrTab() == &Sec) {
+ if (Obj.SymbolTable == &Sec ||
+ (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
return false;
- }
+
// Remove everything else.
return true;
};
}
- if (!Keep.empty()) {
- RemovePred = [RemovePred](const SectionBase &Sec) {
+ if (!Config.Keep.empty()) {
+ RemovePred = [Config, RemovePred](const SectionBase &Sec) {
// Explicitly keep these sections regardless of previous removes.
- if (std::find(std::begin(Keep), std::end(Keep), Sec.Name) !=
- std::end(Keep))
+ if (find(Config.Keep, Sec.Name) != Config.Keep.end())
return false;
// Otherwise defer to RemovePred.
return RemovePred(Sec);
};
}
- Obj->removeSections(RemovePred);
+ // This has to be the last predicate assignment.
+ // If the option --keep-symbol has been specified
+ // and at least one of those symbols is present
+ // (equivalently, the updated symbol table is not empty)
+ // the symbol table and the string table should not be removed.
+ if ((!Config.SymbolsToKeep.empty() || Config.KeepFileSymbols) &&
+ Obj.SymbolTable && !Obj.SymbolTable->empty()) {
+ RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
+ if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
+ return false;
+ return RemovePred(Sec);
+ };
+ }
- if (!AddSection.empty()) {
- for (const auto &Flag : AddSection) {
- auto SecPair = StringRef(Flag).split("=");
+ Obj.removeSections(RemovePred);
+
+ if (!Config.SectionsToRename.empty()) {
+ for (auto &Sec : Obj.sections()) {
+ const auto Iter = Config.SectionsToRename.find(Sec.Name);
+ if (Iter != Config.SectionsToRename.end())
+ Sec.Name = Iter->second;
+ }
+ }
+
+ if (!Config.AddSection.empty()) {
+ for (const auto &Flag : Config.AddSection) {
+ auto SecPair = Flag.split("=");
auto SecName = SecPair.first;
auto File = SecPair.second;
auto BufOrErr = MemoryBuffer::getFile(File);
@@ -302,44 +453,256 @@ template <class ELFT> void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
auto Buf = std::move(*BufOrErr);
auto BufPtr = reinterpret_cast<const uint8_t *>(Buf->getBufferStart());
auto BufSize = Buf->getBufferSize();
- Obj->addSection(SecName, ArrayRef<uint8_t>(BufPtr, BufSize));
+ Obj.addSection<OwnedDataSection>(SecName,
+ ArrayRef<uint8_t>(BufPtr, BufSize));
}
}
- Obj->finalize();
- WriteObjectFile(*Obj, OutputFilename.getValue());
+ if (!Config.AddGnuDebugLink.empty())
+ Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink);
}
-int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::ParseCommandLineOptions(argc, argv, "llvm objcopy utility\n");
- ToolName = argv[0];
- if (InputFilename.empty()) {
- cl::PrintHelpMessage();
- return 2;
+static void ExecuteElfObjcopyOnBinary(const CopyConfig &Config, Binary &Binary,
+ Buffer &Out) {
+ ELFReader Reader(&Binary);
+ std::unique_ptr<Object> Obj = Reader.create();
+
+ HandleArgs(Config, *Obj, Reader, Reader.getElfType());
+
+ std::unique_ptr<Writer> Writer =
+ CreateWriter(Config, *Obj, Out, Reader.getElfType());
+ Writer->finalize();
+ Writer->write();
+}
+
+// For regular archives this function simply calls llvm::writeArchive,
+// For thin archives it writes the archive file itself as well as its members.
+static Error deepWriteArchive(StringRef ArcName,
+ ArrayRef<NewArchiveMember> NewMembers,
+ bool WriteSymtab, object::Archive::Kind Kind,
+ bool Deterministic, bool Thin) {
+ Error E =
+ writeArchive(ArcName, NewMembers, WriteSymtab, Kind, Deterministic, Thin);
+ if (!Thin || E)
+ return E;
+ for (const NewArchiveMember &Member : NewMembers) {
+ // Internally, FileBuffer will use the buffer created by
+ // FileOutputBuffer::create, for regular files (that is the case for
+ // deepWriteArchive) FileOutputBuffer::create will return OnDiskBuffer.
+ // OnDiskBuffer uses a temporary file and then renames it. So in reality
+ // there is no inefficiency / duplicated in-memory buffers in this case. For
+ // now in-memory buffers can not be completely avoided since
+ // NewArchiveMember still requires them even though writeArchive does not
+ // write them on disk.
+ FileBuffer FB(Member.MemberName);
+ FB.allocate(Member.Buf->getBufferSize());
+ std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
+ FB.getBufferStart());
+ if (auto E = FB.commit())
+ return E;
+ }
+ return Error::success();
+}
+
+static void ExecuteElfObjcopyOnArchive(const CopyConfig &Config, const Archive &Ar) {
+ std::vector<NewArchiveMember> NewArchiveMembers;
+ Error Err = Error::success();
+ for (const Archive::Child &Child : Ar.children(Err)) {
+ Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
+ if (!ChildOrErr)
+ reportError(Ar.getFileName(), ChildOrErr.takeError());
+ Expected<StringRef> ChildNameOrErr = Child.getName();
+ if (!ChildNameOrErr)
+ reportError(Ar.getFileName(), ChildNameOrErr.takeError());
+
+ MemBuffer MB(ChildNameOrErr.get());
+ ExecuteElfObjcopyOnBinary(Config, **ChildOrErr, MB);
+
+ Expected<NewArchiveMember> Member =
+ NewArchiveMember::getOldMember(Child, true);
+ if (!Member)
+ reportError(Ar.getFileName(), Member.takeError());
+ Member->Buf = MB.releaseMemoryBuffer();
+ Member->MemberName = Member->Buf->getBufferIdentifier();
+ NewArchiveMembers.push_back(std::move(*Member));
}
- Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFilename);
+
+ if (Err)
+ reportError(Config.InputFilename, std::move(Err));
+ if (Error E =
+ deepWriteArchive(Config.OutputFilename, NewArchiveMembers,
+ Ar.hasSymbolTable(), Ar.kind(), true, Ar.isThin()))
+ reportError(Config.OutputFilename, std::move(E));
+}
+
+static void ExecuteElfObjcopy(const CopyConfig &Config) {
+ Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
+ createBinary(Config.InputFilename);
if (!BinaryOrErr)
- reportError(InputFilename, BinaryOrErr.takeError());
- Binary &Binary = *BinaryOrErr.get().getBinary();
- if (auto *o = dyn_cast<ELFObjectFile<ELF64LE>>(&Binary)) {
- CopyBinary(*o);
- return 0;
+ reportError(Config.InputFilename, BinaryOrErr.takeError());
+
+ if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary()))
+ return ExecuteElfObjcopyOnArchive(Config, *Ar);
+
+ FileBuffer FB(Config.OutputFilename);
+ ExecuteElfObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB);
+}
+
+// ParseObjcopyOptions returns the config and sets the input arguments. If a
+// help flag is set then ParseObjcopyOptions will print the help messege and
+// exit.
+static CopyConfig ParseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
+ ObjcopyOptTable T;
+ unsigned MissingArgumentIndex, MissingArgumentCount;
+ llvm::opt::InputArgList InputArgs =
+ T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
+
+ if (InputArgs.size() == 0) {
+ T.PrintHelp(errs(), "llvm-objcopy <input> [ <output> ]", "objcopy tool");
+ exit(1);
+ }
+
+ if (InputArgs.hasArg(OBJCOPY_help)) {
+ T.PrintHelp(outs(), "llvm-objcopy <input> [ <output> ]", "objcopy tool");
+ exit(0);
+ }
+
+ SmallVector<const char *, 2> Positional;
+
+ for (auto Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
+ error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
+
+ for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
+ Positional.push_back(Arg->getValue());
+
+ if (Positional.empty())
+ error("No input file specified");
+
+ if (Positional.size() > 2)
+ error("Too many positional arguments");
+
+ CopyConfig Config;
+ Config.InputFilename = Positional[0];
+ Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
+ Config.InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
+ Config.OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
+ Config.BinaryArch = InputArgs.getLastArgValue(OBJCOPY_binary_architecture);
+
+ Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
+ Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
+
+ for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
+ if (!StringRef(Arg->getValue()).contains('='))
+ error("Bad format for --redefine-sym");
+ auto Old2New = StringRef(Arg->getValue()).split('=');
+ if (!Config.SymbolsToRename.insert(Old2New).second)
+ error("Multiple redefinition of symbol " + Old2New.first);
}
- if (auto *o = dyn_cast<ELFObjectFile<ELF32LE>>(&Binary)) {
- CopyBinary(*o);
- return 0;
+
+ for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
+ if (!StringRef(Arg->getValue()).contains('='))
+ error("Bad format for --rename-section");
+ auto Old2New = StringRef(Arg->getValue()).split('=');
+ if (!Config.SectionsToRename.insert(Old2New).second)
+ error("Already have a section rename for " + Old2New.first);
}
- if (auto *o = dyn_cast<ELFObjectFile<ELF64BE>>(&Binary)) {
- CopyBinary(*o);
- return 0;
+
+ for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
+ Config.ToRemove.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_keep))
+ Config.Keep.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_only_keep))
+ Config.OnlyKeep.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_add_section))
+ Config.AddSection.push_back(Arg->getValue());
+ Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
+ Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
+ Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
+ Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
+ Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
+ Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
+ Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
+ Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
+ Config.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
+ Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
+ Config.DiscardAll = InputArgs.hasArg(OBJCOPY_discard_all);
+ Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
+ Config.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
+ for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
+ Config.SymbolsToLocalize.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
+ Config.SymbolsToGlobalize.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
+ Config.SymbolsToWeaken.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
+ Config.SymbolsToRemove.push_back(Arg->getValue());
+ for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
+ Config.SymbolsToKeep.push_back(Arg->getValue());
+
+ return Config;
+}
+
+// ParseStripOptions returns the config and sets the input arguments. If a
+// help flag is set then ParseStripOptions will print the help messege and
+// exit.
+static CopyConfig ParseStripOptions(ArrayRef<const char *> ArgsArr) {
+ StripOptTable T;
+ unsigned MissingArgumentIndex, MissingArgumentCount;
+ llvm::opt::InputArgList InputArgs =
+ T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
+
+ if (InputArgs.size() == 0) {
+ T.PrintHelp(errs(), "llvm-strip <input> [ <output> ]", "strip tool");
+ exit(1);
}
- if (auto *o = dyn_cast<ELFObjectFile<ELF32BE>>(&Binary)) {
- CopyBinary(*o);
- return 0;
+
+ if (InputArgs.hasArg(STRIP_help)) {
+ T.PrintHelp(outs(), "llvm-strip <input> [ <output> ]", "strip tool");
+ exit(0);
}
- reportError(InputFilename, object_error::invalid_file_type);
+
+ SmallVector<const char *, 2> Positional;
+ for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
+ error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
+ for (auto Arg : InputArgs.filtered(STRIP_INPUT))
+ Positional.push_back(Arg->getValue());
+
+ if (Positional.empty())
+ error("No input file specified");
+
+ if (Positional.size() > 2)
+ error("Support for multiple input files is not implemented yet");
+
+ CopyConfig Config;
+ Config.InputFilename = Positional[0];
+ Config.OutputFilename =
+ InputArgs.getLastArgValue(STRIP_output, Positional[0]);
+
+ Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
+
+ Config.DiscardAll = InputArgs.hasArg(STRIP_discard_all);
+ Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
+ Config.StripAll = InputArgs.hasArg(STRIP_strip_all);
+
+ if (!Config.StripDebug && !Config.StripUnneeded && !Config.DiscardAll)
+ Config.StripAll = true;
+
+ for (auto Arg : InputArgs.filtered(STRIP_remove_section))
+ Config.ToRemove.push_back(Arg->getValue());
+
+ for (auto Arg : InputArgs.filtered(STRIP_keep_symbol))
+ Config.SymbolsToKeep.push_back(Arg->getValue());
+
+ return Config;
+}
+
+int main(int argc, char **argv) {
+ InitLLVM X(argc, argv);
+ ToolName = argv[0];
+ CopyConfig Config;
+ if (sys::path::stem(ToolName).endswith_lower("strip"))
+ Config = ParseStripOptions(makeArrayRef(argv + 1, argc));
+ else
+ Config = ParseObjcopyOptions(makeArrayRef(argv + 1, argc));
+ ExecuteElfObjcopy(Config);
}
diff --git a/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.h b/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.h
index 6732e410d8e0..e222b65dc78f 100644
--- a/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.h
+++ b/contrib/llvm/tools/llvm-objcopy/llvm-objcopy.h
@@ -17,8 +17,12 @@
#include <string>
namespace llvm {
+namespace objcopy {
LLVM_ATTRIBUTE_NORETURN extern void error(Twine Message);
+LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, Error E);
+LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File,
+ std::error_code EC);
// This is taken from llvm-readobj.
// [see here](llvm/tools/llvm-readobj/llvm-readobj.h:38)
@@ -32,6 +36,7 @@ template <class T> T unwrapOrError(Expected<T> EO) {
error(Buf);
}
+} // end namespace objcopy
} // end namespace llvm
#endif // LLVM_TOOLS_OBJCOPY_OBJCOPY_H
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
index 780d1e9e6111..7ca5d04593ff 100644
--- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the COFF-specific dumper for llvm-objdump.
+/// This file implements the COFF-specific dumper for llvm-objdump.
/// It outputs the Win64 EH data structures as plain text.
/// The encoding of the unwind codes is described in MSDN:
/// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
@@ -453,7 +453,7 @@ static bool getPDataSection(const COFFObjectFile *Obj,
Rels.push_back(Reloc);
// Sort relocations by address.
- std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
+ llvm::sort(Rels.begin(), Rels.end(), RelocAddressLess);
ArrayRef<uint8_t> Contents;
error(Obj->getSectionContents(Pdata, Contents));
diff --git a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp
index 7f5fe5a9d3b8..f4d36656a6c4 100644
--- a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the ELF-specific dumper for llvm-objdump.
+/// This file implements the ELF-specific dumper for llvm-objdump.
///
//===----------------------------------------------------------------------===//
@@ -21,6 +21,77 @@
using namespace llvm;
using namespace llvm::object;
+template <class ELFT>
+Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) {
+ typedef ELFFile<ELFT> ELFO;
+
+ auto DynamicEntriesOrError = Elf->dynamicEntries();
+ if (!DynamicEntriesOrError)
+ return DynamicEntriesOrError.takeError();
+
+ for (const typename ELFO::Elf_Dyn &Dyn : *DynamicEntriesOrError) {
+ if (Dyn.d_tag == ELF::DT_STRTAB) {
+ auto MappedAddrOrError = Elf->toMappedAddr(Dyn.getPtr());
+ if (!MappedAddrOrError)
+ consumeError(MappedAddrOrError.takeError());
+ return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError));
+ }
+ }
+
+ // If the dynamic segment is not present, we fall back on the sections.
+ auto SectionsOrError = Elf->sections();
+ if (!SectionsOrError)
+ return SectionsOrError.takeError();
+
+ for (const typename ELFO::Elf_Shdr &Sec : *SectionsOrError) {
+ if (Sec.sh_type == ELF::SHT_DYNSYM)
+ return Elf->getStringTableForSymtab(Sec);
+ }
+
+ return createError("dynamic string table not found");
+}
+
+template <class ELFT>
+void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) {
+ auto ProgramHeaderOrError = Elf->program_headers();
+ if (!ProgramHeaderOrError)
+ report_error(Filename, ProgramHeaderOrError.takeError());
+
+ auto DynamicEntriesOrError = Elf->dynamicEntries();
+ if (!DynamicEntriesOrError)
+ report_error(Filename, DynamicEntriesOrError.takeError());
+
+ outs() << "Dynamic Section:\n";
+ for (const auto &Dyn : *DynamicEntriesOrError) {
+ if (Dyn.d_tag == ELF::DT_NULL)
+ continue;
+
+ StringRef Str = StringRef(Elf->getDynamicTagAsString(Dyn.d_tag));
+
+ if (Str.empty()) {
+ std::string HexStr = utohexstr(static_cast<uint64_t>(Dyn.d_tag), true);
+ outs() << format(" 0x%-19s", HexStr.c_str());
+ } else {
+ // We use "-21" in order to match GNU objdump's output.
+ outs() << format(" %-21s", Str.data());
+ }
+
+ const char *Fmt =
+ ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n";
+ if (Dyn.d_tag == ELF::DT_NEEDED) {
+ Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf);
+ if (StrTabOrErr) {
+ const char *Data = StrTabOrErr.get().data();
+ outs() << (Data + Dyn.d_un.d_val) << "\n";
+ continue;
+ }
+ warn(errorToErrorCode(StrTabOrErr.takeError()).message());
+ consumeError(StrTabOrErr.takeError());
+ }
+ outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val);
+ }
+}
+
template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
typedef ELFFile<ELFT> ELFO;
outs() << "Program Header:\n";
@@ -103,3 +174,21 @@ void llvm::printELFFileHeader(const object::ObjectFile *Obj) {
if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
printProgramHeaders(ELFObj->getELFFile());
}
+
+void llvm::printELFDynamicSection(const object::ObjectFile *Obj) {
+ // Little-endian 32-bit
+ if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
+ printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
+
+ // Big-endian 32-bit
+ if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
+ printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
+
+ // Little-endian 64-bit
+ if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
+ printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
+
+ // Big-endian 64-bit
+ if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
+ printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
+}
diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
index 9908c2f2d016..bdf80c73b999 100644
--- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
@@ -76,11 +76,6 @@ cl::opt<bool> llvm::UniversalHeaders("universal-headers",
"(requires -macho)"));
cl::opt<bool>
- llvm::ArchiveHeaders("archive-headers",
- cl::desc("Print archive headers for Mach-O archives "
- "(requires -macho)"));
-
-cl::opt<bool>
ArchiveMemberOffsets("archive-member-offsets",
cl::desc("Print the offset to each archive member for "
"Mach-O archives (requires -macho and "
@@ -1284,14 +1279,35 @@ static void DumpLiteralPointerSection(MachOObjectFile *O,
}
}
-static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
+static void DumpInitTermPointerSection(MachOObjectFile *O,
+ const SectionRef &Section,
+ const char *sect,
uint32_t sect_size, uint64_t sect_addr,
SymbolAddressMap *AddrMap,
bool verbose) {
uint32_t stride;
stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
+
+ // Collect the external relocation symbols for the pointers.
+ std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ DataRefImpl Rel;
+ MachO::any_relocation_info RE;
+ bool isExtern = false;
+ Rel = Reloc.getRawDataRefImpl();
+ RE = O->getRelocation(Rel);
+ isExtern = O->getPlainRelocationExternal(RE);
+ if (isExtern) {
+ uint64_t RelocOffset = Reloc.getOffset();
+ symbol_iterator RelocSym = Reloc.getSymbol();
+ Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
+ }
+ }
+ array_pod_sort(Relocs.begin(), Relocs.end());
+
for (uint32_t i = 0; i < sect_size; i += stride) {
const char *SymbolName = nullptr;
+ uint64_t p;
if (O->is64Bit()) {
outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
uint64_t pointer_value;
@@ -1299,8 +1315,7 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
if (O->isLittleEndian() != sys::IsLittleEndianHost)
sys::swapByteOrder(pointer_value);
outs() << format("0x%016" PRIx64, pointer_value);
- if (verbose)
- SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ p = pointer_value;
} else {
outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
uint32_t pointer_value;
@@ -1308,11 +1323,25 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
if (O->isLittleEndian() != sys::IsLittleEndianHost)
sys::swapByteOrder(pointer_value);
outs() << format("0x%08" PRIx32, pointer_value);
- if (verbose)
- SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ p = pointer_value;
+ }
+ if (verbose) {
+ // First look for an external relocation entry for this pointer.
+ auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
+ return P.first == i;
+ });
+ if (Reloc != Relocs.end()) {
+ symbol_iterator RelocSym = Reloc->second;
+ Expected<StringRef> SymName = RelocSym->getName();
+ if (!SymName)
+ report_error(O->getFileName(), SymName.takeError());
+ outs() << " " << *SymName;
+ } else {
+ SymbolName = GuessSymbolName(p, AddrMap);
+ if (SymbolName)
+ outs() << " " << SymbolName;
+ }
}
- if (SymbolName)
- outs() << " " << SymbolName;
outs() << "\n";
}
}
@@ -1463,8 +1492,8 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
break;
case MachO::S_MOD_INIT_FUNC_POINTERS:
case MachO::S_MOD_TERM_FUNC_POINTERS:
- DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
- verbose);
+ DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
+ &AddrMap, verbose);
break;
default:
outs() << "Unknown section type ("
@@ -2149,19 +2178,22 @@ void llvm::ParseInputMachO(StringRef Filename) {
// The block of info used by the Symbolizer call backs.
struct DisassembleInfo {
+ DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
+ std::vector<SectionRef> *Sections, bool verbose)
+ : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
bool verbose;
MachOObjectFile *O;
SectionRef S;
SymbolAddressMap *AddrMap;
std::vector<SectionRef> *Sections;
- const char *class_name;
- const char *selector_name;
- char *method;
- char *demangled_name;
- uint64_t adrp_addr;
- uint32_t adrp_inst;
+ const char *class_name = nullptr;
+ const char *selector_name = nullptr;
+ std::unique_ptr<char[]> method = nullptr;
+ char *demangled_name = nullptr;
+ uint64_t adrp_addr = 0;
+ uint32_t adrp_inst = 0;
std::unique_ptr<SymbolAddressMap> bindtable;
- uint32_t depth;
+ uint32_t depth = 0;
};
// SymbolizerGetOpInfo() is the operand information call back function.
@@ -2756,32 +2788,33 @@ static void method_reference(struct DisassembleInfo *info,
if (*ReferenceName != nullptr) {
if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
if (info->selector_name != nullptr) {
- if (info->method != nullptr)
- free(info->method);
if (info->class_name != nullptr) {
- info->method = (char *)malloc(5 + strlen(info->class_name) +
- strlen(info->selector_name));
- if (info->method != nullptr) {
- strcpy(info->method, "+[");
- strcat(info->method, info->class_name);
- strcat(info->method, " ");
- strcat(info->method, info->selector_name);
- strcat(info->method, "]");
- *ReferenceName = info->method;
+ info->method = llvm::make_unique<char[]>(
+ 5 + strlen(info->class_name) + strlen(info->selector_name));
+ char *method = info->method.get();
+ if (method != nullptr) {
+ strcpy(method, "+[");
+ strcat(method, info->class_name);
+ strcat(method, " ");
+ strcat(method, info->selector_name);
+ strcat(method, "]");
+ *ReferenceName = method;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
}
} else {
- info->method = (char *)malloc(9 + strlen(info->selector_name));
- if (info->method != nullptr) {
+ info->method =
+ llvm::make_unique<char[]>(9 + strlen(info->selector_name));
+ char *method = info->method.get();
+ if (method != nullptr) {
if (Arch == Triple::x86_64)
- strcpy(info->method, "-[%rdi ");
+ strcpy(method, "-[%rdi ");
else if (Arch == Triple::aarch64)
- strcpy(info->method, "-[x0 ");
+ strcpy(method, "-[x0 ");
else
- strcpy(info->method, "-[r? ");
- strcat(info->method, info->selector_name);
- strcat(info->method, "]");
- *ReferenceName = info->method;
+ strcpy(method, "-[r? ");
+ strcat(method, info->selector_name);
+ strcat(method, "]");
+ *ReferenceName = method;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
}
}
@@ -2789,19 +2822,19 @@ static void method_reference(struct DisassembleInfo *info,
}
} else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
if (info->selector_name != nullptr) {
- if (info->method != nullptr)
- free(info->method);
- info->method = (char *)malloc(17 + strlen(info->selector_name));
- if (info->method != nullptr) {
+ info->method =
+ llvm::make_unique<char[]>(17 + strlen(info->selector_name));
+ char *method = info->method.get();
+ if (method != nullptr) {
if (Arch == Triple::x86_64)
- strcpy(info->method, "-[[%rdi super] ");
+ strcpy(method, "-[[%rdi super] ");
else if (Arch == Triple::aarch64)
- strcpy(info->method, "-[[x0 super] ");
+ strcpy(method, "-[[x0 super] ");
else
- strcpy(info->method, "-[[r? super] ");
- strcat(info->method, info->selector_name);
- strcat(info->method, "]");
- *ReferenceName = info->method;
+ strcpy(method, "-[[r? super] ");
+ strcat(method, info->selector_name);
+ strcat(method, "]");
+ *ReferenceName = method;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
}
info->class_name = nullptr;
@@ -3196,6 +3229,8 @@ struct imageInfo_t {
/* masks for objc_image_info.flags */
#define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
#define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
+#define OBJC_IMAGE_IS_SIMULATED (1 << 5)
+#define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
struct message_ref64 {
uint64_t imp; /* IMP (64-bit pointer) */
@@ -5557,12 +5592,24 @@ static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
outs() << " OBJC_IMAGE_IS_REPLACEMENT";
if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
outs() << " OBJC_IMAGE_SUPPORTS_GC";
+ if (o.flags & OBJC_IMAGE_IS_SIMULATED)
+ outs() << " OBJC_IMAGE_IS_SIMULATED";
+ if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
+ outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
swift_version = (o.flags >> 8) & 0xff;
if (swift_version != 0) {
if (swift_version == 1)
outs() << " Swift 1.0";
else if (swift_version == 2)
outs() << " Swift 1.1";
+ else if(swift_version == 3)
+ outs() << " Swift 2.0";
+ else if(swift_version == 4)
+ outs() << " Swift 3.0";
+ else if(swift_version == 5)
+ outs() << " Swift 4.0";
+ else if(swift_version == 6)
+ outs() << " Swift 4.1";
else
outs() << " unknown future Swift version (" << swift_version << ")";
}
@@ -5606,6 +5653,14 @@ static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
outs() << " Swift 1.0";
else if (swift_version == 2)
outs() << " Swift 1.1";
+ else if(swift_version == 3)
+ outs() << " Swift 2.0";
+ else if(swift_version == 4)
+ outs() << " Swift 3.0";
+ else if(swift_version == 5)
+ outs() << " Swift 4.0";
+ else if(swift_version == 6)
+ outs() << " Swift 4.1";
else
outs() << " unknown future Swift version (" << swift_version << ")";
}
@@ -5659,21 +5714,8 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = verbose;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
-
- info.depth = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
+
SectionRef CL = get_section(O, "__OBJC2", "__class_list");
if (CL == SectionRef())
CL = get_section(O, "__DATA", "__objc_classlist");
@@ -5757,19 +5799,7 @@ static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = verbose;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
SectionRef CL = get_section(O, "__OBJC2", "__class_list");
if (CL == SectionRef())
@@ -5867,19 +5897,7 @@ static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = verbose;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
p = S.getAddress() + i;
@@ -6040,19 +6058,7 @@ static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = true;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, true);
const char *p;
struct objc_protocol_t protocol;
@@ -6748,7 +6754,7 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo,
return SymbolName;
}
-/// \brief Emits the comments that are stored in the CommentStream.
+/// Emits the comments that are stored in the CommentStream.
/// Each comment in the CommentStream must end with a newline.
static void emitComments(raw_svector_ostream &CommentStream,
SmallString<128> &CommentsToEmit,
@@ -6817,7 +6823,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
std::unique_ptr<MCDisassembler> DisAsm(
TheTarget->createMCDisassembler(*STI, Ctx));
std::unique_ptr<MCSymbolizer> Symbolizer;
- struct DisassembleInfo SymbolizerInfo;
+ struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
std::unique_ptr<MCRelocationInfo> RelInfo(
TheTarget->createMCRelocationInfo(TripleName, Ctx));
if (RelInfo) {
@@ -6855,7 +6861,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
std::unique_ptr<MCInstPrinter> ThumbIP;
std::unique_ptr<MCContext> ThumbCtx;
std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
- struct DisassembleInfo ThumbSymbolizerInfo;
+ struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
if (ThumbTarget) {
ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
@@ -6904,7 +6910,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
BaseSegmentAddress);
// Sort the symbols by address, just in case they didn't come in that way.
- std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
+ llvm::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
// Build a data in code table that is sorted on by the address of each entry.
uint64_t BaseAddress = 0;
@@ -6940,10 +6946,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
return;
}
- DbgObj =
- ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef())
- .get()
- .release();
+ Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck =
+ ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef());
+
+ if (DbgObjCheck.takeError())
+ report_error(MachOOF->getFileName(), DbgObjCheck.takeError());
+ DbgObj = DbgObjCheck.get().release();
}
// Setup the DIContext
@@ -7003,26 +7011,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SymbolizerInfo.S = Sections[SectIdx];
SymbolizerInfo.AddrMap = &AddrMap;
SymbolizerInfo.Sections = &Sections;
- SymbolizerInfo.class_name = nullptr;
- SymbolizerInfo.selector_name = nullptr;
- SymbolizerInfo.method = nullptr;
- SymbolizerInfo.demangled_name = nullptr;
- SymbolizerInfo.bindtable = nullptr;
- SymbolizerInfo.adrp_addr = 0;
- SymbolizerInfo.adrp_inst = 0;
// Same for the ThumbSymbolizer
ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
ThumbSymbolizerInfo.O = MachOOF;
ThumbSymbolizerInfo.S = Sections[SectIdx];
ThumbSymbolizerInfo.AddrMap = &AddrMap;
ThumbSymbolizerInfo.Sections = &Sections;
- ThumbSymbolizerInfo.class_name = nullptr;
- ThumbSymbolizerInfo.selector_name = nullptr;
- ThumbSymbolizerInfo.method = nullptr;
- ThumbSymbolizerInfo.demangled_name = nullptr;
- ThumbSymbolizerInfo.bindtable = nullptr;
- ThumbSymbolizerInfo.adrp_addr = 0;
- ThumbSymbolizerInfo.adrp_inst = 0;
unsigned int Arch = MachOOF->getArch();
@@ -7293,12 +7287,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
TripleName = "";
ThumbTripleName = "";
- if (SymbolizerInfo.method != nullptr)
- free(SymbolizerInfo.method);
if (SymbolizerInfo.demangled_name != nullptr)
free(SymbolizerInfo.demangled_name);
- if (ThumbSymbolizerInfo.method != nullptr)
- free(ThumbSymbolizerInfo.method);
if (ThumbSymbolizerInfo.demangled_name != nullptr)
free(ThumbSymbolizerInfo.demangled_name);
}
@@ -7310,12 +7300,25 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
namespace {
-template <typename T> static uint64_t readNext(const char *&Buf) {
+template <typename T>
+static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
using llvm::support::little;
using llvm::support::unaligned;
- uint64_t Val = support::endian::read<T, little, unaligned>(Buf);
- Buf += sizeof(T);
+ if (Offset + sizeof(T) > Contents.size()) {
+ outs() << "warning: attempt to read past end of buffer\n";
+ return T();
+ }
+
+ uint64_t Val =
+ support::endian::read<T, little, unaligned>(Contents.data() + Offset);
+ return Val;
+}
+
+template <typename T>
+static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
+ T Val = read<T>(Contents, Offset);
+ Offset += sizeof(T);
return Val;
}
@@ -7335,18 +7338,18 @@ struct CompactUnwindEntry {
CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
: OffsetInSection(Offset) {
if (Is64)
- read<uint64_t>(Contents.data() + Offset);
+ read<uint64_t>(Contents, Offset);
else
- read<uint32_t>(Contents.data() + Offset);
+ read<uint32_t>(Contents, Offset);
}
private:
- template <typename UIntPtr> void read(const char *Buf) {
- FunctionAddr = readNext<UIntPtr>(Buf);
- Length = readNext<uint32_t>(Buf);
- CompactEncoding = readNext<uint32_t>(Buf);
- PersonalityAddr = readNext<UIntPtr>(Buf);
- LSDAAddr = readNext<UIntPtr>(Buf);
+ template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
+ FunctionAddr = readNext<UIntPtr>(Contents, Offset);
+ Length = readNext<uint32_t>(Contents, Offset);
+ CompactEncoding = readNext<uint32_t>(Contents, Offset);
+ PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
+ LSDAAddr = readNext<UIntPtr>(Contents, Offset);
}
};
}
@@ -7448,7 +7451,7 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj,
// First populate the initial raw offsets, encodings and so on from the entry.
for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
- CompactUnwindEntry Entry(Contents.data(), Offset, Is64);
+ CompactUnwindEntry Entry(Contents, Offset, Is64);
CompactUnwinds.push_back(Entry);
}
@@ -7515,19 +7518,19 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj,
// __unwind_info section dumping
//===----------------------------------------------------------------------===//
-static void printRegularSecondLevelUnwindPage(const char *PageStart) {
- const char *Pos = PageStart;
- uint32_t Kind = readNext<uint32_t>(Pos);
+static void printRegularSecondLevelUnwindPage(StringRef PageData) {
+ ptrdiff_t Pos = 0;
+ uint32_t Kind = readNext<uint32_t>(PageData, Pos);
(void)Kind;
assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
- uint16_t EntriesStart = readNext<uint16_t>(Pos);
- uint16_t NumEntries = readNext<uint16_t>(Pos);
+ uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
+ uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
- Pos = PageStart + EntriesStart;
+ Pos = EntriesStart;
for (unsigned i = 0; i < NumEntries; ++i) {
- uint32_t FunctionOffset = readNext<uint32_t>(Pos);
- uint32_t Encoding = readNext<uint32_t>(Pos);
+ uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
+ uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
outs() << " [" << i << "]: "
<< "function offset=" << format("0x%08" PRIx32, FunctionOffset)
@@ -7537,24 +7540,23 @@ static void printRegularSecondLevelUnwindPage(const char *PageStart) {
}
static void printCompressedSecondLevelUnwindPage(
- const char *PageStart, uint32_t FunctionBase,
+ StringRef PageData, uint32_t FunctionBase,
const SmallVectorImpl<uint32_t> &CommonEncodings) {
- const char *Pos = PageStart;
- uint32_t Kind = readNext<uint32_t>(Pos);
+ ptrdiff_t Pos = 0;
+ uint32_t Kind = readNext<uint32_t>(PageData, Pos);
(void)Kind;
assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
- uint16_t EntriesStart = readNext<uint16_t>(Pos);
- uint16_t NumEntries = readNext<uint16_t>(Pos);
+ uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
+ uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
- uint16_t EncodingsStart = readNext<uint16_t>(Pos);
- readNext<uint16_t>(Pos);
- const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>(
- PageStart + EncodingsStart);
+ uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos);
+ readNext<uint16_t>(PageData, Pos);
+ StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos);
- Pos = PageStart + EntriesStart;
+ Pos = EntriesStart;
for (unsigned i = 0; i < NumEntries; ++i) {
- uint32_t Entry = readNext<uint32_t>(Pos);
+ uint32_t Entry = readNext<uint32_t>(PageData, Pos);
uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
uint32_t EncodingIdx = Entry >> 24;
@@ -7562,7 +7564,9 @@ static void printCompressedSecondLevelUnwindPage(
if (EncodingIdx < CommonEncodings.size())
Encoding = CommonEncodings[EncodingIdx];
else
- Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()];
+ Encoding = read<uint32_t>(PageEncodings,
+ sizeof(uint32_t) *
+ (EncodingIdx - CommonEncodings.size()));
outs() << " [" << i << "]: "
<< "function offset=" << format("0x%08" PRIx32, FunctionOffset)
@@ -7585,13 +7589,13 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
StringRef Contents;
UnwindInfo.getContents(Contents);
- const char *Pos = Contents.data();
+ ptrdiff_t Pos = 0;
//===----------------------------------
// Section header
//===----------------------------------
- uint32_t Version = readNext<uint32_t>(Pos);
+ uint32_t Version = readNext<uint32_t>(Contents, Pos);
outs() << " Version: "
<< format("0x%" PRIx32, Version) << '\n';
if (Version != 1) {
@@ -7599,24 +7603,24 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
return;
}
- uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos);
+ uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
outs() << " Common encodings array section offset: "
<< format("0x%" PRIx32, CommonEncodingsStart) << '\n';
- uint32_t NumCommonEncodings = readNext<uint32_t>(Pos);
+ uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
outs() << " Number of common encodings in array: "
<< format("0x%" PRIx32, NumCommonEncodings) << '\n';
- uint32_t PersonalitiesStart = readNext<uint32_t>(Pos);
+ uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
outs() << " Personality function array section offset: "
<< format("0x%" PRIx32, PersonalitiesStart) << '\n';
- uint32_t NumPersonalities = readNext<uint32_t>(Pos);
+ uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
outs() << " Number of personality functions in array: "
<< format("0x%" PRIx32, NumPersonalities) << '\n';
- uint32_t IndicesStart = readNext<uint32_t>(Pos);
+ uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
outs() << " Index array section offset: "
<< format("0x%" PRIx32, IndicesStart) << '\n';
- uint32_t NumIndices = readNext<uint32_t>(Pos);
+ uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
outs() << " Number of indices in array: "
<< format("0x%" PRIx32, NumIndices) << '\n';
@@ -7631,9 +7635,9 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
SmallVector<uint32_t, 64> CommonEncodings;
outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n";
- Pos = Contents.data() + CommonEncodingsStart;
+ Pos = CommonEncodingsStart;
for (unsigned i = 0; i < NumCommonEncodings; ++i) {
- uint32_t Encoding = readNext<uint32_t>(Pos);
+ uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
CommonEncodings.push_back(Encoding);
outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
@@ -7648,9 +7652,9 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
// roughly). Particularly since they only get 2 bits in the compact encoding.
outs() << " Personality functions: (count = " << NumPersonalities << ")\n";
- Pos = Contents.data() + PersonalitiesStart;
+ Pos = PersonalitiesStart;
for (unsigned i = 0; i < NumPersonalities; ++i) {
- uint32_t PersonalityFn = readNext<uint32_t>(Pos);
+ uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
outs() << " personality[" << i + 1
<< "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
}
@@ -7671,13 +7675,13 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
SmallVector<IndexEntry, 4> IndexEntries;
outs() << " Top level indices: (count = " << NumIndices << ")\n";
- Pos = Contents.data() + IndicesStart;
+ Pos = IndicesStart;
for (unsigned i = 0; i < NumIndices; ++i) {
IndexEntry Entry;
- Entry.FunctionOffset = readNext<uint32_t>(Pos);
- Entry.SecondLevelPageStart = readNext<uint32_t>(Pos);
- Entry.LSDAStart = readNext<uint32_t>(Pos);
+ Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
+ Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
+ Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
IndexEntries.push_back(Entry);
outs() << " [" << i << "]: "
@@ -7696,12 +7700,14 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
// the first top-level index's LSDAOffset to the last (sentinel).
outs() << " LSDA descriptors:\n";
- Pos = Contents.data() + IndexEntries[0].LSDAStart;
- int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) /
- (2 * sizeof(uint32_t));
+ Pos = IndexEntries[0].LSDAStart;
+ const uint32_t LSDASize = 2 * sizeof(uint32_t);
+ int NumLSDAs =
+ (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
+
for (int i = 0; i < NumLSDAs; ++i) {
- uint32_t FunctionOffset = readNext<uint32_t>(Pos);
- uint32_t LSDAOffset = readNext<uint32_t>(Pos);
+ uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
+ uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
outs() << " [" << i << "]: "
<< "function offset=" << format("0x%08" PRIx32, FunctionOffset)
<< ", "
@@ -7729,12 +7735,19 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
<< "base function offset="
<< format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
- Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart;
- uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos);
+ Pos = IndexEntries[i].SecondLevelPageStart;
+ if (Pos + sizeof(uint32_t) > Contents.size()) {
+ outs() << "warning: invalid offset for second level page: " << Pos << '\n';
+ continue;
+ }
+
+ uint32_t Kind =
+ *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
if (Kind == 2)
- printRegularSecondLevelUnwindPage(Pos);
+ printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
else if (Kind == 3)
- printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset,
+ printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
+ IndexEntries[i].FunctionOffset,
CommonEncodings);
else
outs() << " Skipping 2nd level page with unknown kind " << Kind
@@ -9352,6 +9365,26 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
outs() << "\t esh.flavor " << es.esh.flavor << " esh.count "
<< es.esh.count << "\n";
}
+ } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
+ outs() << " flavor x86_EXCEPTION_STATE64\n";
+ if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
+ outs() << " count x86_EXCEPTION_STATE64_COUNT\n";
+ else
+ outs() << " count " << count
+ << " (not x86_EXCEPTION_STATE64_COUNT)\n";
+ struct MachO::x86_exception_state64_t es64;
+ left = end - begin;
+ if (left >= sizeof(MachO::x86_exception_state64_t)) {
+ memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
+ begin += sizeof(MachO::x86_exception_state64_t);
+ } else {
+ memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
+ memcpy(&es64, begin, left);
+ begin += left;
+ }
+ if (isLittleEndian != sys::IsLittleEndianHost)
+ swapStruct(es64);
+ Print_x86_exception_state_t(es64);
} else {
outs() << " flavor " << flavor << " (unknown)\n";
outs() << " count " << count << "\n";
diff --git a/contrib/llvm/tools/llvm-objdump/WasmDump.cpp b/contrib/llvm/tools/llvm-objdump/WasmDump.cpp
index 0d8ffba6ba45..045002cd4b34 100644
--- a/contrib/llvm/tools/llvm-objdump/WasmDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/WasmDump.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the wasm-specific dumper for llvm-objdump.
+/// This file implements the wasm-specific dumper for llvm-objdump.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 3a9112423cff..8041e6f59940 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -20,10 +20,12 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/FaultMaps.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -50,10 +52,8 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -68,6 +68,12 @@
using namespace llvm;
using namespace object;
+cl::opt<bool>
+ llvm::AllHeaders("all-headers",
+ cl::desc("Display all available header information"));
+static cl::alias AllHeadersShort("x", cl::desc("Alias for --all-headers"),
+ cl::aliasopt(AllHeaders));
+
static cl::list<std::string>
InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
@@ -85,10 +91,30 @@ static cl::alias
DisassembleAlld("D", cl::desc("Alias for --disassemble-all"),
cl::aliasopt(DisassembleAll));
+cl::opt<std::string> llvm::Demangle("demangle",
+ cl::desc("Demangle symbols names"),
+ cl::ValueOptional, cl::init("none"));
+
+static cl::alias DemangleShort("C", cl::desc("Alias for --demangle"),
+ cl::aliasopt(Demangle));
+
+static cl::list<std::string>
+DisassembleFunctions("df",
+ cl::CommaSeparated,
+ cl::desc("List of functions to disassemble"));
+static StringSet<> DisasmFuncsSet;
+
cl::opt<bool>
llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
cl::opt<bool>
+llvm::DynamicRelocations("dynamic-reloc",
+ cl::desc("Display the dynamic relocation entries in the file"));
+static cl::alias
+DynamicRelocationsd("R", cl::desc("Alias for --dynamic-reloc"),
+ cl::aliasopt(DynamicRelocations));
+
+cl::opt<bool>
llvm::SectionContents("s", cl::desc("Display the content of each section"));
cl::opt<bool>
@@ -182,6 +208,21 @@ static cl::alias
PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
cl::aliasopt(PrivateHeaders));
+cl::opt<bool> llvm::FileHeaders(
+ "file-headers",
+ cl::desc("Display the contents of the overall file header"));
+
+static cl::alias FileHeadersShort("f", cl::desc("Alias for --file-headers"),
+ cl::aliasopt(FileHeaders));
+
+cl::opt<bool>
+ llvm::ArchiveHeaders("archive-headers",
+ cl::desc("Display archive header information"));
+
+cl::alias
+ArchiveHeadersShort("a", cl::desc("Alias for --archive-headers"),
+ cl::aliasopt(ArchiveHeaders));
+
cl::opt<bool>
llvm::PrintImmHex("print-imm-hex",
cl::desc("Use hex format for immediate values"));
@@ -196,7 +237,7 @@ cl::opt<DIDumpType> llvm::DwarfDumpType(
cl::opt<bool> PrintSource(
"source",
cl::desc(
- "Display source inlined with disassembly. Implies disassmble object"));
+ "Display source inlined with disassembly. Implies disassemble object"));
cl::alias PrintSourceShort("S", cl::desc("Alias for -source"),
cl::aliasopt(PrintSource));
@@ -297,6 +338,11 @@ LLVM_ATTRIBUTE_NORETURN void llvm::error(Twine Message) {
exit(1);
}
+void llvm::warn(StringRef Message) {
+ errs() << ToolName << ": warning: " << Message << ".\n";
+ errs().flush();
+}
+
LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,
Twine Message) {
errs() << ToolName << ": '" << File << "': " << Message << ".\n";
@@ -396,252 +442,6 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
return a.getOffset() < b.getOffset();
}
-namespace {
-class SourcePrinter {
-protected:
- DILineInfo OldLineInfo;
- const ObjectFile *Obj = nullptr;
- std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
- // File name to file contents of source
- std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
- // Mark the line endings of the cached source
- std::unordered_map<std::string, std::vector<StringRef>> LineCache;
-
-private:
- bool cacheSource(const std::string& File);
-
-public:
- SourcePrinter() = default;
- SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) {
- symbolize::LLVMSymbolizer::Options SymbolizerOpts(
- DILineInfoSpecifier::FunctionNameKind::None, true, false, false,
- DefaultArch);
- Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts));
- }
- virtual ~SourcePrinter() = default;
- virtual void printSourceLine(raw_ostream &OS, uint64_t Address,
- StringRef Delimiter = "; ");
-};
-
-bool SourcePrinter::cacheSource(const std::string& File) {
- auto BufferOrError = MemoryBuffer::getFile(File);
- if (!BufferOrError)
- return false;
- // Chomp the file to get lines
- size_t BufferSize = (*BufferOrError)->getBufferSize();
- const char *BufferStart = (*BufferOrError)->getBufferStart();
- for (const char *Start = BufferStart, *End = BufferStart;
- End < BufferStart + BufferSize; End++)
- if (*End == '\n' || End == BufferStart + BufferSize - 1 ||
- (*End == '\r' && *(End + 1) == '\n')) {
- LineCache[File].push_back(StringRef(Start, End - Start));
- if (*End == '\r')
- End++;
- Start = End + 1;
- }
- SourceCache[File] = std::move(*BufferOrError);
- return true;
-}
-
-void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address,
- StringRef Delimiter) {
- if (!Symbolizer)
- return;
- DILineInfo LineInfo = DILineInfo();
- auto ExpectecLineInfo =
- Symbolizer->symbolizeCode(Obj->getFileName(), Address);
- if (!ExpectecLineInfo)
- consumeError(ExpectecLineInfo.takeError());
- else
- LineInfo = *ExpectecLineInfo;
-
- if ((LineInfo.FileName == "<invalid>") || OldLineInfo.Line == LineInfo.Line ||
- LineInfo.Line == 0)
- return;
-
- if (PrintLines)
- OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n";
- if (PrintSource) {
- if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
- if (!cacheSource(LineInfo.FileName))
- return;
- auto FileBuffer = SourceCache.find(LineInfo.FileName);
- if (FileBuffer != SourceCache.end()) {
- auto LineBuffer = LineCache.find(LineInfo.FileName);
- if (LineBuffer != LineCache.end()) {
- if (LineInfo.Line > LineBuffer->second.size())
- return;
- // Vector begins at 0, line numbers are non-zero
- OS << Delimiter << LineBuffer->second[LineInfo.Line - 1].ltrim()
- << "\n";
- }
- }
- }
- OldLineInfo = LineInfo;
-}
-
-static bool isArmElf(const ObjectFile *Obj) {
- return (Obj->isELF() &&
- (Obj->getArch() == Triple::aarch64 ||
- Obj->getArch() == Triple::aarch64_be ||
- Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb ||
- Obj->getArch() == Triple::thumb ||
- Obj->getArch() == Triple::thumbeb));
-}
-
-class PrettyPrinter {
-public:
- virtual ~PrettyPrinter() = default;
- virtual void printInst(MCInstPrinter &IP, const MCInst *MI,
- ArrayRef<uint8_t> Bytes, uint64_t Address,
- raw_ostream &OS, StringRef Annot,
- MCSubtargetInfo const &STI, SourcePrinter *SP) {
- if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address);
- if (!NoLeadingAddr)
- OS << format("%8" PRIx64 ":", Address);
- if (!NoShowRawInsn) {
- OS << "\t";
- dumpBytes(Bytes, OS);
- }
- if (MI)
- IP.printInst(MI, OS, "", STI);
- else
- OS << " <unknown>";
- }
-};
-PrettyPrinter PrettyPrinterInst;
-class HexagonPrettyPrinter : public PrettyPrinter {
-public:
- void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
- raw_ostream &OS) {
- uint32_t opcode =
- (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
- if (!NoLeadingAddr)
- OS << format("%8" PRIx64 ":", Address);
- if (!NoShowRawInsn) {
- OS << "\t";
- dumpBytes(Bytes.slice(0, 4), OS);
- OS << format("%08" PRIx32, opcode);
- }
- }
- void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
- uint64_t Address, raw_ostream &OS, StringRef Annot,
- MCSubtargetInfo const &STI, SourcePrinter *SP) override {
- if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, "");
- if (!MI) {
- printLead(Bytes, Address, OS);
- OS << " <unknown>";
- return;
- }
- std::string Buffer;
- {
- raw_string_ostream TempStream(Buffer);
- IP.printInst(MI, TempStream, "", STI);
- }
- StringRef Contents(Buffer);
- // Split off bundle attributes
- auto PacketBundle = Contents.rsplit('\n');
- // Split off first instruction from the rest
- auto HeadTail = PacketBundle.first.split('\n');
- auto Preamble = " { ";
- auto Separator = "";
- while(!HeadTail.first.empty()) {
- OS << Separator;
- Separator = "\n";
- if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, "");
- printLead(Bytes, Address, OS);
- OS << Preamble;
- Preamble = " ";
- StringRef Inst;
- auto Duplex = HeadTail.first.split('\v');
- if(!Duplex.second.empty()){
- OS << Duplex.first;
- OS << "; ";
- Inst = Duplex.second;
- }
- else
- Inst = HeadTail.first;
- OS << Inst;
- Bytes = Bytes.slice(4);
- Address += 4;
- HeadTail = HeadTail.second.split('\n');
- }
- OS << " } " << PacketBundle.second;
- }
-};
-HexagonPrettyPrinter HexagonPrettyPrinterInst;
-
-class AMDGCNPrettyPrinter : public PrettyPrinter {
-public:
- void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
- uint64_t Address, raw_ostream &OS, StringRef Annot,
- MCSubtargetInfo const &STI, SourcePrinter *SP) override {
- if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address);
-
- if (!MI) {
- OS << " <unknown>";
- return;
- }
-
- SmallString<40> InstStr;
- raw_svector_ostream IS(InstStr);
-
- IP.printInst(MI, IS, "", STI);
-
- OS << left_justify(IS.str(), 60) << format("// %012" PRIX64 ": ", Address);
- typedef support::ulittle32_t U32;
- for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()),
- Bytes.size() / sizeof(U32)))
- // D should be explicitly casted to uint32_t here as it is passed
- // by format to snprintf as vararg.
- OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D));
-
- if (!Annot.empty())
- OS << "// " << Annot;
- }
-};
-AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;
-
-class BPFPrettyPrinter : public PrettyPrinter {
-public:
- void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
- uint64_t Address, raw_ostream &OS, StringRef Annot,
- MCSubtargetInfo const &STI, SourcePrinter *SP) override {
- if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address);
- if (!NoLeadingAddr)
- OS << format("%8" PRId64 ":", Address / 8);
- if (!NoShowRawInsn) {
- OS << "\t";
- dumpBytes(Bytes, OS);
- }
- if (MI)
- IP.printInst(MI, OS, "", STI);
- else
- OS << " <unknown>";
- }
-};
-BPFPrettyPrinter BPFPrettyPrinterInst;
-
-PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
- switch(Triple.getArch()) {
- default:
- return PrettyPrinterInst;
- case Triple::hexagon:
- return HexagonPrettyPrinterInst;
- case Triple::amdgcn:
- return AMDGCNPrettyPrinterInst;
- case Triple::bpfel:
- case Triple::bpfeb:
- return BPFPrettyPrinterInst;
- }
-}
-}
-
template <class ELFT>
static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
const RelocationRef &RelRef,
@@ -671,9 +471,11 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
if (!StrTabOrErr)
return errorToErrorCode(StrTabOrErr.takeError());
StringRef StrTab = *StrTabOrErr;
- uint8_t type = RelRef.getType();
- StringRef res;
int64_t addend = 0;
+ // If there is no Symbol associated with the relocation, we set the undef
+ // boolean value to 'true'. This will prevent us from calling functions that
+ // requires the relocation to be associated with a symbol.
+ bool undef = false;
switch (Sec->sh_type) {
default:
return object_error::parse_failed;
@@ -684,97 +486,41 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
case ELF::SHT_RELA: {
const Elf_Rela *ERela = Obj->getRela(Rel);
addend = ERela->r_addend;
+ undef = ERela->getSymbol(false) == 0;
break;
}
}
- symbol_iterator SI = RelRef.getSymbol();
- const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
StringRef Target;
- if (symb->getType() == ELF::STT_SECTION) {
- Expected<section_iterator> SymSI = SI->getSection();
- if (!SymSI)
- return errorToErrorCode(SymSI.takeError());
- const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
- auto SecName = EF.getSectionName(SymSec);
- if (!SecName)
- return errorToErrorCode(SecName.takeError());
- Target = *SecName;
- } else {
- Expected<StringRef> SymName = symb->getName(StrTab);
- if (!SymName)
- return errorToErrorCode(SymName.takeError());
- Target = *SymName;
- }
- switch (EF.getHeader()->e_machine) {
- case ELF::EM_X86_64:
- switch (type) {
- case ELF::R_X86_64_PC8:
- case ELF::R_X86_64_PC16:
- case ELF::R_X86_64_PC32: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << Target << (addend < 0 ? "" : "+") << addend << "-P";
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- } break;
- case ELF::R_X86_64_8:
- case ELF::R_X86_64_16:
- case ELF::R_X86_64_32:
- case ELF::R_X86_64_32S:
- case ELF::R_X86_64_64: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << Target << (addend < 0 ? "" : "+") << addend;
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- } break;
- default:
- res = "Unknown";
- }
- break;
- case ELF::EM_LANAI:
- case ELF::EM_AVR:
- case ELF::EM_AARCH64: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << Target;
- if (addend != 0)
- fmt << (addend < 0 ? "" : "+") << addend;
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- break;
- }
- case ELF::EM_386:
- case ELF::EM_IAMCU:
- case ELF::EM_ARM:
- case ELF::EM_HEXAGON:
- case ELF::EM_MIPS:
- case ELF::EM_BPF:
- case ELF::EM_RISCV:
- res = Target;
- break;
- case ELF::EM_WEBASSEMBLY:
- switch (type) {
- case ELF::R_WEBASSEMBLY_DATA: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << Target << (addend < 0 ? "" : "+") << addend;
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- break;
- }
- case ELF::R_WEBASSEMBLY_FUNCTION:
- res = Target;
- break;
- default:
- res = "Unknown";
+ if (!undef) {
+ symbol_iterator SI = RelRef.getSymbol();
+ const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
+ if (symb->getType() == ELF::STT_SECTION) {
+ Expected<section_iterator> SymSI = SI->getSection();
+ if (!SymSI)
+ return errorToErrorCode(SymSI.takeError());
+ const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
+ auto SecName = EF.getSectionName(SymSec);
+ if (!SecName)
+ return errorToErrorCode(SecName.takeError());
+ Target = *SecName;
+ } else {
+ Expected<StringRef> SymName = symb->getName(StrTab);
+ if (!SymName)
+ return errorToErrorCode(SymName.takeError());
+ Target = *SymName;
}
- break;
- default:
- res = "Unknown";
- }
- if (Result.empty())
- Result.append(res.begin(), res.end());
+ } else
+ Target = "*ABS*";
+
+ // Default scheme is to print Target, as well as "+ <addend>" for nonzero
+ // addend. Should be acceptable for all normal purposes.
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ fmt << Target;
+ if (addend != 0)
+ fmt << (addend < 0 ? "" : "+") << addend;
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
return std::error_code();
}
@@ -887,9 +633,21 @@ static std::error_code getRelocationValueString(const WasmObjectFile *Obj,
const RelocationRef &RelRef,
SmallVectorImpl<char> &Result) {
const wasm::WasmRelocation& Rel = Obj->getWasmRelocation(RelRef);
+ symbol_iterator SI = RelRef.getSymbol();
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
- fmt << Rel.Index << (Rel.Addend < 0 ? "" : "+") << Rel.Addend;
+ if (SI == Obj->symbol_end()) {
+ // Not all wasm relocations have symbols associated with them.
+ // In particular R_WEBASSEMBLY_TYPE_INDEX_LEB.
+ fmt << Rel.Index;
+ } else {
+ Expected<StringRef> SymNameOrErr = SI->getName();
+ if (!SymNameOrErr)
+ return errorToErrorCode(SymNameOrErr.takeError());
+ StringRef SymName = *SymNameOrErr;
+ Result.append(SymName.begin(), SymName.end());
+ }
+ fmt << (Rel.Addend < 0 ? "" : "+") << Rel.Addend;
fmt.flush();
Result.append(fmtbuf.begin(), fmtbuf.end());
return std::error_code();
@@ -1087,7 +845,7 @@ static std::error_code getRelocationValueString(const RelocationRef &Rel,
llvm_unreachable("unknown object file format");
}
-/// @brief Indicates whether this relocation should hidden when listing
+/// Indicates whether this relocation should hidden when listing
/// relocations, usually because it is the trailing part of a multipart
/// relocation that will be printed as part of the leading relocation.
static bool getHidden(RelocationRef RelRef) {
@@ -1120,6 +878,304 @@ static bool getHidden(RelocationRef RelRef) {
return false;
}
+namespace {
+class SourcePrinter {
+protected:
+ DILineInfo OldLineInfo;
+ const ObjectFile *Obj = nullptr;
+ std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
+ // File name to file contents of source
+ std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
+ // Mark the line endings of the cached source
+ std::unordered_map<std::string, std::vector<StringRef>> LineCache;
+
+private:
+ bool cacheSource(const DILineInfo& LineInfoFile);
+
+public:
+ SourcePrinter() = default;
+ SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) {
+ symbolize::LLVMSymbolizer::Options SymbolizerOpts(
+ DILineInfoSpecifier::FunctionNameKind::None, true, false, false,
+ DefaultArch);
+ Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts));
+ }
+ virtual ~SourcePrinter() = default;
+ virtual void printSourceLine(raw_ostream &OS, uint64_t Address,
+ StringRef Delimiter = "; ");
+};
+
+bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
+ std::unique_ptr<MemoryBuffer> Buffer;
+ if (LineInfo.Source) {
+ Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source);
+ } else {
+ auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName);
+ if (!BufferOrError)
+ return false;
+ Buffer = std::move(*BufferOrError);
+ }
+ // Chomp the file to get lines
+ size_t BufferSize = Buffer->getBufferSize();
+ const char *BufferStart = Buffer->getBufferStart();
+ for (const char *Start = BufferStart, *End = BufferStart;
+ End < BufferStart + BufferSize; End++)
+ if (*End == '\n' || End == BufferStart + BufferSize - 1 ||
+ (*End == '\r' && *(End + 1) == '\n')) {
+ LineCache[LineInfo.FileName].push_back(StringRef(Start, End - Start));
+ if (*End == '\r')
+ End++;
+ Start = End + 1;
+ }
+ SourceCache[LineInfo.FileName] = std::move(Buffer);
+ return true;
+}
+
+void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address,
+ StringRef Delimiter) {
+ if (!Symbolizer)
+ return;
+ DILineInfo LineInfo = DILineInfo();
+ auto ExpectecLineInfo =
+ Symbolizer->symbolizeCode(Obj->getFileName(), Address);
+ if (!ExpectecLineInfo)
+ consumeError(ExpectecLineInfo.takeError());
+ else
+ LineInfo = *ExpectecLineInfo;
+
+ if ((LineInfo.FileName == "<invalid>") || OldLineInfo.Line == LineInfo.Line ||
+ LineInfo.Line == 0)
+ return;
+
+ if (PrintLines)
+ OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n";
+ if (PrintSource) {
+ if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
+ if (!cacheSource(LineInfo))
+ return;
+ auto FileBuffer = SourceCache.find(LineInfo.FileName);
+ if (FileBuffer != SourceCache.end()) {
+ auto LineBuffer = LineCache.find(LineInfo.FileName);
+ if (LineBuffer != LineCache.end()) {
+ if (LineInfo.Line > LineBuffer->second.size())
+ return;
+ // Vector begins at 0, line numbers are non-zero
+ OS << Delimiter << LineBuffer->second[LineInfo.Line - 1].ltrim()
+ << "\n";
+ }
+ }
+ }
+ OldLineInfo = LineInfo;
+}
+
+static bool isArmElf(const ObjectFile *Obj) {
+ return (Obj->isELF() &&
+ (Obj->getArch() == Triple::aarch64 ||
+ Obj->getArch() == Triple::aarch64_be ||
+ Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb ||
+ Obj->getArch() == Triple::thumb ||
+ Obj->getArch() == Triple::thumbeb));
+}
+
+class PrettyPrinter {
+public:
+ virtual ~PrettyPrinter() = default;
+ virtual void printInst(MCInstPrinter &IP, const MCInst *MI,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &OS, StringRef Annot,
+ MCSubtargetInfo const &STI, SourcePrinter *SP,
+ std::vector<RelocationRef> *Rels = nullptr) {
+ if (SP && (PrintSource || PrintLines))
+ SP->printSourceLine(OS, Address);
+ if (!NoLeadingAddr)
+ OS << format("%8" PRIx64 ":", Address);
+ if (!NoShowRawInsn) {
+ OS << "\t";
+ dumpBytes(Bytes, OS);
+ }
+ if (MI)
+ IP.printInst(MI, OS, "", STI);
+ else
+ OS << " <unknown>";
+ }
+};
+PrettyPrinter PrettyPrinterInst;
+class HexagonPrettyPrinter : public PrettyPrinter {
+public:
+ void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &OS) {
+ uint32_t opcode =
+ (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
+ if (!NoLeadingAddr)
+ OS << format("%8" PRIx64 ":", Address);
+ if (!NoShowRawInsn) {
+ OS << "\t";
+ dumpBytes(Bytes.slice(0, 4), OS);
+ OS << format("%08" PRIx32, opcode);
+ }
+ }
+ void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
+ uint64_t Address, raw_ostream &OS, StringRef Annot,
+ MCSubtargetInfo const &STI, SourcePrinter *SP,
+ std::vector<RelocationRef> *Rels) override {
+ if (SP && (PrintSource || PrintLines))
+ SP->printSourceLine(OS, Address, "");
+ if (!MI) {
+ printLead(Bytes, Address, OS);
+ OS << " <unknown>";
+ return;
+ }
+ std::string Buffer;
+ {
+ raw_string_ostream TempStream(Buffer);
+ IP.printInst(MI, TempStream, "", STI);
+ }
+ StringRef Contents(Buffer);
+ // Split off bundle attributes
+ auto PacketBundle = Contents.rsplit('\n');
+ // Split off first instruction from the rest
+ auto HeadTail = PacketBundle.first.split('\n');
+ auto Preamble = " { ";
+ auto Separator = "";
+ StringRef Fmt = "\t\t\t%08" PRIx64 ": ";
+ std::vector<RelocationRef>::const_iterator rel_cur = Rels->begin();
+ std::vector<RelocationRef>::const_iterator rel_end = Rels->end();
+
+ // Hexagon's packets require relocations to be inline rather than
+ // clustered at the end of the packet.
+ auto PrintReloc = [&]() -> void {
+ while ((rel_cur != rel_end) && (rel_cur->getOffset() <= Address)) {
+ if (rel_cur->getOffset() == Address) {
+ SmallString<16> name;
+ SmallString<32> val;
+ rel_cur->getTypeName(name);
+ error(getRelocationValueString(*rel_cur, val));
+ OS << Separator << format(Fmt.data(), Address) << name << "\t" << val
+ << "\n";
+ return;
+ }
+ rel_cur++;
+ }
+ };
+
+ while(!HeadTail.first.empty()) {
+ OS << Separator;
+ Separator = "\n";
+ if (SP && (PrintSource || PrintLines))
+ SP->printSourceLine(OS, Address, "");
+ printLead(Bytes, Address, OS);
+ OS << Preamble;
+ Preamble = " ";
+ StringRef Inst;
+ auto Duplex = HeadTail.first.split('\v');
+ if(!Duplex.second.empty()){
+ OS << Duplex.first;
+ OS << "; ";
+ Inst = Duplex.second;
+ }
+ else
+ Inst = HeadTail.first;
+ OS << Inst;
+ HeadTail = HeadTail.second.split('\n');
+ if (HeadTail.first.empty())
+ OS << " } " << PacketBundle.second;
+ PrintReloc();
+ Bytes = Bytes.slice(4);
+ Address += 4;
+ }
+ }
+};
+HexagonPrettyPrinter HexagonPrettyPrinterInst;
+
+class AMDGCNPrettyPrinter : public PrettyPrinter {
+public:
+ void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
+ uint64_t Address, raw_ostream &OS, StringRef Annot,
+ MCSubtargetInfo const &STI, SourcePrinter *SP,
+ std::vector<RelocationRef> *Rels) override {
+ if (SP && (PrintSource || PrintLines))
+ SP->printSourceLine(OS, Address);
+
+ typedef support::ulittle32_t U32;
+
+ if (MI) {
+ SmallString<40> InstStr;
+ raw_svector_ostream IS(InstStr);
+
+ IP.printInst(MI, IS, "", STI);
+
+ OS << left_justify(IS.str(), 60);
+ } else {
+ // an unrecognized encoding - this is probably data so represent it
+ // using the .long directive, or .byte directive if fewer than 4 bytes
+ // remaining
+ if (Bytes.size() >= 4) {
+ OS << format("\t.long 0x%08" PRIx32 " ",
+ static_cast<uint32_t>(*reinterpret_cast<const U32*>(Bytes.data())));
+ OS.indent(42);
+ } else {
+ OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
+ for (unsigned int i = 1; i < Bytes.size(); i++)
+ OS << format(", 0x%02" PRIx8, Bytes[i]);
+ OS.indent(55 - (6 * Bytes.size()));
+ }
+ }
+
+ OS << format("// %012" PRIX64 ": ", Address);
+ if (Bytes.size() >=4) {
+ for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()),
+ Bytes.size() / sizeof(U32)))
+ // D should be explicitly casted to uint32_t here as it is passed
+ // by format to snprintf as vararg.
+ OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D));
+ } else {
+ for (unsigned int i = 0; i < Bytes.size(); i++)
+ OS << format("%02" PRIX8 " ", Bytes[i]);
+ }
+
+ if (!Annot.empty())
+ OS << "// " << Annot;
+ }
+};
+AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;
+
+class BPFPrettyPrinter : public PrettyPrinter {
+public:
+ void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
+ uint64_t Address, raw_ostream &OS, StringRef Annot,
+ MCSubtargetInfo const &STI, SourcePrinter *SP,
+ std::vector<RelocationRef> *Rels) override {
+ if (SP && (PrintSource || PrintLines))
+ SP->printSourceLine(OS, Address);
+ if (!NoLeadingAddr)
+ OS << format("%8" PRId64 ":", Address / 8);
+ if (!NoShowRawInsn) {
+ OS << "\t";
+ dumpBytes(Bytes, OS);
+ }
+ if (MI)
+ IP.printInst(MI, OS, "", STI);
+ else
+ OS << " <unknown>";
+ }
+};
+BPFPrettyPrinter BPFPrettyPrinterInst;
+
+PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
+ switch(Triple.getArch()) {
+ default:
+ return PrettyPrinterInst;
+ case Triple::hexagon:
+ return HexagonPrettyPrinterInst;
+ case Triple::amdgcn:
+ return AMDGCNPrettyPrinterInst;
+ case Triple::bpfel:
+ case Triple::bpfeb:
+ return BPFPrettyPrinterInst;
+ }
+}
+}
+
static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) {
assert(Obj->isELF());
if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
@@ -1254,6 +1310,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Create a mapping from virtual address to symbol name. This is used to
// pretty print the symbols while disassembling.
std::map<SectionRef, SectionSymbolsTy> AllSymbols;
+ SectionSymbolsTy AbsoluteSymbols;
for (const SymbolRef &Symbol : Obj->symbols()) {
Expected<uint64_t> AddressOrErr = Symbol.getAddress();
if (!AddressOrErr)
@@ -1269,15 +1326,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
Expected<section_iterator> SectionOrErr = Symbol.getSection();
if (!SectionOrErr)
report_error(Obj->getFileName(), SectionOrErr.takeError());
- section_iterator SecI = *SectionOrErr;
- if (SecI == Obj->section_end())
- continue;
uint8_t SymbolType = ELF::STT_NOTYPE;
if (Obj->isELF())
SymbolType = getElfSymbolType(Obj, Symbol);
- AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType);
+ section_iterator SecI = *SectionOrErr;
+ if (SecI != Obj->section_end())
+ AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType);
+ else
+ AbsoluteSymbols.emplace_back(Address, *Name, SymbolType);
+
}
if (AllSymbols.empty() && Obj->isELF())
@@ -1313,6 +1372,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (Sec != SectionAddresses.end())
AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE);
+ else
+ AbsoluteSymbols.emplace_back(VA, Name, ELF::STT_NOTYPE);
}
}
@@ -1320,6 +1381,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// a symbol near an address.
for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
array_pod_sort(SecSyms.second.begin(), SecSyms.second.end());
+ array_pod_sort(AbsoluteSymbols.begin(), AbsoluteSymbols.end());
for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
if (!DisassembleAll && (!Section.isText() || Section.isVirtual()))
@@ -1349,8 +1411,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
}
- std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end());
- std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());
+ llvm::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end());
+ llvm::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());
if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
// AMDGPU disassembler uses symbolizer for printing labels
@@ -1375,30 +1437,22 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
// Sort relocations by address.
- std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
+ llvm::sort(Rels.begin(), Rels.end(), RelocAddressLess);
StringRef SegmentName = "";
if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) {
DataRefImpl DR = Section.getRawDataRefImpl();
SegmentName = MachO->getSectionFinalSegmentName(DR);
}
- StringRef name;
- error(Section.getName(name));
-
- if ((SectionAddr <= StopAddress) &&
- (SectionAddr + SectSize) >= StartAddress) {
- outs() << "Disassembly of section ";
- if (!SegmentName.empty())
- outs() << SegmentName << ",";
- outs() << name << ':';
- }
+ StringRef SectionName;
+ error(Section.getName(SectionName));
// If the section has no symbol at the start, just insert a dummy one.
if (Symbols.empty() || std::get<0>(Symbols[0]) != 0) {
- Symbols.insert(Symbols.begin(),
- std::make_tuple(SectionAddr, name, Section.isText()
- ? ELF::STT_FUNC
- : ELF::STT_OBJECT));
+ Symbols.insert(
+ Symbols.begin(),
+ std::make_tuple(SectionAddr, SectionName,
+ Section.isText() ? ELF::STT_FUNC : ELF::STT_OBJECT));
}
SmallString<40> Comments;
@@ -1411,6 +1465,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
uint64_t Size;
uint64_t Index;
+ bool PrintedSection = false;
std::vector<RelocationRef>::const_iterator rel_cur = Rels.begin();
std::vector<RelocationRef>::const_iterator rel_end = Rels.end();
@@ -1435,13 +1490,24 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
continue;
}
+ /// Skip if user requested specific symbols and this is not in the list
+ if (!DisasmFuncsSet.empty() &&
+ !DisasmFuncsSet.count(std::get<1>(Symbols[si])))
+ continue;
+
+ if (!PrintedSection) {
+ PrintedSection = true;
+ outs() << "Disassembly of section ";
+ if (!SegmentName.empty())
+ outs() << SegmentName << ",";
+ outs() << SectionName << ':';
+ }
+
// Stop disassembly at the stop address specified
if (End + SectionAddr > StopAddress)
End = StopAddress - SectionAddr;
if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
- // make size 4 bytes folded
- End = Start + ((End - Start) & ~0x3ull);
if (std::get<2>(Symbols[si]) == ELF::STT_AMDGPU_HSA_KERNEL) {
// skip amd_kernel_code_t at the begining of kernel symbol (256 bytes)
Start += 256;
@@ -1458,7 +1524,32 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
}
- outs() << '\n' << std::get<1>(Symbols[si]) << ":\n";
+ auto PrintSymbol = [](StringRef Name) {
+ outs() << '\n' << Name << ":\n";
+ };
+ StringRef SymbolName = std::get<1>(Symbols[si]);
+ if (Demangle.getValue() == "" || Demangle.getValue() == "itanium") {
+ char *DemangledSymbol = nullptr;
+ size_t Size = 0;
+ int Status;
+ DemangledSymbol =
+ itaniumDemangle(SymbolName.data(), DemangledSymbol, &Size, &Status);
+ if (Status == 0)
+ PrintSymbol(StringRef(DemangledSymbol));
+ else
+ PrintSymbol(SymbolName);
+
+ if (Size != 0)
+ free(DemangledSymbol);
+ } else
+ PrintSymbol(SymbolName);
+
+ // Don't print raw contents of a virtual section. A virtual section
+ // doesn't have any contents in the file.
+ if (Section.isVirtual()) {
+ outs() << "...\n";
+ continue;
+ }
#ifndef NDEBUG
raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
@@ -1560,7 +1651,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
Byte = Bytes.slice(Index)[0];
outs() << format(" %02x", Byte);
- AsciiData[NumBytes] = isprint(Byte) ? Byte : '.';
+ AsciiData[NumBytes] = isPrint(Byte) ? Byte : '.';
uint8_t IndentOffset = 0;
NumBytes++;
@@ -1594,7 +1685,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
PIP.printInst(*IP, Disassembled ? &Inst : nullptr,
Bytes.slice(Index, Size), SectionAddr + Index, outs(), "",
- *STI, &SP);
+ *STI, &SP, &Rels);
outs() << CommentStream.str();
Comments.clear();
@@ -1623,55 +1714,65 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
--SectionAddress;
TargetSectionSymbols = &AllSymbols[SectionAddress->second];
} else {
- TargetSectionSymbols = nullptr;
+ TargetSectionSymbols = &AbsoluteSymbols;
}
}
// Find the first symbol in the section whose offset is less than
- // or equal to the target.
- if (TargetSectionSymbols) {
- auto TargetSym = std::upper_bound(
- TargetSectionSymbols->begin(), TargetSectionSymbols->end(),
+ // or equal to the target. If there isn't a section that contains
+ // the target, find the nearest preceding absolute symbol.
+ auto TargetSym = std::upper_bound(
+ TargetSectionSymbols->begin(), TargetSectionSymbols->end(),
+ Target, [](uint64_t LHS,
+ const std::tuple<uint64_t, StringRef, uint8_t> &RHS) {
+ return LHS < std::get<0>(RHS);
+ });
+ if (TargetSym == TargetSectionSymbols->begin()) {
+ TargetSectionSymbols = &AbsoluteSymbols;
+ TargetSym = std::upper_bound(
+ AbsoluteSymbols.begin(), AbsoluteSymbols.end(),
Target, [](uint64_t LHS,
const std::tuple<uint64_t, StringRef, uint8_t> &RHS) {
- return LHS < std::get<0>(RHS);
- });
- if (TargetSym != TargetSectionSymbols->begin()) {
- --TargetSym;
- uint64_t TargetAddress = std::get<0>(*TargetSym);
- StringRef TargetName = std::get<1>(*TargetSym);
- outs() << " <" << TargetName;
- uint64_t Disp = Target - TargetAddress;
- if (Disp)
- outs() << "+0x" << Twine::utohexstr(Disp);
- outs() << '>';
- }
+ return LHS < std::get<0>(RHS);
+ });
+ }
+ if (TargetSym != TargetSectionSymbols->begin()) {
+ --TargetSym;
+ uint64_t TargetAddress = std::get<0>(*TargetSym);
+ StringRef TargetName = std::get<1>(*TargetSym);
+ outs() << " <" << TargetName;
+ uint64_t Disp = Target - TargetAddress;
+ if (Disp)
+ outs() << "+0x" << Twine::utohexstr(Disp);
+ outs() << '>';
}
}
}
outs() << "\n";
- // Print relocation for instruction.
- while (rel_cur != rel_end) {
- bool hidden = getHidden(*rel_cur);
- uint64_t addr = rel_cur->getOffset();
- SmallString<16> name;
- SmallString<32> val;
+ // Hexagon does this in pretty printer
+ if (Obj->getArch() != Triple::hexagon)
+ // Print relocation for instruction.
+ while (rel_cur != rel_end) {
+ bool hidden = getHidden(*rel_cur);
+ uint64_t addr = rel_cur->getOffset();
+ SmallString<16> name;
+ SmallString<32> val;
+
+ // If this relocation is hidden, skip it.
+ if (hidden || ((SectionAddr + addr) < StartAddress)) {
+ ++rel_cur;
+ continue;
+ }
- // If this relocation is hidden, skip it.
- if (hidden || ((SectionAddr + addr) < StartAddress)) {
+ // Stop when rel_cur's address is past the current instruction.
+ if (addr >= Index + Size) break;
+ rel_cur->getTypeName(name);
+ error(getRelocationValueString(*rel_cur, val));
+ outs() << format(Fmt.data(), SectionAddr + addr) << name
+ << "\t" << val << "\n";
++rel_cur;
- continue;
}
-
- // Stop when rel_cur's address is past the current instruction.
- if (addr >= Index + Size) break;
- rel_cur->getTypeName(name);
- error(getRelocationValueString(*rel_cur, val));
- outs() << format(Fmt.data(), SectionAddr + addr) << name
- << "\t" << val << "\n";
- ++rel_cur;
- }
}
}
}
@@ -1707,10 +1808,44 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
}
}
+void llvm::PrintDynamicRelocations(const ObjectFile *Obj) {
+
+ // For the moment, this option is for ELF only
+ if (!Obj->isELF())
+ return;
+
+ const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
+
+ if (!Elf || Elf->getEType() != ELF::ET_DYN) {
+ error("not a dynamic object");
+ return;
+ }
+
+ StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
+
+ std::vector<SectionRef> DynRelSec = Obj->dynamic_relocation_sections();
+ if (DynRelSec.empty())
+ return;
+
+ outs() << "DYNAMIC RELOCATION RECORDS\n";
+ for (const SectionRef &Section : DynRelSec) {
+ if (Section.relocation_begin() == Section.relocation_end())
+ continue;
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ uint64_t address = Reloc.getOffset();
+ SmallString<32> relocname;
+ SmallString<32> valuestr;
+ Reloc.getTypeName(relocname);
+ error(getRelocationValueString(Reloc, valuestr));
+ outs() << format(Fmt.data(), address) << " " << relocname << " "
+ << valuestr << "\n";
+ }
+ }
+}
+
void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
- unsigned i = 0;
for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
error(Section.getName(Name));
@@ -1721,9 +1856,9 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
bool BSS = Section.isBSS();
std::string Type = (std::string(Text ? "TEXT " : "") +
(Data ? "DATA " : "") + (BSS ? "BSS" : ""));
- outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i,
- Name.str().c_str(), Size, Address, Type.c_str());
- ++i;
+ outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n",
+ (unsigned)Section.getIndex(), Name.str().c_str(), Size,
+ Address, Type.c_str());
}
}
@@ -1764,7 +1899,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {
// Print ascii.
outs() << " ";
for (std::size_t i = 0; i < 16 && addr + i < end; ++i) {
- if (std::isprint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))
+ if (isPrint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))
outs() << Contents[addr + i];
else
outs() << ".";
@@ -2018,8 +2153,10 @@ static void printFaultMaps(const ObjectFile *Obj) {
}
static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) {
- if (o->isELF())
- return printELFFileHeader(o);
+ if (o->isELF()) {
+ printELFFileHeader(o);
+ return printELFDynamicSection(o);
+ }
if (o->isCOFF())
return printCOFFFileHeader(o);
if (o->isWasm())
@@ -2033,7 +2170,86 @@ static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) {
report_error(o->getFileName(), "Invalid/Unsupported object file format");
}
-static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
+static void printFileHeaders(const ObjectFile *o) {
+ if (!o->isELF() && !o->isCOFF())
+ report_error(o->getFileName(), "Invalid/Unsupported object file format");
+
+ Triple::ArchType AT = o->getArch();
+ outs() << "architecture: " << Triple::getArchTypeName(AT) << "\n";
+ Expected<uint64_t> StartAddrOrErr = o->getStartAddress();
+ if (!StartAddrOrErr)
+ report_error(o->getFileName(), StartAddrOrErr.takeError());
+ outs() << "start address: "
+ << format("0x%0*x", o->getBytesInAddress(), StartAddrOrErr.get())
+ << "\n";
+}
+
+static void printArchiveChild(StringRef Filename, const Archive::Child &C) {
+ Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
+ if (!ModeOrErr) {
+ errs() << "ill-formed archive entry.\n";
+ consumeError(ModeOrErr.takeError());
+ return;
+ }
+ sys::fs::perms Mode = ModeOrErr.get();
+ outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
+ outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
+ outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
+
+ outs() << " ";
+
+ Expected<unsigned> UIDOrErr = C.getUID();
+ if (!UIDOrErr)
+ report_error(Filename, UIDOrErr.takeError());
+ unsigned UID = UIDOrErr.get();
+ outs() << format("%d/", UID);
+
+ Expected<unsigned> GIDOrErr = C.getGID();
+ if (!GIDOrErr)
+ report_error(Filename, GIDOrErr.takeError());
+ unsigned GID = GIDOrErr.get();
+ outs() << format("%-d ", GID);
+
+ Expected<uint64_t> Size = C.getRawSize();
+ if (!Size)
+ report_error(Filename, Size.takeError());
+ outs() << format("%6" PRId64, Size.get()) << " ";
+
+ StringRef RawLastModified = C.getRawLastModified();
+ unsigned Seconds;
+ if (RawLastModified.getAsInteger(10, Seconds))
+ outs() << "(date: \"" << RawLastModified
+ << "\" contains non-decimal chars) ";
+ else {
+ // Since ctime(3) returns a 26 character string of the form:
+ // "Sun Sep 16 01:03:52 1973\n\0"
+ // just print 24 characters.
+ time_t t = Seconds;
+ outs() << format("%.24s ", ctime(&t));
+ }
+
+ StringRef Name = "";
+ Expected<StringRef> NameOrErr = C.getName();
+ if (!NameOrErr) {
+ consumeError(NameOrErr.takeError());
+ Expected<StringRef> RawNameOrErr = C.getRawName();
+ if (!RawNameOrErr)
+ report_error(Filename, NameOrErr.takeError());
+ Name = RawNameOrErr.get();
+ } else {
+ Name = NameOrErr.get();
+ }
+ outs() << Name << "\n";
+}
+
+static void DumpObject(ObjectFile *o, const Archive *a = nullptr,
+ const Archive::Child *c = nullptr) {
StringRef ArchiveName = a != nullptr ? a->getFileName() : "";
// Avoid other output when using a raw option.
if (!RawClangAST) {
@@ -2045,10 +2261,14 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
outs() << ":\tfile format " << o->getFileFormatName() << "\n\n";
}
+ if (ArchiveHeaders && !MachOOpt)
+ printArchiveChild(a->getFileName(), *c);
if (Disassemble)
DisassembleObject(o, Relocations);
if (Relocations && !Disassemble)
PrintRelocations(o);
+ if (DynamicRelocations)
+ PrintDynamicRelocations(o);
if (SectionHeaders)
PrintSectionHeaders(o);
if (SectionContents)
@@ -2059,6 +2279,8 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
PrintUnwindInfo(o);
if (PrivateHeaders || FirstPrivateHeader)
printPrivateFileHeaders(o, FirstPrivateHeader);
+ if (FileHeaders)
+ printFileHeaders(o);
if (ExportsTrie)
printExportsTrie(o);
if (Rebase)
@@ -2082,7 +2304,8 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
}
}
-static void DumpObject(const COFFImportFile *I, const Archive *A) {
+static void DumpObject(const COFFImportFile *I, const Archive *A,
+ const Archive::Child *C = nullptr) {
StringRef ArchiveName = A ? A->getFileName() : "";
// Avoid other output when using a raw option.
@@ -2092,11 +2315,13 @@ static void DumpObject(const COFFImportFile *I, const Archive *A) {
<< ":\tfile format COFF-import-file"
<< "\n\n";
+ if (ArchiveHeaders && !MachOOpt)
+ printArchiveChild(A->getFileName(), *C);
if (SymbolTable)
printCOFFSymbolTable(I);
}
-/// @brief Dump each object file in \a a;
+/// Dump each object file in \a a;
static void DumpArchive(const Archive *a) {
Error Err = Error::success();
for (auto &C : a->children(Err)) {
@@ -2107,9 +2332,9 @@ static void DumpArchive(const Archive *a) {
continue;
}
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
- DumpObject(o, a);
+ DumpObject(o, a, &C);
else if (COFFImportFile *I = dyn_cast<COFFImportFile>(&*ChildOrErr.get()))
- DumpObject(I, a);
+ DumpObject(I, a, &C);
else
report_error(a->getFileName(), object_error::invalid_file_type);
}
@@ -2117,7 +2342,7 @@ static void DumpArchive(const Archive *a) {
report_error(a->getFileName(), std::move(Err));
}
-/// @brief Open file and figure out how to dump it.
+/// Open file and figure out how to dump it.
static void DumpInput(StringRef file) {
// If we are using the Mach-O specific object file parser, then let it parse
@@ -2143,10 +2368,7 @@ static void DumpInput(StringRef file) {
}
int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
@@ -2165,15 +2387,25 @@ int main(int argc, char **argv) {
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
+ if (AllHeaders)
+ PrivateHeaders = Relocations = SectionHeaders = SymbolTable = true;
+
if (DisassembleAll || PrintSource || PrintLines)
Disassemble = true;
+
+ if (Demangle.getValue() != "none" && Demangle.getValue() != "" &&
+ Demangle.getValue() != "itanium")
+ warn("Unsupported demangling style");
+
if (!Disassemble
&& !Relocations
+ && !DynamicRelocations
&& !SectionHeaders
&& !SectionContents
&& !SymbolTable
&& !UnwindInfo
&& !PrivateHeaders
+ && !FileHeaders
&& !FirstPrivateHeader
&& !ExportsTrie
&& !Rebase
@@ -2182,7 +2414,7 @@ int main(int argc, char **argv) {
&& !WeakBind
&& !RawClangAST
&& !(UniversalHeaders && MachOOpt)
- && !(ArchiveHeaders && MachOOpt)
+ && !ArchiveHeaders
&& !(IndirectSymbols && MachOOpt)
&& !(DataInCode && MachOOpt)
&& !(LinkOptHints && MachOOpt)
@@ -2197,6 +2429,9 @@ int main(int argc, char **argv) {
return 2;
}
+ DisasmFuncsSet.insert(DisassembleFunctions.begin(),
+ DisassembleFunctions.end());
+
llvm::for_each(InputFilenames, DumpInput);
return EXIT_SUCCESS;
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
index 2fcd506884b1..b2eb6e9d7771 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -30,13 +30,16 @@ namespace object {
extern cl::opt<std::string> TripleName;
extern cl::opt<std::string> ArchName;
extern cl::opt<std::string> MCPU;
+extern cl::opt<std::string> Demangle;
extern cl::list<std::string> MAttrs;
extern cl::list<std::string> FilterSections;
+extern cl::opt<bool> AllHeaders;
extern cl::opt<bool> Disassemble;
extern cl::opt<bool> DisassembleAll;
extern cl::opt<bool> NoShowRawInsn;
extern cl::opt<bool> NoLeadingAddr;
extern cl::opt<bool> PrivateHeaders;
+extern cl::opt<bool> FileHeaders;
extern cl::opt<bool> FirstPrivateHeader;
extern cl::opt<bool> ExportsTrie;
extern cl::opt<bool> Rebase;
@@ -56,6 +59,7 @@ extern cl::opt<bool> ObjcMetaData;
extern cl::opt<std::string> DisSymName;
extern cl::opt<bool> NonVerbose;
extern cl::opt<bool> Relocations;
+extern cl::opt<bool> DynamicRelocations;
extern cl::opt<bool> SectionHeaders;
extern cl::opt<bool> SectionContents;
extern cl::opt<bool> SymbolTable;
@@ -75,6 +79,7 @@ void printMachOBindTable(object::MachOObjectFile* o);
void printMachOLazyBindTable(object::MachOObjectFile* o);
void printMachOWeakBindTable(object::MachOObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
+void printELFDynamicSection(const object::ObjectFile *Obj);
void printCOFFFileHeader(const object::ObjectFile *o);
void printCOFFSymbolTable(const object::COFFImportFile *i);
void printCOFFSymbolTable(const object::COFFObjectFile *o);
@@ -88,10 +93,12 @@ void printLazyBindTable(object::ObjectFile *o);
void printWeakBindTable(object::ObjectFile *o);
void printRawClangAST(const object::ObjectFile *o);
void PrintRelocations(const object::ObjectFile *o);
+void PrintDynamicRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);
void PrintSectionContents(const object::ObjectFile *o);
void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName,
StringRef ArchitectureName = StringRef());
+void warn(StringRef Message);
LLVM_ATTRIBUTE_NORETURN void error(Twine Message);
LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, Twine Message);
LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, std::error_code EC);
diff --git a/contrib/llvm/tools/llvm-pdbutil/Analyze.cpp b/contrib/llvm/tools/llvm-pdbutil/Analyze.cpp
index 6c603dd8542b..974ab49d9440 100644
--- a/contrib/llvm/tools/llvm-pdbutil/Analyze.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/Analyze.cpp
@@ -125,7 +125,7 @@ Error AnalysisStyle::dump() {
const auto &Collisions = CollisionsIter->second;
outs() << TypeName << "\n";
- outs() << formatv(" [HEAD] {0:x} {1} {2}\n", A.second,
+ outs() << formatv(" [HEAD] {0:x} {1} {2}\n", uint32_t(A.second),
getLeafTypeName(HeadRecord.Type), TypeName);
for (const auto &Chain : Collisions) {
if (Chain.TI == TI)
diff --git a/contrib/llvm/tools/llvm-pdbutil/Diff.cpp b/contrib/llvm/tools/llvm-pdbutil/Diff.cpp
deleted file mode 100644
index 286dc51c29b6..000000000000
--- a/contrib/llvm/tools/llvm-pdbutil/Diff.cpp
+++ /dev/null
@@ -1,644 +0,0 @@
-//===- Diff.cpp - PDB diff utility ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Diff.h"
-
-#include "DiffPrinter.h"
-#include "FormatUtil.h"
-#include "StreamUtil.h"
-#include "llvm-pdbutil.h"
-
-#include "llvm/ADT/StringSet.h"
-
-#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Native/Formatters.h"
-#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
-#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
-#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
-
-#include "llvm/Support/FormatAdapters.h"
-#include "llvm/Support/FormatProviders.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Path.h"
-
-using namespace llvm;
-using namespace llvm::pdb;
-
-namespace {
-// Compare and format two stream numbers. Stream numbers are considered
-// identical if they contain the same value, equivalent if they are both
-// the invalid stream or neither is the invalid stream, and different if
-// one is the invalid stream and another isn't.
-struct StreamNumberProvider {
- static DiffResult compare(uint16_t L, uint16_t R) {
- if (L == R)
- return DiffResult::IDENTICAL;
- bool LP = L != kInvalidStreamIndex;
- bool RP = R != kInvalidStreamIndex;
- if (LP != RP)
- return DiffResult::DIFFERENT;
- return DiffResult::EQUIVALENT;
- }
-
- static std::string format(uint16_t SN, bool Right) {
- if (SN == kInvalidStreamIndex)
- return "(not present)";
- return formatv("{0}", SN).str();
- }
-};
-
-// Compares and formats two module indices. Modis are considered identical
-// if they are identical, equivalent if they either both contain a value or
-// both don't contain a value, and different if one contains a value and the
-// other doesn't.
-struct ModiProvider {
- DiffResult compare(Optional<uint32_t> L, Optional<uint32_t> R) {
- if (L == R)
- return DiffResult::IDENTICAL;
- if (L.hasValue() != R.hasValue())
- return DiffResult::DIFFERENT;
- return DiffResult::EQUIVALENT;
- }
-
- std::string format(Optional<uint32_t> Modi, bool Right) {
- if (!Modi.hasValue())
- return "(not present)";
- return formatv("{0}", *Modi).str();
- }
-};
-
-// Compares and formats two paths embedded in the PDB, ignoring the beginning
-// of the path if the user specified it as a "root path" on the command line.
-struct BinaryPathProvider {
- explicit BinaryPathProvider(uint32_t MaxLen) : MaxLen(MaxLen) {}
-
- DiffResult compare(StringRef L, StringRef R) {
- if (L == R)
- return DiffResult::IDENTICAL;
-
- SmallString<64> LN = removeRoot(L, false);
- SmallString<64> RN = removeRoot(R, true);
-
- return (LN.equals_lower(RN)) ? DiffResult::EQUIVALENT
- : DiffResult::DIFFERENT;
- }
-
- std::string format(StringRef S, bool Right) {
- if (S.empty())
- return "(empty)";
-
- SmallString<64> Native = removeRoot(S, Right);
- return truncateStringFront(Native.str(), MaxLen);
- }
-
- SmallString<64> removeRoot(StringRef Path, bool IsRight) const {
- SmallString<64> Native(Path);
- auto &RootOpt = IsRight ? opts::diff::RightRoot : opts::diff::LeftRoot;
- SmallString<64> Root(static_cast<std::string>(RootOpt));
- // pdb paths always use windows syntax, convert slashes to backslashes.
- sys::path::native(Root, sys::path::Style::windows);
- if (sys::path::has_stem(Root, sys::path::Style::windows))
- sys::path::append(Root, sys::path::Style::windows,
- sys::path::get_separator(sys::path::Style::windows));
-
- sys::path::replace_path_prefix(Native, Root, "", sys::path::Style::windows);
- return Native;
- }
- uint32_t MaxLen;
-};
-
-// Compare and format two stream purposes. For general streams, this just
-// compares the description. For module streams it uses the path comparison
-// algorithm taking into consideration the binary root, described above.
-// Formatting stream purposes just prints the stream purpose, except for
-// module streams and named streams, where it prefixes the name / module
-// with an identifier. Example:
-//
-// Named Stream "\names"
-// Module Stream "foo.obj"
-//
-// If a named stream is too long to fit in a column, it is truncated at the
-// end, and if a module is too long to fit in a column, it is truncated at the
-// beginning. Example:
-//
-// Named Stream "\Really Long Str..."
-// Module Stream "...puts\foo.obj"
-//
-struct StreamPurposeProvider {
- explicit StreamPurposeProvider(uint32_t MaxLen) : MaxLen(MaxLen) {}
-
- DiffResult compare(const StreamInfo &L, const StreamInfo &R) {
- if (L.getPurpose() != R.getPurpose())
- return DiffResult::DIFFERENT;
- if (L.getPurpose() == StreamPurpose::ModuleStream) {
- BinaryPathProvider PathProvider(MaxLen);
- return PathProvider.compare(L.getShortName(), R.getShortName());
- }
- return (L.getShortName() == R.getShortName()) ? DiffResult::IDENTICAL
- : DiffResult::DIFFERENT;
- }
-
- std::string format(const StreamInfo &P, bool Right) {
- if (P.getPurpose() == StreamPurpose::Other ||
- P.getPurpose() == StreamPurpose::Symbols)
- return truncateStringBack(P.getShortName(), MaxLen);
- if (P.getPurpose() == StreamPurpose::NamedStream)
- return truncateQuotedNameBack("Named Stream", P.getShortName(), MaxLen);
-
- assert(P.getPurpose() == StreamPurpose::ModuleStream);
- uint32_t ExtraChars = strlen("Module \"\"");
- BinaryPathProvider PathProvider(MaxLen - ExtraChars);
- std::string Result = PathProvider.format(P.getShortName(), Right);
- return formatv("Module \"{0}\"", Result);
- }
-
- uint32_t MaxLen;
-};
-} // namespace
-
-namespace llvm {
-template <> struct format_provider<PdbRaw_FeatureSig> {
- static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream,
- StringRef Style) {
- switch (Sig) {
- case PdbRaw_FeatureSig::MinimalDebugInfo:
- Stream << "MinimalDebugInfo";
- break;
- case PdbRaw_FeatureSig::NoTypeMerge:
- Stream << "NoTypeMerge";
- break;
- case PdbRaw_FeatureSig::VC110:
- Stream << "VC110";
- break;
- case PdbRaw_FeatureSig::VC140:
- Stream << "VC140";
- break;
- }
- }
-};
-}
-
-template <typename R> using ValueOfRange = llvm::detail::ValueOfRange<R>;
-
-DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2)
- : File1(File1), File2(File2) {}
-
-Error DiffStyle::dump() {
- if (auto EC = diffSuperBlock())
- return EC;
-
- if (auto EC = diffFreePageMap())
- return EC;
-
- if (auto EC = diffStreamDirectory())
- return EC;
-
- if (auto EC = diffStringTable())
- return EC;
-
- if (auto EC = diffInfoStream())
- return EC;
-
- if (auto EC = diffDbiStream())
- return EC;
-
- if (auto EC = diffSectionContribs())
- return EC;
-
- if (auto EC = diffSectionMap())
- return EC;
-
- if (auto EC = diffFpoStream())
- return EC;
-
- if (auto EC = diffTpiStream(StreamTPI))
- return EC;
-
- if (auto EC = diffTpiStream(StreamIPI))
- return EC;
-
- if (auto EC = diffPublics())
- return EC;
-
- if (auto EC = diffGlobals())
- return EC;
-
- return Error::success();
-}
-
-Error DiffStyle::diffSuperBlock() {
- DiffPrinter D(2, "MSF Super Block", 16, 20, opts::diff::PrintResultColumn,
- opts::diff::PrintValueColumns, outs());
- D.printExplicit("File", DiffResult::UNSPECIFIED,
- truncateStringFront(File1.getFilePath(), 18),
- truncateStringFront(File2.getFilePath(), 18));
- D.print("Block Size", File1.getBlockSize(), File2.getBlockSize());
- D.print("Block Count", File1.getBlockCount(), File2.getBlockCount());
- D.print("Unknown 1", File1.getUnknown1(), File2.getUnknown1());
- D.print("Directory Size", File1.getNumDirectoryBytes(),
- File2.getNumDirectoryBytes());
- return Error::success();
-}
-
-Error DiffStyle::diffStreamDirectory() {
- DiffPrinter D(2, "Stream Directory", 30, 20, opts::diff::PrintResultColumn,
- opts::diff::PrintValueColumns, outs());
- D.printExplicit("File", DiffResult::UNSPECIFIED,
- truncateStringFront(File1.getFilePath(), 18),
- truncateStringFront(File2.getFilePath(), 18));
-
- SmallVector<StreamInfo, 32> P;
- SmallVector<StreamInfo, 32> Q;
- discoverStreamPurposes(File1, P);
- discoverStreamPurposes(File2, Q);
- D.print("Stream Count", File1.getNumStreams(), File2.getNumStreams());
- auto PI = to_vector<32>(enumerate(P));
- auto QI = to_vector<32>(enumerate(Q));
-
- // Scan all streams in the left hand side, looking for ones that are also
- // in the right. Each time we find one, remove it. When we're done, Q
- // should contain all the streams that are in the right but not in the left.
- StreamPurposeProvider StreamProvider(28);
- for (const auto &P : PI) {
- typedef decltype(PI) ContainerType;
- typedef typename ContainerType::value_type value_type;
-
- auto Iter = llvm::find_if(QI, [P, &StreamProvider](const value_type &V) {
- DiffResult Result = StreamProvider.compare(P.value(), V.value());
- return Result == DiffResult::EQUIVALENT ||
- Result == DiffResult::IDENTICAL;
- });
-
- if (Iter == QI.end()) {
- D.printExplicit(StreamProvider.format(P.value(), false),
- DiffResult::DIFFERENT, P.index(), "(not present)");
- continue;
- }
-
- D.print<EquivalentDiffProvider>(StreamProvider.format(P.value(), false),
- P.index(), Iter->index());
- QI.erase(Iter);
- }
-
- for (const auto &Q : QI) {
- D.printExplicit(StreamProvider.format(Q.value(), true),
- DiffResult::DIFFERENT, "(not present)", Q.index());
- }
-
- return Error::success();
-}
-
-Error DiffStyle::diffStringTable() {
- DiffPrinter D(2, "String Table", 30, 20, opts::diff::PrintResultColumn,
- opts::diff::PrintValueColumns, outs());
- D.printExplicit("File", DiffResult::UNSPECIFIED,
- truncateStringFront(File1.getFilePath(), 18),
- truncateStringFront(File2.getFilePath(), 18));
-
- auto ExpectedST1 = File1.getStringTable();
- auto ExpectedST2 = File2.getStringTable();
- bool Has1 = !!ExpectedST1;
- bool Has2 = !!ExpectedST2;
- std::string Count1 = Has1 ? llvm::utostr(ExpectedST1->getNameCount())
- : "(string table not present)";
- std::string Count2 = Has2 ? llvm::utostr(ExpectedST2->getNameCount())
- : "(string table not present)";
- D.print("Number of Strings", Count1, Count2);
-
- if (!Has1 || !Has2) {
- consumeError(ExpectedST1.takeError());
- consumeError(ExpectedST2.takeError());
- return Error::success();
- }
-
- auto &ST1 = *ExpectedST1;
- auto &ST2 = *ExpectedST2;
-
- D.print("Hash Version", ST1.getHashVersion(), ST2.getHashVersion());
- D.print("Byte Size", ST1.getByteSize(), ST2.getByteSize());
- D.print("Signature", ST1.getSignature(), ST2.getSignature());
-
- // Both have a valid string table, dive in and compare individual strings.
-
- auto IdList1 = ST1.name_ids();
- auto IdList2 = ST2.name_ids();
- StringSet<> LS;
- StringSet<> RS;
- uint32_t Empty1 = 0;
- uint32_t Empty2 = 0;
- for (auto ID : IdList1) {
- auto S = ST1.getStringForID(ID);
- if (!S)
- return S.takeError();
- if (S->empty())
- ++Empty1;
- else
- LS.insert(*S);
- }
- for (auto ID : IdList2) {
- auto S = ST2.getStringForID(ID);
- if (!S)
- return S.takeError();
- if (S->empty())
- ++Empty2;
- else
- RS.insert(*S);
- }
- D.print("Empty Strings", Empty1, Empty2);
-
- for (const auto &S : LS) {
- auto R = RS.find(S.getKey());
- std::string Truncated = truncateStringMiddle(S.getKey(), 28);
- uint32_t I = cantFail(ST1.getIDForString(S.getKey()));
- if (R == RS.end()) {
- D.printExplicit(Truncated, DiffResult::DIFFERENT, I, "(not present)");
- continue;
- }
-
- uint32_t J = cantFail(ST2.getIDForString(R->getKey()));
- D.print<EquivalentDiffProvider>(Truncated, I, J);
- RS.erase(R);
- }
-
- for (const auto &S : RS) {
- auto L = LS.find(S.getKey());
- std::string Truncated = truncateStringMiddle(S.getKey(), 28);
- uint32_t J = cantFail(ST2.getIDForString(S.getKey()));
- if (L == LS.end()) {
- D.printExplicit(Truncated, DiffResult::DIFFERENT, "(not present)", J);
- continue;
- }
-
- uint32_t I = cantFail(ST1.getIDForString(L->getKey()));
- D.print<EquivalentDiffProvider>(Truncated, I, J);
- }
- return Error::success();
-}
-
-Error DiffStyle::diffFreePageMap() { return Error::success(); }
-
-Error DiffStyle::diffInfoStream() {
- DiffPrinter D(2, "PDB Stream", 22, 40, opts::diff::PrintResultColumn,
- opts::diff::PrintValueColumns, outs());
- D.printExplicit("File", DiffResult::UNSPECIFIED,
- truncateStringFront(File1.getFilePath(), 38),
- truncateStringFront(File2.getFilePath(), 38));
-
- auto ExpectedInfo1 = File1.getPDBInfoStream();
- auto ExpectedInfo2 = File2.getPDBInfoStream();
-
- bool Has1 = !!ExpectedInfo1;
- bool Has2 = !!ExpectedInfo2;
- if (!(Has1 && Has2)) {
- std::string L = Has1 ? "(present)" : "(not present)";
- std::string R = Has2 ? "(present)" : "(not present)";
- D.print("Stream", L, R);
-
- consumeError(ExpectedInfo1.takeError());
- consumeError(ExpectedInfo2.takeError());
- return Error::success();
- }
-
- auto &IS1 = *ExpectedInfo1;
- auto &IS2 = *ExpectedInfo2;
- D.print("Stream Size", IS1.getStreamSize(), IS2.getStreamSize());
- D.print("Age", IS1.getAge(), IS2.getAge());
- D.print("Guid", IS1.getGuid(), IS2.getGuid());
- D.print("Signature", IS1.getSignature(), IS2.getSignature());
- D.print("Version", IS1.getVersion(), IS2.getVersion());
- D.diffUnorderedArray("Feature", IS1.getFeatureSignatures(),
- IS2.getFeatureSignatures());
- D.print("Named Stream Size", IS1.getNamedStreamMapByteSize(),
- IS2.getNamedStreamMapByteSize());
- StringMap<uint32_t> NSL = IS1.getNamedStreams().getStringMap();
- StringMap<uint32_t> NSR = IS2.getNamedStreams().getStringMap();
- D.diffUnorderedMap<EquivalentDiffProvider>("Named Stream", NSL, NSR);
- return Error::success();
-}
-
-typedef std::pair<uint32_t, DbiModuleDescriptor> IndexedModuleDescriptor;
-typedef std::vector<IndexedModuleDescriptor> IndexedModuleDescriptorList;
-
-static IndexedModuleDescriptorList
-getModuleDescriptors(const DbiModuleList &ML) {
- IndexedModuleDescriptorList List;
- List.reserve(ML.getModuleCount());
- for (uint32_t I = 0; I < ML.getModuleCount(); ++I)
- List.emplace_back(I, ML.getModuleDescriptor(I));
- return List;
-}
-
-static IndexedModuleDescriptorList::iterator
-findOverrideEquivalentModule(uint32_t Modi,
- IndexedModuleDescriptorList &OtherList) {
- auto &EqMap = opts::diff::Equivalences;
-
- auto Iter = EqMap.find(Modi);
- if (Iter == EqMap.end())
- return OtherList.end();
-
- uint32_t EqValue = Iter->second;
-
- return llvm::find_if(OtherList,
- [EqValue](const IndexedModuleDescriptor &Desc) {
- return Desc.first == EqValue;
- });
-}
-
-static IndexedModuleDescriptorList::iterator
-findEquivalentModule(const IndexedModuleDescriptor &Item,
- IndexedModuleDescriptorList &OtherList, bool ItemIsRight) {
-
- if (!ItemIsRight) {
- uint32_t Modi = Item.first;
- auto OverrideIter = findOverrideEquivalentModule(Modi, OtherList);
- if (OverrideIter != OtherList.end())
- return OverrideIter;
- }
-
- BinaryPathProvider PathProvider(28);
-
- auto Iter = OtherList.begin();
- auto End = OtherList.end();
- for (; Iter != End; ++Iter) {
- const IndexedModuleDescriptor *Left = &Item;
- const IndexedModuleDescriptor *Right = &*Iter;
- if (ItemIsRight)
- std::swap(Left, Right);
- DiffResult Result = PathProvider.compare(Left->second.getModuleName(),
- Right->second.getModuleName());
- if (Result == DiffResult::EQUIVALENT || Result == DiffResult::IDENTICAL)
- return Iter;
- }
- return OtherList.end();
-}
-
-static void diffOneModule(DiffPrinter &D, const IndexedModuleDescriptor &Item,
- IndexedModuleDescriptorList &Other,
- bool ItemIsRight) {
- StreamPurposeProvider HeaderProvider(70);
- StreamInfo Info = StreamInfo::createModuleStream(
- Item.second.getModuleName(), Item.second.getModuleStreamIndex(),
- Item.first);
- D.printFullRow(HeaderProvider.format(Info, ItemIsRight));
-
- const auto *L = &Item;
-
- auto Iter = findEquivalentModule(Item, Other, ItemIsRight);
- if (Iter == Other.end()) {
- // We didn't find this module at all on the other side. Just print one row
- // and continue.
- if (ItemIsRight)
- D.print<ModiProvider>("- Modi", None, Item.first);
- else
- D.print<ModiProvider>("- Modi", Item.first, None);
- return;
- }
-
- // We did find this module. Go through and compare each field.
- const auto *R = &*Iter;
- if (ItemIsRight)
- std::swap(L, R);
-
- BinaryPathProvider PathProvider(28);
- D.print<ModiProvider>("- Modi", L->first, R->first);
- D.print<BinaryPathProvider>("- Obj File Name", L->second.getObjFileName(),
- R->second.getObjFileName(), PathProvider);
- D.print<StreamNumberProvider>("- Debug Stream",
- L->second.getModuleStreamIndex(),
- R->second.getModuleStreamIndex());
- D.print("- C11 Byte Size", L->second.getC11LineInfoByteSize(),
- R->second.getC11LineInfoByteSize());
- D.print("- C13 Byte Size", L->second.getC13LineInfoByteSize(),
- R->second.getC13LineInfoByteSize());
- D.print("- # of files", L->second.getNumberOfFiles(),
- R->second.getNumberOfFiles());
- D.print("- Pdb File Path Index", L->second.getPdbFilePathNameIndex(),
- R->second.getPdbFilePathNameIndex());
- D.print("- Source File Name Index", L->second.getSourceFileNameIndex(),
- R->second.getSourceFileNameIndex());
- D.print("- Symbol Byte Size", L->second.getSymbolDebugInfoByteSize(),
- R->second.getSymbolDebugInfoByteSize());
- Other.erase(Iter);
-}
-
-Error DiffStyle::diffDbiStream() {
- DiffPrinter D(2, "DBI Stream", 40, 30, opts::diff::PrintResultColumn,
- opts::diff::PrintValueColumns, outs());
- D.printExplicit("File", DiffResult::UNSPECIFIED,
- truncateStringFront(File1.getFilePath(), 28),
- truncateStringFront(File2.getFilePath(), 28));
-
- auto ExpectedDbi1 = File1.getPDBDbiStream();
- auto ExpectedDbi2 = File2.getPDBDbiStream();
-
- bool Has1 = !!ExpectedDbi1;
- bool Has2 = !!ExpectedDbi2;
- if (!(Has1 && Has2)) {
- std::string L = Has1 ? "(present)" : "(not present)";
- std::string R = Has2 ? "(present)" : "(not present)";
- D.print("Stream", L, R);
-
- consumeError(ExpectedDbi1.takeError());
- consumeError(ExpectedDbi2.takeError());
- return Error::success();
- }
-
- auto &DL = *ExpectedDbi1;
- auto &DR = *ExpectedDbi2;
-
- D.print("Dbi Version", (uint32_t)DL.getDbiVersion(),
- (uint32_t)DR.getDbiVersion());
- D.print("Age", DL.getAge(), DR.getAge());
- D.print("Machine", (uint16_t)DL.getMachineType(),
- (uint16_t)DR.getMachineType());
- D.print("Flags", DL.getFlags(), DR.getFlags());
- D.print("Build Major", DL.getBuildMajorVersion(), DR.getBuildMajorVersion());
- D.print("Build Minor", DL.getBuildMinorVersion(), DR.getBuildMinorVersion());
- D.print("Build Number", DL.getBuildNumber(), DR.getBuildNumber());
- D.print("PDB DLL Version", DL.getPdbDllVersion(), DR.getPdbDllVersion());
- D.print("PDB DLL RBLD", DL.getPdbDllRbld(), DR.getPdbDllRbld());
- D.print<StreamNumberProvider>("DBG (FPO)",
- DL.getDebugStreamIndex(DbgHeaderType::FPO),
- DR.getDebugStreamIndex(DbgHeaderType::FPO));
- D.print<StreamNumberProvider>(
- "DBG (Exception)", DL.getDebugStreamIndex(DbgHeaderType::Exception),
- DR.getDebugStreamIndex(DbgHeaderType::Exception));
- D.print<StreamNumberProvider>("DBG (Fixup)",
- DL.getDebugStreamIndex(DbgHeaderType::Fixup),
- DR.getDebugStreamIndex(DbgHeaderType::Fixup));
- D.print<StreamNumberProvider>(
- "DBG (OmapToSrc)", DL.getDebugStreamIndex(DbgHeaderType::OmapToSrc),
- DR.getDebugStreamIndex(DbgHeaderType::OmapToSrc));
- D.print<StreamNumberProvider>(
- "DBG (OmapFromSrc)", DL.getDebugStreamIndex(DbgHeaderType::OmapFromSrc),
- DR.getDebugStreamIndex(DbgHeaderType::OmapFromSrc));
- D.print<StreamNumberProvider>(
- "DBG (SectionHdr)", DL.getDebugStreamIndex(DbgHeaderType::SectionHdr),
- DR.getDebugStreamIndex(DbgHeaderType::SectionHdr));
- D.print<StreamNumberProvider>(
- "DBG (TokenRidMap)", DL.getDebugStreamIndex(DbgHeaderType::TokenRidMap),
- DR.getDebugStreamIndex(DbgHeaderType::TokenRidMap));
- D.print<StreamNumberProvider>("DBG (Xdata)",
- DL.getDebugStreamIndex(DbgHeaderType::Xdata),
- DR.getDebugStreamIndex(DbgHeaderType::Xdata));
- D.print<StreamNumberProvider>("DBG (Pdata)",
- DL.getDebugStreamIndex(DbgHeaderType::Pdata),
- DR.getDebugStreamIndex(DbgHeaderType::Pdata));
- D.print<StreamNumberProvider>("DBG (NewFPO)",
- DL.getDebugStreamIndex(DbgHeaderType::NewFPO),
- DR.getDebugStreamIndex(DbgHeaderType::NewFPO));
- D.print<StreamNumberProvider>(
- "DBG (SectionHdrOrig)",
- DL.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig),
- DR.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig));
- D.print<StreamNumberProvider>("Globals Stream",
- DL.getGlobalSymbolStreamIndex(),
- DR.getGlobalSymbolStreamIndex());
- D.print<StreamNumberProvider>("Publics Stream",
- DL.getPublicSymbolStreamIndex(),
- DR.getPublicSymbolStreamIndex());
- D.print<StreamNumberProvider>("Symbol Records", DL.getSymRecordStreamIndex(),
- DR.getSymRecordStreamIndex());
- D.print("Has CTypes", DL.hasCTypes(), DR.hasCTypes());
- D.print("Is Incrementally Linked", DL.isIncrementallyLinked(),
- DR.isIncrementallyLinked());
- D.print("Is Stripped", DL.isStripped(), DR.isStripped());
- const DbiModuleList &ML = DL.modules();
- const DbiModuleList &MR = DR.modules();
- D.print("Module Count", ML.getModuleCount(), MR.getModuleCount());
- D.print("Source File Count", ML.getSourceFileCount(),
- MR.getSourceFileCount());
- auto MDL = getModuleDescriptors(ML);
- auto MDR = getModuleDescriptors(MR);
- // Scan all module descriptors from the left, and look for corresponding
- // module descriptors on the right.
- for (const auto &L : MDL)
- diffOneModule(D, L, MDR, false);
-
- for (const auto &R : MDR)
- diffOneModule(D, R, MDL, true);
-
- return Error::success();
-}
-
-Error DiffStyle::diffSectionContribs() { return Error::success(); }
-
-Error DiffStyle::diffSectionMap() { return Error::success(); }
-
-Error DiffStyle::diffFpoStream() { return Error::success(); }
-
-Error DiffStyle::diffTpiStream(int Index) { return Error::success(); }
-
-Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); }
-
-Error DiffStyle::diffPublics() { return Error::success(); }
-
-Error DiffStyle::diffGlobals() { return Error::success(); }
diff --git a/contrib/llvm/tools/llvm-pdbutil/Diff.h b/contrib/llvm/tools/llvm-pdbutil/Diff.h
deleted file mode 100644
index 6037576e21bb..000000000000
--- a/contrib/llvm/tools/llvm-pdbutil/Diff.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- Diff.h - PDB diff utility --------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
-#define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
-
-#include "OutputStyle.h"
-
-namespace llvm {
-namespace pdb {
-class PDBFile;
-class DiffStyle : public OutputStyle {
-public:
- explicit DiffStyle(PDBFile &File1, PDBFile &File2);
-
- Error dump() override;
-
-private:
- Error diffSuperBlock();
- Error diffStreamDirectory();
- Error diffStringTable();
- Error diffFreePageMap();
- Error diffInfoStream();
- Error diffDbiStream();
- Error diffSectionContribs();
- Error diffSectionMap();
- Error diffFpoStream();
- Error diffTpiStream(int Index);
- Error diffModuleInfoStream(int Index);
- Error diffPublics();
- Error diffGlobals();
-
- PDBFile &File1;
- PDBFile &File2;
-};
-}
-}
-
-#endif
diff --git a/contrib/llvm/tools/llvm-pdbutil/DiffPrinter.cpp b/contrib/llvm/tools/llvm-pdbutil/DiffPrinter.cpp
deleted file mode 100644
index dd61cc182593..000000000000
--- a/contrib/llvm/tools/llvm-pdbutil/DiffPrinter.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-
-#include "DiffPrinter.h"
-
-#include "llvm/Support/FormatAdapters.h"
-
-using namespace llvm;
-using namespace llvm::pdb;
-
-namespace {
-struct Colorize {
- Colorize(raw_ostream &OS, DiffResult Result) : OS(OS) {
- if (!OS.has_colors())
- return;
- switch (Result) {
- case DiffResult::IDENTICAL:
- OS.changeColor(raw_ostream::Colors::GREEN, false);
- break;
- case DiffResult::EQUIVALENT:
- OS.changeColor(raw_ostream::Colors::YELLOW, true);
- break;
- default:
- OS.changeColor(raw_ostream::Colors::RED, false);
- break;
- }
- }
-
- ~Colorize() {
- if (OS.has_colors())
- OS.resetColor();
- }
-
- raw_ostream &OS;
-};
-}
-
-DiffPrinter::DiffPrinter(uint32_t Indent, StringRef Header,
- uint32_t PropertyWidth, uint32_t FieldWidth,
- bool Result, bool Fields, raw_ostream &Stream)
- : PrintResult(Result), PrintValues(Fields), Indent(Indent),
- PropertyWidth(PropertyWidth), FieldWidth(FieldWidth), OS(Stream) {
- printHeaderRow();
- printFullRow(Header);
-}
-
-DiffPrinter::~DiffPrinter() {}
-
-uint32_t DiffPrinter::tableWidth() const {
- // `|`
- uint32_t W = 1;
-
- // `<width>|`
- W += PropertyWidth + 1;
-
- if (PrintResult) {
- // ` I |`
- W += 4;
- }
-
- if (PrintValues) {
- // `<width>|<width>|`
- W += 2 * (FieldWidth + 1);
- }
- return W;
-}
-
-void DiffPrinter::printFullRow(StringRef Text) {
- newLine();
- printValue(Text, DiffResult::UNSPECIFIED, AlignStyle::Center,
- tableWidth() - 2, true);
- printSeparatorRow();
-}
-
-void DiffPrinter::printSeparatorRow() {
- newLine();
- OS << formatv("{0}", fmt_repeat('-', PropertyWidth));
- if (PrintResult) {
- OS << '+';
- OS << formatv("{0}", fmt_repeat('-', 3));
- }
- if (PrintValues) {
- OS << '+';
- OS << formatv("{0}", fmt_repeat('-', FieldWidth));
- OS << '+';
- OS << formatv("{0}", fmt_repeat('-', FieldWidth));
- }
- OS << '|';
-}
-
-void DiffPrinter::printHeaderRow() {
- newLine('-');
- OS << formatv("{0}", fmt_repeat('-', tableWidth() - 1));
-}
-
-void DiffPrinter::newLine(char InitialChar) {
- OS << "\n";
- OS.indent(Indent) << InitialChar;
-}
-
-void DiffPrinter::printExplicit(StringRef Property, DiffResult C,
- StringRef Left, StringRef Right) {
- newLine();
- printValue(Property, DiffResult::UNSPECIFIED, AlignStyle::Right,
- PropertyWidth, true);
- printResult(C);
- printValue(Left, C, AlignStyle::Center, FieldWidth, false);
- printValue(Right, C, AlignStyle::Center, FieldWidth, false);
- printSeparatorRow();
-}
-
-void DiffPrinter::printResult(DiffResult Result) {
- if (!PrintResult)
- return;
- switch (Result) {
- case DiffResult::DIFFERENT:
- printValue("D", Result, AlignStyle::Center, 3, true);
- break;
- case DiffResult::EQUIVALENT:
- printValue("E", Result, AlignStyle::Center, 3, true);
- break;
- case DiffResult::IDENTICAL:
- printValue("I", Result, AlignStyle::Center, 3, true);
- break;
- case DiffResult::UNSPECIFIED:
- printValue(" ", Result, AlignStyle::Center, 3, true);
- break;
- }
-}
-
-void DiffPrinter::printValue(StringRef Value, DiffResult C, AlignStyle Style,
- uint32_t Width, bool Force) {
- if (!Force && !PrintValues)
- return;
-
- if (Style == AlignStyle::Right)
- --Width;
-
- std::string FormattedItem =
- formatv("{0}", fmt_align(Value, Style, Width)).str();
- if (C != DiffResult::UNSPECIFIED) {
- Colorize Color(OS, C);
- OS << FormattedItem;
- } else
- OS << FormattedItem;
- if (Style == AlignStyle::Right)
- OS << ' ';
- OS << '|';
-}
diff --git a/contrib/llvm/tools/llvm-pdbutil/DiffPrinter.h b/contrib/llvm/tools/llvm-pdbutil/DiffPrinter.h
deleted file mode 100644
index 475747d8dc11..000000000000
--- a/contrib/llvm/tools/llvm-pdbutil/DiffPrinter.h
+++ /dev/null
@@ -1,172 +0,0 @@
-//===- DiffPrinter.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_TOOLS_LLVMPDBDUMP_DIFFPRINTER_H
-#define LLVM_TOOLS_LLVMPDBDUMP_DIFFPRINTER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <list>
-#include <unordered_set>
-
-namespace std {
-template <> struct hash<llvm::pdb::PdbRaw_FeatureSig> {
- typedef llvm::pdb::PdbRaw_FeatureSig argument_type;
- typedef std::size_t result_type;
- result_type operator()(argument_type Item) const {
- return std::hash<uint32_t>{}(uint32_t(Item));
- }
-};
-} // namespace std
-
-namespace llvm {
-namespace pdb {
-
-class PDBFile;
-
-enum class DiffResult { UNSPECIFIED, IDENTICAL, EQUIVALENT, DIFFERENT };
-
-struct IdenticalDiffProvider {
- template <typename T, typename U>
- DiffResult compare(const T &Left, const U &Right) {
- return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::DIFFERENT;
- }
-
- template <typename T> std::string format(const T &Item, bool Right) {
- return formatv("{0}", Item).str();
- }
-};
-
-struct EquivalentDiffProvider {
- template <typename T, typename U>
- DiffResult compare(const T &Left, const U &Right) {
- return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::EQUIVALENT;
- }
-
- template <typename T> std::string format(const T &Item, bool Right) {
- return formatv("{0}", Item).str();
- }
-};
-
-class DiffPrinter {
-public:
- DiffPrinter(uint32_t Indent, StringRef Header, uint32_t PropertyWidth,
- uint32_t FieldWidth, bool Result, bool Values,
- raw_ostream &Stream);
- ~DiffPrinter();
-
- template <typename T, typename U> struct Identical {};
-
- template <typename Provider = IdenticalDiffProvider, typename T, typename U>
- void print(StringRef Property, const T &Left, const U &Right,
- Provider P = Provider()) {
- std::string L = P.format(Left, false);
- std::string R = P.format(Right, true);
-
- DiffResult Result = P.compare(Left, Right);
- printExplicit(Property, Result, L, R);
- }
-
- void printExplicit(StringRef Property, DiffResult C, StringRef Left,
- StringRef Right);
-
- template <typename T, typename U>
- void printExplicit(StringRef Property, DiffResult C, const T &Left,
- const U &Right) {
- std::string L = formatv("{0}", Left).str();
- std::string R = formatv("{0}", Right).str();
- printExplicit(Property, C, StringRef(L), StringRef(R));
- }
-
- template <typename T, typename U>
- void diffUnorderedArray(StringRef Property, ArrayRef<T> Left,
- ArrayRef<U> Right) {
- std::unordered_set<T> LS(Left.begin(), Left.end());
- std::unordered_set<U> RS(Right.begin(), Right.end());
- std::string Count1 = formatv("{0} element(s)", Left.size());
- std::string Count2 = formatv("{0} element(s)", Right.size());
- print(std::string(Property) + "s (set)", Count1, Count2);
- for (const auto &L : LS) {
- auto Iter = RS.find(L);
- std::string Text = formatv("{0}", L).str();
- if (Iter == RS.end()) {
- print(Property, Text, "(not present)");
- continue;
- }
- print(Property, Text, Text);
- RS.erase(Iter);
- }
- for (const auto &R : RS) {
- auto Iter = LS.find(R);
- std::string Text = formatv("{0}", R).str();
- if (Iter == LS.end()) {
- print(Property, "(not present)", Text);
- continue;
- }
- print(Property, Text, Text);
- }
- }
-
- template <typename ValueProvider = IdenticalDiffProvider, typename T,
- typename U>
- void diffUnorderedMap(StringRef Property, const StringMap<T> &Left,
- const StringMap<U> &Right,
- ValueProvider P = ValueProvider()) {
- StringMap<U> RightCopy(Right);
-
- std::string Count1 = formatv("{0} element(s)", Left.size());
- std::string Count2 = formatv("{0} element(s)", Right.size());
- print(std::string(Property) + "s (map)", Count1, Count2);
-
- for (const auto &L : Left) {
- auto Iter = RightCopy.find(L.getKey());
- if (Iter == RightCopy.end()) {
- printExplicit(L.getKey(), DiffResult::DIFFERENT, L.getValue(),
- "(not present)");
- continue;
- }
-
- print(L.getKey(), L.getValue(), Iter->getValue(), P);
- RightCopy.erase(Iter);
- }
-
- for (const auto &R : RightCopy) {
- printExplicit(R.getKey(), DiffResult::DIFFERENT, "(not present)",
- R.getValue());
- }
- }
-
- void printFullRow(StringRef Text);
-
-private:
- uint32_t tableWidth() const;
-
- void printHeaderRow();
- void printSeparatorRow();
- void newLine(char InitialChar = '|');
- void printValue(StringRef Value, DiffResult C, AlignStyle Style,
- uint32_t Width, bool Force);
- void printResult(DiffResult Result);
-
- bool PrintResult;
- bool PrintValues;
- uint32_t Indent;
- uint32_t PropertyWidth;
- uint32_t FieldWidth;
- raw_ostream &OS;
-};
-} // namespace pdb
-} // namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index dd8436728baf..9e59adc71967 100644
--- a/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -90,7 +90,13 @@ Error DumpOutputStyle::dump() {
P.NewLine();
}
- if (opts::dump::DumpStringTable) {
+ if (opts::dump::DumpNamedStreams) {
+ if (auto EC = dumpNamedStreams())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpStringTable || opts::dump::DumpStringTableDetails) {
if (auto EC = dumpStringTable())
return EC;
P.NewLine();
@@ -145,6 +151,11 @@ Error DumpOutputStyle::dump() {
}
}
+ if (opts::dump::DumpGSIRecords) {
+ if (auto EC = dumpGSIRecords())
+ return EC;
+ }
+
if (opts::dump::DumpGlobals) {
if (auto EC = dumpGlobals())
return EC;
@@ -434,6 +445,86 @@ static void iterateModuleSubsections(
});
}
+static Expected<std::pair<std::unique_ptr<MappedBlockStream>,
+ ArrayRef<llvm::object::coff_section>>>
+loadSectionHeaders(PDBFile &File, DbgHeaderType Type) {
+ if (!File.hasPDBDbiStream())
+ return make_error<StringError>(
+ "Section headers require a DBI Stream, which could not be loaded",
+ inconvertibleErrorCode());
+
+ auto &Dbi = cantFail(File.getPDBDbiStream());
+ uint32_t SI = Dbi.getDebugStreamIndex(Type);
+
+ if (SI == kInvalidStreamIndex)
+ return make_error<StringError>(
+ "PDB does not contain the requested image section header type",
+ inconvertibleErrorCode());
+
+ auto Stream = File.createIndexedStream(SI);
+ if (!Stream)
+ return make_error<StringError>("Could not load the required stream data",
+ inconvertibleErrorCode());
+
+ ArrayRef<object::coff_section> Headers;
+ if (Stream->getLength() % sizeof(object::coff_section) != 0)
+ return make_error<StringError>(
+ "Section header array size is not a multiple of section header size",
+ inconvertibleErrorCode());
+
+ uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
+ BinaryStreamReader Reader(*Stream);
+ cantFail(Reader.readArray(Headers, NumHeaders));
+ return std::make_pair(std::move(Stream), Headers);
+}
+
+static std::vector<std::string> getSectionNames(PDBFile &File) {
+ auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr);
+ if (!ExpectedHeaders)
+ return {};
+
+ std::unique_ptr<MappedBlockStream> Stream;
+ ArrayRef<object::coff_section> Headers;
+ std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
+ std::vector<std::string> Names;
+ for (const auto &H : Headers)
+ Names.push_back(H.Name);
+ return Names;
+}
+
+static void dumpSectionContrib(LinePrinter &P, const SectionContrib &SC,
+ ArrayRef<std::string> SectionNames,
+ uint32_t FieldWidth) {
+ std::string NameInsert;
+ if (SC.ISect > 0 && SC.ISect <= SectionNames.size()) {
+ StringRef SectionName = SectionNames[SC.ISect - 1];
+ NameInsert = formatv("[{0}]", SectionName).str();
+ } else
+ NameInsert = "[???]";
+ P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
+ "crc = {4}",
+ formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size),
+ fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc),
+ fmt_align(NameInsert, AlignStyle::Left, FieldWidth + 2));
+ AutoIndent Indent(P, FieldWidth + 2);
+ P.formatLine(" {0}",
+ formatSectionCharacteristics(P.getIndentLevel() + 6,
+ SC.Characteristics, 3, " | "));
+}
+
+static void dumpSectionContrib(LinePrinter &P, const SectionContrib2 &SC,
+ ArrayRef<std::string> SectionNames,
+ uint32_t FieldWidth) {
+ P.formatLine("SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
+ "crc = {4}, coff section = {5}",
+ formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
+ fmtle(SC.Base.Size), fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc),
+ fmtle(SC.Base.RelocCrc), fmtle(SC.ISectCoff));
+ P.formatLine(" {0}",
+ formatSectionCharacteristics(P.getIndentLevel() + 6,
+ SC.Base.Characteristics, 3, " | "));
+}
+
Error DumpOutputStyle::dumpModules() {
printHeader(P, "Modules");
AutoIndent Indent(P);
@@ -456,6 +547,10 @@ Error DumpOutputStyle::dumpModules() {
iterateSymbolGroups(
File, PrintScope{P, 11}, [&](uint32_t Modi, const SymbolGroup &Strings) {
auto Desc = Modules.getModuleDescriptor(Modi);
+ if (opts::dump::DumpSectionContribs) {
+ std::vector<std::string> Sections = getSectionNames(getPdb());
+ dumpSectionContrib(P, Desc.getSectionContrib(), Sections, 0);
+ }
P.formatLine("Obj: `{0}`: ", Desc.getObjFileName());
P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}",
Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(),
@@ -848,14 +943,7 @@ Error DumpOutputStyle::dumpXme() {
return Error::success();
}
-Error DumpOutputStyle::dumpStringTable() {
- printHeader(P, "String Table");
-
- if (File.isObj()) {
- P.formatLine("Dumping string table is not supported for object files");
- return Error::success();
- }
-
+Error DumpOutputStyle::dumpStringTableFromPdb() {
AutoIndent Indent(P);
auto IS = getPdb().getStringTable();
if (!IS) {
@@ -864,37 +952,121 @@ Error DumpOutputStyle::dumpStringTable() {
return Error::success();
}
- if (IS->name_ids().empty()) {
- P.formatLine("Empty");
- return Error::success();
+ if (opts::dump::DumpStringTable) {
+ if (IS->name_ids().empty())
+ P.formatLine("Empty");
+ else {
+ auto MaxID =
+ std::max_element(IS->name_ids().begin(), IS->name_ids().end());
+ uint32_t Digits = NumDigits(*MaxID);
+
+ P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
+ "String");
+
+ std::vector<uint32_t> SortedIDs(IS->name_ids().begin(),
+ IS->name_ids().end());
+ llvm::sort(SortedIDs.begin(), SortedIDs.end());
+ for (uint32_t I : SortedIDs) {
+ auto ES = IS->getStringForID(I);
+ llvm::SmallString<32> Str;
+ if (!ES) {
+ consumeError(ES.takeError());
+ Str = "Error reading string";
+ } else if (!ES->empty()) {
+ Str.append("'");
+ Str.append(*ES);
+ Str.append("'");
+ }
+
+ if (!Str.empty())
+ P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits),
+ Str);
+ }
+ }
}
- auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
- uint32_t Digits = NumDigits(*MaxID);
-
- P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
- "String");
-
- std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
- std::sort(SortedIDs.begin(), SortedIDs.end());
- for (uint32_t I : SortedIDs) {
- auto ES = IS->getStringForID(I);
- llvm::SmallString<32> Str;
- if (!ES) {
- consumeError(ES.takeError());
- Str = "Error reading string";
- } else if (!ES->empty()) {
- Str.append("'");
- Str.append(*ES);
- Str.append("'");
+ if (opts::dump::DumpStringTableDetails) {
+ P.NewLine();
+ {
+ P.printLine("String Table Header:");
+ AutoIndent Indent(P);
+ P.formatLine("Signature: {0}", IS->getSignature());
+ P.formatLine("Hash Version: {0}", IS->getHashVersion());
+ P.formatLine("Name Buffer Size: {0}", IS->getByteSize());
+ P.NewLine();
}
- if (!Str.empty())
- P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
+ BinaryStreamRef NameBuffer = IS->getStringTable().getBuffer();
+ ArrayRef<uint8_t> Contents;
+ cantFail(NameBuffer.readBytes(0, NameBuffer.getLength(), Contents));
+ P.formatBinary("Name Buffer", Contents, 0);
+ P.NewLine();
+ {
+ P.printLine("Hash Table:");
+ AutoIndent Indent(P);
+ P.formatLine("Bucket Count: {0}", IS->name_ids().size());
+ for (const auto &Entry : enumerate(IS->name_ids()))
+ P.formatLine("Bucket[{0}] : {1}", Entry.index(),
+ uint32_t(Entry.value()));
+ P.formatLine("Name Count: {0}", IS->getNameCount());
+ }
}
return Error::success();
}
+Error DumpOutputStyle::dumpStringTableFromObj() {
+ iterateModuleSubsections<DebugStringTableSubsectionRef>(
+ File, PrintScope{P, 4},
+ [&](uint32_t Modi, const SymbolGroup &Strings,
+ DebugStringTableSubsectionRef &Strings2) {
+ BinaryStreamRef StringTableBuffer = Strings2.getBuffer();
+ BinaryStreamReader Reader(StringTableBuffer);
+ while (Reader.bytesRemaining() > 0) {
+ StringRef Str;
+ uint32_t Offset = Reader.getOffset();
+ cantFail(Reader.readCString(Str));
+ if (Str.empty())
+ continue;
+
+ P.formatLine("{0} | {1}", fmt_align(Offset, AlignStyle::Right, 4),
+ Str);
+ }
+ });
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpNamedStreams() {
+ printHeader(P, "Named Streams");
+ AutoIndent Indent(P, 2);
+
+ if (File.isObj()) {
+ P.formatLine("Dumping Named Streams is only supported for PDB files.");
+ return Error::success();
+ }
+ ExitOnError Err("Invalid PDB File: ");
+
+ auto &IS = Err(File.pdb().getPDBInfoStream());
+ const NamedStreamMap &NS = IS.getNamedStreams();
+ for (const auto &Entry : NS.entries()) {
+ P.printLine(Entry.getKey());
+ AutoIndent Indent2(P, 2);
+ P.formatLine("Index: {0}", Entry.getValue());
+ P.formatLine("Size in bytes: {0}",
+ File.pdb().getStreamByteSize(Entry.getValue()));
+ }
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpStringTable() {
+ printHeader(P, "String Table");
+
+ if (File.isPdb())
+ return dumpStringTableFromPdb();
+
+ return dumpStringTableFromObj();
+}
+
static void buildDepSet(LazyRandomTypeCollection &Types,
ArrayRef<TypeIndex> Indices,
std::map<TypeIndex, CVType> &DepSet) {
@@ -975,8 +1147,15 @@ Error DumpOutputStyle::dumpTypesFromObjectFile() {
if (auto EC = S.getName(SectionName))
return errorCodeToError(EC);
- if (SectionName != ".debug$T")
+ // .debug$T is a standard CodeView type section, while .debug$P is the same
+ // format but used for MSVC precompiled header object files.
+ if (SectionName == ".debug$T")
+ printHeader(P, "Types (.debug$T)");
+ else if (SectionName == ".debug$P")
+ printHeader(P, "Precompiled Types (.debug$P)");
+ else
continue;
+
StringRef Contents;
if (auto EC = S.getContents(Contents))
return errorCodeToError(EC);
@@ -1124,6 +1303,7 @@ Error DumpOutputStyle::dumpModuleSymsForObj() {
File, PrintScope{P, 2},
[&](uint32_t Modi, const SymbolGroup &Strings,
DebugSymbolsSubsectionRef &Symbols) {
+ Dumper.setSymbolGroup(&Strings);
for (auto Symbol : Symbols) {
if (auto EC = Visitor.visitSymbolRecord(Symbol)) {
SymbolError = llvm::make_unique<Error>(std::move(EC));
@@ -1165,8 +1345,8 @@ Error DumpOutputStyle::dumpModuleSymsForPdb() {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
- MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids,
- Types);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Strings,
+ Ids, Types);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
@@ -1182,6 +1362,39 @@ Error DumpOutputStyle::dumpModuleSymsForPdb() {
return Error::success();
}
+Error DumpOutputStyle::dumpGSIRecords() {
+ printHeader(P, "GSI Records");
+ AutoIndent Indent(P);
+
+ if (File.isObj()) {
+ P.formatLine("Dumping Globals is not supported for object files");
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBSymbolStream()) {
+ P.formatLine("GSI Common Symbol Stream not present");
+ return Error::success();
+ }
+
+ auto &Records = cantFail(getPdb().getPDBSymbolStream());
+ auto &Types = File.types();
+ auto &Ids = File.ids();
+
+ P.printLine("Records");
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+
+ BinaryStreamRef SymStream = Records.getSymbolArray().getUnderlyingStream();
+ if (auto E = Visitor.visitSymbolStream(Records.getSymbolArray(), 0))
+ return E;
+ return Error::success();
+}
+
Error DumpOutputStyle::dumpGlobals() {
printHeader(P, "Global Symbols");
AutoIndent Indent(P);
@@ -1287,6 +1500,7 @@ Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
Pipeline.addCallbackToPipeline(Dumper);
CVSymbolVisitor Visitor(Pipeline);
+
BinaryStreamRef SymStream =
ExpectedSyms->getSymbolArray().getUnderlyingStream();
for (uint32_t PubSymOff : Table) {
@@ -1299,24 +1513,23 @@ Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
}
// Return early if we aren't dumping public hash table and address map info.
- if (!HashExtras)
- return Error::success();
-
- P.formatLine("Hash Entries");
- {
- AutoIndent Indent2(P);
- for (const PSHashRecord &HR : Table.HashRecords)
- P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
- uint32_t(HR.CRef));
- }
+ if (HashExtras) {
+ P.formatBinary("Hash Bitmap", Table.HashBitmap, 0);
- // FIXME: Dump the bitmap.
+ P.formatLine("Hash Entries");
+ {
+ AutoIndent Indent2(P);
+ for (const PSHashRecord &HR : Table.HashRecords)
+ P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
+ uint32_t(HR.CRef));
+ }
- P.formatLine("Hash Buckets");
- {
- AutoIndent Indent2(P);
- for (uint32_t Hash : Table.HashBuckets)
- P.formatLine("{0:x8}", Hash);
+ P.formatLine("Hash Buckets");
+ {
+ AutoIndent Indent2(P);
+ for (uint32_t Hash : Table.HashBuckets)
+ P.formatLine("{0:x8}", Hash);
+ }
}
return Error::success();
@@ -1344,39 +1557,6 @@ Error DumpOutputStyle::dumpSectionHeaders() {
return Error::success();
}
-static Expected<std::pair<std::unique_ptr<MappedBlockStream>,
- ArrayRef<llvm::object::coff_section>>>
-loadSectionHeaders(PDBFile &File, DbgHeaderType Type) {
- if (!File.hasPDBDbiStream())
- return make_error<StringError>(
- "Section headers require a DBI Stream, which could not be loaded",
- inconvertibleErrorCode());
-
- auto &Dbi = cantFail(File.getPDBDbiStream());
- uint32_t SI = Dbi.getDebugStreamIndex(Type);
-
- if (SI == kInvalidStreamIndex)
- return make_error<StringError>(
- "PDB does not contain the requested image section header type",
- inconvertibleErrorCode());
-
- auto Stream = File.createIndexedStream(SI);
- if (!Stream)
- return make_error<StringError>("Could not load the required stream data",
- inconvertibleErrorCode());
-
- ArrayRef<object::coff_section> Headers;
- if (Stream->getLength() % sizeof(object::coff_section) != 0)
- return make_error<StringError>(
- "Section header array size is not a multiple of section header size",
- inconvertibleErrorCode());
-
- uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
- BinaryStreamReader Reader(*Stream);
- cantFail(Reader.readArray(Headers, NumHeaders));
- return std::make_pair(std::move(Stream), Headers);
-}
-
void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) {
printHeader(P, Label);
@@ -1423,20 +1603,6 @@ void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) {
return;
}
-std::vector<std::string> getSectionNames(PDBFile &File) {
- auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr);
- if (!ExpectedHeaders)
- return {};
-
- std::unique_ptr<MappedBlockStream> Stream;
- ArrayRef<object::coff_section> Headers;
- std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
- std::vector<std::string> Names;
- for (const auto &H : Headers)
- Names.push_back(H.Name);
- return Names;
-}
-
Error DumpOutputStyle::dumpSectionContribs() {
printHeader(P, "Section Contributions");
@@ -1465,33 +1631,10 @@ Error DumpOutputStyle::dumpSectionContribs() {
MaxNameLen = (Max == Names.end() ? 0 : Max->size());
}
void visit(const SectionContrib &SC) override {
- assert(SC.ISect > 0);
- std::string NameInsert;
- if (SC.ISect < Names.size()) {
- StringRef SectionName = Names[SC.ISect - 1];
- NameInsert = formatv("[{0}]", SectionName).str();
- } else
- NameInsert = "[???]";
- P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
- "crc = {4}",
- formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size),
- fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc),
- fmt_align(NameInsert, AlignStyle::Left, MaxNameLen + 2));
- AutoIndent Indent(P, MaxNameLen + 2);
- P.formatLine(" {0}",
- formatSectionCharacteristics(P.getIndentLevel() + 6,
- SC.Characteristics, 3, " | "));
+ dumpSectionContrib(P, SC, Names, MaxNameLen);
}
void visit(const SectionContrib2 &SC) override {
- P.formatLine(
- "SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
- "crc = {4}, coff section = {5}",
- formatSegmentOffset(SC.Base.ISect, SC.Base.Off), fmtle(SC.Base.Size),
- fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
- fmtle(SC.ISectCoff));
- P.formatLine(" {0}", formatSectionCharacteristics(
- P.getIndentLevel() + 6,
- SC.Base.Characteristics, 3, " | "));
+ dumpSectionContrib(P, SC, Names, MaxNameLen);
}
private:
diff --git a/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
index 3ce2884b2712..e7e9252f2fa9 100644
--- a/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
+++ b/contrib/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -74,7 +74,10 @@ private:
Error dumpStreamSummary();
Error dumpSymbolStats();
Error dumpUdtStats();
+ Error dumpNamedStreams();
Error dumpStringTable();
+ Error dumpStringTableFromPdb();
+ Error dumpStringTableFromObj();
Error dumpLines();
Error dumpInlineeLines();
Error dumpXmi();
@@ -85,6 +88,7 @@ private:
Error dumpModuleFiles();
Error dumpModuleSymsForPdb();
Error dumpModuleSymsForObj();
+ Error dumpGSIRecords();
Error dumpGlobals();
Error dumpPublics();
Error dumpSymbolsFromGSI(const GSIHashTable &Table, bool HashExtras);
diff --git a/contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp b/contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
new file mode 100644
index 000000000000..d16bfa480e1d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
@@ -0,0 +1,469 @@
+//===- ExplainOutputStyle.cpp --------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExplainOutputStyle.h"
+
+#include "FormatUtil.h"
+#include "InputFile.h"
+#include "StreamUtil.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+ExplainOutputStyle::ExplainOutputStyle(InputFile &File, uint64_t FileOffset)
+ : File(File), FileOffset(FileOffset), P(2, false, outs()) {}
+
+Error ExplainOutputStyle::dump() {
+ P.formatLine("Explaining file offset {0} of file '{1}'.", FileOffset,
+ File.getFilePath());
+
+ if (File.isPdb())
+ return explainPdbFile();
+
+ return explainBinaryFile();
+}
+
+Error ExplainOutputStyle::explainPdbFile() {
+ bool IsAllocated = explainPdbBlockStatus();
+ if (!IsAllocated)
+ return Error::success();
+
+ AutoIndent Indent(P);
+ if (isPdbSuperBlock())
+ explainPdbSuperBlockOffset();
+ else if (isPdbFpmBlock())
+ explainPdbFpmBlockOffset();
+ else if (isPdbBlockMapBlock())
+ explainPdbBlockMapOffset();
+ else if (isPdbStreamDirectoryBlock())
+ explainPdbStreamDirectoryOffset();
+ else if (auto Index = getPdbBlockStreamIndex())
+ explainPdbStreamOffset(*Index);
+ else
+ explainPdbUnknownBlock();
+ return Error::success();
+}
+
+Error ExplainOutputStyle::explainBinaryFile() {
+ std::unique_ptr<BinaryByteStream> Stream =
+ llvm::make_unique<BinaryByteStream>(File.unknown().getBuffer(),
+ llvm::support::little);
+ switch (opts::explain::InputType) {
+ case opts::explain::InputFileType::DBIStream: {
+ DbiStream Dbi(std::move(Stream));
+ if (auto EC = Dbi.reload(nullptr))
+ return EC;
+ explainStreamOffset(Dbi, FileOffset);
+ break;
+ }
+ case opts::explain::InputFileType::PDBStream: {
+ InfoStream Info(std::move(Stream));
+ if (auto EC = Info.reload())
+ return EC;
+ explainStreamOffset(Info, FileOffset);
+ break;
+ }
+ default:
+ llvm_unreachable("Invalid input file type!");
+ }
+ return Error::success();
+}
+
+uint32_t ExplainOutputStyle::pdbBlockIndex() const {
+ return FileOffset / File.pdb().getBlockSize();
+}
+
+uint32_t ExplainOutputStyle::pdbBlockOffset() const {
+ uint64_t BlockStart = pdbBlockIndex() * File.pdb().getBlockSize();
+ assert(FileOffset >= BlockStart);
+ return FileOffset - BlockStart;
+}
+
+bool ExplainOutputStyle::isPdbSuperBlock() const {
+ return pdbBlockIndex() == 0;
+}
+
+bool ExplainOutputStyle::isPdbFpm1() const {
+ return ((pdbBlockIndex() - 1) % File.pdb().getBlockSize() == 0);
+}
+bool ExplainOutputStyle::isPdbFpm2() const {
+ return ((pdbBlockIndex() - 2) % File.pdb().getBlockSize() == 0);
+}
+
+bool ExplainOutputStyle::isPdbFpmBlock() const {
+ return isPdbFpm1() || isPdbFpm2();
+}
+
+bool ExplainOutputStyle::isPdbBlockMapBlock() const {
+ return pdbBlockIndex() == File.pdb().getBlockMapIndex();
+}
+
+bool ExplainOutputStyle::isPdbStreamDirectoryBlock() const {
+ const auto &Layout = File.pdb().getMsfLayout();
+ return llvm::is_contained(Layout.DirectoryBlocks, pdbBlockIndex());
+}
+
+Optional<uint32_t> ExplainOutputStyle::getPdbBlockStreamIndex() const {
+ const auto &Layout = File.pdb().getMsfLayout();
+ for (const auto &Entry : enumerate(Layout.StreamMap)) {
+ if (!llvm::is_contained(Entry.value(), pdbBlockIndex()))
+ continue;
+ return Entry.index();
+ }
+ return None;
+}
+
+bool ExplainOutputStyle::explainPdbBlockStatus() {
+ if (FileOffset >= File.pdb().getFileSize()) {
+ P.formatLine("Address {0} is not in the file (file size = {1}).",
+ FileOffset, File.pdb().getFileSize());
+ return false;
+ }
+ P.formatLine("Block:Offset = {2:X-}:{1:X-4}.", FileOffset, pdbBlockOffset(),
+ pdbBlockIndex());
+
+ bool IsFree = File.pdb().getMsfLayout().FreePageMap[pdbBlockIndex()];
+ P.formatLine("Address is in block {0} ({1}allocated).", pdbBlockIndex(),
+ IsFree ? "un" : "");
+ return !IsFree;
+}
+
+#define endof(Class, Field) (offsetof(Class, Field) + sizeof(Class::Field))
+
+void ExplainOutputStyle::explainPdbSuperBlockOffset() {
+ P.formatLine("This corresponds to offset {0} of the MSF super block, ",
+ pdbBlockOffset());
+ if (pdbBlockOffset() < endof(SuperBlock, MagicBytes))
+ P.printLine("which is part of the MSF file magic.");
+ else if (pdbBlockOffset() < endof(SuperBlock, BlockSize)) {
+ P.printLine("which contains the block size of the file.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->BlockSize));
+ } else if (pdbBlockOffset() < endof(SuperBlock, FreeBlockMapBlock)) {
+ P.printLine("which contains the index of the FPM block (e.g. 1 or 2).");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->FreeBlockMapBlock));
+ } else if (pdbBlockOffset() < endof(SuperBlock, NumBlocks)) {
+ P.printLine("which contains the number of blocks in the file.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->NumBlocks));
+ } else if (pdbBlockOffset() < endof(SuperBlock, NumDirectoryBytes)) {
+ P.printLine("which contains the number of bytes in the stream directory.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->NumDirectoryBytes));
+ } else if (pdbBlockOffset() < endof(SuperBlock, Unknown1)) {
+ P.printLine("whose purpose is unknown.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->Unknown1));
+ } else if (pdbBlockOffset() < endof(SuperBlock, BlockMapAddr)) {
+ P.printLine("which contains the file offset of the block map.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->BlockMapAddr));
+ } else {
+ assert(pdbBlockOffset() > sizeof(SuperBlock));
+ P.printLine(
+ "which is outside the range of valid data for the super block.");
+ }
+}
+
+static std::string toBinaryString(uint8_t Byte) {
+ char Result[9] = {0};
+ for (int I = 0; I < 8; ++I) {
+ char C = (Byte & 1) ? '1' : '0';
+ Result[I] = C;
+ Byte >>= 1;
+ }
+ return std::string(Result);
+}
+
+void ExplainOutputStyle::explainPdbFpmBlockOffset() {
+ const MSFLayout &Layout = File.pdb().getMsfLayout();
+ uint32_t MainFpm = Layout.mainFpmBlock();
+ uint32_t AltFpm = Layout.alternateFpmBlock();
+
+ assert(isPdbFpmBlock());
+ uint32_t Fpm = isPdbFpm1() ? 1 : 2;
+ uint32_t FpmChunk = pdbBlockIndex() / File.pdb().getBlockSize();
+ assert((Fpm == MainFpm) || (Fpm == AltFpm));
+ (void)AltFpm;
+ bool IsMain = (Fpm == MainFpm);
+ P.formatLine("Address is in FPM{0} ({1} FPM)", Fpm, IsMain ? "Main" : "Alt");
+ uint32_t DescribedBlockStart =
+ 8 * (FpmChunk * File.pdb().getBlockSize() + pdbBlockOffset());
+ if (DescribedBlockStart > File.pdb().getBlockCount()) {
+ P.printLine("Address is in extraneous FPM space.");
+ return;
+ }
+
+ P.formatLine("Address describes the allocation status of blocks [{0},{1})",
+ DescribedBlockStart, DescribedBlockStart + 8);
+ ArrayRef<uint8_t> Bytes;
+ cantFail(File.pdb().getMsfBuffer().readBytes(FileOffset, 1, Bytes));
+ P.formatLine("Status = {0} (Note: 0 = allocated, 1 = free)",
+ toBinaryString(Bytes[0]));
+}
+
+void ExplainOutputStyle::explainPdbBlockMapOffset() {
+ uint64_t BlockMapOffset = File.pdb().getBlockMapOffset();
+ uint32_t OffsetInBlock = FileOffset - BlockMapOffset;
+ P.formatLine("Address is at offset {0} of the directory block list",
+ OffsetInBlock);
+}
+
+static uint32_t getOffsetInStream(ArrayRef<support::ulittle32_t> StreamBlocks,
+ uint64_t FileOffset, uint32_t BlockSize) {
+ uint32_t BlockIndex = FileOffset / BlockSize;
+ uint32_t OffsetInBlock = FileOffset - BlockIndex * BlockSize;
+
+ auto Iter = llvm::find(StreamBlocks, BlockIndex);
+ assert(Iter != StreamBlocks.end());
+ uint32_t StreamBlockIndex = std::distance(StreamBlocks.begin(), Iter);
+ return StreamBlockIndex * BlockSize + OffsetInBlock;
+}
+
+void ExplainOutputStyle::explainPdbStreamOffset(uint32_t Stream) {
+ SmallVector<StreamInfo, 12> Streams;
+ discoverStreamPurposes(File.pdb(), Streams);
+
+ assert(Stream <= Streams.size());
+ const StreamInfo &S = Streams[Stream];
+ const auto &Layout = File.pdb().getStreamLayout(Stream);
+ uint32_t StreamOff =
+ getOffsetInStream(Layout.Blocks, FileOffset, File.pdb().getBlockSize());
+ P.formatLine("Address is at offset {0}/{1} of Stream {2} ({3}){4}.",
+ StreamOff, Layout.Length, Stream, S.getLongName(),
+ (StreamOff > Layout.Length) ? " in unused space" : "");
+ switch (S.getPurpose()) {
+ case StreamPurpose::DBI: {
+ DbiStream &Dbi = cantFail(File.pdb().getPDBDbiStream());
+ explainStreamOffset(Dbi, StreamOff);
+ break;
+ }
+ case StreamPurpose::PDB: {
+ InfoStream &Info = cantFail(File.pdb().getPDBInfoStream());
+ explainStreamOffset(Info, StreamOff);
+ break;
+ }
+ case StreamPurpose::IPI:
+ case StreamPurpose::TPI:
+ case StreamPurpose::ModuleStream:
+ case StreamPurpose::NamedStream:
+ default:
+ break;
+ }
+}
+
+void ExplainOutputStyle::explainPdbStreamDirectoryOffset() {
+ auto DirectoryBlocks = File.pdb().getDirectoryBlockArray();
+ const auto &Layout = File.pdb().getMsfLayout();
+ uint32_t StreamOff =
+ getOffsetInStream(DirectoryBlocks, FileOffset, File.pdb().getBlockSize());
+ P.formatLine("Address is at offset {0}/{1} of Stream Directory{2}.",
+ StreamOff, uint32_t(Layout.SB->NumDirectoryBytes),
+ uint32_t(StreamOff > Layout.SB->NumDirectoryBytes)
+ ? " in unused space"
+ : "");
+}
+
+void ExplainOutputStyle::explainPdbUnknownBlock() {
+ P.formatLine("Address has unknown purpose.");
+}
+
+template <typename T>
+static void printStructField(LinePrinter &P, StringRef Label, T Value) {
+ P.formatLine("which contains {0}.", Label);
+ P.formatLine("The current value is {0}.", Value);
+}
+
+static void explainDbiHeaderOffset(LinePrinter &P, DbiStream &Dbi,
+ uint32_t Offset) {
+ const DbiStreamHeader *Header = Dbi.getHeader();
+ assert(Header != nullptr);
+
+ if (Offset < endof(DbiStreamHeader, VersionSignature))
+ printStructField(P, "the DBI Stream Version Signature",
+ int32_t(Header->VersionSignature));
+ else if (Offset < endof(DbiStreamHeader, VersionHeader))
+ printStructField(P, "the DBI Stream Version Header",
+ uint32_t(Header->VersionHeader));
+ else if (Offset < endof(DbiStreamHeader, Age))
+ printStructField(P, "the age of the DBI Stream", uint32_t(Header->Age));
+ else if (Offset < endof(DbiStreamHeader, GlobalSymbolStreamIndex))
+ printStructField(P, "the index of the Global Symbol Stream",
+ uint16_t(Header->GlobalSymbolStreamIndex));
+ else if (Offset < endof(DbiStreamHeader, BuildNumber))
+ printStructField(P, "the build number", uint16_t(Header->BuildNumber));
+ else if (Offset < endof(DbiStreamHeader, PublicSymbolStreamIndex))
+ printStructField(P, "the index of the Public Symbol Stream",
+ uint16_t(Header->PublicSymbolStreamIndex));
+ else if (Offset < endof(DbiStreamHeader, PdbDllVersion))
+ printStructField(P, "the version of mspdb.dll",
+ uint16_t(Header->PdbDllVersion));
+ else if (Offset < endof(DbiStreamHeader, SymRecordStreamIndex))
+ printStructField(P, "the index of the Symbol Record Stream",
+ uint16_t(Header->SymRecordStreamIndex));
+ else if (Offset < endof(DbiStreamHeader, PdbDllRbld))
+ printStructField(P, "the rbld of mspdb.dll", uint16_t(Header->PdbDllRbld));
+ else if (Offset < endof(DbiStreamHeader, ModiSubstreamSize))
+ printStructField(P, "the size of the Module Info Substream",
+ int32_t(Header->ModiSubstreamSize));
+ else if (Offset < endof(DbiStreamHeader, SecContrSubstreamSize))
+ printStructField(P, "the size of the Section Contribution Substream",
+ int32_t(Header->SecContrSubstreamSize));
+ else if (Offset < endof(DbiStreamHeader, SectionMapSize))
+ printStructField(P, "the size of the Section Map Substream",
+ int32_t(Header->SectionMapSize));
+ else if (Offset < endof(DbiStreamHeader, FileInfoSize))
+ printStructField(P, "the size of the File Info Substream",
+ int32_t(Header->FileInfoSize));
+ else if (Offset < endof(DbiStreamHeader, TypeServerSize))
+ printStructField(P, "the size of the Type Server Map",
+ int32_t(Header->TypeServerSize));
+ else if (Offset < endof(DbiStreamHeader, MFCTypeServerIndex))
+ printStructField(P, "the index of the MFC Type Server stream",
+ uint32_t(Header->MFCTypeServerIndex));
+ else if (Offset < endof(DbiStreamHeader, OptionalDbgHdrSize))
+ printStructField(P, "the size of the Optional Debug Stream array",
+ int32_t(Header->OptionalDbgHdrSize));
+ else if (Offset < endof(DbiStreamHeader, ECSubstreamSize))
+ printStructField(P, "the size of the Edit & Continue Substream",
+ int32_t(Header->ECSubstreamSize));
+ else if (Offset < endof(DbiStreamHeader, Flags))
+ printStructField(P, "the DBI Stream flags", uint16_t(Header->Flags));
+ else if (Offset < endof(DbiStreamHeader, MachineType))
+ printStructField(P, "the machine type", uint16_t(Header->MachineType));
+ else if (Offset < endof(DbiStreamHeader, Reserved))
+ printStructField(P, "reserved data", uint32_t(Header->Reserved));
+}
+
+static void explainDbiModiSubstreamOffset(LinePrinter &P, DbiStream &Dbi,
+ uint32_t Offset) {
+ VarStreamArray<DbiModuleDescriptor> ModuleDescriptors;
+ BinaryStreamRef ModiSubstreamData = Dbi.getModiSubstreamData().StreamData;
+ BinaryStreamReader Reader(ModiSubstreamData);
+
+ cantFail(Reader.readArray(ModuleDescriptors, ModiSubstreamData.getLength()));
+ auto Prev = ModuleDescriptors.begin();
+ assert(Prev.offset() == 0);
+ auto Current = Prev;
+ uint32_t Index = 0;
+ while (true) {
+ Prev = Current;
+ ++Current;
+ if (Current == ModuleDescriptors.end() || Offset < Current.offset())
+ break;
+ ++Index;
+ }
+
+ DbiModuleDescriptor &Descriptor = *Prev;
+ P.formatLine("which contains the descriptor for module {0} ({1}).", Index,
+ Descriptor.getModuleName());
+}
+
+template <typename T>
+static void dontExplain(LinePrinter &Printer, T &Stream, uint32_t Offset) {}
+
+template <typename T, typename SubstreamRangeT>
+static void explainSubstreamOffset(LinePrinter &P, uint32_t OffsetInStream,
+ T &Stream,
+ const SubstreamRangeT &Substreams) {
+ uint32_t SubOffset = OffsetInStream;
+ for (const auto &Entry : Substreams) {
+ if (Entry.Size <= 0)
+ continue;
+ uint32_t S = static_cast<uint32_t>(Entry.Size);
+ if (SubOffset < S) {
+ P.formatLine("address is at offset {0}/{1} of the {2}.", SubOffset, S,
+ Entry.Label);
+ Entry.Explain(P, Stream, SubOffset);
+ return;
+ }
+ SubOffset -= S;
+ }
+}
+
+void ExplainOutputStyle::explainStreamOffset(DbiStream &Dbi,
+ uint32_t OffsetInStream) {
+ P.printLine("Within the DBI stream:");
+ AutoIndent Indent(P);
+ const DbiStreamHeader *Header = Dbi.getHeader();
+ assert(Header != nullptr);
+
+ struct SubstreamInfo {
+ int32_t Size;
+ StringRef Label;
+ void (*Explain)(LinePrinter &, DbiStream &, uint32_t);
+ } Substreams[] = {
+ {sizeof(DbiStreamHeader), "DBI Stream Header", explainDbiHeaderOffset},
+ {int32_t(Header->ModiSubstreamSize), "Module Info Substream",
+ explainDbiModiSubstreamOffset},
+ {int32_t(Header->SecContrSubstreamSize), "Section Contribution Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->SectionMapSize), "Section Map", dontExplain<DbiStream>},
+ {int32_t(Header->FileInfoSize), "File Info Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->TypeServerSize), "Type Server Map Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->ECSubstreamSize), "Edit & Continue Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->OptionalDbgHdrSize), "Optional Debug Stream Array",
+ dontExplain<DbiStream>},
+ };
+
+ explainSubstreamOffset(P, OffsetInStream, Dbi, Substreams);
+}
+
+static void explainPdbStreamHeaderOffset(LinePrinter &P, InfoStream &Info,
+ uint32_t Offset) {
+ const InfoStreamHeader *Header = Info.getHeader();
+ assert(Header != nullptr);
+
+ if (Offset < endof(InfoStreamHeader, Version))
+ printStructField(P, "the PDB Stream Version Signature",
+ uint32_t(Header->Version));
+ else if (Offset < endof(InfoStreamHeader, Signature))
+ printStructField(P, "the signature of the PDB Stream",
+ uint32_t(Header->Signature));
+ else if (Offset < endof(InfoStreamHeader, Age))
+ printStructField(P, "the age of the PDB", uint32_t(Header->Age));
+ else if (Offset < endof(InfoStreamHeader, Guid))
+ printStructField(P, "the guid of the PDB", fmt_guid(Header->Guid.Guid));
+}
+
+void ExplainOutputStyle::explainStreamOffset(InfoStream &Info,
+ uint32_t OffsetInStream) {
+ P.printLine("Within the PDB stream:");
+ AutoIndent Indent(P);
+
+ struct SubstreamInfo {
+ uint32_t Size;
+ StringRef Label;
+ void (*Explain)(LinePrinter &, InfoStream &, uint32_t);
+ } Substreams[] = {{sizeof(InfoStreamHeader), "PDB Stream Header",
+ explainPdbStreamHeaderOffset},
+ {Info.getNamedStreamMapByteSize(), "Named Stream Map",
+ dontExplain<InfoStream>},
+ {Info.getStreamSize(), "PDB Feature Signatures",
+ dontExplain<InfoStream>}};
+
+ explainSubstreamOffset(P, OffsetInStream, Info, Substreams);
+}
diff --git a/contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h b/contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
new file mode 100644
index 000000000000..9a497accb812
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
@@ -0,0 +1,68 @@
+//===- ExplainOutputStyle.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_TOOLS_LLVMPDBDUMP_EXPLAINOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_EXPLAINOUTPUTSTYLE_H
+
+#include "LinePrinter.h"
+#include "OutputStyle.h"
+
+#include <string>
+
+namespace llvm {
+
+namespace pdb {
+
+class DbiStream;
+class InfoStream;
+class InputFile;
+
+class ExplainOutputStyle : public OutputStyle {
+
+public:
+ ExplainOutputStyle(InputFile &File, uint64_t FileOffset);
+
+ Error dump() override;
+
+private:
+ Error explainPdbFile();
+ Error explainBinaryFile();
+
+ bool explainPdbBlockStatus();
+
+ bool isPdbFpm1() const;
+ bool isPdbFpm2() const;
+
+ bool isPdbSuperBlock() const;
+ bool isPdbFpmBlock() const;
+ bool isPdbBlockMapBlock() const;
+ bool isPdbStreamDirectoryBlock() const;
+ Optional<uint32_t> getPdbBlockStreamIndex() const;
+
+ void explainPdbSuperBlockOffset();
+ void explainPdbFpmBlockOffset();
+ void explainPdbBlockMapOffset();
+ void explainPdbStreamDirectoryOffset();
+ void explainPdbStreamOffset(uint32_t Stream);
+ void explainPdbUnknownBlock();
+
+ void explainStreamOffset(DbiStream &Stream, uint32_t OffsetInStream);
+ void explainStreamOffset(InfoStream &Stream, uint32_t OffsetInStream);
+
+ uint32_t pdbBlockIndex() const;
+ uint32_t pdbBlockOffset() const;
+
+ InputFile &File;
+ const uint64_t FileOffset;
+ LinePrinter P;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbutil/InputFile.cpp b/contrib/llvm/tools/llvm-pdbutil/InputFile.cpp
index 8b05381174df..7b5af7e96920 100644
--- a/contrib/llvm/tools/llvm-pdbutil/InputFile.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/InputFile.cpp
@@ -95,7 +95,8 @@ static inline bool isDebugSSection(object::SectionRef Section,
static bool isDebugTSection(SectionRef Section, CVTypeArray &Types) {
BinaryStreamReader Reader;
- if (!isCodeViewDebugSubsection(Section, ".debug$T", Reader))
+ if (!isCodeViewDebugSubsection(Section, ".debug$T", Reader) &&
+ !isCodeViewDebugSubsection(Section, ".debug$P", Reader))
return false;
cantFail(Reader.readArray(Types, Reader.bytesRemaining()));
return true;
@@ -242,7 +243,7 @@ void SymbolGroup::formatFromChecksumsOffset(LinePrinter &Printer,
}
}
-Expected<InputFile> InputFile::open(StringRef Path) {
+Expected<InputFile> InputFile::open(StringRef Path, bool AllowUnknownFile) {
InputFile IF;
if (!llvm::sys::fs::exists(Path))
return make_error<StringError>(formatv("File {0} not found", Path),
@@ -263,7 +264,7 @@ Expected<InputFile> InputFile::open(StringRef Path) {
return std::move(IF);
}
- if (Magic == file_magic::unknown) {
+ if (Magic == file_magic::pdb) {
std::unique_ptr<IPDBSession> Session;
if (auto Err = loadDataForPDB(PDB_ReaderType::Native, Path, Session))
return std::move(Err);
@@ -274,9 +275,19 @@ Expected<InputFile> InputFile::open(StringRef Path) {
return std::move(IF);
}
- return make_error<StringError>(
- formatv("File {0} is not a supported file type", Path),
- inconvertibleErrorCode());
+ if (!AllowUnknownFile)
+ return make_error<StringError>(
+ formatv("File {0} is not a supported file type", Path),
+ inconvertibleErrorCode());
+
+ auto Result = MemoryBuffer::getFile(Path, -1LL, false);
+ if (!Result)
+ return make_error<StringError>(
+ formatv("File {0} could not be opened", Path), Result.getError());
+
+ IF.UnknownFile = std::move(*Result);
+ IF.PdbOrObj = IF.UnknownFile.get();
+ return std::move(IF);
}
PDBFile &InputFile::pdb() {
@@ -299,6 +310,25 @@ const object::COFFObjectFile &InputFile::obj() const {
return *PdbOrObj.get<object::COFFObjectFile *>();
}
+MemoryBuffer &InputFile::unknown() {
+ assert(isUnknown());
+ return *PdbOrObj.get<MemoryBuffer *>();
+}
+
+const MemoryBuffer &InputFile::unknown() const {
+ assert(isUnknown());
+ return *PdbOrObj.get<MemoryBuffer *>();
+}
+
+StringRef InputFile::getFilePath() const {
+ if (isPdb())
+ return pdb().getFilePath();
+ if (isObj())
+ return obj().getFileName();
+ assert(isUnknown());
+ return unknown().getBufferIdentifier();
+}
+
bool InputFile::hasTypes() const {
if (isPdb())
return pdb().hasPDBTpiStream();
@@ -323,6 +353,8 @@ bool InputFile::isObj() const {
return PdbOrObj.is<object::COFFObjectFile *>();
}
+bool InputFile::isUnknown() const { return PdbOrObj.is<MemoryBuffer *>(); }
+
codeview::LazyRandomTypeCollection &
InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) {
if (Types && Kind == kTypes)
diff --git a/contrib/llvm/tools/llvm-pdbutil/InputFile.h b/contrib/llvm/tools/llvm-pdbutil/InputFile.h
index 8063439133c2..552f3a3b2127 100644
--- a/contrib/llvm/tools/llvm-pdbutil/InputFile.h
+++ b/contrib/llvm/tools/llvm-pdbutil/InputFile.h
@@ -43,7 +43,8 @@ class InputFile {
std::unique_ptr<NativeSession> PdbSession;
object::OwningBinary<object::Binary> CoffObject;
- PointerUnion<PDBFile *, object::COFFObjectFile *> PdbOrObj;
+ std::unique_ptr<MemoryBuffer> UnknownFile;
+ PointerUnion3<PDBFile *, object::COFFObjectFile *, MemoryBuffer *> PdbOrObj;
using TypeCollectionPtr = std::unique_ptr<codeview::LazyRandomTypeCollection>;
@@ -58,12 +59,17 @@ public:
~InputFile();
InputFile(InputFile &&Other) = default;
- static Expected<InputFile> open(StringRef Path);
+ static Expected<InputFile> open(StringRef Path,
+ bool AllowUnknownFile = false);
PDBFile &pdb();
const PDBFile &pdb() const;
object::COFFObjectFile &obj();
const object::COFFObjectFile &obj() const;
+ MemoryBuffer &unknown();
+ const MemoryBuffer &unknown() const;
+
+ StringRef getFilePath() const;
bool hasTypes() const;
bool hasIds() const;
@@ -77,6 +83,7 @@ public:
bool isPdb() const;
bool isObj() const;
+ bool isUnknown() const;
};
class SymbolGroup {
diff --git a/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
index 40a0e46efd48..f4e38a32a511 100644
--- a/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -10,6 +10,7 @@
#include "MinimalSymbolDumper.h"
#include "FormatUtil.h"
+#include "InputFile.h"
#include "LinePrinter.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
@@ -18,6 +19,7 @@
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
@@ -450,6 +452,17 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FS) {
P.format(" `{0}`", FS.Name);
AutoIndent Indent(P, 7);
+ if (SymGroup) {
+ Expected<StringRef> FileName =
+ SymGroup->getNameFromStringTable(FS.ModFilenameOffset);
+ if (FileName) {
+ P.formatLine("type = {0}, file name = {1} ({2}), flags = {3}",
+ typeIndex(FS.Index), FS.ModFilenameOffset, *FileName,
+ formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
+ }
+ return Error::success();
+ }
+
P.formatLine("type = {0}, file name offset = {1}, flags = {2}",
typeIndex(FS.Index), FS.ModFilenameOffset,
formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
@@ -747,3 +760,9 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
P.formatLine("original type = {0}", UDT.Type);
return Error::success();
}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ UsingNamespaceSym &UN) {
+ P.format(" `{0}`", UN.Name);
+ return Error::success();
+}
diff --git a/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h b/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h
index d9e9861d5b30..1c26a85a4eaf 100644
--- a/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h
+++ b/contrib/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h
@@ -19,6 +19,7 @@ class LazyRandomTypeCollection;
namespace pdb {
class LinePrinter;
+class SymbolGroup;
class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks {
public:
@@ -26,11 +27,19 @@ public:
codeview::LazyRandomTypeCollection &Ids,
codeview::LazyRandomTypeCollection &Types)
: P(P), RecordBytes(RecordBytes), Ids(Ids), Types(Types) {}
+ MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
+ const SymbolGroup &SymGroup,
+ codeview::LazyRandomTypeCollection &Ids,
+ codeview::LazyRandomTypeCollection &Types)
+ : P(P), RecordBytes(RecordBytes), SymGroup(&SymGroup), Ids(Ids),
+ Types(Types) {}
Error visitSymbolBegin(codeview::CVSymbol &Record) override;
Error visitSymbolBegin(codeview::CVSymbol &Record, uint32_t Offset) override;
Error visitSymbolEnd(codeview::CVSymbol &Record) override;
+ void setSymbolGroup(const SymbolGroup *Group) { SymGroup = Group; }
+
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
virtual Error visitKnownRecord(codeview::CVSymbol &CVR, \
codeview::Name &Record) override;
@@ -45,6 +54,7 @@ private:
LinePrinter &P;
bool RecordBytes;
+ const SymbolGroup *SymGroup = nullptr;
codeview::LazyRandomTypeCollection &Ids;
codeview::LazyRandomTypeCollection &Types;
};
diff --git a/contrib/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
index fae89920e0b8..569bca7490fa 100644
--- a/contrib/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -303,8 +303,9 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
P.formatLine("unique name: `{0}`", Class.UniqueName);
P.formatLine("vtable: {0}, base list: {1}, field list: {2}",
Class.VTableShape, Class.DerivationList, Class.FieldList);
- P.formatLine("options: {0}",
- formatClassOptions(P.getIndentLevel(), Class.Options));
+ P.formatLine("options: {0}, sizeof {1}",
+ formatClassOptions(P.getIndentLevel(), Class.Options),
+ Class.Size);
return Error::success();
}
@@ -314,8 +315,9 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
if (Union.hasUniqueName())
P.formatLine("unique name: `{0}`", Union.UniqueName);
P.formatLine("field list: {0}", Union.FieldList);
- P.formatLine("options: {0}",
- formatClassOptions(P.getIndentLevel(), Union.Options));
+ P.formatLine("options: {0}, sizeof {1}",
+ formatClassOptions(P.getIndentLevel(), Union.Options),
+ Union.Size);
return Error::success();
}
@@ -467,6 +469,21 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
return Error::success();
}
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ PrecompRecord &Precomp) {
+ P.format(" start index = {0:X+}, types count = {1:X+}, signature = {2:X+},"
+ " precomp path = {3}",
+ Precomp.StartTypeIndex, Precomp.TypesCount, Precomp.Signature,
+ Precomp.PrecompFilePath);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ EndPrecompRecord &EP) {
+ P.format(" signature = {0:X+}", EP.Signature);
+ return Error::success();
+}
+
Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
NestedTypeRecord &Nested) {
P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
index 10b3d9ee7304..bcdecca81aec 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
@@ -87,7 +87,12 @@ StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) {
return "HRESULT";
case PDB_BuiltinType::BCD:
return "HRESULT";
- default:
- return "void";
+ case PDB_BuiltinType::Char16:
+ return "char16_t";
+ case PDB_BuiltinType::Char32:
+ return "char32_t";
+ case PDB_BuiltinType::None:
+ return "...";
}
+ llvm_unreachable("Unknown PDB_BuiltinType");
}
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
index 66c29fc5d4ee..a572522c8cd7 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
@@ -50,12 +50,9 @@ bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
uint32_t RelativeOffset = Item->getOffsetInParent();
CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
- // Since there is storage there, it should be set! However, this might
- // be an empty base, in which case it could extend outside the bounds of
- // the parent class.
+ // This might be an empty base, in which case it could extend outside the
+ // bounds of the parent class.
if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
- assert(UseMap.test(RelativeOffset));
-
// If there is any remaining padding in this class, and the offset of the
// new item is after the padding, then we must have just jumped over some
// padding. Print a padding row and then look for where the next block
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
index 65e8badbc99a..0d99c9b1245c 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
@@ -55,62 +55,73 @@ void CompilandDumper::start(const PDBSymbolCompiland &Symbol,
if (opts & Flags::Lines) {
const IPDBSession &Session = Symbol.getSession();
- auto Files = Session.getSourceFilesForCompiland(Symbol);
- Printer.Indent();
- while (auto File = Files->getNext()) {
- Printer.NewLine();
- WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName();
-
- auto Lines = Session.findLineNumbers(Symbol, *File);
+ if (auto Files = Session.getSourceFilesForCompiland(Symbol)) {
Printer.Indent();
- while (auto Line = Lines->getNext()) {
+ while (auto File = Files->getNext()) {
Printer.NewLine();
- uint32_t LineStart = Line->getLineNumber();
- uint32_t LineEnd = Line->getLineNumberEnd();
-
- Printer << "Line ";
- PDB_ColorItem StatementColor = Line->isStatement()
- ? PDB_ColorItem::Keyword
- : PDB_ColorItem::LiteralValue;
- WithColor(Printer, StatementColor).get() << LineStart;
- if (LineStart != LineEnd)
- WithColor(Printer, StatementColor).get() << " - " << LineEnd;
-
- uint32_t ColumnStart = Line->getColumnNumber();
- uint32_t ColumnEnd = Line->getColumnNumberEnd();
- if (ColumnStart != 0 || ColumnEnd != 0) {
- Printer << ", Column: ";
- WithColor(Printer, StatementColor).get() << ColumnStart;
- if (ColumnEnd != ColumnStart)
- WithColor(Printer, StatementColor).get() << " - " << ColumnEnd;
+ WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName();
+ if (File->getChecksumType() != PDB_Checksum::None) {
+ auto ChecksumType = File->getChecksumType();
+ auto ChecksumHexString = toHex(File->getChecksum());
+ WithColor(Printer, PDB_ColorItem::Comment).get()
+ << " (" << ChecksumType << ": " << ChecksumHexString << ")";
}
- Printer << ", Address: ";
- if (Line->getLength() > 0) {
- uint64_t AddrStart = Line->getVirtualAddress();
- uint64_t AddrEnd = AddrStart + Line->getLength() - 1;
- WithColor(Printer, PDB_ColorItem::Address).get()
+ auto Lines = Session.findLineNumbers(Symbol, *File);
+ if (!Lines)
+ continue;
+
+ Printer.Indent();
+ while (auto Line = Lines->getNext()) {
+ Printer.NewLine();
+ uint32_t LineStart = Line->getLineNumber();
+ uint32_t LineEnd = Line->getLineNumberEnd();
+
+ Printer << "Line ";
+ PDB_ColorItem StatementColor = Line->isStatement()
+ ? PDB_ColorItem::Keyword
+ : PDB_ColorItem::LiteralValue;
+ WithColor(Printer, StatementColor).get() << LineStart;
+ if (LineStart != LineEnd)
+ WithColor(Printer, StatementColor).get() << " - " << LineEnd;
+
+ uint32_t ColumnStart = Line->getColumnNumber();
+ uint32_t ColumnEnd = Line->getColumnNumberEnd();
+ if (ColumnStart != 0 || ColumnEnd != 0) {
+ Printer << ", Column: ";
+ WithColor(Printer, StatementColor).get() << ColumnStart;
+ if (ColumnEnd != ColumnStart)
+ WithColor(Printer, StatementColor).get() << " - " << ColumnEnd;
+ }
+
+ Printer << ", Address: ";
+ if (Line->getLength() > 0) {
+ uint64_t AddrStart = Line->getVirtualAddress();
+ uint64_t AddrEnd = AddrStart + Line->getLength() - 1;
+ WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(AddrStart, 10) << " - "
<< format_hex(AddrEnd, 10) << "]";
- Printer << " (" << Line->getLength() << " bytes)";
- } else {
- uint64_t AddrStart = Line->getVirtualAddress();
- WithColor(Printer, PDB_ColorItem::Address).get()
+ Printer << " (" << Line->getLength() << " bytes)";
+ } else {
+ uint64_t AddrStart = Line->getVirtualAddress();
+ WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(AddrStart, 10) << "] ";
- Printer << "(0 bytes)";
+ Printer << "(0 bytes)";
+ }
}
+ Printer.Unindent();
}
Printer.Unindent();
}
- Printer.Unindent();
}
if (opts & Flags::Children) {
- auto ChildrenEnum = Symbol.findAllChildren();
- Printer.Indent();
- while (auto Child = ChildrenEnum->getNext())
- Child->dump(*this);
- Printer.Unindent();
+ if (auto ChildrenEnum = Symbol.findAllChildren()) {
+ Printer.Indent();
+ while (auto Child = ChildrenEnum->getNext())
+ Child->dump(*this);
+ Printer.Unindent();
+ }
}
}
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
index fc40d90cee96..1270223b1c78 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
@@ -21,9 +21,10 @@ ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) {
- auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>();
- while (auto Var = Vars->getNext())
- Var->dump(*this);
+ if (auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>()) {
+ while (auto Var = Vars->getNext())
+ Var->dump(*this);
+ }
}
void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
@@ -34,7 +35,7 @@ void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
Printer.NewLine();
uint64_t Addr = Symbol.getVirtualAddress();
- Printer << "[";
+ Printer << "public [";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
Printer << "] ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
index 0bffc73f6c74..177d8a009a2b 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
@@ -189,6 +189,8 @@ void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
if (++Index < Arguments->getChildCount())
Printer << ", ";
}
+ if (Signature->isCVarArgs())
+ Printer << ", ...";
}
Printer << ")";
if (Symbol.isConstType())
@@ -250,6 +252,9 @@ void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
PointeeType->dump(*this);
Printer << (Symbol.isReference() ? "&" : "*");
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
}
}
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
index 0f6086395ad1..663a608fe429 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
@@ -128,14 +128,13 @@ filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
}
if (Comp)
- std::sort(Filtered.begin(), Filtered.end(), Comp);
+ llvm::sort(Filtered.begin(), Filtered.end(), Comp);
return Filtered;
}
TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void TypeDumper::start(const PDBSymbolExe &Exe) {
- auto Children = Exe.findAllChildren();
if (opts::pretty::Enums) {
if (auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>()) {
Printer.NewLine();
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
index ba3b4c8035c5..65443d6bca90 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
@@ -63,6 +63,9 @@ void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) {
PointeeType->dump(*this);
Printer << ((Symbol.isReference()) ? "&" : "*");
}
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
}
void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
diff --git a/contrib/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp b/contrib/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp
index 4884fc8ee5a4..ddac8cf0da4a 100644
--- a/contrib/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp
@@ -169,6 +169,9 @@ void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
}
void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
@@ -189,6 +192,9 @@ void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << " const ";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile ";
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict ";
}
void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) {
diff --git a/contrib/llvm/tools/llvm-pdbutil/StreamUtil.cpp b/contrib/llvm/tools/llvm-pdbutil/StreamUtil.cpp
index 991c99aa8686..367d947d25ee 100644
--- a/contrib/llvm/tools/llvm-pdbutil/StreamUtil.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/StreamUtil.cpp
@@ -49,16 +49,9 @@ StreamInfo StreamInfo::createModuleStream(StringRef Module,
return Result;
}
-static inline StreamInfo otherStream(StringRef Label, uint32_t Idx) {
- return StreamInfo::createStream(StreamPurpose::Other, Label, Idx);
-}
-
-static inline StreamInfo namedStream(StringRef Label, uint32_t Idx) {
- return StreamInfo::createStream(StreamPurpose::NamedStream, Label, Idx);
-}
-
-static inline StreamInfo symbolStream(StringRef Label, uint32_t Idx) {
- return StreamInfo::createStream(StreamPurpose::Symbols, Label, Idx);
+static inline StreamInfo stream(StreamPurpose Purpose, StringRef Label,
+ uint32_t Idx) {
+ return StreamInfo::createStream(Purpose, Label, Idx);
}
static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,
@@ -105,60 +98,75 @@ void llvm::pdb::discoverStreamPurposes(PDBFile &File,
Streams.resize(StreamCount);
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
if (StreamIdx == OldMSFDirectory)
- Streams[StreamIdx] = otherStream("Old MSF Directory", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Old MSF Directory", StreamIdx);
else if (StreamIdx == StreamPDB)
- Streams[StreamIdx] = otherStream("PDB Stream", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::PDB, "PDB Stream", StreamIdx);
else if (StreamIdx == StreamDBI)
- Streams[StreamIdx] = otherStream("DBI Stream", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::DBI, "DBI Stream", StreamIdx);
else if (StreamIdx == StreamTPI)
- Streams[StreamIdx] = otherStream("TPI Stream", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::TPI, "TPI Stream", StreamIdx);
else if (StreamIdx == StreamIPI)
- Streams[StreamIdx] = otherStream("IPI Stream", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::IPI, "IPI Stream", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
- Streams[StreamIdx] = otherStream("Global Symbol Hash", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::GlobalHash, "Global Symbol Hash", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
- Streams[StreamIdx] = otherStream("Public Symbol Hash", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::PublicHash, "Public Symbol Hash", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
- Streams[StreamIdx] = symbolStream("Symbol Records", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Symbols, "Symbol Records", StreamIdx);
else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
- Streams[StreamIdx] = otherStream("TPI Hash", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::TpiHash, "TPI Hash", StreamIdx);
else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
- Streams[StreamIdx] = otherStream("TPI Aux Hash", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "TPI Aux Hash", StreamIdx);
else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
- Streams[StreamIdx] = otherStream("IPI Hash", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::IpiHash, "IPI Hash", StreamIdx);
else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
- Streams[StreamIdx] = otherStream("IPI Aux Hash", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "IPI Aux Hash", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
- Streams[StreamIdx] = otherStream("Exception Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Exception Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
- Streams[StreamIdx] = otherStream("Fixup Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Fixup Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
- Streams[StreamIdx] = otherStream("FPO Data", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "FPO Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
- Streams[StreamIdx] = otherStream("New FPO Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "New FPO Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
- Streams[StreamIdx] = otherStream("Omap From Source Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Omap From Source Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
- Streams[StreamIdx] = otherStream("Omap To Source Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Omap To Source Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
- Streams[StreamIdx] = otherStream("Pdata", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "Pdata", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
- Streams[StreamIdx] = otherStream("Section Header Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Section Header Data", StreamIdx);
else if (Dbi &&
StreamIdx ==
Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
- Streams[StreamIdx] =
- otherStream("Section Header Original Data", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::Other,
+ "Section Header Original Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
- Streams[StreamIdx] = otherStream("Token Rid Data", StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Token Rid Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
- Streams[StreamIdx] = otherStream("Xdata", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "Xdata", StreamIdx);
else {
auto ModIter = ModStreams.find(StreamIdx);
auto NSIter = NamedStreams.find(StreamIdx);
@@ -167,9 +175,10 @@ void llvm::pdb::discoverStreamPurposes(PDBFile &File,
moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx,
ModIter->second.Modi);
} else if (NSIter != NamedStreams.end()) {
- Streams[StreamIdx] = namedStream(NSIter->second, StreamIdx);
+ Streams[StreamIdx] =
+ stream(StreamPurpose::NamedStream, NSIter->second, StreamIdx);
} else {
- Streams[StreamIdx] = otherStream("???", StreamIdx);
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "???", StreamIdx);
}
}
}
diff --git a/contrib/llvm/tools/llvm-pdbutil/StreamUtil.h b/contrib/llvm/tools/llvm-pdbutil/StreamUtil.h
index 443267ca3290..0e2e80707361 100644
--- a/contrib/llvm/tools/llvm-pdbutil/StreamUtil.h
+++ b/contrib/llvm/tools/llvm-pdbutil/StreamUtil.h
@@ -19,7 +19,20 @@
namespace llvm {
namespace pdb {
class PDBFile;
-enum class StreamPurpose { NamedStream, ModuleStream, Symbols, Other };
+enum class StreamPurpose {
+ NamedStream,
+ ModuleStream,
+ Symbols,
+ PDB,
+ DBI,
+ TPI,
+ IPI,
+ GlobalHash,
+ PublicHash,
+ TpiHash,
+ IpiHash,
+ Other
+};
struct StreamInfo {
public:
diff --git a/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 089f7256536f..5b0d21f83db7 100644
--- a/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -15,15 +15,18 @@
#include "Analyze.h"
#include "BytesOutputStyle.h"
-#include "Diff.h"
#include "DumpOutputStyle.h"
+#include "ExplainOutputStyle.h"
#include "InputFile.h"
#include "LinePrinter.h"
#include "OutputStyle.h"
+#include "PrettyClassDefinitionDumper.h"
#include "PrettyCompilandDumper.h"
+#include "PrettyEnumDumper.h"
#include "PrettyExternalSymbolDumper.h"
#include "PrettyFunctionDumper.h"
#include "PrettyTypeDumper.h"
+#include "PrettyTypedefDumper.h"
#include "PrettyVariableDumper.h"
#include "YAMLOutputStyle.h"
@@ -45,10 +48,12 @@
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
@@ -63,7 +68,11 @@
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
@@ -71,6 +80,7 @@
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -82,7 +92,6 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
-
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::msf;
@@ -97,8 +106,6 @@ cl::SubCommand
PrettySubcommand("pretty",
"Dump semantic information about types and symbols");
-cl::SubCommand DiffSubcommand("diff", "Diff the contents of 2 PDB files");
-
cl::SubCommand
YamlToPdbSubcommand("yaml2pdb",
"Generate a PDB file from a YAML description");
@@ -113,6 +120,12 @@ cl::SubCommand
cl::SubCommand MergeSubcommand("merge",
"Merge multiple PDBs into a single PDB");
+cl::SubCommand ExplainSubcommand("explain",
+ "Explain the meaning of a file offset");
+
+cl::SubCommand ExportSubcommand("export",
+ "Write binary data from a stream to a file");
+
cl::OptionCategory TypeCategory("Symbol Type Options");
cl::OptionCategory FilterCategory("Filtering and Sorting Options");
cl::OptionCategory OtherOptions("Other Options");
@@ -147,6 +160,19 @@ cl::list<std::string> InputFilenames(cl::Positional,
cl::desc("<input PDB files>"),
cl::OneOrMore, cl::sub(PrettySubcommand));
+cl::opt<bool> InjectedSources("injected-sources",
+ cl::desc("Display injected sources"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::opt<bool> ShowInjectedSourceContent(
+ "injected-source-content",
+ cl::desc("When displaying an injected source, display the file content"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+
+cl::list<std::string> WithName(
+ "with-name",
+ cl::desc("Display any symbol or type with the specified exact name"),
+ cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand));
+
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Symbols("module-syms",
@@ -286,44 +312,6 @@ cl::opt<bool> NoEnumDefs("no-enum-definitions",
cl::cat(FilterCategory), cl::sub(PrettySubcommand));
}
-namespace diff {
-cl::opt<bool> PrintValueColumns(
- "values", cl::init(true),
- cl::desc("Print one column for each PDB with the field value"),
- cl::Optional, cl::sub(DiffSubcommand));
-cl::opt<bool>
- PrintResultColumn("result", cl::init(false),
- cl::desc("Print a column with the result status"),
- cl::Optional, cl::sub(DiffSubcommand));
-
-cl::list<std::string>
- RawModiEquivalences("modi-equivalence", cl::ZeroOrMore,
- cl::value_desc("left,right"),
- cl::desc("Modules with the specified indices will be "
- "treated as referring to the same module"),
- cl::sub(DiffSubcommand));
-
-cl::opt<std::string> LeftRoot(
- "left-bin-root", cl::Optional,
- cl::desc("Treats the specified path as the root of the tree containing "
- "binaries referenced by the left PDB. The root is stripped from "
- "embedded paths when doing equality comparisons."),
- cl::sub(DiffSubcommand));
-cl::opt<std::string> RightRoot(
- "right-bin-root", cl::Optional,
- cl::desc("Treats the specified path as the root of the tree containing "
- "binaries referenced by the right PDB. The root is stripped from "
- "embedded paths when doing equality comparisons"),
- cl::sub(DiffSubcommand));
-
-cl::opt<std::string> Left(cl::Positional, cl::desc("<left>"),
- cl::sub(DiffSubcommand));
-cl::opt<std::string> Right(cl::Positional, cl::desc("<right>"),
- cl::sub(DiffSubcommand));
-
-llvm::DenseMap<uint32_t, uint32_t> Equivalences;
-}
-
cl::OptionCategory FileOptions("Module & File Options");
namespace bytes {
@@ -482,6 +470,10 @@ cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
cl::opt<bool> DumpPublicExtras("public-extras",
cl::desc("dump Publics hashes and address maps"),
cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool>
+ DumpGSIRecords("gsi-records",
+ cl::desc("dump public / global common record stream"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
@@ -525,8 +517,16 @@ cl::opt<bool> JustMyCode("jmc", cl::Optional,
cl::cat(FileOptions), cl::sub(DumpSubcommand));
// MISCELLANEOUS OPTIONS
+cl::opt<bool> DumpNamedStreams("named-streams",
+ cl::desc("dump PDB named stream table"),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+
cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpStringTableDetails("string-table-details",
+ cl::desc("dump PDB String Table Details"),
+ cl::cat(MiscOptions),
+ cl::sub(DumpSubcommand));
cl::opt<bool> DumpSectionContribs("section-contribs",
cl::desc("dump section contributions"),
@@ -629,6 +629,47 @@ cl::opt<std::string>
PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
cl::sub(MergeSubcommand));
}
+
+namespace explain {
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(ExplainSubcommand));
+
+cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
+ cl::sub(ExplainSubcommand), cl::OneOrMore);
+
+cl::opt<InputFileType> InputType(
+ "input-type", cl::desc("Specify how to interpret the input file"),
+ cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
+ cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
+ "Treat input as a PDB file (default)"),
+ clEnumValN(InputFileType::PDBStream, "pdb-stream",
+ "Treat input as raw contents of PDB stream"),
+ clEnumValN(InputFileType::DBIStream, "dbi-stream",
+ "Treat input as raw contents of DBI stream"),
+ clEnumValN(InputFileType::Names, "names-stream",
+ "Treat input as raw contents of /names named stream"),
+ clEnumValN(InputFileType::ModuleStream, "mod-stream",
+ "Treat input as raw contents of a module stream")));
+} // namespace explain
+
+namespace exportstream {
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(ExportSubcommand));
+cl::opt<std::string> OutputFile("out",
+ cl::desc("The file to write the stream to"),
+ cl::Required, cl::sub(ExportSubcommand));
+cl::opt<std::string>
+ Stream("stream", cl::Required,
+ cl::desc("The index or name of the stream whose contents to export"),
+ cl::sub(ExportSubcommand));
+cl::opt<bool> ForceName("name",
+ cl::desc("Force the interpretation of -stream as a "
+ "string, even if it is a valid integer"),
+ cl::sub(ExportSubcommand), cl::Optional,
+ cl::init(false));
+} // namespace exportstream
}
static ExitOnError ExitOnErr;
@@ -761,7 +802,6 @@ static void pdb2Yaml(StringRef Path) {
}
static void dumpRaw(StringRef Path) {
-
InputFile IF = ExitOnErr(InputFile::open(Path));
auto O = llvm::make_unique<DumpOutputStyle>(IF);
@@ -785,18 +825,6 @@ static void dumpAnalysis(StringRef Path) {
ExitOnErr(O->dump());
}
-static void diff(StringRef Path1, StringRef Path2) {
- std::unique_ptr<IPDBSession> Session1;
- std::unique_ptr<IPDBSession> Session2;
-
- auto &File1 = loadPDB(Path1, Session1);
- auto &File2 = loadPDB(Path2, Session2);
-
- auto O = llvm::make_unique<DiffStyle>(File1, File2);
-
- ExitOnErr(O->dump());
-}
-
bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
if (SymTypes.empty())
return true;
@@ -840,6 +868,62 @@ bool opts::pretty::compareDataSymbols(
return getTypeLength(*F1) > getTypeLength(*F2);
}
+static std::string stringOr(std::string Str, std::string IfEmpty) {
+ return (Str.empty()) ? IfEmpty : Str;
+}
+
+static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {
+ auto Sources = Session.getInjectedSources();
+ if (0 == Sources->getChildCount()) {
+ Printer.printLine("There are no injected sources.");
+ return;
+ }
+
+ while (auto IS = Sources->getNext()) {
+ Printer.NewLine();
+ std::string File = stringOr(IS->getFileName(), "<null>");
+ uint64_t Size = IS->getCodeByteSize();
+ std::string Obj = stringOr(IS->getObjectFileName(), "<null>");
+ std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");
+ uint32_t CRC = IS->getCrc32();
+
+ std::string CompressionStr;
+ llvm::raw_string_ostream Stream(CompressionStr);
+ Stream << IS->getCompression();
+ WithColor(Printer, PDB_ColorItem::Path).get() << File;
+ Printer << " (";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;
+ Printer << " bytes): ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::Path).get() << Obj;
+ Printer << ", ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::Path).get() << VFName;
+ Printer << ", ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;
+ Printer << ", ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Stream.str();
+
+ if (!opts::pretty::ShowInjectedSourceContent)
+ continue;
+
+ // Set the indent level to 0 when printing file content.
+ int Indent = Printer.getIndentLevel();
+ Printer.Unindent(Indent);
+
+ Printer.printLine(IS->getCode());
+
+ // Re-indent back to the original level.
+ Printer.Indent(Indent);
+ }
+}
+
static void dumpPretty(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
@@ -857,6 +941,8 @@ static void dumpPretty(StringRef Path) {
LinePrinter Printer(2, UseColor, Stream);
auto GlobalScope(Session->getGlobalScope());
+ if (!GlobalScope)
+ return;
std::string FileName(GlobalScope->getSymbolsFileName());
WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
@@ -889,19 +975,96 @@ static void dumpPretty(StringRef Path) {
outs() << "HasPrivateSymbols ";
Printer.Unindent();
+ if (!opts::pretty::WithName.empty()) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+ << "---SYMBOLS & TYPES BY NAME---";
+
+ for (StringRef Name : opts::pretty::WithName) {
+ auto Symbols = GlobalScope->findChildren(
+ PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
+ if (!Symbols || Symbols->getChildCount() == 0) {
+ Printer.formatLine("[not found] - {0}", Name);
+ continue;
+ }
+ Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
+ Name);
+
+ AutoIndent Indent(Printer);
+ Printer.NewLine();
+
+ while (auto Symbol = Symbols->getNext()) {
+ switch (Symbol->getSymTag()) {
+ case PDB_SymType::Typedef: {
+ TypedefDumper TD(Printer);
+ std::unique_ptr<PDBSymbolTypeTypedef> T =
+ llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
+ TD.start(*T);
+ break;
+ }
+ case PDB_SymType::Enum: {
+ EnumDumper ED(Printer);
+ std::unique_ptr<PDBSymbolTypeEnum> E =
+ llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
+ ED.start(*E);
+ break;
+ }
+ case PDB_SymType::UDT: {
+ ClassDefinitionDumper CD(Printer);
+ std::unique_ptr<PDBSymbolTypeUDT> C =
+ llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
+ CD.start(*C);
+ break;
+ }
+ case PDB_SymType::BaseClass:
+ case PDB_SymType::Friend: {
+ TypeDumper TD(Printer);
+ Symbol->dump(TD);
+ break;
+ }
+ case PDB_SymType::Function: {
+ FunctionDumper FD(Printer);
+ std::unique_ptr<PDBSymbolFunc> F =
+ llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
+ FD.start(*F, FunctionDumper::PointerType::None);
+ break;
+ }
+ case PDB_SymType::Data: {
+ VariableDumper VD(Printer);
+ std::unique_ptr<PDBSymbolData> D =
+ llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
+ VD.start(*D);
+ break;
+ }
+ case PDB_SymType::PublicSymbol: {
+ ExternalSymbolDumper ED(Printer);
+ std::unique_ptr<PDBSymbolPublicSymbol> PS =
+ llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
+ ED.dump(*PS);
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected symbol tag!");
+ }
+ }
+ }
+ llvm::outs().flush();
+ }
+
if (opts::pretty::Compilands) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get()
<< "---COMPILANDS---";
- Printer.Indent();
- auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
- CompilandDumper Dumper(Printer);
- CompilandDumpFlags options = CompilandDumper::Flags::None;
- if (opts::pretty::Lines)
- options = options | CompilandDumper::Flags::Lines;
- while (auto Compiland = Compilands->getNext())
- Dumper.start(*Compiland, options);
- Printer.Unindent();
+ if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
+ Printer.Indent();
+ CompilandDumper Dumper(Printer);
+ CompilandDumpFlags options = CompilandDumper::Flags::None;
+ if (opts::pretty::Lines)
+ options = options | CompilandDumper::Flags::Lines;
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, options);
+ Printer.Unindent();
+ }
}
if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs) {
@@ -916,12 +1079,13 @@ static void dumpPretty(StringRef Path) {
if (opts::pretty::Symbols) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
- Printer.Indent();
- auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
- CompilandDumper Dumper(Printer);
- while (auto Compiland = Compilands->getNext())
- Dumper.start(*Compiland, true);
- Printer.Unindent();
+ if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
+ Printer.Indent();
+ CompilandDumper Dumper(Printer);
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, true);
+ Printer.Unindent();
+ }
}
if (opts::pretty::Globals) {
@@ -929,45 +1093,49 @@ static void dumpPretty(StringRef Path) {
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
Printer.Indent();
if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
- FunctionDumper Dumper(Printer);
- auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
- if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
- while (auto Function = Functions->getNext()) {
- Printer.NewLine();
- Dumper.start(*Function, FunctionDumper::PointerType::None);
- }
- } else {
- std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
- while (auto Func = Functions->getNext())
- Funcs.push_back(std::move(Func));
- std::sort(Funcs.begin(), Funcs.end(),
- opts::pretty::compareFunctionSymbols);
- for (const auto &Func : Funcs) {
- Printer.NewLine();
- Dumper.start(*Func, FunctionDumper::PointerType::None);
+ if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {
+ FunctionDumper Dumper(Printer);
+ if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
+ while (auto Function = Functions->getNext()) {
+ Printer.NewLine();
+ Dumper.start(*Function, FunctionDumper::PointerType::None);
+ }
+ } else {
+ std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
+ while (auto Func = Functions->getNext())
+ Funcs.push_back(std::move(Func));
+ llvm::sort(Funcs.begin(), Funcs.end(),
+ opts::pretty::compareFunctionSymbols);
+ for (const auto &Func : Funcs) {
+ Printer.NewLine();
+ Dumper.start(*Func, FunctionDumper::PointerType::None);
+ }
}
}
}
if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
- auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
- VariableDumper Dumper(Printer);
- if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
- while (auto Var = Vars->getNext())
- Dumper.start(*Var);
- } else {
- std::vector<std::unique_ptr<PDBSymbolData>> Datas;
- while (auto Var = Vars->getNext())
- Datas.push_back(std::move(Var));
- std::sort(Datas.begin(), Datas.end(), opts::pretty::compareDataSymbols);
- for (const auto &Var : Datas)
- Dumper.start(*Var);
+ if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {
+ VariableDumper Dumper(Printer);
+ if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
+ while (auto Var = Vars->getNext())
+ Dumper.start(*Var);
+ } else {
+ std::vector<std::unique_ptr<PDBSymbolData>> Datas;
+ while (auto Var = Vars->getNext())
+ Datas.push_back(std::move(Var));
+ llvm::sort(Datas.begin(), Datas.end(),
+ opts::pretty::compareDataSymbols);
+ for (const auto &Var : Datas)
+ Dumper.start(*Var);
+ }
}
}
if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
- auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
- CompilandDumper Dumper(Printer);
- while (auto Thunk = Thunks->getNext())
- Dumper.dump(*Thunk);
+ if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {
+ CompilandDumper Dumper(Printer);
+ while (auto Thunk = Thunks->getNext())
+ Dumper.dump(*Thunk);
+ }
}
Printer.Unindent();
}
@@ -981,6 +1149,19 @@ static void dumpPretty(StringRef Path) {
if (opts::pretty::Lines) {
Printer.NewLine();
}
+ if (opts::pretty::InjectedSources) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+ << "---INJECTED SOURCES---";
+ AutoIndent Indent1(Printer);
+
+ if (ReaderType == PDB_ReaderType::Native)
+ Printer.printLine(
+ "Injected sources are not supported with the native reader.");
+ else
+ dumpInjectedSources(Printer, *Session);
+ }
+
outs().flush();
}
@@ -1033,6 +1214,58 @@ static void mergePdbs() {
ExitOnErr(Builder.commit(OutFile));
}
+static void explain() {
+ std::unique_ptr<IPDBSession> Session;
+ InputFile IF =
+ ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
+
+ for (uint64_t Off : opts::explain::Offsets) {
+ auto O = llvm::make_unique<ExplainOutputStyle>(IF, Off);
+
+ ExitOnErr(O->dump());
+ }
+}
+
+static void exportStream() {
+ std::unique_ptr<IPDBSession> Session;
+ PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
+
+ std::unique_ptr<MappedBlockStream> SourceStream;
+ uint32_t Index = 0;
+ bool Success = false;
+ std::string OutFileName = opts::exportstream::OutputFile;
+
+ if (!opts::exportstream::ForceName) {
+ // First try to parse it as an integer, if it fails fall back to treating it
+ // as a named stream.
+ if (to_integer(opts::exportstream::Stream, Index)) {
+ if (Index >= File.getNumStreams()) {
+ errs() << "Error: " << Index << " is not a valid stream index.\n";
+ exit(1);
+ }
+ Success = true;
+ outs() << "Dumping contents of stream index " << Index << " to file "
+ << OutFileName << ".\n";
+ }
+ }
+
+ if (!Success) {
+ InfoStream &IS = cantFail(File.getPDBInfoStream());
+ Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
+ outs() << "Dumping contents of stream '" << opts::exportstream::Stream
+ << "' (index " << Index << ") to file " << OutFileName << ".\n";
+ }
+
+ SourceStream = MappedBlockStream::createIndexedStream(
+ File.getMsfLayout(), File.getMsfBuffer(), Index, File.getAllocator());
+ auto OutFile = ExitOnErr(
+ FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
+ FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
+ BinaryStreamWriter Writer(DestStream);
+ ExitOnErr(Writer.writeStreamRef(*SourceStream));
+ ExitOnErr(DestStream.commit());
+}
+
static bool parseRange(StringRef Str,
Optional<opts::bytes::NumberRange> &Parsed) {
if (Str.empty())
@@ -1064,21 +1297,11 @@ static void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {
Chunks.push_back(opts::ModuleSubsection::All);
}
-int main(int argc_, const char *argv_[]) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv_[0]);
- PrettyStackTraceProgram X(argc_, argv_);
-
+int main(int Argc, const char **Argv) {
+ InitLLVM X(Argc, Argv);
ExitOnErr.setBanner("llvm-pdbutil: ");
- SmallVector<const char *, 256> argv;
- SpecificBumpPtrAllocator<char> ArgAllocator;
- ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
- argv, makeArrayRef(argv_, argc_), ArgAllocator)));
-
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
-
- cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
+ cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
if (opts::BytesSubcommand) {
if (!parseRange(opts::bytes::DumpBlockRangeOpt,
@@ -1113,6 +1336,7 @@ int main(int argc_, const char *argv_[]) {
opts::dump::DumpStreams = true;
opts::dump::DumpStreamBlocks = true;
opts::dump::DumpStringTable = true;
+ opts::dump::DumpStringTableDetails = true;
opts::dump::DumpSummary = true;
opts::dump::DumpSymbols = true;
opts::dump::DumpSymbolStats = true;
@@ -1146,11 +1370,6 @@ int main(int argc_, const char *argv_[]) {
if (opts::pdb2yaml::DumpModules)
opts::pdb2yaml::DbiStream = true;
}
- if (opts::DiffSubcommand) {
- if (!opts::diff::PrintResultColumn && !opts::diff::PrintValueColumns) {
- llvm::errs() << "WARNING: No diff columns specified\n";
- }
- }
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
@@ -1205,27 +1424,16 @@ int main(int argc_, const char *argv_[]) {
llvm::for_each(opts::dump::InputFilenames, dumpRaw);
} else if (opts::BytesSubcommand) {
llvm::for_each(opts::bytes::InputFilenames, dumpBytes);
- } else if (opts::DiffSubcommand) {
- for (StringRef S : opts::diff::RawModiEquivalences) {
- StringRef Left;
- StringRef Right;
- std::tie(Left, Right) = S.split(',');
- uint32_t X, Y;
- if (!to_integer(Left, X) || !to_integer(Right, Y)) {
- errs() << formatv("invalid value {0} specified for modi equivalence\n",
- S);
- exit(1);
- }
- opts::diff::Equivalences[X] = Y;
- }
-
- diff(opts::diff::Left, opts::diff::Right);
} else if (opts::MergeSubcommand) {
if (opts::merge::InputFilenames.size() < 2) {
errs() << "merge subcommand requires at least 2 input files.\n";
exit(1);
}
mergePdbs();
+ } else if (opts::ExplainSubcommand) {
+ explain();
+ } else if (opts::ExportSubcommand) {
+ exportStream();
}
outs().flush();
diff --git a/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
index 3ce03d5880af..7496adaeb62f 100644
--- a/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/contrib/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -75,6 +75,8 @@ bool compareFunctionSymbols(
bool compareDataSymbols(const std::unique_ptr<llvm::pdb::PDBSymbolData> &F1,
const std::unique_ptr<llvm::pdb::PDBSymbolData> &F2);
+extern llvm::cl::list<std::string> WithName;
+
extern llvm::cl::opt<bool> Compilands;
extern llvm::cl::opt<bool> Symbols;
extern llvm::cl::opt<bool> Globals;
@@ -142,7 +144,9 @@ extern llvm::cl::opt<bool> DumpLines;
extern llvm::cl::opt<bool> DumpInlineeLines;
extern llvm::cl::opt<bool> DumpXmi;
extern llvm::cl::opt<bool> DumpXme;
+extern llvm::cl::opt<bool> DumpNamedStreams;
extern llvm::cl::opt<bool> DumpStringTable;
+extern llvm::cl::opt<bool> DumpStringTableDetails;
extern llvm::cl::opt<bool> DumpTypes;
extern llvm::cl::opt<bool> DumpTypeData;
extern llvm::cl::opt<bool> DumpTypeExtras;
@@ -158,6 +162,7 @@ extern llvm::cl::opt<uint32_t> DumpModi;
extern llvm::cl::opt<bool> JustMyCode;
extern llvm::cl::opt<bool> DumpSymbols;
extern llvm::cl::opt<bool> DumpSymRecordBytes;
+extern llvm::cl::opt<bool> DumpGSIRecords;
extern llvm::cl::opt<bool> DumpGlobals;
extern llvm::cl::opt<bool> DumpGlobalExtras;
extern llvm::cl::opt<bool> DumpPublics;
@@ -187,13 +192,19 @@ extern llvm::cl::list<ModuleSubsection> DumpModuleSubsections;
extern llvm::cl::opt<bool> DumpModuleSyms;
} // namespace pdb2yaml
-namespace diff {
-extern llvm::cl::opt<bool> PrintValueColumns;
-extern llvm::cl::opt<bool> PrintResultColumn;
-extern llvm::DenseMap<uint32_t, uint32_t> Equivalences;
-extern llvm::cl::opt<std::string> LeftRoot;
-extern llvm::cl::opt<std::string> RightRoot;
-} // namespace diff
+namespace explain {
+enum class InputFileType { PDBFile, PDBStream, DBIStream, Names, ModuleStream };
+
+extern llvm::cl::list<std::string> InputFilename;
+extern llvm::cl::list<uint64_t> Offsets;
+extern llvm::cl::opt<InputFileType> InputType;
+} // namespace explain
+
+namespace exportstream {
+extern llvm::cl::opt<std::string> OutputFile;
+extern llvm::cl::opt<std::string> Stream;
+extern llvm::cl::opt<bool> ForceName;
+} // namespace exportstream
}
#endif
diff --git a/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp b/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 9afd0ae92eae..1a0b9e127bbc 100644
--- a/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -24,32 +24,42 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
-enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
+enum ProfileFormat {
+ PF_None = 0,
+ PF_Text,
+ PF_Compact_Binary,
+ PF_GCC,
+ PF_Binary
+};
-static void warn(StringRef Prefix, Twine Message, std::string Whence = "",
+static void warn(Twine Message, std::string Whence = "",
std::string Hint = "") {
- errs() << Prefix;
+ WithColor::warning();
if (!Whence.empty())
errs() << Whence << ": ";
errs() << Message << "\n";
if (!Hint.empty())
- errs() << Hint << "\n";
+ WithColor::note() << Hint << "\n";
}
static void exitWithError(Twine Message, std::string Whence = "",
std::string Hint = "") {
- warn("error: ", Message, Whence, Hint);
+ WithColor::error();
+ if (!Whence.empty())
+ errs() << Whence << ": ";
+ errs() << Message << "\n";
+ if (!Hint.empty())
+ WithColor::note() << Hint << "\n";
::exit(1);
}
@@ -232,7 +242,8 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
if (OutputFilename.compare("-") == 0)
exitWithError("Cannot write indexed profdata format to stdout.");
- if (OutputFormat != PF_Binary && OutputFormat != PF_Text)
+ if (OutputFormat != PF_Binary && OutputFormat != PF_Compact_Binary &&
+ OutputFormat != PF_Text)
exitWithError("Unknown format is specified.");
std::error_code EC;
@@ -298,7 +309,7 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
if (isFatalError(IPE))
exitWithError(make_error<InstrProfError>(IPE), WC->ErrWhence);
else
- warn("warning: ", toString(make_error<InstrProfError>(IPE)),
+ warn(toString(make_error<InstrProfError>(IPE)),
WC->ErrWhence);
}
@@ -312,8 +323,8 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
}
static sampleprof::SampleProfileFormat FormatMap[] = {
- sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Binary,
- sampleprof::SPF_GCC};
+ sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Compact_Binary,
+ sampleprof::SPF_GCC, sampleprof::SPF_Binary};
static void mergeSampleProfile(const WeightedFileVector &Inputs,
StringRef OutputFilename,
@@ -462,6 +473,8 @@ static int merge_main(int argc, const char *argv[]) {
cl::opt<ProfileFormat> OutputFormat(
cl::desc("Format of output profile"), cl::init(PF_Binary),
cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding (default)"),
+ clEnumValN(PF_Compact_Binary, "compbinary",
+ "Compact binary encoding"),
clEnumValN(PF_Text, "text", "Text encoding"),
clEnumValN(PF_GCC, "gcc",
"GCC encoding (only meaningful for -sample)")));
@@ -787,7 +800,7 @@ static int show_main(int argc, const char *argv[]) {
exitWithErrorCode(EC, OutputFilename);
if (ShowAllFunctions && !ShowFunction.empty())
- errs() << "warning: -function argument ignored: showing all functions\n";
+ WithColor::warning() << "-function argument ignored: showing all functions\n";
std::vector<uint32_t> Cutoffs(DetailedSummaryCutoffs.begin(),
DetailedSummaryCutoffs.end());
@@ -802,10 +815,7 @@ static int show_main(int argc, const char *argv[]) {
}
int main(int argc, const char *argv[]) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
StringRef ProgName(sys::path::filename(argv[0]));
if (argc > 1) {
diff --git a/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
index 4417aa60fe90..51128f113c4c 100644
--- a/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -323,10 +323,10 @@ inline void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset,
template <typename ET>
class PrinterContext {
- typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym;
- typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr;
- typedef typename object::ELFFile<ET>::Elf_Rel Elf_Rel;
- typedef typename object::ELFFile<ET>::Elf_Word Elf_Word;
+ typedef typename ET::Sym Elf_Sym;
+ typedef typename ET::Shdr Elf_Shdr;
+ typedef typename ET::Rel Elf_Rel;
+ typedef typename ET::Word Elf_Word;
ScopedPrinter &SW;
const object::ELFFile<ET> *ELF;
@@ -386,7 +386,7 @@ PrinterContext<ET>::FunctionAtAddress(unsigned Section,
}
template <typename ET>
-const typename object::ELFFile<ET>::Elf_Shdr *
+const typename ET::Shdr *
PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
off_t IndexTableOffset) const {
/// Iterate through the sections, searching for the relocation section
@@ -410,7 +410,7 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
if (R.r_offset != static_cast<unsigned>(IndexTableOffset))
continue;
- typename object::ELFFile<ET>::Elf_Rela RelA;
+ typename ET::Rela RelA;
RelA.r_offset = R.r_offset;
RelA.r_info = R.r_info;
RelA.r_addend = 0;
@@ -586,4 +586,3 @@ void PrinterContext<ET>::PrintUnwindInformation() const {
}
#endif
-
diff --git a/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 1a033b1eb42e..a90840b22c8d 100644
--- a/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -33,7 +33,7 @@
// (.pdata) entry.
//
// The exception data contains information about the frame setup, all of the
-// epilouge scopes (for functions for which there are multiple exit points) and
+// epilogue scopes (for functions for which there are multiple exit points) and
// the associated exception handler. Additionally, the entry contains byte-code
// describing how to unwind the function (c.f. Decoder::decodeOpcodes).
//
diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
index 0e76e75c085d..0ed4ccd09f6f 100644
--- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the COFF-specific dumper for llvm-readobj.
+/// This file implements the COFF-specific dumper for llvm-readobj.
///
//===----------------------------------------------------------------------===//
@@ -67,6 +67,8 @@ struct LoadConfigTables {
uint32_t GuardFlags = 0;
uint64_t GuardFidTableVA = 0;
uint64_t GuardFidTableCount = 0;
+ uint64_t GuardLJmpTableVA = 0;
+ uint64_t GuardLJmpTableCount = 0;
};
class COFFDumper : public ObjDumper {
@@ -242,7 +244,7 @@ std::error_code createCOFFDumper(const object::ObjectFile *Obj,
} // namespace llvm
-// Given a a section and an offset into this section the function returns the
+// Given a section and an offset into this section the function returns the
// symbol used for the relocation at the offset.
std::error_code COFFDumper::resolveSymbol(const coff_section *Section,
uint64_t Offset, SymbolRef &Sym) {
@@ -605,8 +607,8 @@ void COFFDumper::cacheRelocations() {
RelocMap[Section].push_back(Reloc);
// Sort relocations by address.
- std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
- relocAddressLess);
+ llvm::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
+ relocAddressLess);
}
}
@@ -767,7 +769,7 @@ void COFFDumper::printRVATable(uint64_t TableVA, uint64_t Count,
for (uintptr_t I = TableStart; I < TableEnd; I += EntrySize) {
uint32_t RVA = *reinterpret_cast<const ulittle32_t *>(I);
raw_ostream &OS = W.startLine();
- OS << "0x" << W.hex(Obj->getImageBase() + RVA);
+ OS << W.hex(Obj->getImageBase() + RVA);
if (PrintExtra)
PrintExtra(OS, reinterpret_cast<const uint8_t *>(I));
OS << '\n';
@@ -800,6 +802,11 @@ void COFFDumper::printCOFFLoadConfig() {
printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4);
}
}
+
+ if (Tables.GuardLJmpTableVA) {
+ ListScope LS(W, "GuardLJmpTable");
+ printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount, 4);
+ }
}
template <typename T>
@@ -879,6 +886,9 @@ void COFFDumper::printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables) {
W.printHex("GuardRFVerifyStackPointerFunctionPointer",
Conf->GuardRFVerifyStackPointerFunctionPointer);
W.printHex("HotPatchTableOffset", Conf->HotPatchTableOffset);
+
+ Tables.GuardLJmpTableVA = Conf->GuardLongJumpTargetTable;
+ Tables.GuardLJmpTableCount = Conf->GuardLongJumpTargetCount;
}
void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
@@ -892,7 +902,9 @@ void COFFDumper::printCodeViewDebugInfo() {
for (const SectionRef &S : Obj->sections()) {
StringRef SectionName;
error(S.getName(SectionName));
- if (SectionName == ".debug$T")
+ // .debug$T is a standard CodeView type section, while .debug$P is the same
+ // format but used for MSVC precompiled header object files.
+ if (SectionName == ".debug$T" || SectionName == ".debug$P")
printCodeViewTypeSection(SectionName, S);
}
for (const SectionRef &S : Obj->sections()) {
@@ -1812,10 +1824,9 @@ void COFFDumper::printStackMap() const {
if (Obj->isLittleEndian())
prettyPrintStackMap(
- llvm::outs(),
- StackMapV2Parser<support::little>(StackMapContentsArray));
+ W, StackMapV2Parser<support::little>(StackMapContentsArray));
else
- prettyPrintStackMap(llvm::outs(),
+ prettyPrintStackMap(W,
StackMapV2Parser<support::big>(StackMapContentsArray));
}
diff --git a/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp
index 3b546b3ef508..18010c34f0f3 100644
--- a/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp
@@ -8,41 +8,51 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the COFF import library dumper for llvm-readobj.
+/// This file implements the COFF import library dumper for llvm-readobj.
///
//===----------------------------------------------------------------------===//
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
+#include "llvm/Support/ScopedPrinter.h"
using namespace llvm::object;
namespace llvm {
-void dumpCOFFImportFile(const COFFImportFile *File) {
- outs() << '\n';
- outs() << "File: " << File->getFileName() << "\n";
- outs() << "Format: COFF-import-file\n";
+void dumpCOFFImportFile(const COFFImportFile *File, ScopedPrinter &Writer) {
+ Writer.startLine() << '\n';
+ Writer.printString("File", File->getFileName());
+ Writer.printString("Format", "COFF-import-file");
const coff_import_header *H = File->getCOFFImportHeader();
switch (H->getType()) {
- case COFF::IMPORT_CODE: outs() << "Type: code\n"; break;
- case COFF::IMPORT_DATA: outs() << "Type: data\n"; break;
- case COFF::IMPORT_CONST: outs() << "Type: const\n"; break;
+ case COFF::IMPORT_CODE: Writer.printString("Type", "code"); break;
+ case COFF::IMPORT_DATA: Writer.printString("Type", "data"); break;
+ case COFF::IMPORT_CONST: Writer.printString("Type", "const"); break;
}
switch (H->getNameType()) {
- case COFF::IMPORT_ORDINAL: outs() << "Name type: ordinal\n"; break;
- case COFF::IMPORT_NAME: outs() << "Name type: name\n"; break;
- case COFF::IMPORT_NAME_NOPREFIX: outs() << "Name type: noprefix\n"; break;
- case COFF::IMPORT_NAME_UNDECORATE: outs() << "Name type: undecorate\n"; break;
+ case COFF::IMPORT_ORDINAL:
+ Writer.printString("Name type", "ordinal");
+ break;
+ case COFF::IMPORT_NAME:
+ Writer.printString("Name type", "name");
+ break;
+ case COFF::IMPORT_NAME_NOPREFIX:
+ Writer.printString("Name type", "noprefix");
+ break;
+ case COFF::IMPORT_NAME_UNDECORATE:
+ Writer.printString("Name type", "undecorate");
+ break;
}
for (const object::BasicSymbolRef &Sym : File->symbols()) {
- outs() << "Symbol: ";
- Sym.printName(outs());
- outs() << "\n";
+ raw_ostream &OS = Writer.startLine();
+ OS << "Symbol: ";
+ Sym.printName(OS);
+ OS << "\n";
}
}
diff --git a/contrib/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/contrib/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
new file mode 100644
index 000000000000..5a1eef1d007d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -0,0 +1,245 @@
+//===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
+#define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
+
+#include "Error.h"
+#include "llvm-readobj.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/type_traits.h"
+
+namespace llvm {
+namespace DwarfCFIEH {
+
+template <typename ELFT>
+class PrinterContext {
+ ScopedPrinter &W;
+ const object::ELFFile<ELFT> *Obj;
+
+ void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size) const;
+
+ void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const;
+
+public:
+ PrinterContext(ScopedPrinter &W, const object::ELFFile<ELFT> *Obj)
+ : W(W), Obj(Obj) {}
+
+ void printUnwindInformation() const;
+};
+
+template <class ELFO>
+static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj,
+ uint64_t Addr) {
+ auto Sections = Obj->sections();
+ if (Error E = Sections.takeError())
+ reportError(toString(std::move(E)));
+
+ for (const auto &Shdr : *Sections)
+ if (Shdr.sh_addr == Addr)
+ return &Shdr;
+ return nullptr;
+}
+
+template <typename ELFT>
+void PrinterContext<ELFT>::printUnwindInformation() const {
+ const typename ELFT::Phdr *EHFramePhdr = nullptr;
+
+ auto PHs = Obj->program_headers();
+ if (Error E = PHs.takeError())
+ reportError(toString(std::move(E)));
+
+ for (const auto &Phdr : *PHs) {
+ if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
+ EHFramePhdr = &Phdr;
+ if (Phdr.p_memsz != Phdr.p_filesz)
+ reportError("p_memsz does not match p_filesz for GNU_EH_FRAME");
+ break;
+ }
+ }
+
+ if (EHFramePhdr)
+ printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr,
+ EHFramePhdr->p_memsz);
+
+ auto Sections = Obj->sections();
+ if (Error E = Sections.takeError())
+ reportError(toString(std::move(E)));
+
+ for (const auto &Shdr : *Sections) {
+ auto SectionName = Obj->getSectionName(&Shdr);
+ if (Error E = SectionName.takeError())
+ reportError(toString(std::move(E)));
+
+ if (*SectionName == ".eh_frame")
+ printEHFrame(&Shdr);
+ }
+}
+
+template <typename ELFT>
+void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
+ uint64_t EHFrameHdrAddress,
+ uint64_t EHFrameHdrSize) const {
+ ListScope L(W, "EH_FRAME Header");
+ W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
+ W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
+ W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
+
+ const auto *EHFrameHdrShdr = findSectionByAddress(Obj, EHFrameHdrAddress);
+ if (EHFrameHdrShdr) {
+ auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
+ if (Error E = SectionName.takeError())
+ reportError(toString(std::move(E)));
+
+ W.printString("Corresponding Section", *SectionName);
+ }
+
+ DataExtractor DE(
+ StringRef(reinterpret_cast<const char *>(Obj->base()) + EHFrameHdrOffset,
+ EHFrameHdrSize),
+ ELFT::TargetEndianness == support::endianness::little,
+ ELFT::Is64Bits ? 8 : 4);
+
+ DictScope D(W, "Header");
+ uint32_t Offset = 0;
+
+ auto Version = DE.getU8(&Offset);
+ W.printNumber("version", Version);
+ if (Version != 1)
+ reportError("only version 1 of .eh_frame_hdr is supported");
+
+ uint64_t EHFramePtrEnc = DE.getU8(&Offset);
+ W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);
+ if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
+ reportError("unexpected encoding eh_frame_ptr_enc");
+
+ uint64_t FDECountEnc = DE.getU8(&Offset);
+ W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
+ if (FDECountEnc != dwarf::DW_EH_PE_udata4)
+ reportError("unexpected encoding fde_count_enc");
+
+ uint64_t TableEnc = DE.getU8(&Offset);
+ W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
+ if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
+ reportError("unexpected encoding table_enc");
+
+ auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
+ W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
+
+ auto FDECount = DE.getUnsigned(&Offset, 4);
+ W.printNumber("fde_count", FDECount);
+
+ unsigned NumEntries = 0;
+ uint64_t PrevPC = 0;
+ while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) {
+ DictScope D(W, std::string("entry ") + std::to_string(NumEntries));
+
+ auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
+ W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);
+ auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
+ W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
+
+ if (InitialPC < PrevPC)
+ reportError("initial_location is out of order");
+
+ PrevPC = InitialPC;
+ ++NumEntries;
+ }
+}
+
+template <typename ELFT>
+void PrinterContext<ELFT>::printEHFrame(
+ const typename ELFT::Shdr *EHFrameShdr) const {
+ uint64_t Address = EHFrameShdr->sh_addr;
+ uint64_t ShOffset = EHFrameShdr->sh_offset;
+ W.startLine() << format(".eh_frame section at offset 0x%" PRIx64
+ " address 0x%" PRIx64 ":\n",
+ ShOffset, Address);
+ W.indent();
+
+ auto Result = Obj->getSectionContents(EHFrameShdr);
+ if (Error E = Result.takeError())
+ reportError(toString(std::move(E)));
+
+ auto Contents = Result.get();
+ DWARFDataExtractor DE(
+ StringRef(reinterpret_cast<const char *>(Contents.data()),
+ Contents.size()),
+ ELFT::TargetEndianness == support::endianness::little,
+ ELFT::Is64Bits ? 8 : 4);
+ DWARFDebugFrame EHFrame(/*IsEH=*/true, /*EHFrameAddress=*/Address);
+ EHFrame.parse(DE);
+
+ for (const auto &Entry : EHFrame) {
+ if (const auto *CIE = dyn_cast<dwarf::CIE>(&Entry)) {
+ W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",
+ Address + CIE->getOffset(),
+ CIE->getLength());
+ W.indent();
+
+ W.printNumber("version", CIE->getVersion());
+ W.printString("augmentation", CIE->getAugmentationString());
+ W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor());
+ W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor());
+ W.printNumber("return_address_register", CIE->getReturnAddressRegister());
+
+ W.getOStream() << "\n";
+ W.startLine() << "Program:\n";
+ W.indent();
+ CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
+ W.unindent();
+
+ W.unindent();
+ W.getOStream() << "\n";
+
+ } else if (const auto *FDE = dyn_cast<dwarf::FDE>(&Entry)) {
+ W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64
+ " cie=[0x%" PRIx64 "]\n",
+ Address + FDE->getOffset(),
+ FDE->getLength(),
+ Address + FDE->getLinkedCIE()->getOffset());
+ W.indent();
+
+ W.startLine() << format("initial_location: 0x%" PRIx64 "\n",
+ FDE->getInitialLocation());
+ W.startLine()
+ << format("address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",
+ FDE->getAddressRange(),
+ FDE->getInitialLocation() + FDE->getAddressRange());
+
+ W.getOStream() << "\n";
+ W.startLine() << "Program:\n";
+ W.indent();
+ FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
+ W.unindent();
+
+ W.unindent();
+ W.getOStream() << "\n";
+ } else {
+ llvm_unreachable("unexpected DWARF frame kind");
+ }
+ }
+
+ W.unindent();
+}
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
index 5605eaea7555..645ec2d7e04b 100644
--- a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -8,11 +8,12 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the ELF-specific dumper for llvm-readobj.
+/// This file implements the ELF-specific dumper for llvm-readobj.
///
//===----------------------------------------------------------------------===//
#include "ARMEHABIPrinter.h"
+#include "DwarfCFIEHPrinter.h"
#include "Error.h"
#include "ObjDumper.h"
#include "StackMapPrinter.h"
@@ -43,6 +44,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MipsABIFlags.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -77,28 +79,32 @@ using namespace ELF;
#define TYPEDEF_ELF_TYPES(ELFT) \
using ELFO = ELFFile<ELFT>; \
- using Elf_Addr = typename ELFO::Elf_Addr; \
- using Elf_Shdr = typename ELFO::Elf_Shdr; \
- using Elf_Sym = typename ELFO::Elf_Sym; \
- using Elf_Dyn = typename ELFO::Elf_Dyn; \
- using Elf_Dyn_Range = typename ELFO::Elf_Dyn_Range; \
- using Elf_Rel = typename ELFO::Elf_Rel; \
- using Elf_Rela = typename ELFO::Elf_Rela; \
- using Elf_Rel_Range = typename ELFO::Elf_Rel_Range; \
- using Elf_Rela_Range = typename ELFO::Elf_Rela_Range; \
- using Elf_Phdr = typename ELFO::Elf_Phdr; \
- using Elf_Half = typename ELFO::Elf_Half; \
- using Elf_Ehdr = typename ELFO::Elf_Ehdr; \
- using Elf_Word = typename ELFO::Elf_Word; \
- using Elf_Hash = typename ELFO::Elf_Hash; \
- using Elf_GnuHash = typename ELFO::Elf_GnuHash; \
- using Elf_Sym_Range = typename ELFO::Elf_Sym_Range; \
- using Elf_Versym = typename ELFO::Elf_Versym; \
- using Elf_Verneed = typename ELFO::Elf_Verneed; \
- using Elf_Vernaux = typename ELFO::Elf_Vernaux; \
- using Elf_Verdef = typename ELFO::Elf_Verdef; \
- using Elf_Verdaux = typename ELFO::Elf_Verdaux; \
- using uintX_t = typename ELFO::uintX_t;
+ using Elf_Addr = typename ELFT::Addr; \
+ using Elf_Shdr = typename ELFT::Shdr; \
+ using Elf_Sym = typename ELFT::Sym; \
+ using Elf_Dyn = typename ELFT::Dyn; \
+ using Elf_Dyn_Range = typename ELFT::DynRange; \
+ using Elf_Rel = typename ELFT::Rel; \
+ using Elf_Rela = typename ELFT::Rela; \
+ using Elf_Relr = typename ELFT::Relr; \
+ using Elf_Rel_Range = typename ELFT::RelRange; \
+ using Elf_Rela_Range = typename ELFT::RelaRange; \
+ using Elf_Relr_Range = typename ELFT::RelrRange; \
+ using Elf_Phdr = typename ELFT::Phdr; \
+ using Elf_Half = typename ELFT::Half; \
+ using Elf_Ehdr = typename ELFT::Ehdr; \
+ using Elf_Word = typename ELFT::Word; \
+ using Elf_Hash = typename ELFT::Hash; \
+ using Elf_GnuHash = typename ELFT::GnuHash; \
+ using Elf_Note = typename ELFT::Note; \
+ using Elf_Sym_Range = typename ELFT::SymRange; \
+ using Elf_Versym = typename ELFT::Versym; \
+ using Elf_Verneed = typename ELFT::Verneed; \
+ using Elf_Vernaux = typename ELFT::Vernaux; \
+ using Elf_Verdef = typename ELFT::Verdef; \
+ using Elf_Verdaux = typename ELFT::Verdaux; \
+ using Elf_CGProfile = typename ELFT::CGProfile; \
+ using uintX_t = typename ELFT::uint;
namespace {
@@ -113,11 +119,11 @@ struct DynRegionInfo {
DynRegionInfo(const void *A, uint64_t S, uint64_t ES)
: Addr(A), Size(S), EntSize(ES) {}
- /// \brief Address in current address space.
+ /// Address in current address space.
const void *Addr = nullptr;
- /// \brief Size in bytes of the region.
+ /// Size in bytes of the region.
uint64_t Size = 0;
- /// \brief Size of each entity in the region.
+ /// Size of each entity in the region.
uint64_t EntSize = 0;
template <typename Type> ArrayRef<Type> getAsArrayRef() const {
@@ -162,8 +168,13 @@ public:
void printHashHistogram() override;
+ void printCGProfile() override;
+ void printAddrsig() override;
+
void printNotes() override;
+ void printELFLinkerOptions() override;
+
private:
std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle;
@@ -198,6 +209,7 @@ private:
const ELFO *Obj;
DynRegionInfo DynRelRegion;
DynRegionInfo DynRelaRegion;
+ DynRegionInfo DynRelrRegion;
DynRegionInfo DynPLTRelRegion;
DynRegionInfo DynSymRegion;
DynRegionInfo DynamicTable;
@@ -206,6 +218,8 @@ private:
const Elf_Hash *HashTable = nullptr;
const Elf_GnuHash *GnuHashTable = nullptr;
const Elf_Shdr *DotSymtabSec = nullptr;
+ const Elf_Shdr *DotCGProfileSec = nullptr;
+ const Elf_Shdr *DotAddrsigSec = nullptr;
StringRef DynSymtabName;
ArrayRef<Elf_Word> ShndxTable;
@@ -248,18 +262,23 @@ public:
Elf_Rel_Range dyn_rels() const;
Elf_Rela_Range dyn_relas() const;
+ Elf_Relr_Range dyn_relrs() const;
std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
bool IsDynamic) const;
void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
StringRef &SectionName,
unsigned &SectionIndex) const;
+ StringRef getStaticSymbolName(uint32_t Index) const;
void printSymbolsHelper(bool IsDynamic) const;
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
+ const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; }
+ const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; }
ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; }
StringRef getDynamicStringTable() const { return DynamicStringTable; }
const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; }
const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; }
+ const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; }
const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; }
const Elf_Hash *getHashTable() const { return HashTable; }
const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; }
@@ -295,8 +314,8 @@ template <class ELFT> class MipsGOTParser;
template <typename ELFT> class DumpStyle {
public:
- using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
- using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Sym = typename ELFT::Sym;
DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {}
virtual ~DumpStyle() = default;
@@ -315,7 +334,10 @@ public:
bool IsDynamic) = 0;
virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0;
virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0;
virtual void printNotes(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0;
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
const ELFDumper<ELFT> *dumper() const { return Dumper; }
@@ -344,7 +366,10 @@ public:
size_t Offset) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
+ void printCGProfile(const ELFFile<ELFT> *Obj) override;
+ void printAddrsig(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
+ void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
@@ -374,6 +399,7 @@ private:
}
void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym,
StringRef StrTable, uint32_t Bucket);
+ void printRelocHeader(unsigned SType);
void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
const Elf_Rela &R, bool IsRela);
void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
@@ -404,7 +430,10 @@ public:
void printDynamicRelocations(const ELFO *Obj) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
+ void printCGProfile(const ELFFile<ELFT> *Obj) override;
+ void printAddrsig(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
+ void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
@@ -730,6 +759,16 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
}
template <typename ELFT>
+StringRef ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
+ StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
+ Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
+ if (Index >= Syms.size())
+ reportError("Invalid symbol index");
+ const Elf_Sym *Sym = &Syms[Index];
+ return unwrapOrError(Sym->getName(StrTable));
+}
+
+template <typename ELFT>
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
StringRef StrTable,
bool IsDynamic) const {
@@ -1007,7 +1046,6 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
ENUM_ENT(EM_56800EX, "EM_56800EX"),
ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"),
ENUM_ENT(EM_RISCV, "RISC-V"),
- ENUM_ENT(EM_WEBASSEMBLY, "EM_WEBASSEMBLY"),
ENUM_ENT(EM_LANAI, "EM_LANAI"),
ENUM_ENT(EM_BPF, "EM_BPF"),
};
@@ -1255,9 +1293,39 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
};
static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = {
- LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_NONE),
- LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_R600),
- LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_GCN)
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK)
};
static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
@@ -1353,6 +1421,16 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
reportError("Multiple SHT_GNU_verneed");
dot_gnu_version_r_sec = &Sec;
break;
+ case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
+ if (DotCGProfileSec != nullptr)
+ reportError("Multiple .note.llvm.cgprofile");
+ DotCGProfileSec = &Sec;
+ break;
+ case ELF::SHT_LLVM_ADDRSIG:
+ if (DotAddrsigSec != nullptr)
+ reportError("Multiple .llvm_addrsig");
+ DotAddrsigSec = &Sec;
+ break;
}
}
@@ -1427,6 +1505,18 @@ void ELFDumper<ELFT>::parseDynamicTable(
case ELF::DT_RELENT:
DynRelRegion.EntSize = Dyn.getVal();
break;
+ case ELF::DT_RELR:
+ case ELF::DT_ANDROID_RELR:
+ DynRelrRegion.Addr = toMappedAddr(Dyn.getPtr());
+ break;
+ case ELF::DT_RELRSZ:
+ case ELF::DT_ANDROID_RELRSZ:
+ DynRelrRegion.Size = Dyn.getVal();
+ break;
+ case ELF::DT_RELRENT:
+ case ELF::DT_ANDROID_RELRENT:
+ DynRelrRegion.EntSize = Dyn.getVal();
+ break;
case ELF::DT_PLTREL:
if (Dyn.getVal() == DT_REL)
DynPLTRelRegion.EntSize = sizeof(Elf_Rel);
@@ -1460,6 +1550,11 @@ typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
return DynRelaRegion.getAsArrayRef<Elf_Rela>();
}
+template <typename ELFT>
+typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const {
+ return DynRelrRegion.getAsArrayRef<Elf_Relr>();
+}
+
template<class ELFT>
void ELFDumper<ELFT>::printFileHeaders() {
ELFDumperStyle->printFileHeaders(Obj);
@@ -1497,93 +1592,69 @@ template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() {
ELFDumperStyle->printHashHistogram(Obj);
}
+template <class ELFT> void ELFDumper<ELFT>::printCGProfile() {
+ ELFDumperStyle->printCGProfile(Obj);
+}
+
template <class ELFT> void ELFDumper<ELFT>::printNotes() {
ELFDumperStyle->printNotes(Obj);
}
-#define LLVM_READOBJ_TYPE_CASE(name) \
- case DT_##name: return #name
+template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() {
+ ELFDumperStyle->printELFLinkerOptions(Obj);
+}
static const char *getTypeString(unsigned Arch, uint64_t Type) {
+#define DYNAMIC_TAG(n, v)
switch (Arch) {
case EM_HEXAGON:
switch (Type) {
- LLVM_READOBJ_TYPE_CASE(HEXAGON_SYMSZ);
- LLVM_READOBJ_TYPE_CASE(HEXAGON_VER);
- LLVM_READOBJ_TYPE_CASE(HEXAGON_PLT);
+#define HEXAGON_DYNAMIC_TAG(name, value) \
+ case DT_##name: \
+ return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef HEXAGON_DYNAMIC_TAG
}
+
case EM_MIPS:
switch (Type) {
- LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL);
- LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION);
- LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS);
- LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS);
- LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO);
- LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO);
- LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO);
- LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM);
- LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP);
- LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT);
- LLVM_READOBJ_TYPE_CASE(MIPS_OPTIONS);
+#define MIPS_DYNAMIC_TAG(name, value) \
+ case DT_##name: \
+ return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef MIPS_DYNAMIC_TAG
+ }
+
+ case EM_PPC64:
+ switch(Type) {
+#define PPC64_DYNAMIC_TAG(name, value) \
+ case DT_##name: \
+ return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef PPC64_DYNAMIC_TAG
}
}
+#undef DYNAMIC_TAG
switch (Type) {
- LLVM_READOBJ_TYPE_CASE(ANDROID_REL);
- LLVM_READOBJ_TYPE_CASE(ANDROID_RELSZ);
- LLVM_READOBJ_TYPE_CASE(ANDROID_RELA);
- LLVM_READOBJ_TYPE_CASE(ANDROID_RELASZ);
- LLVM_READOBJ_TYPE_CASE(BIND_NOW);
- LLVM_READOBJ_TYPE_CASE(DEBUG);
- LLVM_READOBJ_TYPE_CASE(FINI);
- LLVM_READOBJ_TYPE_CASE(FINI_ARRAY);
- LLVM_READOBJ_TYPE_CASE(FINI_ARRAYSZ);
- LLVM_READOBJ_TYPE_CASE(FLAGS);
- LLVM_READOBJ_TYPE_CASE(FLAGS_1);
- LLVM_READOBJ_TYPE_CASE(HASH);
- LLVM_READOBJ_TYPE_CASE(INIT);
- LLVM_READOBJ_TYPE_CASE(INIT_ARRAY);
- LLVM_READOBJ_TYPE_CASE(INIT_ARRAYSZ);
- LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAY);
- LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAYSZ);
- LLVM_READOBJ_TYPE_CASE(JMPREL);
- LLVM_READOBJ_TYPE_CASE(NEEDED);
- LLVM_READOBJ_TYPE_CASE(NULL);
- LLVM_READOBJ_TYPE_CASE(PLTGOT);
- LLVM_READOBJ_TYPE_CASE(PLTREL);
- LLVM_READOBJ_TYPE_CASE(PLTRELSZ);
- LLVM_READOBJ_TYPE_CASE(REL);
- LLVM_READOBJ_TYPE_CASE(RELA);
- LLVM_READOBJ_TYPE_CASE(RELENT);
- LLVM_READOBJ_TYPE_CASE(RELSZ);
- LLVM_READOBJ_TYPE_CASE(RELAENT);
- LLVM_READOBJ_TYPE_CASE(RELASZ);
- LLVM_READOBJ_TYPE_CASE(RPATH);
- LLVM_READOBJ_TYPE_CASE(RUNPATH);
- LLVM_READOBJ_TYPE_CASE(SONAME);
- LLVM_READOBJ_TYPE_CASE(STRSZ);
- LLVM_READOBJ_TYPE_CASE(STRTAB);
- LLVM_READOBJ_TYPE_CASE(SYMBOLIC);
- LLVM_READOBJ_TYPE_CASE(SYMENT);
- LLVM_READOBJ_TYPE_CASE(SYMTAB);
- LLVM_READOBJ_TYPE_CASE(TEXTREL);
- LLVM_READOBJ_TYPE_CASE(VERDEF);
- LLVM_READOBJ_TYPE_CASE(VERDEFNUM);
- LLVM_READOBJ_TYPE_CASE(VERNEED);
- LLVM_READOBJ_TYPE_CASE(VERNEEDNUM);
- LLVM_READOBJ_TYPE_CASE(VERSYM);
- LLVM_READOBJ_TYPE_CASE(RELACOUNT);
- LLVM_READOBJ_TYPE_CASE(RELCOUNT);
- LLVM_READOBJ_TYPE_CASE(GNU_HASH);
- LLVM_READOBJ_TYPE_CASE(TLSDESC_PLT);
- LLVM_READOBJ_TYPE_CASE(TLSDESC_GOT);
- LLVM_READOBJ_TYPE_CASE(AUXILIARY);
- LLVM_READOBJ_TYPE_CASE(FILTER);
+// Now handle all dynamic tags except the architecture specific ones
+#define MIPS_DYNAMIC_TAG(name, value)
+#define HEXAGON_DYNAMIC_TAG(name, value)
+#define PPC64_DYNAMIC_TAG(name, value)
+// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
+#define DYNAMIC_TAG_MARKER(name, value)
+#define DYNAMIC_TAG(name, value) \
+ case DT_##name: \
+ return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef DYNAMIC_TAG
+#undef MIPS_DYNAMIC_TAG
+#undef HEXAGON_DYNAMIC_TAG
+#undef PPC64_DYNAMIC_TAG
+#undef DYNAMIC_TAG_MARKER
default: return "unknown";
}
}
-#undef LLVM_READOBJ_TYPE_CASE
-
#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \
{ #enum, prefix##_##enum }
@@ -1771,16 +1842,20 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) {
template<class ELFT>
void ELFDumper<ELFT>::printUnwindInfo() {
+ const unsigned Machine = Obj->getHeader()->e_machine;
+ if (Machine == EM_386 || Machine == EM_X86_64) {
+ DwarfCFIEH::PrinterContext<ELFT> Ctx(W, Obj);
+ return Ctx.printUnwindInformation();
+ }
W.startLine() << "UnwindInfo not implemented.\n";
}
namespace {
-template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() {
+template <> void ELFDumper<ELF32LE>::printUnwindInfo() {
const unsigned Machine = Obj->getHeader()->e_machine;
if (Machine == EM_ARM) {
- ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(
- W, Obj, DotSymtabSec);
+ ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec);
return Ctx.PrintUnwindInformation();
}
W.startLine() << "UnwindInfo not implemented.\n";
@@ -1841,9 +1916,8 @@ void ELFDumper<ELFT>::printNeededLibraries() {
std::stable_sort(Libs.begin(), Libs.end());
- for (const auto &L : Libs) {
- outs() << " " << L << "\n";
- }
+ for (const auto &L : Libs)
+ W.startLine() << L << "\n";
}
@@ -1877,7 +1951,7 @@ void ELFDumper<ELFT>::printGnuHashTable() {
}
template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
- outs() << "LoadName: " << SOName << '\n';
+ W.printString("LoadName", SOName);
}
template <class ELFT>
@@ -1887,7 +1961,7 @@ void ELFDumper<ELFT>::printAttributes() {
namespace {
-template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() {
+template <> void ELFDumper<ELF32LE>::printAttributes() {
if (Obj->getHeader()->e_machine != EM_ARM) {
W.startLine() << "Attributes not implemented.\n";
return;
@@ -2219,7 +2293,9 @@ static const EnumEntry<unsigned> ElfMipsASEFlags[] = {
{"MSA", Mips::AFL_ASE_MSA},
{"MIPS16", Mips::AFL_ASE_MIPS16},
{"microMIPS", Mips::AFL_ASE_MICROMIPS},
- {"XPA", Mips::AFL_ASE_XPA}
+ {"XPA", Mips::AFL_ASE_XPA},
+ {"CRC", Mips::AFL_ASE_CRC},
+ {"GINV", Mips::AFL_ASE_GINV},
};
static const EnumEntry<unsigned> ElfMipsFpABIType[] = {
@@ -2361,14 +2437,18 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
ArrayRef<uint8_t> StackMapContentsArray =
unwrapOrError(Obj->getSectionContents(StackMapSection));
- prettyPrintStackMap(outs(), StackMapV2Parser<ELFT::TargetEndianness>(
- StackMapContentsArray));
+ prettyPrintStackMap(
+ W, StackMapV2Parser<ELFT::TargetEndianness>(StackMapContentsArray));
}
template <class ELFT> void ELFDumper<ELFT>::printGroupSections() {
ELFDumperStyle->printGroupSections(Obj);
}
+template <class ELFT> void ELFDumper<ELFT>::printAddrsig() {
+ ELFDumperStyle->printAddrsig(Obj);
+}
+
static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,
StringRef Str2) {
OS.PadToColumn(2u);
@@ -2378,6 +2458,30 @@ static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,
OS.flush();
}
+template <class ELFT>
+static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) {
+ const typename ELFT::Ehdr *ElfHeader = Obj->getHeader();
+ if (ElfHeader->e_shnum != 0)
+ return to_string(ElfHeader->e_shnum);
+
+ ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections());
+ if (Arr.empty())
+ return "0";
+ return "0 (" + to_string(Arr[0].sh_size) + ")";
+}
+
+template <class ELFT>
+static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) {
+ const typename ELFT::Ehdr *ElfHeader = Obj->getHeader();
+ if (ElfHeader->e_shstrndx != SHN_XINDEX)
+ return to_string(ElfHeader->e_shstrndx);
+
+ ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections());
+ if (Arr.empty())
+ return "65535 (corrupt: out of range)";
+ return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) + ")";
+}
+
template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
const Elf_Ehdr *e = Obj->getHeader();
OS << "ELF Header:\n";
@@ -2423,9 +2527,9 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
printFields(OS, "Number of program headers:", Str);
Str = to_string(e->e_shentsize) + " (bytes)";
printFields(OS, "Size of section headers:", Str);
- Str = to_string(e->e_shnum);
+ Str = getSectionHeadersNumString(Obj);
printFields(OS, "Number of section headers:", Str);
- Str = to_string(e->e_shstrndx);
+ Str = getSectionHeaderTableIndexString(Obj);
printFields(OS, "Section header string table index:", Str);
}
@@ -2440,15 +2544,17 @@ struct GroupSection {
StringRef Signature;
uint64_t ShName;
uint64_t Index;
+ uint32_t Link;
+ uint32_t Info;
uint32_t Type;
std::vector<GroupMember> Members;
};
template <class ELFT>
std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
- using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
- using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
- using Elf_Word = typename ELFFile<ELFT>::Elf_Word;
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Sym = typename ELFT::Sym;
+ using Elf_Word = typename ELFT::Word;
std::vector<GroupSection> Ret;
uint64_t I = 0;
@@ -2466,7 +2572,14 @@ std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
StringRef Signature = StrTable.data() + Sym->st_name;
- Ret.push_back({Name, Signature, Sec.sh_name, I - 1, Data[0], {}});
+ Ret.push_back({Name,
+ Signature,
+ Sec.sh_name,
+ I - 1,
+ Sec.sh_link,
+ Sec.sh_info,
+ Data[0],
+ {}});
std::vector<GroupMember> &GM = Ret.back().Members;
for (uint32_t Ndx : Data.slice(1)) {
@@ -2522,7 +2635,6 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
const Elf_Rela &R, bool IsRela) {
std::string Offset, Info, Addend, Value;
SmallString<32> RelocName;
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
StringRef TargetName;
const Elf_Sym *Sym = nullptr;
unsigned Width = ELFT::Is64Bits ? 16 : 8;
@@ -2538,6 +2650,7 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable()));
TargetName = unwrapOrError(Obj->getSectionName(Sec));
} else if (Sym) {
+ StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
TargetName = unwrapOrError(Sym->getName(StrTable));
}
@@ -2569,35 +2682,62 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
OS << "\n";
}
-static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) {
- if (Is64)
- OS << " Offset Info Type"
+template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) {
+ bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
+ bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR;
+ if (ELFT::Is64Bits)
+ OS << " ";
+ else
+ OS << " ";
+ if (IsRelr && opts::RawRelr)
+ OS << "Data ";
+ else
+ OS << "Offset";
+ if (ELFT::Is64Bits)
+ OS << " Info Type"
<< " Symbol's Value Symbol's Name";
else
- OS << " Offset Info Type Sym. Value "
- << "Symbol's Name";
+ OS << " Info Type Sym. Value Symbol's Name";
if (IsRela)
- OS << (IsRela ? " + Addend" : "");
+ OS << " + Addend";
OS << "\n";
}
template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
bool HasRelocSections = false;
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
+ if (Sec.sh_type != ELF::SHT_REL &&
+ Sec.sh_type != ELF::SHT_RELA &&
+ Sec.sh_type != ELF::SHT_RELR &&
Sec.sh_type != ELF::SHT_ANDROID_REL &&
- Sec.sh_type != ELF::SHT_ANDROID_RELA)
+ Sec.sh_type != ELF::SHT_ANDROID_RELA &&
+ Sec.sh_type != ELF::SHT_ANDROID_RELR)
continue;
HasRelocSections = true;
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
unsigned Entries = Sec.getEntityCount();
+ std::vector<Elf_Rela> AndroidRelas;
+ if (Sec.sh_type == ELF::SHT_ANDROID_REL ||
+ Sec.sh_type == ELF::SHT_ANDROID_RELA) {
+ // Android's packed relocation section needs to be unpacked first
+ // to get the actual number of entries.
+ AndroidRelas = unwrapOrError(Obj->android_relas(&Sec));
+ Entries = AndroidRelas.size();
+ }
+ std::vector<Elf_Rela> RelrRelas;
+ if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR ||
+ Sec.sh_type == ELF::SHT_ANDROID_RELR)) {
+ // .relr.dyn relative relocation section needs to be unpacked first
+ // to get the actual number of entries.
+ Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec));
+ RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ Entries = RelrRelas.size();
+ }
uintX_t Offset = Sec.sh_offset;
OS << "\nRelocation section '" << Name << "' at offset 0x"
<< to_hexString(Offset, false) << " contains " << Entries
<< " entries:\n";
- printRelocHeader(OS, ELFT::Is64Bits,
- Sec.sh_type == ELF::SHT_RELA ||
- Sec.sh_type == ELF::SHT_ANDROID_RELA);
+ printRelocHeader(Sec.sh_type);
const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link));
switch (Sec.sh_type) {
case ELF::SHT_REL:
@@ -2613,9 +2753,19 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
printRelocation(Obj, SymTab, R, true);
break;
+ case ELF::SHT_RELR:
+ case ELF::SHT_ANDROID_RELR:
+ if (opts::RawRelr)
+ for (const auto &R : unwrapOrError(Obj->relrs(&Sec)))
+ OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8))
+ << "\n";
+ else
+ for (const auto &R : RelrRelas)
+ printRelocation(Obj, SymTab, R, false);
+ break;
case ELF::SHT_ANDROID_REL:
case ELF::SHT_ANDROID_RELA:
- for (const auto &R : unwrapOrError(Obj->android_relas(&Sec)))
+ for (const auto &R : AndroidRelas)
printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA);
break;
}
@@ -2694,8 +2844,17 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) {
return "GROUP";
case SHT_SYMTAB_SHNDX:
return "SYMTAB SECTION INDICES";
+ case SHT_RELR:
+ case SHT_ANDROID_RELR:
+ return "RELR";
case SHT_LLVM_ODRTAB:
return "LLVM_ODRTAB";
+ case SHT_LLVM_LINKER_OPTIONS:
+ return "LLVM_LINKER_OPTIONS";
+ case SHT_LLVM_CALL_GRAPH_PROFILE:
+ return "LLVM_CALL_GRAPH_PROFILE";
+ case SHT_LLVM_ADDRSIG:
+ return "LLVM_ADDRSIG";
// FIXME: Parse processor specific GNU attributes
case SHT_GNU_ATTRIBUTES:
return "ATTRIBUTES";
@@ -2727,7 +2886,9 @@ template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) {
Bias = 8;
Width = 8;
}
- OS << "There are " << to_string(Obj->getHeader()->e_shnum)
+
+ ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
+ OS << "There are " << to_string(Sections.size())
<< " section headers, starting at offset "
<< "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n";
OS << "Section Headers:\n";
@@ -2746,7 +2907,7 @@ template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) {
printField(f);
OS << "\n";
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec : Sections) {
Number = to_string(SectionIndex);
Fields[0].Str = Number;
Fields[1].Str = unwrapOrError(Obj->getSectionName(&Sec));
@@ -3198,13 +3359,14 @@ template <class ELFT>
void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion();
const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion();
+ const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion();
const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion();
if (DynRelaRegion.Size > 0) {
OS << "\n'RELA' relocation section at offset "
<< format_hex(reinterpret_cast<const uint8_t *>(DynRelaRegion.Addr) -
Obj->base(),
1) << " contains " << DynRelaRegion.Size << " bytes:\n";
- printRelocHeader(OS, ELFT::Is64Bits, true);
+ printRelocHeader(ELF::SHT_RELA);
for (const Elf_Rela &Rela : this->dumper()->dyn_relas())
printDynamicRelocation(Obj, Rela, true);
}
@@ -3213,7 +3375,7 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
<< format_hex(reinterpret_cast<const uint8_t *>(DynRelRegion.Addr) -
Obj->base(),
1) << " contains " << DynRelRegion.Size << " bytes:\n";
- printRelocHeader(OS, ELFT::Is64Bits, false);
+ printRelocHeader(ELF::SHT_REL);
for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) {
Elf_Rela Rela;
Rela.r_offset = Rel.r_offset;
@@ -3222,6 +3384,18 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
printDynamicRelocation(Obj, Rela, false);
}
}
+ if (DynRelrRegion.Size > 0) {
+ OS << "\n'RELR' relocation section at offset "
+ << format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) -
+ Obj->base(),
+ 1) << " contains " << DynRelrRegion.Size << " bytes:\n";
+ printRelocHeader(ELF::SHT_REL);
+ Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
+ std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ for (const Elf_Rela &Rela : RelrRelas) {
+ printDynamicRelocation(Obj, Rela, false);
+ }
+ }
if (DynPLTRelRegion.Size) {
OS << "\n'PLT' relocation section at offset "
<< format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) -
@@ -3229,11 +3403,11 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
1) << " contains " << DynPLTRelRegion.Size << " bytes:\n";
}
if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {
- printRelocHeader(OS, ELFT::Is64Bits, true);
+ printRelocHeader(ELF::SHT_RELA);
for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>())
printDynamicRelocation(Obj, Rela, true);
} else {
- printRelocHeader(OS, ELFT::Is64Bits, false);
+ printRelocHeader(ELF::SHT_REL);
for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) {
Elf_Rela Rela;
Rela.r_offset = Rel.r_offset;
@@ -3349,6 +3523,16 @@ void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
}
}
+template <class ELFT>
+void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
+ OS << "GNUStyle::printCGProfile not implemented\n";
+}
+
+template <class ELFT>
+void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) {
+ OS << "GNUStyle::printAddrsig not implemented\n";
+}
+
static std::string getGNUNoteTypeName(const uint32_t NT) {
static const struct {
uint32_t ID;
@@ -3358,6 +3542,7 @@ static std::string getGNUNoteTypeName(const uint32_t NT) {
{ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"},
{ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"},
{ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"},
+ {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},
};
for (const auto &Note : Notes)
@@ -3422,9 +3607,65 @@ static std::string getAMDGPUNoteTypeName(const uint32_t NT) {
}
template <typename ELFT>
+static void printGNUProperty(raw_ostream &OS, uint32_t Type, uint32_t DataSize,
+ ArrayRef<uint8_t> Data) {
+ switch (Type) {
+ default:
+ OS << format(" <application-specific type 0x%x>\n", Type);
+ return;
+ case GNU_PROPERTY_STACK_SIZE: {
+ OS << " stack size: ";
+ if (DataSize == sizeof(typename ELFT::uint))
+ OS << format("0x%llx\n",
+ (uint64_t)(*(const typename ELFT::Addr *)Data.data()));
+ else
+ OS << format("<corrupt length: 0x%x>\n", DataSize);
+ break;
+ }
+ case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+ OS << " no copy on protected";
+ if (DataSize)
+ OS << format(" <corrupt length: 0x%x>", DataSize);
+ OS << "\n";
+ break;
+ case GNU_PROPERTY_X86_FEATURE_1_AND:
+ OS << " X86 features: ";
+ if (DataSize != 4 && DataSize != 8) {
+ OS << format("<corrupt length: 0x%x>\n", DataSize);
+ break;
+ }
+ uint64_t CFProtection =
+ (DataSize == 4)
+ ? support::endian::read32<ELFT::TargetEndianness>(Data.data())
+ : support::endian::read64<ELFT::TargetEndianness>(Data.data());
+ if (CFProtection == 0) {
+ OS << "none\n";
+ break;
+ }
+ if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_IBT) {
+ OS << "IBT";
+ CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
+ if (CFProtection)
+ OS << ", ";
+ }
+ if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_SHSTK) {
+ OS << "SHSTK";
+ CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+ if (CFProtection)
+ OS << ", ";
+ }
+ if (CFProtection)
+ OS << format("<unknown flags: 0x%llx>", CFProtection);
+ OS << "\n";
+ break;
+ }
+}
+
+template <typename ELFT>
static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
- ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words,
- size_t Size) {
+ ArrayRef<typename ELFT::Word> Words, size_t Size) {
+ using Elf_Word = typename ELFT::Word;
+
switch (NoteType) {
default:
return;
@@ -3456,15 +3697,37 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
OS << " Version: "
<< StringRef(reinterpret_cast<const char *>(Words.data()), Size);
break;
- }
+ case ELF::NT_GNU_PROPERTY_TYPE_0:
+ OS << " Properties:";
+
+ ArrayRef<uint8_t> Arr(reinterpret_cast<const uint8_t *>(Words.data()),
+ Size);
+ while (Arr.size() >= 8) {
+ uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data());
+ uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4);
+ Arr = Arr.drop_front(8);
+
+ // Take padding size into account if present.
+ uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint));
+ if (Arr.size() < PaddedSize) {
+ OS << format(" <corrupt type (0x%x) datasz: 0x%x>\n", Type,
+ DataSize);
+ break;
+ }
+ printGNUProperty<ELFT>(OS, Type, DataSize, Arr.take_front(PaddedSize));
+ Arr = Arr.drop_front(PaddedSize);
+ }
+ if (!Arr.empty())
+ OS << " <corrupted GNU_PROPERTY_TYPE_0>";
+ break;
+ }
OS << '\n';
}
template <typename ELFT>
static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType,
- ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words,
- size_t Size) {
+ ArrayRef<typename ELFT::Word> Words, size_t Size) {
switch (NoteType) {
default:
return;
@@ -3499,66 +3762,66 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
const Elf_Ehdr *e = Obj->getHeader();
bool IsCore = e->e_type == ELF::ET_CORE;
- auto process = [&](const typename ELFFile<ELFT>::Elf_Off Offset,
- const typename ELFFile<ELFT>::Elf_Addr Size) {
- if (Size <= 0)
- return;
-
- const auto *P = static_cast<const uint8_t *>(Obj->base() + Offset);
- const auto *E = P + Size;
-
+ auto PrintHeader = [&](const typename ELFT::Off Offset,
+ const typename ELFT::Addr Size) {
OS << "Displaying notes found at file offset " << format_hex(Offset, 10)
<< " with length " << format_hex(Size, 10) << ":\n"
<< " Owner Data size\tDescription\n";
+ };
- while (P < E) {
- const Elf_Word *Words = reinterpret_cast<const Elf_Word *>(&P[0]);
-
- uint32_t NameSize = Words[0];
- uint32_t DescriptorSize = Words[1];
- uint32_t Type = Words[2];
-
- ArrayRef<Elf_Word> Descriptor(&Words[3 + (alignTo<4>(NameSize) / 4)],
- alignTo<4>(DescriptorSize) / 4);
-
- StringRef Name;
- if (NameSize)
- Name =
- StringRef(reinterpret_cast<const char *>(&Words[3]), NameSize - 1);
-
- OS << " " << Name << std::string(22 - NameSize, ' ')
- << format_hex(DescriptorSize, 10) << '\t';
-
- if (Name == "GNU") {
- OS << getGNUNoteTypeName(Type) << '\n';
- printGNUNote<ELFT>(OS, Type, Descriptor, DescriptorSize);
- } else if (Name == "FreeBSD") {
- OS << getFreeBSDNoteTypeName(Type) << '\n';
- } else if (Name == "AMD") {
- OS << getAMDGPUNoteTypeName(Type) << '\n';
- printAMDGPUNote<ELFT>(OS, Type, Descriptor, DescriptorSize);
- } else {
- OS << "Unknown note type: (" << format_hex(Type, 10) << ')';
- }
- OS << '\n';
-
- P = P + 3 * sizeof(Elf_Word) + alignTo<4>(NameSize) +
- alignTo<4>(DescriptorSize);
+ auto ProcessNote = [&](const Elf_Note &Note) {
+ StringRef Name = Note.getName();
+ ArrayRef<Elf_Word> Descriptor = Note.getDesc();
+ Elf_Word Type = Note.getType();
+
+ OS << " " << Name << std::string(22 - Name.size(), ' ')
+ << format_hex(Descriptor.size(), 10) << '\t';
+
+ if (Name == "GNU") {
+ OS << getGNUNoteTypeName(Type) << '\n';
+ printGNUNote<ELFT>(OS, Type, Descriptor, Descriptor.size());
+ } else if (Name == "FreeBSD") {
+ OS << getFreeBSDNoteTypeName(Type) << '\n';
+ } else if (Name == "AMD") {
+ OS << getAMDGPUNoteTypeName(Type) << '\n';
+ printAMDGPUNote<ELFT>(OS, Type, Descriptor, Descriptor.size());
+ } else {
+ OS << "Unknown note type: (" << format_hex(Type, 10) << ')';
}
+ OS << '\n';
};
if (IsCore) {
- for (const auto &P : unwrapOrError(Obj->program_headers()))
- if (P.p_type == PT_NOTE)
- process(P.p_offset, P.p_filesz);
+ for (const auto &P : unwrapOrError(Obj->program_headers())) {
+ if (P.p_type != PT_NOTE)
+ continue;
+ PrintHeader(P.p_offset, P.p_filesz);
+ Error Err = Error::success();
+ for (const auto &Note : Obj->notes(P, Err))
+ ProcessNote(Note);
+ if (Err)
+ error(std::move(Err));
+ }
} else {
- for (const auto &S : unwrapOrError(Obj->sections()))
- if (S.sh_type == SHT_NOTE)
- process(S.sh_offset, S.sh_size);
+ for (const auto &S : unwrapOrError(Obj->sections())) {
+ if (S.sh_type != SHT_NOTE)
+ continue;
+ PrintHeader(S.sh_offset, S.sh_size);
+ Error Err = Error::success();
+ for (const auto &Note : Obj->notes(S, Err))
+ ProcessNote(Note);
+ if (Err)
+ error(std::move(Err));
+ }
}
}
template <class ELFT>
+void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
+ OS << "printELFLinkerOptions not implemented!\n";
+}
+
+template <class ELFT>
void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
size_t Bias = ELFT::Is64Bits ? 8 : 0;
auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
@@ -3715,7 +3978,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
unsigned(ELF::EF_MIPS_MACH));
else if (e->e_machine == EM_AMDGPU)
W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags),
- unsigned(ELF::EF_AMDGPU_ARCH));
+ unsigned(ELF::EF_AMDGPU_MACH));
else if (e->e_machine == EM_RISCV)
W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderRISCVFlags));
else
@@ -3724,8 +3987,8 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
W.printNumber("ProgramHeaderEntrySize", e->e_phentsize);
W.printNumber("ProgramHeaderCount", e->e_phnum);
W.printNumber("SectionHeaderEntrySize", e->e_shentsize);
- W.printNumber("SectionHeaderCount", e->e_shnum);
- W.printNumber("StringTableSectionIndex", e->e_shstrndx);
+ W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj));
+ W.printString("StringTableSectionIndex", getSectionHeaderTableIndexString(Obj));
}
}
@@ -3738,6 +4001,8 @@ void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) {
DictScope D(W, "Group");
W.printNumber("Name", G.Name, G.ShName);
W.printNumber("Index", G.Index);
+ W.printNumber("Link", G.Link);
+ W.printNumber("Info", G.Info);
W.printHex("Type", getGroupType(G.Type), G.Type);
W.startLine() << "Signature: " << G.Signature << "\n";
@@ -3768,9 +4033,12 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
++SectionNumber;
- if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
+ if (Sec.sh_type != ELF::SHT_REL &&
+ Sec.sh_type != ELF::SHT_RELA &&
+ Sec.sh_type != ELF::SHT_RELR &&
Sec.sh_type != ELF::SHT_ANDROID_REL &&
- Sec.sh_type != ELF::SHT_ANDROID_RELA)
+ Sec.sh_type != ELF::SHT_ANDROID_RELA &&
+ Sec.sh_type != ELF::SHT_ANDROID_RELR)
continue;
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
@@ -3803,6 +4071,19 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec)))
printRelocation(Obj, R, SymTab);
break;
+ case ELF::SHT_RELR:
+ case ELF::SHT_ANDROID_RELR: {
+ Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec));
+ if (opts::RawRelr) {
+ for (const Elf_Relr &R : Relrs)
+ W.startLine() << W.hex(R) << "\n";
+ } else {
+ std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ for (const Elf_Rela &R : RelrRelas)
+ printRelocation(Obj, R, SymTab);
+ }
+ break;
+ }
case ELF::SHT_ANDROID_REL:
case ELF::SHT_ANDROID_RELA:
for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec)))
@@ -3983,6 +4264,7 @@ template <class ELFT>
void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion();
const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion();
+ const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion();
const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion();
if (DynRelRegion.Size && DynRelaRegion.Size)
report_fatal_error("There are both REL and RELA dynamic relocations");
@@ -3999,6 +4281,12 @@ void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
Rela.r_addend = 0;
printDynamicRelocation(Obj, Rela);
}
+ if (DynRelrRegion.Size > 0) {
+ Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
+ std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ for (const Elf_Rela &Rela : RelrRelas)
+ printDynamicRelocation(Obj, Rela);
+ }
if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela))
for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>())
printDynamicRelocation(Obj, Rela);
@@ -4062,11 +4350,71 @@ void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
}
template <class ELFT>
+void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
+ ListScope L(W, "CGProfile");
+ if (!this->dumper()->getDotCGProfileSec())
+ return;
+ auto CGProfile =
+ unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>(
+ this->dumper()->getDotCGProfileSec()));
+ for (const Elf_CGProfile &CGPE : CGProfile) {
+ DictScope D(W, "CGProfileEntry");
+ W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from),
+ CGPE.cgp_from);
+ W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to),
+ CGPE.cgp_to);
+ W.printNumber("Weight", CGPE.cgp_weight);
+ }
+}
+
+template <class ELFT>
+void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) {
+ ListScope L(W, "Addrsig");
+ if (!this->dumper()->getDotAddrsigSec())
+ return;
+ ArrayRef<uint8_t> Contents = unwrapOrError(
+ Obj->getSectionContents(this->dumper()->getDotAddrsigSec()));
+ const uint8_t *Cur = Contents.begin();
+ const uint8_t *End = Contents.end();
+ while (Cur != End) {
+ unsigned Size;
+ const char *Err;
+ uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);
+ if (Err)
+ reportError(Err);
+ W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex),
+ SymIndex);
+ Cur += Size;
+ }
+}
+
+template <class ELFT>
void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
W.startLine() << "printNotes not implemented!\n";
}
template <class ELFT>
+void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
+ ListScope L(W, "LinkerOptions");
+
+ for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) {
+ if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS)
+ continue;
+
+ ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr));
+ for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) {
+ StringRef Key = StringRef(reinterpret_cast<const char *>(P));
+ StringRef Value =
+ StringRef(reinterpret_cast<const char *>(P) + Key.size() + 1);
+
+ W.printString(Key, Value);
+
+ P = P + Key.size() + Value.size() + 2;
+ }
+ }
+}
+
+template <class ELFT>
void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
auto PrintEntry = [&](const Elf_Addr *E) {
W.printHex("Address", Parser.getGotAddress(E));
diff --git a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
index 64178d7b33ad..69ef1556f78d 100644
--- a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -669,12 +669,11 @@ void MachODumper::printStackMap() const {
StackMapContents.size());
if (Obj->isLittleEndian())
- prettyPrintStackMap(
- llvm::outs(),
- StackMapV2Parser<support::little>(StackMapContentsArray));
+ prettyPrintStackMap(
+ W, StackMapV2Parser<support::little>(StackMapContentsArray));
else
- prettyPrintStackMap(llvm::outs(),
- StackMapV2Parser<support::big>(StackMapContentsArray));
+ prettyPrintStackMap(W,
+ StackMapV2Parser<support::big>(StackMapContentsArray));
}
void MachODumper::printNeededLibraries() {
diff --git a/contrib/llvm/tools/llvm-readobj/ObjDumper.cpp b/contrib/llvm/tools/llvm-readobj/ObjDumper.cpp
index 2a0a90e5cfd5..a725140c9d33 100644
--- a/contrib/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -8,13 +8,15 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements ObjDumper.
+/// This file implements ObjDumper.
///
//===----------------------------------------------------------------------===//
#include "ObjDumper.h"
#include "Error.h"
+#include "llvm-readobj.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
@@ -25,4 +27,122 @@ ObjDumper::ObjDumper(ScopedPrinter &Writer) : W(Writer) {}
ObjDumper::~ObjDumper() {
}
+static void printAsPrintable(raw_ostream &W, const uint8_t *Start, size_t Len) {
+ for (size_t i = 0; i < Len; i++)
+ W << (isPrint(Start[i]) ? static_cast<char>(Start[i]) : '.');
+}
+
+static Expected<object::SectionRef>
+getSecNameOrIndexAsSecRef(const object::ObjectFile *Obj, StringRef SecName) {
+ char *StrPtr;
+ long SectionIndex = strtol(SecName.data(), &StrPtr, 10);
+ object::SectionRef Section;
+ long SecIndex;
+ if (Obj->isELF())
+ SecIndex = 0;
+ else
+ SecIndex = 1;
+ for (object::SectionRef SecRef : Obj->sections()) {
+ if (*StrPtr) {
+ StringRef SectionName;
+
+ if (std::error_code E = SecRef.getName(SectionName))
+ return errorCodeToError(E);
+
+ if (SectionName == SecName)
+ return SecRef;
+ } else if (SecIndex == SectionIndex)
+ return SecRef;
+
+ SecIndex++;
+ }
+ return make_error<StringError>("invalid section reference",
+ object::object_error::parse_failed);
+}
+
+void ObjDumper::printSectionAsString(const object::ObjectFile *Obj,
+ StringRef SecName) {
+ Expected<object::SectionRef> SectionRefOrError =
+ getSecNameOrIndexAsSecRef(Obj, SecName);
+ if (!SectionRefOrError)
+ error(std::move(SectionRefOrError));
+ object::SectionRef Section = *SectionRefOrError;
+ StringRef SectionName;
+
+ if (std::error_code E = Section.getName(SectionName))
+ error(E);
+ W.startLine() << "String dump of section '" << SectionName << "':\n";
+
+ StringRef SectionContent;
+ Section.getContents(SectionContent);
+
+ const uint8_t *SecContent = SectionContent.bytes_begin();
+ const uint8_t *CurrentWord = SecContent;
+ const uint8_t *SecEnd = SectionContent.bytes_end();
+
+ while (CurrentWord <= SecEnd) {
+ size_t WordSize = strnlen(reinterpret_cast<const char *>(CurrentWord),
+ SecEnd - CurrentWord);
+ if (!WordSize) {
+ CurrentWord++;
+ continue;
+ }
+ W.startLine() << format("[%6tx] ", CurrentWord - SecContent);
+ printAsPrintable(W.startLine(), CurrentWord, WordSize);
+ W.startLine() << '\n';
+ CurrentWord += WordSize + 1;
+ }
+}
+
+void ObjDumper::printSectionAsHex(const object::ObjectFile *Obj,
+ StringRef SecName) {
+ Expected<object::SectionRef> SectionRefOrError =
+ getSecNameOrIndexAsSecRef(Obj, SecName);
+ if (!SectionRefOrError)
+ error(std::move(SectionRefOrError));
+ object::SectionRef Section = *SectionRefOrError;
+ StringRef SectionName;
+
+ if (std::error_code E = Section.getName(SectionName))
+ error(E);
+ W.startLine() << "Hex dump of section '" << SectionName << "':\n";
+
+ StringRef SectionContent;
+ Section.getContents(SectionContent);
+ const uint8_t *SecContent = SectionContent.bytes_begin();
+ const uint8_t *SecEnd = SecContent + SectionContent.size();
+
+ for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) {
+ const uint8_t *TmpSecPtr = SecPtr;
+ uint8_t i;
+ uint8_t k;
+
+ W.startLine() << format_hex(SecPtr - SecContent, 10);
+ W.startLine() << ' ';
+ for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) {
+ for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) {
+ uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr));
+ W.startLine() << format_hex_no_prefix(Val, 2);
+ }
+ W.startLine() << ' ';
+ }
+
+ // We need to print the correct amount of spaces to match the format.
+ // We are adding the (4 - i) last rows that are 8 characters each.
+ // Then, the (4 - i) spaces that are in between the rows.
+ // Least, if we cut in a middle of a row, we add the remaining characters,
+ // which is (8 - (k * 2))
+ if (i < 4)
+ W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)),
+ ' ');
+
+ TmpSecPtr = SecPtr;
+ for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i)
+ W.startLine() << (isPrint(TmpSecPtr[i]) ? static_cast<char>(TmpSecPtr[i])
+ : '.');
+
+ W.startLine() << '\n';
+ }
+}
+
} // namespace llvm
diff --git a/contrib/llvm/tools/llvm-readobj/ObjDumper.h b/contrib/llvm/tools/llvm-readobj/ObjDumper.h
index c5b331d944a2..8c3a7bec73be 100644
--- a/contrib/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/contrib/llvm/tools/llvm-readobj/ObjDumper.h
@@ -13,6 +13,9 @@
#include <memory>
#include <system_error>
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ObjectFile.h"
+
namespace llvm {
namespace object {
class COFFImportFile;
@@ -41,13 +44,17 @@ public:
virtual void printDynamicTable() { }
virtual void printNeededLibraries() { }
virtual void printProgramHeaders() { }
+ virtual void printSectionAsHex(StringRef SectionName) {}
virtual void printHashTable() { }
virtual void printGnuHashTable() { }
virtual void printLoadName() {}
virtual void printVersionInfo() {}
virtual void printGroupSections() {}
virtual void printHashHistogram() {}
+ virtual void printCGProfile() {}
+ virtual void printAddrsig() {}
virtual void printNotes() {}
+ virtual void printELFLinkerOptions() {}
// Only implemented for ARM ELF at this time.
virtual void printAttributes() { }
@@ -81,6 +88,9 @@ public:
virtual void printStackMap() const = 0;
+ void printSectionAsString(const object::ObjectFile *Obj, StringRef SecName);
+ void printSectionAsHex(const object::ObjectFile *Obj, StringRef SecName);
+
protected:
ScopedPrinter &W;
};
@@ -101,7 +111,8 @@ std::error_code createWasmDumper(const object::ObjectFile *Obj,
ScopedPrinter &Writer,
std::unique_ptr<ObjDumper> &Result);
-void dumpCOFFImportFile(const object::COFFImportFile *File);
+void dumpCOFFImportFile(const object::COFFImportFile *File,
+ ScopedPrinter &Writer);
void dumpCodeViewMergedTypes(
ScopedPrinter &Writer, llvm::codeview::MergingTypeTableBuilder &IDTable,
diff --git a/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h b/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h
index f4ed68e92d78..77a054b178a5 100644
--- a/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h
+++ b/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h
@@ -11,69 +11,70 @@
#define LLVM_TOOLS_LLVM_READOBJ_STACKMAPPRINTER_H
#include "llvm/Object/StackMapParser.h"
+#include "llvm/Support/ScopedPrinter.h"
namespace llvm {
// Pretty print a stackmap to the given ostream.
-template <typename OStreamT, typename StackMapParserT>
-void prettyPrintStackMap(OStreamT &OS, const StackMapParserT &SMP) {
+template <typename StackMapParserT>
+void prettyPrintStackMap(ScopedPrinter &W, const StackMapParserT &SMP) {
- OS << "LLVM StackMap Version: " << SMP.getVersion()
- << "\nNum Functions: " << SMP.getNumFunctions();
+ W.printNumber("LLVM StackMap Version", SMP.getVersion());
+ W.printNumber("Num Functions", SMP.getNumFunctions());
// Functions:
for (const auto &F : SMP.functions())
- OS << "\n Function address: " << F.getFunctionAddress()
+ W.startLine() << " Function address: " << F.getFunctionAddress()
<< ", stack size: " << F.getStackSize()
- << ", callsite record count: " << F.getRecordCount();
+ << ", callsite record count: " << F.getRecordCount() << "\n";
// Constants:
- OS << "\nNum Constants: " << SMP.getNumConstants();
+ W.printNumber("Num Constants", SMP.getNumConstants());
unsigned ConstantIndex = 0;
for (const auto &C : SMP.constants())
- OS << "\n #" << ++ConstantIndex << ": " << C.getValue();
+ W.startLine() << " #" << ++ConstantIndex << ": " << C.getValue() << "\n";
// Records:
- OS << "\nNum Records: " << SMP.getNumRecords();
+ W.printNumber("Num Records", SMP.getNumRecords());
for (const auto &R : SMP.records()) {
- OS << "\n Record ID: " << R.getID()
- << ", instruction offset: " << R.getInstructionOffset()
- << "\n " << R.getNumLocations() << " locations:";
+ W.startLine() << " Record ID: " << R.getID()
+ << ", instruction offset: " << R.getInstructionOffset()
+ << "\n";
+ W.startLine() << " " << R.getNumLocations() << " locations:\n";
unsigned LocationIndex = 0;
for (const auto &Loc : R.locations()) {
- OS << "\n #" << ++LocationIndex << ": ";
+ raw_ostream &OS = W.startLine();
+ OS << " #" << ++LocationIndex << ": ";
switch (Loc.getKind()) {
case StackMapParserT::LocationKind::Register:
- OS << "Register R#" << Loc.getDwarfRegNum();
+ OS << "Register R#" << Loc.getDwarfRegNum() << "\n";
break;
case StackMapParserT::LocationKind::Direct:
- OS << "Direct R#" << Loc.getDwarfRegNum() << " + "
- << Loc.getOffset();
+ OS << "Direct R#" << Loc.getDwarfRegNum() << " + " << Loc.getOffset()
+ << "\n";
break;
case StackMapParserT::LocationKind::Indirect:
- OS << "Indirect [R#" << Loc.getDwarfRegNum() << " + "
- << Loc.getOffset() << "]";
+ OS << "Indirect [R#" << Loc.getDwarfRegNum() << " + " << Loc.getOffset()
+ << "]\n";
break;
case StackMapParserT::LocationKind::Constant:
- OS << "Constant " << Loc.getSmallConstant();
+ OS << "Constant " << Loc.getSmallConstant() << "\n";
break;
case StackMapParserT::LocationKind::ConstantIndex:
OS << "ConstantIndex #" << Loc.getConstantIndex() << " ("
- << SMP.getConstant(Loc.getConstantIndex()).getValue() << ")";
+ << SMP.getConstant(Loc.getConstantIndex()).getValue() << ")\n";
break;
}
}
- OS << "\n " << R.getNumLiveOuts() << " live-outs: [ ";
+ raw_ostream &OS = W.startLine();
+ OS << " " << R.getNumLiveOuts() << " live-outs: [ ";
for (const auto &LO : R.liveouts())
OS << "R#" << LO.getDwarfRegNum() << " ("
<< LO.getSizeInBytes() << "-bytes) ";
OS << "]\n";
}
-
- OS << "\n";
-
}
}
diff --git a/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp b/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp
index 223c1c752469..ce224836225e 100644
--- a/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -23,12 +23,11 @@ using namespace object;
namespace {
static const EnumEntry<unsigned> WasmSymbolTypes[] = {
-#define ENUM_ENTRY(X) { #X, static_cast<unsigned>(WasmSymbol::SymbolType::X) }
- ENUM_ENTRY(FUNCTION_IMPORT),
- ENUM_ENTRY(FUNCTION_EXPORT),
- ENUM_ENTRY(GLOBAL_IMPORT),
- ENUM_ENTRY(GLOBAL_EXPORT),
- ENUM_ENTRY(DEBUG_FUNCTION_NAME),
+#define ENUM_ENTRY(X) { #X, wasm::WASM_SYMBOL_TYPE_##X }
+ ENUM_ENTRY(FUNCTION),
+ ENUM_ENTRY(DATA),
+ ENUM_ENTRY(GLOBAL),
+ ENUM_ENTRY(SECTION),
#undef ENUM_ENTRY
};
@@ -81,11 +80,18 @@ void WasmDumper::printRelocation(const SectionRef &Section,
Reloc.getTypeName(RelocTypeName);
const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);
+ StringRef SymName;
+ symbol_iterator SI = Reloc.getSymbol();
+ if (SI != Obj->symbol_end())
+ SymName = error(SI->getName());
+
bool HasAddend = false;
switch (RelocType) {
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
HasAddend = true;
break;
default:
@@ -95,13 +101,19 @@ void WasmDumper::printRelocation(const SectionRef &Section,
DictScope Group(W, "Relocation");
W.printNumber("Type", RelocTypeName, RelocType);
W.printHex("Offset", Reloc.getOffset());
- W.printHex("Index", WasmReloc.Index);
+ if (!SymName.empty())
+ W.printString("Symbol", SymName);
+ else
+ W.printHex("Index", WasmReloc.Index);
if (HasAddend)
W.printNumber("Addend", WasmReloc.Addend);
} else {
raw_ostream& OS = W.startLine();
- OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << "["
- << WasmReloc.Index << "]";
+ OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
+ if (!SymName.empty())
+ OS << SymName;
+ else
+ OS << WasmReloc.Index;
if (HasAddend)
OS << " " << WasmReloc.Addend;
OS << "\n";
@@ -155,12 +167,10 @@ void WasmDumper::printSections() {
W.printString("Name", WasmSec.Name);
if (WasmSec.Name == "linking") {
const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
- W.printNumber("DataSize", LinkingData.DataSize);
if (!LinkingData.InitFunctions.empty()) {
ListScope Group(W, "InitFunctions");
for (const wasm::WasmInitFunc &F: LinkingData.InitFunctions)
- W.startLine() << F.FunctionIndex << " (priority=" << F.Priority
- << ")\n";
+ W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";
}
}
break;
@@ -204,9 +214,9 @@ void WasmDumper::printSections() {
void WasmDumper::printSymbol(const SymbolRef &Sym) {
DictScope D(W, "Symbol");
WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
- W.printString("Name", Symbol.Name);
- W.printEnum("Type", static_cast<unsigned>(Symbol.Type), makeArrayRef(WasmSymbolTypes));
- W.printHex("Flags", Symbol.Flags);
+ W.printString("Name", Symbol.Info.Name);
+ W.printEnum("Type", Symbol.Info.Kind, makeArrayRef(WasmSymbolTypes));
+ W.printHex("Flags", Symbol.Info.Flags);
}
}
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
index c076582794fe..a7236c02b8ae 100644
--- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -34,11 +34,10 @@
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -147,6 +146,18 @@ namespace opts {
cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"),
cl::aliasopt(ProgramHeaders));
+ // -string-dump
+ cl::list<std::string> StringDump("string-dump", cl::desc("<number|name>"),
+ cl::ZeroOrMore);
+ cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"),
+ cl::aliasopt(StringDump));
+
+ // -hex-dump
+ cl::list<std::string> HexDump("hex-dump", cl::desc("<number|name>"),
+ cl::ZeroOrMore);
+ cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"),
+ cl::aliasopt(HexDump));
+
// -hash-table
cl::opt<bool> HashTable("hash-table",
cl::desc("Display ELF hash table"));
@@ -159,6 +170,10 @@ namespace opts {
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
+ // -raw-relr
+ cl::opt<bool> RawRelr("raw-relr",
+ cl::desc("Do not decode relocations in SHT_RELR section, display raw contents"));
+
// -codeview
cl::opt<bool> CodeView("codeview",
cl::desc("Display CodeView debug information"));
@@ -228,6 +243,11 @@ namespace opts {
COFFLoadConfig("coff-load-config",
cl::desc("Display the PE/COFF load config"));
+ // -elf-linker-options
+ cl::opt<bool>
+ ELFLinkerOptions("elf-linker-options",
+ cl::desc("Display the ELF .linker-options section"));
+
// -macho-data-in-code
cl::opt<bool>
MachODataInCode("macho-data-in-code",
@@ -280,6 +300,11 @@ namespace opts {
cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"),
cl::aliasopt(HashHistogram));
+ cl::opt<bool> CGProfile("elf-cg-profile", cl::desc("Display callgraph profile section"));
+
+ cl::opt<bool> Addrsig("elf-addrsig",
+ cl::desc("Display address-significance table"));
+
cl::opt<OutputStyleTy>
Output("elf-output-style", cl::desc("Specify ELF dump style"),
cl::values(clEnumVal(LLVM, "LLVM default style"),
@@ -355,7 +380,7 @@ struct ReadObjTypeTableBuilder {
}
static ReadObjTypeTableBuilder CVTypes;
-/// @brief Creates an format-specific object file dumper.
+/// Creates an format-specific object file dumper.
static std::error_code createDumper(const ObjectFile *Obj,
ScopedPrinter &Writer,
std::unique_ptr<ObjDumper> &Result) {
@@ -374,20 +399,20 @@ static std::error_code createDumper(const ObjectFile *Obj,
return readobj_error::unsupported_obj_file_format;
}
-/// @brief Dumps the specified object file.
-static void dumpObject(const ObjectFile *Obj) {
- ScopedPrinter Writer(outs());
+/// Dumps the specified object file.
+static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) {
std::unique_ptr<ObjDumper> Dumper;
if (std::error_code EC = createDumper(Obj, Writer, Dumper))
reportError(Obj->getFileName(), EC);
if (opts::Output == opts::LLVM) {
- outs() << '\n';
- outs() << "File: " << Obj->getFileName() << "\n";
- outs() << "Format: " << Obj->getFileFormatName() << "\n";
- outs() << "Arch: " << Triple::getArchTypeName(
- (llvm::Triple::ArchType)Obj->getArch()) << "\n";
- outs() << "AddressSize: " << (8 * Obj->getBytesInAddress()) << "bit\n";
+ Writer.startLine() << "\n";
+ Writer.printString("File", Obj->getFileName());
+ Writer.printString("Format", Obj->getFileFormatName());
+ Writer.printString("Arch", Triple::getArchTypeName(
+ (llvm::Triple::ArchType)Obj->getArch()));
+ Writer.printString("AddressSize",
+ formatv("{0}bit", 8 * Obj->getBytesInAddress()));
Dumper->printLoadName();
}
@@ -411,6 +436,14 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printNeededLibraries();
if (opts::ProgramHeaders)
Dumper->printProgramHeaders();
+ if (!opts::StringDump.empty())
+ llvm::for_each(opts::StringDump, [&Dumper, Obj](StringRef SectionName) {
+ Dumper->printSectionAsString(Obj, SectionName);
+ });
+ if (!opts::HexDump.empty())
+ llvm::for_each(opts::HexDump, [&Dumper, Obj](StringRef SectionName) {
+ Dumper->printSectionAsHex(Obj, SectionName);
+ });
if (opts::HashTable)
Dumper->printHashTable();
if (opts::GnuHashTable)
@@ -418,6 +451,8 @@ static void dumpObject(const ObjectFile *Obj) {
if (opts::VersionInfo)
Dumper->printVersionInfo();
if (Obj->isELF()) {
+ if (opts::ELFLinkerOptions)
+ Dumper->printELFLinkerOptions();
if (Obj->getArch() == llvm::Triple::arm)
if (opts::ARMAttributes)
Dumper->printAttributes();
@@ -435,6 +470,10 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printGroupSections();
if (opts::HashHistogram)
Dumper->printHashHistogram();
+ if (opts::CGProfile)
+ Dumper->printCGProfile();
+ if (opts::Addrsig)
+ Dumper->printAddrsig();
if (opts::Notes)
Dumper->printNotes();
}
@@ -476,8 +515,8 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printStackMap();
}
-/// @brief Dumps each object file in \a Arc;
-static void dumpArchive(const Archive *Arc) {
+/// Dumps each object file in \a Arc;
+static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
Error Err = Error::success();
for (auto &Child : Arc->children(Err)) {
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
@@ -488,9 +527,9 @@ static void dumpArchive(const Archive *Arc) {
continue;
}
if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
- dumpObject(Obj);
+ dumpObject(Obj, Writer);
else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(&*ChildOrErr.get()))
- dumpCOFFImportFile(Imp);
+ dumpCOFFImportFile(Imp, Writer);
else
reportError(Arc->getFileName(), readobj_error::unrecognized_file_format);
}
@@ -498,21 +537,22 @@ static void dumpArchive(const Archive *Arc) {
reportError(Arc->getFileName(), std::move(Err));
}
-/// @brief Dumps each object file in \a MachO Universal Binary;
-static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) {
+/// Dumps each object file in \a MachO Universal Binary;
+static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
+ ScopedPrinter &Writer) {
for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
if (ObjOrErr)
- dumpObject(&*ObjOrErr.get());
+ dumpObject(&*ObjOrErr.get(), Writer);
else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
reportError(UBinary->getFileName(), ObjOrErr.takeError());
}
else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
- dumpArchive(&*AOrErr.get());
+ dumpArchive(&*AOrErr.get(), Writer);
}
}
-/// @brief Dumps \a WinRes, Windows Resource (.res) file;
+/// Dumps \a WinRes, Windows Resource (.res) file;
static void dumpWindowsResourceFile(WindowsResource *WinRes) {
ScopedPrinter Printer{outs()};
WindowsRes::Dumper Dumper(WinRes, Printer);
@@ -521,8 +561,9 @@ static void dumpWindowsResourceFile(WindowsResource *WinRes) {
}
-/// @brief Opens \a File and dumps it.
+/// Opens \a File and dumps it.
static void dumpInput(StringRef File) {
+ ScopedPrinter Writer(outs());
// Attempt to open the binary.
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
@@ -531,14 +572,14 @@ static void dumpInput(StringRef File) {
Binary &Binary = *BinaryOrErr.get().getBinary();
if (Archive *Arc = dyn_cast<Archive>(&Binary))
- dumpArchive(Arc);
+ dumpArchive(Arc, Writer);
else if (MachOUniversalBinary *UBinary =
dyn_cast<MachOUniversalBinary>(&Binary))
- dumpMachOUniversalBinary(UBinary);
+ dumpMachOUniversalBinary(UBinary, Writer);
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
- dumpObject(Obj);
+ dumpObject(Obj, Writer);
else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary))
- dumpCOFFImportFile(Import);
+ dumpCOFFImportFile(Import, Writer);
else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary))
dumpWindowsResourceFile(WinRes);
else
@@ -546,17 +587,14 @@ static void dumpInput(StringRef File) {
}
int main(int argc, const char *argv[]) {
- StringRef ToolName = argv[0];
- sys::PrintStackTraceOnErrorSignal(ToolName);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y;
+ InitLLVM X(argc, argv);
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
opts::WideOutput.setHiddenFlag(cl::Hidden);
- if (sys::path::stem(ToolName).find("readelf") != StringRef::npos)
+ if (sys::path::stem(argv[0]).find("readelf") != StringRef::npos)
opts::Output = opts::GNU;
cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n");
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
index 840ddbabdc59..374ffd03e13a 100644
--- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -60,6 +60,7 @@ namespace opts {
extern llvm::cl::opt<bool> DynamicSymbols;
extern llvm::cl::opt<bool> UnwindInfo;
extern llvm::cl::opt<bool> ExpandRelocs;
+ extern llvm::cl::opt<bool> RawRelr;
extern llvm::cl::opt<bool> CodeView;
extern llvm::cl::opt<bool> CodeViewSubsectionBytes;
extern llvm::cl::opt<bool> ARMAttributes;
diff --git a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index b09594622ca9..54db1ec113fc 100644
--- a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -27,11 +27,9 @@
#include "llvm/Object/SymbolSize.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
@@ -42,7 +40,7 @@ using namespace llvm::object;
static cl::list<std::string>
InputFileList(cl::Positional, cl::ZeroOrMore,
- cl::desc("<input file>"));
+ cl::desc("<input files>"));
enum ActionType {
AC_Execute,
@@ -736,11 +734,8 @@ static int linkAndVerify() {
}
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
-
+ InitLLVM X(argc, argv);
ProgramName = argv[0];
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
diff --git a/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index b51ec513f23b..6d40a5403504 100644
--- a/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -22,10 +22,8 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <cstring>
@@ -103,24 +101,19 @@ static bool error(Expected<T> &ResOrErr) {
static bool parseCommand(StringRef InputString, bool &IsData,
std::string &ModuleName, uint64_t &ModuleOffset) {
- const char *kDataCmd = "DATA ";
- const char *kCodeCmd = "CODE ";
const char kDelimiters[] = " \n\r";
- IsData = false;
ModuleName = "";
- const char *pos = InputString.data();
- if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) {
- IsData = true;
- pos += strlen(kDataCmd);
- } else if (strncmp(pos, kCodeCmd, strlen(kCodeCmd)) == 0) {
+ if (InputString.consume_front("CODE ")) {
IsData = false;
- pos += strlen(kCodeCmd);
+ } else if (InputString.consume_front("DATA ")) {
+ IsData = true;
} else {
// If no cmd, assume it's CODE.
IsData = false;
}
+ const char *pos = InputString.data();
// Skip delimiters and parse input filename (if needed).
- if (ClBinaryName == "") {
+ if (ClBinaryName.empty()) {
pos += strspn(pos, kDelimiters);
if (*pos == '"' || *pos == '\'') {
char quote = *pos;
@@ -145,10 +138,7 @@ static bool parseCommand(StringRef InputString, bool &IsData,
}
int main(int argc, char **argv) {
- // Print stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
@@ -188,7 +178,7 @@ int main(int argc, char **argv) {
if (ClPrintAddress) {
outs() << "0x";
outs().write_hex(ModuleOffset);
- StringRef Delimiter = (ClPrettyPrint == true) ? ": " : "\n";
+ StringRef Delimiter = ClPrettyPrint ? ": " : "\n";
outs() << Delimiter;
}
if (IsData) {
diff --git a/contrib/llvm/tools/llvm-xray/func-id-helper.cc b/contrib/llvm/tools/llvm-xray/func-id-helper.cpp
index 3234010695b2..c2bef6ddfb39 100644
--- a/contrib/llvm/tools/llvm-xray/func-id-helper.cc
+++ b/contrib/llvm/tools/llvm-xray/func-id-helper.cpp
@@ -1,4 +1,4 @@
-//===- xray-fc-account.cc - XRay Function Call Accounting Tool ------------===//
+//===- xray-fc-account.cpp: XRay Function Call Accounting Tool ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,10 @@ using namespace llvm;
using namespace xray;
std::string FuncIdConversionHelper::SymbolOrNumber(int32_t FuncId) const {
+ auto CacheIt = CachedNames.find(FuncId);
+ if (CacheIt != CachedNames.end())
+ return CacheIt->second;
+
std::ostringstream F;
auto It = FunctionAddresses.find(FuncId);
if (It == FunctionAddresses.end()) {
@@ -37,7 +41,9 @@ std::string FuncIdConversionHelper::SymbolOrNumber(int32_t FuncId) const {
F << "@(" << std::hex << It->second << ")";
});
- return F.str();
+ auto S = F.str();
+ CachedNames[FuncId] = S;
+ return S;
}
std::string FuncIdConversionHelper::FileLineAndColumn(int32_t FuncId) const {
diff --git a/contrib/llvm/tools/llvm-xray/func-id-helper.h b/contrib/llvm/tools/llvm-xray/func-id-helper.h
index 7348a7100b05..3e0780d54f90 100644
--- a/contrib/llvm/tools/llvm-xray/func-id-helper.h
+++ b/contrib/llvm/tools/llvm-xray/func-id-helper.h
@@ -13,6 +13,7 @@
#ifndef LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
#define LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include <unordered_map>
@@ -28,6 +29,7 @@ private:
std::string BinaryInstrMap;
symbolize::LLVMSymbolizer &Symbolizer;
const FunctionAddressMap &FunctionAddresses;
+ mutable llvm::DenseMap<int32_t, std::string> CachedNames;
public:
FuncIdConversionHelper(std::string BinaryInstrMap,
diff --git a/contrib/llvm/tools/llvm-xray/llvm-xray.cc b/contrib/llvm/tools/llvm-xray/llvm-xray.cpp
index 17cc9f90dd71..e74628f5025f 100644
--- a/contrib/llvm/tools/llvm-xray/llvm-xray.cc
+++ b/contrib/llvm/tools/llvm-xray/llvm-xray.cpp
@@ -1,4 +1,4 @@
-//===- llvm-xray.cc - XRay Tool Main Program ------------------------------===//
+//===- llvm-xray.cpp: XRay Tool Main Program ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-xray/xray-account.cc b/contrib/llvm/tools/llvm-xray/xray-account.cpp
index 7b684aad693d..2776a8888481 100644
--- a/contrib/llvm/tools/llvm-xray/xray-account.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-account.cpp
@@ -237,16 +237,19 @@ ResultRow getStats(std::vector<uint64_t> &Timings) {
auto MinMax = std::minmax_element(Timings.begin(), Timings.end());
R.Min = *MinMax.first;
R.Max = *MinMax.second;
+ R.Count = Timings.size();
+
auto MedianOff = Timings.size() / 2;
std::nth_element(Timings.begin(), Timings.begin() + MedianOff, Timings.end());
R.Median = Timings[MedianOff];
+
auto Pct90Off = std::floor(Timings.size() * 0.9);
std::nth_element(Timings.begin(), Timings.begin() + Pct90Off, Timings.end());
R.Pct90 = Timings[Pct90Off];
+
auto Pct99Off = std::floor(Timings.size() * 0.99);
- std::nth_element(Timings.begin(), Timings.begin() + Pct90Off, Timings.end());
+ std::nth_element(Timings.begin(), Timings.begin() + Pct99Off, Timings.end());
R.Pct99 = Timings[Pct99Off];
- R.Count = Timings.size();
return R;
}
@@ -279,79 +282,79 @@ void LatencyAccountant::exportStats(const XRayFileHeader &Header, F Fn) const {
// Sort the data according to user-provided flags.
switch (AccountSortOutput) {
case SortField::FUNCID:
- std::sort(Results.begin(), Results.end(),
- [](const TupleType &L, const TupleType &R) {
- if (AccountSortOrder == SortDirection::ASCENDING)
- return std::get<0>(L) < std::get<0>(R);
- if (AccountSortOrder == SortDirection::DESCENDING)
- return std::get<0>(L) > std::get<0>(R);
- llvm_unreachable("Unknown sort direction");
- });
+ llvm::sort(Results.begin(), Results.end(),
+ [](const TupleType &L, const TupleType &R) {
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return std::get<0>(L) < std::get<0>(R);
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return std::get<0>(L) > std::get<0>(R);
+ llvm_unreachable("Unknown sort direction");
+ });
break;
case SortField::COUNT:
- std::sort(Results.begin(), Results.end(),
- [](const TupleType &L, const TupleType &R) {
- if (AccountSortOrder == SortDirection::ASCENDING)
- return std::get<1>(L) < std::get<1>(R);
- if (AccountSortOrder == SortDirection::DESCENDING)
- return std::get<1>(L) > std::get<1>(R);
- llvm_unreachable("Unknown sort direction");
- });
+ llvm::sort(Results.begin(), Results.end(),
+ [](const TupleType &L, const TupleType &R) {
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return std::get<1>(L) < std::get<1>(R);
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return std::get<1>(L) > std::get<1>(R);
+ llvm_unreachable("Unknown sort direction");
+ });
break;
default:
// Here we need to look into the ResultRow for the rest of the data that
// we want to sort by.
- std::sort(Results.begin(), Results.end(),
- [&](const TupleType &L, const TupleType &R) {
- auto &LR = std::get<2>(L);
- auto &RR = std::get<2>(R);
- switch (AccountSortOutput) {
- case SortField::COUNT:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Count < RR.Count;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Count > RR.Count;
- llvm_unreachable("Unknown sort direction");
- case SortField::MIN:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Min < RR.Min;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Min > RR.Min;
- llvm_unreachable("Unknown sort direction");
- case SortField::MED:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Median < RR.Median;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Median > RR.Median;
- llvm_unreachable("Unknown sort direction");
- case SortField::PCT90:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Pct90 < RR.Pct90;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Pct90 > RR.Pct90;
- llvm_unreachable("Unknown sort direction");
- case SortField::PCT99:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Pct99 < RR.Pct99;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Pct99 > RR.Pct99;
- llvm_unreachable("Unknown sort direction");
- case SortField::MAX:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Max < RR.Max;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Max > RR.Max;
- llvm_unreachable("Unknown sort direction");
- case SortField::SUM:
- if (AccountSortOrder == SortDirection::ASCENDING)
- return LR.Sum < RR.Sum;
- if (AccountSortOrder == SortDirection::DESCENDING)
- return LR.Sum > RR.Sum;
- llvm_unreachable("Unknown sort direction");
- default:
- llvm_unreachable("Unsupported sort order");
- }
- });
+ llvm::sort(Results.begin(), Results.end(),
+ [&](const TupleType &L, const TupleType &R) {
+ auto &LR = std::get<2>(L);
+ auto &RR = std::get<2>(R);
+ switch (AccountSortOutput) {
+ case SortField::COUNT:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Count < RR.Count;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Count > RR.Count;
+ llvm_unreachable("Unknown sort direction");
+ case SortField::MIN:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Min < RR.Min;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Min > RR.Min;
+ llvm_unreachable("Unknown sort direction");
+ case SortField::MED:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Median < RR.Median;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Median > RR.Median;
+ llvm_unreachable("Unknown sort direction");
+ case SortField::PCT90:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Pct90 < RR.Pct90;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Pct90 > RR.Pct90;
+ llvm_unreachable("Unknown sort direction");
+ case SortField::PCT99:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Pct99 < RR.Pct99;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Pct99 > RR.Pct99;
+ llvm_unreachable("Unknown sort direction");
+ case SortField::MAX:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Max < RR.Max;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Max > RR.Max;
+ llvm_unreachable("Unknown sort direction");
+ case SortField::SUM:
+ if (AccountSortOrder == SortDirection::ASCENDING)
+ return LR.Sum < RR.Sum;
+ if (AccountSortOrder == SortDirection::DESCENDING)
+ return LR.Sum > RR.Sum;
+ llvm_unreachable("Unknown sort direction");
+ default:
+ llvm_unreachable("Unsupported sort order");
+ }
+ });
break;
}
@@ -473,9 +476,9 @@ static CommandRegistration Unused(&Account, []() -> Error {
errs()
<< "Error processing record: "
<< llvm::formatv(
- R"({{type: {0}; cpu: {1}; record-type: {2}; function-id: {3}; tsc: {4}; thread-id: {5}}})",
+ R"({{type: {0}; cpu: {1}; record-type: {2}; function-id: {3}; tsc: {4}; thread-id: {5}; process-id: {6}}})",
Record.RecordType, Record.CPU, Record.Type, Record.FuncId,
- Record.TId)
+ Record.TSC, Record.TId, Record.PId)
<< '\n';
for (const auto &ThreadStack : FCA.getPerThreadFunctionStack()) {
errs() << "Thread ID: " << ThreadStack.first << "\n";
diff --git a/contrib/llvm/tools/llvm-xray/xray-account.h b/contrib/llvm/tools/llvm-xray/xray-account.h
index cc9ba897e537..5c457f178166 100644
--- a/contrib/llvm/tools/llvm-xray/xray-account.h
+++ b/contrib/llvm/tools/llvm-xray/xray-account.h
@@ -29,12 +29,11 @@ namespace xray {
class LatencyAccountant {
public:
typedef std::map<int32_t, std::vector<uint64_t>> FunctionLatencyMap;
- typedef std::map<llvm::sys::ProcessInfo::ProcessId,
- std::pair<uint64_t, uint64_t>>
+ typedef std::map<llvm::sys::procid_t, std::pair<uint64_t, uint64_t>>
PerThreadMinMaxTSCMap;
typedef std::map<uint8_t, std::pair<uint64_t, uint64_t>> PerCPUMinMaxTSCMap;
typedef std::vector<std::pair<int32_t, uint64_t>> FunctionStack;
- typedef std::map<llvm::sys::ProcessInfo::ProcessId, FunctionStack>
+ typedef std::map<llvm::sys::procid_t, FunctionStack>
PerThreadFunctionStackMap;
private:
@@ -79,8 +78,7 @@ public:
///
bool accountRecord(const XRayRecord &Record);
- const FunctionStack *
- getThreadFunctionStack(llvm::sys::ProcessInfo::ProcessId TId) const {
+ const FunctionStack *getThreadFunctionStack(llvm::sys::procid_t TId) const {
auto I = PerThreadFunctionStack.find(TId);
if (I == PerThreadFunctionStack.end())
return nullptr;
diff --git a/contrib/llvm/tools/llvm-xray/xray-color-helper.cc b/contrib/llvm/tools/llvm-xray/xray-color-helper.cpp
index 61314d3c766a..78a264b73d8f 100644
--- a/contrib/llvm/tools/llvm-xray/xray-color-helper.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-color-helper.cpp
@@ -1,4 +1,4 @@
-//===-- xray-graph.cc - XRay Function Call Graph Renderer -----------------===//
+//===-- xray-graph.cpp: XRay Function Call Graph Renderer -----------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-xray/xray-converter.cc b/contrib/llvm/tools/llvm-xray/xray-converter.cpp
index aa0da55207b3..90e14d0d8896 100644
--- a/contrib/llvm/tools/llvm-xray/xray-converter.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-converter.cpp
@@ -1,4 +1,4 @@
-//===- xray-converter.cc - XRay Trace Conversion --------------------------===//
+//===- xray-converter.cpp: XRay Trace Conversion --------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -91,7 +91,7 @@ void TraceConverter::exportAsYAML(const Trace &Records, raw_ostream &OS) {
Trace.Records.push_back({R.RecordType, R.CPU, R.Type, R.FuncId,
Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId)
: llvm::to_string(R.FuncId),
- R.TSC, R.TId, R.CallArgs});
+ R.TSC, R.TId, R.PId, R.CallArgs});
}
Output Out(OS, nullptr, 0);
Out << Trace;
@@ -100,7 +100,7 @@ void TraceConverter::exportAsYAML(const Trace &Records, raw_ostream &OS) {
void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) {
// First write out the file header, in the correct endian-appropriate format
// (XRay assumes currently little endian).
- support::endian::Writer<support::endianness::little> Writer(OS);
+ support::endian::Writer Writer(OS, support::endianness::little);
const auto &FH = Records.getFileHeader();
Writer.write(FH.Version);
Writer.write(FH.Type);
@@ -141,7 +141,12 @@ void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) {
Writer.write(R.FuncId);
Writer.write(R.TSC);
Writer.write(R.TId);
- Writer.write(Padding4B);
+
+ if (FH.Version >= 3)
+ Writer.write(R.PId);
+ else
+ Writer.write(Padding4B);
+
Writer.write(Padding4B);
Writer.write(Padding4B);
}
@@ -229,19 +234,29 @@ StackTrieNode *findOrCreateStackNode(
return CurrentStack;
}
-void writeTraceViewerRecord(raw_ostream &OS, int32_t FuncId, uint32_t TId,
- bool Symbolize,
+void writeTraceViewerRecord(uint16_t Version, raw_ostream &OS, int32_t FuncId,
+ uint32_t TId, uint32_t PId, bool Symbolize,
const FuncIdConversionHelper &FuncIdHelper,
double EventTimestampUs,
const StackTrieNode &StackCursor,
StringRef FunctionPhenotype) {
OS << " ";
- OS << llvm::formatv(
- R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "1", )"
- R"("ts" : "{3:f3}", "sf" : "{4}" })",
- (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId)
- : llvm::to_string(FuncId)),
- FunctionPhenotype, TId, EventTimestampUs, StackCursor.ExtraData.id);
+ if (Version >= 3) {
+ OS << llvm::formatv(
+ R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "{3}", )"
+ R"("ts" : "{4:f4}", "sf" : "{5}" })",
+ (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId)
+ : llvm::to_string(FuncId)),
+ FunctionPhenotype, TId, PId, EventTimestampUs,
+ StackCursor.ExtraData.id);
+ } else {
+ OS << llvm::formatv(
+ R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "1", )"
+ R"("ts" : "{3:f3}", "sf" : "{4}" })",
+ (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId)
+ : llvm::to_string(FuncId)),
+ FunctionPhenotype, TId, EventTimestampUs, StackCursor.ExtraData.id);
+ }
}
} // namespace
@@ -249,6 +264,7 @@ void writeTraceViewerRecord(raw_ostream &OS, int32_t FuncId, uint32_t TId,
void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records,
raw_ostream &OS) {
const auto &FH = Records.getFileHeader();
+ auto Version = FH.Version;
auto CycleFreq = FH.CycleFrequency;
unsigned id_counter = 0;
@@ -282,11 +298,11 @@ void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records,
StackRootsByThreadId, StacksByStackId,
&id_counter, NodeStore);
// Each record is represented as a json dictionary with function name,
- // type of B for begin or E for end, thread id, process id (faked),
+ // type of B for begin or E for end, thread id, process id,
// timestamp in microseconds, and a stack frame id. The ids are logged
// in an id dictionary after the events.
- writeTraceViewerRecord(OS, R.FuncId, R.TId, Symbolize, FuncIdHelper,
- EventTimestampUs, *StackCursor, "B");
+ writeTraceViewerRecord(Version, OS, R.FuncId, R.TId, R.PId, Symbolize,
+ FuncIdHelper, EventTimestampUs, *StackCursor, "B");
break;
case RecordTypes::EXIT:
case RecordTypes::TAIL_EXIT:
@@ -297,9 +313,12 @@ void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records,
// (And/Or in loop termination below)
StackTrieNode *PreviousCursor = nullptr;
do {
- writeTraceViewerRecord(OS, StackCursor->FuncId, R.TId, Symbolize,
- FuncIdHelper, EventTimestampUs, *StackCursor,
- "E");
+ if (PreviousCursor != nullptr) {
+ OS << ",\n";
+ }
+ writeTraceViewerRecord(Version, OS, StackCursor->FuncId, R.TId, R.PId,
+ Symbolize, FuncIdHelper, EventTimestampUs,
+ *StackCursor, "E");
PreviousCursor = StackCursor;
StackCursor = StackCursor->Parent;
} while (PreviousCursor->FuncId != R.FuncId && StackCursor != nullptr);
diff --git a/contrib/llvm/tools/llvm-xray/xray-extract.cc b/contrib/llvm/tools/llvm-xray/xray-extract.cpp
index cd87798d0e60..10fe7d8d6209 100644
--- a/contrib/llvm/tools/llvm-xray/xray-extract.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-extract.cpp
@@ -1,4 +1,4 @@
-//===- xray-extract.cc - XRay Instrumentation Map Extraction --------------===//
+//===- xray-extract.cpp: XRay Instrumentation Map Extraction --------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-xray/xray-graph-diff.cc b/contrib/llvm/tools/llvm-xray/xray-graph-diff.cpp
index 3c69b3fb0751..a22f2a99811d 100644
--- a/contrib/llvm/tools/llvm-xray/xray-graph-diff.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-graph-diff.cpp
@@ -1,4 +1,4 @@
-//===-- xray-graph-diff.cc - XRay Function Call Graph Renderer ------------===//
+//===-- xray-graph-diff.cpp: XRay Function Call Graph Renderer ------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-xray/xray-graph.cc b/contrib/llvm/tools/llvm-xray/xray-graph.cpp
index feb676331f89..c619bf86299b 100644
--- a/contrib/llvm/tools/llvm-xray/xray-graph.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-graph.cpp
@@ -1,4 +1,4 @@
-//===-- xray-graph.cc - XRay Function Call Graph Renderer -----------------===//
+//===-- xray-graph.cpp: XRay Function Call Graph Renderer -----------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-xray/xray-graph.h b/contrib/llvm/tools/llvm-xray/xray-graph.h
index a43df265d0e1..fc7f8bb470f2 100644
--- a/contrib/llvm/tools/llvm-xray/xray-graph.h
+++ b/contrib/llvm/tools/llvm-xray/xray-graph.h
@@ -80,7 +80,7 @@ public:
using FunctionStack = SmallVector<FunctionAttr, 4>;
using PerThreadFunctionStackMap =
- DenseMap<llvm::sys::ProcessInfo::ProcessId, FunctionStack>;
+ DenseMap<llvm::sys::procid_t, FunctionStack>;
class GraphT : public Graph<FunctionStats, CallStats, int32_t> {
public:
diff --git a/contrib/llvm/tools/llvm-xray/xray-registry.cc b/contrib/llvm/tools/llvm-xray/xray-registry.cpp
index 36d3a2e58f97..fe58e4deaa1e 100644
--- a/contrib/llvm/tools/llvm-xray/xray-registry.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-registry.cpp
@@ -1,4 +1,4 @@
-//===- xray-registry.cc - Implement a command registry. -------------------===//
+//===- xray-registry.cpp: Implement a command registry. -------------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/llvm-xray/xray-stacks.cc b/contrib/llvm/tools/llvm-xray/xray-stacks.cpp
index 9474de047990..1a6069780a31 100644
--- a/contrib/llvm/tools/llvm-xray/xray-stacks.cc
+++ b/contrib/llvm/tools/llvm-xray/xray-stacks.cpp
@@ -1,4 +1,4 @@
-//===- xray-stacks.cc - XRay Function Call Stack Accounting ---------------===//
+//===- xray-stacks.cpp: XRay Function Call Stack Accounting ---------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/tools/opt/BreakpointPrinter.cpp b/contrib/llvm/tools/opt/BreakpointPrinter.cpp
index e5614ed061e3..d3f54c034f55 100644
--- a/contrib/llvm/tools/opt/BreakpointPrinter.cpp
+++ b/contrib/llvm/tools/opt/BreakpointPrinter.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Breakpoint location printer.
+/// Breakpoint location printer.
///
//===----------------------------------------------------------------------===//
#include "BreakpointPrinter.h"
diff --git a/contrib/llvm/tools/opt/BreakpointPrinter.h b/contrib/llvm/tools/opt/BreakpointPrinter.h
index 81c88e19199e..57670e5ee8d8 100644
--- a/contrib/llvm/tools/opt/BreakpointPrinter.h
+++ b/contrib/llvm/tools/opt/BreakpointPrinter.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Breakpoint location printer.
+/// Breakpoint location printer.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
diff --git a/contrib/llvm/tools/opt/Debugify.cpp b/contrib/llvm/tools/opt/Debugify.cpp
index 40ee545c098d..6c3cdc75e334 100644
--- a/contrib/llvm/tools/opt/Debugify.cpp
+++ b/contrib/llvm/tools/opt/Debugify.cpp
@@ -12,6 +12,7 @@
///
//===----------------------------------------------------------------------===//
+#include "Debugify.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/BasicBlock.h"
@@ -34,10 +35,37 @@ using namespace llvm;
namespace {
-bool applyDebugifyMetadata(Module &M) {
+cl::opt<bool> Quiet("debugify-quiet",
+ cl::desc("Suppress verbose debugify output"));
+
+raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
+
+uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
+ return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
+}
+
+bool isFunctionSkipped(Function &F) {
+ return F.isDeclaration() || !F.hasExactDefinition();
+}
+
+/// Find the basic block's terminating instruction.
+///
+/// Special care is needed to handle musttail and deopt calls, as these behave
+/// like (but are in fact not) terminators.
+Instruction *findTerminatingInstruction(BasicBlock &BB) {
+ if (auto *I = BB.getTerminatingMustTailCall())
+ return I;
+ if (auto *I = BB.getTerminatingDeoptimizeCall())
+ return I;
+ return BB.getTerminator();
+}
+
+bool applyDebugifyMetadata(Module &M,
+ iterator_range<Module::iterator> Functions,
+ StringRef Banner) {
// Skip modules with debug info.
if (M.getNamedMetadata("llvm.dbg.cu")) {
- errs() << "Debugify: Skipping module with debug info\n";
+ dbg() << Banner << "Skipping module with debug info\n";
return false;
}
@@ -47,7 +75,7 @@ bool applyDebugifyMetadata(Module &M) {
// Get a DIType which corresponds to Ty.
DenseMap<uint64_t, DIType *> TypeCache;
auto getCachedDIType = [&](Type *Ty) -> DIType * {
- uint64_t Size = M.getDataLayout().getTypeAllocSizeInBits(Ty);
+ uint64_t Size = getAllocSizeInBits(M, Ty);
DIType *&DTy = TypeCache[Size];
if (!DTy) {
std::string Name = "ty" + utostr(Size);
@@ -59,20 +87,19 @@ bool applyDebugifyMetadata(Module &M) {
unsigned NextLine = 1;
unsigned NextVar = 1;
auto File = DIB.createFile(M.getName(), "/");
- auto CU =
- DIB.createCompileUnit(dwarf::DW_LANG_C, DIB.createFile(M.getName(), "/"),
- "debugify", /*isOptimized=*/true, "", 0);
+ auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
+ /*isOptimized=*/true, "", 0);
// Visit each instruction.
- for (Function &F : M) {
- if (F.isDeclaration())
+ for (Function &F : Functions) {
+ if (isFunctionSkipped(F))
continue;
auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
auto SP =
DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
- IsLocalToUnit, F.hasExactDefinition(), NextLine,
+ IsLocalToUnit, /*isDefinition=*/true, NextLine,
DINode::FlagZero, /*isOptimized=*/true);
F.setSubprogram(SP);
for (BasicBlock &BB : F) {
@@ -80,23 +107,39 @@ bool applyDebugifyMetadata(Module &M) {
for (Instruction &I : BB)
I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
+ // Inserting debug values into EH pads can break IR invariants.
+ if (BB.isEHPad())
+ continue;
+
+ // Find the terminating instruction, after which no debug values are
+ // attached.
+ Instruction *LastInst = findTerminatingInstruction(BB);
+ assert(LastInst && "Expected basic block with a terminator");
+
+ // Maintain an insertion point which can't be invalidated when updates
+ // are made.
+ BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
+ assert(InsertPt != BB.end() && "Expected to find an insertion point");
+ Instruction *InsertBefore = &*InsertPt;
+
// Attach debug values.
- for (Instruction &I : BB) {
+ for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
// Skip void-valued instructions.
- if (I.getType()->isVoidTy())
+ if (I->getType()->isVoidTy())
continue;
- // Skip the terminator instruction and any just-inserted intrinsics.
- if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
- break;
+ // Phis and EH pads must be grouped at the beginning of the block.
+ // Only advance the insertion point when we finish visiting these.
+ if (!isa<PHINode>(I) && !I->isEHPad())
+ InsertBefore = I->getNextNode();
std::string Name = utostr(NextVar++);
- const DILocation *Loc = I.getDebugLoc().get();
+ const DILocation *Loc = I->getDebugLoc().get();
auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
- getCachedDIType(I.getType()),
+ getCachedDIType(I->getType()),
/*AlwaysPreserve=*/true);
- DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
- BB.getTerminator());
+ DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc,
+ InsertBefore);
}
}
DIB.finalizeSubprogram(SP);
@@ -112,48 +155,110 @@ bool applyDebugifyMetadata(Module &M) {
};
addDebugifyOperand(NextLine - 1); // Original number of lines.
addDebugifyOperand(NextVar - 1); // Original number of variables.
+ assert(NMD->getNumOperands() == 2 &&
+ "llvm.debugify should have exactly 2 operands!");
+
+ // Claim that this synthetic debug info is valid.
+ StringRef DIVersionKey = "Debug Info Version";
+ if (!M.getModuleFlag(DIVersionKey))
+ M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
+
return true;
}
-void checkDebugifyMetadata(Module &M) {
+/// Return true if a mis-sized diagnostic is issued for \p DVI.
+bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
+ // The size of a dbg.value's value operand should match the size of the
+ // variable it corresponds to.
+ //
+ // TODO: This, along with a check for non-null value operands, should be
+ // promoted to verifier failures.
+ Value *V = DVI->getValue();
+ if (!V)
+ return false;
+
+ // For now, don't try to interpret anything more complicated than an empty
+ // DIExpression. Eventually we should try to handle OP_deref and fragments.
+ if (DVI->getExpression()->getNumElements())
+ return false;
+
+ Type *Ty = V->getType();
+ uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
+ Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
+ if (!ValueOperandSize || !DbgVarSize)
+ return false;
+
+ bool HasBadSize = false;
+ if (Ty->isIntegerTy()) {
+ auto Signedness = DVI->getVariable()->getSignedness();
+ if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
+ HasBadSize = ValueOperandSize < *DbgVarSize;
+ } else {
+ HasBadSize = ValueOperandSize != *DbgVarSize;
+ }
+
+ if (HasBadSize) {
+ dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
+ << ", but its variable has size " << *DbgVarSize << ": ";
+ DVI->print(dbg());
+ dbg() << "\n";
+ }
+ return HasBadSize;
+}
+
+bool checkDebugifyMetadata(Module &M,
+ iterator_range<Module::iterator> Functions,
+ StringRef NameOfWrappedPass, StringRef Banner,
+ bool Strip, DebugifyStatsMap *StatsMap) {
// Skip modules without debugify metadata.
NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
- if (!NMD)
- return;
+ if (!NMD) {
+ dbg() << Banner << "Skipping module without debugify metadata\n";
+ return false;
+ }
auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
->getZExtValue();
};
+ assert(NMD->getNumOperands() == 2 &&
+ "llvm.debugify should have exactly 2 operands!");
unsigned OriginalNumLines = getDebugifyOperand(0);
unsigned OriginalNumVars = getDebugifyOperand(1);
bool HasErrors = false;
- // Find missing lines.
+ // Track debug info loss statistics if able.
+ DebugifyStatistics *Stats = nullptr;
+ if (StatsMap && !NameOfWrappedPass.empty())
+ Stats = &StatsMap->operator[](NameOfWrappedPass);
+
BitVector MissingLines{OriginalNumLines, true};
- for (Function &F : M) {
+ BitVector MissingVars{OriginalNumVars, true};
+ for (Function &F : Functions) {
+ if (isFunctionSkipped(F))
+ continue;
+
+ // Find missing lines.
for (Instruction &I : instructions(F)) {
if (isa<DbgValueInst>(&I))
continue;
auto DL = I.getDebugLoc();
- if (DL) {
+ if (DL && DL.getLine() != 0) {
MissingLines.reset(DL.getLine() - 1);
continue;
}
- outs() << "ERROR: Instruction with empty DebugLoc -- ";
- I.print(outs());
- outs() << "\n";
- HasErrors = true;
+ if (!DL) {
+ dbg() << "ERROR: Instruction with empty DebugLoc in function ";
+ dbg() << F.getName() << " --";
+ I.print(dbg());
+ dbg() << "\n";
+ HasErrors = true;
+ }
}
- }
- for (unsigned Idx : MissingLines.set_bits())
- outs() << "WARNING: Missing line " << Idx + 1 << "\n";
- // Find missing variables.
- BitVector MissingVars{OriginalNumVars, true};
- for (Function &F : M) {
+ // Find missing variables and mis-sized debug values.
for (Instruction &I : instructions(F)) {
auto *DVI = dyn_cast<DbgValueInst>(&I);
if (!DVI)
@@ -162,21 +267,70 @@ void checkDebugifyMetadata(Module &M) {
unsigned Var = ~0U;
(void)to_integer(DVI->getVariable()->getName(), Var, 10);
assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
- MissingVars.reset(Var - 1);
+ bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
+ if (!HasBadSize)
+ MissingVars.reset(Var - 1);
+ HasErrors |= HasBadSize;
}
}
+
+ // Print the results.
+ for (unsigned Idx : MissingLines.set_bits())
+ dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
+
for (unsigned Idx : MissingVars.set_bits())
- outs() << "ERROR: Missing variable " << Idx + 1 << "\n";
- HasErrors |= MissingVars.count() > 0;
+ dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
+
+ // Update DI loss statistics.
+ if (Stats) {
+ Stats->NumDbgLocsExpected += OriginalNumLines;
+ Stats->NumDbgLocsMissing += MissingLines.count();
+ Stats->NumDbgValuesExpected += OriginalNumVars;
+ Stats->NumDbgValuesMissing += MissingVars.count();
+ }
+
+ dbg() << Banner;
+ if (!NameOfWrappedPass.empty())
+ dbg() << " [" << NameOfWrappedPass << "]";
+ dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
- outs() << "CheckDebugify: " << (HasErrors ? "FAIL" : "PASS") << "\n";
+ // Strip the Debugify Metadata if required.
+ if (Strip) {
+ StripDebugInfo(M);
+ M.eraseNamedMetadata(NMD);
+ return true;
+ }
+
+ return false;
}
-/// Attach synthetic debug info to everything.
-struct DebugifyPass : public ModulePass {
- bool runOnModule(Module &M) override { return applyDebugifyMetadata(M); }
+/// ModulePass for attaching synthetic debug info to everything, used with the
+/// legacy module pass manager.
+struct DebugifyModulePass : public ModulePass {
+ bool runOnModule(Module &M) override {
+ return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
+ }
+
+ DebugifyModulePass() : ModulePass(ID) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ static char ID; // Pass identification.
+};
+
+/// FunctionPass for attaching synthetic debug info to instructions within a
+/// single function, used with the legacy module pass manager.
+struct DebugifyFunctionPass : public FunctionPass {
+ bool runOnFunction(Function &F) override {
+ Module &M = *F.getParent();
+ auto FuncIt = F.getIterator();
+ return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ "FunctionDebugify: ");
+ }
- DebugifyPass() : ModulePass(ID) {}
+ DebugifyFunctionPass() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
@@ -185,28 +339,125 @@ struct DebugifyPass : public ModulePass {
static char ID; // Pass identification.
};
-/// Check debug info inserted by -debugify for completeness.
-struct CheckDebugifyPass : public ModulePass {
+/// ModulePass for checking debug info inserted by -debugify, used with the
+/// legacy module pass manager.
+struct CheckDebugifyModulePass : public ModulePass {
bool runOnModule(Module &M) override {
- checkDebugifyMetadata(M);
- return false;
+ return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
+ "CheckModuleDebugify", Strip, StatsMap);
+ }
+
+ CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr)
+ : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
+ StatsMap(StatsMap) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ static char ID; // Pass identification.
+
+private:
+ bool Strip;
+ StringRef NameOfWrappedPass;
+ DebugifyStatsMap *StatsMap;
+};
+
+/// FunctionPass for checking debug info inserted by -debugify-function, used
+/// with the legacy module pass manager.
+struct CheckDebugifyFunctionPass : public FunctionPass {
+ bool runOnFunction(Function &F) override {
+ Module &M = *F.getParent();
+ auto FuncIt = F.getIterator();
+ return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ NameOfWrappedPass, "CheckFunctionDebugify",
+ Strip, StatsMap);
}
- CheckDebugifyPass() : ModulePass(ID) {}
+ CheckDebugifyFunctionPass(bool Strip = false,
+ StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr)
+ : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
+ StatsMap(StatsMap) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static char ID; // Pass identification.
+
+private:
+ bool Strip;
+ StringRef NameOfWrappedPass;
+ DebugifyStatsMap *StatsMap;
};
} // end anonymous namespace
-char DebugifyPass::ID = 0;
-static RegisterPass<DebugifyPass> X("debugify",
- "Attach debug info to everything");
+void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map) {
+ std::error_code EC;
+ raw_fd_ostream OS{Path, EC};
+ if (EC) {
+ errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
+ return;
+ }
+
+ OS << "Pass Name" << ',' << "# of missing debug values" << ','
+ << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
+ << "Missing/Expected location ratio" << '\n';
+ for (const auto &Entry : Map) {
+ StringRef Pass = Entry.first;
+ DebugifyStatistics Stats = Entry.second;
+
+ OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
+ << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
+ << Stats.getEmptyLocationRatio() << '\n';
+ }
+}
+
+ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
+
+FunctionPass *createDebugifyFunctionPass() {
+ return new DebugifyFunctionPass();
+}
+
+PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
+ applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
+ return PreservedAnalyses::all();
+}
+
+ModulePass *createCheckDebugifyModulePass(bool Strip,
+ StringRef NameOfWrappedPass,
+ DebugifyStatsMap *StatsMap) {
+ return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
+}
+
+FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
+ StringRef NameOfWrappedPass,
+ DebugifyStatsMap *StatsMap) {
+ return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
+}
+
+PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
+ ModuleAnalysisManager &) {
+ checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
+ nullptr);
+ return PreservedAnalyses::all();
+}
+
+char DebugifyModulePass::ID = 0;
+static RegisterPass<DebugifyModulePass> DM("debugify",
+ "Attach debug info to everything");
+
+char CheckDebugifyModulePass::ID = 0;
+static RegisterPass<CheckDebugifyModulePass>
+ CDM("check-debugify", "Check debug info from -debugify");
+
+char DebugifyFunctionPass::ID = 0;
+static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
+ "Attach debug info to a function");
-char CheckDebugifyPass::ID = 0;
-static RegisterPass<CheckDebugifyPass> Y("check-debugify",
- "Check debug info from -debugify");
+char CheckDebugifyFunctionPass::ID = 0;
+static RegisterPass<CheckDebugifyFunctionPass>
+ CDF("check-debugify-function", "Check debug info from -debugify-function");
diff --git a/contrib/llvm/tools/opt/Debugify.h b/contrib/llvm/tools/opt/Debugify.h
new file mode 100644
index 000000000000..d1a60c73e723
--- /dev/null
+++ b/contrib/llvm/tools/opt/Debugify.h
@@ -0,0 +1,75 @@
+//===- Debugify.h - Attach synthetic debug info to everything -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file Interface to the `debugify` synthetic debug info testing utility.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OPT_DEBUGIFY_H
+#define LLVM_TOOLS_OPT_DEBUGIFY_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/raw_ostream.h"
+
+llvm::ModulePass *createDebugifyModulePass();
+llvm::FunctionPass *createDebugifyFunctionPass();
+
+struct NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
+ llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
+};
+
+/// Track how much `debugify` information has been lost.
+struct DebugifyStatistics {
+ /// Number of missing dbg.values.
+ unsigned NumDbgValuesMissing = 0;
+
+ /// Number of dbg.values expected.
+ unsigned NumDbgValuesExpected = 0;
+
+ /// Number of instructions with empty debug locations.
+ unsigned NumDbgLocsMissing = 0;
+
+ /// Number of instructions expected to have debug locations.
+ unsigned NumDbgLocsExpected = 0;
+
+ /// Get the ratio of missing/expected dbg.values.
+ float getMissingValueRatio() const {
+ return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
+ }
+
+ /// Get the ratio of missing/expected instructions with locations.
+ float getEmptyLocationRatio() const {
+ return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
+ }
+};
+
+/// Map pass names to a per-pass DebugifyStatistics instance.
+using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
+
+/// Export per-pass debugify statistics to the file specified by \p Path.
+void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map);
+
+llvm::ModulePass *
+createCheckDebugifyModulePass(bool Strip = false,
+ llvm::StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr);
+
+llvm::FunctionPass *
+createCheckDebugifyFunctionPass(bool Strip = false,
+ llvm::StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr);
+
+struct NewPMCheckDebugifyPass
+ : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
+ llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
+};
+
+#endif // LLVM_TOOLS_OPT_DEBUGIFY_H
diff --git a/contrib/llvm/tools/opt/NewPMDriver.cpp b/contrib/llvm/tools/opt/NewPMDriver.cpp
index a3f16f2538c4..a91d4cb5f9cd 100644
--- a/contrib/llvm/tools/opt/NewPMDriver.cpp
+++ b/contrib/llvm/tools/opt/NewPMDriver.cpp
@@ -13,12 +13,14 @@
///
//===----------------------------------------------------------------------===//
+#include "Debugify.h"
#include "NewPMDriver.h"
+#include "PassPrinters.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
-#include "llvm/Config/config.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
@@ -26,6 +28,7 @@
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -40,6 +43,10 @@ static cl::opt<bool>
DebugPM("debug-pass-manager", cl::Hidden,
cl::desc("Print pass management debugging information"));
+static cl::list<std::string>
+ PassPlugins("load-pass-plugin",
+ cl::desc("Load passes from plugin library"));
+
// This flag specifies a textual description of the alias analysis pipeline to
// use when querying for aliasing information. It only works in concert with
// the "passes" flag above.
@@ -82,6 +89,11 @@ static cl::opt<std::string> VectorizerStartEPPipeline(
cl::desc("A textual description of the function pass pipeline inserted at "
"the VectorizerStart extension point into default pipelines"),
cl::Hidden);
+static cl::opt<std::string> PipelineStartEPPipeline(
+ "passes-ep-pipeline-start",
+ cl::desc("A textual description of the function pass pipeline inserted at "
+ "the PipelineStart extension point into default pipelines"),
+ cl::Hidden);
enum PGOKind { NoPGO, InstrGen, InstrUse, SampleUse };
static cl::opt<PGOKind> PGOKindFlag(
"pgo-kind", cl::init(NoPGO), cl::Hidden,
@@ -159,6 +171,12 @@ static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass,
PB.parsePassPipeline(PM, VectorizerStartEPPipeline, VerifyEachPass,
DebugLogging);
});
+ if (tryParsePipelineText<ModulePassManager>(PB, PipelineStartEPPipeline))
+ PB.registerPipelineStartEPCallback(
+ [&PB, VerifyEachPass, DebugLogging](ModulePassManager &PM) {
+ PB.parsePassPipeline(PM, PipelineStartEPPipeline, VerifyEachPass,
+ DebugLogging);
+ });
}
#ifdef LINK_POLLY_INTO_TOOLS
@@ -174,7 +192,8 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
VerifierKind VK,
bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder,
- bool EmitSummaryIndex, bool EmitModuleHash) {
+ bool EmitSummaryIndex, bool EmitModuleHash,
+ bool EnableDebugify) {
bool VerifyEachPass = VK == VK_VerifyEachPass;
Optional<PGOOptions> P;
@@ -197,6 +216,32 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
PassBuilder PB(TM, P);
registerEPCallbacks(PB, VerifyEachPass, DebugPM);
+ // Load requested pass plugins and let them register pass builder callbacks
+ for (auto &PluginFN : PassPlugins) {
+ auto PassPlugin = PassPlugin::Load(PluginFN);
+ if (!PassPlugin) {
+ errs() << "Failed to load passes from '" << PluginFN
+ << "'. Request ignored.\n";
+ continue;
+ }
+
+ PassPlugin->registerPassBuilderCallbacks(PB);
+ }
+
+ // Register a callback that creates the debugify passes as needed.
+ PB.registerPipelineParsingCallback(
+ [](StringRef Name, ModulePassManager &MPM,
+ ArrayRef<PassBuilder::PipelineElement>) {
+ if (Name == "debugify") {
+ MPM.addPass(NewPMDebugifyPass());
+ return true;
+ } else if (Name == "check-debugify") {
+ MPM.addPass(NewPMCheckDebugifyPass());
+ return true;
+ }
+ return false;
+ });
+
#ifdef LINK_POLLY_INTO_TOOLS
polly::RegisterPollyPasses(PB);
#endif
@@ -227,6 +272,8 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
ModulePassManager MPM(DebugPM);
if (VK > VK_NoVerifier)
MPM.addPass(VerifierPass());
+ if (EnableDebugify)
+ MPM.addPass(NewPMDebugifyPass());
if (!PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) {
errs() << Arg0 << ": unable to parse pass pipeline description.\n";
@@ -235,6 +282,8 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
if (VK > VK_NoVerifier)
MPM.addPass(VerifierPass());
+ if (EnableDebugify)
+ MPM.addPass(NewPMCheckDebugifyPass());
// Add any relevant output pass at the end of the pipeline.
switch (OK) {
diff --git a/contrib/llvm/tools/opt/NewPMDriver.h b/contrib/llvm/tools/opt/NewPMDriver.h
index e5490deaeaf5..7d74a5777d11 100644
--- a/contrib/llvm/tools/opt/NewPMDriver.h
+++ b/contrib/llvm/tools/opt/NewPMDriver.h
@@ -42,7 +42,7 @@ enum VerifierKind {
};
}
-/// \brief Driver function to run the new pass manager over a module.
+/// Driver function to run the new pass manager over a module.
///
/// This function only exists factored away from opt.cpp in order to prevent
/// inclusion of the new pass manager headers and the old headers into the same
@@ -57,7 +57,8 @@ bool runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
opt_tool::OutputKind OK, opt_tool::VerifierKind VK,
bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder,
- bool EmitSummaryIndex, bool EmitModuleHash);
-}
+ bool EmitSummaryIndex, bool EmitModuleHash,
+ bool EnableDebugify);
+} // namespace llvm
#endif
diff --git a/contrib/llvm/tools/opt/PassPrinters.cpp b/contrib/llvm/tools/opt/PassPrinters.cpp
index f52b52080949..310d491c06a5 100644
--- a/contrib/llvm/tools/opt/PassPrinters.cpp
+++ b/contrib/llvm/tools/opt/PassPrinters.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Utilities to print analysis info for various kinds of passes.
+/// Utilities to print analysis info for various kinds of passes.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/opt/PassPrinters.h b/contrib/llvm/tools/opt/PassPrinters.h
index 14b6e43d18e0..e66f3f457b7a 100644
--- a/contrib/llvm/tools/opt/PassPrinters.h
+++ b/contrib/llvm/tools/opt/PassPrinters.h
@@ -8,13 +8,15 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Utilities to print analysis info for various kinds of passes.
+/// Utilities to print analysis info for various kinds of passes.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_OPT_PASSPRINTERS_H
#define LLVM_TOOLS_OPT_PASSPRINTERS_H
+#include "llvm/IR/PassManager.h"
+
namespace llvm {
class BasicBlockPass;
@@ -25,6 +27,7 @@ class LoopPass;
class PassInfo;
class raw_ostream;
class RegionPass;
+class Module;
FunctionPass *createFunctionPassPrinter(const PassInfo *PI, raw_ostream &out,
bool Quiet);
diff --git a/contrib/llvm/tools/opt/opt.cpp b/contrib/llvm/tools/opt/opt.cpp
index c471e0f2e3ec..6e287b6c0ab6 100644
--- a/contrib/llvm/tools/opt/opt.cpp
+++ b/contrib/llvm/tools/opt/opt.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "BreakpointPrinter.h"
+#include "Debugify.h"
#include "NewPMDriver.h"
#include "PassPrinters.h"
#include "llvm/ADT/Triple.h"
@@ -23,8 +24,9 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
@@ -41,10 +43,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PluginLoader.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/TargetRegistry.h"
@@ -123,7 +123,11 @@ StripDebug("strip-debug",
cl::desc("Strip debugger symbol info from translation unit"));
static cl::opt<bool>
-DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));
+ StripNamedMetadata("strip-named-metadata",
+ cl::desc("Strip module-level named metadata"));
+
+static cl::opt<bool> DisableInline("disable-inlining",
+ cl::desc("Do not run the inliner pass"));
static cl::opt<bool>
DisableOptimizations("disable-opt",
@@ -203,6 +207,21 @@ QuietA("quiet", cl::desc("Alias for -q"), cl::aliasopt(Quiet));
static cl::opt<bool>
AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization"));
+static cl::opt<bool> EnableDebugify(
+ "enable-debugify",
+ cl::desc(
+ "Start the pipeline with debugify and end it with check-debugify"));
+
+static cl::opt<bool> DebugifyEach(
+ "debugify-each",
+ cl::desc(
+ "Start each pass with debugify and end it with check-debugify"));
+
+static cl::opt<std::string>
+ DebugifyExport("debugify-export",
+ cl::desc("Export per-pass debugify statistics to this file"),
+ cl::value_desc("filename"), cl::init(""));
+
static cl::opt<bool>
PrintBreakpoints("print-breakpoints-for-testing",
cl::desc("Print select breakpoints location for testing"));
@@ -252,6 +271,48 @@ static cl::opt<std::string>
cl::desc("YAML output filename for pass remarks"),
cl::value_desc("filename"));
+class OptCustomPassManager : public legacy::PassManager {
+ DebugifyStatsMap DIStatsMap;
+
+public:
+ using super = legacy::PassManager;
+
+ void add(Pass *P) override {
+ // Wrap each pass with (-check)-debugify passes if requested, making
+ // exceptions for passes which shouldn't see -debugify instrumentation.
+ bool WrapWithDebugify = DebugifyEach && !P->getAsImmutablePass() &&
+ !isIRPrintingPass(P) && !isBitcodeWriterPass(P);
+ if (!WrapWithDebugify) {
+ super::add(P);
+ return;
+ }
+
+ // Apply -debugify/-check-debugify before/after each pass and collect
+ // debug info loss statistics.
+ PassKind Kind = P->getPassKind();
+ StringRef Name = P->getPassName();
+
+ // TODO: Implement Debugify for BasicBlockPass, LoopPass.
+ switch (Kind) {
+ case PT_Function:
+ super::add(createDebugifyFunctionPass());
+ super::add(P);
+ super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
+ break;
+ case PT_Module:
+ super::add(createDebugifyModulePass());
+ super::add(P);
+ super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
+ break;
+ default:
+ super::add(P);
+ break;
+ }
+ }
+
+ const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
+};
+
static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
// Add the pass to the pass manager...
PM.add(P);
@@ -362,13 +423,11 @@ void initializePollyPasses(llvm::PassRegistry &Registry);
// main for opt
//
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- llvm::PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
// Enable debug stream buffering.
EnableDebugBuffering = true;
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
LLVMContext Context;
InitializeAllTargets();
@@ -387,6 +446,7 @@ int main(int argc, char **argv) {
initializeAnalysis(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
+ initializeAggressiveInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);
// For codegen passes, only passes that do IR to IR transformation are
@@ -408,6 +468,7 @@ int main(int argc, char **argv) {
initializePostInlineEntryExitInstrumenterPass(Registry);
initializeUnreachableBlockElimLegacyPassPass(Registry);
initializeExpandReductionsPass(Registry);
+ initializeWasmEHPreparePass(Registry);
initializeWriteBitcodePassPass(Registry);
#ifdef LINK_POLLY_INTO_TOOLS
@@ -449,7 +510,7 @@ int main(int argc, char **argv) {
// Load the input module...
std::unique_ptr<Module> M =
- parseIRFile(InputFilename, Err, Context, !NoVerify);
+ parseIRFile(InputFilename, Err, Context, !NoVerify, ClDataLayout);
if (!M) {
Err.print(argv[0], errs());
@@ -460,6 +521,18 @@ int main(int argc, char **argv) {
if (StripDebug)
StripDebugInfo(*M);
+ // Erase module-level named metadata, if requested.
+ if (StripNamedMetadata) {
+ while (!M->named_metadata_empty()) {
+ NamedMDNode *NMD = &*M->named_metadata_begin();
+ M->eraseNamedMetadata(NMD);
+ }
+ }
+
+ // If we are supposed to override the target triple or data layout, do so now.
+ if (!TargetTriple.empty())
+ M->setTargetTriple(Triple::normalize(TargetTriple));
+
// Immediately run the verifier to catch any problems before starting up the
// pass pipelines. Otherwise we can crash on broken code during
// doInitialization().
@@ -469,12 +542,6 @@ int main(int argc, char **argv) {
return 1;
}
- // If we are supposed to override the target triple or data layout, do so now.
- if (!TargetTriple.empty())
- M->setTargetTriple(Triple::normalize(TargetTriple));
- if (!ClDataLayout.empty())
- M->setDataLayout(ClDataLayout);
-
// Figure out what stream we are supposed to write to...
std::unique_ptr<ToolOutputFile> Out;
std::unique_ptr<ToolOutputFile> ThinLinkOut;
@@ -548,15 +615,15 @@ int main(int argc, char **argv) {
OptRemarkFile.get(), PassPipeline, OK, VK,
PreserveAssemblyUseListOrder,
PreserveBitcodeUseListOrder, EmitSummaryIndex,
- EmitModuleHash)
+ EmitModuleHash, EnableDebugify)
? 0
: 1;
}
// Create a PassManager to hold and optimize the collection of passes we are
// about to build.
- //
- legacy::PassManager Passes;
+ OptCustomPassManager Passes;
+ bool AddOneTimeDebugifyPasses = EnableDebugify && !DebugifyEach;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
TargetLibraryInfoImpl TLII(ModuleTriple);
@@ -570,6 +637,9 @@ int main(int argc, char **argv) {
Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis()
: TargetIRAnalysis()));
+ if (AddOneTimeDebugifyPasses)
+ Passes.add(createDebugifyModulePass());
+
std::unique_ptr<legacy::FunctionPassManager> FPasses;
if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz ||
OptLevelO3) {
@@ -715,12 +785,15 @@ int main(int argc, char **argv) {
if (!NoVerify && !VerifyEach)
Passes.add(createVerifierPass());
+ if (AddOneTimeDebugifyPasses)
+ Passes.add(createCheckDebugifyModulePass(false));
+
// In run twice mode, we want to make sure the output is bit-by-bit
// equivalent if we run the pass manager again, so setup two buffers and
// a stream to write to them. Note that llc does something similar and it
// may be worth to abstract this out in the future.
SmallVector<char, 0> Buffer;
- SmallVector<char, 0> CompileTwiceBuffer;
+ SmallVector<char, 0> FirstRunBuffer;
std::unique_ptr<raw_svector_ostream> BOS;
raw_ostream *OS = nullptr;
@@ -749,28 +822,30 @@ int main(int argc, char **argv) {
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
- // If requested, run all passes again with the same pass manager to catch
- // bugs caused by persistent state in the passes
- if (RunTwice) {
- std::unique_ptr<Module> M2(CloneModule(M.get()));
- Passes.run(*M2);
- CompileTwiceBuffer = Buffer;
- Buffer.clear();
- }
-
- // Now that we have all of the passes ready, run them.
- Passes.run(*M);
-
- // Compare the two outputs and make sure they're the same
- if (RunTwice) {
+ if (!RunTwice) {
+ // Now that we have all of the passes ready, run them.
+ Passes.run(*M);
+ } else {
+ // If requested, run all passes twice with the same pass manager to catch
+ // bugs caused by persistent state in the passes.
+ std::unique_ptr<Module> M2(CloneModule(*M));
+ // Run all passes on the original module first, so the second run processes
+ // the clone to catch CloneModule bugs.
+ Passes.run(*M);
+ FirstRunBuffer = Buffer;
+ Buffer.clear();
+
+ Passes.run(*M2);
+
+ // Compare the two outputs and make sure they're the same
assert(Out);
- if (Buffer.size() != CompileTwiceBuffer.size() ||
- (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
- 0)) {
- errs() << "Running the pass manager twice changed the output.\n"
- "Writing the result of the second run to the specified output.\n"
- "To generate the one-run comparison binary, just run without\n"
- "the compile-twice option\n";
+ if (Buffer.size() != FirstRunBuffer.size() ||
+ (memcmp(Buffer.data(), FirstRunBuffer.data(), Buffer.size()) != 0)) {
+ errs()
+ << "Running the pass manager twice changed the output.\n"
+ "Writing the result of the second run to the specified output.\n"
+ "To generate the one-run comparison binary, just run without\n"
+ "the compile-twice option\n";
Out->os() << BOS->str();
Out->keep();
if (OptRemarkFile)
@@ -780,6 +855,9 @@ int main(int argc, char **argv) {
Out->os() << BOS->str();
}
+ if (DebugifyEach && !DebugifyExport.empty())
+ exportDebugifyStats(DebugifyExport, Passes.getDebugifyStatsMap());
+
// Declare success.
if (!NoOutput || PrintBreakpoints)
Out->keep();